Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorRoberto Tyley <roberto.tyley@gmail.com>2014-07-15 01:38:01 +0400
committerRoberto Tyley <roberto.tyley@gmail.com>2014-07-26 11:23:17 +0400
commit7cb752aaf746dc0b473afeb9e892b7fbc12666c5 (patch)
treecc4f91ddc18332b5adbe82e3fcb040d976c90105 /core
parent551830f8ea5177042af2c7dd1fc90888bc67387d (diff)
Execute become-spongy.sh
https://github.com/rtyley/spongycastle/blob/3040af/become-spongy.sh
Diffstat (limited to 'core')
-rw-r--r--core/src/main/j2me/java/math/BigInteger.java2
-rw-r--r--core/src/main/j2me/java/security/SecureRandom.java10
-rw-r--r--core/src/main/j2me/org/bouncycastle/asn1/ASN1GeneralizedTime.java260
-rw-r--r--core/src/main/j2me/org/bouncycastle/asn1/ASN1UTCTime.java259
-rw-r--r--core/src/main/j2me/org/bouncycastle/asn1/DERFactory.java31
-rw-r--r--core/src/main/j2me/org/bouncycastle/asn1/DERGeneralizedTime.java27
-rw-r--r--core/src/main/j2me/org/bouncycastle/asn1/DERUTCTime.java22
-rw-r--r--core/src/main/j2me/org/bouncycastle/asn1/DateFormatter.java272
-rw-r--r--core/src/main/j2me/org/bouncycastle/asn1/StreamUtil.java88
-rw-r--r--core/src/main/j2me/org/bouncycastle/asn1/cms/Time.java122
-rw-r--r--core/src/main/j2me/org/bouncycastle/asn1/eac/PackedDate.java70
-rw-r--r--core/src/main/j2me/org/bouncycastle/asn1/x509/Time.java122
-rw-r--r--core/src/main/j2me/org/bouncycastle/crypto/encodings/PKCS1Encoding.java410
-rw-r--r--core/src/main/j2me/org/bouncycastle/crypto/examples/MIDPTest.java177
-rw-r--r--core/src/main/j2me/org/bouncycastle/crypto/examples/midp_test.jad6
-rw-r--r--core/src/main/j2me/org/bouncycastle/crypto/examples/midp_test.mf7
-rw-r--r--core/src/main/j2me/org/bouncycastle/crypto/params/SkeinParameters.java258
-rw-r--r--core/src/main/j2me/org/bouncycastle/crypto/tls/OCSPStatusRequest.java131
-rw-r--r--core/src/main/j2me/org/bouncycastle/crypto/tls/ServerNameList.java86
-rw-r--r--core/src/main/j2me/org/bouncycastle/crypto/tls/UDPTransport.java107
-rw-r--r--core/src/main/j2me/org/bouncycastle/math/ec/LongArray.java2197
-rw-r--r--core/src/main/j2me/org/bouncycastle/util/Integers.java19
-rw-r--r--core/src/main/j2me/org/bouncycastle/util/Selector.java8
-rw-r--r--core/src/main/j2me/org/bouncycastle/util/Shorts.java9
-rw-r--r--core/src/main/j2me/org/bouncycastle/util/Times.java11
-rw-r--r--core/src/main/j2me/org/bouncycastle/util/test/SimpleTest.java84
-rw-r--r--core/src/main/j2me/org/spongycastle/asn1/ASN1GeneralizedTime.java260
-rw-r--r--core/src/main/j2me/org/spongycastle/asn1/ASN1UTCTime.java259
-rw-r--r--core/src/main/j2me/org/spongycastle/asn1/DERFactory.java31
-rw-r--r--core/src/main/j2me/org/spongycastle/asn1/DERGeneralizedTime.java27
-rw-r--r--core/src/main/j2me/org/spongycastle/asn1/DERUTCTime.java22
-rw-r--r--core/src/main/j2me/org/spongycastle/asn1/DateFormatter.java272
-rw-r--r--core/src/main/j2me/org/spongycastle/asn1/StreamUtil.java88
-rw-r--r--core/src/main/j2me/org/spongycastle/asn1/cms/Time.java122
-rw-r--r--core/src/main/j2me/org/spongycastle/asn1/eac/PackedDate.java70
-rw-r--r--core/src/main/j2me/org/spongycastle/asn1/x509/Time.java122
-rw-r--r--core/src/main/j2me/org/spongycastle/crypto/encodings/PKCS1Encoding.java410
-rw-r--r--core/src/main/j2me/org/spongycastle/crypto/examples/MIDPTest.java177
-rw-r--r--core/src/main/j2me/org/spongycastle/crypto/examples/midp_test.jad6
-rw-r--r--core/src/main/j2me/org/spongycastle/crypto/examples/midp_test.mf7
-rw-r--r--core/src/main/j2me/org/spongycastle/crypto/params/SkeinParameters.java258
-rw-r--r--core/src/main/j2me/org/spongycastle/crypto/tls/OCSPStatusRequest.java131
-rw-r--r--core/src/main/j2me/org/spongycastle/crypto/tls/ServerNameList.java86
-rw-r--r--core/src/main/j2me/org/spongycastle/crypto/tls/UDPTransport.java107
-rw-r--r--core/src/main/j2me/org/spongycastle/math/ec/LongArray.java2197
-rw-r--r--core/src/main/j2me/org/spongycastle/util/Integers.java19
-rw-r--r--core/src/main/j2me/org/spongycastle/util/Selector.java8
-rw-r--r--core/src/main/j2me/org/spongycastle/util/Shorts.java9
-rw-r--r--core/src/main/j2me/org/spongycastle/util/Times.java11
-rw-r--r--core/src/main/j2me/org/spongycastle/util/test/SimpleTest.java84
-rw-r--r--core/src/main/java/org/bouncycastle/LICENSE.java63
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java19
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1Boolean.java204
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1Choice.java28
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1Encodable.java13
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1EncodableVector.java63
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1Encoding.java22
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1Enumerated.java174
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1Exception.java25
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1GeneralizedTime.java373
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1Generator.java15
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1InputStream.java472
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1Integer.java157
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1Null.java75
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1Object.java111
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java472
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1OctetString.java251
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1OctetStringParser.java17
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1OutputStream.java194
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1ParsingException.java23
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1Primitive.java82
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1Sequence.java382
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1SequenceParser.java19
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1Set.java560
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1SetParser.java19
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1StreamParser.java250
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1String.java6
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1TaggedObject.java236
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1TaggedObjectParser.java12
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ASN1UTCTime.java314
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/BERApplicationSpecific.java10
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/BERApplicationSpecificParser.java41
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/BERConstructedOctetString.java144
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/BERFactory.java17
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/BERGenerator.java100
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/BEROctetString.java168
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/BEROctetStringGenerator.java102
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/BEROctetStringParser.java41
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/BEROutputStream.java36
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/BERSequence.java73
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/BERSequenceGenerator.java41
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/BERSequenceParser.java38
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/BERSet.java73
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/BERSetParser.java38
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/BERTaggedObject.java147
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/BERTaggedObjectParser.java66
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/BERTags.java36
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ConstructedOctetStream.java111
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERApplicationSpecific.java267
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERBMPString.java157
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERBitString.java318
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERBoolean.java22
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DEREncodableVector.java18
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DEREnumerated.java37
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERExternal.java294
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERExternalParser.java52
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERFactory.java17
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERGeneralString.java110
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERGeneralizedTime.java28
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERGenerator.java119
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERIA5String.java189
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERInteger.java30
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERNull.java38
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERNumericString.java189
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java24
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DEROctetString.java48
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DEROctetStringParser.java39
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DEROutputStream.java41
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERPrintableString.java216
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERSequence.java98
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERSequenceGenerator.java45
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERSequenceParser.java38
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERSet.java108
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERSetParser.java38
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERT61String.java151
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERT61UTF8String.java154
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERTaggedObject.java118
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERTags.java9
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERUTCTime.java27
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERUTF8String.java135
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERUniversalString.java151
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DERVisibleString.java141
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DLOutputStream.java31
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DLSequence.java101
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DLSet.java146
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DLTaggedObject.java112
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/DefiniteLengthInputStream.java105
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/InMemoryRepresentable.java16
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/IndefiniteLengthInputStream.java111
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/LazyConstructionEnumeration.java43
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/LazyEncodedSequence.java109
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/LimitedInputStream.java32
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/OIDTokenizer.java48
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/StreamUtil.java114
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java71
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/bsi/BSIObjectIdentifiers.java35
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/CAKeyUpdAnnContent.java80
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/CMPCertificate.java92
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/CMPObjectIdentifiers.java141
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/CRLAnnContent.java61
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/CertConfirmContent.java54
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/CertOrEncCert.java96
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/CertRepMessage.java123
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/CertResponse.java139
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/CertStatus.java102
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/CertifiedKeyPair.java127
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/Challenge.java120
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/ErrorMsgContent.java121
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/GenMsgContent.java71
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/GenRepContent.java71
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/InfoTypeAndValue.java132
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/KeyRecRepContent.java142
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/OOBCertHash.java117
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/PBMParameter.java117
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/PKIBody.java194
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/PKIConfirmContent.java48
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/PKIFailureInfo.java126
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/PKIFreeText.java115
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/PKIHeader.java260
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/PKIHeaderBuilder.java243
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/PKIMessage.java166
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/PKIMessages.java71
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/PKIStatus.java64
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/PKIStatusInfo.java165
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/POPODecKeyChallContent.java54
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/POPODecKeyRespContent.java55
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/PollRepContent.java119
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/PollReqContent.java80
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/ProtectedPart.java70
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/RevAnnContent.java103
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/RevDetails.java100
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/RevRepContent.java137
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/RevRepContentBuilder.java59
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cmp/RevReqContent.java73
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/Attribute.java110
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/AttributeTable.java240
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/Attributes.java85
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedData.java248
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedDataParser.java157
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedData.java312
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedDataParser.java206
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/CCMParameters.java102
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/CMSAttributes.java30
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/CMSObjectIdentifiers.java43
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/CompressedData.java117
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/CompressedDataParser.java49
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/ContentInfo.java130
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/ContentInfoParser.java48
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/DigestedData.java128
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfo.java120
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfoParser.java53
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/EncryptedData.java111
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/EnvelopedData.java215
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/EnvelopedDataParser.java120
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/Evidence.java80
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/GCMParameters.java102
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/IssuerAndSerialNumber.java138
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/KEKIdentifier.java151
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/KEKRecipientInfo.java133
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientIdentifier.java116
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientInfo.java166
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/KeyTransRecipientInfo.java127
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/MetaData.java135
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/OriginatorIdentifierOrKey.java179
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/OriginatorInfo.java159
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/OriginatorPublicKey.java114
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/OtherKeyAttribute.java96
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/OtherRecipientInfo.java112
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/OtherRevocationInfoFormat.java109
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/PasswordRecipientInfo.java157
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/RecipientEncryptedKey.java109
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/RecipientIdentifier.java111
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/RecipientInfo.java173
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/RecipientKeyIdentifier.java171
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/SCVPReqRes.java108
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/SignedData.java330
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/SignedDataParser.java141
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/SignerIdentifier.java114
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/SignerInfo.java282
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/Time.java198
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/TimeStampAndCRL.java96
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/TimeStampTokenEvidence.java98
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/TimeStampedData.java131
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/TimeStampedDataParser.java141
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cms/ecc/MQVuserKeyingMaterial.java122
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/crmf/AttributeTypeAndValue.java80
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/crmf/CRMFObjectIdentifiers.java29
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/crmf/CertId.java84
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/crmf/CertReqMessages.java74
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/crmf/CertReqMsg.java145
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/crmf/CertRequest.java97
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/crmf/CertTemplate.java163
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/crmf/CertTemplateBuilder.java152
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/crmf/Controls.java72
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/crmf/EncKeyWithID.java117
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/crmf/EncryptedKey.java81
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/crmf/EncryptedValue.java164
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/crmf/OptionalValidity.java98
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/crmf/PKIArchiveOptions.java116
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/crmf/PKIPublicationInfo.java81
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/crmf/PKMACValue.java104
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/crmf/POPOPrivKey.java104
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/crmf/POPOSigningKey.java127
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/crmf/POPOSigningKeyInput.java134
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/crmf/ProofOfPossession.java108
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/crmf/SinglePubInfo.java72
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/crmf/SubsequentMessage.java29
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cryptopro/CryptoProObjectIdentifiers.java101
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cryptopro/ECGOST3410NamedCurves.java177
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cryptopro/ECGOST3410ParamSetParameters.java99
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cryptopro/GOST28147Parameters.java98
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cryptopro/GOST3410NamedParameters.java116
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cryptopro/GOST3410ParamSetParameters.java105
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/cryptopro/GOST3410PublicKeyAlgParameters.java104
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/dvcs/CertEtcToken.java171
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSCertInfo.java302
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSCertInfoBuilder.java151
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSErrorNotice.java96
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSObjectIdentifiers.java29
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSRequest.java107
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSRequestInformation.java271
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSRequestInformationBuilder.java224
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSResponse.java117
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSTime.java111
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/dvcs/Data.java149
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/dvcs/PathProcInput.java180
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/dvcs/ServiceType.java92
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/dvcs/TargetEtcChain.java191
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/eac/BidirectionalMap.java23
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/eac/CVCertificate.java313
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/eac/CVCertificateRequest.java170
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/eac/CertificateBody.java472
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/eac/CertificateHolderAuthorization.java184
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/eac/CertificateHolderReference.java66
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/eac/CertificationAuthorityReference.java15
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/eac/EACObjectIdentifiers.java110
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/eac/EACTags.java209
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/eac/ECDSAPublicKey.java340
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/eac/Flags.java96
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/eac/PackedDate.java124
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/eac/PublicKeyDataObject.java35
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/eac/RSAPublicKey.java120
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/eac/UnsignedInteger.java74
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/CommitmentTypeIdentifier.java14
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/CommitmentTypeIndication.java83
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/CommitmentTypeQualifier.java108
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/CompleteRevocationRefs.java65
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/CrlIdentifier.java106
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/CrlListID.java66
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/CrlOcspRef.java106
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/CrlValidatedID.java82
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/ESFAttributes.java22
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/OcspIdentifier.java73
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/OcspListID.java72
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/OcspResponsesID.java83
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/OtherHash.java81
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/OtherHashAlgAndValue.java81
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/OtherRevRefs.java87
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/OtherRevVals.java89
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/RevocationValues.java151
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/SPUserNotice.java99
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/SPuri.java45
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/SigPolicyQualifierInfo.java75
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/SigPolicyQualifiers.java77
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/SignaturePolicyId.java103
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/SignaturePolicyIdentifier.java76
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/SignerAttribute.java123
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/esf/SignerLocation.java162
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ess/ContentHints.java94
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ess/ContentIdentifier.java63
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ess/ESSCertID.java95
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ess/ESSCertIDv2.java155
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ess/OtherCertID.java137
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ess/OtherSigningCertificate.java109
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ess/SigningCertificate.java109
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ess/SigningCertificateV2.java136
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/gnu/GNUObjectIdentifiers.java58
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/iana/IANAObjectIdentifiers.java60
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/icao/CscaMasterList.java114
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/icao/DataGroupHash.java97
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/icao/ICAOObjectIdentifiers.java49
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/icao/LDSSecurityObject.java159
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/icao/LDSVersionInfo.java75
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/isismtt/ISISMTTObjectIdentifiers.java210
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/isismtt/ocsp/CertHash.java121
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/isismtt/ocsp/RequestedCertificate.java181
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/isismtt/x509/AdditionalInformationSyntax.java69
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/isismtt/x509/AdmissionSyntax.java276
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/isismtt/x509/Admissions.java185
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/isismtt/x509/DeclarationOfMajority.java163
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/isismtt/x509/MonetaryLimit.java128
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/isismtt/x509/NamingAuthority.java224
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/isismtt/x509/ProcurationSyntax.java237
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/isismtt/x509/ProfessionInfo.java407
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/isismtt/x509/Restriction.java79
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/kisa/KISAObjectIdentifiers.java31
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/microsoft/MicrosoftObjectIdentifiers.java28
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/misc/CAST5CBCParameters.java78
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/misc/IDEACBCPar.java81
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java59
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/misc/NetscapeCertType.java54
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/misc/NetscapeRevocationURL.java18
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/misc/VerisignCzagExtension.java18
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/mozilla/PublicKeyAndChallenge.java63
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/nist/NISTNamedCurves.java99
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java96
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ntt/NTTObjectIdentifiers.java25
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ocsp/BasicOCSPResponse.java112
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ocsp/CertID.java105
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ocsp/CertStatus.java105
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ocsp/CrlID.java110
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ocsp/OCSPObjectIdentifiers.java29
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ocsp/OCSPRequest.java90
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ocsp/OCSPResponse.java90
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ocsp/OCSPResponseStatus.java71
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ocsp/Request.java91
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ocsp/ResponderID.java104
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ocsp/ResponseBytes.java82
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ocsp/ResponseData.java181
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ocsp/RevokedInfo.java92
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ocsp/ServiceLocator.java36
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ocsp/Signature.java111
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ocsp/SingleResponse.java162
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ocsp/TBSRequest.java172
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/oiw/ElGamalParameter.java68
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/oiw/OIWObjectIdentifiers.java50
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/Attribute.java88
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/AuthenticatedSafe.java74
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/CRLBag.java82
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/CertBag.java66
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequest.java91
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java164
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/ContentInfo.java102
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/DHParameter.java104
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/EncryptedData.java115
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/EncryptedPrivateKeyInfo.java86
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/EncryptionScheme.java56
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/IssuerAndSerialNumber.java85
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/KeyDerivationFunc.java56
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/MacData.java106
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/PBEParameter.java73
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/PBES2Algorithms.java77
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/PBES2Parameters.java77
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/PBKDF2Params.java248
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/PKCS12PBEParams.java69
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java390
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/Pfx.java87
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/PrivateKeyInfo.java164
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/RC2CBCParameter.java93
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java155
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/RSAPrivateKey.java187
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/RSAPrivateKeyStructure.java189
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/RSAPublicKey.java95
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/RSASSAPSSparams.java172
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/SafeBag.java96
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/SignedData.java167
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/pkcs/SignerInfo.java178
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKey.java143
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKeyStructure.java128
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java1094
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java87
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/smime/SMIMEAttributes.java10
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/smime/SMIMECapabilities.java115
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/smime/SMIMECapabilitiesAttribute.java16
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/smime/SMIMECapability.java103
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/smime/SMIMECapabilityVector.java50
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/smime/SMIMEEncryptionKeyPreferenceAttribute.java48
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTNamedCurves.java398
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java75
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/tsp/Accuracy.java173
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/tsp/MessageImprint.java78
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/tsp/TSTInfo.java233
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/tsp/TimeStampReq.java179
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/tsp/TimeStampResp.java84
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145BinaryField.java119
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145ECBinary.java154
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145NamedCurves.java106
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145Params.java121
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145PointEncoder.java154
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145PublicKey.java46
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/ua/UAObjectIdentifiers.java23
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java403
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/util/DERDump.java41
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/util/Dump.java22
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x500/AttributeTypeAndValue.java72
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x500/DirectoryString.java125
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x500/RDN.java119
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x500/X500Name.java326
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x500/X500NameBuilder.java87
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x500/X500NameStyle.java79
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x500/style/AbstractX500NameStyle.java192
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x500/style/BCStrictStyle.java36
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java349
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x500/style/IETFUtils.java572
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x500/style/RFC4519Style.java248
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x500/style/X500NameTokenizer.java90
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/AccessDescription.java98
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java148
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/AttCertIssuer.java91
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/AttCertValidityPeriod.java84
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/Attribute.java93
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificate.java97
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificateInfo.java180
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/AuthorityInformationAccess.java104
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java229
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/BasicConstraints.java163
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/CRLDistPoint.java100
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/CRLNumber.java54
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/CRLReason.java151
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/CertPolicyId.java57
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/Certificate.java131
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/CertificateList.java144
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/CertificatePair.java168
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/CertificatePolicies.java124
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/DSAParameter.java92
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/DigestInfo.java86
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/DisplayText.java165
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/DistributionPoint.java158
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/DistributionPointName.java138
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/ExtendedKeyUsage.java192
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/Extension.java321
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/Extensions.java221
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/ExtensionsGenerator.java94
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/GeneralName.java439
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/GeneralNames.java108
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/GeneralNamesBuilder.java39
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/GeneralSubtree.java218
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/Holder.java245
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/IetfAttrSyntax.java189
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/IssuerSerial.java123
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/IssuingDistributionPoint.java274
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/KeyPurposeId.java157
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/KeyUsage.java113
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/NameConstraints.java118
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/NoticeReference.java170
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/ObjectDigestInfo.java190
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/PolicyConstraints.java106
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/PolicyInformation.java87
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/PolicyMappings.java107
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/PolicyQualifierId.java31
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/PolicyQualifierInfo.java115
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/PrivateKeyUsagePeriod.java84
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/RSAPublicKeyStructure.java98
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/ReasonFlags.java85
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/RoleSyntax.java237
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/SubjectDirectoryAttributes.java144
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java68
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo.java156
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/TBSCertList.java309
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/TBSCertificate.java192
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/TBSCertificateStructure.java194
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/Target.java138
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/TargetInformation.java120
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/Targets.java121
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/Time.java169
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/UserNotice.java132
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/V1TBSCertificateGenerator.java144
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/V2AttributeCertificateInfoGenerator.java158
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/V2Form.java157
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/V2TBSCertListGenerator.java281
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator.java212
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/X509AttributeIdentifiers.java29
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/X509CertificateStructure.java129
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/X509DefaultEntryConverter.java65
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/X509Extension.java249
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/X509Extensions.java477
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/X509ExtensionsGenerator.java94
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/X509Name.java1379
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/X509NameEntryConverter.java114
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/X509NameTokenizer.java91
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java81
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/qualified/BiometricData.java122
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/qualified/ETSIQCObjectIdentifiers.java11
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/qualified/Iso4217CurrencyCode.java93
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/qualified/MonetaryValue.java92
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/qualified/QCStatement.java95
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/qualified/RFC3739QCObjectIdentifiers.java11
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/qualified/SemanticsInformation.java131
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/qualified/TypeOfBiometricData.java90
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/sigi/NameOrPseudonym.java189
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/sigi/PersonalData.java213
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x509/sigi/SigIObjectIdentifiers.java60
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x9/DHDomainParameters.java163
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x9/DHPublicKey.java52
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x9/DHValidationParms.java79
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x9/ECNamedCurveTable.java128
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x9/KeySpecificInfo.java68
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x9/OtherInfo.java96
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x9/X962NamedCurves.java642
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x9/X962Parameters.java86
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x9/X9Curve.java163
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java200
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x9/X9ECParametersHolder.java18
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java48
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x9/X9FieldElement.java64
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x9/X9FieldID.java148
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x9/X9IntegerConverter.java47
-rw-r--r--core/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java207
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/AsymmetricBlockCipher.java45
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/AsymmetricCipherKeyPair.java61
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/AsymmetricCipherKeyPairGenerator.java22
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/BasicAgreement.java26
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/BlockCipher.java56
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/BufferedAsymmetricBlockCipher.java171
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java313
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/CipherKeyGenerator.java38
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/CipherParameters.java8
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/Commitment.java42
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/Committer.java24
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/CryptoException.java48
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/DSA.java36
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/DataLengthException.java29
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/DerivationFunction.java12
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/DerivationParameters.java8
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/Digest.java51
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/DigestDerivationFunction.java13
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/EphemeralKeyPair.java23
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/ExtendedDigest.java13
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/InvalidCipherTextException.java40
-rwxr-xr-xcore/src/main/java/org/bouncycastle/crypto/KeyEncapsulation.java22
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/KeyEncoder.java8
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/KeyGenerationParameters.java48
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/KeyParser.java12
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/Mac.java71
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/MacDerivationFunction.java13
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/MaxBytesExceededException.java27
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/OutputLengthException.java10
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/PBEParametersGenerator.java171
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/RuntimeCryptoException.java26
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/Signer.java43
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/SignerWithRecovery.java34
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/SkippingCipher.java31
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/SkippingStreamCipher.java9
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/StreamBlockCipher.java58
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/StreamCipher.java54
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/Wrapper.java18
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/agreement/DHAgreement.java94
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/agreement/DHBasicAgreement.java71
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/agreement/DHStandardGroups.java206
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java54
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/agreement/ECDHCBasicAgreement.java64
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/agreement/ECMQVBasicAgreement.java91
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKEParticipant.java546
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java115
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroups.java111
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKERound1Payload.java96
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKERound2Payload.java68
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKERound3Payload.java49
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKEUtil.java495
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/agreement/kdf/DHKDFParameters.java53
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/agreement/kdf/DHKEKGenerator.java131
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/agreement/kdf/ECDHKEKGenerator.java74
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Client.java150
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Server.java148
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Util.java154
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6VerifierGenerator.java47
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/commitments/GeneralHashCommitter.java93
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/commitments/HashCommitter.java89
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/EncodableDigest.java17
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/GOST3411Digest.java362
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java155
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/LongDigest.java409
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/MD2Digest.java258
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/MD4Digest.java291
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/MD5Digest.java323
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/NonMemoableDigest.java64
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/NullDigest.java48
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/RIPEMD128Digest.java482
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/RIPEMD160Digest.java443
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/RIPEMD256Digest.java497
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/RIPEMD320Digest.java481
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/SHA1Digest.java348
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/SHA224Digest.java356
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/SHA256Digest.java360
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/SHA384Digest.java111
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/SHA3Digest.java547
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/SHA512Digest.java114
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/SHA512tDigest.java227
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/SM3Digest.java333
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/ShortenedDigest.java80
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/SkeinDigest.java115
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/SkeinEngine.java817
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/TigerDigest.java879
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/digests/WhirlpoolDigest.java409
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java320
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/ec/ECDecryptor.java11
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/ec/ECElGamalDecryptor.java48
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/ec/ECElGamalEncryptor.java86
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/ec/ECEncryptor.java11
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/ec/ECFixedTransform.java88
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/ec/ECNewPublicKeyTransform.java88
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/ec/ECNewRandomnessTransform.java105
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/ec/ECPair.java40
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/ec/ECPairFactorTransform.java14
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/ec/ECPairTransform.java10
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/ec/ECUtil.java21
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/encodings/ISO9796d1Encoding.java287
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/encodings/OAEPEncoding.java357
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java418
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java537
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java928
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/AESLightEngine.java434
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/AESWrapEngine.java16
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/AESWrapPadEngine.java10
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/BlowfishEngine.java577
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/CAST5Engine.java831
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/CAST6Engine.java296
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/CamelliaEngine.java684
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/CamelliaLightEngine.java592
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/CamelliaWrapEngine.java15
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/ChaChaEngine.java204
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCiphertext.java179
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCoreEngine.java313
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/DESEngine.java495
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/DESedeEngine.java127
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java350
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/ElGamalEngine.java217
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/GOST28147Engine.java372
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/Grain128Engine.java304
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/Grainv1Engine.java290
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/HC128Engine.java259
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/HC256Engine.java246
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/IDEAEngine.java357
-rwxr-xr-xcore/src/main/java/org/bouncycastle/crypto/engines/IESEngine.java438
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/ISAACEngine.java221
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/NaccacheSternEngine.java437
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/NoekeonEngine.java263
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/NullEngine.java96
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/RC2Engine.java317
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/RC2WrapEngine.java385
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/RC4Engine.java146
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/RC532Engine.java287
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/RC564Engine.java288
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/RC6Engine.java363
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/RFC3211WrapEngine.java175
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java177
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/RFC5649WrapEngine.java294
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java126
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/RSABlindingEngine.java137
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/RSACoreEngine.java203
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/RSAEngine.java78
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/RijndaelEngine.java725
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/SEEDEngine.java346
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/SEEDWrapEngine.java15
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/Salsa20Engine.java474
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/SerpentEngine.java783
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/Shacal2Engine.java201
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/SkipjackEngine.java260
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/TEAEngine.java184
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/ThreefishEngine.java1494
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/TwofishEngine.java680
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/VMPCEngine.java142
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/VMPCKSA3Engine.java45
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/XSalsa20Engine.java65
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/XTEAEngine.java188
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/examples/DESExample.java421
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/examples/JPAKEExample.java214
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java143
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/CramerShoupKeyPairGenerator.java63
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/CramerShoupParametersGenerator.java123
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/DESKeyGenerator.java48
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/DESedeKeyGenerator.java56
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/DHBasicKeyPairGenerator.java42
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/DHKeyGeneratorHelper.java67
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/DHKeyPairGenerator.java42
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/DHParametersGenerator.java52
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/DHParametersHelper.java93
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/DSAKeyPairGenerator.java69
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java387
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/DSTU4145KeyPairGenerator.java21
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java84
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/ElGamalKeyPairGenerator.java44
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/ElGamalParametersGenerator.java43
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/EphemeralKeyPairGenerator.java26
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/GOST3410KeyPairGenerator.java74
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/GOST3410ParametersGenerator.java541
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/HKDFBytesGenerator.java161
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/KDF1BytesGenerator.java23
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/KDF2BytesGenerator.java24
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/KDFCounterBytesGenerator.java180
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/KDFDoublePipelineIterationBytesGenerator.java181
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/KDFFeedbackBytesGenerator.java175
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/MGF1BytesGenerator.java114
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/NaccacheSternKeyPairGenerator.java365
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java131
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/PKCS12ParametersGenerator.java220
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/PKCS5S1ParametersGenerator.java119
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java153
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/Poly1305KeyGenerator.java117
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/RSABlindingFactorGenerator.java77
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java153
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/generators/SCrypt.java198
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/io/CipherIOException.java26
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/io/CipherInputStream.java477
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/io/CipherOutputStream.java276
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/io/DigestInputStream.java52
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/io/DigestOutputStream.java42
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/io/InvalidCipherTextIOException.java19
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/io/MacInputStream.java52
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/io/MacOutputStream.java42
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/io/SignerInputStream.java52
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/io/SignerOutputStream.java38
-rwxr-xr-xcore/src/main/java/org/bouncycastle/crypto/kems/ECIESKeyEncapsulation.java244
-rwxr-xr-xcore/src/main/java/org/bouncycastle/crypto/kems/RSAKeyEncapsulation.java155
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/macs/BlockCipherMac.java174
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/macs/CBCBlockCipherMac.java229
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/macs/CFBBlockCipherMac.java388
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/macs/CMac.java261
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/macs/CMacWithIV.java27
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/macs/GMac.java115
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/macs/GOST28147Mac.java298
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/macs/HMac.java231
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/macs/ISO9797Alg3Mac.java305
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/macs/OldHMac.java138
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/macs/Poly1305.java306
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/macs/SipHash.java216
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/macs/SkeinMac.java118
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/macs/VMPCMac.java186
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/AEADBlockCipher.java146
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/CBCBlockCipher.java253
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java457
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java269
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java287
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/EAXBlockCipher.java387
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/GCFBBlockCipher.java120
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java596
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/GOFBBlockCipher.java228
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/OCBBlockCipher.java598
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/OFBBlockCipher.java178
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/OldCTSBlockCipher.java269
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/OpenPGPCFBBlockCipher.java312
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java455
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/PaddedBlockCipher.java253
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java225
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/gcm/BasicGCMExponentiator.java36
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/gcm/BasicGCMMultiplier.java18
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMExponentiator.java7
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMMultiplier.java7
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java457
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java58
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables64kGCMMultiplier.java73
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java90
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/paddings/BlockCipherPadding.java48
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/paddings/ISO10126d2Padding.java79
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/paddings/ISO7816d4Padding.java77
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/paddings/PKCS7Padding.java76
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java299
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/paddings/TBCPadding.java89
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/paddings/X923Padding.java80
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/paddings/ZeroBytePadding.java73
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/AEADParameters.java60
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/AsymmetricKeyParameter.java20
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/CCMParameters.java21
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/CramerShoupKeyGenerationParameters.java24
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/CramerShoupKeyParameters.java40
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/CramerShoupParameters.java53
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/CramerShoupPrivateKeyParameters.java61
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/CramerShoupPublicKeyParameters.java42
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/DESParameters.java107
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/DESedeParameters.java57
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/DHKeyGenerationParameters.java30
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/DHKeyParameters.java54
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/DHParameters.java189
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/DHPrivateKeyParameters.java41
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/DHPublicKeyParameters.java41
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/DHValidationParameters.java50
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/DSAKeyGenerationParameters.java25
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/DSAKeyParameters.java21
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/DSAParameterGenerationParameters.java80
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/DSAParameters.java74
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/DSAPrivateKeyParameters.java23
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/DSAPublicKeyParameters.java23
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/DSAValidationParameters.java65
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java74
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/ECKeyGenerationParameters.java25
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/ECKeyParameters.java21
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/ECNamedDomainParameters.java35
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/ECPrivateKeyParameters.java22
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java22
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/ElGamalKeyGenerationParameters.java30
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/ElGamalKeyParameters.java47
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/ElGamalParameters.java69
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/ElGamalPrivateKeyParameters.java46
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/ElGamalPublicKeyParameters.java41
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/GOST3410KeyGenerationParameters.java25
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/GOST3410KeyParameters.java21
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/GOST3410Parameters.java74
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/GOST3410PrivateKeyParameters.java23
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/GOST3410PublicKeyParameters.java23
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/GOST3410ValidationParameters.java84
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/HKDFParameters.java123
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/IESParameters.java44
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/IESWithCipherParameters.java30
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/ISO18033KDFParameters.java23
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/KDFCounterParameters.java120
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/KDFDoublePipelineIterationParameters.java80
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/KDFFeedbackParameters.java96
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/KDFParameters.java31
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/KeyParameter.java30
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/MGFParameters.java32
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/MQVPrivateParameters.java43
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/MQVPublicParameters.java28
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/NaccacheSternKeyGenerationParameters.java97
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/NaccacheSternKeyParameters.java53
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/NaccacheSternPrivateKeyParameters.java50
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/ParametersWithIV.java39
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/ParametersWithRandom.java36
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/ParametersWithSBox.java28
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/ParametersWithSalt.java42
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/RC2Parameters.java36
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/RC5Parameters.java35
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/RSABlindingParameters.java35
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/RSAKeyGenerationParameters.java48
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/RSAKeyParameters.java31
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/RSAPrivateCrtKeyParameters.java67
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/SkeinParameters.java329
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/params/TweakableBlockCipherParameters.java40
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/parsers/DHIESPublicKeyParser.java31
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/parsers/ECIESPublicKeyParser.java53
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/prng/BasicEntropySourceProvider.java53
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/prng/DRBGProvider.java8
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/prng/DigestRandomGenerator.java123
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/prng/EntropySource.java25
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/prng/EntropySourceProvider.java6
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/prng/FixedSecureRandom.java147
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/prng/RandomGenerator.java38
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/prng/ReversedWindowGenerator.java111
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/prng/SP800SecureRandom.java74
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/prng/SP800SecureRandomBuilder.java290
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/prng/ThreadedSeedGenerator.java95
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/prng/VMPCRandomGenerator.java127
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/prng/drbg/CTRSP800DRBG.java478
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/prng/drbg/DualECPoints.java82
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/prng/drbg/DualECSP800DRBG.java320
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/prng/drbg/HMacSP800DRBG.java181
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/prng/drbg/HashSP800DRBG.java284
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/prng/drbg/SP80090DRBG.java32
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/prng/drbg/Utils.java103
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/signers/DSADigestSigner.java163
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/signers/DSAKCalculator.java41
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java168
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/signers/DSTU4145Signer.java170
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java197
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/signers/ECGOST3410Signer.java160
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/signers/ECNRSigner.java188
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/signers/GOST3410Signer.java131
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/signers/GenericSigner.java136
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/signers/HMacDSAKCalculator.java152
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/signers/ISO9796d2PSSSigner.java668
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/signers/ISO9796d2Signer.java618
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/signers/PSSSigner.java348
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java240
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java43
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsAgreementCredentials.java7
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsCipherFactory.java13
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java235
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsContext.java133
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsCredentials.java6
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsEncryptionCredentials.java7
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsKeyExchange.java166
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsPeer.java42
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsServer.java335
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsSigner.java38
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsSignerCredentials.java11
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/AlertDescription.java216
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/AlertLevel.java10
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/AlwaysValidVerifyer.java23
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/BulkCipherAlgorithm.java23
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/ByteQueue.java153
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/CertChainType.java15
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/Certificate.java148
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/CertificateRequest.java158
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/CertificateStatus.java105
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/CertificateStatusRequest.java98
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/CertificateStatusType.java9
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/CertificateURL.java133
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/CertificateVerifyer.java16
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/Chacha20Poly1305.java156
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/ChangeCipherSpec.java6
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/CipherSuite.java351
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/CipherType.java18
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/ClientAuthenticationType.java11
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/ClientCertificateType.java22
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/CombinedHash.java135
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/CompressionMethod.java24
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/ConnectionEnd.java13
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/ContentType.java13
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/DTLSClientProtocol.java831
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/DTLSEpoch.java52
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/DTLSHandshakeRetransmit.java9
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/DTLSProtocol.java78
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/DTLSReassembler.java133
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/DTLSRecordLayer.java516
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/DTLSReliableHandshake.java453
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/DTLSReplayWindow.java90
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/DTLSServerProtocol.java667
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/DTLSTransport.java80
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/DatagramTransport.java21
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsAgreementCredentials.java78
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsCipherFactory.java237
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsClient.java453
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsEncryptionCredentials.java62
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsServer.java550
-rwxr-xr-xcore/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsSignerCredentials.java104
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/DeferredHash.java207
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/DigestAlgorithm.java23
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/DigestInputBuffer.java13
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/DigitallySigned.java72
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/ECBasisType.java15
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/ECCurveType.java28
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/ECPointFormat.java15
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/EncryptionAlgorithm.java67
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/ExporterLabel.java31
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/ExtensionType.java60
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/HandshakeType.java39
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/HashAlgorithm.java15
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/HeartbeatExtension.java56
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMessage.java111
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMessageType.java15
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMode.java15
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/KeyExchangeAlgorithm.java52
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/LegacyTlsAuthentication.java28
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/LegacyTlsClient.java33
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/MACAlgorithm.java23
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/MaxFragmentLength.java17
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/NameType.java9
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/NamedCurve.java71
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/NewSessionTicket.java55
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/OCSPStatusRequest.java131
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/PRFAlgorithm.java22
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/PSKTlsClient.java256
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/ProtocolVersion.java158
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/RecordStream.java365
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/SRPTlsClient.java121
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/SRTPProtectionProfile.java12
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/SSL3Mac.java114
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/SecurityParameters.java91
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/ServerDHParams.java63
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/ServerName.java112
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/ServerNameList.java86
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/ServerOnlyTlsAuthentication.java10
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/SessionParameters.java142
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/SignatureAlgorithm.java12
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/SignatureAndHashAlgorithm.java96
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/SignerInputBuffer.java13
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/SupplementalDataEntry.java23
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/SupplementalDataType.java12
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsAEADCipher.java193
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsAgreementCredentials.java12
-rwxr-xr-xcore/src/main/java/org/bouncycastle/crypto/tls/TlsAuthentication.java26
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsBlockCipher.java386
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsCipher.java14
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsCipherFactory.java12
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java79
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsClientContext.java6
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsClientContextImpl.java18
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsClientProtocol.java917
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsCompression.java10
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsContext.java45
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsCredentials.java6
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsDHEKeyExchange.java115
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsDHKeyExchange.java208
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsDHUtils.java105
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsDSASigner.java92
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsDSSSigner.java26
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsECCUtils.java690
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsECDHEKeyExchange.java221
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsECDHKeyExchange.java219
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsECDSASigner.java26
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsEncryptionCredentials.java9
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsExtensionsUtils.java267
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsFatalAlert.java21
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsHandshakeHash.java21
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsInputStream.java47
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsKeyExchange.java54
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsMac.java172
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsNullCipher.java123
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsNullCompression.java17
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsOutputStream.java44
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsPSKIdentity.java12
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsPSKKeyExchange.java285
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsPeer.java46
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsProtocol.java1184
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsProtocolHandler.java22
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsRSAKeyExchange.java191
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsRSASigner.java112
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsRSAUtils.java140
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsSRPKeyExchange.java205
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsSRPUtils.java48
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsSRTPUtils.java74
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsServer.java90
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsServerContext.java6
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsServerContextImpl.java18
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsServerProtocol.java778
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsSession.java12
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsSessionImpl.java48
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsSigner.java34
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsSignerCredentials.java12
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsStreamCipher.java178
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/TlsUtils.java1780
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/UDPTransport.java75
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/URLAndHash.java104
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/UseSRTPData.java52
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/tls/UserMappingType.java12
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/util/Pack.java204
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java159
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyInfoFactory.java86
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java195
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java85
-rw-r--r--core/src/main/java/org/bouncycastle/i18n/ErrorBundle.java120
-rw-r--r--core/src/main/java/org/bouncycastle/i18n/LocaleString.java30
-rw-r--r--core/src/main/java/org/bouncycastle/i18n/LocalizedException.java49
-rw-r--r--core/src/main/java/org/bouncycastle/i18n/LocalizedMessage.java476
-rw-r--r--core/src/main/java/org/bouncycastle/i18n/MessageBundle.java92
-rw-r--r--core/src/main/java/org/bouncycastle/i18n/MissingEntryException.java73
-rw-r--r--core/src/main/java/org/bouncycastle/i18n/TextBundle.java92
-rw-r--r--core/src/main/java/org/bouncycastle/i18n/filter/Filter.java21
-rw-r--r--core/src/main/java/org/bouncycastle/i18n/filter/HTMLFilter.java68
-rw-r--r--core/src/main/java/org/bouncycastle/i18n/filter/SQLFilter.java69
-rw-r--r--core/src/main/java/org/bouncycastle/i18n/filter/TrustedInput.java23
-rw-r--r--core/src/main/java/org/bouncycastle/i18n/filter/UntrustedInput.java44
-rw-r--r--core/src/main/java/org/bouncycastle/i18n/filter/UntrustedUrlInput.java14
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java26
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/DoubleAddMultiplier.java24
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java469
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/ECConstants.java12
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/ECCurve.java1113
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java868
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/ECMultiplier.java19
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/ECPoint.java2122
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/ECPointMap.java6
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/FixedPointCombMultiplier.java57
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/FixedPointPreCompInfo.java40
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/FixedPointUtil.java71
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/GLVMultiplier.java42
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/LongArray.java2195
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/MixedNafR2LMultiplier.java77
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/MontgomeryLadderMultiplier.java25
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/NafL2RMultiplier.java30
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/NafR2LMultiplier.java31
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/PreCompInfo.java10
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/ReferenceMultiplier.java11
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/ScaleXPointMap.java16
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/ScaleYPointMap.java16
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/SimpleBigDecimal.java247
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/Tnaf.java823
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/WNafL2RMultiplier.java96
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/WNafPreCompInfo.java56
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/WNafUtil.java485
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java114
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/WTauNafPreCompInfo.java26
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/ZSignedDigitL2RMultiplier.java29
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/ZSignedDigitR2LMultiplier.java30
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/ZTauElement.java37
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519.java80
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519Field.java254
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519FieldElement.java234
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519Point.java348
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Curve.java79
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Field.java177
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1FieldElement.java213
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Point.java298
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Curve.java80
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Field.java286
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1FieldElement.java190
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Point.java310
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Curve.java78
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Field.java178
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1FieldElement.java243
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Point.java298
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Curve.java80
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Field.java298
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1FieldElement.java273
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Point.java308
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Curve.java78
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Field.java179
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1FieldElement.java215
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Point.java298
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Curve.java80
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java312
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1FieldElement.java189
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Point.java308
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Curve.java80
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Field.java295
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1FieldElement.java211
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Point.java309
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Curve.java80
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Field.java156
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1FieldElement.java169
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Point.java333
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/endo/ECEndomorphism.java10
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/endo/GLVEndomorphism.java8
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBEndomorphism.java58
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBParameters.java59
-rw-r--r--core/src/main/java/org/bouncycastle/math/ec/tools/DiscoverEndomorphisms.java373
-rw-r--r--core/src/main/java/org/bouncycastle/math/field/ExtensionField.java8
-rw-r--r--core/src/main/java/org/bouncycastle/math/field/FiniteField.java10
-rw-r--r--core/src/main/java/org/bouncycastle/math/field/FiniteFields.java53
-rw-r--r--core/src/main/java/org/bouncycastle/math/field/GF2Polynomial.java42
-rw-r--r--core/src/main/java/org/bouncycastle/math/field/GenericPolynomialExtensionField.java62
-rw-r--r--core/src/main/java/org/bouncycastle/math/field/Polynomial.java12
-rw-r--r--core/src/main/java/org/bouncycastle/math/field/PolynomialExtensionField.java6
-rw-r--r--core/src/main/java/org/bouncycastle/math/field/PrimeField.java42
-rw-r--r--core/src/main/java/org/bouncycastle/math/raw/Mod.java199
-rw-r--r--core/src/main/java/org/bouncycastle/math/raw/Mont256.java152
-rw-r--r--core/src/main/java/org/bouncycastle/math/raw/Nat.java1038
-rw-r--r--core/src/main/java/org/bouncycastle/math/raw/Nat192.java968
-rw-r--r--core/src/main/java/org/bouncycastle/math/raw/Nat224.java1182
-rw-r--r--core/src/main/java/org/bouncycastle/math/raw/Nat256.java1306
-rw-r--r--core/src/main/java/org/bouncycastle/math/raw/Nat384.java43
-rw-r--r--core/src/main/java/org/bouncycastle/math/raw/Nat512.java43
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/asn1/GMSSPrivateKey.java1312
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/asn1/GMSSPublicKey.java74
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/asn1/McElieceCCA2PrivateKey.java173
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/asn1/McElieceCCA2PublicKey.java96
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/asn1/McEliecePrivateKey.java197
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/asn1/McEliecePublicKey.java97
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/asn1/PQCObjectIdentifiers.java46
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/asn1/ParSet.java140
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/asn1/RainbowPrivateKey.java349
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/asn1/RainbowPublicKey.java174
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/DigestingMessageSigner.java117
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/MessageEncryptor.java30
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/MessageSigner.java32
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSDigestProvider.java8
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSKeyGenerationParameters.java26
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSKeyPairGenerator.java476
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSKeyParameters.java22
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSLeaf.java376
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSParameters.java155
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSPrivateKeyParameters.java1041
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSPublicKeyParameters.java33
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSRootCalc.java596
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSRootSig.java666
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSSigner.java403
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSUtils.java145
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/gmss/Treehash.java525
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/gmss/util/GMSSRandom.java78
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/gmss/util/GMSSUtil.java151
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/gmss/util/WinternitzOTSVerify.java344
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/gmss/util/WinternitzOTSignature.java404
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/Conversions.java236
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2KeyGenerationParameters.java25
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2KeyPairGenerator.java119
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2KeyParameters.java25
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2Parameters.java51
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2Primitives.java86
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2PrivateKeyParameters.java172
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2PublicKeyParameters.java97
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceFujisakiCipher.java218
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceFujisakiDigestCipher.java128
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceKeyGenerationParameters.java25
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceKeyPairGenerator.java151
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceKeyParameters.java25
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceKobaraImaiCipher.java319
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceKobaraImaiDigestCipher.java128
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePKCSCipher.java224
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePKCSDigestCipher.java128
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceParameters.java181
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePointchevalCipher.java241
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePointchevalDigestCipher.java128
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePrivateKeyParameters.java197
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePublicKeyParameters.java96
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/ntru/IndexGenerator.java239
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionKeyGenerationParameters.java463
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionKeyPairGenerator.java113
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionKeyParameters.java20
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionParameters.java410
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionPrivateKeyParameters.java199
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionPublicKeyParameters.java131
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEngine.java495
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUParameters.java7
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigner.java263
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSignerPrng.java64
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningKeyGenerationParameters.java407
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningKeyPairGenerator.java357
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningParameters.java269
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningPrivateKeyParameters.java385
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningPublicKeyParameters.java132
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/Layer.java322
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowKeyGenerationParameters.java26
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowKeyPairGenerator.java413
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowKeyParameters.java25
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowParameters.java111
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowPrivateKeyParameters.java117
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowPublicKeyParameters.java53
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowSigner.java301
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/util/ComputeInField.java490
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/util/GF2Field.java139
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/util/RainbowUtil.java230
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/BigEndianConversions.java306
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/BigIntUtils.java138
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/ByteUtils.java414
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/CharUtils.java98
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Matrix.java1323
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Polynomial.java2039
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Vector.java539
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mField.java365
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mMatrix.java377
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mVector.java256
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nElement.java186
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nField.java292
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nONBElement.java1154
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nONBField.java546
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomial.java587
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomialElement.java1021
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomialField.java553
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GFElement.java158
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GoppaCode.java310
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/IntUtils.java202
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/IntegerFunctions.java1423
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/LittleEndianConversions.java230
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Matrix.java131
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Permutation.java247
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialGF2mSmallM.java1124
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialRingGF2.java278
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialRingGF2m.java175
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/RandUtils.java25
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Vector.java69
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/BigIntEuclidean.java54
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/IntEuclidean.java51
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/BigDecimalPolynomial.java258
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/BigIntPolynomial.java394
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Constants.java12
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/DenseTernaryPolynomial.java142
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/IntegerPolynomial.java1358
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/LongPolynomial2.java255
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/LongPolynomial5.java149
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/ModularResultant.java46
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Polynomial.java42
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/ProductFormPolynomial.java153
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Resultant.java28
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/SparseTernaryPolynomial.java320
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/TernaryPolynomial.java25
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/ntru/util/ArrayEncoder.java292
-rw-r--r--core/src/main/java/org/bouncycastle/pqc/math/ntru/util/Util.java158
-rw-r--r--core/src/main/java/org/bouncycastle/util/Arrays.java971
-rw-r--r--core/src/main/java/org/bouncycastle/util/BigIntegers.java121
-rw-r--r--core/src/main/java/org/bouncycastle/util/CollectionStore.java57
-rw-r--r--core/src/main/java/org/bouncycastle/util/IPAddress.java188
-rw-r--r--core/src/main/java/org/bouncycastle/util/Integers.java19
-rw-r--r--core/src/main/java/org/bouncycastle/util/Memoable.java23
-rw-r--r--core/src/main/java/org/bouncycastle/util/MemoableResetException.java22
-rw-r--r--core/src/main/java/org/bouncycastle/util/Pack.java201
-rw-r--r--core/src/main/java/org/bouncycastle/util/Selector.java9
-rw-r--r--core/src/main/java/org/bouncycastle/util/Shorts.java9
-rw-r--r--core/src/main/java/org/bouncycastle/util/Store.java9
-rw-r--r--core/src/main/java/org/bouncycastle/util/StoreException.java18
-rw-r--r--core/src/main/java/org/bouncycastle/util/StreamParser.java10
-rw-r--r--core/src/main/java/org/bouncycastle/util/StreamParsingException.java18
-rw-r--r--core/src/main/java/org/bouncycastle/util/Strings.java314
-rw-r--r--core/src/main/java/org/bouncycastle/util/Times.java9
-rw-r--r--core/src/main/java/org/bouncycastle/util/encoders/Base64.java154
-rw-r--r--core/src/main/java/org/bouncycastle/util/encoders/Base64Encoder.java331
-rw-r--r--core/src/main/java/org/bouncycastle/util/encoders/BufferedDecoder.java96
-rw-r--r--core/src/main/java/org/bouncycastle/util/encoders/BufferedEncoder.java96
-rw-r--r--core/src/main/java/org/bouncycastle/util/encoders/DecoderException.java22
-rw-r--r--core/src/main/java/org/bouncycastle/util/encoders/Encoder.java17
-rw-r--r--core/src/main/java/org/bouncycastle/util/encoders/EncoderException.java22
-rw-r--r--core/src/main/java/org/bouncycastle/util/encoders/Hex.java151
-rw-r--r--core/src/main/java/org/bouncycastle/util/encoders/HexEncoder.java190
-rw-r--r--core/src/main/java/org/bouncycastle/util/encoders/HexTranslator.java87
-rw-r--r--core/src/main/java/org/bouncycastle/util/encoders/Translator.java23
-rw-r--r--core/src/main/java/org/bouncycastle/util/encoders/UrlBase64.java129
-rw-r--r--core/src/main/java/org/bouncycastle/util/encoders/UrlBase64Encoder.java25
-rw-r--r--core/src/main/java/org/bouncycastle/util/io/BufferingOutputStream.java108
-rw-r--r--core/src/main/java/org/bouncycastle/util/io/StreamOverflowException.java15
-rw-r--r--core/src/main/java/org/bouncycastle/util/io/Streams.java145
-rw-r--r--core/src/main/java/org/bouncycastle/util/io/TeeInputStream.java71
-rw-r--r--core/src/main/java/org/bouncycastle/util/io/TeeOutputStream.java62
-rw-r--r--core/src/main/java/org/bouncycastle/util/io/pem/PemGenerationException.java28
-rw-r--r--core/src/main/java/org/bouncycastle/util/io/pem/PemHeader.java75
-rw-r--r--core/src/main/java/org/bouncycastle/util/io/pem/PemObject.java64
-rw-r--r--core/src/main/java/org/bouncycastle/util/io/pem/PemObjectGenerator.java16
-rw-r--r--core/src/main/java/org/bouncycastle/util/io/pem/PemObjectParser.java19
-rw-r--r--core/src/main/java/org/bouncycastle/util/io/pem/PemReader.java87
-rw-r--r--core/src/main/java/org/bouncycastle/util/io/pem/PemWriter.java137
-rw-r--r--core/src/main/java/org/bouncycastle/util/test/FixedSecureRandom.java135
-rw-r--r--core/src/main/java/org/bouncycastle/util/test/NumberParsing.java34
-rw-r--r--core/src/main/java/org/bouncycastle/util/test/SimpleTest.java84
-rw-r--r--core/src/main/java/org/bouncycastle/util/test/SimpleTestResult.java80
-rw-r--r--core/src/main/java/org/bouncycastle/util/test/Test.java8
-rw-r--r--core/src/main/java/org/bouncycastle/util/test/TestFailedException.java18
-rw-r--r--core/src/main/java/org/bouncycastle/util/test/TestResult.java10
-rw-r--r--core/src/main/java/org/bouncycastle/util/test/UncloseableOutputStream.java23
-rw-r--r--core/src/main/java/org/spongycastle/LICENSE.java63
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1ApplicationSpecificParser.java19
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1Boolean.java204
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1Choice.java28
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1Encodable.java13
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1EncodableVector.java63
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1Encoding.java22
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1Enumerated.java174
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1Exception.java25
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1GeneralizedTime.java373
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1Generator.java15
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1InputStream.java472
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1Integer.java157
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1Null.java75
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1Object.java111
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1ObjectIdentifier.java472
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1OctetString.java251
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1OctetStringParser.java17
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1OutputStream.java194
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1ParsingException.java23
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1Primitive.java82
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1Sequence.java382
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1SequenceParser.java19
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1Set.java560
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1SetParser.java19
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1StreamParser.java250
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1String.java6
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1TaggedObject.java236
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1TaggedObjectParser.java12
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ASN1UTCTime.java314
-rw-r--r--core/src/main/java/org/spongycastle/asn1/BERApplicationSpecific.java10
-rw-r--r--core/src/main/java/org/spongycastle/asn1/BERApplicationSpecificParser.java41
-rw-r--r--core/src/main/java/org/spongycastle/asn1/BERConstructedOctetString.java144
-rw-r--r--core/src/main/java/org/spongycastle/asn1/BERFactory.java17
-rw-r--r--core/src/main/java/org/spongycastle/asn1/BERGenerator.java100
-rw-r--r--core/src/main/java/org/spongycastle/asn1/BEROctetString.java168
-rw-r--r--core/src/main/java/org/spongycastle/asn1/BEROctetStringGenerator.java102
-rw-r--r--core/src/main/java/org/spongycastle/asn1/BEROctetStringParser.java41
-rw-r--r--core/src/main/java/org/spongycastle/asn1/BEROutputStream.java36
-rw-r--r--core/src/main/java/org/spongycastle/asn1/BERSequence.java73
-rw-r--r--core/src/main/java/org/spongycastle/asn1/BERSequenceGenerator.java41
-rw-r--r--core/src/main/java/org/spongycastle/asn1/BERSequenceParser.java38
-rw-r--r--core/src/main/java/org/spongycastle/asn1/BERSet.java73
-rw-r--r--core/src/main/java/org/spongycastle/asn1/BERSetParser.java38
-rw-r--r--core/src/main/java/org/spongycastle/asn1/BERTaggedObject.java147
-rw-r--r--core/src/main/java/org/spongycastle/asn1/BERTaggedObjectParser.java66
-rw-r--r--core/src/main/java/org/spongycastle/asn1/BERTags.java36
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ConstructedOctetStream.java111
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERApplicationSpecific.java267
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERBMPString.java157
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERBitString.java318
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERBoolean.java22
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DEREncodableVector.java18
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DEREnumerated.java37
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERExternal.java294
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERExternalParser.java52
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERFactory.java17
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERGeneralString.java110
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERGeneralizedTime.java28
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERGenerator.java119
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERIA5String.java189
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERInteger.java30
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERNull.java38
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERNumericString.java189
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERObjectIdentifier.java24
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DEROctetString.java48
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DEROctetStringParser.java39
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DEROutputStream.java41
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERPrintableString.java216
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERSequence.java98
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERSequenceGenerator.java45
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERSequenceParser.java38
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERSet.java108
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERSetParser.java38
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERT61String.java151
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERT61UTF8String.java154
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERTaggedObject.java118
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERTags.java9
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERUTCTime.java27
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERUTF8String.java135
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERUniversalString.java151
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DERVisibleString.java141
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DLOutputStream.java31
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DLSequence.java101
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DLSet.java146
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DLTaggedObject.java112
-rw-r--r--core/src/main/java/org/spongycastle/asn1/DefiniteLengthInputStream.java105
-rw-r--r--core/src/main/java/org/spongycastle/asn1/InMemoryRepresentable.java16
-rw-r--r--core/src/main/java/org/spongycastle/asn1/IndefiniteLengthInputStream.java111
-rw-r--r--core/src/main/java/org/spongycastle/asn1/LazyConstructionEnumeration.java43
-rw-r--r--core/src/main/java/org/spongycastle/asn1/LazyEncodedSequence.java109
-rw-r--r--core/src/main/java/org/spongycastle/asn1/LimitedInputStream.java32
-rw-r--r--core/src/main/java/org/spongycastle/asn1/OIDTokenizer.java48
-rw-r--r--core/src/main/java/org/spongycastle/asn1/StreamUtil.java114
-rw-r--r--core/src/main/java/org/spongycastle/asn1/bc/BCObjectIdentifiers.java71
-rw-r--r--core/src/main/java/org/spongycastle/asn1/bsi/BSIObjectIdentifiers.java35
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/CAKeyUpdAnnContent.java80
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/CMPCertificate.java92
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/CMPObjectIdentifiers.java141
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/CRLAnnContent.java61
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/CertConfirmContent.java54
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/CertOrEncCert.java96
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/CertRepMessage.java123
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/CertResponse.java139
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/CertStatus.java102
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/CertifiedKeyPair.java127
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/Challenge.java120
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/ErrorMsgContent.java121
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/GenMsgContent.java71
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/GenRepContent.java71
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/InfoTypeAndValue.java132
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/KeyRecRepContent.java142
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/OOBCertHash.java117
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PBMParameter.java117
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PKIBody.java194
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PKIConfirmContent.java48
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PKIFailureInfo.java126
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PKIFreeText.java115
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PKIHeader.java260
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PKIHeaderBuilder.java243
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PKIMessage.java166
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PKIMessages.java71
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PKIStatus.java64
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PKIStatusInfo.java165
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/POPODecKeyChallContent.java54
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/POPODecKeyRespContent.java55
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PollRepContent.java119
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/PollReqContent.java80
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/ProtectedPart.java70
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/RevAnnContent.java103
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/RevDetails.java100
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/RevRepContent.java137
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/RevRepContentBuilder.java59
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cmp/RevReqContent.java73
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/Attribute.java110
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/AttributeTable.java240
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/Attributes.java85
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/AuthEnvelopedData.java248
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/AuthEnvelopedDataParser.java157
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/AuthenticatedData.java312
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/AuthenticatedDataParser.java206
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/CCMParameters.java102
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/CMSAttributes.java30
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/CMSObjectIdentifiers.java43
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/CompressedData.java117
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/CompressedDataParser.java49
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/ContentInfo.java130
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/ContentInfoParser.java48
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/DigestedData.java128
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/EncryptedContentInfo.java120
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/EncryptedContentInfoParser.java53
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/EncryptedData.java111
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/EnvelopedData.java215
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/EnvelopedDataParser.java120
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/Evidence.java80
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/GCMParameters.java102
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/IssuerAndSerialNumber.java138
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/KEKIdentifier.java151
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/KEKRecipientInfo.java133
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/KeyAgreeRecipientIdentifier.java116
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/KeyAgreeRecipientInfo.java166
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/KeyTransRecipientInfo.java127
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/MetaData.java135
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/OriginatorIdentifierOrKey.java179
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/OriginatorInfo.java159
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/OriginatorPublicKey.java114
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/OtherKeyAttribute.java96
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/OtherRecipientInfo.java112
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/OtherRevocationInfoFormat.java109
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/PasswordRecipientInfo.java157
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/RecipientEncryptedKey.java109
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/RecipientIdentifier.java111
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/RecipientInfo.java173
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/RecipientKeyIdentifier.java171
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/SCVPReqRes.java108
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/SignedData.java330
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/SignedDataParser.java141
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/SignerIdentifier.java114
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/SignerInfo.java282
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/Time.java198
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/TimeStampAndCRL.java96
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/TimeStampTokenEvidence.java98
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/TimeStampedData.java131
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/TimeStampedDataParser.java141
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cms/ecc/MQVuserKeyingMaterial.java122
-rw-r--r--core/src/main/java/org/spongycastle/asn1/crmf/AttributeTypeAndValue.java80
-rw-r--r--core/src/main/java/org/spongycastle/asn1/crmf/CRMFObjectIdentifiers.java29
-rw-r--r--core/src/main/java/org/spongycastle/asn1/crmf/CertId.java84
-rw-r--r--core/src/main/java/org/spongycastle/asn1/crmf/CertReqMessages.java74
-rw-r--r--core/src/main/java/org/spongycastle/asn1/crmf/CertReqMsg.java145
-rw-r--r--core/src/main/java/org/spongycastle/asn1/crmf/CertRequest.java97
-rw-r--r--core/src/main/java/org/spongycastle/asn1/crmf/CertTemplate.java163
-rw-r--r--core/src/main/java/org/spongycastle/asn1/crmf/CertTemplateBuilder.java152
-rw-r--r--core/src/main/java/org/spongycastle/asn1/crmf/Controls.java72
-rw-r--r--core/src/main/java/org/spongycastle/asn1/crmf/EncKeyWithID.java117
-rw-r--r--core/src/main/java/org/spongycastle/asn1/crmf/EncryptedKey.java81
-rw-r--r--core/src/main/java/org/spongycastle/asn1/crmf/EncryptedValue.java164
-rw-r--r--core/src/main/java/org/spongycastle/asn1/crmf/OptionalValidity.java98
-rw-r--r--core/src/main/java/org/spongycastle/asn1/crmf/PKIArchiveOptions.java116
-rw-r--r--core/src/main/java/org/spongycastle/asn1/crmf/PKIPublicationInfo.java81
-rw-r--r--core/src/main/java/org/spongycastle/asn1/crmf/PKMACValue.java104
-rw-r--r--core/src/main/java/org/spongycastle/asn1/crmf/POPOPrivKey.java104
-rw-r--r--core/src/main/java/org/spongycastle/asn1/crmf/POPOSigningKey.java127
-rw-r--r--core/src/main/java/org/spongycastle/asn1/crmf/POPOSigningKeyInput.java134
-rw-r--r--core/src/main/java/org/spongycastle/asn1/crmf/ProofOfPossession.java108
-rw-r--r--core/src/main/java/org/spongycastle/asn1/crmf/SinglePubInfo.java72
-rw-r--r--core/src/main/java/org/spongycastle/asn1/crmf/SubsequentMessage.java29
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cryptopro/CryptoProObjectIdentifiers.java101
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cryptopro/ECGOST3410NamedCurves.java177
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cryptopro/ECGOST3410ParamSetParameters.java99
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cryptopro/GOST28147Parameters.java98
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cryptopro/GOST3410NamedParameters.java116
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cryptopro/GOST3410ParamSetParameters.java105
-rw-r--r--core/src/main/java/org/spongycastle/asn1/cryptopro/GOST3410PublicKeyAlgParameters.java104
-rw-r--r--core/src/main/java/org/spongycastle/asn1/dvcs/CertEtcToken.java171
-rw-r--r--core/src/main/java/org/spongycastle/asn1/dvcs/DVCSCertInfo.java302
-rw-r--r--core/src/main/java/org/spongycastle/asn1/dvcs/DVCSCertInfoBuilder.java151
-rw-r--r--core/src/main/java/org/spongycastle/asn1/dvcs/DVCSErrorNotice.java96
-rw-r--r--core/src/main/java/org/spongycastle/asn1/dvcs/DVCSObjectIdentifiers.java29
-rw-r--r--core/src/main/java/org/spongycastle/asn1/dvcs/DVCSRequest.java107
-rw-r--r--core/src/main/java/org/spongycastle/asn1/dvcs/DVCSRequestInformation.java271
-rw-r--r--core/src/main/java/org/spongycastle/asn1/dvcs/DVCSRequestInformationBuilder.java224
-rw-r--r--core/src/main/java/org/spongycastle/asn1/dvcs/DVCSResponse.java117
-rw-r--r--core/src/main/java/org/spongycastle/asn1/dvcs/DVCSTime.java111
-rw-r--r--core/src/main/java/org/spongycastle/asn1/dvcs/Data.java149
-rw-r--r--core/src/main/java/org/spongycastle/asn1/dvcs/PathProcInput.java180
-rw-r--r--core/src/main/java/org/spongycastle/asn1/dvcs/ServiceType.java92
-rw-r--r--core/src/main/java/org/spongycastle/asn1/dvcs/TargetEtcChain.java191
-rw-r--r--core/src/main/java/org/spongycastle/asn1/eac/BidirectionalMap.java23
-rw-r--r--core/src/main/java/org/spongycastle/asn1/eac/CVCertificate.java313
-rw-r--r--core/src/main/java/org/spongycastle/asn1/eac/CVCertificateRequest.java170
-rw-r--r--core/src/main/java/org/spongycastle/asn1/eac/CertificateBody.java472
-rw-r--r--core/src/main/java/org/spongycastle/asn1/eac/CertificateHolderAuthorization.java184
-rw-r--r--core/src/main/java/org/spongycastle/asn1/eac/CertificateHolderReference.java66
-rw-r--r--core/src/main/java/org/spongycastle/asn1/eac/CertificationAuthorityReference.java15
-rw-r--r--core/src/main/java/org/spongycastle/asn1/eac/EACObjectIdentifiers.java110
-rw-r--r--core/src/main/java/org/spongycastle/asn1/eac/EACTags.java209
-rw-r--r--core/src/main/java/org/spongycastle/asn1/eac/ECDSAPublicKey.java340
-rw-r--r--core/src/main/java/org/spongycastle/asn1/eac/Flags.java96
-rw-r--r--core/src/main/java/org/spongycastle/asn1/eac/PackedDate.java124
-rw-r--r--core/src/main/java/org/spongycastle/asn1/eac/PublicKeyDataObject.java35
-rw-r--r--core/src/main/java/org/spongycastle/asn1/eac/RSAPublicKey.java120
-rw-r--r--core/src/main/java/org/spongycastle/asn1/eac/UnsignedInteger.java74
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/CommitmentTypeIdentifier.java14
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/CommitmentTypeIndication.java83
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/CommitmentTypeQualifier.java108
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/CompleteRevocationRefs.java65
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/CrlIdentifier.java106
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/CrlListID.java66
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/CrlOcspRef.java106
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/CrlValidatedID.java82
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/ESFAttributes.java22
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/OcspIdentifier.java73
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/OcspListID.java72
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/OcspResponsesID.java83
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/OtherHash.java81
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/OtherHashAlgAndValue.java81
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/OtherRevRefs.java87
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/OtherRevVals.java89
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/RevocationValues.java151
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/SPUserNotice.java99
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/SPuri.java45
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/SigPolicyQualifierInfo.java75
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/SigPolicyQualifiers.java77
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/SignaturePolicyId.java103
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/SignaturePolicyIdentifier.java76
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/SignerAttribute.java123
-rw-r--r--core/src/main/java/org/spongycastle/asn1/esf/SignerLocation.java162
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ess/ContentHints.java94
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ess/ContentIdentifier.java63
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ess/ESSCertID.java95
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ess/ESSCertIDv2.java155
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ess/OtherCertID.java137
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ess/OtherSigningCertificate.java109
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ess/SigningCertificate.java109
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ess/SigningCertificateV2.java136
-rw-r--r--core/src/main/java/org/spongycastle/asn1/gnu/GNUObjectIdentifiers.java58
-rw-r--r--core/src/main/java/org/spongycastle/asn1/iana/IANAObjectIdentifiers.java60
-rw-r--r--core/src/main/java/org/spongycastle/asn1/icao/CscaMasterList.java114
-rw-r--r--core/src/main/java/org/spongycastle/asn1/icao/DataGroupHash.java97
-rw-r--r--core/src/main/java/org/spongycastle/asn1/icao/ICAOObjectIdentifiers.java49
-rw-r--r--core/src/main/java/org/spongycastle/asn1/icao/LDSSecurityObject.java159
-rw-r--r--core/src/main/java/org/spongycastle/asn1/icao/LDSVersionInfo.java75
-rw-r--r--core/src/main/java/org/spongycastle/asn1/isismtt/ISISMTTObjectIdentifiers.java210
-rw-r--r--core/src/main/java/org/spongycastle/asn1/isismtt/ocsp/CertHash.java121
-rw-r--r--core/src/main/java/org/spongycastle/asn1/isismtt/ocsp/RequestedCertificate.java181
-rw-r--r--core/src/main/java/org/spongycastle/asn1/isismtt/x509/AdditionalInformationSyntax.java69
-rw-r--r--core/src/main/java/org/spongycastle/asn1/isismtt/x509/AdmissionSyntax.java276
-rw-r--r--core/src/main/java/org/spongycastle/asn1/isismtt/x509/Admissions.java185
-rw-r--r--core/src/main/java/org/spongycastle/asn1/isismtt/x509/DeclarationOfMajority.java163
-rw-r--r--core/src/main/java/org/spongycastle/asn1/isismtt/x509/MonetaryLimit.java128
-rw-r--r--core/src/main/java/org/spongycastle/asn1/isismtt/x509/NamingAuthority.java224
-rw-r--r--core/src/main/java/org/spongycastle/asn1/isismtt/x509/ProcurationSyntax.java237
-rw-r--r--core/src/main/java/org/spongycastle/asn1/isismtt/x509/ProfessionInfo.java407
-rw-r--r--core/src/main/java/org/spongycastle/asn1/isismtt/x509/Restriction.java79
-rw-r--r--core/src/main/java/org/spongycastle/asn1/kisa/KISAObjectIdentifiers.java31
-rw-r--r--core/src/main/java/org/spongycastle/asn1/microsoft/MicrosoftObjectIdentifiers.java28
-rw-r--r--core/src/main/java/org/spongycastle/asn1/misc/CAST5CBCParameters.java78
-rw-r--r--core/src/main/java/org/spongycastle/asn1/misc/IDEACBCPar.java81
-rw-r--r--core/src/main/java/org/spongycastle/asn1/misc/MiscObjectIdentifiers.java59
-rw-r--r--core/src/main/java/org/spongycastle/asn1/misc/NetscapeCertType.java54
-rw-r--r--core/src/main/java/org/spongycastle/asn1/misc/NetscapeRevocationURL.java18
-rw-r--r--core/src/main/java/org/spongycastle/asn1/misc/VerisignCzagExtension.java18
-rw-r--r--core/src/main/java/org/spongycastle/asn1/mozilla/PublicKeyAndChallenge.java63
-rw-r--r--core/src/main/java/org/spongycastle/asn1/nist/NISTNamedCurves.java99
-rw-r--r--core/src/main/java/org/spongycastle/asn1/nist/NISTObjectIdentifiers.java96
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ntt/NTTObjectIdentifiers.java25
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ocsp/BasicOCSPResponse.java112
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ocsp/CertID.java105
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ocsp/CertStatus.java105
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ocsp/CrlID.java110
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ocsp/OCSPObjectIdentifiers.java29
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ocsp/OCSPRequest.java90
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ocsp/OCSPResponse.java90
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ocsp/OCSPResponseStatus.java71
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ocsp/Request.java91
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ocsp/ResponderID.java104
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ocsp/ResponseBytes.java82
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ocsp/ResponseData.java181
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ocsp/RevokedInfo.java92
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ocsp/ServiceLocator.java36
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ocsp/Signature.java111
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ocsp/SingleResponse.java162
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ocsp/TBSRequest.java172
-rw-r--r--core/src/main/java/org/spongycastle/asn1/oiw/ElGamalParameter.java68
-rw-r--r--core/src/main/java/org/spongycastle/asn1/oiw/OIWObjectIdentifiers.java50
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/Attribute.java88
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/AuthenticatedSafe.java74
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/CRLBag.java82
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/CertBag.java66
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/CertificationRequest.java91
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/CertificationRequestInfo.java164
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/ContentInfo.java102
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/DHParameter.java104
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/EncryptedData.java115
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/EncryptedPrivateKeyInfo.java86
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/EncryptionScheme.java56
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/IssuerAndSerialNumber.java85
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/KeyDerivationFunc.java56
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/MacData.java106
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/PBEParameter.java73
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/PBES2Algorithms.java77
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/PBES2Parameters.java77
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/PBKDF2Params.java248
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/PKCS12PBEParams.java69
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/PKCSObjectIdentifiers.java390
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/Pfx.java87
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/PrivateKeyInfo.java164
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/RC2CBCParameter.java93
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/RSAESOAEPparams.java155
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/RSAPrivateKey.java187
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/RSAPrivateKeyStructure.java189
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/RSAPublicKey.java95
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/RSASSAPSSparams.java172
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/SafeBag.java96
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/SignedData.java167
-rw-r--r--core/src/main/java/org/spongycastle/asn1/pkcs/SignerInfo.java178
-rw-r--r--core/src/main/java/org/spongycastle/asn1/sec/ECPrivateKey.java143
-rw-r--r--core/src/main/java/org/spongycastle/asn1/sec/ECPrivateKeyStructure.java128
-rw-r--r--core/src/main/java/org/spongycastle/asn1/sec/SECNamedCurves.java1094
-rw-r--r--core/src/main/java/org/spongycastle/asn1/sec/SECObjectIdentifiers.java87
-rw-r--r--core/src/main/java/org/spongycastle/asn1/smime/SMIMEAttributes.java10
-rw-r--r--core/src/main/java/org/spongycastle/asn1/smime/SMIMECapabilities.java115
-rw-r--r--core/src/main/java/org/spongycastle/asn1/smime/SMIMECapabilitiesAttribute.java16
-rw-r--r--core/src/main/java/org/spongycastle/asn1/smime/SMIMECapability.java103
-rw-r--r--core/src/main/java/org/spongycastle/asn1/smime/SMIMECapabilityVector.java50
-rw-r--r--core/src/main/java/org/spongycastle/asn1/smime/SMIMEEncryptionKeyPreferenceAttribute.java48
-rw-r--r--core/src/main/java/org/spongycastle/asn1/teletrust/TeleTrusTNamedCurves.java398
-rw-r--r--core/src/main/java/org/spongycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java75
-rw-r--r--core/src/main/java/org/spongycastle/asn1/tsp/Accuracy.java173
-rw-r--r--core/src/main/java/org/spongycastle/asn1/tsp/MessageImprint.java78
-rw-r--r--core/src/main/java/org/spongycastle/asn1/tsp/TSTInfo.java233
-rw-r--r--core/src/main/java/org/spongycastle/asn1/tsp/TimeStampReq.java179
-rw-r--r--core/src/main/java/org/spongycastle/asn1/tsp/TimeStampResp.java84
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ua/DSTU4145BinaryField.java119
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ua/DSTU4145ECBinary.java154
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ua/DSTU4145NamedCurves.java106
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ua/DSTU4145Params.java121
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ua/DSTU4145PointEncoder.java154
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ua/DSTU4145PublicKey.java46
-rw-r--r--core/src/main/java/org/spongycastle/asn1/ua/UAObjectIdentifiers.java23
-rw-r--r--core/src/main/java/org/spongycastle/asn1/util/ASN1Dump.java403
-rw-r--r--core/src/main/java/org/spongycastle/asn1/util/DERDump.java41
-rw-r--r--core/src/main/java/org/spongycastle/asn1/util/Dump.java22
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x500/AttributeTypeAndValue.java72
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x500/DirectoryString.java125
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x500/RDN.java119
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x500/X500Name.java326
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x500/X500NameBuilder.java87
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x500/X500NameStyle.java79
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x500/style/AbstractX500NameStyle.java192
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x500/style/BCStrictStyle.java36
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x500/style/BCStyle.java349
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x500/style/IETFUtils.java572
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x500/style/RFC4519Style.java248
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x500/style/X500NameTokenizer.java90
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/AccessDescription.java98
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/AlgorithmIdentifier.java148
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/AttCertIssuer.java91
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/AttCertValidityPeriod.java84
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/Attribute.java93
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/AttributeCertificate.java97
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/AttributeCertificateInfo.java180
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/AuthorityInformationAccess.java104
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/AuthorityKeyIdentifier.java229
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/BasicConstraints.java163
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/CRLDistPoint.java100
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/CRLNumber.java54
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/CRLReason.java151
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/CertPolicyId.java57
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/Certificate.java131
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/CertificateList.java144
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/CertificatePair.java168
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/CertificatePolicies.java124
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/DSAParameter.java92
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/DigestInfo.java86
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/DisplayText.java165
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/DistributionPoint.java158
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/DistributionPointName.java138
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/ExtendedKeyUsage.java192
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/Extension.java321
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/Extensions.java221
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/ExtensionsGenerator.java94
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/GeneralName.java439
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/GeneralNames.java108
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/GeneralNamesBuilder.java39
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/GeneralSubtree.java218
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/Holder.java245
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/IetfAttrSyntax.java189
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/IssuerSerial.java123
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/IssuingDistributionPoint.java274
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/KeyPurposeId.java157
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/KeyUsage.java113
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/NameConstraints.java118
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/NoticeReference.java170
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/ObjectDigestInfo.java190
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/PolicyConstraints.java106
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/PolicyInformation.java87
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/PolicyMappings.java107
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/PolicyQualifierId.java31
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/PolicyQualifierInfo.java115
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/PrivateKeyUsagePeriod.java84
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/RSAPublicKeyStructure.java98
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/ReasonFlags.java85
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/RoleSyntax.java237
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/SubjectDirectoryAttributes.java144
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/SubjectKeyIdentifier.java68
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/SubjectPublicKeyInfo.java156
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/TBSCertList.java309
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/TBSCertificate.java192
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/TBSCertificateStructure.java194
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/Target.java138
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/TargetInformation.java120
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/Targets.java121
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/Time.java169
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/UserNotice.java132
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/V1TBSCertificateGenerator.java144
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/V2AttributeCertificateInfoGenerator.java158
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/V2Form.java157
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/V2TBSCertListGenerator.java281
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/V3TBSCertificateGenerator.java212
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/X509AttributeIdentifiers.java29
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/X509CertificateStructure.java129
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/X509DefaultEntryConverter.java65
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/X509Extension.java249
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/X509Extensions.java477
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/X509ExtensionsGenerator.java94
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/X509Name.java1379
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/X509NameEntryConverter.java114
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/X509NameTokenizer.java91
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/X509ObjectIdentifiers.java81
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/qualified/BiometricData.java122
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/qualified/ETSIQCObjectIdentifiers.java11
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/qualified/Iso4217CurrencyCode.java93
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/qualified/MonetaryValue.java92
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/qualified/QCStatement.java95
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/qualified/RFC3739QCObjectIdentifiers.java11
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/qualified/SemanticsInformation.java131
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/qualified/TypeOfBiometricData.java90
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/sigi/NameOrPseudonym.java189
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/sigi/PersonalData.java213
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x509/sigi/SigIObjectIdentifiers.java60
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x9/DHDomainParameters.java163
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x9/DHPublicKey.java52
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x9/DHValidationParms.java79
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x9/ECNamedCurveTable.java128
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x9/KeySpecificInfo.java68
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x9/OtherInfo.java96
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x9/X962NamedCurves.java642
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x9/X962Parameters.java86
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x9/X9Curve.java163
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x9/X9ECParameters.java200
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x9/X9ECParametersHolder.java18
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x9/X9ECPoint.java48
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x9/X9FieldElement.java64
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x9/X9FieldID.java148
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x9/X9IntegerConverter.java47
-rw-r--r--core/src/main/java/org/spongycastle/asn1/x9/X9ObjectIdentifiers.java207
-rw-r--r--core/src/main/java/org/spongycastle/crypto/AsymmetricBlockCipher.java45
-rw-r--r--core/src/main/java/org/spongycastle/crypto/AsymmetricCipherKeyPair.java61
-rw-r--r--core/src/main/java/org/spongycastle/crypto/AsymmetricCipherKeyPairGenerator.java22
-rw-r--r--core/src/main/java/org/spongycastle/crypto/BasicAgreement.java26
-rw-r--r--core/src/main/java/org/spongycastle/crypto/BlockCipher.java56
-rw-r--r--core/src/main/java/org/spongycastle/crypto/BufferedAsymmetricBlockCipher.java171
-rw-r--r--core/src/main/java/org/spongycastle/crypto/BufferedBlockCipher.java313
-rw-r--r--core/src/main/java/org/spongycastle/crypto/CipherKeyGenerator.java38
-rw-r--r--core/src/main/java/org/spongycastle/crypto/CipherParameters.java8
-rw-r--r--core/src/main/java/org/spongycastle/crypto/Commitment.java42
-rw-r--r--core/src/main/java/org/spongycastle/crypto/Committer.java24
-rw-r--r--core/src/main/java/org/spongycastle/crypto/CryptoException.java48
-rw-r--r--core/src/main/java/org/spongycastle/crypto/DSA.java36
-rw-r--r--core/src/main/java/org/spongycastle/crypto/DataLengthException.java29
-rw-r--r--core/src/main/java/org/spongycastle/crypto/DerivationFunction.java12
-rw-r--r--core/src/main/java/org/spongycastle/crypto/DerivationParameters.java8
-rw-r--r--core/src/main/java/org/spongycastle/crypto/Digest.java51
-rw-r--r--core/src/main/java/org/spongycastle/crypto/DigestDerivationFunction.java13
-rw-r--r--core/src/main/java/org/spongycastle/crypto/EphemeralKeyPair.java23
-rw-r--r--core/src/main/java/org/spongycastle/crypto/ExtendedDigest.java13
-rw-r--r--core/src/main/java/org/spongycastle/crypto/InvalidCipherTextException.java40
-rwxr-xr-xcore/src/main/java/org/spongycastle/crypto/KeyEncapsulation.java22
-rw-r--r--core/src/main/java/org/spongycastle/crypto/KeyEncoder.java8
-rw-r--r--core/src/main/java/org/spongycastle/crypto/KeyGenerationParameters.java48
-rw-r--r--core/src/main/java/org/spongycastle/crypto/KeyParser.java12
-rw-r--r--core/src/main/java/org/spongycastle/crypto/Mac.java71
-rw-r--r--core/src/main/java/org/spongycastle/crypto/MacDerivationFunction.java13
-rw-r--r--core/src/main/java/org/spongycastle/crypto/MaxBytesExceededException.java27
-rw-r--r--core/src/main/java/org/spongycastle/crypto/OutputLengthException.java10
-rw-r--r--core/src/main/java/org/spongycastle/crypto/PBEParametersGenerator.java171
-rw-r--r--core/src/main/java/org/spongycastle/crypto/RuntimeCryptoException.java26
-rw-r--r--core/src/main/java/org/spongycastle/crypto/Signer.java43
-rw-r--r--core/src/main/java/org/spongycastle/crypto/SignerWithRecovery.java34
-rw-r--r--core/src/main/java/org/spongycastle/crypto/SkippingCipher.java31
-rw-r--r--core/src/main/java/org/spongycastle/crypto/SkippingStreamCipher.java9
-rw-r--r--core/src/main/java/org/spongycastle/crypto/StreamBlockCipher.java58
-rw-r--r--core/src/main/java/org/spongycastle/crypto/StreamCipher.java54
-rw-r--r--core/src/main/java/org/spongycastle/crypto/Wrapper.java18
-rw-r--r--core/src/main/java/org/spongycastle/crypto/agreement/DHAgreement.java94
-rw-r--r--core/src/main/java/org/spongycastle/crypto/agreement/DHBasicAgreement.java71
-rw-r--r--core/src/main/java/org/spongycastle/crypto/agreement/DHStandardGroups.java206
-rw-r--r--core/src/main/java/org/spongycastle/crypto/agreement/ECDHBasicAgreement.java54
-rw-r--r--core/src/main/java/org/spongycastle/crypto/agreement/ECDHCBasicAgreement.java64
-rw-r--r--core/src/main/java/org/spongycastle/crypto/agreement/ECMQVBasicAgreement.java91
-rw-r--r--core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEParticipant.java546
-rw-r--r--core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java115
-rw-r--r--core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroups.java111
-rw-r--r--core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound1Payload.java96
-rw-r--r--core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound2Payload.java68
-rw-r--r--core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound3Payload.java49
-rw-r--r--core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEUtil.java495
-rw-r--r--core/src/main/java/org/spongycastle/crypto/agreement/kdf/DHKDFParameters.java53
-rw-r--r--core/src/main/java/org/spongycastle/crypto/agreement/kdf/DHKEKGenerator.java131
-rw-r--r--core/src/main/java/org/spongycastle/crypto/agreement/kdf/ECDHKEKGenerator.java74
-rw-r--r--core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Client.java150
-rw-r--r--core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Server.java148
-rw-r--r--core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Util.java154
-rw-r--r--core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6VerifierGenerator.java47
-rw-r--r--core/src/main/java/org/spongycastle/crypto/commitments/GeneralHashCommitter.java93
-rw-r--r--core/src/main/java/org/spongycastle/crypto/commitments/HashCommitter.java89
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/EncodableDigest.java17
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/GOST3411Digest.java362
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/GeneralDigest.java155
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/LongDigest.java409
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/MD2Digest.java258
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/MD4Digest.java291
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/MD5Digest.java323
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/NonMemoableDigest.java64
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/NullDigest.java48
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/RIPEMD128Digest.java482
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/RIPEMD160Digest.java443
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/RIPEMD256Digest.java497
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/RIPEMD320Digest.java481
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/SHA1Digest.java348
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/SHA224Digest.java356
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/SHA256Digest.java360
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/SHA384Digest.java111
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/SHA3Digest.java547
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/SHA512Digest.java114
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/SHA512tDigest.java227
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/SM3Digest.java333
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/ShortenedDigest.java80
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/SkeinDigest.java115
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/SkeinEngine.java817
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/TigerDigest.java879
-rw-r--r--core/src/main/java/org/spongycastle/crypto/digests/WhirlpoolDigest.java409
-rw-r--r--core/src/main/java/org/spongycastle/crypto/ec/CustomNamedCurves.java320
-rw-r--r--core/src/main/java/org/spongycastle/crypto/ec/ECDecryptor.java11
-rw-r--r--core/src/main/java/org/spongycastle/crypto/ec/ECElGamalDecryptor.java48
-rw-r--r--core/src/main/java/org/spongycastle/crypto/ec/ECElGamalEncryptor.java86
-rw-r--r--core/src/main/java/org/spongycastle/crypto/ec/ECEncryptor.java11
-rw-r--r--core/src/main/java/org/spongycastle/crypto/ec/ECFixedTransform.java88
-rw-r--r--core/src/main/java/org/spongycastle/crypto/ec/ECNewPublicKeyTransform.java88
-rw-r--r--core/src/main/java/org/spongycastle/crypto/ec/ECNewRandomnessTransform.java105
-rw-r--r--core/src/main/java/org/spongycastle/crypto/ec/ECPair.java40
-rw-r--r--core/src/main/java/org/spongycastle/crypto/ec/ECPairFactorTransform.java14
-rw-r--r--core/src/main/java/org/spongycastle/crypto/ec/ECPairTransform.java10
-rw-r--r--core/src/main/java/org/spongycastle/crypto/ec/ECUtil.java21
-rw-r--r--core/src/main/java/org/spongycastle/crypto/encodings/ISO9796d1Encoding.java287
-rw-r--r--core/src/main/java/org/spongycastle/crypto/encodings/OAEPEncoding.java357
-rw-r--r--core/src/main/java/org/spongycastle/crypto/encodings/PKCS1Encoding.java418
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/AESEngine.java537
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/AESFastEngine.java928
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/AESLightEngine.java434
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/AESWrapEngine.java16
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/AESWrapPadEngine.java10
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/BlowfishEngine.java577
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/CAST5Engine.java831
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/CAST6Engine.java296
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/CamelliaEngine.java684
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/CamelliaLightEngine.java592
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/CamelliaWrapEngine.java15
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/ChaChaEngine.java204
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/CramerShoupCiphertext.java179
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/CramerShoupCoreEngine.java313
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/DESEngine.java495
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/DESedeEngine.java127
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/DESedeWrapEngine.java350
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/ElGamalEngine.java217
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/GOST28147Engine.java372
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/Grain128Engine.java304
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/Grainv1Engine.java290
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/HC128Engine.java259
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/HC256Engine.java246
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/IDEAEngine.java357
-rwxr-xr-xcore/src/main/java/org/spongycastle/crypto/engines/IESEngine.java438
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/ISAACEngine.java221
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/NaccacheSternEngine.java437
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/NoekeonEngine.java263
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/NullEngine.java96
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/RC2Engine.java317
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/RC2WrapEngine.java385
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/RC4Engine.java146
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/RC532Engine.java287
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/RC564Engine.java288
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/RC6Engine.java363
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/RFC3211WrapEngine.java175
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/RFC3394WrapEngine.java177
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/RFC5649WrapEngine.java294
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/RSABlindedEngine.java126
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/RSABlindingEngine.java137
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/RSACoreEngine.java203
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/RSAEngine.java78
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/RijndaelEngine.java725
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/SEEDEngine.java346
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/SEEDWrapEngine.java15
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/Salsa20Engine.java474
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/SerpentEngine.java783
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/Shacal2Engine.java201
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/SkipjackEngine.java260
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/TEAEngine.java184
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/ThreefishEngine.java1494
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/TwofishEngine.java680
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/VMPCEngine.java142
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/VMPCKSA3Engine.java45
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/XSalsa20Engine.java65
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/XTEAEngine.java188
-rw-r--r--core/src/main/java/org/spongycastle/crypto/examples/DESExample.java421
-rw-r--r--core/src/main/java/org/spongycastle/crypto/examples/JPAKEExample.java214
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/BaseKDFBytesGenerator.java143
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/CramerShoupKeyPairGenerator.java63
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/CramerShoupParametersGenerator.java123
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/DESKeyGenerator.java48
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/DESedeKeyGenerator.java56
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/DHBasicKeyPairGenerator.java42
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/DHKeyGeneratorHelper.java67
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/DHKeyPairGenerator.java42
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/DHParametersGenerator.java52
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/DHParametersHelper.java93
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/DSAKeyPairGenerator.java69
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/DSAParametersGenerator.java387
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/DSTU4145KeyPairGenerator.java21
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/ECKeyPairGenerator.java84
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/ElGamalKeyPairGenerator.java44
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/ElGamalParametersGenerator.java43
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/EphemeralKeyPairGenerator.java26
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/GOST3410KeyPairGenerator.java74
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/GOST3410ParametersGenerator.java541
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/HKDFBytesGenerator.java161
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/KDF1BytesGenerator.java23
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/KDF2BytesGenerator.java24
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/KDFCounterBytesGenerator.java180
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/KDFDoublePipelineIterationBytesGenerator.java181
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/KDFFeedbackBytesGenerator.java175
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/MGF1BytesGenerator.java114
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/NaccacheSternKeyPairGenerator.java365
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/OpenSSLPBEParametersGenerator.java131
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/PKCS12ParametersGenerator.java220
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/PKCS5S1ParametersGenerator.java119
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/PKCS5S2ParametersGenerator.java153
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/Poly1305KeyGenerator.java117
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/RSABlindingFactorGenerator.java77
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/RSAKeyPairGenerator.java153
-rw-r--r--core/src/main/java/org/spongycastle/crypto/generators/SCrypt.java198
-rw-r--r--core/src/main/java/org/spongycastle/crypto/io/CipherIOException.java26
-rw-r--r--core/src/main/java/org/spongycastle/crypto/io/CipherInputStream.java477
-rw-r--r--core/src/main/java/org/spongycastle/crypto/io/CipherOutputStream.java276
-rw-r--r--core/src/main/java/org/spongycastle/crypto/io/DigestInputStream.java52
-rw-r--r--core/src/main/java/org/spongycastle/crypto/io/DigestOutputStream.java42
-rw-r--r--core/src/main/java/org/spongycastle/crypto/io/InvalidCipherTextIOException.java19
-rw-r--r--core/src/main/java/org/spongycastle/crypto/io/MacInputStream.java52
-rw-r--r--core/src/main/java/org/spongycastle/crypto/io/MacOutputStream.java42
-rw-r--r--core/src/main/java/org/spongycastle/crypto/io/SignerInputStream.java52
-rw-r--r--core/src/main/java/org/spongycastle/crypto/io/SignerOutputStream.java38
-rwxr-xr-xcore/src/main/java/org/spongycastle/crypto/kems/ECIESKeyEncapsulation.java244
-rwxr-xr-xcore/src/main/java/org/spongycastle/crypto/kems/RSAKeyEncapsulation.java155
-rw-r--r--core/src/main/java/org/spongycastle/crypto/macs/BlockCipherMac.java174
-rw-r--r--core/src/main/java/org/spongycastle/crypto/macs/CBCBlockCipherMac.java229
-rw-r--r--core/src/main/java/org/spongycastle/crypto/macs/CFBBlockCipherMac.java388
-rw-r--r--core/src/main/java/org/spongycastle/crypto/macs/CMac.java261
-rw-r--r--core/src/main/java/org/spongycastle/crypto/macs/CMacWithIV.java27
-rw-r--r--core/src/main/java/org/spongycastle/crypto/macs/GMac.java115
-rw-r--r--core/src/main/java/org/spongycastle/crypto/macs/GOST28147Mac.java298
-rw-r--r--core/src/main/java/org/spongycastle/crypto/macs/HMac.java231
-rw-r--r--core/src/main/java/org/spongycastle/crypto/macs/ISO9797Alg3Mac.java305
-rw-r--r--core/src/main/java/org/spongycastle/crypto/macs/OldHMac.java138
-rw-r--r--core/src/main/java/org/spongycastle/crypto/macs/Poly1305.java306
-rw-r--r--core/src/main/java/org/spongycastle/crypto/macs/SipHash.java216
-rw-r--r--core/src/main/java/org/spongycastle/crypto/macs/SkeinMac.java118
-rw-r--r--core/src/main/java/org/spongycastle/crypto/macs/VMPCMac.java186
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/AEADBlockCipher.java146
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/CBCBlockCipher.java253
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/CCMBlockCipher.java457
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/CFBBlockCipher.java269
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/CTSBlockCipher.java287
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/EAXBlockCipher.java387
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/GCFBBlockCipher.java120
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/GCMBlockCipher.java596
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/GOFBBlockCipher.java228
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/OCBBlockCipher.java598
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/OFBBlockCipher.java178
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/OldCTSBlockCipher.java269
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/OpenPGPCFBBlockCipher.java312
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/PGPCFBBlockCipher.java455
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/PaddedBlockCipher.java253
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/SICBlockCipher.java225
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/gcm/BasicGCMExponentiator.java36
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/gcm/BasicGCMMultiplier.java18
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/gcm/GCMExponentiator.java7
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/gcm/GCMMultiplier.java7
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/gcm/GCMUtil.java457
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java58
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/gcm/Tables64kGCMMultiplier.java73
-rw-r--r--core/src/main/java/org/spongycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java90
-rw-r--r--core/src/main/java/org/spongycastle/crypto/paddings/BlockCipherPadding.java48
-rw-r--r--core/src/main/java/org/spongycastle/crypto/paddings/ISO10126d2Padding.java79
-rw-r--r--core/src/main/java/org/spongycastle/crypto/paddings/ISO7816d4Padding.java77
-rw-r--r--core/src/main/java/org/spongycastle/crypto/paddings/PKCS7Padding.java76
-rw-r--r--core/src/main/java/org/spongycastle/crypto/paddings/PaddedBufferedBlockCipher.java299
-rw-r--r--core/src/main/java/org/spongycastle/crypto/paddings/TBCPadding.java89
-rw-r--r--core/src/main/java/org/spongycastle/crypto/paddings/X923Padding.java80
-rw-r--r--core/src/main/java/org/spongycastle/crypto/paddings/ZeroBytePadding.java73
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/AEADParameters.java60
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/AsymmetricKeyParameter.java20
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/CCMParameters.java21
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/CramerShoupKeyGenerationParameters.java24
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/CramerShoupKeyParameters.java40
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/CramerShoupParameters.java53
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/CramerShoupPrivateKeyParameters.java61
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/CramerShoupPublicKeyParameters.java42
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/DESParameters.java107
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/DESedeParameters.java57
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/DHKeyGenerationParameters.java30
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/DHKeyParameters.java54
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/DHParameters.java189
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/DHPrivateKeyParameters.java41
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/DHPublicKeyParameters.java41
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/DHValidationParameters.java50
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/DSAKeyGenerationParameters.java25
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/DSAKeyParameters.java21
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/DSAParameterGenerationParameters.java80
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/DSAParameters.java74
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/DSAPrivateKeyParameters.java23
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/DSAPublicKeyParameters.java23
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/DSAValidationParameters.java65
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/ECDomainParameters.java74
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/ECKeyGenerationParameters.java25
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/ECKeyParameters.java21
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/ECNamedDomainParameters.java35
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/ECPrivateKeyParameters.java22
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/ECPublicKeyParameters.java22
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/ElGamalKeyGenerationParameters.java30
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/ElGamalKeyParameters.java47
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/ElGamalParameters.java69
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/ElGamalPrivateKeyParameters.java46
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/ElGamalPublicKeyParameters.java41
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/GOST3410KeyGenerationParameters.java25
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/GOST3410KeyParameters.java21
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/GOST3410Parameters.java74
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/GOST3410PrivateKeyParameters.java23
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/GOST3410PublicKeyParameters.java23
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/GOST3410ValidationParameters.java84
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/HKDFParameters.java123
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/IESParameters.java44
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/IESWithCipherParameters.java30
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/ISO18033KDFParameters.java23
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/KDFCounterParameters.java120
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/KDFDoublePipelineIterationParameters.java80
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/KDFFeedbackParameters.java96
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/KDFParameters.java31
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/KeyParameter.java30
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/MGFParameters.java32
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/MQVPrivateParameters.java43
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/MQVPublicParameters.java28
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/NaccacheSternKeyGenerationParameters.java97
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/NaccacheSternKeyParameters.java53
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/NaccacheSternPrivateKeyParameters.java50
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/ParametersWithIV.java39
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/ParametersWithRandom.java36
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/ParametersWithSBox.java28
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/ParametersWithSalt.java42
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/RC2Parameters.java36
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/RC5Parameters.java35
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/RSABlindingParameters.java35
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/RSAKeyGenerationParameters.java48
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/RSAKeyParameters.java31
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/RSAPrivateCrtKeyParameters.java67
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/SkeinParameters.java329
-rw-r--r--core/src/main/java/org/spongycastle/crypto/params/TweakableBlockCipherParameters.java40
-rw-r--r--core/src/main/java/org/spongycastle/crypto/parsers/DHIESPublicKeyParser.java31
-rw-r--r--core/src/main/java/org/spongycastle/crypto/parsers/ECIESPublicKeyParser.java53
-rw-r--r--core/src/main/java/org/spongycastle/crypto/prng/BasicEntropySourceProvider.java53
-rw-r--r--core/src/main/java/org/spongycastle/crypto/prng/DRBGProvider.java8
-rw-r--r--core/src/main/java/org/spongycastle/crypto/prng/DigestRandomGenerator.java123
-rw-r--r--core/src/main/java/org/spongycastle/crypto/prng/EntropySource.java25
-rw-r--r--core/src/main/java/org/spongycastle/crypto/prng/EntropySourceProvider.java6
-rw-r--r--core/src/main/java/org/spongycastle/crypto/prng/FixedSecureRandom.java147
-rw-r--r--core/src/main/java/org/spongycastle/crypto/prng/RandomGenerator.java38
-rw-r--r--core/src/main/java/org/spongycastle/crypto/prng/ReversedWindowGenerator.java111
-rw-r--r--core/src/main/java/org/spongycastle/crypto/prng/SP800SecureRandom.java74
-rw-r--r--core/src/main/java/org/spongycastle/crypto/prng/SP800SecureRandomBuilder.java290
-rw-r--r--core/src/main/java/org/spongycastle/crypto/prng/ThreadedSeedGenerator.java95
-rw-r--r--core/src/main/java/org/spongycastle/crypto/prng/VMPCRandomGenerator.java127
-rw-r--r--core/src/main/java/org/spongycastle/crypto/prng/drbg/CTRSP800DRBG.java478
-rw-r--r--core/src/main/java/org/spongycastle/crypto/prng/drbg/DualECPoints.java82
-rw-r--r--core/src/main/java/org/spongycastle/crypto/prng/drbg/DualECSP800DRBG.java320
-rw-r--r--core/src/main/java/org/spongycastle/crypto/prng/drbg/HMacSP800DRBG.java181
-rw-r--r--core/src/main/java/org/spongycastle/crypto/prng/drbg/HashSP800DRBG.java284
-rw-r--r--core/src/main/java/org/spongycastle/crypto/prng/drbg/SP80090DRBG.java32
-rw-r--r--core/src/main/java/org/spongycastle/crypto/prng/drbg/Utils.java103
-rw-r--r--core/src/main/java/org/spongycastle/crypto/signers/DSADigestSigner.java163
-rw-r--r--core/src/main/java/org/spongycastle/crypto/signers/DSAKCalculator.java41
-rw-r--r--core/src/main/java/org/spongycastle/crypto/signers/DSASigner.java168
-rw-r--r--core/src/main/java/org/spongycastle/crypto/signers/DSTU4145Signer.java170
-rw-r--r--core/src/main/java/org/spongycastle/crypto/signers/ECDSASigner.java197
-rw-r--r--core/src/main/java/org/spongycastle/crypto/signers/ECGOST3410Signer.java160
-rw-r--r--core/src/main/java/org/spongycastle/crypto/signers/ECNRSigner.java188
-rw-r--r--core/src/main/java/org/spongycastle/crypto/signers/GOST3410Signer.java131
-rw-r--r--core/src/main/java/org/spongycastle/crypto/signers/GenericSigner.java136
-rw-r--r--core/src/main/java/org/spongycastle/crypto/signers/HMacDSAKCalculator.java152
-rw-r--r--core/src/main/java/org/spongycastle/crypto/signers/ISO9796d2PSSSigner.java668
-rw-r--r--core/src/main/java/org/spongycastle/crypto/signers/ISO9796d2Signer.java618
-rw-r--r--core/src/main/java/org/spongycastle/crypto/signers/PSSSigner.java348
-rw-r--r--core/src/main/java/org/spongycastle/crypto/signers/RSADigestSigner.java240
-rw-r--r--core/src/main/java/org/spongycastle/crypto/signers/RandomDSAKCalculator.java43
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsAgreementCredentials.java7
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsCipherFactory.java13
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsClient.java235
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsContext.java133
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsCredentials.java6
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsEncryptionCredentials.java7
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsKeyExchange.java166
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsPeer.java42
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsServer.java335
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsSigner.java38
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsSignerCredentials.java11
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/AlertDescription.java216
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/AlertLevel.java10
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/AlwaysValidVerifyer.java23
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/BulkCipherAlgorithm.java23
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/ByteQueue.java153
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/CertChainType.java15
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/Certificate.java148
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/CertificateRequest.java158
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/CertificateStatus.java105
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/CertificateStatusRequest.java98
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/CertificateStatusType.java9
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/CertificateURL.java133
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/CertificateVerifyer.java16
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/Chacha20Poly1305.java156
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/ChangeCipherSpec.java6
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/CipherSuite.java351
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/CipherType.java18
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/ClientAuthenticationType.java11
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/ClientCertificateType.java22
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/CombinedHash.java135
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/CompressionMethod.java24
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/ConnectionEnd.java13
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/ContentType.java13
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/DTLSClientProtocol.java831
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/DTLSEpoch.java52
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/DTLSHandshakeRetransmit.java9
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/DTLSProtocol.java78
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/DTLSReassembler.java133
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/DTLSRecordLayer.java516
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/DTLSReliableHandshake.java453
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/DTLSReplayWindow.java90
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/DTLSServerProtocol.java667
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/DTLSTransport.java80
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/DatagramTransport.java21
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsAgreementCredentials.java78
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsCipherFactory.java237
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsClient.java453
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsEncryptionCredentials.java62
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsServer.java550
-rwxr-xr-xcore/src/main/java/org/spongycastle/crypto/tls/DefaultTlsSignerCredentials.java104
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/DeferredHash.java207
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/DigestAlgorithm.java23
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/DigestInputBuffer.java13
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/DigitallySigned.java72
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/ECBasisType.java15
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/ECCurveType.java28
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/ECPointFormat.java15
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/EncryptionAlgorithm.java67
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/ExporterLabel.java31
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/ExtensionType.java60
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/HandshakeType.java39
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/HashAlgorithm.java15
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/HeartbeatExtension.java56
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/HeartbeatMessage.java111
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/HeartbeatMessageType.java15
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/HeartbeatMode.java15
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/KeyExchangeAlgorithm.java52
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/LegacyTlsAuthentication.java28
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/LegacyTlsClient.java33
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/MACAlgorithm.java23
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/MaxFragmentLength.java17
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/NameType.java9
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/NamedCurve.java71
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/NewSessionTicket.java55
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/OCSPStatusRequest.java131
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/PRFAlgorithm.java22
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/PSKTlsClient.java256
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/ProtocolVersion.java158
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/RecordStream.java365
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/SRPTlsClient.java121
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/SRTPProtectionProfile.java12
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/SSL3Mac.java114
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/SecurityParameters.java91
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/ServerDHParams.java63
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/ServerName.java112
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/ServerNameList.java86
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/ServerOnlyTlsAuthentication.java10
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/SessionParameters.java142
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/SignatureAlgorithm.java12
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/SignatureAndHashAlgorithm.java96
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/SignerInputBuffer.java13
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/SupplementalDataEntry.java23
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/SupplementalDataType.java12
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsAEADCipher.java193
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsAgreementCredentials.java12
-rwxr-xr-xcore/src/main/java/org/spongycastle/crypto/tls/TlsAuthentication.java26
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsBlockCipher.java386
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsCipher.java14
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsCipherFactory.java12
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsClient.java79
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsClientContext.java6
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsClientContextImpl.java18
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsClientProtocol.java917
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsCompression.java10
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsContext.java45
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsCredentials.java6
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsDHEKeyExchange.java115
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsDHKeyExchange.java208
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsDHUtils.java105
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsDSASigner.java92
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsDSSSigner.java26
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsECCUtils.java690
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsECDHEKeyExchange.java221
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsECDHKeyExchange.java219
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsECDSASigner.java26
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsEncryptionCredentials.java9
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsExtensionsUtils.java267
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsFatalAlert.java21
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsHandshakeHash.java21
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsInputStream.java47
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsKeyExchange.java54
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsMac.java172
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsNullCipher.java123
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsNullCompression.java17
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsOutputStream.java44
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsPSKIdentity.java12
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsPSKKeyExchange.java285
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsPeer.java46
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsProtocol.java1184
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsProtocolHandler.java22
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsRSAKeyExchange.java191
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsRSASigner.java112
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsRSAUtils.java140
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsSRPKeyExchange.java205
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsSRPUtils.java48
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsSRTPUtils.java74
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsServer.java90
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsServerContext.java6
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsServerContextImpl.java18
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsServerProtocol.java778
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsSession.java12
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsSessionImpl.java48
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsSigner.java34
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsSignerCredentials.java12
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsStreamCipher.java178
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/TlsUtils.java1780
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/UDPTransport.java75
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/URLAndHash.java104
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/UseSRTPData.java52
-rw-r--r--core/src/main/java/org/spongycastle/crypto/tls/UserMappingType.java12
-rw-r--r--core/src/main/java/org/spongycastle/crypto/util/Pack.java204
-rw-r--r--core/src/main/java/org/spongycastle/crypto/util/PrivateKeyFactory.java159
-rw-r--r--core/src/main/java/org/spongycastle/crypto/util/PrivateKeyInfoFactory.java86
-rw-r--r--core/src/main/java/org/spongycastle/crypto/util/PublicKeyFactory.java195
-rw-r--r--core/src/main/java/org/spongycastle/crypto/util/SubjectPublicKeyInfoFactory.java85
-rw-r--r--core/src/main/java/org/spongycastle/i18n/ErrorBundle.java120
-rw-r--r--core/src/main/java/org/spongycastle/i18n/LocaleString.java30
-rw-r--r--core/src/main/java/org/spongycastle/i18n/LocalizedException.java49
-rw-r--r--core/src/main/java/org/spongycastle/i18n/LocalizedMessage.java476
-rw-r--r--core/src/main/java/org/spongycastle/i18n/MessageBundle.java92
-rw-r--r--core/src/main/java/org/spongycastle/i18n/MissingEntryException.java73
-rw-r--r--core/src/main/java/org/spongycastle/i18n/TextBundle.java92
-rw-r--r--core/src/main/java/org/spongycastle/i18n/filter/Filter.java21
-rw-r--r--core/src/main/java/org/spongycastle/i18n/filter/HTMLFilter.java68
-rw-r--r--core/src/main/java/org/spongycastle/i18n/filter/SQLFilter.java69
-rw-r--r--core/src/main/java/org/spongycastle/i18n/filter/TrustedInput.java23
-rw-r--r--core/src/main/java/org/spongycastle/i18n/filter/UntrustedInput.java44
-rw-r--r--core/src/main/java/org/spongycastle/i18n/filter/UntrustedUrlInput.java14
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/AbstractECMultiplier.java26
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/DoubleAddMultiplier.java24
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/ECAlgorithms.java469
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/ECConstants.java12
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/ECCurve.java1113
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/ECFieldElement.java868
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/ECMultiplier.java19
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/ECPoint.java2122
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/ECPointMap.java6
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/FixedPointCombMultiplier.java57
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/FixedPointPreCompInfo.java40
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/FixedPointUtil.java71
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/GLVMultiplier.java42
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/LongArray.java2195
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/MixedNafR2LMultiplier.java77
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/MontgomeryLadderMultiplier.java25
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/NafL2RMultiplier.java30
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/NafR2LMultiplier.java31
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/PreCompInfo.java10
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/ReferenceMultiplier.java11
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/ScaleXPointMap.java16
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/ScaleYPointMap.java16
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/SimpleBigDecimal.java247
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/Tnaf.java823
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/WNafL2RMultiplier.java96
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/WNafPreCompInfo.java56
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/WNafUtil.java485
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/WTauNafMultiplier.java114
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/WTauNafPreCompInfo.java26
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/ZSignedDigitL2RMultiplier.java29
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/ZSignedDigitR2LMultiplier.java30
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/ZTauElement.java37
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519.java80
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519Field.java254
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519FieldElement.java234
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519Point.java348
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1Curve.java79
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1Field.java177
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1FieldElement.java213
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1Point.java298
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1Curve.java80
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1Field.java286
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1FieldElement.java190
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1Point.java310
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1Curve.java78
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1Field.java178
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1FieldElement.java243
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1Point.java298
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1Curve.java80
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1Field.java298
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1FieldElement.java273
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1Point.java308
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1Curve.java78
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1Field.java179
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1FieldElement.java215
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1Point.java298
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1Curve.java80
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1Field.java312
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1FieldElement.java189
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1Point.java308
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1Curve.java80
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1Field.java295
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1FieldElement.java211
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1Point.java309
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1Curve.java80
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1Field.java156
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1FieldElement.java169
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1Point.java333
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/endo/ECEndomorphism.java10
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/endo/GLVEndomorphism.java8
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/endo/GLVTypeBEndomorphism.java58
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/endo/GLVTypeBParameters.java59
-rw-r--r--core/src/main/java/org/spongycastle/math/ec/tools/DiscoverEndomorphisms.java373
-rw-r--r--core/src/main/java/org/spongycastle/math/field/ExtensionField.java8
-rw-r--r--core/src/main/java/org/spongycastle/math/field/FiniteField.java10
-rw-r--r--core/src/main/java/org/spongycastle/math/field/FiniteFields.java53
-rw-r--r--core/src/main/java/org/spongycastle/math/field/GF2Polynomial.java42
-rw-r--r--core/src/main/java/org/spongycastle/math/field/GenericPolynomialExtensionField.java62
-rw-r--r--core/src/main/java/org/spongycastle/math/field/Polynomial.java12
-rw-r--r--core/src/main/java/org/spongycastle/math/field/PolynomialExtensionField.java6
-rw-r--r--core/src/main/java/org/spongycastle/math/field/PrimeField.java42
-rw-r--r--core/src/main/java/org/spongycastle/math/raw/Mod.java199
-rw-r--r--core/src/main/java/org/spongycastle/math/raw/Mont256.java152
-rw-r--r--core/src/main/java/org/spongycastle/math/raw/Nat.java1038
-rw-r--r--core/src/main/java/org/spongycastle/math/raw/Nat192.java968
-rw-r--r--core/src/main/java/org/spongycastle/math/raw/Nat224.java1182
-rw-r--r--core/src/main/java/org/spongycastle/math/raw/Nat256.java1306
-rw-r--r--core/src/main/java/org/spongycastle/math/raw/Nat384.java43
-rw-r--r--core/src/main/java/org/spongycastle/math/raw/Nat512.java43
-rw-r--r--core/src/main/java/org/spongycastle/pqc/asn1/GMSSPrivateKey.java1312
-rw-r--r--core/src/main/java/org/spongycastle/pqc/asn1/GMSSPublicKey.java74
-rw-r--r--core/src/main/java/org/spongycastle/pqc/asn1/McElieceCCA2PrivateKey.java173
-rw-r--r--core/src/main/java/org/spongycastle/pqc/asn1/McElieceCCA2PublicKey.java96
-rw-r--r--core/src/main/java/org/spongycastle/pqc/asn1/McEliecePrivateKey.java197
-rw-r--r--core/src/main/java/org/spongycastle/pqc/asn1/McEliecePublicKey.java97
-rw-r--r--core/src/main/java/org/spongycastle/pqc/asn1/PQCObjectIdentifiers.java46
-rw-r--r--core/src/main/java/org/spongycastle/pqc/asn1/ParSet.java140
-rw-r--r--core/src/main/java/org/spongycastle/pqc/asn1/RainbowPrivateKey.java349
-rw-r--r--core/src/main/java/org/spongycastle/pqc/asn1/RainbowPublicKey.java174
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/DigestingMessageSigner.java117
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/MessageEncryptor.java30
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/MessageSigner.java32
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSDigestProvider.java8
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSKeyGenerationParameters.java26
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSKeyPairGenerator.java476
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSKeyParameters.java22
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSLeaf.java376
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSParameters.java155
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSPrivateKeyParameters.java1041
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSPublicKeyParameters.java33
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSRootCalc.java596
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSRootSig.java666
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSSigner.java403
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSUtils.java145
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/gmss/Treehash.java525
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/GMSSRandom.java78
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/GMSSUtil.java151
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/WinternitzOTSVerify.java344
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/WinternitzOTSignature.java404
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/mceliece/Conversions.java236
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2KeyGenerationParameters.java25
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2KeyPairGenerator.java119
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2KeyParameters.java25
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2Parameters.java51
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2Primitives.java86
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2PrivateKeyParameters.java172
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2PublicKeyParameters.java97
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceFujisakiCipher.java218
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceFujisakiDigestCipher.java128
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceKeyGenerationParameters.java25
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceKeyPairGenerator.java151
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceKeyParameters.java25
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceKobaraImaiCipher.java319
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceKobaraImaiDigestCipher.java128
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePKCSCipher.java224
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePKCSDigestCipher.java128
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceParameters.java181
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePointchevalCipher.java241
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePointchevalDigestCipher.java128
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePrivateKeyParameters.java197
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePublicKeyParameters.java96
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/ntru/IndexGenerator.java239
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionKeyGenerationParameters.java463
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionKeyPairGenerator.java113
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionKeyParameters.java20
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionParameters.java410
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionPrivateKeyParameters.java199
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionPublicKeyParameters.java131
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEngine.java495
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUParameters.java7
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigner.java263
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSignerPrng.java64
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningKeyGenerationParameters.java407
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningKeyPairGenerator.java357
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningParameters.java269
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningPrivateKeyParameters.java385
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningPublicKeyParameters.java132
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/rainbow/Layer.java322
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowKeyGenerationParameters.java26
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowKeyPairGenerator.java413
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowKeyParameters.java25
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowParameters.java111
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowPrivateKeyParameters.java117
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowPublicKeyParameters.java53
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowSigner.java301
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/rainbow/util/ComputeInField.java490
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/rainbow/util/GF2Field.java139
-rw-r--r--core/src/main/java/org/spongycastle/pqc/crypto/rainbow/util/RainbowUtil.java230
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/BigEndianConversions.java306
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/BigIntUtils.java138
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/ByteUtils.java414
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/CharUtils.java98
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2Matrix.java1323
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2Polynomial.java2039
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2Vector.java539
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mField.java365
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mMatrix.java377
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mVector.java256
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nElement.java186
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nField.java292
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nONBElement.java1154
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nONBField.java546
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nPolynomial.java587
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nPolynomialElement.java1021
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nPolynomialField.java553
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GFElement.java158
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GoppaCode.java310
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/IntUtils.java202
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/IntegerFunctions.java1423
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/LittleEndianConversions.java230
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/Matrix.java131
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/Permutation.java247
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialGF2mSmallM.java1124
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialRingGF2.java278
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialRingGF2m.java175
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/RandUtils.java25
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/linearalgebra/Vector.java69
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/ntru/euclid/BigIntEuclidean.java54
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/ntru/euclid/IntEuclidean.java51
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/BigDecimalPolynomial.java258
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/BigIntPolynomial.java394
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/Constants.java12
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/DenseTernaryPolynomial.java142
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/IntegerPolynomial.java1358
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/LongPolynomial2.java255
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/LongPolynomial5.java149
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/ModularResultant.java46
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/Polynomial.java42
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/ProductFormPolynomial.java153
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/Resultant.java28
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/SparseTernaryPolynomial.java320
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/TernaryPolynomial.java25
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/ntru/util/ArrayEncoder.java292
-rw-r--r--core/src/main/java/org/spongycastle/pqc/math/ntru/util/Util.java158
-rw-r--r--core/src/main/java/org/spongycastle/util/Arrays.java971
-rw-r--r--core/src/main/java/org/spongycastle/util/BigIntegers.java121
-rw-r--r--core/src/main/java/org/spongycastle/util/CollectionStore.java57
-rw-r--r--core/src/main/java/org/spongycastle/util/IPAddress.java188
-rw-r--r--core/src/main/java/org/spongycastle/util/Integers.java19
-rw-r--r--core/src/main/java/org/spongycastle/util/Memoable.java23
-rw-r--r--core/src/main/java/org/spongycastle/util/MemoableResetException.java22
-rw-r--r--core/src/main/java/org/spongycastle/util/Pack.java201
-rw-r--r--core/src/main/java/org/spongycastle/util/Selector.java9
-rw-r--r--core/src/main/java/org/spongycastle/util/Shorts.java9
-rw-r--r--core/src/main/java/org/spongycastle/util/Store.java9
-rw-r--r--core/src/main/java/org/spongycastle/util/StoreException.java18
-rw-r--r--core/src/main/java/org/spongycastle/util/StreamParser.java10
-rw-r--r--core/src/main/java/org/spongycastle/util/StreamParsingException.java18
-rw-r--r--core/src/main/java/org/spongycastle/util/Strings.java314
-rw-r--r--core/src/main/java/org/spongycastle/util/Times.java9
-rw-r--r--core/src/main/java/org/spongycastle/util/encoders/Base64.java154
-rw-r--r--core/src/main/java/org/spongycastle/util/encoders/Base64Encoder.java331
-rw-r--r--core/src/main/java/org/spongycastle/util/encoders/BufferedDecoder.java96
-rw-r--r--core/src/main/java/org/spongycastle/util/encoders/BufferedEncoder.java96
-rw-r--r--core/src/main/java/org/spongycastle/util/encoders/DecoderException.java22
-rw-r--r--core/src/main/java/org/spongycastle/util/encoders/Encoder.java17
-rw-r--r--core/src/main/java/org/spongycastle/util/encoders/EncoderException.java22
-rw-r--r--core/src/main/java/org/spongycastle/util/encoders/Hex.java151
-rw-r--r--core/src/main/java/org/spongycastle/util/encoders/HexEncoder.java190
-rw-r--r--core/src/main/java/org/spongycastle/util/encoders/HexTranslator.java87
-rw-r--r--core/src/main/java/org/spongycastle/util/encoders/Translator.java23
-rw-r--r--core/src/main/java/org/spongycastle/util/encoders/UrlBase64.java129
-rw-r--r--core/src/main/java/org/spongycastle/util/encoders/UrlBase64Encoder.java25
-rw-r--r--core/src/main/java/org/spongycastle/util/io/BufferingOutputStream.java108
-rw-r--r--core/src/main/java/org/spongycastle/util/io/StreamOverflowException.java15
-rw-r--r--core/src/main/java/org/spongycastle/util/io/Streams.java145
-rw-r--r--core/src/main/java/org/spongycastle/util/io/TeeInputStream.java71
-rw-r--r--core/src/main/java/org/spongycastle/util/io/TeeOutputStream.java62
-rw-r--r--core/src/main/java/org/spongycastle/util/io/pem/PemGenerationException.java28
-rw-r--r--core/src/main/java/org/spongycastle/util/io/pem/PemHeader.java75
-rw-r--r--core/src/main/java/org/spongycastle/util/io/pem/PemObject.java64
-rw-r--r--core/src/main/java/org/spongycastle/util/io/pem/PemObjectGenerator.java16
-rw-r--r--core/src/main/java/org/spongycastle/util/io/pem/PemObjectParser.java19
-rw-r--r--core/src/main/java/org/spongycastle/util/io/pem/PemReader.java87
-rw-r--r--core/src/main/java/org/spongycastle/util/io/pem/PemWriter.java137
-rw-r--r--core/src/main/java/org/spongycastle/util/test/FixedSecureRandom.java135
-rw-r--r--core/src/main/java/org/spongycastle/util/test/NumberParsing.java34
-rw-r--r--core/src/main/java/org/spongycastle/util/test/SimpleTest.java84
-rw-r--r--core/src/main/java/org/spongycastle/util/test/SimpleTestResult.java80
-rw-r--r--core/src/main/java/org/spongycastle/util/test/Test.java8
-rw-r--r--core/src/main/java/org/spongycastle/util/test/TestFailedException.java18
-rw-r--r--core/src/main/java/org/spongycastle/util/test/TestResult.java10
-rw-r--r--core/src/main/java/org/spongycastle/util/test/UncloseableOutputStream.java23
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/bc/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/bc/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/bsi/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/bsi/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/cmp/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/cmp/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/cms/ecc/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/cms/ecc/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/cms/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/cms/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/crmf/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/crmf/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/cryptopro/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/cryptopro/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/dvcs/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/dvcs/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/eac/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/eac/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/esf/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/esf/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/ess/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/ess/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/gnu/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/gnu/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/iana/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/iana/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/icao/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/icao/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/isismtt/ocsp/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/isismtt/ocsp/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/isismtt/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/isismtt/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/isismtt/x509/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/isismtt/x509/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/kisa/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/kisa/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/microsoft/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/microsoft/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/misc/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/misc/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/mozilla/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/mozilla/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/nist/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/nist/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/ntt/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/ntt/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/ocsp/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/ocsp/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/oiw/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/oiw/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/pkcs/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/pkcs/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/sec/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/sec/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/smime/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/smime/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/teletrust/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/teletrust/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/tsp/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/tsp/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/ua/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/ua/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/util/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/util/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/x500/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/x500/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/x500/style/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/x500/style/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/x509/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/x509/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/x509/qualified/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/x509/qualified/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/x509/sigi/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/x509/sigi/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/asn1/x9/package.html (renamed from core/src/main/javadoc/org/bouncycastle/asn1/x9/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/agreement/jpake/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/agreement/jpake/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/agreement/kdf/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/agreement/kdf/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/agreement/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/agreement/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/agreement/srp/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/agreement/srp/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/commitments/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/commitments/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/digests/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/digests/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/ec/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/ec/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/encodings/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/encodings/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/engines/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/engines/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/examples/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/examples/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/generators/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/generators/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/io/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/io/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/kems/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/kems/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/macs/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/macs/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/modes/gcm/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/modes/gcm/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/modes/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/modes/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/paddings/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/paddings/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/params/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/params/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/parsers/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/parsers/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/prng/drbg/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/prng/drbg/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/prng/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/prng/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/signers/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/signers/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/tls/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/tls/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/crypto/util/package.html (renamed from core/src/main/javadoc/org/bouncycastle/crypto/util/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/math/ec/custom/djb/package.html (renamed from core/src/main/javadoc/org/bouncycastle/math/ec/custom/djb/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/math/ec/custom/sec/package.html (renamed from core/src/main/javadoc/org/bouncycastle/math/ec/custom/sec/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/math/ec/package.html (renamed from core/src/main/javadoc/org/bouncycastle/math/ec/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/math/raw/package.html (renamed from core/src/main/javadoc/org/bouncycastle/math/raw/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/util/encoders/package.html (renamed from core/src/main/javadoc/org/bouncycastle/util/encoders/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/util/io/package.html (renamed from core/src/main/javadoc/org/bouncycastle/util/io/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/util/io/pem/package.html (renamed from core/src/main/javadoc/org/bouncycastle/util/io/pem/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/util/package.html (renamed from core/src/main/javadoc/org/bouncycastle/util/package.html)0
-rw-r--r--core/src/main/javadoc/org/spongycastle/util/test/package.html (renamed from core/src/main/javadoc/org/bouncycastle/util/test/package.html)0
-rw-r--r--core/src/main/jdk1.1/java/security/cert/CertUtil.java16
-rw-r--r--core/src/main/jdk1.1/java/security/cert/PolicyQualifierInfo.java34
-rw-r--r--core/src/main/jdk1.1/java/security/cert/TrustAnchor.java6
-rw-r--r--core/src/main/jdk1.1/java/security/cert/X509CRLSelector.java44
-rw-r--r--core/src/main/jdk1.1/java/security/cert/X509CertSelector.java122
-rw-r--r--core/src/main/jdk1.1/org/bouncycastle/asn1/ASN1InputStream.java466
-rw-r--r--core/src/main/jdk1.1/org/bouncycastle/asn1/ASN1StreamParser.java247
-rw-r--r--core/src/main/jdk1.1/org/bouncycastle/asn1/DERApplicationSpecific.java276
-rw-r--r--core/src/main/jdk1.1/org/bouncycastle/asn1/x500/style/BCStyle.java481
-rw-r--r--core/src/main/jdk1.1/org/bouncycastle/asn1/x500/style/RFC4519Style.java380
-rw-r--r--core/src/main/jdk1.1/org/bouncycastle/crypto/agreement/jpake/JPAKEParticipant.java573
-rw-r--r--core/src/main/jdk1.1/org/bouncycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java122
-rw-r--r--core/src/main/jdk1.1/org/bouncycastle/crypto/digests/SkeinEngine.java817
-rw-r--r--core/src/main/jdk1.1/org/bouncycastle/crypto/encodings/PKCS1Encoding.java410
-rw-r--r--core/src/main/jdk1.1/org/bouncycastle/crypto/engines/NullEngine.java96
-rw-r--r--core/src/main/jdk1.1/org/bouncycastle/crypto/params/DSAParameterGenerationParameters.java80
-rw-r--r--core/src/main/jdk1.1/org/bouncycastle/crypto/params/HKDFParameters.java123
-rw-r--r--core/src/main/jdk1.1/org/bouncycastle/crypto/prng/BasicEntropySourceProvider.java57
-rw-r--r--core/src/main/jdk1.1/org/bouncycastle/crypto/prng/SP800SecureRandomBuilder.java289
-rw-r--r--core/src/main/jdk1.1/org/bouncycastle/crypto/signers/RSADigestSigner.java238
-rw-r--r--core/src/main/jdk1.1/org/bouncycastle/crypto/tls/AbstractTlsContext.java135
-rw-r--r--core/src/main/jdk1.1/org/bouncycastle/crypto/tls/DTLSReassembler.java136
-rw-r--r--core/src/main/jdk1.1/org/bouncycastle/crypto/tls/DTLSReliableHandshake.java457
-rw-r--r--core/src/main/jdk1.1/org/bouncycastle/crypto/tls/UDPTransport.java106
-rw-r--r--core/src/main/jdk1.1/org/bouncycastle/i18n/LocalizedMessage.java464
-rw-r--r--core/src/main/jdk1.1/org/bouncycastle/i18n/MissingEntryException.java63
-rw-r--r--core/src/main/jdk1.1/org/spongycastle/asn1/ASN1InputStream.java466
-rw-r--r--core/src/main/jdk1.1/org/spongycastle/asn1/ASN1StreamParser.java247
-rw-r--r--core/src/main/jdk1.1/org/spongycastle/asn1/DERApplicationSpecific.java276
-rw-r--r--core/src/main/jdk1.1/org/spongycastle/asn1/x500/style/BCStyle.java481
-rw-r--r--core/src/main/jdk1.1/org/spongycastle/asn1/x500/style/RFC4519Style.java380
-rw-r--r--core/src/main/jdk1.1/org/spongycastle/crypto/agreement/jpake/JPAKEParticipant.java573
-rw-r--r--core/src/main/jdk1.1/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java122
-rw-r--r--core/src/main/jdk1.1/org/spongycastle/crypto/digests/SkeinEngine.java817
-rw-r--r--core/src/main/jdk1.1/org/spongycastle/crypto/encodings/PKCS1Encoding.java410
-rw-r--r--core/src/main/jdk1.1/org/spongycastle/crypto/engines/NullEngine.java96
-rw-r--r--core/src/main/jdk1.1/org/spongycastle/crypto/params/DSAParameterGenerationParameters.java80
-rw-r--r--core/src/main/jdk1.1/org/spongycastle/crypto/params/HKDFParameters.java123
-rw-r--r--core/src/main/jdk1.1/org/spongycastle/crypto/prng/BasicEntropySourceProvider.java57
-rw-r--r--core/src/main/jdk1.1/org/spongycastle/crypto/prng/SP800SecureRandomBuilder.java289
-rw-r--r--core/src/main/jdk1.1/org/spongycastle/crypto/signers/RSADigestSigner.java238
-rw-r--r--core/src/main/jdk1.1/org/spongycastle/crypto/tls/AbstractTlsContext.java135
-rw-r--r--core/src/main/jdk1.1/org/spongycastle/crypto/tls/DTLSReassembler.java136
-rw-r--r--core/src/main/jdk1.1/org/spongycastle/crypto/tls/DTLSReliableHandshake.java457
-rw-r--r--core/src/main/jdk1.1/org/spongycastle/crypto/tls/UDPTransport.java106
-rw-r--r--core/src/main/jdk1.1/org/spongycastle/i18n/LocalizedMessage.java464
-rw-r--r--core/src/main/jdk1.1/org/spongycastle/i18n/MissingEntryException.java63
-rw-r--r--core/src/main/jdk1.2/org/bouncycastle/i18n/LocalizedMessage.java464
-rw-r--r--core/src/main/jdk1.2/org/bouncycastle/i18n/MissingEntryException.java63
-rw-r--r--core/src/main/jdk1.2/org/spongycastle/i18n/LocalizedMessage.java464
-rw-r--r--core/src/main/jdk1.2/org/spongycastle/i18n/MissingEntryException.java63
-rw-r--r--core/src/main/jdk1.3/org/bouncycastle/asn1/StreamUtil.java89
-rw-r--r--core/src/main/jdk1.3/org/bouncycastle/crypto/tls/UDPTransport.java78
-rw-r--r--core/src/main/jdk1.3/org/bouncycastle/i18n/LocalizedMessage.java464
-rw-r--r--core/src/main/jdk1.3/org/bouncycastle/i18n/MissingEntryException.java81
-rw-r--r--core/src/main/jdk1.3/org/spongycastle/asn1/StreamUtil.java89
-rw-r--r--core/src/main/jdk1.3/org/spongycastle/crypto/tls/UDPTransport.java78
-rw-r--r--core/src/main/jdk1.3/org/spongycastle/i18n/LocalizedMessage.java464
-rw-r--r--core/src/main/jdk1.3/org/spongycastle/i18n/MissingEntryException.java81
-rw-r--r--core/src/main/jdk1.4/org/bouncycastle/util/Integers.java19
-rw-r--r--core/src/main/jdk1.4/org/bouncycastle/util/Shorts.java9
-rw-r--r--core/src/main/jdk1.4/org/bouncycastle/util/Times.java11
-rw-r--r--core/src/main/jdk1.4/org/spongycastle/util/Integers.java19
-rw-r--r--core/src/main/jdk1.4/org/spongycastle/util/Shorts.java9
-rw-r--r--core/src/main/jdk1.4/org/spongycastle/util/Times.java11
-rw-r--r--core/src/test/j2me/java/math/test/BigIntegerTest.java2
-rw-r--r--core/src/test/j2me/java/math/test/RegressionTest.java4
-rw-r--r--core/src/test/j2me/org/bouncycastle/asn1/test/GeneralizedTimeTest.java189
-rw-r--r--core/src/test/j2me/org/bouncycastle/asn1/test/RegressionTest.java63
-rw-r--r--core/src/test/j2me/org/bouncycastle/asn1/test/UTCTimeTest.java98
-rw-r--r--core/src/test/j2me/org/bouncycastle/crypto/test/BigIntegerTest.java32
-rw-r--r--core/src/test/j2me/org/bouncycastle/crypto/test/CryptoRegressionTest.java64
-rw-r--r--core/src/test/j2me/org/bouncycastle/crypto/test/RSATest.java480
-rw-r--r--core/src/test/j2me/org/bouncycastle/crypto/test/RegressionTest.java68
-rw-r--r--core/src/test/j2me/org/spongycastle/asn1/test/GeneralizedTimeTest.java189
-rw-r--r--core/src/test/j2me/org/spongycastle/asn1/test/RegressionTest.java63
-rw-r--r--core/src/test/j2me/org/spongycastle/asn1/test/UTCTimeTest.java98
-rw-r--r--core/src/test/j2me/org/spongycastle/crypto/test/BigIntegerTest.java32
-rw-r--r--core/src/test/j2me/org/spongycastle/crypto/test/CryptoRegressionTest.java64
-rw-r--r--core/src/test/j2me/org/spongycastle/crypto/test/RSATest.java480
-rw-r--r--core/src/test/j2me/org/spongycastle/crypto/test/RegressionTest.java68
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/ASN1SequenceParserTest.java372
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/ASN1UnitTest.java89
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/AdditionalInformationSyntaxUnitTest.java69
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/AdmissionSyntaxUnitTest.java97
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/AdmissionsUnitTest.java86
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/AllTests.java43
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/AttributeTableUnitTest.java144
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/BiometricDataUnitTest.java133
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/BitStringConstantTester.java22
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/BitStringTest.java73
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/CMSTest.java358
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/CertHashUnitTest.java84
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/CertificateTest.java574
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/CommitmentTypeIndicationUnitTest.java103
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/CommitmentTypeQualifierUnitTest.java102
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/ContentHintsUnitTest.java87
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/CscaMasterListTest.java49
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/DERApplicationSpecificTest.java77
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/DERUTF8StringTest.java101
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/DataGroupHashUnitTest.java106
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/DeclarationOfMajorityUnitTest.java90
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/ESSCertIDv2UnitTest.java33
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/EncryptedPrivateKeyInfoTest.java135
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/EnumeratedTest.java115
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/EqualsAndHashCodeTest.java127
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/GeneralNameTest.java143
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/GeneralizedTimeTest.java201
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/GenerationTest.java441
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/GetInstanceTest.java888
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/InputStreamTest.java75
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/Iso4217CurrencyCodeUnitTest.java142
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/IssuingDistributionPointUnitTest.java122
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/KeyUsageTest.java55
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/LDSSecurityObjectUnitTest.java214
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/MiscTest.java113
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/MonetaryLimitUnitTest.java85
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/MonetaryValueUnitTest.java88
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/NameOrPseudonymUnitTest.java108
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/NamingAuthorityUnitTest.java99
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/NetscapeCertTypeTest.java34
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/OCSPTest.java193
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/OIDTest.java165
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/ObjectIdentifierTest.java38
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/OctetStringTest.java203
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/OtherCertIDUnitTest.java97
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/OtherSigningCertificateUnitTest.java86
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/PKCS10Test.java101
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/PKCS12Test.java227
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/PKIFailureInfoTest.java68
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/ParseTest.java308
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/ParsingTest.java99
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/PersonalDataUnitTest.java121
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/ProcurationSyntaxUnitTest.java107
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/ProfessionInfoUnitTest.java117
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/QCStatementUnitTest.java104
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/RFC4519Test.java149
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/ReasonFlagsTest.java35
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/RegressionTest.java92
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/RequestedCertificateUnitTest.java108
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/RestrictionUnitTest.java70
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/SMIMETest.java109
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/SemanticsInformationUnitTest.java135
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/SetTest.java115
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/SignerLocationUnitTest.java197
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/StringTest.java161
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/SubjectKeyIdentifierTest.java48
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/TagTest.java113
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/TargetInformationTest.java48
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/TypeOfBiometricDataUnitTest.java144
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/UTCTimeTest.java108
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/X500NameTest.java771
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/X509ExtensionsTest.java105
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/X509NameTest.java693
-rw-r--r--core/src/test/java/org/bouncycastle/asn1/test/X9Test.java168
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/agreement/test/AllTests.java25
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/agreement/test/JPAKEParticipantTest.java561
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/agreement/test/JPAKEPrimeOrderGroupTest.java85
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/agreement/test/JPAKEUtilTest.java267
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/ec/test/AllTests.java39
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/ec/test/ECElGamalTest.java88
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/ec/test/ECTransformationTest.java149
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/prng/test/AllTests.java39
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/prng/test/CTRDRBGTest.java513
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/prng/test/DRBGTestVector.java131
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/prng/test/DualECDRBGTest.java415
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/prng/test/FixedSecureRandomTest.java68
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/prng/test/HMacDRBGTest.java508
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/prng/test/HashDRBGTest.java481
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/prng/test/RegressionTest.java33
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/prng/test/SP800RandomTest.java319
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/prng/test/TestEntropySourceProvider.java46
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/AEADTestUtil.java474
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/AESFastTest.java150
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/AESLightTest.java150
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/AESTest.java442
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/AESVectorFileTest.java258
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/AESWrapPadTest.java146
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/AESWrapTest.java238
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/AllTests.java41
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/BlockCipherMonteCarloTest.java82
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/BlockCipherResetTest.java206
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/BlockCipherVectorTest.java71
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/BlowfishTest.java57
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/CAST5Test.java44
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/CAST6Test.java44
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/CCMTest.java305
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/CMacTest.java321
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/CTSTest.java212
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/CamelliaLightTest.java66
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/CamelliaTest.java70
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/ChaChaTest.java403
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/CipherStreamTest.java699
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/CipherTest.java117
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/CramerShoupTest.java147
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/DESTest.java206
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/DESedeTest.java177
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/DHKEKGeneratorTest.java70
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/DHTest.java414
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/DSATest.java602
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/DSTU4145Test.java278
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/DeterministicDSATest.java513
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/DigestRandomNumberTest.java152
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/DigestTest.java226
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/EAXTest.java355
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/ECDHKEKGeneratorTest.java71
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/ECGOST3410Test.java327
-rwxr-xr-xcore/src/test/java/org/bouncycastle/crypto/test/ECIESKeyEncapsulationTest.java138
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/ECIESTest.java377
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/ECNRTest.java99
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/ECTest.java926
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/ElGamalTest.java285
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/EqualsHashCodeTest.java261
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/GCMReorderTest.java347
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/GCMTest.java687
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/GMacTest.java174
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/GOST28147MacTest.java89
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/GOST28147Test.java328
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/GOST3410Test.java1570
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/GOST3411DigestTest.java74
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/Grain128Test.java117
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/Grainv1Test.java140
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/HCFamilyTest.java192
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/HCFamilyVecTest.java199
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/HKDFGeneratorTest.java304
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/HashCommitmentTest.java152
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/IDEATest.java38
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/ISAACTest.java180
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/ISO9796Test.java972
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/ISO9797Alg3MacTest.java126
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/KDF1GeneratorTest.java93
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/KDF2GeneratorTest.java105
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/KDFCounterGeneratorTest.java51
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/KDFDoublePipelineIteratorGeneratorTest.java72
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/KDFFeedbackGeneratorTest.java71
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/MD2DigestTest.java52
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/MD4DigestTest.java43
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/MD5DigestTest.java43
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/MD5HMacTest.java98
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/MGF1GeneratorTest.java88
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/MacTest.java181
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/ModeTest.java115
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/NaccacheSternTest.java354
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/NoekeonTest.java45
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/NonMemoableDigestTest.java112
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/NullTest.java77
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/OAEPTest.java830
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/OCBTest.java520
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/PKCS12Test.java206
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/PKCS5Test.java265
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/PSSBlindTest.java398
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/PSSTest.java332
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/PaddingTest.java200
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/Poly1305Test.java388
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/RC2Test.java66
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/RC2WrapTest.java111
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/RC4Test.java45
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/RC5Test.java188
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/RC6Test.java64
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/RFC3211WrapTest.java220
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/RIPEMD128DigestTest.java58
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/RIPEMD128HMacTest.java86
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/RIPEMD160DigestTest.java58
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/RIPEMD160HMacTest.java86
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/RIPEMD256DigestTest.java58
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/RIPEMD320DigestTest.java58
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/RSABlindedTest.java437
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/RSADigestSignerTest.java55
-rwxr-xr-xcore/src/test/java/org/bouncycastle/crypto/test/RSAKeyEncapsulationTest.java61
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/RSATest.java498
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/RegressionTest.java157
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/ResetTest.java99
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/RijndaelTest.java116
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/SCryptTest.java144
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/SEEDTest.java53
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/SHA1DigestTest.java48
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/SHA1HMacTest.java111
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/SHA224DigestTest.java59
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/SHA224HMacTest.java108
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/SHA256DigestTest.java60
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/SHA256HMacTest.java108
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/SHA384DigestTest.java59
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/SHA384HMacTest.java108
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/SHA3DigestTest.java363
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/SHA512DigestTest.java60
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/SHA512HMacTest.java108
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/SHA512t224DigestTest.java60
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/SHA512t256DigestTest.java60
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/SM3DigestTest.java57
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/SRP6Test.java276
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/Salsa20Test.java400
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/SerpentTest.java103
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/Shacal2Test.java200
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/ShortenedDigestTest.java89
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/SipHashTest.java143
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/SkeinDigestTest.java294
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/SkeinMacTest.java162
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/SkipjackTest.java35
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/StreamCipherResetTest.java133
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/StreamCipherVectorTest.java62
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/TEATest.java48
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/Threefish1024Test.java60
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/Threefish256Test.java45
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/Threefish512Test.java50
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/TigerDigestTest.java59
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/TwofishTest.java45
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/VMPCKSA3Test.java97
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/VMPCMacTest.java51
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/VMPCTest.java97
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/WhirlpoolDigestTest.java105
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/XSalsa20Test.java166
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/XTEATest.java48
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/cavp/CAVPListener.java18
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/cavp/CAVPReader.java152
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/cavp/KDFCounterTests.java119
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/cavp/KDFDoublePipelineCounterTests.java107
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/cavp/KDFDoublePipelineIterationNoCounterTests.java88
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/cavp/KDFFeedbackCounterTests.java108
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/cavp/KDFFeedbackNoCounterTests.java89
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/speedy/MacThroughputTest.java156
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/speedy/Poly1305Reference.java292
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/speedy/ThreefishReferenceEngine.java395
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/test/speedy/ThroughputTest.java203
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/AllTests.java23
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/BasicTlsTest.java200
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/DTLSClientTest.java80
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/DTLSProtocolTest.java102
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/DTLSServerTest.java76
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/DTLSTestCase.java248
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/HTTPSServerThread.java113
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/KeyStores.java113
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/LoggingDatagramTransport.java91
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/MockDTLSClient.java177
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/MockDTLSServer.java148
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/MockDatagramAssociation.java110
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/MockTlsClient.java167
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/MockTlsServer.java153
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/NetworkInputStream.java60
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/NetworkOutputStream.java54
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/TlsClientTest.java69
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/TlsProtocolTest.java82
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/TlsServerTest.java81
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/TlsTestCase.java252
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/TlsTestClientImpl.java263
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/TlsTestConfig.java96
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/TlsTestServerImpl.java222
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/TlsTestUtils.java157
-rw-r--r--core/src/test/java/org/bouncycastle/crypto/tls/test/UnreliableDatagramTransport.java93
-rw-r--r--core/src/test/java/org/bouncycastle/i18n/filter/test/HTMLFilterTest.java29
-rw-r--r--core/src/test/java/org/bouncycastle/i18n/filter/test/SQLFilterTest.java20
-rw-r--r--core/src/test/java/org/bouncycastle/i18n/test/AllTests.java28
-rw-r--r--core/src/test/java/org/bouncycastle/i18n/test/LocalizedMessageTest.java185
-rw-r--r--core/src/test/java/org/bouncycastle/math/ec/test/AllTests.java40
-rw-r--r--core/src/test/java/org/bouncycastle/math/ec/test/ECAlgorithmsTest.java168
-rw-r--r--core/src/test/java/org/bouncycastle/math/ec/test/ECPointPerformanceTest.java198
-rw-r--r--core/src/test/java/org/bouncycastle/math/ec/test/ECPointTest.java521
-rw-r--r--core/src/test/java/org/bouncycastle/math/ec/test/F2mProofer.java203
-rw-r--r--core/src/test/java/org/bouncycastle/math/ec/test/TnafTest.java152
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/crypto/test/AllTests.java47
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/crypto/test/BitStringTest.java88
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/crypto/test/EncryptionKeyTest.java51
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/crypto/test/GMSSSignerTest.java88
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/crypto/test/McElieceFujisakiCipherTest.java102
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/crypto/test/McElieceKobaraImaiCipherTest.java102
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/crypto/test/McEliecePKCSCipherTest.java102
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/crypto/test/McEliecePointchevalCipherTest.java102
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUEncryptTest.java298
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUEncryptionParametersTest.java48
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSignatureKeyTest.java58
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSignatureParametersTest.java64
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSignerTest.java317
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSigningParametersTest.java65
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/crypto/test/RainbowSignerTest.java67
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/crypto/test/RegressionTest.java33
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/math/ntru/euclid/test/AllTests.java24
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/math/ntru/euclid/test/BigIntEuclideanTest.java23
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/math/ntru/euclid/test/IntEuclideanTest.java43
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/AllTests.java29
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/BigDecimalPolynomialTest.java47
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/BigIntPolynomialTest.java26
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/IntegerPolynomialTest.java230
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/LongPolynomial2Test.java60
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/LongPolynomial5Test.java62
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/PolynomialGenerator.java27
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/ProductFormPolynomialTest.java47
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/SparseTernaryPolynomialTest.java45
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/math/ntru/util/test/AllTests.java23
-rw-r--r--core/src/test/java/org/bouncycastle/pqc/math/ntru/util/test/ArrayEncoderTest.java42
-rw-r--r--core/src/test/java/org/bouncycastle/util/encoders/test/AbstractCoderTest.java211
-rw-r--r--core/src/test/java/org/bouncycastle/util/encoders/test/AllTests.java20
-rw-r--r--core/src/test/java/org/bouncycastle/util/encoders/test/Base64Test.java121
-rw-r--r--core/src/test/java/org/bouncycastle/util/encoders/test/EncoderTest.java250
-rw-r--r--core/src/test/java/org/bouncycastle/util/encoders/test/HexTest.java92
-rw-r--r--core/src/test/java/org/bouncycastle/util/encoders/test/UrlBase64Test.java119
-rw-r--r--core/src/test/java/org/bouncycastle/util/io/pem/test/AllTests.java71
-rw-r--r--core/src/test/java/org/bouncycastle/util/io/test/BufferingOutputStreamTest.java68
-rw-r--r--core/src/test/java/org/bouncycastle/util/utiltest/AllTests.java20
-rw-r--r--core/src/test/java/org/bouncycastle/util/utiltest/BigIntegersTest.java90
-rw-r--r--core/src/test/java/org/bouncycastle/util/utiltest/IPTest.java55
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/ASN1SequenceParserTest.java372
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/ASN1UnitTest.java89
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/AdditionalInformationSyntaxUnitTest.java69
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/AdmissionSyntaxUnitTest.java97
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/AdmissionsUnitTest.java86
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/AllTests.java43
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/AttributeTableUnitTest.java144
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/BiometricDataUnitTest.java133
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/BitStringConstantTester.java22
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/BitStringTest.java73
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/CMSTest.java358
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/CertHashUnitTest.java84
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/CertificateTest.java574
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/CommitmentTypeIndicationUnitTest.java103
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/CommitmentTypeQualifierUnitTest.java102
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/ContentHintsUnitTest.java87
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/CscaMasterListTest.java49
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/DERApplicationSpecificTest.java77
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/DERUTF8StringTest.java101
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/DataGroupHashUnitTest.java106
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/DeclarationOfMajorityUnitTest.java90
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/ESSCertIDv2UnitTest.java33
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/EncryptedPrivateKeyInfoTest.java135
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/EnumeratedTest.java115
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/EqualsAndHashCodeTest.java127
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/GeneralNameTest.java143
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/GeneralizedTimeTest.java201
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/GenerationTest.java441
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/GetInstanceTest.java888
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/InputStreamTest.java75
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/Iso4217CurrencyCodeUnitTest.java142
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/IssuingDistributionPointUnitTest.java122
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/KeyUsageTest.java55
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/LDSSecurityObjectUnitTest.java214
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/MiscTest.java113
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/MonetaryLimitUnitTest.java85
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/MonetaryValueUnitTest.java88
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/NameOrPseudonymUnitTest.java108
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/NamingAuthorityUnitTest.java99
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/NetscapeCertTypeTest.java34
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/OCSPTest.java193
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/OIDTest.java165
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/ObjectIdentifierTest.java38
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/OctetStringTest.java203
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/OtherCertIDUnitTest.java97
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/OtherSigningCertificateUnitTest.java86
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/PKCS10Test.java101
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/PKCS12Test.java227
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/PKIFailureInfoTest.java68
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/ParseTest.java308
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/ParsingTest.java99
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/PersonalDataUnitTest.java121
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/ProcurationSyntaxUnitTest.java107
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/ProfessionInfoUnitTest.java117
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/QCStatementUnitTest.java104
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/RFC4519Test.java149
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/ReasonFlagsTest.java35
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/RegressionTest.java92
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/RequestedCertificateUnitTest.java108
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/RestrictionUnitTest.java70
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/SMIMETest.java109
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/SemanticsInformationUnitTest.java135
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/SetTest.java115
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/SignerLocationUnitTest.java197
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/StringTest.java161
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/SubjectKeyIdentifierTest.java48
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/TagTest.java113
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/TargetInformationTest.java48
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/TypeOfBiometricDataUnitTest.java144
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/UTCTimeTest.java108
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/X500NameTest.java771
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/X509ExtensionsTest.java105
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/X509NameTest.java693
-rw-r--r--core/src/test/java/org/spongycastle/asn1/test/X9Test.java168
-rw-r--r--core/src/test/java/org/spongycastle/crypto/agreement/test/AllTests.java25
-rw-r--r--core/src/test/java/org/spongycastle/crypto/agreement/test/JPAKEParticipantTest.java561
-rw-r--r--core/src/test/java/org/spongycastle/crypto/agreement/test/JPAKEPrimeOrderGroupTest.java85
-rw-r--r--core/src/test/java/org/spongycastle/crypto/agreement/test/JPAKEUtilTest.java267
-rw-r--r--core/src/test/java/org/spongycastle/crypto/ec/test/AllTests.java39
-rw-r--r--core/src/test/java/org/spongycastle/crypto/ec/test/ECElGamalTest.java88
-rw-r--r--core/src/test/java/org/spongycastle/crypto/ec/test/ECTransformationTest.java149
-rw-r--r--core/src/test/java/org/spongycastle/crypto/prng/test/AllTests.java39
-rw-r--r--core/src/test/java/org/spongycastle/crypto/prng/test/CTRDRBGTest.java513
-rw-r--r--core/src/test/java/org/spongycastle/crypto/prng/test/DRBGTestVector.java131
-rw-r--r--core/src/test/java/org/spongycastle/crypto/prng/test/DualECDRBGTest.java415
-rw-r--r--core/src/test/java/org/spongycastle/crypto/prng/test/FixedSecureRandomTest.java68
-rw-r--r--core/src/test/java/org/spongycastle/crypto/prng/test/HMacDRBGTest.java508
-rw-r--r--core/src/test/java/org/spongycastle/crypto/prng/test/HashDRBGTest.java481
-rw-r--r--core/src/test/java/org/spongycastle/crypto/prng/test/RegressionTest.java33
-rw-r--r--core/src/test/java/org/spongycastle/crypto/prng/test/SP800RandomTest.java319
-rw-r--r--core/src/test/java/org/spongycastle/crypto/prng/test/TestEntropySourceProvider.java46
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/AEADTestUtil.java474
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/AESFastTest.java150
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/AESLightTest.java150
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/AESTest.java442
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/AESVectorFileTest.java258
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/AESWrapPadTest.java146
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/AESWrapTest.java238
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/AllTests.java41
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/BlockCipherMonteCarloTest.java82
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/BlockCipherResetTest.java206
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/BlockCipherVectorTest.java71
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/BlowfishTest.java57
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/CAST5Test.java44
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/CAST6Test.java44
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/CCMTest.java305
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/CMacTest.java321
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/CTSTest.java212
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/CamelliaLightTest.java66
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/CamelliaTest.java70
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/ChaChaTest.java403
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/CipherStreamTest.java699
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/CipherTest.java117
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/CramerShoupTest.java147
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/DESTest.java206
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/DESedeTest.java177
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/DHKEKGeneratorTest.java70
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/DHTest.java414
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/DSATest.java602
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/DSTU4145Test.java278
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/DeterministicDSATest.java513
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/DigestRandomNumberTest.java152
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/DigestTest.java226
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/EAXTest.java355
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/ECDHKEKGeneratorTest.java71
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/ECGOST3410Test.java327
-rwxr-xr-xcore/src/test/java/org/spongycastle/crypto/test/ECIESKeyEncapsulationTest.java138
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/ECIESTest.java377
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/ECNRTest.java99
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/ECTest.java926
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/ElGamalTest.java285
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/EqualsHashCodeTest.java261
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/GCMReorderTest.java347
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/GCMTest.java687
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/GMacTest.java174
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/GOST28147MacTest.java89
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/GOST28147Test.java328
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/GOST3410Test.java1570
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/GOST3411DigestTest.java74
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/Grain128Test.java117
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/Grainv1Test.java140
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/HCFamilyTest.java192
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/HCFamilyVecTest.java199
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/HKDFGeneratorTest.java304
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/HashCommitmentTest.java152
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/IDEATest.java38
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/ISAACTest.java180
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/ISO9796Test.java972
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/ISO9797Alg3MacTest.java126
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/KDF1GeneratorTest.java93
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/KDF2GeneratorTest.java105
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/KDFCounterGeneratorTest.java51
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/KDFDoublePipelineIteratorGeneratorTest.java72
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/KDFFeedbackGeneratorTest.java71
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/MD2DigestTest.java52
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/MD4DigestTest.java43
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/MD5DigestTest.java43
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/MD5HMacTest.java98
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/MGF1GeneratorTest.java88
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/MacTest.java181
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/ModeTest.java115
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/NaccacheSternTest.java354
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/NoekeonTest.java45
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/NonMemoableDigestTest.java112
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/NullTest.java77
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/OAEPTest.java830
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/OCBTest.java520
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/PKCS12Test.java206
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/PKCS5Test.java265
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/PSSBlindTest.java398
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/PSSTest.java332
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/PaddingTest.java200
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/Poly1305Test.java388
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/RC2Test.java66
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/RC2WrapTest.java111
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/RC4Test.java45
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/RC5Test.java188
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/RC6Test.java64
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/RFC3211WrapTest.java220
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/RIPEMD128DigestTest.java58
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/RIPEMD128HMacTest.java86
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/RIPEMD160DigestTest.java58
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/RIPEMD160HMacTest.java86
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/RIPEMD256DigestTest.java58
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/RIPEMD320DigestTest.java58
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/RSABlindedTest.java437
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/RSADigestSignerTest.java55
-rwxr-xr-xcore/src/test/java/org/spongycastle/crypto/test/RSAKeyEncapsulationTest.java61
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/RSATest.java498
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/RegressionTest.java157
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/ResetTest.java99
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/RijndaelTest.java116
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/SCryptTest.java144
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/SEEDTest.java53
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/SHA1DigestTest.java48
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/SHA1HMacTest.java111
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/SHA224DigestTest.java59
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/SHA224HMacTest.java108
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/SHA256DigestTest.java60
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/SHA256HMacTest.java108
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/SHA384DigestTest.java59
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/SHA384HMacTest.java108
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/SHA3DigestTest.java363
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/SHA512DigestTest.java60
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/SHA512HMacTest.java108
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/SHA512t224DigestTest.java60
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/SHA512t256DigestTest.java60
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/SM3DigestTest.java57
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/SRP6Test.java276
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/Salsa20Test.java400
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/SerpentTest.java103
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/Shacal2Test.java200
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/ShortenedDigestTest.java89
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/SipHashTest.java143
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/SkeinDigestTest.java294
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/SkeinMacTest.java162
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/SkipjackTest.java35
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/StreamCipherResetTest.java133
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/StreamCipherVectorTest.java62
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/TEATest.java48
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/Threefish1024Test.java60
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/Threefish256Test.java45
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/Threefish512Test.java50
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/TigerDigestTest.java59
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/TwofishTest.java45
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/VMPCKSA3Test.java97
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/VMPCMacTest.java51
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/VMPCTest.java97
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/WhirlpoolDigestTest.java105
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/XSalsa20Test.java166
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/XTEATest.java48
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/cavp/CAVPListener.java18
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/cavp/CAVPReader.java152
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/cavp/KDFCounterTests.java119
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/cavp/KDFDoublePipelineCounterTests.java107
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/cavp/KDFDoublePipelineIterationNoCounterTests.java88
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/cavp/KDFFeedbackCounterTests.java108
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/cavp/KDFFeedbackNoCounterTests.java89
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/speedy/MacThroughputTest.java156
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/speedy/Poly1305Reference.java292
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/speedy/ThreefishReferenceEngine.java395
-rw-r--r--core/src/test/java/org/spongycastle/crypto/test/speedy/ThroughputTest.java203
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/AllTests.java23
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/BasicTlsTest.java200
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/DTLSClientTest.java80
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/DTLSProtocolTest.java102
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/DTLSServerTest.java76
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/DTLSTestCase.java248
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/HTTPSServerThread.java113
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/KeyStores.java113
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/LoggingDatagramTransport.java91
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/MockDTLSClient.java177
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/MockDTLSServer.java148
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/MockDatagramAssociation.java110
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/MockTlsClient.java167
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/MockTlsServer.java153
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/NetworkInputStream.java60
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/NetworkOutputStream.java54
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/TlsClientTest.java69
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/TlsProtocolTest.java82
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/TlsServerTest.java81
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/TlsTestCase.java252
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/TlsTestClientImpl.java263
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/TlsTestConfig.java96
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/TlsTestServerImpl.java222
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/TlsTestUtils.java157
-rw-r--r--core/src/test/java/org/spongycastle/crypto/tls/test/UnreliableDatagramTransport.java93
-rw-r--r--core/src/test/java/org/spongycastle/i18n/filter/test/HTMLFilterTest.java29
-rw-r--r--core/src/test/java/org/spongycastle/i18n/filter/test/SQLFilterTest.java20
-rw-r--r--core/src/test/java/org/spongycastle/i18n/test/AllTests.java28
-rw-r--r--core/src/test/java/org/spongycastle/i18n/test/LocalizedMessageTest.java185
-rw-r--r--core/src/test/java/org/spongycastle/math/ec/test/AllTests.java40
-rw-r--r--core/src/test/java/org/spongycastle/math/ec/test/ECAlgorithmsTest.java168
-rw-r--r--core/src/test/java/org/spongycastle/math/ec/test/ECPointPerformanceTest.java198
-rw-r--r--core/src/test/java/org/spongycastle/math/ec/test/ECPointTest.java521
-rw-r--r--core/src/test/java/org/spongycastle/math/ec/test/F2mProofer.java203
-rw-r--r--core/src/test/java/org/spongycastle/math/ec/test/TnafTest.java152
-rw-r--r--core/src/test/java/org/spongycastle/pqc/crypto/test/AllTests.java47
-rw-r--r--core/src/test/java/org/spongycastle/pqc/crypto/test/BitStringTest.java88
-rw-r--r--core/src/test/java/org/spongycastle/pqc/crypto/test/EncryptionKeyTest.java51
-rw-r--r--core/src/test/java/org/spongycastle/pqc/crypto/test/GMSSSignerTest.java88
-rw-r--r--core/src/test/java/org/spongycastle/pqc/crypto/test/McElieceFujisakiCipherTest.java102
-rw-r--r--core/src/test/java/org/spongycastle/pqc/crypto/test/McElieceKobaraImaiCipherTest.java102
-rw-r--r--core/src/test/java/org/spongycastle/pqc/crypto/test/McEliecePKCSCipherTest.java102
-rw-r--r--core/src/test/java/org/spongycastle/pqc/crypto/test/McEliecePointchevalCipherTest.java102
-rw-r--r--core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUEncryptTest.java298
-rw-r--r--core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUEncryptionParametersTest.java48
-rw-r--r--core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUSignatureKeyTest.java58
-rw-r--r--core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUSignatureParametersTest.java64
-rw-r--r--core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUSignerTest.java317
-rw-r--r--core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUSigningParametersTest.java65
-rw-r--r--core/src/test/java/org/spongycastle/pqc/crypto/test/RainbowSignerTest.java67
-rw-r--r--core/src/test/java/org/spongycastle/pqc/crypto/test/RegressionTest.java33
-rw-r--r--core/src/test/java/org/spongycastle/pqc/math/ntru/euclid/test/AllTests.java24
-rw-r--r--core/src/test/java/org/spongycastle/pqc/math/ntru/euclid/test/BigIntEuclideanTest.java23
-rw-r--r--core/src/test/java/org/spongycastle/pqc/math/ntru/euclid/test/IntEuclideanTest.java43
-rw-r--r--core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/AllTests.java29
-rw-r--r--core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/BigDecimalPolynomialTest.java47
-rw-r--r--core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/BigIntPolynomialTest.java26
-rw-r--r--core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/IntegerPolynomialTest.java230
-rw-r--r--core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/LongPolynomial2Test.java60
-rw-r--r--core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/LongPolynomial5Test.java62
-rw-r--r--core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/PolynomialGenerator.java27
-rw-r--r--core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/ProductFormPolynomialTest.java47
-rw-r--r--core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/SparseTernaryPolynomialTest.java45
-rw-r--r--core/src/test/java/org/spongycastle/pqc/math/ntru/util/test/AllTests.java23
-rw-r--r--core/src/test/java/org/spongycastle/pqc/math/ntru/util/test/ArrayEncoderTest.java42
-rw-r--r--core/src/test/java/org/spongycastle/util/encoders/test/AbstractCoderTest.java211
-rw-r--r--core/src/test/java/org/spongycastle/util/encoders/test/AllTests.java20
-rw-r--r--core/src/test/java/org/spongycastle/util/encoders/test/Base64Test.java121
-rw-r--r--core/src/test/java/org/spongycastle/util/encoders/test/EncoderTest.java250
-rw-r--r--core/src/test/java/org/spongycastle/util/encoders/test/HexTest.java92
-rw-r--r--core/src/test/java/org/spongycastle/util/encoders/test/UrlBase64Test.java119
-rw-r--r--core/src/test/java/org/spongycastle/util/io/pem/test/AllTests.java71
-rw-r--r--core/src/test/java/org/spongycastle/util/io/test/BufferingOutputStreamTest.java68
-rw-r--r--core/src/test/java/org/spongycastle/util/utiltest/AllTests.java20
-rw-r--r--core/src/test/java/org/spongycastle/util/utiltest/BigIntegersTest.java90
-rw-r--r--core/src/test/java/org/spongycastle/util/utiltest/IPTest.java55
-rw-r--r--core/src/test/javadoc/org/bouncycastle/cms/test/package.html7
-rw-r--r--core/src/test/javadoc/org/bouncycastle/mail/smime/test/package.html7
-rw-r--r--core/src/test/javadoc/org/bouncycastle/openpgp/test/package.html7
-rw-r--r--core/src/test/javadoc/org/spongycastle/asn1/test/package.html (renamed from core/src/test/javadoc/org/bouncycastle/asn1/test/package.html)0
-rw-r--r--core/src/test/javadoc/org/spongycastle/cms/test/package.html7
-rw-r--r--core/src/test/javadoc/org/spongycastle/crypto/test/package.html (renamed from core/src/test/javadoc/org/bouncycastle/crypto/test/package.html)0
-rw-r--r--core/src/test/javadoc/org/spongycastle/crypto/tls/package.html (renamed from core/src/test/javadoc/org/bouncycastle/crypto/tls/package.html)0
-rw-r--r--core/src/test/javadoc/org/spongycastle/mail/smime/test/package.html7
-rw-r--r--core/src/test/javadoc/org/spongycastle/mozilla/test/package.html (renamed from core/src/test/javadoc/org/bouncycastle/mozilla/test/package.html)0
-rw-r--r--core/src/test/javadoc/org/spongycastle/ocsp/test/package.html (renamed from core/src/test/javadoc/org/bouncycastle/ocsp/test/package.html)0
-rw-r--r--core/src/test/javadoc/org/spongycastle/openpgp/test/package.html7
-rw-r--r--core/src/test/javadoc/org/spongycastle/openssl/test/package.html (renamed from core/src/test/javadoc/org/bouncycastle/openssl/test/package.html)0
-rw-r--r--core/src/test/jdk1.1/org/bouncycastle/asn1/test/RegressionTest.java91
-rw-r--r--core/src/test/jdk1.1/org/bouncycastle/crypto/test/RegressionTest.java149
-rw-r--r--core/src/test/jdk1.1/org/spongycastle/asn1/test/RegressionTest.java91
-rw-r--r--core/src/test/jdk1.1/org/spongycastle/crypto/test/RegressionTest.java149
-rw-r--r--core/src/test/jdk1.2/org/bouncycastle/asn1/test/RegressionTest.java91
-rw-r--r--core/src/test/jdk1.2/org/bouncycastle/crypto/test/RegressionTest.java150
-rw-r--r--core/src/test/jdk1.2/org/spongycastle/asn1/test/RegressionTest.java91
-rw-r--r--core/src/test/jdk1.2/org/spongycastle/crypto/test/RegressionTest.java150
-rw-r--r--core/src/test/jdk1.3/org/bouncycastle/crypto/test/DSATest.java602
-rw-r--r--core/src/test/jdk1.3/org/bouncycastle/i18n/test/AllTests.java27
-rw-r--r--core/src/test/jdk1.3/org/spongycastle/crypto/test/DSATest.java602
-rw-r--r--core/src/test/jdk1.3/org/spongycastle/i18n/test/AllTests.java27
-rw-r--r--core/src/test/jdk1.4/org/bouncycastle/asn1/test/AllTests.java42
-rw-r--r--core/src/test/jdk1.4/org/bouncycastle/crypto/test/RegressionTest.java150
-rw-r--r--core/src/test/jdk1.4/org/bouncycastle/pqc/crypto/test/AllTests.java39
-rw-r--r--core/src/test/jdk1.4/org/spongycastle/asn1/test/AllTests.java42
-rw-r--r--core/src/test/jdk1.4/org/spongycastle/crypto/test/RegressionTest.java150
-rw-r--r--core/src/test/jdk1.4/org/spongycastle/pqc/crypto/test/AllTests.java39
-rw-r--r--core/src/test/resources/org/spongycastle/asn1/test/masterlist-content.data (renamed from core/src/test/resources/org/bouncycastle/asn1/test/masterlist-content.data)bin1748 -> 1748 bytes
-rw-r--r--core/src/test/resources/org/spongycastle/crypto/test/SCryptTestVectors.txt (renamed from core/src/test/resources/org/bouncycastle/crypto/test/SCryptTestVectors.txt)0
-rw-r--r--core/src/test/resources/org/spongycastle/crypto/test/cavp/KDFCTR_gen.rsp (renamed from core/src/test/resources/org/bouncycastle/crypto/test/cavp/KDFCTR_gen.rsp)0
-rw-r--r--core/src/test/resources/org/spongycastle/crypto/test/cavp/KDFDblPipelineCounter_gen.rsp (renamed from core/src/test/resources/org/bouncycastle/crypto/test/cavp/KDFDblPipelineCounter_gen.rsp)0
-rw-r--r--core/src/test/resources/org/spongycastle/crypto/test/cavp/KDFDblPipelineNoCounter_gen.rsp (renamed from core/src/test/resources/org/bouncycastle/crypto/test/cavp/KDFDblPipelineNoCounter_gen.rsp)0
-rw-r--r--core/src/test/resources/org/spongycastle/crypto/test/cavp/KDFFeedbackCounter_gen.rsp (renamed from core/src/test/resources/org/bouncycastle/crypto/test/cavp/KDFFeedbackCounter_gen.rsp)0
-rw-r--r--core/src/test/resources/org/spongycastle/crypto/test/cavp/KDFFeedbackNoCounter_gen.rsp (renamed from core/src/test/resources/org/bouncycastle/crypto/test/cavp/KDFFeedbackNoCounter_gen.rsp)0
-rw-r--r--core/src/test/resources/org/spongycastle/crypto/test/cavp/KDFFeedbackNoIV_gen.rsp (renamed from core/src/test/resources/org/bouncycastle/crypto/test/cavp/KDFFeedbackNoIV_gen.rsp)0
-rw-r--r--core/src/test/resources/org/spongycastle/crypto/test/cavp/[original]_KDFCTR_gen.rsp (renamed from core/src/test/resources/org/bouncycastle/crypto/test/cavp/[original]_KDFCTR_gen.rsp)0
-rw-r--r--core/src/test/resources/org/spongycastle/crypto/test/ecrypt_HC-128.txt (renamed from core/src/test/resources/org/bouncycastle/crypto/test/ecrypt_HC-128.txt)0
-rw-r--r--core/src/test/resources/org/spongycastle/crypto/test/ecrypt_HC-256_128K_128IV.txt (renamed from core/src/test/resources/org/bouncycastle/crypto/test/ecrypt_HC-256_128K_128IV.txt)0
-rw-r--r--core/src/test/resources/org/spongycastle/crypto/test/ecrypt_HC-256_128K_256IV.txt (renamed from core/src/test/resources/org/bouncycastle/crypto/test/ecrypt_HC-256_128K_256IV.txt)0
-rw-r--r--core/src/test/resources/org/spongycastle/crypto/test/ecrypt_HC-256_256K_128IV.txt (renamed from core/src/test/resources/org/bouncycastle/crypto/test/ecrypt_HC-256_256K_128IV.txt)0
-rw-r--r--core/src/test/resources/org/spongycastle/crypto/test/ecrypt_HC-256_256K_256IV.txt (renamed from core/src/test/resources/org/bouncycastle/crypto/test/ecrypt_HC-256_256K_256IV.txt)0
-rw-r--r--core/src/test/resources/org/spongycastle/crypto/tls/test/README.txt (renamed from core/src/test/resources/org/bouncycastle/crypto/tls/test/README.txt)0
-rw-r--r--core/src/test/resources/org/spongycastle/crypto/tls/test/ca.tmpl (renamed from core/src/test/resources/org/bouncycastle/crypto/tls/test/ca.tmpl)0
-rw-r--r--core/src/test/resources/org/spongycastle/crypto/tls/test/client.tmpl (renamed from core/src/test/resources/org/bouncycastle/crypto/tls/test/client.tmpl)0
-rw-r--r--core/src/test/resources/org/spongycastle/crypto/tls/test/server.tmpl (renamed from core/src/test/resources/org/bouncycastle/crypto/tls/test/server.tmpl)0
-rw-r--r--core/src/test/resources/org/spongycastle/crypto/tls/test/x509-ca-key.pem (renamed from core/src/test/resources/org/bouncycastle/crypto/tls/test/x509-ca-key.pem)0
-rw-r--r--core/src/test/resources/org/spongycastle/crypto/tls/test/x509-ca.pem (renamed from core/src/test/resources/org/bouncycastle/crypto/tls/test/x509-ca.pem)0
-rw-r--r--core/src/test/resources/org/spongycastle/crypto/tls/test/x509-client-key.pem (renamed from core/src/test/resources/org/bouncycastle/crypto/tls/test/x509-client-key.pem)0
-rw-r--r--core/src/test/resources/org/spongycastle/crypto/tls/test/x509-client.pem (renamed from core/src/test/resources/org/bouncycastle/crypto/tls/test/x509-client.pem)0
-rw-r--r--core/src/test/resources/org/spongycastle/crypto/tls/test/x509-server-key.pem (renamed from core/src/test/resources/org/bouncycastle/crypto/tls/test/x509-server-key.pem)0
-rw-r--r--core/src/test/resources/org/spongycastle/crypto/tls/test/x509-server.pem (renamed from core/src/test/resources/org/bouncycastle/crypto/tls/test/x509-server.pem)0
-rw-r--r--core/src/test/resources/org/spongycastle/i18n/test/I18nTestMessages_de.properties (renamed from core/src/test/resources/org/bouncycastle/i18n/test/I18nTestMessages_de.properties)0
-rw-r--r--core/src/test/resources/org/spongycastle/i18n/test/I18nTestMessages_en.properties (renamed from core/src/test/resources/org/bouncycastle/i18n/test/I18nTestMessages_en.properties)0
-rw-r--r--core/src/test/resources/org/spongycastle/i18n/test/I18nUTF8TestMessages_de.properties (renamed from core/src/test/resources/org/bouncycastle/i18n/test/I18nUTF8TestMessages_de.properties)0
3467 files changed, 275181 insertions, 275181 deletions
diff --git a/core/src/main/j2me/java/math/BigInteger.java b/core/src/main/j2me/java/math/BigInteger.java
index 23732061..fb59fad4 100644
--- a/core/src/main/j2me/java/math/BigInteger.java
+++ b/core/src/main/j2me/java/math/BigInteger.java
@@ -3,7 +3,7 @@ package java.math;
import java.util.Random;
import java.util.Stack;
-import org.bouncycastle.util.Arrays;
+import org.spongycastle.util.Arrays;
public class BigInteger
{
diff --git a/core/src/main/j2me/java/security/SecureRandom.java b/core/src/main/j2me/java/security/SecureRandom.java
index 13ffde9b..a6a562a4 100644
--- a/core/src/main/j2me/java/security/SecureRandom.java
+++ b/core/src/main/j2me/java/security/SecureRandom.java
@@ -2,10 +2,10 @@ package java.security;
import java.util.Random;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.prng.RandomGenerator;
-import org.bouncycastle.crypto.prng.DigestRandomGenerator;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.prng.RandomGenerator;
+import org.spongycastle.crypto.prng.DigestRandomGenerator;
/**
* An implementation of SecureRandom specifically for the light-weight API, JDK
@@ -13,7 +13,7 @@ import org.bouncycastle.crypto.prng.DigestRandomGenerator;
* counter. Calling setSeed will always increase the entropy of the hash.
* <p>
* <b>Do not use this class without calling setSeed at least once</b>! There
- * are some example seed generators in the org.bouncycastle.prng package.
+ * are some example seed generators in the org.spongycastle.prng package.
*/
public class SecureRandom extends java.util.Random
{
diff --git a/core/src/main/j2me/org/bouncycastle/asn1/ASN1GeneralizedTime.java b/core/src/main/j2me/org/bouncycastle/asn1/ASN1GeneralizedTime.java
deleted file mode 100644
index 87058121..00000000
--- a/core/src/main/j2me/org/bouncycastle/asn1/ASN1GeneralizedTime.java
+++ /dev/null
@@ -1,260 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.util.Date;
-import java.util.TimeZone;
-
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Strings;
-
-/**
- * Generalized time object.
- */
-public class ASN1GeneralizedTime
- extends ASN1Primitive
-{
- private byte[] time;
-
- /**
- * return a generalized time from the passed in object
- *
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static ASN1GeneralizedTime getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ASN1GeneralizedTime)
- {
- return (ASN1GeneralizedTime)obj;
- }
-
- if (obj instanceof ASN1GeneralizedTime)
- {
- return new ASN1GeneralizedTime(((ASN1GeneralizedTime)obj).time);
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return a Generalized Time object from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static ASN1GeneralizedTime getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof ASN1GeneralizedTime)
- {
- return getInstance(o);
- }
- else
- {
- return new ASN1GeneralizedTime(((ASN1OctetString)o).getOctets());
- }
- }
-
- /**
- * The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z
- * for local time, or Z|[+|-]HHMM on the end, for difference between local
- * time and UTC time. The fractional second amount f must consist of at
- * least one number with trailing zeroes removed.
- *
- * @param time the time string.
- * @exception IllegalArgumentException if String is an illegal format.
- */
- public ASN1GeneralizedTime(
- String time)
- {
- char last = time.charAt(time.length() - 1);
- if (last != 'Z' && !(last >= 0 && last <= '9'))
- {
- if (time.indexOf('-') < 0 && time.indexOf('+') < 0)
- {
- throw new IllegalArgumentException("time needs to be in format YYYYMMDDHHMMSS[.f]Z or YYYYMMDDHHMMSS[.f][+-]HHMM");
- }
- }
-
- this.time = Strings.toByteArray(time);
- }
-
- /**
- * base constructer from a java.util.date object
- */
- public ASN1GeneralizedTime(
- Date time)
- {
- this.time = Strings.toByteArray(DateFormatter.getGeneralizedTimeDateString(time, false));
- }
-
- protected ASN1GeneralizedTime(Date date, boolean includeMillis)
- {
- this.time = Strings.toByteArray(DateFormatter.getGeneralizedTimeDateString(date, true));
- }
-
- ASN1GeneralizedTime(
- byte[] bytes)
- {
- this.time = bytes;
- }
-
- /**
- * Return the time.
- * @return The time string as it appeared in the encoded object.
- */
- public String getTimeString()
- {
- return Strings.fromByteArray(time);
- }
-
- /**
- * return the time - always in the form of
- * YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
- * <p>
- * Normally in a certificate we would expect "Z" rather than "GMT",
- * however adding the "GMT" means we can just use:
- * <pre>
- * dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
- * </pre>
- * To read in the time and get a date which is compatible with our local
- * time zone.
- */
- public String getTime()
- {
- String stime = Strings.fromByteArray(time);
-
- //
- // standardise the format.
- //
- if (stime.charAt(stime.length() - 1) == 'Z')
- {
- return stime.substring(0, stime.length() - 1) + "GMT+00:00";
- }
- else
- {
- int signPos = stime.length() - 5;
- char sign = stime.charAt(signPos);
- if (sign == '-' || sign == '+')
- {
- return stime.substring(0, signPos)
- + "GMT"
- + stime.substring(signPos, signPos + 3)
- + ":"
- + stime.substring(signPos + 3);
- }
- else
- {
- signPos = stime.length() - 3;
- sign = stime.charAt(signPos);
- if (sign == '-' || sign == '+')
- {
- return stime.substring(0, signPos)
- + "GMT"
- + stime.substring(signPos)
- + ":00";
- }
- }
- }
- return stime + calculateGMTOffset();
- }
-
- private String calculateGMTOffset()
- {
- String sign = "+";
- TimeZone timeZone = TimeZone.getDefault();
- int offset = timeZone.getRawOffset();
- if (offset < 0)
- {
- sign = "-";
- offset = -offset;
- }
- int hours = offset / (60 * 60 * 1000);
- int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000);
-
-// try
-// {
-// if (timeZone.useDaylightTime() && timeZone.inDaylightTime(this.getDate()))
-// {
-// hours += sign.equals("+") ? 1 : -1;
-// }
-// }
-// catch (ParseException e)
-// {
-// // we'll do our best and ignore daylight savings
-// }
-
- return "GMT" + sign + convert(hours) + ":" + convert(minutes);
- }
-
- private String convert(int time)
- {
- if (time < 10)
- {
- return "0" + time;
- }
-
- return Integer.toString(time);
- }
-
- public Date getDate()
- {
- return DateFormatter.fromGeneralizedTimeString(time);
- }
-
- private boolean hasFractionalSeconds()
- {
- for (int i = 0; i != time.length; i++)
- {
- if (time[i] == '.')
- {
- if (i == 14)
- {
- return true;
- }
- }
- }
- return false;
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- int length = time.length;
-
- return 1 + StreamUtil.calculateBodyLength(length) + length;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.writeEncoded(BERTags.GENERALIZED_TIME, time);
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof ASN1GeneralizedTime))
- {
- return false;
- }
-
- return Arrays.areEqual(time, ((ASN1GeneralizedTime)o).time);
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(time);
- }
-}
diff --git a/core/src/main/j2me/org/bouncycastle/asn1/ASN1UTCTime.java b/core/src/main/j2me/org/bouncycastle/asn1/ASN1UTCTime.java
deleted file mode 100644
index 0d18c6af..00000000
--- a/core/src/main/j2me/org/bouncycastle/asn1/ASN1UTCTime.java
+++ /dev/null
@@ -1,259 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.util.Date;
-
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Strings;
-
-/**
- * UTC time object.
- */
-public class ASN1UTCTime
- extends ASN1Primitive
-{
- private byte[] time;
-
- /**
- * return an UTC Time from the passed in object.
- *
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static ASN1UTCTime getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ASN1UTCTime)
- {
- return (ASN1UTCTime)obj;
- }
-
- if (obj instanceof ASN1UTCTime)
- {
- return new ASN1UTCTime(((ASN1UTCTime)obj).time);
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return an UTC Time from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static ASN1UTCTime getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Object o = obj.getObject();
-
- if (explicit || o instanceof ASN1UTCTime)
- {
- return getInstance(o);
- }
- else
- {
- return new ASN1UTCTime(((ASN1OctetString)o).getOctets());
- }
- }
-
- /**
- * The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
- * never encoded. When you're creating one of these objects from scratch, that's
- * what you want to use, otherwise we'll try to deal with whatever gets read from
- * the input stream... (this is why the input format is different from the getTime()
- * method output).
- * <p>
- *
- * @param time the time string.
- */
- public ASN1UTCTime(
- String time)
- {
- if (time.charAt(time.length() - 1) != 'Z')
- {
- // we accept this as a variation
- if (time.indexOf('-') < 0 && time.indexOf('+') < 0)
- {
- throw new IllegalArgumentException("time needs to be in format YYMMDDHHMMSSZ");
- }
- }
-
- this.time = Strings.toByteArray(time);
- }
-
- /**
- * base constructor from a java.util.date object
- */
- public ASN1UTCTime(
- Date time)
- {
- this.time = Strings.toByteArray(DateFormatter.toUTCDateString(time));
- }
-
- ASN1UTCTime(
- byte[] time)
- {
- this.time = time;
- }
-
- /**
- * return the time as a date based on whatever a 2 digit year will return. For
- * standardised processing use getAdjustedDate().
- *
- * @return the resulting date
- */
- public Date getDate()
- {
- return DateFormatter.adjustedFromUTCDateString(time);
- }
-
- /**
- * return the time as an adjusted date
- * in the range of 1950 - 2049.
- *
- * @return a date in the range of 1950 to 2049.
- */
- public Date getAdjustedDate()
- {
- return DateFormatter.adjustedFromUTCDateString(time);
- }
-
- /**
- * return the time - always in the form of
- * YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
- * <p>
- * Normally in a certificate we would expect "Z" rather than "GMT",
- * however adding the "GMT" means we can just use:
- * <pre>
- * dateF = new SimpleDateFormat("yyMMddHHmmssz");
- * </pre>
- * To read in the time and get a date which is compatible with our local
- * time zone.
- * <p>
- * <b>Note:</b> In some cases, due to the local date processing, this
- * may lead to unexpected results. If you want to stick the normal
- * convention of 1950 to 2049 use the getAdjustedTime() method.
- */
- public String getTime()
- {
- String stime = Strings.fromByteArray(time);
-
- //
- // standardise the format.
- //
- if (stime.indexOf('-') < 0 && stime.indexOf('+') < 0)
- {
- if (stime.length() == 11)
- {
- return stime.substring(0, 10) + "00GMT+00:00";
- }
- else
- {
- return stime.substring(0, 12) + "GMT+00:00";
- }
- }
- else
- {
- int index = stime.indexOf('-');
- if (index < 0)
- {
- index = stime.indexOf('+');
- }
- String d = stime;
-
- if (index == stime.length() - 3)
- {
- d += "00";
- }
-
- if (index == 10)
- {
- return d.substring(0, 10) + "00GMT" + d.substring(10, 13) + ":" + d.substring(13, 15);
- }
- else
- {
- return d.substring(0, 12) + "GMT" + d.substring(12, 15) + ":" + d.substring(15, 17);
- }
- }
- }
-
- /**
- * return a time string as an adjusted date with a 4 digit year. This goes
- * in the range of 1950 - 2049.
- */
- public String getAdjustedTime()
- {
- String d = this.getTime();
-
- if (d.charAt(0) < '5')
- {
- return "20" + d;
- }
- else
- {
- return "19" + d;
- }
- }
-
- /**
- * Return the time.
- * @return The time string as it appeared in the encoded object.
- */
- public String getTimeString()
- {
- return Strings.fromByteArray(time);
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- int length = time.length;
-
- return 1 + StreamUtil.calculateBodyLength(length) + length;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.write(BERTags.UTC_TIME);
-
- int length = time.length;
-
- out.writeLength(length);
-
- for (int i = 0; i != length; i++)
- {
- out.write((byte)time[i]);
- }
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof ASN1UTCTime))
- {
- return false;
- }
-
- return Arrays.areEqual(time, ((ASN1UTCTime)o).time);
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(time);
- }
-
- public String toString()
- {
- return Strings.fromByteArray(time);
- }
-}
diff --git a/core/src/main/j2me/org/bouncycastle/asn1/DERFactory.java b/core/src/main/j2me/org/bouncycastle/asn1/DERFactory.java
deleted file mode 100644
index 0dc0fc65..00000000
--- a/core/src/main/j2me/org/bouncycastle/asn1/DERFactory.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.bouncycastle.asn1;
-
-class DERFactory
-{
- static final ASN1Sequence EMPTY_SEQUENCE = new DERSequence();
- static final ASN1Set EMPTY_SET = new DERSet();
-
- static ASN1Sequence createSequence(ASN1EncodableVector v)
- {
- if (v.size() < 1)
- {
- return EMPTY_SEQUENCE;
- }
- else
- {
- return new DLSequence(v);
- }
- }
-
- static ASN1Set createSet(ASN1EncodableVector v)
- {
- if (v.size() < 1)
- {
- return EMPTY_SET;
- }
- else
- {
- return new DLSet(v);
- }
- }
-}
diff --git a/core/src/main/j2me/org/bouncycastle/asn1/DERGeneralizedTime.java b/core/src/main/j2me/org/bouncycastle/asn1/DERGeneralizedTime.java
deleted file mode 100644
index 6162da40..00000000
--- a/core/src/main/j2me/org/bouncycastle/asn1/DERGeneralizedTime.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.util.Date;
-
-public class DERGeneralizedTime
- extends ASN1GeneralizedTime
-{
- DERGeneralizedTime(byte[] bytes)
- {
- super(bytes);
- }
-
- public DERGeneralizedTime(Date date)
- {
- super(date);
- }
-
- public DERGeneralizedTime(Date date, boolean includeMillis)
- {
- super(date, includeMillis);
- }
-
- public DERGeneralizedTime(String time)
- {
- super(time);
- }
-}
diff --git a/core/src/main/j2me/org/bouncycastle/asn1/DERUTCTime.java b/core/src/main/j2me/org/bouncycastle/asn1/DERUTCTime.java
deleted file mode 100644
index 621febff..00000000
--- a/core/src/main/j2me/org/bouncycastle/asn1/DERUTCTime.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.util.Date;
-
-public class DERUTCTime
- extends ASN1UTCTime
-{
- DERUTCTime(byte[] bytes)
- {
- super(bytes);
- }
-
- public DERUTCTime(Date date)
- {
- super(date);
- }
-
- public DERUTCTime(String time)
- {
- super(time);
- }
-}
diff --git a/core/src/main/j2me/org/bouncycastle/asn1/DateFormatter.java b/core/src/main/j2me/org/bouncycastle/asn1/DateFormatter.java
deleted file mode 100644
index cd707740..00000000
--- a/core/src/main/j2me/org/bouncycastle/asn1/DateFormatter.java
+++ /dev/null
@@ -1,272 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.util.Calendar;
-import java.util.Date;
-import java.util.TimeZone;
-
-class DateFormatter
-{
- // YYMMDDHHMMSSZ
- static String toUTCDateString(Date date)
- {
- Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
-
- calendar.setTime(date);
-
- return format2Year(calendar.get(Calendar.YEAR)) + format2(calendar.get(Calendar.MONTH) + 1) + format2(calendar.get(Calendar.DAY_OF_MONTH))
- + format2(calendar.get(Calendar.HOUR_OF_DAY)) + format2(calendar.get(Calendar.MINUTE)) + format2(calendar.get(Calendar.SECOND)) + "Z";
- }
-
- static Date adjustedFromUTCDateString(byte[] date)
- {
- Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
-
- int year = toInt2(date, 0);
-
- if (year < 50)
- {
- year += 2000;
- }
- else
- {
- year += 1900;
- }
-
- calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
-
- calendar.set(Calendar.YEAR, year);
- calendar.set(Calendar.MONTH, toInt2(date, 2) - 1);
- calendar.set(Calendar.DAY_OF_MONTH, toInt2(date, 4));
- calendar.set(Calendar.HOUR_OF_DAY, toInt2(date, 6));
- calendar.set(Calendar.MINUTE, toInt2(date, 8));
-
- int tzChar = 10;
-
- if (isNumber(date, tzChar))
- {
- calendar.set(Calendar.SECOND, toInt2(date, 10));
- tzChar = 12;
- }
- else
- {
- calendar.set(Calendar.SECOND, 0);
- }
-
- calendar.set(Calendar.MILLISECOND, 0);
-
- if (date[tzChar] != 'Z')
- {
- int hoursOff = 0;
- int minutesOff = 0;
-
- hoursOff = toInt2(date, tzChar + 1) * 60 * 60 * 1000;
-
- if (date.length > tzChar + 3)
- {
- minutesOff = toInt2(date, tzChar + 3) * 60 * 1000;
- }
-
- if (date[tzChar] == '-')
- {
- return new Date(calendar.getTime().getTime() + hoursOff + minutesOff);
- }
- else
- {
- return new Date(calendar.getTime().getTime() - (hoursOff + minutesOff));
- }
- }
-
- return calendar.getTime();
- }
-
- static String getGeneralizedTimeDateString(Date date, boolean includeMillis)
- {
- Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
-
- calendar.setTime(date);
-
- String time = format4Year(calendar.get(Calendar.YEAR)) + format2(calendar.get(Calendar.MONTH) + 1) + format2(calendar.get(Calendar.DAY_OF_MONTH))
- + format2(calendar.get(Calendar.HOUR_OF_DAY)) + format2(calendar.get(Calendar.MINUTE)) + format2(calendar.get(Calendar.SECOND));
-
- if (includeMillis)
- {
- time += "." + format3(calendar.get(Calendar.MILLISECOND));
- }
-
- return time + "Z";
- }
-
- static Date fromGeneralizedTimeString(byte[] date)
- {
- Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
-
- int year = toInt4(date, 0);
-
- if (isLocalTime(date))
- {
- calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
- }
-
- calendar.set(Calendar.YEAR, year);
- calendar.set(Calendar.MONTH, toInt2(date, 4) - 1);
- calendar.set(Calendar.DAY_OF_MONTH, toInt2(date, 6));
- calendar.set(Calendar.HOUR_OF_DAY, toInt2(date, 8));
- calendar.set(Calendar.MINUTE, toInt2(date, 10));
-
- int tzChar = 12;
-
- if (isNumber(date, tzChar))
- {
- calendar.set(Calendar.SECOND, toInt2(date, 12));
- tzChar = 14;
- }
- else
- {
- calendar.set(Calendar.SECOND, 0);
- }
-
- if (tzChar != date.length && date[tzChar] == '.')
- {
- int millis = 0;
- tzChar++;
- if (isNumber(date, tzChar))
- {
- millis = (date[tzChar] - '0') * 100;
- tzChar++;
- }
- if (tzChar != date.length && isNumber(date, tzChar))
- {
- millis += (date[tzChar] - '0') * 10;
- tzChar++;
- }
- if (tzChar != date.length && isNumber(date, tzChar))
- {
- millis += (date[tzChar] - '0');
- tzChar++;
- }
- calendar.set(Calendar.MILLISECOND, millis);
- }
- else
- {
- calendar.set(Calendar.MILLISECOND, 0);
- }
-
- // skip nano-seconds
- while (tzChar != date.length && isNumber(date, tzChar))
- {
- tzChar++;
- }
-
- if (tzChar != date.length && date[tzChar] != 'Z')
- {
- int hoursOff = 0;
- int minutesOff = 0;
-
- hoursOff = toInt2(date, tzChar + 1) * 60 * 60 * 1000;
-
- if (date.length > tzChar + 3)
- {
- minutesOff = toInt2(date, tzChar + 3) * 60 * 1000;
- }
-
- if (date[tzChar] == '-')
- {
- return new Date(calendar.getTime().getTime() + hoursOff + minutesOff);
- }
- else
- {
- return new Date(calendar.getTime().getTime() - (hoursOff + minutesOff));
- }
- }
-
- return calendar.getTime();
- }
-
- private static String format2(int v)
- {
- if (v < 10)
- {
- return "0" + v;
- }
-
- return Integer.toString(v);
- }
-
- private static String format2Year(int v)
- {
- if (v > 2000)
- {
- v = v - 2000;
- }
- else
- {
- v = v - 1900;
- }
-
- return format2(v);
- }
-
- private static String format3(int v)
- {
- if (v < 10)
- {
- return "00" + v;
- }
-
- if (v < 100)
- {
- return "0" + v;
- }
-
- return Integer.toString(v);
- }
-
- private static String format4Year(int v)
- {
- if (v < 10)
- {
- return "000" + v;
- }
-
- if (v < 100)
- {
- return "00" + v;
- }
-
- if (v < 1000)
- {
- return "0" + v;
- }
-
- return Integer.toString(v);
- }
-
- private static boolean isNumber(byte[] input, int off)
- {
- byte b = input[off];
- return (b >= '0') && (b <= '9');
- }
-
- private static boolean isLocalTime(byte[] date)
- {
- for (int i = date.length - 1; i > date.length - 6; i--)
- {
- if (date[i] == 'Z' || date[i] == '-' || date[i] == '+')
- {
- return false;
- }
- }
-
- return true;
- }
-
- private static int toInt2(byte[] input, int off)
- {
- return (input[off] - '0') * 10 + (input[off + 1] - '0');
- }
-
- private static int toInt4(byte[] input, int off)
- {
- return toInt2(input, off) * 100 + toInt2(input, off + 2) ;
- }
-}
diff --git a/core/src/main/j2me/org/bouncycastle/asn1/StreamUtil.java b/core/src/main/j2me/org/bouncycastle/asn1/StreamUtil.java
deleted file mode 100644
index 67e3c208..00000000
--- a/core/src/main/j2me/org/bouncycastle/asn1/StreamUtil.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-class StreamUtil
-{
- /**
- * Find out possible longest length...
- *
- * @param in input stream of interest
- * @return length calculation or MAX_VALUE.
- */
- static int findLimit(InputStream in)
- {
- if (in instanceof LimitedInputStream)
- {
- return ((LimitedInputStream)in).getRemaining();
- }
- else if (in instanceof ASN1InputStream)
- {
- return ((ASN1InputStream)in).getLimit();
- }
- else if (in instanceof ByteArrayInputStream)
- {
- return ((ByteArrayInputStream)in).available();
- }
-
- return Integer.MAX_VALUE;
- }
-
- static int calculateBodyLength(
- int length)
- {
- int count = 1;
-
- if (length > 127)
- {
- int size = 1;
- int val = length;
-
- while ((val >>>= 8) != 0)
- {
- size++;
- }
-
- for (int i = (size - 1) * 8; i >= 0; i -= 8)
- {
- count++;
- }
- }
-
- return count;
- }
-
- static int calculateTagLength(int tagNo)
- throws IOException
- {
- int length = 1;
-
- if (tagNo >= 31)
- {
- if (tagNo < 128)
- {
- length++;
- }
- else
- {
- byte[] stack = new byte[5];
- int pos = stack.length;
-
- stack[--pos] = (byte)(tagNo & 0x7F);
-
- do
- {
- tagNo >>= 7;
- stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
- }
- while (tagNo > 127);
-
- length += stack.length - pos;
- }
- }
-
- return length;
- }
-}
diff --git a/core/src/main/j2me/org/bouncycastle/asn1/cms/Time.java b/core/src/main/j2me/org/bouncycastle/asn1/cms/Time.java
deleted file mode 100644
index 2477d6f2..00000000
--- a/core/src/main/j2me/org/bouncycastle/asn1/cms/Time.java
+++ /dev/null
@@ -1,122 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import java.util.Calendar;
-import java.util.Date;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1UTCTime;
-
-public class Time
- extends ASN1Object
- implements ASN1Choice
-{
- ASN1Primitive time;
-
- public static Time getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject()); // must be explicitly tagged
- }
-
- public Time(
- ASN1Primitive time)
- {
- if (!(time instanceof ASN1UTCTime)
- && !(time instanceof ASN1GeneralizedTime))
- {
- throw new IllegalArgumentException("unknown object passed to Time");
- }
-
- this.time = time;
- }
-
- /**
- * creates a time object from a given date - if the date is between 1950
- * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
- * is used.
- */
- public Time(
- Date date)
- {
- Calendar calendar = Calendar.getInstance();
-
- calendar.setTime(date);
-
- int year = calendar.get(Calendar.YEAR);
-
- if (year < 1950 || year > 2049)
- {
- time = new ASN1GeneralizedTime(date);
- }
- else
- {
- time = new ASN1UTCTime(date);
- }
- }
-
- public static Time getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof Time)
- {
- return (Time)obj;
- }
- else if (obj instanceof ASN1UTCTime)
- {
- return new Time((ASN1UTCTime)obj);
- }
- else if (obj instanceof ASN1GeneralizedTime)
- {
- return new Time((ASN1GeneralizedTime)obj);
- }
-
- throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
- }
-
- public String getTime()
- {
- if (time instanceof ASN1UTCTime)
- {
- return ((ASN1UTCTime)time).getAdjustedTime();
- }
- else
- {
- return ((ASN1GeneralizedTime)time).getTime();
- }
- }
-
- public Date getDate()
- {
- if (time instanceof ASN1UTCTime)
- {
- return ((ASN1UTCTime)time).getAdjustedDate();
- }
- else
- {
- return ((ASN1GeneralizedTime)time).getDate();
- }
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * Time ::= CHOICE {
- * utcTime UTCTime,
- * generalTime GeneralizedTime }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- return time;
- }
-
- public String toString()
- {
- return getTime();
- }
-}
diff --git a/core/src/main/j2me/org/bouncycastle/asn1/eac/PackedDate.java b/core/src/main/j2me/org/bouncycastle/asn1/eac/PackedDate.java
deleted file mode 100644
index 2259eb89..00000000
--- a/core/src/main/j2me/org/bouncycastle/asn1/eac/PackedDate.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package org.bouncycastle.asn1.eac;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * EAC encoding date object
- */
-public class PackedDate
-{
- private byte[] time;
-
- public PackedDate(
- String time)
- {
- this.time = convert(time);
- }
-
- private byte[] convert(String sTime)
- {
- char[] digs = sTime.toCharArray();
- byte[] date = new byte[6];
-
- for (int i = 0; i != 6; i++)
- {
- date[i] = (byte)(digs[i] - '0');
- }
-
- return date;
- }
-
- PackedDate(
- byte[] bytes)
- {
- this.time = bytes;
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(time);
- }
-
- public boolean equals(Object o)
- {
- if (!(o instanceof PackedDate))
- {
- return false;
- }
-
- PackedDate other = (PackedDate)o;
-
- return Arrays.areEqual(time, other.time);
- }
-
- public String toString()
- {
- char[] dateC = new char[time.length];
-
- for (int i = 0; i != dateC.length; i++)
- {
- dateC[i] = (char)((time[i] & 0xff) + '0');
- }
-
- return new String(dateC);
- }
-
- public byte[] getEncoding()
- {
- return time;
- }
-}
diff --git a/core/src/main/j2me/org/bouncycastle/asn1/x509/Time.java b/core/src/main/j2me/org/bouncycastle/asn1/x509/Time.java
deleted file mode 100644
index c723e8d2..00000000
--- a/core/src/main/j2me/org/bouncycastle/asn1/x509/Time.java
+++ /dev/null
@@ -1,122 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.util.Calendar;
-import java.util.Date;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1UTCTime;
-
-public class Time
- extends ASN1Object
- implements ASN1Choice
-{
- ASN1Primitive time;
-
- public static Time getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject()); // must be explicitly tagged
- }
-
- public Time(
- ASN1Primitive time)
- {
- if (!(time instanceof ASN1UTCTime)
- && !(time instanceof ASN1GeneralizedTime))
- {
- throw new IllegalArgumentException("unknown object passed to Time");
- }
-
- this.time = time;
- }
-
- /**
- * creates a time object from a given date - if the date is between 1950
- * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
- * is used.
- */
- public Time(
- Date date)
- {
- Calendar calendar = Calendar.getInstance();
-
- calendar.setTime(date);
-
- int year = calendar.get(Calendar.YEAR);
-
- if (year < 1950 || year > 2049)
- {
- time = new ASN1GeneralizedTime(date);
- }
- else
- {
- time = new ASN1UTCTime(date);
- }
- }
-
- public static Time getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof Time)
- {
- return (Time)obj;
- }
- else if (obj instanceof ASN1UTCTime)
- {
- return new Time((ASN1UTCTime)obj);
- }
- else if (obj instanceof ASN1GeneralizedTime)
- {
- return new Time((ASN1GeneralizedTime)obj);
- }
-
- throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
- }
-
- public String getTime()
- {
- if (time instanceof ASN1UTCTime)
- {
- return ((ASN1UTCTime)time).getAdjustedTime();
- }
- else
- {
- return ((ASN1GeneralizedTime)time).getTime();
- }
- }
-
- public Date getDate()
- {
- if (time instanceof ASN1UTCTime)
- {
- return ((ASN1UTCTime)time).getAdjustedDate();
- }
- else
- {
- return ((ASN1GeneralizedTime)time).getDate();
- }
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * Time ::= CHOICE {
- * utcTime UTCTime,
- * generalTime GeneralizedTime }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- return time;
- }
-
- public String toString()
- {
- return getTime();
- }
-}
diff --git a/core/src/main/j2me/org/bouncycastle/crypto/encodings/PKCS1Encoding.java b/core/src/main/j2me/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
deleted file mode 100644
index 76051c3f..00000000
--- a/core/src/main/j2me/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
+++ /dev/null
@@ -1,410 +0,0 @@
-package org.bouncycastle.crypto.encodings;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-
-/**
- * this does your basic PKCS 1 v1.5 padding - whether or not you should be using this
- * depends on your application - see PKCS1 Version 2 for details.
- */
-public class PKCS1Encoding
- implements AsymmetricBlockCipher
-{
- /**
- * some providers fail to include the leading zero in PKCS1 encoded blocks. If you need to
- * work with one of these set the system property org.bouncycastle.pkcs1.strict to false.
- * <p>
- * The system property is checked during construction of the encoding object, it is set to
- * true by default.
- * </p>
- */
- public static final String STRICT_LENGTH_ENABLED_PROPERTY = "org.bouncycastle.pkcs1.strict";
-
- private static final int HEADER_LENGTH = 10;
-
- private SecureRandom random;
- private AsymmetricBlockCipher engine;
- private boolean forEncryption;
- private boolean forPrivateKey;
- private boolean useStrictLength;
- private int pLen = -1;
- private byte[] fallback = null;
-
- /**
- * Basic constructor.
- * @param cipher
- */
- public PKCS1Encoding(
- AsymmetricBlockCipher cipher)
- {
- this.engine = cipher;
- this.useStrictLength = useStrict();
- }
-
- /**
- * Constructor for decryption with a fixed plaintext length.
- *
- * @param cipher The cipher to use for cryptographic operation.
- * @param pLen Length of the expected plaintext.
- */
- public PKCS1Encoding(
- AsymmetricBlockCipher cipher,
- int pLen)
- {
- this.engine = cipher;
- this.useStrictLength = useStrict();
- this.pLen = pLen;
- }
-
- /**
- * Constructor for decryption with a fixed plaintext length and a fallback
- * value that is returned, if the padding is incorrect.
- *
- * @param cipher
- * The cipher to use for cryptographic operation.
- * @param fallback
- * The fallback value, we don't to a arraycopy here.
- */
- public PKCS1Encoding(
- AsymmetricBlockCipher cipher,
- byte[] fallback)
- {
- this.engine = cipher;
- this.useStrictLength = useStrict();
- this.fallback = fallback;
- this.pLen = fallback.length;
- }
-
-
-
- //
- // for J2ME compatibility
- //
- private boolean useStrict()
- {
- // required if security manager has been installed.
- String strict = System.getProperty(STRICT_LENGTH_ENABLED_PROPERTY);
-
- return strict == null || strict.equals("true");
- }
-
- public AsymmetricBlockCipher getUnderlyingCipher()
- {
- return engine;
- }
-
- public void init(
- boolean forEncryption,
- CipherParameters param)
- {
- AsymmetricKeyParameter kParam;
-
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- this.random = rParam.getRandom();
- kParam = (AsymmetricKeyParameter)rParam.getParameters();
- }
- else
- {
- this.random = new SecureRandom();
- kParam = (AsymmetricKeyParameter)param;
- }
-
- engine.init(forEncryption, param);
-
- this.forPrivateKey = kParam.isPrivate();
- this.forEncryption = forEncryption;
- }
-
- public int getInputBlockSize()
- {
- int baseBlockSize = engine.getInputBlockSize();
-
- if (forEncryption)
- {
- return baseBlockSize - HEADER_LENGTH;
- }
- else
- {
- return baseBlockSize;
- }
- }
-
- public int getOutputBlockSize()
- {
- int baseBlockSize = engine.getOutputBlockSize();
-
- if (forEncryption)
- {
- return baseBlockSize;
- }
- else
- {
- return baseBlockSize - HEADER_LENGTH;
- }
- }
-
- public byte[] processBlock(
- byte[] in,
- int inOff,
- int inLen)
- throws InvalidCipherTextException
- {
- if (forEncryption)
- {
- return encodeBlock(in, inOff, inLen);
- }
- else
- {
- return decodeBlock(in, inOff, inLen);
- }
- }
-
- private byte[] encodeBlock(
- byte[] in,
- int inOff,
- int inLen)
- throws InvalidCipherTextException
- {
- if (inLen > getInputBlockSize())
- {
- throw new IllegalArgumentException("input data too large");
- }
-
- byte[] block = new byte[engine.getInputBlockSize()];
-
- if (forPrivateKey)
- {
- block[0] = 0x01; // type code 1
-
- for (int i = 1; i != block.length - inLen - 1; i++)
- {
- block[i] = (byte)0xFF;
- }
- }
- else
- {
- random.nextBytes(block); // random fill
-
- block[0] = 0x02; // type code 2
-
- //
- // a zero byte marks the end of the padding, so all
- // the pad bytes must be non-zero.
- //
- for (int i = 1; i != block.length - inLen - 1; i++)
- {
- while (block[i] == 0)
- {
- block[i] = (byte)random.nextInt();
- }
- }
- }
-
- block[block.length - inLen - 1] = 0x00; // mark the end of the padding
- System.arraycopy(in, inOff, block, block.length - inLen, inLen);
-
- return engine.processBlock(block, 0, block.length);
- }
-
- /**
- * Checks if the argument is a correctly PKCS#1.5 encoded Plaintext
- * for encryption.
- *
- * @param encoded The Plaintext.
- * @param pLen Expected length of the plaintext.
- * @return Either 0, if the encoding is correct, or -1, if it is incorrect.
- */
- private static int checkPkcs1Encoding(byte[] encoded, int pLen) {
- int correct = 0;
- /*
- * Check if the first two bytes are 0 2
- */
- correct |= (encoded[0] ^ 2);
-
- /*
- * Now the padding check, check for no 0 byte in the padding
- */
- int plen = encoded.length - (
- pLen /* Lenght of the PMS */
- + 1 /* Final 0-byte before PMS */
- );
-
- for (int i = 1; i < plen; i++) {
- int tmp = encoded[i];
- tmp |= tmp >> 1;
- tmp |= tmp >> 2;
- tmp |= tmp >> 4;
- correct |= (tmp & 1) - 1;
- }
-
- /*
- * Make sure the padding ends with a 0 byte.
- */
- correct |= encoded[encoded.length - (pLen +1)];
-
- /*
- * Return 0 or 1, depending on the result.
- */
- correct |= correct >> 1;
- correct |= correct >> 2;
- correct |= correct >> 4;
- return ~((correct & 1) - 1);
- }
-
-
- /**
- * Decode PKCS#1.5 encoding, and return a random value if the padding is not correct.
- *
- * @param in The encrypted block.
- * @param inOff Offset in the encrypted block.
- * @param inLen Length of the encrypted block.
- * //@param pLen Length of the desired output.
- * @return The plaintext without padding, or a random value if the padding was incorrect.
- *
- * @throws InvalidCipherTextException
- */
- private byte[] decodeBlockOrRandom(byte[] in, int inOff, int inLen)
- throws InvalidCipherTextException
- {
- if (!forPrivateKey)
- {
- throw new InvalidCipherTextException("sorry, this method is only for decryption, not for signing");
- }
-
- byte[] block = engine.processBlock(in, inOff, inLen);
- byte[] random = null;
- if (this.fallback == null)
- {
- random = new byte[this.pLen];
- this.random.nextBytes(random);
- }
- else
- {
- random = fallback;
- }
-
- /*
- * TODO: This is a potential dangerous side channel. However, you can
- * fix this by changing the RSA engine in a way, that it will always
- * return blocks of the same length and prepend them with 0 bytes if
- * needed.
- */
- if (block.length < getOutputBlockSize())
- {
- throw new InvalidCipherTextException("block truncated");
- }
-
- /*
- * TODO: Potential side channel. Fix it by making the engine always
- * return blocks of the correct length.
- */
- if (useStrictLength && block.length != engine.getOutputBlockSize())
- {
- throw new InvalidCipherTextException("block incorrect size");
- }
-
- /*
- * Check the padding.
- */
- int correct = PKCS1Encoding.checkPkcs1Encoding(block, this.pLen);
-
- /*
- * Now, to a constant time constant memory copy of the decrypted value
- * or the random value, depending on the validity of the padding.
- */
- byte[] result = new byte[this.pLen];
- for (int i = 0; i < this.pLen; i++)
- {
- result[i] = (byte)((block[i + (block.length - pLen)] & (~correct)) | (random[i] & correct));
- }
-
- return result;
- }
-
- /**
- * @exception InvalidCipherTextException if the decrypted block is not in PKCS1 format.
- */
- private byte[] decodeBlock(
- byte[] in,
- int inOff,
- int inLen)
- throws InvalidCipherTextException
- {
- /*
- * If the length of the expected plaintext is known, we use a constant-time decryption.
- * If the decryption fails, we return a random value.
- */
- if (this.pLen != -1) {
- return this.decodeBlockOrRandom(in, inOff, inLen);
- }
-
- byte[] block = engine.processBlock(in, inOff, inLen);
-
- if (block.length < getOutputBlockSize())
- {
- throw new InvalidCipherTextException("block truncated");
- }
-
- byte type = block[0];
-
- if (forPrivateKey)
- {
- if (type != 2)
- {
- throw new InvalidCipherTextException("unknown block type");
- }
- }
- else
- {
- if (type != 1)
- {
- throw new InvalidCipherTextException("unknown block type");
- }
- }
-
- if (useStrictLength && block.length != engine.getOutputBlockSize())
- {
- throw new InvalidCipherTextException("block incorrect size");
- }
-
- //
- // find and extract the message block.
- //
- int start;
-
- for (start = 1; start != block.length; start++)
- {
- byte pad = block[start];
-
- if (pad == 0)
- {
- break;
- }
- if (type == 1 && pad != (byte)0xff)
- {
- throw new InvalidCipherTextException("block padding incorrect");
- }
- }
-
- start++; // data should start at the next byte
-
- if (start > block.length || start < HEADER_LENGTH)
- {
- throw new InvalidCipherTextException("no data in block");
- }
-
- byte[] result = new byte[block.length - start];
-
- System.arraycopy(block, start, result, 0, result.length);
-
- return result;
- }
-}
diff --git a/core/src/main/j2me/org/bouncycastle/crypto/examples/MIDPTest.java b/core/src/main/j2me/org/bouncycastle/crypto/examples/MIDPTest.java
deleted file mode 100644
index 38f5ba47..00000000
--- a/core/src/main/j2me/org/bouncycastle/crypto/examples/MIDPTest.java
+++ /dev/null
@@ -1,177 +0,0 @@
-package org.bouncycastle.crypto.examples;
-
-import java.io.*;
-import java.lang.*;
-
-import javax.microedition.midlet.MIDlet;
-import javax.microedition.lcdui.*;
-
-import org.bouncycastle.util.test.*;
-import org.bouncycastle.util.encoders.*;
-
-import org.bouncycastle.crypto.*;
-import org.bouncycastle.crypto.paddings.*;
-import org.bouncycastle.crypto.engines.*;
-import org.bouncycastle.crypto.modes.*;
-import org.bouncycastle.crypto.params.*;
-
-/**
- * MIDP is a simple graphics application for the J2ME CLDC/MIDP.
- *
- * It has hardcoded values for the key and plain text. It also performs the
- * standard testing for the chosen cipher, and displays the results.
- *
- * This example shows how to use the light-weight API and a symmetric cipher.
- *
- */
-public class MIDPTest extends MIDlet
-{
- private Display d = null;
-
- private boolean doneEncrypt = false;
-
- private String key = "0123456789abcdef0123456789abcdef";
- private String plainText = "www.bouncycastle.org";
- private byte[] keyBytes = null;
- private byte[] cipherText = null;
- private BufferedBlockCipher cipher = null;
-
- private String[] cipherNames = {"DES", "DESede", "IDEA", "Rijndael", "Twofish"};
-
- private Form output = null;
-
- public void startApp()
- {
- Display.getDisplay(this).setCurrent(output);
- }
-
- public void pauseApp()
- {
-
- }
-
- public void destroyApp(boolean unconditional)
- {
-
- }
-
- public MIDPTest()
- {
- output = new Form("BouncyCastle");
- output.append("Key: " + key.substring(0, 7) + "...\n");
- output.append("In : " + plainText.substring(0, 7) + "...\n");
-
- cipherText = performEncrypt(Hex.decode(key.getBytes()), plainText);
- String ctS = new String(Hex.encode(cipherText));
-
- output.append("\nCT : " + ctS.substring(0, 7) + "...\n");
-
- String decryptText = performDecrypt(Hex.decode(key.getBytes()), cipherText);
-
- output.append("PT : " + decryptText.substring(0, 7) + "...\n");
-
- if (decryptText.compareTo(plainText) == 0)
- {
- output.append("Success");
- }
- else
- {
- output.append("Failure");
- message("[" + plainText + "]");
- message("[" + decryptText + "]");
- }
-
- }
-
- private byte[] performEncrypt(byte[] key, String plainText)
- {
- byte[] ptBytes = plainText.getBytes();
-
- cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(getEngineInstance()));
-
- String name = cipher.getUnderlyingCipher().getAlgorithmName();
- message("Using " + name);
-
- cipher.init(true, new KeyParameter(key));
-
- byte[] rv = new byte[cipher.getOutputSize(ptBytes.length)];
-
- int oLen = cipher.processBytes(ptBytes, 0, ptBytes.length, rv, 0);
- try
- {
- cipher.doFinal(rv, oLen);
- }
- catch (CryptoException ce)
- {
- message("Ooops, encrypt exception");
- status(ce.toString());
- }
- return rv;
- }
-
- private String performDecrypt(byte[] key, byte[] cipherText)
- {
- cipher.init(false, new KeyParameter(key));
-
- byte[] rv = new byte[cipher.getOutputSize(cipherText.length)];
-
- int oLen = cipher.processBytes(cipherText, 0, cipherText.length, rv, 0);
- try
- {
- cipher.doFinal(rv, oLen);
- }
- catch (CryptoException ce)
- {
- message("Ooops, decrypt exception");
- status(ce.toString());
- }
- return new String(rv).trim();
- }
-
- private int whichCipher()
- {
- return 4; // DES
- }
-
- private BlockCipher getEngineInstance()
- {
- // returns a block cipher according to the current
- // state of the radio button lists. This is only
- // done prior to encryption.
- BlockCipher rv = null;
-
- switch (whichCipher())
- {
- case 0 :
- rv = new DESEngine();
- break;
- case 1 :
- rv = new DESedeEngine();
- break;
- case 2 :
- rv = new IDEAEngine();
- break;
- case 3 :
- rv = new RijndaelEngine();
- break;
- case 4 :
- rv = new TwofishEngine();
- break;
- default :
- rv = new DESEngine();
- break;
- }
- return rv;
- }
-
- public void message(String s)
- {
- System.out.println("M:" + s);
- }
-
- public void status(String s)
- {
- System.out.println("S:" + s);
- }
-
-}
diff --git a/core/src/main/j2me/org/bouncycastle/crypto/examples/midp_test.jad b/core/src/main/j2me/org/bouncycastle/crypto/examples/midp_test.jad
deleted file mode 100644
index 8fa31947..00000000
--- a/core/src/main/j2me/org/bouncycastle/crypto/examples/midp_test.jad
+++ /dev/null
@@ -1,6 +0,0 @@
-MIDlet-1: MIDPTest, , org.bouncycastle.crypto.examples.MIDPTest
-MIDlet-Name: MIDPTest
-MIDlet-Jar-Size: 300000
-MIDlet-Jar-URL: midp_test.jar
-MIDlet-Vendor: The Legion of the Bouncy Castle
-MIDlet-Version: 1.0.0
diff --git a/core/src/main/j2me/org/bouncycastle/crypto/examples/midp_test.mf b/core/src/main/j2me/org/bouncycastle/crypto/examples/midp_test.mf
deleted file mode 100644
index 06b981a4..00000000
--- a/core/src/main/j2me/org/bouncycastle/crypto/examples/midp_test.mf
+++ /dev/null
@@ -1,7 +0,0 @@
-MIDlet-1: MIDPTTest, , org.bouncycastle.crypto.examples.MIDPTest
-MIDlet-Name: MIDPTest
-MIDlet-Version: 1.0.0
-MIDlet-Vendor: Jon Eaves
-Created-By: 1.3.1 (Sun Microsystems Inc.)
-MicroEdition-Configuration: CLDC-1.0
-MicroEdition-Profile: MIDP-1.0
diff --git a/core/src/main/j2me/org/bouncycastle/crypto/params/SkeinParameters.java b/core/src/main/j2me/org/bouncycastle/crypto/params/SkeinParameters.java
deleted file mode 100644
index 3e847bea..00000000
--- a/core/src/main/j2me/org/bouncycastle/crypto/params/SkeinParameters.java
+++ /dev/null
@@ -1,258 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-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);
- }
-
- /**
- * 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/core/src/main/j2me/org/bouncycastle/crypto/tls/OCSPStatusRequest.java b/core/src/main/j2me/org/bouncycastle/crypto/tls/OCSPStatusRequest.java
deleted file mode 100644
index 57219998..00000000
--- a/core/src/main/j2me/org/bouncycastle/crypto/tls/OCSPStatusRequest.java
+++ /dev/null
@@ -1,131 +0,0 @@
-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);
- output.write(buf.toByteArray());
- }
-
- 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 an {@link OCSPStatusRequest} from an {@link InputStream}.
- *
- * @param input
- * the {@link InputStream} to parse from.
- * @return an {@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/core/src/main/j2me/org/bouncycastle/crypto/tls/ServerNameList.java b/core/src/main/j2me/org/bouncycastle/crypto/tls/ServerNameList.java
deleted file mode 100644
index c44bb896..00000000
--- a/core/src/main/j2me/org/bouncycastle/crypto/tls/ServerNameList.java
+++ /dev/null
@@ -1,86 +0,0 @@
-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);
- output.write(buf.toByteArray());
- }
-
- /**
- * 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/core/src/main/j2me/org/bouncycastle/crypto/tls/UDPTransport.java b/core/src/main/j2me/org/bouncycastle/crypto/tls/UDPTransport.java
deleted file mode 100644
index ca8f6a73..00000000
--- a/core/src/main/j2me/org/bouncycastle/crypto/tls/UDPTransport.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-import javax.microedition.io.DatagramConnection;
-import javax.microedition.io.Datagram;
-
-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;
-
- protected final DatagramConnection socket;
- protected final int receiveLimit, sendLimit;
-
- public UDPTransport(DatagramConnection socket, int mtu)
- throws IOException
- {
- //
- // In 1.3 and earlier sockets were bound and connected during creation
- //
- //if (!socket.isBound() || !socket.isConnected())
- //{
- // throw new IllegalArgumentException("'socket' must be bound and connected");
- //}
-
- this.socket = socket;
-
- // NOTE: As of JDK 1.6, can use NetworkInterface.getMTU
-
- this.receiveLimit = mtu - MIN_IP_OVERHEAD - UDP_OVERHEAD;
- this.sendLimit = mtu - MAX_IP_OVERHEAD - UDP_OVERHEAD;
- }
-
- public int getReceiveLimit()
- {
- return receiveLimit;
- }
-
- public int getSendLimit()
- {
- // TODO[DTLS] Implement Path-MTU discovery?
- return sendLimit;
- }
-
- public int receive(byte[] buf, int off, int len, int waitMillis)
- throws IOException
- {
- //socket.setSoTimeout(waitMillis); -- not applicable
-
- if (off == 0)
- {
- Datagram packet = socket.newDatagram(buf, len);
- socket.receive(packet);
-
- return packet.getLength();
- }
- else
- {
- byte[] rv = new byte[len];
-
- Datagram packet = socket.newDatagram(rv, len);
- socket.receive(packet);
-
- System.arraycopy(rv, 0, buf, off, packet.getLength());
-
- return packet.getLength();
- }
- }
-
- public void send(byte[] buf, int off, int len)
- throws IOException
- {
- if (len > getSendLimit())
- {
- /*
- * RFC 4347 4.1.1. "If the application attempts to send a record larger than the MTU,
- * the DTLS implementation SHOULD generate an error, thus avoiding sending a packet
- * which will be fragmented."
- */
- // TODO Exception
- }
-
- if (off == 0)
- {
- Datagram packet = socket.newDatagram(buf, len);
- socket.send(packet);
- }
- else
- {
- byte[] data = new byte[len];
-
- System.arraycopy(buf, off, data, 0, len);
-
- Datagram packet = socket.newDatagram(data, len);
- socket.send(packet);
- }
- }
-
- public void close()
- throws IOException
- {
- socket.close();
- }
-}
diff --git a/core/src/main/j2me/org/bouncycastle/math/ec/LongArray.java b/core/src/main/j2me/org/bouncycastle/math/ec/LongArray.java
deleted file mode 100644
index b8522c16..00000000
--- a/core/src/main/j2me/org/bouncycastle/math/ec/LongArray.java
+++ /dev/null
@@ -1,2197 +0,0 @@
-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 isOne()
- {
- long[] a = m_ints;
- if (a[0] != 1L)
- {
- return false;
- }
- for (int i = 1; i < a.length; ++i)
- {
- if (a[i] != 0L)
- {
- return false;
- }
- }
- return true;
- }
-
- public boolean isZero()
- {
- long[] a = m_ints;
- 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) != 0L)
- {
- if ((a & 1L) != 0L)
- {
- long carry = addShiftedUp(c, cOff, b, 0, bLen, k);
- if (carry != 0L)
- {
- 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 a0 = A.m_ints[0];
- if (a0 == 1L)
- {
- return B;
- }
-
- /*
- * Fast path for small A, with performance dependent only on the number of set bits
- */
- long[] c0 = new long[cLen];
- multiplyWord(a0, B.m_ints, bLen, c0, 0);
-
- /*
- * Reduce the raw answer against the reduction coefficients
- */
- return reduceResult(c0, 0, cLen, m, ks);
- }
-
- /*
- * 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 a0 = A.m_ints[0];
- if (a0 == 1L)
- {
- return B;
- }
-
- /*
- * Fast path for small A, with performance dependent only on the number of set bits
- */
- long[] c0 = new long[cLen];
- multiplyWord(a0, B.m_ints, bLen, c0, 0);
-
- /*
- * Reduce the raw answer against the reduction coefficients
- */
- return reduceResult(c0, 0, cLen, m, ks);
- }
-
- /*
- * Determine if B will get bigger during shifting
- */
- int bMax = (bDeg + 7 + 63) >>> 6;
-
- /*
- * Lookup table for the offset of each B in the tables
- */
- int[] ti = new int[16];
-
- /*
- * Precompute table of all 4-bit products of B
- */
- long[] T0 = new long[bMax << 4];
- int tOff = bMax;
- ti[1] = tOff;
- System.arraycopy(B.m_ints, 0, T0, tOff, bLen);
- for (int i = 2; i < 16; ++i)
- {
- ti[i] = (tOff += bMax);
- if ((i & 1) == 0)
- {
- shiftUp(T0, tOff >>> 1, T0, tOff, bMax, 1);
- }
- else
- {
- add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax);
- }
- }
-
- /*
- * Second table with all 4-bit products of B shifted 4 bits
- */
- long[] T1 = new long[T0.length];
- shiftUp(T0, 0, T1, 0, T0.length, 4);
-// shiftUp(T0, bMax, T1, bMax, tOff, 4);
-
- long[] a = A.m_ints;
- long[] c = new long[cLen << 3];
-
- int MASK = 0xF;
-
- /*
- * Lopez-Dahab (Modified) algorithm
- */
-
- for (int aPos = 0; aPos < aLen; ++aPos)
- {
- long aVal = a[aPos];
- int cOff = aPos;
- for (;;)
- {
- int u = (int)aVal & MASK;
- aVal >>>= 4;
- int v = (int)aVal & MASK;
- addBoth(c, cOff, T0, ti[u], T1, ti[v], bMax);
- aVal >>>= 4;
- if (aVal == 0L)
- {
- break;
- }
- cOff += cLen;
- }
- }
-
- {
- int cOff = c.length;
- while ((cOff -= cLen) != 0)
- {
- addShiftedUp(c, cOff - cLen, c, cOff, cLen, 8);
- }
- }
-
- /*
- * Finally the raw answer is collected, reduce it against the reduction coefficients
- */
- return reduceResult(c, 0, cLen, m, ks);
- }
-
- 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 a0 = A.m_ints[0];
- if (a0 == 1L)
- {
- return B;
- }
-
- /*
- * Fast path for small A, with performance dependent only on the number of set bits
- */
- long[] c0 = new long[cLen];
- multiplyWord(a0, B.m_ints, bLen, c0, 0);
-
- /*
- * Reduce the raw answer against the reduction coefficients
- */
- return reduceResult(c0, 0, cLen, m, ks);
- }
-
- // 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);
- }
-
- public LongArray modReduce(int m, int[] ks)
- {
- long[] buf = Arrays.clone(m_ints);
- int rLen = reduceInPlace(buf, 0, buf.length, m, ks);
- return new LongArray(buf, 0, rLen);
- }
-
- public LongArray multiply(LongArray other, int m, int[] ks)
- {
- /*
- * Find out the degree of each argument and handle the zero cases
- */
- int aDeg = degree();
- if (aDeg == 0)
- {
- return this;
- }
- int bDeg = other.degree();
- if (bDeg == 0)
- {
- return other;
- }
-
- /*
- * Swap if necessary so that A is the smaller argument
- */
- LongArray A = this, B = other;
- if (aDeg > bDeg)
- {
- A = other; B = this;
- int tmp = aDeg; aDeg = bDeg; bDeg = tmp;
- }
-
- /*
- * Establish the word lengths of the arguments and result
- */
- int aLen = (aDeg + 63) >>> 6;
- int bLen = (bDeg + 63) >>> 6;
- int cLen = (aDeg + bDeg + 62) >>> 6;
-
- if (aLen == 1)
- {
- long a0 = A.m_ints[0];
- if (a0 == 1L)
- {
- return B;
- }
-
- /*
- * Fast path for small A, with performance dependent only on the number of set bits
- */
- long[] c0 = new long[cLen];
- multiplyWord(a0, B.m_ints, bLen, c0, 0);
-
- /*
- * Reduce the raw answer against the reduction coefficients
- */
-// return reduceResult(c0, 0, cLen, m, ks);
- return new LongArray(c0, 0, cLen);
- }
-
- /*
- * Determine if B will get bigger during shifting
- */
- int bMax = (bDeg + 7 + 63) >>> 6;
-
- /*
- * Lookup table for the offset of each B in the tables
- */
- int[] ti = new int[16];
-
- /*
- * Precompute table of all 4-bit products of B
- */
- long[] T0 = new long[bMax << 4];
- int tOff = bMax;
- ti[1] = tOff;
- System.arraycopy(B.m_ints, 0, T0, tOff, bLen);
- for (int i = 2; i < 16; ++i)
- {
- ti[i] = (tOff += bMax);
- if ((i & 1) == 0)
- {
- shiftUp(T0, tOff >>> 1, T0, tOff, bMax, 1);
- }
- else
- {
- add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax);
- }
- }
-
- /*
- * Second table with all 4-bit products of B shifted 4 bits
- */
- long[] T1 = new long[T0.length];
- shiftUp(T0, 0, T1, 0, T0.length, 4);
-// shiftUp(T0, bMax, T1, bMax, tOff, 4);
-
- long[] a = A.m_ints;
- long[] c = new long[cLen << 3];
-
- int MASK = 0xF;
-
- /*
- * Lopez-Dahab (Modified) algorithm
- */
-
- for (int aPos = 0; aPos < aLen; ++aPos)
- {
- long aVal = a[aPos];
- int cOff = aPos;
- for (;;)
- {
- int u = (int)aVal & MASK;
- aVal >>>= 4;
- int v = (int)aVal & MASK;
- addBoth(c, cOff, T0, ti[u], T1, ti[v], bMax);
- aVal >>>= 4;
- if (aVal == 0L)
- {
- break;
- }
- cOff += cLen;
- }
- }
-
- {
- int cOff = c.length;
- while ((cOff -= cLen) != 0)
- {
- addShiftedUp(c, cOff - cLen, c, cOff, cLen, 8);
- }
- }
-
- /*
- * Finally the raw answer is collected, reduce it against the reduction coefficients
- */
-// return reduceResult(c, 0, cLen, m, ks);
- return new LongArray(c, 0, cLen);
- }
-
- public void reduce(int m, int[] ks)
- {
- long[] buf = m_ints;
- int rLen = reduceInPlace(buf, 0, buf.length, m, ks);
- if (rLen < buf.length)
- {
- m_ints = new long[rLen];
- System.arraycopy(buf, 0, m_ints, 0, rLen);
- }
- }
-
- private static LongArray reduceResult(long[] buf, int off, int len, int m, int[] ks)
- {
- int rLen = reduceInPlace(buf, off, len, m, ks);
- 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 n = bit - m;
- int j = ks.length;
- while (--j >= 0)
- {
- flipBit(buf, off, ks[j] + n);
- }
- flipBit(buf, off, n);
- }
-
- 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));
- }
-
- public LongArray modSquareN(int n, int m, int[] ks)
- {
- int len = getUsedLength();
- if (len == 0)
- {
- return this;
- }
-
- int mLen = (m + 63) >>> 6;
- long[] r = new long[mLen << 1];
- System.arraycopy(m_ints, 0, r, 0, len);
-
- while (--n >= 0)
- {
- squareInPlace(r, len, m, ks);
- len = reduceInPlace(r, 0, r.length, m, ks);
- }
-
- return new LongArray(r, 0, len);
- }
-
- public LongArray square(int m, int[] ks)
- {
- int len = getUsedLength();
- if (len == 0)
- {
- return this;
- }
-
- int _2len = len << 1;
- long[] r = new long[_2len];
-
- int pos = 0;
- while (pos < _2len)
- {
- long mi = m_ints[pos >>> 1];
- r[pos++] = interleave2_32to64((int)mi);
- r[pos++] = interleave2_32to64((int)(mi >>> 32));
- }
-
- return new LongArray(r, 0, r.length);
- }
-
- private static void squareInPlace(long[] x, int xLen, int m, int[] ks)
- {
- int pos = xLen << 1;
- while (--xLen >= 0)
- {
- long xVal = x[xLen];
- x[--pos] = interleave2_32to64((int)(xVal >>> 32));
- x[--pos] = interleave2_32to64((int)xVal);
- }
- }
-
- private static void interleave(long[] x, int xOff, long[] z, int zOff, int count, int width)
- {
- 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 == 0)
- {
- throw new IllegalStateException();
- }
- 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();
-*/
- return "not supported";
- }
-}
diff --git a/core/src/main/j2me/org/bouncycastle/util/Integers.java b/core/src/main/j2me/org/bouncycastle/util/Integers.java
deleted file mode 100644
index e461a77c..00000000
--- a/core/src/main/j2me/org/bouncycastle/util/Integers.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.bouncycastle.util;
-
-public class Integers
-{
- public static int rotateLeft(int i, int distance)
- {
- return (i << distance) ^ (i >>> -distance);
- }
-
- public static int rotateRight(int i, int distance)
- {
- return (i >>> distance) ^ (i << -distance);
- }
-
- public static Integer valueOf(int value)
- {
- return new Integer(value);
- }
-}
diff --git a/core/src/main/j2me/org/bouncycastle/util/Selector.java b/core/src/main/j2me/org/bouncycastle/util/Selector.java
deleted file mode 100644
index 79a1dd82..00000000
--- a/core/src/main/j2me/org/bouncycastle/util/Selector.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.bouncycastle.util;
-
-public interface Selector
-{
- boolean match(Object obj);
-
- Object clone();
-}
diff --git a/core/src/main/j2me/org/bouncycastle/util/Shorts.java b/core/src/main/j2me/org/bouncycastle/util/Shorts.java
deleted file mode 100644
index 71f04fd0..00000000
--- a/core/src/main/j2me/org/bouncycastle/util/Shorts.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.bouncycastle.util;
-
-public class Shorts
-{
- public static Short valueOf(short value)
- {
- return new Short(value);
- }
-}
diff --git a/core/src/main/j2me/org/bouncycastle/util/Times.java b/core/src/main/j2me/org/bouncycastle/util/Times.java
deleted file mode 100644
index d21518fa..00000000
--- a/core/src/main/j2me/org/bouncycastle/util/Times.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.bouncycastle.util;
-
-public final class Times
-{
- private static long NANOS_PER_MILLI = 1000000L;
-
- public static long nanoTime()
- {
- return NANOS_PER_MILLI * System.currentTimeMillis();
- }
-}
diff --git a/core/src/main/j2me/org/bouncycastle/util/test/SimpleTest.java b/core/src/main/j2me/org/bouncycastle/util/test/SimpleTest.java
deleted file mode 100644
index eb1fdbee..00000000
--- a/core/src/main/j2me/org/bouncycastle/util/test/SimpleTest.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package org.bouncycastle.util.test;
-
-import java.io.PrintStream;
-
-import org.bouncycastle.util.Arrays;
-
-public abstract class SimpleTest
- implements Test
-{
- public abstract String getName();
-
- private TestResult success()
- {
- return SimpleTestResult.successful(this, "Okay");
- }
-
- protected void fail(
- String message)
- {
- throw new TestFailedException(SimpleTestResult.failed(this, message));
- }
-
- protected void fail(
- String message,
- Throwable throwable)
- {
- throw new TestFailedException(SimpleTestResult.failed(this, message, throwable));
- }
-
- protected void fail(
- String message,
- Object expected,
- Object found)
- {
- throw new TestFailedException(SimpleTestResult.failed(this, message, expected, found));
- }
-
- protected boolean areEqual(
- byte[] a,
- byte[] b)
- {
- return Arrays.areEqual(a, b);
- }
-
- public TestResult perform()
- {
- try
- {
- performTest();
-
- return success();
- }
- catch (TestFailedException e)
- {
- return e.getResult();
- }
- catch (Exception e)
- {
- return SimpleTestResult.failed(this, "Exception: " + e, e);
- }
- }
-
- protected static void runTest(
- Test test)
- {
- runTest(test, System.out);
- }
-
- protected static void runTest(
- Test test,
- PrintStream out)
- {
- TestResult result = test.perform();
-
- out.println(result.toString());
- if (result.getException() != null)
- {
- result.getException().printStackTrace();
- }
- }
-
- public abstract void performTest()
- throws Exception;
-}
diff --git a/core/src/main/j2me/org/spongycastle/asn1/ASN1GeneralizedTime.java b/core/src/main/j2me/org/spongycastle/asn1/ASN1GeneralizedTime.java
new file mode 100644
index 00000000..919b0f6e
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/asn1/ASN1GeneralizedTime.java
@@ -0,0 +1,260 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Strings;
+
+/**
+ * Generalized time object.
+ */
+public class ASN1GeneralizedTime
+ extends ASN1Primitive
+{
+ private byte[] time;
+
+ /**
+ * return a generalized time from the passed in object
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static ASN1GeneralizedTime getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1GeneralizedTime)
+ {
+ return (ASN1GeneralizedTime)obj;
+ }
+
+ if (obj instanceof ASN1GeneralizedTime)
+ {
+ return new ASN1GeneralizedTime(((ASN1GeneralizedTime)obj).time);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return a Generalized Time object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static ASN1GeneralizedTime getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof ASN1GeneralizedTime)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new ASN1GeneralizedTime(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ /**
+ * The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z
+ * for local time, or Z|[+|-]HHMM on the end, for difference between local
+ * time and UTC time. The fractional second amount f must consist of at
+ * least one number with trailing zeroes removed.
+ *
+ * @param time the time string.
+ * @exception IllegalArgumentException if String is an illegal format.
+ */
+ public ASN1GeneralizedTime(
+ String time)
+ {
+ char last = time.charAt(time.length() - 1);
+ if (last != 'Z' && !(last >= 0 && last <= '9'))
+ {
+ if (time.indexOf('-') < 0 && time.indexOf('+') < 0)
+ {
+ throw new IllegalArgumentException("time needs to be in format YYYYMMDDHHMMSS[.f]Z or YYYYMMDDHHMMSS[.f][+-]HHMM");
+ }
+ }
+
+ this.time = Strings.toByteArray(time);
+ }
+
+ /**
+ * base constructer from a java.util.date object
+ */
+ public ASN1GeneralizedTime(
+ Date time)
+ {
+ this.time = Strings.toByteArray(DateFormatter.getGeneralizedTimeDateString(time, false));
+ }
+
+ protected ASN1GeneralizedTime(Date date, boolean includeMillis)
+ {
+ this.time = Strings.toByteArray(DateFormatter.getGeneralizedTimeDateString(date, true));
+ }
+
+ ASN1GeneralizedTime(
+ byte[] bytes)
+ {
+ this.time = bytes;
+ }
+
+ /**
+ * Return the time.
+ * @return The time string as it appeared in the encoded object.
+ */
+ public String getTimeString()
+ {
+ return Strings.fromByteArray(time);
+ }
+
+ /**
+ * return the time - always in the form of
+ * YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
+ * <p>
+ * Normally in a certificate we would expect "Z" rather than "GMT",
+ * however adding the "GMT" means we can just use:
+ * <pre>
+ * dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
+ * </pre>
+ * To read in the time and get a date which is compatible with our local
+ * time zone.
+ */
+ public String getTime()
+ {
+ String stime = Strings.fromByteArray(time);
+
+ //
+ // standardise the format.
+ //
+ if (stime.charAt(stime.length() - 1) == 'Z')
+ {
+ return stime.substring(0, stime.length() - 1) + "GMT+00:00";
+ }
+ else
+ {
+ int signPos = stime.length() - 5;
+ char sign = stime.charAt(signPos);
+ if (sign == '-' || sign == '+')
+ {
+ return stime.substring(0, signPos)
+ + "GMT"
+ + stime.substring(signPos, signPos + 3)
+ + ":"
+ + stime.substring(signPos + 3);
+ }
+ else
+ {
+ signPos = stime.length() - 3;
+ sign = stime.charAt(signPos);
+ if (sign == '-' || sign == '+')
+ {
+ return stime.substring(0, signPos)
+ + "GMT"
+ + stime.substring(signPos)
+ + ":00";
+ }
+ }
+ }
+ return stime + calculateGMTOffset();
+ }
+
+ private String calculateGMTOffset()
+ {
+ String sign = "+";
+ TimeZone timeZone = TimeZone.getDefault();
+ int offset = timeZone.getRawOffset();
+ if (offset < 0)
+ {
+ sign = "-";
+ offset = -offset;
+ }
+ int hours = offset / (60 * 60 * 1000);
+ int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000);
+
+// try
+// {
+// if (timeZone.useDaylightTime() && timeZone.inDaylightTime(this.getDate()))
+// {
+// hours += sign.equals("+") ? 1 : -1;
+// }
+// }
+// catch (ParseException e)
+// {
+// // we'll do our best and ignore daylight savings
+// }
+
+ return "GMT" + sign + convert(hours) + ":" + convert(minutes);
+ }
+
+ private String convert(int time)
+ {
+ if (time < 10)
+ {
+ return "0" + time;
+ }
+
+ return Integer.toString(time);
+ }
+
+ public Date getDate()
+ {
+ return DateFormatter.fromGeneralizedTimeString(time);
+ }
+
+ private boolean hasFractionalSeconds()
+ {
+ for (int i = 0; i != time.length; i++)
+ {
+ if (time[i] == '.')
+ {
+ if (i == 14)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ int length = time.length;
+
+ return 1 + StreamUtil.calculateBodyLength(length) + length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.GENERALIZED_TIME, time);
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1GeneralizedTime))
+ {
+ return false;
+ }
+
+ return Arrays.areEqual(time, ((ASN1GeneralizedTime)o).time);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(time);
+ }
+}
diff --git a/core/src/main/j2me/org/spongycastle/asn1/ASN1UTCTime.java b/core/src/main/j2me/org/spongycastle/asn1/ASN1UTCTime.java
new file mode 100644
index 00000000..271a2cdc
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/asn1/ASN1UTCTime.java
@@ -0,0 +1,259 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.util.Date;
+
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Strings;
+
+/**
+ * UTC time object.
+ */
+public class ASN1UTCTime
+ extends ASN1Primitive
+{
+ private byte[] time;
+
+ /**
+ * return an UTC Time from the passed in object.
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static ASN1UTCTime getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1UTCTime)
+ {
+ return (ASN1UTCTime)obj;
+ }
+
+ if (obj instanceof ASN1UTCTime)
+ {
+ return new ASN1UTCTime(((ASN1UTCTime)obj).time);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an UTC Time from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static ASN1UTCTime getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Object o = obj.getObject();
+
+ if (explicit || o instanceof ASN1UTCTime)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new ASN1UTCTime(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ /**
+ * The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
+ * never encoded. When you're creating one of these objects from scratch, that's
+ * what you want to use, otherwise we'll try to deal with whatever gets read from
+ * the input stream... (this is why the input format is different from the getTime()
+ * method output).
+ * <p>
+ *
+ * @param time the time string.
+ */
+ public ASN1UTCTime(
+ String time)
+ {
+ if (time.charAt(time.length() - 1) != 'Z')
+ {
+ // we accept this as a variation
+ if (time.indexOf('-') < 0 && time.indexOf('+') < 0)
+ {
+ throw new IllegalArgumentException("time needs to be in format YYMMDDHHMMSSZ");
+ }
+ }
+
+ this.time = Strings.toByteArray(time);
+ }
+
+ /**
+ * base constructor from a java.util.date object
+ */
+ public ASN1UTCTime(
+ Date time)
+ {
+ this.time = Strings.toByteArray(DateFormatter.toUTCDateString(time));
+ }
+
+ ASN1UTCTime(
+ byte[] time)
+ {
+ this.time = time;
+ }
+
+ /**
+ * return the time as a date based on whatever a 2 digit year will return. For
+ * standardised processing use getAdjustedDate().
+ *
+ * @return the resulting date
+ */
+ public Date getDate()
+ {
+ return DateFormatter.adjustedFromUTCDateString(time);
+ }
+
+ /**
+ * return the time as an adjusted date
+ * in the range of 1950 - 2049.
+ *
+ * @return a date in the range of 1950 to 2049.
+ */
+ public Date getAdjustedDate()
+ {
+ return DateFormatter.adjustedFromUTCDateString(time);
+ }
+
+ /**
+ * return the time - always in the form of
+ * YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
+ * <p>
+ * Normally in a certificate we would expect "Z" rather than "GMT",
+ * however adding the "GMT" means we can just use:
+ * <pre>
+ * dateF = new SimpleDateFormat("yyMMddHHmmssz");
+ * </pre>
+ * To read in the time and get a date which is compatible with our local
+ * time zone.
+ * <p>
+ * <b>Note:</b> In some cases, due to the local date processing, this
+ * may lead to unexpected results. If you want to stick the normal
+ * convention of 1950 to 2049 use the getAdjustedTime() method.
+ */
+ public String getTime()
+ {
+ String stime = Strings.fromByteArray(time);
+
+ //
+ // standardise the format.
+ //
+ if (stime.indexOf('-') < 0 && stime.indexOf('+') < 0)
+ {
+ if (stime.length() == 11)
+ {
+ return stime.substring(0, 10) + "00GMT+00:00";
+ }
+ else
+ {
+ return stime.substring(0, 12) + "GMT+00:00";
+ }
+ }
+ else
+ {
+ int index = stime.indexOf('-');
+ if (index < 0)
+ {
+ index = stime.indexOf('+');
+ }
+ String d = stime;
+
+ if (index == stime.length() - 3)
+ {
+ d += "00";
+ }
+
+ if (index == 10)
+ {
+ return d.substring(0, 10) + "00GMT" + d.substring(10, 13) + ":" + d.substring(13, 15);
+ }
+ else
+ {
+ return d.substring(0, 12) + "GMT" + d.substring(12, 15) + ":" + d.substring(15, 17);
+ }
+ }
+ }
+
+ /**
+ * return a time string as an adjusted date with a 4 digit year. This goes
+ * in the range of 1950 - 2049.
+ */
+ public String getAdjustedTime()
+ {
+ String d = this.getTime();
+
+ if (d.charAt(0) < '5')
+ {
+ return "20" + d;
+ }
+ else
+ {
+ return "19" + d;
+ }
+ }
+
+ /**
+ * Return the time.
+ * @return The time string as it appeared in the encoded object.
+ */
+ public String getTimeString()
+ {
+ return Strings.fromByteArray(time);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ int length = time.length;
+
+ return 1 + StreamUtil.calculateBodyLength(length) + length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.write(BERTags.UTC_TIME);
+
+ int length = time.length;
+
+ out.writeLength(length);
+
+ for (int i = 0; i != length; i++)
+ {
+ out.write((byte)time[i]);
+ }
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1UTCTime))
+ {
+ return false;
+ }
+
+ return Arrays.areEqual(time, ((ASN1UTCTime)o).time);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(time);
+ }
+
+ public String toString()
+ {
+ return Strings.fromByteArray(time);
+ }
+}
diff --git a/core/src/main/j2me/org/spongycastle/asn1/DERFactory.java b/core/src/main/j2me/org/spongycastle/asn1/DERFactory.java
new file mode 100644
index 00000000..c002ef6d
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/asn1/DERFactory.java
@@ -0,0 +1,31 @@
+package org.spongycastle.asn1;
+
+class DERFactory
+{
+ static final ASN1Sequence EMPTY_SEQUENCE = new DERSequence();
+ static final ASN1Set EMPTY_SET = new DERSet();
+
+ static ASN1Sequence createSequence(ASN1EncodableVector v)
+ {
+ if (v.size() < 1)
+ {
+ return EMPTY_SEQUENCE;
+ }
+ else
+ {
+ return new DLSequence(v);
+ }
+ }
+
+ static ASN1Set createSet(ASN1EncodableVector v)
+ {
+ if (v.size() < 1)
+ {
+ return EMPTY_SET;
+ }
+ else
+ {
+ return new DLSet(v);
+ }
+ }
+}
diff --git a/core/src/main/j2me/org/spongycastle/asn1/DERGeneralizedTime.java b/core/src/main/j2me/org/spongycastle/asn1/DERGeneralizedTime.java
new file mode 100644
index 00000000..51eee45e
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/asn1/DERGeneralizedTime.java
@@ -0,0 +1,27 @@
+package org.spongycastle.asn1;
+
+import java.util.Date;
+
+public class DERGeneralizedTime
+ extends ASN1GeneralizedTime
+{
+ DERGeneralizedTime(byte[] bytes)
+ {
+ super(bytes);
+ }
+
+ public DERGeneralizedTime(Date date)
+ {
+ super(date);
+ }
+
+ public DERGeneralizedTime(Date date, boolean includeMillis)
+ {
+ super(date, includeMillis);
+ }
+
+ public DERGeneralizedTime(String time)
+ {
+ super(time);
+ }
+}
diff --git a/core/src/main/j2me/org/spongycastle/asn1/DERUTCTime.java b/core/src/main/j2me/org/spongycastle/asn1/DERUTCTime.java
new file mode 100644
index 00000000..4b0379b5
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/asn1/DERUTCTime.java
@@ -0,0 +1,22 @@
+package org.spongycastle.asn1;
+
+import java.util.Date;
+
+public class DERUTCTime
+ extends ASN1UTCTime
+{
+ DERUTCTime(byte[] bytes)
+ {
+ super(bytes);
+ }
+
+ public DERUTCTime(Date date)
+ {
+ super(date);
+ }
+
+ public DERUTCTime(String time)
+ {
+ super(time);
+ }
+}
diff --git a/core/src/main/j2me/org/spongycastle/asn1/DateFormatter.java b/core/src/main/j2me/org/spongycastle/asn1/DateFormatter.java
new file mode 100644
index 00000000..7201a2a4
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/asn1/DateFormatter.java
@@ -0,0 +1,272 @@
+package org.spongycastle.asn1;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+class DateFormatter
+{
+ // YYMMDDHHMMSSZ
+ static String toUTCDateString(Date date)
+ {
+ Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+
+ calendar.setTime(date);
+
+ return format2Year(calendar.get(Calendar.YEAR)) + format2(calendar.get(Calendar.MONTH) + 1) + format2(calendar.get(Calendar.DAY_OF_MONTH))
+ + format2(calendar.get(Calendar.HOUR_OF_DAY)) + format2(calendar.get(Calendar.MINUTE)) + format2(calendar.get(Calendar.SECOND)) + "Z";
+ }
+
+ static Date adjustedFromUTCDateString(byte[] date)
+ {
+ Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+
+ int year = toInt2(date, 0);
+
+ if (year < 50)
+ {
+ year += 2000;
+ }
+ else
+ {
+ year += 1900;
+ }
+
+ calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
+
+ calendar.set(Calendar.YEAR, year);
+ calendar.set(Calendar.MONTH, toInt2(date, 2) - 1);
+ calendar.set(Calendar.DAY_OF_MONTH, toInt2(date, 4));
+ calendar.set(Calendar.HOUR_OF_DAY, toInt2(date, 6));
+ calendar.set(Calendar.MINUTE, toInt2(date, 8));
+
+ int tzChar = 10;
+
+ if (isNumber(date, tzChar))
+ {
+ calendar.set(Calendar.SECOND, toInt2(date, 10));
+ tzChar = 12;
+ }
+ else
+ {
+ calendar.set(Calendar.SECOND, 0);
+ }
+
+ calendar.set(Calendar.MILLISECOND, 0);
+
+ if (date[tzChar] != 'Z')
+ {
+ int hoursOff = 0;
+ int minutesOff = 0;
+
+ hoursOff = toInt2(date, tzChar + 1) * 60 * 60 * 1000;
+
+ if (date.length > tzChar + 3)
+ {
+ minutesOff = toInt2(date, tzChar + 3) * 60 * 1000;
+ }
+
+ if (date[tzChar] == '-')
+ {
+ return new Date(calendar.getTime().getTime() + hoursOff + minutesOff);
+ }
+ else
+ {
+ return new Date(calendar.getTime().getTime() - (hoursOff + minutesOff));
+ }
+ }
+
+ return calendar.getTime();
+ }
+
+ static String getGeneralizedTimeDateString(Date date, boolean includeMillis)
+ {
+ Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+
+ calendar.setTime(date);
+
+ String time = format4Year(calendar.get(Calendar.YEAR)) + format2(calendar.get(Calendar.MONTH) + 1) + format2(calendar.get(Calendar.DAY_OF_MONTH))
+ + format2(calendar.get(Calendar.HOUR_OF_DAY)) + format2(calendar.get(Calendar.MINUTE)) + format2(calendar.get(Calendar.SECOND));
+
+ if (includeMillis)
+ {
+ time += "." + format3(calendar.get(Calendar.MILLISECOND));
+ }
+
+ return time + "Z";
+ }
+
+ static Date fromGeneralizedTimeString(byte[] date)
+ {
+ Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+
+ int year = toInt4(date, 0);
+
+ if (isLocalTime(date))
+ {
+ calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
+ }
+
+ calendar.set(Calendar.YEAR, year);
+ calendar.set(Calendar.MONTH, toInt2(date, 4) - 1);
+ calendar.set(Calendar.DAY_OF_MONTH, toInt2(date, 6));
+ calendar.set(Calendar.HOUR_OF_DAY, toInt2(date, 8));
+ calendar.set(Calendar.MINUTE, toInt2(date, 10));
+
+ int tzChar = 12;
+
+ if (isNumber(date, tzChar))
+ {
+ calendar.set(Calendar.SECOND, toInt2(date, 12));
+ tzChar = 14;
+ }
+ else
+ {
+ calendar.set(Calendar.SECOND, 0);
+ }
+
+ if (tzChar != date.length && date[tzChar] == '.')
+ {
+ int millis = 0;
+ tzChar++;
+ if (isNumber(date, tzChar))
+ {
+ millis = (date[tzChar] - '0') * 100;
+ tzChar++;
+ }
+ if (tzChar != date.length && isNumber(date, tzChar))
+ {
+ millis += (date[tzChar] - '0') * 10;
+ tzChar++;
+ }
+ if (tzChar != date.length && isNumber(date, tzChar))
+ {
+ millis += (date[tzChar] - '0');
+ tzChar++;
+ }
+ calendar.set(Calendar.MILLISECOND, millis);
+ }
+ else
+ {
+ calendar.set(Calendar.MILLISECOND, 0);
+ }
+
+ // skip nano-seconds
+ while (tzChar != date.length && isNumber(date, tzChar))
+ {
+ tzChar++;
+ }
+
+ if (tzChar != date.length && date[tzChar] != 'Z')
+ {
+ int hoursOff = 0;
+ int minutesOff = 0;
+
+ hoursOff = toInt2(date, tzChar + 1) * 60 * 60 * 1000;
+
+ if (date.length > tzChar + 3)
+ {
+ minutesOff = toInt2(date, tzChar + 3) * 60 * 1000;
+ }
+
+ if (date[tzChar] == '-')
+ {
+ return new Date(calendar.getTime().getTime() + hoursOff + minutesOff);
+ }
+ else
+ {
+ return new Date(calendar.getTime().getTime() - (hoursOff + minutesOff));
+ }
+ }
+
+ return calendar.getTime();
+ }
+
+ private static String format2(int v)
+ {
+ if (v < 10)
+ {
+ return "0" + v;
+ }
+
+ return Integer.toString(v);
+ }
+
+ private static String format2Year(int v)
+ {
+ if (v > 2000)
+ {
+ v = v - 2000;
+ }
+ else
+ {
+ v = v - 1900;
+ }
+
+ return format2(v);
+ }
+
+ private static String format3(int v)
+ {
+ if (v < 10)
+ {
+ return "00" + v;
+ }
+
+ if (v < 100)
+ {
+ return "0" + v;
+ }
+
+ return Integer.toString(v);
+ }
+
+ private static String format4Year(int v)
+ {
+ if (v < 10)
+ {
+ return "000" + v;
+ }
+
+ if (v < 100)
+ {
+ return "00" + v;
+ }
+
+ if (v < 1000)
+ {
+ return "0" + v;
+ }
+
+ return Integer.toString(v);
+ }
+
+ private static boolean isNumber(byte[] input, int off)
+ {
+ byte b = input[off];
+ return (b >= '0') && (b <= '9');
+ }
+
+ private static boolean isLocalTime(byte[] date)
+ {
+ for (int i = date.length - 1; i > date.length - 6; i--)
+ {
+ if (date[i] == 'Z' || date[i] == '-' || date[i] == '+')
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static int toInt2(byte[] input, int off)
+ {
+ return (input[off] - '0') * 10 + (input[off + 1] - '0');
+ }
+
+ private static int toInt4(byte[] input, int off)
+ {
+ return toInt2(input, off) * 100 + toInt2(input, off + 2) ;
+ }
+}
diff --git a/core/src/main/j2me/org/spongycastle/asn1/StreamUtil.java b/core/src/main/j2me/org/spongycastle/asn1/StreamUtil.java
new file mode 100644
index 00000000..4f798ffa
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/asn1/StreamUtil.java
@@ -0,0 +1,88 @@
+package org.spongycastle.asn1;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+class StreamUtil
+{
+ /**
+ * Find out possible longest length...
+ *
+ * @param in input stream of interest
+ * @return length calculation or MAX_VALUE.
+ */
+ static int findLimit(InputStream in)
+ {
+ if (in instanceof LimitedInputStream)
+ {
+ return ((LimitedInputStream)in).getRemaining();
+ }
+ else if (in instanceof ASN1InputStream)
+ {
+ return ((ASN1InputStream)in).getLimit();
+ }
+ else if (in instanceof ByteArrayInputStream)
+ {
+ return ((ByteArrayInputStream)in).available();
+ }
+
+ return Integer.MAX_VALUE;
+ }
+
+ static int calculateBodyLength(
+ int length)
+ {
+ int count = 1;
+
+ if (length > 127)
+ {
+ int size = 1;
+ int val = length;
+
+ while ((val >>>= 8) != 0)
+ {
+ size++;
+ }
+
+ for (int i = (size - 1) * 8; i >= 0; i -= 8)
+ {
+ count++;
+ }
+ }
+
+ return count;
+ }
+
+ static int calculateTagLength(int tagNo)
+ throws IOException
+ {
+ int length = 1;
+
+ if (tagNo >= 31)
+ {
+ if (tagNo < 128)
+ {
+ length++;
+ }
+ else
+ {
+ byte[] stack = new byte[5];
+ int pos = stack.length;
+
+ stack[--pos] = (byte)(tagNo & 0x7F);
+
+ do
+ {
+ tagNo >>= 7;
+ stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
+ }
+ while (tagNo > 127);
+
+ length += stack.length - pos;
+ }
+ }
+
+ return length;
+ }
+}
diff --git a/core/src/main/j2me/org/spongycastle/asn1/cms/Time.java b/core/src/main/j2me/org/spongycastle/asn1/cms/Time.java
new file mode 100644
index 00000000..5609cb72
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/asn1/cms/Time.java
@@ -0,0 +1,122 @@
+package org.spongycastle.asn1.cms;
+
+import java.util.Calendar;
+import java.util.Date;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1UTCTime;
+
+public class Time
+ extends ASN1Object
+ implements ASN1Choice
+{
+ ASN1Primitive time;
+
+ public static Time getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject()); // must be explicitly tagged
+ }
+
+ public Time(
+ ASN1Primitive time)
+ {
+ if (!(time instanceof ASN1UTCTime)
+ && !(time instanceof ASN1GeneralizedTime))
+ {
+ throw new IllegalArgumentException("unknown object passed to Time");
+ }
+
+ this.time = time;
+ }
+
+ /**
+ * creates a time object from a given date - if the date is between 1950
+ * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
+ * is used.
+ */
+ public Time(
+ Date date)
+ {
+ Calendar calendar = Calendar.getInstance();
+
+ calendar.setTime(date);
+
+ int year = calendar.get(Calendar.YEAR);
+
+ if (year < 1950 || year > 2049)
+ {
+ time = new ASN1GeneralizedTime(date);
+ }
+ else
+ {
+ time = new ASN1UTCTime(date);
+ }
+ }
+
+ public static Time getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof Time)
+ {
+ return (Time)obj;
+ }
+ else if (obj instanceof ASN1UTCTime)
+ {
+ return new Time((ASN1UTCTime)obj);
+ }
+ else if (obj instanceof ASN1GeneralizedTime)
+ {
+ return new Time((ASN1GeneralizedTime)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
+ }
+
+ public String getTime()
+ {
+ if (time instanceof ASN1UTCTime)
+ {
+ return ((ASN1UTCTime)time).getAdjustedTime();
+ }
+ else
+ {
+ return ((ASN1GeneralizedTime)time).getTime();
+ }
+ }
+
+ public Date getDate()
+ {
+ if (time instanceof ASN1UTCTime)
+ {
+ return ((ASN1UTCTime)time).getAdjustedDate();
+ }
+ else
+ {
+ return ((ASN1GeneralizedTime)time).getDate();
+ }
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * Time ::= CHOICE {
+ * utcTime UTCTime,
+ * generalTime GeneralizedTime }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return time;
+ }
+
+ public String toString()
+ {
+ return getTime();
+ }
+}
diff --git a/core/src/main/j2me/org/spongycastle/asn1/eac/PackedDate.java b/core/src/main/j2me/org/spongycastle/asn1/eac/PackedDate.java
new file mode 100644
index 00000000..e2472251
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/asn1/eac/PackedDate.java
@@ -0,0 +1,70 @@
+package org.spongycastle.asn1.eac;
+
+import org.spongycastle.util.Arrays;
+
+/**
+ * EAC encoding date object
+ */
+public class PackedDate
+{
+ private byte[] time;
+
+ public PackedDate(
+ String time)
+ {
+ this.time = convert(time);
+ }
+
+ private byte[] convert(String sTime)
+ {
+ char[] digs = sTime.toCharArray();
+ byte[] date = new byte[6];
+
+ for (int i = 0; i != 6; i++)
+ {
+ date[i] = (byte)(digs[i] - '0');
+ }
+
+ return date;
+ }
+
+ PackedDate(
+ byte[] bytes)
+ {
+ this.time = bytes;
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(time);
+ }
+
+ public boolean equals(Object o)
+ {
+ if (!(o instanceof PackedDate))
+ {
+ return false;
+ }
+
+ PackedDate other = (PackedDate)o;
+
+ return Arrays.areEqual(time, other.time);
+ }
+
+ public String toString()
+ {
+ char[] dateC = new char[time.length];
+
+ for (int i = 0; i != dateC.length; i++)
+ {
+ dateC[i] = (char)((time[i] & 0xff) + '0');
+ }
+
+ return new String(dateC);
+ }
+
+ public byte[] getEncoding()
+ {
+ return time;
+ }
+}
diff --git a/core/src/main/j2me/org/spongycastle/asn1/x509/Time.java b/core/src/main/j2me/org/spongycastle/asn1/x509/Time.java
new file mode 100644
index 00000000..f388be8d
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/asn1/x509/Time.java
@@ -0,0 +1,122 @@
+package org.spongycastle.asn1.x509;
+
+import java.util.Calendar;
+import java.util.Date;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1UTCTime;
+
+public class Time
+ extends ASN1Object
+ implements ASN1Choice
+{
+ ASN1Primitive time;
+
+ public static Time getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject()); // must be explicitly tagged
+ }
+
+ public Time(
+ ASN1Primitive time)
+ {
+ if (!(time instanceof ASN1UTCTime)
+ && !(time instanceof ASN1GeneralizedTime))
+ {
+ throw new IllegalArgumentException("unknown object passed to Time");
+ }
+
+ this.time = time;
+ }
+
+ /**
+ * creates a time object from a given date - if the date is between 1950
+ * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
+ * is used.
+ */
+ public Time(
+ Date date)
+ {
+ Calendar calendar = Calendar.getInstance();
+
+ calendar.setTime(date);
+
+ int year = calendar.get(Calendar.YEAR);
+
+ if (year < 1950 || year > 2049)
+ {
+ time = new ASN1GeneralizedTime(date);
+ }
+ else
+ {
+ time = new ASN1UTCTime(date);
+ }
+ }
+
+ public static Time getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof Time)
+ {
+ return (Time)obj;
+ }
+ else if (obj instanceof ASN1UTCTime)
+ {
+ return new Time((ASN1UTCTime)obj);
+ }
+ else if (obj instanceof ASN1GeneralizedTime)
+ {
+ return new Time((ASN1GeneralizedTime)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
+ }
+
+ public String getTime()
+ {
+ if (time instanceof ASN1UTCTime)
+ {
+ return ((ASN1UTCTime)time).getAdjustedTime();
+ }
+ else
+ {
+ return ((ASN1GeneralizedTime)time).getTime();
+ }
+ }
+
+ public Date getDate()
+ {
+ if (time instanceof ASN1UTCTime)
+ {
+ return ((ASN1UTCTime)time).getAdjustedDate();
+ }
+ else
+ {
+ return ((ASN1GeneralizedTime)time).getDate();
+ }
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * Time ::= CHOICE {
+ * utcTime UTCTime,
+ * generalTime GeneralizedTime }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return time;
+ }
+
+ public String toString()
+ {
+ return getTime();
+ }
+}
diff --git a/core/src/main/j2me/org/spongycastle/crypto/encodings/PKCS1Encoding.java b/core/src/main/j2me/org/spongycastle/crypto/encodings/PKCS1Encoding.java
new file mode 100644
index 00000000..7af31f36
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/crypto/encodings/PKCS1Encoding.java
@@ -0,0 +1,410 @@
+package org.spongycastle.crypto.encodings;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+
+/**
+ * this does your basic PKCS 1 v1.5 padding - whether or not you should be using this
+ * depends on your application - see PKCS1 Version 2 for details.
+ */
+public class PKCS1Encoding
+ implements AsymmetricBlockCipher
+{
+ /**
+ * some providers fail to include the leading zero in PKCS1 encoded blocks. If you need to
+ * work with one of these set the system property org.spongycastle.pkcs1.strict to false.
+ * <p>
+ * The system property is checked during construction of the encoding object, it is set to
+ * true by default.
+ * </p>
+ */
+ public static final String STRICT_LENGTH_ENABLED_PROPERTY = "org.spongycastle.pkcs1.strict";
+
+ private static final int HEADER_LENGTH = 10;
+
+ private SecureRandom random;
+ private AsymmetricBlockCipher engine;
+ private boolean forEncryption;
+ private boolean forPrivateKey;
+ private boolean useStrictLength;
+ private int pLen = -1;
+ private byte[] fallback = null;
+
+ /**
+ * Basic constructor.
+ * @param cipher
+ */
+ public PKCS1Encoding(
+ AsymmetricBlockCipher cipher)
+ {
+ this.engine = cipher;
+ this.useStrictLength = useStrict();
+ }
+
+ /**
+ * Constructor for decryption with a fixed plaintext length.
+ *
+ * @param cipher The cipher to use for cryptographic operation.
+ * @param pLen Length of the expected plaintext.
+ */
+ public PKCS1Encoding(
+ AsymmetricBlockCipher cipher,
+ int pLen)
+ {
+ this.engine = cipher;
+ this.useStrictLength = useStrict();
+ this.pLen = pLen;
+ }
+
+ /**
+ * Constructor for decryption with a fixed plaintext length and a fallback
+ * value that is returned, if the padding is incorrect.
+ *
+ * @param cipher
+ * The cipher to use for cryptographic operation.
+ * @param fallback
+ * The fallback value, we don't to a arraycopy here.
+ */
+ public PKCS1Encoding(
+ AsymmetricBlockCipher cipher,
+ byte[] fallback)
+ {
+ this.engine = cipher;
+ this.useStrictLength = useStrict();
+ this.fallback = fallback;
+ this.pLen = fallback.length;
+ }
+
+
+
+ //
+ // for J2ME compatibility
+ //
+ private boolean useStrict()
+ {
+ // required if security manager has been installed.
+ String strict = System.getProperty(STRICT_LENGTH_ENABLED_PROPERTY);
+
+ return strict == null || strict.equals("true");
+ }
+
+ public AsymmetricBlockCipher getUnderlyingCipher()
+ {
+ return engine;
+ }
+
+ public void init(
+ boolean forEncryption,
+ CipherParameters param)
+ {
+ AsymmetricKeyParameter kParam;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.random = rParam.getRandom();
+ kParam = (AsymmetricKeyParameter)rParam.getParameters();
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ kParam = (AsymmetricKeyParameter)param;
+ }
+
+ engine.init(forEncryption, param);
+
+ this.forPrivateKey = kParam.isPrivate();
+ this.forEncryption = forEncryption;
+ }
+
+ public int getInputBlockSize()
+ {
+ int baseBlockSize = engine.getInputBlockSize();
+
+ if (forEncryption)
+ {
+ return baseBlockSize - HEADER_LENGTH;
+ }
+ else
+ {
+ return baseBlockSize;
+ }
+ }
+
+ public int getOutputBlockSize()
+ {
+ int baseBlockSize = engine.getOutputBlockSize();
+
+ if (forEncryption)
+ {
+ return baseBlockSize;
+ }
+ else
+ {
+ return baseBlockSize - HEADER_LENGTH;
+ }
+ }
+
+ public byte[] processBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ if (forEncryption)
+ {
+ return encodeBlock(in, inOff, inLen);
+ }
+ else
+ {
+ return decodeBlock(in, inOff, inLen);
+ }
+ }
+
+ private byte[] encodeBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ if (inLen > getInputBlockSize())
+ {
+ throw new IllegalArgumentException("input data too large");
+ }
+
+ byte[] block = new byte[engine.getInputBlockSize()];
+
+ if (forPrivateKey)
+ {
+ block[0] = 0x01; // type code 1
+
+ for (int i = 1; i != block.length - inLen - 1; i++)
+ {
+ block[i] = (byte)0xFF;
+ }
+ }
+ else
+ {
+ random.nextBytes(block); // random fill
+
+ block[0] = 0x02; // type code 2
+
+ //
+ // a zero byte marks the end of the padding, so all
+ // the pad bytes must be non-zero.
+ //
+ for (int i = 1; i != block.length - inLen - 1; i++)
+ {
+ while (block[i] == 0)
+ {
+ block[i] = (byte)random.nextInt();
+ }
+ }
+ }
+
+ block[block.length - inLen - 1] = 0x00; // mark the end of the padding
+ System.arraycopy(in, inOff, block, block.length - inLen, inLen);
+
+ return engine.processBlock(block, 0, block.length);
+ }
+
+ /**
+ * Checks if the argument is a correctly PKCS#1.5 encoded Plaintext
+ * for encryption.
+ *
+ * @param encoded The Plaintext.
+ * @param pLen Expected length of the plaintext.
+ * @return Either 0, if the encoding is correct, or -1, if it is incorrect.
+ */
+ private static int checkPkcs1Encoding(byte[] encoded, int pLen) {
+ int correct = 0;
+ /*
+ * Check if the first two bytes are 0 2
+ */
+ correct |= (encoded[0] ^ 2);
+
+ /*
+ * Now the padding check, check for no 0 byte in the padding
+ */
+ int plen = encoded.length - (
+ pLen /* Lenght of the PMS */
+ + 1 /* Final 0-byte before PMS */
+ );
+
+ for (int i = 1; i < plen; i++) {
+ int tmp = encoded[i];
+ tmp |= tmp >> 1;
+ tmp |= tmp >> 2;
+ tmp |= tmp >> 4;
+ correct |= (tmp & 1) - 1;
+ }
+
+ /*
+ * Make sure the padding ends with a 0 byte.
+ */
+ correct |= encoded[encoded.length - (pLen +1)];
+
+ /*
+ * Return 0 or 1, depending on the result.
+ */
+ correct |= correct >> 1;
+ correct |= correct >> 2;
+ correct |= correct >> 4;
+ return ~((correct & 1) - 1);
+ }
+
+
+ /**
+ * Decode PKCS#1.5 encoding, and return a random value if the padding is not correct.
+ *
+ * @param in The encrypted block.
+ * @param inOff Offset in the encrypted block.
+ * @param inLen Length of the encrypted block.
+ * //@param pLen Length of the desired output.
+ * @return The plaintext without padding, or a random value if the padding was incorrect.
+ *
+ * @throws InvalidCipherTextException
+ */
+ private byte[] decodeBlockOrRandom(byte[] in, int inOff, int inLen)
+ throws InvalidCipherTextException
+ {
+ if (!forPrivateKey)
+ {
+ throw new InvalidCipherTextException("sorry, this method is only for decryption, not for signing");
+ }
+
+ byte[] block = engine.processBlock(in, inOff, inLen);
+ byte[] random = null;
+ if (this.fallback == null)
+ {
+ random = new byte[this.pLen];
+ this.random.nextBytes(random);
+ }
+ else
+ {
+ random = fallback;
+ }
+
+ /*
+ * TODO: This is a potential dangerous side channel. However, you can
+ * fix this by changing the RSA engine in a way, that it will always
+ * return blocks of the same length and prepend them with 0 bytes if
+ * needed.
+ */
+ if (block.length < getOutputBlockSize())
+ {
+ throw new InvalidCipherTextException("block truncated");
+ }
+
+ /*
+ * TODO: Potential side channel. Fix it by making the engine always
+ * return blocks of the correct length.
+ */
+ if (useStrictLength && block.length != engine.getOutputBlockSize())
+ {
+ throw new InvalidCipherTextException("block incorrect size");
+ }
+
+ /*
+ * Check the padding.
+ */
+ int correct = PKCS1Encoding.checkPkcs1Encoding(block, this.pLen);
+
+ /*
+ * Now, to a constant time constant memory copy of the decrypted value
+ * or the random value, depending on the validity of the padding.
+ */
+ byte[] result = new byte[this.pLen];
+ for (int i = 0; i < this.pLen; i++)
+ {
+ result[i] = (byte)((block[i + (block.length - pLen)] & (~correct)) | (random[i] & correct));
+ }
+
+ return result;
+ }
+
+ /**
+ * @exception InvalidCipherTextException if the decrypted block is not in PKCS1 format.
+ */
+ private byte[] decodeBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ /*
+ * If the length of the expected plaintext is known, we use a constant-time decryption.
+ * If the decryption fails, we return a random value.
+ */
+ if (this.pLen != -1) {
+ return this.decodeBlockOrRandom(in, inOff, inLen);
+ }
+
+ byte[] block = engine.processBlock(in, inOff, inLen);
+
+ if (block.length < getOutputBlockSize())
+ {
+ throw new InvalidCipherTextException("block truncated");
+ }
+
+ byte type = block[0];
+
+ if (forPrivateKey)
+ {
+ if (type != 2)
+ {
+ throw new InvalidCipherTextException("unknown block type");
+ }
+ }
+ else
+ {
+ if (type != 1)
+ {
+ throw new InvalidCipherTextException("unknown block type");
+ }
+ }
+
+ if (useStrictLength && block.length != engine.getOutputBlockSize())
+ {
+ throw new InvalidCipherTextException("block incorrect size");
+ }
+
+ //
+ // find and extract the message block.
+ //
+ int start;
+
+ for (start = 1; start != block.length; start++)
+ {
+ byte pad = block[start];
+
+ if (pad == 0)
+ {
+ break;
+ }
+ if (type == 1 && pad != (byte)0xff)
+ {
+ throw new InvalidCipherTextException("block padding incorrect");
+ }
+ }
+
+ start++; // data should start at the next byte
+
+ if (start > block.length || start < HEADER_LENGTH)
+ {
+ throw new InvalidCipherTextException("no data in block");
+ }
+
+ byte[] result = new byte[block.length - start];
+
+ System.arraycopy(block, start, result, 0, result.length);
+
+ return result;
+ }
+}
diff --git a/core/src/main/j2me/org/spongycastle/crypto/examples/MIDPTest.java b/core/src/main/j2me/org/spongycastle/crypto/examples/MIDPTest.java
new file mode 100644
index 00000000..32908a67
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/crypto/examples/MIDPTest.java
@@ -0,0 +1,177 @@
+package org.spongycastle.crypto.examples;
+
+import java.io.*;
+import java.lang.*;
+
+import javax.microedition.midlet.MIDlet;
+import javax.microedition.lcdui.*;
+
+import org.spongycastle.util.test.*;
+import org.spongycastle.util.encoders.*;
+
+import org.spongycastle.crypto.*;
+import org.spongycastle.crypto.paddings.*;
+import org.spongycastle.crypto.engines.*;
+import org.spongycastle.crypto.modes.*;
+import org.spongycastle.crypto.params.*;
+
+/**
+ * MIDP is a simple graphics application for the J2ME CLDC/MIDP.
+ *
+ * It has hardcoded values for the key and plain text. It also performs the
+ * standard testing for the chosen cipher, and displays the results.
+ *
+ * This example shows how to use the light-weight API and a symmetric cipher.
+ *
+ */
+public class MIDPTest extends MIDlet
+{
+ private Display d = null;
+
+ private boolean doneEncrypt = false;
+
+ private String key = "0123456789abcdef0123456789abcdef";
+ private String plainText = "www.bouncycastle.org";
+ private byte[] keyBytes = null;
+ private byte[] cipherText = null;
+ private BufferedBlockCipher cipher = null;
+
+ private String[] cipherNames = {"DES", "DESede", "IDEA", "Rijndael", "Twofish"};
+
+ private Form output = null;
+
+ public void startApp()
+ {
+ Display.getDisplay(this).setCurrent(output);
+ }
+
+ public void pauseApp()
+ {
+
+ }
+
+ public void destroyApp(boolean unconditional)
+ {
+
+ }
+
+ public MIDPTest()
+ {
+ output = new Form("BouncyCastle");
+ output.append("Key: " + key.substring(0, 7) + "...\n");
+ output.append("In : " + plainText.substring(0, 7) + "...\n");
+
+ cipherText = performEncrypt(Hex.decode(key.getBytes()), plainText);
+ String ctS = new String(Hex.encode(cipherText));
+
+ output.append("\nCT : " + ctS.substring(0, 7) + "...\n");
+
+ String decryptText = performDecrypt(Hex.decode(key.getBytes()), cipherText);
+
+ output.append("PT : " + decryptText.substring(0, 7) + "...\n");
+
+ if (decryptText.compareTo(plainText) == 0)
+ {
+ output.append("Success");
+ }
+ else
+ {
+ output.append("Failure");
+ message("[" + plainText + "]");
+ message("[" + decryptText + "]");
+ }
+
+ }
+
+ private byte[] performEncrypt(byte[] key, String plainText)
+ {
+ byte[] ptBytes = plainText.getBytes();
+
+ cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(getEngineInstance()));
+
+ String name = cipher.getUnderlyingCipher().getAlgorithmName();
+ message("Using " + name);
+
+ cipher.init(true, new KeyParameter(key));
+
+ byte[] rv = new byte[cipher.getOutputSize(ptBytes.length)];
+
+ int oLen = cipher.processBytes(ptBytes, 0, ptBytes.length, rv, 0);
+ try
+ {
+ cipher.doFinal(rv, oLen);
+ }
+ catch (CryptoException ce)
+ {
+ message("Ooops, encrypt exception");
+ status(ce.toString());
+ }
+ return rv;
+ }
+
+ private String performDecrypt(byte[] key, byte[] cipherText)
+ {
+ cipher.init(false, new KeyParameter(key));
+
+ byte[] rv = new byte[cipher.getOutputSize(cipherText.length)];
+
+ int oLen = cipher.processBytes(cipherText, 0, cipherText.length, rv, 0);
+ try
+ {
+ cipher.doFinal(rv, oLen);
+ }
+ catch (CryptoException ce)
+ {
+ message("Ooops, decrypt exception");
+ status(ce.toString());
+ }
+ return new String(rv).trim();
+ }
+
+ private int whichCipher()
+ {
+ return 4; // DES
+ }
+
+ private BlockCipher getEngineInstance()
+ {
+ // returns a block cipher according to the current
+ // state of the radio button lists. This is only
+ // done prior to encryption.
+ BlockCipher rv = null;
+
+ switch (whichCipher())
+ {
+ case 0 :
+ rv = new DESEngine();
+ break;
+ case 1 :
+ rv = new DESedeEngine();
+ break;
+ case 2 :
+ rv = new IDEAEngine();
+ break;
+ case 3 :
+ rv = new RijndaelEngine();
+ break;
+ case 4 :
+ rv = new TwofishEngine();
+ break;
+ default :
+ rv = new DESEngine();
+ break;
+ }
+ return rv;
+ }
+
+ public void message(String s)
+ {
+ System.out.println("M:" + s);
+ }
+
+ public void status(String s)
+ {
+ System.out.println("S:" + s);
+ }
+
+}
diff --git a/core/src/main/j2me/org/spongycastle/crypto/examples/midp_test.jad b/core/src/main/j2me/org/spongycastle/crypto/examples/midp_test.jad
new file mode 100644
index 00000000..584f3156
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/crypto/examples/midp_test.jad
@@ -0,0 +1,6 @@
+MIDlet-1: MIDPTest, , org.spongycastle.crypto.examples.MIDPTest
+MIDlet-Name: MIDPTest
+MIDlet-Jar-Size: 300000
+MIDlet-Jar-URL: midp_test.jar
+MIDlet-Vendor: The Legion of the Bouncy Castle
+MIDlet-Version: 1.0.0
diff --git a/core/src/main/j2me/org/spongycastle/crypto/examples/midp_test.mf b/core/src/main/j2me/org/spongycastle/crypto/examples/midp_test.mf
new file mode 100644
index 00000000..27352109
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/crypto/examples/midp_test.mf
@@ -0,0 +1,7 @@
+MIDlet-1: MIDPTTest, , org.spongycastle.crypto.examples.MIDPTest
+MIDlet-Name: MIDPTest
+MIDlet-Version: 1.0.0
+MIDlet-Vendor: Jon Eaves
+Created-By: 1.3.1 (Sun Microsystems Inc.)
+MicroEdition-Configuration: CLDC-1.0
+MicroEdition-Profile: MIDP-1.0
diff --git a/core/src/main/j2me/org/spongycastle/crypto/params/SkeinParameters.java b/core/src/main/j2me/org/spongycastle/crypto/params/SkeinParameters.java
new file mode 100644
index 00000000..b29cd441
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/crypto/params/SkeinParameters.java
@@ -0,0 +1,258 @@
+package org.spongycastle.crypto.params;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.digests.SkeinDigest;
+import org.spongycastle.crypto.digests.SkeinEngine;
+import org.spongycastle.crypto.macs.SkeinMac;
+import org.spongycastle.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);
+ }
+
+ /**
+ * 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/core/src/main/j2me/org/spongycastle/crypto/tls/OCSPStatusRequest.java b/core/src/main/j2me/org/spongycastle/crypto/tls/OCSPStatusRequest.java
new file mode 100644
index 00000000..ea68af90
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/crypto/tls/OCSPStatusRequest.java
@@ -0,0 +1,131 @@
+package org.spongycastle.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.spongycastle.asn1.ASN1Encoding;
+import org.spongycastle.asn1.ocsp.ResponderID;
+import org.spongycastle.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);
+ output.write(buf.toByteArray());
+ }
+
+ 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 an {@link OCSPStatusRequest} from an {@link InputStream}.
+ *
+ * @param input
+ * the {@link InputStream} to parse from.
+ * @return an {@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/core/src/main/j2me/org/spongycastle/crypto/tls/ServerNameList.java b/core/src/main/j2me/org/spongycastle/crypto/tls/ServerNameList.java
new file mode 100644
index 00000000..09817e6b
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/crypto/tls/ServerNameList.java
@@ -0,0 +1,86 @@
+package org.spongycastle.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);
+ output.write(buf.toByteArray());
+ }
+
+ /**
+ * 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/core/src/main/j2me/org/spongycastle/crypto/tls/UDPTransport.java b/core/src/main/j2me/org/spongycastle/crypto/tls/UDPTransport.java
new file mode 100644
index 00000000..ea287144
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/crypto/tls/UDPTransport.java
@@ -0,0 +1,107 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import javax.microedition.io.DatagramConnection;
+import javax.microedition.io.Datagram;
+
+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;
+
+ protected final DatagramConnection socket;
+ protected final int receiveLimit, sendLimit;
+
+ public UDPTransport(DatagramConnection socket, int mtu)
+ throws IOException
+ {
+ //
+ // In 1.3 and earlier sockets were bound and connected during creation
+ //
+ //if (!socket.isBound() || !socket.isConnected())
+ //{
+ // throw new IllegalArgumentException("'socket' must be bound and connected");
+ //}
+
+ this.socket = socket;
+
+ // NOTE: As of JDK 1.6, can use NetworkInterface.getMTU
+
+ this.receiveLimit = mtu - MIN_IP_OVERHEAD - UDP_OVERHEAD;
+ this.sendLimit = mtu - MAX_IP_OVERHEAD - UDP_OVERHEAD;
+ }
+
+ public int getReceiveLimit()
+ {
+ return receiveLimit;
+ }
+
+ public int getSendLimit()
+ {
+ // TODO[DTLS] Implement Path-MTU discovery?
+ return sendLimit;
+ }
+
+ public int receive(byte[] buf, int off, int len, int waitMillis)
+ throws IOException
+ {
+ //socket.setSoTimeout(waitMillis); -- not applicable
+
+ if (off == 0)
+ {
+ Datagram packet = socket.newDatagram(buf, len);
+ socket.receive(packet);
+
+ return packet.getLength();
+ }
+ else
+ {
+ byte[] rv = new byte[len];
+
+ Datagram packet = socket.newDatagram(rv, len);
+ socket.receive(packet);
+
+ System.arraycopy(rv, 0, buf, off, packet.getLength());
+
+ return packet.getLength();
+ }
+ }
+
+ public void send(byte[] buf, int off, int len)
+ throws IOException
+ {
+ if (len > getSendLimit())
+ {
+ /*
+ * RFC 4347 4.1.1. "If the application attempts to send a record larger than the MTU,
+ * the DTLS implementation SHOULD generate an error, thus avoiding sending a packet
+ * which will be fragmented."
+ */
+ // TODO Exception
+ }
+
+ if (off == 0)
+ {
+ Datagram packet = socket.newDatagram(buf, len);
+ socket.send(packet);
+ }
+ else
+ {
+ byte[] data = new byte[len];
+
+ System.arraycopy(buf, off, data, 0, len);
+
+ Datagram packet = socket.newDatagram(data, len);
+ socket.send(packet);
+ }
+ }
+
+ public void close()
+ throws IOException
+ {
+ socket.close();
+ }
+}
diff --git a/core/src/main/j2me/org/spongycastle/math/ec/LongArray.java b/core/src/main/j2me/org/spongycastle/math/ec/LongArray.java
new file mode 100644
index 00000000..0f626d5c
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/math/ec/LongArray.java
@@ -0,0 +1,2197 @@
+package org.spongycastle.math.ec;
+
+import org.spongycastle.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 isOne()
+ {
+ long[] a = m_ints;
+ if (a[0] != 1L)
+ {
+ return false;
+ }
+ for (int i = 1; i < a.length; ++i)
+ {
+ if (a[i] != 0L)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean isZero()
+ {
+ long[] a = m_ints;
+ 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) != 0L)
+ {
+ if ((a & 1L) != 0L)
+ {
+ long carry = addShiftedUp(c, cOff, b, 0, bLen, k);
+ if (carry != 0L)
+ {
+ 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 a0 = A.m_ints[0];
+ if (a0 == 1L)
+ {
+ return B;
+ }
+
+ /*
+ * Fast path for small A, with performance dependent only on the number of set bits
+ */
+ long[] c0 = new long[cLen];
+ multiplyWord(a0, B.m_ints, bLen, c0, 0);
+
+ /*
+ * Reduce the raw answer against the reduction coefficients
+ */
+ return reduceResult(c0, 0, cLen, m, ks);
+ }
+
+ /*
+ * 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 a0 = A.m_ints[0];
+ if (a0 == 1L)
+ {
+ return B;
+ }
+
+ /*
+ * Fast path for small A, with performance dependent only on the number of set bits
+ */
+ long[] c0 = new long[cLen];
+ multiplyWord(a0, B.m_ints, bLen, c0, 0);
+
+ /*
+ * Reduce the raw answer against the reduction coefficients
+ */
+ return reduceResult(c0, 0, cLen, m, ks);
+ }
+
+ /*
+ * Determine if B will get bigger during shifting
+ */
+ int bMax = (bDeg + 7 + 63) >>> 6;
+
+ /*
+ * Lookup table for the offset of each B in the tables
+ */
+ int[] ti = new int[16];
+
+ /*
+ * Precompute table of all 4-bit products of B
+ */
+ long[] T0 = new long[bMax << 4];
+ int tOff = bMax;
+ ti[1] = tOff;
+ System.arraycopy(B.m_ints, 0, T0, tOff, bLen);
+ for (int i = 2; i < 16; ++i)
+ {
+ ti[i] = (tOff += bMax);
+ if ((i & 1) == 0)
+ {
+ shiftUp(T0, tOff >>> 1, T0, tOff, bMax, 1);
+ }
+ else
+ {
+ add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax);
+ }
+ }
+
+ /*
+ * Second table with all 4-bit products of B shifted 4 bits
+ */
+ long[] T1 = new long[T0.length];
+ shiftUp(T0, 0, T1, 0, T0.length, 4);
+// shiftUp(T0, bMax, T1, bMax, tOff, 4);
+
+ long[] a = A.m_ints;
+ long[] c = new long[cLen << 3];
+
+ int MASK = 0xF;
+
+ /*
+ * Lopez-Dahab (Modified) algorithm
+ */
+
+ for (int aPos = 0; aPos < aLen; ++aPos)
+ {
+ long aVal = a[aPos];
+ int cOff = aPos;
+ for (;;)
+ {
+ int u = (int)aVal & MASK;
+ aVal >>>= 4;
+ int v = (int)aVal & MASK;
+ addBoth(c, cOff, T0, ti[u], T1, ti[v], bMax);
+ aVal >>>= 4;
+ if (aVal == 0L)
+ {
+ break;
+ }
+ cOff += cLen;
+ }
+ }
+
+ {
+ int cOff = c.length;
+ while ((cOff -= cLen) != 0)
+ {
+ addShiftedUp(c, cOff - cLen, c, cOff, cLen, 8);
+ }
+ }
+
+ /*
+ * Finally the raw answer is collected, reduce it against the reduction coefficients
+ */
+ return reduceResult(c, 0, cLen, m, ks);
+ }
+
+ 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 a0 = A.m_ints[0];
+ if (a0 == 1L)
+ {
+ return B;
+ }
+
+ /*
+ * Fast path for small A, with performance dependent only on the number of set bits
+ */
+ long[] c0 = new long[cLen];
+ multiplyWord(a0, B.m_ints, bLen, c0, 0);
+
+ /*
+ * Reduce the raw answer against the reduction coefficients
+ */
+ return reduceResult(c0, 0, cLen, m, ks);
+ }
+
+ // 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);
+ }
+
+ public LongArray modReduce(int m, int[] ks)
+ {
+ long[] buf = Arrays.clone(m_ints);
+ int rLen = reduceInPlace(buf, 0, buf.length, m, ks);
+ return new LongArray(buf, 0, rLen);
+ }
+
+ public LongArray multiply(LongArray other, int m, int[] ks)
+ {
+ /*
+ * Find out the degree of each argument and handle the zero cases
+ */
+ int aDeg = degree();
+ if (aDeg == 0)
+ {
+ return this;
+ }
+ int bDeg = other.degree();
+ if (bDeg == 0)
+ {
+ return other;
+ }
+
+ /*
+ * Swap if necessary so that A is the smaller argument
+ */
+ LongArray A = this, B = other;
+ if (aDeg > bDeg)
+ {
+ A = other; B = this;
+ int tmp = aDeg; aDeg = bDeg; bDeg = tmp;
+ }
+
+ /*
+ * Establish the word lengths of the arguments and result
+ */
+ int aLen = (aDeg + 63) >>> 6;
+ int bLen = (bDeg + 63) >>> 6;
+ int cLen = (aDeg + bDeg + 62) >>> 6;
+
+ if (aLen == 1)
+ {
+ long a0 = A.m_ints[0];
+ if (a0 == 1L)
+ {
+ return B;
+ }
+
+ /*
+ * Fast path for small A, with performance dependent only on the number of set bits
+ */
+ long[] c0 = new long[cLen];
+ multiplyWord(a0, B.m_ints, bLen, c0, 0);
+
+ /*
+ * Reduce the raw answer against the reduction coefficients
+ */
+// return reduceResult(c0, 0, cLen, m, ks);
+ return new LongArray(c0, 0, cLen);
+ }
+
+ /*
+ * Determine if B will get bigger during shifting
+ */
+ int bMax = (bDeg + 7 + 63) >>> 6;
+
+ /*
+ * Lookup table for the offset of each B in the tables
+ */
+ int[] ti = new int[16];
+
+ /*
+ * Precompute table of all 4-bit products of B
+ */
+ long[] T0 = new long[bMax << 4];
+ int tOff = bMax;
+ ti[1] = tOff;
+ System.arraycopy(B.m_ints, 0, T0, tOff, bLen);
+ for (int i = 2; i < 16; ++i)
+ {
+ ti[i] = (tOff += bMax);
+ if ((i & 1) == 0)
+ {
+ shiftUp(T0, tOff >>> 1, T0, tOff, bMax, 1);
+ }
+ else
+ {
+ add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax);
+ }
+ }
+
+ /*
+ * Second table with all 4-bit products of B shifted 4 bits
+ */
+ long[] T1 = new long[T0.length];
+ shiftUp(T0, 0, T1, 0, T0.length, 4);
+// shiftUp(T0, bMax, T1, bMax, tOff, 4);
+
+ long[] a = A.m_ints;
+ long[] c = new long[cLen << 3];
+
+ int MASK = 0xF;
+
+ /*
+ * Lopez-Dahab (Modified) algorithm
+ */
+
+ for (int aPos = 0; aPos < aLen; ++aPos)
+ {
+ long aVal = a[aPos];
+ int cOff = aPos;
+ for (;;)
+ {
+ int u = (int)aVal & MASK;
+ aVal >>>= 4;
+ int v = (int)aVal & MASK;
+ addBoth(c, cOff, T0, ti[u], T1, ti[v], bMax);
+ aVal >>>= 4;
+ if (aVal == 0L)
+ {
+ break;
+ }
+ cOff += cLen;
+ }
+ }
+
+ {
+ int cOff = c.length;
+ while ((cOff -= cLen) != 0)
+ {
+ addShiftedUp(c, cOff - cLen, c, cOff, cLen, 8);
+ }
+ }
+
+ /*
+ * Finally the raw answer is collected, reduce it against the reduction coefficients
+ */
+// return reduceResult(c, 0, cLen, m, ks);
+ return new LongArray(c, 0, cLen);
+ }
+
+ public void reduce(int m, int[] ks)
+ {
+ long[] buf = m_ints;
+ int rLen = reduceInPlace(buf, 0, buf.length, m, ks);
+ if (rLen < buf.length)
+ {
+ m_ints = new long[rLen];
+ System.arraycopy(buf, 0, m_ints, 0, rLen);
+ }
+ }
+
+ private static LongArray reduceResult(long[] buf, int off, int len, int m, int[] ks)
+ {
+ int rLen = reduceInPlace(buf, off, len, m, ks);
+ 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 n = bit - m;
+ int j = ks.length;
+ while (--j >= 0)
+ {
+ flipBit(buf, off, ks[j] + n);
+ }
+ flipBit(buf, off, n);
+ }
+
+ 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));
+ }
+
+ public LongArray modSquareN(int n, int m, int[] ks)
+ {
+ int len = getUsedLength();
+ if (len == 0)
+ {
+ return this;
+ }
+
+ int mLen = (m + 63) >>> 6;
+ long[] r = new long[mLen << 1];
+ System.arraycopy(m_ints, 0, r, 0, len);
+
+ while (--n >= 0)
+ {
+ squareInPlace(r, len, m, ks);
+ len = reduceInPlace(r, 0, r.length, m, ks);
+ }
+
+ return new LongArray(r, 0, len);
+ }
+
+ public LongArray square(int m, int[] ks)
+ {
+ int len = getUsedLength();
+ if (len == 0)
+ {
+ return this;
+ }
+
+ int _2len = len << 1;
+ long[] r = new long[_2len];
+
+ int pos = 0;
+ while (pos < _2len)
+ {
+ long mi = m_ints[pos >>> 1];
+ r[pos++] = interleave2_32to64((int)mi);
+ r[pos++] = interleave2_32to64((int)(mi >>> 32));
+ }
+
+ return new LongArray(r, 0, r.length);
+ }
+
+ private static void squareInPlace(long[] x, int xLen, int m, int[] ks)
+ {
+ int pos = xLen << 1;
+ while (--xLen >= 0)
+ {
+ long xVal = x[xLen];
+ x[--pos] = interleave2_32to64((int)(xVal >>> 32));
+ x[--pos] = interleave2_32to64((int)xVal);
+ }
+ }
+
+ private static void interleave(long[] x, int xOff, long[] z, int zOff, int count, int width)
+ {
+ 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 == 0)
+ {
+ throw new IllegalStateException();
+ }
+ 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();
+*/
+ return "not supported";
+ }
+}
diff --git a/core/src/main/j2me/org/spongycastle/util/Integers.java b/core/src/main/j2me/org/spongycastle/util/Integers.java
new file mode 100644
index 00000000..bf6b5e34
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/util/Integers.java
@@ -0,0 +1,19 @@
+package org.spongycastle.util;
+
+public class Integers
+{
+ public static int rotateLeft(int i, int distance)
+ {
+ return (i << distance) ^ (i >>> -distance);
+ }
+
+ public static int rotateRight(int i, int distance)
+ {
+ return (i >>> distance) ^ (i << -distance);
+ }
+
+ public static Integer valueOf(int value)
+ {
+ return new Integer(value);
+ }
+}
diff --git a/core/src/main/j2me/org/spongycastle/util/Selector.java b/core/src/main/j2me/org/spongycastle/util/Selector.java
new file mode 100644
index 00000000..a72cdaa2
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/util/Selector.java
@@ -0,0 +1,8 @@
+package org.spongycastle.util;
+
+public interface Selector
+{
+ boolean match(Object obj);
+
+ Object clone();
+}
diff --git a/core/src/main/j2me/org/spongycastle/util/Shorts.java b/core/src/main/j2me/org/spongycastle/util/Shorts.java
new file mode 100644
index 00000000..66a992f7
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/util/Shorts.java
@@ -0,0 +1,9 @@
+package org.spongycastle.util;
+
+public class Shorts
+{
+ public static Short valueOf(short value)
+ {
+ return new Short(value);
+ }
+}
diff --git a/core/src/main/j2me/org/spongycastle/util/Times.java b/core/src/main/j2me/org/spongycastle/util/Times.java
new file mode 100644
index 00000000..f88b5395
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/util/Times.java
@@ -0,0 +1,11 @@
+package org.spongycastle.util;
+
+public final class Times
+{
+ private static long NANOS_PER_MILLI = 1000000L;
+
+ public static long nanoTime()
+ {
+ return NANOS_PER_MILLI * System.currentTimeMillis();
+ }
+}
diff --git a/core/src/main/j2me/org/spongycastle/util/test/SimpleTest.java b/core/src/main/j2me/org/spongycastle/util/test/SimpleTest.java
new file mode 100644
index 00000000..a61e3bdd
--- /dev/null
+++ b/core/src/main/j2me/org/spongycastle/util/test/SimpleTest.java
@@ -0,0 +1,84 @@
+package org.spongycastle.util.test;
+
+import java.io.PrintStream;
+
+import org.spongycastle.util.Arrays;
+
+public abstract class SimpleTest
+ implements Test
+{
+ public abstract String getName();
+
+ private TestResult success()
+ {
+ return SimpleTestResult.successful(this, "Okay");
+ }
+
+ protected void fail(
+ String message)
+ {
+ throw new TestFailedException(SimpleTestResult.failed(this, message));
+ }
+
+ protected void fail(
+ String message,
+ Throwable throwable)
+ {
+ throw new TestFailedException(SimpleTestResult.failed(this, message, throwable));
+ }
+
+ protected void fail(
+ String message,
+ Object expected,
+ Object found)
+ {
+ throw new TestFailedException(SimpleTestResult.failed(this, message, expected, found));
+ }
+
+ protected boolean areEqual(
+ byte[] a,
+ byte[] b)
+ {
+ return Arrays.areEqual(a, b);
+ }
+
+ public TestResult perform()
+ {
+ try
+ {
+ performTest();
+
+ return success();
+ }
+ catch (TestFailedException e)
+ {
+ return e.getResult();
+ }
+ catch (Exception e)
+ {
+ return SimpleTestResult.failed(this, "Exception: " + e, e);
+ }
+ }
+
+ protected static void runTest(
+ Test test)
+ {
+ runTest(test, System.out);
+ }
+
+ protected static void runTest(
+ Test test,
+ PrintStream out)
+ {
+ TestResult result = test.perform();
+
+ out.println(result.toString());
+ if (result.getException() != null)
+ {
+ result.getException().printStackTrace();
+ }
+ }
+
+ public abstract void performTest()
+ throws Exception;
+}
diff --git a/core/src/main/java/org/bouncycastle/LICENSE.java b/core/src/main/java/org/bouncycastle/LICENSE.java
deleted file mode 100644
index 388afd2b..00000000
--- a/core/src/main/java/org/bouncycastle/LICENSE.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package org.bouncycastle;
-
-/**
- * The Bouncy Castle License
- *
- * Copyright (c) 2000-2014 The Legion Of The Bouncy Castle Inc. (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,
- * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- * <p>
- * The above copyright notice and this permission notice shall be included in all copies or substantial
- * portions of the Software.
- * <p>
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
- * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-public class LICENSE
-{
- public static String licenseText =
- "Copyright (c) 2000-2014 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 "
- + System.getProperty("line.separator")
- + "and associated documentation files (the \"Software\"), to deal in the Software without restriction, "
- + System.getProperty("line.separator")
- + "including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, "
- + System.getProperty("line.separator")
- + "and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,"
- + System.getProperty("line.separator")
- + "subject to the following conditions:"
- + System.getProperty("line.separator")
- + System.getProperty("line.separator")
- + "The above copyright notice and this permission notice shall be included in all copies or substantial"
- + System.getProperty("line.separator")
- + "portions of the Software."
- + System.getProperty("line.separator")
- + System.getProperty("line.separator")
- + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,"
- + System.getProperty("line.separator")
- + "INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR"
- + System.getProperty("line.separator")
- + "PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE"
- + System.getProperty("line.separator")
- + "LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR"
- + System.getProperty("line.separator")
- + "OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER"
- + System.getProperty("line.separator")
- + "DEALINGS IN THE SOFTWARE.";
-
- public static void main(
- String[] args)
- {
- System.out.println(licenseText);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java b/core/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java
deleted file mode 100644
index 8816b2b5..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * Interface to parse ASN.1 application specific objects.
- */
-public interface ASN1ApplicationSpecificParser
- extends ASN1Encodable, InMemoryRepresentable
-{
- /**
- * Read the next object in the parser.
- *
- * @return an ASN1Encodable
- * @throws IOException on a parsing or decoding error.
- */
- ASN1Encodable readObject()
- throws IOException;
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1Boolean.java b/core/src/main/java/org/bouncycastle/asn1/ASN1Boolean.java
deleted file mode 100644
index ace31109..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1Boolean.java
+++ /dev/null
@@ -1,204 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * Public facade of ASN.1 Boolean data.
- * <p>
- * Use following to place a new instance of ASN.1 Boolean in your dataset:
- * </p>
- * <ul>
- * <li> ASN1Boolean.TRUE literal</li>
- * <li> ASN1Boolean.FALSE literal</li>
- * <li> {@link ASN1Boolean#getInstance(boolean) ASN1Boolean.getInstance(boolean)}</li>
- * <li> {@link ASN1Boolean#getInstance(int) ASN1Boolean.getInstance(int)}</li>
- * </ul>
- * </p>
- */
-public class ASN1Boolean
- extends ASN1Primitive
-{
- private static final byte[] TRUE_VALUE = new byte[] { (byte)0xff };
- private static final byte[] FALSE_VALUE = new byte[] { 0 };
-
- private byte[] value;
-
- public static final ASN1Boolean FALSE = new ASN1Boolean(false);
- public static final ASN1Boolean TRUE = new ASN1Boolean(true);
-
- /**
- * return a boolean from the passed in object.
- *
- * @param obj an ASN1Boolean or an object that can be converted into one.
- * @exception IllegalArgumentException if the object cannot be converted.
- * @return an ASN1Boolean instance.
- */
- public static ASN1Boolean getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ASN1Boolean)
- {
- return (ASN1Boolean)obj;
- }
-
- if (obj instanceof byte[])
- {
- byte[] enc = (byte[])obj;
- try
- {
- return (ASN1Boolean)fromByteArray(enc);
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("failed to construct boolean from byte[]: " + e.getMessage());
- }
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return an ASN1Boolean from the passed in boolean.
- * @return an ASN1Boolean instance.
- */
- public static ASN1Boolean getInstance(
- boolean value)
- {
- return (value ? TRUE : FALSE);
- }
-
- /**
- * return an ASN1Boolean from the passed in value.
- * @return an ASN1Boolean instance.
- */
- public static ASN1Boolean getInstance(
- int value)
- {
- return (value != 0 ? TRUE : FALSE);
- }
-
- /**
- * return a Boolean from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- * @return an ASN1Boolean instance.
- */
- public static ASN1Boolean getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof ASN1Boolean)
- {
- return getInstance(o);
- }
- else
- {
- return ASN1Boolean.fromOctetString(((ASN1OctetString)o).getOctets());
- }
- }
-
- ASN1Boolean(
- byte[] value)
- {
- if (value.length != 1)
- {
- throw new IllegalArgumentException("byte value should have 1 byte in it");
- }
-
- if (value[0] == 0)
- {
- this.value = FALSE_VALUE;
- }
- else if ((value[0] & 0xff) == 0xff)
- {
- this.value = TRUE_VALUE;
- }
- else
- {
- this.value = Arrays.clone(value);
- }
- }
-
- /**
- * @deprecated use getInstance(boolean) method.
- * @param value true or false.
- */
- public ASN1Boolean(
- boolean value)
- {
- this.value = (value) ? TRUE_VALUE : FALSE_VALUE;
- }
-
- public boolean isTrue()
- {
- return (value[0] != 0);
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- return 3;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.writeEncoded(BERTags.BOOLEAN, value);
- }
-
- protected boolean asn1Equals(
- ASN1Primitive o)
- {
- if (o instanceof ASN1Boolean)
- {
- return (value[0] == ((ASN1Boolean)o).value[0]);
- }
-
- return false;
- }
-
- public int hashCode()
- {
- return value[0];
- }
-
-
- public String toString()
- {
- return (value[0] != 0) ? "TRUE" : "FALSE";
- }
-
- static ASN1Boolean fromOctetString(byte[] value)
- {
- if (value.length != 1)
- {
- throw new IllegalArgumentException("BOOLEAN value should have 1 byte in it");
- }
-
- if (value[0] == 0)
- {
- return FALSE;
- }
- else if ((value[0] & 0xff) == 0xff)
- {
- return TRUE;
- }
- else
- {
- return new ASN1Boolean(value);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1Choice.java b/core/src/main/java/org/bouncycastle/asn1/ASN1Choice.java
deleted file mode 100644
index 8a6714f2..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1Choice.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.bouncycastle.asn1;
-
-/**
- * Marker interface for CHOICE objects - if you implement this in a role your
- * own object any attempt to tag the object implicitly will convert the tag to
- * an explicit one as the encoding rules require.
- * <p>
- * If you use this interface your class should also implement the getInstance()
- * pattern which takes a tag object and the tagging mode used.
- * <p>
- * <hr>
- * <p><b>X.690</b></p>
- * <p><b>8: Basic encoding rules</b></p>
- * <p><b>8.13 Encoding of a choice value </b></p>
- * <p>
- * The encoding of a choice value shall be the same as the encoding of a value of the chosen type.
- * <blockquote>
- * NOTE 1 &mdash; The encoding may be primitive or constructed depending on the chosen type.
- * <p>
- * NOTE 2 &mdash; The tag used in the identifier octets is the tag of the chosen type,
- * as specified in the ASN.1 definition of the choice type.
- * </blockquote>
- * </p>
- */
-public interface ASN1Choice
-{
- // marker interface
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1Encodable.java b/core/src/main/java/org/bouncycastle/asn1/ASN1Encodable.java
deleted file mode 100644
index aa8825c0..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1Encodable.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.bouncycastle.asn1;
-
-/**
- * Basic interface to produce serialisers for ASN.1 encodings.
- */
-public interface ASN1Encodable
-{
- /**
- * Return an object, possibly constructed, of ASN.1 primitives
- * @return an ASN.1 primitive.
- */
- ASN1Primitive toASN1Primitive();
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1EncodableVector.java b/core/src/main/java/org/bouncycastle/asn1/ASN1EncodableVector.java
deleted file mode 100644
index 530da524..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1EncodableVector.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.util.Enumeration;
-import java.util.Vector;
-
-/**
- * Mutable class for building ASN.1 constructed objects.
- */
-public class ASN1EncodableVector
-{
- Vector v = new Vector();
-
- /**
- * Base constructor.
- */
- public ASN1EncodableVector()
- {
- }
-
- /**
- * Add an encodable to the vector.
- *
- * @param obj the encodable to add.
- */
- public void add(ASN1Encodable obj)
- {
- v.addElement(obj);
- }
-
- /**
- * Add the contents of another vector.
- *
- * @param other the vector to add.
- */
- public void addAll(ASN1EncodableVector other)
- {
- for (Enumeration en = other.v.elements(); en.hasMoreElements();)
- {
- v.addElement(en.nextElement());
- }
- }
-
- /**
- * Return the object at position i in this vector.
- *
- * @param i the index of the object of interest.
- * @return the object at position i.
- */
- public ASN1Encodable get(int i)
- {
- return (ASN1Encodable)v.elementAt(i);
- }
-
- /**
- * Return the size of the vector.
- *
- * @return the object count in the vector.
- */
- public int size()
- {
- return v.size();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1Encoding.java b/core/src/main/java/org/bouncycastle/asn1/ASN1Encoding.java
deleted file mode 100644
index 94a88426..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1Encoding.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.bouncycastle.asn1;
-
-/**
- * Supported encoding formats.
- */
-public interface ASN1Encoding
-{
- /**
- * DER - distinguished encoding rules.
- */
- static final String DER = "DER";
-
- /**
- * DL - definite length encoding.
- */
- static final String DL = "DL";
-
- /**
- * BER - basic encoding rules.
- */
- static final String BER = "BER";
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1Enumerated.java b/core/src/main/java/org/bouncycastle/asn1/ASN1Enumerated.java
deleted file mode 100644
index d6fd2e29..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1Enumerated.java
+++ /dev/null
@@ -1,174 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.math.BigInteger;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * Class representing the ASN.1 ENUMERATED type.
- */
-public class ASN1Enumerated
- extends ASN1Primitive
-{
- byte[] bytes;
-
- /**
- * return an enumerated from the passed in object
- *
- * @param obj an ASN1Enumerated or an object that can be converted into one.
- * @exception IllegalArgumentException if the object cannot be converted.
- * @return an ASN1Enumerated instance, or null.
- */
- public static ASN1Enumerated getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ASN1Enumerated)
- {
- return (ASN1Enumerated)obj;
- }
-
- if (obj instanceof byte[])
- {
- try
- {
- return (ASN1Enumerated)fromByteArray((byte[])obj);
- }
- catch (Exception e)
- {
- throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
- }
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return an Enumerated from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- * @return an ASN1Enumerated instance, or null.
- */
- public static ASN1Enumerated getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof ASN1Enumerated)
- {
- return getInstance(o);
- }
- else
- {
- return fromOctetString(((ASN1OctetString)o).getOctets());
- }
- }
-
- /**
- * Constructor from int.
- *
- * @param value the value of this enumerated.
- */
- public ASN1Enumerated(
- int value)
- {
- bytes = BigInteger.valueOf(value).toByteArray();
- }
-
- /**
- * Constructor from BigInteger
- *
- * @param value the value of this enumerated.
- */
- public ASN1Enumerated(
- BigInteger value)
- {
- bytes = value.toByteArray();
- }
-
- /**
- * Constructor from encoded BigInteger.
- *
- * @param bytes the value of this enumerated as an encoded BigInteger (signed).
- */
- public ASN1Enumerated(
- byte[] bytes)
- {
- this.bytes = bytes;
- }
-
- public BigInteger getValue()
- {
- return new BigInteger(bytes);
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- return 1 + StreamUtil.calculateBodyLength(bytes.length) + bytes.length;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.writeEncoded(BERTags.ENUMERATED, bytes);
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof ASN1Enumerated))
- {
- return false;
- }
-
- ASN1Enumerated other = (ASN1Enumerated)o;
-
- return Arrays.areEqual(this.bytes, other.bytes);
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(bytes);
- }
-
- private static ASN1Enumerated[] cache = new ASN1Enumerated[12];
-
- static ASN1Enumerated fromOctetString(byte[] enc)
- {
- if (enc.length > 1)
- {
- return new ASN1Enumerated(Arrays.clone(enc));
- }
-
- if (enc.length == 0)
- {
- throw new IllegalArgumentException("ENUMERATED has zero length");
- }
- int value = enc[0] & 0xff;
-
- if (value >= cache.length)
- {
- return new ASN1Enumerated(Arrays.clone(enc));
- }
-
- ASN1Enumerated possibleMatch = cache[value];
-
- if (possibleMatch == null)
- {
- possibleMatch = cache[value] = new ASN1Enumerated(Arrays.clone(enc));
- }
-
- return possibleMatch;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1Exception.java b/core/src/main/java/org/bouncycastle/asn1/ASN1Exception.java
deleted file mode 100644
index dc0ee203..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1Exception.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public class ASN1Exception
- extends IOException
-{
- private Throwable cause;
-
- ASN1Exception(String message)
- {
- super(message);
- }
-
- ASN1Exception(String message, Throwable cause)
- {
- super(message);
- this.cause = cause;
- }
-
- public Throwable getCause()
- {
- return cause;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1GeneralizedTime.java b/core/src/main/java/org/bouncycastle/asn1/ASN1GeneralizedTime.java
deleted file mode 100644
index d760a1fa..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1GeneralizedTime.java
+++ /dev/null
@@ -1,373 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-import java.util.SimpleTimeZone;
-import java.util.TimeZone;
-
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Strings;
-
-/**
- * Base class representing the ASN.1 GeneralizedTime type.
- * <p>
- * The main difference between these and UTC time is a 4 digit year.
- * </p>
- */
-public class ASN1GeneralizedTime
- extends ASN1Primitive
-{
- private byte[] time;
-
- /**
- * return a generalized time from the passed in object
- *
- * @param obj an ASN1GeneralizedTime or an object that can be converted into one.
- * @return an ASN1GeneralizedTime instance, or null.
- * @throws IllegalArgumentException if the object cannot be converted.
- */
- public static ASN1GeneralizedTime getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ASN1GeneralizedTime)
- {
- return (ASN1GeneralizedTime)obj;
- }
-
- if (obj instanceof byte[])
- {
- try
- {
- return (ASN1GeneralizedTime)fromByteArray((byte[])obj);
- }
- catch (Exception e)
- {
- throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
- }
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return a Generalized Time object from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @return an ASN1GeneralizedTime instance.
- * @throws IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static ASN1GeneralizedTime getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof ASN1GeneralizedTime)
- {
- return getInstance(o);
- }
- else
- {
- return new ASN1GeneralizedTime(((ASN1OctetString)o).getOctets());
- }
- }
-
- /**
- * The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z
- * for local time, or Z+-HHMM on the end, for difference between local
- * time and UTC time. The fractional second amount f must consist of at
- * least one number with trailing zeroes removed.
- *
- * @param time the time string.
- * @throws IllegalArgumentException if String is an illegal format.
- */
- public ASN1GeneralizedTime(
- String time)
- {
- this.time = Strings.toByteArray(time);
- try
- {
- this.getDate();
- }
- catch (ParseException e)
- {
- throw new IllegalArgumentException("invalid date string: " + e.getMessage());
- }
- }
-
- /**
- * Base constructor from a java.util.date object
- *
- * @param time a date object representing the time of interest.
- */
- public ASN1GeneralizedTime(
- Date time)
- {
- SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
-
- dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
-
- this.time = Strings.toByteArray(dateF.format(time));
- }
-
- /**
- * Base constructor from a java.util.date and Locale - you may need to use this if the default locale
- * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible with other ASN.1 implementations.
- *
- * @param time a date object representing the time of interest.
- * @param locale an appropriate Locale for producing an ASN.1 GeneralizedTime value.
- */
- public ASN1GeneralizedTime(
- Date time,
- Locale locale)
- {
- SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'", locale);
-
- dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
-
- this.time = Strings.toByteArray(dateF.format(time));
- }
-
- ASN1GeneralizedTime(
- byte[] bytes)
- {
- this.time = bytes;
- }
-
- /**
- * Return the time.
- *
- * @return The time string as it appeared in the encoded object.
- */
- public String getTimeString()
- {
- return Strings.fromByteArray(time);
- }
-
- /**
- * return the time - always in the form of
- * YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
- * <p/>
- * Normally in a certificate we would expect "Z" rather than "GMT",
- * however adding the "GMT" means we can just use:
- * <pre>
- * dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
- * </pre>
- * To read in the time and get a date which is compatible with our local
- * time zone.
- */
- public String getTime()
- {
- String stime = Strings.fromByteArray(time);
-
- //
- // standardise the format.
- //
- if (stime.charAt(stime.length() - 1) == 'Z')
- {
- return stime.substring(0, stime.length() - 1) + "GMT+00:00";
- }
- else
- {
- int signPos = stime.length() - 5;
- char sign = stime.charAt(signPos);
- if (sign == '-' || sign == '+')
- {
- return stime.substring(0, signPos)
- + "GMT"
- + stime.substring(signPos, signPos + 3)
- + ":"
- + stime.substring(signPos + 3);
- }
- else
- {
- signPos = stime.length() - 3;
- sign = stime.charAt(signPos);
- if (sign == '-' || sign == '+')
- {
- return stime.substring(0, signPos)
- + "GMT"
- + stime.substring(signPos)
- + ":00";
- }
- }
- }
- return stime + calculateGMTOffset();
- }
-
- private String calculateGMTOffset()
- {
- String sign = "+";
- TimeZone timeZone = TimeZone.getDefault();
- int offset = timeZone.getRawOffset();
- if (offset < 0)
- {
- sign = "-";
- offset = -offset;
- }
- int hours = offset / (60 * 60 * 1000);
- int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000);
-
- try
- {
- if (timeZone.useDaylightTime() && timeZone.inDaylightTime(this.getDate()))
- {
- hours += sign.equals("+") ? 1 : -1;
- }
- }
- catch (ParseException e)
- {
- // we'll do our best and ignore daylight savings
- }
-
- return "GMT" + sign + convert(hours) + ":" + convert(minutes);
- }
-
- private String convert(int time)
- {
- if (time < 10)
- {
- return "0" + time;
- }
-
- return Integer.toString(time);
- }
-
- public Date getDate()
- throws ParseException
- {
- SimpleDateFormat dateF;
- String stime = Strings.fromByteArray(time);
- String d = stime;
-
- if (stime.endsWith("Z"))
- {
- if (hasFractionalSeconds())
- {
- dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS'Z'");
- }
- else
- {
- dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
- }
-
- dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
- }
- else if (stime.indexOf('-') > 0 || stime.indexOf('+') > 0)
- {
- d = this.getTime();
- if (hasFractionalSeconds())
- {
- dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSz");
- }
- else
- {
- dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
- }
-
- dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
- }
- else
- {
- if (hasFractionalSeconds())
- {
- dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS");
- }
- else
- {
- dateF = new SimpleDateFormat("yyyyMMddHHmmss");
- }
-
- dateF.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID()));
- }
-
- if (hasFractionalSeconds())
- {
- // java misinterprets extra digits as being milliseconds...
- String frac = d.substring(14);
- int index;
- for (index = 1; index < frac.length(); index++)
- {
- char ch = frac.charAt(index);
- if (!('0' <= ch && ch <= '9'))
- {
- break;
- }
- }
-
- if (index - 1 > 3)
- {
- frac = frac.substring(0, 4) + frac.substring(index);
- d = d.substring(0, 14) + frac;
- }
- else if (index - 1 == 1)
- {
- frac = frac.substring(0, index) + "00" + frac.substring(index);
- d = d.substring(0, 14) + frac;
- }
- else if (index - 1 == 2)
- {
- frac = frac.substring(0, index) + "0" + frac.substring(index);
- d = d.substring(0, 14) + frac;
- }
- }
-
- return dateF.parse(d);
- }
-
- private boolean hasFractionalSeconds()
- {
- for (int i = 0; i != time.length; i++)
- {
- if (time[i] == '.')
- {
- if (i == 14)
- {
- return true;
- }
- }
- }
- return false;
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- int length = time.length;
-
- return 1 + StreamUtil.calculateBodyLength(length) + length;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.writeEncoded(BERTags.GENERALIZED_TIME, time);
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof ASN1GeneralizedTime))
- {
- return false;
- }
-
- return Arrays.areEqual(time, ((ASN1GeneralizedTime)o).time);
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(time);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1Generator.java b/core/src/main/java/org/bouncycastle/asn1/ASN1Generator.java
deleted file mode 100644
index 50cb7054..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1Generator.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.OutputStream;
-
-public abstract class ASN1Generator
-{
- protected OutputStream _out;
-
- public ASN1Generator(OutputStream out)
- {
- _out = out;
- }
-
- public abstract OutputStream getRawOutputStream();
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1InputStream.java b/core/src/main/java/org/bouncycastle/asn1/ASN1InputStream.java
deleted file mode 100644
index 1971af92..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1InputStream.java
+++ /dev/null
@@ -1,472 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayInputStream;
-import java.io.EOFException;
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.bouncycastle.util.io.Streams;
-
-/**
- * a general purpose ASN.1 decoder - note: this class differs from the
- * others in that it returns null after it has read the last object in
- * the stream. If an ASN.1 NULL is encountered a DER/BER Null object is
- * returned.
- */
-public class ASN1InputStream
- extends FilterInputStream
- implements BERTags
-{
- private final int limit;
- private final boolean lazyEvaluate;
-
- private final byte[][] tmpBuffers;
-
- public ASN1InputStream(
- InputStream is)
- {
- this(is, StreamUtil.findLimit(is));
- }
-
- /**
- * Create an ASN1InputStream based on the input byte array. The length of DER objects in
- * the stream is automatically limited to the length of the input array.
- *
- * @param input array containing ASN.1 encoded data.
- */
- public ASN1InputStream(
- byte[] input)
- {
- this(new ByteArrayInputStream(input), input.length);
- }
-
- /**
- * Create an ASN1InputStream based on the input byte array. The length of DER objects in
- * the stream is automatically limited to the length of the input array.
- *
- * @param input array containing ASN.1 encoded data.
- * @param lazyEvaluate true if parsing inside constructed objects can be delayed.
- */
- public ASN1InputStream(
- byte[] input,
- boolean lazyEvaluate)
- {
- this(new ByteArrayInputStream(input), input.length, lazyEvaluate);
- }
-
- /**
- * Create an ASN1InputStream where no DER object will be longer than limit.
- *
- * @param input stream containing ASN.1 encoded data.
- * @param limit maximum size of a DER encoded object.
- */
- public ASN1InputStream(
- InputStream input,
- int limit)
- {
- this(input, limit, false);
- }
-
- /**
- * Create an ASN1InputStream where no DER object will be longer than limit, and constructed
- * objects such as sequences will be parsed lazily.
- *
- * @param input stream containing ASN.1 encoded data.
- * @param lazyEvaluate true if parsing inside constructed objects can be delayed.
- */
- public ASN1InputStream(
- InputStream input,
- boolean lazyEvaluate)
- {
- this(input, StreamUtil.findLimit(input), lazyEvaluate);
- }
-
- /**
- * Create an ASN1InputStream where no DER object will be longer than limit, and constructed
- * objects such as sequences will be parsed lazily.
- *
- * @param input stream containing ASN.1 encoded data.
- * @param limit maximum size of a DER encoded object.
- * @param lazyEvaluate true if parsing inside constructed objects can be delayed.
- */
- public ASN1InputStream(
- InputStream input,
- int limit,
- boolean lazyEvaluate)
- {
- super(input);
- this.limit = limit;
- this.lazyEvaluate = lazyEvaluate;
- this.tmpBuffers = new byte[11][];
- }
-
- int getLimit()
- {
- return limit;
- }
-
- protected int readLength()
- throws IOException
- {
- return readLength(this, limit);
- }
-
- protected void readFully(
- byte[] bytes)
- throws IOException
- {
- if (Streams.readFully(this, bytes) != bytes.length)
- {
- throw new EOFException("EOF encountered in middle of object");
- }
- }
-
- /**
- * build an object given its tag and the number of bytes to construct it from.
- *
- * @param tag the full tag details.
- * @param tagNo the tagNo defined.
- * @param length the length of the object.
- * @return the resulting primitive.
- * @throws java.io.IOException on processing exception.
- */
- protected ASN1Primitive buildObject(
- int tag,
- int tagNo,
- int length)
- throws IOException
- {
- boolean isConstructed = (tag & CONSTRUCTED) != 0;
-
- DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this, length);
-
- if ((tag & APPLICATION) != 0)
- {
- return new DERApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
- }
-
- if ((tag & TAGGED) != 0)
- {
- return new ASN1StreamParser(defIn).readTaggedObject(isConstructed, tagNo);
- }
-
- if (isConstructed)
- {
- // TODO There are other tags that may be constructed (e.g. BIT_STRING)
- switch (tagNo)
- {
- case OCTET_STRING:
- //
- // yes, people actually do this...
- //
- ASN1EncodableVector v = buildDEREncodableVector(defIn);
- ASN1OctetString[] strings = new ASN1OctetString[v.size()];
-
- for (int i = 0; i != strings.length; i++)
- {
- strings[i] = (ASN1OctetString)v.get(i);
- }
-
- return new BEROctetString(strings);
- case SEQUENCE:
- if (lazyEvaluate)
- {
- return new LazyEncodedSequence(defIn.toByteArray());
- }
- else
- {
- return DERFactory.createSequence(buildDEREncodableVector(defIn));
- }
- case SET:
- return DERFactory.createSet(buildDEREncodableVector(defIn));
- case EXTERNAL:
- return new DERExternal(buildDEREncodableVector(defIn));
- default:
- throw new IOException("unknown tag " + tagNo + " encountered");
- }
- }
-
- return createPrimitiveDERObject(tagNo, defIn, tmpBuffers);
- }
-
- ASN1EncodableVector buildEncodableVector()
- throws IOException
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- ASN1Primitive o;
-
- while ((o = readObject()) != null)
- {
- v.add(o);
- }
-
- return v;
- }
-
- ASN1EncodableVector buildDEREncodableVector(
- DefiniteLengthInputStream dIn) throws IOException
- {
- return new ASN1InputStream(dIn).buildEncodableVector();
- }
-
- public ASN1Primitive readObject()
- throws IOException
- {
- int tag = read();
- if (tag <= 0)
- {
- if (tag == 0)
- {
- throw new IOException("unexpected end-of-contents marker");
- }
-
- return null;
- }
-
- //
- // calculate tag number
- //
- int tagNo = readTagNumber(this, tag);
-
- boolean isConstructed = (tag & CONSTRUCTED) != 0;
-
- //
- // calculate length
- //
- int length = readLength();
-
- if (length < 0) // indefinite length method
- {
- if (!isConstructed)
- {
- throw new IOException("indefinite length primitive encoding encountered");
- }
-
- IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this, limit);
- ASN1StreamParser sp = new ASN1StreamParser(indIn, limit);
-
- if ((tag & APPLICATION) != 0)
- {
- return new BERApplicationSpecificParser(tagNo, sp).getLoadedObject();
- }
-
- if ((tag & TAGGED) != 0)
- {
- return new BERTaggedObjectParser(true, tagNo, sp).getLoadedObject();
- }
-
- // TODO There are other tags that may be constructed (e.g. BIT_STRING)
- switch (tagNo)
- {
- case OCTET_STRING:
- return new BEROctetStringParser(sp).getLoadedObject();
- case SEQUENCE:
- return new BERSequenceParser(sp).getLoadedObject();
- case SET:
- return new BERSetParser(sp).getLoadedObject();
- case EXTERNAL:
- return new DERExternalParser(sp).getLoadedObject();
- default:
- throw new IOException("unknown BER object encountered");
- }
- }
- else
- {
- try
- {
- return buildObject(tag, tagNo, length);
- }
- catch (IllegalArgumentException e)
- {
- throw new ASN1Exception("corrupted stream detected", e);
- }
- }
- }
-
- static int readTagNumber(InputStream s, int tag)
- throws IOException
- {
- int tagNo = tag & 0x1f;
-
- //
- // with tagged object tag number is bottom 5 bits, or stored at the start of the content
- //
- if (tagNo == 0x1f)
- {
- tagNo = 0;
-
- int b = s.read();
-
- // X.690-0207 8.1.2.4.2
- // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
- if ((b & 0x7f) == 0) // Note: -1 will pass
- {
- throw new IOException("corrupted stream - invalid high tag number found");
- }
-
- while ((b >= 0) && ((b & 0x80) != 0))
- {
- tagNo |= (b & 0x7f);
- tagNo <<= 7;
- b = s.read();
- }
-
- if (b < 0)
- {
- throw new EOFException("EOF found inside tag value.");
- }
-
- tagNo |= (b & 0x7f);
- }
-
- return tagNo;
- }
-
- static int readLength(InputStream s, int limit)
- throws IOException
- {
- int length = s.read();
- if (length < 0)
- {
- throw new EOFException("EOF found when length expected");
- }
-
- if (length == 0x80)
- {
- return -1; // indefinite-length encoding
- }
-
- if (length > 127)
- {
- int size = length & 0x7f;
-
- // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
- if (size > 4)
- {
- throw new IOException("DER length more than 4 bytes: " + size);
- }
-
- length = 0;
- for (int i = 0; i < size; i++)
- {
- int next = s.read();
-
- if (next < 0)
- {
- throw new EOFException("EOF found reading length");
- }
-
- length = (length << 8) + next;
- }
-
- if (length < 0)
- {
- throw new IOException("corrupted stream - negative length found");
- }
-
- if (length >= limit) // after all we must have read at least 1 byte
- {
- throw new IOException("corrupted stream - out of bounds length found");
- }
- }
-
- return length;
- }
-
- private static byte[] getBuffer(DefiniteLengthInputStream defIn, byte[][] tmpBuffers)
- throws IOException
- {
- int len = defIn.getRemaining();
- if (defIn.getRemaining() < tmpBuffers.length)
- {
- byte[] buf = tmpBuffers[len];
-
- if (buf == null)
- {
- buf = tmpBuffers[len] = new byte[len];
- }
-
- Streams.readFully(defIn, buf);
-
- return buf;
- }
- else
- {
- return defIn.toByteArray();
- }
- }
-
- private static char[] getBMPCharBuffer(DefiniteLengthInputStream defIn)
- throws IOException
- {
- int len = defIn.getRemaining() / 2;
- char[] buf = new char[len];
- int totalRead = 0;
- while (totalRead < len)
- {
- int ch1 = defIn.read();
- if (ch1 < 0)
- {
- break;
- }
- int ch2 = defIn.read();
- if (ch2 < 0)
- {
- break;
- }
- buf[totalRead++] = (char)((ch1 << 8) | (ch2 & 0xff));
- }
-
- return buf;
- }
-
- static ASN1Primitive createPrimitiveDERObject(
- int tagNo,
- DefiniteLengthInputStream defIn,
- byte[][] tmpBuffers)
- throws IOException
- {
- switch (tagNo)
- {
- case BIT_STRING:
- return DERBitString.fromInputStream(defIn.getRemaining(), defIn);
- case BMP_STRING:
- return new DERBMPString(getBMPCharBuffer(defIn));
- case BOOLEAN:
- return ASN1Boolean.fromOctetString(getBuffer(defIn, tmpBuffers));
- case ENUMERATED:
- return ASN1Enumerated.fromOctetString(getBuffer(defIn, tmpBuffers));
- case GENERALIZED_TIME:
- return new ASN1GeneralizedTime(defIn.toByteArray());
- case GENERAL_STRING:
- return new DERGeneralString(defIn.toByteArray());
- case IA5_STRING:
- return new DERIA5String(defIn.toByteArray());
- case INTEGER:
- return new ASN1Integer(defIn.toByteArray(), false);
- case NULL:
- return DERNull.INSTANCE; // actual content is ignored (enforce 0 length?)
- case NUMERIC_STRING:
- return new DERNumericString(defIn.toByteArray());
- case OBJECT_IDENTIFIER:
- return ASN1ObjectIdentifier.fromOctetString(getBuffer(defIn, tmpBuffers));
- case OCTET_STRING:
- return new DEROctetString(defIn.toByteArray());
- case PRINTABLE_STRING:
- return new DERPrintableString(defIn.toByteArray());
- case T61_STRING:
- return new DERT61String(defIn.toByteArray());
- case UNIVERSAL_STRING:
- return new DERUniversalString(defIn.toByteArray());
- case UTC_TIME:
- return new ASN1UTCTime(defIn.toByteArray());
- case UTF8_STRING:
- return new DERUTF8String(defIn.toByteArray());
- case VISIBLE_STRING:
- return new DERVisibleString(defIn.toByteArray());
- default:
- throw new IOException("unknown tag " + tagNo + " encountered");
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1Integer.java b/core/src/main/java/org/bouncycastle/asn1/ASN1Integer.java
deleted file mode 100644
index 10326cf6..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1Integer.java
+++ /dev/null
@@ -1,157 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.math.BigInteger;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * Class representing the ASN.1 INTEGER type.
- */
-public class ASN1Integer
- extends ASN1Primitive
-{
- byte[] bytes;
-
- /**
- * return an integer from the passed in object
- *
- * @param obj an ASN1Integer or an object that can be converted into one.
- * @throws IllegalArgumentException if the object cannot be converted.
- * @return an ASN1Integer instance.
- */
- public static ASN1Integer getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ASN1Integer)
- {
- return (ASN1Integer)obj;
- }
-
- if (obj instanceof byte[])
- {
- try
- {
- return (ASN1Integer)fromByteArray((byte[])obj);
- }
- catch (Exception e)
- {
- throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
- }
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return an Integer from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @throws IllegalArgumentException if the tagged object cannot
- * be converted.
- * @return an ASN1Integer instance.
- */
- public static ASN1Integer getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof ASN1Integer)
- {
- return getInstance(o);
- }
- else
- {
- return new ASN1Integer(ASN1OctetString.getInstance(obj.getObject()).getOctets());
- }
- }
-
- public ASN1Integer(
- long value)
- {
- bytes = BigInteger.valueOf(value).toByteArray();
- }
-
- public ASN1Integer(
- BigInteger value)
- {
- bytes = value.toByteArray();
- }
-
- public ASN1Integer(
- byte[] bytes)
- {
- this(bytes, true);
- }
-
- ASN1Integer(byte[] bytes, boolean clone)
- {
- this.bytes = (clone) ? Arrays.clone(bytes) : bytes;
- }
-
- public BigInteger getValue()
- {
- return new BigInteger(bytes);
- }
-
- /**
- * in some cases positive values get crammed into a space,
- * that's not quite big enough...
- * @return the BigInteger that results from treating this ASN.1 INTEGER as unsigned.
- */
- public BigInteger getPositiveValue()
- {
- return new BigInteger(1, bytes);
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- return 1 + StreamUtil.calculateBodyLength(bytes.length) + bytes.length;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.writeEncoded(BERTags.INTEGER, bytes);
- }
-
- public int hashCode()
- {
- int value = 0;
-
- for (int i = 0; i != bytes.length; i++)
- {
- value ^= (bytes[i] & 0xff) << (i % 4);
- }
-
- return value;
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof ASN1Integer))
- {
- return false;
- }
-
- ASN1Integer other = (ASN1Integer)o;
-
- return Arrays.areEqual(bytes, other.bytes);
- }
-
- public String toString()
- {
- return getValue().toString();
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1Null.java b/core/src/main/java/org/bouncycastle/asn1/ASN1Null.java
deleted file mode 100644
index f39d1206..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1Null.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * A NULL object - use DERNull.INSTANCE for populating structures.
- */
-public abstract class ASN1Null
- extends ASN1Primitive
-{
- /**
- * Return an instance of ASN.1 NULL from the passed in object.
- * <p>
- * Accepted inputs:
- * <ul>
- * <li> null &rarr; null
- * <li> {@link ASN1Null} object
- * <li> a byte[] containing ASN.1 NULL object
- * </ul>
- * </p>
- *
- * @param o object to be converted.
- * @return an instance of ASN1Null, or null.
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static ASN1Null getInstance(Object o)
- {
- if (o instanceof ASN1Null)
- {
- return (ASN1Null)o;
- }
-
- if (o != null)
- {
- try
- {
- return ASN1Null.getInstance(ASN1Primitive.fromByteArray((byte[])o));
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("failed to construct NULL from byte[]: " + e.getMessage());
- }
- catch (ClassCastException e)
- {
- throw new IllegalArgumentException("unknown object in getInstance(): " + o.getClass().getName());
- }
- }
-
- return null;
- }
-
- public int hashCode()
- {
- return -1;
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof ASN1Null))
- {
- return false;
- }
-
- return true;
- }
-
- abstract void encode(ASN1OutputStream out)
- throws IOException;
-
- public String toString()
- {
- return "NULL";
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1Object.java b/core/src/main/java/org/bouncycastle/asn1/ASN1Object.java
deleted file mode 100644
index cfda1a66..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1Object.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-/**
- * Base class for defining an ASN.1 object.
- */
-public abstract class ASN1Object
- implements ASN1Encodable
-{
- /**
- * Return the default BER or DER encoding for this object.
- *
- * @return BER/DER byte encoded object.
- * @throws java.io.IOException on encoding error.
- */
- public byte[] getEncoded()
- throws IOException
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- ASN1OutputStream aOut = new ASN1OutputStream(bOut);
-
- aOut.writeObject(this);
-
- return bOut.toByteArray();
- }
-
- /**
- * Return either the default for "BER" or a DER encoding if "DER" is specified.
- *
- * @param encoding name of encoding to use.
- * @return byte encoded object.
- * @throws IOException on encoding error.
- */
- public byte[] getEncoded(
- String encoding)
- throws IOException
- {
- if (encoding.equals(ASN1Encoding.DER))
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- DEROutputStream dOut = new DEROutputStream(bOut);
-
- dOut.writeObject(this);
-
- return bOut.toByteArray();
- }
- else if (encoding.equals(ASN1Encoding.DL))
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- DLOutputStream dOut = new DLOutputStream(bOut);
-
- dOut.writeObject(this);
-
- return bOut.toByteArray();
- }
-
- return this.getEncoded();
- }
-
- public int hashCode()
- {
- return this.toASN1Primitive().hashCode();
- }
-
- public boolean equals(
- Object o)
- {
- if (this == o)
- {
- return true;
- }
-
- if (!(o instanceof ASN1Encodable))
- {
- return false;
- }
-
- ASN1Encodable other = (ASN1Encodable)o;
-
- return this.toASN1Primitive().equals(other.toASN1Primitive());
- }
-
- /**
- * @deprecated use toASN1Primitive()
- * @return the underlying primitive type.
- */
- public ASN1Primitive toASN1Object()
- {
- return this.toASN1Primitive();
- }
-
- /**
- * Return true if obj is a byte array and represents an object with the given tag value.
- *
- * @param obj object of interest.
- * @param tagValue tag value to check for.
- * @return true if obj is a byte encoding starting with the given tag value, false otherwise.
- */
- protected static boolean hasEncodedTagValue(Object obj, int tagValue)
- {
- return (obj instanceof byte[]) && ((byte[])obj)[0] == tagValue;
- }
-
- /**
- * Method providing a primitive representation of this object suitable for encoding.
- * @return a primitive representation of this object.
- */
- public abstract ASN1Primitive toASN1Primitive();
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java b/core/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java
deleted file mode 100644
index 4de41b75..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java
+++ /dev/null
@@ -1,472 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * Class representing the ASN.1 OBJECT IDENTIFIER type.
- */
-public class ASN1ObjectIdentifier
- extends ASN1Primitive
-{
- String identifier;
-
- private byte[] body;
-
- /**
- * return an OID from the passed in object
- * @param obj an ASN1ObjectIdentifier or an object that can be converted into one.
- * @throws IllegalArgumentException if the object cannot be converted.
- * @return an ASN1ObjectIdentifier instance, or null.
- */
- public static ASN1ObjectIdentifier getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ASN1ObjectIdentifier)
- {
- return (ASN1ObjectIdentifier)obj;
- }
-
- if (obj instanceof ASN1Encodable && ((ASN1Encodable)obj).toASN1Primitive() instanceof ASN1ObjectIdentifier)
- {
- return (ASN1ObjectIdentifier)((ASN1Encodable)obj).toASN1Primitive();
- }
-
- if (obj instanceof byte[])
- {
- byte[] enc = (byte[])obj;
- try
- {
- return (ASN1ObjectIdentifier)fromByteArray(enc);
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("failed to construct object identifier from byte[]: " + e.getMessage());
- }
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return an Object Identifier from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @throws IllegalArgumentException if the tagged object cannot
- * be converted.
- * @return an ASN1ObjectIdentifier instance, or null.
- */
- public static ASN1ObjectIdentifier getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof ASN1ObjectIdentifier)
- {
- return getInstance(o);
- }
- else
- {
- return ASN1ObjectIdentifier.fromOctetString(ASN1OctetString.getInstance(obj.getObject()).getOctets());
- }
- }
-
- private static final long LONG_LIMIT = (Long.MAX_VALUE >> 7) - 0x7f;
-
- ASN1ObjectIdentifier(
- byte[] bytes)
- {
- StringBuffer objId = new StringBuffer();
- long value = 0;
- BigInteger bigValue = null;
- boolean first = true;
-
- for (int i = 0; i != bytes.length; i++)
- {
- int b = bytes[i] & 0xff;
-
- if (value <= LONG_LIMIT)
- {
- value += (b & 0x7f);
- if ((b & 0x80) == 0) // end of number reached
- {
- if (first)
- {
- if (value < 40)
- {
- objId.append('0');
- }
- else if (value < 80)
- {
- objId.append('1');
- value -= 40;
- }
- else
- {
- objId.append('2');
- value -= 80;
- }
- first = false;
- }
-
- objId.append('.');
- objId.append(value);
- value = 0;
- }
- else
- {
- value <<= 7;
- }
- }
- else
- {
- if (bigValue == null)
- {
- bigValue = BigInteger.valueOf(value);
- }
- bigValue = bigValue.or(BigInteger.valueOf(b & 0x7f));
- if ((b & 0x80) == 0)
- {
- if (first)
- {
- objId.append('2');
- bigValue = bigValue.subtract(BigInteger.valueOf(80));
- first = false;
- }
-
- objId.append('.');
- objId.append(bigValue);
- bigValue = null;
- value = 0;
- }
- else
- {
- bigValue = bigValue.shiftLeft(7);
- }
- }
- }
-
- this.identifier = objId.toString();
- this.body = Arrays.clone(bytes);
- }
-
- /**
- * Create an OID based on the passed in String.
- *
- * @param identifier a string representation of an OID.
- */
- public ASN1ObjectIdentifier(
- String identifier)
- {
- if (identifier == null)
- {
- throw new IllegalArgumentException("'identifier' cannot be null");
- }
- if (!isValidIdentifier(identifier))
- {
- throw new IllegalArgumentException("string " + identifier + " not an OID");
- }
-
- this.identifier = identifier;
- }
-
- /**
- * Create an OID that creates a branch under the current one.
- *
- * @param branchID node numbers for the new branch.
- * @return the OID for the new created branch.
- */
- ASN1ObjectIdentifier(ASN1ObjectIdentifier oid, String branchID)
- {
- if (!isValidBranchID(branchID, 0))
- {
- throw new IllegalArgumentException("string " + branchID + " not a valid OID branch");
- }
-
- this.identifier = oid.getId() + "." + branchID;
- }
-
- /**
- * Return the OID as a string.
- *
- * @return the string representation of the OID carried by this object.
- */
- public String getId()
- {
- return identifier;
- }
-
- /**
- * Return an OID that creates a branch under the current one.
- *
- * @param branchID node numbers for the new branch.
- * @return the OID for the new created branch.
- */
- public ASN1ObjectIdentifier branch(String branchID)
- {
- return new ASN1ObjectIdentifier(this, branchID);
- }
-
- /**
- * Return true if this oid is an extension of the passed in branch, stem.
- *
- * @param stem the arc or branch that is a possible parent.
- * @return true if the branch is on the passed in stem, false otherwise.
- */
- public boolean on(ASN1ObjectIdentifier stem)
- {
- String id = getId(), stemId = stem.getId();
- return id.length() > stemId.length() && id.charAt(stemId.length()) == '.' && id.startsWith(stemId);
- }
-
- private void writeField(
- ByteArrayOutputStream out,
- long fieldValue)
- {
- byte[] result = new byte[9];
- int pos = 8;
- result[pos] = (byte)((int)fieldValue & 0x7f);
- while (fieldValue >= (1L << 7))
- {
- fieldValue >>= 7;
- result[--pos] = (byte)((int)fieldValue & 0x7f | 0x80);
- }
- out.write(result, pos, 9 - pos);
- }
-
- private void writeField(
- ByteArrayOutputStream out,
- BigInteger fieldValue)
- {
- int byteCount = (fieldValue.bitLength() + 6) / 7;
- if (byteCount == 0)
- {
- out.write(0);
- }
- else
- {
- BigInteger tmpValue = fieldValue;
- byte[] tmp = new byte[byteCount];
- for (int i = byteCount - 1; i >= 0; i--)
- {
- tmp[i] = (byte)((tmpValue.intValue() & 0x7f) | 0x80);
- tmpValue = tmpValue.shiftRight(7);
- }
- tmp[byteCount - 1] &= 0x7f;
- out.write(tmp, 0, tmp.length);
- }
- }
-
- private void doOutput(ByteArrayOutputStream aOut)
- {
- OIDTokenizer tok = new OIDTokenizer(identifier);
- int first = Integer.parseInt(tok.nextToken()) * 40;
-
- String secondToken = tok.nextToken();
- if (secondToken.length() <= 18)
- {
- writeField(aOut, first + Long.parseLong(secondToken));
- }
- else
- {
- writeField(aOut, new BigInteger(secondToken).add(BigInteger.valueOf(first)));
- }
-
- while (tok.hasMoreTokens())
- {
- String token = tok.nextToken();
- if (token.length() <= 18)
- {
- writeField(aOut, Long.parseLong(token));
- }
- else
- {
- writeField(aOut, new BigInteger(token));
- }
- }
- }
-
- protected synchronized byte[] getBody()
- {
- if (body == null)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- doOutput(bOut);
-
- body = bOut.toByteArray();
- }
-
- return body;
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- throws IOException
- {
- int length = getBody().length;
-
- return 1 + StreamUtil.calculateBodyLength(length) + length;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- byte[] enc = getBody();
-
- out.write(BERTags.OBJECT_IDENTIFIER);
- out.writeLength(enc.length);
- out.write(enc);
- }
-
- public int hashCode()
- {
- return identifier.hashCode();
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof ASN1ObjectIdentifier))
- {
- return false;
- }
-
- return identifier.equals(((ASN1ObjectIdentifier)o).identifier);
- }
-
- public String toString()
- {
- return getId();
- }
-
- private static boolean isValidBranchID(
- String branchID, int start)
- {
- boolean periodAllowed = false;
-
- int pos = branchID.length();
- while (--pos >= start)
- {
- char ch = branchID.charAt(pos);
-
- // TODO Leading zeroes?
- if ('0' <= ch && ch <= '9')
- {
- periodAllowed = true;
- continue;
- }
-
- if (ch == '.')
- {
- if (!periodAllowed)
- {
- return false;
- }
-
- periodAllowed = false;
- continue;
- }
-
- return false;
- }
-
- return periodAllowed;
- }
-
- private static boolean isValidIdentifier(
- String identifier)
- {
- if (identifier.length() < 3 || identifier.charAt(1) != '.')
- {
- return false;
- }
-
- char first = identifier.charAt(0);
- if (first < '0' || first > '2')
- {
- return false;
- }
-
- return isValidBranchID(identifier, 2);
- }
-
- private static ASN1ObjectIdentifier[][] cache = new ASN1ObjectIdentifier[256][];
-
- static ASN1ObjectIdentifier fromOctetString(byte[] enc)
- {
- if (enc.length < 3)
- {
- return new ASN1ObjectIdentifier(enc);
- }
-
- int idx1 = enc[enc.length - 2] & 0xff;
- // in this case top bit is always zero
- int idx2 = enc[enc.length - 1] & 0x7f;
-
- ASN1ObjectIdentifier possibleMatch;
-
- synchronized (cache)
- {
- ASN1ObjectIdentifier[] first = cache[idx1];
- if (first == null)
- {
- first = cache[idx1] = new ASN1ObjectIdentifier[128];
- }
-
- possibleMatch = first[idx2];
- if (possibleMatch == null)
- {
- return first[idx2] = new ASN1ObjectIdentifier(enc);
- }
-
- if (Arrays.areEqual(enc, possibleMatch.getBody()))
- {
- return possibleMatch;
- }
-
- idx1 = (idx1 + 1) & 0xff;
- first = cache[idx1];
- if (first == null)
- {
- first = cache[idx1] = new ASN1ObjectIdentifier[128];
- }
-
- possibleMatch = first[idx2];
- if (possibleMatch == null)
- {
- return first[idx2] = new ASN1ObjectIdentifier(enc);
- }
-
- if (Arrays.areEqual(enc, possibleMatch.getBody()))
- {
- return possibleMatch;
- }
-
- idx2 = (idx2 + 1) & 0x7f;
- possibleMatch = first[idx2];
- if (possibleMatch == null)
- {
- return first[idx2] = new ASN1ObjectIdentifier(enc);
- }
- }
-
- if (Arrays.areEqual(enc, possibleMatch.getBody()))
- {
- return possibleMatch;
- }
-
- return new ASN1ObjectIdentifier(enc);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1OctetString.java b/core/src/main/java/org/bouncycastle/asn1/ASN1OctetString.java
deleted file mode 100644
index 200b66a3..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1OctetString.java
+++ /dev/null
@@ -1,251 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-
-/**
- * Abstract base for the ASN.1 OCTET STRING data type
- * <p>
- * This supports BER, and DER forms of the data.
- * </p><p>
- * DER form is always primitive single OCTET STRING, while
- * BER support includes the constructed forms.
- * </p>
- * <hr>
- * <p><b>X.690</b></p>
- * <p><b>8: Basic encoding rules</b></p>
- * <p><b>8.7 Encoding of an octetstring value</b></p>
- * <p>
- * <b>8.7.1</b> The encoding of an octetstring value shall be
- * either primitive or constructed at the option of the sender.
- * <blockquote>
- * NOTE &mdash; Where it is necessary to transfer part of an octet string
- * before the entire OCTET STRING is available, the constructed encoding
- * is used.
- * </blockquote>
- * <p>
- * <b>8.7.2</b> The primitive encoding contains zero,
- * one or more contents octets equal in value to the octets
- * in the data value, in the order they appear in the data value,
- * and with the most significant bit of an octet of the data value
- * aligned with the most significant bit of an octet of the contents octets.
- * </p>
- * <p>
- * <b>8.7.3</b> The contents octets for the constructed encoding shall consist
- * of zero, one, or more encodings.
- * <blockquote>
- * NOTE &mdash; Each such encoding includes identifier, length, and contents octets,
- * and may include end-of-contents octets if it is constructed.
- * </blockquote>
- * </p>
- * <p>
- * <b>8.7.3.1</b> To encode an octetstring value in this way,
- * it is segmented. Each segment shall consist of a series of
- * consecutive octets of the value. There shall be no significance
- * placed on the segment boundaries.
- * <blockquote>
- * NOTE &mdash; A segment may be of size zero, i.e. contain no octets.
- * </blockquote>
- * </p>
- * <p>
- * <b>8.7.3.2</b> Each encoding in the contents octets shall represent
- * a segment of the overall octetstring, the encoding arising from
- * a recursive application of this subclause.
- * In this recursive application, each segment is treated as if it were
- * a octetstring value. The encodings of the segments shall appear in the contents
- * octets in the order in which their octets appear in the overall value.
- * <blockquote>
- * NOTE 1 &mdash; As a consequence of this recursion,
- * each encoding in the contents octets may itself
- * be primitive or constructed.
- * However, such encodings will usually be primitive.
- * </p><p>
- * NOTE 2 &mdash; In particular, the tags in the contents octets are always universal class, number 4.
- * </blockquote>
- * </p>
- * <p><b>9: Canonical encoding rules</b></p>
- * <p><b>9.1 Length forms</b></p>
- * <p>
- * If the encoding is constructed, it shall employ the indefinite length form.
- * If the encoding is primitive, it shall include the fewest length octets necessary.
- * [Contrast with 8.1.3.2 b).]
- * </p>
- * <p><b>9.2 String encoding forms</b></p>
- * <p>
- * BIT STRING, OCTET STRING,and restricted character string
- * values shall be encoded with a primitive encoding if they would
- * require no more than 1000 contents octets, and as a constructed
- * encoding otherwise. The string fragments contained in
- * the constructed encoding shall be encoded with a primitive encoding.
- * The encoding of each fragment, except possibly
- * the last, shall have 1000 contents octets. (Contrast with 8.21.6.)
- * </p>
- * <b>10: Distinguished encoding rules</b>
- * </p><p>
- * <b>10.1 Length forms</b>
- * The definite form of length encoding shall be used,
- * encoded in the minimum number of octets.
- * [Contrast with 8.1.3.2 b).]
- * </p><p>
- * <b>10.2 String encoding forms</b>
- * For BIT STRING, OCTET STRING and restricted character string types,
- * the constructed form of encoding shall not be used.
- * (Contrast with 8.21.6.)
- * </p>
- */
-public abstract class ASN1OctetString
- extends ASN1Primitive
- implements ASN1OctetStringParser
-{
- byte[] string;
-
- /**
- * return an Octet String from a tagged object.
- *
- * @param obj the tagged object holding the object we want.
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static ASN1OctetString getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof ASN1OctetString)
- {
- return getInstance(o);
- }
- else
- {
- return BEROctetString.fromSequence(ASN1Sequence.getInstance(o));
- }
- }
-
- /**
- * return an Octet String from the given object.
- *
- * @param obj the object we want converted.
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static ASN1OctetString getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ASN1OctetString)
- {
- return (ASN1OctetString)obj;
- }
- else if (obj instanceof byte[])
- {
- try
- {
- return ASN1OctetString.getInstance(ASN1Primitive.fromByteArray((byte[])obj));
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("failed to construct OCTET STRING from byte[]: " + e.getMessage());
- }
- }
- else if (obj instanceof ASN1Encodable)
- {
- ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive();
-
- if (primitive instanceof ASN1OctetString)
- {
- return (ASN1OctetString)primitive;
- }
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * @param string the octets making up the octet string.
- */
- public ASN1OctetString(
- byte[] string)
- {
- if (string == null)
- {
- throw new NullPointerException("string cannot be null");
- }
- this.string = string;
- }
-
- /**
- * Return the content of the OCTET STRING as an InputStream.
- *
- * @return an InputStream representing the OCTET STRING's content.
- */
- public InputStream getOctetStream()
- {
- return new ByteArrayInputStream(string);
- }
-
- /**
- * Return the parser associated with this object.
- *
- * @return a parser based on this OCTET STRING
- */
- public ASN1OctetStringParser parser()
- {
- return this;
- }
-
- /**
- * Return the content of the OCTET STRING as a byte array.
- *
- * @return the byte[] representing the OCTET STRING's content.
- */
- public byte[] getOctets()
- {
- return string;
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(this.getOctets());
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof ASN1OctetString))
- {
- return false;
- }
-
- ASN1OctetString other = (ASN1OctetString)o;
-
- return Arrays.areEqual(string, other.string);
- }
-
- public ASN1Primitive getLoadedObject()
- {
- return this.toASN1Primitive();
- }
-
- ASN1Primitive toDERObject()
- {
- return new DEROctetString(string);
- }
-
- ASN1Primitive toDLObject()
- {
- return new DEROctetString(string);
- }
-
- abstract void encode(ASN1OutputStream out)
- throws IOException;
-
- public String toString()
- {
- return "#"+new String(Hex.encode(string));
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1OctetStringParser.java b/core/src/main/java/org/bouncycastle/asn1/ASN1OctetStringParser.java
deleted file mode 100644
index 122331f2..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1OctetStringParser.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.InputStream;
-
-/**
- * A basic parser for an OCTET STRING object
- */
-public interface ASN1OctetStringParser
- extends ASN1Encodable, InMemoryRepresentable
-{
- /**
- * Return the content of the OCTET STRING as an InputStream.
- *
- * @return an InputStream representing the OCTET STRING's content.
- */
- public InputStream getOctetStream();
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1OutputStream.java b/core/src/main/java/org/bouncycastle/asn1/ASN1OutputStream.java
deleted file mode 100644
index 9a46a78b..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1OutputStream.java
+++ /dev/null
@@ -1,194 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * Stream that produces output based on the default encoding for the passed in objects.
- */
-public class ASN1OutputStream
-{
- private OutputStream os;
-
- public ASN1OutputStream(
- OutputStream os)
- {
- this.os = os;
- }
-
- void writeLength(
- int length)
- throws IOException
- {
- if (length > 127)
- {
- int size = 1;
- int val = length;
-
- while ((val >>>= 8) != 0)
- {
- size++;
- }
-
- write((byte)(size | 0x80));
-
- for (int i = (size - 1) * 8; i >= 0; i -= 8)
- {
- write((byte)(length >> i));
- }
- }
- else
- {
- write((byte)length);
- }
- }
-
- void write(int b)
- throws IOException
- {
- os.write(b);
- }
-
- void write(byte[] bytes)
- throws IOException
- {
- os.write(bytes);
- }
-
- void write(byte[] bytes, int off, int len)
- throws IOException
- {
- os.write(bytes, off, len);
- }
-
- void writeEncoded(
- int tag,
- byte[] bytes)
- throws IOException
- {
- write(tag);
- writeLength(bytes.length);
- write(bytes);
- }
-
- void writeTag(int flags, int tagNo)
- throws IOException
- {
- if (tagNo < 31)
- {
- write(flags | tagNo);
- }
- else
- {
- write(flags | 0x1f);
- if (tagNo < 128)
- {
- write(tagNo);
- }
- else
- {
- byte[] stack = new byte[5];
- int pos = stack.length;
-
- stack[--pos] = (byte)(tagNo & 0x7F);
-
- do
- {
- tagNo >>= 7;
- stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
- }
- while (tagNo > 127);
-
- write(stack, pos, stack.length - pos);
- }
- }
- }
-
- void writeEncoded(int flags, int tagNo, byte[] bytes)
- throws IOException
- {
- writeTag(flags, tagNo);
- writeLength(bytes.length);
- write(bytes);
- }
-
- protected void writeNull()
- throws IOException
- {
- os.write(BERTags.NULL);
- os.write(0x00);
- }
-
- public void writeObject(
- ASN1Encodable obj)
- throws IOException
- {
- if (obj != null)
- {
- obj.toASN1Primitive().encode(this);
- }
- else
- {
- throw new IOException("null object detected");
- }
- }
-
- void writeImplicitObject(ASN1Primitive obj)
- throws IOException
- {
- if (obj != null)
- {
- obj.encode(new ImplicitOutputStream(os));
- }
- else
- {
- throw new IOException("null object detected");
- }
- }
-
- public void close()
- throws IOException
- {
- os.close();
- }
-
- public void flush()
- throws IOException
- {
- os.flush();
- }
-
- ASN1OutputStream getDERSubStream()
- {
- return new DEROutputStream(os);
- }
-
- ASN1OutputStream getDLSubStream()
- {
- return new DLOutputStream(os);
- }
-
- private class ImplicitOutputStream
- extends ASN1OutputStream
- {
- private boolean first = true;
-
- public ImplicitOutputStream(OutputStream os)
- {
- super(os);
- }
-
- public void write(int b)
- throws IOException
- {
- if (first)
- {
- first = false;
- }
- else
- {
- super.write(b);
- }
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1ParsingException.java b/core/src/main/java/org/bouncycastle/asn1/ASN1ParsingException.java
deleted file mode 100644
index 995b5e93..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1ParsingException.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.asn1;
-
-public class ASN1ParsingException
- extends IllegalStateException
-{
- private Throwable cause;
-
- public ASN1ParsingException(String message)
- {
- super(message);
- }
-
- public ASN1ParsingException(String message, Throwable cause)
- {
- super(message);
- this.cause = cause;
- }
-
- public Throwable getCause()
- {
- return cause;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1Primitive.java b/core/src/main/java/org/bouncycastle/asn1/ASN1Primitive.java
deleted file mode 100644
index 3c887e55..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1Primitive.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * Base class for ASN.1 primitive objects. These are the actual objects used to generate byte encodings.
- */
-public abstract class ASN1Primitive
- extends ASN1Object
-{
- ASN1Primitive()
- {
-
- }
-
- /**
- * Create a base ASN.1 object from a byte stream.
- *
- * @param data the byte stream to parse.
- * @return the base ASN.1 object represented by the byte stream.
- * @exception IOException if there is a problem parsing the data.
- */
- public static ASN1Primitive fromByteArray(byte[] data)
- throws IOException
- {
- ASN1InputStream aIn = new ASN1InputStream(data);
-
- try
- {
- return aIn.readObject();
- }
- catch (ClassCastException e)
- {
- throw new IOException("cannot recognise object in stream");
- }
- }
-
- public final boolean equals(Object o)
- {
- if (this == o)
- {
- return true;
- }
-
- return (o instanceof ASN1Encodable) && asn1Equals(((ASN1Encodable)o).toASN1Primitive());
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return this;
- }
-
- /**
- * Return the current object as one which encodes using Distinguished Encoding Rules.
- *
- * @return a DER version of this.
- */
- ASN1Primitive toDERObject()
- {
- return this;
- }
-
- /**
- * Return the current object as one which encodes using Definite Length encoding.
- *
- * @return a DL version of this.
- */
- ASN1Primitive toDLObject()
- {
- return this;
- }
-
- public abstract int hashCode();
-
- abstract boolean isConstructed();
-
- abstract int encodedLength() throws IOException;
-
- abstract void encode(ASN1OutputStream out) throws IOException;
-
- abstract boolean asn1Equals(ASN1Primitive o);
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1Sequence.java b/core/src/main/java/org/bouncycastle/asn1/ASN1Sequence.java
deleted file mode 100644
index aa543f28..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1Sequence.java
+++ /dev/null
@@ -1,382 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Vector;
-
-/**
- * ASN.1 <code>SEQUENCE</code> and <code>SEQUENCE OF</code> constructs.
- * <p>
- * DER form is always definite form length fields, while
- * BER support uses indefinite form.
- * <hr>
- * <p><b>X.690</b></p>
- * <p><b>8: Basic encoding rules</b></p>
- * <p><b>8.9 Encoding of a sequence value </b></p>
- * 8.9.1 The encoding of a sequence value shall be constructed.
- * <p>
- * <b>8.9.2</b> The contents octets shall consist of the complete
- * encoding of one data value from each of the types listed in
- * the ASN.1 definition of the sequence type, in the order of
- * their appearance in the definition, unless the type was referenced
- * with the keyword <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
- * </p><p>
- * <b>8.9.3</b> The encoding of a data value may, but need not,
- * be present for a type which was referenced with the keyword
- * <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
- * If present, it shall appear in the encoding at the point
- * corresponding to the appearance of the type in the ASN.1 definition.
- * </p><p>
- * <b>8.10 Encoding of a sequence-of value </b>
- * </p><p>
- * <b>8.10.1</b> The encoding of a sequence-of value shall be constructed.
- * <p>
- * <b>8.10.2</b> The contents octets shall consist of zero,
- * one or more complete encodings of data values from the type listed in
- * the ASN.1 definition.
- * <p>
- * <b>8.10.3</b> The order of the encodings of the data values shall be
- * the same as the order of the data values in the sequence-of value to
- * be encoded.
- * </p>
- * <p><b>9: Canonical encoding rules</b></p>
- * <p><b>9.1 Length forms</b></p>
- * If the encoding is constructed, it shall employ the indefinite length form.
- * If the encoding is primitive, it shall include the fewest length octets necessary.
- * [Contrast with 8.1.3.2 b).]
- *
- * <p><b>11: Restrictions on BER employed by both CER and DER</b></p>
- * <p><b>11.5 Set and sequence components with default value</b></p>
- * The encoding of a set value or sequence value shall not include
- * an encoding for any component value which is equal to
- * its default value.
- */
-public abstract class ASN1Sequence
- extends ASN1Primitive
-{
- protected Vector seq = new Vector();
-
- /**
- * Return an ASN1Sequence from the given object.
- *
- * @param obj the object we want converted.
- * @exception IllegalArgumentException if the object cannot be converted.
- * @return an ASN1Sequence instance, or null.
- */
- public static ASN1Sequence getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ASN1Sequence)
- {
- return (ASN1Sequence)obj;
- }
- else if (obj instanceof ASN1SequenceParser)
- {
- return ASN1Sequence.getInstance(((ASN1SequenceParser)obj).toASN1Primitive());
- }
- else if (obj instanceof byte[])
- {
- try
- {
- return ASN1Sequence.getInstance(fromByteArray((byte[])obj));
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("failed to construct sequence from byte[]: " + e.getMessage());
- }
- }
- else if (obj instanceof ASN1Encodable)
- {
- ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive();
-
- if (primitive instanceof ASN1Sequence)
- {
- return (ASN1Sequence)primitive;
- }
- }
-
- throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * Return an ASN1 sequence from a tagged object. There is a special
- * case here, if an object appears to have been explicitly tagged on
- * reading but we were expecting it to be implicitly tagged in the
- * normal course of events it indicates that we lost the surrounding
- * sequence - so we need to add it back (this will happen if the tagged
- * object is a sequence that contains other sequences). If you are
- * dealing with implicitly tagged sequences you really <b>should</b>
- * be using this method.
- *
- * @param obj the tagged object.
- * @param explicit true if the object is meant to be explicitly tagged,
- * false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- * @return an ASN1Sequence instance.
- */
- public static ASN1Sequence getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- if (explicit)
- {
- if (!obj.isExplicit())
- {
- throw new IllegalArgumentException("object implicit - explicit expected.");
- }
-
- return ASN1Sequence.getInstance(obj.getObject().toASN1Primitive());
- }
- else
- {
- //
- // constructed object which appears to be explicitly tagged
- // when it should be implicit means we have to add the
- // surrounding sequence.
- //
- if (obj.isExplicit())
- {
- if (obj instanceof BERTaggedObject)
- {
- return new BERSequence(obj.getObject());
- }
- else
- {
- return new DLSequence(obj.getObject());
- }
- }
- else
- {
- if (obj.getObject() instanceof ASN1Sequence)
- {
- return (ASN1Sequence)obj.getObject();
- }
- }
- }
-
- throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * Create an empty sequence
- */
- protected ASN1Sequence()
- {
- }
-
- /**
- * Create a sequence containing one object
- * @param obj the object to be put in the SEQUENCE.
- */
- protected ASN1Sequence(
- ASN1Encodable obj)
- {
- seq.addElement(obj);
- }
-
- /**
- * Create a sequence containing a vector of objects.
- * @param v the vector of objects to be put in the SEQUENCE
- */
- protected ASN1Sequence(
- ASN1EncodableVector v)
- {
- for (int i = 0; i != v.size(); i++)
- {
- seq.addElement(v.get(i));
- }
- }
-
- /**
- * Create a sequence containing a vector of objects.
- */
- protected ASN1Sequence(
- ASN1Encodable[] array)
- {
- for (int i = 0; i != array.length; i++)
- {
- seq.addElement(array[i]);
- }
- }
-
- public ASN1Encodable[] toArray()
- {
- ASN1Encodable[] values = new ASN1Encodable[this.size()];
-
- for (int i = 0; i != this.size(); i++)
- {
- values[i] = this.getObjectAt(i);
- }
-
- return values;
- }
-
- public Enumeration getObjects()
- {
- return seq.elements();
- }
-
- public ASN1SequenceParser parser()
- {
- final ASN1Sequence outer = this;
-
- return new ASN1SequenceParser()
- {
- private final int max = size();
-
- private int index;
-
- public ASN1Encodable readObject() throws IOException
- {
- if (index == max)
- {
- return null;
- }
-
- ASN1Encodable obj = getObjectAt(index++);
- if (obj instanceof ASN1Sequence)
- {
- return ((ASN1Sequence)obj).parser();
- }
- if (obj instanceof ASN1Set)
- {
- return ((ASN1Set)obj).parser();
- }
-
- return obj;
- }
-
- public ASN1Primitive getLoadedObject()
- {
- return outer;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return outer;
- }
- };
- }
-
- /**
- * Return the object at the sequence position indicated by index.
- *
- * @param index the sequence number (starting at zero) of the object
- * @return the object at the sequence position indicated by index.
- */
- public ASN1Encodable getObjectAt(
- int index)
- {
- return (ASN1Encodable)seq.elementAt(index);
- }
-
- /**
- * Return the number of objects in this sequence.
- *
- * @return the number of objects in this sequence.
- */
- public int size()
- {
- return seq.size();
- }
-
- public int hashCode()
- {
- Enumeration e = this.getObjects();
- int hashCode = size();
-
- while (e.hasMoreElements())
- {
- Object o = getNext(e);
- hashCode *= 17;
-
- hashCode ^= o.hashCode();
- }
-
- return hashCode;
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof ASN1Sequence))
- {
- return false;
- }
-
- ASN1Sequence other = (ASN1Sequence)o;
-
- if (this.size() != other.size())
- {
- return false;
- }
-
- Enumeration s1 = this.getObjects();
- Enumeration s2 = other.getObjects();
-
- while (s1.hasMoreElements())
- {
- ASN1Encodable obj1 = getNext(s1);
- ASN1Encodable obj2 = getNext(s2);
-
- ASN1Primitive o1 = obj1.toASN1Primitive();
- ASN1Primitive o2 = obj2.toASN1Primitive();
-
- if (o1 == o2 || o1.equals(o2))
- {
- continue;
- }
-
- return false;
- }
-
- return true;
- }
-
- private ASN1Encodable getNext(Enumeration e)
- {
- ASN1Encodable encObj = (ASN1Encodable)e.nextElement();
-
- return encObj;
- }
-
- /**
- * Change current SEQUENCE object to be encoded as {@link DERSequence}.
- * This is part of Distinguished Encoding Rules form serialization.
- */
- ASN1Primitive toDERObject()
- {
- ASN1Sequence derSeq = new DERSequence();
-
- derSeq.seq = this.seq;
-
- return derSeq;
- }
-
- /**
- * Change current SEQUENCE object to be encoded as {@link DLSequence}.
- * This is part of Direct Length form serialization.
- */
- ASN1Primitive toDLObject()
- {
- ASN1Sequence dlSeq = new DLSequence();
-
- dlSeq.seq = this.seq;
-
- return dlSeq;
- }
-
- boolean isConstructed()
- {
- return true;
- }
-
- abstract void encode(ASN1OutputStream out)
- throws IOException;
-
- public String toString()
- {
- return seq.toString();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1SequenceParser.java b/core/src/main/java/org/bouncycastle/asn1/ASN1SequenceParser.java
deleted file mode 100644
index 22f83c22..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1SequenceParser.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * A basic parser for a SEQUENCE object
- */
-public interface ASN1SequenceParser
- extends ASN1Encodable, InMemoryRepresentable
-{
- /**
- * Read the next object from the underlying object representing a SEQUENCE.
- *
- * @throws IOException for bad input stream.
- * @return the next object, null if we are at the end.
- */
- ASN1Encodable readObject()
- throws IOException;
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1Set.java b/core/src/main/java/org/bouncycastle/asn1/ASN1Set.java
deleted file mode 100644
index 895f0021..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1Set.java
+++ /dev/null
@@ -1,560 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Vector;
-
-/**
- * ASN.1 <code>SET</code> and <code>SET OF</code> constructs.
- * <p>
- * Note: This does not know which syntax the set is!
- * (The difference: ordering of SET elements or not ordering.)
- * <p>
- * DER form is always definite form length fields, while
- * BER support uses indefinite form.
- * <p>
- * The CER form support does not exist.
- * <p>
- * <hr>
- * <h2>X.690</h2>
- * <h3>8: Basic encoding rules</h3>
- * <h4>8.11 Encoding of a set value </h4>
- * <b>8.11.1</b> The encoding of a set value shall be constructed
- * <p>
- * <b>8.11.2</b> The contents octets shall consist of the complete
- * encoding of a data value from each of the types listed in the
- * ASN.1 definition of the set type, in an order chosen by the sender,
- * unless the type was referenced with the keyword
- * <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
- * <p>
- * <b>8.11.3</b> The encoding of a data value may, but need not,
- * be present for a type which was referenced with the keyword
- * <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
- * <blockquote>
- * NOTE &mdash; The order of data values in a set value is not significant,
- * and places no constraints on the order during transfer
- * </blockquote>
- * <h4>8.12 Encoding of a set-of value</h4>
- * <b>8.12.1</b> The encoding of a set-of value shall be constructed.
- * <p>
- * <b>8.12.2</b> The text of 8.10.2 applies:
- * <i>The contents octets shall consist of zero,
- * one or more complete encodings of data values from the type listed in
- * the ASN.1 definition.</i>
- * <p>
- * <b>8.12.3</b> The order of data values need not be preserved by
- * the encoding and subsequent decoding.
- *
- * <h3>9: Canonical encoding rules</h3>
- * <h4>9.1 Length forms</h4>
- * If the encoding is constructed, it shall employ the indefinite length form.
- * If the encoding is primitive, it shall include the fewest length octets necessary.
- * [Contrast with 8.1.3.2 b).]
- * <h4>9.3 Set components</h4>
- * The encodings of the component values of a set value shall
- * appear in an order determined by their tags as specified
- * in 8.6 of ITU-T Rec. X.680 | ISO/IEC 8824-1.
- * Additionally, for the purposes of determining the order in which
- * components are encoded when one or more component is an untagged
- * choice type, each untagged choice type is ordered as though it
- * has a tag equal to that of the smallest tag in that choice type
- * or any untagged choice types nested within.
- *
- * <h3>10: Distinguished encoding rules</h3>
- * <h4>10.1 Length forms</h4>
- * The definite form of length encoding shall be used,
- * encoded in the minimum number of octets.
- * [Contrast with 8.1.3.2 b).]
- * <h4>10.3 Set components</h4>
- * The encodings of the component values of a set value shall appear
- * in an order determined by their tags as specified
- * in 8.6 of ITU-T Rec. X.680 | ISO/IEC 8824-1.
- * <blockquote>
- * NOTE &mdash; Where a component of the set is an untagged choice type,
- * the location of that component in the ordering will depend on
- * the tag of the choice component being encoded.
- * </blockquote>
- *
- * <h3>11: Restrictions on BER employed by both CER and DER</h3>
- * <h4>11.5 Set and sequence components with default value </h4>
- * The encoding of a set value or sequence value shall not include
- * an encoding for any component value which is equal to
- * its default value.
- * <h4>11.6 Set-of components </h4>
- * <p>
- * The encodings of the component values of a set-of value
- * shall appear in ascending order, the encodings being compared
- * as octet strings with the shorter components being padded at
- * their trailing end with 0-octets.
- * <blockquote>
- * NOTE &mdash; The padding octets are for comparison purposes only
- * and do not appear in the encodings.
- * </blockquote>
- */
-public abstract class ASN1Set
- extends ASN1Primitive
-{
- private Vector set = new Vector();
- private boolean isSorted = false;
-
- /**
- * return an ASN1Set from the given object.
- *
- * @param obj the object we want converted.
- * @exception IllegalArgumentException if the object cannot be converted.
- * @return an ASN1Set instance, or null.
- */
- public static ASN1Set getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ASN1Set)
- {
- return (ASN1Set)obj;
- }
- else if (obj instanceof ASN1SetParser)
- {
- return ASN1Set.getInstance(((ASN1SetParser)obj).toASN1Primitive());
- }
- else if (obj instanceof byte[])
- {
- try
- {
- return ASN1Set.getInstance(ASN1Primitive.fromByteArray((byte[])obj));
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("failed to construct set from byte[]: " + e.getMessage());
- }
- }
- else if (obj instanceof ASN1Encodable)
- {
- ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive();
-
- if (primitive instanceof ASN1Set)
- {
- return (ASN1Set)primitive;
- }
- }
-
- throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * Return an ASN1 set from a tagged object. There is a special
- * case here, if an object appears to have been explicitly tagged on
- * reading but we were expecting it to be implicitly tagged in the
- * normal course of events it indicates that we lost the surrounding
- * set - so we need to add it back (this will happen if the tagged
- * object is a sequence that contains other sequences). If you are
- * dealing with implicitly tagged sets you really <b>should</b>
- * be using this method.
- *
- * @param obj the tagged object.
- * @param explicit true if the object is meant to be explicitly tagged
- * false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- * @return an ASN1Set instance.
- */
- public static ASN1Set getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- if (explicit)
- {
- if (!obj.isExplicit())
- {
- throw new IllegalArgumentException("object implicit - explicit expected.");
- }
-
- return (ASN1Set)obj.getObject();
- }
- else
- {
- //
- // constructed object which appears to be explicitly tagged
- // and it's really implicit means we have to add the
- // surrounding set.
- //
- if (obj.isExplicit())
- {
- if (obj instanceof BERTaggedObject)
- {
- return new BERSet(obj.getObject());
- }
- else
- {
- return new DLSet(obj.getObject());
- }
- }
- else
- {
- if (obj.getObject() instanceof ASN1Set)
- {
- return (ASN1Set)obj.getObject();
- }
-
- //
- // in this case the parser returns a sequence, convert it
- // into a set.
- //
- if (obj.getObject() instanceof ASN1Sequence)
- {
- ASN1Sequence s = (ASN1Sequence)obj.getObject();
-
- if (obj instanceof BERTaggedObject)
- {
- return new BERSet(s.toArray());
- }
- else
- {
- return new DLSet(s.toArray());
- }
- }
- }
- }
-
- throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
- }
-
- protected ASN1Set()
- {
- }
-
- /**
- * create a sequence containing one object
- * @param obj object to be added to the SET.
- */
- protected ASN1Set(
- ASN1Encodable obj)
- {
- set.addElement(obj);
- }
-
- /**
- * create a sequence containing a vector of objects.
- * @param v a vector of objects to make up the SET.
- * @param doSort true if should be sorted DER style, false otherwise.
- */
- protected ASN1Set(
- ASN1EncodableVector v,
- boolean doSort)
- {
- for (int i = 0; i != v.size(); i++)
- {
- set.addElement(v.get(i));
- }
-
- if (doSort)
- {
- this.sort();
- }
- }
-
- /**
- * create a sequence containing a vector of objects.
- */
- protected ASN1Set(
- ASN1Encodable[] array,
- boolean doSort)
- {
- for (int i = 0; i != array.length; i++)
- {
- set.addElement(array[i]);
- }
-
- if (doSort)
- {
- this.sort();
- }
- }
-
- public Enumeration getObjects()
- {
- return set.elements();
- }
-
- /**
- * return the object at the set position indicated by index.
- *
- * @param index the set number (starting at zero) of the object
- * @return the object at the set position indicated by index.
- */
- public ASN1Encodable getObjectAt(
- int index)
- {
- return (ASN1Encodable)set.elementAt(index);
- }
-
- /**
- * return the number of objects in this set.
- *
- * @return the number of objects in this set.
- */
- public int size()
- {
- return set.size();
- }
-
- public ASN1Encodable[] toArray()
- {
- ASN1Encodable[] values = new ASN1Encodable[this.size()];
-
- for (int i = 0; i != this.size(); i++)
- {
- values[i] = this.getObjectAt(i);
- }
-
- return values;
- }
-
- public ASN1SetParser parser()
- {
- final ASN1Set outer = this;
-
- return new ASN1SetParser()
- {
- private final int max = size();
-
- private int index;
-
- public ASN1Encodable readObject() throws IOException
- {
- if (index == max)
- {
- return null;
- }
-
- ASN1Encodable obj = getObjectAt(index++);
- if (obj instanceof ASN1Sequence)
- {
- return ((ASN1Sequence)obj).parser();
- }
- if (obj instanceof ASN1Set)
- {
- return ((ASN1Set)obj).parser();
- }
-
- return obj;
- }
-
- public ASN1Primitive getLoadedObject()
- {
- return outer;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return outer;
- }
- };
- }
-
- public int hashCode()
- {
- Enumeration e = this.getObjects();
- int hashCode = size();
-
- while (e.hasMoreElements())
- {
- Object o = getNext(e);
- hashCode *= 17;
-
- hashCode ^= o.hashCode();
- }
-
- return hashCode;
- }
-
- /**
- * Change current SET object to be encoded as {@link DERSet}.
- * This is part of Distinguished Encoding Rules form serialization.
- */
- ASN1Primitive toDERObject()
- {
- if (isSorted)
- {
- ASN1Set derSet = new DERSet();
-
- derSet.set = this.set;
-
- return derSet;
- }
- else
- {
- Vector v = new Vector();
-
- for (int i = 0; i != set.size(); i++)
- {
- v.addElement(set.elementAt(i));
- }
-
- ASN1Set derSet = new DERSet();
-
- derSet.set = v;
-
- derSet.sort();
-
- return derSet;
- }
- }
-
- /**
- * Change current SET object to be encoded as {@link DLSet}.
- * This is part of Direct Length form serialization.
- */
- ASN1Primitive toDLObject()
- {
- ASN1Set derSet = new DLSet();
-
- derSet.set = this.set;
-
- return derSet;
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof ASN1Set))
- {
- return false;
- }
-
- ASN1Set other = (ASN1Set)o;
-
- if (this.size() != other.size())
- {
- return false;
- }
-
- Enumeration s1 = this.getObjects();
- Enumeration s2 = other.getObjects();
-
- while (s1.hasMoreElements())
- {
- ASN1Encodable obj1 = getNext(s1);
- ASN1Encodable obj2 = getNext(s2);
-
- ASN1Primitive o1 = obj1.toASN1Primitive();
- ASN1Primitive o2 = obj2.toASN1Primitive();
-
- if (o1 == o2 || o1.equals(o2))
- {
- continue;
- }
-
- return false;
- }
-
- return true;
- }
-
- private ASN1Encodable getNext(Enumeration e)
- {
- ASN1Encodable encObj = (ASN1Encodable)e.nextElement();
-
- // unfortunately null was allowed as a substitute for DER null
- if (encObj == null)
- {
- return DERNull.INSTANCE;
- }
-
- return encObj;
- }
-
- /**
- * return true if a <= b (arrays are assumed padded with zeros).
- */
- private boolean lessThanOrEqual(
- byte[] a,
- byte[] b)
- {
- int len = Math.min(a.length, b.length);
- for (int i = 0; i != len; ++i)
- {
- if (a[i] != b[i])
- {
- return (a[i] & 0xff) < (b[i] & 0xff);
- }
- }
- return len == a.length;
- }
-
- private byte[] getEncoded(
- ASN1Encodable obj)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- ASN1OutputStream aOut = new ASN1OutputStream(bOut);
-
- try
- {
- aOut.writeObject(obj);
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("cannot encode object added to SET");
- }
-
- return bOut.toByteArray();
- }
-
- protected void sort()
- {
- if (!isSorted)
- {
- isSorted = true;
- if (set.size() > 1)
- {
- boolean swapped = true;
- int lastSwap = set.size() - 1;
-
- while (swapped)
- {
- int index = 0;
- int swapIndex = 0;
- byte[] a = getEncoded((ASN1Encodable)set.elementAt(0));
-
- swapped = false;
-
- while (index != lastSwap)
- {
- byte[] b = getEncoded((ASN1Encodable)set.elementAt(index + 1));
-
- if (lessThanOrEqual(a, b))
- {
- a = b;
- }
- else
- {
- Object o = set.elementAt(index);
-
- set.setElementAt(set.elementAt(index + 1), index);
- set.setElementAt(o, index + 1);
-
- swapped = true;
- swapIndex = index;
- }
-
- index++;
- }
-
- lastSwap = swapIndex;
- }
- }
- }
- }
-
- boolean isConstructed()
- {
- return true;
- }
-
- abstract void encode(ASN1OutputStream out)
- throws IOException;
-
- public String toString()
- {
- return set.toString();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1SetParser.java b/core/src/main/java/org/bouncycastle/asn1/ASN1SetParser.java
deleted file mode 100644
index 5f36dbb8..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1SetParser.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * A basic parser for a SET object
- */
-public interface ASN1SetParser
- extends ASN1Encodable, InMemoryRepresentable
-{
- /**
- * Read the next object from the underlying object representing a SET.
- *
- * @throws IOException for bad input stream.
- * @return the next object, null if we are at the end.
- */
- public ASN1Encodable readObject()
- throws IOException;
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1StreamParser.java b/core/src/main/java/org/bouncycastle/asn1/ASN1StreamParser.java
deleted file mode 100644
index 418c1016..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1StreamParser.java
+++ /dev/null
@@ -1,250 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * A parser for ASN.1 streams which also returns, where possible, parsers for the objects it encounters.
- */
-public class ASN1StreamParser
-{
- private final InputStream _in;
- private final int _limit;
- private final byte[][] tmpBuffers;
-
- public ASN1StreamParser(
- InputStream in)
- {
- this(in, StreamUtil.findLimit(in));
- }
-
- public ASN1StreamParser(
- InputStream in,
- int limit)
- {
- this._in = in;
- this._limit = limit;
-
- this.tmpBuffers = new byte[11][];
- }
-
- public ASN1StreamParser(
- byte[] encoding)
- {
- this(new ByteArrayInputStream(encoding), encoding.length);
- }
-
- ASN1Encodable readIndef(int tagValue) throws IOException
- {
- // Note: INDEF => CONSTRUCTED
-
- // TODO There are other tags that may be constructed (e.g. BIT_STRING)
- switch (tagValue)
- {
- case BERTags.EXTERNAL:
- return new DERExternalParser(this);
- case BERTags.OCTET_STRING:
- return new BEROctetStringParser(this);
- case BERTags.SEQUENCE:
- return new BERSequenceParser(this);
- case BERTags.SET:
- return new BERSetParser(this);
- default:
- throw new ASN1Exception("unknown BER object encountered: 0x" + Integer.toHexString(tagValue));
- }
- }
-
- ASN1Encodable readImplicit(boolean constructed, int tag) throws IOException
- {
- if (_in instanceof IndefiniteLengthInputStream)
- {
- if (!constructed)
- {
- throw new IOException("indefinite length primitive encoding encountered");
- }
-
- return readIndef(tag);
- }
-
- if (constructed)
- {
- switch (tag)
- {
- case BERTags.SET:
- return new DERSetParser(this);
- case BERTags.SEQUENCE:
- return new DERSequenceParser(this);
- case BERTags.OCTET_STRING:
- return new BEROctetStringParser(this);
- }
- }
- else
- {
- switch (tag)
- {
- case BERTags.SET:
- throw new ASN1Exception("sequences must use constructed encoding (see X.690 8.9.1/8.10.1)");
- case BERTags.SEQUENCE:
- throw new ASN1Exception("sets must use constructed encoding (see X.690 8.11.1/8.12.1)");
- case BERTags.OCTET_STRING:
- return new DEROctetStringParser((DefiniteLengthInputStream)_in);
- }
- }
-
- // TODO ASN1Exception
- throw new RuntimeException("implicit tagging not implemented");
- }
-
- ASN1Primitive readTaggedObject(boolean constructed, int tag) throws IOException
- {
- if (!constructed)
- {
- // Note: !CONSTRUCTED => IMPLICIT
- DefiniteLengthInputStream defIn = (DefiniteLengthInputStream)_in;
- return new DERTaggedObject(false, tag, new DEROctetString(defIn.toByteArray()));
- }
-
- ASN1EncodableVector v = readVector();
-
- if (_in instanceof IndefiniteLengthInputStream)
- {
- return v.size() == 1
- ? new BERTaggedObject(true, tag, v.get(0))
- : new BERTaggedObject(false, tag, BERFactory.createSequence(v));
- }
-
- return v.size() == 1
- ? new DERTaggedObject(true, tag, v.get(0))
- : new DERTaggedObject(false, tag, DERFactory.createSequence(v));
- }
-
- public ASN1Encodable readObject()
- throws IOException
- {
- int tag = _in.read();
- if (tag == -1)
- {
- return null;
- }
-
- //
- // turn of looking for "00" while we resolve the tag
- //
- set00Check(false);
-
- //
- // calculate tag number
- //
- int tagNo = ASN1InputStream.readTagNumber(_in, tag);
-
- boolean isConstructed = (tag & BERTags.CONSTRUCTED) != 0;
-
- //
- // calculate length
- //
- int length = ASN1InputStream.readLength(_in, _limit);
-
- if (length < 0) // indefinite length method
- {
- if (!isConstructed)
- {
- throw new IOException("indefinite length primitive encoding encountered");
- }
-
- IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in, _limit);
- ASN1StreamParser sp = new ASN1StreamParser(indIn, _limit);
-
- if ((tag & BERTags.APPLICATION) != 0)
- {
- return new BERApplicationSpecificParser(tagNo, sp);
- }
-
- if ((tag & BERTags.TAGGED) != 0)
- {
- return new BERTaggedObjectParser(true, tagNo, sp);
- }
-
- return sp.readIndef(tagNo);
- }
- else
- {
- DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length);
-
- if ((tag & BERTags.APPLICATION) != 0)
- {
- return new DERApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
- }
-
- if ((tag & BERTags.TAGGED) != 0)
- {
- return new BERTaggedObjectParser(isConstructed, tagNo, new ASN1StreamParser(defIn));
- }
-
- if (isConstructed)
- {
- // TODO There are other tags that may be constructed (e.g. BIT_STRING)
- switch (tagNo)
- {
- case BERTags.OCTET_STRING:
- //
- // yes, people actually do this...
- //
- return new BEROctetStringParser(new ASN1StreamParser(defIn));
- case BERTags.SEQUENCE:
- return new DERSequenceParser(new ASN1StreamParser(defIn));
- case BERTags.SET:
- return new DERSetParser(new ASN1StreamParser(defIn));
- case BERTags.EXTERNAL:
- return new DERExternalParser(new ASN1StreamParser(defIn));
- default:
- throw new IOException("unknown tag " + tagNo + " encountered");
- }
- }
-
- // Some primitive encodings can be handled by parsers too...
- switch (tagNo)
- {
- case BERTags.OCTET_STRING:
- return new DEROctetStringParser(defIn);
- }
-
- try
- {
- return ASN1InputStream.createPrimitiveDERObject(tagNo, defIn, tmpBuffers);
- }
- catch (IllegalArgumentException e)
- {
- throw new ASN1Exception("corrupted stream detected", e);
- }
- }
- }
-
- private void set00Check(boolean enabled)
- {
- if (_in instanceof IndefiniteLengthInputStream)
- {
- ((IndefiniteLengthInputStream)_in).setEofOn00(enabled);
- }
- }
-
- ASN1EncodableVector readVector() throws IOException
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- ASN1Encodable obj;
- while ((obj = readObject()) != null)
- {
- if (obj instanceof InMemoryRepresentable)
- {
- v.add(((InMemoryRepresentable)obj).getLoadedObject());
- }
- else
- {
- v.add(obj.toASN1Primitive());
- }
- }
-
- return v;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1String.java b/core/src/main/java/org/bouncycastle/asn1/ASN1String.java
deleted file mode 100644
index fde4e239..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1String.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.bouncycastle.asn1;
-
-public interface ASN1String
-{
- public String getString();
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1TaggedObject.java b/core/src/main/java/org/bouncycastle/asn1/ASN1TaggedObject.java
deleted file mode 100644
index fb1e2442..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1TaggedObject.java
+++ /dev/null
@@ -1,236 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * ASN.1 TaggedObject - in ASN.1 notation this is any object preceded by
- * a [n] where n is some number - these are assumed to follow the construction
- * rules (as with sequences).
- */
-public abstract class ASN1TaggedObject
- extends ASN1Primitive
- implements ASN1TaggedObjectParser
-{
- int tagNo;
- boolean empty = false;
- boolean explicit = true;
- ASN1Encodable obj = null;
-
- static public ASN1TaggedObject getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- if (explicit)
- {
- return (ASN1TaggedObject)obj.getObject();
- }
-
- throw new IllegalArgumentException("implicitly tagged tagged object");
- }
-
- static public ASN1TaggedObject getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ASN1TaggedObject)
- {
- return (ASN1TaggedObject)obj;
- }
- else if (obj instanceof byte[])
- {
- try
- {
- return ASN1TaggedObject.getInstance(fromByteArray((byte[])obj));
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("failed to construct tagged object from byte[]: " + e.getMessage());
- }
- }
-
- throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * Create a tagged object with the style given by the value of explicit.
- * <p>
- * If the object implements ASN1Choice the tag style will always be changed
- * to explicit in accordance with the ASN.1 encoding rules.
- * </p>
- * @param explicit true if the object is explicitly tagged.
- * @param tagNo the tag number for this object.
- * @param obj the tagged object.
- */
- public ASN1TaggedObject(
- boolean explicit,
- int tagNo,
- ASN1Encodable obj)
- {
- if (obj instanceof ASN1Choice)
- {
- this.explicit = true;
- }
- else
- {
- this.explicit = explicit;
- }
-
- this.tagNo = tagNo;
-
- if (this.explicit)
- {
- this.obj = obj;
- }
- else
- {
- ASN1Primitive prim = obj.toASN1Primitive();
-
- if (prim instanceof ASN1Set)
- {
- ASN1Set s = null;
- }
-
- this.obj = obj;
- }
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof ASN1TaggedObject))
- {
- return false;
- }
-
- ASN1TaggedObject other = (ASN1TaggedObject)o;
-
- if (tagNo != other.tagNo || empty != other.empty || explicit != other.explicit)
- {
- return false;
- }
-
- if(obj == null)
- {
- if (other.obj != null)
- {
- return false;
- }
- }
- else
- {
- if (!(obj.toASN1Primitive().equals(other.obj.toASN1Primitive())))
- {
- return false;
- }
- }
-
- return true;
- }
-
- public int hashCode()
- {
- int code = tagNo;
-
- // TODO: actually this is wrong - the problem is that a re-encoded
- // object may end up with a different hashCode due to implicit
- // tagging. As implicit tagging is ambiguous if a sequence is involved
- // it seems the only correct method for both equals and hashCode is to
- // compare the encodings...
- if (obj != null)
- {
- code ^= obj.hashCode();
- }
-
- return code;
- }
-
- public int getTagNo()
- {
- return tagNo;
- }
-
- /**
- * return whether or not the object may be explicitly tagged.
- * <p>
- * Note: if the object has been read from an input stream, the only
- * time you can be sure if isExplicit is returning the true state of
- * affairs is if it returns false. An implicitly tagged object may appear
- * to be explicitly tagged, so you need to understand the context under
- * which the reading was done as well, see getObject below.
- */
- public boolean isExplicit()
- {
- return explicit;
- }
-
- public boolean isEmpty()
- {
- return empty;
- }
-
- /**
- * return whatever was following the tag.
- * <p>
- * Note: tagged objects are generally context dependent if you're
- * trying to extract a tagged object you should be going via the
- * appropriate getInstance method.
- */
- public ASN1Primitive getObject()
- {
- if (obj != null)
- {
- return obj.toASN1Primitive();
- }
-
- return null;
- }
-
- /**
- * Return the object held in this tagged object as a parser assuming it has
- * the type of the passed in tag. If the object doesn't have a parser
- * associated with it, the base object is returned.
- */
- public ASN1Encodable getObjectParser(
- int tag,
- boolean isExplicit)
- {
- switch (tag)
- {
- case BERTags.SET:
- return ASN1Set.getInstance(this, isExplicit).parser();
- case BERTags.SEQUENCE:
- return ASN1Sequence.getInstance(this, isExplicit).parser();
- case BERTags.OCTET_STRING:
- return ASN1OctetString.getInstance(this, isExplicit).parser();
- }
-
- if (isExplicit)
- {
- return getObject();
- }
-
- throw new RuntimeException("implicit tagging not implemented for tag: " + tag);
- }
-
- public ASN1Primitive getLoadedObject()
- {
- return this.toASN1Primitive();
- }
-
- ASN1Primitive toDERObject()
- {
- return new DERTaggedObject(explicit, tagNo, obj);
- }
-
- ASN1Primitive toDLObject()
- {
- return new DLTaggedObject(explicit, tagNo, obj);
- }
-
- abstract void encode(ASN1OutputStream out)
- throws IOException;
-
- public String toString()
- {
- return "[" + tagNo + "]" + obj;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1TaggedObjectParser.java b/core/src/main/java/org/bouncycastle/asn1/ASN1TaggedObjectParser.java
deleted file mode 100644
index a681dc94..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1TaggedObjectParser.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public interface ASN1TaggedObjectParser
- extends ASN1Encodable, InMemoryRepresentable
-{
- public int getTagNo();
-
- public ASN1Encodable getObjectParser(int tag, boolean isExplicit)
- throws IOException;
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ASN1UTCTime.java b/core/src/main/java/org/bouncycastle/asn1/ASN1UTCTime.java
deleted file mode 100644
index 2c82df30..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ASN1UTCTime.java
+++ /dev/null
@@ -1,314 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-import java.util.SimpleTimeZone;
-
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Strings;
-
-/**
-- * UTC time object.
- * Internal facade of {@link ASN1UTCTime}.
- * <p>
- * This datatype is valid only from 1950-01-01 00:00:00 UTC until 2049-12-31 23:59:59 UTC.
- * <p>
- * <hr>
- * <p><b>X.690</b></p>
- * <p><b>11: Restrictions on BER employed by both CER and DER</b></p>
- * <p><b>11.8 UTCTime </b></p>
- * <b>11.8.1</b> The encoding shall terminate with "Z",
- * as described in the ITU-T X.680 | ISO/IEC 8824-1 clause on UTCTime.
- * <p>
- * <b>11.8.2</b> The seconds element shall always be present.
- * <p>
- * <b>11.8.3</b> Midnight (GMT) shall be represented in the form:
- * <blockquote>
- * "YYMMDD000000Z"
- * </blockquote>
- * where "YYMMDD" represents the day following the midnight in question.
- */
-public class ASN1UTCTime
- extends ASN1Primitive
-{
- private byte[] time;
-
- /**
- * return an UTC Time from the passed in object.
- *
- * @param obj an ASN1UTCTime or an object that can be converted into one.
- * @exception IllegalArgumentException if the object cannot be converted.
- * @return an ASN1UTCTime instance, or null.
- */
- public static ASN1UTCTime getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ASN1UTCTime)
- {
- return (ASN1UTCTime)obj;
- }
-
- if (obj instanceof byte[])
- {
- try
- {
- return (ASN1UTCTime)fromByteArray((byte[])obj);
- }
- catch (Exception e)
- {
- throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
- }
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return an UTC Time from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- * @return an ASN1UTCTime instance, or null.
- */
- public static ASN1UTCTime getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Object o = obj.getObject();
-
- if (explicit || o instanceof ASN1UTCTime)
- {
- return getInstance(o);
- }
- else
- {
- return new ASN1UTCTime(((ASN1OctetString)o).getOctets());
- }
- }
-
- /**
- * The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
- * never encoded. When you're creating one of these objects from scratch, that's
- * what you want to use, otherwise we'll try to deal with whatever gets read from
- * the input stream... (this is why the input format is different from the getTime()
- * method output).
- * <p>
- *
- * @param time the time string.
- */
- public ASN1UTCTime(
- String time)
- {
- this.time = Strings.toByteArray(time);
- try
- {
- this.getDate();
- }
- catch (ParseException e)
- {
- throw new IllegalArgumentException("invalid date string: " + e.getMessage());
- }
- }
-
- /**
- * base constructor from a java.util.date object
- * @param time the Date to build the time from.
- */
- public ASN1UTCTime(
- Date time)
- {
- SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'");
-
- dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
-
- this.time = Strings.toByteArray(dateF.format(time));
- }
-
- /**
- * Base constructor from a java.util.date and Locale - you may need to use this if the default locale
- * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible with other ASN.1 implementations.
- *
- * @param time a date object representing the time of interest.
- * @param locale an appropriate Locale for producing an ASN.1 UTCTime value.
- */
- public ASN1UTCTime(
- Date time,
- Locale locale)
- {
- SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'", locale);
-
- dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
-
- this.time = Strings.toByteArray(dateF.format(time));
- }
-
- ASN1UTCTime(
- byte[] time)
- {
- this.time = time;
- }
-
- /**
- * return the time as a date based on whatever a 2 digit year will return. For
- * standardised processing use getAdjustedDate().
- *
- * @return the resulting date
- * @exception ParseException if the date string cannot be parsed.
- */
- public Date getDate()
- throws ParseException
- {
- SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmssz");
-
- return dateF.parse(getTime());
- }
-
- /**
- * return the time as an adjusted date
- * in the range of 1950 - 2049.
- *
- * @return a date in the range of 1950 to 2049.
- * @exception ParseException if the date string cannot be parsed.
- */
- public Date getAdjustedDate()
- throws ParseException
- {
- SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
-
- dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
-
- return dateF.parse(getAdjustedTime());
- }
-
- /**
- * return the time - always in the form of
- * YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
- * <p>
- * Normally in a certificate we would expect "Z" rather than "GMT",
- * however adding the "GMT" means we can just use:
- * <pre>
- * dateF = new SimpleDateFormat("yyMMddHHmmssz");
- * </pre>
- * To read in the time and get a date which is compatible with our local
- * time zone.
- * <p>
- * <b>Note:</b> In some cases, due to the local date processing, this
- * may lead to unexpected results. If you want to stick the normal
- * convention of 1950 to 2049 use the getAdjustedTime() method.
- */
- public String getTime()
- {
- String stime = Strings.fromByteArray(time);
-
- //
- // standardise the format.
- //
- if (stime.indexOf('-') < 0 && stime.indexOf('+') < 0)
- {
- if (stime.length() == 11)
- {
- return stime.substring(0, 10) + "00GMT+00:00";
- }
- else
- {
- return stime.substring(0, 12) + "GMT+00:00";
- }
- }
- else
- {
- int index = stime.indexOf('-');
- if (index < 0)
- {
- index = stime.indexOf('+');
- }
- String d = stime;
-
- if (index == stime.length() - 3)
- {
- d += "00";
- }
-
- if (index == 10)
- {
- return d.substring(0, 10) + "00GMT" + d.substring(10, 13) + ":" + d.substring(13, 15);
- }
- else
- {
- return d.substring(0, 12) + "GMT" + d.substring(12, 15) + ":" + d.substring(15, 17);
- }
- }
- }
-
- /**
- * return a time string as an adjusted date with a 4 digit year. This goes
- * in the range of 1950 - 2049.
- */
- public String getAdjustedTime()
- {
- String d = this.getTime();
-
- if (d.charAt(0) < '5')
- {
- return "20" + d;
- }
- else
- {
- return "19" + d;
- }
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- int length = time.length;
-
- return 1 + StreamUtil.calculateBodyLength(length) + length;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.write(BERTags.UTC_TIME);
-
- int length = time.length;
-
- out.writeLength(length);
-
- for (int i = 0; i != length; i++)
- {
- out.write((byte)time[i]);
- }
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof ASN1UTCTime))
- {
- return false;
- }
-
- return Arrays.areEqual(time, ((ASN1UTCTime)o).time);
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(time);
- }
-
- public String toString()
- {
- return Strings.fromByteArray(time);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/BERApplicationSpecific.java b/core/src/main/java/org/bouncycastle/asn1/BERApplicationSpecific.java
deleted file mode 100644
index 8bc8a4eb..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/BERApplicationSpecific.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.bouncycastle.asn1;
-
-public class BERApplicationSpecific
- extends DERApplicationSpecific
-{
- public BERApplicationSpecific(int tagNo, ASN1EncodableVector vec)
- {
- super(tagNo, vec);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/BERApplicationSpecificParser.java b/core/src/main/java/org/bouncycastle/asn1/BERApplicationSpecificParser.java
deleted file mode 100644
index 63bd9f3d..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/BERApplicationSpecificParser.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public class BERApplicationSpecificParser
- implements ASN1ApplicationSpecificParser
-{
- private final int tag;
- private final ASN1StreamParser parser;
-
- BERApplicationSpecificParser(int tag, ASN1StreamParser parser)
- {
- this.tag = tag;
- this.parser = parser;
- }
-
- public ASN1Encodable readObject()
- throws IOException
- {
- return parser.readObject();
- }
-
- public ASN1Primitive getLoadedObject()
- throws IOException
- {
- return new BERApplicationSpecific(tag, parser.readVector());
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- try
- {
- return getLoadedObject();
- }
- catch (IOException e)
- {
- throw new ASN1ParsingException(e.getMessage(), e);
- }
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/BERConstructedOctetString.java b/core/src/main/java/org/bouncycastle/asn1/BERConstructedOctetString.java
deleted file mode 100644
index cad6e42a..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/BERConstructedOctetString.java
+++ /dev/null
@@ -1,144 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Vector;
-
-/**
- * @deprecated use BEROctetString
- */
-public class BERConstructedOctetString
- extends BEROctetString
-{
- private static final int MAX_LENGTH = 1000;
-
- /**
- * convert a vector of octet strings into a single byte string
- */
- static private byte[] toBytes(
- Vector octs)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- for (int i = 0; i != octs.size(); i++)
- {
- try
- {
- DEROctetString o = (DEROctetString)octs.elementAt(i);
-
- bOut.write(o.getOctets());
- }
- catch (ClassCastException e)
- {
- throw new IllegalArgumentException(octs.elementAt(i).getClass().getName() + " found in input should only contain DEROctetString");
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("exception converting octets " + e.toString());
- }
- }
-
- return bOut.toByteArray();
- }
-
- private Vector octs;
-
- /**
- * @param string the octets making up the octet string.
- */
- public BERConstructedOctetString(
- byte[] string)
- {
- super(string);
- }
-
- public BERConstructedOctetString(
- Vector octs)
- {
- super(toBytes(octs));
-
- this.octs = octs;
- }
-
- public BERConstructedOctetString(
- ASN1Primitive obj)
- {
- super(toByteArray(obj));
- }
-
- private static byte[] toByteArray(ASN1Primitive obj)
- {
- try
- {
- return obj.getEncoded();
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("Unable to encode object");
- }
- }
-
- public BERConstructedOctetString(
- ASN1Encodable obj)
- {
- this(obj.toASN1Primitive());
- }
-
- public byte[] getOctets()
- {
- return string;
- }
-
- /**
- * return the DER octets that make up this string.
- */
- public Enumeration getObjects()
- {
- if (octs == null)
- {
- return generateOcts().elements();
- }
-
- return octs.elements();
- }
-
- private Vector generateOcts()
- {
- Vector vec = new Vector();
- for (int i = 0; i < string.length; i += MAX_LENGTH)
- {
- int end;
-
- if (i + MAX_LENGTH > string.length)
- {
- end = string.length;
- }
- else
- {
- end = i + MAX_LENGTH;
- }
-
- byte[] nStr = new byte[end - i];
-
- System.arraycopy(string, i, nStr, 0, nStr.length);
-
- vec.addElement(new DEROctetString(nStr));
- }
-
- return vec;
- }
-
- public static BEROctetString fromSequence(ASN1Sequence seq)
- {
- Vector v = new Vector();
- Enumeration e = seq.getObjects();
-
- while (e.hasMoreElements())
- {
- v.addElement(e.nextElement());
- }
-
- return new BERConstructedOctetString(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/BERFactory.java b/core/src/main/java/org/bouncycastle/asn1/BERFactory.java
deleted file mode 100644
index 023be0b6..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/BERFactory.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.bouncycastle.asn1;
-
-class BERFactory
-{
- static final BERSequence EMPTY_SEQUENCE = new BERSequence();
- static final BERSet EMPTY_SET = new BERSet();
-
- static BERSequence createSequence(ASN1EncodableVector v)
- {
- return v.size() < 1 ? EMPTY_SEQUENCE : new BERSequence(v);
- }
-
- static BERSet createSet(ASN1EncodableVector v)
- {
- return v.size() < 1 ? EMPTY_SET : new BERSet(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/BERGenerator.java b/core/src/main/java/org/bouncycastle/asn1/BERGenerator.java
deleted file mode 100644
index ef7f9a38..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/BERGenerator.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-public class BERGenerator
- extends ASN1Generator
-{
- private boolean _tagged = false;
- private boolean _isExplicit;
- private int _tagNo;
-
- protected BERGenerator(
- OutputStream out)
- {
- super(out);
- }
-
- public BERGenerator(
- OutputStream out,
- int tagNo,
- boolean isExplicit)
- {
- super(out);
-
- _tagged = true;
- _isExplicit = isExplicit;
- _tagNo = tagNo;
- }
-
- public OutputStream getRawOutputStream()
- {
- return _out;
- }
-
- private void writeHdr(
- int tag)
- throws IOException
- {
- _out.write(tag);
- _out.write(0x80);
- }
-
- protected void writeBERHeader(
- int tag)
- throws IOException
- {
- if (_tagged)
- {
- int tagNum = _tagNo | BERTags.TAGGED;
-
- if (_isExplicit)
- {
- writeHdr(tagNum | BERTags.CONSTRUCTED);
- writeHdr(tag);
- }
- else
- {
- if ((tag & BERTags.CONSTRUCTED) != 0)
- {
- writeHdr(tagNum | BERTags.CONSTRUCTED);
- }
- else
- {
- writeHdr(tagNum);
- }
- }
- }
- else
- {
- writeHdr(tag);
- }
- }
-
- protected void writeBERBody(
- InputStream contentStream)
- throws IOException
- {
- int ch;
-
- while ((ch = contentStream.read()) >= 0)
- {
- _out.write(ch);
- }
- }
-
- protected void writeBEREnd()
- throws IOException
- {
- _out.write(0x00);
- _out.write(0x00);
-
- if (_tagged && _isExplicit) // write extra end for tag header
- {
- _out.write(0x00);
- _out.write(0x00);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/BEROctetString.java b/core/src/main/java/org/bouncycastle/asn1/BEROctetString.java
deleted file mode 100644
index bc1ed448..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/BEROctetString.java
+++ /dev/null
@@ -1,168 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Vector;
-
-public class BEROctetString
- extends ASN1OctetString
-{
- private static final int MAX_LENGTH = 1000;
-
- private ASN1OctetString[] octs;
-
- /**
- * convert a vector of octet strings into a single byte string
- */
- static private byte[] toBytes(
- ASN1OctetString[] octs)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- for (int i = 0; i != octs.length; i++)
- {
- try
- {
- DEROctetString o = (DEROctetString)octs[i];
-
- bOut.write(o.getOctets());
- }
- catch (ClassCastException e)
- {
- throw new IllegalArgumentException(octs[i].getClass().getName() + " found in input should only contain DEROctetString");
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("exception converting octets " + e.toString());
- }
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * @param string the octets making up the octet string.
- */
- public BEROctetString(
- byte[] string)
- {
- super(string);
- }
-
- public BEROctetString(
- ASN1OctetString[] octs)
- {
- super(toBytes(octs));
-
- this.octs = octs;
- }
-
- public byte[] getOctets()
- {
- return string;
- }
-
- /**
- * return the DER octets that make up this string.
- */
- public Enumeration getObjects()
- {
- if (octs == null)
- {
- return generateOcts().elements();
- }
-
- return new Enumeration()
- {
- int counter = 0;
-
- public boolean hasMoreElements()
- {
- return counter < octs.length;
- }
-
- public Object nextElement()
- {
- return octs[counter++];
- }
- };
- }
-
- private Vector generateOcts()
- {
- Vector vec = new Vector();
- for (int i = 0; i < string.length; i += MAX_LENGTH)
- {
- int end;
-
- if (i + MAX_LENGTH > string.length)
- {
- end = string.length;
- }
- else
- {
- end = i + MAX_LENGTH;
- }
-
- byte[] nStr = new byte[end - i];
-
- System.arraycopy(string, i, nStr, 0, nStr.length);
-
- vec.addElement(new DEROctetString(nStr));
- }
-
- return vec;
- }
-
- boolean isConstructed()
- {
- return true;
- }
-
- int encodedLength()
- throws IOException
- {
- int length = 0;
- for (Enumeration e = getObjects(); e.hasMoreElements();)
- {
- length += ((ASN1Encodable)e.nextElement()).toASN1Primitive().encodedLength();
- }
-
- return 2 + length + 2;
- }
-
- public void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.write(BERTags.CONSTRUCTED | BERTags.OCTET_STRING);
-
- out.write(0x80);
-
- //
- // write out the octet array
- //
- for (Enumeration e = getObjects(); e.hasMoreElements();)
- {
- out.writeObject((ASN1Encodable)e.nextElement());
- }
-
- out.write(0x00);
- out.write(0x00);
- }
-
- static BEROctetString fromSequence(ASN1Sequence seq)
- {
- ASN1OctetString[] v = new ASN1OctetString[seq.size()];
- Enumeration e = seq.getObjects();
- int index = 0;
-
- while (e.hasMoreElements())
- {
- v[index++] = (ASN1OctetString)e.nextElement();
- }
-
- return new BEROctetString(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/BEROctetStringGenerator.java b/core/src/main/java/org/bouncycastle/asn1/BEROctetStringGenerator.java
deleted file mode 100644
index b8df94af..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/BEROctetStringGenerator.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class BEROctetStringGenerator
- extends BERGenerator
-{
- public BEROctetStringGenerator(OutputStream out)
- throws IOException
- {
- super(out);
-
- writeBERHeader(BERTags.CONSTRUCTED | BERTags.OCTET_STRING);
- }
-
- public BEROctetStringGenerator(
- OutputStream out,
- int tagNo,
- boolean isExplicit)
- throws IOException
- {
- super(out, tagNo, isExplicit);
-
- writeBERHeader(BERTags.CONSTRUCTED | BERTags.OCTET_STRING);
- }
-
- public OutputStream getOctetOutputStream()
- {
- return getOctetOutputStream(new byte[1000]); // limit for CER encoding.
- }
-
- public OutputStream getOctetOutputStream(
- byte[] buf)
- {
- return new BufferedBEROctetStream(buf);
- }
-
- private class BufferedBEROctetStream
- extends OutputStream
- {
- private byte[] _buf;
- private int _off;
- private DEROutputStream _derOut;
-
- BufferedBEROctetStream(
- byte[] buf)
- {
- _buf = buf;
- _off = 0;
- _derOut = new DEROutputStream(_out);
- }
-
- public void write(
- int b)
- throws IOException
- {
- _buf[_off++] = (byte)b;
-
- if (_off == _buf.length)
- {
- DEROctetString.encode(_derOut, _buf);
- _off = 0;
- }
- }
-
- public void write(byte[] b, int off, int len) throws IOException
- {
- while (len > 0)
- {
- int numToCopy = Math.min(len, _buf.length - _off);
- System.arraycopy(b, off, _buf, _off, numToCopy);
-
- _off += numToCopy;
- if (_off < _buf.length)
- {
- break;
- }
-
- DEROctetString.encode(_derOut, _buf);
- _off = 0;
-
- off += numToCopy;
- len -= numToCopy;
- }
- }
-
- public void close()
- throws IOException
- {
- if (_off != 0)
- {
- byte[] bytes = new byte[_off];
- System.arraycopy(_buf, 0, bytes, 0, _off);
-
- DEROctetString.encode(_derOut, bytes);
- }
-
- writeBEREnd();
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/BEROctetStringParser.java b/core/src/main/java/org/bouncycastle/asn1/BEROctetStringParser.java
deleted file mode 100644
index 1c7132e5..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/BEROctetStringParser.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.bouncycastle.util.io.Streams;
-
-public class BEROctetStringParser
- implements ASN1OctetStringParser
-{
- private ASN1StreamParser _parser;
-
- BEROctetStringParser(
- ASN1StreamParser parser)
- {
- _parser = parser;
- }
-
- public InputStream getOctetStream()
- {
- return new ConstructedOctetStream(_parser);
- }
-
- public ASN1Primitive getLoadedObject()
- throws IOException
- {
- return new BEROctetString(Streams.readAll(getOctetStream()));
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- try
- {
- return getLoadedObject();
- }
- catch (IOException e)
- {
- throw new ASN1ParsingException("IOException converting stream to byte array: " + e.getMessage(), e);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/BEROutputStream.java b/core/src/main/java/org/bouncycastle/asn1/BEROutputStream.java
deleted file mode 100644
index 7117d4fb..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/BEROutputStream.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class BEROutputStream
- extends DEROutputStream
-{
- public BEROutputStream(
- OutputStream os)
- {
- super(os);
- }
-
- public void writeObject(
- Object obj)
- throws IOException
- {
- if (obj == null)
- {
- writeNull();
- }
- else if (obj instanceof ASN1Primitive)
- {
- ((ASN1Primitive)obj).encode(this);
- }
- else if (obj instanceof ASN1Encodable)
- {
- ((ASN1Encodable)obj).toASN1Primitive().encode(this);
- }
- else
- {
- throw new IOException("object not BEREncodable");
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/BERSequence.java b/core/src/main/java/org/bouncycastle/asn1/BERSequence.java
deleted file mode 100644
index aa44950f..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/BERSequence.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.util.Enumeration;
-
-public class BERSequence
- extends ASN1Sequence
-{
- /**
- * create an empty sequence
- */
- public BERSequence()
- {
- }
-
- /**
- * create a sequence containing one object
- */
- public BERSequence(
- ASN1Encodable obj)
- {
- super(obj);
- }
-
- /**
- * create a sequence containing a vector of objects.
- */
- public BERSequence(
- ASN1EncodableVector v)
- {
- super(v);
- }
-
- /**
- * create a sequence containing an array of objects.
- */
- public BERSequence(
- ASN1Encodable[] array)
- {
- super(array);
- }
-
- int encodedLength()
- throws IOException
- {
- int length = 0;
- for (Enumeration e = getObjects(); e.hasMoreElements();)
- {
- length += ((ASN1Encodable)e.nextElement()).toASN1Primitive().encodedLength();
- }
-
- return 2 + length + 2;
- }
-
- /*
- */
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.write(BERTags.SEQUENCE | BERTags.CONSTRUCTED);
- out.write(0x80);
-
- Enumeration e = getObjects();
- while (e.hasMoreElements())
- {
- out.writeObject((ASN1Encodable)e.nextElement());
- }
-
- out.write(0x00);
- out.write(0x00);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/BERSequenceGenerator.java b/core/src/main/java/org/bouncycastle/asn1/BERSequenceGenerator.java
deleted file mode 100644
index 6e275651..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/BERSequenceGenerator.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class BERSequenceGenerator
- extends BERGenerator
-{
- public BERSequenceGenerator(
- OutputStream out)
- throws IOException
- {
- super(out);
-
- writeBERHeader(BERTags.CONSTRUCTED | BERTags.SEQUENCE);
- }
-
- public BERSequenceGenerator(
- OutputStream out,
- int tagNo,
- boolean isExplicit)
- throws IOException
- {
- super(out, tagNo, isExplicit);
-
- writeBERHeader(BERTags.CONSTRUCTED | BERTags.SEQUENCE);
- }
-
- public void addObject(
- ASN1Encodable object)
- throws IOException
- {
- object.toASN1Primitive().encode(new BEROutputStream(_out));
- }
-
- public void close()
- throws IOException
- {
- writeBEREnd();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/BERSequenceParser.java b/core/src/main/java/org/bouncycastle/asn1/BERSequenceParser.java
deleted file mode 100644
index d5d43959..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/BERSequenceParser.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public class BERSequenceParser
- implements ASN1SequenceParser
-{
- private ASN1StreamParser _parser;
-
- BERSequenceParser(ASN1StreamParser parser)
- {
- this._parser = parser;
- }
-
- public ASN1Encodable readObject()
- throws IOException
- {
- return _parser.readObject();
- }
-
- public ASN1Primitive getLoadedObject()
- throws IOException
- {
- return new BERSequence(_parser.readVector());
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- try
- {
- return getLoadedObject();
- }
- catch (IOException e)
- {
- throw new IllegalStateException(e.getMessage());
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/BERSet.java b/core/src/main/java/org/bouncycastle/asn1/BERSet.java
deleted file mode 100644
index 064d7786..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/BERSet.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.util.Enumeration;
-
-public class BERSet
- extends ASN1Set
-{
- /**
- * create an empty sequence
- */
- public BERSet()
- {
- }
-
- /**
- * @param obj - a single object that makes up the set.
- */
- public BERSet(
- ASN1Encodable obj)
- {
- super(obj);
- }
-
- /**
- * @param v - a vector of objects making up the set.
- */
- public BERSet(
- ASN1EncodableVector v)
- {
- super(v, false);
- }
-
- /**
- * create a set from an array of objects.
- */
- public BERSet(
- ASN1Encodable[] a)
- {
- super(a, false);
- }
-
- int encodedLength()
- throws IOException
- {
- int length = 0;
- for (Enumeration e = getObjects(); e.hasMoreElements();)
- {
- length += ((ASN1Encodable)e.nextElement()).toASN1Primitive().encodedLength();
- }
-
- return 2 + length + 2;
- }
-
- /*
- */
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.write(BERTags.SET | BERTags.CONSTRUCTED);
- out.write(0x80);
-
- Enumeration e = getObjects();
- while (e.hasMoreElements())
- {
- out.writeObject((ASN1Encodable)e.nextElement());
- }
-
- out.write(0x00);
- out.write(0x00);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/BERSetParser.java b/core/src/main/java/org/bouncycastle/asn1/BERSetParser.java
deleted file mode 100644
index 5a30f3cf..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/BERSetParser.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public class BERSetParser
- implements ASN1SetParser
-{
- private ASN1StreamParser _parser;
-
- BERSetParser(ASN1StreamParser parser)
- {
- this._parser = parser;
- }
-
- public ASN1Encodable readObject()
- throws IOException
- {
- return _parser.readObject();
- }
-
- public ASN1Primitive getLoadedObject()
- throws IOException
- {
- return new BERSet(_parser.readVector());
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- try
- {
- return getLoadedObject();
- }
- catch (IOException e)
- {
- throw new ASN1ParsingException(e.getMessage(), e);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/BERTaggedObject.java b/core/src/main/java/org/bouncycastle/asn1/BERTaggedObject.java
deleted file mode 100644
index 1af0a433..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/BERTaggedObject.java
+++ /dev/null
@@ -1,147 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.util.Enumeration;
-
-/**
- * BER TaggedObject - in ASN.1 notation this is any object preceded by
- * a [n] where n is some number - these are assumed to follow the construction
- * rules (as with sequences).
- */
-public class BERTaggedObject
- extends ASN1TaggedObject
-{
- /**
- * @param tagNo the tag number for this object.
- * @param obj the tagged object.
- */
- public BERTaggedObject(
- int tagNo,
- ASN1Encodable obj)
- {
- super(true, tagNo, obj);
- }
-
- /**
- * @param explicit true if an explicitly tagged object.
- * @param tagNo the tag number for this object.
- * @param obj the tagged object.
- */
- public BERTaggedObject(
- boolean explicit,
- int tagNo,
- ASN1Encodable obj)
- {
- super(explicit, tagNo, obj);
- }
-
- /**
- * create an implicitly tagged object that contains a zero
- * length sequence.
- */
- public BERTaggedObject(
- int tagNo)
- {
- super(false, tagNo, new BERSequence());
- }
-
- boolean isConstructed()
- {
- if (!empty)
- {
- if (explicit)
- {
- return true;
- }
- else
- {
- ASN1Primitive primitive = obj.toASN1Primitive().toDERObject();
-
- return primitive.isConstructed();
- }
- }
- else
- {
- return true;
- }
- }
-
- int encodedLength()
- throws IOException
- {
- if (!empty)
- {
- ASN1Primitive primitive = obj.toASN1Primitive();
- int length = primitive.encodedLength();
-
- if (explicit)
- {
- return StreamUtil.calculateTagLength(tagNo) + StreamUtil.calculateBodyLength(length) + length;
- }
- else
- {
- // header length already in calculation
- length = length - 1;
-
- return StreamUtil.calculateTagLength(tagNo) + length;
- }
- }
- else
- {
- return StreamUtil.calculateTagLength(tagNo) + 1;
- }
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.writeTag(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo);
- out.write(0x80);
-
- if (!empty)
- {
- if (!explicit)
- {
- Enumeration e;
- if (obj instanceof ASN1OctetString)
- {
- if (obj instanceof BEROctetString)
- {
- e = ((BEROctetString)obj).getObjects();
- }
- else
- {
- ASN1OctetString octs = (ASN1OctetString)obj;
- BEROctetString berO = new BEROctetString(octs.getOctets());
- e = berO.getObjects();
- }
- }
- else if (obj instanceof ASN1Sequence)
- {
- e = ((ASN1Sequence)obj).getObjects();
- }
- else if (obj instanceof ASN1Set)
- {
- e = ((ASN1Set)obj).getObjects();
- }
- else
- {
- throw new RuntimeException("not implemented: " + obj.getClass().getName());
- }
-
- while (e.hasMoreElements())
- {
- out.writeObject((ASN1Encodable)e.nextElement());
- }
- }
- else
- {
- out.writeObject(obj);
- }
- }
-
- out.write(0x00);
- out.write(0x00);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/BERTaggedObjectParser.java b/core/src/main/java/org/bouncycastle/asn1/BERTaggedObjectParser.java
deleted file mode 100644
index 7cd334a4..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/BERTaggedObjectParser.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public class BERTaggedObjectParser
- implements ASN1TaggedObjectParser
-{
- private boolean _constructed;
- private int _tagNumber;
- private ASN1StreamParser _parser;
-
- BERTaggedObjectParser(
- boolean constructed,
- int tagNumber,
- ASN1StreamParser parser)
- {
- _constructed = constructed;
- _tagNumber = tagNumber;
- _parser = parser;
- }
-
- public boolean isConstructed()
- {
- return _constructed;
- }
-
- public int getTagNo()
- {
- return _tagNumber;
- }
-
- public ASN1Encodable getObjectParser(
- int tag,
- boolean isExplicit)
- throws IOException
- {
- if (isExplicit)
- {
- if (!_constructed)
- {
- throw new IOException("Explicit tags must be constructed (see X.690 8.14.2)");
- }
- return _parser.readObject();
- }
-
- return _parser.readImplicit(_constructed, tag);
- }
-
- public ASN1Primitive getLoadedObject()
- throws IOException
- {
- return _parser.readTaggedObject(_constructed, _tagNumber);
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- try
- {
- return this.getLoadedObject();
- }
- catch (IOException e)
- {
- throw new ASN1ParsingException(e.getMessage());
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/BERTags.java b/core/src/main/java/org/bouncycastle/asn1/BERTags.java
deleted file mode 100644
index 98ab0d68..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/BERTags.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.bouncycastle.asn1;
-
-public interface BERTags
-{
- public static final int BOOLEAN = 0x01;
- public static final int INTEGER = 0x02;
- public static final int BIT_STRING = 0x03;
- public static final int OCTET_STRING = 0x04;
- public static final int NULL = 0x05;
- public static final int OBJECT_IDENTIFIER = 0x06;
- public static final int EXTERNAL = 0x08;
- public static final int ENUMERATED = 0x0a;
- public static final int SEQUENCE = 0x10;
- public static final int 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 - used to model a SET of the same type.
-
-
- public static final int NUMERIC_STRING = 0x12;
- public static final int PRINTABLE_STRING = 0x13;
- public static final int T61_STRING = 0x14;
- public static final int VIDEOTEX_STRING = 0x15;
- public static final int IA5_STRING = 0x16;
- public static final int UTC_TIME = 0x17;
- public static final int GENERALIZED_TIME = 0x18;
- public static final int GRAPHIC_STRING = 0x19;
- public static final int VISIBLE_STRING = 0x1a;
- public static final int GENERAL_STRING = 0x1b;
- public static final int UNIVERSAL_STRING = 0x1c;
- public static final int BMP_STRING = 0x1e;
- public static final int UTF8_STRING = 0x0c;
-
- public static final int CONSTRUCTED = 0x20;
- public static final int APPLICATION = 0x40;
- public static final int TAGGED = 0x80;
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ConstructedOctetStream.java b/core/src/main/java/org/bouncycastle/asn1/ConstructedOctetStream.java
deleted file mode 100644
index f247b11f..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ConstructedOctetStream.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-class ConstructedOctetStream
- extends InputStream
-{
- private final ASN1StreamParser _parser;
-
- private boolean _first = true;
- private InputStream _currentStream;
-
- ConstructedOctetStream(
- ASN1StreamParser parser)
- {
- _parser = parser;
- }
-
- public int read(byte[] b, int off, int len) throws IOException
- {
- if (_currentStream == null)
- {
- if (!_first)
- {
- return -1;
- }
-
- ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();
-
- if (s == null)
- {
- return -1;
- }
-
- _first = false;
- _currentStream = s.getOctetStream();
- }
-
- int totalRead = 0;
-
- for (;;)
- {
- int numRead = _currentStream.read(b, off + totalRead, len - totalRead);
-
- if (numRead >= 0)
- {
- totalRead += numRead;
-
- if (totalRead == len)
- {
- return totalRead;
- }
- }
- else
- {
- ASN1OctetStringParser aos = (ASN1OctetStringParser)_parser.readObject();
-
- if (aos == null)
- {
- _currentStream = null;
- return totalRead < 1 ? -1 : totalRead;
- }
-
- _currentStream = aos.getOctetStream();
- }
- }
- }
-
- public int read()
- throws IOException
- {
- if (_currentStream == null)
- {
- if (!_first)
- {
- return -1;
- }
-
- ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();
-
- if (s == null)
- {
- return -1;
- }
-
- _first = false;
- _currentStream = s.getOctetStream();
- }
-
- for (;;)
- {
- int b = _currentStream.read();
-
- if (b >= 0)
- {
- return b;
- }
-
- ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();
-
- if (s == null)
- {
- _currentStream = null;
- return -1;
- }
-
- _currentStream = s.getOctetStream();
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERApplicationSpecific.java b/core/src/main/java/org/bouncycastle/asn1/DERApplicationSpecific.java
deleted file mode 100644
index 85d9843b..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERApplicationSpecific.java
+++ /dev/null
@@ -1,267 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * Base class for an application specific object
- */
-public class DERApplicationSpecific
- extends ASN1Primitive
-{
- private final boolean isConstructed;
- private final int tag;
- private final byte[] octets;
-
- DERApplicationSpecific(
- boolean isConstructed,
- int tag,
- byte[] octets)
- {
- this.isConstructed = isConstructed;
- this.tag = tag;
- this.octets = octets;
- }
-
- public DERApplicationSpecific(
- int tag,
- byte[] octets)
- {
- this(false, tag, octets);
- }
-
- public DERApplicationSpecific(
- int tag,
- ASN1Encodable object)
- throws IOException
- {
- this(true, tag, object);
- }
-
- public DERApplicationSpecific(
- boolean explicit,
- int tag,
- ASN1Encodable object)
- throws IOException
- {
- ASN1Primitive primitive = object.toASN1Primitive();
-
- byte[] data = primitive.getEncoded(ASN1Encoding.DER);
-
- this.isConstructed = explicit || (primitive instanceof ASN1Set || primitive instanceof ASN1Sequence);
- this.tag = tag;
-
- if (explicit)
- {
- this.octets = data;
- }
- else
- {
- int lenBytes = getLengthOfHeader(data);
- byte[] tmp = new byte[data.length - lenBytes];
- System.arraycopy(data, lenBytes, tmp, 0, tmp.length);
- this.octets = tmp;
- }
- }
-
- public DERApplicationSpecific(int tagNo, ASN1EncodableVector vec)
- {
- this.tag = tagNo;
- this.isConstructed = true;
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- for (int i = 0; i != vec.size(); i++)
- {
- try
- {
- bOut.write(((ASN1Object)vec.get(i)).getEncoded(ASN1Encoding.DER));
- }
- catch (IOException e)
- {
- throw new ASN1ParsingException("malformed object: " + e, e);
- }
- }
- this.octets = bOut.toByteArray();
- }
-
- public static DERApplicationSpecific getInstance(Object obj)
- {
- if (obj == null || obj instanceof DERApplicationSpecific)
- {
- return (DERApplicationSpecific)obj;
- }
- else if (obj instanceof byte[])
- {
- try
- {
- return DERApplicationSpecific.getInstance(ASN1Primitive.fromByteArray((byte[])obj));
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("failed to construct object from byte[]: " + e.getMessage());
- }
- }
-
- throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
- }
-
- private int getLengthOfHeader(byte[] data)
- {
- int length = data[1] & 0xff; // TODO: assumes 1 byte tag
-
- if (length == 0x80)
- {
- return 2; // indefinite-length encoding
- }
-
- if (length > 127)
- {
- int size = length & 0x7f;
-
- // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
- if (size > 4)
- {
- throw new IllegalStateException("DER length more than 4 bytes: " + size);
- }
-
- return size + 2;
- }
-
- return 2;
- }
-
- public boolean isConstructed()
- {
- return isConstructed;
- }
-
- public byte[] getContents()
- {
- return octets;
- }
-
- public int getApplicationTag()
- {
- return tag;
- }
-
- /**
- * Return the enclosed object assuming explicit tagging.
- *
- * @return the resulting object
- * @throws IOException if reconstruction fails.
- */
- public ASN1Primitive getObject()
- throws IOException
- {
- return new ASN1InputStream(getContents()).readObject();
- }
-
- /**
- * Return the enclosed object assuming implicit tagging.
- *
- * @param derTagNo the type tag that should be applied to the object's contents.
- * @return the resulting object
- * @throws IOException if reconstruction fails.
- */
- public ASN1Primitive getObject(int derTagNo)
- throws IOException
- {
- if (derTagNo >= 0x1f)
- {
- throw new IOException("unsupported tag number");
- }
-
- byte[] orig = this.getEncoded();
- byte[] tmp = replaceTagNumber(derTagNo, orig);
-
- if ((orig[0] & BERTags.CONSTRUCTED) != 0)
- {
- tmp[0] |= BERTags.CONSTRUCTED;
- }
-
- return new ASN1InputStream(tmp).readObject();
- }
-
- int encodedLength()
- throws IOException
- {
- return StreamUtil.calculateTagLength(tag) + StreamUtil.calculateBodyLength(octets.length) + octets.length;
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.asn1.ASN1Primitive#encode(org.bouncycastle.asn1.DEROutputStream)
- */
- void encode(ASN1OutputStream out) throws IOException
- {
- int classBits = BERTags.APPLICATION;
- if (isConstructed)
- {
- classBits |= BERTags.CONSTRUCTED;
- }
-
- out.writeEncoded(classBits, tag, octets);
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof DERApplicationSpecific))
- {
- return false;
- }
-
- DERApplicationSpecific other = (DERApplicationSpecific)o;
-
- return isConstructed == other.isConstructed
- && tag == other.tag
- && Arrays.areEqual(octets, other.octets);
- }
-
- public int hashCode()
- {
- return (isConstructed ? 1 : 0) ^ tag ^ Arrays.hashCode(octets);
- }
-
- private byte[] replaceTagNumber(int newTag, byte[] input)
- throws IOException
- {
- int tagNo = input[0] & 0x1f;
- int index = 1;
- //
- // with tagged object tag number is bottom 5 bits, or stored at the start of the content
- //
- if (tagNo == 0x1f)
- {
- tagNo = 0;
-
- int b = input[index++] & 0xff;
-
- // X.690-0207 8.1.2.4.2
- // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
- if ((b & 0x7f) == 0) // Note: -1 will pass
- {
- throw new ASN1ParsingException("corrupted stream - invalid high tag number found");
- }
-
- while ((b >= 0) && ((b & 0x80) != 0))
- {
- tagNo |= (b & 0x7f);
- tagNo <<= 7;
- b = input[index++] & 0xff;
- }
-
- tagNo |= (b & 0x7f);
- }
-
- byte[] tmp = new byte[input.length - index + 1];
-
- System.arraycopy(input, index, tmp, 1, tmp.length - 1);
-
- tmp[0] = (byte)newTag;
-
- return tmp;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERBMPString.java b/core/src/main/java/org/bouncycastle/asn1/DERBMPString.java
deleted file mode 100644
index 635300b4..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERBMPString.java
+++ /dev/null
@@ -1,157 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * DER BMPString object.
- */
-public class DERBMPString
- extends ASN1Primitive
- implements ASN1String
-{
- private char[] string;
-
- /**
- * return a BMP String from the given object.
- *
- * @param obj the object we want converted.
- * @exception IllegalArgumentException if the object cannot be converted.
- * @return a DERBMPString instance, or null.
- */
- public static DERBMPString getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DERBMPString)
- {
- return (DERBMPString)obj;
- }
-
- if (obj instanceof byte[])
- {
- try
- {
- return (DERBMPString)fromByteArray((byte[])obj);
- }
- catch (Exception e)
- {
- throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
- }
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return a BMP String from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- * @return a DERBMPString instance.
- */
- public static DERBMPString getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof DERBMPString)
- {
- return getInstance(o);
- }
- else
- {
- return new DERBMPString(ASN1OctetString.getInstance(o).getOctets());
- }
- }
-
- /**
- * basic constructor - byte encoded string.
- * @param string the encoded BMP STRING to wrap.
- */
- DERBMPString(
- byte[] string)
- {
- char[] cs = new char[string.length / 2];
-
- for (int i = 0; i != cs.length; i++)
- {
- cs[i] = (char)((string[2 * i] << 8) | (string[2 * i + 1] & 0xff));
- }
-
- this.string = cs;
- }
-
- DERBMPString(char[] string)
- {
- this.string = string;
- }
-
- /**
- * basic constructor
- * @param string a String to wrap as a BMP STRING.
- */
- public DERBMPString(
- String string)
- {
- this.string = string.toCharArray();
- }
-
- public String getString()
- {
- return new String(string);
- }
-
- public String toString()
- {
- return getString();
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(string);
- }
-
- protected boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof DERBMPString))
- {
- return false;
- }
-
- DERBMPString s = (DERBMPString)o;
-
- return Arrays.areEqual(string, s.string);
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- return 1 + StreamUtil.calculateBodyLength(string.length * 2) + (string.length * 2);
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.write(BERTags.BMP_STRING);
- out.writeLength(string.length * 2);
-
- for (int i = 0; i != string.length; i++)
- {
- char c = string[i];
-
- out.write((byte)(c >> 8));
- out.write((byte)c);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERBitString.java b/core/src/main/java/org/bouncycastle/asn1/DERBitString.java
deleted file mode 100644
index 4852a796..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERBitString.java
+++ /dev/null
@@ -1,318 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.io.Streams;
-
-public class DERBitString
- extends ASN1Primitive
- implements ASN1String
-{
- private static final char[] table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
-
- protected byte[] data;
- protected int padBits;
-
- /**
- * @param bitString an int containing the BIT STRING
- * @return the correct number of pad bits for a bit string defined in
- * a 32 bit constant
- */
- static protected int getPadBits(
- int bitString)
- {
- int val = 0;
- for (int i = 3; i >= 0; i--)
- {
- //
- // this may look a little odd, but if it isn't done like this pre jdk1.2
- // JVM's break!
- //
- if (i != 0)
- {
- if ((bitString >> (i * 8)) != 0)
- {
- val = (bitString >> (i * 8)) & 0xFF;
- break;
- }
- }
- else
- {
- if (bitString != 0)
- {
- val = bitString & 0xFF;
- break;
- }
- }
- }
-
- if (val == 0)
- {
- return 7;
- }
-
-
- int bits = 1;
-
- while (((val <<= 1) & 0xFF) != 0)
- {
- bits++;
- }
-
- return 8 - bits;
- }
-
- /**
- * @param bitString an int containing the BIT STRING
- * @return the correct number of bytes for a bit string defined in
- * a 32 bit constant
- */
- static protected byte[] getBytes(int bitString)
- {
- int bytes = 4;
- for (int i = 3; i >= 1; i--)
- {
- if ((bitString & (0xFF << (i * 8))) != 0)
- {
- break;
- }
- bytes--;
- }
-
- byte[] result = new byte[bytes];
- for (int i = 0; i < bytes; i++)
- {
- result[i] = (byte) ((bitString >> (i * 8)) & 0xFF);
- }
-
- return result;
- }
-
- /**
- * return a Bit String from the passed in object
- *
- * @param obj a DERBitString or an object that can be converted into one.
- * @exception IllegalArgumentException if the object cannot be converted.
- * @return a DERBitString instance, or null.
- */
- public static DERBitString getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DERBitString)
- {
- return (DERBitString)obj;
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return a Bit String from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- * @return a DERBitString instance, or null.
- */
- public static DERBitString getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof DERBitString)
- {
- return getInstance(o);
- }
- else
- {
- return fromOctetString(((ASN1OctetString)o).getOctets());
- }
- }
-
- protected DERBitString(
- byte data,
- int padBits)
- {
- this.data = new byte[1];
- this.data[0] = data;
- this.padBits = padBits;
- }
-
- /**
- * @param data the octets making up the bit string.
- * @param padBits the number of extra bits at the end of the string.
- */
- public DERBitString(
- byte[] data,
- int padBits)
- {
- this.data = data;
- this.padBits = padBits;
- }
-
- public DERBitString(
- byte[] data)
- {
- this(data, 0);
- }
-
- public DERBitString(
- int value)
- {
- this.data = getBytes(value);
- this.padBits = getPadBits(value);
- }
-
- public DERBitString(
- ASN1Encodable obj)
- throws IOException
- {
- this.data = obj.toASN1Primitive().getEncoded(ASN1Encoding.DER);
- this.padBits = 0;
- }
-
- public byte[] getBytes()
- {
- return data;
- }
-
- public int getPadBits()
- {
- return padBits;
- }
-
-
- /**
- * @return the value of the bit string as an int (truncating if necessary)
- */
- public int intValue()
- {
- int value = 0;
-
- for (int i = 0; i != data.length && i != 4; i++)
- {
- value |= (data[i] & 0xff) << (8 * i);
- }
-
- return value;
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- return 1 + StreamUtil.calculateBodyLength(data.length + 1) + data.length + 1;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- byte[] bytes = new byte[getBytes().length + 1];
-
- bytes[0] = (byte)getPadBits();
- System.arraycopy(getBytes(), 0, bytes, 1, bytes.length - 1);
-
- out.writeEncoded(BERTags.BIT_STRING, bytes);
- }
-
- public int hashCode()
- {
- return padBits ^ Arrays.hashCode(data);
- }
-
- protected boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof DERBitString))
- {
- return false;
- }
-
- DERBitString other = (DERBitString)o;
-
- return this.padBits == other.padBits
- && Arrays.areEqual(this.data, other.data);
- }
-
- public String getString()
- {
- StringBuffer buf = new StringBuffer("#");
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- ASN1OutputStream aOut = new ASN1OutputStream(bOut);
-
- try
- {
- aOut.writeObject(this);
- }
- catch (IOException e)
- {
- throw new RuntimeException("internal error encoding BitString");
- }
-
- byte[] string = bOut.toByteArray();
-
- for (int i = 0; i != string.length; i++)
- {
- buf.append(table[(string[i] >>> 4) & 0xf]);
- buf.append(table[string[i] & 0xf]);
- }
-
- return buf.toString();
- }
-
- public String toString()
- {
- return getString();
- }
-
- static DERBitString fromOctetString(byte[] bytes)
- {
- if (bytes.length < 1)
- {
- throw new IllegalArgumentException("truncated BIT STRING detected");
- }
-
- int padBits = bytes[0];
- byte[] data = new byte[bytes.length - 1];
-
- if (data.length != 0)
- {
- System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
- }
-
- return new DERBitString(data, padBits);
- }
-
- static DERBitString fromInputStream(int length, InputStream stream)
- throws IOException
- {
- if (length < 1)
- {
- throw new IllegalArgumentException("truncated BIT STRING detected");
- }
-
- int padBits = stream.read();
- byte[] data = new byte[length - 1];
-
- if (data.length != 0)
- {
- if (Streams.readFully(stream, data) != data.length)
- {
- throw new EOFException("EOF encountered in middle of BIT STRING");
- }
- }
-
- return new DERBitString(data, padBits);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERBoolean.java b/core/src/main/java/org/bouncycastle/asn1/DERBoolean.java
deleted file mode 100644
index 378ea359..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERBoolean.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.bouncycastle.asn1;
-
-/**
- * @deprecated use ASN1Boolean
- */
-public class DERBoolean
- extends ASN1Boolean
-{
- /**
- * @deprecated use getInstance(boolean) method.
- * @param value
- */
- public DERBoolean(boolean value)
- {
- super(value);
- }
-
- DERBoolean(byte[] value)
- {
- super(value);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DEREncodableVector.java b/core/src/main/java/org/bouncycastle/asn1/DEREncodableVector.java
deleted file mode 100644
index 919ff72d..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DEREncodableVector.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.bouncycastle.asn1;
-
-/**
- * a general class for building up a vector of DER encodable objects -
- * this will eventually be superceded by ASN1EncodableVector so you should
- * use that class in preference.
- */
-public class DEREncodableVector
- extends ASN1EncodableVector
-{
- /**
- * @deprecated use ASN1EncodableVector instead.
- */
- public DEREncodableVector()
- {
-
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DEREnumerated.java b/core/src/main/java/org/bouncycastle/asn1/DEREnumerated.java
deleted file mode 100644
index daa8777e..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DEREnumerated.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.math.BigInteger;
-
-/**
- * @deprecated Use ASN1Enumerated instead of this.
- */
-public class DEREnumerated
- extends ASN1Enumerated
-{
- /**
- * @param bytes the value of this enumerated as an encoded BigInteger (signed).
- * @deprecated use ASN1Enumerated
- */
- DEREnumerated(byte[] bytes)
- {
- super(bytes);
- }
-
- /**
- * @param value the value of this enumerated.
- * @deprecated use ASN1Enumerated
- */
- public DEREnumerated(BigInteger value)
- {
- super(value);
- }
-
- /**
- * @param value the value of this enumerated.
- * @deprecated use ASN1Enumerated
- */
- public DEREnumerated(int value)
- {
- super(value);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERExternal.java b/core/src/main/java/org/bouncycastle/asn1/DERExternal.java
deleted file mode 100644
index aed1d27f..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERExternal.java
+++ /dev/null
@@ -1,294 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-/**
- * Class representing the DER-type External
- */
-public class DERExternal
- extends ASN1Primitive
-{
- private ASN1ObjectIdentifier directReference;
- private ASN1Integer indirectReference;
- private ASN1Primitive dataValueDescriptor;
- private int encoding;
- private ASN1Primitive externalContent;
-
- public DERExternal(ASN1EncodableVector vector)
- {
- int offset = 0;
-
- ASN1Primitive enc = getObjFromVector(vector, offset);
- if (enc instanceof ASN1ObjectIdentifier)
- {
- directReference = (ASN1ObjectIdentifier)enc;
- offset++;
- enc = getObjFromVector(vector, offset);
- }
- if (enc instanceof ASN1Integer)
- {
- indirectReference = (ASN1Integer) enc;
- offset++;
- enc = getObjFromVector(vector, offset);
- }
- if (!(enc instanceof DERTaggedObject))
- {
- dataValueDescriptor = (ASN1Primitive) enc;
- offset++;
- enc = getObjFromVector(vector, offset);
- }
-
- if (vector.size() != offset + 1)
- {
- throw new IllegalArgumentException("input vector too large");
- }
-
- if (!(enc instanceof DERTaggedObject))
- {
- throw new IllegalArgumentException("No tagged object found in vector. Structure doesn't seem to be of type External");
- }
- DERTaggedObject obj = (DERTaggedObject)enc;
- setEncoding(obj.getTagNo());
- externalContent = obj.getObject();
- }
-
- private ASN1Primitive getObjFromVector(ASN1EncodableVector v, int index)
- {
- if (v.size() <= index)
- {
- throw new IllegalArgumentException("too few objects in input vector");
- }
-
- return v.get(index).toASN1Primitive();
- }
- /**
- * Creates a new instance of DERExternal
- * See X.690 for more informations about the meaning of these parameters
- * @param directReference The direct reference or <code>null</code> if not set.
- * @param indirectReference The indirect reference or <code>null</code> if not set.
- * @param dataValueDescriptor The data value descriptor or <code>null</code> if not set.
- * @param externalData The external data in its encoded form.
- */
- public DERExternal(ASN1ObjectIdentifier directReference, ASN1Integer indirectReference, ASN1Primitive dataValueDescriptor, DERTaggedObject externalData)
- {
- this(directReference, indirectReference, dataValueDescriptor, externalData.getTagNo(), externalData.toASN1Primitive());
- }
-
- /**
- * Creates a new instance of DERExternal.
- * See X.690 for more informations about the meaning of these parameters
- * @param directReference The direct reference or <code>null</code> if not set.
- * @param indirectReference The indirect reference or <code>null</code> if not set.
- * @param dataValueDescriptor The data value descriptor or <code>null</code> if not set.
- * @param encoding The encoding to be used for the external data
- * @param externalData The external data
- */
- public DERExternal(ASN1ObjectIdentifier directReference, ASN1Integer indirectReference, ASN1Primitive dataValueDescriptor, int encoding, ASN1Primitive externalData)
- {
- setDirectReference(directReference);
- setIndirectReference(indirectReference);
- setDataValueDescriptor(dataValueDescriptor);
- setEncoding(encoding);
- setExternalContent(externalData.toASN1Primitive());
- }
-
- /* (non-Javadoc)
- * @see java.lang.Object#hashCode()
- */
- public int hashCode()
- {
- int ret = 0;
- if (directReference != null)
- {
- ret = directReference.hashCode();
- }
- if (indirectReference != null)
- {
- ret ^= indirectReference.hashCode();
- }
- if (dataValueDescriptor != null)
- {
- ret ^= dataValueDescriptor.hashCode();
- }
- ret ^= externalContent.hashCode();
- return ret;
- }
-
- boolean isConstructed()
- {
- return true;
- }
-
- int encodedLength()
- throws IOException
- {
- return this.getEncoded().length;
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.asn1.ASN1Primitive#encode(org.bouncycastle.asn1.DEROutputStream)
- */
- void encode(ASN1OutputStream out)
- throws IOException
- {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- if (directReference != null)
- {
- baos.write(directReference.getEncoded(ASN1Encoding.DER));
- }
- if (indirectReference != null)
- {
- baos.write(indirectReference.getEncoded(ASN1Encoding.DER));
- }
- if (dataValueDescriptor != null)
- {
- baos.write(dataValueDescriptor.getEncoded(ASN1Encoding.DER));
- }
- DERTaggedObject obj = new DERTaggedObject(true, encoding, externalContent);
- baos.write(obj.getEncoded(ASN1Encoding.DER));
- out.writeEncoded(BERTags.CONSTRUCTED, BERTags.EXTERNAL, baos.toByteArray());
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.asn1.ASN1Primitive#asn1Equals(org.bouncycastle.asn1.ASN1Primitive)
- */
- boolean asn1Equals(ASN1Primitive o)
- {
- if (!(o instanceof DERExternal))
- {
- return false;
- }
- if (this == o)
- {
- return true;
- }
- DERExternal other = (DERExternal)o;
- if (directReference != null)
- {
- if (other.directReference == null || !other.directReference.equals(directReference))
- {
- return false;
- }
- }
- if (indirectReference != null)
- {
- if (other.indirectReference == null || !other.indirectReference.equals(indirectReference))
- {
- return false;
- }
- }
- if (dataValueDescriptor != null)
- {
- if (other.dataValueDescriptor == null || !other.dataValueDescriptor.equals(dataValueDescriptor))
- {
- return false;
- }
- }
- return externalContent.equals(other.externalContent);
- }
-
- /**
- * Returns the data value descriptor
- * @return The descriptor
- */
- public ASN1Primitive getDataValueDescriptor()
- {
- return dataValueDescriptor;
- }
-
- /**
- * Returns the direct reference of the external element
- * @return The reference
- */
- public ASN1ObjectIdentifier getDirectReference()
- {
- return directReference;
- }
-
- /**
- * Returns the encoding of the content. Valid values are
- * <ul>
- * <li><code>0</code> single-ASN1-type</li>
- * <li><code>1</code> OCTET STRING</li>
- * <li><code>2</code> BIT STRING</li>
- * </ul>
- * @return The encoding
- */
- public int getEncoding()
- {
- return encoding;
- }
-
- /**
- * Returns the content of this element
- * @return The content
- */
- public ASN1Primitive getExternalContent()
- {
- return externalContent;
- }
-
- /**
- * Returns the indirect reference of this element
- * @return The reference
- */
- public ASN1Integer getIndirectReference()
- {
- return indirectReference;
- }
-
- /**
- * Sets the data value descriptor
- * @param dataValueDescriptor The descriptor
- */
- private void setDataValueDescriptor(ASN1Primitive dataValueDescriptor)
- {
- this.dataValueDescriptor = dataValueDescriptor;
- }
-
- /**
- * Sets the direct reference of the external element
- * @param directReferemce The reference
- */
- private void setDirectReference(ASN1ObjectIdentifier directReferemce)
- {
- this.directReference = directReferemce;
- }
-
- /**
- * Sets the encoding of the content. Valid values are
- * <ul>
- * <li><code>0</code> single-ASN1-type</li>
- * <li><code>1</code> OCTET STRING</li>
- * <li><code>2</code> BIT STRING</li>
- * </ul>
- * @param encoding The encoding
- */
- private void setEncoding(int encoding)
- {
- if (encoding < 0 || encoding > 2)
- {
- throw new IllegalArgumentException("invalid encoding value: " + encoding);
- }
- this.encoding = encoding;
- }
-
- /**
- * Sets the content of this element
- * @param externalContent The content
- */
- private void setExternalContent(ASN1Primitive externalContent)
- {
- this.externalContent = externalContent;
- }
-
- /**
- * Sets the indirect reference of this element
- * @param indirectReference The reference
- */
- private void setIndirectReference(ASN1Integer indirectReference)
- {
- this.indirectReference = indirectReference;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERExternalParser.java b/core/src/main/java/org/bouncycastle/asn1/DERExternalParser.java
deleted file mode 100644
index b19c84d5..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERExternalParser.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public class DERExternalParser
- implements ASN1Encodable, InMemoryRepresentable
-{
- private ASN1StreamParser _parser;
-
- /**
- *
- */
- public DERExternalParser(ASN1StreamParser parser)
- {
- this._parser = parser;
- }
-
- public ASN1Encodable readObject()
- throws IOException
- {
- return _parser.readObject();
- }
-
- public ASN1Primitive getLoadedObject()
- throws IOException
- {
- try
- {
- return new DERExternal(_parser.readVector());
- }
- catch (IllegalArgumentException e)
- {
- throw new ASN1Exception(e.getMessage(), e);
- }
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- try
- {
- return getLoadedObject();
- }
- catch (IOException ioe)
- {
- throw new ASN1ParsingException("unable to get DER object", ioe);
- }
- catch (IllegalArgumentException ioe)
- {
- throw new ASN1ParsingException("unable to get DER object", ioe);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERFactory.java b/core/src/main/java/org/bouncycastle/asn1/DERFactory.java
deleted file mode 100644
index b829e3bc..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERFactory.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.bouncycastle.asn1;
-
-class DERFactory
-{
- static final ASN1Sequence EMPTY_SEQUENCE = new DERSequence();
- static final ASN1Set EMPTY_SET = new DERSet();
-
- static ASN1Sequence createSequence(ASN1EncodableVector v)
- {
- return v.size() < 1 ? EMPTY_SEQUENCE : new DLSequence(v);
- }
-
- static ASN1Set createSet(ASN1EncodableVector v)
- {
- return v.size() < 1 ? EMPTY_SET : new DLSet(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERGeneralString.java b/core/src/main/java/org/bouncycastle/asn1/DERGeneralString.java
deleted file mode 100644
index c6354f46..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERGeneralString.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Strings;
-
-public class DERGeneralString
- extends ASN1Primitive
- implements ASN1String
-{
- private byte[] string;
-
- public static DERGeneralString getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DERGeneralString)
- {
- return (DERGeneralString) obj;
- }
-
- if (obj instanceof byte[])
- {
- try
- {
- return (DERGeneralString)fromByteArray((byte[])obj);
- }
- catch (Exception e)
- {
- throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
- }
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: "
- + obj.getClass().getName());
- }
-
- public static DERGeneralString getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof DERGeneralString)
- {
- return getInstance(o);
- }
- else
- {
- return new DERGeneralString(((ASN1OctetString)o).getOctets());
- }
- }
-
- DERGeneralString(byte[] string)
- {
- this.string = string;
- }
-
- public DERGeneralString(String string)
- {
- this.string = Strings.toByteArray(string);
- }
-
- public String getString()
- {
- return Strings.fromByteArray(string);
- }
-
- public String toString()
- {
- return getString();
- }
-
- public byte[] getOctets()
- {
- return Arrays.clone(string);
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
- }
-
- void encode(ASN1OutputStream out)
- throws IOException
- {
- out.writeEncoded(BERTags.GENERAL_STRING, string);
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(string);
- }
-
- boolean asn1Equals(ASN1Primitive o)
- {
- if (!(o instanceof DERGeneralString))
- {
- return false;
- }
- DERGeneralString s = (DERGeneralString)o;
-
- return Arrays.areEqual(string, s.string);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERGeneralizedTime.java b/core/src/main/java/org/bouncycastle/asn1/DERGeneralizedTime.java
deleted file mode 100644
index adee74ec..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERGeneralizedTime.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.util.Date;
-
-/**
- * DER Generalized time object.
- */
-public class DERGeneralizedTime
- extends ASN1GeneralizedTime
-{
-
- DERGeneralizedTime(byte[] bytes)
- {
- super(bytes);
- }
-
- public DERGeneralizedTime(Date time)
- {
- super(time);
- }
-
- public DERGeneralizedTime(String time)
- {
- super(time);
- }
-
- // TODO: create proper DER encoding.
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERGenerator.java b/core/src/main/java/org/bouncycastle/asn1/DERGenerator.java
deleted file mode 100644
index 7451ad40..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERGenerator.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import org.bouncycastle.util.io.Streams;
-
-public abstract class DERGenerator
- extends ASN1Generator
-{
- private boolean _tagged = false;
- private boolean _isExplicit;
- private int _tagNo;
-
- protected DERGenerator(
- OutputStream out)
- {
- super(out);
- }
-
- public DERGenerator(
- OutputStream out,
- int tagNo,
- boolean isExplicit)
- {
- super(out);
-
- _tagged = true;
- _isExplicit = isExplicit;
- _tagNo = tagNo;
- }
-
- private void writeLength(
- OutputStream out,
- int length)
- throws IOException
- {
- if (length > 127)
- {
- int size = 1;
- int val = length;
-
- while ((val >>>= 8) != 0)
- {
- size++;
- }
-
- out.write((byte)(size | 0x80));
-
- for (int i = (size - 1) * 8; i >= 0; i -= 8)
- {
- out.write((byte)(length >> i));
- }
- }
- else
- {
- out.write((byte)length);
- }
- }
-
- void writeDEREncoded(
- OutputStream out,
- int tag,
- byte[] bytes)
- throws IOException
- {
- out.write(tag);
- writeLength(out, bytes.length);
- out.write(bytes);
- }
-
- void writeDEREncoded(
- int tag,
- byte[] bytes)
- throws IOException
- {
- if (_tagged)
- {
- int tagNum = _tagNo | BERTags.TAGGED;
-
- if (_isExplicit)
- {
- int newTag = _tagNo | BERTags.CONSTRUCTED | BERTags.TAGGED;
-
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- writeDEREncoded(bOut, tag, bytes);
-
- writeDEREncoded(_out, newTag, bOut.toByteArray());
- }
- else
- {
- if ((tag & BERTags.CONSTRUCTED) != 0)
- {
- writeDEREncoded(_out, tagNum | BERTags.CONSTRUCTED, bytes);
- }
- else
- {
- writeDEREncoded(_out, tagNum, bytes);
- }
- }
- }
- else
- {
- writeDEREncoded(_out, tag, bytes);
- }
- }
-
- void writeDEREncoded(
- OutputStream out,
- int tag,
- InputStream in)
- throws IOException
- {
- writeDEREncoded(out, tag, Streams.readAll(in));
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERIA5String.java b/core/src/main/java/org/bouncycastle/asn1/DERIA5String.java
deleted file mode 100644
index 1c533b10..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERIA5String.java
+++ /dev/null
@@ -1,189 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Strings;
-
-/**
- * DER IA5String object - this is an ascii string.
- */
-public class DERIA5String
- extends ASN1Primitive
- implements ASN1String
-{
- private byte[] string;
-
- /**
- * return a IA5 string from the passed in object
- *
- * @param obj a DERIA5String or an object that can be converted into one.
- * @exception IllegalArgumentException if the object cannot be converted.
- * @return a DERIA5String instance, or null.
- */
- public static DERIA5String getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DERIA5String)
- {
- return (DERIA5String)obj;
- }
-
- if (obj instanceof byte[])
- {
- try
- {
- return (DERIA5String)fromByteArray((byte[])obj);
- }
- catch (Exception e)
- {
- throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
- }
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return an IA5 String from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- * @return a DERIA5String instance, or null.
- */
- public static DERIA5String getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof DERIA5String)
- {
- return getInstance(o);
- }
- else
- {
- return new DERIA5String(((ASN1OctetString)o).getOctets());
- }
- }
-
- /**
- * basic constructor - with bytes.
- * @param string the byte encoding of the characters making up the string.
- */
- DERIA5String(
- byte[] string)
- {
- this.string = string;
- }
-
- /**
- * basic constructor - without validation.
- * @param string the base string to use..
- */
- public DERIA5String(
- String string)
- {
- this(string, false);
- }
-
- /**
- * Constructor with optional validation.
- *
- * @param string the base string to wrap.
- * @param validate whether or not to check the string.
- * @throws IllegalArgumentException if validate is true and the string
- * contains characters that should not be in an IA5String.
- */
- public DERIA5String(
- String string,
- boolean validate)
- {
- if (string == null)
- {
- throw new NullPointerException("string cannot be null");
- }
- if (validate && !isIA5String(string))
- {
- throw new IllegalArgumentException("string contains illegal characters");
- }
-
- this.string = Strings.toByteArray(string);
- }
-
- public String getString()
- {
- return Strings.fromByteArray(string);
- }
-
- public String toString()
- {
- return getString();
- }
-
- public byte[] getOctets()
- {
- return Arrays.clone(string);
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.writeEncoded(BERTags.IA5_STRING, string);
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(string);
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof DERIA5String))
- {
- return false;
- }
-
- DERIA5String s = (DERIA5String)o;
-
- return Arrays.areEqual(string, s.string);
- }
-
- /**
- * return true if the passed in String can be represented without
- * loss as an IA5String, false otherwise.
- *
- * @param str the string to check.
- * @return true if character set in IA5String set, false otherwise.
- */
- public static boolean isIA5String(
- String str)
- {
- for (int i = str.length() - 1; i >= 0; i--)
- {
- char ch = str.charAt(i);
-
- if (ch > 0x007f)
- {
- return false;
- }
- }
-
- return true;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERInteger.java b/core/src/main/java/org/bouncycastle/asn1/DERInteger.java
deleted file mode 100644
index d2e850f3..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERInteger.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.math.BigInteger;
-
-/**
- * @deprecated Use ASN1Integer instead of this,
- */
-public class DERInteger
- extends ASN1Integer
-{
- /**
- * Constructor from a byte array containing a signed representation of the number.
- *
- * @param bytes a byte array containing the signed number.A copy is made of the byte array.
- */
- public DERInteger(byte[] bytes)
- {
- super(bytes, true);
- }
-
- public DERInteger(BigInteger value)
- {
- super(value);
- }
-
- public DERInteger(long value)
- {
- super(value);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERNull.java b/core/src/main/java/org/bouncycastle/asn1/DERNull.java
deleted file mode 100644
index 1eb9f450..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERNull.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * A NULL object.
- */
-public class DERNull
- extends ASN1Null
-{
- public static final DERNull INSTANCE = new DERNull();
-
- private static final byte[] zeroBytes = new byte[0];
-
- /**
- * @deprecated use DERNull.INSTANCE
- */
- public DERNull()
- {
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- return 2;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.writeEncoded(BERTags.NULL, zeroBytes);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERNumericString.java b/core/src/main/java/org/bouncycastle/asn1/DERNumericString.java
deleted file mode 100644
index e1b1276d..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERNumericString.java
+++ /dev/null
@@ -1,189 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Strings;
-
-/**
- * DER NumericString object - this is an ascii string of characters {0,1,2,3,4,5,6,7,8,9, }.
- */
-public class DERNumericString
- extends ASN1Primitive
- implements ASN1String
-{
- private byte[] string;
-
- /**
- * return a Numeric string from the passed in object
- *
- * @param obj a DERNumericString or an object that can be converted into one.
- * @exception IllegalArgumentException if the object cannot be converted.
- * @return a DERNumericString instance, or null
- */
- public static DERNumericString getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DERNumericString)
- {
- return (DERNumericString)obj;
- }
-
- if (obj instanceof byte[])
- {
- try
- {
- return (DERNumericString)fromByteArray((byte[])obj);
- }
- catch (Exception e)
- {
- throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
- }
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return an Numeric String from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- * @return a DERNumericString instance, or null.
- */
- public static DERNumericString getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof DERNumericString)
- {
- return getInstance(o);
- }
- else
- {
- return new DERNumericString(ASN1OctetString.getInstance(o).getOctets());
- }
- }
-
- /**
- * basic constructor - with bytes.
- */
- DERNumericString(
- byte[] string)
- {
- this.string = string;
- }
-
- /**
- * basic constructor - without validation..
- */
- public DERNumericString(
- String string)
- {
- this(string, false);
- }
-
- /**
- * Constructor with optional validation.
- *
- * @param string the base string to wrap.
- * @param validate whether or not to check the string.
- * @throws IllegalArgumentException if validate is true and the string
- * contains characters that should not be in a NumericString.
- */
- public DERNumericString(
- String string,
- boolean validate)
- {
- if (validate && !isNumericString(string))
- {
- throw new IllegalArgumentException("string contains illegal characters");
- }
-
- this.string = Strings.toByteArray(string);
- }
-
- public String getString()
- {
- return Strings.fromByteArray(string);
- }
-
- public String toString()
- {
- return getString();
- }
-
- public byte[] getOctets()
- {
- return Arrays.clone(string);
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.writeEncoded(BERTags.NUMERIC_STRING, string);
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(string);
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof DERNumericString))
- {
- return false;
- }
-
- DERNumericString s = (DERNumericString)o;
-
- return Arrays.areEqual(string, s.string);
- }
-
- /**
- * Return true if the string can be represented as a NumericString ('0'..'9', ' ')
- *
- * @param str string to validate.
- * @return true if numeric, fale otherwise.
- */
- public static boolean isNumericString(
- String str)
- {
- for (int i = str.length() - 1; i >= 0; i--)
- {
- char ch = str.charAt(i);
-
- if (ch > 0x007f)
- {
- return false;
- }
-
- if (('0' <= ch && ch <= '9') || ch == ' ')
- {
- continue;
- }
-
- return false;
- }
-
- return true;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java b/core/src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java
deleted file mode 100644
index acb2ada6..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.bouncycastle.asn1;
-
-/**
- *
- * @deprecated Use ASN1ObjectIdentifier instead of this,
- */
-public class DERObjectIdentifier
- extends ASN1ObjectIdentifier
-{
- public DERObjectIdentifier(String identifier)
- {
- super(identifier);
- }
-
- DERObjectIdentifier(byte[] bytes)
- {
- super(bytes);
- }
-
- DERObjectIdentifier(ASN1ObjectIdentifier oid, String branch)
- {
- super(oid, branch);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DEROctetString.java b/core/src/main/java/org/bouncycastle/asn1/DEROctetString.java
deleted file mode 100644
index 988186fb..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DEROctetString.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public class DEROctetString
- extends ASN1OctetString
-{
- /**
- * @param string the octets making up the octet string.
- */
- public DEROctetString(
- byte[] string)
- {
- super(string);
- }
-
- public DEROctetString(
- ASN1Encodable obj)
- throws IOException
- {
- super(obj.toASN1Primitive().getEncoded(ASN1Encoding.DER));
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.writeEncoded(BERTags.OCTET_STRING, string);
- }
-
- static void encode(
- DEROutputStream derOut,
- byte[] bytes)
- throws IOException
- {
- derOut.writeEncoded(BERTags.OCTET_STRING, bytes);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DEROctetStringParser.java b/core/src/main/java/org/bouncycastle/asn1/DEROctetStringParser.java
deleted file mode 100644
index e6e20686..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DEROctetStringParser.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-public class DEROctetStringParser
- implements ASN1OctetStringParser
-{
- private DefiniteLengthInputStream stream;
-
- DEROctetStringParser(
- DefiniteLengthInputStream stream)
- {
- this.stream = stream;
- }
-
- public InputStream getOctetStream()
- {
- return stream;
- }
-
- public ASN1Primitive getLoadedObject()
- throws IOException
- {
- return new DEROctetString(stream.toByteArray());
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- try
- {
- return getLoadedObject();
- }
- catch (IOException e)
- {
- throw new ASN1ParsingException("IOException converting stream to byte array: " + e.getMessage(), e);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DEROutputStream.java b/core/src/main/java/org/bouncycastle/asn1/DEROutputStream.java
deleted file mode 100644
index 8b18c3d7..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DEROutputStream.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * Stream that outputs encoding based on distinguished encoding rules.
- */
-public class DEROutputStream
- extends ASN1OutputStream
-{
- public DEROutputStream(
- OutputStream os)
- {
- super(os);
- }
-
- public void writeObject(
- ASN1Encodable obj)
- throws IOException
- {
- if (obj != null)
- {
- obj.toASN1Primitive().toDERObject().encode(this);
- }
- else
- {
- throw new IOException("null object detected");
- }
- }
-
- ASN1OutputStream getDERSubStream()
- {
- return this;
- }
-
- ASN1OutputStream getDLSubStream()
- {
- return this;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERPrintableString.java b/core/src/main/java/org/bouncycastle/asn1/DERPrintableString.java
deleted file mode 100644
index e7c5d753..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERPrintableString.java
+++ /dev/null
@@ -1,216 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Strings;
-
-/**
- * DER PrintableString object.
- */
-public class DERPrintableString
- extends ASN1Primitive
- implements ASN1String
-{
- private byte[] string;
-
- /**
- * return a printable string from the passed in object.
- *
- * @param obj a DERPrintableString or an object that can be converted into one.
- * @exception IllegalArgumentException if the object cannot be converted.
- * @return a DERPrintableString instance, or null.
- */
- public static DERPrintableString getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DERPrintableString)
- {
- return (DERPrintableString)obj;
- }
-
- if (obj instanceof byte[])
- {
- try
- {
- return (DERPrintableString)fromByteArray((byte[])obj);
- }
- catch (Exception e)
- {
- throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
- }
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return a Printable String from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- * @return a DERPrintableString instance, or null.
- */
- public static DERPrintableString getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof DERPrintableString)
- {
- return getInstance(o);
- }
- else
- {
- return new DERPrintableString(ASN1OctetString.getInstance(o).getOctets());
- }
- }
-
- /**
- * basic constructor - byte encoded string.
- */
- DERPrintableString(
- byte[] string)
- {
- this.string = string;
- }
-
- /**
- * basic constructor - this does not validate the string
- */
- public DERPrintableString(
- String string)
- {
- this(string, false);
- }
-
- /**
- * Constructor with optional validation.
- *
- * @param string the base string to wrap.
- * @param validate whether or not to check the string.
- * @throws IllegalArgumentException if validate is true and the string
- * contains characters that should not be in a PrintableString.
- */
- public DERPrintableString(
- String string,
- boolean validate)
- {
- if (validate && !isPrintableString(string))
- {
- throw new IllegalArgumentException("string contains illegal characters");
- }
-
- this.string = Strings.toByteArray(string);
- }
-
- public String getString()
- {
- return Strings.fromByteArray(string);
- }
-
- public byte[] getOctets()
- {
- return Arrays.clone(string);
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.writeEncoded(BERTags.PRINTABLE_STRING, string);
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(string);
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof DERPrintableString))
- {
- return false;
- }
-
- DERPrintableString s = (DERPrintableString)o;
-
- return Arrays.areEqual(string, s.string);
- }
-
- public String toString()
- {
- return getString();
- }
-
- /**
- * return true if the passed in String can be represented without
- * loss as a PrintableString, false otherwise.
- *
- * @return true if in printable set, false otherwise.
- */
- public static boolean isPrintableString(
- String str)
- {
- for (int i = str.length() - 1; i >= 0; i--)
- {
- char ch = str.charAt(i);
-
- if (ch > 0x007f)
- {
- return false;
- }
-
- if ('a' <= ch && ch <= 'z')
- {
- continue;
- }
-
- if ('A' <= ch && ch <= 'Z')
- {
- continue;
- }
-
- if ('0' <= ch && ch <= '9')
- {
- continue;
- }
-
- switch (ch)
- {
- case ' ':
- case '\'':
- case '(':
- case ')':
- case '+':
- case '-':
- case '.':
- case ':':
- case '=':
- case '?':
- case '/':
- case ',':
- continue;
- }
-
- return false;
- }
-
- return true;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERSequence.java b/core/src/main/java/org/bouncycastle/asn1/DERSequence.java
deleted file mode 100644
index ad48a833..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERSequence.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.util.Enumeration;
-
-public class DERSequence
- extends ASN1Sequence
-{
- private int bodyLength = -1;
-
- /**
- * create an empty sequence
- */
- public DERSequence()
- {
- }
-
- /**
- * create a sequence containing one object
- */
- public DERSequence(
- ASN1Encodable obj)
- {
- super(obj);
- }
-
- /**
- * create a sequence containing a vector of objects.
- */
- public DERSequence(
- ASN1EncodableVector v)
- {
- super(v);
- }
-
- /**
- * create a sequence containing an array of objects.
- */
- public DERSequence(
- ASN1Encodable[] array)
- {
- super(array);
- }
-
- private int getBodyLength()
- throws IOException
- {
- if (bodyLength < 0)
- {
- int length = 0;
-
- for (Enumeration e = this.getObjects(); e.hasMoreElements();)
- {
- Object obj = e.nextElement();
-
- length += ((ASN1Encodable)obj).toASN1Primitive().toDERObject().encodedLength();
- }
-
- bodyLength = length;
- }
-
- return bodyLength;
- }
-
- int encodedLength()
- throws IOException
- {
- int length = getBodyLength();
-
- return 1 + StreamUtil.calculateBodyLength(length) + length;
- }
-
- /*
- * A note on the implementation:
- * <p>
- * As DER requires the constructed, definite-length model to
- * be used for structured types, this varies slightly from the
- * ASN.1 descriptions given. Rather than just outputting SEQUENCE,
- * we also have to specify CONSTRUCTED, and the objects length.
- */
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- ASN1OutputStream dOut = out.getDERSubStream();
- int length = getBodyLength();
-
- out.write(BERTags.SEQUENCE | BERTags.CONSTRUCTED);
- out.writeLength(length);
-
- for (Enumeration e = this.getObjects(); e.hasMoreElements();)
- {
- Object obj = e.nextElement();
-
- dOut.writeObject((ASN1Encodable)obj);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERSequenceGenerator.java b/core/src/main/java/org/bouncycastle/asn1/DERSequenceGenerator.java
deleted file mode 100644
index 8cb5271e..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERSequenceGenerator.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class DERSequenceGenerator
- extends DERGenerator
-{
- private final ByteArrayOutputStream _bOut = new ByteArrayOutputStream();
-
- public DERSequenceGenerator(
- OutputStream out)
- throws IOException
- {
- super(out);
- }
-
- public DERSequenceGenerator(
- OutputStream out,
- int tagNo,
- boolean isExplicit)
- throws IOException
- {
- super(out, tagNo, isExplicit);
- }
-
- public void addObject(
- ASN1Encodable object)
- throws IOException
- {
- object.toASN1Primitive().encode(new DEROutputStream(_bOut));
- }
-
- public OutputStream getRawOutputStream()
- {
- return _bOut;
- }
-
- public void close()
- throws IOException
- {
- writeDEREncoded(BERTags.CONSTRUCTED | BERTags.SEQUENCE, _bOut.toByteArray());
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERSequenceParser.java b/core/src/main/java/org/bouncycastle/asn1/DERSequenceParser.java
deleted file mode 100644
index 376c1fd8..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERSequenceParser.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public class DERSequenceParser
- implements ASN1SequenceParser
-{
- private ASN1StreamParser _parser;
-
- DERSequenceParser(ASN1StreamParser parser)
- {
- this._parser = parser;
- }
-
- public ASN1Encodable readObject()
- throws IOException
- {
- return _parser.readObject();
- }
-
- public ASN1Primitive getLoadedObject()
- throws IOException
- {
- return new DERSequence(_parser.readVector());
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- try
- {
- return getLoadedObject();
- }
- catch (IOException e)
- {
- throw new IllegalStateException(e.getMessage());
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERSet.java b/core/src/main/java/org/bouncycastle/asn1/DERSet.java
deleted file mode 100644
index c1faf849..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERSet.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.util.Enumeration;
-
-/**
- * A DER encoded set object
- */
-public class DERSet
- extends ASN1Set
-{
- private int bodyLength = -1;
-
- /**
- * create an empty set
- */
- public DERSet()
- {
- }
-
- /**
- * @param obj - a single object that makes up the set.
- */
- public DERSet(
- ASN1Encodable obj)
- {
- super(obj);
- }
-
- /**
- * @param v - a vector of objects making up the set.
- */
- public DERSet(
- ASN1EncodableVector v)
- {
- super(v, true);
- }
-
- /**
- * create a set from an array of objects.
- */
- public DERSet(
- ASN1Encodable[] a)
- {
- super(a, true);
- }
-
- DERSet(
- ASN1EncodableVector v,
- boolean doSort)
- {
- super(v, doSort);
- }
-
- private int getBodyLength()
- throws IOException
- {
- if (bodyLength < 0)
- {
- int length = 0;
-
- for (Enumeration e = this.getObjects(); e.hasMoreElements();)
- {
- Object obj = e.nextElement();
-
- length += ((ASN1Encodable)obj).toASN1Primitive().toDERObject().encodedLength();
- }
-
- bodyLength = length;
- }
-
- return bodyLength;
- }
-
- int encodedLength()
- throws IOException
- {
- int length = getBodyLength();
-
- return 1 + StreamUtil.calculateBodyLength(length) + length;
- }
-
- /*
- * A note on the implementation:
- * <p>
- * As DER requires the constructed, definite-length model to
- * be used for structured types, this varies slightly from the
- * ASN.1 descriptions given. Rather than just outputting SET,
- * we also have to specify CONSTRUCTED, and the objects length.
- */
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- ASN1OutputStream dOut = out.getDERSubStream();
- int length = getBodyLength();
-
- out.write(BERTags.SET | BERTags.CONSTRUCTED);
- out.writeLength(length);
-
- for (Enumeration e = this.getObjects(); e.hasMoreElements();)
- {
- Object obj = e.nextElement();
-
- dOut.writeObject((ASN1Encodable)obj);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERSetParser.java b/core/src/main/java/org/bouncycastle/asn1/DERSetParser.java
deleted file mode 100644
index 17702fa4..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERSetParser.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public class DERSetParser
- implements ASN1SetParser
-{
- private ASN1StreamParser _parser;
-
- DERSetParser(ASN1StreamParser parser)
- {
- this._parser = parser;
- }
-
- public ASN1Encodable readObject()
- throws IOException
- {
- return _parser.readObject();
- }
-
- public ASN1Primitive getLoadedObject()
- throws IOException
- {
- return new DERSet(_parser.readVector(), false);
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- try
- {
- return getLoadedObject();
- }
- catch (IOException e)
- {
- throw new ASN1ParsingException(e.getMessage(), e);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERT61String.java b/core/src/main/java/org/bouncycastle/asn1/DERT61String.java
deleted file mode 100644
index 783cd336..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERT61String.java
+++ /dev/null
@@ -1,151 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Strings;
-
-/**
- * DER T61String (also the teletex string), try not to use this if you don't need to. The standard support the encoding for
- * this has been withdrawn.
- */
-public class DERT61String
- extends ASN1Primitive
- implements ASN1String
-{
- private byte[] string;
-
- /**
- * return a T61 string from the passed in object.
- *
- * @param obj a DERT61String or an object that can be converted into one.
- * @exception IllegalArgumentException if the object cannot be converted.
- * @return a DERT61String instance, or null
- */
- public static DERT61String getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DERT61String)
- {
- return (DERT61String)obj;
- }
-
- if (obj instanceof byte[])
- {
- try
- {
- return (DERT61String)fromByteArray((byte[])obj);
- }
- catch (Exception e)
- {
- throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
- }
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return an T61 String from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- * @return a DERT61String instance, or null
- */
- public static DERT61String getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof DERT61String)
- {
- return getInstance(o);
- }
- else
- {
- return new DERT61String(ASN1OctetString.getInstance(o).getOctets());
- }
- }
-
- /**
- * basic constructor - string encoded as a sequence of bytes.
- *
- * @param string the byte encoding of the string to be wrapped.
- */
- public DERT61String(
- byte[] string)
- {
- this.string = string;
- }
-
- /**
- * basic constructor - with string 8 bit assumed.
- *
- * @param string the string to be wrapped.
- */
- public DERT61String(
- String string)
- {
- this(Strings.toByteArray(string));
- }
-
- /**
- * Decode the encoded string and return it, 8 bit encoding assumed.
- * @return the decoded String
- */
- public String getString()
- {
- return Strings.fromByteArray(string);
- }
-
- public String toString()
- {
- return getString();
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.writeEncoded(BERTags.T61_STRING, string);
- }
-
- /**
- * Return the encoded string as a byte array.
- * @return the actual bytes making up the encoded body of the T61 string.
- */
- public byte[] getOctets()
- {
- return Arrays.clone(string);
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof DERT61String))
- {
- return false;
- }
-
- return Arrays.areEqual(string, ((DERT61String)o).string);
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(string);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERT61UTF8String.java b/core/src/main/java/org/bouncycastle/asn1/DERT61UTF8String.java
deleted file mode 100644
index 784aaa9b..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERT61UTF8String.java
+++ /dev/null
@@ -1,154 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Strings;
-
-/**
- * DER T61String (also the teletex string) - a "modern" encapsulation that uses UTF-8. If at all possible, avoid this one! It's only for emergencies.
- * Use UTF8String instead.
- */
-public class DERT61UTF8String
- extends ASN1Primitive
- implements ASN1String
-{
- private byte[] string;
-
- /**
- * return a T61 string from the passed in object. UTF-8 Encoding is assumed in this case.
- *
- * @param obj a DERT61UTF8String or an object that can be converted into one.
- * @throws IllegalArgumentException if the object cannot be converted.
- * @return a DERT61UTF8String instance, or null
- */
- public static DERT61UTF8String getInstance(
- Object obj)
- {
- if (obj instanceof DERT61String)
- {
- return new DERT61UTF8String(((DERT61String)obj).getOctets());
- }
-
- if (obj == null || obj instanceof DERT61UTF8String)
- {
- return (DERT61UTF8String)obj;
- }
-
- if (obj instanceof byte[])
- {
- try
- {
- return new DERT61UTF8String(((DERT61String)fromByteArray((byte[])obj)).getOctets());
- }
- catch (Exception e)
- {
- throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
- }
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return an T61 String from a tagged object. UTF-8 encoding is assumed in this case.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @throws IllegalArgumentException if the tagged object cannot
- * be converted.
- * @return a DERT61UTF8String instance, or null
- */
- public static DERT61UTF8String getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof DERT61String || o instanceof DERT61UTF8String)
- {
- return getInstance(o);
- }
- else
- {
- return new DERT61UTF8String(ASN1OctetString.getInstance(o).getOctets());
- }
- }
-
- /**
- * basic constructor - string encoded as a sequence of bytes.
- */
- public DERT61UTF8String(
- byte[] string)
- {
- this.string = string;
- }
-
- /**
- * basic constructor - with string UTF8 conversion assumed.
- */
- public DERT61UTF8String(
- String string)
- {
- this(Strings.toUTF8ByteArray(string));
- }
-
- /**
- * Decode the encoded string and return it, UTF8 assumed.
- *
- * @return the decoded String
- */
- public String getString()
- {
- return Strings.fromUTF8ByteArray(string);
- }
-
- public String toString()
- {
- return getString();
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.writeEncoded(BERTags.T61_STRING, string);
- }
-
- /**
- * Return the encoded string as a byte array.
- *
- * @return the actual bytes making up the encoded body of the T61 string.
- */
- public byte[] getOctets()
- {
- return Arrays.clone(string);
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof DERT61UTF8String))
- {
- return false;
- }
-
- return Arrays.areEqual(string, ((DERT61UTF8String)o).string);
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(string);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERTaggedObject.java b/core/src/main/java/org/bouncycastle/asn1/DERTaggedObject.java
deleted file mode 100644
index a87a0dc9..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERTaggedObject.java
+++ /dev/null
@@ -1,118 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * DER TaggedObject - in ASN.1 notation this is any object preceded by
- * a [n] where n is some number - these are assumed to follow the construction
- * rules (as with sequences).
- */
-public class DERTaggedObject
- extends ASN1TaggedObject
-{
- private static final byte[] ZERO_BYTES = new byte[0];
-
- /**
- * @param explicit true if an explicitly tagged object.
- * @param tagNo the tag number for this object.
- * @param obj the tagged object.
- */
- public DERTaggedObject(
- boolean explicit,
- int tagNo,
- ASN1Encodable obj)
- {
- super(explicit, tagNo, obj);
- }
-
- public DERTaggedObject(int tagNo, ASN1Encodable encodable)
- {
- super(true, tagNo, encodable);
- }
-
- boolean isConstructed()
- {
- if (!empty)
- {
- if (explicit)
- {
- return true;
- }
- else
- {
- ASN1Primitive primitive = obj.toASN1Primitive().toDERObject();
-
- return primitive.isConstructed();
- }
- }
- else
- {
- return true;
- }
- }
-
- int encodedLength()
- throws IOException
- {
- if (!empty)
- {
- ASN1Primitive primitive = obj.toASN1Primitive().toDERObject();
- int length = primitive.encodedLength();
-
- if (explicit)
- {
- return StreamUtil.calculateTagLength(tagNo) + StreamUtil.calculateBodyLength(length) + length;
- }
- else
- {
- // header length already in calculation
- length = length - 1;
-
- return StreamUtil.calculateTagLength(tagNo) + length;
- }
- }
- else
- {
- return StreamUtil.calculateTagLength(tagNo) + 1;
- }
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- if (!empty)
- {
- ASN1Primitive primitive = obj.toASN1Primitive().toDERObject();
-
- if (explicit)
- {
- out.writeTag(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo);
- out.writeLength(primitive.encodedLength());
- out.writeObject(primitive);
- }
- else
- {
- //
- // need to mark constructed types...
- //
- int flags;
- if (primitive.isConstructed())
- {
- flags = BERTags.CONSTRUCTED | BERTags.TAGGED;
- }
- else
- {
- flags = BERTags.TAGGED;
- }
-
- out.writeTag(flags, tagNo);
- out.writeImplicitObject(primitive);
- }
- }
- else
- {
- out.writeEncoded(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo, ZERO_BYTES);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERTags.java b/core/src/main/java/org/bouncycastle/asn1/DERTags.java
deleted file mode 100644
index 83fd7fde..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERTags.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.bouncycastle.asn1;
-
-/**
- * @deprecated use BERTags
- */
-public interface DERTags
- extends BERTags
-{
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERUTCTime.java b/core/src/main/java/org/bouncycastle/asn1/DERUTCTime.java
deleted file mode 100644
index 18e17b12..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERUTCTime.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.util.Date;
-
-/**
- * DER UTC time object.
- */
-public class DERUTCTime
- extends ASN1UTCTime
-{
- DERUTCTime(byte[] bytes)
- {
- super(bytes);
- }
-
- public DERUTCTime(Date time)
- {
- super(time);
- }
-
- public DERUTCTime(String time)
- {
- super(time);
- }
-
- // TODO: create proper DER encoding.
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERUTF8String.java b/core/src/main/java/org/bouncycastle/asn1/DERUTF8String.java
deleted file mode 100644
index f54d1dbb..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERUTF8String.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Strings;
-
-/**
- * DER UTF8String object.
- */
-public class DERUTF8String
- extends ASN1Primitive
- implements ASN1String
-{
- private byte[] string;
-
- /**
- * Return an UTF8 string from the passed in object.
- *
- * @param obj a DERUTF8String or an object that can be converted into one.
- * @exception IllegalArgumentException
- * if the object cannot be converted.
- * @return a DERUTF8String instance, or null
- */
- public static DERUTF8String getInstance(Object obj)
- {
- if (obj == null || obj instanceof DERUTF8String)
- {
- return (DERUTF8String)obj;
- }
-
- if (obj instanceof byte[])
- {
- try
- {
- return (DERUTF8String)fromByteArray((byte[])obj);
- }
- catch (Exception e)
- {
- throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
- }
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: "
- + obj.getClass().getName());
- }
-
- /**
- * Return an UTF8 String from a tagged object.
- *
- * @param obj
- * the tagged object holding the object we want
- * @param explicit
- * true if the object is meant to be explicitly tagged false
- * otherwise.
- * @exception IllegalArgumentException
- * if the tagged object cannot be converted.
- * @return a DERUTF8String instance, or null
- */
- public static DERUTF8String getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof DERUTF8String)
- {
- return getInstance(o);
- }
- else
- {
- return new DERUTF8String(ASN1OctetString.getInstance(o).getOctets());
- }
- }
-
- /**
- * Basic constructor - byte encoded string.
- */
- DERUTF8String(byte[] string)
- {
- this.string = string;
- }
-
- /**
- * Basic constructor
- */
- public DERUTF8String(String string)
- {
- this.string = Strings.toUTF8ByteArray(string);
- }
-
- public String getString()
- {
- return Strings.fromUTF8ByteArray(string);
- }
-
- public String toString()
- {
- return getString();
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(string);
- }
-
- boolean asn1Equals(ASN1Primitive o)
- {
- if (!(o instanceof DERUTF8String))
- {
- return false;
- }
-
- DERUTF8String s = (DERUTF8String)o;
-
- return Arrays.areEqual(string, s.string);
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- throws IOException
- {
- return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
- }
-
- void encode(ASN1OutputStream out)
- throws IOException
- {
- out.writeEncoded(BERTags.UTF8_STRING, string);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERUniversalString.java b/core/src/main/java/org/bouncycastle/asn1/DERUniversalString.java
deleted file mode 100644
index 0d447df7..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERUniversalString.java
+++ /dev/null
@@ -1,151 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * DER UniversalString object.
- */
-public class DERUniversalString
- extends ASN1Primitive
- implements ASN1String
-{
- private static final char[] table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
- private byte[] string;
-
- /**
- * return a Universal String from the passed in object.
- *
- * @param obj a DERUniversalString or an object that can be converted into one.
- * @exception IllegalArgumentException if the object cannot be converted.
- * @return a DERUniversalString instance, or null
- */
- public static DERUniversalString getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DERUniversalString)
- {
- return (DERUniversalString)obj;
- }
-
- if (obj instanceof byte[])
- {
- try
- {
- return (DERUniversalString)fromByteArray((byte[])obj);
- }
- catch (Exception e)
- {
- throw new IllegalArgumentException("encoding error getInstance: " + e.toString());
- }
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return a Universal String from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- * @return a DERUniversalString instance, or null
- */
- public static DERUniversalString getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof DERUniversalString)
- {
- return getInstance(o);
- }
- else
- {
- return new DERUniversalString(((ASN1OctetString)o).getOctets());
- }
- }
-
- /**
- * basic constructor - byte encoded string.
- */
- public DERUniversalString(
- byte[] string)
- {
- this.string = string;
- }
-
- public String getString()
- {
- StringBuffer buf = new StringBuffer("#");
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- ASN1OutputStream aOut = new ASN1OutputStream(bOut);
-
- try
- {
- aOut.writeObject(this);
- }
- catch (IOException e)
- {
- throw new RuntimeException("internal error encoding BitString");
- }
-
- byte[] string = bOut.toByteArray();
-
- for (int i = 0; i != string.length; i++)
- {
- buf.append(table[(string[i] >>> 4) & 0xf]);
- buf.append(table[string[i] & 0xf]);
- }
-
- return buf.toString();
- }
-
- public String toString()
- {
- return getString();
- }
-
- public byte[] getOctets()
- {
- return string;
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.writeEncoded(BERTags.UNIVERSAL_STRING, this.getOctets());
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof DERUniversalString))
- {
- return false;
- }
-
- return Arrays.areEqual(string, ((DERUniversalString)o).string);
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(string);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DERVisibleString.java b/core/src/main/java/org/bouncycastle/asn1/DERVisibleString.java
deleted file mode 100644
index 6eb282cc..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DERVisibleString.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Strings;
-
-/**
- * DER VisibleString object encoding ISO 646 (ASCII) character code points 32 to 126.
- * <p>
- * Explicit character set escape sequences are not allowed.
- * </p>
- */
-public class DERVisibleString
- extends ASN1Primitive
- implements ASN1String
-{
- private byte[] string;
-
- /**
- * Return a Visible String from the passed in object.
- *
- * @param obj a DERVisibleString or an object that can be converted into one.
- * @exception IllegalArgumentException if the object cannot be converted.
- * @return a DERVisibleString instance, or null
- */
- public static DERVisibleString getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DERVisibleString)
- {
- return (DERVisibleString)obj;
- }
-
- if (obj instanceof byte[])
- {
- try
- {
- return (DERVisibleString)fromByteArray((byte[])obj);
- }
- catch (Exception e)
- {
- throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
- }
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * Return a Visible String from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- * @return a DERVisibleString instance, or null
- */
- public static DERVisibleString getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof DERVisibleString)
- {
- return getInstance(o);
- }
- else
- {
- return new DERVisibleString(ASN1OctetString.getInstance(o).getOctets());
- }
- }
-
- /**
- * Basic constructor - byte encoded string.
- */
- DERVisibleString(
- byte[] string)
- {
- this.string = string;
- }
-
- /**
- * Basic constructor
- */
- public DERVisibleString(
- String string)
- {
- this.string = Strings.toByteArray(string);
- }
-
- public String getString()
- {
- return Strings.fromByteArray(string);
- }
-
- public String toString()
- {
- return getString();
- }
-
- public byte[] getOctets()
- {
- return Arrays.clone(string);
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.writeEncoded(BERTags.VISIBLE_STRING, this.string);
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof DERVisibleString))
- {
- return false;
- }
-
- return Arrays.areEqual(string, ((DERVisibleString)o).string);
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(string);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DLOutputStream.java b/core/src/main/java/org/bouncycastle/asn1/DLOutputStream.java
deleted file mode 100644
index 68c0ed62..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DLOutputStream.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * Stream that outputs encoding based on definite length.
- */
-public class DLOutputStream
- extends ASN1OutputStream
-{
- public DLOutputStream(
- OutputStream os)
- {
- super(os);
- }
-
- public void writeObject(
- ASN1Encodable obj)
- throws IOException
- {
- if (obj != null)
- {
- obj.toASN1Primitive().toDLObject().encode(this);
- }
- else
- {
- throw new IOException("null object detected");
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DLSequence.java b/core/src/main/java/org/bouncycastle/asn1/DLSequence.java
deleted file mode 100644
index b5cc59a2..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DLSequence.java
+++ /dev/null
@@ -1,101 +0,0 @@
-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
- */
- public DLSequence()
- {
- }
-
- /**
- * Create a sequence containing one object
- */
- public DLSequence(
- ASN1Encodable obj)
- {
- super(obj);
- }
-
- /**
- * Create a sequence containing a vector of objects.
- */
- public DLSequence(
- ASN1EncodableVector v)
- {
- super(v);
- }
-
- /**
- * Create a sequence containing an array of objects.
- */
- public DLSequence(
- ASN1Encodable[] array)
- {
- super(array);
- }
-
- private int getBodyLength()
- throws IOException
- {
- if (bodyLength < 0)
- {
- int length = 0;
-
- for (Enumeration e = this.getObjects(); e.hasMoreElements();)
- {
- Object obj = e.nextElement();
-
- length += ((ASN1Encodable)obj).toASN1Primitive().toDLObject().encodedLength();
- }
-
- bodyLength = length;
- }
-
- return bodyLength;
- }
-
- int encodedLength()
- throws IOException
- {
- int length = getBodyLength();
-
- return 1 + StreamUtil.calculateBodyLength(length) + length;
- }
-
- /**
- * A note on the implementation:
- * <p>
- * As DL requires the constructed, definite-length model to
- * be used for structured types, this varies slightly from the
- * ASN.1 descriptions given. Rather than just outputting SEQUENCE,
- * we also have to specify CONSTRUCTED, and the objects length.
- */
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- 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();
-
- dOut.writeObject((ASN1Encodable)obj);
- }
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/asn1/DLSet.java b/core/src/main/java/org/bouncycastle/asn1/DLSet.java
deleted file mode 100644
index e3042c25..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DLSet.java
+++ /dev/null
@@ -1,146 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.util.Enumeration;
-
-/**
- * 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
-{
- private int bodyLength = -1;
-
- /**
- * create an empty set
- */
- public DLSet()
- {
- }
-
- /**
- * @param obj - a single object that makes up the set.
- */
- public DLSet(
- ASN1Encodable obj)
- {
- super(obj);
- }
-
- /**
- * @param v - a vector of objects making up the set.
- */
- public DLSet(
- ASN1EncodableVector v)
- {
- super(v, false);
- }
-
- /**
- * create a set from an array of objects.
- */
- public DLSet(
- ASN1Encodable[] a)
- {
- super(a, false);
- }
-
- private int getBodyLength()
- throws IOException
- {
- if (bodyLength < 0)
- {
- int length = 0;
-
- for (Enumeration e = this.getObjects(); e.hasMoreElements();)
- {
- Object obj = e.nextElement();
-
- length += ((ASN1Encodable)obj).toASN1Primitive().toDLObject().encodedLength();
- }
-
- bodyLength = length;
- }
-
- return bodyLength;
- }
-
- int encodedLength()
- throws IOException
- {
- int length = getBodyLength();
-
- return 1 + StreamUtil.calculateBodyLength(length) + length;
- }
-
- /**
- * A note on the implementation:
- * <p>
- * As DL requires the constructed, definite-length model to
- * be used for structured types, this varies slightly from the
- * ASN.1 descriptions given. Rather than just outputting SET,
- * we also have to specify CONSTRUCTED, and the objects length.
- */
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- 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();
-
- dOut.writeObject((ASN1Encodable)obj);
- }
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/asn1/DLTaggedObject.java b/core/src/main/java/org/bouncycastle/asn1/DLTaggedObject.java
deleted file mode 100644
index 4a245dff..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DLTaggedObject.java
+++ /dev/null
@@ -1,112 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * Definite Length TaggedObject - in ASN.1 notation this is any object preceded by
- * a [n] where n is some number - these are assumed to follow the construction
- * rules (as with sequences).
- */
-public class DLTaggedObject
- extends ASN1TaggedObject
-{
- private static final byte[] ZERO_BYTES = new byte[0];
-
- /**
- * @param explicit true if an explicitly tagged object.
- * @param tagNo the tag number for this object.
- * @param obj the tagged object.
- */
- public DLTaggedObject(
- boolean explicit,
- int tagNo,
- ASN1Encodable obj)
- {
- super(explicit, tagNo, obj);
- }
-
- boolean isConstructed()
- {
- if (!empty)
- {
- if (explicit)
- {
- return true;
- }
- else
- {
- ASN1Primitive primitive = obj.toASN1Primitive().toDLObject();
-
- return primitive.isConstructed();
- }
- }
- else
- {
- return true;
- }
- }
-
- int encodedLength()
- throws IOException
- {
- if (!empty)
- {
- int length = obj.toASN1Primitive().toDLObject().encodedLength();
-
- if (explicit)
- {
- return StreamUtil.calculateTagLength(tagNo) + StreamUtil.calculateBodyLength(length) + length;
- }
- else
- {
- // header length already in calculation
- length = length - 1;
-
- return StreamUtil.calculateTagLength(tagNo) + length;
- }
- }
- else
- {
- return StreamUtil.calculateTagLength(tagNo) + 1;
- }
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- if (!empty)
- {
- ASN1Primitive primitive = obj.toASN1Primitive().toDLObject();
-
- if (explicit)
- {
- out.writeTag(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo);
- out.writeLength(primitive.encodedLength());
- out.writeObject(primitive);
- }
- else
- {
- //
- // need to mark constructed types...
- //
- int flags;
- if (primitive.isConstructed())
- {
- flags = BERTags.CONSTRUCTED | BERTags.TAGGED;
- }
- else
- {
- flags = BERTags.TAGGED;
- }
-
- out.writeTag(flags, tagNo);
- out.writeImplicitObject(primitive);
- }
- }
- else
- {
- out.writeEncoded(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo, ZERO_BYTES);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/DefiniteLengthInputStream.java b/core/src/main/java/org/bouncycastle/asn1/DefiniteLengthInputStream.java
deleted file mode 100644
index 37851748..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/DefiniteLengthInputStream.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.bouncycastle.util.io.Streams;
-
-class DefiniteLengthInputStream
- extends LimitedInputStream
-{
- private static final byte[] EMPTY_BYTES = new byte[0];
-
- private final int _originalLength;
- private int _remaining;
-
- DefiniteLengthInputStream(
- InputStream in,
- int length)
- {
- super(in, length);
-
- if (length < 0)
- {
- throw new IllegalArgumentException("negative lengths not allowed");
- }
-
- this._originalLength = length;
- this._remaining = length;
-
- if (length == 0)
- {
- setParentEofDetect(true);
- }
- }
-
- int getRemaining()
- {
- return _remaining;
- }
-
- public int read()
- throws IOException
- {
- if (_remaining == 0)
- {
- return -1;
- }
-
- int b = _in.read();
-
- if (b < 0)
- {
- throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
- }
-
- if (--_remaining == 0)
- {
- setParentEofDetect(true);
- }
-
- return b;
- }
-
- public int read(byte[] buf, int off, int len)
- throws IOException
- {
- if (_remaining == 0)
- {
- return -1;
- }
-
- int toRead = Math.min(len, _remaining);
- int numRead = _in.read(buf, off, toRead);
-
- if (numRead < 0)
- {
- throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
- }
-
- if ((_remaining -= numRead) == 0)
- {
- setParentEofDetect(true);
- }
-
- return numRead;
- }
-
- byte[] toByteArray()
- throws IOException
- {
- if (_remaining == 0)
- {
- return EMPTY_BYTES;
- }
-
- byte[] bytes = new byte[_remaining];
- if ((_remaining -= Streams.readFully(_in, bytes)) != 0)
- {
- throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
- }
- setParentEofDetect(true);
- return bytes;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/InMemoryRepresentable.java b/core/src/main/java/org/bouncycastle/asn1/InMemoryRepresentable.java
deleted file mode 100644
index 9374ab76..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/InMemoryRepresentable.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * Interface implemented by objects that can be converted from streaming to in-memory objects.
- */
-public interface InMemoryRepresentable
-{
- /**
- * Get the in-memory representation of the ASN.1 object.
- * @throws IOException for bad input data.
- */
- ASN1Primitive getLoadedObject()
- throws IOException;
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/IndefiniteLengthInputStream.java b/core/src/main/java/org/bouncycastle/asn1/IndefiniteLengthInputStream.java
deleted file mode 100644
index 353da3b0..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/IndefiniteLengthInputStream.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.InputStream;
-
-class IndefiniteLengthInputStream
- extends LimitedInputStream
-{
- private int _b1;
- private int _b2;
- private boolean _eofReached = false;
- private boolean _eofOn00 = true;
-
- IndefiniteLengthInputStream(
- InputStream in,
- int limit)
- throws IOException
- {
- super(in, limit);
-
- _b1 = in.read();
- _b2 = in.read();
-
- if (_b2 < 0)
- {
- // Corrupted stream
- throw new EOFException();
- }
-
- checkForEof();
- }
-
- void setEofOn00(
- boolean eofOn00)
- {
- _eofOn00 = eofOn00;
- checkForEof();
- }
-
- private boolean checkForEof()
- {
- if (!_eofReached && _eofOn00 && (_b1 == 0x00 && _b2 == 0x00))
- {
- _eofReached = true;
- setParentEofDetect(true);
- }
- return _eofReached;
- }
-
- public int read(byte[] b, int off, int len)
- throws IOException
- {
- // Only use this optimisation if we aren't checking for 00
- if (_eofOn00 || len < 3)
- {
- return super.read(b, off, len);
- }
-
- if (_eofReached)
- {
- return -1;
- }
-
- int numRead = _in.read(b, off + 2, len - 2);
-
- if (numRead < 0)
- {
- // Corrupted stream
- throw new EOFException();
- }
-
- b[off] = (byte)_b1;
- b[off + 1] = (byte)_b2;
-
- _b1 = _in.read();
- _b2 = _in.read();
-
- if (_b2 < 0)
- {
- // Corrupted stream
- throw new EOFException();
- }
-
- return numRead + 2;
- }
-
- public int read()
- throws IOException
- {
- if (checkForEof())
- {
- return -1;
- }
-
- int b = _in.read();
-
- if (b < 0)
- {
- // Corrupted stream
- throw new EOFException();
- }
-
- int v = _b1;
-
- _b1 = _b2;
- _b2 = b;
-
- return v;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/LazyConstructionEnumeration.java b/core/src/main/java/org/bouncycastle/asn1/LazyConstructionEnumeration.java
deleted file mode 100644
index 31d988d4..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/LazyConstructionEnumeration.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.util.Enumeration;
-
-class LazyConstructionEnumeration
- implements Enumeration
-{
- private ASN1InputStream aIn;
- private Object nextObj;
-
- public LazyConstructionEnumeration(byte[] encoded)
- {
- aIn = new ASN1InputStream(encoded, true);
- nextObj = readObject();
- }
-
- public boolean hasMoreElements()
- {
- return nextObj != null;
- }
-
- public Object nextElement()
- {
- Object o = nextObj;
-
- nextObj = readObject();
-
- return o;
- }
-
- private Object readObject()
- {
- try
- {
- return aIn.readObject();
- }
- catch (IOException e)
- {
- throw new ASN1ParsingException("malformed DER construction: " + e, e);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/LazyEncodedSequence.java b/core/src/main/java/org/bouncycastle/asn1/LazyEncodedSequence.java
deleted file mode 100644
index c7342adf..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/LazyEncodedSequence.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.util.Enumeration;
-
-/**
- * Note: this class is for processing DER/DL encoded sequences only.
- */
-class LazyEncodedSequence
- extends ASN1Sequence
-{
- private byte[] encoded;
-
- LazyEncodedSequence(
- byte[] encoded)
- throws IOException
- {
- this.encoded = encoded;
- }
-
- private void parse()
- {
- Enumeration en = new LazyConstructionEnumeration(encoded);
-
- while (en.hasMoreElements())
- {
- seq.addElement(en.nextElement());
- }
-
- encoded = null;
- }
-
- public synchronized ASN1Encodable getObjectAt(int index)
- {
- if (encoded != null)
- {
- parse();
- }
-
- return super.getObjectAt(index);
- }
-
- public synchronized Enumeration getObjects()
- {
- if (encoded == null)
- {
- return super.getObjects();
- }
-
- return new LazyConstructionEnumeration(encoded);
- }
-
- public synchronized int size()
- {
- if (encoded != null)
- {
- parse();
- }
-
- return super.size();
- }
-
- ASN1Primitive toDERObject()
- {
- if (encoded != null)
- {
- parse();
- }
-
- return super.toDERObject();
- }
-
- ASN1Primitive toDLObject()
- {
- if (encoded != null)
- {
- parse();
- }
-
- return super.toDLObject();
- }
-
- int encodedLength()
- throws IOException
- {
- if (encoded != null)
- {
- return 1 + StreamUtil.calculateBodyLength(encoded.length) + encoded.length;
- }
- else
- {
- return super.toDLObject().encodedLength();
- }
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- if (encoded != null)
- {
- out.writeEncoded(BERTags.SEQUENCE | BERTags.CONSTRUCTED, encoded);
- }
- else
- {
- super.toDLObject().encode(out);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/LimitedInputStream.java b/core/src/main/java/org/bouncycastle/asn1/LimitedInputStream.java
deleted file mode 100644
index d94b0bd8..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/LimitedInputStream.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.InputStream;
-
-abstract class LimitedInputStream
- extends InputStream
-{
- protected final InputStream _in;
- private int _limit;
-
- LimitedInputStream(
- InputStream in,
- int limit)
- {
- this._in = in;
- this._limit = limit;
- }
-
- int getRemaining()
- {
- // TODO: maybe one day this can become more accurate
- return _limit;
- }
-
- protected void setParentEofDetect(boolean on)
- {
- if (_in instanceof IndefiniteLengthInputStream)
- {
- ((IndefiniteLengthInputStream)_in).setEofOn00(on);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/OIDTokenizer.java b/core/src/main/java/org/bouncycastle/asn1/OIDTokenizer.java
deleted file mode 100644
index 54679447..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/OIDTokenizer.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.bouncycastle.asn1;
-
-/**
- * class for breaking up an OID into it's component tokens, ala
- * java.util.StringTokenizer. We need this class as some of the
- * lightweight Java environment don't support classes like
- * StringTokenizer.
- */
-public class OIDTokenizer
-{
- private String oid;
- private int index;
-
- public OIDTokenizer(
- String oid)
- {
- this.oid = oid;
- this.index = 0;
- }
-
- public boolean hasMoreTokens()
- {
- return (index != -1);
- }
-
- public String nextToken()
- {
- if (index == -1)
- {
- return null;
- }
-
- String token;
- int end = oid.indexOf('.', index);
-
- if (end == -1)
- {
- token = oid.substring(index);
- index = -1;
- return token;
- }
-
- token = oid.substring(index, end);
-
- index = end + 1;
- return token;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/StreamUtil.java b/core/src/main/java/org/bouncycastle/asn1/StreamUtil.java
deleted file mode 100644
index b6cb0706..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/StreamUtil.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayInputStream;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.channels.FileChannel;
-
-class StreamUtil
-{
- private static final long MAX_MEMORY = Runtime.getRuntime().maxMemory();
-
- /**
- * Find out possible longest length...
- *
- * @param in input stream of interest
- * @return length calculation or MAX_VALUE.
- */
- static int findLimit(InputStream in)
- {
- if (in instanceof LimitedInputStream)
- {
- return ((LimitedInputStream)in).getRemaining();
- }
- else if (in instanceof ASN1InputStream)
- {
- return ((ASN1InputStream)in).getLimit();
- }
- else if (in instanceof ByteArrayInputStream)
- {
- return ((ByteArrayInputStream)in).available();
- }
- else if (in instanceof FileInputStream)
- {
- try
- {
- FileChannel channel = ((FileInputStream)in).getChannel();
- long size = (channel != null) ? channel.size() : Integer.MAX_VALUE;
-
- if (size < Integer.MAX_VALUE)
- {
- return (int)size;
- }
- }
- catch (IOException e)
- {
- // ignore - they'll find out soon enough!
- }
- }
-
- if (MAX_MEMORY > Integer.MAX_VALUE)
- {
- return Integer.MAX_VALUE;
- }
-
- return (int)MAX_MEMORY;
- }
-
- static int calculateBodyLength(
- int length)
- {
- int count = 1;
-
- if (length > 127)
- {
- int size = 1;
- int val = length;
-
- while ((val >>>= 8) != 0)
- {
- size++;
- }
-
- for (int i = (size - 1) * 8; i >= 0; i -= 8)
- {
- count++;
- }
- }
-
- return count;
- }
-
- static int calculateTagLength(int tagNo)
- throws IOException
- {
- int length = 1;
-
- if (tagNo >= 31)
- {
- if (tagNo < 128)
- {
- length++;
- }
- else
- {
- byte[] stack = new byte[5];
- int pos = stack.length;
-
- stack[--pos] = (byte)(tagNo & 0x7F);
-
- do
- {
- tagNo >>= 7;
- stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
- }
- while (tagNo > 127);
-
- length += stack.length - pos;
- }
- }
-
- return length;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java
deleted file mode 100644
index 16a67682..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java
+++ /dev/null
@@ -1,71 +0,0 @@
-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 = bc.branch("1");
-
- /**
- * SHA-1(1)
- * <p>
- * 1.3.6.1.4.1.22554.1.1
- */
- public static final ASN1ObjectIdentifier bc_pbe_sha1 = bc_pbe.branch("1");
-
- /** 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)
- */
- /** 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");
-
- /** 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))
- */
- /** 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");
-
- /** 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/core/src/main/java/org/bouncycastle/asn1/bsi/BSIObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/bsi/BSIObjectIdentifiers.java
deleted file mode 100644
index 315f6c48..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/bsi/BSIObjectIdentifiers.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.bouncycastle.asn1.bsi;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-
-/**
- * See https://www.bsi.bund.de/cae/servlet/contentblob/471398/publicationFile/30615/BSI-TR-03111_pdf.pdf
- */
-public interface BSIObjectIdentifiers
-{
- static final ASN1ObjectIdentifier bsi_de = new ASN1ObjectIdentifier("0.4.0.127.0.7");
-
- /* 0.4.0.127.0.7.1.1 */
- static final ASN1ObjectIdentifier id_ecc = bsi_de.branch("1.1");
-
- /* 0.4.0.127.0.7.1.1.4.1 */
- static final ASN1ObjectIdentifier ecdsa_plain_signatures = id_ecc.branch("4.1");
-
- /* 0.4.0.127.0.7.1.1.4.1.1 */
- static final ASN1ObjectIdentifier ecdsa_plain_SHA1 = ecdsa_plain_signatures.branch("1");
-
- /* 0.4.0.127.0.7.1.1.4.1.2 */
- static final ASN1ObjectIdentifier ecdsa_plain_SHA224 = ecdsa_plain_signatures.branch("2");
-
- /* 0.4.0.127.0.7.1.1.4.1.3 */
- static final ASN1ObjectIdentifier ecdsa_plain_SHA256 = ecdsa_plain_signatures.branch("3");
-
- /* 0.4.0.127.0.7.1.1.4.1.4 */
- static final ASN1ObjectIdentifier ecdsa_plain_SHA384 = ecdsa_plain_signatures.branch("4");
-
- /* 0.4.0.127.0.7.1.1.4.1.5 */
- static final ASN1ObjectIdentifier ecdsa_plain_SHA512 = ecdsa_plain_signatures.branch("5");
-
- /* 0.4.0.127.0.7.1.1.4.1.6 */
- static final ASN1ObjectIdentifier ecdsa_plain_RIPEMD160 = ecdsa_plain_signatures.branch("6");
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/CAKeyUpdAnnContent.java b/core/src/main/java/org/bouncycastle/asn1/cmp/CAKeyUpdAnnContent.java
deleted file mode 100644
index 41ebd512..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/CAKeyUpdAnnContent.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-public class CAKeyUpdAnnContent
- extends ASN1Object
-{
- private CMPCertificate oldWithNew;
- private CMPCertificate newWithOld;
- private CMPCertificate newWithNew;
-
- private CAKeyUpdAnnContent(ASN1Sequence seq)
- {
- oldWithNew = CMPCertificate.getInstance(seq.getObjectAt(0));
- newWithOld = CMPCertificate.getInstance(seq.getObjectAt(1));
- newWithNew = CMPCertificate.getInstance(seq.getObjectAt(2));
- }
-
- public static CAKeyUpdAnnContent getInstance(Object o)
- {
- if (o instanceof CAKeyUpdAnnContent)
- {
- return (CAKeyUpdAnnContent)o;
- }
-
- if (o != null)
- {
- return new CAKeyUpdAnnContent(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public CAKeyUpdAnnContent(CMPCertificate oldWithNew, CMPCertificate newWithOld, CMPCertificate newWithNew)
- {
- this.oldWithNew = oldWithNew;
- this.newWithOld = newWithOld;
- this.newWithNew = newWithNew;
- }
-
- public CMPCertificate getOldWithNew()
- {
- return oldWithNew;
- }
-
- public CMPCertificate getNewWithOld()
- {
- return newWithOld;
- }
-
- public CMPCertificate getNewWithNew()
- {
- return newWithNew;
- }
-
- /**
- * <pre>
- * CAKeyUpdAnnContent ::= SEQUENCE {
- * oldWithNew CMPCertificate, -- old pub signed with new priv
- * newWithOld CMPCertificate, -- new pub signed with old priv
- * newWithNew CMPCertificate -- new pub signed with new priv
- * }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(oldWithNew);
- v.add(newWithOld);
- v.add(newWithNew);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/CMPCertificate.java b/core/src/main/java/org/bouncycastle/asn1/cmp/CMPCertificate.java
deleted file mode 100644
index 243aacb9..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/CMPCertificate.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.AttributeCertificate;
-import org.bouncycastle.asn1.x509.Certificate;
-
-public class CMPCertificate
- extends ASN1Object
- implements ASN1Choice
-{
- private Certificate x509v3PKCert;
- private AttributeCertificate x509v2AttrCert;
-
- /**
- * Note: the addition of attribute certificates is a BC extension.
- */
- public CMPCertificate(AttributeCertificate x509v2AttrCert)
- {
- this.x509v2AttrCert = x509v2AttrCert;
- }
-
- public CMPCertificate(Certificate x509v3PKCert)
- {
- if (x509v3PKCert.getVersionNumber() != 3)
- {
- throw new IllegalArgumentException("only version 3 certificates allowed");
- }
-
- this.x509v3PKCert = x509v3PKCert;
- }
-
- public static CMPCertificate getInstance(Object o)
- {
- if (o == null || o instanceof CMPCertificate)
- {
- return (CMPCertificate)o;
- }
-
- if (o instanceof ASN1Sequence || o instanceof byte[])
- {
- return new CMPCertificate(Certificate.getInstance(o));
- }
-
- if (o instanceof ASN1TaggedObject)
- {
- return new CMPCertificate(AttributeCertificate.getInstance(((ASN1TaggedObject)o).getObject()));
- }
-
- throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
- }
-
- public boolean isX509v3PKCert()
- {
- return x509v3PKCert != null;
- }
-
- public Certificate getX509v3PKCert()
- {
- return x509v3PKCert;
- }
-
- public AttributeCertificate getX509v2AttrCert()
- {
- return x509v2AttrCert;
- }
-
- /**
- * <pre>
- * CMPCertificate ::= CHOICE {
- * x509v3PKCert Certificate
- * x509v2AttrCert [1] AttributeCertificate
- * }
- * </pre>
- * Note: the addition of attribute certificates is a BC extension.
- *
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- if (x509v2AttrCert != null)
- { // explicit following CMP conventions
- return new DERTaggedObject(true, 1, x509v2AttrCert);
- }
-
- return x509v3PKCert.toASN1Primitive();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/CMPObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/cmp/CMPObjectIdentifiers.java
deleted file mode 100644
index 51aba658..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/CMPObjectIdentifiers.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-
-public interface CMPObjectIdentifiers
-{
- // RFC 4210
-
- /** 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} */
- static final ASN1ObjectIdentifier dhBasedMac = new ASN1ObjectIdentifier("1.2.840.113533.7.66.30");
-
- // Example InfoTypeAndValue contents include, but are not limited
- // to, the following (un-comment in this ASN.1 module and use as
- // appropriate for a given environment):
- //
- // id-it-caProtEncCert OBJECT IDENTIFIER ::= {id-it 1}
- // CAProtEncCertValue ::= CMPCertificate
- // id-it-signKeyPairTypes OBJECT IDENTIFIER ::= {id-it 2}
- // SignKeyPairTypesValue ::= SEQUENCE OF AlgorithmIdentifier
- // id-it-encKeyPairTypes OBJECT IDENTIFIER ::= {id-it 3}
- // EncKeyPairTypesValue ::= SEQUENCE OF AlgorithmIdentifier
- // id-it-preferredSymmAlg OBJECT IDENTIFIER ::= {id-it 4}
- // PreferredSymmAlgValue ::= AlgorithmIdentifier
- // id-it-caKeyUpdateInfo OBJECT IDENTIFIER ::= {id-it 5}
- // CAKeyUpdateInfoValue ::= CAKeyUpdAnnContent
- // id-it-currentCRL OBJECT IDENTIFIER ::= {id-it 6}
- // CurrentCRLValue ::= CertificateList
- // id-it-unsupportedOIDs OBJECT IDENTIFIER ::= {id-it 7}
- // UnsupportedOIDsValue ::= SEQUENCE OF OBJECT IDENTIFIER
- // id-it-keyPairParamReq OBJECT IDENTIFIER ::= {id-it 10}
- // KeyPairParamReqValue ::= OBJECT IDENTIFIER
- // id-it-keyPairParamRep OBJECT IDENTIFIER ::= {id-it 11}
- // KeyPairParamRepValue ::= AlgorithmIdentifer
- // id-it-revPassphrase OBJECT IDENTIFIER ::= {id-it 12}
- // RevPassphraseValue ::= EncryptedValue
- // id-it-implicitConfirm OBJECT IDENTIFIER ::= {id-it 13}
- // ImplicitConfirmValue ::= NULL
- // id-it-confirmWaitTime OBJECT IDENTIFIER ::= {id-it 14}
- // ConfirmWaitTimeValue ::= GeneralizedTime
- // id-it-origPKIMessage OBJECT IDENTIFIER ::= {id-it 15}
- // OrigPKIMessageValue ::= PKIMessages
- // id-it-suppLangTags OBJECT IDENTIFIER ::= {id-it 16}
- // SuppLangTagsValue ::= SEQUENCE OF UTF8String
- //
- // where
- //
- // id-pkix OBJECT IDENTIFIER ::= {
- // iso(1) identified-organization(3)
- // 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
-
- // id-pkix OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
- // dod(6) internet(1) security(5) mechanisms(5) pkix(7) }
- //
- // arc for Internet X.509 PKI protocols and their components
- // id-pkip OBJECT IDENTIFIER :: { id-pkix pkip(5) }
- //
- // arc for Registration Controls in CRMF
- // id-regCtrl OBJECT IDENTIFIER ::= { id-pkip regCtrl(1) }
- //
- // 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}; 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");
-
- /**
- * 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/core/src/main/java/org/bouncycastle/asn1/cmp/CRLAnnContent.java b/core/src/main/java/org/bouncycastle/asn1/cmp/CRLAnnContent.java
deleted file mode 100644
index 10948ae7..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/CRLAnnContent.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.CertificateList;
-
-public class CRLAnnContent
- extends ASN1Object
-{
- private ASN1Sequence content;
-
- private CRLAnnContent(ASN1Sequence seq)
- {
- content = seq;
- }
-
- public static CRLAnnContent getInstance(Object o)
- {
- if (o instanceof CRLAnnContent)
- {
- return (CRLAnnContent)o;
- }
-
- if (o != null)
- {
- return new CRLAnnContent(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public CRLAnnContent(CertificateList crl)
- {
- this.content = new DERSequence(crl);
- }
-
- public CertificateList[] getCertificateLists()
- {
- CertificateList[] result = new CertificateList[content.size()];
-
- for (int i = 0; i != result.length; i++)
- {
- result[i] = CertificateList.getInstance(content.getObjectAt(i));
- }
-
- return result;
- }
-
- /**
- * <pre>
- * CRLAnnContent ::= SEQUENCE OF CertificateList
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- return content;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/CertConfirmContent.java b/core/src/main/java/org/bouncycastle/asn1/cmp/CertConfirmContent.java
deleted file mode 100644
index e4d786f1..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/CertConfirmContent.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-
-public class CertConfirmContent
- extends ASN1Object
-{
- private ASN1Sequence content;
-
- private CertConfirmContent(ASN1Sequence seq)
- {
- content = seq;
- }
-
- public static CertConfirmContent getInstance(Object o)
- {
- if (o instanceof CertConfirmContent)
- {
- return (CertConfirmContent)o;
- }
-
- if (o != null)
- {
- return new CertConfirmContent(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public CertStatus[] toCertStatusArray()
- {
- CertStatus[] result = new CertStatus[content.size()];
-
- for (int i = 0; i != result.length; i++)
- {
- result[i] = CertStatus.getInstance(content.getObjectAt(i));
- }
-
- return result;
- }
-
- /**
- * <pre>
- * CertConfirmContent ::= SEQUENCE OF CertStatus
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- return content;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/CertOrEncCert.java b/core/src/main/java/org/bouncycastle/asn1/cmp/CertOrEncCert.java
deleted file mode 100644
index b94a79c3..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/CertOrEncCert.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.crmf.EncryptedValue;
-
-public class CertOrEncCert
- extends ASN1Object
- implements ASN1Choice
-{
- private CMPCertificate certificate;
- private EncryptedValue encryptedCert;
-
- private CertOrEncCert(ASN1TaggedObject tagged)
- {
- if (tagged.getTagNo() == 0)
- {
- certificate = CMPCertificate.getInstance(tagged.getObject());
- }
- else if (tagged.getTagNo() == 1)
- {
- encryptedCert = EncryptedValue.getInstance(tagged.getObject());
- }
- else
- {
- throw new IllegalArgumentException("unknown tag: " + tagged.getTagNo());
- }
- }
-
- public static CertOrEncCert getInstance(Object o)
- {
- if (o instanceof CertOrEncCert)
- {
- return (CertOrEncCert)o;
- }
-
- if (o instanceof ASN1TaggedObject)
- {
- return new CertOrEncCert((ASN1TaggedObject)o);
- }
-
- return null;
- }
-
- public CertOrEncCert(CMPCertificate certificate)
- {
- if (certificate == null)
- {
- throw new IllegalArgumentException("'certificate' cannot be null");
- }
-
- this.certificate = certificate;
- }
-
- public CertOrEncCert(EncryptedValue encryptedCert)
- {
- if (encryptedCert == null)
- {
- throw new IllegalArgumentException("'encryptedCert' cannot be null");
- }
-
- this.encryptedCert = encryptedCert;
- }
-
- public CMPCertificate getCertificate()
- {
- return certificate;
- }
-
- public EncryptedValue getEncryptedCert()
- {
- return encryptedCert;
- }
-
- /**
- * <pre>
- * CertOrEncCert ::= CHOICE {
- * certificate [0] CMPCertificate,
- * encryptedCert [1] EncryptedValue
- * }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- if (certificate != null)
- {
- return new DERTaggedObject(true, 0, certificate);
- }
-
- return new DERTaggedObject(true, 1, encryptedCert);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/CertRepMessage.java b/core/src/main/java/org/bouncycastle/asn1/cmp/CertRepMessage.java
deleted file mode 100644
index 6180796c..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/CertRepMessage.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-public class CertRepMessage
- extends ASN1Object
-{
- private ASN1Sequence caPubs;
- private ASN1Sequence response;
-
- private CertRepMessage(ASN1Sequence seq)
- {
- int index = 0;
-
- if (seq.size() > 1)
- {
- caPubs = ASN1Sequence.getInstance((ASN1TaggedObject)seq.getObjectAt(index++), true);
- }
-
- response = ASN1Sequence.getInstance(seq.getObjectAt(index));
- }
-
- public static CertRepMessage getInstance(Object o)
- {
- if (o instanceof CertRepMessage)
- {
- return (CertRepMessage)o;
- }
-
- if (o != null)
- {
- return new CertRepMessage(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public CertRepMessage(CMPCertificate[] caPubs, CertResponse[] response)
- {
- if (response == null)
- {
- throw new IllegalArgumentException("'response' cannot be null");
- }
-
- if (caPubs != null)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- for (int i = 0; i < caPubs.length; i++)
- {
- v.add(caPubs[i]);
- }
- this.caPubs = new DERSequence(v);
- }
-
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- for (int i = 0; i < response.length; i++)
- {
- v.add(response[i]);
- }
- this.response = new DERSequence(v);
- }
- }
-
- public CMPCertificate[] getCaPubs()
- {
- if (caPubs == null)
- {
- return null;
- }
-
- CMPCertificate[] results = new CMPCertificate[caPubs.size()];
-
- for (int i = 0; i != results.length; i++)
- {
- results[i] = CMPCertificate.getInstance(caPubs.getObjectAt(i));
- }
-
- return results;
- }
-
- public CertResponse[] getResponse()
- {
- CertResponse[] results = new CertResponse[response.size()];
-
- for (int i = 0; i != results.length; i++)
- {
- results[i] = CertResponse.getInstance(response.getObjectAt(i));
- }
-
- return results;
- }
-
- /**
- * <pre>
- * CertRepMessage ::= SEQUENCE {
- * caPubs [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
- * OPTIONAL,
- * response SEQUENCE OF CertResponse
- * }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (caPubs != null)
- {
- v.add(new DERTaggedObject(true, 1, caPubs));
- }
-
- v.add(response);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/CertResponse.java b/core/src/main/java/org/bouncycastle/asn1/cmp/CertResponse.java
deleted file mode 100644
index 794e7bd8..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/CertResponse.java
+++ /dev/null
@@ -1,139 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-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.DERSequence;
-
-public class CertResponse
- extends ASN1Object
-{
- private ASN1Integer certReqId;
- private PKIStatusInfo status;
- private CertifiedKeyPair certifiedKeyPair;
- private ASN1OctetString rspInfo;
-
- private CertResponse(ASN1Sequence seq)
- {
- certReqId = ASN1Integer.getInstance(seq.getObjectAt(0));
- status = PKIStatusInfo.getInstance(seq.getObjectAt(1));
-
- if (seq.size() >= 3)
- {
- if (seq.size() == 3)
- {
- ASN1Encodable o = seq.getObjectAt(2);
- if (o instanceof ASN1OctetString)
- {
- rspInfo = ASN1OctetString.getInstance(o);
- }
- else
- {
- certifiedKeyPair = CertifiedKeyPair.getInstance(o);
- }
- }
- else
- {
- certifiedKeyPair = CertifiedKeyPair.getInstance(seq.getObjectAt(2));
- rspInfo = ASN1OctetString.getInstance(seq.getObjectAt(3));
- }
- }
- }
-
- public static CertResponse getInstance(Object o)
- {
- if (o instanceof CertResponse)
- {
- return (CertResponse)o;
- }
-
- if (o != null)
- {
- return new CertResponse(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public CertResponse(
- ASN1Integer certReqId,
- PKIStatusInfo status)
- {
- this(certReqId, status, null, null);
- }
-
- public CertResponse(
- ASN1Integer certReqId,
- PKIStatusInfo status,
- CertifiedKeyPair certifiedKeyPair,
- ASN1OctetString rspInfo)
- {
- if (certReqId == null)
- {
- throw new IllegalArgumentException("'certReqId' cannot be null");
- }
- if (status == null)
- {
- throw new IllegalArgumentException("'status' cannot be null");
- }
- this.certReqId = certReqId;
- this.status = status;
- this.certifiedKeyPair = certifiedKeyPair;
- this.rspInfo = rspInfo;
- }
-
- public ASN1Integer getCertReqId()
- {
- return certReqId;
- }
-
- public PKIStatusInfo getStatus()
- {
- return status;
- }
-
- public CertifiedKeyPair getCertifiedKeyPair()
- {
- return certifiedKeyPair;
- }
-
- /**
- * <pre>
- * CertResponse ::= SEQUENCE {
- * certReqId INTEGER,
- * -- to match this response with corresponding request (a value
- * -- of -1 is to be used if certReqId is not specified in the
- * -- corresponding request)
- * status PKIStatusInfo,
- * certifiedKeyPair CertifiedKeyPair OPTIONAL,
- * rspInfo OCTET STRING OPTIONAL
- * -- analogous to the id-regInfo-utf8Pairs string defined
- * -- for regInfo in CertReqMsg [CRMF]
- * }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(certReqId);
- v.add(status);
-
- if (certifiedKeyPair != null)
- {
- v.add(certifiedKeyPair);
- }
-
- if (rspInfo != null)
- {
- v.add(rspInfo);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/CertStatus.java b/core/src/main/java/org/bouncycastle/asn1/cmp/CertStatus.java
deleted file mode 100644
index c92b2a24..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/CertStatus.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import java.math.BigInteger;
-
-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;
-
-public class CertStatus
- extends ASN1Object
-{
- private ASN1OctetString certHash;
- private ASN1Integer certReqId;
- private PKIStatusInfo statusInfo;
-
- private CertStatus(ASN1Sequence seq)
- {
- certHash = ASN1OctetString.getInstance(seq.getObjectAt(0));
- certReqId = ASN1Integer.getInstance(seq.getObjectAt(1));
-
- if (seq.size() > 2)
- {
- statusInfo = PKIStatusInfo.getInstance(seq.getObjectAt(2));
- }
- }
-
- public CertStatus(byte[] certHash, BigInteger certReqId)
- {
- this.certHash = new DEROctetString(certHash);
- this.certReqId = new ASN1Integer(certReqId);
- }
-
- public CertStatus(byte[] certHash, BigInteger certReqId, PKIStatusInfo statusInfo)
- {
- this.certHash = new DEROctetString(certHash);
- this.certReqId = new ASN1Integer(certReqId);
- this.statusInfo = statusInfo;
- }
-
- public static CertStatus getInstance(Object o)
- {
- if (o instanceof CertStatus)
- {
- return (CertStatus)o;
- }
-
- if (o != null)
- {
- return new CertStatus(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public ASN1OctetString getCertHash()
- {
- return certHash;
- }
-
- public ASN1Integer getCertReqId()
- {
- return certReqId;
- }
-
- public PKIStatusInfo getStatusInfo()
- {
- return statusInfo;
- }
-
- /**
- * <pre>
- * CertStatus ::= SEQUENCE {
- * certHash OCTET STRING,
- * -- the hash of the certificate, using the same hash algorithm
- * -- as is used to create and verify the certificate signature
- * certReqId INTEGER,
- * -- to match this confirmation with the corresponding req/rep
- * statusInfo PKIStatusInfo OPTIONAL
- * }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(certHash);
- v.add(certReqId);
-
- if (statusInfo != null)
- {
- v.add(statusInfo);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/CertifiedKeyPair.java b/core/src/main/java/org/bouncycastle/asn1/cmp/CertifiedKeyPair.java
deleted file mode 100644
index 949ad730..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/CertifiedKeyPair.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.crmf.EncryptedValue;
-import org.bouncycastle.asn1.crmf.PKIPublicationInfo;
-
-public class CertifiedKeyPair
- extends ASN1Object
-{
- private CertOrEncCert certOrEncCert;
- private EncryptedValue privateKey;
- private PKIPublicationInfo publicationInfo;
-
- private CertifiedKeyPair(ASN1Sequence seq)
- {
- certOrEncCert = CertOrEncCert.getInstance(seq.getObjectAt(0));
-
- if (seq.size() >= 2)
- {
- if (seq.size() == 2)
- {
- ASN1TaggedObject tagged = ASN1TaggedObject.getInstance(seq.getObjectAt(1));
- if (tagged.getTagNo() == 0)
- {
- privateKey = EncryptedValue.getInstance(tagged.getObject());
- }
- else
- {
- publicationInfo = PKIPublicationInfo.getInstance(tagged.getObject());
- }
- }
- else
- {
- privateKey = EncryptedValue.getInstance(ASN1TaggedObject.getInstance(seq.getObjectAt(1)));
- publicationInfo = PKIPublicationInfo.getInstance(ASN1TaggedObject.getInstance(seq.getObjectAt(2)));
- }
- }
- }
-
- public static CertifiedKeyPair getInstance(Object o)
- {
- if (o instanceof CertifiedKeyPair)
- {
- return (CertifiedKeyPair)o;
- }
-
- if (o != null)
- {
- return new CertifiedKeyPair(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public CertifiedKeyPair(
- CertOrEncCert certOrEncCert)
- {
- this(certOrEncCert, null, null);
- }
-
- public CertifiedKeyPair(
- CertOrEncCert certOrEncCert,
- EncryptedValue privateKey,
- PKIPublicationInfo publicationInfo
- )
- {
- if (certOrEncCert == null)
- {
- throw new IllegalArgumentException("'certOrEncCert' cannot be null");
- }
-
- this.certOrEncCert = certOrEncCert;
- this.privateKey = privateKey;
- this.publicationInfo = publicationInfo;
- }
-
- public CertOrEncCert getCertOrEncCert()
- {
- return certOrEncCert;
- }
-
- public EncryptedValue getPrivateKey()
- {
- return privateKey;
- }
-
- public PKIPublicationInfo getPublicationInfo()
- {
- return publicationInfo;
- }
-
- /**
- * <pre>
- * CertifiedKeyPair ::= SEQUENCE {
- * certOrEncCert CertOrEncCert,
- * privateKey [0] EncryptedValue OPTIONAL,
- * -- see [CRMF] for comment on encoding
- * publicationInfo [1] PKIPublicationInfo OPTIONAL
- * }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(certOrEncCert);
-
- if (privateKey != null)
- {
- v.add(new DERTaggedObject(true, 0, privateKey));
- }
-
- if (publicationInfo != null)
- {
- v.add(new DERTaggedObject(true, 1, publicationInfo));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/Challenge.java b/core/src/main/java/org/bouncycastle/asn1/cmp/Challenge.java
deleted file mode 100644
index 60eb1bac..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/Challenge.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-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.asn1.x509.AlgorithmIdentifier;
-
-public class Challenge
- extends ASN1Object
-{
- private AlgorithmIdentifier owf;
- private ASN1OctetString witness;
- private ASN1OctetString challenge;
-
- private Challenge(ASN1Sequence seq)
- {
- int index = 0;
-
- if (seq.size() == 3)
- {
- owf = AlgorithmIdentifier.getInstance(seq.getObjectAt(index++));
- }
-
- witness = ASN1OctetString.getInstance(seq.getObjectAt(index++));
- challenge = ASN1OctetString.getInstance(seq.getObjectAt(index));
- }
-
- public static Challenge getInstance(Object o)
- {
- if (o instanceof Challenge)
- {
- return (Challenge)o;
- }
-
- if (o != null)
- {
- return new Challenge(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public Challenge(byte[] witness, byte[] challenge)
- {
- this(null, witness, challenge);
- }
-
- public Challenge(AlgorithmIdentifier owf, byte[] witness, byte[] challenge)
- {
- this.owf = owf;
- this.witness = new DEROctetString(witness);
- this.challenge = new DEROctetString(challenge);
- }
-
- public AlgorithmIdentifier getOwf()
- {
- return owf;
- }
-
- public byte[] getWitness()
- {
- return witness.getOctets();
- }
-
- public byte[] getChallenge()
- {
- return challenge.getOctets();
- }
-
- /**
- * <pre>
- * Challenge ::= SEQUENCE {
- * owf AlgorithmIdentifier OPTIONAL,
- *
- * -- MUST be present in the first Challenge; MAY be omitted in
- * -- any subsequent Challenge in POPODecKeyChallContent (if
- * -- omitted, then the owf used in the immediately preceding
- * -- Challenge is to be used).
- *
- * witness OCTET STRING,
- * -- the result of applying the one-way function (owf) to a
- * -- randomly-generated INTEGER, A. [Note that a different
- * -- INTEGER MUST be used for each Challenge.]
- * challenge OCTET STRING
- * -- the encryption (under the public key for which the cert.
- * -- request is being made) of Rand, where Rand is specified as
- * -- Rand ::= SEQUENCE {
- * -- int INTEGER,
- * -- - the randomly-generated INTEGER A (above)
- * -- sender GeneralName
- * -- - the sender's name (as included in PKIHeader)
- * -- }
- * }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- addOptional(v, owf);
- v.add(witness);
- v.add(challenge);
-
- return new DERSequence(v);
- }
-
- private void addOptional(ASN1EncodableVector v, ASN1Encodable obj)
- {
- if (obj != null)
- {
- v.add(obj);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/ErrorMsgContent.java b/core/src/main/java/org/bouncycastle/asn1/cmp/ErrorMsgContent.java
deleted file mode 100644
index 5dc1ac38..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/ErrorMsgContent.java
+++ /dev/null
@@ -1,121 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-public class ErrorMsgContent
- extends ASN1Object
-{
- private PKIStatusInfo pkiStatusInfo;
- private ASN1Integer errorCode;
- private PKIFreeText errorDetails;
-
- private ErrorMsgContent(ASN1Sequence seq)
- {
- Enumeration en = seq.getObjects();
-
- pkiStatusInfo = PKIStatusInfo.getInstance(en.nextElement());
-
- while (en.hasMoreElements())
- {
- Object o = en.nextElement();
-
- if (o instanceof ASN1Integer)
- {
- errorCode = ASN1Integer.getInstance(o);
- }
- else
- {
- errorDetails = PKIFreeText.getInstance(o);
- }
- }
- }
-
- public static ErrorMsgContent getInstance(Object o)
- {
- if (o instanceof ErrorMsgContent)
- {
- return (ErrorMsgContent)o;
- }
-
- if (o != null)
- {
- return new ErrorMsgContent(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public ErrorMsgContent(PKIStatusInfo pkiStatusInfo)
- {
- this(pkiStatusInfo, null, null);
- }
-
- public ErrorMsgContent(
- PKIStatusInfo pkiStatusInfo,
- ASN1Integer errorCode,
- PKIFreeText errorDetails)
- {
- if (pkiStatusInfo == null)
- {
- throw new IllegalArgumentException("'pkiStatusInfo' cannot be null");
- }
-
- this.pkiStatusInfo = pkiStatusInfo;
- this.errorCode = errorCode;
- this.errorDetails = errorDetails;
- }
-
- public PKIStatusInfo getPKIStatusInfo()
- {
- return pkiStatusInfo;
- }
-
- public ASN1Integer getErrorCode()
- {
- return errorCode;
- }
-
- public PKIFreeText getErrorDetails()
- {
- return errorDetails;
- }
-
- /**
- * <pre>
- * ErrorMsgContent ::= SEQUENCE {
- * pKIStatusInfo PKIStatusInfo,
- * errorCode INTEGER OPTIONAL,
- * -- implementation-specific error codes
- * errorDetails PKIFreeText OPTIONAL
- * -- implementation-specific error details
- * }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(pkiStatusInfo);
- addOptional(v, errorCode);
- addOptional(v, errorDetails);
-
- return new DERSequence(v);
- }
-
- private void addOptional(ASN1EncodableVector v, ASN1Encodable obj)
- {
- if (obj != null)
- {
- v.add(obj);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/GenMsgContent.java b/core/src/main/java/org/bouncycastle/asn1/cmp/GenMsgContent.java
deleted file mode 100644
index 109d1801..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/GenMsgContent.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-public class GenMsgContent
- extends ASN1Object
-{
- private ASN1Sequence content;
-
- private GenMsgContent(ASN1Sequence seq)
- {
- content = seq;
- }
-
- public static GenMsgContent getInstance(Object o)
- {
- if (o instanceof GenMsgContent)
- {
- return (GenMsgContent)o;
- }
-
- if (o != null)
- {
- return new GenMsgContent(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public GenMsgContent(InfoTypeAndValue itv)
- {
- content = new DERSequence(itv);
- }
-
- public GenMsgContent(InfoTypeAndValue[] itv)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- for (int i = 0; i < itv.length; i++)
- {
- v.add(itv[i]);
- }
- content = new DERSequence(v);
- }
-
- public InfoTypeAndValue[] toInfoTypeAndValueArray()
- {
- InfoTypeAndValue[] result = new InfoTypeAndValue[content.size()];
-
- for (int i = 0; i != result.length; i++)
- {
- result[i] = InfoTypeAndValue.getInstance(content.getObjectAt(i));
- }
-
- return result;
- }
-
- /**
- * <pre>
- * GenMsgContent ::= SEQUENCE OF InfoTypeAndValue
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- return content;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/GenRepContent.java b/core/src/main/java/org/bouncycastle/asn1/cmp/GenRepContent.java
deleted file mode 100644
index aca4d30f..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/GenRepContent.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-public class GenRepContent
- extends ASN1Object
-{
- private ASN1Sequence content;
-
- private GenRepContent(ASN1Sequence seq)
- {
- content = seq;
- }
-
- public static GenRepContent getInstance(Object o)
- {
- if (o instanceof GenRepContent)
- {
- return (GenRepContent)o;
- }
-
- if (o != null)
- {
- return new GenRepContent(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public GenRepContent(InfoTypeAndValue itv)
- {
- content = new DERSequence(itv);
- }
-
- public GenRepContent(InfoTypeAndValue[] itv)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- for (int i = 0; i < itv.length; i++)
- {
- v.add(itv[i]);
- }
- content = new DERSequence(v);
- }
-
- public InfoTypeAndValue[] toInfoTypeAndValueArray()
- {
- InfoTypeAndValue[] result = new InfoTypeAndValue[content.size()];
-
- for (int i = 0; i != result.length; i++)
- {
- result[i] = InfoTypeAndValue.getInstance(content.getObjectAt(i));
- }
-
- return result;
- }
-
- /**
- * <pre>
- * GenRepContent ::= SEQUENCE OF InfoTypeAndValue
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- return content;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/InfoTypeAndValue.java b/core/src/main/java/org/bouncycastle/asn1/cmp/InfoTypeAndValue.java
deleted file mode 100644
index 9405462e..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/InfoTypeAndValue.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * Example InfoTypeAndValue contents include, but are not limited
- * to, the following (un-comment in this ASN.1 module and use as
- * appropriate for a given environment):
- * <pre>
- * id-it-caProtEncCert OBJECT IDENTIFIER ::= {id-it 1}
- * CAProtEncCertValue ::= CMPCertificate
- * id-it-signKeyPairTypes OBJECT IDENTIFIER ::= {id-it 2}
- * SignKeyPairTypesValue ::= SEQUENCE OF AlgorithmIdentifier
- * id-it-encKeyPairTypes OBJECT IDENTIFIER ::= {id-it 3}
- * EncKeyPairTypesValue ::= SEQUENCE OF AlgorithmIdentifier
- * id-it-preferredSymmAlg OBJECT IDENTIFIER ::= {id-it 4}
- * PreferredSymmAlgValue ::= AlgorithmIdentifier
- * id-it-caKeyUpdateInfo OBJECT IDENTIFIER ::= {id-it 5}
- * CAKeyUpdateInfoValue ::= CAKeyUpdAnnContent
- * id-it-currentCRL OBJECT IDENTIFIER ::= {id-it 6}
- * CurrentCRLValue ::= CertificateList
- * id-it-unsupportedOIDs OBJECT IDENTIFIER ::= {id-it 7}
- * UnsupportedOIDsValue ::= SEQUENCE OF OBJECT IDENTIFIER
- * id-it-keyPairParamReq OBJECT IDENTIFIER ::= {id-it 10}
- * KeyPairParamReqValue ::= OBJECT IDENTIFIER
- * id-it-keyPairParamRep OBJECT IDENTIFIER ::= {id-it 11}
- * KeyPairParamRepValue ::= AlgorithmIdentifer
- * id-it-revPassphrase OBJECT IDENTIFIER ::= {id-it 12}
- * RevPassphraseValue ::= EncryptedValue
- * id-it-implicitConfirm OBJECT IDENTIFIER ::= {id-it 13}
- * ImplicitConfirmValue ::= NULL
- * id-it-confirmWaitTime OBJECT IDENTIFIER ::= {id-it 14}
- * ConfirmWaitTimeValue ::= GeneralizedTime
- * id-it-origPKIMessage OBJECT IDENTIFIER ::= {id-it 15}
- * OrigPKIMessageValue ::= PKIMessages
- * id-it-suppLangTags OBJECT IDENTIFIER ::= {id-it 16}
- * SuppLangTagsValue ::= SEQUENCE OF UTF8String
- *
- * where
- *
- * id-pkix OBJECT IDENTIFIER ::= {
- * iso(1) identified-organization(3)
- * dod(6) internet(1) security(5) mechanisms(5) pkix(7)}
- * and
- * id-it OBJECT IDENTIFIER ::= {id-pkix 4}
- * </pre>
- */
-public class InfoTypeAndValue
- extends ASN1Object
-{
- private ASN1ObjectIdentifier infoType;
- private ASN1Encodable infoValue;
-
- private InfoTypeAndValue(ASN1Sequence seq)
- {
- infoType = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
-
- if (seq.size() > 1)
- {
- infoValue = (ASN1Encodable)seq.getObjectAt(1);
- }
- }
-
- public static InfoTypeAndValue getInstance(Object o)
- {
- if (o instanceof InfoTypeAndValue)
- {
- return (InfoTypeAndValue)o;
- }
-
- if (o != null)
- {
- return new InfoTypeAndValue(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public InfoTypeAndValue(
- ASN1ObjectIdentifier infoType)
- {
- this.infoType = infoType;
- this.infoValue = null;
- }
-
- public InfoTypeAndValue(
- ASN1ObjectIdentifier infoType,
- ASN1Encodable optionalValue)
- {
- this.infoType = infoType;
- this.infoValue = optionalValue;
- }
-
- public ASN1ObjectIdentifier getInfoType()
- {
- return infoType;
- }
-
- public ASN1Encodable getInfoValue()
- {
- return infoValue;
- }
-
- /**
- * <pre>
- * InfoTypeAndValue ::= SEQUENCE {
- * infoType OBJECT IDENTIFIER,
- * infoValue ANY DEFINED BY infoType OPTIONAL
- * }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(infoType);
-
- if (infoValue != null)
- {
- v.add(infoValue);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/KeyRecRepContent.java b/core/src/main/java/org/bouncycastle/asn1/cmp/KeyRecRepContent.java
deleted file mode 100644
index 3bc50329..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/KeyRecRepContent.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-public class KeyRecRepContent
- extends ASN1Object
-{
- private PKIStatusInfo status;
- private CMPCertificate newSigCert;
- private ASN1Sequence caCerts;
- private ASN1Sequence keyPairHist;
-
- private KeyRecRepContent(ASN1Sequence seq)
- {
- Enumeration en = seq.getObjects();
-
- status = PKIStatusInfo.getInstance(en.nextElement());
-
- while (en.hasMoreElements())
- {
- ASN1TaggedObject tObj = ASN1TaggedObject.getInstance(en.nextElement());
-
- switch (tObj.getTagNo())
- {
- case 0:
- newSigCert = CMPCertificate.getInstance(tObj.getObject());
- break;
- case 1:
- caCerts = ASN1Sequence.getInstance(tObj.getObject());
- break;
- case 2:
- keyPairHist = ASN1Sequence.getInstance(tObj.getObject());
- break;
- default:
- throw new IllegalArgumentException("unknown tag number: " + tObj.getTagNo());
- }
- }
- }
-
- public static KeyRecRepContent getInstance(Object o)
- {
- if (o instanceof KeyRecRepContent)
- {
- return (KeyRecRepContent)o;
- }
-
- if (o != null)
- {
- return new KeyRecRepContent(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
-
- public PKIStatusInfo getStatus()
- {
- return status;
- }
-
- public CMPCertificate getNewSigCert()
- {
- return newSigCert;
- }
-
- public CMPCertificate[] getCaCerts()
- {
- if (caCerts == null)
- {
- return null;
- }
-
- CMPCertificate[] results = new CMPCertificate[caCerts.size()];
-
- for (int i = 0; i != results.length; i++)
- {
- results[i] = CMPCertificate.getInstance(caCerts.getObjectAt(i));
- }
-
- return results;
- }
-
- public CertifiedKeyPair[] getKeyPairHist()
- {
- if (keyPairHist == null)
- {
- return null;
- }
-
- CertifiedKeyPair[] results = new CertifiedKeyPair[keyPairHist.size()];
-
- for (int i = 0; i != results.length; i++)
- {
- results[i] = CertifiedKeyPair.getInstance(keyPairHist.getObjectAt(i));
- }
-
- return results;
- }
-
- /**
- * <pre>
- * KeyRecRepContent ::= SEQUENCE {
- * status PKIStatusInfo,
- * newSigCert [0] CMPCertificate OPTIONAL,
- * caCerts [1] SEQUENCE SIZE (1..MAX) OF
- * CMPCertificate OPTIONAL,
- * keyPairHist [2] SEQUENCE SIZE (1..MAX) OF
- * CertifiedKeyPair OPTIONAL
- * }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(status);
-
- addOptional(v, 0, newSigCert);
- addOptional(v, 1, caCerts);
- addOptional(v, 2, keyPairHist);
-
- return new DERSequence(v);
- }
-
- private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj)
- {
- if (obj != null)
- {
- v.add(new DERTaggedObject(true, tagNo, obj));
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/OOBCertHash.java b/core/src/main/java/org/bouncycastle/asn1/cmp/OOBCertHash.java
deleted file mode 100644
index fd833c49..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/OOBCertHash.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.crmf.CertId;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-public class OOBCertHash
- extends ASN1Object
-{
- private AlgorithmIdentifier hashAlg;
- private CertId certId;
- private DERBitString hashVal;
-
- private OOBCertHash(ASN1Sequence seq)
- {
- int index = seq.size() - 1;
-
- hashVal = DERBitString.getInstance(seq.getObjectAt(index--));
-
- for (int i = index; i >= 0; i--)
- {
- ASN1TaggedObject tObj = (ASN1TaggedObject)seq.getObjectAt(i);
-
- if (tObj.getTagNo() == 0)
- {
- hashAlg = AlgorithmIdentifier.getInstance(tObj, true);
- }
- else
- {
- certId = CertId.getInstance(tObj, true);
- }
- }
-
- }
-
- public static OOBCertHash getInstance(Object o)
- {
- if (o instanceof OOBCertHash)
- {
- return (OOBCertHash)o;
- }
-
- if (o != null)
- {
- return new OOBCertHash(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public OOBCertHash(AlgorithmIdentifier hashAlg, CertId certId, byte[] hashVal)
- {
- this(hashAlg, certId, new DERBitString(hashVal));
- }
-
- public OOBCertHash(AlgorithmIdentifier hashAlg, CertId certId, DERBitString hashVal)
- {
- this.hashAlg = hashAlg;
- this.certId = certId;
- this.hashVal = hashVal;
- }
-
- public AlgorithmIdentifier getHashAlg()
- {
- return hashAlg;
- }
-
- public CertId getCertId()
- {
- return certId;
- }
-
- public DERBitString getHashVal()
- {
- return hashVal;
- }
-
- /**
- * <pre>
- * OOBCertHash ::= SEQUENCE {
- * hashAlg [0] AlgorithmIdentifier OPTIONAL,
- * certId [1] CertId OPTIONAL,
- * hashVal BIT STRING
- * -- hashVal is calculated over the DER encoding of the
- * -- self-signed certificate with the identifier certID.
- * }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- addOptional(v, 0, hashAlg);
- addOptional(v, 1, certId);
-
- v.add(hashVal);
-
- return new DERSequence(v);
- }
-
- private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj)
- {
- if (obj != null)
- {
- v.add(new DERTaggedObject(true, tagNo, obj));
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/PBMParameter.java b/core/src/main/java/org/bouncycastle/asn1/cmp/PBMParameter.java
deleted file mode 100644
index fdf2c250..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/PBMParameter.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-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.asn1.x509.AlgorithmIdentifier;
-
-public class PBMParameter
- extends ASN1Object
-{
- private ASN1OctetString salt;
- private AlgorithmIdentifier owf;
- private ASN1Integer iterationCount;
- private AlgorithmIdentifier mac;
-
- private PBMParameter(ASN1Sequence seq)
- {
- salt = ASN1OctetString.getInstance(seq.getObjectAt(0));
- owf = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
- iterationCount = ASN1Integer.getInstance(seq.getObjectAt(2));
- mac = AlgorithmIdentifier.getInstance(seq.getObjectAt(3));
- }
-
- public static PBMParameter getInstance(Object o)
- {
- if (o instanceof PBMParameter)
- {
- return (PBMParameter)o;
- }
-
- if (o != null)
- {
- return new PBMParameter(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public PBMParameter(
- byte[] salt,
- AlgorithmIdentifier owf,
- int iterationCount,
- AlgorithmIdentifier mac)
- {
- this(new DEROctetString(salt), owf,
- new ASN1Integer(iterationCount), mac);
- }
-
- public PBMParameter(
- ASN1OctetString salt,
- AlgorithmIdentifier owf,
- ASN1Integer iterationCount,
- AlgorithmIdentifier mac)
- {
- this.salt = salt;
- this.owf = owf;
- this.iterationCount = iterationCount;
- this.mac = mac;
- }
-
- public ASN1OctetString getSalt()
- {
- return salt;
- }
-
- public AlgorithmIdentifier getOwf()
- {
- return owf;
- }
-
- public ASN1Integer getIterationCount()
- {
- return iterationCount;
- }
-
- public AlgorithmIdentifier getMac()
- {
- return mac;
- }
-
- /**
- * <pre>
- * PBMParameter ::= SEQUENCE {
- * salt OCTET STRING,
- * -- note: implementations MAY wish to limit acceptable sizes
- * -- of this string to values appropriate for their environment
- * -- in order to reduce the risk of denial-of-service attacks
- * owf AlgorithmIdentifier,
- * -- AlgId for a One-Way Function (SHA-1 recommended)
- * iterationCount INTEGER,
- * -- number of times the OWF is applied
- * -- note: implementations MAY wish to limit acceptable sizes
- * -- of this integer to values appropriate for their environment
- * -- in order to reduce the risk of denial-of-service attacks
- * mac AlgorithmIdentifier
- * -- the MAC AlgId (e.g., DES-MAC, Triple-DES-MAC [PKCS11],
- * } -- or HMAC [RFC2104, RFC2202])
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(salt);
- v.add(owf);
- v.add(iterationCount);
- v.add(mac);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/PKIBody.java b/core/src/main/java/org/bouncycastle/asn1/cmp/PKIBody.java
deleted file mode 100644
index 269c3695..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/PKIBody.java
+++ /dev/null
@@ -1,194 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.crmf.CertReqMessages;
-import org.bouncycastle.asn1.pkcs.CertificationRequest;
-
-public class PKIBody
- extends ASN1Object
- implements ASN1Choice
-{
- public static final int TYPE_INIT_REQ = 0;
- public static final int TYPE_INIT_REP = 1;
- public static final int TYPE_CERT_REQ = 2;
- public static final int TYPE_CERT_REP = 3;
- public static final int TYPE_P10_CERT_REQ = 4;
- public static final int TYPE_POPO_CHALL = 5;
- public static final int TYPE_POPO_REP = 6;
- public static final int TYPE_KEY_UPDATE_REQ = 7;
- public static final int TYPE_KEY_UPDATE_REP = 8;
- public static final int TYPE_KEY_RECOVERY_REQ = 9;
- public static final int TYPE_KEY_RECOVERY_REP = 10;
- public static final int TYPE_REVOCATION_REQ = 11;
- public static final int TYPE_REVOCATION_REP = 12;
- public static final int TYPE_CROSS_CERT_REQ = 13;
- public static final int TYPE_CROSS_CERT_REP = 14;
- public static final int TYPE_CA_KEY_UPDATE_ANN = 15;
- public static final int TYPE_CERT_ANN = 16;
- public static final int TYPE_REVOCATION_ANN = 17;
- public static final int TYPE_CRL_ANN = 18;
- public static final int TYPE_CONFIRM = 19;
- public static final int TYPE_NESTED = 20;
- public static final int TYPE_GEN_MSG = 21;
- public static final int TYPE_GEN_REP = 22;
- public static final int TYPE_ERROR = 23;
- public static final int TYPE_CERT_CONFIRM = 24;
- public static final int TYPE_POLL_REQ = 25;
- public static final int TYPE_POLL_REP = 26;
-
- private int tagNo;
- private ASN1Encodable body;
-
- public static PKIBody getInstance(Object o)
- {
- if (o == null || o instanceof PKIBody)
- {
- return (PKIBody)o;
- }
-
- if (o instanceof ASN1TaggedObject)
- {
- return new PKIBody((ASN1TaggedObject)o);
- }
-
- throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
- }
-
- private PKIBody(ASN1TaggedObject tagged)
- {
- tagNo = tagged.getTagNo();
- body = getBodyForType(tagNo, tagged.getObject());
- }
-
- /**
- * Creates a new PKIBody.
- * @param type one of the TYPE_* constants
- * @param content message content
- */
- public PKIBody(
- int type,
- ASN1Encodable content)
- {
- tagNo = type;
- body = getBodyForType(type, content);
- }
-
- private static ASN1Encodable getBodyForType(
- int type,
- ASN1Encodable o)
- {
- switch (type)
- {
- case TYPE_INIT_REQ:
- return CertReqMessages.getInstance(o);
- case TYPE_INIT_REP:
- return CertRepMessage.getInstance(o);
- case TYPE_CERT_REQ:
- return CertReqMessages.getInstance(o);
- case TYPE_CERT_REP:
- return CertRepMessage.getInstance(o);
- case TYPE_P10_CERT_REQ:
- return CertificationRequest.getInstance(o);
- case TYPE_POPO_CHALL:
- return POPODecKeyChallContent.getInstance(o);
- case TYPE_POPO_REP:
- return POPODecKeyRespContent.getInstance(o);
- case TYPE_KEY_UPDATE_REQ:
- return CertReqMessages.getInstance(o);
- case TYPE_KEY_UPDATE_REP:
- return CertRepMessage.getInstance(o);
- case TYPE_KEY_RECOVERY_REQ:
- return CertReqMessages.getInstance(o);
- case TYPE_KEY_RECOVERY_REP:
- return KeyRecRepContent.getInstance(o);
- case TYPE_REVOCATION_REQ:
- return RevReqContent.getInstance(o);
- case TYPE_REVOCATION_REP:
- return RevRepContent.getInstance(o);
- case TYPE_CROSS_CERT_REQ:
- return CertReqMessages.getInstance(o);
- case TYPE_CROSS_CERT_REP:
- return CertRepMessage.getInstance(o);
- case TYPE_CA_KEY_UPDATE_ANN:
- return CAKeyUpdAnnContent.getInstance(o);
- case TYPE_CERT_ANN:
- return CMPCertificate.getInstance(o);
- case TYPE_REVOCATION_ANN:
- return RevAnnContent.getInstance(o);
- case TYPE_CRL_ANN:
- return CRLAnnContent.getInstance(o);
- case TYPE_CONFIRM:
- return PKIConfirmContent.getInstance(o);
- case TYPE_NESTED:
- return PKIMessages.getInstance(o);
- case TYPE_GEN_MSG:
- return GenMsgContent.getInstance(o);
- case TYPE_GEN_REP:
- return GenRepContent.getInstance(o);
- case TYPE_ERROR:
- return ErrorMsgContent.getInstance(o);
- case TYPE_CERT_CONFIRM:
- return CertConfirmContent.getInstance(o);
- case TYPE_POLL_REQ:
- return PollReqContent.getInstance(o);
- case TYPE_POLL_REP:
- return PollRepContent.getInstance(o);
- default:
- throw new IllegalArgumentException("unknown tag number: " + type);
- }
- }
-
- public int getType()
- {
- return tagNo;
- }
-
- public ASN1Encodable getContent()
- {
- return body;
- }
-
- /**
- * <pre>
- * PKIBody ::= CHOICE { -- message-specific body elements
- * ir [0] CertReqMessages, --Initialization Request
- * ip [1] CertRepMessage, --Initialization Response
- * cr [2] CertReqMessages, --Certification Request
- * cp [3] CertRepMessage, --Certification Response
- * p10cr [4] CertificationRequest, --imported from [PKCS10]
- * popdecc [5] POPODecKeyChallContent, --pop Challenge
- * popdecr [6] POPODecKeyRespContent, --pop Response
- * kur [7] CertReqMessages, --Key Update Request
- * kup [8] CertRepMessage, --Key Update Response
- * krr [9] CertReqMessages, --Key Recovery Request
- * krp [10] KeyRecRepContent, --Key Recovery Response
- * rr [11] RevReqContent, --Revocation Request
- * rp [12] RevRepContent, --Revocation Response
- * ccr [13] CertReqMessages, --Cross-Cert. Request
- * ccp [14] CertRepMessage, --Cross-Cert. Response
- * ckuann [15] CAKeyUpdAnnContent, --CA Key Update Ann.
- * cann [16] CertAnnContent, --Certificate Ann.
- * rann [17] RevAnnContent, --Revocation Ann.
- * crlann [18] CRLAnnContent, --CRL Announcement
- * pkiconf [19] PKIConfirmContent, --Confirmation
- * nested [20] NestedMessageContent, --Nested Message
- * genm [21] GenMsgContent, --General Message
- * genp [22] GenRepContent, --General Response
- * error [23] ErrorMsgContent, --Error Message
- * certConf [24] CertConfirmContent, --Certificate confirm
- * pollReq [25] PollReqContent, --Polling request
- * pollRep [26] PollRepContent --Polling response
- * }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- return new DERTaggedObject(true, tagNo, body);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/PKIConfirmContent.java b/core/src/main/java/org/bouncycastle/asn1/cmp/PKIConfirmContent.java
deleted file mode 100644
index 5af3f7d7..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/PKIConfirmContent.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1Null;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.DERNull;
-
-public class PKIConfirmContent
- extends ASN1Object
-{
- private ASN1Null val;
-
- private PKIConfirmContent(ASN1Null val)
- {
- this.val = val;
- }
-
- public static PKIConfirmContent getInstance(Object o)
- {
- if (o == null || o instanceof PKIConfirmContent)
- {
- return (PKIConfirmContent)o;
- }
-
- if (o instanceof ASN1Null)
- {
- return new PKIConfirmContent((ASN1Null)o);
- }
-
- throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
- }
-
- public PKIConfirmContent()
- {
- val = DERNull.INSTANCE;
- }
-
- /**
- * <pre>
- * PKIConfirmContent ::= NULL
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- return val;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/PKIFailureInfo.java b/core/src/main/java/org/bouncycastle/asn1/cmp/PKIFailureInfo.java
deleted file mode 100644
index 10acbb44..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/PKIFailureInfo.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.DERBitString;
-
-/**
- * <pre>
- * PKIFailureInfo ::= BIT STRING {
- * badAlg (0),
- * -- unrecognized or unsupported Algorithm Identifier
- * badMessageCheck (1), -- integrity check failed (e.g., signature did not verify)
- * badRequest (2),
- * -- transaction not permitted or supported
- * badTime (3), -- messageTime was not sufficiently close to the system time, as defined by local policy
- * badCertId (4), -- no certificate could be found matching the provided criteria
- * badDataFormat (5),
- * -- the data submitted has the wrong format
- * wrongAuthority (6), -- the authority indicated in the request is different from the one creating the response token
- * incorrectData (7), -- the requester's data is incorrect (for notary services)
- * missingTimeStamp (8), -- when the timestamp is missing but should be there (by policy)
- * badPOP (9) -- the proof-of-possession failed
- * certRevoked (10),
- * certConfirmed (11),
- * wrongIntegrity (12),
- * badRecipientNonce (13),
- * timeNotAvailable (14),
- * -- the TSA's time source is not available
- * unacceptedPolicy (15),
- * -- the requested TSA policy is not supported by the TSA
- * unacceptedExtension (16),
- * -- the requested extension is not supported by the TSA
- * addInfoNotAvailable (17)
- * -- the additional information requested could not be understood
- * -- or is not available
- * badSenderNonce (18),
- * badCertTemplate (19),
- * signerNotTrusted (20),
- * transactionIdInUse (21),
- * unsupportedVersion (22),
- * notAuthorized (23),
- * systemUnavail (24),
- * systemFailure (25),
- * -- the request cannot be handled due to system failure
- * duplicateCertReq (26)
- * </pre>
- */
-public class PKIFailureInfo
- extends DERBitString
-{
- public static final int badAlg = (1 << 7); // unrecognized or unsupported Algorithm Identifier
- public static final int badMessageCheck = (1 << 6); // integrity check failed (e.g., signature did not verify)
- public static final int badRequest = (1 << 5);
- public static final int badTime = (1 << 4); // -- messageTime was not sufficiently close to the system time, as defined by local policy
- public static final int badCertId = (1 << 3); // no certificate could be found matching the provided criteria
- public static final int badDataFormat = (1 << 2);
- public static final int wrongAuthority = (1 << 1); // the authority indicated in the request is different from the one creating the response token
- public static final int incorrectData = 1; // the requester's data is incorrect (for notary services)
- public static final int missingTimeStamp = (1 << 15); // when the timestamp is missing but should be there (by policy)
- public static final int badPOP = (1 << 14); // the proof-of-possession failed
- public static final int certRevoked = (1 << 13);
- public static final int certConfirmed = (1 << 12);
- public static final int wrongIntegrity = (1 << 11);
- public static final int badRecipientNonce = (1 << 10);
- public static final int timeNotAvailable = (1 << 9); // the TSA's time source is not available
- public static final int unacceptedPolicy = (1 << 8); // the requested TSA policy is not supported by the TSA
- public static final int unacceptedExtension = (1 << 23); //the requested extension is not supported by the TSA
- public static final int addInfoNotAvailable = (1 << 22); //the additional information requested could not be understood or is not available
- public static final int badSenderNonce = (1 << 21);
- public static final int badCertTemplate = (1 << 20);
- public static final int signerNotTrusted = (1 << 19);
- public static final int transactionIdInUse = (1 << 18);
- public static final int unsupportedVersion = (1 << 17);
- public static final int notAuthorized = (1 << 16);
- public static final int systemUnavail = (1 << 31);
- public static final int systemFailure = (1 << 30); //the request cannot be handled due to system failure
- public static final int duplicateCertReq = (1 << 29);
-
- /** @deprecated use lower case version */
- public static final int BAD_ALG = badAlg; // unrecognized or unsupported Algorithm Identifier
- /** @deprecated use lower case version */
- public static final int BAD_MESSAGE_CHECK = badMessageCheck;
- /** @deprecated use lower case version */
- public static final int BAD_REQUEST = badRequest; // transaction not permitted or supported
- /** @deprecated use lower case version */
- public static final int BAD_TIME = badTime;
- /** @deprecated use lower case version */
- public static final int BAD_CERT_ID = badCertId;
- /** @deprecated use lower case version */
- public static final int BAD_DATA_FORMAT = badDataFormat; // the data submitted has the wrong format
- /** @deprecated use lower case version */
- public static final int WRONG_AUTHORITY = wrongAuthority;
- /** @deprecated use lower case version */
- public static final int INCORRECT_DATA = incorrectData;
- /** @deprecated use lower case version */
- public static final int MISSING_TIME_STAMP = missingTimeStamp;
- /** @deprecated use lower case version */
- public static final int BAD_POP = badPOP;
- /** @deprecated use lower case version */
- public static final int TIME_NOT_AVAILABLE = timeNotAvailable;
- /** @deprecated use lower case version */
- public static final int UNACCEPTED_POLICY = unacceptedPolicy;
- /** @deprecated use lower case version */
- public static final int UNACCEPTED_EXTENSION = unacceptedExtension;
- /** @deprecated use lower case version */
- public static final int ADD_INFO_NOT_AVAILABLE = addInfoNotAvailable;
- /** @deprecated use lower case version */
- public static final int SYSTEM_FAILURE = systemFailure;
- /**
- * Basic constructor.
- */
- public PKIFailureInfo(
- int info)
- {
- super(getBytes(info), getPadBits(info));
- }
-
- public PKIFailureInfo(
- DERBitString info)
- {
- super(info.getBytes(), info.getPadBits());
- }
-
- public String toString()
- {
- return "PKIFailureInfo: 0x" + Integer.toHexString(this.intValue());
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/PKIFreeText.java b/core/src/main/java/org/bouncycastle/asn1/cmp/PKIFreeText.java
deleted file mode 100644
index 5b63c194..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/PKIFreeText.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERUTF8String;
-
-public class PKIFreeText
- extends ASN1Object
-{
- ASN1Sequence strings;
-
- public static PKIFreeText getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static PKIFreeText getInstance(
- Object obj)
- {
- if (obj instanceof PKIFreeText)
- {
- return (PKIFreeText)obj;
- }
- else if (obj != null)
- {
- return new PKIFreeText(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private PKIFreeText(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
- while (e.hasMoreElements())
- {
- if (!(e.nextElement() instanceof DERUTF8String))
- {
- throw new IllegalArgumentException("attempt to insert non UTF8 STRING into PKIFreeText");
- }
- }
-
- strings = seq;
- }
-
- public PKIFreeText(
- DERUTF8String p)
- {
- strings = new DERSequence(p);
- }
-
- public PKIFreeText(
- String p)
- {
- this(new DERUTF8String(p));
- }
-
- public PKIFreeText(
- DERUTF8String[] strs)
- {
- strings = new DERSequence(strs);
- }
-
- public PKIFreeText(
- String[] strs)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- for (int i = 0; i < strs.length; i++)
- {
- v.add(new DERUTF8String(strs[i]));
- }
- strings = new DERSequence(v);
- }
-
- /**
- * Return the number of string elements present.
- *
- * @return number of elements present.
- */
- public int size()
- {
- return strings.size();
- }
-
- /**
- * Return the UTF8STRING at index i.
- *
- * @param i index of the string of interest
- * @return the string at index i.
- */
- public DERUTF8String getStringAt(
- int i)
- {
- return (DERUTF8String)strings.getObjectAt(i);
- }
-
- /**
- * <pre>
- * PKIFreeText ::= SEQUENCE SIZE (1..MAX) OF UTF8String
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- return strings;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/PKIHeader.java b/core/src/main/java/org/bouncycastle/asn1/cmp/PKIHeader.java
deleted file mode 100644
index 82f1b087..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/PKIHeader.java
+++ /dev/null
@@ -1,260 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-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.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.GeneralName;
-
-public class PKIHeader
- extends ASN1Object
-{
- /**
- * Value for a "null" recipient or sender.
- */
- public static final GeneralName NULL_NAME = new GeneralName(X500Name.getInstance(new DERSequence()));
-
- public static final int CMP_1999 = 1;
- public static final int CMP_2000 = 2;
-
- private ASN1Integer pvno;
- private GeneralName sender;
- private GeneralName recipient;
- private ASN1GeneralizedTime messageTime;
- private AlgorithmIdentifier protectionAlg;
- private ASN1OctetString senderKID; // KeyIdentifier
- private ASN1OctetString recipKID; // KeyIdentifier
- private ASN1OctetString transactionID;
- private ASN1OctetString senderNonce;
- private ASN1OctetString recipNonce;
- private PKIFreeText freeText;
- private ASN1Sequence generalInfo;
-
- private PKIHeader(ASN1Sequence seq)
- {
- Enumeration en = seq.getObjects();
-
- pvno = ASN1Integer.getInstance(en.nextElement());
- sender = GeneralName.getInstance(en.nextElement());
- recipient = GeneralName.getInstance(en.nextElement());
-
- while (en.hasMoreElements())
- {
- ASN1TaggedObject tObj = (ASN1TaggedObject)en.nextElement();
-
- switch (tObj.getTagNo())
- {
- case 0:
- messageTime = ASN1GeneralizedTime.getInstance(tObj, true);
- break;
- case 1:
- protectionAlg = AlgorithmIdentifier.getInstance(tObj, true);
- break;
- case 2:
- senderKID = ASN1OctetString.getInstance(tObj, true);
- break;
- case 3:
- recipKID = ASN1OctetString.getInstance(tObj, true);
- break;
- case 4:
- transactionID = ASN1OctetString.getInstance(tObj, true);
- break;
- case 5:
- senderNonce = ASN1OctetString.getInstance(tObj, true);
- break;
- case 6:
- recipNonce = ASN1OctetString.getInstance(tObj, true);
- break;
- case 7:
- freeText = PKIFreeText.getInstance(tObj, true);
- break;
- case 8:
- generalInfo = ASN1Sequence.getInstance(tObj, true);
- break;
- default:
- throw new IllegalArgumentException("unknown tag number: " + tObj.getTagNo());
- }
- }
- }
-
- public static PKIHeader getInstance(Object o)
- {
- if (o instanceof PKIHeader)
- {
- return (PKIHeader)o;
- }
-
- if (o != null)
- {
- return new PKIHeader(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public PKIHeader(
- int pvno,
- GeneralName sender,
- GeneralName recipient)
- {
- this(new ASN1Integer(pvno), sender, recipient);
- }
-
- private PKIHeader(
- ASN1Integer pvno,
- GeneralName sender,
- GeneralName recipient)
- {
- this.pvno = pvno;
- this.sender = sender;
- this.recipient = recipient;
- }
-
- public ASN1Integer getPvno()
- {
- return pvno;
- }
-
- public GeneralName getSender()
- {
- return sender;
- }
-
- public GeneralName getRecipient()
- {
- return recipient;
- }
-
- public ASN1GeneralizedTime getMessageTime()
- {
- return messageTime;
- }
-
- public AlgorithmIdentifier getProtectionAlg()
- {
- return protectionAlg;
- }
-
- public ASN1OctetString getSenderKID()
- {
- return senderKID;
- }
-
- public ASN1OctetString getRecipKID()
- {
- return recipKID;
- }
-
- public ASN1OctetString getTransactionID()
- {
- return transactionID;
- }
-
- public ASN1OctetString getSenderNonce()
- {
- return senderNonce;
- }
-
- public ASN1OctetString getRecipNonce()
- {
- return recipNonce;
- }
-
- public PKIFreeText getFreeText()
- {
- return freeText;
- }
-
- public InfoTypeAndValue[] getGeneralInfo()
- {
- if (generalInfo == null)
- {
- return null;
- }
- InfoTypeAndValue[] results = new InfoTypeAndValue[generalInfo.size()];
- for (int i = 0; i < results.length; i++)
- {
- results[i]
- = InfoTypeAndValue.getInstance(generalInfo.getObjectAt(i));
- }
- return results;
- }
-
- /**
- * <pre>
- * PKIHeader ::= SEQUENCE {
- * pvno INTEGER { cmp1999(1), cmp2000(2) },
- * sender GeneralName,
- * -- identifies the sender
- * recipient GeneralName,
- * -- identifies the intended recipient
- * messageTime [0] GeneralizedTime OPTIONAL,
- * -- time of production of this message (used when sender
- * -- believes that the transport will be "suitable"; i.e.,
- * -- that the time will still be meaningful upon receipt)
- * protectionAlg [1] AlgorithmIdentifier OPTIONAL,
- * -- algorithm used for calculation of protection bits
- * senderKID [2] KeyIdentifier OPTIONAL,
- * recipKID [3] KeyIdentifier OPTIONAL,
- * -- to identify specific keys used for protection
- * transactionID [4] OCTET STRING OPTIONAL,
- * -- identifies the transaction; i.e., this will be the same in
- * -- corresponding request, response, certConf, and PKIConf
- * -- messages
- * senderNonce [5] OCTET STRING OPTIONAL,
- * recipNonce [6] OCTET STRING OPTIONAL,
- * -- nonces used to provide replay protection, senderNonce
- * -- is inserted by the creator of this message; recipNonce
- * -- is a nonce previously inserted in a related message by
- * -- the intended recipient of this message
- * freeText [7] PKIFreeText OPTIONAL,
- * -- this may be used to indicate context-specific instructions
- * -- (this field is intended for human consumption)
- * generalInfo [8] SEQUENCE SIZE (1..MAX) OF
- * InfoTypeAndValue OPTIONAL
- * -- this may be used to convey context-specific information
- * -- (this field not primarily intended for human consumption)
- * }
- * </pre>
- *
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(pvno);
- v.add(sender);
- v.add(recipient);
- addOptional(v, 0, messageTime);
- addOptional(v, 1, protectionAlg);
- addOptional(v, 2, senderKID);
- addOptional(v, 3, recipKID);
- addOptional(v, 4, transactionID);
- addOptional(v, 5, senderNonce);
- addOptional(v, 6, recipNonce);
- addOptional(v, 7, freeText);
- addOptional(v, 8, generalInfo);
-
- return new DERSequence(v);
- }
-
- private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj)
- {
- if (obj != null)
- {
- v.add(new DERTaggedObject(true, tagNo, obj));
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/PKIHeaderBuilder.java b/core/src/main/java/org/bouncycastle/asn1/cmp/PKIHeaderBuilder.java
deleted file mode 100644
index c5465a97..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/PKIHeaderBuilder.java
+++ /dev/null
@@ -1,243 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.GeneralName;
-
-public class PKIHeaderBuilder
-{
- private ASN1Integer pvno;
- private GeneralName sender;
- private GeneralName recipient;
- private ASN1GeneralizedTime messageTime;
- private AlgorithmIdentifier protectionAlg;
- private ASN1OctetString senderKID; // KeyIdentifier
- private ASN1OctetString recipKID; // KeyIdentifier
- private ASN1OctetString transactionID;
- private ASN1OctetString senderNonce;
- private ASN1OctetString recipNonce;
- private PKIFreeText freeText;
- private ASN1Sequence generalInfo;
-
- public PKIHeaderBuilder(
- int pvno,
- GeneralName sender,
- GeneralName recipient)
- {
- this(new ASN1Integer(pvno), sender, recipient);
- }
-
- private PKIHeaderBuilder(
- ASN1Integer pvno,
- GeneralName sender,
- GeneralName recipient)
- {
- this.pvno = pvno;
- this.sender = sender;
- this.recipient = recipient;
- }
-
- public PKIHeaderBuilder setMessageTime(ASN1GeneralizedTime time)
- {
- messageTime = time;
-
- return this;
- }
-
- public PKIHeaderBuilder setProtectionAlg(AlgorithmIdentifier aid)
- {
- protectionAlg = aid;
-
- return this;
- }
-
- public PKIHeaderBuilder setSenderKID(byte[] kid)
- {
- return setSenderKID(kid == null ? null : new DEROctetString(kid));
- }
-
- public PKIHeaderBuilder setSenderKID(ASN1OctetString kid)
- {
- senderKID = kid;
-
- return this;
- }
-
- public PKIHeaderBuilder setRecipKID(byte[] kid)
- {
- return setRecipKID(kid == null ? null : new DEROctetString(kid));
- }
-
- public PKIHeaderBuilder setRecipKID(DEROctetString kid)
- {
- recipKID = kid;
-
- return this;
- }
-
- public PKIHeaderBuilder setTransactionID(byte[] tid)
- {
- return setTransactionID(tid == null ? null : new DEROctetString(tid));
- }
-
- public PKIHeaderBuilder setTransactionID(ASN1OctetString tid)
- {
- transactionID = tid;
-
- return this;
- }
-
- public PKIHeaderBuilder setSenderNonce(byte[] nonce)
- {
- return setSenderNonce(nonce == null ? null : new DEROctetString(nonce));
- }
-
- public PKIHeaderBuilder setSenderNonce(ASN1OctetString nonce)
- {
- senderNonce = nonce;
-
- return this;
- }
-
- public PKIHeaderBuilder setRecipNonce(byte[] nonce)
- {
- return setRecipNonce(nonce == null ? null : new DEROctetString(nonce));
- }
-
- public PKIHeaderBuilder setRecipNonce(ASN1OctetString nonce)
- {
- recipNonce = nonce;
-
- return this;
- }
-
- public PKIHeaderBuilder setFreeText(PKIFreeText text)
- {
- freeText = text;
-
- return this;
- }
-
- public PKIHeaderBuilder setGeneralInfo(InfoTypeAndValue genInfo)
- {
- return setGeneralInfo(makeGeneralInfoSeq(genInfo));
- }
-
- public PKIHeaderBuilder setGeneralInfo(InfoTypeAndValue[] genInfos)
- {
- return setGeneralInfo(makeGeneralInfoSeq(genInfos));
- }
-
- public PKIHeaderBuilder setGeneralInfo(ASN1Sequence seqOfInfoTypeAndValue)
- {
- generalInfo = seqOfInfoTypeAndValue;
-
- return this;
- }
-
- private static ASN1Sequence makeGeneralInfoSeq(
- InfoTypeAndValue generalInfo)
- {
- return new DERSequence(generalInfo);
- }
-
- private static ASN1Sequence makeGeneralInfoSeq(
- InfoTypeAndValue[] generalInfos)
- {
- ASN1Sequence genInfoSeq = null;
- if (generalInfos != null)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- for (int i = 0; i < generalInfos.length; i++)
- {
- v.add(generalInfos[i]);
- }
- genInfoSeq = new DERSequence(v);
- }
- return genInfoSeq;
- }
-
- /**
- * <pre>
- * PKIHeader ::= SEQUENCE {
- * pvno INTEGER { cmp1999(1), cmp2000(2) },
- * sender GeneralName,
- * -- identifies the sender
- * recipient GeneralName,
- * -- identifies the intended recipient
- * messageTime [0] GeneralizedTime OPTIONAL,
- * -- time of production of this message (used when sender
- * -- believes that the transport will be "suitable"; i.e.,
- * -- that the time will still be meaningful upon receipt)
- * protectionAlg [1] AlgorithmIdentifier OPTIONAL,
- * -- algorithm used for calculation of protection bits
- * senderKID [2] KeyIdentifier OPTIONAL,
- * recipKID [3] KeyIdentifier OPTIONAL,
- * -- to identify specific keys used for protection
- * transactionID [4] OCTET STRING OPTIONAL,
- * -- identifies the transaction; i.e., this will be the same in
- * -- corresponding request, response, certConf, and PKIConf
- * -- messages
- * senderNonce [5] OCTET STRING OPTIONAL,
- * recipNonce [6] OCTET STRING OPTIONAL,
- * -- nonces used to provide replay protection, senderNonce
- * -- is inserted by the creator of this message; recipNonce
- * -- is a nonce previously inserted in a related message by
- * -- the intended recipient of this message
- * freeText [7] PKIFreeText OPTIONAL,
- * -- this may be used to indicate context-specific instructions
- * -- (this field is intended for human consumption)
- * generalInfo [8] SEQUENCE SIZE (1..MAX) OF
- * InfoTypeAndValue OPTIONAL
- * -- this may be used to convey context-specific information
- * -- (this field not primarily intended for human consumption)
- * }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public PKIHeader build()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(pvno);
- v.add(sender);
- v.add(recipient);
- addOptional(v, 0, messageTime);
- addOptional(v, 1, protectionAlg);
- addOptional(v, 2, senderKID);
- addOptional(v, 3, recipKID);
- addOptional(v, 4, transactionID);
- addOptional(v, 5, senderNonce);
- addOptional(v, 6, recipNonce);
- addOptional(v, 7, freeText);
- addOptional(v, 8, generalInfo);
-
- messageTime = null;
- protectionAlg = null;
- senderKID = null;
- recipKID = null;
- transactionID = null;
- senderNonce = null;
- recipNonce = null;
- freeText = null;
- generalInfo = null;
-
- return PKIHeader.getInstance(new DERSequence(v));
- }
-
- private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj)
- {
- if (obj != null)
- {
- v.add(new DERTaggedObject(true, tagNo, obj));
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/PKIMessage.java b/core/src/main/java/org/bouncycastle/asn1/cmp/PKIMessage.java
deleted file mode 100644
index bfc21133..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/PKIMessage.java
+++ /dev/null
@@ -1,166 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-public class PKIMessage
- extends ASN1Object
-{
- private PKIHeader header;
- private PKIBody body;
- private DERBitString protection;
- private ASN1Sequence extraCerts;
-
- private PKIMessage(ASN1Sequence seq)
- {
- Enumeration en = seq.getObjects();
-
- header = PKIHeader.getInstance(en.nextElement());
- body = PKIBody.getInstance(en.nextElement());
-
- while (en.hasMoreElements())
- {
- ASN1TaggedObject tObj = (ASN1TaggedObject)en.nextElement();
-
- if (tObj.getTagNo() == 0)
- {
- protection = DERBitString.getInstance(tObj, true);
- }
- else
- {
- extraCerts = ASN1Sequence.getInstance(tObj, true);
- }
- }
- }
-
- public static PKIMessage getInstance(Object o)
- {
- if (o instanceof PKIMessage)
- {
- return (PKIMessage)o;
- }
- else if (o != null)
- {
- return new PKIMessage(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- /**
- * Creates a new PKIMessage.
- *
- * @param header message header
- * @param body message body
- * @param protection message protection (may be null)
- * @param extraCerts extra certificates (may be null)
- */
- public PKIMessage(
- PKIHeader header,
- PKIBody body,
- DERBitString protection,
- CMPCertificate[] extraCerts)
- {
- this.header = header;
- this.body = body;
- this.protection = protection;
- if (extraCerts != null)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- for (int i = 0; i < extraCerts.length; i++)
- {
- v.add(extraCerts[i]);
- }
- this.extraCerts = new DERSequence(v);
- }
- }
-
- public PKIMessage(
- PKIHeader header,
- PKIBody body,
- DERBitString protection)
- {
- this(header, body, protection, null);
- }
-
- public PKIMessage(
- PKIHeader header,
- PKIBody body)
- {
- this(header, body, null, null);
- }
-
- public PKIHeader getHeader()
- {
- return header;
- }
-
- public PKIBody getBody()
- {
- return body;
- }
-
- public DERBitString getProtection()
- {
- return protection;
- }
-
- public CMPCertificate[] getExtraCerts()
- {
- if (extraCerts == null)
- {
- return null;
- }
-
- CMPCertificate[] results = new CMPCertificate[extraCerts.size()];
-
- for (int i = 0; i < results.length; i++)
- {
- results[i] = CMPCertificate.getInstance(extraCerts.getObjectAt(i));
- }
- return results;
- }
-
- /**
- * <pre>
- * PKIMessage ::= SEQUENCE {
- * header PKIHeader,
- * body PKIBody,
- * protection [0] PKIProtection OPTIONAL,
- * extraCerts [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
- * OPTIONAL
- * }
- * </pre>
- *
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(header);
- v.add(body);
-
- addOptional(v, 0, protection);
- addOptional(v, 1, extraCerts);
-
- return new DERSequence(v);
- }
-
- private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj)
- {
- if (obj != null)
- {
- v.add(new DERTaggedObject(true, tagNo, obj));
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/PKIMessages.java b/core/src/main/java/org/bouncycastle/asn1/cmp/PKIMessages.java
deleted file mode 100644
index 5a80a0f4..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/PKIMessages.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-public class PKIMessages
- extends ASN1Object
-{
- private ASN1Sequence content;
-
- private PKIMessages(ASN1Sequence seq)
- {
- content = seq;
- }
-
- public static PKIMessages getInstance(Object o)
- {
- if (o instanceof PKIMessages)
- {
- return (PKIMessages)o;
- }
-
- if (o != null)
- {
- return new PKIMessages(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public PKIMessages(PKIMessage msg)
- {
- content = new DERSequence(msg);
- }
-
- public PKIMessages(PKIMessage[] msgs)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- for (int i = 0; i < msgs.length; i++)
- {
- v.add(msgs[i]);
- }
- content = new DERSequence(v);
- }
-
- public PKIMessage[] toPKIMessageArray()
- {
- PKIMessage[] result = new PKIMessage[content.size()];
-
- for (int i = 0; i != result.length; i++)
- {
- result[i] = PKIMessage.getInstance(content.getObjectAt(i));
- }
-
- return result;
- }
-
- /**
- * <pre>
- * PKIMessages ::= SEQUENCE SIZE (1..MAX) OF PKIMessage
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- return content;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/PKIStatus.java b/core/src/main/java/org/bouncycastle/asn1/cmp/PKIStatus.java
deleted file mode 100644
index 58f7ec02..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/PKIStatus.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-
-public class PKIStatus
- extends ASN1Object
-{
- public static final int GRANTED = 0;
- public static final int GRANTED_WITH_MODS = 1;
- public static final int REJECTION = 2;
- public static final int WAITING = 3;
- public static final int REVOCATION_WARNING = 4;
- public static final int REVOCATION_NOTIFICATION = 5;
- public static final int KEY_UPDATE_WARNING = 6;
-
- public static final PKIStatus granted = new PKIStatus(GRANTED);
- public static final PKIStatus grantedWithMods = new PKIStatus(GRANTED_WITH_MODS);
- public static final PKIStatus rejection = new PKIStatus(REJECTION);
- public static final PKIStatus waiting = new PKIStatus(WAITING);
- public static final PKIStatus revocationWarning = new PKIStatus(REVOCATION_WARNING);
- public static final PKIStatus revocationNotification = new PKIStatus(REVOCATION_NOTIFICATION);
- public static final PKIStatus keyUpdateWaiting = new PKIStatus(KEY_UPDATE_WARNING);
-
- private ASN1Integer value;
-
- private PKIStatus(int value)
- {
- this(new ASN1Integer(value));
- }
-
- private PKIStatus(ASN1Integer value)
- {
- this.value = value;
- }
-
- public static PKIStatus getInstance(Object o)
- {
- if (o instanceof PKIStatus)
- {
- return (PKIStatus)o;
- }
-
- if (o != null)
- {
- return new PKIStatus(ASN1Integer.getInstance(o));
- }
-
- return null;
- }
-
- public BigInteger getValue()
- {
- return value.getValue();
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return value;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/PKIStatusInfo.java b/core/src/main/java/org/bouncycastle/asn1/cmp/PKIStatusInfo.java
deleted file mode 100644
index bac1ba56..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/PKIStatusInfo.java
+++ /dev/null
@@ -1,165 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERSequence;
-
-public class PKIStatusInfo
- extends ASN1Object
-{
- ASN1Integer status;
- PKIFreeText statusString;
- DERBitString failInfo;
-
- public static PKIStatusInfo getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static PKIStatusInfo getInstance(
- Object obj)
- {
- if (obj instanceof PKIStatusInfo)
- {
- return (PKIStatusInfo)obj;
- }
- else if (obj != null)
- {
- return new PKIStatusInfo(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private PKIStatusInfo(
- ASN1Sequence seq)
- {
- this.status = ASN1Integer.getInstance(seq.getObjectAt(0));
-
- this.statusString = null;
- this.failInfo = null;
-
- if (seq.size() > 2)
- {
- this.statusString = PKIFreeText.getInstance(seq.getObjectAt(1));
- this.failInfo = DERBitString.getInstance(seq.getObjectAt(2));
- }
- else if (seq.size() > 1)
- {
- Object obj = seq.getObjectAt(1);
- if (obj instanceof DERBitString)
- {
- this.failInfo = DERBitString.getInstance(obj);
- }
- else
- {
- this.statusString = PKIFreeText.getInstance(obj);
- }
- }
- }
-
- /**
- * @param status
- */
- public PKIStatusInfo(PKIStatus status)
- {
- this.status = ASN1Integer.getInstance(status.toASN1Primitive());
- }
-
- /**
- *
- * @param status
- * @param statusString
- */
- public PKIStatusInfo(
- PKIStatus status,
- PKIFreeText statusString)
- {
- this.status = ASN1Integer.getInstance(status.toASN1Primitive());
- this.statusString = statusString;
- }
-
- public PKIStatusInfo(
- PKIStatus status,
- PKIFreeText statusString,
- PKIFailureInfo failInfo)
- {
- this.status = ASN1Integer.getInstance(status.toASN1Primitive());
- this.statusString = statusString;
- this.failInfo = failInfo;
- }
-
- public BigInteger getStatus()
- {
- return status.getValue();
- }
-
- public PKIFreeText getStatusString()
- {
- return statusString;
- }
-
- public DERBitString getFailInfo()
- {
- return failInfo;
- }
-
- /**
- * <pre>
- * PKIStatusInfo ::= SEQUENCE {
- * status PKIStatus, (INTEGER)
- * statusString PKIFreeText OPTIONAL,
- * failInfo PKIFailureInfo OPTIONAL (BIT STRING)
- * }
- *
- * PKIStatus:
- * granted (0), -- you got exactly what you asked for
- * grantedWithMods (1), -- you got something like what you asked for
- * rejection (2), -- you don't get it, more information elsewhere in the message
- * waiting (3), -- the request body part has not yet been processed, expect to hear more later
- * revocationWarning (4), -- this message contains a warning that a revocation is imminent
- * revocationNotification (5), -- notification that a revocation has occurred
- * keyUpdateWarning (6) -- update already done for the oldCertId specified in CertReqMsg
- *
- * PKIFailureInfo:
- * badAlg (0), -- unrecognized or unsupported Algorithm Identifier
- * badMessageCheck (1), -- integrity check failed (e.g., signature did not verify)
- * badRequest (2), -- transaction not permitted or supported
- * badTime (3), -- messageTime was not sufficiently close to the system time, as defined by local policy
- * badCertId (4), -- no certificate could be found matching the provided criteria
- * badDataFormat (5), -- the data submitted has the wrong format
- * wrongAuthority (6), -- the authority indicated in the request is different from the one creating the response token
- * incorrectData (7), -- the requester's data is incorrect (for notary services)
- * missingTimeStamp (8), -- when the timestamp is missing but should be there (by policy)
- * badPOP (9) -- the proof-of-possession failed
- *
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(status);
-
- if (statusString != null)
- {
- v.add(statusString);
- }
-
- if (failInfo!= null)
- {
- v.add(failInfo);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/POPODecKeyChallContent.java b/core/src/main/java/org/bouncycastle/asn1/cmp/POPODecKeyChallContent.java
deleted file mode 100644
index 22340687..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/POPODecKeyChallContent.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-
-public class POPODecKeyChallContent
- extends ASN1Object
-{
- private ASN1Sequence content;
-
- private POPODecKeyChallContent(ASN1Sequence seq)
- {
- content = seq;
- }
-
- public static POPODecKeyChallContent getInstance(Object o)
- {
- if (o instanceof POPODecKeyChallContent)
- {
- return (POPODecKeyChallContent)o;
- }
-
- if (o != null)
- {
- return new POPODecKeyChallContent(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public Challenge[] toChallengeArray()
- {
- Challenge[] result = new Challenge[content.size()];
-
- for (int i = 0; i != result.length; i++)
- {
- result[i] = Challenge.getInstance(content.getObjectAt(i));
- }
-
- return result;
- }
-
- /**
- * <pre>
- * POPODecKeyChallContent ::= SEQUENCE OF Challenge
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- return content;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/POPODecKeyRespContent.java b/core/src/main/java/org/bouncycastle/asn1/cmp/POPODecKeyRespContent.java
deleted file mode 100644
index 9c64db06..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/POPODecKeyRespContent.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-
-public class POPODecKeyRespContent
- extends ASN1Object
-{
- private ASN1Sequence content;
-
- private POPODecKeyRespContent(ASN1Sequence seq)
- {
- content = seq;
- }
-
- public static POPODecKeyRespContent getInstance(Object o)
- {
- if (o instanceof POPODecKeyRespContent)
- {
- return (POPODecKeyRespContent)o;
- }
-
- if (o != null)
- {
- return new POPODecKeyRespContent(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public ASN1Integer[] toASN1IntegerArray()
- {
- ASN1Integer[] result = new ASN1Integer[content.size()];
-
- for (int i = 0; i != result.length; i++)
- {
- result[i] = ASN1Integer.getInstance(content.getObjectAt(i));
- }
-
- return result;
- }
-
- /**
- * <pre>
- * POPODecKeyRespContent ::= SEQUENCE OF INTEGER
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- return content;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/PollRepContent.java b/core/src/main/java/org/bouncycastle/asn1/cmp/PollRepContent.java
deleted file mode 100644
index 95d5f82c..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/PollRepContent.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-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.DERSequence;
-
-public class PollRepContent
- extends ASN1Object
-{
- private ASN1Integer[] certReqId;
- private ASN1Integer[] checkAfter;
- private PKIFreeText[] reason;
-
- private PollRepContent(ASN1Sequence seq)
- {
- certReqId = new ASN1Integer[seq.size()];
- checkAfter = new ASN1Integer[seq.size()];
- reason = new PKIFreeText[seq.size()];
-
- for (int i = 0; i != seq.size(); i++)
- {
- ASN1Sequence s = ASN1Sequence.getInstance(seq.getObjectAt(i));
-
- certReqId[i] = ASN1Integer.getInstance(s.getObjectAt(0));
- checkAfter[i] = ASN1Integer.getInstance(s.getObjectAt(1));
-
- if (s.size() > 2)
- {
- reason[i] = PKIFreeText.getInstance(s.getObjectAt(2));
- }
- }
- }
-
- public static PollRepContent getInstance(Object o)
- {
- if (o instanceof PollRepContent)
- {
- return (PollRepContent)o;
- }
-
- if (o != null)
- {
- return new PollRepContent(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public PollRepContent(ASN1Integer certReqId, ASN1Integer checkAfter)
- {
- this(certReqId, checkAfter, null);
- }
-
- public PollRepContent(ASN1Integer certReqId, ASN1Integer checkAfter, PKIFreeText reason)
- {
- this.certReqId = new ASN1Integer[1];
- this.checkAfter = new ASN1Integer[1];
- this.reason = new PKIFreeText[1];
-
- this.certReqId[0] = certReqId;
- this.checkAfter[0] = checkAfter;
- this.reason[0] = reason;
- }
-
- public int size()
- {
- return certReqId.length;
- }
-
- public ASN1Integer getCertReqId(int index)
- {
- return certReqId[index];
- }
-
- public ASN1Integer getCheckAfter(int index)
- {
- return checkAfter[index];
- }
-
- public PKIFreeText getReason(int index)
- {
- return reason[index];
- }
-
- /**
- * <pre>
- * PollRepContent ::= SEQUENCE OF SEQUENCE {
- * certReqId INTEGER,
- * checkAfter INTEGER, -- time in seconds
- * reason PKIFreeText OPTIONAL
- * }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector outer = new ASN1EncodableVector();
-
- for (int i = 0; i != certReqId.length; i++)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(certReqId[i]);
- v.add(checkAfter[i]);
-
- if (reason[i] != null)
- {
- v.add(reason[i]);
- }
-
- outer.add(new DERSequence(v));
- }
-
- return new DERSequence(outer);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/PollReqContent.java b/core/src/main/java/org/bouncycastle/asn1/cmp/PollReqContent.java
deleted file mode 100644
index de059c5c..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/PollReqContent.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-public class PollReqContent
- extends ASN1Object
-{
- private ASN1Sequence content;
-
- private PollReqContent(ASN1Sequence seq)
- {
- content = seq;
- }
-
- public static PollReqContent getInstance(Object o)
- {
- if (o instanceof PollReqContent)
- {
- return (PollReqContent)o;
- }
-
- if (o != null)
- {
- return new PollReqContent(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- /**
- * Create a pollReqContent for a single certReqId.
- *
- * @param certReqId the certificate request ID.
- */
- public PollReqContent(ASN1Integer certReqId)
- {
- this(new DERSequence(new DERSequence(certReqId)));
- }
-
- public ASN1Integer[][] getCertReqIds()
- {
- ASN1Integer[][] result = new ASN1Integer[content.size()][];
-
- for (int i = 0; i != result.length; i++)
- {
- result[i] = sequenceToASN1IntegerArray((ASN1Sequence)content.getObjectAt(i));
- }
-
- return result;
- }
-
- private static ASN1Integer[] sequenceToASN1IntegerArray(ASN1Sequence seq)
- {
- ASN1Integer[] result = new ASN1Integer[seq.size()];
-
- for (int i = 0; i != result.length; i++)
- {
- result[i] = ASN1Integer.getInstance(seq.getObjectAt(i));
- }
-
- return result;
- }
-
- /**
- * <pre>
- * PollReqContent ::= SEQUENCE OF SEQUENCE {
- * certReqId INTEGER
- * }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- return content;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/ProtectedPart.java b/core/src/main/java/org/bouncycastle/asn1/cmp/ProtectedPart.java
deleted file mode 100644
index 38e4fb80..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/ProtectedPart.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-public class ProtectedPart
- extends ASN1Object
-{
- private PKIHeader header;
- private PKIBody body;
-
- private ProtectedPart(ASN1Sequence seq)
- {
- header = PKIHeader.getInstance(seq.getObjectAt(0));
- body = PKIBody.getInstance(seq.getObjectAt(1));
- }
-
- public static ProtectedPart getInstance(Object o)
- {
- if (o instanceof ProtectedPart)
- {
- return (ProtectedPart)o;
- }
-
- if (o != null)
- {
- return new ProtectedPart(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public ProtectedPart(PKIHeader header, PKIBody body)
- {
- this.header = header;
- this.body = body;
- }
-
- public PKIHeader getHeader()
- {
- return header;
- }
-
- public PKIBody getBody()
- {
- return body;
- }
-
- /**
- * <pre>
- * ProtectedPart ::= SEQUENCE {
- * header PKIHeader,
- * body PKIBody
- * }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(header);
- v.add(body);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/RevAnnContent.java b/core/src/main/java/org/bouncycastle/asn1/cmp/RevAnnContent.java
deleted file mode 100644
index 36b4621b..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/RevAnnContent.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.crmf.CertId;
-import org.bouncycastle.asn1.x509.Extensions;
-
-public class RevAnnContent
- extends ASN1Object
-{
- private PKIStatus status;
- private CertId certId;
- private ASN1GeneralizedTime willBeRevokedAt;
- private ASN1GeneralizedTime badSinceDate;
- private Extensions crlDetails;
-
- private RevAnnContent(ASN1Sequence seq)
- {
- status = PKIStatus.getInstance(seq.getObjectAt(0));
- certId = CertId.getInstance(seq.getObjectAt(1));
- willBeRevokedAt = ASN1GeneralizedTime.getInstance(seq.getObjectAt(2));
- badSinceDate = ASN1GeneralizedTime.getInstance(seq.getObjectAt(3));
-
- if (seq.size() > 4)
- {
- crlDetails = Extensions.getInstance(seq.getObjectAt(4));
- }
- }
-
- public static RevAnnContent getInstance(Object o)
- {
- if (o instanceof RevAnnContent)
- {
- return (RevAnnContent)o;
- }
-
- if (o != null)
- {
- return new RevAnnContent(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public PKIStatus getStatus()
- {
- return status;
- }
-
- public CertId getCertId()
- {
- return certId;
- }
-
- public ASN1GeneralizedTime getWillBeRevokedAt()
- {
- return willBeRevokedAt;
- }
-
- public ASN1GeneralizedTime getBadSinceDate()
- {
- return badSinceDate;
- }
-
- public Extensions getCrlDetails()
- {
- return crlDetails;
- }
-
- /**
- * <pre>
- * RevAnnContent ::= SEQUENCE {
- * status PKIStatus,
- * certId CertId,
- * willBeRevokedAt GeneralizedTime,
- * badSinceDate GeneralizedTime,
- * crlDetails Extensions OPTIONAL
- * -- extra CRL details (e.g., crl number, reason, location, etc.)
- * }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(status);
- v.add(certId);
- v.add(willBeRevokedAt);
- v.add(badSinceDate);
-
- if (crlDetails != null)
- {
- v.add(crlDetails);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/RevDetails.java b/core/src/main/java/org/bouncycastle/asn1/cmp/RevDetails.java
deleted file mode 100644
index 3d9eb712..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/RevDetails.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.crmf.CertTemplate;
-import org.bouncycastle.asn1.x509.Extensions;
-import org.bouncycastle.asn1.x509.X509Extensions;
-
-public class RevDetails
- extends ASN1Object
-{
- private CertTemplate certDetails;
- private Extensions crlEntryDetails;
-
- private RevDetails(ASN1Sequence seq)
- {
- certDetails = CertTemplate.getInstance(seq.getObjectAt(0));
- if (seq.size() > 1)
- {
- crlEntryDetails = Extensions.getInstance(seq.getObjectAt(1));
- }
- }
-
- public static RevDetails getInstance(Object o)
- {
- if (o instanceof RevDetails)
- {
- return (RevDetails)o;
- }
-
- if (o != null)
- {
- return new RevDetails(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public RevDetails(CertTemplate certDetails)
- {
- this.certDetails = certDetails;
- }
-
- /**
- * @deprecated use method taking Extensions
- * @param certDetails
- * @param crlEntryDetails
- */
- public RevDetails(CertTemplate certDetails, X509Extensions crlEntryDetails)
- {
- this.certDetails = certDetails;
- this.crlEntryDetails = Extensions.getInstance(crlEntryDetails.toASN1Primitive());
- }
-
- public RevDetails(CertTemplate certDetails, Extensions crlEntryDetails)
- {
- this.certDetails = certDetails;
- this.crlEntryDetails = crlEntryDetails;
- }
-
- public CertTemplate getCertDetails()
- {
- return certDetails;
- }
-
- public Extensions getCrlEntryDetails()
- {
- return crlEntryDetails;
- }
-
- /**
- * <pre>
- * RevDetails ::= SEQUENCE {
- * certDetails CertTemplate,
- * -- allows requester to specify as much as they can about
- * -- the cert. for which revocation is requested
- * -- (e.g., for cases in which serialNumber is not available)
- * crlEntryDetails Extensions OPTIONAL
- * -- requested crlEntryExtensions
- * }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(certDetails);
-
- if (crlEntryDetails != null)
- {
- v.add(crlEntryDetails);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/RevRepContent.java b/core/src/main/java/org/bouncycastle/asn1/cmp/RevRepContent.java
deleted file mode 100644
index 5cbb8e67..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/RevRepContent.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.crmf.CertId;
-import org.bouncycastle.asn1.x509.CertificateList;
-
-public class RevRepContent
- extends ASN1Object
-{
- private ASN1Sequence status;
- private ASN1Sequence revCerts;
- private ASN1Sequence crls;
-
- private RevRepContent(ASN1Sequence seq)
- {
- Enumeration en = seq.getObjects();
-
- status = ASN1Sequence.getInstance(en.nextElement());
- while (en.hasMoreElements())
- {
- ASN1TaggedObject tObj = ASN1TaggedObject.getInstance(en.nextElement());
-
- if (tObj.getTagNo() == 0)
- {
- revCerts = ASN1Sequence.getInstance(tObj, true);
- }
- else
- {
- crls = ASN1Sequence.getInstance(tObj, true);
- }
- }
- }
-
- public static RevRepContent getInstance(Object o)
- {
- if (o instanceof RevRepContent)
- {
- return (RevRepContent)o;
- }
-
- if (o != null)
- {
- return new RevRepContent(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public PKIStatusInfo[] getStatus()
- {
- PKIStatusInfo[] results = new PKIStatusInfo[status.size()];
-
- for (int i = 0; i != results.length; i++)
- {
- results[i] = PKIStatusInfo.getInstance(status.getObjectAt(i));
- }
-
- return results;
- }
-
- public CertId[] getRevCerts()
- {
- if (revCerts == null)
- {
- return null;
- }
-
- CertId[] results = new CertId[revCerts.size()];
-
- for (int i = 0; i != results.length; i++)
- {
- results[i] = CertId.getInstance(revCerts.getObjectAt(i));
- }
-
- return results;
- }
-
- public CertificateList[] getCrls()
- {
- if (crls == null)
- {
- return null;
- }
-
- CertificateList[] results = new CertificateList[crls.size()];
-
- for (int i = 0; i != results.length; i++)
- {
- results[i] = CertificateList.getInstance(crls.getObjectAt(i));
- }
-
- return results;
- }
-
- /**
- * <pre>
- * RevRepContent ::= SEQUENCE {
- * status SEQUENCE SIZE (1..MAX) OF PKIStatusInfo,
- * -- in same order as was sent in RevReqContent
- * revCerts [0] SEQUENCE SIZE (1..MAX) OF CertId OPTIONAL,
- * -- IDs for which revocation was requested
- * -- (same order as status)
- * crls [1] SEQUENCE SIZE (1..MAX) OF CertificateList OPTIONAL
- * -- the resulting CRLs (there may be more than one)
- * }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(status);
-
- addOptional(v, 0, revCerts);
- addOptional(v, 1, crls);
-
- return new DERSequence(v);
- }
-
- private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj)
- {
- if (obj != null)
- {
- v.add(new DERTaggedObject(true, tagNo, obj));
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/RevRepContentBuilder.java b/core/src/main/java/org/bouncycastle/asn1/cmp/RevRepContentBuilder.java
deleted file mode 100644
index 10522c2f..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/RevRepContentBuilder.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.crmf.CertId;
-import org.bouncycastle.asn1.x509.CertificateList;
-
-public class RevRepContentBuilder
-{
- private ASN1EncodableVector status = new ASN1EncodableVector();
- private ASN1EncodableVector revCerts = new ASN1EncodableVector();
- private ASN1EncodableVector crls = new ASN1EncodableVector();
-
- public RevRepContentBuilder add(PKIStatusInfo status)
- {
- this.status.add(status);
-
- return this;
- }
-
- public RevRepContentBuilder add(PKIStatusInfo status, CertId certId)
- {
- if (this.status.size() != this.revCerts.size())
- {
- throw new IllegalStateException("status and revCerts sequence must be in common order");
- }
- this.status.add(status);
- this.revCerts.add(certId);
-
- return this;
- }
-
- public RevRepContentBuilder addCrl(CertificateList crl)
- {
- this.crls.add(crl);
-
- return this;
- }
-
- public RevRepContent build()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(new DERSequence(status));
-
- if (revCerts.size() != 0)
- {
- v.add(new DERTaggedObject(true, 0, new DERSequence(revCerts)));
- }
-
- if (crls.size() != 0)
- {
- v.add(new DERTaggedObject(true, 1, new DERSequence(crls)));
- }
-
- return RevRepContent.getInstance(new DERSequence(v));
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cmp/RevReqContent.java b/core/src/main/java/org/bouncycastle/asn1/cmp/RevReqContent.java
deleted file mode 100644
index 468be4ef..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cmp/RevReqContent.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package org.bouncycastle.asn1.cmp;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-public class RevReqContent
- extends ASN1Object
-{
- private ASN1Sequence content;
-
- private RevReqContent(ASN1Sequence seq)
- {
- content = seq;
- }
-
- public static RevReqContent getInstance(Object o)
- {
- if (o instanceof RevReqContent)
- {
- return (RevReqContent)o;
- }
-
- if (o != null)
- {
- return new RevReqContent(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public RevReqContent(RevDetails revDetails)
- {
- this.content = new DERSequence(revDetails);
- }
-
- public RevReqContent(RevDetails[] revDetailsArray)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- for (int i = 0; i != revDetailsArray.length; i++)
- {
- v.add(revDetailsArray[i]);
- }
-
- this.content = new DERSequence(v);
- }
-
- public RevDetails[] toRevDetailsArray()
- {
- RevDetails[] result = new RevDetails[content.size()];
-
- for (int i = 0; i != result.length; i++)
- {
- result[i] = RevDetails.getInstance(content.getObjectAt(i));
- }
-
- return result;
- }
-
- /**
- * <pre>
- * RevReqContent ::= SEQUENCE OF RevDetails
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- return content;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/Attribute.java b/core/src/main/java/org/bouncycastle/asn1/cms/Attribute.java
deleted file mode 100644
index 8c487433..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/Attribute.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Set;
-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
-{
- private ASN1ObjectIdentifier attrType;
- private ASN1Set attrValues;
-
- /**
- * 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.
- */
- public static Attribute getInstance(
- Object o)
- {
- if (o instanceof Attribute)
- {
- return (Attribute)o;
- }
-
- if (o != null)
- {
- return new Attribute(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- private Attribute(
- ASN1Sequence seq)
- {
- attrType = (ASN1ObjectIdentifier)seq.getObjectAt(0);
- attrValues = (ASN1Set)seq.getObjectAt(1);
- }
-
- public Attribute(
- ASN1ObjectIdentifier attrType,
- ASN1Set attrValues)
- {
- this.attrType = attrType;
- this.attrValues = attrValues;
- }
-
- public ASN1ObjectIdentifier getAttrType()
- {
- return attrType;
- }
-
- public ASN1Set getAttrValues()
- {
- return attrValues;
- }
-
- public ASN1Encodable[] getAttributeValues()
- {
- return attrValues.toArray();
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(attrType);
- v.add(attrValues);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/AttributeTable.java b/core/src/main/java/org/bouncycastle/asn1/cms/AttributeTable.java
deleted file mode 100644
index 3b8e0bed..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/AttributeTable.java
+++ /dev/null
@@ -1,240 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.DERSet;
-
-/**
- * This is helper tool to construct {@link Attributes} sets.
- */
-public class AttributeTable
-{
- private Hashtable attributes = new Hashtable();
-
- public AttributeTable(
- Hashtable attrs)
- {
- attributes = copyTable(attrs);
- }
-
- public AttributeTable(
- ASN1EncodableVector v)
- {
- for (int i = 0; i != v.size(); i++)
- {
- Attribute a = Attribute.getInstance(v.get(i));
-
- addAttribute(a.getAttrType(), a);
- }
- }
-
- public AttributeTable(
- ASN1Set s)
- {
- for (int i = 0; i != s.size(); i++)
- {
- Attribute a = Attribute.getInstance(s.getObjectAt(i));
-
- addAttribute(a.getAttrType(), a);
- }
- }
-
- public AttributeTable(
- Attribute attr)
- {
- addAttribute(attr.getAttrType(), attr);
- }
-
- public AttributeTable(
- Attributes attrs)
- {
- this(ASN1Set.getInstance(attrs.toASN1Primitive()));
- }
-
- private void addAttribute(
- ASN1ObjectIdentifier oid,
- Attribute a)
- {
- Object value = attributes.get(oid);
-
- if (value == null)
- {
- attributes.put(oid, a);
- }
- else
- {
- Vector v;
-
- if (value instanceof Attribute)
- {
- v = new Vector();
-
- v.addElement(value);
- v.addElement(a);
- }
- else
- {
- v = (Vector)value;
-
- v.addElement(a);
- }
-
- attributes.put(oid, v);
- }
- }
-
- /**
- * Return the first attribute matching the OBJECT IDENTIFIER oid.
- *
- * @param oid type of attribute required.
- * @return first attribute found of type oid.
- */
- public Attribute get(
- ASN1ObjectIdentifier oid)
- {
- Object value = attributes.get(oid);
-
- if (value instanceof Vector)
- {
- return (Attribute)((Vector)value).elementAt(0);
- }
-
- return (Attribute)value;
- }
-
- /**
- * Return all the attributes matching the OBJECT IDENTIFIER oid. The vector will be
- * empty if there are no attributes of the required type present.
- *
- * @param oid type of attribute required.
- * @return a vector of all the attributes found of type oid.
- */
- public ASN1EncodableVector getAll(
- ASN1ObjectIdentifier oid)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- Object value = attributes.get(oid);
-
- if (value instanceof Vector)
- {
- Enumeration e = ((Vector)value).elements();
-
- while (e.hasMoreElements())
- {
- v.add((Attribute)e.nextElement());
- }
- }
- else if (value != null)
- {
- v.add((Attribute)value);
- }
-
- return v;
- }
-
- public int size()
- {
- int size = 0;
-
- for (Enumeration en = attributes.elements(); en.hasMoreElements();)
- {
- Object o = en.nextElement();
-
- if (o instanceof Vector)
- {
- size += ((Vector)o).size();
- }
- else
- {
- size++;
- }
- }
-
- return size;
- }
-
- public Hashtable toHashtable()
- {
- return copyTable(attributes);
- }
-
- public ASN1EncodableVector toASN1EncodableVector()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- Enumeration e = attributes.elements();
-
- while (e.hasMoreElements())
- {
- Object value = e.nextElement();
-
- if (value instanceof Vector)
- {
- Enumeration en = ((Vector)value).elements();
-
- while (en.hasMoreElements())
- {
- v.add(Attribute.getInstance(en.nextElement()));
- }
- }
- else
- {
- v.add(Attribute.getInstance(value));
- }
- }
-
- return v;
- }
-
- public Attributes toASN1Structure()
- {
- return new Attributes(this.toASN1EncodableVector());
- }
-
- private Hashtable copyTable(
- Hashtable in)
- {
- Hashtable out = new Hashtable();
- Enumeration e = in.keys();
-
- while (e.hasMoreElements())
- {
- Object key = e.nextElement();
-
- out.put(key, in.get(key));
- }
-
- return out;
- }
-
- /**
- * Return a new table with the passed in attribute added.
- *
- * @param attrType
- * @param attrValue
- * @return
- */
- public AttributeTable add(ASN1ObjectIdentifier attrType, ASN1Encodable attrValue)
- {
- AttributeTable newTable = new AttributeTable(attributes);
-
- newTable.addAttribute(attrType, new Attribute(attrType, new DERSet(attrValue)));
-
- return newTable;
- }
-
- public AttributeTable remove(ASN1ObjectIdentifier attrType)
- {
- AttributeTable newTable = new AttributeTable(attributes);
-
- newTable.attributes.remove(attrType);
-
- return newTable;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/Attributes.java b/core/src/main/java/org/bouncycastle/asn1/cms/Attributes.java
deleted file mode 100644
index e21c8a7b..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/Attributes.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-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
-{
- private ASN1Set attributes;
-
- private Attributes(ASN1Set set)
- {
- attributes = set;
- }
-
- public Attributes(ASN1EncodableVector v)
- {
- 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)
- {
- return (Attributes)obj;
- }
- else if (obj != null)
- {
- return new Attributes(ASN1Set.getInstance(obj));
- }
-
- return null;
- }
-
- public Attribute[] getAttributes()
- {
- Attribute[] rv = new Attribute[attributes.size()];
-
- for (int i = 0; i != rv.length; i++)
- {
- rv[i] = Attribute.getInstance(attributes.getObjectAt(i));
- }
-
- return rv;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- return attributes;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedData.java b/core/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedData.java
deleted file mode 100644
index 034753fd..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedData.java
+++ /dev/null
@@ -1,248 +0,0 @@
-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.ASN1Set;
-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
-{
- private ASN1Integer version;
- private OriginatorInfo originatorInfo;
- private ASN1Set recipientInfos;
- private EncryptedContentInfo authEncryptedContentInfo;
- private ASN1Set authAttrs;
- private ASN1OctetString mac;
- private ASN1Set unauthAttrs;
-
- public AuthEnvelopedData(
- OriginatorInfo originatorInfo,
- ASN1Set recipientInfos,
- EncryptedContentInfo authEncryptedContentInfo,
- ASN1Set authAttrs,
- ASN1OctetString mac,
- ASN1Set unauthAttrs)
- {
- // "It MUST be set to 0."
- this.version = new ASN1Integer(0);
-
- this.originatorInfo = originatorInfo;
-
- // TODO
- // "There MUST be at least one element in the collection."
- this.recipientInfos = recipientInfos;
-
- this.authEncryptedContentInfo = authEncryptedContentInfo;
-
- // TODO
- // "The authAttrs MUST be present if the content type carried in
- // EncryptedContentInfo is not id-data."
- this.authAttrs = authAttrs;
-
- this.mac = mac;
-
- this.unauthAttrs = unauthAttrs;
- }
-
- /**
- * Constructs AuthEnvelopedData by parsing supplied ASN1Sequence
- * <p>
- * @param seq An ASN1Sequence with AuthEnvelopedData
- * @deprecated use getInstance().
- */
- public AuthEnvelopedData(
- ASN1Sequence seq)
- {
- int index = 0;
-
- // TODO
- // "It MUST be set to 0."
- ASN1Primitive tmp = seq.getObjectAt(index++).toASN1Primitive();
- version = (ASN1Integer)tmp;
-
- tmp = seq.getObjectAt(index++).toASN1Primitive();
- if (tmp instanceof ASN1TaggedObject)
- {
- originatorInfo = OriginatorInfo.getInstance((ASN1TaggedObject)tmp, false);
- tmp = seq.getObjectAt(index++).toASN1Primitive();
- }
-
- // TODO
- // "There MUST be at least one element in the collection."
- recipientInfos = ASN1Set.getInstance(tmp);
-
- tmp = seq.getObjectAt(index++).toASN1Primitive();
- authEncryptedContentInfo = EncryptedContentInfo.getInstance(tmp);
-
- tmp = seq.getObjectAt(index++).toASN1Primitive();
- if (tmp instanceof ASN1TaggedObject)
- {
- authAttrs = ASN1Set.getInstance((ASN1TaggedObject)tmp, false);
- tmp = seq.getObjectAt(index++).toASN1Primitive();
- }
- else
- {
- // TODO
- // "The authAttrs MUST be present if the content type carried in
- // EncryptedContentInfo is not id-data."
- }
-
- mac = ASN1OctetString.getInstance(tmp);
-
- if (seq.size() > index)
- {
- tmp = seq.getObjectAt(index++).toASN1Primitive();
- unauthAttrs = ASN1Set.getInstance((ASN1TaggedObject)tmp, false);
- }
- }
-
- /**
- * 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.
- * @throws IllegalArgumentException if the object held by the
- * tagged object cannot be converted.
- */
- public static AuthEnvelopedData getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- /**
- * 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, or was null.
- */
- public static AuthEnvelopedData getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof AuthEnvelopedData)
- {
- return (AuthEnvelopedData)obj;
- }
-
- if (obj instanceof ASN1Sequence)
- {
- return new AuthEnvelopedData((ASN1Sequence)obj);
- }
-
- throw new IllegalArgumentException("Invalid AuthEnvelopedData: " + obj.getClass().getName());
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public OriginatorInfo getOriginatorInfo()
- {
- return originatorInfo;
- }
-
- public ASN1Set getRecipientInfos()
- {
- return recipientInfos;
- }
-
- public EncryptedContentInfo getAuthEncryptedContentInfo()
- {
- return authEncryptedContentInfo;
- }
-
- public ASN1Set getAuthAttrs()
- {
- return authAttrs;
- }
-
- public ASN1OctetString getMac()
- {
- return mac;
- }
-
- public ASN1Set getUnauthAttrs()
- {
- return unauthAttrs;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(version);
-
- if (originatorInfo != null)
- {
- v.add(new DERTaggedObject(false, 0, originatorInfo));
- }
-
- v.add(recipientInfos);
- v.add(authEncryptedContentInfo);
-
- // "authAttrs optionally contains the authenticated attributes."
- if (authAttrs != null)
- {
- // "AuthAttributes MUST be DER encoded, even if the rest of the
- // AuthEnvelopedData structure is BER encoded."
- v.add(new DERTaggedObject(false, 1, authAttrs));
- }
-
- v.add(mac);
-
- // "unauthAttrs optionally contains the unauthenticated attributes."
- if (unauthAttrs != null)
- {
- v.add(new DERTaggedObject(false, 2, unauthAttrs));
- }
-
- return new BERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedDataParser.java b/core/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedDataParser.java
deleted file mode 100644
index 8460c333..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedDataParser.java
+++ /dev/null
@@ -1,157 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1SequenceParser;
-import org.bouncycastle.asn1.ASN1SetParser;
-import org.bouncycastle.asn1.ASN1TaggedObjectParser;
-import org.bouncycastle.asn1.BERTags;
-
-/**
- * Parse {@link AuthEnvelopedData} input stream.
- *
- * <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 class AuthEnvelopedDataParser
-{
- private ASN1SequenceParser seq;
- private ASN1Integer version;
- private ASN1Encodable nextObject;
- private boolean originatorInfoCalled;
-
- public AuthEnvelopedDataParser(ASN1SequenceParser seq) throws IOException
- {
- this.seq = seq;
-
- // TODO
- // "It MUST be set to 0."
- this.version = ASN1Integer.getInstance(seq.readObject());
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public OriginatorInfo getOriginatorInfo()
- throws IOException
- {
- originatorInfoCalled = true;
-
- if (nextObject == null)
- {
- nextObject = seq.readObject();
- }
-
- if (nextObject instanceof ASN1TaggedObjectParser && ((ASN1TaggedObjectParser)nextObject).getTagNo() == 0)
- {
- ASN1SequenceParser originatorInfo = (ASN1SequenceParser) ((ASN1TaggedObjectParser)nextObject).getObjectParser(BERTags.SEQUENCE, false);
- nextObject = null;
- return OriginatorInfo.getInstance(originatorInfo.toASN1Primitive());
- }
-
- return null;
- }
-
- public ASN1SetParser getRecipientInfos()
- throws IOException
- {
- if (!originatorInfoCalled)
- {
- getOriginatorInfo();
- }
-
- if (nextObject == null)
- {
- nextObject = seq.readObject();
- }
-
- ASN1SetParser recipientInfos = (ASN1SetParser)nextObject;
- nextObject = null;
- return recipientInfos;
- }
-
- public EncryptedContentInfoParser getAuthEncryptedContentInfo()
- throws IOException
- {
- if (nextObject == null)
- {
- nextObject = seq.readObject();
- }
-
- if (nextObject != null)
- {
- ASN1SequenceParser o = (ASN1SequenceParser) nextObject;
- nextObject = null;
- return new EncryptedContentInfoParser(o);
- }
-
- return null;
- }
-
- public ASN1SetParser getAuthAttrs()
- throws IOException
- {
- if (nextObject == null)
- {
- nextObject = seq.readObject();
- }
-
- if (nextObject instanceof ASN1TaggedObjectParser)
- {
- ASN1Encodable o = nextObject;
- nextObject = null;
- return (ASN1SetParser)((ASN1TaggedObjectParser)o).getObjectParser(BERTags.SET, false);
- }
-
- // TODO
- // "The authAttrs MUST be present if the content type carried in
- // EncryptedContentInfo is not id-data."
-
- return null;
- }
-
- public ASN1OctetString getMac()
- throws IOException
- {
- if (nextObject == null)
- {
- nextObject = seq.readObject();
- }
-
- ASN1Encodable o = nextObject;
- nextObject = null;
-
- return ASN1OctetString.getInstance(o.toASN1Primitive());
- }
-
- public ASN1SetParser getUnauthAttrs()
- throws IOException
- {
- if (nextObject == null)
- {
- nextObject = seq.readObject();
- }
-
- if (nextObject != null)
- {
- ASN1Encodable o = nextObject;
- nextObject = null;
- return (ASN1SetParser)((ASN1TaggedObjectParser)o).getObjectParser(BERTags.SET, false);
- }
-
- return null;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedData.java b/core/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedData.java
deleted file mode 100644
index c0945f3f..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedData.java
+++ /dev/null
@@ -1,312 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import java.util.Enumeration;
-
-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.ASN1Set;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-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
-{
- private ASN1Integer version;
- private OriginatorInfo originatorInfo;
- private ASN1Set recipientInfos;
- private AlgorithmIdentifier macAlgorithm;
- private AlgorithmIdentifier digestAlgorithm;
- private ContentInfo encapsulatedContentInfo;
- private ASN1Set authAttrs;
- private ASN1OctetString mac;
- private ASN1Set unauthAttrs;
-
- public AuthenticatedData(
- OriginatorInfo originatorInfo,
- ASN1Set recipientInfos,
- AlgorithmIdentifier macAlgorithm,
- AlgorithmIdentifier digestAlgorithm,
- ContentInfo encapsulatedContent,
- ASN1Set authAttrs,
- ASN1OctetString mac,
- ASN1Set unauthAttrs)
- {
- if (digestAlgorithm != null || authAttrs != null)
- {
- if (digestAlgorithm == null || authAttrs == null)
- {
- throw new IllegalArgumentException("digestAlgorithm and authAttrs must be set together");
- }
- }
-
- version = new ASN1Integer(calculateVersion(originatorInfo));
-
- this.originatorInfo = originatorInfo;
- this.macAlgorithm = macAlgorithm;
- this.digestAlgorithm = digestAlgorithm;
- this.recipientInfos = recipientInfos;
- this.encapsulatedContentInfo = encapsulatedContent;
- this.authAttrs = authAttrs;
- this.mac = mac;
- this.unauthAttrs = unauthAttrs;
- }
-
- /**
- * @deprecated use getInstance()
- */
- public AuthenticatedData(
- ASN1Sequence seq)
- {
- int index = 0;
-
- version = (ASN1Integer)seq.getObjectAt(index++);
-
- Object tmp = seq.getObjectAt(index++);
-
- if (tmp instanceof ASN1TaggedObject)
- {
- originatorInfo = OriginatorInfo.getInstance((ASN1TaggedObject)tmp, false);
- tmp = seq.getObjectAt(index++);
- }
-
- recipientInfos = ASN1Set.getInstance(tmp);
- macAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(index++));
-
- tmp = seq.getObjectAt(index++);
-
- if (tmp instanceof ASN1TaggedObject)
- {
- digestAlgorithm = AlgorithmIdentifier.getInstance((ASN1TaggedObject)tmp, false);
- tmp = seq.getObjectAt(index++);
- }
-
- encapsulatedContentInfo = ContentInfo.getInstance(tmp);
-
- tmp = seq.getObjectAt(index++);
-
- if (tmp instanceof ASN1TaggedObject)
- {
- authAttrs = ASN1Set.getInstance((ASN1TaggedObject)tmp, false);
- tmp = seq.getObjectAt(index++);
- }
-
- mac = ASN1OctetString.getInstance(tmp);
-
- if (seq.size() > index)
- {
- unauthAttrs = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(index), false);
- }
- }
-
- /**
- * 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
- * tagged false otherwise.
- * @throws IllegalArgumentException if the object held by the
- * tagged object cannot be converted.
- */
- public static AuthenticatedData getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- /**
- * 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.
- */
- public static AuthenticatedData getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof AuthenticatedData)
- {
- return (AuthenticatedData)obj;
- }
-
- if (obj instanceof ASN1Sequence)
- {
- return new AuthenticatedData((ASN1Sequence)obj);
- }
-
- throw new IllegalArgumentException("Invalid AuthenticatedData: " + obj.getClass().getName());
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public OriginatorInfo getOriginatorInfo()
- {
- return originatorInfo;
- }
-
- public ASN1Set getRecipientInfos()
- {
- return recipientInfos;
- }
-
- public AlgorithmIdentifier getMacAlgorithm()
- {
- return macAlgorithm;
- }
-
- public AlgorithmIdentifier getDigestAlgorithm()
- {
- return digestAlgorithm;
- }
-
- public ContentInfo getEncapsulatedContentInfo()
- {
- return encapsulatedContentInfo;
- }
-
- public ASN1Set getAuthAttrs()
- {
- return authAttrs;
- }
-
- public ASN1OctetString getMac()
- {
- return mac;
- }
-
- public ASN1Set getUnauthAttrs()
- {
- return unauthAttrs;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(version);
-
- if (originatorInfo != null)
- {
- v.add(new DERTaggedObject(false, 0, originatorInfo));
- }
-
- v.add(recipientInfos);
- v.add(macAlgorithm);
-
- if (digestAlgorithm != null)
- {
- v.add(new DERTaggedObject(false, 1, digestAlgorithm));
- }
-
- v.add(encapsulatedContentInfo);
-
- if (authAttrs != null)
- {
- v.add(new DERTaggedObject(false, 2, authAttrs));
- }
-
- v.add(mac);
-
- if (unauthAttrs != null)
- {
- v.add(new DERTaggedObject(false, 3, unauthAttrs));
- }
-
- return new BERSequence(v);
- }
-
- public static int calculateVersion(OriginatorInfo origInfo)
- {
- if (origInfo == null)
- {
- return 0;
- }
- else
- {
- int ver = 0;
-
- for (Enumeration e = origInfo.getCertificates().getObjects(); e.hasMoreElements();)
- {
- Object obj = e.nextElement();
-
- if (obj instanceof ASN1TaggedObject)
- {
- ASN1TaggedObject tag = (ASN1TaggedObject)obj;
-
- if (tag.getTagNo() == 2)
- {
- ver = 1;
- }
- else if (tag.getTagNo() == 3)
- {
- ver = 3;
- break;
- }
- }
- }
-
- if (origInfo.getCRLs() != null)
- {
- for (Enumeration e = origInfo.getCRLs().getObjects(); e.hasMoreElements();)
- {
- Object obj = e.nextElement();
-
- if (obj instanceof ASN1TaggedObject)
- {
- ASN1TaggedObject tag = (ASN1TaggedObject)obj;
-
- if (tag.getTagNo() == 1)
- {
- ver = 3;
- break;
- }
- }
- }
- }
-
- return ver;
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedDataParser.java b/core/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedDataParser.java
deleted file mode 100644
index ce9aa4f2..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedDataParser.java
+++ /dev/null
@@ -1,206 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1SequenceParser;
-import org.bouncycastle.asn1.ASN1SetParser;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.ASN1TaggedObjectParser;
-import org.bouncycastle.asn1.BERTags;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-/**
- * Parse {@link AuthenticatedData} stream.
- * <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 AuthenticatedDataParser
-{
- private ASN1SequenceParser seq;
- private ASN1Integer version;
- private ASN1Encodable nextObject;
- private boolean originatorInfoCalled;
-
- public AuthenticatedDataParser(
- ASN1SequenceParser seq)
- throws IOException
- {
- this.seq = seq;
- this.version = ASN1Integer.getInstance(seq.readObject());
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public OriginatorInfo getOriginatorInfo()
- throws IOException
- {
- originatorInfoCalled = true;
-
- if (nextObject == null)
- {
- nextObject = seq.readObject();
- }
-
- if (nextObject instanceof ASN1TaggedObjectParser && ((ASN1TaggedObjectParser)nextObject).getTagNo() == 0)
- {
- ASN1SequenceParser originatorInfo = (ASN1SequenceParser) ((ASN1TaggedObjectParser)nextObject).getObjectParser(BERTags.SEQUENCE, false);
- nextObject = null;
- return OriginatorInfo.getInstance(originatorInfo.toASN1Primitive());
- }
-
- return null;
- }
-
- public ASN1SetParser getRecipientInfos()
- throws IOException
- {
- if (!originatorInfoCalled)
- {
- getOriginatorInfo();
- }
-
- if (nextObject == null)
- {
- nextObject = seq.readObject();
- }
-
- ASN1SetParser recipientInfos = (ASN1SetParser)nextObject;
- nextObject = null;
- return recipientInfos;
- }
-
- public AlgorithmIdentifier getMacAlgorithm()
- throws IOException
- {
- if (nextObject == null)
- {
- nextObject = seq.readObject();
- }
-
- if (nextObject != null)
- {
- ASN1SequenceParser o = (ASN1SequenceParser)nextObject;
- nextObject = null;
- return AlgorithmIdentifier.getInstance(o.toASN1Primitive());
- }
-
- return null;
- }
-
- public AlgorithmIdentifier getDigestAlgorithm()
- throws IOException
- {
- if (nextObject == null)
- {
- nextObject = seq.readObject();
- }
-
- if (nextObject instanceof ASN1TaggedObjectParser)
- {
- AlgorithmIdentifier obj = AlgorithmIdentifier.getInstance((ASN1TaggedObject)nextObject.toASN1Primitive(), false);
- nextObject = null;
- return obj;
- }
-
- return null;
- }
-
- /**
- * @deprecated use getEncapsulatedContentInfo()
- */
- public ContentInfoParser getEnapsulatedContentInfo()
- throws IOException
- {
- return getEncapsulatedContentInfo();
- }
-
- public ContentInfoParser getEncapsulatedContentInfo()
- throws IOException
- {
- if (nextObject == null)
- {
- nextObject = seq.readObject();
- }
-
- if (nextObject != null)
- {
- ASN1SequenceParser o = (ASN1SequenceParser)nextObject;
- nextObject = null;
- return new ContentInfoParser(o);
- }
-
- return null;
- }
-
- public ASN1SetParser getAuthAttrs()
- throws IOException
- {
- if (nextObject == null)
- {
- nextObject = seq.readObject();
- }
-
- if (nextObject instanceof ASN1TaggedObjectParser)
- {
- ASN1Encodable o = nextObject;
- nextObject = null;
- return (ASN1SetParser)((ASN1TaggedObjectParser)o).getObjectParser(BERTags.SET, false);
- }
-
- return null;
- }
-
- public ASN1OctetString getMac()
- throws IOException
- {
- if (nextObject == null)
- {
- nextObject = seq.readObject();
- }
-
- ASN1Encodable o = nextObject;
- nextObject = null;
-
- return ASN1OctetString.getInstance(o.toASN1Primitive());
- }
-
- public ASN1SetParser getUnauthAttrs()
- throws IOException
- {
- if (nextObject == null)
- {
- nextObject = seq.readObject();
- }
-
- if (nextObject != null)
- {
- ASN1Encodable o = nextObject;
- nextObject = null;
- return (ASN1SetParser)((ASN1TaggedObjectParser)o).getObjectParser(BERTags.SET, false);
- }
-
- return null;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/CCMParameters.java b/core/src/main/java/org/bouncycastle/asn1/cms/CCMParameters.java
deleted file mode 100644
index 3277bb29..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/CCMParameters.java
+++ /dev/null
@@ -1,102 +0,0 @@
-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/core/src/main/java/org/bouncycastle/asn1/cms/CMSAttributes.java b/core/src/main/java/org/bouncycastle/asn1/cms/CMSAttributes.java
deleted file mode 100644
index d2fc7d1a..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/CMSAttributes.java
+++ /dev/null
@@ -1,30 +0,0 @@
-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/core/src/main/java/org/bouncycastle/asn1/cms/CMSObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/cms/CMSObjectIdentifiers.java
deleted file mode 100644
index b88bf6ef..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/CMSObjectIdentifiers.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-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) }
- * </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/core/src/main/java/org/bouncycastle/asn1/cms/CompressedData.java b/core/src/main/java/org/bouncycastle/asn1/cms/CompressedData.java
deleted file mode 100644
index e5464705..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/CompressedData.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-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.BERSequence;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-/**
- * <a href="http://tools.ietf.org/html/rfc3274">RFC 3274</a>: CMS Compressed Data.
- *
- * <pre>
- * CompressedData ::= SEQUENCE {
- * version CMSVersion,
- * compressionAlgorithm CompressionAlgorithmIdentifier,
- * encapContentInfo EncapsulatedContentInfo
- * }
- * </pre>
- */
-public class CompressedData
- extends ASN1Object
-{
- private ASN1Integer version;
- private AlgorithmIdentifier compressionAlgorithm;
- private ContentInfo encapContentInfo;
-
- public CompressedData(
- AlgorithmIdentifier compressionAlgorithm,
- ContentInfo encapContentInfo)
- {
- this.version = new ASN1Integer(0);
- this.compressionAlgorithm = compressionAlgorithm;
- this.encapContentInfo = encapContentInfo;
- }
-
- private CompressedData(
- ASN1Sequence seq)
- {
- 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.
- *
- * @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 isExplicit)
- {
- return getInstance(ASN1Sequence.getInstance(ato, isExplicit));
- }
-
- /**
- * 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.
- */
- public static CompressedData getInstance(
- Object obj)
- {
- if (obj instanceof CompressedData)
- {
- return (CompressedData)obj;
- }
-
- if (obj != null)
- {
- return new CompressedData(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public AlgorithmIdentifier getCompressionAlgorithmIdentifier()
- {
- return compressionAlgorithm;
- }
-
- public ContentInfo getEncapContentInfo()
- {
- return encapContentInfo;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(version);
- v.add(compressionAlgorithm);
- v.add(encapContentInfo);
-
- return new BERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/CompressedDataParser.java b/core/src/main/java/org/bouncycastle/asn1/cms/CompressedDataParser.java
deleted file mode 100644
index 41895ce2..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/CompressedDataParser.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1SequenceParser;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-/**
- * 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
- * }
- * </pre>
- */
-public class CompressedDataParser
-{
- private ASN1Integer _version;
- private AlgorithmIdentifier _compressionAlgorithm;
- private ContentInfoParser _encapContentInfo;
-
- public CompressedDataParser(
- ASN1SequenceParser seq)
- throws IOException
- {
- this._version = (ASN1Integer)seq.readObject();
- this._compressionAlgorithm = AlgorithmIdentifier.getInstance(seq.readObject().toASN1Primitive());
- this._encapContentInfo = new ContentInfoParser((ASN1SequenceParser)seq.readObject());
- }
-
- public ASN1Integer getVersion()
- {
- return _version;
- }
-
- public AlgorithmIdentifier getCompressionAlgorithmIdentifier()
- {
- return _compressionAlgorithm;
- }
-
- public ContentInfoParser getEncapContentInfo()
- {
- return _encapContentInfo;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/ContentInfo.java b/core/src/main/java/org/bouncycastle/asn1/cms/ContentInfo.java
deleted file mode 100644
index 2e8e0392..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/ContentInfo.java
+++ /dev/null
@@ -1,130 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.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
-{
- 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)
- {
- if (obj instanceof ContentInfo)
- {
- return (ContentInfo)obj;
- }
- else if (obj != null)
- {
- return new ContentInfo(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public static ContentInfo getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- /**
- * @deprecated use getInstance()
- */
- public ContentInfo(
- ASN1Sequence seq)
- {
- if (seq.size() < 1 || seq.size() > 2)
- {
- throw new IllegalArgumentException("Bad sequence size: " + seq.size());
- }
-
- contentType = (ASN1ObjectIdentifier)seq.getObjectAt(0);
-
- if (seq.size() > 1)
- {
- ASN1TaggedObject tagged = (ASN1TaggedObject)seq.getObjectAt(1);
- if (!tagged.isExplicit() || tagged.getTagNo() != 0)
- {
- throw new IllegalArgumentException("Bad tag for 'content'");
- }
-
- content = tagged.getObject();
- }
- }
-
- public ContentInfo(
- ASN1ObjectIdentifier contentType,
- ASN1Encodable content)
- {
- this.contentType = contentType;
- this.content = content;
- }
-
- public ASN1ObjectIdentifier getContentType()
- {
- return contentType;
- }
-
- public ASN1Encodable getContent()
- {
- return content;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(contentType);
-
- if (content != null)
- {
- v.add(new BERTaggedObject(0, content));
- }
-
- return new BERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/ContentInfoParser.java b/core/src/main/java/org/bouncycastle/asn1/cms/ContentInfoParser.java
deleted file mode 100644
index 19f0ec88..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/ContentInfoParser.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1SequenceParser;
-import org.bouncycastle.asn1.ASN1TaggedObjectParser;
-
-/**
- * <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 }
- * </pre>
- */
-public class ContentInfoParser
-{
- private ASN1ObjectIdentifier contentType;
- private ASN1TaggedObjectParser content;
-
- public ContentInfoParser(
- ASN1SequenceParser seq)
- throws IOException
- {
- contentType = (ASN1ObjectIdentifier)seq.readObject();
- content = (ASN1TaggedObjectParser)seq.readObject();
- }
-
- public ASN1ObjectIdentifier getContentType()
- {
- return contentType;
- }
-
- public ASN1Encodable getContent(
- int tag)
- throws IOException
- {
- if (content != null)
- {
- return content.getObjectParser(tag, true);
- }
-
- return null;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/DigestedData.java b/core/src/main/java/org/bouncycastle/asn1/cms/DigestedData.java
deleted file mode 100644
index 0f3b906a..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/DigestedData.java
+++ /dev/null
@@ -1,128 +0,0 @@
-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.ASN1TaggedObject;
-import org.bouncycastle.asn1.BERSequence;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-/**
- * <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 }
- * </pre>
- */
-public class DigestedData
- extends ASN1Object
-{
- private ASN1Integer version;
- private AlgorithmIdentifier digestAlgorithm;
- private ContentInfo encapContentInfo;
- private ASN1OctetString digest;
-
- public DigestedData(
- AlgorithmIdentifier digestAlgorithm,
- ContentInfo encapContentInfo,
- byte[] digest)
- {
- this.version = new ASN1Integer(0);
- this.digestAlgorithm = digestAlgorithm;
- this.encapContentInfo = encapContentInfo;
- this.digest = new DEROctetString(digest);
- }
-
- private DigestedData(
- ASN1Sequence seq)
- {
- this.version = (ASN1Integer)seq.getObjectAt(0);
- this.digestAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
- this.encapContentInfo = ContentInfo.getInstance(seq.getObjectAt(2));
- this.digest = ASN1OctetString.getInstance(seq.getObjectAt(3));
- }
-
- /**
- * Return a DigestedData object from a tagged object.
- *
- * @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 isExplicit)
- {
- return getInstance(ASN1Sequence.getInstance(ato, isExplicit));
- }
-
- /**
- * 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.
- */
- public static DigestedData getInstance(
- Object obj)
- {
- if (obj instanceof DigestedData)
- {
- return (DigestedData)obj;
- }
-
- if (obj != null)
- {
- return new DigestedData(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public AlgorithmIdentifier getDigestAlgorithm()
- {
- return digestAlgorithm;
- }
-
- public ContentInfo getEncapContentInfo()
- {
- return encapContentInfo;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(version);
- v.add(digestAlgorithm);
- v.add(encapContentInfo);
- v.add(digest);
-
- return new BERSequence(v);
- }
-
- public byte[] getDigest()
- {
- return digest.getOctets();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfo.java b/core/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfo.java
deleted file mode 100644
index 64d887d6..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfo.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-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
-{
- private ASN1ObjectIdentifier contentType;
- private AlgorithmIdentifier contentEncryptionAlgorithm;
- private ASN1OctetString encryptedContent;
-
- public EncryptedContentInfo(
- ASN1ObjectIdentifier contentType,
- AlgorithmIdentifier contentEncryptionAlgorithm,
- ASN1OctetString encryptedContent)
- {
- this.contentType = contentType;
- this.contentEncryptionAlgorithm = contentEncryptionAlgorithm;
- this.encryptedContent = encryptedContent;
- }
-
- private EncryptedContentInfo(
- ASN1Sequence seq)
- {
- if (seq.size() < 2)
- {
- throw new IllegalArgumentException("Truncated Sequence Found");
- }
-
- contentType = (ASN1ObjectIdentifier)seq.getObjectAt(0);
- contentEncryptionAlgorithm = AlgorithmIdentifier.getInstance(
- seq.getObjectAt(1));
- if (seq.size() > 2)
- {
- encryptedContent = ASN1OctetString.getInstance(
- (ASN1TaggedObject)seq.getObjectAt(2), false);
- }
- }
-
- /**
- * 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.
- */
- public static EncryptedContentInfo getInstance(
- Object obj)
- {
- if (obj instanceof EncryptedContentInfo)
- {
- return (EncryptedContentInfo)obj;
- }
- if (obj != null)
- {
- return new EncryptedContentInfo(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public ASN1ObjectIdentifier getContentType()
- {
- return contentType;
- }
-
- public AlgorithmIdentifier getContentEncryptionAlgorithm()
- {
- return contentEncryptionAlgorithm;
- }
-
- public ASN1OctetString getEncryptedContent()
- {
- return encryptedContent;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(contentType);
- v.add(contentEncryptionAlgorithm);
-
- if (encryptedContent != null)
- {
- v.add(new BERTaggedObject(false, 0, encryptedContent));
- }
-
- return new BERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfoParser.java b/core/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfoParser.java
deleted file mode 100644
index 77fb0bbf..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfoParser.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1SequenceParser;
-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,
- * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
- * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
- * }
- * </pre>
- */
-public class EncryptedContentInfoParser
-{
- private ASN1ObjectIdentifier _contentType;
- private AlgorithmIdentifier _contentEncryptionAlgorithm;
- private ASN1TaggedObjectParser _encryptedContent;
-
- public EncryptedContentInfoParser(
- ASN1SequenceParser seq)
- throws IOException
- {
- _contentType = (ASN1ObjectIdentifier)seq.readObject();
- _contentEncryptionAlgorithm = AlgorithmIdentifier.getInstance(seq.readObject().toASN1Primitive());
- _encryptedContent = (ASN1TaggedObjectParser)seq.readObject();
- }
-
- public ASN1ObjectIdentifier getContentType()
- {
- return _contentType;
- }
-
- public AlgorithmIdentifier getContentEncryptionAlgorithm()
- {
- return _contentEncryptionAlgorithm;
- }
-
- public ASN1Encodable getEncryptedContent(
- int tag)
- throws IOException
- {
- return _encryptedContent.getObjectParser(tag, false);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/EncryptedData.java b/core/src/main/java/org/bouncycastle/asn1/cms/EncryptedData.java
deleted file mode 100644
index 2c839581..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/EncryptedData.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-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.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
-{
- private ASN1Integer version;
- 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)
- {
- return (EncryptedData)o;
- }
-
- if (o != null)
- {
- return new EncryptedData(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public EncryptedData(EncryptedContentInfo encInfo)
- {
- this(encInfo, null);
- }
-
- public EncryptedData(EncryptedContentInfo encInfo, ASN1Set unprotectedAttrs)
- {
- this.version = new ASN1Integer((unprotectedAttrs == null) ? 0 : 2);
- this.encryptedContentInfo = encInfo;
- this.unprotectedAttrs = unprotectedAttrs;
- }
-
- private EncryptedData(ASN1Sequence seq)
- {
- this.version = ASN1Integer.getInstance(seq.getObjectAt(0));
- this.encryptedContentInfo = EncryptedContentInfo.getInstance(seq.getObjectAt(1));
-
- if (seq.size() == 3)
- {
- this.unprotectedAttrs = ASN1Set.getInstance(seq.getObjectAt(2));
- }
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public EncryptedContentInfo getEncryptedContentInfo()
- {
- return encryptedContentInfo;
- }
-
- public ASN1Set getUnprotectedAttrs()
- {
- return unprotectedAttrs;
- }
-
- /**
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(version);
- v.add(encryptedContentInfo);
- if (unprotectedAttrs != null)
- {
- v.add(new BERTaggedObject(false, 1, unprotectedAttrs));
- }
-
- return new BERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/EnvelopedData.java b/core/src/main/java/org/bouncycastle/asn1/cms/EnvelopedData.java
deleted file mode 100644
index 994575a5..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/EnvelopedData.java
+++ /dev/null
@@ -1,215 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import java.util.Enumeration;
-
-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.ASN1Set;
-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
-{
- private ASN1Integer version;
- private OriginatorInfo originatorInfo;
- private ASN1Set recipientInfos;
- private EncryptedContentInfo encryptedContentInfo;
- private ASN1Set unprotectedAttrs;
-
- public EnvelopedData(
- OriginatorInfo originatorInfo,
- ASN1Set recipientInfos,
- EncryptedContentInfo encryptedContentInfo,
- ASN1Set unprotectedAttrs)
- {
- version = new ASN1Integer(calculateVersion(originatorInfo, recipientInfos, unprotectedAttrs));
-
- this.originatorInfo = originatorInfo;
- this.recipientInfos = recipientInfos;
- this.encryptedContentInfo = encryptedContentInfo;
- this.unprotectedAttrs = unprotectedAttrs;
- }
-
- public EnvelopedData(
- OriginatorInfo originatorInfo,
- ASN1Set recipientInfos,
- EncryptedContentInfo encryptedContentInfo,
- Attributes unprotectedAttrs)
- {
- version = new ASN1Integer(calculateVersion(originatorInfo, recipientInfos, ASN1Set.getInstance(unprotectedAttrs)));
-
- this.originatorInfo = originatorInfo;
- this.recipientInfos = recipientInfos;
- this.encryptedContentInfo = encryptedContentInfo;
- this.unprotectedAttrs = ASN1Set.getInstance(unprotectedAttrs);
- }
-
- /**
- * @deprecated use getInstance()
- */
- public EnvelopedData(
- ASN1Sequence seq)
- {
- int index = 0;
-
- version = (ASN1Integer)seq.getObjectAt(index++);
-
- Object tmp = seq.getObjectAt(index++);
-
- if (tmp instanceof ASN1TaggedObject)
- {
- originatorInfo = OriginatorInfo.getInstance((ASN1TaggedObject)tmp, false);
- tmp = seq.getObjectAt(index++);
- }
-
- recipientInfos = ASN1Set.getInstance(tmp);
-
- encryptedContentInfo = EncryptedContentInfo.getInstance(seq.getObjectAt(index++));
-
- if(seq.size() > index)
- {
- unprotectedAttrs = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(index), false);
- }
- }
-
- /**
- * 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
- * tagged false otherwise.
- * @exception IllegalArgumentException if the object held by the
- * tagged object cannot be converted.
- */
- public static EnvelopedData getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- /**
- * 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.
- */
- public static EnvelopedData getInstance(
- Object obj)
- {
- if (obj instanceof EnvelopedData)
- {
- return (EnvelopedData)obj;
- }
-
- if (obj != null)
- {
- return new EnvelopedData(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public OriginatorInfo getOriginatorInfo()
- {
- return originatorInfo;
- }
-
- public ASN1Set getRecipientInfos()
- {
- return recipientInfos;
- }
-
- public EncryptedContentInfo getEncryptedContentInfo()
- {
- return encryptedContentInfo;
- }
-
- public ASN1Set getUnprotectedAttrs()
- {
- return unprotectedAttrs;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(version);
-
- if (originatorInfo != null)
- {
- v.add(new DERTaggedObject(false, 0, originatorInfo));
- }
-
- v.add(recipientInfos);
- v.add(encryptedContentInfo);
-
- if (unprotectedAttrs != null)
- {
- v.add(new DERTaggedObject(false, 1, unprotectedAttrs));
- }
-
- return new BERSequence(v);
- }
-
- public static int calculateVersion(OriginatorInfo originatorInfo, ASN1Set recipientInfos, ASN1Set unprotectedAttrs)
- {
- int version;
-
- if (originatorInfo != null || unprotectedAttrs != null)
- {
- version = 2;
- }
- else
- {
- version = 0;
-
- Enumeration e = recipientInfos.getObjects();
-
- while (e.hasMoreElements())
- {
- RecipientInfo ri = RecipientInfo.getInstance(e.nextElement());
-
- if (ri.getVersion().getValue().intValue() != version)
- {
- version = 2;
- break;
- }
- }
- }
-
- return version;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/EnvelopedDataParser.java b/core/src/main/java/org/bouncycastle/asn1/cms/EnvelopedDataParser.java
deleted file mode 100644
index 774813af..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/EnvelopedDataParser.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1SequenceParser;
-import org.bouncycastle.asn1.ASN1SetParser;
-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,
- * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
- * recipientInfos RecipientInfos,
- * encryptedContentInfo EncryptedContentInfo,
- * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL
- * }
- * </pre>
- */
-public class EnvelopedDataParser
-{
- private ASN1SequenceParser _seq;
- private ASN1Integer _version;
- private ASN1Encodable _nextObject;
- private boolean _originatorInfoCalled;
-
- public EnvelopedDataParser(
- ASN1SequenceParser seq)
- throws IOException
- {
- this._seq = seq;
- this._version = ASN1Integer.getInstance(seq.readObject());
- }
-
- public ASN1Integer getVersion()
- {
- return _version;
- }
-
- public OriginatorInfo getOriginatorInfo()
- throws IOException
- {
- _originatorInfoCalled = true;
-
- if (_nextObject == null)
- {
- _nextObject = _seq.readObject();
- }
-
- if (_nextObject instanceof ASN1TaggedObjectParser && ((ASN1TaggedObjectParser)_nextObject).getTagNo() == 0)
- {
- ASN1SequenceParser originatorInfo = (ASN1SequenceParser) ((ASN1TaggedObjectParser)_nextObject).getObjectParser(BERTags.SEQUENCE, false);
- _nextObject = null;
- return OriginatorInfo.getInstance(originatorInfo.toASN1Primitive());
- }
-
- return null;
- }
-
- public ASN1SetParser getRecipientInfos()
- throws IOException
- {
- if (!_originatorInfoCalled)
- {
- getOriginatorInfo();
- }
-
- if (_nextObject == null)
- {
- _nextObject = _seq.readObject();
- }
-
- ASN1SetParser recipientInfos = (ASN1SetParser)_nextObject;
- _nextObject = null;
- return recipientInfos;
- }
-
- public EncryptedContentInfoParser getEncryptedContentInfo()
- throws IOException
- {
- if (_nextObject == null)
- {
- _nextObject = _seq.readObject();
- }
-
-
- if (_nextObject != null)
- {
- ASN1SequenceParser o = (ASN1SequenceParser) _nextObject;
- _nextObject = null;
- return new EncryptedContentInfoParser(o);
- }
-
- return null;
- }
-
- public ASN1SetParser getUnprotectedAttrs()
- throws IOException
- {
- if (_nextObject == null)
- {
- _nextObject = _seq.readObject();
- }
-
-
- if (_nextObject != null)
- {
- ASN1Encodable o = _nextObject;
- _nextObject = null;
- return (ASN1SetParser)((ASN1TaggedObjectParser)o).getObjectParser(BERTags.SET, false);
- }
-
- return null;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/Evidence.java b/core/src/main/java/org/bouncycastle/asn1/cms/Evidence.java
deleted file mode 100644
index 4dcbfded..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/Evidence.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Object;
-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
-{
- private TimeStampTokenEvidence tstEvidence;
-
- public Evidence(TimeStampTokenEvidence tstEvidence)
- {
- this.tstEvidence = tstEvidence;
- }
-
- private Evidence(ASN1TaggedObject tagged)
- {
- if (tagged.getTagNo() == 0)
- {
- this.tstEvidence = TimeStampTokenEvidence.getInstance(tagged, false);
- }
- }
-
- /**
- * 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)
- {
- return (Evidence)obj;
- }
- else if (obj instanceof ASN1TaggedObject)
- {
- return new Evidence(ASN1TaggedObject.getInstance(obj));
- }
-
- throw new IllegalArgumentException("unknown object in getInstance");
- }
-
- public TimeStampTokenEvidence getTstEvidence()
- {
- return tstEvidence;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- if (tstEvidence != null)
- {
- return new DERTaggedObject(false, 0, tstEvidence);
- }
-
- return null;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/GCMParameters.java b/core/src/main/java/org/bouncycastle/asn1/cms/GCMParameters.java
deleted file mode 100644
index 0f03c879..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/GCMParameters.java
+++ /dev/null
@@ -1,102 +0,0 @@
-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/core/src/main/java/org/bouncycastle/asn1/cms/IssuerAndSerialNumber.java b/core/src/main/java/org/bouncycastle/asn1/cms/IssuerAndSerialNumber.java
deleted file mode 100644
index d46cbfb2..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/IssuerAndSerialNumber.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-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.DERSequence;
-import org.bouncycastle.asn1.x500.X500Name;
-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)
- {
- if (obj instanceof IssuerAndSerialNumber)
- {
- return (IssuerAndSerialNumber)obj;
- }
- else if (obj != null)
- {
- return new IssuerAndSerialNumber(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- /**
- * @deprecated use getInstance() method.
- */
- public IssuerAndSerialNumber(
- ASN1Sequence seq)
- {
- this.name = X500Name.getInstance(seq.getObjectAt(0));
- this.serialNumber = (ASN1Integer)seq.getObjectAt(1);
- }
-
- public IssuerAndSerialNumber(
- Certificate certificate)
- {
- this.name = certificate.getIssuer();
- this.serialNumber = certificate.getSerialNumber();
- }
-
- /**
- * @deprecated use constructor taking Certificate
- */
- public IssuerAndSerialNumber(
- X509CertificateStructure certificate)
- {
- this.name = certificate.getIssuer();
- this.serialNumber = certificate.getSerialNumber();
- }
-
- public IssuerAndSerialNumber(
- X500Name name,
- BigInteger serialNumber)
- {
- this.name = name;
- this.serialNumber = new ASN1Integer(serialNumber);
- }
-
- /**
- * @deprecated use X500Name constructor
- */
- public IssuerAndSerialNumber(
- X509Name name,
- BigInteger serialNumber)
- {
- this.name = X500Name.getInstance(name);
- this.serialNumber = new ASN1Integer(serialNumber);
- }
-
- /**
- * @deprecated use X500Name constructor
- */
- public IssuerAndSerialNumber(
- X509Name name,
- ASN1Integer serialNumber)
- {
- this.name = X500Name.getInstance(name);
- this.serialNumber = serialNumber;
- }
-
- public X500Name getName()
- {
- return name;
- }
-
- public ASN1Integer getSerialNumber()
- {
- return serialNumber;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(name);
- v.add(serialNumber);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/KEKIdentifier.java b/core/src/main/java/org/bouncycastle/asn1/cms/KEKIdentifier.java
deleted file mode 100644
index 0361e9fb..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/KEKIdentifier.java
+++ /dev/null
@@ -1,151 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-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
-{
- private ASN1OctetString keyIdentifier;
- private ASN1GeneralizedTime date;
- private OtherKeyAttribute other;
-
- public KEKIdentifier(
- byte[] keyIdentifier,
- ASN1GeneralizedTime date,
- OtherKeyAttribute other)
- {
- this.keyIdentifier = new DEROctetString(keyIdentifier);
- this.date = date;
- this.other = other;
- }
-
- private KEKIdentifier(
- ASN1Sequence seq)
- {
- keyIdentifier = (ASN1OctetString)seq.getObjectAt(0);
-
- switch (seq.size())
- {
- case 1:
- break;
- case 2:
- if (seq.getObjectAt(1) instanceof ASN1GeneralizedTime)
- {
- date = (ASN1GeneralizedTime)seq.getObjectAt(1);
- }
- else
- {
- other = OtherKeyAttribute.getInstance(seq.getObjectAt(1));
- }
- break;
- case 3:
- date = (ASN1GeneralizedTime)seq.getObjectAt(1);
- other = OtherKeyAttribute.getInstance(seq.getObjectAt(2));
- break;
- default:
- throw new IllegalArgumentException("Invalid KEKIdentifier");
- }
- }
-
- /**
- * 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
- * tagged false otherwise.
- * @exception IllegalArgumentException if the object held by the
- * tagged object cannot be converted.
- */
- public static KEKIdentifier getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- /**
- * 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.
- */
- public static KEKIdentifier getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof KEKIdentifier)
- {
- return (KEKIdentifier)obj;
- }
-
- if (obj instanceof ASN1Sequence)
- {
- return new KEKIdentifier((ASN1Sequence)obj);
- }
-
- throw new IllegalArgumentException("Invalid KEKIdentifier: " + obj.getClass().getName());
- }
-
- public ASN1OctetString getKeyIdentifier()
- {
- return keyIdentifier;
- }
-
- public ASN1GeneralizedTime getDate()
- {
- return date;
- }
-
- public OtherKeyAttribute getOther()
- {
- return other;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(keyIdentifier);
-
- if (date != null)
- {
- v.add(date);
- }
-
- if (other != null)
- {
- v.add(other);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/KEKRecipientInfo.java b/core/src/main/java/org/bouncycastle/asn1/cms/KEKRecipientInfo.java
deleted file mode 100644
index 2d0cfa6d..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/KEKRecipientInfo.java
+++ /dev/null
@@ -1,133 +0,0 @@
-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.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
-{
- private ASN1Integer version;
- private KEKIdentifier kekid;
- private AlgorithmIdentifier keyEncryptionAlgorithm;
- private ASN1OctetString encryptedKey;
-
- public KEKRecipientInfo(
- KEKIdentifier kekid,
- AlgorithmIdentifier keyEncryptionAlgorithm,
- ASN1OctetString encryptedKey)
- {
- this.version = new ASN1Integer(4);
- this.kekid = kekid;
- this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
- this.encryptedKey = encryptedKey;
- }
-
- public KEKRecipientInfo(
- ASN1Sequence seq)
- {
- version = (ASN1Integer)seq.getObjectAt(0);
- kekid = KEKIdentifier.getInstance(seq.getObjectAt(1));
- keyEncryptionAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(2));
- encryptedKey = (ASN1OctetString)seq.getObjectAt(3);
- }
-
- /**
- * 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
- * tagged false otherwise.
- * @exception IllegalArgumentException if the object held by the
- * tagged object cannot be converted.
- */
- public static KEKRecipientInfo getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- /**
- * 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.
- */
- public static KEKRecipientInfo getInstance(
- Object obj)
- {
- if (obj instanceof KEKRecipientInfo)
- {
- return (KEKRecipientInfo)obj;
- }
-
- if (obj != null)
- {
- return new KEKRecipientInfo(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public KEKIdentifier getKekid()
- {
- return kekid;
- }
-
- public AlgorithmIdentifier getKeyEncryptionAlgorithm()
- {
- return keyEncryptionAlgorithm;
- }
-
- public ASN1OctetString getEncryptedKey()
- {
- return encryptedKey;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(version);
- v.add(kekid);
- v.add(keyEncryptionAlgorithm);
- v.add(encryptedKey);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientIdentifier.java b/core/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientIdentifier.java
deleted file mode 100644
index 6580cd4d..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientIdentifier.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-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
-{
- private IssuerAndSerialNumber issuerSerial;
- private RecipientKeyIdentifier rKeyID;
-
- /**
- * 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
- * tagged false otherwise.
- * @exception IllegalArgumentException if the object held by the
- * tagged object cannot be converted.
- */
- public static KeyAgreeRecipientIdentifier getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- /**
- * 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.
- */
- public static KeyAgreeRecipientIdentifier getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof KeyAgreeRecipientIdentifier)
- {
- return (KeyAgreeRecipientIdentifier)obj;
- }
-
- if (obj instanceof ASN1Sequence)
- {
- return new KeyAgreeRecipientIdentifier(IssuerAndSerialNumber.getInstance(obj));
- }
-
- if (obj instanceof ASN1TaggedObject && ((ASN1TaggedObject)obj).getTagNo() == 0)
- {
- return new KeyAgreeRecipientIdentifier(RecipientKeyIdentifier.getInstance(
- (ASN1TaggedObject)obj, false));
- }
-
- throw new IllegalArgumentException("Invalid KeyAgreeRecipientIdentifier: " + obj.getClass().getName());
- }
-
- public KeyAgreeRecipientIdentifier(
- IssuerAndSerialNumber issuerSerial)
- {
- this.issuerSerial = issuerSerial;
- this.rKeyID = null;
- }
-
- public KeyAgreeRecipientIdentifier(
- RecipientKeyIdentifier rKeyID)
- {
- this.issuerSerial = null;
- this.rKeyID = rKeyID;
- }
-
- public IssuerAndSerialNumber getIssuerAndSerialNumber()
- {
- return issuerSerial;
- }
-
- public RecipientKeyIdentifier getRKeyID()
- {
- return rKeyID;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- if (issuerSerial != null)
- {
- return issuerSerial.toASN1Primitive();
- }
-
- return new DERTaggedObject(false, 0, rKeyID);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientInfo.java b/core/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientInfo.java
deleted file mode 100644
index 224932ad..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientInfo.java
+++ /dev/null
@@ -1,166 +0,0 @@
-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.ASN1TaggedObject;
-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
-{
- private ASN1Integer version;
- private OriginatorIdentifierOrKey originator;
- private ASN1OctetString ukm;
- private AlgorithmIdentifier keyEncryptionAlgorithm;
- private ASN1Sequence recipientEncryptedKeys;
-
- public KeyAgreeRecipientInfo(
- OriginatorIdentifierOrKey originator,
- ASN1OctetString ukm,
- AlgorithmIdentifier keyEncryptionAlgorithm,
- ASN1Sequence recipientEncryptedKeys)
- {
- this.version = new ASN1Integer(3);
- this.originator = originator;
- this.ukm = ukm;
- this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
- this.recipientEncryptedKeys = recipientEncryptedKeys;
- }
-
- /**
- * @deprecated use getInstance()
- */
- public KeyAgreeRecipientInfo(
- ASN1Sequence seq)
- {
- int index = 0;
-
- version = (ASN1Integer)seq.getObjectAt(index++);
- originator = OriginatorIdentifierOrKey.getInstance(
- (ASN1TaggedObject)seq.getObjectAt(index++), true);
-
- if (seq.getObjectAt(index) instanceof ASN1TaggedObject)
- {
- ukm = ASN1OctetString.getInstance(
- (ASN1TaggedObject)seq.getObjectAt(index++), true);
- }
-
- keyEncryptionAlgorithm = AlgorithmIdentifier.getInstance(
- seq.getObjectAt(index++));
-
- recipientEncryptedKeys = (ASN1Sequence)seq.getObjectAt(index++);
- }
-
- /**
- * 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
- * tagged false otherwise.
- * @exception IllegalArgumentException if the object held by the
- * tagged object cannot be converted.
- */
- public static KeyAgreeRecipientInfo getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- /**
- * 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.
- */
- public static KeyAgreeRecipientInfo getInstance(
- Object obj)
- {
- if (obj instanceof KeyAgreeRecipientInfo)
- {
- return (KeyAgreeRecipientInfo)obj;
- }
-
- if (obj != null)
- {
- return new KeyAgreeRecipientInfo(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public OriginatorIdentifierOrKey getOriginator()
- {
- return originator;
- }
-
- public ASN1OctetString getUserKeyingMaterial()
- {
- return ukm;
- }
-
- public AlgorithmIdentifier getKeyEncryptionAlgorithm()
- {
- return keyEncryptionAlgorithm;
- }
-
- public ASN1Sequence getRecipientEncryptedKeys()
- {
- return recipientEncryptedKeys;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(version);
- v.add(new DERTaggedObject(true, 0, originator));
-
- if (ukm != null)
- {
- v.add(new DERTaggedObject(true, 1, ukm));
- }
-
- v.add(keyEncryptionAlgorithm);
- v.add(recipientEncryptedKeys);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/KeyTransRecipientInfo.java b/core/src/main/java/org/bouncycastle/asn1/cms/KeyTransRecipientInfo.java
deleted file mode 100644
index 7d311111..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/KeyTransRecipientInfo.java
+++ /dev/null
@@ -1,127 +0,0 @@
-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.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
-{
- private ASN1Integer version;
- private RecipientIdentifier rid;
- private AlgorithmIdentifier keyEncryptionAlgorithm;
- private ASN1OctetString encryptedKey;
-
- public KeyTransRecipientInfo(
- RecipientIdentifier rid,
- AlgorithmIdentifier keyEncryptionAlgorithm,
- ASN1OctetString encryptedKey)
- {
- if (rid.toASN1Primitive() instanceof ASN1TaggedObject)
- {
- this.version = new ASN1Integer(2);
- }
- else
- {
- this.version = new ASN1Integer(0);
- }
-
- this.rid = rid;
- this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
- this.encryptedKey = encryptedKey;
- }
-
- /**
- * @deprecated use getInstance()
- */
- public KeyTransRecipientInfo(
- ASN1Sequence seq)
- {
- this.version = (ASN1Integer)seq.getObjectAt(0);
- this.rid = RecipientIdentifier.getInstance(seq.getObjectAt(1));
- this.keyEncryptionAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(2));
- this.encryptedKey = (ASN1OctetString)seq.getObjectAt(3);
- }
-
- /**
- * 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.
- */
- public static KeyTransRecipientInfo getInstance(
- Object obj)
- {
- if (obj instanceof KeyTransRecipientInfo)
- {
- return (KeyTransRecipientInfo)obj;
- }
-
- if(obj != null)
- {
- return new KeyTransRecipientInfo(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public RecipientIdentifier getRecipientIdentifier()
- {
- return rid;
- }
-
- public AlgorithmIdentifier getKeyEncryptionAlgorithm()
- {
- return keyEncryptionAlgorithm;
- }
-
- public ASN1OctetString getEncryptedKey()
- {
- return encryptedKey;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(version);
- v.add(rid);
- v.add(keyEncryptionAlgorithm);
- v.add(encryptedKey);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/MetaData.java b/core/src/main/java/org/bouncycastle/asn1/cms/MetaData.java
deleted file mode 100644
index 667187b3..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/MetaData.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import org.bouncycastle.asn1.ASN1Boolean;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-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
-{
- private ASN1Boolean hashProtected;
- private DERUTF8String fileName;
- private DERIA5String mediaType;
- private Attributes otherMetaData;
-
- public MetaData(
- ASN1Boolean hashProtected,
- DERUTF8String fileName,
- DERIA5String mediaType,
- Attributes otherMetaData)
- {
- this.hashProtected = hashProtected;
- this.fileName = fileName;
- this.mediaType = mediaType;
- this.otherMetaData = otherMetaData;
- }
-
- private MetaData(ASN1Sequence seq)
- {
- this.hashProtected = ASN1Boolean.getInstance(seq.getObjectAt(0));
-
- int index = 1;
-
- if (index < seq.size() && seq.getObjectAt(index) instanceof DERUTF8String)
- {
- this.fileName = DERUTF8String.getInstance(seq.getObjectAt(index++));
- }
- if (index < seq.size() && seq.getObjectAt(index) instanceof DERIA5String)
- {
- this.mediaType = DERIA5String.getInstance(seq.getObjectAt(index++));
- }
- if (index < seq.size())
- {
- this.otherMetaData = Attributes.getInstance(seq.getObjectAt(index++));
- }
- }
-
- /**
- * 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)
- {
- return (MetaData)obj;
- }
- else if (obj != null)
- {
- return new MetaData(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(hashProtected);
-
- if (fileName != null)
- {
- v.add(fileName);
- }
-
- if (mediaType != null)
- {
- v.add(mediaType);
- }
-
- if (otherMetaData != null)
- {
- v.add(otherMetaData);
- }
-
- return new DERSequence(v);
- }
-
- public boolean isHashProtected()
- {
- return hashProtected.isTrue();
- }
-
- public DERUTF8String getFileName()
- {
- return this.fileName;
- }
-
- public DERIA5String getMediaType()
- {
- return this.mediaType;
- }
-
- public Attributes getOtherMetaData()
- {
- return otherMetaData;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/OriginatorIdentifierOrKey.java b/core/src/main/java/org/bouncycastle/asn1/cms/OriginatorIdentifierOrKey.java
deleted file mode 100644
index 2096be26..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/OriginatorIdentifierOrKey.java
+++ /dev/null
@@ -1,179 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-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
-{
- private ASN1Encodable id;
-
- public OriginatorIdentifierOrKey(
- IssuerAndSerialNumber id)
- {
- this.id = id;
- }
-
- /**
- * @deprecated use version taking a SubjectKeyIdentifier
- */
- public OriginatorIdentifierOrKey(
- ASN1OctetString id)
- {
- this(new SubjectKeyIdentifier(id.getOctets()));
- }
-
- public OriginatorIdentifierOrKey(
- SubjectKeyIdentifier id)
- {
- this.id = new DERTaggedObject(false, 0, id);
- }
-
- public OriginatorIdentifierOrKey(
- OriginatorPublicKey id)
- {
- this.id = new DERTaggedObject(false, 1, id);
- }
-
- /**
- * @deprecated use more specific version
- */
- public OriginatorIdentifierOrKey(
- ASN1Primitive id)
- {
- this.id = id;
- }
-
- /**
- * 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
- * tagged false otherwise.
- * @exception IllegalArgumentException if the object held by the
- * tagged object cannot be converted.
- */
- public static OriginatorIdentifierOrKey getInstance(
- ASN1TaggedObject o,
- boolean explicit)
- {
- if (!explicit)
- {
- throw new IllegalArgumentException(
- "Can't implicitly tag OriginatorIdentifierOrKey");
- }
-
- return getInstance(o.getObject());
- }
-
- /**
- * 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.
- */
- public static OriginatorIdentifierOrKey getInstance(
- Object o)
- {
- if (o == null || o instanceof OriginatorIdentifierOrKey)
- {
- return (OriginatorIdentifierOrKey)o;
- }
-
- if (o instanceof IssuerAndSerialNumber)
- {
- return new OriginatorIdentifierOrKey((IssuerAndSerialNumber)o);
- }
-
- if (o instanceof SubjectKeyIdentifier)
- {
- return new OriginatorIdentifierOrKey((SubjectKeyIdentifier)o);
- }
-
- if (o instanceof OriginatorPublicKey)
- {
- return new OriginatorIdentifierOrKey((OriginatorPublicKey)o);
- }
-
- if (o instanceof ASN1TaggedObject)
- {
- // TODO Add validation
- return new OriginatorIdentifierOrKey((ASN1TaggedObject)o);
- }
-
- throw new IllegalArgumentException("Invalid OriginatorIdentifierOrKey: " + o.getClass().getName());
- }
-
- public ASN1Encodable getId()
- {
- return id;
- }
-
- public IssuerAndSerialNumber getIssuerAndSerialNumber()
- {
- if (id instanceof IssuerAndSerialNumber)
- {
- return (IssuerAndSerialNumber)id;
- }
-
- return null;
- }
-
- public SubjectKeyIdentifier getSubjectKeyIdentifier()
- {
- if (id instanceof ASN1TaggedObject && ((ASN1TaggedObject)id).getTagNo() == 0)
- {
- return SubjectKeyIdentifier.getInstance((ASN1TaggedObject)id, false);
- }
-
- return null;
- }
-
- public OriginatorPublicKey getOriginatorKey()
- {
- if (id instanceof ASN1TaggedObject && ((ASN1TaggedObject)id).getTagNo() == 1)
- {
- return OriginatorPublicKey.getInstance((ASN1TaggedObject)id, false);
- }
-
- return null;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- return id.toASN1Primitive();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/OriginatorInfo.java b/core/src/main/java/org/bouncycastle/asn1/cms/OriginatorInfo.java
deleted file mode 100644
index 96abf7d6..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/OriginatorInfo.java
+++ /dev/null
@@ -1,159 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Set;
-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
-{
- private ASN1Set certs;
- private ASN1Set crls;
-
- public OriginatorInfo(
- ASN1Set certs,
- ASN1Set crls)
- {
- this.certs = certs;
- this.crls = crls;
- }
-
- private OriginatorInfo(
- ASN1Sequence seq)
- {
- switch (seq.size())
- {
- case 0: // empty
- break;
- case 1:
- ASN1TaggedObject o = (ASN1TaggedObject)seq.getObjectAt(0);
- switch (o.getTagNo())
- {
- case 0 :
- certs = ASN1Set.getInstance(o, false);
- break;
- case 1 :
- crls = ASN1Set.getInstance(o, false);
- break;
- default:
- throw new IllegalArgumentException("Bad tag in OriginatorInfo: " + o.getTagNo());
- }
- break;
- case 2:
- certs = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(0), false);
- crls = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(1), false);
- break;
- default:
- throw new IllegalArgumentException("OriginatorInfo too big");
- }
- }
-
- /**
- * 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
- * tagged false otherwise.
- * @exception IllegalArgumentException if the object held by the
- * tagged object cannot be converted.
- */
- public static OriginatorInfo getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- /**
- * 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.
- */
- public static OriginatorInfo getInstance(
- Object obj)
- {
- if (obj instanceof OriginatorInfo)
- {
- return (OriginatorInfo)obj;
- }
- else if (obj != null)
- {
- return new OriginatorInfo(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public ASN1Set getCertificates()
- {
- return certs;
- }
-
- public ASN1Set getCRLs()
- {
- return crls;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (certs != null)
- {
- v.add(new DERTaggedObject(false, 0, certs));
- }
-
- if (crls != null)
- {
- v.add(new DERTaggedObject(false, 1, crls));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/OriginatorPublicKey.java b/core/src/main/java/org/bouncycastle/asn1/cms/OriginatorPublicKey.java
deleted file mode 100644
index b9bc52fa..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/OriginatorPublicKey.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.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
-{
- private AlgorithmIdentifier algorithm;
- private DERBitString publicKey;
-
- public OriginatorPublicKey(
- AlgorithmIdentifier algorithm,
- byte[] publicKey)
- {
- this.algorithm = algorithm;
- this.publicKey = new DERBitString(publicKey);
- }
-
- /**
- * @deprecated use getInstance()
- */
- public OriginatorPublicKey(
- ASN1Sequence seq)
- {
- algorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(0));
- publicKey = (DERBitString)seq.getObjectAt(1);
- }
-
- /**
- * 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
- * tagged false otherwise.
- * @exception IllegalArgumentException if the object held by the
- * tagged object cannot be converted.
- */
- public static OriginatorPublicKey getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- /**
- * 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.
- */
- public static OriginatorPublicKey getInstance(
- Object obj)
- {
- if (obj instanceof OriginatorPublicKey)
- {
- return (OriginatorPublicKey)obj;
- }
-
- if (obj != null)
- {
- return new OriginatorPublicKey(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public AlgorithmIdentifier getAlgorithm()
- {
- return algorithm;
- }
-
- public DERBitString getPublicKey()
- {
- return publicKey;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(algorithm);
- v.add(publicKey);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/OtherKeyAttribute.java b/core/src/main/java/org/bouncycastle/asn1/cms/OtherKeyAttribute.java
deleted file mode 100644
index 7363c814..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/OtherKeyAttribute.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.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
-{
- private ASN1ObjectIdentifier keyAttrId;
- private ASN1Encodable keyAttr;
-
- /**
- * 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.
- */
- public static OtherKeyAttribute getInstance(
- Object o)
- {
- if (o instanceof OtherKeyAttribute)
- {
- return (OtherKeyAttribute)o;
- }
-
- if (o != null)
- {
- return new OtherKeyAttribute(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- /**
- * @deprecated use getInstance()
- */
- public OtherKeyAttribute(
- ASN1Sequence seq)
- {
- keyAttrId = (ASN1ObjectIdentifier)seq.getObjectAt(0);
- keyAttr = seq.getObjectAt(1);
- }
-
- public OtherKeyAttribute(
- ASN1ObjectIdentifier keyAttrId,
- ASN1Encodable keyAttr)
- {
- this.keyAttrId = keyAttrId;
- this.keyAttr = keyAttr;
- }
-
- public ASN1ObjectIdentifier getKeyAttrId()
- {
- return keyAttrId;
- }
-
- public ASN1Encodable getKeyAttr()
- {
- return keyAttr;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(keyAttrId);
- v.add(keyAttr);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/OtherRecipientInfo.java b/core/src/main/java/org/bouncycastle/asn1/cms/OtherRecipientInfo.java
deleted file mode 100644
index b77b1508..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/OtherRecipientInfo.java
+++ /dev/null
@@ -1,112 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * <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
-{
- private ASN1ObjectIdentifier oriType;
- private ASN1Encodable oriValue;
-
- public OtherRecipientInfo(
- ASN1ObjectIdentifier oriType,
- ASN1Encodable oriValue)
- {
- this.oriType = oriType;
- this.oriValue = oriValue;
- }
-
- /**
- * @deprecated use getInstance().
- */
- public OtherRecipientInfo(
- ASN1Sequence seq)
- {
- oriType = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
- oriValue = seq.getObjectAt(1);
- }
-
- /**
- * 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
- * tagged false otherwise.
- * @exception IllegalArgumentException if the object held by the
- * tagged object cannot be converted.
- */
- public static OtherRecipientInfo getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- /**
- * 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.
- */
- public static OtherRecipientInfo getInstance(
- Object obj)
- {
- if (obj instanceof OtherRecipientInfo)
- {
- return (OtherRecipientInfo)obj;
- }
-
- if (obj != null)
- {
- return new OtherRecipientInfo(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public ASN1ObjectIdentifier getType()
- {
- return oriType;
- }
-
- public ASN1Encodable getValue()
- {
- return oriValue;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(oriType);
- v.add(oriValue);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/OtherRevocationInfoFormat.java b/core/src/main/java/org/bouncycastle/asn1/cms/OtherRevocationInfoFormat.java
deleted file mode 100644
index a8348ff6..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/OtherRevocationInfoFormat.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * <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
-{
- private ASN1ObjectIdentifier otherRevInfoFormat;
- private ASN1Encodable otherRevInfo;
-
- public OtherRevocationInfoFormat(
- ASN1ObjectIdentifier otherRevInfoFormat,
- ASN1Encodable otherRevInfo)
- {
- this.otherRevInfoFormat = otherRevInfoFormat;
- this.otherRevInfo = otherRevInfo;
- }
-
- private OtherRevocationInfoFormat(
- ASN1Sequence seq)
- {
- otherRevInfoFormat = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
- otherRevInfo = seq.getObjectAt(1);
- }
-
- /**
- * 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
- * tagged false otherwise.
- * @exception IllegalArgumentException if the object held by the
- * tagged object cannot be converted.
- */
- public static OtherRevocationInfoFormat getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- /**
- * 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.
- */
- public static OtherRevocationInfoFormat getInstance(
- Object obj)
- {
- if (obj instanceof OtherRevocationInfoFormat)
- {
- return (OtherRevocationInfoFormat)obj;
- }
-
- if (obj != null)
- {
- return new OtherRevocationInfoFormat(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public ASN1ObjectIdentifier getInfoFormat()
- {
- return otherRevInfoFormat;
- }
-
- public ASN1Encodable getInfo()
- {
- return otherRevInfo;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(otherRevInfoFormat);
- v.add(otherRevInfo);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/PasswordRecipientInfo.java b/core/src/main/java/org/bouncycastle/asn1/cms/PasswordRecipientInfo.java
deleted file mode 100644
index 7ed16cfc..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/PasswordRecipientInfo.java
+++ /dev/null
@@ -1,157 +0,0 @@
-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.ASN1TaggedObject;
-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
-{
- private ASN1Integer version;
- private AlgorithmIdentifier keyDerivationAlgorithm;
- private AlgorithmIdentifier keyEncryptionAlgorithm;
- private ASN1OctetString encryptedKey;
-
- public PasswordRecipientInfo(
- AlgorithmIdentifier keyEncryptionAlgorithm,
- ASN1OctetString encryptedKey)
- {
- this.version = new ASN1Integer(0);
- this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
- this.encryptedKey = encryptedKey;
- }
-
- public PasswordRecipientInfo(
- AlgorithmIdentifier keyDerivationAlgorithm,
- AlgorithmIdentifier keyEncryptionAlgorithm,
- ASN1OctetString encryptedKey)
- {
- this.version = new ASN1Integer(0);
- this.keyDerivationAlgorithm = keyDerivationAlgorithm;
- this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
- this.encryptedKey = encryptedKey;
- }
-
- /**
- * @deprecated use getInstance() method.
- */
- public PasswordRecipientInfo(
- ASN1Sequence seq)
- {
- version = (ASN1Integer)seq.getObjectAt(0);
- if (seq.getObjectAt(1) instanceof ASN1TaggedObject)
- {
- keyDerivationAlgorithm = AlgorithmIdentifier.getInstance((ASN1TaggedObject)seq.getObjectAt(1), false);
- keyEncryptionAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(2));
- encryptedKey = (ASN1OctetString)seq.getObjectAt(3);
- }
- else
- {
- keyEncryptionAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
- encryptedKey = (ASN1OctetString)seq.getObjectAt(2);
- }
- }
-
- /**
- * 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
- * tagged false otherwise.
- * @exception IllegalArgumentException if the object held by the
- * tagged object cannot be converted.
- */
- public static PasswordRecipientInfo getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- /**
- * 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.
- */
- public static PasswordRecipientInfo getInstance(
- Object obj)
- {
- if (obj instanceof PasswordRecipientInfo)
- {
- return (PasswordRecipientInfo)obj;
- }
-
- if (obj != null)
- {
- return new PasswordRecipientInfo(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public AlgorithmIdentifier getKeyDerivationAlgorithm()
- {
- return keyDerivationAlgorithm;
- }
-
- public AlgorithmIdentifier getKeyEncryptionAlgorithm()
- {
- return keyEncryptionAlgorithm;
- }
-
- public ASN1OctetString getEncryptedKey()
- {
- return encryptedKey;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(version);
-
- if (keyDerivationAlgorithm != null)
- {
- v.add(new DERTaggedObject(false, 0, keyDerivationAlgorithm));
- }
- v.add(keyEncryptionAlgorithm);
- v.add(encryptedKey);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/RecipientEncryptedKey.java b/core/src/main/java/org/bouncycastle/asn1/cms/RecipientEncryptedKey.java
deleted file mode 100644
index 5062c108..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/RecipientEncryptedKey.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-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
-{
- private KeyAgreeRecipientIdentifier identifier;
- private ASN1OctetString encryptedKey;
-
- private RecipientEncryptedKey(
- ASN1Sequence seq)
- {
- identifier = KeyAgreeRecipientIdentifier.getInstance(seq.getObjectAt(0));
- encryptedKey = (ASN1OctetString)seq.getObjectAt(1);
- }
-
- /**
- * 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
- * tagged false otherwise.
- * @exception IllegalArgumentException if the object held by the
- * tagged object cannot be converted.
- */
- public static RecipientEncryptedKey getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- /**
- * 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.
- */
- public static RecipientEncryptedKey getInstance(
- Object obj)
- {
- if (obj instanceof RecipientEncryptedKey)
- {
- return (RecipientEncryptedKey)obj;
- }
-
- if (obj != null)
- {
- return new RecipientEncryptedKey(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public RecipientEncryptedKey(
- KeyAgreeRecipientIdentifier id,
- ASN1OctetString encryptedKey)
- {
- this.identifier = id;
- this.encryptedKey = encryptedKey;
- }
-
- public KeyAgreeRecipientIdentifier getIdentifier()
- {
- return identifier;
- }
-
- public ASN1OctetString getEncryptedKey()
- {
- return encryptedKey;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(identifier);
- v.add(encryptedKey);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/RecipientIdentifier.java b/core/src/main/java/org/bouncycastle/asn1/cms/RecipientIdentifier.java
deleted file mode 100644
index 66b154a0..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/RecipientIdentifier.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-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
-{
- private ASN1Encodable id;
-
- public RecipientIdentifier(
- IssuerAndSerialNumber id)
- {
- this.id = id;
- }
-
- public RecipientIdentifier(
- ASN1OctetString id)
- {
- this.id = new DERTaggedObject(false, 0, id);
- }
-
- public RecipientIdentifier(
- ASN1Primitive id)
- {
- this.id = id;
- }
-
- /**
- * 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.
- */
- public static RecipientIdentifier getInstance(
- Object o)
- {
- if (o == null || o instanceof RecipientIdentifier)
- {
- return (RecipientIdentifier)o;
- }
-
- if (o instanceof IssuerAndSerialNumber)
- {
- return new RecipientIdentifier((IssuerAndSerialNumber)o);
- }
-
- if (o instanceof ASN1OctetString)
- {
- return new RecipientIdentifier((ASN1OctetString)o);
- }
-
- if (o instanceof ASN1Primitive)
- {
- return new RecipientIdentifier((ASN1Primitive)o);
- }
-
- throw new IllegalArgumentException(
- "Illegal object in RecipientIdentifier: " + o.getClass().getName());
- }
-
- public boolean isTagged()
- {
- return (id instanceof ASN1TaggedObject);
- }
-
- public ASN1Encodable getId()
- {
- if (id instanceof ASN1TaggedObject)
- {
- return ASN1OctetString.getInstance((ASN1TaggedObject)id, false);
- }
-
- return IssuerAndSerialNumber.getInstance(id);
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- return id.toASN1Primitive();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/RecipientInfo.java b/core/src/main/java/org/bouncycastle/asn1/cms/RecipientInfo.java
deleted file mode 100644
index 39a7bb26..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/RecipientInfo.java
+++ /dev/null
@@ -1,173 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-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.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
-{
- ASN1Encodable info;
-
- public RecipientInfo(
- KeyTransRecipientInfo info)
- {
- this.info = info;
- }
-
- public RecipientInfo(
- KeyAgreeRecipientInfo info)
- {
- this.info = new DERTaggedObject(false, 1, info);
- }
-
- public RecipientInfo(
- KEKRecipientInfo info)
- {
- this.info = new DERTaggedObject(false, 2, info);
- }
-
- public RecipientInfo(
- PasswordRecipientInfo info)
- {
- this.info = new DERTaggedObject(false, 3, info);
- }
-
- public RecipientInfo(
- OtherRecipientInfo info)
- {
- this.info = new DERTaggedObject(false, 4, info);
- }
-
- public RecipientInfo(
- ASN1Primitive info)
- {
- 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)
- {
- if (o == null || o instanceof RecipientInfo)
- {
- return (RecipientInfo)o;
- }
- else if (o instanceof ASN1Sequence)
- {
- return new RecipientInfo((ASN1Sequence)o);
- }
- else if (o instanceof ASN1TaggedObject)
- {
- return new RecipientInfo((ASN1TaggedObject)o);
- }
-
- throw new IllegalArgumentException("unknown object in factory: "
- + o.getClass().getName());
- }
-
- public ASN1Integer getVersion()
- {
- if (info instanceof ASN1TaggedObject)
- {
- ASN1TaggedObject o = (ASN1TaggedObject)info;
-
- switch (o.getTagNo())
- {
- case 1:
- return KeyAgreeRecipientInfo.getInstance(o, false).getVersion();
- case 2:
- return getKEKInfo(o).getVersion();
- case 3:
- return PasswordRecipientInfo.getInstance(o, false).getVersion();
- case 4:
- return new ASN1Integer(0); // no syntax version for OtherRecipientInfo
- default:
- throw new IllegalStateException("unknown tag");
- }
- }
-
- return KeyTransRecipientInfo.getInstance(info).getVersion();
- }
-
- public boolean isTagged()
- {
- return (info instanceof ASN1TaggedObject);
- }
-
- public ASN1Encodable getInfo()
- {
- if (info instanceof ASN1TaggedObject)
- {
- ASN1TaggedObject o = (ASN1TaggedObject)info;
-
- switch (o.getTagNo())
- {
- case 1:
- return KeyAgreeRecipientInfo.getInstance(o, false);
- case 2:
- return getKEKInfo(o);
- case 3:
- return PasswordRecipientInfo.getInstance(o, false);
- case 4:
- return OtherRecipientInfo.getInstance(o, false);
- default:
- throw new IllegalStateException("unknown tag");
- }
- }
-
- return KeyTransRecipientInfo.getInstance(info);
- }
-
- private KEKRecipientInfo getKEKInfo(ASN1TaggedObject o)
- {
- if (o.isExplicit())
- { // compatibilty with erroneous version
- return KEKRecipientInfo.getInstance(o, true);
- }
- else
- {
- return KEKRecipientInfo.getInstance(o, false);
- }
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- return info.toASN1Primitive();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/RecipientKeyIdentifier.java b/core/src/main/java/org/bouncycastle/asn1/cms/RecipientKeyIdentifier.java
deleted file mode 100644
index a680e4aa..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/RecipientKeyIdentifier.java
+++ /dev/null
@@ -1,171 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-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.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
-{
- private ASN1OctetString subjectKeyIdentifier;
- private ASN1GeneralizedTime date;
- private OtherKeyAttribute other;
-
- public RecipientKeyIdentifier(
- ASN1OctetString subjectKeyIdentifier,
- ASN1GeneralizedTime date,
- OtherKeyAttribute other)
- {
- this.subjectKeyIdentifier = subjectKeyIdentifier;
- this.date = date;
- this.other = other;
- }
-
- public RecipientKeyIdentifier(
- byte[] subjectKeyIdentifier,
- ASN1GeneralizedTime date,
- OtherKeyAttribute other)
- {
- this.subjectKeyIdentifier = new DEROctetString(subjectKeyIdentifier);
- this.date = date;
- this.other = other;
- }
-
- public RecipientKeyIdentifier(
- byte[] subjectKeyIdentifier)
- {
- this(subjectKeyIdentifier, null, null);
- }
-
- /**
- * @deprecated use getInstance()
- */
- public RecipientKeyIdentifier(
- ASN1Sequence seq)
- {
- subjectKeyIdentifier = ASN1OctetString.getInstance(
- seq.getObjectAt(0));
-
- switch(seq.size())
- {
- case 1:
- break;
- case 2:
- if (seq.getObjectAt(1) instanceof ASN1GeneralizedTime)
- {
- date = ASN1GeneralizedTime.getInstance(seq.getObjectAt(1));
- }
- else
- {
- other = OtherKeyAttribute.getInstance(seq.getObjectAt(2));
- }
- break;
- case 3:
- date = ASN1GeneralizedTime.getInstance(seq.getObjectAt(1));
- other = OtherKeyAttribute.getInstance(seq.getObjectAt(2));
- break;
- default:
- throw new IllegalArgumentException("Invalid RecipientKeyIdentifier");
- }
- }
-
- /**
- * Return a RecipientKeyIdentifier object from a tagged object.
- *
- * @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 isExplicit)
- {
- return getInstance(ASN1Sequence.getInstance(ato, isExplicit));
- }
-
- /**
- * 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.
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static RecipientKeyIdentifier getInstance(Object obj)
- {
- if (obj instanceof RecipientKeyIdentifier)
- {
- return (RecipientKeyIdentifier)obj;
- }
-
- if(obj != null)
- {
- return new RecipientKeyIdentifier(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public ASN1OctetString getSubjectKeyIdentifier()
- {
- return subjectKeyIdentifier;
- }
-
- public ASN1GeneralizedTime getDate()
- {
- return date;
- }
-
- public OtherKeyAttribute getOtherKeyAttribute()
- {
- return other;
- }
-
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(subjectKeyIdentifier);
-
- if (date != null)
- {
- v.add(date);
- }
-
- if (other != null)
- {
- v.add(other);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/SCVPReqRes.java b/core/src/main/java/org/bouncycastle/asn1/cms/SCVPReqRes.java
deleted file mode 100644
index 52279c33..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/SCVPReqRes.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * <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)
- {
- if (obj instanceof SCVPReqRes)
- {
- return (SCVPReqRes)obj;
- }
- else if (obj != null)
- {
- return new SCVPReqRes(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private SCVPReqRes(
- ASN1Sequence seq)
- {
- if (seq.getObjectAt(0) instanceof ASN1TaggedObject)
- {
- this.request = ContentInfo.getInstance(ASN1TaggedObject.getInstance(seq.getObjectAt(0)), true);
- this.response = ContentInfo.getInstance(seq.getObjectAt(1));
- }
- else
- {
- this.request = null;
- this.response = ContentInfo.getInstance(seq.getObjectAt(0));
- }
- }
-
- public SCVPReqRes(ContentInfo response)
- {
- this.request = null; // use of this confuses earlier JDKs
- this.response = response;
- }
-
- public SCVPReqRes(ContentInfo request, ContentInfo response)
- {
- this.request = request;
- this.response = response;
- }
-
- public ContentInfo getRequest()
- {
- return request;
- }
-
- public ContentInfo getResponse()
- {
- return response;
- }
-
- /**
- * @return the ASN.1 primitive representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (request != null)
- {
- v.add(new DERTaggedObject(true, 0, request));
- }
-
- v.add(response);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/SignedData.java b/core/src/main/java/org/bouncycastle/asn1/cms/SignedData.java
deleted file mode 100644
index 8c7fcc2d..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/SignedData.java
+++ /dev/null
@@ -1,330 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.BERSequence;
-import org.bouncycastle.asn1.BERSet;
-import org.bouncycastle.asn1.BERTaggedObject;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * <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
-{
- private static final ASN1Integer VERSION_1 = new ASN1Integer(1);
- private static final ASN1Integer VERSION_3 = new ASN1Integer(3);
- private static final ASN1Integer VERSION_4 = new ASN1Integer(4);
- private static final ASN1Integer VERSION_5 = new ASN1Integer(5);
-
- private ASN1Integer version;
- private ASN1Set digestAlgorithms;
- private ContentInfo contentInfo;
- private ASN1Set certificates;
- private ASN1Set crls;
- private ASN1Set signerInfos;
- 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)
- {
- if (o instanceof SignedData)
- {
- return (SignedData)o;
- }
- else if (o != null)
- {
- return new SignedData(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public SignedData(
- ASN1Set digestAlgorithms,
- ContentInfo contentInfo,
- ASN1Set certificates,
- ASN1Set crls,
- ASN1Set signerInfos)
- {
- this.version = calculateVersion(contentInfo.getContentType(), certificates, crls, signerInfos);
- this.digestAlgorithms = digestAlgorithms;
- this.contentInfo = contentInfo;
- this.certificates = certificates;
- this.crls = crls;
- this.signerInfos = signerInfos;
- this.crlsBer = crls instanceof BERSet;
- this.certsBer = certificates instanceof BERSet;
- }
-
-
- private ASN1Integer calculateVersion(
- ASN1ObjectIdentifier contentOid,
- ASN1Set certs,
- ASN1Set crls,
- ASN1Set signerInfs)
- {
- boolean otherCert = false;
- boolean otherCrl = false;
- boolean attrCertV1Found = false;
- boolean attrCertV2Found = false;
-
- if (certs != null)
- {
- for (Enumeration en = certs.getObjects(); en.hasMoreElements();)
- {
- Object obj = en.nextElement();
- if (obj instanceof ASN1TaggedObject)
- {
- ASN1TaggedObject tagged = ASN1TaggedObject.getInstance(obj);
-
- if (tagged.getTagNo() == 1)
- {
- attrCertV1Found = true;
- }
- else if (tagged.getTagNo() == 2)
- {
- attrCertV2Found = true;
- }
- else if (tagged.getTagNo() == 3)
- {
- otherCert = true;
- }
- }
- }
- }
-
- if (otherCert)
- {
- return new ASN1Integer(5);
- }
-
- if (crls != null) // no need to check if otherCert is true
- {
- for (Enumeration en = crls.getObjects(); en.hasMoreElements();)
- {
- Object obj = en.nextElement();
- if (obj instanceof ASN1TaggedObject)
- {
- otherCrl = true;
- }
- }
- }
-
- if (otherCrl)
- {
- return VERSION_5;
- }
-
- if (attrCertV2Found)
- {
- return VERSION_4;
- }
-
- if (attrCertV1Found)
- {
- return VERSION_3;
- }
-
- if (checkForVersion3(signerInfs))
- {
- return VERSION_3;
- }
-
- if (!CMSObjectIdentifiers.data.equals(contentOid))
- {
- return VERSION_3;
- }
-
- return VERSION_1;
- }
-
- private boolean checkForVersion3(ASN1Set signerInfs)
- {
- for (Enumeration e = signerInfs.getObjects(); e.hasMoreElements();)
- {
- SignerInfo s = SignerInfo.getInstance(e.nextElement());
-
- if (s.getVersion().getValue().intValue() == 3)
- {
- return true;
- }
- }
-
- return false;
- }
-
- private SignedData(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- version = ASN1Integer.getInstance(e.nextElement());
- digestAlgorithms = ((ASN1Set)e.nextElement());
- contentInfo = ContentInfo.getInstance(e.nextElement());
-
- while (e.hasMoreElements())
- {
- ASN1Primitive o = (ASN1Primitive)e.nextElement();
-
- //
- // an interesting feature of SignedData is that there appear
- // to be varying implementations...
- // for the moment we ignore anything which doesn't fit.
- //
- if (o instanceof ASN1TaggedObject)
- {
- ASN1TaggedObject tagged = (ASN1TaggedObject)o;
-
- switch (tagged.getTagNo())
- {
- case 0:
- certsBer = tagged instanceof BERTaggedObject;
- certificates = ASN1Set.getInstance(tagged, false);
- break;
- case 1:
- crlsBer = tagged instanceof BERTaggedObject;
- crls = ASN1Set.getInstance(tagged, false);
- break;
- default:
- throw new IllegalArgumentException("unknown tag value " + tagged.getTagNo());
- }
- }
- else
- {
- signerInfos = (ASN1Set)o;
- }
- }
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public ASN1Set getDigestAlgorithms()
- {
- return digestAlgorithms;
- }
-
- public ContentInfo getEncapContentInfo()
- {
- return contentInfo;
- }
-
- public ASN1Set getCertificates()
- {
- return certificates;
- }
-
- public ASN1Set getCRLs()
- {
- return crls;
- }
-
- public ASN1Set getSignerInfos()
- {
- return signerInfos;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(version);
- v.add(digestAlgorithms);
- v.add(contentInfo);
-
- if (certificates != null)
- {
- if (certsBer)
- {
- v.add(new BERTaggedObject(false, 0, certificates));
- }
- else
- {
- v.add(new DERTaggedObject(false, 0, certificates));
- }
- }
-
- if (crls != null)
- {
- if (crlsBer)
- {
- v.add(new BERTaggedObject(false, 1, crls));
- }
- else
- {
- v.add(new DERTaggedObject(false, 1, crls));
- }
- }
-
- v.add(signerInfos);
-
- return new BERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/SignedDataParser.java b/core/src/main/java/org/bouncycastle/asn1/cms/SignedDataParser.java
deleted file mode 100644
index df22b8e8..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/SignedDataParser.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1SequenceParser;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.ASN1SetParser;
-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,
- * digestAlgorithms DigestAlgorithmIdentifiers,
- * encapContentInfo EncapsulatedContentInfo,
- * certificates [0] IMPLICIT CertificateSet OPTIONAL,
- * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
- * signerInfos SignerInfos
- * }
- * </pre>
- */
-public class SignedDataParser
-{
- private ASN1SequenceParser _seq;
- private ASN1Integer _version;
- private Object _nextObject;
- private boolean _certsCalled;
- private boolean _crlsCalled;
-
- public static SignedDataParser getInstance(
- Object o)
- throws IOException
- {
- if (o instanceof ASN1Sequence)
- {
- return new SignedDataParser(((ASN1Sequence)o).parser());
- }
- if (o instanceof ASN1SequenceParser)
- {
- return new SignedDataParser((ASN1SequenceParser)o);
- }
-
- throw new IOException("unknown object encountered: " + o.getClass().getName());
- }
-
- private SignedDataParser(
- ASN1SequenceParser seq)
- throws IOException
- {
- this._seq = seq;
- this._version = (ASN1Integer)seq.readObject();
- }
-
- public ASN1Integer getVersion()
- {
- return _version;
- }
-
- public ASN1SetParser getDigestAlgorithms()
- throws IOException
- {
- Object o = _seq.readObject();
-
- if (o instanceof ASN1Set)
- {
- return ((ASN1Set)o).parser();
- }
-
- return (ASN1SetParser)o;
- }
-
- public ContentInfoParser getEncapContentInfo()
- throws IOException
- {
- return new ContentInfoParser((ASN1SequenceParser)_seq.readObject());
- }
-
- public ASN1SetParser getCertificates()
- throws IOException
- {
- _certsCalled = true;
- _nextObject = _seq.readObject();
-
- if (_nextObject instanceof ASN1TaggedObjectParser && ((ASN1TaggedObjectParser)_nextObject).getTagNo() == 0)
- {
- ASN1SetParser certs = (ASN1SetParser)((ASN1TaggedObjectParser)_nextObject).getObjectParser(BERTags.SET, false);
- _nextObject = null;
-
- return certs;
- }
-
- return null;
- }
-
- public ASN1SetParser getCrls()
- throws IOException
- {
- if (!_certsCalled)
- {
- throw new IOException("getCerts() has not been called.");
- }
-
- _crlsCalled = true;
-
- if (_nextObject == null)
- {
- _nextObject = _seq.readObject();
- }
-
- if (_nextObject instanceof ASN1TaggedObjectParser && ((ASN1TaggedObjectParser)_nextObject).getTagNo() == 1)
- {
- ASN1SetParser crls = (ASN1SetParser)((ASN1TaggedObjectParser)_nextObject).getObjectParser(BERTags.SET, false);
- _nextObject = null;
-
- return crls;
- }
-
- return null;
- }
-
- public ASN1SetParser getSignerInfos()
- throws IOException
- {
- if (!_certsCalled || !_crlsCalled)
- {
- throw new IOException("getCerts() and/or getCrls() has not been called.");
- }
-
- if (_nextObject == null)
- {
- _nextObject = _seq.readObject();
- }
-
- return (ASN1SetParser)_nextObject;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/SignerIdentifier.java b/core/src/main/java/org/bouncycastle/asn1/cms/SignerIdentifier.java
deleted file mode 100644
index 2543eb1c..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/SignerIdentifier.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-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
-{
- private ASN1Encodable id;
-
- public SignerIdentifier(
- IssuerAndSerialNumber id)
- {
- this.id = id;
- }
-
- public SignerIdentifier(
- ASN1OctetString id)
- {
- this.id = new DERTaggedObject(false, 0, id);
- }
-
- public SignerIdentifier(
- ASN1Primitive id)
- {
- this.id = id;
- }
-
- /**
- * 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.
- */
- public static SignerIdentifier getInstance(
- Object o)
- {
- if (o == null || o instanceof SignerIdentifier)
- {
- return (SignerIdentifier)o;
- }
-
- if (o instanceof IssuerAndSerialNumber)
- {
- return new SignerIdentifier((IssuerAndSerialNumber)o);
- }
-
- if (o instanceof ASN1OctetString)
- {
- return new SignerIdentifier((ASN1OctetString)o);
- }
-
- if (o instanceof ASN1Primitive)
- {
- return new SignerIdentifier((ASN1Primitive)o);
- }
-
- throw new IllegalArgumentException(
- "Illegal object in SignerIdentifier: " + o.getClass().getName());
- }
-
- public boolean isTagged()
- {
- return (id instanceof ASN1TaggedObject);
- }
-
- public ASN1Encodable getId()
- {
- if (id instanceof ASN1TaggedObject)
- {
- return ASN1OctetString.getInstance((ASN1TaggedObject)id, false);
- }
-
- return id;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- return id.toASN1Primitive();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/SignerInfo.java b/core/src/main/java/org/bouncycastle/asn1/cms/SignerInfo.java
deleted file mode 100644
index 42090458..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/SignerInfo.java
+++ /dev/null
@@ -1,282 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import java.util.Enumeration;
-
-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.ASN1Set;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DEROctetString;
-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
-{
- private ASN1Integer version;
- private SignerIdentifier sid;
- private AlgorithmIdentifier digAlgorithm;
- private ASN1Set authenticatedAttributes;
- private AlgorithmIdentifier digEncryptionAlgorithm;
- 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 instanceof SignerInfo)
- {
- return (SignerInfo)o;
- }
- else if (o != null)
- {
- return new SignerInfo(ASN1Sequence.getInstance(o));
- }
-
- 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,
- ASN1Set authenticatedAttributes,
- AlgorithmIdentifier digEncryptionAlgorithm,
- ASN1OctetString encryptedDigest,
- ASN1Set unauthenticatedAttributes)
- {
- if (sid.isTagged())
- {
- this.version = new ASN1Integer(3);
- }
- else
- {
- this.version = new ASN1Integer(1);
- }
-
- this.sid = sid;
- this.digAlgorithm = digAlgorithm;
- this.authenticatedAttributes = authenticatedAttributes;
- this.digEncryptionAlgorithm = digEncryptionAlgorithm;
- this.encryptedDigest = encryptedDigest;
- 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,
- Attributes authenticatedAttributes,
- AlgorithmIdentifier digEncryptionAlgorithm,
- ASN1OctetString encryptedDigest,
- Attributes unauthenticatedAttributes)
- {
- if (sid.isTagged())
- {
- this.version = new ASN1Integer(3);
- }
- else
- {
- this.version = new ASN1Integer(1);
- }
-
- this.sid = sid;
- this.digAlgorithm = digAlgorithm;
- this.authenticatedAttributes = ASN1Set.getInstance(authenticatedAttributes);
- this.digEncryptionAlgorithm = digEncryptionAlgorithm;
- this.encryptedDigest = encryptedDigest;
- this.unauthenticatedAttributes = ASN1Set.getInstance(unauthenticatedAttributes);
- }
-
- /**
- * @deprecated use getInstance() method.
- */
- public SignerInfo(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- version = (ASN1Integer)e.nextElement();
- sid = SignerIdentifier.getInstance(e.nextElement());
- digAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement());
-
- Object obj = e.nextElement();
-
- if (obj instanceof ASN1TaggedObject)
- {
- authenticatedAttributes = ASN1Set.getInstance((ASN1TaggedObject)obj, false);
-
- digEncryptionAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement());
- }
- else
- {
- authenticatedAttributes = null;
- digEncryptionAlgorithm = AlgorithmIdentifier.getInstance(obj);
- }
-
- encryptedDigest = DEROctetString.getInstance(e.nextElement());
-
- if (e.hasMoreElements())
- {
- unauthenticatedAttributes = ASN1Set.getInstance((ASN1TaggedObject)e.nextElement(), false);
- }
- else
- {
- unauthenticatedAttributes = null;
- }
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public SignerIdentifier getSID()
- {
- return sid;
- }
-
- public ASN1Set getAuthenticatedAttributes()
- {
- return authenticatedAttributes;
- }
-
- public AlgorithmIdentifier getDigestAlgorithm()
- {
- return digAlgorithm;
- }
-
- public ASN1OctetString getEncryptedDigest()
- {
- return encryptedDigest;
- }
-
- public AlgorithmIdentifier getDigestEncryptionAlgorithm()
- {
- return digEncryptionAlgorithm;
- }
-
- public ASN1Set getUnauthenticatedAttributes()
- {
- return unauthenticatedAttributes;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(version);
- v.add(sid);
- v.add(digAlgorithm);
-
- if (authenticatedAttributes != null)
- {
- v.add(new DERTaggedObject(false, 0, authenticatedAttributes));
- }
-
- v.add(digEncryptionAlgorithm);
- v.add(encryptedDigest);
-
- if (unauthenticatedAttributes != null)
- {
- v.add(new DERTaggedObject(false, 1, unauthenticatedAttributes));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/Time.java b/core/src/main/java/org/bouncycastle/asn1/cms/Time.java
deleted file mode 100644
index 84f12a9c..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/Time.java
+++ /dev/null
@@ -1,198 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-import java.util.SimpleTimeZone;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.ASN1UTCTime;
-import org.bouncycastle.asn1.DERGeneralizedTime;
-import org.bouncycastle.asn1.DERUTCTime;
-
-/**
- * <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
-{
- ASN1Primitive time;
-
- public static Time getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject());
- }
-
- /**
- * @deprecated use getInstance()
- */
- public Time(
- ASN1Primitive time)
- {
- if (!(time instanceof ASN1UTCTime)
- && !(time instanceof ASN1GeneralizedTime))
- {
- throw new IllegalArgumentException("unknown object passed to Time");
- }
-
- this.time = time;
- }
-
- /**
- * Creates a time object from a given date - if the date is between 1950
- * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
- * is used.
- *
- * @param time a date object representing the time of interest.
- */
- public Time(
- Date time)
- {
- SimpleTimeZone tz = new SimpleTimeZone(0, "Z");
- SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss");
-
- dateF.setTimeZone(tz);
-
- String d = dateF.format(time) + "Z";
- int year = Integer.parseInt(d.substring(0, 4));
-
- if (year < 1950 || year > 2049)
- {
- this.time = new DERGeneralizedTime(d);
- }
- else
- {
- this.time = new DERUTCTime(d.substring(2));
- }
- }
-
- /**
- * Creates a time object from a given date and locale - if the date is between 1950
- * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
- * is used. You may need to use this constructor if the default locale
- * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible with other ASN.1 implementations.
- *
- * @param time a date object representing the time of interest.
- * @param locale an appropriate Locale for producing an ASN.1 GeneralizedTime value.
- */
- public Time(
- Date time,
- Locale locale)
- {
- SimpleTimeZone tz = new SimpleTimeZone(0, "Z");
- SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss", locale);
-
- dateF.setTimeZone(tz);
-
- String d = dateF.format(time) + "Z";
- int year = Integer.parseInt(d.substring(0, 4));
-
- if (year < 1950 || year > 2049)
- {
- this.time = new DERGeneralizedTime(d);
- }
- else
- {
- this.time = new DERUTCTime(d.substring(2));
- }
- }
-
- /**
- * 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)
- {
- if (obj == null || obj instanceof Time)
- {
- return (Time)obj;
- }
- else if (obj instanceof ASN1UTCTime)
- {
- return new Time((ASN1UTCTime)obj);
- }
- else if (obj instanceof ASN1GeneralizedTime)
- {
- return new Time((ASN1GeneralizedTime)obj);
- }
-
- 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 ASN1UTCTime)
- {
- return ((ASN1UTCTime)time).getAdjustedTime();
- }
- else
- {
- return ((ASN1GeneralizedTime)time).getTime();
- }
- }
-
- /**
- * Get java.util.Date version of date+time.
- */
- public Date getDate()
- {
- try
- {
- if (time instanceof ASN1UTCTime)
- {
- return ((ASN1UTCTime)time).getAdjustedDate();
- }
- else
- {
- return ((ASN1GeneralizedTime)time).getDate();
- }
- }
- catch (ParseException e)
- { // this should never happen
- throw new IllegalStateException("invalid date string: " + e.getMessage());
- }
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- return time;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/TimeStampAndCRL.java b/core/src/main/java/org/bouncycastle/asn1/cms/TimeStampAndCRL.java
deleted file mode 100644
index f6d8d5a0..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/TimeStampAndCRL.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.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
-{
- private ContentInfo timeStamp;
- private CertificateList crl;
-
- public TimeStampAndCRL(ContentInfo timeStamp)
- {
- this.timeStamp = timeStamp;
- }
-
- private TimeStampAndCRL(ASN1Sequence seq)
- {
- this.timeStamp = ContentInfo.getInstance(seq.getObjectAt(0));
- if (seq.size() == 2)
- {
- this.crl = CertificateList.getInstance(seq.getObjectAt(1));
- }
- }
-
- /**
- * 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)
- {
- return (TimeStampAndCRL)obj;
- }
- else if (obj != null)
- {
- return new TimeStampAndCRL(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public ContentInfo getTimeStampToken()
- {
- return this.timeStamp;
- }
-
- /** @deprecated use getCRL() */
- public CertificateList getCertificateList()
- {
- return this.crl;
- }
-
- public CertificateList getCRL()
- {
- return this.crl;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(timeStamp);
-
- if (crl != null)
- {
- v.add(crl);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/TimeStampTokenEvidence.java b/core/src/main/java/org/bouncycastle/asn1/cms/TimeStampTokenEvidence.java
deleted file mode 100644
index 5461147b..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/TimeStampTokenEvidence.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * <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
-{
- private TimeStampAndCRL[] timeStampAndCRLs;
-
- public TimeStampTokenEvidence(TimeStampAndCRL[] timeStampAndCRLs)
- {
- this.timeStampAndCRLs = timeStampAndCRLs;
- }
-
- public TimeStampTokenEvidence(TimeStampAndCRL timeStampAndCRL)
- {
- this.timeStampAndCRLs = new TimeStampAndCRL[1];
-
- timeStampAndCRLs[0] = timeStampAndCRL;
- }
-
- private TimeStampTokenEvidence(ASN1Sequence seq)
- {
- this.timeStampAndCRLs = new TimeStampAndCRL[seq.size()];
-
- int count = 0;
-
- for (Enumeration en = seq.getObjects(); en.hasMoreElements();)
- {
- timeStampAndCRLs[count++] = TimeStampAndCRL.getInstance(en.nextElement());
- }
- }
-
- public static TimeStampTokenEvidence getInstance(ASN1TaggedObject tagged, boolean explicit)
- {
- 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)
- {
- return (TimeStampTokenEvidence)obj;
- }
- else if (obj != null)
- {
- return new TimeStampTokenEvidence(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public TimeStampAndCRL[] toTimeStampAndCRLArray()
- {
- return timeStampAndCRLs;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- for (int i = 0; i != timeStampAndCRLs.length; i++)
- {
- v.add(timeStampAndCRLs[i]);
- }
-
- return new DERSequence(v);
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/TimeStampedData.java b/core/src/main/java/org/bouncycastle/asn1/cms/TimeStampedData.java
deleted file mode 100644
index f19061e4..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/TimeStampedData.java
+++ /dev/null
@@ -1,131 +0,0 @@
-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.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
-{
- private ASN1Integer version;
- private DERIA5String dataUri;
- private MetaData metaData;
- private ASN1OctetString content;
- private Evidence temporalEvidence;
-
- public TimeStampedData(DERIA5String dataUri, MetaData metaData, ASN1OctetString content, Evidence temporalEvidence)
- {
- this.version = new ASN1Integer(1);
- this.dataUri = dataUri;
- this.metaData = metaData;
- this.content = content;
- this.temporalEvidence = temporalEvidence;
- }
-
- private TimeStampedData(ASN1Sequence seq)
- {
- this.version = ASN1Integer.getInstance(seq.getObjectAt(0));
-
- int index = 1;
- if (seq.getObjectAt(index) instanceof DERIA5String)
- {
- this.dataUri = DERIA5String.getInstance(seq.getObjectAt(index++));
- }
- if (seq.getObjectAt(index) instanceof MetaData || seq.getObjectAt(index) instanceof ASN1Sequence)
- {
- this.metaData = MetaData.getInstance(seq.getObjectAt(index++));
- }
- if (seq.getObjectAt(index) instanceof ASN1OctetString)
- {
- this.content = ASN1OctetString.getInstance(seq.getObjectAt(index++));
- }
- 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 == null || obj instanceof TimeStampedData)
- {
- return (TimeStampedData)obj;
- }
- return new TimeStampedData(ASN1Sequence.getInstance(obj));
- }
-
- public DERIA5String getDataUri()
- {
- return dataUri;
- }
-
- public MetaData getMetaData()
- {
- return metaData;
- }
-
- public ASN1OctetString getContent()
- {
- return content;
- }
-
- public Evidence getTemporalEvidence()
- {
- return temporalEvidence;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(version);
-
- if (dataUri != null)
- {
- v.add(dataUri);
- }
-
- if (metaData != null)
- {
- v.add(metaData);
- }
-
- if (content != null)
- {
- v.add(content);
- }
-
- v.add(temporalEvidence);
-
- return new BERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/TimeStampedDataParser.java b/core/src/main/java/org/bouncycastle/asn1/cms/TimeStampedDataParser.java
deleted file mode 100644
index f53e00fa..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/TimeStampedDataParser.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1OctetStringParser;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-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;
- private DERIA5String dataUri;
- private MetaData metaData;
- private ASN1OctetStringParser content;
- private Evidence temporalEvidence;
- private ASN1SequenceParser parser;
-
- private TimeStampedDataParser(ASN1SequenceParser parser)
- throws IOException
- {
- this.parser = parser;
- this.version = ASN1Integer.getInstance(parser.readObject());
-
- ASN1Encodable obj = parser.readObject();
-
- if (obj instanceof DERIA5String)
- {
- this.dataUri = DERIA5String.getInstance(obj);
- obj = parser.readObject();
- }
- if (obj instanceof MetaData || obj instanceof ASN1SequenceParser)
- {
- this.metaData = MetaData.getInstance(obj.toASN1Primitive());
- obj = parser.readObject();
- }
- if (obj instanceof ASN1OctetStringParser)
- {
- this.content = (ASN1OctetStringParser)obj;
- }
- }
-
- public static TimeStampedDataParser getInstance(Object obj)
- throws IOException
- {
- if (obj instanceof ASN1Sequence)
- {
- return new TimeStampedDataParser(((ASN1Sequence)obj).parser());
- }
- if (obj instanceof ASN1SequenceParser)
- {
- return new TimeStampedDataParser((ASN1SequenceParser)obj);
- }
-
- return null;
- }
-
- public DERIA5String getDataUri()
- {
- return dataUri;
- }
-
- public MetaData getMetaData()
- {
- return metaData;
- }
-
- public ASN1OctetStringParser getContent()
- {
- return content;
- }
-
- public Evidence getTemporalEvidence()
- throws IOException
- {
- if (temporalEvidence == null)
- {
- temporalEvidence = Evidence.getInstance(parser.readObject().toASN1Primitive());
- }
-
- return temporalEvidence;
- }
-
- /**
- * <pre>
- * TimeStampedData ::= SEQUENCE {
- * version INTEGER { v1(1) },
- * dataUri IA5String OPTIONAL,
- * metaData MetaData OPTIONAL,
- * content OCTET STRING OPTIONAL,
- * temporalEvidence Evidence
- * }
- * </pre>
- * @return
- * @deprecated will be removed
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(version);
-
- if (dataUri != null)
- {
- v.add(dataUri);
- }
-
- if (metaData != null)
- {
- v.add(metaData);
- }
-
- if (content != null)
- {
- v.add(content);
- }
-
- v.add(temporalEvidence);
-
- return new BERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cms/ecc/MQVuserKeyingMaterial.java b/core/src/main/java/org/bouncycastle/asn1/cms/ecc/MQVuserKeyingMaterial.java
deleted file mode 100644
index bd7267ba..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cms/ecc/MQVuserKeyingMaterial.java
+++ /dev/null
@@ -1,122 +0,0 @@
-package org.bouncycastle.asn1.cms.ecc;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.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
-{
- private OriginatorPublicKey ephemeralPublicKey;
- private ASN1OctetString addedukm;
-
- public MQVuserKeyingMaterial(
- OriginatorPublicKey ephemeralPublicKey,
- ASN1OctetString addedukm)
- {
- // TODO Check ephemeralPublicKey not null
-
- this.ephemeralPublicKey = ephemeralPublicKey;
- this.addedukm = addedukm;
- }
-
- private MQVuserKeyingMaterial(
- ASN1Sequence seq)
- {
- // TODO Check seq has either 1 or 2 elements
-
- this.ephemeralPublicKey = OriginatorPublicKey.getInstance(
- seq.getObjectAt(0));
-
- if (seq.size() > 1)
- {
- this.addedukm = ASN1OctetString.getInstance(
- (ASN1TaggedObject)seq.getObjectAt(1), true);
- }
- }
-
- /**
- * 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
- * tagged false otherwise.
- * @throws IllegalArgumentException if the object held by the
- * tagged object cannot be converted.
- */
- public static MQVuserKeyingMaterial getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- /**
- * 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.
- */
- public static MQVuserKeyingMaterial getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof MQVuserKeyingMaterial)
- {
- return (MQVuserKeyingMaterial)obj;
- }
-
- if (obj instanceof ASN1Sequence)
- {
- return new MQVuserKeyingMaterial((ASN1Sequence)obj);
- }
-
- throw new IllegalArgumentException("Invalid MQVuserKeyingMaterial: " + obj.getClass().getName());
- }
-
- public OriginatorPublicKey getEphemeralPublicKey()
- {
- return ephemeralPublicKey;
- }
-
- public ASN1OctetString getAddedukm()
- {
- return addedukm;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- v.add(ephemeralPublicKey);
-
- if (addedukm != null)
- {
- v.add(new DERTaggedObject(true, 0, addedukm));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/crmf/AttributeTypeAndValue.java b/core/src/main/java/org/bouncycastle/asn1/crmf/AttributeTypeAndValue.java
deleted file mode 100644
index ec7d2831..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/crmf/AttributeTypeAndValue.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package org.bouncycastle.asn1.crmf;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-public class AttributeTypeAndValue
- extends ASN1Object
-{
- private ASN1ObjectIdentifier type;
- private ASN1Encodable value;
-
- private AttributeTypeAndValue(ASN1Sequence seq)
- {
- type = (ASN1ObjectIdentifier)seq.getObjectAt(0);
- value = (ASN1Encodable)seq.getObjectAt(1);
- }
-
- public static AttributeTypeAndValue getInstance(Object o)
- {
- if (o instanceof AttributeTypeAndValue)
- {
- return (AttributeTypeAndValue)o;
- }
-
- if (o != null)
- {
- return new AttributeTypeAndValue(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public AttributeTypeAndValue(
- String oid,
- ASN1Encodable value)
- {
- this(new ASN1ObjectIdentifier(oid), value);
- }
-
- public AttributeTypeAndValue(
- ASN1ObjectIdentifier type,
- ASN1Encodable value)
- {
- this.type = type;
- this.value = value;
- }
-
- public ASN1ObjectIdentifier getType()
- {
- return type;
- }
-
- public ASN1Encodable getValue()
- {
- return value;
- }
-
- /**
- * <pre>
- * AttributeTypeAndValue ::= SEQUENCE {
- * type OBJECT IDENTIFIER,
- * value ANY DEFINED BY type }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(type);
- v.add(value);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/crmf/CRMFObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/crmf/CRMFObjectIdentifiers.java
deleted file mode 100644
index c298a7e8..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/crmf/CRMFObjectIdentifiers.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.bouncycastle.asn1.crmf;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-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
-
- /** 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");
- /** 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");
- /** 1.3.6.1.5.5.7.1.4 */
- static final ASN1ObjectIdentifier id_regCtrl_pkiArchiveOptions = id_regCtrl.branch("4");
-
- /** 1.2.840.113549.1.9.16.1,21 */
- static final ASN1ObjectIdentifier id_ct_encKeyWithID = PKCSObjectIdentifiers.id_ct.branch("21");
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/crmf/CertId.java b/core/src/main/java/org/bouncycastle/asn1/crmf/CertId.java
deleted file mode 100644
index bd54c119..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/crmf/CertId.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package org.bouncycastle.asn1.crmf;
-
-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.x509.GeneralName;
-
-public class CertId
- extends ASN1Object
-{
- private GeneralName issuer;
- private ASN1Integer serialNumber;
-
- private CertId(ASN1Sequence seq)
- {
- issuer = GeneralName.getInstance(seq.getObjectAt(0));
- serialNumber = ASN1Integer.getInstance(seq.getObjectAt(1));
- }
-
- public static CertId getInstance(Object o)
- {
- if (o instanceof CertId)
- {
- return (CertId)o;
- }
-
- if (o != null)
- {
- return new CertId(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public static CertId getInstance(ASN1TaggedObject obj, boolean isExplicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, isExplicit));
- }
-
- public CertId(GeneralName issuer, BigInteger serialNumber)
- {
- this(issuer, new ASN1Integer(serialNumber));
- }
-
- public CertId(GeneralName issuer, ASN1Integer serialNumber)
- {
- this.issuer = issuer;
- this.serialNumber = serialNumber;
- }
-
- public GeneralName getIssuer()
- {
- return issuer;
- }
-
- public ASN1Integer getSerialNumber()
- {
- return serialNumber;
- }
-
- /**
- * <pre>
- * CertId ::= SEQUENCE {
- * issuer GeneralName,
- * serialNumber INTEGER }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(issuer);
- v.add(serialNumber);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/crmf/CertReqMessages.java b/core/src/main/java/org/bouncycastle/asn1/crmf/CertReqMessages.java
deleted file mode 100644
index aa48a189..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/crmf/CertReqMessages.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package org.bouncycastle.asn1.crmf;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-public class CertReqMessages
- extends ASN1Object
-{
- private ASN1Sequence content;
-
- private CertReqMessages(ASN1Sequence seq)
- {
- content = seq;
- }
-
- public static CertReqMessages getInstance(Object o)
- {
- if (o instanceof CertReqMessages)
- {
- return (CertReqMessages)o;
- }
-
- if (o != null)
- {
- return new CertReqMessages(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public CertReqMessages(
- CertReqMsg msg)
- {
- content = new DERSequence(msg);
- }
-
- public CertReqMessages(
- CertReqMsg[] msgs)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- for (int i = 0; i < msgs.length; i++)
- {
- v.add(msgs[i]);
- }
- content = new DERSequence(v);
- }
-
- public CertReqMsg[] toCertReqMsgArray()
- {
- CertReqMsg[] result = new CertReqMsg[content.size()];
-
- for (int i = 0; i != result.length; i++)
- {
- result[i] = CertReqMsg.getInstance(content.getObjectAt(i));
- }
-
- return result;
- }
-
- /**
- * <pre>
- * CertReqMessages ::= SEQUENCE SIZE (1..MAX) OF CertReqMsg
- * </pre>
- *
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- return content;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/crmf/CertReqMsg.java b/core/src/main/java/org/bouncycastle/asn1/crmf/CertReqMsg.java
deleted file mode 100644
index 38936630..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/crmf/CertReqMsg.java
+++ /dev/null
@@ -1,145 +0,0 @@
-package org.bouncycastle.asn1.crmf;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-
-public class CertReqMsg
- extends ASN1Object
-{
- private CertRequest certReq;
- private ProofOfPossession pop;
- private ASN1Sequence regInfo;
-
- private CertReqMsg(ASN1Sequence seq)
- {
- Enumeration en = seq.getObjects();
-
- certReq = CertRequest.getInstance(en.nextElement());
- while (en.hasMoreElements())
- {
- Object o = en.nextElement();
-
- if (o instanceof ASN1TaggedObject || o instanceof ProofOfPossession)
- {
- pop = ProofOfPossession.getInstance(o);
- }
- else
- {
- regInfo = ASN1Sequence.getInstance(o);
- }
- }
- }
-
- public static CertReqMsg getInstance(Object o)
- {
- if (o instanceof CertReqMsg)
- {
- return (CertReqMsg)o;
- }
- else if (o != null)
- {
- return new CertReqMsg(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- /**
- * Creates a new CertReqMsg.
- * @param certReq CertRequest
- * @param pop may be null
- * @param regInfo may be null
- */
- public CertReqMsg(
- CertRequest certReq,
- ProofOfPossession pop,
- AttributeTypeAndValue[] regInfo)
- {
- if (certReq == null)
- {
- throw new IllegalArgumentException("'certReq' cannot be null");
- }
-
- this.certReq = certReq;
- this.pop = pop;
-
- if (regInfo != null)
- {
- this.regInfo = new DERSequence(regInfo);
- }
- }
-
- public CertRequest getCertReq()
- {
- return certReq;
- }
-
-
- /**
- * @deprecated use getPopo
- */
- public ProofOfPossession getPop()
- {
- return pop;
- }
-
-
- public ProofOfPossession getPopo()
- {
- return pop;
- }
-
- public AttributeTypeAndValue[] getRegInfo()
- {
- if (regInfo == null)
- {
- return null;
- }
-
- AttributeTypeAndValue[] results = new AttributeTypeAndValue[regInfo.size()];
-
- for (int i = 0; i != results.length; i++)
- {
- results[i] = AttributeTypeAndValue.getInstance(regInfo.getObjectAt(i));
- }
-
- return results;
- }
-
- /**
- * <pre>
- * CertReqMsg ::= SEQUENCE {
- * certReq CertRequest,
- * popo ProofOfPossession OPTIONAL,
- * -- content depends upon key type
- * regInfo SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue OPTIONAL }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(certReq);
-
- addOptional(v, pop);
- addOptional(v, regInfo);
-
- return new DERSequence(v);
- }
-
- private void addOptional(ASN1EncodableVector v, ASN1Encodable obj)
- {
- if (obj != null)
- {
- v.add(obj);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/crmf/CertRequest.java b/core/src/main/java/org/bouncycastle/asn1/crmf/CertRequest.java
deleted file mode 100644
index 70afe8ef..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/crmf/CertRequest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package org.bouncycastle.asn1.crmf;
-
-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.DERSequence;
-
-public class CertRequest
- extends ASN1Object
-{
- private ASN1Integer certReqId;
- private CertTemplate certTemplate;
- private Controls controls;
-
- private CertRequest(ASN1Sequence seq)
- {
- certReqId = new ASN1Integer(ASN1Integer.getInstance(seq.getObjectAt(0)).getValue());
- certTemplate = CertTemplate.getInstance(seq.getObjectAt(1));
- if (seq.size() > 2)
- {
- controls = Controls.getInstance(seq.getObjectAt(2));
- }
- }
-
- public static CertRequest getInstance(Object o)
- {
- if (o instanceof CertRequest)
- {
- return (CertRequest)o;
- }
- else if (o != null)
- {
- return new CertRequest(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public CertRequest(
- int certReqId,
- CertTemplate certTemplate,
- Controls controls)
- {
- this(new ASN1Integer(certReqId), certTemplate, controls);
- }
-
- public CertRequest(
- ASN1Integer certReqId,
- CertTemplate certTemplate,
- Controls controls)
- {
- this.certReqId = certReqId;
- this.certTemplate = certTemplate;
- this.controls = controls;
- }
-
- public ASN1Integer getCertReqId()
- {
- return certReqId;
- }
-
- public CertTemplate getCertTemplate()
- {
- return certTemplate;
- }
-
- public Controls getControls()
- {
- return controls;
- }
-
- /**
- * <pre>
- * CertRequest ::= SEQUENCE {
- * certReqId INTEGER, -- ID for matching request and reply
- * certTemplate CertTemplate, -- Selected fields of cert to be issued
- * controls Controls OPTIONAL } -- Attributes affecting issuance
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(certReqId);
- v.add(certTemplate);
-
- if (controls != null)
- {
- v.add(controls);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/crmf/CertTemplate.java b/core/src/main/java/org/bouncycastle/asn1/crmf/CertTemplate.java
deleted file mode 100644
index 73412e9a..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/crmf/CertTemplate.java
+++ /dev/null
@@ -1,163 +0,0 @@
-package org.bouncycastle.asn1.crmf;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.Extensions;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-
-public class CertTemplate
- extends ASN1Object
-{
- private ASN1Sequence seq;
-
- private ASN1Integer version;
- private ASN1Integer serialNumber;
- private AlgorithmIdentifier signingAlg;
- private X500Name issuer;
- private OptionalValidity validity;
- private X500Name subject;
- private SubjectPublicKeyInfo publicKey;
- private DERBitString issuerUID;
- private DERBitString subjectUID;
- private Extensions extensions;
-
- private CertTemplate(ASN1Sequence seq)
- {
- this.seq = seq;
-
- Enumeration en = seq.getObjects();
- while (en.hasMoreElements())
- {
- ASN1TaggedObject tObj = (ASN1TaggedObject)en.nextElement();
-
- switch (tObj.getTagNo())
- {
- case 0:
- version = ASN1Integer.getInstance(tObj, false);
- break;
- case 1:
- serialNumber = ASN1Integer.getInstance(tObj, false);
- break;
- case 2:
- signingAlg = AlgorithmIdentifier.getInstance(tObj, false);
- break;
- case 3:
- issuer = X500Name.getInstance(tObj, true); // CHOICE
- break;
- case 4:
- validity = OptionalValidity.getInstance(ASN1Sequence.getInstance(tObj, false));
- break;
- case 5:
- subject = X500Name.getInstance(tObj, true); // CHOICE
- break;
- case 6:
- publicKey = SubjectPublicKeyInfo.getInstance(tObj, false);
- break;
- case 7:
- issuerUID = DERBitString.getInstance(tObj, false);
- break;
- case 8:
- subjectUID = DERBitString.getInstance(tObj, false);
- break;
- case 9:
- extensions = Extensions.getInstance(tObj, false);
- break;
- default:
- throw new IllegalArgumentException("unknown tag: " + tObj.getTagNo());
- }
- }
- }
-
- public static CertTemplate getInstance(Object o)
- {
- if (o instanceof CertTemplate)
- {
- return (CertTemplate)o;
- }
- else if (o != null)
- {
- return new CertTemplate(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public int getVersion()
- {
- return version.getValue().intValue();
- }
-
- public ASN1Integer getSerialNumber()
- {
- return serialNumber;
- }
-
- public AlgorithmIdentifier getSigningAlg()
- {
- return signingAlg;
- }
-
- public X500Name getIssuer()
- {
- return issuer;
- }
-
- public OptionalValidity getValidity()
- {
- return validity;
- }
-
- public X500Name getSubject()
- {
- return subject;
- }
-
- public SubjectPublicKeyInfo getPublicKey()
- {
- return publicKey;
- }
-
- public DERBitString getIssuerUID()
- {
- return issuerUID;
- }
-
- public DERBitString getSubjectUID()
- {
- return subjectUID;
- }
-
- public Extensions getExtensions()
- {
- return extensions;
- }
-
- /**
- * <pre>
- * CertTemplate ::= SEQUENCE {
- * version [0] Version OPTIONAL,
- * serialNumber [1] INTEGER OPTIONAL,
- * signingAlg [2] AlgorithmIdentifier OPTIONAL,
- * issuer [3] Name OPTIONAL,
- * validity [4] OptionalValidity OPTIONAL,
- * subject [5] Name OPTIONAL,
- * publicKey [6] SubjectPublicKeyInfo OPTIONAL,
- * issuerUID [7] UniqueIdentifier OPTIONAL,
- * subjectUID [8] UniqueIdentifier OPTIONAL,
- * extensions [9] Extensions OPTIONAL }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- return seq;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/crmf/CertTemplateBuilder.java b/core/src/main/java/org/bouncycastle/asn1/crmf/CertTemplateBuilder.java
deleted file mode 100644
index be5cbe6a..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/crmf/CertTemplateBuilder.java
+++ /dev/null
@@ -1,152 +0,0 @@
-package org.bouncycastle.asn1.crmf;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.Extensions;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.asn1.x509.X509Extensions;
-
-public class CertTemplateBuilder
-{
- private ASN1Integer version;
- private ASN1Integer serialNumber;
- private AlgorithmIdentifier signingAlg;
- private X500Name issuer;
- private OptionalValidity validity;
- private X500Name subject;
- private SubjectPublicKeyInfo publicKey;
- private DERBitString issuerUID;
- private DERBitString subjectUID;
- private Extensions extensions;
-
- /** Sets the X.509 version. Note: for X509v3, use 2 here. */
- public CertTemplateBuilder setVersion(int ver)
- {
- version = new ASN1Integer(ver);
-
- return this;
- }
-
- public CertTemplateBuilder setSerialNumber(ASN1Integer ser)
- {
- serialNumber = ser;
-
- return this;
- }
-
- public CertTemplateBuilder setSigningAlg(AlgorithmIdentifier aid)
- {
- signingAlg = aid;
-
- return this;
- }
-
- public CertTemplateBuilder setIssuer(X500Name name)
- {
- issuer = name;
-
- return this;
- }
-
- public CertTemplateBuilder setValidity(OptionalValidity v)
- {
- validity = v;
-
- return this;
- }
-
- public CertTemplateBuilder setSubject(X500Name name)
- {
- subject = name;
-
- return this;
- }
-
- public CertTemplateBuilder setPublicKey(SubjectPublicKeyInfo spki)
- {
- publicKey = spki;
-
- return this;
- }
-
- /** Sets the issuer unique ID (deprecated in X.509v3) */
- public CertTemplateBuilder setIssuerUID(DERBitString uid)
- {
- issuerUID = uid;
-
- return this;
- }
-
- /** Sets the subject unique ID (deprecated in X.509v3) */
- public CertTemplateBuilder setSubjectUID(DERBitString uid)
- {
- subjectUID = uid;
-
- return this;
- }
-
- /**
- * @deprecated use method taking Extensions
- * @param extens
- * @return
- */
- public CertTemplateBuilder setExtensions(X509Extensions extens)
- {
- return setExtensions(Extensions.getInstance(extens));
- }
-
- public CertTemplateBuilder setExtensions(Extensions extens)
- {
- extensions = extens;
-
- return this;
- }
-
- /**
- * <pre>
- * CertTemplate ::= SEQUENCE {
- * version [0] Version OPTIONAL,
- * serialNumber [1] INTEGER OPTIONAL,
- * signingAlg [2] AlgorithmIdentifier OPTIONAL,
- * issuer [3] Name OPTIONAL,
- * validity [4] OptionalValidity OPTIONAL,
- * subject [5] Name OPTIONAL,
- * publicKey [6] SubjectPublicKeyInfo OPTIONAL,
- * issuerUID [7] UniqueIdentifier OPTIONAL,
- * subjectUID [8] UniqueIdentifier OPTIONAL,
- * extensions [9] Extensions OPTIONAL }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public CertTemplate build()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- addOptional(v, 0, false, version);
- addOptional(v, 1, false, serialNumber);
- addOptional(v, 2, false, signingAlg);
- addOptional(v, 3, true, issuer); // CHOICE
- addOptional(v, 4, false, validity);
- addOptional(v, 5, true, subject); // CHOICE
- addOptional(v, 6, false, publicKey);
- addOptional(v, 7, false, issuerUID);
- addOptional(v, 8, false, subjectUID);
- addOptional(v, 9, false, extensions);
-
- return CertTemplate.getInstance(new DERSequence(v));
- }
-
- private void addOptional(ASN1EncodableVector v, int tagNo, boolean isExplicit, ASN1Encodable obj)
- {
- if (obj != null)
- {
- v.add(new DERTaggedObject(isExplicit, tagNo, obj));
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/crmf/Controls.java b/core/src/main/java/org/bouncycastle/asn1/crmf/Controls.java
deleted file mode 100644
index 2e188fe9..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/crmf/Controls.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.bouncycastle.asn1.crmf;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-public class Controls
- extends ASN1Object
-{
- private ASN1Sequence content;
-
- private Controls(ASN1Sequence seq)
- {
- content = seq;
- }
-
- public static Controls getInstance(Object o)
- {
- if (o instanceof Controls)
- {
- return (Controls)o;
- }
-
- if (o != null)
- {
- return new Controls(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public Controls(AttributeTypeAndValue atv)
- {
- content = new DERSequence(atv);
- }
-
- public Controls(AttributeTypeAndValue[] atvs)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- for (int i = 0; i < atvs.length; i++)
- {
- v.add(atvs[i]);
- }
- content = new DERSequence(v);
- }
-
- public AttributeTypeAndValue[] toAttributeTypeAndValueArray()
- {
- AttributeTypeAndValue[] result = new AttributeTypeAndValue[content.size()];
-
- for (int i = 0; i != result.length; i++)
- {
- result[i] = AttributeTypeAndValue.getInstance(content.getObjectAt(i));
- }
-
- return result;
- }
-
- /**
- * <pre>
- * Controls ::= SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue
- * </pre>
- *
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- return content;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/crmf/EncKeyWithID.java b/core/src/main/java/org/bouncycastle/asn1/crmf/EncKeyWithID.java
deleted file mode 100644
index 478a9185..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/crmf/EncKeyWithID.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package org.bouncycastle.asn1.crmf;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERUTF8String;
-import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
-import org.bouncycastle.asn1.x509.GeneralName;
-
-public class EncKeyWithID
- extends ASN1Object
-{
- private final PrivateKeyInfo privKeyInfo;
- private final ASN1Encodable identifier;
-
- public static EncKeyWithID getInstance(Object o)
- {
- if (o instanceof EncKeyWithID)
- {
- return (EncKeyWithID)o;
- }
- else if (o != null)
- {
- return new EncKeyWithID(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- private EncKeyWithID(ASN1Sequence seq)
- {
- this.privKeyInfo = PrivateKeyInfo.getInstance(seq.getObjectAt(0));
-
- if (seq.size() > 1)
- {
- if (!(seq.getObjectAt(1) instanceof DERUTF8String))
- {
- this.identifier = GeneralName.getInstance(seq.getObjectAt(1));
- }
- else
- {
- this.identifier = (ASN1Encodable)seq.getObjectAt(1);
- }
- }
- else
- {
- this.identifier = null;
- }
- }
-
- public EncKeyWithID(PrivateKeyInfo privKeyInfo)
- {
- this.privKeyInfo = privKeyInfo;
- this.identifier = null;
- }
-
- public EncKeyWithID(PrivateKeyInfo privKeyInfo, DERUTF8String str)
- {
- this.privKeyInfo = privKeyInfo;
- this.identifier = str;
- }
-
- public EncKeyWithID(PrivateKeyInfo privKeyInfo, GeneralName generalName)
- {
- this.privKeyInfo = privKeyInfo;
- this.identifier = generalName;
- }
-
- public PrivateKeyInfo getPrivateKey()
- {
- return privKeyInfo;
- }
-
- public boolean hasIdentifier()
- {
- return identifier != null;
- }
-
- public boolean isIdentifierUTF8String()
- {
- return identifier instanceof DERUTF8String;
- }
-
- public ASN1Encodable getIdentifier()
- {
- return identifier;
- }
-
- /**
- * <pre>
- * EncKeyWithID ::= SEQUENCE {
- * privateKey PrivateKeyInfo,
- * identifier CHOICE {
- * string UTF8String,
- * generalName GeneralName
- * } OPTIONAL
- * }
- * </pre>
- * @return
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(privKeyInfo);
-
- if (identifier != null)
- {
- v.add(identifier);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/crmf/EncryptedKey.java b/core/src/main/java/org/bouncycastle/asn1/crmf/EncryptedKey.java
deleted file mode 100644
index 10ae47b5..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/crmf/EncryptedKey.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package org.bouncycastle.asn1.crmf;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.cms.EnvelopedData;
-
-public class EncryptedKey
- extends ASN1Object
- implements ASN1Choice
-{
- private EnvelopedData envelopedData;
- private EncryptedValue encryptedValue;
-
- public static EncryptedKey getInstance(Object o)
- {
- if (o instanceof EncryptedKey)
- {
- return (EncryptedKey)o;
- }
- else if (o instanceof ASN1TaggedObject)
- {
- return new EncryptedKey(EnvelopedData.getInstance((ASN1TaggedObject)o, false));
- }
- else if (o instanceof EncryptedValue)
- {
- return new EncryptedKey((EncryptedValue)o);
- }
- else
- {
- return new EncryptedKey(EncryptedValue.getInstance(o));
- }
- }
-
- public EncryptedKey(EnvelopedData envelopedData)
- {
- this.envelopedData = envelopedData;
- }
-
- public EncryptedKey(EncryptedValue encryptedValue)
- {
- this.encryptedValue = encryptedValue;
- }
-
- public boolean isEncryptedValue()
- {
- return encryptedValue != null;
- }
-
- public ASN1Encodable getValue()
- {
- if (encryptedValue != null)
- {
- return encryptedValue;
- }
-
- return envelopedData;
- }
-
- /**
- * <pre>
- * EncryptedKey ::= CHOICE {
- * encryptedValue EncryptedValue, -- deprecated
- * envelopedData [0] EnvelopedData }
- * -- The encrypted private key MUST be placed in the envelopedData
- * -- encryptedContentInfo encryptedContent OCTET STRING.
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- if (encryptedValue != null)
- {
- return encryptedValue.toASN1Primitive();
- }
-
- return new DERTaggedObject(false, 0, envelopedData);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/crmf/EncryptedValue.java b/core/src/main/java/org/bouncycastle/asn1/crmf/EncryptedValue.java
deleted file mode 100644
index 3aa54579..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/crmf/EncryptedValue.java
+++ /dev/null
@@ -1,164 +0,0 @@
-package org.bouncycastle.asn1.crmf;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-public class EncryptedValue
- extends ASN1Object
-{
- private AlgorithmIdentifier intendedAlg;
- private AlgorithmIdentifier symmAlg;
- private DERBitString encSymmKey;
- private AlgorithmIdentifier keyAlg;
- private ASN1OctetString valueHint;
- private DERBitString encValue;
-
- private EncryptedValue(ASN1Sequence seq)
- {
- int index = 0;
- while (seq.getObjectAt(index) instanceof ASN1TaggedObject)
- {
- ASN1TaggedObject tObj = (ASN1TaggedObject)seq.getObjectAt(index);
-
- switch (tObj.getTagNo())
- {
- case 0:
- intendedAlg = AlgorithmIdentifier.getInstance(tObj, false);
- break;
- case 1:
- symmAlg = AlgorithmIdentifier.getInstance(tObj, false);
- break;
- case 2:
- encSymmKey = DERBitString.getInstance(tObj, false);
- break;
- case 3:
- keyAlg = AlgorithmIdentifier.getInstance(tObj, false);
- break;
- case 4:
- valueHint = ASN1OctetString.getInstance(tObj, false);
- break;
- }
- index++;
- }
-
- encValue = DERBitString.getInstance(seq.getObjectAt(index));
- }
-
- public static EncryptedValue getInstance(Object o)
- {
- if (o instanceof EncryptedValue)
- {
- return (EncryptedValue)o;
- }
- else if (o != null)
- {
- return new EncryptedValue(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public EncryptedValue(
- AlgorithmIdentifier intendedAlg,
- AlgorithmIdentifier symmAlg,
- DERBitString encSymmKey,
- AlgorithmIdentifier keyAlg,
- ASN1OctetString valueHint,
- DERBitString encValue)
- {
- if (encValue == null)
- {
- throw new IllegalArgumentException("'encValue' cannot be null");
- }
-
- this.intendedAlg = intendedAlg;
- this.symmAlg = symmAlg;
- this.encSymmKey = encSymmKey;
- this.keyAlg = keyAlg;
- this.valueHint = valueHint;
- this.encValue = encValue;
- }
-
- public AlgorithmIdentifier getIntendedAlg()
- {
- return intendedAlg;
- }
-
- public AlgorithmIdentifier getSymmAlg()
- {
- return symmAlg;
- }
-
- public DERBitString getEncSymmKey()
- {
- return encSymmKey;
- }
-
- public AlgorithmIdentifier getKeyAlg()
- {
- return keyAlg;
- }
-
- public ASN1OctetString getValueHint()
- {
- return valueHint;
- }
-
- public DERBitString getEncValue()
- {
- return encValue;
- }
-
- /**
- * <pre>
- * EncryptedValue ::= SEQUENCE {
- * intendedAlg [0] AlgorithmIdentifier OPTIONAL,
- * -- the intended algorithm for which the value will be used
- * symmAlg [1] AlgorithmIdentifier OPTIONAL,
- * -- the symmetric algorithm used to encrypt the value
- * encSymmKey [2] BIT STRING OPTIONAL,
- * -- the (encrypted) symmetric key used to encrypt the value
- * keyAlg [3] AlgorithmIdentifier OPTIONAL,
- * -- algorithm used to encrypt the symmetric key
- * valueHint [4] OCTET STRING OPTIONAL,
- * -- a brief description or identifier of the encValue content
- * -- (may be meaningful only to the sending entity, and used only
- * -- if EncryptedValue might be re-examined by the sending entity
- * -- in the future)
- * encValue BIT STRING }
- * -- the encrypted value itself
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- addOptional(v, 0, intendedAlg);
- addOptional(v, 1, symmAlg);
- addOptional(v, 2, encSymmKey);
- addOptional(v, 3, keyAlg);
- addOptional(v, 4, valueHint);
-
- v.add(encValue);
-
- return new DERSequence(v);
- }
-
- private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj)
- {
- if (obj != null)
- {
- v.add(new DERTaggedObject(false, tagNo, obj));
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/crmf/OptionalValidity.java b/core/src/main/java/org/bouncycastle/asn1/crmf/OptionalValidity.java
deleted file mode 100644
index 9174b5f7..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/crmf/OptionalValidity.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package org.bouncycastle.asn1.crmf;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.Time;
-
-public class OptionalValidity
- extends ASN1Object
-{
- private Time notBefore;
- private Time notAfter;
-
- private OptionalValidity(ASN1Sequence seq)
- {
- Enumeration en = seq.getObjects();
- while (en.hasMoreElements())
- {
- ASN1TaggedObject tObj = (ASN1TaggedObject)en.nextElement();
-
- if (tObj.getTagNo() == 0)
- {
- notBefore = Time.getInstance(tObj, true);
- }
- else
- {
- notAfter = Time.getInstance(tObj, true);
- }
- }
- }
-
- public static OptionalValidity getInstance(Object o)
- {
- if (o instanceof OptionalValidity)
- {
- return (OptionalValidity)o;
- }
-
- if (o != null)
- {
- return new OptionalValidity(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public OptionalValidity(Time notBefore, Time notAfter)
- {
- if (notBefore == null && notAfter == null)
- {
- throw new IllegalArgumentException("at least one of notBefore/notAfter must not be null.");
- }
-
- this.notBefore = notBefore;
- this.notAfter = notAfter;
- }
-
- public Time getNotBefore()
- {
- return notBefore;
- }
-
- public Time getNotAfter()
- {
- return notAfter;
- }
-
- /**
- * <pre>
- * OptionalValidity ::= SEQUENCE {
- * notBefore [0] Time OPTIONAL,
- * notAfter [1] Time OPTIONAL } --at least one MUST be present
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (notBefore != null)
- {
- v.add(new DERTaggedObject(true, 0, notBefore));
- }
-
- if (notAfter != null)
- {
- v.add(new DERTaggedObject(true, 1, notAfter));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/crmf/PKIArchiveOptions.java b/core/src/main/java/org/bouncycastle/asn1/crmf/PKIArchiveOptions.java
deleted file mode 100644
index 46e0e44c..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/crmf/PKIArchiveOptions.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package org.bouncycastle.asn1.crmf;
-
-import org.bouncycastle.asn1.ASN1Boolean;
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-public class PKIArchiveOptions
- extends ASN1Object
- implements ASN1Choice
-{
- public static final int encryptedPrivKey = 0;
- public static final int keyGenParameters = 1;
- public static final int archiveRemGenPrivKey = 2;
-
- private ASN1Encodable value;
-
- public static PKIArchiveOptions getInstance(Object o)
- {
- if (o == null || o instanceof PKIArchiveOptions)
- {
- return (PKIArchiveOptions)o;
- }
- else if (o instanceof ASN1TaggedObject)
- {
- return new PKIArchiveOptions((ASN1TaggedObject)o);
- }
-
- throw new IllegalArgumentException("unknown object: " + o);
- }
-
- private PKIArchiveOptions(ASN1TaggedObject tagged)
- {
- switch (tagged.getTagNo())
- {
- case encryptedPrivKey:
- value = EncryptedKey.getInstance(tagged.getObject());
- break;
- case keyGenParameters:
- value = ASN1OctetString.getInstance(tagged, false);
- break;
- case archiveRemGenPrivKey:
- value = ASN1Boolean.getInstance(tagged, false);
- break;
- default:
- throw new IllegalArgumentException("unknown tag number: " + tagged.getTagNo());
- }
- }
-
- public PKIArchiveOptions(EncryptedKey encKey)
- {
- this.value = encKey;
- }
-
- public PKIArchiveOptions(ASN1OctetString keyGenParameters)
- {
- this.value = keyGenParameters;
- }
-
- public PKIArchiveOptions(boolean archiveRemGenPrivKey)
- {
- this.value = ASN1Boolean.getInstance(archiveRemGenPrivKey);
- }
-
- public int getType()
- {
- if (value instanceof EncryptedKey)
- {
- return encryptedPrivKey;
- }
-
- if (value instanceof ASN1OctetString)
- {
- return keyGenParameters;
- }
-
- return archiveRemGenPrivKey;
- }
-
- public ASN1Encodable getValue()
- {
- return value;
- }
-
- /**
- * <pre>
- * PKIArchiveOptions ::= CHOICE {
- * encryptedPrivKey [0] EncryptedKey,
- * -- the actual value of the private key
- * keyGenParameters [1] KeyGenParameters,
- * -- parameters which allow the private key to be re-generated
- * archiveRemGenPrivKey [2] BOOLEAN }
- * -- set to TRUE if sender wishes receiver to archive the private
- * -- key of a key pair that the receiver generates in response to
- * -- this request; set to FALSE if no archival is desired.
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- if (value instanceof EncryptedKey)
- {
- return new DERTaggedObject(true, encryptedPrivKey, value); // choice
- }
-
- if (value instanceof ASN1OctetString)
- {
- return new DERTaggedObject(false, keyGenParameters, value);
- }
-
- return new DERTaggedObject(false, archiveRemGenPrivKey, value);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/crmf/PKIPublicationInfo.java b/core/src/main/java/org/bouncycastle/asn1/crmf/PKIPublicationInfo.java
deleted file mode 100644
index dba0422d..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/crmf/PKIPublicationInfo.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package org.bouncycastle.asn1.crmf;
-
-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.DERSequence;
-
-public class PKIPublicationInfo
- extends ASN1Object
-{
- private ASN1Integer action;
- private ASN1Sequence pubInfos;
-
- private PKIPublicationInfo(ASN1Sequence seq)
- {
- action = ASN1Integer.getInstance(seq.getObjectAt(0));
- pubInfos = ASN1Sequence.getInstance(seq.getObjectAt(1));
- }
-
- public static PKIPublicationInfo getInstance(Object o)
- {
- if (o instanceof PKIPublicationInfo)
- {
- return (PKIPublicationInfo)o;
- }
-
- if (o != null)
- {
- return new PKIPublicationInfo(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public ASN1Integer getAction()
- {
- return action;
- }
-
- public SinglePubInfo[] getPubInfos()
- {
- if (pubInfos == null)
- {
- return null;
- }
-
- SinglePubInfo[] results = new SinglePubInfo[pubInfos.size()];
-
- for (int i = 0; i != results.length; i++)
- {
- results[i] = SinglePubInfo.getInstance(pubInfos.getObjectAt(i));
- }
-
- return results;
- }
-
- /**
- * <pre>
- * PKIPublicationInfo ::= SEQUENCE {
- * action INTEGER {
- * dontPublish (0),
- * pleasePublish (1) },
- * pubInfos SEQUENCE SIZE (1..MAX) OF SinglePubInfo OPTIONAL }
- * -- pubInfos MUST NOT be present if action is "dontPublish"
- * -- (if action is "pleasePublish" and pubInfos is omitted,
- * -- "dontCare" is assumed)
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(action);
- v.add(pubInfos);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/crmf/PKMACValue.java b/core/src/main/java/org/bouncycastle/asn1/crmf/PKMACValue.java
deleted file mode 100644
index ebbf2dcf..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/crmf/PKMACValue.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package org.bouncycastle.asn1.crmf;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.cmp.CMPObjectIdentifiers;
-import org.bouncycastle.asn1.cmp.PBMParameter;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-/**
- * Password-based MAC value for use with POPOSigningKeyInput.
- */
-public class PKMACValue
- extends ASN1Object
-{
- private AlgorithmIdentifier algId;
- private DERBitString value;
-
- private PKMACValue(ASN1Sequence seq)
- {
- algId = AlgorithmIdentifier.getInstance(seq.getObjectAt(0));
- value = DERBitString.getInstance(seq.getObjectAt(1));
- }
-
- public static PKMACValue getInstance(Object o)
- {
- if (o instanceof PKMACValue)
- {
- return (PKMACValue)o;
- }
-
- if (o != null)
- {
- return new PKMACValue(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public static PKMACValue getInstance(ASN1TaggedObject obj, boolean isExplicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, isExplicit));
- }
-
- /**
- * Creates a new PKMACValue.
- * @param params parameters for password-based MAC
- * @param value MAC of the DER-encoded SubjectPublicKeyInfo
- */
- public PKMACValue(
- PBMParameter params,
- DERBitString value)
- {
- this(new AlgorithmIdentifier(
- CMPObjectIdentifiers.passwordBasedMac, params), value);
- }
-
- /**
- * Creates a new PKMACValue.
- * @param aid CMPObjectIdentifiers.passwordBasedMAC, with PBMParameter
- * @param value MAC of the DER-encoded SubjectPublicKeyInfo
- */
- public PKMACValue(
- AlgorithmIdentifier aid,
- DERBitString value)
- {
- this.algId = aid;
- this.value = value;
- }
-
- public AlgorithmIdentifier getAlgId()
- {
- return algId;
- }
-
- public DERBitString getValue()
- {
- return value;
- }
-
- /**
- * <pre>
- * PKMACValue ::= SEQUENCE {
- * algId AlgorithmIdentifier,
- * -- algorithm value shall be PasswordBasedMac 1.2.840.113533.7.66.13
- * -- parameter value is PBMParameter
- * value BIT STRING }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(algId);
- v.add(value);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/crmf/POPOPrivKey.java b/core/src/main/java/org/bouncycastle/asn1/crmf/POPOPrivKey.java
deleted file mode 100644
index 8c9db8ac..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/crmf/POPOPrivKey.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package org.bouncycastle.asn1.crmf;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.cms.EnvelopedData;
-
-public class POPOPrivKey
- extends ASN1Object
- implements ASN1Choice
-{
- public static final int thisMessage = 0;
- public static final int subsequentMessage = 1;
- public static final int dhMAC = 2;
- public static final int agreeMAC = 3;
- public static final int encryptedKey = 4;
-
- private int tagNo;
- private ASN1Encodable obj;
-
- private POPOPrivKey(ASN1TaggedObject obj)
- {
- this.tagNo = obj.getTagNo();
-
- switch (tagNo)
- {
- case thisMessage:
- this.obj = DERBitString.getInstance(obj, false);
- break;
- case subsequentMessage:
- this.obj = SubsequentMessage.valueOf(ASN1Integer.getInstance(obj, false).getValue().intValue());
- break;
- case dhMAC:
- this.obj = DERBitString.getInstance(obj, false);
- break;
- case agreeMAC:
- this.obj = PKMACValue.getInstance(obj, false);
- break;
- case encryptedKey:
- this.obj = EnvelopedData.getInstance(obj, false);
- break;
- default:
- throw new IllegalArgumentException("unknown tag in POPOPrivKey");
- }
- }
-
- public static POPOPrivKey getInstance(Object obj)
- {
- if (obj instanceof POPOPrivKey)
- {
- return (POPOPrivKey)obj;
- }
- if (obj != null)
- {
- return new POPOPrivKey(ASN1TaggedObject.getInstance(obj));
- }
-
- return null;
- }
-
- public static POPOPrivKey getInstance(ASN1TaggedObject obj, boolean explicit)
- {
- return getInstance(ASN1TaggedObject.getInstance(obj, explicit));
- }
-
- public POPOPrivKey(SubsequentMessage msg)
- {
- this.tagNo = subsequentMessage;
- this.obj = msg;
- }
-
- public int getType()
- {
- return tagNo;
- }
-
- public ASN1Encodable getValue()
- {
- return obj;
- }
-
- /**
- * <pre>
- * POPOPrivKey ::= CHOICE {
- * thisMessage [0] BIT STRING, -- Deprecated
- * -- possession is proven in this message (which contains the private
- * -- key itself (encrypted for the CA))
- * subsequentMessage [1] SubsequentMessage,
- * -- possession will be proven in a subsequent message
- * dhMAC [2] BIT STRING, -- Deprecated
- * agreeMAC [3] PKMACValue,
- * encryptedKey [4] EnvelopedData }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- return new DERTaggedObject(false, tagNo, obj);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/crmf/POPOSigningKey.java b/core/src/main/java/org/bouncycastle/asn1/crmf/POPOSigningKey.java
deleted file mode 100644
index 43dd05b0..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/crmf/POPOSigningKey.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package org.bouncycastle.asn1.crmf;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-public class POPOSigningKey
- extends ASN1Object
-{
- private POPOSigningKeyInput poposkInput;
- private AlgorithmIdentifier algorithmIdentifier;
- private DERBitString signature;
-
- private POPOSigningKey(ASN1Sequence seq)
- {
- int index = 0;
-
- if (seq.getObjectAt(index) instanceof ASN1TaggedObject)
- {
- ASN1TaggedObject tagObj
- = (ASN1TaggedObject)seq.getObjectAt(index++);
- if (tagObj.getTagNo() != 0)
- {
- throw new IllegalArgumentException(
- "Unknown POPOSigningKeyInput tag: " + tagObj.getTagNo());
- }
- poposkInput = POPOSigningKeyInput.getInstance(tagObj.getObject());
- }
- algorithmIdentifier = AlgorithmIdentifier.getInstance(seq.getObjectAt(index++));
- signature = DERBitString.getInstance(seq.getObjectAt(index));
- }
-
- public static POPOSigningKey getInstance(Object o)
- {
- if (o instanceof POPOSigningKey)
- {
- return (POPOSigningKey)o;
- }
-
- if (o != null)
- {
- return new POPOSigningKey(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public static POPOSigningKey getInstance(ASN1TaggedObject obj, boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- /**
- * Creates a new Proof of Possession object for a signing key.
- *
- * @param poposkIn the POPOSigningKeyInput structure, or null if the
- * CertTemplate includes both subject and publicKey values.
- * @param aid the AlgorithmIdentifier used to sign the proof of possession.
- * @param signature a signature over the DER-encoded value of poposkIn,
- * or the DER-encoded value of certReq if poposkIn is null.
- */
- public POPOSigningKey(
- POPOSigningKeyInput poposkIn,
- AlgorithmIdentifier aid,
- DERBitString signature)
- {
- this.poposkInput = poposkIn;
- this.algorithmIdentifier = aid;
- this.signature = signature;
- }
-
- public POPOSigningKeyInput getPoposkInput()
- {
- return poposkInput;
- }
-
- public AlgorithmIdentifier getAlgorithmIdentifier()
- {
- return algorithmIdentifier;
- }
-
- public DERBitString getSignature()
- {
- return signature;
- }
-
- /**
- * <pre>
- * POPOSigningKey ::= SEQUENCE {
- * poposkInput [0] POPOSigningKeyInput OPTIONAL,
- * algorithmIdentifier AlgorithmIdentifier,
- * signature BIT STRING }
- * -- The signature (using "algorithmIdentifier") is on the
- * -- DER-encoded value of poposkInput. NOTE: If the CertReqMsg
- * -- certReq CertTemplate contains the subject and publicKey values,
- * -- then poposkInput MUST be omitted and the signature MUST be
- * -- computed on the DER-encoded value of CertReqMsg certReq. If
- * -- the CertReqMsg certReq CertTemplate does not contain the public
- * -- key and subject values, then poposkInput MUST be present and
- * -- MUST be signed. This strategy ensures that the public key is
- * -- not present in both the poposkInput and CertReqMsg certReq
- * -- CertTemplate fields.
- * </pre>
- *
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (poposkInput != null)
- {
- v.add(new DERTaggedObject(false, 0, poposkInput));
- }
-
- v.add(algorithmIdentifier);
- v.add(signature);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/crmf/POPOSigningKeyInput.java b/core/src/main/java/org/bouncycastle/asn1/crmf/POPOSigningKeyInput.java
deleted file mode 100644
index 54d828e8..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/crmf/POPOSigningKeyInput.java
+++ /dev/null
@@ -1,134 +0,0 @@
-package org.bouncycastle.asn1.crmf;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.GeneralName;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-
-public class POPOSigningKeyInput
- extends ASN1Object
-{
- private GeneralName sender;
- private PKMACValue publicKeyMAC;
- private SubjectPublicKeyInfo publicKey;
-
- private POPOSigningKeyInput(ASN1Sequence seq)
- {
- ASN1Encodable authInfo = (ASN1Encodable)seq.getObjectAt(0);
-
- if (authInfo instanceof ASN1TaggedObject)
- {
- ASN1TaggedObject tagObj = (ASN1TaggedObject)authInfo;
- if (tagObj.getTagNo() != 0)
- {
- throw new IllegalArgumentException(
- "Unknown authInfo tag: " + tagObj.getTagNo());
- }
- sender = GeneralName.getInstance(tagObj.getObject());
- }
- else
- {
- publicKeyMAC = PKMACValue.getInstance(authInfo);
- }
-
- publicKey = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(1));
- }
-
- public static POPOSigningKeyInput getInstance(Object o)
- {
- if (o instanceof POPOSigningKeyInput)
- {
- return (POPOSigningKeyInput)o;
- }
-
- if (o != null)
- {
- return new POPOSigningKeyInput(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- /**
- * Creates a new POPOSigningKeyInput with sender name as authInfo.
- */
- public POPOSigningKeyInput(
- GeneralName sender,
- SubjectPublicKeyInfo spki)
- {
- this.sender = sender;
- this.publicKey = spki;
- }
-
- /**
- * Creates a new POPOSigningKeyInput using password-based MAC.
- */
- public POPOSigningKeyInput(
- PKMACValue pkmac,
- SubjectPublicKeyInfo spki)
- {
- this.publicKeyMAC = pkmac;
- this.publicKey = spki;
- }
-
- /**
- * Returns the sender field, or null if authInfo is publicKeyMAC
- */
- public GeneralName getSender()
- {
- return sender;
- }
-
- /**
- * Returns the publicKeyMAC field, or null if authInfo is sender
- */
- public PKMACValue getPublicKeyMAC()
- {
- return publicKeyMAC;
- }
-
- public SubjectPublicKeyInfo getPublicKey()
- {
- return publicKey;
- }
-
- /**
- * <pre>
- * POPOSigningKeyInput ::= SEQUENCE {
- * authInfo CHOICE {
- * sender [0] GeneralName,
- * -- used only if an authenticated identity has been
- * -- established for the sender (e.g., a DN from a
- * -- previously-issued and currently-valid certificate
- * publicKeyMAC PKMACValue },
- * -- used if no authenticated GeneralName currently exists for
- * -- the sender; publicKeyMAC contains a password-based MAC
- * -- on the DER-encoded value of publicKey
- * publicKey SubjectPublicKeyInfo } -- from CertTemplate
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (sender != null)
- {
- v.add(new DERTaggedObject(false, 0, sender));
- }
- else
- {
- v.add(publicKeyMAC);
- }
-
- v.add(publicKey);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/crmf/ProofOfPossession.java b/core/src/main/java/org/bouncycastle/asn1/crmf/ProofOfPossession.java
deleted file mode 100644
index 8ff23423..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/crmf/ProofOfPossession.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package org.bouncycastle.asn1.crmf;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-public class ProofOfPossession
- extends ASN1Object
- implements ASN1Choice
-{
- public static final int TYPE_RA_VERIFIED = 0;
- public static final int TYPE_SIGNING_KEY = 1;
- public static final int TYPE_KEY_ENCIPHERMENT = 2;
- public static final int TYPE_KEY_AGREEMENT = 3;
-
- private int tagNo;
- private ASN1Encodable obj;
-
- private ProofOfPossession(ASN1TaggedObject tagged)
- {
- tagNo = tagged.getTagNo();
- switch (tagNo)
- {
- case 0:
- obj = DERNull.INSTANCE;
- break;
- case 1:
- obj = POPOSigningKey.getInstance(tagged, false);
- break;
- case 2:
- case 3:
- obj = POPOPrivKey.getInstance(tagged, true);
- break;
- default:
- throw new IllegalArgumentException("unknown tag: " + tagNo);
- }
- }
-
- public static ProofOfPossession getInstance(Object o)
- {
- if (o == null || o instanceof ProofOfPossession)
- {
- return (ProofOfPossession)o;
- }
-
- if (o instanceof ASN1TaggedObject)
- {
- return new ProofOfPossession((ASN1TaggedObject)o);
- }
-
- throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
- }
-
- /** Creates a ProofOfPossession with type raVerified. */
- public ProofOfPossession()
- {
- tagNo = TYPE_RA_VERIFIED;
- obj = DERNull.INSTANCE;
- }
-
- /** Creates a ProofOfPossession for a signing key. */
- public ProofOfPossession(POPOSigningKey poposk)
- {
- tagNo = TYPE_SIGNING_KEY;
- obj = poposk;
- }
-
- /**
- * Creates a ProofOfPossession for key encipherment or agreement.
- * @param type one of TYPE_KEY_ENCIPHERMENT or TYPE_KEY_AGREEMENT
- */
- public ProofOfPossession(int type, POPOPrivKey privkey)
- {
- tagNo = type;
- obj = privkey;
- }
-
- public int getType()
- {
- return tagNo;
- }
-
- public ASN1Encodable getObject()
- {
- return obj;
- }
-
- /**
- * <pre>
- * ProofOfPossession ::= CHOICE {
- * raVerified [0] NULL,
- * -- used if the RA has already verified that the requester is in
- * -- possession of the private key
- * signature [1] POPOSigningKey,
- * keyEncipherment [2] POPOPrivKey,
- * keyAgreement [3] POPOPrivKey }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- return new DERTaggedObject(false, tagNo, obj);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/crmf/SinglePubInfo.java b/core/src/main/java/org/bouncycastle/asn1/crmf/SinglePubInfo.java
deleted file mode 100644
index 0237b3a6..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/crmf/SinglePubInfo.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.bouncycastle.asn1.crmf;
-
-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.DERSequence;
-import org.bouncycastle.asn1.x509.GeneralName;
-
-public class SinglePubInfo
- extends ASN1Object
-{
- private ASN1Integer pubMethod;
- private GeneralName pubLocation;
-
- private SinglePubInfo(ASN1Sequence seq)
- {
- pubMethod = ASN1Integer.getInstance(seq.getObjectAt(0));
-
- if (seq.size() == 2)
- {
- pubLocation = GeneralName.getInstance(seq.getObjectAt(1));
- }
- }
-
- public static SinglePubInfo getInstance(Object o)
- {
- if (o instanceof SinglePubInfo)
- {
- return (SinglePubInfo)o;
- }
-
- if (o != null)
- {
- return new SinglePubInfo(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public GeneralName getPubLocation()
- {
- return pubLocation;
- }
-
- /**
- * <pre>
- * SinglePubInfo ::= SEQUENCE {
- * pubMethod INTEGER {
- * dontCare (0),
- * x500 (1),
- * web (2),
- * ldap (3) },
- * pubLocation GeneralName OPTIONAL }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(pubMethod);
-
- if (pubLocation != null)
- {
- v.add(pubLocation);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/crmf/SubsequentMessage.java b/core/src/main/java/org/bouncycastle/asn1/crmf/SubsequentMessage.java
deleted file mode 100644
index 46917228..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/crmf/SubsequentMessage.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.bouncycastle.asn1.crmf;
-
-import org.bouncycastle.asn1.ASN1Integer;
-
-public class SubsequentMessage
- extends ASN1Integer
-{
- public static final SubsequentMessage encrCert = new SubsequentMessage(0);
- public static final SubsequentMessage challengeResp = new SubsequentMessage(1);
-
- private SubsequentMessage(int value)
- {
- super(value);
- }
-
- public static SubsequentMessage valueOf(int value)
- {
- if (value == 0)
- {
- return encrCert;
- }
- if (value == 1)
- {
- return challengeResp;
- }
-
- throw new IllegalArgumentException("unknown value: " + value);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cryptopro/CryptoProObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/cryptopro/CryptoProObjectIdentifiers.java
deleted file mode 100644
index c6e8e0d1..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cryptopro/CryptoProObjectIdentifiers.java
+++ /dev/null
@@ -1,101 +0,0 @@
-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
-{
- /** 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");
-
- /** 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");
-
- /** 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");
-
- /** 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/core/src/main/java/org/bouncycastle/asn1/cryptopro/ECGOST3410NamedCurves.java b/core/src/main/java/org/bouncycastle/asn1/cryptopro/ECGOST3410NamedCurves.java
deleted file mode 100644
index b0233da5..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cryptopro/ECGOST3410NamedCurves.java
+++ /dev/null
@@ -1,177 +0,0 @@
-package org.bouncycastle.asn1.cryptopro;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-import java.util.Hashtable;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECCurve;
-
-/**
- * table of the available named parameters for GOST 3410-2001.
- */
-public class ECGOST3410NamedCurves
-{
- static final Hashtable objIds = new Hashtable();
- static final Hashtable params = new Hashtable();
- static final Hashtable names = new Hashtable();
-
- static
- {
- 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
- new BigInteger("166"), // b
- mod_q,
- ECConstants.ONE);
-
- ECDomainParameters ecParams = new ECDomainParameters(
- curve,
- 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_q,
- ECConstants.ONE);
-
- ecParams = new ECDomainParameters(
- 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
- new BigInteger("28091019353058090096996979000309560759124368558014865957655842872397301267595"), // b
- mod_q,
- ECConstants.ONE);
-
- ecParams = new ECDomainParameters(
- curve,
- 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_q,
- ECConstants.ONE);
-
- ecParams = new ECDomainParameters(
- 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(
- mod_p, // p
- new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502616"), // a
- new BigInteger("32858"), // b
- mod_q,
- ECConstants.ONE);
-
- ecParams = new ECDomainParameters(
- curve,
- 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");
- names.put(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_XchA, "GostR3410-2001-CryptoPro-XchA");
- names.put(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_XchB, "GostR3410-2001-CryptoPro-XchB");
- }
-
- /**
- * return the ECDomainParameters object for the given OID, null if it
- * isn't present.
- *
- * @param oid an object identifier representing a named parameters, if present.
- */
- public static ECDomainParameters getByOID(
- ASN1ObjectIdentifier oid)
- {
- return (ECDomainParameters)params.get(oid);
- }
-
- /**
- * returns an enumeration containing the name strings for parameters
- * contained in this structure.
- */
- public static Enumeration getNames()
- {
- return objIds.keys();
- }
-
- public static ECDomainParameters getByName(
- String name)
- {
- ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)objIds.get(name);
-
- if (oid != null)
- {
- return (ECDomainParameters)params.get(oid);
- }
-
- return null;
- }
-
- /**
- * return the named curve name represented by the given object identifier.
- */
- public static String getName(
- ASN1ObjectIdentifier oid)
- {
- return (String)names.get(oid);
- }
-
- public static ASN1ObjectIdentifier getOID(String name)
- {
- return (ASN1ObjectIdentifier)objIds.get(name);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cryptopro/ECGOST3410ParamSetParameters.java b/core/src/main/java/org/bouncycastle/asn1/cryptopro/ECGOST3410ParamSetParameters.java
deleted file mode 100644
index 189eabdc..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cryptopro/ECGOST3410ParamSetParameters.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package org.bouncycastle.asn1.cryptopro;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-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;
-
-public class ECGOST3410ParamSetParameters
- extends ASN1Object
-{
- ASN1Integer p, q, a, b, x, y;
-
- public static ECGOST3410ParamSetParameters getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static ECGOST3410ParamSetParameters getInstance(
- Object obj)
- {
- if(obj == null || obj instanceof ECGOST3410ParamSetParameters)
- {
- return (ECGOST3410ParamSetParameters)obj;
- }
-
- if(obj instanceof ASN1Sequence)
- {
- return new ECGOST3410ParamSetParameters((ASN1Sequence)obj);
- }
-
- throw new IllegalArgumentException("Invalid GOST3410Parameter: " + obj.getClass().getName());
- }
-
- public ECGOST3410ParamSetParameters(
- BigInteger a,
- BigInteger b,
- BigInteger p,
- BigInteger q,
- int x,
- BigInteger y)
- {
- this.a = new ASN1Integer(a);
- this.b = new ASN1Integer(b);
- this.p = new ASN1Integer(p);
- this.q = new ASN1Integer(q);
- this.x = new ASN1Integer(x);
- this.y = new ASN1Integer(y);
- }
-
- public ECGOST3410ParamSetParameters(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- a = (ASN1Integer)e.nextElement();
- b = (ASN1Integer)e.nextElement();
- p = (ASN1Integer)e.nextElement();
- q = (ASN1Integer)e.nextElement();
- x = (ASN1Integer)e.nextElement();
- y = (ASN1Integer)e.nextElement();
- }
-
- public BigInteger getP()
- {
- return p.getPositiveValue();
- }
-
- public BigInteger getQ()
- {
- return q.getPositiveValue();
- }
-
- public BigInteger getA()
- {
- return a.getPositiveValue();
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(a);
- v.add(b);
- v.add(p);
- v.add(q);
- v.add(x);
- v.add(y);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cryptopro/GOST28147Parameters.java b/core/src/main/java/org/bouncycastle/asn1/cryptopro/GOST28147Parameters.java
deleted file mode 100644
index 124bca66..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cryptopro/GOST28147Parameters.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package org.bouncycastle.asn1.cryptopro;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-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
-{
- private ASN1OctetString iv;
- private ASN1ObjectIdentifier paramSet;
-
- public static GOST28147Parameters getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static GOST28147Parameters getInstance(
- Object obj)
- {
- if (obj instanceof GOST28147Parameters)
- {
- return (GOST28147Parameters)obj;
- }
-
- if (obj != null)
- {
- return new GOST28147Parameters(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- /**
- * @deprecated use the getInstance() method. This constructor will vanish!
- */
- public GOST28147Parameters(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- iv = (ASN1OctetString)e.nextElement();
- paramSet = (ASN1ObjectIdentifier)e.nextElement();
- }
-
- /**
- * <pre>
- * Gost28147-89-Parameters ::=
- * SEQUENCE {
- * iv Gost28147-89-IV,
- * encryptionParamSet OBJECT IDENTIFIER
- * }
- *
- * Gost28147-89-IV ::= OCTET STRING (SIZE (8))
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(iv);
- v.add(paramSet);
-
- 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/core/src/main/java/org/bouncycastle/asn1/cryptopro/GOST3410NamedParameters.java b/core/src/main/java/org/bouncycastle/asn1/cryptopro/GOST3410NamedParameters.java
deleted file mode 100644
index 6c398b5d..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cryptopro/GOST3410NamedParameters.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package org.bouncycastle.asn1.cryptopro;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-import java.util.Hashtable;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-
-/**
- * table of the available named parameters for GOST 3410-94.
- */
-public class GOST3410NamedParameters
-{
- static final Hashtable objIds = new Hashtable();
- static final Hashtable params = new Hashtable();
- static final Hashtable names = new Hashtable();
-
- static private GOST3410ParamSetParameters cryptoProA = new GOST3410ParamSetParameters(
- 1024,
- new BigInteger("127021248288932417465907042777176443525787653508916535812817507265705031260985098497423188333483401180925999995120988934130659205614996724254121049274349357074920312769561451689224110579311248812610229678534638401693520013288995000362260684222750813532307004517341633685004541062586971416883686778842537820383"),
- new BigInteger("68363196144955700784444165611827252895102170888761442055095051287550314083023"),
- new BigInteger("100997906755055304772081815535925224869841082572053457874823515875577147990529272777244152852699298796483356699682842027972896052747173175480590485607134746852141928680912561502802222185647539190902656116367847270145019066794290930185446216399730872221732889830323194097355403213400972588322876850946740663962")
-// validationAlgorithm {
-// algorithm
-// id-GostR3410-94-bBis,
-// parameters
-// GostR3410-94-ValidationBisParameters: {
-// x0 1376285941,
-// c 3996757427
-// }
-// }
-
- );
-
- static private GOST3410ParamSetParameters cryptoProB = new GOST3410ParamSetParameters(
- 1024,
- new BigInteger("139454871199115825601409655107690713107041707059928031797758001454375765357722984094124368522288239833039114681648076688236921220737322672160740747771700911134550432053804647694904686120113087816240740184800477047157336662926249423571248823968542221753660143391485680840520336859458494803187341288580489525163"),
- new BigInteger("79885141663410976897627118935756323747307951916507639758300472692338873533959"),
- new BigInteger("42941826148615804143873447737955502392672345968607143066798112994089471231420027060385216699563848719957657284814898909770759462613437669456364882730370838934791080835932647976778601915343474400961034231316672578686920482194932878633360203384797092684342247621055760235016132614780652761028509445403338652341")
-// validationAlgorithm {
-// algorithm
-// id-GostR3410-94-bBis,
-// parameters
-// GostR3410-94-ValidationBisParameters: {
-// x0 1536654555,
-// c 1855361757,
-// d 14408629386140014567655
-//4902939282056547857802241461782996702017713059974755104394739915140
-//6115284791024439062735788342744854120601660303926203867703556828005
-//8957203818114895398976594425537561271800850306
-// }
-// }
-//}
- );
-
- static private GOST3410ParamSetParameters cryptoProXchA = new GOST3410ParamSetParameters(
- 1024,
- new BigInteger("142011741597563481196368286022318089743276138395243738762872573441927459393512718973631166078467600360848946623567625795282774719212241929071046134208380636394084512691828894000571524625445295769349356752728956831541775441763139384457191755096847107846595662547942312293338483924514339614727760681880609734239"),
- new BigInteger("91771529896554605945588149018382750217296858393520724172743325725474374979801"),
- new BigInteger("133531813272720673433859519948319001217942375967847486899482359599369642528734712461590403327731821410328012529253871914788598993103310567744136196364803064721377826656898686468463277710150809401182608770201615324990468332931294920912776241137878030224355746606283971659376426832674269780880061631528163475887")
- );
-
- static
- {
- params.put(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_A, cryptoProA);
- params.put(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_B, cryptoProB);
-// params.put(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_C, cryptoProC);
-// params.put(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_D, cryptoProD);
- params.put(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_XchA, cryptoProXchA);
-// params.put(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_XchB, cryptoProXchA);
-// params.put(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_XchC, cryptoProXchA);
-
- objIds.put("GostR3410-94-CryptoPro-A", CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_A);
- objIds.put("GostR3410-94-CryptoPro-B", CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_B);
- objIds.put("GostR3410-94-CryptoPro-XchA", CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_XchA);
- }
-
- /**
- * return the GOST3410ParamSetParameters object for the given OID, null if it
- * isn't present.
- *
- * @param oid an object identifier representing a named parameters, if present.
- */
- public static GOST3410ParamSetParameters getByOID(
- ASN1ObjectIdentifier oid)
- {
- return (GOST3410ParamSetParameters)params.get(oid);
- }
-
- /**
- * returns an enumeration containing the name strings for parameters
- * contained in this structure.
- */
- public static Enumeration getNames()
- {
- return objIds.keys();
- }
-
- public static GOST3410ParamSetParameters getByName(
- String name)
- {
- ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)objIds.get(name);
-
- if (oid != null)
- {
- return (GOST3410ParamSetParameters)params.get(oid);
- }
-
- return null;
- }
-
- public static ASN1ObjectIdentifier getOID(String name)
- {
- return (ASN1ObjectIdentifier)objIds.get(name);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cryptopro/GOST3410ParamSetParameters.java b/core/src/main/java/org/bouncycastle/asn1/cryptopro/GOST3410ParamSetParameters.java
deleted file mode 100644
index 35e9b735..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cryptopro/GOST3410ParamSetParameters.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package org.bouncycastle.asn1.cryptopro;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-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;
-
-public class GOST3410ParamSetParameters
- extends ASN1Object
-{
- int keySize;
- ASN1Integer p, q, a;
-
- public static GOST3410ParamSetParameters getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static GOST3410ParamSetParameters getInstance(
- Object obj)
- {
- if(obj == null || obj instanceof GOST3410ParamSetParameters)
- {
- return (GOST3410ParamSetParameters)obj;
- }
-
- if(obj instanceof ASN1Sequence)
- {
- return new GOST3410ParamSetParameters((ASN1Sequence)obj);
- }
-
- throw new IllegalArgumentException("Invalid GOST3410Parameter: " + obj.getClass().getName());
- }
-
- public GOST3410ParamSetParameters(
- int keySize,
- BigInteger p,
- BigInteger q,
- BigInteger a)
- {
- this.keySize = keySize;
- this.p = new ASN1Integer(p);
- this.q = new ASN1Integer(q);
- this.a = new ASN1Integer(a);
- }
-
- public GOST3410ParamSetParameters(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- keySize = ((ASN1Integer)e.nextElement()).getValue().intValue();
- p = (ASN1Integer)e.nextElement();
- q = (ASN1Integer)e.nextElement();
- a = (ASN1Integer)e.nextElement();
- }
-
- /**
- * @deprecated use getKeySize
- */
- public int getLKeySize()
- {
- return keySize;
- }
-
- public int getKeySize()
- {
- return keySize;
- }
-
- public BigInteger getP()
- {
- return p.getPositiveValue();
- }
-
- public BigInteger getQ()
- {
- return q.getPositiveValue();
- }
-
- public BigInteger getA()
- {
- return a.getPositiveValue();
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(new ASN1Integer(keySize));
- v.add(p);
- v.add(q);
- v.add(a);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/cryptopro/GOST3410PublicKeyAlgParameters.java b/core/src/main/java/org/bouncycastle/asn1/cryptopro/GOST3410PublicKeyAlgParameters.java
deleted file mode 100644
index 45d78147..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/cryptopro/GOST3410PublicKeyAlgParameters.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package org.bouncycastle.asn1.cryptopro;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-
-public class GOST3410PublicKeyAlgParameters
- extends ASN1Object
-{
- private ASN1ObjectIdentifier publicKeyParamSet;
- private ASN1ObjectIdentifier digestParamSet;
- private ASN1ObjectIdentifier encryptionParamSet;
-
- public static GOST3410PublicKeyAlgParameters getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static GOST3410PublicKeyAlgParameters getInstance(
- Object obj)
- {
- if (obj instanceof GOST3410PublicKeyAlgParameters)
- {
- return (GOST3410PublicKeyAlgParameters)obj;
- }
-
- if(obj != null)
- {
- return new GOST3410PublicKeyAlgParameters(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public GOST3410PublicKeyAlgParameters(
- ASN1ObjectIdentifier publicKeyParamSet,
- ASN1ObjectIdentifier digestParamSet)
- {
- this.publicKeyParamSet = publicKeyParamSet;
- this.digestParamSet = digestParamSet;
- this.encryptionParamSet = null;
- }
-
- public GOST3410PublicKeyAlgParameters(
- ASN1ObjectIdentifier publicKeyParamSet,
- ASN1ObjectIdentifier digestParamSet,
- ASN1ObjectIdentifier encryptionParamSet)
- {
- this.publicKeyParamSet = publicKeyParamSet;
- this.digestParamSet = digestParamSet;
- this.encryptionParamSet = encryptionParamSet;
- }
-
- /**
- * @deprecated use getInstance()
- */
- public GOST3410PublicKeyAlgParameters(
- ASN1Sequence seq)
- {
- this.publicKeyParamSet = (ASN1ObjectIdentifier)seq.getObjectAt(0);
- this.digestParamSet = (ASN1ObjectIdentifier)seq.getObjectAt(1);
-
- if (seq.size() > 2)
- {
- this.encryptionParamSet = (ASN1ObjectIdentifier)seq.getObjectAt(2);
- }
- }
-
- public ASN1ObjectIdentifier getPublicKeyParamSet()
- {
- return publicKeyParamSet;
- }
-
- public ASN1ObjectIdentifier getDigestParamSet()
- {
- return digestParamSet;
- }
-
- public ASN1ObjectIdentifier getEncryptionParamSet()
- {
- return encryptionParamSet;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(publicKeyParamSet);
- v.add(digestParamSet);
-
- if (encryptionParamSet != null)
- {
- v.add(encryptionParamSet);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/dvcs/CertEtcToken.java b/core/src/main/java/org/bouncycastle/asn1/dvcs/CertEtcToken.java
deleted file mode 100644
index 3f69c52f..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/dvcs/CertEtcToken.java
+++ /dev/null
@@ -1,171 +0,0 @@
-package org.bouncycastle.asn1.dvcs;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.cmp.PKIStatusInfo;
-import org.bouncycastle.asn1.cms.ContentInfo;
-import org.bouncycastle.asn1.ess.ESSCertID;
-import org.bouncycastle.asn1.ocsp.CertID;
-import org.bouncycastle.asn1.ocsp.CertStatus;
-import org.bouncycastle.asn1.ocsp.OCSPResponse;
-import org.bouncycastle.asn1.smime.SMIMECapabilities;
-import org.bouncycastle.asn1.x509.Certificate;
-import org.bouncycastle.asn1.x509.CertificateList;
-import org.bouncycastle.asn1.x509.Extension;
-
-/**
- * <pre>
- * CertEtcToken ::= CHOICE {
- * certificate [0] IMPLICIT Certificate ,
- * esscertid [1] ESSCertId ,
- * pkistatus [2] IMPLICIT PKIStatusInfo ,
- * assertion [3] ContentInfo ,
- * crl [4] IMPLICIT CertificateList,
- * ocspcertstatus [5] CertStatus,
- * oscpcertid [6] IMPLICIT CertId ,
- * oscpresponse [7] IMPLICIT OCSPResponse,
- * capabilities [8] SMIMECapabilities,
- * extension Extension
- * }
- * </pre>
- */
-public class CertEtcToken
- extends ASN1Object
- implements ASN1Choice
-{
- public static final int TAG_CERTIFICATE = 0;
- public static final int TAG_ESSCERTID = 1;
- public static final int TAG_PKISTATUS = 2;
- public static final int TAG_ASSERTION = 3;
- public static final int TAG_CRL = 4;
- public static final int TAG_OCSPCERTSTATUS = 5;
- public static final int TAG_OCSPCERTID = 6;
- public static final int TAG_OCSPRESPONSE = 7;
- public static final int TAG_CAPABILITIES = 8;
-
- private static final boolean[] explicit = new boolean[]
- {
- false, true, false, true, false, true, false, false, true
- };
-
- private int tagNo;
- private ASN1Encodable value;
- private Extension extension;
-
- public CertEtcToken(int tagNo, ASN1Encodable value)
- {
- this.tagNo = tagNo;
- this.value = value;
- }
-
- public CertEtcToken(Extension extension)
- {
- this.tagNo = -1;
- this.extension = extension;
- }
-
- private CertEtcToken(ASN1TaggedObject choice)
- {
- this.tagNo = choice.getTagNo();
-
- switch (tagNo)
- {
- case TAG_CERTIFICATE:
- value = Certificate.getInstance(choice, false);
- break;
- case TAG_ESSCERTID:
- value = ESSCertID.getInstance(choice.getObject());
- break;
- case TAG_PKISTATUS:
- value = PKIStatusInfo.getInstance(choice, false);
- break;
- case TAG_ASSERTION:
- value = ContentInfo.getInstance(choice.getObject());
- break;
- case TAG_CRL:
- value = CertificateList.getInstance(choice, false);
- break;
- case TAG_OCSPCERTSTATUS:
- value = CertStatus.getInstance(choice.getObject());
- break;
- case TAG_OCSPCERTID:
- value = CertID.getInstance(choice, false);
- break;
- case TAG_OCSPRESPONSE:
- value = OCSPResponse.getInstance(choice, false);
- break;
- case TAG_CAPABILITIES:
- value = SMIMECapabilities.getInstance(choice.getObject());
- break;
- default:
- throw new IllegalArgumentException("Unknown tag: " + tagNo);
- }
- }
-
- public static CertEtcToken getInstance(Object obj)
- {
- if (obj instanceof CertEtcToken)
- {
- return (CertEtcToken)obj;
- }
- else if (obj instanceof ASN1TaggedObject)
- {
- return new CertEtcToken((ASN1TaggedObject)obj);
- }
- else if (obj != null)
- {
- return new CertEtcToken(Extension.getInstance(obj));
- }
-
- return null;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- if (extension == null)
- {
- return new DERTaggedObject(explicit[tagNo], tagNo, value);
- }
- else
- {
- return extension.toASN1Primitive();
- }
- }
-
- public int getTagNo()
- {
- return tagNo;
- }
-
- public ASN1Encodable getValue()
- {
- return value;
- }
-
- public Extension getExtension()
- {
- return extension;
- }
-
- public String toString()
- {
- return "CertEtcToken {\n" + value + "}\n";
- }
-
- public static CertEtcToken[] arrayFromSequence(ASN1Sequence seq)
- {
- CertEtcToken[] tmp = new CertEtcToken[seq.size()];
-
- for (int i = 0; i != tmp.length; i++)
- {
- tmp[i] = CertEtcToken.getInstance(seq.getObjectAt(i));
- }
-
- return tmp;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSCertInfo.java b/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSCertInfo.java
deleted file mode 100644
index b64b31c4..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSCertInfo.java
+++ /dev/null
@@ -1,302 +0,0 @@
-package org.bouncycastle.asn1.dvcs;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.cmp.PKIStatusInfo;
-import org.bouncycastle.asn1.x509.DigestInfo;
-import org.bouncycastle.asn1.x509.Extensions;
-import org.bouncycastle.asn1.x509.PolicyInformation;
-
-/**
- * <pre>
- * DVCSCertInfo::= SEQUENCE {
- * version Integer DEFAULT 1 ,
- * dvReqInfo DVCSRequestInformation,
- * messageImprint DigestInfo,
- * serialNumber Integer,
- * responseTime DVCSTime,
- * dvStatus [0] PKIStatusInfo OPTIONAL,
- * policy [1] PolicyInformation OPTIONAL,
- * reqSignature [2] SignerInfos OPTIONAL,
- * certs [3] SEQUENCE SIZE (1..MAX) OF
- * TargetEtcChain OPTIONAL,
- * extensions Extensions OPTIONAL
- * }
- * </pre>
- */
-
-public class DVCSCertInfo
- extends ASN1Object
-{
-
- private int version = DEFAULT_VERSION;
- private DVCSRequestInformation dvReqInfo;
- private DigestInfo messageImprint;
- private ASN1Integer serialNumber;
- private DVCSTime responseTime;
- private PKIStatusInfo dvStatus;
- private PolicyInformation policy;
- private ASN1Set reqSignature;
- private ASN1Sequence certs;
- private Extensions extensions;
-
- private static final int DEFAULT_VERSION = 1;
- private static final int TAG_DV_STATUS = 0;
- private static final int TAG_POLICY = 1;
- private static final int TAG_REQ_SIGNATURE = 2;
- private static final int TAG_CERTS = 3;
-
- public DVCSCertInfo(
- DVCSRequestInformation dvReqInfo,
- DigestInfo messageImprint,
- ASN1Integer serialNumber,
- DVCSTime responseTime)
- {
- this.dvReqInfo = dvReqInfo;
- this.messageImprint = messageImprint;
- this.serialNumber = serialNumber;
- this.responseTime = responseTime;
- }
-
- private DVCSCertInfo(ASN1Sequence seq)
- {
- int i = 0;
- ASN1Encodable x = seq.getObjectAt(i++);
- try
- {
- ASN1Integer encVersion = ASN1Integer.getInstance(x);
- this.version = encVersion.getValue().intValue();
- x = seq.getObjectAt(i++);
- }
- catch (IllegalArgumentException e)
- {
- }
-
- this.dvReqInfo = DVCSRequestInformation.getInstance(x);
- x = seq.getObjectAt(i++);
- this.messageImprint = DigestInfo.getInstance(x);
- x = seq.getObjectAt(i++);
- this.serialNumber = ASN1Integer.getInstance(x);
- x = seq.getObjectAt(i++);
- this.responseTime = DVCSTime.getInstance(x);
-
- while (i < seq.size())
- {
-
- x = seq.getObjectAt(i++);
-
- try
- {
- ASN1TaggedObject t = ASN1TaggedObject.getInstance(x);
- int tagNo = t.getTagNo();
-
- switch (tagNo)
- {
- case TAG_DV_STATUS:
- this.dvStatus = PKIStatusInfo.getInstance(t, false);
- break;
- case TAG_POLICY:
- this.policy = PolicyInformation.getInstance(ASN1Sequence.getInstance(t, false));
- break;
- case TAG_REQ_SIGNATURE:
- this.reqSignature = ASN1Set.getInstance(t, false);
- break;
- case TAG_CERTS:
- this.certs = ASN1Sequence.getInstance(t, false);
- break;
- }
-
- continue;
-
- }
- catch (IllegalArgumentException e)
- {
- }
-
- try
- {
- this.extensions = Extensions.getInstance(x);
- }
- catch (IllegalArgumentException e)
- {
- }
-
- }
-
- }
-
- public static DVCSCertInfo getInstance(Object obj)
- {
- if (obj instanceof DVCSCertInfo)
- {
- return (DVCSCertInfo)obj;
- }
- else if (obj != null)
- {
- return new DVCSCertInfo(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public static DVCSCertInfo getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public ASN1Primitive toASN1Primitive()
- {
-
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (version != DEFAULT_VERSION)
- {
- v.add(new ASN1Integer(version));
- }
- v.add(dvReqInfo);
- v.add(messageImprint);
- v.add(serialNumber);
- v.add(responseTime);
- if (dvStatus != null)
- {
- v.add(new DERTaggedObject(false, TAG_DV_STATUS, dvStatus));
- }
- if (policy != null)
- {
- v.add(new DERTaggedObject(false, TAG_POLICY, policy));
- }
- if (reqSignature != null)
- {
- v.add(new DERTaggedObject(false, TAG_REQ_SIGNATURE, reqSignature));
- }
- if (certs != null)
- {
- v.add(new DERTaggedObject(false, TAG_CERTS, certs));
- }
- if (extensions != null)
- {
- v.add(extensions);
- }
-
- return new DERSequence(v);
- }
-
- public String toString()
- {
- StringBuffer s = new StringBuffer();
-
- s.append("DVCSCertInfo {\n");
-
- if (version != DEFAULT_VERSION)
- {
- s.append("version: " + version + "\n");
- }
- s.append("dvReqInfo: " + dvReqInfo + "\n");
- s.append("messageImprint: " + messageImprint + "\n");
- s.append("serialNumber: " + serialNumber + "\n");
- s.append("responseTime: " + responseTime + "\n");
- if (dvStatus != null)
- {
- s.append("dvStatus: " + dvStatus + "\n");
- }
- if (policy != null)
- {
- s.append("policy: " + policy + "\n");
- }
- if (reqSignature != null)
- {
- s.append("reqSignature: " + reqSignature + "\n");
- }
- if (certs != null)
- {
- s.append("certs: " + certs + "\n");
- }
- if (extensions != null)
- {
- s.append("extensions: " + extensions + "\n");
- }
-
- s.append("}\n");
- return s.toString();
- }
-
- public int getVersion()
- {
- return version;
- }
-
- private void setVersion(int version)
- {
- this.version = version;
- }
-
- public DVCSRequestInformation getDvReqInfo()
- {
- return dvReqInfo;
- }
-
- private void setDvReqInfo(DVCSRequestInformation dvReqInfo)
- {
- this.dvReqInfo = dvReqInfo;
- }
-
- public DigestInfo getMessageImprint()
- {
- return messageImprint;
- }
-
- private void setMessageImprint(DigestInfo messageImprint)
- {
- this.messageImprint = messageImprint;
- }
-
- public ASN1Integer getSerialNumber()
- {
- return serialNumber;
- }
-
- public DVCSTime getResponseTime()
- {
- return responseTime;
- }
-
- public PKIStatusInfo getDvStatus()
- {
- return dvStatus;
- }
-
- public PolicyInformation getPolicy()
- {
- return policy;
- }
-
- public ASN1Set getReqSignature()
- {
- return reqSignature;
- }
-
- public TargetEtcChain[] getCerts()
- {
- if (certs != null)
- {
- return TargetEtcChain.arrayFromSequence(certs);
- }
-
- return null;
- }
-
- public Extensions getExtensions()
- {
- return extensions;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSCertInfoBuilder.java b/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSCertInfoBuilder.java
deleted file mode 100644
index 5da097f5..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSCertInfoBuilder.java
+++ /dev/null
@@ -1,151 +0,0 @@
-package org.bouncycastle.asn1.dvcs;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.cmp.PKIStatusInfo;
-import org.bouncycastle.asn1.x509.DigestInfo;
-import org.bouncycastle.asn1.x509.Extensions;
-import org.bouncycastle.asn1.x509.PolicyInformation;
-
-/**
- * <pre>
- * DVCSCertInfo::= SEQUENCE {
- * version Integer DEFAULT 1 ,
- * dvReqInfo DVCSRequestInformation,
- * messageImprint DigestInfo,
- * serialNumber Integer,
- * responseTime DVCSTime,
- * dvStatus [0] PKIStatusInfo OPTIONAL,
- * policy [1] PolicyInformation OPTIONAL,
- * reqSignature [2] SignerInfos OPTIONAL,
- * certs [3] SEQUENCE SIZE (1..MAX) OF
- * TargetEtcChain OPTIONAL,
- * extensions Extensions OPTIONAL
- * }
- * </pre>
- */
-
-public class DVCSCertInfoBuilder
-{
-
- private int version = DEFAULT_VERSION;
- private DVCSRequestInformation dvReqInfo;
- private DigestInfo messageImprint;
- private ASN1Integer serialNumber;
- private DVCSTime responseTime;
- private PKIStatusInfo dvStatus;
- private PolicyInformation policy;
- private ASN1Set reqSignature;
- private ASN1Sequence certs;
- private Extensions extensions;
-
- private static final int DEFAULT_VERSION = 1;
- private static final int TAG_DV_STATUS = 0;
- private static final int TAG_POLICY = 1;
- private static final int TAG_REQ_SIGNATURE = 2;
- private static final int TAG_CERTS = 3;
-
- public DVCSCertInfoBuilder(
- DVCSRequestInformation dvReqInfo,
- DigestInfo messageImprint,
- ASN1Integer serialNumber,
- DVCSTime responseTime)
- {
- this.dvReqInfo = dvReqInfo;
- this.messageImprint = messageImprint;
- this.serialNumber = serialNumber;
- this.responseTime = responseTime;
- }
-
- public DVCSCertInfo build()
- {
-
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (version != DEFAULT_VERSION)
- {
- v.add(new ASN1Integer(version));
- }
- v.add(dvReqInfo);
- v.add(messageImprint);
- v.add(serialNumber);
- v.add(responseTime);
- if (dvStatus != null)
- {
- v.add(new DERTaggedObject(false, TAG_DV_STATUS, dvStatus));
- }
- if (policy != null)
- {
- v.add(new DERTaggedObject(false, TAG_POLICY, policy));
- }
- if (reqSignature != null)
- {
- v.add(new DERTaggedObject(false, TAG_REQ_SIGNATURE, reqSignature));
- }
- if (certs != null)
- {
- v.add(new DERTaggedObject(false, TAG_CERTS, certs));
- }
- if (extensions != null)
- {
- v.add(extensions);
- }
-
- return DVCSCertInfo.getInstance(new DERSequence(v));
- }
-
- public void setVersion(int version)
- {
- this.version = version;
- }
-
- public void setDvReqInfo(DVCSRequestInformation dvReqInfo)
- {
- this.dvReqInfo = dvReqInfo;
- }
-
- public void setMessageImprint(DigestInfo messageImprint)
- {
- this.messageImprint = messageImprint;
- }
-
- public void setSerialNumber(ASN1Integer serialNumber)
- {
- this.serialNumber = serialNumber;
- }
-
- public void setResponseTime(DVCSTime responseTime)
- {
- this.responseTime = responseTime;
- }
-
- public void setDvStatus(PKIStatusInfo dvStatus)
- {
- this.dvStatus = dvStatus;
- }
-
- public void setPolicy(PolicyInformation policy)
- {
- this.policy = policy;
- }
-
- public void setReqSignature(ASN1Set reqSignature)
- {
- this.reqSignature = reqSignature;
- }
-
- public void setCerts(TargetEtcChain[] certs)
- {
- this.certs = new DERSequence(certs);
- }
-
- public void setExtensions(Extensions extensions)
- {
- this.extensions = extensions;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSErrorNotice.java b/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSErrorNotice.java
deleted file mode 100644
index 8dd69a9e..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSErrorNotice.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.bouncycastle.asn1.dvcs;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.cmp.PKIStatusInfo;
-import org.bouncycastle.asn1.x509.GeneralName;
-
-/**
- * <pre>
- * DVCSErrorNotice ::= SEQUENCE {
- * transactionStatus PKIStatusInfo ,
- * transactionIdentifier GeneralName OPTIONAL
- * }
- * </pre>
- */
-public class DVCSErrorNotice
- extends ASN1Object
-{
- private PKIStatusInfo transactionStatus;
- private GeneralName transactionIdentifier;
-
- public DVCSErrorNotice(PKIStatusInfo status)
- {
- this(status, null);
- }
-
- public DVCSErrorNotice(PKIStatusInfo status, GeneralName transactionIdentifier)
- {
- this.transactionStatus = status;
- this.transactionIdentifier = transactionIdentifier;
- }
-
- private DVCSErrorNotice(ASN1Sequence seq)
- {
- this.transactionStatus = PKIStatusInfo.getInstance(seq.getObjectAt(0));
- if (seq.size() > 1)
- {
- this.transactionIdentifier = GeneralName.getInstance(seq.getObjectAt(1));
- }
- }
-
- public static DVCSErrorNotice getInstance(Object obj)
- {
- if (obj instanceof DVCSErrorNotice)
- {
- return (DVCSErrorNotice)obj;
- }
- else if (obj != null)
- {
- return new DVCSErrorNotice(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public static DVCSErrorNotice getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- v.add(transactionStatus);
- if (transactionIdentifier != null)
- {
- v.add(transactionIdentifier);
- }
- return new DERSequence(v);
- }
-
- public String toString()
- {
- return "DVCSErrorNotice {\n" +
- "transactionStatus: " + transactionStatus + "\n" +
- (transactionIdentifier != null ? "transactionIdentifier: " + transactionIdentifier + "\n" : "") +
- "}\n";
- }
-
-
- public PKIStatusInfo getTransactionStatus()
- {
- return transactionStatus;
- }
-
- public GeneralName getTransactionIdentifier()
- {
- return transactionIdentifier;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSObjectIdentifiers.java
deleted file mode 100644
index d5f6ab6f..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSObjectIdentifiers.java
+++ /dev/null
@@ -1,29 +0,0 @@
-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");
-
- /** 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");
-
- /** 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");
-
- /** 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");
-
- /** 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/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSRequest.java b/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSRequest.java
deleted file mode 100644
index b9506e79..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSRequest.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package org.bouncycastle.asn1.dvcs;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.GeneralName;
-
-/**
- * <pre>
- * DVCSRequest ::= SEQUENCE {
- * requestInformation DVCSRequestInformation,
- * data Data,
- * transactionIdentifier GeneralName OPTIONAL
- * }
- * </pre>
- */
-
-public class DVCSRequest
- extends ASN1Object
-{
-
- private DVCSRequestInformation requestInformation;
- private Data data;
- private GeneralName transactionIdentifier;
-
- public DVCSRequest(DVCSRequestInformation requestInformation, Data data)
- {
- this(requestInformation, data, null);
- }
-
- public DVCSRequest(DVCSRequestInformation requestInformation, Data data, GeneralName transactionIdentifier)
- {
- this.requestInformation = requestInformation;
- this.data = data;
- this.transactionIdentifier = transactionIdentifier;
- }
-
- private DVCSRequest(ASN1Sequence seq)
- {
- requestInformation = DVCSRequestInformation.getInstance(seq.getObjectAt(0));
- data = Data.getInstance(seq.getObjectAt(1));
- if (seq.size() > 2)
- {
- transactionIdentifier = GeneralName.getInstance(seq.getObjectAt(2));
- }
- }
-
- public static DVCSRequest getInstance(Object obj)
- {
- if (obj instanceof DVCSRequest)
- {
- return (DVCSRequest)obj;
- }
- else if (obj != null)
- {
- return new DVCSRequest(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public static DVCSRequest getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- v.add(requestInformation);
- v.add(data);
- if (transactionIdentifier != null)
- {
- v.add(transactionIdentifier);
- }
- return new DERSequence(v);
- }
-
- public String toString()
- {
- return "DVCSRequest {\n" +
- "requestInformation: " + requestInformation + "\n" +
- "data: " + data + "\n" +
- (transactionIdentifier != null ? "transactionIdentifier: " + transactionIdentifier + "\n" : "") +
- "}\n";
- }
-
- public Data getData()
- {
- return data;
- }
-
- public DVCSRequestInformation getRequestInformation()
- {
- return requestInformation;
- }
-
- public GeneralName getTransactionIdentifier()
- {
- return transactionIdentifier;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSRequestInformation.java b/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSRequestInformation.java
deleted file mode 100644
index 8d28f93d..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSRequestInformation.java
+++ /dev/null
@@ -1,271 +0,0 @@
-package org.bouncycastle.asn1.dvcs;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.Extensions;
-import org.bouncycastle.asn1.x509.GeneralNames;
-import org.bouncycastle.asn1.x509.PolicyInformation;
-
-/**
- * <pre>
- * DVCSRequestInformation ::= SEQUENCE {
- * version INTEGER DEFAULT 1 ,
- * service ServiceType,
- * nonce Nonce OPTIONAL,
- * requestTime DVCSTime OPTIONAL,
- * requester [0] GeneralNames OPTIONAL,
- * requestPolicy [1] PolicyInformation OPTIONAL,
- * dvcs [2] GeneralNames OPTIONAL,
- * dataLocations [3] GeneralNames OPTIONAL,
- * extensions [4] IMPLICIT Extensions OPTIONAL
- * }
- * </pre>
- */
-
-public class DVCSRequestInformation
- extends ASN1Object
-{
- private int version = DEFAULT_VERSION;
- private ServiceType service;
- private BigInteger nonce;
- private DVCSTime requestTime;
- private GeneralNames requester;
- private PolicyInformation requestPolicy;
- private GeneralNames dvcs;
- private GeneralNames dataLocations;
- private Extensions extensions;
-
- private static final int DEFAULT_VERSION = 1;
- private static final int TAG_REQUESTER = 0;
- private static final int TAG_REQUEST_POLICY = 1;
- private static final int TAG_DVCS = 2;
- private static final int TAG_DATA_LOCATIONS = 3;
- private static final int TAG_EXTENSIONS = 4;
-
- private DVCSRequestInformation(ASN1Sequence seq)
- {
- int i = 0;
-
- if (seq.getObjectAt(0) instanceof ASN1Integer)
- {
- ASN1Integer encVersion = ASN1Integer.getInstance(seq.getObjectAt(i++));
- this.version = encVersion.getValue().intValue();
- }
- else
- {
- this.version = 1;
- }
-
- this.service = ServiceType.getInstance(seq.getObjectAt(i++));
-
- while (i < seq.size())
- {
- ASN1Encodable x = seq.getObjectAt(i);
-
- if (x instanceof ASN1Integer)
- {
- this.nonce = ASN1Integer.getInstance(x).getValue();
- }
- else if (x instanceof ASN1GeneralizedTime)
- {
- this.requestTime = DVCSTime.getInstance(x);
- }
- else if (x instanceof ASN1TaggedObject)
- {
- ASN1TaggedObject t = ASN1TaggedObject.getInstance(x);
- int tagNo = t.getTagNo();
-
- switch (tagNo)
- {
- case TAG_REQUESTER:
- this.requester = GeneralNames.getInstance(t, false);
- break;
- case TAG_REQUEST_POLICY:
- this.requestPolicy = PolicyInformation.getInstance(ASN1Sequence.getInstance(t, false));
- break;
- case TAG_DVCS:
- this.dvcs = GeneralNames.getInstance(t, false);
- break;
- case TAG_DATA_LOCATIONS:
- this.dataLocations = GeneralNames.getInstance(t, false);
- break;
- case TAG_EXTENSIONS:
- this.extensions = Extensions.getInstance(t, false);
- break;
- }
- }
- else
- {
- this.requestTime = DVCSTime.getInstance(x);
- }
-
- i++;
- }
- }
-
- public static DVCSRequestInformation getInstance(Object obj)
- {
- if (obj instanceof DVCSRequestInformation)
- {
- return (DVCSRequestInformation)obj;
- }
- else if (obj != null)
- {
- return new DVCSRequestInformation(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public static DVCSRequestInformation getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (version != DEFAULT_VERSION)
- {
- v.add(new ASN1Integer(version));
- }
- v.add(service);
- if (nonce != null)
- {
- v.add(new ASN1Integer(nonce));
- }
- if (requestTime != null)
- {
- v.add(requestTime);
- }
-
- int[] tags = new int[]{
- TAG_REQUESTER,
- TAG_REQUEST_POLICY,
- TAG_DVCS,
- TAG_DATA_LOCATIONS,
- TAG_EXTENSIONS
- };
- ASN1Encodable[] taggedObjects = new ASN1Encodable[]{
- requester,
- requestPolicy,
- dvcs,
- dataLocations,
- extensions
- };
- for (int i = 0; i < tags.length; i++)
- {
- int tag = tags[i];
- ASN1Encodable taggedObject = taggedObjects[i];
- if (taggedObject != null)
- {
- v.add(new DERTaggedObject(false, tag, taggedObject));
- }
- }
-
- return new DERSequence(v);
- }
-
- public String toString()
- {
-
- StringBuffer s = new StringBuffer();
-
- s.append("DVCSRequestInformation {\n");
-
- if (version != DEFAULT_VERSION)
- {
- s.append("version: " + version + "\n");
- }
- s.append("service: " + service + "\n");
- if (nonce != null)
- {
- s.append("nonce: " + nonce + "\n");
- }
- if (requestTime != null)
- {
- s.append("requestTime: " + requestTime + "\n");
- }
- if (requester != null)
- {
- s.append("requester: " + requester + "\n");
- }
- if (requestPolicy != null)
- {
- s.append("requestPolicy: " + requestPolicy + "\n");
- }
- if (dvcs != null)
- {
- s.append("dvcs: " + dvcs + "\n");
- }
- if (dataLocations != null)
- {
- s.append("dataLocations: " + dataLocations + "\n");
- }
- if (extensions != null)
- {
- s.append("extensions: " + extensions + "\n");
- }
-
- s.append("}\n");
- return s.toString();
- }
-
- public int getVersion()
- {
- return version;
- }
-
- public ServiceType getService()
- {
- return service;
- }
-
- public BigInteger getNonce()
- {
- return nonce;
- }
-
- public DVCSTime getRequestTime()
- {
- return requestTime;
- }
-
- public GeneralNames getRequester()
- {
- return requester;
- }
-
- public PolicyInformation getRequestPolicy()
- {
- return requestPolicy;
- }
-
- public GeneralNames getDVCS()
- {
- return dvcs;
- }
-
- public GeneralNames getDataLocations()
- {
- return dataLocations;
- }
-
- public Extensions getExtensions()
- {
- return extensions;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSRequestInformationBuilder.java b/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSRequestInformationBuilder.java
deleted file mode 100644
index 9b73c0a6..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSRequestInformationBuilder.java
+++ /dev/null
@@ -1,224 +0,0 @@
-package org.bouncycastle.asn1.dvcs;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.Extensions;
-import org.bouncycastle.asn1.x509.GeneralName;
-import org.bouncycastle.asn1.x509.GeneralNames;
-import org.bouncycastle.asn1.x509.PolicyInformation;
-import org.bouncycastle.util.BigIntegers;
-
-/**
- * <pre>
- * DVCSRequestInformation ::= SEQUENCE {
- * version INTEGER DEFAULT 1 ,
- * service ServiceType,
- * nonce Nonce OPTIONAL,
- * requestTime DVCSTime OPTIONAL,
- * requester [0] GeneralNames OPTIONAL,
- * requestPolicy [1] PolicyInformation OPTIONAL,
- * dvcs [2] GeneralNames OPTIONAL,
- * dataLocations [3] GeneralNames OPTIONAL,
- * extensions [4] IMPLICIT Extensions OPTIONAL
- * }
- * </pre>
- */
-public class DVCSRequestInformationBuilder
-{
- private int version = DEFAULT_VERSION;
-
- private final ServiceType service;
- private DVCSRequestInformation initialInfo;
-
- private BigInteger nonce;
- private DVCSTime requestTime;
- private GeneralNames requester;
- private PolicyInformation requestPolicy;
- private GeneralNames dvcs;
- private GeneralNames dataLocations;
- private Extensions extensions;
-
- private static final int DEFAULT_VERSION = 1;
- private static final int TAG_REQUESTER = 0;
- private static final int TAG_REQUEST_POLICY = 1;
- private static final int TAG_DVCS = 2;
- private static final int TAG_DATA_LOCATIONS = 3;
- private static final int TAG_EXTENSIONS = 4;
-
- public DVCSRequestInformationBuilder(ServiceType service)
- {
- this.service = service;
- }
-
- public DVCSRequestInformationBuilder(DVCSRequestInformation initialInfo)
- {
- this.initialInfo = initialInfo;
- this.service = initialInfo.getService();
- this.version = initialInfo.getVersion();
- this.nonce = initialInfo.getNonce();
- this.requestTime = initialInfo.getRequestTime();
- this.requestPolicy = initialInfo.getRequestPolicy();
- this.dvcs = initialInfo.getDVCS();
- this.dataLocations = initialInfo.getDataLocations();
- }
-
- public DVCSRequestInformation build()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (version != DEFAULT_VERSION)
- {
- v.add(new ASN1Integer(version));
- }
- v.add(service);
- if (nonce != null)
- {
- v.add(new ASN1Integer(nonce));
- }
- if (requestTime != null)
- {
- v.add(requestTime);
- }
-
- int[] tags = new int[]{
- TAG_REQUESTER,
- TAG_REQUEST_POLICY,
- TAG_DVCS,
- TAG_DATA_LOCATIONS,
- TAG_EXTENSIONS
- };
- ASN1Encodable[] taggedObjects = new ASN1Encodable[]{
- requester,
- requestPolicy,
- dvcs,
- dataLocations,
- extensions
- };
- for (int i = 0; i < tags.length; i++)
- {
- int tag = tags[i];
- ASN1Encodable taggedObject = taggedObjects[i];
- if (taggedObject != null)
- {
- v.add(new DERTaggedObject(false, tag, taggedObject));
- }
- }
-
- return DVCSRequestInformation.getInstance(new DERSequence(v));
- }
-
- public void setVersion(int version)
- {
- if (initialInfo != null)
- {
- throw new IllegalStateException("cannot change version in existing DVCSRequestInformation");
- }
-
- this.version = version;
- }
-
- public void setNonce(BigInteger nonce)
- {
- // RFC 3029, 9.1: The DVCS MAY modify the fields
- // 'dvcs', 'requester', 'dataLocations', and 'nonce' of the ReqInfo structure
-
- // RFC 3029, 9.1: The only modification
- // allowed to a 'nonce' is the inclusion of a new field if it was not
- // present, or to concatenate other data to the end (right) of an
- // existing value.
- if (initialInfo != null)
- {
- if (initialInfo.getNonce() == null)
- {
- this.nonce = nonce;
- }
- else
- {
- byte[] initialBytes = initialInfo.getNonce().toByteArray();
- byte[] newBytes = BigIntegers.asUnsignedByteArray(nonce);
- byte[] nonceBytes = new byte[initialBytes.length + newBytes.length];
-
- System.arraycopy(initialBytes, 0, nonceBytes, 0, initialBytes.length);
- System.arraycopy(newBytes, 0, nonceBytes, initialBytes.length, newBytes.length);
-
- this.nonce = new BigInteger(nonceBytes);
- }
- }
-
- this.nonce = nonce;
- }
-
- public void setRequestTime(DVCSTime requestTime)
- {
- if (initialInfo != null)
- {
- throw new IllegalStateException("cannot change request time in existing DVCSRequestInformation");
- }
-
- this.requestTime = requestTime;
- }
-
- public void setRequester(GeneralName requester)
- {
- this.setRequester(new GeneralNames(requester));
- }
-
- public void setRequester(GeneralNames requester)
- {
- // RFC 3029, 9.1: The DVCS MAY modify the fields
- // 'dvcs', 'requester', 'dataLocations', and 'nonce' of the ReqInfo structure
-
- this.requester = requester;
- }
-
- public void setRequestPolicy(PolicyInformation requestPolicy)
- {
- if (initialInfo != null)
- {
- throw new IllegalStateException("cannot change request policy in existing DVCSRequestInformation");
- }
-
- this.requestPolicy = requestPolicy;
- }
-
- public void setDVCS(GeneralName dvcs)
- {
- this.setDVCS(new GeneralNames(dvcs));
- }
-
- public void setDVCS(GeneralNames dvcs)
- {
- // RFC 3029, 9.1: The DVCS MAY modify the fields
- // 'dvcs', 'requester', 'dataLocations', and 'nonce' of the ReqInfo structure
-
- this.dvcs = dvcs;
- }
-
- public void setDataLocations(GeneralName dataLocation)
- {
- this.setDataLocations(new GeneralNames(dataLocation));
- }
-
- public void setDataLocations(GeneralNames dataLocations)
- {
- // RFC 3029, 9.1: The DVCS MAY modify the fields
- // 'dvcs', 'requester', 'dataLocations', and 'nonce' of the ReqInfo structure
-
- this.dataLocations = dataLocations;
- }
-
- public void setExtensions(Extensions extensions)
- {
- if (initialInfo != null)
- {
- throw new IllegalStateException("cannot change extensions in existing DVCSRequestInformation");
- }
-
- this.extensions = extensions;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSResponse.java b/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSResponse.java
deleted file mode 100644
index 3617e21d..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSResponse.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package org.bouncycastle.asn1.dvcs;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * <pre>
- * DVCSResponse ::= CHOICE
- * {
- * dvCertInfo DVCSCertInfo ,
- * dvErrorNote [0] DVCSErrorNotice
- * }
- * </pre>
- */
-
-public class DVCSResponse
- extends ASN1Object
- implements ASN1Choice
-{
- private DVCSCertInfo dvCertInfo;
- private DVCSErrorNotice dvErrorNote;
-
- public DVCSResponse(DVCSCertInfo dvCertInfo)
- {
- this.dvCertInfo = dvCertInfo;
- }
-
- public DVCSResponse(DVCSErrorNotice dvErrorNote)
- {
- this.dvErrorNote = dvErrorNote;
- }
-
- public static DVCSResponse getInstance(Object obj)
- {
- if (obj == null || obj instanceof DVCSResponse)
- {
- return (DVCSResponse)obj;
- }
- else
- {
- if (obj instanceof byte[])
- {
- try
- {
- return getInstance(ASN1Primitive.fromByteArray((byte[])obj));
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("failed to construct sequence from byte[]: " + e.getMessage());
- }
- }
- if (obj instanceof ASN1Sequence)
- {
- DVCSCertInfo dvCertInfo = DVCSCertInfo.getInstance(obj);
-
- return new DVCSResponse(dvCertInfo);
- }
- if (obj instanceof ASN1TaggedObject)
- {
- ASN1TaggedObject t = ASN1TaggedObject.getInstance(obj);
- DVCSErrorNotice dvErrorNote = DVCSErrorNotice.getInstance(t, false);
-
- return new DVCSResponse(dvErrorNote);
- }
- }
-
- throw new IllegalArgumentException("Couldn't convert from object to DVCSResponse: " + obj.getClass().getName());
- }
-
- public static DVCSResponse getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public DVCSCertInfo getCertInfo()
- {
- return dvCertInfo;
- }
-
- public DVCSErrorNotice getErrorNotice()
- {
- return dvErrorNote;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- if (dvCertInfo != null)
- {
- return dvCertInfo.toASN1Primitive();
- }
- else
- {
- return new DERTaggedObject(0, dvErrorNote);
- }
- }
-
- public String toString()
- {
- if (dvCertInfo != null)
- {
- return "DVCSResponse {\ndvCertInfo: " + dvCertInfo.toString() + "}\n";
- }
- if (dvErrorNote != null)
- {
- return "DVCSResponse {\ndvErrorNote: " + dvErrorNote.toString() + "}\n";
- }
- return null;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSTime.java b/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSTime.java
deleted file mode 100644
index aeb3c2cf..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/dvcs/DVCSTime.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package org.bouncycastle.asn1.dvcs;
-
-import java.util.Date;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.cms.ContentInfo;
-
-/**
- * <pre>
- * DVCSTime ::= CHOICE {
- * genTime GeneralizedTime,
- * timeStampToken ContentInfo
- * }
- * </pre>
- */
-public class DVCSTime
- extends ASN1Object
- implements ASN1Choice
-{
- private ASN1GeneralizedTime genTime;
- private ContentInfo timeStampToken;
- private Date time;
-
- // constructors:
-
- public DVCSTime(Date time)
- {
- this(new ASN1GeneralizedTime(time));
- }
-
- public DVCSTime(ASN1GeneralizedTime genTime)
- {
- this.genTime = genTime;
- }
-
- public DVCSTime(ContentInfo timeStampToken)
- {
- this.timeStampToken = timeStampToken;
- }
-
- public static DVCSTime getInstance(Object obj)
- {
- if (obj instanceof DVCSTime)
- {
- return (DVCSTime)obj;
- }
- else if (obj instanceof ASN1GeneralizedTime)
- {
- return new DVCSTime(ASN1GeneralizedTime.getInstance(obj));
- }
- else if (obj != null)
- {
- return new DVCSTime(ContentInfo.getInstance(obj));
- }
-
- return null;
- }
-
- public static DVCSTime getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject()); // must be explicitly tagged
- }
-
-
- // selectors:
-
- public ASN1GeneralizedTime getGenTime()
- {
- return genTime;
- }
-
- public ContentInfo getTimeStampToken()
- {
- return timeStampToken;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
-
- if (genTime != null)
- {
- return genTime;
- }
-
- if (timeStampToken != null)
- {
- return timeStampToken.toASN1Primitive();
- }
-
- return null;
- }
-
- public String toString()
- {
- if (genTime != null)
- {
- return genTime.toString();
- }
- if (timeStampToken != null)
- {
- return timeStampToken.toString();
- }
- return null;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/dvcs/Data.java b/core/src/main/java/org/bouncycastle/asn1/dvcs/Data.java
deleted file mode 100644
index 9c661f1f..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/dvcs/Data.java
+++ /dev/null
@@ -1,149 +0,0 @@
-package org.bouncycastle.asn1.dvcs;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.DigestInfo;
-
-/**
- * <pre>
- * Data ::= CHOICE {
- * message OCTET STRING ,
- * messageImprint DigestInfo,
- * certs [0] SEQUENCE SIZE (1..MAX) OF
- * TargetEtcChain
- * }
- * </pre>
- */
-
-public class Data
- extends ASN1Object
- implements ASN1Choice
-{
- private ASN1OctetString message;
- private DigestInfo messageImprint;
- private ASN1Sequence certs;
-
- public Data(byte[] messageBytes)
- {
- this.message = new DEROctetString(messageBytes);
- }
-
- public Data(ASN1OctetString message)
- {
- this.message = message;
- }
-
- public Data(DigestInfo messageImprint)
- {
- this.messageImprint = messageImprint;
- }
-
- public Data(TargetEtcChain cert)
- {
- this.certs = new DERSequence(cert);
- }
-
- public Data(TargetEtcChain[] certs)
- {
- this.certs = new DERSequence(certs);
- }
-
- private Data(ASN1Sequence certs)
- {
- this.certs = certs;
- }
-
- public static Data getInstance(Object obj)
- {
- if (obj instanceof Data)
- {
- return (Data)obj;
- }
- else if (obj instanceof ASN1OctetString)
- {
- return new Data((ASN1OctetString)obj);
- }
- else if (obj instanceof ASN1Sequence)
- {
- return new Data(DigestInfo.getInstance(obj));
- }
- else if (obj instanceof ASN1TaggedObject)
- {
- return new Data(ASN1Sequence.getInstance((ASN1TaggedObject)obj, false));
- }
- throw new IllegalArgumentException("Unknown object submitted to getInstance: " + obj.getClass().getName());
- }
-
- public static Data getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject());
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- if (message != null)
- {
- return message.toASN1Primitive();
- }
- if (messageImprint != null)
- {
- return messageImprint.toASN1Primitive();
- }
- else
- {
- return new DERTaggedObject(false, 0, certs);
- }
- }
-
- public String toString()
- {
- if (message != null)
- {
- return "Data {\n" + message + "}\n";
- }
- if (messageImprint != null)
- {
- return "Data {\n" + messageImprint + "}\n";
- }
- else
- {
- return "Data {\n" + certs + "}\n";
- }
- }
-
- public ASN1OctetString getMessage()
- {
- return message;
- }
-
- public DigestInfo getMessageImprint()
- {
- return messageImprint;
- }
-
- public TargetEtcChain[] getCerts()
- {
- if (certs == null)
- {
- return null;
- }
-
- TargetEtcChain[] tmp = new TargetEtcChain[certs.size()];
-
- for (int i = 0; i != tmp.length; i++)
- {
- tmp[i] = TargetEtcChain.getInstance(certs.getObjectAt(i));
- }
-
- return tmp;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/dvcs/PathProcInput.java b/core/src/main/java/org/bouncycastle/asn1/dvcs/PathProcInput.java
deleted file mode 100644
index 3123f40c..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/dvcs/PathProcInput.java
+++ /dev/null
@@ -1,180 +0,0 @@
-package org.bouncycastle.asn1.dvcs;
-
-import org.bouncycastle.asn1.ASN1Boolean;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.PolicyInformation;
-
-/**
- * <pre>
- * PathProcInput ::= SEQUENCE {
- * acceptablePolicySet SEQUENCE SIZE (1..MAX) OF
- * PolicyInformation,
- * inhibitPolicyMapping BOOLEAN DEFAULT FALSE,
- * explicitPolicyReqd [0] BOOLEAN DEFAULT FALSE ,
- * inhibitAnyPolicy [1] BOOLEAN DEFAULT FALSE
- * }
- * </pre>
- */
-public class PathProcInput
- extends ASN1Object
-{
-
- private PolicyInformation[] acceptablePolicySet;
- private boolean inhibitPolicyMapping = false;
- private boolean explicitPolicyReqd = false;
- private boolean inhibitAnyPolicy = false;
-
- public PathProcInput(PolicyInformation[] acceptablePolicySet)
- {
- this.acceptablePolicySet = acceptablePolicySet;
- }
-
- public PathProcInput(PolicyInformation[] acceptablePolicySet, boolean inhibitPolicyMapping, boolean explicitPolicyReqd, boolean inhibitAnyPolicy)
- {
- this.acceptablePolicySet = acceptablePolicySet;
- this.inhibitPolicyMapping = inhibitPolicyMapping;
- this.explicitPolicyReqd = explicitPolicyReqd;
- this.inhibitAnyPolicy = inhibitAnyPolicy;
- }
-
- private static PolicyInformation[] fromSequence(ASN1Sequence seq)
- {
- PolicyInformation[] tmp = new PolicyInformation[seq.size()];
-
- for (int i = 0; i != tmp.length; i++)
- {
- tmp[i] = PolicyInformation.getInstance(seq.getObjectAt(i));
- }
-
- return tmp;
- }
-
- public static PathProcInput getInstance(Object obj)
- {
- if (obj instanceof PathProcInput)
- {
- return (PathProcInput)obj;
- }
- else if (obj != null)
- {
- ASN1Sequence seq = ASN1Sequence.getInstance(obj);
- ASN1Sequence policies = ASN1Sequence.getInstance(seq.getObjectAt(0));
- PathProcInput result = new PathProcInput(fromSequence(policies));
-
- for (int i = 1; i < seq.size(); i++)
- {
- Object o = seq.getObjectAt(i);
-
- if (o instanceof ASN1Boolean)
- {
- ASN1Boolean x = ASN1Boolean.getInstance(o);
- result.setInhibitPolicyMapping(x.isTrue());
- }
- else if (o instanceof ASN1TaggedObject)
- {
- ASN1TaggedObject t = ASN1TaggedObject.getInstance(o);
- ASN1Boolean x;
- switch (t.getTagNo())
- {
- case 0:
- x = ASN1Boolean.getInstance(t, false);
- result.setExplicitPolicyReqd(x.isTrue());
- break;
- case 1:
- x = ASN1Boolean.getInstance(t, false);
- result.setInhibitAnyPolicy(x.isTrue());
- }
- }
- }
- return result;
- }
-
- return null;
- }
-
- public static PathProcInput getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- ASN1EncodableVector pV = new ASN1EncodableVector();
-
- for (int i = 0; i != acceptablePolicySet.length; i++)
- {
- pV.add(acceptablePolicySet[i]);
- }
-
- v.add(new DERSequence(pV));
-
- if (inhibitPolicyMapping)
- {
- v.add(new ASN1Boolean(inhibitPolicyMapping));
- }
- if (explicitPolicyReqd)
- {
- v.add(new DERTaggedObject(false, 0, new ASN1Boolean(explicitPolicyReqd)));
- }
- if (inhibitAnyPolicy)
- {
- v.add(new DERTaggedObject(false, 1, new ASN1Boolean(inhibitAnyPolicy)));
- }
-
- return new DERSequence(v);
- }
-
- public String toString()
- {
- return "PathProcInput: {\n" +
- "acceptablePolicySet: " + acceptablePolicySet + "\n" +
- "inhibitPolicyMapping: " + inhibitPolicyMapping + "\n" +
- "explicitPolicyReqd: " + explicitPolicyReqd + "\n" +
- "inhibitAnyPolicy: " + inhibitAnyPolicy + "\n" +
- "}\n";
- }
-
- public PolicyInformation[] getAcceptablePolicySet()
- {
- return acceptablePolicySet;
- }
-
- public boolean isInhibitPolicyMapping()
- {
- return inhibitPolicyMapping;
- }
-
- private void setInhibitPolicyMapping(boolean inhibitPolicyMapping)
- {
- this.inhibitPolicyMapping = inhibitPolicyMapping;
- }
-
- public boolean isExplicitPolicyReqd()
- {
- return explicitPolicyReqd;
- }
-
- private void setExplicitPolicyReqd(boolean explicitPolicyReqd)
- {
- this.explicitPolicyReqd = explicitPolicyReqd;
- }
-
- public boolean isInhibitAnyPolicy()
- {
- return inhibitAnyPolicy;
- }
-
- private void setInhibitAnyPolicy(boolean inhibitAnyPolicy)
- {
- this.inhibitAnyPolicy = inhibitAnyPolicy;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/dvcs/ServiceType.java b/core/src/main/java/org/bouncycastle/asn1/dvcs/ServiceType.java
deleted file mode 100644
index d6ee94f2..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/dvcs/ServiceType.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package org.bouncycastle.asn1.dvcs;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1Enumerated;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-
-
-/**
- * ServiceType ::= ENUMERATED { cpd(1), vsd(2), cpkc(3), ccpd(4) }
- */
-
-public class ServiceType
- extends ASN1Object
-{
- /**
- * Identifier of CPD service (Certify Possession of Data).
- */
- public static final ServiceType CPD = new ServiceType(1);
-
- /**
- * Identifier of VSD service (Verify Signed Document).
- */
- public static final ServiceType VSD = new ServiceType(2);
-
- /**
- * Identifier of VPKC service (Verify Public Key Certificates (also referred to as CPKC)).
- */
- public static final ServiceType VPKC = new ServiceType(3);
-
- /**
- * Identifier of CCPD service (Certify Claim of Possession of Data).
- */
- public static final ServiceType CCPD = new ServiceType(4);
-
- private ASN1Enumerated value;
-
- public ServiceType(int value)
- {
- this.value = new ASN1Enumerated(value);
- }
-
- private ServiceType(ASN1Enumerated value)
- {
- this.value = value;
- }
-
- public static ServiceType getInstance(Object obj)
- {
- if (obj instanceof ServiceType)
- {
- return (ServiceType)obj;
- }
- else if (obj != null)
- {
- return new ServiceType(ASN1Enumerated.getInstance(obj));
- }
-
- return null;
- }
-
- public static ServiceType getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Enumerated.getInstance(obj, explicit));
- }
-
- public BigInteger getValue()
- {
- return value.getValue();
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return value;
- }
-
- public String toString()
- {
- int num = value.getValue().intValue();
- return "" + num + (
- num == CPD.getValue().intValue() ? "(CPD)" :
- num == VSD.getValue().intValue() ? "(VSD)" :
- num == VPKC.getValue().intValue() ? "(VPKC)" :
- num == CCPD.getValue().intValue() ? "(CCPD)" :
- "?");
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/dvcs/TargetEtcChain.java b/core/src/main/java/org/bouncycastle/asn1/dvcs/TargetEtcChain.java
deleted file mode 100644
index ec3caadf..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/dvcs/TargetEtcChain.java
+++ /dev/null
@@ -1,191 +0,0 @@
-package org.bouncycastle.asn1.dvcs;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * <pre>
- * TargetEtcChain ::= SEQUENCE {
- * target CertEtcToken,
- * chain SEQUENCE SIZE (1..MAX) OF
- * CertEtcToken OPTIONAL,
- * pathProcInput [0] PathProcInput OPTIONAL
- * }
- * </pre>
- */
-
-public class TargetEtcChain
- extends ASN1Object
-{
- private CertEtcToken target;
- private ASN1Sequence chain;
- private PathProcInput pathProcInput;
-
- public TargetEtcChain(CertEtcToken target)
- {
- this(target, null, null);
- }
-
- public TargetEtcChain(CertEtcToken target, CertEtcToken[] chain)
- {
- this(target, chain, null);
- }
-
- public TargetEtcChain(CertEtcToken target, PathProcInput pathProcInput)
- {
- this(target, null, pathProcInput);
- }
-
- public TargetEtcChain(CertEtcToken target, CertEtcToken[] chain, PathProcInput pathProcInput)
- {
- this.target = target;
-
- if (chain != null)
- {
- this.chain = new DERSequence(chain);
- }
-
- this.pathProcInput = pathProcInput;
- }
-
- private TargetEtcChain(ASN1Sequence seq)
- {
- int i = 0;
- ASN1Encodable obj = seq.getObjectAt(i++);
- this.target = CertEtcToken.getInstance(obj);
-
- try
- {
- obj = seq.getObjectAt(i++);
- this.chain = ASN1Sequence.getInstance(obj);
- }
- catch (IllegalArgumentException e)
- {
- }
- catch (IndexOutOfBoundsException e)
- {
- return;
- }
-
- try
- {
- obj = seq.getObjectAt(i++);
- ASN1TaggedObject tagged = ASN1TaggedObject.getInstance(obj);
- switch (tagged.getTagNo())
- {
- case 0:
- this.pathProcInput = PathProcInput.getInstance(tagged, false);
- break;
- }
- }
- catch (IllegalArgumentException e)
- {
- }
- catch (IndexOutOfBoundsException e)
- {
- }
- }
-
- public static TargetEtcChain getInstance(Object obj)
- {
- if (obj instanceof TargetEtcChain)
- {
- return (TargetEtcChain)obj;
- }
- else if (obj != null)
- {
- return new TargetEtcChain(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public static TargetEtcChain getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- v.add(target);
- if (chain != null)
- {
- v.add(chain);
- }
- if (pathProcInput != null)
- {
- v.add(new DERTaggedObject(false, 0, pathProcInput));
- }
-
- return new DERSequence(v);
- }
-
- public String toString()
- {
- StringBuffer s = new StringBuffer();
- s.append("TargetEtcChain {\n");
- s.append("target: " + target + "\n");
- if (chain != null)
- {
- s.append("chain: " + chain + "\n");
- }
- if (pathProcInput != null)
- {
- s.append("pathProcInput: " + pathProcInput + "\n");
- }
- s.append("}\n");
- return s.toString();
- }
-
-
- public CertEtcToken getTarget()
- {
- return target;
- }
-
- public CertEtcToken[] getChain()
- {
- if (chain != null)
- {
- return CertEtcToken.arrayFromSequence(chain);
- }
-
- return null;
- }
-
- private void setChain(ASN1Sequence chain)
- {
- this.chain = chain;
- }
-
- public PathProcInput getPathProcInput()
- {
- return pathProcInput;
- }
-
- private void setPathProcInput(PathProcInput pathProcInput)
- {
- this.pathProcInput = pathProcInput;
- }
-
- public static TargetEtcChain[] arrayFromSequence(ASN1Sequence seq)
- {
- TargetEtcChain[] tmp = new TargetEtcChain[seq.size()];
-
- for (int i = 0; i != tmp.length; i++)
- {
- tmp[i] = TargetEtcChain.getInstance(seq.getObjectAt(i));
- }
-
- return tmp;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/eac/BidirectionalMap.java b/core/src/main/java/org/bouncycastle/asn1/eac/BidirectionalMap.java
deleted file mode 100644
index 3cf14503..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/eac/BidirectionalMap.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.asn1.eac;
-
-import java.util.Hashtable;
-
-public class BidirectionalMap
- extends Hashtable
-{
- private static final long serialVersionUID = -7457289971962812909L;
-
- Hashtable reverseMap = new Hashtable();
-
- public Object getReverse(Object o)
- {
- return reverseMap.get(o);
- }
-
- public Object put(Object key, Object o)
- {
- reverseMap.put(o, key);
- return super.put(key, o);
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/eac/CVCertificate.java b/core/src/main/java/org/bouncycastle/asn1/eac/CVCertificate.java
deleted file mode 100644
index 7bbd7f15..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/eac/CVCertificate.java
+++ /dev/null
@@ -1,313 +0,0 @@
-package org.bouncycastle.asn1.eac;
-
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1ParsingException;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.DERApplicationSpecific;
-import org.bouncycastle.asn1.DEROctetString;
-
-
-/**
- * an iso7816Certificate structure.
- * <pre>
- * Certificate ::= SEQUENCE {
- * CertificateBody Iso7816CertificateBody,
- * signature DER Application specific
- * }
- * </pre>
- */
-public class CVCertificate
- extends ASN1Object
-{
- private CertificateBody certificateBody;
- private byte[] signature;
- private int valid;
- private static int bodyValid = 0x01;
- private static int signValid = 0x02;
- public static final byte version_1 = 0x0;
-
- public static String ReferenceEncoding = "ISO-8859-1";
-
- /**
- * Sets the values of the certificate (body and signature).
- *
- * @param appSpe is a DERApplicationSpecific object containing body and signature.
- * @throws IOException if tags or value are incorrect.
- */
- private void setPrivateData(DERApplicationSpecific appSpe)
- throws IOException
- {
- valid = 0;
- if (appSpe.getApplicationTag() == EACTags.CARDHOLDER_CERTIFICATE)
- {
- ASN1InputStream content = new ASN1InputStream(appSpe.getContents());
- ASN1Primitive tmpObj;
- while ((tmpObj = content.readObject()) != null)
- {
- DERApplicationSpecific aSpe;
- if (tmpObj instanceof DERApplicationSpecific)
- {
- aSpe = (DERApplicationSpecific)tmpObj;
- switch (aSpe.getApplicationTag())
- {
- case EACTags.CERTIFICATE_CONTENT_TEMPLATE:
- certificateBody = CertificateBody.getInstance(aSpe);
- valid |= bodyValid;
- break;
- case EACTags.STATIC_INTERNAL_AUTHENTIFICATION_ONE_STEP:
- signature = aSpe.getContents();
- valid |= signValid;
- break;
- default:
- throw new IOException("Invalid tag, not an Iso7816CertificateStructure :" + aSpe.getApplicationTag());
- }
- }
- else
- {
- throw new IOException("Invalid Object, not an Iso7816CertificateStructure");
- }
- }
- }
- else
- {
- throw new IOException("not a CARDHOLDER_CERTIFICATE :" + appSpe.getApplicationTag());
- }
- }
-
- /**
- * Create an iso7816Certificate structure from an ASN1InputStream.
- *
- * @param aIS the byte stream to parse.
- * @throws IOException if there is a problem parsing the data.
- */
- public CVCertificate(ASN1InputStream aIS)
- throws IOException
- {
- initFrom(aIS);
- }
-
- private void initFrom(ASN1InputStream aIS)
- throws IOException
- {
- ASN1Primitive obj;
- while ((obj = aIS.readObject()) != null)
- {
- if (obj instanceof DERApplicationSpecific)
- {
- setPrivateData((DERApplicationSpecific)obj);
- }
- else
- {
- throw new IOException("Invalid Input Stream for creating an Iso7816CertificateStructure");
- }
- }
- }
-
- /**
- * Create an iso7816Certificate structure from a DERApplicationSpecific.
- *
- * @param appSpe the DERApplicationSpecific object.
- * @return the Iso7816CertificateStructure represented by the DERApplicationSpecific object.
- * @throws IOException if there is a problem parsing the data.
- */
- private CVCertificate(DERApplicationSpecific appSpe)
- throws IOException
- {
- setPrivateData(appSpe);
- }
-
- /**
- * Create an iso7816Certificate structure from a body and its signature.
- *
- * @param body the Iso7816CertificateBody object containing the body.
- * @param signature the byte array containing the signature
- * @throws IOException if there is a problem parsing the data.
- */
- public CVCertificate(CertificateBody body, byte[] signature)
- throws IOException
- {
- certificateBody = body;
- this.signature = signature;
- // patch remi
- valid |= bodyValid;
- valid |= signValid;
- }
-
- /**
- * Create an iso7816Certificate structure from an object.
- *
- * @param obj the Object to extract the certificate from.
- * @return the Iso7816CertificateStructure represented by the byte stream.
- */
- public static CVCertificate getInstance(Object obj)
- {
- if (obj instanceof CVCertificate)
- {
- return (CVCertificate)obj;
- }
- else if (obj != null)
- {
- try
- {
- return new CVCertificate(DERApplicationSpecific.getInstance(obj));
- }
- catch (IOException e)
- {
- throw new ASN1ParsingException("unable to parse data: " + e.getMessage(), e);
- }
- }
-
- return null;
- }
-
- /**
- * Gives the signature of the whole body. Type of signature is given in
- * the Iso7816CertificateBody.Iso7816PublicKey.ASN1ObjectIdentifier
- *
- * @return the signature of the body.
- */
- public byte[] getSignature()
- {
- return signature;
- }
-
- /**
- * Gives the body of the certificate.
- *
- * @return the body.
- */
- public CertificateBody getBody()
- {
- return certificateBody;
- }
-
- /**
- * @see org.bouncycastle.asn1.ASN1Object#toASN1Primitive()
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (valid != (signValid | bodyValid))
- {
- return null;
- }
- v.add(certificateBody);
-
- try
- {
- v.add(new DERApplicationSpecific(false, EACTags.STATIC_INTERNAL_AUTHENTIFICATION_ONE_STEP, new DEROctetString(signature)));
- }
- catch (IOException e)
- {
- throw new IllegalStateException("unable to convert signature!");
- }
-
- return new DERApplicationSpecific(EACTags.CARDHOLDER_CERTIFICATE, v);
- }
-
- /**
- * @return the Holder authorization and role (CVCA, DV, IS).
- */
- public ASN1ObjectIdentifier getHolderAuthorization()
- throws IOException
- {
- CertificateHolderAuthorization cha = certificateBody.getCertificateHolderAuthorization();
- return cha.getOid();
- }
-
- /**
- * @return the date of the certificate generation
- */
- public PackedDate getEffectiveDate()
- throws IOException
- {
- return certificateBody.getCertificateEffectiveDate();
- }
-
-
- /**
- * @return the type of certificate (request or profile)
- * value is either Iso7816CertificateBody.profileType
- * or Iso7816CertificateBody.requestType. Any other value
- * is not valid.
- */
- public int getCertificateType()
- {
- return this.certificateBody.getCertificateType();
- }
-
- /**
- * @return the date of the certificate generation
- */
- public PackedDate getExpirationDate()
- throws IOException
- {
- return certificateBody.getCertificateExpirationDate();
- }
-
-
- /**
- * return a bits field coded on one byte. For signification of the
- * several bit see Iso7816CertificateHolderAuthorization
- *
- * @return role and access rigth
- * @throws IOException
- * @see CertificateHolderAuthorization
- */
- public int getRole()
- throws IOException
- {
- CertificateHolderAuthorization cha = certificateBody.getCertificateHolderAuthorization();
- return cha.getAccessRights();
- }
-
- /**
- * @return the Authority Reference field of the certificate
- * @throws IOException
- */
- public CertificationAuthorityReference getAuthorityReference()
- throws IOException
- {
- return certificateBody.getCertificationAuthorityReference();
- }
-
- /**
- * @return the Holder Reference Field of the certificate
- * @throws IOException
- */
- public CertificateHolderReference getHolderReference()
- throws IOException
- {
- return certificateBody.getCertificateHolderReference();
- }
-
- /**
- * @return the bits corresponding to the role intented for the certificate
- * See Iso7816CertificateHolderAuthorization static int for values
- * @throws IOException
- */
- public int getHolderAuthorizationRole()
- throws IOException
- {
- int rights = certificateBody.getCertificateHolderAuthorization().getAccessRights();
- return rights & 0xC0;
- }
-
- /**
- * @return the bits corresponding the authorizations contained in the certificate
- * See Iso7816CertificateHolderAuthorization static int for values
- * @throws IOException
- */
- public Flags getHolderAuthorizationRights()
- throws IOException
- {
- return new Flags(certificateBody.getCertificateHolderAuthorization().getAccessRights() & 0x1F);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/eac/CVCertificateRequest.java b/core/src/main/java/org/bouncycastle/asn1/eac/CVCertificateRequest.java
deleted file mode 100644
index dcbc8f1d..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/eac/CVCertificateRequest.java
+++ /dev/null
@@ -1,170 +0,0 @@
-package org.bouncycastle.asn1.eac;
-
-import java.io.IOException;
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1ParsingException;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.BERTags;
-import org.bouncycastle.asn1.DERApplicationSpecific;
-import org.bouncycastle.asn1.DEROctetString;
-
-//import java.math.BigInteger;
-
-
-public class CVCertificateRequest
- extends ASN1Object
-{
- private CertificateBody certificateBody;
-
- private byte[] innerSignature = null;
- private byte[] outerSignature = null;
-
- private int valid;
-
- private static int bodyValid = 0x01;
- private static int signValid = 0x02;
-
- private CVCertificateRequest(DERApplicationSpecific request)
- throws IOException
- {
- if (request.getApplicationTag() == EACTags.AUTHENTIFICATION_DATA)
- {
- ASN1Sequence seq = ASN1Sequence.getInstance(request.getObject(BERTags.SEQUENCE));
-
- initCertBody(DERApplicationSpecific.getInstance(seq.getObjectAt(0)));
-
- outerSignature = DERApplicationSpecific.getInstance(seq.getObjectAt(seq.size() - 1)).getContents();
- }
- else
- {
- initCertBody(request);
- }
- }
-
- private void initCertBody(DERApplicationSpecific request)
- throws IOException
- {
- if (request.getApplicationTag() == EACTags.CARDHOLDER_CERTIFICATE)
- {
- ASN1Sequence seq = ASN1Sequence.getInstance(request.getObject(BERTags.SEQUENCE));
- for (Enumeration en = seq.getObjects(); en.hasMoreElements();)
- {
- DERApplicationSpecific obj = DERApplicationSpecific.getInstance(en.nextElement());
- switch (obj.getApplicationTag())
- {
- case EACTags.CERTIFICATE_CONTENT_TEMPLATE:
- certificateBody = CertificateBody.getInstance(obj);
- valid |= bodyValid;
- break;
- case EACTags.STATIC_INTERNAL_AUTHENTIFICATION_ONE_STEP:
- innerSignature = obj.getContents();
- valid |= signValid;
- break;
- default:
- throw new IOException("Invalid tag, not an CV Certificate Request element:" + obj.getApplicationTag());
- }
- }
- }
- else
- {
- throw new IOException("not a CARDHOLDER_CERTIFICATE in request:" + request.getApplicationTag());
- }
- }
-
- public static CVCertificateRequest getInstance(Object obj)
- {
- if (obj instanceof CVCertificateRequest)
- {
- return (CVCertificateRequest)obj;
- }
- else if (obj != null)
- {
- try
- {
- return new CVCertificateRequest(DERApplicationSpecific.getInstance(obj));
- }
- catch (IOException e)
- {
- throw new ASN1ParsingException("unable to parse data: " + e.getMessage(), e);
- }
- }
-
- return null;
- }
-
- ASN1ObjectIdentifier signOid = null;
- ASN1ObjectIdentifier keyOid = null;
-
- public static byte[] ZeroArray = new byte[]{0};
-
-
- String strCertificateHolderReference;
-
- byte[] encodedAuthorityReference;
-
- int ProfileId;
-
- /**
- * Returns the body of the certificate template
- *
- * @return the body.
- */
- public CertificateBody getCertificateBody()
- {
- return certificateBody;
- }
-
- /**
- * Return the public key data object carried in the request
- * @return the public key
- */
- public PublicKeyDataObject getPublicKey()
- {
- return certificateBody.getPublicKey();
- }
-
- public byte[] getInnerSignature()
- {
- return innerSignature;
- }
-
- public byte[] getOuterSignature()
- {
- return outerSignature;
- }
-
- byte[] certificate = null;
- protected String overSignerReference = null;
-
- public boolean hasOuterSignature()
- {
- return outerSignature != null;
- }
-
- byte[] encoded;
-
- PublicKeyDataObject iso7816PubKey = null;
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(certificateBody);
-
- try
- {
- v.add(new DERApplicationSpecific(false, EACTags.STATIC_INTERNAL_AUTHENTIFICATION_ONE_STEP, new DEROctetString(innerSignature)));
- }
- catch (IOException e)
- {
- throw new IllegalStateException("unable to convert signature!");
- }
-
- return new DERApplicationSpecific(EACTags.CARDHOLDER_CERTIFICATE, v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/eac/CertificateBody.java b/core/src/main/java/org/bouncycastle/asn1/eac/CertificateBody.java
deleted file mode 100644
index 04c4d703..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/eac/CertificateBody.java
+++ /dev/null
@@ -1,472 +0,0 @@
-package org.bouncycastle.asn1.eac;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.BERTags;
-import org.bouncycastle.asn1.DERApplicationSpecific;
-import org.bouncycastle.asn1.DEROctetString;
-
-
-/**
- * an Iso7816CertificateBody structure.
- * <pre>
- * CertificateBody ::= SEQUENCE {
- * // version of the certificate format. Must be 0 (version 1)
- * CertificateProfileIdentifer DERApplicationSpecific,
- * //uniquely identifies the issuinng CA's signature key pair
- * // contains the iso3166-1 alpha2 encoded country code, the
- * // name of issuer and the sequence number of the key pair.
- * CertificationAuthorityReference DERApplicationSpecific,
- * // stores the encoded public key
- * PublicKey Iso7816PublicKey,
- * //associates the public key contained in the certificate with a unique name
- * // contains the iso3166-1 alpha2 encoded country code, the
- * // name of the holder and the sequence number of the key pair.
- * certificateHolderReference DERApplicationSpecific,
- * // Encodes the role of the holder (i.e. CVCA, DV, IS) and assigns read/write
- * // access rights to data groups storing sensitive data
- * certificateHolderAuthorization Iso7816CertificateHolderAuthorization,
- * // the date of the certificate generation
- * CertificateEffectiveDate DERApplicationSpecific,
- * // the date after wich the certificate expires
- * certificateExpirationDate DERApplicationSpecific
- * }
- * </pre>
- */
-public class CertificateBody
- extends ASN1Object
-{
- ASN1InputStream seq;
- private DERApplicationSpecific certificateProfileIdentifier;// version of the certificate format. Must be 0 (version 1)
- private DERApplicationSpecific certificationAuthorityReference;//uniquely identifies the issuinng CA's signature key pair
- private PublicKeyDataObject publicKey;// stores the encoded public key
- private DERApplicationSpecific certificateHolderReference;//associates the public key contained in the certificate with a unique name
- private CertificateHolderAuthorization certificateHolderAuthorization;// Encodes the role of the holder (i.e. CVCA, DV, IS) and assigns read/write access rights to data groups storing sensitive data
- private DERApplicationSpecific certificateEffectiveDate;// the date of the certificate generation
- private DERApplicationSpecific certificateExpirationDate;// the date after wich the certificate expires
- private int certificateType = 0;// bit field of initialized data. This will tell us if the data are valid.
- private static final int CPI = 0x01;//certificate Profile Identifier
- private static final int CAR = 0x02;//certification Authority Reference
- private static final int PK = 0x04;//public Key
- private static final int CHR = 0x08;//certificate Holder Reference
- private static final int CHA = 0x10;//certificate Holder Authorization
- private static final int CEfD = 0x20;//certificate Effective Date
- private static final int CExD = 0x40;//certificate Expiration Date
-
- public static final int profileType = 0x7f;//Profile type Certificate
- public static final int requestType = 0x0D;// Request type Certificate
-
- private void setIso7816CertificateBody(DERApplicationSpecific appSpe)
- throws IOException
- {
- byte[] content;
- if (appSpe.getApplicationTag() == EACTags.CERTIFICATE_CONTENT_TEMPLATE)
- {
- content = appSpe.getContents();
- }
- else
- {
- throw new IOException("Bad tag : not an iso7816 CERTIFICATE_CONTENT_TEMPLATE");
- }
- ASN1InputStream aIS = new ASN1InputStream(content);
- ASN1Primitive obj;
- while ((obj = aIS.readObject()) != null)
- {
- DERApplicationSpecific aSpe;
-
- if (obj instanceof DERApplicationSpecific)
- {
- aSpe = (DERApplicationSpecific)obj;
- }
- else
- {
- throw new IOException("Not a valid iso7816 content : not a DERApplicationSpecific Object :" + EACTags.encodeTag(appSpe) + obj.getClass());
- }
- switch (aSpe.getApplicationTag())
- {
- case EACTags.INTERCHANGE_PROFILE:
- setCertificateProfileIdentifier(aSpe);
- break;
- case EACTags.ISSUER_IDENTIFICATION_NUMBER:
- setCertificationAuthorityReference(aSpe);
- break;
- case EACTags.CARDHOLDER_PUBLIC_KEY_TEMPLATE:
- setPublicKey(PublicKeyDataObject.getInstance(aSpe.getObject(BERTags.SEQUENCE)));
- break;
- case EACTags.CARDHOLDER_NAME:
- setCertificateHolderReference(aSpe);
- break;
- case EACTags.CERTIFICATE_HOLDER_AUTHORIZATION_TEMPLATE:
- setCertificateHolderAuthorization(new CertificateHolderAuthorization(aSpe));
- break;
- case EACTags.APPLICATION_EFFECTIVE_DATE:
- setCertificateEffectiveDate(aSpe);
- break;
- case EACTags.APPLICATION_EXPIRATION_DATE:
- setCertificateExpirationDate(aSpe);
- break;
- default:
- certificateType = 0;
- throw new IOException("Not a valid iso7816 DERApplicationSpecific tag " + aSpe.getApplicationTag());
- }
- }
- }
-
- /**
- * builds an Iso7816CertificateBody by settings each parameters.
- *
- * @param certificateProfileIdentifier
- * @param certificationAuthorityReference
- *
- * @param publicKey
- * @param certificateHolderReference
- * @param certificateHolderAuthorization
- * @param certificateEffectiveDate
- * @param certificateExpirationDate
- */
- public CertificateBody(
- DERApplicationSpecific certificateProfileIdentifier,
- CertificationAuthorityReference certificationAuthorityReference,
- PublicKeyDataObject publicKey,
- CertificateHolderReference certificateHolderReference,
- CertificateHolderAuthorization certificateHolderAuthorization,
- PackedDate certificateEffectiveDate,
- PackedDate certificateExpirationDate
- )
- {
- setCertificateProfileIdentifier(certificateProfileIdentifier);
- setCertificationAuthorityReference(new DERApplicationSpecific(
- EACTags.ISSUER_IDENTIFICATION_NUMBER, certificationAuthorityReference.getEncoded()));
- setPublicKey(publicKey);
- setCertificateHolderReference(new DERApplicationSpecific(
- EACTags.CARDHOLDER_NAME, certificateHolderReference.getEncoded()));
- setCertificateHolderAuthorization(certificateHolderAuthorization);
- try
- {
- setCertificateEffectiveDate(new DERApplicationSpecific(
- false, EACTags.APPLICATION_EFFECTIVE_DATE, new DEROctetString(certificateEffectiveDate.getEncoding())));
- setCertificateExpirationDate(new DERApplicationSpecific(
- false, EACTags.APPLICATION_EXPIRATION_DATE, new DEROctetString(certificateExpirationDate.getEncoding())));
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("unable to encode dates: " + e.getMessage());
- }
- }
-
- /**
- * builds an Iso7816CertificateBody with an ASN1InputStream.
- *
- * @param obj DERApplicationSpecific containing the whole body.
- * @throws IOException if the body is not valid.
- */
- private CertificateBody(DERApplicationSpecific obj)
- throws IOException
- {
- setIso7816CertificateBody(obj);
- }
-
- /**
- * create a profile type Iso7816CertificateBody.
- *
- * @return return the "profile" type certificate body.
- * @throws IOException if the DERApplicationSpecific cannot be created.
- */
- private ASN1Primitive profileToASN1Object()
- throws IOException
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(certificateProfileIdentifier);
- v.add(certificationAuthorityReference);
- v.add(new DERApplicationSpecific(false, EACTags.CARDHOLDER_PUBLIC_KEY_TEMPLATE, publicKey));
- v.add(certificateHolderReference);
- v.add(certificateHolderAuthorization);
- v.add(certificateEffectiveDate);
- v.add(certificateExpirationDate);
- return new DERApplicationSpecific(EACTags.CERTIFICATE_CONTENT_TEMPLATE, v);
- }
-
- private void setCertificateProfileIdentifier(DERApplicationSpecific certificateProfileIdentifier)
- throws IllegalArgumentException
- {
- if (certificateProfileIdentifier.getApplicationTag() == EACTags.INTERCHANGE_PROFILE)
- {
- this.certificateProfileIdentifier = certificateProfileIdentifier;
- certificateType |= CPI;
- }
- else
- {
- throw new IllegalArgumentException("Not an Iso7816Tags.INTERCHANGE_PROFILE tag :" + EACTags.encodeTag(certificateProfileIdentifier));
- }
- }
-
- private void setCertificateHolderReference(DERApplicationSpecific certificateHolderReference)
- throws IllegalArgumentException
- {
- if (certificateHolderReference.getApplicationTag() == EACTags.CARDHOLDER_NAME)
- {
- this.certificateHolderReference = certificateHolderReference;
- certificateType |= CHR;
- }
- else
- {
- throw new IllegalArgumentException("Not an Iso7816Tags.CARDHOLDER_NAME tag");
- }
- }
-
- /**
- * set the CertificationAuthorityReference.
- *
- * @param certificationAuthorityReference
- * the DERApplicationSpecific containing the CertificationAuthorityReference.
- * @throws IllegalArgumentException if the DERApplicationSpecific is not valid.
- */
- private void setCertificationAuthorityReference(
- DERApplicationSpecific certificationAuthorityReference)
- throws IllegalArgumentException
- {
- if (certificationAuthorityReference.getApplicationTag() == EACTags.ISSUER_IDENTIFICATION_NUMBER)
- {
- this.certificationAuthorityReference = certificationAuthorityReference;
- certificateType |= CAR;
- }
- else
- {
- throw new IllegalArgumentException("Not an Iso7816Tags.ISSUER_IDENTIFICATION_NUMBER tag");
- }
- }
-
- /**
- * set the public Key
- *
- * @param publicKey : the DERApplicationSpecific containing the public key
- * @throws java.io.IOException
- */
- private void setPublicKey(PublicKeyDataObject publicKey)
- {
- this.publicKey = PublicKeyDataObject.getInstance(publicKey);
- this.certificateType |= PK;
- }
-
- /**
- * create a request type Iso7816CertificateBody.
- *
- * @return return the "request" type certificate body.
- * @throws IOException if the DERApplicationSpecific cannot be created.
- */
- private ASN1Primitive requestToASN1Object()
- throws IOException
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(certificateProfileIdentifier);
- v.add(new DERApplicationSpecific(false, EACTags.CARDHOLDER_PUBLIC_KEY_TEMPLATE, publicKey));
- v.add(certificateHolderReference);
- return new DERApplicationSpecific(EACTags.CERTIFICATE_CONTENT_TEMPLATE, v);
- }
-
- /**
- * create a "request" or "profile" type Iso7816CertificateBody according to the variables sets.
- *
- * @return return the ASN1Primitive representing the "request" or "profile" type certificate body.
- */
- public ASN1Primitive toASN1Primitive()
- {
- try
- {
- if (certificateType == profileType)
- {
- return profileToASN1Object();
- }
- if (certificateType == requestType)
- {
- return requestToASN1Object();
- }
- }
- catch (IOException e)
- {
- return null;
- }
- return null;
- }
-
- /**
- * gives the type of the certificate (value should be profileType or requestType if all data are set).
- *
- * @return the int representing the data already set.
- */
- public int getCertificateType()
- {
- return certificateType;
- }
-
- /**
- * Gives an instance of Iso7816CertificateBody taken from Object obj
- *
- * @param obj is the Object to extract the certificate body from.
- * @return the Iso7816CertificateBody taken from Object obj.
- * @throws IOException if object is not valid.
- */
- public static CertificateBody getInstance(Object obj)
- throws IOException
- {
- if (obj instanceof CertificateBody)
- {
- return (CertificateBody)obj;
- }
- else if (obj != null)
- {
- return new CertificateBody(DERApplicationSpecific.getInstance(obj));
- }
-
- return null;
- }
-
- /**
- * @return the date of the certificate generation
- */
- public PackedDate getCertificateEffectiveDate()
- {
- if ((this.certificateType & CertificateBody.CEfD) ==
- CertificateBody.CEfD)
- {
- return new PackedDate(certificateEffectiveDate.getContents());
- }
- return null;
- }
-
- /**
- * set the date of the certificate generation
- *
- * @param ced DERApplicationSpecific containing the date of the certificate generation
- * @throws IllegalArgumentException if the tag is not Iso7816Tags.APPLICATION_EFFECTIVE_DATE
- */
- private void setCertificateEffectiveDate(DERApplicationSpecific ced)
- throws IllegalArgumentException
- {
- if (ced.getApplicationTag() == EACTags.APPLICATION_EFFECTIVE_DATE)
- {
- this.certificateEffectiveDate = ced;
- certificateType |= CEfD;
- }
- else
- {
- throw new IllegalArgumentException("Not an Iso7816Tags.APPLICATION_EFFECTIVE_DATE tag :" + EACTags.encodeTag(ced));
- }
- }
-
- /**
- * @return the date after wich the certificate expires
- */
- public PackedDate getCertificateExpirationDate()
- throws IOException
- {
- if ((this.certificateType & CertificateBody.CExD) ==
- CertificateBody.CExD)
- {
- return new PackedDate(certificateExpirationDate.getContents());
- }
- throw new IOException("certificate Expiration Date not set");
- }
-
- /**
- * set the date after wich the certificate expires
- *
- * @param ced DERApplicationSpecific containing the date after wich the certificate expires
- * @throws IllegalArgumentException if the tag is not Iso7816Tags.APPLICATION_EXPIRATION_DATE
- */
- private void setCertificateExpirationDate(DERApplicationSpecific ced)
- throws IllegalArgumentException
- {
- if (ced.getApplicationTag() == EACTags.APPLICATION_EXPIRATION_DATE)
- {
- this.certificateExpirationDate = ced;
- certificateType |= CExD;
- }
- else
- {
- throw new IllegalArgumentException("Not an Iso7816Tags.APPLICATION_EXPIRATION_DATE tag");
- }
- }
-
- /**
- * the Iso7816CertificateHolderAuthorization encodes the role of the holder
- * (i.e. CVCA, DV, IS) and assigns read/write access rights to data groups
- * storing sensitive data. This functions returns the Certificate Holder
- * Authorization
- *
- * @return the Iso7816CertificateHolderAuthorization
- */
- public CertificateHolderAuthorization getCertificateHolderAuthorization()
- throws IOException
- {
- if ((this.certificateType & CertificateBody.CHA) ==
- CertificateBody.CHA)
- {
- return certificateHolderAuthorization;
- }
- throw new IOException("Certificate Holder Authorisation not set");
- }
-
- /**
- * set the CertificateHolderAuthorization
- *
- * @param cha the Certificate Holder Authorization
- */
- private void setCertificateHolderAuthorization(
- CertificateHolderAuthorization cha)
- {
- this.certificateHolderAuthorization = cha;
- certificateType |= CHA;
- }
-
- /**
- * certificateHolderReference : associates the public key contained in the certificate with a unique name
- *
- * @return the certificateHolderReference.
- */
- public CertificateHolderReference getCertificateHolderReference()
- {
- return new CertificateHolderReference(certificateHolderReference.getContents());
- }
-
- /**
- * CertificateProfileIdentifier : version of the certificate format. Must be 0 (version 1)
- *
- * @return the CertificateProfileIdentifier
- */
- public DERApplicationSpecific getCertificateProfileIdentifier()
- {
- return certificateProfileIdentifier;
- }
-
- /**
- * get the certificationAuthorityReference
- * certificationAuthorityReference : uniquely identifies the issuinng CA's signature key pair
- *
- * @return the certificationAuthorityReference
- */
- public CertificationAuthorityReference getCertificationAuthorityReference()
- throws IOException
- {
- if ((this.certificateType & CertificateBody.CAR) ==
- CertificateBody.CAR)
- {
- return new CertificationAuthorityReference(certificationAuthorityReference.getContents());
- }
- throw new IOException("Certification authority reference not set");
- }
-
- /**
- * @return the PublicKey
- */
- public PublicKeyDataObject getPublicKey()
- {
- return publicKey;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/eac/CertificateHolderAuthorization.java b/core/src/main/java/org/bouncycastle/asn1/eac/CertificateHolderAuthorization.java
deleted file mode 100644
index ba8486aa..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/eac/CertificateHolderAuthorization.java
+++ /dev/null
@@ -1,184 +0,0 @@
-package org.bouncycastle.asn1.eac;
-
-import java.io.IOException;
-import java.util.Hashtable;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.DERApplicationSpecific;
-import org.bouncycastle.util.Integers;
-
-/**
- * an Iso7816CertificateHolderAuthorization structure.
- * <pre>
- * Certificate Holder Authorization ::= SEQUENCE {
- * // specifies the format and the rules for the evaluation of the authorization
- * // level
- * ASN1ObjectIdentifier oid,
- * // access rights
- * DERApplicationSpecific accessRights,
- * }
- * </pre>
- */
-public class CertificateHolderAuthorization
- extends ASN1Object
-{
- ASN1ObjectIdentifier oid;
- DERApplicationSpecific accessRights;
- public static final ASN1ObjectIdentifier id_role_EAC = EACObjectIdentifiers.bsi_de.branch("3.1.2.1");
- public static final int CVCA = 0xC0;
- public static final int DV_DOMESTIC = 0x80;
- public static final int DV_FOREIGN = 0x40;
- public static final int IS = 0;
- public static final int RADG4 = 0x02;//Read Access to DG4 (Iris)
- public static final int RADG3 = 0x01;//Read Access to DG3 (fingerprint)
-
- static Hashtable RightsDecodeMap = new Hashtable();
- static BidirectionalMap AuthorizationRole = new BidirectionalMap();
- static Hashtable ReverseMap = new Hashtable();
-
- static
- {
- RightsDecodeMap.put(Integers.valueOf(RADG4), "RADG4");
- RightsDecodeMap.put(Integers.valueOf(RADG3), "RADG3");
-
- AuthorizationRole.put(Integers.valueOf(CVCA), "CVCA");
- AuthorizationRole.put(Integers.valueOf(DV_DOMESTIC), "DV_DOMESTIC");
- AuthorizationRole.put(Integers.valueOf(DV_FOREIGN), "DV_FOREIGN");
- AuthorizationRole.put(Integers.valueOf(IS), "IS");
-
- /*
- for (int i : RightsDecodeMap.keySet())
- ReverseMap.put(RightsDecodeMap.get(i), i);
-
- for (int i : AuthorizationRole.keySet())
- ReverseMap.put(AuthorizationRole.get(i), i);
- */
- }
-
- public static String GetRoleDescription(int i)
- {
- return (String)AuthorizationRole.get(Integers.valueOf(i));
- }
-
- public static int GetFlag(String description)
- {
- Integer i = (Integer)AuthorizationRole.getReverse(description);
- if (i == null)
- {
- throw new IllegalArgumentException("Unknown value " + description);
- }
-
- return i.intValue();
- }
-
- private void setPrivateData(ASN1InputStream cha)
- throws IOException
- {
- ASN1Primitive obj;
- obj = cha.readObject();
- if (obj instanceof ASN1ObjectIdentifier)
- {
- this.oid = (ASN1ObjectIdentifier)obj;
- }
- else
- {
- throw new IllegalArgumentException("no Oid in CerticateHolderAuthorization");
- }
- obj = cha.readObject();
- if (obj instanceof DERApplicationSpecific)
- {
- this.accessRights = (DERApplicationSpecific)obj;
- }
- else
- {
- throw new IllegalArgumentException("No access rights in CerticateHolderAuthorization");
- }
- }
-
-
- /**
- * create an Iso7816CertificateHolderAuthorization according to the parameters
- *
- * @param oid Object Identifier : specifies the format and the rules for the
- * evaluatioin of the authorization level.
- * @param rights specifies the access rights
- * @throws IOException
- */
- public CertificateHolderAuthorization(ASN1ObjectIdentifier oid, int rights)
- throws IOException
- {
- setOid(oid);
- setAccessRights((byte)rights);
- }
-
- /**
- * create an Iso7816CertificateHolderAuthorization according to the {@link DERApplicationSpecific}
- *
- * @param aSpe the DERApplicationSpecific containing the data
- * @throws IOException
- */
- public CertificateHolderAuthorization(DERApplicationSpecific aSpe)
- throws IOException
- {
- if (aSpe.getApplicationTag() == EACTags.CERTIFICATE_HOLDER_AUTHORIZATION_TEMPLATE)
- {
- setPrivateData(new ASN1InputStream(aSpe.getContents()));
- }
- }
-
- /**
- * @return containing the access rights
- */
- public int getAccessRights()
- {
- return accessRights.getContents()[0] & 0xff;
- }
-
- /**
- * create a DERApplicationSpecific and set the access rights to "rights"
- *
- * @param rights byte containing the rights.
- */
- private void setAccessRights(byte rights)
- {
- byte[] accessRights = new byte[1];
- accessRights[0] = rights;
- this.accessRights = new DERApplicationSpecific(
- EACTags.getTag(EACTags.DISCRETIONARY_DATA), accessRights);
- }
-
- /**
- * @return the Object identifier
- */
- public ASN1ObjectIdentifier getOid()
- {
- return oid;
- }
-
- /**
- * set the Object Identifier
- *
- * @param oid {@link ASN1ObjectIdentifier} containing the Object Identifier
- */
- private void setOid(ASN1ObjectIdentifier oid)
- {
- this.oid = oid;
- }
-
- /**
- * return the Certificate Holder Authorization as a DERApplicationSpecific Object
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(oid);
- v.add(accessRights);
-
- return new DERApplicationSpecific(EACTags.CERTIFICATE_HOLDER_AUTHORIZATION_TEMPLATE, v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/eac/CertificateHolderReference.java b/core/src/main/java/org/bouncycastle/asn1/eac/CertificateHolderReference.java
deleted file mode 100644
index ec8dec08..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/eac/CertificateHolderReference.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package org.bouncycastle.asn1.eac;
-
-import java.io.UnsupportedEncodingException;
-
-public class CertificateHolderReference
-{
- private static final String ReferenceEncoding = "ISO-8859-1";
-
- private String countryCode;
- private String holderMnemonic;
- private String sequenceNumber;
-
- public CertificateHolderReference(String countryCode, String holderMnemonic, String sequenceNumber)
- {
- this.countryCode = countryCode;
- this.holderMnemonic = holderMnemonic;
- this.sequenceNumber = sequenceNumber;
- }
-
- CertificateHolderReference(byte[] contents)
- {
- try
- {
- String concat = new String(contents, ReferenceEncoding);
-
- this.countryCode = concat.substring(0, 2);
- this.holderMnemonic = concat.substring(2, concat.length() - 5);
-
- this.sequenceNumber = concat.substring(concat.length() - 5);
- }
- catch (UnsupportedEncodingException e)
- {
- throw new IllegalStateException(e.toString());
- }
- }
-
- public String getCountryCode()
- {
- return countryCode;
- }
-
- public String getHolderMnemonic()
- {
- return holderMnemonic;
- }
-
- public String getSequenceNumber()
- {
- return sequenceNumber;
- }
-
-
- public byte[] getEncoded()
- {
- String ref = countryCode + holderMnemonic + sequenceNumber;
-
- try
- {
- return ref.getBytes(ReferenceEncoding);
- }
- catch (UnsupportedEncodingException e)
- {
- throw new IllegalStateException(e.toString());
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/eac/CertificationAuthorityReference.java b/core/src/main/java/org/bouncycastle/asn1/eac/CertificationAuthorityReference.java
deleted file mode 100644
index 7a5dc8ab..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/eac/CertificationAuthorityReference.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.bouncycastle.asn1.eac;
-
-public class CertificationAuthorityReference
- extends CertificateHolderReference
-{
- public CertificationAuthorityReference(String countryCode, String holderMnemonic, String sequenceNumber)
- {
- super(countryCode, holderMnemonic, sequenceNumber);
- }
-
- CertificationAuthorityReference(byte[] contents)
- {
- super(contents);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/eac/EACObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/eac/EACObjectIdentifiers.java
deleted file mode 100644
index 805a5064..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/eac/EACObjectIdentifiers.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package org.bouncycastle.asn1.eac;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-
-/**
- * German Federal Office for Information Security
- * (Bundesamt f&uuml;r Sicherheit in der Informationstechnik)
- * <a href="http://www.bsi.bund.de/">http://www.bsi.bund.de/</a>
- * <p>
- * <a href="https://www.bsi.bund.de/EN/Publications/TechnicalGuidelines/TR03110/BSITR03110.html">BSI TR-03110</a>
- * Technical Guideline Advanced Security Mechanisms for Machine Readable Travel Documents
- * <p>
- * <a href="https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/TechGuidelines/TR03110/TR-03110_v2.1_P3pdf.pdf">
- * Technical Guideline TR-03110-3</a>
- * Advanced Security Mechanisms for Machine Readable Travel Documents;
- * Part 3: Common Specifications.
- */
-public interface EACObjectIdentifiers
-{
- /**
- * <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");
-
- /**
- * <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");
-
- /** 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");
-
- /**
- * <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");
-
- /**
- * <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");
-
- /** 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");
- /** 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");
- /** 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
- * }
- * </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/core/src/main/java/org/bouncycastle/asn1/eac/EACTags.java b/core/src/main/java/org/bouncycastle/asn1/eac/EACTags.java
deleted file mode 100644
index b9ffe9d1..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/eac/EACTags.java
+++ /dev/null
@@ -1,209 +0,0 @@
-package org.bouncycastle.asn1.eac;
-
-import org.bouncycastle.asn1.BERTags;
-import org.bouncycastle.asn1.DERApplicationSpecific;
-
-public class EACTags
-{
- public static final int OBJECT_IDENTIFIER = 0x06;
- public static final int COUNTRY_CODE_NATIONAL_DATA = 0x41;
- public static final int ISSUER_IDENTIFICATION_NUMBER = 0x02; //0x42;
- public static final int CARD_SERVICE_DATA = 0x43;
- public static final int INITIAL_ACCESS_DATA = 0x44;
- public static final int CARD_ISSUER_DATA = 0x45;
- public static final int PRE_ISSUING_DATA = 0x46;
- public static final int CARD_CAPABILITIES = 0x47;
- public static final int STATUS_INFORMATION = 0x48;
- public static final int EXTENDED_HEADER_LIST = 0x4D;
- public static final int APPLICATION_IDENTIFIER = 0x4F;
- public static final int APPLICATION_LABEL = 0x50;
- public static final int FILE_REFERENCE = 0x51;
- public static final int COMMAND_TO_PERFORM = 0x52;
- public static final int DISCRETIONARY_DATA = 0x53;
- public static final int OFFSET_DATA_OBJECT = 0x54;
- public static final int TRACK1_APPLICATION = 0x56;
- public static final int TRACK2_APPLICATION = 0x57;
- public static final int TRACK3_APPLICATION = 0x58;
- public static final int CARD_EXPIRATION_DATA = 0x59;
- public static final int PRIMARY_ACCOUNT_NUMBER = 0x5A;// PAN
- public static final int NAME = 0x5B;
- public static final int TAG_LIST = 0x5C;
- public static final int HEADER_LIST = 0x5D;
- public static final int LOGIN_DATA = 0x5E;
- public static final int CARDHOLDER_NAME = 0x20; // 0x5F20;
- public static final int TRACK1_CARD = 0x5F21;
- public static final int TRACK2_CARD = 0x5F22;
- public static final int TRACK3_CARD = 0x5F23;
- public static final int APPLICATION_EXPIRATION_DATE = 0x24; // 0x5F24;
- public static final int APPLICATION_EFFECTIVE_DATE = 0x25; // 0x5F25;
- public static final int CARD_EFFECTIVE_DATE = 0x5F26;
- public static final int INTERCHANGE_CONTROL = 0x5F27;
- public static final int COUNTRY_CODE = 0x5F28;
- public static final int INTERCHANGE_PROFILE = 0x29; // 0x5F29;
- public static final int CURRENCY_CODE = 0x5F2A;
- public static final int DATE_OF_BIRTH = 0x5F2B;
- public static final int CARDHOLDER_NATIONALITY = 0x5F2C;
- public static final int LANGUAGE_PREFERENCES = 0x5F2D;
- public static final int CARDHOLDER_BIOMETRIC_DATA = 0x5F2E;
- public static final int PIN_USAGE_POLICY = 0x5F2F;
- public static final int SERVICE_CODE = 0x5F30;
- public static final int TRANSACTION_COUNTER = 0x5F32;
- public static final int TRANSACTION_DATE = 0x5F33;
- public static final int CARD_SEQUENCE_NUMBER = 0x5F34;
- public static final int SEX = 0x5F35;
- public static final int CURRENCY_EXPONENT = 0x5F36;
- public static final int STATIC_INTERNAL_AUTHENTIFICATION_ONE_STEP = 0x37; // 0x5F37;
- public static final int SIGNATURE = 0x5F37;
- public static final int STATIC_INTERNAL_AUTHENTIFICATION_FIRST_DATA = 0x5F38;
- public static final int STATIC_INTERNAL_AUTHENTIFICATION_SECOND_DATA = 0x5F39;
- public static final int DYNAMIC_INTERNAL_AUTHENTIFICATION = 0x5F3A;
- public static final int DYNAMIC_EXTERNAL_AUTHENTIFICATION = 0x5F3B;
- public static final int DYNAMIC_MUTUAL_AUTHENTIFICATION = 0x5F3C;
- public static final int CARDHOLDER_PORTRAIT_IMAGE = 0x5F40;
- public static final int ELEMENT_LIST = 0x5F41;
- public static final int ADDRESS = 0x5F42;
- public static final int CARDHOLDER_HANDWRITTEN_SIGNATURE = 0x5F43;
- public static final int APPLICATION_IMAGE = 0x5F44;
- public static final int DISPLAY_IMAGE = 0x5F45;
- public static final int TIMER = 0x5F46;
- public static final int MESSAGE_REFERENCE = 0x5F47;
- public static final int CARDHOLDER_PRIVATE_KEY = 0x5F48;
- public static final int CARDHOLDER_PUBLIC_KEY = 0x5F49;
- public static final int CERTIFICATION_AUTHORITY_PUBLIC_KEY = 0x5F4A;
- public static final int DEPRECATED = 0x5F4B;
- public static final int CERTIFICATE_HOLDER_AUTHORIZATION = 0x5F4C;// Not yet defined in iso7816. The allocation is requested
- public static final int INTEGRATED_CIRCUIT_MANUFACTURER_ID = 0x5F4D;
- public static final int CERTIFICATE_CONTENT = 0x5F4E;
- public static final int UNIFORM_RESOURCE_LOCATOR = 0x5F50;
- public static final int ANSWER_TO_RESET = 0x5F51;
- public static final int HISTORICAL_BYTES = 0x5F52;
- public static final int DIGITAL_SIGNATURE = 0x5F3D;
- public static final int APPLICATION_TEMPLATE = 0x61;
- public static final int FCP_TEMPLATE = 0x62;
- public static final int WRAPPER = 0x63;
- public static final int FMD_TEMPLATE = 0x64;
- public static final int CARDHOLDER_RELATIVE_DATA = 0x65;
- public static final int CARD_DATA = 0x66;
- public static final int AUTHENTIFICATION_DATA = 0x67;
- public static final int SPECIAL_USER_REQUIREMENTS = 0x68;
- public static final int LOGIN_TEMPLATE = 0x6A;
- public static final int QUALIFIED_NAME = 0x6B;
- public static final int CARDHOLDER_IMAGE_TEMPLATE = 0x6C;
- public static final int APPLICATION_IMAGE_TEMPLATE = 0x6D;
- public static final int APPLICATION_RELATED_DATA = 0x6E;
- public static final int FCI_TEMPLATE = 0x6F;
- public static final int DISCRETIONARY_DATA_OBJECTS = 0x73;
- public static final int COMPATIBLE_TAG_ALLOCATION_AUTHORITY = 0x78;
- public static final int COEXISTANT_TAG_ALLOCATION_AUTHORITY = 0x79;
- public static final int SECURITY_SUPPORT_TEMPLATE = 0x7A;
- public static final int SECURITY_ENVIRONMENT_TEMPLATE = 0x7B;
- public static final int DYNAMIC_AUTHENTIFICATION_TEMPLATE = 0x7C;
- public static final int SECURE_MESSAGING_TEMPLATE = 0x7D;
- public static final int NON_INTERINDUSTRY_DATA_OBJECT_NESTING_TEMPLATE = 0x7E;
- public static final int DISPLAY_CONTROL = 0x7F20;
- public static final int CARDHOLDER_CERTIFICATE = 0x21; // 0x7F21;
- public static final int CV_CERTIFICATE = 0x7F21;
- public static final int CARDHOLER_REQUIREMENTS_INCLUDED_FEATURES = 0x7F22;
- public static final int CARDHOLER_REQUIREMENTS_EXCLUDED_FEATURES = 0x7F23;
- public static final int BIOMETRIC_DATA_TEMPLATE = 0x7F2E;
- public static final int DIGITAL_SIGNATURE_BLOCK = 0x7F3D;
- public static final int CARDHOLDER_PRIVATE_KEY_TEMPLATE = 0x7F48;
- public static final int CARDHOLDER_PUBLIC_KEY_TEMPLATE = 0x49; // 0x7F49;
- public static final int CERTIFICATE_HOLDER_AUTHORIZATION_TEMPLATE = 0x4C; // 0x7F4C;
- public static final int CERTIFICATE_CONTENT_TEMPLATE = 0x4E; // 0x7F4E;
- public static final int CERTIFICATE_BODY = 0x4E; // 0x7F4E;
- public static final int BIOMETRIC_INFORMATION_TEMPLATE = 0x7F60;
- public static final int BIOMETRIC_INFORMATION_GROUP_TEMPLATE = 0x7F61;
-
- public static int getTag(int encodedTag)
- {
- /*
- int i;
- for (i = 24; i>=0; i-=8) {
- if (((0xFF<<i) & tag) != 0)
- return (((0xFF<<i) & tag) >> i);
- }
- return 0;
- */
- return decodeTag(encodedTag);
- }
-
- public static int getTagNo(int tag)
- {
- int i;
- for (i = 24; i >= 0; i -= 8)
- {
- if (((0xFF << i) & tag) != 0)
- {
- return ((~(0xFF << i)) & tag);
- }
- }
- return 0;
- }
-
- public static int encodeTag(DERApplicationSpecific spec)
- {
- int retValue = BERTags.APPLICATION;
- boolean constructed = spec.isConstructed();
- if (constructed)
- {
- retValue |= BERTags.CONSTRUCTED;
- }
-
- int tag = spec.getApplicationTag();
-
- if (tag > 31)
- {
- retValue |= 0x1F;
- retValue <<= 8;
-
- int currentByte = tag & 0x7F;
- retValue |= currentByte;
- tag >>= 7;
-
- while (tag > 0)
- {
- retValue |= 0x80;
- retValue <<= 8;
-
- currentByte = tag & 0x7F;
- tag >>= 7;
- }
- }
- else
- {
- retValue |= tag;
- }
-
- return retValue;
- }
-
- public static int decodeTag(int tag)
- {
- int retValue = 0;
- boolean multiBytes = false;
- for (int i = 24; i >= 0; i -= 8)
- {
- int currentByte = tag >> i & 0xFF;
- if (currentByte == 0)
- {
- continue;
- }
-
- if (multiBytes)
- {
- retValue <<= 7;
- retValue |= currentByte & 0x7F;
- }
- else if ((currentByte & 0x1F) == 0x1F)
- {
- multiBytes = true;
- }
- else
- {
- return currentByte & 0x1F; // higher order bit are for DER.Constructed and type
- }
- }
- return retValue;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/eac/ECDSAPublicKey.java b/core/src/main/java/org/bouncycastle/asn1/eac/ECDSAPublicKey.java
deleted file mode 100644
index 077807f2..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/eac/ECDSAPublicKey.java
+++ /dev/null
@@ -1,340 +0,0 @@
-package org.bouncycastle.asn1.eac;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * an Iso7816ECDSAPublicKeyStructure structure.
- * <pre>
- * Certificate Holder Authorization ::= SEQUENCE {
- * ASN1TaggedObject primeModulusP; // OPTIONAL
- * ASN1TaggedObject firstCoefA; // OPTIONAL
- * ASN1TaggedObject secondCoefB; // OPTIONAL
- * ASN1TaggedObject basePointG; // OPTIONAL
- * ASN1TaggedObject orderOfBasePointR; // OPTIONAL
- * ASN1TaggedObject publicPointY; //REQUIRED
- * ASN1TaggedObject cofactorF; // OPTIONAL
- * }
- * </pre>
- */
-public class ECDSAPublicKey
- extends PublicKeyDataObject
-{
- private ASN1ObjectIdentifier usage;
- private BigInteger primeModulusP; // OPTIONAL
- private BigInteger firstCoefA; // OPTIONAL
- private BigInteger secondCoefB; // OPTIONAL
- private byte[] basePointG; // OPTIONAL
- private BigInteger orderOfBasePointR; // OPTIONAL
- private byte[] publicPointY; //REQUIRED
- private BigInteger cofactorF; // OPTIONAL
- private int options;
- private static final int P = 0x01;
- private static final int A = 0x02;
- private static final int B = 0x04;
- private static final int G = 0x08;
- private static final int R = 0x10;
- private static final int Y = 0x20;
- private static final int F = 0x40;
-
- ECDSAPublicKey(ASN1Sequence seq)
- throws IllegalArgumentException
- {
- Enumeration en = seq.getObjects();
-
- this.usage = ASN1ObjectIdentifier.getInstance(en.nextElement());
-
- options = 0;
- while (en.hasMoreElements())
- {
- Object obj = en.nextElement();
-
- if (obj instanceof ASN1TaggedObject)
- {
- ASN1TaggedObject to = (ASN1TaggedObject)obj;
- switch (to.getTagNo())
- {
- case 0x1:
- setPrimeModulusP(UnsignedInteger.getInstance(to).getValue());
- break;
- case 0x2:
- setFirstCoefA(UnsignedInteger.getInstance(to).getValue());
- break;
- case 0x3:
- setSecondCoefB(UnsignedInteger.getInstance(to).getValue());
- break;
- case 0x4:
- setBasePointG(ASN1OctetString.getInstance(to, false));
- break;
- case 0x5:
- setOrderOfBasePointR(UnsignedInteger.getInstance(to).getValue());
- break;
- case 0x6:
- setPublicPointY(ASN1OctetString.getInstance(to, false));
- break;
- case 0x7:
- setCofactorF(UnsignedInteger.getInstance(to).getValue());
- break;
- default:
- options = 0;
- throw new IllegalArgumentException("Unknown Object Identifier!");
- }
- }
- else
- {
- throw new IllegalArgumentException("Unknown Object Identifier!");
- }
- }
- if (options != 0x20 && options != 0x7F)
- {
- throw new IllegalArgumentException("All options must be either present or absent!");
- }
- }
-
- public ECDSAPublicKey(ASN1ObjectIdentifier usage, byte[] ppY)
- throws IllegalArgumentException
- {
- this.usage = usage;
- setPublicPointY(new DEROctetString(ppY));
- }
-
- public ECDSAPublicKey(ASN1ObjectIdentifier usage, BigInteger p, BigInteger a, BigInteger b, byte[] basePoint, BigInteger order, byte[] publicPoint, int cofactor)
- {
- this.usage = usage;
- setPrimeModulusP(p);
- setFirstCoefA(a);
- setSecondCoefB(b);
- setBasePointG(new DEROctetString(basePoint));
- setOrderOfBasePointR(order);
- setPublicPointY(new DEROctetString(publicPoint));
- setCofactorF(BigInteger.valueOf(cofactor));
- }
-
- public ASN1ObjectIdentifier getUsage()
- {
- return usage;
- }
-
- public byte[] getBasePointG()
- {
- if ((options & G) != 0)
- {
- return basePointG;
- }
- else
- {
- return null;
- }
- }
-
- private void setBasePointG(ASN1OctetString basePointG)
- throws IllegalArgumentException
- {
- if ((options & G) == 0)
- {
- options |= G;
- this.basePointG = basePointG.getOctets();
- }
- else
- {
- throw new IllegalArgumentException("Base Point G already set");
- }
- }
-
- public BigInteger getCofactorF()
- {
- if ((options & F) != 0)
- {
- return cofactorF;
- }
- else
- {
- return null;
- }
- }
-
- private void setCofactorF(BigInteger cofactorF)
- throws IllegalArgumentException
- {
- if ((options & F) == 0)
- {
- options |= F;
- this.cofactorF = cofactorF;
- }
- else
- {
- throw new IllegalArgumentException("Cofactor F already set");
- }
- }
-
- public BigInteger getFirstCoefA()
- {
- if ((options & A) != 0)
- {
- return firstCoefA;
- }
- else
- {
- return null;
- }
- }
-
- private void setFirstCoefA(BigInteger firstCoefA)
- throws IllegalArgumentException
- {
- if ((options & A) == 0)
- {
- options |= A;
- this.firstCoefA = firstCoefA;
- }
- else
- {
- throw new IllegalArgumentException("First Coef A already set");
- }
- }
-
- public BigInteger getOrderOfBasePointR()
- {
- if ((options & R) != 0)
- {
- return orderOfBasePointR;
- }
- else
- {
- return null;
- }
- }
-
- private void setOrderOfBasePointR(BigInteger orderOfBasePointR)
- throws IllegalArgumentException
- {
- if ((options & R) == 0)
- {
- options |= R;
- this.orderOfBasePointR = orderOfBasePointR;
- }
- else
- {
- throw new IllegalArgumentException("Order of base point R already set");
- }
- }
-
- public BigInteger getPrimeModulusP()
- {
- if ((options & P) != 0)
- {
- return primeModulusP;
- }
- else
- {
- return null;
- }
- }
-
- private void setPrimeModulusP(BigInteger primeModulusP)
- {
- if ((options & P) == 0)
- {
- options |= P;
- this.primeModulusP = primeModulusP;
- }
- else
- {
- throw new IllegalArgumentException("Prime Modulus P already set");
- }
- }
-
- public byte[] getPublicPointY()
- {
- if ((options & Y) != 0)
- {
- return publicPointY;
- }
- else
- {
- return null;
- }
- }
-
- private void setPublicPointY(ASN1OctetString publicPointY)
- throws IllegalArgumentException
- {
- if ((options & Y) == 0)
- {
- options |= Y;
- this.publicPointY = publicPointY.getOctets();
- }
- else
- {
- throw new IllegalArgumentException("Public Point Y already set");
- }
- }
-
- public BigInteger getSecondCoefB()
- {
- if ((options & B) != 0)
- {
- return secondCoefB;
- }
- else
- {
- return null;
- }
- }
-
- private void setSecondCoefB(BigInteger secondCoefB)
- throws IllegalArgumentException
- {
- if ((options & B) == 0)
- {
- options |= B;
- this.secondCoefB = secondCoefB;
- }
- else
- {
- throw new IllegalArgumentException("Second Coef B already set");
- }
- }
-
- public boolean hasParameters()
- {
- return primeModulusP != null;
- }
-
- public ASN1EncodableVector getASN1EncodableVector(ASN1ObjectIdentifier oid, boolean publicPointOnly)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- v.add(oid);
-
- if (!publicPointOnly)
- {
- v.add(new UnsignedInteger(0x01, getPrimeModulusP()));
- v.add(new UnsignedInteger(0x02, getFirstCoefA()));
- v.add(new UnsignedInteger(0x03, getSecondCoefB()));
- v.add(new DERTaggedObject(false, 0x04, new DEROctetString(getBasePointG())));
- v.add(new UnsignedInteger(0x05, getOrderOfBasePointR()));
- }
- v.add(new DERTaggedObject(false, 0x06, new DEROctetString(getPublicPointY())));
- if (!publicPointOnly)
- {
- v.add(new UnsignedInteger(0x07, getCofactorF()));
- }
-
- return v;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return new DERSequence(getASN1EncodableVector(usage, false));
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/eac/Flags.java b/core/src/main/java/org/bouncycastle/asn1/eac/Flags.java
deleted file mode 100644
index 89d4e9f9..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/eac/Flags.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.bouncycastle.asn1.eac;
-
-import java.util.Enumeration;
-import java.util.Hashtable;
-
-
-public class Flags
-{
-
- int value = 0;
-
- public Flags()
- {
-
- }
-
- public Flags(int v)
- {
- value = v;
- }
-
- public void set(int flag)
- {
- value |= flag;
- }
-
- public boolean isSet(int flag)
- {
- return (value & flag) != 0;
- }
-
- public int getFlags()
- {
- return value;
- }
-
- /* Java 1.5
- String decode(Map<Integer, String> decodeMap)
- {
- StringJoiner joiner = new StringJoiner(" ");
- for (int i : decodeMap.keySet())
- {
- if (isSet(i))
- joiner.add(decodeMap.get(i));
- }
- return joiner.toString();
- }
- */
-
- String decode(Hashtable decodeMap)
- {
- StringJoiner joiner = new StringJoiner(" ");
- Enumeration e = decodeMap.keys();
- while (e.hasMoreElements())
- {
- Integer i = (Integer)e.nextElement();
- if (isSet(i.intValue()))
- {
- joiner.add((String)decodeMap.get(i));
- }
- }
- return joiner.toString();
- }
-
- private class StringJoiner
- {
-
- String mSeparator;
- boolean First = true;
- StringBuffer b = new StringBuffer();
-
- public StringJoiner(String separator)
- {
- mSeparator = separator;
- }
-
- public void add(String str)
- {
- if (First)
- {
- First = false;
- }
- else
- {
- b.append(mSeparator);
- }
-
- b.append(str);
- }
-
- public String toString()
- {
- return b.toString();
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/eac/PackedDate.java b/core/src/main/java/org/bouncycastle/asn1/eac/PackedDate.java
deleted file mode 100644
index e19c96f1..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/eac/PackedDate.java
+++ /dev/null
@@ -1,124 +0,0 @@
-package org.bouncycastle.asn1.eac;
-
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-import java.util.SimpleTimeZone;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * EAC encoding date object
- */
-public class PackedDate
-{
- private byte[] time;
-
- public PackedDate(
- String time)
- {
- this.time = convert(time);
- }
-
- /**
- * Base constructor from a java.util.date object.
- *
- * @param time a date object representing the time of interest.
- */
- public PackedDate(
- Date time)
- {
- SimpleDateFormat dateF = new SimpleDateFormat("yyMMdd'Z'");
-
- dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
-
- this.time = convert(dateF.format(time));
- }
-
- /**
- * Base constructor from a java.util.date object. You may need to use this constructor if the default locale
- * doesn't use a Gregorian calender so that the PackedDate produced is compatible with other ASN.1 implementations.
- *
- * @param time a date object representing the time of interest.
- * @param locale an appropriate Locale for producing an ASN.1 GeneralizedTime value.
- */
- public PackedDate(
- Date time,
- Locale locale)
- {
- SimpleDateFormat dateF = new SimpleDateFormat("yyMMdd'Z'", locale);
-
- dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
-
- this.time = convert(dateF.format(time));
- }
-
- private byte[] convert(String sTime)
- {
- char[] digs = sTime.toCharArray();
- byte[] date = new byte[6];
-
- for (int i = 0; i != 6; i++)
- {
- date[i] = (byte)(digs[i] - '0');
- }
-
- return date;
- }
-
- PackedDate(
- byte[] bytes)
- {
- this.time = bytes;
- }
-
- /**
- * return the time as a date based on whatever a 2 digit year will return. For
- * standardised processing use getAdjustedDate().
- *
- * @return the resulting date
- * @exception java.text.ParseException if the date string cannot be parsed.
- */
- public Date getDate()
- throws ParseException
- {
- SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMdd");
-
- return dateF.parse("20" + toString());
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(time);
- }
-
- public boolean equals(Object o)
- {
- if (!(o instanceof PackedDate))
- {
- return false;
- }
-
- PackedDate other = (PackedDate)o;
-
- return Arrays.areEqual(time, other.time);
- }
-
- public String toString()
- {
- char[] dateC = new char[time.length];
-
- for (int i = 0; i != dateC.length; i++)
- {
- dateC[i] = (char)((time[i] & 0xff) + '0');
- }
-
- return new String(dateC);
- }
-
- public byte[] getEncoding()
- {
- return time;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/eac/PublicKeyDataObject.java b/core/src/main/java/org/bouncycastle/asn1/eac/PublicKeyDataObject.java
deleted file mode 100644
index 40ad3bb1..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/eac/PublicKeyDataObject.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.bouncycastle.asn1.eac;
-
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Sequence;
-
-public abstract class PublicKeyDataObject
- extends ASN1Object
-{
- public static PublicKeyDataObject getInstance(Object obj)
- {
- if (obj instanceof PublicKeyDataObject)
- {
- return (PublicKeyDataObject)obj;
- }
- if (obj != null)
- {
- ASN1Sequence seq = ASN1Sequence.getInstance(obj);
- ASN1ObjectIdentifier usage = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
-
- if (usage.on(EACObjectIdentifiers.id_TA_ECDSA))
- {
- return new ECDSAPublicKey(seq);
- }
- else
- {
- return new RSAPublicKey(seq);
- }
- }
-
- return null;
- }
-
- public abstract ASN1ObjectIdentifier getUsage();
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/eac/RSAPublicKey.java b/core/src/main/java/org/bouncycastle/asn1/eac/RSAPublicKey.java
deleted file mode 100644
index 3e1727e4..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/eac/RSAPublicKey.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package org.bouncycastle.asn1.eac;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-
-/**
- * an Iso7816RSAPublicKeyStructure structure.
- * <pre>
- * Certificate Holder Authorization ::= SEQUENCE {
- * // modulus should be at least 1024bit and a multiple of 512.
- * DERTaggedObject modulus,
- * // access rights exponent
- * DERTaggedObject accessRights,
- * }
- * </pre>
- */
-public class RSAPublicKey
- extends PublicKeyDataObject
-{
- private ASN1ObjectIdentifier usage;
- private BigInteger modulus;
- private BigInteger exponent;
- private int valid = 0;
- private static int modulusValid = 0x01;
- private static int exponentValid = 0x02;
-
- RSAPublicKey(ASN1Sequence seq)
- {
- Enumeration en = seq.getObjects();
-
- this.usage = ASN1ObjectIdentifier.getInstance(en.nextElement());
-
- while (en.hasMoreElements())
- {
- UnsignedInteger val = UnsignedInteger.getInstance(en.nextElement());
-
- switch (val.getTagNo())
- {
- case 0x1:
- setModulus(val);
- break;
- case 0x2:
- setExponent(val);
- break;
- default:
- throw new IllegalArgumentException("Unknown DERTaggedObject :" + val.getTagNo() + "-> not an Iso7816RSAPublicKeyStructure");
- }
- }
- if (valid != 0x3)
- {
- throw new IllegalArgumentException("missing argument -> not an Iso7816RSAPublicKeyStructure");
- }
- }
-
- public RSAPublicKey(ASN1ObjectIdentifier usage, BigInteger modulus, BigInteger exponent)
- {
- this.usage = usage;
- this.modulus = modulus;
- this.exponent = exponent;
- }
-
- public ASN1ObjectIdentifier getUsage()
- {
- return usage;
- }
-
- public BigInteger getModulus()
- {
- return modulus;
- }
-
- public BigInteger getPublicExponent()
- {
- return exponent;
- }
-
- private void setModulus(UnsignedInteger modulus)
- {
- if ((valid & modulusValid) == 0)
- {
- valid |= modulusValid;
- this.modulus = modulus.getValue();
- }
- else
- {
- throw new IllegalArgumentException("Modulus already set");
- }
- }
-
- private void setExponent(UnsignedInteger exponent)
- {
- if ((valid & exponentValid) == 0)
- {
- valid |= exponentValid;
- this.exponent = exponent.getValue();
- }
- else
- {
- throw new IllegalArgumentException("Exponent already set");
- }
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(usage);
- v.add(new UnsignedInteger(0x01, getModulus()));
- v.add(new UnsignedInteger(0x02, getPublicExponent()));
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/eac/UnsignedInteger.java b/core/src/main/java/org/bouncycastle/asn1/eac/UnsignedInteger.java
deleted file mode 100644
index 64a91422..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/eac/UnsignedInteger.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package org.bouncycastle.asn1.eac;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-public class UnsignedInteger
- extends ASN1Object
-{
- private int tagNo;
- private BigInteger value;
-
- public UnsignedInteger(int tagNo, BigInteger value)
- {
- this.tagNo = tagNo;
- this.value = value;
- }
-
- private UnsignedInteger(ASN1TaggedObject obj)
- {
- this.tagNo = obj.getTagNo();
- this.value = new BigInteger(1, ASN1OctetString.getInstance(obj, false).getOctets());
- }
-
- public static UnsignedInteger getInstance(Object obj)
- {
- if (obj instanceof UnsignedInteger)
- {
- return (UnsignedInteger)obj;
- }
- if (obj != null)
- {
- return new UnsignedInteger(ASN1TaggedObject.getInstance(obj));
- }
-
- return null;
- }
-
- private byte[] convertValue()
- {
- byte[] v = value.toByteArray();
-
- if (v[0] == 0)
- {
- byte[] tmp = new byte[v.length - 1];
-
- System.arraycopy(v, 1, tmp, 0, tmp.length);
-
- return tmp;
- }
-
- return v;
- }
-
- public int getTagNo()
- {
- return tagNo;
- }
-
- public BigInteger getValue()
- {
- return value;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return new DERTaggedObject(false, tagNo, new DEROctetString(convertValue()));
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/CommitmentTypeIdentifier.java b/core/src/main/java/org/bouncycastle/asn1/esf/CommitmentTypeIdentifier.java
deleted file mode 100644
index be52e45a..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/CommitmentTypeIdentifier.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-
-public interface CommitmentTypeIdentifier
-{
- public static final ASN1ObjectIdentifier proofOfOrigin = PKCSObjectIdentifiers.id_cti_ets_proofOfOrigin;
- public static final ASN1ObjectIdentifier proofOfReceipt = PKCSObjectIdentifiers.id_cti_ets_proofOfReceipt;
- public static final ASN1ObjectIdentifier proofOfDelivery = PKCSObjectIdentifiers.id_cti_ets_proofOfDelivery;
- public static final ASN1ObjectIdentifier proofOfSender = PKCSObjectIdentifiers.id_cti_ets_proofOfSender;
- public static final ASN1ObjectIdentifier proofOfApproval = PKCSObjectIdentifiers.id_cti_ets_proofOfApproval;
- public static final ASN1ObjectIdentifier proofOfCreation = PKCSObjectIdentifiers.id_cti_ets_proofOfCreation;
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/CommitmentTypeIndication.java b/core/src/main/java/org/bouncycastle/asn1/esf/CommitmentTypeIndication.java
deleted file mode 100644
index 9e2533d9..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/CommitmentTypeIndication.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-public class CommitmentTypeIndication
- extends ASN1Object
-{
- private ASN1ObjectIdentifier commitmentTypeId;
- private ASN1Sequence commitmentTypeQualifier;
-
- private CommitmentTypeIndication(
- ASN1Sequence seq)
- {
- commitmentTypeId = (ASN1ObjectIdentifier)seq.getObjectAt(0);
-
- if (seq.size() > 1)
- {
- commitmentTypeQualifier = (ASN1Sequence)seq.getObjectAt(1);
- }
- }
-
- public CommitmentTypeIndication(
- ASN1ObjectIdentifier commitmentTypeId)
- {
- this.commitmentTypeId = commitmentTypeId;
- }
-
- public CommitmentTypeIndication(
- ASN1ObjectIdentifier commitmentTypeId,
- ASN1Sequence commitmentTypeQualifier)
- {
- this.commitmentTypeId = commitmentTypeId;
- this.commitmentTypeQualifier = commitmentTypeQualifier;
- }
-
- public static CommitmentTypeIndication getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof CommitmentTypeIndication)
- {
- return (CommitmentTypeIndication)obj;
- }
-
- return new CommitmentTypeIndication(ASN1Sequence.getInstance(obj));
- }
-
- public ASN1ObjectIdentifier getCommitmentTypeId()
- {
- return commitmentTypeId;
- }
-
- public ASN1Sequence getCommitmentTypeQualifier()
- {
- return commitmentTypeQualifier;
- }
-
- /**
- * <pre>
- * CommitmentTypeIndication ::= SEQUENCE {
- * commitmentTypeId CommitmentTypeIdentifier,
- * commitmentTypeQualifier SEQUENCE SIZE (1..MAX) OF
- * CommitmentTypeQualifier OPTIONAL }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(commitmentTypeId);
-
- if (commitmentTypeQualifier != null)
- {
- v.add(commitmentTypeQualifier);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/CommitmentTypeQualifier.java b/core/src/main/java/org/bouncycastle/asn1/esf/CommitmentTypeQualifier.java
deleted file mode 100644
index 2cbba924..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/CommitmentTypeQualifier.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * Commitment type qualifiers, used in the Commitment-Type-Indication attribute (RFC3126).
- *
- * <pre>
- * CommitmentTypeQualifier ::= SEQUENCE {
- * commitmentTypeIdentifier CommitmentTypeIdentifier,
- * qualifier ANY DEFINED BY commitmentTypeIdentifier OPTIONAL }
- * </pre>
- */
-public class CommitmentTypeQualifier
- extends ASN1Object
-{
- private ASN1ObjectIdentifier commitmentTypeIdentifier;
- private ASN1Encodable qualifier;
-
- /**
- * Creates a new <code>CommitmentTypeQualifier</code> instance.
- *
- * @param commitmentTypeIdentifier a <code>CommitmentTypeIdentifier</code> value
- */
- public CommitmentTypeQualifier(
- ASN1ObjectIdentifier commitmentTypeIdentifier)
- {
- this(commitmentTypeIdentifier, null);
- }
-
- /**
- * Creates a new <code>CommitmentTypeQualifier</code> instance.
- *
- * @param commitmentTypeIdentifier a <code>CommitmentTypeIdentifier</code> value
- * @param qualifier the qualifier, defined by the above field.
- */
- public CommitmentTypeQualifier(
- ASN1ObjectIdentifier commitmentTypeIdentifier,
- ASN1Encodable qualifier)
- {
- this.commitmentTypeIdentifier = commitmentTypeIdentifier;
- this.qualifier = qualifier;
- }
-
- /**
- * Creates a new <code>CommitmentTypeQualifier</code> instance.
- *
- * @param as <code>CommitmentTypeQualifier</code> structure
- * encoded as an ASN1Sequence.
- */
- private CommitmentTypeQualifier(
- ASN1Sequence as)
- {
- commitmentTypeIdentifier = (ASN1ObjectIdentifier)as.getObjectAt(0);
-
- if (as.size() > 1)
- {
- qualifier = as.getObjectAt(1);
- }
- }
-
- public static CommitmentTypeQualifier getInstance(Object as)
- {
- if (as instanceof CommitmentTypeQualifier)
- {
- return (CommitmentTypeQualifier)as;
- }
- else if (as != null)
- {
- return new CommitmentTypeQualifier(ASN1Sequence.getInstance(as));
- }
-
- return null;
- }
-
- public ASN1ObjectIdentifier getCommitmentTypeIdentifier()
- {
- return commitmentTypeIdentifier;
- }
-
- public ASN1Encodable getQualifier()
- {
- return qualifier;
- }
-
- /**
- * Returns a DER-encodable representation of this instance.
- *
- * @return a <code>ASN1Primitive</code> value
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector dev = new ASN1EncodableVector();
- dev.add(commitmentTypeIdentifier);
- if (qualifier != null)
- {
- dev.add(qualifier);
- }
-
- return new DERSequence(dev);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/CompleteRevocationRefs.java b/core/src/main/java/org/bouncycastle/asn1/esf/CompleteRevocationRefs.java
deleted file mode 100644
index 4e81f293..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/CompleteRevocationRefs.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * <pre>
- * CompleteRevocationRefs ::= SEQUENCE OF CrlOcspRef
- * </pre>
- */
-public class CompleteRevocationRefs
- extends ASN1Object
-{
-
- private ASN1Sequence crlOcspRefs;
-
- public static CompleteRevocationRefs getInstance(Object obj)
- {
- if (obj instanceof CompleteRevocationRefs)
- {
- return (CompleteRevocationRefs)obj;
- }
- else if (obj != null)
- {
- return new CompleteRevocationRefs(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private CompleteRevocationRefs(ASN1Sequence seq)
- {
- Enumeration seqEnum = seq.getObjects();
- while (seqEnum.hasMoreElements())
- {
- CrlOcspRef.getInstance(seqEnum.nextElement());
- }
- this.crlOcspRefs = seq;
- }
-
- public CompleteRevocationRefs(CrlOcspRef[] crlOcspRefs)
- {
- this.crlOcspRefs = new DERSequence(crlOcspRefs);
- }
-
- public CrlOcspRef[] getCrlOcspRefs()
- {
- CrlOcspRef[] result = new CrlOcspRef[this.crlOcspRefs.size()];
- for (int idx = 0; idx < result.length; idx++)
- {
- result[idx] = CrlOcspRef.getInstance(this.crlOcspRefs
- .getObjectAt(idx));
- }
- return result;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return this.crlOcspRefs;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/CrlIdentifier.java b/core/src/main/java/org/bouncycastle/asn1/esf/CrlIdentifier.java
deleted file mode 100644
index 68004185..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/CrlIdentifier.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-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.ASN1UTCTime;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x500.X500Name;
-
-/**
- * <pre>
- * CrlIdentifier ::= SEQUENCE
- * {
- * crlissuer Name,
- * crlIssuedTime UTCTime,
- * crlNumber INTEGER OPTIONAL
- * }
- * </pre>
- */
-public class CrlIdentifier
- extends ASN1Object
-{
- private X500Name crlIssuer;
- private ASN1UTCTime crlIssuedTime;
- private ASN1Integer crlNumber;
-
- public static CrlIdentifier getInstance(Object obj)
- {
- if (obj instanceof CrlIdentifier)
- {
- return (CrlIdentifier)obj;
- }
- else if (obj != null)
- {
- return new CrlIdentifier(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private CrlIdentifier(ASN1Sequence seq)
- {
- if (seq.size() < 2 || seq.size() > 3)
- {
- throw new IllegalArgumentException();
- }
- this.crlIssuer = X500Name.getInstance(seq.getObjectAt(0));
- this.crlIssuedTime = ASN1UTCTime.getInstance(seq.getObjectAt(1));
- if (seq.size() > 2)
- {
- this.crlNumber = ASN1Integer.getInstance(seq.getObjectAt(2));
- }
- }
-
- public CrlIdentifier(X500Name crlIssuer, ASN1UTCTime crlIssuedTime)
- {
- this(crlIssuer, crlIssuedTime, null);
- }
-
- public CrlIdentifier(X500Name crlIssuer, ASN1UTCTime crlIssuedTime,
- BigInteger crlNumber)
- {
- this.crlIssuer = crlIssuer;
- this.crlIssuedTime = crlIssuedTime;
- if (null != crlNumber)
- {
- this.crlNumber = new ASN1Integer(crlNumber);
- }
- }
-
- public X500Name getCrlIssuer()
- {
- return this.crlIssuer;
- }
-
- public ASN1UTCTime getCrlIssuedTime()
- {
- return this.crlIssuedTime;
- }
-
- public BigInteger getCrlNumber()
- {
- if (null == this.crlNumber)
- {
- return null;
- }
- return this.crlNumber.getValue();
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- v.add(this.crlIssuer.toASN1Primitive());
- v.add(this.crlIssuedTime);
- if (null != this.crlNumber)
- {
- v.add(this.crlNumber);
- }
- return new DERSequence(v);
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/CrlListID.java b/core/src/main/java/org/bouncycastle/asn1/esf/CrlListID.java
deleted file mode 100644
index c0cb333c..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/CrlListID.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * <pre>
- * CRLListID ::= SEQUENCE {
- * crls SEQUENCE OF CrlValidatedID }
- * </pre>
- */
-public class CrlListID
- extends ASN1Object
-{
-
- private ASN1Sequence crls;
-
- public static CrlListID getInstance(Object obj)
- {
- if (obj instanceof CrlListID)
- {
- return (CrlListID)obj;
- }
- else if (obj != null)
- {
- return new CrlListID(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private CrlListID(ASN1Sequence seq)
- {
- this.crls = (ASN1Sequence)seq.getObjectAt(0);
- Enumeration e = this.crls.getObjects();
- while (e.hasMoreElements())
- {
- CrlValidatedID.getInstance(e.nextElement());
- }
- }
-
- public CrlListID(CrlValidatedID[] crls)
- {
- this.crls = new DERSequence(crls);
- }
-
- public CrlValidatedID[] getCrls()
- {
- CrlValidatedID[] result = new CrlValidatedID[this.crls.size()];
- for (int idx = 0; idx < result.length; idx++)
- {
- result[idx] = CrlValidatedID
- .getInstance(this.crls.getObjectAt(idx));
- }
- return result;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return new DERSequence(this.crls);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/CrlOcspRef.java b/core/src/main/java/org/bouncycastle/asn1/esf/CrlOcspRef.java
deleted file mode 100644
index 39539f34..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/CrlOcspRef.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * <pre>
- * CrlOcspRef ::= SEQUENCE {
- * crlids [0] CRLListID OPTIONAL,
- * ocspids [1] OcspListID OPTIONAL,
- * otherRev [2] OtherRevRefs OPTIONAL
- * }
- * </pre>
- */
-public class CrlOcspRef
- extends ASN1Object
-{
-
- private CrlListID crlids;
- private OcspListID ocspids;
- private OtherRevRefs otherRev;
-
- public static CrlOcspRef getInstance(Object obj)
- {
- if (obj instanceof CrlOcspRef)
- {
- return (CrlOcspRef)obj;
- }
- else if (obj != null)
- {
- return new CrlOcspRef(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private CrlOcspRef(ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
- while (e.hasMoreElements())
- {
- DERTaggedObject o = (DERTaggedObject)e.nextElement();
- switch (o.getTagNo())
- {
- case 0:
- this.crlids = CrlListID.getInstance(o.getObject());
- break;
- case 1:
- this.ocspids = OcspListID.getInstance(o.getObject());
- break;
- case 2:
- this.otherRev = OtherRevRefs.getInstance(o.getObject());
- break;
- default:
- throw new IllegalArgumentException("illegal tag");
- }
- }
- }
-
- public CrlOcspRef(CrlListID crlids, OcspListID ocspids,
- OtherRevRefs otherRev)
- {
- this.crlids = crlids;
- this.ocspids = ocspids;
- this.otherRev = otherRev;
- }
-
- public CrlListID getCrlids()
- {
- return this.crlids;
- }
-
- public OcspListID getOcspids()
- {
- return this.ocspids;
- }
-
- public OtherRevRefs getOtherRev()
- {
- return this.otherRev;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- if (null != this.crlids)
- {
- v.add(new DERTaggedObject(true, 0, this.crlids.toASN1Primitive()));
- }
- if (null != this.ocspids)
- {
- v.add(new DERTaggedObject(true, 1, this.ocspids.toASN1Primitive()));
- }
- if (null != this.otherRev)
- {
- v.add(new DERTaggedObject(true, 2, this.otherRev.toASN1Primitive()));
- }
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/CrlValidatedID.java b/core/src/main/java/org/bouncycastle/asn1/esf/CrlValidatedID.java
deleted file mode 100644
index b378aeaf..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/CrlValidatedID.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * <pre>
- * CrlValidatedID ::= SEQUENCE {
- * crlHash OtherHash,
- * crlIdentifier CrlIdentifier OPTIONAL }
- * </pre>
- */
-public class CrlValidatedID
- extends ASN1Object
-{
-
- private OtherHash crlHash;
- private CrlIdentifier crlIdentifier;
-
- public static CrlValidatedID getInstance(Object obj)
- {
- if (obj instanceof CrlValidatedID)
- {
- return (CrlValidatedID)obj;
- }
- else if (obj != null)
- {
- return new CrlValidatedID(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private CrlValidatedID(ASN1Sequence seq)
- {
- if (seq.size() < 1 || seq.size() > 2)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
- this.crlHash = OtherHash.getInstance(seq.getObjectAt(0));
- if (seq.size() > 1)
- {
- this.crlIdentifier = CrlIdentifier.getInstance(seq.getObjectAt(1));
- }
- }
-
- public CrlValidatedID(OtherHash crlHash)
- {
- this(crlHash, null);
- }
-
- public CrlValidatedID(OtherHash crlHash, CrlIdentifier crlIdentifier)
- {
- this.crlHash = crlHash;
- this.crlIdentifier = crlIdentifier;
- }
-
- public OtherHash getCrlHash()
- {
- return this.crlHash;
- }
-
- public CrlIdentifier getCrlIdentifier()
- {
- return this.crlIdentifier;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- v.add(this.crlHash.toASN1Primitive());
- if (null != this.crlIdentifier)
- {
- v.add(this.crlIdentifier.toASN1Primitive());
- }
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/ESFAttributes.java b/core/src/main/java/org/bouncycastle/asn1/esf/ESFAttributes.java
deleted file mode 100644
index ebdc5ead..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/ESFAttributes.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-
-public interface ESFAttributes
-{
- public static final ASN1ObjectIdentifier sigPolicyId = PKCSObjectIdentifiers.id_aa_ets_sigPolicyId;
- public static final ASN1ObjectIdentifier commitmentType = PKCSObjectIdentifiers.id_aa_ets_commitmentType;
- public static final ASN1ObjectIdentifier signerLocation = PKCSObjectIdentifiers.id_aa_ets_signerLocation;
- public static final ASN1ObjectIdentifier signerAttr = PKCSObjectIdentifiers.id_aa_ets_signerAttr;
- public static final ASN1ObjectIdentifier otherSigCert = PKCSObjectIdentifiers.id_aa_ets_otherSigCert;
- public static final ASN1ObjectIdentifier contentTimestamp = PKCSObjectIdentifiers.id_aa_ets_contentTimestamp;
- public static final ASN1ObjectIdentifier certificateRefs = PKCSObjectIdentifiers.id_aa_ets_certificateRefs;
- public static final ASN1ObjectIdentifier revocationRefs = PKCSObjectIdentifiers.id_aa_ets_revocationRefs;
- public static final ASN1ObjectIdentifier certValues = PKCSObjectIdentifiers.id_aa_ets_certValues;
- public static final ASN1ObjectIdentifier revocationValues = PKCSObjectIdentifiers.id_aa_ets_revocationValues;
- public static final ASN1ObjectIdentifier escTimeStamp = PKCSObjectIdentifiers.id_aa_ets_escTimeStamp;
- public static final ASN1ObjectIdentifier certCRLTimestamp = PKCSObjectIdentifiers.id_aa_ets_certCRLTimestamp;
- public static final ASN1ObjectIdentifier archiveTimestamp = PKCSObjectIdentifiers.id_aa_ets_archiveTimestamp;
- public static final ASN1ObjectIdentifier archiveTimestampV2 = PKCSObjectIdentifiers.id_aa.branch("48");
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/OcspIdentifier.java b/core/src/main/java/org/bouncycastle/asn1/esf/OcspIdentifier.java
deleted file mode 100644
index a3c41d47..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/OcspIdentifier.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.ocsp.ResponderID;
-
-/**
- * <pre>
- * OcspIdentifier ::= SEQUENCE {
- * ocspResponderID ResponderID, -- As in OCSP response data
- * producedAt GeneralizedTime -- As in OCSP response data
- * }
- * </pre>
- */
-public class OcspIdentifier
- extends ASN1Object
-{
- private ResponderID ocspResponderID;
- private ASN1GeneralizedTime producedAt;
-
- public static OcspIdentifier getInstance(Object obj)
- {
- if (obj instanceof OcspIdentifier)
- {
- return (OcspIdentifier)obj;
- }
- else if (obj != null)
- {
- return new OcspIdentifier(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private OcspIdentifier(ASN1Sequence seq)
- {
- if (seq.size() != 2)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
- this.ocspResponderID = ResponderID.getInstance(seq.getObjectAt(0));
- this.producedAt = (ASN1GeneralizedTime)seq.getObjectAt(1);
- }
-
- public OcspIdentifier(ResponderID ocspResponderID, ASN1GeneralizedTime producedAt)
- {
- this.ocspResponderID = ocspResponderID;
- this.producedAt = producedAt;
- }
-
- public ResponderID getOcspResponderID()
- {
- return this.ocspResponderID;
- }
-
- public ASN1GeneralizedTime getProducedAt()
- {
- return this.producedAt;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- v.add(this.ocspResponderID);
- v.add(this.producedAt);
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/OcspListID.java b/core/src/main/java/org/bouncycastle/asn1/esf/OcspListID.java
deleted file mode 100644
index 349136f1..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/OcspListID.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * <pre>
- * OcspListID ::= SEQUENCE {
- * ocspResponses SEQUENCE OF OcspResponsesID
- * }
- * </pre>
- */
-public class OcspListID
- extends ASN1Object
-{
- private ASN1Sequence ocspResponses;
-
- public static OcspListID getInstance(Object obj)
- {
- if (obj instanceof OcspListID)
- {
- return (OcspListID)obj;
- }
- else if (obj != null)
- {
- return new OcspListID(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private OcspListID(ASN1Sequence seq)
- {
- if (seq.size() != 1)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
- this.ocspResponses = (ASN1Sequence)seq.getObjectAt(0);
- Enumeration e = this.ocspResponses.getObjects();
- while (e.hasMoreElements())
- {
- OcspResponsesID.getInstance(e.nextElement());
- }
- }
-
- public OcspListID(OcspResponsesID[] ocspResponses)
- {
- this.ocspResponses = new DERSequence(ocspResponses);
- }
-
- public OcspResponsesID[] getOcspResponses()
- {
- OcspResponsesID[] result = new OcspResponsesID[this.ocspResponses
- .size()];
- for (int idx = 0; idx < result.length; idx++)
- {
- result[idx] = OcspResponsesID.getInstance(this.ocspResponses
- .getObjectAt(idx));
- }
- return result;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return new DERSequence(this.ocspResponses);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/OcspResponsesID.java b/core/src/main/java/org/bouncycastle/asn1/esf/OcspResponsesID.java
deleted file mode 100644
index 2aac80e2..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/OcspResponsesID.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * <pre>
- * OcspResponsesID ::= SEQUENCE {
- * ocspIdentifier OcspIdentifier,
- * ocspRepHash OtherHash OPTIONAL
- * }
- * </pre>
- */
-public class OcspResponsesID
- extends ASN1Object
-{
-
- private OcspIdentifier ocspIdentifier;
- private OtherHash ocspRepHash;
-
- public static OcspResponsesID getInstance(Object obj)
- {
- if (obj instanceof OcspResponsesID)
- {
- return (OcspResponsesID)obj;
- }
- else if (obj != null)
- {
- return new OcspResponsesID(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private OcspResponsesID(ASN1Sequence seq)
- {
- if (seq.size() < 1 || seq.size() > 2)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
- this.ocspIdentifier = OcspIdentifier.getInstance(seq.getObjectAt(0));
- if (seq.size() > 1)
- {
- this.ocspRepHash = OtherHash.getInstance(seq.getObjectAt(1));
- }
- }
-
- public OcspResponsesID(OcspIdentifier ocspIdentifier)
- {
- this(ocspIdentifier, null);
- }
-
- public OcspResponsesID(OcspIdentifier ocspIdentifier, OtherHash ocspRepHash)
- {
- this.ocspIdentifier = ocspIdentifier;
- this.ocspRepHash = ocspRepHash;
- }
-
- public OcspIdentifier getOcspIdentifier()
- {
- return this.ocspIdentifier;
- }
-
- public OtherHash getOcspRepHash()
- {
- return this.ocspRepHash;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- v.add(this.ocspIdentifier);
- if (null != this.ocspRepHash)
- {
- v.add(this.ocspRepHash);
- }
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/OtherHash.java b/core/src/main/java/org/bouncycastle/asn1/esf/OtherHash.java
deleted file mode 100644
index 0ec257d8..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/OtherHash.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-/**
- * <pre>
- * OtherHash ::= CHOICE {
- * sha1Hash OtherHashValue, -- This contains a SHA-1 hash
- * otherHash OtherHashAlgAndValue
- * }
- * </pre>
- */
-public class OtherHash
- extends ASN1Object
- implements ASN1Choice
-{
-
- private ASN1OctetString sha1Hash;
- private OtherHashAlgAndValue otherHash;
-
- public static OtherHash getInstance(Object obj)
- {
- if (obj instanceof OtherHash)
- {
- return (OtherHash)obj;
- }
- if (obj instanceof ASN1OctetString)
- {
- return new OtherHash((ASN1OctetString)obj);
- }
- return new OtherHash(OtherHashAlgAndValue.getInstance(obj));
- }
-
- private OtherHash(ASN1OctetString sha1Hash)
- {
- this.sha1Hash = sha1Hash;
- }
-
- public OtherHash(OtherHashAlgAndValue otherHash)
- {
- this.otherHash = otherHash;
- }
-
- public OtherHash(byte[] sha1Hash)
- {
- this.sha1Hash = new DEROctetString(sha1Hash);
- }
-
- public AlgorithmIdentifier getHashAlgorithm()
- {
- if (null == this.otherHash)
- {
- return new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1);
- }
- return this.otherHash.getHashAlgorithm();
- }
-
- public byte[] getHashValue()
- {
- if (null == this.otherHash)
- {
- return this.sha1Hash.getOctets();
- }
- return this.otherHash.getHashValue().getOctets();
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- if (null == this.otherHash)
- {
- return this.sha1Hash;
- }
- return this.otherHash.toASN1Primitive();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/OtherHashAlgAndValue.java b/core/src/main/java/org/bouncycastle/asn1/esf/OtherHashAlgAndValue.java
deleted file mode 100644
index 34229d4e..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/OtherHashAlgAndValue.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-public class OtherHashAlgAndValue
- extends ASN1Object
-{
- private AlgorithmIdentifier hashAlgorithm;
- private ASN1OctetString hashValue;
-
-
- public static OtherHashAlgAndValue getInstance(
- Object obj)
- {
- if (obj instanceof OtherHashAlgAndValue)
- {
- return (OtherHashAlgAndValue) obj;
- }
- else if (obj != null)
- {
- return new OtherHashAlgAndValue(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private OtherHashAlgAndValue(
- ASN1Sequence seq)
- {
- if (seq.size() != 2)
- {
- throw new IllegalArgumentException("Bad sequence size: " + seq.size());
- }
-
- hashAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(0));
- hashValue = ASN1OctetString.getInstance(seq.getObjectAt(1));
- }
-
- public OtherHashAlgAndValue(
- AlgorithmIdentifier hashAlgorithm,
- ASN1OctetString hashValue)
- {
- this.hashAlgorithm = hashAlgorithm;
- this.hashValue = hashValue;
- }
-
- public AlgorithmIdentifier getHashAlgorithm()
- {
- return hashAlgorithm;
- }
-
- public ASN1OctetString getHashValue()
- {
- return hashValue;
- }
-
- /**
- * <pre>
- * OtherHashAlgAndValue ::= SEQUENCE {
- * hashAlgorithm AlgorithmIdentifier,
- * hashValue OtherHashValue }
- *
- * OtherHashValue ::= OCTET STRING
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(hashAlgorithm);
- v.add(hashValue);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/OtherRevRefs.java b/core/src/main/java/org/bouncycastle/asn1/esf/OtherRevRefs.java
deleted file mode 100644
index ed9a9b30..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/OtherRevRefs.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Encoding;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * <pre>
- * OtherRevRefs ::= SEQUENCE {
- * otherRevRefType OtherRevRefType,
- * otherRevRefs ANY DEFINED BY otherRevRefType
- * }
- *
- * OtherRevRefType ::= OBJECT IDENTIFIER
- * </pre>
- */
-public class OtherRevRefs
- extends ASN1Object
-{
-
- private ASN1ObjectIdentifier otherRevRefType;
- private ASN1Encodable otherRevRefs;
-
- public static OtherRevRefs getInstance(Object obj)
- {
- if (obj instanceof OtherRevRefs)
- {
- return (OtherRevRefs)obj;
- }
- else if (obj != null)
- {
- return new OtherRevRefs(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private OtherRevRefs(ASN1Sequence seq)
- {
- if (seq.size() != 2)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
- this.otherRevRefType = new ASN1ObjectIdentifier(((ASN1ObjectIdentifier)seq.getObjectAt(0)).getId());
- try
- {
- this.otherRevRefs = ASN1Primitive.fromByteArray(seq.getObjectAt(1)
- .toASN1Primitive().getEncoded(ASN1Encoding.DER));
- }
- catch (IOException e)
- {
- throw new IllegalStateException();
- }
- }
-
- public OtherRevRefs(ASN1ObjectIdentifier otherRevRefType, ASN1Encodable otherRevRefs)
- {
- this.otherRevRefType = otherRevRefType;
- this.otherRevRefs = otherRevRefs;
- }
-
- public ASN1ObjectIdentifier getOtherRevRefType()
- {
- return this.otherRevRefType;
- }
-
- public ASN1Encodable getOtherRevRefs()
- {
- return this.otherRevRefs;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- v.add(this.otherRevRefType);
- v.add(this.otherRevRefs);
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/OtherRevVals.java b/core/src/main/java/org/bouncycastle/asn1/esf/OtherRevVals.java
deleted file mode 100644
index 7389bdfc..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/OtherRevVals.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Encoding;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * <pre>
- * OtherRevVals ::= SEQUENCE {
- * otherRevValType OtherRevValType,
- * otherRevVals ANY DEFINED BY OtherRevValType
- * }
- *
- * OtherRevValType ::= OBJECT IDENTIFIER
- * </pre>
- */
-public class OtherRevVals
- extends ASN1Object
-{
-
- private ASN1ObjectIdentifier otherRevValType;
-
- private ASN1Encodable otherRevVals;
-
- public static OtherRevVals getInstance(Object obj)
- {
- if (obj instanceof OtherRevVals)
- {
- return (OtherRevVals)obj;
- }
- if (obj != null)
- {
- return new OtherRevVals(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private OtherRevVals(ASN1Sequence seq)
- {
- if (seq.size() != 2)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
- this.otherRevValType = (ASN1ObjectIdentifier)seq.getObjectAt(0);
- try
- {
- this.otherRevVals = ASN1Primitive.fromByteArray(seq.getObjectAt(1)
- .toASN1Primitive().getEncoded(ASN1Encoding.DER));
- }
- catch (IOException e)
- {
- throw new IllegalStateException();
- }
- }
-
- public OtherRevVals(ASN1ObjectIdentifier otherRevValType,
- ASN1Encodable otherRevVals)
- {
- this.otherRevValType = otherRevValType;
- this.otherRevVals = otherRevVals;
- }
-
- public ASN1ObjectIdentifier getOtherRevValType()
- {
- return this.otherRevValType;
- }
-
- public ASN1Encodable getOtherRevVals()
- {
- return this.otherRevVals;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- v.add(this.otherRevValType);
- v.add(this.otherRevVals);
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/RevocationValues.java b/core/src/main/java/org/bouncycastle/asn1/esf/RevocationValues.java
deleted file mode 100644
index 9ff41131..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/RevocationValues.java
+++ /dev/null
@@ -1,151 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.ocsp.BasicOCSPResponse;
-import org.bouncycastle.asn1.x509.CertificateList;
-
-/**
- * <pre>
- * RevocationValues ::= SEQUENCE {
- * crlVals [0] SEQUENCE OF CertificateList OPTIONAL,
- * ocspVals [1] SEQUENCE OF BasicOCSPResponse OPTIONAL,
- * otherRevVals [2] OtherRevVals OPTIONAL}
- * </pre>
- */
-public class RevocationValues
- extends ASN1Object
-{
-
- private ASN1Sequence crlVals;
- private ASN1Sequence ocspVals;
- private OtherRevVals otherRevVals;
-
- public static RevocationValues getInstance(Object obj)
- {
- if (obj instanceof RevocationValues)
- {
- return (RevocationValues)obj;
- }
- else if (obj != null)
- {
- return new RevocationValues(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private RevocationValues(ASN1Sequence seq)
- {
- if (seq.size() > 3)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
- Enumeration e = seq.getObjects();
- while (e.hasMoreElements())
- {
- DERTaggedObject o = (DERTaggedObject)e.nextElement();
- switch (o.getTagNo())
- {
- case 0:
- ASN1Sequence crlValsSeq = (ASN1Sequence)o.getObject();
- Enumeration crlValsEnum = crlValsSeq.getObjects();
- while (crlValsEnum.hasMoreElements())
- {
- CertificateList.getInstance(crlValsEnum.nextElement());
- }
- this.crlVals = crlValsSeq;
- break;
- case 1:
- ASN1Sequence ocspValsSeq = (ASN1Sequence)o.getObject();
- Enumeration ocspValsEnum = ocspValsSeq.getObjects();
- while (ocspValsEnum.hasMoreElements())
- {
- BasicOCSPResponse.getInstance(ocspValsEnum.nextElement());
- }
- this.ocspVals = ocspValsSeq;
- break;
- case 2:
- this.otherRevVals = OtherRevVals.getInstance(o.getObject());
- break;
- default:
- throw new IllegalArgumentException("invalid tag: "
- + o.getTagNo());
- }
- }
- }
-
- public RevocationValues(CertificateList[] crlVals,
- BasicOCSPResponse[] ocspVals, OtherRevVals otherRevVals)
- {
- if (null != crlVals)
- {
- this.crlVals = new DERSequence(crlVals);
- }
- if (null != ocspVals)
- {
- this.ocspVals = new DERSequence(ocspVals);
- }
- this.otherRevVals = otherRevVals;
- }
-
- public CertificateList[] getCrlVals()
- {
- if (null == this.crlVals)
- {
- return new CertificateList[0];
- }
- CertificateList[] result = new CertificateList[this.crlVals.size()];
- for (int idx = 0; idx < result.length; idx++)
- {
- result[idx] = CertificateList.getInstance(this.crlVals
- .getObjectAt(idx));
- }
- return result;
- }
-
- public BasicOCSPResponse[] getOcspVals()
- {
- if (null == this.ocspVals)
- {
- return new BasicOCSPResponse[0];
- }
- BasicOCSPResponse[] result = new BasicOCSPResponse[this.ocspVals.size()];
- for (int idx = 0; idx < result.length; idx++)
- {
- result[idx] = BasicOCSPResponse.getInstance(this.ocspVals
- .getObjectAt(idx));
- }
- return result;
- }
-
- public OtherRevVals getOtherRevVals()
- {
- return this.otherRevVals;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- if (null != this.crlVals)
- {
- v.add(new DERTaggedObject(true, 0, this.crlVals));
- }
- if (null != this.ocspVals)
- {
- v.add(new DERTaggedObject(true, 1, this.ocspVals));
- }
- if (null != this.otherRevVals)
- {
- v.add(new DERTaggedObject(true, 2, this.otherRevVals.toASN1Primitive()));
- }
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/SPUserNotice.java b/core/src/main/java/org/bouncycastle/asn1/esf/SPUserNotice.java
deleted file mode 100644
index c026cde9..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/SPUserNotice.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1String;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.DisplayText;
-import org.bouncycastle.asn1.x509.NoticeReference;
-
-public class SPUserNotice
- extends ASN1Object
-{
- private NoticeReference noticeRef;
- private DisplayText explicitText;
-
- public static SPUserNotice getInstance(
- Object obj)
- {
- if (obj instanceof SPUserNotice)
- {
- return (SPUserNotice)obj;
- }
- else if (obj != null)
- {
- return new SPUserNotice(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private SPUserNotice(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
- while (e.hasMoreElements())
- {
- ASN1Encodable object = (ASN1Encodable)e.nextElement();
- if (object instanceof DisplayText || object instanceof ASN1String)
- {
- explicitText = DisplayText.getInstance(object);
- }
- else if (object instanceof NoticeReference || object instanceof ASN1Sequence)
- {
- noticeRef = NoticeReference.getInstance(object);
- }
- else
- {
- throw new IllegalArgumentException("Invalid element in 'SPUserNotice': " + object.getClass().getName());
- }
- }
- }
-
- public SPUserNotice(
- NoticeReference noticeRef,
- DisplayText explicitText)
- {
- this.noticeRef = noticeRef;
- this.explicitText = explicitText;
- }
-
- public NoticeReference getNoticeRef()
- {
- return noticeRef;
- }
-
- public DisplayText getExplicitText()
- {
- return explicitText;
- }
-
- /**
- * <pre>
- * SPUserNotice ::= SEQUENCE {
- * noticeRef NoticeReference OPTIONAL,
- * explicitText DisplayText OPTIONAL }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (noticeRef != null)
- {
- v.add(noticeRef);
- }
-
- if (explicitText != null)
- {
- v.add(explicitText);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/SPuri.java b/core/src/main/java/org/bouncycastle/asn1/esf/SPuri.java
deleted file mode 100644
index 2e2483db..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/SPuri.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.DERIA5String;
-
-public class SPuri
-{
- private DERIA5String uri;
-
- public static SPuri getInstance(
- Object obj)
- {
- if (obj instanceof SPuri)
- {
- return (SPuri) obj;
- }
- else if (obj instanceof DERIA5String)
- {
- return new SPuri(DERIA5String.getInstance(obj));
- }
-
- return null;
- }
-
- public SPuri(
- DERIA5String uri)
- {
- this.uri = uri;
- }
-
- public DERIA5String getUri()
- {
- return uri;
- }
-
- /**
- * <pre>
- * SPuri ::= IA5String
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- return uri.toASN1Primitive();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/SigPolicyQualifierInfo.java b/core/src/main/java/org/bouncycastle/asn1/esf/SigPolicyQualifierInfo.java
deleted file mode 100644
index 3ce4836a..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/SigPolicyQualifierInfo.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-public class SigPolicyQualifierInfo
- extends ASN1Object
-{
- private ASN1ObjectIdentifier sigPolicyQualifierId;
- private ASN1Encodable sigQualifier;
-
- public SigPolicyQualifierInfo(
- ASN1ObjectIdentifier sigPolicyQualifierId,
- ASN1Encodable sigQualifier)
- {
- this.sigPolicyQualifierId = sigPolicyQualifierId;
- this.sigQualifier = sigQualifier;
- }
-
- private SigPolicyQualifierInfo(
- ASN1Sequence seq)
- {
- sigPolicyQualifierId = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
- sigQualifier = seq.getObjectAt(1);
- }
-
- public static SigPolicyQualifierInfo getInstance(
- Object obj)
- {
- if (obj instanceof SigPolicyQualifierInfo)
- {
- return (SigPolicyQualifierInfo) obj;
- }
- else if (obj != null)
- {
- return new SigPolicyQualifierInfo(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public ASN1ObjectIdentifier getSigPolicyQualifierId()
- {
- return new ASN1ObjectIdentifier(sigPolicyQualifierId.getId());
- }
-
- public ASN1Encodable getSigQualifier()
- {
- return sigQualifier;
- }
-
- /**
- * <pre>
- * SigPolicyQualifierInfo ::= SEQUENCE {
- * sigPolicyQualifierId SigPolicyQualifierId,
- * sigQualifier ANY DEFINED BY sigPolicyQualifierId }
- *
- * SigPolicyQualifierId ::= OBJECT IDENTIFIER
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(sigPolicyQualifierId);
- v.add(sigQualifier);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/SigPolicyQualifiers.java b/core/src/main/java/org/bouncycastle/asn1/esf/SigPolicyQualifiers.java
deleted file mode 100644
index 453c6d03..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/SigPolicyQualifiers.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-public class SigPolicyQualifiers
- extends ASN1Object
-{
- ASN1Sequence qualifiers;
-
- public static SigPolicyQualifiers getInstance(
- Object obj)
- {
- if (obj instanceof SigPolicyQualifiers)
- {
- return (SigPolicyQualifiers) obj;
- }
- else if (obj instanceof ASN1Sequence)
- {
- return new SigPolicyQualifiers(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private SigPolicyQualifiers(
- ASN1Sequence seq)
- {
- qualifiers = seq;
- }
-
- public SigPolicyQualifiers(
- SigPolicyQualifierInfo[] qualifierInfos)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- for (int i=0; i < qualifierInfos.length; i++)
- {
- v.add(qualifierInfos[i]);
- }
- qualifiers = new DERSequence(v);
- }
-
- /**
- * Return the number of qualifier info elements present.
- *
- * @return number of elements present.
- */
- public int size()
- {
- return qualifiers.size();
- }
-
- /**
- * Return the SigPolicyQualifierInfo at index i.
- *
- * @param i index of the info of interest
- * @return the info at index i.
- */
- public SigPolicyQualifierInfo getInfoAt(
- int i)
- {
- return SigPolicyQualifierInfo.getInstance(qualifiers.getObjectAt(i));
- }
-
- /**
- * <pre>
- * SigPolicyQualifiers ::= SEQUENCE SIZE (1..MAX) OF SigPolicyQualifierInfo
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- return qualifiers;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/SignaturePolicyId.java b/core/src/main/java/org/bouncycastle/asn1/esf/SignaturePolicyId.java
deleted file mode 100644
index 10b88f85..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/SignaturePolicyId.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-public class SignaturePolicyId
- extends ASN1Object
-{
- private ASN1ObjectIdentifier sigPolicyId;
- private OtherHashAlgAndValue sigPolicyHash;
- private SigPolicyQualifiers sigPolicyQualifiers;
-
-
- public static SignaturePolicyId getInstance(
- Object obj)
- {
- if (obj instanceof SignaturePolicyId)
- {
- return (SignaturePolicyId)obj;
- }
- else if (obj != null)
- {
- return new SignaturePolicyId(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private SignaturePolicyId(
- ASN1Sequence seq)
- {
- if (seq.size() != 2 && seq.size() != 3)
- {
- throw new IllegalArgumentException("Bad sequence size: " + seq.size());
- }
-
- sigPolicyId = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
- sigPolicyHash = OtherHashAlgAndValue.getInstance(seq.getObjectAt(1));
-
- if (seq.size() == 3)
- {
- sigPolicyQualifiers = SigPolicyQualifiers.getInstance(seq.getObjectAt(2));
- }
- }
-
- public SignaturePolicyId(
- ASN1ObjectIdentifier sigPolicyIdentifier,
- OtherHashAlgAndValue sigPolicyHash)
- {
- this(sigPolicyIdentifier, sigPolicyHash, null);
- }
-
- public SignaturePolicyId(
- ASN1ObjectIdentifier sigPolicyId,
- OtherHashAlgAndValue sigPolicyHash,
- SigPolicyQualifiers sigPolicyQualifiers)
- {
- this.sigPolicyId = sigPolicyId;
- this.sigPolicyHash = sigPolicyHash;
- this.sigPolicyQualifiers = sigPolicyQualifiers;
- }
-
- public ASN1ObjectIdentifier getSigPolicyId()
- {
- return new ASN1ObjectIdentifier(sigPolicyId.getId());
- }
-
- public OtherHashAlgAndValue getSigPolicyHash()
- {
- return sigPolicyHash;
- }
-
- public SigPolicyQualifiers getSigPolicyQualifiers()
- {
- return sigPolicyQualifiers;
- }
-
- /**
- * <pre>
- * SignaturePolicyId ::= SEQUENCE {
- * sigPolicyId SigPolicyId,
- * sigPolicyHash SigPolicyHash,
- * sigPolicyQualifiers SEQUENCE SIZE (1..MAX) OF SigPolicyQualifierInfo OPTIONAL}
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(sigPolicyId);
- v.add(sigPolicyHash);
- if (sigPolicyQualifiers != null)
- {
- v.add(sigPolicyQualifiers);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/SignaturePolicyIdentifier.java b/core/src/main/java/org/bouncycastle/asn1/esf/SignaturePolicyIdentifier.java
deleted file mode 100644
index acd8ac4b..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/SignaturePolicyIdentifier.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import org.bouncycastle.asn1.ASN1Null;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.BERTags;
-import org.bouncycastle.asn1.DERNull;
-
-public class SignaturePolicyIdentifier
- extends ASN1Object
-{
- private SignaturePolicyId signaturePolicyId;
- private boolean isSignaturePolicyImplied;
-
- public static SignaturePolicyIdentifier getInstance(
- Object obj)
- {
- if (obj instanceof SignaturePolicyIdentifier)
- {
- return (SignaturePolicyIdentifier)obj;
- }
- else if (obj instanceof ASN1Null || hasEncodedTagValue(obj, BERTags.NULL))
- {
- return new SignaturePolicyIdentifier();
- }
- else if (obj != null)
- {
- return new SignaturePolicyIdentifier(SignaturePolicyId.getInstance(obj));
- }
-
- return null;
- }
-
- public SignaturePolicyIdentifier()
- {
- this.isSignaturePolicyImplied = true;
- }
-
- public SignaturePolicyIdentifier(
- SignaturePolicyId signaturePolicyId)
- {
- this.signaturePolicyId = signaturePolicyId;
- this.isSignaturePolicyImplied = false;
- }
-
- public SignaturePolicyId getSignaturePolicyId()
- {
- return signaturePolicyId;
- }
-
- public boolean isSignaturePolicyImplied()
- {
- return isSignaturePolicyImplied;
- }
-
- /**
- * <pre>
- * SignaturePolicyIdentifier ::= CHOICE{
- * SignaturePolicyId SignaturePolicyId,
- * SignaturePolicyImplied SignaturePolicyImplied }
- *
- * SignaturePolicyImplied ::= NULL
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- if (isSignaturePolicyImplied)
- {
- return DERNull.INSTANCE;
- }
- else
- {
- return signaturePolicyId.toASN1Primitive();
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/SignerAttribute.java b/core/src/main/java/org/bouncycastle/asn1/esf/SignerAttribute.java
deleted file mode 100644
index ecc4db3c..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/SignerAttribute.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.Attribute;
-import org.bouncycastle.asn1.x509.AttributeCertificate;
-
-
-public class SignerAttribute
- extends ASN1Object
-{
- private Object[] values;
-
- public static SignerAttribute getInstance(
- Object o)
- {
- if (o instanceof SignerAttribute)
- {
- return (SignerAttribute) o;
- }
- else if (o != null)
- {
- return new SignerAttribute(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- private SignerAttribute(
- ASN1Sequence seq)
- {
- int index = 0;
- values = new Object[seq.size()];
-
- for (Enumeration e = seq.getObjects(); e.hasMoreElements();)
- {
- ASN1TaggedObject taggedObject = ASN1TaggedObject.getInstance(e.nextElement());
-
- if (taggedObject.getTagNo() == 0)
- {
- ASN1Sequence attrs = ASN1Sequence.getInstance(taggedObject, true);
- Attribute[] attributes = new Attribute[attrs.size()];
-
- for (int i = 0; i != attributes.length; i++)
- {
- attributes[i] = Attribute.getInstance(attrs.getObjectAt(i));
- }
- values[index] = attributes;
- }
- else if (taggedObject.getTagNo() == 1)
- {
- values[index] = AttributeCertificate.getInstance(ASN1Sequence.getInstance(taggedObject, true));
- }
- else
- {
- throw new IllegalArgumentException("illegal tag: " + taggedObject.getTagNo());
- }
- index++;
- }
- }
-
- public SignerAttribute(
- Attribute[] claimedAttributes)
- {
- this.values = new Object[1];
- this.values[0] = claimedAttributes;
- }
-
- public SignerAttribute(
- AttributeCertificate certifiedAttributes)
- {
- this.values = new Object[1];
- this.values[0] = certifiedAttributes;
- }
-
- /**
- * Return the sequence of choices - the array elements will either be of
- * type Attribute[] or AttributeCertificate depending on what tag was used.
- *
- * @return array of choices.
- */
- public Object[] getValues()
- {
- return values;
- }
-
- /**
- *
- * <pre>
- * SignerAttribute ::= SEQUENCE OF CHOICE {
- * claimedAttributes [0] ClaimedAttributes,
- * certifiedAttributes [1] CertifiedAttributes }
- *
- * ClaimedAttributes ::= SEQUENCE OF Attribute
- * CertifiedAttributes ::= AttributeCertificate -- as defined in RFC 3281: see clause 4.1.
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- for (int i = 0; i != values.length; i++)
- {
- if (values[i] instanceof Attribute[])
- {
- v.add(new DERTaggedObject(0, new DERSequence((Attribute[])values[i])));
- }
- else
- {
- v.add(new DERTaggedObject(1, (AttributeCertificate)values[i]));
- }
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/esf/SignerLocation.java b/core/src/main/java/org/bouncycastle/asn1/esf/SignerLocation.java
deleted file mode 100644
index fcdb3206..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/esf/SignerLocation.java
+++ /dev/null
@@ -1,162 +0,0 @@
-package org.bouncycastle.asn1.esf;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.DERUTF8String;
-import org.bouncycastle.asn1.x500.DirectoryString;
-
-/**
- * Signer-Location attribute (RFC3126).
- *
- * <pre>
- * SignerLocation ::= SEQUENCE {
- * countryName [0] DirectoryString OPTIONAL,
- * localityName [1] DirectoryString OPTIONAL,
- * postalAddress [2] PostalAddress OPTIONAL }
- *
- * PostalAddress ::= SEQUENCE SIZE(1..6) OF DirectoryString
- * </pre>
- */
-public class SignerLocation
- extends ASN1Object
-{
- private DERUTF8String countryName;
- private DERUTF8String localityName;
- private ASN1Sequence postalAddress;
-
- private SignerLocation(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- while (e.hasMoreElements())
- {
- DERTaggedObject o = (DERTaggedObject)e.nextElement();
-
- switch (o.getTagNo())
- {
- case 0:
- DirectoryString countryNameDirectoryString = DirectoryString.getInstance(o, true);
- this.countryName = new DERUTF8String(countryNameDirectoryString.getString());
- break;
- case 1:
- DirectoryString localityNameDirectoryString = DirectoryString.getInstance(o, true);
- this.localityName = new DERUTF8String(localityNameDirectoryString.getString());
- break;
- case 2:
- if (o.isExplicit())
- {
- this.postalAddress = ASN1Sequence.getInstance(o, true);
- }
- else // handle erroneous implicitly tagged sequences
- {
- this.postalAddress = ASN1Sequence.getInstance(o, false);
- }
- if (postalAddress != null && postalAddress.size() > 6)
- {
- throw new IllegalArgumentException("postal address must contain less than 6 strings");
- }
- break;
- default:
- throw new IllegalArgumentException("illegal tag");
- }
- }
- }
-
- public SignerLocation(
- DERUTF8String countryName,
- DERUTF8String localityName,
- ASN1Sequence postalAddress)
- {
- if (postalAddress != null && postalAddress.size() > 6)
- {
- throw new IllegalArgumentException("postal address must contain less than 6 strings");
- }
-
- if (countryName != null)
- {
- this.countryName = DERUTF8String.getInstance(countryName.toASN1Primitive());
- }
-
- if (localityName != null)
- {
- this.localityName = DERUTF8String.getInstance(localityName.toASN1Primitive());
- }
-
- if (postalAddress != null)
- {
- this.postalAddress = ASN1Sequence.getInstance(postalAddress.toASN1Primitive());
- }
- }
-
- public static SignerLocation getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof SignerLocation)
- {
- return (SignerLocation)obj;
- }
-
- return new SignerLocation(ASN1Sequence.getInstance(obj));
- }
-
- public DERUTF8String getCountryName()
- {
- return countryName;
- }
-
- public DERUTF8String getLocalityName()
- {
- return localityName;
- }
-
- public ASN1Sequence getPostalAddress()
- {
- return postalAddress;
- }
-
- /**
- * <pre>
- * SignerLocation ::= SEQUENCE {
- * countryName [0] DirectoryString OPTIONAL,
- * localityName [1] DirectoryString OPTIONAL,
- * postalAddress [2] PostalAddress OPTIONAL }
- *
- * PostalAddress ::= SEQUENCE SIZE(1..6) OF DirectoryString
- *
- * DirectoryString ::= CHOICE {
- * teletexString TeletexString (SIZE (1..MAX)),
- * printableString PrintableString (SIZE (1..MAX)),
- * universalString UniversalString (SIZE (1..MAX)),
- * utf8String UTF8String (SIZE (1.. MAX)),
- * bmpString BMPString (SIZE (1..MAX)) }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (countryName != null)
- {
- v.add(new DERTaggedObject(true, 0, countryName));
- }
-
- if (localityName != null)
- {
- v.add(new DERTaggedObject(true, 1, localityName));
- }
-
- if (postalAddress != null)
- {
- v.add(new DERTaggedObject(true, 2, postalAddress));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ess/ContentHints.java b/core/src/main/java/org/bouncycastle/asn1/ess/ContentHints.java
deleted file mode 100644
index 462d9685..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ess/ContentHints.java
+++ /dev/null
@@ -1,94 +0,0 @@
-package org.bouncycastle.asn1.ess;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERUTF8String;
-
-public class ContentHints
- extends ASN1Object
-{
- private DERUTF8String contentDescription;
- private ASN1ObjectIdentifier contentType;
-
- public static ContentHints getInstance(Object o)
- {
- if (o instanceof ContentHints)
- {
- return (ContentHints)o;
- }
- else if (o != null)
- {
- return new ContentHints(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- /**
- * constructor
- */
- private ContentHints(ASN1Sequence seq)
- {
- ASN1Encodable field = seq.getObjectAt(0);
- if (field.toASN1Primitive() instanceof DERUTF8String)
- {
- contentDescription = DERUTF8String.getInstance(field);
- contentType = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(1));
- }
- else
- {
- contentType = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
- }
- }
-
- public ContentHints(
- ASN1ObjectIdentifier contentType)
- {
- this.contentType = contentType;
- this.contentDescription = null;
- }
-
- public ContentHints(
- ASN1ObjectIdentifier contentType,
- DERUTF8String contentDescription)
- {
- this.contentType = contentType;
- this.contentDescription = contentDescription;
- }
-
- public ASN1ObjectIdentifier getContentType()
- {
- return contentType;
- }
-
- public DERUTF8String getContentDescription()
- {
- return contentDescription;
- }
-
- /**
- * <pre>
- * ContentHints ::= SEQUENCE {
- * contentDescription UTF8String (SIZE (1..MAX)) OPTIONAL,
- * contentType ContentType }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (contentDescription != null)
- {
- v.add(contentDescription);
- }
-
- v.add(contentType);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ess/ContentIdentifier.java b/core/src/main/java/org/bouncycastle/asn1/ess/ContentIdentifier.java
deleted file mode 100644
index 37064c4e..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ess/ContentIdentifier.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package org.bouncycastle.asn1.ess;
-
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.DEROctetString;
-
-public class ContentIdentifier
- extends ASN1Object
-{
- ASN1OctetString value;
-
- public static ContentIdentifier getInstance(Object o)
- {
- if (o instanceof ContentIdentifier)
- {
- return (ContentIdentifier) o;
- }
- else if (o != null)
- {
- return new ContentIdentifier(ASN1OctetString.getInstance(o));
- }
-
- return null;
- }
-
- /**
- * Create from OCTET STRING whose octets represent the identifier.
- */
- private ContentIdentifier(
- ASN1OctetString value)
- {
- this.value = value;
- }
-
- /**
- * Create from byte array representing the identifier.
- */
- public ContentIdentifier(
- byte[] value)
- {
- this(new DEROctetString(value));
- }
-
- public ASN1OctetString getValue()
- {
- return value;
- }
-
- /**
- * The definition of ContentIdentifier is
- * <pre>
- * ContentIdentifier ::= OCTET STRING
- * </pre>
- * id-aa-contentIdentifier OBJECT IDENTIFIER ::= { iso(1)
- * member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
- * smime(16) id-aa(2) 7 }
- */
- public ASN1Primitive toASN1Primitive()
- {
- return value;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ess/ESSCertID.java b/core/src/main/java/org/bouncycastle/asn1/ess/ESSCertID.java
deleted file mode 100644
index a6cc3156..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ess/ESSCertID.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package org.bouncycastle.asn1.ess;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-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.asn1.x509.IssuerSerial;
-
-public class ESSCertID
- extends ASN1Object
-{
- private ASN1OctetString certHash;
-
- private IssuerSerial issuerSerial;
-
- public static ESSCertID getInstance(Object o)
- {
- if (o instanceof ESSCertID)
- {
- return (ESSCertID)o;
- }
- else if (o != null)
- {
- return new ESSCertID(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- /**
- * constructor
- */
- private ESSCertID(ASN1Sequence seq)
- {
- if (seq.size() < 1 || seq.size() > 2)
- {
- throw new IllegalArgumentException("Bad sequence size: " + seq.size());
- }
-
- certHash = ASN1OctetString.getInstance(seq.getObjectAt(0));
-
- if (seq.size() > 1)
- {
- issuerSerial = IssuerSerial.getInstance(seq.getObjectAt(1));
- }
- }
-
- public ESSCertID(
- byte[] hash)
- {
- certHash = new DEROctetString(hash);
- }
-
- public ESSCertID(
- byte[] hash,
- IssuerSerial issuerSerial)
- {
- this.certHash = new DEROctetString(hash);
- this.issuerSerial = issuerSerial;
- }
-
- public byte[] getCertHash()
- {
- return certHash.getOctets();
- }
-
- public IssuerSerial getIssuerSerial()
- {
- return issuerSerial;
- }
-
- /**
- * <pre>
- * ESSCertID ::= SEQUENCE {
- * certHash Hash,
- * issuerSerial IssuerSerial OPTIONAL }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(certHash);
-
- if (issuerSerial != null)
- {
- v.add(issuerSerial);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ess/ESSCertIDv2.java b/core/src/main/java/org/bouncycastle/asn1/ess/ESSCertIDv2.java
deleted file mode 100644
index b511f2c2..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ess/ESSCertIDv2.java
+++ /dev/null
@@ -1,155 +0,0 @@
-package org.bouncycastle.asn1.ess;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-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.asn1.nist.NISTObjectIdentifiers;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.IssuerSerial;
-
-public class ESSCertIDv2
- extends ASN1Object
-{
- private AlgorithmIdentifier hashAlgorithm;
- private byte[] certHash;
- private IssuerSerial issuerSerial;
- private static final AlgorithmIdentifier DEFAULT_ALG_ID = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256);
-
- public static ESSCertIDv2 getInstance(
- Object o)
- {
- if (o instanceof ESSCertIDv2)
- {
- return (ESSCertIDv2) o;
- }
- else if (o != null)
- {
- return new ESSCertIDv2(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- private ESSCertIDv2(
- ASN1Sequence seq)
- {
- if (seq.size() > 3)
- {
- throw new IllegalArgumentException("Bad sequence size: " + seq.size());
- }
-
- int count = 0;
-
- if (seq.getObjectAt(0) instanceof ASN1OctetString)
- {
- // Default value
- this.hashAlgorithm = DEFAULT_ALG_ID;
- }
- else
- {
- this.hashAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(count++).toASN1Primitive());
- }
-
- this.certHash = ASN1OctetString.getInstance(seq.getObjectAt(count++).toASN1Primitive()).getOctets();
-
- if (seq.size() > count)
- {
- this.issuerSerial = IssuerSerial.getInstance(seq.getObjectAt(count));
- }
- }
-
- public ESSCertIDv2(
- byte[] certHash)
- {
- this(null, certHash, null);
- }
-
- public ESSCertIDv2(
- AlgorithmIdentifier algId,
- byte[] certHash)
- {
- this(algId, certHash, null);
- }
-
- public ESSCertIDv2(
- byte[] certHash,
- IssuerSerial issuerSerial)
- {
- this(null, certHash, issuerSerial);
- }
-
- public ESSCertIDv2(
- AlgorithmIdentifier algId,
- byte[] certHash,
- IssuerSerial issuerSerial)
- {
- if (algId == null)
- {
- // Default value
- this.hashAlgorithm = DEFAULT_ALG_ID;
- }
- else
- {
- this.hashAlgorithm = algId;
- }
-
- this.certHash = certHash;
- this.issuerSerial = issuerSerial;
- }
-
- public AlgorithmIdentifier getHashAlgorithm()
- {
- return this.hashAlgorithm;
- }
-
- public byte[] getCertHash()
- {
- return certHash;
- }
-
- public IssuerSerial getIssuerSerial()
- {
- return issuerSerial;
- }
-
- /**
- * <pre>
- * ESSCertIDv2 ::= SEQUENCE {
- * hashAlgorithm AlgorithmIdentifier
- * DEFAULT {algorithm id-sha256},
- * certHash Hash,
- * issuerSerial IssuerSerial OPTIONAL
- * }
- *
- * Hash ::= OCTET STRING
- *
- * IssuerSerial ::= SEQUENCE {
- * issuer GeneralNames,
- * serialNumber CertificateSerialNumber
- * }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (!hashAlgorithm.equals(DEFAULT_ALG_ID))
- {
- v.add(hashAlgorithm);
- }
-
- v.add(new DEROctetString(certHash).toASN1Primitive());
-
- if (issuerSerial != null)
- {
- v.add(issuerSerial);
- }
-
- return new DERSequence(v);
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ess/OtherCertID.java b/core/src/main/java/org/bouncycastle/asn1/ess/OtherCertID.java
deleted file mode 100644
index 2cc88ecc..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ess/OtherCertID.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package org.bouncycastle.asn1.ess;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.DigestInfo;
-import org.bouncycastle.asn1.x509.IssuerSerial;
-
-public class OtherCertID
- extends ASN1Object
-{
- private ASN1Encodable otherCertHash;
- private IssuerSerial issuerSerial;
-
- public static OtherCertID getInstance(Object o)
- {
- if (o instanceof OtherCertID)
- {
- return (OtherCertID) o;
- }
- else if (o != null)
- {
- return new OtherCertID(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- /**
- * constructor
- */
- private OtherCertID(ASN1Sequence seq)
- {
- if (seq.size() < 1 || seq.size() > 2)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
-
- if (seq.getObjectAt(0).toASN1Primitive() instanceof ASN1OctetString)
- {
- otherCertHash = ASN1OctetString.getInstance(seq.getObjectAt(0));
- }
- else
- {
- otherCertHash = DigestInfo.getInstance(seq.getObjectAt(0));
-
- }
-
- if (seq.size() > 1)
- {
- issuerSerial = IssuerSerial.getInstance(seq.getObjectAt(1));
- }
- }
-
- public OtherCertID(
- AlgorithmIdentifier algId,
- byte[] digest)
- {
- this.otherCertHash = new DigestInfo(algId, digest);
- }
-
- public OtherCertID(
- AlgorithmIdentifier algId,
- byte[] digest,
- IssuerSerial issuerSerial)
- {
- this.otherCertHash = new DigestInfo(algId, digest);
- this.issuerSerial = issuerSerial;
- }
-
- public AlgorithmIdentifier getAlgorithmHash()
- {
- if (otherCertHash.toASN1Primitive() instanceof ASN1OctetString)
- {
- // SHA-1
- return new AlgorithmIdentifier("1.3.14.3.2.26");
- }
- else
- {
- return DigestInfo.getInstance(otherCertHash).getAlgorithmId();
- }
- }
-
- public byte[] getCertHash()
- {
- if (otherCertHash.toASN1Primitive() instanceof ASN1OctetString)
- {
- // SHA-1
- return ((ASN1OctetString)otherCertHash.toASN1Primitive()).getOctets();
- }
- else
- {
- return DigestInfo.getInstance(otherCertHash).getDigest();
- }
- }
-
- public IssuerSerial getIssuerSerial()
- {
- return issuerSerial;
- }
-
- /**
- * <pre>
- * OtherCertID ::= SEQUENCE {
- * otherCertHash OtherHash,
- * issuerSerial IssuerSerial OPTIONAL }
- *
- * OtherHash ::= CHOICE {
- * sha1Hash OCTET STRING,
- * otherHash OtherHashAlgAndValue }
- *
- * OtherHashAlgAndValue ::= SEQUENCE {
- * hashAlgorithm AlgorithmIdentifier,
- * hashValue OCTET STRING }
- *
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(otherCertHash);
-
- if (issuerSerial != null)
- {
- v.add(issuerSerial);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ess/OtherSigningCertificate.java b/core/src/main/java/org/bouncycastle/asn1/ess/OtherSigningCertificate.java
deleted file mode 100644
index 41f9e930..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ess/OtherSigningCertificate.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package org.bouncycastle.asn1.ess;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.PolicyInformation;
-
-public class OtherSigningCertificate
- extends ASN1Object
-{
- ASN1Sequence certs;
- ASN1Sequence policies;
-
- public static OtherSigningCertificate getInstance(Object o)
- {
- if (o instanceof OtherSigningCertificate)
- {
- return (OtherSigningCertificate) o;
- }
- else if (o != null)
- {
- return new OtherSigningCertificate(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- /**
- * constructeurs
- */
- private OtherSigningCertificate(ASN1Sequence seq)
- {
- if (seq.size() < 1 || seq.size() > 2)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
-
- this.certs = ASN1Sequence.getInstance(seq.getObjectAt(0));
-
- if (seq.size() > 1)
- {
- this.policies = ASN1Sequence.getInstance(seq.getObjectAt(1));
- }
- }
-
- public OtherSigningCertificate(
- OtherCertID otherCertID)
- {
- certs = new DERSequence(otherCertID);
- }
-
- public OtherCertID[] getCerts()
- {
- OtherCertID[] cs = new OtherCertID[certs.size()];
-
- for (int i = 0; i != certs.size(); i++)
- {
- cs[i] = OtherCertID.getInstance(certs.getObjectAt(i));
- }
-
- return cs;
- }
-
- public PolicyInformation[] getPolicies()
- {
- if (policies == null)
- {
- return null;
- }
-
- PolicyInformation[] ps = new PolicyInformation[policies.size()];
-
- for (int i = 0; i != policies.size(); i++)
- {
- ps[i] = PolicyInformation.getInstance(policies.getObjectAt(i));
- }
-
- return ps;
- }
-
- /**
- * The definition of OtherSigningCertificate is
- * <pre>
- * OtherSigningCertificate ::= SEQUENCE {
- * certs SEQUENCE OF OtherCertID,
- * policies SEQUENCE OF PolicyInformation OPTIONAL
- * }
- * </pre>
- * id-aa-ets-otherSigCert OBJECT IDENTIFIER ::= { iso(1)
- * member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
- * smime(16) id-aa(2) 19 }
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(certs);
-
- if (policies != null)
- {
- v.add(policies);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ess/SigningCertificate.java b/core/src/main/java/org/bouncycastle/asn1/ess/SigningCertificate.java
deleted file mode 100644
index eaf22e9f..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ess/SigningCertificate.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package org.bouncycastle.asn1.ess;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.PolicyInformation;
-
-
-public class SigningCertificate
- extends ASN1Object
-{
- ASN1Sequence certs;
- ASN1Sequence policies;
-
- public static SigningCertificate getInstance(Object o)
- {
- if (o instanceof SigningCertificate)
- {
- return (SigningCertificate) o;
- }
- else if (o != null)
- {
- return new SigningCertificate(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- /**
- * constructeurs
- */
- private SigningCertificate(ASN1Sequence seq)
- {
- if (seq.size() < 1 || seq.size() > 2)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
- this.certs = ASN1Sequence.getInstance(seq.getObjectAt(0));
-
- if (seq.size() > 1)
- {
- this.policies = ASN1Sequence.getInstance(seq.getObjectAt(1));
- }
- }
-
- public SigningCertificate(
- ESSCertID essCertID)
- {
- certs = new DERSequence(essCertID);
- }
-
- public ESSCertID[] getCerts()
- {
- ESSCertID[] cs = new ESSCertID[certs.size()];
-
- for (int i = 0; i != certs.size(); i++)
- {
- cs[i] = ESSCertID.getInstance(certs.getObjectAt(i));
- }
-
- return cs;
- }
-
- public PolicyInformation[] getPolicies()
- {
- if (policies == null)
- {
- return null;
- }
-
- PolicyInformation[] ps = new PolicyInformation[policies.size()];
-
- for (int i = 0; i != policies.size(); i++)
- {
- ps[i] = PolicyInformation.getInstance(policies.getObjectAt(i));
- }
-
- return ps;
- }
-
- /**
- * The definition of SigningCertificate is
- * <pre>
- * SigningCertificate ::= SEQUENCE {
- * certs SEQUENCE OF ESSCertID,
- * policies SEQUENCE OF PolicyInformation OPTIONAL
- * }
- * </pre>
- * id-aa-signingCertificate OBJECT IDENTIFIER ::= { iso(1)
- * member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
- * smime(16) id-aa(2) 12 }
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(certs);
-
- if (policies != null)
- {
- v.add(policies);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ess/SigningCertificateV2.java b/core/src/main/java/org/bouncycastle/asn1/ess/SigningCertificateV2.java
deleted file mode 100644
index 07219cdd..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ess/SigningCertificateV2.java
+++ /dev/null
@@ -1,136 +0,0 @@
-package org.bouncycastle.asn1.ess;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.PolicyInformation;
-
-public class SigningCertificateV2
- extends ASN1Object
-{
- ASN1Sequence certs;
- ASN1Sequence policies;
-
- public static SigningCertificateV2 getInstance(
- Object o)
- {
- if (o == null || o instanceof SigningCertificateV2)
- {
- return (SigningCertificateV2) o;
- }
- else if (o instanceof ASN1Sequence)
- {
- return new SigningCertificateV2((ASN1Sequence) o);
- }
-
- return null;
- }
-
- private SigningCertificateV2(
- ASN1Sequence seq)
- {
- if (seq.size() < 1 || seq.size() > 2)
- {
- throw new IllegalArgumentException("Bad sequence size: " + seq.size());
- }
-
- this.certs = ASN1Sequence.getInstance(seq.getObjectAt(0));
-
- if (seq.size() > 1)
- {
- this.policies = ASN1Sequence.getInstance(seq.getObjectAt(1));
- }
- }
-
- public SigningCertificateV2(
- ESSCertIDv2 cert)
- {
- this.certs = new DERSequence(cert);
- }
-
- public SigningCertificateV2(
- ESSCertIDv2[] certs)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- for (int i=0; i < certs.length; i++)
- {
- v.add(certs[i]);
- }
- this.certs = new DERSequence(v);
- }
-
- public SigningCertificateV2(
- ESSCertIDv2[] certs,
- PolicyInformation[] policies)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- for (int i=0; i < certs.length; i++)
- {
- v.add(certs[i]);
- }
- this.certs = new DERSequence(v);
-
- if (policies != null)
- {
- v = new ASN1EncodableVector();
- for (int i=0; i < policies.length; i++)
- {
- v.add(policies[i]);
- }
- this.policies = new DERSequence(v);
- }
- }
-
- public ESSCertIDv2[] getCerts()
- {
- ESSCertIDv2[] certIds = new ESSCertIDv2[certs.size()];
- for (int i = 0; i != certs.size(); i++)
- {
- certIds[i] = ESSCertIDv2.getInstance(certs.getObjectAt(i));
- }
- return certIds;
- }
-
- public PolicyInformation[] getPolicies()
- {
- if (policies == null)
- {
- return null;
- }
-
- PolicyInformation[] policyInformations = new PolicyInformation[policies.size()];
- for (int i = 0; i != policies.size(); i++)
- {
- policyInformations[i] = PolicyInformation.getInstance(policies.getObjectAt(i));
- }
- return policyInformations;
- }
-
- /**
- * The definition of SigningCertificateV2 is
- * <pre>
- * SigningCertificateV2 ::= SEQUENCE {
- * certs SEQUENCE OF ESSCertIDv2,
- * policies SEQUENCE OF PolicyInformation OPTIONAL
- * }
- * </pre>
- * id-aa-signingCertificateV2 OBJECT IDENTIFIER ::= { iso(1)
- * member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
- * smime(16) id-aa(2) 47 }
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(certs);
-
- if (policies != null)
- {
- v.add(policies);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/gnu/GNUObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/gnu/GNUObjectIdentifiers.java
deleted file mode 100644
index a329e63e..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/gnu/GNUObjectIdentifiers.java
+++ /dev/null
@@ -1,58 +0,0 @@
-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
-{
- /** 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/core/src/main/java/org/bouncycastle/asn1/iana/IANAObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/iana/IANAObjectIdentifiers.java
deleted file mode 100644
index 5bfdbab8..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/iana/IANAObjectIdentifiers.java
+++ /dev/null
@@ -1,60 +0,0 @@
-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)}
- //
-
-
- /** 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");
-
- /** IPSEC ISAKMP-Oakley hmacTIGER OID: 1.3.6.1.5.5.8.1.3 */
- static final ASN1ObjectIdentifier hmacTIGER = isakmpOakley.branch("3");
-
- /** IPSEC ISAKMP-Oakley hmacRIPEMD160 OID: 1.3.6.1.5.5.8.1.4 */
- static final ASN1ObjectIdentifier hmacRIPEMD160 = isakmpOakley.branch("4");
-
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/icao/CscaMasterList.java b/core/src/main/java/org/bouncycastle/asn1/icao/CscaMasterList.java
deleted file mode 100644
index ff629f2f..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/icao/CscaMasterList.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package org.bouncycastle.asn1.icao;
-
-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.ASN1Set;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERSet;
-import org.bouncycastle.asn1.x509.Certificate;
-
-/**
- * The CscaMasterList object. This object can be wrapped in a
- * CMSSignedData to be published in LDAP.
- *
- * <pre>
- * CscaMasterList ::= SEQUENCE {
- * version CscaMasterListVersion,
- * certList SET OF Certificate }
- *
- * CscaMasterListVersion :: INTEGER {v0(0)}
- * </pre>
- */
-
-public class CscaMasterList
- extends ASN1Object
-{
- private ASN1Integer version = new ASN1Integer(0);
- private Certificate[] certList;
-
- public static CscaMasterList getInstance(
- Object obj)
- {
- if (obj instanceof CscaMasterList)
- {
- return (CscaMasterList)obj;
- }
- else if (obj != null)
- {
- return new CscaMasterList(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private CscaMasterList(
- ASN1Sequence seq)
- {
- if (seq == null || seq.size() == 0)
- {
- throw new IllegalArgumentException(
- "null or empty sequence passed.");
- }
- if (seq.size() != 2)
- {
- throw new IllegalArgumentException(
- "Incorrect sequence size: " + seq.size());
- }
-
- version = ASN1Integer.getInstance(seq.getObjectAt(0));
- ASN1Set certSet = ASN1Set.getInstance(seq.getObjectAt(1));
- certList = new Certificate[certSet.size()];
- for (int i = 0; i < certList.length; i++)
- {
- certList[i]
- = Certificate.getInstance(certSet.getObjectAt(i));
- }
- }
-
- public CscaMasterList(
- Certificate[] certStructs)
- {
- certList = copyCertList(certStructs);
- }
-
- public int getVersion()
- {
- return version.getValue().intValue();
- }
-
- public Certificate[] getCertStructs()
- {
- return copyCertList(certList);
- }
-
- private Certificate[] copyCertList(Certificate[] orig)
- {
- Certificate[] certs = new Certificate[orig.length];
-
- for (int i = 0; i != certs.length; i++)
- {
- certs[i] = orig[i];
- }
-
- return certs;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector seq = new ASN1EncodableVector();
-
- seq.add(version);
-
- ASN1EncodableVector certSet = new ASN1EncodableVector();
- for (int i = 0; i < certList.length; i++)
- {
- certSet.add(certList[i]);
- }
- seq.add(new DERSet(certSet));
-
- return new DERSequence(seq);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/icao/DataGroupHash.java b/core/src/main/java/org/bouncycastle/asn1/icao/DataGroupHash.java
deleted file mode 100644
index b4c4c5c8..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/icao/DataGroupHash.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package org.bouncycastle.asn1.icao;
-
-import java.util.Enumeration;
-
-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.DERSequence;
-
-/**
- * The DataGroupHash object.
- * <pre>
- * DataGroupHash ::= SEQUENCE {
- * dataGroupNumber DataGroupNumber,
- * dataGroupHashValue OCTET STRING }
- *
- * DataGroupNumber ::= INTEGER {
- * dataGroup1 (1),
- * dataGroup1 (2),
- * dataGroup1 (3),
- * dataGroup1 (4),
- * dataGroup1 (5),
- * dataGroup1 (6),
- * dataGroup1 (7),
- * dataGroup1 (8),
- * dataGroup1 (9),
- * dataGroup1 (10),
- * dataGroup1 (11),
- * dataGroup1 (12),
- * dataGroup1 (13),
- * dataGroup1 (14),
- * dataGroup1 (15),
- * dataGroup1 (16) }
- *
- * </pre>
- */
-public class DataGroupHash
- extends ASN1Object
-{
- ASN1Integer dataGroupNumber;
- ASN1OctetString dataGroupHashValue;
-
- public static DataGroupHash getInstance(
- Object obj)
- {
- if (obj instanceof DataGroupHash)
- {
- return (DataGroupHash)obj;
- }
- else if (obj != null)
- {
- return new DataGroupHash(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private DataGroupHash(ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- // dataGroupNumber
- dataGroupNumber = ASN1Integer.getInstance(e.nextElement());
- // dataGroupHashValue
- dataGroupHashValue = ASN1OctetString.getInstance(e.nextElement());
- }
-
- public DataGroupHash(
- int dataGroupNumber,
- ASN1OctetString dataGroupHashValue)
- {
- this.dataGroupNumber = new ASN1Integer(dataGroupNumber);
- this.dataGroupHashValue = dataGroupHashValue;
- }
-
- public int getDataGroupNumber()
- {
- return dataGroupNumber.getValue().intValue();
- }
-
- public ASN1OctetString getDataGroupHashValue()
- {
- return dataGroupHashValue;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector seq = new ASN1EncodableVector();
- seq.add(dataGroupNumber);
- seq.add(dataGroupHashValue);
-
- return new DERSequence(seq);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/icao/ICAOObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/icao/ICAOObjectIdentifiers.java
deleted file mode 100644
index 3c271dae..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/icao/ICAOObjectIdentifiers.java
+++ /dev/null
@@ -1,49 +0,0 @@
-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<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<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 <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<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<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/core/src/main/java/org/bouncycastle/asn1/icao/LDSSecurityObject.java b/core/src/main/java/org/bouncycastle/asn1/icao/LDSSecurityObject.java
deleted file mode 100644
index fae8762b..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/icao/LDSSecurityObject.java
+++ /dev/null
@@ -1,159 +0,0 @@
-package org.bouncycastle.asn1.icao;
-
-import java.util.Enumeration;
-
-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.DERSequence;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-/**
- * The LDSSecurityObject object (V1.8).
- * <pre>
- * LDSSecurityObject ::= SEQUENCE {
- * version LDSSecurityObjectVersion,
- * hashAlgorithm DigestAlgorithmIdentifier,
- * dataGroupHashValues SEQUENCE SIZE (2..ub-DataGroups) OF DataHashGroup,
- * ldsVersionInfo LDSVersionInfo OPTIONAL
- * -- if present, version MUST be v1 }
- *
- * DigestAlgorithmIdentifier ::= AlgorithmIdentifier,
- *
- * LDSSecurityObjectVersion :: INTEGER {V0(0)}
- * </pre>
- */
-
-public class LDSSecurityObject
- extends ASN1Object
- implements ICAOObjectIdentifiers
-{
- public static final int ub_DataGroups = 16;
-
- private ASN1Integer version = new ASN1Integer(0);
- private AlgorithmIdentifier digestAlgorithmIdentifier;
- private DataGroupHash[] datagroupHash;
- private LDSVersionInfo versionInfo;
-
- public static LDSSecurityObject getInstance(
- Object obj)
- {
- if (obj instanceof LDSSecurityObject)
- {
- return (LDSSecurityObject)obj;
- }
- else if (obj != null)
- {
- return new LDSSecurityObject(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private LDSSecurityObject(
- ASN1Sequence seq)
- {
- if (seq == null || seq.size() == 0)
- {
- throw new IllegalArgumentException("null or empty sequence passed.");
- }
-
- Enumeration e = seq.getObjects();
-
- // version
- version = ASN1Integer.getInstance(e.nextElement());
- // digestAlgorithmIdentifier
- digestAlgorithmIdentifier = AlgorithmIdentifier.getInstance(e.nextElement());
-
- ASN1Sequence datagroupHashSeq = ASN1Sequence.getInstance(e.nextElement());
-
- if (version.getValue().intValue() == 1)
- {
- versionInfo = LDSVersionInfo.getInstance(e.nextElement());
- }
-
- checkDatagroupHashSeqSize(datagroupHashSeq.size());
-
- datagroupHash = new DataGroupHash[datagroupHashSeq.size()];
- for (int i= 0; i< datagroupHashSeq.size();i++)
- {
- datagroupHash[i] = DataGroupHash.getInstance(datagroupHashSeq.getObjectAt(i));
- }
- }
-
- public LDSSecurityObject(
- AlgorithmIdentifier digestAlgorithmIdentifier,
- DataGroupHash[] datagroupHash)
- {
- this.version = new ASN1Integer(0);
- this.digestAlgorithmIdentifier = digestAlgorithmIdentifier;
- this.datagroupHash = datagroupHash;
-
- checkDatagroupHashSeqSize(datagroupHash.length);
- }
-
- public LDSSecurityObject(
- AlgorithmIdentifier digestAlgorithmIdentifier,
- DataGroupHash[] datagroupHash,
- LDSVersionInfo versionInfo)
- {
- this.version = new ASN1Integer(1);
- this.digestAlgorithmIdentifier = digestAlgorithmIdentifier;
- this.datagroupHash = datagroupHash;
- this.versionInfo = versionInfo;
-
- checkDatagroupHashSeqSize(datagroupHash.length);
- }
-
- private void checkDatagroupHashSeqSize(int size)
- {
- if ((size < 2) || (size > ub_DataGroups))
- {
- throw new IllegalArgumentException("wrong size in DataGroupHashValues : not in (2.."+ ub_DataGroups +")");
- }
- }
-
- public int getVersion()
- {
- return version.getValue().intValue();
- }
-
- public AlgorithmIdentifier getDigestAlgorithmIdentifier()
- {
- return digestAlgorithmIdentifier;
- }
-
- public DataGroupHash[] getDatagroupHash()
- {
- return datagroupHash;
- }
-
- public LDSVersionInfo getVersionInfo()
- {
- return versionInfo;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector seq = new ASN1EncodableVector();
-
- seq.add(version);
- seq.add(digestAlgorithmIdentifier);
-
- ASN1EncodableVector seqname = new ASN1EncodableVector();
- for (int i = 0; i < datagroupHash.length; i++)
- {
- seqname.add(datagroupHash[i]);
- }
- seq.add(new DERSequence(seqname));
-
- if (versionInfo != null)
- {
- seq.add(versionInfo);
- }
-
- return new DERSequence(seq);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/icao/LDSVersionInfo.java b/core/src/main/java/org/bouncycastle/asn1/icao/LDSVersionInfo.java
deleted file mode 100644
index 9c5ae336..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/icao/LDSVersionInfo.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package org.bouncycastle.asn1.icao;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERPrintableString;
-import org.bouncycastle.asn1.DERSequence;
-
-public class LDSVersionInfo
- extends ASN1Object
-{
- private DERPrintableString ldsVersion;
- private DERPrintableString unicodeVersion;
-
- public LDSVersionInfo(String ldsVersion, String unicodeVersion)
- {
- this.ldsVersion = new DERPrintableString(ldsVersion);
- this.unicodeVersion = new DERPrintableString(unicodeVersion);
- }
-
- private LDSVersionInfo(ASN1Sequence seq)
- {
- if (seq.size() != 2)
- {
- throw new IllegalArgumentException("sequence wrong size for LDSVersionInfo");
- }
-
- this.ldsVersion = DERPrintableString.getInstance(seq.getObjectAt(0));
- this.unicodeVersion = DERPrintableString.getInstance(seq.getObjectAt(1));
- }
-
- public static LDSVersionInfo getInstance(Object obj)
- {
- if (obj instanceof LDSVersionInfo)
- {
- return (LDSVersionInfo)obj;
- }
- else if (obj != null)
- {
- return new LDSVersionInfo(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public String getLdsVersion()
- {
- return ldsVersion.getString();
- }
-
- public String getUnicodeVersion()
- {
- return unicodeVersion.getString();
- }
-
- /**
- * <pre>
- * LDSVersionInfo ::= SEQUENCE {
- * ldsVersion PRINTABLE STRING
- * unicodeVersion PRINTABLE STRING
- * }
- * </pre>
- * @return
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(ldsVersion);
- v.add(unicodeVersion);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/isismtt/ISISMTTObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/isismtt/ISISMTTObjectIdentifiers.java
deleted file mode 100644
index 6b75fde6..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/isismtt/ISISMTTObjectIdentifiers.java
+++ /dev/null
@@ -1,210 +0,0 @@
-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");
-
- /**
- * The id-isismtt-cp-accredited OID indicates that the certificate is a
- * qualified certificate according to Directive 1999/93/EC of the European
- * 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
- * </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");
-
- /**
- * Monetary limit for transactions. The QcEuMonetaryLimit QC statement MUST
- * be used in new certificates in place of the extension/attribute
- * 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))
- * </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".
- * <pre>
- * 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");
-
- /**
- * 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))
- * </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
- * </pre>
- * <p>
- * OID: 1.3.36.8.3.9
- */
- static final ASN1ObjectIdentifier id_isismtt_at_retrieveIfAllowed = id_isismtt_at.branch("9");
-
- /**
- * 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
- */
- static final ASN1ObjectIdentifier id_isismtt_at_requestedCertificate = id_isismtt_at.branch("10");
-
- /**
- * 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");
-
- /**
- * SingleOCSPResponse extension: Date, when certificate has been published
- * in the directory and status information has become available. Currently,
- * accrediting authorities enforce that SigG-conforming OCSP servers include
- * this extension in the responses.
- *
- * <pre>
- * 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
- */
- static final ASN1ObjectIdentifier id_isismtt_at_certHash = id_isismtt_at.branch("13");
-
- /**
- * <pre>
- * 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");
-
- /**
- * Some other information of non-restrictive nature regarding the usage of
- * this certificate. May be used as attribute in atribute certificate or as
- * extension in a certificate.
- *
- * <pre>
- * AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
- * </pre>
- * <p>
- * OID: 1.3.36.8.3.15
- *
- * @see org.bouncycastle.asn1.isismtt.x509.AdditionalInformationSyntax
- */
- static final ASN1ObjectIdentifier id_isismtt_at_additionalInformation = id_isismtt_at.branch("15");
-
- /**
- * Indicates that an attribute certificate exists, which limits the
- * usability of this public key certificate. Whenever verifying a signature
- * with the help of this certificate, the content of the corresponding
- * attribute certificate should be concerned. This extension MUST be
- * included in a PKC, if a corresponding attribute certificate (having the
- * 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
- * </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/core/src/main/java/org/bouncycastle/asn1/isismtt/ocsp/CertHash.java b/core/src/main/java/org/bouncycastle/asn1/isismtt/ocsp/CertHash.java
deleted file mode 100644
index 1791b508..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/isismtt/ocsp/CertHash.java
+++ /dev/null
@@ -1,121 +0,0 @@
-package org.bouncycastle.asn1.isismtt.ocsp;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-/**
- * ISIS-MTT PROFILE: The responder may include this extension in a response to
- * send the hash of the requested certificate to the responder. This hash is
- * cryptographically bound to the certificate and serves as evidence that the
- * certificate is known to the responder (i.e. it has been issued and is present
- * in the directory). Hence, this extension is a means to provide a positive
- * statement of availability as described in T8.[8]. As explained in T13.[1],
- * clients may rely on this information to be able to validate signatures after
- * the expiry of the corresponding certificate. Hence, clients MUST support this
- * extension. If a positive statement of availability is to be delivered, this
- * extension syntax and OID MUST be used.
- * <pre>
- * CertHash ::= SEQUENCE {
- * hashAlgorithm AlgorithmIdentifier,
- * certificateHash OCTET STRING
- * }
- * </pre>
- */
-public class CertHash
- extends ASN1Object
-{
-
- private AlgorithmIdentifier hashAlgorithm;
- private byte[] certificateHash;
-
- public static CertHash getInstance(Object obj)
- {
- if (obj == null || obj instanceof CertHash)
- {
- return (CertHash)obj;
- }
-
- if (obj instanceof ASN1Sequence)
- {
- return new CertHash((ASN1Sequence)obj);
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: "
- + obj.getClass().getName());
- }
-
- /**
- * Constructor from ASN1Sequence.
- * <p/>
- * The sequence is of type CertHash:
- * <p/>
- * <pre>
- * CertHash ::= SEQUENCE {
- * hashAlgorithm AlgorithmIdentifier,
- * certificateHash OCTET STRING
- * }
- * </pre>
- *
- * @param seq The ASN.1 sequence.
- */
- private CertHash(ASN1Sequence seq)
- {
- if (seq.size() != 2)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
- hashAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(0));
- certificateHash = DEROctetString.getInstance(seq.getObjectAt(1)).getOctets();
- }
-
- /**
- * Constructor from a given details.
- *
- * @param hashAlgorithm The hash algorithm identifier.
- * @param certificateHash The hash of the whole DER encoding of the certificate.
- */
- public CertHash(AlgorithmIdentifier hashAlgorithm, byte[] certificateHash)
- {
- this.hashAlgorithm = hashAlgorithm;
- this.certificateHash = new byte[certificateHash.length];
- System.arraycopy(certificateHash, 0, this.certificateHash, 0,
- certificateHash.length);
- }
-
- public AlgorithmIdentifier getHashAlgorithm()
- {
- return hashAlgorithm;
- }
-
- public byte[] getCertificateHash()
- {
- return certificateHash;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <p>
- * Returns:
- * <pre>
- * CertHash ::= SEQUENCE {
- * hashAlgorithm AlgorithmIdentifier,
- * certificateHash OCTET STRING
- * }
- * </pre>
- *
- * @return a DERObject
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector vec = new ASN1EncodableVector();
- vec.add(hashAlgorithm);
- vec.add(new DEROctetString(certificateHash));
- return new DERSequence(vec);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/isismtt/ocsp/RequestedCertificate.java b/core/src/main/java/org/bouncycastle/asn1/isismtt/ocsp/RequestedCertificate.java
deleted file mode 100644
index 5c12016e..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/isismtt/ocsp/RequestedCertificate.java
+++ /dev/null
@@ -1,181 +0,0 @@
-package org.bouncycastle.asn1.isismtt.ocsp;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.Certificate;
-
-/**
- * ISIS-MTT-Optional: The certificate requested by the client by inserting the
- * RetrieveIfAllowed extension in the request, will be returned in this
- * extension.
- * <p>
- * ISIS-MTT-SigG: The signature act allows publishing certificates only then,
- * when the certificate owner gives his explicit permission. Accordingly, there
- * may be �nondownloadable� certificates, about which the responder must provide
- * status information, but MUST NOT include them in the response. Clients may
- * get therefore the following three kind of answers on a single request
- * including the RetrieveIfAllowed extension:
- * <ul>
- * <li> a) the responder supports the extension and is allowed to publish the
- * certificate: RequestedCertificate returned including the requested
- * certificate
- * <li>b) the responder supports the extension but is NOT allowed to publish
- * the certificate: RequestedCertificate returned including an empty OCTET
- * STRING
- * <li>c) the responder does not support the extension: RequestedCertificate is
- * not included in the response
- * </ul>
- * Clients requesting RetrieveIfAllowed MUST be able to handle these cases. If
- * any of the OCTET STRING options is used, it MUST contain the DER encoding of
- * the requested certificate.
- * <pre>
- * RequestedCertificate ::= CHOICE {
- * Certificate Certificate,
- * publicKeyCertificate [0] EXPLICIT OCTET STRING,
- * attributeCertificate [1] EXPLICIT OCTET STRING
- * }
- * </pre>
- */
-public class RequestedCertificate
- extends ASN1Object
- implements ASN1Choice
-{
- public static final int certificate = -1;
- public static final int publicKeyCertificate = 0;
- public static final int attributeCertificate = 1;
-
- private Certificate cert;
- private byte[] publicKeyCert;
- private byte[] attributeCert;
-
- public static RequestedCertificate getInstance(Object obj)
- {
- if (obj == null || obj instanceof RequestedCertificate)
- {
- return (RequestedCertificate)obj;
- }
-
- if (obj instanceof ASN1Sequence)
- {
- return new RequestedCertificate(Certificate.getInstance(obj));
- }
- if (obj instanceof ASN1TaggedObject)
- {
- return new RequestedCertificate((ASN1TaggedObject)obj);
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: "
- + obj.getClass().getName());
- }
-
- public static RequestedCertificate getInstance(ASN1TaggedObject obj, boolean explicit)
- {
- if (!explicit)
- {
- throw new IllegalArgumentException("choice item must be explicitly tagged");
- }
-
- return getInstance(obj.getObject());
- }
-
- private RequestedCertificate(ASN1TaggedObject tagged)
- {
- if (tagged.getTagNo() == publicKeyCertificate)
- {
- publicKeyCert = ASN1OctetString.getInstance(tagged, true).getOctets();
- }
- else if (tagged.getTagNo() == attributeCertificate)
- {
- attributeCert = ASN1OctetString.getInstance(tagged, true).getOctets();
- }
- else
- {
- throw new IllegalArgumentException("unknown tag number: " + tagged.getTagNo());
- }
- }
-
- /**
- * Constructor from a given details.
- * <p>
- * Only one parameter can be given. All other must be <code>null</code>.
- *
- * @param certificate Given as Certificate
- */
- public RequestedCertificate(Certificate certificate)
- {
- this.cert = certificate;
- }
-
- public RequestedCertificate(int type, byte[] certificateOctets)
- {
- this(new DERTaggedObject(type, new DEROctetString(certificateOctets)));
- }
-
- public int getType()
- {
- if (cert != null)
- {
- return certificate;
- }
- if (publicKeyCert != null)
- {
- return publicKeyCertificate;
- }
- return attributeCertificate;
- }
-
- public byte[] getCertificateBytes()
- {
- if (cert != null)
- {
- try
- {
- return cert.getEncoded();
- }
- catch (IOException e)
- {
- throw new IllegalStateException("can't decode certificate: " + e);
- }
- }
- if (publicKeyCert != null)
- {
- return publicKeyCert;
- }
- return attributeCert;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <p>
- * Returns:
- * <pre>
- * RequestedCertificate ::= CHOICE {
- * Certificate Certificate,
- * publicKeyCertificate [0] EXPLICIT OCTET STRING,
- * attributeCertificate [1] EXPLICIT OCTET STRING
- * }
- * </pre>
- *
- * @return a DERObject
- */
- public ASN1Primitive toASN1Primitive()
- {
- if (publicKeyCert != null)
- {
- return new DERTaggedObject(0, new DEROctetString(publicKeyCert));
- }
- if (attributeCert != null)
- {
- return new DERTaggedObject(1, new DEROctetString(attributeCert));
- }
- return cert.toASN1Primitive();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/AdditionalInformationSyntax.java b/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/AdditionalInformationSyntax.java
deleted file mode 100644
index 55c7d43f..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/AdditionalInformationSyntax.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package org.bouncycastle.asn1.isismtt.x509;
-
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.x500.DirectoryString;
-
-/**
- * Some other information of non-restrictive nature regarding the usage of this
- * certificate.
- *
- * <pre>
- * AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
- * </pre>
- */
-public class AdditionalInformationSyntax
- extends ASN1Object
-{
- private DirectoryString information;
-
- public static AdditionalInformationSyntax getInstance(Object obj)
- {
- if (obj instanceof AdditionalInformationSyntax)
- {
- return (AdditionalInformationSyntax)obj;
- }
-
- if (obj != null)
- {
- return new AdditionalInformationSyntax(DirectoryString.getInstance(obj));
- }
-
- return null;
- }
-
- private AdditionalInformationSyntax(DirectoryString information)
- {
- this.information = information;
- }
-
- /**
- * Constructor from a given details.
- *
- * @param information The describtion of the information.
- */
- public AdditionalInformationSyntax(String information)
- {
- this(new DirectoryString(information));
- }
-
- public DirectoryString getInformation()
- {
- return information;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <p>
- * Returns:
- * <pre>
- * AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
- * </pre>
- *
- * @return a DERObject
- */
- public ASN1Primitive toASN1Primitive()
- {
- return information.toASN1Primitive();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/AdmissionSyntax.java b/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/AdmissionSyntax.java
deleted file mode 100644
index 88bb7411..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/AdmissionSyntax.java
+++ /dev/null
@@ -1,276 +0,0 @@
-package org.bouncycastle.asn1.isismtt.x509;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.GeneralName;
-
-/**
- * Attribute to indicate admissions to certain professions.
- *
- * <pre>
- * AdmissionSyntax ::= SEQUENCE
- * {
- * admissionAuthority GeneralName OPTIONAL,
- * contentsOfAdmissions SEQUENCE OF Admissions
- * }
- *
- * Admissions ::= SEQUENCE
- * {
- * admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
- * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
- * professionInfos SEQUENCE OF ProfessionInfo
- * }
- *
- * NamingAuthority ::= SEQUENCE
- * {
- * namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
- * namingAuthorityUrl IA5String OPTIONAL,
- * namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
- * }
- *
- * ProfessionInfo ::= SEQUENCE
- * {
- * namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
- * professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
- * professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
- * registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
- * addProfessionInfo OCTET STRING OPTIONAL
- * }
- * </pre>
- * <p>
- * ISIS-MTT PROFILE: The relatively complex structure of AdmissionSyntax
- * supports the following concepts and requirements:
- * <ul>
- * <li> External institutions (e.g. professional associations, chambers, unions,
- * administrative bodies, companies, etc.), which are responsible for granting
- * and verifying professional admissions, are indicated by means of the data
- * field admissionAuthority. An admission authority is indicated by a
- * GeneralName object. Here an X.501 directory name (distinguished name) can be
- * indicated in the field directoryName, a URL address can be indicated in the
- * field uniformResourceIdentifier, and an object identifier can be indicated in
- * the field registeredId.
- * <li> The names of authorities which are responsible for the administration of
- * title registers are indicated in the data field namingAuthority. The name of
- * the authority can be identified by an object identifier in the field
- * namingAuthorityId, by means of a text string in the field
- * namingAuthorityText, by means of a URL address in the field
- * namingAuthorityUrl, or by a combination of them. For example, the text string
- * can contain the name of the authority, the country and the name of the title
- * register. The URL-option refers to a web page which contains lists with
- * �officially� registered professions (text and possibly OID) as well as
- * further information on these professions. Object identifiers for the
- * component namingAuthorityId are grouped under the OID-branch
- * id-isis-at-namingAuthorities and must be applied for.
- * <li>See
- * http://www.teletrust.de/anwend.asp?Id=30200&amp;Sprache=E_&amp;HomePG=0 for
- * an application form and http://www.teletrust.de/links.asp?id=30220,11
- * for an overview of registered naming authorities.
- * <li> By means of the data type ProfessionInfo certain professions,
- * specializations, disciplines, fields of activity, etc. are identified. A
- * profession is represented by one or more text strings, resp. profession OIDs
- * in the fields professionItems and professionOIDs and by a registration number
- * in the field registrationNumber. An indication in text form must always be
- * present, whereas the other indications are optional. The component
- * addProfessionInfo may contain additional applicationspecific information in
- * DER-encoded form.
- * </ul>
- * <p>
- * By means of different namingAuthority-OIDs or profession OIDs hierarchies of
- * professions, specializations, disciplines, fields of activity, etc. can be
- * expressed. The issuing admission authority should always be indicated (field
- * admissionAuthority), whenever a registration number is presented. Still,
- * information on admissions can be given without indicating an admission or a
- * naming authority by the exclusive use of the component professionItems. In
- * this case the certification authority is responsible for the verification of
- * the admission information.
- * <p>
- * This attribute is single-valued. Still, several admissions can be captured in
- * the sequence structure of the component contentsOfAdmissions of
- * AdmissionSyntax or in the component professionInfos of Admissions. The
- * component admissionAuthority of AdmissionSyntax serves as default value for
- * the component admissionAuthority of Admissions. Within the latter component
- * the default value can be overwritten, in case that another authority is
- * responsible. The component namingAuthority of Admissions serves as a default
- * value for the component namingAuthority of ProfessionInfo. Within the latter
- * component the default value can be overwritten, in case that another naming
- * authority needs to be recorded.
- * <p>
- * The length of the string objects is limited to 128 characters. It is
- * recommended to indicate a namingAuthorityURL in all issued attribute
- * certificates. If a namingAuthorityURL is indicated, the field professionItems
- * of ProfessionInfo should contain only registered titles. If the field
- * professionOIDs exists, it has to contain the OIDs of the professions listed
- * in professionItems in the same order. In general, the field professionInfos
- * should contain only one entry, unless the admissions that are to be listed
- * are logically connected (e.g. they have been issued under the same admission
- * number).
- *
- * @see org.bouncycastle.asn1.isismtt.x509.Admissions
- * @see org.bouncycastle.asn1.isismtt.x509.ProfessionInfo
- * @see org.bouncycastle.asn1.isismtt.x509.NamingAuthority
- */
-public class AdmissionSyntax
- extends ASN1Object
-{
-
- private GeneralName admissionAuthority;
-
- private ASN1Sequence contentsOfAdmissions;
-
- public static AdmissionSyntax getInstance(Object obj)
- {
- if (obj == null || obj instanceof AdmissionSyntax)
- {
- return (AdmissionSyntax)obj;
- }
-
- if (obj instanceof ASN1Sequence)
- {
- return new AdmissionSyntax((ASN1Sequence)obj);
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: "
- + obj.getClass().getName());
- }
-
- /**
- * Constructor from ASN1Sequence.
- * <p/>
- * The sequence is of type ProcurationSyntax:
- * <p/>
- * <pre>
- * AdmissionSyntax ::= SEQUENCE
- * {
- * admissionAuthority GeneralName OPTIONAL,
- * contentsOfAdmissions SEQUENCE OF Admissions
- * }
- * <p/>
- * Admissions ::= SEQUENCE
- * {
- * admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
- * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
- * professionInfos SEQUENCE OF ProfessionInfo
- * }
- * <p/>
- * NamingAuthority ::= SEQUENCE
- * {
- * namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
- * namingAuthorityUrl IA5String OPTIONAL,
- * namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
- * }
- * <p/>
- * ProfessionInfo ::= SEQUENCE
- * {
- * namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
- * professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
- * professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
- * registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
- * addProfessionInfo OCTET STRING OPTIONAL
- * }
- * </pre>
- *
- * @param seq The ASN.1 sequence.
- */
- private AdmissionSyntax(ASN1Sequence seq)
- {
- switch (seq.size())
- {
- case 1:
- contentsOfAdmissions = DERSequence.getInstance(seq.getObjectAt(0));
- break;
- case 2:
- admissionAuthority = GeneralName.getInstance(seq.getObjectAt(0));
- contentsOfAdmissions = DERSequence.getInstance(seq.getObjectAt(1));
- break;
- default:
- throw new IllegalArgumentException("Bad sequence size: " + seq.size());
- }
- }
-
- /**
- * Constructor from given details.
- *
- * @param admissionAuthority The admission authority.
- * @param contentsOfAdmissions The admissions.
- */
- public AdmissionSyntax(GeneralName admissionAuthority, ASN1Sequence contentsOfAdmissions)
- {
- this.admissionAuthority = admissionAuthority;
- this.contentsOfAdmissions = contentsOfAdmissions;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <p>
- * Returns:
- * <pre>
- * AdmissionSyntax ::= SEQUENCE
- * {
- * admissionAuthority GeneralName OPTIONAL,
- * contentsOfAdmissions SEQUENCE OF Admissions
- * }
- *
- * Admissions ::= SEQUENCE
- * {
- * admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
- * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
- * professionInfos SEQUENCE OF ProfessionInfo
- * }
- *
- * NamingAuthority ::= SEQUENCE
- * {
- * namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
- * namingAuthorityUrl IA5String OPTIONAL,
- * namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
- * }
- *
- * ProfessionInfo ::= SEQUENCE
- * {
- * namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
- * professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
- * professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
- * registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
- * addProfessionInfo OCTET STRING OPTIONAL
- * }
- * </pre>
- *
- * @return a DERObject
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector vec = new ASN1EncodableVector();
- if (admissionAuthority != null)
- {
- vec.add(admissionAuthority);
- }
- vec.add(contentsOfAdmissions);
- return new DERSequence(vec);
- }
-
- /**
- * @return Returns the admissionAuthority if present, null otherwise.
- */
- public GeneralName getAdmissionAuthority()
- {
- return admissionAuthority;
- }
-
- /**
- * @return Returns the contentsOfAdmissions.
- */
- public Admissions[] getContentsOfAdmissions()
- {
- Admissions[] admissions = new Admissions[contentsOfAdmissions.size()];
- int count = 0;
- for (Enumeration e = contentsOfAdmissions.getObjects(); e.hasMoreElements();)
- {
- admissions[count++] = Admissions.getInstance(e.nextElement());
- }
- return admissions;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/Admissions.java b/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/Admissions.java
deleted file mode 100644
index 48a3e470..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/Admissions.java
+++ /dev/null
@@ -1,185 +0,0 @@
-package org.bouncycastle.asn1.isismtt.x509;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.GeneralName;
-
-/**
- * An Admissions structure.
- * <pre>
- * Admissions ::= SEQUENCE
- * {
- * admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
- * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
- * professionInfos SEQUENCE OF ProfessionInfo
- * }
- * </pre>
- *
- * @see org.bouncycastle.asn1.isismtt.x509.AdmissionSyntax
- * @see org.bouncycastle.asn1.isismtt.x509.ProfessionInfo
- * @see org.bouncycastle.asn1.isismtt.x509.NamingAuthority
- */
-public class Admissions
- extends ASN1Object
-{
-
- private GeneralName admissionAuthority;
-
- private NamingAuthority namingAuthority;
-
- private ASN1Sequence professionInfos;
-
- public static Admissions getInstance(Object obj)
- {
- if (obj == null || obj instanceof Admissions)
- {
- return (Admissions)obj;
- }
-
- if (obj instanceof ASN1Sequence)
- {
- return new Admissions((ASN1Sequence)obj);
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * Constructor from ASN1Sequence.
- * <p/>
- * The sequence is of type ProcurationSyntax:
- * <p/>
- * <pre>
- * Admissions ::= SEQUENCE
- * {
- * admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
- * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
- * professionInfos SEQUENCE OF ProfessionInfo
- * }
- * </pre>
- *
- * @param seq The ASN.1 sequence.
- */
- private Admissions(ASN1Sequence seq)
- {
- if (seq.size() > 3)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
- Enumeration e = seq.getObjects();
-
- ASN1Encodable o = (ASN1Encodable)e.nextElement();
- if (o instanceof ASN1TaggedObject)
- {
- switch (((ASN1TaggedObject)o).getTagNo())
- {
- case 0:
- admissionAuthority = GeneralName.getInstance((ASN1TaggedObject)o, true);
- break;
- case 1:
- namingAuthority = NamingAuthority.getInstance((ASN1TaggedObject)o, true);
- break;
- default:
- throw new IllegalArgumentException("Bad tag number: " + ((ASN1TaggedObject)o).getTagNo());
- }
- o = (ASN1Encodable)e.nextElement();
- }
- if (o instanceof ASN1TaggedObject)
- {
- switch (((ASN1TaggedObject)o).getTagNo())
- {
- case 1:
- namingAuthority = NamingAuthority.getInstance((ASN1TaggedObject)o, true);
- break;
- default:
- throw new IllegalArgumentException("Bad tag number: " + ((ASN1TaggedObject)o).getTagNo());
- }
- o = (ASN1Encodable)e.nextElement();
- }
- professionInfos = ASN1Sequence.getInstance(o);
- if (e.hasMoreElements())
- {
- throw new IllegalArgumentException("Bad object encountered: "
- + e.nextElement().getClass());
- }
- }
-
- /**
- * Constructor from a given details.
- * <p>
- * Parameter <code>professionInfos</code> is mandatory.
- *
- * @param admissionAuthority The admission authority.
- * @param namingAuthority The naming authority.
- * @param professionInfos The profession infos.
- */
- public Admissions(GeneralName admissionAuthority,
- NamingAuthority namingAuthority, ProfessionInfo[] professionInfos)
- {
- this.admissionAuthority = admissionAuthority;
- this.namingAuthority = namingAuthority;
- this.professionInfos = new DERSequence(professionInfos);
- }
-
- public GeneralName getAdmissionAuthority()
- {
- return admissionAuthority;
- }
-
- public NamingAuthority getNamingAuthority()
- {
- return namingAuthority;
- }
-
- public ProfessionInfo[] getProfessionInfos()
- {
- ProfessionInfo[] infos = new ProfessionInfo[professionInfos.size()];
- int count = 0;
- for (Enumeration e = professionInfos.getObjects(); e.hasMoreElements();)
- {
- infos[count++] = ProfessionInfo.getInstance(e.nextElement());
- }
- return infos;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <p>
- * Returns:
- * <pre>
- * Admissions ::= SEQUENCE
- * {
- * admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
- * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
- * professionInfos SEQUENCE OF ProfessionInfo
- * }
- * </pre>
- *
- * @return an ASN1Primitive
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector vec = new ASN1EncodableVector();
-
- if (admissionAuthority != null)
- {
- vec.add(new DERTaggedObject(true, 0, admissionAuthority));
- }
- if (namingAuthority != null)
- {
- vec.add(new DERTaggedObject(true, 1, namingAuthority));
- }
- vec.add(professionInfos);
-
- return new DERSequence(vec);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/DeclarationOfMajority.java b/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/DeclarationOfMajority.java
deleted file mode 100644
index 987c5907..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/DeclarationOfMajority.java
+++ /dev/null
@@ -1,163 +0,0 @@
-package org.bouncycastle.asn1.isismtt.x509;
-
-import org.bouncycastle.asn1.ASN1Boolean;
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERPrintableString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * A declaration of majority.
- *
- * <pre>
- * DeclarationOfMajoritySyntax ::= CHOICE
- * {
- * notYoungerThan [0] IMPLICIT INTEGER,
- * fullAgeAtCountry [1] IMPLICIT SEQUENCE
- * {
- * fullAge BOOLEAN DEFAULT TRUE,
- * country PrintableString (SIZE(2))
- * }
- * dateOfBirth [2] IMPLICIT GeneralizedTime
- * }
- * </pre>
- * <p>
- * fullAgeAtCountry indicates the majority of the owner with respect to the laws
- * of a specific country.
- */
-public class DeclarationOfMajority
- extends ASN1Object
- implements ASN1Choice
-{
- public static final int notYoungerThan = 0;
- public static final int fullAgeAtCountry = 1;
- public static final int dateOfBirth = 2;
-
- private ASN1TaggedObject declaration;
-
- public DeclarationOfMajority(int notYoungerThan)
- {
- declaration = new DERTaggedObject(false, 0, new ASN1Integer(notYoungerThan));
- }
-
- public DeclarationOfMajority(boolean fullAge, String country)
- {
- if (country.length() > 2)
- {
- throw new IllegalArgumentException("country can only be 2 characters");
- }
-
- if (fullAge)
- {
- declaration = new DERTaggedObject(false, 1, new DERSequence(new DERPrintableString(country, true)));
- }
- else
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(ASN1Boolean.FALSE);
- v.add(new DERPrintableString(country, true));
-
- declaration = new DERTaggedObject(false, 1, new DERSequence(v));
- }
- }
-
- public DeclarationOfMajority(ASN1GeneralizedTime dateOfBirth)
- {
- declaration = new DERTaggedObject(false, 2, dateOfBirth);
- }
-
- public static DeclarationOfMajority getInstance(Object obj)
- {
- if (obj == null || obj instanceof DeclarationOfMajority)
- {
- return (DeclarationOfMajority)obj;
- }
-
- if (obj instanceof ASN1TaggedObject)
- {
- return new DeclarationOfMajority((ASN1TaggedObject)obj);
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: "
- + obj.getClass().getName());
- }
-
- private DeclarationOfMajority(ASN1TaggedObject o)
- {
- if (o.getTagNo() > 2)
- {
- throw new IllegalArgumentException("Bad tag number: " + o.getTagNo());
- }
- declaration = o;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <p>
- * Returns:
- * <pre>
- * DeclarationOfMajoritySyntax ::= CHOICE
- * {
- * notYoungerThan [0] IMPLICIT INTEGER,
- * fullAgeAtCountry [1] IMPLICIT SEQUENCE
- * {
- * fullAge BOOLEAN DEFAULT TRUE,
- * country PrintableString (SIZE(2))
- * }
- * dateOfBirth [2] IMPLICIT GeneralizedTime
- * }
- * </pre>
- *
- * @return a DERObject
- */
- public ASN1Primitive toASN1Primitive()
- {
- return declaration;
- }
-
- public int getType()
- {
- return declaration.getTagNo();
- }
-
- /**
- * @return notYoungerThan if that's what we are, -1 otherwise
- */
- public int notYoungerThan()
- {
- if (declaration.getTagNo() != 0)
- {
- return -1;
- }
-
- return ASN1Integer.getInstance(declaration, false).getValue().intValue();
- }
-
- public ASN1Sequence fullAgeAtCountry()
- {
- if (declaration.getTagNo() != 1)
- {
- return null;
- }
-
- return ASN1Sequence.getInstance(declaration, false);
- }
-
- public ASN1GeneralizedTime getDateOfBirth()
- {
- if (declaration.getTagNo() != 2)
- {
- return null;
- }
-
- return ASN1GeneralizedTime.getInstance(declaration, false);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/MonetaryLimit.java b/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/MonetaryLimit.java
deleted file mode 100644
index 7425287e..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/MonetaryLimit.java
+++ /dev/null
@@ -1,128 +0,0 @@
-package org.bouncycastle.asn1.isismtt.x509;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-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.DERPrintableString;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * Monetary limit for transactions. The QcEuMonetaryLimit QC statement MUST be
- * used in new certificates in place of the extension/attribute MonetaryLimit
- * since January 1, 2004. For the sake of backward compatibility with
- * certificates already in use, components SHOULD support MonetaryLimit (as well
- * as QcEuLimitValue).
- * <p>
- * Indicates a monetary limit within which the certificate holder is authorized
- * to act. (This value DOES NOT express a limit on the liability of the
- * certification authority).
- * <pre>
- * MonetaryLimitSyntax ::= SEQUENCE
- * {
- * currency PrintableString (SIZE(3)),
- * amount INTEGER,
- * exponent INTEGER
- * }
- * </pre>
- * <p>
- * currency must be the ISO code.
- * <p>
- * value = amount�10*exponent
- */
-public class MonetaryLimit
- extends ASN1Object
-{
- DERPrintableString currency;
- ASN1Integer amount;
- ASN1Integer exponent;
-
- public static MonetaryLimit getInstance(Object obj)
- {
- if (obj == null || obj instanceof MonetaryLimit)
- {
- return (MonetaryLimit)obj;
- }
-
- if (obj instanceof ASN1Sequence)
- {
- return new MonetaryLimit(ASN1Sequence.getInstance(obj));
- }
-
- throw new IllegalArgumentException("unknown object in getInstance");
- }
-
- private MonetaryLimit(ASN1Sequence seq)
- {
- if (seq.size() != 3)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
- Enumeration e = seq.getObjects();
- currency = DERPrintableString.getInstance(e.nextElement());
- amount = ASN1Integer.getInstance(e.nextElement());
- exponent = ASN1Integer.getInstance(e.nextElement());
- }
-
- /**
- * Constructor from a given details.
- * <p>
- * value = amount�10^exponent
- *
- * @param currency The currency. Must be the ISO code.
- * @param amount The amount
- * @param exponent The exponent
- */
- public MonetaryLimit(String currency, int amount, int exponent)
- {
- this.currency = new DERPrintableString(currency, true);
- this.amount = new ASN1Integer(amount);
- this.exponent = new ASN1Integer(exponent);
- }
-
- public String getCurrency()
- {
- return currency.getString();
- }
-
- public BigInteger getAmount()
- {
- return amount.getValue();
- }
-
- public BigInteger getExponent()
- {
- return exponent.getValue();
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <p>
- * Returns:
- * <pre>
- * MonetaryLimitSyntax ::= SEQUENCE
- * {
- * currency PrintableString (SIZE(3)),
- * amount INTEGER,
- * exponent INTEGER
- * }
- * </pre>
- *
- * @return a DERObject
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector seq = new ASN1EncodableVector();
- seq.add(currency);
- seq.add(amount);
- seq.add(exponent);
-
- return new DERSequence(seq);
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/NamingAuthority.java b/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/NamingAuthority.java
deleted file mode 100644
index 17162649..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/NamingAuthority.java
+++ /dev/null
@@ -1,224 +0,0 @@
-package org.bouncycastle.asn1.isismtt.x509;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1String;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.isismtt.ISISMTTObjectIdentifiers;
-import org.bouncycastle.asn1.x500.DirectoryString;
-
-/**
- * Names of authorities which are responsible for the administration of title
- * registers.
- *
- * <pre>
- * NamingAuthority ::= SEQUENCE
- * {
- * namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
- * namingAuthorityUrl IA5String OPTIONAL,
- * namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
- * }
- * </pre>
- * @see org.bouncycastle.asn1.isismtt.x509.AdmissionSyntax
- *
- */
-public class NamingAuthority
- extends ASN1Object
-{
-
- /**
- * Profession OIDs should always be defined under the OID branch of the
- * responsible naming authority. At the time of this writing, the work group
- * �Recht, Wirtschaft, Steuern� (�Law, Economy, Taxes�) is registered as the
- * first naming authority under the OID id-isismtt-at-namingAuthorities.
- */
- public static final ASN1ObjectIdentifier id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern =
- new ASN1ObjectIdentifier(ISISMTTObjectIdentifiers.id_isismtt_at_namingAuthorities + ".1");
-
- private ASN1ObjectIdentifier namingAuthorityId;
- private String namingAuthorityUrl;
- private DirectoryString namingAuthorityText;
-
- public static NamingAuthority getInstance(Object obj)
- {
- if (obj == null || obj instanceof NamingAuthority)
- {
- return (NamingAuthority)obj;
- }
-
- if (obj instanceof ASN1Sequence)
- {
- return new NamingAuthority((ASN1Sequence)obj);
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: "
- + obj.getClass().getName());
- }
-
- public static NamingAuthority getInstance(ASN1TaggedObject obj, boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- /**
- * Constructor from ASN1Sequence.
- * <p/>
- * <p/>
- * <pre>
- * NamingAuthority ::= SEQUENCE
- * {
- * namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
- * namingAuthorityUrl IA5String OPTIONAL,
- * namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
- * }
- * </pre>
- *
- * @param seq The ASN.1 sequence.
- */
- private NamingAuthority(ASN1Sequence seq)
- {
-
- if (seq.size() > 3)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
-
- Enumeration e = seq.getObjects();
-
- if (e.hasMoreElements())
- {
- ASN1Encodable o = (ASN1Encodable)e.nextElement();
- if (o instanceof ASN1ObjectIdentifier)
- {
- namingAuthorityId = (ASN1ObjectIdentifier)o;
- }
- else if (o instanceof DERIA5String)
- {
- namingAuthorityUrl = DERIA5String.getInstance(o).getString();
- }
- else if (o instanceof ASN1String)
- {
- namingAuthorityText = DirectoryString.getInstance(o);
- }
- else
- {
- throw new IllegalArgumentException("Bad object encountered: "
- + o.getClass());
- }
- }
- if (e.hasMoreElements())
- {
- ASN1Encodable o = (ASN1Encodable)e.nextElement();
- if (o instanceof DERIA5String)
- {
- namingAuthorityUrl = DERIA5String.getInstance(o).getString();
- }
- else if (o instanceof ASN1String)
- {
- namingAuthorityText = DirectoryString.getInstance(o);
- }
- else
- {
- throw new IllegalArgumentException("Bad object encountered: "
- + o.getClass());
- }
- }
- if (e.hasMoreElements())
- {
- ASN1Encodable o = (ASN1Encodable)e.nextElement();
- if (o instanceof ASN1String)
- {
- namingAuthorityText = DirectoryString.getInstance(o);
- }
- else
- {
- throw new IllegalArgumentException("Bad object encountered: "
- + o.getClass());
- }
-
- }
- }
-
- /**
- * @return Returns the namingAuthorityId.
- */
- public ASN1ObjectIdentifier getNamingAuthorityId()
- {
- return namingAuthorityId;
- }
-
- /**
- * @return Returns the namingAuthorityText.
- */
- public DirectoryString getNamingAuthorityText()
- {
- return namingAuthorityText;
- }
-
- /**
- * @return Returns the namingAuthorityUrl.
- */
- public String getNamingAuthorityUrl()
- {
- return namingAuthorityUrl;
- }
-
- /**
- * Constructor from given details.
- * <p>
- * All parameters can be combined.
- *
- * @param namingAuthorityId ObjectIdentifier for naming authority.
- * @param namingAuthorityUrl URL for naming authority.
- * @param namingAuthorityText Textual representation of naming authority.
- */
- public NamingAuthority(ASN1ObjectIdentifier namingAuthorityId,
- String namingAuthorityUrl, DirectoryString namingAuthorityText)
- {
- this.namingAuthorityId = namingAuthorityId;
- this.namingAuthorityUrl = namingAuthorityUrl;
- this.namingAuthorityText = namingAuthorityText;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <p>
- * Returns:
- * <pre>
- * NamingAuthority ::= SEQUENCE
- * {
- * namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
- * namingAuthorityUrl IA5String OPTIONAL,
- * namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
- * }
- * </pre>
- *
- * @return a DERObject
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector vec = new ASN1EncodableVector();
- if (namingAuthorityId != null)
- {
- vec.add(namingAuthorityId);
- }
- if (namingAuthorityUrl != null)
- {
- vec.add(new DERIA5String(namingAuthorityUrl, true));
- }
- if (namingAuthorityText != null)
- {
- vec.add(namingAuthorityText);
- }
- return new DERSequence(vec);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/ProcurationSyntax.java b/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/ProcurationSyntax.java
deleted file mode 100644
index b6ab3451..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/ProcurationSyntax.java
+++ /dev/null
@@ -1,237 +0,0 @@
-package org.bouncycastle.asn1.isismtt.x509;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERPrintableString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x500.DirectoryString;
-import org.bouncycastle.asn1.x509.GeneralName;
-import org.bouncycastle.asn1.x509.IssuerSerial;
-
-/**
- * Attribute to indicate that the certificate holder may sign in the name of a
- * third person.
- * <p>
- * ISIS-MTT PROFILE: The corresponding ProcurationSyntax contains either the
- * name of the person who is represented (subcomponent thirdPerson) or a
- * reference to his/her base certificate (in the component signingFor,
- * subcomponent certRef), furthermore the optional components country and
- * typeSubstitution to indicate the country whose laws apply, and respectively
- * the type of procuration (e.g. manager, procuration, custody).
- * <p>
- * ISIS-MTT PROFILE: The GeneralName MUST be of type directoryName and MAY only
- * contain: - RFC3039 attributes, except pseudonym (countryName, commonName,
- * surname, givenName, serialNumber, organizationName, organizationalUnitName,
- * stateOrProvincename, localityName, postalAddress) and - SubjectDirectoryName
- * attributes (title, dateOfBirth, placeOfBirth, gender, countryOfCitizenship,
- * countryOfResidence and NameAtBirth).
- *
- * <pre>
- * ProcurationSyntax ::= SEQUENCE {
- * country [1] EXPLICIT PrintableString(SIZE(2)) OPTIONAL,
- * typeOfSubstitution [2] EXPLICIT DirectoryString (SIZE(1..128)) OPTIONAL,
- * signingFor [3] EXPLICIT SigningFor
- * }
- *
- * SigningFor ::= CHOICE
- * {
- * thirdPerson GeneralName,
- * certRef IssuerSerial
- * }
- * </pre>
- *
- */
-public class ProcurationSyntax
- extends ASN1Object
-{
- private String country;
- private DirectoryString typeOfSubstitution;
-
- private GeneralName thirdPerson;
- private IssuerSerial certRef;
-
- public static ProcurationSyntax getInstance(Object obj)
- {
- if (obj == null || obj instanceof ProcurationSyntax)
- {
- return (ProcurationSyntax)obj;
- }
-
- if (obj instanceof ASN1Sequence)
- {
- return new ProcurationSyntax((ASN1Sequence)obj);
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: "
- + obj.getClass().getName());
- }
-
- /**
- * Constructor from ASN1Sequence.
- * <p/>
- * The sequence is of type ProcurationSyntax:
- * <p/>
- * <pre>
- * ProcurationSyntax ::= SEQUENCE {
- * country [1] EXPLICIT PrintableString(SIZE(2)) OPTIONAL,
- * typeOfSubstitution [2] EXPLICIT DirectoryString (SIZE(1..128)) OPTIONAL,
- * signingFor [3] EXPLICIT SigningFor
- * }
- * <p/>
- * SigningFor ::= CHOICE
- * {
- * thirdPerson GeneralName,
- * certRef IssuerSerial
- * }
- * </pre>
- *
- * @param seq The ASN.1 sequence.
- */
- private ProcurationSyntax(ASN1Sequence seq)
- {
- if (seq.size() < 1 || seq.size() > 3)
- {
- throw new IllegalArgumentException("Bad sequence size: " + seq.size());
- }
- Enumeration e = seq.getObjects();
-
- while (e.hasMoreElements())
- {
- ASN1TaggedObject o = ASN1TaggedObject.getInstance(e.nextElement());
- switch (o.getTagNo())
- {
- case 1:
- country = DERPrintableString.getInstance(o, true).getString();
- break;
- case 2:
- typeOfSubstitution = DirectoryString.getInstance(o, true);
- break;
- case 3:
- ASN1Encodable signingFor = o.getObject();
- if (signingFor instanceof ASN1TaggedObject)
- {
- thirdPerson = GeneralName.getInstance(signingFor);
- }
- else
- {
- certRef = IssuerSerial.getInstance(signingFor);
- }
- break;
- default:
- throw new IllegalArgumentException("Bad tag number: " + o.getTagNo());
- }
- }
- }
-
- /**
- * Constructor from a given details.
- * <p>
- * Either <code>generalName</code> or <code>certRef</code> MUST be
- * <code>null</code>.
- *
- * @param country The country code whose laws apply.
- * @param typeOfSubstitution The type of procuration.
- * @param certRef Reference to certificate of the person who is represented.
- */
- public ProcurationSyntax(
- String country,
- DirectoryString typeOfSubstitution,
- IssuerSerial certRef)
- {
- this.country = country;
- this.typeOfSubstitution = typeOfSubstitution;
- this.thirdPerson = null;
- this.certRef = certRef;
- }
-
- /**
- * Constructor from a given details.
- * <p>
- * Either <code>generalName</code> or <code>certRef</code> MUST be
- * <code>null</code>.
- *
- * @param country The country code whose laws apply.
- * @param typeOfSubstitution The type of procuration.
- * @param thirdPerson The GeneralName of the person who is represented.
- */
- public ProcurationSyntax(
- String country,
- DirectoryString typeOfSubstitution,
- GeneralName thirdPerson)
- {
- this.country = country;
- this.typeOfSubstitution = typeOfSubstitution;
- this.thirdPerson = thirdPerson;
- this.certRef = null;
- }
-
- public String getCountry()
- {
- return country;
- }
-
- public DirectoryString getTypeOfSubstitution()
- {
- return typeOfSubstitution;
- }
-
- public GeneralName getThirdPerson()
- {
- return thirdPerson;
- }
-
- public IssuerSerial getCertRef()
- {
- return certRef;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <p>
- * Returns:
- * <pre>
- * ProcurationSyntax ::= SEQUENCE {
- * country [1] EXPLICIT PrintableString(SIZE(2)) OPTIONAL,
- * typeOfSubstitution [2] EXPLICIT DirectoryString (SIZE(1..128)) OPTIONAL,
- * signingFor [3] EXPLICIT SigningFor
- * }
- *
- * SigningFor ::= CHOICE
- * {
- * thirdPerson GeneralName,
- * certRef IssuerSerial
- * }
- * </pre>
- *
- * @return a DERObject
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector vec = new ASN1EncodableVector();
- if (country != null)
- {
- vec.add(new DERTaggedObject(true, 1, new DERPrintableString(country, true)));
- }
- if (typeOfSubstitution != null)
- {
- vec.add(new DERTaggedObject(true, 2, typeOfSubstitution));
- }
- if (thirdPerson != null)
- {
- vec.add(new DERTaggedObject(true, 3, thirdPerson));
- }
- else
- {
- vec.add(new DERTaggedObject(true, 3, certRef));
- }
-
- return new DERSequence(vec);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/ProfessionInfo.java b/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/ProfessionInfo.java
deleted file mode 100644
index 67737f69..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/ProfessionInfo.java
+++ /dev/null
@@ -1,407 +0,0 @@
-package org.bouncycastle.asn1.isismtt.x509;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERPrintableString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x500.DirectoryString;
-
-/**
- * Professions, specializations, disciplines, fields of activity, etc.
- *
- * <pre>
- * ProfessionInfo ::= SEQUENCE
- * {
- * namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
- * professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
- * professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
- * registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
- * addProfessionInfo OCTET STRING OPTIONAL
- * }
- * </pre>
- *
- * @see org.bouncycastle.asn1.isismtt.x509.AdmissionSyntax
- */
-public class ProfessionInfo
- extends ASN1Object
-{
-
- /**
- * Rechtsanw�ltin
- */
- public static final ASN1ObjectIdentifier Rechtsanwltin = new ASN1ObjectIdentifier(
- NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".1");
-
- /**
- * Rechtsanwalt
- */
- public static final ASN1ObjectIdentifier Rechtsanwalt = new ASN1ObjectIdentifier(
- NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".2");
-
- /**
- * Rechtsbeistand
- */
- public static final ASN1ObjectIdentifier Rechtsbeistand = new ASN1ObjectIdentifier(
- NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".3");
-
- /**
- * Steuerberaterin
- */
- public static final ASN1ObjectIdentifier Steuerberaterin = new ASN1ObjectIdentifier(
- NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".4");
-
- /**
- * Steuerberater
- */
- public static final ASN1ObjectIdentifier Steuerberater = new ASN1ObjectIdentifier(
- NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".5");
-
- /**
- * Steuerbevollm�chtigte
- */
- public static final ASN1ObjectIdentifier Steuerbevollmchtigte = new ASN1ObjectIdentifier(
- NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".6");
-
- /**
- * Steuerbevollm�chtigter
- */
- public static final ASN1ObjectIdentifier Steuerbevollmchtigter = new ASN1ObjectIdentifier(
- NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".7");
-
- /**
- * Notarin
- */
- public static final ASN1ObjectIdentifier Notarin = new ASN1ObjectIdentifier(
- NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".8");
-
- /**
- * Notar
- */
- public static final ASN1ObjectIdentifier Notar = new ASN1ObjectIdentifier(
- NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".9");
-
- /**
- * Notarvertreterin
- */
- public static final ASN1ObjectIdentifier Notarvertreterin = new ASN1ObjectIdentifier(
- NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".10");
-
- /**
- * Notarvertreter
- */
- public static final ASN1ObjectIdentifier Notarvertreter = new ASN1ObjectIdentifier(
- NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".11");
-
- /**
- * Notariatsverwalterin
- */
- public static final ASN1ObjectIdentifier Notariatsverwalterin = new ASN1ObjectIdentifier(
- NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".12");
-
- /**
- * Notariatsverwalter
- */
- public static final ASN1ObjectIdentifier Notariatsverwalter = new ASN1ObjectIdentifier(
- NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".13");
-
- /**
- * Wirtschaftspr�ferin
- */
- public static final ASN1ObjectIdentifier Wirtschaftsprferin = new ASN1ObjectIdentifier(
- NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".14");
-
- /**
- * Wirtschaftspr�fer
- */
- public static final ASN1ObjectIdentifier Wirtschaftsprfer = new ASN1ObjectIdentifier(
- NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".15");
-
- /**
- * Vereidigte Buchpr�ferin
- */
- public static final ASN1ObjectIdentifier VereidigteBuchprferin = new ASN1ObjectIdentifier(
- NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".16");
-
- /**
- * Vereidigter Buchpr�fer
- */
- public static final ASN1ObjectIdentifier VereidigterBuchprfer = new ASN1ObjectIdentifier(
- NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".17");
-
- /**
- * Patentanw�ltin
- */
- public static final ASN1ObjectIdentifier Patentanwltin = new ASN1ObjectIdentifier(
- NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".18");
-
- /**
- * Patentanwalt
- */
- public static final ASN1ObjectIdentifier Patentanwalt = new ASN1ObjectIdentifier(
- NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".19");
-
- private NamingAuthority namingAuthority;
-
- private ASN1Sequence professionItems;
-
- private ASN1Sequence professionOIDs;
-
- private String registrationNumber;
-
- private ASN1OctetString addProfessionInfo;
-
- public static ProfessionInfo getInstance(Object obj)
- {
- if (obj == null || obj instanceof ProfessionInfo)
- {
- return (ProfessionInfo)obj;
- }
-
- if (obj instanceof ASN1Sequence)
- {
- return new ProfessionInfo((ASN1Sequence)obj);
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: "
- + obj.getClass().getName());
- }
-
- /**
- * Constructor from ASN1Sequence.
- * <p/>
- * <p/>
- * <pre>
- * ProfessionInfo ::= SEQUENCE
- * {
- * namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
- * professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
- * professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
- * registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
- * addProfessionInfo OCTET STRING OPTIONAL
- * }
- * </pre>
- *
- * @param seq The ASN.1 sequence.
- */
- private ProfessionInfo(ASN1Sequence seq)
- {
- if (seq.size() > 5)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
-
- Enumeration e = seq.getObjects();
-
- ASN1Encodable o = (ASN1Encodable)e.nextElement();
-
- if (o instanceof ASN1TaggedObject)
- {
- if (((ASN1TaggedObject)o).getTagNo() != 0)
- {
- throw new IllegalArgumentException("Bad tag number: "
- + ((ASN1TaggedObject)o).getTagNo());
- }
- namingAuthority = NamingAuthority.getInstance((ASN1TaggedObject)o, true);
- o = (ASN1Encodable)e.nextElement();
- }
-
- professionItems = ASN1Sequence.getInstance(o);
-
- if (e.hasMoreElements())
- {
- o = (ASN1Encodable)e.nextElement();
- if (o instanceof ASN1Sequence)
- {
- professionOIDs = ASN1Sequence.getInstance(o);
- }
- else if (o instanceof DERPrintableString)
- {
- registrationNumber = DERPrintableString.getInstance(o).getString();
- }
- else if (o instanceof ASN1OctetString)
- {
- addProfessionInfo = ASN1OctetString.getInstance(o);
- }
- else
- {
- throw new IllegalArgumentException("Bad object encountered: "
- + o.getClass());
- }
- }
- if (e.hasMoreElements())
- {
- o = (ASN1Encodable)e.nextElement();
- if (o instanceof DERPrintableString)
- {
- registrationNumber = DERPrintableString.getInstance(o).getString();
- }
- else if (o instanceof DEROctetString)
- {
- addProfessionInfo = (DEROctetString)o;
- }
- else
- {
- throw new IllegalArgumentException("Bad object encountered: "
- + o.getClass());
- }
- }
- if (e.hasMoreElements())
- {
- o = (ASN1Encodable)e.nextElement();
- if (o instanceof DEROctetString)
- {
- addProfessionInfo = (DEROctetString)o;
- }
- else
- {
- throw new IllegalArgumentException("Bad object encountered: "
- + o.getClass());
- }
- }
-
- }
-
- /**
- * Constructor from given details.
- * <p>
- * <code>professionItems</code> is mandatory, all other parameters are
- * optional.
- *
- * @param namingAuthority The naming authority.
- * @param professionItems Directory strings of the profession.
- * @param professionOIDs DERObjectIdentfier objects for the
- * profession.
- * @param registrationNumber Registration number.
- * @param addProfessionInfo Additional infos in encoded form.
- */
- public ProfessionInfo(NamingAuthority namingAuthority,
- DirectoryString[] professionItems, ASN1ObjectIdentifier[] professionOIDs,
- String registrationNumber, ASN1OctetString addProfessionInfo)
- {
- this.namingAuthority = namingAuthority;
- ASN1EncodableVector v = new ASN1EncodableVector();
- for (int i = 0; i != professionItems.length; i++)
- {
- v.add(professionItems[i]);
- }
- this.professionItems = new DERSequence(v);
- if (professionOIDs != null)
- {
- v = new ASN1EncodableVector();
- for (int i = 0; i != professionOIDs.length; i++)
- {
- v.add(professionOIDs[i]);
- }
- this.professionOIDs = new DERSequence(v);
- }
- this.registrationNumber = registrationNumber;
- this.addProfessionInfo = addProfessionInfo;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <p>
- * Returns:
- * <pre>
- * ProfessionInfo ::= SEQUENCE
- * {
- * namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
- * professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
- * professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
- * registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
- * addProfessionInfo OCTET STRING OPTIONAL
- * }
- * </pre>
- *
- * @return a DERObject
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector vec = new ASN1EncodableVector();
- if (namingAuthority != null)
- {
- vec.add(new DERTaggedObject(true, 0, namingAuthority));
- }
- vec.add(professionItems);
- if (professionOIDs != null)
- {
- vec.add(professionOIDs);
- }
- if (registrationNumber != null)
- {
- vec.add(new DERPrintableString(registrationNumber, true));
- }
- if (addProfessionInfo != null)
- {
- vec.add(addProfessionInfo);
- }
- return new DERSequence(vec);
- }
-
- /**
- * @return Returns the addProfessionInfo.
- */
- public ASN1OctetString getAddProfessionInfo()
- {
- return addProfessionInfo;
- }
-
- /**
- * @return Returns the namingAuthority.
- */
- public NamingAuthority getNamingAuthority()
- {
- return namingAuthority;
- }
-
- /**
- * @return Returns the professionItems.
- */
- public DirectoryString[] getProfessionItems()
- {
- DirectoryString[] items = new DirectoryString[professionItems.size()];
- int count = 0;
- for (Enumeration e = professionItems.getObjects(); e.hasMoreElements();)
- {
- items[count++] = DirectoryString.getInstance(e.nextElement());
- }
- return items;
- }
-
- /**
- * @return Returns the professionOIDs.
- */
- public ASN1ObjectIdentifier[] getProfessionOIDs()
- {
- if (professionOIDs == null)
- {
- return new ASN1ObjectIdentifier[0];
- }
- ASN1ObjectIdentifier[] oids = new ASN1ObjectIdentifier[professionOIDs.size()];
- int count = 0;
- for (Enumeration e = professionOIDs.getObjects(); e.hasMoreElements();)
- {
- oids[count++] = ASN1ObjectIdentifier.getInstance(e.nextElement());
- }
- return oids;
- }
-
- /**
- * @return Returns the registrationNumber.
- */
- public String getRegistrationNumber()
- {
- return registrationNumber;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/Restriction.java b/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/Restriction.java
deleted file mode 100644
index 3d06e77b..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/isismtt/x509/Restriction.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.bouncycastle.asn1.isismtt.x509;
-
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.x500.DirectoryString;
-
-/**
- * Some other restriction regarding the usage of this certificate.
- *
- * <pre>
- * RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
- * </pre>
- */
-public class Restriction
- extends ASN1Object
-{
- private DirectoryString restriction;
-
- public static Restriction getInstance(Object obj)
- {
- if (obj instanceof Restriction)
- {
- return (Restriction)obj;
- }
-
- if (obj != null)
- {
- return new Restriction(DirectoryString.getInstance(obj));
- }
-
- return null;
- }
-
- /**
- * Constructor from DirectoryString.
- * <p/>
- * The DirectoryString is of type RestrictionSyntax:
- * <p/>
- * <pre>
- * RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
- * </pre>
- *
- * @param restriction A DirectoryString.
- */
- private Restriction(DirectoryString restriction)
- {
- this.restriction = restriction;
- }
-
- /**
- * Constructor from a given details.
- *
- * @param restriction The describtion of the restriction.
- */
- public Restriction(String restriction)
- {
- this.restriction = new DirectoryString(restriction);
- }
-
- public DirectoryString getRestriction()
- {
- return restriction;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <p>
- * Returns:
- * <pre>
- * RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
- * </pre>
- *
- * @return a DERObject
- */
- public ASN1Primitive toASN1Primitive()
- {
- return restriction.toASN1Primitive();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/kisa/KISAObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/kisa/KISAObjectIdentifiers.java
deleted file mode 100644
index 73575f1c..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/kisa/KISAObjectIdentifiers.java
+++ /dev/null
@@ -1,31 +0,0 @@
-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
-{
- /** 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/core/src/main/java/org/bouncycastle/asn1/microsoft/MicrosoftObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/microsoft/MicrosoftObjectIdentifiers.java
deleted file mode 100644
index 8ba2cf5e..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/microsoft/MicrosoftObjectIdentifiers.java
+++ /dev/null
@@ -1,28 +0,0 @@
-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
-{
- /** 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/core/src/main/java/org/bouncycastle/asn1/misc/CAST5CBCParameters.java b/core/src/main/java/org/bouncycastle/asn1/misc/CAST5CBCParameters.java
deleted file mode 100644
index 715e4bb9..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/misc/CAST5CBCParameters.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.bouncycastle.asn1.misc;
-
-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;
-
-public class CAST5CBCParameters
- extends ASN1Object
-{
- ASN1Integer keyLength;
- ASN1OctetString iv;
-
- public static CAST5CBCParameters getInstance(
- Object o)
- {
- if (o instanceof CAST5CBCParameters)
- {
- return (CAST5CBCParameters)o;
- }
- else if (o != null)
- {
- return new CAST5CBCParameters(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public CAST5CBCParameters(
- byte[] iv,
- int keyLength)
- {
- this.iv = new DEROctetString(iv);
- this.keyLength = new ASN1Integer(keyLength);
- }
-
- public CAST5CBCParameters(
- ASN1Sequence seq)
- {
- iv = (ASN1OctetString)seq.getObjectAt(0);
- keyLength = (ASN1Integer)seq.getObjectAt(1);
- }
-
- public byte[] getIV()
- {
- return iv.getOctets();
- }
-
- public int getKeyLength()
- {
- return keyLength.getValue().intValue();
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * cast5CBCParameters ::= SEQUENCE {
- * iv OCTET STRING DEFAULT 0,
- * -- Initialization vector
- * keyLength INTEGER
- * -- Key length, in bits
- * }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(iv);
- v.add(keyLength);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/misc/IDEACBCPar.java b/core/src/main/java/org/bouncycastle/asn1/misc/IDEACBCPar.java
deleted file mode 100644
index 35b0f244..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/misc/IDEACBCPar.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package org.bouncycastle.asn1.misc;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-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;
-
-public class IDEACBCPar
- extends ASN1Object
-{
- ASN1OctetString iv;
-
- public static IDEACBCPar getInstance(
- Object o)
- {
- if (o instanceof IDEACBCPar)
- {
- return (IDEACBCPar)o;
- }
- else if (o != null)
- {
- return new IDEACBCPar(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public IDEACBCPar(
- byte[] iv)
- {
- this.iv = new DEROctetString(iv);
- }
-
- public IDEACBCPar(
- ASN1Sequence seq)
- {
- if (seq.size() == 1)
- {
- iv = (ASN1OctetString)seq.getObjectAt(0);
- }
- else
- {
- iv = null;
- }
- }
-
- public byte[] getIV()
- {
- if (iv != null)
- {
- return iv.getOctets();
- }
- else
- {
- return null;
- }
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * IDEA-CBCPar ::= SEQUENCE {
- * iv OCTET STRING OPTIONAL -- exactly 8 octets
- * }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (iv != null)
- {
- v.add(iv);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java
deleted file mode 100644
index dfc31214..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package org.bouncycastle.asn1.misc;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-
-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");
-
- /** Verisign CZAG (Country,Zip,Age,Gender) Extension OID: 2.16.840.1.113733.1.6.3 */
- static final ASN1ObjectIdentifier verisignCzagExtension = verisign.branch("6.3");
- /** Verisign D&amp;B D-U-N-S number Extension OID: 2.16.840.1.113733.1.6.15 */
- static final ASN1ObjectIdentifier verisignDnbDunsNumber = verisign.branch("6.15");
-
- //
- // 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/core/src/main/java/org/bouncycastle/asn1/misc/NetscapeCertType.java b/core/src/main/java/org/bouncycastle/asn1/misc/NetscapeCertType.java
deleted file mode 100644
index 846a2057..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/misc/NetscapeCertType.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package org.bouncycastle.asn1.misc;
-
-import org.bouncycastle.asn1.DERBitString;
-
-/**
- * The NetscapeCertType object.
- * <pre>
- * NetscapeCertType ::= BIT STRING {
- * SSLClient (0),
- * SSLServer (1),
- * S/MIME (2),
- * Object Signing (3),
- * Reserved (4),
- * SSL CA (5),
- * S/MIME CA (6),
- * Object Signing CA (7) }
- * </pre>
- */
-public class NetscapeCertType
- extends DERBitString
-{
- public static final int sslClient = (1 << 7);
- public static final int sslServer = (1 << 6);
- public static final int smime = (1 << 5);
- public static final int objectSigning = (1 << 4);
- public static final int reserved = (1 << 3);
- public static final int sslCA = (1 << 2);
- public static final int smimeCA = (1 << 1);
- public static final int objectSigningCA = (1 << 0);
-
- /**
- * Basic constructor.
- *
- * @param usage - the bitwise OR of the Key Usage flags giving the
- * allowed uses for the key.
- * e.g. (X509NetscapeCertType.sslCA | X509NetscapeCertType.smimeCA)
- */
- public NetscapeCertType(
- int usage)
- {
- super(getBytes(usage), getPadBits(usage));
- }
-
- public NetscapeCertType(
- DERBitString usage)
- {
- super(usage.getBytes(), usage.getPadBits());
- }
-
- public String toString()
- {
- return "NetscapeCertType: 0x" + Integer.toHexString(data[0] & 0xff);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/misc/NetscapeRevocationURL.java b/core/src/main/java/org/bouncycastle/asn1/misc/NetscapeRevocationURL.java
deleted file mode 100644
index c0347da0..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/misc/NetscapeRevocationURL.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.bouncycastle.asn1.misc;
-
-import org.bouncycastle.asn1.DERIA5String;
-
-public class NetscapeRevocationURL
- extends DERIA5String
-{
- public NetscapeRevocationURL(
- DERIA5String str)
- {
- super(str.getString());
- }
-
- public String toString()
- {
- return "NetscapeRevocationURL: " + this.getString();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/misc/VerisignCzagExtension.java b/core/src/main/java/org/bouncycastle/asn1/misc/VerisignCzagExtension.java
deleted file mode 100644
index f09880ac..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/misc/VerisignCzagExtension.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.bouncycastle.asn1.misc;
-
-import org.bouncycastle.asn1.DERIA5String;
-
-public class VerisignCzagExtension
- extends DERIA5String
-{
- public VerisignCzagExtension(
- DERIA5String str)
- {
- super(str.getString());
- }
-
- public String toString()
- {
- return "VerisignCzagExtension: " + this.getString();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/mozilla/PublicKeyAndChallenge.java b/core/src/main/java/org/bouncycastle/asn1/mozilla/PublicKeyAndChallenge.java
deleted file mode 100644
index b4e44bf5..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/mozilla/PublicKeyAndChallenge.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package org.bouncycastle.asn1.mozilla;
-
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-
-/**
- * This is designed to parse
- * the PublicKeyAndChallenge created by the KEYGEN tag included by
- * Mozilla based browsers.
- * <pre>
- * PublicKeyAndChallenge ::= SEQUENCE {
- * spki SubjectPublicKeyInfo,
- * challenge IA5STRING
- * }
- *
- * </pre>
- */
-public class PublicKeyAndChallenge
- extends ASN1Object
-{
- private ASN1Sequence pkacSeq;
- private SubjectPublicKeyInfo spki;
- private DERIA5String challenge;
-
- public static PublicKeyAndChallenge getInstance(Object obj)
- {
- if (obj instanceof PublicKeyAndChallenge)
- {
- return (PublicKeyAndChallenge)obj;
- }
- else if (obj != null)
- {
- return new PublicKeyAndChallenge(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private PublicKeyAndChallenge(ASN1Sequence seq)
- {
- pkacSeq = seq;
- spki = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(0));
- challenge = DERIA5String.getInstance(seq.getObjectAt(1));
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return pkacSeq;
- }
-
- public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
- {
- return spki;
- }
-
- public DERIA5String getChallenge()
- {
- return challenge;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/nist/NISTNamedCurves.java b/core/src/main/java/org/bouncycastle/asn1/nist/NISTNamedCurves.java
deleted file mode 100644
index ba7e5187..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/nist/NISTNamedCurves.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package org.bouncycastle.asn1.nist;
-
-import java.util.Enumeration;
-import java.util.Hashtable;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.sec.SECNamedCurves;
-import org.bouncycastle.asn1.sec.SECObjectIdentifiers;
-import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.util.Strings;
-
-/**
- * Utility class for fetching curves using their NIST names as published in FIPS-PUB 186-3
- */
-public class NISTNamedCurves
-{
- static final Hashtable objIds = new Hashtable();
- static final Hashtable names = new Hashtable();
-
- static void defineCurve(String name, ASN1ObjectIdentifier oid)
- {
- objIds.put(name, oid);
- names.put(oid, name);
- }
-
- static
- {
- defineCurve("B-571", SECObjectIdentifiers.sect571r1);
- defineCurve("B-409", SECObjectIdentifiers.sect409r1);
- defineCurve("B-283", SECObjectIdentifiers.sect283r1);
- defineCurve("B-233", SECObjectIdentifiers.sect233r1);
- defineCurve("B-163", SECObjectIdentifiers.sect163r2);
- defineCurve("K-571", SECObjectIdentifiers.sect571k1);
- defineCurve("K-409", SECObjectIdentifiers.sect409k1);
- defineCurve("K-283", SECObjectIdentifiers.sect283k1);
- defineCurve("K-233", SECObjectIdentifiers.sect233k1);
- defineCurve("K-163", SECObjectIdentifiers.sect163k1);
- defineCurve("P-521", SECObjectIdentifiers.secp521r1);
- defineCurve("P-384", SECObjectIdentifiers.secp384r1);
- defineCurve("P-256", SECObjectIdentifiers.secp256r1);
- defineCurve("P-224", SECObjectIdentifiers.secp224r1);
- defineCurve("P-192", SECObjectIdentifiers.secp192r1);
- }
-
- public static X9ECParameters getByName(
- String name)
- {
- ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)objIds.get(Strings.toUpperCase(name));
-
- if (oid != null)
- {
- return getByOID(oid);
- }
-
- return null;
- }
-
- /**
- * return the X9ECParameters object for the named curve represented by
- * the passed in object identifier. Null if the curve isn't present.
- *
- * @param oid an object identifier representing a named curve, if present.
- */
- public static X9ECParameters getByOID(
- ASN1ObjectIdentifier oid)
- {
- return SECNamedCurves.getByOID(oid);
- }
-
- /**
- * return the object identifier signified by the passed in name. Null
- * if there is no object identifier associated with name.
- *
- * @return the object identifier associated with name, if present.
- */
- public static ASN1ObjectIdentifier getOID(
- String name)
- {
- return (ASN1ObjectIdentifier)objIds.get(Strings.toUpperCase(name));
- }
-
- /**
- * return the named curve name represented by the given object identifier.
- */
- public static String getName(
- ASN1ObjectIdentifier oid)
- {
- return (String)names.get(oid);
- }
-
- /**
- * returns an enumeration containing the name strings for curves
- * contained in this structure.
- */
- public static Enumeration getNames()
- {
- return objIds.keys();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java
deleted file mode 100644
index e3613c68..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java
+++ /dev/null
@@ -1,96 +0,0 @@
-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
-{
- //
- // 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");
-
- /** 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/core/src/main/java/org/bouncycastle/asn1/ntt/NTTObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/ntt/NTTObjectIdentifiers.java
deleted file mode 100644
index fa32068e..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ntt/NTTObjectIdentifiers.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.asn1.ntt;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-
-/**
- * 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
-{
- /** 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");
-
- /** 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/core/src/main/java/org/bouncycastle/asn1/ocsp/BasicOCSPResponse.java b/core/src/main/java/org/bouncycastle/asn1/ocsp/BasicOCSPResponse.java
deleted file mode 100644
index 1b2e7f53..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ocsp/BasicOCSPResponse.java
+++ /dev/null
@@ -1,112 +0,0 @@
-package org.bouncycastle.asn1.ocsp;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-public class BasicOCSPResponse
- extends ASN1Object
-{
- private ResponseData tbsResponseData;
- private AlgorithmIdentifier signatureAlgorithm;
- private DERBitString signature;
- private ASN1Sequence certs;
-
- public BasicOCSPResponse(
- ResponseData tbsResponseData,
- AlgorithmIdentifier signatureAlgorithm,
- DERBitString signature,
- ASN1Sequence certs)
- {
- this.tbsResponseData = tbsResponseData;
- this.signatureAlgorithm = signatureAlgorithm;
- this.signature = signature;
- this.certs = certs;
- }
-
- private BasicOCSPResponse(
- ASN1Sequence seq)
- {
- this.tbsResponseData = ResponseData.getInstance(seq.getObjectAt(0));
- this.signatureAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
- this.signature = (DERBitString)seq.getObjectAt(2);
-
- if (seq.size() > 3)
- {
- this.certs = ASN1Sequence.getInstance((ASN1TaggedObject)seq.getObjectAt(3), true);
- }
- }
-
- public static BasicOCSPResponse getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static BasicOCSPResponse getInstance(
- Object obj)
- {
- if (obj instanceof BasicOCSPResponse)
- {
- return (BasicOCSPResponse)obj;
- }
- else if (obj != null)
- {
- return new BasicOCSPResponse(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public ResponseData getTbsResponseData()
- {
- return tbsResponseData;
- }
-
- public AlgorithmIdentifier getSignatureAlgorithm()
- {
- return signatureAlgorithm;
- }
-
- public DERBitString getSignature()
- {
- return signature;
- }
-
- public ASN1Sequence getCerts()
- {
- return certs;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * BasicOCSPResponse ::= SEQUENCE {
- * tbsResponseData ResponseData,
- * signatureAlgorithm AlgorithmIdentifier,
- * signature BIT STRING,
- * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(tbsResponseData);
- v.add(signatureAlgorithm);
- v.add(signature);
- if (certs != null)
- {
- v.add(new DERTaggedObject(true, 0, certs));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ocsp/CertID.java b/core/src/main/java/org/bouncycastle/asn1/ocsp/CertID.java
deleted file mode 100644
index 9d3496ef..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ocsp/CertID.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package org.bouncycastle.asn1.ocsp;
-
-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.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-public class CertID
- extends ASN1Object
-{
- AlgorithmIdentifier hashAlgorithm;
- ASN1OctetString issuerNameHash;
- ASN1OctetString issuerKeyHash;
- ASN1Integer serialNumber;
-
- public CertID(
- AlgorithmIdentifier hashAlgorithm,
- ASN1OctetString issuerNameHash,
- ASN1OctetString issuerKeyHash,
- ASN1Integer serialNumber)
- {
- this.hashAlgorithm = hashAlgorithm;
- this.issuerNameHash = issuerNameHash;
- this.issuerKeyHash = issuerKeyHash;
- this.serialNumber = serialNumber;
- }
-
- private CertID(
- ASN1Sequence seq)
- {
- hashAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(0));
- issuerNameHash = (ASN1OctetString)seq.getObjectAt(1);
- issuerKeyHash = (ASN1OctetString)seq.getObjectAt(2);
- serialNumber = (ASN1Integer)seq.getObjectAt(3);
- }
-
- public static CertID getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static CertID getInstance(
- Object obj)
- {
- if (obj instanceof CertID)
- {
- return (CertID)obj;
- }
- else if (obj != null)
- {
- return new CertID(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public AlgorithmIdentifier getHashAlgorithm()
- {
- return hashAlgorithm;
- }
-
- public ASN1OctetString getIssuerNameHash()
- {
- return issuerNameHash;
- }
-
- public ASN1OctetString getIssuerKeyHash()
- {
- return issuerKeyHash;
- }
-
- public ASN1Integer getSerialNumber()
- {
- return serialNumber;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * CertID ::= SEQUENCE {
- * hashAlgorithm AlgorithmIdentifier,
- * issuerNameHash OCTET STRING, -- Hash of Issuer's DN
- * issuerKeyHash OCTET STRING, -- Hash of Issuers public key
- * serialNumber CertificateSerialNumber }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(hashAlgorithm);
- v.add(issuerNameHash);
- v.add(issuerKeyHash);
- v.add(serialNumber);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ocsp/CertStatus.java b/core/src/main/java/org/bouncycastle/asn1/ocsp/CertStatus.java
deleted file mode 100644
index af530ae5..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ocsp/CertStatus.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package org.bouncycastle.asn1.ocsp;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-public class CertStatus
- extends ASN1Object
- implements ASN1Choice
-{
- private int tagNo;
- private ASN1Encodable value;
-
- /**
- * create a CertStatus object with a tag of zero.
- */
- public CertStatus()
- {
- tagNo = 0;
- value = DERNull.INSTANCE;
- }
-
- public CertStatus(
- RevokedInfo info)
- {
- tagNo = 1;
- value = info;
- }
-
- public CertStatus(
- int tagNo,
- ASN1Encodable value)
- {
- this.tagNo = tagNo;
- this.value = value;
- }
-
- public CertStatus(
- ASN1TaggedObject choice)
- {
- this.tagNo = choice.getTagNo();
-
- switch (choice.getTagNo())
- {
- case 0:
- value = DERNull.INSTANCE;
- break;
- case 1:
- value = RevokedInfo.getInstance(choice, false);
- break;
- case 2:
- value = DERNull.INSTANCE;
- }
- }
-
- public static CertStatus getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof CertStatus)
- {
- return (CertStatus)obj;
- }
- else if (obj instanceof ASN1TaggedObject)
- {
- return new CertStatus((ASN1TaggedObject)obj);
- }
-
- throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
- }
-
- public static CertStatus getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject()); // must be explicitly tagged
- }
-
- public int getTagNo()
- {
- return tagNo;
- }
-
- public ASN1Encodable getStatus()
- {
- return value;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * CertStatus ::= CHOICE {
- * good [0] IMPLICIT NULL,
- * revoked [1] IMPLICIT RevokedInfo,
- * unknown [2] IMPLICIT UnknownInfo }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- return new DERTaggedObject(false, tagNo, value);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ocsp/CrlID.java b/core/src/main/java/org/bouncycastle/asn1/ocsp/CrlID.java
deleted file mode 100644
index f5a35811..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ocsp/CrlID.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package org.bouncycastle.asn1.ocsp;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-public class CrlID
- extends ASN1Object
-{
- private DERIA5String crlUrl;
- private ASN1Integer crlNum;
- private ASN1GeneralizedTime crlTime;
-
- private CrlID(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- while (e.hasMoreElements())
- {
- ASN1TaggedObject o = (ASN1TaggedObject)e.nextElement();
-
- switch (o.getTagNo())
- {
- case 0:
- crlUrl = DERIA5String.getInstance(o, true);
- break;
- case 1:
- crlNum = ASN1Integer.getInstance(o, true);
- break;
- case 2:
- crlTime = ASN1GeneralizedTime.getInstance(o, true);
- break;
- default:
- throw new IllegalArgumentException(
- "unknown tag number: " + o.getTagNo());
- }
- }
- }
-
- public static CrlID getInstance(
- Object obj)
- {
- if (obj instanceof CrlID)
- {
- return (CrlID)obj;
- }
- else if (obj != null)
- {
- return new CrlID(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public DERIA5String getCrlUrl()
- {
- return crlUrl;
- }
-
- public ASN1Integer getCrlNum()
- {
- return crlNum;
- }
-
- public ASN1GeneralizedTime getCrlTime()
- {
- return crlTime;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * CrlID ::= SEQUENCE {
- * crlUrl [0] EXPLICIT IA5String OPTIONAL,
- * crlNum [1] EXPLICIT INTEGER OPTIONAL,
- * crlTime [2] EXPLICIT GeneralizedTime OPTIONAL }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (crlUrl != null)
- {
- v.add(new DERTaggedObject(true, 0, crlUrl));
- }
-
- if (crlNum != null)
- {
- v.add(new DERTaggedObject(true, 1, crlNum));
- }
-
- if (crlTime != null)
- {
- v.add(new DERTaggedObject(true, 2, crlTime));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ocsp/OCSPObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/ocsp/OCSPObjectIdentifiers.java
deleted file mode 100644
index f8ea8f75..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ocsp/OCSPObjectIdentifiers.java
+++ /dev/null
@@ -1,29 +0,0 @@
-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
-{
- /** 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");
-
- /** 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");
-
- /** 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/core/src/main/java/org/bouncycastle/asn1/ocsp/OCSPRequest.java b/core/src/main/java/org/bouncycastle/asn1/ocsp/OCSPRequest.java
deleted file mode 100644
index 559cf4ce..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ocsp/OCSPRequest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package org.bouncycastle.asn1.ocsp;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-public class OCSPRequest
- extends ASN1Object
-{
- TBSRequest tbsRequest;
- Signature optionalSignature;
-
- public OCSPRequest(
- TBSRequest tbsRequest,
- Signature optionalSignature)
- {
- this.tbsRequest = tbsRequest;
- this.optionalSignature = optionalSignature;
- }
-
- private OCSPRequest(
- ASN1Sequence seq)
- {
- tbsRequest = TBSRequest.getInstance(seq.getObjectAt(0));
-
- if (seq.size() == 2)
- {
- optionalSignature = Signature.getInstance(
- (ASN1TaggedObject)seq.getObjectAt(1), true);
- }
- }
-
- public static OCSPRequest getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static OCSPRequest getInstance(
- Object obj)
- {
- if (obj instanceof OCSPRequest)
- {
- return (OCSPRequest)obj;
- }
- else if (obj != null)
- {
- return new OCSPRequest(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public TBSRequest getTbsRequest()
- {
- return tbsRequest;
- }
-
- public Signature getOptionalSignature()
- {
- return optionalSignature;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * OCSPRequest ::= SEQUENCE {
- * tbsRequest TBSRequest,
- * optionalSignature [0] EXPLICIT Signature OPTIONAL }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(tbsRequest);
-
- if (optionalSignature != null)
- {
- v.add(new DERTaggedObject(true, 0, optionalSignature));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ocsp/OCSPResponse.java b/core/src/main/java/org/bouncycastle/asn1/ocsp/OCSPResponse.java
deleted file mode 100644
index 31602daf..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ocsp/OCSPResponse.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package org.bouncycastle.asn1.ocsp;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-public class OCSPResponse
- extends ASN1Object
-{
- OCSPResponseStatus responseStatus;
- ResponseBytes responseBytes;
-
- public OCSPResponse(
- OCSPResponseStatus responseStatus,
- ResponseBytes responseBytes)
- {
- this.responseStatus = responseStatus;
- this.responseBytes = responseBytes;
- }
-
- private OCSPResponse(
- ASN1Sequence seq)
- {
- responseStatus = OCSPResponseStatus.getInstance(seq.getObjectAt(0));
-
- if (seq.size() == 2)
- {
- responseBytes = ResponseBytes.getInstance(
- (ASN1TaggedObject)seq.getObjectAt(1), true);
- }
- }
-
- public static OCSPResponse getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static OCSPResponse getInstance(
- Object obj)
- {
- if (obj instanceof OCSPResponse)
- {
- return (OCSPResponse)obj;
- }
- else if (obj != null)
- {
- return new OCSPResponse(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public OCSPResponseStatus getResponseStatus()
- {
- return responseStatus;
- }
-
- public ResponseBytes getResponseBytes()
- {
- return responseBytes;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * OCSPResponse ::= SEQUENCE {
- * responseStatus OCSPResponseStatus,
- * responseBytes [0] EXPLICIT ResponseBytes OPTIONAL }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(responseStatus);
-
- if (responseBytes != null)
- {
- v.add(new DERTaggedObject(true, 0, responseBytes));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ocsp/OCSPResponseStatus.java b/core/src/main/java/org/bouncycastle/asn1/ocsp/OCSPResponseStatus.java
deleted file mode 100644
index aa225f93..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ocsp/OCSPResponseStatus.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.bouncycastle.asn1.ocsp;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1Enumerated;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-
-public class OCSPResponseStatus
- extends ASN1Object
-{
- public static final int SUCCESSFUL = 0;
- public static final int MALFORMED_REQUEST = 1;
- public static final int INTERNAL_ERROR = 2;
- public static final int TRY_LATER = 3;
- public static final int SIG_REQUIRED = 5;
- public static final int UNAUTHORIZED = 6;
-
- private ASN1Enumerated value;
-
- /**
- * The OCSPResponseStatus enumeration.
- * <pre>
- * OCSPResponseStatus ::= ENUMERATED {
- * successful (0), --Response has valid confirmations
- * malformedRequest (1), --Illegal confirmation request
- * internalError (2), --Internal error in issuer
- * tryLater (3), --Try again later
- * --(4) is not used
- * sigRequired (5), --Must sign the request
- * unauthorized (6) --Request unauthorized
- * }
- * </pre>
- */
- public OCSPResponseStatus(
- int value)
- {
- this(new ASN1Enumerated(value));
- }
-
- private OCSPResponseStatus(
- ASN1Enumerated value)
- {
- this.value = value;
- }
-
- public static OCSPResponseStatus getInstance(
- Object obj)
- {
- if (obj instanceof OCSPResponseStatus)
- {
- return (OCSPResponseStatus)obj;
- }
- else if (obj != null)
- {
- return new OCSPResponseStatus(ASN1Enumerated.getInstance(obj));
- }
-
- return null;
- }
-
- public BigInteger getValue()
- {
- return value.getValue();
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return value;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ocsp/Request.java b/core/src/main/java/org/bouncycastle/asn1/ocsp/Request.java
deleted file mode 100644
index 236bc72f..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ocsp/Request.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package org.bouncycastle.asn1.ocsp;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.Extensions;
-
-public class Request
- extends ASN1Object
-{
- CertID reqCert;
- Extensions singleRequestExtensions;
-
- public Request(
- CertID reqCert,
- Extensions singleRequestExtensions)
- {
- this.reqCert = reqCert;
- this.singleRequestExtensions = singleRequestExtensions;
- }
-
- private Request(
- ASN1Sequence seq)
- {
- reqCert = CertID.getInstance(seq.getObjectAt(0));
-
- if (seq.size() == 2)
- {
- singleRequestExtensions = Extensions.getInstance(
- (ASN1TaggedObject)seq.getObjectAt(1), true);
- }
- }
-
- public static Request getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static Request getInstance(
- Object obj)
- {
- if (obj instanceof Request)
- {
- return (Request)obj;
- }
- else if (obj != null)
- {
- return new Request(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public CertID getReqCert()
- {
- return reqCert;
- }
-
- public Extensions getSingleRequestExtensions()
- {
- return singleRequestExtensions;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * Request ::= SEQUENCE {
- * reqCert CertID,
- * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(reqCert);
-
- if (singleRequestExtensions != null)
- {
- v.add(new DERTaggedObject(true, 0, singleRequestExtensions));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ocsp/ResponderID.java b/core/src/main/java/org/bouncycastle/asn1/ocsp/ResponderID.java
deleted file mode 100644
index 97190472..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ocsp/ResponderID.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package org.bouncycastle.asn1.ocsp;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x500.X500Name;
-
-public class ResponderID
- extends ASN1Object
- implements ASN1Choice
-{
- private ASN1Encodable value;
-
- public ResponderID(
- ASN1OctetString value)
- {
- this.value = value;
- }
-
- public ResponderID(
- X500Name value)
- {
- this.value = value;
- }
-
- public static ResponderID getInstance(
- Object obj)
- {
- if (obj instanceof ResponderID)
- {
- return (ResponderID)obj;
- }
- else if (obj instanceof DEROctetString)
- {
- return new ResponderID((DEROctetString)obj);
- }
- else if (obj instanceof ASN1TaggedObject)
- {
- ASN1TaggedObject o = (ASN1TaggedObject)obj;
-
- if (o.getTagNo() == 1)
- {
- return new ResponderID(X500Name.getInstance(o, true));
- }
- else
- {
- return new ResponderID(ASN1OctetString.getInstance(o, true));
- }
- }
-
- return new ResponderID(X500Name.getInstance(obj));
- }
-
- public static ResponderID getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject()); // must be explicitly tagged
- }
-
- public byte[] getKeyHash()
- {
- if (this.value instanceof ASN1OctetString)
- {
- ASN1OctetString octetString = (ASN1OctetString)this.value;
- return octetString.getOctets();
- }
-
- return null;
- }
-
- public X500Name getName()
- {
- if (this.value instanceof ASN1OctetString)
- {
- return null;
- }
-
- return X500Name.getInstance(value);
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * ResponderID ::= CHOICE {
- * byName [1] Name,
- * byKey [2] KeyHash }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- if (value instanceof ASN1OctetString)
- {
- return new DERTaggedObject(true, 2, value);
- }
-
- return new DERTaggedObject(true, 1, value);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ocsp/ResponseBytes.java b/core/src/main/java/org/bouncycastle/asn1/ocsp/ResponseBytes.java
deleted file mode 100644
index 074294c6..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ocsp/ResponseBytes.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package org.bouncycastle.asn1.ocsp;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-
-public class ResponseBytes
- extends ASN1Object
-{
- ASN1ObjectIdentifier responseType;
- ASN1OctetString response;
-
- public ResponseBytes(
- ASN1ObjectIdentifier responseType,
- ASN1OctetString response)
- {
- this.responseType = responseType;
- this.response = response;
- }
-
- public ResponseBytes(
- ASN1Sequence seq)
- {
- responseType = (ASN1ObjectIdentifier)seq.getObjectAt(0);
- response = (ASN1OctetString)seq.getObjectAt(1);
- }
-
- public static ResponseBytes getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static ResponseBytes getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ResponseBytes)
- {
- return (ResponseBytes)obj;
- }
- else if (obj instanceof ASN1Sequence)
- {
- return new ResponseBytes((ASN1Sequence)obj);
- }
-
- throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
- }
-
- public ASN1ObjectIdentifier getResponseType()
- {
- return responseType;
- }
-
- public ASN1OctetString getResponse()
- {
- return response;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * ResponseBytes ::= SEQUENCE {
- * responseType OBJECT IDENTIFIER,
- * response OCTET STRING }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(responseType);
- v.add(response);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ocsp/ResponseData.java b/core/src/main/java/org/bouncycastle/asn1/ocsp/ResponseData.java
deleted file mode 100644
index 6874b227..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ocsp/ResponseData.java
+++ /dev/null
@@ -1,181 +0,0 @@
-package org.bouncycastle.asn1.ocsp;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.Extensions;
-import org.bouncycastle.asn1.x509.X509Extensions;
-
-public class ResponseData
- extends ASN1Object
-{
- private static final ASN1Integer V1 = new ASN1Integer(0);
-
- private boolean versionPresent;
-
- private ASN1Integer version;
- private ResponderID responderID;
- private ASN1GeneralizedTime producedAt;
- private ASN1Sequence responses;
- private Extensions responseExtensions;
-
- public ResponseData(
- ASN1Integer version,
- ResponderID responderID,
- ASN1GeneralizedTime producedAt,
- ASN1Sequence responses,
- Extensions responseExtensions)
- {
- this.version = version;
- this.responderID = responderID;
- this.producedAt = producedAt;
- this.responses = responses;
- this.responseExtensions = responseExtensions;
- }
-
- /**
- * @deprecated use method taking Extensions
- * @param responderID
- * @param producedAt
- * @param responses
- * @param responseExtensions
- */
- public ResponseData(
- ResponderID responderID,
- ASN1GeneralizedTime producedAt,
- ASN1Sequence responses,
- X509Extensions responseExtensions)
- {
- this(V1, responderID, ASN1GeneralizedTime.getInstance(producedAt), responses, Extensions.getInstance(responseExtensions));
- }
-
- public ResponseData(
- ResponderID responderID,
- ASN1GeneralizedTime producedAt,
- ASN1Sequence responses,
- Extensions responseExtensions)
- {
- this(V1, responderID, producedAt, responses, responseExtensions);
- }
-
- private ResponseData(
- ASN1Sequence seq)
- {
- int index = 0;
-
- if (seq.getObjectAt(0) instanceof ASN1TaggedObject)
- {
- ASN1TaggedObject o = (ASN1TaggedObject)seq.getObjectAt(0);
-
- if (o.getTagNo() == 0)
- {
- this.versionPresent = true;
- this.version = ASN1Integer.getInstance(
- (ASN1TaggedObject)seq.getObjectAt(0), true);
- index++;
- }
- else
- {
- this.version = V1;
- }
- }
- else
- {
- this.version = V1;
- }
-
- this.responderID = ResponderID.getInstance(seq.getObjectAt(index++));
- this.producedAt = ASN1GeneralizedTime.getInstance(seq.getObjectAt(index++));
- this.responses = (ASN1Sequence)seq.getObjectAt(index++);
-
- if (seq.size() > index)
- {
- this.responseExtensions = Extensions.getInstance(
- (ASN1TaggedObject)seq.getObjectAt(index), true);
- }
- }
-
- public static ResponseData getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static ResponseData getInstance(
- Object obj)
- {
- if (obj instanceof ResponseData)
- {
- return (ResponseData)obj;
- }
- else if (obj != null)
- {
- return new ResponseData(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public ResponderID getResponderID()
- {
- return responderID;
- }
-
- public ASN1GeneralizedTime getProducedAt()
- {
- return producedAt;
- }
-
- public ASN1Sequence getResponses()
- {
- return responses;
- }
-
- public Extensions getResponseExtensions()
- {
- return responseExtensions;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * ResponseData ::= SEQUENCE {
- * version [0] EXPLICIT Version DEFAULT v1,
- * responderID ResponderID,
- * producedAt GeneralizedTime,
- * responses SEQUENCE OF SingleResponse,
- * responseExtensions [1] EXPLICIT Extensions OPTIONAL }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (versionPresent || !version.equals(V1))
- {
- v.add(new DERTaggedObject(true, 0, version));
- }
-
- v.add(responderID);
- v.add(producedAt);
- v.add(responses);
- if (responseExtensions != null)
- {
- v.add(new DERTaggedObject(true, 1, responseExtensions));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ocsp/RevokedInfo.java b/core/src/main/java/org/bouncycastle/asn1/ocsp/RevokedInfo.java
deleted file mode 100644
index 67700500..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ocsp/RevokedInfo.java
+++ /dev/null
@@ -1,92 +0,0 @@
-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.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.CRLReason;
-
-public class RevokedInfo
- extends ASN1Object
-{
- private ASN1GeneralizedTime revocationTime;
- private CRLReason revocationReason;
-
- public RevokedInfo(
- ASN1GeneralizedTime revocationTime,
- CRLReason revocationReason)
- {
- this.revocationTime = revocationTime;
- this.revocationReason = revocationReason;
- }
-
- private RevokedInfo(
- ASN1Sequence seq)
- {
- this.revocationTime = ASN1GeneralizedTime.getInstance(seq.getObjectAt(0));
-
- if (seq.size() > 1)
- {
- this.revocationReason = CRLReason.getInstance(ASN1Enumerated.getInstance(
- (ASN1TaggedObject)seq.getObjectAt(1), true));
- }
- }
-
- public static RevokedInfo getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static RevokedInfo getInstance(
- Object obj)
- {
- if (obj instanceof RevokedInfo)
- {
- return (RevokedInfo)obj;
- }
- else if (obj != null)
- {
- return new RevokedInfo(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public ASN1GeneralizedTime getRevocationTime()
- {
- return revocationTime;
- }
-
- public CRLReason getRevocationReason()
- {
- return revocationReason;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * RevokedInfo ::= SEQUENCE {
- * revocationTime GeneralizedTime,
- * revocationReason [0] EXPLICIT CRLReason OPTIONAL }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(revocationTime);
- if (revocationReason != null)
- {
- v.add(new DERTaggedObject(true, 0, revocationReason));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ocsp/ServiceLocator.java b/core/src/main/java/org/bouncycastle/asn1/ocsp/ServiceLocator.java
deleted file mode 100644
index dc9486fc..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ocsp/ServiceLocator.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.bouncycastle.asn1.ocsp;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x500.X500Name;
-
-public class ServiceLocator
- extends ASN1Object
-{
- X500Name issuer;
- ASN1Primitive locator;
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * ServiceLocator ::= SEQUENCE {
- * issuer Name,
- * locator AuthorityInfoAccessSyntax OPTIONAL }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(issuer);
-
- if (locator != null)
- {
- v.add(locator);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ocsp/Signature.java b/core/src/main/java/org/bouncycastle/asn1/ocsp/Signature.java
deleted file mode 100644
index 80bd740a..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ocsp/Signature.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package org.bouncycastle.asn1.ocsp;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-public class Signature
- extends ASN1Object
-{
- AlgorithmIdentifier signatureAlgorithm;
- DERBitString signature;
- ASN1Sequence certs;
-
- public Signature(
- AlgorithmIdentifier signatureAlgorithm,
- DERBitString signature)
- {
- this.signatureAlgorithm = signatureAlgorithm;
- this.signature = signature;
- }
-
- public Signature(
- AlgorithmIdentifier signatureAlgorithm,
- DERBitString signature,
- ASN1Sequence certs)
- {
- this.signatureAlgorithm = signatureAlgorithm;
- this.signature = signature;
- this.certs = certs;
- }
-
- private Signature(
- ASN1Sequence seq)
- {
- signatureAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(0));
- signature = (DERBitString)seq.getObjectAt(1);
-
- if (seq.size() == 3)
- {
- certs = ASN1Sequence.getInstance(
- (ASN1TaggedObject)seq.getObjectAt(2), true);
- }
- }
-
- public static Signature getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static Signature getInstance(
- Object obj)
- {
- if (obj instanceof Signature)
- {
- return (Signature)obj;
- }
- else if (obj != null)
- {
- return new Signature(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public AlgorithmIdentifier getSignatureAlgorithm()
- {
- return signatureAlgorithm;
- }
-
- public DERBitString getSignature()
- {
- return signature;
- }
-
- public ASN1Sequence getCerts()
- {
- return certs;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * Signature ::= SEQUENCE {
- * signatureAlgorithm AlgorithmIdentifier,
- * signature BIT STRING,
- * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL}
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(signatureAlgorithm);
- v.add(signature);
-
- if (certs != null)
- {
- v.add(new DERTaggedObject(true, 0, certs));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ocsp/SingleResponse.java b/core/src/main/java/org/bouncycastle/asn1/ocsp/SingleResponse.java
deleted file mode 100644
index 0dc2a91c..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ocsp/SingleResponse.java
+++ /dev/null
@@ -1,162 +0,0 @@
-package org.bouncycastle.asn1.ocsp;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-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.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.Extensions;
-import org.bouncycastle.asn1.x509.X509Extensions;
-
-public class SingleResponse
- extends ASN1Object
-{
- private CertID certID;
- private CertStatus certStatus;
- private ASN1GeneralizedTime thisUpdate;
- private ASN1GeneralizedTime nextUpdate;
- private Extensions singleExtensions;
-
- /**
- * @deprecated use method taking ASN1GeneralizedTime and Extensions
- * @param certID
- * @param certStatus
- * @param thisUpdate
- * @param nextUpdate
- * @param singleExtensions
- */
- public SingleResponse(
- CertID certID,
- CertStatus certStatus,
- ASN1GeneralizedTime thisUpdate,
- ASN1GeneralizedTime nextUpdate,
- X509Extensions singleExtensions)
- {
- this(certID, certStatus, thisUpdate, nextUpdate, Extensions.getInstance(singleExtensions));
- }
-
- public SingleResponse(
- CertID certID,
- CertStatus certStatus,
- ASN1GeneralizedTime thisUpdate,
- ASN1GeneralizedTime nextUpdate,
- Extensions singleExtensions)
- {
- this.certID = certID;
- this.certStatus = certStatus;
- this.thisUpdate = thisUpdate;
- this.nextUpdate = nextUpdate;
- this.singleExtensions = singleExtensions;
- }
-
- private SingleResponse(
- ASN1Sequence seq)
- {
- this.certID = CertID.getInstance(seq.getObjectAt(0));
- this.certStatus = CertStatus.getInstance(seq.getObjectAt(1));
- this.thisUpdate = ASN1GeneralizedTime.getInstance(seq.getObjectAt(2));
-
- if (seq.size() > 4)
- {
- this.nextUpdate = ASN1GeneralizedTime.getInstance(
- (ASN1TaggedObject)seq.getObjectAt(3), true);
- this.singleExtensions = Extensions.getInstance(
- (ASN1TaggedObject)seq.getObjectAt(4), true);
- }
- else if (seq.size() > 3)
- {
- ASN1TaggedObject o = (ASN1TaggedObject)seq.getObjectAt(3);
-
- if (o.getTagNo() == 0)
- {
- this.nextUpdate = ASN1GeneralizedTime.getInstance(o, true);
- }
- else
- {
- this.singleExtensions = Extensions.getInstance(o, true);
- }
- }
- }
-
- public static SingleResponse getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static SingleResponse getInstance(
- Object obj)
- {
- if (obj instanceof SingleResponse)
- {
- return (SingleResponse)obj;
- }
- else if (obj != null)
- {
- return new SingleResponse(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public CertID getCertID()
- {
- return certID;
- }
-
- public CertStatus getCertStatus()
- {
- return certStatus;
- }
-
- public ASN1GeneralizedTime getThisUpdate()
- {
- return thisUpdate;
- }
-
- public ASN1GeneralizedTime getNextUpdate()
- {
- return nextUpdate;
- }
-
- public Extensions getSingleExtensions()
- {
- return singleExtensions;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * SingleResponse ::= SEQUENCE {
- * certID CertID,
- * certStatus CertStatus,
- * thisUpdate GeneralizedTime,
- * nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
- * singleExtensions [1] EXPLICIT Extensions OPTIONAL }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(certID);
- v.add(certStatus);
- v.add(thisUpdate);
-
- if (nextUpdate != null)
- {
- v.add(new DERTaggedObject(true, 0, nextUpdate));
- }
-
- if (singleExtensions != null)
- {
- v.add(new DERTaggedObject(true, 1, singleExtensions));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ocsp/TBSRequest.java b/core/src/main/java/org/bouncycastle/asn1/ocsp/TBSRequest.java
deleted file mode 100644
index 2a05705b..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ocsp/TBSRequest.java
+++ /dev/null
@@ -1,172 +0,0 @@
-package org.bouncycastle.asn1.ocsp;
-
-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;
-import org.bouncycastle.asn1.x509.Extensions;
-import org.bouncycastle.asn1.x509.GeneralName;
-import org.bouncycastle.asn1.x509.X509Extensions;
-
-public class TBSRequest
- extends ASN1Object
-{
- private static final ASN1Integer V1 = new ASN1Integer(0);
-
- ASN1Integer version;
- GeneralName requestorName;
- ASN1Sequence requestList;
- Extensions requestExtensions;
-
- boolean versionSet;
-
- /**
- * @deprecated use method taking Extensions
- * @param requestorName
- * @param requestList
- * @param requestExtensions
- */
- public TBSRequest(
- GeneralName requestorName,
- ASN1Sequence requestList,
- X509Extensions requestExtensions)
- {
- this.version = V1;
- this.requestorName = requestorName;
- this.requestList = requestList;
- this.requestExtensions = Extensions.getInstance(requestExtensions);
- }
-
- public TBSRequest(
- GeneralName requestorName,
- ASN1Sequence requestList,
- Extensions requestExtensions)
- {
- this.version = V1;
- this.requestorName = requestorName;
- this.requestList = requestList;
- this.requestExtensions = requestExtensions;
- }
-
- private TBSRequest(
- ASN1Sequence seq)
- {
- int index = 0;
-
- if (seq.getObjectAt(0) instanceof ASN1TaggedObject)
- {
- ASN1TaggedObject o = (ASN1TaggedObject)seq.getObjectAt(0);
-
- if (o.getTagNo() == 0)
- {
- versionSet = true;
- version = ASN1Integer.getInstance((ASN1TaggedObject)seq.getObjectAt(0), true);
- index++;
- }
- else
- {
- version = V1;
- }
- }
- else
- {
- version = V1;
- }
-
- if (seq.getObjectAt(index) instanceof ASN1TaggedObject)
- {
- requestorName = GeneralName.getInstance((ASN1TaggedObject)seq.getObjectAt(index++), true);
- }
-
- requestList = (ASN1Sequence)seq.getObjectAt(index++);
-
- if (seq.size() == (index + 1))
- {
- requestExtensions = Extensions.getInstance((ASN1TaggedObject)seq.getObjectAt(index), true);
- }
- }
-
- public static TBSRequest getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static TBSRequest getInstance(
- Object obj)
- {
- if (obj instanceof TBSRequest)
- {
- return (TBSRequest)obj;
- }
- else if (obj != null)
- {
- return new TBSRequest(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public GeneralName getRequestorName()
- {
- return requestorName;
- }
-
- public ASN1Sequence getRequestList()
- {
- return requestList;
- }
-
- public Extensions getRequestExtensions()
- {
- return requestExtensions;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * TBSRequest ::= SEQUENCE {
- * version [0] EXPLICIT Version DEFAULT v1,
- * requestorName [1] EXPLICIT GeneralName OPTIONAL,
- * requestList SEQUENCE OF Request,
- * requestExtensions [2] EXPLICIT Extensions OPTIONAL }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- //
- // if default don't include - unless explicitly provided. Not strictly correct
- // but required for some requests
- //
- if (!version.equals(V1) || versionSet)
- {
- v.add(new DERTaggedObject(true, 0, version));
- }
-
- if (requestorName != null)
- {
- v.add(new DERTaggedObject(true, 1, requestorName));
- }
-
- v.add(requestList);
-
- if (requestExtensions != null)
- {
- v.add(new DERTaggedObject(true, 2, requestExtensions));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/oiw/ElGamalParameter.java b/core/src/main/java/org/bouncycastle/asn1/oiw/ElGamalParameter.java
deleted file mode 100644
index d654d032..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/oiw/ElGamalParameter.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.bouncycastle.asn1.oiw;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-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.DERSequence;
-
-public class ElGamalParameter
- extends ASN1Object
-{
- ASN1Integer p, g;
-
- public ElGamalParameter(
- BigInteger p,
- BigInteger g)
- {
- this.p = new ASN1Integer(p);
- this.g = new ASN1Integer(g);
- }
-
- private ElGamalParameter(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- p = (ASN1Integer)e.nextElement();
- g = (ASN1Integer)e.nextElement();
- }
-
- public static ElGamalParameter getInstance(Object o)
- {
- if (o instanceof ElGamalParameter)
- {
- return (ElGamalParameter)o;
- }
- else if (o != null)
- {
- return new ElGamalParameter(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public BigInteger getP()
- {
- return p.getPositiveValue();
- }
-
- public BigInteger getG()
- {
- return g.getPositiveValue();
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(p);
- v.add(g);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/oiw/OIWObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/oiw/OIWObjectIdentifiers.java
deleted file mode 100644
index c169c169..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/oiw/OIWObjectIdentifiers.java
+++ /dev/null
@@ -1,50 +0,0 @@
-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
-{
- /** 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");
-
- /**
- * <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/core/src/main/java/org/bouncycastle/asn1/pkcs/Attribute.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/Attribute.java
deleted file mode 100644
index 6374c980..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/Attribute.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.DERSequence;
-
-public class Attribute
- extends ASN1Object
-{
- private ASN1ObjectIdentifier attrType;
- private ASN1Set attrValues;
-
- /**
- * return an Attribute object from the given object.
- *
- * @param o the object we want converted.
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static Attribute getInstance(
- Object o)
- {
- if (o == null || o instanceof Attribute)
- {
- return (Attribute)o;
- }
-
- if (o instanceof ASN1Sequence)
- {
- return new Attribute((ASN1Sequence)o);
- }
-
- throw new IllegalArgumentException("unknown object in factory: " + o.getClass().getName());
- }
-
- public Attribute(
- ASN1Sequence seq)
- {
- attrType = (ASN1ObjectIdentifier)seq.getObjectAt(0);
- attrValues = (ASN1Set)seq.getObjectAt(1);
- }
-
- public Attribute(
- ASN1ObjectIdentifier attrType,
- ASN1Set attrValues)
- {
- this.attrType = attrType;
- this.attrValues = attrValues;
- }
-
- public ASN1ObjectIdentifier getAttrType()
- {
- return attrType;
- }
-
- public ASN1Set getAttrValues()
- {
- return attrValues;
- }
-
- public ASN1Encodable[] getAttributeValues()
- {
- return attrValues.toArray();
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * Attribute ::= SEQUENCE {
- * attrType OBJECT IDENTIFIER,
- * attrValues SET OF AttributeValue
- * }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(attrType);
- v.add(attrValues);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/AuthenticatedSafe.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/AuthenticatedSafe.java
deleted file mode 100644
index ea4779bb..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/AuthenticatedSafe.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.BERSequence;
-import org.bouncycastle.asn1.DLSequence;
-
-public class AuthenticatedSafe
- extends ASN1Object
-{
- private ContentInfo[] info;
- private boolean isBer = true;
-
- private AuthenticatedSafe(
- ASN1Sequence seq)
- {
- info = new ContentInfo[seq.size()];
-
- for (int i = 0; i != info.length; i++)
- {
- info[i] = ContentInfo.getInstance(seq.getObjectAt(i));
- }
-
- isBer = seq instanceof BERSequence;
- }
-
- public static AuthenticatedSafe getInstance(
- Object o)
- {
- if (o instanceof AuthenticatedSafe)
- {
- return (AuthenticatedSafe)o;
- }
-
- if (o != null)
- {
- return new AuthenticatedSafe(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public AuthenticatedSafe(
- ContentInfo[] info)
- {
- this.info = info;
- }
-
- public ContentInfo[] getContentInfo()
- {
- return info;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- for (int i = 0; i != info.length; i++)
- {
- v.add(info[i]);
- }
-
- if (isBer)
- {
- return new BERSequence(v);
- }
- else
- {
- return new DLSequence(v);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/CRLBag.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/CRLBag.java
deleted file mode 100644
index 06208731..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/CRLBag.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-public class CRLBag
- extends ASN1Object
-{
- private ASN1ObjectIdentifier crlId;
- private ASN1Encodable crlValue;
-
- private CRLBag(
- ASN1Sequence seq)
- {
- this.crlId = (ASN1ObjectIdentifier)seq.getObjectAt(0);
- this.crlValue = ((DERTaggedObject)seq.getObjectAt(1)).getObject();
- }
-
- public static CRLBag getInstance(Object o)
- {
- if (o instanceof CRLBag)
- {
- return (CRLBag)o;
- }
- else if (o != null)
- {
- return new CRLBag(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public CRLBag(
- ASN1ObjectIdentifier crlId,
- ASN1Encodable crlValue)
- {
- this.crlId = crlId;
- this.crlValue = crlValue;
- }
-
- public ASN1ObjectIdentifier getcrlId()
- {
- return crlId;
- }
-
- public ASN1Encodable getCRLValue()
- {
- return crlValue;
- }
-
- /**
- * <pre>
- * CRLBag ::= SEQUENCE {
- * crlId BAG-TYPE.&amp;id ({CRLTypes}),
- * crlValue [0] EXPLICIT BAG-TYPE.&amp;Type ({CRLTypes}{@crlId})
- * }
- *
- * x509CRL BAG-TYPE ::= {OCTET STRING IDENTIFIED BY {certTypes 1}
- * -- DER-encoded X.509 CRL stored in OCTET STRING
- *
- * CRLTypes BAG-TYPE ::= {
- * x509CRL,
- * ... -- For future extensions
- * }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(crlId);
- v.add(new DERTaggedObject(0, crlValue));
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/CertBag.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/CertBag.java
deleted file mode 100644
index 4a730286..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/CertBag.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-public class CertBag
- extends ASN1Object
-{
- private ASN1ObjectIdentifier certId;
- private ASN1Encodable certValue;
-
- private CertBag(
- ASN1Sequence seq)
- {
- this.certId = (ASN1ObjectIdentifier)seq.getObjectAt(0);
- this.certValue = ((DERTaggedObject)seq.getObjectAt(1)).getObject();
- }
-
- public static CertBag getInstance(Object o)
- {
- if (o instanceof CertBag)
- {
- return (CertBag)o;
- }
- else if (o != null)
- {
- return new CertBag(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public CertBag(
- ASN1ObjectIdentifier certId,
- ASN1Encodable certValue)
- {
- this.certId = certId;
- this.certValue = certValue;
- }
-
- public ASN1ObjectIdentifier getCertId()
- {
- return certId;
- }
-
- public ASN1Encodable getCertValue()
- {
- return certValue;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(certId);
- v.add(new DERTaggedObject(0, certValue));
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequest.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequest.java
deleted file mode 100644
index 987d4eba..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequest.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-/**
- * PKCS10 Certification request object.
- * <pre>
- * CertificationRequest ::= SEQUENCE {
- * certificationRequestInfo CertificationRequestInfo,
- * signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }},
- * signature BIT STRING
- * }
- * </pre>
- */
-public class CertificationRequest
- extends ASN1Object
-{
- protected CertificationRequestInfo reqInfo = null;
- protected AlgorithmIdentifier sigAlgId = null;
- protected DERBitString sigBits = null;
-
- public static CertificationRequest getInstance(Object o)
- {
- if (o instanceof CertificationRequest)
- {
- return (CertificationRequest)o;
- }
-
- if (o != null)
- {
- return new CertificationRequest(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- protected CertificationRequest()
- {
- }
-
- public CertificationRequest(
- CertificationRequestInfo requestInfo,
- AlgorithmIdentifier algorithm,
- DERBitString signature)
- {
- this.reqInfo = requestInfo;
- this.sigAlgId = algorithm;
- this.sigBits = signature;
- }
-
- public CertificationRequest(
- ASN1Sequence seq)
- {
- reqInfo = CertificationRequestInfo.getInstance(seq.getObjectAt(0));
- sigAlgId = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
- sigBits = (DERBitString)seq.getObjectAt(2);
- }
-
- public CertificationRequestInfo getCertificationRequestInfo()
- {
- return reqInfo;
- }
-
- public AlgorithmIdentifier getSignatureAlgorithm()
- {
- return sigAlgId;
- }
-
- public DERBitString getSignature()
- {
- return sigBits;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- // Construct the CertificateRequest
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(reqInfo);
- v.add(sigAlgId);
- v.add(sigBits);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java
deleted file mode 100644
index d2acd303..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java
+++ /dev/null
@@ -1,164 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-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.ASN1Set;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.asn1.x509.X509Name;
-
-/**
- * PKCS10 CertificationRequestInfo object.
- * <pre>
- * CertificationRequestInfo ::= SEQUENCE {
- * version INTEGER { v1(0) } (v1,...),
- * subject Name,
- * subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
- * attributes [0] Attributes{{ CRIAttributes }}
- * }
- *
- * Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }}
- *
- * Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
- * type ATTRIBUTE.&amp;id({IOSet}),
- * values SET SIZE(1..MAX) OF ATTRIBUTE.&amp;Type({IOSet}{\@type})
- * }
- * </pre>
- */
-public class CertificationRequestInfo
- extends ASN1Object
-{
- ASN1Integer version = new ASN1Integer(0);
- X500Name subject;
- SubjectPublicKeyInfo subjectPKInfo;
- ASN1Set attributes = null;
-
- public static CertificationRequestInfo getInstance(
- Object obj)
- {
- if (obj instanceof CertificationRequestInfo)
- {
- return (CertificationRequestInfo)obj;
- }
- else if (obj != null)
- {
- return new CertificationRequestInfo(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- /**
- * Basic constructor.
- * <p>
- * Note: Early on a lot of CAs would only accept messages with attributes missing. As the ASN.1 def shows
- * the attributes field is not optional so should always at least contain an empty set. If a fully compliant
- * request is required, pass in an empty set, the class will otherwise interpret a null as it should
- * encode the request with the field missing.
- * </p>
- *
- * @param subject subject to be associated with the public key
- * @param pkInfo public key to be associated with subject
- * @param attributes any attributes to be associated with the request.
- */
- public CertificationRequestInfo(
- X500Name subject,
- SubjectPublicKeyInfo pkInfo,
- ASN1Set attributes)
- {
- this.subject = subject;
- this.subjectPKInfo = pkInfo;
- this.attributes = attributes;
-
- if ((subject == null) || (version == null) || (subjectPKInfo == null))
- {
- throw new IllegalArgumentException("Not all mandatory fields set in CertificationRequestInfo generator.");
- }
- }
-
- /**
- * @deprecated use X500Name method.
- */
- public CertificationRequestInfo(
- X509Name subject,
- SubjectPublicKeyInfo pkInfo,
- ASN1Set attributes)
- {
- this.subject = X500Name.getInstance(subject.toASN1Primitive());
- this.subjectPKInfo = pkInfo;
- this.attributes = attributes;
-
- if ((subject == null) || (version == null) || (subjectPKInfo == null))
- {
- throw new IllegalArgumentException("Not all mandatory fields set in CertificationRequestInfo generator.");
- }
- }
-
- /**
- * @deprecated use getInstance().
- */
- public CertificationRequestInfo(
- ASN1Sequence seq)
- {
- version = (ASN1Integer)seq.getObjectAt(0);
-
- subject = X500Name.getInstance(seq.getObjectAt(1));
- subjectPKInfo = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(2));
-
- //
- // some CertificationRequestInfo objects seem to treat this field
- // as optional.
- //
- if (seq.size() > 3)
- {
- DERTaggedObject tagobj = (DERTaggedObject)seq.getObjectAt(3);
- attributes = ASN1Set.getInstance(tagobj, false);
- }
-
- if ((subject == null) || (version == null) || (subjectPKInfo == null))
- {
- throw new IllegalArgumentException("Not all mandatory fields set in CertificationRequestInfo generator.");
- }
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public X500Name getSubject()
- {
- return subject;
- }
-
- public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
- {
- return subjectPKInfo;
- }
-
- public ASN1Set getAttributes()
- {
- return attributes;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(version);
- v.add(subject);
- v.add(subjectPKInfo);
-
- if (attributes != null)
- {
- v.add(new DERTaggedObject(false, 0, attributes));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/ContentInfo.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/ContentInfo.java
deleted file mode 100644
index 1ee920fd..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/ContentInfo.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.BERSequence;
-import org.bouncycastle.asn1.BERTaggedObject;
-import org.bouncycastle.asn1.DLSequence;
-
-public class ContentInfo
- extends ASN1Object
- implements PKCSObjectIdentifiers
-{
- private ASN1ObjectIdentifier contentType;
- private ASN1Encodable content;
- private boolean isBer = true;
-
- public static ContentInfo getInstance(
- Object obj)
- {
- if (obj instanceof ContentInfo)
- {
- return (ContentInfo)obj;
- }
-
- if (obj != null)
- {
- return new ContentInfo(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private ContentInfo(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- contentType = (ASN1ObjectIdentifier)e.nextElement();
-
- if (e.hasMoreElements())
- {
- content = ((ASN1TaggedObject)e.nextElement()).getObject();
- }
-
- isBer = seq instanceof BERSequence;
- }
-
- public ContentInfo(
- ASN1ObjectIdentifier contentType,
- ASN1Encodable content)
- {
- this.contentType = contentType;
- this.content = content;
- }
-
- public ASN1ObjectIdentifier getContentType()
- {
- return contentType;
- }
-
- public ASN1Encodable getContent()
- {
- return content;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * ContentInfo ::= SEQUENCE {
- * contentType ContentType,
- * content
- * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(contentType);
-
- if (content != null)
- {
- v.add(new BERTaggedObject(true, 0, content));
- }
-
- if (isBer)
- {
- return new BERSequence(v);
- }
- else
- {
- return new DLSequence(v);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/DHParameter.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/DHParameter.java
deleted file mode 100644
index fa22f792..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/DHParameter.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-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.DERSequence;
-
-public class DHParameter
- extends ASN1Object
-{
- ASN1Integer p, g, l;
-
- public DHParameter(
- BigInteger p,
- BigInteger g,
- int l)
- {
- this.p = new ASN1Integer(p);
- this.g = new ASN1Integer(g);
-
- if (l != 0)
- {
- this.l = new ASN1Integer(l);
- }
- else
- {
- this.l = null;
- }
- }
-
- public static DHParameter getInstance(
- Object obj)
- {
- if (obj instanceof DHParameter)
- {
- return (DHParameter)obj;
- }
-
- if (obj != null)
- {
- return new DHParameter(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private DHParameter(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- p = ASN1Integer.getInstance(e.nextElement());
- g = ASN1Integer.getInstance(e.nextElement());
-
- if (e.hasMoreElements())
- {
- l = (ASN1Integer)e.nextElement();
- }
- else
- {
- l = null;
- }
- }
-
- public BigInteger getP()
- {
- return p.getPositiveValue();
- }
-
- public BigInteger getG()
- {
- return g.getPositiveValue();
- }
-
- public BigInteger getL()
- {
- if (l == null)
- {
- return null;
- }
-
- return l.getPositiveValue();
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(p);
- v.add(g);
-
- if (this.getL() != null)
- {
- v.add(l);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/EncryptedData.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/EncryptedData.java
deleted file mode 100644
index e0f5efdf..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/EncryptedData.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.BERSequence;
-import org.bouncycastle.asn1.BERTaggedObject;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-/**
- * The EncryptedData object.
- * <pre>
- * EncryptedData ::= SEQUENCE {
- * version Version,
- * encryptedContentInfo EncryptedContentInfo
- * }
- *
- *
- * EncryptedContentInfo ::= SEQUENCE {
- * contentType ContentType,
- * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
- * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
- * }
- *
- * EncryptedContent ::= OCTET STRING
- * </pre>
- */
-public class EncryptedData
- extends ASN1Object
-{
- ASN1Sequence data;
- ASN1ObjectIdentifier bagId;
- ASN1Primitive bagValue;
-
- public static EncryptedData getInstance(
- Object obj)
- {
- if (obj instanceof EncryptedData)
- {
- return (EncryptedData)obj;
- }
-
- if (obj != null)
- {
- return new EncryptedData(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private EncryptedData(
- ASN1Sequence seq)
- {
- int version = ((ASN1Integer)seq.getObjectAt(0)).getValue().intValue();
-
- if (version != 0)
- {
- throw new IllegalArgumentException("sequence not version 0");
- }
-
- this.data = ASN1Sequence.getInstance(seq.getObjectAt(1));
- }
-
- public EncryptedData(
- ASN1ObjectIdentifier contentType,
- AlgorithmIdentifier encryptionAlgorithm,
- ASN1Encodable content)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(contentType);
- v.add(encryptionAlgorithm.toASN1Primitive());
- v.add(new BERTaggedObject(false, 0, content));
-
- data = new BERSequence(v);
- }
-
- public ASN1ObjectIdentifier getContentType()
- {
- return ASN1ObjectIdentifier.getInstance(data.getObjectAt(0));
- }
-
- public AlgorithmIdentifier getEncryptionAlgorithm()
- {
- return AlgorithmIdentifier.getInstance(data.getObjectAt(1));
- }
-
- public ASN1OctetString getContent()
- {
- if (data.size() == 3)
- {
- ASN1TaggedObject o = ASN1TaggedObject.getInstance(data.getObjectAt(2));
-
- return ASN1OctetString.getInstance(o, false);
- }
-
- return null;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(new ASN1Integer(0));
- v.add(data);
-
- return new BERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/EncryptedPrivateKeyInfo.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/EncryptedPrivateKeyInfo.java
deleted file mode 100644
index acbe04a9..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/EncryptedPrivateKeyInfo.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-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.asn1.x509.AlgorithmIdentifier;
-
-public class EncryptedPrivateKeyInfo
- extends ASN1Object
-{
- private AlgorithmIdentifier algId;
- private ASN1OctetString data;
-
- private EncryptedPrivateKeyInfo(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- algId = AlgorithmIdentifier.getInstance(e.nextElement());
- data = ASN1OctetString.getInstance(e.nextElement());
- }
-
- public EncryptedPrivateKeyInfo(
- AlgorithmIdentifier algId,
- byte[] encoding)
- {
- this.algId = algId;
- this.data = new DEROctetString(encoding);
- }
-
- public static EncryptedPrivateKeyInfo getInstance(
- Object obj)
- {
- if (obj instanceof EncryptedPrivateKeyInfo)
- {
- return (EncryptedPrivateKeyInfo)obj;
- }
- else if (obj != null)
- {
- return new EncryptedPrivateKeyInfo(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public AlgorithmIdentifier getEncryptionAlgorithm()
- {
- return algId;
- }
-
- public byte[] getEncryptedData()
- {
- return data.getOctets();
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * EncryptedPrivateKeyInfo ::= SEQUENCE {
- * encryptionAlgorithm AlgorithmIdentifier {{KeyEncryptionAlgorithms}},
- * encryptedData EncryptedData
- * }
- *
- * EncryptedData ::= OCTET STRING
- *
- * KeyEncryptionAlgorithms ALGORITHM-IDENTIFIER ::= {
- * ... -- For local profiles
- * }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(algId);
- v.add(data);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/EncryptionScheme.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/EncryptionScheme.java
deleted file mode 100644
index 848f4fcf..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/EncryptionScheme.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-public class EncryptionScheme
- extends ASN1Object
-{
- private AlgorithmIdentifier algId;
-
- public EncryptionScheme(
- ASN1ObjectIdentifier objectId,
- ASN1Encodable parameters)
- {
- this.algId = new AlgorithmIdentifier(objectId, parameters);
- }
-
- private EncryptionScheme(
- ASN1Sequence seq)
- {
- this.algId = AlgorithmIdentifier.getInstance(seq);
- }
-
- public static EncryptionScheme getInstance(Object obj)
- {
- if (obj instanceof EncryptionScheme)
- {
- return (EncryptionScheme)obj;
- }
- else if (obj != null)
- {
- return new EncryptionScheme(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public ASN1ObjectIdentifier getAlgorithm()
- {
- return algId.getAlgorithm();
- }
-
- public ASN1Encodable getParameters()
- {
- return algId.getParameters();
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return algId.toASN1Primitive();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/IssuerAndSerialNumber.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/IssuerAndSerialNumber.java
deleted file mode 100644
index 6cbf907a..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/IssuerAndSerialNumber.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-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.DERSequence;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x509.X509Name;
-
-public class IssuerAndSerialNumber
- extends ASN1Object
-{
- X500Name name;
- ASN1Integer certSerialNumber;
-
- public static IssuerAndSerialNumber getInstance(
- Object obj)
- {
- if (obj instanceof IssuerAndSerialNumber)
- {
- return (IssuerAndSerialNumber)obj;
- }
- else if (obj != null)
- {
- return new IssuerAndSerialNumber(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private IssuerAndSerialNumber(
- ASN1Sequence seq)
- {
- this.name = X500Name.getInstance(seq.getObjectAt(0));
- this.certSerialNumber = (ASN1Integer)seq.getObjectAt(1);
- }
-
- public IssuerAndSerialNumber(
- X509Name name,
- BigInteger certSerialNumber)
- {
- this.name = X500Name.getInstance(name.toASN1Primitive());
- this.certSerialNumber = new ASN1Integer(certSerialNumber);
- }
-
- public IssuerAndSerialNumber(
- X509Name name,
- ASN1Integer certSerialNumber)
- {
- this.name = X500Name.getInstance(name.toASN1Primitive());
- this.certSerialNumber = certSerialNumber;
- }
-
- public IssuerAndSerialNumber(
- X500Name name,
- BigInteger certSerialNumber)
- {
- this.name = name;
- this.certSerialNumber = new ASN1Integer(certSerialNumber);
- }
-
- public X500Name getName()
- {
- return name;
- }
-
- public ASN1Integer getCertificateSerialNumber()
- {
- return certSerialNumber;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(name);
- v.add(certSerialNumber);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/KeyDerivationFunc.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/KeyDerivationFunc.java
deleted file mode 100644
index 83804f38..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/KeyDerivationFunc.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-public class KeyDerivationFunc
- extends ASN1Object
-{
- private AlgorithmIdentifier algId;
-
- public KeyDerivationFunc(
- ASN1ObjectIdentifier objectId,
- ASN1Encodable parameters)
- {
- this.algId = new AlgorithmIdentifier(objectId, parameters);
- }
-
- private KeyDerivationFunc(
- ASN1Sequence seq)
- {
- this.algId = AlgorithmIdentifier.getInstance(seq);
- }
-
- public static KeyDerivationFunc getInstance(Object obj)
- {
- if (obj instanceof KeyDerivationFunc)
- {
- return (KeyDerivationFunc)obj;
- }
- else if (obj != null)
- {
- return new KeyDerivationFunc(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public ASN1ObjectIdentifier getAlgorithm()
- {
- return algId.getAlgorithm();
- }
-
- public ASN1Encodable getParameters()
- {
- return algId.getParameters();
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return algId.toASN1Primitive();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/MacData.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/MacData.java
deleted file mode 100644
index 1d8f582c..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/MacData.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.math.BigInteger;
-
-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.asn1.x509.DigestInfo;
-
-public class MacData
- extends ASN1Object
-{
- private static final BigInteger ONE = BigInteger.valueOf(1);
-
- DigestInfo digInfo;
- byte[] salt;
- BigInteger iterationCount;
-
- public static MacData getInstance(
- Object obj)
- {
- if (obj instanceof MacData)
- {
- return (MacData)obj;
- }
- else if (obj != null)
- {
- return new MacData(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private MacData(
- ASN1Sequence seq)
- {
- this.digInfo = DigestInfo.getInstance(seq.getObjectAt(0));
-
- this.salt = ((ASN1OctetString)seq.getObjectAt(1)).getOctets();
-
- if (seq.size() == 3)
- {
- this.iterationCount = ((ASN1Integer)seq.getObjectAt(2)).getValue();
- }
- else
- {
- this.iterationCount = ONE;
- }
- }
-
- public MacData(
- DigestInfo digInfo,
- byte[] salt,
- int iterationCount)
- {
- this.digInfo = digInfo;
- this.salt = salt;
- this.iterationCount = BigInteger.valueOf(iterationCount);
- }
-
- public DigestInfo getMac()
- {
- return digInfo;
- }
-
- public byte[] getSalt()
- {
- return salt;
- }
-
- public BigInteger getIterationCount()
- {
- return iterationCount;
- }
-
- /**
- * <pre>
- * MacData ::= SEQUENCE {
- * mac DigestInfo,
- * macSalt OCTET STRING,
- * iterations INTEGER DEFAULT 1
- * -- Note: The default is for historic reasons and its use is deprecated. A
- * -- higher value, like 1024 is recommended.
- * </pre>
- * @return the basic ASN1Primitive construction.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(digInfo);
- v.add(new DEROctetString(salt));
-
- if (!iterationCount.equals(ONE))
- {
- v.add(new ASN1Integer(iterationCount));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/PBEParameter.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/PBEParameter.java
deleted file mode 100644
index 06180dfe..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/PBEParameter.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.math.BigInteger;
-
-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;
-
-public class PBEParameter
- extends ASN1Object
-{
- ASN1Integer iterations;
- ASN1OctetString salt;
-
- public PBEParameter(
- byte[] salt,
- int iterations)
- {
- if (salt.length != 8)
- {
- throw new IllegalArgumentException("salt length must be 8");
- }
- this.salt = new DEROctetString(salt);
- this.iterations = new ASN1Integer(iterations);
- }
-
- private PBEParameter(
- ASN1Sequence seq)
- {
- salt = (ASN1OctetString)seq.getObjectAt(0);
- iterations = (ASN1Integer)seq.getObjectAt(1);
- }
-
- public static PBEParameter getInstance(
- Object obj)
- {
- if (obj instanceof PBEParameter)
- {
- return (PBEParameter)obj;
- }
- else if (obj != null)
- {
- return new PBEParameter(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public BigInteger getIterationCount()
- {
- return iterations.getValue();
- }
-
- public byte[] getSalt()
- {
- return salt.getOctets();
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(salt);
- v.add(iterations);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/PBES2Algorithms.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/PBES2Algorithms.java
deleted file mode 100644
index db44a82a..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/PBES2Algorithms.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-/**
- * @deprecated - use AlgorithmIdentifier and PBES2Parameters
- */
-public class PBES2Algorithms
- extends AlgorithmIdentifier implements PKCSObjectIdentifiers
-{
- private ASN1ObjectIdentifier objectId;
- private KeyDerivationFunc func;
- private EncryptionScheme scheme;
-
- public PBES2Algorithms(
- ASN1Sequence obj)
- {
- super(obj);
-
- Enumeration e = obj.getObjects();
-
- objectId = (ASN1ObjectIdentifier)e.nextElement();
-
- ASN1Sequence seq = (ASN1Sequence)e.nextElement();
-
- e = seq.getObjects();
-
- ASN1Sequence funcSeq = (ASN1Sequence)e.nextElement();
-
- if (funcSeq.getObjectAt(0).equals(id_PBKDF2))
- {
- func = new KeyDerivationFunc(id_PBKDF2, PBKDF2Params.getInstance(funcSeq.getObjectAt(1)));
- }
- else
- {
- func = KeyDerivationFunc.getInstance(funcSeq);
- }
-
- scheme = EncryptionScheme.getInstance(e.nextElement());
- }
-
- public ASN1ObjectIdentifier getObjectId()
- {
- return objectId;
- }
-
- public KeyDerivationFunc getKeyDerivationFunc()
- {
- return func;
- }
-
- public EncryptionScheme getEncryptionScheme()
- {
- return scheme;
- }
-
- public ASN1Primitive getASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- ASN1EncodableVector subV = new ASN1EncodableVector();
-
- v.add(objectId);
-
- subV.add(func);
- subV.add(scheme);
- v.add(new DERSequence(subV));
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/PBES2Parameters.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/PBES2Parameters.java
deleted file mode 100644
index b47e9cdd..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/PBES2Parameters.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-public class PBES2Parameters
- extends ASN1Object
- implements PKCSObjectIdentifiers
-{
- private KeyDerivationFunc func;
- private EncryptionScheme scheme;
-
- public static PBES2Parameters getInstance(
- Object obj)
- {
- if (obj instanceof PBES2Parameters)
- {
- return (PBES2Parameters)obj;
- }
- if (obj != null)
- {
- return new PBES2Parameters(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public PBES2Parameters(KeyDerivationFunc keyDevFunc, EncryptionScheme encScheme)
- {
- this.func = keyDevFunc;
- this.scheme = encScheme;
- }
-
- private PBES2Parameters(
- ASN1Sequence obj)
- {
- Enumeration e = obj.getObjects();
- ASN1Sequence funcSeq = ASN1Sequence.getInstance(((ASN1Encodable)e.nextElement()).toASN1Primitive());
-
- if (funcSeq.getObjectAt(0).equals(id_PBKDF2))
- {
- func = new KeyDerivationFunc(id_PBKDF2, PBKDF2Params.getInstance(funcSeq.getObjectAt(1)));
- }
- else
- {
- func = KeyDerivationFunc.getInstance(funcSeq);
- }
-
- scheme = EncryptionScheme.getInstance(e.nextElement());
- }
-
- public KeyDerivationFunc getKeyDerivationFunc()
- {
- return func;
- }
-
- public EncryptionScheme getEncryptionScheme()
- {
- return scheme;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(func);
- v.add(scheme);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/PBKDF2Params.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/PBKDF2Params.java
deleted file mode 100644
index 92c4e8f1..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/PBKDF2Params.java
+++ /dev/null
@@ -1,248 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-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.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)
- {
- if (obj instanceof PBKDF2Params)
- {
- return (PBKDF2Params)obj;
- }
-
- if (obj != null)
- {
- return new PBKDF2Params(ASN1Sequence.getInstance(obj));
- }
-
- 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)
- {
- this.octStr = new DEROctetString(salt);
- 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,
- int keyLength)
- {
- this(salt, iterationCount);
-
- 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)
- {
- Enumeration e = seq.getObjects();
-
- octStr = (ASN1OctetString)e.nextElement();
- iterationCount = (ASN1Integer)e.nextElement();
-
- if (e.hasMoreElements())
- {
- 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)
- {
- return keyLength.getValue();
- }
-
- 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();
-
- v.add(octStr);
- v.add(iterationCount);
-
- if (keyLength != null)
- {
- v.add(keyLength);
- }
-
- if (prf != null && !prf.equals(algid_hmacWithSHA1))
- {
- v.add(prf);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/PKCS12PBEParams.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/PKCS12PBEParams.java
deleted file mode 100644
index 0ddf5c34..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/PKCS12PBEParams.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.math.BigInteger;
-
-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;
-
-public class PKCS12PBEParams
- extends ASN1Object
-{
- ASN1Integer iterations;
- ASN1OctetString iv;
-
- public PKCS12PBEParams(
- byte[] salt,
- int iterations)
- {
- this.iv = new DEROctetString(salt);
- this.iterations = new ASN1Integer(iterations);
- }
-
- private PKCS12PBEParams(
- ASN1Sequence seq)
- {
- iv = (ASN1OctetString)seq.getObjectAt(0);
- iterations = ASN1Integer.getInstance(seq.getObjectAt(1));
- }
-
- public static PKCS12PBEParams getInstance(
- Object obj)
- {
- if (obj instanceof PKCS12PBEParams)
- {
- return (PKCS12PBEParams)obj;
- }
- else if (obj != null)
- {
- return new PKCS12PBEParams(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public BigInteger getIterations()
- {
- return iterations.getValue();
- }
-
- public byte[] getIV()
- {
- return iv.getOctets();
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(iv);
- v.add(iterations);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java
deleted file mode 100644
index 05fced04..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java
+++ /dev/null
@@ -1,390 +0,0 @@
-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: 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}
- //
- /** 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}
- //
- /** 1.2.840.113549.2.5 */
- static final ASN1ObjectIdentifier md5 = digestAlgorithm.branch("5");
-
- /** 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 }
- //
- /** 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");
-
- /** 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");
- /** 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");
-
- /** 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");
-
- //
- // 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");
-
- /** 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");
- /** 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");
-
- /** 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}
- *
- */
- /** 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;
- /** @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;
-
- /**
- * 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";
-
- /** 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");
-
- /** PKCS#12: 1.2.840.113549.1.12.1 */
- static final ASN1ObjectIdentifier pkcs_12PbeIds = pkcs_12.branch("1");
-
- /** PKCS#12: 1.2.840.113549.1.12.1.1 */
- static final ASN1ObjectIdentifier pbeWithSHAAnd128BitRC4 = pkcs_12PbeIds.branch("1");
- /** 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");
- /** 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");
- /** 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/core/src/main/java/org/bouncycastle/asn1/pkcs/Pfx.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/Pfx.java
deleted file mode 100644
index 7885a795..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/Pfx.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-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.BERSequence;
-
-/**
- * the infamous Pfx from PKCS12
- */
-public class Pfx
- extends ASN1Object
- implements PKCSObjectIdentifiers
-{
- private ContentInfo contentInfo;
- private MacData macData = null;
-
- private Pfx(
- ASN1Sequence seq)
- {
- BigInteger version = ((ASN1Integer)seq.getObjectAt(0)).getValue();
- if (version.intValue() != 3)
- {
- throw new IllegalArgumentException("wrong version for PFX PDU");
- }
-
- contentInfo = ContentInfo.getInstance(seq.getObjectAt(1));
-
- if (seq.size() == 3)
- {
- macData = MacData.getInstance(seq.getObjectAt(2));
- }
- }
-
- public static Pfx getInstance(
- Object obj)
- {
- if (obj instanceof Pfx)
- {
- return (Pfx)obj;
- }
-
- if (obj != null)
- {
- return new Pfx(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public Pfx(
- ContentInfo contentInfo,
- MacData macData)
- {
- this.contentInfo = contentInfo;
- this.macData = macData;
- }
-
- public ContentInfo getAuthSafe()
- {
- return contentInfo;
- }
-
- public MacData getMacData()
- {
- return macData;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(new ASN1Integer(3));
- v.add(contentInfo);
-
- if (macData != null)
- {
- v.add(macData);
- }
-
- return new BERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/PrivateKeyInfo.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/PrivateKeyInfo.java
deleted file mode 100644
index 7f02e709..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/PrivateKeyInfo.java
+++ /dev/null
@@ -1,164 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.io.IOException;
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Encoding;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-public class PrivateKeyInfo
- extends ASN1Object
-{
- private ASN1OctetString privKey;
- private AlgorithmIdentifier algId;
- private ASN1Set attributes;
-
- public static PrivateKeyInfo getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static PrivateKeyInfo getInstance(
- Object obj)
- {
- if (obj instanceof PrivateKeyInfo)
- {
- return (PrivateKeyInfo)obj;
- }
- else if (obj != null)
- {
- return new PrivateKeyInfo(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public PrivateKeyInfo(
- AlgorithmIdentifier algId,
- ASN1Encodable privateKey)
- throws IOException
- {
- this(algId, privateKey, null);
- }
-
- public PrivateKeyInfo(
- AlgorithmIdentifier algId,
- ASN1Encodable privateKey,
- ASN1Set attributes)
- throws IOException
- {
- this.privKey = new DEROctetString(privateKey.toASN1Primitive().getEncoded(ASN1Encoding.DER));
- this.algId = algId;
- this.attributes = attributes;
- }
-
- /**
- * @deprecated use PrivateKeyInfo.getInstance()
- * @param seq
- */
- public PrivateKeyInfo(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- BigInteger version = ((ASN1Integer)e.nextElement()).getValue();
- if (version.intValue() != 0)
- {
- throw new IllegalArgumentException("wrong version for private key info");
- }
-
- algId = AlgorithmIdentifier.getInstance(e.nextElement());
- privKey = ASN1OctetString.getInstance(e.nextElement());
-
- if (e.hasMoreElements())
- {
- attributes = ASN1Set.getInstance((ASN1TaggedObject)e.nextElement(), false);
- }
- }
-
- public AlgorithmIdentifier getPrivateKeyAlgorithm()
- {
- return algId;
- }
- /**
- * @deprecated use getPrivateKeyAlgorithm()
- */
- public AlgorithmIdentifier getAlgorithmId()
- {
- return algId;
- }
-
- public ASN1Encodable parsePrivateKey()
- throws IOException
- {
- return ASN1Primitive.fromByteArray(privKey.getOctets());
- }
-
- /**
- * @deprecated use parsePrivateKey()
- */
- public ASN1Primitive getPrivateKey()
- {
- try
- {
- return parsePrivateKey().toASN1Primitive();
- }
- catch (IOException e)
- {
- throw new IllegalStateException("unable to parse private key");
- }
- }
-
- public ASN1Set getAttributes()
- {
- return attributes;
- }
-
- /**
- * write out an RSA private key with its associated information
- * as described in PKCS8.
- * <pre>
- * PrivateKeyInfo ::= SEQUENCE {
- * version Version,
- * privateKeyAlgorithm AlgorithmIdentifier {{PrivateKeyAlgorithms}},
- * privateKey PrivateKey,
- * attributes [0] IMPLICIT Attributes OPTIONAL
- * }
- * Version ::= INTEGER {v1(0)} (v1,...)
- *
- * PrivateKey ::= OCTET STRING
- *
- * Attributes ::= SET OF Attribute
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(new ASN1Integer(0));
- v.add(algId);
- v.add(privKey);
-
- if (attributes != null)
- {
- v.add(new DERTaggedObject(false, 0, attributes));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/RC2CBCParameter.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/RC2CBCParameter.java
deleted file mode 100644
index 0a116f71..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/RC2CBCParameter.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.math.BigInteger;
-
-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;
-
-public class RC2CBCParameter
- extends ASN1Object
-{
- ASN1Integer version;
- ASN1OctetString iv;
-
- public static RC2CBCParameter getInstance(
- Object o)
- {
- if (o instanceof RC2CBCParameter)
- {
- return (RC2CBCParameter)o;
- }
- if (o != null)
- {
- return new RC2CBCParameter(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public RC2CBCParameter(
- byte[] iv)
- {
- this.version = null;
- this.iv = new DEROctetString(iv);
- }
-
- public RC2CBCParameter(
- int parameterVersion,
- byte[] iv)
- {
- this.version = new ASN1Integer(parameterVersion);
- this.iv = new DEROctetString(iv);
- }
-
- private RC2CBCParameter(
- ASN1Sequence seq)
- {
- if (seq.size() == 1)
- {
- version = null;
- iv = (ASN1OctetString)seq.getObjectAt(0);
- }
- else
- {
- version = (ASN1Integer)seq.getObjectAt(0);
- iv = (ASN1OctetString)seq.getObjectAt(1);
- }
- }
-
- public BigInteger getRC2ParameterVersion()
- {
- if (version == null)
- {
- return null;
- }
-
- return version.getValue();
- }
-
- public byte[] getIV()
- {
- return iv.getOctets();
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (version != null)
- {
- v.add(version);
- }
-
- v.add(iv);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java
deleted file mode 100644
index e707fd10..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java
+++ /dev/null
@@ -1,155 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-public class RSAESOAEPparams
- extends ASN1Object
-{
- private AlgorithmIdentifier hashAlgorithm;
- private AlgorithmIdentifier maskGenAlgorithm;
- private AlgorithmIdentifier pSourceAlgorithm;
-
- public final static AlgorithmIdentifier DEFAULT_HASH_ALGORITHM = new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE);
- public final static AlgorithmIdentifier DEFAULT_MASK_GEN_FUNCTION = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_mgf1, DEFAULT_HASH_ALGORITHM);
- public final static AlgorithmIdentifier DEFAULT_P_SOURCE_ALGORITHM = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_pSpecified, new DEROctetString(new byte[0]));
-
- public static RSAESOAEPparams getInstance(
- Object obj)
- {
- if (obj instanceof RSAESOAEPparams)
- {
- return (RSAESOAEPparams)obj;
- }
- else if (obj != null)
- {
- return new RSAESOAEPparams(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- /**
- * The default version
- */
- public RSAESOAEPparams()
- {
- hashAlgorithm = DEFAULT_HASH_ALGORITHM;
- maskGenAlgorithm = DEFAULT_MASK_GEN_FUNCTION;
- pSourceAlgorithm = DEFAULT_P_SOURCE_ALGORITHM;
- }
-
- public RSAESOAEPparams(
- AlgorithmIdentifier hashAlgorithm,
- AlgorithmIdentifier maskGenAlgorithm,
- AlgorithmIdentifier pSourceAlgorithm)
- {
- this.hashAlgorithm = hashAlgorithm;
- this.maskGenAlgorithm = maskGenAlgorithm;
- this.pSourceAlgorithm = pSourceAlgorithm;
- }
-
- /**
- * @deprecated use getInstance()
- * @param seq
- */
- public RSAESOAEPparams(
- ASN1Sequence seq)
- {
- hashAlgorithm = DEFAULT_HASH_ALGORITHM;
- maskGenAlgorithm = DEFAULT_MASK_GEN_FUNCTION;
- pSourceAlgorithm = DEFAULT_P_SOURCE_ALGORITHM;
-
- for (int i = 0; i != seq.size(); i++)
- {
- ASN1TaggedObject o = (ASN1TaggedObject)seq.getObjectAt(i);
-
- switch (o.getTagNo())
- {
- case 0:
- hashAlgorithm = AlgorithmIdentifier.getInstance(o, true);
- break;
- case 1:
- maskGenAlgorithm = AlgorithmIdentifier.getInstance(o, true);
- break;
- case 2:
- pSourceAlgorithm = AlgorithmIdentifier.getInstance(o, true);
- break;
- default:
- throw new IllegalArgumentException("unknown tag");
- }
- }
- }
-
- public AlgorithmIdentifier getHashAlgorithm()
- {
- return hashAlgorithm;
- }
-
- public AlgorithmIdentifier getMaskGenAlgorithm()
- {
- return maskGenAlgorithm;
- }
-
- public AlgorithmIdentifier getPSourceAlgorithm()
- {
- return pSourceAlgorithm;
- }
-
- /**
- * <pre>
- * RSAES-OAEP-params ::= SEQUENCE {
- * hashAlgorithm [0] OAEP-PSSDigestAlgorithms DEFAULT sha1,
- * maskGenAlgorithm [1] PKCS1MGFAlgorithms DEFAULT mgf1SHA1,
- * pSourceAlgorithm [2] PKCS1PSourceAlgorithms DEFAULT pSpecifiedEmpty
- * }
- *
- * OAEP-PSSDigestAlgorithms ALGORITHM-IDENTIFIER ::= {
- * { OID id-sha1 PARAMETERS NULL }|
- * { OID id-sha256 PARAMETERS NULL }|
- * { OID id-sha384 PARAMETERS NULL }|
- * { OID id-sha512 PARAMETERS NULL },
- * ... -- Allows for future expansion --
- * }
- * PKCS1MGFAlgorithms ALGORITHM-IDENTIFIER ::= {
- * { OID id-mgf1 PARAMETERS OAEP-PSSDigestAlgorithms },
- * ... -- Allows for future expansion --
- * }
- * PKCS1PSourceAlgorithms ALGORITHM-IDENTIFIER ::= {
- * { OID id-pSpecified PARAMETERS OCTET STRING },
- * ... -- Allows for future expansion --
- * }
- * </pre>
- * @return the asn1 primitive representing the parameters.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (!hashAlgorithm.equals(DEFAULT_HASH_ALGORITHM))
- {
- v.add(new DERTaggedObject(true, 0, hashAlgorithm));
- }
-
- if (!maskGenAlgorithm.equals(DEFAULT_MASK_GEN_FUNCTION))
- {
- v.add(new DERTaggedObject(true, 1, maskGenAlgorithm));
- }
-
- if (!pSourceAlgorithm.equals(DEFAULT_P_SOURCE_ALGORITHM))
- {
- v.add(new DERTaggedObject(true, 2, pSourceAlgorithm));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/RSAPrivateKey.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/RSAPrivateKey.java
deleted file mode 100644
index 36992cf5..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/RSAPrivateKey.java
+++ /dev/null
@@ -1,187 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-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;
-
-public class RSAPrivateKey
- extends ASN1Object
-{
- private BigInteger version;
- private BigInteger modulus;
- private BigInteger publicExponent;
- private BigInteger privateExponent;
- private BigInteger prime1;
- private BigInteger prime2;
- private BigInteger exponent1;
- private BigInteger exponent2;
- private BigInteger coefficient;
- private ASN1Sequence otherPrimeInfos = null;
-
- public static RSAPrivateKey getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static RSAPrivateKey getInstance(
- Object obj)
- {
- if (obj instanceof RSAPrivateKey)
- {
- return (RSAPrivateKey)obj;
- }
-
- if (obj != null)
- {
- return new RSAPrivateKey(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public RSAPrivateKey(
- BigInteger modulus,
- BigInteger publicExponent,
- BigInteger privateExponent,
- BigInteger prime1,
- BigInteger prime2,
- BigInteger exponent1,
- BigInteger exponent2,
- BigInteger coefficient)
- {
- this.version = BigInteger.valueOf(0);
- this.modulus = modulus;
- this.publicExponent = publicExponent;
- this.privateExponent = privateExponent;
- this.prime1 = prime1;
- this.prime2 = prime2;
- this.exponent1 = exponent1;
- this.exponent2 = exponent2;
- this.coefficient = coefficient;
- }
-
- private RSAPrivateKey(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- BigInteger v = ((ASN1Integer)e.nextElement()).getValue();
- if (v.intValue() != 0 && v.intValue() != 1)
- {
- throw new IllegalArgumentException("wrong version for RSA private key");
- }
-
- version = v;
- modulus = ((ASN1Integer)e.nextElement()).getValue();
- publicExponent = ((ASN1Integer)e.nextElement()).getValue();
- privateExponent = ((ASN1Integer)e.nextElement()).getValue();
- prime1 = ((ASN1Integer)e.nextElement()).getValue();
- prime2 = ((ASN1Integer)e.nextElement()).getValue();
- exponent1 = ((ASN1Integer)e.nextElement()).getValue();
- exponent2 = ((ASN1Integer)e.nextElement()).getValue();
- coefficient = ((ASN1Integer)e.nextElement()).getValue();
-
- if (e.hasMoreElements())
- {
- otherPrimeInfos = (ASN1Sequence)e.nextElement();
- }
- }
-
- public BigInteger getVersion()
- {
- return version;
- }
-
- public BigInteger getModulus()
- {
- return modulus;
- }
-
- public BigInteger getPublicExponent()
- {
- return publicExponent;
- }
-
- public BigInteger getPrivateExponent()
- {
- return privateExponent;
- }
-
- public BigInteger getPrime1()
- {
- return prime1;
- }
-
- public BigInteger getPrime2()
- {
- return prime2;
- }
-
- public BigInteger getExponent1()
- {
- return exponent1;
- }
-
- public BigInteger getExponent2()
- {
- return exponent2;
- }
-
- public BigInteger getCoefficient()
- {
- return coefficient;
- }
-
- /**
- * This outputs the key in PKCS1v2 format.
- * <pre>
- * RSAPrivateKey ::= SEQUENCE {
- * version Version,
- * modulus INTEGER, -- n
- * publicExponent INTEGER, -- e
- * privateExponent INTEGER, -- d
- * prime1 INTEGER, -- p
- * prime2 INTEGER, -- q
- * exponent1 INTEGER, -- d mod (p-1)
- * exponent2 INTEGER, -- d mod (q-1)
- * coefficient INTEGER, -- (inverse of q) mod p
- * otherPrimeInfos OtherPrimeInfos OPTIONAL
- * }
- *
- * Version ::= INTEGER { two-prime(0), multi(1) }
- * (CONSTRAINED BY {-- version must be multi if otherPrimeInfos present --})
- * </pre>
- * <p>
- * This routine is written to output PKCS1 version 2.1, private keys.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(new ASN1Integer(version)); // version
- v.add(new ASN1Integer(getModulus()));
- v.add(new ASN1Integer(getPublicExponent()));
- v.add(new ASN1Integer(getPrivateExponent()));
- v.add(new ASN1Integer(getPrime1()));
- v.add(new ASN1Integer(getPrime2()));
- v.add(new ASN1Integer(getExponent1()));
- v.add(new ASN1Integer(getExponent2()));
- v.add(new ASN1Integer(getCoefficient()));
-
- if (otherPrimeInfos != null)
- {
- v.add(otherPrimeInfos);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/RSAPrivateKeyStructure.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/RSAPrivateKeyStructure.java
deleted file mode 100644
index 5912d5ea..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/RSAPrivateKeyStructure.java
+++ /dev/null
@@ -1,189 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-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;
-
-/**
- * @deprecated use RSAPrivateKey
- */
-public class RSAPrivateKeyStructure
- extends ASN1Object
-{
- private int version;
- private BigInteger modulus;
- private BigInteger publicExponent;
- private BigInteger privateExponent;
- private BigInteger prime1;
- private BigInteger prime2;
- private BigInteger exponent1;
- private BigInteger exponent2;
- private BigInteger coefficient;
- private ASN1Sequence otherPrimeInfos = null;
-
- public static RSAPrivateKeyStructure getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static RSAPrivateKeyStructure getInstance(
- Object obj)
- {
- if (obj instanceof RSAPrivateKeyStructure)
- {
- return (RSAPrivateKeyStructure)obj;
- }
- else if (obj instanceof ASN1Sequence)
- {
- return new RSAPrivateKeyStructure((ASN1Sequence)obj);
- }
-
- throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
- }
-
- public RSAPrivateKeyStructure(
- BigInteger modulus,
- BigInteger publicExponent,
- BigInteger privateExponent,
- BigInteger prime1,
- BigInteger prime2,
- BigInteger exponent1,
- BigInteger exponent2,
- BigInteger coefficient)
- {
- this.version = 0;
- this.modulus = modulus;
- this.publicExponent = publicExponent;
- this.privateExponent = privateExponent;
- this.prime1 = prime1;
- this.prime2 = prime2;
- this.exponent1 = exponent1;
- this.exponent2 = exponent2;
- this.coefficient = coefficient;
- }
-
- public RSAPrivateKeyStructure(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- BigInteger v = ((ASN1Integer)e.nextElement()).getValue();
- if (v.intValue() != 0 && v.intValue() != 1)
- {
- throw new IllegalArgumentException("wrong version for RSA private key");
- }
-
- version = v.intValue();
- modulus = ((ASN1Integer)e.nextElement()).getValue();
- publicExponent = ((ASN1Integer)e.nextElement()).getValue();
- privateExponent = ((ASN1Integer)e.nextElement()).getValue();
- prime1 = ((ASN1Integer)e.nextElement()).getValue();
- prime2 = ((ASN1Integer)e.nextElement()).getValue();
- exponent1 = ((ASN1Integer)e.nextElement()).getValue();
- exponent2 = ((ASN1Integer)e.nextElement()).getValue();
- coefficient = ((ASN1Integer)e.nextElement()).getValue();
-
- if (e.hasMoreElements())
- {
- otherPrimeInfos = (ASN1Sequence)e.nextElement();
- }
- }
-
- public int getVersion()
- {
- return version;
- }
-
- public BigInteger getModulus()
- {
- return modulus;
- }
-
- public BigInteger getPublicExponent()
- {
- return publicExponent;
- }
-
- public BigInteger getPrivateExponent()
- {
- return privateExponent;
- }
-
- public BigInteger getPrime1()
- {
- return prime1;
- }
-
- public BigInteger getPrime2()
- {
- return prime2;
- }
-
- public BigInteger getExponent1()
- {
- return exponent1;
- }
-
- public BigInteger getExponent2()
- {
- return exponent2;
- }
-
- public BigInteger getCoefficient()
- {
- return coefficient;
- }
-
- /**
- * This outputs the key in PKCS1v2 format.
- * <pre>
- * RSAPrivateKey ::= SEQUENCE {
- * version Version,
- * modulus INTEGER, -- n
- * publicExponent INTEGER, -- e
- * privateExponent INTEGER, -- d
- * prime1 INTEGER, -- p
- * prime2 INTEGER, -- q
- * exponent1 INTEGER, -- d mod (p-1)
- * exponent2 INTEGER, -- d mod (q-1)
- * coefficient INTEGER, -- (inverse of q) mod p
- * otherPrimeInfos OtherPrimeInfos OPTIONAL
- * }
- *
- * Version ::= INTEGER { two-prime(0), multi(1) }
- * (CONSTRAINED BY {-- version must be multi if otherPrimeInfos present --})
- * </pre>
- * <p>
- * This routine is written to output PKCS1 version 2.1, private keys.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(new ASN1Integer(version)); // version
- v.add(new ASN1Integer(getModulus()));
- v.add(new ASN1Integer(getPublicExponent()));
- v.add(new ASN1Integer(getPrivateExponent()));
- v.add(new ASN1Integer(getPrime1()));
- v.add(new ASN1Integer(getPrime2()));
- v.add(new ASN1Integer(getExponent1()));
- v.add(new ASN1Integer(getExponent2()));
- v.add(new ASN1Integer(getCoefficient()));
-
- if (otherPrimeInfos != null)
- {
- v.add(otherPrimeInfos);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/RSAPublicKey.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/RSAPublicKey.java
deleted file mode 100644
index 6c432985..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/RSAPublicKey.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-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;
-
-public class RSAPublicKey
- extends ASN1Object
-{
- private BigInteger modulus;
- private BigInteger publicExponent;
-
- public static RSAPublicKey getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static RSAPublicKey getInstance(
- Object obj)
- {
- if (obj instanceof RSAPublicKey)
- {
- return (RSAPublicKey)obj;
- }
-
- if (obj != null)
- {
- return new RSAPublicKey(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public RSAPublicKey(
- BigInteger modulus,
- BigInteger publicExponent)
- {
- this.modulus = modulus;
- this.publicExponent = publicExponent;
- }
-
- private RSAPublicKey(
- ASN1Sequence seq)
- {
- if (seq.size() != 2)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
-
- Enumeration e = seq.getObjects();
-
- modulus = ASN1Integer.getInstance(e.nextElement()).getPositiveValue();
- publicExponent = ASN1Integer.getInstance(e.nextElement()).getPositiveValue();
- }
-
- public BigInteger getModulus()
- {
- return modulus;
- }
-
- public BigInteger getPublicExponent()
- {
- return publicExponent;
- }
-
- /**
- * This outputs the key in PKCS1v2 format.
- * <pre>
- * RSAPublicKey ::= SEQUENCE {
- * modulus INTEGER, -- n
- * publicExponent INTEGER, -- e
- * }
- * </pre>
- * <p>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(new ASN1Integer(getModulus()));
- v.add(new ASN1Integer(getPublicExponent()));
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/RSASSAPSSparams.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/RSASSAPSSparams.java
deleted file mode 100644
index dc91c9c1..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/RSASSAPSSparams.java
+++ /dev/null
@@ -1,172 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-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.DERNull;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-public class RSASSAPSSparams
- extends ASN1Object
-{
- private AlgorithmIdentifier hashAlgorithm;
- private AlgorithmIdentifier maskGenAlgorithm;
- private ASN1Integer saltLength;
- private ASN1Integer trailerField;
-
- public final static AlgorithmIdentifier DEFAULT_HASH_ALGORITHM = new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE);
- public final static AlgorithmIdentifier DEFAULT_MASK_GEN_FUNCTION = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_mgf1, DEFAULT_HASH_ALGORITHM);
- public final static ASN1Integer DEFAULT_SALT_LENGTH = new ASN1Integer(20);
- public final static ASN1Integer DEFAULT_TRAILER_FIELD = new ASN1Integer(1);
-
- public static RSASSAPSSparams getInstance(
- Object obj)
- {
- if (obj instanceof RSASSAPSSparams)
- {
- return (RSASSAPSSparams)obj;
- }
- else if (obj != null)
- {
- return new RSASSAPSSparams(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- /**
- * The default version
- */
- public RSASSAPSSparams()
- {
- hashAlgorithm = DEFAULT_HASH_ALGORITHM;
- maskGenAlgorithm = DEFAULT_MASK_GEN_FUNCTION;
- saltLength = DEFAULT_SALT_LENGTH;
- trailerField = DEFAULT_TRAILER_FIELD;
- }
-
- public RSASSAPSSparams(
- AlgorithmIdentifier hashAlgorithm,
- AlgorithmIdentifier maskGenAlgorithm,
- ASN1Integer saltLength,
- ASN1Integer trailerField)
- {
- this.hashAlgorithm = hashAlgorithm;
- this.maskGenAlgorithm = maskGenAlgorithm;
- this.saltLength = saltLength;
- this.trailerField = trailerField;
- }
-
- private RSASSAPSSparams(
- ASN1Sequence seq)
- {
- hashAlgorithm = DEFAULT_HASH_ALGORITHM;
- maskGenAlgorithm = DEFAULT_MASK_GEN_FUNCTION;
- saltLength = DEFAULT_SALT_LENGTH;
- trailerField = DEFAULT_TRAILER_FIELD;
-
- for (int i = 0; i != seq.size(); i++)
- {
- ASN1TaggedObject o = (ASN1TaggedObject)seq.getObjectAt(i);
-
- switch (o.getTagNo())
- {
- case 0:
- hashAlgorithm = AlgorithmIdentifier.getInstance(o, true);
- break;
- case 1:
- maskGenAlgorithm = AlgorithmIdentifier.getInstance(o, true);
- break;
- case 2:
- saltLength = ASN1Integer.getInstance(o, true);
- break;
- case 3:
- trailerField = ASN1Integer.getInstance(o, true);
- break;
- default:
- throw new IllegalArgumentException("unknown tag");
- }
- }
- }
-
- public AlgorithmIdentifier getHashAlgorithm()
- {
- return hashAlgorithm;
- }
-
- public AlgorithmIdentifier getMaskGenAlgorithm()
- {
- return maskGenAlgorithm;
- }
-
- public BigInteger getSaltLength()
- {
- return saltLength.getValue();
- }
-
- public BigInteger getTrailerField()
- {
- return trailerField.getValue();
- }
-
- /**
- * <pre>
- * RSASSA-PSS-params ::= SEQUENCE {
- * hashAlgorithm [0] OAEP-PSSDigestAlgorithms DEFAULT sha1,
- * maskGenAlgorithm [1] PKCS1MGFAlgorithms DEFAULT mgf1SHA1,
- * saltLength [2] INTEGER DEFAULT 20,
- * trailerField [3] TrailerField DEFAULT trailerFieldBC
- * }
- *
- * OAEP-PSSDigestAlgorithms ALGORITHM-IDENTIFIER ::= {
- * { OID id-sha1 PARAMETERS NULL }|
- * { OID id-sha256 PARAMETERS NULL }|
- * { OID id-sha384 PARAMETERS NULL }|
- * { OID id-sha512 PARAMETERS NULL },
- * ... -- Allows for future expansion --
- * }
- *
- * PKCS1MGFAlgorithms ALGORITHM-IDENTIFIER ::= {
- * { OID id-mgf1 PARAMETERS OAEP-PSSDigestAlgorithms },
- * ... -- Allows for future expansion --
- * }
- *
- * TrailerField ::= INTEGER { trailerFieldBC(1) }
- * </pre>
- * @return the asn1 primitive representing the parameters.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (!hashAlgorithm.equals(DEFAULT_HASH_ALGORITHM))
- {
- v.add(new DERTaggedObject(true, 0, hashAlgorithm));
- }
-
- if (!maskGenAlgorithm.equals(DEFAULT_MASK_GEN_FUNCTION))
- {
- v.add(new DERTaggedObject(true, 1, maskGenAlgorithm));
- }
-
- if (!saltLength.equals(DEFAULT_SALT_LENGTH))
- {
- v.add(new DERTaggedObject(true, 2, saltLength));
- }
-
- if (!trailerField.equals(DEFAULT_TRAILER_FIELD))
- {
- v.add(new DERTaggedObject(true, 3, trailerField));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/SafeBag.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/SafeBag.java
deleted file mode 100644
index 00ca0a20..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/SafeBag.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DLSequence;
-import org.bouncycastle.asn1.DLTaggedObject;
-
-public class SafeBag
- extends ASN1Object
-{
- private ASN1ObjectIdentifier bagId;
- private ASN1Encodable bagValue;
- private ASN1Set bagAttributes;
-
- public SafeBag(
- ASN1ObjectIdentifier oid,
- ASN1Encodable obj)
- {
- this.bagId = oid;
- this.bagValue = obj;
- this.bagAttributes = null;
- }
-
- public SafeBag(
- ASN1ObjectIdentifier oid,
- ASN1Encodable obj,
- ASN1Set bagAttributes)
- {
- this.bagId = oid;
- this.bagValue = obj;
- this.bagAttributes = bagAttributes;
- }
-
- public static SafeBag getInstance(
- Object obj)
- {
- if (obj instanceof SafeBag)
- {
- return (SafeBag)obj;
- }
-
- if (obj != null)
- {
- return new SafeBag(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private SafeBag(
- ASN1Sequence seq)
- {
- this.bagId = (ASN1ObjectIdentifier)seq.getObjectAt(0);
- this.bagValue = ((ASN1TaggedObject)seq.getObjectAt(1)).getObject();
- if (seq.size() == 3)
- {
- this.bagAttributes = (ASN1Set)seq.getObjectAt(2);
- }
- }
-
- public ASN1ObjectIdentifier getBagId()
- {
- return bagId;
- }
-
- public ASN1Encodable getBagValue()
- {
- return bagValue;
- }
-
- public ASN1Set getBagAttributes()
- {
- return bagAttributes;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(bagId);
- v.add(new DLTaggedObject(true, 0, bagValue));
-
- if (bagAttributes != null)
- {
- v.add(bagAttributes);
- }
-
- return new DLSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/SignedData.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/SignedData.java
deleted file mode 100644
index 3d3089bc..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/SignedData.java
+++ /dev/null
@@ -1,167 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.util.Enumeration;
-
-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.ASN1Set;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.BERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * a PKCS#7 signed data object.
- */
-public class SignedData
- extends ASN1Object
- implements PKCSObjectIdentifiers
-{
- private ASN1Integer version;
- private ASN1Set digestAlgorithms;
- private ContentInfo contentInfo;
- private ASN1Set certificates;
- private ASN1Set crls;
- private ASN1Set signerInfos;
-
- public static SignedData getInstance(
- Object o)
- {
- if (o instanceof SignedData)
- {
- return (SignedData)o;
- }
- else if (o != null)
- {
- return new SignedData(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public SignedData(
- ASN1Integer _version,
- ASN1Set _digestAlgorithms,
- ContentInfo _contentInfo,
- ASN1Set _certificates,
- ASN1Set _crls,
- ASN1Set _signerInfos)
- {
- version = _version;
- digestAlgorithms = _digestAlgorithms;
- contentInfo = _contentInfo;
- certificates = _certificates;
- crls = _crls;
- signerInfos = _signerInfos;
- }
-
- public SignedData(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- version = (ASN1Integer)e.nextElement();
- digestAlgorithms = ((ASN1Set)e.nextElement());
- contentInfo = ContentInfo.getInstance(e.nextElement());
-
- while (e.hasMoreElements())
- {
- ASN1Primitive o = (ASN1Primitive)e.nextElement();
-
- //
- // an interesting feature of SignedData is that there appear to be varying implementations...
- // for the moment we ignore anything which doesn't fit.
- //
- if (o instanceof ASN1TaggedObject)
- {
- ASN1TaggedObject tagged = (ASN1TaggedObject)o;
-
- switch (tagged.getTagNo())
- {
- case 0:
- certificates = ASN1Set.getInstance(tagged, false);
- break;
- case 1:
- crls = ASN1Set.getInstance(tagged, false);
- break;
- default:
- throw new IllegalArgumentException("unknown tag value " + tagged.getTagNo());
- }
- }
- else
- {
- signerInfos = (ASN1Set)o;
- }
- }
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public ASN1Set getDigestAlgorithms()
- {
- return digestAlgorithms;
- }
-
- public ContentInfo getContentInfo()
- {
- return contentInfo;
- }
-
- public ASN1Set getCertificates()
- {
- return certificates;
- }
-
- public ASN1Set getCRLs()
- {
- return crls;
- }
-
- public ASN1Set getSignerInfos()
- {
- return signerInfos;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * SignedData ::= SEQUENCE {
- * version Version,
- * digestAlgorithms DigestAlgorithmIdentifiers,
- * contentInfo ContentInfo,
- * certificates
- * [0] IMPLICIT ExtendedCertificatesAndCertificates
- * OPTIONAL,
- * crls
- * [1] IMPLICIT CertificateRevocationLists OPTIONAL,
- * signerInfos SignerInfos }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(version);
- v.add(digestAlgorithms);
- v.add(contentInfo);
-
- if (certificates != null)
- {
- v.add(new DERTaggedObject(false, 0, certificates));
- }
-
- if (crls != null)
- {
- v.add(new DERTaggedObject(false, 1, crls));
- }
-
- v.add(signerInfos);
-
- return new BERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/pkcs/SignerInfo.java b/core/src/main/java/org/bouncycastle/asn1/pkcs/SignerInfo.java
deleted file mode 100644
index ab5d78ab..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/pkcs/SignerInfo.java
+++ /dev/null
@@ -1,178 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.util.Enumeration;
-
-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.ASN1Set;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-/**
- * a PKCS#7 signer info object.
- */
-public class SignerInfo
- extends ASN1Object
-{
- private ASN1Integer version;
- private IssuerAndSerialNumber issuerAndSerialNumber;
- private AlgorithmIdentifier digAlgorithm;
- private ASN1Set authenticatedAttributes;
- private AlgorithmIdentifier digEncryptionAlgorithm;
- private ASN1OctetString encryptedDigest;
- private ASN1Set unauthenticatedAttributes;
-
- public static SignerInfo getInstance(
- Object o)
- {
- if (o instanceof SignerInfo)
- {
- return (SignerInfo)o;
- }
- else if (o instanceof ASN1Sequence)
- {
- return new SignerInfo((ASN1Sequence)o);
- }
-
- throw new IllegalArgumentException("unknown object in factory: " + o.getClass().getName());
- }
-
- public SignerInfo(
- ASN1Integer version,
- IssuerAndSerialNumber issuerAndSerialNumber,
- AlgorithmIdentifier digAlgorithm,
- ASN1Set authenticatedAttributes,
- AlgorithmIdentifier digEncryptionAlgorithm,
- ASN1OctetString encryptedDigest,
- ASN1Set unauthenticatedAttributes)
- {
- this.version = version;
- this.issuerAndSerialNumber = issuerAndSerialNumber;
- this.digAlgorithm = digAlgorithm;
- this.authenticatedAttributes = authenticatedAttributes;
- this.digEncryptionAlgorithm = digEncryptionAlgorithm;
- this.encryptedDigest = encryptedDigest;
- this.unauthenticatedAttributes = unauthenticatedAttributes;
- }
-
- public SignerInfo(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- version = (ASN1Integer)e.nextElement();
- issuerAndSerialNumber = IssuerAndSerialNumber.getInstance(e.nextElement());
- digAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement());
-
- Object obj = e.nextElement();
-
- if (obj instanceof ASN1TaggedObject)
- {
- authenticatedAttributes = ASN1Set.getInstance((ASN1TaggedObject)obj, false);
-
- digEncryptionAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement());
- }
- else
- {
- authenticatedAttributes = null;
- digEncryptionAlgorithm = AlgorithmIdentifier.getInstance(obj);
- }
-
- encryptedDigest = DEROctetString.getInstance(e.nextElement());
-
- if (e.hasMoreElements())
- {
- unauthenticatedAttributes = ASN1Set.getInstance((ASN1TaggedObject)e.nextElement(), false);
- }
- else
- {
- unauthenticatedAttributes = null;
- }
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public IssuerAndSerialNumber getIssuerAndSerialNumber()
- {
- return issuerAndSerialNumber;
- }
-
- public ASN1Set getAuthenticatedAttributes()
- {
- return authenticatedAttributes;
- }
-
- public AlgorithmIdentifier getDigestAlgorithm()
- {
- return digAlgorithm;
- }
-
- public ASN1OctetString getEncryptedDigest()
- {
- return encryptedDigest;
- }
-
- public AlgorithmIdentifier getDigestEncryptionAlgorithm()
- {
- return digEncryptionAlgorithm;
- }
-
- public ASN1Set getUnauthenticatedAttributes()
- {
- return unauthenticatedAttributes;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * SignerInfo ::= SEQUENCE {
- * version Version,
- * issuerAndSerialNumber IssuerAndSerialNumber,
- * 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()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(version);
- v.add(issuerAndSerialNumber);
- v.add(digAlgorithm);
-
- if (authenticatedAttributes != null)
- {
- v.add(new DERTaggedObject(false, 0, authenticatedAttributes));
- }
-
- v.add(digEncryptionAlgorithm);
- v.add(encryptedDigest);
-
- if (unauthenticatedAttributes != null)
- {
- v.add(new DERTaggedObject(false, 1, unauthenticatedAttributes));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKey.java b/core/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKey.java
deleted file mode 100644
index df2238a3..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKey.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package org.bouncycastle.asn1.sec;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.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.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.util.BigIntegers;
-
-/**
- * the elliptic curve private key object from SEC 1
- */
-public class ECPrivateKey
- extends ASN1Object
-{
- private ASN1Sequence seq;
-
- private ECPrivateKey(
- ASN1Sequence seq)
- {
- this.seq = seq;
- }
-
- public static ECPrivateKey getInstance(
- Object obj)
- {
- if (obj instanceof ECPrivateKey)
- {
- return (ECPrivateKey)obj;
- }
-
- if (obj != null)
- {
- return new ECPrivateKey(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public ECPrivateKey(
- BigInteger key)
- {
- byte[] bytes = BigIntegers.asUnsignedByteArray(key);
-
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(new ASN1Integer(1));
- v.add(new DEROctetString(bytes));
-
- seq = new DERSequence(v);
- }
-
- public ECPrivateKey(
- BigInteger key,
- ASN1Encodable parameters)
- {
- this(key, null, parameters);
- }
-
- public ECPrivateKey(
- BigInteger key,
- DERBitString publicKey,
- ASN1Encodable parameters)
- {
- byte[] bytes = BigIntegers.asUnsignedByteArray(key);
-
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(new ASN1Integer(1));
- v.add(new DEROctetString(bytes));
-
- if (parameters != null)
- {
- v.add(new DERTaggedObject(true, 0, parameters));
- }
-
- if (publicKey != null)
- {
- v.add(new DERTaggedObject(true, 1, publicKey));
- }
-
- seq = new DERSequence(v);
- }
-
- public BigInteger getKey()
- {
- ASN1OctetString octs = (ASN1OctetString)seq.getObjectAt(1);
-
- return new BigInteger(1, octs.getOctets());
- }
-
- public DERBitString getPublicKey()
- {
- return (DERBitString)getObjectInTag(1);
- }
-
- public ASN1Primitive getParameters()
- {
- return getObjectInTag(0);
- }
-
- private ASN1Primitive getObjectInTag(int tagNo)
- {
- Enumeration e = seq.getObjects();
-
- while (e.hasMoreElements())
- {
- ASN1Encodable obj = (ASN1Encodable)e.nextElement();
-
- if (obj instanceof ASN1TaggedObject)
- {
- ASN1TaggedObject tag = (ASN1TaggedObject)obj;
- if (tag.getTagNo() == tagNo)
- {
- return tag.getObject().toASN1Primitive();
- }
- }
- }
- return null;
- }
-
- /**
- * ECPrivateKey ::= SEQUENCE {
- * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
- * privateKey OCTET STRING,
- * parameters [0] Parameters OPTIONAL,
- * publicKey [1] BIT STRING OPTIONAL }
- */
- public ASN1Primitive toASN1Primitive()
- {
- return seq;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKeyStructure.java b/core/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKeyStructure.java
deleted file mode 100644
index 3b1bcc38..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKeyStructure.java
+++ /dev/null
@@ -1,128 +0,0 @@
-package org.bouncycastle.asn1.sec;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.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.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.util.BigIntegers;
-
-/**
- * the elliptic curve private key object from SEC 1
- * @deprecated use ECPrivateKey
- */
-public class ECPrivateKeyStructure
- extends ASN1Object
-{
- private ASN1Sequence seq;
-
- public ECPrivateKeyStructure(
- ASN1Sequence seq)
- {
- this.seq = seq;
- }
-
- public ECPrivateKeyStructure(
- BigInteger key)
- {
- byte[] bytes = BigIntegers.asUnsignedByteArray(key);
-
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(new ASN1Integer(1));
- v.add(new DEROctetString(bytes));
-
- seq = new DERSequence(v);
- }
-
- public ECPrivateKeyStructure(
- BigInteger key,
- ASN1Encodable parameters)
- {
- this(key, null, parameters);
- }
-
- public ECPrivateKeyStructure(
- BigInteger key,
- DERBitString publicKey,
- ASN1Encodable parameters)
- {
- byte[] bytes = BigIntegers.asUnsignedByteArray(key);
-
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(new ASN1Integer(1));
- v.add(new DEROctetString(bytes));
-
- if (parameters != null)
- {
- v.add(new DERTaggedObject(true, 0, parameters));
- }
-
- if (publicKey != null)
- {
- v.add(new DERTaggedObject(true, 1, publicKey));
- }
-
- seq = new DERSequence(v);
- }
-
- public BigInteger getKey()
- {
- ASN1OctetString octs = (ASN1OctetString)seq.getObjectAt(1);
-
- return new BigInteger(1, octs.getOctets());
- }
-
- public DERBitString getPublicKey()
- {
- return (DERBitString)getObjectInTag(1);
- }
-
- public ASN1Primitive getParameters()
- {
- return getObjectInTag(0);
- }
-
- private ASN1Primitive getObjectInTag(int tagNo)
- {
- Enumeration e = seq.getObjects();
-
- while (e.hasMoreElements())
- {
- ASN1Encodable obj = (ASN1Encodable)e.nextElement();
-
- if (obj instanceof ASN1TaggedObject)
- {
- ASN1TaggedObject tag = (ASN1TaggedObject)obj;
- if (tag.getTagNo() == tagNo)
- {
- return (ASN1Primitive)((ASN1Encodable)tag.getObject()).toASN1Primitive();
- }
- }
- }
- return null;
- }
-
- /**
- * ECPrivateKey ::= SEQUENCE {
- * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
- * privateKey OCTET STRING,
- * parameters [0] Parameters OPTIONAL,
- * publicKey [1] BIT STRING OPTIONAL }
- */
- public ASN1Primitive toASN1Primitive()
- {
- return seq;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java b/core/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java
deleted file mode 100644
index ed7a8d82..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java
+++ /dev/null
@@ -1,1094 +0,0 @@
-package org.bouncycastle.asn1.sec;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-import java.util.Hashtable;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.asn1.x9.X9ECParametersHolder;
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.ec.endo.GLVTypeBEndomorphism;
-import org.bouncycastle.math.ec.endo.GLVTypeBParameters;
-import org.bouncycastle.util.Strings;
-import org.bouncycastle.util.encoders.Hex;
-
-public class SECNamedCurves
-{
- private static ECCurve configureCurve(ECCurve curve)
- {
- return curve;
- }
-
- private static ECCurve configureCurveGLV(ECCurve c, GLVTypeBParameters p)
- {
- return c.configure().setEndomorphism(new GLVTypeBEndomorphism(c, p)).create();
- }
-
- private static BigInteger fromHex(
- String hex)
- {
- return new BigInteger(1, Hex.decode(hex));
- }
-
- /*
- * secp112r1
- */
- static X9ECParametersHolder secp112r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- // p = (2^128 - 3) / 76439
- BigInteger p = fromHex("DB7C2ABF62E35E668076BEAD208B");
- BigInteger a = fromHex("DB7C2ABF62E35E668076BEAD2088");
- BigInteger b = fromHex("659EF8BA043916EEDE8911702B22");
- byte[] S = Hex.decode("00F50B028E4D696E676875615175290472783FB1");
- BigInteger n = fromHex("DB7C2ABF62E35E7628DFAC6561C5");
- BigInteger h = BigInteger.valueOf(1);
-
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
- //ECPoint G = curve.decodePoint(Hex.decode("02"
- //+ "09487239995A5EE76B55F9C2F098"));
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "09487239995A5EE76B55F9C2F098"
- + "A89CE5AF8724C0A23E0E0FF77500"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * secp112r2
- */
- static X9ECParametersHolder secp112r2 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- // p = (2^128 - 3) / 76439
- BigInteger p = fromHex("DB7C2ABF62E35E668076BEAD208B");
- BigInteger a = fromHex("6127C24C05F38A0AAAF65C0EF02C");
- BigInteger b = fromHex("51DEF1815DB5ED74FCC34C85D709");
- byte[] S = Hex.decode("002757A1114D696E6768756151755316C05E0BD4");
- BigInteger n = fromHex("36DF0AAFD8B8D7597CA10520D04B");
- BigInteger h = BigInteger.valueOf(4);
-
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
- //ECPoint G = curve.decodePoint(Hex.decode("03"
- //+ "4BA30AB5E892B4E1649DD0928643"));
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "4BA30AB5E892B4E1649DD0928643"
- + "ADCD46F5882E3747DEF36E956E97"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * secp128r1
- */
- static X9ECParametersHolder secp128r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- // p = 2^128 - 2^97 - 1
- BigInteger p = fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF");
- BigInteger a = fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC");
- BigInteger b = fromHex("E87579C11079F43DD824993C2CEE5ED3");
- byte[] S = Hex.decode("000E0D4D696E6768756151750CC03A4473D03679");
- BigInteger n = fromHex("FFFFFFFE0000000075A30D1B9038A115");
- BigInteger h = BigInteger.valueOf(1);
-
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
- //ECPoint G = curve.decodePoint(Hex.decode("03"
- //+ "161FF7528B899B2D0C28607CA52C5B86"));
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "161FF7528B899B2D0C28607CA52C5B86"
- + "CF5AC8395BAFEB13C02DA292DDED7A83"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * secp128r2
- */
- static X9ECParametersHolder secp128r2 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- // p = 2^128 - 2^97 - 1
- BigInteger p = fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF");
- BigInteger a = fromHex("D6031998D1B3BBFEBF59CC9BBFF9AEE1");
- BigInteger b = fromHex("5EEEFCA380D02919DC2C6558BB6D8A5D");
- byte[] S = Hex.decode("004D696E67687561517512D8F03431FCE63B88F4");
- BigInteger n = fromHex("3FFFFFFF7FFFFFFFBE0024720613B5A3");
- BigInteger h = BigInteger.valueOf(4);
-
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
- //ECPoint G = curve.decodePoint(Hex.decode("02"
- //+ "7B6AA5D85E572983E6FB32A7CDEBC140"));
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "7B6AA5D85E572983E6FB32A7CDEBC140"
- + "27B6916A894D3AEE7106FE805FC34B44"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * secp160k1
- */
- static X9ECParametersHolder secp160k1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- // p = 2^160 - 2^32 - 2^14 - 2^12 - 2^9 - 2^8 - 2^7 - 2^3 - 2^2 - 1
- BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73");
- BigInteger a = ECConstants.ZERO;
- BigInteger b = BigInteger.valueOf(7);
- byte[] S = null;
- BigInteger n = fromHex("0100000000000000000001B8FA16DFAB9ACA16B6B3");
- BigInteger h = BigInteger.valueOf(1);
-
- GLVTypeBParameters glv = new GLVTypeBParameters(
- new BigInteger("9ba48cba5ebcb9b6bd33b92830b2a2e0e192f10a", 16),
- new BigInteger("c39c6c3b3a36d7701b9c71a1f5804ae5d0003f4", 16),
- new BigInteger[]{
- new BigInteger("9162fbe73984472a0a9e", 16),
- new BigInteger("-96341f1138933bc2f505", 16) },
- new BigInteger[]{
- new BigInteger("127971af8721782ecffa3", 16),
- new BigInteger("9162fbe73984472a0a9e", 16) },
- new BigInteger("9162fbe73984472a0a9d0590", 16),
- new BigInteger("96341f1138933bc2f503fd44", 16),
- 176);
-
- ECCurve curve = configureCurveGLV(new ECCurve.Fp(p, a, b, n, h), glv);
-// ECPoint G = curve.decodePoint(Hex.decode("02"
-// + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB"));
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB"
- + "938CF935318FDCED6BC28286531733C3F03C4FEE"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * secp160r1
- */
- static X9ECParametersHolder secp160r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- // p = 2^160 - 2^31 - 1
- BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF");
- BigInteger a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC");
- BigInteger b = fromHex("1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45");
- byte[] S = Hex.decode("1053CDE42C14D696E67687561517533BF3F83345");
- BigInteger n = fromHex("0100000000000000000001F4C8F927AED3CA752257");
- BigInteger h = BigInteger.valueOf(1);
-
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
- //ECPoint G = curve.decodePoint(Hex.decode("02"
- //+ "4A96B5688EF573284664698968C38BB913CBFC82"));
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "4A96B5688EF573284664698968C38BB913CBFC82"
- + "23A628553168947D59DCC912042351377AC5FB32"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * secp160r2
- */
- static X9ECParametersHolder secp160r2 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- // p = 2^160 - 2^32 - 2^14 - 2^12 - 2^9 - 2^8 - 2^7 - 2^3 - 2^2 - 1
- BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73");
- BigInteger a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70");
- BigInteger b = fromHex("B4E134D3FB59EB8BAB57274904664D5AF50388BA");
- byte[] S = Hex.decode("B99B99B099B323E02709A4D696E6768756151751");
- BigInteger n = fromHex("0100000000000000000000351EE786A818F3A1A16B");
- BigInteger h = BigInteger.valueOf(1);
-
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
- //ECPoint G = curve.decodePoint(Hex.decode("02"
- //+ "52DCB034293A117E1F4FF11B30F7199D3144CE6D"));
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "52DCB034293A117E1F4FF11B30F7199D3144CE6D"
- + "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * secp192k1
- */
- static X9ECParametersHolder secp192k1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- // p = 2^192 - 2^32 - 2^12 - 2^8 - 2^7 - 2^6 - 2^3 - 1
- BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37");
- BigInteger a = ECConstants.ZERO;
- BigInteger b = BigInteger.valueOf(3);
- byte[] S = null;
- BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D");
- BigInteger h = BigInteger.valueOf(1);
-
- GLVTypeBParameters glv = new GLVTypeBParameters(
- new BigInteger("bb85691939b869c1d087f601554b96b80cb4f55b35f433c2", 16),
- new BigInteger("3d84f26c12238d7b4f3d516613c1759033b1a5800175d0b1", 16),
- new BigInteger[]{
- new BigInteger("71169be7330b3038edb025f1", 16),
- new BigInteger("-b3fb3400dec5c4adceb8655c", 16) },
- new BigInteger[]{
- new BigInteger("12511cfe811d0f4e6bc688b4d", 16),
- new BigInteger("71169be7330b3038edb025f1", 16) },
- new BigInteger("71169be7330b3038edb025f1d0f9", 16),
- new BigInteger("b3fb3400dec5c4adceb8655d4c94", 16),
- 208);
-
- ECCurve curve = configureCurveGLV(new ECCurve.Fp(p, a, b, n, h), glv);
- //ECPoint G = curve.decodePoint(Hex.decode("03"
- //+ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"));
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"
- + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * secp192r1
- */
- static X9ECParametersHolder secp192r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- // p = 2^192 - 2^64 - 1
- BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF");
- BigInteger a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC");
- BigInteger b = fromHex("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1");
- byte[] S = Hex.decode("3045AE6FC8422F64ED579528D38120EAE12196D5");
- BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831");
- BigInteger h = BigInteger.valueOf(1);
-
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
- //ECPoint G = curve.decodePoint(Hex.decode("03"
- //+ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"));
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"
- + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * secp224k1
- */
- static X9ECParametersHolder secp224k1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- // p = 2^224 - 2^32 - 2^12 - 2^11 - 2^9 - 2^7 - 2^4 - 2 - 1
- BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D");
- BigInteger a = ECConstants.ZERO;
- BigInteger b = BigInteger.valueOf(5);
- byte[] S = null;
- BigInteger n = fromHex("010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7");
- BigInteger h = BigInteger.valueOf(1);
-
- GLVTypeBParameters glv = new GLVTypeBParameters(
- new BigInteger("fe0e87005b4e83761908c5131d552a850b3f58b749c37cf5b84d6768", 16),
- new BigInteger("60dcd2104c4cbc0be6eeefc2bdd610739ec34e317f9b33046c9e4788", 16),
- new BigInteger[]{
- new BigInteger("6b8cf07d4ca75c88957d9d670591", 16),
- new BigInteger("-b8adf1378a6eb73409fa6c9c637d", 16) },
- new BigInteger[]{
- new BigInteger("1243ae1b4d71613bc9f780a03690e", 16),
- new BigInteger("6b8cf07d4ca75c88957d9d670591", 16) },
- new BigInteger("6b8cf07d4ca75c88957d9d67059037a4", 16),
- new BigInteger("b8adf1378a6eb73409fa6c9c637ba7f5", 16),
- 240);
-
- ECCurve curve = configureCurveGLV(new ECCurve.Fp(p, a, b, n, h), glv);
- //ECPoint G = curve.decodePoint(Hex.decode("03"
- //+ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"));
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"
- + "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * secp224r1
- */
- static X9ECParametersHolder secp224r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- // p = 2^224 - 2^96 + 1
- BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001");
- BigInteger a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE");
- BigInteger b = fromHex("B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4");
- byte[] S = Hex.decode("BD71344799D5C7FCDC45B59FA3B9AB8F6A948BC5");
- BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D");
- BigInteger h = BigInteger.valueOf(1);
-
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
- //ECPoint G = curve.decodePoint(Hex.decode("02"
- //+ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"));
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"
- + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * secp256k1
- */
- static X9ECParametersHolder secp256k1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- // p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
- BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F");
- BigInteger a = ECConstants.ZERO;
- BigInteger b = BigInteger.valueOf(7);
- byte[] S = null;
- BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
- BigInteger h = BigInteger.valueOf(1);
-
- GLVTypeBParameters glv = new GLVTypeBParameters(
- new BigInteger("7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee", 16),
- new BigInteger("5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72", 16),
- new BigInteger[]{
- new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16),
- new BigInteger("-e4437ed6010e88286f547fa90abfe4c3", 16) },
- new BigInteger[]{
- new BigInteger("114ca50f7a8e2f3f657c1108d9d44cfd8", 16),
- new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16) },
- new BigInteger("3086d221a7d46bcde86c90e49284eb153dab", 16),
- new BigInteger("e4437ed6010e88286f547fa90abfe4c42212", 16),
- 272);
-
- ECCurve curve = configureCurveGLV(new ECCurve.Fp(p, a, b, n, h), glv);
- //ECPoint G = curve.decodePoint(Hex.decode("02"
- //+ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"));
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
- + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * secp256r1
- */
- static X9ECParametersHolder secp256r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- // p = 2^224 (2^32 - 1) + 2^192 + 2^96 - 1
- BigInteger p = fromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF");
- BigInteger a = fromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC");
- BigInteger b = fromHex("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B");
- byte[] S = Hex.decode("C49D360886E704936A6678E1139D26B7819F7E90");
- BigInteger n = fromHex("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551");
- BigInteger h = BigInteger.valueOf(1);
-
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
- //ECPoint G = curve.decodePoint(Hex.decode("03"
- //+ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"));
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"
- + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * secp384r1
- */
- static X9ECParametersHolder secp384r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- // p = 2^384 - 2^128 - 2^96 + 2^32 - 1
- BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF");
- BigInteger a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC");
- BigInteger b = fromHex("B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF");
- byte[] S = Hex.decode("A335926AA319A27A1D00896A6773A4827ACDAC73");
- BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973");
- BigInteger h = BigInteger.valueOf(1);
-
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
- //ECPoint G = curve.decodePoint(Hex.decode("03"
- //+ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"));
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"
- + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * secp521r1
- */
- static X9ECParametersHolder secp521r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- // p = 2^521 - 1
- BigInteger p = fromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
- BigInteger a = fromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC");
- BigInteger b = fromHex("0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00");
- byte[] S = Hex.decode("D09E8800291CB85396CC6717393284AAA0DA64BA");
- BigInteger n = fromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409");
- BigInteger h = BigInteger.valueOf(1);
-
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
-
- //ECPoint G = curve.decodePoint(Hex.decode("02"
- //+ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"));
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"
- + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * sect113r1
- */
- static X9ECParametersHolder sect113r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- int m = 113;
- int k = 9;
-
- BigInteger a = fromHex("003088250CA6E7C7FE649CE85820F7");
- BigInteger b = fromHex("00E8BEE4D3E2260744188BE0E9C723");
- byte[] S = Hex.decode("10E723AB14D696E6768756151756FEBF8FCB49A9");
- BigInteger n = fromHex("0100000000000000D9CCEC8A39E56F");
- BigInteger h = BigInteger.valueOf(2);
-
- ECCurve curve = 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"
- + "009D73616F35F4AB1407D73562C10F"
- + "00A52830277958EE84D1315ED31886"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * sect113r2
- */
- static X9ECParametersHolder sect113r2 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- int m = 113;
- int k = 9;
-
- BigInteger a = fromHex("00689918DBEC7E5A0DD6DFC0AA55C7");
- BigInteger b = fromHex("0095E9A9EC9B297BD4BF36E059184F");
- byte[] S = Hex.decode("10C0FB15760860DEF1EEF4D696E676875615175D");
- BigInteger n = fromHex("010000000000000108789B2496AF93");
- BigInteger h = BigInteger.valueOf(2);
-
- ECCurve curve = 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"
- + "01A57A6A7B26CA5EF52FCDB8164797"
- + "00B3ADC94ED1FE674C06E695BABA1D"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * sect131r1
- */
- static X9ECParametersHolder sect131r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- int m = 131;
- int k1 = 2;
- int k2 = 3;
- int k3 = 8;
-
- BigInteger a = fromHex("07A11B09A76B562144418FF3FF8C2570B8");
- BigInteger b = fromHex("0217C05610884B63B9C6C7291678F9D341");
- byte[] S = Hex.decode("4D696E676875615175985BD3ADBADA21B43A97E2");
- BigInteger n = fromHex("0400000000000000023123953A9464B54D");
- BigInteger h = BigInteger.valueOf(2);
-
- ECCurve curve = 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"
- + "0081BAF91FDF9833C40F9C181343638399"
- + "078C6E7EA38C001F73C8134B1B4EF9E150"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * sect131r2
- */
- static X9ECParametersHolder sect131r2 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- int m = 131;
- int k1 = 2;
- int k2 = 3;
- int k3 = 8;
-
- BigInteger a = fromHex("03E5A88919D7CAFCBF415F07C2176573B2");
- BigInteger b = fromHex("04B8266A46C55657AC734CE38F018F2192");
- byte[] S = Hex.decode("985BD3ADBAD4D696E676875615175A21B43A97E3");
- BigInteger n = fromHex("0400000000000000016954A233049BA98F");
- BigInteger h = BigInteger.valueOf(2);
-
- ECCurve curve = 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"
- + "0356DCD8F2F95031AD652D23951BB366A8"
- + "0648F06D867940A5366D9E265DE9EB240F"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * sect163k1
- */
- static X9ECParametersHolder sect163k1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- int m = 163;
- int k1 = 3;
- int k2 = 6;
- int k3 = 7;
-
- BigInteger a = BigInteger.valueOf(1);
- BigInteger b = BigInteger.valueOf(1);
- byte[] S = null;
- BigInteger n = fromHex("04000000000000000000020108A2E0CC0D99F8A5EF");
- BigInteger h = BigInteger.valueOf(2);
-
- ECCurve curve = 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"
- + "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8"
- + "0289070FB05D38FF58321F2E800536D538CCDAA3D9"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * sect163r1
- */
- static X9ECParametersHolder sect163r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- int m = 163;
- int k1 = 3;
- int k2 = 6;
- int k3 = 7;
-
- BigInteger a = fromHex("07B6882CAAEFA84F9554FF8428BD88E246D2782AE2");
- BigInteger b = fromHex("0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9");
- byte[] S = Hex.decode("24B7B137C8A14D696E6768756151756FD0DA2E5C");
- BigInteger n = fromHex("03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B");
- BigInteger h = BigInteger.valueOf(2);
-
- ECCurve curve = 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"
- + "0369979697AB43897789566789567F787A7876A654"
- + "00435EDB42EFAFB2989D51FEFCE3C80988F41FF883"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * sect163r2
- */
- static X9ECParametersHolder sect163r2 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- int m = 163;
- int k1 = 3;
- int k2 = 6;
- int k3 = 7;
-
- BigInteger a = BigInteger.valueOf(1);
- BigInteger b = fromHex("020A601907B8C953CA1481EB10512F78744A3205FD");
- byte[] S = Hex.decode("85E25BFE5C86226CDB12016F7553F9D0E693A268");
- BigInteger n = fromHex("040000000000000000000292FE77E70C12A4234C33");
- BigInteger h = BigInteger.valueOf(2);
-
- ECCurve curve = 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"
- + "03F0EBA16286A2D57EA0991168D4994637E8343E36"
- + "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * sect193r1
- */
- static X9ECParametersHolder sect193r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- int m = 193;
- int k = 15;
-
- BigInteger a = fromHex("0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01");
- BigInteger b = fromHex("00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814");
- byte[] S = Hex.decode("103FAEC74D696E676875615175777FC5B191EF30");
- BigInteger n = fromHex("01000000000000000000000000C7F34A778F443ACC920EBA49");
- BigInteger h = BigInteger.valueOf(2);
-
- ECCurve curve = 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"
- + "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1"
- + "0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * sect193r2
- */
- static X9ECParametersHolder sect193r2 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- int m = 193;
- int k = 15;
-
- BigInteger a = fromHex("0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B");
- BigInteger b = fromHex("00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE");
- byte[] S = Hex.decode("10B7B4D696E676875615175137C8A16FD0DA2211");
- BigInteger n = fromHex("010000000000000000000000015AAB561B005413CCD4EE99D5");
- BigInteger h = BigInteger.valueOf(2);
-
- ECCurve curve = 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"
- + "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F"
- + "01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * sect233k1
- */
- static X9ECParametersHolder sect233k1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- int m = 233;
- int k = 74;
-
- BigInteger a = ECConstants.ZERO;
- BigInteger b = BigInteger.valueOf(1);
- byte[] S = null;
- BigInteger n = fromHex("8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF");
- BigInteger h = BigInteger.valueOf(4);
-
- ECCurve curve = 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"
- + "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126"
- + "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * sect233r1
- */
- static X9ECParametersHolder sect233r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- int m = 233;
- int k = 74;
-
- BigInteger a = BigInteger.valueOf(1);
- BigInteger b = fromHex("0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD");
- byte[] S = Hex.decode("74D59FF07F6B413D0EA14B344B20A2DB049B50C3");
- BigInteger n = fromHex("01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7");
- BigInteger h = BigInteger.valueOf(2);
-
- ECCurve curve = 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"
- + "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B"
- + "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * sect239k1
- */
- static X9ECParametersHolder sect239k1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- int m = 239;
- int k = 158;
-
- BigInteger a = ECConstants.ZERO;
- BigInteger b = BigInteger.valueOf(1);
- byte[] S = null;
- BigInteger n = fromHex("2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5");
- BigInteger h = BigInteger.valueOf(4);
-
- ECCurve curve = 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"
- + "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC"
- + "76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * sect283k1
- */
- static X9ECParametersHolder sect283k1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- int m = 283;
- int k1 = 5;
- int k2 = 7;
- int k3 = 12;
-
- BigInteger a = ECConstants.ZERO;
- BigInteger b = BigInteger.valueOf(1);
- byte[] S = null;
- BigInteger n = fromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61");
- BigInteger h = BigInteger.valueOf(4);
-
- ECCurve curve = 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"
- + "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836"
- + "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * sect283r1
- */
- static X9ECParametersHolder sect283r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- int m = 283;
- int k1 = 5;
- int k2 = 7;
- int k3 = 12;
-
- BigInteger a = BigInteger.valueOf(1);
- BigInteger b = fromHex("027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5");
- byte[] S = Hex.decode("77E2B07370EB0F832A6DD5B62DFC88CD06BB84BE");
- BigInteger n = fromHex("03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307");
- BigInteger h = BigInteger.valueOf(2);
-
- ECCurve curve = 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"
- + "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053"
- + "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * sect409k1
- */
- static X9ECParametersHolder sect409k1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- int m = 409;
- int k = 87;
-
- BigInteger a = ECConstants.ZERO;
- BigInteger b = BigInteger.valueOf(1);
- byte[] S = null;
- BigInteger n = fromHex("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF");
- BigInteger h = BigInteger.valueOf(4);
-
- ECCurve curve = 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"
- + "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746"
- + "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * sect409r1
- */
- static X9ECParametersHolder sect409r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- int m = 409;
- int k = 87;
-
- BigInteger a = BigInteger.valueOf(1);
- BigInteger b = fromHex("0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F");
- byte[] S = Hex.decode("4099B5A457F9D69F79213D094C4BCD4D4262210B");
- BigInteger n = fromHex("010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173");
- BigInteger h = BigInteger.valueOf(2);
-
- ECCurve curve = 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"
- + "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7"
- + "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * sect571k1
- */
- static X9ECParametersHolder sect571k1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- int m = 571;
- int k1 = 2;
- int k2 = 5;
- int k3 = 10;
-
- BigInteger a = ECConstants.ZERO;
- BigInteger b = BigInteger.valueOf(1);
- byte[] S = null;
- BigInteger n = fromHex("020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001");
- BigInteger h = BigInteger.valueOf(4);
-
- ECCurve curve = 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"
- + "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972"
- + "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
- /*
- * sect571r1
- */
- static X9ECParametersHolder sect571r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- int m = 571;
- int k1 = 2;
- int k2 = 5;
- int k3 = 10;
-
- BigInteger a = BigInteger.valueOf(1);
- BigInteger b = fromHex("02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A");
- byte[] S = Hex.decode("2AA058F73A0E33AB486B0F610410C53A7F132310");
- BigInteger n = fromHex("03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47");
- BigInteger h = BigInteger.valueOf(2);
-
- ECCurve curve = 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"
- + "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19"
- + "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B"));
-
- return new X9ECParameters(curve, G, n, h, S);
- }
- };
-
-
- static final Hashtable objIds = new Hashtable();
- static final Hashtable curves = new Hashtable();
- static final Hashtable names = new Hashtable();
-
- static void defineCurve(String name, ASN1ObjectIdentifier oid, X9ECParametersHolder holder)
- {
- objIds.put(name, oid);
- names.put(oid, name);
- curves.put(oid, holder);
- }
-
- static
- {
- defineCurve("secp112r1", SECObjectIdentifiers.secp112r1, secp112r1);
- defineCurve("secp112r2", SECObjectIdentifiers.secp112r2, secp112r2);
- defineCurve("secp128r1", SECObjectIdentifiers.secp128r1, secp128r1);
- defineCurve("secp128r2", SECObjectIdentifiers.secp128r2, secp128r2);
- defineCurve("secp160k1", SECObjectIdentifiers.secp160k1, secp160k1);
- defineCurve("secp160r1", SECObjectIdentifiers.secp160r1, secp160r1);
- defineCurve("secp160r2", SECObjectIdentifiers.secp160r2, secp160r2);
- defineCurve("secp192k1", SECObjectIdentifiers.secp192k1, secp192k1);
- defineCurve("secp192r1", SECObjectIdentifiers.secp192r1, secp192r1);
- defineCurve("secp224k1", SECObjectIdentifiers.secp224k1, secp224k1);
- defineCurve("secp224r1", SECObjectIdentifiers.secp224r1, secp224r1);
- defineCurve("secp256k1", SECObjectIdentifiers.secp256k1, secp256k1);
- defineCurve("secp256r1", SECObjectIdentifiers.secp256r1, secp256r1);
- defineCurve("secp384r1", SECObjectIdentifiers.secp384r1, secp384r1);
- defineCurve("secp521r1", SECObjectIdentifiers.secp521r1, secp521r1);
-
- defineCurve("sect113r1", SECObjectIdentifiers.sect113r1, sect113r1);
- defineCurve("sect113r2", SECObjectIdentifiers.sect113r2, sect113r2);
- defineCurve("sect131r1", SECObjectIdentifiers.sect131r1, sect131r1);
- defineCurve("sect131r2", SECObjectIdentifiers.sect131r2, sect131r2);
- defineCurve("sect163k1", SECObjectIdentifiers.sect163k1, sect163k1);
- defineCurve("sect163r1", SECObjectIdentifiers.sect163r1, sect163r1);
- defineCurve("sect163r2", SECObjectIdentifiers.sect163r2, sect163r2);
- defineCurve("sect193r1", SECObjectIdentifiers.sect193r1, sect193r1);
- defineCurve("sect193r2", SECObjectIdentifiers.sect193r2, sect193r2);
- defineCurve("sect233k1", SECObjectIdentifiers.sect233k1, sect233k1);
- defineCurve("sect233r1", SECObjectIdentifiers.sect233r1, sect233r1);
- defineCurve("sect239k1", SECObjectIdentifiers.sect239k1, sect239k1);
- defineCurve("sect283k1", SECObjectIdentifiers.sect283k1, sect283k1);
- defineCurve("sect283r1", SECObjectIdentifiers.sect283r1, sect283r1);
- defineCurve("sect409k1", SECObjectIdentifiers.sect409k1, sect409k1);
- defineCurve("sect409r1", SECObjectIdentifiers.sect409r1, sect409r1);
- defineCurve("sect571k1", SECObjectIdentifiers.sect571k1, sect571k1);
- defineCurve("sect571r1", SECObjectIdentifiers.sect571r1, sect571r1);
- }
-
- public static X9ECParameters getByName(
- String name)
- {
- ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)objIds.get(Strings.toLowerCase(name));
-
- if (oid != null)
- {
- return getByOID(oid);
- }
-
- return null;
- }
-
- /**
- * return the X9ECParameters object for the named curve represented by
- * the passed in object identifier. Null if the curve isn't present.
- *
- * @param oid an object identifier representing a named curve, if present.
- */
- public static X9ECParameters getByOID(
- ASN1ObjectIdentifier oid)
- {
- X9ECParametersHolder holder = (X9ECParametersHolder)curves.get(oid);
-
- if (holder != null)
- {
- return holder.getParameters();
- }
-
- return null;
- }
-
- /**
- * return the object identifier signified by the passed in name. Null
- * if there is no object identifier associated with name.
- *
- * @return the object identifier associated with name, if present.
- */
- public static ASN1ObjectIdentifier getOID(
- String name)
- {
- return (ASN1ObjectIdentifier)objIds.get(Strings.toLowerCase(name));
- }
-
- /**
- * return the named curve name represented by the given object identifier.
- */
- public static String getName(
- ASN1ObjectIdentifier oid)
- {
- return (String)names.get(oid);
- }
-
- /**
- * returns an enumeration containing the name strings for curves
- * contained in this structure.
- */
- public static Enumeration getNames()
- {
- return objIds.keys();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java
deleted file mode 100644
index fb60aca6..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java
+++ /dev/null
@@ -1,87 +0,0 @@
-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
-{
- /** 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/core/src/main/java/org/bouncycastle/asn1/smime/SMIMEAttributes.java b/core/src/main/java/org/bouncycastle/asn1/smime/SMIMEAttributes.java
deleted file mode 100644
index eec29e65..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/smime/SMIMEAttributes.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.bouncycastle.asn1.smime;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-
-public interface SMIMEAttributes
-{
- public static final ASN1ObjectIdentifier smimeCapabilities = PKCSObjectIdentifiers.pkcs_9_at_smimeCapabilities;
- public static final ASN1ObjectIdentifier encrypKeyPref = PKCSObjectIdentifiers.id_aa_encrypKeyPref;
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/smime/SMIMECapabilities.java b/core/src/main/java/org/bouncycastle/asn1/smime/SMIMECapabilities.java
deleted file mode 100644
index f4558db5..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/smime/SMIMECapabilities.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package org.bouncycastle.asn1.smime;
-
-import java.util.Enumeration;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.cms.Attribute;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-
-/**
- * Handler class for dealing with S/MIME Capabilities
- */
-public class SMIMECapabilities
- extends ASN1Object
-{
- /**
- * general preferences
- */
- public static final ASN1ObjectIdentifier preferSignedData = PKCSObjectIdentifiers.preferSignedData;
- public static final ASN1ObjectIdentifier canNotDecryptAny = PKCSObjectIdentifiers.canNotDecryptAny;
- public static final ASN1ObjectIdentifier sMIMECapabilitesVersions = PKCSObjectIdentifiers.sMIMECapabilitiesVersions;
-
- /**
- * encryption algorithms preferences
- */
- public static final ASN1ObjectIdentifier dES_CBC = new ASN1ObjectIdentifier("1.3.14.3.2.7");
- public static final ASN1ObjectIdentifier dES_EDE3_CBC = PKCSObjectIdentifiers.des_EDE3_CBC;
- public static final ASN1ObjectIdentifier rC2_CBC = PKCSObjectIdentifiers.RC2_CBC;
-
- private ASN1Sequence capabilities;
-
- /**
- * return an Attribute object from the given object.
- *
- * @param o the object we want converted.
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static SMIMECapabilities getInstance(
- Object o)
- {
- if (o == null || o instanceof SMIMECapabilities)
- {
- return (SMIMECapabilities)o;
- }
-
- if (o instanceof ASN1Sequence)
- {
- return new SMIMECapabilities((ASN1Sequence)o);
- }
-
- if (o instanceof Attribute)
- {
- return new SMIMECapabilities(
- (ASN1Sequence)(((Attribute)o).getAttrValues().getObjectAt(0)));
- }
-
- throw new IllegalArgumentException("unknown object in factory: " + o.getClass().getName());
- }
-
- public SMIMECapabilities(
- ASN1Sequence seq)
- {
- capabilities = seq;
- }
-
- /**
- * returns a vector with 0 or more objects of all the capabilities
- * matching the passed in capability OID. If the OID passed is null the
- * entire set is returned.
- */
- public Vector getCapabilities(
- ASN1ObjectIdentifier capability)
- {
- Enumeration e = capabilities.getObjects();
- Vector list = new Vector();
-
- if (capability == null)
- {
- while (e.hasMoreElements())
- {
- SMIMECapability cap = SMIMECapability.getInstance(e.nextElement());
-
- list.addElement(cap);
- }
- }
- else
- {
- while (e.hasMoreElements())
- {
- SMIMECapability cap = SMIMECapability.getInstance(e.nextElement());
-
- if (capability.equals(cap.getCapabilityID()))
- {
- list.addElement(cap);
- }
- }
- }
-
- return list;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * SMIMECapabilities ::= SEQUENCE OF SMIMECapability
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- return capabilities;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/smime/SMIMECapabilitiesAttribute.java b/core/src/main/java/org/bouncycastle/asn1/smime/SMIMECapabilitiesAttribute.java
deleted file mode 100644
index cfad31ec..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/smime/SMIMECapabilitiesAttribute.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.bouncycastle.asn1.smime;
-
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERSet;
-import org.bouncycastle.asn1.cms.Attribute;
-
-public class SMIMECapabilitiesAttribute
- extends Attribute
-{
- public SMIMECapabilitiesAttribute(
- SMIMECapabilityVector capabilities)
- {
- super(SMIMEAttributes.smimeCapabilities,
- new DERSet(new DERSequence(capabilities.toASN1EncodableVector())));
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/smime/SMIMECapability.java b/core/src/main/java/org/bouncycastle/asn1/smime/SMIMECapability.java
deleted file mode 100644
index f70d28ae..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/smime/SMIMECapability.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package org.bouncycastle.asn1.smime;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-
-public class SMIMECapability
- extends ASN1Object
-{
- /**
- * general preferences
- */
- public static final ASN1ObjectIdentifier preferSignedData = PKCSObjectIdentifiers.preferSignedData;
- public static final ASN1ObjectIdentifier canNotDecryptAny = PKCSObjectIdentifiers.canNotDecryptAny;
- public static final ASN1ObjectIdentifier sMIMECapabilitiesVersions = PKCSObjectIdentifiers.sMIMECapabilitiesVersions;
-
- /**
- * encryption algorithms preferences
- */
- public static final ASN1ObjectIdentifier dES_CBC = new ASN1ObjectIdentifier("1.3.14.3.2.7");
- public static final ASN1ObjectIdentifier dES_EDE3_CBC = PKCSObjectIdentifiers.des_EDE3_CBC;
- public static final ASN1ObjectIdentifier rC2_CBC = PKCSObjectIdentifiers.RC2_CBC;
- public static final ASN1ObjectIdentifier aES128_CBC = NISTObjectIdentifiers.id_aes128_CBC;
- public static final ASN1ObjectIdentifier aES192_CBC = NISTObjectIdentifiers.id_aes192_CBC;
- public static final ASN1ObjectIdentifier aES256_CBC = NISTObjectIdentifiers.id_aes256_CBC;
-
- private ASN1ObjectIdentifier capabilityID;
- private ASN1Encodable parameters;
-
- public SMIMECapability(
- ASN1Sequence seq)
- {
- capabilityID = (ASN1ObjectIdentifier)seq.getObjectAt(0);
-
- if (seq.size() > 1)
- {
- parameters = (ASN1Primitive)seq.getObjectAt(1);
- }
- }
-
- public SMIMECapability(
- ASN1ObjectIdentifier capabilityID,
- ASN1Encodable parameters)
- {
- this.capabilityID = capabilityID;
- this.parameters = parameters;
- }
-
- public static SMIMECapability getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof SMIMECapability)
- {
- return (SMIMECapability)obj;
- }
-
- if (obj instanceof ASN1Sequence)
- {
- return new SMIMECapability((ASN1Sequence)obj);
- }
-
- throw new IllegalArgumentException("Invalid SMIMECapability");
- }
-
- public ASN1ObjectIdentifier getCapabilityID()
- {
- return capabilityID;
- }
-
- public ASN1Encodable getParameters()
- {
- return parameters;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * SMIMECapability ::= SEQUENCE {
- * capabilityID OBJECT IDENTIFIER,
- * parameters ANY DEFINED BY capabilityID OPTIONAL
- * }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(capabilityID);
-
- if (parameters != null)
- {
- v.add(parameters);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/smime/SMIMECapabilityVector.java b/core/src/main/java/org/bouncycastle/asn1/smime/SMIMECapabilityVector.java
deleted file mode 100644
index 965a9965..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/smime/SMIMECapabilityVector.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package org.bouncycastle.asn1.smime;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * Handler for creating a vector S/MIME Capabilities
- */
-public class SMIMECapabilityVector
-{
- private ASN1EncodableVector capabilities = new ASN1EncodableVector();
-
- public void addCapability(
- ASN1ObjectIdentifier capability)
- {
- capabilities.add(new DERSequence(capability));
- }
-
- public void addCapability(
- ASN1ObjectIdentifier capability,
- int value)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(capability);
- v.add(new ASN1Integer(value));
-
- capabilities.add(new DERSequence(v));
- }
-
- public void addCapability(
- ASN1ObjectIdentifier capability,
- ASN1Encodable params)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(capability);
- v.add(params);
-
- capabilities.add(new DERSequence(v));
- }
-
- public ASN1EncodableVector toASN1EncodableVector()
- {
- return capabilities;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/smime/SMIMEEncryptionKeyPreferenceAttribute.java b/core/src/main/java/org/bouncycastle/asn1/smime/SMIMEEncryptionKeyPreferenceAttribute.java
deleted file mode 100644
index 1e5b5396..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/smime/SMIMEEncryptionKeyPreferenceAttribute.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.bouncycastle.asn1.smime;
-
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.DERSet;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.cms.Attribute;
-import org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
-import org.bouncycastle.asn1.cms.RecipientKeyIdentifier;
-
-/**
- * The SMIMEEncryptionKeyPreference object.
- * <pre>
- * SMIMEEncryptionKeyPreference ::= CHOICE {
- * issuerAndSerialNumber [0] IssuerAndSerialNumber,
- * receipentKeyId [1] RecipientKeyIdentifier,
- * subjectAltKeyIdentifier [2] SubjectKeyIdentifier
- * }
- * </pre>
- */
-public class SMIMEEncryptionKeyPreferenceAttribute
- extends Attribute
-{
- public SMIMEEncryptionKeyPreferenceAttribute(
- IssuerAndSerialNumber issAndSer)
- {
- super(SMIMEAttributes.encrypKeyPref,
- new DERSet(new DERTaggedObject(false, 0, issAndSer)));
- }
-
- public SMIMEEncryptionKeyPreferenceAttribute(
- RecipientKeyIdentifier rKeyId)
- {
-
- super(SMIMEAttributes.encrypKeyPref,
- new DERSet(new DERTaggedObject(false, 1, rKeyId)));
- }
-
- /**
- * @param sKeyId the subjectKeyIdentifier value (normally the X.509 one)
- */
- public SMIMEEncryptionKeyPreferenceAttribute(
- ASN1OctetString sKeyId)
- {
-
- super(SMIMEAttributes.encrypKeyPref,
- new DERSet(new DERTaggedObject(false, 2, sKeyId)));
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTNamedCurves.java b/core/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTNamedCurves.java
deleted file mode 100644
index 9420c3ce..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTNamedCurves.java
+++ /dev/null
@@ -1,398 +0,0 @@
-package org.bouncycastle.asn1.teletrust;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-import java.util.Hashtable;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.asn1.x9.X9ECParametersHolder;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.util.Strings;
-import org.bouncycastle.util.encoders.Hex;
-
-/**
- * elliptic curves defined in "ECC Brainpool Standard Curves and Curve Generation"
- * http://www.ecc-brainpool.org/download/draft_pkix_additional_ecc_dp.txt
- */
-public class TeleTrusTNamedCurves
-{
- private static ECCurve configureCurve(ECCurve curve)
- {
- return curve;
- }
-
- static X9ECParametersHolder brainpoolP160r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger n = new BigInteger("E95E4A5F737059DC60DF5991D45029409E60FC09", 16);
- BigInteger h = new BigInteger("01", 16);
-
- ECCurve curve = configureCurve(new ECCurve.Fp(
- new BigInteger("E95E4A5F737059DC60DFC7AD95B3D8139515620F", 16), // q
- new BigInteger("340E7BE2A280EB74E2BE61BADA745D97E8F7C300", 16), // a
- new BigInteger("1E589A8595423412134FAA2DBDEC95C8D8675E58", 16), // b
- n, h));
-
- return new X9ECParameters(
- curve,
- curve.decodePoint(Hex.decode("04BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC31667CB477A1A8EC338F94741669C976316DA6321")), // G
- n, h);
- }
- };
-
- static X9ECParametersHolder brainpoolP160t1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger n = new BigInteger("E95E4A5F737059DC60DF5991D45029409E60FC09", 16);
- BigInteger h = new BigInteger("01", 16);
-
- 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'
- n, h));
-
- return new X9ECParameters(
- curve,
- curve.decodePoint(Hex.decode("04B199B13B9B34EFC1397E64BAEB05ACC265FF2378ADD6718B7C7C1961F0991B842443772152C9E0AD")), // G
- n, h);
- }
- };
-
- static X9ECParametersHolder brainpoolP192r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger n = new BigInteger("C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", 16);
- BigInteger h = new BigInteger("01", 16);
-
- ECCurve curve = configureCurve(new ECCurve.Fp(
- new BigInteger("C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", 16), // q
- new BigInteger("6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", 16), // a
- new BigInteger("469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", 16), // b
- n, h));
-
- return new X9ECParameters(
- curve,
- curve.decodePoint(Hex.decode("04C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD614B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F")), // G
- n, h);
- }
- };
-
- static X9ECParametersHolder brainpoolP192t1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger n = new BigInteger("C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", 16);
- BigInteger h = new BigInteger("01", 16);
-
- 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'
- n, h));
-
- return new X9ECParameters(
- curve,
- curve.decodePoint(Hex.decode("043AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9")), // G'
- n, h);
- }
- };
-
- static X9ECParametersHolder brainpoolP224r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger n = new BigInteger("D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", 16);
- BigInteger h = new BigInteger("01", 16);
-
- ECCurve curve = configureCurve(new ECCurve.Fp(
- new BigInteger("D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", 16), // q
- new BigInteger("68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", 16), // a
- new BigInteger("2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", 16), // b
- n, h));
-
- return new X9ECParameters(
- curve,
- curve.decodePoint(Hex.decode("040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD")), // G
- n, h);
- }
- };
- static X9ECParametersHolder brainpoolP224t1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger n = new BigInteger("D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", 16);
- BigInteger h = new BigInteger("01", 16);
-
- 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'
- n, h));
-
- return new X9ECParameters(
- curve,
- curve.decodePoint(Hex.decode("046AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D5800374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C")), // G'
- n, h);
- }
- };
- static X9ECParametersHolder brainpoolP256r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger n = new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 16);
- BigInteger h = new BigInteger("01", 16);
-
- ECCurve curve = configureCurve(new ECCurve.Fp(
- new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", 16), // q
- new BigInteger("7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", 16), // a
- new BigInteger("26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", 16), // b
- n, h));
-
- return new X9ECParameters(
- curve,
- curve.decodePoint(Hex.decode("048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997")), // G
- n, h);
- }
- };
- static X9ECParametersHolder brainpoolP256t1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger n = new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 16);
- BigInteger h = new BigInteger("01", 16);
-
- 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'
- n, h));
-
- return new X9ECParameters(
- curve,
- curve.decodePoint(Hex.decode("04A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F42D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE")), // G'
- n, h);
- }
- };
- static X9ECParametersHolder brainpoolP320r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger n = new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", 16);
- BigInteger h = new BigInteger("01", 16);
-
- ECCurve curve = configureCurve(new ECCurve.Fp(
- new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", 16), // q
- new BigInteger("3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", 16), // a
- new BigInteger("520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", 16), // b
- n, h));
-
- return new X9ECParameters(
- curve,
- curve.decodePoint(Hex.decode("0443BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E2061114FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1")), // G
- n, h);
- }
- };
- static X9ECParametersHolder brainpoolP320t1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger n = new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", 16);
- BigInteger h = new BigInteger("01", 16);
-
- 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'
- n, h));
-
- return new X9ECParameters(
- curve,
- curve.decodePoint(Hex.decode("04925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED5263BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3")), // G'
- n, h);
- }
- };
- static X9ECParametersHolder brainpoolP384r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger n = new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 16);
- BigInteger h = new BigInteger("01", 16);
-
- ECCurve curve = configureCurve(new ECCurve.Fp(
- new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", 16), // q
- new BigInteger("7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", 16), // a
- new BigInteger("4A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", 16), // b
- n, h));
-
- return new X9ECParameters(
- curve,
- curve.decodePoint(Hex.decode("041D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315")), // G
- n, h);
- }
- };
- static X9ECParametersHolder brainpoolP384t1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger n = new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 16);
- BigInteger h = new BigInteger("01", 16);
-
- 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'
- n, h));
-
- return new X9ECParameters(
- curve,
- curve.decodePoint(Hex.decode("0418DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928")), // G'
- n, h);
- }
- };
- static X9ECParametersHolder brainpoolP512r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger n = new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 16);
- BigInteger h = new BigInteger("01", 16);
-
- ECCurve curve = configureCurve(new ECCurve.Fp(
- new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", 16), // q
- new BigInteger("7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", 16), // a
- new BigInteger("3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", 16), // b
- n, h));
-
- return new X9ECParameters(
- curve,
- curve.decodePoint(Hex.decode("0481AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F8227DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892")), // G
- n, h);
- }
- };
- static X9ECParametersHolder brainpoolP512t1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger n = new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 16);
- BigInteger h = new BigInteger("01", 16);
-
- 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'
- n, h));
-
- return new X9ECParameters(
- curve,
- curve.decodePoint(Hex.decode("04640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332")), // G'
- n, h);
- }
- };
-
- static final Hashtable objIds = new Hashtable();
- static final Hashtable curves = new Hashtable();
- static final Hashtable names = new Hashtable();
-
- static void defineCurve(String name, ASN1ObjectIdentifier oid, X9ECParametersHolder holder)
- {
- objIds.put(name, oid);
- names.put(oid, name);
- curves.put(oid, holder);
- }
-
- static
- {
- defineCurve("brainpoolp160r1", TeleTrusTObjectIdentifiers.brainpoolP160r1, brainpoolP160r1);
- defineCurve("brainpoolp160t1", TeleTrusTObjectIdentifiers.brainpoolP160t1, brainpoolP160t1);
- defineCurve("brainpoolp192r1", TeleTrusTObjectIdentifiers.brainpoolP192r1, brainpoolP192r1);
- defineCurve("brainpoolp192t1", TeleTrusTObjectIdentifiers.brainpoolP192t1, brainpoolP192t1);
- defineCurve("brainpoolp224r1", TeleTrusTObjectIdentifiers.brainpoolP224r1, brainpoolP224r1);
- defineCurve("brainpoolp224t1", TeleTrusTObjectIdentifiers.brainpoolP224t1, brainpoolP224t1);
- defineCurve("brainpoolp256r1", TeleTrusTObjectIdentifiers.brainpoolP256r1, brainpoolP256r1);
- defineCurve("brainpoolp256t1", TeleTrusTObjectIdentifiers.brainpoolP256t1, brainpoolP256t1);
- defineCurve("brainpoolp320r1", TeleTrusTObjectIdentifiers.brainpoolP320r1, brainpoolP320r1);
- defineCurve("brainpoolp320t1", TeleTrusTObjectIdentifiers.brainpoolP320t1, brainpoolP320t1);
- defineCurve("brainpoolp384r1", TeleTrusTObjectIdentifiers.brainpoolP384r1, brainpoolP384r1);
- defineCurve("brainpoolp384t1", TeleTrusTObjectIdentifiers.brainpoolP384t1, brainpoolP384t1);
- defineCurve("brainpoolp512r1", TeleTrusTObjectIdentifiers.brainpoolP512r1, brainpoolP512r1);
- defineCurve("brainpoolp512t1", TeleTrusTObjectIdentifiers.brainpoolP512t1, brainpoolP512t1);
- }
-
- public static X9ECParameters getByName(
- String name)
- {
- ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)objIds.get(Strings.toLowerCase(name));
-
- if (oid != null)
- {
- return getByOID(oid);
- }
-
- return null;
- }
-
- /**
- * return the X9ECParameters object for the named curve represented by
- * the passed in object identifier. Null if the curve isn't present.
- *
- * @param oid an object identifier representing a named curve, if present.
- */
- public static X9ECParameters getByOID(
- ASN1ObjectIdentifier oid)
- {
- X9ECParametersHolder holder = (X9ECParametersHolder)curves.get(oid);
-
- if (holder != null)
- {
- return holder.getParameters();
- }
-
- return null;
- }
-
- /**
- * return the object identifier signified by the passed in name. Null
- * if there is no object identifier associated with name.
- *
- * @return the object identifier associated with name, if present.
- */
- public static ASN1ObjectIdentifier getOID(
- String name)
- {
- return (ASN1ObjectIdentifier)objIds.get(Strings.toLowerCase(name));
- }
-
- /**
- * return the named curve name represented by the given object identifier.
- */
- public static String getName(
- ASN1ObjectIdentifier oid)
- {
- return (String)names.get(oid);
- }
-
- /**
- * returns an enumeration containing the name strings for curves
- * contained in this structure.
- */
- public static Enumeration getNames()
- {
- return objIds.keys();
- }
-
- public static ASN1ObjectIdentifier getOID(short curvesize, boolean twisted)
- {
- return getOID("brainpoolP" + curvesize + (twisted ? "t" : "r") + "1");
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java
deleted file mode 100644
index 2be7efec..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java
+++ /dev/null
@@ -1,75 +0,0 @@
-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");
-
- /** 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");
-
- /** 1.3.36.3.3.2 */
- static final ASN1ObjectIdentifier ecSign = teleTrusTAlgorithm.branch("3.2");
-
- /** 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.1 */
- static final ASN1ObjectIdentifier versionOne = ellipticCurve.branch("1");
-
- /** 1.3.36.3.3.2.8.1.1.1 */
- static final ASN1ObjectIdentifier brainpoolP160r1 = versionOne.branch("1");
- /** 1.3.36.3.3.2.8.1.1.2 */
- static final ASN1ObjectIdentifier brainpoolP160t1 = versionOne.branch("2");
- /** 1.3.36.3.3.2.8.1.1.3 */
- static final ASN1ObjectIdentifier brainpoolP192r1 = versionOne.branch("3");
- /** 1.3.36.3.3.2.8.1.1.4 */
- static final ASN1ObjectIdentifier brainpoolP192t1 = versionOne.branch("4");
- /** 1.3.36.3.3.2.8.1.1.5 */
- static final ASN1ObjectIdentifier brainpoolP224r1 = versionOne.branch("5");
- /** 1.3.36.3.3.2.8.1.1.6 */
- static final ASN1ObjectIdentifier brainpoolP224t1 = versionOne.branch("6");
- /** 1.3.36.3.3.2.8.1.1.7 */
- static final ASN1ObjectIdentifier brainpoolP256r1 = versionOne.branch("7");
- /** 1.3.36.3.3.2.8.1.1.8 */
- static final ASN1ObjectIdentifier brainpoolP256t1 = versionOne.branch("8");
- /** 1.3.36.3.3.2.8.1.1.9 */
- static final ASN1ObjectIdentifier brainpoolP320r1 = versionOne.branch("9");
- /** 1.3.36.3.3.2.8.1.1.10 */
- static final ASN1ObjectIdentifier brainpoolP320t1 = versionOne.branch("10");
- /** 1.3.36.3.3.2.8.1.1.11 */
- static final ASN1ObjectIdentifier brainpoolP384r1 = versionOne.branch("11");
- /** 1.3.36.3.3.2.8.1.1.12 */
- static final ASN1ObjectIdentifier brainpoolP384t1 = versionOne.branch("12");
- /** 1.3.36.3.3.2.8.1.1.13 */
- static final ASN1ObjectIdentifier brainpoolP512r1 = versionOne.branch("13");
- /** 1.3.36.3.3.2.8.1.1.14 */
- static final ASN1ObjectIdentifier brainpoolP512t1 = versionOne.branch("14");
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/tsp/Accuracy.java b/core/src/main/java/org/bouncycastle/asn1/tsp/Accuracy.java
deleted file mode 100644
index fb7763d1..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/tsp/Accuracy.java
+++ /dev/null
@@ -1,173 +0,0 @@
-package org.bouncycastle.asn1.tsp;
-
-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.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-
-public class Accuracy
- extends ASN1Object
-{
- ASN1Integer seconds;
-
- ASN1Integer millis;
-
- ASN1Integer micros;
-
- // constantes
- protected static final int MIN_MILLIS = 1;
-
- protected static final int MAX_MILLIS = 999;
-
- protected static final int MIN_MICROS = 1;
-
- protected static final int MAX_MICROS = 999;
-
- protected Accuracy()
- {
- }
-
- public Accuracy(
- ASN1Integer seconds,
- ASN1Integer millis,
- ASN1Integer micros)
- {
- this.seconds = seconds;
-
- //Verifications
- if (millis != null
- && (millis.getValue().intValue() < MIN_MILLIS || millis
- .getValue().intValue() > MAX_MILLIS))
- {
- throw new IllegalArgumentException(
- "Invalid millis field : not in (1..999)");
- }
- else
- {
- this.millis = millis;
- }
-
- if (micros != null
- && (micros.getValue().intValue() < MIN_MICROS || micros
- .getValue().intValue() > MAX_MICROS))
- {
- throw new IllegalArgumentException(
- "Invalid micros field : not in (1..999)");
- }
- else
- {
- this.micros = micros;
- }
-
- }
-
- private Accuracy(ASN1Sequence seq)
- {
- seconds = null;
- millis = null;
- micros = null;
-
- for (int i = 0; i < seq.size(); i++)
- {
- // seconds
- if (seq.getObjectAt(i) instanceof ASN1Integer)
- {
- seconds = (ASN1Integer) seq.getObjectAt(i);
- }
- else if (seq.getObjectAt(i) instanceof DERTaggedObject)
- {
- DERTaggedObject extra = (DERTaggedObject) seq.getObjectAt(i);
-
- switch (extra.getTagNo())
- {
- case 0:
- millis = ASN1Integer.getInstance(extra, false);
- if (millis.getValue().intValue() < MIN_MILLIS
- || millis.getValue().intValue() > MAX_MILLIS)
- {
- throw new IllegalArgumentException(
- "Invalid millis field : not in (1..999).");
- }
- break;
- case 1:
- micros = ASN1Integer.getInstance(extra, false);
- if (micros.getValue().intValue() < MIN_MICROS
- || micros.getValue().intValue() > MAX_MICROS)
- {
- throw new IllegalArgumentException(
- "Invalid micros field : not in (1..999).");
- }
- break;
- default:
- throw new IllegalArgumentException("Invalig tag number");
- }
- }
- }
- }
-
- public static Accuracy getInstance(Object o)
- {
- if (o instanceof Accuracy)
- {
- return (Accuracy) o;
- }
-
- if (o != null)
- {
- return new Accuracy(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public ASN1Integer getSeconds()
- {
- return seconds;
- }
-
- public ASN1Integer getMillis()
- {
- return millis;
- }
-
- public ASN1Integer getMicros()
- {
- return micros;
- }
-
- /**
- * <pre>
- * Accuracy ::= SEQUENCE {
- * seconds INTEGER OPTIONAL,
- * millis [0] INTEGER (1..999) OPTIONAL,
- * micros [1] INTEGER (1..999) OPTIONAL
- * }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
-
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (seconds != null)
- {
- v.add(seconds);
- }
-
- if (millis != null)
- {
- v.add(new DERTaggedObject(false, 0, millis));
- }
-
- if (micros != null)
- {
- v.add(new DERTaggedObject(false, 1, micros));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/tsp/MessageImprint.java b/core/src/main/java/org/bouncycastle/asn1/tsp/MessageImprint.java
deleted file mode 100644
index b551fcfb..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/tsp/MessageImprint.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.bouncycastle.asn1.tsp;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-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.asn1.x509.AlgorithmIdentifier;
-
-public class MessageImprint
- extends ASN1Object
-{
- AlgorithmIdentifier hashAlgorithm;
- byte[] hashedMessage;
-
- /**
- * @param o
- * @return a MessageImprint object.
- */
- public static MessageImprint getInstance(Object o)
- {
- if (o instanceof MessageImprint)
- {
- return (MessageImprint)o;
- }
-
- if (o != null)
- {
- return new MessageImprint(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- private MessageImprint(
- ASN1Sequence seq)
- {
- this.hashAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(0));
- this.hashedMessage = ASN1OctetString.getInstance(seq.getObjectAt(1)).getOctets();
- }
-
- public MessageImprint(
- AlgorithmIdentifier hashAlgorithm,
- byte[] hashedMessage)
- {
- this.hashAlgorithm = hashAlgorithm;
- this.hashedMessage = hashedMessage;
- }
-
- public AlgorithmIdentifier getHashAlgorithm()
- {
- return hashAlgorithm;
- }
-
- public byte[] getHashedMessage()
- {
- return hashedMessage;
- }
-
- /**
- * <pre>
- * MessageImprint ::= SEQUENCE {
- * hashAlgorithm AlgorithmIdentifier,
- * hashedMessage OCTET STRING }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(hashAlgorithm);
- v.add(new DEROctetString(hashedMessage));
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/tsp/TSTInfo.java b/core/src/main/java/org/bouncycastle/asn1/tsp/TSTInfo.java
deleted file mode 100644
index 312224e5..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/tsp/TSTInfo.java
+++ /dev/null
@@ -1,233 +0,0 @@
-package org.bouncycastle.asn1.tsp;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Boolean;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.Extensions;
-import org.bouncycastle.asn1.x509.GeneralName;
-
-public class TSTInfo
- extends ASN1Object
-{
- private ASN1Integer version;
- private ASN1ObjectIdentifier tsaPolicyId;
- private MessageImprint messageImprint;
- private ASN1Integer serialNumber;
- private ASN1GeneralizedTime genTime;
- private Accuracy accuracy;
- private ASN1Boolean ordering;
- private ASN1Integer nonce;
- private GeneralName tsa;
- private Extensions extensions;
-
- public static TSTInfo getInstance(Object o)
- {
- if (o instanceof TSTInfo)
- {
- return (TSTInfo)o;
- }
- else if (o != null)
- {
- return new TSTInfo(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- private TSTInfo(ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- // version
- version = ASN1Integer.getInstance(e.nextElement());
-
- // tsaPolicy
- tsaPolicyId = ASN1ObjectIdentifier.getInstance(e.nextElement());
-
- // messageImprint
- messageImprint = MessageImprint.getInstance(e.nextElement());
-
- // serialNumber
- serialNumber = ASN1Integer.getInstance(e.nextElement());
-
- // genTime
- genTime = ASN1GeneralizedTime.getInstance(e.nextElement());
-
- // default for ordering
- ordering = ASN1Boolean.getInstance(false);
-
- while (e.hasMoreElements())
- {
- ASN1Object o = (ASN1Object) e.nextElement();
-
- if (o instanceof ASN1TaggedObject)
- {
- DERTaggedObject tagged = (DERTaggedObject) o;
-
- switch (tagged.getTagNo())
- {
- case 0:
- tsa = GeneralName.getInstance(tagged, true);
- break;
- case 1:
- extensions = Extensions.getInstance(tagged, false);
- break;
- default:
- throw new IllegalArgumentException("Unknown tag value " + tagged.getTagNo());
- }
- }
- else if (o instanceof ASN1Sequence || o instanceof Accuracy)
- {
- accuracy = Accuracy.getInstance(o);
- }
- else if (o instanceof ASN1Boolean)
- {
- ordering = ASN1Boolean.getInstance(o);
- }
- else if (o instanceof ASN1Integer)
- {
- nonce = ASN1Integer.getInstance(o);
- }
-
- }
- }
-
- public TSTInfo(ASN1ObjectIdentifier tsaPolicyId, MessageImprint messageImprint,
- ASN1Integer serialNumber, ASN1GeneralizedTime genTime,
- Accuracy accuracy, ASN1Boolean ordering, ASN1Integer nonce,
- GeneralName tsa, Extensions extensions)
- {
- version = new ASN1Integer(1);
- this.tsaPolicyId = tsaPolicyId;
- this.messageImprint = messageImprint;
- this.serialNumber = serialNumber;
- this.genTime = genTime;
-
- this.accuracy = accuracy;
- this.ordering = ordering;
- this.nonce = nonce;
- this.tsa = tsa;
- this.extensions = extensions;
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public MessageImprint getMessageImprint()
- {
- return messageImprint;
- }
-
- public ASN1ObjectIdentifier getPolicy()
- {
- return tsaPolicyId;
- }
-
- public ASN1Integer getSerialNumber()
- {
- return serialNumber;
- }
-
- public Accuracy getAccuracy()
- {
- return accuracy;
- }
-
- public ASN1GeneralizedTime getGenTime()
- {
- return genTime;
- }
-
- public ASN1Boolean getOrdering()
- {
- return ordering;
- }
-
- public ASN1Integer getNonce()
- {
- return nonce;
- }
-
- public GeneralName getTsa()
- {
- return tsa;
- }
-
- public Extensions getExtensions()
- {
- return extensions;
- }
-
- /**
- * <pre>
- *
- * TSTInfo ::= SEQUENCE {
- * version INTEGER { v1(1) },
- * policy TSAPolicyId,
- * messageImprint MessageImprint,
- * -- MUST have the same value as the similar field in
- * -- TimeStampReq
- * serialNumber INTEGER,
- * -- Time-Stamping users MUST be ready to accommodate integers
- * -- up to 160 bits.
- * genTime GeneralizedTime,
- * accuracy Accuracy OPTIONAL,
- * ordering BOOLEAN DEFAULT FALSE,
- * nonce INTEGER OPTIONAL,
- * -- MUST be present if the similar field was present
- * -- in TimeStampReq. In that case it MUST have the same value.
- * tsa [0] GeneralName OPTIONAL,
- * extensions [1] IMPLICIT Extensions OPTIONAL }
- *
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector seq = new ASN1EncodableVector();
- seq.add(version);
-
- seq.add(tsaPolicyId);
- seq.add(messageImprint);
- seq.add(serialNumber);
- seq.add(genTime);
-
- if (accuracy != null)
- {
- seq.add(accuracy);
- }
-
- if (ordering != null && ordering.isTrue())
- {
- seq.add(ordering);
- }
-
- if (nonce != null)
- {
- seq.add(nonce);
- }
-
- if (tsa != null)
- {
- seq.add(new DERTaggedObject(true, 0, tsa));
- }
-
- if (extensions != null)
- {
- seq.add(new DERTaggedObject(false, 1, extensions));
- }
-
- return new DERSequence(seq);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/tsp/TimeStampReq.java b/core/src/main/java/org/bouncycastle/asn1/tsp/TimeStampReq.java
deleted file mode 100644
index 44490f02..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/tsp/TimeStampReq.java
+++ /dev/null
@@ -1,179 +0,0 @@
-package org.bouncycastle.asn1.tsp;
-
-import org.bouncycastle.asn1.ASN1Boolean;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.Extensions;
-
-public class TimeStampReq
- extends ASN1Object
-{
- ASN1Integer version;
-
- MessageImprint messageImprint;
-
- ASN1ObjectIdentifier tsaPolicy;
-
- ASN1Integer nonce;
-
- ASN1Boolean certReq;
-
- Extensions extensions;
-
- public static TimeStampReq getInstance(Object o)
- {
- if (o instanceof TimeStampReq)
- {
- return (TimeStampReq) o;
- }
- else if (o != null)
- {
- return new TimeStampReq(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- private TimeStampReq(ASN1Sequence seq)
- {
- int nbObjects = seq.size();
-
- int seqStart = 0;
-
- // version
- version = ASN1Integer.getInstance(seq.getObjectAt(seqStart));
-
- seqStart++;
-
- // messageImprint
- messageImprint = MessageImprint.getInstance(seq.getObjectAt(seqStart));
-
- seqStart++;
-
- for (int opt = seqStart; opt < nbObjects; opt++)
- {
- // tsaPolicy
- if (seq.getObjectAt(opt) instanceof ASN1ObjectIdentifier)
- {
- tsaPolicy = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(opt));
- }
- // nonce
- else if (seq.getObjectAt(opt) instanceof ASN1Integer)
- {
- nonce = ASN1Integer.getInstance(seq.getObjectAt(opt));
- }
- // certReq
- else if (seq.getObjectAt(opt) instanceof ASN1Boolean)
- {
- certReq = ASN1Boolean.getInstance(seq.getObjectAt(opt));
- }
- // extensions
- else if (seq.getObjectAt(opt) instanceof ASN1TaggedObject)
- {
- ASN1TaggedObject tagged = (ASN1TaggedObject)seq.getObjectAt(opt);
- if (tagged.getTagNo() == 0)
- {
- extensions = Extensions.getInstance(tagged, false);
- }
- }
- }
- }
-
- public TimeStampReq(
- MessageImprint messageImprint,
- ASN1ObjectIdentifier tsaPolicy,
- ASN1Integer nonce,
- ASN1Boolean certReq,
- Extensions extensions)
- {
- // default
- version = new ASN1Integer(1);
-
- this.messageImprint = messageImprint;
- this.tsaPolicy = tsaPolicy;
- this.nonce = nonce;
- this.certReq = certReq;
- this.extensions = extensions;
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public MessageImprint getMessageImprint()
- {
- return messageImprint;
- }
-
- public ASN1ObjectIdentifier getReqPolicy()
- {
- return tsaPolicy;
- }
-
- public ASN1Integer getNonce()
- {
- return nonce;
- }
-
- public ASN1Boolean getCertReq()
- {
- return certReq;
- }
-
- public Extensions getExtensions()
- {
- return extensions;
- }
-
- /**
- * <pre>
- * TimeStampReq ::= SEQUENCE {
- * version INTEGER { v1(1) },
- * messageImprint MessageImprint,
- * --a hash algorithm OID and the hash value of the data to be
- * --time-stamped
- * reqPolicy TSAPolicyId OPTIONAL,
- * nonce INTEGER OPTIONAL,
- * certReq BOOLEAN DEFAULT FALSE,
- * extensions [0] IMPLICIT Extensions OPTIONAL
- * }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(version);
- v.add(messageImprint);
-
- if (tsaPolicy != null)
- {
- v.add(tsaPolicy);
- }
-
- if (nonce != null)
- {
- v.add(nonce);
- }
-
- if (certReq != null && certReq.isTrue())
- {
- v.add(certReq);
- }
-
- if (extensions != null)
- {
- v.add(new DERTaggedObject(false, 0, extensions));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/tsp/TimeStampResp.java b/core/src/main/java/org/bouncycastle/asn1/tsp/TimeStampResp.java
deleted file mode 100644
index 96d08a12..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/tsp/TimeStampResp.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package org.bouncycastle.asn1.tsp;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.cmp.PKIStatusInfo;
-import org.bouncycastle.asn1.cms.ContentInfo;
-
-
-public class TimeStampResp
- extends ASN1Object
-{
- PKIStatusInfo pkiStatusInfo;
-
- ContentInfo timeStampToken;
-
- public static TimeStampResp getInstance(Object o)
- {
- if (o instanceof TimeStampResp)
- {
- return (TimeStampResp) o;
- }
- else if (o != null)
- {
- return new TimeStampResp(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- private TimeStampResp(ASN1Sequence seq)
- {
-
- Enumeration e = seq.getObjects();
-
- // status
- pkiStatusInfo = PKIStatusInfo.getInstance(e.nextElement());
-
- if (e.hasMoreElements())
- {
- timeStampToken = ContentInfo.getInstance(e.nextElement());
- }
- }
-
- public TimeStampResp(PKIStatusInfo pkiStatusInfo, ContentInfo timeStampToken)
- {
- this.pkiStatusInfo = pkiStatusInfo;
- this.timeStampToken = timeStampToken;
- }
-
- public PKIStatusInfo getStatus()
- {
- return pkiStatusInfo;
- }
-
- public ContentInfo getTimeStampToken()
- {
- return timeStampToken;
- }
-
- /**
- * <pre>
- * TimeStampResp ::= SEQUENCE {
- * status PKIStatusInfo,
- * timeStampToken TimeStampToken OPTIONAL }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(pkiStatusInfo);
- if (timeStampToken != null)
- {
- v.add(timeStampToken);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145BinaryField.java b/core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145BinaryField.java
deleted file mode 100644
index a0cca6b4..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145BinaryField.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package org.bouncycastle.asn1.ua;
-
-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.DERSequence;
-
-public class DSTU4145BinaryField
- extends ASN1Object
-{
-
- private int m, k, j, l;
-
- private DSTU4145BinaryField(ASN1Sequence seq)
- {
- m = ASN1Integer.getInstance(seq.getObjectAt(0)).getPositiveValue().intValue();
-
- if (seq.getObjectAt(1) instanceof ASN1Integer)
- {
- k = ((ASN1Integer)seq.getObjectAt(1)).getPositiveValue().intValue();
- }
- else if (seq.getObjectAt(1) instanceof ASN1Sequence)
- {
- ASN1Sequence coefs = ASN1Sequence.getInstance(seq.getObjectAt(1));
-
- k = ASN1Integer.getInstance(coefs.getObjectAt(0)).getPositiveValue().intValue();
- j = ASN1Integer.getInstance(coefs.getObjectAt(1)).getPositiveValue().intValue();
- l = ASN1Integer.getInstance(coefs.getObjectAt(2)).getPositiveValue().intValue();
- }
- else
- {
- throw new IllegalArgumentException("object parse error");
- }
- }
-
- public static DSTU4145BinaryField getInstance(Object obj)
- {
- if (obj instanceof DSTU4145BinaryField)
- {
- return (DSTU4145BinaryField)obj;
- }
-
- if (obj != null)
- {
- return new DSTU4145BinaryField(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public DSTU4145BinaryField(int m, int k1, int k2, int k3)
- {
- this.m = m;
- this.k = k1;
- this.j = k2;
- this.l = k3;
- }
-
- public int getM()
- {
- return m;
- }
-
- public int getK1()
- {
- return k;
- }
-
- public int getK2()
- {
- return j;
- }
-
- public int getK3()
- {
- return l;
- }
-
- public DSTU4145BinaryField(int m, int k)
- {
- this(m, k, 0, 0);
- }
-
- /**
- * BinaryField ::= SEQUENCE {
- * M INTEGER,
- * CHOICE {Trinomial, Pentanomial}
- * Trinomial::= INTEGER
- * Pentanomial::= SEQUENCE {
- * k INTEGER,
- * j INTEGER,
- * l INTEGER}
- */
- public ASN1Primitive toASN1Primitive()
- {
-
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(new ASN1Integer(m));
- if (j == 0) //Trinomial
- {
- v.add(new ASN1Integer(k));
- }
- else
- {
- ASN1EncodableVector coefs = new ASN1EncodableVector();
- coefs.add(new ASN1Integer(k));
- coefs.add(new ASN1Integer(j));
- coefs.add(new ASN1Integer(l));
-
- v.add(new DERSequence(coefs));
- }
-
- return new DERSequence(v);
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145ECBinary.java b/core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145ECBinary.java
deleted file mode 100644
index dc9f74c0..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145ECBinary.java
+++ /dev/null
@@ -1,154 +0,0 @@
-package org.bouncycastle.asn1.ua;
-
-import java.math.BigInteger;
-
-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.ASN1TaggedObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.math.ec.ECAlgorithms;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.field.PolynomialExtensionField;
-import org.bouncycastle.util.Arrays;
-
-public class DSTU4145ECBinary
- extends ASN1Object
-{
- BigInteger version = BigInteger.valueOf(0);
-
- DSTU4145BinaryField f;
- ASN1Integer a;
- ASN1OctetString b;
- ASN1Integer n;
- ASN1OctetString bp;
-
- public DSTU4145ECBinary(ECDomainParameters params)
- {
- ECCurve curve = params.getCurve();
- if (!ECAlgorithms.isF2mCurve(curve))
- {
- throw new IllegalArgumentException("only binary domain is possible");
- }
-
- // We always use big-endian in parameter encoding
-
- PolynomialExtensionField field = (PolynomialExtensionField)curve.getField();
- int[] exponents = field.getMinimalPolynomial().getExponentsPresent();
- if (exponents.length == 3)
- {
- f = new DSTU4145BinaryField(exponents[2], exponents[1]);
- }
- else if (exponents.length == 5)
- {
- f = new DSTU4145BinaryField(exponents[4], exponents[1], exponents[2], exponents[3]);
- }
-
- a = new ASN1Integer(curve.getA().toBigInteger());
- b = new DEROctetString(curve.getB().getEncoded());
- n = new ASN1Integer(params.getN());
- bp = new DEROctetString(DSTU4145PointEncoder.encodePoint(params.getG()));
- }
-
- private DSTU4145ECBinary(ASN1Sequence seq)
- {
- int index = 0;
-
- if (seq.getObjectAt(index) instanceof ASN1TaggedObject)
- {
- ASN1TaggedObject taggedVersion = (ASN1TaggedObject)seq.getObjectAt(index);
- if (taggedVersion.isExplicit() && 0 == taggedVersion.getTagNo())
- {
- version = ASN1Integer.getInstance(taggedVersion.getLoadedObject()).getValue();
- index++;
- }
- else
- {
- throw new IllegalArgumentException("object parse error");
- }
- }
- f = DSTU4145BinaryField.getInstance(seq.getObjectAt(index));
- index++;
- a = ASN1Integer.getInstance(seq.getObjectAt(index));
- index++;
- b = ASN1OctetString.getInstance(seq.getObjectAt(index));
- index++;
- n = ASN1Integer.getInstance(seq.getObjectAt(index));
- index++;
- bp = ASN1OctetString.getInstance(seq.getObjectAt(index));
- }
-
- public static DSTU4145ECBinary getInstance(Object obj)
- {
- if (obj instanceof DSTU4145ECBinary)
- {
- return (DSTU4145ECBinary)obj;
- }
-
- if (obj != null)
- {
- return new DSTU4145ECBinary(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public DSTU4145BinaryField getField()
- {
- return f;
- }
-
- public BigInteger getA()
- {
- return a.getValue();
- }
-
- public byte[] getB()
- {
- return Arrays.clone(b.getOctets());
- }
-
- public BigInteger getN()
- {
- return n.getValue();
- }
-
- public byte[] getG()
- {
- return Arrays.clone(bp.getOctets());
- }
-
- /**
- * ECBinary ::= SEQUENCE {
- * version [0] EXPLICIT INTEGER DEFAULT 0,
- * f BinaryField,
- * a INTEGER (0..1),
- * b OCTET STRING,
- * n INTEGER,
- * bp OCTET STRING}
- */
- public ASN1Primitive toASN1Primitive()
- {
-
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (0 != version.compareTo(BigInteger.valueOf(0)))
- {
- v.add(new DERTaggedObject(true, 0, new ASN1Integer(version)));
- }
- v.add(f);
- v.add(a);
- v.add(b);
- v.add(n);
- v.add(bp);
-
- return new DERSequence(v);
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145NamedCurves.java b/core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145NamedCurves.java
deleted file mode 100644
index 0c02ce8b..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145NamedCurves.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package org.bouncycastle.asn1.ua;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECPoint;
-
-public class DSTU4145NamedCurves
-{
- private static final BigInteger ZERO = BigInteger.valueOf(0);
- private static final BigInteger ONE = BigInteger.valueOf(1);
-
- public static final ECDomainParameters[] params = new ECDomainParameters[10];
- static final ASN1ObjectIdentifier[] oids = new ASN1ObjectIdentifier[10];
-
- //All named curves have the following oid format: 1.2.804.2.1.1.1.1.3.1.1.2.X
- //where X is the curve number 0-9
- static final String oidBase = UAObjectIdentifiers.dstu4145le.getId() + ".2.";
-
- static
- {
- BigInteger[] n_s = new BigInteger[10];
- n_s[0] = new BigInteger("400000000000000000002BEC12BE2262D39BCF14D", 16);
- n_s[1] = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFB12EBCC7D7F29FF7701F", 16);
- n_s[2] = new BigInteger("800000000000000000000189B4E67606E3825BB2831", 16);
- n_s[3] = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFFB981960435FE5AB64236EF", 16);
- n_s[4] = new BigInteger("40000000000000000000000069A779CAC1DABC6788F7474F", 16);
- n_s[5] = new BigInteger("1000000000000000000000000000013E974E72F8A6922031D2603CFE0D7", 16);
- n_s[6] = new BigInteger("800000000000000000000000000000006759213AF182E987D3E17714907D470D", 16);
- n_s[7] = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC079C2F3825DA70D390FBBA588D4604022B7B7", 16);
- n_s[8] = new BigInteger("40000000000000000000000000000000000000000000009C300B75A3FA824F22428FD28CE8812245EF44049B2D49", 16);
- n_s[9] = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBA3175458009A8C0A724F02F81AA8A1FCBAF80D90C7A95110504CF", 16);
-
- BigInteger[] h_s = new BigInteger[10];
- h_s[0] = BigInteger.valueOf(2);
- h_s[1] = BigInteger.valueOf(2);
- h_s[2] = BigInteger.valueOf(4);
- h_s[3] = BigInteger.valueOf(2);
- h_s[4] = BigInteger.valueOf(2);
- h_s[5] = BigInteger.valueOf(2);
- h_s[6] = BigInteger.valueOf(4);
- h_s[7] = BigInteger.valueOf(2);
- h_s[8] = BigInteger.valueOf(2);
- h_s[9] = BigInteger.valueOf(2);
-
- ECCurve.F2m[] curves = new ECCurve.F2m[10];
- curves[0] = new ECCurve.F2m(163, 3, 6, 7, ONE, new BigInteger("5FF6108462A2DC8210AB403925E638A19C1455D21", 16), n_s[0], h_s[0]);
- curves[1] = new ECCurve.F2m(167, 6, ONE, new BigInteger("6EE3CEEB230811759F20518A0930F1A4315A827DAC", 16), n_s[1], h_s[1]);
- curves[2] = new ECCurve.F2m(173, 1, 2, 10, ZERO, new BigInteger("108576C80499DB2FC16EDDF6853BBB278F6B6FB437D9", 16), n_s[2], h_s[2]);
- curves[3] = new ECCurve.F2m(179, 1, 2, 4, ONE, new BigInteger("4A6E0856526436F2F88DD07A341E32D04184572BEB710", 16), n_s[3], h_s[3]);
- curves[4] = new ECCurve.F2m(191, 9, ONE, new BigInteger("7BC86E2102902EC4D5890E8B6B4981ff27E0482750FEFC03", 16), n_s[4], h_s[4]);
- curves[5] = new ECCurve.F2m(233, 1, 4, 9, ONE, new BigInteger("06973B15095675534C7CF7E64A21BD54EF5DD3B8A0326AA936ECE454D2C", 16), n_s[5], h_s[5]);
- curves[6] = new ECCurve.F2m(257, 12, ZERO, new BigInteger("1CEF494720115657E18F938D7A7942394FF9425C1458C57861F9EEA6ADBE3BE10", 16), n_s[6], h_s[6]);
- curves[7] = new ECCurve.F2m(307, 2, 4, 8, ONE, new BigInteger("393C7F7D53666B5054B5E6C6D3DE94F4296C0C599E2E2E241050DF18B6090BDC90186904968BB", 16), n_s[7], h_s[7]);
- curves[8] = new ECCurve.F2m(367, 21, ONE, new BigInteger("43FC8AD242B0B7A6F3D1627AD5654447556B47BF6AA4A64B0C2AFE42CADAB8F93D92394C79A79755437B56995136", 16), n_s[8], h_s[8]);
- curves[9] = new ECCurve.F2m(431, 1, 3, 5, ONE, new BigInteger("03CE10490F6A708FC26DFE8C3D27C4F94E690134D5BFF988D8D28AAEAEDE975936C66BAC536B18AE2DC312CA493117DAA469C640CAF3", 16), n_s[9], h_s[9]);
-
- ECPoint[] points = new ECPoint[10];
- 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));
-
- for (int i = 0; i < params.length; i++)
- {
- params[i] = new ECDomainParameters(curves[i], points[i], n_s[i], h_s[i]);
- }
-
- for (int i = 0; i < oids.length; i++)
- {
- oids[i] = new ASN1ObjectIdentifier(oidBase + i);
- }
- }
-
- /**
- * All named curves have the following oid format: 1.2.804.2.1.1.1.1.3.1.1.2.X
- * where X is the curve number 0-9
- */
- public static ASN1ObjectIdentifier[] getOIDs()
- {
- return oids;
- }
-
- /**
- * All named curves have the following oid format: 1.2.804.2.1.1.1.1.3.1.1.2.X
- * where X is the curve number 0-9
- */
- public static ECDomainParameters getByOID(ASN1ObjectIdentifier oid)
- {
- String oidStr = oid.getId();
- if (oidStr.startsWith(oidBase))
- {
- int index = Integer.parseInt(oidStr.substring(oidStr.length() - 1));
- return params[index];
- }
- return null;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145Params.java b/core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145Params.java
deleted file mode 100644
index c425d73b..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145Params.java
+++ /dev/null
@@ -1,121 +0,0 @@
-package org.bouncycastle.asn1.ua;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-
-public class DSTU4145Params
- extends ASN1Object
-{
- private static final byte DEFAULT_DKE[] = {
- (byte)0xa9, (byte)0xd6, (byte)0xeb, 0x45, (byte)0xf1, 0x3c, 0x70, (byte)0x82,
- (byte)0x80, (byte)0xc4, (byte)0x96, 0x7b, 0x23, 0x1f, 0x5e, (byte)0xad,
- (byte)0xf6, 0x58, (byte)0xeb, (byte)0xa4, (byte)0xc0, 0x37, 0x29, 0x1d,
- 0x38, (byte)0xd9, 0x6b, (byte)0xf0, 0x25, (byte)0xca, 0x4e, 0x17,
- (byte)0xf8, (byte)0xe9, 0x72, 0x0d, (byte)0xc6, 0x15, (byte)0xb4, 0x3a,
- 0x28, (byte)0x97, 0x5f, 0x0b, (byte)0xc1, (byte)0xde, (byte)0xa3, 0x64,
- 0x38, (byte)0xb5, 0x64, (byte)0xea, 0x2c, 0x17, (byte)0x9f, (byte)0xd0,
- 0x12, 0x3e, 0x6d, (byte)0xb8, (byte)0xfa, (byte)0xc5, 0x79, 0x04};
-
-
- private ASN1ObjectIdentifier namedCurve;
- private DSTU4145ECBinary ecbinary;
- private byte[] dke = DEFAULT_DKE;
-
- public DSTU4145Params(ASN1ObjectIdentifier namedCurve)
- {
- this.namedCurve = namedCurve;
- }
-
- public DSTU4145Params(DSTU4145ECBinary ecbinary)
- {
- this.ecbinary = ecbinary;
- }
-
- public boolean isNamedCurve()
- {
- return namedCurve != null;
- }
-
- public DSTU4145ECBinary getECBinary()
- {
- return ecbinary;
- }
-
- public byte[] getDKE()
- {
- return dke;
- }
-
- public static byte[] getDefaultDKE()
- {
- return DEFAULT_DKE;
- }
-
- public ASN1ObjectIdentifier getNamedCurve()
- {
- return namedCurve;
- }
-
- public static DSTU4145Params getInstance(Object obj)
- {
- if (obj instanceof DSTU4145Params)
- {
- return (DSTU4145Params)obj;
- }
-
- if (obj != null)
- {
- ASN1Sequence seq = ASN1Sequence.getInstance(obj);
- DSTU4145Params params;
-
- if (seq.getObjectAt(0) instanceof ASN1ObjectIdentifier)
- {
- params = new DSTU4145Params(ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0)));
- }
- else
- {
- params = new DSTU4145Params(DSTU4145ECBinary.getInstance(seq.getObjectAt(0)));
- }
-
- if (seq.size() == 2)
- {
- params.dke = ASN1OctetString.getInstance(seq.getObjectAt(1)).getOctets();
- if (params.dke.length != DSTU4145Params.DEFAULT_DKE.length)
- {
- throw new IllegalArgumentException("object parse error");
- }
- }
-
- return params;
- }
-
- throw new IllegalArgumentException("object parse error");
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (namedCurve != null)
- {
- v.add(namedCurve);
- }
- else
- {
- v.add(ecbinary);
- }
-
- if (!org.bouncycastle.util.Arrays.areEqual(dke, DEFAULT_DKE))
- {
- v.add(new DEROctetString(dke));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145PointEncoder.java b/core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145PointEncoder.java
deleted file mode 100644
index 3405130e..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145PointEncoder.java
+++ /dev/null
@@ -1,154 +0,0 @@
-package org.bouncycastle.asn1.ua;
-
-import java.math.BigInteger;
-import java.util.Random;
-
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECPoint;
-
-/**
- * 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 ECFieldElement trace(ECFieldElement fe)
- {
- ECFieldElement t = fe;
- for (int i = 1; i < fe.getFieldSize(); ++i)
- {
- t = t.square().add(fe);
- }
- return t;
- }
-
- /**
- * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
- * D.1.6) The other solution is <code>z + 1</code>.
- *
- * @param beta The value to solve the quadratic equation for.
- * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
- * <code>null</code> if no solution exists.
- */
- private static ECFieldElement solveQuadraticEquation(ECCurve curve, ECFieldElement beta)
- {
- if (beta.isZero())
- {
- return beta;
- }
-
- ECFieldElement zeroElement = curve.fromBigInteger(ECConstants.ZERO);
-
- ECFieldElement z = null;
- ECFieldElement gamma = null;
-
- Random rand = new Random();
- int m = beta.getFieldSize();
- do
- {
- ECFieldElement t = curve.fromBigInteger(new BigInteger(m, rand));
- z = zeroElement;
- ECFieldElement w = beta;
- for (int i = 1; i <= m - 1; i++)
- {
- ECFieldElement w2 = w.square();
- z = z.square().add(w2.multiply(t));
- w = w2.add(beta);
- }
- if (!w.isZero())
- {
- return null;
- }
- gamma = z.square().add(z);
- }
- while (gamma.isZero());
-
- return z;
- }
-
- public static byte[] encodePoint(ECPoint Q)
- {
- /*if (!Q.isCompressed())
- Q=new ECPoint.F2m(Q.getCurve(),Q.getX(),Q.getY(),true);
-
- byte[] bytes=Q.getEncoded();
-
- if (bytes[0]==0x02)
- bytes[bytes.length-1]&=0xFE;
- else if (bytes[0]==0x02)
- bytes[bytes.length-1]|=0x01;
-
- return Arrays.copyOfRange(bytes, 1, bytes.length);*/
-
- Q = Q.normalize();
-
- ECFieldElement x = Q.getAffineXCoord();
-
- byte[] bytes = x.getEncoded();
-
- if (!x.isZero())
- {
- ECFieldElement z = Q.getAffineYCoord().divide(x);
- if (trace(z).isOne())
- {
- bytes[bytes.length - 1] |= 0x01;
- }
- else
- {
- bytes[bytes.length - 1] &= 0xFE;
- }
- }
-
- return bytes;
- }
-
- public static ECPoint decodePoint(ECCurve curve, byte[] bytes)
- {
- /*byte[] bp_enc=new byte[bytes.length+1];
- if (0==(bytes[bytes.length-1]&0x1))
- bp_enc[0]=0x02;
- else
- bp_enc[0]=0x03;
- System.arraycopy(bytes, 0, bp_enc, 1, bytes.length);
- if (!trace(curve.fromBigInteger(new BigInteger(1, bytes))).equals(curve.getA().toBigInteger()))
- bp_enc[bp_enc.length-1]^=0x01;
-
- return curve.decodePoint(bp_enc);*/
-
- ECFieldElement k = curve.fromBigInteger(BigInteger.valueOf(bytes[bytes.length - 1] & 0x1));
-
- ECFieldElement xp = curve.fromBigInteger(new BigInteger(1, bytes));
- if (!trace(xp).equals(curve.getA()))
- {
- xp = xp.addOne();
- }
-
- ECFieldElement yp = null;
- if (xp.isZero())
- {
- yp = curve.getB().sqrt();
- }
- else
- {
- ECFieldElement beta = xp.square().invert().multiply(curve.getB()).add(curve.getA()).add(xp);
- ECFieldElement z = solveQuadraticEquation(curve, beta);
- if (z != null)
- {
- if (!trace(z).equals(k))
- {
- z = z.addOne();
- }
- yp = xp.multiply(z);
- }
- }
-
- if (yp == null)
- {
- throw new IllegalArgumentException("Invalid point compression");
- }
-
- return curve.createPoint(xp.toBigInteger(), yp.toBigInteger());
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145PublicKey.java b/core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145PublicKey.java
deleted file mode 100644
index 769eff66..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ua/DSTU4145PublicKey.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.bouncycastle.asn1.ua;
-
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.math.ec.ECPoint;
-
-public class DSTU4145PublicKey
- extends ASN1Object
-{
-
- private ASN1OctetString pubKey;
-
- public DSTU4145PublicKey(ECPoint pubKey)
- {
- // We always use big-endian in parameter encoding
- this.pubKey = new DEROctetString(DSTU4145PointEncoder.encodePoint(pubKey));
- }
-
- private DSTU4145PublicKey(ASN1OctetString ocStr)
- {
- pubKey = ocStr;
- }
-
- public static DSTU4145PublicKey getInstance(Object obj)
- {
- if (obj instanceof DSTU4145PublicKey)
- {
- return (DSTU4145PublicKey)obj;
- }
-
- if (obj != null)
- {
- return new DSTU4145PublicKey(ASN1OctetString.getInstance(obj));
- }
-
- return null;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return pubKey;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/ua/UAObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/ua/UAObjectIdentifiers.java
deleted file mode 100644
index ccdb34ec..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/ua/UAObjectIdentifiers.java
+++ /dev/null
@@ -1,23 +0,0 @@
-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
-{
- /** Base OID: 1.2.804.2.1.1.1 */
- static final ASN1ObjectIdentifier UaOid = new ASN1ObjectIdentifier("1.2.804.2.1.1.1");
-
- /** 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/core/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java b/core/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java
deleted file mode 100644
index 8a454f27..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java
+++ /dev/null
@@ -1,403 +0,0 @@
-package org.bouncycastle.asn1.util;
-
-import java.io.IOException;
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Boolean;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Enumerated;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.ASN1UTCTime;
-import org.bouncycastle.asn1.BERApplicationSpecific;
-import org.bouncycastle.asn1.BEROctetString;
-import org.bouncycastle.asn1.BERSequence;
-import org.bouncycastle.asn1.BERSet;
-import org.bouncycastle.asn1.BERTaggedObject;
-import org.bouncycastle.asn1.BERTags;
-import org.bouncycastle.asn1.DERApplicationSpecific;
-import org.bouncycastle.asn1.DERBMPString;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERExternal;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.DERPrintableString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERT61String;
-import org.bouncycastle.asn1.DERUTF8String;
-import org.bouncycastle.asn1.DERVisibleString;
-import org.bouncycastle.util.encoders.Hex;
-
-public class ASN1Dump
-{
- private static final String TAB = " ";
- private static final int SAMPLE_SIZE = 32;
-
- /**
- * dump a DER object as a formatted string with indentation
- *
- * @param obj the ASN1Primitive to be dumped out.
- */
- static void _dumpAsString(
- String indent,
- boolean verbose,
- ASN1Primitive obj,
- StringBuffer buf)
- {
- String nl = System.getProperty("line.separator");
- if (obj instanceof ASN1Sequence)
- {
- Enumeration e = ((ASN1Sequence)obj).getObjects();
- String tab = indent + TAB;
-
- buf.append(indent);
- if (obj instanceof BERSequence)
- {
- buf.append("BER Sequence");
- }
- else if (obj instanceof DERSequence)
- {
- buf.append("DER Sequence");
- }
- else
- {
- buf.append("Sequence");
- }
-
- buf.append(nl);
-
- while (e.hasMoreElements())
- {
- Object o = e.nextElement();
-
- if (o == null || o.equals(DERNull.INSTANCE))
- {
- buf.append(tab);
- buf.append("NULL");
- buf.append(nl);
- }
- else if (o instanceof ASN1Primitive)
- {
- _dumpAsString(tab, verbose, (ASN1Primitive)o, buf);
- }
- else
- {
- _dumpAsString(tab, verbose, ((ASN1Encodable)o).toASN1Primitive(), buf);
- }
- }
- }
- else if (obj instanceof ASN1TaggedObject)
- {
- String tab = indent + TAB;
-
- buf.append(indent);
- if (obj instanceof BERTaggedObject)
- {
- buf.append("BER Tagged [");
- }
- else
- {
- buf.append("Tagged [");
- }
-
- ASN1TaggedObject o = (ASN1TaggedObject)obj;
-
- buf.append(Integer.toString(o.getTagNo()));
- buf.append(']');
-
- if (!o.isExplicit())
- {
- buf.append(" IMPLICIT ");
- }
-
- buf.append(nl);
-
- if (o.isEmpty())
- {
- buf.append(tab);
- buf.append("EMPTY");
- buf.append(nl);
- }
- else
- {
- _dumpAsString(tab, verbose, o.getObject(), buf);
- }
- }
- else if (obj instanceof ASN1Set)
- {
- Enumeration e = ((ASN1Set)obj).getObjects();
- String tab = indent + TAB;
-
- buf.append(indent);
-
- if (obj instanceof BERSet)
- {
- buf.append("BER Set");
- }
- else
- {
- buf.append("DER Set");
- }
-
- buf.append(nl);
-
- while (e.hasMoreElements())
- {
- Object o = e.nextElement();
-
- if (o == null)
- {
- buf.append(tab);
- buf.append("NULL");
- buf.append(nl);
- }
- else if (o instanceof ASN1Primitive)
- {
- _dumpAsString(tab, verbose, (ASN1Primitive)o, buf);
- }
- else
- {
- _dumpAsString(tab, verbose, ((ASN1Encodable)o).toASN1Primitive(), buf);
- }
- }
- }
- else if (obj instanceof ASN1OctetString)
- {
- ASN1OctetString oct = (ASN1OctetString)obj;
-
- if (obj instanceof BEROctetString)
- {
- buf.append(indent + "BER Constructed Octet String" + "[" + oct.getOctets().length + "] ");
- }
- else
- {
- buf.append(indent + "DER Octet String" + "[" + oct.getOctets().length + "] ");
- }
- if (verbose)
- {
- buf.append(dumpBinaryDataAsString(indent, oct.getOctets()));
- }
- else
- {
- buf.append(nl);
- }
- }
- else if (obj instanceof ASN1ObjectIdentifier)
- {
- buf.append(indent + "ObjectIdentifier(" + ((ASN1ObjectIdentifier)obj).getId() + ")" + nl);
- }
- else if (obj instanceof ASN1Boolean)
- {
- buf.append(indent + "Boolean(" + ((ASN1Boolean)obj).isTrue() + ")" + nl);
- }
- else if (obj instanceof ASN1Integer)
- {
- buf.append(indent + "Integer(" + ((ASN1Integer)obj).getValue() + ")" + nl);
- }
- else if (obj instanceof DERBitString)
- {
- DERBitString bt = (DERBitString)obj;
- buf.append(indent + "DER Bit String" + "[" + bt.getBytes().length + ", " + bt.getPadBits() + "] ");
- if (verbose)
- {
- buf.append(dumpBinaryDataAsString(indent, bt.getBytes()));
- }
- else
- {
- buf.append(nl);
- }
- }
- else if (obj instanceof DERIA5String)
- {
- buf.append(indent + "IA5String(" + ((DERIA5String)obj).getString() + ") " + nl);
- }
- else if (obj instanceof DERUTF8String)
- {
- buf.append(indent + "UTF8String(" + ((DERUTF8String)obj).getString() + ") " + nl);
- }
- else if (obj instanceof DERPrintableString)
- {
- buf.append(indent + "PrintableString(" + ((DERPrintableString)obj).getString() + ") " + nl);
- }
- else if (obj instanceof DERVisibleString)
- {
- buf.append(indent + "VisibleString(" + ((DERVisibleString)obj).getString() + ") " + nl);
- }
- else if (obj instanceof DERBMPString)
- {
- buf.append(indent + "BMPString(" + ((DERBMPString)obj).getString() + ") " + nl);
- }
- else if (obj instanceof DERT61String)
- {
- buf.append(indent + "T61String(" + ((DERT61String)obj).getString() + ") " + nl);
- }
- else if (obj instanceof ASN1UTCTime)
- {
- buf.append(indent + "UTCTime(" + ((ASN1UTCTime)obj).getTime() + ") " + nl);
- }
- else if (obj instanceof ASN1GeneralizedTime)
- {
- buf.append(indent + "GeneralizedTime(" + ((ASN1GeneralizedTime)obj).getTime() + ") " + nl);
- }
- else if (obj instanceof BERApplicationSpecific)
- {
- buf.append(outputApplicationSpecific("BER", indent, verbose, obj, nl));
- }
- else if (obj instanceof DERApplicationSpecific)
- {
- buf.append(outputApplicationSpecific("DER", indent, verbose, obj, nl));
- }
- else if (obj instanceof ASN1Enumerated)
- {
- ASN1Enumerated en = (ASN1Enumerated) obj;
- buf.append(indent + "DER Enumerated(" + en.getValue() + ")" + nl);
- }
- else if (obj instanceof DERExternal)
- {
- DERExternal ext = (DERExternal) obj;
- buf.append(indent + "External " + nl);
- String tab = indent + TAB;
- if (ext.getDirectReference() != null)
- {
- buf.append(tab + "Direct Reference: " + ext.getDirectReference().getId() + nl);
- }
- if (ext.getIndirectReference() != null)
- {
- buf.append(tab + "Indirect Reference: " + ext.getIndirectReference().toString() + nl);
- }
- if (ext.getDataValueDescriptor() != null)
- {
- _dumpAsString(tab, verbose, ext.getDataValueDescriptor(), buf);
- }
- buf.append(tab + "Encoding: " + ext.getEncoding() + nl);
- _dumpAsString(tab, verbose, ext.getExternalContent(), buf);
- }
- else
- {
- buf.append(indent + obj.toString() + nl);
- }
- }
-
- private static String outputApplicationSpecific(String type, String indent, boolean verbose, ASN1Primitive obj, String nl)
- {
- DERApplicationSpecific app = (DERApplicationSpecific)obj;
- StringBuffer buf = new StringBuffer();
-
- if (app.isConstructed())
- {
- try
- {
- ASN1Sequence s = ASN1Sequence.getInstance(app.getObject(BERTags.SEQUENCE));
- buf.append(indent + type + " ApplicationSpecific[" + app.getApplicationTag() + "]" + nl);
- for (Enumeration e = s.getObjects(); e.hasMoreElements();)
- {
- _dumpAsString(indent + TAB, verbose, (ASN1Primitive)e.nextElement(), buf);
- }
- }
- catch (IOException e)
- {
- buf.append(e);
- }
- return buf.toString();
- }
-
- return indent + type + " ApplicationSpecific[" + app.getApplicationTag() + "] (" + new String(Hex.encode(app.getContents())) + ")" + nl;
- }
-
- /**
- * dump out a DER object as a formatted string, in non-verbose mode.
- *
- * @param obj the ASN1Primitive to be dumped out.
- * @return the resulting string.
- */
- public static String dumpAsString(
- Object obj)
- {
- return dumpAsString(obj, false);
- }
-
- /**
- * Dump out the object as a string.
- *
- * @param obj the object to be dumped
- * @param verbose if true, dump out the contents of octet and bit strings.
- * @return the resulting string.
- */
- public static String dumpAsString(
- Object obj,
- boolean verbose)
- {
- StringBuffer buf = new StringBuffer();
-
- if (obj instanceof ASN1Primitive)
- {
- _dumpAsString("", verbose, (ASN1Primitive)obj, buf);
- }
- else if (obj instanceof ASN1Encodable)
- {
- _dumpAsString("", verbose, ((ASN1Encodable)obj).toASN1Primitive(), buf);
- }
- else
- {
- return "unknown object type " + obj.toString();
- }
-
- return buf.toString();
- }
-
- private static String dumpBinaryDataAsString(String indent, byte[] bytes)
- {
- String nl = System.getProperty("line.separator");
- StringBuffer buf = new StringBuffer();
-
- indent += TAB;
-
- buf.append(nl);
- for (int i = 0; i < bytes.length; i += SAMPLE_SIZE)
- {
- if (bytes.length - i > SAMPLE_SIZE)
- {
- buf.append(indent);
- buf.append(new String(Hex.encode(bytes, i, SAMPLE_SIZE)));
- buf.append(TAB);
- buf.append(calculateAscString(bytes, i, SAMPLE_SIZE));
- buf.append(nl);
- }
- else
- {
- buf.append(indent);
- buf.append(new String(Hex.encode(bytes, i, bytes.length - i)));
- for (int j = bytes.length - i; j != SAMPLE_SIZE; j++)
- {
- buf.append(" ");
- }
- buf.append(TAB);
- buf.append(calculateAscString(bytes, i, bytes.length - i));
- buf.append(nl);
- }
- }
-
- return buf.toString();
- }
-
- private static String calculateAscString(byte[] bytes, int off, int len)
- {
- StringBuffer buf = new StringBuffer();
-
- for (int i = off; i != off + len; i++)
- {
- if (bytes[i] >= ' ' && bytes[i] <= '~')
- {
- buf.append((char)bytes[i]);
- }
- }
-
- return buf.toString();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/util/DERDump.java b/core/src/main/java/org/bouncycastle/asn1/util/DERDump.java
deleted file mode 100644
index 78875ff2..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/util/DERDump.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.bouncycastle.asn1.util;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Primitive;
-
-/**
- * @deprecated use ASN1Dump.
- */
-public class DERDump
- extends ASN1Dump
-{
- /**
- * dump out a DER object as a formatted string
- *
- * @param obj the ASN1Primitive to be dumped out.
- */
- public static String dumpAsString(
- ASN1Primitive obj)
- {
- StringBuffer buf = new StringBuffer();
-
- _dumpAsString("", false, obj, buf);
-
- return buf.toString();
- }
-
- /**
- * dump out a DER object as a formatted string
- *
- * @param obj the ASN1Primitive to be dumped out.
- */
- public static String dumpAsString(
- ASN1Encodable obj)
- {
- StringBuffer buf = new StringBuffer();
-
- _dumpAsString("", false, obj.toASN1Primitive(), buf);
-
- return buf.toString();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/util/Dump.java b/core/src/main/java/org/bouncycastle/asn1/util/Dump.java
deleted file mode 100644
index 27a37f34..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/util/Dump.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.bouncycastle.asn1.util;
-
-import java.io.FileInputStream;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-
-public class Dump
-{
- public static void main(
- String args[])
- throws Exception
- {
- FileInputStream fIn = new FileInputStream(args[0]);
- ASN1InputStream bIn = new ASN1InputStream(fIn);
- Object obj = null;
-
- while ((obj = bIn.readObject()) != null)
- {
- System.out.println(ASN1Dump.dumpAsString(obj));
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x500/AttributeTypeAndValue.java b/core/src/main/java/org/bouncycastle/asn1/x500/AttributeTypeAndValue.java
deleted file mode 100644
index 7f283f97..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x500/AttributeTypeAndValue.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.bouncycastle.asn1.x500;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-public class AttributeTypeAndValue
- extends ASN1Object
-{
- private ASN1ObjectIdentifier type;
- private ASN1Encodable value;
-
- private AttributeTypeAndValue(ASN1Sequence seq)
- {
- type = (ASN1ObjectIdentifier)seq.getObjectAt(0);
- value = (ASN1Encodable)seq.getObjectAt(1);
- }
-
- public static AttributeTypeAndValue getInstance(Object o)
- {
- if (o instanceof AttributeTypeAndValue)
- {
- return (AttributeTypeAndValue)o;
- }
- else if (o != null)
- {
- return new AttributeTypeAndValue(ASN1Sequence.getInstance(o));
- }
-
- throw new IllegalArgumentException("null value in getInstance()");
- }
-
- public AttributeTypeAndValue(
- ASN1ObjectIdentifier type,
- ASN1Encodable value)
- {
- this.type = type;
- this.value = value;
- }
-
- public ASN1ObjectIdentifier getType()
- {
- return type;
- }
-
- public ASN1Encodable getValue()
- {
- return value;
- }
-
- /**
- * <pre>
- * AttributeTypeAndValue ::= SEQUENCE {
- * type OBJECT IDENTIFIER,
- * value ANY DEFINED BY type }
- * </pre>
- * @return a basic ASN.1 object representation.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(type);
- v.add(value);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x500/DirectoryString.java b/core/src/main/java/org/bouncycastle/asn1/x500/DirectoryString.java
deleted file mode 100644
index cf7563e2..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x500/DirectoryString.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package org.bouncycastle.asn1.x500;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1String;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBMPString;
-import org.bouncycastle.asn1.DERPrintableString;
-import org.bouncycastle.asn1.DERT61String;
-import org.bouncycastle.asn1.DERUTF8String;
-import org.bouncycastle.asn1.DERUniversalString;
-
-public class DirectoryString
- extends ASN1Object
- implements ASN1Choice, ASN1String
-{
- private ASN1String string;
-
- public static DirectoryString getInstance(Object o)
- {
- if (o == null || o instanceof DirectoryString)
- {
- return (DirectoryString)o;
- }
-
- if (o instanceof DERT61String)
- {
- return new DirectoryString((DERT61String)o);
- }
-
- if (o instanceof DERPrintableString)
- {
- return new DirectoryString((DERPrintableString)o);
- }
-
- if (o instanceof DERUniversalString)
- {
- return new DirectoryString((DERUniversalString)o);
- }
-
- if (o instanceof DERUTF8String)
- {
- return new DirectoryString((DERUTF8String)o);
- }
-
- if (o instanceof DERBMPString)
- {
- return new DirectoryString((DERBMPString)o);
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + o.getClass().getName());
- }
-
- public static DirectoryString getInstance(ASN1TaggedObject o, boolean explicit)
- {
- if (!explicit)
- {
- throw new IllegalArgumentException("choice item must be explicitly tagged");
- }
-
- return getInstance(o.getObject());
- }
-
- private DirectoryString(
- DERT61String string)
- {
- this.string = string;
- }
-
- private DirectoryString(
- DERPrintableString string)
- {
- this.string = string;
- }
-
- private DirectoryString(
- DERUniversalString string)
- {
- this.string = string;
- }
-
- private DirectoryString(
- DERUTF8String string)
- {
- this.string = string;
- }
-
- private DirectoryString(
- DERBMPString string)
- {
- this.string = string;
- }
-
- public DirectoryString(String string)
- {
- this.string = new DERUTF8String(string);
- }
-
- public String getString()
- {
- return string.getString();
- }
-
- public String toString()
- {
- return string.getString();
- }
-
- /**
- * <pre>
- * DirectoryString ::= CHOICE {
- * teletexString TeletexString (SIZE (1..MAX)),
- * printableString PrintableString (SIZE (1..MAX)),
- * universalString UniversalString (SIZE (1..MAX)),
- * utf8String UTF8String (SIZE (1..MAX)),
- * bmpString BMPString (SIZE (1..MAX)) }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- return ((ASN1Encodable)string).toASN1Primitive();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x500/RDN.java b/core/src/main/java/org/bouncycastle/asn1/x500/RDN.java
deleted file mode 100644
index f51c2619..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x500/RDN.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package org.bouncycastle.asn1.x500;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERSet;
-
-public class RDN
- extends ASN1Object
-{
- private ASN1Set values;
-
- private RDN(ASN1Set values)
- {
- this.values = values;
- }
-
- public static RDN getInstance(Object obj)
- {
- if (obj instanceof RDN)
- {
- return (RDN)obj;
- }
- else if (obj != null)
- {
- return new RDN(ASN1Set.getInstance(obj));
- }
-
- return null;
- }
-
- /**
- * Create a single valued RDN.
- *
- * @param oid RDN type.
- * @param value RDN value.
- */
- public RDN(ASN1ObjectIdentifier oid, ASN1Encodable value)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(oid);
- v.add(value);
-
- this.values = new DERSet(new DERSequence(v));
- }
-
- public RDN(AttributeTypeAndValue attrTAndV)
- {
- this.values = new DERSet(attrTAndV);
- }
-
- /**
- * Create a multi-valued RDN.
- *
- * @param aAndVs attribute type/value pairs making up the RDN
- */
- public RDN(AttributeTypeAndValue[] aAndVs)
- {
- this.values = new DERSet(aAndVs);
- }
-
- public boolean isMultiValued()
- {
- return this.values.size() > 1;
- }
-
- /**
- * Return the number of AttributeTypeAndValue objects in this RDN,
- *
- * @return size of RDN, greater than 1 if multi-valued.
- */
- public int size()
- {
- return this.values.size();
- }
-
- public AttributeTypeAndValue getFirst()
- {
- if (this.values.size() == 0)
- {
- return null;
- }
-
- return AttributeTypeAndValue.getInstance(this.values.getObjectAt(0));
- }
-
- public AttributeTypeAndValue[] getTypesAndValues()
- {
- AttributeTypeAndValue[] tmp = new AttributeTypeAndValue[values.size()];
-
- for (int i = 0; i != tmp.length; i++)
- {
- tmp[i] = AttributeTypeAndValue.getInstance(values.getObjectAt(i));
- }
-
- return tmp;
- }
-
- /**
- * <pre>
- * RelativeDistinguishedName ::=
- * SET OF AttributeTypeAndValue
-
- * AttributeTypeAndValue ::= SEQUENCE {
- * type AttributeType,
- * value AttributeValue }
- * </pre>
- * @return this object as an ASN1Primitive type
- */
- public ASN1Primitive toASN1Primitive()
- {
- return values;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x500/X500Name.java b/core/src/main/java/org/bouncycastle/asn1/x500/X500Name.java
deleted file mode 100644
index 50e57c51..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x500/X500Name.java
+++ /dev/null
@@ -1,326 +0,0 @@
-package org.bouncycastle.asn1.x500;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x500.style.BCStyle;
-
-/**
- * <pre>
- * Name ::= CHOICE {
- * RDNSequence }
- *
- * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
- *
- * RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
- *
- * AttributeTypeAndValue ::= SEQUENCE {
- * type OBJECT IDENTIFIER,
- * value ANY }
- * </pre>
- */
-public class X500Name
- extends ASN1Object
- implements ASN1Choice
-{
- private static X500NameStyle defaultStyle = BCStyle.INSTANCE;
-
- private boolean isHashCodeCalculated;
- private int hashCodeValue;
-
- private X500NameStyle style;
- private RDN[] rdns;
-
- public X500Name(X500NameStyle style, X500Name name)
- {
- this.rdns = name.rdns;
- this.style = style;
- }
-
- /**
- * Return a X500Name based on the passed in tagged object.
- *
- * @param obj tag object holding name.
- * @param explicit true if explicitly tagged false otherwise.
- * @return the X500Name
- */
- public static X500Name getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- // must be true as choice item
- return getInstance(ASN1Sequence.getInstance(obj, true));
- }
-
- public static X500Name getInstance(
- Object obj)
- {
- if (obj instanceof X500Name)
- {
- return (X500Name)obj;
- }
- else if (obj != null)
- {
- return new X500Name(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public static X500Name getInstance(
- X500NameStyle style,
- Object obj)
- {
- if (obj instanceof X500Name)
- {
- return getInstance(style, ((X500Name)obj).toASN1Primitive());
- }
- else if (obj != null)
- {
- return new X500Name(style, ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- /**
- * Constructor from ASN1Sequence
- *
- * the principal will be a list of constructed sets, each containing an (OID, String) pair.
- */
- private X500Name(
- ASN1Sequence seq)
- {
- this(defaultStyle, seq);
- }
-
- private X500Name(
- X500NameStyle style,
- ASN1Sequence seq)
- {
- this.style = style;
- this.rdns = new RDN[seq.size()];
-
- int index = 0;
-
- for (Enumeration e = seq.getObjects(); e.hasMoreElements();)
- {
- rdns[index++] = RDN.getInstance(e.nextElement());
- }
- }
-
- public X500Name(
- RDN[] rDNs)
- {
- this(defaultStyle, rDNs);
- }
-
- public X500Name(
- X500NameStyle style,
- RDN[] rDNs)
- {
- this.rdns = rDNs;
- this.style = style;
- }
-
- public X500Name(
- String dirName)
- {
- this(defaultStyle, dirName);
- }
-
- public X500Name(
- X500NameStyle style,
- String dirName)
- {
- this(style.fromString(dirName));
-
- this.style = style;
- }
-
- /**
- * return an array of RDNs in structure order.
- *
- * @return an array of RDN objects.
- */
- public RDN[] getRDNs()
- {
- RDN[] tmp = new RDN[this.rdns.length];
-
- System.arraycopy(rdns, 0, tmp, 0, tmp.length);
-
- return tmp;
- }
-
- /**
- * return an array of OIDs contained in the attribute type of each RDN in structure order.
- *
- * @return an array, possibly zero length, of ASN1ObjectIdentifiers objects.
- */
- public ASN1ObjectIdentifier[] getAttributeTypes()
- {
- int count = 0;
-
- for (int i = 0; i != rdns.length; i++)
- {
- RDN rdn = rdns[i];
-
- count += rdn.size();
- }
-
- ASN1ObjectIdentifier[] res = new ASN1ObjectIdentifier[count];
-
- count = 0;
-
- for (int i = 0; i != rdns.length; i++)
- {
- RDN rdn = rdns[i];
-
- if (rdn.isMultiValued())
- {
- AttributeTypeAndValue[] attr = rdn.getTypesAndValues();
- for (int j = 0; j != attr.length; j++)
- {
- res[count++] = attr[j].getType();
- }
- }
- else if (rdn.size() != 0)
- {
- res[count++] = rdn.getFirst().getType();
- }
- }
-
- return res;
- }
-
- /**
- * return an array of RDNs containing the attribute type given by OID in structure order.
- *
- * @param attributeType the type OID we are looking for.
- * @return an array, possibly zero length, of RDN objects.
- */
- public RDN[] getRDNs(ASN1ObjectIdentifier attributeType)
- {
- RDN[] res = new RDN[rdns.length];
- int count = 0;
-
- for (int i = 0; i != rdns.length; i++)
- {
- RDN rdn = rdns[i];
-
- if (rdn.isMultiValued())
- {
- AttributeTypeAndValue[] attr = rdn.getTypesAndValues();
- for (int j = 0; j != attr.length; j++)
- {
- if (attr[j].getType().equals(attributeType))
- {
- res[count++] = rdn;
- break;
- }
- }
- }
- else
- {
- if (rdn.getFirst().getType().equals(attributeType))
- {
- res[count++] = rdn;
- }
- }
- }
-
- RDN[] tmp = new RDN[count];
-
- System.arraycopy(res, 0, tmp, 0, tmp.length);
-
- return tmp;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return new DERSequence(rdns);
- }
-
- public int hashCode()
- {
- if (isHashCodeCalculated)
- {
- return hashCodeValue;
- }
-
- isHashCodeCalculated = true;
-
- hashCodeValue = style.calculateHashCode(this);
-
- return hashCodeValue;
- }
-
- /**
- * test for equality - note: case is ignored.
- */
- public boolean equals(Object obj)
- {
- if (obj == this)
- {
- return true;
- }
-
- if (!(obj instanceof X500Name || obj instanceof ASN1Sequence))
- {
- return false;
- }
-
- ASN1Primitive derO = ((ASN1Encodable)obj).toASN1Primitive();
-
- if (this.toASN1Primitive().equals(derO))
- {
- return true;
- }
-
- try
- {
- return style.areEqual(this, new X500Name(ASN1Sequence.getInstance(((ASN1Encodable)obj).toASN1Primitive())));
- }
- catch (Exception e)
- {
- return false;
- }
- }
-
- public String toString()
- {
- return style.toString(this);
- }
-
- /**
- * Set the default style for X500Name construction.
- *
- * @param style an X500NameStyle
- */
- public static void setDefaultStyle(X500NameStyle style)
- {
- if (style == null)
- {
- throw new NullPointerException("cannot set style to null");
- }
-
- defaultStyle = style;
- }
-
- /**
- * Return the current default style.
- *
- * @return default style for X500Name construction.
- */
- public static X500NameStyle getDefaultStyle()
- {
- return defaultStyle;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x500/X500NameBuilder.java b/core/src/main/java/org/bouncycastle/asn1/x500/X500NameBuilder.java
deleted file mode 100644
index 7c9506a9..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x500/X500NameBuilder.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package org.bouncycastle.asn1.x500;
-
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.x500.style.BCStyle;
-
-public class X500NameBuilder
-{
- private X500NameStyle template;
- private Vector rdns = new Vector();
-
- public X500NameBuilder()
- {
- this(BCStyle.INSTANCE);
- }
-
- public X500NameBuilder(X500NameStyle template)
- {
- this.template = template;
- }
-
- public X500NameBuilder addRDN(ASN1ObjectIdentifier oid, String value)
- {
- this.addRDN(oid, template.stringToValue(oid, value));
-
- return this;
- }
-
- public X500NameBuilder addRDN(ASN1ObjectIdentifier oid, ASN1Encodable value)
- {
- rdns.addElement(new RDN(oid, value));
-
- return this;
- }
-
- public X500NameBuilder addRDN(AttributeTypeAndValue attrTAndV)
- {
- rdns.addElement(new RDN(attrTAndV));
-
- return this;
- }
-
- public X500NameBuilder addMultiValuedRDN(ASN1ObjectIdentifier[] oids, String[] values)
- {
- ASN1Encodable[] vals = new ASN1Encodable[values.length];
-
- for (int i = 0; i != vals.length; i++)
- {
- vals[i] = template.stringToValue(oids[i], values[i]);
- }
-
- return addMultiValuedRDN(oids, vals);
- }
-
- public X500NameBuilder addMultiValuedRDN(ASN1ObjectIdentifier[] oids, ASN1Encodable[] values)
- {
- AttributeTypeAndValue[] avs = new AttributeTypeAndValue[oids.length];
-
- for (int i = 0; i != oids.length; i++)
- {
- avs[i] = new AttributeTypeAndValue(oids[i], values[i]);
- }
-
- return addMultiValuedRDN(avs);
- }
-
- public X500NameBuilder addMultiValuedRDN(AttributeTypeAndValue[] attrTAndVs)
- {
- rdns.addElement(new RDN(attrTAndVs));
-
- return this;
- }
-
- public X500Name build()
- {
- RDN[] vals = new RDN[rdns.size()];
-
- for (int i = 0; i != vals.length; i++)
- {
- vals[i] = (RDN)rdns.elementAt(i);
- }
-
- return new X500Name(template, vals);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x500/X500NameStyle.java b/core/src/main/java/org/bouncycastle/asn1/x500/X500NameStyle.java
deleted file mode 100644
index 704ea72e..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x500/X500NameStyle.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.bouncycastle.asn1.x500;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-
-/**
- * It turns out that the number of standard ways the fields in a DN should be
- * encoded into their ASN.1 counterparts is rapidly approaching the
- * number of machines on the internet. By default the X500Name class
- * will produce UTF8Strings in line with the current recommendations (RFC 3280).
- * <p>
- */
-public interface X500NameStyle
-{
- /**
- * Convert the passed in String value into the appropriate ASN.1
- * encoded object.
- *
- * @param oid the OID associated with the value in the DN.
- * @param value the value of the particular DN component.
- * @return the ASN.1 equivalent for the value.
- */
- ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value);
-
- /**
- * Return the OID associated with the passed in name.
- *
- * @param attrName the string to match.
- * @return an OID
- */
- ASN1ObjectIdentifier attrNameToOID(String attrName);
-
- /**
- * Return an array of RDN generated from the passed in String.
- * @param dirName the String representation.
- * @return an array of corresponding RDNs.
- */
- RDN[] fromString(String dirName);
-
- /**
- * Return true if the two names are equal.
- *
- * @param name1 first name for comparison.
- * @param name2 second name for comparison.
- * @return true if name1 = name 2, false otherwise.
- */
- boolean areEqual(X500Name name1, X500Name name2);
-
- /**
- * Calculate a hashCode for the passed in name.
- *
- * @param name the name the hashCode is required for.
- * @return the calculated hashCode.
- */
- int calculateHashCode(X500Name name);
-
- /**
- * Convert the passed in X500Name to a String.
- * @param name the name to convert.
- * @return a String representation.
- */
- String toString(X500Name name);
-
- /**
- * Return the display name for toString() associated with the OID.
- *
- * @param oid the OID of interest.
- * @return the name displayed in toString(), null if no mapping provided.
- */
- String oidToDisplayName(ASN1ObjectIdentifier oid);
-
- /**
- * Return the acceptable names in a String DN that map to OID.
- *
- * @param oid the OID of interest.
- * @return an array of String aliases for the OID, zero length if there are none.
- */
- String[] oidToAttrNames(ASN1ObjectIdentifier oid);
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x500/style/AbstractX500NameStyle.java b/core/src/main/java/org/bouncycastle/asn1/x500/style/AbstractX500NameStyle.java
deleted file mode 100644
index 9792d40e..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x500/style/AbstractX500NameStyle.java
+++ /dev/null
@@ -1,192 +0,0 @@
-package org.bouncycastle.asn1.x500.style;
-
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Hashtable;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.DERUTF8String;
-import org.bouncycastle.asn1.x500.AttributeTypeAndValue;
-import org.bouncycastle.asn1.x500.RDN;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x500.X500NameStyle;
-
-/**
- * This class provides some default behavior and common implementation for a
- * X500NameStyle. It should be easily extendable to support implementing the
- * desired X500NameStyle.
- */
-public abstract class AbstractX500NameStyle
- implements X500NameStyle
-{
-
- /**
- * Tool function to shallow copy a Hashtable.
- *
- * @param paramsMap table to copy
- * @return the copy of the table
- */
- public static Hashtable copyHashTable(Hashtable paramsMap)
- {
- Hashtable newTable = new Hashtable();
-
- Enumeration keys = paramsMap.keys();
- while (keys.hasMoreElements())
- {
- Object key = keys.nextElement();
- newTable.put(key, paramsMap.get(key));
- }
-
- return newTable;
- }
-
- private int calcHashCode(ASN1Encodable enc)
- {
- String value = IETFUtils.valueToString(enc);
- value = IETFUtils.canonicalize(value);
- return value.hashCode();
- }
-
- public int calculateHashCode(X500Name name)
- {
- int hashCodeValue = 0;
- RDN[] rdns = name.getRDNs();
-
- // this needs to be order independent, like equals
- for (int i = 0; i != rdns.length; i++)
- {
- if (rdns[i].isMultiValued())
- {
- AttributeTypeAndValue[] atv = rdns[i].getTypesAndValues();
-
- for (int j = 0; j != atv.length; j++)
- {
- hashCodeValue ^= atv[j].getType().hashCode();
- hashCodeValue ^= calcHashCode(atv[j].getValue());
- }
- }
- else
- {
- hashCodeValue ^= rdns[i].getFirst().getType().hashCode();
- hashCodeValue ^= calcHashCode(rdns[i].getFirst().getValue());
- }
- }
-
- return hashCodeValue;
- }
-
-
- /**
- * For all string values starting with '#' is assumed, that these are
- * already valid ASN.1 objects encoded in hex.
- * <p>
- * All other string values are send to
- * {@link AbstractX500NameStyle#encodeStringValue(ASN1ObjectIdentifier, String)}.
- * </p>
- * Subclasses should overwrite
- * {@link AbstractX500NameStyle#encodeStringValue(ASN1ObjectIdentifier, String)}
- * to change the encoding of specific types.
- *
- * @param oid the DN name of the value.
- * @param value the String representation of the value.
- */
- public ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value)
- {
- if (value.length() != 0 && value.charAt(0) == '#')
- {
- try
- {
- return IETFUtils.valueFromHexString(value, 1);
- }
- catch (IOException e)
- {
- throw new RuntimeException("can't recode value for oid " + oid.getId());
- }
- }
-
- if (value.length() != 0 && value.charAt(0) == '\\')
- {
- value = value.substring(1);
- }
-
- return encodeStringValue(oid, value);
- }
-
- /**
- * Encoded every value into a UTF8String.
- * <p>
- * Subclasses should overwrite
- * this method to change the encoding of specific types.
- * </p>
- *
- * @param oid the DN oid of the value
- * @param value the String representation of the value
- * @return a the value encoded into a ASN.1 object. Never returns <code>null</code>.
- */
- protected ASN1Encodable encodeStringValue(ASN1ObjectIdentifier oid, String value)
- {
- return new DERUTF8String(value);
- }
-
- public boolean areEqual(X500Name name1, X500Name name2)
- {
- RDN[] rdns1 = name1.getRDNs();
- RDN[] rdns2 = name2.getRDNs();
-
- if (rdns1.length != rdns2.length)
- {
- return false;
- }
-
- boolean reverse = false;
-
- if (rdns1[0].getFirst() != null && rdns2[0].getFirst() != null)
- {
- reverse = !rdns1[0].getFirst().getType().equals(rdns2[0].getFirst().getType()); // guess forward
- }
-
- for (int i = 0; i != rdns1.length; i++)
- {
- if (!foundMatch(reverse, rdns1[i], rdns2))
- {
- return false;
- }
- }
-
- return true;
- }
-
- private boolean foundMatch(boolean reverse, RDN rdn, RDN[] possRDNs)
- {
- if (reverse)
- {
- for (int i = possRDNs.length - 1; i >= 0; i--)
- {
- if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
- {
- possRDNs[i] = null;
- return true;
- }
- }
- }
- else
- {
- for (int i = 0; i != possRDNs.length; i++)
- {
- if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
- {
- possRDNs[i] = null;
- return true;
- }
- }
- }
-
- return false;
- }
-
- protected boolean rdnAreEqual(RDN rdn1, RDN rdn2)
- {
- return IETFUtils.rDNAreEqual(rdn1, rdn2);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x500/style/BCStrictStyle.java b/core/src/main/java/org/bouncycastle/asn1/x500/style/BCStrictStyle.java
deleted file mode 100644
index eb627c0e..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x500/style/BCStrictStyle.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.bouncycastle.asn1.x500.style;
-
-import org.bouncycastle.asn1.x500.RDN;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x500.X500NameStyle;
-
-/**
- * Variation of BCStyle that insists on strict ordering for equality
- * and hashCode comparisons
- */
-public class BCStrictStyle
- extends BCStyle
-{
- public static final X500NameStyle INSTANCE = new BCStrictStyle();
-
- public boolean areEqual(X500Name name1, X500Name name2)
- {
- RDN[] rdns1 = name1.getRDNs();
- RDN[] rdns2 = name2.getRDNs();
-
- if (rdns1.length != rdns2.length)
- {
- return false;
- }
-
- for (int i = 0; i != rdns1.length; i++)
- {
- if (!rdnAreEqual(rdns1[i], rdns2[i]))
- {
- return false;
- }
- }
-
- return true;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java b/core/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java
deleted file mode 100644
index 1c2a9269..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java
+++ /dev/null
@@ -1,349 +0,0 @@
-package org.bouncycastle.asn1.x500.style;
-
-import java.util.Hashtable;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DERPrintableString;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.asn1.x500.RDN;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x500.X500NameStyle;
-import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
-
-public class BCStyle
- extends AbstractX500NameStyle
-{
- /**
- * country code - StringType(SIZE(2))
- */
- public static final ASN1ObjectIdentifier C = new ASN1ObjectIdentifier("2.5.4.6");
-
- /**
- * organization - StringType(SIZE(1..64))
- */
- public static final ASN1ObjectIdentifier O = new ASN1ObjectIdentifier("2.5.4.10");
-
- /**
- * organizational unit name - StringType(SIZE(1..64))
- */
- public static final ASN1ObjectIdentifier OU = new ASN1ObjectIdentifier("2.5.4.11");
-
- /**
- * Title
- */
- public static final ASN1ObjectIdentifier T = new ASN1ObjectIdentifier("2.5.4.12");
-
- /**
- * common name - StringType(SIZE(1..64))
- */
- public static final ASN1ObjectIdentifier CN = new ASN1ObjectIdentifier("2.5.4.3");
-
- /**
- * device serial number name - StringType(SIZE(1..64))
- */
- public static final ASN1ObjectIdentifier SN = new ASN1ObjectIdentifier("2.5.4.5");
-
- /**
- * street - StringType(SIZE(1..64))
- */
- public static final ASN1ObjectIdentifier STREET = new ASN1ObjectIdentifier("2.5.4.9");
-
- /**
- * device serial number name - StringType(SIZE(1..64))
- */
- public static final ASN1ObjectIdentifier SERIALNUMBER = SN;
-
- /**
- * locality name - StringType(SIZE(1..64))
- */
- public static final ASN1ObjectIdentifier L = new ASN1ObjectIdentifier("2.5.4.7");
-
- /**
- * state, or province name - StringType(SIZE(1..64))
- */
- public static final ASN1ObjectIdentifier ST = new ASN1ObjectIdentifier("2.5.4.8");
-
- /**
- * Naming attributes of type X520name
- */
- public static final ASN1ObjectIdentifier SURNAME = new ASN1ObjectIdentifier("2.5.4.4");
- public static final ASN1ObjectIdentifier GIVENNAME = new ASN1ObjectIdentifier("2.5.4.42");
- public static final ASN1ObjectIdentifier INITIALS = new ASN1ObjectIdentifier("2.5.4.43");
- public static final ASN1ObjectIdentifier GENERATION = new ASN1ObjectIdentifier("2.5.4.44");
- public static final ASN1ObjectIdentifier UNIQUE_IDENTIFIER = new ASN1ObjectIdentifier("2.5.4.45");
-
- /**
- * businessCategory - DirectoryString(SIZE(1..128)
- */
- public static final ASN1ObjectIdentifier BUSINESS_CATEGORY = new ASN1ObjectIdentifier(
- "2.5.4.15");
-
- /**
- * postalCode - DirectoryString(SIZE(1..40)
- */
- public static final ASN1ObjectIdentifier POSTAL_CODE = new ASN1ObjectIdentifier(
- "2.5.4.17");
-
- /**
- * dnQualifier - DirectoryString(SIZE(1..64)
- */
- public static final ASN1ObjectIdentifier DN_QUALIFIER = new ASN1ObjectIdentifier(
- "2.5.4.46");
-
- /**
- * RFC 3039 Pseudonym - DirectoryString(SIZE(1..64)
- */
- public static final ASN1ObjectIdentifier PSEUDONYM = new ASN1ObjectIdentifier(
- "2.5.4.65");
-
-
- /**
- * RFC 3039 DateOfBirth - GeneralizedTime - YYYYMMDD000000Z
- */
- public static final ASN1ObjectIdentifier DATE_OF_BIRTH = new ASN1ObjectIdentifier(
- "1.3.6.1.5.5.7.9.1");
-
- /**
- * RFC 3039 PlaceOfBirth - DirectoryString(SIZE(1..128)
- */
- public static final ASN1ObjectIdentifier PLACE_OF_BIRTH = new ASN1ObjectIdentifier(
- "1.3.6.1.5.5.7.9.2");
-
- /**
- * RFC 3039 Gender - PrintableString (SIZE(1)) -- "M", "F", "m" or "f"
- */
- public static final ASN1ObjectIdentifier GENDER = new ASN1ObjectIdentifier(
- "1.3.6.1.5.5.7.9.3");
-
- /**
- * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
- * codes only
- */
- public static final ASN1ObjectIdentifier COUNTRY_OF_CITIZENSHIP = new ASN1ObjectIdentifier(
- "1.3.6.1.5.5.7.9.4");
-
- /**
- * RFC 3039 CountryOfResidence - PrintableString (SIZE (2)) -- ISO 3166
- * codes only
- */
- public static final ASN1ObjectIdentifier COUNTRY_OF_RESIDENCE = new ASN1ObjectIdentifier(
- "1.3.6.1.5.5.7.9.5");
-
-
- /**
- * ISIS-MTT NameAtBirth - DirectoryString(SIZE(1..64)
- */
- public static final ASN1ObjectIdentifier NAME_AT_BIRTH = new ASN1ObjectIdentifier("1.3.36.8.3.14");
-
- /**
- * RFC 3039 PostalAddress - SEQUENCE SIZE (1..6) OF
- * DirectoryString(SIZE(1..30))
- */
- public static final ASN1ObjectIdentifier POSTAL_ADDRESS = new ASN1ObjectIdentifier("2.5.4.16");
-
- /**
- * RFC 2256 dmdName
- */
- public static final ASN1ObjectIdentifier DMD_NAME = new ASN1ObjectIdentifier("2.5.4.54");
-
- /**
- * id-at-telephoneNumber
- */
- public static final ASN1ObjectIdentifier TELEPHONE_NUMBER = X509ObjectIdentifiers.id_at_telephoneNumber;
-
- /**
- * id-at-name
- */
- public static final ASN1ObjectIdentifier NAME = X509ObjectIdentifiers.id_at_name;
-
- /**
- * Email address (RSA PKCS#9 extension) - IA5String.
- * <p>Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.
- */
- public static final ASN1ObjectIdentifier EmailAddress = PKCSObjectIdentifiers.pkcs_9_at_emailAddress;
-
- /**
- * more from PKCS#9
- */
- public static final ASN1ObjectIdentifier UnstructuredName = PKCSObjectIdentifiers.pkcs_9_at_unstructuredName;
- public static final ASN1ObjectIdentifier UnstructuredAddress = PKCSObjectIdentifiers.pkcs_9_at_unstructuredAddress;
-
- /**
- * email address in Verisign certificates
- */
- public static final ASN1ObjectIdentifier E = EmailAddress;
-
- /*
- * others...
- */
- public static final ASN1ObjectIdentifier DC = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.25");
-
- /**
- * LDAP User id.
- */
- public static final ASN1ObjectIdentifier UID = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.1");
-
- /**
- * default look up table translating OID values into their common symbols following
- * the convention in RFC 2253 with a few extras
- */
- private static final Hashtable DefaultSymbols = new Hashtable();
-
- /**
- * look up table translating common symbols into their OIDS.
- */
- private static final Hashtable DefaultLookUp = new Hashtable();
-
- static
- {
- DefaultSymbols.put(C, "C");
- DefaultSymbols.put(O, "O");
- DefaultSymbols.put(T, "T");
- DefaultSymbols.put(OU, "OU");
- DefaultSymbols.put(CN, "CN");
- DefaultSymbols.put(L, "L");
- DefaultSymbols.put(ST, "ST");
- DefaultSymbols.put(SN, "SERIALNUMBER");
- DefaultSymbols.put(EmailAddress, "E");
- DefaultSymbols.put(DC, "DC");
- DefaultSymbols.put(UID, "UID");
- DefaultSymbols.put(STREET, "STREET");
- DefaultSymbols.put(SURNAME, "SURNAME");
- DefaultSymbols.put(GIVENNAME, "GIVENNAME");
- DefaultSymbols.put(INITIALS, "INITIALS");
- DefaultSymbols.put(GENERATION, "GENERATION");
- DefaultSymbols.put(UnstructuredAddress, "unstructuredAddress");
- DefaultSymbols.put(UnstructuredName, "unstructuredName");
- DefaultSymbols.put(UNIQUE_IDENTIFIER, "UniqueIdentifier");
- DefaultSymbols.put(DN_QUALIFIER, "DN");
- DefaultSymbols.put(PSEUDONYM, "Pseudonym");
- DefaultSymbols.put(POSTAL_ADDRESS, "PostalAddress");
- DefaultSymbols.put(NAME_AT_BIRTH, "NameAtBirth");
- DefaultSymbols.put(COUNTRY_OF_CITIZENSHIP, "CountryOfCitizenship");
- DefaultSymbols.put(COUNTRY_OF_RESIDENCE, "CountryOfResidence");
- DefaultSymbols.put(GENDER, "Gender");
- DefaultSymbols.put(PLACE_OF_BIRTH, "PlaceOfBirth");
- DefaultSymbols.put(DATE_OF_BIRTH, "DateOfBirth");
- DefaultSymbols.put(POSTAL_CODE, "PostalCode");
- DefaultSymbols.put(BUSINESS_CATEGORY, "BusinessCategory");
- DefaultSymbols.put(TELEPHONE_NUMBER, "TelephoneNumber");
- DefaultSymbols.put(NAME, "Name");
-
- DefaultLookUp.put("c", C);
- DefaultLookUp.put("o", O);
- DefaultLookUp.put("t", T);
- DefaultLookUp.put("ou", OU);
- DefaultLookUp.put("cn", CN);
- DefaultLookUp.put("l", L);
- DefaultLookUp.put("st", ST);
- DefaultLookUp.put("sn", SN);
- DefaultLookUp.put("serialnumber", SN);
- DefaultLookUp.put("street", STREET);
- DefaultLookUp.put("emailaddress", E);
- DefaultLookUp.put("dc", DC);
- DefaultLookUp.put("e", E);
- DefaultLookUp.put("uid", UID);
- DefaultLookUp.put("surname", SURNAME);
- DefaultLookUp.put("givenname", GIVENNAME);
- DefaultLookUp.put("initials", INITIALS);
- DefaultLookUp.put("generation", GENERATION);
- DefaultLookUp.put("unstructuredaddress", UnstructuredAddress);
- DefaultLookUp.put("unstructuredname", UnstructuredName);
- DefaultLookUp.put("uniqueidentifier", UNIQUE_IDENTIFIER);
- DefaultLookUp.put("dn", DN_QUALIFIER);
- DefaultLookUp.put("pseudonym", PSEUDONYM);
- DefaultLookUp.put("postaladdress", POSTAL_ADDRESS);
- DefaultLookUp.put("nameofbirth", NAME_AT_BIRTH);
- DefaultLookUp.put("countryofcitizenship", COUNTRY_OF_CITIZENSHIP);
- DefaultLookUp.put("countryofresidence", COUNTRY_OF_RESIDENCE);
- DefaultLookUp.put("gender", GENDER);
- DefaultLookUp.put("placeofbirth", PLACE_OF_BIRTH);
- DefaultLookUp.put("dateofbirth", DATE_OF_BIRTH);
- DefaultLookUp.put("postalcode", POSTAL_CODE);
- DefaultLookUp.put("businesscategory", BUSINESS_CATEGORY);
- DefaultLookUp.put("telephonenumber", TELEPHONE_NUMBER);
- 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);
- }
-
- protected ASN1Encodable encodeStringValue(ASN1ObjectIdentifier oid,
- String value) {
- if (oid.equals(EmailAddress) || oid.equals(DC))
- {
- return new DERIA5String(value);
- }
- else if (oid.equals(DATE_OF_BIRTH)) // accept time string as well as # (for compatibility)
- {
- return new ASN1GeneralizedTime(value);
- }
- else if (oid.equals(C) || oid.equals(SN) || oid.equals(DN_QUALIFIER)
- || oid.equals(TELEPHONE_NUMBER))
- {
- return new DERPrintableString(value);
- }
-
- return super.encodeStringValue(oid, value);
- }
-
- public String oidToDisplayName(ASN1ObjectIdentifier oid)
- {
- return (String)DefaultSymbols.get(oid);
- }
-
- public String[] oidToAttrNames(ASN1ObjectIdentifier oid)
- {
- return IETFUtils.findAttrNamesForOID(oid, defaultLookUp);
- }
-
- public ASN1ObjectIdentifier attrNameToOID(String attrName)
- {
- return IETFUtils.decodeAttrName(attrName, defaultLookUp);
- }
-
- public RDN[] fromString(String dirName)
- {
- return IETFUtils.rDNsFromString(dirName, this);
- }
-
- public String toString(X500Name name)
- {
- StringBuffer buf = new StringBuffer();
- boolean first = true;
-
- RDN[] rdns = name.getRDNs();
-
- for (int i = 0; i < rdns.length; i++)
- {
- if (first)
- {
- first = false;
- }
- else
- {
- buf.append(',');
- }
-
- IETFUtils.appendRDN(buf, rdns[i], defaultSymbols);
- }
-
- return buf.toString();
- }
-
-
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x500/style/IETFUtils.java b/core/src/main/java/org/bouncycastle/asn1/x500/style/IETFUtils.java
deleted file mode 100644
index b4f17941..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x500/style/IETFUtils.java
+++ /dev/null
@@ -1,572 +0,0 @@
-package org.bouncycastle.asn1.x500.style;
-
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Encoding;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1String;
-import org.bouncycastle.asn1.DERUniversalString;
-import org.bouncycastle.asn1.x500.AttributeTypeAndValue;
-import org.bouncycastle.asn1.x500.RDN;
-import org.bouncycastle.asn1.x500.X500NameBuilder;
-import org.bouncycastle.asn1.x500.X500NameStyle;
-import org.bouncycastle.util.Strings;
-import org.bouncycastle.util.encoders.Hex;
-
-public class IETFUtils
-{
- private static String unescape(String elt)
- {
- if (elt.length() == 0 || (elt.indexOf('\\') < 0 && elt.indexOf('"') < 0))
- {
- return elt.trim();
- }
-
- char[] elts = elt.toCharArray();
- boolean escaped = false;
- boolean quoted = false;
- StringBuffer buf = new StringBuffer(elt.length());
- int start = 0;
-
- // if it's an escaped hash string and not an actual encoding in string form
- // we need to leave it escaped.
- if (elts[0] == '\\')
- {
- if (elts[1] == '#')
- {
- start = 2;
- buf.append("\\#");
- }
- }
-
- boolean nonWhiteSpaceEncountered = false;
- int lastEscaped = 0;
- char hex1 = 0;
-
- for (int i = start; i != elts.length; i++)
- {
- char c = elts[i];
-
- if (c != ' ')
- {
- nonWhiteSpaceEncountered = true;
- }
-
- if (c == '"')
- {
- if (!escaped)
- {
- quoted = !quoted;
- }
- else
- {
- buf.append(c);
- }
- escaped = false;
- }
- else if (c == '\\' && !(escaped || quoted))
- {
- escaped = true;
- lastEscaped = buf.length();
- }
- else
- {
- if (c == ' ' && !escaped && !nonWhiteSpaceEncountered)
- {
- continue;
- }
- if (escaped && isHexDigit(c))
- {
- if (hex1 != 0)
- {
- buf.append((char)(convertHex(hex1) * 16 + convertHex(c)));
- escaped = false;
- hex1 = 0;
- continue;
- }
- hex1 = c;
- continue;
- }
- buf.append(c);
- escaped = false;
- }
- }
-
- if (buf.length() > 0)
- {
- while (buf.charAt(buf.length() - 1) == ' ' && lastEscaped != (buf.length() - 1))
- {
- buf.setLength(buf.length() - 1);
- }
- }
-
- return buf.toString();
- }
-
- private static boolean isHexDigit(char c)
- {
- return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F');
- }
-
- private static int convertHex(char c)
- {
- if ('0' <= c && c <= '9')
- {
- return c - '0';
- }
- if ('a' <= c && c <= 'f')
- {
- return c - 'a' + 10;
- }
- return c - 'A' + 10;
- }
-
- public static RDN[] rDNsFromString(String name, X500NameStyle x500Style)
- {
- X500NameTokenizer nTok = new X500NameTokenizer(name);
- X500NameBuilder builder = new X500NameBuilder(x500Style);
-
- while (nTok.hasMoreTokens())
- {
- String token = nTok.nextToken();
-
- if (token.indexOf('+') > 0)
- {
- X500NameTokenizer pTok = new X500NameTokenizer(token, '+');
- X500NameTokenizer vTok = new X500NameTokenizer(pTok.nextToken(), '=');
-
- String attr = vTok.nextToken();
-
- if (!vTok.hasMoreTokens())
- {
- throw new IllegalArgumentException("badly formatted directory string");
- }
-
- String value = vTok.nextToken();
- ASN1ObjectIdentifier oid = x500Style.attrNameToOID(attr.trim());
-
- if (pTok.hasMoreTokens())
- {
- Vector oids = new Vector();
- Vector values = new Vector();
-
- oids.addElement(oid);
- values.addElement(unescape(value));
-
- while (pTok.hasMoreTokens())
- {
- vTok = new X500NameTokenizer(pTok.nextToken(), '=');
-
- attr = vTok.nextToken();
-
- if (!vTok.hasMoreTokens())
- {
- throw new IllegalArgumentException("badly formatted directory string");
- }
-
- value = vTok.nextToken();
- oid = x500Style.attrNameToOID(attr.trim());
-
-
- oids.addElement(oid);
- values.addElement(unescape(value));
- }
-
- builder.addMultiValuedRDN(toOIDArray(oids), toValueArray(values));
- }
- else
- {
- builder.addRDN(oid, unescape(value));
- }
- }
- else
- {
- X500NameTokenizer vTok = new X500NameTokenizer(token, '=');
-
- String attr = vTok.nextToken();
-
- if (!vTok.hasMoreTokens())
- {
- throw new IllegalArgumentException("badly formatted directory string");
- }
-
- String value = vTok.nextToken();
- ASN1ObjectIdentifier oid = x500Style.attrNameToOID(attr.trim());
-
- builder.addRDN(oid, unescape(value));
- }
- }
-
- return builder.build().getRDNs();
- }
-
- private static String[] toValueArray(Vector values)
- {
- String[] tmp = new String[values.size()];
-
- for (int i = 0; i != tmp.length; i++)
- {
- tmp[i] = (String)values.elementAt(i);
- }
-
- return tmp;
- }
-
- private static ASN1ObjectIdentifier[] toOIDArray(Vector oids)
- {
- ASN1ObjectIdentifier[] tmp = new ASN1ObjectIdentifier[oids.size()];
-
- for (int i = 0; i != tmp.length; i++)
- {
- tmp[i] = (ASN1ObjectIdentifier)oids.elementAt(i);
- }
-
- return tmp;
- }
-
- public static String[] findAttrNamesForOID(
- ASN1ObjectIdentifier oid,
- Hashtable lookup)
- {
- int count = 0;
- for (Enumeration en = lookup.elements(); en.hasMoreElements();)
- {
- if (oid.equals(en.nextElement()))
- {
- count++;
- }
- }
-
- String[] aliases = new String[count];
- count = 0;
-
- for (Enumeration en = lookup.keys(); en.hasMoreElements();)
- {
- String key = (String)en.nextElement();
- if (oid.equals(lookup.get(key)))
- {
- aliases[count++] = key;
- }
- }
-
- return aliases;
- }
-
- public static ASN1ObjectIdentifier decodeAttrName(
- String name,
- Hashtable lookUp)
- {
- if (Strings.toUpperCase(name).startsWith("OID."))
- {
- return new ASN1ObjectIdentifier(name.substring(4));
- }
- else if (name.charAt(0) >= '0' && name.charAt(0) <= '9')
- {
- return new ASN1ObjectIdentifier(name);
- }
-
- ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)lookUp.get(Strings.toLowerCase(name));
- if (oid == null)
- {
- throw new IllegalArgumentException("Unknown object id - " + name + " - passed to distinguished name");
- }
-
- return oid;
- }
-
- public static ASN1Encodable valueFromHexString(
- String str,
- int off)
- throws IOException
- {
- byte[] data = new byte[(str.length() - off) / 2];
- for (int index = 0; index != data.length; index++)
- {
- char left = str.charAt((index * 2) + off);
- char right = str.charAt((index * 2) + off + 1);
-
- data[index] = (byte)((convertHex(left) << 4) | convertHex(right));
- }
-
- return ASN1Primitive.fromByteArray(data);
- }
-
- public static void appendRDN(
- StringBuffer buf,
- RDN rdn,
- Hashtable oidSymbols)
- {
- if (rdn.isMultiValued())
- {
- AttributeTypeAndValue[] atv = rdn.getTypesAndValues();
- boolean firstAtv = true;
-
- for (int j = 0; j != atv.length; j++)
- {
- if (firstAtv)
- {
- firstAtv = false;
- }
- else
- {
- buf.append('+');
- }
-
- IETFUtils.appendTypeAndValue(buf, atv[j], oidSymbols);
- }
- }
- else
- {
- IETFUtils.appendTypeAndValue(buf, rdn.getFirst(), oidSymbols);
- }
- }
-
- public static void appendTypeAndValue(
- StringBuffer buf,
- AttributeTypeAndValue typeAndValue,
- Hashtable oidSymbols)
- {
- String sym = (String)oidSymbols.get(typeAndValue.getType());
-
- if (sym != null)
- {
- buf.append(sym);
- }
- else
- {
- buf.append(typeAndValue.getType().getId());
- }
-
- buf.append('=');
-
- buf.append(valueToString(typeAndValue.getValue()));
- }
-
- public static String valueToString(ASN1Encodable value)
- {
- StringBuffer vBuf = new StringBuffer();
-
- if (value instanceof ASN1String && !(value instanceof DERUniversalString))
- {
- String v = ((ASN1String)value).getString();
- if (v.length() > 0 && v.charAt(0) == '#')
- {
- vBuf.append("\\" + v);
- }
- else
- {
- vBuf.append(v);
- }
- }
- else
- {
- try
- {
- vBuf.append("#" + bytesToString(Hex.encode(value.toASN1Primitive().getEncoded(ASN1Encoding.DER))));
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("Other value has no encoded form");
- }
- }
-
- int end = vBuf.length();
- int index = 0;
-
- if (vBuf.length() >= 2 && vBuf.charAt(0) == '\\' && vBuf.charAt(1) == '#')
- {
- index += 2;
- }
-
- while (index != end)
- {
- if ((vBuf.charAt(index) == ',')
- || (vBuf.charAt(index) == '"')
- || (vBuf.charAt(index) == '\\')
- || (vBuf.charAt(index) == '+')
- || (vBuf.charAt(index) == '=')
- || (vBuf.charAt(index) == '<')
- || (vBuf.charAt(index) == '>')
- || (vBuf.charAt(index) == ';'))
- {
- vBuf.insert(index, "\\");
- index++;
- end++;
- }
-
- index++;
- }
-
- int start = 0;
- if (vBuf.length() > 0)
- {
- while (vBuf.length() > start && vBuf.charAt(start) == ' ')
- {
- vBuf.insert(start, "\\");
- start += 2;
- }
- }
-
- int endBuf = vBuf.length() - 1;
-
- while (endBuf >= 0 && vBuf.charAt(endBuf) == ' ')
- {
- vBuf.insert(endBuf, '\\');
- endBuf--;
- }
-
- return vBuf.toString();
- }
-
- private static String bytesToString(
- byte[] data)
- {
- char[] cs = new char[data.length];
-
- for (int i = 0; i != cs.length; i++)
- {
- cs[i] = (char)(data[i] & 0xff);
- }
-
- return new String(cs);
- }
-
- public static String canonicalize(String s)
- {
- String value = Strings.toLowerCase(s.trim());
-
- if (value.length() > 0 && value.charAt(0) == '#')
- {
- ASN1Primitive obj = decodeObject(value);
-
- if (obj instanceof ASN1String)
- {
- value = Strings.toLowerCase(((ASN1String)obj).getString().trim());
- }
- }
-
- value = stripInternalSpaces(value);
-
- return value;
- }
-
- private static ASN1Primitive decodeObject(String oValue)
- {
- try
- {
- return ASN1Primitive.fromByteArray(Hex.decode(oValue.substring(1)));
- }
- catch (IOException e)
- {
- throw new IllegalStateException("unknown encoding in name: " + e);
- }
- }
-
- public static String stripInternalSpaces(
- String str)
- {
- StringBuffer res = new StringBuffer();
-
- if (str.length() != 0)
- {
- char c1 = str.charAt(0);
-
- res.append(c1);
-
- for (int k = 1; k < str.length(); k++)
- {
- char c2 = str.charAt(k);
- if (!(c1 == ' ' && c2 == ' '))
- {
- res.append(c2);
- }
- c1 = c2;
- }
- }
-
- return res.toString();
- }
-
- public static boolean rDNAreEqual(RDN rdn1, RDN rdn2)
- {
- if (rdn1.isMultiValued())
- {
- if (rdn2.isMultiValued())
- {
- AttributeTypeAndValue[] atvs1 = rdn1.getTypesAndValues();
- AttributeTypeAndValue[] atvs2 = rdn2.getTypesAndValues();
-
- if (atvs1.length != atvs2.length)
- {
- return false;
- }
-
- for (int i = 0; i != atvs1.length; i++)
- {
- if (!atvAreEqual(atvs1[i], atvs2[i]))
- {
- return false;
- }
- }
- }
- else
- {
- return false;
- }
- }
- else
- {
- if (!rdn2.isMultiValued())
- {
- return atvAreEqual(rdn1.getFirst(), rdn2.getFirst());
- }
- else
- {
- return false;
- }
- }
-
- return true;
- }
-
- private static boolean atvAreEqual(AttributeTypeAndValue atv1, AttributeTypeAndValue atv2)
- {
- if (atv1 == atv2)
- {
- return true;
- }
-
- if (atv1 == null)
- {
- return false;
- }
-
- if (atv2 == null)
- {
- return false;
- }
-
- ASN1ObjectIdentifier o1 = atv1.getType();
- ASN1ObjectIdentifier o2 = atv2.getType();
-
- if (!o1.equals(o2))
- {
- return false;
- }
-
- String v1 = IETFUtils.canonicalize(IETFUtils.valueToString(atv1.getValue()));
- String v2 = IETFUtils.canonicalize(IETFUtils.valueToString(atv2.getValue()));
-
- if (!v1.equals(v2))
- {
- return false;
- }
-
- return true;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x500/style/RFC4519Style.java b/core/src/main/java/org/bouncycastle/asn1/x500/style/RFC4519Style.java
deleted file mode 100644
index 13f6ef1e..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x500/style/RFC4519Style.java
+++ /dev/null
@@ -1,248 +0,0 @@
-package org.bouncycastle.asn1.x500.style;
-
-import java.util.Hashtable;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DERPrintableString;
-import org.bouncycastle.asn1.x500.RDN;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x500.X500NameStyle;
-
-public class RFC4519Style
- extends AbstractX500NameStyle
-{
- public static final ASN1ObjectIdentifier businessCategory = new ASN1ObjectIdentifier("2.5.4.15");
- public static final ASN1ObjectIdentifier c = new ASN1ObjectIdentifier("2.5.4.6");
- public static final ASN1ObjectIdentifier cn = new ASN1ObjectIdentifier("2.5.4.3");
- public static final ASN1ObjectIdentifier dc = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.25");
- public static final ASN1ObjectIdentifier description = new ASN1ObjectIdentifier("2.5.4.13");
- public static final ASN1ObjectIdentifier destinationIndicator = new ASN1ObjectIdentifier("2.5.4.27");
- public static final ASN1ObjectIdentifier distinguishedName = new ASN1ObjectIdentifier("2.5.4.49");
- public static final ASN1ObjectIdentifier dnQualifier = new ASN1ObjectIdentifier("2.5.4.46");
- public static final ASN1ObjectIdentifier enhancedSearchGuide = new ASN1ObjectIdentifier("2.5.4.47");
- public static final ASN1ObjectIdentifier facsimileTelephoneNumber = new ASN1ObjectIdentifier("2.5.4.23");
- public static final ASN1ObjectIdentifier generationQualifier = new ASN1ObjectIdentifier("2.5.4.44");
- public static final ASN1ObjectIdentifier givenName = new ASN1ObjectIdentifier("2.5.4.42");
- public static final ASN1ObjectIdentifier houseIdentifier = new ASN1ObjectIdentifier("2.5.4.51");
- public static final ASN1ObjectIdentifier initials = new ASN1ObjectIdentifier("2.5.4.43");
- public static final ASN1ObjectIdentifier internationalISDNNumber = new ASN1ObjectIdentifier("2.5.4.25");
- public static final ASN1ObjectIdentifier l = new ASN1ObjectIdentifier("2.5.4.7");
- public static final ASN1ObjectIdentifier member = new ASN1ObjectIdentifier("2.5.4.31");
- public static final ASN1ObjectIdentifier name = new ASN1ObjectIdentifier("2.5.4.41");
- public static final ASN1ObjectIdentifier o = new ASN1ObjectIdentifier("2.5.4.10");
- public static final ASN1ObjectIdentifier ou = new ASN1ObjectIdentifier("2.5.4.11");
- public static final ASN1ObjectIdentifier owner = new ASN1ObjectIdentifier("2.5.4.32");
- public static final ASN1ObjectIdentifier physicalDeliveryOfficeName = new ASN1ObjectIdentifier("2.5.4.19");
- public static final ASN1ObjectIdentifier postalAddress = new ASN1ObjectIdentifier("2.5.4.16");
- public static final ASN1ObjectIdentifier postalCode = new ASN1ObjectIdentifier("2.5.4.17");
- public static final ASN1ObjectIdentifier postOfficeBox = new ASN1ObjectIdentifier("2.5.4.18");
- public static final ASN1ObjectIdentifier preferredDeliveryMethod = new ASN1ObjectIdentifier("2.5.4.28");
- public static final ASN1ObjectIdentifier registeredAddress = new ASN1ObjectIdentifier("2.5.4.26");
- public static final ASN1ObjectIdentifier roleOccupant = new ASN1ObjectIdentifier("2.5.4.33");
- public static final ASN1ObjectIdentifier searchGuide = new ASN1ObjectIdentifier("2.5.4.14");
- public static final ASN1ObjectIdentifier seeAlso = new ASN1ObjectIdentifier("2.5.4.34");
- public static final ASN1ObjectIdentifier serialNumber = new ASN1ObjectIdentifier("2.5.4.5");
- public static final ASN1ObjectIdentifier sn = new ASN1ObjectIdentifier("2.5.4.4");
- public static final ASN1ObjectIdentifier st = new ASN1ObjectIdentifier("2.5.4.8");
- public static final ASN1ObjectIdentifier street = new ASN1ObjectIdentifier("2.5.4.9");
- public static final ASN1ObjectIdentifier telephoneNumber = new ASN1ObjectIdentifier("2.5.4.20");
- public static final ASN1ObjectIdentifier teletexTerminalIdentifier = new ASN1ObjectIdentifier("2.5.4.22");
- public static final ASN1ObjectIdentifier telexNumber = new ASN1ObjectIdentifier("2.5.4.21");
- public static final ASN1ObjectIdentifier title = new ASN1ObjectIdentifier("2.5.4.12");
- public static final ASN1ObjectIdentifier uid = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.1");
- public static final ASN1ObjectIdentifier uniqueMember = new ASN1ObjectIdentifier("2.5.4.50");
- public static final ASN1ObjectIdentifier userPassword = new ASN1ObjectIdentifier("2.5.4.35");
- public static final ASN1ObjectIdentifier x121Address = new ASN1ObjectIdentifier("2.5.4.24");
- public static final ASN1ObjectIdentifier x500UniqueIdentifier = new ASN1ObjectIdentifier("2.5.4.45");
-
- /**
- * default look up table translating OID values into their common symbols following
- * the convention in RFC 2253 with a few extras
- */
- private static final Hashtable DefaultSymbols = new Hashtable();
-
- /**
- * look up table translating common symbols into their OIDS.
- */
- private static final Hashtable DefaultLookUp = new Hashtable();
-
- static
- {
- DefaultSymbols.put(businessCategory, "businessCategory");
- DefaultSymbols.put(c, "c");
- DefaultSymbols.put(cn, "cn");
- DefaultSymbols.put(dc, "dc");
- DefaultSymbols.put(description, "description");
- DefaultSymbols.put(destinationIndicator, "destinationIndicator");
- DefaultSymbols.put(distinguishedName, "distinguishedName");
- DefaultSymbols.put(dnQualifier, "dnQualifier");
- DefaultSymbols.put(enhancedSearchGuide, "enhancedSearchGuide");
- DefaultSymbols.put(facsimileTelephoneNumber, "facsimileTelephoneNumber");
- DefaultSymbols.put(generationQualifier, "generationQualifier");
- DefaultSymbols.put(givenName, "givenName");
- DefaultSymbols.put(houseIdentifier, "houseIdentifier");
- DefaultSymbols.put(initials, "initials");
- DefaultSymbols.put(internationalISDNNumber, "internationalISDNNumber");
- DefaultSymbols.put(l, "l");
- DefaultSymbols.put(member, "member");
- DefaultSymbols.put(name, "name");
- DefaultSymbols.put(o, "o");
- DefaultSymbols.put(ou, "ou");
- DefaultSymbols.put(owner, "owner");
- DefaultSymbols.put(physicalDeliveryOfficeName, "physicalDeliveryOfficeName");
- DefaultSymbols.put(postalAddress, "postalAddress");
- DefaultSymbols.put(postalCode, "postalCode");
- DefaultSymbols.put(postOfficeBox, "postOfficeBox");
- DefaultSymbols.put(preferredDeliveryMethod, "preferredDeliveryMethod");
- DefaultSymbols.put(registeredAddress, "registeredAddress");
- DefaultSymbols.put(roleOccupant, "roleOccupant");
- DefaultSymbols.put(searchGuide, "searchGuide");
- DefaultSymbols.put(seeAlso, "seeAlso");
- DefaultSymbols.put(serialNumber, "serialNumber");
- DefaultSymbols.put(sn, "sn");
- DefaultSymbols.put(st, "st");
- DefaultSymbols.put(street, "street");
- DefaultSymbols.put(telephoneNumber, "telephoneNumber");
- DefaultSymbols.put(teletexTerminalIdentifier, "teletexTerminalIdentifier");
- DefaultSymbols.put(telexNumber, "telexNumber");
- DefaultSymbols.put(title, "title");
- DefaultSymbols.put(uid, "uid");
- DefaultSymbols.put(uniqueMember, "uniqueMember");
- DefaultSymbols.put(userPassword, "userPassword");
- DefaultSymbols.put(x121Address, "x121Address");
- DefaultSymbols.put(x500UniqueIdentifier, "x500UniqueIdentifier");
-
- DefaultLookUp.put("businesscategory", businessCategory);
- DefaultLookUp.put("c", c);
- DefaultLookUp.put("cn", cn);
- DefaultLookUp.put("dc", dc);
- DefaultLookUp.put("description", description);
- DefaultLookUp.put("destinationindicator", destinationIndicator);
- DefaultLookUp.put("distinguishedname", distinguishedName);
- DefaultLookUp.put("dnqualifier", dnQualifier);
- DefaultLookUp.put("enhancedsearchguide", enhancedSearchGuide);
- DefaultLookUp.put("facsimiletelephonenumber", facsimileTelephoneNumber);
- DefaultLookUp.put("generationqualifier", generationQualifier);
- DefaultLookUp.put("givenname", givenName);
- DefaultLookUp.put("houseidentifier", houseIdentifier);
- DefaultLookUp.put("initials", initials);
- DefaultLookUp.put("internationalisdnnumber", internationalISDNNumber);
- DefaultLookUp.put("l", l);
- DefaultLookUp.put("member", member);
- DefaultLookUp.put("name", name);
- DefaultLookUp.put("o", o);
- DefaultLookUp.put("ou", ou);
- DefaultLookUp.put("owner", owner);
- DefaultLookUp.put("physicaldeliveryofficename", physicalDeliveryOfficeName);
- DefaultLookUp.put("postaladdress", postalAddress);
- DefaultLookUp.put("postalcode", postalCode);
- DefaultLookUp.put("postofficebox", postOfficeBox);
- DefaultLookUp.put("preferreddeliverymethod", preferredDeliveryMethod);
- DefaultLookUp.put("registeredaddress", registeredAddress);
- DefaultLookUp.put("roleoccupant", roleOccupant);
- DefaultLookUp.put("searchguide", searchGuide);
- DefaultLookUp.put("seealso", seeAlso);
- DefaultLookUp.put("serialnumber", serialNumber);
- DefaultLookUp.put("sn", sn);
- DefaultLookUp.put("st", st);
- DefaultLookUp.put("street", street);
- DefaultLookUp.put("telephonenumber", telephoneNumber);
- DefaultLookUp.put("teletexterminalidentifier", teletexTerminalIdentifier);
- DefaultLookUp.put("telexnumber", telexNumber);
- DefaultLookUp.put("title", title);
- DefaultLookUp.put("uid", uid);
- DefaultLookUp.put("uniquemember", uniqueMember);
- DefaultLookUp.put("userpassword", userPassword);
- DefaultLookUp.put("x121address", x121Address);
- DefaultLookUp.put("x500uniqueidentifier", x500UniqueIdentifier);
-
- // 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);
- }
-
- protected ASN1Encodable encodeStringValue(ASN1ObjectIdentifier oid,
- String value) {
- if (oid.equals(dc))
- {
- return new DERIA5String(value);
- }
- else if (oid.equals(c) || oid.equals(serialNumber) || oid.equals(dnQualifier)
- || oid.equals(telephoneNumber))
- {
- return new DERPrintableString(value);
- }
-
- return super.encodeStringValue(oid, value);
- }
-
- public String oidToDisplayName(ASN1ObjectIdentifier oid)
- {
- return (String)DefaultSymbols.get(oid);
- }
-
- public String[] oidToAttrNames(ASN1ObjectIdentifier oid)
- {
- return IETFUtils.findAttrNamesForOID(oid, defaultLookUp);
- }
-
- public ASN1ObjectIdentifier attrNameToOID(String attrName)
- {
- return IETFUtils.decodeAttrName(attrName, defaultLookUp);
- }
-
- // parse backwards
- public RDN[] fromString(String dirName)
- {
- RDN[] tmp = IETFUtils.rDNsFromString(dirName, this);
- RDN[] res = new RDN[tmp.length];
-
- for (int i = 0; i != tmp.length; i++)
- {
- res[res.length - i - 1] = tmp[i];
- }
-
- return res;
- }
-
- // convert in reverse
- public String toString(X500Name name)
- {
- StringBuffer buf = new StringBuffer();
- boolean first = true;
-
- RDN[] rdns = name.getRDNs();
-
- for (int i = rdns.length - 1; i >= 0; i--)
- {
- if (first)
- {
- first = false;
- }
- else
- {
- buf.append(',');
- }
-
- IETFUtils.appendRDN(buf, rdns[i], defaultSymbols);
- }
-
- return buf.toString();
- }
-
-
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x500/style/X500NameTokenizer.java b/core/src/main/java/org/bouncycastle/asn1/x500/style/X500NameTokenizer.java
deleted file mode 100644
index b7e52f22..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x500/style/X500NameTokenizer.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package org.bouncycastle.asn1.x500.style;
-
-/**
- * class for breaking up an X500 Name into it's component tokens, ala
- * java.util.StringTokenizer. We need this class as some of the
- * lightweight Java environment don't support classes like
- * StringTokenizer.
- */
-public class X500NameTokenizer
-{
- private String value;
- private int index;
- private char separator;
- private StringBuffer buf = new StringBuffer();
-
- public X500NameTokenizer(
- String oid)
- {
- this(oid, ',');
- }
-
- public X500NameTokenizer(
- String oid,
- char separator)
- {
- this.value = oid;
- this.index = -1;
- this.separator = separator;
- }
-
- public boolean hasMoreTokens()
- {
- return (index != value.length());
- }
-
- public String nextToken()
- {
- if (index == value.length())
- {
- return null;
- }
-
- int end = index + 1;
- boolean quoted = false;
- boolean escaped = false;
-
- buf.setLength(0);
-
- while (end != value.length())
- {
- char c = value.charAt(end);
-
- if (c == '"')
- {
- if (!escaped)
- {
- quoted = !quoted;
- }
- buf.append(c);
- escaped = false;
- }
- else
- {
- if (escaped || quoted)
- {
- buf.append(c);
- escaped = false;
- }
- else if (c == '\\')
- {
- buf.append(c);
- escaped = true;
- }
- else if (c == separator)
- {
- break;
- }
- else
- {
- buf.append(c);
- }
- }
- end++;
- }
-
- index = end;
-
- return buf.toString();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/AccessDescription.java b/core/src/main/java/org/bouncycastle/asn1/x509/AccessDescription.java
deleted file mode 100644
index a1aaca4e..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/AccessDescription.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * The AccessDescription object.
- * <pre>
- * AccessDescription ::= SEQUENCE {
- * accessMethod OBJECT IDENTIFIER,
- * accessLocation GeneralName }
- * </pre>
- */
-public class AccessDescription
- extends ASN1Object
-{
- public final static ASN1ObjectIdentifier id_ad_caIssuers = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.48.2");
-
- public final static ASN1ObjectIdentifier id_ad_ocsp = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.48.1");
-
- ASN1ObjectIdentifier accessMethod = null;
- GeneralName accessLocation = null;
-
- public static AccessDescription getInstance(
- Object obj)
- {
- if (obj instanceof AccessDescription)
- {
- return (AccessDescription)obj;
- }
- else if (obj != null)
- {
- return new AccessDescription(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private AccessDescription(
- ASN1Sequence seq)
- {
- if (seq.size() != 2)
- {
- throw new IllegalArgumentException("wrong number of elements in sequence");
- }
-
- accessMethod = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
- accessLocation = GeneralName.getInstance(seq.getObjectAt(1));
- }
-
- /**
- * create an AccessDescription with the oid and location provided.
- */
- public AccessDescription(
- ASN1ObjectIdentifier oid,
- GeneralName location)
- {
- accessMethod = oid;
- accessLocation = location;
- }
-
- /**
- *
- * @return the access method.
- */
- public ASN1ObjectIdentifier getAccessMethod()
- {
- return accessMethod;
- }
-
- /**
- *
- * @return the access location
- */
- public GeneralName getAccessLocation()
- {
- return accessLocation;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector accessDescription = new ASN1EncodableVector();
-
- accessDescription.add(accessMethod);
- accessDescription.add(accessLocation);
-
- return new DERSequence(accessDescription);
- }
-
- public String toString()
- {
- return ("AccessDescription: Oid(" + this.accessMethod.getId() + ")");
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java b/core/src/main/java/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java
deleted file mode 100644
index bb90030c..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java
+++ /dev/null
@@ -1,148 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.DERSequence;
-
-public class AlgorithmIdentifier
- extends ASN1Object
-{
- private ASN1ObjectIdentifier objectId;
- private ASN1Encodable parameters;
- private boolean parametersDefined = false;
-
- public static AlgorithmIdentifier getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static AlgorithmIdentifier getInstance(
- Object obj)
- {
- if (obj== null || obj instanceof AlgorithmIdentifier)
- {
- return (AlgorithmIdentifier)obj;
- }
-
- // TODO: delete
- if (obj instanceof ASN1ObjectIdentifier)
- {
- return new AlgorithmIdentifier((ASN1ObjectIdentifier)obj);
- }
-
- // TODO: delete
- if (obj instanceof String)
- {
- return new AlgorithmIdentifier((String)obj);
- }
-
- return new AlgorithmIdentifier(ASN1Sequence.getInstance(obj));
- }
-
- public AlgorithmIdentifier(
- ASN1ObjectIdentifier objectId)
- {
- this.objectId = objectId;
- }
-
- /**
- * @deprecated use ASN1ObjectIdentifier
- * @param objectId
- */
- public AlgorithmIdentifier(
- String objectId)
- {
- this.objectId = new ASN1ObjectIdentifier(objectId);
- }
-
- public AlgorithmIdentifier(
- ASN1ObjectIdentifier objectId,
- ASN1Encodable parameters)
- {
- parametersDefined = true;
- this.objectId = objectId;
- this.parameters = parameters;
- }
-
- /**
- * @deprecated use AlgorithmIdentifier.getInstance()
- * @param seq
- */
- public AlgorithmIdentifier(
- ASN1Sequence seq)
- {
- if (seq.size() < 1 || seq.size() > 2)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
-
- objectId = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
-
- if (seq.size() == 2)
- {
- parametersDefined = true;
- parameters = seq.getObjectAt(1);
- }
- else
- {
- parameters = null;
- }
- }
-
- public ASN1ObjectIdentifier getAlgorithm()
- {
- return new ASN1ObjectIdentifier(objectId.getId());
- }
-
- /**
- * @deprecated use getAlgorithm
- * @return
- */
- public ASN1ObjectIdentifier getObjectId()
- {
- return objectId;
- }
-
- public ASN1Encodable getParameters()
- {
- return parameters;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * AlgorithmIdentifier ::= SEQUENCE {
- * algorithm OBJECT IDENTIFIER,
- * parameters ANY DEFINED BY algorithm OPTIONAL }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(objectId);
-
- if (parametersDefined)
- {
- if (parameters != null)
- {
- v.add(parameters);
- }
- else
- {
- v.add(DERNull.INSTANCE);
- }
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/AttCertIssuer.java b/core/src/main/java/org/bouncycastle/asn1/x509/AttCertIssuer.java
deleted file mode 100644
index 21907c68..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/AttCertIssuer.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-public class AttCertIssuer
- extends ASN1Object
- implements ASN1Choice
-{
- ASN1Encodable obj;
- ASN1Primitive choiceObj;
-
- public static AttCertIssuer getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof AttCertIssuer)
- {
- return (AttCertIssuer)obj;
- }
- else if (obj instanceof V2Form)
- {
- return new AttCertIssuer(V2Form.getInstance(obj));
- }
- else if (obj instanceof GeneralNames)
- {
- return new AttCertIssuer((GeneralNames)obj);
- }
- else if (obj instanceof ASN1TaggedObject)
- {
- return new AttCertIssuer(V2Form.getInstance((ASN1TaggedObject)obj, false));
- }
- else if (obj instanceof ASN1Sequence)
- {
- return new AttCertIssuer(GeneralNames.getInstance(obj));
- }
-
- throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
- }
-
- public static AttCertIssuer getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject()); // must be explicitly tagged
- }
-
- /**
- * Don't use this one if you are trying to be RFC 3281 compliant.
- * Use it for v1 attribute certificates only.
- *
- * @param names our GeneralNames structure
- */
- public AttCertIssuer(
- GeneralNames names)
- {
- obj = names;
- choiceObj = obj.toASN1Primitive();
- }
-
- public AttCertIssuer(
- V2Form v2Form)
- {
- obj = v2Form;
- choiceObj = new DERTaggedObject(false, 0, obj);
- }
-
- public ASN1Encodable getIssuer()
- {
- return obj;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * AttCertIssuer ::= CHOICE {
- * v1Form GeneralNames, -- MUST NOT be used in this
- * -- profile
- * v2Form [0] V2Form -- v2 only
- * }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- return choiceObj;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/AttCertValidityPeriod.java b/core/src/main/java/org/bouncycastle/asn1/x509/AttCertValidityPeriod.java
deleted file mode 100644
index 2f781564..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/AttCertValidityPeriod.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-public class AttCertValidityPeriod
- extends ASN1Object
-{
- ASN1GeneralizedTime notBeforeTime;
- ASN1GeneralizedTime notAfterTime;
-
- public static AttCertValidityPeriod getInstance(
- Object obj)
- {
- if (obj instanceof AttCertValidityPeriod)
- {
- return (AttCertValidityPeriod)obj;
- }
- else if (obj != null)
- {
- return new AttCertValidityPeriod(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private AttCertValidityPeriod(
- ASN1Sequence seq)
- {
- if (seq.size() != 2)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
-
- notBeforeTime = ASN1GeneralizedTime.getInstance(seq.getObjectAt(0));
- notAfterTime = ASN1GeneralizedTime.getInstance(seq.getObjectAt(1));
- }
-
- /**
- * @param notBeforeTime
- * @param notAfterTime
- */
- public AttCertValidityPeriod(
- ASN1GeneralizedTime notBeforeTime,
- ASN1GeneralizedTime notAfterTime)
- {
- this.notBeforeTime = notBeforeTime;
- this.notAfterTime = notAfterTime;
- }
-
- public ASN1GeneralizedTime getNotBeforeTime()
- {
- return notBeforeTime;
- }
-
- public ASN1GeneralizedTime getNotAfterTime()
- {
- return notAfterTime;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * AttCertValidityPeriod ::= SEQUENCE {
- * notBeforeTime GeneralizedTime,
- * notAfterTime GeneralizedTime
- * }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(notBeforeTime);
- v.add(notAfterTime);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/Attribute.java b/core/src/main/java/org/bouncycastle/asn1/x509/Attribute.java
deleted file mode 100644
index b8d4bde7..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/Attribute.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.DERSequence;
-
-public class Attribute
- extends ASN1Object
-{
- private ASN1ObjectIdentifier attrType;
- private ASN1Set attrValues;
-
- /**
- * return an Attribute object from the given object.
- *
- * @param o the object we want converted.
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static Attribute getInstance(
- Object o)
- {
- if (o instanceof Attribute)
- {
- return (Attribute)o;
- }
-
- if (o != null)
- {
- return new Attribute(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- private Attribute(
- ASN1Sequence seq)
- {
- if (seq.size() != 2)
- {
- throw new IllegalArgumentException("Bad sequence size: " + seq.size());
- }
-
- attrType = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
- attrValues = ASN1Set.getInstance(seq.getObjectAt(1));
- }
-
- public Attribute(
- ASN1ObjectIdentifier attrType,
- ASN1Set attrValues)
- {
- this.attrType = attrType;
- this.attrValues = attrValues;
- }
-
- public ASN1ObjectIdentifier getAttrType()
- {
- return new ASN1ObjectIdentifier(attrType.getId());
- }
-
- public ASN1Encodable[] getAttributeValues()
- {
- return attrValues.toArray();
- }
-
- public ASN1Set getAttrValues()
- {
- return attrValues;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * Attribute ::= SEQUENCE {
- * attrType OBJECT IDENTIFIER,
- * attrValues SET OF AttributeValue
- * }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(attrType);
- v.add(attrValues);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificate.java b/core/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificate.java
deleted file mode 100644
index 73fe7b49..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificate.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERSequence;
-
-public class AttributeCertificate
- extends ASN1Object
-{
- AttributeCertificateInfo acinfo;
- AlgorithmIdentifier signatureAlgorithm;
- DERBitString signatureValue;
-
- /**
- * @param obj
- * @return an AttributeCertificate object
- */
- public static AttributeCertificate getInstance(Object obj)
- {
- if (obj instanceof AttributeCertificate)
- {
- return (AttributeCertificate)obj;
- }
- else if (obj != null)
- {
- return new AttributeCertificate(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public AttributeCertificate(
- AttributeCertificateInfo acinfo,
- AlgorithmIdentifier signatureAlgorithm,
- DERBitString signatureValue)
- {
- this.acinfo = acinfo;
- this.signatureAlgorithm = signatureAlgorithm;
- this.signatureValue = signatureValue;
- }
-
- /**
- * @deprecated use getInstance() method.
- */
- public AttributeCertificate(
- ASN1Sequence seq)
- {
- if (seq.size() != 3)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
-
- this.acinfo = AttributeCertificateInfo.getInstance(seq.getObjectAt(0));
- this.signatureAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
- this.signatureValue = DERBitString.getInstance(seq.getObjectAt(2));
- }
-
- public AttributeCertificateInfo getAcinfo()
- {
- return acinfo;
- }
-
- public AlgorithmIdentifier getSignatureAlgorithm()
- {
- return signatureAlgorithm;
- }
-
- public DERBitString getSignatureValue()
- {
- return signatureValue;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * AttributeCertificate ::= SEQUENCE {
- * acinfo AttributeCertificateInfo,
- * signatureAlgorithm AlgorithmIdentifier,
- * signatureValue BIT STRING
- * }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(acinfo);
- v.add(signatureAlgorithm);
- v.add(signatureValue);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificateInfo.java b/core/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificateInfo.java
deleted file mode 100644
index ae539f42..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificateInfo.java
+++ /dev/null
@@ -1,180 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERSequence;
-
-public class AttributeCertificateInfo
- extends ASN1Object
-{
- private ASN1Integer version;
- private Holder holder;
- private AttCertIssuer issuer;
- private AlgorithmIdentifier signature;
- private ASN1Integer serialNumber;
- private AttCertValidityPeriod attrCertValidityPeriod;
- private ASN1Sequence attributes;
- private DERBitString issuerUniqueID;
- private Extensions extensions;
-
- public static AttributeCertificateInfo getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static AttributeCertificateInfo getInstance(
- Object obj)
- {
- if (obj instanceof AttributeCertificateInfo)
- {
- return (AttributeCertificateInfo)obj;
- }
- else if (obj != null)
- {
- return new AttributeCertificateInfo(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private AttributeCertificateInfo(
- ASN1Sequence seq)
- {
- if (seq.size() < 6 || seq.size() > 9)
- {
- throw new IllegalArgumentException("Bad sequence size: " + seq.size());
- }
-
- 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 = start + 6; i < seq.size(); i++)
- {
- ASN1Encodable obj = seq.getObjectAt(i);
-
- if (obj instanceof DERBitString)
- {
- this.issuerUniqueID = DERBitString.getInstance(seq.getObjectAt(i));
- }
- else if (obj instanceof ASN1Sequence || obj instanceof Extensions)
- {
- this.extensions = Extensions.getInstance(seq.getObjectAt(i));
- }
- }
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public Holder getHolder()
- {
- return holder;
- }
-
- public AttCertIssuer getIssuer()
- {
- return issuer;
- }
-
- public AlgorithmIdentifier getSignature()
- {
- return signature;
- }
-
- public ASN1Integer getSerialNumber()
- {
- return serialNumber;
- }
-
- public AttCertValidityPeriod getAttrCertValidityPeriod()
- {
- return attrCertValidityPeriod;
- }
-
- public ASN1Sequence getAttributes()
- {
- return attributes;
- }
-
- public DERBitString getIssuerUniqueID()
- {
- return issuerUniqueID;
- }
-
- public Extensions getExtensions()
- {
- return extensions;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * AttributeCertificateInfo ::= SEQUENCE {
- * version AttCertVersion -- version is v2,
- * holder Holder,
- * issuer AttCertIssuer,
- * signature AlgorithmIdentifier,
- * serialNumber CertificateSerialNumber,
- * attrCertValidityPeriod AttCertValidityPeriod,
- * attributes SEQUENCE OF Attribute,
- * issuerUniqueID UniqueIdentifier OPTIONAL,
- * extensions Extensions OPTIONAL
- * }
- *
- * AttCertVersion ::= INTEGER { v2(1) }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (version.getValue().intValue() != 0)
- {
- v.add(version);
- }
- v.add(holder);
- v.add(issuer);
- v.add(signature);
- v.add(serialNumber);
- v.add(attrCertValidityPeriod);
- v.add(attributes);
-
- if (issuerUniqueID != null)
- {
- v.add(issuerUniqueID);
- }
-
- if (extensions != null)
- {
- v.add(extensions);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/AuthorityInformationAccess.java b/core/src/main/java/org/bouncycastle/asn1/x509/AuthorityInformationAccess.java
deleted file mode 100644
index f66f270d..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/AuthorityInformationAccess.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * The AuthorityInformationAccess object.
- * <pre>
- * id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 }
- *
- * AuthorityInfoAccessSyntax ::=
- * SEQUENCE SIZE (1..MAX) OF AccessDescription
- * AccessDescription ::= SEQUENCE {
- * accessMethod OBJECT IDENTIFIER,
- * accessLocation GeneralName }
- *
- * id-ad OBJECT IDENTIFIER ::= { id-pkix 48 }
- * id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 }
- * id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 }
- * </pre>
- */
-public class AuthorityInformationAccess
- extends ASN1Object
-{
- private AccessDescription[] descriptions;
-
- public static AuthorityInformationAccess getInstance(
- Object obj)
- {
- if (obj instanceof AuthorityInformationAccess)
- {
- return (AuthorityInformationAccess)obj;
- }
-
- if (obj != null)
- {
- return new AuthorityInformationAccess(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private AuthorityInformationAccess(
- ASN1Sequence seq)
- {
- if (seq.size() < 1)
- {
- throw new IllegalArgumentException("sequence may not be empty");
- }
-
- descriptions = new AccessDescription[seq.size()];
-
- for (int i = 0; i != seq.size(); i++)
- {
- descriptions[i] = AccessDescription.getInstance(seq.getObjectAt(i));
- }
- }
-
- public AuthorityInformationAccess(
- AccessDescription description)
- {
- this.descriptions = new AccessDescription[]{ description };
- }
-
- /**
- * create an AuthorityInformationAccess with the oid and location provided.
- */
- public AuthorityInformationAccess(
- ASN1ObjectIdentifier oid,
- GeneralName location)
- {
- this(new AccessDescription(oid, location));
- }
-
- /**
- *
- * @return the access descriptions contained in this object.
- */
- public AccessDescription[] getAccessDescriptions()
- {
- return descriptions;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector vec = new ASN1EncodableVector();
-
- for (int i = 0; i != descriptions.length; i++)
- {
- vec.add(descriptions[i]);
- }
-
- return new DERSequence(vec);
- }
-
- public String toString()
- {
- return ("AuthorityInformationAccess: Oid(" + this.descriptions[0].getAccessMethod().getId() + ")");
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java b/core/src/main/java/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java
deleted file mode 100644
index 302ba032..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java
+++ /dev/null
@@ -1,229 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-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.ASN1TaggedObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-
-/**
- * The AuthorityKeyIdentifier object.
- * <pre>
- * id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 }
- *
- * AuthorityKeyIdentifier ::= SEQUENCE {
- * keyIdentifier [0] IMPLICIT KeyIdentifier OPTIONAL,
- * authorityCertIssuer [1] IMPLICIT GeneralNames OPTIONAL,
- * authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL }
- *
- * KeyIdentifier ::= OCTET STRING
- * </pre>
- *
- */
-public class AuthorityKeyIdentifier
- extends ASN1Object
-{
- ASN1OctetString keyidentifier=null;
- GeneralNames certissuer=null;
- ASN1Integer certserno=null;
-
- public static AuthorityKeyIdentifier getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static AuthorityKeyIdentifier getInstance(
- Object obj)
- {
- if (obj instanceof AuthorityKeyIdentifier)
- {
- return (AuthorityKeyIdentifier)obj;
- }
- if (obj != null)
- {
- return new AuthorityKeyIdentifier(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public static AuthorityKeyIdentifier fromExtensions(Extensions extensions)
- {
- return AuthorityKeyIdentifier.getInstance(extensions.getExtensionParsedValue(Extension.authorityKeyIdentifier));
- }
-
- protected AuthorityKeyIdentifier(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- while (e.hasMoreElements())
- {
- ASN1TaggedObject o = DERTaggedObject.getInstance(e.nextElement());
-
- switch (o.getTagNo())
- {
- case 0:
- this.keyidentifier = ASN1OctetString.getInstance(o, false);
- break;
- case 1:
- this.certissuer = GeneralNames.getInstance(o, false);
- break;
- case 2:
- this.certserno = ASN1Integer.getInstance(o, false);
- break;
- default:
- throw new IllegalArgumentException("illegal tag");
- }
- }
- }
-
- /**
- *
- * Calulates the keyidentifier using a SHA1 hash over the BIT STRING
- * from SubjectPublicKeyInfo as defined in RFC2459.
- *
- * Example of making a AuthorityKeyIdentifier:
- * <pre>
- * SubjectPublicKeyInfo apki = new SubjectPublicKeyInfo((ASN1Sequence)new ASN1InputStream(
- * publicKey.getEncoded()).readObject());
- * AuthorityKeyIdentifier aki = new AuthorityKeyIdentifier(apki);
- * </pre>
- * @deprecated create the extension using org.bouncycastle.cert.X509ExtensionUtils
- **/
- public AuthorityKeyIdentifier(
- SubjectPublicKeyInfo spki)
- {
- Digest digest = new SHA1Digest();
- byte[] resBuf = new byte[digest.getDigestSize()];
-
- byte[] bytes = spki.getPublicKeyData().getBytes();
- digest.update(bytes, 0, bytes.length);
- digest.doFinal(resBuf, 0);
- this.keyidentifier = new DEROctetString(resBuf);
- }
-
- /**
- * create an AuthorityKeyIdentifier with the GeneralNames tag and
- * the serial number provided as well.
- * @deprecated create the extension using org.bouncycastle.cert.X509ExtensionUtils
- */
- public AuthorityKeyIdentifier(
- SubjectPublicKeyInfo spki,
- GeneralNames name,
- BigInteger serialNumber)
- {
- Digest digest = new SHA1Digest();
- byte[] resBuf = new byte[digest.getDigestSize()];
-
- byte[] bytes = spki.getPublicKeyData().getBytes();
- digest.update(bytes, 0, bytes.length);
- digest.doFinal(resBuf, 0);
-
- this.keyidentifier = new DEROctetString(resBuf);
- this.certissuer = GeneralNames.getInstance(name.toASN1Primitive());
- this.certserno = new ASN1Integer(serialNumber);
- }
-
- /**
- * create an AuthorityKeyIdentifier with the GeneralNames tag and
- * the serial number provided.
- */
- public AuthorityKeyIdentifier(
- GeneralNames name,
- BigInteger serialNumber)
- {
- this((byte[])null, name, serialNumber);
- }
-
- /**
- * create an AuthorityKeyIdentifier with a precomputed key identifier
- */
- public AuthorityKeyIdentifier(
- byte[] keyIdentifier)
- {
- this(keyIdentifier, null, null);
- }
-
- /**
- * create an AuthorityKeyIdentifier with a precomputed key identifier
- * and the GeneralNames tag and the serial number provided as well.
- */
- public AuthorityKeyIdentifier(
- byte[] keyIdentifier,
- GeneralNames name,
- BigInteger serialNumber)
- {
- this.keyidentifier = (keyIdentifier != null) ? new DEROctetString(keyIdentifier) : null;
- this.certissuer = name;
- this.certserno = (serialNumber != null) ? new ASN1Integer(serialNumber) : null;
- }
-
- public byte[] getKeyIdentifier()
- {
- if (keyidentifier != null)
- {
- return keyidentifier.getOctets();
- }
-
- return null;
- }
-
- public GeneralNames getAuthorityCertIssuer()
- {
- return certissuer;
- }
-
- public BigInteger getAuthorityCertSerialNumber()
- {
- if (certserno != null)
- {
- return certserno.getValue();
- }
-
- return null;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (keyidentifier != null)
- {
- v.add(new DERTaggedObject(false, 0, keyidentifier));
- }
-
- if (certissuer != null)
- {
- v.add(new DERTaggedObject(false, 1, certissuer));
- }
-
- if (certserno != null)
- {
- v.add(new DERTaggedObject(false, 2, certserno));
- }
-
-
- return new DERSequence(v);
- }
-
- public String toString()
- {
- return ("AuthorityKeyIdentifier: KeyID(" + this.keyidentifier.getOctets() + ")");
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/BasicConstraints.java b/core/src/main/java/org/bouncycastle/asn1/x509/BasicConstraints.java
deleted file mode 100644
index ba5ecf1f..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/BasicConstraints.java
+++ /dev/null
@@ -1,163 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1Boolean;
-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;
-
-public class BasicConstraints
- extends ASN1Object
-{
- ASN1Boolean cA = ASN1Boolean.getInstance(false);
- ASN1Integer pathLenConstraint = null;
-
- public static BasicConstraints getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static BasicConstraints getInstance(
- Object obj)
- {
- if (obj instanceof BasicConstraints)
- {
- return (BasicConstraints)obj;
- }
- if (obj instanceof X509Extension)
- {
- return getInstance(X509Extension.convertValueToObject((X509Extension)obj));
- }
- if (obj != null)
- {
- return new BasicConstraints(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public static BasicConstraints fromExtensions(Extensions extensions)
- {
- return BasicConstraints.getInstance(extensions.getExtensionParsedValue(Extension.basicConstraints));
- }
-
- private BasicConstraints(
- ASN1Sequence seq)
- {
- if (seq.size() == 0)
- {
- this.cA = null;
- this.pathLenConstraint = null;
- }
- else
- {
- if (seq.getObjectAt(0) instanceof ASN1Boolean)
- {
- this.cA = ASN1Boolean.getInstance(seq.getObjectAt(0));
- }
- else
- {
- this.cA = null;
- this.pathLenConstraint = ASN1Integer.getInstance(seq.getObjectAt(0));
- }
- if (seq.size() > 1)
- {
- if (this.cA != null)
- {
- this.pathLenConstraint = ASN1Integer.getInstance(seq.getObjectAt(1));
- }
- else
- {
- throw new IllegalArgumentException("wrong sequence in constructor");
- }
- }
- }
- }
-
- public BasicConstraints(
- boolean cA)
- {
- if (cA)
- {
- this.cA = ASN1Boolean.getInstance(true);
- }
- else
- {
- this.cA = null;
- }
- this.pathLenConstraint = null;
- }
-
- /**
- * create a cA=true object for the given path length constraint.
- *
- * @param pathLenConstraint
- */
- public BasicConstraints(
- int pathLenConstraint)
- {
- this.cA = ASN1Boolean.getInstance(true);
- this.pathLenConstraint = new ASN1Integer(pathLenConstraint);
- }
-
- public boolean isCA()
- {
- return (cA != null) && cA.isTrue();
- }
-
- public BigInteger getPathLenConstraint()
- {
- if (pathLenConstraint != null)
- {
- return pathLenConstraint.getValue();
- }
-
- return null;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * BasicConstraints := SEQUENCE {
- * cA BOOLEAN DEFAULT FALSE,
- * pathLenConstraint INTEGER (0..MAX) OPTIONAL
- * }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (cA != null)
- {
- v.add(cA);
- }
-
- if (pathLenConstraint != null) // yes some people actually do this when cA is false...
- {
- v.add(pathLenConstraint);
- }
-
- return new DERSequence(v);
- }
-
- public String toString()
- {
- if (pathLenConstraint == null)
- {
- if (cA == null)
- {
- return "BasicConstraints: isCa(false)";
- }
- return "BasicConstraints: isCa(" + this.isCA() + ")";
- }
- return "BasicConstraints: isCa(" + this.isCA() + "), pathLenConstraint = " + pathLenConstraint.getValue();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/CRLDistPoint.java b/core/src/main/java/org/bouncycastle/asn1/x509/CRLDistPoint.java
deleted file mode 100644
index 1ee6aa5a..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/CRLDistPoint.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-
-public class CRLDistPoint
- extends ASN1Object
-{
- ASN1Sequence seq = null;
-
- public static CRLDistPoint getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static CRLDistPoint getInstance(
- Object obj)
- {
- if (obj instanceof CRLDistPoint)
- {
- return (CRLDistPoint)obj;
- }
- else if (obj != null)
- {
- return new CRLDistPoint(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private CRLDistPoint(
- ASN1Sequence seq)
- {
- this.seq = seq;
- }
-
- public CRLDistPoint(
- DistributionPoint[] points)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- for (int i = 0; i != points.length; i++)
- {
- v.add(points[i]);
- }
-
- seq = new DERSequence(v);
- }
-
- /**
- * Return the distribution points making up the sequence.
- *
- * @return DistributionPoint[]
- */
- public DistributionPoint[] getDistributionPoints()
- {
- DistributionPoint[] dp = new DistributionPoint[seq.size()];
-
- for (int i = 0; i != seq.size(); i++)
- {
- dp[i] = DistributionPoint.getInstance(seq.getObjectAt(i));
- }
-
- return dp;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * CRLDistPoint ::= SEQUENCE SIZE {1..MAX} OF DistributionPoint
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- return seq;
- }
-
- public String toString()
- {
- StringBuffer buf = new StringBuffer();
- String sep = System.getProperty("line.separator");
-
- buf.append("CRLDistPoint:");
- buf.append(sep);
- DistributionPoint dp[] = getDistributionPoints();
- for (int i = 0; i != dp.length; i++)
- {
- buf.append(" ");
- buf.append(dp[i]);
- buf.append(sep);
- }
- return buf.toString();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/CRLNumber.java b/core/src/main/java/org/bouncycastle/asn1/x509/CRLNumber.java
deleted file mode 100644
index 95425ba3..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/CRLNumber.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-
-/**
- * The CRLNumber object.
- * <pre>
- * CRLNumber::= INTEGER(0..MAX)
- * </pre>
- */
-public class CRLNumber
- extends ASN1Object
-{
- private BigInteger number;
-
- public CRLNumber(
- BigInteger number)
- {
- this.number = number;
- }
-
- public BigInteger getCRLNumber()
- {
- return number;
- }
-
- public String toString()
- {
- return "CRLNumber: " + getCRLNumber();
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return new ASN1Integer(number);
- }
-
- public static CRLNumber getInstance(Object o)
- {
- if (o instanceof CRLNumber)
- {
- return (CRLNumber)o;
- }
- else if (o != null)
- {
- return new CRLNumber(ASN1Integer.getInstance(o).getValue());
- }
-
- return null;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/CRLReason.java b/core/src/main/java/org/bouncycastle/asn1/x509/CRLReason.java
deleted file mode 100644
index ecc68721..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/CRLReason.java
+++ /dev/null
@@ -1,151 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.math.BigInteger;
-import java.util.Hashtable;
-
-import org.bouncycastle.asn1.ASN1Enumerated;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.util.Integers;
-
-/**
- * The CRLReason enumeration.
- * <pre>
- * CRLReason ::= ENUMERATED {
- * unspecified (0),
- * keyCompromise (1),
- * cACompromise (2),
- * affiliationChanged (3),
- * superseded (4),
- * cessationOfOperation (5),
- * certificateHold (6),
- * removeFromCRL (8),
- * privilegeWithdrawn (9),
- * aACompromise (10)
- * }
- * </pre>
- */
-public class CRLReason
- extends ASN1Object
-{
- /**
- * @deprecated use lower case version
- */
- public static final int UNSPECIFIED = 0;
- /**
- * @deprecated use lower case version
- */
- public static final int KEY_COMPROMISE = 1;
- /**
- * @deprecated use lower case version
- */
- public static final int CA_COMPROMISE = 2;
- /**
- * @deprecated use lower case version
- */
- public static final int AFFILIATION_CHANGED = 3;
- /**
- * @deprecated use lower case version
- */
- public static final int SUPERSEDED = 4;
- /**
- * @deprecated use lower case version
- */
- public static final int CESSATION_OF_OPERATION = 5;
- /**
- * @deprecated use lower case version
- */
- public static final int CERTIFICATE_HOLD = 6;
- /**
- * @deprecated use lower case version
- */
- public static final int REMOVE_FROM_CRL = 8;
- /**
- * @deprecated use lower case version
- */
- public static final int PRIVILEGE_WITHDRAWN = 9;
- /**
- * @deprecated use lower case version
- */
- public static final int AA_COMPROMISE = 10;
-
- public static final int unspecified = 0;
- public static final int keyCompromise = 1;
- public static final int cACompromise = 2;
- public static final int affiliationChanged = 3;
- public static final int superseded = 4;
- public static final int cessationOfOperation = 5;
- public static final int certificateHold = 6;
- // 7 -> unknown
- public static final int removeFromCRL = 8;
- public static final int privilegeWithdrawn = 9;
- public static final int aACompromise = 10;
-
- private static final String[] reasonString =
- {
- "unspecified", "keyCompromise", "cACompromise", "affiliationChanged",
- "superseded", "cessationOfOperation", "certificateHold", "unknown",
- "removeFromCRL", "privilegeWithdrawn", "aACompromise"
- };
-
- private static final Hashtable table = new Hashtable();
-
- private ASN1Enumerated value;
-
- public static CRLReason getInstance(Object o)
- {
- if (o instanceof CRLReason)
- {
- return (CRLReason)o;
- }
- else if (o != null)
- {
- return lookup(ASN1Enumerated.getInstance(o).getValue().intValue());
- }
-
- return null;
- }
-
- private CRLReason(
- int reason)
- {
- value = new ASN1Enumerated(reason);
- }
-
- public String toString()
- {
- String str;
- int reason = getValue().intValue();
- if (reason < 0 || reason > 10)
- {
- str = "invalid";
- }
- else
- {
- str = reasonString[reason];
- }
- return "CRLReason: " + str;
- }
-
- public BigInteger getValue()
- {
- return value.getValue();
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return value;
- }
-
- public static CRLReason lookup(int value)
- {
- Integer idx = Integers.valueOf(value);
-
- if (!table.containsKey(idx))
- {
- table.put(idx, new CRLReason(value));
- }
-
- return (CRLReason)table.get(idx);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/CertPolicyId.java b/core/src/main/java/org/bouncycastle/asn1/x509/CertPolicyId.java
deleted file mode 100644
index ab1e5a22..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/CertPolicyId.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-
-
-/**
- * CertPolicyId, used in the CertificatePolicies and PolicyMappings
- * X509V3 Extensions.
- *
- * <pre>
- * CertPolicyId ::= OBJECT IDENTIFIER
- * </pre>
- */
-/**
- * CertPolicyId, used in the CertificatePolicies and PolicyMappings
- * X509V3 Extensions.
- *
- * <pre>
- * CertPolicyId ::= OBJECT IDENTIFIER
- * </pre>
- */
-public class CertPolicyId
- extends ASN1Object
-{
- private ASN1ObjectIdentifier id;
-
- private CertPolicyId(ASN1ObjectIdentifier id)
- {
- this.id = id;
- }
-
- public static CertPolicyId getInstance(Object o)
- {
- if (o instanceof CertPolicyId)
- {
- return (CertPolicyId)o;
- }
- else if (o != null)
- {
- return new CertPolicyId(ASN1ObjectIdentifier.getInstance(o));
- }
-
- return null;
- }
-
- public String getId()
- {
- return id.getId();
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return id;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/Certificate.java b/core/src/main/java/org/bouncycastle/asn1/x509/Certificate.java
deleted file mode 100644
index 4ca14d40..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/Certificate.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.x500.X500Name;
-
-/**
- * an X509Certificate structure.
- * <pre>
- * Certificate ::= SEQUENCE {
- * tbsCertificate TBSCertificate,
- * signatureAlgorithm AlgorithmIdentifier,
- * signature BIT STRING
- * }
- * </pre>
- */
-public class Certificate
- extends ASN1Object
-{
- ASN1Sequence seq;
- TBSCertificate tbsCert;
- AlgorithmIdentifier sigAlgId;
- DERBitString sig;
-
- public static Certificate getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static Certificate getInstance(
- Object obj)
- {
- if (obj instanceof Certificate)
- {
- return (Certificate)obj;
- }
- else if (obj != null)
- {
- return new Certificate(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private Certificate(
- ASN1Sequence seq)
- {
- this.seq = seq;
-
- //
- // correct x509 certficate
- //
- if (seq.size() == 3)
- {
- tbsCert = TBSCertificate.getInstance(seq.getObjectAt(0));
- sigAlgId = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
-
- sig = DERBitString.getInstance(seq.getObjectAt(2));
- }
- else
- {
- throw new IllegalArgumentException("sequence wrong size for a certificate");
- }
- }
-
- public TBSCertificate getTBSCertificate()
- {
- return tbsCert;
- }
-
- public ASN1Integer getVersion()
- {
- return tbsCert.getVersion();
- }
-
- public int getVersionNumber()
- {
- return tbsCert.getVersionNumber();
- }
-
- public ASN1Integer getSerialNumber()
- {
- return tbsCert.getSerialNumber();
- }
-
- public X500Name getIssuer()
- {
- return tbsCert.getIssuer();
- }
-
- public Time getStartDate()
- {
- return tbsCert.getStartDate();
- }
-
- public Time getEndDate()
- {
- return tbsCert.getEndDate();
- }
-
- public X500Name getSubject()
- {
- return tbsCert.getSubject();
- }
-
- public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
- {
- return tbsCert.getSubjectPublicKeyInfo();
- }
-
- public AlgorithmIdentifier getSignatureAlgorithm()
- {
- return sigAlgId;
- }
-
- public DERBitString getSignature()
- {
- return sig;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return seq;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/CertificateList.java b/core/src/main/java/org/bouncycastle/asn1/x509/CertificateList.java
deleted file mode 100644
index 61d7d4a5..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/CertificateList.java
+++ /dev/null
@@ -1,144 +0,0 @@
-
-package org.bouncycastle.asn1.x509;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x500.X500Name;
-
-/**
- * PKIX RFC-2459
- *
- * The X.509 v2 CRL syntax is as follows. For signature calculation,
- * the data that is to be signed is ASN.1 DER encoded.
- *
- * <pre>
- * CertificateList ::= SEQUENCE {
- * tbsCertList TBSCertList,
- * signatureAlgorithm AlgorithmIdentifier,
- * signatureValue BIT STRING }
- * </pre>
- */
-public class CertificateList
- extends ASN1Object
-{
- TBSCertList tbsCertList;
- AlgorithmIdentifier sigAlgId;
- DERBitString sig;
- boolean isHashCodeSet = false;
- int hashCodeValue;
-
- public static CertificateList getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static CertificateList getInstance(
- Object obj)
- {
- if (obj instanceof CertificateList)
- {
- return (CertificateList)obj;
- }
- else if (obj != null)
- {
- return new CertificateList(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- /**
- * @deprecated use getInstance() method.
- * @param seq
- */
- public CertificateList(
- ASN1Sequence seq)
- {
- if (seq.size() == 3)
- {
- tbsCertList = TBSCertList.getInstance(seq.getObjectAt(0));
- sigAlgId = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
- sig = DERBitString.getInstance(seq.getObjectAt(2));
- }
- else
- {
- throw new IllegalArgumentException("sequence wrong size for CertificateList");
- }
- }
-
- public TBSCertList getTBSCertList()
- {
- return tbsCertList;
- }
-
- public TBSCertList.CRLEntry[] getRevokedCertificates()
- {
- return tbsCertList.getRevokedCertificates();
- }
-
- public Enumeration getRevokedCertificateEnumeration()
- {
- return tbsCertList.getRevokedCertificateEnumeration();
- }
-
- public AlgorithmIdentifier getSignatureAlgorithm()
- {
- return sigAlgId;
- }
-
- public DERBitString getSignature()
- {
- return sig;
- }
-
- public int getVersionNumber()
- {
- return tbsCertList.getVersionNumber();
- }
-
- public X500Name getIssuer()
- {
- return tbsCertList.getIssuer();
- }
-
- public Time getThisUpdate()
- {
- return tbsCertList.getThisUpdate();
- }
-
- public Time getNextUpdate()
- {
- return tbsCertList.getNextUpdate();
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(tbsCertList);
- v.add(sigAlgId);
- v.add(sig);
-
- return new DERSequence(v);
- }
-
- public int hashCode()
- {
- if (!isHashCodeSet)
- {
- hashCodeValue = super.hashCode();
- isHashCodeSet = true;
- }
-
- return hashCodeValue;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/CertificatePair.java b/core/src/main/java/org/bouncycastle/asn1/x509/CertificatePair.java
deleted file mode 100644
index 4a70f2df..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/CertificatePair.java
+++ /dev/null
@@ -1,168 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * This class helps to support crossCerfificatePairs in a LDAP directory
- * according RFC 2587
- *
- * <pre>
- * crossCertificatePairATTRIBUTE::={
- * WITH SYNTAX CertificatePair
- * EQUALITY MATCHING RULE certificatePairExactMatch
- * ID joint-iso-ccitt(2) ds(5) attributeType(4) crossCertificatePair(40)}
- * </pre>
- *
- * <blockquote> The forward elements of the crossCertificatePair attribute of a
- * CA's directory entry shall be used to store all, except self-issued
- * certificates issued to this CA. Optionally, the reverse elements of the
- * crossCertificatePair attribute, of a CA's directory entry may contain a
- * subset of certificates issued by this CA to other CAs. When both the forward
- * and the reverse elements are present in a single attribute value, issuer name
- * in one certificate shall match the subject name in the other and vice versa,
- * and the subject public key in one certificate shall be capable of verifying
- * the digital signature on the other certificate and vice versa.
- *
- * When a reverse element is present, the forward element value and the reverse
- * element value need not be stored in the same attribute value; in other words,
- * they can be stored in either a single attribute value or two attribute
- * values. </blockquote>
- *
- * <pre>
- * CertificatePair ::= SEQUENCE {
- * forward [0] Certificate OPTIONAL,
- * reverse [1] Certificate OPTIONAL,
- * -- at least one of the pair shall be present -- }
- * </pre>
- */
-public class CertificatePair
- extends ASN1Object
-{
- private Certificate forward;
-
- private Certificate reverse;
-
- public static CertificatePair getInstance(Object obj)
- {
- if (obj == null || obj instanceof CertificatePair)
- {
- return (CertificatePair)obj;
- }
-
- if (obj instanceof ASN1Sequence)
- {
- return new CertificatePair((ASN1Sequence)obj);
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: "
- + obj.getClass().getName());
- }
-
- /**
- * Constructor from ASN1Sequence.
- * <p/>
- * The sequence is of type CertificatePair:
- * <p/>
- * <pre>
- * CertificatePair ::= SEQUENCE {
- * forward [0] Certificate OPTIONAL,
- * reverse [1] Certificate OPTIONAL,
- * -- at least one of the pair shall be present -- }
- * </pre>
- *
- * @param seq The ASN.1 sequence.
- */
- private CertificatePair(ASN1Sequence seq)
- {
- if (seq.size() != 1 && seq.size() != 2)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
-
- Enumeration e = seq.getObjects();
-
- while (e.hasMoreElements())
- {
- ASN1TaggedObject o = ASN1TaggedObject.getInstance(e.nextElement());
- if (o.getTagNo() == 0)
- {
- forward = Certificate.getInstance(o, true);
- }
- else if (o.getTagNo() == 1)
- {
- reverse = Certificate.getInstance(o, true);
- }
- else
- {
- throw new IllegalArgumentException("Bad tag number: "
- + o.getTagNo());
- }
- }
- }
-
- /**
- * Constructor from a given details.
- *
- * @param forward Certificates issued to this CA.
- * @param reverse Certificates issued by this CA to other CAs.
- */
- public CertificatePair(Certificate forward, Certificate reverse)
- {
- this.forward = forward;
- this.reverse = reverse;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <p>
- * Returns:
- * <pre>
- * CertificatePair ::= SEQUENCE {
- * forward [0] Certificate OPTIONAL,
- * reverse [1] Certificate OPTIONAL,
- * -- at least one of the pair shall be present -- }
- * </pre>
- *
- * @return a ASN1Primitive
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector vec = new ASN1EncodableVector();
-
- if (forward != null)
- {
- vec.add(new DERTaggedObject(0, forward));
- }
- if (reverse != null)
- {
- vec.add(new DERTaggedObject(1, reverse));
- }
-
- return new DERSequence(vec);
- }
-
- /**
- * @return Returns the forward.
- */
- public Certificate getForward()
- {
- return forward;
- }
-
- /**
- * @return Returns the reverse.
- */
- public Certificate getReverse()
- {
- return reverse;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/CertificatePolicies.java b/core/src/main/java/org/bouncycastle/asn1/x509/CertificatePolicies.java
deleted file mode 100644
index 4d7fc0b0..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/CertificatePolicies.java
+++ /dev/null
@@ -1,124 +0,0 @@
-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;
-import org.bouncycastle.asn1.DERSequence;
-
-public class CertificatePolicies
- extends ASN1Object
-{
- private final PolicyInformation[] policyInformation;
-
- public static CertificatePolicies getInstance(
- Object obj)
- {
- if (obj instanceof CertificatePolicies)
- {
- return (CertificatePolicies)obj;
- }
-
- if (obj != null)
- {
- return new CertificatePolicies(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public static CertificatePolicies getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- /**
- * 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.
- */
- public CertificatePolicies(
- PolicyInformation name)
- {
- this.policyInformation = new PolicyInformation[] { name };
- }
-
- public CertificatePolicies(
- PolicyInformation[] policyInformation)
- {
- this.policyInformation = policyInformation;
- }
-
- private CertificatePolicies(
- ASN1Sequence seq)
- {
- this.policyInformation = new PolicyInformation[seq.size()];
-
- for (int i = 0; i != seq.size(); i++)
- {
- policyInformation[i] = PolicyInformation.getInstance(seq.getObjectAt(i));
- }
- }
-
- public PolicyInformation[] getPolicyInformation()
- {
- PolicyInformation[] tmp = new PolicyInformation[policyInformation.length];
-
- System.arraycopy(policyInformation, 0, tmp, 0, policyInformation.length);
-
- 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>
- * CertificatePolicies ::= SEQUENCE SIZE {1..MAX} OF PolicyInformation
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- return new DERSequence(policyInformation);
- }
-
- public String toString()
- {
- String p = null;
- for (int i = 0; i < policyInformation.length; i++)
- {
- if (p != null)
- {
- p += ", ";
- }
- p += policyInformation[i];
- }
-
- return "CertificatePolicies: " + p;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/DSAParameter.java b/core/src/main/java/org/bouncycastle/asn1/x509/DSAParameter.java
deleted file mode 100644
index 056798ca..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/DSAParameter.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-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;
-
-public class DSAParameter
- extends ASN1Object
-{
- ASN1Integer p, q, g;
-
- public static DSAParameter getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static DSAParameter getInstance(
- Object obj)
- {
- if (obj instanceof DSAParameter)
- {
- return (DSAParameter)obj;
- }
-
- if(obj != null)
- {
- return new DSAParameter(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public DSAParameter(
- BigInteger p,
- BigInteger q,
- BigInteger g)
- {
- this.p = new ASN1Integer(p);
- this.q = new ASN1Integer(q);
- this.g = new ASN1Integer(g);
- }
-
- private DSAParameter(
- ASN1Sequence seq)
- {
- if (seq.size() != 3)
- {
- throw new IllegalArgumentException("Bad sequence size: " + seq.size());
- }
-
- Enumeration e = seq.getObjects();
-
- p = ASN1Integer.getInstance(e.nextElement());
- q = ASN1Integer.getInstance(e.nextElement());
- g = ASN1Integer.getInstance(e.nextElement());
- }
-
- public BigInteger getP()
- {
- return p.getPositiveValue();
- }
-
- public BigInteger getQ()
- {
- return q.getPositiveValue();
- }
-
- public BigInteger getG()
- {
- return g.getPositiveValue();
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(p);
- v.add(q);
- v.add(g);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/DigestInfo.java b/core/src/main/java/org/bouncycastle/asn1/x509/DigestInfo.java
deleted file mode 100644
index fd17f1b5..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/DigestInfo.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * The DigestInfo object.
- * <pre>
- * DigestInfo::=SEQUENCE{
- * digestAlgorithm AlgorithmIdentifier,
- * digest OCTET STRING }
- * </pre>
- */
-public class DigestInfo
- extends ASN1Object
-{
- private byte[] digest;
- private AlgorithmIdentifier algId;
-
- public static DigestInfo getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static DigestInfo getInstance(
- Object obj)
- {
- if (obj instanceof DigestInfo)
- {
- return (DigestInfo)obj;
- }
- else if (obj != null)
- {
- return new DigestInfo(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public DigestInfo(
- AlgorithmIdentifier algId,
- byte[] digest)
- {
- this.digest = digest;
- this.algId = algId;
- }
-
- public DigestInfo(
- ASN1Sequence obj)
- {
- Enumeration e = obj.getObjects();
-
- algId = AlgorithmIdentifier.getInstance(e.nextElement());
- digest = ASN1OctetString.getInstance(e.nextElement()).getOctets();
- }
-
- public AlgorithmIdentifier getAlgorithmId()
- {
- return algId;
- }
-
- public byte[] getDigest()
- {
- return digest;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(algId);
- v.add(new DEROctetString(digest));
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/DisplayText.java b/core/src/main/java/org/bouncycastle/asn1/x509/DisplayText.java
deleted file mode 100644
index acebcbe7..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/DisplayText.java
+++ /dev/null
@@ -1,165 +0,0 @@
-
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1String;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBMPString;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DERUTF8String;
-import org.bouncycastle.asn1.DERVisibleString;
-
-/**
- * <code>DisplayText</code> class, used in
- * <code>CertificatePolicies</code> X509 V3 extensions (in policy qualifiers).
- *
- * <p>It stores a string in a chosen encoding.
- * <pre>
- * DisplayText ::= CHOICE {
- * ia5String IA5String (SIZE (1..200)),
- * visibleString VisibleString (SIZE (1..200)),
- * bmpString BMPString (SIZE (1..200)),
- * utf8String UTF8String (SIZE (1..200)) }
- * </pre>
- * @see PolicyQualifierInfo
- * @see PolicyInformation
- */
-public class DisplayText
- extends ASN1Object
- implements ASN1Choice
-{
- /**
- * Constant corresponding to ia5String encoding.
- *
- */
- public static final int CONTENT_TYPE_IA5STRING = 0;
- /**
- * Constant corresponding to bmpString encoding.
- *
- */
- public static final int CONTENT_TYPE_BMPSTRING = 1;
- /**
- * Constant corresponding to utf8String encoding.
- *
- */
- public static final int CONTENT_TYPE_UTF8STRING = 2;
- /**
- * Constant corresponding to visibleString encoding.
- *
- */
- public static final int CONTENT_TYPE_VISIBLESTRING = 3;
-
- /**
- * Describe constant <code>DISPLAY_TEXT_MAXIMUM_SIZE</code> here.
- *
- */
- public static final int DISPLAY_TEXT_MAXIMUM_SIZE = 200;
-
- int contentType;
- ASN1String contents;
-
- /**
- * Creates a new <code>DisplayText</code> instance.
- *
- * @param type the desired encoding type for the text.
- * @param text the text to store. Strings longer than 200
- * characters are truncated.
- */
- public DisplayText(int type, String text)
- {
- if (text.length() > DISPLAY_TEXT_MAXIMUM_SIZE)
- {
- // RFC3280 limits these strings to 200 chars
- // truncate the string
- text = text.substring (0, DISPLAY_TEXT_MAXIMUM_SIZE);
- }
-
- contentType = type;
- switch (type)
- {
- case CONTENT_TYPE_IA5STRING:
- contents = new DERIA5String(text);
- break;
- case CONTENT_TYPE_UTF8STRING:
- contents = new DERUTF8String(text);
- break;
- case CONTENT_TYPE_VISIBLESTRING:
- contents = new DERVisibleString(text);
- break;
- case CONTENT_TYPE_BMPSTRING:
- contents = new DERBMPString(text);
- break;
- default:
- contents = new DERUTF8String(text);
- break;
- }
- }
-
- /**
- * Creates a new <code>DisplayText</code> instance.
- *
- * @param text the text to encapsulate. Strings longer than 200
- * characters are truncated.
- */
- public DisplayText(String text)
- {
- // by default use UTF8String
- if (text.length() > DISPLAY_TEXT_MAXIMUM_SIZE)
- {
- text = text.substring(0, DISPLAY_TEXT_MAXIMUM_SIZE);
- }
-
- contentType = CONTENT_TYPE_UTF8STRING;
- contents = new DERUTF8String(text);
- }
-
- /**
- * Creates a new <code>DisplayText</code> instance.
- * <p>Useful when reading back a <code>DisplayText</code> class
- * from it's ASN1Encodable/DEREncodable form.
- *
- * @param de a <code>DEREncodable</code> instance.
- */
- private DisplayText(ASN1String de)
- {
- contents = de;
- }
-
- public static DisplayText getInstance(Object obj)
- {
- if (obj instanceof ASN1String)
- {
- return new DisplayText((ASN1String)obj);
- }
- else if (obj == null || obj instanceof DisplayText)
- {
- return (DisplayText)obj;
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- public static DisplayText getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject()); // must be explicitly tagged
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return (ASN1Primitive)contents;
- }
-
- /**
- * Returns the stored <code>String</code> object.
- *
- * @return the stored text as a <code>String</code>.
- */
- public String getString()
- {
- return contents.getString();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/DistributionPoint.java b/core/src/main/java/org/bouncycastle/asn1/x509/DistributionPoint.java
deleted file mode 100644
index ab73dfbb..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/DistributionPoint.java
+++ /dev/null
@@ -1,158 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * The DistributionPoint object.
- * <pre>
- * DistributionPoint ::= SEQUENCE {
- * distributionPoint [0] DistributionPointName OPTIONAL,
- * reasons [1] ReasonFlags OPTIONAL,
- * cRLIssuer [2] GeneralNames OPTIONAL
- * }
- * </pre>
- */
-public class DistributionPoint
- extends ASN1Object
-{
- DistributionPointName distributionPoint;
- ReasonFlags reasons;
- GeneralNames cRLIssuer;
-
- public static DistributionPoint getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static DistributionPoint getInstance(
- Object obj)
- {
- if(obj == null || obj instanceof DistributionPoint)
- {
- return (DistributionPoint)obj;
- }
-
- if(obj instanceof ASN1Sequence)
- {
- return new DistributionPoint((ASN1Sequence)obj);
- }
-
- throw new IllegalArgumentException("Invalid DistributionPoint: " + obj.getClass().getName());
- }
-
- public DistributionPoint(
- ASN1Sequence seq)
- {
- for (int i = 0; i != seq.size(); i++)
- {
- ASN1TaggedObject t = ASN1TaggedObject.getInstance(seq.getObjectAt(i));
- switch (t.getTagNo())
- {
- case 0:
- distributionPoint = DistributionPointName.getInstance(t, true);
- break;
- case 1:
- reasons = new ReasonFlags(DERBitString.getInstance(t, false));
- break;
- case 2:
- cRLIssuer = GeneralNames.getInstance(t, false);
- }
- }
- }
-
- public DistributionPoint(
- DistributionPointName distributionPoint,
- ReasonFlags reasons,
- GeneralNames cRLIssuer)
- {
- this.distributionPoint = distributionPoint;
- this.reasons = reasons;
- this.cRLIssuer = cRLIssuer;
- }
-
- public DistributionPointName getDistributionPoint()
- {
- return distributionPoint;
- }
-
- public ReasonFlags getReasons()
- {
- return reasons;
- }
-
- public GeneralNames getCRLIssuer()
- {
- return cRLIssuer;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (distributionPoint != null)
- {
- //
- // as this is a CHOICE it must be explicitly tagged
- //
- v.add(new DERTaggedObject(0, distributionPoint));
- }
-
- if (reasons != null)
- {
- v.add(new DERTaggedObject(false, 1, reasons));
- }
-
- if (cRLIssuer != null)
- {
- v.add(new DERTaggedObject(false, 2, cRLIssuer));
- }
-
- return new DERSequence(v);
- }
-
- public String toString()
- {
- String sep = System.getProperty("line.separator");
- StringBuffer buf = new StringBuffer();
- buf.append("DistributionPoint: [");
- buf.append(sep);
- if (distributionPoint != null)
- {
- appendObject(buf, sep, "distributionPoint", distributionPoint.toString());
- }
- if (reasons != null)
- {
- appendObject(buf, sep, "reasons", reasons.toString());
- }
- if (cRLIssuer != null)
- {
- appendObject(buf, sep, "cRLIssuer", cRLIssuer.toString());
- }
- buf.append("]");
- buf.append(sep);
- return buf.toString();
- }
-
- private void appendObject(StringBuffer buf, String sep, String name, String value)
- {
- String indent = " ";
-
- buf.append(indent);
- buf.append(name);
- buf.append(":");
- buf.append(sep);
- buf.append(indent);
- buf.append(indent);
- buf.append(value);
- buf.append(sep);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/DistributionPointName.java b/core/src/main/java/org/bouncycastle/asn1/x509/DistributionPointName.java
deleted file mode 100644
index ee06efdc..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/DistributionPointName.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * The DistributionPointName object.
- * <pre>
- * DistributionPointName ::= CHOICE {
- * fullName [0] GeneralNames,
- * nameRelativeToCRLIssuer [1] RDN
- * }
- * </pre>
- */
-public class DistributionPointName
- extends ASN1Object
- implements ASN1Choice
-{
- ASN1Encodable name;
- int type;
-
- public static final int FULL_NAME = 0;
- public static final int NAME_RELATIVE_TO_CRL_ISSUER = 1;
-
- public static DistributionPointName getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1TaggedObject.getInstance(obj, true));
- }
-
- public static DistributionPointName getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DistributionPointName)
- {
- return (DistributionPointName)obj;
- }
- else if (obj instanceof ASN1TaggedObject)
- {
- return new DistributionPointName((ASN1TaggedObject)obj);
- }
-
- throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
- }
-
- public DistributionPointName(
- int type,
- ASN1Encodable name)
- {
- this.type = type;
- this.name = name;
- }
-
- public DistributionPointName(
- GeneralNames name)
- {
- this(FULL_NAME, name);
- }
-
- /**
- * Return the tag number applying to the underlying choice.
- *
- * @return the tag number for this point name.
- */
- public int getType()
- {
- return this.type;
- }
-
- /**
- * Return the tagged object inside the distribution point name.
- *
- * @return the underlying choice item.
- */
- public ASN1Encodable getName()
- {
- return (ASN1Encodable)name;
- }
-
- public DistributionPointName(
- ASN1TaggedObject obj)
- {
- this.type = obj.getTagNo();
-
- if (type == 0)
- {
- this.name = GeneralNames.getInstance(obj, false);
- }
- else
- {
- this.name = ASN1Set.getInstance(obj, false);
- }
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return new DERTaggedObject(false, type, name);
- }
-
- public String toString()
- {
- String sep = System.getProperty("line.separator");
- StringBuffer buf = new StringBuffer();
- buf.append("DistributionPointName: [");
- buf.append(sep);
- if (type == FULL_NAME)
- {
- appendObject(buf, sep, "fullName", name.toString());
- }
- else
- {
- appendObject(buf, sep, "nameRelativeToCRLIssuer", name.toString());
- }
- buf.append("]");
- buf.append(sep);
- return buf.toString();
- }
-
- private void appendObject(StringBuffer buf, String sep, String name, String value)
- {
- String indent = " ";
-
- buf.append(indent);
- buf.append(name);
- buf.append(":");
- buf.append(sep);
- buf.append(indent);
- buf.append(indent);
- buf.append(value);
- buf.append(sep);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/ExtendedKeyUsage.java b/core/src/main/java/org/bouncycastle/asn1/x509/ExtendedKeyUsage.java
deleted file mode 100644
index 84d21cac..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/ExtendedKeyUsage.java
+++ /dev/null
@@ -1,192 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * The extendedKeyUsage object.
- * <pre>
- * extendedKeyUsage ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
- * </pre>
- */
-public class ExtendedKeyUsage
- extends ASN1Object
-{
- 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)
- {
- 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)
- {
- if (obj instanceof ExtendedKeyUsage)
- {
- return (ExtendedKeyUsage)obj;
- }
- else if (obj != null)
- {
- return new ExtendedKeyUsage(ASN1Sequence.getInstance(obj));
- }
-
- 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)
- {
- this.seq = new DERSequence(usage);
-
- this.usageTable.put(usage, usage);
- }
-
- private ExtendedKeyUsage(
- ASN1Sequence seq)
- {
- this.seq = seq;
-
- Enumeration e = seq.getObjects();
-
- while (e.hasMoreElements())
- {
- ASN1Encodable o = (ASN1Encodable)e.nextElement();
- if (!(o.toASN1Primitive() instanceof ASN1ObjectIdentifier))
- {
- throw new IllegalArgumentException("Only ASN1ObjectIdentifiers allowed in ExtendedKeyUsage.");
- }
- this.usageTable.put(o, o);
- }
- }
-
- /**
- * Base constructor, from multiple KeyPurposeIds.
- *
- * @param usages an array of KeyPurposeIds.
- */
- public ExtendedKeyUsage(
- KeyPurposeId[] usages)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- for (int i = 0; i != usages.length; i++)
- {
- v.add(usages[i]);
- this.usageTable.put(usages[i], usages[i]);
- }
-
- this.seq = new DERSequence(v);
- }
-
- /**
- * @deprecated use KeyPurposeId[] constructor.
- */
- public ExtendedKeyUsage(
- Vector usages)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- Enumeration e = usages.elements();
-
- while (e.hasMoreElements())
- {
- KeyPurposeId o = KeyPurposeId.getInstance(e.nextElement());
-
- v.add(o);
- this.usageTable.put(o, o);
- }
-
- 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)
- {
- return (usageTable.get(keyPurposeId) != null);
- }
-
- /**
- * Returns all extended key usages.
- *
- * @return An array with all key purposes.
- */
- public KeyPurposeId[] getUsages()
- {
- KeyPurposeId[] temp = new KeyPurposeId[seq.size()];
-
- int i = 0;
- for (Enumeration it = seq.getObjects(); it.hasMoreElements();)
- {
- temp[i++] = KeyPurposeId.getInstance(it.nextElement());
- }
- 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/core/src/main/java/org/bouncycastle/asn1/x509/Extension.java b/core/src/main/java/org/bouncycastle/asn1/x509/Extension.java
deleted file mode 100644
index 4d566b18..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/Extension.java
+++ /dev/null
@@ -1,321 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Boolean;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * an object for the elements in the X.509 V3 extension block.
- */
-public class Extension
- extends ASN1Object
-{
- /**
- * Subject Directory Attributes
- */
- public static final ASN1ObjectIdentifier subjectDirectoryAttributes = new ASN1ObjectIdentifier("2.5.29.9");
-
- /**
- * Subject Key Identifier
- */
- public static final ASN1ObjectIdentifier subjectKeyIdentifier = new ASN1ObjectIdentifier("2.5.29.14");
-
- /**
- * Key Usage
- */
- public static final ASN1ObjectIdentifier keyUsage = new ASN1ObjectIdentifier("2.5.29.15");
-
- /**
- * Private Key Usage Period
- */
- public static final ASN1ObjectIdentifier privateKeyUsagePeriod = new ASN1ObjectIdentifier("2.5.29.16");
-
- /**
- * Subject Alternative Name
- */
- public static final ASN1ObjectIdentifier subjectAlternativeName = new ASN1ObjectIdentifier("2.5.29.17");
-
- /**
- * Issuer Alternative Name
- */
- public static final ASN1ObjectIdentifier issuerAlternativeName = new ASN1ObjectIdentifier("2.5.29.18");
-
- /**
- * Basic Constraints
- */
- public static final ASN1ObjectIdentifier basicConstraints = new ASN1ObjectIdentifier("2.5.29.19");
-
- /**
- * CRL Number
- */
- public static final ASN1ObjectIdentifier cRLNumber = new ASN1ObjectIdentifier("2.5.29.20");
-
- /**
- * Reason code
- */
- public static final ASN1ObjectIdentifier reasonCode = new ASN1ObjectIdentifier("2.5.29.21");
-
- /**
- * Hold Instruction Code
- */
- public static final ASN1ObjectIdentifier instructionCode = new ASN1ObjectIdentifier("2.5.29.23");
-
- /**
- * Invalidity Date
- */
- public static final ASN1ObjectIdentifier invalidityDate = new ASN1ObjectIdentifier("2.5.29.24");
-
- /**
- * Delta CRL indicator
- */
- public static final ASN1ObjectIdentifier deltaCRLIndicator = new ASN1ObjectIdentifier("2.5.29.27");
-
- /**
- * Issuing Distribution Point
- */
- public static final ASN1ObjectIdentifier issuingDistributionPoint = new ASN1ObjectIdentifier("2.5.29.28");
-
- /**
- * Certificate Issuer
- */
- public static final ASN1ObjectIdentifier certificateIssuer = new ASN1ObjectIdentifier("2.5.29.29");
-
- /**
- * Name Constraints
- */
- public static final ASN1ObjectIdentifier nameConstraints = new ASN1ObjectIdentifier("2.5.29.30");
-
- /**
- * CRL Distribution Points
- */
- public static final ASN1ObjectIdentifier cRLDistributionPoints = new ASN1ObjectIdentifier("2.5.29.31");
-
- /**
- * Certificate Policies
- */
- public static final ASN1ObjectIdentifier certificatePolicies = new ASN1ObjectIdentifier("2.5.29.32");
-
- /**
- * Policy Mappings
- */
- public static final ASN1ObjectIdentifier policyMappings = new ASN1ObjectIdentifier("2.5.29.33");
-
- /**
- * Authority Key Identifier
- */
- public static final ASN1ObjectIdentifier authorityKeyIdentifier = new ASN1ObjectIdentifier("2.5.29.35");
-
- /**
- * Policy Constraints
- */
- public static final ASN1ObjectIdentifier policyConstraints = new ASN1ObjectIdentifier("2.5.29.36");
-
- /**
- * Extended Key Usage
- */
- public static final ASN1ObjectIdentifier extendedKeyUsage = new ASN1ObjectIdentifier("2.5.29.37");
-
- /**
- * Freshest CRL
- */
- public static final ASN1ObjectIdentifier freshestCRL = new ASN1ObjectIdentifier("2.5.29.46");
-
- /**
- * Inhibit Any Policy
- */
- public static final ASN1ObjectIdentifier inhibitAnyPolicy = new ASN1ObjectIdentifier("2.5.29.54");
-
- /**
- * Authority Info Access
- */
- public static final ASN1ObjectIdentifier authorityInfoAccess = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.1");
-
- /**
- * Subject Info Access
- */
- public static final ASN1ObjectIdentifier subjectInfoAccess = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.11");
-
- /**
- * Logo Type
- */
- public static final ASN1ObjectIdentifier logoType = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.12");
-
- /**
- * BiometricInfo
- */
- public static final ASN1ObjectIdentifier biometricInfo = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.2");
-
- /**
- * QCStatements
- */
- public static final ASN1ObjectIdentifier qCStatements = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.3");
-
- /**
- * Audit identity extension in attribute certificates.
- */
- public static final ASN1ObjectIdentifier auditIdentity = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.4");
-
- /**
- * NoRevAvail extension in attribute certificates.
- */
- public static final ASN1ObjectIdentifier noRevAvail = new ASN1ObjectIdentifier("2.5.29.56");
-
- /**
- * TargetInformation extension in attribute certificates.
- */
- public static final ASN1ObjectIdentifier targetInformation = new ASN1ObjectIdentifier("2.5.29.55");
-
- private ASN1ObjectIdentifier extnId;
- private boolean critical;
- private ASN1OctetString value;
-
- public Extension(
- ASN1ObjectIdentifier extnId,
- ASN1Boolean critical,
- ASN1OctetString value)
- {
- this(extnId, critical.isTrue(), value);
- }
-
- public Extension(
- ASN1ObjectIdentifier extnId,
- boolean critical,
- byte[] value)
- {
- this(extnId, critical, new DEROctetString(value));
- }
-
- public Extension(
- ASN1ObjectIdentifier extnId,
- boolean critical,
- ASN1OctetString value)
- {
- this.extnId = extnId;
- this.critical = critical;
- this.value = value;
- }
-
- private Extension(ASN1Sequence seq)
- {
- if (seq.size() == 2)
- {
- this.extnId = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
- this.critical = false;
- this.value = ASN1OctetString.getInstance(seq.getObjectAt(1));
- }
- else if (seq.size() == 3)
- {
- this.extnId = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
- this.critical = ASN1Boolean.getInstance(seq.getObjectAt(1)).isTrue();
- this.value = ASN1OctetString.getInstance(seq.getObjectAt(2));
- }
- else
- {
- throw new IllegalArgumentException("Bad sequence size: " + seq.size());
- }
- }
-
- public static Extension getInstance(Object obj)
- {
- if (obj instanceof Extension)
- {
- return (Extension)obj;
- }
- else if (obj != null)
- {
- return new Extension(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public ASN1ObjectIdentifier getExtnId()
- {
- return extnId;
- }
-
- public boolean isCritical()
- {
- return critical;
- }
-
- public ASN1OctetString getExtnValue()
- {
- return value;
- }
-
- public ASN1Encodable getParsedValue()
- {
- return convertValueToObject(this);
- }
-
- public int hashCode()
- {
- if (this.isCritical())
- {
- return this.getExtnValue().hashCode() ^ this.getExtnId().hashCode();
- }
-
- return ~(this.getExtnValue().hashCode() ^ this.getExtnId().hashCode());
- }
-
- public boolean equals(
- Object o)
- {
- if (!(o instanceof Extension))
- {
- return false;
- }
-
- Extension other = (Extension)o;
-
- return other.getExtnId().equals(this.getExtnId())
- && other.getExtnValue().equals(this.getExtnValue())
- && (other.isCritical() == this.isCritical());
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(extnId);
-
- if (critical)
- {
- v.add(ASN1Boolean.getInstance(true));
- }
-
- v.add(value);
-
- return new DERSequence(v);
- }
-
- /**
- * Convert the value of the passed in extension to an object
- * @param ext the extension to parse
- * @return the object the value string contains
- * @exception IllegalArgumentException if conversion is not possible
- */
- private static ASN1Primitive convertValueToObject(
- Extension ext)
- throws IllegalArgumentException
- {
- try
- {
- return ASN1Primitive.fromByteArray(ext.getExtnValue().getOctets());
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("can't convert extension: " + e);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/Extensions.java b/core/src/main/java/org/bouncycastle/asn1/x509/Extensions.java
deleted file mode 100644
index 1aeed15d..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/Extensions.java
+++ /dev/null
@@ -1,221 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-
-public class Extensions
- extends ASN1Object
-{
- private Hashtable extensions = new Hashtable();
- private Vector ordering = new Vector();
-
- public static Extensions getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static Extensions getInstance(
- Object obj)
- {
- if (obj instanceof Extensions)
- {
- return (Extensions)obj;
- }
- else if (obj != null)
- {
- return new Extensions(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- /**
- * Constructor from ASN1Sequence.
- * <p/>
- * the extensions are a list of constructed sequences, either with (OID, OctetString) or (OID, Boolean, OctetString)
- */
- private Extensions(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- while (e.hasMoreElements())
- {
- Extension ext = Extension.getInstance(e.nextElement());
-
- extensions.put(ext.getExtnId(), ext);
- ordering.addElement(ext.getExtnId());
- }
- }
-
- /**
- * Base Constructor
- *
- * @param extension a single extension.
- */
- public Extensions(
- Extension extension)
- {
- this.ordering.addElement(extension.getExtnId());
- this.extensions.put(extension.getExtnId(), extension);
- }
-
- /**
- * Base Constructor
- *
- * @param extensions an array of extensions.
- */
- public Extensions(
- Extension[] extensions)
- {
- for (int i = 0; i != extensions.length; i++)
- {
- Extension ext = extensions[i];
-
- this.ordering.addElement(ext.getExtnId());
- this.extensions.put(ext.getExtnId(), ext);
- }
- }
-
- /**
- * return an Enumeration of the extension field's object ids.
- */
- public Enumeration oids()
- {
- return ordering.elements();
- }
-
- /**
- * return the extension represented by the object identifier
- * passed in.
- *
- * @return the extension if it's present, null otherwise.
- */
- public Extension getExtension(
- ASN1ObjectIdentifier oid)
- {
- return (Extension)extensions.get(oid);
- }
-
- /**
- * return the parsed value of the extension represented by the object identifier
- * passed in.
- *
- * @return the parsed value of the extension if it's present, null otherwise.
- */
- public ASN1Encodable getExtensionParsedValue(ASN1ObjectIdentifier oid)
- {
- Extension ext = this.getExtension(oid);
-
- if (ext != null)
- {
- return ext.getParsedValue();
- }
-
- return null;
- }
-
- /**
- * <pre>
- * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
- *
- * Extension ::= SEQUENCE {
- * extnId EXTENSION.&amp;id ({ExtensionSet}),
- * critical BOOLEAN DEFAULT FALSE,
- * extnValue OCTET STRING }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector vec = new ASN1EncodableVector();
- Enumeration e = ordering.elements();
-
- while (e.hasMoreElements())
- {
- ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
- Extension ext = (Extension)extensions.get(oid);
-
- vec.add(ext);
- }
-
- return new DERSequence(vec);
- }
-
- public boolean equivalent(
- Extensions other)
- {
- if (extensions.size() != other.extensions.size())
- {
- return false;
- }
-
- Enumeration e1 = extensions.keys();
-
- while (e1.hasMoreElements())
- {
- Object key = e1.nextElement();
-
- if (!extensions.get(key).equals(other.extensions.get(key)))
- {
- return false;
- }
- }
-
- return true;
- }
-
- public ASN1ObjectIdentifier[] getExtensionOIDs()
- {
- return toOidArray(ordering);
- }
-
- public ASN1ObjectIdentifier[] getNonCriticalExtensionOIDs()
- {
- return getExtensionOIDs(false);
- }
-
- public ASN1ObjectIdentifier[] getCriticalExtensionOIDs()
- {
- return getExtensionOIDs(true);
- }
-
- private ASN1ObjectIdentifier[] getExtensionOIDs(boolean isCritical)
- {
- Vector oidVec = new Vector();
-
- for (int i = 0; i != ordering.size(); i++)
- {
- Object oid = ordering.elementAt(i);
-
- if (((Extension)extensions.get(oid)).isCritical() == isCritical)
- {
- oidVec.addElement(oid);
- }
- }
-
- return toOidArray(oidVec);
- }
-
- private ASN1ObjectIdentifier[] toOidArray(Vector oidVec)
- {
- ASN1ObjectIdentifier[] oids = new ASN1ObjectIdentifier[oidVec.size()];
-
- for (int i = 0; i != oids.length; i++)
- {
- oids[i] = (ASN1ObjectIdentifier)oidVec.elementAt(i);
- }
- return oids;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/ExtensionsGenerator.java b/core/src/main/java/org/bouncycastle/asn1/x509/ExtensionsGenerator.java
deleted file mode 100644
index 270ef1c4..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/ExtensionsGenerator.java
+++ /dev/null
@@ -1,94 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.io.IOException;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Encoding;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.DEROctetString;
-
-/**
- * Generator for X.509 extensions
- */
-public class ExtensionsGenerator
-{
- private Hashtable extensions = new Hashtable();
- private Vector extOrdering = new Vector();
-
- /**
- * Reset the generator
- */
- public void reset()
- {
- extensions = new Hashtable();
- extOrdering = new Vector();
- }
-
- /**
- * Add an extension with the given oid and the passed in value to be included
- * in the OCTET STRING associated with the extension.
- *
- * @param oid OID for the extension.
- * @param critical true if critical, false otherwise.
- * @param value the ASN.1 object to be included in the extension.
- */
- public void addExtension(
- ASN1ObjectIdentifier oid,
- boolean critical,
- ASN1Encodable value)
- throws IOException
- {
- this.addExtension(oid, critical, value.toASN1Primitive().getEncoded(ASN1Encoding.DER));
- }
-
- /**
- * Add an extension with the given oid and the passed in byte array to be wrapped in the
- * OCTET STRING associated with the extension.
- *
- * @param oid OID for the extension.
- * @param critical true if critical, false otherwise.
- * @param value the byte array to be wrapped.
- */
- public void addExtension(
- ASN1ObjectIdentifier oid,
- boolean critical,
- byte[] value)
- {
- if (extensions.containsKey(oid))
- {
- throw new IllegalArgumentException("extension " + oid + " already added");
- }
-
- extOrdering.addElement(oid);
- extensions.put(oid, new Extension(oid, critical, new DEROctetString(value)));
- }
-
- /**
- * Return true if there are no extension present in this generator.
- *
- * @return true if empty, false otherwise
- */
- public boolean isEmpty()
- {
- return extOrdering.isEmpty();
- }
-
- /**
- * Generate an Extensions object based on the current state of the generator.
- *
- * @return an X09Extensions object.
- */
- public Extensions generate()
- {
- Extension[] exts = new Extension[extOrdering.size()];
-
- for (int i = 0; i != extOrdering.size(); i++)
- {
- exts[i] = (Extension)extensions.get(extOrdering.elementAt(i));
- }
-
- return new Extensions(exts);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/GeneralName.java b/core/src/main/java/org/bouncycastle/asn1/x509/GeneralName.java
deleted file mode 100644
index 1829ecd2..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/GeneralName.java
+++ /dev/null
@@ -1,439 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.io.IOException;
-import java.util.StringTokenizer;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.util.IPAddress;
-
-/**
- * The GeneralName object.
- * <pre>
- * GeneralName ::= CHOICE {
- * otherName [0] OtherName,
- * rfc822Name [1] IA5String,
- * dNSName [2] IA5String,
- * x400Address [3] ORAddress,
- * directoryName [4] Name,
- * ediPartyName [5] EDIPartyName,
- * uniformResourceIdentifier [6] IA5String,
- * iPAddress [7] OCTET STRING,
- * registeredID [8] OBJECT IDENTIFIER}
- *
- * OtherName ::= SEQUENCE {
- * type-id OBJECT IDENTIFIER,
- * value [0] EXPLICIT ANY DEFINED BY type-id }
- *
- * EDIPartyName ::= SEQUENCE {
- * nameAssigner [0] DirectoryString OPTIONAL,
- * partyName [1] DirectoryString }
- *
- * Name ::= CHOICE { RDNSequence }
- * </pre>
- */
-public class GeneralName
- extends ASN1Object
- implements ASN1Choice
-{
- public static final int otherName = 0;
- public static final int rfc822Name = 1;
- public static final int dNSName = 2;
- public static final int x400Address = 3;
- public static final int directoryName = 4;
- public static final int ediPartyName = 5;
- public static final int uniformResourceIdentifier = 6;
- public static final int iPAddress = 7;
- public static final int registeredID = 8;
-
- private ASN1Encodable obj;
- private int tag;
-
- /**
- * @deprecated use X500Name constructor.
- * @param dirName
- */
- public GeneralName(
- X509Name dirName)
- {
- this.obj = X500Name.getInstance(dirName);
- this.tag = 4;
- }
-
- public GeneralName(
- X500Name dirName)
- {
- this.obj = dirName;
- this.tag = 4;
- }
-
- /**
- * When the subjectAltName extension contains an Internet mail address,
- * the address MUST be included as an rfc822Name. The format of an
- * rfc822Name is an "addr-spec" as defined in RFC 822 [RFC 822].
- *
- * When the subjectAltName extension contains a domain name service
- * label, the domain name MUST be stored in the dNSName (an IA5String).
- * The name MUST be in the "preferred name syntax," as specified by RFC
- * 1034 [RFC 1034].
- *
- * When the subjectAltName extension contains a URI, the name MUST be
- * stored in the uniformResourceIdentifier (an IA5String). The name MUST
- * be a non-relative URL, and MUST follow the URL syntax and encoding
- * rules specified in [RFC 1738]. The name must include both a scheme
- * (e.g., "http" or "ftp") and a scheme-specific-part. The scheme-
- * specific-part must include a fully qualified domain name or IP
- * address as the host.
- *
- * When the subjectAltName extension contains a iPAddress, the address
- * MUST be stored in the octet string in "network byte order," as
- * specified in RFC 791 [RFC 791]. The least significant bit (LSB) of
- * each octet is the LSB of the corresponding byte in the network
- * address. For IP Version 4, as specified in RFC 791, the octet string
- * MUST contain exactly four octets. For IP Version 6, as specified in
- * RFC 1883, the octet string MUST contain exactly sixteen octets [RFC
- * 1883].
- */
- public GeneralName(
- int tag,
- ASN1Encodable name)
- {
- this.obj = name;
- this.tag = tag;
- }
-
- /**
- * Create a GeneralName for the given tag from the passed in String.
- * <p>
- * This constructor can handle:
- * <ul>
- * <li>rfc822Name
- * <li>iPAddress
- * <li>directoryName
- * <li>dNSName
- * <li>uniformResourceIdentifier
- * <li>registeredID
- * </ul>
- * For x400Address, otherName and ediPartyName there is no common string
- * format defined.
- * <p>
- * Note: A directory name can be encoded in different ways into a byte
- * representation. Be aware of this if the byte representation is used for
- * comparing results.
- *
- * @param tag tag number
- * @param name string representation of name
- * @throws IllegalArgumentException if the string encoding is not correct or * not supported.
- */
- public GeneralName(
- int tag,
- String name)
- {
- this.tag = tag;
-
- if (tag == rfc822Name || tag == dNSName || tag == uniformResourceIdentifier)
- {
- this.obj = new DERIA5String(name);
- }
- else if (tag == registeredID)
- {
- this.obj = new ASN1ObjectIdentifier(name);
- }
- else if (tag == directoryName)
- {
- this.obj = new X500Name(name);
- }
- else if (tag == iPAddress)
- {
- byte[] enc = toGeneralNameEncoding(name);
- if (enc != null)
- {
- this.obj = new DEROctetString(enc);
- }
- else
- {
- throw new IllegalArgumentException("IP Address is invalid");
- }
- }
- else
- {
- throw new IllegalArgumentException("can't process String for tag: " + tag);
- }
- }
-
- public static GeneralName getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof GeneralName)
- {
- return (GeneralName)obj;
- }
-
- if (obj instanceof ASN1TaggedObject)
- {
- ASN1TaggedObject tagObj = (ASN1TaggedObject)obj;
- int tag = tagObj.getTagNo();
-
- switch (tag)
- {
- case otherName:
- return new GeneralName(tag, ASN1Sequence.getInstance(tagObj, false));
- case rfc822Name:
- return new GeneralName(tag, DERIA5String.getInstance(tagObj, false));
- case dNSName:
- return new GeneralName(tag, DERIA5String.getInstance(tagObj, false));
- case x400Address:
- throw new IllegalArgumentException("unknown tag: " + tag);
- case directoryName:
- return new GeneralName(tag, X500Name.getInstance(tagObj, true));
- case ediPartyName:
- return new GeneralName(tag, ASN1Sequence.getInstance(tagObj, false));
- case uniformResourceIdentifier:
- return new GeneralName(tag, DERIA5String.getInstance(tagObj, false));
- case iPAddress:
- return new GeneralName(tag, ASN1OctetString.getInstance(tagObj, false));
- case registeredID:
- return new GeneralName(tag, ASN1ObjectIdentifier.getInstance(tagObj, false));
- }
- }
-
- if (obj instanceof byte[])
- {
- try
- {
- return getInstance(ASN1Primitive.fromByteArray((byte[])obj));
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("unable to parse encoded general name");
- }
- }
-
- throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
- }
-
- public static GeneralName getInstance(
- ASN1TaggedObject tagObj,
- boolean explicit)
- {
- return GeneralName.getInstance(ASN1TaggedObject.getInstance(tagObj, true));
- }
-
- public int getTagNo()
- {
- return tag;
- }
-
- public ASN1Encodable getName()
- {
- return obj;
- }
-
- public String toString()
- {
- StringBuffer buf = new StringBuffer();
-
- buf.append(tag);
- buf.append(": ");
- switch (tag)
- {
- case rfc822Name:
- case dNSName:
- case uniformResourceIdentifier:
- buf.append(DERIA5String.getInstance(obj).getString());
- break;
- case directoryName:
- buf.append(X500Name.getInstance(obj).toString());
- break;
- default:
- buf.append(obj.toString());
- }
- return buf.toString();
- }
-
- private byte[] toGeneralNameEncoding(String ip)
- {
- if (IPAddress.isValidIPv6WithNetmask(ip) || IPAddress.isValidIPv6(ip))
- {
- int slashIndex = ip.indexOf('/');
-
- if (slashIndex < 0)
- {
- byte[] addr = new byte[16];
- int[] parsedIp = parseIPv6(ip);
- copyInts(parsedIp, addr, 0);
-
- return addr;
- }
- else
- {
- byte[] addr = new byte[32];
- int[] parsedIp = parseIPv6(ip.substring(0, slashIndex));
- copyInts(parsedIp, addr, 0);
- String mask = ip.substring(slashIndex + 1);
- if (mask.indexOf(':') > 0)
- {
- parsedIp = parseIPv6(mask);
- }
- else
- {
- parsedIp = parseMask(mask);
- }
- copyInts(parsedIp, addr, 16);
-
- return addr;
- }
- }
- else if (IPAddress.isValidIPv4WithNetmask(ip) || IPAddress.isValidIPv4(ip))
- {
- int slashIndex = ip.indexOf('/');
-
- if (slashIndex < 0)
- {
- byte[] addr = new byte[4];
-
- parseIPv4(ip, addr, 0);
-
- return addr;
- }
- else
- {
- byte[] addr = new byte[8];
-
- parseIPv4(ip.substring(0, slashIndex), addr, 0);
-
- String mask = ip.substring(slashIndex + 1);
- if (mask.indexOf('.') > 0)
- {
- parseIPv4(mask, addr, 4);
- }
- else
- {
- parseIPv4Mask(mask, addr, 4);
- }
-
- return addr;
- }
- }
-
- return null;
- }
-
- private void parseIPv4Mask(String mask, byte[] addr, int offset)
- {
- int maskVal = Integer.parseInt(mask);
-
- for (int i = 0; i != maskVal; i++)
- {
- addr[(i / 8) + offset] |= 1 << (7 - (i % 8));
- }
- }
-
- private void parseIPv4(String ip, byte[] addr, int offset)
- {
- StringTokenizer sTok = new StringTokenizer(ip, "./");
- int index = 0;
-
- while (sTok.hasMoreTokens())
- {
- addr[offset + index++] = (byte)Integer.parseInt(sTok.nextToken());
- }
- }
-
- private int[] parseMask(String mask)
- {
- int[] res = new int[8];
- int maskVal = Integer.parseInt(mask);
-
- for (int i = 0; i != maskVal; i++)
- {
- res[i / 16] |= 1 << (15 - (i % 16));
- }
- return res;
- }
-
- private void copyInts(int[] parsedIp, byte[] addr, int offSet)
- {
- for (int i = 0; i != parsedIp.length; i++)
- {
- addr[(i * 2) + offSet] = (byte)(parsedIp[i] >> 8);
- addr[(i * 2 + 1) + offSet] = (byte)parsedIp[i];
- }
- }
-
- private int[] parseIPv6(String ip)
- {
- StringTokenizer sTok = new StringTokenizer(ip, ":", true);
- int index = 0;
- int[] val = new int[8];
-
- if (ip.charAt(0) == ':' && ip.charAt(1) == ':')
- {
- sTok.nextToken(); // skip the first one
- }
-
- int doubleColon = -1;
-
- while (sTok.hasMoreTokens())
- {
- String e = sTok.nextToken();
-
- if (e.equals(":"))
- {
- doubleColon = index;
- val[index++] = 0;
- }
- else
- {
- if (e.indexOf('.') < 0)
- {
- val[index++] = Integer.parseInt(e, 16);
- if (sTok.hasMoreTokens())
- {
- sTok.nextToken();
- }
- }
- else
- {
- StringTokenizer eTok = new StringTokenizer(e, ".");
-
- val[index++] = (Integer.parseInt(eTok.nextToken()) << 8) | Integer.parseInt(eTok.nextToken());
- val[index++] = (Integer.parseInt(eTok.nextToken()) << 8) | Integer.parseInt(eTok.nextToken());
- }
- }
- }
-
- if (index != val.length)
- {
- System.arraycopy(val, doubleColon, val, val.length - (index - doubleColon), index - doubleColon);
- for (int i = doubleColon; i != val.length - (index - doubleColon); i++)
- {
- val[i] = 0;
- }
- }
-
- return val;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- if (tag == directoryName) // directoryName is explicitly tagged as it is a CHOICE
- {
- return new DERTaggedObject(true, tag, obj);
- }
- else
- {
- return new DERTaggedObject(false, tag, obj);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/GeneralNames.java b/core/src/main/java/org/bouncycastle/asn1/x509/GeneralNames.java
deleted file mode 100644
index 7118d107..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/GeneralNames.java
+++ /dev/null
@@ -1,108 +0,0 @@
-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;
-import org.bouncycastle.asn1.DERSequence;
-
-public class GeneralNames
- extends ASN1Object
-{
- private final GeneralName[] names;
-
- public static GeneralNames getInstance(
- Object obj)
- {
- if (obj instanceof GeneralNames)
- {
- return (GeneralNames)obj;
- }
-
- if (obj != null)
- {
- return new GeneralNames(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public static GeneralNames getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static GeneralNames fromExtensions(Extensions extensions, ASN1ObjectIdentifier extOID)
- {
- return GeneralNames.getInstance(extensions.getExtensionParsedValue(extOID));
- }
-
- /**
- * Construct a GeneralNames object containing one GeneralName.
- *
- * @param name the name to be contained.
- */
- public GeneralNames(
- GeneralName name)
- {
- this.names = new GeneralName[] { name };
- }
-
-
- public GeneralNames(
- GeneralName[] names)
- {
- this.names = names;
- }
-
- private GeneralNames(
- ASN1Sequence seq)
- {
- this.names = new GeneralName[seq.size()];
-
- for (int i = 0; i != seq.size(); i++)
- {
- names[i] = GeneralName.getInstance(seq.getObjectAt(i));
- }
- }
-
- public GeneralName[] getNames()
- {
- GeneralName[] tmp = new GeneralName[names.length];
-
- System.arraycopy(names, 0, tmp, 0, names.length);
-
- return tmp;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * GeneralNames ::= SEQUENCE SIZE {1..MAX} OF GeneralName
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- return new DERSequence(names);
- }
-
- public String toString()
- {
- StringBuffer buf = new StringBuffer();
- String sep = System.getProperty("line.separator");
-
- buf.append("GeneralNames:");
- buf.append(sep);
-
- for (int i = 0; i != names.length; i++)
- {
- buf.append(" ");
- buf.append(names[i]);
- buf.append(sep);
- }
- return buf.toString();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/GeneralNamesBuilder.java b/core/src/main/java/org/bouncycastle/asn1/x509/GeneralNamesBuilder.java
deleted file mode 100644
index 14f0c2c1..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/GeneralNamesBuilder.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.util.Vector;
-
-public class GeneralNamesBuilder
-{
- private Vector names = new Vector();
-
- public GeneralNamesBuilder addNames(GeneralNames names)
- {
- GeneralName[] n = names.getNames();
-
- for (int i = 0; i != n.length; i++)
- {
- this.names.addElement(n[i]);
- }
-
- return this;
- }
-
- public GeneralNamesBuilder addName(GeneralName name)
- {
- names.addElement(name);
-
- return this;
- }
-
- public GeneralNames build()
- {
- GeneralName[] tmp = new GeneralName[names.size()];
-
- for (int i = 0; i != tmp.length; i++)
- {
- tmp[i] = (GeneralName)names.elementAt(i);
- }
-
- return new GeneralNames(tmp);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/GeneralSubtree.java b/core/src/main/java/org/bouncycastle/asn1/x509/GeneralSubtree.java
deleted file mode 100644
index bf72ce63..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/GeneralSubtree.java
+++ /dev/null
@@ -1,218 +0,0 @@
-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;
-
-/**
- * Class for containing a restriction object subtrees in NameConstraints. See
- * RFC 3280.
- *
- * <pre>
- *
- * GeneralSubtree ::= SEQUENCE
- * {
- * base GeneralName,
- * minimum [0] BaseDistance DEFAULT 0,
- * maximum [1] BaseDistance OPTIONAL
- * }
- * </pre>
- *
- * @see org.bouncycastle.asn1.x509.NameConstraints
- *
- */
-public class GeneralSubtree
- extends ASN1Object
-{
- private static final BigInteger ZERO = BigInteger.valueOf(0);
-
- private GeneralName base;
-
- private ASN1Integer minimum;
-
- private ASN1Integer maximum;
-
- private GeneralSubtree(
- ASN1Sequence seq)
- {
- base = GeneralName.getInstance(seq.getObjectAt(0));
-
- switch (seq.size())
- {
- case 1:
- break;
- case 2:
- ASN1TaggedObject o = ASN1TaggedObject.getInstance(seq.getObjectAt(1));
- switch (o.getTagNo())
- {
- case 0:
- minimum = ASN1Integer.getInstance(o, false);
- break;
- case 1:
- maximum = ASN1Integer.getInstance(o, false);
- break;
- default:
- throw new IllegalArgumentException("Bad tag number: "
- + o.getTagNo());
- }
- break;
- case 3:
- {
- {
- ASN1TaggedObject oMin = ASN1TaggedObject.getInstance(seq.getObjectAt(1));
- if (oMin.getTagNo() != 0)
- {
- throw new IllegalArgumentException("Bad tag number for 'minimum': " + oMin.getTagNo());
- }
- minimum = ASN1Integer.getInstance(oMin, false);
- }
-
- {
- ASN1TaggedObject oMax = ASN1TaggedObject.getInstance(seq.getObjectAt(2));
- if (oMax.getTagNo() != 1)
- {
- throw new IllegalArgumentException("Bad tag number for 'maximum': " + oMax.getTagNo());
- }
- maximum = ASN1Integer.getInstance(oMax, false);
- }
-
- break;
- }
- default:
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
- }
-
- /**
- * Constructor from a given details.
- *
- * According RFC 3280, the minimum and maximum fields are not used with any
- * name forms, thus minimum MUST be zero, and maximum MUST be absent.
- * <p>
- * If minimum is <code>null</code>, zero is assumed, if
- * maximum is <code>null</code>, maximum is absent.
- *
- * @param base
- * A restriction.
- * @param minimum
- * Minimum
- *
- * @param maximum
- * Maximum
- */
- public GeneralSubtree(
- GeneralName base,
- BigInteger minimum,
- BigInteger maximum)
- {
- this.base = base;
- if (maximum != null)
- {
- this.maximum = new ASN1Integer(maximum);
- }
- if (minimum == null)
- {
- this.minimum = null;
- }
- else
- {
- this.minimum = new ASN1Integer(minimum);
- }
- }
-
- public GeneralSubtree(GeneralName base)
- {
- this(base, null, null);
- }
-
- public static GeneralSubtree getInstance(
- ASN1TaggedObject o,
- boolean explicit)
- {
- return new GeneralSubtree(ASN1Sequence.getInstance(o, explicit));
- }
-
- public static GeneralSubtree getInstance(
- Object obj)
- {
- if (obj == null)
- {
- return null;
- }
-
- if (obj instanceof GeneralSubtree)
- {
- return (GeneralSubtree) obj;
- }
-
- return new GeneralSubtree(ASN1Sequence.getInstance(obj));
- }
-
- public GeneralName getBase()
- {
- return base;
- }
-
- public BigInteger getMinimum()
- {
- if (minimum == null)
- {
- return ZERO;
- }
-
- return minimum.getValue();
- }
-
- public BigInteger getMaximum()
- {
- if (maximum == null)
- {
- return null;
- }
-
- return maximum.getValue();
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- *
- * Returns:
- *
- * <pre>
- * GeneralSubtree ::= SEQUENCE
- * {
- * base GeneralName,
- * minimum [0] BaseDistance DEFAULT 0,
- * maximum [1] BaseDistance OPTIONAL
- * }
- * </pre>
- *
- * @return a ASN1Primitive
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(base);
-
- if (minimum != null && !minimum.getValue().equals(ZERO))
- {
- v.add(new DERTaggedObject(false, 0, minimum));
- }
-
- if (maximum != null)
- {
- v.add(new DERTaggedObject(false, 1, maximum));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/Holder.java b/core/src/main/java/org/bouncycastle/asn1/x509/Holder.java
deleted file mode 100644
index e854681f..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/Holder.java
+++ /dev/null
@@ -1,245 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * The Holder object.
- * <p>
- * For an v2 attribute certificate this is:
- *
- * <pre>
- * Holder ::= SEQUENCE {
- * baseCertificateID [0] IssuerSerial OPTIONAL,
- * -- the issuer and serial number of
- * -- the holder's Public Key Certificate
- * entityName [1] GeneralNames OPTIONAL,
- * -- the name of the claimant or role
- * objectDigestInfo [2] ObjectDigestInfo OPTIONAL
- * -- used to directly authenticate the holder,
- * -- for example, an executable
- * }
- * </pre>
- *
- * <p>
- * For an v1 attribute certificate this is:
- *
- * <pre>
- * subject CHOICE {
- * baseCertificateID [0] EXPLICIT IssuerSerial,
- * -- associated with a Public Key Certificate
- * subjectName [1] EXPLICIT GeneralNames },
- * -- associated with a name
- * </pre>
- */
-public class Holder
- extends ASN1Object
-{
- public static final int V1_CERTIFICATE_HOLDER = 0;
- public static final int V2_CERTIFICATE_HOLDER = 1;
-
- IssuerSerial baseCertificateID;
-
- GeneralNames entityName;
-
- ObjectDigestInfo objectDigestInfo;
-
- private int version = V2_CERTIFICATE_HOLDER;
-
- public static Holder getInstance(Object obj)
- {
- if (obj instanceof Holder)
- {
- return (Holder)obj;
- }
- else if (obj instanceof ASN1TaggedObject)
- {
- return new Holder(ASN1TaggedObject.getInstance(obj));
- }
- else if (obj != null)
- {
- return new Holder(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- /**
- * Constructor for a holder for an V1 attribute certificate.
- *
- * @param tagObj The ASN.1 tagged holder object.
- */
- private Holder(ASN1TaggedObject tagObj)
- {
- switch (tagObj.getTagNo())
- {
- case 0:
- baseCertificateID = IssuerSerial.getInstance(tagObj, true);
- break;
- case 1:
- entityName = GeneralNames.getInstance(tagObj, true);
- break;
- default:
- throw new IllegalArgumentException("unknown tag in Holder");
- }
- version = 0;
- }
-
- /**
- * Constructor for a holder for an V2 attribute certificate.
- *
- * @param seq The ASN.1 sequence.
- */
- private Holder(ASN1Sequence seq)
- {
- if (seq.size() > 3)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
-
- for (int i = 0; i != seq.size(); i++)
- {
- ASN1TaggedObject tObj = ASN1TaggedObject.getInstance(seq
- .getObjectAt(i));
-
- switch (tObj.getTagNo())
- {
- case 0:
- baseCertificateID = IssuerSerial.getInstance(tObj, false);
- break;
- case 1:
- entityName = GeneralNames.getInstance(tObj, false);
- break;
- case 2:
- objectDigestInfo = ObjectDigestInfo.getInstance(tObj, false);
- break;
- default:
- throw new IllegalArgumentException("unknown tag in Holder");
- }
- }
- version = 1;
- }
-
- public Holder(IssuerSerial baseCertificateID)
- {
- this(baseCertificateID, V2_CERTIFICATE_HOLDER);
- }
-
- /**
- * Constructs a holder from a IssuerSerial for a V1 or V2 certificate.
- * .
- * @param baseCertificateID The IssuerSerial.
- * @param version The version of the attribute certificate.
- */
- public Holder(IssuerSerial baseCertificateID, int version)
- {
- this.baseCertificateID = baseCertificateID;
- this.version = version;
- }
-
- /**
- * Returns 1 for V2 attribute certificates or 0 for V1 attribute
- * certificates.
- * @return The version of the attribute certificate.
- */
- public int getVersion()
- {
- return version;
- }
-
- /**
- * Constructs a holder with an entityName for V2 attribute certificates.
- *
- * @param entityName The entity or subject name.
- */
- public Holder(GeneralNames entityName)
- {
- this(entityName, V2_CERTIFICATE_HOLDER);
- }
-
- /**
- * Constructs a holder with an entityName for V2 attribute certificates or
- * with a subjectName for V1 attribute certificates.
- *
- * @param entityName The entity or subject name.
- * @param version The version of the attribute certificate.
- */
- public Holder(GeneralNames entityName, int version)
- {
- this.entityName = entityName;
- this.version = version;
- }
-
- /**
- * Constructs a holder from an object digest info.
- *
- * @param objectDigestInfo The object digest info object.
- */
- public Holder(ObjectDigestInfo objectDigestInfo)
- {
- this.objectDigestInfo = objectDigestInfo;
- }
-
- public IssuerSerial getBaseCertificateID()
- {
- return baseCertificateID;
- }
-
- /**
- * Returns the entityName for an V2 attribute certificate or the subjectName
- * for an V1 attribute certificate.
- *
- * @return The entityname or subjectname.
- */
- public GeneralNames getEntityName()
- {
- return entityName;
- }
-
- public ObjectDigestInfo getObjectDigestInfo()
- {
- return objectDigestInfo;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- if (version == 1)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (baseCertificateID != null)
- {
- v.add(new DERTaggedObject(false, 0, baseCertificateID));
- }
-
- if (entityName != null)
- {
- v.add(new DERTaggedObject(false, 1, entityName));
- }
-
- if (objectDigestInfo != null)
- {
- v.add(new DERTaggedObject(false, 2, objectDigestInfo));
- }
-
- return new DERSequence(v);
- }
- else
- {
- if (entityName != null)
- {
- return new DERTaggedObject(true, 1, entityName);
- }
- else
- {
- return new DERTaggedObject(true, 0, baseCertificateID);
- }
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/IetfAttrSyntax.java b/core/src/main/java/org/bouncycastle/asn1/x509/IetfAttrSyntax.java
deleted file mode 100644
index 5a701407..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/IetfAttrSyntax.java
+++ /dev/null
@@ -1,189 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.util.Enumeration;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.DERUTF8String;
-
-/**
- * Implementation of <code>IetfAttrSyntax</code> as specified by RFC3281.
- */
-public class IetfAttrSyntax
- extends ASN1Object
-{
- public static final int VALUE_OCTETS = 1;
- public static final int VALUE_OID = 2;
- public static final int VALUE_UTF8 = 3;
- GeneralNames policyAuthority = null;
- Vector values = new Vector();
- int valueChoice = -1;
-
- public static IetfAttrSyntax getInstance(Object obj)
- {
- if (obj instanceof IetfAttrSyntax)
- {
- return (IetfAttrSyntax)obj;
- }
- if (obj != null)
- {
- return new IetfAttrSyntax(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- /**
- *
- */
- private IetfAttrSyntax(ASN1Sequence seq)
- {
- int i = 0;
-
- if (seq.getObjectAt(0) instanceof ASN1TaggedObject)
- {
- policyAuthority = GeneralNames.getInstance(((ASN1TaggedObject)seq.getObjectAt(0)), false);
- i++;
- }
- else if (seq.size() == 2)
- { // VOMS fix
- policyAuthority = GeneralNames.getInstance(seq.getObjectAt(0));
- i++;
- }
-
- if (!(seq.getObjectAt(i) instanceof ASN1Sequence))
- {
- throw new IllegalArgumentException("Non-IetfAttrSyntax encoding");
- }
-
- seq = (ASN1Sequence)seq.getObjectAt(i);
-
- for (Enumeration e = seq.getObjects(); e.hasMoreElements();)
- {
- ASN1Primitive obj = (ASN1Primitive)e.nextElement();
- int type;
-
- if (obj instanceof ASN1ObjectIdentifier)
- {
- type = VALUE_OID;
- }
- else if (obj instanceof DERUTF8String)
- {
- type = VALUE_UTF8;
- }
- else if (obj instanceof DEROctetString)
- {
- type = VALUE_OCTETS;
- }
- else
- {
- throw new IllegalArgumentException("Bad value type encoding IetfAttrSyntax");
- }
-
- if (valueChoice < 0)
- {
- valueChoice = type;
- }
-
- if (type != valueChoice)
- {
- throw new IllegalArgumentException("Mix of value types in IetfAttrSyntax");
- }
-
- values.addElement(obj);
- }
- }
-
- public GeneralNames getPolicyAuthority()
- {
- return policyAuthority;
- }
-
- public int getValueType()
- {
- return valueChoice;
- }
-
- public Object[] getValues()
- {
- if (this.getValueType() == VALUE_OCTETS)
- {
- ASN1OctetString[] tmp = new ASN1OctetString[values.size()];
-
- for (int i = 0; i != tmp.length; i++)
- {
- tmp[i] = (ASN1OctetString)values.elementAt(i);
- }
-
- return tmp;
- }
- else if (this.getValueType() == VALUE_OID)
- {
- ASN1ObjectIdentifier[] tmp = new ASN1ObjectIdentifier[values.size()];
-
- for (int i = 0; i != tmp.length; i++)
- {
- tmp[i] = (ASN1ObjectIdentifier)values.elementAt(i);
- }
-
- return tmp;
- }
- else
- {
- DERUTF8String[] tmp = new DERUTF8String[values.size()];
-
- for (int i = 0; i != tmp.length; i++)
- {
- tmp[i] = (DERUTF8String)values.elementAt(i);
- }
-
- return tmp;
- }
- }
-
- /**
- *
- * <pre>
- *
- * IetfAttrSyntax ::= SEQUENCE {
- * policyAuthority [0] GeneralNames OPTIONAL,
- * values SEQUENCE OF CHOICE {
- * octets OCTET STRING,
- * oid OBJECT IDENTIFIER,
- * string UTF8String
- * }
- * }
- *
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (policyAuthority != null)
- {
- v.add(new DERTaggedObject(0, policyAuthority));
- }
-
- ASN1EncodableVector v2 = new ASN1EncodableVector();
-
- for (Enumeration i = values.elements(); i.hasMoreElements();)
- {
- v2.add((ASN1Encodable)i.nextElement());
- }
-
- v.add(new DERSequence(v2));
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/IssuerSerial.java b/core/src/main/java/org/bouncycastle/asn1/x509/IssuerSerial.java
deleted file mode 100644
index fefc9396..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/IssuerSerial.java
+++ /dev/null
@@ -1,123 +0,0 @@
-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.DERBitString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x500.X500Name;
-
-public class IssuerSerial
- extends ASN1Object
-{
- GeneralNames issuer;
- ASN1Integer serial;
- DERBitString issuerUID;
-
- public static IssuerSerial getInstance(
- Object obj)
- {
- if (obj instanceof IssuerSerial)
- {
- return (IssuerSerial)obj;
- }
-
- if (obj != null)
- {
- return new IssuerSerial(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public static IssuerSerial getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- private IssuerSerial(
- ASN1Sequence seq)
- {
- if (seq.size() != 2 && seq.size() != 3)
- {
- throw new IllegalArgumentException("Bad sequence size: " + seq.size());
- }
-
- issuer = GeneralNames.getInstance(seq.getObjectAt(0));
- serial = ASN1Integer.getInstance(seq.getObjectAt(1));
-
- if (seq.size() == 3)
- {
- issuerUID = DERBitString.getInstance(seq.getObjectAt(2));
- }
- }
-
- public IssuerSerial(
- X500Name issuer,
- BigInteger serial)
- {
- this(new GeneralNames(new GeneralName(issuer)), new ASN1Integer(serial));
- }
-
- public IssuerSerial(
- GeneralNames issuer,
- BigInteger serial)
- {
- this(issuer, new ASN1Integer(serial));
- }
-
- public IssuerSerial(
- GeneralNames issuer,
- ASN1Integer serial)
- {
- this.issuer = issuer;
- this.serial = serial;
- }
-
- public GeneralNames getIssuer()
- {
- return issuer;
- }
-
- public ASN1Integer getSerial()
- {
- return serial;
- }
-
- public DERBitString getIssuerUID()
- {
- return issuerUID;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * IssuerSerial ::= SEQUENCE {
- * issuer GeneralNames,
- * serial CertificateSerialNumber,
- * issuerUID UniqueIdentifier OPTIONAL
- * }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(issuer);
- v.add(serial);
-
- if (issuerUID != null)
- {
- v.add(issuerUID);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/IssuingDistributionPoint.java b/core/src/main/java/org/bouncycastle/asn1/x509/IssuingDistributionPoint.java
deleted file mode 100644
index 1f29162b..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/IssuingDistributionPoint.java
+++ /dev/null
@@ -1,274 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Boolean;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * <pre>
- * IssuingDistributionPoint ::= SEQUENCE {
- * distributionPoint [0] DistributionPointName OPTIONAL,
- * onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE,
- * onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE,
- * onlySomeReasons [3] ReasonFlags OPTIONAL,
- * indirectCRL [4] BOOLEAN DEFAULT FALSE,
- * onlyContainsAttributeCerts [5] BOOLEAN DEFAULT FALSE }
- * </pre>
- */
-public class IssuingDistributionPoint
- extends ASN1Object
-{
- private DistributionPointName distributionPoint;
-
- private boolean onlyContainsUserCerts;
-
- private boolean onlyContainsCACerts;
-
- private ReasonFlags onlySomeReasons;
-
- private boolean indirectCRL;
-
- private boolean onlyContainsAttributeCerts;
-
- private ASN1Sequence seq;
-
- public static IssuingDistributionPoint getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static IssuingDistributionPoint getInstance(
- Object obj)
- {
- if (obj instanceof IssuingDistributionPoint)
- {
- return (IssuingDistributionPoint)obj;
- }
- else if (obj != null)
- {
- return new IssuingDistributionPoint(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- /**
- * Constructor from given details.
- *
- * @param distributionPoint
- * May contain an URI as pointer to most current CRL.
- * @param onlyContainsUserCerts Covers revocation information for end certificates.
- * @param onlyContainsCACerts Covers revocation information for CA certificates.
- *
- * @param onlySomeReasons
- * Which revocation reasons does this point cover.
- * @param indirectCRL
- * If <code>true</code> then the CRL contains revocation
- * information about certificates ssued by other CAs.
- * @param onlyContainsAttributeCerts Covers revocation information for attribute certificates.
- */
- public IssuingDistributionPoint(
- DistributionPointName distributionPoint,
- boolean onlyContainsUserCerts,
- boolean onlyContainsCACerts,
- ReasonFlags onlySomeReasons,
- boolean indirectCRL,
- boolean onlyContainsAttributeCerts)
- {
- this.distributionPoint = distributionPoint;
- this.indirectCRL = indirectCRL;
- this.onlyContainsAttributeCerts = onlyContainsAttributeCerts;
- this.onlyContainsCACerts = onlyContainsCACerts;
- this.onlyContainsUserCerts = onlyContainsUserCerts;
- this.onlySomeReasons = onlySomeReasons;
-
- ASN1EncodableVector vec = new ASN1EncodableVector();
- if (distributionPoint != null)
- { // CHOICE item so explicitly tagged
- vec.add(new DERTaggedObject(true, 0, distributionPoint));
- }
- if (onlyContainsUserCerts)
- {
- vec.add(new DERTaggedObject(false, 1, ASN1Boolean.getInstance(true)));
- }
- if (onlyContainsCACerts)
- {
- vec.add(new DERTaggedObject(false, 2, ASN1Boolean.getInstance(true)));
- }
- if (onlySomeReasons != null)
- {
- vec.add(new DERTaggedObject(false, 3, onlySomeReasons));
- }
- if (indirectCRL)
- {
- vec.add(new DERTaggedObject(false, 4, ASN1Boolean.getInstance(true)));
- }
- if (onlyContainsAttributeCerts)
- {
- vec.add(new DERTaggedObject(false, 5, ASN1Boolean.getInstance(true)));
- }
-
- seq = new DERSequence(vec);
- }
-
- /**
- * Shorthand Constructor from given details.
- *
- * @param distributionPoint
- * May contain an URI as pointer to most current CRL.
- * @param indirectCRL
- * If <code>true</code> then the CRL contains revocation
- * information about certificates ssued by other CAs.
- * @param onlyContainsAttributeCerts Covers revocation information for attribute certificates.
- */
- public IssuingDistributionPoint(
- DistributionPointName distributionPoint,
- boolean indirectCRL,
- boolean onlyContainsAttributeCerts)
- {
- this(distributionPoint, false, false, null, indirectCRL, onlyContainsAttributeCerts);
- }
-
- /**
- * Constructor from ASN1Sequence
- */
- private IssuingDistributionPoint(
- ASN1Sequence seq)
- {
- this.seq = seq;
-
- for (int i = 0; i != seq.size(); i++)
- {
- ASN1TaggedObject o = ASN1TaggedObject.getInstance(seq.getObjectAt(i));
-
- switch (o.getTagNo())
- {
- case 0:
- // CHOICE so explicit
- distributionPoint = DistributionPointName.getInstance(o, true);
- break;
- case 1:
- onlyContainsUserCerts = ASN1Boolean.getInstance(o, false).isTrue();
- break;
- case 2:
- onlyContainsCACerts = ASN1Boolean.getInstance(o, false).isTrue();
- break;
- case 3:
- onlySomeReasons = new ReasonFlags(ReasonFlags.getInstance(o, false));
- break;
- case 4:
- indirectCRL = ASN1Boolean.getInstance(o, false).isTrue();
- break;
- case 5:
- onlyContainsAttributeCerts = ASN1Boolean.getInstance(o, false).isTrue();
- break;
- default:
- throw new IllegalArgumentException(
- "unknown tag in IssuingDistributionPoint");
- }
- }
- }
-
- public boolean onlyContainsUserCerts()
- {
- return onlyContainsUserCerts;
- }
-
- public boolean onlyContainsCACerts()
- {
- return onlyContainsCACerts;
- }
-
- public boolean isIndirectCRL()
- {
- return indirectCRL;
- }
-
- public boolean onlyContainsAttributeCerts()
- {
- return onlyContainsAttributeCerts;
- }
-
- /**
- * @return Returns the distributionPoint.
- */
- public DistributionPointName getDistributionPoint()
- {
- return distributionPoint;
- }
-
- /**
- * @return Returns the onlySomeReasons.
- */
- public ReasonFlags getOnlySomeReasons()
- {
- return onlySomeReasons;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return seq;
- }
-
- public String toString()
- {
- String sep = System.getProperty("line.separator");
- StringBuffer buf = new StringBuffer();
-
- buf.append("IssuingDistributionPoint: [");
- buf.append(sep);
- if (distributionPoint != null)
- {
- appendObject(buf, sep, "distributionPoint", distributionPoint.toString());
- }
- if (onlyContainsUserCerts)
- {
- appendObject(buf, sep, "onlyContainsUserCerts", booleanToString(onlyContainsUserCerts));
- }
- if (onlyContainsCACerts)
- {
- appendObject(buf, sep, "onlyContainsCACerts", booleanToString(onlyContainsCACerts));
- }
- if (onlySomeReasons != null)
- {
- appendObject(buf, sep, "onlySomeReasons", onlySomeReasons.toString());
- }
- if (onlyContainsAttributeCerts)
- {
- appendObject(buf, sep, "onlyContainsAttributeCerts", booleanToString(onlyContainsAttributeCerts));
- }
- if (indirectCRL)
- {
- appendObject(buf, sep, "indirectCRL", booleanToString(indirectCRL));
- }
- buf.append("]");
- buf.append(sep);
- return buf.toString();
- }
-
- private void appendObject(StringBuffer buf, String sep, String name, String value)
- {
- String indent = " ";
-
- buf.append(indent);
- buf.append(name);
- buf.append(":");
- buf.append(sep);
- buf.append(indent);
- buf.append(indent);
- buf.append(value);
- buf.append(sep);
- }
-
- private String booleanToString(boolean value)
- {
- return value ? "true" : "false";
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/KeyPurposeId.java b/core/src/main/java/org/bouncycastle/asn1/x509/KeyPurposeId.java
deleted file mode 100644
index 01980bec..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/KeyPurposeId.java
+++ /dev/null
@@ -1,157 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-
-/**
- * The KeyPurposeId object.
- * <pre>
- * KeyPurposeId ::= OBJECT IDENTIFIER
- *
- * id-kp ::= OBJECT IDENTIFIER { iso(1) identified-organization(3)
- * dod(6) internet(1) security(5) mechanisms(5) pkix(7) 3}
- *
- * </pre>
- * To create a new KeyPurposeId where none of the below suit, use
- * <pre>
- * ASN1ObjectIdentifier newKeyPurposeIdOID = new ASN1ObjectIdentifier("1.3.6.1...");
- *
- * KeyPurposeId newKeyPurposeId = KeyPurposeId.getInstance(newKeyPurposeIdOID);
- * </pre>
- */
-public class KeyPurposeId
- extends ASN1Object
-{
- private static final ASN1ObjectIdentifier id_kp = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.3");
-
- /**
- * { 2 5 29 37 0 }
- */
- public static final KeyPurposeId anyExtendedKeyUsage = new KeyPurposeId(Extension.extendedKeyUsage.branch("0"));
-
- /**
- * { id-kp 1 }
- */
- public static final KeyPurposeId id_kp_serverAuth = new KeyPurposeId(id_kp.branch("1"));
- /**
- * { id-kp 2 }
- */
- public static final KeyPurposeId id_kp_clientAuth = new KeyPurposeId(id_kp.branch("2"));
- /**
- * { id-kp 3 }
- */
- public static final KeyPurposeId id_kp_codeSigning = new KeyPurposeId(id_kp.branch("3"));
- /**
- * { id-kp 4 }
- */
- public static final KeyPurposeId id_kp_emailProtection = new KeyPurposeId(id_kp.branch("4"));
- /**
- * Usage deprecated by RFC4945 - was { id-kp 5 }
- */
- public static final KeyPurposeId id_kp_ipsecEndSystem = new KeyPurposeId(id_kp.branch("5"));
- /**
- * Usage deprecated by RFC4945 - was { id-kp 6 }
- */
- public static final KeyPurposeId id_kp_ipsecTunnel = new KeyPurposeId(id_kp.branch("6"));
- /**
- * Usage deprecated by RFC4945 - was { idkp 7 }
- */
- public static final KeyPurposeId id_kp_ipsecUser = new KeyPurposeId(id_kp.branch("7"));
- /**
- * { id-kp 8 }
- */
- public static final KeyPurposeId id_kp_timeStamping = new KeyPurposeId(id_kp.branch("8"));
- /**
- * { id-kp 9 }
- */
- public static final KeyPurposeId id_kp_OCSPSigning = new KeyPurposeId(id_kp.branch("9"));
- /**
- * { id-kp 10 }
- */
- public static final KeyPurposeId id_kp_dvcs = new KeyPurposeId(id_kp.branch("10"));
- /**
- * { id-kp 11 }
- */
- public static final KeyPurposeId id_kp_sbgpCertAAServerAuth = new KeyPurposeId(id_kp.branch("11"));
- /**
- * { id-kp 12 }
- */
- public static final KeyPurposeId id_kp_scvp_responder = new KeyPurposeId(id_kp.branch("12"));
- /**
- * { id-kp 13 }
- */
- public static final KeyPurposeId id_kp_eapOverPPP = new KeyPurposeId(id_kp.branch("13"));
- /**
- * { id-kp 14 }
- */
- public static final KeyPurposeId id_kp_eapOverLAN = new KeyPurposeId(id_kp.branch("14"));
- /**
- * { id-kp 15 }
- */
- public static final KeyPurposeId id_kp_scvpServer = new KeyPurposeId(id_kp.branch("15"));
- /**
- * { id-kp 16 }
- */
- public static final KeyPurposeId id_kp_scvpClient = new KeyPurposeId(id_kp.branch("16"));
- /**
- * { id-kp 17 }
- */
- public static final KeyPurposeId id_kp_ipsecIKE = new KeyPurposeId(id_kp.branch("17"));
- /**
- * { id-kp 18 }
- */
- public static final KeyPurposeId id_kp_capwapAC = new KeyPurposeId(id_kp.branch("18"));
- /**
- * { id-kp 19 }
- */
- public static final KeyPurposeId id_kp_capwapWTP = new KeyPurposeId(id_kp.branch("19"));
-
- //
- // microsoft key purpose ids
- //
- /**
- * { 1 3 6 1 4 1 311 20 2 2 }
- */
- public static final KeyPurposeId id_kp_smartcardlogon = new KeyPurposeId(new ASN1ObjectIdentifier("1.3.6.1.4.1.311.20.2.2"));
-
- private ASN1ObjectIdentifier id;
-
- private KeyPurposeId(ASN1ObjectIdentifier id)
- {
- this.id = id;
- }
-
- /**
- * @deprecated use getInstance and an OID or one of the constants above.
- * @param id string representation of an OID.
- */
- public KeyPurposeId(String id)
- {
- this(new ASN1ObjectIdentifier(id));
- }
-
- public static KeyPurposeId getInstance(Object o)
- {
- if (o instanceof KeyPurposeId)
- {
- return (KeyPurposeId)o;
- }
- else if (o != null)
- {
- return new KeyPurposeId(ASN1ObjectIdentifier.getInstance(o));
- }
-
- return null;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return id;
- }
-
- public String getId()
- {
- return id.getId();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/KeyUsage.java b/core/src/main/java/org/bouncycastle/asn1/x509/KeyUsage.java
deleted file mode 100644
index d4456b74..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/KeyUsage.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.DERBitString;
-
-/**
- * The KeyUsage object.
- * <pre>
- * id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 }
- *
- * KeyUsage ::= BIT STRING {
- * digitalSignature (0),
- * nonRepudiation (1),
- * keyEncipherment (2),
- * dataEncipherment (3),
- * keyAgreement (4),
- * keyCertSign (5),
- * cRLSign (6),
- * encipherOnly (7),
- * decipherOnly (8) }
- * </pre>
- */
-public class KeyUsage
- extends ASN1Object
-{
- public static final int digitalSignature = (1 << 7);
- public static final int nonRepudiation = (1 << 6);
- public static final int keyEncipherment = (1 << 5);
- public static final int dataEncipherment = (1 << 4);
- public static final int keyAgreement = (1 << 3);
- public static final int keyCertSign = (1 << 2);
- public static final int cRLSign = (1 << 1);
- public static final int encipherOnly = (1 << 0);
- public static final int decipherOnly = (1 << 15);
-
- private DERBitString bitString;
-
- public static KeyUsage getInstance(Object obj) // needs to be DERBitString for other VMs
- {
- if (obj instanceof KeyUsage)
- {
- return (KeyUsage)obj;
- }
- else if (obj != null)
- {
- return new KeyUsage(DERBitString.getInstance(obj));
- }
-
- return null;
- }
-
- public static KeyUsage fromExtensions(Extensions extensions)
- {
- return KeyUsage.getInstance(extensions.getExtensionParsedValue(Extension.keyUsage));
- }
-
- /**
- * Basic constructor.
- *
- * @param usage - the bitwise OR of the Key Usage flags giving the
- * allowed uses for the key.
- * e.g. (KeyUsage.keyEncipherment | KeyUsage.dataEncipherment)
- */
- public KeyUsage(
- int usage)
- {
- this.bitString = new DERBitString(usage);
- }
-
- private KeyUsage(
- DERBitString bitString)
- {
- 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();
- }
-
- public int getPadBits()
- {
- return bitString.getPadBits();
- }
-
- public String toString()
- {
- byte[] data = bitString.getBytes();
-
- if (data.length == 1)
- {
- return "KeyUsage: 0x" + Integer.toHexString(data[0] & 0xff);
- }
- return "KeyUsage: 0x" + Integer.toHexString((data[1] & 0xff) << 8 | (data[0] & 0xff));
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return bitString;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/NameConstraints.java b/core/src/main/java/org/bouncycastle/asn1/x509/NameConstraints.java
deleted file mode 100644
index 0a923a85..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/NameConstraints.java
+++ /dev/null
@@ -1,118 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-public class NameConstraints
- extends ASN1Object
-{
- private GeneralSubtree[] permitted, excluded;
-
- public static NameConstraints getInstance(Object obj)
- {
- if (obj instanceof NameConstraints)
- {
- return (NameConstraints)obj;
- }
- if (obj != null)
- {
- return new NameConstraints(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private NameConstraints(ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
- while (e.hasMoreElements())
- {
- ASN1TaggedObject o = ASN1TaggedObject.getInstance(e.nextElement());
- switch (o.getTagNo())
- {
- case 0:
- permitted = createArray(ASN1Sequence.getInstance(o, false));
- break;
- case 1:
- excluded = createArray(ASN1Sequence.getInstance(o, false));
- break;
- }
- }
- }
-
- /**
- * Constructor from a given details.
- *
- * <p>
- * permitted and excluded are arrays of GeneralSubtree objects.
- *
- * @param permitted
- * Permitted subtrees
- * @param excluded
- * Excludes subtrees
- */
- public NameConstraints(
- GeneralSubtree[] permitted,
- GeneralSubtree[] excluded)
- {
- if (permitted != null)
- {
- this.permitted = permitted;
- }
-
- if (excluded != null)
- {
- this.excluded = excluded;
- }
- }
-
- private GeneralSubtree[] createArray(ASN1Sequence subtree)
- {
- GeneralSubtree[] ar = new GeneralSubtree[subtree.size()];
-
- for (int i = 0; i != ar.length; i++)
- {
- ar[i] = GeneralSubtree.getInstance(subtree.getObjectAt(i));
- }
-
- return ar;
- }
-
- public GeneralSubtree[] getPermittedSubtrees()
- {
- return permitted;
- }
-
- public GeneralSubtree[] getExcludedSubtrees()
- {
- return excluded;
- }
-
- /*
- * NameConstraints ::= SEQUENCE { permittedSubtrees [0] GeneralSubtrees
- * OPTIONAL, excludedSubtrees [1] GeneralSubtrees OPTIONAL }
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (permitted != null)
- {
- v.add(new DERTaggedObject(false, 0, new DERSequence(permitted)));
- }
-
- if (excluded != null)
- {
- v.add(new DERTaggedObject(false, 1, new DERSequence(excluded)));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/NoticeReference.java b/core/src/main/java/org/bouncycastle/asn1/x509/NoticeReference.java
deleted file mode 100644
index d46f524e..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/NoticeReference.java
+++ /dev/null
@@ -1,170 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-import java.util.Vector;
-
-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.DERSequence;
-
-/**
- * <code>NoticeReference</code> class, used in
- * <code>CertificatePolicies</code> X509 V3 extensions
- * (in policy qualifiers).
- *
- * <pre>
- * NoticeReference ::= SEQUENCE {
- * organization DisplayText,
- * noticeNumbers SEQUENCE OF INTEGER }
- *
- * </pre>
- *
- * @see PolicyQualifierInfo
- * @see PolicyInformation
- */
-public class NoticeReference
- extends ASN1Object
-{
- private DisplayText organization;
- private ASN1Sequence noticeNumbers;
-
- private static ASN1EncodableVector convertVector(Vector numbers)
- {
- ASN1EncodableVector av = new ASN1EncodableVector();
-
- Enumeration it = numbers.elements();
-
- while (it.hasMoreElements())
- {
- Object o = it.nextElement();
- ASN1Integer di;
-
- if (o instanceof BigInteger)
- {
- di = new ASN1Integer((BigInteger)o);
- }
- else if (o instanceof Integer)
- {
- di = new ASN1Integer(((Integer)o).intValue());
- }
- else
- {
- throw new IllegalArgumentException();
- }
-
- av.add(di);
- }
- return av;
- }
-
- /**
- * Creates a new <code>NoticeReference</code> instance.
- *
- * @param organization a <code>String</code> value
- * @param numbers a <code>Vector</code> value
- */
- public NoticeReference(
- String organization,
- Vector numbers)
- {
- this(organization, convertVector(numbers));
- }
-
- /**
- * Creates a new <code>NoticeReference</code> instance.
- *
- * @param organization a <code>String</code> value
- * @param noticeNumbers an <code>ASN1EncodableVector</code> value
- */
- public NoticeReference(
- String organization,
- ASN1EncodableVector noticeNumbers)
- {
- this(new DisplayText(organization), noticeNumbers);
- }
-
- /**
- * Creates a new <code>NoticeReference</code> instance.
- *
- * @param organization displayText
- * @param noticeNumbers an <code>ASN1EncodableVector</code> value
- */
- public NoticeReference(
- DisplayText organization,
- ASN1EncodableVector noticeNumbers)
- {
- this.organization = organization;
- this.noticeNumbers = new DERSequence(noticeNumbers);
- }
-
- /**
- * Creates a new <code>NoticeReference</code> instance.
- * <p>Useful for reconstructing a <code>NoticeReference</code>
- * instance from its encodable/encoded form.
- *
- * @param as an <code>ASN1Sequence</code> value obtained from either
- * calling @{link toASN1Primitive()} for a <code>NoticeReference</code>
- * instance or from parsing it from a DER-encoded stream.
- */
- private NoticeReference(
- ASN1Sequence as)
- {
- if (as.size() != 2)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + as.size());
- }
-
- organization = DisplayText.getInstance(as.getObjectAt(0));
- noticeNumbers = ASN1Sequence.getInstance(as.getObjectAt(1));
- }
-
- public static NoticeReference getInstance(
- Object as)
- {
- if (as instanceof NoticeReference)
- {
- return (NoticeReference)as;
- }
- else if (as != null)
- {
- return new NoticeReference(ASN1Sequence.getInstance(as));
- }
-
- return null;
- }
-
- public DisplayText getOrganization()
- {
- return organization;
- }
-
- public ASN1Integer[] getNoticeNumbers()
- {
- ASN1Integer[] tmp = new ASN1Integer[noticeNumbers.size()];
-
- for (int i = 0; i != noticeNumbers.size(); i++)
- {
- tmp[i] = ASN1Integer.getInstance(noticeNumbers.getObjectAt(i));
- }
-
- return tmp;
- }
-
- /**
- * Describe <code>toASN1Object</code> method here.
- *
- * @return a <code>ASN1Primitive</code> value
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector av = new ASN1EncodableVector();
- av.add (organization);
- av.add (noticeNumbers);
- return new DERSequence (av);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/ObjectDigestInfo.java b/core/src/main/java/org/bouncycastle/asn1/x509/ObjectDigestInfo.java
deleted file mode 100644
index c4668b76..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/ObjectDigestInfo.java
+++ /dev/null
@@ -1,190 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Enumerated;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * ObjectDigestInfo ASN.1 structure used in v2 attribute certificates.
- *
- * <pre>
- *
- * ObjectDigestInfo ::= SEQUENCE {
- * digestedObjectType ENUMERATED {
- * publicKey (0),
- * publicKeyCert (1),
- * otherObjectTypes (2) },
- * -- otherObjectTypes MUST NOT
- * -- be used in this profile
- * otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
- * digestAlgorithm AlgorithmIdentifier,
- * objectDigest BIT STRING
- * }
- *
- * </pre>
- *
- */
-public class ObjectDigestInfo
- extends ASN1Object
-{
- /**
- * The public key is hashed.
- */
- public final static int publicKey = 0;
-
- /**
- * The public key certificate is hashed.
- */
- public final static int publicKeyCert = 1;
-
- /**
- * An other object is hashed.
- */
- public final static int otherObjectDigest = 2;
-
- ASN1Enumerated digestedObjectType;
-
- ASN1ObjectIdentifier otherObjectTypeID;
-
- AlgorithmIdentifier digestAlgorithm;
-
- DERBitString objectDigest;
-
- public static ObjectDigestInfo getInstance(
- Object obj)
- {
- if (obj instanceof ObjectDigestInfo)
- {
- return (ObjectDigestInfo)obj;
- }
-
- if (obj != null)
- {
- return new ObjectDigestInfo(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public static ObjectDigestInfo getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- /**
- * Constructor from given details.
- * <p>
- * If <code>digestedObjectType</code> is not {@link #publicKeyCert} or
- * {@link #publicKey} <code>otherObjectTypeID</code> must be given,
- * otherwise it is ignored.
- *
- * @param digestedObjectType The digest object type.
- * @param otherObjectTypeID The object type ID for
- * <code>otherObjectDigest</code>.
- * @param digestAlgorithm The algorithm identifier for the hash.
- * @param objectDigest The hash value.
- */
- public ObjectDigestInfo(
- int digestedObjectType,
- ASN1ObjectIdentifier otherObjectTypeID,
- AlgorithmIdentifier digestAlgorithm,
- byte[] objectDigest)
- {
- this.digestedObjectType = new ASN1Enumerated(digestedObjectType);
- if (digestedObjectType == otherObjectDigest)
- {
- this.otherObjectTypeID = otherObjectTypeID;
- }
-
- this.digestAlgorithm = digestAlgorithm;
- this.objectDigest = new DERBitString(objectDigest);
- }
-
- private ObjectDigestInfo(
- ASN1Sequence seq)
- {
- if (seq.size() > 4 || seq.size() < 3)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
-
- digestedObjectType = ASN1Enumerated.getInstance(seq.getObjectAt(0));
-
- int offset = 0;
-
- if (seq.size() == 4)
- {
- otherObjectTypeID = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(1));
- offset++;
- }
-
- digestAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1 + offset));
-
- objectDigest = DERBitString.getInstance(seq.getObjectAt(2 + offset));
- }
-
- public ASN1Enumerated getDigestedObjectType()
- {
- return digestedObjectType;
- }
-
- public ASN1ObjectIdentifier getOtherObjectTypeID()
- {
- return otherObjectTypeID;
- }
-
- public AlgorithmIdentifier getDigestAlgorithm()
- {
- return digestAlgorithm;
- }
-
- public DERBitString getObjectDigest()
- {
- return objectDigest;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- *
- * <pre>
- *
- * ObjectDigestInfo ::= SEQUENCE {
- * digestedObjectType ENUMERATED {
- * publicKey (0),
- * publicKeyCert (1),
- * otherObjectTypes (2) },
- * -- otherObjectTypes MUST NOT
- * -- be used in this profile
- * otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
- * digestAlgorithm AlgorithmIdentifier,
- * objectDigest BIT STRING
- * }
- *
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(digestedObjectType);
-
- if (otherObjectTypeID != null)
- {
- v.add(otherObjectTypeID);
- }
-
- v.add(digestAlgorithm);
- v.add(objectDigest);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/PolicyConstraints.java b/core/src/main/java/org/bouncycastle/asn1/x509/PolicyConstraints.java
deleted file mode 100644
index aeb53f09..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/PolicyConstraints.java
+++ /dev/null
@@ -1,106 +0,0 @@
-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/core/src/main/java/org/bouncycastle/asn1/x509/PolicyInformation.java b/core/src/main/java/org/bouncycastle/asn1/x509/PolicyInformation.java
deleted file mode 100644
index d1de26fc..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/PolicyInformation.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-public class PolicyInformation
- extends ASN1Object
-{
- private ASN1ObjectIdentifier policyIdentifier;
- private ASN1Sequence policyQualifiers;
-
- private PolicyInformation(
- ASN1Sequence seq)
- {
- if (seq.size() < 1 || seq.size() > 2)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
-
- policyIdentifier = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
-
- if (seq.size() > 1)
- {
- policyQualifiers = ASN1Sequence.getInstance(seq.getObjectAt(1));
- }
- }
-
- public PolicyInformation(
- ASN1ObjectIdentifier policyIdentifier)
- {
- this.policyIdentifier = policyIdentifier;
- }
-
- public PolicyInformation(
- ASN1ObjectIdentifier policyIdentifier,
- ASN1Sequence policyQualifiers)
- {
- this.policyIdentifier = policyIdentifier;
- this.policyQualifiers = policyQualifiers;
- }
-
- public static PolicyInformation getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof PolicyInformation)
- {
- return (PolicyInformation)obj;
- }
-
- return new PolicyInformation(ASN1Sequence.getInstance(obj));
- }
-
- public ASN1ObjectIdentifier getPolicyIdentifier()
- {
- return policyIdentifier;
- }
-
- public ASN1Sequence getPolicyQualifiers()
- {
- return policyQualifiers;
- }
-
- /*
- * PolicyInformation ::= SEQUENCE {
- * policyIdentifier CertPolicyId,
- * policyQualifiers SEQUENCE SIZE (1..MAX) OF
- * PolicyQualifierInfo OPTIONAL }
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(policyIdentifier);
-
- if (policyQualifiers != null)
- {
- v.add(policyQualifiers);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/PolicyMappings.java b/core/src/main/java/org/bouncycastle/asn1/x509/PolicyMappings.java
deleted file mode 100644
index 6afab95f..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/PolicyMappings.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.util.Enumeration;
-import java.util.Hashtable;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * PolicyMappings V3 extension, described in RFC3280.
- * <pre>
- * PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
- * issuerDomainPolicy CertPolicyId,
- * subjectDomainPolicy CertPolicyId }
- * </pre>
- *
- * @see <a href="http://www.faqs.org/rfc/rfc3280.txt">RFC 3280, section 4.2.1.6</a>
- */
-public class PolicyMappings
- extends ASN1Object
-{
- ASN1Sequence seq = null;
-
- public static PolicyMappings getInstance(Object obj)
- {
- if (obj instanceof PolicyMappings)
- {
- return (PolicyMappings)obj;
- }
- if (obj != null)
- {
- return new PolicyMappings(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- /**
- * Creates a new <code>PolicyMappings</code> instance.
- *
- * @param seq an <code>ASN1Sequence</code> constructed as specified
- * in RFC 3280
- */
- private PolicyMappings(ASN1Sequence seq)
- {
- this.seq = seq;
- }
-
- /**
- * Creates a new <code>PolicyMappings</code> instance.
- *
- * @param mappings a <code>HashMap</code> value that maps
- * <code>String</code> oids
- * to other <code>String</code> oids.
- * @deprecated use CertPolicyId constructors.
- */
- public PolicyMappings(Hashtable mappings)
- {
- ASN1EncodableVector dev = new ASN1EncodableVector();
- Enumeration it = mappings.keys();
-
- while (it.hasMoreElements())
- {
- String idp = (String)it.nextElement();
- String sdp = (String)mappings.get(idp);
- ASN1EncodableVector dv = new ASN1EncodableVector();
- dv.add(new ASN1ObjectIdentifier(idp));
- dv.add(new ASN1ObjectIdentifier(sdp));
- dev.add(new DERSequence(dv));
- }
-
- seq = new DERSequence(dev);
- }
-
- public PolicyMappings(CertPolicyId issuerDomainPolicy, CertPolicyId subjectDomainPolicy)
- {
- ASN1EncodableVector dv = new ASN1EncodableVector();
- dv.add(issuerDomainPolicy);
- dv.add(subjectDomainPolicy);
-
- seq = new DERSequence(new DERSequence(dv));
- }
-
- public PolicyMappings(CertPolicyId[] issuerDomainPolicy, CertPolicyId[] subjectDomainPolicy)
- {
- ASN1EncodableVector dev = new ASN1EncodableVector();
-
- for (int i = 0; i != issuerDomainPolicy.length; i++)
- {
- ASN1EncodableVector dv = new ASN1EncodableVector();
- dv.add(issuerDomainPolicy[i]);
- dv.add(subjectDomainPolicy[i]);
- dev.add(new DERSequence(dv));
- }
-
- seq = new DERSequence(dev);
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return seq;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/PolicyQualifierId.java b/core/src/main/java/org/bouncycastle/asn1/x509/PolicyQualifierId.java
deleted file mode 100644
index 82835f6a..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/PolicyQualifierId.java
+++ /dev/null
@@ -1,31 +0,0 @@
-
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-
-/**
- * PolicyQualifierId, used in the CertificatePolicies
- * X509V3 extension.
- *
- * <pre>
- * id-qt OBJECT IDENTIFIER ::= { id-pkix 2 }
- * id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 }
- * id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 }
- * PolicyQualifierId ::=
- * OBJECT IDENTIFIER (id-qt-cps | id-qt-unotice)
- * </pre>
- */
-public class PolicyQualifierId extends ASN1ObjectIdentifier
-{
- private static final String id_qt = "1.3.6.1.5.5.7.2";
-
- private PolicyQualifierId(String id)
- {
- super(id);
- }
-
- public static final PolicyQualifierId id_qt_cps =
- new PolicyQualifierId(id_qt + ".1");
- public static final PolicyQualifierId id_qt_unotice =
- new PolicyQualifierId(id_qt + ".2");
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/PolicyQualifierInfo.java b/core/src/main/java/org/bouncycastle/asn1/x509/PolicyQualifierInfo.java
deleted file mode 100644
index fe091690..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/PolicyQualifierInfo.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * Policy qualifiers, used in the X509V3 CertificatePolicies
- * extension.
- *
- * <pre>
- * PolicyQualifierInfo ::= SEQUENCE {
- * policyQualifierId PolicyQualifierId,
- * qualifier ANY DEFINED BY policyQualifierId }
- * </pre>
- */
-public class PolicyQualifierInfo
- extends ASN1Object
-{
- private ASN1ObjectIdentifier policyQualifierId;
- private ASN1Encodable qualifier;
-
- /**
- * Creates a new <code>PolicyQualifierInfo</code> instance.
- *
- * @param policyQualifierId a <code>PolicyQualifierId</code> value
- * @param qualifier the qualifier, defined by the above field.
- */
- public PolicyQualifierInfo(
- ASN1ObjectIdentifier policyQualifierId,
- ASN1Encodable qualifier)
- {
- this.policyQualifierId = policyQualifierId;
- this.qualifier = qualifier;
- }
-
- /**
- * Creates a new <code>PolicyQualifierInfo</code> containing a
- * cPSuri qualifier.
- *
- * @param cps the CPS (certification practice statement) uri as a
- * <code>String</code>.
- */
- public PolicyQualifierInfo(
- String cps)
- {
- policyQualifierId = PolicyQualifierId.id_qt_cps;
- qualifier = new DERIA5String (cps);
- }
-
- /**
- * Creates a new <code>PolicyQualifierInfo</code> instance.
- *
- * @param as <code>PolicyQualifierInfo</code> X509 structure
- * encoded as an ASN1Sequence.
- * @deprecated use PolicyQualifierInfo.getInstance()
- */
- public PolicyQualifierInfo(
- ASN1Sequence as)
- {
- if (as.size() != 2)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + as.size());
- }
-
- policyQualifierId = ASN1ObjectIdentifier.getInstance(as.getObjectAt(0));
- qualifier = as.getObjectAt(1);
- }
-
- public static PolicyQualifierInfo getInstance(
- Object obj)
- {
- if (obj instanceof PolicyQualifierInfo)
- {
- return (PolicyQualifierInfo)obj;
- }
- else if (obj != null)
- {
- return new PolicyQualifierInfo(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
-
- public ASN1ObjectIdentifier getPolicyQualifierId()
- {
- return policyQualifierId;
- }
-
- public ASN1Encodable getQualifier()
- {
- return qualifier;
- }
-
- /**
- * Returns a DER-encodable representation of this instance.
- *
- * @return a <code>ASN1Primitive</code> value
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector dev = new ASN1EncodableVector();
- dev.add(policyQualifierId);
- dev.add(qualifier);
-
- return new DERSequence(dev);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/PrivateKeyUsagePeriod.java b/core/src/main/java/org/bouncycastle/asn1/x509/PrivateKeyUsagePeriod.java
deleted file mode 100644
index 44e0b671..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/PrivateKeyUsagePeriod.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-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.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * <pre>
- * PrivateKeyUsagePeriod ::= SEQUENCE {
- * notBefore [0] GeneralizedTime OPTIONAL,
- * notAfter [1] GeneralizedTime OPTIONAL }
- * </pre>
- */
-public class PrivateKeyUsagePeriod
- extends ASN1Object
-{
- public static PrivateKeyUsagePeriod getInstance(Object obj)
- {
- if (obj instanceof PrivateKeyUsagePeriod)
- {
- return (PrivateKeyUsagePeriod)obj;
- }
-
- if (obj != null)
- {
- return new PrivateKeyUsagePeriod(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private ASN1GeneralizedTime _notBefore, _notAfter;
-
- private PrivateKeyUsagePeriod(ASN1Sequence seq)
- {
- Enumeration en = seq.getObjects();
- while (en.hasMoreElements())
- {
- ASN1TaggedObject tObj = (ASN1TaggedObject)en.nextElement();
-
- if (tObj.getTagNo() == 0)
- {
- _notBefore = ASN1GeneralizedTime.getInstance(tObj, false);
- }
- else if (tObj.getTagNo() == 1)
- {
- _notAfter = ASN1GeneralizedTime.getInstance(tObj, false);
- }
- }
- }
-
- public ASN1GeneralizedTime getNotBefore()
- {
- return _notBefore;
- }
-
- public ASN1GeneralizedTime getNotAfter()
- {
- return _notAfter;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (_notBefore != null)
- {
- v.add(new DERTaggedObject(false, 0, _notBefore));
- }
- if (_notAfter != null)
- {
- v.add(new DERTaggedObject(false, 1, _notAfter));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/RSAPublicKeyStructure.java b/core/src/main/java/org/bouncycastle/asn1/x509/RSAPublicKeyStructure.java
deleted file mode 100644
index 91c87256..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/RSAPublicKeyStructure.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-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;
-
-/**
- * @deprecated use org.bouncycastle.asn1.pkcs.RSAPublicKey
- */
-public class RSAPublicKeyStructure
- extends ASN1Object
-{
- private BigInteger modulus;
- private BigInteger publicExponent;
-
- public static RSAPublicKeyStructure getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static RSAPublicKeyStructure getInstance(
- Object obj)
- {
- if(obj == null || obj instanceof RSAPublicKeyStructure)
- {
- return (RSAPublicKeyStructure)obj;
- }
-
- if(obj instanceof ASN1Sequence)
- {
- return new RSAPublicKeyStructure((ASN1Sequence)obj);
- }
-
- throw new IllegalArgumentException("Invalid RSAPublicKeyStructure: " + obj.getClass().getName());
- }
-
- public RSAPublicKeyStructure(
- BigInteger modulus,
- BigInteger publicExponent)
- {
- this.modulus = modulus;
- this.publicExponent = publicExponent;
- }
-
- public RSAPublicKeyStructure(
- ASN1Sequence seq)
- {
- if (seq.size() != 2)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
-
- Enumeration e = seq.getObjects();
-
- modulus = ASN1Integer.getInstance(e.nextElement()).getPositiveValue();
- publicExponent = ASN1Integer.getInstance(e.nextElement()).getPositiveValue();
- }
-
- public BigInteger getModulus()
- {
- return modulus;
- }
-
- public BigInteger getPublicExponent()
- {
- return publicExponent;
- }
-
- /**
- * This outputs the key in PKCS1v2 format.
- * <pre>
- * RSAPublicKey ::= SEQUENCE {
- * modulus INTEGER, -- n
- * publicExponent INTEGER, -- e
- * }
- * </pre>
- * <p>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(new ASN1Integer(getModulus()));
- v.add(new ASN1Integer(getPublicExponent()));
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/ReasonFlags.java b/core/src/main/java/org/bouncycastle/asn1/x509/ReasonFlags.java
deleted file mode 100644
index 612e2c5e..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/ReasonFlags.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.DERBitString;
-
-/**
- * The ReasonFlags object.
- * <pre>
- * ReasonFlags ::= BIT STRING {
- * unused (0),
- * keyCompromise (1),
- * cACompromise (2),
- * affiliationChanged (3),
- * superseded (4),
- * cessationOfOperation (5),
- * certificateHold (6),
- * privilegeWithdrawn (7),
- * aACompromise (8) }
- * </pre>
- */
-public class ReasonFlags
- extends DERBitString
-{
- /**
- * @deprecated use lower case version
- */
- public static final int UNUSED = (1 << 7);
- /**
- * @deprecated use lower case version
- */
- public static final int KEY_COMPROMISE = (1 << 6);
- /**
- * @deprecated use lower case version
- */
- public static final int CA_COMPROMISE = (1 << 5);
- /**
- * @deprecated use lower case version
- */
- public static final int AFFILIATION_CHANGED = (1 << 4);
- /**
- * @deprecated use lower case version
- */
- public static final int SUPERSEDED = (1 << 3);
- /**
- * @deprecated use lower case version
- */
- public static final int CESSATION_OF_OPERATION = (1 << 2);
- /**
- * @deprecated use lower case version
- */
- public static final int CERTIFICATE_HOLD = (1 << 1);
- /**
- * @deprecated use lower case version
- */
- public static final int PRIVILEGE_WITHDRAWN = (1 << 0);
- /**
- * @deprecated use lower case version
- */
- public static final int AA_COMPROMISE = (1 << 15);
-
- public static final int unused = (1 << 7);
- public static final int keyCompromise = (1 << 6);
- public static final int cACompromise = (1 << 5);
- public static final int affiliationChanged = (1 << 4);
- public static final int superseded = (1 << 3);
- public static final int cessationOfOperation = (1 << 2);
- public static final int certificateHold = (1 << 1);
- public static final int privilegeWithdrawn = (1 << 0);
- public static final int aACompromise = (1 << 15);
-
- /**
- * @param reasons - the bitwise OR of the Key Reason flags giving the
- * allowed uses for the key.
- */
- public ReasonFlags(
- int reasons)
- {
- super(getBytes(reasons), getPadBits(reasons));
- }
-
- public ReasonFlags(
- DERBitString reasons)
- {
- super(reasons.getBytes(), reasons.getPadBits());
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/RoleSyntax.java b/core/src/main/java/org/bouncycastle/asn1/x509/RoleSyntax.java
deleted file mode 100644
index 7558c12d..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/RoleSyntax.java
+++ /dev/null
@@ -1,237 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1String;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * Implementation of the RoleSyntax object as specified by the RFC3281.
- *
- * <pre>
- * RoleSyntax ::= SEQUENCE {
- * roleAuthority [0] GeneralNames OPTIONAL,
- * roleName [1] GeneralName
- * }
- * </pre>
- */
-public class RoleSyntax
- extends ASN1Object
-{
- private GeneralNames roleAuthority;
- private GeneralName roleName;
-
- /**
- * RoleSyntax factory method.
- * @param obj the object used to construct an instance of <code>
- * RoleSyntax</code>. It must be an instance of <code>RoleSyntax
- * </code> or <code>ASN1Sequence</code>.
- * @return the instance of <code>RoleSyntax</code> built from the
- * supplied object.
- * @throws java.lang.IllegalArgumentException if the object passed
- * to the factory is not an instance of <code>RoleSyntax</code> or
- * <code>ASN1Sequence</code>.
- */
- public static RoleSyntax getInstance(
- Object obj)
- {
-
- if (obj instanceof RoleSyntax)
- {
- return (RoleSyntax)obj;
- }
- else if (obj != null)
- {
- return new RoleSyntax(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- /**
- * Constructor.
- * @param roleAuthority the role authority of this RoleSyntax.
- * @param roleName the role name of this RoleSyntax.
- */
- public RoleSyntax(
- GeneralNames roleAuthority,
- GeneralName roleName)
- {
- if(roleName == null ||
- roleName.getTagNo() != GeneralName.uniformResourceIdentifier ||
- ((ASN1String)roleName.getName()).getString().equals(""))
- {
- throw new IllegalArgumentException("the role name MUST be non empty and MUST " +
- "use the URI option of GeneralName");
- }
- this.roleAuthority = roleAuthority;
- this.roleName = roleName;
- }
-
- /**
- * Constructor. Invoking this constructor is the same as invoking
- * <code>new RoleSyntax(null, roleName)</code>.
- * @param roleName the role name of this RoleSyntax.
- */
- public RoleSyntax(
- GeneralName roleName)
- {
- this(null, roleName);
- }
-
- /**
- * Utility constructor. Takes a <code>String</code> argument representing
- * the role name, builds a <code>GeneralName</code> to hold the role name
- * and calls the constructor that takes a <code>GeneralName</code>.
- * @param roleName
- */
- public RoleSyntax(
- String roleName)
- {
- this(new GeneralName(GeneralName.uniformResourceIdentifier,
- (roleName == null)? "": roleName));
- }
-
- /**
- * Constructor that builds an instance of <code>RoleSyntax</code> by
- * extracting the encoded elements from the <code>ASN1Sequence</code>
- * object supplied.
- * @param seq an instance of <code>ASN1Sequence</code> that holds
- * the encoded elements used to build this <code>RoleSyntax</code>.
- */
- private RoleSyntax(
- ASN1Sequence seq)
- {
- if (seq.size() < 1 || seq.size() > 2)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
-
- for (int i = 0; i != seq.size(); i++)
- {
- ASN1TaggedObject taggedObject = ASN1TaggedObject.getInstance(seq.getObjectAt(i));
- switch (taggedObject.getTagNo())
- {
- case 0:
- roleAuthority = GeneralNames.getInstance(taggedObject, false);
- break;
- case 1:
- roleName = GeneralName.getInstance(taggedObject, true);
- break;
- default:
- throw new IllegalArgumentException("Unknown tag in RoleSyntax");
- }
- }
- }
-
- /**
- * Gets the role authority of this RoleSyntax.
- * @return an instance of <code>GeneralNames</code> holding the
- * role authority of this RoleSyntax.
- */
- public GeneralNames getRoleAuthority()
- {
- return this.roleAuthority;
- }
-
- /**
- * Gets the role name of this RoleSyntax.
- * @return an instance of <code>GeneralName</code> holding the
- * role name of this RoleSyntax.
- */
- public GeneralName getRoleName()
- {
- return this.roleName;
- }
-
- /**
- * Gets the role name as a <code>java.lang.String</code> object.
- * @return the role name of this RoleSyntax represented as a
- * <code>java.lang.String</code> object.
- */
- public String getRoleNameAsString()
- {
- ASN1String str = (ASN1String)this.roleName.getName();
-
- return str.getString();
- }
-
- /**
- * Gets the role authority as a <code>String[]</code> object.
- * @return the role authority of this RoleSyntax represented as a
- * <code>String[]</code> array.
- */
- public String[] getRoleAuthorityAsString()
- {
- if(roleAuthority == null)
- {
- return new String[0];
- }
-
- GeneralName[] names = roleAuthority.getNames();
- String[] namesString = new String[names.length];
- for(int i = 0; i < names.length; i++)
- {
- ASN1Encodable value = names[i].getName();
- if(value instanceof ASN1String)
- {
- namesString[i] = ((ASN1String)value).getString();
- }
- else
- {
- namesString[i] = value.toString();
- }
- }
- return namesString;
- }
-
- /**
- * Implementation of the method <code>toASN1Object</code> as
- * required by the superclass <code>ASN1Encodable</code>.
- *
- * <pre>
- * RoleSyntax ::= SEQUENCE {
- * roleAuthority [0] GeneralNames OPTIONAL,
- * roleName [1] GeneralName
- * }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- if(this.roleAuthority != null)
- {
- v.add(new DERTaggedObject(false, 0, roleAuthority));
- }
- v.add(new DERTaggedObject(true, 1, roleName));
-
- return new DERSequence(v);
- }
-
- public String toString()
- {
- StringBuffer buff = new StringBuffer("Name: " + this.getRoleNameAsString() +
- " - Auth: ");
- if(this.roleAuthority == null || roleAuthority.getNames().length == 0)
- {
- buff.append("N/A");
- }
- else
- {
- String[] names = this.getRoleAuthorityAsString();
- buff.append('[').append(names[0]);
- for(int i = 1; i < names.length; i++)
- {
- buff.append(", ").append(names[i]);
- }
- buff.append(']');
- }
- return buff.toString();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/SubjectDirectoryAttributes.java b/core/src/main/java/org/bouncycastle/asn1/x509/SubjectDirectoryAttributes.java
deleted file mode 100644
index 95918024..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/SubjectDirectoryAttributes.java
+++ /dev/null
@@ -1,144 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.util.Enumeration;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * This extension may contain further X.500 attributes of the subject. See also
- * RFC 3039.
- *
- * <pre>
- * SubjectDirectoryAttributes ::= Attributes
- * Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
- * Attribute ::= SEQUENCE
- * {
- * type AttributeType
- * values SET OF AttributeValue
- * }
- *
- * AttributeType ::= OBJECT IDENTIFIER
- * AttributeValue ::= ANY DEFINED BY AttributeType
- * </pre>
- *
- * @see org.bouncycastle.asn1.x500.style.BCStyle for AttributeType ObjectIdentifiers.
- */
-public class SubjectDirectoryAttributes
- extends ASN1Object
-{
- private Vector attributes = new Vector();
-
- public static SubjectDirectoryAttributes getInstance(
- Object obj)
- {
- if (obj instanceof SubjectDirectoryAttributes)
- {
- return (SubjectDirectoryAttributes)obj;
- }
-
- if (obj != null)
- {
- return new SubjectDirectoryAttributes(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- /**
- * Constructor from ASN1Sequence.
- *
- * The sequence is of type SubjectDirectoryAttributes:
- *
- * <pre>
- * SubjectDirectoryAttributes ::= Attributes
- * Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
- * Attribute ::= SEQUENCE
- * {
- * type AttributeType
- * values SET OF AttributeValue
- * }
- *
- * AttributeType ::= OBJECT IDENTIFIER
- * AttributeValue ::= ANY DEFINED BY AttributeType
- * </pre>
- *
- * @param seq
- * The ASN.1 sequence.
- */
- private SubjectDirectoryAttributes(ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- while (e.hasMoreElements())
- {
- ASN1Sequence s = ASN1Sequence.getInstance(e.nextElement());
- attributes.addElement(Attribute.getInstance(s));
- }
- }
-
- /**
- * Constructor from a vector of attributes.
- *
- * The vector consists of attributes of type {@link Attribute Attribute}
- *
- * @param attributes
- * The attributes.
- *
- */
- public SubjectDirectoryAttributes(Vector attributes)
- {
- Enumeration e = attributes.elements();
-
- while (e.hasMoreElements())
- {
- this.attributes.addElement(e.nextElement());
- }
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- *
- * Returns:
- *
- * <pre>
- * SubjectDirectoryAttributes ::= Attributes
- * Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
- * Attribute ::= SEQUENCE
- * {
- * type AttributeType
- * values SET OF AttributeValue
- * }
- *
- * AttributeType ::= OBJECT IDENTIFIER
- * AttributeValue ::= ANY DEFINED BY AttributeType
- * </pre>
- *
- * @return a ASN1Primitive
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector vec = new ASN1EncodableVector();
- Enumeration e = attributes.elements();
-
- while (e.hasMoreElements())
- {
-
- vec.add((Attribute)e.nextElement());
- }
-
- return new DERSequence(vec);
- }
-
- /**
- * @return Returns the attributes.
- */
- public Vector getAttributes()
- {
- return attributes;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java b/core/src/main/java/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java
deleted file mode 100644
index 5f0cd079..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DEROctetString;
-
-/**
- * The SubjectKeyIdentifier object.
- * <pre>
- * SubjectKeyIdentifier::= OCTET STRING
- * </pre>
- */
-public class SubjectKeyIdentifier
- extends ASN1Object
-{
- private byte[] keyidentifier;
-
- public static SubjectKeyIdentifier getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1OctetString.getInstance(obj, explicit));
- }
-
- public static SubjectKeyIdentifier getInstance(
- Object obj)
- {
- if (obj instanceof SubjectKeyIdentifier)
- {
- return (SubjectKeyIdentifier)obj;
- }
- else if (obj != null)
- {
- return new SubjectKeyIdentifier(ASN1OctetString.getInstance(obj));
- }
-
- return null;
- }
-
- public static SubjectKeyIdentifier fromExtensions(Extensions extensions)
- {
- return SubjectKeyIdentifier.getInstance(extensions.getExtensionParsedValue(Extension.subjectKeyIdentifier));
- }
-
- public SubjectKeyIdentifier(
- byte[] keyid)
- {
- this.keyidentifier = keyid;
- }
-
- protected SubjectKeyIdentifier(
- ASN1OctetString keyid)
- {
- this.keyidentifier = keyid.getOctets();
- }
-
- public byte[] getKeyIdentifier()
- {
- return keyidentifier;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return new DEROctetString(keyidentifier);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo.java b/core/src/main/java/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo.java
deleted file mode 100644
index 9e09cd72..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo.java
+++ /dev/null
@@ -1,156 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.io.IOException;
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * The object that contains the public key stored in a certficate.
- * <p>
- * The getEncoded() method in the public keys in the JCE produces a DER
- * encoded one of these.
- */
-public class SubjectPublicKeyInfo
- extends ASN1Object
-{
- private AlgorithmIdentifier algId;
- private DERBitString keyData;
-
- public static SubjectPublicKeyInfo getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static SubjectPublicKeyInfo getInstance(
- Object obj)
- {
- if (obj instanceof SubjectPublicKeyInfo)
- {
- return (SubjectPublicKeyInfo)obj;
- }
- else if (obj != null)
- {
- return new SubjectPublicKeyInfo(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public SubjectPublicKeyInfo(
- AlgorithmIdentifier algId,
- ASN1Encodable publicKey)
- throws IOException
- {
- this.keyData = new DERBitString(publicKey);
- this.algId = algId;
- }
-
- public SubjectPublicKeyInfo(
- AlgorithmIdentifier algId,
- byte[] publicKey)
- {
- this.keyData = new DERBitString(publicKey);
- this.algId = algId;
- }
-
- public SubjectPublicKeyInfo(
- ASN1Sequence seq)
- {
- if (seq.size() != 2)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
-
- Enumeration e = seq.getObjects();
-
- this.algId = AlgorithmIdentifier.getInstance(e.nextElement());
- this.keyData = DERBitString.getInstance(e.nextElement());
- }
-
- public AlgorithmIdentifier getAlgorithm()
- {
- return algId;
- }
-
- /**
- * @deprecated use getAlgorithm()
- * @return alg ID.
- */
- public AlgorithmIdentifier getAlgorithmId()
- {
- return algId;
- }
-
- /**
- * for when the public key is an encoded object - if the bitstring
- * can't be decoded this routine throws an IOException.
- *
- * @exception IOException - if the bit string doesn't represent a DER
- * encoded object.
- * @return the public key as an ASN.1 primitive.
- */
- public ASN1Primitive parsePublicKey()
- throws IOException
- {
- ASN1InputStream aIn = new ASN1InputStream(keyData.getBytes());
-
- return aIn.readObject();
- }
-
- /**
- * for when the public key is an encoded object - if the bitstring
- * can't be decoded this routine throws an IOException.
- *
- * @exception IOException - if the bit string doesn't represent a DER
- * encoded object.
- * @deprecated use parsePublicKey
- * @return the public key as an ASN.1 primitive.
- */
- public ASN1Primitive getPublicKey()
- throws IOException
- {
- ASN1InputStream aIn = new ASN1InputStream(keyData.getBytes());
-
- return aIn.readObject();
- }
-
- /**
- * for when the public key is raw bits.
- *
- * @return the public key as the raw bit string...
- */
- public DERBitString getPublicKeyData()
- {
- return keyData;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * SubjectPublicKeyInfo ::= SEQUENCE {
- * algorithm AlgorithmIdentifier,
- * publicKey BIT STRING }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(algId);
- v.add(keyData);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/TBSCertList.java b/core/src/main/java/org/bouncycastle/asn1/x509/TBSCertList.java
deleted file mode 100644
index 5fdbcd67..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/TBSCertList.java
+++ /dev/null
@@ -1,309 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.ASN1UTCTime;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x500.X500Name;
-
-/**
- * PKIX RFC-2459 - TBSCertList object.
- * <pre>
- * TBSCertList ::= SEQUENCE {
- * version Version OPTIONAL,
- * -- if present, shall be v2
- * signature AlgorithmIdentifier,
- * issuer Name,
- * thisUpdate Time,
- * nextUpdate Time OPTIONAL,
- * revokedCertificates SEQUENCE OF SEQUENCE {
- * userCertificate CertificateSerialNumber,
- * revocationDate Time,
- * crlEntryExtensions Extensions OPTIONAL
- * -- if present, shall be v2
- * } OPTIONAL,
- * crlExtensions [0] EXPLICIT Extensions OPTIONAL
- * -- if present, shall be v2
- * }
- * </pre>
- */
-public class TBSCertList
- extends ASN1Object
-{
- public static class CRLEntry
- extends ASN1Object
- {
- ASN1Sequence seq;
-
- Extensions crlEntryExtensions;
-
- private CRLEntry(
- ASN1Sequence seq)
- {
- if (seq.size() < 2 || seq.size() > 3)
- {
- throw new IllegalArgumentException("Bad sequence size: " + seq.size());
- }
-
- this.seq = seq;
- }
-
- public static CRLEntry getInstance(Object o)
- {
- if (o instanceof CRLEntry)
- {
- return ((CRLEntry)o);
- }
- else if (o != null)
- {
- return new CRLEntry(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public ASN1Integer getUserCertificate()
- {
- return ASN1Integer.getInstance(seq.getObjectAt(0));
- }
-
- public Time getRevocationDate()
- {
- return Time.getInstance(seq.getObjectAt(1));
- }
-
- public Extensions getExtensions()
- {
- if (crlEntryExtensions == null && seq.size() == 3)
- {
- crlEntryExtensions = Extensions.getInstance(seq.getObjectAt(2));
- }
-
- return crlEntryExtensions;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return seq;
- }
-
- public boolean hasExtensions()
- {
- return seq.size() == 3;
- }
- }
-
- private class RevokedCertificatesEnumeration
- implements Enumeration
- {
- private final Enumeration en;
-
- RevokedCertificatesEnumeration(Enumeration en)
- {
- this.en = en;
- }
-
- public boolean hasMoreElements()
- {
- return en.hasMoreElements();
- }
-
- public Object nextElement()
- {
- return CRLEntry.getInstance(en.nextElement());
- }
- }
-
- private class EmptyEnumeration
- implements Enumeration
- {
- public boolean hasMoreElements()
- {
- return false;
- }
-
- public Object nextElement()
- {
- return null; // TODO: check exception handling
- }
- }
-
- ASN1Integer version;
- AlgorithmIdentifier signature;
- X500Name issuer;
- Time thisUpdate;
- Time nextUpdate;
- ASN1Sequence revokedCertificates;
- Extensions crlExtensions;
-
- public static TBSCertList getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static TBSCertList getInstance(
- Object obj)
- {
- if (obj instanceof TBSCertList)
- {
- return (TBSCertList)obj;
- }
- else if (obj != null)
- {
- return new TBSCertList(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public TBSCertList(
- ASN1Sequence seq)
- {
- if (seq.size() < 3 || seq.size() > 7)
- {
- throw new IllegalArgumentException("Bad sequence size: " + seq.size());
- }
-
- int seqPos = 0;
-
- if (seq.getObjectAt(seqPos) instanceof ASN1Integer)
- {
- version = ASN1Integer.getInstance(seq.getObjectAt(seqPos++));
- }
- else
- {
- version = null; // version is optional
- }
-
- signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(seqPos++));
- issuer = X500Name.getInstance(seq.getObjectAt(seqPos++));
- thisUpdate = Time.getInstance(seq.getObjectAt(seqPos++));
-
- if (seqPos < seq.size()
- && (seq.getObjectAt(seqPos) instanceof ASN1UTCTime
- || seq.getObjectAt(seqPos) instanceof ASN1GeneralizedTime
- || seq.getObjectAt(seqPos) instanceof Time))
- {
- nextUpdate = Time.getInstance(seq.getObjectAt(seqPos++));
- }
-
- if (seqPos < seq.size()
- && !(seq.getObjectAt(seqPos) instanceof DERTaggedObject))
- {
- revokedCertificates = ASN1Sequence.getInstance(seq.getObjectAt(seqPos++));
- }
-
- if (seqPos < seq.size()
- && seq.getObjectAt(seqPos) instanceof DERTaggedObject)
- {
- crlExtensions = Extensions.getInstance(ASN1Sequence.getInstance((ASN1TaggedObject)seq.getObjectAt(seqPos), true));
- }
- }
-
- public int getVersionNumber()
- {
- if (version == null)
- {
- return 1;
- }
- return version.getValue().intValue() + 1;
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public AlgorithmIdentifier getSignature()
- {
- return signature;
- }
-
- public X500Name getIssuer()
- {
- return issuer;
- }
-
- public Time getThisUpdate()
- {
- return thisUpdate;
- }
-
- public Time getNextUpdate()
- {
- return nextUpdate;
- }
-
- public CRLEntry[] getRevokedCertificates()
- {
- if (revokedCertificates == null)
- {
- return new CRLEntry[0];
- }
-
- CRLEntry[] entries = new CRLEntry[revokedCertificates.size()];
-
- for (int i = 0; i < entries.length; i++)
- {
- entries[i] = CRLEntry.getInstance(revokedCertificates.getObjectAt(i));
- }
-
- return entries;
- }
-
- public Enumeration getRevokedCertificateEnumeration()
- {
- if (revokedCertificates == null)
- {
- return new EmptyEnumeration();
- }
-
- return new RevokedCertificatesEnumeration(revokedCertificates.getObjects());
- }
-
- public Extensions getExtensions()
- {
- return crlExtensions;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (version != null)
- {
- v.add(version);
- }
- v.add(signature);
- v.add(issuer);
-
- v.add(thisUpdate);
- if (nextUpdate != null)
- {
- v.add(nextUpdate);
- }
-
- // Add CRLEntries if they exist
- if (revokedCertificates != null)
- {
- v.add(revokedCertificates);
- }
-
- if (crlExtensions != null)
- {
- v.add(new DERTaggedObject(0, crlExtensions));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/TBSCertificate.java b/core/src/main/java/org/bouncycastle/asn1/x509/TBSCertificate.java
deleted file mode 100644
index dc419649..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/TBSCertificate.java
+++ /dev/null
@@ -1,192 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x500.X500Name;
-
-/**
- * The TBSCertificate object.
- * <pre>
- * TBSCertificate ::= SEQUENCE {
- * version [ 0 ] Version DEFAULT v1(0),
- * serialNumber CertificateSerialNumber,
- * signature AlgorithmIdentifier,
- * issuer Name,
- * validity Validity,
- * subject Name,
- * subjectPublicKeyInfo SubjectPublicKeyInfo,
- * issuerUniqueID [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
- * subjectUniqueID [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
- * extensions [ 3 ] Extensions OPTIONAL
- * }
- * </pre>
- * <p>
- * Note: issuerUniqueID and subjectUniqueID are both deprecated by the IETF. This class
- * will parse them, but you really shouldn't be creating new ones.
- */
-public class TBSCertificate
- extends ASN1Object
-{
- ASN1Sequence seq;
-
- ASN1Integer version;
- ASN1Integer serialNumber;
- AlgorithmIdentifier signature;
- X500Name issuer;
- Time startDate, endDate;
- X500Name subject;
- SubjectPublicKeyInfo subjectPublicKeyInfo;
- DERBitString issuerUniqueId;
- DERBitString subjectUniqueId;
- Extensions extensions;
-
- public static TBSCertificate getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static TBSCertificate getInstance(
- Object obj)
- {
- if (obj instanceof TBSCertificate)
- {
- return (TBSCertificate)obj;
- }
- else if (obj != null)
- {
- return new TBSCertificate(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private TBSCertificate(
- ASN1Sequence seq)
- {
- int seqStart = 0;
-
- this.seq = seq;
-
- //
- // some certficates don't include a version number - we assume v1
- //
- if (seq.getObjectAt(0) instanceof DERTaggedObject)
- {
- version = ASN1Integer.getInstance((ASN1TaggedObject)seq.getObjectAt(0), true);
- }
- else
- {
- seqStart = -1; // field 0 is missing!
- version = new ASN1Integer(0);
- }
-
- serialNumber = ASN1Integer.getInstance(seq.getObjectAt(seqStart + 1));
-
- signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(seqStart + 2));
- issuer = X500Name.getInstance(seq.getObjectAt(seqStart + 3));
-
- //
- // before and after dates
- //
- ASN1Sequence dates = (ASN1Sequence)seq.getObjectAt(seqStart + 4);
-
- startDate = Time.getInstance(dates.getObjectAt(0));
- endDate = Time.getInstance(dates.getObjectAt(1));
-
- subject = X500Name.getInstance(seq.getObjectAt(seqStart + 5));
-
- //
- // public key info.
- //
- subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(seqStart + 6));
-
- for (int extras = seq.size() - (seqStart + 6) - 1; extras > 0; extras--)
- {
- DERTaggedObject extra = (DERTaggedObject)seq.getObjectAt(seqStart + 6 + extras);
-
- switch (extra.getTagNo())
- {
- case 1:
- issuerUniqueId = DERBitString.getInstance(extra, false);
- break;
- case 2:
- subjectUniqueId = DERBitString.getInstance(extra, false);
- break;
- case 3:
- extensions = Extensions.getInstance(ASN1Sequence.getInstance(extra, true));
- }
- }
- }
-
- public int getVersionNumber()
- {
- return version.getValue().intValue() + 1;
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- public ASN1Integer getSerialNumber()
- {
- return serialNumber;
- }
-
- public AlgorithmIdentifier getSignature()
- {
- return signature;
- }
-
- public X500Name getIssuer()
- {
- return issuer;
- }
-
- public Time getStartDate()
- {
- return startDate;
- }
-
- public Time getEndDate()
- {
- return endDate;
- }
-
- public X500Name getSubject()
- {
- return subject;
- }
-
- public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
- {
- return subjectPublicKeyInfo;
- }
-
- public DERBitString getIssuerUniqueId()
- {
- return issuerUniqueId;
- }
-
- public DERBitString getSubjectUniqueId()
- {
- return subjectUniqueId;
- }
-
- public Extensions getExtensions()
- {
- return extensions;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return seq;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/TBSCertificateStructure.java b/core/src/main/java/org/bouncycastle/asn1/x509/TBSCertificateStructure.java
deleted file mode 100644
index 2c5d920a..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/TBSCertificateStructure.java
+++ /dev/null
@@ -1,194 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.asn1.x500.X500Name;
-
-/**
- * The TBSCertificate object.
- * <pre>
- * TBSCertificate ::= SEQUENCE {
- * version [ 0 ] Version DEFAULT v1(0),
- * serialNumber CertificateSerialNumber,
- * signature AlgorithmIdentifier,
- * issuer Name,
- * validity Validity,
- * subject Name,
- * subjectPublicKeyInfo SubjectPublicKeyInfo,
- * issuerUniqueID [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
- * subjectUniqueID [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
- * extensions [ 3 ] Extensions OPTIONAL
- * }
- * </pre>
- * <p>
- * Note: issuerUniqueID and subjectUniqueID are both deprecated by the IETF. This class
- * will parse them, but you really shouldn't be creating new ones.
- */
-public class TBSCertificateStructure
- extends ASN1Object
- implements X509ObjectIdentifiers, PKCSObjectIdentifiers
-{
- ASN1Sequence seq;
-
- ASN1Integer version;
- ASN1Integer serialNumber;
- AlgorithmIdentifier signature;
- X500Name issuer;
- Time startDate, endDate;
- X500Name subject;
- SubjectPublicKeyInfo subjectPublicKeyInfo;
- DERBitString issuerUniqueId;
- DERBitString subjectUniqueId;
- X509Extensions extensions;
-
- public static TBSCertificateStructure getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static TBSCertificateStructure getInstance(
- Object obj)
- {
- if (obj instanceof TBSCertificateStructure)
- {
- return (TBSCertificateStructure)obj;
- }
- else if (obj != null)
- {
- return new TBSCertificateStructure(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public TBSCertificateStructure(
- ASN1Sequence seq)
- {
- int seqStart = 0;
-
- this.seq = seq;
-
- //
- // some certficates don't include a version number - we assume v1
- //
- if (seq.getObjectAt(0) instanceof DERTaggedObject)
- {
- version = ASN1Integer.getInstance((ASN1TaggedObject)seq.getObjectAt(0), true);
- }
- else
- {
- seqStart = -1; // field 0 is missing!
- version = new ASN1Integer(0);
- }
-
- serialNumber = ASN1Integer.getInstance(seq.getObjectAt(seqStart + 1));
-
- signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(seqStart + 2));
- issuer = X500Name.getInstance(seq.getObjectAt(seqStart + 3));
-
- //
- // before and after dates
- //
- ASN1Sequence dates = (ASN1Sequence)seq.getObjectAt(seqStart + 4);
-
- startDate = Time.getInstance(dates.getObjectAt(0));
- endDate = Time.getInstance(dates.getObjectAt(1));
-
- subject = X500Name.getInstance(seq.getObjectAt(seqStart + 5));
-
- //
- // public key info.
- //
- subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(seqStart + 6));
-
- for (int extras = seq.size() - (seqStart + 6) - 1; extras > 0; extras--)
- {
- DERTaggedObject extra = (DERTaggedObject)seq.getObjectAt(seqStart + 6 + extras);
-
- switch (extra.getTagNo())
- {
- case 1:
- issuerUniqueId = DERBitString.getInstance(extra, false);
- break;
- case 2:
- subjectUniqueId = DERBitString.getInstance(extra, false);
- break;
- case 3:
- extensions = X509Extensions.getInstance(extra);
- }
- }
- }
-
- public int getVersion()
- {
- return version.getValue().intValue() + 1;
- }
-
- public ASN1Integer getVersionNumber()
- {
- return version;
- }
-
- public ASN1Integer getSerialNumber()
- {
- return serialNumber;
- }
-
- public AlgorithmIdentifier getSignature()
- {
- return signature;
- }
-
- public X500Name getIssuer()
- {
- return issuer;
- }
-
- public Time getStartDate()
- {
- return startDate;
- }
-
- public Time getEndDate()
- {
- return endDate;
- }
-
- public X500Name getSubject()
- {
- return subject;
- }
-
- public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
- {
- return subjectPublicKeyInfo;
- }
-
- public DERBitString getIssuerUniqueId()
- {
- return issuerUniqueId;
- }
-
- public DERBitString getSubjectUniqueId()
- {
- return subjectUniqueId;
- }
-
- public X509Extensions getExtensions()
- {
- return extensions;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return seq;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/Target.java b/core/src/main/java/org/bouncycastle/asn1/x509/Target.java
deleted file mode 100644
index b302f5a2..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/Target.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * Target structure used in target information extension for attribute
- * certificates from RFC 3281.
- *
- * <pre>
- * Target ::= CHOICE {
- * targetName [0] GeneralName,
- * targetGroup [1] GeneralName,
- * targetCert [2] TargetCert
- * }
- * </pre>
- *
- * <p>
- * The targetCert field is currently not supported and must not be used
- * according to RFC 3281.
- */
-public class Target
- extends ASN1Object
- implements ASN1Choice
-{
- public static final int targetName = 0;
- public static final int targetGroup = 1;
-
- private GeneralName targName;
- private GeneralName targGroup;
-
- /**
- * Creates an instance of a Target from the given object.
- * <p>
- * <code>obj</code> can be a Target or a {@link ASN1TaggedObject}
- *
- * @param obj The object.
- * @return A Target instance.
- * @throws IllegalArgumentException if the given object cannot be
- * interpreted as Target.
- */
- public static Target getInstance(Object obj)
- {
- if (obj == null || obj instanceof Target)
- {
- return (Target) obj;
- }
- else if (obj instanceof ASN1TaggedObject)
- {
- return new Target((ASN1TaggedObject)obj);
- }
-
- throw new IllegalArgumentException("unknown object in factory: "
- + obj.getClass());
- }
-
- /**
- * Constructor from ASN1TaggedObject.
- *
- * @param tagObj The tagged object.
- * @throws IllegalArgumentException if the encoding is wrong.
- */
- private Target(ASN1TaggedObject tagObj)
- {
- switch (tagObj.getTagNo())
- {
- case targetName: // GeneralName is already a choice so explicit
- targName = GeneralName.getInstance(tagObj, true);
- break;
- case targetGroup:
- targGroup = GeneralName.getInstance(tagObj, true);
- break;
- default:
- throw new IllegalArgumentException("unknown tag: " + tagObj.getTagNo());
- }
- }
-
- /**
- * Constructor from given details.
- * <p>
- * Exactly one of the parameters must be not <code>null</code>.
- *
- * @param type the choice type to apply to the name.
- * @param name the general name.
- * @throws IllegalArgumentException if type is invalid.
- */
- public Target(int type, GeneralName name)
- {
- this(new DERTaggedObject(type, name));
- }
-
- /**
- * @return Returns the targetGroup.
- */
- public GeneralName getTargetGroup()
- {
- return targGroup;
- }
-
- /**
- * @return Returns the targetName.
- */
- public GeneralName getTargetName()
- {
- return targName;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- *
- * Returns:
- *
- * <pre>
- * Target ::= CHOICE {
- * targetName [0] GeneralName,
- * targetGroup [1] GeneralName,
- * targetCert [2] TargetCert
- * }
- * </pre>
- *
- * @return a ASN1Primitive
- */
- public ASN1Primitive toASN1Primitive()
- {
- // GeneralName is a choice already so most be explicitly tagged
- if (targName != null)
- {
- return new DERTaggedObject(true, 0, targName);
- }
- else
- {
- return new DERTaggedObject(true, 1, targGroup);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/TargetInformation.java b/core/src/main/java/org/bouncycastle/asn1/x509/TargetInformation.java
deleted file mode 100644
index eb892b9d..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/TargetInformation.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * Target information extension for attributes certificates according to RFC
- * 3281.
- *
- * <pre>
- * SEQUENCE OF Targets
- * </pre>
- *
- */
-public class TargetInformation
- extends ASN1Object
-{
- private ASN1Sequence targets;
-
- /**
- * Creates an instance of a TargetInformation from the given object.
- * <p>
- * <code>obj</code> can be a TargetInformation or a {@link ASN1Sequence}
- *
- * @param obj The object.
- * @return A TargetInformation instance.
- * @throws IllegalArgumentException if the given object cannot be
- * interpreted as TargetInformation.
- */
- public static TargetInformation getInstance(Object obj)
- {
- if (obj instanceof TargetInformation)
- {
- return (TargetInformation)obj;
- }
- else if (obj != null)
- {
- return new TargetInformation(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- /**
- * Constructor from a ASN1Sequence.
- *
- * @param seq The ASN1Sequence.
- * @throws IllegalArgumentException if the sequence does not contain
- * correctly encoded Targets elements.
- */
- private TargetInformation(ASN1Sequence seq)
- {
- targets = seq;
- }
-
- /**
- * Returns the targets in this target information extension.
- *
- * @return Returns the targets.
- */
- public Targets[] getTargetsObjects()
- {
- Targets[] copy = new Targets[targets.size()];
- int count = 0;
- for (Enumeration e = targets.getObjects(); e.hasMoreElements();)
- {
- copy[count++] = Targets.getInstance(e.nextElement());
- }
- return copy;
- }
-
- /**
- * Constructs a target information from a single targets element.
- * According to RFC 3281 only one targets element must be produced.
- *
- * @param targets A Targets instance.
- */
- public TargetInformation(Targets targets)
- {
- this.targets = new DERSequence(targets);
- }
-
- /**
- * According to RFC 3281 only one targets element must be produced. If
- * multiple targets are given they must be merged in
- * into one targets element.
- *
- * @param targets An array with {@link Targets}.
- */
- public TargetInformation(Target[] targets)
- {
- this(new Targets(targets));
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- *
- * Returns:
- *
- * <pre>
- * SEQUENCE OF Targets
- * </pre>
- *
- * <p>
- * According to RFC 3281 only one targets element must be produced. If
- * multiple targets are given in the constructor they are merged into one
- * targets element. If this was produced from a
- * {@link org.bouncycastle.asn1.ASN1Sequence} the encoding is kept.
- *
- * @return a ASN1Primitive
- */
- public ASN1Primitive toASN1Primitive()
- {
- return targets;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/Targets.java b/core/src/main/java/org/bouncycastle/asn1/x509/Targets.java
deleted file mode 100644
index 4c7d0625..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/Targets.java
+++ /dev/null
@@ -1,121 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * Targets structure used in target information extension for attribute
- * certificates from RFC 3281.
- *
- * <pre>
- * Targets ::= SEQUENCE OF Target
- *
- * Target ::= CHOICE {
- * targetName [0] GeneralName,
- * targetGroup [1] GeneralName,
- * targetCert [2] TargetCert
- * }
- *
- * TargetCert ::= SEQUENCE {
- * targetCertificate IssuerSerial,
- * targetName GeneralName OPTIONAL,
- * certDigestInfo ObjectDigestInfo OPTIONAL
- * }
- * </pre>
- *
- * @see org.bouncycastle.asn1.x509.Target
- * @see org.bouncycastle.asn1.x509.TargetInformation
- */
-public class Targets
- extends ASN1Object
-{
- private ASN1Sequence targets;
-
- /**
- * Creates an instance of a Targets from the given object.
- * <p>
- * <code>obj</code> can be a Targets or a {@link ASN1Sequence}
- *
- * @param obj The object.
- * @return A Targets instance.
- * @throws IllegalArgumentException if the given object cannot be
- * interpreted as Target.
- */
- public static Targets getInstance(Object obj)
- {
- if (obj instanceof Targets)
- {
- return (Targets)obj;
- }
- else if (obj != null)
- {
- return new Targets(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- /**
- * Constructor from ASN1Sequence.
- *
- * @param targets The ASN.1 SEQUENCE.
- * @throws IllegalArgumentException if the contents of the sequence are
- * invalid.
- */
- private Targets(ASN1Sequence targets)
- {
- this.targets = targets;
- }
-
- /**
- * Constructor from given targets.
- * <p>
- * The vector is copied.
- *
- * @param targets A <code>Vector</code> of {@link Target}s.
- * @see Target
- * @throws IllegalArgumentException if the vector contains not only Targets.
- */
- public Targets(Target[] targets)
- {
- this.targets = new DERSequence(targets);
- }
-
- /**
- * Returns the targets in a <code>Vector</code>.
- * <p>
- * The vector is cloned before it is returned.
- *
- * @return Returns the targets.
- */
- public Target[] getTargets()
- {
- Target[] targs = new Target[targets.size()];
- int count = 0;
- for (Enumeration e = targets.getObjects(); e.hasMoreElements();)
- {
- targs[count++] = Target.getInstance(e.nextElement());
- }
- return targs;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- *
- * Returns:
- *
- * <pre>
- * Targets ::= SEQUENCE OF Target
- * </pre>
- *
- * @return a ASN1Primitive
- */
- public ASN1Primitive toASN1Primitive()
- {
- return targets;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/Time.java b/core/src/main/java/org/bouncycastle/asn1/x509/Time.java
deleted file mode 100644
index 77d36b31..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/Time.java
+++ /dev/null
@@ -1,169 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-import java.util.SimpleTimeZone;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.ASN1UTCTime;
-import org.bouncycastle.asn1.DERGeneralizedTime;
-import org.bouncycastle.asn1.DERUTCTime;
-
-public class Time
- extends ASN1Object
- implements ASN1Choice
-{
- ASN1Primitive time;
-
- public static Time getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject()); // must be explicitly tagged
- }
-
- public Time(
- ASN1Primitive time)
- {
- if (!(time instanceof ASN1UTCTime)
- && !(time instanceof ASN1GeneralizedTime))
- {
- throw new IllegalArgumentException("unknown object passed to Time");
- }
-
- this.time = time;
- }
-
- /**
- * Creates a time object from a given date - if the date is between 1950
- * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
- * is used.
- *
- * @param time a date object representing the time of interest.
- */
- public Time(
- Date time)
- {
- SimpleTimeZone tz = new SimpleTimeZone(0, "Z");
- SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss");
-
- dateF.setTimeZone(tz);
-
- String d = dateF.format(time) + "Z";
- int year = Integer.parseInt(d.substring(0, 4));
-
- if (year < 1950 || year > 2049)
- {
- this.time = new DERGeneralizedTime(d);
- }
- else
- {
- this.time = new DERUTCTime(d.substring(2));
- }
- }
-
- /**
- * Creates a time object from a given date and locale - if the date is between 1950
- * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
- * is used. You may need to use this constructor if the default locale
- * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible with other ASN.1 implementations.
- *
- * @param time a date object representing the time of interest.
- * @param locale an appropriate Locale for producing an ASN.1 GeneralizedTime value.
- */
- public Time(
- Date time,
- Locale locale)
- {
- SimpleTimeZone tz = new SimpleTimeZone(0, "Z");
- SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss", locale);
-
- dateF.setTimeZone(tz);
-
- String d = dateF.format(time) + "Z";
- int year = Integer.parseInt(d.substring(0, 4));
-
- if (year < 1950 || year > 2049)
- {
- this.time = new DERGeneralizedTime(d);
- }
- else
- {
- this.time = new DERUTCTime(d.substring(2));
- }
- }
-
- public static Time getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof Time)
- {
- return (Time)obj;
- }
- else if (obj instanceof ASN1UTCTime)
- {
- return new Time((ASN1UTCTime)obj);
- }
- else if (obj instanceof ASN1GeneralizedTime)
- {
- return new Time((ASN1GeneralizedTime)obj);
- }
-
- throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
- }
-
- public String getTime()
- {
- if (time instanceof ASN1UTCTime)
- {
- return ((ASN1UTCTime)time).getAdjustedTime();
- }
- else
- {
- return ((ASN1GeneralizedTime)time).getTime();
- }
- }
-
- public Date getDate()
- {
- try
- {
- if (time instanceof ASN1UTCTime)
- {
- return ((ASN1UTCTime)time).getAdjustedDate();
- }
- else
- {
- return ((ASN1GeneralizedTime)time).getDate();
- }
- }
- catch (ParseException e)
- { // this should never happen
- throw new IllegalStateException("invalid date string: " + e.getMessage());
- }
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * Time ::= CHOICE {
- * utcTime UTCTime,
- * generalTime GeneralizedTime }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- return time;
- }
-
- public String toString()
- {
- return getTime();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/UserNotice.java b/core/src/main/java/org/bouncycastle/asn1/x509/UserNotice.java
deleted file mode 100644
index ebc04051..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/UserNotice.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * <code>UserNotice</code> class, used in
- * <code>CertificatePolicies</code> X509 extensions (in policy
- * qualifiers).
- * <pre>
- * UserNotice ::= SEQUENCE {
- * noticeRef NoticeReference OPTIONAL,
- * explicitText DisplayText OPTIONAL}
- *
- * </pre>
- *
- * @see PolicyQualifierId
- * @see PolicyInformation
- */
-public class UserNotice
- extends ASN1Object
-{
- private NoticeReference noticeRef;
- private DisplayText explicitText;
-
- /**
- * Creates a new <code>UserNotice</code> instance.
- *
- * @param noticeRef a <code>NoticeReference</code> value
- * @param explicitText a <code>DisplayText</code> value
- */
- public UserNotice(
- NoticeReference noticeRef,
- DisplayText explicitText)
- {
- this.noticeRef = noticeRef;
- this.explicitText = explicitText;
- }
-
- /**
- * Creates a new <code>UserNotice</code> instance.
- *
- * @param noticeRef a <code>NoticeReference</code> value
- * @param str the explicitText field as a String.
- */
- public UserNotice(
- NoticeReference noticeRef,
- String str)
- {
- this(noticeRef, new DisplayText(str));
- }
-
- /**
- * Creates a new <code>UserNotice</code> instance.
- * <p>Useful from reconstructing a <code>UserNotice</code> instance
- * from its encodable/encoded form.
- *
- * @param as an <code>ASN1Sequence</code> value obtained from either
- * calling @{link toASN1Primitive()} for a <code>UserNotice</code>
- * instance or from parsing it from a DER-encoded stream.
- */
- private UserNotice(
- ASN1Sequence as)
- {
- if (as.size() == 2)
- {
- noticeRef = NoticeReference.getInstance(as.getObjectAt(0));
- explicitText = DisplayText.getInstance(as.getObjectAt(1));
- }
- else if (as.size() == 1)
- {
- if (as.getObjectAt(0).toASN1Primitive() instanceof ASN1Sequence)
- {
- noticeRef = NoticeReference.getInstance(as.getObjectAt(0));
- }
- else
- {
- explicitText = DisplayText.getInstance(as.getObjectAt(0));
- }
- }
- else
- {
- throw new IllegalArgumentException("Bad sequence size: " + as.size());
- }
- }
-
- public static UserNotice getInstance(
- Object obj)
- {
- if (obj instanceof UserNotice)
- {
- return (UserNotice)obj;
- }
-
- if (obj != null)
- {
- return new UserNotice(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public NoticeReference getNoticeRef()
- {
- return noticeRef;
- }
-
- public DisplayText getExplicitText()
- {
- return explicitText;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector av = new ASN1EncodableVector();
-
- if (noticeRef != null)
- {
- av.add(noticeRef);
- }
-
- if (explicitText != null)
- {
- av.add(explicitText);
- }
-
- return new DERSequence(av);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/V1TBSCertificateGenerator.java b/core/src/main/java/org/bouncycastle/asn1/x509/V1TBSCertificateGenerator.java
deleted file mode 100644
index fe4cb5eb..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/V1TBSCertificateGenerator.java
+++ /dev/null
@@ -1,144 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1UTCTime;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x500.X500Name;
-
-/**
- * Generator for Version 1 TBSCertificateStructures.
- * <pre>
- * TBSCertificate ::= SEQUENCE {
- * version [ 0 ] Version DEFAULT v1(0),
- * serialNumber CertificateSerialNumber,
- * signature AlgorithmIdentifier,
- * issuer Name,
- * validity Validity,
- * subject Name,
- * subjectPublicKeyInfo SubjectPublicKeyInfo,
- * }
- * </pre>
- *
- */
-public class V1TBSCertificateGenerator
-{
- DERTaggedObject version = new DERTaggedObject(true, 0, new ASN1Integer(0));
-
- ASN1Integer serialNumber;
- AlgorithmIdentifier signature;
- X500Name issuer;
- Time startDate, endDate;
- X500Name subject;
- SubjectPublicKeyInfo subjectPublicKeyInfo;
-
- public V1TBSCertificateGenerator()
- {
- }
-
- public void setSerialNumber(
- ASN1Integer serialNumber)
- {
- this.serialNumber = serialNumber;
- }
-
- public void setSignature(
- AlgorithmIdentifier signature)
- {
- this.signature = signature;
- }
-
- /**
- * @deprecated use X500Name method
- */
- public void setIssuer(
- X509Name issuer)
- {
- this.issuer = X500Name.getInstance(issuer.toASN1Primitive());
- }
-
- public void setIssuer(
- X500Name issuer)
- {
- this.issuer = issuer;
- }
-
- public void setStartDate(
- Time startDate)
- {
- this.startDate = startDate;
- }
-
- public void setStartDate(
- ASN1UTCTime startDate)
- {
- this.startDate = new Time(startDate);
- }
-
- public void setEndDate(
- Time endDate)
- {
- this.endDate = endDate;
- }
-
- public void setEndDate(
- ASN1UTCTime endDate)
- {
- this.endDate = new Time(endDate);
- }
-
- /**
- * @deprecated use X500Name method
- */
- public void setSubject(
- X509Name subject)
- {
- this.subject = X500Name.getInstance(subject.toASN1Primitive());
- }
-
- public void setSubject(
- X500Name subject)
- {
- this.subject = subject;
- }
-
- public void setSubjectPublicKeyInfo(
- SubjectPublicKeyInfo pubKeyInfo)
- {
- this.subjectPublicKeyInfo = pubKeyInfo;
- }
-
- public TBSCertificate generateTBSCertificate()
- {
- if ((serialNumber == null) || (signature == null)
- || (issuer == null) || (startDate == null) || (endDate == null)
- || (subject == null) || (subjectPublicKeyInfo == null))
- {
- throw new IllegalStateException("not all mandatory fields set in V1 TBScertificate generator");
- }
-
- ASN1EncodableVector seq = new ASN1EncodableVector();
-
- // seq.add(version); - not required as default value.
- seq.add(serialNumber);
- seq.add(signature);
- seq.add(issuer);
-
- //
- // before and after dates
- //
- ASN1EncodableVector validity = new ASN1EncodableVector();
-
- validity.add(startDate);
- validity.add(endDate);
-
- seq.add(new DERSequence(validity));
-
- seq.add(subject);
-
- seq.add(subjectPublicKeyInfo);
-
- return TBSCertificate.getInstance(new DERSequence(seq));
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/V2AttributeCertificateInfoGenerator.java b/core/src/main/java/org/bouncycastle/asn1/x509/V2AttributeCertificateInfoGenerator.java
deleted file mode 100644
index 635a69e8..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/V2AttributeCertificateInfoGenerator.java
+++ /dev/null
@@ -1,158 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERSet;
-
-/**
- * Generator for Version 2 AttributeCertificateInfo
- * <pre>
- * AttributeCertificateInfo ::= SEQUENCE {
- * version AttCertVersion -- version is v2,
- * holder Holder,
- * issuer AttCertIssuer,
- * signature AlgorithmIdentifier,
- * serialNumber CertificateSerialNumber,
- * attrCertValidityPeriod AttCertValidityPeriod,
- * attributes SEQUENCE OF Attribute,
- * issuerUniqueID UniqueIdentifier OPTIONAL,
- * extensions Extensions OPTIONAL
- * }
- * </pre>
- *
- */
-public class V2AttributeCertificateInfoGenerator
-{
- private ASN1Integer version;
- private Holder holder;
- private AttCertIssuer issuer;
- private AlgorithmIdentifier signature;
- private ASN1Integer serialNumber;
- private ASN1EncodableVector attributes;
- private DERBitString issuerUniqueID;
- private Extensions extensions;
-
- // Note: validity period start/end dates stored directly
- //private AttCertValidityPeriod attrCertValidityPeriod;
- private ASN1GeneralizedTime startDate, endDate;
-
- public V2AttributeCertificateInfoGenerator()
- {
- this.version = new ASN1Integer(1);
- attributes = new ASN1EncodableVector();
- }
-
- public void setHolder(Holder holder)
- {
- this.holder = holder;
- }
-
- public void addAttribute(String oid, ASN1Encodable value)
- {
- attributes.add(new Attribute(new ASN1ObjectIdentifier(oid), new DERSet(value)));
- }
-
- /**
- * @param attribute
- */
- public void addAttribute(Attribute attribute)
- {
- attributes.add(attribute);
- }
-
- public void setSerialNumber(
- ASN1Integer serialNumber)
- {
- this.serialNumber = serialNumber;
- }
-
- public void setSignature(
- AlgorithmIdentifier signature)
- {
- this.signature = signature;
- }
-
- public void setIssuer(
- AttCertIssuer issuer)
- {
- this.issuer = issuer;
- }
-
- public void setStartDate(
- ASN1GeneralizedTime startDate)
- {
- this.startDate = startDate;
- }
-
- public void setEndDate(
- ASN1GeneralizedTime endDate)
- {
- this.endDate = endDate;
- }
-
- public void setIssuerUniqueID(
- DERBitString issuerUniqueID)
- {
- this.issuerUniqueID = issuerUniqueID;
- }
-
- /**
- * @deprecated use method taking Extensions
- * @param extensions
- */
- public void setExtensions(
- X509Extensions extensions)
- {
- this.extensions = Extensions.getInstance(extensions.toASN1Primitive());
- }
-
- public void setExtensions(
- Extensions extensions)
- {
- this.extensions = extensions;
- }
-
- public AttributeCertificateInfo generateAttributeCertificateInfo()
- {
- if ((serialNumber == null) || (signature == null)
- || (issuer == null) || (startDate == null) || (endDate == null)
- || (holder == null) || (attributes == null))
- {
- throw new IllegalStateException("not all mandatory fields set in V2 AttributeCertificateInfo generator");
- }
-
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(version);
- v.add(holder);
- v.add(issuer);
- v.add(signature);
- v.add(serialNumber);
-
- //
- // before and after dates => AttCertValidityPeriod
- //
- AttCertValidityPeriod validity = new AttCertValidityPeriod(startDate, endDate);
- v.add(validity);
-
- // Attributes
- v.add(new DERSequence(attributes));
-
- if (issuerUniqueID != null)
- {
- v.add(issuerUniqueID);
- }
-
- if (extensions != null)
- {
- v.add(extensions);
- }
-
- return AttributeCertificateInfo.getInstance(new DERSequence(v));
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/V2Form.java b/core/src/main/java/org/bouncycastle/asn1/x509/V2Form.java
deleted file mode 100644
index 5cee8471..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/V2Form.java
+++ /dev/null
@@ -1,157 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-public class V2Form
- extends ASN1Object
-{
- GeneralNames issuerName;
- IssuerSerial baseCertificateID;
- ObjectDigestInfo objectDigestInfo;
-
- public static V2Form getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static V2Form getInstance(
- Object obj)
- {
- if (obj instanceof V2Form)
- {
- return (V2Form)obj;
- }
- else if (obj != null)
- {
- return new V2Form(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public V2Form(
- GeneralNames issuerName)
- {
- this(issuerName, null, null);
- }
-
- public V2Form(
- GeneralNames issuerName,
- IssuerSerial baseCertificateID)
- {
- this(issuerName, baseCertificateID, null);
- }
-
- public V2Form(
- GeneralNames issuerName,
- ObjectDigestInfo objectDigestInfo)
- {
- this(issuerName, null, objectDigestInfo);
- }
-
- public V2Form(
- GeneralNames issuerName,
- IssuerSerial baseCertificateID,
- ObjectDigestInfo objectDigestInfo)
- {
- this.issuerName = issuerName;
- this.baseCertificateID = baseCertificateID;
- this.objectDigestInfo = objectDigestInfo;
- }
-
- /**
- * @deprecated use getInstance().
- */
- public V2Form(
- ASN1Sequence seq)
- {
- if (seq.size() > 3)
- {
- throw new IllegalArgumentException("Bad sequence size: " + seq.size());
- }
-
- int index = 0;
-
- if (!(seq.getObjectAt(0) instanceof ASN1TaggedObject))
- {
- index++;
- this.issuerName = GeneralNames.getInstance(seq.getObjectAt(0));
- }
-
- for (int i = index; i != seq.size(); i++)
- {
- ASN1TaggedObject o = ASN1TaggedObject.getInstance(seq.getObjectAt(i));
- if (o.getTagNo() == 0)
- {
- baseCertificateID = IssuerSerial.getInstance(o, false);
- }
- else if (o.getTagNo() == 1)
- {
- objectDigestInfo = ObjectDigestInfo.getInstance(o, false);
- }
- else
- {
- throw new IllegalArgumentException("Bad tag number: "
- + o.getTagNo());
- }
- }
- }
-
- public GeneralNames getIssuerName()
- {
- return issuerName;
- }
-
- public IssuerSerial getBaseCertificateID()
- {
- return baseCertificateID;
- }
-
- public ObjectDigestInfo getObjectDigestInfo()
- {
- return objectDigestInfo;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * V2Form ::= SEQUENCE {
- * issuerName GeneralNames OPTIONAL,
- * baseCertificateID [0] IssuerSerial OPTIONAL,
- * objectDigestInfo [1] ObjectDigestInfo OPTIONAL
- * -- issuerName MUST be present in this profile
- * -- baseCertificateID and objectDigestInfo MUST NOT
- * -- be present in this profile
- * }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (issuerName != null)
- {
- v.add(issuerName);
- }
-
- if (baseCertificateID != null)
- {
- v.add(new DERTaggedObject(false, 0, baseCertificateID));
- }
-
- if (objectDigestInfo != null)
- {
- v.add(new DERTaggedObject(false, 1, objectDigestInfo));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/V2TBSCertListGenerator.java b/core/src/main/java/org/bouncycastle/asn1/x509/V2TBSCertListGenerator.java
deleted file mode 100644
index 869f5bc5..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/V2TBSCertListGenerator.java
+++ /dev/null
@@ -1,281 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1UTCTime;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x500.X500Name;
-
-/**
- * Generator for Version 2 TBSCertList structures.
- * <pre>
- * TBSCertList ::= SEQUENCE {
- * version Version OPTIONAL,
- * -- if present, shall be v2
- * signature AlgorithmIdentifier,
- * issuer Name,
- * thisUpdate Time,
- * nextUpdate Time OPTIONAL,
- * revokedCertificates SEQUENCE OF SEQUENCE {
- * userCertificate CertificateSerialNumber,
- * revocationDate Time,
- * crlEntryExtensions Extensions OPTIONAL
- * -- if present, shall be v2
- * } OPTIONAL,
- * crlExtensions [0] EXPLICIT Extensions OPTIONAL
- * -- if present, shall be v2
- * }
- * </pre>
- *
- * <b>Note: This class may be subject to change</b>
- */
-public class V2TBSCertListGenerator
-{
- private ASN1Integer version = new ASN1Integer(1);
- private AlgorithmIdentifier signature;
- private X500Name issuer;
- private Time thisUpdate, nextUpdate=null;
- private Extensions extensions = null;
- private ASN1EncodableVector crlentries = new ASN1EncodableVector();
-
- private final static ASN1Sequence[] reasons;
-
- static
- {
- reasons = new ASN1Sequence[11];
-
- reasons[0] = createReasonExtension(CRLReason.unspecified);
- reasons[1] = createReasonExtension(CRLReason.keyCompromise);
- reasons[2] = createReasonExtension(CRLReason.cACompromise);
- reasons[3] = createReasonExtension(CRLReason.affiliationChanged);
- reasons[4] = createReasonExtension(CRLReason.superseded);
- reasons[5] = createReasonExtension(CRLReason.cessationOfOperation);
- reasons[6] = createReasonExtension(CRLReason.certificateHold);
- reasons[7] = createReasonExtension(7); // 7 -> unknown
- reasons[8] = createReasonExtension(CRLReason.removeFromCRL);
- reasons[9] = createReasonExtension(CRLReason.privilegeWithdrawn);
- reasons[10] = createReasonExtension(CRLReason.aACompromise);
- }
-
- public V2TBSCertListGenerator()
- {
- }
-
-
- public void setSignature(
- AlgorithmIdentifier signature)
- {
- this.signature = signature;
- }
-
- /**
- * @deprecated use X500Name method
- */
- public void setIssuer(
- X509Name issuer)
- {
- this.issuer = X500Name.getInstance(issuer.toASN1Primitive());
- }
-
- public void setIssuer(X500Name issuer)
- {
- this.issuer = issuer;
- }
-
- public void setThisUpdate(
- ASN1UTCTime thisUpdate)
- {
- this.thisUpdate = new Time(thisUpdate);
- }
-
- public void setNextUpdate(
- ASN1UTCTime nextUpdate)
- {
- this.nextUpdate = new Time(nextUpdate);
- }
-
- public void setThisUpdate(
- Time thisUpdate)
- {
- this.thisUpdate = thisUpdate;
- }
-
- public void setNextUpdate(
- Time nextUpdate)
- {
- this.nextUpdate = nextUpdate;
- }
-
- public void addCRLEntry(
- ASN1Sequence crlEntry)
- {
- crlentries.add(crlEntry);
- }
-
- public void addCRLEntry(ASN1Integer userCertificate, ASN1UTCTime revocationDate, int reason)
- {
- addCRLEntry(userCertificate, new Time(revocationDate), reason);
- }
-
- public void addCRLEntry(ASN1Integer userCertificate, Time revocationDate, int reason)
- {
- addCRLEntry(userCertificate, revocationDate, reason, null);
- }
-
- public void addCRLEntry(ASN1Integer userCertificate, Time revocationDate, int reason, ASN1GeneralizedTime invalidityDate)
- {
- if (reason != 0)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (reason < reasons.length)
- {
- if (reason < 0)
- {
- throw new IllegalArgumentException("invalid reason value: " + reason);
- }
- v.add(reasons[reason]);
- }
- else
- {
- v.add(createReasonExtension(reason));
- }
-
- if (invalidityDate != null)
- {
- v.add(createInvalidityDateExtension(invalidityDate));
- }
-
- internalAddCRLEntry(userCertificate, revocationDate, new DERSequence(v));
- }
- else if (invalidityDate != null)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(createInvalidityDateExtension(invalidityDate));
-
- internalAddCRLEntry(userCertificate, revocationDate, new DERSequence(v));
- }
- else
- {
- addCRLEntry(userCertificate, revocationDate, null);
- }
- }
-
- private void internalAddCRLEntry(ASN1Integer userCertificate, Time revocationDate, ASN1Sequence extensions)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(userCertificate);
- v.add(revocationDate);
-
- if (extensions != null)
- {
- v.add(extensions);
- }
-
- addCRLEntry(new DERSequence(v));
- }
-
- public void addCRLEntry(ASN1Integer userCertificate, Time revocationDate, Extensions extensions)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(userCertificate);
- v.add(revocationDate);
-
- if (extensions != null)
- {
- v.add(extensions);
- }
-
- addCRLEntry(new DERSequence(v));
- }
-
- public void setExtensions(
- X509Extensions extensions)
- {
- setExtensions(Extensions.getInstance(extensions));
- }
-
- public void setExtensions(
- Extensions extensions)
- {
- this.extensions = extensions;
- }
-
- public TBSCertList generateTBSCertList()
- {
- if ((signature == null) || (issuer == null) || (thisUpdate == null))
- {
- throw new IllegalStateException("Not all mandatory fields set in V2 TBSCertList generator.");
- }
-
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(version);
- v.add(signature);
- v.add(issuer);
-
- v.add(thisUpdate);
- if (nextUpdate != null)
- {
- v.add(nextUpdate);
- }
-
- // Add CRLEntries if they exist
- if (crlentries.size() != 0)
- {
- v.add(new DERSequence(crlentries));
- }
-
- if (extensions != null)
- {
- v.add(new DERTaggedObject(0, extensions));
- }
-
- return new TBSCertList(new DERSequence(v));
- }
-
- private static ASN1Sequence createReasonExtension(int reasonCode)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- CRLReason crlReason = CRLReason.lookup(reasonCode);
-
- try
- {
- v.add(Extension.reasonCode);
- v.add(new DEROctetString(crlReason.getEncoded()));
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("error encoding reason: " + e);
- }
-
- return new DERSequence(v);
- }
-
- private static ASN1Sequence createInvalidityDateExtension(ASN1GeneralizedTime invalidityDate)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- try
- {
- v.add(Extension.invalidityDate);
- v.add(new DEROctetString(invalidityDate.getEncoded()));
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("error encoding reason: " + e);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator.java b/core/src/main/java/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator.java
deleted file mode 100644
index d778d7f5..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator.java
+++ /dev/null
@@ -1,212 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1UTCTime;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x500.X500Name;
-
-/**
- * Generator for Version 3 TBSCertificateStructures.
- * <pre>
- * TBSCertificate ::= SEQUENCE {
- * version [ 0 ] Version DEFAULT v1(0),
- * serialNumber CertificateSerialNumber,
- * signature AlgorithmIdentifier,
- * issuer Name,
- * validity Validity,
- * subject Name,
- * subjectPublicKeyInfo SubjectPublicKeyInfo,
- * issuerUniqueID [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
- * subjectUniqueID [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
- * extensions [ 3 ] Extensions OPTIONAL
- * }
- * </pre>
- *
- */
-public class V3TBSCertificateGenerator
-{
- DERTaggedObject version = new DERTaggedObject(true, 0, new ASN1Integer(2));
-
- ASN1Integer serialNumber;
- AlgorithmIdentifier signature;
- X500Name issuer;
- Time startDate, endDate;
- X500Name subject;
- SubjectPublicKeyInfo subjectPublicKeyInfo;
- Extensions extensions;
-
- private boolean altNamePresentAndCritical;
- private DERBitString issuerUniqueID;
- private DERBitString subjectUniqueID;
-
- public V3TBSCertificateGenerator()
- {
- }
-
- public void setSerialNumber(
- ASN1Integer serialNumber)
- {
- this.serialNumber = serialNumber;
- }
-
- public void setSignature(
- AlgorithmIdentifier signature)
- {
- this.signature = signature;
- }
-
- /**
- * @deprecated use X500Name method
- */
- public void setIssuer(
- X509Name issuer)
- {
- this.issuer = X500Name.getInstance(issuer);
- }
-
- public void setIssuer(
- X500Name issuer)
- {
- this.issuer = issuer;
- }
-
- public void setStartDate(
- ASN1UTCTime startDate)
- {
- this.startDate = new Time(startDate);
- }
-
- public void setStartDate(
- Time startDate)
- {
- this.startDate = startDate;
- }
-
- public void setEndDate(
- ASN1UTCTime endDate)
- {
- this.endDate = new Time(endDate);
- }
-
- public void setEndDate(
- Time endDate)
- {
- this.endDate = endDate;
- }
-
- /**
- * @deprecated use X500Name method
- */
- public void setSubject(
- X509Name subject)
- {
- this.subject = X500Name.getInstance(subject.toASN1Primitive());
- }
-
- public void setSubject(
- X500Name subject)
- {
- this.subject = subject;
- }
-
- public void setIssuerUniqueID(
- DERBitString uniqueID)
- {
- this.issuerUniqueID = uniqueID;
- }
-
- public void setSubjectUniqueID(
- DERBitString uniqueID)
- {
- this.subjectUniqueID = uniqueID;
- }
-
- public void setSubjectPublicKeyInfo(
- SubjectPublicKeyInfo pubKeyInfo)
- {
- this.subjectPublicKeyInfo = pubKeyInfo;
- }
-
- /**
- * @deprecated use method taking Extensions
- * @param extensions
- */
- public void setExtensions(
- X509Extensions extensions)
- {
- setExtensions(Extensions.getInstance(extensions));
- }
-
- public void setExtensions(
- Extensions extensions)
- {
- this.extensions = extensions;
- if (extensions != null)
- {
- Extension altName = extensions.getExtension(Extension.subjectAlternativeName);
-
- if (altName != null && altName.isCritical())
- {
- altNamePresentAndCritical = true;
- }
- }
- }
-
- public TBSCertificate generateTBSCertificate()
- {
- if ((serialNumber == null) || (signature == null)
- || (issuer == null) || (startDate == null) || (endDate == null)
- || (subject == null && !altNamePresentAndCritical) || (subjectPublicKeyInfo == null))
- {
- throw new IllegalStateException("not all mandatory fields set in V3 TBScertificate generator");
- }
-
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(version);
- v.add(serialNumber);
- v.add(signature);
- v.add(issuer);
-
- //
- // before and after dates
- //
- ASN1EncodableVector validity = new ASN1EncodableVector();
-
- validity.add(startDate);
- validity.add(endDate);
-
- v.add(new DERSequence(validity));
-
- if (subject != null)
- {
- v.add(subject);
- }
- else
- {
- v.add(new DERSequence());
- }
-
- v.add(subjectPublicKeyInfo);
-
- if (issuerUniqueID != null)
- {
- v.add(new DERTaggedObject(false, 1, issuerUniqueID));
- }
-
- if (subjectUniqueID != null)
- {
- v.add(new DERTaggedObject(false, 2, subjectUniqueID));
- }
-
- if (extensions != null)
- {
- v.add(new DERTaggedObject(true, 3, extensions));
- }
-
- return TBSCertificate.getInstance(new DERSequence(v));
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/X509AttributeIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/x509/X509AttributeIdentifiers.java
deleted file mode 100644
index 0ed12f7e..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/X509AttributeIdentifiers.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-
-public interface X509AttributeIdentifiers
-{
- /**
- * @deprecated use id_at_role
- */
- static final ASN1ObjectIdentifier RoleSyntax = new ASN1ObjectIdentifier("2.5.4.72");
-
- static final ASN1ObjectIdentifier id_pe_ac_auditIdentity = X509ObjectIdentifiers.id_pe.branch("4");
- static final ASN1ObjectIdentifier id_pe_aaControls = X509ObjectIdentifiers.id_pe.branch("6");
- static final ASN1ObjectIdentifier id_pe_ac_proxying = X509ObjectIdentifiers.id_pe.branch("10");
-
- static final ASN1ObjectIdentifier id_ce_targetInformation= X509ObjectIdentifiers.id_ce.branch("55");
-
- static final ASN1ObjectIdentifier id_aca = X509ObjectIdentifiers.id_pkix.branch("10");
-
- static final ASN1ObjectIdentifier id_aca_authenticationInfo = id_aca.branch("1");
- static final ASN1ObjectIdentifier id_aca_accessIdentity = id_aca.branch("2");
- static final ASN1ObjectIdentifier id_aca_chargingIdentity = id_aca.branch("3");
- static final ASN1ObjectIdentifier id_aca_group = id_aca.branch("4");
- // { id-aca 5 } is reserved
- static final ASN1ObjectIdentifier id_aca_encAttrs = id_aca.branch("6");
-
- static final ASN1ObjectIdentifier id_at_role = new ASN1ObjectIdentifier("2.5.4.72");
- static final ASN1ObjectIdentifier id_at_clearance = new ASN1ObjectIdentifier("2.5.1.5.55");
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/X509CertificateStructure.java b/core/src/main/java/org/bouncycastle/asn1/x509/X509CertificateStructure.java
deleted file mode 100644
index 6830030e..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/X509CertificateStructure.java
+++ /dev/null
@@ -1,129 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.asn1.x500.X500Name;
-
-/**
- * an X509Certificate structure.
- * <pre>
- * Certificate ::= SEQUENCE {
- * tbsCertificate TBSCertificate,
- * signatureAlgorithm AlgorithmIdentifier,
- * signature BIT STRING
- * }
- * </pre>
- * @deprecated use org.bouncycastle.asn1.x509.Certificate
- */
-public class X509CertificateStructure
- extends ASN1Object
- implements X509ObjectIdentifiers, PKCSObjectIdentifiers
-{
- ASN1Sequence seq;
- TBSCertificateStructure tbsCert;
- AlgorithmIdentifier sigAlgId;
- DERBitString sig;
-
- public static X509CertificateStructure getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static X509CertificateStructure getInstance(
- Object obj)
- {
- if (obj instanceof X509CertificateStructure)
- {
- return (X509CertificateStructure)obj;
- }
- else if (obj != null)
- {
- return new X509CertificateStructure(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public X509CertificateStructure(
- ASN1Sequence seq)
- {
- this.seq = seq;
-
- //
- // correct x509 certficate
- //
- if (seq.size() == 3)
- {
- tbsCert = TBSCertificateStructure.getInstance(seq.getObjectAt(0));
- sigAlgId = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
-
- sig = DERBitString.getInstance(seq.getObjectAt(2));
- }
- else
- {
- throw new IllegalArgumentException("sequence wrong size for a certificate");
- }
- }
-
- public TBSCertificateStructure getTBSCertificate()
- {
- return tbsCert;
- }
-
- public int getVersion()
- {
- return tbsCert.getVersion();
- }
-
- public ASN1Integer getSerialNumber()
- {
- return tbsCert.getSerialNumber();
- }
-
- public X500Name getIssuer()
- {
- return tbsCert.getIssuer();
- }
-
- public Time getStartDate()
- {
- return tbsCert.getStartDate();
- }
-
- public Time getEndDate()
- {
- return tbsCert.getEndDate();
- }
-
- public X500Name getSubject()
- {
- return tbsCert.getSubject();
- }
-
- public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
- {
- return tbsCert.getSubjectPublicKeyInfo();
- }
-
- public AlgorithmIdentifier getSignatureAlgorithm()
- {
- return sigAlgId;
- }
-
- public DERBitString getSignature()
- {
- return sig;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return seq;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/X509DefaultEntryConverter.java b/core/src/main/java/org/bouncycastle/asn1/x509/X509DefaultEntryConverter.java
deleted file mode 100644
index 0ae0f802..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/X509DefaultEntryConverter.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.DERGeneralizedTime;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DERPrintableString;
-import org.bouncycastle.asn1.DERUTF8String;
-
-/**
- * The default converter for X509 DN entries when going from their
- * string value to ASN.1 strings.
- */
-public class X509DefaultEntryConverter
- extends X509NameEntryConverter
-{
- /**
- * Apply default coversion for the given value depending on the oid
- * and the character range of the value.
- *
- * @param oid the object identifier for the DN entry
- * @param value the value associated with it
- * @return the ASN.1 equivalent for the string value.
- */
- public ASN1Primitive getConvertedValue(
- ASN1ObjectIdentifier oid,
- String value)
- {
- if (value.length() != 0 && value.charAt(0) == '#')
- {
- try
- {
- return convertHexEncoded(value, 1);
- }
- catch (IOException e)
- {
- throw new RuntimeException("can't recode value for oid " + oid.getId());
- }
- }
- else
- {
- if (value.length() != 0 && value.charAt(0) == '\\')
- {
- value = value.substring(1);
- }
- if (oid.equals(X509Name.EmailAddress) || oid.equals(X509Name.DC))
- {
- return new DERIA5String(value);
- }
- else if (oid.equals(X509Name.DATE_OF_BIRTH)) // accept time string as well as # (for compatibility)
- {
- return new DERGeneralizedTime(value);
- }
- else if (oid.equals(X509Name.C) || oid.equals(X509Name.SN) || oid.equals(X509Name.DN_QUALIFIER)
- || oid.equals(X509Name.TELEPHONE_NUMBER))
- {
- return new DERPrintableString(value);
- }
- }
-
- return new DERUTF8String(value);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/X509Extension.java b/core/src/main/java/org/bouncycastle/asn1/x509/X509Extension.java
deleted file mode 100644
index 93530571..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/X509Extension.java
+++ /dev/null
@@ -1,249 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Boolean;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-
-/**
- * an object for the elements in the X.509 V3 extension block.
- * @deprecated use Extension
- */
-public class X509Extension
-{
- /**
- * Subject Directory Attributes
- */
- public static final ASN1ObjectIdentifier subjectDirectoryAttributes = new ASN1ObjectIdentifier("2.5.29.9");
-
- /**
- * Subject Key Identifier
- */
- public static final ASN1ObjectIdentifier subjectKeyIdentifier = new ASN1ObjectIdentifier("2.5.29.14");
-
- /**
- * Key Usage
- */
- public static final ASN1ObjectIdentifier keyUsage = new ASN1ObjectIdentifier("2.5.29.15");
-
- /**
- * Private Key Usage Period
- */
- public static final ASN1ObjectIdentifier privateKeyUsagePeriod = new ASN1ObjectIdentifier("2.5.29.16");
-
- /**
- * Subject Alternative Name
- */
- public static final ASN1ObjectIdentifier subjectAlternativeName = new ASN1ObjectIdentifier("2.5.29.17");
-
- /**
- * Issuer Alternative Name
- */
- public static final ASN1ObjectIdentifier issuerAlternativeName = new ASN1ObjectIdentifier("2.5.29.18");
-
- /**
- * Basic Constraints
- */
- public static final ASN1ObjectIdentifier basicConstraints = new ASN1ObjectIdentifier("2.5.29.19");
-
- /**
- * CRL Number
- */
- public static final ASN1ObjectIdentifier cRLNumber = new ASN1ObjectIdentifier("2.5.29.20");
-
- /**
- * Reason code
- */
- public static final ASN1ObjectIdentifier reasonCode = new ASN1ObjectIdentifier("2.5.29.21");
-
- /**
- * Hold Instruction Code
- */
- public static final ASN1ObjectIdentifier instructionCode = new ASN1ObjectIdentifier("2.5.29.23");
-
- /**
- * Invalidity Date
- */
- public static final ASN1ObjectIdentifier invalidityDate = new ASN1ObjectIdentifier("2.5.29.24");
-
- /**
- * Delta CRL indicator
- */
- public static final ASN1ObjectIdentifier deltaCRLIndicator = new ASN1ObjectIdentifier("2.5.29.27");
-
- /**
- * Issuing Distribution Point
- */
- public static final ASN1ObjectIdentifier issuingDistributionPoint = new ASN1ObjectIdentifier("2.5.29.28");
-
- /**
- * Certificate Issuer
- */
- public static final ASN1ObjectIdentifier certificateIssuer = new ASN1ObjectIdentifier("2.5.29.29");
-
- /**
- * Name Constraints
- */
- public static final ASN1ObjectIdentifier nameConstraints = new ASN1ObjectIdentifier("2.5.29.30");
-
- /**
- * CRL Distribution Points
- */
- public static final ASN1ObjectIdentifier cRLDistributionPoints = new ASN1ObjectIdentifier("2.5.29.31");
-
- /**
- * Certificate Policies
- */
- public static final ASN1ObjectIdentifier certificatePolicies = new ASN1ObjectIdentifier("2.5.29.32");
-
- /**
- * Policy Mappings
- */
- public static final ASN1ObjectIdentifier policyMappings = new ASN1ObjectIdentifier("2.5.29.33");
-
- /**
- * Authority Key Identifier
- */
- public static final ASN1ObjectIdentifier authorityKeyIdentifier = new ASN1ObjectIdentifier("2.5.29.35");
-
- /**
- * Policy Constraints
- */
- public static final ASN1ObjectIdentifier policyConstraints = new ASN1ObjectIdentifier("2.5.29.36");
-
- /**
- * Extended Key Usage
- */
- public static final ASN1ObjectIdentifier extendedKeyUsage = new ASN1ObjectIdentifier("2.5.29.37");
-
- /**
- * Freshest CRL
- */
- public static final ASN1ObjectIdentifier freshestCRL = new ASN1ObjectIdentifier("2.5.29.46");
-
- /**
- * Inhibit Any Policy
- */
- public static final ASN1ObjectIdentifier inhibitAnyPolicy = new ASN1ObjectIdentifier("2.5.29.54");
-
- /**
- * Authority Info Access
- */
- public static final ASN1ObjectIdentifier authorityInfoAccess = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.1");
-
- /**
- * Subject Info Access
- */
- public static final ASN1ObjectIdentifier subjectInfoAccess = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.11");
-
- /**
- * Logo Type
- */
- public static final ASN1ObjectIdentifier logoType = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.12");
-
- /**
- * BiometricInfo
- */
- public static final ASN1ObjectIdentifier biometricInfo = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.2");
-
- /**
- * QCStatements
- */
- public static final ASN1ObjectIdentifier qCStatements = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.3");
-
- /**
- * Audit identity extension in attribute certificates.
- */
- public static final ASN1ObjectIdentifier auditIdentity = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.4");
-
- /**
- * NoRevAvail extension in attribute certificates.
- */
- public static final ASN1ObjectIdentifier noRevAvail = new ASN1ObjectIdentifier("2.5.29.56");
-
- /**
- * TargetInformation extension in attribute certificates.
- */
- public static final ASN1ObjectIdentifier targetInformation = new ASN1ObjectIdentifier("2.5.29.55");
-
- boolean critical;
- ASN1OctetString value;
-
- public X509Extension(
- ASN1Boolean critical,
- ASN1OctetString value)
- {
- this.critical = critical.isTrue();
- this.value = value;
- }
-
- public X509Extension(
- boolean critical,
- ASN1OctetString value)
- {
- this.critical = critical;
- this.value = value;
- }
-
- public boolean isCritical()
- {
- return critical;
- }
-
- public ASN1OctetString getValue()
- {
- return value;
- }
-
- public ASN1Encodable getParsedValue()
- {
- return convertValueToObject(this);
- }
-
- public int hashCode()
- {
- if (this.isCritical())
- {
- return this.getValue().hashCode();
- }
-
- return ~this.getValue().hashCode();
- }
-
- public boolean equals(
- Object o)
- {
- if (!(o instanceof X509Extension))
- {
- return false;
- }
-
- X509Extension other = (X509Extension)o;
-
- return other.getValue().equals(this.getValue())
- && (other.isCritical() == this.isCritical());
- }
-
- /**
- * Convert the value of the passed in extension to an object
- * @param ext the extension to parse
- * @return the object the value string contains
- * @exception IllegalArgumentException if conversion is not possible
- */
- public static ASN1Primitive convertValueToObject(
- X509Extension ext)
- throws IllegalArgumentException
- {
- try
- {
- return ASN1Primitive.fromByteArray(ext.getValue().getOctets());
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("can't convert extension: " + e);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/X509Extensions.java b/core/src/main/java/org/bouncycastle/asn1/x509/X509Extensions.java
deleted file mode 100644
index 5b9ea9e1..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/X509Extensions.java
+++ /dev/null
@@ -1,477 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1Boolean;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * @deprecated use Extensions
- */
-public class X509Extensions
- extends ASN1Object
-{
- /**
- * Subject Directory Attributes
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier SubjectDirectoryAttributes = new ASN1ObjectIdentifier("2.5.29.9");
-
- /**
- * Subject Key Identifier
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier SubjectKeyIdentifier = new ASN1ObjectIdentifier("2.5.29.14");
-
- /**
- * Key Usage
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier KeyUsage = new ASN1ObjectIdentifier("2.5.29.15");
-
- /**
- * Private Key Usage Period
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier PrivateKeyUsagePeriod = new ASN1ObjectIdentifier("2.5.29.16");
-
- /**
- * Subject Alternative Name
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier SubjectAlternativeName = new ASN1ObjectIdentifier("2.5.29.17");
-
- /**
- * Issuer Alternative Name
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier IssuerAlternativeName = new ASN1ObjectIdentifier("2.5.29.18");
-
- /**
- * Basic Constraints
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier BasicConstraints = new ASN1ObjectIdentifier("2.5.29.19");
-
- /**
- * CRL Number
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier CRLNumber = new ASN1ObjectIdentifier("2.5.29.20");
-
- /**
- * Reason code
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier ReasonCode = new ASN1ObjectIdentifier("2.5.29.21");
-
- /**
- * Hold Instruction Code
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier InstructionCode = new ASN1ObjectIdentifier("2.5.29.23");
-
- /**
- * Invalidity Date
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier InvalidityDate = new ASN1ObjectIdentifier("2.5.29.24");
-
- /**
- * Delta CRL indicator
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier DeltaCRLIndicator = new ASN1ObjectIdentifier("2.5.29.27");
-
- /**
- * Issuing Distribution Point
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier IssuingDistributionPoint = new ASN1ObjectIdentifier("2.5.29.28");
-
- /**
- * Certificate Issuer
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier CertificateIssuer = new ASN1ObjectIdentifier("2.5.29.29");
-
- /**
- * Name Constraints
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier NameConstraints = new ASN1ObjectIdentifier("2.5.29.30");
-
- /**
- * CRL Distribution Points
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier CRLDistributionPoints = new ASN1ObjectIdentifier("2.5.29.31");
-
- /**
- * Certificate Policies
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier CertificatePolicies = new ASN1ObjectIdentifier("2.5.29.32");
-
- /**
- * Policy Mappings
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier PolicyMappings = new ASN1ObjectIdentifier("2.5.29.33");
-
- /**
- * Authority Key Identifier
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier AuthorityKeyIdentifier = new ASN1ObjectIdentifier("2.5.29.35");
-
- /**
- * Policy Constraints
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier PolicyConstraints = new ASN1ObjectIdentifier("2.5.29.36");
-
- /**
- * Extended Key Usage
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier ExtendedKeyUsage = new ASN1ObjectIdentifier("2.5.29.37");
-
- /**
- * Freshest CRL
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier FreshestCRL = new ASN1ObjectIdentifier("2.5.29.46");
-
- /**
- * Inhibit Any Policy
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier InhibitAnyPolicy = new ASN1ObjectIdentifier("2.5.29.54");
-
- /**
- * Authority Info Access
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier AuthorityInfoAccess = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.1");
-
- /**
- * Subject Info Access
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier SubjectInfoAccess = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.11");
-
- /**
- * Logo Type
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier LogoType = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.12");
-
- /**
- * BiometricInfo
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier BiometricInfo = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.2");
-
- /**
- * QCStatements
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier QCStatements = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.3");
-
- /**
- * Audit identity extension in attribute certificates.
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier AuditIdentity = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.4");
-
- /**
- * NoRevAvail extension in attribute certificates.
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier NoRevAvail = new ASN1ObjectIdentifier("2.5.29.56");
-
- /**
- * TargetInformation extension in attribute certificates.
- * @deprecated use X509Extension value.
- */
- public static final ASN1ObjectIdentifier TargetInformation = new ASN1ObjectIdentifier("2.5.29.55");
-
- private Hashtable extensions = new Hashtable();
- private Vector ordering = new Vector();
-
- public static X509Extensions getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static X509Extensions getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof X509Extensions)
- {
- return (X509Extensions)obj;
- }
-
- if (obj instanceof ASN1Sequence)
- {
- return new X509Extensions((ASN1Sequence)obj);
- }
-
- if (obj instanceof Extensions)
- {
- return new X509Extensions((ASN1Sequence)((Extensions)obj).toASN1Primitive());
- }
-
- if (obj instanceof ASN1TaggedObject)
- {
- return getInstance(((ASN1TaggedObject)obj).getObject());
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * Constructor from ASN1Sequence.
- *
- * the extensions are a list of constructed sequences, either with (OID, OctetString) or (OID, Boolean, OctetString)
- */
- public X509Extensions(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- while (e.hasMoreElements())
- {
- ASN1Sequence s = ASN1Sequence.getInstance(e.nextElement());
-
- if (s.size() == 3)
- {
- extensions.put(s.getObjectAt(0), new X509Extension(ASN1Boolean.getInstance(s.getObjectAt(1)), ASN1OctetString.getInstance(s.getObjectAt(2))));
- }
- else if (s.size() == 2)
- {
- extensions.put(s.getObjectAt(0), new X509Extension(false, ASN1OctetString.getInstance(s.getObjectAt(1))));
- }
- else
- {
- throw new IllegalArgumentException("Bad sequence size: " + s.size());
- }
-
- ordering.addElement(s.getObjectAt(0));
- }
- }
-
- /**
- * constructor from a table of extensions.
- * <p>
- * it's is assumed the table contains OID/String pairs.
- */
- public X509Extensions(
- Hashtable extensions)
- {
- this(null, extensions);
- }
-
- /**
- * Constructor from a table of extensions with ordering.
- * <p>
- * It's is assumed the table contains OID/String pairs.
- * @deprecated use Extensions
- */
- public X509Extensions(
- Vector ordering,
- Hashtable extensions)
- {
- Enumeration e;
-
- if (ordering == null)
- {
- e = extensions.keys();
- }
- else
- {
- e = ordering.elements();
- }
-
- while (e.hasMoreElements())
- {
- this.ordering.addElement(ASN1ObjectIdentifier.getInstance(e.nextElement()));
- }
-
- e = this.ordering.elements();
-
- while (e.hasMoreElements())
- {
- ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(e.nextElement());
- X509Extension ext = (X509Extension)extensions.get(oid);
-
- this.extensions.put(oid, ext);
- }
- }
-
- /**
- * Constructor from two vectors
- *
- * @param objectIDs a vector of the object identifiers.
- * @param values a vector of the extension values.
- * @deprecated use Extensions
- */
- public X509Extensions(
- Vector objectIDs,
- Vector values)
- {
- Enumeration e = objectIDs.elements();
-
- while (e.hasMoreElements())
- {
- this.ordering.addElement(e.nextElement());
- }
-
- int count = 0;
-
- e = this.ordering.elements();
-
- while (e.hasMoreElements())
- {
- ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
- X509Extension ext = (X509Extension)values.elementAt(count);
-
- this.extensions.put(oid, ext);
- count++;
- }
- }
-
- /**
- * return an Enumeration of the extension field's object ids.
- */
- public Enumeration oids()
- {
- return ordering.elements();
- }
-
- /**
- * return the extension represented by the object identifier
- * passed in.
- *
- * @return the extension if it's present, null otherwise.
- */
- public X509Extension getExtension(
- ASN1ObjectIdentifier oid)
- {
- return (X509Extension)extensions.get(oid);
- }
-
- /**
- * <pre>
- * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
- *
- * Extension ::= SEQUENCE {
- * extnId EXTENSION.&amp;id ({ExtensionSet}),
- * critical BOOLEAN DEFAULT FALSE,
- * extnValue OCTET STRING }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector vec = new ASN1EncodableVector();
- Enumeration e = ordering.elements();
-
- while (e.hasMoreElements())
- {
- ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
- X509Extension ext = (X509Extension)extensions.get(oid);
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(oid);
-
- if (ext.isCritical())
- {
- v.add(ASN1Boolean.TRUE);
- }
-
- v.add(ext.getValue());
-
- vec.add(new DERSequence(v));
- }
-
- return new DERSequence(vec);
- }
-
- public boolean equivalent(
- X509Extensions other)
- {
- if (extensions.size() != other.extensions.size())
- {
- return false;
- }
-
- Enumeration e1 = extensions.keys();
-
- while (e1.hasMoreElements())
- {
- Object key = e1.nextElement();
-
- if (!extensions.get(key).equals(other.extensions.get(key)))
- {
- return false;
- }
- }
-
- return true;
- }
-
- public ASN1ObjectIdentifier[] getExtensionOIDs()
- {
- return toOidArray(ordering);
- }
-
- public ASN1ObjectIdentifier[] getNonCriticalExtensionOIDs()
- {
- return getExtensionOIDs(false);
- }
-
- public ASN1ObjectIdentifier[] getCriticalExtensionOIDs()
- {
- return getExtensionOIDs(true);
- }
-
- private ASN1ObjectIdentifier[] getExtensionOIDs(boolean isCritical)
- {
- Vector oidVec = new Vector();
-
- for (int i = 0; i != ordering.size(); i++)
- {
- Object oid = ordering.elementAt(i);
-
- if (((X509Extension)extensions.get(oid)).isCritical() == isCritical)
- {
- oidVec.addElement(oid);
- }
- }
-
- return toOidArray(oidVec);
- }
-
- private ASN1ObjectIdentifier[] toOidArray(Vector oidVec)
- {
- ASN1ObjectIdentifier[] oids = new ASN1ObjectIdentifier[oidVec.size()];
-
- for (int i = 0; i != oids.length; i++)
- {
- oids[i] = (ASN1ObjectIdentifier)oidVec.elementAt(i);
- }
- return oids;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/X509ExtensionsGenerator.java b/core/src/main/java/org/bouncycastle/asn1/x509/X509ExtensionsGenerator.java
deleted file mode 100644
index 589d512f..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/X509ExtensionsGenerator.java
+++ /dev/null
@@ -1,94 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.io.IOException;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Encoding;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.DEROctetString;
-
-/**
- * Generator for X.509 extensions
- * @deprecated use org.bouncycastle.asn1.x509.ExtensionsGenerator
- */
-public class X509ExtensionsGenerator
-{
- private Hashtable extensions = new Hashtable();
- private Vector extOrdering = new Vector();
-
- /**
- * Reset the generator
- */
- public void reset()
- {
- extensions = new Hashtable();
- extOrdering = new Vector();
- }
-
- /**
- * Add an extension with the given oid and the passed in value to be included
- * in the OCTET STRING associated with the extension.
- *
- * @param oid OID for the extension.
- * @param critical true if critical, false otherwise.
- * @param value the ASN.1 object to be included in the extension.
- */
- public void addExtension(
- ASN1ObjectIdentifier oid,
- boolean critical,
- ASN1Encodable value)
- {
- try
- {
- this.addExtension(oid, critical, value.toASN1Primitive().getEncoded(ASN1Encoding.DER));
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("error encoding value: " + e);
- }
- }
-
- /**
- * Add an extension with the given oid and the passed in byte array to be wrapped in the
- * OCTET STRING associated with the extension.
- *
- * @param oid OID for the extension.
- * @param critical true if critical, false otherwise.
- * @param value the byte array to be wrapped.
- */
- public void addExtension(
- ASN1ObjectIdentifier oid,
- boolean critical,
- byte[] value)
- {
- if (extensions.containsKey(oid))
- {
- throw new IllegalArgumentException("extension " + oid + " already added");
- }
-
- extOrdering.addElement(oid);
- extensions.put(oid, new X509Extension(critical, new DEROctetString(value)));
- }
-
- /**
- * Return true if there are no extension present in this generator.
- *
- * @return true if empty, false otherwise
- */
- public boolean isEmpty()
- {
- return extOrdering.isEmpty();
- }
-
- /**
- * Generate an X509Extensions object based on the current state of the generator.
- *
- * @return an X09Extensions object.
- */
- public X509Extensions generate()
- {
- return new X509Extensions(extOrdering, extensions);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/X509Name.java b/core/src/main/java/org/bouncycastle/asn1/x509/X509Name.java
deleted file mode 100644
index ff7af8c8..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/X509Name.java
+++ /dev/null
@@ -1,1379 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Encoding;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.ASN1String;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERSet;
-import org.bouncycastle.asn1.DERUniversalString;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.util.Strings;
-import org.bouncycastle.util.encoders.Hex;
-
-/**
- * <pre>
- * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
- *
- * RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
- *
- * AttributeTypeAndValue ::= SEQUENCE {
- * type OBJECT IDENTIFIER,
- * value ANY }
- * </pre>
- * @deprecated use org.bouncycastle.asn1.x500.X500Name.
- */
-public class X509Name
- extends ASN1Object
-{
- /**
- * country code - StringType(SIZE(2))
- * @deprecated use a X500NameStyle
- */
- public static final ASN1ObjectIdentifier C = new ASN1ObjectIdentifier("2.5.4.6");
-
- /**
- * organization - StringType(SIZE(1..64))
- * @deprecated use a X500NameStyle
- */
- public static final ASN1ObjectIdentifier O = new ASN1ObjectIdentifier("2.5.4.10");
-
- /**
- * organizational unit name - StringType(SIZE(1..64))
- * @deprecated use a X500NameStyle
- */
- public static final ASN1ObjectIdentifier OU = new ASN1ObjectIdentifier("2.5.4.11");
-
- /**
- * Title
- * @deprecated use a X500NameStyle
- */
- public static final ASN1ObjectIdentifier T = new ASN1ObjectIdentifier("2.5.4.12");
-
- /**
- * common name - StringType(SIZE(1..64))
- * @deprecated use a X500NameStyle
- */
- public static final ASN1ObjectIdentifier CN = new ASN1ObjectIdentifier("2.5.4.3");
-
- /**
- * device serial number name - StringType(SIZE(1..64))
- */
- public static final ASN1ObjectIdentifier SN = new ASN1ObjectIdentifier("2.5.4.5");
-
- /**
- * street - StringType(SIZE(1..64))
- */
- public static final ASN1ObjectIdentifier STREET = new ASN1ObjectIdentifier("2.5.4.9");
-
- /**
- * device serial number name - StringType(SIZE(1..64))
- */
- public static final ASN1ObjectIdentifier SERIALNUMBER = SN;
-
- /**
- * locality name - StringType(SIZE(1..64))
- */
- public static final ASN1ObjectIdentifier L = new ASN1ObjectIdentifier("2.5.4.7");
-
- /**
- * state, or province name - StringType(SIZE(1..64))
- */
- public static final ASN1ObjectIdentifier ST = new ASN1ObjectIdentifier("2.5.4.8");
-
- /**
- * Naming attributes of type X520name
- */
- public static final ASN1ObjectIdentifier SURNAME = new ASN1ObjectIdentifier("2.5.4.4");
- public static final ASN1ObjectIdentifier GIVENNAME = new ASN1ObjectIdentifier("2.5.4.42");
- public static final ASN1ObjectIdentifier INITIALS = new ASN1ObjectIdentifier("2.5.4.43");
- public static final ASN1ObjectIdentifier GENERATION = new ASN1ObjectIdentifier("2.5.4.44");
- public static final ASN1ObjectIdentifier UNIQUE_IDENTIFIER = new ASN1ObjectIdentifier("2.5.4.45");
-
- /**
- * businessCategory - DirectoryString(SIZE(1..128)
- */
- public static final ASN1ObjectIdentifier BUSINESS_CATEGORY = new ASN1ObjectIdentifier(
- "2.5.4.15");
-
- /**
- * postalCode - DirectoryString(SIZE(1..40)
- */
- public static final ASN1ObjectIdentifier POSTAL_CODE = new ASN1ObjectIdentifier(
- "2.5.4.17");
-
- /**
- * dnQualifier - DirectoryString(SIZE(1..64)
- */
- public static final ASN1ObjectIdentifier DN_QUALIFIER = new ASN1ObjectIdentifier(
- "2.5.4.46");
-
- /**
- * RFC 3039 Pseudonym - DirectoryString(SIZE(1..64)
- */
- public static final ASN1ObjectIdentifier PSEUDONYM = new ASN1ObjectIdentifier(
- "2.5.4.65");
-
-
- /**
- * RFC 3039 DateOfBirth - GeneralizedTime - YYYYMMDD000000Z
- */
- public static final ASN1ObjectIdentifier DATE_OF_BIRTH = new ASN1ObjectIdentifier(
- "1.3.6.1.5.5.7.9.1");
-
- /**
- * RFC 3039 PlaceOfBirth - DirectoryString(SIZE(1..128)
- */
- public static final ASN1ObjectIdentifier PLACE_OF_BIRTH = new ASN1ObjectIdentifier(
- "1.3.6.1.5.5.7.9.2");
-
- /**
- * RFC 3039 Gender - PrintableString (SIZE(1)) -- "M", "F", "m" or "f"
- */
- public static final ASN1ObjectIdentifier GENDER = new ASN1ObjectIdentifier(
- "1.3.6.1.5.5.7.9.3");
-
- /**
- * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
- * codes only
- */
- public static final ASN1ObjectIdentifier COUNTRY_OF_CITIZENSHIP = new ASN1ObjectIdentifier(
- "1.3.6.1.5.5.7.9.4");
-
- /**
- * RFC 3039 CountryOfResidence - PrintableString (SIZE (2)) -- ISO 3166
- * codes only
- */
- public static final ASN1ObjectIdentifier COUNTRY_OF_RESIDENCE = new ASN1ObjectIdentifier(
- "1.3.6.1.5.5.7.9.5");
-
-
- /**
- * ISIS-MTT NameAtBirth - DirectoryString(SIZE(1..64)
- */
- public static final ASN1ObjectIdentifier NAME_AT_BIRTH = new ASN1ObjectIdentifier("1.3.36.8.3.14");
-
- /**
- * RFC 3039 PostalAddress - SEQUENCE SIZE (1..6) OF
- * DirectoryString(SIZE(1..30))
- */
- public static final ASN1ObjectIdentifier POSTAL_ADDRESS = new ASN1ObjectIdentifier("2.5.4.16");
-
- /**
- * RFC 2256 dmdName
- */
- public static final ASN1ObjectIdentifier DMD_NAME = new ASN1ObjectIdentifier("2.5.4.54");
-
- /**
- * id-at-telephoneNumber
- */
- public static final ASN1ObjectIdentifier TELEPHONE_NUMBER = X509ObjectIdentifiers.id_at_telephoneNumber;
-
- /**
- * id-at-name
- */
- public static final ASN1ObjectIdentifier NAME = X509ObjectIdentifiers.id_at_name;
-
- /**
- * Email address (RSA PKCS#9 extension) - IA5String.
- * <p>Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.
- * @deprecated use a X500NameStyle
- */
- public static final ASN1ObjectIdentifier EmailAddress = PKCSObjectIdentifiers.pkcs_9_at_emailAddress;
-
- /**
- * more from PKCS#9
- */
- public static final ASN1ObjectIdentifier UnstructuredName = PKCSObjectIdentifiers.pkcs_9_at_unstructuredName;
- public static final ASN1ObjectIdentifier UnstructuredAddress = PKCSObjectIdentifiers.pkcs_9_at_unstructuredAddress;
-
- /**
- * email address in Verisign certificates
- */
- public static final ASN1ObjectIdentifier E = EmailAddress;
-
- /*
- * others...
- */
- public static final ASN1ObjectIdentifier DC = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.25");
-
- /**
- * LDAP User id.
- */
- public static final ASN1ObjectIdentifier UID = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.1");
-
- /**
- * determines whether or not strings should be processed and printed
- * from back to front.
- */
- public static boolean DefaultReverse = false;
-
- /**
- * default look up table translating OID values into their common symbols following
- * the convention in RFC 2253 with a few extras
- */
- public static final Hashtable DefaultSymbols = new Hashtable();
-
- /**
- * look up table translating OID values into their common symbols following the convention in RFC 2253
- *
- */
- public static final Hashtable RFC2253Symbols = new Hashtable();
-
- /**
- * look up table translating OID values into their common symbols following the convention in RFC 1779
- *
- */
- public static final Hashtable RFC1779Symbols = new Hashtable();
-
- /**
- * look up table translating common symbols into their OIDS.
- */
- public static final Hashtable DefaultLookUp = new Hashtable();
-
- /**
- * look up table translating OID values into their common symbols
- * @deprecated use DefaultSymbols
- */
- public static final Hashtable OIDLookUp = DefaultSymbols;
-
- /**
- * look up table translating string values into their OIDS -
- * @deprecated use DefaultLookUp
- */
- public static final Hashtable SymbolLookUp = DefaultLookUp;
-
- private static final Boolean TRUE = new Boolean(true); // for J2ME compatibility
- private static final Boolean FALSE = new Boolean(false);
-
- static
- {
- DefaultSymbols.put(C, "C");
- DefaultSymbols.put(O, "O");
- DefaultSymbols.put(T, "T");
- DefaultSymbols.put(OU, "OU");
- DefaultSymbols.put(CN, "CN");
- DefaultSymbols.put(L, "L");
- DefaultSymbols.put(ST, "ST");
- DefaultSymbols.put(SN, "SERIALNUMBER");
- DefaultSymbols.put(EmailAddress, "E");
- DefaultSymbols.put(DC, "DC");
- DefaultSymbols.put(UID, "UID");
- DefaultSymbols.put(STREET, "STREET");
- DefaultSymbols.put(SURNAME, "SURNAME");
- DefaultSymbols.put(GIVENNAME, "GIVENNAME");
- DefaultSymbols.put(INITIALS, "INITIALS");
- DefaultSymbols.put(GENERATION, "GENERATION");
- DefaultSymbols.put(UnstructuredAddress, "unstructuredAddress");
- DefaultSymbols.put(UnstructuredName, "unstructuredName");
- DefaultSymbols.put(UNIQUE_IDENTIFIER, "UniqueIdentifier");
- DefaultSymbols.put(DN_QUALIFIER, "DN");
- DefaultSymbols.put(PSEUDONYM, "Pseudonym");
- DefaultSymbols.put(POSTAL_ADDRESS, "PostalAddress");
- DefaultSymbols.put(NAME_AT_BIRTH, "NameAtBirth");
- DefaultSymbols.put(COUNTRY_OF_CITIZENSHIP, "CountryOfCitizenship");
- DefaultSymbols.put(COUNTRY_OF_RESIDENCE, "CountryOfResidence");
- DefaultSymbols.put(GENDER, "Gender");
- DefaultSymbols.put(PLACE_OF_BIRTH, "PlaceOfBirth");
- DefaultSymbols.put(DATE_OF_BIRTH, "DateOfBirth");
- DefaultSymbols.put(POSTAL_CODE, "PostalCode");
- DefaultSymbols.put(BUSINESS_CATEGORY, "BusinessCategory");
- DefaultSymbols.put(TELEPHONE_NUMBER, "TelephoneNumber");
- DefaultSymbols.put(NAME, "Name");
-
- RFC2253Symbols.put(C, "C");
- RFC2253Symbols.put(O, "O");
- RFC2253Symbols.put(OU, "OU");
- RFC2253Symbols.put(CN, "CN");
- RFC2253Symbols.put(L, "L");
- RFC2253Symbols.put(ST, "ST");
- RFC2253Symbols.put(STREET, "STREET");
- RFC2253Symbols.put(DC, "DC");
- RFC2253Symbols.put(UID, "UID");
-
- RFC1779Symbols.put(C, "C");
- RFC1779Symbols.put(O, "O");
- RFC1779Symbols.put(OU, "OU");
- RFC1779Symbols.put(CN, "CN");
- RFC1779Symbols.put(L, "L");
- RFC1779Symbols.put(ST, "ST");
- RFC1779Symbols.put(STREET, "STREET");
-
- DefaultLookUp.put("c", C);
- DefaultLookUp.put("o", O);
- DefaultLookUp.put("t", T);
- DefaultLookUp.put("ou", OU);
- DefaultLookUp.put("cn", CN);
- DefaultLookUp.put("l", L);
- DefaultLookUp.put("st", ST);
- DefaultLookUp.put("sn", SN);
- DefaultLookUp.put("serialnumber", SN);
- DefaultLookUp.put("street", STREET);
- DefaultLookUp.put("emailaddress", E);
- DefaultLookUp.put("dc", DC);
- DefaultLookUp.put("e", E);
- DefaultLookUp.put("uid", UID);
- DefaultLookUp.put("surname", SURNAME);
- DefaultLookUp.put("givenname", GIVENNAME);
- DefaultLookUp.put("initials", INITIALS);
- DefaultLookUp.put("generation", GENERATION);
- DefaultLookUp.put("unstructuredaddress", UnstructuredAddress);
- DefaultLookUp.put("unstructuredname", UnstructuredName);
- DefaultLookUp.put("uniqueidentifier", UNIQUE_IDENTIFIER);
- DefaultLookUp.put("dn", DN_QUALIFIER);
- DefaultLookUp.put("pseudonym", PSEUDONYM);
- DefaultLookUp.put("postaladdress", POSTAL_ADDRESS);
- DefaultLookUp.put("nameofbirth", NAME_AT_BIRTH);
- DefaultLookUp.put("countryofcitizenship", COUNTRY_OF_CITIZENSHIP);
- DefaultLookUp.put("countryofresidence", COUNTRY_OF_RESIDENCE);
- DefaultLookUp.put("gender", GENDER);
- DefaultLookUp.put("placeofbirth", PLACE_OF_BIRTH);
- DefaultLookUp.put("dateofbirth", DATE_OF_BIRTH);
- DefaultLookUp.put("postalcode", POSTAL_CODE);
- DefaultLookUp.put("businesscategory", BUSINESS_CATEGORY);
- DefaultLookUp.put("telephonenumber", TELEPHONE_NUMBER);
- DefaultLookUp.put("name", NAME);
- }
-
- private X509NameEntryConverter converter = null;
- private Vector ordering = new Vector();
- private Vector values = new Vector();
- private Vector added = new Vector();
-
- private ASN1Sequence seq;
-
- private boolean isHashCodeCalculated;
- private int hashCodeValue;
-
- /**
- * Return a X509Name based on the passed in tagged object.
- *
- * @param obj tag object holding name.
- * @param explicit true if explicitly tagged false otherwise.
- * @return the X509Name
- */
- public static X509Name getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static X509Name getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof X509Name)
- {
- return (X509Name)obj;
- }
- else if (obj instanceof X500Name)
- {
- return new X509Name(ASN1Sequence.getInstance(((X500Name)obj).toASN1Primitive()));
- }
- else if (obj != null)
- {
- return new X509Name(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- protected X509Name()
- {
- // constructure use by new X500 Name class
- }
- /**
- * Constructor from ASN1Sequence
- *
- * the principal will be a list of constructed sets, each containing an (OID, String) pair.
- * @deprecated use X500Name.getInstance()
- */
- public X509Name(
- ASN1Sequence seq)
- {
- this.seq = seq;
-
- Enumeration e = seq.getObjects();
-
- while (e.hasMoreElements())
- {
- ASN1Set set = ASN1Set.getInstance(((ASN1Encodable)e.nextElement()).toASN1Primitive());
-
- for (int i = 0; i < set.size(); i++)
- {
- ASN1Sequence s = ASN1Sequence.getInstance(set.getObjectAt(i).toASN1Primitive());
-
- if (s.size() != 2)
- {
- throw new IllegalArgumentException("badly sized pair");
- }
-
- ordering.addElement(ASN1ObjectIdentifier.getInstance(s.getObjectAt(0)));
-
- ASN1Encodable value = s.getObjectAt(1);
- if (value instanceof ASN1String && !(value instanceof DERUniversalString))
- {
- String v = ((ASN1String)value).getString();
- if (v.length() > 0 && v.charAt(0) == '#')
- {
- values.addElement("\\" + v);
- }
- else
- {
- values.addElement(v);
- }
- }
- else
- {
- try
- {
- values.addElement("#" + bytesToString(Hex.encode(value.toASN1Primitive().getEncoded(ASN1Encoding.DER))));
- }
- catch (IOException e1)
- {
- throw new IllegalArgumentException("cannot encode value");
- }
- }
- added.addElement((i != 0) ? TRUE : FALSE); // to allow earlier JDK compatibility
- }
- }
- }
-
- /**
- * constructor from a table of attributes.
- * <p>
- * it's is assumed the table contains OID/String pairs, and the contents
- * of the table are copied into an internal table as part of the
- * construction process.
- * <p>
- * <b>Note:</b> if the name you are trying to generate should be
- * following a specific ordering, you should use the constructor
- * with the ordering specified below.
- * @deprecated use an ordered constructor! The hashtable ordering is rarely correct
- */
- public X509Name(
- Hashtable attributes)
- {
- this(null, attributes);
- }
-
- /**
- * Constructor from a table of attributes with ordering.
- * <p>
- * it's is assumed the table contains OID/String pairs, and the contents
- * of the table are copied into an internal table as part of the
- * construction process. The ordering vector should contain the OIDs
- * in the order they are meant to be encoded or printed in toString.
- */
- public X509Name(
- Vector ordering,
- Hashtable attributes)
- {
- this(ordering, attributes, new X509DefaultEntryConverter());
- }
-
- /**
- * Constructor from a table of attributes with ordering.
- * <p>
- * it's is assumed the table contains OID/String pairs, and the contents
- * of the table are copied into an internal table as part of the
- * construction process. The ordering vector should contain the OIDs
- * in the order they are meant to be encoded or printed in toString.
- * <p>
- * The passed in converter will be used to convert the strings into their
- * ASN.1 counterparts.
- * @deprecated use X500Name, X500NameBuilder
- */
- public X509Name(
- Vector ordering,
- Hashtable attributes,
- X509NameEntryConverter converter)
- {
- this.converter = converter;
-
- if (ordering != null)
- {
- for (int i = 0; i != ordering.size(); i++)
- {
- this.ordering.addElement(ordering.elementAt(i));
- this.added.addElement(FALSE);
- }
- }
- else
- {
- Enumeration e = attributes.keys();
-
- while (e.hasMoreElements())
- {
- this.ordering.addElement(e.nextElement());
- this.added.addElement(FALSE);
- }
- }
-
- for (int i = 0; i != this.ordering.size(); i++)
- {
- ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)this.ordering.elementAt(i);
-
- if (attributes.get(oid) == null)
- {
- throw new IllegalArgumentException("No attribute for object id - " + oid.getId() + " - passed to distinguished name");
- }
-
- this.values.addElement(attributes.get(oid)); // copy the hash table
- }
- }
-
- /**
- * Takes two vectors one of the oids and the other of the values.
- * @deprecated use X500Name, X500NameBuilder
- */
- public X509Name(
- Vector oids,
- Vector values)
- {
- this(oids, values, new X509DefaultEntryConverter());
- }
-
- /**
- * Takes two vectors one of the oids and the other of the values.
- * <p>
- * The passed in converter will be used to convert the strings into their
- * ASN.1 counterparts.
- * @deprecated use X500Name, X500NameBuilder
- */
- public X509Name(
- Vector oids,
- Vector values,
- X509NameEntryConverter converter)
- {
- this.converter = converter;
-
- if (oids.size() != values.size())
- {
- throw new IllegalArgumentException("oids vector must be same length as values.");
- }
-
- for (int i = 0; i < oids.size(); i++)
- {
- this.ordering.addElement(oids.elementAt(i));
- this.values.addElement(values.elementAt(i));
- this.added.addElement(FALSE);
- }
- }
-
-// private Boolean isEncoded(String s)
-// {
-// if (s.charAt(0) == '#')
-// {
-// return TRUE;
-// }
-//
-// return FALSE;
-// }
-
- /**
- * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
- * some such, converting it into an ordered set of name attributes.
- * @deprecated use X500Name, X500NameBuilder
- */
- public X509Name(
- String dirName)
- {
- this(DefaultReverse, DefaultLookUp, dirName);
- }
-
- /**
- * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
- * some such, converting it into an ordered set of name attributes with each
- * string value being converted to its associated ASN.1 type using the passed
- * in converter.
- * @deprecated use X500Name, X500NameBuilder
- */
- public X509Name(
- String dirName,
- X509NameEntryConverter converter)
- {
- this(DefaultReverse, DefaultLookUp, dirName, converter);
- }
-
- /**
- * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
- * some such, converting it into an ordered set of name attributes. If reverse
- * is true, create the encoded version of the sequence starting from the
- * last element in the string.
- * @deprecated use X500Name, X500NameBuilder
- */
- public X509Name(
- boolean reverse,
- String dirName)
- {
- this(reverse, DefaultLookUp, dirName);
- }
-
- /**
- * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
- * some such, converting it into an ordered set of name attributes with each
- * string value being converted to its associated ASN.1 type using the passed
- * in converter. If reverse is true the ASN.1 sequence representing the DN will
- * be built by starting at the end of the string, rather than the start.
- * @deprecated use X500Name, X500NameBuilder
- */
- public X509Name(
- boolean reverse,
- String dirName,
- X509NameEntryConverter converter)
- {
- this(reverse, DefaultLookUp, dirName, converter);
- }
-
- /**
- * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
- * some such, converting it into an ordered set of name attributes. lookUp
- * should provide a table of lookups, indexed by lowercase only strings and
- * yielding a ASN1ObjectIdentifier, other than that OID. and numeric oids
- * will be processed automatically.
- * <br>
- * If reverse is true, create the encoded version of the sequence
- * starting from the last element in the string.
- * @param reverse true if we should start scanning from the end (RFC 2553).
- * @param lookUp table of names and their oids.
- * @param dirName the X.500 string to be parsed.
- * @deprecated use X500Name, X500NameBuilder
- */
- public X509Name(
- boolean reverse,
- Hashtable lookUp,
- String dirName)
- {
- this(reverse, lookUp, dirName, new X509DefaultEntryConverter());
- }
-
- private ASN1ObjectIdentifier decodeOID(
- String name,
- Hashtable lookUp)
- {
- name = name.trim();
- if (Strings.toUpperCase(name).startsWith("OID."))
- {
- return new ASN1ObjectIdentifier(name.substring(4));
- }
- else if (name.charAt(0) >= '0' && name.charAt(0) <= '9')
- {
- return new ASN1ObjectIdentifier(name);
- }
-
- ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)lookUp.get(Strings.toLowerCase(name));
- if (oid == null)
- {
- throw new IllegalArgumentException("Unknown object id - " + name + " - passed to distinguished name");
- }
-
- return oid;
- }
-
- private String unescape(String elt)
- {
- if (elt.length() == 0 || (elt.indexOf('\\') < 0 && elt.indexOf('"') < 0))
- {
- return elt.trim();
- }
-
- char[] elts = elt.toCharArray();
- boolean escaped = false;
- boolean quoted = false;
- StringBuffer buf = new StringBuffer(elt.length());
- int start = 0;
-
- // if it's an escaped hash string and not an actual encoding in string form
- // we need to leave it escaped.
- if (elts[0] == '\\')
- {
- if (elts[1] == '#')
- {
- start = 2;
- buf.append("\\#");
- }
- }
-
- boolean nonWhiteSpaceEncountered = false;
- int lastEscaped = 0;
-
- for (int i = start; i != elts.length; i++)
- {
- char c = elts[i];
-
- if (c != ' ')
- {
- nonWhiteSpaceEncountered = true;
- }
-
- if (c == '"')
- {
- if (!escaped)
- {
- quoted = !quoted;
- }
- else
- {
- buf.append(c);
- }
- escaped = false;
- }
- else if (c == '\\' && !(escaped || quoted))
- {
- escaped = true;
- lastEscaped = buf.length();
- }
- else
- {
- if (c == ' ' && !escaped && !nonWhiteSpaceEncountered)
- {
- continue;
- }
- buf.append(c);
- escaped = false;
- }
- }
-
- if (buf.length() > 0)
- {
- while (buf.charAt(buf.length() - 1) == ' ' && lastEscaped != (buf.length() - 1))
- {
- buf.setLength(buf.length() - 1);
- }
- }
-
- return buf.toString();
- }
-
- /**
- * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
- * some such, converting it into an ordered set of name attributes. lookUp
- * should provide a table of lookups, indexed by lowercase only strings and
- * yielding a ASN1ObjectIdentifier, other than that OID. and numeric oids
- * will be processed automatically. The passed in converter is used to convert the
- * string values to the right of each equals sign to their ASN.1 counterparts.
- * <br>
- * @param reverse true if we should start scanning from the end, false otherwise.
- * @param lookUp table of names and oids.
- * @param dirName the string dirName
- * @param converter the converter to convert string values into their ASN.1 equivalents
- */
- public X509Name(
- boolean reverse,
- Hashtable lookUp,
- String dirName,
- X509NameEntryConverter converter)
- {
- this.converter = converter;
- X509NameTokenizer nTok = new X509NameTokenizer(dirName);
-
- while (nTok.hasMoreTokens())
- {
- String token = nTok.nextToken();
-
- if (token.indexOf('+') > 0)
- {
- X509NameTokenizer pTok = new X509NameTokenizer(token, '+');
-
- addEntry(lookUp, pTok.nextToken(), FALSE);
-
- while (pTok.hasMoreTokens())
- {
- addEntry(lookUp, pTok.nextToken(), TRUE);
- }
- }
- else
- {
- addEntry(lookUp, token, FALSE);
- }
- }
-
- if (reverse)
- {
- Vector o = new Vector();
- Vector v = new Vector();
- Vector a = new Vector();
-
- int count = 1;
-
- for (int i = 0; i < this.ordering.size(); i++)
- {
- if (((Boolean)this.added.elementAt(i)).booleanValue())
- {
- o.insertElementAt(this.ordering.elementAt(i), count);
- v.insertElementAt(this.values.elementAt(i), count);
- a.insertElementAt(this.added.elementAt(i), count);
- count++;
- }
- else
- {
- o.insertElementAt(this.ordering.elementAt(i), 0);
- v.insertElementAt(this.values.elementAt(i), 0);
- a.insertElementAt(this.added.elementAt(i), 0);
- count = 1;
- }
- }
-
- this.ordering = o;
- this.values = v;
- this.added = a;
- }
- }
-
- private void addEntry(Hashtable lookUp, String token, Boolean isAdded)
- {
- X509NameTokenizer vTok;
- String name;
- String value;ASN1ObjectIdentifier oid;
- vTok = new X509NameTokenizer(token, '=');
-
- name = vTok.nextToken();
-
- if (!vTok.hasMoreTokens())
- {
- throw new IllegalArgumentException("badly formatted directory string");
- }
-
- value = vTok.nextToken();
-
- oid = decodeOID(name, lookUp);
-
- this.ordering.addElement(oid);
- this.values.addElement(unescape(value));
- this.added.addElement(isAdded);
- }
-
- /**
- * return a vector of the oids in the name, in the order they were found.
- */
- public Vector getOIDs()
- {
- Vector v = new Vector();
-
- for (int i = 0; i != ordering.size(); i++)
- {
- v.addElement(ordering.elementAt(i));
- }
-
- return v;
- }
-
- /**
- * return a vector of the values found in the name, in the order they
- * were found.
- */
- public Vector getValues()
- {
- Vector v = new Vector();
-
- for (int i = 0; i != values.size(); i++)
- {
- v.addElement(values.elementAt(i));
- }
-
- return v;
- }
-
- /**
- * return a vector of the values found in the name, in the order they
- * were found, with the DN label corresponding to passed in oid.
- */
- public Vector getValues(
- ASN1ObjectIdentifier oid)
- {
- Vector v = new Vector();
-
- for (int i = 0; i != values.size(); i++)
- {
- if (ordering.elementAt(i).equals(oid))
- {
- String val = (String)values.elementAt(i);
-
- if (val.length() > 2 && val.charAt(0) == '\\' && val.charAt(1) == '#')
- {
- v.addElement(val.substring(1));
- }
- else
- {
- v.addElement(val);
- }
- }
- }
-
- return v;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- if (seq == null)
- {
- ASN1EncodableVector vec = new ASN1EncodableVector();
- ASN1EncodableVector sVec = new ASN1EncodableVector();
- ASN1ObjectIdentifier lstOid = null;
-
- for (int i = 0; i != ordering.size(); i++)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)ordering.elementAt(i);
-
- v.add(oid);
-
- String str = (String)values.elementAt(i);
-
- v.add(converter.getConvertedValue(oid, str));
-
- if (lstOid == null
- || ((Boolean)this.added.elementAt(i)).booleanValue())
- {
- sVec.add(new DERSequence(v));
- }
- else
- {
- vec.add(new DERSet(sVec));
- sVec = new ASN1EncodableVector();
-
- sVec.add(new DERSequence(v));
- }
-
- lstOid = oid;
- }
-
- vec.add(new DERSet(sVec));
-
- seq = new DERSequence(vec);
- }
-
- return seq;
- }
-
- /**
- * @param inOrder if true the order of both X509 names must be the same,
- * as well as the values associated with each element.
- */
- public boolean equals(Object obj, boolean inOrder)
- {
- if (!inOrder)
- {
- return this.equals(obj);
- }
-
- if (obj == this)
- {
- return true;
- }
-
- if (!(obj instanceof X509Name || obj instanceof ASN1Sequence))
- {
- return false;
- }
-
- ASN1Primitive derO = ((ASN1Encodable)obj).toASN1Primitive();
-
- if (this.toASN1Primitive().equals(derO))
- {
- return true;
- }
-
- X509Name other;
-
- try
- {
- other = X509Name.getInstance(obj);
- }
- catch (IllegalArgumentException e)
- {
- return false;
- }
-
- int orderingSize = ordering.size();
-
- if (orderingSize != other.ordering.size())
- {
- return false;
- }
-
- for (int i = 0; i < orderingSize; i++)
- {
- ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)ordering.elementAt(i);
- ASN1ObjectIdentifier oOid = (ASN1ObjectIdentifier)other.ordering.elementAt(i);
-
- if (oid.equals(oOid))
- {
- String value = (String)values.elementAt(i);
- String oValue = (String)other.values.elementAt(i);
-
- if (!equivalentStrings(value, oValue))
- {
- return false;
- }
- }
- else
- {
- return false;
- }
- }
-
- return true;
- }
-
- public int hashCode()
- {
- if (isHashCodeCalculated)
- {
- return hashCodeValue;
- }
-
- isHashCodeCalculated = true;
-
- // this needs to be order independent, like equals
- for (int i = 0; i != ordering.size(); i += 1)
- {
- String value = (String)values.elementAt(i);
-
- value = canonicalize(value);
- value = stripInternalSpaces(value);
-
- hashCodeValue ^= ordering.elementAt(i).hashCode();
- hashCodeValue ^= value.hashCode();
- }
-
- return hashCodeValue;
- }
-
- /**
- * test for equality - note: case is ignored.
- */
- public boolean equals(Object obj)
- {
- if (obj == this)
- {
- return true;
- }
-
- if (!(obj instanceof X509Name || obj instanceof ASN1Sequence))
- {
- return false;
- }
-
- ASN1Primitive derO = ((ASN1Encodable)obj).toASN1Primitive();
-
- if (this.toASN1Primitive().equals(derO))
- {
- return true;
- }
-
- X509Name other;
-
- try
- {
- other = X509Name.getInstance(obj);
- }
- catch (IllegalArgumentException e)
- {
- return false;
- }
-
- int orderingSize = ordering.size();
-
- if (orderingSize != other.ordering.size())
- {
- return false;
- }
-
- boolean[] indexes = new boolean[orderingSize];
- int start, end, delta;
-
- if (ordering.elementAt(0).equals(other.ordering.elementAt(0))) // guess forward
- {
- start = 0;
- end = orderingSize;
- delta = 1;
- }
- else // guess reversed - most common problem
- {
- start = orderingSize - 1;
- end = -1;
- delta = -1;
- }
-
- for (int i = start; i != end; i += delta)
- {
- boolean found = false;
- ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)ordering.elementAt(i);
- String value = (String)values.elementAt(i);
-
- for (int j = 0; j < orderingSize; j++)
- {
- if (indexes[j])
- {
- continue;
- }
-
- ASN1ObjectIdentifier oOid = (ASN1ObjectIdentifier)other.ordering.elementAt(j);
-
- if (oid.equals(oOid))
- {
- String oValue = (String)other.values.elementAt(j);
-
- if (equivalentStrings(value, oValue))
- {
- indexes[j] = true;
- found = true;
- break;
- }
- }
- }
-
- if (!found)
- {
- return false;
- }
- }
-
- return true;
- }
-
- private boolean equivalentStrings(String s1, String s2)
- {
- String value = canonicalize(s1);
- String oValue = canonicalize(s2);
-
- if (!value.equals(oValue))
- {
- value = stripInternalSpaces(value);
- oValue = stripInternalSpaces(oValue);
-
- if (!value.equals(oValue))
- {
- return false;
- }
- }
-
- return true;
- }
-
- private String canonicalize(String s)
- {
- String value = Strings.toLowerCase(s.trim());
-
- if (value.length() > 0 && value.charAt(0) == '#')
- {
- ASN1Primitive obj = decodeObject(value);
-
- if (obj instanceof ASN1String)
- {
- value = Strings.toLowerCase(((ASN1String)obj).getString().trim());
- }
- }
-
- return value;
- }
-
- private ASN1Primitive decodeObject(String oValue)
- {
- try
- {
- return ASN1Primitive.fromByteArray(Hex.decode(oValue.substring(1)));
- }
- catch (IOException e)
- {
- throw new IllegalStateException("unknown encoding in name: " + e);
- }
- }
-
- private String stripInternalSpaces(
- String str)
- {
- StringBuffer res = new StringBuffer();
-
- if (str.length() != 0)
- {
- char c1 = str.charAt(0);
-
- res.append(c1);
-
- for (int k = 1; k < str.length(); k++)
- {
- char c2 = str.charAt(k);
- if (!(c1 == ' ' && c2 == ' '))
- {
- res.append(c2);
- }
- c1 = c2;
- }
- }
-
- return res.toString();
- }
-
- private void appendValue(
- StringBuffer buf,
- Hashtable oidSymbols,
- ASN1ObjectIdentifier oid,
- String value)
- {
- String sym = (String)oidSymbols.get(oid);
-
- if (sym != null)
- {
- buf.append(sym);
- }
- else
- {
- buf.append(oid.getId());
- }
-
- buf.append('=');
-
- int start = buf.length();
- buf.append(value);
- int end = buf.length();
-
- if (value.length() >= 2 && value.charAt(0) == '\\' && value.charAt(1) == '#')
- {
- start += 2;
- }
-
- while (start < end && buf.charAt(start) == ' ')
- {
- buf.insert(start, "\\");
- start += 2;
- ++end;
- }
-
- while (--end > start && buf.charAt(end) == ' ')
- {
- buf.insert(end, '\\');
- }
-
- while (start <= end)
- {
- switch (buf.charAt(start))
- {
- case ',':
- case '"':
- case '\\':
- case '+':
- case '=':
- case '<':
- case '>':
- case ';':
- buf.insert(start, "\\");
- start += 2;
- ++end;
- break;
- default:
- ++start;
- break;
- }
- }
- }
-
- /**
- * convert the structure to a string - if reverse is true the
- * oids and values are listed out starting with the last element
- * in the sequence (ala RFC 2253), otherwise the string will begin
- * with the first element of the structure. If no string definition
- * for the oid is found in oidSymbols the string value of the oid is
- * added. Two standard symbol tables are provided DefaultSymbols, and
- * RFC2253Symbols as part of this class.
- *
- * @param reverse if true start at the end of the sequence and work back.
- * @param oidSymbols look up table strings for oids.
- */
- public String toString(
- boolean reverse,
- Hashtable oidSymbols)
- {
- StringBuffer buf = new StringBuffer();
- Vector components = new Vector();
- boolean first = true;
-
- StringBuffer ava = null;
-
- for (int i = 0; i < ordering.size(); i++)
- {
- if (((Boolean)added.elementAt(i)).booleanValue())
- {
- ava.append('+');
- appendValue(ava, oidSymbols,
- (ASN1ObjectIdentifier)ordering.elementAt(i),
- (String)values.elementAt(i));
- }
- else
- {
- ava = new StringBuffer();
- appendValue(ava, oidSymbols,
- (ASN1ObjectIdentifier)ordering.elementAt(i),
- (String)values.elementAt(i));
- components.addElement(ava);
- }
- }
-
- if (reverse)
- {
- for (int i = components.size() - 1; i >= 0; i--)
- {
- if (first)
- {
- first = false;
- }
- else
- {
- buf.append(',');
- }
-
- buf.append(components.elementAt(i).toString());
- }
- }
- else
- {
- for (int i = 0; i < components.size(); i++)
- {
- if (first)
- {
- first = false;
- }
- else
- {
- buf.append(',');
- }
-
- buf.append(components.elementAt(i).toString());
- }
- }
-
- return buf.toString();
- }
-
- private String bytesToString(
- byte[] data)
- {
- char[] cs = new char[data.length];
-
- for (int i = 0; i != cs.length; i++)
- {
- cs[i] = (char)(data[i] & 0xff);
- }
-
- return new String(cs);
- }
-
- public String toString()
- {
- return toString(DefaultReverse, DefaultSymbols);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/X509NameEntryConverter.java b/core/src/main/java/org/bouncycastle/asn1/x509/X509NameEntryConverter.java
deleted file mode 100644
index 188af430..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/X509NameEntryConverter.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.DERPrintableString;
-import org.bouncycastle.util.Strings;
-
-/**
- * It turns out that the number of standard ways the fields in a DN should be
- * encoded into their ASN.1 counterparts is rapidly approaching the
- * number of machines on the internet. By default the X509Name class
- * will produce UTF8Strings in line with the current recommendations (RFC 3280).
- * <p>
- * An example of an encoder look like below:
- * <pre>
- * public class X509DirEntryConverter
- * extends X509NameEntryConverter
- * {
- * public ASN1Primitive getConvertedValue(
- * ASN1ObjectIdentifier oid,
- * String value)
- * {
- * if (str.length() != 0 &amp;&amp; str.charAt(0) == '#')
- * {
- * return convertHexEncoded(str, 1);
- * }
- * if (oid.equals(EmailAddress))
- * {
- * return new DERIA5String(str);
- * }
- * else if (canBePrintable(str))
- * {
- * return new DERPrintableString(str);
- * }
- * else if (canBeUTF8(str))
- * {
- * return new DERUTF8String(str);
- * }
- * else
- * {
- * return new DERBMPString(str);
- * }
- * }
- * }
- * </pre>
- */
-public abstract class X509NameEntryConverter
-{
- /**
- * Convert an inline encoded hex string rendition of an ASN.1
- * object back into its corresponding ASN.1 object.
- *
- * @param str the hex encoded object
- * @param off the index at which the encoding starts
- * @return the decoded object
- */
- protected ASN1Primitive convertHexEncoded(
- String str,
- int off)
- throws IOException
- {
- str = Strings.toLowerCase(str);
- byte[] data = new byte[(str.length() - off) / 2];
- for (int index = 0; index != data.length; index++)
- {
- char left = str.charAt((index * 2) + off);
- char right = str.charAt((index * 2) + off + 1);
-
- if (left < 'a')
- {
- data[index] = (byte)((left - '0') << 4);
- }
- else
- {
- data[index] = (byte)((left - 'a' + 10) << 4);
- }
- if (right < 'a')
- {
- data[index] |= (byte)(right - '0');
- }
- else
- {
- data[index] |= (byte)(right - 'a' + 10);
- }
- }
-
- ASN1InputStream aIn = new ASN1InputStream(data);
-
- return aIn.readObject();
- }
-
- /**
- * return true if the passed in String can be represented without
- * loss as a PrintableString, false otherwise.
- */
- protected boolean canBePrintable(
- String str)
- {
- return DERPrintableString.isPrintableString(str);
- }
-
- /**
- * Convert the passed in String value into the appropriate ASN.1
- * encoded object.
- *
- * @param oid the oid associated with the value in the DN.
- * @param value the value of the particular DN component.
- * @return the ASN.1 equivalent for the value.
- */
- public abstract ASN1Primitive getConvertedValue(ASN1ObjectIdentifier oid, String value);
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/X509NameTokenizer.java b/core/src/main/java/org/bouncycastle/asn1/x509/X509NameTokenizer.java
deleted file mode 100644
index 7f99235b..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/X509NameTokenizer.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-/**
- * class for breaking up an X500 Name into it's component tokens, ala
- * java.util.StringTokenizer. We need this class as some of the
- * lightweight Java environment don't support classes like
- * StringTokenizer.
- * @deprecated use X500NameTokenizer
- */
-public class X509NameTokenizer
-{
- private String value;
- private int index;
- private char separator;
- private StringBuffer buf = new StringBuffer();
-
- public X509NameTokenizer(
- String oid)
- {
- this(oid, ',');
- }
-
- public X509NameTokenizer(
- String oid,
- char separator)
- {
- this.value = oid;
- this.index = -1;
- this.separator = separator;
- }
-
- public boolean hasMoreTokens()
- {
- return (index != value.length());
- }
-
- public String nextToken()
- {
- if (index == value.length())
- {
- return null;
- }
-
- int end = index + 1;
- boolean quoted = false;
- boolean escaped = false;
-
- buf.setLength(0);
-
- while (end != value.length())
- {
- char c = value.charAt(end);
-
- if (c == '"')
- {
- if (!escaped)
- {
- quoted = !quoted;
- }
- buf.append(c);
- escaped = false;
- }
- else
- {
- if (escaped || quoted)
- {
- buf.append(c);
- escaped = false;
- }
- else if (c == '\\')
- {
- buf.append(c);
- escaped = true;
- }
- else if (c == separator)
- {
- break;
- }
- else
- {
- buf.append(c);
- }
- }
- end++;
- }
-
- index = end;
-
- return buf.toString();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java
deleted file mode 100644
index e1c7a54b..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-
-public interface X509ObjectIdentifiers
-{
-
- /** 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");
- /** 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 }
- * <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)}
- * <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) }
- * <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 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; 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
- * <p>
- * OID: 2.5.29
- */
- static final ASN1ObjectIdentifier id_ce = new ASN1ObjectIdentifier("2.5.29");
-
- /** 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 uri in AuthorityInformationAccess extension */
- static final ASN1ObjectIdentifier ocspAccessMethod = id_ad_ocsp;
- /** OID for crl uri in AuthorityInformationAccess extension */
- static final ASN1ObjectIdentifier crlAccessMethod = id_ad_caIssuers;
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/qualified/BiometricData.java b/core/src/main/java/org/bouncycastle/asn1/x509/qualified/BiometricData.java
deleted file mode 100644
index 32fa451d..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/qualified/BiometricData.java
+++ /dev/null
@@ -1,122 +0,0 @@
-package org.bouncycastle.asn1.x509.qualified;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-/**
- * The BiometricData object.
- * <pre>
- * BiometricData ::= SEQUENCE {
- * typeOfBiometricData TypeOfBiometricData,
- * hashAlgorithm AlgorithmIdentifier,
- * biometricDataHash OCTET STRING,
- * sourceDataUri IA5String OPTIONAL }
- * </pre>
- */
-public class BiometricData
- extends ASN1Object
-{
- private TypeOfBiometricData typeOfBiometricData;
- private AlgorithmIdentifier hashAlgorithm;
- private ASN1OctetString biometricDataHash;
- private DERIA5String sourceDataUri;
-
- public static BiometricData getInstance(
- Object obj)
- {
- if (obj instanceof BiometricData)
- {
- return (BiometricData)obj;
- }
-
- if (obj != null)
- {
- return new BiometricData(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private BiometricData(ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- // typeOfBiometricData
- typeOfBiometricData = TypeOfBiometricData.getInstance(e.nextElement());
- // hashAlgorithm
- hashAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement());
- // biometricDataHash
- biometricDataHash = ASN1OctetString.getInstance(e.nextElement());
- // sourceDataUri
- if (e.hasMoreElements())
- {
- sourceDataUri = DERIA5String.getInstance(e.nextElement());
- }
- }
-
- public BiometricData(
- TypeOfBiometricData typeOfBiometricData,
- AlgorithmIdentifier hashAlgorithm,
- ASN1OctetString biometricDataHash,
- DERIA5String sourceDataUri)
- {
- this.typeOfBiometricData = typeOfBiometricData;
- this.hashAlgorithm = hashAlgorithm;
- this.biometricDataHash = biometricDataHash;
- this.sourceDataUri = sourceDataUri;
- }
-
- public BiometricData(
- TypeOfBiometricData typeOfBiometricData,
- AlgorithmIdentifier hashAlgorithm,
- ASN1OctetString biometricDataHash)
- {
- this.typeOfBiometricData = typeOfBiometricData;
- this.hashAlgorithm = hashAlgorithm;
- this.biometricDataHash = biometricDataHash;
- this.sourceDataUri = null;
- }
-
- public TypeOfBiometricData getTypeOfBiometricData()
- {
- return typeOfBiometricData;
- }
-
- public AlgorithmIdentifier getHashAlgorithm()
- {
- return hashAlgorithm;
- }
-
- public ASN1OctetString getBiometricDataHash()
- {
- return biometricDataHash;
- }
-
- public DERIA5String getSourceDataUri()
- {
- return sourceDataUri;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector seq = new ASN1EncodableVector();
- seq.add(typeOfBiometricData);
- seq.add(hashAlgorithm);
- seq.add(biometricDataHash);
-
- if (sourceDataUri != null)
- {
- seq.add(sourceDataUri);
- }
-
- return new DERSequence(seq);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/qualified/ETSIQCObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/x509/qualified/ETSIQCObjectIdentifiers.java
deleted file mode 100644
index 22db8cb8..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/qualified/ETSIQCObjectIdentifiers.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.bouncycastle.asn1.x509.qualified;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-
-public interface ETSIQCObjectIdentifiers
-{
- 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/core/src/main/java/org/bouncycastle/asn1/x509/qualified/Iso4217CurrencyCode.java b/core/src/main/java/org/bouncycastle/asn1/x509/qualified/Iso4217CurrencyCode.java
deleted file mode 100644
index b6cfb629..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/qualified/Iso4217CurrencyCode.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package org.bouncycastle.asn1.x509.qualified;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.DERPrintableString;
-
-/**
- * The Iso4217CurrencyCode object.
- * <pre>
- * Iso4217CurrencyCode ::= CHOICE {
- * alphabetic PrintableString (SIZE 3), --Recommended
- * numeric INTEGER (1..999) }
- * -- Alphabetic or numeric currency code as defined in ISO 4217
- * -- It is recommended that the Alphabetic form is used
- * </pre>
- */
-public class Iso4217CurrencyCode
- extends ASN1Object
- implements ASN1Choice
-{
- final int ALPHABETIC_MAXSIZE = 3;
- final int NUMERIC_MINSIZE = 1;
- final int NUMERIC_MAXSIZE = 999;
-
- ASN1Encodable obj;
- int numeric;
-
- public static Iso4217CurrencyCode getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof Iso4217CurrencyCode)
- {
- return (Iso4217CurrencyCode)obj;
- }
-
- if (obj instanceof ASN1Integer)
- {
- ASN1Integer numericobj = ASN1Integer.getInstance(obj);
- int numeric = numericobj.getValue().intValue();
- return new Iso4217CurrencyCode(numeric);
- }
- else
- if (obj instanceof DERPrintableString)
- {
- DERPrintableString alphabetic = DERPrintableString.getInstance(obj);
- return new Iso4217CurrencyCode(alphabetic.getString());
- }
- throw new IllegalArgumentException("unknown object in getInstance");
- }
-
- public Iso4217CurrencyCode(
- int numeric)
- {
- if (numeric > NUMERIC_MAXSIZE || numeric < NUMERIC_MINSIZE)
- {
- throw new IllegalArgumentException("wrong size in numeric code : not in (" +NUMERIC_MINSIZE +".."+ NUMERIC_MAXSIZE +")");
- }
- obj = new ASN1Integer(numeric);
- }
-
- public Iso4217CurrencyCode(
- String alphabetic)
- {
- if (alphabetic.length() > ALPHABETIC_MAXSIZE)
- {
- throw new IllegalArgumentException("wrong size in alphabetic code : max size is " + ALPHABETIC_MAXSIZE);
- }
- obj = new DERPrintableString(alphabetic);
- }
-
- public boolean isAlphabetic()
- {
- return obj instanceof DERPrintableString;
- }
-
- public String getAlphabetic()
- {
- return ((DERPrintableString)obj).getString();
- }
-
- public int getNumeric()
- {
- return ((ASN1Integer)obj).getValue().intValue();
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return obj.toASN1Primitive();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/qualified/MonetaryValue.java b/core/src/main/java/org/bouncycastle/asn1/x509/qualified/MonetaryValue.java
deleted file mode 100644
index 1ec2dcdb..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/qualified/MonetaryValue.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package org.bouncycastle.asn1.x509.qualified;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-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.DERSequence;
-
-/**
- * The MonetaryValue object.
- * <pre>
- * MonetaryValue ::= SEQUENCE {
- * currency Iso4217CurrencyCode,
- * amount INTEGER,
- * exponent INTEGER }
- * -- value = amount * 10^exponent
- * </pre>
- */
-public class MonetaryValue
- extends ASN1Object
-{
- private Iso4217CurrencyCode currency;
- private ASN1Integer amount;
- private ASN1Integer exponent;
-
- public static MonetaryValue getInstance(
- Object obj)
- {
- if (obj instanceof MonetaryValue)
- {
- return (MonetaryValue)obj;
- }
-
- if (obj != null)
- {
- return new MonetaryValue(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private MonetaryValue(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
- // currency
- currency = Iso4217CurrencyCode.getInstance(e.nextElement());
- // hashAlgorithm
- amount = ASN1Integer.getInstance(e.nextElement());
- // exponent
- exponent = ASN1Integer.getInstance(e.nextElement());
- }
-
- public MonetaryValue(
- Iso4217CurrencyCode currency,
- int amount,
- int exponent)
- {
- this.currency = currency;
- this.amount = new ASN1Integer(amount);
- this.exponent = new ASN1Integer(exponent);
- }
-
- public Iso4217CurrencyCode getCurrency()
- {
- return currency;
- }
-
- public BigInteger getAmount()
- {
- return amount.getValue();
- }
-
- public BigInteger getExponent()
- {
- return exponent.getValue();
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector seq = new ASN1EncodableVector();
- seq.add(currency);
- seq.add(amount);
- seq.add(exponent);
-
- return new DERSequence(seq);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/qualified/QCStatement.java b/core/src/main/java/org/bouncycastle/asn1/x509/qualified/QCStatement.java
deleted file mode 100644
index 82b01e71..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/qualified/QCStatement.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package org.bouncycastle.asn1.x509.qualified;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * The QCStatement object.
- * <pre>
- * QCStatement ::= SEQUENCE {
- * statementId OBJECT IDENTIFIER,
- * statementInfo ANY DEFINED BY statementId OPTIONAL}
- * </pre>
- */
-
-public class QCStatement
- extends ASN1Object
- implements ETSIQCObjectIdentifiers, RFC3739QCObjectIdentifiers
-{
- ASN1ObjectIdentifier qcStatementId;
- ASN1Encodable qcStatementInfo;
-
- public static QCStatement getInstance(
- Object obj)
- {
- if (obj instanceof QCStatement)
- {
- return (QCStatement)obj;
- }
- if (obj != null)
- {
- return new QCStatement(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private QCStatement(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- // qcStatementId
- qcStatementId = ASN1ObjectIdentifier.getInstance(e.nextElement());
- // qcstatementInfo
- if (e.hasMoreElements())
- {
- qcStatementInfo = (ASN1Encodable) e.nextElement();
- }
- }
-
- public QCStatement(
- ASN1ObjectIdentifier qcStatementId)
- {
- this.qcStatementId = qcStatementId;
- this.qcStatementInfo = null;
- }
-
- public QCStatement(
- ASN1ObjectIdentifier qcStatementId,
- ASN1Encodable qcStatementInfo)
- {
- this.qcStatementId = qcStatementId;
- this.qcStatementInfo = qcStatementInfo;
- }
-
- public ASN1ObjectIdentifier getStatementId()
- {
- return qcStatementId;
- }
-
- public ASN1Encodable getStatementInfo()
- {
- return qcStatementInfo;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector seq = new ASN1EncodableVector();
- seq.add(qcStatementId);
-
- if (qcStatementInfo != null)
- {
- seq.add(qcStatementInfo);
- }
-
- return new DERSequence(seq);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/qualified/RFC3739QCObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/x509/qualified/RFC3739QCObjectIdentifiers.java
deleted file mode 100644
index 0c840bdc..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/qualified/RFC3739QCObjectIdentifiers.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.bouncycastle.asn1.x509.qualified;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-
-public interface RFC3739QCObjectIdentifiers
-{
- /** 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/core/src/main/java/org/bouncycastle/asn1/x509/qualified/SemanticsInformation.java b/core/src/main/java/org/bouncycastle/asn1/x509/qualified/SemanticsInformation.java
deleted file mode 100644
index 43d8d585..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/qualified/SemanticsInformation.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package org.bouncycastle.asn1.x509.qualified;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.GeneralName;
-
-/**
- * The SemanticsInformation object.
- * <pre>
- * SemanticsInformation ::= SEQUENCE {
- * semanticsIdentifier OBJECT IDENTIFIER OPTIONAL,
- * nameRegistrationAuthorities NameRegistrationAuthorities
- * OPTIONAL }
- * (WITH COMPONENTS {..., semanticsIdentifier PRESENT}|
- * WITH COMPONENTS {..., nameRegistrationAuthorities PRESENT})
- *
- * NameRegistrationAuthorities ::= SEQUENCE SIZE (1..MAX) OF
- * GeneralName
- * </pre>
- */
-public class SemanticsInformation
- extends ASN1Object
-{
- private ASN1ObjectIdentifier semanticsIdentifier;
- private GeneralName[] nameRegistrationAuthorities;
-
- public static SemanticsInformation getInstance(Object obj)
- {
- if (obj instanceof SemanticsInformation)
- {
- return (SemanticsInformation)obj;
- }
-
- if (obj != null)
- {
- return new SemanticsInformation(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- private SemanticsInformation(ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
- if (seq.size() < 1)
- {
- throw new IllegalArgumentException("no objects in SemanticsInformation");
- }
-
- Object object = e.nextElement();
- if (object instanceof ASN1ObjectIdentifier)
- {
- semanticsIdentifier = ASN1ObjectIdentifier.getInstance(object);
- if (e.hasMoreElements())
- {
- object = e.nextElement();
- }
- else
- {
- object = null;
- }
- }
-
- if (object != null)
- {
- ASN1Sequence generalNameSeq = ASN1Sequence.getInstance(object);
- nameRegistrationAuthorities = new GeneralName[generalNameSeq.size()];
- for (int i= 0; i < generalNameSeq.size(); i++)
- {
- nameRegistrationAuthorities[i] = GeneralName.getInstance(generalNameSeq.getObjectAt(i));
- }
- }
- }
-
- public SemanticsInformation(
- ASN1ObjectIdentifier semanticsIdentifier,
- GeneralName[] generalNames)
- {
- this.semanticsIdentifier = semanticsIdentifier;
- this.nameRegistrationAuthorities = generalNames;
- }
-
- public SemanticsInformation(ASN1ObjectIdentifier semanticsIdentifier)
- {
- this.semanticsIdentifier = semanticsIdentifier;
- this.nameRegistrationAuthorities = null;
- }
-
- public SemanticsInformation(GeneralName[] generalNames)
- {
- this.semanticsIdentifier = null;
- this.nameRegistrationAuthorities = generalNames;
- }
-
- public ASN1ObjectIdentifier getSemanticsIdentifier()
- {
- return semanticsIdentifier;
- }
-
- public GeneralName[] getNameRegistrationAuthorities()
- {
- return nameRegistrationAuthorities;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector seq = new ASN1EncodableVector();
-
- if (this.semanticsIdentifier != null)
- {
- seq.add(semanticsIdentifier);
- }
- if (this.nameRegistrationAuthorities != null)
- {
- ASN1EncodableVector seqname = new ASN1EncodableVector();
- for (int i = 0; i < nameRegistrationAuthorities.length; i++)
- {
- seqname.add(nameRegistrationAuthorities[i]);
- }
- seq.add(new DERSequence(seqname));
- }
-
- return new DERSequence(seq);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/qualified/TypeOfBiometricData.java b/core/src/main/java/org/bouncycastle/asn1/x509/qualified/TypeOfBiometricData.java
deleted file mode 100644
index 01b254eb..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/qualified/TypeOfBiometricData.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package org.bouncycastle.asn1.x509.qualified;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-
-/**
- * The TypeOfBiometricData object.
- * <pre>
- * TypeOfBiometricData ::= CHOICE {
- * predefinedBiometricType PredefinedBiometricType,
- * biometricDataOid OBJECT IDENTIFIER }
- *
- * PredefinedBiometricType ::= INTEGER {
- * picture(0),handwritten-signature(1)}
- * (picture|handwritten-signature)
- * </pre>
- */
-public class TypeOfBiometricData
- extends ASN1Object
- implements ASN1Choice
-{
- public static final int PICTURE = 0;
- public static final int HANDWRITTEN_SIGNATURE = 1;
-
- ASN1Encodable obj;
-
- public static TypeOfBiometricData getInstance(Object obj)
- {
- if (obj == null || obj instanceof TypeOfBiometricData)
- {
- return (TypeOfBiometricData)obj;
- }
-
- if (obj instanceof ASN1Integer)
- {
- ASN1Integer predefinedBiometricTypeObj = ASN1Integer.getInstance(obj);
- int predefinedBiometricType = predefinedBiometricTypeObj.getValue().intValue();
-
- return new TypeOfBiometricData(predefinedBiometricType);
- }
- else if (obj instanceof ASN1ObjectIdentifier)
- {
- ASN1ObjectIdentifier BiometricDataID = ASN1ObjectIdentifier.getInstance(obj);
- return new TypeOfBiometricData(BiometricDataID);
- }
-
- throw new IllegalArgumentException("unknown object in getInstance");
- }
-
- public TypeOfBiometricData(int predefinedBiometricType)
- {
- if (predefinedBiometricType == PICTURE || predefinedBiometricType == HANDWRITTEN_SIGNATURE)
- {
- obj = new ASN1Integer(predefinedBiometricType);
- }
- else
- {
- throw new IllegalArgumentException("unknow PredefinedBiometricType : " + predefinedBiometricType);
- }
- }
-
- public TypeOfBiometricData(ASN1ObjectIdentifier BiometricDataID)
- {
- obj = BiometricDataID;
- }
-
- public boolean isPredefined()
- {
- return obj instanceof ASN1Integer;
- }
-
- public int getPredefinedBiometricType()
- {
- return ((ASN1Integer)obj).getValue().intValue();
- }
-
- public ASN1ObjectIdentifier getBiometricDataOid()
- {
- return (ASN1ObjectIdentifier)obj;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return obj.toASN1Primitive();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/sigi/NameOrPseudonym.java b/core/src/main/java/org/bouncycastle/asn1/x509/sigi/NameOrPseudonym.java
deleted file mode 100644
index f7162e2a..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/sigi/NameOrPseudonym.java
+++ /dev/null
@@ -1,189 +0,0 @@
-package org.bouncycastle.asn1.x509.sigi;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1String;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x500.DirectoryString;
-
-/**
- * Structure for a name or pseudonym.
- *
- * <pre>
- * NameOrPseudonym ::= CHOICE {
- * surAndGivenName SEQUENCE {
- * surName DirectoryString,
- * givenName SEQUENCE OF DirectoryString
- * },
- * pseudonym DirectoryString
- * }
- * </pre>
- *
- * @see org.bouncycastle.asn1.x509.sigi.PersonalData
- *
- */
-public class NameOrPseudonym
- extends ASN1Object
- implements ASN1Choice
-{
- private DirectoryString pseudonym;
-
- private DirectoryString surname;
-
- private ASN1Sequence givenName;
-
- public static NameOrPseudonym getInstance(Object obj)
- {
- if (obj == null || obj instanceof NameOrPseudonym)
- {
- return (NameOrPseudonym)obj;
- }
-
- if (obj instanceof ASN1String)
- {
- return new NameOrPseudonym(DirectoryString.getInstance(obj));
- }
-
- if (obj instanceof ASN1Sequence)
- {
- return new NameOrPseudonym((ASN1Sequence)obj);
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: "
- + obj.getClass().getName());
- }
-
- /**
- * Constructor from DirectoryString.
- * <p>
- * The sequence is of type NameOrPseudonym:
- * <pre>
- * NameOrPseudonym ::= CHOICE {
- * surAndGivenName SEQUENCE {
- * surName DirectoryString,
- * givenName SEQUENCE OF DirectoryString
- * },
- * pseudonym DirectoryString
- * }
- * </pre>
- * @param pseudonym pseudonym value to use.
- */
- public NameOrPseudonym(DirectoryString pseudonym)
- {
- this.pseudonym = pseudonym;
- }
-
- /**
- * Constructor from ASN1Sequence.
- * <p/>
- * The sequence is of type NameOrPseudonym:
- * <p/>
- * <pre>
- * NameOrPseudonym ::= CHOICE {
- * surAndGivenName SEQUENCE {
- * surName DirectoryString,
- * givenName SEQUENCE OF DirectoryString
- * },
- * pseudonym DirectoryString
- * }
- * </pre>
- *
- * @param seq The ASN.1 sequence.
- */
- private NameOrPseudonym(ASN1Sequence seq)
- {
- if (seq.size() != 2)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
-
- if (!(seq.getObjectAt(0) instanceof ASN1String))
- {
- throw new IllegalArgumentException("Bad object encountered: "
- + seq.getObjectAt(0).getClass());
- }
-
- surname = DirectoryString.getInstance(seq.getObjectAt(0));
- givenName = ASN1Sequence.getInstance(seq.getObjectAt(1));
- }
-
- /**
- * Constructor from a given details.
- *
- * @param pseudonym The pseudonym.
- */
- public NameOrPseudonym(String pseudonym)
- {
- this(new DirectoryString(pseudonym));
- }
-
- /**
- * Constructor from a given details.
- *
- * @param surname The surname.
- * @param givenName A sequence of directory strings making up the givenName
- */
- public NameOrPseudonym(DirectoryString surname, ASN1Sequence givenName)
- {
- this.surname = surname;
- this.givenName = givenName;
- }
-
- public DirectoryString getPseudonym()
- {
- return pseudonym;
- }
-
- public DirectoryString getSurname()
- {
- return surname;
- }
-
- public DirectoryString[] getGivenName()
- {
- DirectoryString[] items = new DirectoryString[givenName.size()];
- int count = 0;
- for (Enumeration e = givenName.getObjects(); e.hasMoreElements();)
- {
- items[count++] = DirectoryString.getInstance(e.nextElement());
- }
- return items;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <p>
- * Returns:
- * <pre>
- * NameOrPseudonym ::= CHOICE {
- * surAndGivenName SEQUENCE {
- * surName DirectoryString,
- * givenName SEQUENCE OF DirectoryString
- * },
- * pseudonym DirectoryString
- * }
- * </pre>
- *
- * @return a DERObject
- */
- public ASN1Primitive toASN1Primitive()
- {
- if (pseudonym != null)
- {
- return pseudonym.toASN1Primitive();
- }
- else
- {
- ASN1EncodableVector vec1 = new ASN1EncodableVector();
- vec1.add(surname);
- vec1.add(givenName);
- return new DERSequence(vec1);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/sigi/PersonalData.java b/core/src/main/java/org/bouncycastle/asn1/x509/sigi/PersonalData.java
deleted file mode 100644
index f8c23b3a..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/sigi/PersonalData.java
+++ /dev/null
@@ -1,213 +0,0 @@
-package org.bouncycastle.asn1.x509.sigi;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERPrintableString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x500.DirectoryString;
-
-/**
- * Contains personal data for the otherName field in the subjectAltNames
- * extension.
- *
- * <pre>
- * PersonalData ::= SEQUENCE {
- * nameOrPseudonym NameOrPseudonym,
- * nameDistinguisher [0] INTEGER OPTIONAL,
- * dateOfBirth [1] GeneralizedTime OPTIONAL,
- * placeOfBirth [2] DirectoryString OPTIONAL,
- * gender [3] PrintableString OPTIONAL,
- * postalAddress [4] DirectoryString OPTIONAL
- * }
- * </pre>
- *
- * @see org.bouncycastle.asn1.x509.sigi.NameOrPseudonym
- * @see org.bouncycastle.asn1.x509.sigi.SigIObjectIdentifiers
- */
-public class PersonalData
- extends ASN1Object
-{
- private NameOrPseudonym nameOrPseudonym;
- private BigInteger nameDistinguisher;
- private ASN1GeneralizedTime dateOfBirth;
- private DirectoryString placeOfBirth;
- private String gender;
- private DirectoryString postalAddress;
-
- public static PersonalData getInstance(Object obj)
- {
- if (obj == null || obj instanceof PersonalData)
- {
- return (PersonalData)obj;
- }
-
- if (obj instanceof ASN1Sequence)
- {
- return new PersonalData((ASN1Sequence)obj);
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * Constructor from ASN1Sequence.
- * <p/>
- * The sequence is of type NameOrPseudonym:
- * <p/>
- * <pre>
- * PersonalData ::= SEQUENCE {
- * nameOrPseudonym NameOrPseudonym,
- * nameDistinguisher [0] INTEGER OPTIONAL,
- * dateOfBirth [1] GeneralizedTime OPTIONAL,
- * placeOfBirth [2] DirectoryString OPTIONAL,
- * gender [3] PrintableString OPTIONAL,
- * postalAddress [4] DirectoryString OPTIONAL
- * }
- * </pre>
- *
- * @param seq The ASN.1 sequence.
- */
- private PersonalData(ASN1Sequence seq)
- {
- if (seq.size() < 1)
- {
- throw new IllegalArgumentException("Bad sequence size: "
- + seq.size());
- }
-
- Enumeration e = seq.getObjects();
-
- nameOrPseudonym = NameOrPseudonym.getInstance(e.nextElement());
-
- while (e.hasMoreElements())
- {
- ASN1TaggedObject o = ASN1TaggedObject.getInstance(e.nextElement());
- int tag = o.getTagNo();
- switch (tag)
- {
- case 0:
- nameDistinguisher = ASN1Integer.getInstance(o, false).getValue();
- break;
- case 1:
- dateOfBirth = ASN1GeneralizedTime.getInstance(o, false);
- break;
- case 2:
- placeOfBirth = DirectoryString.getInstance(o, true);
- break;
- case 3:
- gender = DERPrintableString.getInstance(o, false).getString();
- break;
- case 4:
- postalAddress = DirectoryString.getInstance(o, true);
- break;
- default:
- throw new IllegalArgumentException("Bad tag number: " + o.getTagNo());
- }
- }
- }
-
- /**
- * Constructor from a given details.
- *
- * @param nameOrPseudonym Name or pseudonym.
- * @param nameDistinguisher Name distinguisher.
- * @param dateOfBirth Date of birth.
- * @param placeOfBirth Place of birth.
- * @param gender Gender.
- * @param postalAddress Postal Address.
- */
- public PersonalData(NameOrPseudonym nameOrPseudonym,
- BigInteger nameDistinguisher, ASN1GeneralizedTime dateOfBirth,
- DirectoryString placeOfBirth, String gender, DirectoryString postalAddress)
- {
- this.nameOrPseudonym = nameOrPseudonym;
- this.dateOfBirth = dateOfBirth;
- this.gender = gender;
- this.nameDistinguisher = nameDistinguisher;
- this.postalAddress = postalAddress;
- this.placeOfBirth = placeOfBirth;
- }
-
- public NameOrPseudonym getNameOrPseudonym()
- {
- return nameOrPseudonym;
- }
-
- public BigInteger getNameDistinguisher()
- {
- return nameDistinguisher;
- }
-
- public ASN1GeneralizedTime getDateOfBirth()
- {
- return dateOfBirth;
- }
-
- public DirectoryString getPlaceOfBirth()
- {
- return placeOfBirth;
- }
-
- public String getGender()
- {
- return gender;
- }
-
- public DirectoryString getPostalAddress()
- {
- return postalAddress;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <p>
- * Returns:
- * <pre>
- * PersonalData ::= SEQUENCE {
- * nameOrPseudonym NameOrPseudonym,
- * nameDistinguisher [0] INTEGER OPTIONAL,
- * dateOfBirth [1] GeneralizedTime OPTIONAL,
- * placeOfBirth [2] DirectoryString OPTIONAL,
- * gender [3] PrintableString OPTIONAL,
- * postalAddress [4] DirectoryString OPTIONAL
- * }
- * </pre>
- *
- * @return a DERObject
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector vec = new ASN1EncodableVector();
- vec.add(nameOrPseudonym);
- if (nameDistinguisher != null)
- {
- vec.add(new DERTaggedObject(false, 0, new ASN1Integer(nameDistinguisher)));
- }
- if (dateOfBirth != null)
- {
- vec.add(new DERTaggedObject(false, 1, dateOfBirth));
- }
- if (placeOfBirth != null)
- {
- vec.add(new DERTaggedObject(true, 2, placeOfBirth));
- }
- if (gender != null)
- {
- vec.add(new DERTaggedObject(false, 3, new DERPrintableString(gender, true)));
- }
- if (postalAddress != null)
- {
- vec.add(new DERTaggedObject(true, 4, postalAddress));
- }
- return new DERSequence(vec);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x509/sigi/SigIObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/x509/sigi/SigIObjectIdentifiers.java
deleted file mode 100644
index d338614d..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x509/sigi/SigIObjectIdentifiers.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package org.bouncycastle.asn1.x509.sigi;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-
-/**
- * Object Identifiers of SigI specifciation (German Signature Law
- * Interoperability specification).
- */
-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("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("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("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("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("1.3.36.8.4.1");
-
- /**
- * 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("1.3.36.8.1.1");
-
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x9/DHDomainParameters.java b/core/src/main/java/org/bouncycastle/asn1/x9/DHDomainParameters.java
deleted file mode 100644
index 509111ad..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x9/DHDomainParameters.java
+++ /dev/null
@@ -1,163 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERSequence;
-
-public class DHDomainParameters
- extends ASN1Object
-{
- private ASN1Integer p, g, q, j;
- private DHValidationParms validationParms;
-
- public static DHDomainParameters getInstance(ASN1TaggedObject obj, boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static DHDomainParameters getInstance(Object obj)
- {
- if (obj == null || obj instanceof DHDomainParameters)
- {
- return (DHDomainParameters)obj;
- }
-
- if (obj instanceof ASN1Sequence)
- {
- return new DHDomainParameters((ASN1Sequence)obj);
- }
-
- throw new IllegalArgumentException("Invalid DHDomainParameters: "
- + obj.getClass().getName());
- }
-
- public DHDomainParameters(BigInteger p, BigInteger g, BigInteger q, BigInteger j,
- DHValidationParms validationParms)
- {
- if (p == null)
- {
- throw new IllegalArgumentException("'p' cannot be null");
- }
- if (g == null)
- {
- throw new IllegalArgumentException("'g' cannot be null");
- }
- if (q == null)
- {
- throw new IllegalArgumentException("'q' cannot be null");
- }
-
- this.p = new ASN1Integer(p);
- this.g = new ASN1Integer(g);
- this.q = new ASN1Integer(q);
- this.j = new ASN1Integer(j);
- this.validationParms = validationParms;
- }
-
- public DHDomainParameters(ASN1Integer p, ASN1Integer g, ASN1Integer q, ASN1Integer j,
- DHValidationParms validationParms)
- {
- if (p == null)
- {
- throw new IllegalArgumentException("'p' cannot be null");
- }
- if (g == null)
- {
- throw new IllegalArgumentException("'g' cannot be null");
- }
- if (q == null)
- {
- throw new IllegalArgumentException("'q' cannot be null");
- }
-
- this.p = p;
- this.g = g;
- this.q = q;
- this.j = j;
- this.validationParms = validationParms;
- }
-
- private DHDomainParameters(ASN1Sequence seq)
- {
- if (seq.size() < 3 || seq.size() > 5)
- {
- throw new IllegalArgumentException("Bad sequence size: " + seq.size());
- }
-
- Enumeration e = seq.getObjects();
- this.p = ASN1Integer.getInstance(e.nextElement());
- this.g = ASN1Integer.getInstance(e.nextElement());
- this.q = ASN1Integer.getInstance(e.nextElement());
-
- ASN1Encodable next = getNext(e);
-
- if (next != null && next instanceof ASN1Integer)
- {
- this.j = ASN1Integer.getInstance(next);
- next = getNext(e);
- }
-
- if (next != null)
- {
- this.validationParms = DHValidationParms.getInstance(next.toASN1Primitive());
- }
- }
-
- private static ASN1Encodable getNext(Enumeration e)
- {
- return e.hasMoreElements() ? (ASN1Encodable)e.nextElement() : null;
- }
-
- public ASN1Integer getP()
- {
- return this.p;
- }
-
- public ASN1Integer getG()
- {
- return this.g;
- }
-
- public ASN1Integer getQ()
- {
- return this.q;
- }
-
- public ASN1Integer getJ()
- {
- return this.j;
- }
-
- public DHValidationParms getValidationParms()
- {
- return this.validationParms;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- v.add(this.p);
- v.add(this.g);
- v.add(this.q);
-
- if (this.j != null)
- {
- v.add(this.j);
- }
-
- if (this.validationParms != null)
- {
- v.add(this.validationParms);
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x9/DHPublicKey.java b/core/src/main/java/org/bouncycastle/asn1/x9/DHPublicKey.java
deleted file mode 100644
index 7c6d217e..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x9/DHPublicKey.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-
-public class DHPublicKey
- extends ASN1Object
-{
- private ASN1Integer y;
-
- public static DHPublicKey getInstance(ASN1TaggedObject obj, boolean explicit)
- {
- return getInstance(ASN1Integer.getInstance(obj, explicit));
- }
-
- public static DHPublicKey getInstance(Object obj)
- {
- if (obj == null || obj instanceof DHPublicKey)
- {
- return (DHPublicKey)obj;
- }
-
- if (obj instanceof ASN1Integer)
- {
- return new DHPublicKey((ASN1Integer)obj);
- }
-
- throw new IllegalArgumentException("Invalid DHPublicKey: " + obj.getClass().getName());
- }
-
- public DHPublicKey(ASN1Integer y)
- {
- if (y == null)
- {
- throw new IllegalArgumentException("'y' cannot be null");
- }
-
- this.y = y;
- }
-
- public ASN1Integer getY()
- {
- return this.y;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return this.y;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x9/DHValidationParms.java b/core/src/main/java/org/bouncycastle/asn1/x9/DHValidationParms.java
deleted file mode 100644
index b3020e0a..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x9/DHValidationParms.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERSequence;
-
-public class DHValidationParms extends ASN1Object
-{
- private DERBitString seed;
- private ASN1Integer pgenCounter;
-
- public static DHValidationParms getInstance(ASN1TaggedObject obj, boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static DHValidationParms getInstance(Object obj)
- {
- if (obj instanceof DHValidationParms)
- {
- return (DHValidationParms)obj;
- }
- else if (obj != null)
- {
- return new DHValidationParms(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public DHValidationParms(DERBitString seed, ASN1Integer pgenCounter)
- {
- if (seed == null)
- {
- throw new IllegalArgumentException("'seed' cannot be null");
- }
- if (pgenCounter == null)
- {
- throw new IllegalArgumentException("'pgenCounter' cannot be null");
- }
-
- this.seed = seed;
- this.pgenCounter = pgenCounter;
- }
-
- private DHValidationParms(ASN1Sequence seq)
- {
- if (seq.size() != 2)
- {
- throw new IllegalArgumentException("Bad sequence size: " + seq.size());
- }
-
- this.seed = DERBitString.getInstance(seq.getObjectAt(0));
- this.pgenCounter = ASN1Integer.getInstance(seq.getObjectAt(1));
- }
-
- public DERBitString getSeed()
- {
- return this.seed;
- }
-
- public ASN1Integer getPgenCounter()
- {
- return this.pgenCounter;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- v.add(this.seed);
- v.add(this.pgenCounter);
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x9/ECNamedCurveTable.java b/core/src/main/java/org/bouncycastle/asn1/x9/ECNamedCurveTable.java
deleted file mode 100644
index 2206a331..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x9/ECNamedCurveTable.java
+++ /dev/null
@@ -1,128 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-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;
-
-/**
- * A general class that reads all X9.62 style EC curve tables.
- */
-public class ECNamedCurveTable
-{
- /**
- * return a X9ECParameters object representing the passed in named
- * curve. The routine returns null if the curve is not present.
- *
- * @param name the name of the curve requested
- * @return an X9ECParameters object or null if the curve is not available.
- */
- public static X9ECParameters getByName(
- String name)
- {
- X9ECParameters ecP = X962NamedCurves.getByName(name);
-
- if (ecP == null)
- {
- ecP = SECNamedCurves.getByName(name);
- }
-
- if (ecP == null)
- {
- ecP = TeleTrusTNamedCurves.getByName(name);
- }
-
- if (ecP == null)
- {
- ecP = NISTNamedCurves.getByName(name);
- }
-
- return ecP;
- }
-
- /**
- * return the object identifier signified by the passed in name. Null
- * if there is no object identifier associated with name.
- *
- * @return the object identifier associated with name, if present.
- */
- public static ASN1ObjectIdentifier getOID(
- String name)
- {
- ASN1ObjectIdentifier oid = X962NamedCurves.getOID(name);
-
- if (oid == null)
- {
- oid = SECNamedCurves.getOID(name);
- }
-
- if (oid == null)
- {
- oid = TeleTrusTNamedCurves.getOID(name);
- }
-
- if (oid == null)
- {
- oid = NISTNamedCurves.getOID(name);
- }
-
- return oid;
- }
-
- /**
- * return a X9ECParameters object representing the passed in named
- * curve.
- *
- * @param oid the object id of the curve requested
- * @return an X9ECParameters object or null if the curve is not available.
- */
- public static X9ECParameters getByOID(
- ASN1ObjectIdentifier oid)
- {
- X9ECParameters ecP = X962NamedCurves.getByOID(oid);
-
- if (ecP == null)
- {
- ecP = SECNamedCurves.getByOID(oid);
- }
-
- if (ecP == null)
- {
- ecP = TeleTrusTNamedCurves.getByOID(oid);
- }
-
- // NOTE: All the NIST curves are currently from SEC, so no point in redundant OID lookup
-
- return ecP;
- }
-
- /**
- * return an enumeration of the names of the available curves.
- *
- * @return an enumeration of the names of the available curves.
- */
- 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());
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x9/KeySpecificInfo.java b/core/src/main/java/org/bouncycastle/asn1/x9/KeySpecificInfo.java
deleted file mode 100644
index 092716fe..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x9/KeySpecificInfo.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * ASN.1 def for Diffie-Hellman key exchange KeySpecificInfo structure. See
- * RFC 2631, or X9.42, for further details.
- */
-public class KeySpecificInfo
- extends ASN1Object
-{
- private ASN1ObjectIdentifier algorithm;
- private ASN1OctetString counter;
-
- public KeySpecificInfo(
- ASN1ObjectIdentifier algorithm,
- ASN1OctetString counter)
- {
- this.algorithm = algorithm;
- this.counter = counter;
- }
-
- public KeySpecificInfo(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- algorithm = (ASN1ObjectIdentifier)e.nextElement();
- counter = (ASN1OctetString)e.nextElement();
- }
-
- public ASN1ObjectIdentifier getAlgorithm()
- {
- return algorithm;
- }
-
- public ASN1OctetString getCounter()
- {
- return counter;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * KeySpecificInfo ::= SEQUENCE {
- * algorithm OBJECT IDENTIFIER,
- * counter OCTET STRING SIZE (4..4)
- * }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(algorithm);
- v.add(counter);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x9/OtherInfo.java b/core/src/main/java/org/bouncycastle/asn1/x9/OtherInfo.java
deleted file mode 100644
index 0959244a..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x9/OtherInfo.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * ANS.1 def for Diffie-Hellman key exchange OtherInfo structure. See
- * RFC 2631, or X9.42, for further details.
- */
-public class OtherInfo
- extends ASN1Object
-{
- private KeySpecificInfo keyInfo;
- private ASN1OctetString partyAInfo;
- private ASN1OctetString suppPubInfo;
-
- public OtherInfo(
- KeySpecificInfo keyInfo,
- ASN1OctetString partyAInfo,
- ASN1OctetString suppPubInfo)
- {
- this.keyInfo = keyInfo;
- this.partyAInfo = partyAInfo;
- this.suppPubInfo = suppPubInfo;
- }
-
- public OtherInfo(
- ASN1Sequence seq)
- {
- Enumeration e = seq.getObjects();
-
- keyInfo = new KeySpecificInfo((ASN1Sequence)e.nextElement());
-
- while (e.hasMoreElements())
- {
- DERTaggedObject o = (DERTaggedObject)e.nextElement();
-
- if (o.getTagNo() == 0)
- {
- partyAInfo = (ASN1OctetString)o.getObject();
- }
- else if (o.getTagNo() == 2)
- {
- suppPubInfo = (ASN1OctetString)o.getObject();
- }
- }
- }
-
- public KeySpecificInfo getKeyInfo()
- {
- return keyInfo;
- }
-
- public ASN1OctetString getPartyAInfo()
- {
- return partyAInfo;
- }
-
- public ASN1OctetString getSuppPubInfo()
- {
- return suppPubInfo;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * OtherInfo ::= SEQUENCE {
- * keyInfo KeySpecificInfo,
- * partyAInfo [0] OCTET STRING OPTIONAL,
- * suppPubInfo [2] OCTET STRING
- * }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(keyInfo);
-
- if (partyAInfo != null)
- {
- v.add(new DERTaggedObject(0, partyAInfo));
- }
-
- v.add(new DERTaggedObject(2, suppPubInfo));
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x9/X962NamedCurves.java b/core/src/main/java/org/bouncycastle/asn1/x9/X962NamedCurves.java
deleted file mode 100644
index 25312feb..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x9/X962NamedCurves.java
+++ /dev/null
@@ -1,642 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-import java.util.Hashtable;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.util.Strings;
-import org.bouncycastle.util.encoders.Hex;
-
-
-/**
- * table of the current named curves defined in X.962 EC-DSA.
- */
-public class X962NamedCurves
-{
- static X9ECParametersHolder prime192v1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger n = new BigInteger("ffffffffffffffffffffffff99def836146bc9b1b4d22831", 16);
- BigInteger h = BigInteger.valueOf(1);
-
- ECCurve cFp192v1 = new ECCurve.Fp(
- new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
- new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
- new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16),
- n, h);
-
- return new X9ECParameters(
- cFp192v1,
- cFp192v1.decodePoint(
- Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")),
- n, h,
- Hex.decode("3045AE6FC8422f64ED579528D38120EAE12196D5"));
- }
- };
-
- static X9ECParametersHolder prime192v2 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger n = new BigInteger("fffffffffffffffffffffffe5fb1a724dc80418648d8dd31", 16);
- BigInteger h = BigInteger.valueOf(1);
-
- ECCurve cFp192v2 = new ECCurve.Fp(
- new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
- new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
- new BigInteger("cc22d6dfb95c6b25e49c0d6364a4e5980c393aa21668d953", 16),
- n, h);
-
- return new X9ECParameters(
- cFp192v2,
- cFp192v2.decodePoint(
- Hex.decode("03eea2bae7e1497842f2de7769cfe9c989c072ad696f48034a")),
- n, h,
- Hex.decode("31a92ee2029fd10d901b113e990710f0d21ac6b6"));
- }
- };
-
- static X9ECParametersHolder prime192v3 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger n = new BigInteger("ffffffffffffffffffffffff7a62d031c83f4294f640ec13", 16);
- BigInteger h = BigInteger.valueOf(1);
-
- ECCurve cFp192v3 = new ECCurve.Fp(
- new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
- new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
- new BigInteger("22123dc2395a05caa7423daeccc94760a7d462256bd56916", 16),
- n, h);
-
- return new X9ECParameters(
- cFp192v3,
- cFp192v3.decodePoint(
- Hex.decode("027d29778100c65a1da1783716588dce2b8b4aee8e228f1896")),
- n, h,
- Hex.decode("c469684435deb378c4b65ca9591e2a5763059a2e"));
- }
- };
-
- static X9ECParametersHolder prime239v1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger n = new BigInteger("7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b", 16);
- BigInteger h = BigInteger.valueOf(1);
-
- ECCurve cFp239v1 = new ECCurve.Fp(
- new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
- new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
- new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16),
- n, h);
-
- return new X9ECParameters(
- cFp239v1,
- cFp239v1.decodePoint(
- Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")),
- n, h,
- Hex.decode("e43bb460f0b80cc0c0b075798e948060f8321b7d"));
- }
- };
-
- static X9ECParametersHolder prime239v2 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger n = new BigInteger("7fffffffffffffffffffffff800000cfa7e8594377d414c03821bc582063", 16);
- BigInteger h = BigInteger.valueOf(1);
-
- ECCurve cFp239v2 = new ECCurve.Fp(
- new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
- new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
- new BigInteger("617fab6832576cbbfed50d99f0249c3fee58b94ba0038c7ae84c8c832f2c", 16),
- n, h);
-
- return new X9ECParameters(
- cFp239v2,
- cFp239v2.decodePoint(
- Hex.decode("0238af09d98727705120c921bb5e9e26296a3cdcf2f35757a0eafd87b830e7")),
- n, h,
- Hex.decode("e8b4011604095303ca3b8099982be09fcb9ae616"));
- }
- };
-
- static X9ECParametersHolder prime239v3 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger n = new BigInteger("7fffffffffffffffffffffff7fffff975deb41b3a6057c3c432146526551", 16);
- BigInteger h = BigInteger.valueOf(1);
-
- ECCurve cFp239v3 = new ECCurve.Fp(
- new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
- new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
- new BigInteger("255705fa2a306654b1f4cb03d6a750a30c250102d4988717d9ba15ab6d3e", 16),
- n, h);
-
- return new X9ECParameters(
- cFp239v3,
- cFp239v3.decodePoint(
- Hex.decode("036768ae8e18bb92cfcf005c949aa2c6d94853d0e660bbf854b1c9505fe95a")),
- n, h,
- Hex.decode("7d7374168ffe3471b60a857686a19475d3bfa2ff"));
- }
- };
-
- static X9ECParametersHolder prime256v1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger n = new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16);
- BigInteger h = BigInteger.valueOf(1);
-
- ECCurve cFp256v1 = new ECCurve.Fp(
- new BigInteger("115792089210356248762697446949407573530086143415290314195533631308867097853951"),
- new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16),
- new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16),
- n, h);
-
- return new X9ECParameters(
- cFp256v1,
- cFp256v1.decodePoint(
- Hex.decode("036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296")),
- n, h,
- Hex.decode("c49d360886e704936a6678e1139d26b7819f7e90"));
- }
- };
-
- /*
- * F2m Curves
- */
- static X9ECParametersHolder c2pnb163v1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger c2m163v1n = new BigInteger("0400000000000000000001E60FC8821CC74DAEAFC1", 16);
- BigInteger c2m163v1h = BigInteger.valueOf(2);
-
- ECCurve c2m163v1 = new ECCurve.F2m(
- 163,
- 1, 2, 8,
- new BigInteger("072546B5435234A422E0789675F432C89435DE5242", 16),
- new BigInteger("00C9517D06D5240D3CFF38C74B20B6CD4D6F9DD4D9", 16),
- c2m163v1n, c2m163v1h);
-
- return new X9ECParameters(
- c2m163v1,
- c2m163v1.decodePoint(
- Hex.decode("0307AF69989546103D79329FCC3D74880F33BBE803CB")),
- c2m163v1n, c2m163v1h,
- Hex.decode("D2C0FB15760860DEF1EEF4D696E6768756151754"));
- }
- };
-
- static X9ECParametersHolder c2pnb163v2 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger c2m163v2n = new BigInteger("03FFFFFFFFFFFFFFFFFFFDF64DE1151ADBB78F10A7", 16);
- BigInteger c2m163v2h = BigInteger.valueOf(2);
-
- ECCurve c2m163v2 = new ECCurve.F2m(
- 163,
- 1, 2, 8,
- new BigInteger("0108B39E77C4B108BED981ED0E890E117C511CF072", 16),
- new BigInteger("0667ACEB38AF4E488C407433FFAE4F1C811638DF20", 16),
- c2m163v2n, c2m163v2h);
-
- return new X9ECParameters(
- c2m163v2,
- c2m163v2.decodePoint(
- Hex.decode("030024266E4EB5106D0A964D92C4860E2671DB9B6CC5")),
- c2m163v2n, c2m163v2h,
- null);
- }
- };
-
- static X9ECParametersHolder c2pnb163v3 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger c2m163v3n = new BigInteger("03FFFFFFFFFFFFFFFFFFFE1AEE140F110AFF961309", 16);
- BigInteger c2m163v3h = BigInteger.valueOf(2);
-
- ECCurve c2m163v3 = new ECCurve.F2m(
- 163,
- 1, 2, 8,
- new BigInteger("07A526C63D3E25A256A007699F5447E32AE456B50E", 16),
- new BigInteger("03F7061798EB99E238FD6F1BF95B48FEEB4854252B", 16),
- c2m163v3n, c2m163v3h);
-
- return new X9ECParameters(
- c2m163v3,
- c2m163v3.decodePoint(
- Hex.decode("0202F9F87B7C574D0BDECF8A22E6524775F98CDEBDCB")),
- c2m163v3n, c2m163v3h,
- null);
- }
- };
-
- static X9ECParametersHolder c2pnb176w1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger c2m176w1n = new BigInteger("010092537397ECA4F6145799D62B0A19CE06FE26AD", 16);
- BigInteger c2m176w1h = BigInteger.valueOf(0xFF6E);
-
- ECCurve c2m176w1 = new ECCurve.F2m(
- 176,
- 1, 2, 43,
- new BigInteger("00E4E6DB2995065C407D9D39B8D0967B96704BA8E9C90B", 16),
- new BigInteger("005DDA470ABE6414DE8EC133AE28E9BBD7FCEC0AE0FFF2", 16),
- c2m176w1n, c2m176w1h);
-
- return new X9ECParameters(
- c2m176w1,
- c2m176w1.decodePoint(
- Hex.decode("038D16C2866798B600F9F08BB4A8E860F3298CE04A5798")),
- c2m176w1n, c2m176w1h,
- null);
- }
- };
-
- static X9ECParametersHolder c2tnb191v1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger c2m191v1n = new BigInteger("40000000000000000000000004A20E90C39067C893BBB9A5", 16);
- BigInteger c2m191v1h = BigInteger.valueOf(2);
-
- ECCurve c2m191v1 = new ECCurve.F2m(
- 191,
- 9,
- new BigInteger("2866537B676752636A68F56554E12640276B649EF7526267", 16),
- new BigInteger("2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC", 16),
- c2m191v1n, c2m191v1h);
-
- return new X9ECParameters(
- c2m191v1,
- c2m191v1.decodePoint(
- Hex.decode("0236B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D")),
- c2m191v1n, c2m191v1h,
- Hex.decode("4E13CA542744D696E67687561517552F279A8C84"));
- }
- };
-
- static X9ECParametersHolder c2tnb191v2 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger c2m191v2n = new BigInteger("20000000000000000000000050508CB89F652824E06B8173", 16);
- BigInteger c2m191v2h = BigInteger.valueOf(4);
-
- ECCurve c2m191v2 = new ECCurve.F2m(
- 191,
- 9,
- new BigInteger("401028774D7777C7B7666D1366EA432071274F89FF01E718", 16),
- new BigInteger("0620048D28BCBD03B6249C99182B7C8CD19700C362C46A01", 16),
- c2m191v2n, c2m191v2h);
-
- return new X9ECParameters(
- c2m191v2,
- c2m191v2.decodePoint(
- Hex.decode("023809B2B7CC1B28CC5A87926AAD83FD28789E81E2C9E3BF10")),
- c2m191v2n, c2m191v2h,
- null);
- }
- };
-
- static X9ECParametersHolder c2tnb191v3 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger c2m191v3n = new BigInteger("155555555555555555555555610C0B196812BFB6288A3EA3", 16);
- BigInteger c2m191v3h = BigInteger.valueOf(6);
-
- ECCurve c2m191v3 = new ECCurve.F2m(
- 191,
- 9,
- new BigInteger("6C01074756099122221056911C77D77E77A777E7E7E77FCB", 16),
- new BigInteger("71FE1AF926CF847989EFEF8DB459F66394D90F32AD3F15E8", 16),
- c2m191v3n, c2m191v3h);
-
- return new X9ECParameters(
- c2m191v3,
- c2m191v3.decodePoint(
- Hex.decode("03375D4CE24FDE434489DE8746E71786015009E66E38A926DD")),
- c2m191v3n, c2m191v3h,
- null);
- }
- };
-
- static X9ECParametersHolder c2pnb208w1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger c2m208w1n = new BigInteger("0101BAF95C9723C57B6C21DA2EFF2D5ED588BDD5717E212F9D", 16);
- BigInteger c2m208w1h = BigInteger.valueOf(0xFE48);
-
- ECCurve c2m208w1 = new ECCurve.F2m(
- 208,
- 1, 2, 83,
- new BigInteger("0", 16),
- new BigInteger("00C8619ED45A62E6212E1160349E2BFA844439FAFC2A3FD1638F9E", 16),
- c2m208w1n, c2m208w1h);
-
- return new X9ECParameters(
- c2m208w1,
- c2m208w1.decodePoint(
- Hex.decode("0289FDFBE4ABE193DF9559ECF07AC0CE78554E2784EB8C1ED1A57A")),
- c2m208w1n, c2m208w1h,
- null);
- }
- };
-
- static X9ECParametersHolder c2tnb239v1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger c2m239v1n = new BigInteger("2000000000000000000000000000000F4D42FFE1492A4993F1CAD666E447", 16);
- BigInteger c2m239v1h = BigInteger.valueOf(4);
-
- ECCurve c2m239v1 = new ECCurve.F2m(
- 239,
- 36,
- new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16),
- new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16),
- c2m239v1n, c2m239v1h);
-
- return new X9ECParameters(
- c2m239v1,
- c2m239v1.decodePoint(
- Hex.decode("0257927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D")),
- c2m239v1n, c2m239v1h,
- null);
- }
- };
-
- static X9ECParametersHolder c2tnb239v2 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger c2m239v2n = new BigInteger("1555555555555555555555555555553C6F2885259C31E3FCDF154624522D", 16);
- BigInteger c2m239v2h = BigInteger.valueOf(6);
-
- ECCurve c2m239v2 = new ECCurve.F2m(
- 239,
- 36,
- new BigInteger("4230017757A767FAE42398569B746325D45313AF0766266479B75654E65F", 16),
- new BigInteger("5037EA654196CFF0CD82B2C14A2FCF2E3FF8775285B545722F03EACDB74B", 16),
- c2m239v2n, c2m239v2h);
-
- return new X9ECParameters(
- c2m239v2,
- c2m239v2.decodePoint(
- Hex.decode("0228F9D04E900069C8DC47A08534FE76D2B900B7D7EF31F5709F200C4CA205")),
- c2m239v2n, c2m239v2h,
- null);
- }
- };
-
- static X9ECParametersHolder c2tnb239v3 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger c2m239v3n = new BigInteger("0CCCCCCCCCCCCCCCCCCCCCCCCCCCCCAC4912D2D9DF903EF9888B8A0E4CFF", 16);
- BigInteger c2m239v3h = BigInteger.valueOf(10);
-
- ECCurve c2m239v3 = new ECCurve.F2m(
- 239,
- 36,
- new BigInteger("01238774666A67766D6676F778E676B66999176666E687666D8766C66A9F", 16),
- new BigInteger("6A941977BA9F6A435199ACFC51067ED587F519C5ECB541B8E44111DE1D40", 16),
- c2m239v3n, c2m239v3h);
-
- return new X9ECParameters(
- c2m239v3,
- c2m239v3.decodePoint(
- Hex.decode("0370F6E9D04D289C4E89913CE3530BFDE903977D42B146D539BF1BDE4E9C92")),
- c2m239v3n, c2m239v3h,
- null);
- }
- };
-
- static X9ECParametersHolder c2pnb272w1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger c2m272w1n = new BigInteger("0100FAF51354E0E39E4892DF6E319C72C8161603FA45AA7B998A167B8F1E629521", 16);
- BigInteger c2m272w1h = BigInteger.valueOf(0xFF06);
-
- ECCurve c2m272w1 = new ECCurve.F2m(
- 272,
- 1, 3, 56,
- new BigInteger("0091A091F03B5FBA4AB2CCF49C4EDD220FB028712D42BE752B2C40094DBACDB586FB20", 16),
- new BigInteger("7167EFC92BB2E3CE7C8AAAFF34E12A9C557003D7C73A6FAF003F99F6CC8482E540F7", 16),
- c2m272w1n, c2m272w1h);
-
- return new X9ECParameters(
- c2m272w1,
- c2m272w1.decodePoint(
- Hex.decode("026108BABB2CEEBCF787058A056CBE0CFE622D7723A289E08A07AE13EF0D10D171DD8D")),
- c2m272w1n, c2m272w1h,
- null);
- }
- };
-
- static X9ECParametersHolder c2pnb304w1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger c2m304w1n = new BigInteger("0101D556572AABAC800101D556572AABAC8001022D5C91DD173F8FB561DA6899164443051D", 16);
- BigInteger c2m304w1h = BigInteger.valueOf(0xFE2E);
-
- ECCurve c2m304w1 = new ECCurve.F2m(
- 304,
- 1, 2, 11,
- new BigInteger("00FD0D693149A118F651E6DCE6802085377E5F882D1B510B44160074C1288078365A0396C8E681", 16),
- new BigInteger("00BDDB97E555A50A908E43B01C798EA5DAA6788F1EA2794EFCF57166B8C14039601E55827340BE", 16),
- c2m304w1n, c2m304w1h);
-
- return new X9ECParameters(
- c2m304w1,
- c2m304w1.decodePoint(
- Hex.decode("02197B07845E9BE2D96ADB0F5F3C7F2CFFBD7A3EB8B6FEC35C7FD67F26DDF6285A644F740A2614")),
- c2m304w1n, c2m304w1h,
- null);
- }
- };
-
- static X9ECParametersHolder c2tnb359v1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger c2m359v1n = new BigInteger("01AF286BCA1AF286BCA1AF286BCA1AF286BCA1AF286BC9FB8F6B85C556892C20A7EB964FE7719E74F490758D3B", 16);
- BigInteger c2m359v1h = BigInteger.valueOf(0x4C);
-
- ECCurve c2m359v1 = new ECCurve.F2m(
- 359,
- 68,
- new BigInteger("5667676A654B20754F356EA92017D946567C46675556F19556A04616B567D223A5E05656FB549016A96656A557", 16),
- new BigInteger("2472E2D0197C49363F1FE7F5B6DB075D52B6947D135D8CA445805D39BC345626089687742B6329E70680231988", 16),
- c2m359v1n, c2m359v1h);
-
- return new X9ECParameters(
- c2m359v1,
- c2m359v1.decodePoint(
- Hex.decode("033C258EF3047767E7EDE0F1FDAA79DAEE3841366A132E163ACED4ED2401DF9C6BDCDE98E8E707C07A2239B1B097")),
- c2m359v1n, c2m359v1h,
- null);
- }
- };
-
- static X9ECParametersHolder c2pnb368w1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger c2m368w1n = new BigInteger("010090512DA9AF72B08349D98A5DD4C7B0532ECA51CE03E2D10F3B7AC579BD87E909AE40A6F131E9CFCE5BD967", 16);
- BigInteger c2m368w1h = BigInteger.valueOf(0xFF70);
-
- ECCurve c2m368w1 = new ECCurve.F2m(
- 368,
- 1, 2, 85,
- new BigInteger("00E0D2EE25095206F5E2A4F9ED229F1F256E79A0E2B455970D8D0D865BD94778C576D62F0AB7519CCD2A1A906AE30D", 16),
- new BigInteger("00FC1217D4320A90452C760A58EDCD30C8DD069B3C34453837A34ED50CB54917E1C2112D84D164F444F8F74786046A", 16),
- c2m368w1n, c2m368w1h);
-
- return new X9ECParameters(
- c2m368w1,
- c2m368w1.decodePoint(
- Hex.decode("021085E2755381DCCCE3C1557AFA10C2F0C0C2825646C5B34A394CBCFA8BC16B22E7E789E927BE216F02E1FB136A5F")),
- c2m368w1n, c2m368w1h,
- null);
- }
- };
-
- static X9ECParametersHolder c2tnb431r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- BigInteger c2m431r1n = new BigInteger("0340340340340340340340340340340340340340340340340340340323C313FAB50589703B5EC68D3587FEC60D161CC149C1AD4A91", 16);
- BigInteger c2m431r1h = BigInteger.valueOf(0x2760);
-
- ECCurve c2m431r1 = new ECCurve.F2m(
- 431,
- 120,
- new BigInteger("1A827EF00DD6FC0E234CAF046C6A5D8A85395B236CC4AD2CF32A0CADBDC9DDF620B0EB9906D0957F6C6FEACD615468DF104DE296CD8F", 16),
- new BigInteger("10D9B4A3D9047D8B154359ABFB1B7F5485B04CEB868237DDC9DEDA982A679A5A919B626D4E50A8DD731B107A9962381FB5D807BF2618", 16),
- c2m431r1n, c2m431r1h);
-
- return new X9ECParameters(
- c2m431r1,
- c2m431r1.decodePoint(
- Hex.decode("02120FC05D3C67A99DE161D2F4092622FECA701BE4F50F4758714E8A87BBF2A658EF8C21E7C5EFE965361F6C2999C0C247B0DBD70CE6B7")),
- c2m431r1n, c2m431r1h,
- null);
- }
- };
-
- static final Hashtable objIds = new Hashtable();
- static final Hashtable curves = new Hashtable();
- static final Hashtable names = new Hashtable();
-
- static void defineCurve(String name, ASN1ObjectIdentifier oid, X9ECParametersHolder holder)
- {
- objIds.put(name, oid);
- names.put(oid, name);
- curves.put(oid, holder);
- }
-
- static
- {
- defineCurve("prime192v1", X9ObjectIdentifiers.prime192v1, prime192v1);
- defineCurve("prime192v2", X9ObjectIdentifiers.prime192v2, prime192v2);
- defineCurve("prime192v3", X9ObjectIdentifiers.prime192v3, prime192v3);
- defineCurve("prime239v1", X9ObjectIdentifiers.prime239v1, prime239v1);
- defineCurve("prime239v2", X9ObjectIdentifiers.prime239v2, prime239v2);
- defineCurve("prime239v3", X9ObjectIdentifiers.prime239v3, prime239v3);
- defineCurve("prime256v1", X9ObjectIdentifiers.prime256v1, prime256v1);
- defineCurve("c2pnb163v1", X9ObjectIdentifiers.c2pnb163v1, c2pnb163v1);
- defineCurve("c2pnb163v2", X9ObjectIdentifiers.c2pnb163v2, c2pnb163v2);
- defineCurve("c2pnb163v3", X9ObjectIdentifiers.c2pnb163v3, c2pnb163v3);
- defineCurve("c2pnb176w1", X9ObjectIdentifiers.c2pnb176w1, c2pnb176w1);
- defineCurve("c2tnb191v1", X9ObjectIdentifiers.c2tnb191v1, c2tnb191v1);
- defineCurve("c2tnb191v2", X9ObjectIdentifiers.c2tnb191v2, c2tnb191v2);
- defineCurve("c2tnb191v3", X9ObjectIdentifiers.c2tnb191v3, c2tnb191v3);
- defineCurve("c2pnb208w1", X9ObjectIdentifiers.c2pnb208w1, c2pnb208w1);
- defineCurve("c2tnb239v1", X9ObjectIdentifiers.c2tnb239v1, c2tnb239v1);
- defineCurve("c2tnb239v2", X9ObjectIdentifiers.c2tnb239v2, c2tnb239v2);
- defineCurve("c2tnb239v3", X9ObjectIdentifiers.c2tnb239v3, c2tnb239v3);
- defineCurve("c2pnb272w1", X9ObjectIdentifiers.c2pnb272w1, c2pnb272w1);
- defineCurve("c2pnb304w1", X9ObjectIdentifiers.c2pnb304w1, c2pnb304w1);
- defineCurve("c2tnb359v1", X9ObjectIdentifiers.c2tnb359v1, c2tnb359v1);
- defineCurve("c2pnb368w1", X9ObjectIdentifiers.c2pnb368w1, c2pnb368w1);
- defineCurve("c2tnb431r1", X9ObjectIdentifiers.c2tnb431r1, c2tnb431r1);
- }
-
- public static X9ECParameters getByName(
- String name)
- {
- ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)objIds.get(Strings.toLowerCase(name));
-
- if (oid != null)
- {
- return getByOID(oid);
- }
-
- return null;
- }
-
- /**
- * return the X9ECParameters object for the named curve represented by
- * the passed in object identifier. Null if the curve isn't present.
- *
- * @param oid an object identifier representing a named curve, if present.
- */
- public static X9ECParameters getByOID(
- ASN1ObjectIdentifier oid)
- {
- X9ECParametersHolder holder = (X9ECParametersHolder)curves.get(oid);
-
- if (holder != null)
- {
- return holder.getParameters();
- }
-
- return null;
- }
-
- /**
- * return the object identifier signified by the passed in name. Null
- * if there is no object identifier associated with name.
- *
- * @return the object identifier associated with name, if present.
- */
- public static ASN1ObjectIdentifier getOID(
- String name)
- {
- return (ASN1ObjectIdentifier)objIds.get(Strings.toLowerCase(name));
- }
-
- /**
- * return the named curve name represented by the given object identifier.
- */
- public static String getName(
- ASN1ObjectIdentifier oid)
- {
- return (String)names.get(oid);
- }
-
- /**
- * returns an enumeration containing the name strings for curves
- * contained in this structure.
- */
- public static Enumeration getNames()
- {
- return objIds.keys();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x9/X962Parameters.java b/core/src/main/java/org/bouncycastle/asn1/x9/X962Parameters.java
deleted file mode 100644
index a4348dec..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x9/X962Parameters.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Null;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-
-public class X962Parameters
- extends ASN1Object
- implements ASN1Choice
-{
- private ASN1Primitive params = null;
-
- public static X962Parameters getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof X962Parameters)
- {
- return (X962Parameters)obj;
- }
-
- if (obj instanceof ASN1Primitive)
- {
- return new X962Parameters((ASN1Primitive)obj);
- }
-
- throw new IllegalArgumentException("unknown object in getInstance()");
- }
-
- public static X962Parameters getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject()); // must be explicitly tagged
- }
-
- public X962Parameters(
- X9ECParameters ecParameters)
- {
- this.params = ecParameters.toASN1Primitive();
- }
-
- public X962Parameters(
- ASN1ObjectIdentifier namedCurve)
- {
- this.params = namedCurve;
- }
-
- public X962Parameters(
- ASN1Primitive obj)
- {
- this.params = obj;
- }
-
- public boolean isNamedCurve()
- {
- return (params instanceof ASN1ObjectIdentifier);
- }
-
- public boolean isImplicitlyCA()
- {
- return (params instanceof ASN1Null);
- }
-
- public ASN1Primitive getParameters()
- {
- return params;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * Parameters ::= CHOICE {
- * ecParameters ECParameters,
- * namedCurve CURVES.&amp;id({CurveNames}),
- * implicitlyCA NULL
- * }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- return (ASN1Primitive)params;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x9/X9Curve.java b/core/src/main/java/org/bouncycastle/asn1/x9/X9Curve.java
deleted file mode 100644
index f1bac2b8..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x9/X9Curve.java
+++ /dev/null
@@ -1,163 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.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.DERSequence;
-import org.bouncycastle.math.ec.ECAlgorithms;
-import org.bouncycastle.math.ec.ECCurve;
-
-/**
- * ASN.1 def for Elliptic-Curve Curve structure. See
- * X9.62, for further details.
- */
-public class X9Curve
- extends ASN1Object
- implements X9ObjectIdentifiers
-{
- private ECCurve curve;
- private byte[] seed;
- private ASN1ObjectIdentifier fieldIdentifier = null;
-
- public X9Curve(
- ECCurve curve)
- {
- this.curve = curve;
- this.seed = null;
- setFieldIdentifier();
- }
-
- public X9Curve(
- ECCurve curve,
- byte[] seed)
- {
- this.curve = curve;
- this.seed = seed;
- setFieldIdentifier();
- }
-
- public X9Curve(
- X9FieldID fieldID,
- ASN1Sequence seq)
- {
- // TODO Is it possible to get the order(n) and cofactor(h) too?
-
- fieldIdentifier = fieldID.getIdentifier();
- if (fieldIdentifier.equals(prime_field))
- {
- BigInteger p = ((ASN1Integer)fieldID.getParameters()).getValue();
- X9FieldElement x9A = new X9FieldElement(p, (ASN1OctetString)seq.getObjectAt(0));
- X9FieldElement x9B = new X9FieldElement(p, (ASN1OctetString)seq.getObjectAt(1));
- curve = new ECCurve.Fp(p, x9A.getValue().toBigInteger(), x9B.getValue().toBigInteger());
- }
- else if (fieldIdentifier.equals(characteristic_two_field))
- {
- // Characteristic two field
- ASN1Sequence parameters = ASN1Sequence.getInstance(fieldID.getParameters());
- int m = ((ASN1Integer)parameters.getObjectAt(0)).getValue().
- intValue();
- ASN1ObjectIdentifier representation
- = (ASN1ObjectIdentifier)parameters.getObjectAt(1);
-
- int k1 = 0;
- int k2 = 0;
- int k3 = 0;
-
- if (representation.equals(tpBasis))
- {
- // Trinomial basis representation
- k1 = ASN1Integer.getInstance(parameters.getObjectAt(2)).getValue().intValue();
- }
- else if (representation.equals(ppBasis))
- {
- // Pentanomial basis representation
- ASN1Sequence pentanomial = ASN1Sequence.getInstance(parameters.getObjectAt(2));
- k1 = ASN1Integer.getInstance(pentanomial.getObjectAt(0)).getValue().intValue();
- k2 = ASN1Integer.getInstance(pentanomial.getObjectAt(1)).getValue().intValue();
- k3 = ASN1Integer.getInstance(pentanomial.getObjectAt(2)).getValue().intValue();
- }
- else
- {
- throw new IllegalArgumentException("This type of EC basis is not implemented");
- }
- X9FieldElement x9A = new X9FieldElement(m, k1, k2, k3, (ASN1OctetString)seq.getObjectAt(0));
- X9FieldElement x9B = new X9FieldElement(m, k1, k2, k3, (ASN1OctetString)seq.getObjectAt(1));
- curve = new ECCurve.F2m(m, k1, k2, k3, x9A.getValue().toBigInteger(), x9B.getValue().toBigInteger());
- }
- else
- {
- throw new IllegalArgumentException("This type of ECCurve is not implemented");
- }
-
- if (seq.size() == 3)
- {
- seed = ((DERBitString)seq.getObjectAt(2)).getBytes();
- }
- }
-
- private void setFieldIdentifier()
- {
- if (ECAlgorithms.isFpCurve(curve))
- {
- fieldIdentifier = prime_field;
- }
- else if (ECAlgorithms.isF2mCurve(curve))
- {
- fieldIdentifier = characteristic_two_field;
- }
- else
- {
- throw new IllegalArgumentException("This type of ECCurve is not implemented");
- }
- }
-
- public ECCurve getCurve()
- {
- return curve;
- }
-
- public byte[] getSeed()
- {
- return seed;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * Curve ::= SEQUENCE {
- * a FieldElement,
- * b FieldElement,
- * seed BIT STRING OPTIONAL
- * }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (fieldIdentifier.equals(prime_field))
- {
- v.add(new X9FieldElement(curve.getA()).toASN1Primitive());
- v.add(new X9FieldElement(curve.getB()).toASN1Primitive());
- }
- else if (fieldIdentifier.equals(characteristic_two_field))
- {
- v.add(new X9FieldElement(curve.getA()).toASN1Primitive());
- v.add(new X9FieldElement(curve.getB()).toASN1Primitive());
- }
-
- if (seed != null)
- {
- v.add(new DERBitString(seed));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java b/core/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java
deleted file mode 100644
index 302c1300..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java
+++ /dev/null
@@ -1,200 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.math.ec.ECAlgorithms;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.field.PolynomialExtensionField;
-
-/**
- * ASN.1 def for Elliptic-Curve ECParameters structure. See
- * X9.62, for further details.
- */
-public class X9ECParameters
- extends ASN1Object
- implements X9ObjectIdentifiers
-{
- private static final BigInteger ONE = BigInteger.valueOf(1);
-
- private X9FieldID fieldID;
- private ECCurve curve;
- private ECPoint g;
- private BigInteger n;
- private BigInteger h;
- private byte[] seed;
-
- private X9ECParameters(
- ASN1Sequence seq)
- {
- if (!(seq.getObjectAt(0) instanceof ASN1Integer)
- || !((ASN1Integer)seq.getObjectAt(0)).getValue().equals(ONE))
- {
- throw new IllegalArgumentException("bad version in X9ECParameters");
- }
-
- X9Curve x9c = new X9Curve(
- X9FieldID.getInstance(seq.getObjectAt(1)),
- ASN1Sequence.getInstance(seq.getObjectAt(2)));
-
- this.curve = x9c.getCurve();
- 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();
-
- if (seq.size() == 6)
- {
- this.h = ((ASN1Integer)seq.getObjectAt(5)).getValue();
- }
- }
-
- public static X9ECParameters getInstance(Object obj)
- {
- if (obj instanceof X9ECParameters)
- {
- return (X9ECParameters)obj;
- }
-
- if (obj != null)
- {
- return new X9ECParameters(ASN1Sequence.getInstance(obj));
- }
-
- return null;
- }
-
- public X9ECParameters(
- ECCurve curve,
- ECPoint g,
- BigInteger n)
- {
- this(curve, g, n, ONE, null);
- }
-
- public X9ECParameters(
- ECCurve curve,
- ECPoint g,
- BigInteger n,
- BigInteger h)
- {
- this(curve, g, n, h, null);
- }
-
- public X9ECParameters(
- ECCurve curve,
- ECPoint g,
- BigInteger n,
- BigInteger h,
- byte[] seed)
- {
- this.curve = curve;
- this.g = g.normalize();
- this.n = n;
- this.h = h;
- this.seed = seed;
-
- if (ECAlgorithms.isFpCurve(curve))
- {
- this.fieldID = new X9FieldID(curve.getField().getCharacteristic());
- }
- else if (ECAlgorithms.isF2mCurve(curve))
- {
- PolynomialExtensionField field = (PolynomialExtensionField)curve.getField();
- int[] exponents = field.getMinimalPolynomial().getExponentsPresent();
- if (exponents.length == 3)
- {
- this.fieldID = new X9FieldID(exponents[2], exponents[1]);
- }
- else if (exponents.length == 5)
- {
- this.fieldID = new X9FieldID(exponents[4], exponents[1], exponents[2], exponents[3]);
- }
- else
- {
- throw new IllegalArgumentException("Only trinomial and pentomial curves are supported");
- }
- }
- else
- {
- throw new IllegalArgumentException("'curve' is of an unsupported type");
- }
- }
-
- public ECCurve getCurve()
- {
- return curve;
- }
-
- public ECPoint getG()
- {
- return g;
- }
-
- public BigInteger getN()
- {
- return n;
- }
-
- public BigInteger getH()
- {
- if (h == null)
- {
- return ONE; // TODO - this should be calculated, it will cause issues with custom curves.
- }
-
- return h;
- }
-
- public byte[] getSeed()
- {
- return seed;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * ECParameters ::= SEQUENCE {
- * version INTEGER { ecpVer1(1) } (ecpVer1),
- * fieldID FieldID {{FieldTypes}},
- * curve X9Curve,
- * base X9ECPoint,
- * order INTEGER,
- * cofactor INTEGER OPTIONAL
- * }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(new ASN1Integer(1));
- v.add(fieldID);
- v.add(new X9Curve(curve, seed));
- v.add(new X9ECPoint(g));
- v.add(new ASN1Integer(n));
-
- if (h != null)
- {
- v.add(new ASN1Integer(h));
- }
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x9/X9ECParametersHolder.java b/core/src/main/java/org/bouncycastle/asn1/x9/X9ECParametersHolder.java
deleted file mode 100644
index 47361f89..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x9/X9ECParametersHolder.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-public abstract class X9ECParametersHolder
-{
- private X9ECParameters params;
-
- public X9ECParameters getParameters()
- {
- if (params == null)
- {
- params = createParameters();
- }
-
- return params;
- }
-
- protected abstract X9ECParameters createParameters();
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java b/core/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java
deleted file mode 100644
index cbb91160..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECPoint;
-
-/**
- * class for describing an ECPoint as a DER object.
- */
-public class X9ECPoint
- extends ASN1Object
-{
- ECPoint p;
-
- public X9ECPoint(
- ECPoint p)
- {
- this.p = p.normalize();
- }
-
- public X9ECPoint(
- ECCurve c,
- ASN1OctetString s)
- {
- this.p = c.decodePoint(s.getOctets());
- }
-
- public ECPoint getPoint()
- {
- return p;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * ECPoint ::= OCTET STRING
- * </pre>
- * <p>
- * Octet string produced using ECPoint.getEncoded().
- */
- public ASN1Primitive toASN1Primitive()
- {
- return new DEROctetString(p.getEncoded());
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x9/X9FieldElement.java b/core/src/main/java/org/bouncycastle/asn1/x9/X9FieldElement.java
deleted file mode 100644
index 13fe7721..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x9/X9FieldElement.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.math.ec.ECFieldElement;
-
-/**
- * class for processing an FieldElement as a DER object.
- */
-public class X9FieldElement
- extends ASN1Object
-{
- protected ECFieldElement f;
-
- private static X9IntegerConverter converter = new X9IntegerConverter();
-
- public X9FieldElement(ECFieldElement f)
- {
- this.f = f;
- }
-
- public X9FieldElement(BigInteger p, ASN1OctetString s)
- {
- this(new ECFieldElement.Fp(p, new BigInteger(1, s.getOctets())));
- }
-
- public X9FieldElement(int m, int k1, int k2, int k3, ASN1OctetString s)
- {
- this(new ECFieldElement.F2m(m, k1, k2, k3, new BigInteger(1, s.getOctets())));
- }
-
- public ECFieldElement getValue()
- {
- return f;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * FieldElement ::= OCTET STRING
- * </pre>
- * <p>
- * <ol>
- * <li> if <i>q</i> is an odd prime then the field element is
- * processed as an Integer and converted to an octet string
- * according to x 9.62 4.3.1.</li>
- * <li> if <i>q</i> is 2<sup>m</sup> then the bit string
- * contained in the field element is converted into an octet
- * string with the same ordering padded at the front if necessary.
- * </li>
- * </ol>
- */
- public ASN1Primitive toASN1Primitive()
- {
- int byteCount = converter.getByteLength(f);
- byte[] paddedBigInteger = converter.integerToBytes(f.toBigInteger(), byteCount);
-
- return new DEROctetString(paddedBigInteger);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x9/X9FieldID.java b/core/src/main/java/org/bouncycastle/asn1/x9/X9FieldID.java
deleted file mode 100644
index cb74234e..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x9/X9FieldID.java
+++ /dev/null
@@ -1,148 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * ASN.1 def for Elliptic-Curve Field ID structure. See
- * X9.62, for further details.
- */
-public class X9FieldID
- extends ASN1Object
- implements X9ObjectIdentifiers
-{
- private ASN1ObjectIdentifier id;
- private ASN1Primitive parameters;
-
- /**
- * Constructor for elliptic curves over prime fields
- * <code>F<sub>2</sub></code>.
- * @param primeP The prime <code>p</code> defining the prime field.
- */
- public X9FieldID(BigInteger primeP)
- {
- this.id = prime_field;
- this.parameters = new ASN1Integer(primeP);
- }
-
- /**
- * Constructor for elliptic curves over binary fields
- * <code>F<sub>2<sup>m</sup></sub></code>.
- * @param m The exponent <code>m</code> of
- * <code>F<sub>2<sup>m</sup></sub></code>.
- * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
- * x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.
- */
- public X9FieldID(int m, int k1)
- {
- this(m, k1, 0, 0);
- }
-
- /**
- * Constructor for elliptic curves over binary fields
- * <code>F<sub>2<sup>m</sup></sub></code>.
- * @param m The exponent <code>m</code> of
- * <code>F<sub>2<sup>m</sup></sub></code>.
- * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.
- * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.
- * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>..
- */
- public X9FieldID(int m, int k1, int k2, int k3)
- {
- this.id = characteristic_two_field;
- ASN1EncodableVector fieldIdParams = new ASN1EncodableVector();
- fieldIdParams.add(new ASN1Integer(m));
-
- if (k2 == 0)
- {
- if (k3 != 0)
- {
- throw new IllegalArgumentException("inconsistent k values");
- }
-
- fieldIdParams.add(tpBasis);
- fieldIdParams.add(new ASN1Integer(k1));
- }
- else
- {
- if (k2 <= k1 || k3 <= k2)
- {
- throw new IllegalArgumentException("inconsistent k values");
- }
-
- fieldIdParams.add(ppBasis);
- ASN1EncodableVector pentanomialParams = new ASN1EncodableVector();
- pentanomialParams.add(new ASN1Integer(k1));
- pentanomialParams.add(new ASN1Integer(k2));
- pentanomialParams.add(new ASN1Integer(k3));
- fieldIdParams.add(new DERSequence(pentanomialParams));
- }
-
- this.parameters = new DERSequence(fieldIdParams);
- }
-
- private X9FieldID(
- ASN1Sequence seq)
- {
- 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()
- {
- return id;
- }
-
- public ASN1Primitive getParameters()
- {
- return parameters;
- }
-
- /**
- * Produce a DER encoding of the following structure.
- * <pre>
- * FieldID ::= SEQUENCE {
- * fieldType FIELD-ID.&amp;id({IOSet}),
- * parameters FIELD-ID.&amp;Type({IOSet}{&#64;fieldType})
- * }
- * </pre>
- */
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(this.id);
- v.add(this.parameters);
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x9/X9IntegerConverter.java b/core/src/main/java/org/bouncycastle/asn1/x9/X9IntegerConverter.java
deleted file mode 100644
index 16a803cc..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x9/X9IntegerConverter.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-
-public class X9IntegerConverter
-{
- public int getByteLength(
- ECCurve c)
- {
- return (c.getFieldSize() + 7) / 8;
- }
-
- public int getByteLength(
- ECFieldElement fe)
- {
- return (fe.getFieldSize() + 7) / 8;
- }
-
- public byte[] integerToBytes(
- BigInteger s,
- int qLength)
- {
- byte[] bytes = s.toByteArray();
-
- if (qLength < bytes.length)
- {
- byte[] tmp = new byte[qLength];
-
- System.arraycopy(bytes, bytes.length - tmp.length, tmp, 0, tmp.length);
-
- return tmp;
- }
- else if (qLength > bytes.length)
- {
- byte[] tmp = new byte[qLength];
-
- System.arraycopy(bytes, 0, tmp, tmp.length - bytes.length, bytes.length);
-
- return tmp;
- }
-
- return bytes;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java
deleted file mode 100644
index eabf90ea..00000000
--- a/core/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java
+++ /dev/null
@@ -1,207 +0,0 @@
-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
-{
- /** 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");
-
- /** 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 base
- * <p>
- * OID: 1.2.840.10045.1
- */
- static final ASN1ObjectIdentifier ellipticCurve = ansi_X9_62.branch("3");
-
- /**
- * 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 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
- * <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");
-
- /**
- * <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
- */
- static final ASN1ObjectIdentifier id_dsa_with_sha1 = new ASN1ObjectIdentifier("1.2.840.10040.4.3");
-
- /**
- * X9.63 - Signature Specification
- * <p>
- * Base OID: 1.3.133.16.840.63.0
- */
- static final ASN1ObjectIdentifier x9_63_scheme = new ASN1ObjectIdentifier("1.3.133.16.840.63.0");
- /** 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
- */
-
- static final ASN1ObjectIdentifier ansi_X9_42 = new ASN1ObjectIdentifier("1.2.840.10046");
-
- /**
- * 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/core/src/main/java/org/bouncycastle/crypto/AsymmetricBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/AsymmetricBlockCipher.java
deleted file mode 100644
index 565effcc..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/AsymmetricBlockCipher.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.bouncycastle.crypto;
-
-
-/**
- * base interface that a public/private key block cipher needs
- * to conform to.
- */
-public interface AsymmetricBlockCipher
-{
- /**
- * initialise the cipher.
- *
- * @param forEncryption if true the cipher is initialised for
- * encryption, if false for decryption.
- * @param param the key and other data required by the cipher.
- */
- public void init(boolean forEncryption, CipherParameters param);
-
- /**
- * returns the largest size an input block can be.
- *
- * @return maximum size for an input block.
- */
- public int getInputBlockSize();
-
- /**
- * returns the maximum size of the block produced by this cipher.
- *
- * @return maximum size of the output block produced by the cipher.
- */
- public int getOutputBlockSize();
-
- /**
- * process the block of len bytes stored in in from offset inOff.
- *
- * @param in the input data
- * @param inOff offset into the in array where the data starts
- * @param len the length of the block to be processed.
- * @return the resulting byte array of the encryption/decryption process.
- * @exception InvalidCipherTextException data decrypts improperly.
- * @exception DataLengthException the input data is too large for the cipher.
- */
- public byte[] processBlock(byte[] in, int inOff, int len)
- throws InvalidCipherTextException;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/AsymmetricCipherKeyPair.java b/core/src/main/java/org/bouncycastle/crypto/AsymmetricCipherKeyPair.java
deleted file mode 100644
index ddee7019..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/AsymmetricCipherKeyPair.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package org.bouncycastle.crypto;
-
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-
-/**
- * a holding class for public/private parameter pairs.
- */
-public class AsymmetricCipherKeyPair
-{
- private AsymmetricKeyParameter publicParam;
- private AsymmetricKeyParameter privateParam;
-
- /**
- * basic constructor.
- *
- * @param publicParam a public key parameters object.
- * @param privateParam the corresponding private key parameters.
- */
- public AsymmetricCipherKeyPair(
- AsymmetricKeyParameter publicParam,
- AsymmetricKeyParameter privateParam)
- {
- this.publicParam = publicParam;
- this.privateParam = privateParam;
- }
-
- /**
- * basic constructor.
- *
- * @param publicParam a public key parameters object.
- * @param privateParam the corresponding private key parameters.
- * @deprecated use AsymmetricKeyParameter
- */
- public AsymmetricCipherKeyPair(
- CipherParameters publicParam,
- CipherParameters privateParam)
- {
- this.publicParam = (AsymmetricKeyParameter)publicParam;
- this.privateParam = (AsymmetricKeyParameter)privateParam;
- }
-
- /**
- * return the public key parameters.
- *
- * @return the public key parameters.
- */
- public AsymmetricKeyParameter getPublic()
- {
- return publicParam;
- }
-
- /**
- * return the private key parameters.
- *
- * @return the private key parameters.
- */
- public AsymmetricKeyParameter getPrivate()
- {
- return privateParam;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/AsymmetricCipherKeyPairGenerator.java b/core/src/main/java/org/bouncycastle/crypto/AsymmetricCipherKeyPairGenerator.java
deleted file mode 100644
index 919db199..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/AsymmetricCipherKeyPairGenerator.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * interface that a public/private key pair generator should conform to.
- */
-public interface AsymmetricCipherKeyPairGenerator
-{
- /**
- * intialise the key pair generator.
- *
- * @param param the parameters the key pair is to be initialised with.
- */
- public void init(KeyGenerationParameters param);
-
- /**
- * return an AsymmetricCipherKeyPair containing the generated keys.
- *
- * @return an AsymmetricCipherKeyPair containing the generated keys.
- */
- public AsymmetricCipherKeyPair generateKeyPair();
-}
-
diff --git a/core/src/main/java/org/bouncycastle/crypto/BasicAgreement.java b/core/src/main/java/org/bouncycastle/crypto/BasicAgreement.java
deleted file mode 100644
index 8e5ff0da..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/BasicAgreement.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.bouncycastle.crypto;
-
-import java.math.BigInteger;
-
-/**
- * The basic interface that basic Diffie-Hellman implementations
- * conforms to.
- */
-public interface BasicAgreement
-{
- /**
- * initialise the agreement engine.
- */
- void init(CipherParameters param);
-
- /**
- * return the field size for the agreement algorithm in bytes.
- */
- int getFieldSize();
-
- /**
- * given a public key from a given party calculate the next
- * message in the agreement sequence.
- */
- BigInteger calculateAgreement(CipherParameters pubKey);
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/BlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/BlockCipher.java
deleted file mode 100644
index 3cfa25a0..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/BlockCipher.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package org.bouncycastle.crypto;
-
-
-/**
- * Block cipher engines are expected to conform to this interface.
- */
-public interface BlockCipher
-{
- /**
- * Initialise the cipher.
- *
- * @param forEncryption if true the cipher is initialised for
- * encryption, if false for decryption.
- * @param params the key and other data required by the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(boolean forEncryption, CipherParameters params)
- throws IllegalArgumentException;
-
- /**
- * Return the name of the algorithm the cipher implements.
- *
- * @return the name of the algorithm the cipher implements.
- */
- public String getAlgorithmName();
-
- /**
- * Return the block size for this cipher (in bytes).
- *
- * @return the block size for this cipher in bytes.
- */
- public int getBlockSize();
-
- /**
- * Process one block of input from the array in and write it to
- * the out array.
- *
- * @param in the array containing the input data.
- * @param inOff offset into the in array the data starts at.
- * @param out the array the output data will be copied into.
- * @param outOff the offset into the out array the output will start at.
- * @exception DataLengthException if there isn't enough data in in, or
- * space in out.
- * @exception IllegalStateException if the cipher isn't initialised.
- * @return the number of bytes processed and produced.
- */
- public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
- throws DataLengthException, IllegalStateException;
-
- /**
- * Reset the cipher. After resetting the cipher is in the same state
- * as it was after the last init (if there was one).
- */
- public void reset();
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/BufferedAsymmetricBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/BufferedAsymmetricBlockCipher.java
deleted file mode 100644
index 1bf7ce3e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/BufferedAsymmetricBlockCipher.java
+++ /dev/null
@@ -1,171 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * a buffer wrapper for an asymmetric block cipher, allowing input
- * to be accumulated in a piecemeal fashion until final processing.
- */
-public class BufferedAsymmetricBlockCipher
-{
- protected byte[] buf;
- protected int bufOff;
-
- private final AsymmetricBlockCipher cipher;
-
- /**
- * base constructor.
- *
- * @param cipher the cipher this buffering object wraps.
- */
- public BufferedAsymmetricBlockCipher(
- AsymmetricBlockCipher cipher)
- {
- this.cipher = cipher;
- }
-
- /**
- * return the underlying cipher for the buffer.
- *
- * @return the underlying cipher for the buffer.
- */
- public AsymmetricBlockCipher getUnderlyingCipher()
- {
- return cipher;
- }
-
- /**
- * return the amount of data sitting in the buffer.
- *
- * @return the amount of data sitting in the buffer.
- */
- public int getBufferPosition()
- {
- return bufOff;
- }
-
- /**
- * initialise the buffer and the underlying cipher.
- *
- * @param forEncryption if true the cipher is initialised for
- * encryption, if false for decryption.
- * @param params the key and other data required by the cipher.
- */
- public void init(
- boolean forEncryption,
- CipherParameters params)
- {
- reset();
-
- cipher.init(forEncryption, params);
-
- //
- // we allow for an extra byte where people are using their own padding
- // mechanisms on a raw cipher.
- //
- buf = new byte[cipher.getInputBlockSize() + (forEncryption ? 1 : 0)];
- bufOff = 0;
- }
-
- /**
- * returns the largest size an input block can be.
- *
- * @return maximum size for an input block.
- */
- public int getInputBlockSize()
- {
- return cipher.getInputBlockSize();
- }
-
- /**
- * returns the maximum size of the block produced by this cipher.
- *
- * @return maximum size of the output block produced by the cipher.
- */
- public int getOutputBlockSize()
- {
- return cipher.getOutputBlockSize();
- }
-
- /**
- * add another byte for processing.
- *
- * @param in the input byte.
- */
- public void processByte(
- byte in)
- {
- if (bufOff >= buf.length)
- {
- throw new DataLengthException("attempt to process message too long for cipher");
- }
-
- buf[bufOff++] = in;
- }
-
- /**
- * add len bytes to the buffer for processing.
- *
- * @param in the input data
- * @param inOff offset into the in array where the data starts
- * @param len the length of the block to be processed.
- */
- public void processBytes(
- byte[] in,
- int inOff,
- int len)
- {
- if (len == 0)
- {
- return;
- }
-
- if (len < 0)
- {
- throw new IllegalArgumentException("Can't have a negative input length!");
- }
-
- if (bufOff + len > buf.length)
- {
- throw new DataLengthException("attempt to process message too long for cipher");
- }
-
- System.arraycopy(in, inOff, buf, bufOff, len);
- bufOff += len;
- }
-
- /**
- * process the contents of the buffer using the underlying
- * cipher.
- *
- * @return the result of the encryption/decryption process on the
- * buffer.
- * @exception InvalidCipherTextException if we are given a garbage block.
- */
- public byte[] doFinal()
- throws InvalidCipherTextException
- {
- byte[] out = cipher.processBlock(buf, 0, bufOff);
-
- reset();
-
- return out;
- }
-
- /**
- * Reset the buffer and the underlying cipher.
- */
- public void reset()
- {
- /*
- * clean the buffer.
- */
- if (buf != null)
- {
- for (int i = 0; i < buf.length; i++)
- {
- buf[i] = 0;
- }
- }
-
- bufOff = 0;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
deleted file mode 100644
index 8e41e492..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
+++ /dev/null
@@ -1,313 +0,0 @@
-package org.bouncycastle.crypto;
-
-
-/**
- * A wrapper class that allows block ciphers to be used to process data in
- * a piecemeal fashion. The BufferedBlockCipher outputs a block only when the
- * buffer is full and more data is being added, or on a doFinal.
- * <p>
- * Note: in the case where the underlying cipher is either a CFB cipher or an
- * OFB one the last block may not be a multiple of the block size.
- */
-public class BufferedBlockCipher
-{
- protected byte[] buf;
- protected int bufOff;
-
- protected boolean forEncryption;
- protected BlockCipher cipher;
-
- protected boolean partialBlockOkay;
- protected boolean pgpCFB;
-
- /**
- * constructor for subclasses
- */
- protected BufferedBlockCipher()
- {
- }
-
- /**
- * Create a buffered block cipher without padding.
- *
- * @param cipher the underlying block cipher this buffering object wraps.
- */
- public BufferedBlockCipher(
- BlockCipher cipher)
- {
- this.cipher = cipher;
-
- buf = new byte[cipher.getBlockSize()];
- bufOff = 0;
-
- //
- // check if we can handle partial blocks on doFinal.
- //
- String name = cipher.getAlgorithmName();
- int idx = name.indexOf('/') + 1;
-
- pgpCFB = (idx > 0 && name.startsWith("PGP", idx));
-
- if (pgpCFB || cipher instanceof StreamCipher)
- {
- partialBlockOkay = true;
- }
- else
- {
- partialBlockOkay = (idx > 0 && (name.startsWith("OpenPGP", idx)));
- }
- }
-
- /**
- * return the cipher this object wraps.
- *
- * @return the cipher this object wraps.
- */
- public BlockCipher getUnderlyingCipher()
- {
- return cipher;
- }
-
- /**
- * initialise the cipher.
- *
- * @param forEncryption if true the cipher is initialised for
- * encryption, if false for decryption.
- * @param params the key and other data required by the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean forEncryption,
- CipherParameters params)
- throws IllegalArgumentException
- {
- this.forEncryption = forEncryption;
-
- reset();
-
- cipher.init(forEncryption, params);
- }
-
- /**
- * return the blocksize for the underlying cipher.
- *
- * @return the blocksize for the underlying cipher.
- */
- public int getBlockSize()
- {
- return cipher.getBlockSize();
- }
-
- /**
- * 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;
-
- if (pgpCFB)
- {
- leftOver = total % buf.length - (cipher.getBlockSize() + 2);
- }
- else
- {
- leftOver = total % buf.length;
- }
-
- return total - leftOver;
- }
-
- /**
- * return the size of the output buffer required for an update plus a
- * doFinal with an input of 'length' bytes.
- *
- * @param length the length of the input.
- * @return the space required to accommodate a call to update and doFinal
- * with 'length' bytes of input.
- */
- public int getOutputSize(
- int length)
- {
- // Note: Can assume partialBlockOkay is true for purposes of this calculation
- return length + bufOff;
- }
-
- /**
- * process a single byte, producing an output block if neccessary.
- *
- * @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 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;
-
- buf[bufOff++] = in;
-
- if (bufOff == buf.length)
- {
- resultLen = cipher.processBlock(buf, 0, out, outOff);
- bufOff = 0;
- }
-
- 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 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 OutputLengthException("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);
-
- bufOff = 0;
- len -= gapLen;
- inOff += gapLen;
-
- while (len > buf.length)
- {
- resultLen += cipher.processBlock(in, inOff, out, outOff + resultLen);
-
- len -= blockSize;
- inOff += blockSize;
- }
- }
-
- System.arraycopy(in, inOff, buf, bufOff, len);
-
- bufOff += len;
-
- if (bufOff == buf.length)
- {
- resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen);
- bufOff = 0;
- }
-
- 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 DataLengthException if there is insufficient space in out for
- * the output, or the input is not block size aligned and should be.
- * @exception IllegalStateException if the underlying cipher is not
- * initialised.
- * @exception InvalidCipherTextException if padding is expected and not found.
- * @exception DataLengthException if the input is not block size
- * aligned.
- */
- public int doFinal(
- byte[] out,
- int outOff)
- throws DataLengthException, IllegalStateException, InvalidCipherTextException
- {
- try
- {
- int resultLen = 0;
-
- if (outOff + bufOff > out.length)
- {
- throw new OutputLengthException("output buffer too short for doFinal()");
- }
-
- if (bufOff != 0)
- {
- if (!partialBlockOkay)
- {
- throw new DataLengthException("data not block size aligned");
- }
-
- cipher.processBlock(buf, 0, buf, 0);
- resultLen = bufOff;
- bufOff = 0;
- System.arraycopy(buf, 0, out, outOff, resultLen);
- }
-
- return resultLen;
- }
- finally
- {
- reset();
- }
- }
-
- /**
- * Reset the buffer and cipher. After resetting the object is in the same
- * state as it was after the last init (if there was one).
- */
- public void reset()
- {
- //
- // clean the buffer.
- //
- for (int i = 0; i < buf.length; i++)
- {
- buf[i] = 0;
- }
-
- bufOff = 0;
-
- //
- // reset the underlying cipher.
- //
- cipher.reset();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/CipherKeyGenerator.java b/core/src/main/java/org/bouncycastle/crypto/CipherKeyGenerator.java
deleted file mode 100644
index 451f8e8f..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/CipherKeyGenerator.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.bouncycastle.crypto;
-
-import java.security.SecureRandom;
-
-/**
- * The base class for symmetric, or secret, cipher key generators.
- */
-public class CipherKeyGenerator
-{
- protected SecureRandom random;
- protected int strength;
-
- /**
- * initialise the key generator.
- *
- * @param param the parameters to be used for key generation
- */
- public void init(
- KeyGenerationParameters param)
- {
- this.random = param.getRandom();
- this.strength = (param.getStrength() + 7) / 8;
- }
-
- /**
- * generate a secret key.
- *
- * @return a byte array containing the key value.
- */
- public byte[] generateKey()
- {
- byte[] key = new byte[strength];
-
- random.nextBytes(key);
-
- return key;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/CipherParameters.java b/core/src/main/java/org/bouncycastle/crypto/CipherParameters.java
deleted file mode 100644
index 5be87304..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/CipherParameters.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * all parameter classes implement this.
- */
-public interface CipherParameters
-{
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/Commitment.java b/core/src/main/java/org/bouncycastle/crypto/Commitment.java
deleted file mode 100644
index f1dc05a3..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/Commitment.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * General holding class for a commitment.
- */
-public class Commitment
-{
- private final byte[] secret;
- private final byte[] commitment;
-
- /**
- * Base constructor.
- *
- * @param secret an encoding of the secret required to reveal the commitment.
- * @param commitment an encoding of the sealed commitment.
- */
- public Commitment(byte[] secret, byte[] commitment)
- {
- this.secret = secret;
- this.commitment = commitment;
- }
-
- /**
- * The secret required to reveal the commitment.
- *
- * @return an encoding of the secret associated with the commitment.
- */
- public byte[] getSecret()
- {
- return secret;
- }
-
- /**
- * The sealed commitment.
- *
- * @return an encoding of the sealed commitment.
- */
- public byte[] getCommitment()
- {
- return commitment;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/Committer.java b/core/src/main/java/org/bouncycastle/crypto/Committer.java
deleted file mode 100644
index 5c93e5d1..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/Committer.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * General interface fdr classes that produce and validate commitments.
- */
-public interface Committer
-{
- /**
- * Generate a commitment for the passed in message.
- *
- * @param message the message to be committed to,
- * @return a Commitment
- */
- Commitment commit(byte[] message);
-
- /**
- * Return true if the passed in commitment represents a commitment to the passed in maessage.
- *
- * @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.
- */
- boolean isRevealed(Commitment commitment, byte[] message);
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/CryptoException.java b/core/src/main/java/org/bouncycastle/crypto/CryptoException.java
deleted file mode 100644
index 352c5569..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/CryptoException.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * the foundation class for the hard exceptions thrown by the crypto packages.
- */
-public class CryptoException
- extends Exception
-{
- private Throwable cause;
-
- /**
- * base constructor.
- */
- public CryptoException()
- {
- }
-
- /**
- * create a CryptoException with the given message.
- *
- * @param message the message to be carried with the exception.
- */
- public CryptoException(
- String message)
- {
- super(message);
- }
-
- /**
- * Create a CryptoException with the given message and underlying cause.
- *
- * @param message message describing exception.
- * @param cause the throwable that was the underlying cause.
- */
- public CryptoException(
- String message,
- Throwable cause)
- {
- super(message);
-
- this.cause = cause;
- }
-
- public Throwable getCause()
- {
- return cause;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/DSA.java b/core/src/main/java/org/bouncycastle/crypto/DSA.java
deleted file mode 100644
index 1f584762..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/DSA.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.bouncycastle.crypto;
-
-import java.math.BigInteger;
-
-/**
- * interface for classes implementing algorithms modeled similar to the Digital Signature Alorithm.
- */
-public interface DSA
-{
- /**
- * initialise the signer for signature generation or signature
- * verification.
- *
- * @param forSigning true if we are generating a signature, false
- * otherwise.
- * @param param key parameters for signature generation.
- */
- public void init(boolean forSigning, CipherParameters param);
-
- /**
- * sign the passed in message (usually the output of a hash function).
- *
- * @param message the message to be signed.
- * @return two big integers representing the r and s values respectively.
- */
- public BigInteger[] generateSignature(byte[] message);
-
- /**
- * verify the message message against the signature values r and s.
- *
- * @param message the message that was supposed to have been signed.
- * @param r the r signature value.
- * @param s the s signature value.
- */
- public boolean verifySignature(byte[] message, BigInteger r, BigInteger s);
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/DataLengthException.java b/core/src/main/java/org/bouncycastle/crypto/DataLengthException.java
deleted file mode 100644
index fbf047cf..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/DataLengthException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * this exception is thrown if a buffer that is meant to have output
- * copied into it turns out to be too short, or if we've been given
- * insufficient input. In general this exception will get thrown rather
- * than an ArrayOutOfBounds exception.
- */
-public class DataLengthException
- extends RuntimeCryptoException
-{
- /**
- * base constructor.
- */
- public DataLengthException()
- {
- }
-
- /**
- * create a DataLengthException with the given message.
- *
- * @param message the message to be carried with the exception.
- */
- public DataLengthException(
- String message)
- {
- super(message);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/DerivationFunction.java b/core/src/main/java/org/bouncycastle/crypto/DerivationFunction.java
deleted file mode 100644
index 0e2b4b06..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/DerivationFunction.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * base interface for general purpose byte derivation functions.
- */
-public interface DerivationFunction
-{
- public void init(DerivationParameters param);
-
- public int generateBytes(byte[] out, int outOff, int len)
- throws DataLengthException, IllegalArgumentException;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/DerivationParameters.java b/core/src/main/java/org/bouncycastle/crypto/DerivationParameters.java
deleted file mode 100644
index e11eb867..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/DerivationParameters.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * Parameters for key/byte stream derivation classes
- */
-public interface DerivationParameters
-{
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/Digest.java b/core/src/main/java/org/bouncycastle/crypto/Digest.java
deleted file mode 100644
index f44fad0d..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/Digest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * interface that a message digest conforms to.
- */
-public interface Digest
-{
- /**
- * return the algorithm name
- *
- * @return the algorithm name
- */
- public String getAlgorithmName();
-
- /**
- * return the size, in bytes, of the digest produced by this message digest.
- *
- * @return the size, in bytes, of the digest produced by this message digest.
- */
- public int getDigestSize();
-
- /**
- * update the message digest with a single byte.
- *
- * @param in the input byte to be entered.
- */
- public void update(byte in);
-
- /**
- * update the message digest with a block of bytes.
- *
- * @param in the byte array containing the data.
- * @param inOff the offset into the byte array where the data starts.
- * @param len the length of the data.
- */
- public void update(byte[] in, int inOff, int len);
-
- /**
- * close the digest, producing the final digest value. The doFinal
- * call leaves the digest reset.
- *
- * @param out the array the digest is to be copied into.
- * @param outOff the offset into the out array the digest is to start at.
- */
- public int doFinal(byte[] out, int outOff);
-
- /**
- * reset the digest back to it's initial state.
- */
- public void reset();
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/DigestDerivationFunction.java b/core/src/main/java/org/bouncycastle/crypto/DigestDerivationFunction.java
deleted file mode 100644
index 180382d2..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/DigestDerivationFunction.java
+++ /dev/null
@@ -1,13 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/EphemeralKeyPair.java b/core/src/main/java/org/bouncycastle/crypto/EphemeralKeyPair.java
deleted file mode 100644
index f16812f9..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/EphemeralKeyPair.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.crypto;
-
-public class EphemeralKeyPair
-{
- private AsymmetricCipherKeyPair keyPair;
- private KeyEncoder publicKeyEncoder;
-
- public EphemeralKeyPair(AsymmetricCipherKeyPair keyPair, KeyEncoder publicKeyEncoder)
- {
- this.keyPair = keyPair;
- this.publicKeyEncoder = publicKeyEncoder;
- }
-
- public AsymmetricCipherKeyPair getKeyPair()
- {
- return keyPair;
- }
-
- public byte[] getEncodedPublicKey()
- {
- return publicKeyEncoder.getEncoded(keyPair.getPublic());
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/ExtendedDigest.java b/core/src/main/java/org/bouncycastle/crypto/ExtendedDigest.java
deleted file mode 100644
index c5e9e8b0..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/ExtendedDigest.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.bouncycastle.crypto;
-
-public interface ExtendedDigest
- extends Digest
-{
- /**
- * Return the size in bytes of the internal buffer the digest applies it's compression
- * function to.
- *
- * @return byte length of the digests internal buffer.
- */
- public int getByteLength();
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/InvalidCipherTextException.java b/core/src/main/java/org/bouncycastle/crypto/InvalidCipherTextException.java
deleted file mode 100644
index 21c150d9..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/InvalidCipherTextException.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * this exception is thrown whenever we find something we don't expect in a
- * message.
- */
-public class InvalidCipherTextException
- extends CryptoException
-{
- /**
- * base constructor.
- */
- public InvalidCipherTextException()
- {
- }
-
- /**
- * create a InvalidCipherTextException with the given message.
- *
- * @param message the message to be carried with the exception.
- */
- public InvalidCipherTextException(
- String message)
- {
- super(message);
- }
-
- /**
- * create a InvalidCipherTextException with the given message.
- *
- * @param message the message to be carried with the exception.
- * @param cause the root cause of the exception.
- */
- public InvalidCipherTextException(
- String message,
- Throwable cause)
- {
- super(message, cause);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/KeyEncapsulation.java b/core/src/main/java/org/bouncycastle/crypto/KeyEncapsulation.java
deleted file mode 100755
index 16744573..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/KeyEncapsulation.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * The basic interface for key encapsulation mechanisms.
- */
-public interface KeyEncapsulation
-{
- /**
- * Initialise the key encapsulation mechanism.
- */
- public void init(CipherParameters param);
-
- /**
- * Encapsulate a randomly generated session key.
- */
- public CipherParameters encrypt(byte[] out, int outOff, int keyLen);
-
- /**
- * Decapsulate an encapsulated session key.
- */
- public CipherParameters decrypt(byte[] in, int inOff, int inLen, int keyLen);
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/KeyEncoder.java b/core/src/main/java/org/bouncycastle/crypto/KeyEncoder.java
deleted file mode 100644
index 92ded9cd..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/KeyEncoder.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.bouncycastle.crypto;
-
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-
-public interface KeyEncoder
-{
- byte[] getEncoded(AsymmetricKeyParameter keyParameter);
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/KeyGenerationParameters.java b/core/src/main/java/org/bouncycastle/crypto/KeyGenerationParameters.java
deleted file mode 100644
index 9a63522f..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/KeyGenerationParameters.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.bouncycastle.crypto;
-
-import java.security.SecureRandom;
-
-/**
- * The base class for parameters to key generators.
- */
-public class KeyGenerationParameters
-{
- private SecureRandom random;
- private int strength;
-
- /**
- * initialise the generator with a source of randomness
- * and a strength (in bits).
- *
- * @param random the random byte source.
- * @param strength the size, in bits, of the keys we want to produce.
- */
- public KeyGenerationParameters(
- SecureRandom random,
- int strength)
- {
- this.random = random;
- this.strength = strength;
- }
-
- /**
- * return the random source associated with this
- * generator.
- *
- * @return the generators random source.
- */
- public SecureRandom getRandom()
- {
- return random;
- }
-
- /**
- * return the bit strength for keys produced by this generator,
- *
- * @return the strength of the keys this generator produces (in bits).
- */
- public int getStrength()
- {
- return strength;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/KeyParser.java b/core/src/main/java/org/bouncycastle/crypto/KeyParser.java
deleted file mode 100644
index 60ce29de..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/KeyParser.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.bouncycastle.crypto;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-
-public interface KeyParser
-{
- AsymmetricKeyParameter readKey(InputStream stream)
- throws IOException;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/Mac.java b/core/src/main/java/org/bouncycastle/crypto/Mac.java
deleted file mode 100644
index c00cd58c..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/Mac.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.bouncycastle.crypto;
-
-
-/**
- * The base interface for implementations of message authentication codes (MACs).
- */
-public interface Mac
-{
- /**
- * Initialise the MAC.
- *
- * @param params the key and other data required by the MAC.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(CipherParameters params)
- throws IllegalArgumentException;
-
- /**
- * Return the name of the algorithm the MAC implements.
- *
- * @return the name of the algorithm the MAC implements.
- */
- public String getAlgorithmName();
-
- /**
- * Return the block size for this MAC (in bytes).
- *
- * @return the block size for this MAC in bytes.
- */
- public int getMacSize();
-
- /**
- * add a single byte to the mac for processing.
- *
- * @param in the byte to be processed.
- * @exception IllegalStateException if the MAC is not initialised.
- */
- public void update(byte in)
- throws IllegalStateException;
-
- /**
- * @param in the array containing the input.
- * @param inOff the index in the array the data begins at.
- * @param len the length of the input starting at inOff.
- * @exception IllegalStateException if the MAC is not initialised.
- * @exception DataLengthException if there isn't enough data in in.
- */
- public void update(byte[] in, int inOff, int len)
- throws DataLengthException, IllegalStateException;
-
- /**
- * Compute the final stage of the MAC writing the output to the out
- * parameter.
- * <p>
- * doFinal leaves the MAC in the same state it was after the last init.
- *
- * @param out the array the MAC is to be output to.
- * @param outOff the offset into the out buffer the output is to start at.
- * @exception DataLengthException if there isn't enough space in out.
- * @exception IllegalStateException if the MAC is not initialised.
- */
- public int doFinal(byte[] out, int outOff)
- throws DataLengthException, IllegalStateException;
-
- /**
- * Reset the MAC. At the end of resetting the MAC should be in the
- * in the same state it was after the last init (if there was one).
- */
- public void reset();
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/MacDerivationFunction.java b/core/src/main/java/org/bouncycastle/crypto/MacDerivationFunction.java
deleted file mode 100644
index 16198bab..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/MacDerivationFunction.java
+++ /dev/null
@@ -1,13 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/MaxBytesExceededException.java b/core/src/main/java/org/bouncycastle/crypto/MaxBytesExceededException.java
deleted file mode 100644
index bfa15442..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/MaxBytesExceededException.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * this exception is thrown whenever a cipher requires a change of key, iv
- * or similar after x amount of bytes enciphered
- */
-public class MaxBytesExceededException
- extends RuntimeCryptoException
-{
- /**
- * base constructor.
- */
- public MaxBytesExceededException()
- {
- }
-
- /**
- * create an with the given message.
- *
- * @param message the message to be carried with the exception.
- */
- public MaxBytesExceededException(
- String message)
- {
- super(message);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/OutputLengthException.java b/core/src/main/java/org/bouncycastle/crypto/OutputLengthException.java
deleted file mode 100644
index 62811a2b..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/OutputLengthException.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.bouncycastle.crypto;
-
-public class OutputLengthException
- extends DataLengthException
-{
- public OutputLengthException(String msg)
- {
- super(msg);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/PBEParametersGenerator.java b/core/src/main/java/org/bouncycastle/crypto/PBEParametersGenerator.java
deleted file mode 100644
index 18cc648a..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/PBEParametersGenerator.java
+++ /dev/null
@@ -1,171 +0,0 @@
-package org.bouncycastle.crypto;
-
-import org.bouncycastle.util.Strings;
-
-/**
- * super class for all Password Based Encryption (PBE) parameter generator classes.
- */
-public abstract class PBEParametersGenerator
-{
- protected byte[] password;
- protected byte[] salt;
- protected int iterationCount;
-
- /**
- * base constructor.
- */
- protected PBEParametersGenerator()
- {
- }
-
- /**
- * initialise the PBE generator.
- *
- * @param password the password converted into bytes (see below).
- * @param salt the salt to be mixed with the password.
- * @param iterationCount the number of iterations the "mixing" function
- * is to be applied for.
- */
- public void init(
- byte[] password,
- byte[] salt,
- int iterationCount)
- {
- this.password = password;
- this.salt = salt;
- this.iterationCount = iterationCount;
- }
-
- /**
- * return the password byte array.
- *
- * @return the password byte array.
- */
- public byte[] getPassword()
- {
- return password;
- }
-
- /**
- * return the salt byte array.
- *
- * @return the salt byte array.
- */
- public byte[] getSalt()
- {
- return salt;
- }
-
- /**
- * return the iteration count.
- *
- * @return the iteration count.
- */
- public int getIterationCount()
- {
- return iterationCount;
- }
-
- /**
- * generate derived parameters for a key of length keySize.
- *
- * @param keySize the length, in bits, of the key required.
- * @return a parameters object representing a key.
- */
- public abstract CipherParameters generateDerivedParameters(int keySize);
-
- /**
- * generate derived parameters for a key of length keySize, and
- * an initialisation vector (IV) of length ivSize.
- *
- * @param keySize the length, in bits, of the key required.
- * @param ivSize the length, in bits, of the iv required.
- * @return a parameters object representing a key and an IV.
- */
- public abstract CipherParameters generateDerivedParameters(int keySize, int ivSize);
-
- /**
- * generate derived parameters for a key of length keySize, specifically
- * for use with a MAC.
- *
- * @param keySize the length, in bits, of the key required.
- * @return a parameters object representing a key.
- */
- public abstract CipherParameters generateDerivedMacParameters(int keySize);
-
- /**
- * converts a password to a byte array according to the scheme in
- * PKCS5 (ascii, no padding)
- *
- * @param password a character array representing the password.
- * @return a byte array representing the password.
- */
- public static byte[] PKCS5PasswordToBytes(
- char[] password)
- {
- if (password != null)
- {
- byte[] bytes = new byte[password.length];
-
- for (int i = 0; i != bytes.length; i++)
- {
- bytes[i] = (byte)password[i];
- }
-
- return bytes;
- }
- else
- {
- return new byte[0];
- }
- }
-
- /**
- * converts a password to a byte array according to the scheme in
- * PKCS5 (UTF-8, no padding)
- *
- * @param password a character array representing the password.
- * @return a byte array representing the password.
- */
- public static byte[] PKCS5PasswordToUTF8Bytes(
- char[] password)
- {
- if (password != null)
- {
- return Strings.toUTF8ByteArray(password);
- }
- else
- {
- return new byte[0];
- }
- }
-
- /**
- * converts a password to a byte array according to the scheme in
- * PKCS12 (unicode, big endian, 2 zero pad bytes at the end).
- *
- * @param password a character array representing the password.
- * @return a byte array representing the password.
- */
- public static byte[] PKCS12PasswordToBytes(
- char[] password)
- {
- if (password != null && password.length > 0)
- {
- // +1 for extra 2 pad bytes.
- byte[] bytes = new byte[(password.length + 1) * 2];
-
- for (int i = 0; i != password.length; i ++)
- {
- bytes[i * 2] = (byte)(password[i] >>> 8);
- bytes[i * 2 + 1] = (byte)password[i];
- }
-
- return bytes;
- }
- else
- {
- return new byte[0];
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/RuntimeCryptoException.java b/core/src/main/java/org/bouncycastle/crypto/RuntimeCryptoException.java
deleted file mode 100644
index c1572020..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/RuntimeCryptoException.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * the foundation class for the exceptions thrown by the crypto packages.
- */
-public class RuntimeCryptoException
- extends RuntimeException
-{
- /**
- * base constructor.
- */
- public RuntimeCryptoException()
- {
- }
-
- /**
- * create a RuntimeCryptoException with the given message.
- *
- * @param message the message to be carried with the exception.
- */
- public RuntimeCryptoException(
- String message)
- {
- super(message);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/Signer.java b/core/src/main/java/org/bouncycastle/crypto/Signer.java
deleted file mode 100644
index 357b0da4..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/Signer.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * Generic signer interface for hash based and message recovery signers.
- */
-public interface Signer
-{
- /**
- * Initialise the signer for signing or verification.
- *
- * @param forSigning true if for signing, false otherwise
- * @param param necessary parameters.
- */
- public void init(boolean forSigning, CipherParameters param);
-
- /**
- * update the internal digest with the byte b
- */
- public void update(byte b);
-
- /**
- * update the internal digest with the byte array in
- */
- public void update(byte[] in, int off, int len);
-
- /**
- * generate a signature for the message we've been loaded with using
- * the key we were initialised with.
- */
- public byte[] generateSignature()
- throws CryptoException, DataLengthException;
-
- /**
- * return true if the internal state represents the signature described
- * in the passed in array.
- */
- public boolean verifySignature(byte[] signature);
-
- /**
- * reset the internal state
- */
- public void reset();
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/SignerWithRecovery.java b/core/src/main/java/org/bouncycastle/crypto/SignerWithRecovery.java
deleted file mode 100644
index 452b367f..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/SignerWithRecovery.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * Signer with message recovery.
- */
-public interface SignerWithRecovery
- extends Signer
-{
- /**
- * Returns true if the signer has recovered the full message as
- * part of signature verification.
- *
- * @return true if full message recovered.
- */
- public boolean hasFullMessage();
-
- /**
- * Returns a reference to what message was recovered (if any).
- *
- * @return full/partial message, null if nothing.
- */
- public byte[] getRecoveredMessage();
-
- /**
- * Perform an update with the recovered message before adding any other data. This must
- * be the first update method called, and calling it will result in the signer assuming
- * that further calls to update will include message content past what is recoverable.
- *
- * @param signature the signature that we are in the process of verifying.
- * @throws IllegalStateException
- */
- public void updateWithRecoveredMessage(byte[] signature)
- throws InvalidCipherTextException;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/SkippingCipher.java b/core/src/main/java/org/bouncycastle/crypto/SkippingCipher.java
deleted file mode 100644
index f8cc648e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/SkippingCipher.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * Ciphers producing a key stream which can be reset to particular points in the stream implement this.
- */
-public interface SkippingCipher
-{
- /**
- * Skip numberOfBytes forwards, or backwards.
- *
- * @param numberOfBytes the number of bytes to skip (positive forward, negative backwards).
- * @return the number of bytes actually skipped.
- * @throws java.lang.IllegalArgumentException if numberOfBytes is an invalid value.
- */
- long skip(long numberOfBytes);
-
- /**
- * Reset the cipher and then skip forward to a given position.
- *
- * @param position the number of bytes in to set the cipher state to.
- * @return the byte position moved to.
- */
- long seekTo(long position);
-
- /**
- * Return the current "position" of the cipher
- *
- * @return the current byte position.
- */
- long getPosition();
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/SkippingStreamCipher.java b/core/src/main/java/org/bouncycastle/crypto/SkippingStreamCipher.java
deleted file mode 100644
index a707a810..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/SkippingStreamCipher.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * General interface for a stream cipher that supports skipping.
- */
-public interface SkippingStreamCipher
- extends StreamCipher, SkippingCipher
-{
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/StreamBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/StreamBlockCipher.java
deleted file mode 100644
index 09aadfbf..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/StreamBlockCipher.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * A parent class for block cipher modes that do not require block aligned data to be processed, but can function in
- * a streaming mode.
- */
-public abstract class StreamBlockCipher
- implements BlockCipher, StreamCipher
-{
- private final BlockCipher cipher;
-
- protected StreamBlockCipher(BlockCipher cipher)
- {
- this.cipher = cipher;
- }
-
- /**
- * return the underlying block cipher that we are wrapping.
- *
- * @return the underlying block cipher that we are wrapping.
- */
- public BlockCipher getUnderlyingCipher()
- {
- return cipher;
- }
-
- public final byte returnByte(byte in)
- {
- return calculateByte(in);
- }
-
- public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
- throws DataLengthException
- {
- if (outOff + len > out.length)
- {
- throw new DataLengthException("output buffer too short");
- }
-
- if (inOff + len > in.length)
- {
- throw new DataLengthException("input buffer too small");
- }
-
- int inStart = inOff;
- int inEnd = inOff + len;
- int outStart = outOff;
-
- while (inStart < inEnd)
- {
- out[outStart++] = calculateByte(in[inStart++]);
- }
-
- return len;
- }
-
- protected abstract byte calculateByte(byte b);
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/crypto/StreamCipher.java b/core/src/main/java/org/bouncycastle/crypto/StreamCipher.java
deleted file mode 100644
index c1255e94..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/StreamCipher.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * the interface stream ciphers conform to.
- */
-public interface StreamCipher
-{
- /**
- * Initialise the cipher.
- *
- * @param forEncryption if true the cipher is initialised for
- * encryption, if false for decryption.
- * @param params the key and other data required by the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(boolean forEncryption, CipherParameters params)
- throws IllegalArgumentException;
-
- /**
- * Return the name of the algorithm the cipher implements.
- *
- * @return the name of the algorithm the cipher implements.
- */
- public String getAlgorithmName();
-
- /**
- * encrypt/decrypt a single byte returning the result.
- *
- * @param in the byte to be processed.
- * @return the result of processing the input byte.
- */
- public byte returnByte(byte in);
-
- /**
- * process a block of bytes from in putting the result into out.
- *
- * @param in the input byte array.
- * @param inOff the offset into the in array where the data to be processed starts.
- * @param len the number of bytes to be processed.
- * @param out the output buffer the processed bytes go into.
- * @param outOff the offset into the output byte array the processed data starts at.
- * @return the number of bytes produced - should always be len.
- * @exception DataLengthException if the output buffer is too small.
- */
- public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
- throws DataLengthException;
-
- /**
- * reset the cipher. This leaves it in the same state
- * it was at after the last init (if there was one).
- */
- public void reset();
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/Wrapper.java b/core/src/main/java/org/bouncycastle/crypto/Wrapper.java
deleted file mode 100644
index 3956a6fc..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/Wrapper.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.bouncycastle.crypto;
-
-public interface Wrapper
-{
- public void init(boolean forWrapping, CipherParameters param);
-
- /**
- * Return the name of the algorithm the wrapper implements.
- *
- * @return the name of the algorithm the wrapper implements.
- */
- public String getAlgorithmName();
-
- public byte[] wrap(byte[] in, int inOff, int inLen);
-
- public byte[] unwrap(byte[] in, int inOff, int inLen)
- throws InvalidCipherTextException;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/agreement/DHAgreement.java b/core/src/main/java/org/bouncycastle/crypto/agreement/DHAgreement.java
deleted file mode 100644
index 021a7153..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/agreement/DHAgreement.java
+++ /dev/null
@@ -1,94 +0,0 @@
-package org.bouncycastle.crypto.agreement;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.generators.DHKeyPairGenerator;
-import org.bouncycastle.crypto.params.DHKeyGenerationParameters;
-import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.crypto.params.DHPublicKeyParameters;
-import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-
-/**
- * a Diffie-Hellman key exchange engine.
- * <p>
- * note: This uses MTI/A0 key agreement in order to make the key agreement
- * secure against passive attacks. If you're doing Diffie-Hellman and both
- * parties have long term public keys you should look at using this. For
- * further information have a look at RFC 2631.
- * <p>
- * It's possible to extend this to more than two parties as well, for the moment
- * that is left as an exercise for the reader.
- */
-public class DHAgreement
-{
- private DHPrivateKeyParameters key;
- private DHParameters dhParams;
- private BigInteger privateValue;
- private SecureRandom random;
-
- public void init(
- CipherParameters param)
- {
- AsymmetricKeyParameter kParam;
-
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- this.random = rParam.getRandom();
- kParam = (AsymmetricKeyParameter)rParam.getParameters();
- }
- else
- {
- this.random = new SecureRandom();
- kParam = (AsymmetricKeyParameter)param;
- }
-
-
- if (!(kParam instanceof DHPrivateKeyParameters))
- {
- throw new IllegalArgumentException("DHEngine expects DHPrivateKeyParameters");
- }
-
- this.key = (DHPrivateKeyParameters)kParam;
- this.dhParams = key.getParameters();
- }
-
- /**
- * calculate our initial message.
- */
- public BigInteger calculateMessage()
- {
- DHKeyPairGenerator dhGen = new DHKeyPairGenerator();
- dhGen.init(new DHKeyGenerationParameters(random, dhParams));
- AsymmetricCipherKeyPair dhPair = dhGen.generateKeyPair();
-
- this.privateValue = ((DHPrivateKeyParameters)dhPair.getPrivate()).getX();
-
- return ((DHPublicKeyParameters)dhPair.getPublic()).getY();
- }
-
- /**
- * given a message from a given party and the corresponding public key,
- * calculate the next message in the agreement sequence. In this case
- * this will represent the shared secret.
- */
- public BigInteger calculateAgreement(
- DHPublicKeyParameters pub,
- BigInteger message)
- {
- if (!pub.getParameters().equals(dhParams))
- {
- throw new IllegalArgumentException("Diffie-Hellman public key has wrong parameters.");
- }
-
- BigInteger p = dhParams.getP();
-
- return message.modPow(key.getX(), p).multiply(pub.getY().modPow(privateValue, p)).mod(p);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/agreement/DHBasicAgreement.java b/core/src/main/java/org/bouncycastle/crypto/agreement/DHBasicAgreement.java
deleted file mode 100644
index d2e2a09f..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/agreement/DHBasicAgreement.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.bouncycastle.crypto.agreement;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.BasicAgreement;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
-import org.bouncycastle.crypto.params.DHPublicKeyParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-
-/**
- * a Diffie-Hellman key agreement class.
- * <p>
- * note: This is only the basic algorithm, it doesn't take advantage of
- * long term public keys if they are available. See the DHAgreement class
- * for a "better" implementation.
- */
-public class DHBasicAgreement
- implements BasicAgreement
-{
- private DHPrivateKeyParameters key;
- private DHParameters dhParams;
-
- public void init(
- CipherParameters param)
- {
- AsymmetricKeyParameter kParam;
-
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
- kParam = (AsymmetricKeyParameter)rParam.getParameters();
- }
- else
- {
- kParam = (AsymmetricKeyParameter)param;
- }
-
- if (!(kParam instanceof DHPrivateKeyParameters))
- {
- throw new IllegalArgumentException("DHEngine expects DHPrivateKeyParameters");
- }
-
- this.key = (DHPrivateKeyParameters)kParam;
- this.dhParams = key.getParameters();
- }
-
- public int getFieldSize()
- {
- return (key.getParameters().getP().bitLength() + 7) / 8;
- }
-
- /**
- * given a short term public key from a given party calculate the next
- * message in the agreement sequence.
- */
- public BigInteger calculateAgreement(
- CipherParameters pubKey)
- {
- DHPublicKeyParameters pub = (DHPublicKeyParameters)pubKey;
-
- if (!pub.getParameters().equals(dhParams))
- {
- throw new IllegalArgumentException("Diffie-Hellman public key has wrong parameters.");
- }
-
- return pub.getY().modPow(key.getX(), dhParams.getP());
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/agreement/DHStandardGroups.java b/core/src/main/java/org/bouncycastle/crypto/agreement/DHStandardGroups.java
deleted file mode 100644
index 638bcb13..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/agreement/DHStandardGroups.java
+++ /dev/null
@@ -1,206 +0,0 @@
-package org.bouncycastle.crypto.agreement;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.util.encoders.Hex;
-
-/**
- * Standard Diffie-Hellman groups from various IETF specifications.
- */
-public class DHStandardGroups
-{
-
- private static DHParameters fromPG(String hexP, String hexG)
- {
- BigInteger p = new BigInteger(1, Hex.decode(hexP));
- BigInteger g = new BigInteger(1, Hex.decode(hexG));
- return new DHParameters(p, g);
- }
-
- private static DHParameters fromPGQ(String hexP, String hexG, String hexQ)
- {
- BigInteger p = new BigInteger(1, Hex.decode(hexP));
- BigInteger g = new BigInteger(1, Hex.decode(hexG));
- BigInteger q = new BigInteger(1, Hex.decode(hexQ));
- return new DHParameters(p, g, q);
- }
-
- /*
- * RFC 2409
- */
- private static final String rfc2409_768_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
- + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
- + "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF";
- private static final String rfc2409_768_g = "02";
- public static final DHParameters rfc2409_768 = fromPG(rfc2409_768_p, rfc2409_768_g);
-
- private static final String rfc2409_1024_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
- + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
- + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381"
- + "FFFFFFFFFFFFFFFF";
- private static final String rfc2409_1024_g = "02";
- public static final DHParameters rfc2409_1024 = fromPG(rfc2409_1024_p, rfc2409_1024_g);
-
- /*
- * RFC 3526
- */
- private static final String rfc3526_1536_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
- + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
- + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
- + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
- + "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF";
- private static final String rfc3526_1536_g = "02";
- public static final DHParameters rfc3526_1536 = fromPG(rfc3526_1536_p, rfc3526_1536_g);
-
- private static final String rfc3526_2048_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
- + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
- + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
- + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
- + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
- + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AACAA68FFFFFFFFFFFFFFFF";
- private static final String rfc3526_2048_g = "02";
- public static final DHParameters rfc3526_2048 = fromPG(rfc3526_2048_p, rfc3526_2048_g);
-
- private static final String rfc3526_3072_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
- + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
- + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
- + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
- + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
- + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
- + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
- + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
- + "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF";
- private static final String rfc3526_3072_g = "02";
- public static final DHParameters rfc3526_3072 = fromPG(rfc3526_3072_p, rfc3526_3072_g);
-
- private static final String rfc3526_4096_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
- + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
- + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
- + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
- + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
- + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
- + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
- + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
- + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
- + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
- + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199"
- + "FFFFFFFFFFFFFFFF";
- private static final String rfc3526_4096_g = "02";
- public static final DHParameters rfc3526_4096 = fromPG(rfc3526_4096_p, rfc3526_4096_g);
-
- private static final String rfc3526_6144_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
- + "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
- + "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
- + "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
- + "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8"
- + "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D"
- + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C"
- + "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718"
- + "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D"
- + "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D"
- + "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226"
- + "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
- + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC"
- + "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26"
- + "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB"
- + "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2"
- + "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127"
- + "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
- + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406"
- + "AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918"
- + "DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B33205151"
- + "2BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03"
- + "F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97F"
- + "BEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
- + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58B"
- + "B7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632"
- + "387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E" + "6DCC4024FFFFFFFFFFFFFFFF";
- private static final String rfc3526_6144_g = "02";
- public static final DHParameters rfc3526_6144 = fromPG(rfc3526_6144_p, rfc3526_6144_g);
-
- private static final String rfc3526_8192_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
- + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
- + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
- + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
- + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
- + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
- + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
- + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
- + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
- + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
- + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
- + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" + "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831"
- + "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" + "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF"
- + "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" + "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3"
- + "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328"
- + "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" + "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE"
- + "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4" + "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300"
- + "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568" + "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9"
- + "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B" + "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A"
- + "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36" + "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1"
- + "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92" + "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47"
- + "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" + "60C980DD98EDD3DFFFFFFFFFFFFFFFFF";
- private static final String rfc3526_8192_g = "02";
- public static final DHParameters rfc3526_8192 = fromPG(rfc3526_8192_p, rfc3526_8192_g);
-
- /*
- * RFC 4306
- */
- public static final DHParameters rfc4306_768 = rfc2409_768;
- public static final DHParameters rfc4306_1024 = rfc2409_1024;
-
- /*
- * RFC 5114
- */
- private static final String rfc5114_1024_160_p = "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C6"
- + "9A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C0" + "13ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD70"
- + "98488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0" + "A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708"
- + "DF1FB2BC2E4A4371";
- private static final String rfc5114_1024_160_g = "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507F"
- + "D6406CFF14266D31266FEA1E5C41564B777E690F5504F213" + "160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1"
- + "909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28A" + "D662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24"
- + "855E6EEB22B3B2E5";
- private static final String rfc5114_1024_160_q = "F518AA8781A8DF278ABA4E7D64B7CB9D49462353";
- public static final DHParameters rfc5114_1024_160 = fromPGQ(rfc5114_1024_160_p, rfc5114_1024_160_g,
- rfc5114_1024_160_q);
-
- private static final String rfc5114_2048_224_p = "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1"
- + "B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15" + "EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC212"
- + "9037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207" + "C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708"
- + "B3BF8A317091883681286130BC8985DB1602E714415D9330" + "278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486D"
- + "CDF93ACC44328387315D75E198C641A480CD86A1B9E587E8" + "BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763"
- + "C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71" + "CF9DE5384E71B81C0AC4DFFE0C10E64F";
- private static final String rfc5114_2048_224_g = "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF"
- + "74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFA" + "AB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7"
- + "C17669101999024AF4D027275AC1348BB8A762D0521BC98A" + "E247150422EA1ED409939D54DA7460CDB5F6C6B250717CBE"
- + "F180EB34118E98D119529A45D6F834566E3025E316A330EF" + "BB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB"
- + "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381" + "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269"
- + "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179" + "81BC087F2A7065B384B890D3191F2BFA";
- private static final String rfc5114_2048_224_q = "801C0D34C58D93FE997177101F80535A4738CEBCBF389A99B36371EB";
- public static final DHParameters rfc5114_2048_224 = fromPGQ(rfc5114_2048_224_p, rfc5114_2048_224_g,
- rfc5114_2048_224_q);
-
- private static final String rfc5114_2048_256_p = "87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F2"
- + "5D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA30" + "16C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD"
- + "5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B" + "6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C"
- + "4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0E" + "F13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D9"
- + "67E144E5140564251CCACB83E6B486F6B3CA3F7971506026" + "C0B857F689962856DED4010ABD0BE621C3A3960A54E710C3"
- + "75F26375D7014103A4B54330C198AF126116D2276E11715F" + "693877FAD7EF09CADB094AE91E1A1597";
- private static final String rfc5114_2048_256_g = "3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF2054"
- + "07F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555" + "BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18"
- + "A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B" + "777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC83"
- + "1D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55" + "A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14"
- + "C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915" + "B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6"
- + "184B523D1DB246C32F63078490F00EF8D647D148D4795451" + "5E2327CFEF98C582664B4C0F6CC41659";
- private static final String rfc5114_2048_256_q = "8CF83642A709A097B447997640129DA299B1A47D1EB3750B"
- + "A308B0FE64F5FBD3";
- public static final DHParameters rfc5114_2048_256 = fromPGQ(rfc5114_2048_256_p, rfc5114_2048_256_g,
- rfc5114_2048_256_q);
-
- /*
- * RFC 5996
- */
- public static final DHParameters rfc5996_768 = rfc4306_768;
- public static final DHParameters rfc5996_1024 = rfc4306_1024;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java b/core/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java
deleted file mode 100644
index a491b9df..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package org.bouncycastle.crypto.agreement;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.BasicAgreement;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.math.ec.ECPoint;
-
-/**
- * P1363 7.2.1 ECSVDP-DH
- *
- * ECSVDP-DH is Elliptic Curve Secret Value Derivation Primitive,
- * Diffie-Hellman version. It is based on the work of [DH76], [Mil86],
- * and [Kob87]. This primitive derives a shared secret value from one
- * party's private key and another party's public key, where both have
- * the same set of EC domain parameters. If two parties correctly
- * execute this primitive, they will produce the same output. This
- * primitive can be invoked by a scheme to derive a shared secret key;
- * specifically, it may be used with the schemes ECKAS-DH1 and
- * DL/ECKAS-DH2. It assumes that the input keys are valid (see also
- * Section 7.2.2).
- */
-public class ECDHBasicAgreement
- implements BasicAgreement
-{
- private ECPrivateKeyParameters key;
-
- public void init(
- CipherParameters key)
- {
- this.key = (ECPrivateKeyParameters)key;
- }
-
- public int getFieldSize()
- {
- return (key.getParameters().getCurve().getFieldSize() + 7) / 8;
- }
-
- public BigInteger calculateAgreement(
- CipherParameters pubKey)
- {
- ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey;
- ECPoint P = pub.getQ().multiply(key.getD()).normalize();
-
- if (P.isInfinity())
- {
- throw new IllegalStateException("Infinity is not a valid agreement value for ECDH");
- }
-
- return P.getAffineXCoord().toBigInteger();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/agreement/ECDHCBasicAgreement.java b/core/src/main/java/org/bouncycastle/crypto/agreement/ECDHCBasicAgreement.java
deleted file mode 100644
index 28140df7..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/agreement/ECDHCBasicAgreement.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.bouncycastle.crypto.agreement;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.BasicAgreement;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.math.ec.ECPoint;
-
-/**
- * P1363 7.2.2 ECSVDP-DHC
- *
- * ECSVDP-DHC is Elliptic Curve Secret Value Derivation Primitive,
- * Diffie-Hellman version with cofactor multiplication. It is based on
- * the work of [DH76], [Mil86], [Kob87], [LMQ98] and [Kal98a]. This
- * primitive derives a shared secret value from one party's private key
- * and another party's public key, where both have the same set of EC
- * domain parameters. If two parties correctly execute this primitive,
- * they will produce the same output. This primitive can be invoked by a
- * scheme to derive a shared secret key; specifically, it may be used
- * with the schemes ECKAS-DH1 and DL/ECKAS-DH2. It does not assume the
- * validity of the input public key (see also Section 7.2.1).
- * <p>
- * Note: As stated P1363 compatibility mode with ECDH can be preset, and
- * in this case the implementation doesn't have a ECDH compatibility mode
- * (if you want that just use ECDHBasicAgreement and note they both implement
- * BasicAgreement!).
- */
-public class ECDHCBasicAgreement
- implements BasicAgreement
-{
- ECPrivateKeyParameters key;
-
- public void init(
- CipherParameters key)
- {
- this.key = (ECPrivateKeyParameters)key;
- }
-
- public int getFieldSize()
- {
- return (key.getParameters().getCurve().getFieldSize() + 7) / 8;
- }
-
- public BigInteger calculateAgreement(
- CipherParameters pubKey)
- {
- ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey;
- ECDomainParameters params = pub.getParameters();
-
- BigInteger hd = params.getH().multiply(key.getD()).mod(params.getN());
-
- 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/core/src/main/java/org/bouncycastle/crypto/agreement/ECMQVBasicAgreement.java b/core/src/main/java/org/bouncycastle/crypto/agreement/ECMQVBasicAgreement.java
deleted file mode 100644
index 794f555b..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/agreement/ECMQVBasicAgreement.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package org.bouncycastle.crypto.agreement;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.BasicAgreement;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-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
- implements BasicAgreement
-{
- MQVPrivateParameters privParams;
-
- public void init(
- CipherParameters key)
- {
- this.privParams = (MQVPrivateParameters)key;
- }
-
- public int getFieldSize()
- {
- return (privParams.getStaticPrivateKey().getParameters().getCurve().getFieldSize() + 7) / 8;
- }
-
- public BigInteger calculateAgreement(CipherParameters pubKey)
- {
- MQVPublicParameters pubParams = (MQVPublicParameters)pubKey;
-
- ECPrivateKeyParameters staticPrivateKey = privParams.getStaticPrivateKey();
-
- ECPoint agreement = calculateMqvAgreement(staticPrivateKey.getParameters(), staticPrivateKey,
- privParams.getEphemeralPrivateKey(), privParams.getEphemeralPublicKey(),
- pubParams.getStaticPublicKey(), pubParams.getEphemeralPublicKey()).normalize();
-
- 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
- private ECPoint calculateMqvAgreement(
- ECDomainParameters parameters,
- ECPrivateKeyParameters d1U,
- ECPrivateKeyParameters d2U,
- ECPublicKeyParameters Q2U,
- ECPublicKeyParameters Q1V,
- ECPublicKeyParameters Q2V)
- {
- BigInteger n = parameters.getN();
- int e = (n.bitLength() + 1) / 2;
- BigInteger powE = ECConstants.ONE.shiftLeft(e);
-
- ECCurve curve = parameters.getCurve();
-
- 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).add(d2U.getD()).mod(n);
-
- BigInteger xPrime = q2v.getAffineXCoord().toBigInteger();
- BigInteger xPrimeBar = xPrime.mod(powE);
- BigInteger Q2VBar = xPrimeBar.setBit(e);
-
- BigInteger hs = parameters.getH().multiply(s).mod(n);
-
- return ECAlgorithms.sumOfTwoMultiplies(
- q1v, Q2VBar.multiply(hs).mod(n), q2v, hs);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKEParticipant.java b/core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKEParticipant.java
deleted file mode 100644
index 605b88ed..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKEParticipant.java
+++ /dev/null
@@ -1,546 +0,0 @@
-package org.bouncycastle.crypto.agreement.jpake;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.util.Arrays;
-
-/**
- * A participant in a Password Authenticated Key Exchange by Juggling (J-PAKE) exchange.
- * <p>
- * The J-PAKE exchange is defined by Feng Hao and Peter Ryan in the paper
- * <a href="http://grouper.ieee.org/groups/1363/Research/contributions/hao-ryan-2008.pdf">
- * "Password Authenticated Key Exchange by Juggling, 2008."</a>
- * <p>
- * The J-PAKE protocol is symmetric.
- * There is no notion of a <i>client</i> or <i>server</i>, but rather just two <i>participants</i>.
- * An instance of {@link JPAKEParticipant} represents one participant, and
- * is the primary interface for executing the exchange.
- * <p>
- * To execute an exchange, construct a {@link JPAKEParticipant} on each end,
- * and call the following 7 methods
- * (once and only once, in the given order, for each participant, sending messages between them as described):
- * <ol>
- * <li>{@link #createRound1PayloadToSend()} - and send the payload to the other participant</li>
- * <li>{@link #validateRound1PayloadReceived(JPAKERound1Payload)} - use the payload received from the other participant</li>
- * <li>{@link #createRound2PayloadToSend()} - and send the payload to the other participant</li>
- * <li>{@link #validateRound2PayloadReceived(JPAKERound2Payload)} - use the payload received from the other participant</li>
- * <li>{@link #calculateKeyingMaterial()}</li>
- * <li>{@link #createRound3PayloadToSend(BigInteger)} - and send the payload to the other participant</li>
- * <li>{@link #validateRound3PayloadReceived(JPAKERound3Payload, BigInteger)} - use the payload received from the other participant</li>
- * </ol>
- * <p>
- * Each side should derive a session key from the keying material returned by {@link #calculateKeyingMaterial()}.
- * The caller is responsible for deriving the session key using a secure key derivation function (KDF).
- * <p>
- * Round 3 is an optional key confirmation process.
- * If you do not execute round 3, then there is no assurance that both participants are using the same key.
- * (i.e. if the participants used different passwords, then their session keys will differ.)
- * <p>
- * If the round 3 validation succeeds, then the keys are guaranteed to be the same on both sides.
- * <p>
- * The symmetric design can easily support the asymmetric cases when one party initiates the communication.
- * e.g. Sometimes the round1 payload and round2 payload may be sent in one pass.
- * Also, in some cases, the key confirmation payload can be sent together with the round2 payload.
- * These are the trivial techniques to optimize the communication.
- * <p>
- * The key confirmation process is implemented as specified in
- * <a href="http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf">NIST SP 800-56A Revision 1</a>,
- * Section 8.2 Unilateral Key Confirmation for Key Agreement Schemes.
- * <p>
- * This class is stateful and NOT threadsafe.
- * Each instance should only be used for ONE complete J-PAKE exchange
- * (i.e. a new {@link JPAKEParticipant} should be constructed for each new J-PAKE exchange).
- * <p>
- * See {@link JPAKEExample} for example usage.
- */
-public class JPAKEParticipant
-{
- /*
- * Possible internal states. Used for state checking.
- */
-
- public static final int STATE_INITIALIZED = 0;
- public static final int STATE_ROUND_1_CREATED = 10;
- public static final int STATE_ROUND_1_VALIDATED = 20;
- public static final int STATE_ROUND_2_CREATED = 30;
- public static final int STATE_ROUND_2_VALIDATED = 40;
- public static final int STATE_KEY_CALCULATED = 50;
- public static final int STATE_ROUND_3_CREATED = 60;
- public static final int STATE_ROUND_3_VALIDATED = 70;
-
- /**
- * Unique identifier of this participant.
- * The two participants in the exchange must NOT share the same id.
- */
- private final String participantId;
-
- /**
- * Shared secret. This only contains the secret between construction
- * and the call to {@link #calculateKeyingMaterial()}.
- * <p/>
- * i.e. When {@link #calculateKeyingMaterial()} is called, this buffer overwritten with 0's,
- * and the field is set to null.
- */
- private char[] password;
-
- /**
- * Digest to use during calculations.
- */
- private final Digest digest;
-
- /**
- * Source of secure random data.
- */
- private final SecureRandom random;
-
- private final BigInteger p;
- private final BigInteger q;
- private final BigInteger g;
-
- /**
- * The participantId of the other participant in this exchange.
- */
- private String partnerParticipantId;
-
- /**
- * Alice's x1 or Bob's x3.
- */
- private BigInteger x1;
- /**
- * Alice's x2 or Bob's x4.
- */
- private BigInteger x2;
- /**
- * Alice's g^x1 or Bob's g^x3.
- */
- private BigInteger gx1;
- /**
- * Alice's g^x2 or Bob's g^x4.
- */
- private BigInteger gx2;
- /**
- * Alice's g^x3 or Bob's g^x1.
- */
- private BigInteger gx3;
- /**
- * Alice's g^x4 or Bob's g^x2.
- */
- private BigInteger gx4;
- /**
- * Alice's B or Bob's A.
- */
- private BigInteger b;
-
- /**
- * The current state.
- * See the <tt>STATE_*</tt> constants for possible values.
- */
- private int state;
-
- /**
- * Convenience constructor for a new {@link JPAKEParticipant} that uses
- * the {@link JPAKEPrimeOrderGroups#NIST_3072} prime order group,
- * a SHA-256 digest, and a default {@link SecureRandom} implementation.
- * <p>
- * After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}.
- *
- * @param participantId unique identifier of this participant.
- * The two participants in the exchange must NOT share the same id.
- * @param password shared secret.
- * A defensive copy of this array is made (and cleared once {@link #calculateKeyingMaterial()} is called).
- * Caller should clear the input password as soon as possible.
- * @throws NullPointerException if any argument is null
- * @throws IllegalArgumentException if password is empty
- */
- public JPAKEParticipant(
- String participantId,
- char[] password)
- {
- this(
- participantId,
- password,
- JPAKEPrimeOrderGroups.NIST_3072);
- }
-
-
- /**
- * Convenience constructor for a new {@link JPAKEParticipant} that uses
- * a SHA-256 digest and a default {@link SecureRandom} implementation.
- * <p>
- * After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}.
- *
- * @param participantId unique identifier of this participant.
- * The two participants in the exchange must NOT share the same id.
- * @param password shared secret.
- * A defensive copy of this array is made (and cleared once {@link #calculateKeyingMaterial()} is called).
- * Caller should clear the input password as soon as possible.
- * @param group prime order group.
- * See {@link JPAKEPrimeOrderGroups} for standard groups
- * @throws NullPointerException if any argument is null
- * @throws IllegalArgumentException if password is empty
- */
- public JPAKEParticipant(
- String participantId,
- char[] password,
- JPAKEPrimeOrderGroup group)
- {
- this(
- participantId,
- password,
- group,
- new SHA256Digest(),
- new SecureRandom());
- }
-
-
- /**
- * Construct a new {@link JPAKEParticipant}.
- * <p>
- * After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}.
- *
- * @param participantId unique identifier of this participant.
- * The two participants in the exchange must NOT share the same id.
- * @param password shared secret.
- * A defensive copy of this array is made (and cleared once {@link #calculateKeyingMaterial()} is called).
- * Caller should clear the input password as soon as possible.
- * @param group prime order group.
- * See {@link JPAKEPrimeOrderGroups} for standard groups
- * @param digest digest to use during zero knowledge proofs and key confirmation (SHA-256 or stronger preferred)
- * @param random source of secure random data for x1 and x2, and for the zero knowledge proofs
- * @throws NullPointerException if any argument is null
- * @throws IllegalArgumentException if password is empty
- */
- public JPAKEParticipant(
- String participantId,
- char[] password,
- JPAKEPrimeOrderGroup group,
- Digest digest,
- SecureRandom random)
- {
- JPAKEUtil.validateNotNull(participantId, "participantId");
- JPAKEUtil.validateNotNull(password, "password");
- JPAKEUtil.validateNotNull(group, "p");
- JPAKEUtil.validateNotNull(digest, "digest");
- JPAKEUtil.validateNotNull(random, "random");
- if (password.length == 0)
- {
- throw new IllegalArgumentException("Password must not be empty.");
- }
-
- this.participantId = participantId;
-
- /*
- * Create a defensive copy so as to fully encapsulate the password.
- *
- * This array will contain the password for the lifetime of this
- * participant BEFORE {@link #calculateKeyingMaterial()} is called.
- *
- * i.e. When {@link #calculateKeyingMaterial()} is called, the array will be cleared
- * in order to remove the password from memory.
- *
- * The caller is responsible for clearing the original password array
- * given as input to this constructor.
- */
- this.password = Arrays.copyOf(password, password.length);
-
- this.p = group.getP();
- this.q = group.getQ();
- this.g = group.getG();
-
- this.digest = digest;
- this.random = random;
-
- this.state = STATE_INITIALIZED;
- }
-
- /**
- * Gets the current state of this participant.
- * See the <tt>STATE_*</tt> constants for possible values.
- */
- public int getState()
- {
- return this.state;
- }
-
- /**
- * Creates and returns the payload to send to the other participant during round 1.
- * <p>
- * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_1_CREATED}.
- */
- public JPAKERound1Payload createRound1PayloadToSend()
- {
- if (this.state >= STATE_ROUND_1_CREATED)
- {
- throw new IllegalStateException("Round1 payload already created for " + participantId);
- }
-
- this.x1 = JPAKEUtil.generateX1(q, random);
- this.x2 = JPAKEUtil.generateX2(q, random);
-
- this.gx1 = JPAKEUtil.calculateGx(p, g, x1);
- this.gx2 = JPAKEUtil.calculateGx(p, g, x2);
- BigInteger[] knowledgeProofForX1 = JPAKEUtil.calculateZeroKnowledgeProof(p, q, g, gx1, x1, participantId, digest, random);
- BigInteger[] knowledgeProofForX2 = JPAKEUtil.calculateZeroKnowledgeProof(p, q, g, gx2, x2, participantId, digest, random);
-
- this.state = STATE_ROUND_1_CREATED;
-
- return new JPAKERound1Payload(participantId, gx1, gx2, knowledgeProofForX1, knowledgeProofForX2);
- }
-
- /**
- * Validates the payload received from the other participant during round 1.
- * <p>
- * Must be called prior to {@link #createRound2PayloadToSend()}.
- * <p>
- * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_1_VALIDATED}.
- *
- * @throws CryptoException if validation fails.
- * @throws IllegalStateException if called multiple times.
- */
- public void validateRound1PayloadReceived(JPAKERound1Payload round1PayloadReceived)
- throws CryptoException
- {
- if (this.state >= STATE_ROUND_1_VALIDATED)
- {
- throw new IllegalStateException("Validation already attempted for round1 payload for" + participantId);
- }
- this.partnerParticipantId = round1PayloadReceived.getParticipantId();
- this.gx3 = round1PayloadReceived.getGx1();
- this.gx4 = round1PayloadReceived.getGx2();
-
- BigInteger[] knowledgeProofForX3 = round1PayloadReceived.getKnowledgeProofForX1();
- BigInteger[] knowledgeProofForX4 = round1PayloadReceived.getKnowledgeProofForX2();
-
- JPAKEUtil.validateParticipantIdsDiffer(participantId, round1PayloadReceived.getParticipantId());
- JPAKEUtil.validateGx4(gx4);
- JPAKEUtil.validateZeroKnowledgeProof(p, q, g, gx3, knowledgeProofForX3, round1PayloadReceived.getParticipantId(), digest);
- JPAKEUtil.validateZeroKnowledgeProof(p, q, g, gx4, knowledgeProofForX4, round1PayloadReceived.getParticipantId(), digest);
-
- this.state = STATE_ROUND_1_VALIDATED;
- }
-
- /**
- * Creates and returns the payload to send to the other participant during round 2.
- * <p>
- * {@link #validateRound1PayloadReceived(JPAKERound1Payload)} must be called prior to this method.
- * <p>
- * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_2_CREATED}.
- *
- * @throws IllegalStateException if called prior to {@link #validateRound1PayloadReceived(JPAKERound1Payload)}, or multiple times
- */
- public JPAKERound2Payload createRound2PayloadToSend()
- {
- if (this.state >= STATE_ROUND_2_CREATED)
- {
- throw new IllegalStateException("Round2 payload already created for " + this.participantId);
- }
- if (this.state < STATE_ROUND_1_VALIDATED)
- {
- throw new IllegalStateException("Round1 payload must be validated prior to creating Round2 payload for " + this.participantId);
- }
- BigInteger gA = JPAKEUtil.calculateGA(p, gx1, gx3, gx4);
- BigInteger s = JPAKEUtil.calculateS(password);
- BigInteger x2s = JPAKEUtil.calculateX2s(q, x2, s);
- BigInteger A = JPAKEUtil.calculateA(p, q, gA, x2s);
- BigInteger[] knowledgeProofForX2s = JPAKEUtil.calculateZeroKnowledgeProof(p, q, gA, A, x2s, participantId, digest, random);
-
- this.state = STATE_ROUND_2_CREATED;
-
- return new JPAKERound2Payload(participantId, A, knowledgeProofForX2s);
- }
-
- /**
- * Validates the payload received from the other participant during round 2.
- * <p>
- * Note that this DOES NOT detect a non-common password.
- * The only indication of a non-common password is through derivation
- * of different keys (which can be detected explicitly by executing round 3 and round 4)
- * <p>
- * Must be called prior to {@link #calculateKeyingMaterial()}.
- * <p>
- * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_2_VALIDATED}.
- *
- * @throws CryptoException if validation fails.
- * @throws IllegalStateException if called prior to {@link #validateRound1PayloadReceived(JPAKERound1Payload)}, or multiple times
- */
- public void validateRound2PayloadReceived(JPAKERound2Payload round2PayloadReceived)
- throws CryptoException
- {
- if (this.state >= STATE_ROUND_2_VALIDATED)
- {
- throw new IllegalStateException("Validation already attempted for round2 payload for" + participantId);
- }
- if (this.state < STATE_ROUND_1_VALIDATED)
- {
- throw new IllegalStateException("Round1 payload must be validated prior to validating Round2 payload for " + this.participantId);
- }
- BigInteger gB = JPAKEUtil.calculateGA(p, gx3, gx1, gx2);
- this.b = round2PayloadReceived.getA();
- BigInteger[] knowledgeProofForX4s = round2PayloadReceived.getKnowledgeProofForX2s();
-
- JPAKEUtil.validateParticipantIdsDiffer(participantId, round2PayloadReceived.getParticipantId());
- JPAKEUtil.validateParticipantIdsEqual(this.partnerParticipantId, round2PayloadReceived.getParticipantId());
- JPAKEUtil.validateGa(gB);
- JPAKEUtil.validateZeroKnowledgeProof(p, q, gB, b, knowledgeProofForX4s, round2PayloadReceived.getParticipantId(), digest);
-
- this.state = STATE_ROUND_2_VALIDATED;
- }
-
- /**
- * Calculates and returns the key material.
- * A session key must be derived from this key material using a secure key derivation function (KDF).
- * The KDF used to derive the key is handled externally (i.e. not by {@link JPAKEParticipant}).
- * <p>
- * The keying material will be identical for each participant if and only if
- * each participant's password is the same. i.e. If the participants do not
- * share the same password, then each participant will derive a different key.
- * Therefore, if you immediately start using a key derived from
- * the keying material, then you must handle detection of incorrect keys.
- * If you want to handle this detection explicitly, you can optionally perform
- * rounds 3 and 4. See {@link JPAKEParticipant} for details on how to execute
- * rounds 3 and 4.
- * <p>
- * The keying material will be in the range <tt>[0, p-1]</tt>.
- * <p>
- * {@link #validateRound2PayloadReceived(JPAKERound2Payload)} must be called prior to this method.
- * <p>
- * As a side effect, the internal {@link #password} array is cleared, since it is no longer needed.
- * <p>
- * After execution, the {@link #getState() state} will be {@link #STATE_KEY_CALCULATED}.
- *
- * @throws IllegalStateException if called prior to {@link #validateRound2PayloadReceived(JPAKERound2Payload)},
- * or if called multiple times.
- */
- public BigInteger calculateKeyingMaterial()
- {
- if (this.state >= STATE_KEY_CALCULATED)
- {
- throw new IllegalStateException("Key already calculated for " + participantId);
- }
- if (this.state < STATE_ROUND_2_VALIDATED)
- {
- throw new IllegalStateException("Round2 payload must be validated prior to creating key for " + participantId);
- }
- BigInteger s = JPAKEUtil.calculateS(password);
-
- /*
- * Clear the password array from memory, since we don't need it anymore.
- *
- * Also set the field to null as a flag to indicate that the key has already been calculated.
- */
- Arrays.fill(password, (char)0);
- this.password = null;
-
- BigInteger keyingMaterial = JPAKEUtil.calculateKeyingMaterial(p, q, gx4, x2, s, b);
-
- /*
- * Clear the ephemeral private key fields as well.
- * Note that we're relying on the garbage collector to do its job to clean these up.
- * The old objects will hang around in memory until the garbage collector destroys them.
- *
- * If the ephemeral private keys x1 and x2 are leaked,
- * the attacker might be able to brute-force the password.
- */
- this.x1 = null;
- this.x2 = null;
- this.b = null;
-
- /*
- * Do not clear gx* yet, since those are needed by round 3.
- */
-
- this.state = STATE_KEY_CALCULATED;
-
- return keyingMaterial;
- }
-
-
- /**
- * Creates and returns the payload to send to the other participant during round 3.
- * <p>
- * See {@link JPAKEParticipant} for more details on round 3.
- * <p>
- * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_3_CREATED}.
- *
- * @param keyingMaterial The keying material as returned from {@link #calculateKeyingMaterial()}.
- * @throws IllegalStateException if called prior to {@link #calculateKeyingMaterial()}, or multiple times
- */
- public JPAKERound3Payload createRound3PayloadToSend(BigInteger keyingMaterial)
- {
- if (this.state >= STATE_ROUND_3_CREATED)
- {
- throw new IllegalStateException("Round3 payload already created for " + this.participantId);
- }
- if (this.state < STATE_KEY_CALCULATED)
- {
- throw new IllegalStateException("Keying material must be calculated prior to creating Round3 payload for " + this.participantId);
- }
-
- BigInteger macTag = JPAKEUtil.calculateMacTag(
- this.participantId,
- this.partnerParticipantId,
- this.gx1,
- this.gx2,
- this.gx3,
- this.gx4,
- keyingMaterial,
- this.digest);
-
- this.state = STATE_ROUND_3_CREATED;
-
- return new JPAKERound3Payload(participantId, macTag);
- }
-
- /**
- * Validates the payload received from the other participant during round 3.
- * <p>
- * See {@link JPAKEParticipant} for more details on round 3.
- * <p>
- * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_3_VALIDATED}.
- *
- * @param keyingMaterial The keying material as returned from {@link #calculateKeyingMaterial()}.
- * @throws CryptoException if validation fails.
- * @throws IllegalStateException if called prior to {@link #calculateKeyingMaterial()}, or multiple times
- */
- public void validateRound3PayloadReceived(JPAKERound3Payload round3PayloadReceived, BigInteger keyingMaterial)
- throws CryptoException
- {
- if (this.state >= STATE_ROUND_3_VALIDATED)
- {
- throw new IllegalStateException("Validation already attempted for round3 payload for" + participantId);
- }
- if (this.state < STATE_KEY_CALCULATED)
- {
- throw new IllegalStateException("Keying material must be calculated validated prior to validating Round3 payload for " + this.participantId);
- }
- JPAKEUtil.validateParticipantIdsDiffer(participantId, round3PayloadReceived.getParticipantId());
- JPAKEUtil.validateParticipantIdsEqual(this.partnerParticipantId, round3PayloadReceived.getParticipantId());
-
- JPAKEUtil.validateMacTag(
- this.participantId,
- this.partnerParticipantId,
- this.gx1,
- this.gx2,
- this.gx3,
- this.gx4,
- keyingMaterial,
- this.digest,
- round3PayloadReceived.getMacTag());
-
-
- /*
- * Clear the rest of the fields.
- */
- this.gx1 = null;
- this.gx2 = null;
- this.gx3 = null;
- this.gx4 = null;
-
- this.state = STATE_ROUND_3_VALIDATED;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java b/core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java
deleted file mode 100644
index ad2c6aea..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package org.bouncycastle.crypto.agreement.jpake;
-
-import java.math.BigInteger;
-
-/**
- * A pre-computed prime order group for use during a J-PAKE exchange.
- * <p>
- * Typically a Schnorr group is used. In general, J-PAKE can use any prime order group
- * that is suitable for public key cryptography, including elliptic curve cryptography.
- * <p>
- * See {@link JPAKEPrimeOrderGroups} for convenient standard groups.
- * <p>
- * NIST <a href="http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/DSA2_All.pdf">publishes</a>
- * many groups that can be used for the desired level of security.
- */
-public class JPAKEPrimeOrderGroup
-{
- private final BigInteger p;
- private final BigInteger q;
- private final BigInteger g;
-
- /**
- * Constructs a new {@link JPAKEPrimeOrderGroup}.
- * <p>
- * In general, you should use one of the pre-approved groups from
- * {@link JPAKEPrimeOrderGroups}, rather than manually constructing one.
- * <p>
- * The following basic checks are performed:
- * <ul>
- * <li>p-1 must be evenly divisible by q</li>
- * <li>g must be in [2, p-1]</li>
- * <li>g^q mod p must equal 1</li>
- * <li>p must be prime (within reasonably certainty)</li>
- * <li>q must be prime (within reasonably certainty)</li>
- * </ul>
- * <p>
- * The prime checks are performed using {@link BigInteger#isProbablePrime(int)},
- * and are therefore subject to the same probability guarantees.
- * <p>
- * These checks prevent trivial mistakes.
- * However, due to the small uncertainties if p and q are not prime,
- * advanced attacks are not prevented.
- * Use it at your own risk.
- *
- * @throws NullPointerException if any argument is null
- * @throws IllegalArgumentException if any of the above validations fail
- */
- public JPAKEPrimeOrderGroup(BigInteger p, BigInteger q, BigInteger g)
- {
- /*
- * Don't skip the checks on user-specified groups.
- */
- this(p, q, g, false);
- }
-
- /**
- * Internal package-private constructor used by the pre-approved
- * groups in {@link JPAKEPrimeOrderGroups}.
- * These pre-approved groups can avoid the expensive checks.
- */
- JPAKEPrimeOrderGroup(BigInteger p, BigInteger q, BigInteger g, boolean skipChecks)
- {
- JPAKEUtil.validateNotNull(p, "p");
- JPAKEUtil.validateNotNull(q, "q");
- JPAKEUtil.validateNotNull(g, "g");
-
- if (!skipChecks)
- {
- if (!p.subtract(JPAKEUtil.ONE).mod(q).equals(JPAKEUtil.ZERO))
- {
- throw new IllegalArgumentException("p-1 must be evenly divisible by q");
- }
- if (g.compareTo(BigInteger.valueOf(2)) == -1 || g.compareTo(p.subtract(JPAKEUtil.ONE)) == 1)
- {
- throw new IllegalArgumentException("g must be in [2, p-1]");
- }
- if (!g.modPow(q, p).equals(JPAKEUtil.ONE))
- {
- throw new IllegalArgumentException("g^q mod p must equal 1");
- }
- /*
- * Note that these checks do not guarantee that p and q are prime.
- * We just have reasonable certainty that they are prime.
- */
- if (!p.isProbablePrime(20))
- {
- throw new IllegalArgumentException("p must be prime");
- }
- if (!q.isProbablePrime(20))
- {
- throw new IllegalArgumentException("q must be prime");
- }
- }
-
- this.p = p;
- this.q = q;
- this.g = g;
- }
-
- public BigInteger getP()
- {
- return p;
- }
-
- public BigInteger getQ()
- {
- return q;
- }
-
- public BigInteger getG()
- {
- return g;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroups.java b/core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroups.java
deleted file mode 100644
index 2fb18613..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroups.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package org.bouncycastle.crypto.agreement.jpake;
-
-import java.math.BigInteger;
-
-/**
- * Standard pre-computed prime order groups for use by J-PAKE.
- * (J-PAKE can use pre-computed prime order groups, same as DSA and Diffie-Hellman.)
- * <p>
- * This class contains some convenient constants for use as input for
- * constructing {@link JPAKEParticipant}s.
- * <p>
- * The prime order groups below are taken from Sun's JDK JavaDoc (docs/guide/security/CryptoSpec.html#AppB),
- * and from the prime order groups
- * <a href="http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/DSA2_All.pdf">published by NIST</a>.
- */
-public class JPAKEPrimeOrderGroups
-{
- /**
- * From Sun's JDK JavaDoc (docs/guide/security/CryptoSpec.html#AppB)
- * 1024-bit p, 160-bit q and 1024-bit g for 80-bit security.
- */
- public static final JPAKEPrimeOrderGroup SUN_JCE_1024 = new JPAKEPrimeOrderGroup(
- // p
- new BigInteger(
- "fd7f53811d75122952df4a9c2eece4e7f611b7523cef4400c31e3f80b6512669" +
- "455d402251fb593d8d58fabfc5f5ba30f6cb9b556cd7813b801d346ff26660b7" +
- "6b9950a5a49f9fe8047b1022c24fbba9d7feb7c61bf83b57e7c6a8a6150f04fb" +
- "83f6d3c51ec3023554135a169132f675f3ae2b61d72aeff22203199dd14801c7", 16),
- // q
- new BigInteger(
- "9760508f15230bccb292b982a2eb840bf0581cf5", 16),
- // g
- new BigInteger(
- "f7e1a085d69b3ddecbbcab5c36b857b97994afbbfa3aea82f9574c0b3d078267" +
- "5159578ebad4594fe67107108180b449167123e84c281613b7cf09328cc8a6e1" +
- "3c167a8b547c8d28e0a3ae1e2bb3a675916ea37f0bfa213562f1fb627a01243b" +
- "cca4f1bea8519089a883dfe15ae59f06928b665e807b552564014c3bfecf492a", 16),
- true
- );
-
- /**
- * From NIST.
- * 2048-bit p, 224-bit q and 2048-bit g for 112-bit security.
- */
- public static final JPAKEPrimeOrderGroup NIST_2048 = new JPAKEPrimeOrderGroup(
- // p
- new BigInteger(
- "C196BA05AC29E1F9C3C72D56DFFC6154A033F1477AC88EC37F09BE6C5BB95F51" +
- "C296DD20D1A28A067CCC4D4316A4BD1DCA55ED1066D438C35AEBAABF57E7DAE4" +
- "28782A95ECA1C143DB701FD48533A3C18F0FE23557EA7AE619ECACC7E0B51652" +
- "A8776D02A425567DED36EABD90CA33A1E8D988F0BBB92D02D1D20290113BB562" +
- "CE1FC856EEB7CDD92D33EEA6F410859B179E7E789A8F75F645FAE2E136D252BF" +
- "FAFF89528945C1ABE705A38DBC2D364AADE99BE0D0AAD82E5320121496DC65B3" +
- "930E38047294FF877831A16D5228418DE8AB275D7D75651CEFED65F78AFC3EA7" +
- "FE4D79B35F62A0402A1117599ADAC7B269A59F353CF450E6982D3B1702D9CA83", 16),
- // q
- new BigInteger(
- "90EAF4D1AF0708B1B612FF35E0A2997EB9E9D263C9CE659528945C0D", 16),
- // g
- new BigInteger(
- "A59A749A11242C58C894E9E5A91804E8FA0AC64B56288F8D47D51B1EDC4D6544" +
- "4FECA0111D78F35FC9FDD4CB1F1B79A3BA9CBEE83A3F811012503C8117F98E50" +
- "48B089E387AF6949BF8784EBD9EF45876F2E6A5A495BE64B6E770409494B7FEE" +
- "1DBB1E4B2BC2A53D4F893D418B7159592E4FFFDF6969E91D770DAEBD0B5CB14C" +
- "00AD68EC7DC1E5745EA55C706C4A1C5C88964E34D09DEB753AD418C1AD0F4FDF" +
- "D049A955E5D78491C0B7A2F1575A008CCD727AB376DB6E695515B05BD412F5B8" +
- "C2F4C77EE10DA48ABD53F5DD498927EE7B692BBBCDA2FB23A516C5B4533D7398" +
- "0B2A3B60E384ED200AE21B40D273651AD6060C13D97FD69AA13C5611A51B9085", 16),
- true
- );
-
- /**
- * From NIST.
- * 3072-bit p, 256-bit q and 3072-bit g for 128-bit security.
- */
- public static final JPAKEPrimeOrderGroup NIST_3072 = new JPAKEPrimeOrderGroup(
- // p
- new BigInteger(
- "90066455B5CFC38F9CAA4A48B4281F292C260FEEF01FD61037E56258A7795A1C" +
- "7AD46076982CE6BB956936C6AB4DCFE05E6784586940CA544B9B2140E1EB523F" +
- "009D20A7E7880E4E5BFA690F1B9004A27811CD9904AF70420EEFD6EA11EF7DA1" +
- "29F58835FF56B89FAA637BC9AC2EFAAB903402229F491D8D3485261CD068699B" +
- "6BA58A1DDBBEF6DB51E8FE34E8A78E542D7BA351C21EA8D8F1D29F5D5D159394" +
- "87E27F4416B0CA632C59EFD1B1EB66511A5A0FBF615B766C5862D0BD8A3FE7A0" +
- "E0DA0FB2FE1FCB19E8F9996A8EA0FCCDE538175238FC8B0EE6F29AF7F642773E" +
- "BE8CD5402415A01451A840476B2FCEB0E388D30D4B376C37FE401C2A2C2F941D" +
- "AD179C540C1C8CE030D460C4D983BE9AB0B20F69144C1AE13F9383EA1C08504F" +
- "B0BF321503EFE43488310DD8DC77EC5B8349B8BFE97C2C560EA878DE87C11E3D" +
- "597F1FEA742D73EEC7F37BE43949EF1A0D15C3F3E3FC0A8335617055AC91328E" +
- "C22B50FC15B941D3D1624CD88BC25F3E941FDDC6200689581BFEC416B4B2CB73", 16),
- // q
- new BigInteger(
- "CFA0478A54717B08CE64805B76E5B14249A77A4838469DF7F7DC987EFCCFB11D", 16),
- // g
- new BigInteger(
- "5E5CBA992E0A680D885EB903AEA78E4A45A469103D448EDE3B7ACCC54D521E37" +
- "F84A4BDD5B06B0970CC2D2BBB715F7B82846F9A0C393914C792E6A923E2117AB" +
- "805276A975AADB5261D91673EA9AAFFEECBFA6183DFCB5D3B7332AA19275AFA1" +
- "F8EC0B60FB6F66CC23AE4870791D5982AAD1AA9485FD8F4A60126FEB2CF05DB8" +
- "A7F0F09B3397F3937F2E90B9E5B9C9B6EFEF642BC48351C46FB171B9BFA9EF17" +
- "A961CE96C7E7A7CC3D3D03DFAD1078BA21DA425198F07D2481622BCE45969D9C" +
- "4D6063D72AB7A0F08B2F49A7CC6AF335E08C4720E31476B67299E231F8BD90B3" +
- "9AC3AE3BE0C6B6CACEF8289A2E2873D58E51E029CAFBD55E6841489AB66B5B4B" +
- "9BA6E2F784660896AFF387D92844CCB8B69475496DE19DA2E58259B090489AC8" +
- "E62363CDF82CFD8EF2A427ABCD65750B506F56DDE3B988567A88126B914D7828" +
- "E2B63A6D7ED0747EC59E0E0A23CE7D8A74C1D2C2A7AFB6A29799620F00E11C33" +
- "787F7DED3B30E1A22D09F1FBDA1ABBBFBF25CAE05A13F812E34563F99410E73B", 16),
- true
- );
-
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKERound1Payload.java b/core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKERound1Payload.java
deleted file mode 100644
index 086196dd..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKERound1Payload.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.bouncycastle.crypto.agreement.jpake;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * The payload sent/received during the first round of a J-PAKE exchange.
- * <p>
- * Each {@link JPAKEParticipant} creates and sends an instance
- * of this payload to the other {@link JPAKEParticipant}.
- * The payload to send should be created via
- * {@link JPAKEParticipant#createRound1PayloadToSend()}.
- * <p>
- * Each {@link JPAKEParticipant} must also validate the payload
- * received from the other {@link JPAKEParticipant}.
- * The received payload should be validated via
- * {@link JPAKEParticipant#validateRound1PayloadReceived(JPAKERound1Payload)}.
- */
-public class JPAKERound1Payload
-{
- /**
- * The id of the {@link JPAKEParticipant} who created/sent this payload.
- */
- private final String participantId;
-
- /**
- * The value of g^x1
- */
- private final BigInteger gx1;
-
- /**
- * The value of g^x2
- */
- private final BigInteger gx2;
-
- /**
- * The zero knowledge proof for x1.
- * <p/>
- * This is a two element array, containing {g^v, r} for x1.
- */
- private final BigInteger[] knowledgeProofForX1;
-
- /**
- * The zero knowledge proof for x2.
- * <p/>
- * This is a two element array, containing {g^v, r} for x2.
- */
- private final BigInteger[] knowledgeProofForX2;
-
- public JPAKERound1Payload(
- String participantId,
- BigInteger gx1,
- BigInteger gx2,
- BigInteger[] knowledgeProofForX1,
- BigInteger[] knowledgeProofForX2)
- {
- JPAKEUtil.validateNotNull(participantId, "participantId");
- JPAKEUtil.validateNotNull(gx1, "gx1");
- JPAKEUtil.validateNotNull(gx2, "gx2");
- JPAKEUtil.validateNotNull(knowledgeProofForX1, "knowledgeProofForX1");
- JPAKEUtil.validateNotNull(knowledgeProofForX2, "knowledgeProofForX2");
-
- this.participantId = participantId;
- this.gx1 = gx1;
- this.gx2 = gx2;
- this.knowledgeProofForX1 = Arrays.copyOf(knowledgeProofForX1, knowledgeProofForX1.length);
- this.knowledgeProofForX2 = Arrays.copyOf(knowledgeProofForX2, knowledgeProofForX2.length);
- }
-
- public String getParticipantId()
- {
- return participantId;
- }
-
- public BigInteger getGx1()
- {
- return gx1;
- }
-
- public BigInteger getGx2()
- {
- return gx2;
- }
-
- public BigInteger[] getKnowledgeProofForX1()
- {
- return Arrays.copyOf(knowledgeProofForX1, knowledgeProofForX1.length);
- }
-
- public BigInteger[] getKnowledgeProofForX2()
- {
- return Arrays.copyOf(knowledgeProofForX2, knowledgeProofForX2.length);
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKERound2Payload.java b/core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKERound2Payload.java
deleted file mode 100644
index e047443e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKERound2Payload.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.bouncycastle.crypto.agreement.jpake;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * The payload sent/received during the second round of a J-PAKE exchange.
- * <p>
- * Each {@link JPAKEParticipant} creates and sends an instance
- * of this payload to the other {@link JPAKEParticipant}.
- * The payload to send should be created via
- * {@link JPAKEParticipant#createRound2PayloadToSend()}
- * <p>
- * Each {@link JPAKEParticipant} must also validate the payload
- * received from the other {@link JPAKEParticipant}.
- * The received payload should be validated via
- * {@link JPAKEParticipant#validateRound2PayloadReceived(JPAKERound2Payload)}
- */
-public class JPAKERound2Payload
-{
- /**
- * The id of the {@link JPAKEParticipant} who created/sent this payload.
- */
- private final String participantId;
-
- /**
- * The value of A, as computed during round 2.
- */
- private final BigInteger a;
-
- /**
- * The zero knowledge proof for x2 * s.
- * <p/>
- * This is a two element array, containing {g^v, r} for x2 * s.
- */
- private final BigInteger[] knowledgeProofForX2s;
-
- public JPAKERound2Payload(
- String participantId,
- BigInteger a,
- BigInteger[] knowledgeProofForX2s)
- {
- JPAKEUtil.validateNotNull(participantId, "participantId");
- JPAKEUtil.validateNotNull(a, "a");
- JPAKEUtil.validateNotNull(knowledgeProofForX2s, "knowledgeProofForX2s");
-
- this.participantId = participantId;
- this.a = a;
- this.knowledgeProofForX2s = Arrays.copyOf(knowledgeProofForX2s, knowledgeProofForX2s.length);
- }
-
- public String getParticipantId()
- {
- return participantId;
- }
-
- public BigInteger getA()
- {
- return a;
- }
-
- public BigInteger[] getKnowledgeProofForX2s()
- {
- return Arrays.copyOf(knowledgeProofForX2s, knowledgeProofForX2s.length);
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKERound3Payload.java b/core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKERound3Payload.java
deleted file mode 100644
index 0fe1cba9..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKERound3Payload.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package org.bouncycastle.crypto.agreement.jpake;
-
-import java.math.BigInteger;
-
-/**
- * The payload sent/received during the optional third round of a J-PAKE exchange,
- * which is for explicit key confirmation.
- * <p>
- * Each {@link JPAKEParticipant} creates and sends an instance
- * of this payload to the other {@link JPAKEParticipant}.
- * The payload to send should be created via
- * {@link JPAKEParticipant#createRound3PayloadToSend(BigInteger)}
- * <p>
- * Each {@link JPAKEParticipant} must also validate the payload
- * received from the other {@link JPAKEParticipant}.
- * The received payload should be validated via
- * {@link JPAKEParticipant#validateRound3PayloadReceived(JPAKERound3Payload, BigInteger)}
- */
-public class JPAKERound3Payload
-{
- /**
- * The id of the {@link JPAKEParticipant} who created/sent this payload.
- */
- private final String participantId;
-
- /**
- * The value of MacTag, as computed by round 3.
- *
- * @see JPAKEUtil#calculateMacTag(String, String, BigInteger, BigInteger, BigInteger, BigInteger, BigInteger, org.bouncycastle.crypto.Digest)
- */
- private final BigInteger macTag;
-
- public JPAKERound3Payload(String participantId, BigInteger magTag)
- {
- this.participantId = participantId;
- this.macTag = magTag;
- }
-
- public String getParticipantId()
- {
- return participantId;
- }
-
- public BigInteger getMacTag()
- {
- return macTag;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKEUtil.java b/core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKEUtil.java
deleted file mode 100644
index 0a6c5fe4..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/agreement/jpake/JPAKEUtil.java
+++ /dev/null
@@ -1,495 +0,0 @@
-package org.bouncycastle.crypto.agreement.jpake;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.macs.HMac;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.BigIntegers;
-import org.bouncycastle.util.Strings;
-
-/**
- * Primitives needed for a J-PAKE exchange.
- * <p>
- * The recommended way to perform a J-PAKE exchange is by using
- * two {@link JPAKEParticipant}s. Internally, those participants
- * call these primitive operations in {@link JPAKEUtil}.
- * <p>
- * The primitives, however, can be used without a {@link JPAKEParticipant}
- * if needed.
- */
-public class JPAKEUtil
-{
- static final BigInteger ZERO = BigInteger.valueOf(0);
- static final BigInteger ONE = BigInteger.valueOf(1);
-
- /**
- * Return a value that can be used as x1 or x3 during round 1.
- * <p>
- * The returned value is a random value in the range <tt>[0, q-1]</tt>.
- */
- public static BigInteger generateX1(
- BigInteger q,
- SecureRandom random)
- {
- BigInteger min = ZERO;
- BigInteger max = q.subtract(ONE);
- return BigIntegers.createRandomInRange(min, max, random);
- }
-
- /**
- * Return a value that can be used as x2 or x4 during round 1.
- * <p>
- * The returned value is a random value in the range <tt>[1, q-1]</tt>.
- */
- public static BigInteger generateX2(
- BigInteger q,
- SecureRandom random)
- {
- BigInteger min = ONE;
- BigInteger max = q.subtract(ONE);
- return BigIntegers.createRandomInRange(min, max, random);
- }
-
- /**
- * Converts the given password to a {@link BigInteger}
- * for use in arithmetic calculations.
- */
- public static BigInteger calculateS(char[] password)
- {
- return new BigInteger(Strings.toUTF8ByteArray(password));
- }
-
- /**
- * Calculate g^x mod p as done in round 1.
- */
- public static BigInteger calculateGx(
- BigInteger p,
- BigInteger g,
- BigInteger x)
- {
- return g.modPow(x, p);
- }
-
-
- /**
- * Calculate ga as done in round 2.
- */
- public static BigInteger calculateGA(
- BigInteger p,
- BigInteger gx1,
- BigInteger gx3,
- BigInteger gx4)
- {
- // ga = g^(x1+x3+x4) = g^x1 * g^x3 * g^x4
- return gx1.multiply(gx3).multiply(gx4).mod(p);
- }
-
-
- /**
- * Calculate x2 * s as done in round 2.
- */
- public static BigInteger calculateX2s(
- BigInteger q,
- BigInteger x2,
- BigInteger s)
- {
- return x2.multiply(s).mod(q);
- }
-
-
- /**
- * Calculate A as done in round 2.
- */
- public static BigInteger calculateA(
- BigInteger p,
- BigInteger q,
- BigInteger gA,
- BigInteger x2s)
- {
- // A = ga^(x*s)
- return gA.modPow(x2s, p);
- }
-
- /**
- * Calculate a zero knowledge proof of x using Schnorr's signature.
- * The returned array has two elements {g^v, r = v-x*h} for x.
- */
- public static BigInteger[] calculateZeroKnowledgeProof(
- BigInteger p,
- BigInteger q,
- BigInteger g,
- BigInteger gx,
- BigInteger x,
- String participantId,
- Digest digest,
- SecureRandom random)
- {
- BigInteger[] zeroKnowledgeProof = new BigInteger[2];
-
- /* Generate a random v, and compute g^v */
- BigInteger vMin = ZERO;
- BigInteger vMax = q.subtract(ONE);
- BigInteger v = BigIntegers.createRandomInRange(vMin, vMax, random);
-
- BigInteger gv = g.modPow(v, p);
- BigInteger h = calculateHashForZeroKnowledgeProof(g, gv, gx, participantId, digest); // h
-
- zeroKnowledgeProof[0] = gv;
- zeroKnowledgeProof[1] = v.subtract(x.multiply(h)).mod(q); // r = v-x*h
-
- return zeroKnowledgeProof;
- }
-
- private static BigInteger calculateHashForZeroKnowledgeProof(
- BigInteger g,
- BigInteger gr,
- BigInteger gx,
- String participantId,
- Digest digest)
- {
- digest.reset();
-
- updateDigestIncludingSize(digest, g);
-
- updateDigestIncludingSize(digest, gr);
-
- updateDigestIncludingSize(digest, gx);
-
- updateDigestIncludingSize(digest, participantId);
-
- byte[] output = new byte[digest.getDigestSize()];
- digest.doFinal(output, 0);
-
- return new BigInteger(output);
- }
-
- /**
- * Validates that g^x4 is not 1.
- *
- * @throws CryptoException if g^x4 is 1
- */
- public static void validateGx4(BigInteger gx4)
- throws CryptoException
- {
- if (gx4.equals(ONE))
- {
- throw new CryptoException("g^x validation failed. g^x should not be 1.");
- }
- }
-
- /**
- * Validates that ga is not 1.
- * <p>
- * As described by Feng Hao...
- * <p>
- * <blockquote>
- * Alice could simply check ga != 1 to ensure it is a generator.
- * In fact, as we will explain in Section 3, (x1 + x3 + x4 ) is random over Zq even in the face of active attacks.
- * Hence, the probability for ga = 1 is extremely small - on the order of 2^160 for 160-bit q.
- * </blockquote>
- *
- * @throws CryptoException if ga is 1
- */
- public static void validateGa(BigInteger ga)
- throws CryptoException
- {
- if (ga.equals(ONE))
- {
- throw new CryptoException("ga is equal to 1. It should not be. The chances of this happening are on the order of 2^160 for a 160-bit q. Try again.");
- }
- }
-
- /**
- * Validates the zero knowledge proof (generated by
- * {@link #calculateZeroKnowledgeProof(BigInteger, BigInteger, BigInteger, BigInteger, BigInteger, String, Digest, SecureRandom)})
- * is correct.
- *
- * @throws CryptoException if the zero knowledge proof is not correct
- */
- public static void validateZeroKnowledgeProof(
- BigInteger p,
- BigInteger q,
- BigInteger g,
- BigInteger gx,
- BigInteger[] zeroKnowledgeProof,
- String participantId,
- Digest digest)
- throws CryptoException
- {
-
- /* sig={g^v,r} */
- BigInteger gv = zeroKnowledgeProof[0];
- BigInteger r = zeroKnowledgeProof[1];
-
- BigInteger h = calculateHashForZeroKnowledgeProof(g, gv, gx, participantId, digest);
- if (!(gx.compareTo(ZERO) == 1 && // g^x > 0
- gx.compareTo(p) == -1 && // g^x < p
- gx.modPow(q, p).compareTo(ONE) == 0 && // g^x^q mod q = 1
- /*
- * Below, I took an straightforward way to compute g^r * g^x^h,
- * which needs 2 exp. Using a simultaneous computation technique
- * would only need 1 exp.
- */
- g.modPow(r, p).multiply(gx.modPow(h, p)).mod(p).compareTo(gv) == 0)) // g^v=g^r * g^x^h
- {
- throw new CryptoException("Zero-knowledge proof validation failed");
- }
- }
-
- /**
- * Calculates the keying material, which can be done after round 2 has completed.
- * A session key must be derived from this key material using a secure key derivation function (KDF).
- * The KDF used to derive the key is handled externally (i.e. not by {@link JPAKEParticipant}).
- * <pre>
- * KeyingMaterial = (B/g^{x2*x4*s})^x2
- * </pre>
- */
- public static BigInteger calculateKeyingMaterial(
- BigInteger p,
- BigInteger q,
- BigInteger gx4,
- BigInteger x2,
- BigInteger s,
- BigInteger B)
- {
- return gx4.modPow(x2.multiply(s).negate().mod(q), p).multiply(B).modPow(x2, p);
- }
-
- /**
- * Validates that the given participant ids are not equal.
- * (For the J-PAKE exchange, each participant must use a unique id.)
- *
- * @throws CryptoException if the participantId strings are equal.
- */
- public static void validateParticipantIdsDiffer(String participantId1, String participantId2)
- throws CryptoException
- {
- if (participantId1.equals(participantId2))
- {
- throw new CryptoException(
- "Both participants are using the same participantId ("
- + participantId1
- + "). This is not allowed. "
- + "Each participant must use a unique participantId.");
- }
- }
-
- /**
- * Validates that the given participant ids are equal.
- * This is used to ensure that the payloads received from
- * each round all come from the same participant.
- *
- * @throws CryptoException if the participantId strings are equal.
- */
- public static void validateParticipantIdsEqual(String expectedParticipantId, String actualParticipantId)
- throws CryptoException
- {
- if (!expectedParticipantId.equals(actualParticipantId))
- {
- throw new CryptoException(
- "Received payload from incorrect partner ("
- + actualParticipantId
- + "). Expected to receive payload from "
- + expectedParticipantId
- + ".");
- }
- }
-
- /**
- * Validates that the given object is not null.
- *
- * @param object object in question
- * @param description name of the object (to be used in exception message)
- * @throws NullPointerException if the object is null.
- */
- public static void validateNotNull(Object object, String description)
- {
- if (object == null)
- {
- throw new NullPointerException(description + " must not be null");
- }
- }
-
- /**
- * Calculates the MacTag (to be used for key confirmation), as defined by
- * <a href="http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf">NIST SP 800-56A Revision 1</a>,
- * Section 8.2 Unilateral Key Confirmation for Key Agreement Schemes.
- * <pre>
- * MacTag = HMAC(MacKey, MacLen, MacData)
- *
- * MacKey = H(K || "JPAKE_KC")
- *
- * MacData = "KC_1_U" || participantId || partnerParticipantId || gx1 || gx2 || gx3 || gx4
- *
- * Note that both participants use "KC_1_U" because the sender of the round 3 message
- * is always the initiator for key confirmation.
- *
- * HMAC = {@link HMac} used with the given {@link Digest}
- * H = The given {@link Digest}
- * MacLen = length of MacTag
- * </pre>
- */
- public static BigInteger calculateMacTag(
- String participantId,
- String partnerParticipantId,
- BigInteger gx1,
- BigInteger gx2,
- BigInteger gx3,
- BigInteger gx4,
- BigInteger keyingMaterial,
- Digest digest)
- {
- byte[] macKey = calculateMacKey(
- keyingMaterial,
- digest);
-
- HMac mac = new HMac(digest);
- byte[] macOutput = new byte[mac.getMacSize()];
- mac.init(new KeyParameter(macKey));
-
- /*
- * MacData = "KC_1_U" || participantId_Alice || participantId_Bob || gx1 || gx2 || gx3 || gx4.
- */
- updateMac(mac, "KC_1_U");
- updateMac(mac, participantId);
- updateMac(mac, partnerParticipantId);
- updateMac(mac, gx1);
- updateMac(mac, gx2);
- updateMac(mac, gx3);
- updateMac(mac, gx4);
-
- mac.doFinal(macOutput, 0);
-
- Arrays.fill(macKey, (byte)0);
-
- return new BigInteger(macOutput);
-
- }
-
- /**
- * Calculates the MacKey (i.e. the key to use when calculating the MagTag for key confirmation).
- * <pre>
- * MacKey = H(K || "JPAKE_KC")
- * </pre>
- */
- private static byte[] calculateMacKey(BigInteger keyingMaterial, Digest digest)
- {
- digest.reset();
-
- updateDigest(digest, keyingMaterial);
- /*
- * This constant is used to ensure that the macKey is NOT the same as the derived key.
- */
- updateDigest(digest, "JPAKE_KC");
-
- byte[] output = new byte[digest.getDigestSize()];
- digest.doFinal(output, 0);
-
- return output;
- }
-
- /**
- * Validates the MacTag received from the partner participant.
- *
- * @param partnerMacTag the MacTag received from the partner.
- * @throws CryptoException if the participantId strings are equal.
- */
- public static void validateMacTag(
- String participantId,
- String partnerParticipantId,
- BigInteger gx1,
- BigInteger gx2,
- BigInteger gx3,
- BigInteger gx4,
- BigInteger keyingMaterial,
- Digest digest,
- BigInteger partnerMacTag)
- throws CryptoException
- {
- /*
- * Calculate the expected MacTag using the parameters as the partner
- * would have used when the partner called calculateMacTag.
- *
- * i.e. basically all the parameters are reversed.
- * participantId <-> partnerParticipantId
- * x1 <-> x3
- * x2 <-> x4
- */
- BigInteger expectedMacTag = calculateMacTag(
- partnerParticipantId,
- participantId,
- gx3,
- gx4,
- gx1,
- gx2,
- keyingMaterial,
- digest);
-
- if (!expectedMacTag.equals(partnerMacTag))
- {
- throw new CryptoException(
- "Partner MacTag validation failed. "
- + "Therefore, the password, MAC, or digest algorithm of each participant does not match.");
- }
- }
-
- private static void updateDigest(Digest digest, BigInteger bigInteger)
- {
- byte[] byteArray = BigIntegers.asUnsignedByteArray(bigInteger);
- digest.update(byteArray, 0, byteArray.length);
- Arrays.fill(byteArray, (byte)0);
- }
-
- private static void updateDigestIncludingSize(Digest digest, BigInteger bigInteger)
- {
- byte[] byteArray = BigIntegers.asUnsignedByteArray(bigInteger);
- digest.update(intToByteArray(byteArray.length), 0, 4);
- digest.update(byteArray, 0, byteArray.length);
- Arrays.fill(byteArray, (byte)0);
- }
-
- private static void updateDigest(Digest digest, String string)
- {
- byte[] byteArray = Strings.toUTF8ByteArray(string);
- digest.update(byteArray, 0, byteArray.length);
- Arrays.fill(byteArray, (byte)0);
- }
-
- private static void updateDigestIncludingSize(Digest digest, String string)
- {
- byte[] byteArray = Strings.toUTF8ByteArray(string);
- digest.update(intToByteArray(byteArray.length), 0, 4);
- digest.update(byteArray, 0, byteArray.length);
- Arrays.fill(byteArray, (byte)0);
- }
-
- private static void updateMac(Mac mac, BigInteger bigInteger)
- {
- byte[] byteArray = BigIntegers.asUnsignedByteArray(bigInteger);
- mac.update(byteArray, 0, byteArray.length);
- Arrays.fill(byteArray, (byte)0);
- }
-
- private static void updateMac(Mac mac, String string)
- {
- byte[] byteArray = Strings.toUTF8ByteArray(string);
- mac.update(byteArray, 0, byteArray.length);
- Arrays.fill(byteArray, (byte)0);
- }
-
- private static byte[] intToByteArray(int value)
- {
- return new byte[]{
- (byte)(value >>> 24),
- (byte)(value >>> 16),
- (byte)(value >>> 8),
- (byte)value
- };
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/agreement/kdf/DHKDFParameters.java b/core/src/main/java/org/bouncycastle/crypto/agreement/kdf/DHKDFParameters.java
deleted file mode 100644
index 315c5486..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/agreement/kdf/DHKDFParameters.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.bouncycastle.crypto.agreement.kdf;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.crypto.DerivationParameters;
-
-public class DHKDFParameters
- implements DerivationParameters
-{
- private ASN1ObjectIdentifier algorithm;
- private int keySize;
- private byte[] z;
- private byte[] extraInfo;
-
- public DHKDFParameters(
- ASN1ObjectIdentifier algorithm,
- int keySize,
- byte[] z)
- {
- this(algorithm, keySize, z, null);
- }
-
- public DHKDFParameters(
- ASN1ObjectIdentifier algorithm,
- int keySize,
- byte[] z,
- byte[] extraInfo)
- {
- this.algorithm = algorithm;
- this.keySize = keySize;
- this.z = z;
- this.extraInfo = extraInfo;
- }
-
- public ASN1ObjectIdentifier getAlgorithm()
- {
- return algorithm;
- }
-
- public int getKeySize()
- {
- return keySize;
- }
-
- public byte[] getZ()
- {
- return z;
- }
-
- public byte[] getExtraInfo()
- {
- return extraInfo;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/agreement/kdf/DHKEKGenerator.java b/core/src/main/java/org/bouncycastle/crypto/agreement/kdf/DHKEKGenerator.java
deleted file mode 100644
index 6feb5076..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/agreement/kdf/DHKEKGenerator.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package org.bouncycastle.crypto.agreement.kdf;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Encoding;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.DerivationFunction;
-import org.bouncycastle.crypto.DerivationParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.util.Pack;
-
-/**
- * RFC 2631 Diffie-hellman KEK derivation function.
- */
-public class DHKEKGenerator
- implements DerivationFunction
-{
- private final Digest digest;
-
- private ASN1ObjectIdentifier algorithm;
- private int keySize;
- private byte[] z;
- private byte[] partyAInfo;
-
- public DHKEKGenerator(
- Digest digest)
- {
- this.digest = digest;
- }
-
- public void init(DerivationParameters param)
- {
- DHKDFParameters params = (DHKDFParameters)param;
-
- this.algorithm = params.getAlgorithm();
- this.keySize = params.getKeySize();
- this.z = params.getZ();
- this.partyAInfo = params.getExtraInfo();
- }
-
- public Digest getDigest()
- {
- return digest;
- }
-
- public int generateBytes(byte[] out, int outOff, int len)
- throws DataLengthException, IllegalArgumentException
- {
- if ((out.length - len) < outOff)
- {
- throw new DataLengthException("output buffer too small");
- }
-
- long oBytes = len;
- int outLen = digest.getDigestSize();
-
- //
- // this is at odds with the standard implementation, the
- // maximum value should be hBits * (2^32 - 1) where hBits
- // is the digest output size in bits. We can't have an
- // array with a long index at the moment...
- //
- if (oBytes > ((2L << 32) - 1))
- {
- throw new IllegalArgumentException("Output length too large");
- }
-
- int cThreshold = (int)((oBytes + outLen - 1) / outLen);
-
- byte[] dig = new byte[digest.getDigestSize()];
-
- int counter = 1;
-
- for (int i = 0; i < cThreshold; i++)
- {
- digest.update(z, 0, z.length);
-
- // OtherInfo
- ASN1EncodableVector v1 = new ASN1EncodableVector();
- // KeySpecificInfo
- ASN1EncodableVector v2 = new ASN1EncodableVector();
-
- v2.add(algorithm);
- v2.add(new DEROctetString(Pack.intToBigEndian(counter)));
-
- v1.add(new DERSequence(v2));
-
- if (partyAInfo != null)
- {
- v1.add(new DERTaggedObject(true, 0, new DEROctetString(partyAInfo)));
- }
-
- v1.add(new DERTaggedObject(true, 2, new DEROctetString(Pack.intToBigEndian(keySize))));
-
- try
- {
- byte[] other = new DERSequence(v1).getEncoded(ASN1Encoding.DER);
-
- digest.update(other, 0, other.length);
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("unable to encode parameter info: " + e.getMessage());
- }
-
- digest.doFinal(dig, 0);
-
- if (len > outLen)
- {
- System.arraycopy(dig, 0, out, outOff, outLen);
- outOff += outLen;
- len -= outLen;
- }
- else
- {
- System.arraycopy(dig, 0, out, outOff, len);
- }
-
- counter++;
- }
-
- digest.reset();
-
- return (int)oBytes;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/agreement/kdf/ECDHKEKGenerator.java b/core/src/main/java/org/bouncycastle/crypto/agreement/kdf/ECDHKEKGenerator.java
deleted file mode 100644
index 5d15b992..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/agreement/kdf/ECDHKEKGenerator.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package org.bouncycastle.crypto.agreement.kdf;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Encoding;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.DEROctetString;
-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.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.util.Pack;
-
-/**
- * X9.63 based key derivation function for ECDH CMS.
- */
-public class ECDHKEKGenerator
- implements DigestDerivationFunction
-{
- private DigestDerivationFunction kdf;
-
- private ASN1ObjectIdentifier algorithm;
- private int keySize;
- private byte[] z;
-
- public ECDHKEKGenerator(
- Digest digest)
- {
- this.kdf = new KDF2BytesGenerator(digest);
- }
-
- public void init(DerivationParameters param)
- {
- DHKDFParameters params = (DHKDFParameters)param;
-
- this.algorithm = params.getAlgorithm();
- this.keySize = params.getKeySize();
- this.z = params.getZ();
- }
-
- public Digest getDigest()
- {
- return kdf.getDigest();
- }
-
- public int generateBytes(byte[] out, int outOff, int len)
- throws DataLengthException, IllegalArgumentException
- {
- // TODO Create an ASN.1 class for this (RFC3278)
- // ECC-CMS-SharedInfo
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(new AlgorithmIdentifier(algorithm, DERNull.INSTANCE));
- v.add(new DERTaggedObject(true, 2, new DEROctetString(Pack.intToBigEndian(keySize))));
-
- try
- {
- kdf.init(new KDFParameters(z, new DERSequence(v).getEncoded(ASN1Encoding.DER)));
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("unable to initialise kdf: " + e.getMessage());
- }
-
- return kdf.generateBytes(out, outOff, len);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Client.java b/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Client.java
deleted file mode 100644
index 153e5a83..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Client.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package org.bouncycastle.crypto.agreement.srp;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.Digest;
-
-/**
- * Implements the client side SRP-6a protocol. Note that this class is stateful, and therefore NOT threadsafe.
- * This implementation of SRP is based on the optimized message sequence put forth by Thomas Wu in the paper
- * "SRP-6: Improvements and Refinements to the Secure Remote Password Protocol, 2002"
- */
-public class SRP6Client
-{
- protected BigInteger N;
- protected BigInteger g;
-
- protected BigInteger a;
- protected BigInteger A;
-
- protected BigInteger B;
-
- protected BigInteger x;
- protected BigInteger u;
- protected BigInteger S;
-
- protected BigInteger M1;
- protected BigInteger M2;
- protected BigInteger Key;
-
- protected Digest digest;
- protected SecureRandom random;
-
- public SRP6Client()
- {
- }
-
- /**
- * Initialises the client to begin new authentication attempt
- * @param N The safe prime associated with the client's verifier
- * @param g The group parameter associated with the client's verifier
- * @param digest The digest algorithm associated with the client's verifier
- * @param random For key generation
- */
- public void init(BigInteger N, BigInteger g, Digest digest, SecureRandom random)
- {
- this.N = N;
- this.g = g;
- this.digest = digest;
- this.random = random;
- }
-
- /**
- * Generates client's credentials given the client's salt, identity and password
- * @param salt The salt used in the client's verifier.
- * @param identity The user's identity (eg. username)
- * @param password The user's password
- * @return Client's public value to send to server
- */
- public BigInteger generateClientCredentials(byte[] salt, byte[] identity, byte[] password)
- {
- this.x = SRP6Util.calculateX(digest, N, salt, identity, password);
- this.a = selectPrivateValue();
- this.A = g.modPow(a, N);
-
- return A;
- }
-
- /**
- * Generates the secret S given the server's credentials
- * @param serverB The server's credentials
- * @return Client's verification message for the server
- * @throws CryptoException If server's credentials are invalid
- */
- public BigInteger calculateSecret(BigInteger serverB) throws CryptoException
- {
- this.B = SRP6Util.validatePublicValue(N, serverB);
- this.u = SRP6Util.calculateU(digest, N, A, B);
- this.S = calculateS();
-
- return S;
- }
-
- protected BigInteger selectPrivateValue()
- {
- return SRP6Util.generatePrivateValue(digest, N, g, random);
- }
-
- private BigInteger calculateS()
- {
- BigInteger k = SRP6Util.calculateK(digest, N, g);
- BigInteger exp = u.multiply(x).add(a);
- BigInteger tmp = g.modPow(x, N).multiply(k).mod(N);
- return B.subtract(tmp).mod(N).modPow(exp, N);
- }
-
- /**
- * Computes the client evidence message M1 using the previously received values.
- * To be called after calculating the secret S.
- * @return M1: the client side generated evidence message
- * @throws CryptoException
- */
- public BigInteger calculateClientEvidenceMessage() throws CryptoException{
- // verify pre-requirements
- if ((this.A==null)||(this.B==null)||(this.S==null)){
- throw new CryptoException("Impossible to compute M1: " +
- "some data are missing from the previous operations (A,B,S)");
- }
- // compute the client evidence message 'M1'
- this.M1 = SRP6Util.calculateM1(digest, N, A, B, S);
- return M1;
- }
-
- /** Authenticates the server evidence message M2 received and saves it only if correct.
- * @param M2: the server side generated evidence message
- * @return A boolean indicating if the server message M2 was the expected one.
- * @throws CryptoException
- */
- public boolean verifyServerEvidenceMessage(BigInteger serverM2) throws CryptoException{
- //verify pre-requirements
- if ((this.A==null)||(this.M1==null)||(this.S==null)){
- throw new CryptoException("Impossible to compute and verify M2: " +
- "some data are missing from the previous operations (A,M1,S)");
- }
- // Compute the own server evidence message 'M2'
- BigInteger computedM2 = SRP6Util.calculateM2(digest, N, A, M1, S);
- if (computedM2.equals(serverM2)){
- this.M2 = serverM2;
- return true;
- }
- return false;
- }
-
- /**
- * Computes the final session key as a result of the SRP successful mutual authentication
- * To be called after verifying the server evidence message M2.
- * @return Key: the mutually authenticated symmetric session key
- * @throws CryptoException
- */
- public BigInteger calculateSessionKey() throws CryptoException{
- //verify pre-requirements (here we enforce a previous calculation of M1 and M2)
- if ((this.S==null)||(this.M1==null)||(this.M2==null)){
- throw new CryptoException("Impossible to compute Key: " +
- "some data are missing from the previous operations (S,M1,M2)");
- }
- this.Key = SRP6Util.calculateKey(digest, N, S);
- return Key;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Server.java b/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Server.java
deleted file mode 100644
index 5d703470..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Server.java
+++ /dev/null
@@ -1,148 +0,0 @@
-package org.bouncycastle.crypto.agreement.srp;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.Digest;
-
-/**
- * Implements the server side SRP-6a protocol. Note that this class is stateful, and therefore NOT threadsafe.
- * This implementation of SRP is based on the optimized message sequence put forth by Thomas Wu in the paper
- * "SRP-6: Improvements and Refinements to the Secure Remote Password Protocol, 2002"
- */
-public class SRP6Server
-{
- protected BigInteger N;
- protected BigInteger g;
- protected BigInteger v;
-
- protected SecureRandom random;
- protected Digest digest;
-
- protected BigInteger A;
-
- protected BigInteger b;
- protected BigInteger B;
-
- protected BigInteger u;
- protected BigInteger S;
- protected BigInteger M1;
- protected BigInteger M2;
- protected BigInteger Key;
-
- public SRP6Server()
- {
- }
-
- /**
- * Initialises the server to accept a new client authentication attempt
- * @param N The safe prime associated with the client's verifier
- * @param g The group parameter associated with the client's verifier
- * @param v The client's verifier
- * @param digest The digest algorithm associated with the client's verifier
- * @param random For key generation
- */
- public void init(BigInteger N, BigInteger g, BigInteger v, Digest digest, SecureRandom random)
- {
- this.N = N;
- this.g = g;
- this.v = v;
-
- this.random = random;
- this.digest = digest;
- }
-
- /**
- * Generates the server's credentials that are to be sent to the client.
- * @return The server's public value to the client
- */
- public BigInteger generateServerCredentials()
- {
- BigInteger k = SRP6Util.calculateK(digest, N, g);
- this.b = selectPrivateValue();
- this.B = k.multiply(v).mod(N).add(g.modPow(b, N)).mod(N);
-
- return B;
- }
-
- /**
- * Processes the client's credentials. If valid the shared secret is generated and returned.
- * @param clientA The client's credentials
- * @return A shared secret BigInteger
- * @throws CryptoException If client's credentials are invalid
- */
- public BigInteger calculateSecret(BigInteger clientA) throws CryptoException
- {
- this.A = SRP6Util.validatePublicValue(N, clientA);
- this.u = SRP6Util.calculateU(digest, N, A, B);
- this.S = calculateS();
-
- return S;
- }
-
- protected BigInteger selectPrivateValue()
- {
- return SRP6Util.generatePrivateValue(digest, N, g, random);
- }
-
- private BigInteger calculateS()
- {
- return v.modPow(u, N).multiply(A).mod(N).modPow(b, N);
- }
-
- /**
- * Authenticates the received client evidence message M1 and saves it only if correct.
- * To be called after calculating the secret S.
- * @param M1: the client side generated evidence message
- * @return A boolean indicating if the client message M1 was the expected one.
- * @throws CryptoException
- */
- public boolean verifyClientEvidenceMessage(BigInteger clientM1) throws CryptoException{
- //verify pre-requirements
- if ((this.A==null)||(this.B==null)||(this.S==null)){
- throw new CryptoException("Impossible to compute and verify M1: " +
- "some data are missing from the previous operations (A,B,S)");
- }
- // Compute the own client evidence message 'M1'
- BigInteger computedM1 = SRP6Util.calculateM1(digest, N, A, B, S);
- if (computedM1.equals(clientM1)){
- this.M1 = clientM1;
- return true;
- }
- return false;
- }
-
- /**
- * Computes the server evidence message M2 using the previously verified values.
- * To be called after successfully verifying the client evidence message M1.
- * @return M2: the server side generated evidence message
- * @throws CryptoException
- */
- public BigInteger calculateServerEvidenceMessage() throws CryptoException{
- //verify pre-requirements
- if ((this.A==null)||(this.M1==null)||(this.S==null)){
- throw new CryptoException("Impossible to compute M2: " +
- "some data are missing from the previous operations (A,M1,S)");
- }
- // Compute the server evidence message 'M2'
- this.M2 = SRP6Util.calculateM2(digest, N, A, M1, S);
- return M2;
- }
-
- /**
- * Computes the final session key as a result of the SRP successful mutual authentication
- * To be called after calculating the server evidence message M2.
- * @return Key: the mutual authenticated symmetric session key
- * @throws CryptoException
- */
- public BigInteger calculateSessionKey() throws CryptoException{
- //verify pre-requirements
- if ((this.S==null)||(this.M1==null)||(this.M2==null)){
- throw new CryptoException("Impossible to compute Key: " +
- "some data are missing from the previous operations (S,M1,M2)");
- }
- this.Key = SRP6Util.calculateKey(digest, N, S);
- return Key;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Util.java b/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Util.java
deleted file mode 100644
index 6bcf0183..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6Util.java
+++ /dev/null
@@ -1,154 +0,0 @@
-package org.bouncycastle.crypto.agreement.srp;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.util.BigIntegers;
-
-public class SRP6Util
-{
- private static BigInteger ZERO = BigInteger.valueOf(0);
- private static BigInteger ONE = BigInteger.valueOf(1);
-
- public static BigInteger calculateK(Digest digest, BigInteger N, BigInteger g)
- {
- return hashPaddedPair(digest, N, N, g);
- }
-
- public static BigInteger calculateU(Digest digest, BigInteger N, BigInteger A, BigInteger B)
- {
- return hashPaddedPair(digest, N, A, B);
- }
-
- public static BigInteger calculateX(Digest digest, BigInteger N, byte[] salt, byte[] identity, byte[] password)
- {
- byte[] output = new byte[digest.getDigestSize()];
-
- digest.update(identity, 0, identity.length);
- digest.update((byte)':');
- digest.update(password, 0, password.length);
- digest.doFinal(output, 0);
-
- digest.update(salt, 0, salt.length);
- digest.update(output, 0, output.length);
- digest.doFinal(output, 0);
-
- return new BigInteger(1, output);
- }
-
- public static BigInteger generatePrivateValue(Digest digest, BigInteger N, BigInteger g, SecureRandom random)
- {
- int minBits = Math.min(256, N.bitLength() / 2);
- BigInteger min = ONE.shiftLeft(minBits - 1);
- BigInteger max = N.subtract(ONE);
-
- return BigIntegers.createRandomInRange(min, max, random);
- }
-
- public static BigInteger validatePublicValue(BigInteger N, BigInteger val)
- throws CryptoException
- {
- val = val.mod(N);
-
- // Check that val % N != 0
- if (val.equals(ZERO))
- {
- throw new CryptoException("Invalid public value: 0");
- }
-
- return val;
- }
- /**
- * Computes the client evidence message (M1) according to the standard routine:
- * M1 = H( A | B | S )
- * @param digest The Digest used as the hashing function H
- * @param N Modulus used to get the pad length
- * @param A The public client value
- * @param B The public server value
- * @param S The secret calculated by both sides
- * @return M1 The calculated client evidence message
- */
- public static BigInteger calculateM1(Digest digest, BigInteger N, BigInteger A, BigInteger B, BigInteger S) {
- BigInteger M1 = hashPaddedTriplet(digest,N,A,B,S);
- return M1;
- }
-
- /**
- * Computes the server evidence message (M2) according to the standard routine:
- * M2 = H( A | M1 | S )
- * @param digest The Digest used as the hashing function H
- * @param N Modulus used to get the pad length
- * @param A The public client value
- * @param M1 The client evidence message
- * @param S The secret calculated by both sides
- * @return M2 The calculated server evidence message
- */
- public static BigInteger calculateM2(Digest digest, BigInteger N, BigInteger A, BigInteger M1, BigInteger S){
- BigInteger M2 = hashPaddedTriplet(digest,N,A,M1,S);
- return M2;
- }
-
- /**
- * Computes the final Key according to the standard routine: Key = H(S)
- * @param digest The Digest used as the hashing function H
- * @param N Modulus used to get the pad length
- * @param S The secret calculated by both sides
- * @return
- */
- public static BigInteger calculateKey(Digest digest, BigInteger N, BigInteger S) {
- int padLength = (N.bitLength() + 7) / 8;
- byte[] _S = getPadded(S,padLength);
- digest.update(_S, 0, _S.length);
-
- byte[] output = new byte[digest.getDigestSize()];
- digest.doFinal(output, 0);
- return new BigInteger(1, output);
- }
-
- private static BigInteger hashPaddedTriplet(Digest digest, BigInteger N, BigInteger n1, BigInteger n2, BigInteger n3){
- int padLength = (N.bitLength() + 7) / 8;
-
- byte[] n1_bytes = getPadded(n1, padLength);
- byte[] n2_bytes = getPadded(n2, padLength);
- byte[] n3_bytes = getPadded(n3, padLength);
-
- digest.update(n1_bytes, 0, n1_bytes.length);
- digest.update(n2_bytes, 0, n2_bytes.length);
- digest.update(n3_bytes, 0, n3_bytes.length);
-
- byte[] output = new byte[digest.getDigestSize()];
- digest.doFinal(output, 0);
-
- return new BigInteger(1, output);
- }
-
- private static BigInteger hashPaddedPair(Digest digest, BigInteger N, BigInteger n1, BigInteger n2)
- {
- int padLength = (N.bitLength() + 7) / 8;
-
- byte[] n1_bytes = getPadded(n1, padLength);
- byte[] n2_bytes = getPadded(n2, padLength);
-
- digest.update(n1_bytes, 0, n1_bytes.length);
- digest.update(n2_bytes, 0, n2_bytes.length);
-
- byte[] output = new byte[digest.getDigestSize()];
- digest.doFinal(output, 0);
-
- return new BigInteger(1, output);
- }
-
- private static byte[] getPadded(BigInteger n, int length)
- {
- byte[] bs = BigIntegers.asUnsignedByteArray(n);
- if (bs.length < length)
- {
- byte[] tmp = new byte[length];
- System.arraycopy(bs, 0, tmp, length - bs.length, bs.length);
- bs = tmp;
- }
- return bs;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6VerifierGenerator.java b/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6VerifierGenerator.java
deleted file mode 100644
index 631ecc6e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/agreement/srp/SRP6VerifierGenerator.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.bouncycastle.crypto.agreement.srp;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.Digest;
-
-/**
- * Generates new SRP verifier for user
- */
-public class SRP6VerifierGenerator
-{
- protected BigInteger N;
- protected BigInteger g;
- protected Digest digest;
-
- public SRP6VerifierGenerator()
- {
- }
-
- /**
- * Initialises generator to create new verifiers
- * @param N The safe prime to use (see DHParametersGenerator)
- * @param g The group parameter to use (see DHParametersGenerator)
- * @param digest The digest to use. The same digest type will need to be used later for the actual authentication
- * attempt. Also note that the final session key size is dependent on the chosen digest.
- */
- public void init(BigInteger N, BigInteger g, Digest digest)
- {
- this.N = N;
- this.g = g;
- this.digest = digest;
- }
-
- /**
- * Creates a new SRP verifier
- * @param salt The salt to use, generally should be large and random
- * @param identity The user's identifying information (eg. username)
- * @param password The user's password
- * @return A new verifier for use in future SRP authentication
- */
- public BigInteger generateVerifier(byte[] salt, byte[] identity, byte[] password)
- {
- BigInteger x = SRP6Util.calculateX(digest, N, salt, identity, password);
-
- return g.modPow(x, N);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/commitments/GeneralHashCommitter.java b/core/src/main/java/org/bouncycastle/crypto/commitments/GeneralHashCommitter.java
deleted file mode 100644
index 3969fe8a..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/commitments/GeneralHashCommitter.java
+++ /dev/null
@@ -1,93 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/commitments/HashCommitter.java b/core/src/main/java/org/bouncycastle/crypto/commitments/HashCommitter.java
deleted file mode 100644
index b5860b52..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/commitments/HashCommitter.java
+++ /dev/null
@@ -1,89 +0,0 @@
-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 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
-{
- 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 HashCommitter(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.doFinal(commitment, 0);
-
- return commitment;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/digests/EncodableDigest.java b/core/src/main/java/org/bouncycastle/crypto/digests/EncodableDigest.java
deleted file mode 100644
index d79fece8..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/EncodableDigest.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-/**
- * Encodable digests allow you to download an encoded copy of their internal state. This is useful for the situation where
- * you need to generate a signature on an external device and it allows for "sign with last round", so a copy of the
- * internal state of the digest, plus the last few blocks of the message are all that needs to be sent, rather than the
- * entire message.
- */
-public interface EncodableDigest
-{
- /**
- * Return an encoded byte array for the digest's internal state
- *
- * @return an encoding of the digests internal state.
- */
- byte[] getEncodedState();
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/digests/GOST3411Digest.java b/core/src/main/java/org/bouncycastle/crypto/digests/GOST3411Digest.java
deleted file mode 100644
index 2df2d51a..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/GOST3411Digest.java
+++ /dev/null
@@ -1,362 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.ExtendedDigest;
-import org.bouncycastle.crypto.engines.GOST28147Engine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithSBox;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Memoable;
-import org.bouncycastle.util.Pack;
-
-/**
- * implementation of GOST R 34.11-94
- */
-public class GOST3411Digest
- implements ExtendedDigest, Memoable
-{
- private static final int DIGEST_LENGTH = 32;
-
- private byte[] H = new byte[32], L = new byte[32],
- M = new byte[32], Sum = new byte[32];
- private byte[][] C = new byte[4][32];
-
- private byte[] xBuf = new byte[32];
- private int xBufOff;
- private long byteCount;
-
- private BlockCipher cipher = new GOST28147Engine();
- private byte[] sBox;
-
- /**
- * Standard constructor
- */
- public GOST3411Digest()
- {
- sBox = GOST28147Engine.getSBox("D-A");
- cipher.init(true, new ParametersWithSBox(null, sBox));
-
- reset();
- }
-
- /**
- * Constructor to allow use of a particular sbox with GOST28147
- * @see GOST28147Engine#getSBox(String)
- */
- public GOST3411Digest(byte[] sBoxParam)
- {
- sBox = Arrays.clone(sBoxParam);
- cipher.init(true, new ParametersWithSBox(null, sBox));
-
- reset();
- }
-
- /**
- * Copy constructor. This will copy the state of the provided
- * message digest.
- */
- public GOST3411Digest(GOST3411Digest t)
- {
- reset(t);
- }
-
- public String getAlgorithmName()
- {
- return "GOST3411";
- }
-
- public int getDigestSize()
- {
- return DIGEST_LENGTH;
- }
-
- public void update(byte in)
- {
- xBuf[xBufOff++] = in;
- if (xBufOff == xBuf.length)
- {
- sumByteArray(xBuf); // calc sum M
- processBlock(xBuf, 0);
- xBufOff = 0;
- }
- byteCount++;
- }
-
- public void update(byte[] in, int inOff, int len)
- {
- while ((xBufOff != 0) && (len > 0))
- {
- update(in[inOff]);
- inOff++;
- len--;
- }
-
- while (len > xBuf.length)
- {
- System.arraycopy(in, inOff, xBuf, 0, xBuf.length);
-
- sumByteArray(xBuf); // calc sum M
- processBlock(xBuf, 0);
- inOff += xBuf.length;
- len -= xBuf.length;
- byteCount += xBuf.length;
- }
-
- // load in the remainder.
- while (len > 0)
- {
- update(in[inOff]);
- inOff++;
- len--;
- }
- }
-
- // (i + 1 + 4(k - 1)) = 8i + k i = 0-3, k = 1-8
- private byte[] K = new byte[32];
-
- private byte[] P(byte[] in)
- {
- for(int k = 0; k < 8; k++)
- {
- K[4*k] = in[k];
- K[1 + 4*k] = in[ 8 + k];
- K[2 + 4*k] = in[16 + k];
- K[3 + 4*k] = in[24 + k];
- }
-
- return K;
- }
-
- //A (x) = (x0 ^ x1) || x3 || x2 || x1
- byte[] a = new byte[8];
- private byte[] A(byte[] in)
- {
- for(int j=0; j<8; j++)
- {
- a[j]=(byte)(in[j] ^ in[j+8]);
- }
-
- System.arraycopy(in, 8, in, 0, 24);
- System.arraycopy(a, 0, in, 24, 8);
-
- return in;
- }
-
- //Encrypt function, ECB mode
- private void E(byte[] key, byte[] s, int sOff, byte[] in, int inOff)
- {
- cipher.init(true, new KeyParameter(key));
-
- cipher.processBlock(in, inOff, s, sOff);
- }
-
- // (in:) n16||..||n1 ==> (out:) n1^n2^n3^n4^n13^n16||n16||..||n2
- short[] wS = new short[16], w_S = new short[16];
-
- private void fw(byte[] in)
- {
- cpyBytesToShort(in, wS);
- w_S[15] = (short)(wS[0] ^ wS[1] ^ wS[2] ^ wS[3] ^ wS[12] ^ wS[15]);
- System.arraycopy(wS, 1, w_S, 0, 15);
- cpyShortToBytes(w_S, in);
- }
-
- // block processing
- byte[] S = new byte[32];
- byte[] U = new byte[32], V = new byte[32], W = new byte[32];
-
- protected void processBlock(byte[] in, int inOff)
- {
- System.arraycopy(in, inOff, M, 0, 32);
-
- //key step 1
-
- // H = h3 || h2 || h1 || h0
- // S = s3 || s2 || s1 || s0
- System.arraycopy(H, 0, U, 0, 32);
- System.arraycopy(M, 0, V, 0, 32);
- for (int j=0; j<32; j++)
- {
- W[j] = (byte)(U[j]^V[j]);
- }
- // Encrypt gost28147-ECB
- E(P(W), S, 0, H, 0); // s0 = EK0 [h0]
-
- //keys step 2,3,4
- for (int i=1; i<4; i++)
- {
- byte[] tmpA = A(U);
- for (int j=0; j<32; j++)
- {
- U[j] = (byte)(tmpA[j] ^ C[i][j]);
- }
- V = A(A(V));
- for (int j=0; j<32; j++)
- {
- W[j] = (byte)(U[j]^V[j]);
- }
- // Encrypt gost28147-ECB
- E(P(W), S, i * 8, H, i * 8); // si = EKi [hi]
- }
-
- // x(M, H) = y61(H^y(M^y12(S)))
- for(int n = 0; n < 12; n++)
- {
- fw(S);
- }
- for(int n = 0; n < 32; n++)
- {
- S[n] = (byte)(S[n] ^ M[n]);
- }
-
- fw(S);
-
- for(int n = 0; n < 32; n++)
- {
- S[n] = (byte)(H[n] ^ S[n]);
- }
- for(int n = 0; n < 61; n++)
- {
- fw(S);
- }
- System.arraycopy(S, 0, H, 0, H.length);
- }
-
- private void finish()
- {
- Pack.longToLittleEndian(byteCount * 8, L, 0); // get length into L (byteCount * 8 = bitCount)
-
- while (xBufOff != 0)
- {
- update((byte)0);
- }
-
- processBlock(L, 0);
- processBlock(Sum, 0);
- }
-
- public int doFinal(
- byte[] out,
- int outOff)
- {
- finish();
-
- System.arraycopy(H, 0, out, outOff, H.length);
-
- reset();
-
- return DIGEST_LENGTH;
- }
-
- /**
- * reset the chaining variables to the IV values.
- */
- private static final byte[] C2 = {
- 0x00,(byte)0xFF,0x00,(byte)0xFF,0x00,(byte)0xFF,0x00,(byte)0xFF,
- (byte)0xFF,0x00,(byte)0xFF,0x00,(byte)0xFF,0x00,(byte)0xFF,0x00,
- 0x00,(byte)0xFF,(byte)0xFF,0x00,(byte)0xFF,0x00,0x00,(byte)0xFF,
- (byte)0xFF,0x00,0x00,0x00,(byte)0xFF,(byte)0xFF,0x00,(byte)0xFF};
-
- public void reset()
- {
- byteCount = 0;
- xBufOff = 0;
-
- for(int i=0; i<H.length; i++)
- {
- H[i] = 0; // start vector H
- }
- for(int i=0; i<L.length; i++)
- {
- L[i] = 0;
- }
- for(int i=0; i<M.length; i++)
- {
- M[i] = 0;
- }
- for(int i=0; i<C[1].length; i++)
- {
- C[1][i] = 0; // real index C = +1 because index array with 0.
- }
- for(int i=0; i<C[3].length; i++)
- {
- C[3][i] = 0;
- }
- for(int i=0; i<Sum.length; i++)
- {
- Sum[i] = 0;
- }
- for(int i = 0; i < xBuf.length; i++)
- {
- xBuf[i] = 0;
- }
-
- System.arraycopy(C2, 0, C[2], 0, C2.length);
- }
-
- // 256 bitsblock modul -> (Sum + a mod (2^256))
- private void sumByteArray(byte[] in)
- {
- int carry = 0;
-
- for (int i = 0; i != Sum.length; i++)
- {
- int sum = (Sum[i] & 0xff) + (in[i] & 0xff) + carry;
-
- Sum[i] = (byte)sum;
-
- carry = sum >>> 8;
- }
- }
-
- private void cpyBytesToShort(byte[] S, short[] wS)
- {
- for(int i=0; i<S.length/2; i++)
- {
- wS[i] = (short)(((S[i*2+1]<<8)&0xFF00)|(S[i*2]&0xFF));
- }
- }
-
- private void cpyShortToBytes(short[] wS, byte[] S)
- {
- for(int i=0; i<S.length/2; i++)
- {
- S[i*2 + 1] = (byte)(wS[i] >> 8);
- S[i*2] = (byte)wS[i];
- }
- }
-
- public int getByteLength()
- {
- return 32;
- }
-
- public Memoable copy()
- {
- return new GOST3411Digest(this);
- }
-
- public void reset(Memoable other)
- {
- GOST3411Digest t = (GOST3411Digest)other;
-
- this.sBox = t.sBox;
- cipher.init(true, new ParametersWithSBox(null, sBox));
-
- reset();
-
- System.arraycopy(t.H, 0, this.H, 0, t.H.length);
- System.arraycopy(t.L, 0, this.L, 0, t.L.length);
- System.arraycopy(t.M, 0, this.M, 0, t.M.length);
- System.arraycopy(t.Sum, 0, this.Sum, 0, t.Sum.length);
- System.arraycopy(t.C[1], 0, this.C[1], 0, t.C[1].length);
- System.arraycopy(t.C[2], 0, this.C[2], 0, t.C[2].length);
- System.arraycopy(t.C[3], 0, this.C[3], 0, t.C[3].length);
- System.arraycopy(t.xBuf, 0, this.xBuf, 0, t.xBuf.length);
-
- this.xBufOff = t.xBufOff;
- this.byteCount = t.byteCount;
- }
-}
-
-
diff --git a/core/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java b/core/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java
deleted file mode 100644
index 29692bad..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java
+++ /dev/null
@@ -1,155 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-import org.bouncycastle.crypto.ExtendedDigest;
-import org.bouncycastle.util.Memoable;
-import org.bouncycastle.util.Pack;
-
-/**
- * base implementation of MD4 family style digest as outlined in
- * "Handbook of Applied Cryptography", pages 344 - 347.
- */
-public abstract class GeneralDigest
- implements ExtendedDigest, Memoable
-{
- private static final int BYTE_LENGTH = 64;
-
- private final byte[] xBuf = new byte[4];
- private int xBufOff;
-
- private long byteCount;
-
- /**
- * Standard constructor
- */
- protected GeneralDigest()
- {
- xBufOff = 0;
- }
-
- /**
- * Copy constructor. We are using copy constructors in place
- * of the Object.clone() interface as this interface is not
- * supported by J2ME.
- */
- protected GeneralDigest(GeneralDigest t)
- {
- copyIn(t);
- }
-
- protected GeneralDigest(byte[] encodedState)
- {
- System.arraycopy(encodedState, 0, xBuf, 0, xBuf.length);
- xBufOff = Pack.bigEndianToInt(encodedState, 4);
- byteCount = Pack.bigEndianToLong(encodedState, 8);
- }
-
- protected void copyIn(GeneralDigest t)
- {
- System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length);
-
- xBufOff = t.xBufOff;
- byteCount = t.byteCount;
- }
-
- public void update(
- byte in)
- {
- xBuf[xBufOff++] = in;
-
- if (xBufOff == xBuf.length)
- {
- processWord(xBuf, 0);
- xBufOff = 0;
- }
-
- byteCount++;
- }
-
- public void update(
- byte[] in,
- int inOff,
- int len)
- {
- //
- // fill the current word
- //
- while ((xBufOff != 0) && (len > 0))
- {
- update(in[inOff]);
-
- inOff++;
- len--;
- }
-
- //
- // process whole words.
- //
- while (len > xBuf.length)
- {
- processWord(in, inOff);
-
- inOff += xBuf.length;
- len -= xBuf.length;
- byteCount += xBuf.length;
- }
-
- //
- // load in the remainder.
- //
- while (len > 0)
- {
- update(in[inOff]);
-
- inOff++;
- len--;
- }
- }
-
- public void finish()
- {
- long bitLength = (byteCount << 3);
-
- //
- // add the pad bytes.
- //
- update((byte)128);
-
- while (xBufOff != 0)
- {
- update((byte)0);
- }
-
- processLength(bitLength);
-
- processBlock();
- }
-
- public void reset()
- {
- byteCount = 0;
-
- xBufOff = 0;
- for (int i = 0; i < xBuf.length; i++)
- {
- xBuf[i] = 0;
- }
- }
-
- protected void populateState(byte[] state)
- {
- System.arraycopy(xBuf, 0, state, 0, xBufOff);
- Pack.intToBigEndian(xBufOff, state, 4);
- Pack.longToBigEndian(byteCount, state, 8);
- }
-
- public int getByteLength()
- {
- return BYTE_LENGTH;
- }
-
- protected abstract void processWord(byte[] in, int inOff);
-
- protected abstract void processLength(long bitLength);
-
- protected abstract void processBlock();
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/digests/LongDigest.java b/core/src/main/java/org/bouncycastle/crypto/digests/LongDigest.java
deleted file mode 100644
index 8ea474b3..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/LongDigest.java
+++ /dev/null
@@ -1,409 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-import org.bouncycastle.crypto.ExtendedDigest;
-import org.bouncycastle.util.Memoable;
-import org.bouncycastle.util.Pack;
-
-/**
- * Base class for SHA-384 and SHA-512.
- */
-public abstract class LongDigest
- implements ExtendedDigest, Memoable, EncodableDigest
-{
- private static final int BYTE_LENGTH = 128;
-
- private byte[] xBuf = new byte[8];
- private int xBufOff;
-
- private long byteCount1;
- private long byteCount2;
-
- protected long H1, H2, H3, H4, H5, H6, H7, H8;
-
- private long[] W = new long[80];
- private int wOff;
-
- /**
- * Constructor for variable length word
- */
- protected LongDigest()
- {
- xBufOff = 0;
-
- reset();
- }
-
- /**
- * Copy constructor. We are using copy constructors in place
- * of the Object.clone() interface as this interface is not
- * supported by J2ME.
- */
- protected LongDigest(LongDigest t)
- {
- copyIn(t);
- }
-
- protected void copyIn(LongDigest t)
- {
- System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length);
-
- xBufOff = t.xBufOff;
- byteCount1 = t.byteCount1;
- byteCount2 = t.byteCount2;
-
- H1 = t.H1;
- H2 = t.H2;
- H3 = t.H3;
- H4 = t.H4;
- H5 = t.H5;
- H6 = t.H6;
- H7 = t.H7;
- H8 = t.H8;
-
- System.arraycopy(t.W, 0, W, 0, t.W.length);
- wOff = t.wOff;
- }
-
- protected void populateState(byte[] state)
- {
- System.arraycopy(xBuf, 0, state, 0, xBufOff);
- Pack.intToBigEndian(xBufOff, state, 8);
- Pack.longToBigEndian(byteCount1, state, 12);
- Pack.longToBigEndian(byteCount2, state, 20);
- Pack.longToBigEndian(H1, state, 28);
- Pack.longToBigEndian(H2, state, 36);
- Pack.longToBigEndian(H3, state, 44);
- Pack.longToBigEndian(H4, state, 52);
- Pack.longToBigEndian(H5, state, 60);
- Pack.longToBigEndian(H6, state, 68);
- Pack.longToBigEndian(H7, state, 76);
- Pack.longToBigEndian(H8, state, 84);
-
- Pack.intToBigEndian(wOff, state, 92);
- for (int i = 0; i < wOff; i++)
- {
- Pack.longToBigEndian(W[i], state, 96 + (i * 8));
- }
- }
-
- protected void restoreState(byte[] encodedState)
- {
- xBufOff = Pack.bigEndianToInt(encodedState, 8);
- System.arraycopy(encodedState, 0, xBuf, 0, xBufOff);
- byteCount1 = Pack.bigEndianToLong(encodedState, 12);
- byteCount2 = Pack.bigEndianToLong(encodedState, 20);
-
- H1 = Pack.bigEndianToLong(encodedState, 28);
- H2 = Pack.bigEndianToLong(encodedState, 36);
- H3 = Pack.bigEndianToLong(encodedState, 44);
- H4 = Pack.bigEndianToLong(encodedState, 52);
- H5 = Pack.bigEndianToLong(encodedState, 60);
- H6 = Pack.bigEndianToLong(encodedState, 68);
- H7 = Pack.bigEndianToLong(encodedState, 76);
- H8 = Pack.bigEndianToLong(encodedState, 84);
-
- wOff = Pack.bigEndianToInt(encodedState, 92);
- for (int i = 0; i < wOff; i++)
- {
- W[i] = Pack.bigEndianToLong(encodedState, 96 + (i * 8));
- }
- }
-
- protected int getEncodedStateSize()
- {
- return 96 + (wOff * 8);
- }
-
- public void update(
- byte in)
- {
- xBuf[xBufOff++] = in;
-
- if (xBufOff == xBuf.length)
- {
- processWord(xBuf, 0);
- xBufOff = 0;
- }
-
- byteCount1++;
- }
-
- public void update(
- byte[] in,
- int inOff,
- int len)
- {
- //
- // fill the current word
- //
- while ((xBufOff != 0) && (len > 0))
- {
- update(in[inOff]);
-
- inOff++;
- len--;
- }
-
- //
- // process whole words.
- //
- while (len > xBuf.length)
- {
- processWord(in, inOff);
-
- inOff += xBuf.length;
- len -= xBuf.length;
- byteCount1 += xBuf.length;
- }
-
- //
- // load in the remainder.
- //
- while (len > 0)
- {
- update(in[inOff]);
-
- inOff++;
- len--;
- }
- }
-
- public void finish()
- {
- adjustByteCounts();
-
- long lowBitLength = byteCount1 << 3;
- long hiBitLength = byteCount2;
-
- //
- // add the pad bytes.
- //
- update((byte)128);
-
- while (xBufOff != 0)
- {
- update((byte)0);
- }
-
- processLength(lowBitLength, hiBitLength);
-
- processBlock();
- }
-
- public void reset()
- {
- byteCount1 = 0;
- byteCount2 = 0;
-
- xBufOff = 0;
- for (int i = 0; i < xBuf.length; i++)
- {
- xBuf[i] = 0;
- }
-
- wOff = 0;
- for (int i = 0; i != W.length; i++)
- {
- W[i] = 0;
- }
- }
-
- public int getByteLength()
- {
- return BYTE_LENGTH;
- }
-
- protected void processWord(
- byte[] in,
- int inOff)
- {
- W[wOff] = Pack.bigEndianToLong(in, inOff);
-
- if (++wOff == 16)
- {
- processBlock();
- }
- }
-
- /**
- * adjust the byte counts so that byteCount2 represents the
- * upper long (less 3 bits) word of the byte count.
- */
- private void adjustByteCounts()
- {
- if (byteCount1 > 0x1fffffffffffffffL)
- {
- byteCount2 += (byteCount1 >>> 61);
- byteCount1 &= 0x1fffffffffffffffL;
- }
- }
-
- protected void processLength(
- long lowW,
- long hiW)
- {
- if (wOff > 14)
- {
- processBlock();
- }
-
- W[14] = hiW;
- W[15] = lowW;
- }
-
- protected void processBlock()
- {
- adjustByteCounts();
-
- //
- // expand 16 word block into 80 word blocks.
- //
- for (int t = 16; t <= 79; t++)
- {
- W[t] = Sigma1(W[t - 2]) + W[t - 7] + Sigma0(W[t - 15]) + W[t - 16];
- }
-
- //
- // set up working variables.
- //
- long a = H1;
- long b = H2;
- long c = H3;
- long d = H4;
- long e = H5;
- long f = H6;
- long g = H7;
- long h = H8;
-
- int t = 0;
- for(int i = 0; i < 10; i ++)
- {
- // t = 8 * i
- h += Sum1(e) + Ch(e, f, g) + K[t] + W[t++];
- d += h;
- h += Sum0(a) + Maj(a, b, c);
-
- // t = 8 * i + 1
- g += Sum1(d) + Ch(d, e, f) + K[t] + W[t++];
- c += g;
- g += Sum0(h) + Maj(h, a, b);
-
- // t = 8 * i + 2
- f += Sum1(c) + Ch(c, d, e) + K[t] + W[t++];
- b += f;
- f += Sum0(g) + Maj(g, h, a);
-
- // t = 8 * i + 3
- e += Sum1(b) + Ch(b, c, d) + K[t] + W[t++];
- a += e;
- e += Sum0(f) + Maj(f, g, h);
-
- // t = 8 * i + 4
- d += Sum1(a) + Ch(a, b, c) + K[t] + W[t++];
- h += d;
- d += Sum0(e) + Maj(e, f, g);
-
- // t = 8 * i + 5
- c += Sum1(h) + Ch(h, a, b) + K[t] + W[t++];
- g += c;
- c += Sum0(d) + Maj(d, e, f);
-
- // t = 8 * i + 6
- b += Sum1(g) + Ch(g, h, a) + K[t] + W[t++];
- f += b;
- b += Sum0(c) + Maj(c, d, e);
-
- // t = 8 * i + 7
- a += Sum1(f) + Ch(f, g, h) + K[t] + W[t++];
- e += a;
- a += Sum0(b) + Maj(b, c, d);
- }
-
- H1 += a;
- H2 += b;
- H3 += c;
- H4 += d;
- H5 += e;
- H6 += f;
- H7 += g;
- H8 += h;
-
- //
- // reset the offset and clean out the word buffer.
- //
- wOff = 0;
- for (int i = 0; i < 16; i++)
- {
- W[i] = 0;
- }
- }
-
- /* SHA-384 and SHA-512 functions (as for SHA-256 but for longs) */
- private long Ch(
- long x,
- long y,
- long z)
- {
- return ((x & y) ^ ((~x) & z));
- }
-
- private long Maj(
- long x,
- long y,
- long z)
- {
- return ((x & y) ^ (x & z) ^ (y & z));
- }
-
- private long Sum0(
- long x)
- {
- return ((x << 36)|(x >>> 28)) ^ ((x << 30)|(x >>> 34)) ^ ((x << 25)|(x >>> 39));
- }
-
- private long Sum1(
- long x)
- {
- return ((x << 50)|(x >>> 14)) ^ ((x << 46)|(x >>> 18)) ^ ((x << 23)|(x >>> 41));
- }
-
- private long Sigma0(
- long x)
- {
- return ((x << 63)|(x >>> 1)) ^ ((x << 56)|(x >>> 8)) ^ (x >>> 7);
- }
-
- private long Sigma1(
- long x)
- {
- return ((x << 45)|(x >>> 19)) ^ ((x << 3)|(x >>> 61)) ^ (x >>> 6);
- }
-
- /* SHA-384 and SHA-512 Constants
- * (represent the first 64 bits of the fractional parts of the
- * cube roots of the first sixty-four prime numbers)
- */
- static final long K[] = {
-0x428a2f98d728ae22L, 0x7137449123ef65cdL, 0xb5c0fbcfec4d3b2fL, 0xe9b5dba58189dbbcL,
-0x3956c25bf348b538L, 0x59f111f1b605d019L, 0x923f82a4af194f9bL, 0xab1c5ed5da6d8118L,
-0xd807aa98a3030242L, 0x12835b0145706fbeL, 0x243185be4ee4b28cL, 0x550c7dc3d5ffb4e2L,
-0x72be5d74f27b896fL, 0x80deb1fe3b1696b1L, 0x9bdc06a725c71235L, 0xc19bf174cf692694L,
-0xe49b69c19ef14ad2L, 0xefbe4786384f25e3L, 0x0fc19dc68b8cd5b5L, 0x240ca1cc77ac9c65L,
-0x2de92c6f592b0275L, 0x4a7484aa6ea6e483L, 0x5cb0a9dcbd41fbd4L, 0x76f988da831153b5L,
-0x983e5152ee66dfabL, 0xa831c66d2db43210L, 0xb00327c898fb213fL, 0xbf597fc7beef0ee4L,
-0xc6e00bf33da88fc2L, 0xd5a79147930aa725L, 0x06ca6351e003826fL, 0x142929670a0e6e70L,
-0x27b70a8546d22ffcL, 0x2e1b21385c26c926L, 0x4d2c6dfc5ac42aedL, 0x53380d139d95b3dfL,
-0x650a73548baf63deL, 0x766a0abb3c77b2a8L, 0x81c2c92e47edaee6L, 0x92722c851482353bL,
-0xa2bfe8a14cf10364L, 0xa81a664bbc423001L, 0xc24b8b70d0f89791L, 0xc76c51a30654be30L,
-0xd192e819d6ef5218L, 0xd69906245565a910L, 0xf40e35855771202aL, 0x106aa07032bbd1b8L,
-0x19a4c116b8d2d0c8L, 0x1e376c085141ab53L, 0x2748774cdf8eeb99L, 0x34b0bcb5e19b48a8L,
-0x391c0cb3c5c95a63L, 0x4ed8aa4ae3418acbL, 0x5b9cca4f7763e373L, 0x682e6ff3d6b2b8a3L,
-0x748f82ee5defb2fcL, 0x78a5636f43172f60L, 0x84c87814a1f0ab72L, 0x8cc702081a6439ecL,
-0x90befffa23631e28L, 0xa4506cebde82bde9L, 0xbef9a3f7b2c67915L, 0xc67178f2e372532bL,
-0xca273eceea26619cL, 0xd186b8c721c0c207L, 0xeada7dd6cde0eb1eL, 0xf57d4f7fee6ed178L,
-0x06f067aa72176fbaL, 0x0a637dc5a2c898a6L, 0x113f9804bef90daeL, 0x1b710b35131c471bL,
-0x28db77f523047d84L, 0x32caab7b40c72493L, 0x3c9ebe0a15c9bebcL, 0x431d67c49c100d4cL,
-0x4cc5d4becb3e42b6L, 0x597f299cfc657e2aL, 0x5fcb6fab3ad6faecL, 0x6c44198c4a475817L
- };
-
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/digests/MD2Digest.java b/core/src/main/java/org/bouncycastle/crypto/digests/MD2Digest.java
deleted file mode 100644
index f96b4a15..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/MD2Digest.java
+++ /dev/null
@@ -1,258 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-import org.bouncycastle.crypto.*;
-import org.bouncycastle.util.Memoable;
-
-/**
- * implementation of MD2
- * as outlined in RFC1319 by B.Kaliski from RSA Laboratories April 1992
- */
-public class MD2Digest
- implements ExtendedDigest, Memoable
-{
- private static final int DIGEST_LENGTH = 16;
-
- /* X buffer */
- private byte[] X = new byte[48];
- private int xOff;
- /* M buffer */
- private byte[] M = new byte[16];
- private int mOff;
- /* check sum */
- private byte[] C = new byte[16];
- private int COff;
-
- public MD2Digest()
- {
- reset();
- }
-
- public MD2Digest(MD2Digest t)
- {
- copyIn(t);
- }
-
- private void copyIn(MD2Digest t)
- {
- System.arraycopy(t.X, 0, X, 0, t.X.length);
- xOff = t.xOff;
- System.arraycopy(t.M, 0, M, 0, t.M.length);
- mOff = t.mOff;
- System.arraycopy(t.C, 0, C, 0, t.C.length);
- COff = t.COff;
- }
-
- /**
- * return the algorithm name
- *
- * @return the algorithm name
- */
- public String getAlgorithmName()
- {
- return "MD2";
- }
- /**
- * return the size, in bytes, of the digest produced by this message digest.
- *
- * @return the size, in bytes, of the digest produced by this message digest.
- */
- public int getDigestSize()
- {
- return DIGEST_LENGTH;
- }
- /**
- * close the digest, producing the final digest value. The doFinal
- * call leaves the digest reset.
- *
- * @param out the array the digest is to be copied into.
- * @param outOff the offset into the out array the digest is to start at.
- */
- public int doFinal(byte[] out, int outOff)
- {
- // add padding
- byte paddingByte = (byte)(M.length-mOff);
- for (int i=mOff;i<M.length;i++)
- {
- M[i] = paddingByte;
- }
- //do final check sum
- processCheckSum(M);
- // do final block process
- processBlock(M);
-
- processBlock(C);
-
- System.arraycopy(X,xOff,out,outOff,16);
-
- reset();
-
- return DIGEST_LENGTH;
- }
- /**
- * reset the digest back to it's initial state.
- */
- public void reset()
- {
- xOff = 0;
- for (int i = 0; i != X.length; i++)
- {
- X[i] = 0;
- }
- mOff = 0;
- for (int i = 0; i != M.length; i++)
- {
- M[i] = 0;
- }
- COff = 0;
- for (int i = 0; i != C.length; i++)
- {
- C[i] = 0;
- }
- }
- /**
- * update the message digest with a single byte.
- *
- * @param in the input byte to be entered.
- */
- public void update(byte in)
- {
- M[mOff++] = in;
-
- if (mOff == 16)
- {
- processCheckSum(M);
- processBlock(M);
- mOff = 0;
- }
- }
-
- /**
- * update the message digest with a block of bytes.
- *
- * @param in the byte array containing the data.
- * @param inOff the offset into the byte array where the data starts.
- * @param len the length of the data.
- */
- public void update(byte[] in, int inOff, int len)
- {
- //
- // fill the current word
- //
- while ((mOff != 0) && (len > 0))
- {
- update(in[inOff]);
- inOff++;
- len--;
- }
-
- //
- // process whole words.
- //
- while (len > 16)
- {
- System.arraycopy(in,inOff,M,0,16);
- processCheckSum(M);
- processBlock(M);
- len -= 16;
- inOff += 16;
- }
-
- //
- // load in the remainder.
- //
- while (len > 0)
- {
- update(in[inOff]);
- inOff++;
- len--;
- }
- }
- protected void processCheckSum(byte[] m)
- {
- int L = C[15];
- for (int i=0;i<16;i++)
- {
- C[i] ^= S[(m[i] ^ L) & 0xff];
- L = C[i];
- }
- }
- protected void processBlock(byte[] m)
- {
- for (int i=0;i<16;i++)
- {
- X[i+16] = m[i];
- X[i+32] = (byte)(m[i] ^ X[i]);
- }
- // encrypt block
- int t = 0;
-
- for (int j=0;j<18;j++)
- {
- for (int k=0;k<48;k++)
- {
- t = X[k] ^= S[t];
- t = t & 0xff;
- }
- t = (t + j)%256;
- }
- }
- // 256-byte random permutation constructed from the digits of PI
- private static final byte[] S = {
- (byte)41,(byte)46,(byte)67,(byte)201,(byte)162,(byte)216,(byte)124,
- (byte)1,(byte)61,(byte)54,(byte)84,(byte)161,(byte)236,(byte)240,
- (byte)6,(byte)19,(byte)98,(byte)167,(byte)5,(byte)243,(byte)192,
- (byte)199,(byte)115,(byte)140,(byte)152,(byte)147,(byte)43,(byte)217,
- (byte)188,(byte)76,(byte)130,(byte)202,(byte)30,(byte)155,(byte)87,
- (byte)60,(byte)253,(byte)212,(byte)224,(byte)22,(byte)103,(byte)66,
- (byte)111,(byte)24,(byte)138,(byte)23,(byte)229,(byte)18,(byte)190,
- (byte)78,(byte)196,(byte)214,(byte)218,(byte)158,(byte)222,(byte)73,
- (byte)160,(byte)251,(byte)245,(byte)142,(byte)187,(byte)47,(byte)238,
- (byte)122,(byte)169,(byte)104,(byte)121,(byte)145,(byte)21,(byte)178,
- (byte)7,(byte)63,(byte)148,(byte)194,(byte)16,(byte)137,(byte)11,
- (byte)34,(byte)95,(byte)33,(byte)128,(byte)127,(byte)93,(byte)154,
- (byte)90,(byte)144,(byte)50,(byte)39,(byte)53,(byte)62,(byte)204,
- (byte)231,(byte)191,(byte)247,(byte)151,(byte)3,(byte)255,(byte)25,
- (byte)48,(byte)179,(byte)72,(byte)165,(byte)181,(byte)209,(byte)215,
- (byte)94,(byte)146,(byte)42,(byte)172,(byte)86,(byte)170,(byte)198,
- (byte)79,(byte)184,(byte)56,(byte)210,(byte)150,(byte)164,(byte)125,
- (byte)182,(byte)118,(byte)252,(byte)107,(byte)226,(byte)156,(byte)116,
- (byte)4,(byte)241,(byte)69,(byte)157,(byte)112,(byte)89,(byte)100,
- (byte)113,(byte)135,(byte)32,(byte)134,(byte)91,(byte)207,(byte)101,
- (byte)230,(byte)45,(byte)168,(byte)2,(byte)27,(byte)96,(byte)37,
- (byte)173,(byte)174,(byte)176,(byte)185,(byte)246,(byte)28,(byte)70,
- (byte)97,(byte)105,(byte)52,(byte)64,(byte)126,(byte)15,(byte)85,
- (byte)71,(byte)163,(byte)35,(byte)221,(byte)81,(byte)175,(byte)58,
- (byte)195,(byte)92,(byte)249,(byte)206,(byte)186,(byte)197,(byte)234,
- (byte)38,(byte)44,(byte)83,(byte)13,(byte)110,(byte)133,(byte)40,
- (byte)132, 9,(byte)211,(byte)223,(byte)205,(byte)244,(byte)65,
- (byte)129,(byte)77,(byte)82,(byte)106,(byte)220,(byte)55,(byte)200,
- (byte)108,(byte)193,(byte)171,(byte)250,(byte)36,(byte)225,(byte)123,
- (byte)8,(byte)12,(byte)189,(byte)177,(byte)74,(byte)120,(byte)136,
- (byte)149,(byte)139,(byte)227,(byte)99,(byte)232,(byte)109,(byte)233,
- (byte)203,(byte)213,(byte)254,(byte)59,(byte)0,(byte)29,(byte)57,
- (byte)242,(byte)239,(byte)183,(byte)14,(byte)102,(byte)88,(byte)208,
- (byte)228,(byte)166,(byte)119,(byte)114,(byte)248,(byte)235,(byte)117,
- (byte)75,(byte)10,(byte)49,(byte)68,(byte)80,(byte)180,(byte)143,
- (byte)237,(byte)31,(byte)26,(byte)219,(byte)153,(byte)141,(byte)51,
- (byte)159,(byte)17,(byte)131,(byte)20
- };
-
- public int getByteLength()
- {
- return 16;
- }
-
- public Memoable copy()
- {
- return new MD2Digest(this);
- }
-
- public void reset(Memoable other)
- {
- MD2Digest d = (MD2Digest)other;
-
- copyIn(d);
- }
-}
-
-
diff --git a/core/src/main/java/org/bouncycastle/crypto/digests/MD4Digest.java b/core/src/main/java/org/bouncycastle/crypto/digests/MD4Digest.java
deleted file mode 100644
index 68532bd2..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/MD4Digest.java
+++ /dev/null
@@ -1,291 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-
-import org.bouncycastle.util.Memoable;
-
-/**
- * implementation of MD4 as RFC 1320 by R. Rivest, MIT Laboratory for
- * Computer Science and RSA Data Security, Inc.
- * <p>
- * <b>NOTE</b>: This algorithm is only included for backwards compatability
- * with legacy applications, it's not secure, don't use it for anything new!
- */
-public class MD4Digest
- extends GeneralDigest
-{
- private static final int DIGEST_LENGTH = 16;
-
- private int H1, H2, H3, H4; // IV's
-
- private int[] X = new int[16];
- private int xOff;
-
- /**
- * Standard constructor
- */
- public MD4Digest()
- {
- reset();
- }
-
- /**
- * Copy constructor. This will copy the state of the provided
- * message digest.
- */
- public MD4Digest(MD4Digest t)
- {
- super(t);
-
- copyIn(t);
- }
-
- private void copyIn(MD4Digest t)
- {
- super.copyIn(t);
-
- H1 = t.H1;
- H2 = t.H2;
- H3 = t.H3;
- H4 = t.H4;
-
- System.arraycopy(t.X, 0, X, 0, t.X.length);
- xOff = t.xOff;
- }
-
- public String getAlgorithmName()
- {
- return "MD4";
- }
-
- public int getDigestSize()
- {
- return DIGEST_LENGTH;
- }
-
- protected void processWord(
- byte[] in,
- int inOff)
- {
- X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
- | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
-
- if (xOff == 16)
- {
- processBlock();
- }
- }
-
- protected void processLength(
- long bitLength)
- {
- if (xOff > 14)
- {
- processBlock();
- }
-
- X[14] = (int)(bitLength & 0xffffffff);
- X[15] = (int)(bitLength >>> 32);
- }
-
- private void unpackWord(
- int word,
- byte[] out,
- int outOff)
- {
- out[outOff] = (byte)word;
- out[outOff + 1] = (byte)(word >>> 8);
- out[outOff + 2] = (byte)(word >>> 16);
- out[outOff + 3] = (byte)(word >>> 24);
- }
-
- public int doFinal(
- byte[] out,
- int outOff)
- {
- finish();
-
- unpackWord(H1, out, outOff);
- unpackWord(H2, out, outOff + 4);
- unpackWord(H3, out, outOff + 8);
- unpackWord(H4, out, outOff + 12);
-
- reset();
-
- return DIGEST_LENGTH;
- }
-
- /**
- * reset the chaining variables to the IV values.
- */
- public void reset()
- {
- super.reset();
-
- H1 = 0x67452301;
- H2 = 0xefcdab89;
- H3 = 0x98badcfe;
- H4 = 0x10325476;
-
- xOff = 0;
-
- for (int i = 0; i != X.length; i++)
- {
- X[i] = 0;
- }
- }
-
- //
- // round 1 left rotates
- //
- private static final int S11 = 3;
- private static final int S12 = 7;
- private static final int S13 = 11;
- private static final int S14 = 19;
-
- //
- // round 2 left rotates
- //
- private static final int S21 = 3;
- private static final int S22 = 5;
- private static final int S23 = 9;
- private static final int S24 = 13;
-
- //
- // round 3 left rotates
- //
- private static final int S31 = 3;
- private static final int S32 = 9;
- private static final int S33 = 11;
- private static final int S34 = 15;
-
- /*
- * rotate int x left n bits.
- */
- private int rotateLeft(
- int x,
- int n)
- {
- return (x << n) | (x >>> (32 - n));
- }
-
- /*
- * F, G, H and I are the basic MD4 functions.
- */
- private int F(
- int u,
- int v,
- int w)
- {
- return (u & v) | (~u & w);
- }
-
- private int G(
- int u,
- int v,
- int w)
- {
- return (u & v) | (u & w) | (v & w);
- }
-
- private int H(
- int u,
- int v,
- int w)
- {
- return u ^ v ^ w;
- }
-
- protected void processBlock()
- {
- int a = H1;
- int b = H2;
- int c = H3;
- int d = H4;
-
- //
- // Round 1 - F cycle, 16 times.
- //
- a = rotateLeft(a + F(b, c, d) + X[ 0], S11);
- d = rotateLeft(d + F(a, b, c) + X[ 1], S12);
- c = rotateLeft(c + F(d, a, b) + X[ 2], S13);
- b = rotateLeft(b + F(c, d, a) + X[ 3], S14);
- a = rotateLeft(a + F(b, c, d) + X[ 4], S11);
- d = rotateLeft(d + F(a, b, c) + X[ 5], S12);
- c = rotateLeft(c + F(d, a, b) + X[ 6], S13);
- b = rotateLeft(b + F(c, d, a) + X[ 7], S14);
- a = rotateLeft(a + F(b, c, d) + X[ 8], S11);
- d = rotateLeft(d + F(a, b, c) + X[ 9], S12);
- c = rotateLeft(c + F(d, a, b) + X[10], S13);
- b = rotateLeft(b + F(c, d, a) + X[11], S14);
- a = rotateLeft(a + F(b, c, d) + X[12], S11);
- d = rotateLeft(d + F(a, b, c) + X[13], S12);
- c = rotateLeft(c + F(d, a, b) + X[14], S13);
- b = rotateLeft(b + F(c, d, a) + X[15], S14);
-
- //
- // Round 2 - G cycle, 16 times.
- //
- a = rotateLeft(a + G(b, c, d) + X[ 0] + 0x5a827999, S21);
- d = rotateLeft(d + G(a, b, c) + X[ 4] + 0x5a827999, S22);
- c = rotateLeft(c + G(d, a, b) + X[ 8] + 0x5a827999, S23);
- b = rotateLeft(b + G(c, d, a) + X[12] + 0x5a827999, S24);
- a = rotateLeft(a + G(b, c, d) + X[ 1] + 0x5a827999, S21);
- d = rotateLeft(d + G(a, b, c) + X[ 5] + 0x5a827999, S22);
- c = rotateLeft(c + G(d, a, b) + X[ 9] + 0x5a827999, S23);
- b = rotateLeft(b + G(c, d, a) + X[13] + 0x5a827999, S24);
- a = rotateLeft(a + G(b, c, d) + X[ 2] + 0x5a827999, S21);
- d = rotateLeft(d + G(a, b, c) + X[ 6] + 0x5a827999, S22);
- c = rotateLeft(c + G(d, a, b) + X[10] + 0x5a827999, S23);
- b = rotateLeft(b + G(c, d, a) + X[14] + 0x5a827999, S24);
- a = rotateLeft(a + G(b, c, d) + X[ 3] + 0x5a827999, S21);
- d = rotateLeft(d + G(a, b, c) + X[ 7] + 0x5a827999, S22);
- c = rotateLeft(c + G(d, a, b) + X[11] + 0x5a827999, S23);
- b = rotateLeft(b + G(c, d, a) + X[15] + 0x5a827999, S24);
-
- //
- // Round 3 - H cycle, 16 times.
- //
- a = rotateLeft(a + H(b, c, d) + X[ 0] + 0x6ed9eba1, S31);
- d = rotateLeft(d + H(a, b, c) + X[ 8] + 0x6ed9eba1, S32);
- c = rotateLeft(c + H(d, a, b) + X[ 4] + 0x6ed9eba1, S33);
- b = rotateLeft(b + H(c, d, a) + X[12] + 0x6ed9eba1, S34);
- a = rotateLeft(a + H(b, c, d) + X[ 2] + 0x6ed9eba1, S31);
- d = rotateLeft(d + H(a, b, c) + X[10] + 0x6ed9eba1, S32);
- c = rotateLeft(c + H(d, a, b) + X[ 6] + 0x6ed9eba1, S33);
- b = rotateLeft(b + H(c, d, a) + X[14] + 0x6ed9eba1, S34);
- a = rotateLeft(a + H(b, c, d) + X[ 1] + 0x6ed9eba1, S31);
- d = rotateLeft(d + H(a, b, c) + X[ 9] + 0x6ed9eba1, S32);
- c = rotateLeft(c + H(d, a, b) + X[ 5] + 0x6ed9eba1, S33);
- b = rotateLeft(b + H(c, d, a) + X[13] + 0x6ed9eba1, S34);
- a = rotateLeft(a + H(b, c, d) + X[ 3] + 0x6ed9eba1, S31);
- d = rotateLeft(d + H(a, b, c) + X[11] + 0x6ed9eba1, S32);
- c = rotateLeft(c + H(d, a, b) + X[ 7] + 0x6ed9eba1, S33);
- b = rotateLeft(b + H(c, d, a) + X[15] + 0x6ed9eba1, S34);
-
- H1 += a;
- H2 += b;
- H3 += c;
- H4 += d;
-
- //
- // reset the offset and clean out the word buffer.
- //
- xOff = 0;
- for (int i = 0; i != X.length; i++)
- {
- X[i] = 0;
- }
- }
-
- public Memoable copy()
- {
- return new MD4Digest(this);
- }
-
- public void reset(Memoable other)
- {
- MD4Digest d = (MD4Digest)other;
-
- copyIn(d);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/digests/MD5Digest.java b/core/src/main/java/org/bouncycastle/crypto/digests/MD5Digest.java
deleted file mode 100644
index ff9cedf0..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/MD5Digest.java
+++ /dev/null
@@ -1,323 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-
-import org.bouncycastle.util.Memoable;
-
-/**
- * implementation of MD5 as outlined in "Handbook of Applied Cryptography", pages 346 - 347.
- */
-public class MD5Digest
- extends GeneralDigest
-{
- private static final int DIGEST_LENGTH = 16;
-
- private int H1, H2, H3, H4; // IV's
-
- private int[] X = new int[16];
- private int xOff;
-
- /**
- * Standard constructor
- */
- public MD5Digest()
- {
- reset();
- }
-
- /**
- * Copy constructor. This will copy the state of the provided
- * message digest.
- */
- public MD5Digest(MD5Digest t)
- {
- super(t);
-
- copyIn(t);
- }
-
- private void copyIn(MD5Digest t)
- {
- super.copyIn(t);
-
- H1 = t.H1;
- H2 = t.H2;
- H3 = t.H3;
- H4 = t.H4;
-
- System.arraycopy(t.X, 0, X, 0, t.X.length);
- xOff = t.xOff;
- }
-
- public String getAlgorithmName()
- {
- return "MD5";
- }
-
- public int getDigestSize()
- {
- return DIGEST_LENGTH;
- }
-
- protected void processWord(
- byte[] in,
- int inOff)
- {
- X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
- | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
-
- if (xOff == 16)
- {
- processBlock();
- }
- }
-
- protected void processLength(
- long bitLength)
- {
- if (xOff > 14)
- {
- processBlock();
- }
-
- X[14] = (int)(bitLength & 0xffffffff);
- X[15] = (int)(bitLength >>> 32);
- }
-
- private void unpackWord(
- int word,
- byte[] out,
- int outOff)
- {
- out[outOff] = (byte)word;
- out[outOff + 1] = (byte)(word >>> 8);
- out[outOff + 2] = (byte)(word >>> 16);
- out[outOff + 3] = (byte)(word >>> 24);
- }
-
- public int doFinal(
- byte[] out,
- int outOff)
- {
- finish();
-
- unpackWord(H1, out, outOff);
- unpackWord(H2, out, outOff + 4);
- unpackWord(H3, out, outOff + 8);
- unpackWord(H4, out, outOff + 12);
-
- reset();
-
- return DIGEST_LENGTH;
- }
-
- /**
- * reset the chaining variables to the IV values.
- */
- public void reset()
- {
- super.reset();
-
- H1 = 0x67452301;
- H2 = 0xefcdab89;
- H3 = 0x98badcfe;
- H4 = 0x10325476;
-
- xOff = 0;
-
- for (int i = 0; i != X.length; i++)
- {
- X[i] = 0;
- }
- }
-
- //
- // round 1 left rotates
- //
- private static final int S11 = 7;
- private static final int S12 = 12;
- private static final int S13 = 17;
- private static final int S14 = 22;
-
- //
- // round 2 left rotates
- //
- private static final int S21 = 5;
- private static final int S22 = 9;
- private static final int S23 = 14;
- private static final int S24 = 20;
-
- //
- // round 3 left rotates
- //
- private static final int S31 = 4;
- private static final int S32 = 11;
- private static final int S33 = 16;
- private static final int S34 = 23;
-
- //
- // round 4 left rotates
- //
- private static final int S41 = 6;
- private static final int S42 = 10;
- private static final int S43 = 15;
- private static final int S44 = 21;
-
- /*
- * rotate int x left n bits.
- */
- private int rotateLeft(
- int x,
- int n)
- {
- return (x << n) | (x >>> (32 - n));
- }
-
- /*
- * F, G, H and I are the basic MD5 functions.
- */
- private int F(
- int u,
- int v,
- int w)
- {
- return (u & v) | (~u & w);
- }
-
- private int G(
- int u,
- int v,
- int w)
- {
- return (u & w) | (v & ~w);
- }
-
- private int H(
- int u,
- int v,
- int w)
- {
- return u ^ v ^ w;
- }
-
- private int K(
- int u,
- int v,
- int w)
- {
- return v ^ (u | ~w);
- }
-
- protected void processBlock()
- {
- int a = H1;
- int b = H2;
- int c = H3;
- int d = H4;
-
- //
- // Round 1 - F cycle, 16 times.
- //
- a = rotateLeft(a + F(b, c, d) + X[ 0] + 0xd76aa478, S11) + b;
- d = rotateLeft(d + F(a, b, c) + X[ 1] + 0xe8c7b756, S12) + a;
- c = rotateLeft(c + F(d, a, b) + X[ 2] + 0x242070db, S13) + d;
- b = rotateLeft(b + F(c, d, a) + X[ 3] + 0xc1bdceee, S14) + c;
- a = rotateLeft(a + F(b, c, d) + X[ 4] + 0xf57c0faf, S11) + b;
- d = rotateLeft(d + F(a, b, c) + X[ 5] + 0x4787c62a, S12) + a;
- c = rotateLeft(c + F(d, a, b) + X[ 6] + 0xa8304613, S13) + d;
- b = rotateLeft(b + F(c, d, a) + X[ 7] + 0xfd469501, S14) + c;
- a = rotateLeft(a + F(b, c, d) + X[ 8] + 0x698098d8, S11) + b;
- d = rotateLeft(d + F(a, b, c) + X[ 9] + 0x8b44f7af, S12) + a;
- c = rotateLeft(c + F(d, a, b) + X[10] + 0xffff5bb1, S13) + d;
- b = rotateLeft(b + F(c, d, a) + X[11] + 0x895cd7be, S14) + c;
- a = rotateLeft(a + F(b, c, d) + X[12] + 0x6b901122, S11) + b;
- d = rotateLeft(d + F(a, b, c) + X[13] + 0xfd987193, S12) + a;
- c = rotateLeft(c + F(d, a, b) + X[14] + 0xa679438e, S13) + d;
- b = rotateLeft(b + F(c, d, a) + X[15] + 0x49b40821, S14) + c;
-
- //
- // Round 2 - G cycle, 16 times.
- //
- a = rotateLeft(a + G(b, c, d) + X[ 1] + 0xf61e2562, S21) + b;
- d = rotateLeft(d + G(a, b, c) + X[ 6] + 0xc040b340, S22) + a;
- c = rotateLeft(c + G(d, a, b) + X[11] + 0x265e5a51, S23) + d;
- b = rotateLeft(b + G(c, d, a) + X[ 0] + 0xe9b6c7aa, S24) + c;
- a = rotateLeft(a + G(b, c, d) + X[ 5] + 0xd62f105d, S21) + b;
- d = rotateLeft(d + G(a, b, c) + X[10] + 0x02441453, S22) + a;
- c = rotateLeft(c + G(d, a, b) + X[15] + 0xd8a1e681, S23) + d;
- b = rotateLeft(b + G(c, d, a) + X[ 4] + 0xe7d3fbc8, S24) + c;
- a = rotateLeft(a + G(b, c, d) + X[ 9] + 0x21e1cde6, S21) + b;
- d = rotateLeft(d + G(a, b, c) + X[14] + 0xc33707d6, S22) + a;
- c = rotateLeft(c + G(d, a, b) + X[ 3] + 0xf4d50d87, S23) + d;
- b = rotateLeft(b + G(c, d, a) + X[ 8] + 0x455a14ed, S24) + c;
- a = rotateLeft(a + G(b, c, d) + X[13] + 0xa9e3e905, S21) + b;
- d = rotateLeft(d + G(a, b, c) + X[ 2] + 0xfcefa3f8, S22) + a;
- c = rotateLeft(c + G(d, a, b) + X[ 7] + 0x676f02d9, S23) + d;
- b = rotateLeft(b + G(c, d, a) + X[12] + 0x8d2a4c8a, S24) + c;
-
- //
- // Round 3 - H cycle, 16 times.
- //
- a = rotateLeft(a + H(b, c, d) + X[ 5] + 0xfffa3942, S31) + b;
- d = rotateLeft(d + H(a, b, c) + X[ 8] + 0x8771f681, S32) + a;
- c = rotateLeft(c + H(d, a, b) + X[11] + 0x6d9d6122, S33) + d;
- b = rotateLeft(b + H(c, d, a) + X[14] + 0xfde5380c, S34) + c;
- a = rotateLeft(a + H(b, c, d) + X[ 1] + 0xa4beea44, S31) + b;
- d = rotateLeft(d + H(a, b, c) + X[ 4] + 0x4bdecfa9, S32) + a;
- c = rotateLeft(c + H(d, a, b) + X[ 7] + 0xf6bb4b60, S33) + d;
- b = rotateLeft(b + H(c, d, a) + X[10] + 0xbebfbc70, S34) + c;
- a = rotateLeft(a + H(b, c, d) + X[13] + 0x289b7ec6, S31) + b;
- d = rotateLeft(d + H(a, b, c) + X[ 0] + 0xeaa127fa, S32) + a;
- c = rotateLeft(c + H(d, a, b) + X[ 3] + 0xd4ef3085, S33) + d;
- b = rotateLeft(b + H(c, d, a) + X[ 6] + 0x04881d05, S34) + c;
- a = rotateLeft(a + H(b, c, d) + X[ 9] + 0xd9d4d039, S31) + b;
- d = rotateLeft(d + H(a, b, c) + X[12] + 0xe6db99e5, S32) + a;
- c = rotateLeft(c + H(d, a, b) + X[15] + 0x1fa27cf8, S33) + d;
- b = rotateLeft(b + H(c, d, a) + X[ 2] + 0xc4ac5665, S34) + c;
-
- //
- // Round 4 - K cycle, 16 times.
- //
- a = rotateLeft(a + K(b, c, d) + X[ 0] + 0xf4292244, S41) + b;
- d = rotateLeft(d + K(a, b, c) + X[ 7] + 0x432aff97, S42) + a;
- c = rotateLeft(c + K(d, a, b) + X[14] + 0xab9423a7, S43) + d;
- b = rotateLeft(b + K(c, d, a) + X[ 5] + 0xfc93a039, S44) + c;
- a = rotateLeft(a + K(b, c, d) + X[12] + 0x655b59c3, S41) + b;
- d = rotateLeft(d + K(a, b, c) + X[ 3] + 0x8f0ccc92, S42) + a;
- c = rotateLeft(c + K(d, a, b) + X[10] + 0xffeff47d, S43) + d;
- b = rotateLeft(b + K(c, d, a) + X[ 1] + 0x85845dd1, S44) + c;
- a = rotateLeft(a + K(b, c, d) + X[ 8] + 0x6fa87e4f, S41) + b;
- d = rotateLeft(d + K(a, b, c) + X[15] + 0xfe2ce6e0, S42) + a;
- c = rotateLeft(c + K(d, a, b) + X[ 6] + 0xa3014314, S43) + d;
- b = rotateLeft(b + K(c, d, a) + X[13] + 0x4e0811a1, S44) + c;
- a = rotateLeft(a + K(b, c, d) + X[ 4] + 0xf7537e82, S41) + b;
- d = rotateLeft(d + K(a, b, c) + X[11] + 0xbd3af235, S42) + a;
- c = rotateLeft(c + K(d, a, b) + X[ 2] + 0x2ad7d2bb, S43) + d;
- b = rotateLeft(b + K(c, d, a) + X[ 9] + 0xeb86d391, S44) + c;
-
- H1 += a;
- H2 += b;
- H3 += c;
- H4 += d;
-
- //
- // reset the offset and clean out the word buffer.
- //
- xOff = 0;
- for (int i = 0; i != X.length; i++)
- {
- X[i] = 0;
- }
- }
-
- public Memoable copy()
- {
- return new MD5Digest(this);
- }
-
- public void reset(Memoable other)
- {
- MD5Digest d = (MD5Digest)other;
-
- copyIn(d);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/digests/NonMemoableDigest.java b/core/src/main/java/org/bouncycastle/crypto/digests/NonMemoableDigest.java
deleted file mode 100644
index 87a4d249..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/NonMemoableDigest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-import org.bouncycastle.crypto.ExtendedDigest;
-
-/**
- * Wrapper removes exposure to the Memoable interface on an ExtendedDigest implementation.
- */
-public class NonMemoableDigest
- implements ExtendedDigest
-{
- private ExtendedDigest baseDigest;
-
- /**
- * Base constructor.
- *
- * @param baseDigest underlying digest to use.
- * @exception IllegalArgumentException if baseDigest is null
- */
- public NonMemoableDigest(
- ExtendedDigest baseDigest)
- {
- if (baseDigest == null)
- {
- throw new IllegalArgumentException("baseDigest must not be null");
- }
-
- this.baseDigest = baseDigest;
- }
-
- public String getAlgorithmName()
- {
- return baseDigest.getAlgorithmName();
- }
-
- public int getDigestSize()
- {
- return baseDigest.getDigestSize();
- }
-
- public void update(byte in)
- {
- baseDigest.update(in);
- }
-
- public void update(byte[] in, int inOff, int len)
- {
- baseDigest.update(in, inOff, len);
- }
-
- public int doFinal(byte[] out, int outOff)
- {
- return baseDigest.doFinal(out, outOff);
- }
-
- public void reset()
- {
- baseDigest.reset();
- }
-
- public int getByteLength()
- {
- return baseDigest.getByteLength();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/digests/NullDigest.java b/core/src/main/java/org/bouncycastle/crypto/digests/NullDigest.java
deleted file mode 100644
index 6cb0d4ac..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/NullDigest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-import java.io.ByteArrayOutputStream;
-
-import org.bouncycastle.crypto.Digest;
-
-
-public class NullDigest
- implements Digest
-{
- private ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- public String getAlgorithmName()
- {
- return "NULL";
- }
-
- public int getDigestSize()
- {
- return bOut.size();
- }
-
- public void update(byte in)
- {
- bOut.write(in);
- }
-
- public void update(byte[] in, int inOff, int len)
- {
- bOut.write(in, inOff, len);
- }
-
- public int doFinal(byte[] out, int outOff)
- {
- byte[] res = bOut.toByteArray();
-
- System.arraycopy(res, 0, out, outOff, res.length);
-
- reset();
-
- return res.length;
- }
-
- public void reset()
- {
- bOut.reset();
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/crypto/digests/RIPEMD128Digest.java b/core/src/main/java/org/bouncycastle/crypto/digests/RIPEMD128Digest.java
deleted file mode 100644
index ec7fa859..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/RIPEMD128Digest.java
+++ /dev/null
@@ -1,482 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-
-import org.bouncycastle.util.Memoable;
-
-/**
- * implementation of RIPEMD128
- */
-public class RIPEMD128Digest
- extends GeneralDigest
-{
- private static final int DIGEST_LENGTH = 16;
-
- private int H0, H1, H2, H3; // IV's
-
- private int[] X = new int[16];
- private int xOff;
-
- /**
- * Standard constructor
- */
- public RIPEMD128Digest()
- {
- reset();
- }
-
- /**
- * Copy constructor. This will copy the state of the provided
- * message digest.
- */
- public RIPEMD128Digest(RIPEMD128Digest t)
- {
- super(t);
-
- copyIn(t);
- }
-
- private void copyIn(RIPEMD128Digest t)
- {
- super.copyIn(t);
-
- H0 = t.H0;
- H1 = t.H1;
- H2 = t.H2;
- H3 = t.H3;
-
- System.arraycopy(t.X, 0, X, 0, t.X.length);
- xOff = t.xOff;
- }
-
- public String getAlgorithmName()
- {
- return "RIPEMD128";
- }
-
- public int getDigestSize()
- {
- return DIGEST_LENGTH;
- }
-
- protected void processWord(
- byte[] in,
- int inOff)
- {
- X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
- | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
-
- if (xOff == 16)
- {
- processBlock();
- }
- }
-
- protected void processLength(
- long bitLength)
- {
- if (xOff > 14)
- {
- processBlock();
- }
-
- X[14] = (int)(bitLength & 0xffffffff);
- X[15] = (int)(bitLength >>> 32);
- }
-
- private void unpackWord(
- int word,
- byte[] out,
- int outOff)
- {
- out[outOff] = (byte)word;
- out[outOff + 1] = (byte)(word >>> 8);
- out[outOff + 2] = (byte)(word >>> 16);
- out[outOff + 3] = (byte)(word >>> 24);
- }
-
- public int doFinal(
- byte[] out,
- int outOff)
- {
- finish();
-
- unpackWord(H0, out, outOff);
- unpackWord(H1, out, outOff + 4);
- unpackWord(H2, out, outOff + 8);
- unpackWord(H3, out, outOff + 12);
-
- reset();
-
- return DIGEST_LENGTH;
- }
-
- /**
- * reset the chaining variables to the IV values.
- */
- public void reset()
- {
- super.reset();
-
- H0 = 0x67452301;
- H1 = 0xefcdab89;
- H2 = 0x98badcfe;
- H3 = 0x10325476;
-
- xOff = 0;
-
- for (int i = 0; i != X.length; i++)
- {
- X[i] = 0;
- }
- }
-
- /*
- * rotate int x left n bits.
- */
- private int RL(
- int x,
- int n)
- {
- return (x << n) | (x >>> (32 - n));
- }
-
- /*
- * f1,f2,f3,f4 are the basic RIPEMD128 functions.
- */
-
- /*
- * F
- */
- private int f1(
- int x,
- int y,
- int z)
- {
- return x ^ y ^ z;
- }
-
- /*
- * G
- */
- private int f2(
- int x,
- int y,
- int z)
- {
- return (x & y) | (~x & z);
- }
-
- /*
- * H
- */
- private int f3(
- int x,
- int y,
- int z)
- {
- return (x | ~y) ^ z;
- }
-
- /*
- * I
- */
- private int f4(
- int x,
- int y,
- int z)
- {
- return (x & z) | (y & ~z);
- }
-
- private int F1(
- int a,
- int b,
- int c,
- int d,
- int x,
- int s)
- {
- return RL(a + f1(b, c, d) + x, s);
- }
-
- private int F2(
- int a,
- int b,
- int c,
- int d,
- int x,
- int s)
- {
- return RL(a + f2(b, c, d) + x + 0x5a827999, s);
- }
-
- private int F3(
- int a,
- int b,
- int c,
- int d,
- int x,
- int s)
- {
- return RL(a + f3(b, c, d) + x + 0x6ed9eba1, s);
- }
-
- private int F4(
- int a,
- int b,
- int c,
- int d,
- int x,
- int s)
- {
- return RL(a + f4(b, c, d) + x + 0x8f1bbcdc, s);
- }
-
- private int FF1(
- int a,
- int b,
- int c,
- int d,
- int x,
- int s)
- {
- return RL(a + f1(b, c, d) + x, s);
- }
-
- private int FF2(
- int a,
- int b,
- int c,
- int d,
- int x,
- int s)
- {
- return RL(a + f2(b, c, d) + x + 0x6d703ef3, s);
- }
-
- private int FF3(
- int a,
- int b,
- int c,
- int d,
- int x,
- int s)
- {
- return RL(a + f3(b, c, d) + x + 0x5c4dd124, s);
- }
-
- private int FF4(
- int a,
- int b,
- int c,
- int d,
- int x,
- int s)
- {
- return RL(a + f4(b, c, d) + x + 0x50a28be6, s);
- }
-
- protected void processBlock()
- {
- int a, aa;
- int b, bb;
- int c, cc;
- int d, dd;
-
- a = aa = H0;
- b = bb = H1;
- c = cc = H2;
- d = dd = H3;
-
- //
- // Round 1
- //
- a = F1(a, b, c, d, X[ 0], 11);
- d = F1(d, a, b, c, X[ 1], 14);
- c = F1(c, d, a, b, X[ 2], 15);
- b = F1(b, c, d, a, X[ 3], 12);
- a = F1(a, b, c, d, X[ 4], 5);
- d = F1(d, a, b, c, X[ 5], 8);
- c = F1(c, d, a, b, X[ 6], 7);
- b = F1(b, c, d, a, X[ 7], 9);
- a = F1(a, b, c, d, X[ 8], 11);
- d = F1(d, a, b, c, X[ 9], 13);
- c = F1(c, d, a, b, X[10], 14);
- b = F1(b, c, d, a, X[11], 15);
- a = F1(a, b, c, d, X[12], 6);
- d = F1(d, a, b, c, X[13], 7);
- c = F1(c, d, a, b, X[14], 9);
- b = F1(b, c, d, a, X[15], 8);
-
- //
- // Round 2
- //
- a = F2(a, b, c, d, X[ 7], 7);
- d = F2(d, a, b, c, X[ 4], 6);
- c = F2(c, d, a, b, X[13], 8);
- b = F2(b, c, d, a, X[ 1], 13);
- a = F2(a, b, c, d, X[10], 11);
- d = F2(d, a, b, c, X[ 6], 9);
- c = F2(c, d, a, b, X[15], 7);
- b = F2(b, c, d, a, X[ 3], 15);
- a = F2(a, b, c, d, X[12], 7);
- d = F2(d, a, b, c, X[ 0], 12);
- c = F2(c, d, a, b, X[ 9], 15);
- b = F2(b, c, d, a, X[ 5], 9);
- a = F2(a, b, c, d, X[ 2], 11);
- d = F2(d, a, b, c, X[14], 7);
- c = F2(c, d, a, b, X[11], 13);
- b = F2(b, c, d, a, X[ 8], 12);
-
- //
- // Round 3
- //
- a = F3(a, b, c, d, X[ 3], 11);
- d = F3(d, a, b, c, X[10], 13);
- c = F3(c, d, a, b, X[14], 6);
- b = F3(b, c, d, a, X[ 4], 7);
- a = F3(a, b, c, d, X[ 9], 14);
- d = F3(d, a, b, c, X[15], 9);
- c = F3(c, d, a, b, X[ 8], 13);
- b = F3(b, c, d, a, X[ 1], 15);
- a = F3(a, b, c, d, X[ 2], 14);
- d = F3(d, a, b, c, X[ 7], 8);
- c = F3(c, d, a, b, X[ 0], 13);
- b = F3(b, c, d, a, X[ 6], 6);
- a = F3(a, b, c, d, X[13], 5);
- d = F3(d, a, b, c, X[11], 12);
- c = F3(c, d, a, b, X[ 5], 7);
- b = F3(b, c, d, a, X[12], 5);
-
- //
- // Round 4
- //
- a = F4(a, b, c, d, X[ 1], 11);
- d = F4(d, a, b, c, X[ 9], 12);
- c = F4(c, d, a, b, X[11], 14);
- b = F4(b, c, d, a, X[10], 15);
- a = F4(a, b, c, d, X[ 0], 14);
- d = F4(d, a, b, c, X[ 8], 15);
- c = F4(c, d, a, b, X[12], 9);
- b = F4(b, c, d, a, X[ 4], 8);
- a = F4(a, b, c, d, X[13], 9);
- d = F4(d, a, b, c, X[ 3], 14);
- c = F4(c, d, a, b, X[ 7], 5);
- b = F4(b, c, d, a, X[15], 6);
- a = F4(a, b, c, d, X[14], 8);
- d = F4(d, a, b, c, X[ 5], 6);
- c = F4(c, d, a, b, X[ 6], 5);
- b = F4(b, c, d, a, X[ 2], 12);
-
- //
- // Parallel round 1
- //
- aa = FF4(aa, bb, cc, dd, X[ 5], 8);
- dd = FF4(dd, aa, bb, cc, X[14], 9);
- cc = FF4(cc, dd, aa, bb, X[ 7], 9);
- bb = FF4(bb, cc, dd, aa, X[ 0], 11);
- aa = FF4(aa, bb, cc, dd, X[ 9], 13);
- dd = FF4(dd, aa, bb, cc, X[ 2], 15);
- cc = FF4(cc, dd, aa, bb, X[11], 15);
- bb = FF4(bb, cc, dd, aa, X[ 4], 5);
- aa = FF4(aa, bb, cc, dd, X[13], 7);
- dd = FF4(dd, aa, bb, cc, X[ 6], 7);
- cc = FF4(cc, dd, aa, bb, X[15], 8);
- bb = FF4(bb, cc, dd, aa, X[ 8], 11);
- aa = FF4(aa, bb, cc, dd, X[ 1], 14);
- dd = FF4(dd, aa, bb, cc, X[10], 14);
- cc = FF4(cc, dd, aa, bb, X[ 3], 12);
- bb = FF4(bb, cc, dd, aa, X[12], 6);
-
- //
- // Parallel round 2
- //
- aa = FF3(aa, bb, cc, dd, X[ 6], 9);
- dd = FF3(dd, aa, bb, cc, X[11], 13);
- cc = FF3(cc, dd, aa, bb, X[ 3], 15);
- bb = FF3(bb, cc, dd, aa, X[ 7], 7);
- aa = FF3(aa, bb, cc, dd, X[ 0], 12);
- dd = FF3(dd, aa, bb, cc, X[13], 8);
- cc = FF3(cc, dd, aa, bb, X[ 5], 9);
- bb = FF3(bb, cc, dd, aa, X[10], 11);
- aa = FF3(aa, bb, cc, dd, X[14], 7);
- dd = FF3(dd, aa, bb, cc, X[15], 7);
- cc = FF3(cc, dd, aa, bb, X[ 8], 12);
- bb = FF3(bb, cc, dd, aa, X[12], 7);
- aa = FF3(aa, bb, cc, dd, X[ 4], 6);
- dd = FF3(dd, aa, bb, cc, X[ 9], 15);
- cc = FF3(cc, dd, aa, bb, X[ 1], 13);
- bb = FF3(bb, cc, dd, aa, X[ 2], 11);
-
- //
- // Parallel round 3
- //
- aa = FF2(aa, bb, cc, dd, X[15], 9);
- dd = FF2(dd, aa, bb, cc, X[ 5], 7);
- cc = FF2(cc, dd, aa, bb, X[ 1], 15);
- bb = FF2(bb, cc, dd, aa, X[ 3], 11);
- aa = FF2(aa, bb, cc, dd, X[ 7], 8);
- dd = FF2(dd, aa, bb, cc, X[14], 6);
- cc = FF2(cc, dd, aa, bb, X[ 6], 6);
- bb = FF2(bb, cc, dd, aa, X[ 9], 14);
- aa = FF2(aa, bb, cc, dd, X[11], 12);
- dd = FF2(dd, aa, bb, cc, X[ 8], 13);
- cc = FF2(cc, dd, aa, bb, X[12], 5);
- bb = FF2(bb, cc, dd, aa, X[ 2], 14);
- aa = FF2(aa, bb, cc, dd, X[10], 13);
- dd = FF2(dd, aa, bb, cc, X[ 0], 13);
- cc = FF2(cc, dd, aa, bb, X[ 4], 7);
- bb = FF2(bb, cc, dd, aa, X[13], 5);
-
- //
- // Parallel round 4
- //
- aa = FF1(aa, bb, cc, dd, X[ 8], 15);
- dd = FF1(dd, aa, bb, cc, X[ 6], 5);
- cc = FF1(cc, dd, aa, bb, X[ 4], 8);
- bb = FF1(bb, cc, dd, aa, X[ 1], 11);
- aa = FF1(aa, bb, cc, dd, X[ 3], 14);
- dd = FF1(dd, aa, bb, cc, X[11], 14);
- cc = FF1(cc, dd, aa, bb, X[15], 6);
- bb = FF1(bb, cc, dd, aa, X[ 0], 14);
- aa = FF1(aa, bb, cc, dd, X[ 5], 6);
- dd = FF1(dd, aa, bb, cc, X[12], 9);
- cc = FF1(cc, dd, aa, bb, X[ 2], 12);
- bb = FF1(bb, cc, dd, aa, X[13], 9);
- aa = FF1(aa, bb, cc, dd, X[ 9], 12);
- dd = FF1(dd, aa, bb, cc, X[ 7], 5);
- cc = FF1(cc, dd, aa, bb, X[10], 15);
- bb = FF1(bb, cc, dd, aa, X[14], 8);
-
- dd += c + H1; // final result for H0
-
- //
- // combine the results
- //
- H1 = H2 + d + aa;
- H2 = H3 + a + bb;
- H3 = H0 + b + cc;
- H0 = dd;
-
- //
- // reset the offset and clean out the word buffer.
- //
- xOff = 0;
- for (int i = 0; i != X.length; i++)
- {
- X[i] = 0;
- }
- }
-
- public Memoable copy()
- {
- return new RIPEMD128Digest(this);
- }
-
- public void reset(Memoable other)
- {
- RIPEMD128Digest d = (RIPEMD128Digest)other;
-
- copyIn(d);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/digests/RIPEMD160Digest.java b/core/src/main/java/org/bouncycastle/crypto/digests/RIPEMD160Digest.java
deleted file mode 100644
index 20c81e68..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/RIPEMD160Digest.java
+++ /dev/null
@@ -1,443 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-
-import org.bouncycastle.util.Memoable;
-
-/**
- * implementation of RIPEMD see,
- * http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html
- */
-public class RIPEMD160Digest
- extends GeneralDigest
-{
- private static final int DIGEST_LENGTH = 20;
-
- private int H0, H1, H2, H3, H4; // IV's
-
- private int[] X = new int[16];
- private int xOff;
-
- /**
- * Standard constructor
- */
- public RIPEMD160Digest()
- {
- reset();
- }
-
- /**
- * Copy constructor. This will copy the state of the provided
- * message digest.
- */
- public RIPEMD160Digest(RIPEMD160Digest t)
- {
- super(t);
-
- copyIn(t);
- }
-
- private void copyIn(RIPEMD160Digest t)
- {
- super.copyIn(t);
-
- H0 = t.H0;
- H1 = t.H1;
- H2 = t.H2;
- H3 = t.H3;
- H4 = t.H4;
-
- System.arraycopy(t.X, 0, X, 0, t.X.length);
- xOff = t.xOff;
- }
-
- public String getAlgorithmName()
- {
- return "RIPEMD160";
- }
-
- public int getDigestSize()
- {
- return DIGEST_LENGTH;
- }
-
- protected void processWord(
- byte[] in,
- int inOff)
- {
- X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
- | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
-
- if (xOff == 16)
- {
- processBlock();
- }
- }
-
- protected void processLength(
- long bitLength)
- {
- if (xOff > 14)
- {
- processBlock();
- }
-
- X[14] = (int)(bitLength & 0xffffffff);
- X[15] = (int)(bitLength >>> 32);
- }
-
- private void unpackWord(
- int word,
- byte[] out,
- int outOff)
- {
- out[outOff] = (byte)word;
- out[outOff + 1] = (byte)(word >>> 8);
- out[outOff + 2] = (byte)(word >>> 16);
- out[outOff + 3] = (byte)(word >>> 24);
- }
-
- public int doFinal(
- byte[] out,
- int outOff)
- {
- finish();
-
- unpackWord(H0, out, outOff);
- unpackWord(H1, out, outOff + 4);
- unpackWord(H2, out, outOff + 8);
- unpackWord(H3, out, outOff + 12);
- unpackWord(H4, out, outOff + 16);
-
- reset();
-
- return DIGEST_LENGTH;
- }
-
- /**
- * reset the chaining variables to the IV values.
- */
- public void reset()
- {
- super.reset();
-
- H0 = 0x67452301;
- H1 = 0xefcdab89;
- H2 = 0x98badcfe;
- H3 = 0x10325476;
- H4 = 0xc3d2e1f0;
-
- xOff = 0;
-
- for (int i = 0; i != X.length; i++)
- {
- X[i] = 0;
- }
- }
-
- /*
- * rotate int x left n bits.
- */
- private int RL(
- int x,
- int n)
- {
- return (x << n) | (x >>> (32 - n));
- }
-
- /*
- * f1,f2,f3,f4,f5 are the basic RIPEMD160 functions.
- */
-
- /*
- * rounds 0-15
- */
- private int f1(
- int x,
- int y,
- int z)
- {
- return x ^ y ^ z;
- }
-
- /*
- * rounds 16-31
- */
- private int f2(
- int x,
- int y,
- int z)
- {
- return (x & y) | (~x & z);
- }
-
- /*
- * rounds 32-47
- */
- private int f3(
- int x,
- int y,
- int z)
- {
- return (x | ~y) ^ z;
- }
-
- /*
- * rounds 48-63
- */
- private int f4(
- int x,
- int y,
- int z)
- {
- return (x & z) | (y & ~z);
- }
-
- /*
- * rounds 64-79
- */
- private int f5(
- int x,
- int y,
- int z)
- {
- return x ^ (y | ~z);
- }
-
- protected void processBlock()
- {
- int a, aa;
- int b, bb;
- int c, cc;
- int d, dd;
- int e, ee;
-
- a = aa = H0;
- b = bb = H1;
- c = cc = H2;
- d = dd = H3;
- e = ee = H4;
-
- //
- // Rounds 1 - 16
- //
- // left
- a = RL(a + f1(b,c,d) + X[ 0], 11) + e; c = RL(c, 10);
- e = RL(e + f1(a,b,c) + X[ 1], 14) + d; b = RL(b, 10);
- d = RL(d + f1(e,a,b) + X[ 2], 15) + c; a = RL(a, 10);
- c = RL(c + f1(d,e,a) + X[ 3], 12) + b; e = RL(e, 10);
- b = RL(b + f1(c,d,e) + X[ 4], 5) + a; d = RL(d, 10);
- a = RL(a + f1(b,c,d) + X[ 5], 8) + e; c = RL(c, 10);
- e = RL(e + f1(a,b,c) + X[ 6], 7) + d; b = RL(b, 10);
- d = RL(d + f1(e,a,b) + X[ 7], 9) + c; a = RL(a, 10);
- c = RL(c + f1(d,e,a) + X[ 8], 11) + b; e = RL(e, 10);
- b = RL(b + f1(c,d,e) + X[ 9], 13) + a; d = RL(d, 10);
- a = RL(a + f1(b,c,d) + X[10], 14) + e; c = RL(c, 10);
- e = RL(e + f1(a,b,c) + X[11], 15) + d; b = RL(b, 10);
- d = RL(d + f1(e,a,b) + X[12], 6) + c; a = RL(a, 10);
- c = RL(c + f1(d,e,a) + X[13], 7) + b; e = RL(e, 10);
- b = RL(b + f1(c,d,e) + X[14], 9) + a; d = RL(d, 10);
- a = RL(a + f1(b,c,d) + X[15], 8) + e; c = RL(c, 10);
-
- // right
- aa = RL(aa + f5(bb,cc,dd) + X[ 5] + 0x50a28be6, 8) + ee; cc = RL(cc, 10);
- ee = RL(ee + f5(aa,bb,cc) + X[14] + 0x50a28be6, 9) + dd; bb = RL(bb, 10);
- dd = RL(dd + f5(ee,aa,bb) + X[ 7] + 0x50a28be6, 9) + cc; aa = RL(aa, 10);
- cc = RL(cc + f5(dd,ee,aa) + X[ 0] + 0x50a28be6, 11) + bb; ee = RL(ee, 10);
- bb = RL(bb + f5(cc,dd,ee) + X[ 9] + 0x50a28be6, 13) + aa; dd = RL(dd, 10);
- aa = RL(aa + f5(bb,cc,dd) + X[ 2] + 0x50a28be6, 15) + ee; cc = RL(cc, 10);
- ee = RL(ee + f5(aa,bb,cc) + X[11] + 0x50a28be6, 15) + dd; bb = RL(bb, 10);
- dd = RL(dd + f5(ee,aa,bb) + X[ 4] + 0x50a28be6, 5) + cc; aa = RL(aa, 10);
- cc = RL(cc + f5(dd,ee,aa) + X[13] + 0x50a28be6, 7) + bb; ee = RL(ee, 10);
- bb = RL(bb + f5(cc,dd,ee) + X[ 6] + 0x50a28be6, 7) + aa; dd = RL(dd, 10);
- aa = RL(aa + f5(bb,cc,dd) + X[15] + 0x50a28be6, 8) + ee; cc = RL(cc, 10);
- ee = RL(ee + f5(aa,bb,cc) + X[ 8] + 0x50a28be6, 11) + dd; bb = RL(bb, 10);
- dd = RL(dd + f5(ee,aa,bb) + X[ 1] + 0x50a28be6, 14) + cc; aa = RL(aa, 10);
- cc = RL(cc + f5(dd,ee,aa) + X[10] + 0x50a28be6, 14) + bb; ee = RL(ee, 10);
- bb = RL(bb + f5(cc,dd,ee) + X[ 3] + 0x50a28be6, 12) + aa; dd = RL(dd, 10);
- aa = RL(aa + f5(bb,cc,dd) + X[12] + 0x50a28be6, 6) + ee; cc = RL(cc, 10);
-
- //
- // Rounds 16-31
- //
- // left
- e = RL(e + f2(a,b,c) + X[ 7] + 0x5a827999, 7) + d; b = RL(b, 10);
- d = RL(d + f2(e,a,b) + X[ 4] + 0x5a827999, 6) + c; a = RL(a, 10);
- c = RL(c + f2(d,e,a) + X[13] + 0x5a827999, 8) + b; e = RL(e, 10);
- b = RL(b + f2(c,d,e) + X[ 1] + 0x5a827999, 13) + a; d = RL(d, 10);
- a = RL(a + f2(b,c,d) + X[10] + 0x5a827999, 11) + e; c = RL(c, 10);
- e = RL(e + f2(a,b,c) + X[ 6] + 0x5a827999, 9) + d; b = RL(b, 10);
- d = RL(d + f2(e,a,b) + X[15] + 0x5a827999, 7) + c; a = RL(a, 10);
- c = RL(c + f2(d,e,a) + X[ 3] + 0x5a827999, 15) + b; e = RL(e, 10);
- b = RL(b + f2(c,d,e) + X[12] + 0x5a827999, 7) + a; d = RL(d, 10);
- a = RL(a + f2(b,c,d) + X[ 0] + 0x5a827999, 12) + e; c = RL(c, 10);
- e = RL(e + f2(a,b,c) + X[ 9] + 0x5a827999, 15) + d; b = RL(b, 10);
- d = RL(d + f2(e,a,b) + X[ 5] + 0x5a827999, 9) + c; a = RL(a, 10);
- c = RL(c + f2(d,e,a) + X[ 2] + 0x5a827999, 11) + b; e = RL(e, 10);
- b = RL(b + f2(c,d,e) + X[14] + 0x5a827999, 7) + a; d = RL(d, 10);
- a = RL(a + f2(b,c,d) + X[11] + 0x5a827999, 13) + e; c = RL(c, 10);
- e = RL(e + f2(a,b,c) + X[ 8] + 0x5a827999, 12) + d; b = RL(b, 10);
-
- // right
- ee = RL(ee + f4(aa,bb,cc) + X[ 6] + 0x5c4dd124, 9) + dd; bb = RL(bb, 10);
- dd = RL(dd + f4(ee,aa,bb) + X[11] + 0x5c4dd124, 13) + cc; aa = RL(aa, 10);
- cc = RL(cc + f4(dd,ee,aa) + X[ 3] + 0x5c4dd124, 15) + bb; ee = RL(ee, 10);
- bb = RL(bb + f4(cc,dd,ee) + X[ 7] + 0x5c4dd124, 7) + aa; dd = RL(dd, 10);
- aa = RL(aa + f4(bb,cc,dd) + X[ 0] + 0x5c4dd124, 12) + ee; cc = RL(cc, 10);
- ee = RL(ee + f4(aa,bb,cc) + X[13] + 0x5c4dd124, 8) + dd; bb = RL(bb, 10);
- dd = RL(dd + f4(ee,aa,bb) + X[ 5] + 0x5c4dd124, 9) + cc; aa = RL(aa, 10);
- cc = RL(cc + f4(dd,ee,aa) + X[10] + 0x5c4dd124, 11) + bb; ee = RL(ee, 10);
- bb = RL(bb + f4(cc,dd,ee) + X[14] + 0x5c4dd124, 7) + aa; dd = RL(dd, 10);
- aa = RL(aa + f4(bb,cc,dd) + X[15] + 0x5c4dd124, 7) + ee; cc = RL(cc, 10);
- ee = RL(ee + f4(aa,bb,cc) + X[ 8] + 0x5c4dd124, 12) + dd; bb = RL(bb, 10);
- dd = RL(dd + f4(ee,aa,bb) + X[12] + 0x5c4dd124, 7) + cc; aa = RL(aa, 10);
- cc = RL(cc + f4(dd,ee,aa) + X[ 4] + 0x5c4dd124, 6) + bb; ee = RL(ee, 10);
- bb = RL(bb + f4(cc,dd,ee) + X[ 9] + 0x5c4dd124, 15) + aa; dd = RL(dd, 10);
- aa = RL(aa + f4(bb,cc,dd) + X[ 1] + 0x5c4dd124, 13) + ee; cc = RL(cc, 10);
- ee = RL(ee + f4(aa,bb,cc) + X[ 2] + 0x5c4dd124, 11) + dd; bb = RL(bb, 10);
-
- //
- // Rounds 32-47
- //
- // left
- d = RL(d + f3(e,a,b) + X[ 3] + 0x6ed9eba1, 11) + c; a = RL(a, 10);
- c = RL(c + f3(d,e,a) + X[10] + 0x6ed9eba1, 13) + b; e = RL(e, 10);
- b = RL(b + f3(c,d,e) + X[14] + 0x6ed9eba1, 6) + a; d = RL(d, 10);
- a = RL(a + f3(b,c,d) + X[ 4] + 0x6ed9eba1, 7) + e; c = RL(c, 10);
- e = RL(e + f3(a,b,c) + X[ 9] + 0x6ed9eba1, 14) + d; b = RL(b, 10);
- d = RL(d + f3(e,a,b) + X[15] + 0x6ed9eba1, 9) + c; a = RL(a, 10);
- c = RL(c + f3(d,e,a) + X[ 8] + 0x6ed9eba1, 13) + b; e = RL(e, 10);
- b = RL(b + f3(c,d,e) + X[ 1] + 0x6ed9eba1, 15) + a; d = RL(d, 10);
- a = RL(a + f3(b,c,d) + X[ 2] + 0x6ed9eba1, 14) + e; c = RL(c, 10);
- e = RL(e + f3(a,b,c) + X[ 7] + 0x6ed9eba1, 8) + d; b = RL(b, 10);
- d = RL(d + f3(e,a,b) + X[ 0] + 0x6ed9eba1, 13) + c; a = RL(a, 10);
- c = RL(c + f3(d,e,a) + X[ 6] + 0x6ed9eba1, 6) + b; e = RL(e, 10);
- b = RL(b + f3(c,d,e) + X[13] + 0x6ed9eba1, 5) + a; d = RL(d, 10);
- a = RL(a + f3(b,c,d) + X[11] + 0x6ed9eba1, 12) + e; c = RL(c, 10);
- e = RL(e + f3(a,b,c) + X[ 5] + 0x6ed9eba1, 7) + d; b = RL(b, 10);
- d = RL(d + f3(e,a,b) + X[12] + 0x6ed9eba1, 5) + c; a = RL(a, 10);
-
- // right
- dd = RL(dd + f3(ee,aa,bb) + X[15] + 0x6d703ef3, 9) + cc; aa = RL(aa, 10);
- cc = RL(cc + f3(dd,ee,aa) + X[ 5] + 0x6d703ef3, 7) + bb; ee = RL(ee, 10);
- bb = RL(bb + f3(cc,dd,ee) + X[ 1] + 0x6d703ef3, 15) + aa; dd = RL(dd, 10);
- aa = RL(aa + f3(bb,cc,dd) + X[ 3] + 0x6d703ef3, 11) + ee; cc = RL(cc, 10);
- ee = RL(ee + f3(aa,bb,cc) + X[ 7] + 0x6d703ef3, 8) + dd; bb = RL(bb, 10);
- dd = RL(dd + f3(ee,aa,bb) + X[14] + 0x6d703ef3, 6) + cc; aa = RL(aa, 10);
- cc = RL(cc + f3(dd,ee,aa) + X[ 6] + 0x6d703ef3, 6) + bb; ee = RL(ee, 10);
- bb = RL(bb + f3(cc,dd,ee) + X[ 9] + 0x6d703ef3, 14) + aa; dd = RL(dd, 10);
- aa = RL(aa + f3(bb,cc,dd) + X[11] + 0x6d703ef3, 12) + ee; cc = RL(cc, 10);
- ee = RL(ee + f3(aa,bb,cc) + X[ 8] + 0x6d703ef3, 13) + dd; bb = RL(bb, 10);
- dd = RL(dd + f3(ee,aa,bb) + X[12] + 0x6d703ef3, 5) + cc; aa = RL(aa, 10);
- cc = RL(cc + f3(dd,ee,aa) + X[ 2] + 0x6d703ef3, 14) + bb; ee = RL(ee, 10);
- bb = RL(bb + f3(cc,dd,ee) + X[10] + 0x6d703ef3, 13) + aa; dd = RL(dd, 10);
- aa = RL(aa + f3(bb,cc,dd) + X[ 0] + 0x6d703ef3, 13) + ee; cc = RL(cc, 10);
- ee = RL(ee + f3(aa,bb,cc) + X[ 4] + 0x6d703ef3, 7) + dd; bb = RL(bb, 10);
- dd = RL(dd + f3(ee,aa,bb) + X[13] + 0x6d703ef3, 5) + cc; aa = RL(aa, 10);
-
- //
- // Rounds 48-63
- //
- // left
- c = RL(c + f4(d,e,a) + X[ 1] + 0x8f1bbcdc, 11) + b; e = RL(e, 10);
- b = RL(b + f4(c,d,e) + X[ 9] + 0x8f1bbcdc, 12) + a; d = RL(d, 10);
- a = RL(a + f4(b,c,d) + X[11] + 0x8f1bbcdc, 14) + e; c = RL(c, 10);
- e = RL(e + f4(a,b,c) + X[10] + 0x8f1bbcdc, 15) + d; b = RL(b, 10);
- d = RL(d + f4(e,a,b) + X[ 0] + 0x8f1bbcdc, 14) + c; a = RL(a, 10);
- c = RL(c + f4(d,e,a) + X[ 8] + 0x8f1bbcdc, 15) + b; e = RL(e, 10);
- b = RL(b + f4(c,d,e) + X[12] + 0x8f1bbcdc, 9) + a; d = RL(d, 10);
- a = RL(a + f4(b,c,d) + X[ 4] + 0x8f1bbcdc, 8) + e; c = RL(c, 10);
- e = RL(e + f4(a,b,c) + X[13] + 0x8f1bbcdc, 9) + d; b = RL(b, 10);
- d = RL(d + f4(e,a,b) + X[ 3] + 0x8f1bbcdc, 14) + c; a = RL(a, 10);
- c = RL(c + f4(d,e,a) + X[ 7] + 0x8f1bbcdc, 5) + b; e = RL(e, 10);
- b = RL(b + f4(c,d,e) + X[15] + 0x8f1bbcdc, 6) + a; d = RL(d, 10);
- a = RL(a + f4(b,c,d) + X[14] + 0x8f1bbcdc, 8) + e; c = RL(c, 10);
- e = RL(e + f4(a,b,c) + X[ 5] + 0x8f1bbcdc, 6) + d; b = RL(b, 10);
- d = RL(d + f4(e,a,b) + X[ 6] + 0x8f1bbcdc, 5) + c; a = RL(a, 10);
- c = RL(c + f4(d,e,a) + X[ 2] + 0x8f1bbcdc, 12) + b; e = RL(e, 10);
-
- // right
- cc = RL(cc + f2(dd,ee,aa) + X[ 8] + 0x7a6d76e9, 15) + bb; ee = RL(ee, 10);
- bb = RL(bb + f2(cc,dd,ee) + X[ 6] + 0x7a6d76e9, 5) + aa; dd = RL(dd, 10);
- aa = RL(aa + f2(bb,cc,dd) + X[ 4] + 0x7a6d76e9, 8) + ee; cc = RL(cc, 10);
- ee = RL(ee + f2(aa,bb,cc) + X[ 1] + 0x7a6d76e9, 11) + dd; bb = RL(bb, 10);
- dd = RL(dd + f2(ee,aa,bb) + X[ 3] + 0x7a6d76e9, 14) + cc; aa = RL(aa, 10);
- cc = RL(cc + f2(dd,ee,aa) + X[11] + 0x7a6d76e9, 14) + bb; ee = RL(ee, 10);
- bb = RL(bb + f2(cc,dd,ee) + X[15] + 0x7a6d76e9, 6) + aa; dd = RL(dd, 10);
- aa = RL(aa + f2(bb,cc,dd) + X[ 0] + 0x7a6d76e9, 14) + ee; cc = RL(cc, 10);
- ee = RL(ee + f2(aa,bb,cc) + X[ 5] + 0x7a6d76e9, 6) + dd; bb = RL(bb, 10);
- dd = RL(dd + f2(ee,aa,bb) + X[12] + 0x7a6d76e9, 9) + cc; aa = RL(aa, 10);
- cc = RL(cc + f2(dd,ee,aa) + X[ 2] + 0x7a6d76e9, 12) + bb; ee = RL(ee, 10);
- bb = RL(bb + f2(cc,dd,ee) + X[13] + 0x7a6d76e9, 9) + aa; dd = RL(dd, 10);
- aa = RL(aa + f2(bb,cc,dd) + X[ 9] + 0x7a6d76e9, 12) + ee; cc = RL(cc, 10);
- ee = RL(ee + f2(aa,bb,cc) + X[ 7] + 0x7a6d76e9, 5) + dd; bb = RL(bb, 10);
- dd = RL(dd + f2(ee,aa,bb) + X[10] + 0x7a6d76e9, 15) + cc; aa = RL(aa, 10);
- cc = RL(cc + f2(dd,ee,aa) + X[14] + 0x7a6d76e9, 8) + bb; ee = RL(ee, 10);
-
- //
- // Rounds 64-79
- //
- // left
- b = RL(b + f5(c,d,e) + X[ 4] + 0xa953fd4e, 9) + a; d = RL(d, 10);
- a = RL(a + f5(b,c,d) + X[ 0] + 0xa953fd4e, 15) + e; c = RL(c, 10);
- e = RL(e + f5(a,b,c) + X[ 5] + 0xa953fd4e, 5) + d; b = RL(b, 10);
- d = RL(d + f5(e,a,b) + X[ 9] + 0xa953fd4e, 11) + c; a = RL(a, 10);
- c = RL(c + f5(d,e,a) + X[ 7] + 0xa953fd4e, 6) + b; e = RL(e, 10);
- b = RL(b + f5(c,d,e) + X[12] + 0xa953fd4e, 8) + a; d = RL(d, 10);
- a = RL(a + f5(b,c,d) + X[ 2] + 0xa953fd4e, 13) + e; c = RL(c, 10);
- e = RL(e + f5(a,b,c) + X[10] + 0xa953fd4e, 12) + d; b = RL(b, 10);
- d = RL(d + f5(e,a,b) + X[14] + 0xa953fd4e, 5) + c; a = RL(a, 10);
- c = RL(c + f5(d,e,a) + X[ 1] + 0xa953fd4e, 12) + b; e = RL(e, 10);
- b = RL(b + f5(c,d,e) + X[ 3] + 0xa953fd4e, 13) + a; d = RL(d, 10);
- a = RL(a + f5(b,c,d) + X[ 8] + 0xa953fd4e, 14) + e; c = RL(c, 10);
- e = RL(e + f5(a,b,c) + X[11] + 0xa953fd4e, 11) + d; b = RL(b, 10);
- d = RL(d + f5(e,a,b) + X[ 6] + 0xa953fd4e, 8) + c; a = RL(a, 10);
- c = RL(c + f5(d,e,a) + X[15] + 0xa953fd4e, 5) + b; e = RL(e, 10);
- b = RL(b + f5(c,d,e) + X[13] + 0xa953fd4e, 6) + a; d = RL(d, 10);
-
- // right
- bb = RL(bb + f1(cc,dd,ee) + X[12], 8) + aa; dd = RL(dd, 10);
- aa = RL(aa + f1(bb,cc,dd) + X[15], 5) + ee; cc = RL(cc, 10);
- ee = RL(ee + f1(aa,bb,cc) + X[10], 12) + dd; bb = RL(bb, 10);
- dd = RL(dd + f1(ee,aa,bb) + X[ 4], 9) + cc; aa = RL(aa, 10);
- cc = RL(cc + f1(dd,ee,aa) + X[ 1], 12) + bb; ee = RL(ee, 10);
- bb = RL(bb + f1(cc,dd,ee) + X[ 5], 5) + aa; dd = RL(dd, 10);
- aa = RL(aa + f1(bb,cc,dd) + X[ 8], 14) + ee; cc = RL(cc, 10);
- ee = RL(ee + f1(aa,bb,cc) + X[ 7], 6) + dd; bb = RL(bb, 10);
- dd = RL(dd + f1(ee,aa,bb) + X[ 6], 8) + cc; aa = RL(aa, 10);
- cc = RL(cc + f1(dd,ee,aa) + X[ 2], 13) + bb; ee = RL(ee, 10);
- bb = RL(bb + f1(cc,dd,ee) + X[13], 6) + aa; dd = RL(dd, 10);
- aa = RL(aa + f1(bb,cc,dd) + X[14], 5) + ee; cc = RL(cc, 10);
- ee = RL(ee + f1(aa,bb,cc) + X[ 0], 15) + dd; bb = RL(bb, 10);
- dd = RL(dd + f1(ee,aa,bb) + X[ 3], 13) + cc; aa = RL(aa, 10);
- cc = RL(cc + f1(dd,ee,aa) + X[ 9], 11) + bb; ee = RL(ee, 10);
- bb = RL(bb + f1(cc,dd,ee) + X[11], 11) + aa; dd = RL(dd, 10);
-
- dd += c + H1;
- H1 = H2 + d + ee;
- H2 = H3 + e + aa;
- H3 = H4 + a + bb;
- H4 = H0 + b + cc;
- H0 = dd;
-
- //
- // reset the offset and clean out the word buffer.
- //
- xOff = 0;
- for (int i = 0; i != X.length; i++)
- {
- X[i] = 0;
- }
- }
-
- public Memoable copy()
- {
- return new RIPEMD160Digest(this);
- }
-
- public void reset(Memoable other)
- {
- RIPEMD160Digest d = (RIPEMD160Digest)other;
-
- copyIn(d);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/digests/RIPEMD256Digest.java b/core/src/main/java/org/bouncycastle/crypto/digests/RIPEMD256Digest.java
deleted file mode 100644
index 86746b45..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/RIPEMD256Digest.java
+++ /dev/null
@@ -1,497 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-
-import org.bouncycastle.util.Memoable;
-
-/**
- * implementation of RIPEMD256.
- * <p>
- * <b>note:</b> this algorithm offers the same level of security as RIPEMD128.
- */
-public class RIPEMD256Digest
- extends GeneralDigest
-{
- private static final int DIGEST_LENGTH = 32;
-
- private int H0, H1, H2, H3, H4, H5, H6, H7; // IV's
-
- private int[] X = new int[16];
- private int xOff;
-
- /**
- * Standard constructor
- */
- public RIPEMD256Digest()
- {
- reset();
- }
-
- /**
- * Copy constructor. This will copy the state of the provided
- * message digest.
- */
- public RIPEMD256Digest(RIPEMD256Digest t)
- {
- super(t);
-
- copyIn(t);
- }
-
- private void copyIn(RIPEMD256Digest t)
- {
- super.copyIn(t);
-
- H0 = t.H0;
- H1 = t.H1;
- H2 = t.H2;
- H3 = t.H3;
- H4 = t.H4;
- H5 = t.H5;
- H6 = t.H6;
- H7 = t.H7;
-
- System.arraycopy(t.X, 0, X, 0, t.X.length);
- xOff = t.xOff;
- }
-
- public String getAlgorithmName()
- {
- return "RIPEMD256";
- }
-
- public int getDigestSize()
- {
- return DIGEST_LENGTH;
- }
-
- protected void processWord(
- byte[] in,
- int inOff)
- {
- X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
- | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
-
- if (xOff == 16)
- {
- processBlock();
- }
- }
-
- protected void processLength(
- long bitLength)
- {
- if (xOff > 14)
- {
- processBlock();
- }
-
- X[14] = (int)(bitLength & 0xffffffff);
- X[15] = (int)(bitLength >>> 32);
- }
-
- private void unpackWord(
- int word,
- byte[] out,
- int outOff)
- {
- out[outOff] = (byte)word;
- out[outOff + 1] = (byte)(word >>> 8);
- out[outOff + 2] = (byte)(word >>> 16);
- out[outOff + 3] = (byte)(word >>> 24);
- }
-
- public int doFinal(
- byte[] out,
- int outOff)
- {
- finish();
-
- unpackWord(H0, out, outOff);
- unpackWord(H1, out, outOff + 4);
- unpackWord(H2, out, outOff + 8);
- unpackWord(H3, out, outOff + 12);
- unpackWord(H4, out, outOff + 16);
- unpackWord(H5, out, outOff + 20);
- unpackWord(H6, out, outOff + 24);
- unpackWord(H7, out, outOff + 28);
-
- reset();
-
- return DIGEST_LENGTH;
- }
-
- /**
- * reset the chaining variables to the IV values.
- */
- public void reset()
- {
- super.reset();
-
- H0 = 0x67452301;
- H1 = 0xefcdab89;
- H2 = 0x98badcfe;
- H3 = 0x10325476;
- H4 = 0x76543210;
- H5 = 0xFEDCBA98;
- H6 = 0x89ABCDEF;
- H7 = 0x01234567;
-
- xOff = 0;
-
- for (int i = 0; i != X.length; i++)
- {
- X[i] = 0;
- }
- }
-
- /*
- * rotate int x left n bits.
- */
- private int RL(
- int x,
- int n)
- {
- return (x << n) | (x >>> (32 - n));
- }
-
- /*
- * f1,f2,f3,f4 are the basic RIPEMD128 functions.
- */
-
- /*
- * F
- */
- private int f1(
- int x,
- int y,
- int z)
- {
- return x ^ y ^ z;
- }
-
- /*
- * G
- */
- private int f2(
- int x,
- int y,
- int z)
- {
- return (x & y) | (~x & z);
- }
-
- /*
- * H
- */
- private int f3(
- int x,
- int y,
- int z)
- {
- return (x | ~y) ^ z;
- }
-
- /*
- * I
- */
- private int f4(
- int x,
- int y,
- int z)
- {
- return (x & z) | (y & ~z);
- }
-
- private int F1(
- int a,
- int b,
- int c,
- int d,
- int x,
- int s)
- {
- return RL(a + f1(b, c, d) + x, s);
- }
-
- private int F2(
- int a,
- int b,
- int c,
- int d,
- int x,
- int s)
- {
- return RL(a + f2(b, c, d) + x + 0x5a827999, s);
- }
-
- private int F3(
- int a,
- int b,
- int c,
- int d,
- int x,
- int s)
- {
- return RL(a + f3(b, c, d) + x + 0x6ed9eba1, s);
- }
-
- private int F4(
- int a,
- int b,
- int c,
- int d,
- int x,
- int s)
- {
- return RL(a + f4(b, c, d) + x + 0x8f1bbcdc, s);
- }
-
- private int FF1(
- int a,
- int b,
- int c,
- int d,
- int x,
- int s)
- {
- return RL(a + f1(b, c, d) + x, s);
- }
-
- private int FF2(
- int a,
- int b,
- int c,
- int d,
- int x,
- int s)
- {
- return RL(a + f2(b, c, d) + x + 0x6d703ef3, s);
- }
-
- private int FF3(
- int a,
- int b,
- int c,
- int d,
- int x,
- int s)
- {
- return RL(a + f3(b, c, d) + x + 0x5c4dd124, s);
- }
-
- private int FF4(
- int a,
- int b,
- int c,
- int d,
- int x,
- int s)
- {
- return RL(a + f4(b, c, d) + x + 0x50a28be6, s);
- }
-
- protected void processBlock()
- {
- int a, aa;
- int b, bb;
- int c, cc;
- int d, dd;
- int t;
-
- a = H0;
- b = H1;
- c = H2;
- d = H3;
- aa = H4;
- bb = H5;
- cc = H6;
- dd = H7;
-
- //
- // Round 1
- //
-
- a = F1(a, b, c, d, X[ 0], 11);
- d = F1(d, a, b, c, X[ 1], 14);
- c = F1(c, d, a, b, X[ 2], 15);
- b = F1(b, c, d, a, X[ 3], 12);
- a = F1(a, b, c, d, X[ 4], 5);
- d = F1(d, a, b, c, X[ 5], 8);
- c = F1(c, d, a, b, X[ 6], 7);
- b = F1(b, c, d, a, X[ 7], 9);
- a = F1(a, b, c, d, X[ 8], 11);
- d = F1(d, a, b, c, X[ 9], 13);
- c = F1(c, d, a, b, X[10], 14);
- b = F1(b, c, d, a, X[11], 15);
- a = F1(a, b, c, d, X[12], 6);
- d = F1(d, a, b, c, X[13], 7);
- c = F1(c, d, a, b, X[14], 9);
- b = F1(b, c, d, a, X[15], 8);
-
- aa = FF4(aa, bb, cc, dd, X[ 5], 8);
- dd = FF4(dd, aa, bb, cc, X[14], 9);
- cc = FF4(cc, dd, aa, bb, X[ 7], 9);
- bb = FF4(bb, cc, dd, aa, X[ 0], 11);
- aa = FF4(aa, bb, cc, dd, X[ 9], 13);
- dd = FF4(dd, aa, bb, cc, X[ 2], 15);
- cc = FF4(cc, dd, aa, bb, X[11], 15);
- bb = FF4(bb, cc, dd, aa, X[ 4], 5);
- aa = FF4(aa, bb, cc, dd, X[13], 7);
- dd = FF4(dd, aa, bb, cc, X[ 6], 7);
- cc = FF4(cc, dd, aa, bb, X[15], 8);
- bb = FF4(bb, cc, dd, aa, X[ 8], 11);
- aa = FF4(aa, bb, cc, dd, X[ 1], 14);
- dd = FF4(dd, aa, bb, cc, X[10], 14);
- cc = FF4(cc, dd, aa, bb, X[ 3], 12);
- bb = FF4(bb, cc, dd, aa, X[12], 6);
-
- t = a; a = aa; aa = t;
-
- //
- // Round 2
- //
- a = F2(a, b, c, d, X[ 7], 7);
- d = F2(d, a, b, c, X[ 4], 6);
- c = F2(c, d, a, b, X[13], 8);
- b = F2(b, c, d, a, X[ 1], 13);
- a = F2(a, b, c, d, X[10], 11);
- d = F2(d, a, b, c, X[ 6], 9);
- c = F2(c, d, a, b, X[15], 7);
- b = F2(b, c, d, a, X[ 3], 15);
- a = F2(a, b, c, d, X[12], 7);
- d = F2(d, a, b, c, X[ 0], 12);
- c = F2(c, d, a, b, X[ 9], 15);
- b = F2(b, c, d, a, X[ 5], 9);
- a = F2(a, b, c, d, X[ 2], 11);
- d = F2(d, a, b, c, X[14], 7);
- c = F2(c, d, a, b, X[11], 13);
- b = F2(b, c, d, a, X[ 8], 12);
-
- aa = FF3(aa, bb, cc, dd, X[ 6], 9);
- dd = FF3(dd, aa, bb, cc, X[ 11], 13);
- cc = FF3(cc, dd, aa, bb, X[3], 15);
- bb = FF3(bb, cc, dd, aa, X[ 7], 7);
- aa = FF3(aa, bb, cc, dd, X[0], 12);
- dd = FF3(dd, aa, bb, cc, X[13], 8);
- cc = FF3(cc, dd, aa, bb, X[5], 9);
- bb = FF3(bb, cc, dd, aa, X[10], 11);
- aa = FF3(aa, bb, cc, dd, X[14], 7);
- dd = FF3(dd, aa, bb, cc, X[15], 7);
- cc = FF3(cc, dd, aa, bb, X[ 8], 12);
- bb = FF3(bb, cc, dd, aa, X[12], 7);
- aa = FF3(aa, bb, cc, dd, X[ 4], 6);
- dd = FF3(dd, aa, bb, cc, X[ 9], 15);
- cc = FF3(cc, dd, aa, bb, X[ 1], 13);
- bb = FF3(bb, cc, dd, aa, X[ 2], 11);
-
- t = b; b = bb; bb = t;
-
- //
- // Round 3
- //
- a = F3(a, b, c, d, X[ 3], 11);
- d = F3(d, a, b, c, X[10], 13);
- c = F3(c, d, a, b, X[14], 6);
- b = F3(b, c, d, a, X[ 4], 7);
- a = F3(a, b, c, d, X[ 9], 14);
- d = F3(d, a, b, c, X[15], 9);
- c = F3(c, d, a, b, X[ 8], 13);
- b = F3(b, c, d, a, X[ 1], 15);
- a = F3(a, b, c, d, X[ 2], 14);
- d = F3(d, a, b, c, X[ 7], 8);
- c = F3(c, d, a, b, X[ 0], 13);
- b = F3(b, c, d, a, X[ 6], 6);
- a = F3(a, b, c, d, X[13], 5);
- d = F3(d, a, b, c, X[11], 12);
- c = F3(c, d, a, b, X[ 5], 7);
- b = F3(b, c, d, a, X[12], 5);
-
- aa = FF2(aa, bb, cc, dd, X[ 15], 9);
- dd = FF2(dd, aa, bb, cc, X[5], 7);
- cc = FF2(cc, dd, aa, bb, X[1], 15);
- bb = FF2(bb, cc, dd, aa, X[ 3], 11);
- aa = FF2(aa, bb, cc, dd, X[ 7], 8);
- dd = FF2(dd, aa, bb, cc, X[14], 6);
- cc = FF2(cc, dd, aa, bb, X[ 6], 6);
- bb = FF2(bb, cc, dd, aa, X[ 9], 14);
- aa = FF2(aa, bb, cc, dd, X[11], 12);
- dd = FF2(dd, aa, bb, cc, X[ 8], 13);
- cc = FF2(cc, dd, aa, bb, X[12], 5);
- bb = FF2(bb, cc, dd, aa, X[ 2], 14);
- aa = FF2(aa, bb, cc, dd, X[10], 13);
- dd = FF2(dd, aa, bb, cc, X[ 0], 13);
- cc = FF2(cc, dd, aa, bb, X[ 4], 7);
- bb = FF2(bb, cc, dd, aa, X[13], 5);
-
- t = c; c = cc; cc = t;
-
- //
- // Round 4
- //
- a = F4(a, b, c, d, X[ 1], 11);
- d = F4(d, a, b, c, X[ 9], 12);
- c = F4(c, d, a, b, X[11], 14);
- b = F4(b, c, d, a, X[10], 15);
- a = F4(a, b, c, d, X[ 0], 14);
- d = F4(d, a, b, c, X[ 8], 15);
- c = F4(c, d, a, b, X[12], 9);
- b = F4(b, c, d, a, X[ 4], 8);
- a = F4(a, b, c, d, X[13], 9);
- d = F4(d, a, b, c, X[ 3], 14);
- c = F4(c, d, a, b, X[ 7], 5);
- b = F4(b, c, d, a, X[15], 6);
- a = F4(a, b, c, d, X[14], 8);
- d = F4(d, a, b, c, X[ 5], 6);
- c = F4(c, d, a, b, X[ 6], 5);
- b = F4(b, c, d, a, X[ 2], 12);
-
- aa = FF1(aa, bb, cc, dd, X[ 8], 15);
- dd = FF1(dd, aa, bb, cc, X[ 6], 5);
- cc = FF1(cc, dd, aa, bb, X[ 4], 8);
- bb = FF1(bb, cc, dd, aa, X[ 1], 11);
- aa = FF1(aa, bb, cc, dd, X[ 3], 14);
- dd = FF1(dd, aa, bb, cc, X[11], 14);
- cc = FF1(cc, dd, aa, bb, X[15], 6);
- bb = FF1(bb, cc, dd, aa, X[ 0], 14);
- aa = FF1(aa, bb, cc, dd, X[ 5], 6);
- dd = FF1(dd, aa, bb, cc, X[12], 9);
- cc = FF1(cc, dd, aa, bb, X[ 2], 12);
- bb = FF1(bb, cc, dd, aa, X[13], 9);
- aa = FF1(aa, bb, cc, dd, X[ 9], 12);
- dd = FF1(dd, aa, bb, cc, X[ 7], 5);
- cc = FF1(cc, dd, aa, bb, X[10], 15);
- bb = FF1(bb, cc, dd, aa, X[14], 8);
-
- t = d; d = dd; dd = t;
-
- H0 += a;
- H1 += b;
- H2 += c;
- H3 += d;
- H4 += aa;
- H5 += bb;
- H6 += cc;
- H7 += dd;
-
- //
- // reset the offset and clean out the word buffer.
- //
- xOff = 0;
- for (int i = 0; i != X.length; i++)
- {
- X[i] = 0;
- }
- }
-
- public Memoable copy()
- {
- return new RIPEMD256Digest(this);
- }
-
- public void reset(Memoable other)
- {
- RIPEMD256Digest d = (RIPEMD256Digest)other;
-
- copyIn(d);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/digests/RIPEMD320Digest.java b/core/src/main/java/org/bouncycastle/crypto/digests/RIPEMD320Digest.java
deleted file mode 100644
index 32775e77..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/RIPEMD320Digest.java
+++ /dev/null
@@ -1,481 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-
-import org.bouncycastle.util.Memoable;
-
-/**
- * implementation of RIPEMD 320.
- * <p>
- * <b>Note:</b> this implementation offers the same level of security
- * as RIPEMD 160.
- */
-public class RIPEMD320Digest
- extends GeneralDigest
-{
- private static final int DIGEST_LENGTH = 40;
-
- private int H0, H1, H2, H3, H4, H5, H6, H7, H8, H9; // IV's
-
- private int[] X = new int[16];
- private int xOff;
-
- /**
- * Standard constructor
- */
- public RIPEMD320Digest()
- {
- reset();
- }
-
- /**
- * Copy constructor. This will copy the state of the provided
- * message digest.
- */
- public RIPEMD320Digest(RIPEMD320Digest t)
- {
- super(t);
-
- doCopy(t);
- }
-
- private void doCopy(RIPEMD320Digest t)
- {
- super.copyIn(t);
- H0 = t.H0;
- H1 = t.H1;
- H2 = t.H2;
- H3 = t.H3;
- H4 = t.H4;
- H5 = t.H5;
- H6 = t.H6;
- H7 = t.H7;
- H8 = t.H8;
- H9 = t.H9;
-
- System.arraycopy(t.X, 0, X, 0, t.X.length);
- xOff = t.xOff;
- }
-
- public String getAlgorithmName()
- {
- return "RIPEMD320";
- }
-
- public int getDigestSize()
- {
- return DIGEST_LENGTH;
- }
-
- protected void processWord(
- byte[] in,
- int inOff)
- {
- X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
- | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
-
- if (xOff == 16)
- {
- processBlock();
- }
- }
-
- protected void processLength(
- long bitLength)
- {
- if (xOff > 14)
- {
- processBlock();
- }
-
- X[14] = (int)(bitLength & 0xffffffff);
- X[15] = (int)(bitLength >>> 32);
- }
-
- private void unpackWord(
- int word,
- byte[] out,
- int outOff)
- {
- out[outOff] = (byte)word;
- out[outOff + 1] = (byte)(word >>> 8);
- out[outOff + 2] = (byte)(word >>> 16);
- out[outOff + 3] = (byte)(word >>> 24);
- }
-
- public int doFinal(
- byte[] out,
- int outOff)
- {
- finish();
-
- unpackWord(H0, out, outOff);
- unpackWord(H1, out, outOff + 4);
- unpackWord(H2, out, outOff + 8);
- unpackWord(H3, out, outOff + 12);
- unpackWord(H4, out, outOff + 16);
- unpackWord(H5, out, outOff + 20);
- unpackWord(H6, out, outOff + 24);
- unpackWord(H7, out, outOff + 28);
- unpackWord(H8, out, outOff + 32);
- unpackWord(H9, out, outOff + 36);
-
- reset();
-
- return DIGEST_LENGTH;
- }
-
- /**
- * reset the chaining variables to the IV values.
- */
- public void reset()
- {
- super.reset();
-
- H0 = 0x67452301;
- H1 = 0xefcdab89;
- H2 = 0x98badcfe;
- H3 = 0x10325476;
- H4 = 0xc3d2e1f0;
- H5 = 0x76543210;
- H6 = 0xFEDCBA98;
- H7 = 0x89ABCDEF;
- H8 = 0x01234567;
- H9 = 0x3C2D1E0F;
-
- xOff = 0;
-
- for (int i = 0; i != X.length; i++)
- {
- X[i] = 0;
- }
- }
-
- /*
- * rotate int x left n bits.
- */
- private int RL(
- int x,
- int n)
- {
- return (x << n) | (x >>> (32 - n));
- }
-
- /*
- * f1,f2,f3,f4,f5 are the basic RIPEMD160 functions.
- */
-
- /*
- * rounds 0-15
- */
- private int f1(
- int x,
- int y,
- int z)
- {
- return x ^ y ^ z;
- }
-
- /*
- * rounds 16-31
- */
- private int f2(
- int x,
- int y,
- int z)
- {
- return (x & y) | (~x & z);
- }
-
- /*
- * rounds 32-47
- */
- private int f3(
- int x,
- int y,
- int z)
- {
- return (x | ~y) ^ z;
- }
-
- /*
- * rounds 48-63
- */
- private int f4(
- int x,
- int y,
- int z)
- {
- return (x & z) | (y & ~z);
- }
-
- /*
- * rounds 64-79
- */
- private int f5(
- int x,
- int y,
- int z)
- {
- return x ^ (y | ~z);
- }
-
- protected void processBlock()
- {
- int a, aa;
- int b, bb;
- int c, cc;
- int d, dd;
- int e, ee;
- int t;
-
- a = H0;
- b = H1;
- c = H2;
- d = H3;
- e = H4;
- aa = H5;
- bb = H6;
- cc = H7;
- dd = H8;
- ee = H9;
-
- //
- // Rounds 1 - 16
- //
- // left
- a = RL(a + f1(b,c,d) + X[ 0], 11) + e; c = RL(c, 10);
- e = RL(e + f1(a,b,c) + X[ 1], 14) + d; b = RL(b, 10);
- d = RL(d + f1(e,a,b) + X[ 2], 15) + c; a = RL(a, 10);
- c = RL(c + f1(d,e,a) + X[ 3], 12) + b; e = RL(e, 10);
- b = RL(b + f1(c,d,e) + X[ 4], 5) + a; d = RL(d, 10);
- a = RL(a + f1(b,c,d) + X[ 5], 8) + e; c = RL(c, 10);
- e = RL(e + f1(a,b,c) + X[ 6], 7) + d; b = RL(b, 10);
- d = RL(d + f1(e,a,b) + X[ 7], 9) + c; a = RL(a, 10);
- c = RL(c + f1(d,e,a) + X[ 8], 11) + b; e = RL(e, 10);
- b = RL(b + f1(c,d,e) + X[ 9], 13) + a; d = RL(d, 10);
- a = RL(a + f1(b,c,d) + X[10], 14) + e; c = RL(c, 10);
- e = RL(e + f1(a,b,c) + X[11], 15) + d; b = RL(b, 10);
- d = RL(d + f1(e,a,b) + X[12], 6) + c; a = RL(a, 10);
- c = RL(c + f1(d,e,a) + X[13], 7) + b; e = RL(e, 10);
- b = RL(b + f1(c,d,e) + X[14], 9) + a; d = RL(d, 10);
- a = RL(a + f1(b,c,d) + X[15], 8) + e; c = RL(c, 10);
-
- // right
- aa = RL(aa + f5(bb,cc,dd) + X[ 5] + 0x50a28be6, 8) + ee; cc = RL(cc, 10);
- ee = RL(ee + f5(aa,bb,cc) + X[14] + 0x50a28be6, 9) + dd; bb = RL(bb, 10);
- dd = RL(dd + f5(ee,aa,bb) + X[ 7] + 0x50a28be6, 9) + cc; aa = RL(aa, 10);
- cc = RL(cc + f5(dd,ee,aa) + X[ 0] + 0x50a28be6, 11) + bb; ee = RL(ee, 10);
- bb = RL(bb + f5(cc,dd,ee) + X[ 9] + 0x50a28be6, 13) + aa; dd = RL(dd, 10);
- aa = RL(aa + f5(bb,cc,dd) + X[ 2] + 0x50a28be6, 15) + ee; cc = RL(cc, 10);
- ee = RL(ee + f5(aa,bb,cc) + X[11] + 0x50a28be6, 15) + dd; bb = RL(bb, 10);
- dd = RL(dd + f5(ee,aa,bb) + X[ 4] + 0x50a28be6, 5) + cc; aa = RL(aa, 10);
- cc = RL(cc + f5(dd,ee,aa) + X[13] + 0x50a28be6, 7) + bb; ee = RL(ee, 10);
- bb = RL(bb + f5(cc,dd,ee) + X[ 6] + 0x50a28be6, 7) + aa; dd = RL(dd, 10);
- aa = RL(aa + f5(bb,cc,dd) + X[15] + 0x50a28be6, 8) + ee; cc = RL(cc, 10);
- ee = RL(ee + f5(aa,bb,cc) + X[ 8] + 0x50a28be6, 11) + dd; bb = RL(bb, 10);
- dd = RL(dd + f5(ee,aa,bb) + X[ 1] + 0x50a28be6, 14) + cc; aa = RL(aa, 10);
- cc = RL(cc + f5(dd,ee,aa) + X[10] + 0x50a28be6, 14) + bb; ee = RL(ee, 10);
- bb = RL(bb + f5(cc,dd,ee) + X[ 3] + 0x50a28be6, 12) + aa; dd = RL(dd, 10);
- aa = RL(aa + f5(bb,cc,dd) + X[12] + 0x50a28be6, 6) + ee; cc = RL(cc, 10);
-
- t = a; a = aa; aa = t;
-
- //
- // Rounds 16-31
- //
- // left
- e = RL(e + f2(a,b,c) + X[ 7] + 0x5a827999, 7) + d; b = RL(b, 10);
- d = RL(d + f2(e,a,b) + X[ 4] + 0x5a827999, 6) + c; a = RL(a, 10);
- c = RL(c + f2(d,e,a) + X[13] + 0x5a827999, 8) + b; e = RL(e, 10);
- b = RL(b + f2(c,d,e) + X[ 1] + 0x5a827999, 13) + a; d = RL(d, 10);
- a = RL(a + f2(b,c,d) + X[10] + 0x5a827999, 11) + e; c = RL(c, 10);
- e = RL(e + f2(a,b,c) + X[ 6] + 0x5a827999, 9) + d; b = RL(b, 10);
- d = RL(d + f2(e,a,b) + X[15] + 0x5a827999, 7) + c; a = RL(a, 10);
- c = RL(c + f2(d,e,a) + X[ 3] + 0x5a827999, 15) + b; e = RL(e, 10);
- b = RL(b + f2(c,d,e) + X[12] + 0x5a827999, 7) + a; d = RL(d, 10);
- a = RL(a + f2(b,c,d) + X[ 0] + 0x5a827999, 12) + e; c = RL(c, 10);
- e = RL(e + f2(a,b,c) + X[ 9] + 0x5a827999, 15) + d; b = RL(b, 10);
- d = RL(d + f2(e,a,b) + X[ 5] + 0x5a827999, 9) + c; a = RL(a, 10);
- c = RL(c + f2(d,e,a) + X[ 2] + 0x5a827999, 11) + b; e = RL(e, 10);
- b = RL(b + f2(c,d,e) + X[14] + 0x5a827999, 7) + a; d = RL(d, 10);
- a = RL(a + f2(b,c,d) + X[11] + 0x5a827999, 13) + e; c = RL(c, 10);
- e = RL(e + f2(a,b,c) + X[ 8] + 0x5a827999, 12) + d; b = RL(b, 10);
-
- // right
- ee = RL(ee + f4(aa,bb,cc) + X[ 6] + 0x5c4dd124, 9) + dd; bb = RL(bb, 10);
- dd = RL(dd + f4(ee,aa,bb) + X[11] + 0x5c4dd124, 13) + cc; aa = RL(aa, 10);
- cc = RL(cc + f4(dd,ee,aa) + X[ 3] + 0x5c4dd124, 15) + bb; ee = RL(ee, 10);
- bb = RL(bb + f4(cc,dd,ee) + X[ 7] + 0x5c4dd124, 7) + aa; dd = RL(dd, 10);
- aa = RL(aa + f4(bb,cc,dd) + X[ 0] + 0x5c4dd124, 12) + ee; cc = RL(cc, 10);
- ee = RL(ee + f4(aa,bb,cc) + X[13] + 0x5c4dd124, 8) + dd; bb = RL(bb, 10);
- dd = RL(dd + f4(ee,aa,bb) + X[ 5] + 0x5c4dd124, 9) + cc; aa = RL(aa, 10);
- cc = RL(cc + f4(dd,ee,aa) + X[10] + 0x5c4dd124, 11) + bb; ee = RL(ee, 10);
- bb = RL(bb + f4(cc,dd,ee) + X[14] + 0x5c4dd124, 7) + aa; dd = RL(dd, 10);
- aa = RL(aa + f4(bb,cc,dd) + X[15] + 0x5c4dd124, 7) + ee; cc = RL(cc, 10);
- ee = RL(ee + f4(aa,bb,cc) + X[ 8] + 0x5c4dd124, 12) + dd; bb = RL(bb, 10);
- dd = RL(dd + f4(ee,aa,bb) + X[12] + 0x5c4dd124, 7) + cc; aa = RL(aa, 10);
- cc = RL(cc + f4(dd,ee,aa) + X[ 4] + 0x5c4dd124, 6) + bb; ee = RL(ee, 10);
- bb = RL(bb + f4(cc,dd,ee) + X[ 9] + 0x5c4dd124, 15) + aa; dd = RL(dd, 10);
- aa = RL(aa + f4(bb,cc,dd) + X[ 1] + 0x5c4dd124, 13) + ee; cc = RL(cc, 10);
- ee = RL(ee + f4(aa,bb,cc) + X[ 2] + 0x5c4dd124, 11) + dd; bb = RL(bb, 10);
-
- t = b; b = bb; bb = t;
-
- //
- // Rounds 32-47
- //
- // left
- d = RL(d + f3(e,a,b) + X[ 3] + 0x6ed9eba1, 11) + c; a = RL(a, 10);
- c = RL(c + f3(d,e,a) + X[10] + 0x6ed9eba1, 13) + b; e = RL(e, 10);
- b = RL(b + f3(c,d,e) + X[14] + 0x6ed9eba1, 6) + a; d = RL(d, 10);
- a = RL(a + f3(b,c,d) + X[ 4] + 0x6ed9eba1, 7) + e; c = RL(c, 10);
- e = RL(e + f3(a,b,c) + X[ 9] + 0x6ed9eba1, 14) + d; b = RL(b, 10);
- d = RL(d + f3(e,a,b) + X[15] + 0x6ed9eba1, 9) + c; a = RL(a, 10);
- c = RL(c + f3(d,e,a) + X[ 8] + 0x6ed9eba1, 13) + b; e = RL(e, 10);
- b = RL(b + f3(c,d,e) + X[ 1] + 0x6ed9eba1, 15) + a; d = RL(d, 10);
- a = RL(a + f3(b,c,d) + X[ 2] + 0x6ed9eba1, 14) + e; c = RL(c, 10);
- e = RL(e + f3(a,b,c) + X[ 7] + 0x6ed9eba1, 8) + d; b = RL(b, 10);
- d = RL(d + f3(e,a,b) + X[ 0] + 0x6ed9eba1, 13) + c; a = RL(a, 10);
- c = RL(c + f3(d,e,a) + X[ 6] + 0x6ed9eba1, 6) + b; e = RL(e, 10);
- b = RL(b + f3(c,d,e) + X[13] + 0x6ed9eba1, 5) + a; d = RL(d, 10);
- a = RL(a + f3(b,c,d) + X[11] + 0x6ed9eba1, 12) + e; c = RL(c, 10);
- e = RL(e + f3(a,b,c) + X[ 5] + 0x6ed9eba1, 7) + d; b = RL(b, 10);
- d = RL(d + f3(e,a,b) + X[12] + 0x6ed9eba1, 5) + c; a = RL(a, 10);
-
- // right
- dd = RL(dd + f3(ee,aa,bb) + X[15] + 0x6d703ef3, 9) + cc; aa = RL(aa, 10);
- cc = RL(cc + f3(dd,ee,aa) + X[ 5] + 0x6d703ef3, 7) + bb; ee = RL(ee, 10);
- bb = RL(bb + f3(cc,dd,ee) + X[ 1] + 0x6d703ef3, 15) + aa; dd = RL(dd, 10);
- aa = RL(aa + f3(bb,cc,dd) + X[ 3] + 0x6d703ef3, 11) + ee; cc = RL(cc, 10);
- ee = RL(ee + f3(aa,bb,cc) + X[ 7] + 0x6d703ef3, 8) + dd; bb = RL(bb, 10);
- dd = RL(dd + f3(ee,aa,bb) + X[14] + 0x6d703ef3, 6) + cc; aa = RL(aa, 10);
- cc = RL(cc + f3(dd,ee,aa) + X[ 6] + 0x6d703ef3, 6) + bb; ee = RL(ee, 10);
- bb = RL(bb + f3(cc,dd,ee) + X[ 9] + 0x6d703ef3, 14) + aa; dd = RL(dd, 10);
- aa = RL(aa + f3(bb,cc,dd) + X[11] + 0x6d703ef3, 12) + ee; cc = RL(cc, 10);
- ee = RL(ee + f3(aa,bb,cc) + X[ 8] + 0x6d703ef3, 13) + dd; bb = RL(bb, 10);
- dd = RL(dd + f3(ee,aa,bb) + X[12] + 0x6d703ef3, 5) + cc; aa = RL(aa, 10);
- cc = RL(cc + f3(dd,ee,aa) + X[ 2] + 0x6d703ef3, 14) + bb; ee = RL(ee, 10);
- bb = RL(bb + f3(cc,dd,ee) + X[10] + 0x6d703ef3, 13) + aa; dd = RL(dd, 10);
- aa = RL(aa + f3(bb,cc,dd) + X[ 0] + 0x6d703ef3, 13) + ee; cc = RL(cc, 10);
- ee = RL(ee + f3(aa,bb,cc) + X[ 4] + 0x6d703ef3, 7) + dd; bb = RL(bb, 10);
- dd = RL(dd + f3(ee,aa,bb) + X[13] + 0x6d703ef3, 5) + cc; aa = RL(aa, 10);
-
- t = c; c = cc; cc = t;
-
- //
- // Rounds 48-63
- //
- // left
- c = RL(c + f4(d,e,a) + X[ 1] + 0x8f1bbcdc, 11) + b; e = RL(e, 10);
- b = RL(b + f4(c,d,e) + X[ 9] + 0x8f1bbcdc, 12) + a; d = RL(d, 10);
- a = RL(a + f4(b,c,d) + X[11] + 0x8f1bbcdc, 14) + e; c = RL(c, 10);
- e = RL(e + f4(a,b,c) + X[10] + 0x8f1bbcdc, 15) + d; b = RL(b, 10);
- d = RL(d + f4(e,a,b) + X[ 0] + 0x8f1bbcdc, 14) + c; a = RL(a, 10);
- c = RL(c + f4(d,e,a) + X[ 8] + 0x8f1bbcdc, 15) + b; e = RL(e, 10);
- b = RL(b + f4(c,d,e) + X[12] + 0x8f1bbcdc, 9) + a; d = RL(d, 10);
- a = RL(a + f4(b,c,d) + X[ 4] + 0x8f1bbcdc, 8) + e; c = RL(c, 10);
- e = RL(e + f4(a,b,c) + X[13] + 0x8f1bbcdc, 9) + d; b = RL(b, 10);
- d = RL(d + f4(e,a,b) + X[ 3] + 0x8f1bbcdc, 14) + c; a = RL(a, 10);
- c = RL(c + f4(d,e,a) + X[ 7] + 0x8f1bbcdc, 5) + b; e = RL(e, 10);
- b = RL(b + f4(c,d,e) + X[15] + 0x8f1bbcdc, 6) + a; d = RL(d, 10);
- a = RL(a + f4(b,c,d) + X[14] + 0x8f1bbcdc, 8) + e; c = RL(c, 10);
- e = RL(e + f4(a,b,c) + X[ 5] + 0x8f1bbcdc, 6) + d; b = RL(b, 10);
- d = RL(d + f4(e,a,b) + X[ 6] + 0x8f1bbcdc, 5) + c; a = RL(a, 10);
- c = RL(c + f4(d,e,a) + X[ 2] + 0x8f1bbcdc, 12) + b; e = RL(e, 10);
-
- // right
- cc = RL(cc + f2(dd,ee,aa) + X[ 8] + 0x7a6d76e9, 15) + bb; ee = RL(ee, 10);
- bb = RL(bb + f2(cc,dd,ee) + X[ 6] + 0x7a6d76e9, 5) + aa; dd = RL(dd, 10);
- aa = RL(aa + f2(bb,cc,dd) + X[ 4] + 0x7a6d76e9, 8) + ee; cc = RL(cc, 10);
- ee = RL(ee + f2(aa,bb,cc) + X[ 1] + 0x7a6d76e9, 11) + dd; bb = RL(bb, 10);
- dd = RL(dd + f2(ee,aa,bb) + X[ 3] + 0x7a6d76e9, 14) + cc; aa = RL(aa, 10);
- cc = RL(cc + f2(dd,ee,aa) + X[11] + 0x7a6d76e9, 14) + bb; ee = RL(ee, 10);
- bb = RL(bb + f2(cc,dd,ee) + X[15] + 0x7a6d76e9, 6) + aa; dd = RL(dd, 10);
- aa = RL(aa + f2(bb,cc,dd) + X[ 0] + 0x7a6d76e9, 14) + ee; cc = RL(cc, 10);
- ee = RL(ee + f2(aa,bb,cc) + X[ 5] + 0x7a6d76e9, 6) + dd; bb = RL(bb, 10);
- dd = RL(dd + f2(ee,aa,bb) + X[12] + 0x7a6d76e9, 9) + cc; aa = RL(aa, 10);
- cc = RL(cc + f2(dd,ee,aa) + X[ 2] + 0x7a6d76e9, 12) + bb; ee = RL(ee, 10);
- bb = RL(bb + f2(cc,dd,ee) + X[13] + 0x7a6d76e9, 9) + aa; dd = RL(dd, 10);
- aa = RL(aa + f2(bb,cc,dd) + X[ 9] + 0x7a6d76e9, 12) + ee; cc = RL(cc, 10);
- ee = RL(ee + f2(aa,bb,cc) + X[ 7] + 0x7a6d76e9, 5) + dd; bb = RL(bb, 10);
- dd = RL(dd + f2(ee,aa,bb) + X[10] + 0x7a6d76e9, 15) + cc; aa = RL(aa, 10);
- cc = RL(cc + f2(dd,ee,aa) + X[14] + 0x7a6d76e9, 8) + bb; ee = RL(ee, 10);
-
- t = d; d = dd; dd = t;
-
- //
- // Rounds 64-79
- //
- // left
- b = RL(b + f5(c,d,e) + X[ 4] + 0xa953fd4e, 9) + a; d = RL(d, 10);
- a = RL(a + f5(b,c,d) + X[ 0] + 0xa953fd4e, 15) + e; c = RL(c, 10);
- e = RL(e + f5(a,b,c) + X[ 5] + 0xa953fd4e, 5) + d; b = RL(b, 10);
- d = RL(d + f5(e,a,b) + X[ 9] + 0xa953fd4e, 11) + c; a = RL(a, 10);
- c = RL(c + f5(d,e,a) + X[ 7] + 0xa953fd4e, 6) + b; e = RL(e, 10);
- b = RL(b + f5(c,d,e) + X[12] + 0xa953fd4e, 8) + a; d = RL(d, 10);
- a = RL(a + f5(b,c,d) + X[ 2] + 0xa953fd4e, 13) + e; c = RL(c, 10);
- e = RL(e + f5(a,b,c) + X[10] + 0xa953fd4e, 12) + d; b = RL(b, 10);
- d = RL(d + f5(e,a,b) + X[14] + 0xa953fd4e, 5) + c; a = RL(a, 10);
- c = RL(c + f5(d,e,a) + X[ 1] + 0xa953fd4e, 12) + b; e = RL(e, 10);
- b = RL(b + f5(c,d,e) + X[ 3] + 0xa953fd4e, 13) + a; d = RL(d, 10);
- a = RL(a + f5(b,c,d) + X[ 8] + 0xa953fd4e, 14) + e; c = RL(c, 10);
- e = RL(e + f5(a,b,c) + X[11] + 0xa953fd4e, 11) + d; b = RL(b, 10);
- d = RL(d + f5(e,a,b) + X[ 6] + 0xa953fd4e, 8) + c; a = RL(a, 10);
- c = RL(c + f5(d,e,a) + X[15] + 0xa953fd4e, 5) + b; e = RL(e, 10);
- b = RL(b + f5(c,d,e) + X[13] + 0xa953fd4e, 6) + a; d = RL(d, 10);
-
- // right
- bb = RL(bb + f1(cc,dd,ee) + X[12], 8) + aa; dd = RL(dd, 10);
- aa = RL(aa + f1(bb,cc,dd) + X[15], 5) + ee; cc = RL(cc, 10);
- ee = RL(ee + f1(aa,bb,cc) + X[10], 12) + dd; bb = RL(bb, 10);
- dd = RL(dd + f1(ee,aa,bb) + X[ 4], 9) + cc; aa = RL(aa, 10);
- cc = RL(cc + f1(dd,ee,aa) + X[ 1], 12) + bb; ee = RL(ee, 10);
- bb = RL(bb + f1(cc,dd,ee) + X[ 5], 5) + aa; dd = RL(dd, 10);
- aa = RL(aa + f1(bb,cc,dd) + X[ 8], 14) + ee; cc = RL(cc, 10);
- ee = RL(ee + f1(aa,bb,cc) + X[ 7], 6) + dd; bb = RL(bb, 10);
- dd = RL(dd + f1(ee,aa,bb) + X[ 6], 8) + cc; aa = RL(aa, 10);
- cc = RL(cc + f1(dd,ee,aa) + X[ 2], 13) + bb; ee = RL(ee, 10);
- bb = RL(bb + f1(cc,dd,ee) + X[13], 6) + aa; dd = RL(dd, 10);
- aa = RL(aa + f1(bb,cc,dd) + X[14], 5) + ee; cc = RL(cc, 10);
- ee = RL(ee + f1(aa,bb,cc) + X[ 0], 15) + dd; bb = RL(bb, 10);
- dd = RL(dd + f1(ee,aa,bb) + X[ 3], 13) + cc; aa = RL(aa, 10);
- cc = RL(cc + f1(dd,ee,aa) + X[ 9], 11) + bb; ee = RL(ee, 10);
- bb = RL(bb + f1(cc,dd,ee) + X[11], 11) + aa; dd = RL(dd, 10);
-
- //
- // do (e, ee) swap as part of assignment.
- //
-
- H0 += a;
- H1 += b;
- H2 += c;
- H3 += d;
- H4 += ee;
- H5 += aa;
- H6 += bb;
- H7 += cc;
- H8 += dd;
- H9 += e;
-
- //
- // reset the offset and clean out the word buffer.
- //
- xOff = 0;
- for (int i = 0; i != X.length; i++)
- {
- X[i] = 0;
- }
- }
-
- public Memoable copy()
- {
- return new RIPEMD320Digest(this);
- }
-
- public void reset(Memoable other)
- {
- RIPEMD320Digest d = (RIPEMD320Digest)other;
-
- doCopy(d);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/digests/SHA1Digest.java b/core/src/main/java/org/bouncycastle/crypto/digests/SHA1Digest.java
deleted file mode 100644
index 450dda46..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/SHA1Digest.java
+++ /dev/null
@@ -1,348 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-import org.bouncycastle.util.Memoable;
-import org.bouncycastle.util.Pack;
-
-/**
- * implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", pages 346 - 349.
- *
- * It is interesting to ponder why the, apart from the extra IV, the other difference here from MD5
- * is the "endianness" of the word processing!
- */
-public class SHA1Digest
- extends GeneralDigest
- implements EncodableDigest
-{
- private static final int DIGEST_LENGTH = 20;
-
- private int H1, H2, H3, H4, H5;
-
- private int[] X = new int[80];
- private int xOff;
-
- /**
- * Standard constructor
- */
- public SHA1Digest()
- {
- reset();
- }
-
- /**
- * Copy constructor. This will copy the state of the provided
- * message digest.
- */
- public SHA1Digest(SHA1Digest t)
- {
- super(t);
-
- copyIn(t);
- }
-
- public SHA1Digest(byte[] encodedState)
- {
- super(encodedState);
-
- H1 = Pack.bigEndianToInt(encodedState, 16);
- H2 = Pack.bigEndianToInt(encodedState, 20);
- H3 = Pack.bigEndianToInt(encodedState, 24);
- H4 = Pack.bigEndianToInt(encodedState, 28);
- H5 = Pack.bigEndianToInt(encodedState, 32);
-
- xOff = Pack.bigEndianToInt(encodedState, 36);
- for (int i = 0; i != xOff; i++)
- {
- X[i] = Pack.bigEndianToInt(encodedState, 40 + (i * 4));
- }
- }
-
- private void copyIn(SHA1Digest t)
- {
- H1 = t.H1;
- H2 = t.H2;
- H3 = t.H3;
- H4 = t.H4;
- H5 = t.H5;
-
- System.arraycopy(t.X, 0, X, 0, t.X.length);
- xOff = t.xOff;
- }
-
- public String getAlgorithmName()
- {
- return "SHA-1";
- }
-
- public int getDigestSize()
- {
- return DIGEST_LENGTH;
- }
-
- protected void processWord(
- byte[] in,
- int inOff)
- {
- // Note: Inlined for performance
-// X[xOff] = Pack.bigEndianToInt(in, inOff);
- int n = in[ inOff] << 24;
- n |= (in[++inOff] & 0xff) << 16;
- n |= (in[++inOff] & 0xff) << 8;
- n |= (in[++inOff] & 0xff);
- X[xOff] = n;
-
- if (++xOff == 16)
- {
- processBlock();
- }
- }
-
- protected void processLength(
- long bitLength)
- {
- if (xOff > 14)
- {
- processBlock();
- }
-
- X[14] = (int)(bitLength >>> 32);
- X[15] = (int)(bitLength & 0xffffffff);
- }
-
- public int doFinal(
- byte[] out,
- int outOff)
- {
- finish();
-
- Pack.intToBigEndian(H1, out, outOff);
- Pack.intToBigEndian(H2, out, outOff + 4);
- Pack.intToBigEndian(H3, out, outOff + 8);
- Pack.intToBigEndian(H4, out, outOff + 12);
- Pack.intToBigEndian(H5, out, outOff + 16);
-
- reset();
-
- return DIGEST_LENGTH;
- }
-
- /**
- * reset the chaining variables
- */
- public void reset()
- {
- super.reset();
-
- H1 = 0x67452301;
- H2 = 0xefcdab89;
- H3 = 0x98badcfe;
- H4 = 0x10325476;
- H5 = 0xc3d2e1f0;
-
- xOff = 0;
- for (int i = 0; i != X.length; i++)
- {
- X[i] = 0;
- }
- }
-
- //
- // Additive constants
- //
- private static final int Y1 = 0x5a827999;
- private static final int Y2 = 0x6ed9eba1;
- private static final int Y3 = 0x8f1bbcdc;
- private static final int Y4 = 0xca62c1d6;
-
- private int f(
- int u,
- int v,
- int w)
- {
- return ((u & v) | ((~u) & w));
- }
-
- private int h(
- int u,
- int v,
- int w)
- {
- return (u ^ v ^ w);
- }
-
- private int g(
- int u,
- int v,
- int w)
- {
- return ((u & v) | (u & w) | (v & w));
- }
-
- protected void processBlock()
- {
- //
- // expand 16 word block into 80 word block.
- //
- for (int i = 16; i < 80; i++)
- {
- int t = X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16];
- X[i] = t << 1 | t >>> 31;
- }
-
- //
- // set up working variables.
- //
- int A = H1;
- int B = H2;
- int C = H3;
- int D = H4;
- int E = H5;
-
- //
- // round 1
- //
- int idx = 0;
-
- for (int j = 0; j < 4; j++)
- {
- // E = rotateLeft(A, 5) + f(B, C, D) + E + X[idx++] + Y1
- // B = rotateLeft(B, 30)
- E += (A << 5 | A >>> 27) + f(B, C, D) + X[idx++] + Y1;
- B = B << 30 | B >>> 2;
-
- D += (E << 5 | E >>> 27) + f(A, B, C) + X[idx++] + Y1;
- A = A << 30 | A >>> 2;
-
- C += (D << 5 | D >>> 27) + f(E, A, B) + X[idx++] + Y1;
- E = E << 30 | E >>> 2;
-
- B += (C << 5 | C >>> 27) + f(D, E, A) + X[idx++] + Y1;
- D = D << 30 | D >>> 2;
-
- A += (B << 5 | B >>> 27) + f(C, D, E) + X[idx++] + Y1;
- C = C << 30 | C >>> 2;
- }
-
- //
- // round 2
- //
- for (int j = 0; j < 4; j++)
- {
- // E = rotateLeft(A, 5) + h(B, C, D) + E + X[idx++] + Y2
- // B = rotateLeft(B, 30)
- E += (A << 5 | A >>> 27) + h(B, C, D) + X[idx++] + Y2;
- B = B << 30 | B >>> 2;
-
- D += (E << 5 | E >>> 27) + h(A, B, C) + X[idx++] + Y2;
- A = A << 30 | A >>> 2;
-
- C += (D << 5 | D >>> 27) + h(E, A, B) + X[idx++] + Y2;
- E = E << 30 | E >>> 2;
-
- B += (C << 5 | C >>> 27) + h(D, E, A) + X[idx++] + Y2;
- D = D << 30 | D >>> 2;
-
- A += (B << 5 | B >>> 27) + h(C, D, E) + X[idx++] + Y2;
- C = C << 30 | C >>> 2;
- }
-
- //
- // round 3
- //
- for (int j = 0; j < 4; j++)
- {
- // E = rotateLeft(A, 5) + g(B, C, D) + E + X[idx++] + Y3
- // B = rotateLeft(B, 30)
- E += (A << 5 | A >>> 27) + g(B, C, D) + X[idx++] + Y3;
- B = B << 30 | B >>> 2;
-
- D += (E << 5 | E >>> 27) + g(A, B, C) + X[idx++] + Y3;
- A = A << 30 | A >>> 2;
-
- C += (D << 5 | D >>> 27) + g(E, A, B) + X[idx++] + Y3;
- E = E << 30 | E >>> 2;
-
- B += (C << 5 | C >>> 27) + g(D, E, A) + X[idx++] + Y3;
- D = D << 30 | D >>> 2;
-
- A += (B << 5 | B >>> 27) + g(C, D, E) + X[idx++] + Y3;
- C = C << 30 | C >>> 2;
- }
-
- //
- // round 4
- //
- for (int j = 0; j <= 3; j++)
- {
- // E = rotateLeft(A, 5) + h(B, C, D) + E + X[idx++] + Y4
- // B = rotateLeft(B, 30)
- E += (A << 5 | A >>> 27) + h(B, C, D) + X[idx++] + Y4;
- B = B << 30 | B >>> 2;
-
- D += (E << 5 | E >>> 27) + h(A, B, C) + X[idx++] + Y4;
- A = A << 30 | A >>> 2;
-
- C += (D << 5 | D >>> 27) + h(E, A, B) + X[idx++] + Y4;
- E = E << 30 | E >>> 2;
-
- B += (C << 5 | C >>> 27) + h(D, E, A) + X[idx++] + Y4;
- D = D << 30 | D >>> 2;
-
- A += (B << 5 | B >>> 27) + h(C, D, E) + X[idx++] + Y4;
- C = C << 30 | C >>> 2;
- }
-
-
- H1 += A;
- H2 += B;
- H3 += C;
- H4 += D;
- H5 += E;
-
- //
- // reset start of the buffer.
- //
- xOff = 0;
- for (int i = 0; i < 16; i++)
- {
- X[i] = 0;
- }
- }
-
- public Memoable copy()
- {
- return new SHA1Digest(this);
- }
-
- public void reset(Memoable other)
- {
- SHA1Digest d = (SHA1Digest)other;
-
- super.copyIn(d);
- copyIn(d);
- }
-
- public byte[] getEncodedState()
- {
- byte[] state = new byte[40 + xOff * 4];
-
- super.populateState(state);
-
- Pack.intToBigEndian(H1, state, 16);
- Pack.intToBigEndian(H2, state, 20);
- Pack.intToBigEndian(H3, state, 24);
- Pack.intToBigEndian(H4, state, 28);
- Pack.intToBigEndian(H5, state, 32);
- Pack.intToBigEndian(xOff, state, 36);
-
- for (int i = 0; i != xOff; i++)
- {
- Pack.intToBigEndian(X[i], state, 40 + (i * 4));
- }
-
- return state;
- }
-}
-
-
-
-
diff --git a/core/src/main/java/org/bouncycastle/crypto/digests/SHA224Digest.java b/core/src/main/java/org/bouncycastle/crypto/digests/SHA224Digest.java
deleted file mode 100644
index 4f2b2842..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/SHA224Digest.java
+++ /dev/null
@@ -1,356 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-
-import org.bouncycastle.util.Memoable;
-import org.bouncycastle.util.Pack;
-
-
-/**
- * SHA-224 as described in RFC 3874
- * <pre>
- * block word digest
- * SHA-1 512 32 160
- * SHA-224 512 32 224
- * SHA-256 512 32 256
- * SHA-384 1024 64 384
- * SHA-512 1024 64 512
- * </pre>
- */
-public class SHA224Digest
- extends GeneralDigest
- implements EncodableDigest
-{
- private static final int DIGEST_LENGTH = 28;
-
- private int H1, H2, H3, H4, H5, H6, H7, H8;
-
- private int[] X = new int[64];
- private int xOff;
-
- /**
- * Standard constructor
- */
- public SHA224Digest()
- {
- reset();
- }
-
- /**
- * Copy constructor. This will copy the state of the provided
- * message digest.
- */
- public SHA224Digest(SHA224Digest t)
- {
- super(t);
-
- doCopy(t);
- }
-
- private void doCopy(SHA224Digest t)
- {
- super.copyIn(t);
-
- H1 = t.H1;
- H2 = t.H2;
- H3 = t.H3;
- H4 = t.H4;
- H5 = t.H5;
- H6 = t.H6;
- H7 = t.H7;
- H8 = t.H8;
-
- System.arraycopy(t.X, 0, X, 0, t.X.length);
- xOff = t.xOff;
- }
-
- public SHA224Digest(byte[] encodedState)
- {
- super(encodedState);
-
- H1 = Pack.bigEndianToInt(encodedState, 16);
- H2 = Pack.bigEndianToInt(encodedState, 20);
- H3 = Pack.bigEndianToInt(encodedState, 24);
- H4 = Pack.bigEndianToInt(encodedState, 28);
- H5 = Pack.bigEndianToInt(encodedState, 32);
- H6 = Pack.bigEndianToInt(encodedState, 36);
- H7 = Pack.bigEndianToInt(encodedState, 40);
- H8 = Pack.bigEndianToInt(encodedState, 44);
-
- xOff = Pack.bigEndianToInt(encodedState, 48);
- for (int i = 0; i != xOff; i++)
- {
- X[i] = Pack.bigEndianToInt(encodedState, 52 + (i * 4));
- }
- }
-
- public String getAlgorithmName()
- {
- return "SHA-224";
- }
-
- public int getDigestSize()
- {
- return DIGEST_LENGTH;
- }
-
- protected void processWord(
- byte[] in,
- int inOff)
- {
- // Note: Inlined for performance
-// X[xOff] = Pack.bigEndianToInt(in, inOff);
- int n = in[ inOff] << 24;
- n |= (in[++inOff] & 0xff) << 16;
- n |= (in[++inOff] & 0xff) << 8;
- n |= (in[++inOff] & 0xff);
- X[xOff] = n;
-
- if (++xOff == 16)
- {
- processBlock();
- }
- }
-
- protected void processLength(
- long bitLength)
- {
- if (xOff > 14)
- {
- processBlock();
- }
-
- X[14] = (int)(bitLength >>> 32);
- X[15] = (int)(bitLength & 0xffffffff);
- }
-
- public int doFinal(
- byte[] out,
- int outOff)
- {
- finish();
-
- Pack.intToBigEndian(H1, out, outOff);
- Pack.intToBigEndian(H2, out, outOff + 4);
- Pack.intToBigEndian(H3, out, outOff + 8);
- Pack.intToBigEndian(H4, out, outOff + 12);
- Pack.intToBigEndian(H5, out, outOff + 16);
- Pack.intToBigEndian(H6, out, outOff + 20);
- Pack.intToBigEndian(H7, out, outOff + 24);
-
- reset();
-
- return DIGEST_LENGTH;
- }
-
- /**
- * reset the chaining variables
- */
- public void reset()
- {
- super.reset();
-
- /* SHA-224 initial hash value
- */
-
- H1 = 0xc1059ed8;
- H2 = 0x367cd507;
- H3 = 0x3070dd17;
- H4 = 0xf70e5939;
- H5 = 0xffc00b31;
- H6 = 0x68581511;
- H7 = 0x64f98fa7;
- H8 = 0xbefa4fa4;
-
- xOff = 0;
- for (int i = 0; i != X.length; i++)
- {
- X[i] = 0;
- }
- }
-
- protected void processBlock()
- {
- //
- // expand 16 word block into 64 word blocks.
- //
- for (int t = 16; t <= 63; t++)
- {
- X[t] = Theta1(X[t - 2]) + X[t - 7] + Theta0(X[t - 15]) + X[t - 16];
- }
-
- //
- // set up working variables.
- //
- int a = H1;
- int b = H2;
- int c = H3;
- int d = H4;
- int e = H5;
- int f = H6;
- int g = H7;
- int h = H8;
-
-
- int t = 0;
- for(int i = 0; i < 8; i ++)
- {
- // t = 8 * i
- h += Sum1(e) + Ch(e, f, g) + K[t] + X[t];
- d += h;
- h += Sum0(a) + Maj(a, b, c);
- ++t;
-
- // t = 8 * i + 1
- g += Sum1(d) + Ch(d, e, f) + K[t] + X[t];
- c += g;
- g += Sum0(h) + Maj(h, a, b);
- ++t;
-
- // t = 8 * i + 2
- f += Sum1(c) + Ch(c, d, e) + K[t] + X[t];
- b += f;
- f += Sum0(g) + Maj(g, h, a);
- ++t;
-
- // t = 8 * i + 3
- e += Sum1(b) + Ch(b, c, d) + K[t] + X[t];
- a += e;
- e += Sum0(f) + Maj(f, g, h);
- ++t;
-
- // t = 8 * i + 4
- d += Sum1(a) + Ch(a, b, c) + K[t] + X[t];
- h += d;
- d += Sum0(e) + Maj(e, f, g);
- ++t;
-
- // t = 8 * i + 5
- c += Sum1(h) + Ch(h, a, b) + K[t] + X[t];
- g += c;
- c += Sum0(d) + Maj(d, e, f);
- ++t;
-
- // t = 8 * i + 6
- b += Sum1(g) + Ch(g, h, a) + K[t] + X[t];
- f += b;
- b += Sum0(c) + Maj(c, d, e);
- ++t;
-
- // t = 8 * i + 7
- a += Sum1(f) + Ch(f, g, h) + K[t] + X[t];
- e += a;
- a += Sum0(b) + Maj(b, c, d);
- ++t;
- }
-
- H1 += a;
- H2 += b;
- H3 += c;
- H4 += d;
- H5 += e;
- H6 += f;
- H7 += g;
- H8 += h;
-
- //
- // reset the offset and clean out the word buffer.
- //
- xOff = 0;
- for (int i = 0; i < 16; i++)
- {
- X[i] = 0;
- }
- }
-
- /* SHA-224 functions */
- private int Ch(
- int x,
- int y,
- int z)
- {
- return ((x & y) ^ ((~x) & z));
- }
-
- private int Maj(
- int x,
- int y,
- int z)
- {
- return ((x & y) ^ (x & z) ^ (y & z));
- }
-
- private int Sum0(
- int x)
- {
- return ((x >>> 2) | (x << 30)) ^ ((x >>> 13) | (x << 19)) ^ ((x >>> 22) | (x << 10));
- }
-
- private int Sum1(
- int x)
- {
- return ((x >>> 6) | (x << 26)) ^ ((x >>> 11) | (x << 21)) ^ ((x >>> 25) | (x << 7));
- }
-
- private int Theta0(
- int x)
- {
- return ((x >>> 7) | (x << 25)) ^ ((x >>> 18) | (x << 14)) ^ (x >>> 3);
- }
-
- private int Theta1(
- int x)
- {
- return ((x >>> 17) | (x << 15)) ^ ((x >>> 19) | (x << 13)) ^ (x >>> 10);
- }
-
- /* SHA-224 Constants
- * (represent the first 32 bits of the fractional parts of the
- * cube roots of the first sixty-four prime numbers)
- */
- static final int K[] = {
- 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
- };
-
- public Memoable copy()
- {
- return new SHA224Digest(this);
- }
-
- public void reset(Memoable other)
- {
- SHA224Digest d = (SHA224Digest)other;
-
- doCopy(d);
- }
-
- public byte[] getEncodedState()
- {
- byte[] state = new byte[52 + xOff * 4];
-
- super.populateState(state);
-
- Pack.intToBigEndian(H1, state, 16);
- Pack.intToBigEndian(H2, state, 20);
- Pack.intToBigEndian(H3, state, 24);
- Pack.intToBigEndian(H4, state, 28);
- Pack.intToBigEndian(H5, state, 32);
- Pack.intToBigEndian(H6, state, 36);
- Pack.intToBigEndian(H7, state, 40);
- Pack.intToBigEndian(H8, state, 44);
- Pack.intToBigEndian(xOff, state, 48);
-
- for (int i = 0; i != xOff; i++)
- {
- Pack.intToBigEndian(X[i], state, 52 + (i * 4));
- }
-
- return state;
- }
-}
-
diff --git a/core/src/main/java/org/bouncycastle/crypto/digests/SHA256Digest.java b/core/src/main/java/org/bouncycastle/crypto/digests/SHA256Digest.java
deleted file mode 100644
index 600d2343..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/SHA256Digest.java
+++ /dev/null
@@ -1,360 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-
-import org.bouncycastle.util.Memoable;
-import org.bouncycastle.util.Pack;
-
-
-/**
- * FIPS 180-2 implementation of SHA-256.
- *
- * <pre>
- * block word digest
- * SHA-1 512 32 160
- * SHA-256 512 32 256
- * SHA-384 1024 64 384
- * SHA-512 1024 64 512
- * </pre>
- */
-public class SHA256Digest
- extends GeneralDigest
- implements EncodableDigest
-{
- private static final int DIGEST_LENGTH = 32;
-
- private int H1, H2, H3, H4, H5, H6, H7, H8;
-
- private int[] X = new int[64];
- private int xOff;
-
- /**
- * Standard constructor
- */
- public SHA256Digest()
- {
- reset();
- }
-
- /**
- * Copy constructor. This will copy the state of the provided
- * message digest.
- */
- public SHA256Digest(SHA256Digest t)
- {
- super(t);
-
- copyIn(t);
- }
-
- private void copyIn(SHA256Digest t)
- {
- super.copyIn(t);
-
- H1 = t.H1;
- H2 = t.H2;
- H3 = t.H3;
- H4 = t.H4;
- H5 = t.H5;
- H6 = t.H6;
- H7 = t.H7;
- H8 = t.H8;
-
- System.arraycopy(t.X, 0, X, 0, t.X.length);
- xOff = t.xOff;
- }
-
- public SHA256Digest(byte[] encodedState)
- {
- super(encodedState);
-
- H1 = Pack.bigEndianToInt(encodedState, 16);
- H2 = Pack.bigEndianToInt(encodedState, 20);
- H3 = Pack.bigEndianToInt(encodedState, 24);
- H4 = Pack.bigEndianToInt(encodedState, 28);
- H5 = Pack.bigEndianToInt(encodedState, 32);
- H6 = Pack.bigEndianToInt(encodedState, 36);
- H7 = Pack.bigEndianToInt(encodedState, 40);
- H8 = Pack.bigEndianToInt(encodedState, 44);
-
- xOff = Pack.bigEndianToInt(encodedState, 48);
- for (int i = 0; i != xOff; i++)
- {
- X[i] = Pack.bigEndianToInt(encodedState, 52 + (i * 4));
- }
- }
-
-
- public String getAlgorithmName()
- {
- return "SHA-256";
- }
-
- public int getDigestSize()
- {
- return DIGEST_LENGTH;
- }
-
- protected void processWord(
- byte[] in,
- int inOff)
- {
- // Note: Inlined for performance
-// X[xOff] = Pack.bigEndianToInt(in, inOff);
- int n = in[inOff] << 24;
- n |= (in[++inOff] & 0xff) << 16;
- n |= (in[++inOff] & 0xff) << 8;
- n |= (in[++inOff] & 0xff);
- X[xOff] = n;
-
- if (++xOff == 16)
- {
- processBlock();
- }
- }
-
- protected void processLength(
- long bitLength)
- {
- if (xOff > 14)
- {
- processBlock();
- }
-
- X[14] = (int)(bitLength >>> 32);
- X[15] = (int)(bitLength & 0xffffffff);
- }
-
- public int doFinal(
- byte[] out,
- int outOff)
- {
- finish();
-
- Pack.intToBigEndian(H1, out, outOff);
- Pack.intToBigEndian(H2, out, outOff + 4);
- Pack.intToBigEndian(H3, out, outOff + 8);
- Pack.intToBigEndian(H4, out, outOff + 12);
- Pack.intToBigEndian(H5, out, outOff + 16);
- Pack.intToBigEndian(H6, out, outOff + 20);
- Pack.intToBigEndian(H7, out, outOff + 24);
- Pack.intToBigEndian(H8, out, outOff + 28);
-
- reset();
-
- return DIGEST_LENGTH;
- }
-
- /**
- * reset the chaining variables
- */
- public void reset()
- {
- super.reset();
-
- /* SHA-256 initial hash value
- * The first 32 bits of the fractional parts of the square roots
- * of the first eight prime numbers
- */
-
- H1 = 0x6a09e667;
- H2 = 0xbb67ae85;
- H3 = 0x3c6ef372;
- H4 = 0xa54ff53a;
- H5 = 0x510e527f;
- H6 = 0x9b05688c;
- H7 = 0x1f83d9ab;
- H8 = 0x5be0cd19;
-
- xOff = 0;
- for (int i = 0; i != X.length; i++)
- {
- X[i] = 0;
- }
- }
-
- protected void processBlock()
- {
- //
- // expand 16 word block into 64 word blocks.
- //
- for (int t = 16; t <= 63; t++)
- {
- X[t] = Theta1(X[t - 2]) + X[t - 7] + Theta0(X[t - 15]) + X[t - 16];
- }
-
- //
- // set up working variables.
- //
- int a = H1;
- int b = H2;
- int c = H3;
- int d = H4;
- int e = H5;
- int f = H6;
- int g = H7;
- int h = H8;
-
- int t = 0;
- for(int i = 0; i < 8; i ++)
- {
- // t = 8 * i
- h += Sum1(e) + Ch(e, f, g) + K[t] + X[t];
- d += h;
- h += Sum0(a) + Maj(a, b, c);
- ++t;
-
- // t = 8 * i + 1
- g += Sum1(d) + Ch(d, e, f) + K[t] + X[t];
- c += g;
- g += Sum0(h) + Maj(h, a, b);
- ++t;
-
- // t = 8 * i + 2
- f += Sum1(c) + Ch(c, d, e) + K[t] + X[t];
- b += f;
- f += Sum0(g) + Maj(g, h, a);
- ++t;
-
- // t = 8 * i + 3
- e += Sum1(b) + Ch(b, c, d) + K[t] + X[t];
- a += e;
- e += Sum0(f) + Maj(f, g, h);
- ++t;
-
- // t = 8 * i + 4
- d += Sum1(a) + Ch(a, b, c) + K[t] + X[t];
- h += d;
- d += Sum0(e) + Maj(e, f, g);
- ++t;
-
- // t = 8 * i + 5
- c += Sum1(h) + Ch(h, a, b) + K[t] + X[t];
- g += c;
- c += Sum0(d) + Maj(d, e, f);
- ++t;
-
- // t = 8 * i + 6
- b += Sum1(g) + Ch(g, h, a) + K[t] + X[t];
- f += b;
- b += Sum0(c) + Maj(c, d, e);
- ++t;
-
- // t = 8 * i + 7
- a += Sum1(f) + Ch(f, g, h) + K[t] + X[t];
- e += a;
- a += Sum0(b) + Maj(b, c, d);
- ++t;
- }
-
- H1 += a;
- H2 += b;
- H3 += c;
- H4 += d;
- H5 += e;
- H6 += f;
- H7 += g;
- H8 += h;
-
- //
- // reset the offset and clean out the word buffer.
- //
- xOff = 0;
- for (int i = 0; i < 16; i++)
- {
- X[i] = 0;
- }
- }
-
- /* SHA-256 functions */
- private int Ch(
- int x,
- int y,
- int z)
- {
- return (x & y) ^ ((~x) & z);
- }
-
- private int Maj(
- int x,
- int y,
- int z)
- {
- return (x & y) ^ (x & z) ^ (y & z);
- }
-
- private int Sum0(
- int x)
- {
- return ((x >>> 2) | (x << 30)) ^ ((x >>> 13) | (x << 19)) ^ ((x >>> 22) | (x << 10));
- }
-
- private int Sum1(
- int x)
- {
- return ((x >>> 6) | (x << 26)) ^ ((x >>> 11) | (x << 21)) ^ ((x >>> 25) | (x << 7));
- }
-
- private int Theta0(
- int x)
- {
- return ((x >>> 7) | (x << 25)) ^ ((x >>> 18) | (x << 14)) ^ (x >>> 3);
- }
-
- private int Theta1(
- int x)
- {
- return ((x >>> 17) | (x << 15)) ^ ((x >>> 19) | (x << 13)) ^ (x >>> 10);
- }
-
- /* SHA-256 Constants
- * (represent the first 32 bits of the fractional parts of the
- * cube roots of the first sixty-four prime numbers)
- */
- static final int K[] = {
- 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
- };
-
- public Memoable copy()
- {
- return new SHA256Digest(this);
- }
-
- public void reset(Memoable other)
- {
- SHA256Digest d = (SHA256Digest)other;
-
- copyIn(d);
- }
-
- public byte[] getEncodedState()
- {
- byte[] state = new byte[52 + xOff * 4];
-
- super.populateState(state);
-
- Pack.intToBigEndian(H1, state, 16);
- Pack.intToBigEndian(H2, state, 20);
- Pack.intToBigEndian(H3, state, 24);
- Pack.intToBigEndian(H4, state, 28);
- Pack.intToBigEndian(H5, state, 32);
- Pack.intToBigEndian(H6, state, 36);
- Pack.intToBigEndian(H7, state, 40);
- Pack.intToBigEndian(H8, state, 44);
- Pack.intToBigEndian(xOff, state, 48);
-
- for (int i = 0; i != xOff; i++)
- {
- Pack.intToBigEndian(X[i], state, 52 + (i * 4));
- }
-
- return state;
- }
-}
-
diff --git a/core/src/main/java/org/bouncycastle/crypto/digests/SHA384Digest.java b/core/src/main/java/org/bouncycastle/crypto/digests/SHA384Digest.java
deleted file mode 100644
index fc9fa1e7..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/SHA384Digest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-import org.bouncycastle.util.Memoable;
-import org.bouncycastle.util.Pack;
-
-
-/**
- * FIPS 180-2 implementation of SHA-384.
- *
- * <pre>
- * block word digest
- * SHA-1 512 32 160
- * SHA-256 512 32 256
- * SHA-384 1024 64 384
- * SHA-512 1024 64 512
- * </pre>
- */
-public class SHA384Digest
- extends LongDigest
-{
- private static final int DIGEST_LENGTH = 48;
-
- /**
- * Standard constructor
- */
- public SHA384Digest()
- {
- }
-
- /**
- * Copy constructor. This will copy the state of the provided
- * message digest.
- */
- public SHA384Digest(SHA384Digest t)
- {
- super(t);
- }
-
- public SHA384Digest(byte[] encodedState)
- {
- restoreState(encodedState);
- }
-
- public String getAlgorithmName()
- {
- return "SHA-384";
- }
-
- public int getDigestSize()
- {
- return DIGEST_LENGTH;
- }
-
- public int doFinal(
- byte[] out,
- int outOff)
- {
- finish();
-
- Pack.longToBigEndian(H1, out, outOff);
- Pack.longToBigEndian(H2, out, outOff + 8);
- Pack.longToBigEndian(H3, out, outOff + 16);
- Pack.longToBigEndian(H4, out, outOff + 24);
- Pack.longToBigEndian(H5, out, outOff + 32);
- Pack.longToBigEndian(H6, out, outOff + 40);
-
- reset();
-
- return DIGEST_LENGTH;
- }
-
- /**
- * reset the chaining variables
- */
- public void reset()
- {
- super.reset();
-
- /* SHA-384 initial hash value
- * The first 64 bits of the fractional parts of the square roots
- * of the 9th through 16th prime numbers
- */
- H1 = 0xcbbb9d5dc1059ed8l;
- H2 = 0x629a292a367cd507l;
- H3 = 0x9159015a3070dd17l;
- H4 = 0x152fecd8f70e5939l;
- H5 = 0x67332667ffc00b31l;
- H6 = 0x8eb44a8768581511l;
- H7 = 0xdb0c2e0d64f98fa7l;
- H8 = 0x47b5481dbefa4fa4l;
- }
-
- public Memoable copy()
- {
- return new SHA384Digest(this);
- }
-
- public void reset(Memoable other)
- {
- SHA384Digest d = (SHA384Digest)other;
-
- super.copyIn(d);
- }
-
- public byte[] getEncodedState()
- {
- byte[] encoded = new byte[getEncodedStateSize()];
- super.populateState(encoded);
- return encoded;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/digests/SHA3Digest.java b/core/src/main/java/org/bouncycastle/crypto/digests/SHA3Digest.java
deleted file mode 100644
index e13dc614..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/SHA3Digest.java
+++ /dev/null
@@ -1,547 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-import org.bouncycastle.crypto.ExtendedDigest;
-import org.bouncycastle.util.Arrays;
-
-/**
- * implementation of SHA-3 based on following KeccakNISTInterface.c from http://keccak.noekeon.org/
- * <p>
- * Following the naming conventions used in the C source code to enable easy review of the implementation.
- */
-public class SHA3Digest
- implements ExtendedDigest
-{
- private static long[] KeccakRoundConstants = keccakInitializeRoundConstants();
-
- private static int[] KeccakRhoOffsets = keccakInitializeRhoOffsets();
-
- private static long[] keccakInitializeRoundConstants()
- {
- long[] keccakRoundConstants = new long[24];
- byte[] LFSRstate = new byte[1];
-
- LFSRstate[0] = 0x01;
- int i, j, bitPosition;
-
- for (i = 0; i < 24; i++)
- {
- keccakRoundConstants[i] = 0;
- for (j = 0; j < 7; j++)
- {
- bitPosition = (1 << j) - 1;
- if (LFSR86540(LFSRstate))
- {
- keccakRoundConstants[i] ^= 1L << bitPosition;
- }
- }
- }
-
- return keccakRoundConstants;
- }
-
- private static boolean LFSR86540(byte[] LFSR)
- {
- boolean result = (((LFSR[0]) & 0x01) != 0);
- if (((LFSR[0]) & 0x80) != 0)
- {
- LFSR[0] = (byte)(((LFSR[0]) << 1) ^ 0x71);
- }
- else
- {
- LFSR[0] <<= 1;
- }
-
- return result;
- }
-
- private static int[] keccakInitializeRhoOffsets()
- {
- int[] keccakRhoOffsets = new int[25];
- int x, y, t, newX, newY;
-
- keccakRhoOffsets[(((0) % 5) + 5 * ((0) % 5))] = 0;
- x = 1;
- y = 0;
- for (t = 0; t < 24; t++)
- {
- keccakRhoOffsets[(((x) % 5) + 5 * ((y) % 5))] = ((t + 1) * (t + 2) / 2) % 64;
- newX = (0 * x + 1 * y) % 5;
- newY = (2 * x + 3 * y) % 5;
- x = newX;
- y = newY;
- }
-
- return keccakRhoOffsets;
- }
-
- private byte[] state = new byte[(1600 / 8)];
- private byte[] dataQueue = new byte[(1536 / 8)];
- private int rate;
- private int bitsInQueue;
- private int fixedOutputLength;
- private boolean squeezing;
- private int bitsAvailableForSqueezing;
- private byte[] chunk;
- private byte[] oneByte;
-
- private void clearDataQueueSection(int off, int len)
- {
- for (int i = off; i != off + len; i++)
- {
- dataQueue[i] = 0;
- }
- }
-
- public SHA3Digest()
- {
- init(0);
- }
-
- public SHA3Digest(int bitLength)
- {
- init(bitLength);
- }
-
- public SHA3Digest(SHA3Digest source) {
- System.arraycopy(source.state, 0, this.state, 0, source.state.length);
- System.arraycopy(source.dataQueue, 0, this.dataQueue, 0, source.dataQueue.length);
- this.rate = source.rate;
- this.bitsInQueue = source.bitsInQueue;
- this.fixedOutputLength = source.fixedOutputLength;
- this.squeezing = source.squeezing;
- this.bitsAvailableForSqueezing = source.bitsAvailableForSqueezing;
- this.chunk = Arrays.clone(source.chunk);
- this.oneByte = Arrays.clone(source.oneByte);
- }
-
- public String getAlgorithmName()
- {
- return "SHA3-" + fixedOutputLength;
- }
-
- public int getDigestSize()
- {
- return fixedOutputLength / 8;
- }
-
- public void update(byte in)
- {
- oneByte[0] = in;
-
- doUpdate(oneByte, 0, 8L);
- }
-
- public void update(byte[] in, int inOff, int len)
- {
- doUpdate(in, inOff, len * 8L);
- }
-
- public int doFinal(byte[] out, int outOff)
- {
- squeeze(out, outOff, fixedOutputLength);
-
- reset();
-
- return getDigestSize();
- }
-
- public void reset()
- {
- init(fixedOutputLength);
- }
-
- /**
- * Return the size of block that the compression function is applied to in bytes.
- *
- * @return internal byte length of a block.
- */
- public int getByteLength()
- {
- return rate / 8;
- }
-
- private void init(int bitLength)
- {
- switch (bitLength)
- {
- case 0:
- case 288:
- initSponge(1024, 576);
- break;
- case 224:
- initSponge(1152, 448);
- break;
- case 256:
- initSponge(1088, 512);
- break;
- case 384:
- initSponge(832, 768);
- break;
- case 512:
- initSponge(576, 1024);
- break;
- default:
- throw new IllegalArgumentException("bitLength must be one of 224, 256, 384, or 512.");
- }
- }
-
- private void doUpdate(byte[] data, int off, long databitlen)
- {
- if ((databitlen % 8) == 0)
- {
- absorb(data, off, databitlen);
- }
- else
- {
- absorb(data, off, databitlen - (databitlen % 8));
-
- byte[] lastByte = new byte[1];
-
- lastByte[0] = (byte)(data[off + (int)(databitlen / 8)] >> (8 - (databitlen % 8)));
- absorb(lastByte, off, databitlen % 8);
- }
- }
-
- private void initSponge(int rate, int capacity)
- {
- if (rate + capacity != 1600)
- {
- throw new IllegalStateException("rate + capacity != 1600");
- }
- if ((rate <= 0) || (rate >= 1600) || ((rate % 64) != 0))
- {
- throw new IllegalStateException("invalid rate value");
- }
-
- this.rate = rate;
- // this is never read, need to check to see why we want to save it
- // this.capacity = capacity;
- this.fixedOutputLength = 0;
- Arrays.fill(this.state, (byte)0);
- Arrays.fill(this.dataQueue, (byte)0);
- this.bitsInQueue = 0;
- this.squeezing = false;
- this.bitsAvailableForSqueezing = 0;
- this.fixedOutputLength = capacity / 2;
- this.chunk = new byte[rate / 8];
- this.oneByte = new byte[1];
- }
-
- private void absorbQueue()
- {
- KeccakAbsorb(state, dataQueue, rate / 8);
-
- bitsInQueue = 0;
- }
-
- private void absorb(byte[] data, int off, long databitlen)
- {
- long i, j, wholeBlocks;
-
- if ((bitsInQueue % 8) != 0)
- {
- throw new IllegalStateException("attempt to absorb with odd length queue.");
- }
- if (squeezing)
- {
- throw new IllegalStateException("attempt to absorb while squeezing.");
- }
-
- i = 0;
- while (i < databitlen)
- {
- if ((bitsInQueue == 0) && (databitlen >= rate) && (i <= (databitlen - rate)))
- {
- wholeBlocks = (databitlen - i) / rate;
-
- for (j = 0; j < wholeBlocks; j++)
- {
- System.arraycopy(data, (int)(off + (i / 8) + (j * chunk.length)), chunk, 0, chunk.length);
-
-// displayIntermediateValues.displayBytes(1, "Block to be absorbed", curData, rate / 8);
-
- KeccakAbsorb(state, chunk, chunk.length);
- }
-
- i += wholeBlocks * rate;
- }
- else
- {
- int partialBlock = (int)(databitlen - i);
- if (partialBlock + bitsInQueue > rate)
- {
- partialBlock = rate - bitsInQueue;
- }
- int partialByte = partialBlock % 8;
- partialBlock -= partialByte;
- System.arraycopy(data, off + (int)(i / 8), dataQueue, bitsInQueue / 8, partialBlock / 8);
-
- bitsInQueue += partialBlock;
- i += partialBlock;
- if (bitsInQueue == rate)
- {
- absorbQueue();
- }
- if (partialByte > 0)
- {
- int mask = (1 << partialByte) - 1;
- dataQueue[bitsInQueue / 8] = (byte)(data[off + ((int)(i / 8))] & mask);
- bitsInQueue += partialByte;
- i += partialByte;
- }
- }
- }
- }
-
- private void padAndSwitchToSqueezingPhase()
- {
- if (bitsInQueue + 1 == rate)
- {
- dataQueue[bitsInQueue / 8] |= 1 << (bitsInQueue % 8);
- absorbQueue();
- clearDataQueueSection(0, rate / 8);
- }
- else
- {
- clearDataQueueSection((bitsInQueue + 7) / 8, rate / 8 - (bitsInQueue + 7) / 8);
- dataQueue[bitsInQueue / 8] |= 1 << (bitsInQueue % 8);
- }
- dataQueue[(rate - 1) / 8] |= 1 << ((rate - 1) % 8);
- absorbQueue();
-
-
-// displayIntermediateValues.displayText(1, "--- Switching to squeezing phase ---");
-
-
- if (rate == 1024)
- {
- KeccakExtract1024bits(state, dataQueue);
- bitsAvailableForSqueezing = 1024;
- }
- else
-
- {
- KeccakExtract(state, dataQueue, rate / 64);
- bitsAvailableForSqueezing = rate;
- }
-
-// displayIntermediateValues.displayBytes(1, "Block available for squeezing", dataQueue, bitsAvailableForSqueezing / 8);
-
- squeezing = true;
- }
-
- private void squeeze(byte[] output, int offset, long outputLength)
- {
- long i;
- int partialBlock;
-
- if (!squeezing)
- {
- padAndSwitchToSqueezingPhase();
- }
- if ((outputLength % 8) != 0)
- {
- throw new IllegalStateException("outputLength not a multiple of 8");
- }
-
- i = 0;
- while (i < outputLength)
- {
- if (bitsAvailableForSqueezing == 0)
- {
- keccakPermutation(state);
-
- if (rate == 1024)
- {
- KeccakExtract1024bits(state, dataQueue);
- bitsAvailableForSqueezing = 1024;
- }
- else
-
- {
- KeccakExtract(state, dataQueue, rate / 64);
- bitsAvailableForSqueezing = rate;
- }
-
-// displayIntermediateValues.displayBytes(1, "Block available for squeezing", dataQueue, bitsAvailableForSqueezing / 8);
-
- }
- partialBlock = bitsAvailableForSqueezing;
- if ((long)partialBlock > outputLength - i)
- {
- partialBlock = (int)(outputLength - i);
- }
-
- System.arraycopy(dataQueue, (rate - bitsAvailableForSqueezing) / 8, output, offset + (int)(i / 8), partialBlock / 8);
- bitsAvailableForSqueezing -= partialBlock;
- i += partialBlock;
- }
- }
-
- private void fromBytesToWords(long[] stateAsWords, byte[] state)
- {
- for (int i = 0; i < (1600 / 64); i++)
- {
- stateAsWords[i] = 0;
- int index = i * (64 / 8);
- for (int j = 0; j < (64 / 8); j++)
- {
- stateAsWords[i] |= ((long)state[index + j] & 0xff) << ((8 * j));
- }
- }
- }
-
- private void fromWordsToBytes(byte[] state, long[] stateAsWords)
- {
- for (int i = 0; i < (1600 / 64); i++)
- {
- int index = i * (64 / 8);
- for (int j = 0; j < (64 / 8); j++)
- {
- state[index + j] = (byte)((stateAsWords[i] >>> ((8 * j))) & 0xFF);
- }
- }
- }
-
- private void keccakPermutation(byte[] state)
- {
- long[] longState = new long[state.length / 8];
-
- fromBytesToWords(longState, state);
-
-// displayIntermediateValues.displayStateAsBytes(1, "Input of permutation", longState);
-
- keccakPermutationOnWords(longState);
-
-// displayIntermediateValues.displayStateAsBytes(1, "State after permutation", longState);
-
- fromWordsToBytes(state, longState);
- }
-
- private void keccakPermutationAfterXor(byte[] state, byte[] data, int dataLengthInBytes)
- {
- int i;
-
- for (i = 0; i < dataLengthInBytes; i++)
- {
- state[i] ^= data[i];
- }
-
- keccakPermutation(state);
- }
-
- private void keccakPermutationOnWords(long[] state)
- {
- int i;
-
-// displayIntermediateValues.displayStateAs64bitWords(3, "Same, with lanes as 64-bit words", state);
-
- for (i = 0; i < 24; i++)
- {
-// displayIntermediateValues.displayRoundNumber(3, i);
-
- theta(state);
-// displayIntermediateValues.displayStateAs64bitWords(3, "After theta", state);
-
- rho(state);
-// displayIntermediateValues.displayStateAs64bitWords(3, "After rho", state);
-
- pi(state);
-// displayIntermediateValues.displayStateAs64bitWords(3, "After pi", state);
-
- chi(state);
-// displayIntermediateValues.displayStateAs64bitWords(3, "After chi", state);
-
- iota(state, i);
-// displayIntermediateValues.displayStateAs64bitWords(3, "After iota", state);
- }
- }
-
- long[] C = new long[5];
-
- private void theta(long[] A)
- {
- for (int x = 0; x < 5; x++)
- {
- C[x] = 0;
- for (int y = 0; y < 5; y++)
- {
- C[x] ^= A[x + 5 * y];
- }
- }
- for (int x = 0; x < 5; x++)
- {
- long dX = ((((C[(x + 1) % 5]) << 1) ^ ((C[(x + 1) % 5]) >>> (64 - 1)))) ^ C[(x + 4) % 5];
- for (int y = 0; y < 5; y++)
- {
- A[x + 5 * y] ^= dX;
- }
- }
- }
-
- private void rho(long[] A)
- {
- for (int x = 0; x < 5; x++)
- {
- for (int y = 0; y < 5; y++)
- {
- int index = x + 5 * y;
- A[index] = ((KeccakRhoOffsets[index] != 0) ? (((A[index]) << KeccakRhoOffsets[index]) ^ ((A[index]) >>> (64 - KeccakRhoOffsets[index]))) : A[index]);
- }
- }
- }
-
- long[] tempA = new long[25];
-
- private void pi(long[] A)
- {
- System.arraycopy(A, 0, tempA, 0, tempA.length);
-
- for (int x = 0; x < 5; x++)
- {
- for (int y = 0; y < 5; y++)
- {
- A[y + 5 * ((2 * x + 3 * y) % 5)] = tempA[x + 5 * y];
- }
- }
- }
-
- long[] chiC = new long[5];
-
- private void chi(long[] A)
- {
- for (int y = 0; y < 5; y++)
- {
- for (int x = 0; x < 5; x++)
- {
- chiC[x] = A[x + 5 * y] ^ ((~A[(((x + 1) % 5) + 5 * y)]) & A[(((x + 2) % 5) + 5 * y)]);
- }
- for (int x = 0; x < 5; x++)
- {
- A[x + 5 * y] = chiC[x];
- }
- }
- }
-
- private void iota(long[] A, int indexRound)
- {
- A[(((0) % 5) + 5 * ((0) % 5))] ^= KeccakRoundConstants[indexRound];
- }
-
- private void KeccakAbsorb(byte[] byteState, byte[] data, int dataInBytes)
- {
- keccakPermutationAfterXor(byteState, data, dataInBytes);
- }
-
-
- private void KeccakExtract1024bits(byte[] byteState, byte[] data)
- {
- System.arraycopy(byteState, 0, data, 0, 128);
- }
-
-
- private void KeccakExtract(byte[] byteState, byte[] data, int laneCount)
- {
- System.arraycopy(byteState, 0, data, 0, laneCount * 8);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/digests/SHA512Digest.java b/core/src/main/java/org/bouncycastle/crypto/digests/SHA512Digest.java
deleted file mode 100644
index 644bafad..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/SHA512Digest.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-import org.bouncycastle.util.Memoable;
-import org.bouncycastle.util.Pack;
-
-
-/**
- * FIPS 180-2 implementation of SHA-512.
- *
- * <pre>
- * block word digest
- * SHA-1 512 32 160
- * SHA-256 512 32 256
- * SHA-384 1024 64 384
- * SHA-512 1024 64 512
- * </pre>
- */
-public class SHA512Digest
- extends LongDigest
-{
- private static final int DIGEST_LENGTH = 64;
-
- /**
- * Standard constructor
- */
- public SHA512Digest()
- {
- }
-
- /**
- * Copy constructor. This will copy the state of the provided
- * message digest.
- */
- public SHA512Digest(SHA512Digest t)
- {
- super(t);
- }
-
- public SHA512Digest(byte[] encodedState)
- {
- restoreState(encodedState);
- }
-
- public String getAlgorithmName()
- {
- return "SHA-512";
- }
-
- public int getDigestSize()
- {
- return DIGEST_LENGTH;
- }
-
- public int doFinal(
- byte[] out,
- int outOff)
- {
- finish();
-
- Pack.longToBigEndian(H1, out, outOff);
- Pack.longToBigEndian(H2, out, outOff + 8);
- Pack.longToBigEndian(H3, out, outOff + 16);
- Pack.longToBigEndian(H4, out, outOff + 24);
- Pack.longToBigEndian(H5, out, outOff + 32);
- Pack.longToBigEndian(H6, out, outOff + 40);
- Pack.longToBigEndian(H7, out, outOff + 48);
- Pack.longToBigEndian(H8, out, outOff + 56);
-
- reset();
-
- return DIGEST_LENGTH;
- }
-
- /**
- * reset the chaining variables
- */
- public void reset()
- {
- super.reset();
-
- /* SHA-512 initial hash value
- * The first 64 bits of the fractional parts of the square roots
- * of the first eight prime numbers
- */
- H1 = 0x6a09e667f3bcc908L;
- H2 = 0xbb67ae8584caa73bL;
- H3 = 0x3c6ef372fe94f82bL;
- H4 = 0xa54ff53a5f1d36f1L;
- H5 = 0x510e527fade682d1L;
- H6 = 0x9b05688c2b3e6c1fL;
- H7 = 0x1f83d9abfb41bd6bL;
- H8 = 0x5be0cd19137e2179L;
- }
-
- public Memoable copy()
- {
- return new SHA512Digest(this);
- }
-
- public void reset(Memoable other)
- {
- SHA512Digest d = (SHA512Digest)other;
-
- copyIn(d);
- }
-
- public byte[] getEncodedState()
- {
- byte[] encoded = new byte[getEncodedStateSize()];
- super.populateState(encoded);
- return encoded;
- }
-}
-
diff --git a/core/src/main/java/org/bouncycastle/crypto/digests/SHA512tDigest.java b/core/src/main/java/org/bouncycastle/crypto/digests/SHA512tDigest.java
deleted file mode 100644
index d5848b17..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/SHA512tDigest.java
+++ /dev/null
@@ -1,227 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-import org.bouncycastle.util.Memoable;
-import org.bouncycastle.util.MemoableResetException;
-import org.bouncycastle.util.Pack;
-
-/**
- * FIPS 180-4 implementation of SHA-512/t
- */
-public class SHA512tDigest
- extends LongDigest
-{
- private int digestLength; // non-final due to old flow analyser.
-
- private long H1t, H2t, H3t, H4t, H5t, H6t, H7t, H8t;
-
- /**
- * Standard constructor
- */
- public SHA512tDigest(int bitLength)
- {
- if (bitLength >= 512)
- {
- throw new IllegalArgumentException("bitLength cannot be >= 512");
- }
-
- if (bitLength % 8 != 0)
- {
- throw new IllegalArgumentException("bitLength needs to be a multiple of 8");
- }
-
- if (bitLength == 384)
- {
- throw new IllegalArgumentException("bitLength cannot be 384 use SHA384 instead");
- }
-
- this.digestLength = bitLength / 8;
-
- tIvGenerate(digestLength * 8);
-
- reset();
- }
-
- /**
- * Copy constructor. This will copy the state of the provided
- * message digest.
- */
- public SHA512tDigest(SHA512tDigest t)
- {
- super(t);
-
- this.digestLength = t.digestLength;
-
- reset(t);
- }
-
- public SHA512tDigest(byte[] encodedState)
- {
- this(readDigestLength(encodedState));
- restoreState(encodedState);
- }
-
- private static int readDigestLength(byte[] encodedState)
- {
- return Pack.bigEndianToInt(encodedState, encodedState.length - 4);
- }
-
- public String getAlgorithmName()
- {
- return "SHA-512/" + Integer.toString(digestLength * 8);
- }
-
- public int getDigestSize()
- {
- return digestLength;
- }
-
- public int doFinal(
- byte[] out,
- int outOff)
- {
- finish();
-
- longToBigEndian(H1, out, outOff, digestLength);
- longToBigEndian(H2, out, outOff + 8, digestLength - 8);
- longToBigEndian(H3, out, outOff + 16, digestLength - 16);
- longToBigEndian(H4, out, outOff + 24, digestLength - 24);
- longToBigEndian(H5, out, outOff + 32, digestLength - 32);
- longToBigEndian(H6, out, outOff + 40, digestLength - 40);
- longToBigEndian(H7, out, outOff + 48, digestLength - 48);
- longToBigEndian(H8, out, outOff + 56, digestLength - 56);
-
- reset();
-
- return digestLength;
- }
-
- /**
- * reset the chaining variables
- */
- public void reset()
- {
- super.reset();
-
- /*
- * initial hash values use the iv generation algorithm for t.
- */
- H1 = H1t;
- H2 = H2t;
- H3 = H3t;
- H4 = H4t;
- H5 = H5t;
- H6 = H6t;
- H7 = H7t;
- H8 = H8t;
- }
-
- private void tIvGenerate(int bitLength)
- {
- H1 = 0x6a09e667f3bcc908L ^ 0xa5a5a5a5a5a5a5a5L;
- H2 = 0xbb67ae8584caa73bL ^ 0xa5a5a5a5a5a5a5a5L;
- H3 = 0x3c6ef372fe94f82bL ^ 0xa5a5a5a5a5a5a5a5L;
- H4 = 0xa54ff53a5f1d36f1L ^ 0xa5a5a5a5a5a5a5a5L;
- H5 = 0x510e527fade682d1L ^ 0xa5a5a5a5a5a5a5a5L;
- H6 = 0x9b05688c2b3e6c1fL ^ 0xa5a5a5a5a5a5a5a5L;
- H7 = 0x1f83d9abfb41bd6bL ^ 0xa5a5a5a5a5a5a5a5L;
- H8 = 0x5be0cd19137e2179L ^ 0xa5a5a5a5a5a5a5a5L;
-
- update((byte)0x53);
- update((byte)0x48);
- update((byte)0x41);
- update((byte)0x2D);
- update((byte)0x35);
- update((byte)0x31);
- update((byte)0x32);
- update((byte)0x2F);
-
- if (bitLength > 100)
- {
- update((byte)(bitLength / 100 + 0x30));
- bitLength = bitLength % 100;
- update((byte)(bitLength / 10 + 0x30));
- bitLength = bitLength % 10;
- update((byte)(bitLength + 0x30));
- }
- else if (bitLength > 10)
- {
- update((byte)(bitLength / 10 + 0x30));
- bitLength = bitLength % 10;
- update((byte)(bitLength + 0x30));
- }
- else
- {
- update((byte)(bitLength + 0x30));
- }
-
- finish();
-
- H1t = H1;
- H2t = H2;
- H3t = H3;
- H4t = H4;
- H5t = H5;
- H6t = H6;
- H7t = H7;
- H8t = H8;
- }
-
- private static void longToBigEndian(long n, byte[] bs, int off, int max)
- {
- if (max > 0)
- {
- intToBigEndian((int)(n >>> 32), bs, off, max);
-
- if (max > 4)
- {
- intToBigEndian((int)(n & 0xffffffffL), bs, off + 4, max - 4);
- }
- }
- }
-
- private static void intToBigEndian(int n, byte[] bs, int off, int max)
- {
- int num = Math.min(4, max);
- while (--num >= 0)
- {
- int shift = 8 * (3 - num);
- bs[off + num] = (byte)(n >>> shift);
- }
- }
-
- public Memoable copy()
- {
- return new SHA512tDigest(this);
- }
-
- public void reset(Memoable other)
- {
- SHA512tDigest t = (SHA512tDigest)other;
-
- if (this.digestLength != t.digestLength)
- {
- throw new MemoableResetException("digestLength inappropriate in other");
- }
-
- super.copyIn(t);
-
- this.H1t = t.H1t;
- this.H2t = t.H2t;
- this.H3t = t.H3t;
- this.H4t = t.H4t;
- this.H5t = t.H5t;
- this.H6t = t.H6t;
- this.H7t = t.H7t;
- this.H8t = t.H8t;
- }
-
- public byte[] getEncodedState()
- {
- final int baseSize = getEncodedStateSize();
- byte[] encoded = new byte[baseSize + 4];
- populateState(encoded);
- Pack.intToBigEndian(digestLength * 8, encoded, baseSize);
- return encoded;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/digests/SM3Digest.java b/core/src/main/java/org/bouncycastle/crypto/digests/SM3Digest.java
deleted file mode 100644
index 5e90add5..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/SM3Digest.java
+++ /dev/null
@@ -1,333 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-import org.bouncycastle.util.Memoable;
-import org.bouncycastle.util.Pack;
-
-/**
- * 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/core/src/main/java/org/bouncycastle/crypto/digests/ShortenedDigest.java b/core/src/main/java/org/bouncycastle/crypto/digests/ShortenedDigest.java
deleted file mode 100644
index 89033e80..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/ShortenedDigest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-import org.bouncycastle.crypto.ExtendedDigest;
-
-/**
- * Wrapper class that reduces the output length of a particular digest to
- * only the first n bytes of the digest function.
- */
-public class ShortenedDigest
- implements ExtendedDigest
-{
- private ExtendedDigest baseDigest;
- private int length;
-
- /**
- * Base constructor.
- *
- * @param baseDigest underlying digest to use.
- * @param length length in bytes of the output of doFinal.
- * @exception IllegalArgumentException if baseDigest is null, or length is greater than baseDigest.getDigestSize().
- */
- public ShortenedDigest(
- ExtendedDigest baseDigest,
- int length)
- {
- if (baseDigest == null)
- {
- throw new IllegalArgumentException("baseDigest must not be null");
- }
-
- if (length > baseDigest.getDigestSize())
- {
- throw new IllegalArgumentException("baseDigest output not large enough to support length");
- }
-
- this.baseDigest = baseDigest;
- this.length = length;
- }
-
- public String getAlgorithmName()
- {
- return baseDigest.getAlgorithmName() + "(" + length * 8 + ")";
- }
-
- public int getDigestSize()
- {
- return length;
- }
-
- public void update(byte in)
- {
- baseDigest.update(in);
- }
-
- public void update(byte[] in, int inOff, int len)
- {
- baseDigest.update(in, inOff, len);
- }
-
- public int doFinal(byte[] out, int outOff)
- {
- byte[] tmp = new byte[baseDigest.getDigestSize()];
-
- baseDigest.doFinal(tmp, 0);
-
- System.arraycopy(tmp, 0, out, outOff, length);
-
- return length;
- }
-
- public void reset()
- {
- baseDigest.reset();
- }
-
- public int getByteLength()
- {
- return baseDigest.getByteLength();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/digests/SkeinDigest.java b/core/src/main/java/org/bouncycastle/crypto/digests/SkeinDigest.java
deleted file mode 100644
index ae1dbd62..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/SkeinDigest.java
+++ /dev/null
@@ -1,115 +0,0 @@
-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.
- *
- * @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/core/src/main/java/org/bouncycastle/crypto/digests/SkeinEngine.java b/core/src/main/java/org/bouncycastle/crypto/digests/SkeinEngine.java
deleted file mode 100644
index b125dbd6..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/SkeinEngine.java
+++ /dev/null
@@ -1,817 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/digests/TigerDigest.java b/core/src/main/java/org/bouncycastle/crypto/digests/TigerDigest.java
deleted file mode 100644
index 2899e305..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/TigerDigest.java
+++ /dev/null
@@ -1,879 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-import org.bouncycastle.crypto.ExtendedDigest;
-import org.bouncycastle.util.Memoable;
-
-/**
- * implementation of Tiger based on:
- * <a href="http://www.cs.technion.ac.il/~biham/Reports/Tiger">
- * http://www.cs.technion.ac.il/~biham/Reports/Tiger</a>
- */
-public class TigerDigest
- implements ExtendedDigest, Memoable
-{
- private static final int BYTE_LENGTH = 64;
-
- /*
- * S-Boxes.
- */
- private static final long[] t1 = {
- 0x02AAB17CF7E90C5EL /* 0 */, 0xAC424B03E243A8ECL /* 1 */,
- 0x72CD5BE30DD5FCD3L /* 2 */, 0x6D019B93F6F97F3AL /* 3 */,
- 0xCD9978FFD21F9193L /* 4 */, 0x7573A1C9708029E2L /* 5 */,
- 0xB164326B922A83C3L /* 6 */, 0x46883EEE04915870L /* 7 */,
- 0xEAACE3057103ECE6L /* 8 */, 0xC54169B808A3535CL /* 9 */,
- 0x4CE754918DDEC47CL /* 10 */, 0x0AA2F4DFDC0DF40CL /* 11 */,
- 0x10B76F18A74DBEFAL /* 12 */, 0xC6CCB6235AD1AB6AL /* 13 */,
- 0x13726121572FE2FFL /* 14 */, 0x1A488C6F199D921EL /* 15 */,
- 0x4BC9F9F4DA0007CAL /* 16 */, 0x26F5E6F6E85241C7L /* 17 */,
- 0x859079DBEA5947B6L /* 18 */, 0x4F1885C5C99E8C92L /* 19 */,
- 0xD78E761EA96F864BL /* 20 */, 0x8E36428C52B5C17DL /* 21 */,
- 0x69CF6827373063C1L /* 22 */, 0xB607C93D9BB4C56EL /* 23 */,
- 0x7D820E760E76B5EAL /* 24 */, 0x645C9CC6F07FDC42L /* 25 */,
- 0xBF38A078243342E0L /* 26 */, 0x5F6B343C9D2E7D04L /* 27 */,
- 0xF2C28AEB600B0EC6L /* 28 */, 0x6C0ED85F7254BCACL /* 29 */,
- 0x71592281A4DB4FE5L /* 30 */, 0x1967FA69CE0FED9FL /* 31 */,
- 0xFD5293F8B96545DBL /* 32 */, 0xC879E9D7F2A7600BL /* 33 */,
- 0x860248920193194EL /* 34 */, 0xA4F9533B2D9CC0B3L /* 35 */,
- 0x9053836C15957613L /* 36 */, 0xDB6DCF8AFC357BF1L /* 37 */,
- 0x18BEEA7A7A370F57L /* 38 */, 0x037117CA50B99066L /* 39 */,
- 0x6AB30A9774424A35L /* 40 */, 0xF4E92F02E325249BL /* 41 */,
- 0x7739DB07061CCAE1L /* 42 */, 0xD8F3B49CECA42A05L /* 43 */,
- 0xBD56BE3F51382F73L /* 44 */, 0x45FAED5843B0BB28L /* 45 */,
- 0x1C813D5C11BF1F83L /* 46 */, 0x8AF0E4B6D75FA169L /* 47 */,
- 0x33EE18A487AD9999L /* 48 */, 0x3C26E8EAB1C94410L /* 49 */,
- 0xB510102BC0A822F9L /* 50 */, 0x141EEF310CE6123BL /* 51 */,
- 0xFC65B90059DDB154L /* 52 */, 0xE0158640C5E0E607L /* 53 */,
- 0x884E079826C3A3CFL /* 54 */, 0x930D0D9523C535FDL /* 55 */,
- 0x35638D754E9A2B00L /* 56 */, 0x4085FCCF40469DD5L /* 57 */,
- 0xC4B17AD28BE23A4CL /* 58 */, 0xCAB2F0FC6A3E6A2EL /* 59 */,
- 0x2860971A6B943FCDL /* 60 */, 0x3DDE6EE212E30446L /* 61 */,
- 0x6222F32AE01765AEL /* 62 */, 0x5D550BB5478308FEL /* 63 */,
- 0xA9EFA98DA0EDA22AL /* 64 */, 0xC351A71686C40DA7L /* 65 */,
- 0x1105586D9C867C84L /* 66 */, 0xDCFFEE85FDA22853L /* 67 */,
- 0xCCFBD0262C5EEF76L /* 68 */, 0xBAF294CB8990D201L /* 69 */,
- 0xE69464F52AFAD975L /* 70 */, 0x94B013AFDF133E14L /* 71 */,
- 0x06A7D1A32823C958L /* 72 */, 0x6F95FE5130F61119L /* 73 */,
- 0xD92AB34E462C06C0L /* 74 */, 0xED7BDE33887C71D2L /* 75 */,
- 0x79746D6E6518393EL /* 76 */, 0x5BA419385D713329L /* 77 */,
- 0x7C1BA6B948A97564L /* 78 */, 0x31987C197BFDAC67L /* 79 */,
- 0xDE6C23C44B053D02L /* 80 */, 0x581C49FED002D64DL /* 81 */,
- 0xDD474D6338261571L /* 82 */, 0xAA4546C3E473D062L /* 83 */,
- 0x928FCE349455F860L /* 84 */, 0x48161BBACAAB94D9L /* 85 */,
- 0x63912430770E6F68L /* 86 */, 0x6EC8A5E602C6641CL /* 87 */,
- 0x87282515337DDD2BL /* 88 */, 0x2CDA6B42034B701BL /* 89 */,
- 0xB03D37C181CB096DL /* 90 */, 0xE108438266C71C6FL /* 91 */,
- 0x2B3180C7EB51B255L /* 92 */, 0xDF92B82F96C08BBCL /* 93 */,
- 0x5C68C8C0A632F3BAL /* 94 */, 0x5504CC861C3D0556L /* 95 */,
- 0xABBFA4E55FB26B8FL /* 96 */, 0x41848B0AB3BACEB4L /* 97 */,
- 0xB334A273AA445D32L /* 98 */, 0xBCA696F0A85AD881L /* 99 */,
- 0x24F6EC65B528D56CL /* 100 */, 0x0CE1512E90F4524AL /* 101 */,
- 0x4E9DD79D5506D35AL /* 102 */, 0x258905FAC6CE9779L /* 103 */,
- 0x2019295B3E109B33L /* 104 */, 0xF8A9478B73A054CCL /* 105 */,
- 0x2924F2F934417EB0L /* 106 */, 0x3993357D536D1BC4L /* 107 */,
- 0x38A81AC21DB6FF8BL /* 108 */, 0x47C4FBF17D6016BFL /* 109 */,
- 0x1E0FAADD7667E3F5L /* 110 */, 0x7ABCFF62938BEB96L /* 111 */,
- 0xA78DAD948FC179C9L /* 112 */, 0x8F1F98B72911E50DL /* 113 */,
- 0x61E48EAE27121A91L /* 114 */, 0x4D62F7AD31859808L /* 115 */,
- 0xECEBA345EF5CEAEBL /* 116 */, 0xF5CEB25EBC9684CEL /* 117 */,
- 0xF633E20CB7F76221L /* 118 */, 0xA32CDF06AB8293E4L /* 119 */,
- 0x985A202CA5EE2CA4L /* 120 */, 0xCF0B8447CC8A8FB1L /* 121 */,
- 0x9F765244979859A3L /* 122 */, 0xA8D516B1A1240017L /* 123 */,
- 0x0BD7BA3EBB5DC726L /* 124 */, 0xE54BCA55B86ADB39L /* 125 */,
- 0x1D7A3AFD6C478063L /* 126 */, 0x519EC608E7669EDDL /* 127 */,
- 0x0E5715A2D149AA23L /* 128 */, 0x177D4571848FF194L /* 129 */,
- 0xEEB55F3241014C22L /* 130 */, 0x0F5E5CA13A6E2EC2L /* 131 */,
- 0x8029927B75F5C361L /* 132 */, 0xAD139FABC3D6E436L /* 133 */,
- 0x0D5DF1A94CCF402FL /* 134 */, 0x3E8BD948BEA5DFC8L /* 135 */,
- 0xA5A0D357BD3FF77EL /* 136 */, 0xA2D12E251F74F645L /* 137 */,
- 0x66FD9E525E81A082L /* 138 */, 0x2E0C90CE7F687A49L /* 139 */,
- 0xC2E8BCBEBA973BC5L /* 140 */, 0x000001BCE509745FL /* 141 */,
- 0x423777BBE6DAB3D6L /* 142 */, 0xD1661C7EAEF06EB5L /* 143 */,
- 0xA1781F354DAACFD8L /* 144 */, 0x2D11284A2B16AFFCL /* 145 */,
- 0xF1FC4F67FA891D1FL /* 146 */, 0x73ECC25DCB920ADAL /* 147 */,
- 0xAE610C22C2A12651L /* 148 */, 0x96E0A810D356B78AL /* 149 */,
- 0x5A9A381F2FE7870FL /* 150 */, 0xD5AD62EDE94E5530L /* 151 */,
- 0xD225E5E8368D1427L /* 152 */, 0x65977B70C7AF4631L /* 153 */,
- 0x99F889B2DE39D74FL /* 154 */, 0x233F30BF54E1D143L /* 155 */,
- 0x9A9675D3D9A63C97L /* 156 */, 0x5470554FF334F9A8L /* 157 */,
- 0x166ACB744A4F5688L /* 158 */, 0x70C74CAAB2E4AEADL /* 159 */,
- 0xF0D091646F294D12L /* 160 */, 0x57B82A89684031D1L /* 161 */,
- 0xEFD95A5A61BE0B6BL /* 162 */, 0x2FBD12E969F2F29AL /* 163 */,
- 0x9BD37013FEFF9FE8L /* 164 */, 0x3F9B0404D6085A06L /* 165 */,
- 0x4940C1F3166CFE15L /* 166 */, 0x09542C4DCDF3DEFBL /* 167 */,
- 0xB4C5218385CD5CE3L /* 168 */, 0xC935B7DC4462A641L /* 169 */,
- 0x3417F8A68ED3B63FL /* 170 */, 0xB80959295B215B40L /* 171 */,
- 0xF99CDAEF3B8C8572L /* 172 */, 0x018C0614F8FCB95DL /* 173 */,
- 0x1B14ACCD1A3ACDF3L /* 174 */, 0x84D471F200BB732DL /* 175 */,
- 0xC1A3110E95E8DA16L /* 176 */, 0x430A7220BF1A82B8L /* 177 */,
- 0xB77E090D39DF210EL /* 178 */, 0x5EF4BD9F3CD05E9DL /* 179 */,
- 0x9D4FF6DA7E57A444L /* 180 */, 0xDA1D60E183D4A5F8L /* 181 */,
- 0xB287C38417998E47L /* 182 */, 0xFE3EDC121BB31886L /* 183 */,
- 0xC7FE3CCC980CCBEFL /* 184 */, 0xE46FB590189BFD03L /* 185 */,
- 0x3732FD469A4C57DCL /* 186 */, 0x7EF700A07CF1AD65L /* 187 */,
- 0x59C64468A31D8859L /* 188 */, 0x762FB0B4D45B61F6L /* 189 */,
- 0x155BAED099047718L /* 190 */, 0x68755E4C3D50BAA6L /* 191 */,
- 0xE9214E7F22D8B4DFL /* 192 */, 0x2ADDBF532EAC95F4L /* 193 */,
- 0x32AE3909B4BD0109L /* 194 */, 0x834DF537B08E3450L /* 195 */,
- 0xFA209DA84220728DL /* 196 */, 0x9E691D9B9EFE23F7L /* 197 */,
- 0x0446D288C4AE8D7FL /* 198 */, 0x7B4CC524E169785BL /* 199 */,
- 0x21D87F0135CA1385L /* 200 */, 0xCEBB400F137B8AA5L /* 201 */,
- 0x272E2B66580796BEL /* 202 */, 0x3612264125C2B0DEL /* 203 */,
- 0x057702BDAD1EFBB2L /* 204 */, 0xD4BABB8EACF84BE9L /* 205 */,
- 0x91583139641BC67BL /* 206 */, 0x8BDC2DE08036E024L /* 207 */,
- 0x603C8156F49F68EDL /* 208 */, 0xF7D236F7DBEF5111L /* 209 */,
- 0x9727C4598AD21E80L /* 210 */, 0xA08A0896670A5FD7L /* 211 */,
- 0xCB4A8F4309EBA9CBL /* 212 */, 0x81AF564B0F7036A1L /* 213 */,
- 0xC0B99AA778199ABDL /* 214 */, 0x959F1EC83FC8E952L /* 215 */,
- 0x8C505077794A81B9L /* 216 */, 0x3ACAAF8F056338F0L /* 217 */,
- 0x07B43F50627A6778L /* 218 */, 0x4A44AB49F5ECCC77L /* 219 */,
- 0x3BC3D6E4B679EE98L /* 220 */, 0x9CC0D4D1CF14108CL /* 221 */,
- 0x4406C00B206BC8A0L /* 222 */, 0x82A18854C8D72D89L /* 223 */,
- 0x67E366B35C3C432CL /* 224 */, 0xB923DD61102B37F2L /* 225 */,
- 0x56AB2779D884271DL /* 226 */, 0xBE83E1B0FF1525AFL /* 227 */,
- 0xFB7C65D4217E49A9L /* 228 */, 0x6BDBE0E76D48E7D4L /* 229 */,
- 0x08DF828745D9179EL /* 230 */, 0x22EA6A9ADD53BD34L /* 231 */,
- 0xE36E141C5622200AL /* 232 */, 0x7F805D1B8CB750EEL /* 233 */,
- 0xAFE5C7A59F58E837L /* 234 */, 0xE27F996A4FB1C23CL /* 235 */,
- 0xD3867DFB0775F0D0L /* 236 */, 0xD0E673DE6E88891AL /* 237 */,
- 0x123AEB9EAFB86C25L /* 238 */, 0x30F1D5D5C145B895L /* 239 */,
- 0xBB434A2DEE7269E7L /* 240 */, 0x78CB67ECF931FA38L /* 241 */,
- 0xF33B0372323BBF9CL /* 242 */, 0x52D66336FB279C74L /* 243 */,
- 0x505F33AC0AFB4EAAL /* 244 */, 0xE8A5CD99A2CCE187L /* 245 */,
- 0x534974801E2D30BBL /* 246 */, 0x8D2D5711D5876D90L /* 247 */,
- 0x1F1A412891BC038EL /* 248 */, 0xD6E2E71D82E56648L /* 249 */,
- 0x74036C3A497732B7L /* 250 */, 0x89B67ED96361F5ABL /* 251 */,
- 0xFFED95D8F1EA02A2L /* 252 */, 0xE72B3BD61464D43DL /* 253 */,
- 0xA6300F170BDC4820L /* 254 */, 0xEBC18760ED78A77AL /* 255 */,
- };
-
- private static final long[] t2 = {
- 0xE6A6BE5A05A12138L /* 256 */, 0xB5A122A5B4F87C98L /* 257 */,
- 0x563C6089140B6990L /* 258 */, 0x4C46CB2E391F5DD5L /* 259 */,
- 0xD932ADDBC9B79434L /* 260 */, 0x08EA70E42015AFF5L /* 261 */,
- 0xD765A6673E478CF1L /* 262 */, 0xC4FB757EAB278D99L /* 263 */,
- 0xDF11C6862D6E0692L /* 264 */, 0xDDEB84F10D7F3B16L /* 265 */,
- 0x6F2EF604A665EA04L /* 266 */, 0x4A8E0F0FF0E0DFB3L /* 267 */,
- 0xA5EDEEF83DBCBA51L /* 268 */, 0xFC4F0A2A0EA4371EL /* 269 */,
- 0xE83E1DA85CB38429L /* 270 */, 0xDC8FF882BA1B1CE2L /* 271 */,
- 0xCD45505E8353E80DL /* 272 */, 0x18D19A00D4DB0717L /* 273 */,
- 0x34A0CFEDA5F38101L /* 274 */, 0x0BE77E518887CAF2L /* 275 */,
- 0x1E341438B3C45136L /* 276 */, 0xE05797F49089CCF9L /* 277 */,
- 0xFFD23F9DF2591D14L /* 278 */, 0x543DDA228595C5CDL /* 279 */,
- 0x661F81FD99052A33L /* 280 */, 0x8736E641DB0F7B76L /* 281 */,
- 0x15227725418E5307L /* 282 */, 0xE25F7F46162EB2FAL /* 283 */,
- 0x48A8B2126C13D9FEL /* 284 */, 0xAFDC541792E76EEAL /* 285 */,
- 0x03D912BFC6D1898FL /* 286 */, 0x31B1AAFA1B83F51BL /* 287 */,
- 0xF1AC2796E42AB7D9L /* 288 */, 0x40A3A7D7FCD2EBACL /* 289 */,
- 0x1056136D0AFBBCC5L /* 290 */, 0x7889E1DD9A6D0C85L /* 291 */,
- 0xD33525782A7974AAL /* 292 */, 0xA7E25D09078AC09BL /* 293 */,
- 0xBD4138B3EAC6EDD0L /* 294 */, 0x920ABFBE71EB9E70L /* 295 */,
- 0xA2A5D0F54FC2625CL /* 296 */, 0xC054E36B0B1290A3L /* 297 */,
- 0xF6DD59FF62FE932BL /* 298 */, 0x3537354511A8AC7DL /* 299 */,
- 0xCA845E9172FADCD4L /* 300 */, 0x84F82B60329D20DCL /* 301 */,
- 0x79C62CE1CD672F18L /* 302 */, 0x8B09A2ADD124642CL /* 303 */,
- 0xD0C1E96A19D9E726L /* 304 */, 0x5A786A9B4BA9500CL /* 305 */,
- 0x0E020336634C43F3L /* 306 */, 0xC17B474AEB66D822L /* 307 */,
- 0x6A731AE3EC9BAAC2L /* 308 */, 0x8226667AE0840258L /* 309 */,
- 0x67D4567691CAECA5L /* 310 */, 0x1D94155C4875ADB5L /* 311 */,
- 0x6D00FD985B813FDFL /* 312 */, 0x51286EFCB774CD06L /* 313 */,
- 0x5E8834471FA744AFL /* 314 */, 0xF72CA0AEE761AE2EL /* 315 */,
- 0xBE40E4CDAEE8E09AL /* 316 */, 0xE9970BBB5118F665L /* 317 */,
- 0x726E4BEB33DF1964L /* 318 */, 0x703B000729199762L /* 319 */,
- 0x4631D816F5EF30A7L /* 320 */, 0xB880B5B51504A6BEL /* 321 */,
- 0x641793C37ED84B6CL /* 322 */, 0x7B21ED77F6E97D96L /* 323 */,
- 0x776306312EF96B73L /* 324 */, 0xAE528948E86FF3F4L /* 325 */,
- 0x53DBD7F286A3F8F8L /* 326 */, 0x16CADCE74CFC1063L /* 327 */,
- 0x005C19BDFA52C6DDL /* 328 */, 0x68868F5D64D46AD3L /* 329 */,
- 0x3A9D512CCF1E186AL /* 330 */, 0x367E62C2385660AEL /* 331 */,
- 0xE359E7EA77DCB1D7L /* 332 */, 0x526C0773749ABE6EL /* 333 */,
- 0x735AE5F9D09F734BL /* 334 */, 0x493FC7CC8A558BA8L /* 335 */,
- 0xB0B9C1533041AB45L /* 336 */, 0x321958BA470A59BDL /* 337 */,
- 0x852DB00B5F46C393L /* 338 */, 0x91209B2BD336B0E5L /* 339 */,
- 0x6E604F7D659EF19FL /* 340 */, 0xB99A8AE2782CCB24L /* 341 */,
- 0xCCF52AB6C814C4C7L /* 342 */, 0x4727D9AFBE11727BL /* 343 */,
- 0x7E950D0C0121B34DL /* 344 */, 0x756F435670AD471FL /* 345 */,
- 0xF5ADD442615A6849L /* 346 */, 0x4E87E09980B9957AL /* 347 */,
- 0x2ACFA1DF50AEE355L /* 348 */, 0xD898263AFD2FD556L /* 349 */,
- 0xC8F4924DD80C8FD6L /* 350 */, 0xCF99CA3D754A173AL /* 351 */,
- 0xFE477BACAF91BF3CL /* 352 */, 0xED5371F6D690C12DL /* 353 */,
- 0x831A5C285E687094L /* 354 */, 0xC5D3C90A3708A0A4L /* 355 */,
- 0x0F7F903717D06580L /* 356 */, 0x19F9BB13B8FDF27FL /* 357 */,
- 0xB1BD6F1B4D502843L /* 358 */, 0x1C761BA38FFF4012L /* 359 */,
- 0x0D1530C4E2E21F3BL /* 360 */, 0x8943CE69A7372C8AL /* 361 */,
- 0xE5184E11FEB5CE66L /* 362 */, 0x618BDB80BD736621L /* 363 */,
- 0x7D29BAD68B574D0BL /* 364 */, 0x81BB613E25E6FE5BL /* 365 */,
- 0x071C9C10BC07913FL /* 366 */, 0xC7BEEB7909AC2D97L /* 367 */,
- 0xC3E58D353BC5D757L /* 368 */, 0xEB017892F38F61E8L /* 369 */,
- 0xD4EFFB9C9B1CC21AL /* 370 */, 0x99727D26F494F7ABL /* 371 */,
- 0xA3E063A2956B3E03L /* 372 */, 0x9D4A8B9A4AA09C30L /* 373 */,
- 0x3F6AB7D500090FB4L /* 374 */, 0x9CC0F2A057268AC0L /* 375 */,
- 0x3DEE9D2DEDBF42D1L /* 376 */, 0x330F49C87960A972L /* 377 */,
- 0xC6B2720287421B41L /* 378 */, 0x0AC59EC07C00369CL /* 379 */,
- 0xEF4EAC49CB353425L /* 380 */, 0xF450244EEF0129D8L /* 381 */,
- 0x8ACC46E5CAF4DEB6L /* 382 */, 0x2FFEAB63989263F7L /* 383 */,
- 0x8F7CB9FE5D7A4578L /* 384 */, 0x5BD8F7644E634635L /* 385 */,
- 0x427A7315BF2DC900L /* 386 */, 0x17D0C4AA2125261CL /* 387 */,
- 0x3992486C93518E50L /* 388 */, 0xB4CBFEE0A2D7D4C3L /* 389 */,
- 0x7C75D6202C5DDD8DL /* 390 */, 0xDBC295D8E35B6C61L /* 391 */,
- 0x60B369D302032B19L /* 392 */, 0xCE42685FDCE44132L /* 393 */,
- 0x06F3DDB9DDF65610L /* 394 */, 0x8EA4D21DB5E148F0L /* 395 */,
- 0x20B0FCE62FCD496FL /* 396 */, 0x2C1B912358B0EE31L /* 397 */,
- 0xB28317B818F5A308L /* 398 */, 0xA89C1E189CA6D2CFL /* 399 */,
- 0x0C6B18576AAADBC8L /* 400 */, 0xB65DEAA91299FAE3L /* 401 */,
- 0xFB2B794B7F1027E7L /* 402 */, 0x04E4317F443B5BEBL /* 403 */,
- 0x4B852D325939D0A6L /* 404 */, 0xD5AE6BEEFB207FFCL /* 405 */,
- 0x309682B281C7D374L /* 406 */, 0xBAE309A194C3B475L /* 407 */,
- 0x8CC3F97B13B49F05L /* 408 */, 0x98A9422FF8293967L /* 409 */,
- 0x244B16B01076FF7CL /* 410 */, 0xF8BF571C663D67EEL /* 411 */,
- 0x1F0D6758EEE30DA1L /* 412 */, 0xC9B611D97ADEB9B7L /* 413 */,
- 0xB7AFD5887B6C57A2L /* 414 */, 0x6290AE846B984FE1L /* 415 */,
- 0x94DF4CDEACC1A5FDL /* 416 */, 0x058A5BD1C5483AFFL /* 417 */,
- 0x63166CC142BA3C37L /* 418 */, 0x8DB8526EB2F76F40L /* 419 */,
- 0xE10880036F0D6D4EL /* 420 */, 0x9E0523C9971D311DL /* 421 */,
- 0x45EC2824CC7CD691L /* 422 */, 0x575B8359E62382C9L /* 423 */,
- 0xFA9E400DC4889995L /* 424 */, 0xD1823ECB45721568L /* 425 */,
- 0xDAFD983B8206082FL /* 426 */, 0xAA7D29082386A8CBL /* 427 */,
- 0x269FCD4403B87588L /* 428 */, 0x1B91F5F728BDD1E0L /* 429 */,
- 0xE4669F39040201F6L /* 430 */, 0x7A1D7C218CF04ADEL /* 431 */,
- 0x65623C29D79CE5CEL /* 432 */, 0x2368449096C00BB1L /* 433 */,
- 0xAB9BF1879DA503BAL /* 434 */, 0xBC23ECB1A458058EL /* 435 */,
- 0x9A58DF01BB401ECCL /* 436 */, 0xA070E868A85F143DL /* 437 */,
- 0x4FF188307DF2239EL /* 438 */, 0x14D565B41A641183L /* 439 */,
- 0xEE13337452701602L /* 440 */, 0x950E3DCF3F285E09L /* 441 */,
- 0x59930254B9C80953L /* 442 */, 0x3BF299408930DA6DL /* 443 */,
- 0xA955943F53691387L /* 444 */, 0xA15EDECAA9CB8784L /* 445 */,
- 0x29142127352BE9A0L /* 446 */, 0x76F0371FFF4E7AFBL /* 447 */,
- 0x0239F450274F2228L /* 448 */, 0xBB073AF01D5E868BL /* 449 */,
- 0xBFC80571C10E96C1L /* 450 */, 0xD267088568222E23L /* 451 */,
- 0x9671A3D48E80B5B0L /* 452 */, 0x55B5D38AE193BB81L /* 453 */,
- 0x693AE2D0A18B04B8L /* 454 */, 0x5C48B4ECADD5335FL /* 455 */,
- 0xFD743B194916A1CAL /* 456 */, 0x2577018134BE98C4L /* 457 */,
- 0xE77987E83C54A4ADL /* 458 */, 0x28E11014DA33E1B9L /* 459 */,
- 0x270CC59E226AA213L /* 460 */, 0x71495F756D1A5F60L /* 461 */,
- 0x9BE853FB60AFEF77L /* 462 */, 0xADC786A7F7443DBFL /* 463 */,
- 0x0904456173B29A82L /* 464 */, 0x58BC7A66C232BD5EL /* 465 */,
- 0xF306558C673AC8B2L /* 466 */, 0x41F639C6B6C9772AL /* 467 */,
- 0x216DEFE99FDA35DAL /* 468 */, 0x11640CC71C7BE615L /* 469 */,
- 0x93C43694565C5527L /* 470 */, 0xEA038E6246777839L /* 471 */,
- 0xF9ABF3CE5A3E2469L /* 472 */, 0x741E768D0FD312D2L /* 473 */,
- 0x0144B883CED652C6L /* 474 */, 0xC20B5A5BA33F8552L /* 475 */,
- 0x1AE69633C3435A9DL /* 476 */, 0x97A28CA4088CFDECL /* 477 */,
- 0x8824A43C1E96F420L /* 478 */, 0x37612FA66EEEA746L /* 479 */,
- 0x6B4CB165F9CF0E5AL /* 480 */, 0x43AA1C06A0ABFB4AL /* 481 */,
- 0x7F4DC26FF162796BL /* 482 */, 0x6CBACC8E54ED9B0FL /* 483 */,
- 0xA6B7FFEFD2BB253EL /* 484 */, 0x2E25BC95B0A29D4FL /* 485 */,
- 0x86D6A58BDEF1388CL /* 486 */, 0xDED74AC576B6F054L /* 487 */,
- 0x8030BDBC2B45805DL /* 488 */, 0x3C81AF70E94D9289L /* 489 */,
- 0x3EFF6DDA9E3100DBL /* 490 */, 0xB38DC39FDFCC8847L /* 491 */,
- 0x123885528D17B87EL /* 492 */, 0xF2DA0ED240B1B642L /* 493 */,
- 0x44CEFADCD54BF9A9L /* 494 */, 0x1312200E433C7EE6L /* 495 */,
- 0x9FFCC84F3A78C748L /* 496 */, 0xF0CD1F72248576BBL /* 497 */,
- 0xEC6974053638CFE4L /* 498 */, 0x2BA7B67C0CEC4E4CL /* 499 */,
- 0xAC2F4DF3E5CE32EDL /* 500 */, 0xCB33D14326EA4C11L /* 501 */,
- 0xA4E9044CC77E58BCL /* 502 */, 0x5F513293D934FCEFL /* 503 */,
- 0x5DC9645506E55444L /* 504 */, 0x50DE418F317DE40AL /* 505 */,
- 0x388CB31A69DDE259L /* 506 */, 0x2DB4A83455820A86L /* 507 */,
- 0x9010A91E84711AE9L /* 508 */, 0x4DF7F0B7B1498371L /* 509 */,
- 0xD62A2EABC0977179L /* 510 */, 0x22FAC097AA8D5C0EL /* 511 */,
- };
-
- private static final long[] t3 = {
- 0xF49FCC2FF1DAF39BL /* 512 */, 0x487FD5C66FF29281L /* 513 */,
- 0xE8A30667FCDCA83FL /* 514 */, 0x2C9B4BE3D2FCCE63L /* 515 */,
- 0xDA3FF74B93FBBBC2L /* 516 */, 0x2FA165D2FE70BA66L /* 517 */,
- 0xA103E279970E93D4L /* 518 */, 0xBECDEC77B0E45E71L /* 519 */,
- 0xCFB41E723985E497L /* 520 */, 0xB70AAA025EF75017L /* 521 */,
- 0xD42309F03840B8E0L /* 522 */, 0x8EFC1AD035898579L /* 523 */,
- 0x96C6920BE2B2ABC5L /* 524 */, 0x66AF4163375A9172L /* 525 */,
- 0x2174ABDCCA7127FBL /* 526 */, 0xB33CCEA64A72FF41L /* 527 */,
- 0xF04A4933083066A5L /* 528 */, 0x8D970ACDD7289AF5L /* 529 */,
- 0x8F96E8E031C8C25EL /* 530 */, 0xF3FEC02276875D47L /* 531 */,
- 0xEC7BF310056190DDL /* 532 */, 0xF5ADB0AEBB0F1491L /* 533 */,
- 0x9B50F8850FD58892L /* 534 */, 0x4975488358B74DE8L /* 535 */,
- 0xA3354FF691531C61L /* 536 */, 0x0702BBE481D2C6EEL /* 537 */,
- 0x89FB24057DEDED98L /* 538 */, 0xAC3075138596E902L /* 539 */,
- 0x1D2D3580172772EDL /* 540 */, 0xEB738FC28E6BC30DL /* 541 */,
- 0x5854EF8F63044326L /* 542 */, 0x9E5C52325ADD3BBEL /* 543 */,
- 0x90AA53CF325C4623L /* 544 */, 0xC1D24D51349DD067L /* 545 */,
- 0x2051CFEEA69EA624L /* 546 */, 0x13220F0A862E7E4FL /* 547 */,
- 0xCE39399404E04864L /* 548 */, 0xD9C42CA47086FCB7L /* 549 */,
- 0x685AD2238A03E7CCL /* 550 */, 0x066484B2AB2FF1DBL /* 551 */,
- 0xFE9D5D70EFBF79ECL /* 552 */, 0x5B13B9DD9C481854L /* 553 */,
- 0x15F0D475ED1509ADL /* 554 */, 0x0BEBCD060EC79851L /* 555 */,
- 0xD58C6791183AB7F8L /* 556 */, 0xD1187C5052F3EEE4L /* 557 */,
- 0xC95D1192E54E82FFL /* 558 */, 0x86EEA14CB9AC6CA2L /* 559 */,
- 0x3485BEB153677D5DL /* 560 */, 0xDD191D781F8C492AL /* 561 */,
- 0xF60866BAA784EBF9L /* 562 */, 0x518F643BA2D08C74L /* 563 */,
- 0x8852E956E1087C22L /* 564 */, 0xA768CB8DC410AE8DL /* 565 */,
- 0x38047726BFEC8E1AL /* 566 */, 0xA67738B4CD3B45AAL /* 567 */,
- 0xAD16691CEC0DDE19L /* 568 */, 0xC6D4319380462E07L /* 569 */,
- 0xC5A5876D0BA61938L /* 570 */, 0x16B9FA1FA58FD840L /* 571 */,
- 0x188AB1173CA74F18L /* 572 */, 0xABDA2F98C99C021FL /* 573 */,
- 0x3E0580AB134AE816L /* 574 */, 0x5F3B05B773645ABBL /* 575 */,
- 0x2501A2BE5575F2F6L /* 576 */, 0x1B2F74004E7E8BA9L /* 577 */,
- 0x1CD7580371E8D953L /* 578 */, 0x7F6ED89562764E30L /* 579 */,
- 0xB15926FF596F003DL /* 580 */, 0x9F65293DA8C5D6B9L /* 581 */,
- 0x6ECEF04DD690F84CL /* 582 */, 0x4782275FFF33AF88L /* 583 */,
- 0xE41433083F820801L /* 584 */, 0xFD0DFE409A1AF9B5L /* 585 */,
- 0x4325A3342CDB396BL /* 586 */, 0x8AE77E62B301B252L /* 587 */,
- 0xC36F9E9F6655615AL /* 588 */, 0x85455A2D92D32C09L /* 589 */,
- 0xF2C7DEA949477485L /* 590 */, 0x63CFB4C133A39EBAL /* 591 */,
- 0x83B040CC6EBC5462L /* 592 */, 0x3B9454C8FDB326B0L /* 593 */,
- 0x56F56A9E87FFD78CL /* 594 */, 0x2DC2940D99F42BC6L /* 595 */,
- 0x98F7DF096B096E2DL /* 596 */, 0x19A6E01E3AD852BFL /* 597 */,
- 0x42A99CCBDBD4B40BL /* 598 */, 0xA59998AF45E9C559L /* 599 */,
- 0x366295E807D93186L /* 600 */, 0x6B48181BFAA1F773L /* 601 */,
- 0x1FEC57E2157A0A1DL /* 602 */, 0x4667446AF6201AD5L /* 603 */,
- 0xE615EBCACFB0F075L /* 604 */, 0xB8F31F4F68290778L /* 605 */,
- 0x22713ED6CE22D11EL /* 606 */, 0x3057C1A72EC3C93BL /* 607 */,
- 0xCB46ACC37C3F1F2FL /* 608 */, 0xDBB893FD02AAF50EL /* 609 */,
- 0x331FD92E600B9FCFL /* 610 */, 0xA498F96148EA3AD6L /* 611 */,
- 0xA8D8426E8B6A83EAL /* 612 */, 0xA089B274B7735CDCL /* 613 */,
- 0x87F6B3731E524A11L /* 614 */, 0x118808E5CBC96749L /* 615 */,
- 0x9906E4C7B19BD394L /* 616 */, 0xAFED7F7E9B24A20CL /* 617 */,
- 0x6509EADEEB3644A7L /* 618 */, 0x6C1EF1D3E8EF0EDEL /* 619 */,
- 0xB9C97D43E9798FB4L /* 620 */, 0xA2F2D784740C28A3L /* 621 */,
- 0x7B8496476197566FL /* 622 */, 0x7A5BE3E6B65F069DL /* 623 */,
- 0xF96330ED78BE6F10L /* 624 */, 0xEEE60DE77A076A15L /* 625 */,
- 0x2B4BEE4AA08B9BD0L /* 626 */, 0x6A56A63EC7B8894EL /* 627 */,
- 0x02121359BA34FEF4L /* 628 */, 0x4CBF99F8283703FCL /* 629 */,
- 0x398071350CAF30C8L /* 630 */, 0xD0A77A89F017687AL /* 631 */,
- 0xF1C1A9EB9E423569L /* 632 */, 0x8C7976282DEE8199L /* 633 */,
- 0x5D1737A5DD1F7ABDL /* 634 */, 0x4F53433C09A9FA80L /* 635 */,
- 0xFA8B0C53DF7CA1D9L /* 636 */, 0x3FD9DCBC886CCB77L /* 637 */,
- 0xC040917CA91B4720L /* 638 */, 0x7DD00142F9D1DCDFL /* 639 */,
- 0x8476FC1D4F387B58L /* 640 */, 0x23F8E7C5F3316503L /* 641 */,
- 0x032A2244E7E37339L /* 642 */, 0x5C87A5D750F5A74BL /* 643 */,
- 0x082B4CC43698992EL /* 644 */, 0xDF917BECB858F63CL /* 645 */,
- 0x3270B8FC5BF86DDAL /* 646 */, 0x10AE72BB29B5DD76L /* 647 */,
- 0x576AC94E7700362BL /* 648 */, 0x1AD112DAC61EFB8FL /* 649 */,
- 0x691BC30EC5FAA427L /* 650 */, 0xFF246311CC327143L /* 651 */,
- 0x3142368E30E53206L /* 652 */, 0x71380E31E02CA396L /* 653 */,
- 0x958D5C960AAD76F1L /* 654 */, 0xF8D6F430C16DA536L /* 655 */,
- 0xC8FFD13F1BE7E1D2L /* 656 */, 0x7578AE66004DDBE1L /* 657 */,
- 0x05833F01067BE646L /* 658 */, 0xBB34B5AD3BFE586DL /* 659 */,
- 0x095F34C9A12B97F0L /* 660 */, 0x247AB64525D60CA8L /* 661 */,
- 0xDCDBC6F3017477D1L /* 662 */, 0x4A2E14D4DECAD24DL /* 663 */,
- 0xBDB5E6D9BE0A1EEBL /* 664 */, 0x2A7E70F7794301ABL /* 665 */,
- 0xDEF42D8A270540FDL /* 666 */, 0x01078EC0A34C22C1L /* 667 */,
- 0xE5DE511AF4C16387L /* 668 */, 0x7EBB3A52BD9A330AL /* 669 */,
- 0x77697857AA7D6435L /* 670 */, 0x004E831603AE4C32L /* 671 */,
- 0xE7A21020AD78E312L /* 672 */, 0x9D41A70C6AB420F2L /* 673 */,
- 0x28E06C18EA1141E6L /* 674 */, 0xD2B28CBD984F6B28L /* 675 */,
- 0x26B75F6C446E9D83L /* 676 */, 0xBA47568C4D418D7FL /* 677 */,
- 0xD80BADBFE6183D8EL /* 678 */, 0x0E206D7F5F166044L /* 679 */,
- 0xE258A43911CBCA3EL /* 680 */, 0x723A1746B21DC0BCL /* 681 */,
- 0xC7CAA854F5D7CDD3L /* 682 */, 0x7CAC32883D261D9CL /* 683 */,
- 0x7690C26423BA942CL /* 684 */, 0x17E55524478042B8L /* 685 */,
- 0xE0BE477656A2389FL /* 686 */, 0x4D289B5E67AB2DA0L /* 687 */,
- 0x44862B9C8FBBFD31L /* 688 */, 0xB47CC8049D141365L /* 689 */,
- 0x822C1B362B91C793L /* 690 */, 0x4EB14655FB13DFD8L /* 691 */,
- 0x1ECBBA0714E2A97BL /* 692 */, 0x6143459D5CDE5F14L /* 693 */,
- 0x53A8FBF1D5F0AC89L /* 694 */, 0x97EA04D81C5E5B00L /* 695 */,
- 0x622181A8D4FDB3F3L /* 696 */, 0xE9BCD341572A1208L /* 697 */,
- 0x1411258643CCE58AL /* 698 */, 0x9144C5FEA4C6E0A4L /* 699 */,
- 0x0D33D06565CF620FL /* 700 */, 0x54A48D489F219CA1L /* 701 */,
- 0xC43E5EAC6D63C821L /* 702 */, 0xA9728B3A72770DAFL /* 703 */,
- 0xD7934E7B20DF87EFL /* 704 */, 0xE35503B61A3E86E5L /* 705 */,
- 0xCAE321FBC819D504L /* 706 */, 0x129A50B3AC60BFA6L /* 707 */,
- 0xCD5E68EA7E9FB6C3L /* 708 */, 0xB01C90199483B1C7L /* 709 */,
- 0x3DE93CD5C295376CL /* 710 */, 0xAED52EDF2AB9AD13L /* 711 */,
- 0x2E60F512C0A07884L /* 712 */, 0xBC3D86A3E36210C9L /* 713 */,
- 0x35269D9B163951CEL /* 714 */, 0x0C7D6E2AD0CDB5FAL /* 715 */,
- 0x59E86297D87F5733L /* 716 */, 0x298EF221898DB0E7L /* 717 */,
- 0x55000029D1A5AA7EL /* 718 */, 0x8BC08AE1B5061B45L /* 719 */,
- 0xC2C31C2B6C92703AL /* 720 */, 0x94CC596BAF25EF42L /* 721 */,
- 0x0A1D73DB22540456L /* 722 */, 0x04B6A0F9D9C4179AL /* 723 */,
- 0xEFFDAFA2AE3D3C60L /* 724 */, 0xF7C8075BB49496C4L /* 725 */,
- 0x9CC5C7141D1CD4E3L /* 726 */, 0x78BD1638218E5534L /* 727 */,
- 0xB2F11568F850246AL /* 728 */, 0xEDFABCFA9502BC29L /* 729 */,
- 0x796CE5F2DA23051BL /* 730 */, 0xAAE128B0DC93537CL /* 731 */,
- 0x3A493DA0EE4B29AEL /* 732 */, 0xB5DF6B2C416895D7L /* 733 */,
- 0xFCABBD25122D7F37L /* 734 */, 0x70810B58105DC4B1L /* 735 */,
- 0xE10FDD37F7882A90L /* 736 */, 0x524DCAB5518A3F5CL /* 737 */,
- 0x3C9E85878451255BL /* 738 */, 0x4029828119BD34E2L /* 739 */,
- 0x74A05B6F5D3CECCBL /* 740 */, 0xB610021542E13ECAL /* 741 */,
- 0x0FF979D12F59E2ACL /* 742 */, 0x6037DA27E4F9CC50L /* 743 */,
- 0x5E92975A0DF1847DL /* 744 */, 0xD66DE190D3E623FEL /* 745 */,
- 0x5032D6B87B568048L /* 746 */, 0x9A36B7CE8235216EL /* 747 */,
- 0x80272A7A24F64B4AL /* 748 */, 0x93EFED8B8C6916F7L /* 749 */,
- 0x37DDBFF44CCE1555L /* 750 */, 0x4B95DB5D4B99BD25L /* 751 */,
- 0x92D3FDA169812FC0L /* 752 */, 0xFB1A4A9A90660BB6L /* 753 */,
- 0x730C196946A4B9B2L /* 754 */, 0x81E289AA7F49DA68L /* 755 */,
- 0x64669A0F83B1A05FL /* 756 */, 0x27B3FF7D9644F48BL /* 757 */,
- 0xCC6B615C8DB675B3L /* 758 */, 0x674F20B9BCEBBE95L /* 759 */,
- 0x6F31238275655982L /* 760 */, 0x5AE488713E45CF05L /* 761 */,
- 0xBF619F9954C21157L /* 762 */, 0xEABAC46040A8EAE9L /* 763 */,
- 0x454C6FE9F2C0C1CDL /* 764 */, 0x419CF6496412691CL /* 765 */,
- 0xD3DC3BEF265B0F70L /* 766 */, 0x6D0E60F5C3578A9EL /* 767 */,
- };
-
- private static final long[] t4 = {
- 0x5B0E608526323C55L /* 768 */, 0x1A46C1A9FA1B59F5L /* 769 */,
- 0xA9E245A17C4C8FFAL /* 770 */, 0x65CA5159DB2955D7L /* 771 */,
- 0x05DB0A76CE35AFC2L /* 772 */, 0x81EAC77EA9113D45L /* 773 */,
- 0x528EF88AB6AC0A0DL /* 774 */, 0xA09EA253597BE3FFL /* 775 */,
- 0x430DDFB3AC48CD56L /* 776 */, 0xC4B3A67AF45CE46FL /* 777 */,
- 0x4ECECFD8FBE2D05EL /* 778 */, 0x3EF56F10B39935F0L /* 779 */,
- 0x0B22D6829CD619C6L /* 780 */, 0x17FD460A74DF2069L /* 781 */,
- 0x6CF8CC8E8510ED40L /* 782 */, 0xD6C824BF3A6ECAA7L /* 783 */,
- 0x61243D581A817049L /* 784 */, 0x048BACB6BBC163A2L /* 785 */,
- 0xD9A38AC27D44CC32L /* 786 */, 0x7FDDFF5BAAF410ABL /* 787 */,
- 0xAD6D495AA804824BL /* 788 */, 0xE1A6A74F2D8C9F94L /* 789 */,
- 0xD4F7851235DEE8E3L /* 790 */, 0xFD4B7F886540D893L /* 791 */,
- 0x247C20042AA4BFDAL /* 792 */, 0x096EA1C517D1327CL /* 793 */,
- 0xD56966B4361A6685L /* 794 */, 0x277DA5C31221057DL /* 795 */,
- 0x94D59893A43ACFF7L /* 796 */, 0x64F0C51CCDC02281L /* 797 */,
- 0x3D33BCC4FF6189DBL /* 798 */, 0xE005CB184CE66AF1L /* 799 */,
- 0xFF5CCD1D1DB99BEAL /* 800 */, 0xB0B854A7FE42980FL /* 801 */,
- 0x7BD46A6A718D4B9FL /* 802 */, 0xD10FA8CC22A5FD8CL /* 803 */,
- 0xD31484952BE4BD31L /* 804 */, 0xC7FA975FCB243847L /* 805 */,
- 0x4886ED1E5846C407L /* 806 */, 0x28CDDB791EB70B04L /* 807 */,
- 0xC2B00BE2F573417FL /* 808 */, 0x5C9590452180F877L /* 809 */,
- 0x7A6BDDFFF370EB00L /* 810 */, 0xCE509E38D6D9D6A4L /* 811 */,
- 0xEBEB0F00647FA702L /* 812 */, 0x1DCC06CF76606F06L /* 813 */,
- 0xE4D9F28BA286FF0AL /* 814 */, 0xD85A305DC918C262L /* 815 */,
- 0x475B1D8732225F54L /* 816 */, 0x2D4FB51668CCB5FEL /* 817 */,
- 0xA679B9D9D72BBA20L /* 818 */, 0x53841C0D912D43A5L /* 819 */,
- 0x3B7EAA48BF12A4E8L /* 820 */, 0x781E0E47F22F1DDFL /* 821 */,
- 0xEFF20CE60AB50973L /* 822 */, 0x20D261D19DFFB742L /* 823 */,
- 0x16A12B03062A2E39L /* 824 */, 0x1960EB2239650495L /* 825 */,
- 0x251C16FED50EB8B8L /* 826 */, 0x9AC0C330F826016EL /* 827 */,
- 0xED152665953E7671L /* 828 */, 0x02D63194A6369570L /* 829 */,
- 0x5074F08394B1C987L /* 830 */, 0x70BA598C90B25CE1L /* 831 */,
- 0x794A15810B9742F6L /* 832 */, 0x0D5925E9FCAF8C6CL /* 833 */,
- 0x3067716CD868744EL /* 834 */, 0x910AB077E8D7731BL /* 835 */,
- 0x6A61BBDB5AC42F61L /* 836 */, 0x93513EFBF0851567L /* 837 */,
- 0xF494724B9E83E9D5L /* 838 */, 0xE887E1985C09648DL /* 839 */,
- 0x34B1D3C675370CFDL /* 840 */, 0xDC35E433BC0D255DL /* 841 */,
- 0xD0AAB84234131BE0L /* 842 */, 0x08042A50B48B7EAFL /* 843 */,
- 0x9997C4EE44A3AB35L /* 844 */, 0x829A7B49201799D0L /* 845 */,
- 0x263B8307B7C54441L /* 846 */, 0x752F95F4FD6A6CA6L /* 847 */,
- 0x927217402C08C6E5L /* 848 */, 0x2A8AB754A795D9EEL /* 849 */,
- 0xA442F7552F72943DL /* 850 */, 0x2C31334E19781208L /* 851 */,
- 0x4FA98D7CEAEE6291L /* 852 */, 0x55C3862F665DB309L /* 853 */,
- 0xBD0610175D53B1F3L /* 854 */, 0x46FE6CB840413F27L /* 855 */,
- 0x3FE03792DF0CFA59L /* 856 */, 0xCFE700372EB85E8FL /* 857 */,
- 0xA7BE29E7ADBCE118L /* 858 */, 0xE544EE5CDE8431DDL /* 859 */,
- 0x8A781B1B41F1873EL /* 860 */, 0xA5C94C78A0D2F0E7L /* 861 */,
- 0x39412E2877B60728L /* 862 */, 0xA1265EF3AFC9A62CL /* 863 */,
- 0xBCC2770C6A2506C5L /* 864 */, 0x3AB66DD5DCE1CE12L /* 865 */,
- 0xE65499D04A675B37L /* 866 */, 0x7D8F523481BFD216L /* 867 */,
- 0x0F6F64FCEC15F389L /* 868 */, 0x74EFBE618B5B13C8L /* 869 */,
- 0xACDC82B714273E1DL /* 870 */, 0xDD40BFE003199D17L /* 871 */,
- 0x37E99257E7E061F8L /* 872 */, 0xFA52626904775AAAL /* 873 */,
- 0x8BBBF63A463D56F9L /* 874 */, 0xF0013F1543A26E64L /* 875 */,
- 0xA8307E9F879EC898L /* 876 */, 0xCC4C27A4150177CCL /* 877 */,
- 0x1B432F2CCA1D3348L /* 878 */, 0xDE1D1F8F9F6FA013L /* 879 */,
- 0x606602A047A7DDD6L /* 880 */, 0xD237AB64CC1CB2C7L /* 881 */,
- 0x9B938E7225FCD1D3L /* 882 */, 0xEC4E03708E0FF476L /* 883 */,
- 0xFEB2FBDA3D03C12DL /* 884 */, 0xAE0BCED2EE43889AL /* 885 */,
- 0x22CB8923EBFB4F43L /* 886 */, 0x69360D013CF7396DL /* 887 */,
- 0x855E3602D2D4E022L /* 888 */, 0x073805BAD01F784CL /* 889 */,
- 0x33E17A133852F546L /* 890 */, 0xDF4874058AC7B638L /* 891 */,
- 0xBA92B29C678AA14AL /* 892 */, 0x0CE89FC76CFAADCDL /* 893 */,
- 0x5F9D4E0908339E34L /* 894 */, 0xF1AFE9291F5923B9L /* 895 */,
- 0x6E3480F60F4A265FL /* 896 */, 0xEEBF3A2AB29B841CL /* 897 */,
- 0xE21938A88F91B4ADL /* 898 */, 0x57DFEFF845C6D3C3L /* 899 */,
- 0x2F006B0BF62CAAF2L /* 900 */, 0x62F479EF6F75EE78L /* 901 */,
- 0x11A55AD41C8916A9L /* 902 */, 0xF229D29084FED453L /* 903 */,
- 0x42F1C27B16B000E6L /* 904 */, 0x2B1F76749823C074L /* 905 */,
- 0x4B76ECA3C2745360L /* 906 */, 0x8C98F463B91691BDL /* 907 */,
- 0x14BCC93CF1ADE66AL /* 908 */, 0x8885213E6D458397L /* 909 */,
- 0x8E177DF0274D4711L /* 910 */, 0xB49B73B5503F2951L /* 911 */,
- 0x10168168C3F96B6BL /* 912 */, 0x0E3D963B63CAB0AEL /* 913 */,
- 0x8DFC4B5655A1DB14L /* 914 */, 0xF789F1356E14DE5CL /* 915 */,
- 0x683E68AF4E51DAC1L /* 916 */, 0xC9A84F9D8D4B0FD9L /* 917 */,
- 0x3691E03F52A0F9D1L /* 918 */, 0x5ED86E46E1878E80L /* 919 */,
- 0x3C711A0E99D07150L /* 920 */, 0x5A0865B20C4E9310L /* 921 */,
- 0x56FBFC1FE4F0682EL /* 922 */, 0xEA8D5DE3105EDF9BL /* 923 */,
- 0x71ABFDB12379187AL /* 924 */, 0x2EB99DE1BEE77B9CL /* 925 */,
- 0x21ECC0EA33CF4523L /* 926 */, 0x59A4D7521805C7A1L /* 927 */,
- 0x3896F5EB56AE7C72L /* 928 */, 0xAA638F3DB18F75DCL /* 929 */,
- 0x9F39358DABE9808EL /* 930 */, 0xB7DEFA91C00B72ACL /* 931 */,
- 0x6B5541FD62492D92L /* 932 */, 0x6DC6DEE8F92E4D5BL /* 933 */,
- 0x353F57ABC4BEEA7EL /* 934 */, 0x735769D6DA5690CEL /* 935 */,
- 0x0A234AA642391484L /* 936 */, 0xF6F9508028F80D9DL /* 937 */,
- 0xB8E319A27AB3F215L /* 938 */, 0x31AD9C1151341A4DL /* 939 */,
- 0x773C22A57BEF5805L /* 940 */, 0x45C7561A07968633L /* 941 */,
- 0xF913DA9E249DBE36L /* 942 */, 0xDA652D9B78A64C68L /* 943 */,
- 0x4C27A97F3BC334EFL /* 944 */, 0x76621220E66B17F4L /* 945 */,
- 0x967743899ACD7D0BL /* 946 */, 0xF3EE5BCAE0ED6782L /* 947 */,
- 0x409F753600C879FCL /* 948 */, 0x06D09A39B5926DB6L /* 949 */,
- 0x6F83AEB0317AC588L /* 950 */, 0x01E6CA4A86381F21L /* 951 */,
- 0x66FF3462D19F3025L /* 952 */, 0x72207C24DDFD3BFBL /* 953 */,
- 0x4AF6B6D3E2ECE2EBL /* 954 */, 0x9C994DBEC7EA08DEL /* 955 */,
- 0x49ACE597B09A8BC4L /* 956 */, 0xB38C4766CF0797BAL /* 957 */,
- 0x131B9373C57C2A75L /* 958 */, 0xB1822CCE61931E58L /* 959 */,
- 0x9D7555B909BA1C0CL /* 960 */, 0x127FAFDD937D11D2L /* 961 */,
- 0x29DA3BADC66D92E4L /* 962 */, 0xA2C1D57154C2ECBCL /* 963 */,
- 0x58C5134D82F6FE24L /* 964 */, 0x1C3AE3515B62274FL /* 965 */,
- 0xE907C82E01CB8126L /* 966 */, 0xF8ED091913E37FCBL /* 967 */,
- 0x3249D8F9C80046C9L /* 968 */, 0x80CF9BEDE388FB63L /* 969 */,
- 0x1881539A116CF19EL /* 970 */, 0x5103F3F76BD52457L /* 971 */,
- 0x15B7E6F5AE47F7A8L /* 972 */, 0xDBD7C6DED47E9CCFL /* 973 */,
- 0x44E55C410228BB1AL /* 974 */, 0xB647D4255EDB4E99L /* 975 */,
- 0x5D11882BB8AAFC30L /* 976 */, 0xF5098BBB29D3212AL /* 977 */,
- 0x8FB5EA14E90296B3L /* 978 */, 0x677B942157DD025AL /* 979 */,
- 0xFB58E7C0A390ACB5L /* 980 */, 0x89D3674C83BD4A01L /* 981 */,
- 0x9E2DA4DF4BF3B93BL /* 982 */, 0xFCC41E328CAB4829L /* 983 */,
- 0x03F38C96BA582C52L /* 984 */, 0xCAD1BDBD7FD85DB2L /* 985 */,
- 0xBBB442C16082AE83L /* 986 */, 0xB95FE86BA5DA9AB0L /* 987 */,
- 0xB22E04673771A93FL /* 988 */, 0x845358C9493152D8L /* 989 */,
- 0xBE2A488697B4541EL /* 990 */, 0x95A2DC2DD38E6966L /* 991 */,
- 0xC02C11AC923C852BL /* 992 */, 0x2388B1990DF2A87BL /* 993 */,
- 0x7C8008FA1B4F37BEL /* 994 */, 0x1F70D0C84D54E503L /* 995 */,
- 0x5490ADEC7ECE57D4L /* 996 */, 0x002B3C27D9063A3AL /* 997 */,
- 0x7EAEA3848030A2BFL /* 998 */, 0xC602326DED2003C0L /* 999 */,
- 0x83A7287D69A94086L /* 1000 */, 0xC57A5FCB30F57A8AL /* 1001 */,
- 0xB56844E479EBE779L /* 1002 */, 0xA373B40F05DCBCE9L /* 1003 */,
- 0xD71A786E88570EE2L /* 1004 */, 0x879CBACDBDE8F6A0L /* 1005 */,
- 0x976AD1BCC164A32FL /* 1006 */, 0xAB21E25E9666D78BL /* 1007 */,
- 0x901063AAE5E5C33CL /* 1008 */, 0x9818B34448698D90L /* 1009 */,
- 0xE36487AE3E1E8ABBL /* 1010 */, 0xAFBDF931893BDCB4L /* 1011 */,
- 0x6345A0DC5FBBD519L /* 1012 */, 0x8628FE269B9465CAL /* 1013 */,
- 0x1E5D01603F9C51ECL /* 1014 */, 0x4DE44006A15049B7L /* 1015 */,
- 0xBF6C70E5F776CBB1L /* 1016 */, 0x411218F2EF552BEDL /* 1017 */,
- 0xCB0C0708705A36A3L /* 1018 */, 0xE74D14754F986044L /* 1019 */,
- 0xCD56D9430EA8280EL /* 1020 */, 0xC12591D7535F5065L /* 1021 */,
- 0xC83223F1720AEF96L /* 1022 */, 0xC3A0396F7363A51FL /* 1023 */
- };
-
- private static final int DIGEST_LENGTH = 24;
-
- //
- // registers
- //
- private long a, b, c;
- private long byteCount;
-
- //
- // buffers
- //
- private byte[] buf = new byte[8];
- private int bOff = 0;
-
- private long[] x = new long[8];
- private int xOff = 0;
-
- /**
- * Standard constructor
- */
- public TigerDigest()
- {
- reset();
- }
-
- /**
- * Copy constructor. This will copy the state of the provided
- * message digest.
- */
- public TigerDigest(TigerDigest t)
- {
- this.reset(t);
- }
-
- public String getAlgorithmName()
- {
- return "Tiger";
- }
-
- public int getDigestSize()
- {
- return DIGEST_LENGTH;
- }
-
- private void processWord(
- byte[] b,
- int off)
- {
- x[xOff++] = ((long)(b[off + 7] & 0xff) << 56)
- | ((long)(b[off + 6] & 0xff) << 48)
- | ((long)(b[off + 5] & 0xff) << 40)
- | ((long)(b[off + 4] & 0xff) << 32)
- | ((long)(b[off + 3] & 0xff) << 24)
- | ((long)(b[off + 2] & 0xff) << 16)
- | ((long)(b[off + 1] & 0xff) << 8)
- | ((b[off + 0] & 0xff));
-
- if (xOff == x.length)
- {
- processBlock();
- }
-
- bOff = 0;
- }
-
- public void update(
- byte in)
- {
- buf[bOff++] = in;
-
- if (bOff == buf.length)
- {
- processWord(buf, 0);
- }
-
- byteCount++;
- }
-
- public void update(
- byte[] in,
- int inOff,
- int len)
- {
- //
- // fill the current word
- //
- while ((bOff != 0) && (len > 0))
- {
- update(in[inOff]);
-
- inOff++;
- len--;
- }
-
- //
- // process whole words.
- //
- while (len > 8)
- {
- processWord(in, inOff);
-
- inOff += 8;
- len -= 8;
- byteCount += 8;
- }
-
- //
- // load in the remainder.
- //
- while (len > 0)
- {
- update(in[inOff]);
-
- inOff++;
- len--;
- }
- }
-
- private void roundABC(
- long x,
- long mul)
- {
- c ^= x ;
- a -= t1[(int)c & 0xff] ^ t2[(int)(c >> 16) & 0xff]
- ^ t3[(int)(c >> 32) & 0xff] ^ t4[(int)(c >> 48) & 0xff];
- b += t4[(int)(c >> 8) & 0xff] ^ t3[(int)(c >> 24) & 0xff]
- ^ t2[(int)(c >> 40) & 0xff] ^ t1[(int)(c >> 56) & 0xff];
- b *= mul;
- }
-
- private void roundBCA(
- long x,
- long mul)
- {
- a ^= x ;
- b -= t1[(int)a & 0xff] ^ t2[(int)(a >> 16) & 0xff]
- ^ t3[(int)(a >> 32) & 0xff] ^ t4[(int)(a >> 48) & 0xff];
- c += t4[(int)(a >> 8) & 0xff] ^ t3[(int)(a >> 24) & 0xff]
- ^ t2[(int)(a >> 40) & 0xff] ^ t1[(int)(a >> 56) & 0xff];
- c *= mul;
- }
-
- private void roundCAB(
- long x,
- long mul)
- {
- b ^= x ;
- c -= t1[(int)b & 0xff] ^ t2[(int)(b >> 16) & 0xff]
- ^ t3[(int)(b >> 32) & 0xff] ^ t4[(int)(b >> 48) & 0xff];
- a += t4[(int)(b >> 8) & 0xff] ^ t3[(int)(b >> 24) & 0xff]
- ^ t2[(int)(b >> 40) & 0xff] ^ t1[(int)(b >> 56) & 0xff];
- a *= mul;
- }
-
- private void keySchedule()
- {
- x[0] -= x[7] ^ 0xA5A5A5A5A5A5A5A5L;
- x[1] ^= x[0];
- x[2] += x[1];
- x[3] -= x[2] ^ ((~x[1]) << 19);
- x[4] ^= x[3];
- x[5] += x[4];
- x[6] -= x[5] ^ ((~x[4]) >>> 23);
- x[7] ^= x[6];
- x[0] += x[7];
- x[1] -= x[0] ^ ((~x[7]) << 19);
- x[2] ^= x[1];
- x[3] += x[2];
- x[4] -= x[3] ^ ((~x[2]) >>> 23);
- x[5] ^= x[4];
- x[6] += x[5];
- x[7] -= x[6] ^ 0x0123456789ABCDEFL;
- }
-
- private void processBlock()
- {
- //
- // save abc
- //
- long aa = a;
- long bb = b;
- long cc = c;
-
- //
- // rounds and schedule
- //
- roundABC(x[0], 5);
- roundBCA(x[1], 5);
- roundCAB(x[2], 5);
- roundABC(x[3], 5);
- roundBCA(x[4], 5);
- roundCAB(x[5], 5);
- roundABC(x[6], 5);
- roundBCA(x[7], 5);
-
- keySchedule();
-
- roundCAB(x[0], 7);
- roundABC(x[1], 7);
- roundBCA(x[2], 7);
- roundCAB(x[3], 7);
- roundABC(x[4], 7);
- roundBCA(x[5], 7);
- roundCAB(x[6], 7);
- roundABC(x[7], 7);
-
- keySchedule();
-
- roundBCA(x[0], 9);
- roundCAB(x[1], 9);
- roundABC(x[2], 9);
- roundBCA(x[3], 9);
- roundCAB(x[4], 9);
- roundABC(x[5], 9);
- roundBCA(x[6], 9);
- roundCAB(x[7], 9);
-
- //
- // feed forward
- //
- a ^= aa;
- b -= bb;
- c += cc;
-
- //
- // clear the x buffer
- //
- xOff = 0;
- for (int i = 0; i != x.length; i++)
- {
- x[i] = 0;
- }
- }
-
- public void unpackWord(
- long r,
- byte[] out,
- int outOff)
- {
- out[outOff + 7] = (byte)(r >> 56);
- out[outOff + 6] = (byte)(r >> 48);
- out[outOff + 5] = (byte)(r >> 40);
- out[outOff + 4] = (byte)(r >> 32);
- out[outOff + 3] = (byte)(r >> 24);
- out[outOff + 2] = (byte)(r >> 16);
- out[outOff + 1] = (byte)(r >> 8);
- out[outOff] = (byte)r;
- }
-
- private void processLength(
- long bitLength)
- {
- x[7] = bitLength;
- }
-
- private void finish()
- {
- long bitLength = (byteCount << 3);
-
- update((byte)0x01);
-
- while (bOff != 0)
- {
- update((byte)0);
- }
-
- processLength(bitLength);
-
- processBlock();
- }
-
- public int doFinal(
- byte[] out,
- int outOff)
- {
- finish();
-
- unpackWord(a, out, outOff);
- unpackWord(b, out, outOff + 8);
- unpackWord(c, out, outOff + 16);
-
- reset();
-
- return DIGEST_LENGTH;
- }
-
- /**
- * reset the chaining variables
- */
- public void reset()
- {
- a = 0x0123456789ABCDEFL;
- b = 0xFEDCBA9876543210L;
- c = 0xF096A5B4C3B2E187L;
-
- xOff = 0;
- for (int i = 0; i != x.length; i++)
- {
- x[i] = 0;
- }
-
- bOff = 0;
- for (int i = 0; i != buf.length; i++)
- {
- buf[i] = 0;
- }
-
- byteCount = 0;
- }
-
- public int getByteLength()
- {
- return BYTE_LENGTH;
- }
-
- public Memoable copy()
- {
- return new TigerDigest(this);
- }
-
- public void reset(Memoable other)
- {
- TigerDigest t = (TigerDigest)other;
-
- a = t.a;
- b = t.b;
- c = t.c;
-
- System.arraycopy(t.x, 0, x, 0, t.x.length);
- xOff = t.xOff;
-
- System.arraycopy(t.buf, 0, buf, 0, t.buf.length);
- bOff = t.bOff;
-
- byteCount = t.byteCount;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/digests/WhirlpoolDigest.java b/core/src/main/java/org/bouncycastle/crypto/digests/WhirlpoolDigest.java
deleted file mode 100644
index 11e884cd..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/digests/WhirlpoolDigest.java
+++ /dev/null
@@ -1,409 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-import org.bouncycastle.crypto.ExtendedDigest;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Memoable;
-
-
-/**
- * Implementation of WhirlpoolDigest, based on Java source published by Barreto
- * and Rijmen.
- *
- */
-public final class WhirlpoolDigest
- implements ExtendedDigest, Memoable
-{
- private static final int BYTE_LENGTH = 64;
-
- private static final int DIGEST_LENGTH_BYTES = 512 / 8;
- private static final int ROUNDS = 10;
- private static final int REDUCTION_POLYNOMIAL = 0x011d; // 2^8 + 2^4 + 2^3 + 2 + 1;
-
- private static final int[] SBOX = {
- 0x18, 0x23, 0xc6, 0xe8, 0x87, 0xb8, 0x01, 0x4f, 0x36, 0xa6, 0xd2, 0xf5, 0x79, 0x6f, 0x91, 0x52,
- 0x60, 0xbc, 0x9b, 0x8e, 0xa3, 0x0c, 0x7b, 0x35, 0x1d, 0xe0, 0xd7, 0xc2, 0x2e, 0x4b, 0xfe, 0x57,
- 0x15, 0x77, 0x37, 0xe5, 0x9f, 0xf0, 0x4a, 0xda, 0x58, 0xc9, 0x29, 0x0a, 0xb1, 0xa0, 0x6b, 0x85,
- 0xbd, 0x5d, 0x10, 0xf4, 0xcb, 0x3e, 0x05, 0x67, 0xe4, 0x27, 0x41, 0x8b, 0xa7, 0x7d, 0x95, 0xd8,
- 0xfb, 0xee, 0x7c, 0x66, 0xdd, 0x17, 0x47, 0x9e, 0xca, 0x2d, 0xbf, 0x07, 0xad, 0x5a, 0x83, 0x33,
- 0x63, 0x02, 0xaa, 0x71, 0xc8, 0x19, 0x49, 0xd9, 0xf2, 0xe3, 0x5b, 0x88, 0x9a, 0x26, 0x32, 0xb0,
- 0xe9, 0x0f, 0xd5, 0x80, 0xbe, 0xcd, 0x34, 0x48, 0xff, 0x7a, 0x90, 0x5f, 0x20, 0x68, 0x1a, 0xae,
- 0xb4, 0x54, 0x93, 0x22, 0x64, 0xf1, 0x73, 0x12, 0x40, 0x08, 0xc3, 0xec, 0xdb, 0xa1, 0x8d, 0x3d,
- 0x97, 0x00, 0xcf, 0x2b, 0x76, 0x82, 0xd6, 0x1b, 0xb5, 0xaf, 0x6a, 0x50, 0x45, 0xf3, 0x30, 0xef,
- 0x3f, 0x55, 0xa2, 0xea, 0x65, 0xba, 0x2f, 0xc0, 0xde, 0x1c, 0xfd, 0x4d, 0x92, 0x75, 0x06, 0x8a,
- 0xb2, 0xe6, 0x0e, 0x1f, 0x62, 0xd4, 0xa8, 0x96, 0xf9, 0xc5, 0x25, 0x59, 0x84, 0x72, 0x39, 0x4c,
- 0x5e, 0x78, 0x38, 0x8c, 0xd1, 0xa5, 0xe2, 0x61, 0xb3, 0x21, 0x9c, 0x1e, 0x43, 0xc7, 0xfc, 0x04,
- 0x51, 0x99, 0x6d, 0x0d, 0xfa, 0xdf, 0x7e, 0x24, 0x3b, 0xab, 0xce, 0x11, 0x8f, 0x4e, 0xb7, 0xeb,
- 0x3c, 0x81, 0x94, 0xf7, 0xb9, 0x13, 0x2c, 0xd3, 0xe7, 0x6e, 0xc4, 0x03, 0x56, 0x44, 0x7f, 0xa9,
- 0x2a, 0xbb, 0xc1, 0x53, 0xdc, 0x0b, 0x9d, 0x6c, 0x31, 0x74, 0xf6, 0x46, 0xac, 0x89, 0x14, 0xe1,
- 0x16, 0x3a, 0x69, 0x09, 0x70, 0xb6, 0xd0, 0xed, 0xcc, 0x42, 0x98, 0xa4, 0x28, 0x5c, 0xf8, 0x86
- };
-
- private static final long[] C0 = new long[256];
- private static final long[] C1 = new long[256];
- private static final long[] C2 = new long[256];
- private static final long[] C3 = new long[256];
- private static final long[] C4 = new long[256];
- private static final long[] C5 = new long[256];
- private static final long[] C6 = new long[256];
- private static final long[] C7 = new long[256];
-
- private final long[] _rc = new long[ROUNDS + 1];
-
- public WhirlpoolDigest()
- {
- for (int i = 0; i < 256; i++)
- {
- int v1 = SBOX[i];
- int v2 = maskWithReductionPolynomial(v1 << 1);
- int v4 = maskWithReductionPolynomial(v2 << 1);
- int v5 = v4 ^ v1;
- int v8 = maskWithReductionPolynomial(v4 << 1);
- int v9 = v8 ^ v1;
-
- C0[i] = packIntoLong(v1, v1, v4, v1, v8, v5, v2, v9);
- C1[i] = packIntoLong(v9, v1, v1, v4, v1, v8, v5, v2);
- C2[i] = packIntoLong(v2, v9, v1, v1, v4, v1, v8, v5);
- C3[i] = packIntoLong(v5, v2, v9, v1, v1, v4, v1, v8);
- C4[i] = packIntoLong(v8, v5, v2, v9, v1, v1, v4, v1);
- C5[i] = packIntoLong(v1, v8, v5, v2, v9, v1, v1, v4);
- C6[i] = packIntoLong(v4, v1, v8, v5, v2, v9, v1, v1);
- C7[i] = packIntoLong(v1, v4, v1, v8, v5, v2, v9, v1);
-
- }
-
- _rc[0] = 0L;
- for (int r = 1; r <= ROUNDS; r++)
- {
- int i = 8 * (r - 1);
- _rc[r] = (C0[i ] & 0xff00000000000000L) ^
- (C1[i + 1] & 0x00ff000000000000L) ^
- (C2[i + 2] & 0x0000ff0000000000L) ^
- (C3[i + 3] & 0x000000ff00000000L) ^
- (C4[i + 4] & 0x00000000ff000000L) ^
- (C5[i + 5] & 0x0000000000ff0000L) ^
- (C6[i + 6] & 0x000000000000ff00L) ^
- (C7[i + 7] & 0x00000000000000ffL);
- }
-
- }
-
- private long packIntoLong(int b7, int b6, int b5, int b4, int b3, int b2, int b1, int b0)
- {
- return
- ((long)b7 << 56) ^
- ((long)b6 << 48) ^
- ((long)b5 << 40) ^
- ((long)b4 << 32) ^
- ((long)b3 << 24) ^
- ((long)b2 << 16) ^
- ((long)b1 << 8) ^
- b0;
- }
-
- /*
- * int's are used to prevent sign extension. The values that are really being used are
- * actually just 0..255
- */
- private int maskWithReductionPolynomial(int input)
- {
- int rv = input;
- if (rv >= 0x100L) // high bit set
- {
- rv ^= REDUCTION_POLYNOMIAL; // reduced by the polynomial
- }
- return rv;
- }
-
- // --------------------------------------------------------------------------------------//
-
- // -- buffer information --
- private static final int BITCOUNT_ARRAY_SIZE = 32;
- private byte[] _buffer = new byte[64];
- private int _bufferPos = 0;
- private short[] _bitCount = new short[BITCOUNT_ARRAY_SIZE];
-
- // -- internal hash state --
- private long[] _hash = new long[8];
- private long[] _K = new long[8]; // the round key
- private long[] _L = new long[8];
- private long[] _block = new long[8]; // mu (buffer)
- private long[] _state = new long[8]; // the current "cipher" state
-
-
-
- /**
- * Copy constructor. This will copy the state of the provided message
- * digest.
- */
- public WhirlpoolDigest(WhirlpoolDigest originalDigest)
- {
- reset(originalDigest);
- }
-
- public String getAlgorithmName()
- {
- return "Whirlpool";
- }
-
- public int getDigestSize()
- {
- return DIGEST_LENGTH_BYTES;
- }
-
- public int doFinal(byte[] out, int outOff)
- {
- // sets out[outOff] .. out[outOff+DIGEST_LENGTH_BYTES]
- finish();
-
- for (int i = 0; i < 8; i++)
- {
- convertLongToByteArray(_hash[i], out, outOff + (i * 8));
- }
-
- reset();
- return getDigestSize();
- }
-
- /**
- * reset the chaining variables
- */
- public void reset()
- {
- // set variables to null, blank, whatever
- _bufferPos = 0;
- Arrays.fill(_bitCount, (short)0);
- Arrays.fill(_buffer, (byte)0);
- Arrays.fill(_hash, 0);
- Arrays.fill(_K, 0);
- Arrays.fill(_L, 0);
- Arrays.fill(_block, 0);
- Arrays.fill(_state, 0);
- }
-
- // this takes a buffer of information and fills the block
- private void processFilledBuffer(byte[] in, int inOff)
- {
- // copies into the block...
- for (int i = 0; i < _state.length; i++)
- {
- _block[i] = bytesToLongFromBuffer(_buffer, i * 8);
- }
- processBlock();
- _bufferPos = 0;
- Arrays.fill(_buffer, (byte)0);
- }
-
- private long bytesToLongFromBuffer(byte[] buffer, int startPos)
- {
- long rv = (((buffer[startPos + 0] & 0xffL) << 56) |
- ((buffer[startPos + 1] & 0xffL) << 48) |
- ((buffer[startPos + 2] & 0xffL) << 40) |
- ((buffer[startPos + 3] & 0xffL) << 32) |
- ((buffer[startPos + 4] & 0xffL) << 24) |
- ((buffer[startPos + 5] & 0xffL) << 16) |
- ((buffer[startPos + 6] & 0xffL) << 8) |
- ((buffer[startPos + 7]) & 0xffL));
-
- return rv;
- }
-
- private void convertLongToByteArray(long inputLong, byte[] outputArray, int offSet)
- {
- for (int i = 0; i < 8; i++)
- {
- outputArray[offSet + i] = (byte)((inputLong >> (56 - (i * 8))) & 0xff);
- }
- }
-
- protected void processBlock()
- {
- // buffer contents have been transferred to the _block[] array via
- // processFilledBuffer
-
- // compute and apply K^0
- for (int i = 0; i < 8; i++)
- {
- _state[i] = _block[i] ^ (_K[i] = _hash[i]);
- }
-
- // iterate over the rounds
- for (int round = 1; round <= ROUNDS; round++)
- {
- for (int i = 0; i < 8; i++)
- {
- _L[i] = 0;
- _L[i] ^= C0[(int)(_K[(i - 0) & 7] >>> 56) & 0xff];
- _L[i] ^= C1[(int)(_K[(i - 1) & 7] >>> 48) & 0xff];
- _L[i] ^= C2[(int)(_K[(i - 2) & 7] >>> 40) & 0xff];
- _L[i] ^= C3[(int)(_K[(i - 3) & 7] >>> 32) & 0xff];
- _L[i] ^= C4[(int)(_K[(i - 4) & 7] >>> 24) & 0xff];
- _L[i] ^= C5[(int)(_K[(i - 5) & 7] >>> 16) & 0xff];
- _L[i] ^= C6[(int)(_K[(i - 6) & 7] >>> 8) & 0xff];
- _L[i] ^= C7[(int)(_K[(i - 7) & 7]) & 0xff];
- }
-
- System.arraycopy(_L, 0, _K, 0, _K.length);
-
- _K[0] ^= _rc[round];
-
- // apply the round transformation
- for (int i = 0; i < 8; i++)
- {
- _L[i] = _K[i];
-
- _L[i] ^= C0[(int)(_state[(i - 0) & 7] >>> 56) & 0xff];
- _L[i] ^= C1[(int)(_state[(i - 1) & 7] >>> 48) & 0xff];
- _L[i] ^= C2[(int)(_state[(i - 2) & 7] >>> 40) & 0xff];
- _L[i] ^= C3[(int)(_state[(i - 3) & 7] >>> 32) & 0xff];
- _L[i] ^= C4[(int)(_state[(i - 4) & 7] >>> 24) & 0xff];
- _L[i] ^= C5[(int)(_state[(i - 5) & 7] >>> 16) & 0xff];
- _L[i] ^= C6[(int)(_state[(i - 6) & 7] >>> 8) & 0xff];
- _L[i] ^= C7[(int)(_state[(i - 7) & 7]) & 0xff];
- }
-
- // save the current state
- System.arraycopy(_L, 0, _state, 0, _state.length);
- }
-
- // apply Miuaguchi-Preneel compression
- for (int i = 0; i < 8; i++)
- {
- _hash[i] ^= _state[i] ^ _block[i];
- }
-
- }
-
- public void update(byte in)
- {
- _buffer[_bufferPos] = in;
-
- //System.out.println("adding to buffer = "+_buffer[_bufferPos]);
-
- ++_bufferPos;
-
- if (_bufferPos == _buffer.length)
- {
- processFilledBuffer(_buffer, 0);
- }
-
- increment();
- }
-
- /*
- * increment() can be implemented in this way using 2 arrays or
- * by having some temporary variables that are used to set the
- * value provided by EIGHT[i] and carry within the loop.
- *
- * not having done any timing, this seems likely to be faster
- * at the slight expense of 32*(sizeof short) bytes
- */
- private static final short[] EIGHT = new short[BITCOUNT_ARRAY_SIZE];
- static
- {
- EIGHT[BITCOUNT_ARRAY_SIZE - 1] = 8;
- }
-
- private void increment()
- {
- int carry = 0;
- for (int i = _bitCount.length - 1; i >= 0; i--)
- {
- int sum = (_bitCount[i] & 0xff) + EIGHT[i] + carry;
-
- carry = sum >>> 8;
- _bitCount[i] = (short)(sum & 0xff);
- }
- }
-
- public void update(byte[] in, int inOff, int len)
- {
- while (len > 0)
- {
- update(in[inOff]);
- ++inOff;
- --len;
- }
-
- }
-
- private void finish()
- {
- /*
- * this makes a copy of the current bit length. at the expense of an
- * object creation of 32 bytes rather than providing a _stopCounting
- * boolean which was the alternative I could think of.
- */
- byte[] bitLength = copyBitLength();
-
- _buffer[_bufferPos++] |= 0x80;
-
- if (_bufferPos == _buffer.length)
- {
- processFilledBuffer(_buffer, 0);
- }
-
- /*
- * Final block contains
- * [ ... data .... ][0][0][0][ length ]
- *
- * if [ length ] cannot fit. Need to create a new block.
- */
- if (_bufferPos > 32)
- {
- while (_bufferPos != 0)
- {
- update((byte)0);
- }
- }
-
- while (_bufferPos <= 32)
- {
- update((byte)0);
- }
-
- // copy the length information to the final 32 bytes of the
- // 64 byte block....
- System.arraycopy(bitLength, 0, _buffer, 32, bitLength.length);
-
- processFilledBuffer(_buffer, 0);
- }
-
- private byte[] copyBitLength()
- {
- byte[] rv = new byte[BITCOUNT_ARRAY_SIZE];
- for (int i = 0; i < rv.length; i++)
- {
- rv[i] = (byte)(_bitCount[i] & 0xff);
- }
- return rv;
- }
-
- public int getByteLength()
- {
- return BYTE_LENGTH;
- }
-
- public Memoable copy()
- {
- return new WhirlpoolDigest(this);
- }
-
- public void reset(Memoable other)
- {
- WhirlpoolDigest originalDigest = (WhirlpoolDigest)other;
-
- System.arraycopy(originalDigest._rc, 0, _rc, 0, _rc.length);
-
- System.arraycopy(originalDigest._buffer, 0, _buffer, 0, _buffer.length);
-
- this._bufferPos = originalDigest._bufferPos;
- System.arraycopy(originalDigest._bitCount, 0, _bitCount, 0, _bitCount.length);
-
- // -- internal hash state --
- System.arraycopy(originalDigest._hash, 0, _hash, 0, _hash.length);
- System.arraycopy(originalDigest._K, 0, _K, 0, _K.length);
- System.arraycopy(originalDigest._L, 0, _L, 0, _L.length);
- System.arraycopy(originalDigest._block, 0, _block, 0, _block.length);
- System.arraycopy(originalDigest._state, 0, _state, 0, _state.length);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java b/core/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java
deleted file mode 100644
index c3d4f5bb..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java
+++ /dev/null
@@ -1,320 +0,0 @@
-package org.bouncycastle.crypto.ec;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-import java.util.Hashtable;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.sec.SECObjectIdentifiers;
-import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.asn1.x9.X9ECParametersHolder;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.ec.custom.djb.Curve25519;
-import org.bouncycastle.math.ec.custom.sec.SecP192K1Curve;
-import org.bouncycastle.math.ec.custom.sec.SecP192R1Curve;
-import org.bouncycastle.math.ec.custom.sec.SecP224K1Curve;
-import org.bouncycastle.math.ec.custom.sec.SecP224R1Curve;
-import org.bouncycastle.math.ec.custom.sec.SecP256K1Curve;
-import org.bouncycastle.math.ec.custom.sec.SecP256R1Curve;
-import org.bouncycastle.math.ec.custom.sec.SecP384R1Curve;
-import org.bouncycastle.math.ec.custom.sec.SecP521R1Curve;
-import org.bouncycastle.math.ec.endo.GLVTypeBEndomorphism;
-import org.bouncycastle.math.ec.endo.GLVTypeBParameters;
-import org.bouncycastle.util.Strings;
-import org.bouncycastle.util.encoders.Hex;
-
-public class CustomNamedCurves
-{
- private static ECCurve configureCurve(ECCurve curve)
- {
- return curve;
- }
-
- private static ECCurve configureCurveGLV(ECCurve c, GLVTypeBParameters p)
- {
- return c.configure().setEndomorphism(new GLVTypeBEndomorphism(c, p)).create();
- }
-
- /*
- * curve25519
- */
- static X9ECParametersHolder curve25519 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- byte[] S = null;
- ECCurve curve = configureCurve(new Curve25519());
-
- /*
- * NOTE: Curve25519 was specified in Montgomery form. Rewriting in Weierstrass form
- * involves substitution of variables, so the base-point x coordinate is 9 + (486662 / 3).
- *
- * The Curve25519 paper doesn't say which of the two possible y values the base
- * point has. The choice here is guided by language in the Ed25519 paper.
- *
- * (The other possible y value is 5F51E65E475F794B1FE122D388B72EB36DC2B28192839E4DD6163A5D81312C14)
- */
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD245A"
- + "20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9"));
-
- return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
- }
- };
-
- /*
- * secp192k1
- */
- static X9ECParametersHolder secp192k1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- byte[] S = null;
- GLVTypeBParameters glv = new GLVTypeBParameters(
- new BigInteger("bb85691939b869c1d087f601554b96b80cb4f55b35f433c2", 16),
- new BigInteger("3d84f26c12238d7b4f3d516613c1759033b1a5800175d0b1", 16),
- new BigInteger[]{
- new BigInteger("71169be7330b3038edb025f1", 16),
- new BigInteger("-b3fb3400dec5c4adceb8655c", 16) },
- new BigInteger[]{
- new BigInteger("12511cfe811d0f4e6bc688b4d", 16),
- new BigInteger("71169be7330b3038edb025f1", 16) },
- new BigInteger("71169be7330b3038edb025f1d0f9", 16),
- new BigInteger("b3fb3400dec5c4adceb8655d4c94", 16),
- 208);
- ECCurve curve = configureCurveGLV(new SecP192K1Curve(), glv);
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"
- + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D"));
- return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
- }
- };
-
- /*
- * secp192r1
- */
- static X9ECParametersHolder secp192r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- byte[] S = Hex.decode("3045AE6FC8422F64ED579528D38120EAE12196D5");
- ECCurve curve = configureCurve(new SecP192R1Curve());
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"
- + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811"));
- return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
- }
- };
-
- /*
- * secp224k1
- */
- static X9ECParametersHolder secp224k1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- byte[] S = null;
- GLVTypeBParameters glv = new GLVTypeBParameters(
- new BigInteger("fe0e87005b4e83761908c5131d552a850b3f58b749c37cf5b84d6768", 16),
- new BigInteger("60dcd2104c4cbc0be6eeefc2bdd610739ec34e317f9b33046c9e4788", 16),
- new BigInteger[]{
- new BigInteger("6b8cf07d4ca75c88957d9d670591", 16),
- new BigInteger("-b8adf1378a6eb73409fa6c9c637d", 16) },
- new BigInteger[]{
- new BigInteger("1243ae1b4d71613bc9f780a03690e", 16),
- new BigInteger("6b8cf07d4ca75c88957d9d670591", 16) },
- new BigInteger("6b8cf07d4ca75c88957d9d67059037a4", 16),
- new BigInteger("b8adf1378a6eb73409fa6c9c637ba7f5", 16),
- 240);
- ECCurve curve = configureCurveGLV(new SecP224K1Curve(), glv);
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"
- + "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5"));
- return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
- }
- };
-
- /*
- * secp224r1
- */
- static X9ECParametersHolder secp224r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- byte[] S = Hex.decode("BD71344799D5C7FCDC45B59FA3B9AB8F6A948BC5");
- ECCurve curve = configureCurve(new SecP224R1Curve());
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"
- + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"));
- return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
- }
- };
-
- /*
- * secp256k1
- */
- static X9ECParametersHolder secp256k1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- byte[] S = null;
- GLVTypeBParameters glv = new GLVTypeBParameters(
- new BigInteger("7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee", 16),
- new BigInteger("5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72", 16),
- new BigInteger[]{
- new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16),
- new BigInteger("-e4437ed6010e88286f547fa90abfe4c3", 16) },
- new BigInteger[]{
- new BigInteger("114ca50f7a8e2f3f657c1108d9d44cfd8", 16),
- new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16) },
- new BigInteger("3086d221a7d46bcde86c90e49284eb153dab", 16),
- new BigInteger("e4437ed6010e88286f547fa90abfe4c42212", 16),
- 272);
- ECCurve curve = configureCurveGLV(new SecP256K1Curve(), glv);
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
- + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"));
- return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
- }
- };
-
- /*
- * secp256r1
- */
- static X9ECParametersHolder secp256r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- byte[] S = Hex.decode("C49D360886E704936A6678E1139D26B7819F7E90");
- ECCurve curve = configureCurve(new SecP256R1Curve());
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"
- + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"));
- return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
- }
- };
-
- /*
- * secp384r1
- */
- static X9ECParametersHolder secp384r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- byte[] S = Hex.decode("A335926AA319A27A1D00896A6773A4827ACDAC73");
- ECCurve curve = configureCurve(new SecP384R1Curve());
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"
- + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F"));
- return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
- }
- };
-
- /*
- * secp521r1
- */
- static X9ECParametersHolder secp521r1 = new X9ECParametersHolder()
- {
- protected X9ECParameters createParameters()
- {
- byte[] S = Hex.decode("D09E8800291CB85396CC6717393284AAA0DA64BA");
- ECCurve curve = configureCurve(new SecP521R1Curve());
- ECPoint G = curve.decodePoint(Hex.decode("04"
- + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"
- + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"));
- return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
- }
- };
-
- static final Hashtable nameToCurve = new Hashtable();
- static final Hashtable nameToOID = new Hashtable();
- static final Hashtable oidToCurve = new Hashtable();
- static final Hashtable oidToName = new Hashtable();
-
- static void defineCurve(String name, X9ECParametersHolder holder)
- {
- nameToCurve.put(name, holder);
- }
-
- static void defineCurveWithOID(String name, ASN1ObjectIdentifier oid, X9ECParametersHolder holder)
- {
- nameToCurve.put(name, holder);
- nameToOID.put(name, oid);
- oidToName.put(oid, name);
- oidToCurve.put(oid, holder);
- }
-
- static void defineCurveAlias(String alias, ASN1ObjectIdentifier oid)
- {
- alias = Strings.toLowerCase(alias);
- nameToOID.put(alias, oid);
- nameToCurve.put(alias, oidToCurve.get(oid));
- }
-
- static
- {
- defineCurve("curve25519", curve25519);
-
- defineCurveWithOID("secp192k1", SECObjectIdentifiers.secp192k1, secp192k1);
- defineCurveWithOID("secp192r1", SECObjectIdentifiers.secp192r1, secp192r1);
- defineCurveWithOID("secp224k1", SECObjectIdentifiers.secp224k1, secp224k1);
- defineCurveWithOID("secp224r1", SECObjectIdentifiers.secp224r1, secp224r1);
- defineCurveWithOID("secp256k1", SECObjectIdentifiers.secp256k1, secp256k1);
- defineCurveWithOID("secp256r1", SECObjectIdentifiers.secp256r1, secp256r1);
- defineCurveWithOID("secp384r1", SECObjectIdentifiers.secp384r1, secp384r1);
- defineCurveWithOID("secp521r1", SECObjectIdentifiers.secp521r1, secp521r1);
-
- defineCurveAlias("P-192", SECObjectIdentifiers.secp192r1);
- defineCurveAlias("P-224", SECObjectIdentifiers.secp224r1);
- defineCurveAlias("P-256", SECObjectIdentifiers.secp256r1);
- defineCurveAlias("P-384", SECObjectIdentifiers.secp384r1);
- defineCurveAlias("P-521", SECObjectIdentifiers.secp521r1);
- }
-
- public static X9ECParameters getByName(String name)
- {
- X9ECParametersHolder holder = (X9ECParametersHolder)nameToCurve.get(Strings.toLowerCase(name));
- return holder == null ? null : holder.getParameters();
- }
-
- /**
- * return the X9ECParameters object for the named curve represented by the passed in object
- * identifier. Null if the curve isn't present.
- *
- * @param oid
- * an object identifier representing a named curve, if present.
- */
- public static X9ECParameters getByOID(ASN1ObjectIdentifier oid)
- {
- X9ECParametersHolder holder = (X9ECParametersHolder)oidToCurve.get(oid);
- return holder == null ? null : holder.getParameters();
- }
-
- /**
- * return the object identifier signified by the passed in name. Null if there is no object
- * identifier associated with name.
- *
- * @return the object identifier associated with name, if present.
- */
- public static ASN1ObjectIdentifier getOID(String name)
- {
- return (ASN1ObjectIdentifier)nameToOID.get(Strings.toLowerCase(name));
- }
-
- /**
- * return the named curve name represented by the given object identifier.
- */
- public static String getName(ASN1ObjectIdentifier oid)
- {
- return (String)oidToName.get(oid);
- }
-
- /**
- * returns an enumeration containing the name strings for curves contained in this structure.
- */
- public static Enumeration getNames()
- {
- return nameToCurve.keys();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/ec/ECDecryptor.java b/core/src/main/java/org/bouncycastle/crypto/ec/ECDecryptor.java
deleted file mode 100644
index c4faf4c2..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/ec/ECDecryptor.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.bouncycastle.crypto.ec;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.math.ec.ECPoint;
-
-public interface ECDecryptor
-{
- void init(CipherParameters params);
-
- ECPoint decrypt(ECPair cipherText);
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/ec/ECElGamalDecryptor.java b/core/src/main/java/org/bouncycastle/crypto/ec/ECElGamalDecryptor.java
deleted file mode 100644
index 2f1c9374..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/ec/ECElGamalDecryptor.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.bouncycastle.crypto.ec;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.math.ec.ECPoint;
-
-/**
- * this does your basic decryption ElGamal style using EC
- */
-public class ECElGamalDecryptor
- implements ECDecryptor
-{
- private ECPrivateKeyParameters key;
-
- /**
- * initialise the decryptor.
- *
- * @param param the necessary EC key parameters.
- */
- public void init(
- CipherParameters param)
- {
- if (!(param instanceof ECPrivateKeyParameters))
- {
- throw new IllegalArgumentException("ECPrivateKeyParameters are required for decryption.");
- }
-
- this.key = (ECPrivateKeyParameters)param;
- }
-
- /**
- * Decrypt an EC pair producing the original EC point.
- *
- * @param pair the EC point pair to process.
- * @return the result of the Elgamal process.
- */
- public ECPoint decrypt(ECPair pair)
- {
- if (key == null)
- {
- throw new IllegalStateException("ECElGamalDecryptor not initialised");
- }
-
- ECPoint tmp = pair.getX().multiply(key.getD());
-
- return pair.getY().subtract(tmp).normalize();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/ec/ECElGamalEncryptor.java b/core/src/main/java/org/bouncycastle/crypto/ec/ECElGamalEncryptor.java
deleted file mode 100644
index 48fc0467..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/ec/ECElGamalEncryptor.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.bouncycastle.crypto.ec;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.math.ec.ECMultiplier;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.ec.FixedPointCombMultiplier;
-
-/**
- * this does your basic ElGamal encryption algorithm using EC
- */
-public class ECElGamalEncryptor
- implements ECEncryptor
-{
- private ECPublicKeyParameters key;
- private SecureRandom random;
-
- /**
- * initialise the encryptor.
- *
- * @param param the necessary EC key parameters.
- */
- public void init(
- CipherParameters param)
- {
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom p = (ParametersWithRandom)param;
-
- if (!(p.getParameters() instanceof ECPublicKeyParameters))
- {
- throw new IllegalArgumentException("ECPublicKeyParameters are required for encryption.");
- }
- this.key = (ECPublicKeyParameters)p.getParameters();
- this.random = p.getRandom();
- }
- else
- {
- if (!(param instanceof ECPublicKeyParameters))
- {
- throw new IllegalArgumentException("ECPublicKeyParameters are required for encryption.");
- }
-
- this.key = (ECPublicKeyParameters)param;
- this.random = new SecureRandom();
- }
- }
-
- /**
- * Process a single EC point using the basic ElGamal algorithm.
- *
- * @param point the EC point to process.
- * @return the result of the Elgamal process.
- */
- public ECPair encrypt(ECPoint point)
- {
- if (key == null)
- {
- throw new IllegalStateException("ECElGamalEncryptor not initialised");
- }
-
- ECDomainParameters ec = key.getParameters();
- BigInteger k = ECUtil.generateK(ec.getN(), random);
-
- ECMultiplier basePointMultiplier = createBasePointMultiplier();
-
- ECPoint[] gamma_phi = new ECPoint[]{
- basePointMultiplier.multiply(ec.getG(), k),
- key.getQ().multiply(k).add(point)
- };
-
- ec.getCurve().normalizeAll(gamma_phi);
-
- return new ECPair(gamma_phi[0], gamma_phi[1]);
- }
-
- protected ECMultiplier createBasePointMultiplier()
- {
- return new FixedPointCombMultiplier();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/ec/ECEncryptor.java b/core/src/main/java/org/bouncycastle/crypto/ec/ECEncryptor.java
deleted file mode 100644
index 39704b94..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/ec/ECEncryptor.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.bouncycastle.crypto.ec;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.math.ec.ECPoint;
-
-public interface ECEncryptor
-{
- void init(CipherParameters params);
-
- ECPair encrypt(ECPoint point);
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/ec/ECFixedTransform.java b/core/src/main/java/org/bouncycastle/crypto/ec/ECFixedTransform.java
deleted file mode 100644
index 2c6a920b..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/ec/ECFixedTransform.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package org.bouncycastle.crypto.ec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.math.ec.ECMultiplier;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.ec.FixedPointCombMultiplier;
-
-/**
- * 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 text 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");
- }
-
- ECDomainParameters ec = key.getParameters();
- BigInteger n = ec.getN();
-
- ECMultiplier basePointMultiplier = createBasePointMultiplier();
- BigInteger k = this.k.mod(n);
-
- ECPoint[] gamma_phi = new ECPoint[]{
- basePointMultiplier.multiply(ec.getG(), k).add(cipherText.getX()),
- key.getQ().multiply(k).add(cipherText.getY())
- };
-
- ec.getCurve().normalizeAll(gamma_phi);
-
- return new ECPair(gamma_phi[0], gamma_phi[1]);
- }
-
- /**
- * Return the last transform value used by the transform
- *
- * @return a BigInteger representing k value.
- */
- public BigInteger getTransformValue()
- {
- return k;
- }
-
- protected ECMultiplier createBasePointMultiplier()
- {
- return new FixedPointCombMultiplier();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/ec/ECNewPublicKeyTransform.java b/core/src/main/java/org/bouncycastle/crypto/ec/ECNewPublicKeyTransform.java
deleted file mode 100644
index 112d20c1..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/ec/ECNewPublicKeyTransform.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package org.bouncycastle.crypto.ec;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.math.ec.ECMultiplier;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.ec.FixedPointCombMultiplier;
-
-/**
- * this does your basic Elgamal encryption algorithm using EC
- */
-public class ECNewPublicKeyTransform
- implements ECPairTransform
-{
- private ECPublicKeyParameters key;
- private SecureRandom random;
-
- /**
- * initialise the EC Elgamal engine.
- *
- * @param param the necessary EC key parameters.
- */
- public void init(
- CipherParameters param)
- {
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom p = (ParametersWithRandom)param;
-
- if (!(p.getParameters() instanceof ECPublicKeyParameters))
- {
- throw new IllegalArgumentException("ECPublicKeyParameters are required for new public key transform.");
- }
- this.key = (ECPublicKeyParameters)p.getParameters();
- this.random = p.getRandom();
- }
- else
- {
- if (!(param instanceof ECPublicKeyParameters))
- {
- throw new IllegalArgumentException("ECPublicKeyParameters are required for new public key transform.");
- }
-
- this.key = (ECPublicKeyParameters)param;
- this.random = new SecureRandom();
- }
- }
-
- /**
- * Transform an existing cipher text pair using the ElGamal algorithm. Note: the input cipherText will
- * need to be preserved in order to complete the transformation to the new public key.
- *
- * @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("ECNewPublicKeyTransform not initialised");
- }
-
- ECDomainParameters ec = key.getParameters();
- BigInteger n = ec.getN();
-
- ECMultiplier basePointMultiplier = createBasePointMultiplier();
- BigInteger k = ECUtil.generateK(n, random);
-
- ECPoint[] gamma_phi = new ECPoint[]{
- basePointMultiplier.multiply(ec.getG(), k),
- key.getQ().multiply(k).add(cipherText.getY())
- };
-
- ec.getCurve().normalizeAll(gamma_phi);
-
- return new ECPair(gamma_phi[0], gamma_phi[1]);
- }
-
- protected ECMultiplier createBasePointMultiplier()
- {
- return new FixedPointCombMultiplier();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/ec/ECNewRandomnessTransform.java b/core/src/main/java/org/bouncycastle/crypto/ec/ECNewRandomnessTransform.java
deleted file mode 100644
index 7bfc0b30..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/ec/ECNewRandomnessTransform.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package org.bouncycastle.crypto.ec;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.math.ec.ECMultiplier;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.ec.FixedPointCombMultiplier;
-
-/**
- * this transforms the original randomness used for an ElGamal encryption.
- */
-public class ECNewRandomnessTransform
- implements ECPairFactorTransform
-{
- private ECPublicKeyParameters key;
- private SecureRandom random;
-
- private BigInteger lastK;
-
- /**
- * initialise the underlying EC ElGamal engine.
- *
- * @param param the necessary EC key parameters.
- */
- public void init(
- CipherParameters param)
- {
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom p = (ParametersWithRandom)param;
-
- if (!(p.getParameters() instanceof ECPublicKeyParameters))
- {
- throw new IllegalArgumentException("ECPublicKeyParameters are required for new randomness transform.");
- }
-
- this.key = (ECPublicKeyParameters)p.getParameters();
- this.random = p.getRandom();
- }
- else
- {
- if (!(param instanceof ECPublicKeyParameters))
- {
- throw new IllegalArgumentException("ECPublicKeyParameters are required for new randomness transform.");
- }
-
- this.key = (ECPublicKeyParameters)param;
- this.random = new SecureRandom();
- }
- }
-
- /**
- * 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("ECNewRandomnessTransform not initialised");
- }
-
-
- ECDomainParameters ec = key.getParameters();
- BigInteger n = ec.getN();
-
- ECMultiplier basePointMultiplier = createBasePointMultiplier();
- BigInteger k = ECUtil.generateK(n, random);
-
- ECPoint[] gamma_phi = new ECPoint[]{
- basePointMultiplier.multiply(ec.getG(), k).add(cipherText.getX()),
- key.getQ().multiply(k).add(cipherText.getY())
- };
-
- ec.getCurve().normalizeAll(gamma_phi);
-
- lastK = k;
-
- return new ECPair(gamma_phi[0], gamma_phi[1]);
- }
-
- /**
- * Return the last random value generated for a transform
- *
- * @return a BigInteger representing the last random value.
- */
- public BigInteger getTransformValue()
- {
- return lastK;
- }
-
- protected ECMultiplier createBasePointMultiplier()
- {
- return new FixedPointCombMultiplier();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/ec/ECPair.java b/core/src/main/java/org/bouncycastle/crypto/ec/ECPair.java
deleted file mode 100644
index ea3b4b99..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/ec/ECPair.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package org.bouncycastle.crypto.ec;
-
-import org.bouncycastle.math.ec.ECPoint;
-
-public class ECPair
-{
- private final ECPoint x;
- private final ECPoint y;
-
- public ECPair(ECPoint x, ECPoint y)
- {
- this.x = x;
- this.y = y;
- }
-
- public ECPoint getX()
- {
- return x;
- }
-
- public ECPoint getY()
- {
- return y;
- }
-
- public boolean equals(ECPair other)
- {
- return other.getX().equals(getX()) && other.getY().equals(getY());
- }
-
- public boolean equals(Object other)
- {
- return other instanceof ECPair ? equals((ECPair)other) : false;
- }
-
- public int hashCode()
- {
- return x.hashCode() + 37 * y.hashCode();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/ec/ECPairFactorTransform.java b/core/src/main/java/org/bouncycastle/crypto/ec/ECPairFactorTransform.java
deleted file mode 100644
index be485518..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/ec/ECPairFactorTransform.java
+++ /dev/null
@@ -1,14 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/ec/ECPairTransform.java b/core/src/main/java/org/bouncycastle/crypto/ec/ECPairTransform.java
deleted file mode 100644
index e3f1787d..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/ec/ECPairTransform.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.bouncycastle.crypto.ec;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public interface ECPairTransform
-{
- void init(CipherParameters params);
-
- ECPair transform(ECPair cipherText);
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/ec/ECUtil.java b/core/src/main/java/org/bouncycastle/crypto/ec/ECUtil.java
deleted file mode 100644
index 74921f09..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/ec/ECUtil.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.bouncycastle.crypto.ec;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.math.ec.ECConstants;
-
-class ECUtil
-{
- static BigInteger generateK(BigInteger n, SecureRandom random)
- {
- int nBitLength = n.bitLength();
- BigInteger k;
- do
- {
- k = new BigInteger(nBitLength, random);
- }
- while (k.equals(ECConstants.ZERO) || (k.compareTo(n) >= 0));
- return k;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/encodings/ISO9796d1Encoding.java b/core/src/main/java/org/bouncycastle/crypto/encodings/ISO9796d1Encoding.java
deleted file mode 100644
index ec91e1ac..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/encodings/ISO9796d1Encoding.java
+++ /dev/null
@@ -1,287 +0,0 @@
-package org.bouncycastle.crypto.encodings;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-
-/**
- * ISO 9796-1 padding. Note in the light of recent results you should
- * only use this with RSA (rather than the "simpler" Rabin keys) and you
- * should never use it with anything other than a hash (ie. even if the
- * message is small don't sign the message, sign it's hash) or some "random"
- * value. See your favorite search engine for details.
- */
-public class ISO9796d1Encoding
- implements AsymmetricBlockCipher
-{
- private static final BigInteger SIXTEEN = BigInteger.valueOf(16L);
- private static final BigInteger SIX = BigInteger.valueOf(6L);
-
- private static byte[] shadows = { 0xe, 0x3, 0x5, 0x8, 0x9, 0x4, 0x2, 0xf,
- 0x0, 0xd, 0xb, 0x6, 0x7, 0xa, 0xc, 0x1 };
- private static byte[] inverse = { 0x8, 0xf, 0x6, 0x1, 0x5, 0x2, 0xb, 0xc,
- 0x3, 0x4, 0xd, 0xa, 0xe, 0x9, 0x0, 0x7 };
-
- private AsymmetricBlockCipher engine;
- private boolean forEncryption;
- private int bitSize;
- private int padBits = 0;
- private BigInteger modulus;
-
- public ISO9796d1Encoding(
- AsymmetricBlockCipher cipher)
- {
- this.engine = cipher;
- }
-
- public AsymmetricBlockCipher getUnderlyingCipher()
- {
- return engine;
- }
-
- public void init(
- boolean forEncryption,
- CipherParameters param)
- {
- RSAKeyParameters kParam = null;
-
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- kParam = (RSAKeyParameters)rParam.getParameters();
- }
- else
- {
- kParam = (RSAKeyParameters)param;
- }
-
- engine.init(forEncryption, param);
-
- modulus = kParam.getModulus();
- bitSize = modulus.bitLength();
-
- this.forEncryption = forEncryption;
- }
-
- /**
- * return the input block size. The largest message we can process
- * is (key_size_in_bits + 3)/16, which in our world comes to
- * key_size_in_bytes / 2.
- */
- public int getInputBlockSize()
- {
- int baseBlockSize = engine.getInputBlockSize();
-
- if (forEncryption)
- {
- return (baseBlockSize + 1) / 2;
- }
- else
- {
- return baseBlockSize;
- }
- }
-
- /**
- * return the maximum possible size for the output.
- */
- public int getOutputBlockSize()
- {
- int baseBlockSize = engine.getOutputBlockSize();
-
- if (forEncryption)
- {
- return baseBlockSize;
- }
- else
- {
- return (baseBlockSize + 1) / 2;
- }
- }
-
- /**
- * set the number of bits in the next message to be treated as
- * pad bits.
- */
- public void setPadBits(
- int padBits)
- {
- if (padBits > 7)
- {
- throw new IllegalArgumentException("padBits > 7");
- }
-
- this.padBits = padBits;
- }
-
- /**
- * retrieve the number of pad bits in the last decoded message.
- */
- public int getPadBits()
- {
- return padBits;
- }
-
- public byte[] processBlock(
- byte[] in,
- int inOff,
- int inLen)
- throws InvalidCipherTextException
- {
- if (forEncryption)
- {
- return encodeBlock(in, inOff, inLen);
- }
- else
- {
- return decodeBlock(in, inOff, inLen);
- }
- }
-
- private byte[] encodeBlock(
- byte[] in,
- int inOff,
- int inLen)
- throws InvalidCipherTextException
- {
- byte[] block = new byte[(bitSize + 7) / 8];
- int r = padBits + 1;
- int z = inLen;
- int t = (bitSize + 13) / 16;
-
- for (int i = 0; i < t; i += z)
- {
- if (i > t - z)
- {
- System.arraycopy(in, inOff + inLen - (t - i),
- block, block.length - t, t - i);
- }
- else
- {
- System.arraycopy(in, inOff, block, block.length - (i + z), z);
- }
- }
-
- for (int i = block.length - 2 * t; i != block.length; i += 2)
- {
- byte val = block[block.length - t + i / 2];
-
- block[i] = (byte)((shadows[(val & 0xff) >>> 4] << 4)
- | shadows[val & 0x0f]);
- block[i + 1] = val;
- }
-
- block[block.length - 2 * z] ^= r;
- block[block.length - 1] = (byte)((block[block.length - 1] << 4) | 0x06);
-
- int maxBit = (8 - (bitSize - 1) % 8);
- int offSet = 0;
-
- if (maxBit != 8)
- {
- block[0] &= 0xff >>> maxBit;
- block[0] |= 0x80 >>> maxBit;
- }
- else
- {
- block[0] = 0x00;
- block[1] |= 0x80;
- offSet = 1;
- }
-
- return engine.processBlock(block, offSet, block.length - offSet);
- }
-
- /**
- * @exception InvalidCipherTextException if the decrypted block is not a valid ISO 9796 bit string
- */
- private byte[] decodeBlock(
- byte[] in,
- int inOff,
- int inLen)
- throws InvalidCipherTextException
- {
- byte[] block = engine.processBlock(in, inOff, inLen);
- int r = 1;
- int t = (bitSize + 13) / 16;
-
- BigInteger iS = new BigInteger(1, block);
- BigInteger iR;
- if (iS.mod(SIXTEEN).equals(SIX))
- {
- iR = iS;
- }
- else if ((modulus.subtract(iS)).mod(SIXTEEN).equals(SIX))
- {
- iR = modulus.subtract(iS);
- }
- else
- {
- throw new InvalidCipherTextException("resulting integer iS or (modulus - iS) is not congruent to 6 mod 16");
- }
-
- block = convertOutputDecryptOnly(iR);
-
- if ((block[block.length - 1] & 0x0f) != 0x6 )
- {
- throw new InvalidCipherTextException("invalid forcing byte in block");
- }
-
- block[block.length - 1] = (byte)(((block[block.length - 1] & 0xff) >>> 4) | ((inverse[(block[block.length - 2] & 0xff) >> 4]) << 4));
- block[0] = (byte)((shadows[(block[1] & 0xff) >>> 4] << 4)
- | shadows[block[1] & 0x0f]);
-
- boolean boundaryFound = false;
- int boundary = 0;
-
- for (int i = block.length - 1; i >= block.length - 2 * t; i -= 2)
- {
- int val = ((shadows[(block[i] & 0xff) >>> 4] << 4)
- | shadows[block[i] & 0x0f]);
-
- if (((block[i - 1] ^ val) & 0xff) != 0)
- {
- if (!boundaryFound)
- {
- boundaryFound = true;
- r = (block[i - 1] ^ val) & 0xff;
- boundary = i - 1;
- }
- else
- {
- throw new InvalidCipherTextException("invalid tsums in block");
- }
- }
- }
-
- block[boundary] = 0;
-
- byte[] nblock = new byte[(block.length - boundary) / 2];
-
- for (int i = 0; i < nblock.length; i++)
- {
- nblock[i] = block[2 * i + boundary + 1];
- }
-
- padBits = r - 1;
-
- return nblock;
- }
-
- private static byte[] convertOutputDecryptOnly(BigInteger result)
- {
- byte[] output = result.toByteArray();
- if (output[0] == 0) // have ended up with an extra zero byte, copy down.
- {
- byte[] tmp = new byte[output.length - 1];
- System.arraycopy(output, 1, tmp, 0, tmp.length);
- return tmp;
- }
- return output;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/encodings/OAEPEncoding.java b/core/src/main/java/org/bouncycastle/crypto/encodings/OAEPEncoding.java
deleted file mode 100644
index 17d8e3b0..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/encodings/OAEPEncoding.java
+++ /dev/null
@@ -1,357 +0,0 @@
-package org.bouncycastle.crypto.encodings;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-
-/**
- * Optimal Asymmetric Encryption Padding (OAEP) - see PKCS 1 V 2.
- */
-public class OAEPEncoding
- implements AsymmetricBlockCipher
-{
- private byte[] defHash;
- private Digest mgf1Hash;
-
- private AsymmetricBlockCipher engine;
- private SecureRandom random;
- private boolean forEncryption;
-
- public OAEPEncoding(
- AsymmetricBlockCipher cipher)
- {
- this(cipher, new SHA1Digest(), null);
- }
-
- public OAEPEncoding(
- AsymmetricBlockCipher cipher,
- Digest hash)
- {
- this(cipher, hash, null);
- }
-
- public OAEPEncoding(
- AsymmetricBlockCipher cipher,
- Digest hash,
- byte[] encodingParams)
- {
- this(cipher, hash, hash, encodingParams);
- }
-
- public OAEPEncoding(
- AsymmetricBlockCipher cipher,
- Digest hash,
- Digest mgf1Hash,
- byte[] encodingParams)
- {
- this.engine = cipher;
- this.mgf1Hash = mgf1Hash;
- this.defHash = new byte[hash.getDigestSize()];
-
- hash.reset();
-
- if (encodingParams != null)
- {
- hash.update(encodingParams, 0, encodingParams.length);
- }
-
- hash.doFinal(defHash, 0);
- }
-
- public AsymmetricBlockCipher getUnderlyingCipher()
- {
- return engine;
- }
-
- public void init(
- boolean forEncryption,
- CipherParameters param)
- {
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- this.random = rParam.getRandom();
- }
- else
- {
- this.random = new SecureRandom();
- }
-
- engine.init(forEncryption, param);
-
- this.forEncryption = forEncryption;
- }
-
- public int getInputBlockSize()
- {
- int baseBlockSize = engine.getInputBlockSize();
-
- if (forEncryption)
- {
- return baseBlockSize - 1 - 2 * defHash.length;
- }
- else
- {
- return baseBlockSize;
- }
- }
-
- public int getOutputBlockSize()
- {
- int baseBlockSize = engine.getOutputBlockSize();
-
- if (forEncryption)
- {
- return baseBlockSize;
- }
- else
- {
- return baseBlockSize - 1 - 2 * defHash.length;
- }
- }
-
- public byte[] processBlock(
- byte[] in,
- int inOff,
- int inLen)
- throws InvalidCipherTextException
- {
- if (forEncryption)
- {
- return encodeBlock(in, inOff, inLen);
- }
- else
- {
- return decodeBlock(in, inOff, inLen);
- }
- }
-
- public byte[] encodeBlock(
- byte[] in,
- int inOff,
- int inLen)
- throws InvalidCipherTextException
- {
- byte[] block = new byte[getInputBlockSize() + 1 + 2 * defHash.length];
-
- //
- // copy in the message
- //
- System.arraycopy(in, inOff, block, block.length - inLen, inLen);
-
- //
- // add sentinel
- //
- block[block.length - inLen - 1] = 0x01;
-
- //
- // as the block is already zeroed - there's no need to add PS (the >= 0 pad of 0)
- //
-
- //
- // add the hash of the encoding params.
- //
- System.arraycopy(defHash, 0, block, defHash.length, defHash.length);
-
- //
- // generate the seed.
- //
- byte[] seed = new byte[defHash.length];
-
- random.nextBytes(seed);
-
- //
- // mask the message block.
- //
- byte[] mask = maskGeneratorFunction1(seed, 0, seed.length, block.length - defHash.length);
-
- for (int i = defHash.length; i != block.length; i++)
- {
- block[i] ^= mask[i - defHash.length];
- }
-
- //
- // add in the seed
- //
- System.arraycopy(seed, 0, block, 0, defHash.length);
-
- //
- // mask the seed.
- //
- mask = maskGeneratorFunction1(
- block, defHash.length, block.length - defHash.length, defHash.length);
-
- for (int i = 0; i != defHash.length; i++)
- {
- block[i] ^= mask[i];
- }
-
- return engine.processBlock(block, 0, block.length);
- }
-
- /**
- * @exception InvalidCipherTextException if the decrypted block turns out to
- * be badly formatted.
- */
- public byte[] decodeBlock(
- byte[] in,
- int inOff,
- int inLen)
- throws InvalidCipherTextException
- {
- byte[] data = engine.processBlock(in, inOff, inLen);
- byte[] block;
-
- //
- // as we may have zeros in our leading bytes for the block we produced
- // on encryption, we need to make sure our decrypted block comes back
- // the same size.
- //
- if (data.length < engine.getOutputBlockSize())
- {
- block = new byte[engine.getOutputBlockSize()];
-
- System.arraycopy(data, 0, block, block.length - data.length, data.length);
- }
- else
- {
- block = data;
- }
-
- if (block.length < (2 * defHash.length) + 1)
- {
- throw new InvalidCipherTextException("data too short");
- }
-
- //
- // unmask the seed.
- //
- byte[] mask = maskGeneratorFunction1(
- block, defHash.length, block.length - defHash.length, defHash.length);
-
- for (int i = 0; i != defHash.length; i++)
- {
- block[i] ^= mask[i];
- }
-
- //
- // unmask the message block.
- //
- mask = maskGeneratorFunction1(block, 0, defHash.length, block.length - defHash.length);
-
- for (int i = defHash.length; i != block.length; i++)
- {
- block[i] ^= mask[i - defHash.length];
- }
-
- //
- // check the hash of the encoding params.
- // long check to try to avoid this been a source of a timing attack.
- //
- boolean defHashWrong = false;
-
- for (int i = 0; i != defHash.length; i++)
- {
- if (defHash[i] != block[defHash.length + i])
- {
- defHashWrong = true;
- }
- }
-
- if (defHashWrong)
- {
- throw new InvalidCipherTextException("data hash wrong");
- }
-
- //
- // find the data block
- //
- int start;
-
- for (start = 2 * defHash.length; start != block.length; start++)
- {
- if (block[start] != 0)
- {
- break;
- }
- }
-
- if (start >= (block.length - 1) || block[start] != 1)
- {
- throw new InvalidCipherTextException("data start wrong " + start);
- }
-
- start++;
-
- //
- // extract the data block
- //
- byte[] output = new byte[block.length - start];
-
- System.arraycopy(block, start, output, 0, output.length);
-
- return output;
- }
-
- /**
- * int to octet string.
- */
- private void ItoOSP(
- int i,
- byte[] sp)
- {
- sp[0] = (byte)(i >>> 24);
- sp[1] = (byte)(i >>> 16);
- sp[2] = (byte)(i >>> 8);
- sp[3] = (byte)(i >>> 0);
- }
-
- /**
- * mask generator function, as described in PKCS1v2.
- */
- private byte[] maskGeneratorFunction1(
- byte[] Z,
- int zOff,
- int zLen,
- int length)
- {
- byte[] mask = new byte[length];
- byte[] hashBuf = new byte[mgf1Hash.getDigestSize()];
- byte[] C = new byte[4];
- int counter = 0;
-
- mgf1Hash.reset();
-
- while (counter < (length / hashBuf.length))
- {
- ItoOSP(counter, C);
-
- mgf1Hash.update(Z, zOff, zLen);
- mgf1Hash.update(C, 0, C.length);
- mgf1Hash.doFinal(hashBuf, 0);
-
- System.arraycopy(hashBuf, 0, mask, counter * hashBuf.length, hashBuf.length);
-
- counter++;
- }
-
- if ((counter * hashBuf.length) < length)
- {
- ItoOSP(counter, C);
-
- mgf1Hash.update(Z, zOff, zLen);
- mgf1Hash.update(C, 0, C.length);
- mgf1Hash.doFinal(hashBuf, 0);
-
- System.arraycopy(hashBuf, 0, mask, counter * hashBuf.length, mask.length - (counter * hashBuf.length));
- }
-
- return mask;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java b/core/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
deleted file mode 100644
index dec40f01..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
+++ /dev/null
@@ -1,418 +0,0 @@
-package org.bouncycastle.crypto.encodings;
-
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-
-/**
- * this does your basic PKCS 1 v1.5 padding - whether or not you should be using this
- * depends on your application - see PKCS1 Version 2 for details.
- */
-public class PKCS1Encoding
- implements AsymmetricBlockCipher
-{
- /**
- * some providers fail to include the leading zero in PKCS1 encoded blocks. If you need to
- * work with one of these set the system property org.bouncycastle.pkcs1.strict to false.
- * <p>
- * The system property is checked during construction of the encoding object, it is set to
- * true by default.
- * </p>
- */
- public static final String STRICT_LENGTH_ENABLED_PROPERTY = "org.bouncycastle.pkcs1.strict";
-
- private static final int HEADER_LENGTH = 10;
-
- private SecureRandom random;
- private AsymmetricBlockCipher engine;
- private boolean forEncryption;
- private boolean forPrivateKey;
- private boolean useStrictLength;
- private int pLen = -1;
- private byte[] fallback = null;
-
- /**
- * Basic constructor.
- * @param cipher
- */
- public PKCS1Encoding(
- AsymmetricBlockCipher cipher)
- {
- this.engine = cipher;
- this.useStrictLength = useStrict();
- }
-
- /**
- * Constructor for decryption with a fixed plaintext length.
- *
- * @param cipher The cipher to use for cryptographic operation.
- * @param pLen Length of the expected plaintext.
- */
- public PKCS1Encoding(
- AsymmetricBlockCipher cipher,
- int pLen)
- {
- this.engine = cipher;
- this.useStrictLength = useStrict();
- this.pLen = pLen;
- }
-
- /**
- * Constructor for decryption with a fixed plaintext length and a fallback
- * value that is returned, if the padding is incorrect.
- *
- * @param cipher
- * The cipher to use for cryptographic operation.
- * @param fallback
- * The fallback value, we don't to a arraycopy here.
- */
- public PKCS1Encoding(
- AsymmetricBlockCipher cipher,
- byte[] fallback)
- {
- this.engine = cipher;
- this.useStrictLength = useStrict();
- this.fallback = fallback;
- this.pLen = fallback.length;
- }
-
-
-
- //
- // for J2ME compatibility
- //
- private boolean useStrict()
- {
- // required if security manager has been installed.
- String strict = (String)AccessController.doPrivileged(new PrivilegedAction()
- {
- public Object run()
- {
- return System.getProperty(STRICT_LENGTH_ENABLED_PROPERTY);
- }
- });
-
- return strict == null || strict.equals("true");
- }
-
- public AsymmetricBlockCipher getUnderlyingCipher()
- {
- return engine;
- }
-
- public void init(
- boolean forEncryption,
- CipherParameters param)
- {
- AsymmetricKeyParameter kParam;
-
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- this.random = rParam.getRandom();
- kParam = (AsymmetricKeyParameter)rParam.getParameters();
- }
- else
- {
- this.random = new SecureRandom();
- kParam = (AsymmetricKeyParameter)param;
- }
-
- engine.init(forEncryption, param);
-
- this.forPrivateKey = kParam.isPrivate();
- this.forEncryption = forEncryption;
- }
-
- public int getInputBlockSize()
- {
- int baseBlockSize = engine.getInputBlockSize();
-
- if (forEncryption)
- {
- return baseBlockSize - HEADER_LENGTH;
- }
- else
- {
- return baseBlockSize;
- }
- }
-
- public int getOutputBlockSize()
- {
- int baseBlockSize = engine.getOutputBlockSize();
-
- if (forEncryption)
- {
- return baseBlockSize;
- }
- else
- {
- return baseBlockSize - HEADER_LENGTH;
- }
- }
-
- public byte[] processBlock(
- byte[] in,
- int inOff,
- int inLen)
- throws InvalidCipherTextException
- {
- if (forEncryption)
- {
- return encodeBlock(in, inOff, inLen);
- }
- else
- {
- return decodeBlock(in, inOff, inLen);
- }
- }
-
- private byte[] encodeBlock(
- byte[] in,
- int inOff,
- int inLen)
- throws InvalidCipherTextException
- {
- if (inLen > getInputBlockSize())
- {
- throw new IllegalArgumentException("input data too large");
- }
-
- byte[] block = new byte[engine.getInputBlockSize()];
-
- if (forPrivateKey)
- {
- block[0] = 0x01; // type code 1
-
- for (int i = 1; i != block.length - inLen - 1; i++)
- {
- block[i] = (byte)0xFF;
- }
- }
- else
- {
- random.nextBytes(block); // random fill
-
- block[0] = 0x02; // type code 2
-
- //
- // a zero byte marks the end of the padding, so all
- // the pad bytes must be non-zero.
- //
- for (int i = 1; i != block.length - inLen - 1; i++)
- {
- while (block[i] == 0)
- {
- block[i] = (byte)random.nextInt();
- }
- }
- }
-
- block[block.length - inLen - 1] = 0x00; // mark the end of the padding
- System.arraycopy(in, inOff, block, block.length - inLen, inLen);
-
- return engine.processBlock(block, 0, block.length);
- }
-
- /**
- * Checks if the argument is a correctly PKCS#1.5 encoded Plaintext
- * for encryption.
- *
- * @param encoded The Plaintext.
- * @param pLen Expected length of the plaintext.
- * @return Either 0, if the encoding is correct, or -1, if it is incorrect.
- */
- private static int checkPkcs1Encoding(byte[] encoded, int pLen) {
- int correct = 0;
- /*
- * Check if the first two bytes are 0 2
- */
- correct |= (encoded[0] ^ 2);
-
- /*
- * Now the padding check, check for no 0 byte in the padding
- */
- int plen = encoded.length - (
- pLen /* Lenght of the PMS */
- + 1 /* Final 0-byte before PMS */
- );
-
- for (int i = 1; i < plen; i++) {
- int tmp = encoded[i];
- tmp |= tmp >> 1;
- tmp |= tmp >> 2;
- tmp |= tmp >> 4;
- correct |= (tmp & 1) - 1;
- }
-
- /*
- * Make sure the padding ends with a 0 byte.
- */
- correct |= encoded[encoded.length - (pLen +1)];
-
- /*
- * Return 0 or 1, depending on the result.
- */
- correct |= correct >> 1;
- correct |= correct >> 2;
- correct |= correct >> 4;
- return ~((correct & 1) - 1);
- }
-
-
- /**
- * Decode PKCS#1.5 encoding, and return a random value if the padding is not correct.
- *
- * @param in The encrypted block.
- * @param inOff Offset in the encrypted block.
- * @param inLen Length of the encrypted block.
- * //@param pLen Length of the desired output.
- * @return The plaintext without padding, or a random value if the padding was incorrect.
- *
- * @throws InvalidCipherTextException
- */
- private byte[] decodeBlockOrRandom(byte[] in, int inOff, int inLen)
- throws InvalidCipherTextException
- {
- if (!forPrivateKey)
- {
- throw new InvalidCipherTextException("sorry, this method is only for decryption, not for signing");
- }
-
- byte[] block = engine.processBlock(in, inOff, inLen);
- byte[] random = null;
- if (this.fallback == null)
- {
- random = new byte[this.pLen];
- this.random.nextBytes(random);
- }
- else
- {
- random = fallback;
- }
-
- /*
- * TODO: This is a potential dangerous side channel. However, you can
- * fix this by changing the RSA engine in a way, that it will always
- * return blocks of the same length and prepend them with 0 bytes if
- * needed.
- */
- if (block.length < getOutputBlockSize())
- {
- throw new InvalidCipherTextException("block truncated");
- }
-
- /*
- * TODO: Potential side channel. Fix it by making the engine always
- * return blocks of the correct length.
- */
- if (useStrictLength && block.length != engine.getOutputBlockSize())
- {
- throw new InvalidCipherTextException("block incorrect size");
- }
-
- /*
- * Check the padding.
- */
- int correct = PKCS1Encoding.checkPkcs1Encoding(block, this.pLen);
-
- /*
- * Now, to a constant time constant memory copy of the decrypted value
- * or the random value, depending on the validity of the padding.
- */
- byte[] result = new byte[this.pLen];
- for (int i = 0; i < this.pLen; i++)
- {
- result[i] = (byte)((block[i + (block.length - pLen)] & (~correct)) | (random[i] & correct));
- }
-
- return result;
- }
-
- /**
- * @exception InvalidCipherTextException if the decrypted block is not in PKCS1 format.
- */
- private byte[] decodeBlock(
- byte[] in,
- int inOff,
- int inLen)
- throws InvalidCipherTextException
- {
- /*
- * If the length of the expected plaintext is known, we use a constant-time decryption.
- * If the decryption fails, we return a random value.
- */
- if (this.pLen != -1) {
- return this.decodeBlockOrRandom(in, inOff, inLen);
- }
-
- byte[] block = engine.processBlock(in, inOff, inLen);
-
- if (block.length < getOutputBlockSize())
- {
- throw new InvalidCipherTextException("block truncated");
- }
-
- byte type = block[0];
-
- if (forPrivateKey)
- {
- if (type != 2)
- {
- throw new InvalidCipherTextException("unknown block type");
- }
- }
- else
- {
- if (type != 1)
- {
- throw new InvalidCipherTextException("unknown block type");
- }
- }
-
- if (useStrictLength && block.length != engine.getOutputBlockSize())
- {
- throw new InvalidCipherTextException("block incorrect size");
- }
-
- //
- // find and extract the message block.
- //
- int start;
-
- for (start = 1; start != block.length; start++)
- {
- byte pad = block[start];
-
- if (pad == 0)
- {
- break;
- }
- if (type == 1 && pad != (byte)0xff)
- {
- throw new InvalidCipherTextException("block padding incorrect");
- }
- }
-
- start++; // data should start at the next byte
-
- if (start > block.length || start < HEADER_LENGTH)
- {
- throw new InvalidCipherTextException("no data in block");
- }
-
- byte[] result = new byte[block.length - start];
-
- System.arraycopy(block, start, result, 0, result.length);
-
- return result;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java
deleted file mode 100644
index a0fd0840..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java
+++ /dev/null
@@ -1,537 +0,0 @@
-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;
-
-/**
- * an implementation of the AES (Rijndael), from FIPS-197.
- * <p>
- * For further details see: <a href="http://csrc.nist.gov/encryption/aes/">http://csrc.nist.gov/encryption/aes/</a>.
- *
- * This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at
- * <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
- *
- * There are three levels of tradeoff of speed vs memory
- * Because java has no preprocessor, they are written as three separate classes from which to choose
- *
- * The fastest uses 8Kbytes of static tables to precompute round calculations, 4 256 word tables for encryption
- * and 4 for decryption.
- *
- * The middle performance version uses only one 256 word table for each, for a total of 2Kbytes,
- * adding 12 rotate operations per round to compute the values contained in the other tables from
- * the contents of the first.
- *
- * The slowest version uses no static tables at all and computes the values in each round.
- * <p>
- * This file contains the middle performance version with 2Kbytes of static tables for round precomputation.
- *
- */
-public class AESEngine
- implements BlockCipher
-{
- // The S box
- private static final byte[] S = {
- (byte)99, (byte)124, (byte)119, (byte)123, (byte)242, (byte)107, (byte)111, (byte)197,
- (byte)48, (byte)1, (byte)103, (byte)43, (byte)254, (byte)215, (byte)171, (byte)118,
- (byte)202, (byte)130, (byte)201, (byte)125, (byte)250, (byte)89, (byte)71, (byte)240,
- (byte)173, (byte)212, (byte)162, (byte)175, (byte)156, (byte)164, (byte)114, (byte)192,
- (byte)183, (byte)253, (byte)147, (byte)38, (byte)54, (byte)63, (byte)247, (byte)204,
- (byte)52, (byte)165, (byte)229, (byte)241, (byte)113, (byte)216, (byte)49, (byte)21,
- (byte)4, (byte)199, (byte)35, (byte)195, (byte)24, (byte)150, (byte)5, (byte)154,
- (byte)7, (byte)18, (byte)128, (byte)226, (byte)235, (byte)39, (byte)178, (byte)117,
- (byte)9, (byte)131, (byte)44, (byte)26, (byte)27, (byte)110, (byte)90, (byte)160,
- (byte)82, (byte)59, (byte)214, (byte)179, (byte)41, (byte)227, (byte)47, (byte)132,
- (byte)83, (byte)209, (byte)0, (byte)237, (byte)32, (byte)252, (byte)177, (byte)91,
- (byte)106, (byte)203, (byte)190, (byte)57, (byte)74, (byte)76, (byte)88, (byte)207,
- (byte)208, (byte)239, (byte)170, (byte)251, (byte)67, (byte)77, (byte)51, (byte)133,
- (byte)69, (byte)249, (byte)2, (byte)127, (byte)80, (byte)60, (byte)159, (byte)168,
- (byte)81, (byte)163, (byte)64, (byte)143, (byte)146, (byte)157, (byte)56, (byte)245,
- (byte)188, (byte)182, (byte)218, (byte)33, (byte)16, (byte)255, (byte)243, (byte)210,
- (byte)205, (byte)12, (byte)19, (byte)236, (byte)95, (byte)151, (byte)68, (byte)23,
- (byte)196, (byte)167, (byte)126, (byte)61, (byte)100, (byte)93, (byte)25, (byte)115,
- (byte)96, (byte)129, (byte)79, (byte)220, (byte)34, (byte)42, (byte)144, (byte)136,
- (byte)70, (byte)238, (byte)184, (byte)20, (byte)222, (byte)94, (byte)11, (byte)219,
- (byte)224, (byte)50, (byte)58, (byte)10, (byte)73, (byte)6, (byte)36, (byte)92,
- (byte)194, (byte)211, (byte)172, (byte)98, (byte)145, (byte)149, (byte)228, (byte)121,
- (byte)231, (byte)200, (byte)55, (byte)109, (byte)141, (byte)213, (byte)78, (byte)169,
- (byte)108, (byte)86, (byte)244, (byte)234, (byte)101, (byte)122, (byte)174, (byte)8,
- (byte)186, (byte)120, (byte)37, (byte)46, (byte)28, (byte)166, (byte)180, (byte)198,
- (byte)232, (byte)221, (byte)116, (byte)31, (byte)75, (byte)189, (byte)139, (byte)138,
- (byte)112, (byte)62, (byte)181, (byte)102, (byte)72, (byte)3, (byte)246, (byte)14,
- (byte)97, (byte)53, (byte)87, (byte)185, (byte)134, (byte)193, (byte)29, (byte)158,
- (byte)225, (byte)248, (byte)152, (byte)17, (byte)105, (byte)217, (byte)142, (byte)148,
- (byte)155, (byte)30, (byte)135, (byte)233, (byte)206, (byte)85, (byte)40, (byte)223,
- (byte)140, (byte)161, (byte)137, (byte)13, (byte)191, (byte)230, (byte)66, (byte)104,
- (byte)65, (byte)153, (byte)45, (byte)15, (byte)176, (byte)84, (byte)187, (byte)22,
- };
-
- // The inverse S-box
- private static final byte[] Si = {
- (byte)82, (byte)9, (byte)106, (byte)213, (byte)48, (byte)54, (byte)165, (byte)56,
- (byte)191, (byte)64, (byte)163, (byte)158, (byte)129, (byte)243, (byte)215, (byte)251,
- (byte)124, (byte)227, (byte)57, (byte)130, (byte)155, (byte)47, (byte)255, (byte)135,
- (byte)52, (byte)142, (byte)67, (byte)68, (byte)196, (byte)222, (byte)233, (byte)203,
- (byte)84, (byte)123, (byte)148, (byte)50, (byte)166, (byte)194, (byte)35, (byte)61,
- (byte)238, (byte)76, (byte)149, (byte)11, (byte)66, (byte)250, (byte)195, (byte)78,
- (byte)8, (byte)46, (byte)161, (byte)102, (byte)40, (byte)217, (byte)36, (byte)178,
- (byte)118, (byte)91, (byte)162, (byte)73, (byte)109, (byte)139, (byte)209, (byte)37,
- (byte)114, (byte)248, (byte)246, (byte)100, (byte)134, (byte)104, (byte)152, (byte)22,
- (byte)212, (byte)164, (byte)92, (byte)204, (byte)93, (byte)101, (byte)182, (byte)146,
- (byte)108, (byte)112, (byte)72, (byte)80, (byte)253, (byte)237, (byte)185, (byte)218,
- (byte)94, (byte)21, (byte)70, (byte)87, (byte)167, (byte)141, (byte)157, (byte)132,
- (byte)144, (byte)216, (byte)171, (byte)0, (byte)140, (byte)188, (byte)211, (byte)10,
- (byte)247, (byte)228, (byte)88, (byte)5, (byte)184, (byte)179, (byte)69, (byte)6,
- (byte)208, (byte)44, (byte)30, (byte)143, (byte)202, (byte)63, (byte)15, (byte)2,
- (byte)193, (byte)175, (byte)189, (byte)3, (byte)1, (byte)19, (byte)138, (byte)107,
- (byte)58, (byte)145, (byte)17, (byte)65, (byte)79, (byte)103, (byte)220, (byte)234,
- (byte)151, (byte)242, (byte)207, (byte)206, (byte)240, (byte)180, (byte)230, (byte)115,
- (byte)150, (byte)172, (byte)116, (byte)34, (byte)231, (byte)173, (byte)53, (byte)133,
- (byte)226, (byte)249, (byte)55, (byte)232, (byte)28, (byte)117, (byte)223, (byte)110,
- (byte)71, (byte)241, (byte)26, (byte)113, (byte)29, (byte)41, (byte)197, (byte)137,
- (byte)111, (byte)183, (byte)98, (byte)14, (byte)170, (byte)24, (byte)190, (byte)27,
- (byte)252, (byte)86, (byte)62, (byte)75, (byte)198, (byte)210, (byte)121, (byte)32,
- (byte)154, (byte)219, (byte)192, (byte)254, (byte)120, (byte)205, (byte)90, (byte)244,
- (byte)31, (byte)221, (byte)168, (byte)51, (byte)136, (byte)7, (byte)199, (byte)49,
- (byte)177, (byte)18, (byte)16, (byte)89, (byte)39, (byte)128, (byte)236, (byte)95,
- (byte)96, (byte)81, (byte)127, (byte)169, (byte)25, (byte)181, (byte)74, (byte)13,
- (byte)45, (byte)229, (byte)122, (byte)159, (byte)147, (byte)201, (byte)156, (byte)239,
- (byte)160, (byte)224, (byte)59, (byte)77, (byte)174, (byte)42, (byte)245, (byte)176,
- (byte)200, (byte)235, (byte)187, (byte)60, (byte)131, (byte)83, (byte)153, (byte)97,
- (byte)23, (byte)43, (byte)4, (byte)126, (byte)186, (byte)119, (byte)214, (byte)38,
- (byte)225, (byte)105, (byte)20, (byte)99, (byte)85, (byte)33, (byte)12, (byte)125,
- };
-
- // vector used in calculating key schedule (powers of x in GF(256))
- private static final int[] rcon = {
- 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
- 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 };
-
- // precomputation tables of calculations for rounds
- private static final int[] T0 =
- {
- 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff,
- 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102,
- 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d,
- 0x9a7676ec, 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa,
- 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, 0xecadad41,
- 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453,
- 0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d,
- 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83,
- 0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9, 0x937171e2,
- 0x73d8d8ab, 0x53313162, 0x3f15152a, 0x0c040408, 0x52c7c795,
- 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0x0f05050a,
- 0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
- 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912,
- 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc,
- 0xee5a5ab4, 0xfba0a05b, 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7,
- 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413,
- 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, 0x60202040,
- 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d,
- 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0,
- 0x4acfcf85, 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed,
- 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, 0xcf45458a,
- 0x10f9f9e9, 0x06020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78,
- 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d, 0xc0404080,
- 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
- 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020,
- 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18,
- 0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488,
- 0x3917172e, 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a,
- 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, 0xa06060c0,
- 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54,
- 0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b,
- 0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad,
- 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992,
- 0x0a06060c, 0x6c242448, 0xe45c5cb8, 0x5dc2c29f, 0x6ed3d3bd,
- 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3,
- 0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
- 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8,
- 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4,
- 0xe9aeae47, 0x18080810, 0xd5baba6f, 0x887878f0, 0x6f25254a,
- 0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697,
- 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96,
- 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c,
- 0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x05030306, 0x01f6f6f7,
- 0x120e0e1c, 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969,
- 0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9,
- 0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9,
- 0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c, 0x92878715,
- 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
- 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65,
- 0x31e6e6d7, 0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929,
- 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d,
- 0x3a16162c};
-
-private static final int[] Tinv0 =
- {
- 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b,
- 0xf1459d1f, 0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad,
- 0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526,
- 0x8fa362b5, 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d,
- 0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, 0xe75f8f03,
- 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458,
- 0x2969e049, 0x44c8c98e, 0x6a89c275, 0x78798ef4, 0x6b3e5899,
- 0xdd71b927, 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d,
- 0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362, 0xe07764b1,
- 0x84ae6bbb, 0x1ca081fe, 0x942b08f9, 0x58684870, 0x19fd458f,
- 0x876cde94, 0xb7f87b52, 0x23d373ab, 0xe2024b72, 0x578f1fe3,
- 0x2aab5566, 0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3,
- 0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a,
- 0x92b479a7, 0xf0f207f3, 0xa1e2694e, 0xcdf4da65, 0xd5be0506,
- 0x1f6234d1, 0x8afea6c4, 0x9d532e34, 0xa055f3a2, 0x32e18a05,
- 0x75ebf6a4, 0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd,
- 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, 0xb58d5491,
- 0x055dc471, 0x6fd40604, 0xff155060, 0x24fb9819, 0x97e9bdd6,
- 0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7,
- 0xdbeec879, 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000,
- 0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, 0xfbff0efd,
- 0x5638850f, 0x1ed5ae3d, 0x27392d36, 0x64d90f0a, 0x21a65c68,
- 0xd1545b9b, 0x3a2e3624, 0xb1670a0c, 0x0fe75793, 0xd296eeb4,
- 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c,
- 0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 0x0b0d090e,
- 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, 0x8519f157, 0x4c0775af,
- 0xbbdd99ee, 0xfd607fa3, 0x9f2601f7, 0xbcf5725c, 0xc53b6644,
- 0x347efb5b, 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8,
- 0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684, 0x7d244a85,
- 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc,
- 0xec52860d, 0xd0e3c177, 0x6c16b32b, 0x99b970a9, 0xfa489411,
- 0x2264e947, 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322,
- 0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, 0xcf81f5a6,
- 0x28de7aa5, 0x268eb7da, 0xa4bfad3f, 0xe49d3a2c, 0x0d927850,
- 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890, 0x5ef7392e,
- 0xf5afc382, 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf,
- 0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 0x097826cd,
- 0xf418596e, 0x01b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa,
- 0x08cfbc21, 0xe6e815ef, 0xd99be7ba, 0xce366f4a, 0xd4099fea,
- 0xd67cb029, 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235,
- 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, 0x4a9804f1,
- 0xf7daec41, 0x0e50cd7f, 0x2ff69117, 0x8dd64d76, 0x4db0ef43,
- 0x544daacc, 0xdf0496e4, 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1,
- 0x7f516546, 0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb,
- 0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d, 0x8c61d79a,
- 0x7a0ca137, 0x8e14f859, 0x893c13eb, 0xee27a9ce, 0x35c961b7,
- 0xede51ce1, 0x3cb1477a, 0x59dfd29c, 0x3f73f255, 0x79ce1418,
- 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478,
- 0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16,
- 0x0c25e2bc, 0x8b493c28, 0x41950dff, 0x7101a839, 0xdeb30c08,
- 0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48,
- 0x4257b8d0};
-
- private static int shift(int r, int shift)
- {
- return (r >>> shift) | (r << -shift);
- }
-
- /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */
-
- private static final int m1 = 0x80808080;
- private static final int m2 = 0x7f7f7f7f;
- private static final int m3 = 0x0000001b;
-
- private static int FFmulX(int x)
- {
- return (((x & m2) << 1) ^ (((x & m1) >>> 7) * m3));
- }
-
- /*
- The following defines provide alternative definitions of FFmulX that might
- give improved performance if a fast 32-bit multiply is not available.
-
- private int FFmulX(int x) { int u = x & m1; u |= (u >> 1); return ((x & m2) << 1) ^ ((u >>> 3) | (u >>> 6)); }
- private static final int m4 = 0x1b1b1b1b;
- private int FFmulX(int x) { int u = x & m1; return ((x & m2) << 1) ^ ((u - (u >>> 7)) & m4); }
-
- */
-
- private static int inv_mcol(int x)
- {
- int f2 = FFmulX(x);
- int f4 = FFmulX(f2);
- int f8 = FFmulX(f4);
- int f9 = x ^ f8;
-
- return f2 ^ f4 ^ f8 ^ shift(f2 ^ f9, 8) ^ shift(f4 ^ f9, 16) ^ shift(f9, 24);
- }
-
- private static int subWord(int x)
- {
- return (S[x&255]&255 | ((S[(x>>8)&255]&255)<<8) | ((S[(x>>16)&255]&255)<<16) | S[(x>>24)&255]<<24);
- }
-
- /**
- * Calculate the necessary round keys
- * The number of calculations depends on key size and block size
- * AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
- * This code is written assuming those are the only possible values
- */
- private int[][] generateWorkingKey(
- byte[] key,
- boolean forEncryption)
- {
- int KC = key.length / 4; // key length in words
- int t;
-
- if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.length))
- {
- throw new IllegalArgumentException("Key length not 128/192/256 bits.");
- }
-
- ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes
- int[][] W = new int[ROUNDS+1][4]; // 4 words in a block
-
- //
- // copy the key into the round key array
- //
-
- t = 0;
- int i = 0;
- while (i < key.length)
- {
- W[t >> 2][t & 3] = (key[i]&0xff) | ((key[i+1]&0xff) << 8) | ((key[i+2]&0xff) << 16) | (key[i+3] << 24);
- i+=4;
- t++;
- }
-
- //
- // while not enough round key material calculated
- // calculate new values
- //
- int k = (ROUNDS + 1) << 2;
- for (i = KC; (i < k); i++)
- {
- int temp = W[(i-1)>>2][(i-1)&3];
- if ((i % KC) == 0)
- {
- temp = subWord(shift(temp, 8)) ^ rcon[(i / KC)-1];
- }
- else if ((KC > 6) && ((i % KC) == 4))
- {
- temp = subWord(temp);
- }
-
- W[i>>2][i&3] = W[(i - KC)>>2][(i-KC)&3] ^ temp;
- }
-
- if (!forEncryption)
- {
- for (int j = 1; j < ROUNDS; j++)
- {
- for (i = 0; i < 4; i++)
- {
- W[j][i] = inv_mcol(W[j][i]);
- }
- }
- }
-
- return W;
- }
-
- private int ROUNDS;
- private int[][] WorkingKey = null;
- private int C0, C1, C2, C3;
- private boolean forEncryption;
-
- private static final int BLOCK_SIZE = 16;
-
- /**
- * default constructor - 128 bit block size.
- */
- public AESEngine()
- {
- }
-
- /**
- * initialise an AES cipher.
- *
- * @param forEncryption whether or not we are for encryption.
- * @param params the parameters required to set up the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean forEncryption,
- CipherParameters params)
- {
- if (params instanceof KeyParameter)
- {
- WorkingKey = generateWorkingKey(((KeyParameter)params).getKey(), forEncryption);
- this.forEncryption = forEncryption;
- return;
- }
-
- throw new IllegalArgumentException("invalid parameter passed to AES init - " + params.getClass().getName());
- }
-
- public String getAlgorithmName()
- {
- return "AES";
- }
-
- public int getBlockSize()
- {
- return BLOCK_SIZE;
- }
-
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- if (WorkingKey == null)
- {
- throw new IllegalStateException("AES engine not initialised");
- }
-
- if ((inOff + (32 / 2)) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + (32 / 2)) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- if (forEncryption)
- {
- unpackBlock(in, inOff);
- encryptBlock(WorkingKey);
- packBlock(out, outOff);
- }
- else
- {
- unpackBlock(in, inOff);
- decryptBlock(WorkingKey);
- packBlock(out, outOff);
- }
-
- return BLOCK_SIZE;
- }
-
- public void reset()
- {
- }
-
- private void unpackBlock(
- byte[] bytes,
- int off)
- {
- int index = off;
-
- C0 = (bytes[index++] & 0xff);
- C0 |= (bytes[index++] & 0xff) << 8;
- C0 |= (bytes[index++] & 0xff) << 16;
- C0 |= bytes[index++] << 24;
-
- C1 = (bytes[index++] & 0xff);
- C1 |= (bytes[index++] & 0xff) << 8;
- C1 |= (bytes[index++] & 0xff) << 16;
- C1 |= bytes[index++] << 24;
-
- C2 = (bytes[index++] & 0xff);
- C2 |= (bytes[index++] & 0xff) << 8;
- C2 |= (bytes[index++] & 0xff) << 16;
- C2 |= bytes[index++] << 24;
-
- C3 = (bytes[index++] & 0xff);
- C3 |= (bytes[index++] & 0xff) << 8;
- C3 |= (bytes[index++] & 0xff) << 16;
- C3 |= bytes[index++] << 24;
- }
-
- private void packBlock(
- byte[] bytes,
- int off)
- {
- int index = off;
-
- bytes[index++] = (byte)C0;
- bytes[index++] = (byte)(C0 >> 8);
- bytes[index++] = (byte)(C0 >> 16);
- bytes[index++] = (byte)(C0 >> 24);
-
- bytes[index++] = (byte)C1;
- bytes[index++] = (byte)(C1 >> 8);
- bytes[index++] = (byte)(C1 >> 16);
- bytes[index++] = (byte)(C1 >> 24);
-
- bytes[index++] = (byte)C2;
- bytes[index++] = (byte)(C2 >> 8);
- bytes[index++] = (byte)(C2 >> 16);
- bytes[index++] = (byte)(C2 >> 24);
-
- bytes[index++] = (byte)C3;
- bytes[index++] = (byte)(C3 >> 8);
- bytes[index++] = (byte)(C3 >> 16);
- bytes[index++] = (byte)(C3 >> 24);
- }
-
-
- private void encryptBlock(int[][] KW)
- {
- int t0 = this.C0 ^ KW[0][0];
- int t1 = this.C1 ^ KW[0][1];
- int t2 = this.C2 ^ KW[0][2];
-
- int r = 1, r0, r1, r2, r3 = this.C3 ^ KW[0][3];
- while (r < ROUNDS - 1)
- {
- r0 = T0[t0&255] ^ shift(T0[(t1>>8)&255], 24) ^ shift(T0[(t2>>16)&255], 16) ^ shift(T0[(r3>>24)&255], 8) ^ KW[r][0];
- r1 = T0[t1&255] ^ shift(T0[(t2>>8)&255], 24) ^ shift(T0[(r3>>16)&255], 16) ^ shift(T0[(t0>>24)&255], 8) ^ KW[r][1];
- r2 = T0[t2&255] ^ shift(T0[(r3>>8)&255], 24) ^ shift(T0[(t0>>16)&255], 16) ^ shift(T0[(t1>>24)&255], 8) ^ KW[r][2];
- r3 = T0[r3&255] ^ shift(T0[(t0>>8)&255], 24) ^ shift(T0[(t1>>16)&255], 16) ^ shift(T0[(t2>>24)&255], 8) ^ KW[r++][3];
- t0 = T0[r0&255] ^ shift(T0[(r1>>8)&255], 24) ^ shift(T0[(r2>>16)&255], 16) ^ shift(T0[(r3>>24)&255], 8) ^ KW[r][0];
- t1 = T0[r1&255] ^ shift(T0[(r2>>8)&255], 24) ^ shift(T0[(r3>>16)&255], 16) ^ shift(T0[(r0>>24)&255], 8) ^ KW[r][1];
- t2 = T0[r2&255] ^ shift(T0[(r3>>8)&255], 24) ^ shift(T0[(r0>>16)&255], 16) ^ shift(T0[(r1>>24)&255], 8) ^ KW[r][2];
- r3 = T0[r3&255] ^ shift(T0[(r0>>8)&255], 24) ^ shift(T0[(r1>>16)&255], 16) ^ shift(T0[(r2>>24)&255], 8) ^ KW[r++][3];
- }
-
- r0 = T0[t0&255] ^ shift(T0[(t1>>8)&255], 24) ^ shift(T0[(t2>>16)&255], 16) ^ shift(T0[(r3>>24)&255], 8) ^ KW[r][0];
- r1 = T0[t1&255] ^ shift(T0[(t2>>8)&255], 24) ^ shift(T0[(r3>>16)&255], 16) ^ shift(T0[(t0>>24)&255], 8) ^ KW[r][1];
- r2 = T0[t2&255] ^ shift(T0[(r3>>8)&255], 24) ^ shift(T0[(t0>>16)&255], 16) ^ shift(T0[(t1>>24)&255], 8) ^ KW[r][2];
- r3 = T0[r3&255] ^ shift(T0[(t0>>8)&255], 24) ^ shift(T0[(t1>>16)&255], 16) ^ shift(T0[(t2>>24)&255], 8) ^ KW[r++][3];
-
- // the final round's table is a simple function of S so we don't use a whole other four tables for it
-
- this.C0 = (S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((S[(r2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24) ^ KW[r][0];
- this.C1 = (S[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(r0>>24)&255]<<24) ^ KW[r][1];
- this.C2 = (S[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24) ^ KW[r][2];
- this.C3 = (S[r3&255]&255) ^ ((S[(r0>>8)&255]&255)<<8) ^ ((S[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24) ^ KW[r][3];
- }
-
- private void decryptBlock(int[][] KW)
- {
- int t0 = this.C0 ^ KW[ROUNDS][0];
- int t1 = this.C1 ^ KW[ROUNDS][1];
- int t2 = this.C2 ^ KW[ROUNDS][2];
-
- int r = ROUNDS - 1, r0, r1, r2, r3 = this.C3 ^ KW[ROUNDS][3];
- while (r > 1)
- {
- r0 = Tinv0[t0&255] ^ shift(Tinv0[(r3>>8)&255], 24) ^ shift(Tinv0[(t2>>16)&255], 16) ^ shift(Tinv0[(t1>>24)&255], 8) ^ KW[r][0];
- r1 = Tinv0[t1&255] ^ shift(Tinv0[(t0>>8)&255], 24) ^ shift(Tinv0[(r3>>16)&255], 16) ^ shift(Tinv0[(t2>>24)&255], 8) ^ KW[r][1];
- r2 = Tinv0[t2&255] ^ shift(Tinv0[(t1>>8)&255], 24) ^ shift(Tinv0[(t0>>16)&255], 16) ^ shift(Tinv0[(r3>>24)&255], 8) ^ KW[r][2];
- r3 = Tinv0[r3&255] ^ shift(Tinv0[(t2>>8)&255], 24) ^ shift(Tinv0[(t1>>16)&255], 16) ^ shift(Tinv0[(t0>>24)&255], 8) ^ KW[r--][3];
- t0 = Tinv0[r0&255] ^ shift(Tinv0[(r3>>8)&255], 24) ^ shift(Tinv0[(r2>>16)&255], 16) ^ shift(Tinv0[(r1>>24)&255], 8) ^ KW[r][0];
- t1 = Tinv0[r1&255] ^ shift(Tinv0[(r0>>8)&255], 24) ^ shift(Tinv0[(r3>>16)&255], 16) ^ shift(Tinv0[(r2>>24)&255], 8) ^ KW[r][1];
- t2 = Tinv0[r2&255] ^ shift(Tinv0[(r1>>8)&255], 24) ^ shift(Tinv0[(r0>>16)&255], 16) ^ shift(Tinv0[(r3>>24)&255], 8) ^ KW[r][2];
- r3 = Tinv0[r3&255] ^ shift(Tinv0[(r2>>8)&255], 24) ^ shift(Tinv0[(r1>>16)&255], 16) ^ shift(Tinv0[(r0>>24)&255], 8) ^ KW[r--][3];
- }
-
- r0 = Tinv0[t0&255] ^ shift(Tinv0[(r3>>8)&255], 24) ^ shift(Tinv0[(t2>>16)&255], 16) ^ shift(Tinv0[(t1>>24)&255], 8) ^ KW[r][0];
- r1 = Tinv0[t1&255] ^ shift(Tinv0[(t0>>8)&255], 24) ^ shift(Tinv0[(r3>>16)&255], 16) ^ shift(Tinv0[(t2>>24)&255], 8) ^ KW[r][1];
- r2 = Tinv0[t2&255] ^ shift(Tinv0[(t1>>8)&255], 24) ^ shift(Tinv0[(t0>>16)&255], 16) ^ shift(Tinv0[(r3>>24)&255], 8) ^ KW[r][2];
- r3 = Tinv0[r3&255] ^ shift(Tinv0[(t2>>8)&255], 24) ^ shift(Tinv0[(t1>>16)&255], 16) ^ shift(Tinv0[(t0>>24)&255], 8) ^ KW[r][3];
-
- // the final round's table is a simple function of Si so we don't use a whole other four tables for it
-
- this.C0 = (Si[r0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24) ^ KW[0][0];
- this.C1 = (Si[r1&255]&255) ^ ((Si[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(r2>>24)&255]<<24) ^ KW[0][1];
- this.C2 = (Si[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24) ^ KW[0][2];
- this.C3 = (Si[r3&255]&255) ^ ((Si[(r2>>8)&255]&255)<<8) ^ ((Si[(r1>>16)&255]&255)<<16) ^ (Si[(r0>>24)&255]<<24) ^ KW[0][3];
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java
deleted file mode 100644
index e2b00d3a..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java
+++ /dev/null
@@ -1,928 +0,0 @@
-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;
-import org.bouncycastle.util.Pack;
-
-/**
- * an implementation of the AES (Rijndael), from FIPS-197.
- * <p>
- * For further details see: <a href="http://csrc.nist.gov/encryption/aes/">http://csrc.nist.gov/encryption/aes/</a>.
- *
- * This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at
- * <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
- *
- * There are three levels of tradeoff of speed vs memory
- * Because java has no preprocessor, they are written as three separate classes from which to choose
- *
- * The fastest uses 8Kbytes of static tables to precompute round calculations, 4 256 word tables for encryption
- * and 4 for decryption.
- *
- * The middle performance version uses only one 256 word table for each, for a total of 2Kbytes,
- * adding 12 rotate operations per round to compute the values contained in the other tables from
- * the contents of the first
- *
- * The slowest version uses no static tables at all and computes the values in each round
- * <p>
- * This file contains the fast version with 8Kbytes of static tables for round precomputation
- *
- */
-public class AESFastEngine
- implements BlockCipher
-{
- // The S box
- private static final byte[] S = {
- (byte)99, (byte)124, (byte)119, (byte)123, (byte)242, (byte)107, (byte)111, (byte)197,
- (byte)48, (byte)1, (byte)103, (byte)43, (byte)254, (byte)215, (byte)171, (byte)118,
- (byte)202, (byte)130, (byte)201, (byte)125, (byte)250, (byte)89, (byte)71, (byte)240,
- (byte)173, (byte)212, (byte)162, (byte)175, (byte)156, (byte)164, (byte)114, (byte)192,
- (byte)183, (byte)253, (byte)147, (byte)38, (byte)54, (byte)63, (byte)247, (byte)204,
- (byte)52, (byte)165, (byte)229, (byte)241, (byte)113, (byte)216, (byte)49, (byte)21,
- (byte)4, (byte)199, (byte)35, (byte)195, (byte)24, (byte)150, (byte)5, (byte)154,
- (byte)7, (byte)18, (byte)128, (byte)226, (byte)235, (byte)39, (byte)178, (byte)117,
- (byte)9, (byte)131, (byte)44, (byte)26, (byte)27, (byte)110, (byte)90, (byte)160,
- (byte)82, (byte)59, (byte)214, (byte)179, (byte)41, (byte)227, (byte)47, (byte)132,
- (byte)83, (byte)209, (byte)0, (byte)237, (byte)32, (byte)252, (byte)177, (byte)91,
- (byte)106, (byte)203, (byte)190, (byte)57, (byte)74, (byte)76, (byte)88, (byte)207,
- (byte)208, (byte)239, (byte)170, (byte)251, (byte)67, (byte)77, (byte)51, (byte)133,
- (byte)69, (byte)249, (byte)2, (byte)127, (byte)80, (byte)60, (byte)159, (byte)168,
- (byte)81, (byte)163, (byte)64, (byte)143, (byte)146, (byte)157, (byte)56, (byte)245,
- (byte)188, (byte)182, (byte)218, (byte)33, (byte)16, (byte)255, (byte)243, (byte)210,
- (byte)205, (byte)12, (byte)19, (byte)236, (byte)95, (byte)151, (byte)68, (byte)23,
- (byte)196, (byte)167, (byte)126, (byte)61, (byte)100, (byte)93, (byte)25, (byte)115,
- (byte)96, (byte)129, (byte)79, (byte)220, (byte)34, (byte)42, (byte)144, (byte)136,
- (byte)70, (byte)238, (byte)184, (byte)20, (byte)222, (byte)94, (byte)11, (byte)219,
- (byte)224, (byte)50, (byte)58, (byte)10, (byte)73, (byte)6, (byte)36, (byte)92,
- (byte)194, (byte)211, (byte)172, (byte)98, (byte)145, (byte)149, (byte)228, (byte)121,
- (byte)231, (byte)200, (byte)55, (byte)109, (byte)141, (byte)213, (byte)78, (byte)169,
- (byte)108, (byte)86, (byte)244, (byte)234, (byte)101, (byte)122, (byte)174, (byte)8,
- (byte)186, (byte)120, (byte)37, (byte)46, (byte)28, (byte)166, (byte)180, (byte)198,
- (byte)232, (byte)221, (byte)116, (byte)31, (byte)75, (byte)189, (byte)139, (byte)138,
- (byte)112, (byte)62, (byte)181, (byte)102, (byte)72, (byte)3, (byte)246, (byte)14,
- (byte)97, (byte)53, (byte)87, (byte)185, (byte)134, (byte)193, (byte)29, (byte)158,
- (byte)225, (byte)248, (byte)152, (byte)17, (byte)105, (byte)217, (byte)142, (byte)148,
- (byte)155, (byte)30, (byte)135, (byte)233, (byte)206, (byte)85, (byte)40, (byte)223,
- (byte)140, (byte)161, (byte)137, (byte)13, (byte)191, (byte)230, (byte)66, (byte)104,
- (byte)65, (byte)153, (byte)45, (byte)15, (byte)176, (byte)84, (byte)187, (byte)22,
- };
-
- // The inverse S-box
- private static final byte[] Si = {
- (byte)82, (byte)9, (byte)106, (byte)213, (byte)48, (byte)54, (byte)165, (byte)56,
- (byte)191, (byte)64, (byte)163, (byte)158, (byte)129, (byte)243, (byte)215, (byte)251,
- (byte)124, (byte)227, (byte)57, (byte)130, (byte)155, (byte)47, (byte)255, (byte)135,
- (byte)52, (byte)142, (byte)67, (byte)68, (byte)196, (byte)222, (byte)233, (byte)203,
- (byte)84, (byte)123, (byte)148, (byte)50, (byte)166, (byte)194, (byte)35, (byte)61,
- (byte)238, (byte)76, (byte)149, (byte)11, (byte)66, (byte)250, (byte)195, (byte)78,
- (byte)8, (byte)46, (byte)161, (byte)102, (byte)40, (byte)217, (byte)36, (byte)178,
- (byte)118, (byte)91, (byte)162, (byte)73, (byte)109, (byte)139, (byte)209, (byte)37,
- (byte)114, (byte)248, (byte)246, (byte)100, (byte)134, (byte)104, (byte)152, (byte)22,
- (byte)212, (byte)164, (byte)92, (byte)204, (byte)93, (byte)101, (byte)182, (byte)146,
- (byte)108, (byte)112, (byte)72, (byte)80, (byte)253, (byte)237, (byte)185, (byte)218,
- (byte)94, (byte)21, (byte)70, (byte)87, (byte)167, (byte)141, (byte)157, (byte)132,
- (byte)144, (byte)216, (byte)171, (byte)0, (byte)140, (byte)188, (byte)211, (byte)10,
- (byte)247, (byte)228, (byte)88, (byte)5, (byte)184, (byte)179, (byte)69, (byte)6,
- (byte)208, (byte)44, (byte)30, (byte)143, (byte)202, (byte)63, (byte)15, (byte)2,
- (byte)193, (byte)175, (byte)189, (byte)3, (byte)1, (byte)19, (byte)138, (byte)107,
- (byte)58, (byte)145, (byte)17, (byte)65, (byte)79, (byte)103, (byte)220, (byte)234,
- (byte)151, (byte)242, (byte)207, (byte)206, (byte)240, (byte)180, (byte)230, (byte)115,
- (byte)150, (byte)172, (byte)116, (byte)34, (byte)231, (byte)173, (byte)53, (byte)133,
- (byte)226, (byte)249, (byte)55, (byte)232, (byte)28, (byte)117, (byte)223, (byte)110,
- (byte)71, (byte)241, (byte)26, (byte)113, (byte)29, (byte)41, (byte)197, (byte)137,
- (byte)111, (byte)183, (byte)98, (byte)14, (byte)170, (byte)24, (byte)190, (byte)27,
- (byte)252, (byte)86, (byte)62, (byte)75, (byte)198, (byte)210, (byte)121, (byte)32,
- (byte)154, (byte)219, (byte)192, (byte)254, (byte)120, (byte)205, (byte)90, (byte)244,
- (byte)31, (byte)221, (byte)168, (byte)51, (byte)136, (byte)7, (byte)199, (byte)49,
- (byte)177, (byte)18, (byte)16, (byte)89, (byte)39, (byte)128, (byte)236, (byte)95,
- (byte)96, (byte)81, (byte)127, (byte)169, (byte)25, (byte)181, (byte)74, (byte)13,
- (byte)45, (byte)229, (byte)122, (byte)159, (byte)147, (byte)201, (byte)156, (byte)239,
- (byte)160, (byte)224, (byte)59, (byte)77, (byte)174, (byte)42, (byte)245, (byte)176,
- (byte)200, (byte)235, (byte)187, (byte)60, (byte)131, (byte)83, (byte)153, (byte)97,
- (byte)23, (byte)43, (byte)4, (byte)126, (byte)186, (byte)119, (byte)214, (byte)38,
- (byte)225, (byte)105, (byte)20, (byte)99, (byte)85, (byte)33, (byte)12, (byte)125,
- };
-
- // vector used in calculating key schedule (powers of x in GF(256))
- private static final int[] rcon = {
- 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
- 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 };
-
- // precomputation tables of calculations for rounds
- private static final int[] T =
- {
- // T0
- 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff,
- 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102,
- 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d,
- 0x9a7676ec, 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa,
- 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, 0xecadad41,
- 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453,
- 0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d,
- 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83,
- 0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9, 0x937171e2,
- 0x73d8d8ab, 0x53313162, 0x3f15152a, 0x0c040408, 0x52c7c795,
- 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0x0f05050a,
- 0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
- 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912,
- 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc,
- 0xee5a5ab4, 0xfba0a05b, 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7,
- 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413,
- 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, 0x60202040,
- 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d,
- 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0,
- 0x4acfcf85, 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed,
- 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, 0xcf45458a,
- 0x10f9f9e9, 0x06020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78,
- 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d, 0xc0404080,
- 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
- 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020,
- 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18,
- 0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488,
- 0x3917172e, 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a,
- 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, 0xa06060c0,
- 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54,
- 0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b,
- 0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad,
- 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992,
- 0x0a06060c, 0x6c242448, 0xe45c5cb8, 0x5dc2c29f, 0x6ed3d3bd,
- 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3,
- 0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
- 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8,
- 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4,
- 0xe9aeae47, 0x18080810, 0xd5baba6f, 0x887878f0, 0x6f25254a,
- 0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697,
- 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96,
- 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c,
- 0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x05030306, 0x01f6f6f7,
- 0x120e0e1c, 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969,
- 0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9,
- 0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9,
- 0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c, 0x92878715,
- 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
- 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65,
- 0x31e6e6d7, 0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929,
- 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d,
- 0x3a16162c,
-
- // T1
- 0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, 0xf2f2ff0d,
- 0x6b6bd6bd, 0x6f6fdeb1, 0xc5c59154, 0x30306050, 0x01010203,
- 0x6767cea9, 0x2b2b567d, 0xfefee719, 0xd7d7b562, 0xabab4de6,
- 0x7676ec9a, 0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87,
- 0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b, 0xadad41ec,
- 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea, 0x9c9c23bf, 0xa4a453f7,
- 0x7272e496, 0xc0c09b5b, 0xb7b775c2, 0xfdfde11c, 0x93933dae,
- 0x26264c6a, 0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f,
- 0x3434685c, 0xa5a551f4, 0xe5e5d134, 0xf1f1f908, 0x7171e293,
- 0xd8d8ab73, 0x31316253, 0x15152a3f, 0x0404080c, 0xc7c79552,
- 0x23234665, 0xc3c39d5e, 0x18183028, 0x969637a1, 0x05050a0f,
- 0x9a9a2fb5, 0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d,
- 0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f, 0x0909121b,
- 0x83831d9e, 0x2c2c5874, 0x1a1a342e, 0x1b1b362d, 0x6e6edcb2,
- 0x5a5ab4ee, 0xa0a05bfb, 0x5252a4f6, 0x3b3b764d, 0xd6d6b761,
- 0xb3b37dce, 0x2929527b, 0xe3e3dd3e, 0x2f2f5e71, 0x84841397,
- 0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c, 0x20204060,
- 0xfcfce31f, 0xb1b179c8, 0x5b5bb6ed, 0x6a6ad4be, 0xcbcb8d46,
- 0xbebe67d9, 0x3939724b, 0x4a4a94de, 0x4c4c98d4, 0x5858b0e8,
- 0xcfcf854a, 0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16,
- 0x434386c5, 0x4d4d9ad7, 0x33336655, 0x85851194, 0x45458acf,
- 0xf9f9e910, 0x02020406, 0x7f7ffe81, 0x5050a0f0, 0x3c3c7844,
- 0x9f9f25ba, 0xa8a84be3, 0x5151a2f3, 0xa3a35dfe, 0x404080c0,
- 0x8f8f058a, 0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104,
- 0xbcbc63df, 0xb6b677c1, 0xdadaaf75, 0x21214263, 0x10102030,
- 0xffffe51a, 0xf3f3fd0e, 0xd2d2bf6d, 0xcdcd814c, 0x0c0c1814,
- 0x13132635, 0xececc32f, 0x5f5fbee1, 0x979735a2, 0x444488cc,
- 0x17172e39, 0xc4c49357, 0xa7a755f2, 0x7e7efc82, 0x3d3d7a47,
- 0x6464c8ac, 0x5d5dbae7, 0x1919322b, 0x7373e695, 0x6060c0a0,
- 0x81811998, 0x4f4f9ed1, 0xdcdca37f, 0x22224466, 0x2a2a547e,
- 0x90903bab, 0x88880b83, 0x46468cca, 0xeeeec729, 0xb8b86bd3,
- 0x1414283c, 0xdedea779, 0x5e5ebce2, 0x0b0b161d, 0xdbdbad76,
- 0xe0e0db3b, 0x32326456, 0x3a3a744e, 0x0a0a141e, 0x494992db,
- 0x06060c0a, 0x2424486c, 0x5c5cb8e4, 0xc2c29f5d, 0xd3d3bd6e,
- 0xacac43ef, 0x6262c4a6, 0x919139a8, 0x959531a4, 0xe4e4d337,
- 0x7979f28b, 0xe7e7d532, 0xc8c88b43, 0x37376e59, 0x6d6ddab7,
- 0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0, 0x6c6cd8b4,
- 0x5656acfa, 0xf4f4f307, 0xeaeacf25, 0x6565caaf, 0x7a7af48e,
- 0xaeae47e9, 0x08081018, 0xbaba6fd5, 0x7878f088, 0x25254a6f,
- 0x2e2e5c72, 0x1c1c3824, 0xa6a657f1, 0xb4b473c7, 0xc6c69751,
- 0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21, 0x4b4b96dd,
- 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85, 0x7070e090, 0x3e3e7c42,
- 0xb5b571c4, 0x6666ccaa, 0x484890d8, 0x03030605, 0xf6f6f701,
- 0x0e0e1c12, 0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0,
- 0x86861791, 0xc1c19958, 0x1d1d3a27, 0x9e9e27b9, 0xe1e1d938,
- 0xf8f8eb13, 0x98982bb3, 0x11112233, 0x6969d2bb, 0xd9d9a970,
- 0x8e8e0789, 0x949433a7, 0x9b9b2db6, 0x1e1e3c22, 0x87871592,
- 0xe9e9c920, 0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a,
- 0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17, 0xbfbf65da,
- 0xe6e6d731, 0x424284c6, 0x6868d0b8, 0x414182c3, 0x999929b0,
- 0x2d2d5a77, 0x0f0f1e11, 0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6,
- 0x16162c3a,
-
- // T2
- 0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, 0xf2ff0df2,
- 0x6bd6bd6b, 0x6fdeb16f, 0xc59154c5, 0x30605030, 0x01020301,
- 0x67cea967, 0x2b567d2b, 0xfee719fe, 0xd7b562d7, 0xab4de6ab,
- 0x76ec9a76, 0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d,
- 0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0, 0xad41ecad,
- 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf, 0x9c23bf9c, 0xa453f7a4,
- 0x72e49672, 0xc09b5bc0, 0xb775c2b7, 0xfde11cfd, 0x933dae93,
- 0x264c6a26, 0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc,
- 0x34685c34, 0xa551f4a5, 0xe5d134e5, 0xf1f908f1, 0x71e29371,
- 0xd8ab73d8, 0x31625331, 0x152a3f15, 0x04080c04, 0xc79552c7,
- 0x23466523, 0xc39d5ec3, 0x18302818, 0x9637a196, 0x050a0f05,
- 0x9a2fb59a, 0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2,
- 0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75, 0x09121b09,
- 0x831d9e83, 0x2c58742c, 0x1a342e1a, 0x1b362d1b, 0x6edcb26e,
- 0x5ab4ee5a, 0xa05bfba0, 0x52a4f652, 0x3b764d3b, 0xd6b761d6,
- 0xb37dceb3, 0x29527b29, 0xe3dd3ee3, 0x2f5e712f, 0x84139784,
- 0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced, 0x20406020,
- 0xfce31ffc, 0xb179c8b1, 0x5bb6ed5b, 0x6ad4be6a, 0xcb8d46cb,
- 0xbe67d9be, 0x39724b39, 0x4a94de4a, 0x4c98d44c, 0x58b0e858,
- 0xcf854acf, 0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb,
- 0x4386c543, 0x4d9ad74d, 0x33665533, 0x85119485, 0x458acf45,
- 0xf9e910f9, 0x02040602, 0x7ffe817f, 0x50a0f050, 0x3c78443c,
- 0x9f25ba9f, 0xa84be3a8, 0x51a2f351, 0xa35dfea3, 0x4080c040,
- 0x8f058a8f, 0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5,
- 0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, 0x21426321, 0x10203010,
- 0xffe51aff, 0xf3fd0ef3, 0xd2bf6dd2, 0xcd814ccd, 0x0c18140c,
- 0x13263513, 0xecc32fec, 0x5fbee15f, 0x9735a297, 0x4488cc44,
- 0x172e3917, 0xc49357c4, 0xa755f2a7, 0x7efc827e, 0x3d7a473d,
- 0x64c8ac64, 0x5dbae75d, 0x19322b19, 0x73e69573, 0x60c0a060,
- 0x81199881, 0x4f9ed14f, 0xdca37fdc, 0x22446622, 0x2a547e2a,
- 0x903bab90, 0x880b8388, 0x468cca46, 0xeec729ee, 0xb86bd3b8,
- 0x14283c14, 0xdea779de, 0x5ebce25e, 0x0b161d0b, 0xdbad76db,
- 0xe0db3be0, 0x32645632, 0x3a744e3a, 0x0a141e0a, 0x4992db49,
- 0x060c0a06, 0x24486c24, 0x5cb8e45c, 0xc29f5dc2, 0xd3bd6ed3,
- 0xac43efac, 0x62c4a662, 0x9139a891, 0x9531a495, 0xe4d337e4,
- 0x79f28b79, 0xe7d532e7, 0xc88b43c8, 0x376e5937, 0x6ddab76d,
- 0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9, 0x6cd8b46c,
- 0x56acfa56, 0xf4f307f4, 0xeacf25ea, 0x65caaf65, 0x7af48e7a,
- 0xae47e9ae, 0x08101808, 0xba6fd5ba, 0x78f08878, 0x254a6f25,
- 0x2e5c722e, 0x1c38241c, 0xa657f1a6, 0xb473c7b4, 0xc69751c6,
- 0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f, 0x4b96dd4b,
- 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a, 0x70e09070, 0x3e7c423e,
- 0xb571c4b5, 0x66ccaa66, 0x4890d848, 0x03060503, 0xf6f701f6,
- 0x0e1c120e, 0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9,
- 0x86179186, 0xc19958c1, 0x1d3a271d, 0x9e27b99e, 0xe1d938e1,
- 0xf8eb13f8, 0x982bb398, 0x11223311, 0x69d2bb69, 0xd9a970d9,
- 0x8e07898e, 0x9433a794, 0x9b2db69b, 0x1e3c221e, 0x87159287,
- 0xe9c920e9, 0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf,
- 0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d, 0xbf65dabf,
- 0xe6d731e6, 0x4284c642, 0x68d0b868, 0x4182c341, 0x9929b099,
- 0x2d5a772d, 0x0f1e110f, 0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb,
- 0x162c3a16,
-
- // T3
- 0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, 0xff0df2f2,
- 0xd6bd6b6b, 0xdeb16f6f, 0x9154c5c5, 0x60503030, 0x02030101,
- 0xcea96767, 0x567d2b2b, 0xe719fefe, 0xb562d7d7, 0x4de6abab,
- 0xec9a7676, 0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d,
- 0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0, 0x41ecadad,
- 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf, 0x23bf9c9c, 0x53f7a4a4,
- 0xe4967272, 0x9b5bc0c0, 0x75c2b7b7, 0xe11cfdfd, 0x3dae9393,
- 0x4c6a2626, 0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc,
- 0x685c3434, 0x51f4a5a5, 0xd134e5e5, 0xf908f1f1, 0xe2937171,
- 0xab73d8d8, 0x62533131, 0x2a3f1515, 0x080c0404, 0x9552c7c7,
- 0x46652323, 0x9d5ec3c3, 0x30281818, 0x37a19696, 0x0a0f0505,
- 0x2fb59a9a, 0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2,
- 0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575, 0x121b0909,
- 0x1d9e8383, 0x58742c2c, 0x342e1a1a, 0x362d1b1b, 0xdcb26e6e,
- 0xb4ee5a5a, 0x5bfba0a0, 0xa4f65252, 0x764d3b3b, 0xb761d6d6,
- 0x7dceb3b3, 0x527b2929, 0xdd3ee3e3, 0x5e712f2f, 0x13978484,
- 0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded, 0x40602020,
- 0xe31ffcfc, 0x79c8b1b1, 0xb6ed5b5b, 0xd4be6a6a, 0x8d46cbcb,
- 0x67d9bebe, 0x724b3939, 0x94de4a4a, 0x98d44c4c, 0xb0e85858,
- 0x854acfcf, 0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb,
- 0x86c54343, 0x9ad74d4d, 0x66553333, 0x11948585, 0x8acf4545,
- 0xe910f9f9, 0x04060202, 0xfe817f7f, 0xa0f05050, 0x78443c3c,
- 0x25ba9f9f, 0x4be3a8a8, 0xa2f35151, 0x5dfea3a3, 0x80c04040,
- 0x058a8f8f, 0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5,
- 0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, 0x42632121, 0x20301010,
- 0xe51affff, 0xfd0ef3f3, 0xbf6dd2d2, 0x814ccdcd, 0x18140c0c,
- 0x26351313, 0xc32fecec, 0xbee15f5f, 0x35a29797, 0x88cc4444,
- 0x2e391717, 0x9357c4c4, 0x55f2a7a7, 0xfc827e7e, 0x7a473d3d,
- 0xc8ac6464, 0xbae75d5d, 0x322b1919, 0xe6957373, 0xc0a06060,
- 0x19988181, 0x9ed14f4f, 0xa37fdcdc, 0x44662222, 0x547e2a2a,
- 0x3bab9090, 0x0b838888, 0x8cca4646, 0xc729eeee, 0x6bd3b8b8,
- 0x283c1414, 0xa779dede, 0xbce25e5e, 0x161d0b0b, 0xad76dbdb,
- 0xdb3be0e0, 0x64563232, 0x744e3a3a, 0x141e0a0a, 0x92db4949,
- 0x0c0a0606, 0x486c2424, 0xb8e45c5c, 0x9f5dc2c2, 0xbd6ed3d3,
- 0x43efacac, 0xc4a66262, 0x39a89191, 0x31a49595, 0xd337e4e4,
- 0xf28b7979, 0xd532e7e7, 0x8b43c8c8, 0x6e593737, 0xdab76d6d,
- 0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9, 0xd8b46c6c,
- 0xacfa5656, 0xf307f4f4, 0xcf25eaea, 0xcaaf6565, 0xf48e7a7a,
- 0x47e9aeae, 0x10180808, 0x6fd5baba, 0xf0887878, 0x4a6f2525,
- 0x5c722e2e, 0x38241c1c, 0x57f1a6a6, 0x73c7b4b4, 0x9751c6c6,
- 0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f, 0x96dd4b4b,
- 0x61dcbdbd, 0x0d868b8b, 0x0f858a8a, 0xe0907070, 0x7c423e3e,
- 0x71c4b5b5, 0xccaa6666, 0x90d84848, 0x06050303, 0xf701f6f6,
- 0x1c120e0e, 0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9,
- 0x17918686, 0x9958c1c1, 0x3a271d1d, 0x27b99e9e, 0xd938e1e1,
- 0xeb13f8f8, 0x2bb39898, 0x22331111, 0xd2bb6969, 0xa970d9d9,
- 0x07898e8e, 0x33a79494, 0x2db69b9b, 0x3c221e1e, 0x15928787,
- 0xc920e9e9, 0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf,
- 0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d, 0x65dabfbf,
- 0xd731e6e6, 0x84c64242, 0xd0b86868, 0x82c34141, 0x29b09999,
- 0x5a772d2d, 0x1e110f0f, 0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb,
- 0x2c3a1616};
-
- private static final int[] Tinv =
- {
- // Tinv0
- 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b,
- 0xf1459d1f, 0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad,
- 0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526,
- 0x8fa362b5, 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d,
- 0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, 0xe75f8f03,
- 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458,
- 0x2969e049, 0x44c8c98e, 0x6a89c275, 0x78798ef4, 0x6b3e5899,
- 0xdd71b927, 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d,
- 0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362, 0xe07764b1,
- 0x84ae6bbb, 0x1ca081fe, 0x942b08f9, 0x58684870, 0x19fd458f,
- 0x876cde94, 0xb7f87b52, 0x23d373ab, 0xe2024b72, 0x578f1fe3,
- 0x2aab5566, 0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3,
- 0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a,
- 0x92b479a7, 0xf0f207f3, 0xa1e2694e, 0xcdf4da65, 0xd5be0506,
- 0x1f6234d1, 0x8afea6c4, 0x9d532e34, 0xa055f3a2, 0x32e18a05,
- 0x75ebf6a4, 0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd,
- 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, 0xb58d5491,
- 0x055dc471, 0x6fd40604, 0xff155060, 0x24fb9819, 0x97e9bdd6,
- 0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7,
- 0xdbeec879, 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000,
- 0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, 0xfbff0efd,
- 0x5638850f, 0x1ed5ae3d, 0x27392d36, 0x64d90f0a, 0x21a65c68,
- 0xd1545b9b, 0x3a2e3624, 0xb1670a0c, 0x0fe75793, 0xd296eeb4,
- 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c,
- 0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 0x0b0d090e,
- 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, 0x8519f157, 0x4c0775af,
- 0xbbdd99ee, 0xfd607fa3, 0x9f2601f7, 0xbcf5725c, 0xc53b6644,
- 0x347efb5b, 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8,
- 0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684, 0x7d244a85,
- 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc,
- 0xec52860d, 0xd0e3c177, 0x6c16b32b, 0x99b970a9, 0xfa489411,
- 0x2264e947, 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322,
- 0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, 0xcf81f5a6,
- 0x28de7aa5, 0x268eb7da, 0xa4bfad3f, 0xe49d3a2c, 0x0d927850,
- 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890, 0x5ef7392e,
- 0xf5afc382, 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf,
- 0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 0x097826cd,
- 0xf418596e, 0x01b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa,
- 0x08cfbc21, 0xe6e815ef, 0xd99be7ba, 0xce366f4a, 0xd4099fea,
- 0xd67cb029, 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235,
- 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, 0x4a9804f1,
- 0xf7daec41, 0x0e50cd7f, 0x2ff69117, 0x8dd64d76, 0x4db0ef43,
- 0x544daacc, 0xdf0496e4, 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1,
- 0x7f516546, 0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb,
- 0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d, 0x8c61d79a,
- 0x7a0ca137, 0x8e14f859, 0x893c13eb, 0xee27a9ce, 0x35c961b7,
- 0xede51ce1, 0x3cb1477a, 0x59dfd29c, 0x3f73f255, 0x79ce1418,
- 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478,
- 0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16,
- 0x0c25e2bc, 0x8b493c28, 0x41950dff, 0x7101a839, 0xdeb30c08,
- 0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48,
- 0x4257b8d0,
-
- // Tinv1
- 0xa7f45150, 0x65417e53, 0xa4171ac3, 0x5e273a96, 0x6bab3bcb,
- 0x459d1ff1, 0x58faacab, 0x03e34b93, 0xfa302055, 0x6d76adf6,
- 0x76cc8891, 0x4c02f525, 0xd7e54ffc, 0xcb2ac5d7, 0x44352680,
- 0xa362b58f, 0x5ab1de49, 0x1bba2567, 0x0eea4598, 0xc0fe5de1,
- 0x752fc302, 0xf04c8112, 0x97468da3, 0xf9d36bc6, 0x5f8f03e7,
- 0x9c921595, 0x7a6dbfeb, 0x595295da, 0x83bed42d, 0x217458d3,
- 0x69e04929, 0xc8c98e44, 0x89c2756a, 0x798ef478, 0x3e58996b,
- 0x71b927dd, 0x4fe1beb6, 0xad88f017, 0xac20c966, 0x3ace7db4,
- 0x4adf6318, 0x311ae582, 0x33519760, 0x7f536245, 0x7764b1e0,
- 0xae6bbb84, 0xa081fe1c, 0x2b08f994, 0x68487058, 0xfd458f19,
- 0x6cde9487, 0xf87b52b7, 0xd373ab23, 0x024b72e2, 0x8f1fe357,
- 0xab55662a, 0x28ebb207, 0xc2b52f03, 0x7bc5869a, 0x0837d3a5,
- 0x872830f2, 0xa5bf23b2, 0x6a0302ba, 0x8216ed5c, 0x1ccf8a2b,
- 0xb479a792, 0xf207f3f0, 0xe2694ea1, 0xf4da65cd, 0xbe0506d5,
- 0x6234d11f, 0xfea6c48a, 0x532e349d, 0x55f3a2a0, 0xe18a0532,
- 0xebf6a475, 0xec830b39, 0xef6040aa, 0x9f715e06, 0x106ebd51,
- 0x8a213ef9, 0x06dd963d, 0x053eddae, 0xbde64d46, 0x8d5491b5,
- 0x5dc47105, 0xd406046f, 0x155060ff, 0xfb981924, 0xe9bdd697,
- 0x434089cc, 0x9ed96777, 0x42e8b0bd, 0x8b890788, 0x5b19e738,
- 0xeec879db, 0x0a7ca147, 0x0f427ce9, 0x1e84f8c9, 0x00000000,
- 0x86800983, 0xed2b3248, 0x70111eac, 0x725a6c4e, 0xff0efdfb,
- 0x38850f56, 0xd5ae3d1e, 0x392d3627, 0xd90f0a64, 0xa65c6821,
- 0x545b9bd1, 0x2e36243a, 0x670a0cb1, 0xe757930f, 0x96eeb4d2,
- 0x919b1b9e, 0xc5c0804f, 0x20dc61a2, 0x4b775a69, 0x1a121c16,
- 0xba93e20a, 0x2aa0c0e5, 0xe0223c43, 0x171b121d, 0x0d090e0b,
- 0xc78bf2ad, 0xa8b62db9, 0xa91e14c8, 0x19f15785, 0x0775af4c,
- 0xdd99eebb, 0x607fa3fd, 0x2601f79f, 0xf5725cbc, 0x3b6644c5,
- 0x7efb5b34, 0x29438b76, 0xc623cbdc, 0xfcedb668, 0xf1e4b863,
- 0xdc31d7ca, 0x85634210, 0x22971340, 0x11c68420, 0x244a857d,
- 0x3dbbd2f8, 0x32f9ae11, 0xa129c76d, 0x2f9e1d4b, 0x30b2dcf3,
- 0x52860dec, 0xe3c177d0, 0x16b32b6c, 0xb970a999, 0x489411fa,
- 0x64e94722, 0x8cfca8c4, 0x3ff0a01a, 0x2c7d56d8, 0x903322ef,
- 0x4e4987c7, 0xd138d9c1, 0xa2ca8cfe, 0x0bd49836, 0x81f5a6cf,
- 0xde7aa528, 0x8eb7da26, 0xbfad3fa4, 0x9d3a2ce4, 0x9278500d,
- 0xcc5f6a9b, 0x467e5462, 0x138df6c2, 0xb8d890e8, 0xf7392e5e,
- 0xafc382f5, 0x805d9fbe, 0x93d0697c, 0x2dd56fa9, 0x1225cfb3,
- 0x99acc83b, 0x7d1810a7, 0x639ce86e, 0xbb3bdb7b, 0x7826cd09,
- 0x18596ef4, 0xb79aec01, 0x9a4f83a8, 0x6e95e665, 0xe6ffaa7e,
- 0xcfbc2108, 0xe815efe6, 0x9be7bad9, 0x366f4ace, 0x099fead4,
- 0x7cb029d6, 0xb2a431af, 0x233f2a31, 0x94a5c630, 0x66a235c0,
- 0xbc4e7437, 0xca82fca6, 0xd090e0b0, 0xd8a73315, 0x9804f14a,
- 0xdaec41f7, 0x50cd7f0e, 0xf691172f, 0xd64d768d, 0xb0ef434d,
- 0x4daacc54, 0x0496e4df, 0xb5d19ee3, 0x886a4c1b, 0x1f2cc1b8,
- 0x5165467f, 0xea5e9d04, 0x358c015d, 0x7487fa73, 0x410bfb2e,
- 0x1d67b35a, 0xd2db9252, 0x5610e933, 0x47d66d13, 0x61d79a8c,
- 0x0ca1377a, 0x14f8598e, 0x3c13eb89, 0x27a9ceee, 0xc961b735,
- 0xe51ce1ed, 0xb1477a3c, 0xdfd29c59, 0x73f2553f, 0xce141879,
- 0x37c773bf, 0xcdf753ea, 0xaafd5f5b, 0x6f3ddf14, 0xdb447886,
- 0xf3afca81, 0xc468b93e, 0x3424382c, 0x40a3c25f, 0xc31d1672,
- 0x25e2bc0c, 0x493c288b, 0x950dff41, 0x01a83971, 0xb30c08de,
- 0xe4b4d89c, 0xc1566490, 0x84cb7b61, 0xb632d570, 0x5c6c4874,
- 0x57b8d042,
-
- // Tinv2
- 0xf45150a7, 0x417e5365, 0x171ac3a4, 0x273a965e, 0xab3bcb6b,
- 0x9d1ff145, 0xfaacab58, 0xe34b9303, 0x302055fa, 0x76adf66d,
- 0xcc889176, 0x02f5254c, 0xe54ffcd7, 0x2ac5d7cb, 0x35268044,
- 0x62b58fa3, 0xb1de495a, 0xba25671b, 0xea45980e, 0xfe5de1c0,
- 0x2fc30275, 0x4c8112f0, 0x468da397, 0xd36bc6f9, 0x8f03e75f,
- 0x9215959c, 0x6dbfeb7a, 0x5295da59, 0xbed42d83, 0x7458d321,
- 0xe0492969, 0xc98e44c8, 0xc2756a89, 0x8ef47879, 0x58996b3e,
- 0xb927dd71, 0xe1beb64f, 0x88f017ad, 0x20c966ac, 0xce7db43a,
- 0xdf63184a, 0x1ae58231, 0x51976033, 0x5362457f, 0x64b1e077,
- 0x6bbb84ae, 0x81fe1ca0, 0x08f9942b, 0x48705868, 0x458f19fd,
- 0xde94876c, 0x7b52b7f8, 0x73ab23d3, 0x4b72e202, 0x1fe3578f,
- 0x55662aab, 0xebb20728, 0xb52f03c2, 0xc5869a7b, 0x37d3a508,
- 0x2830f287, 0xbf23b2a5, 0x0302ba6a, 0x16ed5c82, 0xcf8a2b1c,
- 0x79a792b4, 0x07f3f0f2, 0x694ea1e2, 0xda65cdf4, 0x0506d5be,
- 0x34d11f62, 0xa6c48afe, 0x2e349d53, 0xf3a2a055, 0x8a0532e1,
- 0xf6a475eb, 0x830b39ec, 0x6040aaef, 0x715e069f, 0x6ebd5110,
- 0x213ef98a, 0xdd963d06, 0x3eddae05, 0xe64d46bd, 0x5491b58d,
- 0xc471055d, 0x06046fd4, 0x5060ff15, 0x981924fb, 0xbdd697e9,
- 0x4089cc43, 0xd967779e, 0xe8b0bd42, 0x8907888b, 0x19e7385b,
- 0xc879dbee, 0x7ca1470a, 0x427ce90f, 0x84f8c91e, 0x00000000,
- 0x80098386, 0x2b3248ed, 0x111eac70, 0x5a6c4e72, 0x0efdfbff,
- 0x850f5638, 0xae3d1ed5, 0x2d362739, 0x0f0a64d9, 0x5c6821a6,
- 0x5b9bd154, 0x36243a2e, 0x0a0cb167, 0x57930fe7, 0xeeb4d296,
- 0x9b1b9e91, 0xc0804fc5, 0xdc61a220, 0x775a694b, 0x121c161a,
- 0x93e20aba, 0xa0c0e52a, 0x223c43e0, 0x1b121d17, 0x090e0b0d,
- 0x8bf2adc7, 0xb62db9a8, 0x1e14c8a9, 0xf1578519, 0x75af4c07,
- 0x99eebbdd, 0x7fa3fd60, 0x01f79f26, 0x725cbcf5, 0x6644c53b,
- 0xfb5b347e, 0x438b7629, 0x23cbdcc6, 0xedb668fc, 0xe4b863f1,
- 0x31d7cadc, 0x63421085, 0x97134022, 0xc6842011, 0x4a857d24,
- 0xbbd2f83d, 0xf9ae1132, 0x29c76da1, 0x9e1d4b2f, 0xb2dcf330,
- 0x860dec52, 0xc177d0e3, 0xb32b6c16, 0x70a999b9, 0x9411fa48,
- 0xe9472264, 0xfca8c48c, 0xf0a01a3f, 0x7d56d82c, 0x3322ef90,
- 0x4987c74e, 0x38d9c1d1, 0xca8cfea2, 0xd498360b, 0xf5a6cf81,
- 0x7aa528de, 0xb7da268e, 0xad3fa4bf, 0x3a2ce49d, 0x78500d92,
- 0x5f6a9bcc, 0x7e546246, 0x8df6c213, 0xd890e8b8, 0x392e5ef7,
- 0xc382f5af, 0x5d9fbe80, 0xd0697c93, 0xd56fa92d, 0x25cfb312,
- 0xacc83b99, 0x1810a77d, 0x9ce86e63, 0x3bdb7bbb, 0x26cd0978,
- 0x596ef418, 0x9aec01b7, 0x4f83a89a, 0x95e6656e, 0xffaa7ee6,
- 0xbc2108cf, 0x15efe6e8, 0xe7bad99b, 0x6f4ace36, 0x9fead409,
- 0xb029d67c, 0xa431afb2, 0x3f2a3123, 0xa5c63094, 0xa235c066,
- 0x4e7437bc, 0x82fca6ca, 0x90e0b0d0, 0xa73315d8, 0x04f14a98,
- 0xec41f7da, 0xcd7f0e50, 0x91172ff6, 0x4d768dd6, 0xef434db0,
- 0xaacc544d, 0x96e4df04, 0xd19ee3b5, 0x6a4c1b88, 0x2cc1b81f,
- 0x65467f51, 0x5e9d04ea, 0x8c015d35, 0x87fa7374, 0x0bfb2e41,
- 0x67b35a1d, 0xdb9252d2, 0x10e93356, 0xd66d1347, 0xd79a8c61,
- 0xa1377a0c, 0xf8598e14, 0x13eb893c, 0xa9ceee27, 0x61b735c9,
- 0x1ce1ede5, 0x477a3cb1, 0xd29c59df, 0xf2553f73, 0x141879ce,
- 0xc773bf37, 0xf753eacd, 0xfd5f5baa, 0x3ddf146f, 0x447886db,
- 0xafca81f3, 0x68b93ec4, 0x24382c34, 0xa3c25f40, 0x1d1672c3,
- 0xe2bc0c25, 0x3c288b49, 0x0dff4195, 0xa8397101, 0x0c08deb3,
- 0xb4d89ce4, 0x566490c1, 0xcb7b6184, 0x32d570b6, 0x6c48745c,
- 0xb8d04257,
-
- // Tinv3
- 0x5150a7f4, 0x7e536541, 0x1ac3a417, 0x3a965e27, 0x3bcb6bab,
- 0x1ff1459d, 0xacab58fa, 0x4b9303e3, 0x2055fa30, 0xadf66d76,
- 0x889176cc, 0xf5254c02, 0x4ffcd7e5, 0xc5d7cb2a, 0x26804435,
- 0xb58fa362, 0xde495ab1, 0x25671bba, 0x45980eea, 0x5de1c0fe,
- 0xc302752f, 0x8112f04c, 0x8da39746, 0x6bc6f9d3, 0x03e75f8f,
- 0x15959c92, 0xbfeb7a6d, 0x95da5952, 0xd42d83be, 0x58d32174,
- 0x492969e0, 0x8e44c8c9, 0x756a89c2, 0xf478798e, 0x996b3e58,
- 0x27dd71b9, 0xbeb64fe1, 0xf017ad88, 0xc966ac20, 0x7db43ace,
- 0x63184adf, 0xe582311a, 0x97603351, 0x62457f53, 0xb1e07764,
- 0xbb84ae6b, 0xfe1ca081, 0xf9942b08, 0x70586848, 0x8f19fd45,
- 0x94876cde, 0x52b7f87b, 0xab23d373, 0x72e2024b, 0xe3578f1f,
- 0x662aab55, 0xb20728eb, 0x2f03c2b5, 0x869a7bc5, 0xd3a50837,
- 0x30f28728, 0x23b2a5bf, 0x02ba6a03, 0xed5c8216, 0x8a2b1ccf,
- 0xa792b479, 0xf3f0f207, 0x4ea1e269, 0x65cdf4da, 0x06d5be05,
- 0xd11f6234, 0xc48afea6, 0x349d532e, 0xa2a055f3, 0x0532e18a,
- 0xa475ebf6, 0x0b39ec83, 0x40aaef60, 0x5e069f71, 0xbd51106e,
- 0x3ef98a21, 0x963d06dd, 0xddae053e, 0x4d46bde6, 0x91b58d54,
- 0x71055dc4, 0x046fd406, 0x60ff1550, 0x1924fb98, 0xd697e9bd,
- 0x89cc4340, 0x67779ed9, 0xb0bd42e8, 0x07888b89, 0xe7385b19,
- 0x79dbeec8, 0xa1470a7c, 0x7ce90f42, 0xf8c91e84, 0x00000000,
- 0x09838680, 0x3248ed2b, 0x1eac7011, 0x6c4e725a, 0xfdfbff0e,
- 0x0f563885, 0x3d1ed5ae, 0x3627392d, 0x0a64d90f, 0x6821a65c,
- 0x9bd1545b, 0x243a2e36, 0x0cb1670a, 0x930fe757, 0xb4d296ee,
- 0x1b9e919b, 0x804fc5c0, 0x61a220dc, 0x5a694b77, 0x1c161a12,
- 0xe20aba93, 0xc0e52aa0, 0x3c43e022, 0x121d171b, 0x0e0b0d09,
- 0xf2adc78b, 0x2db9a8b6, 0x14c8a91e, 0x578519f1, 0xaf4c0775,
- 0xeebbdd99, 0xa3fd607f, 0xf79f2601, 0x5cbcf572, 0x44c53b66,
- 0x5b347efb, 0x8b762943, 0xcbdcc623, 0xb668fced, 0xb863f1e4,
- 0xd7cadc31, 0x42108563, 0x13402297, 0x842011c6, 0x857d244a,
- 0xd2f83dbb, 0xae1132f9, 0xc76da129, 0x1d4b2f9e, 0xdcf330b2,
- 0x0dec5286, 0x77d0e3c1, 0x2b6c16b3, 0xa999b970, 0x11fa4894,
- 0x472264e9, 0xa8c48cfc, 0xa01a3ff0, 0x56d82c7d, 0x22ef9033,
- 0x87c74e49, 0xd9c1d138, 0x8cfea2ca, 0x98360bd4, 0xa6cf81f5,
- 0xa528de7a, 0xda268eb7, 0x3fa4bfad, 0x2ce49d3a, 0x500d9278,
- 0x6a9bcc5f, 0x5462467e, 0xf6c2138d, 0x90e8b8d8, 0x2e5ef739,
- 0x82f5afc3, 0x9fbe805d, 0x697c93d0, 0x6fa92dd5, 0xcfb31225,
- 0xc83b99ac, 0x10a77d18, 0xe86e639c, 0xdb7bbb3b, 0xcd097826,
- 0x6ef41859, 0xec01b79a, 0x83a89a4f, 0xe6656e95, 0xaa7ee6ff,
- 0x2108cfbc, 0xefe6e815, 0xbad99be7, 0x4ace366f, 0xead4099f,
- 0x29d67cb0, 0x31afb2a4, 0x2a31233f, 0xc63094a5, 0x35c066a2,
- 0x7437bc4e, 0xfca6ca82, 0xe0b0d090, 0x3315d8a7, 0xf14a9804,
- 0x41f7daec, 0x7f0e50cd, 0x172ff691, 0x768dd64d, 0x434db0ef,
- 0xcc544daa, 0xe4df0496, 0x9ee3b5d1, 0x4c1b886a, 0xc1b81f2c,
- 0x467f5165, 0x9d04ea5e, 0x015d358c, 0xfa737487, 0xfb2e410b,
- 0xb35a1d67, 0x9252d2db, 0xe9335610, 0x6d1347d6, 0x9a8c61d7,
- 0x377a0ca1, 0x598e14f8, 0xeb893c13, 0xceee27a9, 0xb735c961,
- 0xe1ede51c, 0x7a3cb147, 0x9c59dfd2, 0x553f73f2, 0x1879ce14,
- 0x73bf37c7, 0x53eacdf7, 0x5f5baafd, 0xdf146f3d, 0x7886db44,
- 0xca81f3af, 0xb93ec468, 0x382c3424, 0xc25f40a3, 0x1672c31d,
- 0xbc0c25e2, 0x288b493c, 0xff41950d, 0x397101a8, 0x08deb30c,
- 0xd89ce4b4, 0x6490c156, 0x7b6184cb, 0xd570b632, 0x48745c6c,
- 0xd04257b8};
-
- private static int shift(int r, int shift)
- {
- return (r >>> shift) | (r << -shift);
- }
-
- /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */
-
- private static final int m1 = 0x80808080;
- private static final int m2 = 0x7f7f7f7f;
- private static final int m3 = 0x0000001b;
-
- private static int FFmulX(int x)
- {
- return (((x & m2) << 1) ^ (((x & m1) >>> 7) * m3));
- }
-
- /*
- The following defines provide alternative definitions of FFmulX that might
- give improved performance if a fast 32-bit multiply is not available.
-
- private int FFmulX(int x) { int u = x & m1; u |= (u >> 1); return ((x & m2) << 1) ^ ((u >>> 3) | (u >>> 6)); }
- private static final int m4 = 0x1b1b1b1b;
- private int FFmulX(int x) { int u = x & m1; return ((x & m2) << 1) ^ ((u - (u >>> 7)) & m4); }
-
- */
-
- private static int inv_mcol(int x)
- {
- int f2 = FFmulX(x);
- int f4 = FFmulX(f2);
- int f8 = FFmulX(f4);
- int f9 = x ^ f8;
-
- return f2 ^ f4 ^ f8 ^ shift(f2 ^ f9, 8) ^ shift(f4 ^ f9, 16) ^ shift(f9, 24);
- }
-
- private static int subWord(int x)
- {
- int i0 = x, i1 = x >>> 8, i2 = x >>> 16, i3 = x >>> 24;
- i0 = S[i0 & 255] & 255; i1 = S[i1 & 255] & 255; i2 = S[i2 & 255] & 255; i3 = S[i3 & 255] & 255;
- return i0 | i1 << 8 | i2 << 16 | i3 << 24;
- }
-
- /**
- * Calculate the necessary round keys
- * The number of calculations depends on key size and block size
- * AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
- * This code is written assuming those are the only possible values
- */
- private int[][] generateWorkingKey(
- byte[] key,
- boolean forEncryption)
- {
- int KC = key.length / 4; // key length in words
- int t;
-
- if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.length))
- {
- throw new IllegalArgumentException("Key length not 128/192/256 bits.");
- }
-
- ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes
- int[][] W = new int[ROUNDS+1][4]; // 4 words in a block
-
- //
- // copy the key into the round key array
- //
-
- t = 0;
- int i = 0;
- while (i < key.length)
- {
- W[t >> 2][t & 3] = (key[i]&0xff) | ((key[i+1]&0xff) << 8) | ((key[i+2]&0xff) << 16) | (key[i+3] << 24);
- i+=4;
- t++;
- }
-
- //
- // while not enough round key material calculated
- // calculate new values
- //
- int k = (ROUNDS + 1) << 2;
- for (i = KC; (i < k); i++)
- {
- int temp = W[(i - 1) >> 2][(i - 1) & 3];
- if ((i % KC) == 0)
- {
- temp = subWord(shift(temp, 8)) ^ rcon[(i / KC) - 1];
- }
- else if ((KC > 6) && ((i % KC) == 4))
- {
- temp = subWord(temp);
- }
-
- W[i >> 2][i & 3] = W[(i - KC) >> 2][(i - KC) & 3] ^ temp;
- }
-
- if (!forEncryption)
- {
- for (int j = 1; j < ROUNDS; j++)
- {
- for (i = 0; i < 4; i++)
- {
- W[j][i] = inv_mcol(W[j][i]);
- }
- }
- }
-
- return W;
- }
-
- private int ROUNDS;
- private int[][] WorkingKey = null;
- private int C0, C1, C2, C3;
- private boolean forEncryption;
-
- private static final int BLOCK_SIZE = 16;
-
- /**
- * default constructor - 128 bit block size.
- */
- public AESFastEngine()
- {
- }
-
- /**
- * initialise an AES cipher.
- *
- * @param forEncryption whether or not we are for encryption.
- * @param params the parameters required to set up the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean forEncryption,
- CipherParameters params)
- {
- if (params instanceof KeyParameter)
- {
- WorkingKey = generateWorkingKey(((KeyParameter)params).getKey(), forEncryption);
- this.forEncryption = forEncryption;
- return;
- }
-
- throw new IllegalArgumentException("invalid parameter passed to AES init - " + params.getClass().getName());
- }
-
- public String getAlgorithmName()
- {
- return "AES";
- }
-
- public int getBlockSize()
- {
- return BLOCK_SIZE;
- }
-
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- if (WorkingKey == null)
- {
- throw new IllegalStateException("AES engine not initialised");
- }
-
- if ((inOff + (32 / 2)) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + (32 / 2)) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- unpackBlock(in, inOff);
-
- if (forEncryption)
- {
- encryptBlock(WorkingKey);
- }
- else
- {
- decryptBlock(WorkingKey);
- }
-
- packBlock(out, outOff);
-
- return BLOCK_SIZE;
- }
-
- public void reset()
- {
- }
-
- private void unpackBlock(byte[] bytes, int off)
- {
- this.C0 = Pack.littleEndianToInt(bytes, off);
- this.C1 = Pack.littleEndianToInt(bytes, off + 4);
- this.C2 = Pack.littleEndianToInt(bytes, off + 8);
- this.C3 = Pack.littleEndianToInt(bytes, off + 12);
- }
-
- private void packBlock(byte[] bytes, int off)
- {
- Pack.intToLittleEndian(this.C0, bytes, off);
- Pack.intToLittleEndian(this.C1, bytes, off + 4);
- Pack.intToLittleEndian(this.C2, bytes, off + 8);
- Pack.intToLittleEndian(this.C3, bytes, off + 12);
- }
-
- private void encryptBlock(int[][] KW)
- {
- int t0 = this.C0 ^ KW[0][0];
- int t1 = this.C1 ^ KW[0][1];
- int t2 = this.C2 ^ KW[0][2];
-
- /*
- * Fast engine has precomputed rotr(T0, 8/16/24) tables T1/T2/T3.
- *
- * Placing all precomputes in one array requires offsets additions for 8/16/24 rotations but
- * avoids additional array range checks on 3 more arrays (which on HotSpot are more
- * expensive than the offset additions).
- */
- int r = 1, r0, r1, r2, r3 = this.C3 ^ KW[0][3];
- int i0, i1, i2, i3;
-
- while (r < ROUNDS - 1)
- {
- i0 = t0; i1 = t1 >>> 8; i2 = t2 >>> 16; i3 = r3 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- r0 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][0];
-
- i0 = t1; i1 = t2 >>> 8; i2 = r3 >>> 16; i3 = t0 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- r1 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][1];
-
- i0 = t2; i1 = r3 >>> 8; i2 = t0 >>> 16; i3 = t1 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- r2 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][2];
-
- i0 = r3; i1 = t0 >>> 8; i2 = t1 >>> 16; i3 = t2 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- r3 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r++][3];
-
- i0 = r0; i1 = r1 >>> 8; i2 = r2 >>> 16; i3 = r3 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- t0 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][0];
-
- i0 = r1; i1 = r2 >>> 8; i2 = r3 >>> 16; i3 = r0 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- t1 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][1];
-
- i0 = r2; i1 = r3 >>> 8; i2 = r0 >>> 16; i3 = r1 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- t2 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][2];
-
- i0 = r3; i1 = r0 >>> 8; i2 = r1 >>> 16; i3 = r2 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- r3 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r++][3];
- }
-
- i0 = t0; i1 = t1 >>> 8; i2 = t2 >>> 16; i3 = r3 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- r0 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][0];
-
- i0 = t1; i1 = t2 >>> 8; i2 = r3 >>> 16; i3 = t0 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- r1 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][1];
-
- i0 = t2; i1 = r3 >>> 8; i2 = t0 >>> 16; i3 = t1 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- r2 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][2];
-
- i0 = r3; i1 = t0 >>> 8; i2 = t1 >>> 16; i3 = t2 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- r3 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r++][3];
-
- // the final round's table is a simple function of S so we don't use a whole other four tables for it
-
- i0 = r0; i1 = r1 >>> 8; i2 = r2 >>> 16; i3 = r3 >>> 24;
- i0 = S[i0 & 255] & 255; i1 = S[i1 & 255] & 255; i2 = S[i2 & 255] & 255; i3 = S[i3 & 255] & 255;
- this.C0 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[r][0];
-
- i0 = r1; i1 = r2 >>> 8; i2 = r3 >>> 16; i3 = r0 >>> 24;
- i0 = S[i0 & 255] & 255; i1 = S[i1 & 255] & 255; i2 = S[i2 & 255] & 255; i3 = S[i3 & 255] & 255;
- this.C1 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[r][1];
-
- i0 = r2; i1 = r3 >>> 8; i2 = r0 >>> 16; i3 = r1 >>> 24;
- i0 = S[i0 & 255] & 255; i1 = S[i1 & 255] & 255; i2 = S[i2 & 255] & 255; i3 = S[i3 & 255] & 255;
- this.C2 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[r][2];
-
- i0 = r3; i1 = r0 >>> 8; i2 = r1 >>> 16; i3 = r2 >>> 24;
- i0 = S[i0 & 255] & 255; i1 = S[i1 & 255] & 255; i2 = S[i2 & 255] & 255; i3 = S[i3 & 255] & 255;
- this.C3 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[r][3];
- }
-
- private void decryptBlock(int[][] KW)
- {
- int t0 = this.C0 ^ KW[ROUNDS][0];
- int t1 = this.C1 ^ KW[ROUNDS][1];
- int t2 = this.C2 ^ KW[ROUNDS][2];
-
- int r = ROUNDS - 1, r0, r1, r2, r3 = this.C3 ^ KW[ROUNDS][3];
- int i0, i1, i2, i3;
-
- while (r > 1)
- {
- i0 = t0; i1 = r3 >>> 8; i2 = t2 >>> 16; i3 = t1 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- r0 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][0];
-
- i0 = t1; i1 = t0 >>> 8; i2 = r3 >>> 16; i3 = t2 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- r1 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][1];
-
- i0 = t2; i1 = t1 >>> 8; i2 = t0 >>> 16; i3 = r3 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- r2 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][2];
-
- i0 = r3; i1 = t2 >>> 8; i2 = t1 >>> 16; i3 = t0 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- r3 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r--][3];
-
- i0 = r0; i1 = r3 >>> 8; i2 = r2 >>> 16; i3 = r1 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- t0 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][0];
-
- i0 = r1; i1 = r0 >>> 8; i2 = r3 >>> 16; i3 = r2 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- t1 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][1];
-
- i0 = r2; i1 = r1 >>> 8; i2 = r0 >>> 16; i3 = r3 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- t2 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][2];
-
- i0 = r3; i1 = r2 >>> 8; i2 = r1 >>> 16; i3 = r0 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- r3 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r--][3];
- }
-
- i0 = t0; i1 = r3 >>> 8; i2 = t2 >>> 16; i3 = t1 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- r0 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[1][0];
-
- i0 = t1; i1 = t0 >>> 8; i2 = r3 >>> 16; i3 = t2 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- r1 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[1][1];
-
- i0 = t2; i1 = t1 >>> 8; i2 = t0 >>> 16; i3 = r3 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- r2 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[1][2];
-
- i0 = r3; i1 = t2 >>> 8; i2 = t1 >>> 16; i3 = t0 >>> 24;
- i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
- r3 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[1][3];
-
- // the final round's table is a simple function of Si so we don't use a whole other four tables for it
-
- i0 = r0; i1 = r3 >>> 8; i2 = r2 >>> 16; i3 = r1 >>> 24;
- i0 = Si[i0 & 255] & 255; i1 = Si[i1 & 255] & 255; i2 = Si[i2 & 255] & 255; i3 = Si[i3 & 255] & 255;
- this.C0 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[0][0];
-
- i0 = r1; i1 = r0 >>> 8; i2 = r3 >>> 16; i3 = r2 >>> 24;
- i0 = Si[i0 & 255] & 255; i1 = Si[i1 & 255] & 255; i2 = Si[i2 & 255] & 255; i3 = Si[i3 & 255] & 255;
- this.C1 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[0][1];
-
- i0 = r2; i1 = r1 >>> 8; i2 = r0 >>> 16; i3 = r3 >>> 24;
- i0 = Si[i0 & 255] & 255; i1 = Si[i1 & 255] & 255; i2 = Si[i2 & 255] & 255; i3 = Si[i3 & 255] & 255;
- this.C2 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[0][2];
-
- i0 = r3; i1 = r2 >>> 8; i2 = r1 >>> 16; i3 = r0 >>> 24;
- i0 = Si[i0 & 255] & 255; i1 = Si[i1 & 255] & 255; i2 = Si[i2 & 255] & 255; i3 = Si[i3 & 255] & 255;
- this.C3 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[0][3];
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/AESLightEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/AESLightEngine.java
deleted file mode 100644
index 70a3f683..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/AESLightEngine.java
+++ /dev/null
@@ -1,434 +0,0 @@
-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;
-
-/**
- * an implementation of the AES (Rijndael), from FIPS-197.
- * <p>
- * For further details see: <a href="http://csrc.nist.gov/encryption/aes/">http://csrc.nist.gov/encryption/aes/</a>.
- *
- * This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at
- * <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
- *
- * There are three levels of tradeoff of speed vs memory
- * Because java has no preprocessor, they are written as three separate classes from which to choose
- *
- * The fastest uses 8Kbytes of static tables to precompute round calculations, 4 256 word tables for encryption
- * and 4 for decryption.
- *
- * The middle performance version uses only one 256 word table for each, for a total of 2Kbytes,
- * adding 12 rotate operations per round to compute the values contained in the other tables from
- * the contents of the first
- *
- * The slowest version uses no static tables at all and computes the values
- * in each round.
- * <p>
- * This file contains the slowest performance version with no static tables
- * for round precomputation, but it has the smallest foot print.
- *
- */
-public class AESLightEngine
- implements BlockCipher
-{
- // The S box
- private static final byte[] S = {
- (byte)99, (byte)124, (byte)119, (byte)123, (byte)242, (byte)107, (byte)111, (byte)197,
- (byte)48, (byte)1, (byte)103, (byte)43, (byte)254, (byte)215, (byte)171, (byte)118,
- (byte)202, (byte)130, (byte)201, (byte)125, (byte)250, (byte)89, (byte)71, (byte)240,
- (byte)173, (byte)212, (byte)162, (byte)175, (byte)156, (byte)164, (byte)114, (byte)192,
- (byte)183, (byte)253, (byte)147, (byte)38, (byte)54, (byte)63, (byte)247, (byte)204,
- (byte)52, (byte)165, (byte)229, (byte)241, (byte)113, (byte)216, (byte)49, (byte)21,
- (byte)4, (byte)199, (byte)35, (byte)195, (byte)24, (byte)150, (byte)5, (byte)154,
- (byte)7, (byte)18, (byte)128, (byte)226, (byte)235, (byte)39, (byte)178, (byte)117,
- (byte)9, (byte)131, (byte)44, (byte)26, (byte)27, (byte)110, (byte)90, (byte)160,
- (byte)82, (byte)59, (byte)214, (byte)179, (byte)41, (byte)227, (byte)47, (byte)132,
- (byte)83, (byte)209, (byte)0, (byte)237, (byte)32, (byte)252, (byte)177, (byte)91,
- (byte)106, (byte)203, (byte)190, (byte)57, (byte)74, (byte)76, (byte)88, (byte)207,
- (byte)208, (byte)239, (byte)170, (byte)251, (byte)67, (byte)77, (byte)51, (byte)133,
- (byte)69, (byte)249, (byte)2, (byte)127, (byte)80, (byte)60, (byte)159, (byte)168,
- (byte)81, (byte)163, (byte)64, (byte)143, (byte)146, (byte)157, (byte)56, (byte)245,
- (byte)188, (byte)182, (byte)218, (byte)33, (byte)16, (byte)255, (byte)243, (byte)210,
- (byte)205, (byte)12, (byte)19, (byte)236, (byte)95, (byte)151, (byte)68, (byte)23,
- (byte)196, (byte)167, (byte)126, (byte)61, (byte)100, (byte)93, (byte)25, (byte)115,
- (byte)96, (byte)129, (byte)79, (byte)220, (byte)34, (byte)42, (byte)144, (byte)136,
- (byte)70, (byte)238, (byte)184, (byte)20, (byte)222, (byte)94, (byte)11, (byte)219,
- (byte)224, (byte)50, (byte)58, (byte)10, (byte)73, (byte)6, (byte)36, (byte)92,
- (byte)194, (byte)211, (byte)172, (byte)98, (byte)145, (byte)149, (byte)228, (byte)121,
- (byte)231, (byte)200, (byte)55, (byte)109, (byte)141, (byte)213, (byte)78, (byte)169,
- (byte)108, (byte)86, (byte)244, (byte)234, (byte)101, (byte)122, (byte)174, (byte)8,
- (byte)186, (byte)120, (byte)37, (byte)46, (byte)28, (byte)166, (byte)180, (byte)198,
- (byte)232, (byte)221, (byte)116, (byte)31, (byte)75, (byte)189, (byte)139, (byte)138,
- (byte)112, (byte)62, (byte)181, (byte)102, (byte)72, (byte)3, (byte)246, (byte)14,
- (byte)97, (byte)53, (byte)87, (byte)185, (byte)134, (byte)193, (byte)29, (byte)158,
- (byte)225, (byte)248, (byte)152, (byte)17, (byte)105, (byte)217, (byte)142, (byte)148,
- (byte)155, (byte)30, (byte)135, (byte)233, (byte)206, (byte)85, (byte)40, (byte)223,
- (byte)140, (byte)161, (byte)137, (byte)13, (byte)191, (byte)230, (byte)66, (byte)104,
- (byte)65, (byte)153, (byte)45, (byte)15, (byte)176, (byte)84, (byte)187, (byte)22,
- };
-
- // The inverse S-box
- private static final byte[] Si = {
- (byte)82, (byte)9, (byte)106, (byte)213, (byte)48, (byte)54, (byte)165, (byte)56,
- (byte)191, (byte)64, (byte)163, (byte)158, (byte)129, (byte)243, (byte)215, (byte)251,
- (byte)124, (byte)227, (byte)57, (byte)130, (byte)155, (byte)47, (byte)255, (byte)135,
- (byte)52, (byte)142, (byte)67, (byte)68, (byte)196, (byte)222, (byte)233, (byte)203,
- (byte)84, (byte)123, (byte)148, (byte)50, (byte)166, (byte)194, (byte)35, (byte)61,
- (byte)238, (byte)76, (byte)149, (byte)11, (byte)66, (byte)250, (byte)195, (byte)78,
- (byte)8, (byte)46, (byte)161, (byte)102, (byte)40, (byte)217, (byte)36, (byte)178,
- (byte)118, (byte)91, (byte)162, (byte)73, (byte)109, (byte)139, (byte)209, (byte)37,
- (byte)114, (byte)248, (byte)246, (byte)100, (byte)134, (byte)104, (byte)152, (byte)22,
- (byte)212, (byte)164, (byte)92, (byte)204, (byte)93, (byte)101, (byte)182, (byte)146,
- (byte)108, (byte)112, (byte)72, (byte)80, (byte)253, (byte)237, (byte)185, (byte)218,
- (byte)94, (byte)21, (byte)70, (byte)87, (byte)167, (byte)141, (byte)157, (byte)132,
- (byte)144, (byte)216, (byte)171, (byte)0, (byte)140, (byte)188, (byte)211, (byte)10,
- (byte)247, (byte)228, (byte)88, (byte)5, (byte)184, (byte)179, (byte)69, (byte)6,
- (byte)208, (byte)44, (byte)30, (byte)143, (byte)202, (byte)63, (byte)15, (byte)2,
- (byte)193, (byte)175, (byte)189, (byte)3, (byte)1, (byte)19, (byte)138, (byte)107,
- (byte)58, (byte)145, (byte)17, (byte)65, (byte)79, (byte)103, (byte)220, (byte)234,
- (byte)151, (byte)242, (byte)207, (byte)206, (byte)240, (byte)180, (byte)230, (byte)115,
- (byte)150, (byte)172, (byte)116, (byte)34, (byte)231, (byte)173, (byte)53, (byte)133,
- (byte)226, (byte)249, (byte)55, (byte)232, (byte)28, (byte)117, (byte)223, (byte)110,
- (byte)71, (byte)241, (byte)26, (byte)113, (byte)29, (byte)41, (byte)197, (byte)137,
- (byte)111, (byte)183, (byte)98, (byte)14, (byte)170, (byte)24, (byte)190, (byte)27,
- (byte)252, (byte)86, (byte)62, (byte)75, (byte)198, (byte)210, (byte)121, (byte)32,
- (byte)154, (byte)219, (byte)192, (byte)254, (byte)120, (byte)205, (byte)90, (byte)244,
- (byte)31, (byte)221, (byte)168, (byte)51, (byte)136, (byte)7, (byte)199, (byte)49,
- (byte)177, (byte)18, (byte)16, (byte)89, (byte)39, (byte)128, (byte)236, (byte)95,
- (byte)96, (byte)81, (byte)127, (byte)169, (byte)25, (byte)181, (byte)74, (byte)13,
- (byte)45, (byte)229, (byte)122, (byte)159, (byte)147, (byte)201, (byte)156, (byte)239,
- (byte)160, (byte)224, (byte)59, (byte)77, (byte)174, (byte)42, (byte)245, (byte)176,
- (byte)200, (byte)235, (byte)187, (byte)60, (byte)131, (byte)83, (byte)153, (byte)97,
- (byte)23, (byte)43, (byte)4, (byte)126, (byte)186, (byte)119, (byte)214, (byte)38,
- (byte)225, (byte)105, (byte)20, (byte)99, (byte)85, (byte)33, (byte)12, (byte)125,
- };
-
- // vector used in calculating key schedule (powers of x in GF(256))
- private static final int[] rcon = {
- 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
- 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 };
-
- private static int shift(int r, int shift)
- {
- return (r >>> shift) | (r << -shift);
- }
-
- /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */
-
- private static final int m1 = 0x80808080;
- private static final int m2 = 0x7f7f7f7f;
- private static final int m3 = 0x0000001b;
-
- private static int FFmulX(int x)
- {
- return (((x & m2) << 1) ^ (((x & m1) >>> 7) * m3));
- }
-
- /*
- The following defines provide alternative definitions of FFmulX that might
- give improved performance if a fast 32-bit multiply is not available.
-
- private int FFmulX(int x) { int u = x & m1; u |= (u >> 1); return ((x & m2) << 1) ^ ((u >>> 3) | (u >>> 6)); }
- private static final int m4 = 0x1b1b1b1b;
- private int FFmulX(int x) { int u = x & m1; return ((x & m2) << 1) ^ ((u - (u >>> 7)) & m4); }
-
- */
-
- private static int mcol(int x)
- {
- int f2 = FFmulX(x);
- return f2 ^ shift(x ^ f2, 8) ^ shift(x, 16) ^ shift(x, 24);
- }
-
- private static int inv_mcol(int x)
- {
- int f2 = FFmulX(x);
- int f4 = FFmulX(f2);
- int f8 = FFmulX(f4);
- int f9 = x ^ f8;
-
- return f2 ^ f4 ^ f8 ^ shift(f2 ^ f9, 8) ^ shift(f4 ^ f9, 16) ^ shift(f9, 24);
- }
-
-
- private static int subWord(int x)
- {
- return (S[x&255]&255 | ((S[(x>>8)&255]&255)<<8) | ((S[(x>>16)&255]&255)<<16) | S[(x>>24)&255]<<24);
- }
-
- /**
- * Calculate the necessary round keys
- * The number of calculations depends on key size and block size
- * AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
- * This code is written assuming those are the only possible values
- */
- private int[][] generateWorkingKey(
- byte[] key,
- boolean forEncryption)
- {
- int KC = key.length / 4; // key length in words
- int t;
-
- if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.length))
- {
- throw new IllegalArgumentException("Key length not 128/192/256 bits.");
- }
-
- ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes
- int[][] W = new int[ROUNDS+1][4]; // 4 words in a block
-
- //
- // copy the key into the round key array
- //
-
- t = 0;
- int i = 0;
- while (i < key.length)
- {
- W[t >> 2][t & 3] = (key[i]&0xff) | ((key[i+1]&0xff) << 8) | ((key[i+2]&0xff) << 16) | (key[i+3] << 24);
- i+=4;
- t++;
- }
-
- //
- // while not enough round key material calculated
- // calculate new values
- //
- int k = (ROUNDS + 1) << 2;
- for (i = KC; (i < k); i++)
- {
- int temp = W[(i-1)>>2][(i-1)&3];
- if ((i % KC) == 0)
- {
- temp = subWord(shift(temp, 8)) ^ rcon[(i / KC)-1];
- }
- else if ((KC > 6) && ((i % KC) == 4))
- {
- temp = subWord(temp);
- }
-
- W[i>>2][i&3] = W[(i - KC)>>2][(i-KC)&3] ^ temp;
- }
-
- if (!forEncryption)
- {
- for (int j = 1; j < ROUNDS; j++)
- {
- for (i = 0; i < 4; i++)
- {
- W[j][i] = inv_mcol(W[j][i]);
- }
- }
- }
-
- return W;
- }
-
- private int ROUNDS;
- private int[][] WorkingKey = null;
- private int C0, C1, C2, C3;
- private boolean forEncryption;
-
- private static final int BLOCK_SIZE = 16;
-
- /**
- * default constructor - 128 bit block size.
- */
- public AESLightEngine()
- {
- }
-
- /**
- * initialise an AES cipher.
- *
- * @param forEncryption whether or not we are for encryption.
- * @param params the parameters required to set up the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean forEncryption,
- CipherParameters params)
- {
- if (params instanceof KeyParameter)
- {
- WorkingKey = generateWorkingKey(((KeyParameter)params).getKey(), forEncryption);
- this.forEncryption = forEncryption;
- return;
- }
-
- throw new IllegalArgumentException("invalid parameter passed to AES init - " + params.getClass().getName());
- }
-
- public String getAlgorithmName()
- {
- return "AES";
- }
-
- public int getBlockSize()
- {
- return BLOCK_SIZE;
- }
-
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- if (WorkingKey == null)
- {
- throw new IllegalStateException("AES engine not initialised");
- }
-
- if ((inOff + (32 / 2)) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + (32 / 2)) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- if (forEncryption)
- {
- unpackBlock(in, inOff);
- encryptBlock(WorkingKey);
- packBlock(out, outOff);
- }
- else
- {
- unpackBlock(in, inOff);
- decryptBlock(WorkingKey);
- packBlock(out, outOff);
- }
-
- return BLOCK_SIZE;
- }
-
- public void reset()
- {
- }
-
- private void unpackBlock(
- byte[] bytes,
- int off)
- {
- int index = off;
-
- C0 = (bytes[index++] & 0xff);
- C0 |= (bytes[index++] & 0xff) << 8;
- C0 |= (bytes[index++] & 0xff) << 16;
- C0 |= bytes[index++] << 24;
-
- C1 = (bytes[index++] & 0xff);
- C1 |= (bytes[index++] & 0xff) << 8;
- C1 |= (bytes[index++] & 0xff) << 16;
- C1 |= bytes[index++] << 24;
-
- C2 = (bytes[index++] & 0xff);
- C2 |= (bytes[index++] & 0xff) << 8;
- C2 |= (bytes[index++] & 0xff) << 16;
- C2 |= bytes[index++] << 24;
-
- C3 = (bytes[index++] & 0xff);
- C3 |= (bytes[index++] & 0xff) << 8;
- C3 |= (bytes[index++] & 0xff) << 16;
- C3 |= bytes[index++] << 24;
- }
-
- private void packBlock(
- byte[] bytes,
- int off)
- {
- int index = off;
-
- bytes[index++] = (byte)C0;
- bytes[index++] = (byte)(C0 >> 8);
- bytes[index++] = (byte)(C0 >> 16);
- bytes[index++] = (byte)(C0 >> 24);
-
- bytes[index++] = (byte)C1;
- bytes[index++] = (byte)(C1 >> 8);
- bytes[index++] = (byte)(C1 >> 16);
- bytes[index++] = (byte)(C1 >> 24);
-
- bytes[index++] = (byte)C2;
- bytes[index++] = (byte)(C2 >> 8);
- bytes[index++] = (byte)(C2 >> 16);
- bytes[index++] = (byte)(C2 >> 24);
-
- bytes[index++] = (byte)C3;
- bytes[index++] = (byte)(C3 >> 8);
- bytes[index++] = (byte)(C3 >> 16);
- bytes[index++] = (byte)(C3 >> 24);
- }
-
- private void encryptBlock(int[][] KW)
- {
- int t0 = this.C0 ^ KW[0][0];
- int t1 = this.C1 ^ KW[0][1];
- int t2 = this.C2 ^ KW[0][2];
-
- int r = 1, r0, r1, r2, r3 = this.C3 ^ KW[0][3];
- while (r < ROUNDS - 1)
- {
- r0 = mcol((S[t0&255]&255) ^ ((S[(t1>>8)&255]&255)<<8) ^ ((S[(t2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24)) ^ KW[r][0];
- r1 = mcol((S[t1&255]&255) ^ ((S[(t2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(t0>>24)&255]<<24)) ^ KW[r][1];
- r2 = mcol((S[t2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(t0>>16)&255]&255)<<16) ^ (S[(t1>>24)&255]<<24)) ^ KW[r][2];
- r3 = mcol((S[r3&255]&255) ^ ((S[(t0>>8)&255]&255)<<8) ^ ((S[(t1>>16)&255]&255)<<16) ^ (S[(t2>>24)&255]<<24)) ^ KW[r++][3];
- t0 = mcol((S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((S[(r2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24)) ^ KW[r][0];
- t1 = mcol((S[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(r0>>24)&255]<<24)) ^ KW[r][1];
- t2 = mcol((S[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24)) ^ KW[r][2];
- r3 = mcol((S[r3&255]&255) ^ ((S[(r0>>8)&255]&255)<<8) ^ ((S[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24)) ^ KW[r++][3];
- }
-
- r0 = mcol((S[t0&255]&255) ^ ((S[(t1>>8)&255]&255)<<8) ^ ((S[(t2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24)) ^ KW[r][0];
- r1 = mcol((S[t1&255]&255) ^ ((S[(t2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(t0>>24)&255]<<24)) ^ KW[r][1];
- r2 = mcol((S[t2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(t0>>16)&255]&255)<<16) ^ (S[(t1>>24)&255]<<24)) ^ KW[r][2];
- r3 = mcol((S[r3&255]&255) ^ ((S[(t0>>8)&255]&255)<<8) ^ ((S[(t1>>16)&255]&255)<<16) ^ (S[(t2>>24)&255]<<24)) ^ KW[r++][3];
-
- // the final round is a simple function of S
-
- this.C0 = (S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((S[(r2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24) ^ KW[r][0];
- this.C1 = (S[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(r0>>24)&255]<<24) ^ KW[r][1];
- this.C2 = (S[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24) ^ KW[r][2];
- this.C3 = (S[r3&255]&255) ^ ((S[(r0>>8)&255]&255)<<8) ^ ((S[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24) ^ KW[r][3];
- }
-
- private void decryptBlock(int[][] KW)
- {
- int t0 = this.C0 ^ KW[ROUNDS][0];
- int t1 = this.C1 ^ KW[ROUNDS][1];
- int t2 = this.C2 ^ KW[ROUNDS][2];
-
- int r = ROUNDS - 1, r0, r1, r2, r3 = this.C3 ^ KW[ROUNDS][3];
- while (r > 1)
- {
- r0 = inv_mcol((Si[t0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(t2>>16)&255]&255)<<16) ^ (Si[(t1>>24)&255]<<24)) ^ KW[r][0];
- r1 = inv_mcol((Si[t1&255]&255) ^ ((Si[(t0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(t2>>24)&255]<<24)) ^ KW[r][1];
- r2 = inv_mcol((Si[t2&255]&255) ^ ((Si[(t1>>8)&255]&255)<<8) ^ ((Si[(t0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24)) ^ KW[r][2];
- r3 = inv_mcol((Si[r3&255]&255) ^ ((Si[(t2>>8)&255]&255)<<8) ^ ((Si[(t1>>16)&255]&255)<<16) ^ (Si[(t0>>24)&255]<<24)) ^ KW[r--][3];
- t0 = inv_mcol((Si[r0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24)) ^ KW[r][0];
- t1 = inv_mcol((Si[r1&255]&255) ^ ((Si[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(r2>>24)&255]<<24)) ^ KW[r][1];
- t2 = inv_mcol((Si[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24)) ^ KW[r][2];
- r3 = inv_mcol((Si[r3&255]&255) ^ ((Si[(r2>>8)&255]&255)<<8) ^ ((Si[(r1>>16)&255]&255)<<16) ^ (Si[(r0>>24)&255]<<24)) ^ KW[r--][3];
- }
-
- r0 = inv_mcol((Si[t0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(t2>>16)&255]&255)<<16) ^ (Si[(t1>>24)&255]<<24)) ^ KW[r][0];
- r1 = inv_mcol((Si[t1&255]&255) ^ ((Si[(t0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(t2>>24)&255]<<24)) ^ KW[r][1];
- r2 = inv_mcol((Si[t2&255]&255) ^ ((Si[(t1>>8)&255]&255)<<8) ^ ((Si[(t0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24)) ^ KW[r][2];
- r3 = inv_mcol((Si[r3&255]&255) ^ ((Si[(t2>>8)&255]&255)<<8) ^ ((Si[(t1>>16)&255]&255)<<16) ^ (Si[(t0>>24)&255]<<24)) ^ KW[r][3];
-
- // the final round's table is a simple function of Si
-
- this.C0 = (Si[r0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24) ^ KW[0][0];
- this.C1 = (Si[r1&255]&255) ^ ((Si[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(r2>>24)&255]<<24) ^ KW[0][1];
- this.C2 = (Si[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24) ^ KW[0][2];
- this.C3 = (Si[r3&255]&255) ^ ((Si[(r2>>8)&255]&255)<<8) ^ ((Si[(r1>>16)&255]&255)<<16) ^ (Si[(r0>>24)&255]<<24) ^ KW[0][3];
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/AESWrapEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/AESWrapEngine.java
deleted file mode 100644
index 5d316ac4..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/AESWrapEngine.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-/**
- * an implementation of the AES Key Wrapper from the NIST Key Wrap
- * Specification.
- * <p>
- * For further details see: <a href="http://csrc.nist.gov/encryption/kms/key-wrap.pdf">http://csrc.nist.gov/encryption/kms/key-wrap.pdf</a>.
- */
-public class AESWrapEngine
- extends RFC3394WrapEngine
-{
- public AESWrapEngine()
- {
- super(new AESEngine());
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/AESWrapPadEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/AESWrapPadEngine.java
deleted file mode 100644
index 77760612..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/AESWrapPadEngine.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-public class AESWrapPadEngine
- extends RFC5649WrapEngine
-{
- public AESWrapPadEngine()
- {
- super(new AESEngine());
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/BlowfishEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/BlowfishEngine.java
deleted file mode 100644
index cfe7f1ff..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/BlowfishEngine.java
+++ /dev/null
@@ -1,577 +0,0 @@
-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;
-
-/**
- * A class that provides Blowfish key encryption operations,
- * such as encoding data and generating keys.
- * All the algorithms herein are from Applied Cryptography
- * and implement a simplified cryptography interface.
- */
-public final class BlowfishEngine
-implements BlockCipher
-{
- private final static int[]
- KP = {
- 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344,
- 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89,
- 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C,
- 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917,
- 0x9216D5D9, 0x8979FB1B
- },
-
- KS0 = {
- 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7,
- 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99,
- 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16,
- 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E,
- 0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE,
- 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013,
- 0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF,
- 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E,
- 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60,
- 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440,
- 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE,
- 0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A,
- 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E,
- 0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677,
- 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193,
- 0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032,
- 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88,
- 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239,
- 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E,
- 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0,
- 0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3,
- 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98,
- 0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88,
- 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE,
- 0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6,
- 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D,
- 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B,
- 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7,
- 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA,
- 0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463,
- 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F,
- 0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09,
- 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3,
- 0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB,
- 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279,
- 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8,
- 0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB,
- 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82,
- 0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB,
- 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573,
- 0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0,
- 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B,
- 0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790,
- 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8,
- 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4,
- 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0,
- 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7,
- 0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C,
- 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD,
- 0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1,
- 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299,
- 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9,
- 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477,
- 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF,
- 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49,
- 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF,
- 0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA,
- 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5,
- 0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41,
- 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915,
- 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400,
- 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915,
- 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664,
- 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A
- },
-
- KS1 = {
- 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623,
- 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266,
- 0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1,
- 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E,
- 0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6,
- 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1,
- 0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E,
- 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1,
- 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737,
- 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8,
- 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF,
- 0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD,
- 0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701,
- 0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7,
- 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41,
- 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331,
- 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF,
- 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF,
- 0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E,
- 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87,
- 0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C,
- 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2,
- 0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16,
- 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD,
- 0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B,
- 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509,
- 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E,
- 0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3,
- 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F,
- 0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A,
- 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4,
- 0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960,
- 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66,
- 0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28,
- 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802,
- 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84,
- 0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510,
- 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF,
- 0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14,
- 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E,
- 0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50,
- 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7,
- 0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8,
- 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281,
- 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99,
- 0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696,
- 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128,
- 0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73,
- 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0,
- 0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0,
- 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105,
- 0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250,
- 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3,
- 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285,
- 0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00,
- 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061,
- 0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB,
- 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E,
- 0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735,
- 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC,
- 0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9,
- 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340,
- 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20,
- 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7
- },
-
- KS2 = {
- 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934,
- 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068,
- 0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF,
- 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840,
- 0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45,
- 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504,
- 0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A,
- 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB,
- 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE,
- 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6,
- 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42,
- 0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B,
- 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2,
- 0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB,
- 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527,
- 0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B,
- 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33,
- 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C,
- 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3,
- 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC,
- 0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17,
- 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564,
- 0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B,
- 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115,
- 0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922,
- 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728,
- 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0,
- 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E,
- 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37,
- 0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D,
- 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804,
- 0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B,
- 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3,
- 0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB,
- 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D,
- 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C,
- 0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350,
- 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9,
- 0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A,
- 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE,
- 0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D,
- 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC,
- 0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F,
- 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61,
- 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2,
- 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9,
- 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2,
- 0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C,
- 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E,
- 0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633,
- 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10,
- 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169,
- 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52,
- 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027,
- 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5,
- 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62,
- 0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634,
- 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76,
- 0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24,
- 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC,
- 0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4,
- 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C,
- 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837,
- 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0
- },
-
- KS3 = {
- 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B,
- 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE,
- 0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B,
- 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4,
- 0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8,
- 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6,
- 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304,
- 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22,
- 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4,
- 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6,
- 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9,
- 0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59,
- 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593,
- 0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51,
- 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28,
- 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C,
- 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B,
- 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28,
- 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C,
- 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD,
- 0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A,
- 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319,
- 0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB,
- 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F,
- 0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991,
- 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32,
- 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680,
- 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166,
- 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE,
- 0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB,
- 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5,
- 0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47,
- 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370,
- 0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D,
- 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84,
- 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048,
- 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8,
- 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD,
- 0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9,
- 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7,
- 0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38,
- 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F,
- 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C,
- 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525,
- 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1,
- 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442,
- 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964,
- 0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E,
- 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8,
- 0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D,
- 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F,
- 0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299,
- 0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02,
- 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC,
- 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614,
- 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A,
- 0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6,
- 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B,
- 0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0,
- 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060,
- 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E,
- 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9,
- 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F,
- 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6
- };
-
- //====================================
- // Useful constants
- //====================================
-
- private static final int ROUNDS = 16;
- private static final int BLOCK_SIZE = 8; // bytes = 64 bits
- private static final int SBOX_SK = 256;
- private static final int P_SZ = ROUNDS+2;
-
- private final int[] S0, S1, S2, S3; // the s-boxes
- private final int[] P; // the p-array
-
- private boolean encrypting = false;
-
- private byte[] workingKey = null;
-
- public BlowfishEngine()
- {
- S0 = new int[SBOX_SK];
- S1 = new int[SBOX_SK];
- S2 = new int[SBOX_SK];
- S3 = new int[SBOX_SK];
- P = new int[P_SZ];
- }
-
- /**
- * initialise a Blowfish cipher.
- *
- * @param encrypting whether or not we are for encryption.
- * @param params the parameters required to set up the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean encrypting,
- CipherParameters params)
- {
- if (params instanceof KeyParameter)
- {
- this.encrypting = encrypting;
- this.workingKey = ((KeyParameter)params).getKey();
- setKey(this.workingKey);
-
- return;
- }
-
- throw new IllegalArgumentException("invalid parameter passed to Blowfish init - " + params.getClass().getName());
- }
-
- public String getAlgorithmName()
- {
- return "Blowfish";
- }
-
- public final int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- if (workingKey == null)
- {
- throw new IllegalStateException("Blowfish not initialised");
- }
-
- if ((inOff + BLOCK_SIZE) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + BLOCK_SIZE) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- if (encrypting)
- {
- encryptBlock(in, inOff, out, outOff);
- }
- else
- {
- decryptBlock(in, inOff, out, outOff);
- }
-
- return BLOCK_SIZE;
- }
-
- public void reset()
- {
- }
-
- public int getBlockSize()
- {
- return BLOCK_SIZE;
- }
-
- //==================================
- // Private Implementation
- //==================================
-
- private int F(int x)
- {
- return (((S0[(x >>> 24)] + S1[(x >>> 16) & 0xff])
- ^ S2[(x >>> 8) & 0xff]) + S3[x & 0xff]);
- }
-
- /**
- * apply the encryption cycle to each value pair in the table.
- */
- private void processTable(
- int xl,
- int xr,
- int[] table)
- {
- int size = table.length;
-
- for (int s = 0; s < size; s += 2)
- {
- xl ^= P[0];
-
- for (int i = 1; i < ROUNDS; i += 2)
- {
- xr ^= F(xl) ^ P[i];
- xl ^= F(xr) ^ P[i + 1];
- }
-
- xr ^= P[ROUNDS + 1];
-
- table[s] = xr;
- table[s + 1] = xl;
-
- xr = xl; // end of cycle swap
- xl = table[s];
- }
- }
-
- private void setKey(byte[] key)
- {
- /*
- * - comments are from _Applied Crypto_, Schneier, p338
- * please be careful comparing the two, AC numbers the
- * arrays from 1, the enclosed code from 0.
- *
- * (1)
- * Initialise the S-boxes and the P-array, with a fixed string
- * This string contains the hexadecimal digits of pi (3.141...)
- */
- System.arraycopy(KS0, 0, S0, 0, SBOX_SK);
- System.arraycopy(KS1, 0, S1, 0, SBOX_SK);
- System.arraycopy(KS2, 0, S2, 0, SBOX_SK);
- System.arraycopy(KS3, 0, S3, 0, SBOX_SK);
-
- System.arraycopy(KP, 0, P, 0, P_SZ);
-
- /*
- * (2)
- * Now, XOR P[0] with the first 32 bits of the key, XOR P[1] with the
- * second 32-bits of the key, and so on for all bits of the key
- * (up to P[17]). Repeatedly cycle through the key bits until the
- * entire P-array has been XOR-ed with the key bits
- */
- int keyLength = key.length;
- int keyIndex = 0;
-
- for (int i=0; i < P_SZ; i++)
- {
- // get the 32 bits of the key, in 4 * 8 bit chunks
- int data = 0x0000000;
- for (int j=0; j < 4; j++)
- {
- // create a 32 bit block
- data = (data << 8) | (key[keyIndex++] & 0xff);
-
- // wrap when we get to the end of the key
- if (keyIndex >= keyLength)
- {
- keyIndex = 0;
- }
- }
- // XOR the newly created 32 bit chunk onto the P-array
- P[i] ^= data;
- }
-
- /*
- * (3)
- * Encrypt the all-zero string with the Blowfish algorithm, using
- * the subkeys described in (1) and (2)
- *
- * (4)
- * Replace P1 and P2 with the output of step (3)
- *
- * (5)
- * Encrypt the output of step(3) using the Blowfish algorithm,
- * with the modified subkeys.
- *
- * (6)
- * Replace P3 and P4 with the output of step (5)
- *
- * (7)
- * Continue the process, replacing all elements of the P-array
- * and then all four S-boxes in order, with the output of the
- * continuously changing Blowfish algorithm
- */
-
- processTable(0, 0, P);
- processTable(P[P_SZ - 2], P[P_SZ - 1], S0);
- processTable(S0[SBOX_SK - 2], S0[SBOX_SK - 1], S1);
- processTable(S1[SBOX_SK - 2], S1[SBOX_SK - 1], S2);
- processTable(S2[SBOX_SK - 2], S2[SBOX_SK - 1], S3);
- }
-
- /**
- * Encrypt the given input starting at the given offset and place
- * the result in the provided buffer starting at the given offset.
- * The input will be an exact multiple of our blocksize.
- */
- private void encryptBlock(
- byte[] src,
- int srcIndex,
- byte[] dst,
- int dstIndex)
- {
- int xl = BytesTo32bits(src, srcIndex);
- int xr = BytesTo32bits(src, srcIndex+4);
-
- xl ^= P[0];
-
- for (int i = 1; i < ROUNDS; i += 2)
- {
- xr ^= F(xl) ^ P[i];
- xl ^= F(xr) ^ P[i + 1];
- }
-
- xr ^= P[ROUNDS + 1];
-
- Bits32ToBytes(xr, dst, dstIndex);
- Bits32ToBytes(xl, dst, dstIndex + 4);
- }
-
- /**
- * Decrypt the given input starting at the given offset and place
- * the result in the provided buffer starting at the given offset.
- * The input will be an exact multiple of our blocksize.
- */
- private void decryptBlock(
- byte[] src,
- int srcIndex,
- byte[] dst,
- int dstIndex)
- {
- int xl = BytesTo32bits(src, srcIndex);
- int xr = BytesTo32bits(src, srcIndex + 4);
-
- xl ^= P[ROUNDS + 1];
-
- for (int i = ROUNDS; i > 0 ; i -= 2)
- {
- xr ^= F(xl) ^ P[i];
- xl ^= F(xr) ^ P[i - 1];
- }
-
- xr ^= P[0];
-
- Bits32ToBytes(xr, dst, dstIndex);
- Bits32ToBytes(xl, dst, dstIndex+4);
- }
-
- private int BytesTo32bits(byte[] b, int i)
- {
- return ((b[i] & 0xff) << 24) |
- ((b[i+1] & 0xff) << 16) |
- ((b[i+2] & 0xff) << 8) |
- ((b[i+3] & 0xff));
- }
-
- private void Bits32ToBytes(int in, byte[] b, int offset)
- {
- b[offset + 3] = (byte)in;
- b[offset + 2] = (byte)(in >> 8);
- b[offset + 1] = (byte)(in >> 16);
- b[offset] = (byte)(in >> 24);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/CAST5Engine.java b/core/src/main/java/org/bouncycastle/crypto/engines/CAST5Engine.java
deleted file mode 100644
index 5a8c7806..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/CAST5Engine.java
+++ /dev/null
@@ -1,831 +0,0 @@
-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;
-
-/**
- * A class that provides CAST key encryption operations,
- * such as encoding data and generating keys.
- *
- * All the algorithms herein are from the Internet RFC's
- *
- * RFC2144 - CAST5 (64bit block, 40-128bit key)
- * RFC2612 - CAST6 (128bit block, 128-256bit key)
- *
- * and implement a simplified cryptography interface.
- */
-public class CAST5Engine
- implements BlockCipher
-{
- protected final static int M32 = 0xffffffff;
-
- protected final static int[]
- S1 = {
-0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
-0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
-0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
-0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
-0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
-0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
-0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
-0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
-0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
-0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
-0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
-0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
-0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
-0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
-0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
-0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
-0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
-0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
-0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
-0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
-0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
-0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
-0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
-0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
-0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
-0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
-0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
-0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
-0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
-0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
-0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
-0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf
- },
- S2 = {
-0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
-0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
-0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
-0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
-0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
-0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
-0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
-0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
-0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
-0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
-0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
-0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
-0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
-0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
-0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
-0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
-0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
-0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
-0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
-0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
-0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
-0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
-0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
-0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
-0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
-0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
-0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
-0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
-0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
-0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
-0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
-0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1
- },
- S3 = {
-0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
-0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
-0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
-0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
-0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
-0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
-0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
-0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
-0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
-0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
-0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
-0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
-0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
-0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
-0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
-0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
-0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
-0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
-0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
-0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
-0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
-0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
-0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
-0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
-0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
-0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
-0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
-0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
-0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
-0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
-0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
-0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783
- },
- S4 = {
-0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
-0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
-0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
-0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
-0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
-0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
-0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
-0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
-0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
-0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
-0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
-0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
-0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
-0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
-0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
-0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
-0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
-0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
-0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
-0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
-0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
-0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
-0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
-0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
-0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
-0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
-0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
-0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
-0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
-0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
-0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
-0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2
- },
- S5 = {
-0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
-0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
-0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
-0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
-0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
-0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
-0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
-0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
-0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
-0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
-0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
-0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
-0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
-0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
-0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
-0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
-0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
-0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
-0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
-0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
-0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
-0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
-0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
-0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
-0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
-0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
-0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
-0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
-0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
-0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
-0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
-0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4
- },
- S6 = {
-0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
-0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
-0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
-0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
-0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
-0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
-0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
-0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
-0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
-0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
-0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
-0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
-0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
-0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
-0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
-0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
-0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
-0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
-0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
-0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
-0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
-0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
-0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
-0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
-0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
-0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
-0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
-0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
-0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
-0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
-0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
-0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f
- },
- S7 = {
-0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
-0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
-0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
-0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
-0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
-0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
-0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
-0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
-0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
-0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
-0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
-0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
-0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
-0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
-0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
-0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
-0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
-0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
-0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
-0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
-0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
-0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
-0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
-0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
-0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
-0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
-0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
-0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
-0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
-0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
-0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
-0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3
- },
- S8 = {
-0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
-0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
-0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
-0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
-0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
-0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
-0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
-0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
-0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
-0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
-0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
-0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
-0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
-0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
-0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
-0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
-0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
-0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
-0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
-0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
-0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
-0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
-0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
-0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
-0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
-0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
-0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
-0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
-0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
-0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
-0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
-0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e
- };
-
- //====================================
- // Useful constants
- //====================================
-
- protected static final int MAX_ROUNDS = 16;
- protected static final int RED_ROUNDS = 12;
-
- protected static final int BLOCK_SIZE = 8; // bytes = 64 bits
-
- protected int _Kr[] = new int[17]; // the rotating round key
- protected int _Km[] = new int[17]; // the masking round key
-
- private boolean _encrypting = false;
-
- private byte[] _workingKey = null;
- private int _rounds = MAX_ROUNDS;
-
- public CAST5Engine()
- {
- }
-
- /**
- * initialise a CAST cipher.
- *
- * @param encrypting whether or not we are for encryption.
- * @param params the parameters required to set up the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean encrypting,
- CipherParameters params)
- {
- if (params instanceof KeyParameter)
- {
- _encrypting = encrypting;
- _workingKey = ((KeyParameter)params).getKey();
-
- setKey(_workingKey);
-
- return;
- }
-
- throw new IllegalArgumentException("Invalid parameter passed to "+getAlgorithmName()+" init - " + params.getClass().getName());
- }
-
- public String getAlgorithmName()
- {
- return "CAST5";
- }
-
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- if (_workingKey == null)
- {
- throw new IllegalStateException(getAlgorithmName()+" not initialised");
- }
-
- int blockSize = getBlockSize();
- if ((inOff + blockSize) > in.length)
- {
- throw new DataLengthException("Input buffer too short");
- }
-
- if ((outOff + blockSize) > out.length)
- {
- throw new OutputLengthException("Output buffer too short");
- }
-
- if (_encrypting)
- {
- return encryptBlock(in, inOff, out, outOff);
- }
- else
- {
- return decryptBlock(in, inOff, out, outOff);
- }
- }
-
- public void reset()
- {
- }
-
- public int getBlockSize()
- {
- return BLOCK_SIZE;
- }
-
- //==================================
- // Private Implementation
- //==================================
-
- /*
- * Creates the subkeys using the same nomenclature
- * as described in RFC2144.
- *
- * See section 2.4
- */
- protected void setKey(byte[] key)
- {
- /*
- * Determine the key size here, if required
- *
- * if keysize <= 80bits, use 12 rounds instead of 16
- * if keysize < 128bits, pad with 0
- *
- * Typical key sizes => 40, 64, 80, 128
- */
-
- if (key.length < 11)
- {
- _rounds = RED_ROUNDS;
- }
-
- int z[] = new int[16];
- int x[] = new int[16];
-
- int z03, z47, z8B, zCF;
- int x03, x47, x8B, xCF;
-
- /* copy the key into x */
- for (int i=0; i< key.length; i++)
- {
- x[i] = key[i] & 0xff;
- }
-
- /*
- * This will look different because the selection of
- * bytes from the input key I've already chosen the
- * correct int.
- */
- x03 = IntsTo32bits(x, 0x0);
- x47 = IntsTo32bits(x, 0x4);
- x8B = IntsTo32bits(x, 0x8);
- xCF = IntsTo32bits(x, 0xC);
-
- z03 = x03 ^S5[x[0xD]] ^S6[x[0xF]] ^S7[x[0xC]] ^S8[x[0xE]] ^S7[x[0x8]];
-
- Bits32ToInts(z03, z, 0x0);
- z47 = x8B ^S5[z[0x0]] ^S6[z[0x2]] ^S7[z[0x1]] ^S8[z[0x3]] ^S8[x[0xA]];
- Bits32ToInts(z47, z, 0x4);
- z8B = xCF ^S5[z[0x7]] ^S6[z[0x6]] ^S7[z[0x5]] ^S8[z[0x4]] ^S5[x[0x9]];
- Bits32ToInts(z8B, z, 0x8);
- zCF = x47 ^S5[z[0xA]] ^S6[z[0x9]] ^S7[z[0xB]] ^S8[z[0x8]] ^S6[x[0xB]];
- Bits32ToInts(zCF, z, 0xC);
- _Km[ 1]= S5[z[0x8]] ^ S6[z[0x9]] ^ S7[z[0x7]] ^ S8[z[0x6]] ^ S5[z[0x2]];
- _Km[ 2]= S5[z[0xA]] ^ S6[z[0xB]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S6[z[0x6]];
- _Km[ 3]= S5[z[0xC]] ^ S6[z[0xD]] ^ S7[z[0x3]] ^ S8[z[0x2]] ^ S7[z[0x9]];
- _Km[ 4]= S5[z[0xE]] ^ S6[z[0xF]] ^ S7[z[0x1]] ^ S8[z[0x0]] ^ S8[z[0xC]];
-
- z03 = IntsTo32bits(z, 0x0);
- z47 = IntsTo32bits(z, 0x4);
- z8B = IntsTo32bits(z, 0x8);
- zCF = IntsTo32bits(z, 0xC);
- x03 = z8B ^S5[z[0x5]] ^S6[z[0x7]] ^S7[z[0x4]] ^S8[z[0x6]] ^S7[z[0x0]];
- Bits32ToInts(x03, x, 0x0);
- x47 = z03 ^S5[x[0x0]] ^S6[x[0x2]] ^S7[x[0x1]] ^S8[x[0x3]] ^S8[z[0x2]];
- Bits32ToInts(x47, x, 0x4);
- x8B = z47 ^S5[x[0x7]] ^S6[x[0x6]] ^S7[x[0x5]] ^S8[x[0x4]] ^S5[z[0x1]];
- Bits32ToInts(x8B, x, 0x8);
- xCF = zCF ^S5[x[0xA]] ^S6[x[0x9]] ^S7[x[0xB]] ^S8[x[0x8]] ^S6[z[0x3]];
- Bits32ToInts(xCF, x, 0xC);
- _Km[ 5]= S5[x[0x3]] ^ S6[x[0x2]] ^ S7[x[0xC]] ^ S8[x[0xD]] ^ S5[x[0x8]];
- _Km[ 6]= S5[x[0x1]] ^ S6[x[0x0]] ^ S7[x[0xE]] ^ S8[x[0xF]] ^ S6[x[0xD]];
- _Km[ 7]= S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x8]] ^ S8[x[0x9]] ^ S7[x[0x3]];
- _Km[ 8]= S5[x[0x5]] ^ S6[x[0x4]] ^ S7[x[0xA]] ^ S8[x[0xB]] ^ S8[x[0x7]];
-
- x03 = IntsTo32bits(x, 0x0);
- x47 = IntsTo32bits(x, 0x4);
- x8B = IntsTo32bits(x, 0x8);
- xCF = IntsTo32bits(x, 0xC);
- z03 = x03 ^S5[x[0xD]] ^S6[x[0xF]] ^S7[x[0xC]] ^S8[x[0xE]] ^S7[x[0x8]];
- Bits32ToInts(z03, z, 0x0);
- z47 = x8B ^S5[z[0x0]] ^S6[z[0x2]] ^S7[z[0x1]] ^S8[z[0x3]] ^S8[x[0xA]];
- Bits32ToInts(z47, z, 0x4);
- z8B = xCF ^S5[z[0x7]] ^S6[z[0x6]] ^S7[z[0x5]] ^S8[z[0x4]] ^S5[x[0x9]];
- Bits32ToInts(z8B, z, 0x8);
- zCF = x47 ^S5[z[0xA]] ^S6[z[0x9]] ^S7[z[0xB]] ^S8[z[0x8]] ^S6[x[0xB]];
- Bits32ToInts(zCF, z, 0xC);
- _Km[ 9]= S5[z[0x3]] ^ S6[z[0x2]] ^ S7[z[0xC]] ^ S8[z[0xD]] ^ S5[z[0x9]];
- _Km[10]= S5[z[0x1]] ^ S6[z[0x0]] ^ S7[z[0xE]] ^ S8[z[0xF]] ^ S6[z[0xc]];
- _Km[11]= S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x8]] ^ S8[z[0x9]] ^ S7[z[0x2]];
- _Km[12]= S5[z[0x5]] ^ S6[z[0x4]] ^ S7[z[0xA]] ^ S8[z[0xB]] ^ S8[z[0x6]];
-
- z03 = IntsTo32bits(z, 0x0);
- z47 = IntsTo32bits(z, 0x4);
- z8B = IntsTo32bits(z, 0x8);
- zCF = IntsTo32bits(z, 0xC);
- x03 = z8B ^S5[z[0x5]] ^S6[z[0x7]] ^S7[z[0x4]] ^S8[z[0x6]] ^S7[z[0x0]];
- Bits32ToInts(x03, x, 0x0);
- x47 = z03 ^S5[x[0x0]] ^S6[x[0x2]] ^S7[x[0x1]] ^S8[x[0x3]] ^S8[z[0x2]];
- Bits32ToInts(x47, x, 0x4);
- x8B = z47 ^S5[x[0x7]] ^S6[x[0x6]] ^S7[x[0x5]] ^S8[x[0x4]] ^S5[z[0x1]];
- Bits32ToInts(x8B, x, 0x8);
- xCF = zCF ^S5[x[0xA]] ^S6[x[0x9]] ^S7[x[0xB]] ^S8[x[0x8]] ^S6[z[0x3]];
- Bits32ToInts(xCF, x, 0xC);
- _Km[13]= S5[x[0x8]] ^ S6[x[0x9]] ^ S7[x[0x7]] ^ S8[x[0x6]] ^ S5[x[0x3]];
- _Km[14]= S5[x[0xA]] ^ S6[x[0xB]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S6[x[0x7]];
- _Km[15]= S5[x[0xC]] ^ S6[x[0xD]] ^ S7[x[0x3]] ^ S8[x[0x2]] ^ S7[x[0x8]];
- _Km[16]= S5[x[0xE]] ^ S6[x[0xF]] ^ S7[x[0x1]] ^ S8[x[0x0]] ^ S8[x[0xD]];
-
- x03 = IntsTo32bits(x, 0x0);
- x47 = IntsTo32bits(x, 0x4);
- x8B = IntsTo32bits(x, 0x8);
- xCF = IntsTo32bits(x, 0xC);
- z03 = x03 ^S5[x[0xD]] ^S6[x[0xF]] ^S7[x[0xC]] ^S8[x[0xE]] ^S7[x[0x8]];
- Bits32ToInts(z03, z, 0x0);
- z47 = x8B ^S5[z[0x0]] ^S6[z[0x2]] ^S7[z[0x1]] ^S8[z[0x3]] ^S8[x[0xA]];
- Bits32ToInts(z47, z, 0x4);
- z8B = xCF ^S5[z[0x7]] ^S6[z[0x6]] ^S7[z[0x5]] ^S8[z[0x4]] ^S5[x[0x9]];
- Bits32ToInts(z8B, z, 0x8);
- zCF = x47 ^S5[z[0xA]] ^S6[z[0x9]] ^S7[z[0xB]] ^S8[z[0x8]] ^S6[x[0xB]];
- Bits32ToInts(zCF, z, 0xC);
- _Kr[ 1]=(S5[z[0x8]]^S6[z[0x9]]^S7[z[0x7]]^S8[z[0x6]] ^ S5[z[0x2]])&0x1f;
- _Kr[ 2]=(S5[z[0xA]]^S6[z[0xB]]^S7[z[0x5]]^S8[z[0x4]] ^ S6[z[0x6]])&0x1f;
- _Kr[ 3]=(S5[z[0xC]]^S6[z[0xD]]^S7[z[0x3]]^S8[z[0x2]] ^ S7[z[0x9]])&0x1f;
- _Kr[ 4]=(S5[z[0xE]]^S6[z[0xF]]^S7[z[0x1]]^S8[z[0x0]] ^ S8[z[0xC]])&0x1f;
-
- z03 = IntsTo32bits(z, 0x0);
- z47 = IntsTo32bits(z, 0x4);
- z8B = IntsTo32bits(z, 0x8);
- zCF = IntsTo32bits(z, 0xC);
- x03 = z8B ^S5[z[0x5]] ^S6[z[0x7]] ^S7[z[0x4]] ^S8[z[0x6]] ^S7[z[0x0]];
- Bits32ToInts(x03, x, 0x0);
- x47 = z03 ^S5[x[0x0]] ^S6[x[0x2]] ^S7[x[0x1]] ^S8[x[0x3]] ^S8[z[0x2]];
- Bits32ToInts(x47, x, 0x4);
- x8B = z47 ^S5[x[0x7]] ^S6[x[0x6]] ^S7[x[0x5]] ^S8[x[0x4]] ^S5[z[0x1]];
- Bits32ToInts(x8B, x, 0x8);
- xCF = zCF ^S5[x[0xA]] ^S6[x[0x9]] ^S7[x[0xB]] ^S8[x[0x8]] ^S6[z[0x3]];
- Bits32ToInts(xCF, x, 0xC);
- _Kr[ 5]=(S5[x[0x3]]^S6[x[0x2]]^S7[x[0xC]]^S8[x[0xD]]^S5[x[0x8]])&0x1f;
- _Kr[ 6]=(S5[x[0x1]]^S6[x[0x0]]^S7[x[0xE]]^S8[x[0xF]]^S6[x[0xD]])&0x1f;
- _Kr[ 7]=(S5[x[0x7]]^S6[x[0x6]]^S7[x[0x8]]^S8[x[0x9]]^S7[x[0x3]])&0x1f;
- _Kr[ 8]=(S5[x[0x5]]^S6[x[0x4]]^S7[x[0xA]]^S8[x[0xB]]^S8[x[0x7]])&0x1f;
-
- x03 = IntsTo32bits(x, 0x0);
- x47 = IntsTo32bits(x, 0x4);
- x8B = IntsTo32bits(x, 0x8);
- xCF = IntsTo32bits(x, 0xC);
- z03 = x03 ^S5[x[0xD]] ^S6[x[0xF]] ^S7[x[0xC]] ^S8[x[0xE]] ^S7[x[0x8]];
- Bits32ToInts(z03, z, 0x0);
- z47 = x8B ^S5[z[0x0]] ^S6[z[0x2]] ^S7[z[0x1]] ^S8[z[0x3]] ^S8[x[0xA]];
- Bits32ToInts(z47, z, 0x4);
- z8B = xCF ^S5[z[0x7]] ^S6[z[0x6]] ^S7[z[0x5]] ^S8[z[0x4]] ^S5[x[0x9]];
- Bits32ToInts(z8B, z, 0x8);
- zCF = x47 ^S5[z[0xA]] ^S6[z[0x9]] ^S7[z[0xB]] ^S8[z[0x8]] ^S6[x[0xB]];
- Bits32ToInts(zCF, z, 0xC);
- _Kr[ 9]=(S5[z[0x3]]^S6[z[0x2]]^S7[z[0xC]]^S8[z[0xD]]^S5[z[0x9]])&0x1f;
- _Kr[10]=(S5[z[0x1]]^S6[z[0x0]]^S7[z[0xE]]^S8[z[0xF]]^S6[z[0xc]])&0x1f;
- _Kr[11]=(S5[z[0x7]]^S6[z[0x6]]^S7[z[0x8]]^S8[z[0x9]]^S7[z[0x2]])&0x1f;
- _Kr[12]=(S5[z[0x5]]^S6[z[0x4]]^S7[z[0xA]]^S8[z[0xB]]^S8[z[0x6]])&0x1f;
-
- z03 = IntsTo32bits(z, 0x0);
- z47 = IntsTo32bits(z, 0x4);
- z8B = IntsTo32bits(z, 0x8);
- zCF = IntsTo32bits(z, 0xC);
- x03 = z8B ^S5[z[0x5]] ^S6[z[0x7]] ^S7[z[0x4]] ^S8[z[0x6]] ^S7[z[0x0]];
- Bits32ToInts(x03, x, 0x0);
- x47 = z03 ^S5[x[0x0]] ^S6[x[0x2]] ^S7[x[0x1]] ^S8[x[0x3]] ^S8[z[0x2]];
- Bits32ToInts(x47, x, 0x4);
- x8B = z47 ^S5[x[0x7]] ^S6[x[0x6]] ^S7[x[0x5]] ^S8[x[0x4]] ^S5[z[0x1]];
- Bits32ToInts(x8B, x, 0x8);
- xCF = zCF ^S5[x[0xA]] ^S6[x[0x9]] ^S7[x[0xB]] ^S8[x[0x8]] ^S6[z[0x3]];
- Bits32ToInts(xCF, x, 0xC);
- _Kr[13]=(S5[x[0x8]]^S6[x[0x9]]^S7[x[0x7]]^S8[x[0x6]]^S5[x[0x3]])&0x1f;
- _Kr[14]=(S5[x[0xA]]^S6[x[0xB]]^S7[x[0x5]]^S8[x[0x4]]^S6[x[0x7]])&0x1f;
- _Kr[15]=(S5[x[0xC]]^S6[x[0xD]]^S7[x[0x3]]^S8[x[0x2]]^S7[x[0x8]])&0x1f;
- _Kr[16]=(S5[x[0xE]]^S6[x[0xF]]^S7[x[0x1]]^S8[x[0x0]]^S8[x[0xD]])&0x1f;
- }
-
- /**
- * Encrypt the given input starting at the given offset and place
- * the result in the provided buffer starting at the given offset.
- *
- * @param src The plaintext buffer
- * @param srcIndex An offset into src
- * @param dst The ciphertext buffer
- * @param dstIndex An offset into dst
- */
- protected int encryptBlock(
- byte[] src,
- int srcIndex,
- byte[] dst,
- int dstIndex)
- {
-
- int result[] = new int[2];
-
- // process the input block
- // batch the units up into a 32 bit chunk and go for it
- // the array is in bytes, the increment is 8x8 bits = 64
-
- int L0 = BytesTo32bits(src, srcIndex);
- int R0 = BytesTo32bits(src, srcIndex + 4);
-
- CAST_Encipher(L0, R0, result);
-
- // now stuff them into the destination block
- Bits32ToBytes(result[0], dst, dstIndex);
- Bits32ToBytes(result[1], dst, dstIndex + 4);
-
- return BLOCK_SIZE;
- }
-
- /**
- * Decrypt the given input starting at the given offset and place
- * the result in the provided buffer starting at the given offset.
- *
- * @param src The plaintext buffer
- * @param srcIndex An offset into src
- * @param dst The ciphertext buffer
- * @param dstIndex An offset into dst
- */
- protected int decryptBlock(
- byte[] src,
- int srcIndex,
- byte[] dst,
- int dstIndex)
- {
- int result[] = new int[2];
-
- // process the input block
- // batch the units up into a 32 bit chunk and go for it
- // the array is in bytes, the increment is 8x8 bits = 64
- int L16 = BytesTo32bits(src, srcIndex);
- int R16 = BytesTo32bits(src, srcIndex+4);
-
- CAST_Decipher(L16, R16, result);
-
- // now stuff them into the destination block
- Bits32ToBytes(result[0], dst, dstIndex);
- Bits32ToBytes(result[1], dst, dstIndex+4);
-
- return BLOCK_SIZE;
- }
-
- /**
- * The first of the three processing functions for the
- * encryption and decryption.
- *
- * @param D the input to be processed
- * @param Kmi the mask to be used from Km[n]
- * @param Kri the rotation value to be used
- *
- */
- protected final int F1(int D, int Kmi, int Kri)
- {
- int I = Kmi + D;
- I = I << Kri | I >>> (32-Kri);
- return ((S1[(I>>>24)&0xff]^S2[(I>>>16)&0xff])-S3[(I>>> 8)&0xff])+
- S4[I & 0xff];
- }
-
- /**
- * The second of the three processing functions for the
- * encryption and decryption.
- *
- * @param D the input to be processed
- * @param Kmi the mask to be used from Km[n]
- * @param Kri the rotation value to be used
- *
- */
- protected final int F2(int D, int Kmi, int Kri)
- {
- int I = Kmi ^ D;
- I = I << Kri | I >>> (32-Kri);
- return ((S1[(I>>>24)&0xff]-S2[(I>>>16)&0xff])+S3[(I>>> 8)&0xff])^
- S4[I & 0xff];
- }
-
- /**
- * The third of the three processing functions for the
- * encryption and decryption.
- *
- * @param D the input to be processed
- * @param Kmi the mask to be used from Km[n]
- * @param Kri the rotation value to be used
- *
- */
- protected final int F3(int D, int Kmi, int Kri)
- {
- int I = Kmi - D;
- I = I << Kri | I >>> (32-Kri);
- return ((S1[(I>>>24)&0xff]+S2[(I>>>16)&0xff])^S3[(I>>> 8)&0xff])-
- S4[I & 0xff];
- }
-
- /**
- * Does the 16 rounds to encrypt the block.
- *
- * @param L0 the LH-32bits of the plaintext block
- * @param R0 the RH-32bits of the plaintext block
- */
- protected final void CAST_Encipher(int L0, int R0, int result[])
- {
- int Lp = L0; // the previous value, equiv to L[i-1]
- int Rp = R0; // equivalent to R[i-1]
-
- /*
- * numbering consistent with paper to make
- * checking and validating easier
- */
- int Li = L0, Ri = R0;
-
- for (int i = 1; i<=_rounds ; i++)
- {
- Lp = Li;
- Rp = Ri;
-
- Li = Rp;
- switch (i)
- {
- case 1:
- case 4:
- case 7:
- case 10:
- case 13:
- case 16:
- Ri = Lp ^ F1(Rp, _Km[i], _Kr[i]);
- break;
- case 2:
- case 5:
- case 8:
- case 11:
- case 14:
- Ri = Lp ^ F2(Rp, _Km[i], _Kr[i]);
- break;
- case 3:
- case 6:
- case 9:
- case 12:
- case 15:
- Ri = Lp ^ F3(Rp, _Km[i], _Kr[i]);
- break;
- }
- }
-
- result[0] = Ri;
- result[1] = Li;
-
- return;
- }
-
- protected final void CAST_Decipher(int L16, int R16, int result[])
- {
- int Lp = L16; // the previous value, equiv to L[i-1]
- int Rp = R16; // equivalent to R[i-1]
-
- /*
- * numbering consistent with paper to make
- * checking and validating easier
- */
- int Li = L16, Ri = R16;
-
- for (int i = _rounds; i > 0; i--)
- {
- Lp = Li;
- Rp = Ri;
-
- Li = Rp;
- switch (i)
- {
- case 1:
- case 4:
- case 7:
- case 10:
- case 13:
- case 16:
- Ri = Lp ^ F1(Rp, _Km[i], _Kr[i]);
- break;
- case 2:
- case 5:
- case 8:
- case 11:
- case 14:
- Ri = Lp ^ F2(Rp, _Km[i], _Kr[i]);
- break;
- case 3:
- case 6:
- case 9:
- case 12:
- case 15:
- Ri = Lp ^ F3(Rp, _Km[i], _Kr[i]);
- break;
- }
- }
-
- result[0] = Ri;
- result[1] = Li;
-
- return;
- }
-
- protected final void Bits32ToInts(int in, int[] b, int offset)
- {
- b[offset + 3] = (in & 0xff);
- b[offset + 2] = ((in >>> 8) & 0xff);
- b[offset + 1] = ((in >>> 16) & 0xff);
- b[offset] = ((in >>> 24) & 0xff);
- }
-
- protected final int IntsTo32bits(int[] b, int i)
- {
- int rv = 0;
-
- rv = ((b[i] & 0xff) << 24) |
- ((b[i+1] & 0xff) << 16) |
- ((b[i+2] & 0xff) << 8) |
- ((b[i+3] & 0xff));
-
- return rv;
- }
-
- protected final void Bits32ToBytes(int in, byte[] b, int offset)
- {
- b[offset + 3] = (byte)in;
- b[offset + 2] = (byte)(in >>> 8);
- b[offset + 1] = (byte)(in >>> 16);
- b[offset] = (byte)(in >>> 24);
- }
-
- protected final int BytesTo32bits(byte[] b, int i)
- {
- return ((b[i] & 0xff) << 24) |
- ((b[i+1] & 0xff) << 16) |
- ((b[i+2] & 0xff) << 8) |
- ((b[i+3] & 0xff));
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/CAST6Engine.java b/core/src/main/java/org/bouncycastle/crypto/engines/CAST6Engine.java
deleted file mode 100644
index db57b503..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/CAST6Engine.java
+++ /dev/null
@@ -1,296 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-
-/**
- * A class that provides CAST6 key encryption operations,
- * such as encoding data and generating keys.
- *
- * All the algorithms herein are from the Internet RFC
- *
- * RFC2612 - CAST6 (128bit block, 128-256bit key)
- *
- * and implement a simplified cryptography interface.
- */
-public final class CAST6Engine extends CAST5Engine
-{
- //====================================
- // Useful constants
- //====================================
-
- protected static final int ROUNDS = 12;
-
- protected static final int BLOCK_SIZE = 16; // bytes = 128 bits
-
- /*
- * Put the round and mask keys into an array.
- * Kr0[i] => _Kr[i*4 + 0]
- */
- protected int _Kr[] = new int[ROUNDS*4]; // the rotating round key(s)
- protected int _Km[] = new int[ROUNDS*4]; // the masking round key(s)
-
- /*
- * Key setup
- */
- protected int _Tr[] = new int[24 * 8];
- protected int _Tm[] = new int[24 * 8];
-
- private int[] _workingKey = new int[8];
-
- public CAST6Engine()
- {
- }
-
- public String getAlgorithmName()
- {
- return "CAST6";
- }
-
- public void reset()
- {
- }
-
- public int getBlockSize()
- {
- return BLOCK_SIZE;
- }
-
- //==================================
- // Private Implementation
- //==================================
-
- /*
- * Creates the subkeys using the same nomenclature
- * as described in RFC2612.
- *
- * See section 2.4
- */
- protected void setKey(byte[] key)
- {
- int Cm = 0x5a827999;
- int Mm = 0x6ed9eba1;
- int Cr = 19;
- int Mr = 17;
-
- /*
- * Determine the key size here, if required
- *
- * if keysize < 256 bytes, pad with 0
- *
- * Typical key sizes => 128, 160, 192, 224, 256
- */
- for (int i=0; i< 24; i++)
- {
- for (int j=0; j< 8; j++)
- {
- _Tm[i*8 + j] = Cm;
- Cm = (Cm + Mm); // mod 2^32;
-
- _Tr[i*8 + j] = Cr;
- Cr = (Cr + Mr) & 0x1f; // mod 32
- }
- }
-
- byte[] tmpKey = new byte[64];
- int length = key.length;
- System.arraycopy(key, 0, tmpKey, 0, length);
-
- // now create ABCDEFGH
- for (int i=0; i< 8; i++)
- {
- _workingKey[i] = BytesTo32bits(tmpKey, i*4);
- }
-
- // Generate the key schedule
- for (int i=0; i< 12; i++)
- {
- // KAPPA <- W2i(KAPPA)
- int i2 = i*2 *8;
- _workingKey[6] ^= F1(_workingKey[7], _Tm[i2 ], _Tr[i2 ]);
- _workingKey[5] ^= F2(_workingKey[6], _Tm[i2+1], _Tr[i2+1]);
- _workingKey[4] ^= F3(_workingKey[5], _Tm[i2+2], _Tr[i2+2]);
- _workingKey[3] ^= F1(_workingKey[4], _Tm[i2+3], _Tr[i2+3]);
- _workingKey[2] ^= F2(_workingKey[3], _Tm[i2+4], _Tr[i2+4]);
- _workingKey[1] ^= F3(_workingKey[2], _Tm[i2+5], _Tr[i2+5]);
- _workingKey[0] ^= F1(_workingKey[1], _Tm[i2+6], _Tr[i2+6]);
- _workingKey[7] ^= F2(_workingKey[0], _Tm[i2+7], _Tr[i2+7]);
-
- // KAPPA <- W2i+1(KAPPA)
- i2 = (i*2 + 1)*8;
- _workingKey[6] ^= F1(_workingKey[7], _Tm[i2 ], _Tr[i2 ]);
- _workingKey[5] ^= F2(_workingKey[6], _Tm[i2+1], _Tr[i2+1]);
- _workingKey[4] ^= F3(_workingKey[5], _Tm[i2+2], _Tr[i2+2]);
- _workingKey[3] ^= F1(_workingKey[4], _Tm[i2+3], _Tr[i2+3]);
- _workingKey[2] ^= F2(_workingKey[3], _Tm[i2+4], _Tr[i2+4]);
- _workingKey[1] ^= F3(_workingKey[2], _Tm[i2+5], _Tr[i2+5]);
- _workingKey[0] ^= F1(_workingKey[1], _Tm[i2+6], _Tr[i2+6]);
- _workingKey[7] ^= F2(_workingKey[0], _Tm[i2+7], _Tr[i2+7]);
-
- // Kr_(i) <- KAPPA
- _Kr[i*4 ] = _workingKey[0] & 0x1f;
- _Kr[i*4 + 1] = _workingKey[2] & 0x1f;
- _Kr[i*4 + 2] = _workingKey[4] & 0x1f;
- _Kr[i*4 + 3] = _workingKey[6] & 0x1f;
-
-
- // Km_(i) <- KAPPA
- _Km[i*4 ] = _workingKey[7];
- _Km[i*4 + 1] = _workingKey[5];
- _Km[i*4 + 2] = _workingKey[3];
- _Km[i*4 + 3] = _workingKey[1];
- }
-
- }
-
- /**
- * Encrypt the given input starting at the given offset and place
- * the result in the provided buffer starting at the given offset.
- *
- * @param src The plaintext buffer
- * @param srcIndex An offset into src
- * @param dst The ciphertext buffer
- * @param dstIndex An offset into dst
- */
- protected int encryptBlock(
- byte[] src,
- int srcIndex,
- byte[] dst,
- int dstIndex)
- {
-
- int result[] = new int[4];
-
- // process the input block
- // batch the units up into 4x32 bit chunks and go for it
-
- int A = BytesTo32bits(src, srcIndex);
- int B = BytesTo32bits(src, srcIndex + 4);
- int C = BytesTo32bits(src, srcIndex + 8);
- int D = BytesTo32bits(src, srcIndex + 12);
-
- CAST_Encipher(A, B, C, D, result);
-
- // now stuff them into the destination block
- Bits32ToBytes(result[0], dst, dstIndex);
- Bits32ToBytes(result[1], dst, dstIndex + 4);
- Bits32ToBytes(result[2], dst, dstIndex + 8);
- Bits32ToBytes(result[3], dst, dstIndex + 12);
-
- return BLOCK_SIZE;
- }
-
- /**
- * Decrypt the given input starting at the given offset and place
- * the result in the provided buffer starting at the given offset.
- *
- * @param src The plaintext buffer
- * @param srcIndex An offset into src
- * @param dst The ciphertext buffer
- * @param dstIndex An offset into dst
- */
- protected int decryptBlock(
- byte[] src,
- int srcIndex,
- byte[] dst,
- int dstIndex)
- {
- int result[] = new int[4];
-
- // process the input block
- // batch the units up into 4x32 bit chunks and go for it
- int A = BytesTo32bits(src, srcIndex);
- int B = BytesTo32bits(src, srcIndex + 4);
- int C = BytesTo32bits(src, srcIndex + 8);
- int D = BytesTo32bits(src, srcIndex + 12);
-
- CAST_Decipher(A, B, C, D, result);
-
- // now stuff them into the destination block
- Bits32ToBytes(result[0], dst, dstIndex);
- Bits32ToBytes(result[1], dst, dstIndex + 4);
- Bits32ToBytes(result[2], dst, dstIndex + 8);
- Bits32ToBytes(result[3], dst, dstIndex + 12);
-
- return BLOCK_SIZE;
- }
-
- /**
- * Does the 12 quad rounds rounds to encrypt the block.
- *
- * @param A the 00-31 bits of the plaintext block
- * @param B the 32-63 bits of the plaintext block
- * @param C the 64-95 bits of the plaintext block
- * @param D the 96-127 bits of the plaintext block
- * @param result the resulting ciphertext
- */
- protected final void CAST_Encipher(int A, int B, int C, int D,int result[])
- {
- int x;
- for (int i=0; i< 6; i++)
- {
- x = i*4;
- // BETA <- Qi(BETA)
- C ^= F1(D, _Km[x], _Kr[x]);
- B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
- A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
- D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
-
- }
-
- for (int i=6; i<12; i++)
- {
- x = i*4;
- // BETA <- QBARi(BETA)
- D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
- A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
- B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
- C ^= F1(D, _Km[x], _Kr[x]);
-
- }
-
- result[0] = A;
- result[1] = B;
- result[2] = C;
- result[3] = D;
- }
-
- /**
- * Does the 12 quad rounds rounds to decrypt the block.
- *
- * @param A the 00-31 bits of the ciphertext block
- * @param B the 32-63 bits of the ciphertext block
- * @param C the 64-95 bits of the ciphertext block
- * @param D the 96-127 bits of the ciphertext block
- * @param result the resulting plaintext
- */
- protected final void CAST_Decipher(int A, int B, int C, int D,int result[])
- {
- int x;
- for (int i=0; i< 6; i++)
- {
- x = (11-i)*4;
- // BETA <- Qi(BETA)
- C ^= F1(D, _Km[x], _Kr[x]);
- B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
- A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
- D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
-
- }
-
- for (int i=6; i<12; i++)
- {
- x = (11-i)*4;
- // BETA <- QBARi(BETA)
- D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
- A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
- B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
- C ^= F1(D, _Km[x], _Kr[x]);
-
- }
-
- result[0] = A;
- result[1] = B;
- result[2] = C;
- result[3] = D;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/CamelliaEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/CamelliaEngine.java
deleted file mode 100644
index a486e1b5..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/CamelliaEngine.java
+++ /dev/null
@@ -1,684 +0,0 @@
-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;
-
-/**
- * Camellia - based on RFC 3713.
- */
-public class CamelliaEngine
- implements BlockCipher
-{
- private boolean initialised = false;
- private boolean _keyIs128;
-
- private static final int BLOCK_SIZE = 16;
- private static final int MASK8 = 0xff;
-
- private int[] subkey = new int[24 * 4];
- private int[] kw = new int[4 * 2]; // for whitening
- private int[] ke = new int[6 * 2]; // for FL and FL^(-1)
- private int[] state = new int[4]; // for encryption and decryption
-
- private static final int SIGMA[] = {
- 0xa09e667f, 0x3bcc908b,
- 0xb67ae858, 0x4caa73b2,
- 0xc6ef372f, 0xe94f82be,
- 0x54ff53a5, 0xf1d36f1c,
- 0x10e527fa, 0xde682d1d,
- 0xb05688c2, 0xb3e6c1fd
- };
-
- /*
- *
- * S-box data
- *
- */
- private static final int SBOX1_1110[] = {
- 0x70707000, 0x82828200, 0x2c2c2c00, 0xececec00, 0xb3b3b300, 0x27272700,
- 0xc0c0c000, 0xe5e5e500, 0xe4e4e400, 0x85858500, 0x57575700, 0x35353500,
- 0xeaeaea00, 0x0c0c0c00, 0xaeaeae00, 0x41414100, 0x23232300, 0xefefef00,
- 0x6b6b6b00, 0x93939300, 0x45454500, 0x19191900, 0xa5a5a500, 0x21212100,
- 0xededed00, 0x0e0e0e00, 0x4f4f4f00, 0x4e4e4e00, 0x1d1d1d00, 0x65656500,
- 0x92929200, 0xbdbdbd00, 0x86868600, 0xb8b8b800, 0xafafaf00, 0x8f8f8f00,
- 0x7c7c7c00, 0xebebeb00, 0x1f1f1f00, 0xcecece00, 0x3e3e3e00, 0x30303000,
- 0xdcdcdc00, 0x5f5f5f00, 0x5e5e5e00, 0xc5c5c500, 0x0b0b0b00, 0x1a1a1a00,
- 0xa6a6a600, 0xe1e1e100, 0x39393900, 0xcacaca00, 0xd5d5d500, 0x47474700,
- 0x5d5d5d00, 0x3d3d3d00, 0xd9d9d900, 0x01010100, 0x5a5a5a00, 0xd6d6d600,
- 0x51515100, 0x56565600, 0x6c6c6c00, 0x4d4d4d00, 0x8b8b8b00, 0x0d0d0d00,
- 0x9a9a9a00, 0x66666600, 0xfbfbfb00, 0xcccccc00, 0xb0b0b000, 0x2d2d2d00,
- 0x74747400, 0x12121200, 0x2b2b2b00, 0x20202000, 0xf0f0f000, 0xb1b1b100,
- 0x84848400, 0x99999900, 0xdfdfdf00, 0x4c4c4c00, 0xcbcbcb00, 0xc2c2c200,
- 0x34343400, 0x7e7e7e00, 0x76767600, 0x05050500, 0x6d6d6d00, 0xb7b7b700,
- 0xa9a9a900, 0x31313100, 0xd1d1d100, 0x17171700, 0x04040400, 0xd7d7d700,
- 0x14141400, 0x58585800, 0x3a3a3a00, 0x61616100, 0xdedede00, 0x1b1b1b00,
- 0x11111100, 0x1c1c1c00, 0x32323200, 0x0f0f0f00, 0x9c9c9c00, 0x16161600,
- 0x53535300, 0x18181800, 0xf2f2f200, 0x22222200, 0xfefefe00, 0x44444400,
- 0xcfcfcf00, 0xb2b2b200, 0xc3c3c300, 0xb5b5b500, 0x7a7a7a00, 0x91919100,
- 0x24242400, 0x08080800, 0xe8e8e800, 0xa8a8a800, 0x60606000, 0xfcfcfc00,
- 0x69696900, 0x50505000, 0xaaaaaa00, 0xd0d0d000, 0xa0a0a000, 0x7d7d7d00,
- 0xa1a1a100, 0x89898900, 0x62626200, 0x97979700, 0x54545400, 0x5b5b5b00,
- 0x1e1e1e00, 0x95959500, 0xe0e0e000, 0xffffff00, 0x64646400, 0xd2d2d200,
- 0x10101000, 0xc4c4c400, 0x00000000, 0x48484800, 0xa3a3a300, 0xf7f7f700,
- 0x75757500, 0xdbdbdb00, 0x8a8a8a00, 0x03030300, 0xe6e6e600, 0xdadada00,
- 0x09090900, 0x3f3f3f00, 0xdddddd00, 0x94949400, 0x87878700, 0x5c5c5c00,
- 0x83838300, 0x02020200, 0xcdcdcd00, 0x4a4a4a00, 0x90909000, 0x33333300,
- 0x73737300, 0x67676700, 0xf6f6f600, 0xf3f3f300, 0x9d9d9d00, 0x7f7f7f00,
- 0xbfbfbf00, 0xe2e2e200, 0x52525200, 0x9b9b9b00, 0xd8d8d800, 0x26262600,
- 0xc8c8c800, 0x37373700, 0xc6c6c600, 0x3b3b3b00, 0x81818100, 0x96969600,
- 0x6f6f6f00, 0x4b4b4b00, 0x13131300, 0xbebebe00, 0x63636300, 0x2e2e2e00,
- 0xe9e9e900, 0x79797900, 0xa7a7a700, 0x8c8c8c00, 0x9f9f9f00, 0x6e6e6e00,
- 0xbcbcbc00, 0x8e8e8e00, 0x29292900, 0xf5f5f500, 0xf9f9f900, 0xb6b6b600,
- 0x2f2f2f00, 0xfdfdfd00, 0xb4b4b400, 0x59595900, 0x78787800, 0x98989800,
- 0x06060600, 0x6a6a6a00, 0xe7e7e700, 0x46464600, 0x71717100, 0xbababa00,
- 0xd4d4d400, 0x25252500, 0xababab00, 0x42424200, 0x88888800, 0xa2a2a200,
- 0x8d8d8d00, 0xfafafa00, 0x72727200, 0x07070700, 0xb9b9b900, 0x55555500,
- 0xf8f8f800, 0xeeeeee00, 0xacacac00, 0x0a0a0a00, 0x36363600, 0x49494900,
- 0x2a2a2a00, 0x68686800, 0x3c3c3c00, 0x38383800, 0xf1f1f100, 0xa4a4a400,
- 0x40404000, 0x28282800, 0xd3d3d300, 0x7b7b7b00, 0xbbbbbb00, 0xc9c9c900,
- 0x43434300, 0xc1c1c100, 0x15151500, 0xe3e3e300, 0xadadad00, 0xf4f4f400,
- 0x77777700, 0xc7c7c700, 0x80808000, 0x9e9e9e00
- };
-
- private static final int SBOX4_4404[] = {
- 0x70700070, 0x2c2c002c, 0xb3b300b3, 0xc0c000c0, 0xe4e400e4, 0x57570057,
- 0xeaea00ea, 0xaeae00ae, 0x23230023, 0x6b6b006b, 0x45450045, 0xa5a500a5,
- 0xeded00ed, 0x4f4f004f, 0x1d1d001d, 0x92920092, 0x86860086, 0xafaf00af,
- 0x7c7c007c, 0x1f1f001f, 0x3e3e003e, 0xdcdc00dc, 0x5e5e005e, 0x0b0b000b,
- 0xa6a600a6, 0x39390039, 0xd5d500d5, 0x5d5d005d, 0xd9d900d9, 0x5a5a005a,
- 0x51510051, 0x6c6c006c, 0x8b8b008b, 0x9a9a009a, 0xfbfb00fb, 0xb0b000b0,
- 0x74740074, 0x2b2b002b, 0xf0f000f0, 0x84840084, 0xdfdf00df, 0xcbcb00cb,
- 0x34340034, 0x76760076, 0x6d6d006d, 0xa9a900a9, 0xd1d100d1, 0x04040004,
- 0x14140014, 0x3a3a003a, 0xdede00de, 0x11110011, 0x32320032, 0x9c9c009c,
- 0x53530053, 0xf2f200f2, 0xfefe00fe, 0xcfcf00cf, 0xc3c300c3, 0x7a7a007a,
- 0x24240024, 0xe8e800e8, 0x60600060, 0x69690069, 0xaaaa00aa, 0xa0a000a0,
- 0xa1a100a1, 0x62620062, 0x54540054, 0x1e1e001e, 0xe0e000e0, 0x64640064,
- 0x10100010, 0x00000000, 0xa3a300a3, 0x75750075, 0x8a8a008a, 0xe6e600e6,
- 0x09090009, 0xdddd00dd, 0x87870087, 0x83830083, 0xcdcd00cd, 0x90900090,
- 0x73730073, 0xf6f600f6, 0x9d9d009d, 0xbfbf00bf, 0x52520052, 0xd8d800d8,
- 0xc8c800c8, 0xc6c600c6, 0x81810081, 0x6f6f006f, 0x13130013, 0x63630063,
- 0xe9e900e9, 0xa7a700a7, 0x9f9f009f, 0xbcbc00bc, 0x29290029, 0xf9f900f9,
- 0x2f2f002f, 0xb4b400b4, 0x78780078, 0x06060006, 0xe7e700e7, 0x71710071,
- 0xd4d400d4, 0xabab00ab, 0x88880088, 0x8d8d008d, 0x72720072, 0xb9b900b9,
- 0xf8f800f8, 0xacac00ac, 0x36360036, 0x2a2a002a, 0x3c3c003c, 0xf1f100f1,
- 0x40400040, 0xd3d300d3, 0xbbbb00bb, 0x43430043, 0x15150015, 0xadad00ad,
- 0x77770077, 0x80800080, 0x82820082, 0xecec00ec, 0x27270027, 0xe5e500e5,
- 0x85850085, 0x35350035, 0x0c0c000c, 0x41410041, 0xefef00ef, 0x93930093,
- 0x19190019, 0x21210021, 0x0e0e000e, 0x4e4e004e, 0x65650065, 0xbdbd00bd,
- 0xb8b800b8, 0x8f8f008f, 0xebeb00eb, 0xcece00ce, 0x30300030, 0x5f5f005f,
- 0xc5c500c5, 0x1a1a001a, 0xe1e100e1, 0xcaca00ca, 0x47470047, 0x3d3d003d,
- 0x01010001, 0xd6d600d6, 0x56560056, 0x4d4d004d, 0x0d0d000d, 0x66660066,
- 0xcccc00cc, 0x2d2d002d, 0x12120012, 0x20200020, 0xb1b100b1, 0x99990099,
- 0x4c4c004c, 0xc2c200c2, 0x7e7e007e, 0x05050005, 0xb7b700b7, 0x31310031,
- 0x17170017, 0xd7d700d7, 0x58580058, 0x61610061, 0x1b1b001b, 0x1c1c001c,
- 0x0f0f000f, 0x16160016, 0x18180018, 0x22220022, 0x44440044, 0xb2b200b2,
- 0xb5b500b5, 0x91910091, 0x08080008, 0xa8a800a8, 0xfcfc00fc, 0x50500050,
- 0xd0d000d0, 0x7d7d007d, 0x89890089, 0x97970097, 0x5b5b005b, 0x95950095,
- 0xffff00ff, 0xd2d200d2, 0xc4c400c4, 0x48480048, 0xf7f700f7, 0xdbdb00db,
- 0x03030003, 0xdada00da, 0x3f3f003f, 0x94940094, 0x5c5c005c, 0x02020002,
- 0x4a4a004a, 0x33330033, 0x67670067, 0xf3f300f3, 0x7f7f007f, 0xe2e200e2,
- 0x9b9b009b, 0x26260026, 0x37370037, 0x3b3b003b, 0x96960096, 0x4b4b004b,
- 0xbebe00be, 0x2e2e002e, 0x79790079, 0x8c8c008c, 0x6e6e006e, 0x8e8e008e,
- 0xf5f500f5, 0xb6b600b6, 0xfdfd00fd, 0x59590059, 0x98980098, 0x6a6a006a,
- 0x46460046, 0xbaba00ba, 0x25250025, 0x42420042, 0xa2a200a2, 0xfafa00fa,
- 0x07070007, 0x55550055, 0xeeee00ee, 0x0a0a000a, 0x49490049, 0x68680068,
- 0x38380038, 0xa4a400a4, 0x28280028, 0x7b7b007b, 0xc9c900c9, 0xc1c100c1,
- 0xe3e300e3, 0xf4f400f4, 0xc7c700c7, 0x9e9e009e
- };
-
- private static final int SBOX2_0222[] = {
- 0x00e0e0e0, 0x00050505, 0x00585858, 0x00d9d9d9, 0x00676767, 0x004e4e4e,
- 0x00818181, 0x00cbcbcb, 0x00c9c9c9, 0x000b0b0b, 0x00aeaeae, 0x006a6a6a,
- 0x00d5d5d5, 0x00181818, 0x005d5d5d, 0x00828282, 0x00464646, 0x00dfdfdf,
- 0x00d6d6d6, 0x00272727, 0x008a8a8a, 0x00323232, 0x004b4b4b, 0x00424242,
- 0x00dbdbdb, 0x001c1c1c, 0x009e9e9e, 0x009c9c9c, 0x003a3a3a, 0x00cacaca,
- 0x00252525, 0x007b7b7b, 0x000d0d0d, 0x00717171, 0x005f5f5f, 0x001f1f1f,
- 0x00f8f8f8, 0x00d7d7d7, 0x003e3e3e, 0x009d9d9d, 0x007c7c7c, 0x00606060,
- 0x00b9b9b9, 0x00bebebe, 0x00bcbcbc, 0x008b8b8b, 0x00161616, 0x00343434,
- 0x004d4d4d, 0x00c3c3c3, 0x00727272, 0x00959595, 0x00ababab, 0x008e8e8e,
- 0x00bababa, 0x007a7a7a, 0x00b3b3b3, 0x00020202, 0x00b4b4b4, 0x00adadad,
- 0x00a2a2a2, 0x00acacac, 0x00d8d8d8, 0x009a9a9a, 0x00171717, 0x001a1a1a,
- 0x00353535, 0x00cccccc, 0x00f7f7f7, 0x00999999, 0x00616161, 0x005a5a5a,
- 0x00e8e8e8, 0x00242424, 0x00565656, 0x00404040, 0x00e1e1e1, 0x00636363,
- 0x00090909, 0x00333333, 0x00bfbfbf, 0x00989898, 0x00979797, 0x00858585,
- 0x00686868, 0x00fcfcfc, 0x00ececec, 0x000a0a0a, 0x00dadada, 0x006f6f6f,
- 0x00535353, 0x00626262, 0x00a3a3a3, 0x002e2e2e, 0x00080808, 0x00afafaf,
- 0x00282828, 0x00b0b0b0, 0x00747474, 0x00c2c2c2, 0x00bdbdbd, 0x00363636,
- 0x00222222, 0x00383838, 0x00646464, 0x001e1e1e, 0x00393939, 0x002c2c2c,
- 0x00a6a6a6, 0x00303030, 0x00e5e5e5, 0x00444444, 0x00fdfdfd, 0x00888888,
- 0x009f9f9f, 0x00656565, 0x00878787, 0x006b6b6b, 0x00f4f4f4, 0x00232323,
- 0x00484848, 0x00101010, 0x00d1d1d1, 0x00515151, 0x00c0c0c0, 0x00f9f9f9,
- 0x00d2d2d2, 0x00a0a0a0, 0x00555555, 0x00a1a1a1, 0x00414141, 0x00fafafa,
- 0x00434343, 0x00131313, 0x00c4c4c4, 0x002f2f2f, 0x00a8a8a8, 0x00b6b6b6,
- 0x003c3c3c, 0x002b2b2b, 0x00c1c1c1, 0x00ffffff, 0x00c8c8c8, 0x00a5a5a5,
- 0x00202020, 0x00898989, 0x00000000, 0x00909090, 0x00474747, 0x00efefef,
- 0x00eaeaea, 0x00b7b7b7, 0x00151515, 0x00060606, 0x00cdcdcd, 0x00b5b5b5,
- 0x00121212, 0x007e7e7e, 0x00bbbbbb, 0x00292929, 0x000f0f0f, 0x00b8b8b8,
- 0x00070707, 0x00040404, 0x009b9b9b, 0x00949494, 0x00212121, 0x00666666,
- 0x00e6e6e6, 0x00cecece, 0x00ededed, 0x00e7e7e7, 0x003b3b3b, 0x00fefefe,
- 0x007f7f7f, 0x00c5c5c5, 0x00a4a4a4, 0x00373737, 0x00b1b1b1, 0x004c4c4c,
- 0x00919191, 0x006e6e6e, 0x008d8d8d, 0x00767676, 0x00030303, 0x002d2d2d,
- 0x00dedede, 0x00969696, 0x00262626, 0x007d7d7d, 0x00c6c6c6, 0x005c5c5c,
- 0x00d3d3d3, 0x00f2f2f2, 0x004f4f4f, 0x00191919, 0x003f3f3f, 0x00dcdcdc,
- 0x00797979, 0x001d1d1d, 0x00525252, 0x00ebebeb, 0x00f3f3f3, 0x006d6d6d,
- 0x005e5e5e, 0x00fbfbfb, 0x00696969, 0x00b2b2b2, 0x00f0f0f0, 0x00313131,
- 0x000c0c0c, 0x00d4d4d4, 0x00cfcfcf, 0x008c8c8c, 0x00e2e2e2, 0x00757575,
- 0x00a9a9a9, 0x004a4a4a, 0x00575757, 0x00848484, 0x00111111, 0x00454545,
- 0x001b1b1b, 0x00f5f5f5, 0x00e4e4e4, 0x000e0e0e, 0x00737373, 0x00aaaaaa,
- 0x00f1f1f1, 0x00dddddd, 0x00595959, 0x00141414, 0x006c6c6c, 0x00929292,
- 0x00545454, 0x00d0d0d0, 0x00787878, 0x00707070, 0x00e3e3e3, 0x00494949,
- 0x00808080, 0x00505050, 0x00a7a7a7, 0x00f6f6f6, 0x00777777, 0x00939393,
- 0x00868686, 0x00838383, 0x002a2a2a, 0x00c7c7c7, 0x005b5b5b, 0x00e9e9e9,
- 0x00eeeeee, 0x008f8f8f, 0x00010101, 0x003d3d3d
- };
-
- private static final int SBOX3_3033[] = {
- 0x38003838, 0x41004141, 0x16001616, 0x76007676, 0xd900d9d9, 0x93009393,
- 0x60006060, 0xf200f2f2, 0x72007272, 0xc200c2c2, 0xab00abab, 0x9a009a9a,
- 0x75007575, 0x06000606, 0x57005757, 0xa000a0a0, 0x91009191, 0xf700f7f7,
- 0xb500b5b5, 0xc900c9c9, 0xa200a2a2, 0x8c008c8c, 0xd200d2d2, 0x90009090,
- 0xf600f6f6, 0x07000707, 0xa700a7a7, 0x27002727, 0x8e008e8e, 0xb200b2b2,
- 0x49004949, 0xde00dede, 0x43004343, 0x5c005c5c, 0xd700d7d7, 0xc700c7c7,
- 0x3e003e3e, 0xf500f5f5, 0x8f008f8f, 0x67006767, 0x1f001f1f, 0x18001818,
- 0x6e006e6e, 0xaf00afaf, 0x2f002f2f, 0xe200e2e2, 0x85008585, 0x0d000d0d,
- 0x53005353, 0xf000f0f0, 0x9c009c9c, 0x65006565, 0xea00eaea, 0xa300a3a3,
- 0xae00aeae, 0x9e009e9e, 0xec00ecec, 0x80008080, 0x2d002d2d, 0x6b006b6b,
- 0xa800a8a8, 0x2b002b2b, 0x36003636, 0xa600a6a6, 0xc500c5c5, 0x86008686,
- 0x4d004d4d, 0x33003333, 0xfd00fdfd, 0x66006666, 0x58005858, 0x96009696,
- 0x3a003a3a, 0x09000909, 0x95009595, 0x10001010, 0x78007878, 0xd800d8d8,
- 0x42004242, 0xcc00cccc, 0xef00efef, 0x26002626, 0xe500e5e5, 0x61006161,
- 0x1a001a1a, 0x3f003f3f, 0x3b003b3b, 0x82008282, 0xb600b6b6, 0xdb00dbdb,
- 0xd400d4d4, 0x98009898, 0xe800e8e8, 0x8b008b8b, 0x02000202, 0xeb00ebeb,
- 0x0a000a0a, 0x2c002c2c, 0x1d001d1d, 0xb000b0b0, 0x6f006f6f, 0x8d008d8d,
- 0x88008888, 0x0e000e0e, 0x19001919, 0x87008787, 0x4e004e4e, 0x0b000b0b,
- 0xa900a9a9, 0x0c000c0c, 0x79007979, 0x11001111, 0x7f007f7f, 0x22002222,
- 0xe700e7e7, 0x59005959, 0xe100e1e1, 0xda00dada, 0x3d003d3d, 0xc800c8c8,
- 0x12001212, 0x04000404, 0x74007474, 0x54005454, 0x30003030, 0x7e007e7e,
- 0xb400b4b4, 0x28002828, 0x55005555, 0x68006868, 0x50005050, 0xbe00bebe,
- 0xd000d0d0, 0xc400c4c4, 0x31003131, 0xcb00cbcb, 0x2a002a2a, 0xad00adad,
- 0x0f000f0f, 0xca00caca, 0x70007070, 0xff00ffff, 0x32003232, 0x69006969,
- 0x08000808, 0x62006262, 0x00000000, 0x24002424, 0xd100d1d1, 0xfb00fbfb,
- 0xba00baba, 0xed00eded, 0x45004545, 0x81008181, 0x73007373, 0x6d006d6d,
- 0x84008484, 0x9f009f9f, 0xee00eeee, 0x4a004a4a, 0xc300c3c3, 0x2e002e2e,
- 0xc100c1c1, 0x01000101, 0xe600e6e6, 0x25002525, 0x48004848, 0x99009999,
- 0xb900b9b9, 0xb300b3b3, 0x7b007b7b, 0xf900f9f9, 0xce00cece, 0xbf00bfbf,
- 0xdf00dfdf, 0x71007171, 0x29002929, 0xcd00cdcd, 0x6c006c6c, 0x13001313,
- 0x64006464, 0x9b009b9b, 0x63006363, 0x9d009d9d, 0xc000c0c0, 0x4b004b4b,
- 0xb700b7b7, 0xa500a5a5, 0x89008989, 0x5f005f5f, 0xb100b1b1, 0x17001717,
- 0xf400f4f4, 0xbc00bcbc, 0xd300d3d3, 0x46004646, 0xcf00cfcf, 0x37003737,
- 0x5e005e5e, 0x47004747, 0x94009494, 0xfa00fafa, 0xfc00fcfc, 0x5b005b5b,
- 0x97009797, 0xfe00fefe, 0x5a005a5a, 0xac00acac, 0x3c003c3c, 0x4c004c4c,
- 0x03000303, 0x35003535, 0xf300f3f3, 0x23002323, 0xb800b8b8, 0x5d005d5d,
- 0x6a006a6a, 0x92009292, 0xd500d5d5, 0x21002121, 0x44004444, 0x51005151,
- 0xc600c6c6, 0x7d007d7d, 0x39003939, 0x83008383, 0xdc00dcdc, 0xaa00aaaa,
- 0x7c007c7c, 0x77007777, 0x56005656, 0x05000505, 0x1b001b1b, 0xa400a4a4,
- 0x15001515, 0x34003434, 0x1e001e1e, 0x1c001c1c, 0xf800f8f8, 0x52005252,
- 0x20002020, 0x14001414, 0xe900e9e9, 0xbd00bdbd, 0xdd00dddd, 0xe400e4e4,
- 0xa100a1a1, 0xe000e0e0, 0x8a008a8a, 0xf100f1f1, 0xd600d6d6, 0x7a007a7a,
- 0xbb00bbbb, 0xe300e3e3, 0x40004040, 0x4f004f4f
- };
-
- private static int rightRotate(int x, int s)
- {
- return (((x) >>> (s)) + ((x) << (32 - s)));
- }
-
- private static int leftRotate(int x, int s)
- {
- return ((x) << (s)) + ((x) >>> (32 - s));
- }
-
- private static void roldq(int rot, int[] ki, int ioff,
- int[] ko, int ooff)
- {
- ko[0 + ooff] = (ki[0 + ioff] << rot) | (ki[1 + ioff] >>> (32 - rot));
- ko[1 + ooff] = (ki[1 + ioff] << rot) | (ki[2 + ioff] >>> (32 - rot));
- ko[2 + ooff] = (ki[2 + ioff] << rot) | (ki[3 + ioff] >>> (32 - rot));
- ko[3 + ooff] = (ki[3 + ioff] << rot) | (ki[0 + ioff] >>> (32 - rot));
- ki[0 + ioff] = ko[0 + ooff];
- ki[1 + ioff] = ko[1 + ooff];
- ki[2 + ioff] = ko[2 + ooff];
- ki[3 + ioff] = ko[3 + ooff];
- }
-
- private static void decroldq(int rot, int[] ki, int ioff,
- int[] ko, int ooff)
- {
- ko[2 + ooff] = (ki[0 + ioff] << rot) | (ki[1 + ioff] >>> (32 - rot));
- ko[3 + ooff] = (ki[1 + ioff] << rot) | (ki[2 + ioff] >>> (32 - rot));
- ko[0 + ooff] = (ki[2 + ioff] << rot) | (ki[3 + ioff] >>> (32 - rot));
- ko[1 + ooff] = (ki[3 + ioff] << rot) | (ki[0 + ioff] >>> (32 - rot));
- ki[0 + ioff] = ko[2 + ooff];
- ki[1 + ioff] = ko[3 + ooff];
- ki[2 + ioff] = ko[0 + ooff];
- ki[3 + ioff] = ko[1 + ooff];
- }
-
- private static void roldqo32(int rot, int[] ki, int ioff,
- int[] ko, int ooff)
- {
- ko[0 + ooff] = (ki[1 + ioff] << (rot - 32)) | (ki[2 + ioff] >>> (64 - rot));
- ko[1 + ooff] = (ki[2 + ioff] << (rot - 32)) | (ki[3 + ioff] >>> (64 - rot));
- ko[2 + ooff] = (ki[3 + ioff] << (rot - 32)) | (ki[0 + ioff] >>> (64 - rot));
- ko[3 + ooff] = (ki[0 + ioff] << (rot - 32)) | (ki[1 + ioff] >>> (64 - rot));
- ki[0 + ioff] = ko[0 + ooff];
- ki[1 + ioff] = ko[1 + ooff];
- ki[2 + ioff] = ko[2 + ooff];
- ki[3 + ioff] = ko[3 + ooff];
- }
-
- private static void decroldqo32(int rot, int[] ki, int ioff,
- int[] ko, int ooff)
- {
- ko[2 + ooff] = (ki[1 + ioff] << (rot - 32)) | (ki[2 + ioff] >>> (64 - rot));
- ko[3 + ooff] = (ki[2 + ioff] << (rot - 32)) | (ki[3 + ioff] >>> (64 - rot));
- ko[0 + ooff] = (ki[3 + ioff] << (rot - 32)) | (ki[0 + ioff] >>> (64 - rot));
- ko[1 + ooff] = (ki[0 + ioff] << (rot - 32)) | (ki[1 + ioff] >>> (64 - rot));
- ki[0 + ioff] = ko[2 + ooff];
- ki[1 + ioff] = ko[3 + ooff];
- ki[2 + ioff] = ko[0 + ooff];
- ki[3 + ioff] = ko[1 + ooff];
- }
-
- private int bytes2int(byte[] src, int offset)
- {
- int word = 0;
-
- for (int i = 0; i < 4; i++)
- {
- word = (word << 8) + (src[i + offset] & MASK8);
- }
- return word;
- }
-
- private void int2bytes(int word, byte[] dst, int offset)
- {
- for (int i = 0; i < 4; i++)
- {
- dst[(3 - i) + offset] = (byte)word;
- word >>>= 8;
- }
- }
-
- private void camelliaF2(int[] s, int[] skey, int keyoff)
- {
- int t1, t2, u, v;
-
- t1 = s[0] ^ skey[0 + keyoff];
- u = SBOX4_4404[t1 & MASK8];
- u ^= SBOX3_3033[(t1 >>> 8) & MASK8];
- u ^= SBOX2_0222[(t1 >>> 16) & MASK8];
- u ^= SBOX1_1110[(t1 >>> 24) & MASK8];
- t2 = s[1] ^ skey[1 + keyoff];
- v = SBOX1_1110[t2 & MASK8];
- v ^= SBOX4_4404[(t2 >>> 8) & MASK8];
- v ^= SBOX3_3033[(t2 >>> 16) & MASK8];
- v ^= SBOX2_0222[(t2 >>> 24) & MASK8];
-
- s[2] ^= u ^ v;
- s[3] ^= u ^ v ^ rightRotate(u, 8);
-
- t1 = s[2] ^ skey[2 + keyoff];
- u = SBOX4_4404[t1 & MASK8];
- u ^= SBOX3_3033[(t1 >>> 8) & MASK8];
- u ^= SBOX2_0222[(t1 >>> 16) & MASK8];
- u ^= SBOX1_1110[(t1 >>> 24) & MASK8];
- t2 = s[3] ^ skey[3 + keyoff];
- v = SBOX1_1110[t2 & MASK8];
- v ^= SBOX4_4404[(t2 >>> 8) & MASK8];
- v ^= SBOX3_3033[(t2 >>> 16) & MASK8];
- v ^= SBOX2_0222[(t2 >>> 24) & MASK8];
-
- s[0] ^= u ^ v;
- s[1] ^= u ^ v ^ rightRotate(u, 8);
- }
-
- private void camelliaFLs(int[] s, int[] fkey, int keyoff)
- {
-
- s[1] ^= leftRotate(s[0] & fkey[0 + keyoff], 1);
- s[0] ^= fkey[1 + keyoff] | s[1];
-
- s[2] ^= fkey[3 + keyoff] | s[3];
- s[3] ^= leftRotate(fkey[2 + keyoff] & s[2], 1);
- }
-
- private void setKey(boolean forEncryption, byte[] key)
- {
- int[] k = new int[8];
- int[] ka = new int[4];
- int[] kb = new int[4];
- int[] t = new int[4];
-
- switch (key.length)
- {
- case 16:
- _keyIs128 = true;
- k[0] = bytes2int(key, 0);
- k[1] = bytes2int(key, 4);
- k[2] = bytes2int(key, 8);
- k[3] = bytes2int(key, 12);
- k[4] = k[5] = k[6] = k[7] = 0;
- break;
- case 24:
- k[0] = bytes2int(key, 0);
- k[1] = bytes2int(key, 4);
- k[2] = bytes2int(key, 8);
- k[3] = bytes2int(key, 12);
- k[4] = bytes2int(key, 16);
- k[5] = bytes2int(key, 20);
- k[6] = ~k[4];
- k[7] = ~k[5];
- _keyIs128 = false;
- break;
- case 32:
- k[0] = bytes2int(key, 0);
- k[1] = bytes2int(key, 4);
- k[2] = bytes2int(key, 8);
- k[3] = bytes2int(key, 12);
- k[4] = bytes2int(key, 16);
- k[5] = bytes2int(key, 20);
- k[6] = bytes2int(key, 24);
- k[7] = bytes2int(key, 28);
- _keyIs128 = false;
- break;
- default:
- throw new
- IllegalArgumentException("key sizes are only 16/24/32 bytes.");
- }
-
- for (int i = 0; i < 4; i++)
- {
- ka[i] = k[i] ^ k[i + 4];
- }
- /* compute KA */
- camelliaF2(ka, SIGMA, 0);
- for (int i = 0; i < 4; i++)
- {
- ka[i] ^= k[i];
- }
- camelliaF2(ka, SIGMA, 4);
-
- if (_keyIs128)
- {
- if (forEncryption)
- {
- /* KL dependant keys */
- kw[0] = k[0];
- kw[1] = k[1];
- kw[2] = k[2];
- kw[3] = k[3];
- roldq(15, k, 0, subkey, 4);
- roldq(30, k, 0, subkey, 12);
- roldq(15, k, 0, t, 0);
- subkey[18] = t[2];
- subkey[19] = t[3];
- roldq(17, k, 0, ke, 4);
- roldq(17, k, 0, subkey, 24);
- roldq(17, k, 0, subkey, 32);
- /* KA dependant keys */
- subkey[0] = ka[0];
- subkey[1] = ka[1];
- subkey[2] = ka[2];
- subkey[3] = ka[3];
- roldq(15, ka, 0, subkey, 8);
- roldq(15, ka, 0, ke, 0);
- roldq(15, ka, 0, t, 0);
- subkey[16] = t[0];
- subkey[17] = t[1];
- roldq(15, ka, 0, subkey, 20);
- roldqo32(34, ka, 0, subkey, 28);
- roldq(17, ka, 0, kw, 4);
-
- }
- else
- { // decryption
- /* KL dependant keys */
- kw[4] = k[0];
- kw[5] = k[1];
- kw[6] = k[2];
- kw[7] = k[3];
- decroldq(15, k, 0, subkey, 28);
- decroldq(30, k, 0, subkey, 20);
- decroldq(15, k, 0, t, 0);
- subkey[16] = t[0];
- subkey[17] = t[1];
- decroldq(17, k, 0, ke, 0);
- decroldq(17, k, 0, subkey, 8);
- decroldq(17, k, 0, subkey, 0);
- /* KA dependant keys */
- subkey[34] = ka[0];
- subkey[35] = ka[1];
- subkey[32] = ka[2];
- subkey[33] = ka[3];
- decroldq(15, ka, 0, subkey, 24);
- decroldq(15, ka, 0, ke, 4);
- decroldq(15, ka, 0, t, 0);
- subkey[18] = t[2];
- subkey[19] = t[3];
- decroldq(15, ka, 0, subkey, 12);
- decroldqo32(34, ka, 0, subkey, 4);
- roldq(17, ka, 0, kw, 0);
- }
- }
- else
- { // 192bit or 256bit
- /* compute KB */
- for (int i = 0; i < 4; i++)
- {
- kb[i] = ka[i] ^ k[i + 4];
- }
- camelliaF2(kb, SIGMA, 8);
-
- if (forEncryption)
- {
- /* KL dependant keys */
- kw[0] = k[0];
- kw[1] = k[1];
- kw[2] = k[2];
- kw[3] = k[3];
- roldqo32(45, k, 0, subkey, 16);
- roldq(15, k, 0, ke, 4);
- roldq(17, k, 0, subkey, 32);
- roldqo32(34, k, 0, subkey, 44);
- /* KR dependant keys */
- roldq(15, k, 4, subkey, 4);
- roldq(15, k, 4, ke, 0);
- roldq(30, k, 4, subkey, 24);
- roldqo32(34, k, 4, subkey, 36);
- /* KA dependant keys */
- roldq(15, ka, 0, subkey, 8);
- roldq(30, ka, 0, subkey, 20);
- /* 32bit rotation */
- ke[8] = ka[1];
- ke[9] = ka[2];
- ke[10] = ka[3];
- ke[11] = ka[0];
- roldqo32(49, ka, 0, subkey, 40);
-
- /* KB dependant keys */
- subkey[0] = kb[0];
- subkey[1] = kb[1];
- subkey[2] = kb[2];
- subkey[3] = kb[3];
- roldq(30, kb, 0, subkey, 12);
- roldq(30, kb, 0, subkey, 28);
- roldqo32(51, kb, 0, kw, 4);
-
- }
- else
- { // decryption
- /* KL dependant keys */
- kw[4] = k[0];
- kw[5] = k[1];
- kw[6] = k[2];
- kw[7] = k[3];
- decroldqo32(45, k, 0, subkey, 28);
- decroldq(15, k, 0, ke, 4);
- decroldq(17, k, 0, subkey, 12);
- decroldqo32(34, k, 0, subkey, 0);
- /* KR dependant keys */
- decroldq(15, k, 4, subkey, 40);
- decroldq(15, k, 4, ke, 8);
- decroldq(30, k, 4, subkey, 20);
- decroldqo32(34, k, 4, subkey, 8);
- /* KA dependant keys */
- decroldq(15, ka, 0, subkey, 36);
- decroldq(30, ka, 0, subkey, 24);
- /* 32bit rotation */
- ke[2] = ka[1];
- ke[3] = ka[2];
- ke[0] = ka[3];
- ke[1] = ka[0];
- decroldqo32(49, ka, 0, subkey, 4);
-
- /* KB dependant keys */
- subkey[46] = kb[0];
- subkey[47] = kb[1];
- subkey[44] = kb[2];
- subkey[45] = kb[3];
- decroldq(30, kb, 0, subkey, 32);
- decroldq(30, kb, 0, subkey, 16);
- roldqo32(51, kb, 0, kw, 0);
- }
- }
- }
-
- private int processBlock128(byte[] in, int inOff,
- byte[] out, int outOff)
- {
- for (int i = 0; i < 4; i++)
- {
- state[i] = bytes2int(in, inOff + (i * 4));
- state[i] ^= kw[i];
- }
-
- camelliaF2(state, subkey, 0);
- camelliaF2(state, subkey, 4);
- camelliaF2(state, subkey, 8);
- camelliaFLs(state, ke, 0);
- camelliaF2(state, subkey, 12);
- camelliaF2(state, subkey, 16);
- camelliaF2(state, subkey, 20);
- camelliaFLs(state, ke, 4);
- camelliaF2(state, subkey, 24);
- camelliaF2(state, subkey, 28);
- camelliaF2(state, subkey, 32);
-
- state[2] ^= kw[4];
- state[3] ^= kw[5];
- state[0] ^= kw[6];
- state[1] ^= kw[7];
-
- int2bytes(state[2], out, outOff);
- int2bytes(state[3], out, outOff + 4);
- int2bytes(state[0], out, outOff + 8);
- int2bytes(state[1], out, outOff + 12);
-
- return BLOCK_SIZE;
- }
-
- private int processBlock192or256(byte[] in, int inOff,
- byte[] out, int outOff)
- {
- for (int i = 0; i < 4; i++)
- {
- state[i] = bytes2int(in, inOff + (i * 4));
- state[i] ^= kw[i];
- }
-
- camelliaF2(state, subkey, 0);
- camelliaF2(state, subkey, 4);
- camelliaF2(state, subkey, 8);
- camelliaFLs(state, ke, 0);
- camelliaF2(state, subkey, 12);
- camelliaF2(state, subkey, 16);
- camelliaF2(state, subkey, 20);
- camelliaFLs(state, ke, 4);
- camelliaF2(state, subkey, 24);
- camelliaF2(state, subkey, 28);
- camelliaF2(state, subkey, 32);
- camelliaFLs(state, ke, 8);
- camelliaF2(state, subkey, 36);
- camelliaF2(state, subkey, 40);
- camelliaF2(state, subkey, 44);
-
- state[2] ^= kw[4];
- state[3] ^= kw[5];
- state[0] ^= kw[6];
- state[1] ^= kw[7];
-
- int2bytes(state[2], out, outOff);
- int2bytes(state[3], out, outOff + 4);
- int2bytes(state[0], out, outOff + 8);
- int2bytes(state[1], out, outOff + 12);
- return BLOCK_SIZE;
- }
-
- public CamelliaEngine()
- {
- }
-
- public void init(boolean forEncryption, CipherParameters params)
- throws IllegalArgumentException
- {
- if (!(params instanceof KeyParameter))
- {
- throw new IllegalArgumentException("only simple KeyParameter expected.");
- }
-
- setKey(forEncryption, ((KeyParameter)params).getKey());
- initialised = true;
- }
-
- public String getAlgorithmName()
- {
- return "Camellia";
- }
-
- public int getBlockSize()
- {
- return BLOCK_SIZE;
- }
-
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- throws DataLengthException, IllegalStateException
- {
- if (!initialised)
- {
- throw new IllegalStateException("Camellia engine not initialised");
- }
-
- if ((inOff + BLOCK_SIZE) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + BLOCK_SIZE) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- if (_keyIs128)
- {
- return processBlock128(in, inOff, out, outOff);
- }
- else
- {
- return processBlock192or256(in, inOff, out, outOff);
- }
- }
-
- public void reset()
- {
- // nothing
-
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/CamelliaLightEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/CamelliaLightEngine.java
deleted file mode 100644
index 2b1e71b2..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/CamelliaLightEngine.java
+++ /dev/null
@@ -1,592 +0,0 @@
-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;
-
-/**
- * Camellia - based on RFC 3713, smaller implementation, about half the size of CamelliaEngine.
- */
-
-public class CamelliaLightEngine
- implements BlockCipher
-{
- private static final int BLOCK_SIZE = 16;
- private static final int MASK8 = 0xff;
- private boolean initialized;
- private boolean _keyis128;
-
- private int[] subkey = new int[24 * 4];
- private int[] kw = new int[4 * 2]; // for whitening
- private int[] ke = new int[6 * 2]; // for FL and FL^(-1)
- private int[] state = new int[4]; // for encryption and decryption
-
- private static final int SIGMA[] = {
- 0xa09e667f, 0x3bcc908b,
- 0xb67ae858, 0x4caa73b2,
- 0xc6ef372f, 0xe94f82be,
- 0x54ff53a5, 0xf1d36f1c,
- 0x10e527fa, 0xde682d1d,
- 0xb05688c2, 0xb3e6c1fd
- };
-
- /*
- *
- * S-box data
- *
- */
- private static final byte SBOX1[] = {
- (byte)112, (byte)130, (byte)44, (byte)236,
- (byte)179, (byte)39, (byte)192, (byte)229,
- (byte)228, (byte)133, (byte)87, (byte)53,
- (byte)234, (byte)12, (byte)174, (byte)65,
- (byte)35, (byte)239, (byte)107, (byte)147,
- (byte)69, (byte)25, (byte)165, (byte)33,
- (byte)237, (byte)14, (byte)79, (byte)78,
- (byte)29, (byte)101, (byte)146, (byte)189,
- (byte)134, (byte)184, (byte)175, (byte)143,
- (byte)124, (byte)235, (byte)31, (byte)206,
- (byte)62, (byte)48, (byte)220, (byte)95,
- (byte)94, (byte)197, (byte)11, (byte)26,
- (byte)166, (byte)225, (byte)57, (byte)202,
- (byte)213, (byte)71, (byte)93, (byte)61,
- (byte)217, (byte)1, (byte)90, (byte)214,
- (byte)81, (byte)86, (byte)108, (byte)77,
- (byte)139, (byte)13, (byte)154, (byte)102,
- (byte)251, (byte)204, (byte)176, (byte)45,
- (byte)116, (byte)18, (byte)43, (byte)32,
- (byte)240, (byte)177, (byte)132, (byte)153,
- (byte)223, (byte)76, (byte)203, (byte)194,
- (byte)52, (byte)126, (byte)118, (byte)5,
- (byte)109, (byte)183, (byte)169, (byte)49,
- (byte)209, (byte)23, (byte)4, (byte)215,
- (byte)20, (byte)88, (byte)58, (byte)97,
- (byte)222, (byte)27, (byte)17, (byte)28,
- (byte)50, (byte)15, (byte)156, (byte)22,
- (byte)83, (byte)24, (byte)242, (byte)34,
- (byte)254, (byte)68, (byte)207, (byte)178,
- (byte)195, (byte)181, (byte)122, (byte)145,
- (byte)36, (byte)8, (byte)232, (byte)168,
- (byte)96, (byte)252, (byte)105, (byte)80,
- (byte)170, (byte)208, (byte)160, (byte)125,
- (byte)161, (byte)137, (byte)98, (byte)151,
- (byte)84, (byte)91, (byte)30, (byte)149,
- (byte)224, (byte)255, (byte)100, (byte)210,
- (byte)16, (byte)196, (byte)0, (byte)72,
- (byte)163, (byte)247, (byte)117, (byte)219,
- (byte)138, (byte)3, (byte)230, (byte)218,
- (byte)9, (byte)63, (byte)221, (byte)148,
- (byte)135, (byte)92, (byte)131, (byte)2,
- (byte)205, (byte)74, (byte)144, (byte)51,
- (byte)115, (byte)103, (byte)246, (byte)243,
- (byte)157, (byte)127, (byte)191, (byte)226,
- (byte)82, (byte)155, (byte)216, (byte)38,
- (byte)200, (byte)55, (byte)198, (byte)59,
- (byte)129, (byte)150, (byte)111, (byte)75,
- (byte)19, (byte)190, (byte)99, (byte)46,
- (byte)233, (byte)121, (byte)167, (byte)140,
- (byte)159, (byte)110, (byte)188, (byte)142,
- (byte)41, (byte)245, (byte)249, (byte)182,
- (byte)47, (byte)253, (byte)180, (byte)89,
- (byte)120, (byte)152, (byte)6, (byte)106,
- (byte)231, (byte)70, (byte)113, (byte)186,
- (byte)212, (byte)37, (byte)171, (byte)66,
- (byte)136, (byte)162, (byte)141, (byte)250,
- (byte)114, (byte)7, (byte)185, (byte)85,
- (byte)248, (byte)238, (byte)172, (byte)10,
- (byte)54, (byte)73, (byte)42, (byte)104,
- (byte)60, (byte)56, (byte)241, (byte)164,
- (byte)64, (byte)40, (byte)211, (byte)123,
- (byte)187, (byte)201, (byte)67, (byte)193,
- (byte)21, (byte)227, (byte)173, (byte)244,
- (byte)119, (byte)199, (byte)128, (byte)158
- };
-
- private static int rightRotate(int x, int s)
- {
- return (((x) >>> (s)) + ((x) << (32 - s)));
- }
-
- private static int leftRotate(int x, int s)
- {
- return ((x) << (s)) + ((x) >>> (32 - s));
- }
-
- private static void roldq(int rot, int[] ki, int ioff,
- int[] ko, int ooff)
- {
- ko[0 + ooff] = (ki[0 + ioff] << rot) | (ki[1 + ioff] >>> (32 - rot));
- ko[1 + ooff] = (ki[1 + ioff] << rot) | (ki[2 + ioff] >>> (32 - rot));
- ko[2 + ooff] = (ki[2 + ioff] << rot) | (ki[3 + ioff] >>> (32 - rot));
- ko[3 + ooff] = (ki[3 + ioff] << rot) | (ki[0 + ioff] >>> (32 - rot));
- ki[0 + ioff] = ko[0 + ooff];
- ki[1 + ioff] = ko[1 + ooff];
- ki[2 + ioff] = ko[2 + ooff];
- ki[3 + ioff] = ko[3 + ooff];
- }
-
- private static void decroldq(int rot, int[] ki, int ioff,
- int[] ko, int ooff)
- {
- ko[2 + ooff] = (ki[0 + ioff] << rot) | (ki[1 + ioff] >>> (32 - rot));
- ko[3 + ooff] = (ki[1 + ioff] << rot) | (ki[2 + ioff] >>> (32 - rot));
- ko[0 + ooff] = (ki[2 + ioff] << rot) | (ki[3 + ioff] >>> (32 - rot));
- ko[1 + ooff] = (ki[3 + ioff] << rot) | (ki[0 + ioff] >>> (32 - rot));
- ki[0 + ioff] = ko[2 + ooff];
- ki[1 + ioff] = ko[3 + ooff];
- ki[2 + ioff] = ko[0 + ooff];
- ki[3 + ioff] = ko[1 + ooff];
- }
-
- private static void roldqo32(int rot, int[] ki, int ioff,
- int[] ko, int ooff)
- {
- ko[0 + ooff] = (ki[1 + ioff] << (rot - 32)) | (ki[2 + ioff] >>> (64 - rot));
- ko[1 + ooff] = (ki[2 + ioff] << (rot - 32)) | (ki[3 + ioff] >>> (64 - rot));
- ko[2 + ooff] = (ki[3 + ioff] << (rot - 32)) | (ki[0 + ioff] >>> (64 - rot));
- ko[3 + ooff] = (ki[0 + ioff] << (rot - 32)) | (ki[1 + ioff] >>> (64 - rot));
- ki[0 + ioff] = ko[0 + ooff];
- ki[1 + ioff] = ko[1 + ooff];
- ki[2 + ioff] = ko[2 + ooff];
- ki[3 + ioff] = ko[3 + ooff];
- }
-
- private static void decroldqo32(int rot, int[] ki, int ioff,
- int[] ko, int ooff)
- {
- ko[2 + ooff] = (ki[1 + ioff] << (rot - 32)) | (ki[2 + ioff] >>> (64 - rot));
- ko[3 + ooff] = (ki[2 + ioff] << (rot - 32)) | (ki[3 + ioff] >>> (64 - rot));
- ko[0 + ooff] = (ki[3 + ioff] << (rot - 32)) | (ki[0 + ioff] >>> (64 - rot));
- ko[1 + ooff] = (ki[0 + ioff] << (rot - 32)) | (ki[1 + ioff] >>> (64 - rot));
- ki[0 + ioff] = ko[2 + ooff];
- ki[1 + ioff] = ko[3 + ooff];
- ki[2 + ioff] = ko[0 + ooff];
- ki[3 + ioff] = ko[1 + ooff];
- }
-
- private int bytes2int(byte[] src, int offset)
- {
- int word = 0;
-
- for (int i = 0; i < 4; i++)
- {
- word = (word << 8) + (src[i + offset] & MASK8);
- }
- return word;
- }
-
- private void int2bytes(int word, byte[] dst, int offset)
- {
- for (int i = 0; i < 4; i++)
- {
- dst[(3 - i) + offset] = (byte)word;
- word >>>= 8;
- }
- }
-
- private byte lRot8(byte v, int rot)
- {
- return (byte)((v << rot) | ((v & 0xff) >>> (8 - rot)));
- }
-
- private int sbox2(int x)
- {
- return (lRot8(SBOX1[x], 1) & MASK8);
- }
-
- private int sbox3(int x)
- {
- return (lRot8(SBOX1[x], 7) & MASK8);
- }
-
- private int sbox4(int x)
- {
- return (SBOX1[((int)lRot8((byte)x, 1) & MASK8)] & MASK8);
- }
-
- private void camelliaF2(int[] s, int[] skey, int keyoff)
- {
- int t1, t2, u, v;
-
- t1 = s[0] ^ skey[0 + keyoff];
- u = sbox4((t1 & MASK8));
- u |= (sbox3(((t1 >>> 8) & MASK8)) << 8);
- u |= (sbox2(((t1 >>> 16) & MASK8)) << 16);
- u |= ((int)(SBOX1[((t1 >>> 24) & MASK8)] & MASK8) << 24);
-
- t2 = s[1] ^ skey[1 + keyoff];
- v = (int)SBOX1[(t2 & MASK8)] & MASK8;
- v |= (sbox4(((t2 >>> 8) & MASK8)) << 8);
- v |= (sbox3(((t2 >>> 16) & MASK8)) << 16);
- v |= (sbox2(((t2 >>> 24) & MASK8)) << 24);
-
- v = leftRotate(v, 8);
- u ^= v;
- v = leftRotate(v, 8) ^ u;
- u = rightRotate(u, 8) ^ v;
- s[2] ^= leftRotate(v, 16) ^ u;
- s[3] ^= leftRotate(u, 8);
-
- t1 = s[2] ^ skey[2 + keyoff];
- u = sbox4((t1 & MASK8));
- u |= sbox3(((t1 >>> 8) & MASK8)) << 8;
- u |= sbox2(((t1 >>> 16) & MASK8)) << 16;
- u |= ((int)SBOX1[((t1 >>> 24) & MASK8)] & MASK8) << 24;
-
- t2 = s[3] ^ skey[3 + keyoff];
- v = ((int)SBOX1[(t2 & MASK8)] & MASK8);
- v |= sbox4(((t2 >>> 8) & MASK8)) << 8;
- v |= sbox3(((t2 >>> 16) & MASK8)) << 16;
- v |= sbox2(((t2 >>> 24) & MASK8)) << 24;
-
- v = leftRotate(v, 8);
- u ^= v;
- v = leftRotate(v, 8) ^ u;
- u = rightRotate(u, 8) ^ v;
- s[0] ^= leftRotate(v, 16) ^ u;
- s[1] ^= leftRotate(u, 8);
- }
-
- private void camelliaFLs(int[] s, int[] fkey, int keyoff)
- {
-
- s[1] ^= leftRotate(s[0] & fkey[0 + keyoff], 1);
- s[0] ^= fkey[1 + keyoff] | s[1];
-
- s[2] ^= fkey[3 + keyoff] | s[3];
- s[3] ^= leftRotate(fkey[2 + keyoff] & s[2], 1);
- }
-
- private void setKey(boolean forEncryption, byte[] key)
- {
- int[] k = new int[8];
- int[] ka = new int[4];
- int[] kb = new int[4];
- int[] t = new int[4];
-
- switch (key.length)
- {
- case 16:
- _keyis128 = true;
- k[0] = bytes2int(key, 0);
- k[1] = bytes2int(key, 4);
- k[2] = bytes2int(key, 8);
- k[3] = bytes2int(key, 12);
- k[4] = k[5] = k[6] = k[7] = 0;
- break;
- case 24:
- k[0] = bytes2int(key, 0);
- k[1] = bytes2int(key, 4);
- k[2] = bytes2int(key, 8);
- k[3] = bytes2int(key, 12);
- k[4] = bytes2int(key, 16);
- k[5] = bytes2int(key, 20);
- k[6] = ~k[4];
- k[7] = ~k[5];
- _keyis128 = false;
- break;
- case 32:
- k[0] = bytes2int(key, 0);
- k[1] = bytes2int(key, 4);
- k[2] = bytes2int(key, 8);
- k[3] = bytes2int(key, 12);
- k[4] = bytes2int(key, 16);
- k[5] = bytes2int(key, 20);
- k[6] = bytes2int(key, 24);
- k[7] = bytes2int(key, 28);
- _keyis128 = false;
- break;
- default:
- throw new
- IllegalArgumentException("key sizes are only 16/24/32 bytes.");
- }
-
- for (int i = 0; i < 4; i++)
- {
- ka[i] = k[i] ^ k[i + 4];
- }
- /* compute KA */
- camelliaF2(ka, SIGMA, 0);
- for (int i = 0; i < 4; i++)
- {
- ka[i] ^= k[i];
- }
- camelliaF2(ka, SIGMA, 4);
-
- if (_keyis128)
- {
- if (forEncryption)
- {
- /* KL dependant keys */
- kw[0] = k[0];
- kw[1] = k[1];
- kw[2] = k[2];
- kw[3] = k[3];
- roldq(15, k, 0, subkey, 4);
- roldq(30, k, 0, subkey, 12);
- roldq(15, k, 0, t, 0);
- subkey[18] = t[2];
- subkey[19] = t[3];
- roldq(17, k, 0, ke, 4);
- roldq(17, k, 0, subkey, 24);
- roldq(17, k, 0, subkey, 32);
- /* KA dependant keys */
- subkey[0] = ka[0];
- subkey[1] = ka[1];
- subkey[2] = ka[2];
- subkey[3] = ka[3];
- roldq(15, ka, 0, subkey, 8);
- roldq(15, ka, 0, ke, 0);
- roldq(15, ka, 0, t, 0);
- subkey[16] = t[0];
- subkey[17] = t[1];
- roldq(15, ka, 0, subkey, 20);
- roldqo32(34, ka, 0, subkey, 28);
- roldq(17, ka, 0, kw, 4);
-
- }
- else
- { // decryption
- /* KL dependant keys */
- kw[4] = k[0];
- kw[5] = k[1];
- kw[6] = k[2];
- kw[7] = k[3];
- decroldq(15, k, 0, subkey, 28);
- decroldq(30, k, 0, subkey, 20);
- decroldq(15, k, 0, t, 0);
- subkey[16] = t[0];
- subkey[17] = t[1];
- decroldq(17, k, 0, ke, 0);
- decroldq(17, k, 0, subkey, 8);
- decroldq(17, k, 0, subkey, 0);
- /* KA dependant keys */
- subkey[34] = ka[0];
- subkey[35] = ka[1];
- subkey[32] = ka[2];
- subkey[33] = ka[3];
- decroldq(15, ka, 0, subkey, 24);
- decroldq(15, ka, 0, ke, 4);
- decroldq(15, ka, 0, t, 0);
- subkey[18] = t[2];
- subkey[19] = t[3];
- decroldq(15, ka, 0, subkey, 12);
- decroldqo32(34, ka, 0, subkey, 4);
- roldq(17, ka, 0, kw, 0);
- }
- }
- else
- { // 192bit or 256bit
- /* compute KB */
- for (int i = 0; i < 4; i++)
- {
- kb[i] = ka[i] ^ k[i + 4];
- }
- camelliaF2(kb, SIGMA, 8);
-
- if (forEncryption)
- {
- /* KL dependant keys */
- kw[0] = k[0];
- kw[1] = k[1];
- kw[2] = k[2];
- kw[3] = k[3];
- roldqo32(45, k, 0, subkey, 16);
- roldq(15, k, 0, ke, 4);
- roldq(17, k, 0, subkey, 32);
- roldqo32(34, k, 0, subkey, 44);
- /* KR dependant keys */
- roldq(15, k, 4, subkey, 4);
- roldq(15, k, 4, ke, 0);
- roldq(30, k, 4, subkey, 24);
- roldqo32(34, k, 4, subkey, 36);
- /* KA dependant keys */
- roldq(15, ka, 0, subkey, 8);
- roldq(30, ka, 0, subkey, 20);
- /* 32bit rotation */
- ke[8] = ka[1];
- ke[9] = ka[2];
- ke[10] = ka[3];
- ke[11] = ka[0];
- roldqo32(49, ka, 0, subkey, 40);
-
- /* KB dependant keys */
- subkey[0] = kb[0];
- subkey[1] = kb[1];
- subkey[2] = kb[2];
- subkey[3] = kb[3];
- roldq(30, kb, 0, subkey, 12);
- roldq(30, kb, 0, subkey, 28);
- roldqo32(51, kb, 0, kw, 4);
-
- }
- else
- { // decryption
- /* KL dependant keys */
- kw[4] = k[0];
- kw[5] = k[1];
- kw[6] = k[2];
- kw[7] = k[3];
- decroldqo32(45, k, 0, subkey, 28);
- decroldq(15, k, 0, ke, 4);
- decroldq(17, k, 0, subkey, 12);
- decroldqo32(34, k, 0, subkey, 0);
- /* KR dependant keys */
- decroldq(15, k, 4, subkey, 40);
- decroldq(15, k, 4, ke, 8);
- decroldq(30, k, 4, subkey, 20);
- decroldqo32(34, k, 4, subkey, 8);
- /* KA dependant keys */
- decroldq(15, ka, 0, subkey, 36);
- decroldq(30, ka, 0, subkey, 24);
- /* 32bit rotation */
- ke[2] = ka[1];
- ke[3] = ka[2];
- ke[0] = ka[3];
- ke[1] = ka[0];
- decroldqo32(49, ka, 0, subkey, 4);
-
- /* KB dependant keys */
- subkey[46] = kb[0];
- subkey[47] = kb[1];
- subkey[44] = kb[2];
- subkey[45] = kb[3];
- decroldq(30, kb, 0, subkey, 32);
- decroldq(30, kb, 0, subkey, 16);
- roldqo32(51, kb, 0, kw, 0);
- }
- }
- }
-
- private int processBlock128(byte[] in, int inOff,
- byte[] out, int outOff)
- {
- for (int i = 0; i < 4; i++)
- {
- state[i] = bytes2int(in, inOff + (i * 4));
- state[i] ^= kw[i];
- }
-
- camelliaF2(state, subkey, 0);
- camelliaF2(state, subkey, 4);
- camelliaF2(state, subkey, 8);
- camelliaFLs(state, ke, 0);
- camelliaF2(state, subkey, 12);
- camelliaF2(state, subkey, 16);
- camelliaF2(state, subkey, 20);
- camelliaFLs(state, ke, 4);
- camelliaF2(state, subkey, 24);
- camelliaF2(state, subkey, 28);
- camelliaF2(state, subkey, 32);
-
- state[2] ^= kw[4];
- state[3] ^= kw[5];
- state[0] ^= kw[6];
- state[1] ^= kw[7];
-
- int2bytes(state[2], out, outOff);
- int2bytes(state[3], out, outOff + 4);
- int2bytes(state[0], out, outOff + 8);
- int2bytes(state[1], out, outOff + 12);
-
- return BLOCK_SIZE;
- }
-
- private int processBlock192or256(byte[] in, int inOff,
- byte[] out, int outOff)
- {
- for (int i = 0; i < 4; i++)
- {
- state[i] = bytes2int(in, inOff + (i * 4));
- state[i] ^= kw[i];
- }
-
- camelliaF2(state, subkey, 0);
- camelliaF2(state, subkey, 4);
- camelliaF2(state, subkey, 8);
- camelliaFLs(state, ke, 0);
- camelliaF2(state, subkey, 12);
- camelliaF2(state, subkey, 16);
- camelliaF2(state, subkey, 20);
- camelliaFLs(state, ke, 4);
- camelliaF2(state, subkey, 24);
- camelliaF2(state, subkey, 28);
- camelliaF2(state, subkey, 32);
- camelliaFLs(state, ke, 8);
- camelliaF2(state, subkey, 36);
- camelliaF2(state, subkey, 40);
- camelliaF2(state, subkey, 44);
-
- state[2] ^= kw[4];
- state[3] ^= kw[5];
- state[0] ^= kw[6];
- state[1] ^= kw[7];
-
- int2bytes(state[2], out, outOff);
- int2bytes(state[3], out, outOff + 4);
- int2bytes(state[0], out, outOff + 8);
- int2bytes(state[1], out, outOff + 12);
- return BLOCK_SIZE;
- }
-
- public CamelliaLightEngine()
- {
- }
-
- public String getAlgorithmName()
- {
- return "Camellia";
- }
-
- public int getBlockSize()
- {
- return BLOCK_SIZE;
- }
-
- public void init(boolean forEncryption, CipherParameters params)
- {
- if (!(params instanceof KeyParameter))
- {
- throw new IllegalArgumentException("only simple KeyParameter expected.");
- }
-
- setKey(forEncryption, ((KeyParameter)params).getKey());
- initialized = true;
- }
-
- public int processBlock(byte[] in, int inOff,
- byte[] out, int outOff)
- throws IllegalStateException
- {
-
- if (!initialized)
- {
- throw new IllegalStateException("Camellia is not initialized");
- }
-
- if ((inOff + BLOCK_SIZE) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + BLOCK_SIZE) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- if (_keyis128)
- {
- return processBlock128(in, inOff, out, outOff);
- }
- else
- {
- return processBlock192or256(in, inOff, out, outOff);
- }
- }
-
- public void reset()
- {
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/CamelliaWrapEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/CamelliaWrapEngine.java
deleted file mode 100644
index 5ca239a6..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/CamelliaWrapEngine.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-/**
- * An implementation of the Camellia key wrapper based on RFC 3657/RFC 3394.
- * <p>
- * For further details see: <a href="http://www.ietf.org/rfc/rfc3657.txt">http://www.ietf.org/rfc/rfc3657.txt</a>.
- */
-public class CamelliaWrapEngine
- extends RFC3394WrapEngine
-{
- public CamelliaWrapEngine()
- {
- super(new CamelliaEngine());
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/ChaChaEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/ChaChaEngine.java
deleted file mode 100644
index 31da795f..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/ChaChaEngine.java
+++ /dev/null
@@ -1,204 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import org.bouncycastle.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 retreatCounter()
- {
- if (engineState[12] == 0 && engineState[13] == 0)
- {
- throw new IllegalStateException("attempt to reduce counter past zero.");
- }
-
- if (--engineState[12] == -1)
- {
- --engineState[13];
- }
- }
-
- protected long getCounter()
- {
- return ((long)engineState[13] << 32) | (engineState[12] & 0xffffffffL);
- }
-
- protected void resetCounter()
- {
- engineState[12] = engineState[13] = 0;
- }
-
- protected void setKey(byte[] keyBytes, byte[] ivBytes)
- {
- if (keyBytes != null)
- {
- if ((keyBytes.length != 16) && (keyBytes.length != 32))
- {
- throw new IllegalArgumentException(getAlgorithmName() + " requires 128 bit or 256 bit key");
- }
-
- // 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);
-
- byte[] constants;
- int offset;
- if (keyBytes.length == 32)
- {
- constants = sigma;
- offset = 16;
- }
- else
- {
- constants = tau;
- offset = 0;
- }
-
- 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);
- }
-
- // 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
- */
- 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/core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCiphertext.java b/core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCiphertext.java
deleted file mode 100644
index 0d8ba19d..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCiphertext.java
+++ /dev/null
@@ -1,179 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import java.math.BigInteger;
-
-/**
- * Class, holding Cramer Shoup ciphertexts (u1, u2, e, v)
- */
-public class CramerShoupCiphertext
-{
-
- BigInteger u1, u2, e, v;
-
- public CramerShoupCiphertext()
- {
-
- }
-
- public CramerShoupCiphertext(BigInteger u1, BigInteger u2, BigInteger e, BigInteger v)
- {
- this.u1 = u1;
- this.u2 = u2;
- this.e = e;
- this.v = v;
- }
-
- public CramerShoupCiphertext(byte[] c)
- {
- int off = 0, s;
- byte[] size = new byte[4];
- byte[] tmp;
-
- System.arraycopy(c, off, size, 0, 4);
- s = byteArrayToInt(size);
- tmp = new byte[s];
- off += 4;
- System.arraycopy(c, off, tmp, 0, s);
- off += s;
- u1 = new BigInteger(tmp);
-
- System.arraycopy(c, off, size, 0, 4);
- s = byteArrayToInt(size);
- tmp = new byte[s];
- off += 4;
- System.arraycopy(c, off, tmp, 0, s);
- off += s;
- u2 = new BigInteger(tmp);
-
- System.arraycopy(c, off, size, 0, 4);
- s = byteArrayToInt(size);
- tmp = new byte[s];
- off += 4;
- System.arraycopy(c, off, tmp, 0, s);
- off += s;
- e = new BigInteger(tmp);
-
- System.arraycopy(c, off, size, 0, 4);
- s = byteArrayToInt(size);
- tmp = new byte[s];
- off += 4;
- System.arraycopy(c, off, tmp, 0, s);
- off += s;
- v = new BigInteger(tmp);
- }
-
- public BigInteger getU1()
- {
- return u1;
- }
-
- public void setU1(BigInteger u1)
- {
- this.u1 = u1;
- }
-
- public BigInteger getU2()
- {
- return u2;
- }
-
- public void setU2(BigInteger u2)
- {
- this.u2 = u2;
- }
-
- public BigInteger getE()
- {
- return e;
- }
-
- public void setE(BigInteger e)
- {
- this.e = e;
- }
-
- public BigInteger getV()
- {
- return v;
- }
-
- public void setV(BigInteger v)
- {
- this.v = v;
- }
-
- public String toString()
- {
- StringBuffer result = new StringBuffer();
-
- result.append("u1: " + u1.toString());
- result.append("\nu2: " + u2.toString());
- result.append("\ne: " + e.toString());
- result.append("\nv: " + v.toString());
-
- return result.toString();
- }
-
- /**
- * convert the cipher-text in a byte array,
- * prepending them with 4 Bytes for their length
- *
- * @return
- */
- public byte[] toByteArray()
- {
-
- byte[] u1Bytes = u1.toByteArray();
- int u1Length = u1Bytes.length;
- byte[] u2Bytes = u2.toByteArray();
- int u2Length = u2Bytes.length;
- byte[] eBytes = e.toByteArray();
- int eLength = eBytes.length;
- byte[] vBytes = v.toByteArray();
- int vLength = vBytes.length;
-
- int off = 0;
- byte[] result = new byte[u1Length + u2Length + eLength + vLength + 4 * 4];
- System.arraycopy(intToByteArray(u1Length), 0, result, 0, 4);
- off += 4;
- System.arraycopy(u1Bytes, 0, result, off, u1Length);
- off += u1Length;
- System.arraycopy(intToByteArray(u2Length), 0, result, off, 4);
- off += 4;
- System.arraycopy(u2Bytes, 0, result, off, u2Length);
- off += u2Length;
- System.arraycopy(intToByteArray(eLength), 0, result, off, 4);
- off += 4;
- System.arraycopy(eBytes, 0, result, off, eLength);
- off += eLength;
- System.arraycopy(intToByteArray(vLength), 0, result, off, 4);
- off += 4;
- System.arraycopy(vBytes, 0, result, off, vLength);
-
- return result;
- }
-
- private byte[] intToByteArray(int in)
- {
- byte[] bytes = new byte[4];
- for (int i = 0; i < 4; i++)
- {
- bytes[3 - i] = (byte)(in >>> (i * 8));
- }
- return bytes;
- }
-
- private int byteArrayToInt(byte[] in)
- {
- if (in.length != 4)
- {
- return -1;
- }
- int r = 0;
- for (int i = 3; i >= 0; i--)
- {
- r += (int)in[i] << ((3 - i) * 8);
- }
- return r;
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCoreEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCoreEngine.java
deleted file mode 100644
index 4c0db1b5..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/CramerShoupCoreEngine.java
+++ /dev/null
@@ -1,313 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.params.CramerShoupKeyParameters;
-import org.bouncycastle.crypto.params.CramerShoupPrivateKeyParameters;
-import org.bouncycastle.crypto.params.CramerShoupPublicKeyParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.util.BigIntegers;
-
-/**
- * Essentially the Cramer-Shoup encryption / decryption algorithms according to
- * "A practical public key cryptosystem provably secure against adaptive chosen ciphertext attack." (Crypto 1998)
- */
-public class CramerShoupCoreEngine
-{
-
- private static final BigInteger ONE = BigInteger.valueOf(1);
-
- private CramerShoupKeyParameters key;
- private SecureRandom random;
- private boolean forEncryption;
- private String label = null;
-
- /**
- * initialise the CramerShoup engine.
- *
- * @param forEncryption whether this engine should encrypt or decrypt
- * @param param the necessary CramerShoup key parameters.
- * @param label the label for labelled CS as {@link String}
- */
- public void init(boolean forEncryption, CipherParameters param, String label)
- {
- init(forEncryption, param);
-
- this.label = label;
- }
-
- /**
- * initialise the CramerShoup engine.
- *
- * @param forEncryption whether this engine should encrypt or decrypt
- * @param param the necessary CramerShoup key parameters.
- */
- public void init(boolean forEncryption, CipherParameters param)
- {
- SecureRandom providedRandom = null;
-
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- key = (CramerShoupKeyParameters)rParam.getParameters();
- providedRandom = rParam.getRandom();
- }
- else
- {
- key = (CramerShoupKeyParameters)param;
- }
-
- this.random = initSecureRandom(forEncryption, providedRandom);
- this.forEncryption = forEncryption;
- }
-
- /**
- * Return the maximum size for an input block to this engine. For Cramer
- * Shoup this is always one byte less than the key size on encryption, and
- * the same length as the key size on decryption.
- *
- * @return maximum size for an input block.
- * <p/>
- * TODO: correct?
- */
- public int getInputBlockSize()
- {
- int bitSize = key.getParameters().getP().bitLength();
-
- if (forEncryption)
- {
- return (bitSize + 7) / 8 - 1;
- }
- else
- {
- return (bitSize + 7) / 8;
- }
- }
-
- /**
- * Return the maximum size for an output block to this engine. For Cramer
- * Shoup this is always one byte less than the key size on decryption, and
- * the same length as the key size on encryption.
- *
- * @return maximum size for an output block.
- * <p/>
- * TODO: correct?
- */
- public int getOutputBlockSize()
- {
- int bitSize = key.getParameters().getP().bitLength();
-
- if (forEncryption)
- {
- return (bitSize + 7) / 8;
- }
- else
- {
- return (bitSize + 7) / 8 - 1;
- }
- }
-
- public BigInteger convertInput(byte[] in, int inOff, int inLen)
- {
- if (inLen > (getInputBlockSize() + 1))
- {
- throw new DataLengthException("input too large for Cramer Shoup cipher.");
- }
- else if (inLen == (getInputBlockSize() + 1) && forEncryption)
- {
- throw new DataLengthException("input too large for Cramer Shoup cipher.");
- }
-
- byte[] block;
-
- if (inOff != 0 || inLen != in.length)
- {
- block = new byte[inLen];
-
- System.arraycopy(in, inOff, block, 0, inLen);
- }
- else
- {
- block = in;
- }
-
- BigInteger res = new BigInteger(1, block);
- if (res.compareTo(key.getParameters().getP()) >= 0)
- {
- throw new DataLengthException("input too large for Cramer Shoup cipher.");
- }
-
- return res;
- }
-
- public byte[] convertOutput(BigInteger result)
- {
- byte[] output = result.toByteArray();
-
- if (!forEncryption)
- {
- if (output[0] == 0 && output.length > getOutputBlockSize())
- { // have ended up with an extra zero byte, copy down.
- byte[] tmp = new byte[output.length - 1];
-
- System.arraycopy(output, 1, tmp, 0, tmp.length);
-
- return tmp;
- }
-
- if (output.length < getOutputBlockSize())
- {// have ended up with less bytes than normal, lengthen
- byte[] tmp = new byte[getOutputBlockSize()];
-
- System.arraycopy(output, 0, tmp, tmp.length - output.length, output.length);
-
- return tmp;
- }
- }
- else
- {
- if (output[0] == 0)
- { // have ended up with an extra zero byte, copy down.
- byte[] tmp = new byte[output.length - 1];
-
- System.arraycopy(output, 1, tmp, 0, tmp.length);
-
- return tmp;
- }
- }
-
- return output;
- }
-
- public CramerShoupCiphertext encryptBlock(BigInteger input)
- {
-
- CramerShoupCiphertext result = null;
-
- if (!key.isPrivate() && this.forEncryption && key instanceof CramerShoupPublicKeyParameters)
- {
- CramerShoupPublicKeyParameters pk = (CramerShoupPublicKeyParameters)key;
- BigInteger p = pk.getParameters().getP();
- BigInteger g1 = pk.getParameters().getG1();
- BigInteger g2 = pk.getParameters().getG2();
-
- BigInteger h = pk.getH();
-
- if (!isValidMessage(input, p))
- {
- return result;
- }
-
- BigInteger r = generateRandomElement(p, random);
-
- BigInteger u1, u2, v, e, a;
-
- u1 = g1.modPow(r, p);
- u2 = g2.modPow(r, p);
- e = h.modPow(r, p).multiply(input).mod(p);
-
- Digest digest = pk.getParameters().getH();
- byte[] u1Bytes = u1.toByteArray();
- digest.update(u1Bytes, 0, u1Bytes.length);
- byte[] u2Bytes = u2.toByteArray();
- digest.update(u2Bytes, 0, u2Bytes.length);
- byte[] eBytes = e.toByteArray();
- digest.update(eBytes, 0, eBytes.length);
- if (this.label != null)
- {
- byte[] lBytes = this.label.getBytes();
- digest.update(lBytes, 0, lBytes.length);
- }
- byte[] out = new byte[digest.getDigestSize()];
- digest.doFinal(out, 0);
- a = new BigInteger(1, out);
-
- v = pk.getC().modPow(r, p).multiply(pk.getD().modPow(r.multiply(a), p)).mod(p);
-
- result = new CramerShoupCiphertext(u1, u2, e, v);
- }
- return result;
- }
-
- public BigInteger decryptBlock(CramerShoupCiphertext input)
- throws CramerShoupCiphertextException
- {
-
- BigInteger result = null;
-
- if (key.isPrivate() && !this.forEncryption && key instanceof CramerShoupPrivateKeyParameters)
- {
- CramerShoupPrivateKeyParameters sk = (CramerShoupPrivateKeyParameters)key;
-
- BigInteger p = sk.getParameters().getP();
-
- Digest digest = sk.getParameters().getH();
- byte[] u1Bytes = input.getU1().toByteArray();
- digest.update(u1Bytes, 0, u1Bytes.length);
- byte[] u2Bytes = input.getU2().toByteArray();
- digest.update(u2Bytes, 0, u2Bytes.length);
- byte[] eBytes = input.getE().toByteArray();
- digest.update(eBytes, 0, eBytes.length);
- if (this.label != null)
- {
- byte[] lBytes = this.label.getBytes();
- digest.update(lBytes, 0, lBytes.length);
- }
- byte[] out = new byte[digest.getDigestSize()];
- digest.doFinal(out, 0);
-
- BigInteger a = new BigInteger(1, out);
- BigInteger v = input.u1.modPow(sk.getX1().add(sk.getY1().multiply(a)), p).
- multiply(input.u2.modPow(sk.getX2().add(sk.getY2().multiply(a)), p)).mod(p);
-
- // check correctness of ciphertext
- if (input.v.equals(v))
- {
- result = input.e.multiply(input.u1.modPow(sk.getZ(), p).modInverse(p)).mod(p);
- }
- else
- {
- throw new CramerShoupCiphertextException("Sorry, that ciphertext is not correct");
- }
- }
- return result;
- }
-
- private BigInteger generateRandomElement(BigInteger p, SecureRandom random)
- {
- return BigIntegers.createRandomInRange(ONE, p.subtract(ONE), random);
- }
-
- /**
- * just checking whether the message m is actually less than the group order p
- */
- private boolean isValidMessage(BigInteger m, BigInteger p)
- {
- return m.compareTo(p) < 0;
- }
-
- protected SecureRandom initSecureRandom(boolean needed, SecureRandom provided)
- {
- return !needed ? null : (provided != null) ? provided : new SecureRandom();
- }
-
- /**
- * CS exception for wrong cipher-texts
- */
- public static class CramerShoupCiphertextException
- extends Exception
- {
- private static final long serialVersionUID = -6360977166495345076L;
-
- public CramerShoupCiphertextException(String msg)
- {
- super(msg);
- }
-
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/DESEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/DESEngine.java
deleted file mode 100644
index 6980fd08..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/DESEngine.java
+++ /dev/null
@@ -1,495 +0,0 @@
-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;
-
-/**
- * a class that provides a basic DES engine.
- */
-public class DESEngine
- implements BlockCipher
-{
- protected static final int BLOCK_SIZE = 8;
-
- private int[] workingKey = null;
-
- /**
- * standard constructor.
- */
- public DESEngine()
- {
- }
-
- /**
- * initialise a DES cipher.
- *
- * @param encrypting whether or not we are for encryption.
- * @param params the parameters required to set up the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean encrypting,
- CipherParameters params)
- {
- if (params instanceof KeyParameter)
- {
- if (((KeyParameter)params).getKey().length > 8)
- {
- throw new IllegalArgumentException("DES key too long - should be 8 bytes");
- }
-
- workingKey = generateWorkingKey(encrypting,
- ((KeyParameter)params).getKey());
-
- return;
- }
-
- throw new IllegalArgumentException("invalid parameter passed to DES init - " + params.getClass().getName());
- }
-
- public String getAlgorithmName()
- {
- return "DES";
- }
-
- public int getBlockSize()
- {
- return BLOCK_SIZE;
- }
-
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- if (workingKey == null)
- {
- throw new IllegalStateException("DES engine not initialised");
- }
-
- if ((inOff + BLOCK_SIZE) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + BLOCK_SIZE) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- desFunc(workingKey, in, inOff, out, outOff);
-
- return BLOCK_SIZE;
- }
-
- public void reset()
- {
- }
-
- /**
- * what follows is mainly taken from "Applied Cryptography", by
- * Bruce Schneier, however it also bears great resemblance to Richard
- * Outerbridge's D3DES...
- */
-
-// private static final short[] Df_Key =
-// {
-// 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
-// 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,
-// 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67
-// };
-
- private static final short[] bytebit =
- {
- 0200, 0100, 040, 020, 010, 04, 02, 01
- };
-
- private static final int[] bigbyte =
- {
- 0x800000, 0x400000, 0x200000, 0x100000,
- 0x80000, 0x40000, 0x20000, 0x10000,
- 0x8000, 0x4000, 0x2000, 0x1000,
- 0x800, 0x400, 0x200, 0x100,
- 0x80, 0x40, 0x20, 0x10,
- 0x8, 0x4, 0x2, 0x1
- };
-
- /*
- * Use the key schedule specified in the Standard (ANSI X3.92-1981).
- */
-
- private static final byte[] pc1 =
- {
- 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
- 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
- 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
- 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3
- };
-
- private static final byte[] totrot =
- {
- 1, 2, 4, 6, 8, 10, 12, 14,
- 15, 17, 19, 21, 23, 25, 27, 28
- };
-
- private static final byte[] pc2 =
- {
- 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
- 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
- 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
- 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
- };
-
- private static final int[] SP1 = {
- 0x01010400, 0x00000000, 0x00010000, 0x01010404,
- 0x01010004, 0x00010404, 0x00000004, 0x00010000,
- 0x00000400, 0x01010400, 0x01010404, 0x00000400,
- 0x01000404, 0x01010004, 0x01000000, 0x00000004,
- 0x00000404, 0x01000400, 0x01000400, 0x00010400,
- 0x00010400, 0x01010000, 0x01010000, 0x01000404,
- 0x00010004, 0x01000004, 0x01000004, 0x00010004,
- 0x00000000, 0x00000404, 0x00010404, 0x01000000,
- 0x00010000, 0x01010404, 0x00000004, 0x01010000,
- 0x01010400, 0x01000000, 0x01000000, 0x00000400,
- 0x01010004, 0x00010000, 0x00010400, 0x01000004,
- 0x00000400, 0x00000004, 0x01000404, 0x00010404,
- 0x01010404, 0x00010004, 0x01010000, 0x01000404,
- 0x01000004, 0x00000404, 0x00010404, 0x01010400,
- 0x00000404, 0x01000400, 0x01000400, 0x00000000,
- 0x00010004, 0x00010400, 0x00000000, 0x01010004
- };
-
- private static final int[] SP2 = {
- 0x80108020, 0x80008000, 0x00008000, 0x00108020,
- 0x00100000, 0x00000020, 0x80100020, 0x80008020,
- 0x80000020, 0x80108020, 0x80108000, 0x80000000,
- 0x80008000, 0x00100000, 0x00000020, 0x80100020,
- 0x00108000, 0x00100020, 0x80008020, 0x00000000,
- 0x80000000, 0x00008000, 0x00108020, 0x80100000,
- 0x00100020, 0x80000020, 0x00000000, 0x00108000,
- 0x00008020, 0x80108000, 0x80100000, 0x00008020,
- 0x00000000, 0x00108020, 0x80100020, 0x00100000,
- 0x80008020, 0x80100000, 0x80108000, 0x00008000,
- 0x80100000, 0x80008000, 0x00000020, 0x80108020,
- 0x00108020, 0x00000020, 0x00008000, 0x80000000,
- 0x00008020, 0x80108000, 0x00100000, 0x80000020,
- 0x00100020, 0x80008020, 0x80000020, 0x00100020,
- 0x00108000, 0x00000000, 0x80008000, 0x00008020,
- 0x80000000, 0x80100020, 0x80108020, 0x00108000
- };
-
- private static final int[] SP3 = {
- 0x00000208, 0x08020200, 0x00000000, 0x08020008,
- 0x08000200, 0x00000000, 0x00020208, 0x08000200,
- 0x00020008, 0x08000008, 0x08000008, 0x00020000,
- 0x08020208, 0x00020008, 0x08020000, 0x00000208,
- 0x08000000, 0x00000008, 0x08020200, 0x00000200,
- 0x00020200, 0x08020000, 0x08020008, 0x00020208,
- 0x08000208, 0x00020200, 0x00020000, 0x08000208,
- 0x00000008, 0x08020208, 0x00000200, 0x08000000,
- 0x08020200, 0x08000000, 0x00020008, 0x00000208,
- 0x00020000, 0x08020200, 0x08000200, 0x00000000,
- 0x00000200, 0x00020008, 0x08020208, 0x08000200,
- 0x08000008, 0x00000200, 0x00000000, 0x08020008,
- 0x08000208, 0x00020000, 0x08000000, 0x08020208,
- 0x00000008, 0x00020208, 0x00020200, 0x08000008,
- 0x08020000, 0x08000208, 0x00000208, 0x08020000,
- 0x00020208, 0x00000008, 0x08020008, 0x00020200
- };
-
- private static final int[] SP4 = {
- 0x00802001, 0x00002081, 0x00002081, 0x00000080,
- 0x00802080, 0x00800081, 0x00800001, 0x00002001,
- 0x00000000, 0x00802000, 0x00802000, 0x00802081,
- 0x00000081, 0x00000000, 0x00800080, 0x00800001,
- 0x00000001, 0x00002000, 0x00800000, 0x00802001,
- 0x00000080, 0x00800000, 0x00002001, 0x00002080,
- 0x00800081, 0x00000001, 0x00002080, 0x00800080,
- 0x00002000, 0x00802080, 0x00802081, 0x00000081,
- 0x00800080, 0x00800001, 0x00802000, 0x00802081,
- 0x00000081, 0x00000000, 0x00000000, 0x00802000,
- 0x00002080, 0x00800080, 0x00800081, 0x00000001,
- 0x00802001, 0x00002081, 0x00002081, 0x00000080,
- 0x00802081, 0x00000081, 0x00000001, 0x00002000,
- 0x00800001, 0x00002001, 0x00802080, 0x00800081,
- 0x00002001, 0x00002080, 0x00800000, 0x00802001,
- 0x00000080, 0x00800000, 0x00002000, 0x00802080
- };
-
- private static final int[] SP5 = {
- 0x00000100, 0x02080100, 0x02080000, 0x42000100,
- 0x00080000, 0x00000100, 0x40000000, 0x02080000,
- 0x40080100, 0x00080000, 0x02000100, 0x40080100,
- 0x42000100, 0x42080000, 0x00080100, 0x40000000,
- 0x02000000, 0x40080000, 0x40080000, 0x00000000,
- 0x40000100, 0x42080100, 0x42080100, 0x02000100,
- 0x42080000, 0x40000100, 0x00000000, 0x42000000,
- 0x02080100, 0x02000000, 0x42000000, 0x00080100,
- 0x00080000, 0x42000100, 0x00000100, 0x02000000,
- 0x40000000, 0x02080000, 0x42000100, 0x40080100,
- 0x02000100, 0x40000000, 0x42080000, 0x02080100,
- 0x40080100, 0x00000100, 0x02000000, 0x42080000,
- 0x42080100, 0x00080100, 0x42000000, 0x42080100,
- 0x02080000, 0x00000000, 0x40080000, 0x42000000,
- 0x00080100, 0x02000100, 0x40000100, 0x00080000,
- 0x00000000, 0x40080000, 0x02080100, 0x40000100
- };
-
- private static final int[] SP6 = {
- 0x20000010, 0x20400000, 0x00004000, 0x20404010,
- 0x20400000, 0x00000010, 0x20404010, 0x00400000,
- 0x20004000, 0x00404010, 0x00400000, 0x20000010,
- 0x00400010, 0x20004000, 0x20000000, 0x00004010,
- 0x00000000, 0x00400010, 0x20004010, 0x00004000,
- 0x00404000, 0x20004010, 0x00000010, 0x20400010,
- 0x20400010, 0x00000000, 0x00404010, 0x20404000,
- 0x00004010, 0x00404000, 0x20404000, 0x20000000,
- 0x20004000, 0x00000010, 0x20400010, 0x00404000,
- 0x20404010, 0x00400000, 0x00004010, 0x20000010,
- 0x00400000, 0x20004000, 0x20000000, 0x00004010,
- 0x20000010, 0x20404010, 0x00404000, 0x20400000,
- 0x00404010, 0x20404000, 0x00000000, 0x20400010,
- 0x00000010, 0x00004000, 0x20400000, 0x00404010,
- 0x00004000, 0x00400010, 0x20004010, 0x00000000,
- 0x20404000, 0x20000000, 0x00400010, 0x20004010
- };
-
- private static final int[] SP7 = {
- 0x00200000, 0x04200002, 0x04000802, 0x00000000,
- 0x00000800, 0x04000802, 0x00200802, 0x04200800,
- 0x04200802, 0x00200000, 0x00000000, 0x04000002,
- 0x00000002, 0x04000000, 0x04200002, 0x00000802,
- 0x04000800, 0x00200802, 0x00200002, 0x04000800,
- 0x04000002, 0x04200000, 0x04200800, 0x00200002,
- 0x04200000, 0x00000800, 0x00000802, 0x04200802,
- 0x00200800, 0x00000002, 0x04000000, 0x00200800,
- 0x04000000, 0x00200800, 0x00200000, 0x04000802,
- 0x04000802, 0x04200002, 0x04200002, 0x00000002,
- 0x00200002, 0x04000000, 0x04000800, 0x00200000,
- 0x04200800, 0x00000802, 0x00200802, 0x04200800,
- 0x00000802, 0x04000002, 0x04200802, 0x04200000,
- 0x00200800, 0x00000000, 0x00000002, 0x04200802,
- 0x00000000, 0x00200802, 0x04200000, 0x00000800,
- 0x04000002, 0x04000800, 0x00000800, 0x00200002
- };
-
- private static final int[] SP8 = {
- 0x10001040, 0x00001000, 0x00040000, 0x10041040,
- 0x10000000, 0x10001040, 0x00000040, 0x10000000,
- 0x00040040, 0x10040000, 0x10041040, 0x00041000,
- 0x10041000, 0x00041040, 0x00001000, 0x00000040,
- 0x10040000, 0x10000040, 0x10001000, 0x00001040,
- 0x00041000, 0x00040040, 0x10040040, 0x10041000,
- 0x00001040, 0x00000000, 0x00000000, 0x10040040,
- 0x10000040, 0x10001000, 0x00041040, 0x00040000,
- 0x00041040, 0x00040000, 0x10041000, 0x00001000,
- 0x00000040, 0x10040040, 0x00001000, 0x00041040,
- 0x10001000, 0x00000040, 0x10000040, 0x10040000,
- 0x10040040, 0x10000000, 0x00040000, 0x10001040,
- 0x00000000, 0x10041040, 0x00040040, 0x10000040,
- 0x10040000, 0x10001000, 0x10001040, 0x00000000,
- 0x10041040, 0x00041000, 0x00041000, 0x00001040,
- 0x00001040, 0x00040040, 0x10000000, 0x10041000
- };
-
- /**
- * generate an integer based working key based on our secret key
- * and what we processing we are planning to do.
- *
- * Acknowledgements for this routine go to James Gillogly &amp; Phil Karn.
- * (whoever, and wherever they are!).
- */
- protected int[] generateWorkingKey(
- boolean encrypting,
- byte[] key)
- {
- int[] newKey = new int[32];
- boolean[] pc1m = new boolean[56],
- pcr = new boolean[56];
-
- for (int j = 0; j < 56; j++)
- {
- int l = pc1[j];
-
- pc1m[j] = ((key[l >>> 3] & bytebit[l & 07]) != 0);
- }
-
- for (int i = 0; i < 16; i++)
- {
- int l, m, n;
-
- if (encrypting)
- {
- m = i << 1;
- }
- else
- {
- m = (15 - i) << 1;
- }
-
- n = m + 1;
- newKey[m] = newKey[n] = 0;
-
- for (int j = 0; j < 28; j++)
- {
- l = j + totrot[i];
- if (l < 28)
- {
- pcr[j] = pc1m[l];
- }
- else
- {
- pcr[j] = pc1m[l - 28];
- }
- }
-
- for (int j = 28; j < 56; j++)
- {
- l = j + totrot[i];
- if (l < 56)
- {
- pcr[j] = pc1m[l];
- }
- else
- {
- pcr[j] = pc1m[l - 28];
- }
- }
-
- for (int j = 0; j < 24; j++)
- {
- if (pcr[pc2[j]])
- {
- newKey[m] |= bigbyte[j];
- }
-
- if (pcr[pc2[j + 24]])
- {
- newKey[n] |= bigbyte[j];
- }
- }
- }
-
- //
- // store the processed key
- //
- for (int i = 0; i != 32; i += 2)
- {
- int i1, i2;
-
- i1 = newKey[i];
- i2 = newKey[i + 1];
-
- newKey[i] = ((i1 & 0x00fc0000) << 6) | ((i1 & 0x00000fc0) << 10)
- | ((i2 & 0x00fc0000) >>> 10) | ((i2 & 0x00000fc0) >>> 6);
-
- newKey[i + 1] = ((i1 & 0x0003f000) << 12) | ((i1 & 0x0000003f) << 16)
- | ((i2 & 0x0003f000) >>> 4) | (i2 & 0x0000003f);
- }
-
- return newKey;
- }
-
- /**
- * the DES engine.
- */
- protected void desFunc(
- int[] wKey,
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- int work, right, left;
-
- left = (in[inOff + 0] & 0xff) << 24;
- left |= (in[inOff + 1] & 0xff) << 16;
- left |= (in[inOff + 2] & 0xff) << 8;
- left |= (in[inOff + 3] & 0xff);
-
- right = (in[inOff + 4] & 0xff) << 24;
- right |= (in[inOff + 5] & 0xff) << 16;
- right |= (in[inOff + 6] & 0xff) << 8;
- right |= (in[inOff + 7] & 0xff);
-
- work = ((left >>> 4) ^ right) & 0x0f0f0f0f;
- right ^= work;
- left ^= (work << 4);
- work = ((left >>> 16) ^ right) & 0x0000ffff;
- right ^= work;
- left ^= (work << 16);
- work = ((right >>> 2) ^ left) & 0x33333333;
- left ^= work;
- right ^= (work << 2);
- work = ((right >>> 8) ^ left) & 0x00ff00ff;
- left ^= work;
- right ^= (work << 8);
- right = ((right << 1) | ((right >>> 31) & 1)) & 0xffffffff;
- work = (left ^ right) & 0xaaaaaaaa;
- left ^= work;
- right ^= work;
- left = ((left << 1) | ((left >>> 31) & 1)) & 0xffffffff;
-
- for (int round = 0; round < 8; round++)
- {
- int fval;
-
- work = (right << 28) | (right >>> 4);
- work ^= wKey[round * 4 + 0];
- fval = SP7[ work & 0x3f];
- fval |= SP5[(work >>> 8) & 0x3f];
- fval |= SP3[(work >>> 16) & 0x3f];
- fval |= SP1[(work >>> 24) & 0x3f];
- work = right ^ wKey[round * 4 + 1];
- fval |= SP8[ work & 0x3f];
- fval |= SP6[(work >>> 8) & 0x3f];
- fval |= SP4[(work >>> 16) & 0x3f];
- fval |= SP2[(work >>> 24) & 0x3f];
- left ^= fval;
- work = (left << 28) | (left >>> 4);
- work ^= wKey[round * 4 + 2];
- fval = SP7[ work & 0x3f];
- fval |= SP5[(work >>> 8) & 0x3f];
- fval |= SP3[(work >>> 16) & 0x3f];
- fval |= SP1[(work >>> 24) & 0x3f];
- work = left ^ wKey[round * 4 + 3];
- fval |= SP8[ work & 0x3f];
- fval |= SP6[(work >>> 8) & 0x3f];
- fval |= SP4[(work >>> 16) & 0x3f];
- fval |= SP2[(work >>> 24) & 0x3f];
- right ^= fval;
- }
-
- right = (right << 31) | (right >>> 1);
- work = (left ^ right) & 0xaaaaaaaa;
- left ^= work;
- right ^= work;
- left = (left << 31) | (left >>> 1);
- work = ((left >>> 8) ^ right) & 0x00ff00ff;
- right ^= work;
- left ^= (work << 8);
- work = ((left >>> 2) ^ right) & 0x33333333;
- right ^= work;
- left ^= (work << 2);
- work = ((right >>> 16) ^ left) & 0x0000ffff;
- left ^= work;
- right ^= (work << 16);
- work = ((right >>> 4) ^ left) & 0x0f0f0f0f;
- left ^= work;
- right ^= (work << 4);
-
- out[outOff + 0] = (byte)((right >>> 24) & 0xff);
- out[outOff + 1] = (byte)((right >>> 16) & 0xff);
- out[outOff + 2] = (byte)((right >>> 8) & 0xff);
- out[outOff + 3] = (byte)(right & 0xff);
- out[outOff + 4] = (byte)((left >>> 24) & 0xff);
- out[outOff + 5] = (byte)((left >>> 16) & 0xff);
- out[outOff + 6] = (byte)((left >>> 8) & 0xff);
- out[outOff + 7] = (byte)(left & 0xff);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/DESedeEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/DESedeEngine.java
deleted file mode 100644
index 513eccdf..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/DESedeEngine.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.OutputLengthException;
-import org.bouncycastle.crypto.params.KeyParameter;
-
-/**
- * a class that provides a basic DESede (or Triple DES) engine.
- */
-public class DESedeEngine
- extends DESEngine
-{
- protected static final int BLOCK_SIZE = 8;
-
- private int[] workingKey1 = null;
- private int[] workingKey2 = null;
- private int[] workingKey3 = null;
-
- private boolean forEncryption;
-
- /**
- * standard constructor.
- */
- public DESedeEngine()
- {
- }
-
- /**
- * initialise a DESede cipher.
- *
- * @param encrypting whether or not we are for encryption.
- * @param params the parameters required to set up the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean encrypting,
- CipherParameters params)
- {
- if (!(params instanceof KeyParameter))
- {
- throw new IllegalArgumentException("invalid parameter passed to DESede init - " + params.getClass().getName());
- }
-
- byte[] keyMaster = ((KeyParameter)params).getKey();
-
- if (keyMaster.length != 24 && keyMaster.length != 16)
- {
- throw new IllegalArgumentException("key size must be 16 or 24 bytes.");
- }
-
- this.forEncryption = encrypting;
-
- byte[] key1 = new byte[8];
- System.arraycopy(keyMaster, 0, key1, 0, key1.length);
- workingKey1 = generateWorkingKey(encrypting, key1);
-
- byte[] key2 = new byte[8];
- System.arraycopy(keyMaster, 8, key2, 0, key2.length);
- workingKey2 = generateWorkingKey(!encrypting, key2);
-
- if (keyMaster.length == 24)
- {
- byte[] key3 = new byte[8];
- System.arraycopy(keyMaster, 16, key3, 0, key3.length);
- workingKey3 = generateWorkingKey(encrypting, key3);
- }
- else // 16 byte key
- {
- workingKey3 = workingKey1;
- }
- }
-
- public String getAlgorithmName()
- {
- return "DESede";
- }
-
- public int getBlockSize()
- {
- return BLOCK_SIZE;
- }
-
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- if (workingKey1 == null)
- {
- throw new IllegalStateException("DESede engine not initialised");
- }
-
- if ((inOff + BLOCK_SIZE) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + BLOCK_SIZE) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- byte[] temp = new byte[BLOCK_SIZE];
-
- if (forEncryption)
- {
- desFunc(workingKey1, in, inOff, temp, 0);
- desFunc(workingKey2, temp, 0, temp, 0);
- desFunc(workingKey3, temp, 0, out, outOff);
- }
- else
- {
- desFunc(workingKey3, in, inOff, temp, 0);
- desFunc(workingKey2, temp, 0, temp, 0);
- desFunc(workingKey1, temp, 0, out, outOff);
- }
-
- return BLOCK_SIZE;
- }
-
- public void reset()
- {
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java
deleted file mode 100644
index 923a79cd..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java
+++ /dev/null
@@ -1,350 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.Wrapper;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.modes.CBCBlockCipher;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.util.Arrays;
-
-/**
- * Wrap keys according to
- * <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-smime-key-wrap-01.txt">
- * draft-ietf-smime-key-wrap-01.txt</A>.
- * <p>
- * Note:
- * <ul>
- * <li>this is based on a draft, and as such is subject to change - don't use this class for anything requiring long term storage.
- * <li>if you are using this to wrap triple-des keys you need to set the
- * parity bits on the key and, if it's a two-key triple-des key, pad it
- * yourself.
- * </ul>
- */
-public class DESedeWrapEngine
- implements Wrapper
-{
- /** Field engine */
- private CBCBlockCipher engine;
-
- /** Field param */
- private KeyParameter param;
-
- /** Field paramPlusIV */
- private ParametersWithIV paramPlusIV;
-
- /** Field iv */
- private byte[] iv;
-
- /** Field forWrapping */
- private boolean forWrapping;
-
- /** Field IV2 */
- private static final byte[] IV2 = { (byte) 0x4a, (byte) 0xdd, (byte) 0xa2,
- (byte) 0x2c, (byte) 0x79, (byte) 0xe8,
- (byte) 0x21, (byte) 0x05 };
-
- //
- // checksum digest
- //
- Digest sha1 = new SHA1Digest();
- byte[] digest = new byte[20];
-
- /**
- * Method init
- *
- * @param forWrapping true if for wrapping, false otherwise.
- * @param param necessary parameters, may include KeyParameter, ParametersWithRandom, and ParametersWithIV
- */
- public void init(boolean forWrapping, CipherParameters param)
- {
-
- this.forWrapping = forWrapping;
- this.engine = new CBCBlockCipher(new DESedeEngine());
-
- SecureRandom sr;
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom pr = (ParametersWithRandom) param;
- param = pr.getParameters();
- sr = pr.getRandom();
- }
- else
- {
- sr = new SecureRandom();
- }
-
- if (param instanceof KeyParameter)
- {
- this.param = (KeyParameter)param;
-
- if (this.forWrapping)
- {
-
- // Hm, we have no IV but we want to wrap ?!?
- // well, then we have to create our own IV.
- this.iv = new byte[8];
- sr.nextBytes(iv);
-
- this.paramPlusIV = new ParametersWithIV(this.param, this.iv);
- }
- }
- else if (param instanceof ParametersWithIV)
- {
- this.paramPlusIV = (ParametersWithIV)param;
- this.iv = this.paramPlusIV.getIV();
- this.param = (KeyParameter)this.paramPlusIV.getParameters();
-
- if (this.forWrapping)
- {
- if ((this.iv == null) || (this.iv.length != 8))
- {
- throw new IllegalArgumentException("IV is not 8 octets");
- }
- }
- else
- {
- throw new IllegalArgumentException(
- "You should not supply an IV for unwrapping");
- }
- }
- }
-
- /**
- * Method getAlgorithmName
- *
- * @return the algorithm name "DESede".
- */
- public String getAlgorithmName()
- {
- return "DESede";
- }
-
- /**
- * Method wrap
- *
- * @param in byte array containing the encoded key.
- * @param inOff off set into in that the data starts at.
- * @param inLen length of the data.
- * @return the wrapped bytes.
- */
- public byte[] wrap(byte[] in, int inOff, int inLen)
- {
- if (!forWrapping)
- {
- throw new IllegalStateException("Not initialized for wrapping");
- }
-
- byte keyToBeWrapped[] = new byte[inLen];
-
- System.arraycopy(in, inOff, keyToBeWrapped, 0, inLen);
-
- // Compute the CMS Key Checksum, (section 5.6.1), call this CKS.
- byte[] CKS = calculateCMSKeyChecksum(keyToBeWrapped);
-
- // Let WKCKS = WK || CKS where || is concatenation.
- byte[] WKCKS = new byte[keyToBeWrapped.length + CKS.length];
-
- System.arraycopy(keyToBeWrapped, 0, WKCKS, 0, keyToBeWrapped.length);
- System.arraycopy(CKS, 0, WKCKS, keyToBeWrapped.length, CKS.length);
-
- // Encrypt WKCKS in CBC mode using KEK as the key and IV as the
- // initialization vector. Call the results TEMP1.
-
- int blockSize = engine.getBlockSize();
-
- if (WKCKS.length % blockSize != 0)
- {
- throw new IllegalStateException("Not multiple of block length");
- }
-
- engine.init(true, paramPlusIV);
-
- byte TEMP1[] = new byte[WKCKS.length];
-
- for (int currentBytePos = 0; currentBytePos != WKCKS.length; currentBytePos += blockSize)
- {
- engine.processBlock(WKCKS, currentBytePos, TEMP1, currentBytePos);
- }
-
- // Let TEMP2 = IV || TEMP1.
- byte[] TEMP2 = new byte[this.iv.length + TEMP1.length];
-
- System.arraycopy(this.iv, 0, TEMP2, 0, this.iv.length);
- System.arraycopy(TEMP1, 0, TEMP2, this.iv.length, TEMP1.length);
-
- // Reverse the order of the octets in TEMP2 and call the result TEMP3.
- byte[] TEMP3 = reverse(TEMP2);
-
- // Encrypt TEMP3 in CBC mode using the KEK and an initialization vector
- // of 0x 4a dd a2 2c 79 e8 21 05. The resulting cipher text is the desired
- // result. It is 40 octets long if a 168 bit key is being wrapped.
- ParametersWithIV param2 = new ParametersWithIV(this.param, IV2);
-
- this.engine.init(true, param2);
-
- for (int currentBytePos = 0; currentBytePos != TEMP3.length; currentBytePos += blockSize)
- {
- engine.processBlock(TEMP3, currentBytePos, TEMP3, currentBytePos);
- }
-
- return TEMP3;
- }
-
- /**
- * Method unwrap
- *
- * @param in byte array containing the wrapped key.
- * @param inOff off set into in that the data starts at.
- * @param inLen length of the data.
- * @return the unwrapped bytes.
- * @throws InvalidCipherTextException
- */
- public byte[] unwrap(byte[] in, int inOff, int inLen)
- throws InvalidCipherTextException
- {
- if (forWrapping)
- {
- throw new IllegalStateException("Not set for unwrapping");
- }
-
- if (in == null)
- {
- throw new InvalidCipherTextException("Null pointer as ciphertext");
- }
-
- final int blockSize = engine.getBlockSize();
- if (inLen % blockSize != 0)
- {
- throw new InvalidCipherTextException("Ciphertext not multiple of " + blockSize);
- }
-
- /*
- // Check if the length of the cipher text is reasonable given the key
- // type. It must be 40 bytes for a 168 bit key and either 32, 40, or
- // 48 bytes for a 128, 192, or 256 bit key. If the length is not supported
- // or inconsistent with the algorithm for which the key is intended,
- // return error.
- //
- // we do not accept 168 bit keys. it has to be 192 bit.
- int lengthA = (estimatedKeyLengthInBit / 8) + 16;
- int lengthB = estimatedKeyLengthInBit % 8;
-
- if ((lengthA != keyToBeUnwrapped.length) || (lengthB != 0)) {
- throw new XMLSecurityException("empty");
- }
- */
-
- // Decrypt the cipher text with TRIPLedeS in CBC mode using the KEK
- // and an initialization vector (IV) of 0x4adda22c79e82105. Call the output TEMP3.
- ParametersWithIV param2 = new ParametersWithIV(this.param, IV2);
-
- this.engine.init(false, param2);
-
- byte TEMP3[] = new byte[inLen];
-
- for (int currentBytePos = 0; currentBytePos != inLen; currentBytePos += blockSize)
- {
- engine.processBlock(in, inOff + currentBytePos, TEMP3, currentBytePos);
- }
-
- // Reverse the order of the octets in TEMP3 and call the result TEMP2.
- byte[] TEMP2 = reverse(TEMP3);
-
- // Decompose TEMP2 into IV, the first 8 octets, and TEMP1, the remaining octets.
- this.iv = new byte[8];
-
- byte[] TEMP1 = new byte[TEMP2.length - 8];
-
- System.arraycopy(TEMP2, 0, this.iv, 0, 8);
- System.arraycopy(TEMP2, 8, TEMP1, 0, TEMP2.length - 8);
-
- // Decrypt TEMP1 using TRIPLedeS in CBC mode using the KEK and the IV
- // found in the previous step. Call the result WKCKS.
- this.paramPlusIV = new ParametersWithIV(this.param, this.iv);
-
- this.engine.init(false, this.paramPlusIV);
-
- byte[] WKCKS = new byte[TEMP1.length];
-
- for (int currentBytePos = 0; currentBytePos != WKCKS.length; currentBytePos += blockSize)
- {
- engine.processBlock(TEMP1, currentBytePos, WKCKS, currentBytePos);
- }
-
- // Decompose WKCKS. CKS is the last 8 octets and WK, the wrapped key, are
- // those octets before the CKS.
- byte[] result = new byte[WKCKS.length - 8];
- byte[] CKStoBeVerified = new byte[8];
-
- System.arraycopy(WKCKS, 0, result, 0, WKCKS.length - 8);
- System.arraycopy(WKCKS, WKCKS.length - 8, CKStoBeVerified, 0, 8);
-
- // Calculate a CMS Key Checksum, (section 5.6.1), over the WK and compare
- // with the CKS extracted in the above step. If they are not equal, return error.
- if (!checkCMSKeyChecksum(result, CKStoBeVerified))
- {
- throw new InvalidCipherTextException(
- "Checksum inside ciphertext is corrupted");
- }
-
- // WK is the wrapped key, now extracted for use in data decryption.
- return result;
- }
-
- /**
- * Some key wrap algorithms make use of the Key Checksum defined
- * in CMS [CMS-Algorithms]. This is used to provide an integrity
- * check value for the key being wrapped. The algorithm is
- *
- * - Compute the 20 octet SHA-1 hash on the key being wrapped.
- * - Use the first 8 octets of this hash as the checksum value.
- *
- * For details see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum.
- *
- * @param key the key to check,
- * @return the CMS checksum.
- * @throws RuntimeException
- */
- private byte[] calculateCMSKeyChecksum(
- byte[] key)
- {
- byte[] result = new byte[8];
-
- sha1.update(key, 0, key.length);
- sha1.doFinal(digest, 0);
-
- System.arraycopy(digest, 0, result, 0, 8);
-
- return result;
- }
-
- /**
- * For details see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
- *
- * @param key key to be validated.
- * @param checksum the checksum.
- * @return true if okay, false otherwise.
- */
- private boolean checkCMSKeyChecksum(
- byte[] key,
- byte[] checksum)
- {
- return Arrays.constantTimeAreEqual(calculateCMSKeyChecksum(key), checksum);
- }
-
- private static byte[] reverse(byte[] bs)
- {
- byte[] result = new byte[bs.length];
- for (int i = 0; i < bs.length; i++)
- {
- result[i] = bs[bs.length - (i + 1)];
- }
- return result;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/ElGamalEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/ElGamalEngine.java
deleted file mode 100644
index ef8e799d..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/ElGamalEngine.java
+++ /dev/null
@@ -1,217 +0,0 @@
-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;
-import org.bouncycastle.crypto.params.ElGamalKeyParameters;
-import org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ElGamalPublicKeyParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.util.BigIntegers;
-
-/**
- * this does your basic ElGamal algorithm.
- */
-public class ElGamalEngine
- implements AsymmetricBlockCipher
-{
- private ElGamalKeyParameters key;
- private SecureRandom random;
- private boolean forEncryption;
- private int bitSize;
-
- private static final BigInteger ZERO = BigInteger.valueOf(0);
- private static final BigInteger ONE = BigInteger.valueOf(1);
- private static final BigInteger TWO = BigInteger.valueOf(2);
-
- /**
- * initialise the ElGamal engine.
- *
- * @param forEncryption true if we are encrypting, false otherwise.
- * @param param the necessary ElGamal key parameters.
- */
- public void init(
- boolean forEncryption,
- CipherParameters param)
- {
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom p = (ParametersWithRandom)param;
-
- this.key = (ElGamalKeyParameters)p.getParameters();
- this.random = p.getRandom();
- }
- else
- {
- this.key = (ElGamalKeyParameters)param;
- this.random = new SecureRandom();
- }
-
- this.forEncryption = forEncryption;
-
- BigInteger p = key.getParameters().getP();
-
- bitSize = p.bitLength();
-
- if (forEncryption)
- {
- if (!(key instanceof ElGamalPublicKeyParameters))
- {
- throw new IllegalArgumentException("ElGamalPublicKeyParameters are required for encryption.");
- }
- }
- else
- {
- if (!(key instanceof ElGamalPrivateKeyParameters))
- {
- throw new IllegalArgumentException("ElGamalPrivateKeyParameters are required for decryption.");
- }
- }
- }
-
- /**
- * Return the maximum size for an input block to this engine.
- * For ElGamal this is always one byte less than the size of P on
- * encryption, and twice the length as the size of P on decryption.
- *
- * @return maximum size for an input block.
- */
- public int getInputBlockSize()
- {
- if (forEncryption)
- {
- return (bitSize - 1) / 8;
- }
-
- return 2 * ((bitSize + 7) / 8);
- }
-
- /**
- * Return the maximum size for an output block to this engine.
- * For ElGamal this is always one byte less than the size of P on
- * decryption, and twice the length as the size of P on encryption.
- *
- * @return maximum size for an output block.
- */
- public int getOutputBlockSize()
- {
- if (forEncryption)
- {
- return 2 * ((bitSize + 7) / 8);
- }
-
- return (bitSize - 1) / 8;
- }
-
- /**
- * Process a single block using the basic ElGamal algorithm.
- *
- * @param in the input array.
- * @param inOff the offset into the input buffer where the data starts.
- * @param inLen the length of the data to be processed.
- * @return the result of the ElGamal process.
- * @exception DataLengthException the input block is too large.
- */
- public byte[] processBlock(
- byte[] in,
- int inOff,
- int inLen)
- {
- if (key == null)
- {
- throw new IllegalStateException("ElGamal engine not initialised");
- }
-
- int maxLength = forEncryption
- ? (bitSize - 1 + 7) / 8
- : getInputBlockSize();
-
- if (inLen > maxLength)
- {
- throw new DataLengthException("input too large for ElGamal cipher.\n");
- }
-
- BigInteger p = key.getParameters().getP();
-
- if (key instanceof ElGamalPrivateKeyParameters) // decryption
- {
- byte[] in1 = new byte[inLen / 2];
- byte[] in2 = new byte[inLen / 2];
-
- System.arraycopy(in, inOff, in1, 0, in1.length);
- System.arraycopy(in, inOff + in1.length, in2, 0, in2.length);
-
- BigInteger gamma = new BigInteger(1, in1);
- BigInteger phi = new BigInteger(1, in2);
-
- ElGamalPrivateKeyParameters priv = (ElGamalPrivateKeyParameters)key;
- // a shortcut, which generally relies on p being prime amongst other things.
- // if a problem with this shows up, check the p and g values!
- BigInteger m = gamma.modPow(p.subtract(ONE).subtract(priv.getX()), p).multiply(phi).mod(p);
-
- return BigIntegers.asUnsignedByteArray(m);
- }
- else // encryption
- {
- byte[] block;
- if (inOff != 0 || inLen != in.length)
- {
- block = new byte[inLen];
-
- System.arraycopy(in, inOff, block, 0, inLen);
- }
- else
- {
- block = in;
- }
-
- BigInteger input = new BigInteger(1, block);
-
- if (input.compareTo(p) >= 0)
- {
- throw new DataLengthException("input too large for ElGamal cipher.\n");
- }
-
- ElGamalPublicKeyParameters pub = (ElGamalPublicKeyParameters)key;
-
- int pBitLength = p.bitLength();
- BigInteger k = new BigInteger(pBitLength, random);
-
- while (k.equals(ZERO) || (k.compareTo(p.subtract(TWO)) > 0))
- {
- k = new BigInteger(pBitLength, random);
- }
-
- BigInteger g = key.getParameters().getG();
- BigInteger gamma = g.modPow(k, p);
- BigInteger phi = input.multiply(pub.getY().modPow(k, p)).mod(p);
-
- byte[] out1 = gamma.toByteArray();
- byte[] out2 = phi.toByteArray();
- byte[] output = new byte[this.getOutputBlockSize()];
-
- if (out1.length > output.length / 2)
- {
- System.arraycopy(out1, 1, output, output.length / 2 - (out1.length - 1), out1.length - 1);
- }
- else
- {
- System.arraycopy(out1, 0, output, output.length / 2 - out1.length, out1.length);
- }
-
- if (out2.length > output.length / 2)
- {
- System.arraycopy(out2, 1, output, output.length - (out2.length - 1), out2.length - 1);
- }
- else
- {
- System.arraycopy(out2, 0, output, output.length - out2.length, out2.length);
- }
-
- return output;
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/GOST28147Engine.java b/core/src/main/java/org/bouncycastle/crypto/engines/GOST28147Engine.java
deleted file mode 100644
index 5a88b7fe..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/GOST28147Engine.java
+++ /dev/null
@@ -1,372 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import java.util.Hashtable;
-
-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;
-import org.bouncycastle.crypto.params.ParametersWithSBox;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Strings;
-
-/**
- * implementation of GOST 28147-89
- */
-public class GOST28147Engine
- implements BlockCipher
-{
- protected static final int BLOCK_SIZE = 8;
- private int[] workingKey = null;
- private boolean forEncryption;
-
- private byte[] S = Sbox_Default;
-
- // these are the S-boxes given in Applied Cryptography 2nd Ed., p. 333
- // This is default S-box!
- private static byte Sbox_Default[] = {
- 0x4,0xA,0x9,0x2,0xD,0x8,0x0,0xE,0x6,0xB,0x1,0xC,0x7,0xF,0x5,0x3,
- 0xE,0xB,0x4,0xC,0x6,0xD,0xF,0xA,0x2,0x3,0x8,0x1,0x0,0x7,0x5,0x9,
- 0x5,0x8,0x1,0xD,0xA,0x3,0x4,0x2,0xE,0xF,0xC,0x7,0x6,0x0,0x9,0xB,
- 0x7,0xD,0xA,0x1,0x0,0x8,0x9,0xF,0xE,0x4,0x6,0xC,0xB,0x2,0x5,0x3,
- 0x6,0xC,0x7,0x1,0x5,0xF,0xD,0x8,0x4,0xA,0x9,0xE,0x0,0x3,0xB,0x2,
- 0x4,0xB,0xA,0x0,0x7,0x2,0x1,0xD,0x3,0x6,0x8,0x5,0x9,0xC,0xF,0xE,
- 0xD,0xB,0x4,0x1,0x3,0xF,0x5,0x9,0x0,0xA,0xE,0x7,0x6,0x8,0x2,0xC,
- 0x1,0xF,0xD,0x0,0x5,0x7,0xA,0x4,0x9,0x2,0x3,0xE,0x6,0xB,0x8,0xC
- };
-
- /*
- * class content S-box parameters for encrypting
- * getting from, see: http://tools.ietf.org/id/draft-popov-cryptopro-cpalgs-01.txt
- * http://tools.ietf.org/id/draft-popov-cryptopro-cpalgs-02.txt
- */
- private static byte[] ESbox_Test = {
- 0x4,0x2,0xF,0x5,0x9,0x1,0x0,0x8,0xE,0x3,0xB,0xC,0xD,0x7,0xA,0x6,
- 0xC,0x9,0xF,0xE,0x8,0x1,0x3,0xA,0x2,0x7,0x4,0xD,0x6,0x0,0xB,0x5,
- 0xD,0x8,0xE,0xC,0x7,0x3,0x9,0xA,0x1,0x5,0x2,0x4,0x6,0xF,0x0,0xB,
- 0xE,0x9,0xB,0x2,0x5,0xF,0x7,0x1,0x0,0xD,0xC,0x6,0xA,0x4,0x3,0x8,
- 0x3,0xE,0x5,0x9,0x6,0x8,0x0,0xD,0xA,0xB,0x7,0xC,0x2,0x1,0xF,0x4,
- 0x8,0xF,0x6,0xB,0x1,0x9,0xC,0x5,0xD,0x3,0x7,0xA,0x0,0xE,0x2,0x4,
- 0x9,0xB,0xC,0x0,0x3,0x6,0x7,0x5,0x4,0x8,0xE,0xF,0x1,0xA,0x2,0xD,
- 0xC,0x6,0x5,0x2,0xB,0x0,0x9,0xD,0x3,0xE,0x7,0xA,0xF,0x4,0x1,0x8
- };
-
- private static byte[] ESbox_A = {
- 0x9,0x6,0x3,0x2,0x8,0xB,0x1,0x7,0xA,0x4,0xE,0xF,0xC,0x0,0xD,0x5,
- 0x3,0x7,0xE,0x9,0x8,0xA,0xF,0x0,0x5,0x2,0x6,0xC,0xB,0x4,0xD,0x1,
- 0xE,0x4,0x6,0x2,0xB,0x3,0xD,0x8,0xC,0xF,0x5,0xA,0x0,0x7,0x1,0x9,
- 0xE,0x7,0xA,0xC,0xD,0x1,0x3,0x9,0x0,0x2,0xB,0x4,0xF,0x8,0x5,0x6,
- 0xB,0x5,0x1,0x9,0x8,0xD,0xF,0x0,0xE,0x4,0x2,0x3,0xC,0x7,0xA,0x6,
- 0x3,0xA,0xD,0xC,0x1,0x2,0x0,0xB,0x7,0x5,0x9,0x4,0x8,0xF,0xE,0x6,
- 0x1,0xD,0x2,0x9,0x7,0xA,0x6,0x0,0x8,0xC,0x4,0x5,0xF,0x3,0xB,0xE,
- 0xB,0xA,0xF,0x5,0x0,0xC,0xE,0x8,0x6,0x2,0x3,0x9,0x1,0x7,0xD,0x4
- };
-
- private static byte[] ESbox_B = {
- 0x8,0x4,0xB,0x1,0x3,0x5,0x0,0x9,0x2,0xE,0xA,0xC,0xD,0x6,0x7,0xF,
- 0x0,0x1,0x2,0xA,0x4,0xD,0x5,0xC,0x9,0x7,0x3,0xF,0xB,0x8,0x6,0xE,
- 0xE,0xC,0x0,0xA,0x9,0x2,0xD,0xB,0x7,0x5,0x8,0xF,0x3,0x6,0x1,0x4,
- 0x7,0x5,0x0,0xD,0xB,0x6,0x1,0x2,0x3,0xA,0xC,0xF,0x4,0xE,0x9,0x8,
- 0x2,0x7,0xC,0xF,0x9,0x5,0xA,0xB,0x1,0x4,0x0,0xD,0x6,0x8,0xE,0x3,
- 0x8,0x3,0x2,0x6,0x4,0xD,0xE,0xB,0xC,0x1,0x7,0xF,0xA,0x0,0x9,0x5,
- 0x5,0x2,0xA,0xB,0x9,0x1,0xC,0x3,0x7,0x4,0xD,0x0,0x6,0xF,0x8,0xE,
- 0x0,0x4,0xB,0xE,0x8,0x3,0x7,0x1,0xA,0x2,0x9,0x6,0xF,0xD,0x5,0xC
- };
-
- private static byte[] ESbox_C = {
- 0x1,0xB,0xC,0x2,0x9,0xD,0x0,0xF,0x4,0x5,0x8,0xE,0xA,0x7,0x6,0x3,
- 0x0,0x1,0x7,0xD,0xB,0x4,0x5,0x2,0x8,0xE,0xF,0xC,0x9,0xA,0x6,0x3,
- 0x8,0x2,0x5,0x0,0x4,0x9,0xF,0xA,0x3,0x7,0xC,0xD,0x6,0xE,0x1,0xB,
- 0x3,0x6,0x0,0x1,0x5,0xD,0xA,0x8,0xB,0x2,0x9,0x7,0xE,0xF,0xC,0x4,
- 0x8,0xD,0xB,0x0,0x4,0x5,0x1,0x2,0x9,0x3,0xC,0xE,0x6,0xF,0xA,0x7,
- 0xC,0x9,0xB,0x1,0x8,0xE,0x2,0x4,0x7,0x3,0x6,0x5,0xA,0x0,0xF,0xD,
- 0xA,0x9,0x6,0x8,0xD,0xE,0x2,0x0,0xF,0x3,0x5,0xB,0x4,0x1,0xC,0x7,
- 0x7,0x4,0x0,0x5,0xA,0x2,0xF,0xE,0xC,0x6,0x1,0xB,0xD,0x9,0x3,0x8
- };
-
- private static byte[] ESbox_D = {
- 0xF,0xC,0x2,0xA,0x6,0x4,0x5,0x0,0x7,0x9,0xE,0xD,0x1,0xB,0x8,0x3,
- 0xB,0x6,0x3,0x4,0xC,0xF,0xE,0x2,0x7,0xD,0x8,0x0,0x5,0xA,0x9,0x1,
- 0x1,0xC,0xB,0x0,0xF,0xE,0x6,0x5,0xA,0xD,0x4,0x8,0x9,0x3,0x7,0x2,
- 0x1,0x5,0xE,0xC,0xA,0x7,0x0,0xD,0x6,0x2,0xB,0x4,0x9,0x3,0xF,0x8,
- 0x0,0xC,0x8,0x9,0xD,0x2,0xA,0xB,0x7,0x3,0x6,0x5,0x4,0xE,0xF,0x1,
- 0x8,0x0,0xF,0x3,0x2,0x5,0xE,0xB,0x1,0xA,0x4,0x7,0xC,0x9,0xD,0x6,
- 0x3,0x0,0x6,0xF,0x1,0xE,0x9,0x2,0xD,0x8,0xC,0x4,0xB,0xA,0x5,0x7,
- 0x1,0xA,0x6,0x8,0xF,0xB,0x0,0x4,0xC,0x3,0x5,0x9,0x7,0xD,0x2,0xE
- };
-
- //S-box for digest
- private static byte DSbox_Test[] = {
- 0x4,0xA,0x9,0x2,0xD,0x8,0x0,0xE,0x6,0xB,0x1,0xC,0x7,0xF,0x5,0x3,
- 0xE,0xB,0x4,0xC,0x6,0xD,0xF,0xA,0x2,0x3,0x8,0x1,0x0,0x7,0x5,0x9,
- 0x5,0x8,0x1,0xD,0xA,0x3,0x4,0x2,0xE,0xF,0xC,0x7,0x6,0x0,0x9,0xB,
- 0x7,0xD,0xA,0x1,0x0,0x8,0x9,0xF,0xE,0x4,0x6,0xC,0xB,0x2,0x5,0x3,
- 0x6,0xC,0x7,0x1,0x5,0xF,0xD,0x8,0x4,0xA,0x9,0xE,0x0,0x3,0xB,0x2,
- 0x4,0xB,0xA,0x0,0x7,0x2,0x1,0xD,0x3,0x6,0x8,0x5,0x9,0xC,0xF,0xE,
- 0xD,0xB,0x4,0x1,0x3,0xF,0x5,0x9,0x0,0xA,0xE,0x7,0x6,0x8,0x2,0xC,
- 0x1,0xF,0xD,0x0,0x5,0x7,0xA,0x4,0x9,0x2,0x3,0xE,0x6,0xB,0x8,0xC
- };
-
- private static byte DSbox_A[] = {
- 0xA,0x4,0x5,0x6,0x8,0x1,0x3,0x7,0xD,0xC,0xE,0x0,0x9,0x2,0xB,0xF,
- 0x5,0xF,0x4,0x0,0x2,0xD,0xB,0x9,0x1,0x7,0x6,0x3,0xC,0xE,0xA,0x8,
- 0x7,0xF,0xC,0xE,0x9,0x4,0x1,0x0,0x3,0xB,0x5,0x2,0x6,0xA,0x8,0xD,
- 0x4,0xA,0x7,0xC,0x0,0xF,0x2,0x8,0xE,0x1,0x6,0x5,0xD,0xB,0x9,0x3,
- 0x7,0x6,0x4,0xB,0x9,0xC,0x2,0xA,0x1,0x8,0x0,0xE,0xF,0xD,0x3,0x5,
- 0x7,0x6,0x2,0x4,0xD,0x9,0xF,0x0,0xA,0x1,0x5,0xB,0x8,0xE,0xC,0x3,
- 0xD,0xE,0x4,0x1,0x7,0x0,0x5,0xA,0x3,0xC,0x8,0xF,0x6,0x2,0x9,0xB,
- 0x1,0x3,0xA,0x9,0x5,0xB,0x4,0xF,0x8,0x6,0x7,0xE,0xD,0x0,0x2,0xC
- };
-
- //
- // pre-defined sbox table
- //
- private static Hashtable sBoxes = new Hashtable();
-
- static
- {
- addSBox("Default", Sbox_Default);
- addSBox("E-TEST", ESbox_Test);
- addSBox("E-A", ESbox_A);
- addSBox("E-B", ESbox_B);
- addSBox("E-C", ESbox_C);
- addSBox("E-D", ESbox_D);
- addSBox("D-TEST", DSbox_Test);
- addSBox("D-A", DSbox_A);
- }
-
- private static void addSBox(String sBoxName, byte[] sBox)
- {
- sBoxes.put(Strings.toUpperCase(sBoxName), sBox);
- }
-
- /**
- * standard constructor.
- */
- public GOST28147Engine()
- {
- }
-
- /**
- * initialise an GOST28147 cipher.
- *
- * @param forEncryption whether or not we are for encryption.
- * @param params the parameters required to set up the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean forEncryption,
- CipherParameters params)
- {
- if (params instanceof ParametersWithSBox)
- {
- ParametersWithSBox param = (ParametersWithSBox)params;
-
- //
- // Set the S-Box
- //
- byte[] sBox = param.getSBox();
- if (sBox.length != Sbox_Default.length)
- {
- throw new IllegalArgumentException("invalid S-box passed to GOST28147 init");
- }
- this.S = Arrays.clone(sBox);
-
- //
- // set key if there is one
- //
- if (param.getParameters() != null)
- {
- workingKey = generateWorkingKey(forEncryption,
- ((KeyParameter)param.getParameters()).getKey());
- }
- }
- else if (params instanceof KeyParameter)
- {
- workingKey = generateWorkingKey(forEncryption,
- ((KeyParameter)params).getKey());
- }
- else if (params != null)
- {
- throw new IllegalArgumentException("invalid parameter passed to GOST28147 init - " + params.getClass().getName());
- }
- }
-
- public String getAlgorithmName()
- {
- return "GOST28147";
- }
-
- public int getBlockSize()
- {
- return BLOCK_SIZE;
- }
-
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- if (workingKey == null)
- {
- throw new IllegalStateException("GOST28147 engine not initialised");
- }
-
- if ((inOff + BLOCK_SIZE) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + BLOCK_SIZE) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- GOST28147Func(workingKey, in, inOff, out, outOff);
-
- return BLOCK_SIZE;
- }
-
- public void reset()
- {
- }
-
- private int[] generateWorkingKey(
- boolean forEncryption,
- byte[] userKey)
- {
- this.forEncryption = forEncryption;
-
- if (userKey.length != 32)
- {
- throw new IllegalArgumentException("Key length invalid. Key needs to be 32 byte - 256 bit!!!");
- }
-
- int key[] = new int[8];
- for(int i=0; i!=8; i++)
- {
- key[i] = bytesToint(userKey,i*4);
- }
-
- return key;
- }
-
- private int GOST28147_mainStep(int n1, int key)
- {
- int cm = (key + n1); // CM1
-
- // S-box replacing
-
- int om = S[ 0 + ((cm >> (0 * 4)) & 0xF)] << (0 * 4);
- om += S[ 16 + ((cm >> (1 * 4)) & 0xF)] << (1 * 4);
- om += S[ 32 + ((cm >> (2 * 4)) & 0xF)] << (2 * 4);
- om += S[ 48 + ((cm >> (3 * 4)) & 0xF)] << (3 * 4);
- om += S[ 64 + ((cm >> (4 * 4)) & 0xF)] << (4 * 4);
- om += S[ 80 + ((cm >> (5 * 4)) & 0xF)] << (5 * 4);
- om += S[ 96 + ((cm >> (6 * 4)) & 0xF)] << (6 * 4);
- om += S[112 + ((cm >> (7 * 4)) & 0xF)] << (7 * 4);
-
- return om << 11 | om >>> (32-11); // 11-leftshift
- }
-
- private void GOST28147Func(
- int[] workingKey,
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- int N1, N2, tmp; //tmp -> for saving N1
- N1 = bytesToint(in, inOff);
- N2 = bytesToint(in, inOff + 4);
-
- if (this.forEncryption)
- {
- for(int k = 0; k < 3; k++) // 1-24 steps
- {
- for(int j = 0; j < 8; j++)
- {
- tmp = N1;
- N1 = N2 ^ GOST28147_mainStep(N1, workingKey[j]); // CM2
- N2 = tmp;
- }
- }
- for(int j = 7; j > 0; j--) // 25-31 steps
- {
- tmp = N1;
- N1 = N2 ^ GOST28147_mainStep(N1, workingKey[j]); // CM2
- N2 = tmp;
- }
- }
- else //decrypt
- {
- for(int j = 0; j < 8; j++) // 1-8 steps
- {
- tmp = N1;
- N1 = N2 ^ GOST28147_mainStep(N1, workingKey[j]); // CM2
- N2 = tmp;
- }
- for(int k = 0; k < 3; k++) //9-31 steps
- {
- for(int j = 7; j >= 0; j--)
- {
- if ((k == 2) && (j==0))
- {
- break; // break 32 step
- }
- tmp = N1;
- N1 = N2 ^ GOST28147_mainStep(N1, workingKey[j]); // CM2
- N2 = tmp;
- }
- }
- }
-
- N2 = N2 ^ GOST28147_mainStep(N1, workingKey[0]); // 32 step (N1=N1)
-
- intTobytes(N1, out, outOff);
- intTobytes(N2, out, outOff + 4);
- }
-
- //array of bytes to type int
- private int bytesToint(
- byte[] in,
- int inOff)
- {
- return ((in[inOff + 3] << 24) & 0xff000000) + ((in[inOff + 2] << 16) & 0xff0000) +
- ((in[inOff + 1] << 8) & 0xff00) + (in[inOff] & 0xff);
- }
-
- //int to array of bytes
- private void intTobytes(
- int num,
- byte[] out,
- int outOff)
- {
- out[outOff + 3] = (byte)(num >>> 24);
- out[outOff + 2] = (byte)(num >>> 16);
- out[outOff + 1] = (byte)(num >>> 8);
- out[outOff] = (byte)num;
- }
-
- /**
- * Return the S-Box associated with SBoxName
- * @param sBoxName name of the S-Box
- * @return byte array representing the S-Box
- */
- public static byte[] getSBox(
- String sBoxName)
- {
- byte[] sBox = (byte[])sBoxes.get(Strings.toUpperCase(sBoxName));
-
- if (sBox == null)
- {
- throw new IllegalArgumentException("Unknown S-Box - possible types: "
- + "\"Default\", \"E-Test\", \"E-A\", \"E-B\", \"E-C\", \"E-D\", \"D-Test\", \"D-A\".");
- }
-
- return Arrays.clone(sBox);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/Grain128Engine.java b/core/src/main/java/org/bouncycastle/crypto/engines/Grain128Engine.java
deleted file mode 100644
index f5ecb75c..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/Grain128Engine.java
+++ /dev/null
@@ -1,304 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.OutputLengthException;
-import org.bouncycastle.crypto.StreamCipher;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-/**
- * Implementation of Martin Hell's, Thomas Johansson's and Willi Meier's stream
- * cipher, Grain-128.
- */
-public class Grain128Engine
- implements StreamCipher
-{
-
- /**
- * Constants
- */
- private static final int STATE_SIZE = 4;
-
- /**
- * Variables to hold the state of the engine during encryption and
- * decryption
- */
- private byte[] workingKey;
- private byte[] workingIV;
- private byte[] out;
- private int[] lfsr;
- private int[] nfsr;
- private int output;
- private int index = 4;
-
- private boolean initialised = false;
-
- public String getAlgorithmName()
- {
- return "Grain-128";
- }
-
- /**
- * Initialize a Grain-128 cipher.
- *
- * @param forEncryption Whether or not we are for encryption.
- * @param params The parameters required to set up the cipher.
- * @throws IllegalArgumentException If the params argument is inappropriate.
- */
- public void init(boolean forEncryption, CipherParameters params)
- throws IllegalArgumentException
- {
- /**
- * Grain encryption and decryption is completely symmetrical, so the
- * 'forEncryption' is irrelevant.
- */
- if (!(params instanceof ParametersWithIV))
- {
- throw new IllegalArgumentException(
- "Grain-128 Init parameters must include an IV");
- }
-
- ParametersWithIV ivParams = (ParametersWithIV)params;
-
- byte[] iv = ivParams.getIV();
-
- if (iv == null || iv.length != 12)
- {
- throw new IllegalArgumentException(
- "Grain-128 requires exactly 12 bytes of IV");
- }
-
- if (!(ivParams.getParameters() instanceof KeyParameter))
- {
- throw new IllegalArgumentException(
- "Grain-128 Init parameters must include a key");
- }
-
- KeyParameter key = (KeyParameter)ivParams.getParameters();
-
- /**
- * Initialize variables.
- */
- workingIV = new byte[key.getKey().length];
- workingKey = new byte[key.getKey().length];
- lfsr = new int[STATE_SIZE];
- nfsr = new int[STATE_SIZE];
- out = new byte[4];
-
- System.arraycopy(iv, 0, workingIV, 0, iv.length);
- System.arraycopy(key.getKey(), 0, workingKey, 0, key.getKey().length);
-
- reset();
- }
-
- /**
- * 256 clocks initialization phase.
- */
- private void initGrain()
- {
- for (int i = 0; i < 8; i++)
- {
- output = getOutput();
- nfsr = shift(nfsr, getOutputNFSR() ^ lfsr[0] ^ output);
- lfsr = shift(lfsr, getOutputLFSR() ^ output);
- }
- initialised = true;
- }
-
- /**
- * Get output from non-linear function g(x).
- *
- * @return Output from NFSR.
- */
- private int getOutputNFSR()
- {
- int b0 = nfsr[0];
- int b3 = nfsr[0] >>> 3 | nfsr[1] << 29;
- int b11 = nfsr[0] >>> 11 | nfsr[1] << 21;
- int b13 = nfsr[0] >>> 13 | nfsr[1] << 19;
- int b17 = nfsr[0] >>> 17 | nfsr[1] << 15;
- int b18 = nfsr[0] >>> 18 | nfsr[1] << 14;
- int b26 = nfsr[0] >>> 26 | nfsr[1] << 6;
- int b27 = nfsr[0] >>> 27 | nfsr[1] << 5;
- int b40 = nfsr[1] >>> 8 | nfsr[2] << 24;
- int b48 = nfsr[1] >>> 16 | nfsr[2] << 16;
- int b56 = nfsr[1] >>> 24 | nfsr[2] << 8;
- int b59 = nfsr[1] >>> 27 | nfsr[2] << 5;
- int b61 = nfsr[1] >>> 29 | nfsr[2] << 3;
- int b65 = nfsr[2] >>> 1 | nfsr[3] << 31;
- int b67 = nfsr[2] >>> 3 | nfsr[3] << 29;
- int b68 = nfsr[2] >>> 4 | nfsr[3] << 28;
- int b84 = nfsr[2] >>> 20 | nfsr[3] << 12;
- int b91 = nfsr[2] >>> 27 | nfsr[3] << 5;
- int b96 = nfsr[3];
-
- return b0 ^ b26 ^ b56 ^ b91 ^ b96 ^ b3 & b67 ^ b11 & b13 ^ b17 & b18
- ^ b27 & b59 ^ b40 & b48 ^ b61 & b65 ^ b68 & b84;
- }
-
- /**
- * Get output from linear function f(x).
- *
- * @return Output from LFSR.
- */
- private int getOutputLFSR()
- {
- int s0 = lfsr[0];
- int s7 = lfsr[0] >>> 7 | lfsr[1] << 25;
- int s38 = lfsr[1] >>> 6 | lfsr[2] << 26;
- int s70 = lfsr[2] >>> 6 | lfsr[3] << 26;
- int s81 = lfsr[2] >>> 17 | lfsr[3] << 15;
- int s96 = lfsr[3];
-
- return s0 ^ s7 ^ s38 ^ s70 ^ s81 ^ s96;
- }
-
- /**
- * Get output from output function h(x).
- *
- * @return Output from h(x).
- */
- private int getOutput()
- {
- int b2 = nfsr[0] >>> 2 | nfsr[1] << 30;
- int b12 = nfsr[0] >>> 12 | nfsr[1] << 20;
- int b15 = nfsr[0] >>> 15 | nfsr[1] << 17;
- int b36 = nfsr[1] >>> 4 | nfsr[2] << 28;
- int b45 = nfsr[1] >>> 13 | nfsr[2] << 19;
- int b64 = nfsr[2];
- int b73 = nfsr[2] >>> 9 | nfsr[3] << 23;
- int b89 = nfsr[2] >>> 25 | nfsr[3] << 7;
- int b95 = nfsr[2] >>> 31 | nfsr[3] << 1;
- int s8 = lfsr[0] >>> 8 | lfsr[1] << 24;
- int s13 = lfsr[0] >>> 13 | lfsr[1] << 19;
- int s20 = lfsr[0] >>> 20 | lfsr[1] << 12;
- int s42 = lfsr[1] >>> 10 | lfsr[2] << 22;
- int s60 = lfsr[1] >>> 28 | lfsr[2] << 4;
- int s79 = lfsr[2] >>> 15 | lfsr[3] << 17;
- int s93 = lfsr[2] >>> 29 | lfsr[3] << 3;
- int s95 = lfsr[2] >>> 31 | lfsr[3] << 1;
-
- return b12 & s8 ^ s13 & s20 ^ b95 & s42 ^ s60 & s79 ^ b12 & b95 & s95 ^ s93
- ^ b2 ^ b15 ^ b36 ^ b45 ^ b64 ^ b73 ^ b89;
- }
-
- /**
- * Shift array 32 bits and add val to index.length - 1.
- *
- * @param array The array to shift.
- * @param val The value to shift in.
- * @return The shifted array with val added to index.length - 1.
- */
- private int[] shift(int[] array, int val)
- {
- array[0] = array[1];
- array[1] = array[2];
- array[2] = array[3];
- array[3] = val;
-
- return array;
- }
-
- /**
- * Set keys, reset cipher.
- *
- * @param keyBytes The key.
- * @param ivBytes The IV.
- */
- private void setKey(byte[] keyBytes, byte[] ivBytes)
- {
- ivBytes[12] = (byte)0xFF;
- ivBytes[13] = (byte)0xFF;
- ivBytes[14] = (byte)0xFF;
- ivBytes[15] = (byte)0xFF;
- workingKey = keyBytes;
- workingIV = ivBytes;
-
- /**
- * Load NFSR and LFSR
- */
- int j = 0;
- for (int i = 0; i < nfsr.length; i++)
- {
- nfsr[i] = ((workingKey[j + 3]) << 24) | ((workingKey[j + 2]) << 16)
- & 0x00FF0000 | ((workingKey[j + 1]) << 8) & 0x0000FF00
- | ((workingKey[j]) & 0x000000FF);
-
- lfsr[i] = ((workingIV[j + 3]) << 24) | ((workingIV[j + 2]) << 16)
- & 0x00FF0000 | ((workingIV[j + 1]) << 8) & 0x0000FF00
- | ((workingIV[j]) & 0x000000FF);
- j += 4;
- }
- }
-
- public int processBytes(byte[] in, int inOff, int len, byte[] out,
- int outOff)
- throws DataLengthException
- {
- if (!initialised)
- {
- throw new IllegalStateException(getAlgorithmName()
- + " not initialised");
- }
-
- if ((inOff + len) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + len) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- for (int i = 0; i < len; i++)
- {
- out[outOff + i] = (byte)(in[inOff + i] ^ getKeyStream());
- }
-
- return len;
- }
-
- public void reset()
- {
- index = 4;
- setKey(workingKey, workingIV);
- initGrain();
- }
-
- /**
- * Run Grain one round(i.e. 32 bits).
- */
- private void oneRound()
- {
- output = getOutput();
- out[0] = (byte)output;
- out[1] = (byte)(output >> 8);
- out[2] = (byte)(output >> 16);
- out[3] = (byte)(output >> 24);
-
- nfsr = shift(nfsr, getOutputNFSR() ^ lfsr[0]);
- lfsr = shift(lfsr, getOutputLFSR());
- }
-
- public byte returnByte(byte in)
- {
- if (!initialised)
- {
- throw new IllegalStateException(getAlgorithmName()
- + " not initialised");
- }
- return (byte)(in ^ getKeyStream());
- }
-
- private byte getKeyStream()
- {
- if (index > 3)
- {
- oneRound();
- index = 0;
- }
- return out[index++];
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/Grainv1Engine.java b/core/src/main/java/org/bouncycastle/crypto/engines/Grainv1Engine.java
deleted file mode 100644
index 77f52d1c..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/Grainv1Engine.java
+++ /dev/null
@@ -1,290 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.OutputLengthException;
-import org.bouncycastle.crypto.StreamCipher;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-/**
- * Implementation of Martin Hell's, Thomas Johansson's and Willi Meier's stream
- * cipher, Grain v1.
- */
-public class Grainv1Engine
- implements StreamCipher
-{
-
- /**
- * Constants
- */
- private static final int STATE_SIZE = 5;
-
- /**
- * Variables to hold the state of the engine during encryption and
- * decryption
- */
- private byte[] workingKey;
- private byte[] workingIV;
- private byte[] out;
- private int[] lfsr;
- private int[] nfsr;
- private int output;
- private int index = 2;
-
- private boolean initialised = false;
-
- public String getAlgorithmName()
- {
- return "Grain v1";
- }
-
- /**
- * Initialize a Grain v1 cipher.
- *
- * @param forEncryption Whether or not we are for encryption.
- * @param params The parameters required to set up the cipher.
- * @throws IllegalArgumentException If the params argument is inappropriate.
- */
- public void init(boolean forEncryption, CipherParameters params)
- throws IllegalArgumentException
- {
- /**
- * Grain encryption and decryption is completely symmetrical, so the
- * 'forEncryption' is irrelevant.
- */
- if (!(params instanceof ParametersWithIV))
- {
- throw new IllegalArgumentException(
- "Grain v1 Init parameters must include an IV");
- }
-
- ParametersWithIV ivParams = (ParametersWithIV)params;
-
- byte[] iv = ivParams.getIV();
-
- if (iv == null || iv.length != 8)
- {
- throw new IllegalArgumentException(
- "Grain v1 requires exactly 8 bytes of IV");
- }
-
- if (!(ivParams.getParameters() instanceof KeyParameter))
- {
- throw new IllegalArgumentException(
- "Grain v1 Init parameters must include a key");
- }
-
- KeyParameter key = (KeyParameter)ivParams.getParameters();
-
- /**
- * Initialize variables.
- */
- workingIV = new byte[key.getKey().length];
- workingKey = new byte[key.getKey().length];
- lfsr = new int[STATE_SIZE];
- nfsr = new int[STATE_SIZE];
- out = new byte[2];
-
- System.arraycopy(iv, 0, workingIV, 0, iv.length);
- System.arraycopy(key.getKey(), 0, workingKey, 0, key.getKey().length);
-
- reset();
- }
-
- /**
- * 160 clocks initialization phase.
- */
- private void initGrain()
- {
- for (int i = 0; i < 10; i++)
- {
- output = getOutput();
- nfsr = shift(nfsr, getOutputNFSR() ^ lfsr[0] ^ output);
- lfsr = shift(lfsr, getOutputLFSR() ^ output);
- }
- initialised = true;
- }
-
- /**
- * Get output from non-linear function g(x).
- *
- * @return Output from NFSR.
- */
- private int getOutputNFSR()
- {
- int b0 = nfsr[0];
- int b9 = nfsr[0] >>> 9 | nfsr[1] << 7;
- int b14 = nfsr[0] >>> 14 | nfsr[1] << 2;
- int b15 = nfsr[0] >>> 15 | nfsr[1] << 1;
- int b21 = nfsr[1] >>> 5 | nfsr[2] << 11;
- int b28 = nfsr[1] >>> 12 | nfsr[2] << 4;
- int b33 = nfsr[2] >>> 1 | nfsr[3] << 15;
- int b37 = nfsr[2] >>> 5 | nfsr[3] << 11;
- int b45 = nfsr[2] >>> 13 | nfsr[3] << 3;
- int b52 = nfsr[3] >>> 4 | nfsr[4] << 12;
- int b60 = nfsr[3] >>> 12 | nfsr[4] << 4;
- int b62 = nfsr[3] >>> 14 | nfsr[4] << 2;
- int b63 = nfsr[3] >>> 15 | nfsr[4] << 1;
-
- return (b62 ^ b60 ^ b52 ^ b45 ^ b37 ^ b33 ^ b28 ^ b21 ^ b14
- ^ b9 ^ b0 ^ b63 & b60 ^ b37 & b33 ^ b15 & b9 ^ b60 & b52 & b45
- ^ b33 & b28 & b21 ^ b63 & b45 & b28 & b9 ^ b60 & b52 & b37
- & b33 ^ b63 & b60 & b21 & b15 ^ b63 & b60 & b52 & b45 & b37
- ^ b33 & b28 & b21 & b15 & b9 ^ b52 & b45 & b37 & b33 & b28
- & b21) & 0x0000FFFF;
- }
-
- /**
- * Get output from linear function f(x).
- *
- * @return Output from LFSR.
- */
- private int getOutputLFSR()
- {
- int s0 = lfsr[0];
- int s13 = lfsr[0] >>> 13 | lfsr[1] << 3;
- int s23 = lfsr[1] >>> 7 | lfsr[2] << 9;
- int s38 = lfsr[2] >>> 6 | lfsr[3] << 10;
- int s51 = lfsr[3] >>> 3 | lfsr[4] << 13;
- int s62 = lfsr[3] >>> 14 | lfsr[4] << 2;
-
- return (s0 ^ s13 ^ s23 ^ s38 ^ s51 ^ s62) & 0x0000FFFF;
- }
-
- /**
- * Get output from output function h(x).
- *
- * @return Output from h(x).
- */
- private int getOutput()
- {
- int b1 = nfsr[0] >>> 1 | nfsr[1] << 15;
- int b2 = nfsr[0] >>> 2 | nfsr[1] << 14;
- int b4 = nfsr[0] >>> 4 | nfsr[1] << 12;
- int b10 = nfsr[0] >>> 10 | nfsr[1] << 6;
- int b31 = nfsr[1] >>> 15 | nfsr[2] << 1;
- int b43 = nfsr[2] >>> 11 | nfsr[3] << 5;
- int b56 = nfsr[3] >>> 8 | nfsr[4] << 8;
- int b63 = nfsr[3] >>> 15 | nfsr[4] << 1;
- int s3 = lfsr[0] >>> 3 | lfsr[1] << 13;
- int s25 = lfsr[1] >>> 9 | lfsr[2] << 7;
- int s46 = lfsr[2] >>> 14 | lfsr[3] << 2;
- int s64 = lfsr[4];
-
- return (s25 ^ b63 ^ s3 & s64 ^ s46 & s64 ^ s64 & b63 ^ s3
- & s25 & s46 ^ s3 & s46 & s64 ^ s3 & s46 & b63 ^ s25 & s46 & b63 ^ s46
- & s64 & b63 ^ b1 ^ b2 ^ b4 ^ b10 ^ b31 ^ b43 ^ b56) & 0x0000FFFF;
- }
-
- /**
- * Shift array 16 bits and add val to index.length - 1.
- *
- * @param array The array to shift.
- * @param val The value to shift in.
- * @return The shifted array with val added to index.length - 1.
- */
- private int[] shift(int[] array, int val)
- {
- array[0] = array[1];
- array[1] = array[2];
- array[2] = array[3];
- array[3] = array[4];
- array[4] = val;
-
- return array;
- }
-
- /**
- * Set keys, reset cipher.
- *
- * @param keyBytes The key.
- * @param ivBytes The IV.
- */
- private void setKey(byte[] keyBytes, byte[] ivBytes)
- {
- ivBytes[8] = (byte)0xFF;
- ivBytes[9] = (byte)0xFF;
- workingKey = keyBytes;
- workingIV = ivBytes;
-
- /**
- * Load NFSR and LFSR
- */
- int j = 0;
- for (int i = 0; i < nfsr.length; i++)
- {
- nfsr[i] = (workingKey[j + 1] << 8 | workingKey[j] & 0xFF) & 0x0000FFFF;
- lfsr[i] = (workingIV[j + 1] << 8 | workingIV[j] & 0xFF) & 0x0000FFFF;
- j += 2;
- }
- }
-
- public int processBytes(byte[] in, int inOff, int len, byte[] out,
- int outOff)
- throws DataLengthException
- {
- if (!initialised)
- {
- throw new IllegalStateException(getAlgorithmName()
- + " not initialised");
- }
-
- if ((inOff + len) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + len) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- for (int i = 0; i < len; i++)
- {
- out[outOff + i] = (byte)(in[inOff + i] ^ getKeyStream());
- }
-
- return len;
- }
-
- public void reset()
- {
- index = 2;
- setKey(workingKey, workingIV);
- initGrain();
- }
-
- /**
- * Run Grain one round(i.e. 16 bits).
- */
- private void oneRound()
- {
- output = getOutput();
- out[0] = (byte)output;
- out[1] = (byte)(output >> 8);
-
- nfsr = shift(nfsr, getOutputNFSR() ^ lfsr[0]);
- lfsr = shift(lfsr, getOutputLFSR());
- }
-
- public byte returnByte(byte in)
- {
- if (!initialised)
- {
- throw new IllegalStateException(getAlgorithmName()
- + " not initialised");
- }
- return (byte)(in ^ getKeyStream());
- }
-
- private byte getKeyStream()
- {
- if (index > 1)
- {
- oneRound();
- index = 0;
- }
- return out[index++];
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/HC128Engine.java b/core/src/main/java/org/bouncycastle/crypto/engines/HC128Engine.java
deleted file mode 100644
index 7d18d623..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/HC128Engine.java
+++ /dev/null
@@ -1,259 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.OutputLengthException;
-import org.bouncycastle.crypto.StreamCipher;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-/**
- * HC-128 is a software-efficient stream cipher created by Hongjun Wu. It
- * generates keystream from a 128-bit secret key and a 128-bit initialization
- * vector.
- * <p>
- * http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc128_p3.pdf
- * </p><p>
- * It is a third phase candidate in the eStream contest, and is patent-free.
- * No attacks are known as of today (April 2007). See
- *
- * http://www.ecrypt.eu.org/stream/hcp3.html
- * </p>
- */
-public class HC128Engine
- implements StreamCipher
-{
- private int[] p = new int[512];
- private int[] q = new int[512];
- private int cnt = 0;
-
- private static int f1(int x)
- {
- return rotateRight(x, 7) ^ rotateRight(x, 18)
- ^ (x >>> 3);
- }
-
- private static int f2(int x)
- {
- return rotateRight(x, 17) ^ rotateRight(x, 19)
- ^ (x >>> 10);
- }
-
- private int g1(int x, int y, int z)
- {
- return (rotateRight(x, 10) ^ rotateRight(z, 23))
- + rotateRight(y, 8);
- }
-
- private int g2(int x, int y, int z)
- {
- return (rotateLeft(x, 10) ^ rotateLeft(z, 23)) + rotateLeft(y, 8);
- }
-
- private static int rotateLeft(
- int x,
- int bits)
- {
- return (x << bits) | (x >>> -bits);
- }
-
- private static int rotateRight(
- int x,
- int bits)
- {
- return (x >>> bits) | (x << -bits);
- }
-
- private int h1(int x)
- {
- return q[x & 0xFF] + q[((x >> 16) & 0xFF) + 256];
- }
-
- private int h2(int x)
- {
- return p[x & 0xFF] + p[((x >> 16) & 0xFF) + 256];
- }
-
- private static int mod1024(int x)
- {
- return x & 0x3FF;
- }
-
- private static int mod512(int x)
- {
- return x & 0x1FF;
- }
-
- private static int dim(int x, int y)
- {
- return mod512(x - y);
- }
-
- private int step()
- {
- int j = mod512(cnt);
- int ret;
- if (cnt < 512)
- {
- p[j] += g1(p[dim(j, 3)], p[dim(j, 10)], p[dim(j, 511)]);
- ret = h1(p[dim(j, 12)]) ^ p[j];
- }
- else
- {
- q[j] += g2(q[dim(j, 3)], q[dim(j, 10)], q[dim(j, 511)]);
- ret = h2(q[dim(j, 12)]) ^ q[j];
- }
- cnt = mod1024(cnt + 1);
- return ret;
- }
-
- private byte[] key, iv;
- private boolean initialised;
-
- private void init()
- {
- if (key.length != 16)
- {
- throw new java.lang.IllegalArgumentException(
- "The key must be 128 bits long");
- }
-
- idx = 0;
- cnt = 0;
-
- int[] w = new int[1280];
-
- for (int i = 0; i < 16; i++)
- {
- w[i >> 2] |= (key[i] & 0xff) << (8 * (i & 0x3));
- }
- System.arraycopy(w, 0, w, 4, 4);
-
- for (int i = 0; i < iv.length && i < 16; i++)
- {
- w[(i >> 2) + 8] |= (iv[i] & 0xff) << (8 * (i & 0x3));
- }
- System.arraycopy(w, 8, w, 12, 4);
-
- for (int i = 16; i < 1280; i++)
- {
- w[i] = f2(w[i - 2]) + w[i - 7] + f1(w[i - 15]) + w[i - 16] + i;
- }
-
- System.arraycopy(w, 256, p, 0, 512);
- System.arraycopy(w, 768, q, 0, 512);
-
- for (int i = 0; i < 512; i++)
- {
- p[i] = step();
- }
- for (int i = 0; i < 512; i++)
- {
- q[i] = step();
- }
-
- cnt = 0;
- }
-
- public String getAlgorithmName()
- {
- return "HC-128";
- }
-
- /**
- * Initialise a HC-128 cipher.
- *
- * @param forEncryption whether or not we are for encryption. Irrelevant, as
- * encryption and decryption are the same.
- * @param params the parameters required to set up the cipher.
- * @throws IllegalArgumentException if the params argument is
- * inappropriate (ie. the key is not 128 bit long).
- */
- public void init(boolean forEncryption, CipherParameters params)
- throws IllegalArgumentException
- {
- CipherParameters keyParam = params;
-
- if (params instanceof ParametersWithIV)
- {
- iv = ((ParametersWithIV)params).getIV();
- keyParam = ((ParametersWithIV)params).getParameters();
- }
- else
- {
- iv = new byte[0];
- }
-
- if (keyParam instanceof KeyParameter)
- {
- key = ((KeyParameter)keyParam).getKey();
- init();
- }
- else
- {
- throw new IllegalArgumentException(
- "Invalid parameter passed to HC128 init - "
- + params.getClass().getName());
- }
-
- initialised = true;
- }
-
- private byte[] buf = new byte[4];
- private int idx = 0;
-
- private byte getByte()
- {
- if (idx == 0)
- {
- int step = step();
- buf[0] = (byte)(step & 0xFF);
- step >>= 8;
- buf[1] = (byte)(step & 0xFF);
- step >>= 8;
- buf[2] = (byte)(step & 0xFF);
- step >>= 8;
- buf[3] = (byte)(step & 0xFF);
- }
- byte ret = buf[idx];
- idx = idx + 1 & 0x3;
- return ret;
- }
-
- public int processBytes(byte[] in, int inOff, int len, byte[] out,
- int outOff) throws DataLengthException
- {
- if (!initialised)
- {
- throw new IllegalStateException(getAlgorithmName()
- + " not initialised");
- }
-
- if ((inOff + len) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + len) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- for (int i = 0; i < len; i++)
- {
- out[outOff + i] = (byte)(in[inOff + i] ^ getByte());
- }
-
- return len;
- }
-
- public void reset()
- {
- init();
- }
-
- public byte returnByte(byte in)
- {
- return (byte)(in ^ getByte());
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/HC256Engine.java b/core/src/main/java/org/bouncycastle/crypto/engines/HC256Engine.java
deleted file mode 100644
index a74164ae..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/HC256Engine.java
+++ /dev/null
@@ -1,246 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.OutputLengthException;
-import org.bouncycastle.crypto.StreamCipher;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-/**
- * HC-256 is a software-efficient stream cipher created by Hongjun Wu. It
- * generates keystream from a 256-bit secret key and a 256-bit initialization
- * vector.
- * <p>
- * http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc256_p3.pdf
- * </p><p>
- * Its brother, HC-128, is a third phase candidate in the eStream contest.
- * The algorithm is patent-free. No attacks are known as of today (April 2007).
- * See
- *
- * http://www.ecrypt.eu.org/stream/hcp3.html
- * </p>
- */
-public class HC256Engine
- implements StreamCipher
-{
- private int[] p = new int[1024];
- private int[] q = new int[1024];
- private int cnt = 0;
-
- private int step()
- {
- int j = cnt & 0x3FF;
- int ret;
- if (cnt < 1024)
- {
- int x = p[(j - 3 & 0x3FF)];
- int y = p[(j - 1023 & 0x3FF)];
- p[j] += p[(j - 10 & 0x3FF)]
- + (rotateRight(x, 10) ^ rotateRight(y, 23))
- + q[((x ^ y) & 0x3FF)];
-
- x = p[(j - 12 & 0x3FF)];
- ret = (q[x & 0xFF] + q[((x >> 8) & 0xFF) + 256]
- + q[((x >> 16) & 0xFF) + 512] + q[((x >> 24) & 0xFF) + 768])
- ^ p[j];
- }
- else
- {
- int x = q[(j - 3 & 0x3FF)];
- int y = q[(j - 1023 & 0x3FF)];
- q[j] += q[(j - 10 & 0x3FF)]
- + (rotateRight(x, 10) ^ rotateRight(y, 23))
- + p[((x ^ y) & 0x3FF)];
-
- x = q[(j - 12 & 0x3FF)];
- ret = (p[x & 0xFF] + p[((x >> 8) & 0xFF) + 256]
- + p[((x >> 16) & 0xFF) + 512] + p[((x >> 24) & 0xFF) + 768])
- ^ q[j];
- }
- cnt = cnt + 1 & 0x7FF;
- return ret;
- }
-
- private byte[] key, iv;
- private boolean initialised;
-
- private void init()
- {
- if (key.length != 32 && key.length != 16)
- {
- throw new IllegalArgumentException(
- "The key must be 128/256 bits long");
- }
-
- if (iv.length < 16)
- {
- throw new IllegalArgumentException(
- "The IV must be at least 128 bits long");
- }
-
- if (key.length != 32)
- {
- byte[] k = new byte[32];
-
- System.arraycopy(key, 0, k, 0, key.length);
- System.arraycopy(key, 0, k, 16, key.length);
-
- key = k;
- }
-
- if (iv.length < 32)
- {
- byte[] newIV = new byte[32];
-
- System.arraycopy(iv, 0, newIV, 0, iv.length);
- System.arraycopy(iv, 0, newIV, iv.length, newIV.length - iv.length);
-
- iv = newIV;
- }
-
- idx = 0;
- cnt = 0;
-
- int[] w = new int[2560];
-
- for (int i = 0; i < 32; i++)
- {
- w[i >> 2] |= (key[i] & 0xff) << (8 * (i & 0x3));
- }
-
- for (int i = 0; i < 32; i++)
- {
- w[(i >> 2) + 8] |= (iv[i] & 0xff) << (8 * (i & 0x3));
- }
-
- for (int i = 16; i < 2560; i++)
- {
- int x = w[i - 2];
- int y = w[i - 15];
- w[i] = (rotateRight(x, 17) ^ rotateRight(x, 19) ^ (x >>> 10))
- + w[i - 7]
- + (rotateRight(y, 7) ^ rotateRight(y, 18) ^ (y >>> 3))
- + w[i - 16] + i;
- }
-
- System.arraycopy(w, 512, p, 0, 1024);
- System.arraycopy(w, 1536, q, 0, 1024);
-
- for (int i = 0; i < 4096; i++)
- {
- step();
- }
-
- cnt = 0;
- }
-
- public String getAlgorithmName()
- {
- return "HC-256";
- }
-
- /**
- * Initialise a HC-256 cipher.
- *
- * @param forEncryption whether or not we are for encryption. Irrelevant, as
- * encryption and decryption are the same.
- * @param params the parameters required to set up the cipher.
- * @throws IllegalArgumentException if the params argument is
- * inappropriate (ie. the key is not 256 bit long).
- */
- public void init(boolean forEncryption, CipherParameters params)
- throws IllegalArgumentException
- {
- CipherParameters keyParam = params;
-
- if (params instanceof ParametersWithIV)
- {
- iv = ((ParametersWithIV)params).getIV();
- keyParam = ((ParametersWithIV)params).getParameters();
- }
- else
- {
- iv = new byte[0];
- }
-
- if (keyParam instanceof KeyParameter)
- {
- key = ((KeyParameter)keyParam).getKey();
- init();
- }
- else
- {
- throw new IllegalArgumentException(
- "Invalid parameter passed to HC256 init - "
- + params.getClass().getName());
- }
-
- initialised = true;
- }
-
- private byte[] buf = new byte[4];
- private int idx = 0;
-
- private byte getByte()
- {
- if (idx == 0)
- {
- int step = step();
- buf[0] = (byte)(step & 0xFF);
- step >>= 8;
- buf[1] = (byte)(step & 0xFF);
- step >>= 8;
- buf[2] = (byte)(step & 0xFF);
- step >>= 8;
- buf[3] = (byte)(step & 0xFF);
- }
- byte ret = buf[idx];
- idx = idx + 1 & 0x3;
- return ret;
- }
-
- public int processBytes(byte[] in, int inOff, int len, byte[] out,
- int outOff) throws DataLengthException
- {
- if (!initialised)
- {
- throw new IllegalStateException(getAlgorithmName()
- + " not initialised");
- }
-
- if ((inOff + len) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + len) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- for (int i = 0; i < len; i++)
- {
- out[outOff + i] = (byte)(in[inOff + i] ^ getByte());
- }
-
- return len;
- }
-
- public void reset()
- {
- init();
- }
-
- public byte returnByte(byte in)
- {
- return (byte)(in ^ getByte());
- }
-
- private static int rotateRight(
- int x,
- int bits)
- {
- return (x >>> bits) | (x << -bits);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/IDEAEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/IDEAEngine.java
deleted file mode 100644
index 08cf738e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/IDEAEngine.java
+++ /dev/null
@@ -1,357 +0,0 @@
-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;
-
-/**
- * A class that provides a basic International Data Encryption Algorithm (IDEA) engine.
- * <p>
- * This implementation is based on the "HOWTO: INTERNATIONAL DATA ENCRYPTION ALGORITHM"
- * implementation summary by Fauzan Mirza (F.U.Mirza@sheffield.ac.uk). (barring 1 typo at the
- * end of the mulinv function!).
- * <p>
- * It can be found at ftp://ftp.funet.fi/pub/crypt/cryptography/symmetric/idea/
- * <p>
- * Note: This algorithm was patented in the USA, Japan and Europe. These patents expired in 2011/2012.
- */
-public class IDEAEngine
- implements BlockCipher
-{
- protected static final int BLOCK_SIZE = 8;
-
- private int[] workingKey = null;
-
- /**
- * standard constructor.
- */
- public IDEAEngine()
- {
- }
-
- /**
- * initialise an IDEA cipher.
- *
- * @param forEncryption whether or not we are for encryption.
- * @param params the parameters required to set up the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean forEncryption,
- CipherParameters params)
- {
- if (params instanceof KeyParameter)
- {
- workingKey = generateWorkingKey(forEncryption,
- ((KeyParameter)params).getKey());
- return;
- }
-
- throw new IllegalArgumentException("invalid parameter passed to IDEA init - " + params.getClass().getName());
- }
-
- public String getAlgorithmName()
- {
- return "IDEA";
- }
-
- public int getBlockSize()
- {
- return BLOCK_SIZE;
- }
-
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- if (workingKey == null)
- {
- throw new IllegalStateException("IDEA engine not initialised");
- }
-
- if ((inOff + BLOCK_SIZE) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + BLOCK_SIZE) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- ideaFunc(workingKey, in, inOff, out, outOff);
-
- return BLOCK_SIZE;
- }
-
- public void reset()
- {
- }
-
- private static final int MASK = 0xffff;
- private static final int BASE = 0x10001;
-
- private int bytesToWord(
- byte[] in,
- int inOff)
- {
- return ((in[inOff] << 8) & 0xff00) + (in[inOff + 1] & 0xff);
- }
-
- private void wordToBytes(
- int word,
- byte[] out,
- int outOff)
- {
- out[outOff] = (byte)(word >>> 8);
- out[outOff + 1] = (byte)word;
- }
-
- /**
- * return x = x * y where the multiplication is done modulo
- * 65537 (0x10001) (as defined in the IDEA specification) and
- * a zero input is taken to be 65536 (0x10000).
- *
- * @param x the x value
- * @param y the y value
- * @return x = x * y
- */
- private int mul(
- int x,
- int y)
- {
- if (x == 0)
- {
- x = (BASE - y);
- }
- else if (y == 0)
- {
- x = (BASE - x);
- }
- else
- {
- int p = x * y;
-
- y = p & MASK;
- x = p >>> 16;
- x = y - x + ((y < x) ? 1 : 0);
- }
-
- return x & MASK;
- }
-
- private void ideaFunc(
- int[] workingKey,
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- int x0, x1, x2, x3, t0, t1;
- int keyOff = 0;
-
- x0 = bytesToWord(in, inOff);
- x1 = bytesToWord(in, inOff + 2);
- x2 = bytesToWord(in, inOff + 4);
- x3 = bytesToWord(in, inOff + 6);
-
- for (int round = 0; round < 8; round++)
- {
- x0 = mul(x0, workingKey[keyOff++]);
- x1 += workingKey[keyOff++];
- x1 &= MASK;
- x2 += workingKey[keyOff++];
- x2 &= MASK;
- x3 = mul(x3, workingKey[keyOff++]);
-
- t0 = x1;
- t1 = x2;
- x2 ^= x0;
- x1 ^= x3;
-
- x2 = mul(x2, workingKey[keyOff++]);
- x1 += x2;
- x1 &= MASK;
-
- x1 = mul(x1, workingKey[keyOff++]);
- x2 += x1;
- x2 &= MASK;
-
- x0 ^= x1;
- x3 ^= x2;
- x1 ^= t1;
- x2 ^= t0;
- }
-
- wordToBytes(mul(x0, workingKey[keyOff++]), out, outOff);
- wordToBytes(x2 + workingKey[keyOff++], out, outOff + 2); /* NB: Order */
- wordToBytes(x1 + workingKey[keyOff++], out, outOff + 4);
- wordToBytes(mul(x3, workingKey[keyOff]), out, outOff + 6);
- }
-
- /**
- * The following function is used to expand the user key to the encryption
- * subkey. The first 16 bytes are the user key, and the rest of the subkey
- * is calculated by rotating the previous 16 bytes by 25 bits to the left,
- * and so on until the subkey is completed.
- */
- private int[] expandKey(
- byte[] uKey)
- {
- int[] key = new int[52];
-
- if (uKey.length < 16)
- {
- byte[] tmp = new byte[16];
-
- System.arraycopy(uKey, 0, tmp, tmp.length - uKey.length, uKey.length);
-
- uKey = tmp;
- }
-
- for (int i = 0; i < 8; i++)
- {
- key[i] = bytesToWord(uKey, i * 2);
- }
-
- for (int i = 8; i < 52; i++)
- {
- if ((i & 7) < 6)
- {
- key[i] = ((key[i - 7] & 127) << 9 | key[i - 6] >> 7) & MASK;
- }
- else if ((i & 7) == 6)
- {
- key[i] = ((key[i - 7] & 127) << 9 | key[i - 14] >> 7) & MASK;
- }
- else
- {
- key[i] = ((key[i - 15] & 127) << 9 | key[i - 14] >> 7) & MASK;
- }
- }
-
- return key;
- }
-
- /**
- * This function computes multiplicative inverse using Euclid's Greatest
- * Common Divisor algorithm. Zero and one are self inverse.
- * <p>
- * i.e. x * mulInv(x) == 1 (modulo BASE)
- */
- private int mulInv(
- int x)
- {
- int t0, t1, q, y;
-
- if (x < 2)
- {
- return x;
- }
-
- t0 = 1;
- t1 = BASE / x;
- y = BASE % x;
-
- while (y != 1)
- {
- q = x / y;
- x = x % y;
- t0 = (t0 + (t1 * q)) & MASK;
- if (x == 1)
- {
- return t0;
- }
- q = y / x;
- y = y % x;
- t1 = (t1 + (t0 * q)) & MASK;
- }
-
- return (1 - t1) & MASK;
- }
-
- /**
- * Return the additive inverse of x.
- * <p>
- * i.e. x + addInv(x) == 0
- */
- int addInv(
- int x)
- {
- return (0 - x) & MASK;
- }
-
- /**
- * The function to invert the encryption subkey to the decryption subkey.
- * It also involves the multiplicative inverse and the additive inverse functions.
- */
- private int[] invertKey(
- int[] inKey)
- {
- int t1, t2, t3, t4;
- int p = 52; /* We work backwards */
- int[] key = new int[52];
- int inOff = 0;
-
- t1 = mulInv(inKey[inOff++]);
- t2 = addInv(inKey[inOff++]);
- t3 = addInv(inKey[inOff++]);
- t4 = mulInv(inKey[inOff++]);
- key[--p] = t4;
- key[--p] = t3;
- key[--p] = t2;
- key[--p] = t1;
-
- for (int round = 1; round < 8; round++)
- {
- t1 = inKey[inOff++];
- t2 = inKey[inOff++];
- key[--p] = t2;
- key[--p] = t1;
-
- t1 = mulInv(inKey[inOff++]);
- t2 = addInv(inKey[inOff++]);
- t3 = addInv(inKey[inOff++]);
- t4 = mulInv(inKey[inOff++]);
- key[--p] = t4;
- key[--p] = t2; /* NB: Order */
- key[--p] = t3;
- key[--p] = t1;
- }
-
- t1 = inKey[inOff++];
- t2 = inKey[inOff++];
- key[--p] = t2;
- key[--p] = t1;
-
- t1 = mulInv(inKey[inOff++]);
- t2 = addInv(inKey[inOff++]);
- t3 = addInv(inKey[inOff++]);
- t4 = mulInv(inKey[inOff]);
- key[--p] = t4;
- key[--p] = t3;
- key[--p] = t2;
- key[--p] = t1;
-
- return key;
- }
-
- private int[] generateWorkingKey(
- boolean forEncryption,
- byte[] userKey)
- {
- if (forEncryption)
- {
- return expandKey(userKey);
- }
- else
- {
- return invertKey(expandKey(userKey));
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/IESEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/IESEngine.java
deleted file mode 100755
index 9914bd47..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/IESEngine.java
+++ /dev/null
@@ -1,438 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.BasicAgreement;
-import org.bouncycastle.crypto.BufferedBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DerivationFunction;
-import org.bouncycastle.crypto.EphemeralKeyPair;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.KeyParser;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.generators.EphemeralKeyPairGenerator;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.IESParameters;
-import org.bouncycastle.crypto.params.IESWithCipherParameters;
-import org.bouncycastle.crypto.params.KDFParameters;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.BigIntegers;
-import org.bouncycastle.util.Pack;
-
-/**
- * Support class for constructing integrated encryption ciphers
- * for doing basic message exchanges on top of key agreement ciphers.
- * Follows the description given in IEEE Std 1363a.
- */
-public class IESEngine
-{
- BasicAgreement agree;
- DerivationFunction kdf;
- Mac mac;
- BufferedBlockCipher cipher;
- byte[] macBuf;
-
- boolean forEncryption;
- CipherParameters privParam, pubParam;
- IESParameters param;
-
- byte[] V;
- private EphemeralKeyPairGenerator keyPairGenerator;
- private KeyParser keyParser;
- private byte[] IV;
-
- /**
- * set up for use with stream mode, where the key derivation function
- * is used to provide a stream of bytes to xor with the message.
- *
- * @param agree the key agreement used as the basis for the encryption
- * @param kdf the key derivation function used for byte generation
- * @param mac the message authentication code generator for the message
- */
- public IESEngine(
- BasicAgreement agree,
- DerivationFunction kdf,
- Mac mac)
- {
- this.agree = agree;
- this.kdf = kdf;
- this.mac = mac;
- this.macBuf = new byte[mac.getMacSize()];
- this.cipher = null;
- }
-
-
- /**
- * set up for use in conjunction with a block cipher to handle the
- * message.
- *
- * @param agree the key agreement used as the basis for the encryption
- * @param kdf the key derivation function used for byte generation
- * @param mac the message authentication code generator for the message
- * @param cipher the cipher to used for encrypting the message
- */
- public IESEngine(
- BasicAgreement agree,
- DerivationFunction kdf,
- Mac mac,
- BufferedBlockCipher cipher)
- {
- this.agree = agree;
- this.kdf = kdf;
- this.mac = mac;
- this.macBuf = new byte[mac.getMacSize()];
- this.cipher = cipher;
- }
-
- /**
- * Initialise the encryptor.
- *
- * @param forEncryption whether or not this is encryption/decryption.
- * @param privParam our private key parameters
- * @param pubParam the recipient's/sender's public key parameters
- * @param params encoding and derivation parameters, may be wrapped to include an IV for an underlying block cipher.
- */
- public void init(
- boolean forEncryption,
- CipherParameters privParam,
- CipherParameters pubParam,
- CipherParameters params)
- {
- this.forEncryption = forEncryption;
- this.privParam = privParam;
- this.pubParam = pubParam;
- this.V = new byte[0];
-
- extractParams(params);
- }
-
-
- /**
- * Initialise the encryptor.
- *
- * @param publicKey the recipient's/sender's public key parameters
- * @param params encoding and derivation parameters, may be wrapped to include an IV for an underlying block cipher.
- * @param ephemeralKeyPairGenerator the ephemeral key pair generator to use.
- */
- public void init(AsymmetricKeyParameter publicKey, CipherParameters params, EphemeralKeyPairGenerator ephemeralKeyPairGenerator)
- {
- this.forEncryption = true;
- this.pubParam = publicKey;
- this.keyPairGenerator = ephemeralKeyPairGenerator;
-
- extractParams(params);
- }
-
- /**
- * Initialise the encryptor.
- *
- * @param privateKey the recipient's private key.
- * @param params encoding and derivation parameters, may be wrapped to include an IV for an underlying block cipher.
- * @param publicKeyParser the parser for reading the ephemeral public key.
- */
- public void init(AsymmetricKeyParameter privateKey, CipherParameters params, KeyParser publicKeyParser)
- {
- this.forEncryption = false;
- this.privParam = privateKey;
- this.keyParser = publicKeyParser;
-
- extractParams(params);
- }
-
- private void extractParams(CipherParameters params)
- {
- if (params instanceof ParametersWithIV)
- {
- this.IV = ((ParametersWithIV)params).getIV();
- this.param = (IESParameters)((ParametersWithIV)params).getParameters();
- }
- else
- {
- this.IV = null;
- this.param = (IESParameters)params;
- }
- }
-
- public BufferedBlockCipher getCipher()
- {
- return cipher;
- }
-
- public Mac getMac()
- {
- return mac;
- }
-
- private byte[] encryptBlock(
- byte[] in,
- int inOff,
- int inLen)
- throws InvalidCipherTextException
- {
- byte[] C = null, K = null, K1 = null, K2 = null;
- int len;
-
- if (cipher == null)
- {
- // Streaming mode.
- K1 = new byte[inLen];
- K2 = new byte[param.getMacKeySize() / 8];
- K = new byte[K1.length + K2.length];
-
- kdf.generateBytes(K, 0, K.length);
-
- if (V.length != 0)
- {
- System.arraycopy(K, 0, K2, 0, K2.length);
- System.arraycopy(K, K2.length, K1, 0, K1.length);
- }
- else
- {
- System.arraycopy(K, 0, K1, 0, K1.length);
- System.arraycopy(K, inLen, K2, 0, K2.length);
- }
-
- C = new byte[inLen];
-
- for (int i = 0; i != inLen; i++)
- {
- C[i] = (byte)(in[inOff + i] ^ K1[i]);
- }
- len = inLen;
- }
- else
- {
- // Block cipher mode.
- K1 = new byte[((IESWithCipherParameters)param).getCipherKeySize() / 8];
- K2 = new byte[param.getMacKeySize() / 8];
- K = new byte[K1.length + K2.length];
-
- kdf.generateBytes(K, 0, K.length);
- System.arraycopy(K, 0, K1, 0, K1.length);
- System.arraycopy(K, K1.length, K2, 0, K2.length);
-
- // If iv provided use it to initialise the cipher
- if (IV != null)
- {
- cipher.init(true, new ParametersWithIV(new KeyParameter(K1), IV));
- }
- else
- {
- cipher.init(true, new KeyParameter(K1));
- }
-
- C = new byte[cipher.getOutputSize(inLen)];
- len = cipher.processBytes(in, inOff, inLen, C, 0);
- len += cipher.doFinal(C, len);
- }
-
-
- // Convert the length of the encoding vector into a byte array.
- byte[] P2 = param.getEncodingV();
- byte[] L2 = new byte[4];
- if (V.length != 0 && P2 != null)
- {
- Pack.intToBigEndian(P2.length * 8, L2, 0);
- }
-
-
- // Apply the MAC.
- byte[] T = new byte[mac.getMacSize()];
-
- mac.init(new KeyParameter(K2));
- mac.update(C, 0, C.length);
- if (P2 != null)
- {
- mac.update(P2, 0, P2.length);
- }
- if (V.length != 0)
- {
- mac.update(L2, 0, L2.length);
- }
- mac.doFinal(T, 0);
-
-
- // Output the triple (V,C,T).
- byte[] Output = new byte[V.length + len + T.length];
- System.arraycopy(V, 0, Output, 0, V.length);
- System.arraycopy(C, 0, Output, V.length, len);
- System.arraycopy(T, 0, Output, V.length + len, T.length);
- return Output;
- }
-
- private byte[] decryptBlock(
- byte[] in_enc,
- int inOff,
- int inLen)
- throws InvalidCipherTextException
- {
- byte[] M = null, K = null, K1 = null, K2 = null;
- int len;
-
- // Ensure that the length of the input is greater than the MAC in bytes
- if (inLen <= (param.getMacKeySize() / 8))
- {
- throw new InvalidCipherTextException("Length of input must be greater than the MAC");
- }
-
- if (cipher == null)
- {
- // Streaming mode.
- K1 = new byte[inLen - V.length - mac.getMacSize()];
- K2 = new byte[param.getMacKeySize() / 8];
- K = new byte[K1.length + K2.length];
-
- kdf.generateBytes(K, 0, K.length);
-
- if (V.length != 0)
- {
- System.arraycopy(K, 0, K2, 0, K2.length);
- System.arraycopy(K, K2.length, K1, 0, K1.length);
- }
- else
- {
- System.arraycopy(K, 0, K1, 0, K1.length);
- System.arraycopy(K, K1.length, K2, 0, K2.length);
- }
-
- M = new byte[K1.length];
-
- for (int i = 0; i != K1.length; i++)
- {
- M[i] = (byte)(in_enc[inOff + V.length + i] ^ K1[i]);
- }
-
- len = K1.length;
- }
- else
- {
- // Block cipher mode.
- K1 = new byte[((IESWithCipherParameters)param).getCipherKeySize() / 8];
- K2 = new byte[param.getMacKeySize() / 8];
- K = new byte[K1.length + K2.length];
-
- kdf.generateBytes(K, 0, K.length);
- System.arraycopy(K, 0, K1, 0, K1.length);
- System.arraycopy(K, K1.length, K2, 0, K2.length);
-
- // If IV provide use it to initialize the cipher
- if (IV != null)
- {
- cipher.init(false, new ParametersWithIV(new KeyParameter(K1), IV));
- }
- else
- {
- cipher.init(false, new KeyParameter(K1));
- }
-
- M = new byte[cipher.getOutputSize(inLen - V.length - mac.getMacSize())];
- len = cipher.processBytes(in_enc, inOff + V.length, inLen - V.length - mac.getMacSize(), M, 0);
- len += cipher.doFinal(M, len);
- }
-
-
- // Convert the length of the encoding vector into a byte array.
- byte[] P2 = param.getEncodingV();
- byte[] L2 = new byte[4];
- if (V.length != 0 && P2 != null)
- {
- Pack.intToBigEndian(P2.length * 8, L2, 0);
- }
-
-
- // Verify the MAC.
- int end = inOff + inLen;
- byte[] T1 = Arrays.copyOfRange(in_enc, end - mac.getMacSize(), end);
-
- byte[] T2 = new byte[T1.length];
- mac.init(new KeyParameter(K2));
- mac.update(in_enc, inOff + V.length, inLen - V.length - T2.length);
-
- if (P2 != null)
- {
- mac.update(P2, 0, P2.length);
- }
- if (V.length != 0)
- {
- mac.update(L2, 0, L2.length);
- }
- mac.doFinal(T2, 0);
-
- if (!Arrays.constantTimeAreEqual(T1, T2))
- {
- throw new InvalidCipherTextException("Invalid MAC.");
- }
-
-
- // Output the message.
- return Arrays.copyOfRange(M, 0, len);
- }
-
-
- public byte[] processBlock(
- byte[] in,
- int inOff,
- int inLen)
- throws InvalidCipherTextException
- {
- if (forEncryption)
- {
- if (keyPairGenerator != null)
- {
- EphemeralKeyPair ephKeyPair = keyPairGenerator.generate();
-
- this.privParam = ephKeyPair.getKeyPair().getPrivate();
- this.V = ephKeyPair.getEncodedPublicKey();
- }
- }
- else
- {
- if (keyParser != null)
- {
- ByteArrayInputStream bIn = new ByteArrayInputStream(in, inOff, inLen);
-
- try
- {
- this.pubParam = keyParser.readKey(bIn);
- }
- catch (IOException e)
- {
- throw new InvalidCipherTextException("unable to recover ephemeral public key: " + e.getMessage(), e);
- }
-
- int encLength = (inLen - bIn.available());
- this.V = Arrays.copyOfRange(in, inOff, inOff + encLength);
- }
- }
-
- // Compute the common value and convert to byte array.
- agree.init(privParam);
- BigInteger z = agree.calculateAgreement(pubParam);
- byte[] Z = BigIntegers.asUnsignedByteArray(agree.getFieldSize(), z);
-
- // Create input to KDF.
- byte[] VZ;
- if (V.length != 0)
- {
- VZ = new byte[V.length + Z.length];
- System.arraycopy(V, 0, VZ, 0, V.length);
- System.arraycopy(Z, 0, VZ, V.length, Z.length);
- }
- else
- {
- VZ = Z;
- }
-
- // Initialise the KDF.
- KDFParameters kdfParam = new KDFParameters(VZ, param.getDerivationV());
- kdf.init(kdfParam);
-
- return forEncryption
- ? encryptBlock(in, inOff, inLen)
- : decryptBlock(in, inOff, inLen);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/ISAACEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/ISAACEngine.java
deleted file mode 100644
index d2dd2657..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/ISAACEngine.java
+++ /dev/null
@@ -1,221 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.OutputLengthException;
-import org.bouncycastle.crypto.StreamCipher;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Pack;
-
-/**
- * Implementation of Bob Jenkin's ISAAC (Indirection Shift Accumulate Add and Count).
- * see: http://www.burtleburtle.net/bob/rand/isaacafa.html
-*/
-public class ISAACEngine
- implements StreamCipher
-{
- // Constants
- private final int sizeL = 8,
- stateArraySize = sizeL<<5; // 256
-
- // Cipher's internal state
- private int[] engineState = null, // mm
- results = null; // randrsl
- private int a = 0, b = 0, c = 0;
-
- // Engine state
- private int index = 0;
- private byte[] keyStream = new byte[stateArraySize<<2], // results expanded into bytes
- workingKey = null;
- private boolean initialised = false;
-
- /**
- * initialise an ISAAC cipher.
- *
- * @param forEncryption whether or not we are for encryption.
- * @param params the parameters required to set up the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean forEncryption,
- CipherParameters params)
- {
- if (!(params instanceof KeyParameter))
- {
- throw new IllegalArgumentException("invalid parameter passed to ISAAC init - " + params.getClass().getName());
- }
- /*
- * ISAAC encryption and decryption is completely
- * symmetrical, so the 'forEncryption' is
- * irrelevant.
- */
- KeyParameter p = (KeyParameter)params;
- setKey(p.getKey());
-
- return;
- }
-
- public byte returnByte(byte in)
- {
- if (index == 0)
- {
- isaac();
- keyStream = Pack.intToBigEndian(results);
- }
- byte out = (byte)(keyStream[index]^in);
- index = (index + 1) & 1023;
-
- return out;
- }
-
- public int processBytes(
- byte[] in,
- int inOff,
- int len,
- byte[] out,
- int outOff)
- {
- if (!initialised)
- {
- throw new IllegalStateException(getAlgorithmName()+" not initialised");
- }
-
- if ((inOff + len) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + len) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- for (int i = 0; i < len; i++)
- {
- if (index == 0)
- {
- isaac();
- keyStream = Pack.intToBigEndian(results);
- }
- out[i+outOff] = (byte)(keyStream[index]^in[i+inOff]);
- index = (index + 1) & 1023;
- }
-
- return len;
- }
-
- public String getAlgorithmName()
- {
- return "ISAAC";
- }
-
- public void reset()
- {
- setKey(workingKey);
- }
-
- // Private implementation
- private void setKey(byte[] keyBytes)
- {
- workingKey = keyBytes;
-
- if (engineState == null)
- {
- engineState = new int[stateArraySize];
- }
-
- if (results == null)
- {
- results = new int[stateArraySize];
- }
-
- int i, j, k;
-
- // Reset state
- for (i = 0; i < stateArraySize; i++)
- {
- engineState[i] = results[i] = 0;
- }
- a = b = c = 0;
-
- // Reset index counter for output
- index = 0;
-
- // Convert the key bytes to ints and put them into results[] for initialization
- byte[] t = new byte[keyBytes.length + (keyBytes.length & 3)];
- System.arraycopy(keyBytes, 0, t, 0, keyBytes.length);
- for (i = 0; i < t.length; i+=4)
- {
- results[i >>> 2] = Pack.littleEndianToInt(t, i);
- }
-
- // It has begun?
- int[] abcdefgh = new int[sizeL];
-
- for (i = 0; i < sizeL; i++)
- {
- abcdefgh[i] = 0x9e3779b9; // Phi (golden ratio)
- }
-
- for (i = 0; i < 4; i++)
- {
- mix(abcdefgh);
- }
-
- for (i = 0; i < 2; i++)
- {
- for (j = 0; j < stateArraySize; j+=sizeL)
- {
- for (k = 0; k < sizeL; k++)
- {
- abcdefgh[k] += (i<1) ? results[j+k] : engineState[j+k];
- }
-
- mix(abcdefgh);
-
- for (k = 0; k < sizeL; k++)
- {
- engineState[j+k] = abcdefgh[k];
- }
- }
- }
-
- isaac();
-
- initialised = true;
- }
-
- private void isaac()
- {
- int i, x, y;
-
- b += ++c;
- for (i = 0; i < stateArraySize; i++)
- {
- x = engineState[i];
- switch (i & 3)
- {
- case 0: a ^= (a << 13); break;
- case 1: a ^= (a >>> 6); break;
- case 2: a ^= (a << 2); break;
- case 3: a ^= (a >>> 16); break;
- }
- a += engineState[(i+128) & 0xFF];
- engineState[i] = y = engineState[(x >>> 2) & 0xFF] + a + b;
- results[i] = b = engineState[(y >>> 10) & 0xFF] + x;
- }
- }
-
- private void mix(int[] x)
- {
- x[0]^=x[1]<< 11; x[3]+=x[0]; x[1]+=x[2];
- x[1]^=x[2]>>> 2; x[4]+=x[1]; x[2]+=x[3];
- x[2]^=x[3]<< 8; x[5]+=x[2]; x[3]+=x[4];
- x[3]^=x[4]>>>16; x[6]+=x[3]; x[4]+=x[5];
- x[4]^=x[5]<< 10; x[7]+=x[4]; x[5]+=x[6];
- x[5]^=x[6]>>> 4; x[0]+=x[5]; x[6]+=x[7];
- x[6]^=x[7]<< 8; x[1]+=x[6]; x[7]+=x[0];
- x[7]^=x[0]>>> 9; x[2]+=x[7]; x[0]+=x[1];
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/NaccacheSternEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/NaccacheSternEngine.java
deleted file mode 100644
index a5403fac..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/NaccacheSternEngine.java
+++ /dev/null
@@ -1,437 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import java.math.BigInteger;
-import java.util.Vector;
-import org.bouncycastle.util.Arrays;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.params.NaccacheSternKeyParameters;
-import org.bouncycastle.crypto.params.NaccacheSternPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-
-/**
- * NaccacheStern Engine. For details on this cipher, please see
- * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
- */
-public class NaccacheSternEngine
- implements AsymmetricBlockCipher
-{
- private boolean forEncryption;
-
- private NaccacheSternKeyParameters key;
-
- private Vector[] lookup = null;
-
- private boolean debug = false;
-
- private static BigInteger ZERO = BigInteger.valueOf(0);
- private static BigInteger ONE = BigInteger.valueOf(1);
-
- /**
- * Initializes this algorithm. Must be called before all other Functions.
- *
- * @see org.bouncycastle.crypto.AsymmetricBlockCipher#init(boolean,
- * org.bouncycastle.crypto.CipherParameters)
- */
- public void init(boolean forEncryption, CipherParameters param)
- {
- this.forEncryption = forEncryption;
-
- if (param instanceof ParametersWithRandom)
- {
- param = ((ParametersWithRandom) param).getParameters();
- }
-
- key = (NaccacheSternKeyParameters)param;
-
- // construct lookup table for faster decryption if necessary
- if (!this.forEncryption)
- {
- if (debug)
- {
- System.out.println("Constructing lookup Array");
- }
- NaccacheSternPrivateKeyParameters priv = (NaccacheSternPrivateKeyParameters)key;
- Vector primes = priv.getSmallPrimes();
- lookup = new Vector[primes.size()];
- for (int i = 0; i < primes.size(); i++)
- {
- BigInteger actualPrime = (BigInteger)primes.elementAt(i);
- int actualPrimeValue = actualPrime.intValue();
-
- lookup[i] = new Vector();
- lookup[i].addElement(ONE);
-
- if (debug)
- {
- System.out.println("Constructing lookup ArrayList for " + actualPrimeValue);
- }
-
- BigInteger accJ = ZERO;
-
- for (int j = 1; j < actualPrimeValue; j++)
- {
- accJ = accJ.add(priv.getPhi_n());
- BigInteger comp = accJ.divide(actualPrime);
- lookup[i].addElement(priv.getG().modPow(comp, priv.getModulus()));
- }
- }
- }
- }
-
- public void setDebug(boolean debug)
- {
- this.debug = debug;
- }
-
- /**
- * Returns the input block size of this algorithm.
- *
- * @see org.bouncycastle.crypto.AsymmetricBlockCipher#getInputBlockSize()
- */
- public int getInputBlockSize()
- {
- if (forEncryption)
- {
- // We can only encrypt values up to lowerSigmaBound
- return (key.getLowerSigmaBound() + 7) / 8 - 1;
- }
- else
- {
- // We pad to modulus-size bytes for easier decryption.
- return key.getModulus().toByteArray().length;
- }
- }
-
- /**
- * Returns the output block size of this algorithm.
- *
- * @see org.bouncycastle.crypto.AsymmetricBlockCipher#getOutputBlockSize()
- */
- public int getOutputBlockSize()
- {
- if (forEncryption)
- {
- // encrypted Data is always padded up to modulus size
- return key.getModulus().toByteArray().length;
- }
- else
- {
- // decrypted Data has upper limit lowerSigmaBound
- return (key.getLowerSigmaBound() + 7) / 8 - 1;
- }
- }
-
- /**
- * Process a single Block using the Naccache-Stern algorithm.
- *
- * @see org.bouncycastle.crypto.AsymmetricBlockCipher#processBlock(byte[],
- * int, int)
- */
- public byte[] processBlock(byte[] in, int inOff, int len) throws InvalidCipherTextException
- {
- if (key == null)
- {
- throw new IllegalStateException("NaccacheStern engine not initialised");
- }
- if (len > (getInputBlockSize() + 1))
- {
- throw new DataLengthException("input too large for Naccache-Stern cipher.\n");
- }
-
- if (!forEncryption)
- {
- // At decryption make sure that we receive padded data blocks
- if (len < getInputBlockSize())
- {
- throw new InvalidCipherTextException("BlockLength does not match modulus for Naccache-Stern cipher.\n");
- }
- }
-
- byte[] block;
-
- if (inOff != 0 || len != in.length)
- {
- block = new byte[len];
- System.arraycopy(in, inOff, block, 0, len);
- }
- else
- {
- block = in;
- }
-
- // transform input into BigInteger
- BigInteger input = new BigInteger(1, block);
- if (debug)
- {
- System.out.println("input as BigInteger: " + input);
- }
- byte[] output;
- if (forEncryption)
- {
- output = encrypt(input);
- }
- else
- {
- Vector plain = new Vector();
- NaccacheSternPrivateKeyParameters priv = (NaccacheSternPrivateKeyParameters)key;
- Vector primes = priv.getSmallPrimes();
- // Get Chinese Remainders of CipherText
- for (int i = 0; i < primes.size(); i++)
- {
- BigInteger exp = input.modPow(priv.getPhi_n().divide((BigInteger)primes.elementAt(i)), priv.getModulus());
- Vector al = lookup[i];
- if (lookup[i].size() != ((BigInteger)primes.elementAt(i)).intValue())
- {
- if (debug)
- {
- System.out.println("Prime is " + primes.elementAt(i) + ", lookup table has size " + al.size());
- }
- throw new InvalidCipherTextException("Error in lookup Array for "
- + ((BigInteger)primes.elementAt(i)).intValue()
- + ": Size mismatch. Expected ArrayList with length "
- + ((BigInteger)primes.elementAt(i)).intValue() + " but found ArrayList of length "
- + lookup[i].size());
- }
- int lookedup = al.indexOf(exp);
-
- if (lookedup == -1)
- {
- if (debug)
- {
- System.out.println("Actual prime is " + primes.elementAt(i));
- System.out.println("Decrypted value is " + exp);
-
- System.out.println("LookupList for " + primes.elementAt(i) + " with size " + lookup[i].size()
- + " is: ");
- for (int j = 0; j < lookup[i].size(); j++)
- {
- System.out.println(lookup[i].elementAt(j));
- }
- }
- throw new InvalidCipherTextException("Lookup failed");
- }
- plain.addElement(BigInteger.valueOf(lookedup));
- }
- BigInteger test = chineseRemainder(plain, primes);
-
- // Should not be used as an oracle, so reencrypt output to see
- // if it corresponds to input
-
- // this breaks probabilisic encryption, so disable it. Anyway, we do
- // use the first n primes for key generation, so it is pretty easy
- // to guess them. But as stated in the paper, this is not a security
- // breach. So we can just work with the correct sigma.
-
- // if (debug) {
- // System.out.println("Decryption is " + test);
- // }
- // if ((key.getG().modPow(test, key.getModulus())).equals(input)) {
- // output = test.toByteArray();
- // } else {
- // if(debug){
- // System.out.println("Engine seems to be used as an oracle,
- // returning null");
- // }
- // output = null;
- // }
-
- output = test.toByteArray();
-
- }
-
- return output;
- }
-
- /**
- * Encrypts a BigInteger aka Plaintext with the public key.
- *
- * @param plain
- * The BigInteger to encrypt
- * @return The byte[] representation of the encrypted BigInteger (i.e.
- * crypted.toByteArray())
- */
- public byte[] encrypt(BigInteger plain)
- {
- // Always return modulus size values 0-padded at the beginning
- // 0-padding at the beginning is correctly parsed by BigInteger :)
- byte[] output = key.getModulus().toByteArray();
- Arrays.fill(output, (byte)0);
- byte[] tmp = key.getG().modPow(plain, key.getModulus()).toByteArray();
- System
- .arraycopy(tmp, 0, output, output.length - tmp.length,
- tmp.length);
- if (debug)
- {
- System.out
- .println("Encrypted value is: " + new BigInteger(output));
- }
- return output;
- }
-
- /**
- * Adds the contents of two encrypted blocks mod sigma
- *
- * @param block1
- * the first encrypted block
- * @param block2
- * the second encrypted block
- * @return encrypt((block1 + block2) mod sigma)
- * @throws InvalidCipherTextException
- */
- public byte[] addCryptedBlocks(byte[] block1, byte[] block2)
- throws InvalidCipherTextException
- {
- // check for correct blocksize
- if (forEncryption)
- {
- if ((block1.length > getOutputBlockSize())
- || (block2.length > getOutputBlockSize()))
- {
- throw new InvalidCipherTextException(
- "BlockLength too large for simple addition.\n");
- }
- }
- else
- {
- if ((block1.length > getInputBlockSize())
- || (block2.length > getInputBlockSize()))
- {
- throw new InvalidCipherTextException(
- "BlockLength too large for simple addition.\n");
- }
- }
-
- // calculate resulting block
- BigInteger m1Crypt = new BigInteger(1, block1);
- BigInteger m2Crypt = new BigInteger(1, block2);
- BigInteger m1m2Crypt = m1Crypt.multiply(m2Crypt);
- m1m2Crypt = m1m2Crypt.mod(key.getModulus());
- if (debug)
- {
- System.out.println("c(m1) as BigInteger:....... " + m1Crypt);
- System.out.println("c(m2) as BigInteger:....... " + m2Crypt);
- System.out.println("c(m1)*c(m2)%n = c(m1+m2)%n: " + m1m2Crypt);
- }
-
- byte[] output = key.getModulus().toByteArray();
- Arrays.fill(output, (byte)0);
- System.arraycopy(m1m2Crypt.toByteArray(), 0, output, output.length
- - m1m2Crypt.toByteArray().length,
- m1m2Crypt.toByteArray().length);
-
- return output;
- }
-
- /**
- * Convenience Method for data exchange with the cipher.
- *
- * Determines blocksize and splits data to blocksize.
- *
- * @param data the data to be processed
- * @return the data after it went through the NaccacheSternEngine.
- * @throws InvalidCipherTextException
- */
- public byte[] processData(byte[] data) throws InvalidCipherTextException
- {
- if (debug)
- {
- System.out.println();
- }
- if (data.length > getInputBlockSize())
- {
- int inBlocksize = getInputBlockSize();
- int outBlocksize = getOutputBlockSize();
- if (debug)
- {
- System.out.println("Input blocksize is: " + inBlocksize + " bytes");
- System.out.println("Output blocksize is: " + outBlocksize + " bytes");
- System.out.println("Data has length:.... " + data.length + " bytes");
- }
- int datapos = 0;
- int retpos = 0;
- byte[] retval = new byte[(data.length / inBlocksize + 1) * outBlocksize];
- while (datapos < data.length)
- {
- byte[] tmp;
- if (datapos + inBlocksize < data.length)
- {
- tmp = processBlock(data, datapos, inBlocksize);
- datapos += inBlocksize;
- }
- else
- {
- tmp = processBlock(data, datapos, data.length - datapos);
- datapos += data.length - datapos;
- }
- if (debug)
- {
- System.out.println("new datapos is " + datapos);
- }
- if (tmp != null)
- {
- System.arraycopy(tmp, 0, retval, retpos, tmp.length);
-
- retpos += tmp.length;
- }
- else
- {
- if (debug)
- {
- System.out.println("cipher returned null");
- }
- throw new InvalidCipherTextException("cipher returned null");
- }
- }
- byte[] ret = new byte[retpos];
- System.arraycopy(retval, 0, ret, 0, retpos);
- if (debug)
- {
- System.out.println("returning " + ret.length + " bytes");
- }
- return ret;
- }
- else
- {
- if (debug)
- {
- System.out.println("data size is less then input block size, processing directly");
- }
- return processBlock(data, 0, data.length);
- }
- }
-
- /**
- * Computes the integer x that is expressed through the given primes and the
- * congruences with the chinese remainder theorem (CRT).
- *
- * @param congruences
- * the congruences c_i
- * @param primes
- * the primes p_i
- * @return an integer x for that x % p_i == c_i
- */
- private static BigInteger chineseRemainder(Vector congruences, Vector primes)
- {
- BigInteger retval = ZERO;
- BigInteger all = ONE;
- for (int i = 0; i < primes.size(); i++)
- {
- all = all.multiply((BigInteger)primes.elementAt(i));
- }
- for (int i = 0; i < primes.size(); i++)
- {
- BigInteger a = (BigInteger)primes.elementAt(i);
- BigInteger b = all.divide(a);
- BigInteger b_ = b.modInverse(a);
- BigInteger tmp = b.multiply(b_);
- tmp = tmp.multiply((BigInteger)congruences.elementAt(i));
- retval = retval.add(tmp);
- }
-
- return retval.mod(all);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/NoekeonEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/NoekeonEngine.java
deleted file mode 100644
index c4494c40..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/NoekeonEngine.java
+++ /dev/null
@@ -1,263 +0,0 @@
-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;
-
-/**
- * A Noekeon engine, using direct-key mode.
- */
-
-public class NoekeonEngine
- implements BlockCipher
-{
- private static final int genericSize = 16; // Block and key size, as well as the amount of rounds.
-
- private static final int[] nullVector =
- {
- 0x00, 0x00, 0x00, 0x00 // Used in decryption
- },
-
- roundConstants =
- {
- 0x80, 0x1b, 0x36, 0x6c,
- 0xd8, 0xab, 0x4d, 0x9a,
- 0x2f, 0x5e, 0xbc, 0x63,
- 0xc6, 0x97, 0x35, 0x6a,
- 0xd4
- };
-
- private int[] state = new int[4], // a
- subKeys = new int[4], // k
- decryptKeys = new int[4];
-
- private boolean _initialised,
- _forEncryption;
-
- /**
- * Create an instance of the Noekeon encryption algorithm
- * and set some defaults
- */
- public NoekeonEngine()
- {
- _initialised = false;
- }
-
- public String getAlgorithmName()
- {
- return "Noekeon";
- }
-
- public int getBlockSize()
- {
- return genericSize;
- }
-
- /**
- * initialise
- *
- * @param forEncryption whether or not we are for encryption.
- * @param params the parameters required to set up the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean forEncryption,
- CipherParameters params)
- {
- if (!(params instanceof KeyParameter))
- {
- throw new IllegalArgumentException("invalid parameter passed to Noekeon init - " + params.getClass().getName());
- }
-
- _forEncryption = forEncryption;
- _initialised = true;
-
- KeyParameter p = (KeyParameter)params;
-
- setKey(p.getKey());
- }
-
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- if (!_initialised)
- {
- throw new IllegalStateException(getAlgorithmName()+" not initialised");
- }
-
- if ((inOff + genericSize) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + genericSize) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- return (_forEncryption) ? encryptBlock(in, inOff, out, outOff)
- : decryptBlock(in, inOff, out, outOff);
- }
-
- public void reset()
- {
- }
-
- /**
- * Re-key the cipher.
- * <p>
- * @param key the key to be used
- */
- private void setKey(
- byte[] key)
- {
- subKeys[0] = bytesToIntBig(key, 0);
- subKeys[1] = bytesToIntBig(key, 4);
- subKeys[2] = bytesToIntBig(key, 8);
- subKeys[3] = bytesToIntBig(key, 12);
- }
-
- private int encryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- state[0] = bytesToIntBig(in, inOff);
- state[1] = bytesToIntBig(in, inOff+4);
- state[2] = bytesToIntBig(in, inOff+8);
- state[3] = bytesToIntBig(in, inOff+12);
-
- int i;
- for (i = 0; i < genericSize; i++)
- {
- state[0] ^= roundConstants[i];
- theta(state, subKeys);
- pi1(state);
- gamma(state);
- pi2(state);
- }
-
- state[0] ^= roundConstants[i];
- theta(state, subKeys);
-
- intToBytesBig(state[0], out, outOff);
- intToBytesBig(state[1], out, outOff+4);
- intToBytesBig(state[2], out, outOff+8);
- intToBytesBig(state[3], out, outOff+12);
-
- return genericSize;
- }
-
- private int decryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- state[0] = bytesToIntBig(in, inOff);
- state[1] = bytesToIntBig(in, inOff+4);
- state[2] = bytesToIntBig(in, inOff+8);
- state[3] = bytesToIntBig(in, inOff+12);
-
- System.arraycopy(subKeys, 0, decryptKeys, 0, subKeys.length);
- theta(decryptKeys, nullVector);
-
- int i;
- for (i = genericSize; i > 0; i--)
- {
- theta(state, decryptKeys);
- state[0] ^= roundConstants[i];
- pi1(state);
- gamma(state);
- pi2(state);
- }
-
- theta(state, decryptKeys);
- state[0] ^= roundConstants[i];
-
- intToBytesBig(state[0], out, outOff);
- intToBytesBig(state[1], out, outOff+4);
- intToBytesBig(state[2], out, outOff+8);
- intToBytesBig(state[3], out, outOff+12);
-
- return genericSize;
- }
-
- private void gamma(int[] a)
- {
- a[1] ^= ~a[3] & ~a[2];
- a[0] ^= a[2] & a[1];
-
- int tmp = a[3];
- a[3] = a[0];
- a[0] = tmp;
- a[2] ^= a[0]^a[1]^a[3];
-
- a[1] ^= ~a[3] & ~a[2];
- a[0] ^= a[2] & a[1];
- }
-
- private void theta(int[] a, int[] k)
- {
- int tmp;
-
- tmp = a[0]^a[2];
- tmp ^= rotl(tmp,8)^rotl(tmp,24);
- a[1] ^= tmp;
- a[3] ^= tmp;
-
- for (int i = 0; i < 4; i++)
- {
- a[i] ^= k[i];
- }
-
- tmp = a[1]^a[3];
- tmp ^= rotl(tmp,8)^rotl(tmp,24);
- a[0] ^= tmp;
- a[2] ^= tmp;
- }
-
- private void pi1(int[] a)
- {
- a[1] = rotl(a[1], 1);
- a[2] = rotl(a[2], 5);
- a[3] = rotl(a[3], 2);
- }
-
- private void pi2(int[] a)
- {
- a[1] = rotl(a[1], 31);
- a[2] = rotl(a[2], 27);
- a[3] = rotl(a[3], 30);
- }
-
- // Helpers
-
- private int bytesToIntBig(byte[] in, int off)
- {
- return ((in[off++]) << 24) |
- ((in[off++] & 0xff) << 16) |
- ((in[off++] & 0xff) << 8) |
- (in[off ] & 0xff);
- }
-
- private void intToBytesBig(int x, byte[] out, int off)
- {
- out[off++] = (byte)(x >>> 24);
- out[off++] = (byte)(x >>> 16);
- out[off++] = (byte)(x >>> 8);
- out[off ] = (byte)x;
- }
-
- private int rotl(int x, int y)
- {
- return (x << y) | (x >>> (32-y));
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/NullEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/NullEngine.java
deleted file mode 100644
index 1ad2c9df..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/NullEngine.java
+++ /dev/null
@@ -1,96 +0,0 @@
-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;
-
-/**
- * The no-op engine that just copies bytes through, irrespective of whether encrypting and decrypting.
- * Provided for the sake of completeness.
- */
-public class NullEngine implements BlockCipher
-{
- private boolean initialised;
- protected static final int DEFAULT_BLOCK_SIZE = 1;
- private final int blockSize;
-
- /**
- * Constructs a null engine with a block size of 1 byte.
- */
- public NullEngine()
- {
- 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)
- * @see org.bouncycastle.crypto.BlockCipher#init(boolean, org.bouncycastle.crypto.CipherParameters)
- */
- public void init(boolean forEncryption, CipherParameters params) throws IllegalArgumentException
- {
- // we don't mind any parameters that may come in
- this.initialised = true;
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.crypto.BlockCipher#getAlgorithmName()
- */
- public String getAlgorithmName()
- {
- return "Null";
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.crypto.BlockCipher#getBlockSize()
- */
- public int getBlockSize()
- {
- return blockSize;
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.crypto.BlockCipher#processBlock(byte[], int, byte[], int)
- */
- public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
- throws DataLengthException, IllegalStateException
- {
- if (!initialised)
- {
- throw new IllegalStateException("Null engine not initialised");
- }
- 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];
- }
-
- return blockSize;
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.crypto.BlockCipher#reset()
- */
- public void reset()
- {
- // nothing needs to be done
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/RC2Engine.java b/core/src/main/java/org/bouncycastle/crypto/engines/RC2Engine.java
deleted file mode 100644
index 02cb8811..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/RC2Engine.java
+++ /dev/null
@@ -1,317 +0,0 @@
-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;
-import org.bouncycastle.crypto.params.RC2Parameters;
-
-/**
- * an implementation of RC2 as described in RFC 2268
- * "A Description of the RC2(r) Encryption Algorithm" R. Rivest.
- */
-public class RC2Engine
- implements BlockCipher
-{
- //
- // the values we use for key expansion (based on the digits of PI)
- //
- private static byte[] piTable =
- {
- (byte)0xd9, (byte)0x78, (byte)0xf9, (byte)0xc4, (byte)0x19, (byte)0xdd, (byte)0xb5, (byte)0xed,
- (byte)0x28, (byte)0xe9, (byte)0xfd, (byte)0x79, (byte)0x4a, (byte)0xa0, (byte)0xd8, (byte)0x9d,
- (byte)0xc6, (byte)0x7e, (byte)0x37, (byte)0x83, (byte)0x2b, (byte)0x76, (byte)0x53, (byte)0x8e,
- (byte)0x62, (byte)0x4c, (byte)0x64, (byte)0x88, (byte)0x44, (byte)0x8b, (byte)0xfb, (byte)0xa2,
- (byte)0x17, (byte)0x9a, (byte)0x59, (byte)0xf5, (byte)0x87, (byte)0xb3, (byte)0x4f, (byte)0x13,
- (byte)0x61, (byte)0x45, (byte)0x6d, (byte)0x8d, (byte)0x9, (byte)0x81, (byte)0x7d, (byte)0x32,
- (byte)0xbd, (byte)0x8f, (byte)0x40, (byte)0xeb, (byte)0x86, (byte)0xb7, (byte)0x7b, (byte)0xb,
- (byte)0xf0, (byte)0x95, (byte)0x21, (byte)0x22, (byte)0x5c, (byte)0x6b, (byte)0x4e, (byte)0x82,
- (byte)0x54, (byte)0xd6, (byte)0x65, (byte)0x93, (byte)0xce, (byte)0x60, (byte)0xb2, (byte)0x1c,
- (byte)0x73, (byte)0x56, (byte)0xc0, (byte)0x14, (byte)0xa7, (byte)0x8c, (byte)0xf1, (byte)0xdc,
- (byte)0x12, (byte)0x75, (byte)0xca, (byte)0x1f, (byte)0x3b, (byte)0xbe, (byte)0xe4, (byte)0xd1,
- (byte)0x42, (byte)0x3d, (byte)0xd4, (byte)0x30, (byte)0xa3, (byte)0x3c, (byte)0xb6, (byte)0x26,
- (byte)0x6f, (byte)0xbf, (byte)0xe, (byte)0xda, (byte)0x46, (byte)0x69, (byte)0x7, (byte)0x57,
- (byte)0x27, (byte)0xf2, (byte)0x1d, (byte)0x9b, (byte)0xbc, (byte)0x94, (byte)0x43, (byte)0x3,
- (byte)0xf8, (byte)0x11, (byte)0xc7, (byte)0xf6, (byte)0x90, (byte)0xef, (byte)0x3e, (byte)0xe7,
- (byte)0x6, (byte)0xc3, (byte)0xd5, (byte)0x2f, (byte)0xc8, (byte)0x66, (byte)0x1e, (byte)0xd7,
- (byte)0x8, (byte)0xe8, (byte)0xea, (byte)0xde, (byte)0x80, (byte)0x52, (byte)0xee, (byte)0xf7,
- (byte)0x84, (byte)0xaa, (byte)0x72, (byte)0xac, (byte)0x35, (byte)0x4d, (byte)0x6a, (byte)0x2a,
- (byte)0x96, (byte)0x1a, (byte)0xd2, (byte)0x71, (byte)0x5a, (byte)0x15, (byte)0x49, (byte)0x74,
- (byte)0x4b, (byte)0x9f, (byte)0xd0, (byte)0x5e, (byte)0x4, (byte)0x18, (byte)0xa4, (byte)0xec,
- (byte)0xc2, (byte)0xe0, (byte)0x41, (byte)0x6e, (byte)0xf, (byte)0x51, (byte)0xcb, (byte)0xcc,
- (byte)0x24, (byte)0x91, (byte)0xaf, (byte)0x50, (byte)0xa1, (byte)0xf4, (byte)0x70, (byte)0x39,
- (byte)0x99, (byte)0x7c, (byte)0x3a, (byte)0x85, (byte)0x23, (byte)0xb8, (byte)0xb4, (byte)0x7a,
- (byte)0xfc, (byte)0x2, (byte)0x36, (byte)0x5b, (byte)0x25, (byte)0x55, (byte)0x97, (byte)0x31,
- (byte)0x2d, (byte)0x5d, (byte)0xfa, (byte)0x98, (byte)0xe3, (byte)0x8a, (byte)0x92, (byte)0xae,
- (byte)0x5, (byte)0xdf, (byte)0x29, (byte)0x10, (byte)0x67, (byte)0x6c, (byte)0xba, (byte)0xc9,
- (byte)0xd3, (byte)0x0, (byte)0xe6, (byte)0xcf, (byte)0xe1, (byte)0x9e, (byte)0xa8, (byte)0x2c,
- (byte)0x63, (byte)0x16, (byte)0x1, (byte)0x3f, (byte)0x58, (byte)0xe2, (byte)0x89, (byte)0xa9,
- (byte)0xd, (byte)0x38, (byte)0x34, (byte)0x1b, (byte)0xab, (byte)0x33, (byte)0xff, (byte)0xb0,
- (byte)0xbb, (byte)0x48, (byte)0xc, (byte)0x5f, (byte)0xb9, (byte)0xb1, (byte)0xcd, (byte)0x2e,
- (byte)0xc5, (byte)0xf3, (byte)0xdb, (byte)0x47, (byte)0xe5, (byte)0xa5, (byte)0x9c, (byte)0x77,
- (byte)0xa, (byte)0xa6, (byte)0x20, (byte)0x68, (byte)0xfe, (byte)0x7f, (byte)0xc1, (byte)0xad
- };
-
- private static final int BLOCK_SIZE = 8;
-
- private int[] workingKey;
- private boolean encrypting;
-
- private int[] generateWorkingKey(
- byte[] key,
- int bits)
- {
- int x;
- int[] xKey = new int[128];
-
- for (int i = 0; i != key.length; i++)
- {
- xKey[i] = key[i] & 0xff;
- }
-
- // Phase 1: Expand input key to 128 bytes
- int len = key.length;
-
- if (len < 128)
- {
- int index = 0;
-
- x = xKey[len - 1];
-
- do
- {
- x = piTable[(x + xKey[index++]) & 255] & 0xff;
- xKey[len++] = x;
- }
- while (len < 128);
- }
-
- // Phase 2 - reduce effective key size to "bits"
- len = (bits + 7) >> 3;
- x = piTable[xKey[128 - len] & (255 >> (7 & -bits))] & 0xff;
- xKey[128 - len] = x;
-
- for (int i = 128 - len - 1; i >= 0; i--)
- {
- x = piTable[x ^ xKey[i + len]] & 0xff;
- xKey[i] = x;
- }
-
- // Phase 3 - copy to newKey in little-endian order
- int[] newKey = new int[64];
-
- for (int i = 0; i != newKey.length; i++)
- {
- newKey[i] = (xKey[2 * i] + (xKey[2 * i + 1] << 8));
- }
-
- return newKey;
- }
-
- /**
- * initialise a RC2 cipher.
- *
- * @param encrypting whether or not we are for encryption.
- * @param params the parameters required to set up the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean encrypting,
- CipherParameters params)
- {
- this.encrypting = encrypting;
-
- if (params instanceof RC2Parameters)
- {
- RC2Parameters param = (RC2Parameters)params;
-
- workingKey = generateWorkingKey(param.getKey(),
- param.getEffectiveKeyBits());
- }
- else if (params instanceof KeyParameter)
- {
- byte[] key = ((KeyParameter)params).getKey();
-
- workingKey = generateWorkingKey(key, key.length * 8);
- }
- else
- {
- throw new IllegalArgumentException("invalid parameter passed to RC2 init - " + params.getClass().getName());
- }
-
- }
-
- public void reset()
- {
- }
-
- public String getAlgorithmName()
- {
- return "RC2";
- }
-
- public int getBlockSize()
- {
- return BLOCK_SIZE;
- }
-
- public final int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- if (workingKey == null)
- {
- throw new IllegalStateException("RC2 engine not initialised");
- }
-
- if ((inOff + BLOCK_SIZE) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + BLOCK_SIZE) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- if (encrypting)
- {
- encryptBlock(in, inOff, out, outOff);
- }
- else
- {
- decryptBlock(in, inOff, out, outOff);
- }
-
- return BLOCK_SIZE;
- }
-
- /**
- * return the result rotating the 16 bit number in x left by y
- */
- private int rotateWordLeft(
- int x,
- int y)
- {
- x &= 0xffff;
- return (x << y) | (x >> (16 - y));
- }
-
- private void encryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- int x76, x54, x32, x10;
-
- x76 = ((in[inOff + 7] & 0xff) << 8) + (in[inOff + 6] & 0xff);
- x54 = ((in[inOff + 5] & 0xff) << 8) + (in[inOff + 4] & 0xff);
- x32 = ((in[inOff + 3] & 0xff) << 8) + (in[inOff + 2] & 0xff);
- x10 = ((in[inOff + 1] & 0xff) << 8) + (in[inOff + 0] & 0xff);
-
- for (int i = 0; i <= 16; i += 4)
- {
- x10 = rotateWordLeft(x10 + (x32 & ~x76) + (x54 & x76) + workingKey[i ], 1);
- x32 = rotateWordLeft(x32 + (x54 & ~x10) + (x76 & x10) + workingKey[i+1], 2);
- x54 = rotateWordLeft(x54 + (x76 & ~x32) + (x10 & x32) + workingKey[i+2], 3);
- x76 = rotateWordLeft(x76 + (x10 & ~x54) + (x32 & x54) + workingKey[i+3], 5);
- }
-
- x10 += workingKey[x76 & 63];
- x32 += workingKey[x10 & 63];
- x54 += workingKey[x32 & 63];
- x76 += workingKey[x54 & 63];
-
- for (int i = 20; i <= 40; i += 4)
- {
- x10 = rotateWordLeft(x10 + (x32 & ~x76) + (x54 & x76) + workingKey[i ], 1);
- x32 = rotateWordLeft(x32 + (x54 & ~x10) + (x76 & x10) + workingKey[i+1], 2);
- x54 = rotateWordLeft(x54 + (x76 & ~x32) + (x10 & x32) + workingKey[i+2], 3);
- x76 = rotateWordLeft(x76 + (x10 & ~x54) + (x32 & x54) + workingKey[i+3], 5);
- }
-
- x10 += workingKey[x76 & 63];
- x32 += workingKey[x10 & 63];
- x54 += workingKey[x32 & 63];
- x76 += workingKey[x54 & 63];
-
- for (int i = 44; i < 64; i += 4)
- {
- x10 = rotateWordLeft(x10 + (x32 & ~x76) + (x54 & x76) + workingKey[i ], 1);
- x32 = rotateWordLeft(x32 + (x54 & ~x10) + (x76 & x10) + workingKey[i+1], 2);
- x54 = rotateWordLeft(x54 + (x76 & ~x32) + (x10 & x32) + workingKey[i+2], 3);
- x76 = rotateWordLeft(x76 + (x10 & ~x54) + (x32 & x54) + workingKey[i+3], 5);
- }
-
- out[outOff + 0] = (byte)x10;
- out[outOff + 1] = (byte)(x10 >> 8);
- out[outOff + 2] = (byte)x32;
- out[outOff + 3] = (byte)(x32 >> 8);
- out[outOff + 4] = (byte)x54;
- out[outOff + 5] = (byte)(x54 >> 8);
- out[outOff + 6] = (byte)x76;
- out[outOff + 7] = (byte)(x76 >> 8);
- }
-
- private void decryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- int x76, x54, x32, x10;
-
- x76 = ((in[inOff + 7] & 0xff) << 8) + (in[inOff + 6] & 0xff);
- x54 = ((in[inOff + 5] & 0xff) << 8) + (in[inOff + 4] & 0xff);
- x32 = ((in[inOff + 3] & 0xff) << 8) + (in[inOff + 2] & 0xff);
- x10 = ((in[inOff + 1] & 0xff) << 8) + (in[inOff + 0] & 0xff);
-
- for (int i = 60; i >= 44; i -= 4)
- {
- x76 = rotateWordLeft(x76, 11) - ((x10 & ~x54) + (x32 & x54) + workingKey[i+3]);
- x54 = rotateWordLeft(x54, 13) - ((x76 & ~x32) + (x10 & x32) + workingKey[i+2]);
- x32 = rotateWordLeft(x32, 14) - ((x54 & ~x10) + (x76 & x10) + workingKey[i+1]);
- x10 = rotateWordLeft(x10, 15) - ((x32 & ~x76) + (x54 & x76) + workingKey[i ]);
- }
-
- x76 -= workingKey[x54 & 63];
- x54 -= workingKey[x32 & 63];
- x32 -= workingKey[x10 & 63];
- x10 -= workingKey[x76 & 63];
-
- for (int i = 40; i >= 20; i -= 4)
- {
- x76 = rotateWordLeft(x76, 11) - ((x10 & ~x54) + (x32 & x54) + workingKey[i+3]);
- x54 = rotateWordLeft(x54, 13) - ((x76 & ~x32) + (x10 & x32) + workingKey[i+2]);
- x32 = rotateWordLeft(x32, 14) - ((x54 & ~x10) + (x76 & x10) + workingKey[i+1]);
- x10 = rotateWordLeft(x10, 15) - ((x32 & ~x76) + (x54 & x76) + workingKey[i ]);
- }
-
- x76 -= workingKey[x54 & 63];
- x54 -= workingKey[x32 & 63];
- x32 -= workingKey[x10 & 63];
- x10 -= workingKey[x76 & 63];
-
- for (int i = 16; i >= 0; i -= 4)
- {
- x76 = rotateWordLeft(x76, 11) - ((x10 & ~x54) + (x32 & x54) + workingKey[i+3]);
- x54 = rotateWordLeft(x54, 13) - ((x76 & ~x32) + (x10 & x32) + workingKey[i+2]);
- x32 = rotateWordLeft(x32, 14) - ((x54 & ~x10) + (x76 & x10) + workingKey[i+1]);
- x10 = rotateWordLeft(x10, 15) - ((x32 & ~x76) + (x54 & x76) + workingKey[i ]);
- }
-
- out[outOff + 0] = (byte)x10;
- out[outOff + 1] = (byte)(x10 >> 8);
- out[outOff + 2] = (byte)x32;
- out[outOff + 3] = (byte)(x32 >> 8);
- out[outOff + 4] = (byte)x54;
- out[outOff + 5] = (byte)(x54 >> 8);
- out[outOff + 6] = (byte)x76;
- out[outOff + 7] = (byte)(x76 >> 8);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/RC2WrapEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/RC2WrapEngine.java
deleted file mode 100644
index ec82b1aa..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/RC2WrapEngine.java
+++ /dev/null
@@ -1,385 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.Wrapper;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.modes.CBCBlockCipher;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.util.Arrays;
-
-/**
- * Wrap keys according to RFC 3217 - RC2 mechanism
- */
-public class RC2WrapEngine
- implements Wrapper
-{
- /** Field engine */
- private CBCBlockCipher engine;
-
- /** Field param */
- private CipherParameters param;
-
- /** Field paramPlusIV */
- private ParametersWithIV paramPlusIV;
-
- /** Field iv */
- private byte[] iv;
-
- /** Field forWrapping */
- private boolean forWrapping;
-
- private SecureRandom sr;
-
- /** Field IV2 */
- private static final byte[] IV2 = { (byte) 0x4a, (byte) 0xdd, (byte) 0xa2,
- (byte) 0x2c, (byte) 0x79, (byte) 0xe8,
- (byte) 0x21, (byte) 0x05 };
-
- //
- // checksum digest
- //
- Digest sha1 = new SHA1Digest();
- byte[] digest = new byte[20];
-
- /**
- * Method init
- *
- * @param forWrapping
- * @param param
- */
- public void init(boolean forWrapping, CipherParameters param)
- {
- this.forWrapping = forWrapping;
- this.engine = new CBCBlockCipher(new RC2Engine());
-
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom pWithR = (ParametersWithRandom)param;
- sr = pWithR.getRandom();
- param = pWithR.getParameters();
- }
- else
- {
- sr = new SecureRandom();
- }
-
- if (param instanceof ParametersWithIV)
- {
- this.paramPlusIV = (ParametersWithIV)param;
- this.iv = this.paramPlusIV.getIV();
- this.param = this.paramPlusIV.getParameters();
-
- if (this.forWrapping)
- {
- if ((this.iv == null) || (this.iv.length != 8))
- {
- throw new IllegalArgumentException("IV is not 8 octets");
- }
- }
- else
- {
- throw new IllegalArgumentException(
- "You should not supply an IV for unwrapping");
- }
- }
- else
- {
- this.param = param;
-
- if (this.forWrapping)
- {
-
- // Hm, we have no IV but we want to wrap ?!?
- // well, then we have to create our own IV.
- this.iv = new byte[8];
-
- sr.nextBytes(iv);
-
- this.paramPlusIV = new ParametersWithIV(this.param, this.iv);
- }
- }
-
- }
-
- /**
- * Method getAlgorithmName
- *
- * @return the algorithm name "RC2".
- */
- public String getAlgorithmName()
- {
- return "RC2";
- }
-
- /**
- * Method wrap
- *
- * @param in
- * @param inOff
- * @param inLen
- * @return the wrapped bytes.
- */
- public byte[] wrap(byte[] in, int inOff, int inLen)
- {
-
- if (!forWrapping)
- {
- throw new IllegalStateException("Not initialized for wrapping");
- }
-
- int length = inLen + 1;
- if ((length % 8) != 0)
- {
- length += 8 - (length % 8);
- }
-
- byte keyToBeWrapped[] = new byte[length];
-
- keyToBeWrapped[0] = (byte)inLen;
- System.arraycopy(in, inOff, keyToBeWrapped, 1, inLen);
-
- byte[] pad = new byte[keyToBeWrapped.length - inLen - 1];
-
- if (pad.length > 0)
- {
- sr.nextBytes(pad);
- System.arraycopy(pad, 0, keyToBeWrapped, inLen + 1, pad.length);
- }
-
- // Compute the CMS Key Checksum, (section 5.6.1), call this CKS.
- byte[] CKS = calculateCMSKeyChecksum(keyToBeWrapped);
-
- // Let WKCKS = WK || CKS where || is concatenation.
- byte[] WKCKS = new byte[keyToBeWrapped.length + CKS.length];
-
- System.arraycopy(keyToBeWrapped, 0, WKCKS, 0, keyToBeWrapped.length);
- System.arraycopy(CKS, 0, WKCKS, keyToBeWrapped.length, CKS.length);
-
- // Encrypt WKCKS in CBC mode using KEK as the key and IV as the
- // initialization vector. Call the results TEMP1.
- byte TEMP1[] = new byte[WKCKS.length];
-
- System.arraycopy(WKCKS, 0, TEMP1, 0, WKCKS.length);
-
- int noOfBlocks = WKCKS.length / engine.getBlockSize();
- int extraBytes = WKCKS.length % engine.getBlockSize();
-
- if (extraBytes != 0)
- {
- throw new IllegalStateException("Not multiple of block length");
- }
-
- engine.init(true, paramPlusIV);
-
- for (int i = 0; i < noOfBlocks; i++)
- {
- int currentBytePos = i * engine.getBlockSize();
-
- engine.processBlock(TEMP1, currentBytePos, TEMP1, currentBytePos);
- }
-
- // Left TEMP2 = IV || TEMP1.
- byte[] TEMP2 = new byte[this.iv.length + TEMP1.length];
-
- System.arraycopy(this.iv, 0, TEMP2, 0, this.iv.length);
- System.arraycopy(TEMP1, 0, TEMP2, this.iv.length, TEMP1.length);
-
- // Reverse the order of the octets in TEMP2 and call the result TEMP3.
- byte[] TEMP3 = new byte[TEMP2.length];
-
- for (int i = 0; i < TEMP2.length; i++)
- {
- TEMP3[i] = TEMP2[TEMP2.length - (i + 1)];
- }
-
- // Encrypt TEMP3 in CBC mode using the KEK and an initialization vector
- // of 0x 4a dd a2 2c 79 e8 21 05. The resulting cipher text is the
- // desired
- // result. It is 40 octets long if a 168 bit key is being wrapped.
- ParametersWithIV param2 = new ParametersWithIV(this.param, IV2);
-
- this.engine.init(true, param2);
-
- for (int i = 0; i < noOfBlocks + 1; i++)
- {
- int currentBytePos = i * engine.getBlockSize();
-
- engine.processBlock(TEMP3, currentBytePos, TEMP3, currentBytePos);
- }
-
- return TEMP3;
- }
-
- /**
- * Method unwrap
- *
- * @param in
- * @param inOff
- * @param inLen
- * @return the unwrapped bytes.
- * @throws InvalidCipherTextException
- */
- public byte[] unwrap(byte[] in, int inOff, int inLen)
- throws InvalidCipherTextException
- {
-
- if (forWrapping)
- {
- throw new IllegalStateException("Not set for unwrapping");
- }
-
- if (in == null)
- {
- throw new InvalidCipherTextException("Null pointer as ciphertext");
- }
-
- if (inLen % engine.getBlockSize() != 0)
- {
- throw new InvalidCipherTextException("Ciphertext not multiple of "
- + engine.getBlockSize());
- }
-
- /*
- * // Check if the length of the cipher text is reasonable given the key //
- * type. It must be 40 bytes for a 168 bit key and either 32, 40, or //
- * 48 bytes for a 128, 192, or 256 bit key. If the length is not
- * supported // or inconsistent with the algorithm for which the key is
- * intended, // return error. // // we do not accept 168 bit keys. it
- * has to be 192 bit. int lengthA = (estimatedKeyLengthInBit / 8) + 16;
- * int lengthB = estimatedKeyLengthInBit % 8;
- *
- * if ((lengthA != keyToBeUnwrapped.length) || (lengthB != 0)) { throw
- * new XMLSecurityException("empty"); }
- */
-
- // Decrypt the cipher text with TRIPLedeS in CBC mode using the KEK
- // and an initialization vector (IV) of 0x4adda22c79e82105. Call the
- // output TEMP3.
- ParametersWithIV param2 = new ParametersWithIV(this.param, IV2);
-
- this.engine.init(false, param2);
-
- byte TEMP3[] = new byte[inLen];
-
- System.arraycopy(in, inOff, TEMP3, 0, inLen);
-
- for (int i = 0; i < (TEMP3.length / engine.getBlockSize()); i++)
- {
- int currentBytePos = i * engine.getBlockSize();
-
- engine.processBlock(TEMP3, currentBytePos, TEMP3, currentBytePos);
- }
-
- // Reverse the order of the octets in TEMP3 and call the result TEMP2.
- byte[] TEMP2 = new byte[TEMP3.length];
-
- for (int i = 0; i < TEMP3.length; i++)
- {
- TEMP2[i] = TEMP3[TEMP3.length - (i + 1)];
- }
-
- // Decompose TEMP2 into IV, the first 8 octets, and TEMP1, the remaining
- // octets.
- this.iv = new byte[8];
-
- byte[] TEMP1 = new byte[TEMP2.length - 8];
-
- System.arraycopy(TEMP2, 0, this.iv, 0, 8);
- System.arraycopy(TEMP2, 8, TEMP1, 0, TEMP2.length - 8);
-
- // Decrypt TEMP1 using TRIPLedeS in CBC mode using the KEK and the IV
- // found in the previous step. Call the result WKCKS.
- this.paramPlusIV = new ParametersWithIV(this.param, this.iv);
-
- this.engine.init(false, this.paramPlusIV);
-
- byte[] LCEKPADICV = new byte[TEMP1.length];
-
- System.arraycopy(TEMP1, 0, LCEKPADICV, 0, TEMP1.length);
-
- for (int i = 0; i < (LCEKPADICV.length / engine.getBlockSize()); i++)
- {
- int currentBytePos = i * engine.getBlockSize();
-
- engine.processBlock(LCEKPADICV, currentBytePos, LCEKPADICV,
- currentBytePos);
- }
-
- // Decompose LCEKPADICV. CKS is the last 8 octets and WK, the wrapped
- // key, are
- // those octets before the CKS.
- byte[] result = new byte[LCEKPADICV.length - 8];
- byte[] CKStoBeVerified = new byte[8];
-
- System.arraycopy(LCEKPADICV, 0, result, 0, LCEKPADICV.length - 8);
- System.arraycopy(LCEKPADICV, LCEKPADICV.length - 8, CKStoBeVerified, 0,
- 8);
-
- // Calculate a CMS Key Checksum, (section 5.6.1), over the WK and
- // compare
- // with the CKS extracted in the above step. If they are not equal,
- // return error.
- if (!checkCMSKeyChecksum(result, CKStoBeVerified))
- {
- throw new InvalidCipherTextException(
- "Checksum inside ciphertext is corrupted");
- }
-
- if ((result.length - ((result[0] & 0xff) + 1)) > 7)
- {
- throw new InvalidCipherTextException("too many pad bytes ("
- + (result.length - ((result[0] & 0xff) + 1)) + ")");
- }
-
- // CEK is the wrapped key, now extracted for use in data decryption.
- byte[] CEK = new byte[result[0]];
- System.arraycopy(result, 1, CEK, 0, CEK.length);
- return CEK;
- }
-
- /**
- * Some key wrap algorithms make use of the Key Checksum defined
- * in CMS [CMS-Algorithms]. This is used to provide an integrity
- * check value for the key being wrapped. The algorithm is
- *
- * - Compute the 20 octet SHA-1 hash on the key being wrapped.
- * - Use the first 8 octets of this hash as the checksum value.
- *
- * For details see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
- * @param key
- * @return
- * @throws RuntimeException
- *
- */
- private byte[] calculateCMSKeyChecksum(
- byte[] key)
- {
- byte[] result = new byte[8];
-
- sha1.update(key, 0, key.length);
- sha1.doFinal(digest, 0);
-
- System.arraycopy(digest, 0, result, 0, 8);
-
- return result;
- }
-
- /**
- * For details see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
- *
- * @param key
- * @param checksum
- * @return
- */
- private boolean checkCMSKeyChecksum(
- byte[] key,
- byte[] checksum)
- {
- return Arrays.constantTimeAreEqual(calculateCMSKeyChecksum(key), checksum);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/RC4Engine.java b/core/src/main/java/org/bouncycastle/crypto/engines/RC4Engine.java
deleted file mode 100644
index c1ceaa4a..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/RC4Engine.java
+++ /dev/null
@@ -1,146 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.OutputLengthException;
-import org.bouncycastle.crypto.StreamCipher;
-import org.bouncycastle.crypto.params.KeyParameter;
-
-public class RC4Engine implements StreamCipher
-{
- private final static int STATE_LENGTH = 256;
-
- /*
- * variables to hold the state of the RC4 engine
- * during encryption and decryption
- */
-
- private byte[] engineState = null;
- private int x = 0;
- private int y = 0;
- private byte[] workingKey = null;
-
- /**
- * initialise a RC4 cipher.
- *
- * @param forEncryption whether or not we are for encryption.
- * @param params the parameters required to set up the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean forEncryption,
- CipherParameters params
- )
- {
- if (params instanceof KeyParameter)
- {
- /*
- * RC4 encryption and decryption is completely
- * symmetrical, so the 'forEncryption' is
- * irrelevant.
- */
- workingKey = ((KeyParameter)params).getKey();
- setKey(workingKey);
-
- return;
- }
-
- throw new IllegalArgumentException("invalid parameter passed to RC4 init - " + params.getClass().getName());
- }
-
- public String getAlgorithmName()
- {
- return "RC4";
- }
-
- public byte returnByte(byte in)
- {
- x = (x + 1) & 0xff;
- y = (engineState[x] + y) & 0xff;
-
- // swap
- byte tmp = engineState[x];
- engineState[x] = engineState[y];
- engineState[y] = tmp;
-
- // xor
- return (byte)(in ^ engineState[(engineState[x] + engineState[y]) & 0xff]);
- }
-
- public int processBytes(
- byte[] in,
- int inOff,
- int len,
- byte[] out,
- int outOff)
- {
- if ((inOff + len) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + len) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- for (int i = 0; i < len ; i++)
- {
- x = (x + 1) & 0xff;
- y = (engineState[x] + y) & 0xff;
-
- // swap
- byte tmp = engineState[x];
- engineState[x] = engineState[y];
- engineState[y] = tmp;
-
- // xor
- out[i+outOff] = (byte)(in[i + inOff]
- ^ engineState[(engineState[x] + engineState[y]) & 0xff]);
- }
-
- return len;
- }
-
- public void reset()
- {
- setKey(workingKey);
- }
-
- // Private implementation
-
- private void setKey(byte[] keyBytes)
- {
- workingKey = keyBytes;
-
- // System.out.println("the key length is ; "+ workingKey.length);
-
- x = 0;
- y = 0;
-
- if (engineState == null)
- {
- engineState = new byte[STATE_LENGTH];
- }
-
- // reset the state of the engine
- for (int i=0; i < STATE_LENGTH; i++)
- {
- engineState[i] = (byte)i;
- }
-
- int i1 = 0;
- int i2 = 0;
-
- for (int i=0; i < STATE_LENGTH; i++)
- {
- i2 = ((keyBytes[i1] & 0xff) + engineState[i] + i2) & 0xff;
- // do the byte-swap inline
- byte tmp = engineState[i];
- engineState[i] = engineState[i2];
- engineState[i2] = tmp;
- i1 = (i1+1) % keyBytes.length;
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/RC532Engine.java b/core/src/main/java/org/bouncycastle/crypto/engines/RC532Engine.java
deleted file mode 100644
index 9fb6f550..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/RC532Engine.java
+++ /dev/null
@@ -1,287 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.RC5Parameters;
-
-/**
- * The specification for RC5 came from the <code>RC5 Encryption Algorithm</code>
- * publication in RSA CryptoBytes, Spring of 1995.
- * <em>http://www.rsasecurity.com/rsalabs/cryptobytes</em>.
- * <p>
- * This implementation has a word size of 32 bits.
- * <p>
- * Implementation courtesy of Tito Pena.
- */
-public class RC532Engine
- implements BlockCipher
-{
- /*
- * the number of rounds to perform
- */
- private int _noRounds;
-
- /*
- * the expanded key array of size 2*(rounds + 1)
- */
- private int _S[];
-
- /*
- * our "magic constants" for 32 32
- *
- * Pw = Odd((e-2) * 2^wordsize)
- * Qw = Odd((o-2) * 2^wordsize)
- *
- * where e is the base of natural logarithms (2.718281828...)
- * and o is the golden ratio (1.61803398...)
- */
- private static final int P32 = 0xb7e15163;
- private static final int Q32 = 0x9e3779b9;
-
- private boolean forEncryption;
-
- /**
- * Create an instance of the RC5 encryption algorithm
- * and set some defaults
- */
- public RC532Engine()
- {
- _noRounds = 12; // the default
- _S = null;
- }
-
- public String getAlgorithmName()
- {
- return "RC5-32";
- }
-
- public int getBlockSize()
- {
- return 2 * 4;
- }
-
- /**
- * initialise a RC5-32 cipher.
- *
- * @param forEncryption whether or not we are for encryption.
- * @param params the parameters required to set up the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean forEncryption,
- CipherParameters params)
- {
- if (params instanceof RC5Parameters)
- {
- RC5Parameters p = (RC5Parameters)params;
-
- _noRounds = p.getRounds();
-
- setKey(p.getKey());
- }
- else if (params instanceof KeyParameter)
- {
- KeyParameter p = (KeyParameter)params;
-
- setKey(p.getKey());
- }
- else
- {
- throw new IllegalArgumentException("invalid parameter passed to RC532 init - " + params.getClass().getName());
- }
-
- this.forEncryption = forEncryption;
- }
-
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- return (forEncryption) ? encryptBlock(in, inOff, out, outOff)
- : decryptBlock(in, inOff, out, outOff);
- }
-
- public void reset()
- {
- }
-
- /**
- * Re-key the cipher.
- * <p>
- * @param key the key to be used
- */
- private void setKey(
- byte[] key)
- {
- //
- // KEY EXPANSION:
- //
- // There are 3 phases to the key expansion.
- //
- // Phase 1:
- // Copy the secret key K[0...b-1] into an array L[0..c-1] of
- // c = ceil(b/u), where u = 32/8 in little-endian order.
- // In other words, we fill up L using u consecutive key bytes
- // of K. Any unfilled byte positions in L are zeroed. In the
- // case that b = c = 0, set c = 1 and L[0] = 0.
- //
- int[] L = new int[(key.length + (4 - 1)) / 4];
-
- for (int i = 0; i != key.length; i++)
- {
- L[i / 4] += (key[i] & 0xff) << (8 * (i % 4));
- }
-
- //
- // Phase 2:
- // Initialize S to a particular fixed pseudo-random bit pattern
- // using an arithmetic progression modulo 2^wordsize determined
- // by the magic numbers, Pw & Qw.
- //
- _S = new int[2*(_noRounds + 1)];
-
- _S[0] = P32;
- for (int i=1; i < _S.length; i++)
- {
- _S[i] = (_S[i-1] + Q32);
- }
-
- //
- // Phase 3:
- // Mix in the user's secret key in 3 passes over the arrays S & L.
- // The max of the arrays sizes is used as the loop control
- //
- int iter;
-
- if (L.length > _S.length)
- {
- iter = 3 * L.length;
- }
- else
- {
- iter = 3 * _S.length;
- }
-
- int A = 0, B = 0;
- int i = 0, j = 0;
-
- for (int k = 0; k < iter; k++)
- {
- A = _S[i] = rotateLeft(_S[i] + A + B, 3);
- B = L[j] = rotateLeft(L[j] + A + B, A+B);
- i = (i+1) % _S.length;
- j = (j+1) % L.length;
- }
- }
-
- /**
- * Encrypt the given block starting at the given offset and place
- * the result in the provided buffer starting at the given offset.
- * <p>
- * @param in in byte buffer containing data to encrypt
- * @param inOff offset into src buffer
- * @param out out buffer where encrypted data is written
- * @param outOff offset into out buffer
- */
- private int encryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- int A = bytesToWord(in, inOff) + _S[0];
- int B = bytesToWord(in, inOff + 4) + _S[1];
-
- for (int i = 1; i <= _noRounds; i++)
- {
- A = rotateLeft(A ^ B, B) + _S[2*i];
- B = rotateLeft(B ^ A, A) + _S[2*i+1];
- }
-
- wordToBytes(A, out, outOff);
- wordToBytes(B, out, outOff + 4);
-
- return 2 * 4;
- }
-
- private int decryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- int A = bytesToWord(in, inOff);
- int B = bytesToWord(in, inOff + 4);
-
- for (int i = _noRounds; i >= 1; i--)
- {
- B = rotateRight(B - _S[2*i+1], A) ^ A;
- A = rotateRight(A - _S[2*i], B) ^ B;
- }
-
- wordToBytes(A - _S[0], out, outOff);
- wordToBytes(B - _S[1], out, outOff + 4);
-
- return 2 * 4;
- }
-
-
- //////////////////////////////////////////////////////////////
- //
- // PRIVATE Helper Methods
- //
- //////////////////////////////////////////////////////////////
-
- /**
- * Perform a left "spin" of the word. The rotation of the given
- * word <em>x</em> is rotated left by <em>y</em> bits.
- * Only the <em>lg(32)</em> low-order bits of <em>y</em>
- * are used to determine the rotation amount. Here it is
- * assumed that the wordsize used is a power of 2.
- * <p>
- * @param x word to rotate
- * @param y number of bits to rotate % 32
- */
- private int rotateLeft(int x, int y)
- {
- return ((x << (y & (32-1))) | (x >>> (32 - (y & (32-1)))));
- }
-
- /**
- * Perform a right "spin" of the word. The rotation of the given
- * word <em>x</em> is rotated left by <em>y</em> bits.
- * Only the <em>lg(32)</em> low-order bits of <em>y</em>
- * are used to determine the rotation amount. Here it is
- * assumed that the wordsize used is a power of 2.
- * <p>
- * @param x word to rotate
- * @param y number of bits to rotate % 32
- */
- private int rotateRight(int x, int y)
- {
- return ((x >>> (y & (32-1))) | (x << (32 - (y & (32-1)))));
- }
-
- private int bytesToWord(
- byte[] src,
- int srcOff)
- {
- return (src[srcOff] & 0xff) | ((src[srcOff + 1] & 0xff) << 8)
- | ((src[srcOff + 2] & 0xff) << 16) | ((src[srcOff + 3] & 0xff) << 24);
- }
-
- private void wordToBytes(
- int word,
- byte[] dst,
- int dstOff)
- {
- dst[dstOff] = (byte)word;
- dst[dstOff + 1] = (byte)(word >> 8);
- dst[dstOff + 2] = (byte)(word >> 16);
- dst[dstOff + 3] = (byte)(word >> 24);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/RC564Engine.java b/core/src/main/java/org/bouncycastle/crypto/engines/RC564Engine.java
deleted file mode 100644
index 2121a4bc..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/RC564Engine.java
+++ /dev/null
@@ -1,288 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.params.RC5Parameters;
-
-/**
- * The specification for RC5 came from the <code>RC5 Encryption Algorithm</code>
- * publication in RSA CryptoBytes, Spring of 1995.
- * <em>http://www.rsasecurity.com/rsalabs/cryptobytes</em>.
- * <p>
- * This implementation is set to work with a 64 bit word size.
- * <p>
- * Implementation courtesy of Tito Pena.
- */
-public class RC564Engine
- implements BlockCipher
-{
- private static final int wordSize = 64;
- private static final int bytesPerWord = wordSize / 8;
-
- /*
- * the number of rounds to perform
- */
- private int _noRounds;
-
- /*
- * the expanded key array of size 2*(rounds + 1)
- */
- private long _S[];
-
- /*
- * our "magic constants" for wordSize 62
- *
- * Pw = Odd((e-2) * 2^wordsize)
- * Qw = Odd((o-2) * 2^wordsize)
- *
- * where e is the base of natural logarithms (2.718281828...)
- * and o is the golden ratio (1.61803398...)
- */
- private static final long P64 = 0xb7e151628aed2a6bL;
- private static final long Q64 = 0x9e3779b97f4a7c15L;
-
- private boolean forEncryption;
-
- /**
- * Create an instance of the RC5 encryption algorithm
- * and set some defaults
- */
- public RC564Engine()
- {
- _noRounds = 12;
- _S = null;
- }
-
- public String getAlgorithmName()
- {
- return "RC5-64";
- }
-
- public int getBlockSize()
- {
- return 2 * bytesPerWord;
- }
-
- /**
- * initialise a RC5-64 cipher.
- *
- * @param forEncryption whether or not we are for encryption.
- * @param params the parameters required to set up the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean forEncryption,
- CipherParameters params)
- {
- if (!(params instanceof RC5Parameters))
- {
- throw new IllegalArgumentException("invalid parameter passed to RC564 init - " + params.getClass().getName());
- }
-
- RC5Parameters p = (RC5Parameters)params;
-
- this.forEncryption = forEncryption;
-
- _noRounds = p.getRounds();
-
- setKey(p.getKey());
- }
-
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- return (forEncryption) ? encryptBlock(in, inOff, out, outOff)
- : decryptBlock(in, inOff, out, outOff);
- }
-
- public void reset()
- {
- }
-
- /**
- * Re-key the cipher.
- * <p>
- * @param key the key to be used
- */
- private void setKey(
- byte[] key)
- {
- //
- // KEY EXPANSION:
- //
- // There are 3 phases to the key expansion.
- //
- // Phase 1:
- // Copy the secret key K[0...b-1] into an array L[0..c-1] of
- // c = ceil(b/u), where u = wordSize/8 in little-endian order.
- // In other words, we fill up L using u consecutive key bytes
- // of K. Any unfilled byte positions in L are zeroed. In the
- // case that b = c = 0, set c = 1 and L[0] = 0.
- //
- long[] L = new long[(key.length + (bytesPerWord - 1)) / bytesPerWord];
-
- for (int i = 0; i != key.length; i++)
- {
- L[i / bytesPerWord] += (long)(key[i] & 0xff) << (8 * (i % bytesPerWord));
- }
-
- //
- // Phase 2:
- // Initialize S to a particular fixed pseudo-random bit pattern
- // using an arithmetic progression modulo 2^wordsize determined
- // by the magic numbers, Pw & Qw.
- //
- _S = new long[2*(_noRounds + 1)];
-
- _S[0] = P64;
- for (int i=1; i < _S.length; i++)
- {
- _S[i] = (_S[i-1] + Q64);
- }
-
- //
- // Phase 3:
- // Mix in the user's secret key in 3 passes over the arrays S & L.
- // The max of the arrays sizes is used as the loop control
- //
- int iter;
-
- if (L.length > _S.length)
- {
- iter = 3 * L.length;
- }
- else
- {
- iter = 3 * _S.length;
- }
-
- long A = 0, B = 0;
- int i = 0, j = 0;
-
- for (int k = 0; k < iter; k++)
- {
- A = _S[i] = rotateLeft(_S[i] + A + B, 3);
- B = L[j] = rotateLeft(L[j] + A + B, A+B);
- i = (i+1) % _S.length;
- j = (j+1) % L.length;
- }
- }
-
- /**
- * Encrypt the given block starting at the given offset and place
- * the result in the provided buffer starting at the given offset.
- * <p>
- * @param in in byte buffer containing data to encrypt
- * @param inOff offset into src buffer
- * @param out out buffer where encrypted data is written
- * @param outOff offset into out buffer
- */
- private int encryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- long A = bytesToWord(in, inOff) + _S[0];
- long B = bytesToWord(in, inOff + bytesPerWord) + _S[1];
-
- for (int i = 1; i <= _noRounds; i++)
- {
- A = rotateLeft(A ^ B, B) + _S[2*i];
- B = rotateLeft(B ^ A, A) + _S[2*i+1];
- }
-
- wordToBytes(A, out, outOff);
- wordToBytes(B, out, outOff + bytesPerWord);
-
- return 2 * bytesPerWord;
- }
-
- private int decryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- long A = bytesToWord(in, inOff);
- long B = bytesToWord(in, inOff + bytesPerWord);
-
- for (int i = _noRounds; i >= 1; i--)
- {
- B = rotateRight(B - _S[2*i+1], A) ^ A;
- A = rotateRight(A - _S[2*i], B) ^ B;
- }
-
- wordToBytes(A - _S[0], out, outOff);
- wordToBytes(B - _S[1], out, outOff + bytesPerWord);
-
- return 2 * bytesPerWord;
- }
-
-
- //////////////////////////////////////////////////////////////
- //
- // PRIVATE Helper Methods
- //
- //////////////////////////////////////////////////////////////
-
- /**
- * Perform a left "spin" of the word. The rotation of the given
- * word <em>x</em> is rotated left by <em>y</em> bits.
- * Only the <em>lg(wordSize)</em> low-order bits of <em>y</em>
- * are used to determine the rotation amount. Here it is
- * assumed that the wordsize used is a power of 2.
- * <p>
- * @param x word to rotate
- * @param y number of bits to rotate % wordSize
- */
- private long rotateLeft(long x, long y)
- {
- return ((x << (y & (wordSize-1))) | (x >>> (wordSize - (y & (wordSize-1)))));
- }
-
- /**
- * Perform a right "spin" of the word. The rotation of the given
- * word <em>x</em> is rotated left by <em>y</em> bits.
- * Only the <em>lg(wordSize)</em> low-order bits of <em>y</em>
- * are used to determine the rotation amount. Here it is
- * assumed that the wordsize used is a power of 2.
- * <p>
- * @param x word to rotate
- * @param y number of bits to rotate % wordSize
- */
- private long rotateRight(long x, long y)
- {
- return ((x >>> (y & (wordSize-1))) | (x << (wordSize - (y & (wordSize-1)))));
- }
-
- private long bytesToWord(
- byte[] src,
- int srcOff)
- {
- long word = 0;
-
- for (int i = bytesPerWord - 1; i >= 0; i--)
- {
- word = (word << 8) + (src[i + srcOff] & 0xff);
- }
-
- return word;
- }
-
- private void wordToBytes(
- long word,
- byte[] dst,
- int dstOff)
- {
- for (int i = 0; i < bytesPerWord; i++)
- {
- dst[i + dstOff] = (byte)word;
- word >>>= 8;
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/RC6Engine.java b/core/src/main/java/org/bouncycastle/crypto/engines/RC6Engine.java
deleted file mode 100644
index bbf5d306..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/RC6Engine.java
+++ /dev/null
@@ -1,363 +0,0 @@
-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;
-
-/**
- * An RC6 engine.
- */
-public class RC6Engine
- implements BlockCipher
-{
- private static final int wordSize = 32;
- private static final int bytesPerWord = wordSize / 8;
-
- /*
- * the number of rounds to perform
- */
- private static final int _noRounds = 20;
-
- /*
- * the expanded key array of size 2*(rounds + 1)
- */
- private int _S[];
-
- /*
- * our "magic constants" for wordSize 32
- *
- * Pw = Odd((e-2) * 2^wordsize)
- * Qw = Odd((o-2) * 2^wordsize)
- *
- * where e is the base of natural logarithms (2.718281828...)
- * and o is the golden ratio (1.61803398...)
- */
- private static final int P32 = 0xb7e15163;
- private static final int Q32 = 0x9e3779b9;
-
- private static final int LGW = 5; // log2(32)
-
- private boolean forEncryption;
-
- /**
- * Create an instance of the RC6 encryption algorithm
- * and set some defaults
- */
- public RC6Engine()
- {
- _S = null;
- }
-
- public String getAlgorithmName()
- {
- return "RC6";
- }
-
- public int getBlockSize()
- {
- return 4 * bytesPerWord;
- }
-
- /**
- * initialise a RC5-32 cipher.
- *
- * @param forEncryption whether or not we are for encryption.
- * @param params the parameters required to set up the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean forEncryption,
- CipherParameters params)
- {
- if (!(params instanceof KeyParameter))
- {
- throw new IllegalArgumentException("invalid parameter passed to RC6 init - " + params.getClass().getName());
- }
-
- KeyParameter p = (KeyParameter)params;
- this.forEncryption = forEncryption;
- setKey(p.getKey());
- }
-
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- int blockSize = getBlockSize();
- if (_S == null)
- {
- throw new IllegalStateException("RC6 engine not initialised");
- }
- if ((inOff + blockSize) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
- if ((outOff + blockSize) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- return (forEncryption)
- ? encryptBlock(in, inOff, out, outOff)
- : decryptBlock(in, inOff, out, outOff);
- }
-
- public void reset()
- {
- }
-
- /**
- * Re-key the cipher.
- * <p>
- * @param key the key to be used
- */
- private void setKey(
- byte[] key)
- {
-
- //
- // KEY EXPANSION:
- //
- // There are 3 phases to the key expansion.
- //
- // Phase 1:
- // Copy the secret key K[0...b-1] into an array L[0..c-1] of
- // c = ceil(b/u), where u = wordSize/8 in little-endian order.
- // In other words, we fill up L using u consecutive key bytes
- // of K. Any unfilled byte positions in L are zeroed. In the
- // case that b = c = 0, set c = 1 and L[0] = 0.
- //
- // compute number of dwords
- int c = (key.length + (bytesPerWord - 1)) / bytesPerWord;
- if (c == 0)
- {
- c = 1;
- }
- int[] L = new int[(key.length + bytesPerWord - 1) / bytesPerWord];
-
- // load all key bytes into array of key dwords
- for (int i = key.length - 1; i >= 0; i--)
- {
- L[i / bytesPerWord] = (L[i / bytesPerWord] << 8) + (key[i] & 0xff);
- }
-
- //
- // Phase 2:
- // Key schedule is placed in a array of 2+2*ROUNDS+2 = 44 dwords.
- // Initialize S to a particular fixed pseudo-random bit pattern
- // using an arithmetic progression modulo 2^wordsize determined
- // by the magic numbers, Pw & Qw.
- //
- _S = new int[2+2*_noRounds+2];
-
- _S[0] = P32;
- for (int i=1; i < _S.length; i++)
- {
- _S[i] = (_S[i-1] + Q32);
- }
-
- //
- // Phase 3:
- // Mix in the user's secret key in 3 passes over the arrays S & L.
- // The max of the arrays sizes is used as the loop control
- //
- int iter;
-
- if (L.length > _S.length)
- {
- iter = 3 * L.length;
- }
- else
- {
- iter = 3 * _S.length;
- }
-
- int A = 0;
- int B = 0;
- int i = 0, j = 0;
-
- for (int k = 0; k < iter; k++)
- {
- A = _S[i] = rotateLeft(_S[i] + A + B, 3);
- B = L[j] = rotateLeft(L[j] + A + B, A+B);
- i = (i+1) % _S.length;
- j = (j+1) % L.length;
- }
- }
-
- private int encryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- // load A,B,C and D registers from in.
- int A = bytesToWord(in, inOff);
- int B = bytesToWord(in, inOff + bytesPerWord);
- int C = bytesToWord(in, inOff + bytesPerWord*2);
- int D = bytesToWord(in, inOff + bytesPerWord*3);
-
- // Do pseudo-round #0: pre-whitening of B and D
- B += _S[0];
- D += _S[1];
-
- // perform round #1,#2 ... #ROUNDS of encryption
- for (int i = 1; i <= _noRounds; i++)
- {
- int t = 0,u = 0;
-
- t = B*(2*B+1);
- t = rotateLeft(t,5);
-
- u = D*(2*D+1);
- u = rotateLeft(u,5);
-
- A ^= t;
- A = rotateLeft(A,u);
- A += _S[2*i];
-
- C ^= u;
- C = rotateLeft(C,t);
- C += _S[2*i+1];
-
- int temp = A;
- A = B;
- B = C;
- C = D;
- D = temp;
- }
- // do pseudo-round #(ROUNDS+1) : post-whitening of A and C
- A += _S[2*_noRounds+2];
- C += _S[2*_noRounds+3];
-
- // store A, B, C and D registers to out
- wordToBytes(A, out, outOff);
- wordToBytes(B, out, outOff + bytesPerWord);
- wordToBytes(C, out, outOff + bytesPerWord*2);
- wordToBytes(D, out, outOff + bytesPerWord*3);
-
- return 4 * bytesPerWord;
- }
-
- private int decryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- // load A,B,C and D registers from out.
- int A = bytesToWord(in, inOff);
- int B = bytesToWord(in, inOff + bytesPerWord);
- int C = bytesToWord(in, inOff + bytesPerWord*2);
- int D = bytesToWord(in, inOff + bytesPerWord*3);
-
- // Undo pseudo-round #(ROUNDS+1) : post whitening of A and C
- C -= _S[2*_noRounds+3];
- A -= _S[2*_noRounds+2];
-
- // Undo round #ROUNDS, .., #2,#1 of encryption
- for (int i = _noRounds; i >= 1; i--)
- {
- int t=0,u = 0;
-
- int temp = D;
- D = C;
- C = B;
- B = A;
- A = temp;
-
- t = B*(2*B+1);
- t = rotateLeft(t, LGW);
-
- u = D*(2*D+1);
- u = rotateLeft(u, LGW);
-
- C -= _S[2*i+1];
- C = rotateRight(C,t);
- C ^= u;
-
- A -= _S[2*i];
- A = rotateRight(A,u);
- A ^= t;
-
- }
- // Undo pseudo-round #0: pre-whitening of B and D
- D -= _S[1];
- B -= _S[0];
-
- wordToBytes(A, out, outOff);
- wordToBytes(B, out, outOff + bytesPerWord);
- wordToBytes(C, out, outOff + bytesPerWord*2);
- wordToBytes(D, out, outOff + bytesPerWord*3);
-
- return 4 * bytesPerWord;
- }
-
-
- //////////////////////////////////////////////////////////////
- //
- // PRIVATE Helper Methods
- //
- //////////////////////////////////////////////////////////////
-
- /**
- * Perform a left "spin" of the word. The rotation of the given
- * word <em>x</em> is rotated left by <em>y</em> bits.
- * Only the <em>lg(wordSize)</em> low-order bits of <em>y</em>
- * are used to determine the rotation amount. Here it is
- * assumed that the wordsize used is 32.
- * <p>
- * @param x word to rotate
- * @param y number of bits to rotate % wordSize
- */
- private int rotateLeft(int x, int y)
- {
- return (x << y) | (x >>> -y);
- }
-
- /**
- * Perform a right "spin" of the word. The rotation of the given
- * word <em>x</em> is rotated left by <em>y</em> bits.
- * Only the <em>lg(wordSize)</em> low-order bits of <em>y</em>
- * are used to determine the rotation amount. Here it is
- * assumed that the wordsize used is a power of 2.
- * <p>
- * @param x word to rotate
- * @param y number of bits to rotate % wordSize
- */
- private int rotateRight(int x, int y)
- {
- return (x >>> y) | (x << -y);
- }
-
- private int bytesToWord(
- byte[] src,
- int srcOff)
- {
- int word = 0;
-
- for (int i = bytesPerWord - 1; i >= 0; i--)
- {
- word = (word << 8) + (src[i + srcOff] & 0xff);
- }
-
- return word;
- }
-
- private void wordToBytes(
- int word,
- byte[] dst,
- int dstOff)
- {
- for (int i = 0; i < bytesPerWord; i++)
- {
- dst[i + dstOff] = (byte)word;
- word >>>= 8;
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/RFC3211WrapEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/RFC3211WrapEngine.java
deleted file mode 100644
index 0d10eeb5..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/RFC3211WrapEngine.java
+++ /dev/null
@@ -1,175 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.Wrapper;
-import org.bouncycastle.crypto.modes.CBCBlockCipher;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-
-import java.security.SecureRandom;
-
-/**
- * an implementation of the RFC 3211 Key Wrap
- * Specification.
- */
-public class RFC3211WrapEngine
- implements Wrapper
-{
- private CBCBlockCipher engine;
- private ParametersWithIV param;
- private boolean forWrapping;
- private SecureRandom rand;
-
- public RFC3211WrapEngine(BlockCipher engine)
- {
- this.engine = new CBCBlockCipher(engine);
- }
-
- public void init(
- boolean forWrapping,
- CipherParameters param)
- {
- this.forWrapping = forWrapping;
-
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom p = (ParametersWithRandom)param;
-
- rand = p.getRandom();
- this.param = (ParametersWithIV)p.getParameters();
- }
- else
- {
- if (forWrapping)
- {
- rand = new SecureRandom();
- }
-
- this.param = (ParametersWithIV)param;
- }
- }
-
- public String getAlgorithmName()
- {
- return engine.getUnderlyingCipher().getAlgorithmName() + "/RFC3211Wrap";
- }
-
- public byte[] wrap(
- byte[] in,
- int inOff,
- int inLen)
- {
- if (!forWrapping)
- {
- throw new IllegalStateException("not set for wrapping");
- }
-
- engine.init(true, param);
-
- int blockSize = engine.getBlockSize();
- byte[] cekBlock;
-
- if (inLen + 4 < blockSize * 2)
- {
- cekBlock = new byte[blockSize * 2];
- }
- else
- {
- cekBlock = new byte[(inLen + 4) % blockSize == 0 ? inLen + 4 : ((inLen + 4) / blockSize + 1) * blockSize];
- }
-
- cekBlock[0] = (byte)inLen;
- cekBlock[1] = (byte)~in[inOff];
- cekBlock[2] = (byte)~in[inOff + 1];
- cekBlock[3] = (byte)~in[inOff + 2];
-
- System.arraycopy(in, inOff, cekBlock, 4, inLen);
-
- for (int i = inLen + 4; i < cekBlock.length; i++)
- {
- cekBlock[i] = (byte)rand.nextInt();
- }
-
- for (int i = 0; i < cekBlock.length; i += blockSize)
- {
- engine.processBlock(cekBlock, i, cekBlock, i);
- }
-
- for (int i = 0; i < cekBlock.length; i += blockSize)
- {
- engine.processBlock(cekBlock, i, cekBlock, i);
- }
-
- return cekBlock;
- }
-
- public byte[] unwrap(
- byte[] in,
- int inOff,
- int inLen)
- throws InvalidCipherTextException
- {
- if (forWrapping)
- {
- throw new IllegalStateException("not set for unwrapping");
- }
-
- int blockSize = engine.getBlockSize();
-
- if (inLen < 2 * blockSize)
- {
- throw new InvalidCipherTextException("input too short");
- }
-
- byte[] cekBlock = new byte[inLen];
- byte[] iv = new byte[blockSize];
-
- System.arraycopy(in, inOff, cekBlock, 0, inLen);
- System.arraycopy(in, inOff, iv, 0, iv.length);
-
- engine.init(false, new ParametersWithIV(param.getParameters(), iv));
-
- for (int i = blockSize; i < cekBlock.length; i += blockSize)
- {
- engine.processBlock(cekBlock, i, cekBlock, i);
- }
-
- System.arraycopy(cekBlock, cekBlock.length - iv.length, iv, 0, iv.length);
-
- engine.init(false, new ParametersWithIV(param.getParameters(), iv));
-
- engine.processBlock(cekBlock, 0, cekBlock, 0);
-
- engine.init(false, param);
-
- for (int i = 0; i < cekBlock.length; i += blockSize)
- {
- engine.processBlock(cekBlock, i, cekBlock, i);
- }
-
- if ((cekBlock[0] & 0xff) > cekBlock.length - 4)
- {
- throw new InvalidCipherTextException("wrapped key corrupted");
- }
-
- byte[] key = new byte[cekBlock[0] & 0xff];
-
- System.arraycopy(cekBlock, 4, key, 0, cekBlock[0]);
-
- // Note: Using constant time comparison
- int nonEqual = 0;
- for (int i = 0; i != 3; i++)
- {
- byte check = (byte)~cekBlock[1 + i];
- nonEqual |= (check ^ key[i]);
- }
- if (nonEqual != 0)
- {
- throw new InvalidCipherTextException("wrapped key fails checksum");
- }
-
- return key;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java
deleted file mode 100644
index cfd86fb6..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java
+++ /dev/null
@@ -1,177 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.Wrapper;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.util.Arrays;
-
-/**
- * an implementation of the AES Key Wrapper from the NIST Key Wrap
- * Specification as described in RFC 3394.
- * <p>
- * For further details see: <a href="http://www.ietf.org/rfc/rfc3394.txt">http://www.ietf.org/rfc/rfc3394.txt</a>
- * and <a href="http://csrc.nist.gov/encryption/kms/key-wrap.pdf">http://csrc.nist.gov/encryption/kms/key-wrap.pdf</a>.
- */
-public class RFC3394WrapEngine
- implements Wrapper
-{
- private BlockCipher engine;
- private KeyParameter param;
- private boolean forWrapping;
-
- private byte[] iv = {
- (byte)0xa6, (byte)0xa6, (byte)0xa6, (byte)0xa6,
- (byte)0xa6, (byte)0xa6, (byte)0xa6, (byte)0xa6 };
-
- public RFC3394WrapEngine(BlockCipher engine)
- {
- this.engine = engine;
- }
-
- public void init(
- boolean forWrapping,
- CipherParameters param)
- {
- this.forWrapping = forWrapping;
-
- if (param instanceof ParametersWithRandom)
- {
- param = ((ParametersWithRandom) param).getParameters();
- }
-
- if (param instanceof KeyParameter)
- {
- this.param = (KeyParameter)param;
- }
- else if (param instanceof ParametersWithIV)
- {
- this.iv = ((ParametersWithIV)param).getIV();
- this.param = (KeyParameter)((ParametersWithIV) param).getParameters();
- if (this.iv.length != 8)
- {
- throw new IllegalArgumentException("IV not equal to 8");
- }
- }
- }
-
- public String getAlgorithmName()
- {
- return engine.getAlgorithmName();
- }
-
- public byte[] wrap(
- byte[] in,
- int inOff,
- int inLen)
- {
- if (!forWrapping)
- {
- throw new IllegalStateException("not set for wrapping");
- }
-
- int n = inLen / 8;
-
- if ((n * 8) != inLen)
- {
- throw new DataLengthException("wrap data must be a multiple of 8 bytes");
- }
-
- byte[] block = new byte[inLen + iv.length];
- byte[] buf = new byte[8 + iv.length];
-
- System.arraycopy(iv, 0, block, 0, iv.length);
- System.arraycopy(in, inOff, block, iv.length, inLen);
-
- engine.init(true, param);
-
- for (int j = 0; j != 6; j++)
- {
- for (int i = 1; i <= n; i++)
- {
- System.arraycopy(block, 0, buf, 0, iv.length);
- System.arraycopy(block, 8 * i, buf, iv.length, 8);
- engine.processBlock(buf, 0, buf, 0);
-
- int t = n * j + i;
- for (int k = 1; t != 0; k++)
- {
- byte v = (byte)t;
-
- buf[iv.length - k] ^= v;
-
- t >>>= 8;
- }
-
- System.arraycopy(buf, 0, block, 0, 8);
- System.arraycopy(buf, 8, block, 8 * i, 8);
- }
- }
-
- return block;
- }
-
- public byte[] unwrap(
- byte[] in,
- int inOff,
- int inLen)
- throws InvalidCipherTextException
- {
- if (forWrapping)
- {
- throw new IllegalStateException("not set for unwrapping");
- }
-
- int n = inLen / 8;
-
- if ((n * 8) != inLen)
- {
- throw new InvalidCipherTextException("unwrap data must be a multiple of 8 bytes");
- }
-
- byte[] block = new byte[inLen - iv.length];
- byte[] a = new byte[iv.length];
- byte[] buf = new byte[8 + 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);
-
- n = n - 1;
-
- for (int j = 5; j >= 0; j--)
- {
- for (int i = n; i >= 1; i--)
- {
- System.arraycopy(a, 0, buf, 0, iv.length);
- System.arraycopy(block, 8 * (i - 1), buf, iv.length, 8);
-
- int t = n * j + i;
- for (int k = 1; t != 0; k++)
- {
- byte v = (byte)t;
-
- buf[iv.length - k] ^= v;
-
- t >>>= 8;
- }
-
- engine.processBlock(buf, 0, buf, 0);
- System.arraycopy(buf, 0, a, 0, 8);
- System.arraycopy(buf, 8, block, 8 * (i - 1), 8);
- }
- }
-
- if (!Arrays.constantTimeAreEqual(a, iv))
- {
- throw new InvalidCipherTextException("checksum failed");
- }
-
- return block;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/RFC5649WrapEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/RFC5649WrapEngine.java
deleted file mode 100644
index 548969ac..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/RFC5649WrapEngine.java
+++ /dev/null
@@ -1,294 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.Wrapper;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Pack;
-
-/**
- * An implementation of the AES Key Wrap with Padding specification
- * as described in RFC 5649.
- * <p>
- * For details on the specification see:
- * <a href="https://tools.ietf.org/html/rfc5649">https://tools.ietf.org/html/rfc5649</a>
- * </p>
- */
-public class RFC5649WrapEngine
- implements Wrapper
-{
- private BlockCipher engine;
- private KeyParameter param;
- private boolean forWrapping;
-
- // The AIV as defined in the RFC
- private byte[] highOrderIV = {(byte)0xa6, (byte)0x59, (byte)0x59, (byte)0xa6};
- private byte[] preIV = highOrderIV;
-
- private byte[] extractedAIV = null;
-
- public RFC5649WrapEngine(BlockCipher engine)
- {
- this.engine = engine;
- }
-
- public void init(boolean forWrapping, CipherParameters param)
- {
- this.forWrapping = forWrapping;
-
- if (param instanceof ParametersWithRandom)
- {
- param = ((ParametersWithRandom)param).getParameters();
- }
-
- if (param instanceof KeyParameter)
- {
- this.param = (KeyParameter)param;
- }
- else if (param instanceof ParametersWithIV)
- {
- this.preIV = ((ParametersWithIV)param).getIV();
- this.param = (KeyParameter)((ParametersWithIV)param).getParameters();
- if (this.preIV.length != 4)
- {
- throw new IllegalArgumentException("IV length not equal to 4");
- }
- }
- }
-
- public String getAlgorithmName()
- {
- return engine.getAlgorithmName();
- }
-
- /**
- * Pads the plaintext (i.e., the key to be wrapped)
- * as per section 4.1 of RFC 5649.
- *
- * @param plaintext The key being wrapped.
- * @return The padded key.
- */
- private byte[] padPlaintext(byte[] plaintext)
- {
- int plaintextLength = plaintext.length;
- int numOfZerosToAppend = (8 - (plaintextLength % 8)) % 8;
- byte[] paddedPlaintext = new byte[plaintextLength + numOfZerosToAppend];
- System.arraycopy(plaintext, 0, paddedPlaintext, 0, plaintextLength);
- if (numOfZerosToAppend != 0)
- {
- // plaintext (i.e., key to be wrapped) does not have
- // a multiple of 8 octet blocks so it must be padded
- byte[] zeros = new byte[numOfZerosToAppend];
- System.arraycopy(zeros, 0, paddedPlaintext, plaintextLength, numOfZerosToAppend);
- }
- return paddedPlaintext;
- }
-
- public byte[] wrap(byte[] in, int inOff, int inLen)
- {
- if (!forWrapping)
- {
- throw new IllegalStateException("not set for wrapping");
- }
- byte[] iv = new byte[8];
-
- // MLI = size of key to be wrapped
- byte[] mli = Pack.intToBigEndian(inLen);
- // copy in the fixed portion of the AIV
- System.arraycopy(preIV, 0, iv, 0, preIV.length);
- // copy in the MLI after the AIV
- System.arraycopy(mli, 0, iv, preIV.length, mli.length);
-
- // get the relevant plaintext to be wrapped
- byte[] relevantPlaintext = new byte[inLen];
- System.arraycopy(in, inOff, relevantPlaintext, 0, inLen);
- byte[] paddedPlaintext = padPlaintext(relevantPlaintext);
-
- if (paddedPlaintext.length == 8)
- {
- // if the padded plaintext contains exactly 8 octets,
- // then prepend iv and encrypt using AES in ECB mode.
-
- // prepend the IV to the plaintext
- byte[] paddedPlainTextWithIV = new byte[paddedPlaintext.length + iv.length];
- System.arraycopy(iv, 0, paddedPlainTextWithIV, 0, iv.length);
- System.arraycopy(paddedPlaintext, 0, paddedPlainTextWithIV, iv.length, paddedPlaintext.length);
-
- engine.init(true, param);
- for (int i = 0; i < paddedPlainTextWithIV.length; i += engine.getBlockSize())
- {
- engine.processBlock(paddedPlainTextWithIV, i, paddedPlainTextWithIV, i);
- }
-
- return paddedPlainTextWithIV;
- }
- else
- {
- // otherwise, apply the RFC 3394 wrap to
- // the padded plaintext with the new IV
- Wrapper wrapper = new RFC3394WrapEngine(engine);
- ParametersWithIV paramsWithIV = new ParametersWithIV(param, iv);
- wrapper.init(true, paramsWithIV);
- return wrapper.wrap(paddedPlaintext, inOff, paddedPlaintext.length);
- }
-
- }
-
- public byte[] unwrap(byte[] in, int inOff, int inLen)
- throws InvalidCipherTextException
- {
- if (forWrapping)
- {
- throw new IllegalStateException("not set for unwrapping");
- }
-
- int n = inLen / 8;
-
- if ((n * 8) != inLen)
- {
- throw new InvalidCipherTextException("unwrap data must be a multiple of 8 bytes");
- }
-
- if (n == 1)
- {
- throw new InvalidCipherTextException("unwrap data must be at least 16 bytes");
- }
-
- byte[] relevantCiphertext = new byte[inLen];
- System.arraycopy(in, inOff, relevantCiphertext, 0, inLen);
- byte[] decrypted = new byte[inLen];
- byte[] paddedPlaintext;
-
- if (n == 2)
- {
- // When there are exactly two 64-bit blocks of ciphertext,
- // they are decrypted as a single block using AES in ECB.
- engine.init(false, param);
- for (int i = 0; i < relevantCiphertext.length; i += engine.getBlockSize())
- {
- engine.processBlock(relevantCiphertext, i, decrypted, i);
- }
-
- // extract the AIV
- extractedAIV = new byte[8];
- System.arraycopy(decrypted, 0, extractedAIV, 0, extractedAIV.length);
- paddedPlaintext = new byte[decrypted.length - extractedAIV.length];
- System.arraycopy(decrypted, extractedAIV.length, paddedPlaintext, 0, paddedPlaintext.length);
- }
- else
- {
- // Otherwise, unwrap as per RFC 3394 but don't check IV the same way
- decrypted = rfc3394UnwrapNoIvCheck(in, inOff, inLen);
- paddedPlaintext = decrypted;
- }
-
- // Decompose the extracted AIV to the fixed portion and the MLI
- byte[] extractedHighOrderAIV = new byte[4];
- byte[] mliBytes = new byte[4];
- System.arraycopy(extractedAIV, 0, extractedHighOrderAIV, 0, extractedHighOrderAIV.length);
- System.arraycopy(extractedAIV, extractedHighOrderAIV.length, mliBytes, 0, mliBytes.length);
- int mli = Pack.bigEndianToInt(mliBytes, 0);
-
- // Even if a check fails we still continue and check everything
- // else in order to avoid certain timing based side-channel attacks.
- boolean isValid = true;
-
- // Check the fixed portion of the AIV
- if (!Arrays.constantTimeAreEqual(extractedHighOrderAIV, preIV))
- {
- isValid = false;
- }
-
- // Check the MLI against the actual length
- int upperBound = paddedPlaintext.length;
- int lowerBound = upperBound - 8;
- if (mli <= lowerBound)
- {
- isValid = false;
- }
- if (mli > upperBound)
- {
- isValid = false;
- }
-
- // Check the number of padded zeros
- int expectedZeros = upperBound - mli;
- byte[] zeros = new byte[expectedZeros];
- byte[] pad = new byte[expectedZeros];
- System.arraycopy(paddedPlaintext, paddedPlaintext.length - expectedZeros, pad, 0, expectedZeros);
- if (!Arrays.constantTimeAreEqual(pad, zeros))
- {
- isValid = false;
- }
-
- // Extract the plaintext from the padded plaintext
- byte[] plaintext = new byte[mli];
- System.arraycopy(paddedPlaintext, 0, plaintext, 0, plaintext.length);
-
- if (!isValid)
- {
- throw new InvalidCipherTextException("checksum failed");
- }
-
- return plaintext;
- }
-
- /**
- * Performs steps 1 and 2 of the unwrap process defined in RFC 3394.
- * This code is duplicated from RFC3394WrapEngine because that class
- * will throw an error during unwrap because the IV won't match up.
- *
- * @param in
- * @param inOff
- * @param inLen
- * @return Unwrapped data.
- */
- private byte[] rfc3394UnwrapNoIvCheck(byte[] in, int inOff, int inLen)
- {
- byte[] iv = new byte[8];
- byte[] block = new byte[inLen - iv.length];
- byte[] a = new byte[iv.length];
- byte[] buf = new byte[8 + 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);
-
- int n = inLen / 8;
- n = n - 1;
-
- for (int j = 5; j >= 0; j--)
- {
- for (int i = n; i >= 1; i--)
- {
- System.arraycopy(a, 0, buf, 0, iv.length);
- System.arraycopy(block, 8 * (i - 1), buf, iv.length, 8);
-
- int t = n * j + i;
- for (int k = 1; t != 0; k++)
- {
- byte v = (byte)t;
-
- buf[iv.length - k] ^= v;
-
- t >>>= 8;
- }
-
- engine.processBlock(buf, 0, buf, 0);
- System.arraycopy(buf, 0, a, 0, 8);
- System.arraycopy(buf, 8, block, 8 * (i - 1), 8);
- }
- }
-
- // set the extracted AIV
- extractedAIV = a;
-
- return block;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java
deleted file mode 100644
index c9765bf8..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java
+++ /dev/null
@@ -1,126 +0,0 @@
-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;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
-import org.bouncycastle.util.BigIntegers;
-
-/**
- * this does your basic RSA algorithm with blinding
- */
-public class RSABlindedEngine
- implements AsymmetricBlockCipher
-{
- private static final BigInteger ONE = BigInteger.valueOf(1);
-
- private RSACoreEngine core = new RSACoreEngine();
- private RSAKeyParameters key;
- private SecureRandom random;
-
- /**
- * initialise the RSA engine.
- *
- * @param forEncryption true if we are encrypting, false otherwise.
- * @param param the necessary RSA key parameters.
- */
- public void init(
- boolean forEncryption,
- CipherParameters param)
- {
- core.init(forEncryption, param);
-
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- key = (RSAKeyParameters)rParam.getParameters();
- random = rParam.getRandom();
- }
- else
- {
- key = (RSAKeyParameters)param;
- random = new SecureRandom();
- }
- }
-
- /**
- * Return the maximum size for an input block to this engine.
- * For RSA this is always one byte less than the key size on
- * encryption, and the same length as the key size on decryption.
- *
- * @return maximum size for an input block.
- */
- public int getInputBlockSize()
- {
- return core.getInputBlockSize();
- }
-
- /**
- * Return the maximum size for an output block to this engine.
- * For RSA this is always one byte less than the key size on
- * decryption, and the same length as the key size on encryption.
- *
- * @return maximum size for an output block.
- */
- public int getOutputBlockSize()
- {
- return core.getOutputBlockSize();
- }
-
- /**
- * Process a single block using the basic RSA algorithm.
- *
- * @param in the input array.
- * @param inOff the offset into the input buffer where the data starts.
- * @param inLen the length of the data to be processed.
- * @return the result of the RSA process.
- * @exception DataLengthException the input block is too large.
- */
- public byte[] processBlock(
- byte[] in,
- int inOff,
- int inLen)
- {
- if (key == null)
- {
- throw new IllegalStateException("RSA engine not initialised");
- }
-
- BigInteger input = core.convertInput(in, inOff, inLen);
-
- BigInteger result;
- if (key instanceof RSAPrivateCrtKeyParameters)
- {
- RSAPrivateCrtKeyParameters k = (RSAPrivateCrtKeyParameters)key;
-
- BigInteger e = k.getPublicExponent();
- if (e != null) // can't do blinding without a public exponent
- {
- BigInteger m = k.getModulus();
- BigInteger r = BigIntegers.createRandomInRange(ONE, m.subtract(ONE), random);
-
- BigInteger blindedInput = r.modPow(e, m).multiply(input).mod(m);
- BigInteger blindedResult = core.processBlock(blindedInput);
-
- BigInteger rInv = r.modInverse(m);
- result = blindedResult.multiply(rInv).mod(m);
- }
- else
- {
- result = core.processBlock(input);
- }
- }
- else
- {
- result = core.processBlock(input);
- }
-
- return core.convertOutput(result);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/RSABlindingEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/RSABlindingEngine.java
deleted file mode 100644
index a8ecb9bf..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/RSABlindingEngine.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.params.RSABlindingParameters;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-
-import java.math.BigInteger;
-
-/**
- * This does your basic RSA Chaum's blinding and unblinding as outlined in
- * "Handbook of Applied Cryptography", page 475. You need to use this if you are
- * trying to get another party to generate signatures without them being aware
- * of the message they are signing.
- */
-public class RSABlindingEngine
- implements AsymmetricBlockCipher
-{
- private RSACoreEngine core = new RSACoreEngine();
-
- private RSAKeyParameters key;
- private BigInteger blindingFactor;
-
- private boolean forEncryption;
-
- /**
- * Initialise the blinding engine.
- *
- * @param forEncryption true if we are encrypting (blinding), false otherwise.
- * @param param the necessary RSA key parameters.
- */
- public void init(
- boolean forEncryption,
- CipherParameters param)
- {
- RSABlindingParameters p;
-
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- p = (RSABlindingParameters)rParam.getParameters();
- }
- else
- {
- p = (RSABlindingParameters)param;
- }
-
- core.init(forEncryption, p.getPublicKey());
-
- this.forEncryption = forEncryption;
- this.key = p.getPublicKey();
- this.blindingFactor = p.getBlindingFactor();
- }
-
- /**
- * Return the maximum size for an input block to this engine.
- * For RSA this is always one byte less than the key size on
- * encryption, and the same length as the key size on decryption.
- *
- * @return maximum size for an input block.
- */
- public int getInputBlockSize()
- {
- return core.getInputBlockSize();
- }
-
- /**
- * Return the maximum size for an output block to this engine.
- * For RSA this is always one byte less than the key size on
- * decryption, and the same length as the key size on encryption.
- *
- * @return maximum size for an output block.
- */
- public int getOutputBlockSize()
- {
- return core.getOutputBlockSize();
- }
-
- /**
- * Process a single block using the RSA blinding algorithm.
- *
- * @param in the input array.
- * @param inOff the offset into the input buffer where the data starts.
- * @param inLen the length of the data to be processed.
- * @return the result of the RSA process.
- * @throws DataLengthException the input block is too large.
- */
- public byte[] processBlock(
- byte[] in,
- int inOff,
- int inLen)
- {
- BigInteger msg = core.convertInput(in, inOff, inLen);
-
- if (forEncryption)
- {
- msg = blindMessage(msg);
- }
- else
- {
- msg = unblindMessage(msg);
- }
-
- return core.convertOutput(msg);
- }
-
- /*
- * Blind message with the blind factor.
- */
- private BigInteger blindMessage(
- BigInteger msg)
- {
- BigInteger blindMsg = blindingFactor;
- blindMsg = msg.multiply(blindMsg.modPow(key.getExponent(), key.getModulus()));
- blindMsg = blindMsg.mod(key.getModulus());
-
- return blindMsg;
- }
-
- /*
- * Unblind the message blinded with the blind factor.
- */
- private BigInteger unblindMessage(
- BigInteger blindedMsg)
- {
- BigInteger m = key.getModulus();
- BigInteger msg = blindedMsg;
- BigInteger blindFactorInverse = blindingFactor.modInverse(m);
- msg = msg.multiply(blindFactorInverse);
- msg = msg.mod(m);
-
- return msg;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/RSACoreEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/RSACoreEngine.java
deleted file mode 100644
index 510cd5a5..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/RSACoreEngine.java
+++ /dev/null
@@ -1,203 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
-
-import java.math.BigInteger;
-
-/**
- * this does your basic RSA algorithm.
- */
-class RSACoreEngine
-{
- private RSAKeyParameters key;
- private boolean forEncryption;
-
- /**
- * initialise the RSA engine.
- *
- * @param forEncryption true if we are encrypting, false otherwise.
- * @param param the necessary RSA key parameters.
- */
- public void init(
- boolean forEncryption,
- CipherParameters param)
- {
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- key = (RSAKeyParameters)rParam.getParameters();
- }
- else
- {
- key = (RSAKeyParameters)param;
- }
-
- this.forEncryption = forEncryption;
- }
-
- /**
- * Return the maximum size for an input block to this engine.
- * For RSA this is always one byte less than the key size on
- * encryption, and the same length as the key size on decryption.
- *
- * @return maximum size for an input block.
- */
- public int getInputBlockSize()
- {
- int bitSize = key.getModulus().bitLength();
-
- if (forEncryption)
- {
- return (bitSize + 7) / 8 - 1;
- }
- else
- {
- return (bitSize + 7) / 8;
- }
- }
-
- /**
- * Return the maximum size for an output block to this engine.
- * For RSA this is always one byte less than the key size on
- * decryption, and the same length as the key size on encryption.
- *
- * @return maximum size for an output block.
- */
- public int getOutputBlockSize()
- {
- int bitSize = key.getModulus().bitLength();
-
- if (forEncryption)
- {
- return (bitSize + 7) / 8;
- }
- else
- {
- return (bitSize + 7) / 8 - 1;
- }
- }
-
- public BigInteger convertInput(
- byte[] in,
- int inOff,
- int inLen)
- {
- if (inLen > (getInputBlockSize() + 1))
- {
- throw new DataLengthException("input too large for RSA cipher.");
- }
- else if (inLen == (getInputBlockSize() + 1) && !forEncryption)
- {
- throw new DataLengthException("input too large for RSA cipher.");
- }
-
- byte[] block;
-
- if (inOff != 0 || inLen != in.length)
- {
- block = new byte[inLen];
-
- System.arraycopy(in, inOff, block, 0, inLen);
- }
- else
- {
- block = in;
- }
-
- BigInteger res = new BigInteger(1, block);
- if (res.compareTo(key.getModulus()) >= 0)
- {
- throw new DataLengthException("input too large for RSA cipher.");
- }
-
- return res;
- }
-
- public byte[] convertOutput(
- BigInteger result)
- {
- byte[] output = result.toByteArray();
-
- if (forEncryption)
- {
- if (output[0] == 0 && output.length > getOutputBlockSize()) // have ended up with an extra zero byte, copy down.
- {
- byte[] tmp = new byte[output.length - 1];
-
- System.arraycopy(output, 1, tmp, 0, tmp.length);
-
- return tmp;
- }
-
- if (output.length < getOutputBlockSize()) // have ended up with less bytes than normal, lengthen
- {
- byte[] tmp = new byte[getOutputBlockSize()];
-
- System.arraycopy(output, 0, tmp, tmp.length - output.length, output.length);
-
- return tmp;
- }
- }
- else
- {
- if (output[0] == 0) // have ended up with an extra zero byte, copy down.
- {
- byte[] tmp = new byte[output.length - 1];
-
- System.arraycopy(output, 1, tmp, 0, tmp.length);
-
- return tmp;
- }
- }
-
- return output;
- }
-
- public BigInteger processBlock(BigInteger input)
- {
- if (key instanceof RSAPrivateCrtKeyParameters)
- {
- //
- // we have the extra factors, use the Chinese Remainder Theorem - the author
- // wishes to express his thanks to Dirk Bonekaemper at rtsffm.com for
- // advice regarding the expression of this.
- //
- RSAPrivateCrtKeyParameters crtKey = (RSAPrivateCrtKeyParameters)key;
-
- BigInteger p = crtKey.getP();
- BigInteger q = crtKey.getQ();
- BigInteger dP = crtKey.getDP();
- BigInteger dQ = crtKey.getDQ();
- BigInteger qInv = crtKey.getQInv();
-
- BigInteger mP, mQ, h, m;
-
- // mP = ((input mod p) ^ dP)) mod p
- mP = (input.remainder(p)).modPow(dP, p);
-
- // mQ = ((input mod q) ^ dQ)) mod q
- mQ = (input.remainder(q)).modPow(dQ, q);
-
- // h = qInv * (mP - mQ) mod p
- h = mP.subtract(mQ);
- h = h.multiply(qInv);
- h = h.mod(p); // mod (in Java) returns the positive residual
-
- // m = h * q + mQ
- m = h.multiply(q);
- m = m.add(mQ);
-
- return m;
- }
- else
- {
- return input.modPow(
- key.getExponent(), key.getModulus());
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/RSAEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/RSAEngine.java
deleted file mode 100644
index 009dcd43..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/RSAEngine.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-
-/**
- * this does your basic RSA algorithm.
- */
-public class RSAEngine
- implements AsymmetricBlockCipher
-{
- private RSACoreEngine core;
-
- /**
- * initialise the RSA engine.
- *
- * @param forEncryption true if we are encrypting, false otherwise.
- * @param param the necessary RSA key parameters.
- */
- public void init(
- boolean forEncryption,
- CipherParameters param)
- {
- if (core == null)
- {
- core = new RSACoreEngine();
- }
-
- core.init(forEncryption, param);
- }
-
- /**
- * Return the maximum size for an input block to this engine.
- * For RSA this is always one byte less than the key size on
- * encryption, and the same length as the key size on decryption.
- *
- * @return maximum size for an input block.
- */
- public int getInputBlockSize()
- {
- return core.getInputBlockSize();
- }
-
- /**
- * Return the maximum size for an output block to this engine.
- * For RSA this is always one byte less than the key size on
- * decryption, and the same length as the key size on encryption.
- *
- * @return maximum size for an output block.
- */
- public int getOutputBlockSize()
- {
- return core.getOutputBlockSize();
- }
-
- /**
- * Process a single block using the basic RSA algorithm.
- *
- * @param in the input array.
- * @param inOff the offset into the input buffer where the data starts.
- * @param inLen the length of the data to be processed.
- * @return the result of the RSA process.
- * @exception DataLengthException the input block is too large.
- */
- public byte[] processBlock(
- byte[] in,
- int inOff,
- int inLen)
- {
- if (core == null)
- {
- throw new IllegalStateException("RSA engine not initialised");
- }
-
- return core.convertOutput(core.processBlock(core.convertInput(in, inOff, inLen)));
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/RijndaelEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/RijndaelEngine.java
deleted file mode 100644
index c80f6655..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/RijndaelEngine.java
+++ /dev/null
@@ -1,725 +0,0 @@
-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;
-
-/**
- * an implementation of Rijndael, based on the documentation and reference implementation
- * by Paulo Barreto, Vincent Rijmen, for v2.0 August '99.
- * <p>
- * Note: this implementation is based on information prior to final NIST publication.
- */
-public class RijndaelEngine
- implements BlockCipher
-{
- private static final int MAXROUNDS = 14;
-
- private static final int MAXKC = (256/4);
-
- private static final byte[] logtable = {
- (byte)0, (byte)0, (byte)25, (byte)1, (byte)50, (byte)2, (byte)26, (byte)198,
- (byte)75, (byte)199, (byte)27, (byte)104, (byte)51, (byte)238, (byte)223, (byte)3,
- (byte)100, (byte)4, (byte)224, (byte)14, (byte)52, (byte)141, (byte)129, (byte)239,
- (byte)76, (byte)113, (byte)8, (byte)200, (byte)248, (byte)105, (byte)28, (byte)193,
- (byte)125, (byte)194, (byte)29, (byte)181, (byte)249, (byte)185, (byte)39, (byte)106,
- (byte)77, (byte)228, (byte)166, (byte)114, (byte)154, (byte)201, (byte)9, (byte)120,
- (byte)101, (byte)47, (byte)138, (byte)5, (byte)33, (byte)15, (byte)225, (byte)36,
- (byte)18, (byte)240, (byte)130, (byte)69, (byte)53, (byte)147, (byte)218, (byte)142,
- (byte)150, (byte)143, (byte)219, (byte)189, (byte)54, (byte)208, (byte)206, (byte)148,
- (byte)19, (byte)92, (byte)210, (byte)241, (byte)64, (byte)70, (byte)131, (byte)56,
- (byte)102, (byte)221, (byte)253, (byte)48, (byte)191, (byte)6, (byte)139, (byte)98,
- (byte)179, (byte)37, (byte)226, (byte)152, (byte)34, (byte)136, (byte)145, (byte)16,
- (byte)126, (byte)110, (byte)72, (byte)195, (byte)163, (byte)182, (byte)30, (byte)66,
- (byte)58, (byte)107, (byte)40, (byte)84, (byte)250, (byte)133, (byte)61, (byte)186,
- (byte)43, (byte)121, (byte)10, (byte)21, (byte)155, (byte)159, (byte)94, (byte)202,
- (byte)78, (byte)212, (byte)172, (byte)229, (byte)243, (byte)115, (byte)167, (byte)87,
- (byte)175, (byte)88, (byte)168, (byte)80, (byte)244, (byte)234, (byte)214, (byte)116,
- (byte)79, (byte)174, (byte)233, (byte)213, (byte)231, (byte)230, (byte)173, (byte)232,
- (byte)44, (byte)215, (byte)117, (byte)122, (byte)235, (byte)22, (byte)11, (byte)245,
- (byte)89, (byte)203, (byte)95, (byte)176, (byte)156, (byte)169, (byte)81, (byte)160,
- (byte)127, (byte)12, (byte)246, (byte)111, (byte)23, (byte)196, (byte)73, (byte)236,
- (byte)216, (byte)67, (byte)31, (byte)45, (byte)164, (byte)118, (byte)123, (byte)183,
- (byte)204, (byte)187, (byte)62, (byte)90, (byte)251, (byte)96, (byte)177, (byte)134,
- (byte)59, (byte)82, (byte)161, (byte)108, (byte)170, (byte)85, (byte)41, (byte)157,
- (byte)151, (byte)178, (byte)135, (byte)144, (byte)97, (byte)190, (byte)220, (byte)252,
- (byte)188, (byte)149, (byte)207, (byte)205, (byte)55, (byte)63, (byte)91, (byte)209,
- (byte)83, (byte)57, (byte)132, (byte)60, (byte)65, (byte)162, (byte)109, (byte)71,
- (byte)20, (byte)42, (byte)158, (byte)93, (byte)86, (byte)242, (byte)211, (byte)171,
- (byte)68, (byte)17, (byte)146, (byte)217, (byte)35, (byte)32, (byte)46, (byte)137,
- (byte)180, (byte)124, (byte)184, (byte)38, (byte)119, (byte)153, (byte)227, (byte)165,
- (byte)103, (byte)74, (byte)237, (byte)222, (byte)197, (byte)49, (byte)254, (byte)24,
- (byte)13, (byte)99, (byte)140, (byte)128, (byte)192, (byte)247, (byte)112, (byte)7
- };
-
- private static final byte[] aLogtable = {
- (byte)0, (byte)3, (byte)5, (byte)15, (byte)17, (byte)51, (byte)85, (byte)255, (byte)26, (byte)46, (byte)114, (byte)150, (byte)161, (byte)248, (byte)19, (byte)53,
- (byte)95, (byte)225, (byte)56, (byte)72, (byte)216, (byte)115, (byte)149, (byte)164, (byte)247, (byte)2, (byte)6, (byte)10, (byte)30, (byte)34, (byte)102, (byte)170,
- (byte)229, (byte)52, (byte)92, (byte)228, (byte)55, (byte)89, (byte)235, (byte)38, (byte)106, (byte)190, (byte)217, (byte)112, (byte)144, (byte)171, (byte)230, (byte)49,
- (byte)83, (byte)245, (byte)4, (byte)12, (byte)20, (byte)60, (byte)68, (byte)204, (byte)79, (byte)209, (byte)104, (byte)184, (byte)211, (byte)110, (byte)178, (byte)205,
- (byte)76, (byte)212, (byte)103, (byte)169, (byte)224, (byte)59, (byte)77, (byte)215, (byte)98, (byte)166, (byte)241, (byte)8, (byte)24, (byte)40, (byte)120, (byte)136,
- (byte)131, (byte)158, (byte)185, (byte)208, (byte)107, (byte)189, (byte)220, (byte)127, (byte)129, (byte)152, (byte)179, (byte)206, (byte)73, (byte)219, (byte)118, (byte)154,
- (byte)181, (byte)196, (byte)87, (byte)249, (byte)16, (byte)48, (byte)80, (byte)240, (byte)11, (byte)29, (byte)39, (byte)105, (byte)187, (byte)214, (byte)97, (byte)163,
- (byte)254, (byte)25, (byte)43, (byte)125, (byte)135, (byte)146, (byte)173, (byte)236, (byte)47, (byte)113, (byte)147, (byte)174, (byte)233, (byte)32, (byte)96, (byte)160,
- (byte)251, (byte)22, (byte)58, (byte)78, (byte)210, (byte)109, (byte)183, (byte)194, (byte)93, (byte)231, (byte)50, (byte)86, (byte)250, (byte)21, (byte)63, (byte)65,
- (byte)195, (byte)94, (byte)226, (byte)61, (byte)71, (byte)201, (byte)64, (byte)192, (byte)91, (byte)237, (byte)44, (byte)116, (byte)156, (byte)191, (byte)218, (byte)117,
- (byte)159, (byte)186, (byte)213, (byte)100, (byte)172, (byte)239, (byte)42, (byte)126, (byte)130, (byte)157, (byte)188, (byte)223, (byte)122, (byte)142, (byte)137, (byte)128,
- (byte)155, (byte)182, (byte)193, (byte)88, (byte)232, (byte)35, (byte)101, (byte)175, (byte)234, (byte)37, (byte)111, (byte)177, (byte)200, (byte)67, (byte)197, (byte)84,
- (byte)252, (byte)31, (byte)33, (byte)99, (byte)165, (byte)244, (byte)7, (byte)9, (byte)27, (byte)45, (byte)119, (byte)153, (byte)176, (byte)203, (byte)70, (byte)202,
- (byte)69, (byte)207, (byte)74, (byte)222, (byte)121, (byte)139, (byte)134, (byte)145, (byte)168, (byte)227, (byte)62, (byte)66, (byte)198, (byte)81, (byte)243, (byte)14,
- (byte)18, (byte)54, (byte)90, (byte)238, (byte)41, (byte)123, (byte)141, (byte)140, (byte)143, (byte)138, (byte)133, (byte)148, (byte)167, (byte)242, (byte)13, (byte)23,
- (byte)57, (byte)75, (byte)221, (byte)124, (byte)132, (byte)151, (byte)162, (byte)253, (byte)28, (byte)36, (byte)108, (byte)180, (byte)199, (byte)82, (byte)246, (byte)1,
- (byte)3, (byte)5, (byte)15, (byte)17, (byte)51, (byte)85, (byte)255, (byte)26, (byte)46, (byte)114, (byte)150, (byte)161, (byte)248, (byte)19, (byte)53,
- (byte)95, (byte)225, (byte)56, (byte)72, (byte)216, (byte)115, (byte)149, (byte)164, (byte)247, (byte)2, (byte)6, (byte)10, (byte)30, (byte)34, (byte)102, (byte)170,
- (byte)229, (byte)52, (byte)92, (byte)228, (byte)55, (byte)89, (byte)235, (byte)38, (byte)106, (byte)190, (byte)217, (byte)112, (byte)144, (byte)171, (byte)230, (byte)49,
- (byte)83, (byte)245, (byte)4, (byte)12, (byte)20, (byte)60, (byte)68, (byte)204, (byte)79, (byte)209, (byte)104, (byte)184, (byte)211, (byte)110, (byte)178, (byte)205,
- (byte)76, (byte)212, (byte)103, (byte)169, (byte)224, (byte)59, (byte)77, (byte)215, (byte)98, (byte)166, (byte)241, (byte)8, (byte)24, (byte)40, (byte)120, (byte)136,
- (byte)131, (byte)158, (byte)185, (byte)208, (byte)107, (byte)189, (byte)220, (byte)127, (byte)129, (byte)152, (byte)179, (byte)206, (byte)73, (byte)219, (byte)118, (byte)154,
- (byte)181, (byte)196, (byte)87, (byte)249, (byte)16, (byte)48, (byte)80, (byte)240, (byte)11, (byte)29, (byte)39, (byte)105, (byte)187, (byte)214, (byte)97, (byte)163,
- (byte)254, (byte)25, (byte)43, (byte)125, (byte)135, (byte)146, (byte)173, (byte)236, (byte)47, (byte)113, (byte)147, (byte)174, (byte)233, (byte)32, (byte)96, (byte)160,
- (byte)251, (byte)22, (byte)58, (byte)78, (byte)210, (byte)109, (byte)183, (byte)194, (byte)93, (byte)231, (byte)50, (byte)86, (byte)250, (byte)21, (byte)63, (byte)65,
- (byte)195, (byte)94, (byte)226, (byte)61, (byte)71, (byte)201, (byte)64, (byte)192, (byte)91, (byte)237, (byte)44, (byte)116, (byte)156, (byte)191, (byte)218, (byte)117,
- (byte)159, (byte)186, (byte)213, (byte)100, (byte)172, (byte)239, (byte)42, (byte)126, (byte)130, (byte)157, (byte)188, (byte)223, (byte)122, (byte)142, (byte)137, (byte)128,
- (byte)155, (byte)182, (byte)193, (byte)88, (byte)232, (byte)35, (byte)101, (byte)175, (byte)234, (byte)37, (byte)111, (byte)177, (byte)200, (byte)67, (byte)197, (byte)84,
- (byte)252, (byte)31, (byte)33, (byte)99, (byte)165, (byte)244, (byte)7, (byte)9, (byte)27, (byte)45, (byte)119, (byte)153, (byte)176, (byte)203, (byte)70, (byte)202,
- (byte)69, (byte)207, (byte)74, (byte)222, (byte)121, (byte)139, (byte)134, (byte)145, (byte)168, (byte)227, (byte)62, (byte)66, (byte)198, (byte)81, (byte)243, (byte)14,
- (byte)18, (byte)54, (byte)90, (byte)238, (byte)41, (byte)123, (byte)141, (byte)140, (byte)143, (byte)138, (byte)133, (byte)148, (byte)167, (byte)242, (byte)13, (byte)23,
- (byte)57, (byte)75, (byte)221, (byte)124, (byte)132, (byte)151, (byte)162, (byte)253, (byte)28, (byte)36, (byte)108, (byte)180, (byte)199, (byte)82, (byte)246, (byte)1,
- };
-
- private static final byte[] S = {
- (byte)99, (byte)124, (byte)119, (byte)123, (byte)242, (byte)107, (byte)111, (byte)197, (byte)48, (byte)1, (byte)103, (byte)43, (byte)254, (byte)215, (byte)171, (byte)118,
- (byte)202, (byte)130, (byte)201, (byte)125, (byte)250, (byte)89, (byte)71, (byte)240, (byte)173, (byte)212, (byte)162, (byte)175, (byte)156, (byte)164, (byte)114, (byte)192,
- (byte)183, (byte)253, (byte)147, (byte)38, (byte)54, (byte)63, (byte)247, (byte)204, (byte)52, (byte)165, (byte)229, (byte)241, (byte)113, (byte)216, (byte)49, (byte)21,
- (byte)4, (byte)199, (byte)35, (byte)195, (byte)24, (byte)150, (byte)5, (byte)154, (byte)7, (byte)18, (byte)128, (byte)226, (byte)235, (byte)39, (byte)178, (byte)117,
- (byte)9, (byte)131, (byte)44, (byte)26, (byte)27, (byte)110, (byte)90, (byte)160, (byte)82, (byte)59, (byte)214, (byte)179, (byte)41, (byte)227, (byte)47, (byte)132,
- (byte)83, (byte)209, (byte)0, (byte)237, (byte)32, (byte)252, (byte)177, (byte)91, (byte)106, (byte)203, (byte)190, (byte)57, (byte)74, (byte)76, (byte)88, (byte)207,
- (byte)208, (byte)239, (byte)170, (byte)251, (byte)67, (byte)77, (byte)51, (byte)133, (byte)69, (byte)249, (byte)2, (byte)127, (byte)80, (byte)60, (byte)159, (byte)168,
- (byte)81, (byte)163, (byte)64, (byte)143, (byte)146, (byte)157, (byte)56, (byte)245, (byte)188, (byte)182, (byte)218, (byte)33, (byte)16, (byte)255, (byte)243, (byte)210,
- (byte)205, (byte)12, (byte)19, (byte)236, (byte)95, (byte)151, (byte)68, (byte)23, (byte)196, (byte)167, (byte)126, (byte)61, (byte)100, (byte)93, (byte)25, (byte)115,
- (byte)96, (byte)129, (byte)79, (byte)220, (byte)34, (byte)42, (byte)144, (byte)136, (byte)70, (byte)238, (byte)184, (byte)20, (byte)222, (byte)94, (byte)11, (byte)219,
- (byte)224, (byte)50, (byte)58, (byte)10, (byte)73, (byte)6, (byte)36, (byte)92, (byte)194, (byte)211, (byte)172, (byte)98, (byte)145, (byte)149, (byte)228, (byte)121,
- (byte)231, (byte)200, (byte)55, (byte)109, (byte)141, (byte)213, (byte)78, (byte)169, (byte)108, (byte)86, (byte)244, (byte)234, (byte)101, (byte)122, (byte)174, (byte)8,
- (byte)186, (byte)120, (byte)37, (byte)46, (byte)28, (byte)166, (byte)180, (byte)198, (byte)232, (byte)221, (byte)116, (byte)31, (byte)75, (byte)189, (byte)139, (byte)138,
- (byte)112, (byte)62, (byte)181, (byte)102, (byte)72, (byte)3, (byte)246, (byte)14, (byte)97, (byte)53, (byte)87, (byte)185, (byte)134, (byte)193, (byte)29, (byte)158,
- (byte)225, (byte)248, (byte)152, (byte)17, (byte)105, (byte)217, (byte)142, (byte)148, (byte)155, (byte)30, (byte)135, (byte)233, (byte)206, (byte)85, (byte)40, (byte)223,
- (byte)140, (byte)161, (byte)137, (byte)13, (byte)191, (byte)230, (byte)66, (byte)104, (byte)65, (byte)153, (byte)45, (byte)15, (byte)176, (byte)84, (byte)187, (byte)22,
- };
-
- private static final byte[] Si = {
- (byte)82, (byte)9, (byte)106, (byte)213, (byte)48, (byte)54, (byte)165, (byte)56, (byte)191, (byte)64, (byte)163, (byte)158, (byte)129, (byte)243, (byte)215, (byte)251,
- (byte)124, (byte)227, (byte)57, (byte)130, (byte)155, (byte)47, (byte)255, (byte)135, (byte)52, (byte)142, (byte)67, (byte)68, (byte)196, (byte)222, (byte)233, (byte)203,
- (byte)84, (byte)123, (byte)148, (byte)50, (byte)166, (byte)194, (byte)35, (byte)61, (byte)238, (byte)76, (byte)149, (byte)11, (byte)66, (byte)250, (byte)195, (byte)78,
- (byte)8, (byte)46, (byte)161, (byte)102, (byte)40, (byte)217, (byte)36, (byte)178, (byte)118, (byte)91, (byte)162, (byte)73, (byte)109, (byte)139, (byte)209, (byte)37,
- (byte)114, (byte)248, (byte)246, (byte)100, (byte)134, (byte)104, (byte)152, (byte)22, (byte)212, (byte)164, (byte)92, (byte)204, (byte)93, (byte)101, (byte)182, (byte)146,
- (byte)108, (byte)112, (byte)72, (byte)80, (byte)253, (byte)237, (byte)185, (byte)218, (byte)94, (byte)21, (byte)70, (byte)87, (byte)167, (byte)141, (byte)157, (byte)132,
- (byte)144, (byte)216, (byte)171, (byte)0, (byte)140, (byte)188, (byte)211, (byte)10, (byte)247, (byte)228, (byte)88, (byte)5, (byte)184, (byte)179, (byte)69, (byte)6,
- (byte)208, (byte)44, (byte)30, (byte)143, (byte)202, (byte)63, (byte)15, (byte)2, (byte)193, (byte)175, (byte)189, (byte)3, (byte)1, (byte)19, (byte)138, (byte)107,
- (byte)58, (byte)145, (byte)17, (byte)65, (byte)79, (byte)103, (byte)220, (byte)234, (byte)151, (byte)242, (byte)207, (byte)206, (byte)240, (byte)180, (byte)230, (byte)115,
- (byte)150, (byte)172, (byte)116, (byte)34, (byte)231, (byte)173, (byte)53, (byte)133, (byte)226, (byte)249, (byte)55, (byte)232, (byte)28, (byte)117, (byte)223, (byte)110,
- (byte)71, (byte)241, (byte)26, (byte)113, (byte)29, (byte)41, (byte)197, (byte)137, (byte)111, (byte)183, (byte)98, (byte)14, (byte)170, (byte)24, (byte)190, (byte)27,
- (byte)252, (byte)86, (byte)62, (byte)75, (byte)198, (byte)210, (byte)121, (byte)32, (byte)154, (byte)219, (byte)192, (byte)254, (byte)120, (byte)205, (byte)90, (byte)244,
- (byte)31, (byte)221, (byte)168, (byte)51, (byte)136, (byte)7, (byte)199, (byte)49, (byte)177, (byte)18, (byte)16, (byte)89, (byte)39, (byte)128, (byte)236, (byte)95,
- (byte)96, (byte)81, (byte)127, (byte)169, (byte)25, (byte)181, (byte)74, (byte)13, (byte)45, (byte)229, (byte)122, (byte)159, (byte)147, (byte)201, (byte)156, (byte)239,
- (byte)160, (byte)224, (byte)59, (byte)77, (byte)174, (byte)42, (byte)245, (byte)176, (byte)200, (byte)235, (byte)187, (byte)60, (byte)131, (byte)83, (byte)153, (byte)97,
- (byte)23, (byte)43, (byte)4, (byte)126, (byte)186, (byte)119, (byte)214, (byte)38, (byte)225, (byte)105, (byte)20, (byte)99, (byte)85, (byte)33, (byte)12, (byte)125,
- };
-
- private static final int[] rcon = {
- 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 };
-
- static byte[][] shifts0 =
- {
- { 0, 8, 16, 24 },
- { 0, 8, 16, 24 },
- { 0, 8, 16, 24 },
- { 0, 8, 16, 32 },
- { 0, 8, 24, 32 }
- };
-
- static byte[][] shifts1 =
- {
- { 0, 24, 16, 8 },
- { 0, 32, 24, 16 },
- { 0, 40, 32, 24 },
- { 0, 48, 40, 24 },
- { 0, 56, 40, 32 }
- };
-
- /**
- * multiply two elements of GF(2^m)
- * needed for MixColumn and InvMixColumn
- */
- private byte mul0x2(
- int b)
- {
- if (b != 0)
- {
- return aLogtable[25 + (logtable[b] & 0xff)];
- }
- else
- {
- return 0;
- }
- }
-
- private byte mul0x3(
- int b)
- {
- if (b != 0)
- {
- return aLogtable[1 + (logtable[b] & 0xff)];
- }
- else
- {
- return 0;
- }
- }
-
- private byte mul0x9(
- int b)
- {
- if (b >= 0)
- {
- return aLogtable[199 + b];
- }
- else
- {
- return 0;
- }
- }
-
- private byte mul0xb(
- int b)
- {
- if (b >= 0)
- {
- return aLogtable[104 + b];
- }
- else
- {
- return 0;
- }
- }
-
- private byte mul0xd(
- int b)
- {
- if (b >= 0)
- {
- return aLogtable[238 + b];
- }
- else
- {
- return 0;
- }
- }
-
- private byte mul0xe(
- int b)
- {
- if (b >= 0)
- {
- return aLogtable[223 + b];
- }
- else
- {
- return 0;
- }
- }
-
- /**
- * xor corresponding text input and round key input bytes
- */
- private void KeyAddition(
- long[] rk)
- {
- A0 ^= rk[0];
- A1 ^= rk[1];
- A2 ^= rk[2];
- A3 ^= rk[3];
- }
-
- private long shift(
- long r,
- int shift)
- {
- return (((r >>> shift) | (r << (BC - shift)))) & BC_MASK;
- }
-
- /**
- * Row 0 remains unchanged
- * The other three rows are shifted a variable amount
- */
- private void ShiftRow(
- byte[] shiftsSC)
- {
- A1 = shift(A1, shiftsSC[1]);
- A2 = shift(A2, shiftsSC[2]);
- A3 = shift(A3, shiftsSC[3]);
- }
-
- private long applyS(
- long r,
- byte[] box)
- {
- long res = 0;
-
- for (int j = 0; j < BC; j += 8)
- {
- res |= (long)(box[(int)((r >> j) & 0xff)] & 0xff) << j;
- }
-
- return res;
- }
-
- /**
- * Replace every byte of the input by the byte at that place
- * in the nonlinear S-box
- */
- private void Substitution(
- byte[] box)
- {
- A0 = applyS(A0, box);
- A1 = applyS(A1, box);
- A2 = applyS(A2, box);
- A3 = applyS(A3, box);
- }
-
- /**
- * Mix the bytes of every column in a linear way
- */
- private void MixColumn()
- {
- long r0, r1, r2, r3;
-
- r0 = r1 = r2 = r3 = 0;
-
- for (int j = 0; j < BC; j += 8)
- {
- int a0 = (int)((A0 >> j) & 0xff);
- int a1 = (int)((A1 >> j) & 0xff);
- int a2 = (int)((A2 >> j) & 0xff);
- int a3 = (int)((A3 >> j) & 0xff);
-
- r0 |= (long)((mul0x2(a0) ^ mul0x3(a1) ^ a2 ^ a3) & 0xff) << j;
-
- r1 |= (long)((mul0x2(a1) ^ mul0x3(a2) ^ a3 ^ a0) & 0xff) << j;
-
- r2 |= (long)((mul0x2(a2) ^ mul0x3(a3) ^ a0 ^ a1) & 0xff) << j;
-
- r3 |= (long)((mul0x2(a3) ^ mul0x3(a0) ^ a1 ^ a2) & 0xff) << j;
- }
-
- A0 = r0;
- A1 = r1;
- A2 = r2;
- A3 = r3;
- }
-
- /**
- * Mix the bytes of every column in a linear way
- * This is the opposite operation of Mixcolumn
- */
- private void InvMixColumn()
- {
- long r0, r1, r2, r3;
-
- r0 = r1 = r2 = r3 = 0;
- for (int j = 0; j < BC; j += 8)
- {
- int a0 = (int)((A0 >> j) & 0xff);
- int a1 = (int)((A1 >> j) & 0xff);
- int a2 = (int)((A2 >> j) & 0xff);
- int a3 = (int)((A3 >> j) & 0xff);
-
- //
- // pre-lookup the log table
- //
- a0 = (a0 != 0) ? (logtable[a0 & 0xff] & 0xff) : -1;
- a1 = (a1 != 0) ? (logtable[a1 & 0xff] & 0xff) : -1;
- a2 = (a2 != 0) ? (logtable[a2 & 0xff] & 0xff) : -1;
- a3 = (a3 != 0) ? (logtable[a3 & 0xff] & 0xff) : -1;
-
- r0 |= (long)((mul0xe(a0) ^ mul0xb(a1) ^ mul0xd(a2) ^ mul0x9(a3)) & 0xff) << j;
-
- r1 |= (long)((mul0xe(a1) ^ mul0xb(a2) ^ mul0xd(a3) ^ mul0x9(a0)) & 0xff) << j;
-
- r2 |= (long)((mul0xe(a2) ^ mul0xb(a3) ^ mul0xd(a0) ^ mul0x9(a1)) & 0xff) << j;
-
- r3 |= (long)((mul0xe(a3) ^ mul0xb(a0) ^ mul0xd(a1) ^ mul0x9(a2)) & 0xff) << j;
- }
-
- A0 = r0;
- A1 = r1;
- A2 = r2;
- A3 = r3;
- }
-
- /**
- * Calculate the necessary round keys
- * The number of calculations depends on keyBits and blockBits
- */
- private long[][] generateWorkingKey(
- byte[] key)
- {
- int KC;
- int t, rconpointer = 0;
- int keyBits = key.length * 8;
- byte[][] tk = new byte[4][MAXKC];
- long[][] W = new long[MAXROUNDS+1][4];
-
- switch (keyBits)
- {
- case 128:
- KC = 4;
- break;
- case 160:
- KC = 5;
- break;
- case 192:
- KC = 6;
- break;
- case 224:
- KC = 7;
- break;
- case 256:
- KC = 8;
- break;
- default :
- throw new IllegalArgumentException("Key length not 128/160/192/224/256 bits.");
- }
-
- if (keyBits >= blockBits)
- {
- ROUNDS = KC + 6;
- }
- else
- {
- ROUNDS = (BC / 8) + 6;
- }
-
- //
- // copy the key into the processing area
- //
- int index = 0;
-
- for (int i = 0; i < key.length; i++)
- {
- tk[i % 4][i / 4] = key[index++];
- }
-
- t = 0;
-
- //
- // copy values into round key array
- //
- for (int j = 0; (j < KC) && (t < (ROUNDS+1)*(BC / 8)); j++, t++)
- {
- for (int i = 0; i < 4; i++)
- {
- W[t / (BC / 8)][i] |= (long)(tk[i][j] & 0xff) << ((t * 8) % BC);
- }
- }
-
- //
- // while not enough round key material calculated
- // calculate new values
- //
- while (t < (ROUNDS+1)*(BC/8))
- {
- for (int i = 0; i < 4; i++)
- {
- tk[i][0] ^= S[tk[(i+1)%4][KC-1] & 0xff];
- }
- tk[0][0] ^= rcon[rconpointer++];
-
- if (KC <= 6)
- {
- for (int j = 1; j < KC; j++)
- {
- for (int i = 0; i < 4; i++)
- {
- tk[i][j] ^= tk[i][j-1];
- }
- }
- }
- else
- {
- for (int j = 1; j < 4; j++)
- {
- for (int i = 0; i < 4; i++)
- {
- tk[i][j] ^= tk[i][j-1];
- }
- }
- for (int i = 0; i < 4; i++)
- {
- tk[i][4] ^= S[tk[i][3] & 0xff];
- }
- for (int j = 5; j < KC; j++)
- {
- for (int i = 0; i < 4; i++)
- {
- tk[i][j] ^= tk[i][j-1];
- }
- }
- }
-
- //
- // copy values into round key array
- //
- for (int j = 0; (j < KC) && (t < (ROUNDS+1)*(BC/8)); j++, t++)
- {
- for (int i = 0; i < 4; i++)
- {
- W[t / (BC/8)][i] |= (long)(tk[i][j] & 0xff) << ((t * 8) % (BC));
- }
- }
- }
-
- return W;
- }
-
- private int BC;
- private long BC_MASK;
- private int ROUNDS;
- private int blockBits;
- private long[][] workingKey;
- private long A0, A1, A2, A3;
- private boolean forEncryption;
- private byte[] shifts0SC;
- private byte[] shifts1SC;
-
- /**
- * default constructor - 128 bit block size.
- */
- public RijndaelEngine()
- {
- this(128);
- }
-
- /**
- * basic constructor - set the cipher up for a given blocksize
- *
- * @param blockBits the blocksize in bits, must be 128, 192, or 256.
- */
- public RijndaelEngine(
- int blockBits)
- {
- switch (blockBits)
- {
- case 128:
- BC = 32;
- BC_MASK = 0xffffffffL;
- shifts0SC = shifts0[0];
- shifts1SC = shifts1[0];
- break;
- case 160:
- BC = 40;
- BC_MASK = 0xffffffffffL;
- shifts0SC = shifts0[1];
- shifts1SC = shifts1[1];
- break;
- case 192:
- BC = 48;
- BC_MASK = 0xffffffffffffL;
- shifts0SC = shifts0[2];
- shifts1SC = shifts1[2];
- break;
- case 224:
- BC = 56;
- BC_MASK = 0xffffffffffffffL;
- shifts0SC = shifts0[3];
- shifts1SC = shifts1[3];
- break;
- case 256:
- BC = 64;
- BC_MASK = 0xffffffffffffffffL;
- shifts0SC = shifts0[4];
- shifts1SC = shifts1[4];
- break;
- default:
- throw new IllegalArgumentException("unknown blocksize to Rijndael");
- }
-
- this.blockBits = blockBits;
- }
-
- /**
- * initialise a Rijndael cipher.
- *
- * @param forEncryption whether or not we are for encryption.
- * @param params the parameters required to set up the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean forEncryption,
- CipherParameters params)
- {
- if (params instanceof KeyParameter)
- {
- workingKey = generateWorkingKey(((KeyParameter)params).getKey());
- this.forEncryption = forEncryption;
- return;
- }
-
- throw new IllegalArgumentException("invalid parameter passed to Rijndael init - " + params.getClass().getName());
- }
-
- public String getAlgorithmName()
- {
- return "Rijndael";
- }
-
- public int getBlockSize()
- {
- return BC / 2;
- }
-
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- if (workingKey == null)
- {
- throw new IllegalStateException("Rijndael engine not initialised");
- }
-
- if ((inOff + (BC / 2)) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + (BC / 2)) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- if (forEncryption)
- {
- unpackBlock(in, inOff);
- encryptBlock(workingKey);
- packBlock(out, outOff);
- }
- else
- {
- unpackBlock(in, inOff);
- decryptBlock(workingKey);
- packBlock(out, outOff);
- }
-
- return BC / 2;
- }
-
- public void reset()
- {
- }
-
- private void unpackBlock(
- byte[] bytes,
- int off)
- {
- int index = off;
-
- A0 = (bytes[index++] & 0xff);
- A1 = (bytes[index++] & 0xff);
- A2 = (bytes[index++] & 0xff);
- A3 = (bytes[index++] & 0xff);
-
- for (int j = 8; j != BC; j += 8)
- {
- A0 |= (long)(bytes[index++] & 0xff) << j;
- A1 |= (long)(bytes[index++] & 0xff) << j;
- A2 |= (long)(bytes[index++] & 0xff) << j;
- A3 |= (long)(bytes[index++] & 0xff) << j;
- }
- }
-
- private void packBlock(
- byte[] bytes,
- int off)
- {
- int index = off;
-
- for (int j = 0; j != BC; j += 8)
- {
- bytes[index++] = (byte)(A0 >> j);
- bytes[index++] = (byte)(A1 >> j);
- bytes[index++] = (byte)(A2 >> j);
- bytes[index++] = (byte)(A3 >> j);
- }
- }
-
- private void encryptBlock(
- long[][] rk)
- {
- int r;
-
- //
- // begin with a key addition
- //
- KeyAddition(rk[0]);
-
- //
- // ROUNDS-1 ordinary rounds
- //
- for (r = 1; r < ROUNDS; r++)
- {
- Substitution(S);
- ShiftRow(shifts0SC);
- MixColumn();
- KeyAddition(rk[r]);
- }
-
- //
- // Last round is special: there is no MixColumn
- //
- Substitution(S);
- ShiftRow(shifts0SC);
- KeyAddition(rk[ROUNDS]);
- }
-
- private void decryptBlock(
- long[][] rk)
- {
- int r;
-
- // To decrypt: apply the inverse operations of the encrypt routine,
- // in opposite order
- //
- // (KeyAddition is an involution: it 's equal to its inverse)
- // (the inverse of Substitution with table S is Substitution with the inverse table of S)
- // (the inverse of Shiftrow is Shiftrow over a suitable distance)
- //
-
- // First the special round:
- // without InvMixColumn
- // with extra KeyAddition
- //
- KeyAddition(rk[ROUNDS]);
- Substitution(Si);
- ShiftRow(shifts1SC);
-
- //
- // ROUNDS-1 ordinary rounds
- //
- for (r = ROUNDS-1; r > 0; r--)
- {
- KeyAddition(rk[r]);
- InvMixColumn();
- Substitution(Si);
- ShiftRow(shifts1SC);
- }
-
- //
- // End with the extra key addition
- //
- KeyAddition(rk[0]);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/SEEDEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/SEEDEngine.java
deleted file mode 100644
index 43872ed3..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/SEEDEngine.java
+++ /dev/null
@@ -1,346 +0,0 @@
-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;
-
-/**
- * Implementation of the SEED algorithm as described in RFC 4009
- */
-public class SEEDEngine
- implements BlockCipher
-{
- private final int BLOCK_SIZE = 16;
-
- private static final int[] SS0 =
- {
- 0x2989a1a8, 0x05858184, 0x16c6d2d4, 0x13c3d3d0, 0x14445054, 0x1d0d111c, 0x2c8ca0ac, 0x25052124,
- 0x1d4d515c, 0x03434340, 0x18081018, 0x1e0e121c, 0x11415150, 0x3cccf0fc, 0x0acac2c8, 0x23436360,
- 0x28082028, 0x04444044, 0x20002020, 0x1d8d919c, 0x20c0e0e0, 0x22c2e2e0, 0x08c8c0c8, 0x17071314,
- 0x2585a1a4, 0x0f8f838c, 0x03030300, 0x3b4b7378, 0x3b8bb3b8, 0x13031310, 0x12c2d2d0, 0x2ecee2ec,
- 0x30407070, 0x0c8c808c, 0x3f0f333c, 0x2888a0a8, 0x32023230, 0x1dcdd1dc, 0x36c6f2f4, 0x34447074,
- 0x2ccce0ec, 0x15859194, 0x0b0b0308, 0x17475354, 0x1c4c505c, 0x1b4b5358, 0x3d8db1bc, 0x01010100,
- 0x24042024, 0x1c0c101c, 0x33437370, 0x18889098, 0x10001010, 0x0cccc0cc, 0x32c2f2f0, 0x19c9d1d8,
- 0x2c0c202c, 0x27c7e3e4, 0x32427270, 0x03838380, 0x1b8b9398, 0x11c1d1d0, 0x06868284, 0x09c9c1c8,
- 0x20406060, 0x10405050, 0x2383a3a0, 0x2bcbe3e8, 0x0d0d010c, 0x3686b2b4, 0x1e8e929c, 0x0f4f434c,
- 0x3787b3b4, 0x1a4a5258, 0x06c6c2c4, 0x38487078, 0x2686a2a4, 0x12021210, 0x2f8fa3ac, 0x15c5d1d4,
- 0x21416160, 0x03c3c3c0, 0x3484b0b4, 0x01414140, 0x12425250, 0x3d4d717c, 0x0d8d818c, 0x08080008,
- 0x1f0f131c, 0x19899198, 0x00000000, 0x19091118, 0x04040004, 0x13435350, 0x37c7f3f4, 0x21c1e1e0,
- 0x3dcdf1fc, 0x36467274, 0x2f0f232c, 0x27072324, 0x3080b0b0, 0x0b8b8388, 0x0e0e020c, 0x2b8ba3a8,
- 0x2282a2a0, 0x2e4e626c, 0x13839390, 0x0d4d414c, 0x29496168, 0x3c4c707c, 0x09090108, 0x0a0a0208,
- 0x3f8fb3bc, 0x2fcfe3ec, 0x33c3f3f0, 0x05c5c1c4, 0x07878384, 0x14041014, 0x3ecef2fc, 0x24446064,
- 0x1eced2dc, 0x2e0e222c, 0x0b4b4348, 0x1a0a1218, 0x06060204, 0x21012120, 0x2b4b6368, 0x26466264,
- 0x02020200, 0x35c5f1f4, 0x12829290, 0x0a8a8288, 0x0c0c000c, 0x3383b3b0, 0x3e4e727c, 0x10c0d0d0,
- 0x3a4a7278, 0x07474344, 0x16869294, 0x25c5e1e4, 0x26062224, 0x00808080, 0x2d8da1ac, 0x1fcfd3dc,
- 0x2181a1a0, 0x30003030, 0x37073334, 0x2e8ea2ac, 0x36063234, 0x15051114, 0x22022220, 0x38083038,
- 0x34c4f0f4, 0x2787a3a4, 0x05454144, 0x0c4c404c, 0x01818180, 0x29c9e1e8, 0x04848084, 0x17879394,
- 0x35053134, 0x0bcbc3c8, 0x0ecec2cc, 0x3c0c303c, 0x31417170, 0x11011110, 0x07c7c3c4, 0x09898188,
- 0x35457174, 0x3bcbf3f8, 0x1acad2d8, 0x38c8f0f8, 0x14849094, 0x19495158, 0x02828280, 0x04c4c0c4,
- 0x3fcff3fc, 0x09494148, 0x39093138, 0x27476364, 0x00c0c0c0, 0x0fcfc3cc, 0x17c7d3d4, 0x3888b0b8,
- 0x0f0f030c, 0x0e8e828c, 0x02424240, 0x23032320, 0x11819190, 0x2c4c606c, 0x1bcbd3d8, 0x2484a0a4,
- 0x34043034, 0x31c1f1f0, 0x08484048, 0x02c2c2c0, 0x2f4f636c, 0x3d0d313c, 0x2d0d212c, 0x00404040,
- 0x3e8eb2bc, 0x3e0e323c, 0x3c8cb0bc, 0x01c1c1c0, 0x2a8aa2a8, 0x3a8ab2b8, 0x0e4e424c, 0x15455154,
- 0x3b0b3338, 0x1cccd0dc, 0x28486068, 0x3f4f737c, 0x1c8c909c, 0x18c8d0d8, 0x0a4a4248, 0x16465254,
- 0x37477374, 0x2080a0a0, 0x2dcde1ec, 0x06464244, 0x3585b1b4, 0x2b0b2328, 0x25456164, 0x3acaf2f8,
- 0x23c3e3e0, 0x3989b1b8, 0x3181b1b0, 0x1f8f939c, 0x1e4e525c, 0x39c9f1f8, 0x26c6e2e4, 0x3282b2b0,
- 0x31013130, 0x2acae2e8, 0x2d4d616c, 0x1f4f535c, 0x24c4e0e4, 0x30c0f0f0, 0x0dcdc1cc, 0x08888088,
- 0x16061214, 0x3a0a3238, 0x18485058, 0x14c4d0d4, 0x22426260, 0x29092128, 0x07070304, 0x33033330,
- 0x28c8e0e8, 0x1b0b1318, 0x05050104, 0x39497178, 0x10809090, 0x2a4a6268, 0x2a0a2228, 0x1a8a9298
- };
-
- private static final int[] SS1 =
- {
-
- 0x38380830, 0xe828c8e0, 0x2c2d0d21, 0xa42686a2, 0xcc0fcfc3, 0xdc1eced2, 0xb03383b3, 0xb83888b0,
- 0xac2f8fa3, 0x60204060, 0x54154551, 0xc407c7c3, 0x44044440, 0x6c2f4f63, 0x682b4b63, 0x581b4b53,
- 0xc003c3c3, 0x60224262, 0x30330333, 0xb43585b1, 0x28290921, 0xa02080a0, 0xe022c2e2, 0xa42787a3,
- 0xd013c3d3, 0x90118191, 0x10110111, 0x04060602, 0x1c1c0c10, 0xbc3c8cb0, 0x34360632, 0x480b4b43,
- 0xec2fcfe3, 0x88088880, 0x6c2c4c60, 0xa82888a0, 0x14170713, 0xc404c4c0, 0x14160612, 0xf434c4f0,
- 0xc002c2c2, 0x44054541, 0xe021c1e1, 0xd416c6d2, 0x3c3f0f33, 0x3c3d0d31, 0x8c0e8e82, 0x98188890,
- 0x28280820, 0x4c0e4e42, 0xf436c6f2, 0x3c3e0e32, 0xa42585a1, 0xf839c9f1, 0x0c0d0d01, 0xdc1fcfd3,
- 0xd818c8d0, 0x282b0b23, 0x64264662, 0x783a4a72, 0x24270723, 0x2c2f0f23, 0xf031c1f1, 0x70324272,
- 0x40024242, 0xd414c4d0, 0x40014141, 0xc000c0c0, 0x70334373, 0x64274763, 0xac2c8ca0, 0x880b8b83,
- 0xf437c7f3, 0xac2d8da1, 0x80008080, 0x1c1f0f13, 0xc80acac2, 0x2c2c0c20, 0xa82a8aa2, 0x34340430,
- 0xd012c2d2, 0x080b0b03, 0xec2ecee2, 0xe829c9e1, 0x5c1d4d51, 0x94148490, 0x18180810, 0xf838c8f0,
- 0x54174753, 0xac2e8ea2, 0x08080800, 0xc405c5c1, 0x10130313, 0xcc0dcdc1, 0x84068682, 0xb83989b1,
- 0xfc3fcff3, 0x7c3d4d71, 0xc001c1c1, 0x30310131, 0xf435c5f1, 0x880a8a82, 0x682a4a62, 0xb03181b1,
- 0xd011c1d1, 0x20200020, 0xd417c7d3, 0x00020202, 0x20220222, 0x04040400, 0x68284860, 0x70314171,
- 0x04070703, 0xd81bcbd3, 0x9c1d8d91, 0x98198991, 0x60214161, 0xbc3e8eb2, 0xe426c6e2, 0x58194951,
- 0xdc1dcdd1, 0x50114151, 0x90108090, 0xdc1cccd0, 0x981a8a92, 0xa02383a3, 0xa82b8ba3, 0xd010c0d0,
- 0x80018181, 0x0c0f0f03, 0x44074743, 0x181a0a12, 0xe023c3e3, 0xec2ccce0, 0x8c0d8d81, 0xbc3f8fb3,
- 0x94168692, 0x783b4b73, 0x5c1c4c50, 0xa02282a2, 0xa02181a1, 0x60234363, 0x20230323, 0x4c0d4d41,
- 0xc808c8c0, 0x9c1e8e92, 0x9c1c8c90, 0x383a0a32, 0x0c0c0c00, 0x2c2e0e22, 0xb83a8ab2, 0x6c2e4e62,
- 0x9c1f8f93, 0x581a4a52, 0xf032c2f2, 0x90128292, 0xf033c3f3, 0x48094941, 0x78384870, 0xcc0cccc0,
- 0x14150511, 0xf83bcbf3, 0x70304070, 0x74354571, 0x7c3f4f73, 0x34350531, 0x10100010, 0x00030303,
- 0x64244460, 0x6c2d4d61, 0xc406c6c2, 0x74344470, 0xd415c5d1, 0xb43484b0, 0xe82acae2, 0x08090901,
- 0x74364672, 0x18190911, 0xfc3ecef2, 0x40004040, 0x10120212, 0xe020c0e0, 0xbc3d8db1, 0x04050501,
- 0xf83acaf2, 0x00010101, 0xf030c0f0, 0x282a0a22, 0x5c1e4e52, 0xa82989a1, 0x54164652, 0x40034343,
- 0x84058581, 0x14140410, 0x88098981, 0x981b8b93, 0xb03080b0, 0xe425c5e1, 0x48084840, 0x78394971,
- 0x94178793, 0xfc3cccf0, 0x1c1e0e12, 0x80028282, 0x20210121, 0x8c0c8c80, 0x181b0b13, 0x5c1f4f53,
- 0x74374773, 0x54144450, 0xb03282b2, 0x1c1d0d11, 0x24250521, 0x4c0f4f43, 0x00000000, 0x44064642,
- 0xec2dcde1, 0x58184850, 0x50124252, 0xe82bcbe3, 0x7c3e4e72, 0xd81acad2, 0xc809c9c1, 0xfc3dcdf1,
- 0x30300030, 0x94158591, 0x64254561, 0x3c3c0c30, 0xb43686b2, 0xe424c4e0, 0xb83b8bb3, 0x7c3c4c70,
- 0x0c0e0e02, 0x50104050, 0x38390931, 0x24260622, 0x30320232, 0x84048480, 0x68294961, 0x90138393,
- 0x34370733, 0xe427c7e3, 0x24240420, 0xa42484a0, 0xc80bcbc3, 0x50134353, 0x080a0a02, 0x84078783,
- 0xd819c9d1, 0x4c0c4c40, 0x80038383, 0x8c0f8f83, 0xcc0ecec2, 0x383b0b33, 0x480a4a42, 0xb43787b3
- };
-
- private static final int[] SS2 =
- {
-
- 0xa1a82989, 0x81840585, 0xd2d416c6, 0xd3d013c3, 0x50541444, 0x111c1d0d, 0xa0ac2c8c, 0x21242505,
- 0x515c1d4d, 0x43400343, 0x10181808, 0x121c1e0e, 0x51501141, 0xf0fc3ccc, 0xc2c80aca, 0x63602343,
- 0x20282808, 0x40440444, 0x20202000, 0x919c1d8d, 0xe0e020c0, 0xe2e022c2, 0xc0c808c8, 0x13141707,
- 0xa1a42585, 0x838c0f8f, 0x03000303, 0x73783b4b, 0xb3b83b8b, 0x13101303, 0xd2d012c2, 0xe2ec2ece,
- 0x70703040, 0x808c0c8c, 0x333c3f0f, 0xa0a82888, 0x32303202, 0xd1dc1dcd, 0xf2f436c6, 0x70743444,
- 0xe0ec2ccc, 0x91941585, 0x03080b0b, 0x53541747, 0x505c1c4c, 0x53581b4b, 0xb1bc3d8d, 0x01000101,
- 0x20242404, 0x101c1c0c, 0x73703343, 0x90981888, 0x10101000, 0xc0cc0ccc, 0xf2f032c2, 0xd1d819c9,
- 0x202c2c0c, 0xe3e427c7, 0x72703242, 0x83800383, 0x93981b8b, 0xd1d011c1, 0x82840686, 0xc1c809c9,
- 0x60602040, 0x50501040, 0xa3a02383, 0xe3e82bcb, 0x010c0d0d, 0xb2b43686, 0x929c1e8e, 0x434c0f4f,
- 0xb3b43787, 0x52581a4a, 0xc2c406c6, 0x70783848, 0xa2a42686, 0x12101202, 0xa3ac2f8f, 0xd1d415c5,
- 0x61602141, 0xc3c003c3, 0xb0b43484, 0x41400141, 0x52501242, 0x717c3d4d, 0x818c0d8d, 0x00080808,
- 0x131c1f0f, 0x91981989, 0x00000000, 0x11181909, 0x00040404, 0x53501343, 0xf3f437c7, 0xe1e021c1,
- 0xf1fc3dcd, 0x72743646, 0x232c2f0f, 0x23242707, 0xb0b03080, 0x83880b8b, 0x020c0e0e, 0xa3a82b8b,
- 0xa2a02282, 0x626c2e4e, 0x93901383, 0x414c0d4d, 0x61682949, 0x707c3c4c, 0x01080909, 0x02080a0a,
- 0xb3bc3f8f, 0xe3ec2fcf, 0xf3f033c3, 0xc1c405c5, 0x83840787, 0x10141404, 0xf2fc3ece, 0x60642444,
- 0xd2dc1ece, 0x222c2e0e, 0x43480b4b, 0x12181a0a, 0x02040606, 0x21202101, 0x63682b4b, 0x62642646,
- 0x02000202, 0xf1f435c5, 0x92901282, 0x82880a8a, 0x000c0c0c, 0xb3b03383, 0x727c3e4e, 0xd0d010c0,
- 0x72783a4a, 0x43440747, 0x92941686, 0xe1e425c5, 0x22242606, 0x80800080, 0xa1ac2d8d, 0xd3dc1fcf,
- 0xa1a02181, 0x30303000, 0x33343707, 0xa2ac2e8e, 0x32343606, 0x11141505, 0x22202202, 0x30383808,
- 0xf0f434c4, 0xa3a42787, 0x41440545, 0x404c0c4c, 0x81800181, 0xe1e829c9, 0x80840484, 0x93941787,
- 0x31343505, 0xc3c80bcb, 0xc2cc0ece, 0x303c3c0c, 0x71703141, 0x11101101, 0xc3c407c7, 0x81880989,
- 0x71743545, 0xf3f83bcb, 0xd2d81aca, 0xf0f838c8, 0x90941484, 0x51581949, 0x82800282, 0xc0c404c4,
- 0xf3fc3fcf, 0x41480949, 0x31383909, 0x63642747, 0xc0c000c0, 0xc3cc0fcf, 0xd3d417c7, 0xb0b83888,
- 0x030c0f0f, 0x828c0e8e, 0x42400242, 0x23202303, 0x91901181, 0x606c2c4c, 0xd3d81bcb, 0xa0a42484,
- 0x30343404, 0xf1f031c1, 0x40480848, 0xc2c002c2, 0x636c2f4f, 0x313c3d0d, 0x212c2d0d, 0x40400040,
- 0xb2bc3e8e, 0x323c3e0e, 0xb0bc3c8c, 0xc1c001c1, 0xa2a82a8a, 0xb2b83a8a, 0x424c0e4e, 0x51541545,
- 0x33383b0b, 0xd0dc1ccc, 0x60682848, 0x737c3f4f, 0x909c1c8c, 0xd0d818c8, 0x42480a4a, 0x52541646,
- 0x73743747, 0xa0a02080, 0xe1ec2dcd, 0x42440646, 0xb1b43585, 0x23282b0b, 0x61642545, 0xf2f83aca,
- 0xe3e023c3, 0xb1b83989, 0xb1b03181, 0x939c1f8f, 0x525c1e4e, 0xf1f839c9, 0xe2e426c6, 0xb2b03282,
- 0x31303101, 0xe2e82aca, 0x616c2d4d, 0x535c1f4f, 0xe0e424c4, 0xf0f030c0, 0xc1cc0dcd, 0x80880888,
- 0x12141606, 0x32383a0a, 0x50581848, 0xd0d414c4, 0x62602242, 0x21282909, 0x03040707, 0x33303303,
- 0xe0e828c8, 0x13181b0b, 0x01040505, 0x71783949, 0x90901080, 0x62682a4a, 0x22282a0a, 0x92981a8a
- };
-
-
- private static final int[] SS3 =
- {
-
- 0x08303838, 0xc8e0e828, 0x0d212c2d, 0x86a2a426, 0xcfc3cc0f, 0xced2dc1e, 0x83b3b033, 0x88b0b838,
- 0x8fa3ac2f, 0x40606020, 0x45515415, 0xc7c3c407, 0x44404404, 0x4f636c2f, 0x4b63682b, 0x4b53581b,
- 0xc3c3c003, 0x42626022, 0x03333033, 0x85b1b435, 0x09212829, 0x80a0a020, 0xc2e2e022, 0x87a3a427,
- 0xc3d3d013, 0x81919011, 0x01111011, 0x06020406, 0x0c101c1c, 0x8cb0bc3c, 0x06323436, 0x4b43480b,
- 0xcfe3ec2f, 0x88808808, 0x4c606c2c, 0x88a0a828, 0x07131417, 0xc4c0c404, 0x06121416, 0xc4f0f434,
- 0xc2c2c002, 0x45414405, 0xc1e1e021, 0xc6d2d416, 0x0f333c3f, 0x0d313c3d, 0x8e828c0e, 0x88909818,
- 0x08202828, 0x4e424c0e, 0xc6f2f436, 0x0e323c3e, 0x85a1a425, 0xc9f1f839, 0x0d010c0d, 0xcfd3dc1f,
- 0xc8d0d818, 0x0b23282b, 0x46626426, 0x4a72783a, 0x07232427, 0x0f232c2f, 0xc1f1f031, 0x42727032,
- 0x42424002, 0xc4d0d414, 0x41414001, 0xc0c0c000, 0x43737033, 0x47636427, 0x8ca0ac2c, 0x8b83880b,
- 0xc7f3f437, 0x8da1ac2d, 0x80808000, 0x0f131c1f, 0xcac2c80a, 0x0c202c2c, 0x8aa2a82a, 0x04303434,
- 0xc2d2d012, 0x0b03080b, 0xcee2ec2e, 0xc9e1e829, 0x4d515c1d, 0x84909414, 0x08101818, 0xc8f0f838,
- 0x47535417, 0x8ea2ac2e, 0x08000808, 0xc5c1c405, 0x03131013, 0xcdc1cc0d, 0x86828406, 0x89b1b839,
- 0xcff3fc3f, 0x4d717c3d, 0xc1c1c001, 0x01313031, 0xc5f1f435, 0x8a82880a, 0x4a62682a, 0x81b1b031,
- 0xc1d1d011, 0x00202020, 0xc7d3d417, 0x02020002, 0x02222022, 0x04000404, 0x48606828, 0x41717031,
- 0x07030407, 0xcbd3d81b, 0x8d919c1d, 0x89919819, 0x41616021, 0x8eb2bc3e, 0xc6e2e426, 0x49515819,
- 0xcdd1dc1d, 0x41515011, 0x80909010, 0xccd0dc1c, 0x8a92981a, 0x83a3a023, 0x8ba3a82b, 0xc0d0d010,
- 0x81818001, 0x0f030c0f, 0x47434407, 0x0a12181a, 0xc3e3e023, 0xcce0ec2c, 0x8d818c0d, 0x8fb3bc3f,
- 0x86929416, 0x4b73783b, 0x4c505c1c, 0x82a2a022, 0x81a1a021, 0x43636023, 0x03232023, 0x4d414c0d,
- 0xc8c0c808, 0x8e929c1e, 0x8c909c1c, 0x0a32383a, 0x0c000c0c, 0x0e222c2e, 0x8ab2b83a, 0x4e626c2e,
- 0x8f939c1f, 0x4a52581a, 0xc2f2f032, 0x82929012, 0xc3f3f033, 0x49414809, 0x48707838, 0xccc0cc0c,
- 0x05111415, 0xcbf3f83b, 0x40707030, 0x45717435, 0x4f737c3f, 0x05313435, 0x00101010, 0x03030003,
- 0x44606424, 0x4d616c2d, 0xc6c2c406, 0x44707434, 0xc5d1d415, 0x84b0b434, 0xcae2e82a, 0x09010809,
- 0x46727436, 0x09111819, 0xcef2fc3e, 0x40404000, 0x02121012, 0xc0e0e020, 0x8db1bc3d, 0x05010405,
- 0xcaf2f83a, 0x01010001, 0xc0f0f030, 0x0a22282a, 0x4e525c1e, 0x89a1a829, 0x46525416, 0x43434003,
- 0x85818405, 0x04101414, 0x89818809, 0x8b93981b, 0x80b0b030, 0xc5e1e425, 0x48404808, 0x49717839,
- 0x87939417, 0xccf0fc3c, 0x0e121c1e, 0x82828002, 0x01212021, 0x8c808c0c, 0x0b13181b, 0x4f535c1f,
- 0x47737437, 0x44505414, 0x82b2b032, 0x0d111c1d, 0x05212425, 0x4f434c0f, 0x00000000, 0x46424406,
- 0xcde1ec2d, 0x48505818, 0x42525012, 0xcbe3e82b, 0x4e727c3e, 0xcad2d81a, 0xc9c1c809, 0xcdf1fc3d,
- 0x00303030, 0x85919415, 0x45616425, 0x0c303c3c, 0x86b2b436, 0xc4e0e424, 0x8bb3b83b, 0x4c707c3c,
- 0x0e020c0e, 0x40505010, 0x09313839, 0x06222426, 0x02323032, 0x84808404, 0x49616829, 0x83939013,
- 0x07333437, 0xc7e3e427, 0x04202424, 0x84a0a424, 0xcbc3c80b, 0x43535013, 0x0a02080a, 0x87838407,
- 0xc9d1d819, 0x4c404c0c, 0x83838003, 0x8f838c0f, 0xcec2cc0e, 0x0b33383b, 0x4a42480a, 0x87b3b437
- };
-
-
- private static final int[] KC =
- {
- 0x9e3779b9, 0x3c6ef373, 0x78dde6e6, 0xf1bbcdcc,
- 0xe3779b99, 0xc6ef3733, 0x8dde6e67, 0x1bbcdccf,
- 0x3779b99e, 0x6ef3733c, 0xdde6e678, 0xbbcdccf1,
- 0x779b99e3, 0xef3733c6, 0xde6e678d, 0xbcdccf1b
- };
-
- private int[] wKey;
- private boolean forEncryption;
-
- public void init(boolean forEncryption, CipherParameters params) throws IllegalArgumentException
- {
- this.forEncryption = forEncryption;
- wKey = createWorkingKey(((KeyParameter)params).getKey());
- }
-
- public String getAlgorithmName()
- {
- return "SEED";
- }
-
- public int getBlockSize()
- {
- return BLOCK_SIZE;
- }
-
- public int processBlock(byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException
- {
- if (wKey == null)
- {
- throw new IllegalStateException("SEED engine not initialised");
- }
-
- if (inOff + BLOCK_SIZE > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if (outOff + BLOCK_SIZE > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- long l = bytesToLong(in, inOff + 0);
- long r = bytesToLong(in, inOff + 8);
-
- if (forEncryption)
- {
- for (int i = 0; i < 16; i++)
- {
- long nl = r;
-
- r = l ^ F(wKey[2 * i], wKey[(2 * i) + 1], r);
- l = nl;
- }
- }
- else
- {
- for (int i = 15; i >= 0; i--)
- {
- long nl = r;
-
- r = l ^ F(wKey[2 * i], wKey[(2 * i) + 1], r);
- l = nl;
- }
- }
-
- longToBytes(out, outOff + 0, r);
- longToBytes(out, outOff + 8, l);
-
- return BLOCK_SIZE;
- }
-
- public void reset()
- {
- }
-
- private int[] createWorkingKey(byte[] inKey)
- {
- int[] key = new int[32];
- long lower = bytesToLong(inKey, 0);
- long upper = bytesToLong(inKey, 8);
-
- int key0 = extractW0(lower);
- int key1 = extractW1(lower);
- int key2 = extractW0(upper);
- int key3 = extractW1(upper);
-
- for (int i = 0; i < 16; i++)
- {
- key[2 * i] = G(key0 + key2 - KC[i]);
- key[2 * i + 1] = G(key1 - key3 + KC[i]);
-
- if (i % 2 == 0)
- {
- lower = rotateRight8(lower);
- key0 = extractW0(lower);
- key1 = extractW1(lower);
- }
- else
- {
- upper = rotateLeft8(upper);
- key2 = extractW0(upper);
- key3 = extractW1(upper);
- }
- }
-
- return key;
- }
-
- private int extractW1(long lVal)
- {
- return (int)lVal;
- }
-
- private int extractW0(long lVal)
- {
- return (int)(lVal >> 32);
- }
-
- private long rotateLeft8(long x)
- {
- return (x << 8) | (x >>> 56);
- }
-
- private long rotateRight8(long x)
- {
- return (x >>> 8) | (x << 56);
- }
-
- private long bytesToLong(
- byte[] src,
- int srcOff)
- {
- long word = 0;
-
- for (int i = 0; i <= 7; i++)
- {
- word = (word << 8) + (src[i + srcOff] & 0xff);
- }
-
- return word;
- }
-
- private void longToBytes(
- byte[] dest,
- int destOff,
- long value)
- {
- for (int i = 0; i < 8; i++)
- {
- dest[i + destOff] = (byte)(value >> ((7 - i) * 8));
- }
- }
-
- private int G(int x)
- {
- return SS0[x & 0xff] ^ SS1[(x >> 8) & 0xff] ^ SS2[(x >> 16) & 0xff] ^ SS3[(x >> 24) & 0xff];
- }
-
- private long F(int ki0, int ki1, long r)
- {
- int r0 = (int)(r >> 32);
- int r1 = (int)r;
- int rd1 = phaseCalc2(r0, ki0, r1, ki1);
- int rd0 = rd1 + phaseCalc1(r0, ki0, r1, ki1);
-
- return ((long)rd0 << 32) | (rd1 & 0xffffffffL);
- }
-
- private int phaseCalc1(int r0, int ki0, int r1, int ki1)
- {
- return G(G((r0 ^ ki0) ^ (r1 ^ ki1)) + (r0 ^ ki0));
- }
-
- private int phaseCalc2(int r0, int ki0, int r1, int ki1)
- {
- return G(phaseCalc1(r0, ki0, r1, ki1) + G((r0 ^ ki0) ^ (r1 ^ ki1)));
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/SEEDWrapEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/SEEDWrapEngine.java
deleted file mode 100644
index 5b65b00c..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/SEEDWrapEngine.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-/**
- * An implementation of the SEED key wrapper based on RFC 4010/RFC 3394.
- * <p>
- * For further details see: <a href="http://www.ietf.org/rfc/rfc4010.txt">http://www.ietf.org/rfc/rfc4010.txt</a>.
- */
-public class SEEDWrapEngine
- extends RFC3394WrapEngine
-{
- public SEEDWrapEngine()
- {
- super(new SEEDEngine());
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/Salsa20Engine.java b/core/src/main/java/org/bouncycastle/crypto/engines/Salsa20Engine.java
deleted file mode 100644
index 1452d1e6..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/Salsa20Engine.java
+++ /dev/null
@@ -1,474 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.MaxBytesExceededException;
-import org.bouncycastle.crypto.OutputLengthException;
-import org.bouncycastle.crypto.SkippingStreamCipher;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Pack;
-import org.bouncycastle.util.Strings;
-
-/**
- * Implementation of Daniel J. Bernstein's Salsa20 stream cipher, Snuffle 2005
- */
-public class Salsa20Engine
- implements SkippingStreamCipher
-{
- public final static int DEFAULT_ROUNDS = 20;
-
- /** Constants */
- private final static int STATE_SIZE = 16; // 16, 32 bit ints = 64 bytes
-
- 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;
- 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;
-
- /*
- * internal counter
- */
- 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.
- * @param params the parameters required to set up the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean forEncryption,
- CipherParameters params)
- {
- /*
- * Salsa20 encryption and decryption is completely
- * symmetrical, so the 'forEncryption' is
- * irrelevant. (Like 90% of stream ciphers)
- */
-
- if (!(params instanceof ParametersWithIV))
- {
- throw new IllegalArgumentException(getAlgorithmName() + " Init parameters must include an IV");
- }
-
- ParametersWithIV ivParams = (ParametersWithIV) params;
-
- byte[] iv = ivParams.getIV();
- if (iv == null || iv.length != getNonceSize())
- {
- throw new IllegalArgumentException(getAlgorithmName() + " requires exactly " + getNonceSize()
- + " bytes of IV");
- }
-
- CipherParameters keyParam = ivParams.getParameters();
- if (keyParam == null)
- {
- if (!initialised)
- {
- throw new IllegalStateException(getAlgorithmName() + " KeyParameter can not be null for first initialisation");
- }
-
- setKey(null, iv);
- }
- else if (keyParam instanceof KeyParameter)
- {
- setKey(((KeyParameter)keyParam).getKey(), iv);
- }
- else
- {
- throw new IllegalArgumentException(getAlgorithmName() + " Init parameters must contain a KeyParameter (or null for re-init)");
- }
-
- reset();
-
- initialised = true;
- }
-
- protected int getNonceSize()
- {
- return 8;
- }
-
- public String getAlgorithmName()
- {
- String name = "Salsa20";
- if (rounds != DEFAULT_ROUNDS)
- {
- name += "/" + rounds;
- }
- return name;
- }
-
- public byte returnByte(byte in)
- {
- if (limitExceeded())
- {
- throw new MaxBytesExceededException("2^70 byte limit per IV; Change IV");
- }
-
- byte out = (byte)(keyStream[index]^in);
- index = (index + 1) & 63;
-
- if (index == 0)
- {
- advanceCounter();
- generateKeyStream(keyStream);
- }
-
- return out;
- }
-
- protected void advanceCounter()
- {
- if (++engineState[8] == 0)
- {
- ++engineState[9];
- }
- }
-
- protected void retreatCounter()
- {
- if (engineState[8] == 0 && engineState[9] == 0)
- {
- throw new IllegalStateException("attempt to reduce counter past zero.");
- }
-
- if (--engineState[8] == -1)
- {
- --engineState[9];
- }
- }
-
- public int processBytes(
- byte[] in,
- int inOff,
- int len,
- byte[] out,
- int outOff)
- {
- if (!initialised)
- {
- throw new IllegalStateException(getAlgorithmName() + " not initialised");
- }
-
- if ((inOff + len) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + len) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- if (limitExceeded(len))
- {
- throw new MaxBytesExceededException("2^70 byte limit per IV would be exceeded; Change IV");
- }
-
- for (int i = 0; i < len; i++)
- {
- out[i + outOff] = (byte)(keyStream[index] ^ in[i + inOff]);
- index = (index + 1) & 63;
-
- if (index == 0)
- {
- advanceCounter();
- generateKeyStream(keyStream);
- }
- }
-
- return len;
- }
-
- public long skip(long numberOfBytes)
- {
- if (numberOfBytes >= 0)
- {
- for (long i = 0; i < numberOfBytes; i++)
- {
- index = (index + 1) & 63;
-
- if (index == 0)
- {
- advanceCounter();
- }
- }
- }
- else
- {
- for (long i = 0; i > numberOfBytes; i--)
- {
- if (index == 0)
- {
- retreatCounter();
- }
-
- index = (index - 1) & 63;
- }
- }
-
- generateKeyStream(keyStream);
-
- return numberOfBytes;
- }
-
- public long seekTo(long position)
- {
- reset();
-
- return skip(position);
- }
-
- public long getPosition()
- {
- return getCounter() * 64 + index;
- }
-
- public void reset()
- {
- index = 0;
- resetLimitCounter();
- resetCounter();
-
- generateKeyStream(keyStream);
- }
-
- protected long getCounter()
- {
- return ((long)engineState[9] << 32) | (engineState[8] & 0xffffffffL);
- }
-
- protected void resetCounter()
- {
- engineState[8] = engineState[9] = 0;
- }
-
- protected void setKey(byte[] keyBytes, byte[] ivBytes)
- {
- if (keyBytes != null)
- {
- if ((keyBytes.length != 16) && (keyBytes.length != 32))
- {
- throw new IllegalArgumentException(getAlgorithmName() + " requires 128 bit or 256 bit key");
- }
-
- // Key
- engineState[1] = Pack.littleEndianToInt(keyBytes, 0);
- engineState[2] = Pack.littleEndianToInt(keyBytes, 4);
- engineState[3] = Pack.littleEndianToInt(keyBytes, 8);
- engineState[4] = Pack.littleEndianToInt(keyBytes, 12);
-
- byte[] constants;
- int offset;
- if (keyBytes.length == 32)
- {
- constants = sigma;
- offset = 16;
- }
- else
- {
- constants = tau;
- offset = 0;
- }
-
- 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(ivBytes, 0);
- engineState[7] = Pack.littleEndianToInt(ivBytes, 4);
- }
-
- protected void generateKeyStream(byte[] output)
- {
- salsaCore(rounds, engineState, x);
- Pack.intToLittleEndian(x, output, 0);
- }
-
- /**
- * Salsa20 function
- *
- * @param input input data
- */
- public static void salsaCore(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)
- {
- 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);
- }
-
- 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];
- }
-
- /**
- * Rotate left
- *
- * @param x value to rotate
- * @param y amount to rotate x
- *
- * @return rotated x
- */
- protected static int rotl(int x, int y)
- {
- return (x << y) | (x >>> -y);
- }
-
- private void resetLimitCounter()
- {
- cW0 = 0;
- cW1 = 0;
- cW2 = 0;
- }
-
- private boolean limitExceeded()
- {
- if (++cW0 == 0)
- {
- if (++cW1 == 0)
- {
- return (++cW2 & 0x20) != 0; // 2^(32 + 32 + 6)
- }
- }
-
- return false;
- }
-
- /*
- * this relies on the fact len will always be positive.
- */
- private boolean limitExceeded(int len)
- {
- cW0 += len;
- if (cW0 < len && cW0 >= 0)
- {
- if (++cW1 == 0)
- {
- return (++cW2 & 0x20) != 0; // 2^(32 + 32 + 6)
- }
- }
-
- return false;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/SerpentEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/SerpentEngine.java
deleted file mode 100644
index 8db5a6f7..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/SerpentEngine.java
+++ /dev/null
@@ -1,783 +0,0 @@
-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;
-
-/**
- * Serpent is a 128-bit 32-round block cipher with variable key lengths,
- * including 128, 192 and 256 bit keys conjectured to be at least as
- * secure as three-key triple-DES.
- * <p>
- * Serpent was designed by Ross Anderson, Eli Biham and Lars Knudsen as a
- * candidate algorithm for the NIST AES Quest.
- * <p>
- * For full details see the <a href="http://www.cl.cam.ac.uk/~rja14/serpent.html">The Serpent home page</a>
- */
-public class SerpentEngine
- implements BlockCipher
-{
- private static final int BLOCK_SIZE = 16;
-
- static final int ROUNDS = 32;
- static final int PHI = 0x9E3779B9; // (sqrt(5) - 1) * 2**31
-
- private boolean encrypting;
- private int[] wKey;
-
- private int X0, X1, X2, X3; // registers
-
- /**
- * initialise a Serpent cipher.
- *
- * @param encrypting whether or not we are for encryption.
- * @param params the parameters required to set up the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean encrypting,
- CipherParameters params)
- {
- if (params instanceof KeyParameter)
- {
- this.encrypting = encrypting;
- this.wKey = makeWorkingKey(((KeyParameter)params).getKey());
- return;
- }
-
- throw new IllegalArgumentException("invalid parameter passed to Serpent init - " + params.getClass().getName());
- }
-
- public String getAlgorithmName()
- {
- return "Serpent";
- }
-
- public int getBlockSize()
- {
- return BLOCK_SIZE;
- }
-
- /**
- * Process one block of input from the array in and write it to
- * the out array.
- *
- * @param in the array containing the input data.
- * @param inOff offset into the in array the data starts at.
- * @param out the array the output data will be copied into.
- * @param outOff the offset into the out array the output will start at.
- * @exception DataLengthException if there isn't enough data in in, or
- * space in out.
- * @exception IllegalStateException if the cipher isn't initialised.
- * @return the number of bytes processed and produced.
- */
- public final int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- if (wKey == null)
- {
- throw new IllegalStateException("Serpent not initialised");
- }
-
- if ((inOff + BLOCK_SIZE) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + BLOCK_SIZE) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- if (encrypting)
- {
- encryptBlock(in, inOff, out, outOff);
- }
- else
- {
- decryptBlock(in, inOff, out, outOff);
- }
-
- return BLOCK_SIZE;
- }
-
- public void reset()
- {
- }
-
- /**
- * Expand a user-supplied key material into a session key.
- *
- * @param key The user-key bytes (multiples of 4) to use.
- * @exception IllegalArgumentException
- */
- private int[] makeWorkingKey(
- byte[] key)
- throws IllegalArgumentException
- {
- //
- // pad key to 256 bits
- //
- int[] kPad = new int[16];
- int off = 0;
- int length = 0;
-
- for (off = key.length - 4; off > 0; off -= 4)
- {
- kPad[length++] = bytesToWord(key, off);
- }
-
- if (off == 0)
- {
- kPad[length++] = bytesToWord(key, 0);
- if (length < 8)
- {
- kPad[length] = 1;
- }
- }
- else
- {
- throw new IllegalArgumentException("key must be a multiple of 4 bytes");
- }
-
- //
- // expand the padded key up to 33 x 128 bits of key material
- //
- int amount = (ROUNDS + 1) * 4;
- int[] w = new int[amount];
-
- //
- // compute w0 to w7 from w-8 to w-1
- //
- for (int i = 8; i < 16; i++)
- {
- kPad[i] = rotateLeft(kPad[i - 8] ^ kPad[i - 5] ^ kPad[i - 3] ^ kPad[i - 1] ^ PHI ^ (i - 8), 11);
- }
-
- System.arraycopy(kPad, 8, w, 0, 8);
-
- //
- // compute w8 to w136
- //
- for (int i = 8; i < amount; i++)
- {
- w[i] = rotateLeft(w[i - 8] ^ w[i - 5] ^ w[i - 3] ^ w[i - 1] ^ PHI ^ i, 11);
- }
-
- //
- // create the working keys by processing w with the Sbox and IP
- //
- sb3(w[0], w[1], w[2], w[3]);
- w[0] = X0; w[1] = X1; w[2] = X2; w[3] = X3;
- sb2(w[4], w[5], w[6], w[7]);
- w[4] = X0; w[5] = X1; w[6] = X2; w[7] = X3;
- sb1(w[8], w[9], w[10], w[11]);
- w[8] = X0; w[9] = X1; w[10] = X2; w[11] = X3;
- sb0(w[12], w[13], w[14], w[15]);
- w[12] = X0; w[13] = X1; w[14] = X2; w[15] = X3;
- sb7(w[16], w[17], w[18], w[19]);
- w[16] = X0; w[17] = X1; w[18] = X2; w[19] = X3;
- sb6(w[20], w[21], w[22], w[23]);
- w[20] = X0; w[21] = X1; w[22] = X2; w[23] = X3;
- sb5(w[24], w[25], w[26], w[27]);
- w[24] = X0; w[25] = X1; w[26] = X2; w[27] = X3;
- sb4(w[28], w[29], w[30], w[31]);
- w[28] = X0; w[29] = X1; w[30] = X2; w[31] = X3;
- sb3(w[32], w[33], w[34], w[35]);
- w[32] = X0; w[33] = X1; w[34] = X2; w[35] = X3;
- sb2(w[36], w[37], w[38], w[39]);
- w[36] = X0; w[37] = X1; w[38] = X2; w[39] = X3;
- sb1(w[40], w[41], w[42], w[43]);
- w[40] = X0; w[41] = X1; w[42] = X2; w[43] = X3;
- sb0(w[44], w[45], w[46], w[47]);
- w[44] = X0; w[45] = X1; w[46] = X2; w[47] = X3;
- sb7(w[48], w[49], w[50], w[51]);
- w[48] = X0; w[49] = X1; w[50] = X2; w[51] = X3;
- sb6(w[52], w[53], w[54], w[55]);
- w[52] = X0; w[53] = X1; w[54] = X2; w[55] = X3;
- sb5(w[56], w[57], w[58], w[59]);
- w[56] = X0; w[57] = X1; w[58] = X2; w[59] = X3;
- sb4(w[60], w[61], w[62], w[63]);
- w[60] = X0; w[61] = X1; w[62] = X2; w[63] = X3;
- sb3(w[64], w[65], w[66], w[67]);
- w[64] = X0; w[65] = X1; w[66] = X2; w[67] = X3;
- sb2(w[68], w[69], w[70], w[71]);
- w[68] = X0; w[69] = X1; w[70] = X2; w[71] = X3;
- sb1(w[72], w[73], w[74], w[75]);
- w[72] = X0; w[73] = X1; w[74] = X2; w[75] = X3;
- sb0(w[76], w[77], w[78], w[79]);
- w[76] = X0; w[77] = X1; w[78] = X2; w[79] = X3;
- sb7(w[80], w[81], w[82], w[83]);
- w[80] = X0; w[81] = X1; w[82] = X2; w[83] = X3;
- sb6(w[84], w[85], w[86], w[87]);
- w[84] = X0; w[85] = X1; w[86] = X2; w[87] = X3;
- sb5(w[88], w[89], w[90], w[91]);
- w[88] = X0; w[89] = X1; w[90] = X2; w[91] = X3;
- sb4(w[92], w[93], w[94], w[95]);
- w[92] = X0; w[93] = X1; w[94] = X2; w[95] = X3;
- sb3(w[96], w[97], w[98], w[99]);
- w[96] = X0; w[97] = X1; w[98] = X2; w[99] = X3;
- sb2(w[100], w[101], w[102], w[103]);
- w[100] = X0; w[101] = X1; w[102] = X2; w[103] = X3;
- sb1(w[104], w[105], w[106], w[107]);
- w[104] = X0; w[105] = X1; w[106] = X2; w[107] = X3;
- sb0(w[108], w[109], w[110], w[111]);
- w[108] = X0; w[109] = X1; w[110] = X2; w[111] = X3;
- sb7(w[112], w[113], w[114], w[115]);
- w[112] = X0; w[113] = X1; w[114] = X2; w[115] = X3;
- sb6(w[116], w[117], w[118], w[119]);
- w[116] = X0; w[117] = X1; w[118] = X2; w[119] = X3;
- sb5(w[120], w[121], w[122], w[123]);
- w[120] = X0; w[121] = X1; w[122] = X2; w[123] = X3;
- sb4(w[124], w[125], w[126], w[127]);
- w[124] = X0; w[125] = X1; w[126] = X2; w[127] = X3;
- sb3(w[128], w[129], w[130], w[131]);
- w[128] = X0; w[129] = X1; w[130] = X2; w[131] = X3;
-
- return w;
- }
-
- private int rotateLeft(
- int x,
- int bits)
- {
- return (x << bits) | (x >>> -bits);
- }
-
- private int rotateRight(
- int x,
- int bits)
- {
- return (x >>> bits) | (x << -bits);
- }
-
- private int bytesToWord(
- byte[] src,
- int srcOff)
- {
- return (((src[srcOff] & 0xff) << 24) | ((src[srcOff + 1] & 0xff) << 16) |
- ((src[srcOff + 2] & 0xff) << 8) | ((src[srcOff + 3] & 0xff)));
- }
-
- private void wordToBytes(
- int word,
- byte[] dst,
- int dstOff)
- {
- dst[dstOff + 3] = (byte)(word);
- dst[dstOff + 2] = (byte)(word >>> 8);
- dst[dstOff + 1] = (byte)(word >>> 16);
- dst[dstOff] = (byte)(word >>> 24);
- }
-
- /**
- * Encrypt one block of plaintext.
- *
- * @param in the array containing the input data.
- * @param inOff offset into the in array the data starts at.
- * @param out the array the output data will be copied into.
- * @param outOff the offset into the out array the output will start at.
- */
- private void encryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- X3 = bytesToWord(in, inOff);
- X2 = bytesToWord(in, inOff + 4);
- X1 = bytesToWord(in, inOff + 8);
- X0 = bytesToWord(in, inOff + 12);
-
- sb0(wKey[0] ^ X0, wKey[1] ^ X1, wKey[2] ^ X2, wKey[3] ^ X3); LT();
- sb1(wKey[4] ^ X0, wKey[5] ^ X1, wKey[6] ^ X2, wKey[7] ^ X3); LT();
- sb2(wKey[8] ^ X0, wKey[9] ^ X1, wKey[10] ^ X2, wKey[11] ^ X3); LT();
- sb3(wKey[12] ^ X0, wKey[13] ^ X1, wKey[14] ^ X2, wKey[15] ^ X3); LT();
- sb4(wKey[16] ^ X0, wKey[17] ^ X1, wKey[18] ^ X2, wKey[19] ^ X3); LT();
- sb5(wKey[20] ^ X0, wKey[21] ^ X1, wKey[22] ^ X2, wKey[23] ^ X3); LT();
- sb6(wKey[24] ^ X0, wKey[25] ^ X1, wKey[26] ^ X2, wKey[27] ^ X3); LT();
- sb7(wKey[28] ^ X0, wKey[29] ^ X1, wKey[30] ^ X2, wKey[31] ^ X3); LT();
- sb0(wKey[32] ^ X0, wKey[33] ^ X1, wKey[34] ^ X2, wKey[35] ^ X3); LT();
- sb1(wKey[36] ^ X0, wKey[37] ^ X1, wKey[38] ^ X2, wKey[39] ^ X3); LT();
- sb2(wKey[40] ^ X0, wKey[41] ^ X1, wKey[42] ^ X2, wKey[43] ^ X3); LT();
- sb3(wKey[44] ^ X0, wKey[45] ^ X1, wKey[46] ^ X2, wKey[47] ^ X3); LT();
- sb4(wKey[48] ^ X0, wKey[49] ^ X1, wKey[50] ^ X2, wKey[51] ^ X3); LT();
- sb5(wKey[52] ^ X0, wKey[53] ^ X1, wKey[54] ^ X2, wKey[55] ^ X3); LT();
- sb6(wKey[56] ^ X0, wKey[57] ^ X1, wKey[58] ^ X2, wKey[59] ^ X3); LT();
- sb7(wKey[60] ^ X0, wKey[61] ^ X1, wKey[62] ^ X2, wKey[63] ^ X3); LT();
- sb0(wKey[64] ^ X0, wKey[65] ^ X1, wKey[66] ^ X2, wKey[67] ^ X3); LT();
- sb1(wKey[68] ^ X0, wKey[69] ^ X1, wKey[70] ^ X2, wKey[71] ^ X3); LT();
- sb2(wKey[72] ^ X0, wKey[73] ^ X1, wKey[74] ^ X2, wKey[75] ^ X3); LT();
- sb3(wKey[76] ^ X0, wKey[77] ^ X1, wKey[78] ^ X2, wKey[79] ^ X3); LT();
- sb4(wKey[80] ^ X0, wKey[81] ^ X1, wKey[82] ^ X2, wKey[83] ^ X3); LT();
- sb5(wKey[84] ^ X0, wKey[85] ^ X1, wKey[86] ^ X2, wKey[87] ^ X3); LT();
- sb6(wKey[88] ^ X0, wKey[89] ^ X1, wKey[90] ^ X2, wKey[91] ^ X3); LT();
- sb7(wKey[92] ^ X0, wKey[93] ^ X1, wKey[94] ^ X2, wKey[95] ^ X3); LT();
- sb0(wKey[96] ^ X0, wKey[97] ^ X1, wKey[98] ^ X2, wKey[99] ^ X3); LT();
- sb1(wKey[100] ^ X0, wKey[101] ^ X1, wKey[102] ^ X2, wKey[103] ^ X3); LT();
- sb2(wKey[104] ^ X0, wKey[105] ^ X1, wKey[106] ^ X2, wKey[107] ^ X3); LT();
- sb3(wKey[108] ^ X0, wKey[109] ^ X1, wKey[110] ^ X2, wKey[111] ^ X3); LT();
- sb4(wKey[112] ^ X0, wKey[113] ^ X1, wKey[114] ^ X2, wKey[115] ^ X3); LT();
- sb5(wKey[116] ^ X0, wKey[117] ^ X1, wKey[118] ^ X2, wKey[119] ^ X3); LT();
- sb6(wKey[120] ^ X0, wKey[121] ^ X1, wKey[122] ^ X2, wKey[123] ^ X3); LT();
- sb7(wKey[124] ^ X0, wKey[125] ^ X1, wKey[126] ^ X2, wKey[127] ^ X3);
-
- wordToBytes(wKey[131] ^ X3, out, outOff);
- wordToBytes(wKey[130] ^ X2, out, outOff + 4);
- wordToBytes(wKey[129] ^ X1, out, outOff + 8);
- wordToBytes(wKey[128] ^ X0, out, outOff + 12);
- }
-
- /**
- * Decrypt one block of ciphertext.
- *
- * @param in the array containing the input data.
- * @param inOff offset into the in array the data starts at.
- * @param out the array the output data will be copied into.
- * @param outOff the offset into the out array the output will start at.
- */
- private void decryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- X3 = wKey[131] ^ bytesToWord(in, inOff);
- X2 = wKey[130] ^ bytesToWord(in, inOff + 4);
- X1 = wKey[129] ^ bytesToWord(in, inOff + 8);
- X0 = wKey[128] ^ bytesToWord(in, inOff + 12);
-
- ib7(X0, X1, X2, X3);
- X0 ^= wKey[124]; X1 ^= wKey[125]; X2 ^= wKey[126]; X3 ^= wKey[127];
- inverseLT(); ib6(X0, X1, X2, X3);
- X0 ^= wKey[120]; X1 ^= wKey[121]; X2 ^= wKey[122]; X3 ^= wKey[123];
- inverseLT(); ib5(X0, X1, X2, X3);
- X0 ^= wKey[116]; X1 ^= wKey[117]; X2 ^= wKey[118]; X3 ^= wKey[119];
- inverseLT(); ib4(X0, X1, X2, X3);
- X0 ^= wKey[112]; X1 ^= wKey[113]; X2 ^= wKey[114]; X3 ^= wKey[115];
- inverseLT(); ib3(X0, X1, X2, X3);
- X0 ^= wKey[108]; X1 ^= wKey[109]; X2 ^= wKey[110]; X3 ^= wKey[111];
- inverseLT(); ib2(X0, X1, X2, X3);
- X0 ^= wKey[104]; X1 ^= wKey[105]; X2 ^= wKey[106]; X3 ^= wKey[107];
- inverseLT(); ib1(X0, X1, X2, X3);
- X0 ^= wKey[100]; X1 ^= wKey[101]; X2 ^= wKey[102]; X3 ^= wKey[103];
- inverseLT(); ib0(X0, X1, X2, X3);
- X0 ^= wKey[96]; X1 ^= wKey[97]; X2 ^= wKey[98]; X3 ^= wKey[99];
- inverseLT(); ib7(X0, X1, X2, X3);
- X0 ^= wKey[92]; X1 ^= wKey[93]; X2 ^= wKey[94]; X3 ^= wKey[95];
- inverseLT(); ib6(X0, X1, X2, X3);
- X0 ^= wKey[88]; X1 ^= wKey[89]; X2 ^= wKey[90]; X3 ^= wKey[91];
- inverseLT(); ib5(X0, X1, X2, X3);
- X0 ^= wKey[84]; X1 ^= wKey[85]; X2 ^= wKey[86]; X3 ^= wKey[87];
- inverseLT(); ib4(X0, X1, X2, X3);
- X0 ^= wKey[80]; X1 ^= wKey[81]; X2 ^= wKey[82]; X3 ^= wKey[83];
- inverseLT(); ib3(X0, X1, X2, X3);
- X0 ^= wKey[76]; X1 ^= wKey[77]; X2 ^= wKey[78]; X3 ^= wKey[79];
- inverseLT(); ib2(X0, X1, X2, X3);
- X0 ^= wKey[72]; X1 ^= wKey[73]; X2 ^= wKey[74]; X3 ^= wKey[75];
- inverseLT(); ib1(X0, X1, X2, X3);
- X0 ^= wKey[68]; X1 ^= wKey[69]; X2 ^= wKey[70]; X3 ^= wKey[71];
- inverseLT(); ib0(X0, X1, X2, X3);
- X0 ^= wKey[64]; X1 ^= wKey[65]; X2 ^= wKey[66]; X3 ^= wKey[67];
- inverseLT(); ib7(X0, X1, X2, X3);
- X0 ^= wKey[60]; X1 ^= wKey[61]; X2 ^= wKey[62]; X3 ^= wKey[63];
- inverseLT(); ib6(X0, X1, X2, X3);
- X0 ^= wKey[56]; X1 ^= wKey[57]; X2 ^= wKey[58]; X3 ^= wKey[59];
- inverseLT(); ib5(X0, X1, X2, X3);
- X0 ^= wKey[52]; X1 ^= wKey[53]; X2 ^= wKey[54]; X3 ^= wKey[55];
- inverseLT(); ib4(X0, X1, X2, X3);
- X0 ^= wKey[48]; X1 ^= wKey[49]; X2 ^= wKey[50]; X3 ^= wKey[51];
- inverseLT(); ib3(X0, X1, X2, X3);
- X0 ^= wKey[44]; X1 ^= wKey[45]; X2 ^= wKey[46]; X3 ^= wKey[47];
- inverseLT(); ib2(X0, X1, X2, X3);
- X0 ^= wKey[40]; X1 ^= wKey[41]; X2 ^= wKey[42]; X3 ^= wKey[43];
- inverseLT(); ib1(X0, X1, X2, X3);
- X0 ^= wKey[36]; X1 ^= wKey[37]; X2 ^= wKey[38]; X3 ^= wKey[39];
- inverseLT(); ib0(X0, X1, X2, X3);
- X0 ^= wKey[32]; X1 ^= wKey[33]; X2 ^= wKey[34]; X3 ^= wKey[35];
- inverseLT(); ib7(X0, X1, X2, X3);
- X0 ^= wKey[28]; X1 ^= wKey[29]; X2 ^= wKey[30]; X3 ^= wKey[31];
- inverseLT(); ib6(X0, X1, X2, X3);
- X0 ^= wKey[24]; X1 ^= wKey[25]; X2 ^= wKey[26]; X3 ^= wKey[27];
- inverseLT(); ib5(X0, X1, X2, X3);
- X0 ^= wKey[20]; X1 ^= wKey[21]; X2 ^= wKey[22]; X3 ^= wKey[23];
- inverseLT(); ib4(X0, X1, X2, X3);
- X0 ^= wKey[16]; X1 ^= wKey[17]; X2 ^= wKey[18]; X3 ^= wKey[19];
- inverseLT(); ib3(X0, X1, X2, X3);
- X0 ^= wKey[12]; X1 ^= wKey[13]; X2 ^= wKey[14]; X3 ^= wKey[15];
- inverseLT(); ib2(X0, X1, X2, X3);
- X0 ^= wKey[8]; X1 ^= wKey[9]; X2 ^= wKey[10]; X3 ^= wKey[11];
- inverseLT(); ib1(X0, X1, X2, X3);
- X0 ^= wKey[4]; X1 ^= wKey[5]; X2 ^= wKey[6]; X3 ^= wKey[7];
- inverseLT(); ib0(X0, X1, X2, X3);
-
- wordToBytes(X3 ^ wKey[3], out, outOff);
- wordToBytes(X2 ^ wKey[2], out, outOff + 4);
- wordToBytes(X1 ^ wKey[1], out, outOff + 8);
- wordToBytes(X0 ^ wKey[0], out, outOff + 12);
- }
-
- /**
- * The sboxes below are based on the work of Brian Gladman and
- * Sam Simpson, whose original notice appears below.
- * <p>
- * For further details see:
- * http://fp.gladman.plus.com/cryptography_technology/serpent/
- */
-
- /* Partially optimised Serpent S Box boolean functions derived */
- /* using a recursive descent analyser but without a full search */
- /* of all subtrees. This set of S boxes is the result of work */
- /* by Sam Simpson and Brian Gladman using the spare time on a */
- /* cluster of high capacity servers to search for S boxes with */
- /* this customised search engine. There are now an average of */
- /* 15.375 terms per S box. */
- /* */
- /* Copyright: Dr B. R Gladman (gladman@seven77.demon.co.uk) */
- /* and Sam Simpson (s.simpson@mia.co.uk) */
- /* 17th December 1998 */
- /* */
- /* We hereby give permission for information in this file to be */
- /* used freely subject only to acknowledgement of its origin. */
-
- /**
- * S0 - { 3, 8,15, 1,10, 6, 5,11,14,13, 4, 2, 7, 0, 9,12 } - 15 terms.
- */
- private void sb0(int a, int b, int c, int d)
- {
- int t1 = a ^ d;
- int t3 = c ^ t1;
- int t4 = b ^ t3;
- X3 = (a & d) ^ t4;
- int t7 = a ^ (b & t1);
- X2 = t4 ^ (c | t7);
- int t12 = X3 & (t3 ^ t7);
- X1 = (~t3) ^ t12;
- X0 = t12 ^ (~t7);
- }
-
- /**
- * InvSO - {13, 3,11, 0,10, 6, 5,12, 1,14, 4, 7,15, 9, 8, 2 } - 15 terms.
- */
- private void ib0(int a, int b, int c, int d)
- {
- int t1 = ~a;
- int t2 = a ^ b;
- int t4 = d ^ (t1 | t2);
- int t5 = c ^ t4;
- X2 = t2 ^ t5;
- int t8 = t1 ^ (d & t2);
- X1 = t4 ^ (X2 & t8);
- X3 = (a & t4) ^ (t5 | X1);
- X0 = X3 ^ (t5 ^ t8);
- }
-
- /**
- * S1 - {15,12, 2, 7, 9, 0, 5,10, 1,11,14, 8, 6,13, 3, 4 } - 14 terms.
- */
- private void sb1(int a, int b, int c, int d)
- {
- int t2 = b ^ (~a);
- int t5 = c ^ (a | t2);
- X2 = d ^ t5;
- int t7 = b ^ (d | t2);
- int t8 = t2 ^ X2;
- X3 = t8 ^ (t5 & t7);
- int t11 = t5 ^ t7;
- X1 = X3 ^ t11;
- X0 = t5 ^ (t8 & t11);
- }
-
- /**
- * InvS1 - { 5, 8, 2,14,15, 6,12, 3,11, 4, 7, 9, 1,13,10, 0 } - 14 steps.
- */
- private void ib1(int a, int b, int c, int d)
- {
- int t1 = b ^ d;
- int t3 = a ^ (b & t1);
- int t4 = t1 ^ t3;
- X3 = c ^ t4;
- int t7 = b ^ (t1 & t3);
- int t8 = X3 | t7;
- X1 = t3 ^ t8;
- int t10 = ~X1;
- int t11 = X3 ^ t7;
- X0 = t10 ^ t11;
- X2 = t4 ^ (t10 | t11);
- }
-
- /**
- * S2 - { 8, 6, 7, 9, 3,12,10,15,13, 1,14, 4, 0,11, 5, 2 } - 16 terms.
- */
- private void sb2(int a, int b, int c, int d)
- {
- int t1 = ~a;
- int t2 = b ^ d;
- int t3 = c & t1;
- X0 = t2 ^ t3;
- int t5 = c ^ t1;
- int t6 = c ^ X0;
- int t7 = b & t6;
- X3 = t5 ^ t7;
- X2 = a ^ ((d | t7) & (X0 | t5));
- X1 = (t2 ^ X3) ^ (X2 ^ (d | t1));
- }
-
- /**
- * InvS2 - {12, 9,15, 4,11,14, 1, 2, 0, 3, 6,13, 5, 8,10, 7 } - 16 steps.
- */
- private void ib2(int a, int b, int c, int d)
- {
- int t1 = b ^ d;
- int t2 = ~t1;
- int t3 = a ^ c;
- int t4 = c ^ t1;
- int t5 = b & t4;
- X0 = t3 ^ t5;
- int t7 = a | t2;
- int t8 = d ^ t7;
- int t9 = t3 | t8;
- X3 = t1 ^ t9;
- int t11 = ~t4;
- int t12 = X0 | X3;
- X1 = t11 ^ t12;
- X2 = (d & t11) ^ (t3 ^ t12);
- }
-
- /**
- * S3 - { 0,15,11, 8,12, 9, 6, 3,13, 1, 2, 4,10, 7, 5,14 } - 16 terms.
- */
- private void sb3(int a, int b, int c, int d)
- {
- int t1 = a ^ b;
- int t2 = a & c;
- int t3 = a | d;
- int t4 = c ^ d;
- int t5 = t1 & t3;
- int t6 = t2 | t5;
- X2 = t4 ^ t6;
- int t8 = b ^ t3;
- int t9 = t6 ^ t8;
- int t10 = t4 & t9;
- X0 = t1 ^ t10;
- int t12 = X2 & X0;
- X1 = t9 ^ t12;
- X3 = (b | d) ^ (t4 ^ t12);
- }
-
- /**
- * InvS3 - { 0, 9,10, 7,11,14, 6,13, 3, 5,12, 2, 4, 8,15, 1 } - 15 terms
- */
- private void ib3(int a, int b, int c, int d)
- {
- int t1 = a | b;
- int t2 = b ^ c;
- int t3 = b & t2;
- int t4 = a ^ t3;
- int t5 = c ^ t4;
- int t6 = d | t4;
- X0 = t2 ^ t6;
- int t8 = t2 | t6;
- int t9 = d ^ t8;
- X2 = t5 ^ t9;
- int t11 = t1 ^ t9;
- int t12 = X0 & t11;
- X3 = t4 ^ t12;
- X1 = X3 ^ (X0 ^ t11);
- }
-
- /**
- * S4 - { 1,15, 8, 3,12, 0,11, 6, 2, 5, 4,10, 9,14, 7,13 } - 15 terms.
- */
- private void sb4(int a, int b, int c, int d)
- {
- int t1 = a ^ d;
- int t2 = d & t1;
- int t3 = c ^ t2;
- int t4 = b | t3;
- X3 = t1 ^ t4;
- int t6 = ~b;
- int t7 = t1 | t6;
- X0 = t3 ^ t7;
- int t9 = a & X0;
- int t10 = t1 ^ t6;
- int t11 = t4 & t10;
- X2 = t9 ^ t11;
- X1 = (a ^ t3) ^ (t10 & X2);
- }
-
- /**
- * InvS4 - { 5, 0, 8, 3,10, 9, 7,14, 2,12,11, 6, 4,15,13, 1 } - 15 terms.
- */
- private void ib4(int a, int b, int c, int d)
- {
- int t1 = c | d;
- int t2 = a & t1;
- int t3 = b ^ t2;
- int t4 = a & t3;
- int t5 = c ^ t4;
- X1 = d ^ t5;
- int t7 = ~a;
- int t8 = t5 & X1;
- X3 = t3 ^ t8;
- int t10 = X1 | t7;
- int t11 = d ^ t10;
- X0 = X3 ^ t11;
- X2 = (t3 & t11) ^ (X1 ^ t7);
- }
-
- /**
- * S5 - {15, 5, 2,11, 4,10, 9,12, 0, 3,14, 8,13, 6, 7, 1 } - 16 terms.
- */
- private void sb5(int a, int b, int c, int d)
- {
- int t1 = ~a;
- int t2 = a ^ b;
- int t3 = a ^ d;
- int t4 = c ^ t1;
- int t5 = t2 | t3;
- X0 = t4 ^ t5;
- int t7 = d & X0;
- int t8 = t2 ^ X0;
- X1 = t7 ^ t8;
- int t10 = t1 | X0;
- int t11 = t2 | t7;
- int t12 = t3 ^ t10;
- X2 = t11 ^ t12;
- X3 = (b ^ t7) ^ (X1 & t12);
- }
-
- /**
- * InvS5 - { 8,15, 2, 9, 4, 1,13,14,11, 6, 5, 3, 7,12,10, 0 } - 16 terms.
- */
- private void ib5(int a, int b, int c, int d)
- {
- int t1 = ~c;
- int t2 = b & t1;
- int t3 = d ^ t2;
- int t4 = a & t3;
- int t5 = b ^ t1;
- X3 = t4 ^ t5;
- int t7 = b | X3;
- int t8 = a & t7;
- X1 = t3 ^ t8;
- int t10 = a | d;
- int t11 = t1 ^ t7;
- X0 = t10 ^ t11;
- X2 = (b & t10) ^ (t4 | (a ^ c));
- }
-
- /**
- * S6 - { 7, 2,12, 5, 8, 4, 6,11,14, 9, 1,15,13, 3,10, 0 } - 15 terms.
- */
- private void sb6(int a, int b, int c, int d)
- {
- int t1 = ~a;
- int t2 = a ^ d;
- int t3 = b ^ t2;
- int t4 = t1 | t2;
- int t5 = c ^ t4;
- X1 = b ^ t5;
- int t7 = t2 | X1;
- int t8 = d ^ t7;
- int t9 = t5 & t8;
- X2 = t3 ^ t9;
- int t11 = t5 ^ t8;
- X0 = X2 ^ t11;
- X3 = (~t5) ^ (t3 & t11);
- }
-
- /**
- * InvS6 - {15,10, 1,13, 5, 3, 6, 0, 4, 9,14, 7, 2,12, 8,11 } - 15 terms.
- */
- private void ib6(int a, int b, int c, int d)
- {
- int t1 = ~a;
- int t2 = a ^ b;
- int t3 = c ^ t2;
- int t4 = c | t1;
- int t5 = d ^ t4;
- X1 = t3 ^ t5;
- int t7 = t3 & t5;
- int t8 = t2 ^ t7;
- int t9 = b | t8;
- X3 = t5 ^ t9;
- int t11 = b | X3;
- X0 = t8 ^ t11;
- X2 = (d & t1) ^ (t3 ^ t11);
- }
-
- /**
- * S7 - { 1,13,15, 0,14, 8, 2,11, 7, 4,12,10, 9, 3, 5, 6 } - 16 terms.
- */
- private void sb7(int a, int b, int c, int d)
- {
- int t1 = b ^ c;
- int t2 = c & t1;
- int t3 = d ^ t2;
- int t4 = a ^ t3;
- int t5 = d | t1;
- int t6 = t4 & t5;
- X1 = b ^ t6;
- int t8 = t3 | X1;
- int t9 = a & t4;
- X3 = t1 ^ t9;
- int t11 = t4 ^ t8;
- int t12 = X3 & t11;
- X2 = t3 ^ t12;
- X0 = (~t11) ^ (X3 & X2);
- }
-
- /**
- * InvS7 - { 3, 0, 6,13, 9,14,15, 8, 5,12,11, 7,10, 1, 4, 2 } - 17 terms.
- */
- private void ib7(int a, int b, int c, int d)
- {
- int t3 = c | (a & b);
- int t4 = d & (a | b);
- X3 = t3 ^ t4;
- int t6 = ~d;
- int t7 = b ^ t4;
- int t9 = t7 | (X3 ^ t6);
- X1 = a ^ t9;
- X0 = (c ^ t7) ^ (d | X1);
- X2 = (t3 ^ X1) ^ (X0 ^ (a & X3));
- }
-
- /**
- * Apply the linear transformation to the register set.
- */
- private void LT()
- {
- int x0 = rotateLeft(X0, 13);
- int x2 = rotateLeft(X2, 3);
- int x1 = X1 ^ x0 ^ x2 ;
- int x3 = X3 ^ x2 ^ x0 << 3;
-
- X1 = rotateLeft(x1, 1);
- X3 = rotateLeft(x3, 7);
- X0 = rotateLeft(x0 ^ X1 ^ X3, 5);
- X2 = rotateLeft(x2 ^ X3 ^ (X1 << 7), 22);
- }
-
- /**
- * Apply the inverse of the linear transformation to the register set.
- */
- private void inverseLT()
- {
- int x2 = rotateRight(X2, 22) ^ X3 ^ (X1 << 7);
- int x0 = rotateRight(X0, 5) ^ X1 ^ X3;
- int x3 = rotateRight(X3, 7);
- int x1 = rotateRight(X1, 1);
- X3 = x3 ^ x2 ^ x0 << 3;
- X1 = x1 ^ x0 ^ x2;
- X2 = rotateRight(x2, 3);
- X0 = rotateRight(x0, 13);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/Shacal2Engine.java b/core/src/main/java/org/bouncycastle/crypto/engines/Shacal2Engine.java
deleted file mode 100644
index b59205de..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/Shacal2Engine.java
+++ /dev/null
@@ -1,201 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/engines/SkipjackEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/SkipjackEngine.java
deleted file mode 100644
index 1fac5362..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/SkipjackEngine.java
+++ /dev/null
@@ -1,260 +0,0 @@
-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;
-
-/**
- * a class that provides a basic SKIPJACK engine.
- */
-public class SkipjackEngine
- implements BlockCipher
-{
- static final int BLOCK_SIZE = 8;
-
- static short ftable[] =
- {
- 0xa3, 0xd7, 0x09, 0x83, 0xf8, 0x48, 0xf6, 0xf4, 0xb3, 0x21, 0x15, 0x78, 0x99, 0xb1, 0xaf, 0xf9,
- 0xe7, 0x2d, 0x4d, 0x8a, 0xce, 0x4c, 0xca, 0x2e, 0x52, 0x95, 0xd9, 0x1e, 0x4e, 0x38, 0x44, 0x28,
- 0x0a, 0xdf, 0x02, 0xa0, 0x17, 0xf1, 0x60, 0x68, 0x12, 0xb7, 0x7a, 0xc3, 0xe9, 0xfa, 0x3d, 0x53,
- 0x96, 0x84, 0x6b, 0xba, 0xf2, 0x63, 0x9a, 0x19, 0x7c, 0xae, 0xe5, 0xf5, 0xf7, 0x16, 0x6a, 0xa2,
- 0x39, 0xb6, 0x7b, 0x0f, 0xc1, 0x93, 0x81, 0x1b, 0xee, 0xb4, 0x1a, 0xea, 0xd0, 0x91, 0x2f, 0xb8,
- 0x55, 0xb9, 0xda, 0x85, 0x3f, 0x41, 0xbf, 0xe0, 0x5a, 0x58, 0x80, 0x5f, 0x66, 0x0b, 0xd8, 0x90,
- 0x35, 0xd5, 0xc0, 0xa7, 0x33, 0x06, 0x65, 0x69, 0x45, 0x00, 0x94, 0x56, 0x6d, 0x98, 0x9b, 0x76,
- 0x97, 0xfc, 0xb2, 0xc2, 0xb0, 0xfe, 0xdb, 0x20, 0xe1, 0xeb, 0xd6, 0xe4, 0xdd, 0x47, 0x4a, 0x1d,
- 0x42, 0xed, 0x9e, 0x6e, 0x49, 0x3c, 0xcd, 0x43, 0x27, 0xd2, 0x07, 0xd4, 0xde, 0xc7, 0x67, 0x18,
- 0x89, 0xcb, 0x30, 0x1f, 0x8d, 0xc6, 0x8f, 0xaa, 0xc8, 0x74, 0xdc, 0xc9, 0x5d, 0x5c, 0x31, 0xa4,
- 0x70, 0x88, 0x61, 0x2c, 0x9f, 0x0d, 0x2b, 0x87, 0x50, 0x82, 0x54, 0x64, 0x26, 0x7d, 0x03, 0x40,
- 0x34, 0x4b, 0x1c, 0x73, 0xd1, 0xc4, 0xfd, 0x3b, 0xcc, 0xfb, 0x7f, 0xab, 0xe6, 0x3e, 0x5b, 0xa5,
- 0xad, 0x04, 0x23, 0x9c, 0x14, 0x51, 0x22, 0xf0, 0x29, 0x79, 0x71, 0x7e, 0xff, 0x8c, 0x0e, 0xe2,
- 0x0c, 0xef, 0xbc, 0x72, 0x75, 0x6f, 0x37, 0xa1, 0xec, 0xd3, 0x8e, 0x62, 0x8b, 0x86, 0x10, 0xe8,
- 0x08, 0x77, 0x11, 0xbe, 0x92, 0x4f, 0x24, 0xc5, 0x32, 0x36, 0x9d, 0xcf, 0xf3, 0xa6, 0xbb, 0xac,
- 0x5e, 0x6c, 0xa9, 0x13, 0x57, 0x25, 0xb5, 0xe3, 0xbd, 0xa8, 0x3a, 0x01, 0x05, 0x59, 0x2a, 0x46
- };
-
- private int[] key0, key1, key2, key3;
- private boolean encrypting;
-
- /**
- * initialise a SKIPJACK cipher.
- *
- * @param encrypting whether or not we are for encryption.
- * @param params the parameters required to set up the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean encrypting,
- CipherParameters params)
- {
- if (!(params instanceof KeyParameter))
- {
- throw new IllegalArgumentException("invalid parameter passed to SKIPJACK init - " + params.getClass().getName());
- }
-
- byte[] keyBytes = ((KeyParameter)params).getKey();
-
- this.encrypting = encrypting;
- this.key0 = new int[32];
- this.key1 = new int[32];
- this.key2 = new int[32];
- this.key3 = new int[32];
-
- //
- // expand the key to 128 bytes in 4 parts (saving us a modulo, multiply
- // and an addition).
- //
- for (int i = 0; i < 32; i ++)
- {
- key0[i] = keyBytes[(i * 4) % 10] & 0xff;
- key1[i] = keyBytes[(i * 4 + 1) % 10] & 0xff;
- key2[i] = keyBytes[(i * 4 + 2) % 10] & 0xff;
- key3[i] = keyBytes[(i * 4 + 3) % 10] & 0xff;
- }
- }
-
- public String getAlgorithmName()
- {
- return "SKIPJACK";
- }
-
- public int getBlockSize()
- {
- return BLOCK_SIZE;
- }
-
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- if (key1 == null)
- {
- throw new IllegalStateException("SKIPJACK engine not initialised");
- }
-
- if ((inOff + BLOCK_SIZE) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + BLOCK_SIZE) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- if (encrypting)
- {
- encryptBlock(in, inOff, out, outOff);
- }
- else
- {
- decryptBlock(in, inOff, out, outOff);
- }
-
- return BLOCK_SIZE;
- }
-
- public void reset()
- {
- }
-
- /**
- * The G permutation
- */
- private int g(
- int k,
- int w)
- {
- int g1, g2, g3, g4, g5, g6;
-
- g1 = (w >> 8) & 0xff;
- g2 = w & 0xff;
-
- g3 = ftable[g2 ^ key0[k]] ^ g1;
- g4 = ftable[g3 ^ key1[k]] ^ g2;
- g5 = ftable[g4 ^ key2[k]] ^ g3;
- g6 = ftable[g5 ^ key3[k]] ^ g4;
-
- return ((g5 << 8) + g6);
- }
-
- public int encryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- int w1 = (in[inOff + 0] << 8) + (in[inOff + 1] & 0xff);
- int w2 = (in[inOff + 2] << 8) + (in[inOff + 3] & 0xff);
- int w3 = (in[inOff + 4] << 8) + (in[inOff + 5] & 0xff);
- int w4 = (in[inOff + 6] << 8) + (in[inOff + 7] & 0xff);
-
- int k = 0;
-
- for (int t = 0; t < 2; t++)
- {
- for(int i = 0; i < 8; i++)
- {
- int tmp = w4;
- w4 = w3;
- w3 = w2;
- w2 = g(k, w1);
- w1 = w2 ^ tmp ^ (k + 1);
- k++;
- }
-
- for(int i = 0; i < 8; i++)
- {
- int tmp = w4;
- w4 = w3;
- w3 = w1 ^ w2 ^ (k + 1);
- w2 = g(k, w1);
- w1 = tmp;
- k++;
- }
- }
-
- out[outOff + 0] = (byte)((w1 >> 8));
- out[outOff + 1] = (byte)(w1);
- out[outOff + 2] = (byte)((w2 >> 8));
- out[outOff + 3] = (byte)(w2);
- out[outOff + 4] = (byte)((w3 >> 8));
- out[outOff + 5] = (byte)(w3);
- out[outOff + 6] = (byte)((w4 >> 8));
- out[outOff + 7] = (byte)(w4);
-
- return BLOCK_SIZE;
- }
-
- /**
- * the inverse of the G permutation.
- */
- private int h(
- int k,
- int w)
- {
- int h1, h2, h3, h4, h5, h6;
-
- h1 = w & 0xff;
- h2 = (w >> 8) & 0xff;
-
- h3 = ftable[h2 ^ key3[k]] ^ h1;
- h4 = ftable[h3 ^ key2[k]] ^ h2;
- h5 = ftable[h4 ^ key1[k]] ^ h3;
- h6 = ftable[h5 ^ key0[k]] ^ h4;
-
- return ((h6 << 8) + h5);
- }
-
- public int decryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- int w2 = (in[inOff + 0] << 8) + (in[inOff + 1] & 0xff);
- int w1 = (in[inOff + 2] << 8) + (in[inOff + 3] & 0xff);
- int w4 = (in[inOff + 4] << 8) + (in[inOff + 5] & 0xff);
- int w3 = (in[inOff + 6] << 8) + (in[inOff + 7] & 0xff);
-
- int k = 31;
-
- for (int t = 0; t < 2; t++)
- {
- for(int i = 0; i < 8; i++)
- {
- int tmp = w4;
- w4 = w3;
- w3 = w2;
- w2 = h(k, w1);
- w1 = w2 ^ tmp ^ (k + 1);
- k--;
- }
-
- for(int i = 0; i < 8; i++)
- {
- int tmp = w4;
- w4 = w3;
- w3 = w1 ^ w2 ^ (k + 1);
- w2 = h(k, w1);
- w1 = tmp;
- k--;
- }
- }
-
- out[outOff + 0] = (byte)((w2 >> 8));
- out[outOff + 1] = (byte)(w2);
- out[outOff + 2] = (byte)((w1 >> 8));
- out[outOff + 3] = (byte)(w1);
- out[outOff + 4] = (byte)((w4 >> 8));
- out[outOff + 5] = (byte)(w4);
- out[outOff + 6] = (byte)((w3 >> 8));
- out[outOff + 7] = (byte)(w3);
-
- return BLOCK_SIZE;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/TEAEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/TEAEngine.java
deleted file mode 100644
index ac65443c..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/TEAEngine.java
+++ /dev/null
@@ -1,184 +0,0 @@
-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;
-
-/**
- * An TEA engine.
- */
-public class TEAEngine
- implements BlockCipher
-{
- private static final int rounds = 32,
- block_size = 8,
-// key_size = 16,
- delta = 0x9E3779B9,
- d_sum = 0xC6EF3720; // sum on decrypt
- /*
- * the expanded key array of 4 subkeys
- */
- private int _a, _b, _c, _d;
- private boolean _initialised;
- private boolean _forEncryption;
-
- /**
- * Create an instance of the TEA encryption algorithm
- * and set some defaults
- */
- public TEAEngine()
- {
- _initialised = false;
- }
-
- public String getAlgorithmName()
- {
- return "TEA";
- }
-
- public int getBlockSize()
- {
- return block_size;
- }
-
- /**
- * initialise
- *
- * @param forEncryption whether or not we are for encryption.
- * @param params the parameters required to set up the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean forEncryption,
- CipherParameters params)
- {
- if (!(params instanceof KeyParameter))
- {
- throw new IllegalArgumentException("invalid parameter passed to TEA init - " + params.getClass().getName());
- }
-
- _forEncryption = forEncryption;
- _initialised = true;
-
- KeyParameter p = (KeyParameter)params;
-
- setKey(p.getKey());
- }
-
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- if (!_initialised)
- {
- throw new IllegalStateException(getAlgorithmName()+" not initialised");
- }
-
- if ((inOff + block_size) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + block_size) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- return (_forEncryption) ? encryptBlock(in, inOff, out, outOff)
- : decryptBlock(in, inOff, out, outOff);
- }
-
- public void reset()
- {
- }
-
- /**
- * Re-key the cipher.
- * <p>
- * @param key the key to be used
- */
- 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);
- _d = bytesToInt(key, 12);
- }
-
- private int encryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- // Pack bytes into integers
- int v0 = bytesToInt(in, inOff);
- int v1 = bytesToInt(in, inOff + 4);
-
- int sum = 0;
-
- for (int i = 0; i != rounds; i++)
- {
- sum += delta;
- v0 += ((v1 << 4) + _a) ^ (v1 + sum) ^ ((v1 >>> 5) + _b);
- v1 += ((v0 << 4) + _c) ^ (v0 + sum) ^ ((v0 >>> 5) + _d);
- }
-
- unpackInt(v0, out, outOff);
- unpackInt(v1, out, outOff + 4);
-
- return block_size;
- }
-
- private int decryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- // Pack bytes into integers
- int v0 = bytesToInt(in, inOff);
- int v1 = bytesToInt(in, inOff + 4);
-
- int sum = d_sum;
-
- for (int i = 0; i != rounds; i++)
- {
- v1 -= ((v0 << 4) + _c) ^ (v0 + sum) ^ ((v0 >>> 5) + _d);
- v0 -= ((v1 << 4) + _a) ^ (v1 + sum) ^ ((v1 >>> 5) + _b);
- sum -= delta;
- }
-
- unpackInt(v0, out, outOff);
- unpackInt(v1, out, outOff + 4);
-
- return block_size;
- }
-
- private int bytesToInt(byte[] in, int inOff)
- {
- return ((in[inOff++]) << 24) |
- ((in[inOff++] & 255) << 16) |
- ((in[inOff++] & 255) << 8) |
- ((in[inOff] & 255));
- }
-
- private void unpackInt(int v, byte[] out, int outOff)
- {
- out[outOff++] = (byte)(v >>> 24);
- out[outOff++] = (byte)(v >>> 16);
- out[outOff++] = (byte)(v >>> 8);
- out[outOff ] = (byte)v;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/ThreefishEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/ThreefishEngine.java
deleted file mode 100644
index 33660224..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/ThreefishEngine.java
+++ /dev/null
@@ -1,1494 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/engines/TwofishEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/TwofishEngine.java
deleted file mode 100644
index 31ac0878..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/TwofishEngine.java
+++ /dev/null
@@ -1,680 +0,0 @@
-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;
-
-/**
- * A class that provides Twofish encryption operations.
- *
- * This Java implementation is based on the Java reference
- * implementation provided by Bruce Schneier and developed
- * by Raif S. Naffah.
- */
-public final class TwofishEngine
- implements BlockCipher
-{
- private static final byte[][] P = {
- { // p0
- (byte) 0xA9, (byte) 0x67, (byte) 0xB3, (byte) 0xE8,
- (byte) 0x04, (byte) 0xFD, (byte) 0xA3, (byte) 0x76,
- (byte) 0x9A, (byte) 0x92, (byte) 0x80, (byte) 0x78,
- (byte) 0xE4, (byte) 0xDD, (byte) 0xD1, (byte) 0x38,
- (byte) 0x0D, (byte) 0xC6, (byte) 0x35, (byte) 0x98,
- (byte) 0x18, (byte) 0xF7, (byte) 0xEC, (byte) 0x6C,
- (byte) 0x43, (byte) 0x75, (byte) 0x37, (byte) 0x26,
- (byte) 0xFA, (byte) 0x13, (byte) 0x94, (byte) 0x48,
- (byte) 0xF2, (byte) 0xD0, (byte) 0x8B, (byte) 0x30,
- (byte) 0x84, (byte) 0x54, (byte) 0xDF, (byte) 0x23,
- (byte) 0x19, (byte) 0x5B, (byte) 0x3D, (byte) 0x59,
- (byte) 0xF3, (byte) 0xAE, (byte) 0xA2, (byte) 0x82,
- (byte) 0x63, (byte) 0x01, (byte) 0x83, (byte) 0x2E,
- (byte) 0xD9, (byte) 0x51, (byte) 0x9B, (byte) 0x7C,
- (byte) 0xA6, (byte) 0xEB, (byte) 0xA5, (byte) 0xBE,
- (byte) 0x16, (byte) 0x0C, (byte) 0xE3, (byte) 0x61,
- (byte) 0xC0, (byte) 0x8C, (byte) 0x3A, (byte) 0xF5,
- (byte) 0x73, (byte) 0x2C, (byte) 0x25, (byte) 0x0B,
- (byte) 0xBB, (byte) 0x4E, (byte) 0x89, (byte) 0x6B,
- (byte) 0x53, (byte) 0x6A, (byte) 0xB4, (byte) 0xF1,
- (byte) 0xE1, (byte) 0xE6, (byte) 0xBD, (byte) 0x45,
- (byte) 0xE2, (byte) 0xF4, (byte) 0xB6, (byte) 0x66,
- (byte) 0xCC, (byte) 0x95, (byte) 0x03, (byte) 0x56,
- (byte) 0xD4, (byte) 0x1C, (byte) 0x1E, (byte) 0xD7,
- (byte) 0xFB, (byte) 0xC3, (byte) 0x8E, (byte) 0xB5,
- (byte) 0xE9, (byte) 0xCF, (byte) 0xBF, (byte) 0xBA,
- (byte) 0xEA, (byte) 0x77, (byte) 0x39, (byte) 0xAF,
- (byte) 0x33, (byte) 0xC9, (byte) 0x62, (byte) 0x71,
- (byte) 0x81, (byte) 0x79, (byte) 0x09, (byte) 0xAD,
- (byte) 0x24, (byte) 0xCD, (byte) 0xF9, (byte) 0xD8,
- (byte) 0xE5, (byte) 0xC5, (byte) 0xB9, (byte) 0x4D,
- (byte) 0x44, (byte) 0x08, (byte) 0x86, (byte) 0xE7,
- (byte) 0xA1, (byte) 0x1D, (byte) 0xAA, (byte) 0xED,
- (byte) 0x06, (byte) 0x70, (byte) 0xB2, (byte) 0xD2,
- (byte) 0x41, (byte) 0x7B, (byte) 0xA0, (byte) 0x11,
- (byte) 0x31, (byte) 0xC2, (byte) 0x27, (byte) 0x90,
- (byte) 0x20, (byte) 0xF6, (byte) 0x60, (byte) 0xFF,
- (byte) 0x96, (byte) 0x5C, (byte) 0xB1, (byte) 0xAB,
- (byte) 0x9E, (byte) 0x9C, (byte) 0x52, (byte) 0x1B,
- (byte) 0x5F, (byte) 0x93, (byte) 0x0A, (byte) 0xEF,
- (byte) 0x91, (byte) 0x85, (byte) 0x49, (byte) 0xEE,
- (byte) 0x2D, (byte) 0x4F, (byte) 0x8F, (byte) 0x3B,
- (byte) 0x47, (byte) 0x87, (byte) 0x6D, (byte) 0x46,
- (byte) 0xD6, (byte) 0x3E, (byte) 0x69, (byte) 0x64,
- (byte) 0x2A, (byte) 0xCE, (byte) 0xCB, (byte) 0x2F,
- (byte) 0xFC, (byte) 0x97, (byte) 0x05, (byte) 0x7A,
- (byte) 0xAC, (byte) 0x7F, (byte) 0xD5, (byte) 0x1A,
- (byte) 0x4B, (byte) 0x0E, (byte) 0xA7, (byte) 0x5A,
- (byte) 0x28, (byte) 0x14, (byte) 0x3F, (byte) 0x29,
- (byte) 0x88, (byte) 0x3C, (byte) 0x4C, (byte) 0x02,
- (byte) 0xB8, (byte) 0xDA, (byte) 0xB0, (byte) 0x17,
- (byte) 0x55, (byte) 0x1F, (byte) 0x8A, (byte) 0x7D,
- (byte) 0x57, (byte) 0xC7, (byte) 0x8D, (byte) 0x74,
- (byte) 0xB7, (byte) 0xC4, (byte) 0x9F, (byte) 0x72,
- (byte) 0x7E, (byte) 0x15, (byte) 0x22, (byte) 0x12,
- (byte) 0x58, (byte) 0x07, (byte) 0x99, (byte) 0x34,
- (byte) 0x6E, (byte) 0x50, (byte) 0xDE, (byte) 0x68,
- (byte) 0x65, (byte) 0xBC, (byte) 0xDB, (byte) 0xF8,
- (byte) 0xC8, (byte) 0xA8, (byte) 0x2B, (byte) 0x40,
- (byte) 0xDC, (byte) 0xFE, (byte) 0x32, (byte) 0xA4,
- (byte) 0xCA, (byte) 0x10, (byte) 0x21, (byte) 0xF0,
- (byte) 0xD3, (byte) 0x5D, (byte) 0x0F, (byte) 0x00,
- (byte) 0x6F, (byte) 0x9D, (byte) 0x36, (byte) 0x42,
- (byte) 0x4A, (byte) 0x5E, (byte) 0xC1, (byte) 0xE0 },
- { // p1
- (byte) 0x75, (byte) 0xF3, (byte) 0xC6, (byte) 0xF4,
- (byte) 0xDB, (byte) 0x7B, (byte) 0xFB, (byte) 0xC8,
- (byte) 0x4A, (byte) 0xD3, (byte) 0xE6, (byte) 0x6B,
- (byte) 0x45, (byte) 0x7D, (byte) 0xE8, (byte) 0x4B,
- (byte) 0xD6, (byte) 0x32, (byte) 0xD8, (byte) 0xFD,
- (byte) 0x37, (byte) 0x71, (byte) 0xF1, (byte) 0xE1,
- (byte) 0x30, (byte) 0x0F, (byte) 0xF8, (byte) 0x1B,
- (byte) 0x87, (byte) 0xFA, (byte) 0x06, (byte) 0x3F,
- (byte) 0x5E, (byte) 0xBA, (byte) 0xAE, (byte) 0x5B,
- (byte) 0x8A, (byte) 0x00, (byte) 0xBC, (byte) 0x9D,
- (byte) 0x6D, (byte) 0xC1, (byte) 0xB1, (byte) 0x0E,
- (byte) 0x80, (byte) 0x5D, (byte) 0xD2, (byte) 0xD5,
- (byte) 0xA0, (byte) 0x84, (byte) 0x07, (byte) 0x14,
- (byte) 0xB5, (byte) 0x90, (byte) 0x2C, (byte) 0xA3,
- (byte) 0xB2, (byte) 0x73, (byte) 0x4C, (byte) 0x54,
- (byte) 0x92, (byte) 0x74, (byte) 0x36, (byte) 0x51,
- (byte) 0x38, (byte) 0xB0, (byte) 0xBD, (byte) 0x5A,
- (byte) 0xFC, (byte) 0x60, (byte) 0x62, (byte) 0x96,
- (byte) 0x6C, (byte) 0x42, (byte) 0xF7, (byte) 0x10,
- (byte) 0x7C, (byte) 0x28, (byte) 0x27, (byte) 0x8C,
- (byte) 0x13, (byte) 0x95, (byte) 0x9C, (byte) 0xC7,
- (byte) 0x24, (byte) 0x46, (byte) 0x3B, (byte) 0x70,
- (byte) 0xCA, (byte) 0xE3, (byte) 0x85, (byte) 0xCB,
- (byte) 0x11, (byte) 0xD0, (byte) 0x93, (byte) 0xB8,
- (byte) 0xA6, (byte) 0x83, (byte) 0x20, (byte) 0xFF,
- (byte) 0x9F, (byte) 0x77, (byte) 0xC3, (byte) 0xCC,
- (byte) 0x03, (byte) 0x6F, (byte) 0x08, (byte) 0xBF,
- (byte) 0x40, (byte) 0xE7, (byte) 0x2B, (byte) 0xE2,
- (byte) 0x79, (byte) 0x0C, (byte) 0xAA, (byte) 0x82,
- (byte) 0x41, (byte) 0x3A, (byte) 0xEA, (byte) 0xB9,
- (byte) 0xE4, (byte) 0x9A, (byte) 0xA4, (byte) 0x97,
- (byte) 0x7E, (byte) 0xDA, (byte) 0x7A, (byte) 0x17,
- (byte) 0x66, (byte) 0x94, (byte) 0xA1, (byte) 0x1D,
- (byte) 0x3D, (byte) 0xF0, (byte) 0xDE, (byte) 0xB3,
- (byte) 0x0B, (byte) 0x72, (byte) 0xA7, (byte) 0x1C,
- (byte) 0xEF, (byte) 0xD1, (byte) 0x53, (byte) 0x3E,
- (byte) 0x8F, (byte) 0x33, (byte) 0x26, (byte) 0x5F,
- (byte) 0xEC, (byte) 0x76, (byte) 0x2A, (byte) 0x49,
- (byte) 0x81, (byte) 0x88, (byte) 0xEE, (byte) 0x21,
- (byte) 0xC4, (byte) 0x1A, (byte) 0xEB, (byte) 0xD9,
- (byte) 0xC5, (byte) 0x39, (byte) 0x99, (byte) 0xCD,
- (byte) 0xAD, (byte) 0x31, (byte) 0x8B, (byte) 0x01,
- (byte) 0x18, (byte) 0x23, (byte) 0xDD, (byte) 0x1F,
- (byte) 0x4E, (byte) 0x2D, (byte) 0xF9, (byte) 0x48,
- (byte) 0x4F, (byte) 0xF2, (byte) 0x65, (byte) 0x8E,
- (byte) 0x78, (byte) 0x5C, (byte) 0x58, (byte) 0x19,
- (byte) 0x8D, (byte) 0xE5, (byte) 0x98, (byte) 0x57,
- (byte) 0x67, (byte) 0x7F, (byte) 0x05, (byte) 0x64,
- (byte) 0xAF, (byte) 0x63, (byte) 0xB6, (byte) 0xFE,
- (byte) 0xF5, (byte) 0xB7, (byte) 0x3C, (byte) 0xA5,
- (byte) 0xCE, (byte) 0xE9, (byte) 0x68, (byte) 0x44,
- (byte) 0xE0, (byte) 0x4D, (byte) 0x43, (byte) 0x69,
- (byte) 0x29, (byte) 0x2E, (byte) 0xAC, (byte) 0x15,
- (byte) 0x59, (byte) 0xA8, (byte) 0x0A, (byte) 0x9E,
- (byte) 0x6E, (byte) 0x47, (byte) 0xDF, (byte) 0x34,
- (byte) 0x35, (byte) 0x6A, (byte) 0xCF, (byte) 0xDC,
- (byte) 0x22, (byte) 0xC9, (byte) 0xC0, (byte) 0x9B,
- (byte) 0x89, (byte) 0xD4, (byte) 0xED, (byte) 0xAB,
- (byte) 0x12, (byte) 0xA2, (byte) 0x0D, (byte) 0x52,
- (byte) 0xBB, (byte) 0x02, (byte) 0x2F, (byte) 0xA9,
- (byte) 0xD7, (byte) 0x61, (byte) 0x1E, (byte) 0xB4,
- (byte) 0x50, (byte) 0x04, (byte) 0xF6, (byte) 0xC2,
- (byte) 0x16, (byte) 0x25, (byte) 0x86, (byte) 0x56,
- (byte) 0x55, (byte) 0x09, (byte) 0xBE, (byte) 0x91 }
- };
-
- /**
- * Define the fixed p0/p1 permutations used in keyed S-box lookup.
- * By changing the following constant definitions, the S-boxes will
- * automatically get changed in the Twofish engine.
- */
- private static final int P_00 = 1;
- private static final int P_01 = 0;
- private static final int P_02 = 0;
- private static final int P_03 = P_01 ^ 1;
- private static final int P_04 = 1;
-
- private static final int P_10 = 0;
- private static final int P_11 = 0;
- private static final int P_12 = 1;
- private static final int P_13 = P_11 ^ 1;
- private static final int P_14 = 0;
-
- private static final int P_20 = 1;
- private static final int P_21 = 1;
- private static final int P_22 = 0;
- private static final int P_23 = P_21 ^ 1;
- private static final int P_24 = 0;
-
- private static final int P_30 = 0;
- private static final int P_31 = 1;
- private static final int P_32 = 1;
- private static final int P_33 = P_31 ^ 1;
- private static final int P_34 = 1;
-
- /* Primitive polynomial for GF(256) */
- private static final int GF256_FDBK = 0x169;
- private static final int GF256_FDBK_2 = GF256_FDBK / 2;
- private static final int GF256_FDBK_4 = GF256_FDBK / 4;
-
- private static final int RS_GF_FDBK = 0x14D; // field generator
-
- //====================================
- // Useful constants
- //====================================
-
- private static final int ROUNDS = 16;
- private static final int MAX_ROUNDS = 16; // bytes = 128 bits
- private static final int BLOCK_SIZE = 16; // bytes = 128 bits
- private static final int MAX_KEY_BITS = 256;
-
- private static final int INPUT_WHITEN=0;
- private static final int OUTPUT_WHITEN=INPUT_WHITEN+BLOCK_SIZE/4; // 4
- private static final int ROUND_SUBKEYS=OUTPUT_WHITEN+BLOCK_SIZE/4;// 8
-
- private static final int TOTAL_SUBKEYS=ROUND_SUBKEYS+2*MAX_ROUNDS;// 40
-
- private static final int SK_STEP = 0x02020202;
- private static final int SK_BUMP = 0x01010101;
- private static final int SK_ROTL = 9;
-
- private boolean encrypting = false;
-
- private int[] gMDS0 = new int[MAX_KEY_BITS];
- private int[] gMDS1 = new int[MAX_KEY_BITS];
- private int[] gMDS2 = new int[MAX_KEY_BITS];
- private int[] gMDS3 = new int[MAX_KEY_BITS];
-
- /**
- * gSubKeys[] and gSBox[] are eventually used in the
- * encryption and decryption methods.
- */
- private int[] gSubKeys;
- private int[] gSBox;
-
- private int k64Cnt = 0;
-
- private byte[] workingKey = null;
-
- public TwofishEngine()
- {
- // calculate the MDS matrix
- int[] m1 = new int[2];
- int[] mX = new int[2];
- int[] mY = new int[2];
- int j;
-
- for (int i=0; i< MAX_KEY_BITS ; i++)
- {
- j = P[0][i] & 0xff;
- m1[0] = j;
- mX[0] = Mx_X(j) & 0xff;
- mY[0] = Mx_Y(j) & 0xff;
-
- j = P[1][i] & 0xff;
- m1[1] = j;
- mX[1] = Mx_X(j) & 0xff;
- mY[1] = Mx_Y(j) & 0xff;
-
- gMDS0[i] = m1[P_00] | mX[P_00] << 8 |
- mY[P_00] << 16 | mY[P_00] << 24;
-
- gMDS1[i] = mY[P_10] | mY[P_10] << 8 |
- mX[P_10] << 16 | m1[P_10] << 24;
-
- gMDS2[i] = mX[P_20] | mY[P_20] << 8 |
- m1[P_20] << 16 | mY[P_20] << 24;
-
- gMDS3[i] = mX[P_30] | m1[P_30] << 8 |
- mY[P_30] << 16 | mX[P_30] << 24;
- }
- }
-
- /**
- * initialise a Twofish cipher.
- *
- * @param encrypting whether or not we are for encryption.
- * @param params the parameters required to set up the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean encrypting,
- CipherParameters params)
- {
- if (params instanceof KeyParameter)
- {
- this.encrypting = encrypting;
- this.workingKey = ((KeyParameter)params).getKey();
- this.k64Cnt = (this.workingKey.length / 8); // pre-padded ?
- setKey(this.workingKey);
-
- return;
- }
-
- throw new IllegalArgumentException("invalid parameter passed to Twofish init - " + params.getClass().getName());
- }
-
- public String getAlgorithmName()
- {
- return "Twofish";
- }
-
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- if (workingKey == null)
- {
- throw new IllegalStateException("Twofish not initialised");
- }
-
- if ((inOff + BLOCK_SIZE) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + BLOCK_SIZE) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- if (encrypting)
- {
- encryptBlock(in, inOff, out, outOff);
- }
- else
- {
- decryptBlock(in, inOff, out, outOff);
- }
-
- return BLOCK_SIZE;
- }
-
- public void reset()
- {
- if (this.workingKey != null)
- {
- setKey(this.workingKey);
- }
- }
-
- public int getBlockSize()
- {
- return BLOCK_SIZE;
- }
-
- //==================================
- // Private Implementation
- //==================================
-
- private void setKey(byte[] key)
- {
- int[] k32e = new int[MAX_KEY_BITS/64]; // 4
- int[] k32o = new int[MAX_KEY_BITS/64]; // 4
-
- int[] sBoxKeys = new int[MAX_KEY_BITS/64]; // 4
- gSubKeys = new int[TOTAL_SUBKEYS];
-
- if (k64Cnt < 1)
- {
- throw new IllegalArgumentException("Key size less than 64 bits");
- }
-
- if (k64Cnt > 4)
- {
- throw new IllegalArgumentException("Key size larger than 256 bits");
- }
-
- /*
- * k64Cnt is the number of 8 byte blocks (64 chunks)
- * that are in the input key. The input key is a
- * maximum of 32 bytes (256 bits), so the range
- * for k64Cnt is 1..4
- */
- for (int i=0; i<k64Cnt ; i++)
- {
- int p = i* 8;
-
- k32e[i] = BytesTo32Bits(key, p);
- k32o[i] = BytesTo32Bits(key, p+4);
-
- sBoxKeys[k64Cnt-1-i] = RS_MDS_Encode(k32e[i], k32o[i]);
- }
-
- int q,A,B;
- for (int i=0; i < TOTAL_SUBKEYS / 2 ; i++)
- {
- q = i*SK_STEP;
- A = F32(q, k32e);
- B = F32(q+SK_BUMP, k32o);
- B = B << 8 | B >>> 24;
- A += B;
- gSubKeys[i*2] = A;
- A += B;
- gSubKeys[i*2 + 1] = A << SK_ROTL | A >>> (32-SK_ROTL);
- }
-
- /*
- * fully expand the table for speed
- */
- int k0 = sBoxKeys[0];
- int k1 = sBoxKeys[1];
- int k2 = sBoxKeys[2];
- int k3 = sBoxKeys[3];
- int b0, b1, b2, b3;
- gSBox = new int[4*MAX_KEY_BITS];
- for (int i=0; i<MAX_KEY_BITS; i++)
- {
- b0 = b1 = b2 = b3 = i;
- switch (k64Cnt & 3)
- {
- case 1:
- gSBox[i*2] = gMDS0[(P[P_01][b0] & 0xff) ^ b0(k0)];
- gSBox[i*2+1] = gMDS1[(P[P_11][b1] & 0xff) ^ b1(k0)];
- gSBox[i*2+0x200] = gMDS2[(P[P_21][b2] & 0xff) ^ b2(k0)];
- gSBox[i*2+0x201] = gMDS3[(P[P_31][b3] & 0xff) ^ b3(k0)];
- break;
- case 0: // 256 bits of key
- b0 = (P[P_04][b0] & 0xff) ^ b0(k3);
- b1 = (P[P_14][b1] & 0xff) ^ b1(k3);
- b2 = (P[P_24][b2] & 0xff) ^ b2(k3);
- b3 = (P[P_34][b3] & 0xff) ^ b3(k3);
- // fall through, having pre-processed b[0]..b[3] with k32[3]
- case 3: // 192 bits of key
- b0 = (P[P_03][b0] & 0xff) ^ b0(k2);
- b1 = (P[P_13][b1] & 0xff) ^ b1(k2);
- b2 = (P[P_23][b2] & 0xff) ^ b2(k2);
- b3 = (P[P_33][b3] & 0xff) ^ b3(k2);
- // fall through, having pre-processed b[0]..b[3] with k32[2]
- case 2: // 128 bits of key
- gSBox[i*2] = gMDS0[(P[P_01]
- [(P[P_02][b0] & 0xff) ^ b0(k1)] & 0xff) ^ b0(k0)];
- gSBox[i*2+1] = gMDS1[(P[P_11]
- [(P[P_12][b1] & 0xff) ^ b1(k1)] & 0xff) ^ b1(k0)];
- gSBox[i*2+0x200] = gMDS2[(P[P_21]
- [(P[P_22][b2] & 0xff) ^ b2(k1)] & 0xff) ^ b2(k0)];
- gSBox[i*2+0x201] = gMDS3[(P[P_31]
- [(P[P_32][b3] & 0xff) ^ b3(k1)] & 0xff) ^ b3(k0)];
- break;
- }
- }
-
- /*
- * the function exits having setup the gSBox with the
- * input key material.
- */
- }
-
- /**
- * Encrypt the given input starting at the given offset and place
- * the result in the provided buffer starting at the given offset.
- * The input will be an exact multiple of our blocksize.
- *
- * encryptBlock uses the pre-calculated gSBox[] and subKey[]
- * arrays.
- */
- private void encryptBlock(
- byte[] src,
- int srcIndex,
- byte[] dst,
- int dstIndex)
- {
- int x0 = BytesTo32Bits(src, srcIndex) ^ gSubKeys[INPUT_WHITEN];
- int x1 = BytesTo32Bits(src, srcIndex + 4) ^ gSubKeys[INPUT_WHITEN + 1];
- int x2 = BytesTo32Bits(src, srcIndex + 8) ^ gSubKeys[INPUT_WHITEN + 2];
- int x3 = BytesTo32Bits(src, srcIndex + 12) ^ gSubKeys[INPUT_WHITEN + 3];
-
- int k = ROUND_SUBKEYS;
- int t0, t1;
- for (int r = 0; r < ROUNDS; r +=2)
- {
- t0 = Fe32_0(x0);
- t1 = Fe32_3(x1);
- x2 ^= t0 + t1 + gSubKeys[k++];
- x2 = x2 >>>1 | x2 << 31;
- x3 = (x3 << 1 | x3 >>> 31) ^ (t0 + 2*t1 + gSubKeys[k++]);
-
- t0 = Fe32_0(x2);
- t1 = Fe32_3(x3);
- x0 ^= t0 + t1 + gSubKeys[k++];
- x0 = x0 >>>1 | x0 << 31;
- x1 = (x1 << 1 | x1 >>> 31) ^ (t0 + 2*t1 + gSubKeys[k++]);
- }
-
- Bits32ToBytes(x2 ^ gSubKeys[OUTPUT_WHITEN], dst, dstIndex);
- Bits32ToBytes(x3 ^ gSubKeys[OUTPUT_WHITEN + 1], dst, dstIndex + 4);
- Bits32ToBytes(x0 ^ gSubKeys[OUTPUT_WHITEN + 2], dst, dstIndex + 8);
- Bits32ToBytes(x1 ^ gSubKeys[OUTPUT_WHITEN + 3], dst, dstIndex + 12);
- }
-
- /**
- * Decrypt the given input starting at the given offset and place
- * the result in the provided buffer starting at the given offset.
- * The input will be an exact multiple of our blocksize.
- */
- private void decryptBlock(
- byte[] src,
- int srcIndex,
- byte[] dst,
- int dstIndex)
- {
- int x2 = BytesTo32Bits(src, srcIndex) ^ gSubKeys[OUTPUT_WHITEN];
- int x3 = BytesTo32Bits(src, srcIndex+4) ^ gSubKeys[OUTPUT_WHITEN + 1];
- int x0 = BytesTo32Bits(src, srcIndex+8) ^ gSubKeys[OUTPUT_WHITEN + 2];
- int x1 = BytesTo32Bits(src, srcIndex+12) ^ gSubKeys[OUTPUT_WHITEN + 3];
-
- int k = ROUND_SUBKEYS + 2 * ROUNDS -1 ;
- int t0, t1;
- for (int r = 0; r< ROUNDS ; r +=2)
- {
- t0 = Fe32_0(x2);
- t1 = Fe32_3(x3);
- x1 ^= t0 + 2*t1 + gSubKeys[k--];
- x0 = (x0 << 1 | x0 >>> 31) ^ (t0 + t1 + gSubKeys[k--]);
- x1 = x1 >>>1 | x1 << 31;
-
- t0 = Fe32_0(x0);
- t1 = Fe32_3(x1);
- x3 ^= t0 + 2*t1 + gSubKeys[k--];
- x2 = (x2 << 1 | x2 >>> 31) ^ (t0 + t1 + gSubKeys[k--]);
- x3 = x3 >>>1 | x3 << 31;
- }
-
- Bits32ToBytes(x0 ^ gSubKeys[INPUT_WHITEN], dst, dstIndex);
- Bits32ToBytes(x1 ^ gSubKeys[INPUT_WHITEN + 1], dst, dstIndex + 4);
- Bits32ToBytes(x2 ^ gSubKeys[INPUT_WHITEN + 2], dst, dstIndex + 8);
- Bits32ToBytes(x3 ^ gSubKeys[INPUT_WHITEN + 3], dst, dstIndex + 12);
- }
-
- /*
- * TODO: This can be optimised and made cleaner by combining
- * the functionality in this function and applying it appropriately
- * to the creation of the subkeys during key setup.
- */
- private int F32(int x, int[] k32)
- {
- int b0 = b0(x);
- int b1 = b1(x);
- int b2 = b2(x);
- int b3 = b3(x);
- int k0 = k32[0];
- int k1 = k32[1];
- int k2 = k32[2];
- int k3 = k32[3];
-
- int result = 0;
- switch (k64Cnt & 3)
- {
- case 1:
- result = gMDS0[(P[P_01][b0] & 0xff) ^ b0(k0)] ^
- gMDS1[(P[P_11][b1] & 0xff) ^ b1(k0)] ^
- gMDS2[(P[P_21][b2] & 0xff) ^ b2(k0)] ^
- gMDS3[(P[P_31][b3] & 0xff) ^ b3(k0)];
- break;
- case 0: /* 256 bits of key */
- b0 = (P[P_04][b0] & 0xff) ^ b0(k3);
- b1 = (P[P_14][b1] & 0xff) ^ b1(k3);
- b2 = (P[P_24][b2] & 0xff) ^ b2(k3);
- b3 = (P[P_34][b3] & 0xff) ^ b3(k3);
- case 3:
- b0 = (P[P_03][b0] & 0xff) ^ b0(k2);
- b1 = (P[P_13][b1] & 0xff) ^ b1(k2);
- b2 = (P[P_23][b2] & 0xff) ^ b2(k2);
- b3 = (P[P_33][b3] & 0xff) ^ b3(k2);
- case 2:
- result =
- gMDS0[(P[P_01][(P[P_02][b0]&0xff)^b0(k1)]&0xff)^b0(k0)] ^
- gMDS1[(P[P_11][(P[P_12][b1]&0xff)^b1(k1)]&0xff)^b1(k0)] ^
- gMDS2[(P[P_21][(P[P_22][b2]&0xff)^b2(k1)]&0xff)^b2(k0)] ^
- gMDS3[(P[P_31][(P[P_32][b3]&0xff)^b3(k1)]&0xff)^b3(k0)];
- break;
- }
- return result;
- }
-
- /**
- * Use (12, 8) Reed-Solomon code over GF(256) to produce
- * a key S-box 32-bit entity from 2 key material 32-bit
- * entities.
- *
- * @param k0 first 32-bit entity
- * @param k1 second 32-bit entity
- * @return Remainder polynomial generated using RS code
- */
- private int RS_MDS_Encode(int k0, int k1)
- {
- int r = k1;
- for (int i = 0 ; i < 4 ; i++) // shift 1 byte at a time
- {
- r = RS_rem(r);
- }
- r ^= k0;
- for (int i=0 ; i < 4 ; i++)
- {
- r = RS_rem(r);
- }
-
- return r;
- }
-
- /**
- * Reed-Solomon code parameters: (12,8) reversible code:<p>
- * <pre>
- * g(x) = x^4 + (a+1/a)x^3 + ax^2 + (a+1/a)x + 1
- * </pre>
- * where a = primitive root of field generator 0x14D
- */
- private int RS_rem(int x)
- {
- int b = (x >>> 24) & 0xff;
- int g2 = ((b << 1) ^
- ((b & 0x80) != 0 ? RS_GF_FDBK : 0)) & 0xff;
- int g3 = ((b >>> 1) ^
- ((b & 0x01) != 0 ? (RS_GF_FDBK >>> 1) : 0)) ^ g2 ;
- return ((x << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b);
- }
-
- private int LFSR1(int x)
- {
- return (x >> 1) ^
- (((x & 0x01) != 0) ? GF256_FDBK_2 : 0);
- }
-
- private int LFSR2(int x)
- {
- return (x >> 2) ^
- (((x & 0x02) != 0) ? GF256_FDBK_2 : 0) ^
- (((x & 0x01) != 0) ? GF256_FDBK_4 : 0);
- }
-
- private int Mx_X(int x)
- {
- return x ^ LFSR2(x);
- } // 5B
-
- private int Mx_Y(int x)
- {
- return x ^ LFSR1(x) ^ LFSR2(x);
- } // EF
-
- private int b0(int x)
- {
- return x & 0xff;
- }
-
- private int b1(int x)
- {
- return (x >>> 8) & 0xff;
- }
-
- private int b2(int x)
- {
- return (x >>> 16) & 0xff;
- }
-
- private int b3(int x)
- {
- return (x >>> 24) & 0xff;
- }
-
- private int Fe32_0(int x)
- {
- return gSBox[ 0x000 + 2*(x & 0xff) ] ^
- gSBox[ 0x001 + 2*((x >>> 8) & 0xff) ] ^
- gSBox[ 0x200 + 2*((x >>> 16) & 0xff) ] ^
- gSBox[ 0x201 + 2*((x >>> 24) & 0xff) ];
- }
-
- private int Fe32_3(int x)
- {
- return gSBox[ 0x000 + 2*((x >>> 24) & 0xff) ] ^
- gSBox[ 0x001 + 2*(x & 0xff) ] ^
- gSBox[ 0x200 + 2*((x >>> 8) & 0xff) ] ^
- gSBox[ 0x201 + 2*((x >>> 16) & 0xff) ];
- }
-
- private int BytesTo32Bits(byte[] b, int p)
- {
- return ((b[p] & 0xff)) |
- ((b[p+1] & 0xff) << 8) |
- ((b[p+2] & 0xff) << 16) |
- ((b[p+3] & 0xff) << 24);
- }
-
- private void Bits32ToBytes(int in, byte[] b, int offset)
- {
- b[offset] = (byte)in;
- b[offset + 1] = (byte)(in >> 8);
- b[offset + 2] = (byte)(in >> 16);
- b[offset + 3] = (byte)(in >> 24);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/VMPCEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/VMPCEngine.java
deleted file mode 100644
index 364c5d82..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/VMPCEngine.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.OutputLengthException;
-import org.bouncycastle.crypto.StreamCipher;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-public class VMPCEngine implements StreamCipher
-{
- /*
- * variables to hold the state of the VMPC engine during encryption and
- * decryption
- */
- protected byte n = 0;
- protected byte[] P = null;
- protected byte s = 0;
-
- protected byte[] workingIV;
- protected byte[] workingKey;
-
- public String getAlgorithmName()
- {
- return "VMPC";
- }
-
- /**
- * initialise a VMPC cipher.
- *
- * @param forEncryption
- * whether or not we are for encryption.
- * @param params
- * the parameters required to set up the cipher.
- * @exception IllegalArgumentException
- * if the params argument is inappropriate.
- */
- public void init(boolean forEncryption, CipherParameters params)
- {
- if (!(params instanceof ParametersWithIV))
- {
- throw new IllegalArgumentException(
- "VMPC init parameters must include an IV");
- }
-
- ParametersWithIV ivParams = (ParametersWithIV) params;
-
- if (!(ivParams.getParameters() instanceof KeyParameter))
- {
- throw new IllegalArgumentException(
- "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)
- {
- throw new IllegalArgumentException("VMPC requires 1 to 768 bytes of IV");
- }
-
- this.workingKey = key.getKey();
-
- initKey(this.workingKey, this.workingIV);
- }
-
- protected void initKey(byte[] keyBytes, byte[] ivBytes)
- {
- s = 0;
- P = new byte[256];
- for (int i = 0; i < 256; i++)
- {
- P[i] = (byte) i;
- }
-
- for (int m = 0; m < 768; m++)
- {
- s = P[(s + P[m & 0xff] + keyBytes[m % keyBytes.length]) & 0xff];
- byte temp = P[m & 0xff];
- P[m & 0xff] = P[s & 0xff];
- P[s & 0xff] = temp;
- }
- for (int m = 0; m < 768; m++)
- {
- s = P[(s + P[m & 0xff] + ivBytes[m % ivBytes.length]) & 0xff];
- byte temp = P[m & 0xff];
- P[m & 0xff] = P[s & 0xff];
- P[s & 0xff] = temp;
- }
- n = 0;
- }
-
- public int processBytes(byte[] in, int inOff, int len, byte[] out,
- int outOff)
- {
- if ((inOff + len) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + len) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- for (int i = 0; i < len; i++)
- {
- s = P[(s + P[n & 0xff]) & 0xff];
- byte z = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff];
- // encryption
- byte temp = P[n & 0xff];
- P[n & 0xff] = P[s & 0xff];
- P[s & 0xff] = temp;
- n = (byte) ((n + 1) & 0xff);
-
- // xor
- out[i + outOff] = (byte) (in[i + inOff] ^ z);
- }
-
- return len;
- }
-
- public void reset()
- {
- initKey(this.workingKey, this.workingIV);
- }
-
- public byte returnByte(byte in)
- {
- s = P[(s + P[n & 0xff]) & 0xff];
- byte z = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff];
- // encryption
- byte temp = P[n & 0xff];
- P[n & 0xff] = P[s & 0xff];
- P[s & 0xff] = temp;
- n = (byte) ((n + 1) & 0xff);
-
- // xor
- return (byte) (in ^ z);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/VMPCKSA3Engine.java b/core/src/main/java/org/bouncycastle/crypto/engines/VMPCKSA3Engine.java
deleted file mode 100644
index 9e40272b..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/VMPCKSA3Engine.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-public class VMPCKSA3Engine extends VMPCEngine
-{
- public String getAlgorithmName()
- {
- return "VMPC-KSA3";
- }
-
- protected void initKey(byte[] keyBytes, byte[] ivBytes)
- {
- s = 0;
- P = new byte[256];
- for (int i = 0; i < 256; i++)
- {
- P[i] = (byte) i;
- }
-
- for (int m = 0; m < 768; m++)
- {
- s = P[(s + P[m & 0xff] + keyBytes[m % keyBytes.length]) & 0xff];
- byte temp = P[m & 0xff];
- P[m & 0xff] = P[s & 0xff];
- P[s & 0xff] = temp;
- }
-
- for (int m = 0; m < 768; m++)
- {
- s = P[(s + P[m & 0xff] + ivBytes[m % ivBytes.length]) & 0xff];
- byte temp = P[m & 0xff];
- P[m & 0xff] = P[s & 0xff];
- P[s & 0xff] = temp;
- }
-
- for (int m = 0; m < 768; m++)
- {
- s = P[(s + P[m & 0xff] + keyBytes[m % keyBytes.length]) & 0xff];
- byte temp = P[m & 0xff];
- P[m & 0xff] = P[s & 0xff];
- P[s & 0xff] = temp;
- }
-
- n = 0;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/XSalsa20Engine.java b/core/src/main/java/org/bouncycastle/crypto/engines/XSalsa20Engine.java
deleted file mode 100644
index 45cc478e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/XSalsa20Engine.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import org.bouncycastle.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 == null)
- {
- throw new IllegalArgumentException(getAlgorithmName() + " doesn't support re-init with null key");
- }
-
- 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);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/XTEAEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/XTEAEngine.java
deleted file mode 100644
index fb21bbc2..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/XTEAEngine.java
+++ /dev/null
@@ -1,188 +0,0 @@
-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;
-
-/**
- * An XTEA engine.
- */
-public class XTEAEngine
- implements BlockCipher
-{
- private static final int rounds = 32,
- block_size = 8,
-// key_size = 16,
- delta = 0x9E3779B9;
-
- /*
- * the expanded key array of 4 subkeys
- */
- private int[] _S = new int[4],
- _sum0 = new int[32],
- _sum1 = new int[32];
- private boolean _initialised,
- _forEncryption;
-
- /**
- * Create an instance of the TEA encryption algorithm
- * and set some defaults
- */
- public XTEAEngine()
- {
- _initialised = false;
- }
-
- public String getAlgorithmName()
- {
- return "XTEA";
- }
-
- public int getBlockSize()
- {
- return block_size;
- }
-
- /**
- * initialise
- *
- * @param forEncryption whether or not we are for encryption.
- * @param params the parameters required to set up the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean forEncryption,
- CipherParameters params)
- {
- if (!(params instanceof KeyParameter))
- {
- throw new IllegalArgumentException("invalid parameter passed to TEA init - " + params.getClass().getName());
- }
-
- _forEncryption = forEncryption;
- _initialised = true;
-
- KeyParameter p = (KeyParameter)params;
-
- setKey(p.getKey());
- }
-
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- if (!_initialised)
- {
- throw new IllegalStateException(getAlgorithmName()+" not initialised");
- }
-
- if ((inOff + block_size) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + block_size) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- return (_forEncryption) ? encryptBlock(in, inOff, out, outOff)
- : decryptBlock(in, inOff, out, outOff);
- }
-
- public void reset()
- {
- }
-
- /**
- * Re-key the cipher.
- * <p>
- * @param key the key to be used
- */
- 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)
- {
- _S[i] = bytesToInt(key, j);
- }
-
- for (i = j = 0; i < rounds; i++)
- {
- _sum0[i] = (j + _S[j & 3]);
- j += delta;
- _sum1[i] = (j + _S[j >>> 11 & 3]);
- }
- }
-
- private int encryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- // Pack bytes into integers
- int v0 = bytesToInt(in, inOff);
- int v1 = bytesToInt(in, inOff + 4);
-
- for (int i = 0; i < rounds; i++)
- {
- v0 += ((v1 << 4 ^ v1 >>> 5) + v1) ^ _sum0[i];
- v1 += ((v0 << 4 ^ v0 >>> 5) + v0) ^ _sum1[i];
- }
-
- unpackInt(v0, out, outOff);
- unpackInt(v1, out, outOff + 4);
-
- return block_size;
- }
-
- private int decryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- // Pack bytes into integers
- int v0 = bytesToInt(in, inOff);
- int v1 = bytesToInt(in, inOff + 4);
-
- for (int i = rounds-1; i >= 0; i--)
- {
- v1 -= ((v0 << 4 ^ v0 >>> 5) + v0) ^ _sum1[i];
- v0 -= ((v1 << 4 ^ v1 >>> 5) + v1) ^ _sum0[i];
- }
-
- unpackInt(v0, out, outOff);
- unpackInt(v1, out, outOff + 4);
-
- return block_size;
- }
-
- private int bytesToInt(byte[] in, int inOff)
- {
- return ((in[inOff++]) << 24) |
- ((in[inOff++] & 255) << 16) |
- ((in[inOff++] & 255) << 8) |
- ((in[inOff] & 255));
- }
-
- private void unpackInt(int v, byte[] out, int outOff)
- {
- out[outOff++] = (byte)(v >>> 24);
- out[outOff++] = (byte)(v >>> 16);
- out[outOff++] = (byte)(v >>> 8);
- out[outOff ] = (byte)v;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/examples/DESExample.java b/core/src/main/java/org/bouncycastle/crypto/examples/DESExample.java
deleted file mode 100644
index 90a21def..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/examples/DESExample.java
+++ /dev/null
@@ -1,421 +0,0 @@
-package org.bouncycastle.crypto.examples;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.engines.DESedeEngine;
-import org.bouncycastle.crypto.generators.DESedeKeyGenerator;
-import org.bouncycastle.crypto.modes.CBCBlockCipher;
-import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
-import org.bouncycastle.crypto.params.DESedeParameters;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.encoders.Hex;
-
-/**
- * DESExample is a simple DES based encryptor/decryptor.
- * <p>
- * The program is command line driven, with the input
- * and output files specified on the command line.
- * <pre>
- * java org.bouncycastle.crypto.examples.DESExample infile outfile [keyfile]
- * </pre>
- * A new key is generated for each encryption, if key is not specified,
- * then the example will assume encryption is required, and as output
- * create deskey.dat in the current directory. This key is a hex
- * encoded byte-stream that is used for the decryption. The output
- * file is Hex encoded, 60 characters wide text file.
- * <p>
- * When encrypting;
- * <ul>
- * <li>the infile is expected to be a byte stream (text or binary)
- * <li>there is no keyfile specified on the input line
- * </ul>
- * <p>
- * When decrypting;
- * <ul>
- * <li>the infile is expected to be the 60 character wide base64
- * encoded file
- * <li>the keyfile is expected to be a base64 encoded file
- * </ul>
- * <p>
- * This example shows how to use the light-weight API, DES and
- * the filesystem for message encryption and decryption.
- *
- */
-public class DESExample extends Object
-{
- // Encrypting or decrypting ?
- private boolean encrypt = true;
-
- // To hold the initialised DESede cipher
- private PaddedBufferedBlockCipher cipher = null;
-
- // The input stream of bytes to be processed for encryption
- private BufferedInputStream in = null;
-
- // The output stream of bytes to be procssed
- private BufferedOutputStream out = null;
-
- // The key
- private byte[] key = null;
-
- /*
- * start the application
- */
- public static void main(String[] args)
- {
- boolean encrypt = true;
- String infile = null;
- String outfile = null;
- String keyfile = null;
-
- if (args.length < 2)
- {
- DESExample de = new DESExample();
- System.err.println("Usage: java "+de.getClass().getName()+
- " infile outfile [keyfile]");
- System.exit(1);
- }
-
- keyfile = "deskey.dat";
- infile = args[0];
- outfile = args[1];
-
- if (args.length > 2)
- {
- encrypt = false;
- keyfile = args[2];
- }
-
- DESExample de = new DESExample(infile, outfile, keyfile, encrypt);
- de.process();
- }
-
- // Default constructor, used for the usage message
- public DESExample()
- {
- }
-
- /*
- * Constructor, that takes the arguments appropriate for
- * processing the command line directives.
- */
- public DESExample(
- String infile,
- String outfile,
- String keyfile,
- boolean encrypt)
- {
- /*
- * First, determine that infile & keyfile exist as appropriate.
- *
- * This will also create the BufferedInputStream as required
- * for reading the input file. All input files are treated
- * as if they are binary, even if they contain text, it's the
- * bytes that are encrypted.
- */
- this.encrypt = encrypt;
- try
- {
- in = new BufferedInputStream(new FileInputStream(infile));
- }
- catch (FileNotFoundException fnf)
- {
- System.err.println("Input file not found ["+infile+"]");
- System.exit(1);
- }
-
- try
- {
- out = new BufferedOutputStream(new FileOutputStream(outfile));
- }
- catch (IOException fnf)
- {
- System.err.println("Output file not created ["+outfile+"]");
- System.exit(1);
- }
-
- if (encrypt)
- {
- try
- {
- /*
- * The process of creating a new key requires a
- * number of steps.
- *
- * First, create the parameters for the key generator
- * which are a secure random number generator, and
- * the length of the key (in bits).
- */
- SecureRandom sr = null;
- try
- {
- sr = new SecureRandom();
- /*
- * This following call to setSeed() makes the
- * initialisation of the SecureRandom object
- * _very_ fast, but not secure AT ALL.
- *
- * Remove the line, recreate the class file and
- * then run DESExample again to see the difference.
- *
- * The initialisation of a SecureRandom object
- * can take 5 or more seconds depending on the
- * CPU that the program is running on. That can
- * be annoying during unit testing.
- * -- jon
- */
- sr.setSeed("www.bouncycastle.org".getBytes());
- }
- catch (Exception nsa)
- {
- System.err.println("Hmmm, no SHA1PRNG, you need the "+
- "Sun implementation");
- System.exit(1);
- }
- KeyGenerationParameters kgp = new KeyGenerationParameters(
- sr,
- DESedeParameters.DES_EDE_KEY_LENGTH*8);
-
- /*
- * Second, initialise the key generator with the parameters
- */
- DESedeKeyGenerator kg = new DESedeKeyGenerator();
- kg.init(kgp);
-
- /*
- * Third, and finally, generate the key
- */
- key = kg.generateKey();
-
- /*
- * We can now output the key to the file, but first
- * hex encode the key so that we can have a look
- * at it with a text editor if we so desire
- */
- BufferedOutputStream keystream =
- new BufferedOutputStream(new FileOutputStream(keyfile));
- byte[] keyhex = Hex.encode(key);
- keystream.write(keyhex, 0, keyhex.length);
- keystream.flush();
- keystream.close();
- }
- catch (IOException createKey)
- {
- System.err.println("Could not decryption create key file "+
- "["+keyfile+"]");
- System.exit(1);
- }
- }
- else
- {
- try
- {
- // read the key, and decode from hex encoding
- BufferedInputStream keystream =
- new BufferedInputStream(new FileInputStream(keyfile));
- int len = keystream.available();
- byte[] keyhex = new byte[len];
- keystream.read(keyhex, 0, len);
- key = Hex.decode(keyhex);
- }
- catch (IOException ioe)
- {
- System.err.println("Decryption key file not found, "+
- "or not valid ["+keyfile+"]");
- System.exit(1);
- }
- }
- }
-
- private void process()
- {
- /*
- * Setup the DESede cipher engine, create a PaddedBufferedBlockCipher
- * in CBC mode.
- */
- cipher = new PaddedBufferedBlockCipher(
- new CBCBlockCipher(new DESedeEngine()));
-
- /*
- * The input and output streams are currently set up
- * appropriately, and the key bytes are ready to be
- * used.
- *
- */
-
- if (encrypt)
- {
- performEncrypt(key);
- }
- else
- {
- performDecrypt(key);
- }
-
- // after processing clean up the files
- try
- {
- in.close();
- out.flush();
- out.close();
- }
- catch (IOException closing)
- {
-
- }
- }
-
- /*
- * This method performs all the encryption and writes
- * the cipher text to the buffered output stream created
- * previously.
- */
- private void performEncrypt(byte[] key)
- {
- // initialise the cipher with the key bytes, for encryption
- cipher.init(true, new KeyParameter(key));
-
- /*
- * Create some temporary byte arrays for use in
- * encryption, make them a reasonable size so that
- * we don't spend forever reading small chunks from
- * a file.
- *
- * There is no particular reason for using getBlockSize()
- * to determine the size of the input chunk. It just
- * was a convenient number for the example.
- */
- // int inBlockSize = cipher.getBlockSize() * 5;
- int inBlockSize = 47;
- int outBlockSize = cipher.getOutputSize(inBlockSize);
-
- byte[] inblock = new byte[inBlockSize];
- byte[] outblock = new byte[outBlockSize];
-
- /*
- * now, read the file, and output the chunks
- */
- try
- {
- int inL;
- int outL;
- byte[] rv = null;
- while ((inL=in.read(inblock, 0, inBlockSize)) > 0)
- {
- outL = cipher.processBytes(inblock, 0, inL, outblock, 0);
- /*
- * Before we write anything out, we need to make sure
- * that we've got something to write out.
- */
- if (outL > 0)
- {
- rv = Hex.encode(outblock, 0, outL);
- out.write(rv, 0, rv.length);
- out.write('\n');
- }
- }
-
- try
- {
- /*
- * Now, process the bytes that are still buffered
- * within the cipher.
- */
- outL = cipher.doFinal(outblock, 0);
- if (outL > 0)
- {
- rv = Hex.encode(outblock, 0, outL);
- out.write(rv, 0, rv.length);
- out.write('\n');
- }
- }
- catch (CryptoException ce)
- {
-
- }
- }
- catch (IOException ioeread)
- {
- ioeread.printStackTrace();
- }
- }
-
- /*
- * This method performs all the decryption and writes
- * the plain text to the buffered output stream created
- * previously.
- */
- private void performDecrypt(byte[] key)
- {
- // initialise the cipher for decryption
- cipher.init(false, new KeyParameter(key));
-
- /*
- * As the decryption is from our preformatted file,
- * and we know that it's a hex encoded format, then
- * we wrap the InputStream with a BufferedReader
- * so that we can read it easily.
- */
- BufferedReader br = new BufferedReader(new InputStreamReader(in));
-
- /*
- * now, read the file, and output the chunks
- */
- try
- {
- int outL;
- byte[] inblock = null;
- byte[] outblock = null;
- String rv = null;
- while ((rv = br.readLine()) != null)
- {
- inblock = Hex.decode(rv);
- outblock = new byte[cipher.getOutputSize(inblock.length)];
-
- outL = cipher.processBytes(inblock, 0, inblock.length,
- outblock, 0);
- /*
- * Before we write anything out, we need to make sure
- * that we've got something to write out.
- */
- if (outL > 0)
- {
- out.write(outblock, 0, outL);
- }
- }
-
- try
- {
- /*
- * Now, process the bytes that are still buffered
- * within the cipher.
- */
- outL = cipher.doFinal(outblock, 0);
- if (outL > 0)
- {
- out.write(outblock, 0, outL);
- }
- }
- catch (CryptoException ce)
- {
-
- }
- }
- catch (IOException ioeread)
- {
- ioeread.printStackTrace();
- }
- }
-
-}
-
diff --git a/core/src/main/java/org/bouncycastle/crypto/examples/JPAKEExample.java b/core/src/main/java/org/bouncycastle/crypto/examples/JPAKEExample.java
deleted file mode 100644
index f0065f4c..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/examples/JPAKEExample.java
+++ /dev/null
@@ -1,214 +0,0 @@
-package org.bouncycastle.crypto.examples;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroup;
-import org.bouncycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroups;
-import org.bouncycastle.crypto.agreement.jpake.JPAKEParticipant;
-import org.bouncycastle.crypto.agreement.jpake.JPAKERound1Payload;
-import org.bouncycastle.crypto.agreement.jpake.JPAKERound2Payload;
-import org.bouncycastle.crypto.agreement.jpake.JPAKERound3Payload;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-
-/**
- * An example of a J-PAKE exchange.
- * <p>
- *
- * In this example, both Alice and Bob are on the same computer (in the same JVM, in fact).
- * In reality, Alice and Bob would be in different locations,
- * and would be sending their generated payloads to each other.
- */
-public class JPAKEExample
-{
-
- public static void main(String args[]) throws CryptoException
- {
- /*
- * Initialization
- *
- * Pick an appropriate prime order group to use throughout the exchange.
- * Note that both participants must use the same group.
- */
- JPAKEPrimeOrderGroup group = JPAKEPrimeOrderGroups.NIST_3072;
-
- BigInteger p = group.getP();
- BigInteger q = group.getQ();
- BigInteger g = group.getG();
-
- String alicePassword = "password";
- String bobPassword = "password";
-
- System.out.println("********* Initialization **********");
- System.out.println("Public parameters for the cyclic group:");
- System.out.println("p (" + p.bitLength() + " bits): " + p.toString(16));
- System.out.println("q (" + q.bitLength() + " bits): " + q.toString(16));
- System.out.println("g (" + p.bitLength() + " bits): " + g.toString(16));
- System.out.println("p mod q = " + p.mod(q).toString(16));
- System.out.println("g^{q} mod p = " + g.modPow(q, p).toString(16));
- System.out.println("");
-
- System.out.println("(Secret passwords used by Alice and Bob: " +
- "\"" + alicePassword + "\" and \"" + bobPassword + "\")\n");
-
- /*
- * Both participants must use the same hashing algorithm.
- */
- Digest digest = new SHA256Digest();
- SecureRandom random = new SecureRandom();
-
- JPAKEParticipant alice = new JPAKEParticipant("alice", alicePassword.toCharArray(), group, digest, random);
- JPAKEParticipant bob = new JPAKEParticipant("bob", bobPassword.toCharArray(), group, digest, random);
-
- /*
- * Round 1
- *
- * Alice and Bob each generate a round 1 payload, and send it to each other.
- */
-
- JPAKERound1Payload aliceRound1Payload = alice.createRound1PayloadToSend();
- JPAKERound1Payload bobRound1Payload = bob.createRound1PayloadToSend();
-
- System.out.println("************ Round 1 **************");
- System.out.println("Alice sends to Bob: ");
- System.out.println("g^{x1}=" + aliceRound1Payload.getGx1().toString(16));
- System.out.println("g^{x2}=" + aliceRound1Payload.getGx2().toString(16));
- System.out.println("KP{x1}={" + aliceRound1Payload.getKnowledgeProofForX1()[0].toString(16) + "};{" + aliceRound1Payload.getKnowledgeProofForX1()[1].toString(16) + "}");
- System.out.println("KP{x2}={" + aliceRound1Payload.getKnowledgeProofForX2()[0].toString(16) + "};{" + aliceRound1Payload.getKnowledgeProofForX2()[1].toString(16) + "}");
- System.out.println("");
-
- System.out.println("Bob sends to Alice: ");
- System.out.println("g^{x3}=" + bobRound1Payload.getGx1().toString(16));
- System.out.println("g^{x4}=" + bobRound1Payload.getGx2().toString(16));
- System.out.println("KP{x3}={" + bobRound1Payload.getKnowledgeProofForX1()[0].toString(16) + "};{" + bobRound1Payload.getKnowledgeProofForX1()[1].toString(16) + "}");
- System.out.println("KP{x4}={" + bobRound1Payload.getKnowledgeProofForX2()[0].toString(16) + "};{" + bobRound1Payload.getKnowledgeProofForX2()[1].toString(16) + "}");
- System.out.println("");
-
- /*
- * Each participant must then validate the received payload for round 1
- */
-
- alice.validateRound1PayloadReceived(bobRound1Payload);
- System.out.println("Alice checks g^{x4}!=1: OK");
- System.out.println("Alice checks KP{x3}: OK");
- System.out.println("Alice checks KP{x4}: OK");
- System.out.println("");
-
- bob.validateRound1PayloadReceived(aliceRound1Payload);
- System.out.println("Bob checks g^{x2}!=1: OK");
- System.out.println("Bob checks KP{x1},: OK");
- System.out.println("Bob checks KP{x2},: OK");
- System.out.println("");
-
- /*
- * Round 2
- *
- * Alice and Bob each generate a round 2 payload, and send it to each other.
- */
-
- JPAKERound2Payload aliceRound2Payload = alice.createRound2PayloadToSend();
- JPAKERound2Payload bobRound2Payload = bob.createRound2PayloadToSend();
-
- System.out.println("************ Round 2 **************");
- System.out.println("Alice sends to Bob: ");
- System.out.println("A=" + aliceRound2Payload.getA().toString(16));
- System.out.println("KP{x2*s}={" + aliceRound2Payload.getKnowledgeProofForX2s()[0].toString(16) + "},{" + aliceRound2Payload.getKnowledgeProofForX2s()[1].toString(16) + "}");
- System.out.println("");
-
- System.out.println("Bob sends to Alice");
- System.out.println("B=" + bobRound2Payload.getA().toString(16));
- System.out.println("KP{x4*s}={" + bobRound2Payload.getKnowledgeProofForX2s()[0].toString(16) + "},{" + bobRound2Payload.getKnowledgeProofForX2s()[1].toString(16) + "}");
- System.out.println("");
-
- /*
- * Each participant must then validate the received payload for round 2
- */
-
- alice.validateRound2PayloadReceived(bobRound2Payload);
- System.out.println("Alice checks KP{x4*s}: OK\n");
-
- bob.validateRound2PayloadReceived(aliceRound2Payload);
- System.out.println("Bob checks KP{x2*s}: OK\n");
-
- /*
- * After round 2, each participant computes the keying material.
- */
-
- BigInteger aliceKeyingMaterial = alice.calculateKeyingMaterial();
- BigInteger bobKeyingMaterial = bob.calculateKeyingMaterial();
-
- System.out.println("********* After round 2 ***********");
- System.out.println("Alice computes key material \t K=" + aliceKeyingMaterial.toString(16));
- System.out.println("Bob computes key material \t K=" + bobKeyingMaterial.toString(16));
- System.out.println();
-
-
- /*
- * You must derive a session key from the keying material applicable
- * to whatever encryption algorithm you want to use.
- */
-
- BigInteger aliceKey = deriveSessionKey(aliceKeyingMaterial);
- BigInteger bobKey = deriveSessionKey(bobKeyingMaterial);
-
- /*
- * At this point, you can stop and use the session keys if you want.
- * This is implicit key confirmation.
- *
- * If you want to explicitly confirm that the key material matches,
- * you can continue on and perform round 3.
- */
-
- /*
- * Round 3
- *
- * Alice and Bob each generate a round 3 payload, and send it to each other.
- */
-
- JPAKERound3Payload aliceRound3Payload = alice.createRound3PayloadToSend(aliceKeyingMaterial);
- JPAKERound3Payload bobRound3Payload = bob.createRound3PayloadToSend(bobKeyingMaterial);
-
- System.out.println("************ Round 3 **************");
- System.out.println("Alice sends to Bob: ");
- System.out.println("MacTag=" + aliceRound3Payload.getMacTag().toString(16));
- System.out.println("");
- System.out.println("Bob sends to Alice: ");
- System.out.println("MacTag=" + bobRound3Payload.getMacTag().toString(16));
- System.out.println("");
-
- /*
- * Each participant must then validate the received payload for round 3
- */
-
- alice.validateRound3PayloadReceived(bobRound3Payload, aliceKeyingMaterial);
- System.out.println("Alice checks MacTag: OK\n");
-
- bob.validateRound3PayloadReceived(aliceRound3Payload, bobKeyingMaterial);
- System.out.println("Bob checks MacTag: OK\n");
-
- System.out.println();
- System.out.println("MacTags validated, therefore the keying material matches.");
- }
-
- private static BigInteger deriveSessionKey(BigInteger keyingMaterial)
- {
- /*
- * You should use a secure key derivation function (KDF) to derive the session key.
- *
- * For the purposes of this example, I'm just going to use a hash of the keying material.
- */
- SHA256Digest digest = new SHA256Digest();
-
- byte[] keyByteArray = keyingMaterial.toByteArray();
-
- byte[] output = new byte[digest.getDigestSize()];
-
- digest.update(keyByteArray, 0, keyByteArray.length);
-
- digest.doFinal(output, 0);
-
- return new BigInteger(output);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java
deleted file mode 100644
index b284a931..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.DataLengthException;
-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.util.Pack;
-
-/**
- * Basic KDF generator for derived keys and ivs as defined by IEEE P1363a/ISO
- * 18033 <br>
- * This implementation is based on ISO 18033/P1363a.
- */
-public class BaseKDFBytesGenerator
- implements DigestDerivationFunction
-{
- private int counterStart;
- private Digest digest;
- private byte[] shared;
- private byte[] iv;
-
- /**
- * Construct a KDF Parameters generator.
- * <p>
- *
- * @param counterStart
- * value of counter.
- * @param digest
- * the digest to be used as the source of derived keys.
- */
- protected BaseKDFBytesGenerator(int counterStart, Digest digest)
- {
- this.counterStart = counterStart;
- this.digest = digest;
- }
-
- public void init(DerivationParameters param)
- {
- if (param instanceof KDFParameters)
- {
- KDFParameters p = (KDFParameters)param;
-
- shared = p.getSharedSecret();
- iv = p.getIV();
- }
- else if (param instanceof ISO18033KDFParameters)
- {
- ISO18033KDFParameters p = (ISO18033KDFParameters)param;
-
- shared = p.getSeed();
- iv = null;
- }
- else
- {
- throw new IllegalArgumentException("KDF parameters required for KDF2Generator");
- }
- }
-
- /**
- * return the underlying digest.
- */
- public Digest getDigest()
- {
- return digest;
- }
-
- /**
- * fill len bytes of the output buffer with bytes generated from the
- * derivation function.
- *
- * @throws IllegalArgumentException
- * if the size of the request will cause an overflow.
- * @throws DataLengthException
- * if the out buffer is too small.
- */
- public int generateBytes(byte[] out, int outOff, int len) throws DataLengthException,
- IllegalArgumentException
- {
- if ((out.length - len) < outOff)
- {
- throw new DataLengthException("output buffer too small");
- }
-
- long oBytes = len;
- int outLen = digest.getDigestSize();
-
- //
- // this is at odds with the standard implementation, the
- // maximum value should be hBits * (2^32 - 1) where hBits
- // is the digest output size in bits. We can't have an
- // array with a long index at the moment...
- //
- if (oBytes > ((2L << 32) - 1))
- {
- throw new IllegalArgumentException("Output length too large");
- }
-
- int cThreshold = (int)((oBytes + outLen - 1) / outLen);
-
- byte[] dig = new byte[digest.getDigestSize()];
-
- byte[] C = new byte[4];
- Pack.intToBigEndian(counterStart, C, 0);
-
- int counterBase = counterStart & ~0xFF;
-
- for (int i = 0; i < cThreshold; i++)
- {
- digest.update(shared, 0, shared.length);
- digest.update(C, 0, C.length);
-
- if (iv != null)
- {
- digest.update(iv, 0, iv.length);
- }
-
- digest.doFinal(dig, 0);
-
- if (len > outLen)
- {
- System.arraycopy(dig, 0, out, outOff, outLen);
- outOff += outLen;
- len -= outLen;
- }
- else
- {
- System.arraycopy(dig, 0, out, outOff, len);
- }
-
- if (++C[3] == 0)
- {
- counterBase += 0x100;
- Pack.intToBigEndian(counterBase, C, 0);
- }
- }
-
- digest.reset();
-
- return (int)oBytes;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/CramerShoupKeyPairGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/CramerShoupKeyPairGenerator.java
deleted file mode 100644
index 8fcdf858..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/CramerShoupKeyPairGenerator.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.params.CramerShoupKeyGenerationParameters;
-import org.bouncycastle.crypto.params.CramerShoupParameters;
-import org.bouncycastle.crypto.params.CramerShoupPrivateKeyParameters;
-import org.bouncycastle.crypto.params.CramerShoupPublicKeyParameters;
-import org.bouncycastle.util.BigIntegers;
-
-/**
- * a Cramer Shoup key pair generator
- *
- */
-public class CramerShoupKeyPairGenerator implements AsymmetricCipherKeyPairGenerator {
-
- private static final BigInteger ONE = BigInteger.valueOf(1);
-
- private CramerShoupKeyGenerationParameters param;
-
- public void init(KeyGenerationParameters param) {
- this.param = (CramerShoupKeyGenerationParameters) param;
- }
-
- public AsymmetricCipherKeyPair generateKeyPair() {
- CramerShoupParameters csParams = param.getParameters();
-
- CramerShoupPrivateKeyParameters sk = generatePrivateKey(param.getRandom(), csParams);
- CramerShoupPublicKeyParameters pk = calculatePublicKey(csParams, sk);
- sk.setPk(pk);
-
- return new AsymmetricCipherKeyPair(pk, sk);
- }
-
- private BigInteger generateRandomElement(BigInteger p, SecureRandom random) {
- return BigIntegers.createRandomInRange(ONE, p.subtract(ONE), random);
- }
-
- private CramerShoupPrivateKeyParameters generatePrivateKey(SecureRandom random, CramerShoupParameters csParams){
- BigInteger p = csParams.getP();
- CramerShoupPrivateKeyParameters key = new CramerShoupPrivateKeyParameters(csParams,
- generateRandomElement(p, random), generateRandomElement(p, random),
- generateRandomElement(p, random), generateRandomElement(p, random),
- generateRandomElement(p, random));
- return key;
- }
-
- private CramerShoupPublicKeyParameters calculatePublicKey(CramerShoupParameters csParams, CramerShoupPrivateKeyParameters sk) {
- BigInteger g1 = csParams.getG1();
- BigInteger g2 = csParams.getG2();
- BigInteger p = csParams.getP();
-
- BigInteger c = g1.modPow(sk.getX1(), p).multiply(g2.modPow(sk.getX2(), p));
- BigInteger d = g1.modPow(sk.getY1(), p).multiply(g2.modPow(sk.getY2(), p));
- BigInteger h = g1.modPow(sk.getZ(), p);
-
- return new CramerShoupPublicKeyParameters(csParams, c, d, h);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/CramerShoupParametersGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/CramerShoupParametersGenerator.java
deleted file mode 100644
index 4788a8ca..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/CramerShoupParametersGenerator.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.params.CramerShoupParameters;
-import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.util.BigIntegers;
-
-public class CramerShoupParametersGenerator
-{
- private static final BigInteger ONE = BigInteger.valueOf(1);
-
- private int size;
- private int certainty;
- private SecureRandom random;
-
- /**
- * Initialise the parameters generator.
- *
- * @param size bit length for the prime p
- * @param certainty a measure of the uncertainty that the caller is willing to tolerate:
- * the probability that the generated modulus is prime exceeds (1 - 1/2^certainty).
- * The execution time of this method is proportional to the value of this parameter.
- * @param random a source of randomness
- */
- public void init(int size, int certainty, SecureRandom random)
- {
- this.size = size;
- this.certainty = certainty;
- this.random = random;
- }
-
- /**
- * which generates the p and g values from the given parameters, returning
- * the CramerShoupParameters object.
- * <p/>
- * Note: can take a while...
- */
- public CramerShoupParameters generateParameters()
- {
- //
- // find a safe prime p where p = 2*q + 1, where p and q are prime.
- //
- BigInteger[] safePrimes = ParametersHelper.generateSafePrimes(size, certainty, random);
-
-// BigInteger p = safePrimes[0];
- BigInteger q = safePrimes[1];
- BigInteger g1 = ParametersHelper.selectGenerator(q, random);
- BigInteger g2 = ParametersHelper.selectGenerator(q, random);
- while (g1.equals(g2))
- {
- g2 = ParametersHelper.selectGenerator(q, random);
- }
-
- return new CramerShoupParameters(q, g1, g2, new SHA256Digest());
- }
-
- public CramerShoupParameters generateParameters(DHParameters dhParams)
- {
- BigInteger p = dhParams.getP();
- BigInteger g1 = dhParams.getG();
-
- // now we just need a second generator
- BigInteger g2 = ParametersHelper.selectGenerator(p, random);
- while (g1.equals(g2))
- {
- g2 = ParametersHelper.selectGenerator(p, random);
- }
-
- return new CramerShoupParameters(p, g1, g2, new SHA256Digest());
- }
-
- private static class ParametersHelper
- {
-
- private static final BigInteger TWO = BigInteger.valueOf(2);
-
- /*
- * Finds a pair of prime BigInteger's {p, q: p = 2q + 1}
- *
- * (see: Handbook of Applied Cryptography 4.86)
- */
- static BigInteger[] generateSafePrimes(int size, int certainty, SecureRandom random)
- {
- BigInteger p, q;
- int qLength = size - 1;
-
- for (; ; )
- {
- q = new BigInteger(qLength, 2, random);
- p = q.shiftLeft(1).add(ONE);
- if (p.isProbablePrime(certainty) && (certainty <= 2 || q.isProbablePrime(certainty)))
- {
- break;
- }
- }
-
- return new BigInteger[]{p, q};
- }
-
- static BigInteger selectGenerator(BigInteger p, SecureRandom random)
- {
- BigInteger pMinusTwo = p.subtract(TWO);
- BigInteger g;
-
- /*
- * RFC 2631 2.2.1.2 (and see: Handbook of Applied Cryptography 4.81)
- */
- do
- {
- BigInteger h = BigIntegers.createRandomInRange(TWO, pMinusTwo, random);
-
- g = h.modPow(TWO, p);
- }
- while (g.equals(ONE));
-
- return g;
- }
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/DESKeyGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/DESKeyGenerator.java
deleted file mode 100644
index 7111118b..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/DESKeyGenerator.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.CipherKeyGenerator;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.params.DESParameters;
-
-public class DESKeyGenerator
- extends CipherKeyGenerator
-{
- /**
- * initialise the key generator - if strength is set to zero
- * the key generated will be 64 bits in size, otherwise
- * strength can be 64 or 56 bits (if you don't count the parity bits).
- *
- * @param param the parameters to be used for key generation
- */
- public void init(
- KeyGenerationParameters param)
- {
- super.init(param);
-
- if (strength == 0 || strength == (56 / 8))
- {
- strength = DESParameters.DES_KEY_LENGTH;
- }
- else if (strength != DESParameters.DES_KEY_LENGTH)
- {
- throw new IllegalArgumentException("DES key must be "
- + (DESParameters.DES_KEY_LENGTH * 8)
- + " bits long.");
- }
- }
-
- public byte[] generateKey()
- {
- byte[] newKey = new byte[DESParameters.DES_KEY_LENGTH];
-
- do
- {
- random.nextBytes(newKey);
-
- DESParameters.setOddParity(newKey);
- }
- while (DESParameters.isWeakKey(newKey, 0));
-
- return newKey;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/DESedeKeyGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/DESedeKeyGenerator.java
deleted file mode 100644
index 3cab983d..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/DESedeKeyGenerator.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.params.DESedeParameters;
-
-public class DESedeKeyGenerator
- extends DESKeyGenerator
-{
- /**
- * initialise the key generator - if strength is set to zero
- * the key generated will be 192 bits in size, otherwise
- * strength can be 128 or 192 (or 112 or 168 if you don't count
- * parity bits), depending on whether you wish to do 2-key or 3-key
- * triple DES.
- *
- * @param param the parameters to be used for key generation
- */
- public void init(
- KeyGenerationParameters param)
- {
- this.random = param.getRandom();
- this.strength = (param.getStrength() + 7) / 8;
-
- if (strength == 0 || strength == (168 / 8))
- {
- strength = DESedeParameters.DES_EDE_KEY_LENGTH;
- }
- else if (strength == (112 / 8))
- {
- strength = 2 * DESedeParameters.DES_KEY_LENGTH;
- }
- else if (strength != DESedeParameters.DES_EDE_KEY_LENGTH
- && strength != (2 * DESedeParameters.DES_KEY_LENGTH))
- {
- throw new IllegalArgumentException("DESede key must be "
- + (DESedeParameters.DES_EDE_KEY_LENGTH * 8) + " or "
- + (2 * 8 * DESedeParameters.DES_KEY_LENGTH)
- + " bits long.");
- }
- }
-
- public byte[] generateKey()
- {
- byte[] newKey = new byte[strength];
-
- do
- {
- random.nextBytes(newKey);
-
- DESedeParameters.setOddParity(newKey);
- }
- while (DESedeParameters.isWeakKey(newKey, 0, newKey.length));
-
- return newKey;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/DHBasicKeyPairGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/DHBasicKeyPairGenerator.java
deleted file mode 100644
index f93428ef..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/DHBasicKeyPairGenerator.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.params.DHKeyGenerationParameters;
-import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
-import org.bouncycastle.crypto.params.DHPublicKeyParameters;
-
-import java.math.BigInteger;
-
-/**
- * a basic Diffie-Hellman key pair generator.
- *
- * This generates keys consistent for use with the basic algorithm for
- * Diffie-Hellman.
- */
-public class DHBasicKeyPairGenerator
- implements AsymmetricCipherKeyPairGenerator
-{
- private DHKeyGenerationParameters param;
-
- public void init(
- KeyGenerationParameters param)
- {
- this.param = (DHKeyGenerationParameters)param;
- }
-
- public AsymmetricCipherKeyPair generateKeyPair()
- {
- DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.INSTANCE;
- DHParameters dhp = param.getParameters();
-
- BigInteger x = helper.calculatePrivate(dhp, param.getRandom());
- BigInteger y = helper.calculatePublic(dhp, x);
-
- return new AsymmetricCipherKeyPair(
- new DHPublicKeyParameters(y, dhp),
- new DHPrivateKeyParameters(x, dhp));
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/DHKeyGeneratorHelper.java b/core/src/main/java/org/bouncycastle/crypto/generators/DHKeyGeneratorHelper.java
deleted file mode 100644
index 6795ec96..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/DHKeyGeneratorHelper.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.math.ec.WNafUtil;
-import org.bouncycastle.util.BigIntegers;
-
-class DHKeyGeneratorHelper
-{
- static final DHKeyGeneratorHelper INSTANCE = new DHKeyGeneratorHelper();
-
- private static final BigInteger ONE = BigInteger.valueOf(1);
- private static final BigInteger TWO = BigInteger.valueOf(2);
-
- private DHKeyGeneratorHelper()
- {
- }
-
- BigInteger calculatePrivate(DHParameters dhParams, SecureRandom random)
- {
- int limit = dhParams.getL();
-
- if (limit != 0)
- {
- int minWeight = limit >>> 2;
- for (;;)
- {
- BigInteger x = new BigInteger(limit, random).setBit(limit - 1);
- if (WNafUtil.getNafWeight(x) >= minWeight)
- {
- return x;
- }
- }
- }
-
- BigInteger min = TWO;
- int m = dhParams.getM();
- if (m != 0)
- {
- min = ONE.shiftLeft(m - 1);
- }
-
- BigInteger q = dhParams.getQ();
- if (q == null)
- {
- q = dhParams.getP();
- }
- BigInteger max = q.subtract(TWO);
-
- int minWeight = max.bitLength() >>> 2;
- for (;;)
- {
- BigInteger x = BigIntegers.createRandomInRange(min, max, random);
- if (WNafUtil.getNafWeight(x) >= minWeight)
- {
- return x;
- }
- }
- }
-
- BigInteger calculatePublic(DHParameters dhParams, BigInteger x)
- {
- return dhParams.getG().modPow(x, dhParams.getP());
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/DHKeyPairGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/DHKeyPairGenerator.java
deleted file mode 100644
index d07ca80d..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/DHKeyPairGenerator.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.params.DHKeyGenerationParameters;
-import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
-import org.bouncycastle.crypto.params.DHPublicKeyParameters;
-
-import java.math.BigInteger;
-
-/**
- * a Diffie-Hellman key pair generator.
- *
- * This generates keys consistent for use in the MTI/A0 key agreement protocol
- * as described in "Handbook of Applied Cryptography", Pages 516-519.
- */
-public class DHKeyPairGenerator
- implements AsymmetricCipherKeyPairGenerator
-{
- private DHKeyGenerationParameters param;
-
- public void init(
- KeyGenerationParameters param)
- {
- this.param = (DHKeyGenerationParameters)param;
- }
-
- public AsymmetricCipherKeyPair generateKeyPair()
- {
- DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.INSTANCE;
- DHParameters dhp = param.getParameters();
-
- BigInteger x = helper.calculatePrivate(dhp, param.getRandom());
- BigInteger y = helper.calculatePublic(dhp, x);
-
- return new AsymmetricCipherKeyPair(
- new DHPublicKeyParameters(y, dhp),
- new DHPrivateKeyParameters(x, dhp));
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/DHParametersGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/DHParametersGenerator.java
deleted file mode 100644
index f5d42642..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/DHParametersGenerator.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.params.DHParameters;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-public class DHParametersGenerator
-{
- private int size;
- private int certainty;
- private SecureRandom random;
-
- private static final BigInteger TWO = BigInteger.valueOf(2);
-
- /**
- * Initialise the parameters generator.
- *
- * @param size bit length for the prime p
- * @param certainty level of certainty for the prime number tests
- * @param random a source of randomness
- */
- public void init(
- int size,
- int certainty,
- SecureRandom random)
- {
- this.size = size;
- this.certainty = certainty;
- this.random = random;
- }
-
- /**
- * which generates the p and g values from the given parameters,
- * returning the DHParameters object.
- * <p>
- * Note: can take a while...
- */
- public DHParameters generateParameters()
- {
- //
- // find a safe prime p where p = 2*q + 1, where p and q are prime.
- //
- BigInteger[] safePrimes = DHParametersHelper.generateSafePrimes(size, certainty, random);
-
- BigInteger p = safePrimes[0];
- BigInteger q = safePrimes[1];
- BigInteger g = DHParametersHelper.selectGenerator(p, q, random);
-
- return new DHParameters(p, g, q, TWO, null);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/DHParametersHelper.java b/core/src/main/java/org/bouncycastle/crypto/generators/DHParametersHelper.java
deleted file mode 100644
index dc0a5ae1..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/DHParametersHelper.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.math.ec.WNafUtil;
-import org.bouncycastle.util.BigIntegers;
-
-class DHParametersHelper
-{
- private static final BigInteger ONE = BigInteger.valueOf(1);
- private static final BigInteger TWO = BigInteger.valueOf(2);
-
- /*
- * Finds a pair of prime BigInteger's {p, q: p = 2q + 1}
- *
- * (see: Handbook of Applied Cryptography 4.86)
- */
- static BigInteger[] generateSafePrimes(int size, int certainty, SecureRandom random)
- {
- BigInteger p, q;
- int qLength = size - 1;
- int minWeight = size >>> 2;
-
- for (;;)
- {
- q = new BigInteger(qLength, 2, random);
-
- // p <- 2q + 1
- p = q.shiftLeft(1).add(ONE);
-
- if (!p.isProbablePrime(certainty))
- {
- continue;
- }
-
- if (certainty > 2 && !q.isProbablePrime(certainty - 2))
- {
- continue;
- }
-
- /*
- * Require a minimum weight of the NAF representation, since low-weight primes may be
- * weak against a version of the number-field-sieve for the discrete-logarithm-problem.
- *
- * See "The number field sieve for integers of low weight", Oliver Schirokauer.
- */
- if (WNafUtil.getNafWeight(p) < minWeight)
- {
- continue;
- }
-
- break;
- }
-
- return new BigInteger[] { p, q };
- }
-
- /*
- * Select a high order element of the multiplicative group Zp*
- *
- * p and q must be s.t. p = 2*q + 1, where p and q are prime (see generateSafePrimes)
- */
- static BigInteger selectGenerator(BigInteger p, BigInteger q, SecureRandom random)
- {
- BigInteger pMinusTwo = p.subtract(TWO);
- BigInteger g;
-
- /*
- * (see: Handbook of Applied Cryptography 4.80)
- */
-// do
-// {
-// g = BigIntegers.createRandomInRange(TWO, pMinusTwo, random);
-// }
-// while (g.modPow(TWO, p).equals(ONE) || g.modPow(q, p).equals(ONE));
-
-
- /*
- * RFC 2631 2.2.1.2 (and see: Handbook of Applied Cryptography 4.81)
- */
- do
- {
- BigInteger h = BigIntegers.createRandomInRange(TWO, pMinusTwo, random);
-
- g = h.modPow(TWO, p);
- }
- while (g.equals(ONE));
-
-
- return g;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/DSAKeyPairGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/DSAKeyPairGenerator.java
deleted file mode 100644
index ff3df358..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/DSAKeyPairGenerator.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.params.DSAKeyGenerationParameters;
-import org.bouncycastle.crypto.params.DSAParameters;
-import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
-import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
-import org.bouncycastle.math.ec.WNafUtil;
-import org.bouncycastle.util.BigIntegers;
-
-/**
- * a DSA key pair generator.
- *
- * This generates DSA keys in line with the method described
- * in <i>FIPS 186-3 B.1 FFC Key Pair Generation</i>.
- */
-public class DSAKeyPairGenerator
- implements AsymmetricCipherKeyPairGenerator
-{
- private static final BigInteger ONE = BigInteger.valueOf(1);
-
- private DSAKeyGenerationParameters param;
-
- public void init(
- KeyGenerationParameters param)
- {
- this.param = (DSAKeyGenerationParameters)param;
- }
-
- public AsymmetricCipherKeyPair generateKeyPair()
- {
- DSAParameters dsaParams = param.getParameters();
-
- BigInteger x = generatePrivateKey(dsaParams.getQ(), param.getRandom());
- BigInteger y = calculatePublicKey(dsaParams.getP(), dsaParams.getG(), x);
-
- return new AsymmetricCipherKeyPair(
- new DSAPublicKeyParameters(y, dsaParams),
- new DSAPrivateKeyParameters(x, dsaParams));
- }
-
- private static BigInteger generatePrivateKey(BigInteger q, SecureRandom random)
- {
- // B.1.2 Key Pair Generation by Testing Candidates
- int minWeight = q.bitLength() >>> 2;
- for (;;)
- {
- // TODO Prefer this method? (change test cases that used fixed random)
- // B.1.1 Key Pair Generation Using Extra Random Bits
-// BigInteger x = new BigInteger(q.bitLength() + 64, random).mod(q.subtract(ONE)).add(ONE);
-
- BigInteger x = BigIntegers.createRandomInRange(ONE, q.subtract(ONE), random);
- if (WNafUtil.getNafWeight(x) >= minWeight)
- {
- return x;
- }
- }
- }
-
- private static BigInteger calculatePublicKey(BigInteger p, BigInteger g, BigInteger x)
- {
- return g.modPow(x, p);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
deleted file mode 100644
index fe98b7c8..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
+++ /dev/null
@@ -1,387 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.params.DSAParameterGenerationParameters;
-import org.bouncycastle.crypto.params.DSAParameters;
-import org.bouncycastle.crypto.params.DSAValidationParameters;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.BigIntegers;
-import org.bouncycastle.util.encoders.Hex;
-
-/**
- * Generate suitable parameters for DSA, in line with FIPS 186-2, or FIPS 186-3.
- */
-public class DSAParametersGenerator
-{
- private Digest digest;
- private int L, N;
- private int certainty;
- private SecureRandom random;
-
- private static final BigInteger ZERO = BigInteger.valueOf(0);
- private static final BigInteger ONE = BigInteger.valueOf(1);
- private static final BigInteger TWO = BigInteger.valueOf(2);
-
- private boolean use186_3;
- private int usageIndex;
-
- public DSAParametersGenerator()
- {
- this(new SHA1Digest());
- }
-
- public DSAParametersGenerator(Digest digest)
- {
- this.digest = digest;
- }
-
- /**
- * initialise the key generator.
- *
- * @param size size of the key (range 2^512 -&gt; 2^1024 - 64 bit increments)
- * @param certainty measure of robustness of prime (for FIPS 186-2 compliance this should be at least 80).
- * @param random random byte source.
- */
- public void init(
- int size,
- int certainty,
- SecureRandom random)
- {
- this.use186_3 = false;
- this.L = size;
- this.N = getDefaultN(size);
- this.certainty = certainty;
- this.random = random;
- }
-
- /**
- * Initialise the key generator for DSA 2.
- * <p>
- * Use this init method if you need to generate parameters for DSA 2 keys.
- * </p>
- *
- * @param params DSA 2 key generation parameters.
- */
- public void init(
- DSAParameterGenerationParameters params)
- {
- // TODO Should we enforce the minimum 'certainty' values as per C.3 Table C.1?
- this.use186_3 = true;
- this.L = params.getL();
- this.N = params.getN();
- this.certainty = params.getCertainty();
- this.random = params.getRandom();
- this.usageIndex = params.getUsageIndex();
-
- if ((L < 1024 || L > 3072) || L % 1024 != 0)
- {
- throw new IllegalArgumentException("L values must be between 1024 and 3072 and a multiple of 1024");
- }
- else if (L == 1024 && N != 160)
- {
- throw new IllegalArgumentException("N must be 160 for L = 1024");
- }
- else if (L == 2048 && (N != 224 && N != 256))
- {
- throw new IllegalArgumentException("N must be 224 or 256 for L = 2048");
- }
- else if (L == 3072 && N != 256)
- {
- throw new IllegalArgumentException("N must be 256 for L = 3072");
- }
-
- if (digest.getDigestSize() * 8 < N)
- {
- throw new IllegalStateException("Digest output size too small for value of N");
- }
- }
-
- /**
- * which generates the p and g values from the given parameters,
- * returning the DSAParameters object.
- * <p>
- * Note: can take a while...
- */
- public DSAParameters generateParameters()
- {
- return (use186_3)
- ? generateParameters_FIPS186_3()
- : generateParameters_FIPS186_2();
- }
-
- private DSAParameters generateParameters_FIPS186_2()
- {
- byte[] seed = new byte[20];
- byte[] part1 = new byte[20];
- byte[] part2 = new byte[20];
- byte[] u = new byte[20];
- int n = (L - 1) / 160;
- byte[] w = new byte[L / 8];
-
- if (!(digest instanceof SHA1Digest))
- {
- throw new IllegalStateException("can only use SHA-1 for generating FIPS 186-2 parameters");
- }
-
- for (;;)
- {
- random.nextBytes(seed);
-
- hash(digest, seed, part1);
- System.arraycopy(seed, 0, part2, 0, seed.length);
- inc(part2);
- hash(digest, part2, part2);
-
- for (int i = 0; i != u.length; i++)
- {
- u[i] = (byte)(part1[i] ^ part2[i]);
- }
-
- u[0] |= (byte)0x80;
- u[19] |= (byte)0x01;
-
- BigInteger q = new BigInteger(1, u);
-
- if (!q.isProbablePrime(certainty))
- {
- continue;
- }
-
- byte[] offset = Arrays.clone(seed);
- inc(offset);
-
- for (int counter = 0; counter < 4096; ++counter)
- {
- for (int k = 0; k < n; k++)
- {
- inc(offset);
- hash(digest, offset, part1);
- System.arraycopy(part1, 0, w, w.length - (k + 1) * part1.length, part1.length);
- }
-
- inc(offset);
- hash(digest, offset, part1);
- System.arraycopy(part1, part1.length - ((w.length - (n) * part1.length)), w, 0, w.length - n * part1.length);
-
- w[0] |= (byte)0x80;
-
- BigInteger x = new BigInteger(1, w);
-
- BigInteger c = x.mod(q.shiftLeft(1));
-
- BigInteger p = x.subtract(c.subtract(ONE));
-
- if (p.bitLength() != L)
- {
- continue;
- }
-
- if (p.isProbablePrime(certainty))
- {
- BigInteger g = calculateGenerator_FIPS186_2(p, q, random);
-
- return new DSAParameters(p, q, g, new DSAValidationParameters(seed, counter));
- }
- }
- }
- }
-
- private static BigInteger calculateGenerator_FIPS186_2(BigInteger p, BigInteger q, SecureRandom r)
- {
- BigInteger e = p.subtract(ONE).divide(q);
- BigInteger pSub2 = p.subtract(TWO);
-
- for (;;)
- {
- BigInteger h = BigIntegers.createRandomInRange(TWO, pSub2, r);
- BigInteger g = h.modPow(e, p);
- if (g.bitLength() > 1)
- {
- return g;
- }
- }
- }
-
- /**
- * generate suitable parameters for DSA, in line with
- * <i>FIPS 186-3 A.1 Generation of the FFC Primes p and q</i>.
- */
- private DSAParameters generateParameters_FIPS186_3()
- {
-// A.1.1.2 Generation of the Probable Primes p and q Using an Approved Hash Function
- // FIXME This should be configurable (digest size in bits must be >= N)
- Digest d = digest;
- int outlen = d.getDigestSize() * 8;
-
-// 1. Check that the (L, N) pair is in the list of acceptable (L, N pairs) (see Section 4.2). If
-// the pair is not in the list, then return INVALID.
- // Note: checked at initialisation
-
-// 2. If (seedlen < N), then return INVALID.
- // FIXME This should be configurable (must be >= N)
- int seedlen = N;
- byte[] seed = new byte[seedlen / 8];
-
-// 3. n = ceiling(L / outlen) - 1.
- int n = (L - 1) / outlen;
-
-// 4. b = L - 1 - (n * outlen).
- int b = (L - 1) % outlen;
-
- byte[] output = new byte[d.getDigestSize()];
- for (;;)
- {
-// 5. Get an arbitrary sequence of seedlen bits as the domain_parameter_seed.
- random.nextBytes(seed);
-
-// 6. U = Hash (domain_parameter_seed) mod 2^(N–1).
- hash(d, seed, output);
-
- BigInteger U = new BigInteger(1, output).mod(ONE.shiftLeft(N - 1));
-
-// 7. q = 2^(N–1) + U + 1 – ( U mod 2).
- BigInteger q = ONE.shiftLeft(N - 1).add(U).add(ONE).subtract(U.mod(TWO));
-
-// 8. Test whether or not q is prime as specified in Appendix C.3.
- // TODO Review C.3 for primality checking
- if (!q.isProbablePrime(certainty))
- {
-// 9. If q is not a prime, then go to step 5.
- continue;
- }
-
-// 10. offset = 1.
- // Note: 'offset' value managed incrementally
- byte[] offset = Arrays.clone(seed);
-
-// 11. For counter = 0 to (4L – 1) do
- int counterLimit = 4 * L;
- for (int counter = 0; counter < counterLimit; ++counter)
- {
-// 11.1 For j = 0 to n do
-// Vj = Hash ((domain_parameter_seed + offset + j) mod 2^seedlen).
-// 11.2 W = V0 + (V1 ∗ 2^outlen) + ... + (V^(n–1) ∗ 2^((n–1) ∗ outlen)) + ((Vn mod 2^b) ∗ 2^(n ∗ outlen)).
- // TODO Assemble w as a byte array
- BigInteger W = ZERO;
- for (int j = 0, exp = 0; j <= n; ++j, exp += outlen)
- {
- inc(offset);
- hash(d, offset, output);
-
- BigInteger Vj = new BigInteger(1, output);
- if (j == n)
- {
- Vj = Vj.mod(ONE.shiftLeft(b));
- }
-
- W = W.add(Vj.shiftLeft(exp));
- }
-
-// 11.3 X = W + 2^(L–1). Comment: 0 ≤ W < 2L–1; hence, 2L–1 ≤ X < 2L.
- BigInteger X = W.add(ONE.shiftLeft(L - 1));
-
-// 11.4 c = X mod 2q.
- BigInteger c = X.mod(q.shiftLeft(1));
-
-// 11.5 p = X - (c - 1). Comment: p ≡ 1 (mod 2q).
- BigInteger p = X.subtract(c.subtract(ONE));
-
-// 11.6 If (p < 2^(L - 1)), then go to step 11.9
- if (p.bitLength() != L)
- {
- continue;
- }
-
-// 11.7 Test whether or not p is prime as specified in Appendix C.3.
- // TODO Review C.3 for primality checking
- if (p.isProbablePrime(certainty))
- {
-// 11.8 If p is determined to be prime, then return VALID and the values of p, q and
-// (optionally) the values of domain_parameter_seed and counter.
- if (usageIndex >= 0)
- {
- BigInteger g = calculateGenerator_FIPS186_3_Verifiable(d, p, q, seed, usageIndex);
- if (g != null)
- {
- return new DSAParameters(p, q, g, new DSAValidationParameters(seed, counter, usageIndex));
- }
- }
-
- BigInteger g = calculateGenerator_FIPS186_3_Unverifiable(p, q, random);
-
- return new DSAParameters(p, q, g, new DSAValidationParameters(seed, counter));
- }
-
-// 11.9 offset = offset + n + 1. Comment: Increment offset; then, as part of
-// the loop in step 11, increment counter; if
-// counter < 4L, repeat steps 11.1 through 11.8.
- // Note: 'offset' value already incremented in inner loop
- }
-// 12. Go to step 5.
- }
- }
-
- private static BigInteger calculateGenerator_FIPS186_3_Unverifiable(BigInteger p, BigInteger q,
- SecureRandom r)
- {
- return calculateGenerator_FIPS186_2(p, q, r);
- }
-
- private static BigInteger calculateGenerator_FIPS186_3_Verifiable(Digest d, BigInteger p, BigInteger q,
- byte[] seed, int index)
- {
-// A.2.3 Verifiable Canonical Generation of the Generator g
- BigInteger e = p.subtract(ONE).divide(q);
- byte[] ggen = Hex.decode("6767656E");
-
- // 7. U = domain_parameter_seed || "ggen" || index || count.
- byte[] U = new byte[seed.length + ggen.length + 1 + 2];
- System.arraycopy(seed, 0, U, 0, seed.length);
- System.arraycopy(ggen, 0, U, seed.length, ggen.length);
- U[U.length - 3] = (byte)index;
-
- byte[] w = new byte[d.getDigestSize()];
- for (int count = 1; count < (1 << 16); ++count)
- {
- inc(U);
- hash(d, U, w);
- BigInteger W = new BigInteger(1, w);
- BigInteger g = W.modPow(e, p);
- if (g.compareTo(TWO) >= 0)
- {
- return g;
- }
- }
-
- return null;
- }
-
- private static void hash(Digest d, byte[] input, byte[] output)
- {
- d.update(input, 0, input.length);
- d.doFinal(output, 0);
- }
-
- private static int getDefaultN(int L)
- {
- return L > 1024 ? 256 : 160;
- }
-
- private static void inc(byte[] buf)
- {
- for (int i = buf.length - 1; i >= 0; --i)
- {
- byte b = (byte)((buf[i] + 1) & 0xff);
- buf[i] = b;
-
- if (b != 0)
- {
- break;
- }
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/DSTU4145KeyPairGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/DSTU4145KeyPairGenerator.java
deleted file mode 100644
index 3f931b2c..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/DSTU4145KeyPairGenerator.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-
-public class DSTU4145KeyPairGenerator
- extends ECKeyPairGenerator
-{
- public AsymmetricCipherKeyPair generateKeyPair()
- {
- AsymmetricCipherKeyPair pair = super.generateKeyPair();
-
- ECPublicKeyParameters pub = (ECPublicKeyParameters)pair.getPublic();
- ECPrivateKeyParameters priv = (ECPrivateKeyParameters)pair.getPrivate();
-
- pub = new ECPublicKeyParameters(pub.getQ().negate(), pub.getParameters());
-
- return new AsymmetricCipherKeyPair(pub, priv);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java
deleted file mode 100644
index 4f46a38d..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECMultiplier;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.ec.FixedPointCombMultiplier;
-import org.bouncycastle.math.ec.WNafUtil;
-
-public class ECKeyPairGenerator
- implements AsymmetricCipherKeyPairGenerator, ECConstants
-{
- ECDomainParameters params;
- SecureRandom random;
-
- public void init(
- KeyGenerationParameters param)
- {
- ECKeyGenerationParameters ecP = (ECKeyGenerationParameters)param;
-
- this.random = ecP.getRandom();
- this.params = ecP.getDomainParameters();
-
- if (this.random == null)
- {
- this.random = new SecureRandom();
- }
- }
-
- /**
- * Given the domain parameters this routine generates an EC key
- * pair in accordance with X9.62 section 5.2.1 pages 26, 27.
- */
- public AsymmetricCipherKeyPair generateKeyPair()
- {
- BigInteger n = params.getN();
- int nBitLength = n.bitLength();
- int minWeight = nBitLength >>> 2;
-
- BigInteger d;
- for (;;)
- {
- d = new BigInteger(nBitLength, random);
-
- if (d.compareTo(TWO) < 0 || (d.compareTo(n) >= 0))
- {
- continue;
- }
-
- /*
- * Require a minimum weight of the NAF representation, since low-weight primes may be
- * weak against a version of the number-field-sieve for the discrete-logarithm-problem.
- *
- * See "The number field sieve for integers of low weight", Oliver Schirokauer.
- */
- if (WNafUtil.getNafWeight(d) < minWeight)
- {
- continue;
- }
-
- break;
- }
-
- ECPoint Q = createBasePointMultiplier().multiply(params.getG(), d);
-
- return new AsymmetricCipherKeyPair(
- new ECPublicKeyParameters(Q, params),
- new ECPrivateKeyParameters(d, params));
- }
-
- protected ECMultiplier createBasePointMultiplier()
- {
- return new FixedPointCombMultiplier();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/ElGamalKeyPairGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/ElGamalKeyPairGenerator.java
deleted file mode 100644
index f23b6976..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/ElGamalKeyPairGenerator.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.crypto.params.ElGamalKeyGenerationParameters;
-import org.bouncycastle.crypto.params.ElGamalParameters;
-import org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ElGamalPublicKeyParameters;
-
-/**
- * a ElGamal key pair generator.
- * <p>
- * This generates keys consistent for use with ElGamal as described in
- * page 164 of "Handbook of Applied Cryptography".
- */
-public class ElGamalKeyPairGenerator
- implements AsymmetricCipherKeyPairGenerator
-{
- private ElGamalKeyGenerationParameters param;
-
- public void init(
- KeyGenerationParameters param)
- {
- this.param = (ElGamalKeyGenerationParameters)param;
- }
-
- public AsymmetricCipherKeyPair generateKeyPair()
- {
- DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.INSTANCE;
- ElGamalParameters egp = param.getParameters();
- DHParameters dhp = new DHParameters(egp.getP(), egp.getG(), null, egp.getL());
-
- BigInteger x = helper.calculatePrivate(dhp, param.getRandom());
- BigInteger y = helper.calculatePublic(dhp, x);
-
- return new AsymmetricCipherKeyPair(
- new ElGamalPublicKeyParameters(y, egp),
- new ElGamalPrivateKeyParameters(x, egp));
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/ElGamalParametersGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/ElGamalParametersGenerator.java
deleted file mode 100644
index 21e8c2a0..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/ElGamalParametersGenerator.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.params.ElGamalParameters;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-public class ElGamalParametersGenerator
-{
- private int size;
- private int certainty;
- private SecureRandom random;
-
- public void init(
- int size,
- int certainty,
- SecureRandom random)
- {
- this.size = size;
- this.certainty = certainty;
- this.random = random;
- }
-
- /**
- * which generates the p and g values from the given parameters,
- * returning the ElGamalParameters object.
- * <p>
- * Note: can take a while...
- */
- public ElGamalParameters generateParameters()
- {
- //
- // find a safe prime p where p = 2*q + 1, where p and q are prime.
- //
- BigInteger[] safePrimes = DHParametersHelper.generateSafePrimes(size, certainty, random);
-
- BigInteger p = safePrimes[0];
- BigInteger q = safePrimes[1];
- BigInteger g = DHParametersHelper.selectGenerator(p, q, random);
-
- return new ElGamalParameters(p, g);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/EphemeralKeyPairGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/EphemeralKeyPairGenerator.java
deleted file mode 100644
index 1004f23e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/EphemeralKeyPairGenerator.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
-import org.bouncycastle.crypto.EphemeralKeyPair;
-import org.bouncycastle.crypto.KeyEncoder;
-
-public class EphemeralKeyPairGenerator
-{
- private AsymmetricCipherKeyPairGenerator gen;
- private KeyEncoder keyEncoder;
-
- public EphemeralKeyPairGenerator(AsymmetricCipherKeyPairGenerator gen, KeyEncoder keyEncoder)
- {
- this.gen = gen;
- this.keyEncoder = keyEncoder;
- }
-
- public EphemeralKeyPair generate()
- {
- AsymmetricCipherKeyPair eph = gen.generateKeyPair();
-
- // Encode the ephemeral public key
- return new EphemeralKeyPair(eph, keyEncoder);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/GOST3410KeyPairGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/GOST3410KeyPairGenerator.java
deleted file mode 100644
index 8948f931..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/GOST3410KeyPairGenerator.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.params.GOST3410KeyGenerationParameters;
-import org.bouncycastle.crypto.params.GOST3410Parameters;
-import org.bouncycastle.crypto.params.GOST3410PrivateKeyParameters;
-import org.bouncycastle.crypto.params.GOST3410PublicKeyParameters;
-import org.bouncycastle.math.ec.WNafUtil;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-/**
- * a GOST3410 key pair generator.
- * This generates GOST3410 keys in line with the method described
- * in GOST R 34.10-94.
- */
-public class GOST3410KeyPairGenerator
- implements AsymmetricCipherKeyPairGenerator
- {
- private GOST3410KeyGenerationParameters param;
-
- public void init(
- KeyGenerationParameters param)
- {
- this.param = (GOST3410KeyGenerationParameters)param;
- }
-
- public AsymmetricCipherKeyPair generateKeyPair()
- {
- BigInteger p, q, a, x, y;
- GOST3410Parameters GOST3410Params = param.getParameters();
- SecureRandom random = param.getRandom();
-
- q = GOST3410Params.getQ();
- p = GOST3410Params.getP();
- a = GOST3410Params.getA();
-
- int minWeight = 64;
- for (;;)
- {
- x = new BigInteger(256, random);
-
- if (x.signum() < 1 || x.compareTo(q) >= 0)
- {
- continue;
- }
-
- /*
- * Require a minimum weight of the NAF representation, since low-weight primes may be
- * weak against a version of the number-field-sieve for the discrete-logarithm-problem.
- *
- * See "The number field sieve for integers of low weight", Oliver Schirokauer.
- */
- if (WNafUtil.getNafWeight(x) < minWeight)
- {
- continue;
- }
-
- break;
- }
-
- //
- // calculate the public key.
- //
- y = a.modPow(x, p);
-
- return new AsymmetricCipherKeyPair(
- new GOST3410PublicKeyParameters(y, GOST3410Params),
- new GOST3410PrivateKeyParameters(x, GOST3410Params));
- }
- }
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/GOST3410ParametersGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/GOST3410ParametersGenerator.java
deleted file mode 100644
index 1c7cecf8..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/GOST3410ParametersGenerator.java
+++ /dev/null
@@ -1,541 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.params.GOST3410Parameters;
-import org.bouncycastle.crypto.params.GOST3410ValidationParameters;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-/**
- * generate suitable parameters for GOST3410.
- */
-public class GOST3410ParametersGenerator
-{
- private int size;
- private int typeproc;
- private SecureRandom init_random;
-
- private static final BigInteger ONE = BigInteger.valueOf(1);
- private static final BigInteger TWO = BigInteger.valueOf(2);
-
- /**
- * initialise the key generator.
- *
- * @param size size of the key
- * @param typeproc type procedure A,B = 1; A',B' - else
- * @param random random byte source.
- */
- public void init(
- int size,
- int typeproc,
- SecureRandom random)
- {
- this.size = size;
- this.typeproc = typeproc;
- this.init_random = random;
- }
-
- //Procedure A
- private int procedure_A(int x0, int c, BigInteger[] pq, int size)
- {
- //Verify and perform condition: 0<x<2^16; 0<c<2^16; c - odd.
- while(x0<0 || x0>65536)
- {
- x0 = init_random.nextInt()/32768;
- }
-
- while((c<0 || c>65536) || (c/2==0))
- {
- c = init_random.nextInt()/32768 + 1;
- }
-
- BigInteger C = new BigInteger(Integer.toString(c));
- BigInteger constA16 = new BigInteger("19381");
-
- //step1
- BigInteger[] y = new BigInteger[1]; // begin length = 1
- y[0] = new BigInteger(Integer.toString(x0));
-
- //step 2
- int[] t = new int[1]; // t - orders; begin length = 1
- t[0] = size;
- int s = 0;
- for (int i=0; t[i]>=17; i++)
- {
- // extension array t
- int tmp_t[] = new int[t.length + 1]; ///////////////
- System.arraycopy(t,0,tmp_t,0,t.length); // extension
- t = new int[tmp_t.length]; // array t
- System.arraycopy(tmp_t, 0, t, 0, tmp_t.length); ///////////////
-
- t[i+1] = t[i]/2;
- s = i+1;
- }
-
- //step3
- BigInteger p[] = new BigInteger[s+1];
- p[s] = new BigInteger("8003",16); //set min prime number length 16 bit
-
- int m = s-1; //step4
-
- for (int i=0; i<s; i++)
- {
- int rm = t[m]/16; //step5
-
- step6: for(;;)
- {
- //step 6
- BigInteger tmp_y[] = new BigInteger[y.length]; ////////////////
- System.arraycopy(y,0,tmp_y,0,y.length); // extension
- y = new BigInteger[rm+1]; // array y
- System.arraycopy(tmp_y,0,y,0,tmp_y.length); ////////////////
-
- for (int j=0; j<rm; j++)
- {
- y[j+1] = (y[j].multiply(constA16).add(C)).mod(TWO.pow(16));
- }
-
- //step 7
- BigInteger Ym = new BigInteger("0");
- for (int j=0; j<rm; j++)
- {
- Ym = Ym.add(y[j].multiply(TWO.pow(16*j)));
- }
-
- y[0] = y[rm]; //step 8
-
- //step 9
- BigInteger N = TWO.pow(t[m]-1).divide(p[m+1]).
- add((TWO.pow(t[m]-1).multiply(Ym)).
- divide(p[m+1].multiply(TWO.pow(16*rm))));
-
- if (N.mod(TWO).compareTo(ONE)==0)
- {
- N = N.add(ONE);
- }
-
- int k = 0; //step 10
-
- step11: for(;;)
- {
- //step 11
- p[m] = p[m+1].multiply(N.add(BigInteger.valueOf(k))).add(ONE);
-
- if (p[m].compareTo(TWO.pow(t[m]))==1)
- {
- continue step6; //step 12
- }
-
- //step13
- if ((TWO.modPow(p[m+1].multiply(N.add(BigInteger.valueOf(k))),p[m]).compareTo(ONE)==0) &&
- (TWO.modPow(N.add(BigInteger.valueOf(k)),p[m]).compareTo(ONE)!=0))
- {
- m -= 1;
- break;
- }
- else
- {
- k += 2;
- continue step11;
- }
- }
-
- if (m>=0)
- {
- break; //step 14
- }
- else
- {
- pq[0] = p[0];
- pq[1] = p[1];
- return y[0].intValue(); //return for procedure B step 2
- }
- }
- }
- return y[0].intValue();
- }
-
- //Procedure A'
- private long procedure_Aa(long x0, long c, BigInteger[] pq, int size)
- {
- //Verify and perform condition: 0<x<2^32; 0<c<2^32; c - odd.
- while(x0<0 || x0>4294967296L)
- {
- x0 = init_random.nextInt()*2;
- }
-
- while((c<0 || c>4294967296L) || (c/2==0))
- {
- c = init_random.nextInt()*2+1;
- }
-
- BigInteger C = new BigInteger(Long.toString(c));
- BigInteger constA32 = new BigInteger("97781173");
-
- //step1
- BigInteger[] y = new BigInteger[1]; // begin length = 1
- y[0] = new BigInteger(Long.toString(x0));
-
- //step 2
- int[] t = new int[1]; // t - orders; begin length = 1
- t[0] = size;
- int s = 0;
- for (int i=0; t[i]>=33; i++)
- {
- // extension array t
- int tmp_t[] = new int[t.length + 1]; ///////////////
- System.arraycopy(t,0,tmp_t,0,t.length); // extension
- t = new int[tmp_t.length]; // array t
- System.arraycopy(tmp_t, 0, t, 0, tmp_t.length); ///////////////
-
- t[i+1] = t[i]/2;
- s = i+1;
- }
-
- //step3
- BigInteger p[] = new BigInteger[s+1];
- p[s] = new BigInteger("8000000B",16); //set min prime number length 32 bit
-
- int m = s-1; //step4
-
- for (int i=0; i<s; i++)
- {
- int rm = t[m]/32; //step5
-
- step6: for(;;)
- {
- //step 6
- BigInteger tmp_y[] = new BigInteger[y.length]; ////////////////
- System.arraycopy(y,0,tmp_y,0,y.length); // extension
- y = new BigInteger[rm+1]; // array y
- System.arraycopy(tmp_y,0,y,0,tmp_y.length); ////////////////
-
- for (int j=0; j<rm; j++)
- {
- y[j+1] = (y[j].multiply(constA32).add(C)).mod(TWO.pow(32));
- }
-
- //step 7
- BigInteger Ym = new BigInteger("0");
- for (int j=0; j<rm; j++)
- {
- Ym = Ym.add(y[j].multiply(TWO.pow(32*j)));
- }
-
- y[0] = y[rm]; //step 8
-
- //step 9
- BigInteger N = TWO.pow(t[m]-1).divide(p[m+1]).
- add((TWO.pow(t[m]-1).multiply(Ym)).
- divide(p[m+1].multiply(TWO.pow(32*rm))));
-
- if (N.mod(TWO).compareTo(ONE)==0)
- {
- N = N.add(ONE);
- }
-
- int k = 0; //step 10
-
- step11: for(;;)
- {
- //step 11
- p[m] = p[m+1].multiply(N.add(BigInteger.valueOf(k))).add(ONE);
-
- if (p[m].compareTo(TWO.pow(t[m]))==1)
- {
- continue step6; //step 12
- }
-
- //step13
- if ((TWO.modPow(p[m+1].multiply(N.add(BigInteger.valueOf(k))),p[m]).compareTo(ONE)==0) &&
- (TWO.modPow(N.add(BigInteger.valueOf(k)),p[m]).compareTo(ONE)!=0))
- {
- m -= 1;
- break;
- }
- else
- {
- k += 2;
- continue step11;
- }
- }
-
- if (m>=0)
- {
- break; //step 14
- }
- else
- {
- pq[0] = p[0];
- pq[1] = p[1];
- return y[0].longValue(); //return for procedure B' step 2
- }
- }
- }
- return y[0].longValue();
- }
-
- //Procedure B
- private void procedure_B(int x0, int c, BigInteger[] pq)
- {
- //Verify and perform condition: 0<x<2^16; 0<c<2^16; c - odd.
- while(x0<0 || x0>65536)
- {
- x0 = init_random.nextInt()/32768;
- }
-
- while((c<0 || c>65536) || (c/2==0))
- {
- c = init_random.nextInt()/32768 + 1;
- }
-
- BigInteger [] qp = new BigInteger[2];
- BigInteger q = null, Q = null, p = null;
- BigInteger C = new BigInteger(Integer.toString(c));
- BigInteger constA16 = new BigInteger("19381");
-
- //step1
- x0 = procedure_A(x0, c, qp, 256);
- q = qp[0];
-
- //step2
- x0 = procedure_A(x0, c, qp, 512);
- Q = qp[0];
-
- BigInteger[] y = new BigInteger[65];
- y[0] = new BigInteger(Integer.toString(x0));
-
- int tp = 1024;
-
- step3: for(;;)
- {
- //step 3
- for (int j=0; j<64; j++)
- {
- y[j+1] = (y[j].multiply(constA16).add(C)).mod(TWO.pow(16));
- }
-
- //step 4
- BigInteger Y = new BigInteger("0");
-
- for (int j=0; j<64; j++)
- {
- Y = Y.add(y[j].multiply(TWO.pow(16*j)));
- }
-
- y[0] = y[64]; //step 5
-
- //step 6
- BigInteger N = TWO.pow(tp-1).divide(q.multiply(Q)).
- add((TWO.pow(tp-1).multiply(Y)).
- divide(q.multiply(Q).multiply(TWO.pow(1024))));
-
- if (N.mod(TWO).compareTo(ONE)==0)
- {
- N = N.add(ONE);
- }
-
- int k = 0; //step 7
-
- step8: for(;;)
- {
- //step 11
- p = q.multiply(Q).multiply(N.add(BigInteger.valueOf(k))).add(ONE);
-
- if (p.compareTo(TWO.pow(tp))==1)
- {
- continue step3; //step 9
- }
-
- //step10
- if ((TWO.modPow(q.multiply(Q).multiply(N.add(BigInteger.valueOf(k))),p).compareTo(ONE)==0) &&
- (TWO.modPow(q.multiply(N.add(BigInteger.valueOf(k))),p).compareTo(ONE)!=0))
- {
- pq[0] = p;
- pq[1] = q;
- return;
- }
- else
- {
- k += 2;
- continue step8;
- }
- }
- }
- }
-
- //Procedure B'
- private void procedure_Bb(long x0, long c, BigInteger[] pq)
- {
- //Verify and perform condition: 0<x<2^32; 0<c<2^32; c - odd.
- while(x0<0 || x0>4294967296L)
- {
- x0 = init_random.nextInt()*2;
- }
-
- while((c<0 || c>4294967296L) || (c/2==0))
- {
- c = init_random.nextInt()*2+1;
- }
-
- BigInteger [] qp = new BigInteger[2];
- BigInteger q = null, Q = null, p = null;
- BigInteger C = new BigInteger(Long.toString(c));
- BigInteger constA32 = new BigInteger("97781173");
-
- //step1
- x0 = procedure_Aa(x0, c, qp, 256);
- q = qp[0];
-
- //step2
- x0 = procedure_Aa(x0, c, qp, 512);
- Q = qp[0];
-
- BigInteger[] y = new BigInteger[33];
- y[0] = new BigInteger(Long.toString(x0));
-
- int tp = 1024;
-
- step3: for(;;)
- {
- //step 3
- for (int j=0; j<32; j++)
- {
- y[j+1] = (y[j].multiply(constA32).add(C)).mod(TWO.pow(32));
- }
-
- //step 4
- BigInteger Y = new BigInteger("0");
- for (int j=0; j<32; j++)
- {
- Y = Y.add(y[j].multiply(TWO.pow(32*j)));
- }
-
- y[0] = y[32]; //step 5
-
- //step 6
- BigInteger N = TWO.pow(tp-1).divide(q.multiply(Q)).
- add((TWO.pow(tp-1).multiply(Y)).
- divide(q.multiply(Q).multiply(TWO.pow(1024))));
-
- if (N.mod(TWO).compareTo(ONE)==0)
- {
- N = N.add(ONE);
- }
-
- int k = 0; //step 7
-
- step8: for(;;)
- {
- //step 11
- p = q.multiply(Q).multiply(N.add(BigInteger.valueOf(k))).add(ONE);
-
- if (p.compareTo(TWO.pow(tp))==1)
- {
- continue step3; //step 9
- }
-
- //step10
- if ((TWO.modPow(q.multiply(Q).multiply(N.add(BigInteger.valueOf(k))),p).compareTo(ONE)==0) &&
- (TWO.modPow(q.multiply(N.add(BigInteger.valueOf(k))),p).compareTo(ONE)!=0))
- {
- pq[0] = p;
- pq[1] = q;
- return;
- }
- else
- {
- k += 2;
- continue step8;
- }
- }
- }
- }
-
-
- /**
- * Procedure C
- * procedure generates the a value from the given p,q,
- * returning the a value.
- */
- private BigInteger procedure_C(BigInteger p, BigInteger q)
- {
- BigInteger pSub1 = p.subtract(ONE);
- BigInteger pSub1DivQ = pSub1.divide(q);
- int length = p.bitLength();
-
- for(;;)
- {
- BigInteger d = new BigInteger(length, init_random);
-
- // 1 < d < p-1
- if (d.compareTo(ONE) > 0 && d.compareTo(pSub1) < 0)
- {
- BigInteger a = d.modPow(pSub1DivQ, p);
-
- if (a.compareTo(ONE) != 0)
- {
- return a;
- }
- }
- }
- }
-
- /**
- * which generates the p , q and a values from the given parameters,
- * returning the GOST3410Parameters object.
- */
- public GOST3410Parameters generateParameters()
- {
- BigInteger [] pq = new BigInteger[2];
- BigInteger q = null, p = null, a = null;
-
- int x0, c;
- long x0L, cL;
-
- if (typeproc==1)
- {
- x0 = init_random.nextInt();
- c = init_random.nextInt();
-
- switch(size)
- {
- case 512:
- procedure_A(x0, c, pq, 512);
- break;
- case 1024:
- procedure_B(x0, c, pq);
- break;
- default:
- throw new IllegalArgumentException("Ooops! key size 512 or 1024 bit.");
- }
- p = pq[0]; q = pq[1];
- a = procedure_C(p, q);
- //System.out.println("p:"+p.toString(16)+"\n"+"q:"+q.toString(16)+"\n"+"a:"+a.toString(16));
- //System.out.println("p:"+p+"\n"+"q:"+q+"\n"+"a:"+a);
- return new GOST3410Parameters(p, q, a, new GOST3410ValidationParameters(x0, c));
- }
- else
- {
- x0L = init_random.nextLong();
- cL = init_random.nextLong();
-
- switch(size)
- {
- case 512:
- procedure_Aa(x0L, cL, pq, 512);
- break;
- case 1024:
- procedure_Bb(x0L, cL, pq);
- break;
- default:
- throw new IllegalStateException("Ooops! key size 512 or 1024 bit.");
- }
- p = pq[0]; q = pq[1];
- a = procedure_C(p, q);
- //System.out.println("p:"+p.toString(16)+"\n"+"q:"+q.toString(16)+"\n"+"a:"+a.toString(16));
- //System.out.println("p:"+p+"\n"+"q:"+q+"\n"+"a:"+a);
- return new GOST3410Parameters(p, q, a, new GOST3410ValidationParameters(x0L, cL));
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/HKDFBytesGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/HKDFBytesGenerator.java
deleted file mode 100644
index 75915cf2..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/HKDFBytesGenerator.java
+++ /dev/null
@@ -1,161 +0,0 @@
-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.macs.HMac;
-import org.bouncycastle.crypto.params.HKDFParameters;
-import org.bouncycastle.crypto.params.KeyParameter;
-
-/**
- * HMAC-based Extract-and-Expand Key Derivation Function (HKDF) implemented
- * according to IETF RFC 5869, May 2010 as specified by H. Krawczyk, IBM
- * Research &amp; P. Eronen, Nokia. It uses a HMac internally to compute de OKM
- * (output keying material) and is likely to have better security properties
- * than KDF's based on just a hash function.
- */
-public class HKDFBytesGenerator
- implements DerivationFunction
-{
-
- private HMac hMacHash;
- private int hashLen;
-
- private byte[] info;
- private byte[] currentT;
-
- private int generatedBytes;
-
- /**
- * Creates a HKDFBytesGenerator based on the given hash function.
- *
- * @param hash the digest to be used as the source of generatedBytes bytes
- */
- public HKDFBytesGenerator(Digest hash)
- {
- this.hMacHash = new HMac(hash);
- this.hashLen = hash.getDigestSize();
- }
-
- public void init(DerivationParameters param)
- {
- if (!(param instanceof HKDFParameters))
- {
- throw new IllegalArgumentException(
- "HKDF parameters required for HKDFBytesGenerator");
- }
-
- HKDFParameters params = (HKDFParameters)param;
- if (params.skipExtract())
- {
- // use IKM directly as PRK
- hMacHash.init(new KeyParameter(params.getIKM()));
- }
- else
- {
- hMacHash.init(extract(params.getSalt(), params.getIKM()));
- }
-
- info = params.getInfo();
-
- generatedBytes = 0;
- currentT = new byte[hashLen];
- }
-
- /**
- * Performs the extract part of the key derivation function.
- *
- * @param salt the salt to use
- * @param ikm the input keying material
- * @return the PRK as KeyParameter
- */
- private KeyParameter extract(byte[] salt, byte[] ikm)
- {
- hMacHash.init(new KeyParameter(ikm));
- if (salt == null)
- {
- // TODO check if hashLen is indeed same as HMAC size
- hMacHash.init(new KeyParameter(new byte[hashLen]));
- }
- else
- {
- hMacHash.init(new KeyParameter(salt));
- }
-
- hMacHash.update(ikm, 0, ikm.length);
-
- byte[] prk = new byte[hashLen];
- hMacHash.doFinal(prk, 0);
- return new KeyParameter(prk);
- }
-
- /**
- * Performs the expand part of the key derivation function, using currentT
- * as input and output buffer.
- *
- * @throws DataLengthException if the total number of bytes generated is larger than the one
- * specified by RFC 5869 (255 * HashLen)
- */
- private void expandNext()
- throws DataLengthException
- {
- int n = generatedBytes / hashLen + 1;
- if (n >= 256)
- {
- throw new DataLengthException(
- "HKDF cannot generate more than 255 blocks of HashLen size");
- }
- // special case for T(0): T(0) is empty, so no update
- if (generatedBytes != 0)
- {
- hMacHash.update(currentT, 0, hashLen);
- }
- hMacHash.update(info, 0, info.length);
- hMacHash.update((byte)n);
- hMacHash.doFinal(currentT, 0);
- }
-
- public Digest getDigest()
- {
- return hMacHash.getUnderlyingDigest();
- }
-
- public int generateBytes(byte[] out, int outOff, int len)
- throws DataLengthException, IllegalArgumentException
- {
-
- if (generatedBytes + len > 255 * hashLen)
- {
- throw new DataLengthException(
- "HKDF may only be used for 255 * HashLen bytes of output");
- }
-
- if (generatedBytes % hashLen == 0)
- {
- expandNext();
- }
-
- // copy what is left in the currentT (1..hash
- int toGenerate = len;
- int posInT = generatedBytes % hashLen;
- int leftInT = hashLen - generatedBytes % hashLen;
- int toCopy = Math.min(leftInT, toGenerate);
- System.arraycopy(currentT, posInT, out, outOff, toCopy);
- generatedBytes += toCopy;
- toGenerate -= toCopy;
- outOff += toCopy;
-
- while (toGenerate > 0)
- {
- expandNext();
- toCopy = Math.min(hashLen, toGenerate);
- System.arraycopy(currentT, 0, out, outOff, toCopy);
- generatedBytes += toCopy;
- toGenerate -= toCopy;
- outOff += toCopy;
- }
-
- return len;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/KDF1BytesGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/KDF1BytesGenerator.java
deleted file mode 100644
index 7789b7b5..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/KDF1BytesGenerator.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.Digest;
-
-/**
- * KDF1 generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033
- * <br>
- * This implementation is based on ISO 18033/IEEE P1363a.
- */
-public class KDF1BytesGenerator
- extends BaseKDFBytesGenerator
-{
- /**
- * Construct a KDF1 byte generator.
- * <p>
- * @param digest the digest to be used as the source of derived keys.
- */
- public KDF1BytesGenerator(
- Digest digest)
- {
- super(0, digest);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/KDF2BytesGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/KDF2BytesGenerator.java
deleted file mode 100644
index ac0c64a4..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/KDF2BytesGenerator.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.Digest;
-
-/**
- * KDF2 generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033
- * <br>
- * This implementation is based on IEEE P1363/ISO 18033.
- */
-public class KDF2BytesGenerator
- extends BaseKDFBytesGenerator
-{
- /**
- * Construct a KDF2 bytes generator. Generates key material
- * according to IEEE P1363 or ISO 18033 depending on the initialisation.
- * <p>
- * @param digest the digest to be used as the source of derived keys.
- */
- public KDF2BytesGenerator(
- Digest digest)
- {
- super(1, digest);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/KDFCounterBytesGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/KDFCounterBytesGenerator.java
deleted file mode 100644
index 7147add7..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/KDFCounterBytesGenerator.java
+++ /dev/null
@@ -1,180 +0,0 @@
-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.
- * NIST SP800-108 allows for alternative orderings of the input fields, meaning that the input can be formated in multiple ways.
- * There are 3 supported formats: - Below [i]_2 is a counter of r-bits length concatenated to the fixedInputData.
- * <ul>
- * <li>1: K(i) := PRF( KI, [i]_2 || Label || 0x00 || Context || [L]_2 ) with the counter at the very beginning of the fixedInputData (The default implementation has this format)</li>
- * <li>2: K(i) := PRF( KI, Label || 0x00 || Context || [L]_2 || [i]_2 ) with the counter at the very end of the fixedInputData</li>
- * <li>3a: K(i) := PRF( KI, Label || 0x00 || [i]_2 || Context || [L]_2 ) OR:</li>
- * <li>3b: K(i) := PRF( KI, Label || 0x00 || [i]_2 || [L]_2 || Context ) OR:</li>
- * <li>3c: K(i) := PRF( KI, Label || [i]_2 || 0x00 || Context || [L]_2 ) etc... with the counter somewhere in the 'middle' of the fixedInputData.</li>
- * </ul>
- * </p>
- * <p>
- * This function must be called with the following KDFCounterParameters():
- * - KI <br/>
- * - The part of the fixedInputData that comes BEFORE the counter OR null <br/>
- * - the part of the fixedInputData that comes AFTER the counter OR null <br/>
- * - the length of the counter in bits (not bytes)
- * </p>
- * Resulting function calls assuming an 8 bit counter.
- * <ul>
- * <li>1. KDFCounterParameters(ki, null, "Label || 0x00 || Context || [L]_2]", 8);</li>
- * <li>2. KDFCounterParameters(ki, "Label || 0x00 || Context || [L]_2]", null, 8);</li>
- * <li>3a. KDFCounterParameters(ki, "Label || 0x00", "Context || [L]_2]", 8);</li>
- * <li>3b. KDFCounterParameters(ki, "Label || 0x00", "[L]_2] || Context", 8);</li>
- * <li>3c. KDFCounterParameters(ki, "Label", "0x00 || Context || [L]_2]", 8);</li>
- * </ul>
- */
-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[] fixedInputDataCtrPrefix;
- private byte[] fixedInputData_afterCtr;
- 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.fixedInputDataCtrPrefix = kdfParams.getFixedInputDataCounterPrefix();
- this.fixedInputData_afterCtr = kdfParams.getFixedInputDataCounterSuffix();
-
- 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(fixedInputDataCtrPrefix, 0, fixedInputDataCtrPrefix.length);
- prf.update(ios, 0, ios.length);
- prf.update(fixedInputData_afterCtr, 0, fixedInputData_afterCtr.length);
- prf.doFinal(k, 0);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/KDFDoublePipelineIterationBytesGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/KDFDoublePipelineIterationBytesGenerator.java
deleted file mode 100644
index 6115a1a3..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/KDFDoublePipelineIterationBytesGenerator.java
+++ /dev/null
@@ -1,181 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/generators/KDFFeedbackBytesGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/KDFFeedbackBytesGenerator.java
deleted file mode 100644
index 60030376..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/KDFFeedbackBytesGenerator.java
+++ /dev/null
@@ -1,175 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/generators/MGF1BytesGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/MGF1BytesGenerator.java
deleted file mode 100644
index e93c0d73..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/MGF1BytesGenerator.java
+++ /dev/null
@@ -1,114 +0,0 @@
-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.params.MGFParameters;
-
-/**
- * Generator for MGF1 as defined in PKCS 1v2
- */
-public class MGF1BytesGenerator
- implements DerivationFunction
-{
- private Digest digest;
- private byte[] seed;
- private int hLen;
-
- /**
- * @param digest the digest to be used as the source of generated bytes
- */
- public MGF1BytesGenerator(
- Digest digest)
- {
- this.digest = digest;
- this.hLen = digest.getDigestSize();
- }
-
- public void init(
- DerivationParameters param)
- {
- if (!(param instanceof MGFParameters))
- {
- throw new IllegalArgumentException("MGF parameters required for MGF1Generator");
- }
-
- MGFParameters p = (MGFParameters)param;
-
- seed = p.getSeed();
- }
-
- /**
- * return the underlying digest.
- */
- public Digest getDigest()
- {
- return digest;
- }
-
- /**
- * int to octet string.
- */
- private void ItoOSP(
- int i,
- byte[] sp)
- {
- sp[0] = (byte)(i >>> 24);
- sp[1] = (byte)(i >>> 16);
- sp[2] = (byte)(i >>> 8);
- sp[3] = (byte)(i >>> 0);
- }
-
- /**
- * fill len bytes of the output buffer with bytes generated from
- * the derivation function.
- *
- * @throws DataLengthException if the out buffer is too small.
- */
- public int generateBytes(
- byte[] out,
- int outOff,
- int len)
- throws DataLengthException, IllegalArgumentException
- {
- if ((out.length - len) < outOff)
- {
- throw new DataLengthException("output buffer too small");
- }
-
- byte[] hashBuf = new byte[hLen];
- byte[] C = new byte[4];
- int counter = 0;
-
- digest.reset();
-
- if (len > hLen)
- {
- do
- {
- ItoOSP(counter, C);
-
- digest.update(seed, 0, seed.length);
- digest.update(C, 0, C.length);
- digest.doFinal(hashBuf, 0);
-
- System.arraycopy(hashBuf, 0, out, outOff + counter * hLen, hLen);
- }
- while (++counter < (len / hLen));
- }
-
- if ((counter * hLen) < len)
- {
- ItoOSP(counter, C);
-
- digest.update(seed, 0, seed.length);
- digest.update(C, 0, C.length);
- digest.doFinal(hashBuf, 0);
-
- System.arraycopy(hashBuf, 0, out, outOff + counter * hLen, len - (counter * hLen));
- }
-
- return len;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/NaccacheSternKeyPairGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/NaccacheSternKeyPairGenerator.java
deleted file mode 100644
index ceb39407..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/NaccacheSternKeyPairGenerator.java
+++ /dev/null
@@ -1,365 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.params.NaccacheSternKeyGenerationParameters;
-import org.bouncycastle.crypto.params.NaccacheSternKeyParameters;
-import org.bouncycastle.crypto.params.NaccacheSternPrivateKeyParameters;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-import java.util.Vector;
-
-/**
- * Key generation parameters for NaccacheStern cipher. For details on this cipher, please see
- *
- * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
- */
-public class NaccacheSternKeyPairGenerator
- implements AsymmetricCipherKeyPairGenerator
-{
-
- private static int[] smallPrimes =
- {
- 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67,
- 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149,
- 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
- 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331,
- 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431,
- 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523,
- 541, 547, 557
- };
-
- private NaccacheSternKeyGenerationParameters param;
-
- private static final BigInteger ONE = BigInteger.valueOf(1); // JDK 1.1 compatibility
-
- /*
- * (non-Javadoc)
- *
- * @see org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator#init(org.bouncycastle.crypto.KeyGenerationParameters)
- */
- public void init(KeyGenerationParameters param)
- {
- this.param = (NaccacheSternKeyGenerationParameters)param;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator#generateKeyPair()
- */
- public AsymmetricCipherKeyPair generateKeyPair()
- {
- int strength = param.getStrength();
- SecureRandom rand = param.getRandom();
- int certainty = param.getCertainty();
- boolean debug = param.isDebug();
-
- if (debug)
- {
- System.out.println("Fetching first " + param.getCntSmallPrimes() + " primes.");
- }
-
- Vector smallPrimes = findFirstPrimes(param.getCntSmallPrimes());
- smallPrimes = permuteList(smallPrimes, rand);
-
- BigInteger u = ONE;
- BigInteger v = ONE;
-
- for (int i = 0; i < smallPrimes.size() / 2; i++)
- {
- u = u.multiply((BigInteger)smallPrimes.elementAt(i));
- }
- for (int i = smallPrimes.size() / 2; i < smallPrimes.size(); i++)
- {
- v = v.multiply((BigInteger)smallPrimes.elementAt(i));
- }
-
- BigInteger sigma = u.multiply(v);
-
- // n = (2 a u p_ + 1 ) ( 2 b v q_ + 1)
- // -> |n| = strength
- // |2| = 1 in bits
- // -> |a| * |b| = |n| - |u| - |v| - |p_| - |q_| - |2| -|2|
- // remainingStrength = strength - sigma.bitLength() - p_.bitLength() -
- // q_.bitLength() - 1 -1
- int remainingStrength = strength - sigma.bitLength() - 48;
- BigInteger a = generatePrime(remainingStrength / 2 + 1, certainty, rand);
- BigInteger b = generatePrime(remainingStrength / 2 + 1, certainty, rand);
-
- BigInteger p_;
- BigInteger q_;
- BigInteger p;
- BigInteger q;
- long tries = 0;
- if (debug)
- {
- System.out.println("generating p and q");
- }
-
- BigInteger _2au = a.multiply(u).shiftLeft(1);
- BigInteger _2bv = b.multiply(v).shiftLeft(1);
-
- for (;;)
- {
- tries++;
-
- p_ = generatePrime(24, certainty, rand);
-
- p = p_.multiply(_2au).add(ONE);
-
- if (!p.isProbablePrime(certainty))
- {
- continue;
- }
-
- for (;;)
- {
- q_ = generatePrime(24, certainty, rand);
-
- if (p_.equals(q_))
- {
- continue;
- }
-
- q = q_.multiply(_2bv).add(ONE);
-
- if (q.isProbablePrime(certainty))
- {
- break;
- }
- }
-
- if (!sigma.gcd(p_.multiply(q_)).equals(ONE))
- {
- // System.out.println("sigma.gcd(p_.mult(q_)) != 1!\n p_: " + p_
- // +"\n q_: "+ q_ );
- continue;
- }
-
- if (p.multiply(q).bitLength() < strength)
- {
- if (debug)
- {
- System.out.println("key size too small. Should be " + strength + " but is actually "
- + p.multiply(q).bitLength());
- }
- continue;
- }
- break;
- }
-
- if (debug)
- {
- System.out.println("needed " + tries + " tries to generate p and q.");
- }
-
- BigInteger n = p.multiply(q);
- BigInteger phi_n = p.subtract(ONE).multiply(q.subtract(ONE));
- BigInteger g;
- tries = 0;
- if (debug)
- {
- System.out.println("generating g");
- }
- for (;;)
- {
-
- Vector gParts = new Vector();
- for (int ind = 0; ind != smallPrimes.size(); ind++)
- {
- BigInteger i = (BigInteger)smallPrimes.elementAt(ind);
- BigInteger e = phi_n.divide(i);
-
- for (;;)
- {
- tries++;
- g = new BigInteger(strength, certainty, rand);
- if (g.modPow(e, n).equals(ONE))
- {
- continue;
- }
- gParts.addElement(g);
- break;
- }
- }
- g = ONE;
- for (int i = 0; i < smallPrimes.size(); i++)
- {
- g = g.multiply(((BigInteger)gParts.elementAt(i)).modPow(sigma.divide((BigInteger)smallPrimes.elementAt(i)), n)).mod(n);
- }
-
- // make sure that g is not divisible by p_i or q_i
- boolean divisible = false;
- for (int i = 0; i < smallPrimes.size(); i++)
- {
- if (g.modPow(phi_n.divide((BigInteger)smallPrimes.elementAt(i)), n).equals(ONE))
- {
- if (debug)
- {
- System.out.println("g has order phi(n)/" + smallPrimes.elementAt(i) + "\n g: " + g);
- }
- divisible = true;
- break;
- }
- }
-
- if (divisible)
- {
- continue;
- }
-
- // make sure that g has order > phi_n/4
-
- if (g.modPow(phi_n.divide(BigInteger.valueOf(4)), n).equals(ONE))
- {
- if (debug)
- {
- System.out.println("g has order phi(n)/4\n g:" + g);
- }
- continue;
- }
-
- if (g.modPow(phi_n.divide(p_), n).equals(ONE))
- {
- if (debug)
- {
- System.out.println("g has order phi(n)/p'\n g: " + g);
- }
- continue;
- }
- if (g.modPow(phi_n.divide(q_), n).equals(ONE))
- {
- if (debug)
- {
- System.out.println("g has order phi(n)/q'\n g: " + g);
- }
- continue;
- }
- if (g.modPow(phi_n.divide(a), n).equals(ONE))
- {
- if (debug)
- {
- System.out.println("g has order phi(n)/a\n g: " + g);
- }
- continue;
- }
- if (g.modPow(phi_n.divide(b), n).equals(ONE))
- {
- if (debug)
- {
- System.out.println("g has order phi(n)/b\n g: " + g);
- }
- continue;
- }
- break;
- }
- if (debug)
- {
- System.out.println("needed " + tries + " tries to generate g");
- System.out.println();
- System.out.println("found new NaccacheStern cipher variables:");
- System.out.println("smallPrimes: " + smallPrimes);
- System.out.println("sigma:...... " + sigma + " (" + sigma.bitLength() + " bits)");
- System.out.println("a:.......... " + a);
- System.out.println("b:.......... " + b);
- System.out.println("p':......... " + p_);
- System.out.println("q':......... " + q_);
- System.out.println("p:.......... " + p);
- System.out.println("q:.......... " + q);
- System.out.println("n:.......... " + n);
- System.out.println("phi(n):..... " + phi_n);
- System.out.println("g:.......... " + g);
- System.out.println();
- }
-
- return new AsymmetricCipherKeyPair(new NaccacheSternKeyParameters(false, g, n, sigma.bitLength()),
- new NaccacheSternPrivateKeyParameters(g, n, sigma.bitLength(), smallPrimes, phi_n));
- }
-
- private static BigInteger generatePrime(
- int bitLength,
- int certainty,
- SecureRandom rand)
- {
- BigInteger p_ = new BigInteger(bitLength, certainty, rand);
- while (p_.bitLength() != bitLength)
- {
- p_ = new BigInteger(bitLength, certainty, rand);
- }
- return p_;
- }
-
- /**
- * Generates a permuted ArrayList from the original one. The original List
- * is not modified
- *
- * @param arr
- * the ArrayList to be permuted
- * @param rand
- * the source of Randomness for permutation
- * @return a new ArrayList with the permuted elements.
- */
- private static Vector permuteList(
- Vector arr,
- SecureRandom rand)
- {
- Vector retval = new Vector();
- Vector tmp = new Vector();
- for (int i = 0; i < arr.size(); i++)
- {
- tmp.addElement(arr.elementAt(i));
- }
- retval.addElement(tmp.elementAt(0));
- tmp.removeElementAt(0);
- while (tmp.size() != 0)
- {
- retval.insertElementAt(tmp.elementAt(0), getInt(rand, retval.size() + 1));
- tmp.removeElementAt(0);
- }
- return retval;
- }
-
- private static int getInt(
- SecureRandom rand,
- int n)
- {
- if ((n & -n) == n)
- {
- return (int)((n * (long)(rand.nextInt() & 0x7fffffff)) >> 31);
- }
-
- int bits, val;
- do
- {
- bits = rand.nextInt() & 0x7fffffff;
- val = bits % n;
- }
- while (bits - val + (n-1) < 0);
-
- return val;
- }
-
- /**
- * Finds the first 'count' primes starting with 3
- *
- * @param count
- * the number of primes to find
- * @return a vector containing the found primes as Integer
- */
- private static Vector findFirstPrimes(
- int count)
- {
- Vector primes = new Vector(count);
-
- for (int i = 0; i != count; i++)
- {
- primes.addElement(BigInteger.valueOf(smallPrimes[i]));
- }
-
- return primes;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java
deleted file mode 100644
index 8a4d28ab..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.PBEParametersGenerator;
-import org.bouncycastle.crypto.digests.MD5Digest;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-/**
- * Generator for PBE derived keys and ivs as usd by OpenSSL.
- * <p>
- * The scheme is a simple extension of PKCS 5 V2.0 Scheme 1 using MD5 with an
- * iteration count of 1.
- * <p>
- */
-public class OpenSSLPBEParametersGenerator
- extends PBEParametersGenerator
-{
- private Digest digest = new MD5Digest();
-
- /**
- * Construct a OpenSSL Parameters generator.
- */
- public OpenSSLPBEParametersGenerator()
- {
- }
-
- /**
- * Initialise - note the iteration count for this algorithm is fixed at 1.
- *
- * @param password password to use.
- * @param salt salt to use.
- */
- public void init(
- byte[] password,
- byte[] salt)
- {
- super.init(password, salt, 1);
- }
-
- /**
- * the derived key function, the ith hash of the password and the salt.
- */
- private byte[] generateDerivedKey(
- int bytesNeeded)
- {
- byte[] buf = new byte[digest.getDigestSize()];
- byte[] key = new byte[bytesNeeded];
- int offset = 0;
-
- for (;;)
- {
- digest.update(password, 0, password.length);
- digest.update(salt, 0, salt.length);
-
- digest.doFinal(buf, 0);
-
- int len = (bytesNeeded > buf.length) ? buf.length : bytesNeeded;
- System.arraycopy(buf, 0, key, offset, len);
- offset += len;
-
- // check if we need any more
- bytesNeeded -= len;
- if (bytesNeeded == 0)
- {
- break;
- }
-
- // do another round
- digest.reset();
- digest.update(buf, 0, buf.length);
- }
-
- return key;
- }
-
- /**
- * Generate a key parameter derived from the password, salt, and iteration
- * count we are currently initialised with.
- *
- * @param keySize the size of the key we want (in bits)
- * @return a KeyParameter object.
- * @exception IllegalArgumentException if the key length larger than the base hash size.
- */
- public CipherParameters generateDerivedParameters(
- int keySize)
- {
- keySize = keySize / 8;
-
- byte[] dKey = generateDerivedKey(keySize);
-
- return new KeyParameter(dKey, 0, keySize);
- }
-
- /**
- * Generate a key with initialisation vector parameter derived from
- * the password, salt, and iteration count we are currently initialised
- * with.
- *
- * @param keySize the size of the key we want (in bits)
- * @param ivSize the size of the iv we want (in bits)
- * @return a ParametersWithIV object.
- * @exception IllegalArgumentException if keySize + ivSize is larger than the base hash size.
- */
- public CipherParameters generateDerivedParameters(
- int keySize,
- int ivSize)
- {
- keySize = keySize / 8;
- ivSize = ivSize / 8;
-
- byte[] dKey = generateDerivedKey(keySize + ivSize);
-
- return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
- }
-
- /**
- * Generate a key parameter for use with a MAC derived from the password,
- * salt, and iteration count we are currently initialised with.
- *
- * @param keySize the size of the key we want (in bits)
- * @return a KeyParameter object.
- * @exception IllegalArgumentException if the key length larger than the base hash size.
- */
- public CipherParameters generateDerivedMacParameters(
- int keySize)
- {
- return generateDerivedParameters(keySize);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/PKCS12ParametersGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/PKCS12ParametersGenerator.java
deleted file mode 100644
index d9b82c32..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/PKCS12ParametersGenerator.java
+++ /dev/null
@@ -1,220 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.ExtendedDigest;
-import org.bouncycastle.crypto.PBEParametersGenerator;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-/**
- * Generator for PBE derived keys and ivs as defined by PKCS 12 V1.0.
- * <p>
- * The document this implementation is based on can be found at
- * <a href=http://www.rsasecurity.com/rsalabs/pkcs/pkcs-12/index.html>
- * RSA's PKCS12 Page</a>
- */
-public class PKCS12ParametersGenerator
- extends PBEParametersGenerator
-{
- public static final int KEY_MATERIAL = 1;
- public static final int IV_MATERIAL = 2;
- public static final int MAC_MATERIAL = 3;
-
- private Digest digest;
-
- private int u;
- private int v;
-
- /**
- * Construct a PKCS 12 Parameters generator. This constructor will
- * accept any digest which also implements ExtendedDigest.
- *
- * @param digest the digest to be used as the source of derived keys.
- * @exception IllegalArgumentException if an unknown digest is passed in.
- */
- public PKCS12ParametersGenerator(
- Digest digest)
- {
- this.digest = digest;
- if (digest instanceof ExtendedDigest)
- {
- u = digest.getDigestSize();
- v = ((ExtendedDigest)digest).getByteLength();
- }
- else
- {
- throw new IllegalArgumentException("Digest " + digest.getAlgorithmName() + " unsupported");
- }
- }
-
- /**
- * add a + b + 1, returning the result in a. The a value is treated
- * as a BigInteger of length (b.length * 8) bits. The result is
- * modulo 2^b.length in case of overflow.
- */
- private void adjust(
- byte[] a,
- int aOff,
- byte[] b)
- {
- int x = (b[b.length - 1] & 0xff) + (a[aOff + b.length - 1] & 0xff) + 1;
-
- a[aOff + b.length - 1] = (byte)x;
- x >>>= 8;
-
- for (int i = b.length - 2; i >= 0; i--)
- {
- x += (b[i] & 0xff) + (a[aOff + i] & 0xff);
- a[aOff + i] = (byte)x;
- x >>>= 8;
- }
- }
-
- /**
- * generation of a derived key ala PKCS12 V1.0.
- */
- private byte[] generateDerivedKey(
- int idByte,
- int n)
- {
- byte[] D = new byte[v];
- byte[] dKey = new byte[n];
-
- for (int i = 0; i != D.length; i++)
- {
- D[i] = (byte)idByte;
- }
-
- byte[] S;
-
- if ((salt != null) && (salt.length != 0))
- {
- S = new byte[v * ((salt.length + v - 1) / v)];
-
- for (int i = 0; i != S.length; i++)
- {
- S[i] = salt[i % salt.length];
- }
- }
- else
- {
- S = new byte[0];
- }
-
- byte[] P;
-
- if ((password != null) && (password.length != 0))
- {
- P = new byte[v * ((password.length + v - 1) / v)];
-
- for (int i = 0; i != P.length; i++)
- {
- P[i] = password[i % password.length];
- }
- }
- else
- {
- P = new byte[0];
- }
-
- byte[] I = new byte[S.length + P.length];
-
- System.arraycopy(S, 0, I, 0, S.length);
- System.arraycopy(P, 0, I, S.length, P.length);
-
- byte[] B = new byte[v];
- int c = (n + u - 1) / u;
- byte[] A = new byte[u];
-
- for (int i = 1; i <= c; i++)
- {
- digest.update(D, 0, D.length);
- digest.update(I, 0, I.length);
- digest.doFinal(A, 0);
- for (int j = 1; j < iterationCount; j++)
- {
- digest.update(A, 0, A.length);
- digest.doFinal(A, 0);
- }
-
- for (int j = 0; j != B.length; j++)
- {
- B[j] = A[j % A.length];
- }
-
- for (int j = 0; j != I.length / v; j++)
- {
- adjust(I, j * v, B);
- }
-
- if (i == c)
- {
- System.arraycopy(A, 0, dKey, (i - 1) * u, dKey.length - ((i - 1) * u));
- }
- else
- {
- System.arraycopy(A, 0, dKey, (i - 1) * u, A.length);
- }
- }
-
- return dKey;
- }
-
- /**
- * Generate a key parameter derived from the password, salt, and iteration
- * count we are currently initialised with.
- *
- * @param keySize the size of the key we want (in bits)
- * @return a KeyParameter object.
- */
- public CipherParameters generateDerivedParameters(
- int keySize)
- {
- keySize = keySize / 8;
-
- byte[] dKey = generateDerivedKey(KEY_MATERIAL, keySize);
-
- return new KeyParameter(dKey, 0, keySize);
- }
-
- /**
- * Generate a key with initialisation vector parameter derived from
- * the password, salt, and iteration count we are currently initialised
- * with.
- *
- * @param keySize the size of the key we want (in bits)
- * @param ivSize the size of the iv we want (in bits)
- * @return a ParametersWithIV object.
- */
- public CipherParameters generateDerivedParameters(
- int keySize,
- int ivSize)
- {
- keySize = keySize / 8;
- ivSize = ivSize / 8;
-
- byte[] dKey = generateDerivedKey(KEY_MATERIAL, keySize);
-
- byte[] iv = generateDerivedKey(IV_MATERIAL, ivSize);
-
- return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), iv, 0, ivSize);
- }
-
- /**
- * Generate a key parameter for use with a MAC derived from the password,
- * salt, and iteration count we are currently initialised with.
- *
- * @param keySize the size of the key we want (in bits)
- * @return a KeyParameter object.
- */
- public CipherParameters generateDerivedMacParameters(
- int keySize)
- {
- keySize = keySize / 8;
-
- byte[] dKey = generateDerivedKey(MAC_MATERIAL, keySize);
-
- return new KeyParameter(dKey, 0, keySize);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/PKCS5S1ParametersGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/PKCS5S1ParametersGenerator.java
deleted file mode 100644
index 1c62eccc..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/PKCS5S1ParametersGenerator.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.PBEParametersGenerator;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-/**
- * Generator for PBE derived keys and ivs as defined by PKCS 5 V2.0 Scheme 1.
- * Note this generator is limited to the size of the hash produced by the
- * digest used to drive it.
- * <p>
- * The document this implementation is based on can be found at
- * <a href=http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html>
- * RSA's PKCS5 Page</a>
- */
-public class PKCS5S1ParametersGenerator
- extends PBEParametersGenerator
-{
- private Digest digest;
-
- /**
- * Construct a PKCS 5 Scheme 1 Parameters generator.
- *
- * @param digest the digest to be used as the source of derived keys.
- */
- public PKCS5S1ParametersGenerator(
- Digest digest)
- {
- this.digest = digest;
- }
-
- /**
- * the derived key function, the ith hash of the password and the salt.
- */
- private byte[] generateDerivedKey()
- {
- byte[] digestBytes = new byte[digest.getDigestSize()];
-
- digest.update(password, 0, password.length);
- digest.update(salt, 0, salt.length);
-
- digest.doFinal(digestBytes, 0);
- for (int i = 1; i < iterationCount; i++)
- {
- digest.update(digestBytes, 0, digestBytes.length);
- digest.doFinal(digestBytes, 0);
- }
-
- return digestBytes;
- }
-
- /**
- * Generate a key parameter derived from the password, salt, and iteration
- * count we are currently initialised with.
- *
- * @param keySize the size of the key we want (in bits)
- * @return a KeyParameter object.
- * @exception IllegalArgumentException if the key length larger than the base hash size.
- */
- public CipherParameters generateDerivedParameters(
- int keySize)
- {
- keySize = keySize / 8;
-
- if (keySize > digest.getDigestSize())
- {
- throw new IllegalArgumentException(
- "Can't generate a derived key " + keySize + " bytes long.");
- }
-
- byte[] dKey = generateDerivedKey();
-
- return new KeyParameter(dKey, 0, keySize);
- }
-
- /**
- * Generate a key with initialisation vector parameter derived from
- * the password, salt, and iteration count we are currently initialised
- * with.
- *
- * @param keySize the size of the key we want (in bits)
- * @param ivSize the size of the iv we want (in bits)
- * @return a ParametersWithIV object.
- * @exception IllegalArgumentException if keySize + ivSize is larger than the base hash size.
- */
- public CipherParameters generateDerivedParameters(
- int keySize,
- int ivSize)
- {
- keySize = keySize / 8;
- ivSize = ivSize / 8;
-
- if ((keySize + ivSize) > digest.getDigestSize())
- {
- throw new IllegalArgumentException(
- "Can't generate a derived key " + (keySize + ivSize) + " bytes long.");
- }
-
- byte[] dKey = generateDerivedKey();
-
- return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
- }
-
- /**
- * Generate a key parameter for use with a MAC derived from the password,
- * salt, and iteration count we are currently initialised with.
- *
- * @param keySize the size of the key we want (in bits)
- * @return a KeyParameter object.
- * @exception IllegalArgumentException if the key length larger than the base hash size.
- */
- public CipherParameters generateDerivedMacParameters(
- int keySize)
- {
- return generateDerivedParameters(keySize);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java
deleted file mode 100644
index 0954d481..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java
+++ /dev/null
@@ -1,153 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.PBEParametersGenerator;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.macs.HMac;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-/**
- * Generator for PBE derived keys and ivs as defined by PKCS 5 V2.0 Scheme 2.
- * This generator uses a SHA-1 HMac as the calculation function.
- * <p>
- * The document this implementation is based on can be found at
- * <a href=http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html>
- * RSA's PKCS5 Page</a>
- */
-public class PKCS5S2ParametersGenerator
- extends PBEParametersGenerator
-{
- private Mac hMac;
- private byte[] state;
-
- /**
- * construct a PKCS5 Scheme 2 Parameters generator.
- */
- public PKCS5S2ParametersGenerator()
- {
- this(new SHA1Digest());
- }
-
- public PKCS5S2ParametersGenerator(Digest digest)
- {
- hMac = new HMac(digest);
- state = new byte[hMac.getMacSize()];
- }
-
- private void F(
- byte[] S,
- int c,
- byte[] iBuf,
- byte[] out,
- int outOff)
- {
- if (c == 0)
- {
- throw new IllegalArgumentException("iteration count must be at least 1.");
- }
-
- if (S != null)
- {
- hMac.update(S, 0, S.length);
- }
-
- hMac.update(iBuf, 0, iBuf.length);
- 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);
- hMac.doFinal(state, 0);
-
- for (int j = 0; j != state.length; j++)
- {
- out[outOff + j] ^= state[j];
- }
- }
- }
-
- private byte[] generateDerivedKey(
- int dkLen)
- {
- int hLen = hMac.getMacSize();
- int l = (dkLen + hLen - 1) / hLen;
- byte[] iBuf = new byte[4];
- byte[] outBytes = new byte[l * hLen];
- int outPos = 0;
-
- CipherParameters param = new KeyParameter(password);
-
- hMac.init(param);
-
- for (int i = 1; i <= l; i++)
- {
- // Increment the value in 'iBuf'
- int pos = 3;
- while (++iBuf[pos] == 0)
- {
- --pos;
- }
-
- F(salt, iterationCount, iBuf, outBytes, outPos);
- outPos += hLen;
- }
-
- return outBytes;
- }
-
- /**
- * Generate a key parameter derived from the password, salt, and iteration
- * count we are currently initialised with.
- *
- * @param keySize the size of the key we want (in bits)
- * @return a KeyParameter object.
- */
- public CipherParameters generateDerivedParameters(
- int keySize)
- {
- keySize = keySize / 8;
-
- byte[] dKey = generateDerivedKey(keySize);
-
- return new KeyParameter(dKey, 0, keySize);
- }
-
- /**
- * Generate a key with initialisation vector parameter derived from
- * the password, salt, and iteration count we are currently initialised
- * with.
- *
- * @param keySize the size of the key we want (in bits)
- * @param ivSize the size of the iv we want (in bits)
- * @return a ParametersWithIV object.
- */
- public CipherParameters generateDerivedParameters(
- int keySize,
- int ivSize)
- {
- keySize = keySize / 8;
- ivSize = ivSize / 8;
-
- byte[] dKey = generateDerivedKey(keySize + ivSize);
-
- return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
- }
-
- /**
- * Generate a key parameter for use with a MAC derived from the password,
- * salt, and iteration count we are currently initialised with.
- *
- * @param keySize the size of the key we want (in bits)
- * @return a KeyParameter object.
- */
- public CipherParameters generateDerivedMacParameters(
- int keySize)
- {
- return generateDerivedParameters(keySize);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/Poly1305KeyGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/Poly1305KeyGenerator.java
deleted file mode 100644
index 59eee39e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/Poly1305KeyGenerator.java
+++ /dev/null
@@ -1,117 +0,0 @@
-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 key 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/core/src/main/java/org/bouncycastle/crypto/generators/RSABlindingFactorGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/RSABlindingFactorGenerator.java
deleted file mode 100644
index add67143..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/RSABlindingFactorGenerator.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-/**
- * Generate a random factor suitable for use with RSA blind signatures
- * as outlined in Chaum's blinding and unblinding as outlined in
- * "Handbook of Applied Cryptography", page 475.
- */
-public class RSABlindingFactorGenerator
-{
- private static BigInteger ZERO = BigInteger.valueOf(0);
- private static BigInteger ONE = BigInteger.valueOf(1);
-
- private RSAKeyParameters key;
- private SecureRandom random;
-
- /**
- * Initialise the factor generator
- *
- * @param param the necessary RSA key parameters.
- */
- public void init(
- CipherParameters param)
- {
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- key = (RSAKeyParameters)rParam.getParameters();
- random = rParam.getRandom();
- }
- else
- {
- key = (RSAKeyParameters)param;
- random = new SecureRandom();
- }
-
- if (key instanceof RSAPrivateCrtKeyParameters)
- {
- throw new IllegalArgumentException("generator requires RSA public key");
- }
- }
-
- /**
- * Generate a suitable blind factor for the public key the generator was initialised with.
- *
- * @return a random blind factor
- */
- public BigInteger generateBlindingFactor()
- {
- if (key == null)
- {
- throw new IllegalStateException("generator not initialised");
- }
-
- BigInteger m = key.getModulus();
- int length = m.bitLength() - 1; // must be less than m.bitLength()
- BigInteger factor;
- BigInteger gcd;
-
- do
- {
- factor = new BigInteger(length, random);
- gcd = factor.gcd(m);
- }
- while (factor.equals(ZERO) || factor.equals(ONE) || !gcd.equals(ONE));
-
- return factor;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java b/core/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java
deleted file mode 100644
index 928c6a6e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java
+++ /dev/null
@@ -1,153 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
-import org.bouncycastle.math.ec.WNafUtil;
-
-import java.math.BigInteger;
-
-/**
- * an RSA key pair generator.
- */
-public class RSAKeyPairGenerator
- implements AsymmetricCipherKeyPairGenerator
-{
- private static final BigInteger ONE = BigInteger.valueOf(1);
-
- private RSAKeyGenerationParameters param;
-
- public void init(KeyGenerationParameters param)
- {
- this.param = (RSAKeyGenerationParameters)param;
- }
-
- public AsymmetricCipherKeyPair generateKeyPair()
- {
- BigInteger p, q, n, d, e, pSub1, qSub1, phi;
-
- //
- // p and q values should have a length of half the strength in bits
- //
- int strength = param.getStrength();
- int qBitlength = strength >>> 1;
- int pBitlength = strength - qBitlength;
- int mindiffbits = strength / 3;
- int minWeight = strength >>> 2;
-
- e = param.getPublicExponent();
-
- // TODO Consider generating safe primes for p, q (see DHParametersHelper.generateSafePrimes)
- // (then p-1 and q-1 will not consist of only small factors - see "Pollard's algorithm")
-
- p = chooseRandomPrime(pBitlength, e);
-
- //
- // generate a modulus of the required length
- //
- for (;;)
- {
- q = chooseRandomPrime(qBitlength, e);
-
- // p and q should not be too close together (or equal!)
- BigInteger diff = q.subtract(p).abs();
- if (diff.bitLength() < mindiffbits)
- {
- continue;
- }
-
- //
- // calculate the modulus
- //
- n = p.multiply(q);
-
- if (n.bitLength() != strength)
- {
- //
- // if we get here our primes aren't big enough, make the largest
- // of the two p and try again
- //
- p = p.max(q);
- continue;
- }
-
- /*
- * Require a minimum weight of the NAF representation, since low-weight composites may
- * be weak against a version of the number-field-sieve for factoring.
- *
- * See "The number field sieve for integers of low weight", Oliver Schirokauer.
- */
- if (WNafUtil.getNafWeight(n) < minWeight)
- {
- p = chooseRandomPrime(pBitlength, e);
- continue;
- }
-
- break;
- }
-
- if (p.compareTo(q) < 0)
- {
- phi = p;
- p = q;
- q = phi;
- }
-
- pSub1 = p.subtract(ONE);
- qSub1 = q.subtract(ONE);
- phi = pSub1.multiply(qSub1);
-
- //
- // calculate the private exponent
- //
- d = e.modInverse(phi);
-
- //
- // calculate the CRT factors
- //
- BigInteger dP, dQ, qInv;
-
- dP = d.remainder(pSub1);
- dQ = d.remainder(qSub1);
- qInv = q.modInverse(p);
-
- return new AsymmetricCipherKeyPair(
- new RSAKeyParameters(false, n, e),
- new RSAPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv));
- }
-
- /**
- * Choose a random prime value for use with RSA
- *
- * @param bitlength the bit-length of the returned prime
- * @param e the RSA public exponent
- * @return a prime p, with (p-1) relatively prime to e
- */
- protected BigInteger chooseRandomPrime(int bitlength, BigInteger e)
- {
- for (;;)
- {
- BigInteger p = new BigInteger(bitlength, 1, param.getRandom());
-
- if (p.mod(e).equals(ONE))
- {
- continue;
- }
-
- if (!p.isProbablePrime(param.getCertainty()))
- {
- continue;
- }
-
- if (!e.gcd(p.subtract(ONE)).equals(ONE))
- {
- continue;
- }
-
- return p;
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/generators/SCrypt.java b/core/src/main/java/org/bouncycastle/crypto/generators/SCrypt.java
deleted file mode 100644
index 0b3dc147..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/generators/SCrypt.java
+++ /dev/null
@@ -1,198 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.PBEParametersGenerator;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.engines.Salsa20Engine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Pack;
-
-/**
- * Implementation of the scrypt a password-based key derivation function.
- * <p>
- * Scrypt was created by Colin Percival and is specified in <a
- * href="http://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01">draft-josefsson-scrypt-kd</a>
- *
- */
-public class SCrypt
-{
- /**
- * Generate a key using the scrypt key derivation function.
- *
- * @param P the bytes of the pass phrase.
- * @param S the salt to use for this invocation.
- * @param N CPU/Memory cost parameter. Must be larger than 1, a power of 2 and less than
- * <code>2^(128 * r / 8)</code>.
- * @param r the block size, must be >= 1.
- * @param p Parallelization parameter. Must be a positive integer less than or equal to
- * <code>Integer.MAX_VALUE / (128 * r * 8)</code>.
- *
- * @param dkLen the length of the key to generate.
- * @return the generated key.
- */
- public static byte[] generate(byte[] P, byte[] S, int N, int r, int p, int dkLen)
- {
- if (P== null)
- {
- throw new IllegalArgumentException("Passphrase P must be provided.");
- }
- if (S == null)
- {
- throw new IllegalArgumentException("Salt S must be provided.");
- }
- if (N <= 1)
- {
- throw new IllegalArgumentException("Cost parameter N must be > 1.");
- }
- // Only value of r that cost (as an int) could be exceeded for is 1
- if (r == 1 && N > 65536)
- {
- throw new IllegalArgumentException("Cost parameter N must be > 1 and < 65536.");
- }
- if (r < 1)
- {
- throw new IllegalArgumentException("Block size r must be >= 1.");
- }
- int maxParallel = Integer.MAX_VALUE / (128 * r * 8);
- if (p < 1 || p > maxParallel)
- {
- throw new IllegalArgumentException("Parallelisation parameter p must be >= 1 and <= " + maxParallel
- + " (based on block size r of " + r + ")");
- }
- if (dkLen < 1)
- {
- throw new IllegalArgumentException("Generated key length dkLen must be >= 1.");
- }
- return MFcrypt(P, S, N, r, p, dkLen);
- }
-
- private static byte[] MFcrypt(byte[] P, byte[] S, int N, int r, int p, int dkLen)
- {
- int MFLenBytes = r * 128;
- byte[] bytes = SingleIterationPBKDF2(P, S, p * MFLenBytes);
-
- int[] B = null;
-
- try
- {
- int BLen = bytes.length >>> 2;
- B = new int[BLen];
-
- Pack.littleEndianToInt(bytes, 0, B);
-
- int MFLenWords = MFLenBytes >>> 2;
- for (int BOff = 0; BOff < BLen; BOff += MFLenWords)
- {
- // TODO These can be done in parallel threads
- SMix(B, BOff, N, r);
- }
-
- Pack.intToLittleEndian(B, bytes, 0);
-
- return SingleIterationPBKDF2(P, bytes, dkLen);
- }
- finally
- {
- Clear(bytes);
- Clear(B);
- }
- }
-
- private static byte[] SingleIterationPBKDF2(byte[] P, byte[] S, int dkLen)
- {
- PBEParametersGenerator pGen = new PKCS5S2ParametersGenerator(new SHA256Digest());
- pGen.init(P, S, 1);
- KeyParameter key = (KeyParameter) pGen.generateDerivedMacParameters(dkLen * 8);
- return key.getKey();
- }
-
- private static void SMix(int[] B, int BOff, int N, int r)
- {
- int BCount = r * 32;
-
- int[] blockX1 = new int[16];
- int[] blockX2 = new int[16];
- int[] blockY = new int[BCount];
-
- int[] X = new int[BCount];
- int[][] V = new int[N][];
-
- try
- {
- System.arraycopy(B, BOff, X, 0, BCount);
-
- for (int i = 0; i < N; ++i)
- {
- V[i] = Arrays.clone(X);
- BlockMix(X, blockX1, blockX2, blockY, r);
- }
-
- int mask = N - 1;
- for (int i = 0; i < N; ++i)
- {
- int j = X[BCount - 16] & mask;
- Xor(X, V[j], 0, X);
- BlockMix(X, blockX1, blockX2, blockY, r);
- }
-
- System.arraycopy(X, 0, B, BOff, BCount);
- }
- finally
- {
- ClearAll(V);
- ClearAll(new int[][]{ X, blockX1, blockX2, blockY });
- }
- }
-
- private static void BlockMix(int[] B, int[] X1, int[] X2, int[] Y, int r)
- {
- System.arraycopy(B, B.length - 16, X1, 0, 16);
-
- int BOff = 0, YOff = 0, halfLen = B.length >>> 1;
-
- for (int i = 2 * r; i > 0; --i)
- {
- Xor(X1, B, BOff, X2);
-
- Salsa20Engine.salsaCore(8, X2, X1);
- System.arraycopy(X1, 0, Y, YOff, 16);
-
- YOff = halfLen + BOff - YOff;
- BOff += 16;
- }
-
- System.arraycopy(Y, 0, B, 0, Y.length);
- }
-
- private static void Xor(int[] a, int[] b, int bOff, int[] output)
- {
- for (int i = output.length - 1; i >= 0; --i)
- {
- output[i] = a[i] ^ b[bOff + i];
- }
- }
-
- private static void Clear(byte[] array)
- {
- if (array != null)
- {
- Arrays.fill(array, (byte)0);
- }
- }
-
- private static void Clear(int[] array)
- {
- if (array != null)
- {
- Arrays.fill(array, 0);
- }
- }
-
- private static void ClearAll(int[][] arrays)
- {
- for (int i = 0; i < arrays.length; ++i)
- {
- Clear(arrays[i]);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/io/CipherIOException.java b/core/src/main/java/org/bouncycastle/crypto/io/CipherIOException.java
deleted file mode 100644
index beeb60bc..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/io/CipherIOException.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.bouncycastle.crypto.io;
-
-import java.io.IOException;
-
-/**
- * {@link IOException} wrapper around an exception indicating a problem with the use of a cipher.
- */
-public class CipherIOException
- extends IOException
-{
- private static final long serialVersionUID = 1L;
-
- private final Throwable cause;
-
- public CipherIOException(String message, Throwable cause)
- {
- super(message);
-
- this.cause = cause;
- }
-
- public Throwable getCause()
- {
- return cause;
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/crypto/io/CipherInputStream.java b/core/src/main/java/org/bouncycastle/crypto/io/CipherInputStream.java
deleted file mode 100644
index b06d1f53..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/io/CipherInputStream.java
+++ /dev/null
@@ -1,477 +0,0 @@
-package org.bouncycastle.crypto.io;
-
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.bouncycastle.crypto.BufferedBlockCipher;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.SkippingCipher;
-import org.bouncycastle.crypto.StreamCipher;
-import org.bouncycastle.crypto.modes.AEADBlockCipher;
-import org.bouncycastle.util.Arrays;
-
-/**
- * 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.
- */
-public class CipherInputStream
- extends FilterInputStream
-{
- private static final int INPUT_BUF_SIZE = 2048;
-
- private SkippingCipher skippingCipher;
- private byte[] inBuf;
-
- private BufferedBlockCipher bufferedBlockCipher;
- private StreamCipher streamCipher;
- private AEADBlockCipher aeadBlockCipher;
-
- private byte[] buf;
- private byte[] markBuf;
-
-
- private int bufOff;
- private int maxBuf;
- private boolean finalized;
- private long markPosition;
- private int markBufOff;
-
- /**
- * Constructs a CipherInputStream from an InputStream and a
- * BufferedBlockCipher.
- */
- public CipherInputStream(
- InputStream is,
- BufferedBlockCipher cipher)
- {
- this(is, cipher, INPUT_BUF_SIZE);
- }
-
- /**
- * Constructs a CipherInputStream from an InputStream and a StreamCipher.
- */
- public CipherInputStream(
- InputStream is,
- StreamCipher cipher)
- {
- this(is, cipher, INPUT_BUF_SIZE);
- }
-
- /**
- * Constructs a CipherInputStream from an InputStream and an AEADBlockCipher.
- */
- public CipherInputStream(
- InputStream is,
- AEADBlockCipher cipher)
- {
- this(is, cipher, INPUT_BUF_SIZE);
- }
-
- /**
- * Constructs a CipherInputStream from an InputStream, a
- * BufferedBlockCipher, and a specified internal buffer size.
- */
- public CipherInputStream(
- InputStream is,
- BufferedBlockCipher cipher,
- int bufSize)
- {
- super(is);
-
- this.bufferedBlockCipher = cipher;
- this.inBuf = new byte[bufSize];
- this.skippingCipher = (cipher instanceof SkippingCipher) ? (SkippingCipher)cipher : null;
- }
-
- /**
- * Constructs a CipherInputStream from an InputStream, a StreamCipher, and a specified internal buffer size.
- */
- public CipherInputStream(
- InputStream is,
- StreamCipher cipher,
- int bufSize)
- {
- super(is);
-
- this.streamCipher = cipher;
- this.inBuf = new byte[bufSize];
- this.skippingCipher = (cipher instanceof SkippingCipher) ? (SkippingCipher)cipher : null;
- }
-
- /**
- * Constructs a CipherInputStream from an InputStream, an AEADBlockCipher, and a specified internal buffer size.
- */
- public CipherInputStream(
- InputStream is,
- AEADBlockCipher cipher,
- int bufSize)
- {
- super(is);
-
- this.aeadBlockCipher = cipher;
- this.inBuf = new byte[bufSize];
- this.skippingCipher = (cipher instanceof SkippingCipher) ? (SkippingCipher)cipher : null;
- }
-
- /**
- * 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(inBuf);
- if (read == -1)
- {
- finaliseCipher();
- if (maxBuf == 0)
- {
- return -1;
- }
- return maxBuf;
- }
-
- try
- {
- ensureCapacity(read, false);
- if (bufferedBlockCipher != null)
- {
- maxBuf = bufferedBlockCipher.processBytes(inBuf, 0, read, buf, 0);
- }
- else if (aeadBlockCipher != null)
- {
- maxBuf = aeadBlockCipher.processBytes(inBuf, 0, read, buf, 0);
- }
- else
- {
- streamCipher.processBytes(inBuf, 0, read, buf, 0);
- maxBuf = read;
- }
- }
- catch (Exception e)
- {
- throw new CipherIOException("Error processing stream ", e);
- }
- }
- return maxBuf;
- }
-
- private void finaliseCipher()
- throws IOException
- {
- try
- {
- finalized = true;
- ensureCapacity(0, true);
- if (bufferedBlockCipher != null)
- {
- maxBuf = bufferedBlockCipher.doFinal(buf, 0);
- }
- else if (aeadBlockCipher != null)
- {
- maxBuf = aeadBlockCipher.doFinal(buf, 0);
- }
- else
- {
- maxBuf = 0; // a stream cipher
- }
- }
- 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.
- * </p>
- * @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>b.length</code> bytes in the provided array.
- * <p>
- * If the underlying stream is exhausted by this call, the cipher will be finalised.
- * </p>
- * @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
- {
- 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.
- * </p>
- * @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;
- }
-
- if (skippingCipher != null)
- {
- int avail = available();
- if (n <= avail)
- {
- bufOff += n;
-
- return n;
- }
-
- bufOff = maxBuf;
-
- long skip = in.skip(n - avail);
-
- long cSkip = skippingCipher.skip(skip);
-
- if (skip != cSkip)
- {
- throw new IOException("Unable to skip cipher " + skip + " bytes.");
- }
-
- return skip + avail;
- }
- else
- {
- int skip = (int)Math.min(n, available());
- bufOff += skip;
-
- return skip;
- }
- }
-
- public int available()
- throws IOException
- {
- return maxBuf - bufOff;
- }
-
- /**
- * Ensure the cipher text buffer has space sufficient to accept an upcoming output.
- *
- * @param updateSize the size of the pending update.
- * @param finalOutput <code>true</code> iff this the cipher is to be finalised.
- */
- private void ensureCapacity(int updateSize, boolean finalOutput)
- {
- int bufLen = updateSize;
- if (finalOutput)
- {
- if (bufferedBlockCipher != null)
- {
- bufLen = bufferedBlockCipher.getOutputSize(updateSize);
- }
- else if (aeadBlockCipher != null)
- {
- bufLen = aeadBlockCipher.getOutputSize(updateSize);
- }
- }
- else
- {
- if (bufferedBlockCipher != null)
- {
- bufLen = bufferedBlockCipher.getUpdateOutputSize(updateSize);
- }
- else if (aeadBlockCipher != null)
- {
- bufLen = aeadBlockCipher.getUpdateOutputSize(updateSize);
- }
- }
-
- if ((buf == null) || (buf.length < bufLen))
- {
- buf = new byte[bufLen];
- }
- }
-
- /**
- * 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();
- }
- 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;
- markBufOff = 0;
- markPosition = 0;
- if (markBuf != null)
- {
- Arrays.fill(markBuf, (byte)0);
- markBuf = null;
- }
- if (buf != null)
- {
- Arrays.fill(buf, (byte)0);
- buf = null;
- }
- Arrays.fill(inBuf, (byte)0);
- }
-
- /**
- * Mark the current position.
- * <p>
- * This method only works if markSupported() returns true - which means the underlying stream supports marking, and the cipher passed
- * in to this stream's constructor is a SkippingCipher (so capable of being reset to an arbitrary point easily).
- * </p>
- * @param readlimit the maximum read ahead required before a reset() may be called.
- */
- public void mark(int readlimit)
- {
- in.mark(readlimit);
- if (skippingCipher != null)
- {
- markPosition = skippingCipher.getPosition();
- }
-
- if (buf != null)
- {
- markBuf = new byte[buf.length];
- System.arraycopy(buf, 0, markBuf, 0, buf.length);
- }
-
- markBufOff = bufOff;
- }
-
- /**
- * Reset to the last marked position, if supported.
- *
- * @throws IOException if marking not supported by the cipher used, or the underlying stream.
- */
- public void reset()
- throws IOException
- {
- if (skippingCipher == null)
- {
- throw new IOException("cipher must implement SkippingCipher to be used with reset()");
- }
-
- in.reset();
-
- skippingCipher.seekTo(markPosition);
-
- if (markBuf != null)
- {
- buf = markBuf;
- }
-
- bufOff = markBufOff;
- }
-
- /**
- * Return true if mark(readlimit) is supported. This will be true if the underlying stream supports marking and the
- * cipher used is a SkippingCipher,
- *
- * @return true if mark(readlimit) supported, false otherwise.
- */
- public boolean markSupported()
- {
- if (skippingCipher != null)
- {
- return in.markSupported();
- }
-
- return false;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/io/CipherOutputStream.java b/core/src/main/java/org/bouncycastle/crypto/io/CipherOutputStream.java
deleted file mode 100644
index 5d5f0d11..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/io/CipherOutputStream.java
+++ /dev/null
@@ -1,276 +0,0 @@
-package org.bouncycastle.crypto.io;
-
-import java.io.FilterOutputStream;
-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 final byte[] oneByte = new byte[1];
- private byte[] buf;
-
- /**
- * Constructs a CipherOutputStream from an OutputStream and a
- * BufferedBlockCipher.
- */
- public CipherOutputStream(
- OutputStream os,
- BufferedBlockCipher cipher)
- {
- super(os);
- this.bufferedBlockCipher = cipher;
- }
-
- /**
- * Constructs a CipherOutputStream from an OutputStream and a
- * BufferedBlockCipher.
- */
- public CipherOutputStream(
- OutputStream os,
- StreamCipher cipher)
- {
- super(os);
- this.streamCipher = cipher;
- }
-
- /**
- * 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>.
- * @throws java.io.IOException if an I/O error occurs.
- */
- public void write(
- int b)
- throws IOException
- {
- oneByte[0] = (byte)b;
-
- if (streamCipher != null)
- {
- out.write(streamCipher.returnByte((byte)b));
- }
- else
- {
- write(oneByte, 0, 1);
- }
- }
-
- /**
- * Writes <code>b.length</code> bytes from the specified byte array
- * to this output stream.
- * <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.
- * @throws java.io.IOException if an I/O error occurs.
- * @see #write(byte[], int, int)
- */
- public void write(
- byte[] b)
- throws IOException
- {
- write(b, 0, b.length);
- }
-
- /**
- * 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
- {
- ensureCapacity(len, false);
-
- if (bufferedBlockCipher != null)
- {
- int outLen = bufferedBlockCipher.processBytes(b, off, len, buf, 0);
-
- if (outLen != 0)
- {
- out.write(buf, 0, outLen);
- }
- }
- else if (aeadBlockCipher != null)
- {
- 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);
- }
- }
-
- /**
- * Ensure the ciphertext buffer has space sufficient to accept an upcoming output.
- *
- * @param updateSize the size of the pending update.
- * @param finalOutput <code>true</code> iff this the cipher is to be finalised.
- */
- private void ensureCapacity(int updateSize, boolean finalOutput)
- {
- int bufLen = updateSize;
- if (finalOutput)
- {
- if (bufferedBlockCipher != null)
- {
- bufLen = bufferedBlockCipher.getOutputSize(updateSize);
- }
- else if (aeadBlockCipher != null)
- {
- bufLen = aeadBlockCipher.getOutputSize(updateSize);
- }
- }
- else
- {
- if (bufferedBlockCipher != null)
- {
- bufLen = bufferedBlockCipher.getUpdateOutputSize(updateSize);
- }
- else if (aeadBlockCipher != null)
- {
- bufLen = aeadBlockCipher.getUpdateOutputSize(updateSize);
- }
- }
-
- 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>
- * 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
- {
- ensureCapacity(0, true);
- IOException error = null;
- try
- {
- if (bufferedBlockCipher != null)
- {
- int outLen = bufferedBlockCipher.doFinal(buf, 0);
-
- if (outLen != 0)
- {
- 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)
- {
- error = new CipherIOException("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/core/src/main/java/org/bouncycastle/crypto/io/DigestInputStream.java b/core/src/main/java/org/bouncycastle/crypto/io/DigestInputStream.java
deleted file mode 100644
index ef0b03e2..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/io/DigestInputStream.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.bouncycastle.crypto.io;
-
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.bouncycastle.crypto.Digest;
-
-public class DigestInputStream
- extends FilterInputStream
-{
- protected Digest digest;
-
- public DigestInputStream(
- InputStream stream,
- Digest digest)
- {
- super(stream);
- this.digest = digest;
- }
-
- public int read()
- throws IOException
- {
- int b = in.read();
-
- if (b >= 0)
- {
- digest.update((byte)b);
- }
- return b;
- }
-
- public int read(
- byte[] b,
- int off,
- int len)
- throws IOException
- {
- int n = in.read(b, off, len);
- if (n > 0)
- {
- digest.update(b, off, n);
- }
- return n;
- }
-
- public Digest getDigest()
- {
- return digest;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/io/DigestOutputStream.java b/core/src/main/java/org/bouncycastle/crypto/io/DigestOutputStream.java
deleted file mode 100644
index 23c7e539..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/io/DigestOutputStream.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.bouncycastle.crypto.io;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.bouncycastle.crypto.Digest;
-
-public class DigestOutputStream
- extends OutputStream
-{
- protected Digest digest;
-
- public DigestOutputStream(
- Digest Digest)
- {
- this.digest = Digest;
- }
-
- public void write(int b)
- throws IOException
- {
- digest.update((byte)b);
- }
-
- public void write(
- byte[] b,
- int off,
- int len)
- throws IOException
- {
- digest.update(b, off, len);
- }
-
- public byte[] getDigest()
- {
- byte[] res = new byte[digest.getDigestSize()];
-
- digest.doFinal(res, 0);
-
- return res;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/io/InvalidCipherTextIOException.java b/core/src/main/java/org/bouncycastle/crypto/io/InvalidCipherTextIOException.java
deleted file mode 100644
index 46561c67..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/io/InvalidCipherTextIOException.java
+++ /dev/null
@@ -1,19 +0,0 @@
-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 CipherIOException
-{
- private static final long serialVersionUID = 1L;
-
- public InvalidCipherTextIOException(String message, Throwable cause)
- {
- super(message, cause);
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/crypto/io/MacInputStream.java b/core/src/main/java/org/bouncycastle/crypto/io/MacInputStream.java
deleted file mode 100644
index b78548c6..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/io/MacInputStream.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.bouncycastle.crypto.io;
-
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.bouncycastle.crypto.Mac;
-
-public class MacInputStream
- extends FilterInputStream
-{
- protected Mac mac;
-
- public MacInputStream(
- InputStream stream,
- Mac mac)
- {
- super(stream);
- this.mac = mac;
- }
-
- public int read()
- throws IOException
- {
- int b = in.read();
-
- if (b >= 0)
- {
- mac.update((byte)b);
- }
- return b;
- }
-
- public int read(
- byte[] b,
- int off,
- int len)
- throws IOException
- {
- int n = in.read(b, off, len);
- if (n >= 0)
- {
- mac.update(b, off, n);
- }
- return n;
- }
-
- public Mac getMac()
- {
- return mac;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/io/MacOutputStream.java b/core/src/main/java/org/bouncycastle/crypto/io/MacOutputStream.java
deleted file mode 100644
index 0f0e7dbe..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/io/MacOutputStream.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.bouncycastle.crypto.io;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.bouncycastle.crypto.Mac;
-
-public class MacOutputStream
- extends OutputStream
-{
- protected Mac mac;
-
- public MacOutputStream(
- Mac mac)
- {
- this.mac = mac;
- }
-
- public void write(int b)
- throws IOException
- {
- mac.update((byte)b);
- }
-
- public void write(
- byte[] b,
- int off,
- int len)
- throws IOException
- {
- mac.update(b, off, len);
- }
-
- public byte[] getMac()
- {
- byte[] res = new byte[mac.getMacSize()];
-
- mac.doFinal(res, 0);
-
- return res;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/io/SignerInputStream.java b/core/src/main/java/org/bouncycastle/crypto/io/SignerInputStream.java
deleted file mode 100644
index 9583e4cf..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/io/SignerInputStream.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.bouncycastle.crypto.io;
-
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.bouncycastle.crypto.Signer;
-
-public class SignerInputStream
- extends FilterInputStream
-{
- protected Signer signer;
-
- public SignerInputStream(
- InputStream stream,
- Signer signer)
- {
- super(stream);
- this.signer = signer;
- }
-
- public int read()
- throws IOException
- {
- int b = in.read();
-
- if (b >= 0)
- {
- signer.update((byte)b);
- }
- return b;
- }
-
- public int read(
- byte[] b,
- int off,
- int len)
- throws IOException
- {
- int n = in.read(b, off, len);
- if (n > 0)
- {
- signer.update(b, off, n);
- }
- return n;
- }
-
- public Signer getSigner()
- {
- return signer;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/io/SignerOutputStream.java b/core/src/main/java/org/bouncycastle/crypto/io/SignerOutputStream.java
deleted file mode 100644
index 1c21b5dc..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/io/SignerOutputStream.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.bouncycastle.crypto.io;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.bouncycastle.crypto.Signer;
-
-public class SignerOutputStream
- extends OutputStream
-{
- protected Signer signer;
-
- public SignerOutputStream(
- Signer Signer)
- {
- this.signer = Signer;
- }
-
- public void write(int b)
- throws IOException
- {
- signer.update((byte)b);
- }
-
- public void write(
- byte[] b,
- int off,
- int len)
- throws IOException
- {
- signer.update(b, off, len);
- }
-
- public Signer getSigner()
- {
- return signer;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/kems/ECIESKeyEncapsulation.java b/core/src/main/java/org/bouncycastle/crypto/kems/ECIESKeyEncapsulation.java
deleted file mode 100755
index 517acfb1..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/kems/ECIESKeyEncapsulation.java
+++ /dev/null
@@ -1,244 +0,0 @@
-package org.bouncycastle.crypto.kems;
-
-import java.math.BigInteger;
-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.ECMultiplier;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.ec.FixedPointCombMultiplier;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.BigIntegers;
-
-/**
- * The ECIES Key Encapsulation Mechanism (ECIES-KEM) from ISO 18033-2.
- */
-public class ECIESKeyEncapsulation
- implements KeyEncapsulation
-{
- private static final BigInteger ONE = BigInteger.valueOf(1);
-
- private DerivationFunction kdf;
- private SecureRandom rnd;
- private ECKeyParameters key;
- private boolean CofactorMode;
- private boolean OldCofactorMode;
- private boolean SingleHashMode;
-
- /**
- * Set up the ECIES-KEM.
- *
- * @param kdf the key derivation function to be used.
- * @param rnd the random source for the session key.
- */
- public ECIESKeyEncapsulation(
- DerivationFunction kdf,
- SecureRandom rnd)
- {
- this.kdf = kdf;
- this.rnd = rnd;
- this.CofactorMode = false;
- this.OldCofactorMode = false;
- this.SingleHashMode = false;
- }
-
- /**
- * Set up the ECIES-KEM.
- *
- * @param kdf the key derivation function to be used.
- * @param rnd the random source for the session key.
- * @param cofactorMode true to use the new cofactor ECDH.
- * @param oldCofactorMode true to use the old cofactor ECDH.
- * @param singleHashMode true to use single hash mode.
- */
- public ECIESKeyEncapsulation(
- DerivationFunction kdf,
- SecureRandom rnd,
- boolean cofactorMode,
- boolean oldCofactorMode,
- boolean singleHashMode)
- {
- this.kdf = kdf;
- this.rnd = rnd;
-
- // If both cofactorMode and oldCofactorMode are set to true
- // then the implementation will use the new cofactor ECDH
- this.CofactorMode = cofactorMode;
- this.OldCofactorMode = oldCofactorMode;
- this.SingleHashMode = singleHashMode;
- }
-
- /**
- * Initialise the ECIES-KEM.
- *
- * @param key the recipient's public (for encryption) or private (for decryption) key.
- */
- public void init(CipherParameters key)
- throws IllegalArgumentException
- {
- if (!(key instanceof ECKeyParameters))
- {
- throw new IllegalArgumentException("EC key required");
- }
- else
- {
- this.key = (ECKeyParameters)key;
- }
- }
-
- /**
- * Generate and encapsulate a random session key.
- *
- * @param out the output buffer for the encapsulated key.
- * @param outOff the offset for the output buffer.
- * @param keyLen the length of the session key.
- * @return the random session key.
- */
- public CipherParameters encrypt(byte[] out, int outOff, int keyLen)
- throws IllegalArgumentException
- {
- if (!(key instanceof ECPublicKeyParameters))
- {
- throw new IllegalArgumentException("Public key required for encryption");
- }
-
- 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);
-
- // Compute the static-ephemeral key agreement
- BigInteger rPrime = CofactorMode ? r.multiply(h).mod(n) : r;
-
- ECMultiplier basePointMultiplier = createBasePointMultiplier();
-
- ECPoint[] ghTilde = new ECPoint[]{
- basePointMultiplier.multiply(ecParams.getG(), 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);
-
- // Encode the shared secret value
- byte[] PEH = hTilde.getAffineXCoord().getEncoded();
-
- // Initialise the KDF
- byte[] kdfInput = SingleHashMode ? Arrays.concatenate(C, PEH) : PEH;
- kdf.init(new KDFParameters(kdfInput, null));
-
- // Generate the secret key
- byte[] K = new byte[keyLen];
- kdf.generateBytes(K, 0, K.length);
-
- // Return the ciphertext
- return new KeyParameter(K);
- }
-
- /**
- * Generate and encapsulate a random session key.
- *
- * @param out the output buffer for the encapsulated key.
- * @param keyLen the length of the session key.
- * @return the random session key.
- */
- public CipherParameters encrypt(byte[] out, int keyLen)
- {
- return encrypt(out, 0, keyLen);
- }
-
- /**
- * Decrypt an encapsulated session key.
- *
- * @param in the input buffer for the encapsulated key.
- * @param inOff the offset for the input buffer.
- * @param inLen the length of the encapsulated key.
- * @param keyLen the length of the session key.
- * @return the session key.
- */
- public CipherParameters decrypt(byte[] in, int inOff, int inLen, int keyLen)
- throws IllegalArgumentException
- {
- if (!(key instanceof ECPrivateKeyParameters))
- {
- throw new IllegalArgumentException("Private key required for encryption");
- }
-
- 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);
-
- // NOTE: Decoded points are already normalized (i.e in affine form)
- ECPoint gTilde = curve.decodePoint(C);
-
- // Compute the static-ephemeral key agreement
- ECPoint gHat = gTilde;
- if ((CofactorMode) || (OldCofactorMode))
- {
- gHat = gHat.multiply(h);
- }
-
- BigInteger xHat = ecPrivKey.getD();
- if (CofactorMode)
- {
- xHat = xHat.multiply(h.modInverse(n)).mod(n);
- }
-
- ECPoint hTilde = gHat.multiply(xHat).normalize();
-
- // Encode the shared secret value
- byte[] PEH = hTilde.getAffineXCoord().getEncoded();
-
- // Initialise the KDF
- byte[] kdfInput = SingleHashMode ? Arrays.concatenate(C, PEH) : PEH;
- kdf.init(new KDFParameters(kdfInput, null));
-
- // Generate the secret key
- byte[] K = new byte[keyLen];
- kdf.generateBytes(K, 0, K.length);
-
- return new KeyParameter(K);
- }
-
- /**
- * Decrypt an encapsulated session key.
- *
- * @param in the input buffer for the encapsulated key.
- * @param keyLen the length of the session key.
- * @return the session key.
- */
- public CipherParameters decrypt(byte[] in, int keyLen)
- {
- return decrypt(in, 0, in.length, keyLen);
- }
-
- protected ECMultiplier createBasePointMultiplier()
- {
- return new FixedPointCombMultiplier();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/kems/RSAKeyEncapsulation.java b/core/src/main/java/org/bouncycastle/crypto/kems/RSAKeyEncapsulation.java
deleted file mode 100755
index 42fc2353..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/kems/RSAKeyEncapsulation.java
+++ /dev/null
@@ -1,155 +0,0 @@
-package org.bouncycastle.crypto.kems;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DerivationFunction;
-import org.bouncycastle.crypto.KeyEncapsulation;
-import org.bouncycastle.crypto.params.KDFParameters;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.util.BigIntegers;
-
-/**
- * The RSA Key Encapsulation Mechanism (RSA-KEM) from ISO 18033-2.
- */
-public class RSAKeyEncapsulation
- implements KeyEncapsulation
-{
- private static final BigInteger ZERO = BigInteger.valueOf(0);
- private static final BigInteger ONE = BigInteger.valueOf(1);
-
- private DerivationFunction kdf;
- private SecureRandom rnd;
- private RSAKeyParameters key;
-
- /**
- * Set up the RSA-KEM.
- *
- * @param kdf the key derivation function to be used.
- * @param rnd the random source for the session key.
- */
- public RSAKeyEncapsulation(
- DerivationFunction kdf,
- SecureRandom rnd)
- {
- this.kdf = kdf;
- this.rnd = rnd;
- }
-
- /**
- * Initialise the RSA-KEM.
- *
- * @param key the recipient's public (for encryption) or private (for decryption) key.
- */
- public void init(CipherParameters key)
- throws IllegalArgumentException
- {
- if (!(key instanceof RSAKeyParameters))
- {
- throw new IllegalArgumentException("RSA key required");
- }
-
- this.key = (RSAKeyParameters)key;
- }
-
- /**
- * Generate and encapsulate a random session key.
- *
- * @param out the output buffer for the encapsulated key.
- * @param outOff the offset for the output buffer.
- * @param keyLen the length of the random session key.
- * @return the random session key.
- */
- public CipherParameters encrypt(byte[] out, int outOff, int keyLen)
- throws IllegalArgumentException
- {
- if (key.isPrivate())
- {
- throw new IllegalArgumentException("Public key required for encryption");
- }
-
- BigInteger n = key.getModulus();
- BigInteger e = key.getExponent();
-
- // Generate the ephemeral random and encode it
- BigInteger r = BigIntegers.createRandomInRange(ZERO, n.subtract(ONE), rnd);
-
- // Encrypt the random and encode it
- BigInteger c = r.modPow(e, n);
- byte[] C = BigIntegers.asUnsignedByteArray((n.bitLength() + 7) / 8, c);
- System.arraycopy(C, 0, out, outOff, C.length);
-
- return generateKey(n, r, keyLen);
- }
-
- /**
- * Generate and encapsulate a random session key.
- *
- * @param out the output buffer for the encapsulated key.
- * @param keyLen the length of the random session key.
- * @return the random session key.
- */
- public CipherParameters encrypt(byte[] out, int keyLen)
- {
- return encrypt(out, 0, keyLen);
- }
-
- /**
- * Decrypt an encapsulated session key.
- *
- * @param in the input buffer for the encapsulated key.
- * @param inOff the offset for the input buffer.
- * @param inLen the length of the encapsulated key.
- * @param keyLen the length of the session key.
- * @return the session key.
- */
- public CipherParameters decrypt(byte[] in, int inOff, int inLen, int keyLen)
- throws IllegalArgumentException
- {
- if (!key.isPrivate())
- {
- throw new IllegalArgumentException("Private key required for decryption");
- }
-
- BigInteger n = key.getModulus();
- BigInteger d = key.getExponent();
-
- // Decode the input
- byte[] C = new byte[inLen];
- System.arraycopy(in, inOff, C, 0, C.length);
- BigInteger c = new BigInteger(1, C);
-
- // Decrypt the ephemeral random and encode it
- BigInteger r = c.modPow(d, n);
-
- return generateKey(n, r, keyLen);
- }
-
- /**
- * Decrypt an encapsulated session key.
- *
- * @param in the input buffer for the encapsulated key.
- * @param keyLen the length of the session key.
- * @return the session key.
- */
- public CipherParameters decrypt(byte[] in, int keyLen)
- {
- return decrypt(in, 0, in.length, keyLen);
- }
-
- protected KeyParameter generateKey(BigInteger n, BigInteger r, int keyLen)
- {
- byte[] R = BigIntegers.asUnsignedByteArray((n.bitLength() + 7) / 8, r);
-
- // Initialise the KDF
- kdf.init(new KDFParameters(R, null));
-
- // Generate the secret key
- byte[] K = new byte[keyLen];
- kdf.generateBytes(K, 0, K.length);
-
- return new KeyParameter(K);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/macs/BlockCipherMac.java b/core/src/main/java/org/bouncycastle/crypto/macs/BlockCipherMac.java
deleted file mode 100644
index 6de39a85..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/macs/BlockCipherMac.java
+++ /dev/null
@@ -1,174 +0,0 @@
-package org.bouncycastle.crypto.macs;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.modes.CBCBlockCipher;
-
-public class BlockCipherMac
- implements Mac
-{
- private byte[] mac;
-
- private byte[] buf;
- private int bufOff;
- private BlockCipher cipher;
-
- private int macSize;
-
- /**
- * create a standard MAC based on a block cipher. This will produce an
- * authentication code half the length of the block size of the cipher.
- *
- * @param cipher the cipher to be used as the basis of the MAC generation.
- * @deprecated use CBCBlockCipherMac
- */
- public BlockCipherMac(
- BlockCipher cipher)
- {
- this(cipher, (cipher.getBlockSize() * 8) / 2);
- }
-
- /**
- * create a standard MAC based on a block cipher with the size of the
- * MAC been given in bits.
- * <p>
- * Note: the size of the MAC must be at least 16 bits (FIPS Publication 113),
- * and in general should be less than the size of the block cipher as it reduces
- * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
- *
- * @param cipher the cipher to be used as the basis of the MAC generation.
- * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
- * @deprecated use CBCBlockCipherMac
- */
- public BlockCipherMac(
- BlockCipher cipher,
- int macSizeInBits)
- {
- if ((macSizeInBits % 8) != 0)
- {
- throw new IllegalArgumentException("MAC size must be multiple of 8");
- }
-
- this.cipher = new CBCBlockCipher(cipher);
- this.macSize = macSizeInBits / 8;
-
- mac = new byte[cipher.getBlockSize()];
-
- buf = new byte[cipher.getBlockSize()];
- bufOff = 0;
- }
-
- public String getAlgorithmName()
- {
- return cipher.getAlgorithmName();
- }
-
- public void init(
- CipherParameters params)
- {
- reset();
-
- cipher.init(true, params);
- }
-
- public int getMacSize()
- {
- return macSize;
- }
-
- public void update(
- byte in)
- {
- if (bufOff == buf.length)
- {
- cipher.processBlock(buf, 0, mac, 0);
- bufOff = 0;
- }
-
- buf[bufOff++] = in;
- }
-
- public void update(
- byte[] in,
- int inOff,
- int len)
- {
- if (len < 0)
- {
- throw new IllegalArgumentException("Can't have a negative input length!");
- }
-
- int blockSize = cipher.getBlockSize();
- int resultLen = 0;
- int gapLen = blockSize - bufOff;
-
- if (len > gapLen)
- {
- System.arraycopy(in, inOff, buf, bufOff, gapLen);
-
- resultLen += cipher.processBlock(buf, 0, mac, 0);
-
- bufOff = 0;
- len -= gapLen;
- inOff += gapLen;
-
- while (len > blockSize)
- {
- resultLen += cipher.processBlock(in, inOff, mac, 0);
-
- len -= blockSize;
- inOff += blockSize;
- }
- }
-
- System.arraycopy(in, inOff, buf, bufOff, len);
-
- bufOff += len;
- }
-
- public int doFinal(
- byte[] out,
- int outOff)
- {
- int blockSize = cipher.getBlockSize();
-
- //
- // pad with zeroes
- //
- while (bufOff < blockSize)
- {
- buf[bufOff] = 0;
- bufOff++;
- }
-
- cipher.processBlock(buf, 0, mac, 0);
-
- System.arraycopy(mac, 0, out, outOff, macSize);
-
- reset();
-
- return macSize;
- }
-
- /**
- * Reset the mac generator.
- */
- public void reset()
- {
- /*
- * clean the buffer.
- */
- for (int i = 0; i < buf.length; i++)
- {
- buf[i] = 0;
- }
-
- bufOff = 0;
-
- /*
- * reset the underlying cipher.
- */
- cipher.reset();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/macs/CBCBlockCipherMac.java b/core/src/main/java/org/bouncycastle/crypto/macs/CBCBlockCipherMac.java
deleted file mode 100644
index 9bf6cb0e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/macs/CBCBlockCipherMac.java
+++ /dev/null
@@ -1,229 +0,0 @@
-package org.bouncycastle.crypto.macs;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.modes.CBCBlockCipher;
-import org.bouncycastle.crypto.paddings.BlockCipherPadding;
-
-/**
- * standard CBC Block Cipher MAC - if no padding is specified the default of
- * pad of zeroes is used.
- */
-public class CBCBlockCipherMac
- implements Mac
-{
- private byte[] mac;
-
- private byte[] buf;
- private int bufOff;
- private BlockCipher cipher;
- private BlockCipherPadding padding;
-
- private int macSize;
-
- /**
- * create a standard MAC based on a CBC block cipher. This will produce an
- * authentication code half the length of the block size of the cipher.
- *
- * @param cipher the cipher to be used as the basis of the MAC generation.
- */
- public CBCBlockCipherMac(
- BlockCipher cipher)
- {
- this(cipher, (cipher.getBlockSize() * 8) / 2, null);
- }
-
- /**
- * create a standard MAC based on a CBC block cipher. This will produce an
- * authentication code half the length of the block size of the cipher.
- *
- * @param cipher the cipher to be used as the basis of the MAC generation.
- * @param padding the padding to be used to complete the last block.
- */
- public CBCBlockCipherMac(
- BlockCipher cipher,
- BlockCipherPadding padding)
- {
- this(cipher, (cipher.getBlockSize() * 8) / 2, padding);
- }
-
- /**
- * create a standard MAC based on a block cipher with the size of the
- * MAC been given in bits. This class uses CBC mode as the basis for the
- * MAC generation.
- * <p>
- * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
- * or 16 bits if being used as a data authenticator (FIPS Publication 113),
- * and in general should be less than the size of the block cipher as it reduces
- * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
- *
- * @param cipher the cipher to be used as the basis of the MAC generation.
- * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
- */
- public CBCBlockCipherMac(
- BlockCipher cipher,
- int macSizeInBits)
- {
- this(cipher, macSizeInBits, null);
- }
-
- /**
- * create a standard MAC based on a block cipher with the size of the
- * MAC been given in bits. This class uses CBC mode as the basis for the
- * MAC generation.
- * <p>
- * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
- * or 16 bits if being used as a data authenticator (FIPS Publication 113),
- * and in general should be less than the size of the block cipher as it reduces
- * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
- *
- * @param cipher the cipher to be used as the basis of the MAC generation.
- * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
- * @param padding the padding to be used to complete the last block.
- */
- public CBCBlockCipherMac(
- BlockCipher cipher,
- int macSizeInBits,
- BlockCipherPadding padding)
- {
- if ((macSizeInBits % 8) != 0)
- {
- throw new IllegalArgumentException("MAC size must be multiple of 8");
- }
-
- this.cipher = new CBCBlockCipher(cipher);
- this.padding = padding;
- this.macSize = macSizeInBits / 8;
-
- mac = new byte[cipher.getBlockSize()];
-
- buf = new byte[cipher.getBlockSize()];
- bufOff = 0;
- }
-
- public String getAlgorithmName()
- {
- return cipher.getAlgorithmName();
- }
-
- public void init(
- CipherParameters params)
- {
- reset();
-
- cipher.init(true, params);
- }
-
- public int getMacSize()
- {
- return macSize;
- }
-
- public void update(
- byte in)
- {
- if (bufOff == buf.length)
- {
- cipher.processBlock(buf, 0, mac, 0);
- bufOff = 0;
- }
-
- buf[bufOff++] = in;
- }
-
- public void update(
- byte[] in,
- int inOff,
- int len)
- {
- if (len < 0)
- {
- throw new IllegalArgumentException("Can't have a negative input length!");
- }
-
- int blockSize = cipher.getBlockSize();
- int gapLen = blockSize - bufOff;
-
- if (len > gapLen)
- {
- System.arraycopy(in, inOff, buf, bufOff, gapLen);
-
- cipher.processBlock(buf, 0, mac, 0);
-
- bufOff = 0;
- len -= gapLen;
- inOff += gapLen;
-
- while (len > blockSize)
- {
- cipher.processBlock(in, inOff, mac, 0);
-
- len -= blockSize;
- inOff += blockSize;
- }
- }
-
- System.arraycopy(in, inOff, buf, bufOff, len);
-
- bufOff += len;
- }
-
- public int doFinal(
- byte[] out,
- int outOff)
- {
- int blockSize = cipher.getBlockSize();
-
- if (padding == null)
- {
- //
- // pad with zeroes
- //
- while (bufOff < blockSize)
- {
- buf[bufOff] = 0;
- bufOff++;
- }
- }
- else
- {
- if (bufOff == blockSize)
- {
- cipher.processBlock(buf, 0, mac, 0);
- bufOff = 0;
- }
-
- padding.addPadding(buf, bufOff);
- }
-
- cipher.processBlock(buf, 0, mac, 0);
-
- System.arraycopy(mac, 0, out, outOff, macSize);
-
- reset();
-
- return macSize;
- }
-
- /**
- * Reset the mac generator.
- */
- public void reset()
- {
- /*
- * clean the buffer.
- */
- for (int i = 0; i < buf.length; i++)
- {
- buf[i] = 0;
- }
-
- bufOff = 0;
-
- /*
- * reset the underlying cipher.
- */
- cipher.reset();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/macs/CFBBlockCipherMac.java b/core/src/main/java/org/bouncycastle/crypto/macs/CFBBlockCipherMac.java
deleted file mode 100644
index d7ad6126..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/macs/CFBBlockCipherMac.java
+++ /dev/null
@@ -1,388 +0,0 @@
-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.paddings.BlockCipherPadding;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-/**
- * implements a Cipher-FeedBack (CFB) mode on top of a simple cipher.
- */
-class MacCFBBlockCipher
-{
- private byte[] IV;
- private byte[] cfbV;
- private byte[] cfbOutV;
-
- private int blockSize;
- private BlockCipher cipher = null;
-
- /**
- * Basic constructor.
- *
- * @param cipher the block cipher to be used as the basis of the
- * feedback mode.
- * @param blockSize the block size in bits (note: a multiple of 8)
- */
- public MacCFBBlockCipher(
- BlockCipher cipher,
- int bitBlockSize)
- {
- this.cipher = cipher;
- this.blockSize = bitBlockSize / 8;
-
- this.IV = new byte[cipher.getBlockSize()];
- this.cfbV = new byte[cipher.getBlockSize()];
- this.cfbOutV = new byte[cipher.getBlockSize()];
- }
-
- /**
- * Initialise the cipher and, possibly, the initialisation vector (IV).
- * If an IV isn't passed as part of the parameter, the IV will be all zeros.
- * An IV which is too short is handled in FIPS compliant fashion.
- *
- * @param param the key and other data required by the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- CipherParameters params)
- throws IllegalArgumentException
- {
- if (params instanceof ParametersWithIV)
- {
- ParametersWithIV ivParam = (ParametersWithIV)params;
- byte[] iv = ivParam.getIV();
-
- if (iv.length < IV.length)
- {
- System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
- }
- else
- {
- System.arraycopy(iv, 0, IV, 0, IV.length);
- }
-
- reset();
-
- cipher.init(true, ivParam.getParameters());
- }
- else
- {
- reset();
-
- cipher.init(true, params);
- }
- }
-
- /**
- * return the algorithm name and mode.
- *
- * @return the name of the underlying algorithm followed by "/CFB"
- * and the block size in bits.
- */
- public String getAlgorithmName()
- {
- return cipher.getAlgorithmName() + "/CFB" + (blockSize * 8);
- }
-
- /**
- * return the block size we are operating at.
- *
- * @return the block size we are operating at (in bytes).
- */
- public int getBlockSize()
- {
- return blockSize;
- }
-
- /**
- * Process one block of input from the array in and write it to
- * the out array.
- *
- * @param in the array containing the input data.
- * @param inOff offset into the in array the data starts at.
- * @param out the array the output data will be copied into.
- * @param outOff the offset into the out array the output will start at.
- * @exception DataLengthException if there isn't enough data in in, or
- * space in out.
- * @exception IllegalStateException if the cipher isn't initialised.
- * @return the number of bytes processed and produced.
- */
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- throws DataLengthException, IllegalStateException
- {
- if ((inOff + blockSize) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + blockSize) > out.length)
- {
- throw new DataLengthException("output buffer too short");
- }
-
- cipher.processBlock(cfbV, 0, cfbOutV, 0);
-
- //
- // XOR the cfbV with the plaintext producing the cipher text
- //
- for (int i = 0; i < blockSize; i++)
- {
- out[outOff + i] = (byte)(cfbOutV[i] ^ in[inOff + i]);
- }
-
- //
- // change over the input block.
- //
- System.arraycopy(cfbV, blockSize, cfbV, 0, cfbV.length - blockSize);
- System.arraycopy(out, outOff, cfbV, cfbV.length - blockSize, blockSize);
-
- return blockSize;
- }
-
- /**
- * reset the chaining vector back to the IV and reset the underlying
- * cipher.
- */
- public void reset()
- {
- System.arraycopy(IV, 0, cfbV, 0, IV.length);
-
- cipher.reset();
- }
-
- void getMacBlock(
- byte[] mac)
- {
- cipher.processBlock(cfbV, 0, mac, 0);
- }
-}
-
-public class CFBBlockCipherMac
- implements Mac
-{
- private byte[] mac;
-
- private byte[] buf;
- private int bufOff;
- private MacCFBBlockCipher cipher;
- private BlockCipherPadding padding = null;
-
-
- private int macSize;
-
- /**
- * create a standard MAC based on a CFB block cipher. This will produce an
- * authentication code half the length of the block size of the cipher, with
- * the CFB mode set to 8 bits.
- *
- * @param cipher the cipher to be used as the basis of the MAC generation.
- */
- public CFBBlockCipherMac(
- BlockCipher cipher)
- {
- this(cipher, 8, (cipher.getBlockSize() * 8) / 2, null);
- }
-
- /**
- * create a standard MAC based on a CFB block cipher. This will produce an
- * authentication code half the length of the block size of the cipher, with
- * the CFB mode set to 8 bits.
- *
- * @param cipher the cipher to be used as the basis of the MAC generation.
- * @param padding the padding to be used.
- */
- public CFBBlockCipherMac(
- BlockCipher cipher,
- BlockCipherPadding padding)
- {
- this(cipher, 8, (cipher.getBlockSize() * 8) / 2, padding);
- }
-
- /**
- * create a standard MAC based on a block cipher with the size of the
- * MAC been given in bits. This class uses CFB mode as the basis for the
- * MAC generation.
- * <p>
- * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
- * or 16 bits if being used as a data authenticator (FIPS Publication 113),
- * and in general should be less than the size of the block cipher as it reduces
- * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
- *
- * @param cipher the cipher to be used as the basis of the MAC generation.
- * @param cfbBitSize the size of an output block produced by the CFB mode.
- * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
- */
- public CFBBlockCipherMac(
- BlockCipher cipher,
- int cfbBitSize,
- int macSizeInBits)
- {
- this(cipher, cfbBitSize, macSizeInBits, null);
- }
-
- /**
- * create a standard MAC based on a block cipher with the size of the
- * MAC been given in bits. This class uses CFB mode as the basis for the
- * MAC generation.
- * <p>
- * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
- * or 16 bits if being used as a data authenticator (FIPS Publication 113),
- * and in general should be less than the size of the block cipher as it reduces
- * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
- *
- * @param cipher the cipher to be used as the basis of the MAC generation.
- * @param cfbBitSize the size of an output block produced by the CFB mode.
- * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
- * @param padding a padding to be used.
- */
- public CFBBlockCipherMac(
- BlockCipher cipher,
- int cfbBitSize,
- int macSizeInBits,
- BlockCipherPadding padding)
- {
- if ((macSizeInBits % 8) != 0)
- {
- throw new IllegalArgumentException("MAC size must be multiple of 8");
- }
-
- mac = new byte[cipher.getBlockSize()];
-
- this.cipher = new MacCFBBlockCipher(cipher, cfbBitSize);
- this.padding = padding;
- this.macSize = macSizeInBits / 8;
-
- buf = new byte[this.cipher.getBlockSize()];
- bufOff = 0;
- }
-
- public String getAlgorithmName()
- {
- return cipher.getAlgorithmName();
- }
-
- public void init(
- CipherParameters params)
- {
- reset();
-
- cipher.init(params);
- }
-
- public int getMacSize()
- {
- return macSize;
- }
-
- public void update(
- byte in)
- {
- if (bufOff == buf.length)
- {
- cipher.processBlock(buf, 0, mac, 0);
- bufOff = 0;
- }
-
- buf[bufOff++] = in;
- }
-
- public void update(
- byte[] in,
- int inOff,
- int len)
- {
- if (len < 0)
- {
- throw new IllegalArgumentException("Can't have a negative input length!");
- }
-
- int blockSize = cipher.getBlockSize();
- int resultLen = 0;
- int gapLen = blockSize - bufOff;
-
- if (len > gapLen)
- {
- System.arraycopy(in, inOff, buf, bufOff, gapLen);
-
- resultLen += cipher.processBlock(buf, 0, mac, 0);
-
- bufOff = 0;
- len -= gapLen;
- inOff += gapLen;
-
- while (len > blockSize)
- {
- resultLen += cipher.processBlock(in, inOff, mac, 0);
-
- len -= blockSize;
- inOff += blockSize;
- }
- }
-
- System.arraycopy(in, inOff, buf, bufOff, len);
-
- bufOff += len;
- }
-
- public int doFinal(
- byte[] out,
- int outOff)
- {
- int blockSize = cipher.getBlockSize();
-
- //
- // pad with zeroes
- //
- if (this.padding == null)
- {
- while (bufOff < blockSize)
- {
- buf[bufOff] = 0;
- bufOff++;
- }
- }
- else
- {
- padding.addPadding(buf, bufOff);
- }
-
- cipher.processBlock(buf, 0, mac, 0);
-
- cipher.getMacBlock(mac);
-
- System.arraycopy(mac, 0, out, outOff, macSize);
-
- reset();
-
- return macSize;
- }
-
- /**
- * Reset the mac generator.
- */
- public void reset()
- {
- /*
- * clean the buffer.
- */
- for (int i = 0; i < buf.length; i++)
- {
- buf[i] = 0;
- }
-
- bufOff = 0;
-
- /*
- * reset the underlying cipher.
- */
- cipher.reset();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/macs/CMac.java b/core/src/main/java/org/bouncycastle/crypto/macs/CMac.java
deleted file mode 100644
index 0492ae69..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/macs/CMac.java
+++ /dev/null
@@ -1,261 +0,0 @@
-package org.bouncycastle.crypto.macs;
-
-import org.bouncycastle.crypto.BlockCipher;
-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
- * <p>
- * CMAC is analogous to OMAC1 - see also en.wikipedia.org/wiki/CMAC
- * </p><p>
- * CMAC is a NIST recomendation - see
- * csrc.nist.gov/CryptoToolkit/modes/800-38_Series_Publications/SP800-38B.pdf
- * </p><p>
- * CMAC/OMAC1 is a blockcipher-based message authentication code designed and
- * analyzed by Tetsu Iwata and Kaoru Kurosawa.
- * </p><p>
- * CMAC/OMAC1 is a simple variant of the CBC MAC (Cipher Block Chaining Message
- * Authentication Code). OMAC stands for One-Key CBC MAC.
- * </p><p>
- * It supports 128- or 64-bits block ciphers, with any key size, and returns
- * a MAC with dimension less or equal to the block size of the underlying
- * cipher.
- * </p>
- */
-public class CMac implements Mac
-{
- private static final byte CONSTANT_128 = (byte)0x87;
- private static final byte CONSTANT_64 = (byte)0x1b;
-
- private byte[] ZEROES;
-
- private byte[] mac;
-
- private byte[] buf;
- private int bufOff;
- private BlockCipher cipher;
-
- private int macSize;
-
- private byte[] L, Lu, Lu2;
-
- /**
- * create a standard MAC based on a CBC block cipher (64 or 128 bit block).
- * This will produce an authentication code the length of the block size
- * of the cipher.
- *
- * @param cipher the cipher to be used as the basis of the MAC generation.
- */
- public CMac(BlockCipher cipher)
- {
- this(cipher, cipher.getBlockSize() * 8);
- }
-
- /**
- * create a standard MAC based on a block cipher with the size of the
- * MAC been given in bits.
- * <p>
- * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
- * or 16 bits if being used as a data authenticator (FIPS Publication 113),
- * and in general should be less than the size of the block cipher as it reduces
- * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
- *
- * @param cipher the cipher to be used as the basis of the MAC generation.
- * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8 and &lt;= 128.
- */
- public CMac(BlockCipher cipher, int macSizeInBits)
- {
- if ((macSizeInBits % 8) != 0)
- {
- throw new IllegalArgumentException("MAC size must be multiple of 8");
- }
-
- if (macSizeInBits > (cipher.getBlockSize() * 8))
- {
- throw new IllegalArgumentException(
- "MAC size must be less or equal to "
- + (cipher.getBlockSize() * 8));
- }
-
- if (cipher.getBlockSize() != 8 && cipher.getBlockSize() != 16)
- {
- throw new IllegalArgumentException(
- "Block size must be either 64 or 128 bits");
- }
-
- this.cipher = new CBCBlockCipher(cipher);
- this.macSize = macSizeInBits / 8;
-
- mac = new byte[cipher.getBlockSize()];
-
- buf = new byte[cipher.getBlockSize()];
-
- ZEROES = new byte[cipher.getBlockSize()];
-
- bufOff = 0;
- }
-
- public String getAlgorithmName()
- {
- return cipher.getAlgorithmName();
- }
-
- private static int shiftLeft(byte[] block, byte[] output)
- {
- int i = block.length;
- int bit = 0;
- while (--i >= 0)
- {
- 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)
- {
- validate(params);
-
- cipher.init(true, params);
-
- //initializes the L, Lu, Lu2 numbers
- L = new byte[ZEROES.length];
- cipher.processBlock(ZEROES, 0, L, 0);
- Lu = doubleLu(L);
- Lu2 = doubleLu(Lu);
-
- reset();
- }
-
- void validate(CipherParameters params)
- {
- if (params != null)
- {
- if (!(params instanceof KeyParameter))
- {
- // CMAC mode does not permit IV to underlying CBC mode
- throw new IllegalArgumentException("CMac mode only permits key to be set.");
- }
- }
- }
-
- public int getMacSize()
- {
- return macSize;
- }
-
- public void update(byte in)
- {
- if (bufOff == buf.length)
- {
- cipher.processBlock(buf, 0, mac, 0);
- bufOff = 0;
- }
-
- buf[bufOff++] = in;
- }
-
- public void update(byte[] in, int inOff, int len)
- {
- if (len < 0)
- {
- throw new IllegalArgumentException(
- "Can't have a negative input length!");
- }
-
- int blockSize = cipher.getBlockSize();
- int gapLen = blockSize - bufOff;
-
- if (len > gapLen)
- {
- System.arraycopy(in, inOff, buf, bufOff, gapLen);
-
- cipher.processBlock(buf, 0, mac, 0);
-
- bufOff = 0;
- len -= gapLen;
- inOff += gapLen;
-
- while (len > blockSize)
- {
- cipher.processBlock(in, inOff, mac, 0);
-
- len -= blockSize;
- inOff += blockSize;
- }
- }
-
- System.arraycopy(in, inOff, buf, bufOff, len);
-
- bufOff += len;
- }
-
- public int doFinal(byte[] out, int outOff)
- {
- int blockSize = cipher.getBlockSize();
-
- byte[] lu;
- if (bufOff == blockSize)
- {
- lu = Lu;
- }
- else
- {
- new ISO7816d4Padding().addPadding(buf, bufOff);
- lu = Lu2;
- }
-
- for (int i = 0; i < mac.length; i++)
- {
- buf[i] ^= lu[i];
- }
-
- cipher.processBlock(buf, 0, mac, 0);
-
- System.arraycopy(mac, 0, out, outOff, macSize);
-
- reset();
-
- return macSize;
- }
-
- /**
- * Reset the mac generator.
- */
- public void reset()
- {
- /*
- * clean the buffer.
- */
- for (int i = 0; i < buf.length; i++)
- {
- buf[i] = 0;
- }
-
- bufOff = 0;
-
- /*
- * reset the underlying cipher.
- */
- cipher.reset();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/macs/CMacWithIV.java b/core/src/main/java/org/bouncycastle/crypto/macs/CMacWithIV.java
deleted file mode 100644
index a0371d95..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/macs/CMacWithIV.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.bouncycastle.crypto.macs;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-
-/**
- * A non-NIST variant which allows passing of an IV to the underlying CBC cipher.
- * <p>Note: there isn't really a good reason to use an IV here, use the regular CMac where possible.</p>
- */
-public class CMacWithIV
- extends CMac
-{
- public CMacWithIV(BlockCipher cipher)
- {
- super(cipher);
- }
-
- public CMacWithIV(BlockCipher cipher, int macSizeInBits)
- {
- super(cipher, macSizeInBits);
- }
-
- void validate(CipherParameters params)
- {
- // accept all
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/macs/GMac.java b/core/src/main/java/org/bouncycastle/crypto/macs/GMac.java
deleted file mode 100644
index b34f9ea5..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/macs/GMac.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package org.bouncycastle.crypto.macs;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.modes.GCMBlockCipher;
-import org.bouncycastle.crypto.params.AEADParameters;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-/**
- * The GMAC specialisation of Galois/Counter mode (GCM) detailed in NIST Special Publication
- * 800-38D.
- * <p>
- * GMac is an invocation of the GCM mode where no data is encrypted (i.e. all input data to the Mac
- * is processed as additional authenticated data with the underlying GCM block cipher).
- */
-public class GMac implements Mac
-{
- private final GCMBlockCipher cipher;
- private final int macSizeBits;
-
- /**
- * Creates a GMAC based on the operation of a block cipher in GCM mode.
- * <p>
- * This will produce an authentication code the length of the block size of the cipher.
- *
- * @param cipher
- * the cipher to be used in GCM mode to generate the MAC.
- */
- public GMac(final GCMBlockCipher cipher)
- {
- // use of this confused flow analyser in some earlier JDKs
- this.cipher = cipher;
- this.macSizeBits = 128;
- }
-
- /**
- * Creates a GMAC based on the operation of a 128 bit block cipher in GCM mode.
- *
- * @param macSizeBits
- * the mac size to generate, in bits. Must be a multiple of 8 and &gt;= 32 and &lt;= 128.
- * Sizes less than 96 are not recommended, but are supported for specialized applications.
- * @param cipher
- * the cipher to be used in GCM mode to generate the MAC.
- */
- public GMac(final GCMBlockCipher cipher, final int macSizeBits)
- {
- this.cipher = cipher;
- this.macSizeBits = macSizeBits;
- }
-
- /**
- * Initialises the GMAC - requires a {@link ParametersWithIV} providing a {@link KeyParameter}
- * and a nonce.
- */
- public void init(final CipherParameters params) throws IllegalArgumentException
- {
- if (params instanceof ParametersWithIV)
- {
- final ParametersWithIV param = (ParametersWithIV)params;
-
- final byte[] iv = param.getIV();
- final KeyParameter keyParam = (KeyParameter)param.getParameters();
-
- // GCM is always operated in encrypt mode to calculate MAC
- cipher.init(true, new AEADParameters(keyParam, macSizeBits, iv));
- }
- else
- {
- throw new IllegalArgumentException("GMAC requires ParametersWithIV");
- }
- }
-
- public String getAlgorithmName()
- {
- return cipher.getUnderlyingCipher().getAlgorithmName() + "-GMAC";
- }
-
- public int getMacSize()
- {
- return macSizeBits / 8;
- }
-
- public void update(byte in) throws IllegalStateException
- {
- cipher.processAADByte(in);
- }
-
- public void update(byte[] in, int inOff, int len)
- throws DataLengthException, IllegalStateException
- {
- cipher.processAADBytes(in, inOff, len);
- }
-
- public int doFinal(byte[] out, int outOff)
- throws DataLengthException, IllegalStateException
- {
- try
- {
- return cipher.doFinal(out, outOff);
- }
- catch (InvalidCipherTextException e)
- {
- // Impossible in encrypt mode
- throw new IllegalStateException(e.toString());
- }
- }
-
- public void reset()
- {
- cipher.reset();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/macs/GOST28147Mac.java b/core/src/main/java/org/bouncycastle/crypto/macs/GOST28147Mac.java
deleted file mode 100644
index b71975b8..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/macs/GOST28147Mac.java
+++ /dev/null
@@ -1,298 +0,0 @@
-package org.bouncycastle.crypto.macs;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithSBox;
-
-/**
- * implementation of GOST 28147-89 MAC
- */
-public class GOST28147Mac
- implements Mac
-{
- private int blockSize = 8;
- private int macSize = 4;
- private int bufOff;
- private byte[] buf;
- private byte[] mac;
- private boolean firstStep = true;
- private int[] workingKey = null;
-
- //
- // This is default S-box - E_A.
- private byte S[] = {
- 0x9,0x6,0x3,0x2,0x8,0xB,0x1,0x7,0xA,0x4,0xE,0xF,0xC,0x0,0xD,0x5,
- 0x3,0x7,0xE,0x9,0x8,0xA,0xF,0x0,0x5,0x2,0x6,0xC,0xB,0x4,0xD,0x1,
- 0xE,0x4,0x6,0x2,0xB,0x3,0xD,0x8,0xC,0xF,0x5,0xA,0x0,0x7,0x1,0x9,
- 0xE,0x7,0xA,0xC,0xD,0x1,0x3,0x9,0x0,0x2,0xB,0x4,0xF,0x8,0x5,0x6,
- 0xB,0x5,0x1,0x9,0x8,0xD,0xF,0x0,0xE,0x4,0x2,0x3,0xC,0x7,0xA,0x6,
- 0x3,0xA,0xD,0xC,0x1,0x2,0x0,0xB,0x7,0x5,0x9,0x4,0x8,0xF,0xE,0x6,
- 0x1,0xD,0x2,0x9,0x7,0xA,0x6,0x0,0x8,0xC,0x4,0x5,0xF,0x3,0xB,0xE,
- 0xB,0xA,0xF,0x5,0x0,0xC,0xE,0x8,0x6,0x2,0x3,0x9,0x1,0x7,0xD,0x4
- };
-
- public GOST28147Mac()
- {
- mac = new byte[blockSize];
-
- buf = new byte[blockSize];
- bufOff = 0;
- }
-
- private int[] generateWorkingKey(
- byte[] userKey)
- {
- if (userKey.length != 32)
- {
- throw new IllegalArgumentException("Key length invalid. Key needs to be 32 byte - 256 bit!!!");
- }
-
- int key[] = new int[8];
- for(int i=0; i!=8; i++)
- {
- key[i] = bytesToint(userKey,i*4);
- }
-
- return key;
- }
-
- public void init(
- CipherParameters params)
- throws IllegalArgumentException
- {
- reset();
- buf = new byte[blockSize];
- if (params instanceof ParametersWithSBox)
- {
- ParametersWithSBox param = (ParametersWithSBox)params;
-
- //
- // Set the S-Box
- //
- System.arraycopy(param.getSBox(), 0, this.S, 0, param.getSBox().length);
-
- //
- // set key if there is one
- //
- if (param.getParameters() != null)
- {
- workingKey = generateWorkingKey(((KeyParameter)param.getParameters()).getKey());
- }
- }
- else if (params instanceof KeyParameter)
- {
- workingKey = generateWorkingKey(((KeyParameter)params).getKey());
- }
- else
- {
- throw new IllegalArgumentException("invalid parameter passed to GOST28147 init - " + params.getClass().getName());
- }
- }
-
- public String getAlgorithmName()
- {
- return "GOST28147Mac";
- }
-
- public int getMacSize()
- {
- return macSize;
- }
-
- private int gost28147_mainStep(int n1, int key)
- {
- int cm = (key + n1); // CM1
-
- // S-box replacing
-
- int om = S[ 0 + ((cm >> (0 * 4)) & 0xF)] << (0 * 4);
- om += S[ 16 + ((cm >> (1 * 4)) & 0xF)] << (1 * 4);
- om += S[ 32 + ((cm >> (2 * 4)) & 0xF)] << (2 * 4);
- om += S[ 48 + ((cm >> (3 * 4)) & 0xF)] << (3 * 4);
- om += S[ 64 + ((cm >> (4 * 4)) & 0xF)] << (4 * 4);
- om += S[ 80 + ((cm >> (5 * 4)) & 0xF)] << (5 * 4);
- om += S[ 96 + ((cm >> (6 * 4)) & 0xF)] << (6 * 4);
- om += S[112 + ((cm >> (7 * 4)) & 0xF)] << (7 * 4);
-
- return om << 11 | om >>> (32-11); // 11-leftshift
- }
-
- private void gost28147MacFunc(
- int[] workingKey,
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- {
- int N1, N2, tmp; //tmp -> for saving N1
- N1 = bytesToint(in, inOff);
- N2 = bytesToint(in, inOff + 4);
-
- for(int k = 0; k < 2; k++) // 1-16 steps
- {
- for(int j = 0; j < 8; j++)
- {
- tmp = N1;
- N1 = N2 ^ gost28147_mainStep(N1, workingKey[j]); // CM2
- N2 = tmp;
- }
- }
-
- intTobytes(N1, out, outOff);
- intTobytes(N2, out, outOff + 4);
- }
-
- //array of bytes to type int
- private int bytesToint(
- byte[] in,
- int inOff)
- {
- return ((in[inOff + 3] << 24) & 0xff000000) + ((in[inOff + 2] << 16) & 0xff0000) +
- ((in[inOff + 1] << 8) & 0xff00) + (in[inOff] & 0xff);
- }
-
- //int to array of bytes
- private void intTobytes(
- int num,
- byte[] out,
- int outOff)
- {
- out[outOff + 3] = (byte)(num >>> 24);
- out[outOff + 2] = (byte)(num >>> 16);
- out[outOff + 1] = (byte)(num >>> 8);
- out[outOff] = (byte)num;
- }
-
- private byte[] CM5func(byte[] buf, int bufOff, byte[] mac)
- {
- byte[] sum = new byte[buf.length - bufOff];
-
- System.arraycopy(buf, bufOff, sum, 0, mac.length);
-
- for (int i = 0; i != mac.length; i++)
- {
- sum[i] = (byte)(sum[i] ^ mac[i]);
- }
-
- return sum;
- }
-
- public void update(byte in)
- throws IllegalStateException
- {
- if (bufOff == buf.length)
- {
- byte[] sumbuf = new byte[buf.length];
- System.arraycopy(buf, 0, sumbuf, 0, mac.length);
-
- if (firstStep)
- {
- firstStep = false;
- }
- else
- {
- sumbuf = CM5func(buf, 0, mac);
- }
-
- gost28147MacFunc(workingKey, sumbuf, 0, mac, 0);
- bufOff = 0;
- }
-
- buf[bufOff++] = in;
- }
-
- public void update(byte[] in, int inOff, int len)
- throws DataLengthException, IllegalStateException
- {
- if (len < 0)
- {
- throw new IllegalArgumentException("Can't have a negative input length!");
- }
-
- int gapLen = blockSize - bufOff;
-
- if (len > gapLen)
- {
- System.arraycopy(in, inOff, buf, bufOff, gapLen);
-
- byte[] sumbuf = new byte[buf.length];
- System.arraycopy(buf, 0, sumbuf, 0, mac.length);
-
- if (firstStep)
- {
- firstStep = false;
- }
- else
- {
- sumbuf = CM5func(buf, 0, mac);
- }
-
- gost28147MacFunc(workingKey, sumbuf, 0, mac, 0);
-
- bufOff = 0;
- len -= gapLen;
- inOff += gapLen;
-
- while (len > blockSize)
- {
- sumbuf = CM5func(in, inOff, mac);
- gost28147MacFunc(workingKey, sumbuf, 0, mac, 0);
-
- len -= blockSize;
- inOff += blockSize;
- }
- }
-
- System.arraycopy(in, inOff, buf, bufOff, len);
-
- bufOff += len;
- }
-
- public int doFinal(byte[] out, int outOff)
- throws DataLengthException, IllegalStateException
- {
- //padding with zero
- while (bufOff < blockSize)
- {
- buf[bufOff] = 0;
- bufOff++;
- }
-
- byte[] sumbuf = new byte[buf.length];
- System.arraycopy(buf, 0, sumbuf, 0, mac.length);
-
- if (firstStep)
- {
- firstStep = false;
- }
- else
- {
- sumbuf = CM5func(buf, 0, mac);
- }
-
- gost28147MacFunc(workingKey, sumbuf, 0, mac, 0);
-
- System.arraycopy(mac, (mac.length/2)-macSize, out, outOff, macSize);
-
- reset();
-
- return macSize;
- }
-
- public void reset()
- {
- /*
- * clean the buffer.
- */
- for (int i = 0; i < buf.length; i++)
- {
- buf[i] = 0;
- }
-
- bufOff = 0;
-
- firstStep = true;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/macs/HMac.java b/core/src/main/java/org/bouncycastle/crypto/macs/HMac.java
deleted file mode 100644
index d4345d9b..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/macs/HMac.java
+++ /dev/null
@@ -1,231 +0,0 @@
-package org.bouncycastle.crypto.macs;
-
-import java.util.Hashtable;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.ExtendedDigest;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Integers;
-import org.bouncycastle.util.Memoable;
-
-/**
- * HMAC implementation based on RFC2104
- *
- * H(K XOR opad, H(K XOR ipad, text))
- */
-public class HMac
- implements Mac
-{
- private final static byte IPAD = (byte)0x36;
- private final static byte OPAD = (byte)0x5C;
-
- private Digest digest;
- private int digestSize;
- private int blockLength;
- private Memoable ipadState;
- private Memoable opadState;
-
- private byte[] inputPad;
- private byte[] outputBuf;
-
- private static Hashtable blockLengths;
-
- static
- {
- blockLengths = new Hashtable();
-
- blockLengths.put("GOST3411", Integers.valueOf(32));
-
- blockLengths.put("MD2", Integers.valueOf(16));
- blockLengths.put("MD4", Integers.valueOf(64));
- blockLengths.put("MD5", Integers.valueOf(64));
-
- blockLengths.put("RIPEMD128", Integers.valueOf(64));
- blockLengths.put("RIPEMD160", Integers.valueOf(64));
-
- blockLengths.put("SHA-1", Integers.valueOf(64));
- blockLengths.put("SHA-224", Integers.valueOf(64));
- blockLengths.put("SHA-256", Integers.valueOf(64));
- blockLengths.put("SHA-384", Integers.valueOf(128));
- blockLengths.put("SHA-512", Integers.valueOf(128));
-
- blockLengths.put("Tiger", Integers.valueOf(64));
- blockLengths.put("Whirlpool", Integers.valueOf(64));
- }
-
- private static int getByteLength(
- Digest digest)
- {
- if (digest instanceof ExtendedDigest)
- {
- return ((ExtendedDigest)digest).getByteLength();
- }
-
- Integer b = (Integer)blockLengths.get(digest.getAlgorithmName());
-
- if (b == null)
- {
- throw new IllegalArgumentException("unknown digest passed: " + digest.getAlgorithmName());
- }
-
- return b.intValue();
- }
-
- /**
- * Base constructor for one of the standard digest algorithms that the
- * byteLength of the algorithm is know for.
- *
- * @param digest the digest.
- */
- public HMac(
- Digest digest)
- {
- this(digest, getByteLength(digest));
- }
-
- private HMac(
- Digest digest,
- int byteLength)
- {
- this.digest = digest;
- this.digestSize = digest.getDigestSize();
- this.blockLength = byteLength;
- this.inputPad = new byte[blockLength];
- this.outputBuf = new byte[blockLength + digestSize];
- }
-
- public String getAlgorithmName()
- {
- return digest.getAlgorithmName() + "/HMAC";
- }
-
- public Digest getUnderlyingDigest()
- {
- return digest;
- }
-
- public void init(
- CipherParameters params)
- {
- digest.reset();
-
- byte[] key = ((KeyParameter)params).getKey();
- int keyLength = key.length;
-
- if (keyLength > blockLength)
- {
- digest.update(key, 0, keyLength);
- digest.doFinal(inputPad, 0);
-
- keyLength = digestSize;
- }
- else
- {
- System.arraycopy(key, 0, inputPad, 0, keyLength);
- }
-
- for (int i = keyLength; i < inputPad.length; i++)
- {
- inputPad[i] = 0;
- }
-
- System.arraycopy(inputPad, 0, outputBuf, 0, blockLength);
-
- xorPad(inputPad, blockLength, IPAD);
- xorPad(outputBuf, blockLength, OPAD);
-
- if (digest instanceof Memoable)
- {
- opadState = ((Memoable)digest).copy();
-
- ((Digest)opadState).update(outputBuf, 0, blockLength);
- }
-
- digest.update(inputPad, 0, inputPad.length);
-
- if (digest instanceof Memoable)
- {
- ipadState = ((Memoable)digest).copy();
- }
- }
-
- public int getMacSize()
- {
- return digestSize;
- }
-
- public void update(
- byte in)
- {
- digest.update(in);
- }
-
- public void update(
- byte[] in,
- int inOff,
- int len)
- {
- digest.update(in, inOff, len);
- }
-
- public int doFinal(
- byte[] out,
- int outOff)
- {
- digest.doFinal(outputBuf, blockLength);
-
- if (opadState != null)
- {
- ((Memoable)digest).reset(opadState);
- digest.update(outputBuf, blockLength, digest.getDigestSize());
- }
- else
- {
- digest.update(outputBuf, 0, outputBuf.length);
- }
-
- int len = digest.doFinal(out, outOff);
-
- for (int i = blockLength; i < outputBuf.length; i++)
- {
- outputBuf[i] = 0;
- }
-
- if (ipadState != null)
- {
- ((Memoable)digest).reset(ipadState);
- }
- else
- {
- digest.update(inputPad, 0, inputPad.length);
- }
-
- return len;
- }
-
- /**
- * Reset the mac generator.
- */
- public void reset()
- {
- /*
- * reset the underlying digest.
- */
- digest.reset();
-
- /*
- * reinitialize the digest.
- */
- digest.update(inputPad, 0, inputPad.length);
- }
-
- private static void xorPad(byte[] pad, int len, byte n)
- {
- for (int i = 0; i < len; ++i)
- {
- pad[i] ^= n;
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/macs/ISO9797Alg3Mac.java b/core/src/main/java/org/bouncycastle/crypto/macs/ISO9797Alg3Mac.java
deleted file mode 100644
index 330b39e7..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/macs/ISO9797Alg3Mac.java
+++ /dev/null
@@ -1,305 +0,0 @@
-package org.bouncycastle.crypto.macs;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.engines.DESEngine;
-import org.bouncycastle.crypto.modes.CBCBlockCipher;
-import org.bouncycastle.crypto.paddings.BlockCipherPadding;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-/**
- * DES based CBC Block Cipher MAC according to ISO9797, algorithm 3 (ANSI X9.19 Retail MAC)
- *
- * This could as well be derived from CBCBlockCipherMac, but then the property mac in the base
- * class must be changed to protected
- */
-
-public class ISO9797Alg3Mac
- implements Mac
-{
- private byte[] mac;
-
- private byte[] buf;
- private int bufOff;
- private BlockCipher cipher;
- private BlockCipherPadding padding;
-
- private int macSize;
- private KeyParameter lastKey2;
- private KeyParameter lastKey3;
-
- /**
- * create a Retail-MAC based on a CBC block cipher. This will produce an
- * authentication code of the length of the block size of the cipher.
- *
- * @param cipher the cipher to be used as the basis of the MAC generation. This must
- * be DESEngine.
- */
- public ISO9797Alg3Mac(
- BlockCipher cipher)
- {
- this(cipher, cipher.getBlockSize() * 8, null);
- }
-
- /**
- * create a Retail-MAC based on a CBC block cipher. This will produce an
- * authentication code of the length of the block size of the cipher.
- *
- * @param cipher the cipher to be used as the basis of the MAC generation.
- * @param padding the padding to be used to complete the last block.
- */
- public ISO9797Alg3Mac(
- BlockCipher cipher,
- BlockCipherPadding padding)
- {
- this(cipher, cipher.getBlockSize() * 8, padding);
- }
-
- /**
- * create a Retail-MAC based on a block cipher with the size of the
- * MAC been given in bits. This class uses single DES CBC mode as the basis for the
- * MAC generation.
- * <p>
- * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
- * or 16 bits if being used as a data authenticator (FIPS Publication 113),
- * and in general should be less than the size of the block cipher as it reduces
- * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
- *
- * @param cipher the cipher to be used as the basis of the MAC generation.
- * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
- */
- public ISO9797Alg3Mac(
- BlockCipher cipher,
- int macSizeInBits)
- {
- this(cipher, macSizeInBits, null);
- }
-
- /**
- * create a standard MAC based on a block cipher with the size of the
- * MAC been given in bits. This class uses single DES CBC mode as the basis for the
- * MAC generation. The final block is decrypted and then encrypted using the
- * middle and right part of the key.
- * <p>
- * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
- * or 16 bits if being used as a data authenticator (FIPS Publication 113),
- * and in general should be less than the size of the block cipher as it reduces
- * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
- *
- * @param cipher the cipher to be used as the basis of the MAC generation.
- * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
- * @param padding the padding to be used to complete the last block.
- */
- public ISO9797Alg3Mac(
- BlockCipher cipher,
- int macSizeInBits,
- BlockCipherPadding padding)
- {
- if ((macSizeInBits % 8) != 0)
- {
- throw new IllegalArgumentException("MAC size must be multiple of 8");
- }
-
- if (!(cipher instanceof DESEngine))
- {
- throw new IllegalArgumentException("cipher must be instance of DESEngine");
- }
-
- this.cipher = new CBCBlockCipher(cipher);
- this.padding = padding;
- this.macSize = macSizeInBits / 8;
-
- mac = new byte[cipher.getBlockSize()];
-
- buf = new byte[cipher.getBlockSize()];
- bufOff = 0;
- }
-
- public String getAlgorithmName()
- {
- return "ISO9797Alg3";
- }
-
- public void init(CipherParameters params)
- {
- reset();
-
- if (!(params instanceof KeyParameter || params instanceof ParametersWithIV))
- {
- throw new IllegalArgumentException(
- "params must be an instance of KeyParameter or ParametersWithIV");
- }
-
- // KeyParameter must contain a double or triple length DES key,
- // however the underlying cipher is a single DES. The middle and
- // right key are used only in the final step.
-
- KeyParameter kp;
-
- if (params instanceof KeyParameter)
- {
- kp = (KeyParameter)params;
- }
- else
- {
- kp = (KeyParameter)((ParametersWithIV)params).getParameters();
- }
-
- KeyParameter key1;
- byte[] keyvalue = kp.getKey();
-
- if (keyvalue.length == 16)
- { // Double length DES key
- key1 = new KeyParameter(keyvalue, 0, 8);
- this.lastKey2 = new KeyParameter(keyvalue, 8, 8);
- this.lastKey3 = key1;
- }
- else if (keyvalue.length == 24)
- { // Triple length DES key
- key1 = new KeyParameter(keyvalue, 0, 8);
- this.lastKey2 = new KeyParameter(keyvalue, 8, 8);
- this.lastKey3 = new KeyParameter(keyvalue, 16, 8);
- }
- else
- {
- throw new IllegalArgumentException(
- "Key must be either 112 or 168 bit long");
- }
-
- if (params instanceof ParametersWithIV)
- {
- cipher.init(true, new ParametersWithIV(key1, ((ParametersWithIV)params).getIV()));
- }
- else
- {
- cipher.init(true, key1);
- }
- }
-
- public int getMacSize()
- {
- return macSize;
- }
-
- public void update(
- byte in)
- {
- if (bufOff == buf.length)
- {
- cipher.processBlock(buf, 0, mac, 0);
- bufOff = 0;
- }
-
- buf[bufOff++] = in;
- }
-
-
- public void update(
- byte[] in,
- int inOff,
- int len)
- {
- if (len < 0)
- {
- throw new IllegalArgumentException("Can't have a negative input length!");
- }
-
- int blockSize = cipher.getBlockSize();
- int resultLen = 0;
- int gapLen = blockSize - bufOff;
-
- if (len > gapLen)
- {
- System.arraycopy(in, inOff, buf, bufOff, gapLen);
-
- resultLen += cipher.processBlock(buf, 0, mac, 0);
-
- bufOff = 0;
- len -= gapLen;
- inOff += gapLen;
-
- while (len > blockSize)
- {
- resultLen += cipher.processBlock(in, inOff, mac, 0);
-
- len -= blockSize;
- inOff += blockSize;
- }
- }
-
- System.arraycopy(in, inOff, buf, bufOff, len);
-
- bufOff += len;
- }
-
- public int doFinal(
- byte[] out,
- int outOff)
- {
- int blockSize = cipher.getBlockSize();
-
- if (padding == null)
- {
- //
- // pad with zeroes
- //
- while (bufOff < blockSize)
- {
- buf[bufOff] = 0;
- bufOff++;
- }
- }
- else
- {
- if (bufOff == blockSize)
- {
- cipher.processBlock(buf, 0, mac, 0);
- bufOff = 0;
- }
-
- padding.addPadding(buf, bufOff);
- }
-
- cipher.processBlock(buf, 0, mac, 0);
-
- // Added to code from base class
- DESEngine deseng = new DESEngine();
-
- deseng.init(false, this.lastKey2);
- deseng.processBlock(mac, 0, mac, 0);
-
- deseng.init(true, this.lastKey3);
- deseng.processBlock(mac, 0, mac, 0);
- // ****
-
- System.arraycopy(mac, 0, out, outOff, macSize);
-
- reset();
-
- return macSize;
- }
-
-
- /**
- * Reset the mac generator.
- */
- public void reset()
- {
- /*
- * clean the buffer.
- */
- for (int i = 0; i < buf.length; i++)
- {
- buf[i] = 0;
- }
-
- bufOff = 0;
-
- /*
- * reset the underlying cipher.
- */
- cipher.reset();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/macs/OldHMac.java b/core/src/main/java/org/bouncycastle/crypto/macs/OldHMac.java
deleted file mode 100644
index 7463afd3..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/macs/OldHMac.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package org.bouncycastle.crypto.macs;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.params.KeyParameter;
-
-/**
- * HMAC implementation based on RFC2104
- *
- * H(K XOR opad, H(K XOR ipad, text))
- */
-public class OldHMac
-implements Mac
-{
- private final static int BLOCK_LENGTH = 64;
-
- private final static byte IPAD = (byte)0x36;
- private final static byte OPAD = (byte)0x5C;
-
- private Digest digest;
- private int digestSize;
- private byte[] inputPad = new byte[BLOCK_LENGTH];
- private byte[] outputPad = new byte[BLOCK_LENGTH];
-
- /**
- * @deprecated uses incorrect pad for SHA-512 and SHA-384 use HMac.
- */
- public OldHMac(
- Digest digest)
- {
- this.digest = digest;
- digestSize = digest.getDigestSize();
- }
-
- public String getAlgorithmName()
- {
- return digest.getAlgorithmName() + "/HMAC";
- }
-
- public Digest getUnderlyingDigest()
- {
- return digest;
- }
-
- public void init(
- CipherParameters params)
- {
- digest.reset();
-
- byte[] key = ((KeyParameter)params).getKey();
-
- if (key.length > BLOCK_LENGTH)
- {
- digest.update(key, 0, key.length);
- digest.doFinal(inputPad, 0);
- for (int i = digestSize; i < inputPad.length; i++)
- {
- inputPad[i] = 0;
- }
- }
- else
- {
- System.arraycopy(key, 0, inputPad, 0, key.length);
- for (int i = key.length; i < inputPad.length; i++)
- {
- inputPad[i] = 0;
- }
- }
-
- outputPad = new byte[inputPad.length];
- System.arraycopy(inputPad, 0, outputPad, 0, inputPad.length);
-
- for (int i = 0; i < inputPad.length; i++)
- {
- inputPad[i] ^= IPAD;
- }
-
- for (int i = 0; i < outputPad.length; i++)
- {
- outputPad[i] ^= OPAD;
- }
-
- digest.update(inputPad, 0, inputPad.length);
- }
-
- public int getMacSize()
- {
- return digestSize;
- }
-
- public void update(
- byte in)
- {
- digest.update(in);
- }
-
- public void update(
- byte[] in,
- int inOff,
- int len)
- {
- digest.update(in, inOff, len);
- }
-
- public int doFinal(
- byte[] out,
- int outOff)
- {
- byte[] tmp = new byte[digestSize];
- digest.doFinal(tmp, 0);
-
- digest.update(outputPad, 0, outputPad.length);
- digest.update(tmp, 0, tmp.length);
-
- int len = digest.doFinal(out, outOff);
-
- reset();
-
- return len;
- }
-
- /**
- * Reset the mac generator.
- */
- public void reset()
- {
- /*
- * reset the underlying digest.
- */
- digest.reset();
-
- /*
- * reinitialize the digest.
- */
- digest.update(inputPad, 0, inputPad.length);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/macs/Poly1305.java b/core/src/main/java/org/bouncycastle/crypto/macs/Poly1305.java
deleted file mode 100644
index 7a346f1e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/macs/Poly1305.java
+++ /dev/null
@@ -1,306 +0,0 @@
-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.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, where the key passed to init() will be used directly.
- */
- public Poly1305()
- {
- this.cipher = null;
- }
-
- /**
- * 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 params if used with a block cipher, then 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}, otherwise just the
- * {@link KeyParameter}.
- */
- public void init(CipherParameters params)
- throws IllegalArgumentException
- {
- byte[] nonce = null;
-
- if (cipher != null)
- {
- if (!(params instanceof ParametersWithIV))
- {
- throw new IllegalArgumentException("Poly1305 requires an IV when used with a block cipher.");
- }
-
- ParametersWithIV ivParams = (ParametersWithIV)params;
- nonce = ivParams.getIV();
- params = ivParams.getParameters();
- }
-
- if (!(params instanceof KeyParameter))
- {
- throw new IllegalArgumentException("Poly1305 requires a key.");
- }
-
- KeyParameter keyParams = (KeyParameter)params;
-
- setKey(keyParams.getKey(), nonce);
-
- reset();
- }
-
- private void setKey(final byte[] key, final byte[] nonce)
- {
- if (cipher != null && (nonce == null || 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;
-
- final byte[] kBytes;
- if (cipher == null)
- {
- kBytes = key;
- }
- else
- {
- // Compute encrypted nonce
- kBytes = new byte[BLOCK_SIZE];
- cipher.init(true, new KeyParameter(key, 0, BLOCK_SIZE));
- cipher.processBlock(nonce, 0, kBytes, 0);
- }
-
- k0 = Pack.littleEndianToInt(kBytes, 0);
- k1 = Pack.littleEndianToInt(kBytes, 4);
- k2 = Pack.littleEndianToInt(kBytes, 8);
- k3 = Pack.littleEndianToInt(kBytes, 12);
- }
-
- public String getAlgorithmName()
- {
- return cipher == null ? "Poly1305" : "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/core/src/main/java/org/bouncycastle/crypto/macs/SipHash.java b/core/src/main/java/org/bouncycastle/crypto/macs/SipHash.java
deleted file mode 100644
index d6b9dbb8..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/macs/SipHash.java
+++ /dev/null
@@ -1,216 +0,0 @@
-package org.bouncycastle.crypto.macs;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Pack;
-
-/**
- * Implementation of SipHash as specified in "SipHash: a fast short-input PRF", by Jean-Philippe
- * Aumasson and Daniel J. Bernstein (https://131002.net/siphash/siphash.pdf).
- * <p>
- * "SipHash is a family of PRFs SipHash-c-d where the integer parameters c and d are the number of
- * compression rounds and the number of finalization rounds. A compression round is identical to a
- * finalization round and this round function is called SipRound. Given a 128-bit key k and a
- * (possibly empty) byte string m, SipHash-c-d returns a 64-bit value..."
- */
-public class SipHash
- implements Mac
-{
- protected final int c, d;
-
- protected long k0, k1;
- protected long v0, v1, v2, v3;
-
- protected long m = 0;
- protected int wordPos = 0;
- protected int wordCount = 0;
-
- /**
- * SipHash-2-4
- */
- public SipHash()
- {
- // use of 'this' confuses the flow analyser on earlier JDKs.
- this.c = 2;
- this.d = 4;
- }
-
- /**
- * SipHash-c-d
- *
- * @param c the number of compression rounds
- * @param d the number of finalization rounds
- */
- public SipHash(int c, int d)
- {
- this.c = c;
- this.d = d;
- }
-
- public String getAlgorithmName()
- {
- return "SipHash-" + c + "-" + d;
- }
-
- public int getMacSize()
- {
- return 8;
- }
-
- public void init(CipherParameters params)
- throws IllegalArgumentException
- {
- if (!(params instanceof KeyParameter))
- {
- throw new IllegalArgumentException("'params' must be an instance of KeyParameter");
- }
- KeyParameter keyParameter = (KeyParameter)params;
- byte[] key = keyParameter.getKey();
- if (key.length != 16)
- {
- throw new IllegalArgumentException("'params' must be a 128-bit key");
- }
-
- this.k0 = Pack.littleEndianToLong(key, 0);
- this.k1 = Pack.littleEndianToLong(key, 8);
-
- reset();
- }
-
- public void update(byte input)
- throws IllegalStateException
- {
- m >>>= 8;
- m |= (input & 0xffL) << 56;
-
- if (++wordPos == 8)
- {
- processMessageWord();
- wordPos = 0;
- }
- }
-
- public void update(byte[] input, int offset, int length)
- throws DataLengthException,
- IllegalStateException
- {
- int i = 0, fullWords = length & ~7;
- if (wordPos == 0)
- {
- for (; i < fullWords; i += 8)
- {
- m = Pack.littleEndianToLong(input, offset + i);
- processMessageWord();
- }
- for (; i < length; ++i)
- {
- m >>>= 8;
- m |= (input[offset + i] & 0xffL) << 56;
- }
- wordPos = length - fullWords;
- }
- else
- {
- int bits = wordPos << 3;
- for (; i < fullWords; i += 8)
- {
- long n = Pack.littleEndianToLong(input, offset + i);
- m = (n << bits) | (m >>> -bits);
- processMessageWord();
- m = n;
- }
- for (; i < length; ++i)
- {
- m >>>= 8;
- m |= (input[offset + i] & 0xffL) << 56;
-
- if (++wordPos == 8)
- {
- processMessageWord();
- wordPos = 0;
- }
- }
- }
- }
-
- public long doFinal()
- throws DataLengthException, IllegalStateException
- {
- // NOTE: 2 distinct shifts to avoid "64-bit shift" when wordPos == 0
- m >>>= ((7 - wordPos) << 3);
- m >>>= 8;
- m |= (((wordCount << 3) + wordPos) & 0xffL) << 56;
-
- processMessageWord();
-
- v2 ^= 0xffL;
-
- applySipRounds(d);
-
- long result = v0 ^ v1 ^ v2 ^ v3;
-
- reset();
-
- return result;
- }
-
- public int doFinal(byte[] out, int outOff)
- throws DataLengthException, IllegalStateException
- {
- long result = doFinal();
- Pack.longToLittleEndian(result, out, outOff);
- return 8;
- }
-
- public void reset()
- {
- v0 = k0 ^ 0x736f6d6570736575L;
- v1 = k1 ^ 0x646f72616e646f6dL;
- v2 = k0 ^ 0x6c7967656e657261L;
- v3 = k1 ^ 0x7465646279746573L;
-
- m = 0;
- wordPos = 0;
- wordCount = 0;
- }
-
- protected void processMessageWord()
- {
- ++wordCount;
- v3 ^= m;
- applySipRounds(c);
- v0 ^= m;
- }
-
- protected void applySipRounds(int n)
- {
- long r0 = v0, r1 = v1, r2 = v2, r3 = v3;
-
- for (int r = 0; r < n; ++r)
- {
- r0 += r1;
- r2 += r3;
- r1 = rotateLeft(r1, 13);
- r3 = rotateLeft(r3, 16);
- r1 ^= r0;
- r3 ^= r2;
- r0 = rotateLeft(r0, 32);
- r2 += r1;
- r0 += r3;
- r1 = rotateLeft(r1, 17);
- r3 = rotateLeft(r3, 21);
- r1 ^= r2;
- r3 ^= r0;
- r2 = rotateLeft(r2, 32);
- }
-
- v0 = r0; v1 = r1; v2 = r2; v3 = r3;
- }
-
- protected static long rotateLeft(long x, int n)
- {
- return (x << n) | (x >>> -n);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/macs/SkeinMac.java b/core/src/main/java/org/bouncycastle/crypto/macs/SkeinMac.java
deleted file mode 100644
index 7115b510..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/macs/SkeinMac.java
+++ /dev/null
@@ -1,118 +0,0 @@
-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.
- *
- * @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/core/src/main/java/org/bouncycastle/crypto/macs/VMPCMac.java b/core/src/main/java/org/bouncycastle/crypto/macs/VMPCMac.java
deleted file mode 100644
index 58d06d08..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/macs/VMPCMac.java
+++ /dev/null
@@ -1,186 +0,0 @@
-package org.bouncycastle.crypto.macs;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-public class VMPCMac implements Mac
-{
- private byte g;
-
- private byte n = 0;
- private byte[] P = null;
- private byte s = 0;
-
- private byte[] T;
- private byte[] workingIV;
-
- private byte[] workingKey;
-
- private byte x1, x2, x3, x4;
-
- public int doFinal(byte[] out, int outOff)
- throws DataLengthException, IllegalStateException
- {
- // Execute the Post-Processing Phase
- for (int r = 1; r < 25; r++)
- {
- s = P[(s + P[n & 0xff]) & 0xff];
-
- x4 = P[(x4 + x3 + r) & 0xff];
- x3 = P[(x3 + x2 + r) & 0xff];
- x2 = P[(x2 + x1 + r) & 0xff];
- x1 = P[(x1 + s + r) & 0xff];
- T[g & 0x1f] = (byte) (T[g & 0x1f] ^ x1);
- T[(g + 1) & 0x1f] = (byte) (T[(g + 1) & 0x1f] ^ x2);
- T[(g + 2) & 0x1f] = (byte) (T[(g + 2) & 0x1f] ^ x3);
- T[(g + 3) & 0x1f] = (byte) (T[(g + 3) & 0x1f] ^ x4);
- g = (byte) ((g + 4) & 0x1f);
-
- byte temp = P[n & 0xff];
- P[n & 0xff] = P[s & 0xff];
- P[s & 0xff] = temp;
- n = (byte) ((n + 1) & 0xff);
- }
-
- // Input T to the IV-phase of the VMPC KSA
- for (int m = 0; m < 768; m++)
- {
- s = P[(s + P[m & 0xff] + T[m & 0x1f]) & 0xff];
- byte temp = P[m & 0xff];
- P[m & 0xff] = P[s & 0xff];
- P[s & 0xff] = temp;
- }
-
- // Store 20 new outputs of the VMPC Stream Cipher in table M
- byte[] M = new byte[20];
- for (int i = 0; i < 20; i++)
- {
- s = P[(s + P[i & 0xff]) & 0xff];
- M[i] = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff];
-
- byte temp = P[i & 0xff];
- P[i & 0xff] = P[s & 0xff];
- P[s & 0xff] = temp;
- }
-
- System.arraycopy(M, 0, out, outOff, M.length);
- reset();
-
- return M.length;
- }
-
- public String getAlgorithmName()
- {
- return "VMPC-MAC";
- }
-
- public int getMacSize()
- {
- return 20;
- }
-
- public void init(CipherParameters params) throws IllegalArgumentException
- {
- if (!(params instanceof ParametersWithIV))
- {
- throw new IllegalArgumentException(
- "VMPC-MAC Init parameters must include an IV");
- }
-
- ParametersWithIV ivParams = (ParametersWithIV) params;
- KeyParameter key = (KeyParameter) ivParams.getParameters();
-
- if (!(ivParams.getParameters() instanceof KeyParameter))
- {
- throw new IllegalArgumentException(
- "VMPC-MAC Init parameters must include a key");
- }
-
- this.workingIV = ivParams.getIV();
-
- if (workingIV == null || workingIV.length < 1 || workingIV.length > 768)
- {
- throw new IllegalArgumentException(
- "VMPC-MAC requires 1 to 768 bytes of IV");
- }
-
- this.workingKey = key.getKey();
-
- reset();
-
- }
-
- private void initKey(byte[] keyBytes, byte[] ivBytes)
- {
- s = 0;
- P = new byte[256];
- for (int i = 0; i < 256; i++)
- {
- P[i] = (byte) i;
- }
- for (int m = 0; m < 768; m++)
- {
- s = P[(s + P[m & 0xff] + keyBytes[m % keyBytes.length]) & 0xff];
- byte temp = P[m & 0xff];
- P[m & 0xff] = P[s & 0xff];
- P[s & 0xff] = temp;
- }
- for (int m = 0; m < 768; m++)
- {
- s = P[(s + P[m & 0xff] + ivBytes[m % ivBytes.length]) & 0xff];
- byte temp = P[m & 0xff];
- P[m & 0xff] = P[s & 0xff];
- P[s & 0xff] = temp;
- }
- n = 0;
- }
-
- public void reset()
- {
- initKey(this.workingKey, this.workingIV);
- g = x1 = x2 = x3 = x4 = n = 0;
- T = new byte[32];
- for (int i = 0; i < 32; i++)
- {
- T[i] = 0;
- }
- }
-
- public void update(byte in) throws IllegalStateException
- {
- s = P[(s + P[n & 0xff]) & 0xff];
- byte c = (byte) (in ^ P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff]);
-
- x4 = P[(x4 + x3) & 0xff];
- x3 = P[(x3 + x2) & 0xff];
- x2 = P[(x2 + x1) & 0xff];
- x1 = P[(x1 + s + c) & 0xff];
- T[g & 0x1f] = (byte) (T[g & 0x1f] ^ x1);
- T[(g + 1) & 0x1f] = (byte) (T[(g + 1) & 0x1f] ^ x2);
- T[(g + 2) & 0x1f] = (byte) (T[(g + 2) & 0x1f] ^ x3);
- T[(g + 3) & 0x1f] = (byte) (T[(g + 3) & 0x1f] ^ x4);
- g = (byte) ((g + 4) & 0x1f);
-
- byte temp = P[n & 0xff];
- P[n & 0xff] = P[s & 0xff];
- P[s & 0xff] = temp;
- n = (byte) ((n + 1) & 0xff);
- }
-
- public void update(byte[] in, int inOff, int len)
- throws DataLengthException, IllegalStateException
- {
- if ((inOff + len) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- for (int i = 0; i < len; i++)
- {
- update(in[i]);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/AEADBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/AEADBlockCipher.java
deleted file mode 100644
index fe461196..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/AEADBlockCipher.java
+++ /dev/null
@@ -1,146 +0,0 @@
-package org.bouncycastle.crypto.modes;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-
-/**
- * A block cipher mode that includes authenticated encryption with a streaming mode and optional associated data.
- * <p>
- * Implementations of this interface may operate in a packet mode (where all input data is buffered and
- * processed dugin the call to {@link #doFinal(byte[], int)}), or in a streaming mode (where output data is
- * incrementally produced with each call to {@link #processByte(byte, byte[], int)} or
- * {@link #processBytes(byte[], int, int, byte[], int)}.
- * </p>
- * This is important to consider during decryption: in a streaming mode, unauthenticated plaintext data
- * may be output prior to the call to {@link #doFinal(byte[], int)} that results in an authentication
- * failure. The higher level protocol utilising this cipher must ensure the plaintext data is handled
- * appropriately until the end of data is reached and the entire ciphertext is authenticated.
- * @see org.bouncycastle.crypto.params.AEADParameters
- */
-public interface AEADBlockCipher
-{
- /**
- * initialise the underlying cipher. Parameter can either be an AEADParameters or a ParametersWithIV object.
- *
- * @param forEncryption true if we are setting up for encryption, false otherwise.
- * @param params the necessary parameters for the underlying cipher to be initialised.
- * @exception IllegalArgumentException if the params argument is inappropriate.
- */
- public void init(boolean forEncryption, CipherParameters params)
- throws IllegalArgumentException;
-
- /**
- * Return the name of the algorithm.
- *
- * @return the algorithm name.
- */
- public String getAlgorithmName();
-
- /**
- * return the cipher this object wraps.
- *
- * @return the cipher this object wraps.
- */
- public BlockCipher getUnderlyingCipher();
-
- /**
- * Add a single byte to the associated data check.
- * <br>If the implementation supports it, this will be an online operation and will not retain the associated data.
- *
- * @param in the byte to be processed.
- */
- public void processAADByte(byte in);
-
- /**
- * Add a sequence of bytes to the associated data check.
- * <br>If the implementation supports it, this will be an online operation and will not retain the associated data.
- *
- * @param in the input byte array.
- * @param inOff the offset into the in array where the data to be processed starts.
- * @param len the number of bytes to be processed.
- */
- public void processAADBytes(byte[] in, int inOff, int len);
-
- /**
- * encrypt/decrypt a single byte.
- *
- * @param in the byte to be processed.
- * @param out the output buffer the processed byte goes into.
- * @param outOff the offset into the output byte array the processed data starts at.
- * @return the number of bytes written to out.
- * @exception DataLengthException if the output buffer is too small.
- */
- public int processByte(byte in, byte[] out, int outOff)
- throws DataLengthException;
-
- /**
- * process a block of bytes from in putting the result into out.
- *
- * @param in the input byte array.
- * @param inOff the offset into the in array where the data to be processed starts.
- * @param len the number of bytes to be processed.
- * @param out the output buffer the processed bytes go into.
- * @param outOff the offset into the output byte array the processed data starts at.
- * @return the number of bytes written to out.
- * @exception DataLengthException if the output buffer is too small.
- */
- public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
- throws DataLengthException;
-
- /**
- * Finish the operation either appending or verifying the MAC at the end of the data.
- *
- * @param out space for any resulting output data.
- * @param outOff offset into out to start copying the data at.
- * @return number of bytes written into out.
- * @throws IllegalStateException if the cipher is in an inappropriate state.
- * @throws org.bouncycastle.crypto.InvalidCipherTextException if the MAC fails to match.
- */
- public int doFinal(byte[] out, int outOff)
- throws IllegalStateException, InvalidCipherTextException;
-
- /**
- * Return the value of the MAC associated with the last stream processed.
- *
- * @return MAC for plaintext data.
- */
- public byte[] getMac();
-
- /**
- * return the size of the output buffer required for a processBytes
- * an input of len bytes.
- * <p>
- * The returned size may be dependent on the initialisation of this cipher
- * and may not be accurate once subsequent input data is processed - this method
- * should be invoked immediately prior to input data being processed.
- * </p>
- *
- * @param len the length of the input.
- * @return the space required to accommodate a call to processBytes
- * with len bytes of input.
- */
- public int getUpdateOutputSize(int len);
-
- /**
- * return the size of the output buffer required for a processBytes plus a
- * doFinal with an input of len bytes.
- * <p>
- * The returned size may be dependent on the initialisation of this cipher
- * and may not be accurate once subsequent input data is processed - this method
- * should be invoked immediately prior to a call to final processing of input data
- * and a call to {@link #doFinal(byte[], int)}.
- * </p>
- * @param len the length of the input.
- * @return the space required to accommodate a call to processBytes and doFinal
- * with len bytes of input.
- */
- public int getOutputSize(int len);
-
- /**
- * Reset the cipher. After resetting the cipher is in the same state
- * as it was after the last init (if there was one).
- */
- public void reset();
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/CBCBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/CBCBlockCipher.java
deleted file mode 100644
index d4800e62..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/CBCBlockCipher.java
+++ /dev/null
@@ -1,253 +0,0 @@
-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.ParametersWithIV;
-import org.bouncycastle.util.Arrays;
-
-/**
- * implements Cipher-Block-Chaining (CBC) mode on top of a simple cipher.
- */
-public class CBCBlockCipher
- implements BlockCipher
-{
- private byte[] IV;
- private byte[] cbcV;
- private byte[] cbcNextV;
-
- private int blockSize;
- private BlockCipher cipher = null;
- private boolean encrypting;
-
- /**
- * Basic constructor.
- *
- * @param cipher the block cipher to be used as the basis of chaining.
- */
- public CBCBlockCipher(
- BlockCipher cipher)
- {
- this.cipher = cipher;
- this.blockSize = cipher.getBlockSize();
-
- this.IV = new byte[blockSize];
- this.cbcV = new byte[blockSize];
- this.cbcNextV = new byte[blockSize];
- }
-
- /**
- * return the underlying block cipher that we are wrapping.
- *
- * @return the underlying block cipher that we are wrapping.
- */
- public BlockCipher getUnderlyingCipher()
- {
- return cipher;
- }
-
- /**
- * Initialise the cipher and, possibly, the initialisation vector (IV).
- * If an IV isn't passed as part of the parameter, the IV will be all zeros.
- *
- * @param encrypting if true the cipher is initialised for
- * encryption, if false for decryption.
- * @param params the key and other data required by the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean encrypting,
- CipherParameters params)
- throws IllegalArgumentException
- {
- boolean oldEncrypting = this.encrypting;
-
- this.encrypting = encrypting;
-
- if (params instanceof ParametersWithIV)
- {
- ParametersWithIV ivParam = (ParametersWithIV)params;
- byte[] iv = ivParam.getIV();
-
- if (iv.length != blockSize)
- {
- throw new IllegalArgumentException("initialisation vector must be the same length as block size");
- }
-
- System.arraycopy(iv, 0, IV, 0, iv.length);
-
- reset();
-
- // if null it's an IV changed only.
- if (ivParam.getParameters() != null)
- {
- cipher.init(encrypting, ivParam.getParameters());
- }
- else if (oldEncrypting != encrypting)
- {
- throw new IllegalArgumentException("cannot change encrypting state without providing key.");
- }
- }
- else
- {
- reset();
-
- // if it's null, key is to be reused.
- if (params != null)
- {
- cipher.init(encrypting, params);
- }
- else if (oldEncrypting != encrypting)
- {
- throw new IllegalArgumentException("cannot change encrypting state without providing key.");
- }
- }
- }
-
- /**
- * return the algorithm name and mode.
- *
- * @return the name of the underlying algorithm followed by "/CBC".
- */
- public String getAlgorithmName()
- {
- return cipher.getAlgorithmName() + "/CBC";
- }
-
- /**
- * return the block size of the underlying cipher.
- *
- * @return the block size of the underlying cipher.
- */
- public int getBlockSize()
- {
- return cipher.getBlockSize();
- }
-
- /**
- * Process one block of input from the array in and write it to
- * the out array.
- *
- * @param in the array containing the input data.
- * @param inOff offset into the in array the data starts at.
- * @param out the array the output data will be copied into.
- * @param outOff the offset into the out array the output will start at.
- * @exception DataLengthException if there isn't enough data in in, or
- * space in out.
- * @exception IllegalStateException if the cipher isn't initialised.
- * @return the number of bytes processed and produced.
- */
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- throws DataLengthException, IllegalStateException
- {
- return (encrypting) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff);
- }
-
- /**
- * reset the chaining vector back to the IV and reset the underlying
- * cipher.
- */
- public void reset()
- {
- System.arraycopy(IV, 0, cbcV, 0, IV.length);
- Arrays.fill(cbcNextV, (byte)0);
-
- cipher.reset();
- }
-
- /**
- * Do the appropriate chaining step for CBC mode encryption.
- *
- * @param in the array containing the data to be encrypted.
- * @param inOff offset into the in array the data starts at.
- * @param out the array the encrypted data will be copied into.
- * @param outOff the offset into the out array the output will start at.
- * @exception DataLengthException if there isn't enough data in in, or
- * space in out.
- * @exception IllegalStateException if the cipher isn't initialised.
- * @return the number of bytes processed and produced.
- */
- private int encryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- throws DataLengthException, IllegalStateException
- {
- if ((inOff + blockSize) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- /*
- * XOR the cbcV and the input,
- * then encrypt the cbcV
- */
- for (int i = 0; i < blockSize; i++)
- {
- cbcV[i] ^= in[inOff + i];
- }
-
- int length = cipher.processBlock(cbcV, 0, out, outOff);
-
- /*
- * copy ciphertext to cbcV
- */
- System.arraycopy(out, outOff, cbcV, 0, cbcV.length);
-
- return length;
- }
-
- /**
- * Do the appropriate chaining step for CBC mode decryption.
- *
- * @param in the array containing the data to be decrypted.
- * @param inOff offset into the in array the data starts at.
- * @param out the array the decrypted data will be copied into.
- * @param outOff the offset into the out array the output will start at.
- * @exception DataLengthException if there isn't enough data in in, or
- * space in out.
- * @exception IllegalStateException if the cipher isn't initialised.
- * @return the number of bytes processed and produced.
- */
- private int decryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- throws DataLengthException, IllegalStateException
- {
- if ((inOff + blockSize) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- System.arraycopy(in, inOff, cbcNextV, 0, blockSize);
-
- int length = cipher.processBlock(in, inOff, out, outOff);
-
- /*
- * XOR the cbcV and the output
- */
- for (int i = 0; i < blockSize; i++)
- {
- out[outOff + i] ^= cbcV[i];
- }
-
- /*
- * swap the back up buffer into next position
- */
- byte[] tmp;
-
- tmp = cbcV;
- cbcV = cbcNextV;
- cbcNextV = tmp;
-
- return length;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java
deleted file mode 100644
index 7f870ca2..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java
+++ /dev/null
@@ -1,457 +0,0 @@
-package org.bouncycastle.crypto.modes;
-
-import java.io.ByteArrayOutputStream;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.OutputLengthException;
-import org.bouncycastle.crypto.macs.CBCBlockCipherMac;
-import org.bouncycastle.crypto.params.AEADParameters;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Arrays;
-
-/**
- * Implements the Counter with Cipher Block Chaining mode (CCM) detailed in
- * NIST Special Publication 800-38C.
- * <p>
- * <b>Note</b>: this mode is a packet mode - it needs all the data up front.
- */
-public class CCMBlockCipher
- implements AEADBlockCipher
-{
- private BlockCipher cipher;
- private int blockSize;
- private boolean forEncryption;
- private byte[] nonce;
- private byte[] initialAssociatedText;
- private int macSize;
- private CipherParameters keyParam;
- private byte[] macBlock;
- private ExposedByteArrayOutputStream associatedText = new ExposedByteArrayOutputStream();
- private ExposedByteArrayOutputStream data = new ExposedByteArrayOutputStream();
-
- /**
- * Basic constructor.
- *
- * @param c the block cipher to be used.
- */
- public CCMBlockCipher(BlockCipher c)
- {
- this.cipher = c;
- this.blockSize = c.getBlockSize();
- this.macBlock = new byte[blockSize];
-
- if (blockSize != 16)
- {
- throw new IllegalArgumentException("cipher required with a block size of 16.");
- }
- }
-
- /**
- * return the underlying block cipher that we are wrapping.
- *
- * @return the underlying block cipher that we are wrapping.
- */
- public BlockCipher getUnderlyingCipher()
- {
- return cipher;
- }
-
-
- public void init(boolean forEncryption, CipherParameters params)
- throws IllegalArgumentException
- {
- this.forEncryption = forEncryption;
-
- CipherParameters cipherParameters;
- if (params instanceof AEADParameters)
- {
- AEADParameters param = (AEADParameters)params;
-
- nonce = param.getNonce();
- initialAssociatedText = param.getAssociatedText();
- macSize = param.getMacSize() / 8;
- cipherParameters = param.getKey();
- }
- else if (params instanceof ParametersWithIV)
- {
- ParametersWithIV param = (ParametersWithIV)params;
-
- nonce = param.getIV();
- initialAssociatedText = null;
- macSize = macBlock.length / 2;
- 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()
- {
- return cipher.getAlgorithmName() + "/CCM";
- }
-
- public void processAADByte(byte in)
- {
- associatedText.write(in);
- }
-
- public void processAADBytes(byte[] in, int inOff, int len)
- {
- // TODO: Process AAD online
- associatedText.write(in, inOff, len);
- }
-
- public int processByte(byte in, byte[] out, int outOff)
- throws DataLengthException, IllegalStateException
- {
- data.write(in);
-
- return 0;
- }
-
- public int processBytes(byte[] in, int inOff, int inLen, byte[] out, int outOff)
- throws DataLengthException, IllegalStateException
- {
- if (in.length < (inOff + inLen))
- {
- throw new DataLengthException("Input buffer too short");
- }
- data.write(in, inOff, inLen);
-
- return 0;
- }
-
- public int doFinal(byte[] out, int outOff)
- throws IllegalStateException, InvalidCipherTextException
- {
- int len = processPacket(data.getBuffer(), 0, data.size(), out, outOff);
-
- reset();
-
- return len;
- }
-
- public void reset()
- {
- cipher.reset();
- associatedText.reset();
- data.reset();
- }
-
- /**
- * Returns a byte array containing the mac calculated as part of the
- * last encrypt or decrypt operation.
- *
- * @return the last mac calculated.
- */
- public byte[] getMac()
- {
- byte[] mac = new byte[macSize];
-
- System.arraycopy(macBlock, 0, mac, 0, mac.length);
-
- return mac;
- }
-
- public int getUpdateOutputSize(int len)
- {
- return 0;
- }
-
- public int getOutputSize(int len)
- {
- int totalData = len + data.size();
-
- if (forEncryption)
- {
- return totalData + macSize;
- }
-
- 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)
- {
- throw new IllegalStateException("CCM cipher unitialized.");
- }
-
- int n = nonce.length;
- int q = 15 - n;
- if (q < 4)
- {
- int limitLen = 1 << (8 * q);
- if (inLen >= limitLen)
- {
- throw new IllegalStateException("CCM packet too large for choice of q.");
- }
- }
-
- byte[] iv = new byte[blockSize];
- iv[0] = (byte)((q - 1) & 0x7);
- System.arraycopy(nonce, 0, iv, 1, nonce.length);
-
- BlockCipher ctrCipher = new SICBlockCipher(cipher);
- ctrCipher.init(forEncryption, new ParametersWithIV(keyParam, iv));
-
- int outputLen;
- int inIndex = inOff;
- int outIndex = outOff;
-
- if (forEncryption)
- {
- outputLen = inLen + macSize;
- if (output.length < (outputLen + outOff))
- {
- throw new OutputLengthException("Output buffer too short.");
- }
-
- calculateMac(in, inOff, inLen, macBlock);
-
- ctrCipher.processBlock(macBlock, 0, macBlock, 0); // S0
-
- while (inIndex < (inOff + inLen - blockSize)) // S1...
- {
- ctrCipher.processBlock(in, inIndex, output, outIndex);
- outIndex += blockSize;
- inIndex += blockSize;
- }
-
- byte[] block = new byte[blockSize];
-
- System.arraycopy(in, inIndex, block, 0, inLen + inOff - inIndex);
-
- ctrCipher.processBlock(block, 0, block, 0);
-
- System.arraycopy(block, 0, output, outIndex, inLen + inOff - inIndex);
-
- System.arraycopy(macBlock, 0, output, outOff + inLen, macSize);
- }
- else
- {
- if (inLen < macSize)
- {
- throw new InvalidCipherTextException("data too short");
- }
- outputLen = inLen - macSize;
- if (output.length < (outputLen + outOff))
- {
- throw new OutputLengthException("Output buffer too short.");
- }
-
- System.arraycopy(in, inOff + outputLen, macBlock, 0, macSize);
-
- ctrCipher.processBlock(macBlock, 0, macBlock, 0);
-
- for (int i = macSize; i != macBlock.length; i++)
- {
- macBlock[i] = 0;
- }
-
- while (inIndex < (inOff + outputLen - blockSize))
- {
- ctrCipher.processBlock(in, inIndex, output, outIndex);
- outIndex += blockSize;
- inIndex += blockSize;
- }
-
- byte[] block = new byte[blockSize];
-
- System.arraycopy(in, inIndex, block, 0, outputLen - (inIndex - inOff));
-
- ctrCipher.processBlock(block, 0, block, 0);
-
- System.arraycopy(block, 0, output, outIndex, outputLen - (inIndex - inOff));
-
- byte[] calculatedMacBlock = new byte[blockSize];
-
- calculateMac(output, outOff, outputLen, calculatedMacBlock);
-
- if (!Arrays.constantTimeAreEqual(macBlock, calculatedMacBlock))
- {
- throw new InvalidCipherTextException("mac check in CCM failed");
- }
- }
-
- return outputLen;
- }
-
- private int calculateMac(byte[] data, int dataOff, int dataLen, byte[] macBlock)
- {
- Mac cMac = new CBCBlockCipherMac(cipher, macSize * 8);
-
- cMac.init(keyParam);
-
- //
- // build b0
- //
- byte[] b0 = new byte[16];
-
- if (hasAssociatedText())
- {
- b0[0] |= 0x40;
- }
-
- b0[0] |= (((cMac.getMacSize() - 2) / 2) & 0x7) << 3;
-
- b0[0] |= ((15 - nonce.length) - 1) & 0x7;
-
- System.arraycopy(nonce, 0, b0, 1, nonce.length);
-
- int q = dataLen;
- int count = 1;
- while (q > 0)
- {
- b0[b0.length - count] = (byte)(q & 0xff);
- q >>>= 8;
- count++;
- }
-
- cMac.update(b0, 0, b0.length);
-
- //
- // process associated text
- //
- if (hasAssociatedText())
- {
- int extra;
-
- int textLength = getAssociatedTextLength();
- if (textLength < ((1 << 16) - (1 << 8)))
- {
- cMac.update((byte)(textLength >> 8));
- cMac.update((byte)textLength);
-
- extra = 2;
- }
- else // can't go any higher than 2^32
- {
- cMac.update((byte)0xff);
- cMac.update((byte)0xfe);
- cMac.update((byte)(textLength >> 24));
- cMac.update((byte)(textLength >> 16));
- cMac.update((byte)(textLength >> 8));
- cMac.update((byte)textLength);
-
- extra = 6;
- }
-
- if (initialAssociatedText != null)
- {
- cMac.update(initialAssociatedText, 0, initialAssociatedText.length);
- }
- if (associatedText.size() > 0)
- {
- cMac.update(associatedText.getBuffer(), 0, associatedText.size());
- }
-
- extra = (extra + textLength) % 16;
- if (extra != 0)
- {
- for (int i = extra; i != 16; i++)
- {
- cMac.update((byte)0x00);
- }
- }
- }
-
- //
- // add the text
- //
- cMac.update(data, dataOff, dataLen);
-
- return cMac.doFinal(macBlock, 0);
- }
-
- private int getAssociatedTextLength()
- {
- return associatedText.size() + ((initialAssociatedText == null) ? 0 : initialAssociatedText.length);
- }
-
- private boolean hasAssociatedText()
- {
- return getAssociatedTextLength() > 0;
- }
-
- private class ExposedByteArrayOutputStream
- extends ByteArrayOutputStream
- {
- public ExposedByteArrayOutputStream()
- {
- }
-
- public byte[] getBuffer()
- {
- return this.buf;
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java
deleted file mode 100644
index 6167d256..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java
+++ /dev/null
@@ -1,269 +0,0 @@
-package org.bouncycastle.crypto.modes;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.StreamBlockCipher;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Arrays;
-
-/**
- * implements a Cipher-FeedBack (CFB) mode on top of a simple cipher.
- */
-public class CFBBlockCipher
- extends StreamBlockCipher
-{
- private byte[] IV;
- private byte[] cfbV;
- private byte[] cfbOutV;
- private byte[] inBuf;
-
- private int blockSize;
- private BlockCipher cipher = null;
- private boolean encrypting;
- private int byteCount;
-
- /**
- * Basic constructor.
- *
- * @param cipher the block cipher to be used as the basis of the
- * feedback mode.
- * @param bitBlockSize the block size in bits (note: a multiple of 8)
- */
- public CFBBlockCipher(
- BlockCipher cipher,
- int bitBlockSize)
- {
- super(cipher);
-
- this.cipher = cipher;
- this.blockSize = bitBlockSize / 8;
-
- this.IV = new byte[cipher.getBlockSize()];
- this.cfbV = new byte[cipher.getBlockSize()];
- this.cfbOutV = new byte[cipher.getBlockSize()];
- this.inBuf = new byte[blockSize];
- }
-
- /**
- * Initialise the cipher and, possibly, the initialisation vector (IV).
- * If an IV isn't passed as part of the parameter, the IV will be all zeros.
- * An IV which is too short is handled in FIPS compliant fashion.
- *
- * @param encrypting if true the cipher is initialised for
- * encryption, if false for decryption.
- * @param params the key and other data required by the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean encrypting,
- CipherParameters params)
- throws IllegalArgumentException
- {
- this.encrypting = encrypting;
-
- if (params instanceof ParametersWithIV)
- {
- ParametersWithIV ivParam = (ParametersWithIV)params;
- byte[] iv = ivParam.getIV();
-
- if (iv.length < IV.length)
- {
- // prepend the supplied IV with zeros (per FIPS PUB 81)
- System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
- for (int i = 0; i < IV.length - iv.length; i++)
- {
- IV[i] = 0;
- }
- }
- else
- {
- System.arraycopy(iv, 0, IV, 0, IV.length);
- }
-
- reset();
-
- // if null it's an IV changed only.
- if (ivParam.getParameters() != null)
- {
- cipher.init(true, ivParam.getParameters());
- }
- }
- else
- {
- reset();
-
- // if it's null, key is to be reused.
- if (params != null)
- {
- cipher.init(true, params);
- }
- }
- }
-
- /**
- * return the algorithm name and mode.
- *
- * @return the name of the underlying algorithm followed by "/CFB"
- * and the block size in bits.
- */
- public String getAlgorithmName()
- {
- return cipher.getAlgorithmName() + "/CFB" + (blockSize * 8);
- }
-
- protected byte calculateByte(byte in)
- throws DataLengthException, IllegalStateException
- {
- return (encrypting) ? encryptByte(in) : decryptByte(in);
- }
-
- private byte encryptByte(byte in)
- {
- if (byteCount == 0)
- {
- cipher.processBlock(cfbV, 0, cfbOutV, 0);
- }
-
- byte rv = (byte)(cfbOutV[byteCount] ^ in);
- inBuf[byteCount++] = rv;
-
- if (byteCount == blockSize)
- {
- byteCount = 0;
-
- System.arraycopy(cfbV, blockSize, cfbV, 0, cfbV.length - blockSize);
- System.arraycopy(inBuf, 0, cfbV, cfbV.length - blockSize, blockSize);
- }
-
- return rv;
- }
-
- private byte decryptByte(byte in)
- {
- if (byteCount == 0)
- {
- cipher.processBlock(cfbV, 0, cfbOutV, 0);
- }
-
- inBuf[byteCount] = in;
- byte rv = (byte)(cfbOutV[byteCount++] ^ in);
-
- if (byteCount == blockSize)
- {
- byteCount = 0;
-
- System.arraycopy(cfbV, blockSize, cfbV, 0, cfbV.length - blockSize);
- System.arraycopy(inBuf, 0, cfbV, cfbV.length - blockSize, blockSize);
- }
-
- return rv;
- }
-
- /**
- * return the block size we are operating at.
- *
- * @return the block size we are operating at (in bytes).
- */
- public int getBlockSize()
- {
- return blockSize;
- }
-
- /**
- * Process one block of input from the array in and write it to
- * the out array.
- *
- * @param in the array containing the input data.
- * @param inOff offset into the in array the data starts at.
- * @param out the array the output data will be copied into.
- * @param outOff the offset into the out array the output will start at.
- * @exception DataLengthException if there isn't enough data in in, or
- * space in out.
- * @exception IllegalStateException if the cipher isn't initialised.
- * @return the number of bytes processed and produced.
- */
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- throws DataLengthException, IllegalStateException
- {
- processBytes(in, inOff, blockSize, out, outOff);
-
- return blockSize;
- }
-
- /**
- * Do the appropriate processing for CFB mode encryption.
- *
- * @param in the array containing the data to be encrypted.
- * @param inOff offset into the in array the data starts at.
- * @param out the array the encrypted data will be copied into.
- * @param outOff the offset into the out array the output will start at.
- * @exception DataLengthException if there isn't enough data in in, or
- * space in out.
- * @exception IllegalStateException if the cipher isn't initialised.
- * @return the number of bytes processed and produced.
- */
- public int encryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- throws DataLengthException, IllegalStateException
- {
- processBytes(in, inOff, blockSize, out, outOff);
-
- return blockSize;
- }
-
- /**
- * Do the appropriate processing for CFB mode decryption.
- *
- * @param in the array containing the data to be decrypted.
- * @param inOff offset into the in array the data starts at.
- * @param out the array the encrypted data will be copied into.
- * @param outOff the offset into the out array the output will start at.
- * @exception DataLengthException if there isn't enough data in in, or
- * space in out.
- * @exception IllegalStateException if the cipher isn't initialised.
- * @return the number of bytes processed and produced.
- */
- public int decryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- throws DataLengthException, IllegalStateException
- {
- processBytes(in, inOff, blockSize, out, outOff);
-
- return blockSize;
- }
-
- /**
- * 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.
- */
- public void reset()
- {
- System.arraycopy(IV, 0, cfbV, 0, IV.length);
- Arrays.fill(inBuf, (byte)0);
- byteCount = 0;
-
- cipher.reset();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java
deleted file mode 100644
index 5388b407..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java
+++ /dev/null
@@ -1,287 +0,0 @@
-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.
- */
-public class CTSBlockCipher
- 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 CTSBlockCipher(
- BlockCipher cipher)
- {
- 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");
- }
-
- 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 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 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 DataLengthException if there is insufficient space in out for
- * the output.
- * @exception IllegalStateException if the underlying cipher is not
- * initialised.
- * @exception 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)
- {
- if (bufOff < blockSize)
- {
- throw new DataLengthException("need at least one block of input for CTS");
- }
-
- cipher.processBlock(buf, 0, block, 0);
-
- if (bufOff > blockSize)
- {
- 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
- {
- System.arraycopy(block, 0, out, outOff, blockSize);
- }
- }
- else
- {
- if (bufOff < blockSize)
- {
- throw new DataLengthException("need at least one block of input for CTS");
- }
-
- byte[] lastBlock = new byte[blockSize];
-
- if (bufOff > 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);
- }
- else
- {
- cipher.processBlock(buf, 0, block, 0);
-
- System.arraycopy(block, 0, out, outOff, blockSize);
- }
- }
-
- int offset = bufOff;
-
- reset();
-
- return offset;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/EAXBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/EAXBlockCipher.java
deleted file mode 100644
index 209d5cdb..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/EAXBlockCipher.java
+++ /dev/null
@@ -1,387 +0,0 @@
-package org.bouncycastle.crypto.modes;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.OutputLengthException;
-import org.bouncycastle.crypto.macs.CMac;
-import org.bouncycastle.crypto.params.AEADParameters;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Arrays;
-
-/**
- * A Two-Pass Authenticated-Encryption Scheme Optimized for Simplicity and
- * Efficiency - by M. Bellare, P. Rogaway, D. Wagner.
- *
- * http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf
- *
- * EAX is an AEAD scheme based on CTR and OMAC1/CMAC, that uses a single block
- * cipher to encrypt and authenticate data. It's on-line (the length of a
- * message isn't needed to begin processing it), has good performances, it's
- * simple and provably secure (provided the underlying block cipher is secure).
- *
- * Of course, this implementations is NOT thread-safe.
- */
-public class EAXBlockCipher
- implements AEADBlockCipher
-{
- private static final byte nTAG = 0x0;
-
- private static final byte hTAG = 0x1;
-
- private static final byte cTAG = 0x2;
-
- private SICBlockCipher cipher;
-
- private boolean forEncryption;
-
- private int blockSize;
-
- private Mac mac;
-
- private byte[] nonceMac;
- private byte[] associatedTextMac;
- private byte[] macBlock;
-
- private int macSize;
- private byte[] bufBlock;
- private int bufOff;
-
- private boolean cipherInitialized;
- private byte[] initialAssociatedText;
-
- /**
- * Constructor that accepts an instance of a block cipher engine.
- *
- * @param cipher the engine to use
- */
- public EAXBlockCipher(BlockCipher cipher)
- {
- blockSize = cipher.getBlockSize();
- mac = new CMac(cipher);
- macBlock = new byte[blockSize];
- associatedTextMac = new byte[mac.getMacSize()];
- nonceMac = new byte[mac.getMacSize()];
- this.cipher = new SICBlockCipher(cipher);
- }
-
- public String getAlgorithmName()
- {
- return cipher.getUnderlyingCipher().getAlgorithmName() + "/EAX";
- }
-
- public BlockCipher getUnderlyingCipher()
- {
- return cipher.getUnderlyingCipher();
- }
-
- public int getBlockSize()
- {
- return cipher.getBlockSize();
- }
-
- public void init(boolean forEncryption, CipherParameters params)
- throws IllegalArgumentException
- {
- this.forEncryption = forEncryption;
-
- byte[] nonce;
- CipherParameters keyParam;
-
- if (params instanceof AEADParameters)
- {
- AEADParameters param = (AEADParameters)params;
-
- nonce = param.getNonce();
- initialAssociatedText = param.getAssociatedText();
- macSize = param.getMacSize() / 8;
- keyParam = param.getKey();
- }
- else if (params instanceof ParametersWithIV)
- {
- ParametersWithIV param = (ParametersWithIV)params;
-
- nonce = param.getIV();
- initialAssociatedText = null;
- macSize = mac.getMacSize() / 2;
- keyParam = param.getParameters();
- }
- else
- {
- throw new IllegalArgumentException("invalid parameters passed to EAX");
- }
-
- bufBlock = new byte[forEncryption ? blockSize : (blockSize + macSize)];
-
- byte[] tag = new byte[blockSize];
-
- // Key reuse implemented in CBC mode of underlying CMac
- mac.init(keyParam);
-
- tag[blockSize - 1] = nTAG;
- mac.update(tag, 0, blockSize);
- mac.update(nonce, 0, nonce.length);
- mac.doFinal(nonceMac, 0);
-
- // Same BlockCipher underlies this and the mac, so reuse last key on cipher
- cipher.init(true, new ParametersWithIV(null, nonceMac));
-
- reset();
- }
-
- private void initCipher()
- {
- if (cipherInitialized)
- {
- return;
- }
-
- cipherInitialized = true;
-
- mac.doFinal(associatedTextMac, 0);
-
- byte[] tag = new byte[blockSize];
- tag[blockSize - 1] = cTAG;
- mac.update(tag, 0, blockSize);
- }
-
- private void calculateMac()
- {
- byte[] outC = new byte[blockSize];
- mac.doFinal(outC, 0);
-
- for (int i = 0; i < macBlock.length; i++)
- {
- macBlock[i] = (byte)(nonceMac[i] ^ associatedTextMac[i] ^ outC[i]);
- }
- }
-
- public void reset()
- {
- reset(true);
- }
-
- private void reset(
- boolean clearMac)
- {
- cipher.reset(); // TODO Redundant since the mac will reset it?
- mac.reset();
-
- bufOff = 0;
- Arrays.fill(bufBlock, (byte)0);
-
- if (clearMac)
- {
- Arrays.fill(macBlock, (byte)0);
- }
-
- byte[] tag = new byte[blockSize];
- tag[blockSize - 1] = hTAG;
- mac.update(tag, 0, blockSize);
-
- cipherInitialized = false;
-
- if (initialAssociatedText != null)
- {
- processAADBytes(initialAssociatedText, 0, initialAssociatedText.length);
- }
- }
-
- public void processAADByte(byte in)
- {
- if (cipherInitialized)
- {
- throw new IllegalStateException("AAD data cannot be added after encryption/decription processing has begun.");
- }
- mac.update(in);
- }
-
- public void processAADBytes(byte[] in, int inOff, int len)
- {
- if (cipherInitialized)
- {
- throw new IllegalStateException("AAD data cannot be added after encryption/decryption processing has begun.");
- }
- mac.update(in, inOff, len);
- }
-
- public int processByte(byte in, byte[] out, int outOff)
- throws DataLengthException
- {
- initCipher();
-
- return process(in, out, outOff);
- }
-
- public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
- throws DataLengthException
- {
- initCipher();
-
- if (in.length < (inOff + len))
- {
- throw new DataLengthException("Input buffer too short");
- }
-
- int resultLen = 0;
-
- for (int i = 0; i != len; i++)
- {
- resultLen += process(in[inOff + i], out, outOff + resultLen);
- }
-
- return resultLen;
- }
-
- public int doFinal(byte[] out, int outOff)
- throws IllegalStateException, InvalidCipherTextException
- {
- initCipher();
-
- int extra = bufOff;
- byte[] tmp = new byte[bufBlock.length];
-
- bufOff = 0;
-
- if (forEncryption)
- {
- if (out.length < (outOff + extra + macSize))
- {
- throw new OutputLengthException("Output buffer too short");
- }
- cipher.processBlock(bufBlock, 0, tmp, 0);
-
- System.arraycopy(tmp, 0, out, outOff, extra);
-
- mac.update(tmp, 0, extra);
-
- calculateMac();
-
- System.arraycopy(macBlock, 0, out, outOff + extra, macSize);
-
- reset(false);
-
- return extra + macSize;
- }
- else
- {
- if (out.length < (outOff + extra - macSize))
- {
- throw new OutputLengthException("Output buffer too short");
- }
- if (extra < macSize)
- {
- throw new InvalidCipherTextException("data too short");
- }
- if (extra > macSize)
- {
- mac.update(bufBlock, 0, extra - macSize);
-
- cipher.processBlock(bufBlock, 0, tmp, 0);
-
- System.arraycopy(tmp, 0, out, outOff, extra - macSize);
- }
-
- calculateMac();
-
- if (!verifyMac(bufBlock, extra - macSize))
- {
- throw new InvalidCipherTextException("mac check in EAX failed");
- }
-
- reset(false);
-
- return extra - macSize;
- }
- }
-
- public byte[] getMac()
- {
- byte[] mac = new byte[macSize];
-
- System.arraycopy(macBlock, 0, mac, 0, macSize);
-
- return mac;
- }
-
- public int getUpdateOutputSize(int len)
- {
- int totalData = len + bufOff;
- if (!forEncryption)
- {
- if (totalData < macSize)
- {
- return 0;
- }
- totalData -= macSize;
- }
- return totalData - totalData % blockSize;
- }
-
- public int getOutputSize(int len)
- {
- int totalData = len + bufOff;
-
- if (forEncryption)
- {
- return totalData + macSize;
- }
-
- return totalData < macSize ? 0 : totalData - macSize;
- }
-
- private int process(byte b, byte[] out, int outOff)
- {
- bufBlock[bufOff++] = b;
-
- if (bufOff == bufBlock.length)
- {
- if (out.length < (outOff + blockSize))
- {
- throw new OutputLengthException("Output buffer is too short");
- }
- // TODO Could move the processByte(s) calls to here
-// initCipher();
-
- int size;
-
- if (forEncryption)
- {
- size = cipher.processBlock(bufBlock, 0, out, outOff);
-
- mac.update(out, outOff, blockSize);
- }
- else
- {
- mac.update(bufBlock, 0, blockSize);
-
- size = cipher.processBlock(bufBlock, 0, out, outOff);
- }
-
- bufOff = 0;
- if (!forEncryption)
- {
- System.arraycopy(bufBlock, blockSize, bufBlock, 0, macSize);
- bufOff = macSize;
- }
-
- return size;
- }
-
- return 0;
- }
-
- private boolean verifyMac(byte[] mac, int off)
- {
- int nonEqual = 0;
-
- for (int i = 0; i < macSize; i++)
- {
- nonEqual |= (macBlock[i] ^ mac[off + i]);
- }
-
- return nonEqual == 0;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/GCFBBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/GCFBBlockCipher.java
deleted file mode 100644
index 5791e89c..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/GCFBBlockCipher.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package org.bouncycastle.crypto.modes;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.StreamBlockCipher;
-import org.bouncycastle.crypto.params.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
- extends StreamBlockCipher
-{
- 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)
- {
- super(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()
- {
- String name = cfbEngine.getAlgorithmName();
- return name.substring(0, name.indexOf('/') - 1) + "/G" + name.substring(name.indexOf('/') + 1);
- }
-
- public int getBlockSize()
- {
- return cfbEngine.getBlockSize();
- }
-
- public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
- throws DataLengthException, IllegalStateException
- {
- this.processBytes(in, inOff, cfbEngine.getBlockSize(), out, outOff);
-
- return cfbEngine.getBlockSize();
- }
-
- protected byte calculateByte(byte b)
- {
- 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);
-
- base.init(true, key);
-
- byte[] iv = cfbEngine.getCurrentIV();
-
- base.processBlock(iv, 0, iv, 0);
-
- cfbEngine.init(forEncryption, new ParametersWithIV(key, iv));
- }
-
- counter++;
-
- return cfbEngine.calculateByte(b);
- }
-
- public void reset()
- {
- counter = 0;
- cfbEngine.reset();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java
deleted file mode 100644
index 024eb860..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java
+++ /dev/null
@@ -1,596 +0,0 @@
-package org.bouncycastle.crypto.modes;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.OutputLengthException;
-import org.bouncycastle.crypto.modes.gcm.GCMExponentiator;
-import org.bouncycastle.crypto.modes.gcm.GCMMultiplier;
-import org.bouncycastle.crypto.modes.gcm.Tables1kGCMExponentiator;
-import org.bouncycastle.crypto.modes.gcm.Tables8kGCMMultiplier;
-import org.bouncycastle.crypto.params.AEADParameters;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Pack;
-
-/**
- * Implements the Galois/Counter mode (GCM) detailed in
- * NIST Special Publication 800-38D.
- */
-public class GCMBlockCipher
- implements AEADBlockCipher
-{
- private static final int BLOCK_SIZE = 16;
-
- // not final due to a compiler bug
- private BlockCipher cipher;
- private GCMMultiplier multiplier;
- private GCMExponentiator exp;
-
- // These fields are set by init and not modified by processing
- private boolean forEncryption;
- private int macSize;
- private byte[] nonce;
- private byte[] initialAssociatedText;
- private byte[] H;
- private byte[] J0;
-
- // These fields are modified during processing
- private byte[] bufBlock;
- private byte[] macBlock;
- private byte[] S, S_at, S_atPre;
- private byte[] counter;
- private int bufOff;
- private long totalLength;
- private byte[] atBlock;
- private int atBlockPos;
- private long atLength;
- private long atLengthPre;
-
- public GCMBlockCipher(BlockCipher c)
- {
- this(c, null);
- }
-
- public GCMBlockCipher(BlockCipher c, GCMMultiplier m)
- {
- if (c.getBlockSize() != BLOCK_SIZE)
- {
- throw new IllegalArgumentException(
- "cipher required with a block size of " + BLOCK_SIZE + ".");
- }
-
- if (m == null)
- {
- // TODO Consider a static property specifying default multiplier
- m = new Tables8kGCMMultiplier();
- }
-
- this.cipher = c;
- this.multiplier = m;
- }
-
- public BlockCipher getUnderlyingCipher()
- {
- return cipher;
- }
-
- public String getAlgorithmName()
- {
- return cipher.getAlgorithmName() + "/GCM";
- }
-
- /**
- * NOTE: MAC sizes from 32 bits to 128 bits (must be a multiple of 8) are supported. The default is 128 bits.
- * Sizes less than 96 are not recommended, but are supported for specialized applications.
- */
- public void init(boolean forEncryption, CipherParameters params)
- throws IllegalArgumentException
- {
- this.forEncryption = forEncryption;
- this.macBlock = null;
-
- KeyParameter keyParam;
-
- if (params instanceof AEADParameters)
- {
- AEADParameters param = (AEADParameters)params;
-
- nonce = param.getNonce();
- initialAssociatedText = param.getAssociatedText();
-
- int macSizeBits = param.getMacSize();
- if (macSizeBits < 32 || macSizeBits > 128 || macSizeBits % 8 != 0)
- {
- throw new IllegalArgumentException("Invalid value for MAC size: " + macSizeBits);
- }
-
- macSize = macSizeBits / 8;
- keyParam = param.getKey();
- }
- else if (params instanceof ParametersWithIV)
- {
- ParametersWithIV param = (ParametersWithIV)params;
-
- nonce = param.getIV();
- initialAssociatedText = null;
- macSize = 16;
- keyParam = (KeyParameter)param.getParameters();
- }
- else
- {
- throw new IllegalArgumentException("invalid parameters passed to GCM");
- }
-
- int bufLength = forEncryption ? BLOCK_SIZE : (BLOCK_SIZE + macSize);
- this.bufBlock = new byte[bufLength];
-
- if (nonce == null || nonce.length < 1)
- {
- throw new IllegalArgumentException("IV must be at least 1 byte");
- }
-
- // TODO Restrict macSize to 16 if nonce length not 12?
-
- // Cipher always used in forward mode
- // if keyParam is null we're reusing the last key.
- if (keyParam != null)
- {
- cipher.init(true, keyParam);
-
- this.H = new byte[BLOCK_SIZE];
- cipher.processBlock(H, 0, H, 0);
-
- // GCMMultiplier tables don't change unless the key changes (and are expensive to init)
- multiplier.init(H);
- exp = null;
- }
- else if (this.H == null)
- {
- throw new IllegalArgumentException("Key must be specified in initial init");
- }
-
- this.J0 = new byte[BLOCK_SIZE];
-
- if (nonce.length == 12)
- {
- System.arraycopy(nonce, 0, J0, 0, nonce.length);
- this.J0[BLOCK_SIZE - 1] = 0x01;
- }
- else
- {
- gHASH(J0, nonce, nonce.length);
- byte[] X = new byte[BLOCK_SIZE];
- Pack.longToBigEndian((long)nonce.length * 8, X, 8);
- gHASHBlock(J0, X);
- }
-
- this.S = new byte[BLOCK_SIZE];
- this.S_at = new byte[BLOCK_SIZE];
- this.S_atPre = new byte[BLOCK_SIZE];
- this.atBlock = new byte[BLOCK_SIZE];
- this.atBlockPos = 0;
- this.atLength = 0;
- this.atLengthPre = 0;
- this.counter = Arrays.clone(J0);
- this.bufOff = 0;
- this.totalLength = 0;
-
- if (initialAssociatedText != null)
- {
- processAADBytes(initialAssociatedText, 0, initialAssociatedText.length);
- }
- }
-
- public byte[] getMac()
- {
- return Arrays.clone(macBlock);
- }
-
- public int getOutputSize(int len)
- {
- int totalData = len + bufOff;
-
- if (forEncryption)
- {
- return totalData + macSize;
- }
-
- return totalData < macSize ? 0 : totalData - macSize;
- }
-
- public int getUpdateOutputSize(int len)
- {
- int totalData = len + bufOff;
- if (!forEncryption)
- {
- if (totalData < macSize)
- {
- return 0;
- }
- totalData -= macSize;
- }
- return totalData - totalData % BLOCK_SIZE;
- }
-
- public void processAADByte(byte in)
- {
- atBlock[atBlockPos] = in;
- if (++atBlockPos == BLOCK_SIZE)
- {
- // Hash each block as it fills
- gHASHBlock(S_at, atBlock);
- atBlockPos = 0;
- atLength += BLOCK_SIZE;
- }
- }
-
- public void processAADBytes(byte[] in, int inOff, int len)
- {
- for (int i = 0; i < len; ++i)
- {
- atBlock[atBlockPos] = in[inOff + i];
- if (++atBlockPos == BLOCK_SIZE)
- {
- // Hash each block as it fills
- gHASHBlock(S_at, atBlock);
- atBlockPos = 0;
- atLength += BLOCK_SIZE;
- }
- }
- }
-
- private void initCipher()
- {
- if (atLength > 0)
- {
- System.arraycopy(S_at, 0, S_atPre, 0, BLOCK_SIZE);
- atLengthPre = atLength;
- }
-
- // Finish hash for partial AAD block
- if (atBlockPos > 0)
- {
- gHASHPartial(S_atPre, atBlock, 0, atBlockPos);
- atLengthPre += atBlockPos;
- }
-
- if (atLengthPre > 0)
- {
- System.arraycopy(S_atPre, 0, S, 0, BLOCK_SIZE);
- }
- }
-
- public int processByte(byte in, byte[] out, int outOff)
- throws DataLengthException
- {
- bufBlock[bufOff] = in;
- if (++bufOff == bufBlock.length)
- {
- outputBlock(out, outOff);
- return BLOCK_SIZE;
- }
- return 0;
- }
-
- public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
- throws DataLengthException
- {
- if (in.length < (inOff + len))
- {
- throw new DataLengthException("Input buffer too short");
- }
- int resultLen = 0;
-
- for (int i = 0; i < len; ++i)
- {
- bufBlock[bufOff] = in[inOff + i];
- if (++bufOff == bufBlock.length)
- {
- outputBlock(out, outOff + resultLen);
- resultLen += BLOCK_SIZE;
- }
- }
-
- return resultLen;
- }
-
- private void outputBlock(byte[] output, int offset)
- {
- if (output.length < (offset + BLOCK_SIZE))
- {
- throw new OutputLengthException("Output buffer too short");
- }
- if (totalLength == 0)
- {
- initCipher();
- }
- gCTRBlock(bufBlock, output, offset);
- if (forEncryption)
- {
- bufOff = 0;
- }
- else
- {
- System.arraycopy(bufBlock, BLOCK_SIZE, bufBlock, 0, macSize);
- bufOff = macSize;
- }
- }
-
- public int doFinal(byte[] out, int outOff)
- throws IllegalStateException, InvalidCipherTextException
- {
- if (totalLength == 0)
- {
- initCipher();
- }
-
- int extra = bufOff;
- if (!forEncryption)
- {
- if (extra < macSize)
- {
- throw new InvalidCipherTextException("data too short");
- }
- extra -= macSize;
- }
-
- if (extra > 0)
- {
- if (out.length < (outOff + extra))
- {
- throw new OutputLengthException("Output buffer too short");
- }
- gCTRPartial(bufBlock, 0, extra, out, outOff);
- }
-
- atLength += atBlockPos;
-
- if (atLength > atLengthPre)
- {
- /*
- * Some AAD was sent after the cipher started. We determine the difference b/w the hash value
- * we actually used when the cipher started (S_atPre) and the final hash value calculated (S_at).
- * Then we carry this difference forward by multiplying by H^c, where c is the number of (full or
- * partial) cipher-text blocks produced, and adjust the current hash.
- */
-
- // Finish hash for partial AAD block
- if (atBlockPos > 0)
- {
- gHASHPartial(S_at, atBlock, 0, atBlockPos);
- }
-
- // Find the difference between the AAD hashes
- if (atLengthPre > 0)
- {
- xor(S_at, S_atPre);
- }
-
- // Number of cipher-text blocks produced
- long c = ((totalLength * 8) + 127) >>> 7;
-
- // Calculate the adjustment factor
- byte[] H_c = new byte[16];
- if (exp == null)
- {
- exp = new Tables1kGCMExponentiator();
- exp.init(H);
- }
- exp.exponentiateX(c, H_c);
-
- // Carry the difference forward
- multiply(S_at, H_c);
-
- // Adjust the current hash
- xor(S, S_at);
- }
-
- // Final gHASH
- byte[] X = new byte[BLOCK_SIZE];
- Pack.longToBigEndian(atLength * 8, X, 0);
- Pack.longToBigEndian(totalLength * 8, X, 8);
-
- gHASHBlock(S, X);
-
- // T = MSBt(GCTRk(J0,S))
- byte[] tag = new byte[BLOCK_SIZE];
- cipher.processBlock(J0, 0, tag, 0);
- xor(tag, S);
-
- int resultLen = extra;
-
- // We place into macBlock our calculated value for T
- this.macBlock = new byte[macSize];
- System.arraycopy(tag, 0, macBlock, 0, macSize);
-
- if (forEncryption)
- {
- if (out.length < (outOff + extra + macSize))
- {
- throw new OutputLengthException("Output buffer too short");
- }
- // Append T to the message
- System.arraycopy(macBlock, 0, out, outOff + bufOff, macSize);
- resultLen += macSize;
- }
- else
- {
- // Retrieve the T value from the message and compare to calculated one
- byte[] msgMac = new byte[macSize];
- System.arraycopy(bufBlock, extra, msgMac, 0, macSize);
- if (!Arrays.constantTimeAreEqual(this.macBlock, msgMac))
- {
- throw new InvalidCipherTextException("mac check in GCM failed");
- }
- }
-
- reset(false);
-
- return resultLen;
- }
-
- public void reset()
- {
- reset(true);
- }
-
- private void reset(
- boolean clearMac)
- {
- cipher.reset();
-
- S = new byte[BLOCK_SIZE];
- S_at = new byte[BLOCK_SIZE];
- S_atPre = new byte[BLOCK_SIZE];
- atBlock = new byte[BLOCK_SIZE];
- atBlockPos = 0;
- atLength = 0;
- atLengthPre = 0;
- counter = Arrays.clone(J0);
- bufOff = 0;
- totalLength = 0;
-
- if (bufBlock != null)
- {
- Arrays.fill(bufBlock, (byte)0);
- }
-
- if (clearMac)
- {
- macBlock = null;
- }
-
- if (initialAssociatedText != null)
- {
- processAADBytes(initialAssociatedText, 0, initialAssociatedText.length);
- }
- }
-
- private void gCTRBlock(byte[] block, byte[] out, int outOff)
- {
- byte[] tmp = getNextCounterBlock();
-
- xor(tmp, block);
- System.arraycopy(tmp, 0, out, outOff, BLOCK_SIZE);
-
- gHASHBlock(S, forEncryption ? tmp : block);
-
- totalLength += BLOCK_SIZE;
- }
-
- private void gCTRPartial(byte[] buf, int off, int len, byte[] out, int outOff)
- {
- byte[] tmp = getNextCounterBlock();
-
- xor(tmp, buf, off, len);
- System.arraycopy(tmp, 0, out, outOff, len);
-
- gHASHPartial(S, forEncryption ? tmp : buf, 0, len);
-
- totalLength += len;
- }
-
- private void gHASH(byte[] Y, byte[] b, int len)
- {
- for (int pos = 0; pos < len; pos += BLOCK_SIZE)
- {
- int num = Math.min(len - pos, BLOCK_SIZE);
- gHASHPartial(Y, b, pos, num);
- }
- }
-
- private void gHASHBlock(byte[] Y, byte[] b)
- {
- xor(Y, b);
- multiplier.multiplyH(Y);
- }
-
- private void gHASHPartial(byte[] Y, byte[] b, int off, int len)
- {
- xor(Y, b, off, len);
- multiplier.multiplyH(Y);
- }
-
- private byte[] getNextCounterBlock()
- {
- for (int i = 15; i >= 12; --i)
- {
- byte b = (byte)((counter[i] + 1) & 0xff);
- counter[i] = b;
-
- if (b != 0)
- {
- break;
- }
- }
-
- byte[] tmp = new byte[BLOCK_SIZE];
- // TODO Sure would be nice if ciphers could operate on int[]
- cipher.processBlock(counter, 0, tmp, 0);
- return tmp;
- }
-
- private static void multiply(byte[] block, byte[] val)
- {
- byte[] tmp = Arrays.clone(block);
- byte[] c = new byte[16];
-
- for (int i = 0; i < 16; ++i)
- {
- byte bits = val[i];
- for (int j = 7; j >= 0; --j)
- {
- if ((bits & (1 << j)) != 0)
- {
- xor(c, tmp);
- }
-
- boolean lsb = (tmp[15] & 1) != 0;
- shiftRight(tmp);
- if (lsb)
- {
- // R = new byte[]{ 0xe1, ... };
-// xor(v, R);
- tmp[0] ^= (byte)0xe1;
- }
- }
- }
-
- System.arraycopy(c, 0, block, 0, 16);
- }
-
- private static void shiftRight(byte[] block)
- {
- int i = 0;
- int bit = 0;
- for (;;)
- {
- int b = block[i] & 0xff;
- block[i] = (byte) ((b >>> 1) | bit);
- if (++i == 16)
- {
- break;
- }
- bit = (b & 1) << 7;
- }
- }
-
- private static void xor(byte[] block, byte[] val)
- {
- for (int i = 15; i >= 0; --i)
- {
- block[i] ^= val[i];
- }
- }
-
- private static void xor(byte[] block, byte[] val, int off, int len)
- {
- while (len-- > 0)
- {
- block[len] ^= val[off + len];
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/GOFBBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/GOFBBlockCipher.java
deleted file mode 100644
index b025a1b8..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/GOFBBlockCipher.java
+++ /dev/null
@@ -1,228 +0,0 @@
-package org.bouncycastle.crypto.modes;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.StreamBlockCipher;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-/**
- * implements the GOST 28147 OFB counter mode (GCTR).
- */
-public class GOFBBlockCipher
- extends StreamBlockCipher
-{
- private byte[] IV;
- private byte[] ofbV;
- private byte[] ofbOutV;
- private int byteCount;
-
- private final int blockSize;
- private final BlockCipher cipher;
-
- boolean firstStep = true;
- int N3;
- int N4;
- static final int C1 = 16843012; //00000001000000010000000100000100
- static final int C2 = 16843009; //00000001000000010000000100000001
-
-
- /**
- * Basic constructor.
- *
- * @param cipher the block cipher to be used as the basis of the
- * counter mode (must have a 64 bit block size).
- */
- public GOFBBlockCipher(
- BlockCipher cipher)
- {
- super(cipher);
-
- this.cipher = cipher;
- this.blockSize = cipher.getBlockSize();
-
- if (blockSize != 8)
- {
- throw new IllegalArgumentException("GCTR only for 64 bit block ciphers");
- }
-
- this.IV = new byte[cipher.getBlockSize()];
- this.ofbV = new byte[cipher.getBlockSize()];
- this.ofbOutV = new byte[cipher.getBlockSize()];
- }
-
- /**
- * Initialise the cipher and, possibly, the initialisation vector (IV).
- * If an IV isn't passed as part of the parameter, the IV will be all zeros.
- * An IV which is too short is handled in FIPS compliant fashion.
- *
- * @param encrypting if true the cipher is initialised for
- * encryption, if false for decryption.
- * @param params the key and other data required by the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean encrypting, //ignored by this CTR mode
- CipherParameters params)
- throws IllegalArgumentException
- {
- firstStep = true;
- N3 = 0;
- N4 = 0;
-
- if (params instanceof ParametersWithIV)
- {
- ParametersWithIV ivParam = (ParametersWithIV)params;
- byte[] iv = ivParam.getIV();
-
- if (iv.length < IV.length)
- {
- // prepend the supplied IV with zeros (per FIPS PUB 81)
- System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
- for (int i = 0; i < IV.length - iv.length; i++)
- {
- IV[i] = 0;
- }
- }
- else
- {
- System.arraycopy(iv, 0, IV, 0, IV.length);
- }
-
- reset();
-
- // if params is null we reuse the current working key.
- if (ivParam.getParameters() != null)
- {
- cipher.init(true, ivParam.getParameters());
- }
- }
- else
- {
- reset();
-
- // if params is null we reuse the current working key.
- if (params != null)
- {
- cipher.init(true, params);
- }
- }
- }
-
- /**
- * return the algorithm name and mode.
- *
- * @return the name of the underlying algorithm followed by "/GCTR"
- * and the block size in bits
- */
- public String getAlgorithmName()
- {
- return cipher.getAlgorithmName() + "/GCTR";
- }
-
- /**
- * return the block size we are operating at (in bytes).
- *
- * @return the block size we are operating at (in bytes).
- */
- public int getBlockSize()
- {
- return blockSize;
- }
-
- /**
- * Process one block of input from the array in and write it to
- * the out array.
- *
- * @param in the array containing the input data.
- * @param inOff offset into the in array the data starts at.
- * @param out the array the output data will be copied into.
- * @param outOff the offset into the out array the output will start at.
- * @exception DataLengthException if there isn't enough data in in, or
- * space in out.
- * @exception IllegalStateException if the cipher isn't initialised.
- * @return the number of bytes processed and produced.
- */
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- throws DataLengthException, IllegalStateException
- {
- processBytes(in, inOff, blockSize, out, outOff);
-
- return blockSize;
- }
-
- /**
- * reset the feedback vector back to the IV and reset the underlying
- * cipher.
- */
- public void reset()
- {
- firstStep = true;
- N3 = 0;
- N4 = 0;
- System.arraycopy(IV, 0, ofbV, 0, IV.length);
- byteCount = 0;
- cipher.reset();
- }
-
- //array of bytes to type int
- private int bytesToint(
- byte[] in,
- int inOff)
- {
- return ((in[inOff + 3] << 24) & 0xff000000) + ((in[inOff + 2] << 16) & 0xff0000) +
- ((in[inOff + 1] << 8) & 0xff00) + (in[inOff] & 0xff);
- }
-
- //int to array of bytes
- private void intTobytes(
- int num,
- byte[] out,
- int outOff)
- {
- out[outOff + 3] = (byte)(num >>> 24);
- out[outOff + 2] = (byte)(num >>> 16);
- out[outOff + 1] = (byte)(num >>> 8);
- out[outOff] = (byte)num;
- }
-
- protected byte calculateByte(byte b)
- {
- if (byteCount == 0)
- {
- if (firstStep)
- {
- firstStep = false;
- cipher.processBlock(ofbV, 0, ofbOutV, 0);
- N3 = bytesToint(ofbOutV, 0);
- N4 = bytesToint(ofbOutV, 4);
- }
- N3 += C2;
- N4 += C1;
- intTobytes(N3, ofbV, 0);
- intTobytes(N4, ofbV, 4);
-
- cipher.processBlock(ofbV, 0, ofbOutV, 0);
- }
-
- byte rv = (byte)(ofbOutV[byteCount++] ^ b);
-
- if (byteCount == blockSize)
- {
- byteCount = 0;
-
- //
- // change over the input block.
- //
- System.arraycopy(ofbV, blockSize, ofbV, 0, ofbV.length - blockSize);
- System.arraycopy(ofbOutV, 0, ofbV, ofbV.length - blockSize, blockSize);
- }
-
- return rv;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/OCBBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/OCBBlockCipher.java
deleted file mode 100644
index 86263914..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/OCBBlockCipher.java
+++ /dev/null
@@ -1,598 +0,0 @@
-package org.bouncycastle.crypto.modes;
-
-import java.util.Vector;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.OutputLengthException;
-import org.bouncycastle.crypto.params.AEADParameters;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Arrays;
-
-/**
- * An implementation of <a href="http://tools.ietf.org/html/rfc7253">RFC 7253 on The OCB
- * Authenticated-Encryption Algorithm</a>, licensed per:
- * <p>
- * <blockquote> <a href="http://www.cs.ucdavis.edu/~rogaway/ocb/license1.pdf">License for
- * Open-Source Software Implementations of OCB</a> (Jan 9, 2013) &mdash; &ldquo;License 1&rdquo; <br>
- * Under this license, you are authorized to make, use, and distribute open-source software
- * implementations of OCB. This license terminates for you if you sue someone over their open-source
- * software implementation of OCB claiming that you have a patent covering their implementation.
- * <p>
- * This is a non-binding summary of a legal document (the link above). The parameters of the license
- * are specified in the license document and that document is controlling. </blockquote>
- */
-public class OCBBlockCipher
- implements AEADBlockCipher
-{
- private static final int BLOCK_SIZE = 16;
-
- private BlockCipher hashCipher;
- private BlockCipher mainCipher;
-
- /*
- * CONFIGURATION
- */
- private boolean forEncryption;
- private int macSize;
- private byte[] initialAssociatedText;
-
- /*
- * KEY-DEPENDENT
- */
- // NOTE: elements are lazily calculated
- private Vector L;
- private byte[] L_Asterisk, L_Dollar;
-
- /*
- * NONCE-DEPENDENT
- */
- private byte[] KtopInput = null;
- private byte[] Stretch = new byte[24];
- private byte[] OffsetMAIN_0 = new byte[16];
-
- /*
- * PER-ENCRYPTION/DECRYPTION
- */
- private byte[] hashBlock, mainBlock;
- private int hashBlockPos, mainBlockPos;
- private long hashBlockCount, mainBlockCount;
- private byte[] OffsetHASH;
- private byte[] Sum;
- private byte[] OffsetMAIN = new byte[16];
- private byte[] Checksum;
-
- // NOTE: The MAC value is preserved after doFinal
- private byte[] macBlock;
-
- public OCBBlockCipher(BlockCipher hashCipher, BlockCipher mainCipher)
- {
- if (hashCipher == null)
- {
- throw new IllegalArgumentException("'hashCipher' cannot be null");
- }
- if (hashCipher.getBlockSize() != BLOCK_SIZE)
- {
- throw new IllegalArgumentException("'hashCipher' must have a block size of "
- + BLOCK_SIZE);
- }
- if (mainCipher == null)
- {
- throw new IllegalArgumentException("'mainCipher' cannot be null");
- }
- if (mainCipher.getBlockSize() != BLOCK_SIZE)
- {
- throw new IllegalArgumentException("'mainCipher' must have a block size of "
- + BLOCK_SIZE);
- }
-
- if (!hashCipher.getAlgorithmName().equals(mainCipher.getAlgorithmName()))
- {
- throw new IllegalArgumentException(
- "'hashCipher' and 'mainCipher' must be the same algorithm");
- }
-
- this.hashCipher = hashCipher;
- this.mainCipher = mainCipher;
- }
-
- public BlockCipher getUnderlyingCipher()
- {
- return mainCipher;
- }
-
- public String getAlgorithmName()
- {
- return mainCipher.getAlgorithmName() + "/OCB";
- }
-
- public void init(boolean forEncryption, CipherParameters parameters)
- throws IllegalArgumentException
- {
- boolean oldForEncryption = this.forEncryption;
- this.forEncryption = forEncryption;
- this.macBlock = null;
-
- KeyParameter keyParameter;
-
- byte[] N;
- if (parameters instanceof AEADParameters)
- {
- AEADParameters aeadParameters = (AEADParameters)parameters;
-
- N = aeadParameters.getNonce();
- initialAssociatedText = aeadParameters.getAssociatedText();
-
- int macSizeBits = aeadParameters.getMacSize();
- if (macSizeBits < 64 || macSizeBits > 128 || macSizeBits % 8 != 0)
- {
- throw new IllegalArgumentException("Invalid value for MAC size: " + macSizeBits);
- }
-
- macSize = macSizeBits / 8;
- keyParameter = aeadParameters.getKey();
- }
- else if (parameters instanceof ParametersWithIV)
- {
- ParametersWithIV parametersWithIV = (ParametersWithIV)parameters;
-
- N = parametersWithIV.getIV();
- initialAssociatedText = null;
- macSize = 16;
- keyParameter = (KeyParameter)parametersWithIV.getParameters();
- }
- else
- {
- throw new IllegalArgumentException("invalid parameters passed to OCB");
- }
-
- this.hashBlock = new byte[16];
- this.mainBlock = new byte[forEncryption ? BLOCK_SIZE : (BLOCK_SIZE + macSize)];
-
- if (N == null)
- {
- N = new byte[0];
- }
-
- if (N.length > 15)
- {
- throw new IllegalArgumentException("IV must be no more than 15 bytes");
- }
-
- /*
- * KEY-DEPENDENT INITIALISATION
- */
-
- if (keyParameter != null)
- {
- // hashCipher always used in forward mode
- hashCipher.init(true, keyParameter);
- mainCipher.init(forEncryption, keyParameter);
- KtopInput = null;
- }
- else if (oldForEncryption != forEncryption)
- {
- throw new IllegalArgumentException("cannot change encrypting state without providing key.");
- }
-
- this.L_Asterisk = new byte[16];
- hashCipher.processBlock(L_Asterisk, 0, L_Asterisk, 0);
-
- this.L_Dollar = OCB_double(L_Asterisk);
-
- this.L = new Vector();
- this.L.addElement(OCB_double(L_Dollar));
-
- /*
- * NONCE-DEPENDENT AND PER-ENCRYPTION/DECRYPTION INITIALISATION
- */
-
- int bottom = processNonce(N);
-
- int bits = bottom % 8, bytes = bottom / 8;
- if (bits == 0)
- {
- System.arraycopy(Stretch, bytes, OffsetMAIN_0, 0, 16);
- }
- else
- {
- for (int i = 0; i < 16; ++i)
- {
- int b1 = Stretch[bytes] & 0xff;
- int b2 = Stretch[++bytes] & 0xff;
- this.OffsetMAIN_0[i] = (byte)((b1 << bits) | (b2 >>> (8 - bits)));
- }
- }
-
- this.hashBlockPos = 0;
- this.mainBlockPos = 0;
-
- this.hashBlockCount = 0;
- this.mainBlockCount = 0;
-
- this.OffsetHASH = new byte[16];
- this.Sum = new byte[16];
- System.arraycopy(this.OffsetMAIN_0, 0, this.OffsetMAIN, 0, 16);
- this.Checksum = new byte[16];
-
- if (initialAssociatedText != null)
- {
- processAADBytes(initialAssociatedText, 0, initialAssociatedText.length);
- }
- }
-
- protected int processNonce(byte[] N)
- {
- byte[] nonce = new byte[16];
- System.arraycopy(N, 0, nonce, nonce.length - N.length, N.length);
- nonce[0] = (byte)(macSize << 4);
- nonce[15 - N.length] |= 1;
-
- int bottom = nonce[15] & 0x3F;
- nonce[15] &= 0xC0;
-
- /*
- * When used with incrementing nonces, the cipher is only applied once every 64 inits.
- */
- if (KtopInput == null || !Arrays.areEqual(nonce, KtopInput))
- {
- byte[] Ktop = new byte[16];
- KtopInput = nonce;
- hashCipher.processBlock(KtopInput, 0, Ktop, 0);
- System.arraycopy(Ktop, 0, Stretch, 0, 16);
- for (int i = 0; i < 8; ++i)
- {
- Stretch[16 + i] = (byte)(Ktop[i] ^ Ktop[i + 1]);
- }
- }
-
- return bottom;
- }
-
- public byte[] getMac()
- {
- return Arrays.clone(macBlock);
- }
-
- public int getOutputSize(int len)
- {
- int totalData = len + mainBlockPos;
- if (forEncryption)
- {
- return totalData + macSize;
- }
- return totalData < macSize ? 0 : totalData - macSize;
- }
-
- public int getUpdateOutputSize(int len)
- {
- int totalData = len + mainBlockPos;
- if (!forEncryption)
- {
- if (totalData < macSize)
- {
- return 0;
- }
- totalData -= macSize;
- }
- return totalData - totalData % BLOCK_SIZE;
- }
-
- public void processAADByte(byte input)
- {
- hashBlock[hashBlockPos] = input;
- if (++hashBlockPos == hashBlock.length)
- {
- processHashBlock();
- }
- }
-
- public void processAADBytes(byte[] input, int off, int len)
- {
- for (int i = 0; i < len; ++i)
- {
- hashBlock[hashBlockPos] = input[off + i];
- if (++hashBlockPos == hashBlock.length)
- {
- processHashBlock();
- }
- }
- }
-
- public int processByte(byte input, byte[] output, int outOff)
- throws DataLengthException
- {
- mainBlock[mainBlockPos] = input;
- if (++mainBlockPos == mainBlock.length)
- {
- processMainBlock(output, outOff);
- return BLOCK_SIZE;
- }
- return 0;
- }
-
- public int processBytes(byte[] input, int inOff, int len, byte[] output, int outOff)
- throws DataLengthException
- {
- if (input.length < (inOff + len))
- {
- throw new DataLengthException("Input buffer too short");
- }
- int resultLen = 0;
-
- for (int i = 0; i < len; ++i)
- {
- mainBlock[mainBlockPos] = input[inOff + i];
- if (++mainBlockPos == mainBlock.length)
- {
- processMainBlock(output, outOff + resultLen);
- resultLen += BLOCK_SIZE;
- }
- }
-
- return resultLen;
- }
-
- public int doFinal(byte[] output, int outOff)
- throws IllegalStateException,
- InvalidCipherTextException
- {
- /*
- * For decryption, get the tag from the end of the message
- */
- byte[] tag = null;
- if (!forEncryption)
- {
- if (mainBlockPos < macSize)
- {
- throw new InvalidCipherTextException("data too short");
- }
- mainBlockPos -= macSize;
- tag = new byte[macSize];
- System.arraycopy(mainBlock, mainBlockPos, tag, 0, macSize);
- }
-
- /*
- * HASH: Process any final partial block; compute final hash value
- */
- if (hashBlockPos > 0)
- {
- OCB_extend(hashBlock, hashBlockPos);
- updateHASH(L_Asterisk);
- }
-
- /*
- * OCB-ENCRYPT/OCB-DECRYPT: Process any final partial block
- */
- if (mainBlockPos > 0)
- {
- if (forEncryption)
- {
- OCB_extend(mainBlock, mainBlockPos);
- xor(Checksum, mainBlock);
- }
-
- xor(OffsetMAIN, L_Asterisk);
-
- byte[] Pad = new byte[16];
- hashCipher.processBlock(OffsetMAIN, 0, Pad, 0);
-
- xor(mainBlock, Pad);
-
- if (output.length < (outOff + mainBlockPos))
- {
- throw new OutputLengthException("Output buffer too short");
- }
- System.arraycopy(mainBlock, 0, output, outOff, mainBlockPos);
-
- if (!forEncryption)
- {
- OCB_extend(mainBlock, mainBlockPos);
- xor(Checksum, mainBlock);
- }
- }
-
- /*
- * OCB-ENCRYPT/OCB-DECRYPT: Compute raw tag
- */
- xor(Checksum, OffsetMAIN);
- xor(Checksum, L_Dollar);
- hashCipher.processBlock(Checksum, 0, Checksum, 0);
- xor(Checksum, Sum);
-
- this.macBlock = new byte[macSize];
- System.arraycopy(Checksum, 0, macBlock, 0, macSize);
-
- /*
- * Validate or append tag and reset this cipher for the next run
- */
- int resultLen = mainBlockPos;
-
- if (forEncryption)
- {
- if (output.length < (outOff + resultLen + macSize))
- {
- throw new OutputLengthException("Output buffer too short");
- }
- // Append tag to the message
- System.arraycopy(macBlock, 0, output, outOff + resultLen, macSize);
- resultLen += macSize;
- }
- else
- {
- // Compare the tag from the message with the calculated one
- if (!Arrays.constantTimeAreEqual(macBlock, tag))
- {
- throw new InvalidCipherTextException("mac check in OCB failed");
- }
- }
-
- reset(false);
-
- return resultLen;
- }
-
- public void reset()
- {
- reset(true);
- }
-
- protected void clear(byte[] bs)
- {
- if (bs != null)
- {
- Arrays.fill(bs, (byte)0);
- }
- }
-
- protected byte[] getLSub(int n)
- {
- while (n >= L.size())
- {
- L.addElement(OCB_double((byte[])L.lastElement()));
- }
- return (byte[])L.elementAt(n);
- }
-
- protected void processHashBlock()
- {
- /*
- * HASH: Process any whole blocks
- */
- updateHASH(getLSub(OCB_ntz(++hashBlockCount)));
- hashBlockPos = 0;
- }
-
- protected void processMainBlock(byte[] output, int outOff)
- {
- if (output.length < (outOff + BLOCK_SIZE))
- {
- throw new OutputLengthException("Output buffer too short");
- }
-
- /*
- * OCB-ENCRYPT/OCB-DECRYPT: Process any whole blocks
- */
-
- if (forEncryption)
- {
- xor(Checksum, mainBlock);
- mainBlockPos = 0;
- }
-
- xor(OffsetMAIN, getLSub(OCB_ntz(++mainBlockCount)));
-
- xor(mainBlock, OffsetMAIN);
- mainCipher.processBlock(mainBlock, 0, mainBlock, 0);
- xor(mainBlock, OffsetMAIN);
-
- System.arraycopy(mainBlock, 0, output, outOff, 16);
-
- if (!forEncryption)
- {
- xor(Checksum, mainBlock);
- System.arraycopy(mainBlock, BLOCK_SIZE, mainBlock, 0, macSize);
- mainBlockPos = macSize;
- }
- }
-
- protected void reset(boolean clearMac)
- {
- hashCipher.reset();
- mainCipher.reset();
-
- clear(hashBlock);
- clear(mainBlock);
-
- hashBlockPos = 0;
- mainBlockPos = 0;
-
- hashBlockCount = 0;
- mainBlockCount = 0;
-
- clear(OffsetHASH);
- clear(Sum);
- System.arraycopy(OffsetMAIN_0, 0, OffsetMAIN, 0, 16);
- clear(Checksum);
-
- if (clearMac)
- {
- macBlock = null;
- }
-
- if (initialAssociatedText != null)
- {
- processAADBytes(initialAssociatedText, 0, initialAssociatedText.length);
- }
- }
-
- protected void updateHASH(byte[] LSub)
- {
- xor(OffsetHASH, LSub);
- xor(hashBlock, OffsetHASH);
- hashCipher.processBlock(hashBlock, 0, hashBlock, 0);
- xor(Sum, hashBlock);
- }
-
- protected static byte[] OCB_double(byte[] block)
- {
- byte[] result = new byte[16];
- int carry = shiftLeft(block, result);
-
- /*
- * NOTE: This construction is an attempt at a constant-time implementation.
- */
- result[15] ^= (0x87 >>> ((1 - carry) << 3));
-
- return result;
- }
-
- protected static void OCB_extend(byte[] block, int pos)
- {
- block[pos] = (byte)0x80;
- while (++pos < 16)
- {
- block[pos] = 0;
- }
- }
-
- protected static int OCB_ntz(long x)
- {
- if (x == 0)
- {
- return 64;
- }
-
- int n = 0;
- while ((x & 1L) == 0L)
- {
- ++n;
- x >>>= 1;
- }
- return n;
- }
-
- protected static int shiftLeft(byte[] block, byte[] output)
- {
- int i = 16;
- int bit = 0;
- while (--i >= 0)
- {
- int b = block[i] & 0xff;
- output[i] = (byte)((b << 1) | bit);
- bit = (b >>> 7) & 1;
- }
- return bit;
- }
-
- protected static void xor(byte[] block, byte[] val)
- {
- for (int i = 15; i >= 0; --i)
- {
- block[i] ^= val[i];
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/OFBBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/OFBBlockCipher.java
deleted file mode 100644
index d9ff428f..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/OFBBlockCipher.java
+++ /dev/null
@@ -1,178 +0,0 @@
-package org.bouncycastle.crypto.modes;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.StreamBlockCipher;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-/**
- * implements a Output-FeedBack (OFB) mode on top of a simple cipher.
- */
-public class OFBBlockCipher
- extends StreamBlockCipher
-{
- private int byteCount;
- private byte[] IV;
- private byte[] ofbV;
- private byte[] ofbOutV;
-
- private final int blockSize;
- private final BlockCipher cipher;
-
- /**
- * Basic constructor.
- *
- * @param cipher the block cipher to be used as the basis of the
- * feedback mode.
- * @param blockSize the block size in bits (note: a multiple of 8)
- */
- public OFBBlockCipher(
- BlockCipher cipher,
- int blockSize)
- {
- super(cipher);
-
- this.cipher = cipher;
- this.blockSize = blockSize / 8;
-
- this.IV = new byte[cipher.getBlockSize()];
- this.ofbV = new byte[cipher.getBlockSize()];
- this.ofbOutV = new byte[cipher.getBlockSize()];
- }
-
- /**
- * Initialise the cipher and, possibly, the initialisation vector (IV).
- * If an IV isn't passed as part of the parameter, the IV will be all zeros.
- * An IV which is too short is handled in FIPS compliant fashion.
- *
- * @param encrypting if true the cipher is initialised for
- * encryption, if false for decryption.
- * @param params the key and other data required by the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean encrypting, //ignored by this OFB mode
- CipherParameters params)
- throws IllegalArgumentException
- {
- if (params instanceof ParametersWithIV)
- {
- ParametersWithIV ivParam = (ParametersWithIV)params;
- byte[] iv = ivParam.getIV();
-
- if (iv.length < IV.length)
- {
- // prepend the supplied IV with zeros (per FIPS PUB 81)
- System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
- for (int i = 0; i < IV.length - iv.length; i++)
- {
- IV[i] = 0;
- }
- }
- else
- {
- System.arraycopy(iv, 0, IV, 0, IV.length);
- }
-
- reset();
-
- // if null it's an IV changed only.
- if (ivParam.getParameters() != null)
- {
- cipher.init(true, ivParam.getParameters());
- }
- }
- else
- {
- reset();
-
- // if it's null, key is to be reused.
- if (params != null)
- {
- cipher.init(true, params);
- }
- }
- }
-
- /**
- * return the algorithm name and mode.
- *
- * @return the name of the underlying algorithm followed by "/OFB"
- * and the block size in bits
- */
- public String getAlgorithmName()
- {
- return cipher.getAlgorithmName() + "/OFB" + (blockSize * 8);
- }
-
-
- /**
- * return the block size we are operating at (in bytes).
- *
- * @return the block size we are operating at (in bytes).
- */
- public int getBlockSize()
- {
- return blockSize;
- }
-
- /**
- * Process one block of input from the array in and write it to
- * the out array.
- *
- * @param in the array containing the input data.
- * @param inOff offset into the in array the data starts at.
- * @param out the array the output data will be copied into.
- * @param outOff the offset into the out array the output will start at.
- * @exception DataLengthException if there isn't enough data in in, or
- * space in out.
- * @exception IllegalStateException if the cipher isn't initialised.
- * @return the number of bytes processed and produced.
- */
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- throws DataLengthException, IllegalStateException
- {
- processBytes(in, inOff, blockSize, out, outOff);
-
- return blockSize;
- }
-
- /**
- * reset the feedback vector back to the IV and reset the underlying
- * cipher.
- */
- public void reset()
- {
- System.arraycopy(IV, 0, ofbV, 0, IV.length);
- byteCount = 0;
-
- cipher.reset();
- }
-
- protected byte calculateByte(byte in)
- throws DataLengthException, IllegalStateException
- {
- if (byteCount == 0)
- {
- cipher.processBlock(ofbV, 0, ofbOutV, 0);
- }
-
- byte rv = (byte)(ofbOutV[byteCount++] ^ in);
-
- if (byteCount == blockSize)
- {
- byteCount = 0;
-
- System.arraycopy(ofbV, blockSize, ofbV, 0, ofbV.length - blockSize);
- System.arraycopy(ofbOutV, 0, ofbV, ofbV.length - blockSize, blockSize);
- }
-
- return rv;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/OldCTSBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/OldCTSBlockCipher.java
deleted file mode 100644
index b34432ac..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/OldCTSBlockCipher.java
+++ /dev/null
@@ -1,269 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/modes/OpenPGPCFBBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/OpenPGPCFBBlockCipher.java
deleted file mode 100644
index e48731b3..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/OpenPGPCFBBlockCipher.java
+++ /dev/null
@@ -1,312 +0,0 @@
-package org.bouncycastle.crypto.modes;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-
-/**
- * Implements OpenPGP's rather strange version of Cipher-FeedBack (CFB) mode
- * on top of a simple cipher. This class assumes the IV has been prepended
- * to the data stream already, and just accomodates the reset after
- * (blockSize + 2) bytes have been read.
- * <p>
- * For further info see <a href="http://www.ietf.org/rfc/rfc2440.html">RFC 2440</a>.
- */
-public class OpenPGPCFBBlockCipher
- implements BlockCipher
-{
- private byte[] IV;
- private byte[] FR;
- private byte[] FRE;
-
- private BlockCipher cipher;
-
- private int count;
- private int blockSize;
- private boolean forEncryption;
-
- /**
- * Basic constructor.
- *
- * @param cipher the block cipher to be used as the basis of the
- * feedback mode.
- */
- public OpenPGPCFBBlockCipher(
- BlockCipher cipher)
- {
- this.cipher = cipher;
-
- this.blockSize = cipher.getBlockSize();
- this.IV = new byte[blockSize];
- this.FR = new byte[blockSize];
- this.FRE = new byte[blockSize];
- }
-
- /**
- * return the underlying block cipher that we are wrapping.
- *
- * @return the underlying block cipher that we are wrapping.
- */
- public BlockCipher getUnderlyingCipher()
- {
- return cipher;
- }
-
- /**
- * return the algorithm name and mode.
- *
- * @return the name of the underlying algorithm followed by "/PGPCFB"
- * and the block size in bits.
- */
- public String getAlgorithmName()
- {
- return cipher.getAlgorithmName() + "/OpenPGPCFB";
- }
-
- /**
- * return the block size we are operating at.
- *
- * @return the block size we are operating at (in bytes).
- */
- public int getBlockSize()
- {
- return cipher.getBlockSize();
- }
-
- /**
- * Process one block of input from the array in and write it to
- * the out array.
- *
- * @param in the array containing the input data.
- * @param inOff offset into the in array the data starts at.
- * @param out the array the output data will be copied into.
- * @param outOff the offset into the out array the output will start at.
- * @exception DataLengthException if there isn't enough data in in, or
- * space in out.
- * @exception IllegalStateException if the cipher isn't initialised.
- * @return the number of bytes processed and produced.
- */
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- throws DataLengthException, IllegalStateException
- {
- return (forEncryption) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff);
- }
-
- /**
- * reset the chaining vector back to the IV and reset the underlying
- * cipher.
- */
- public void reset()
- {
- count = 0;
-
- System.arraycopy(IV, 0, FR, 0, FR.length);
-
- cipher.reset();
- }
-
- /**
- * Initialise the cipher and, possibly, the initialisation vector (IV).
- * If an IV isn't passed as part of the parameter, the IV will be all zeros.
- * An IV which is too short is handled in FIPS compliant fashion.
- *
- * @param forEncryption if true the cipher is initialised for
- * encryption, if false for decryption.
- * @param params the key and other data required by the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean forEncryption,
- CipherParameters params)
- throws IllegalArgumentException
- {
- this.forEncryption = forEncryption;
-
- reset();
-
- cipher.init(true, params);
- }
-
- /**
- * Encrypt one byte of data according to CFB mode.
- * @param data the byte to encrypt
- * @param blockOff offset in the current block
- * @return the encrypted byte
- */
- private byte encryptByte(byte data, int blockOff)
- {
- return (byte)(FRE[blockOff] ^ data);
- }
-
- /**
- * Do the appropriate processing for CFB IV mode encryption.
- *
- * @param in the array containing the data to be encrypted.
- * @param inOff offset into the in array the data starts at.
- * @param out the array the encrypted data will be copied into.
- * @param outOff the offset into the out array the output will start at.
- * @exception DataLengthException if there isn't enough data in in, or
- * space in out.
- * @exception IllegalStateException if the cipher isn't initialised.
- * @return the number of bytes processed and produced.
- */
- private int encryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- throws DataLengthException, IllegalStateException
- {
- if ((inOff + blockSize) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + blockSize) > out.length)
- {
- throw new DataLengthException("output buffer too short");
- }
-
- if (count > blockSize)
- {
- FR[blockSize - 2] = out[outOff] = encryptByte(in[inOff], blockSize - 2);
- FR[blockSize - 1] = out[outOff + 1] = encryptByte(in[inOff + 1], blockSize - 1);
-
- cipher.processBlock(FR, 0, FRE, 0);
-
- for (int n = 2; n < blockSize; n++)
- {
- FR[n - 2] = out[outOff + n] = encryptByte(in[inOff + n], n - 2);
- }
- }
- else if (count == 0)
- {
- cipher.processBlock(FR, 0, FRE, 0);
-
- for (int n = 0; n < blockSize; n++)
- {
- FR[n] = out[outOff + n] = encryptByte(in[inOff + n], n);
- }
-
- count += blockSize;
- }
- else if (count == blockSize)
- {
- cipher.processBlock(FR, 0, FRE, 0);
-
- out[outOff] = encryptByte(in[inOff], 0);
- out[outOff + 1] = encryptByte(in[inOff + 1], 1);
-
- //
- // do reset
- //
- System.arraycopy(FR, 2, FR, 0, blockSize - 2);
- System.arraycopy(out, outOff, FR, blockSize - 2, 2);
-
- cipher.processBlock(FR, 0, FRE, 0);
-
- for (int n = 2; n < blockSize; n++)
- {
- FR[n - 2] = out[outOff + n] = encryptByte(in[inOff + n], n - 2);
- }
-
- count += blockSize;
- }
-
- return blockSize;
- }
-
- /**
- * Do the appropriate processing for CFB IV mode decryption.
- *
- * @param in the array containing the data to be decrypted.
- * @param inOff offset into the in array the data starts at.
- * @param out the array the encrypted data will be copied into.
- * @param outOff the offset into the out array the output will start at.
- * @exception DataLengthException if there isn't enough data in in, or
- * space in out.
- * @exception IllegalStateException if the cipher isn't initialised.
- * @return the number of bytes processed and produced.
- */
- private int decryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- throws DataLengthException, IllegalStateException
- {
- if ((inOff + blockSize) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + blockSize) > out.length)
- {
- throw new DataLengthException("output buffer too short");
- }
-
- if (count > blockSize)
- {
- byte inVal = in[inOff];
- FR[blockSize - 2] = inVal;
- out[outOff] = encryptByte(inVal, blockSize - 2);
-
- inVal = in[inOff + 1];
- FR[blockSize - 1] = inVal;
- out[outOff + 1] = encryptByte(inVal, blockSize - 1);
-
- cipher.processBlock(FR, 0, FRE, 0);
-
- for (int n = 2; n < blockSize; n++)
- {
- inVal = in[inOff + n];
- FR[n - 2] = inVal;
- out[outOff + n] = encryptByte(inVal, n - 2);
- }
- }
- else if (count == 0)
- {
- cipher.processBlock(FR, 0, FRE, 0);
-
- for (int n = 0; n < blockSize; n++)
- {
- FR[n] = in[inOff + n];
- out[n] = encryptByte(in[inOff + n], n);
- }
-
- count += blockSize;
- }
- else if (count == blockSize)
- {
- cipher.processBlock(FR, 0, FRE, 0);
-
- byte inVal1 = in[inOff];
- byte inVal2 = in[inOff + 1];
- out[outOff ] = encryptByte(inVal1, 0);
- out[outOff + 1] = encryptByte(inVal2, 1);
-
- System.arraycopy(FR, 2, FR, 0, blockSize - 2);
-
- FR[blockSize - 2] = inVal1;
- FR[blockSize - 1] = inVal2;
-
- cipher.processBlock(FR, 0, FRE, 0);
-
- for (int n = 2; n < blockSize; n++)
- {
- byte inVal = in[inOff + n];
- FR[n - 2] = inVal;
- out[outOff + n] = encryptByte(inVal, n - 2);
- }
-
- count += blockSize;
- }
-
- return blockSize;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java
deleted file mode 100644
index 4dee63a5..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java
+++ /dev/null
@@ -1,455 +0,0 @@
-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.ParametersWithIV;
-
-/**
- * Implements OpenPGP's rather strange version of Cipher-FeedBack (CFB) mode on top of a simple cipher. For further info see <a href="http://www.ietf.org/rfc/rfc2440.html">RFC 2440</a>.
- */
-public class PGPCFBBlockCipher
- implements BlockCipher
-{
- private byte[] IV;
- private byte[] FR;
- private byte[] FRE;
- private byte[] tmp;
-
- private BlockCipher cipher;
-
- private int count;
- private int blockSize;
- private boolean forEncryption;
-
- private boolean inlineIv; // if false we don't need to prepend an IV
-
- /**
- * Basic constructor.
- *
- * @param cipher the block cipher to be used as the basis of the
- * feedback mode.
- * @param inlineIv if true this is for PGP CFB with a prepended iv.
- */
- public PGPCFBBlockCipher(
- BlockCipher cipher,
- boolean inlineIv)
- {
- this.cipher = cipher;
- this.inlineIv = inlineIv;
-
- this.blockSize = cipher.getBlockSize();
- this.IV = new byte[blockSize];
- this.FR = new byte[blockSize];
- this.FRE = new byte[blockSize];
- this.tmp = new byte[blockSize];
- }
-
- /**
- * return the underlying block cipher that we are wrapping.
- *
- * @return the underlying block cipher that we are wrapping.
- */
- public BlockCipher getUnderlyingCipher()
- {
- return cipher;
- }
-
- /**
- * return the algorithm name and mode.
- *
- * @return the name of the underlying algorithm followed by "/PGPCFB"
- * and the block size in bits.
- */
- public String getAlgorithmName()
- {
- if (inlineIv)
- {
- return cipher.getAlgorithmName() + "/PGPCFBwithIV";
- }
- else
- {
- return cipher.getAlgorithmName() + "/PGPCFB";
- }
- }
-
- /**
- * return the block size we are operating at.
- *
- * @return the block size we are operating at (in bytes).
- */
- public int getBlockSize()
- {
- return cipher.getBlockSize();
- }
-
- /**
- * Process one block of input from the array in and write it to
- * the out array.
- *
- * @param in the array containing the input data.
- * @param inOff offset into the in array the data starts at.
- * @param out the array the output data will be copied into.
- * @param outOff the offset into the out array the output will start at.
- * @exception DataLengthException if there isn't enough data in in, or
- * space in out.
- * @exception IllegalStateException if the cipher isn't initialised.
- * @return the number of bytes processed and produced.
- */
- public int processBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- throws DataLengthException, IllegalStateException
- {
- if (inlineIv)
- {
- return (forEncryption) ? encryptBlockWithIV(in, inOff, out, outOff) : decryptBlockWithIV(in, inOff, out, outOff);
- }
- else
- {
- return (forEncryption) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff);
- }
- }
-
- /**
- * reset the chaining vector back to the IV and reset the underlying
- * cipher.
- */
- public void reset()
- {
- count = 0;
-
- for (int i = 0; i != FR.length; i++)
- {
- if (inlineIv)
- {
- FR[i] = 0;
- }
- else
- {
- FR[i] = IV[i]; // if simple mode, key is IV (even if this is zero)
- }
- }
-
- cipher.reset();
- }
-
- /**
- * Initialise the cipher and, possibly, the initialisation vector (IV).
- * If an IV isn't passed as part of the parameter, the IV will be all zeros.
- * An IV which is too short is handled in FIPS compliant fashion.
- *
- * @param forEncryption if true the cipher is initialised for
- * encryption, if false for decryption.
- * @param params the key and other data required by the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean forEncryption,
- CipherParameters params)
- throws IllegalArgumentException
- {
- this.forEncryption = forEncryption;
-
- if (params instanceof ParametersWithIV)
- {
- ParametersWithIV ivParam = (ParametersWithIV)params;
- byte[] iv = ivParam.getIV();
-
- if (iv.length < IV.length)
- {
- // prepend the supplied IV with zeros (per FIPS PUB 81)
- System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
- for (int i = 0; i < IV.length - iv.length; i++)
- {
- IV[i] = 0;
- }
- }
- else
- {
- System.arraycopy(iv, 0, IV, 0, IV.length);
- }
-
- reset();
-
- cipher.init(true, ivParam.getParameters());
- }
- else
- {
- reset();
-
- cipher.init(true, params);
- }
- }
-
- /**
- * Encrypt one byte of data according to CFB mode.
- * @param data the byte to encrypt
- * @param blockOff where am i in the current block, determines when to resync the block
- * @returns the encrypted byte
- */
- private byte encryptByte(byte data, int blockOff)
- {
- return (byte)(FRE[blockOff] ^ data);
- }
-
- /**
- * Do the appropriate processing for CFB IV mode encryption.
- *
- * @param in the array containing the data to be encrypted.
- * @param inOff offset into the in array the data starts at.
- * @param out the array the encrypted data will be copied into.
- * @param outOff the offset into the out array the output will start at.
- * @exception DataLengthException if there isn't enough data in in, or
- * space in out.
- * @exception IllegalStateException if the cipher isn't initialised.
- * @return the number of bytes processed and produced.
- */
- private int encryptBlockWithIV(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- throws DataLengthException, IllegalStateException
- {
- if ((inOff + blockSize) > in.length)
- {
- throw new DataLengthException("input 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++)
- {
- out[outOff + n] = encryptByte(IV[n], n);
- }
-
- System.arraycopy(out, outOff, FR, 0, blockSize);
-
- cipher.processBlock(FR, 0, FRE, 0);
-
- out[outOff + blockSize] = encryptByte(IV[blockSize - 2], 0);
- out[outOff + blockSize + 1] = encryptByte(IV[blockSize - 1], 1);
-
- System.arraycopy(out, outOff + 2, FR, 0, blockSize);
-
- cipher.processBlock(FR, 0, FRE, 0);
-
- for (int n = 0; n < blockSize; n++)
- {
- out[outOff + blockSize + 2 + n] = encryptByte(in[inOff + n], n);
- }
-
- System.arraycopy(out, outOff + blockSize + 2, FR, 0, blockSize);
-
- count += 2 * blockSize + 2;
-
- return 2 * blockSize + 2;
- }
- 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++)
- {
- out[outOff + n] = encryptByte(in[inOff + n], n);
- }
-
- System.arraycopy(out, outOff, FR, 0, blockSize);
- }
-
- return blockSize;
- }
-
- /**
- * Do the appropriate processing for CFB IV mode decryption.
- *
- * @param in the array containing the data to be decrypted.
- * @param inOff offset into the in array the data starts at.
- * @param out the array the encrypted data will be copied into.
- * @param outOff the offset into the out array the output will start at.
- * @exception DataLengthException if there isn't enough data in in, or
- * space in out.
- * @exception IllegalStateException if the cipher isn't initialised.
- * @return the number of bytes processed and produced.
- */
- private int decryptBlockWithIV(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- throws DataLengthException, IllegalStateException
- {
- if ((inOff + blockSize) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + blockSize) > out.length)
- {
- throw new DataLengthException("output buffer too short");
- }
-
- if (count == 0)
- {
- for (int n = 0; n < blockSize; n++)
- {
- FR[n] = in[inOff + n];
- }
-
- cipher.processBlock(FR, 0, FRE, 0);
-
- count += blockSize;
-
- return 0;
- }
- else if (count == blockSize)
- {
- // copy in buffer so that this mode works if in and out are the same
- System.arraycopy(in, inOff, tmp, 0, blockSize);
-
- System.arraycopy(FR, 2, FR, 0, blockSize - 2);
-
- FR[blockSize - 2] = tmp[0];
- FR[blockSize - 1] = tmp[1];
-
- cipher.processBlock(FR, 0, FRE, 0);
-
- for (int n = 0; n < blockSize - 2; n++)
- {
- out[outOff + n] = encryptByte(tmp[n + 2], n);
- }
-
- System.arraycopy(tmp, 2, FR, 0, blockSize - 2);
-
- count += 2;
-
- return blockSize - 2;
- }
- else if (count >= blockSize + 2)
- {
- // copy in buffer so that this mode works if in and out are the same
- System.arraycopy(in, inOff, tmp, 0, blockSize);
-
- out[outOff + 0] = encryptByte(tmp[0], blockSize - 2);
- out[outOff + 1] = encryptByte(tmp[1], blockSize - 1);
-
- System.arraycopy(tmp, 0, FR, blockSize - 2, 2);
-
- cipher.processBlock(FR, 0, FRE, 0);
-
- for (int n = 0; n < blockSize - 2; n++)
- {
- out[outOff + n + 2] = encryptByte(tmp[n + 2], n);
- }
-
- System.arraycopy(tmp, 2, FR, 0, blockSize - 2);
-
- }
-
- return blockSize;
- }
-
- /**
- * Do the appropriate processing for CFB mode encryption.
- *
- * @param in the array containing the data to be encrypted.
- * @param inOff offset into the in array the data starts at.
- * @param out the array the encrypted data will be copied into.
- * @param outOff the offset into the out array the output will start at.
- * @exception DataLengthException if there isn't enough data in in, or
- * space in out.
- * @exception IllegalStateException if the cipher isn't initialised.
- * @return the number of bytes processed and produced.
- */
- private int encryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- throws DataLengthException, IllegalStateException
- {
- if ((inOff + blockSize) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + blockSize) > out.length)
- {
- throw new DataLengthException("output buffer too short");
- }
-
- cipher.processBlock(FR, 0, FRE, 0);
- for (int n = 0; n < blockSize; n++)
- {
- out[outOff + n] = encryptByte(in[inOff + n], n);
- }
-
- for (int n = 0; n < blockSize; n++)
- {
- FR[n] = out[outOff + n];
- }
-
- return blockSize;
-
- }
-
- /**
- * Do the appropriate processing for CFB mode decryption.
- *
- * @param in the array containing the data to be decrypted.
- * @param inOff offset into the in array the data starts at.
- * @param out the array the encrypted data will be copied into.
- * @param outOff the offset into the out array the output will start at.
- * @exception DataLengthException if there isn't enough data in in, or
- * space in out.
- * @exception IllegalStateException if the cipher isn't initialised.
- * @return the number of bytes processed and produced.
- */
- private int decryptBlock(
- byte[] in,
- int inOff,
- byte[] out,
- int outOff)
- throws DataLengthException, IllegalStateException
- {
- if ((inOff + blockSize) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + blockSize) > out.length)
- {
- throw new DataLengthException("output buffer too short");
- }
-
- cipher.processBlock(FR, 0, FRE, 0);
- for (int n = 0; n < blockSize; n++)
- {
- out[outOff + n] = encryptByte(in[inOff + n], n);
- }
-
- for (int n = 0; n < blockSize; n++)
- {
- FR[n] = in[inOff + n];
- }
-
- return blockSize;
-
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/PaddedBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/PaddedBlockCipher.java
deleted file mode 100644
index f15ed673..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/PaddedBlockCipher.java
+++ /dev/null
@@ -1,253 +0,0 @@
-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 wrapper class that allows block ciphers to be used to process data in
- * a piecemeal fashion with PKCS5/PKCS7 padding. The PaddedBlockCipher
- * outputs a block only when the buffer is full and more data is being added,
- * or on a doFinal (unless the current block in the buffer is a pad block).
- * The padding mechanism used is the one outlined in PKCS5/PKCS7.
- *
- * @deprecated use org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher instead.
- */
-public class PaddedBlockCipher
- extends BufferedBlockCipher
-{
- /**
- * Create a buffered block cipher with, or without, padding.
- *
- * @param cipher the underlying block cipher this buffering object wraps.
- */
- public PaddedBlockCipher(
- BlockCipher cipher)
- {
- this.cipher = cipher;
-
- buf = new byte[cipher.getBlockSize()];
- bufOff = 0;
- }
-
- /**
- * 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)
- {
- int total = len + bufOff;
- int leftOver = total % buf.length;
-
- if (leftOver == 0)
- {
- if (forEncryption)
- {
- return total + buf.length;
- }
-
- return total;
- }
-
- return total - leftOver + buf.length;
- }
-
- /**
- * 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;
- }
-
- /**
- * process a single byte, producing an output block if neccessary.
- *
- * @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.
- * @exception 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);
- bufOff = 0;
- }
-
- 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.
- * @exception 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);
-
- bufOff = 0;
- len -= gapLen;
- inOff += gapLen;
-
- while (len > buf.length)
- {
- resultLen += cipher.processBlock(in, inOff, out, outOff + resultLen);
-
- len -= blockSize;
- inOff += blockSize;
- }
- }
-
- System.arraycopy(in, inOff, buf, bufOff, len);
-
- bufOff += len;
-
- return resultLen;
- }
-
- /**
- * Process the last block in the buffer. If the buffer is currently
- * full and padding needs to be added a call to doFinal will produce
- * 2 * getBlockSize() bytes.
- *
- * @param out the array the block currently being held is copied into.
- * @param outOff the offset at which the copying starts.
- * @exception DataLengthException if there is insufficient space in out for
- * the output or we are decrypting and the input is not block size aligned.
- * @exception IllegalStateException if the underlying cipher is not
- * initialised.
- * @exception InvalidCipherTextException if padding is expected and not found.
- */
- public int doFinal(
- byte[] out,
- int outOff)
- throws DataLengthException, IllegalStateException, InvalidCipherTextException
- {
- int blockSize = cipher.getBlockSize();
- int resultLen = 0;
-
- if (forEncryption)
- {
- if (bufOff == blockSize)
- {
- if ((outOff + 2 * blockSize) > out.length)
- {
- throw new DataLengthException("output buffer too short");
- }
-
- resultLen = cipher.processBlock(buf, 0, out, outOff);
- bufOff = 0;
- }
-
- //
- // add PKCS7 padding
- //
- byte code = (byte)(blockSize - bufOff);
-
- while (bufOff < blockSize)
- {
- buf[bufOff] = code;
- bufOff++;
- }
-
- resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen);
- }
- else
- {
- if (bufOff == blockSize)
- {
- resultLen = cipher.processBlock(buf, 0, buf, 0);
- bufOff = 0;
- }
- else
- {
- throw new DataLengthException("last block incomplete in decryption");
- }
-
- //
- // remove PKCS7 padding
- //
- int count = buf[blockSize - 1] & 0xff;
-
- if ((count < 0) || (count > blockSize))
- {
- throw new InvalidCipherTextException("pad block corrupted");
- }
-
- resultLen -= count;
-
- System.arraycopy(buf, 0, out, outOff, resultLen);
- }
-
- reset();
-
- return resultLen;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java
deleted file mode 100644
index 5dd47ae6..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java
+++ /dev/null
@@ -1,225 +0,0 @@
-package org.bouncycastle.crypto.modes;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.SkippingStreamCipher;
-import org.bouncycastle.crypto.StreamBlockCipher;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Pack;
-
-/**
- * Implements the Segmented Integer Counter (SIC) mode on top of a simple
- * block cipher. This mode is also known as CTR mode.
- */
-public class SICBlockCipher
- extends StreamBlockCipher
- implements SkippingStreamCipher
-{
- private final BlockCipher cipher;
- private final int blockSize;
-
- private byte[] IV;
- private byte[] counter;
- private byte[] counterOut;
- private int byteCount;
-
- /**
- * Basic constructor.
- *
- * @param c the block cipher to be used.
- */
- public SICBlockCipher(BlockCipher c)
- {
- super(c);
-
- this.cipher = c;
- this.blockSize = cipher.getBlockSize();
- this.IV = new byte[blockSize];
- this.counter = new byte[blockSize];
- this.counterOut = new byte[blockSize];
- this.byteCount = 0;
- }
-
- public void init(
- boolean forEncryption, //ignored by this CTR mode
- CipherParameters params)
- throws IllegalArgumentException
- {
- if (params instanceof ParametersWithIV)
- {
- ParametersWithIV ivParam = (ParametersWithIV)params;
- byte[] iv = ivParam.getIV();
- System.arraycopy(iv, 0, IV, 0, IV.length);
-
- // if null it's an IV changed only.
- if (ivParam.getParameters() != null)
- {
- cipher.init(true, ivParam.getParameters());
- }
-
- reset();
- }
- else
- {
- throw new IllegalArgumentException("SIC mode requires ParametersWithIV");
- }
- }
-
- public String getAlgorithmName()
- {
- return cipher.getAlgorithmName() + "/SIC";
- }
-
- public int getBlockSize()
- {
- return cipher.getBlockSize();
- }
-
- public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
- throws DataLengthException, IllegalStateException
- {
- processBytes(in, inOff, blockSize, out, outOff);
-
- return blockSize;
- }
-
- protected byte calculateByte(byte in)
- throws DataLengthException, IllegalStateException
- {
- if (byteCount == 0)
- {
- cipher.processBlock(counter, 0, counterOut, 0);
-
- return (byte)(counterOut[byteCount++] ^ in);
- }
-
- byte rv = (byte)(counterOut[byteCount++] ^ in);
-
- if (byteCount == counter.length)
- {
- byteCount = 0;
-
- incrementCounter();
- }
-
- return rv;
- }
-
- private void incrementCounter()
- {
- // increment counter by 1.
- for (int i = counter.length - 1; i >= 0 && ++counter[i] == 0; i--)
- {
- ; // do nothing - pre-increment and test for 0 in counter does the job.
- }
- }
-
- private void decrementCounter()
- {
- if (counter[0] == 0)
- {
- boolean nonZero = false;
-
- for (int i = counter.length - 1; i > 0; i--)
- {
- if (counter[i] != 0)
- {
- nonZero = true;
- }
- }
-
- if (!nonZero)
- {
- throw new IllegalStateException("attempt to reduce counter past zero.");
- }
- }
-
- // decrement counter by 1.
- for (int i = counter.length - 1; i >= 0 && --counter[i] == -1; i--)
- {
- ;
- }
- }
-
- private void adjustCounter(long n)
- {
- if (n >= 0)
- {
- long numBlocks = (n + byteCount) / blockSize;
-
- for (long i = 0; i != numBlocks; i++)
- {
- incrementCounter();
- }
-
- byteCount = (int)((n + byteCount) - (blockSize * numBlocks));
- }
- else
- {
- long numBlocks = (-n - byteCount) / blockSize;
-
- for (long i = 0; i != numBlocks; i++)
- {
- decrementCounter();
- }
-
- int gap = (int)(byteCount + n + (blockSize * numBlocks));
-
- if (gap >= 0)
- {
- byteCount = 0;
- }
- else
- {
- decrementCounter();
- byteCount = blockSize + gap;
- }
- }
- }
-
- public void reset()
- {
- System.arraycopy(IV, 0, counter, 0, counter.length);
- cipher.reset();
- this.byteCount = 0;
- }
-
- public long skip(long numberOfBytes)
- {
- adjustCounter(numberOfBytes);
-
- cipher.processBlock(counter, 0, counterOut, 0);
-
- return numberOfBytes;
- }
-
- public long seekTo(long position)
- {
- reset();
-
- return skip(position);
- }
-
- public long getPosition()
- {
- byte[] res = new byte[IV.length];
-
- System.arraycopy(counter, 0, res, 0, res.length);
-
- for (int i = res.length - 1; i >= 1; i--)
- {
- int v = (res[i] - IV[i]);
-
- if (v < 0)
- {
- res[i - 1]--;
- v += 256;
- }
-
- res[i] = (byte)v;
- }
-
- return Pack.bigEndianToLong(res, res.length - 8) * blockSize + byteCount;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/gcm/BasicGCMExponentiator.java b/core/src/main/java/org/bouncycastle/crypto/modes/gcm/BasicGCMExponentiator.java
deleted file mode 100644
index fc25810d..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/gcm/BasicGCMExponentiator.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.bouncycastle.crypto.modes.gcm;
-
-import org.bouncycastle.util.Arrays;
-
-public class BasicGCMExponentiator implements GCMExponentiator
-{
- private int[] x;
-
- public void init(byte[] x)
- {
- this.x = GCMUtil.asInts(x);
- }
-
- public void exponentiateX(long pow, byte[] output)
- {
- // Initial value is little-endian 1
- int[] y = GCMUtil.oneAsInts();
-
- if (pow > 0)
- {
- int[] powX = Arrays.clone(x);
- do
- {
- if ((pow & 1L) != 0)
- {
- GCMUtil.multiply(y, powX);
- }
- GCMUtil.multiply(powX, powX);
- pow >>>= 1;
- }
- while (pow > 0);
- }
-
- GCMUtil.asBytes(y, output);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/gcm/BasicGCMMultiplier.java b/core/src/main/java/org/bouncycastle/crypto/modes/gcm/BasicGCMMultiplier.java
deleted file mode 100644
index a98d5b2a..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/gcm/BasicGCMMultiplier.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.bouncycastle.crypto.modes.gcm;
-
-import org.bouncycastle.util.Arrays;
-
-public class BasicGCMMultiplier implements GCMMultiplier
-{
- private byte[] H;
-
- public void init(byte[] H)
- {
- this.H = Arrays.clone(H);
- }
-
- public void multiplyH(byte[] x)
- {
- GCMUtil.multiply(x, H);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMExponentiator.java b/core/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMExponentiator.java
deleted file mode 100644
index e1cc5c76..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMExponentiator.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.bouncycastle.crypto.modes.gcm;
-
-public interface GCMExponentiator
-{
- void init(byte[] x);
- void exponentiateX(long pow, byte[] output);
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMMultiplier.java b/core/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMMultiplier.java
deleted file mode 100644
index f52f6105..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMMultiplier.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.bouncycastle.crypto.modes.gcm;
-
-public interface GCMMultiplier
-{
- void init(byte[] H);
- void multiplyH(byte[] x);
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java b/core/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java
deleted file mode 100644
index f5ed7e4f..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java
+++ /dev/null
@@ -1,457 +0,0 @@
-package org.bouncycastle.crypto.modes.gcm;
-
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Pack;
-
-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];
- tmp[0] = (byte)0x80;
- return tmp;
- }
-
- static int[] oneAsInts()
- {
- int[] tmp = new int[4];
- tmp[0] = 1 << 31;
- return tmp;
- }
-
- static long[] oneAsLongs()
- {
- long[] tmp = new long[2];
- tmp[0] = 1L << 63;
- return tmp;
- }
-
- 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)
- {
- Pack.bigEndianToInt(x, 0, z);
- }
-
- static long[] asLongs(byte[] x)
- {
- long[] z = new long[2];
- Pack.bigEndianToLong(x, 0, z);
- return z;
- }
-
- static void asLongs(byte[] x, long[] z)
- {
- Pack.bigEndianToLong(x, 0, z);
- }
-
- static void multiply(byte[] x, byte[] y)
- {
- byte[] r0 = Arrays.clone(x);
- byte[] r1 = new byte[16];
-
- for (int i = 0; i < 16; ++i)
- {
- byte bits = y[i];
- for (int j = 7; j >= 0; --j)
- {
- if ((bits & (1 << j)) != 0)
- {
- xor(r1, r0);
- }
-
- if (shiftRight(r0) != 0)
- {
- r0[0] ^= E1B;
- }
- }
- }
-
- 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)
- {
- if (shiftRight(x) != 0)
- {
- x[0] ^= E1;
- }
- }
-
- static void multiplyP(int[] x, int[] y)
- {
- if (shiftRight(x, y) != 0)
- {
- y[0] ^= E1;
- }
- }
-
- // P is the value with only bit i=1 set
- static void multiplyP8(int[] x)
- {
-// for (int i = 8; i != 0; --i)
-// {
-// multiplyP(x);
-// }
-
- int c = shiftRightN(x, 8);
- x[0] ^= LOOKUP[c >>> 24];
- }
-
- static void multiplyP8(int[] x, int[] y)
- {
- int c = shiftRightN(x, 8, y);
- y[0] ^= LOOKUP[c >>> 24];
- }
-
- static byte shiftRight(byte[] x)
- {
-// 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 = 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 byte shiftRight(byte[] x, byte[] z)
- {
-// 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 = 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 int shiftRight(int[] x)
- {
-// int c = 0;
-// for (int i = 0; i < 4; ++i)
-// {
-// int b = x[i];
-// x[i] = (b >>> 1) | c;
-// c = b << 31;
-// }
-// return c;
-
- int b = x[0];
- x[0] = b >>> 1;
- int c = b << 31;
- b = x[1];
- x[1] = (b >>> 1) | c;
- c = b << 31;
- b = x[2];
- x[2] = (b >>> 1) | c;
- c = b << 31;
- b = x[3];
- x[3] = (b >>> 1) | c;
- return b << 31;
- }
-
- static int shiftRight(int[] x, int[] z)
- {
-// int c = 0;
-// for (int i = 0; i < 4; ++i)
-// {
-// int b = x[i];
-// z[i] = (b >>> 1) | c;
-// c = b << 31;
-// }
-// return c;
-
- int b = x[0];
- z[0] = b >>> 1;
- int c = b << 31;
- b = x[1];
- z[1] = (b >>> 1) | c;
- c = b << 31;
- b = x[2];
- z[2] = (b >>> 1) | c;
- c = b << 31;
- b = x[3];
- z[3] = (b >>> 1) | c;
- return b << 31;
- }
-
- static long shiftRight(long[] x)
- {
- long b = x[0];
- x[0] = b >>> 1;
- long c = b << 63;
- b = x[1];
- x[1] = (b >>> 1) | c;
- return b << 63;
- }
-
- static long shiftRight(long[] x, long[] z)
- {
- long b = x[0];
- z[0] = b >>> 1;
- long c = b << 63;
- b = x[1];
- z[1] = (b >>> 1) | c;
- return b << 63;
- }
-
- static int shiftRightN(int[] x, int n)
- {
-// int c = 0, nInv = 32 - n;
-// for (int i = 0; i < 4; ++i)
-// {
-// int b = x[i];
-// x[i] = (b >>> n) | c;
-// c = b << nInv;
-// }
-// return c;
-
- int b = x[0], nInv = 32 - n;
- x[0] = b >>> n;
- int c = b << nInv;
- b = x[1];
- x[1] = (b >>> n) | c;
- c = b << nInv;
- b = x[2];
- x[2] = (b >>> n) | c;
- c = b << nInv;
- b = x[3];
- x[3] = (b >>> n) | c;
- return b << nInv;
- }
-
- static int shiftRightN(int[] x, int n, int[] z)
- {
-// int c = 0, nInv = 32 - n;
-// for (int i = 0; i < 4; ++i)
-// {
-// int b = x[i];
-// z[i] = (b >>> n) | c;
-// c = b << nInv;
-// }
-// return c;
-
- int b = x[0], nInv = 32 - n;
- z[0] = b >>> n;
- int c = b << nInv;
- b = x[1];
- z[1] = (b >>> n) | c;
- c = b << nInv;
- b = x[2];
- z[2] = (b >>> n) | c;
- c = b << nInv;
- b = x[3];
- z[3] = (b >>> n) | c;
- return b << nInv;
- }
-
- static void xor(byte[] x, byte[] y)
- {
- int i = 0;
- do
- {
- 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[] x, byte[] y, int yOff, int yLen)
- {
- while (yLen-- > 0)
- {
- x[yLen] ^= y[yOff + yLen];
- }
- }
-
- static void xor(byte[] x, byte[] y, byte[] z)
- {
- int i = 0;
- do
- {
- 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(int[] x, int[] y)
- {
- x[0] ^= y[0];
- x[1] ^= y[1];
- x[2] ^= y[2];
- x[3] ^= y[3];
- }
-
- static void xor(int[] x, int[] y, int[] z)
- {
- 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(long[] x, long[] y)
- {
- 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/core/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java b/core/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java
deleted file mode 100644
index 6eff4e3f..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.bouncycastle.crypto.modes.gcm;
-
-import java.util.Vector;
-
-import org.bouncycastle.util.Arrays;
-
-public class Tables1kGCMExponentiator implements GCMExponentiator
-{
- // A lookup table of the power-of-two powers of 'x'
- // - lookupPowX2[i] = x^(2^i)
- private Vector lookupPowX2;
-
- public void init(byte[] x)
- {
- int[] y = GCMUtil.asInts(x);
- if (lookupPowX2 != null && Arrays.areEqual(y, (int[])lookupPowX2.elementAt(0)))
- {
- return;
- }
-
- lookupPowX2 = new Vector(8);
- lookupPowX2.addElement(y);
- }
-
- public void exponentiateX(long pow, byte[] output)
- {
- int[] y = GCMUtil.oneAsInts();
- int bit = 0;
- while (pow > 0)
- {
- if ((pow & 1L) != 0)
- {
- ensureAvailable(bit);
- GCMUtil.multiply(y, (int[])lookupPowX2.elementAt(bit));
- }
- ++bit;
- pow >>>= 1;
- }
-
- GCMUtil.asBytes(y, output);
- }
-
- private void ensureAvailable(int bit)
- {
- int count = lookupPowX2.size();
- if (count <= bit)
- {
- int[] tmp = (int[])lookupPowX2.elementAt(count - 1);
- do
- {
- tmp = Arrays.clone(tmp);
- GCMUtil.multiply(tmp, tmp);
- lookupPowX2.addElement(tmp);
- }
- while (++count <= bit);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables64kGCMMultiplier.java b/core/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables64kGCMMultiplier.java
deleted file mode 100644
index 4f32a0d9..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables64kGCMMultiplier.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package org.bouncycastle.crypto.modes.gcm;
-
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Pack;
-
-public class Tables64kGCMMultiplier implements GCMMultiplier
-{
- private byte[] H;
- private int[][][] M;
-
- public void init(byte[] H)
- {
- if (M == null)
- {
- M = new int[16][256][4];
- }
- else if (Arrays.areEqual(this.H, H))
- {
- return;
- }
-
- this.H = Arrays.clone(H);
-
- // M[0][0] is ZEROES;
- GCMUtil.asInts(H, M[0][128]);
-
- for (int j = 64; j >= 1; j >>= 1)
- {
- GCMUtil.multiplyP(M[0][j + j], M[0][j]);
- }
-
- int i = 0;
- for (;;)
- {
- for (int j = 2; j < 256; j += j)
- {
- for (int k = 1; k < j; ++k)
- {
- GCMUtil.xor(M[i][j], M[i][k], M[i][j + k]);
- }
- }
-
- if (++i == 16)
- {
- return;
- }
-
- // M[i][0] is ZEROES;
- for (int j = 128; j > 0; j >>= 1)
- {
- GCMUtil.multiplyP8(M[i - 1][j], M[i][j]);
- }
- }
- }
-
- public void multiplyH(byte[] x)
- {
-// assert x.Length == 16;
-
- int[] z = new int[4];
- for (int i = 15; i >= 0; --i)
- {
-// GCMUtil.xor(z, M[i][x[i] & 0xff]);
- int[] m = M[i][x[i] & 0xff];
- z[0] ^= m[0];
- z[1] ^= m[1];
- z[2] ^= m[2];
- z[3] ^= m[3];
- }
-
- Pack.intToBigEndian(z, x, 0);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java b/core/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java
deleted file mode 100644
index 69c1dce8..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package org.bouncycastle.crypto.modes.gcm;
-
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Pack;
-
-public class Tables8kGCMMultiplier implements GCMMultiplier
-{
- private byte[] H;
- private int[][][] M;
-
- public void init(byte[] H)
- {
- if (M == null)
- {
- M = new int[32][16][4];
- }
- else if (Arrays.areEqual(this.H, H))
- {
- return;
- }
-
- this.H = Arrays.clone(H);
-
- // M[0][0] is ZEROES;
- // M[1][0] is ZEROES;
- GCMUtil.asInts(H, M[1][8]);
-
- for (int j = 4; j >= 1; j >>= 1)
- {
- GCMUtil.multiplyP(M[1][j + j], M[1][j]);
- }
-
- GCMUtil.multiplyP(M[1][1], M[0][8]);
-
- for (int j = 4; j >= 1; j >>= 1)
- {
- GCMUtil.multiplyP(M[0][j + j], M[0][j]);
- }
-
- int i = 0;
- for (;;)
- {
- for (int j = 2; j < 16; j += j)
- {
- for (int k = 1; k < j; ++k)
- {
- GCMUtil.xor(M[i][j], M[i][k], M[i][j + k]);
- }
- }
-
- if (++i == 32)
- {
- return;
- }
-
- if (i > 1)
- {
- // M[i][0] is ZEROES;
- for(int j = 8; j > 0; j >>= 1)
- {
- GCMUtil.multiplyP8(M[i - 2][j], M[i][j]);
- }
- }
- }
- }
-
- public void multiplyH(byte[] x)
- {
-// assert x.Length == 16;
-
- int[] z = new int[4];
- for (int i = 15; i >= 0; --i)
- {
-// GCMUtil.xor(z, M[i + i][x[i] & 0x0f]);
- int[] m = M[i + i][x[i] & 0x0f];
- z[0] ^= m[0];
- z[1] ^= m[1];
- z[2] ^= m[2];
- z[3] ^= m[3];
-// GCMUtil.xor(z, M[i + i + 1][(x[i] & 0xf0) >>> 4]);
- m = M[i + i + 1][(x[i] & 0xf0) >>> 4];
- z[0] ^= m[0];
- z[1] ^= m[1];
- z[2] ^= m[2];
- z[3] ^= m[3];
- }
-
- Pack.intToBigEndian(z, x, 0);
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/crypto/paddings/BlockCipherPadding.java b/core/src/main/java/org/bouncycastle/crypto/paddings/BlockCipherPadding.java
deleted file mode 100644
index 7c4f0aee..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/paddings/BlockCipherPadding.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.bouncycastle.crypto.paddings;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.InvalidCipherTextException;
-
-/**
- * Block cipher padders are expected to conform to this interface
- */
-public interface BlockCipherPadding
-{
- /**
- * Initialise the padder.
- *
- * @param random the source of randomness for the padding, if required.
- */
- public void init(SecureRandom random)
- throws IllegalArgumentException;
-
- /**
- * Return the name of the algorithm the cipher implements.
- *
- * @return the name of the algorithm the cipher implements.
- */
- public String getPaddingName();
-
- /**
- * add the pad bytes to the passed in block, returning the
- * number of bytes added.
- * <p>
- * Note: this assumes that the last block of plain text is always
- * passed to it inside in. i.e. if inOff is zero, indicating the
- * entire block is to be overwritten with padding the value of in
- * should be the same as the last block of plain text. The reason
- * for this is that some modes such as "trailing bit compliment"
- * base the padding on the last byte of plain text.
- * </p>
- */
- public int addPadding(byte[] in, int inOff);
-
- /**
- * return the number of pad bytes present in the block.
- * @exception InvalidCipherTextException if the padding is badly formed
- * or invalid.
- */
- public int padCount(byte[] in)
- throws InvalidCipherTextException;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/paddings/ISO10126d2Padding.java b/core/src/main/java/org/bouncycastle/crypto/paddings/ISO10126d2Padding.java
deleted file mode 100644
index 63e29d84..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/paddings/ISO10126d2Padding.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.bouncycastle.crypto.paddings;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.InvalidCipherTextException;
-
-/**
- * A padder that adds ISO10126-2 padding to a block.
- */
-public class ISO10126d2Padding
- implements BlockCipherPadding
-{
- SecureRandom random;
-
- /**
- * Initialise the padder.
- *
- * @param random a SecureRandom if available.
- */
- public void init(SecureRandom random)
- throws IllegalArgumentException
- {
- if (random != null)
- {
- this.random = random;
- }
- else
- {
- this.random = new SecureRandom();
- }
- }
-
- /**
- * Return the name of the algorithm the padder implements.
- *
- * @return the name of the algorithm the padder implements.
- */
- public String getPaddingName()
- {
- return "ISO10126-2";
- }
-
- /**
- * add the pad bytes to the passed in block, returning the
- * number of bytes added.
- */
- public int addPadding(
- byte[] in,
- int inOff)
- {
- byte code = (byte)(in.length - inOff);
-
- while (inOff < (in.length - 1))
- {
- in[inOff] = (byte)random.nextInt();
- inOff++;
- }
-
- in[inOff] = code;
-
- return code;
- }
-
- /**
- * return the number of pad bytes present in the block.
- */
- public int padCount(byte[] in)
- throws InvalidCipherTextException
- {
- int count = in[in.length - 1] & 0xff;
-
- if (count > in.length)
- {
- throw new InvalidCipherTextException("pad block corrupted");
- }
-
- return count;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/paddings/ISO7816d4Padding.java b/core/src/main/java/org/bouncycastle/crypto/paddings/ISO7816d4Padding.java
deleted file mode 100644
index 54c31a9b..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/paddings/ISO7816d4Padding.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package org.bouncycastle.crypto.paddings;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.InvalidCipherTextException;
-
-/**
- * A padder that adds the padding according to the scheme referenced in
- * ISO 7814-4 - scheme 2 from ISO 9797-1. The first byte is 0x80, rest is 0x00
- */
-public class ISO7816d4Padding
- implements BlockCipherPadding
-{
- /**
- * Initialise the padder.
- *
- * @param random - a SecureRandom if available.
- */
- public void init(SecureRandom random)
- throws IllegalArgumentException
- {
- // nothing to do.
- }
-
- /**
- * Return the name of the algorithm the padder implements.
- *
- * @return the name of the algorithm the padder implements.
- */
- public String getPaddingName()
- {
- return "ISO7816-4";
- }
-
- /**
- * add the pad bytes to the passed in block, returning the
- * number of bytes added.
- */
- public int addPadding(
- byte[] in,
- int inOff)
- {
- int added = (in.length - inOff);
-
- in [inOff]= (byte) 0x80;
- inOff ++;
-
- while (inOff < in.length)
- {
- in[inOff] = (byte) 0;
- inOff++;
- }
-
- return added;
- }
-
- /**
- * return the number of pad bytes present in the block.
- */
- public int padCount(byte[] in)
- throws InvalidCipherTextException
- {
- int count = in.length - 1;
-
- while (count > 0 && in[count] == 0)
- {
- count--;
- }
-
- if (in[count] != (byte)0x80)
- {
- throw new InvalidCipherTextException("pad block corrupted");
- }
-
- return in.length - count;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/paddings/PKCS7Padding.java b/core/src/main/java/org/bouncycastle/crypto/paddings/PKCS7Padding.java
deleted file mode 100644
index 93b149fa..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/paddings/PKCS7Padding.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package org.bouncycastle.crypto.paddings;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.InvalidCipherTextException;
-
-/**
- * A padder that adds PKCS7/PKCS5 padding to a block.
- */
-public class PKCS7Padding
- implements BlockCipherPadding
-{
- /**
- * Initialise the padder.
- *
- * @param random - a SecureRandom if available.
- */
- public void init(SecureRandom random)
- throws IllegalArgumentException
- {
- // nothing to do.
- }
-
- /**
- * Return the name of the algorithm the padder implements.
- *
- * @return the name of the algorithm the padder implements.
- */
- public String getPaddingName()
- {
- return "PKCS7";
- }
-
- /**
- * add the pad bytes to the passed in block, returning the
- * number of bytes added.
- */
- public int addPadding(
- byte[] in,
- int inOff)
- {
- byte code = (byte)(in.length - inOff);
-
- while (inOff < in.length)
- {
- in[inOff] = code;
- inOff++;
- }
-
- return code;
- }
-
- /**
- * return the number of pad bytes present in the block.
- */
- public int padCount(byte[] in)
- throws InvalidCipherTextException
- {
- int count = in[in.length - 1] & 0xff;
-
- if (count > in.length || count == 0)
- {
- throw new InvalidCipherTextException("pad block corrupted");
- }
-
- for (int i = 1; i <= count; i++)
- {
- if (in[in.length - i] != count)
- {
- throw new InvalidCipherTextException("pad block corrupted");
- }
- }
-
- return count;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java
deleted file mode 100644
index d5928f70..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java
+++ /dev/null
@@ -1,299 +0,0 @@
-package org.bouncycastle.crypto.paddings;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.BufferedBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.OutputLengthException;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-
-/**
- * A wrapper class that allows block ciphers to be used to process data in
- * a piecemeal fashion with padding. The PaddedBufferedBlockCipher
- * outputs a block only when the buffer is full and more data is being added,
- * or on a doFinal (unless the current block in the buffer is a pad block).
- * The default padding mechanism used is the one outlined in PKCS5/PKCS7.
- */
-public class PaddedBufferedBlockCipher
- extends BufferedBlockCipher
-{
- BlockCipherPadding padding;
-
- /**
- * Create a buffered block cipher with the desired padding.
- *
- * @param cipher the underlying block cipher this buffering object wraps.
- * @param padding the padding type.
- */
- public PaddedBufferedBlockCipher(
- BlockCipher cipher,
- BlockCipherPadding padding)
- {
- this.cipher = cipher;
- this.padding = padding;
-
- buf = new byte[cipher.getBlockSize()];
- bufOff = 0;
- }
-
- /**
- * Create a buffered block cipher PKCS7 padding
- *
- * @param cipher the underlying block cipher this buffering object wraps.
- */
- public PaddedBufferedBlockCipher(
- BlockCipher cipher)
- {
- this(cipher, new PKCS7Padding());
- }
-
- /**
- * initialise the cipher.
- *
- * @param forEncryption if true the cipher is initialised for
- * encryption, if false for decryption.
- * @param params the key and other data required by the cipher.
- * @exception IllegalArgumentException if the params argument is
- * inappropriate.
- */
- public void init(
- boolean forEncryption,
- CipherParameters params)
- throws IllegalArgumentException
- {
- this.forEncryption = forEncryption;
-
- reset();
-
- if (params instanceof ParametersWithRandom)
- {
- ParametersWithRandom p = (ParametersWithRandom)params;
-
- padding.init(p.getRandom());
-
- cipher.init(forEncryption, p.getParameters());
- }
- else
- {
- padding.init(null);
-
- cipher.init(forEncryption, params);
- }
- }
-
- /**
- * return the minimum 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)
- {
- int total = len + bufOff;
- int leftOver = total % buf.length;
-
- if (leftOver == 0)
- {
- if (forEncryption)
- {
- return total + buf.length;
- }
-
- return total;
- }
-
- return total - leftOver + buf.length;
- }
-
- /**
- * 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 Math.max(0, total - buf.length);
- }
-
- return total - leftOver;
- }
-
- /**
- * process a single byte, producing an output block if neccessary.
- *
- * @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 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);
- bufOff = 0;
- }
-
- 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 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 OutputLengthException("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);
-
- bufOff = 0;
- len -= gapLen;
- inOff += gapLen;
-
- while (len > buf.length)
- {
- resultLen += cipher.processBlock(in, inOff, out, outOff + resultLen);
-
- len -= blockSize;
- inOff += blockSize;
- }
- }
-
- System.arraycopy(in, inOff, buf, bufOff, len);
-
- bufOff += len;
-
- return resultLen;
- }
-
- /**
- * Process the last block in the buffer. If the buffer is currently
- * full and padding needs to be added a call to doFinal will produce
- * 2 * getBlockSize() bytes.
- *
- * @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 DataLengthException if there is insufficient space in out for
- * the output or we are decrypting and the input is not block size aligned.
- * @exception IllegalStateException if the underlying cipher is not
- * initialised.
- * @exception InvalidCipherTextException if padding is expected and not found.
- */
- public int doFinal(
- byte[] out,
- int outOff)
- throws DataLengthException, IllegalStateException, InvalidCipherTextException
- {
- int blockSize = cipher.getBlockSize();
- int resultLen = 0;
-
- if (forEncryption)
- {
- if (bufOff == blockSize)
- {
- if ((outOff + 2 * blockSize) > out.length)
- {
- reset();
-
- throw new OutputLengthException("output buffer too short");
- }
-
- resultLen = cipher.processBlock(buf, 0, out, outOff);
- bufOff = 0;
- }
-
- padding.addPadding(buf, bufOff);
-
- resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen);
-
- reset();
- }
- else
- {
- if (bufOff == blockSize)
- {
- resultLen = cipher.processBlock(buf, 0, buf, 0);
- bufOff = 0;
- }
- else
- {
- reset();
-
- throw new DataLengthException("last block incomplete in decryption");
- }
-
- try
- {
- resultLen -= padding.padCount(buf);
-
- System.arraycopy(buf, 0, out, outOff, resultLen);
- }
- finally
- {
- reset();
- }
- }
-
- return resultLen;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/paddings/TBCPadding.java b/core/src/main/java/org/bouncycastle/crypto/paddings/TBCPadding.java
deleted file mode 100644
index 219912fe..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/paddings/TBCPadding.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package org.bouncycastle.crypto.paddings;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.InvalidCipherTextException;
-
-/**
- * A padder that adds Trailing-Bit-Compliment padding to a block.
- * <p>
- * This padding pads the block out with the compliment of the last bit
- * of the plain text.
- * </p>
- */
-public class TBCPadding
- implements BlockCipherPadding
-{
- /**
- * Initialise the padder.
- *
- * @param random - a SecureRandom if available.
- */
- public void init(SecureRandom random)
- throws IllegalArgumentException
- {
- // nothing to do.
- }
-
- /**
- * Return the name of the algorithm the padder implements.
- *
- * @return the name of the algorithm the padder implements.
- */
- public String getPaddingName()
- {
- return "TBC";
- }
-
- /**
- * add the pad bytes to the passed in block, returning the
- * number of bytes added.
- * <p>
- * Note: this assumes that the last block of plain text is always
- * passed to it inside in. i.e. if inOff is zero, indicating the
- * entire block is to be overwritten with padding the value of in
- * should be the same as the last block of plain text.
- * </p>
- */
- public int addPadding(
- byte[] in,
- int inOff)
- {
- int count = in.length - inOff;
- byte code;
-
- if (inOff > 0)
- {
- code = (byte)((in[inOff - 1] & 0x01) == 0 ? 0xff : 0x00);
- }
- else
- {
- code = (byte)((in[in.length - 1] & 0x01) == 0 ? 0xff : 0x00);
- }
-
- while (inOff < in.length)
- {
- in[inOff] = code;
- inOff++;
- }
-
- return count;
- }
-
- /**
- * return the number of pad bytes present in the block.
- */
- public int padCount(byte[] in)
- throws InvalidCipherTextException
- {
- byte code = in[in.length - 1];
-
- int index = in.length - 1;
- while (index > 0 && in[index - 1] == code)
- {
- index--;
- }
-
- return in.length - index;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/paddings/X923Padding.java b/core/src/main/java/org/bouncycastle/crypto/paddings/X923Padding.java
deleted file mode 100644
index d4d34aad..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/paddings/X923Padding.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package org.bouncycastle.crypto.paddings;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.InvalidCipherTextException;
-
-/**
- * A padder that adds X9.23 padding to a block - if a SecureRandom is
- * passed in random padding is assumed, otherwise padding with zeros is used.
- */
-public class X923Padding
- implements BlockCipherPadding
-{
- SecureRandom random = null;
-
- /**
- * Initialise the padder.
- *
- * @param random a SecureRandom if one is available.
- */
- public void init(SecureRandom random)
- throws IllegalArgumentException
- {
- this.random = random;
- }
-
- /**
- * Return the name of the algorithm the padder implements.
- *
- * @return the name of the algorithm the padder implements.
- */
- public String getPaddingName()
- {
- return "X9.23";
- }
-
- /**
- * add the pad bytes to the passed in block, returning the
- * number of bytes added.
- */
- public int addPadding(
- byte[] in,
- int inOff)
- {
- byte code = (byte)(in.length - inOff);
-
- while (inOff < in.length - 1)
- {
- if (random == null)
- {
- in[inOff] = 0;
- }
- else
- {
- in[inOff] = (byte)random.nextInt();
- }
- inOff++;
- }
-
- in[inOff] = code;
-
- return code;
- }
-
- /**
- * return the number of pad bytes present in the block.
- */
- public int padCount(byte[] in)
- throws InvalidCipherTextException
- {
- int count = in[in.length - 1] & 0xff;
-
- if (count > in.length)
- {
- throw new InvalidCipherTextException("pad block corrupted");
- }
-
- return count;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/paddings/ZeroBytePadding.java b/core/src/main/java/org/bouncycastle/crypto/paddings/ZeroBytePadding.java
deleted file mode 100644
index c7560286..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/paddings/ZeroBytePadding.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package org.bouncycastle.crypto.paddings;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.InvalidCipherTextException;
-
-/**
- * A padder that adds NULL byte padding to a block.
- */
-public class ZeroBytePadding
- implements BlockCipherPadding
-{
- /**
- * Initialise the padder.
- *
- * @param random - a SecureRandom if available.
- */
- public void init(SecureRandom random)
- throws IllegalArgumentException
- {
- // nothing to do.
- }
-
- /**
- * Return the name of the algorithm the padder implements.
- *
- * @return the name of the algorithm the padder implements.
- */
- public String getPaddingName()
- {
- return "ZeroByte";
- }
-
- /**
- * add the pad bytes to the passed in block, returning the
- * number of bytes added.
- */
- public int addPadding(
- byte[] in,
- int inOff)
- {
- int added = (in.length - inOff);
-
- while (inOff < in.length)
- {
- in[inOff] = (byte) 0;
- inOff++;
- }
-
- return added;
- }
-
- /**
- * return the number of pad bytes present in the block.
- */
- public int padCount(byte[] in)
- throws InvalidCipherTextException
- {
- int count = in.length;
-
- while (count > 0)
- {
- if (in[count - 1] != 0)
- {
- break;
- }
-
- count--;
- }
-
- return in.length - count;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/AEADParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/AEADParameters.java
deleted file mode 100644
index 9a9272ba..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/AEADParameters.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public class AEADParameters
- implements CipherParameters
-{
- private byte[] associatedText;
- private byte[] nonce;
- private KeyParameter key;
- private int macSize;
-
- /**
- * Base constructor.
- *
- * @param key key to be used by underlying cipher
- * @param macSize macSize in bits
- * @param nonce nonce to be used
- */
- public AEADParameters(KeyParameter key, int macSize, byte[] nonce)
- {
- this(key, macSize, nonce, null);
- }
-
- /**
- * Base constructor.
- *
- * @param key key to be used by underlying cipher
- * @param macSize macSize in bits
- * @param nonce nonce to be used
- * @param associatedText initial associated text, if any
- */
- public AEADParameters(KeyParameter key, int macSize, byte[] nonce, byte[] associatedText)
- {
- this.key = key;
- this.nonce = nonce;
- this.macSize = macSize;
- this.associatedText = associatedText;
- }
-
- public KeyParameter getKey()
- {
- return key;
- }
-
- public int getMacSize()
- {
- return macSize;
- }
-
- public byte[] getAssociatedText()
- {
- return associatedText;
- }
-
- public byte[] getNonce()
- {
- return nonce;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/AsymmetricKeyParameter.java b/core/src/main/java/org/bouncycastle/crypto/params/AsymmetricKeyParameter.java
deleted file mode 100644
index 03ba7253..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/AsymmetricKeyParameter.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public class AsymmetricKeyParameter
- implements CipherParameters
-{
- boolean privateKey;
-
- public AsymmetricKeyParameter(
- boolean privateKey)
- {
- this.privateKey = privateKey;
- }
-
- public boolean isPrivate()
- {
- return privateKey;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/CCMParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/CCMParameters.java
deleted file mode 100644
index 4924dcca..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/CCMParameters.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-/**
- * @deprecated use AEADParameters
- */
-public class CCMParameters
- extends AEADParameters
-{
- /**
- * Base constructor.
- *
- * @param key key to be used by underlying cipher
- * @param macSize macSize in bits
- * @param nonce nonce to be used
- * @param associatedText associated text, if any
- */
- public CCMParameters(KeyParameter key, int macSize, byte[] nonce, byte[] associatedText)
- {
- super(key, macSize, nonce, associatedText);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupKeyGenerationParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupKeyGenerationParameters.java
deleted file mode 100644
index 15b6d6a5..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupKeyGenerationParameters.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.KeyGenerationParameters;
-
-public class CramerShoupKeyGenerationParameters extends KeyGenerationParameters {
-
- private CramerShoupParameters params;
-
- public CramerShoupKeyGenerationParameters(SecureRandom random, CramerShoupParameters params) {
- super(random, getStrength(params));
-
- this.params = params;
- }
-
- public CramerShoupParameters getParameters() {
- return params;
- }
-
- static int getStrength(CramerShoupParameters params) {
- return params.getP().bitLength();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupKeyParameters.java
deleted file mode 100644
index 9e4219c8..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupKeyParameters.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-public class CramerShoupKeyParameters extends AsymmetricKeyParameter {
-
- private CramerShoupParameters params;
-
- protected CramerShoupKeyParameters(boolean isPrivate, CramerShoupParameters params) {
- super(isPrivate);
-
- this.params = params;
- }
-
- public CramerShoupParameters getParameters() {
- return params;
- }
-
- public boolean equals(Object obj) {
- if (!(obj instanceof CramerShoupKeyParameters)) {
- return false;
- }
-
- CramerShoupKeyParameters csKey = (CramerShoupKeyParameters) obj;
-
- if (params == null) {
- return csKey.getParameters() == null;
- } else {
- return params.equals(csKey.getParameters());
- }
- }
-
- public int hashCode() {
- int code = isPrivate() ? 0 : 1;
-
- if (params != null) {
- code ^= params.hashCode();
- }
-
- return code;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupParameters.java
deleted file mode 100644
index 24264b6c..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupParameters.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-
-public class CramerShoupParameters implements CipherParameters {
-
- private BigInteger p; // prime order of G
- private BigInteger g1, g2; // generate G
-
- private Digest H; // hash function
-
- public CramerShoupParameters(BigInteger p, BigInteger g1, BigInteger g2, Digest H) {
- this.p = p;
- this.g1 = g1;
- this.g2 = g2;
- this.H = H;
- }
-
- public boolean equals(Object obj) {
- if (!(obj instanceof DSAParameters)) {
- return false;
- }
-
- CramerShoupParameters pm = (CramerShoupParameters) obj;
-
- return (pm.getP().equals(p) && pm.getG1().equals(g1) && pm.getG2().equals(g2));
- }
-
- public int hashCode() {
- return getP().hashCode() ^ getG1().hashCode() ^ getG2().hashCode();
- }
-
- public BigInteger getG1() {
- return g1;
- }
-
- public BigInteger getG2() {
- return g2;
- }
-
- public BigInteger getP() {
- return p;
- }
-
- public Digest getH() {
- H.reset();
- return H;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupPrivateKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupPrivateKeyParameters.java
deleted file mode 100644
index 79de46ad..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupPrivateKeyParameters.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-public class CramerShoupPrivateKeyParameters extends CramerShoupKeyParameters {
-
- private BigInteger x1, x2, y1, y2, z; // Z_p
- private CramerShoupPublicKeyParameters pk; // public key
-
- public CramerShoupPrivateKeyParameters(CramerShoupParameters params, BigInteger x1, BigInteger x2, BigInteger y1, BigInteger y2, BigInteger z) {
- super(true, params);
-
- this.x1 = x1;
- this.x2 = x2;
- this.y1 = y1;
- this.y2 = y2;
- this.z = z;
- }
-
- public BigInteger getX1() {
- return x1;
- }
-
- public BigInteger getX2() {
- return x2;
- }
-
- public BigInteger getY1() {
- return y1;
- }
-
- public BigInteger getY2() {
- return y2;
- }
-
- public BigInteger getZ() {
- return z;
- }
-
- public void setPk(CramerShoupPublicKeyParameters pk) {
- this.pk = pk;
- }
-
- public CramerShoupPublicKeyParameters getPk() {
- return pk;
- }
-
- public int hashCode() {
- return x1.hashCode() ^ x2.hashCode() ^ y1.hashCode() ^ y2.hashCode() ^ z.hashCode() ^ super.hashCode();
- }
-
- public boolean equals(Object obj) {
- if (!(obj instanceof CramerShoupPrivateKeyParameters)) {
- return false;
- }
-
- CramerShoupPrivateKeyParameters other = (CramerShoupPrivateKeyParameters) obj;
-
- return other.getX1().equals(this.x1) && other.getX2().equals(this.x2) && other.getY1().equals(this.y1) && other.getY2().equals(this.y2) && other.getZ().equals(this.z) && super.equals(obj);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupPublicKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupPublicKeyParameters.java
deleted file mode 100644
index 341149c1..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/CramerShoupPublicKeyParameters.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-public class CramerShoupPublicKeyParameters extends CramerShoupKeyParameters {
-
- private BigInteger c, d, h; // public key group elements
-
- public CramerShoupPublicKeyParameters(CramerShoupParameters params, BigInteger c, BigInteger d, BigInteger h) {
- super(false, params);
-
- this.c = c;
- this.d = d;
- this.h = h;
- }
-
- public BigInteger getC() {
- return c;
- }
-
- public BigInteger getD() {
- return d;
- }
-
- public BigInteger getH() {
- return h;
- }
-
- public int hashCode() {
- return c.hashCode() ^ d.hashCode() ^ h.hashCode() ^ super.hashCode();
- }
-
- public boolean equals(Object obj) {
- if (!(obj instanceof CramerShoupPublicKeyParameters)) {
- return false;
- }
-
- CramerShoupPublicKeyParameters other = (CramerShoupPublicKeyParameters) obj;
-
- return other.getC().equals(c) && other.getD().equals(d) && other.getH().equals(h) && super.equals(obj);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/DESParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/DESParameters.java
deleted file mode 100644
index 5bee3604..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/DESParameters.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-public class DESParameters
- extends KeyParameter
-{
- public DESParameters(
- byte[] key)
- {
- super(key);
-
- if (isWeakKey(key, 0))
- {
- throw new IllegalArgumentException("attempt to create weak DES key");
- }
- }
-
- /*
- * DES Key length in bytes.
- */
- static public final int DES_KEY_LENGTH = 8;
-
- /*
- * Table of weak and semi-weak keys taken from Schneier pp281
- */
- static private final int N_DES_WEAK_KEYS = 16;
-
- static private byte[] DES_weak_keys =
- {
- /* weak keys */
- (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01, (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01,
- (byte)0x1f,(byte)0x1f,(byte)0x1f,(byte)0x1f, (byte)0x0e,(byte)0x0e,(byte)0x0e,(byte)0x0e,
- (byte)0xe0,(byte)0xe0,(byte)0xe0,(byte)0xe0, (byte)0xf1,(byte)0xf1,(byte)0xf1,(byte)0xf1,
- (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe, (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe,
-
- /* semi-weak keys */
- (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe, (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe,
- (byte)0x1f,(byte)0xe0,(byte)0x1f,(byte)0xe0, (byte)0x0e,(byte)0xf1,(byte)0x0e,(byte)0xf1,
- (byte)0x01,(byte)0xe0,(byte)0x01,(byte)0xe0, (byte)0x01,(byte)0xf1,(byte)0x01,(byte)0xf1,
- (byte)0x1f,(byte)0xfe,(byte)0x1f,(byte)0xfe, (byte)0x0e,(byte)0xfe,(byte)0x0e,(byte)0xfe,
- (byte)0x01,(byte)0x1f,(byte)0x01,(byte)0x1f, (byte)0x01,(byte)0x0e,(byte)0x01,(byte)0x0e,
- (byte)0xe0,(byte)0xfe,(byte)0xe0,(byte)0xfe, (byte)0xf1,(byte)0xfe,(byte)0xf1,(byte)0xfe,
- (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01, (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01,
- (byte)0xe0,(byte)0x1f,(byte)0xe0,(byte)0x1f, (byte)0xf1,(byte)0x0e,(byte)0xf1,(byte)0x0e,
- (byte)0xe0,(byte)0x01,(byte)0xe0,(byte)0x01, (byte)0xf1,(byte)0x01,(byte)0xf1,(byte)0x01,
- (byte)0xfe,(byte)0x1f,(byte)0xfe,(byte)0x1f, (byte)0xfe,(byte)0x0e,(byte)0xfe,(byte)0x0e,
- (byte)0x1f,(byte)0x01,(byte)0x1f,(byte)0x01, (byte)0x0e,(byte)0x01,(byte)0x0e,(byte)0x01,
- (byte)0xfe,(byte)0xe0,(byte)0xfe,(byte)0xe0, (byte)0xfe,(byte)0xf1,(byte)0xfe,(byte)0xf1
- };
-
- /**
- * DES has 16 weak keys. This method will check
- * if the given DES key material is weak or semi-weak.
- * Key material that is too short is regarded as weak.
- * <p>
- * See <a href="http://www.counterpane.com/applied.html">"Applied
- * Cryptography"</a> by Bruce Schneier for more information.
- *
- * @return true if the given DES key material is weak or semi-weak,
- * false otherwise.
- */
- public static boolean isWeakKey(
- byte[] key,
- int offset)
- {
- if (key.length - offset < DES_KEY_LENGTH)
- {
- throw new IllegalArgumentException("key material too short.");
- }
-
- nextkey: for (int i = 0; i < N_DES_WEAK_KEYS; i++)
- {
- for (int j = 0; j < DES_KEY_LENGTH; j++)
- {
- if (key[j + offset] != DES_weak_keys[i * DES_KEY_LENGTH + j])
- {
- continue nextkey;
- }
- }
-
- return true;
- }
- return false;
- }
-
- /**
- * DES Keys use the LSB as the odd parity bit. This can
- * be used to check for corrupt keys.
- *
- * @param bytes the byte array to set the parity on.
- */
- public static void setOddParity(
- byte[] bytes)
- {
- for (int i = 0; i < bytes.length; i++)
- {
- int b = bytes[i];
- bytes[i] = (byte)((b & 0xfe) |
- ((((b >> 1) ^
- (b >> 2) ^
- (b >> 3) ^
- (b >> 4) ^
- (b >> 5) ^
- (b >> 6) ^
- (b >> 7)) ^ 0x01) & 0x01));
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/DESedeParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/DESedeParameters.java
deleted file mode 100644
index 3a4bbfca..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/DESedeParameters.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-public class DESedeParameters
- extends DESParameters
-{
- /*
- * DES-EDE Key length in bytes.
- */
- static public final int DES_EDE_KEY_LENGTH = 24;
-
- public DESedeParameters(
- byte[] key)
- {
- super(key);
-
- if (isWeakKey(key, 0, key.length))
- {
- throw new IllegalArgumentException("attempt to create weak DESede key");
- }
- }
-
- /**
- * return true if the passed in key is a DES-EDE weak key.
- *
- * @param key bytes making up the key
- * @param offset offset into the byte array the key starts at
- * @param length number of bytes making up the key
- */
- public static boolean isWeakKey(
- byte[] key,
- int offset,
- int length)
- {
- for (int i = offset; i < length; i += DES_KEY_LENGTH)
- {
- if (DESParameters.isWeakKey(key, i))
- {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * return true if the passed in key is a DES-EDE weak key.
- *
- * @param key bytes making up the key
- * @param offset offset into the byte array the key starts at
- */
- public static boolean isWeakKey(
- byte[] key,
- int offset)
- {
- return isWeakKey(key, offset, key.length - offset);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/DHKeyGenerationParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/DHKeyGenerationParameters.java
deleted file mode 100644
index 34c730eb..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/DHKeyGenerationParameters.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.KeyGenerationParameters;
-
-public class DHKeyGenerationParameters
- extends KeyGenerationParameters
-{
- private DHParameters params;
-
- public DHKeyGenerationParameters(
- SecureRandom random,
- DHParameters params)
- {
- super(random, getStrength(params));
-
- this.params = params;
- }
-
- public DHParameters getParameters()
- {
- return params;
- }
-
- static int getStrength(DHParameters params)
- {
- return params.getL() != 0 ? params.getL() : params.getP().bitLength();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/DHKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/DHKeyParameters.java
deleted file mode 100644
index e686f357..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/DHKeyParameters.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-
-public class DHKeyParameters
- extends AsymmetricKeyParameter
-{
- private DHParameters params;
-
- protected DHKeyParameters(
- boolean isPrivate,
- DHParameters params)
- {
- super(isPrivate);
-
- this.params = params;
- }
-
- public DHParameters getParameters()
- {
- return params;
- }
-
- public boolean equals(
- Object obj)
- {
- if (!(obj instanceof DHKeyParameters))
- {
- return false;
- }
-
- DHKeyParameters dhKey = (DHKeyParameters)obj;
-
- if (params == null)
- {
- return dhKey.getParameters() == null;
- }
- else
- {
- return params.equals(dhKey.getParameters());
- }
- }
-
- public int hashCode()
- {
- int code = isPrivate() ? 0 : 1;
-
- if (params != null)
- {
- code ^= params.hashCode();
- }
-
- return code;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/DHParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/DHParameters.java
deleted file mode 100644
index b679287c..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/DHParameters.java
+++ /dev/null
@@ -1,189 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public class DHParameters
- implements CipherParameters
-{
- private static final int DEFAULT_MINIMUM_LENGTH = 160;
-
- // not final due to compiler bug in "simpler" JDKs
- private BigInteger g;
- private BigInteger p;
- private BigInteger q;
- private BigInteger j;
- private int m;
- private int l;
- private DHValidationParameters validation;
-
- private static int getDefaultMParam(
- int lParam)
- {
- if (lParam == 0)
- {
- return DEFAULT_MINIMUM_LENGTH;
- }
-
- return lParam < DEFAULT_MINIMUM_LENGTH ? lParam : DEFAULT_MINIMUM_LENGTH;
- }
-
- public DHParameters(
- BigInteger p,
- BigInteger g)
- {
- this(p, g, null, 0);
- }
-
- public DHParameters(
- BigInteger p,
- BigInteger g,
- BigInteger q)
- {
- this(p, g, q, 0);
- }
-
- public DHParameters(
- BigInteger p,
- BigInteger g,
- BigInteger q,
- int l)
- {
- this(p, g, q, getDefaultMParam(l), l, null, null);
- }
-
- public DHParameters(
- BigInteger p,
- BigInteger g,
- BigInteger q,
- int m,
- int l)
- {
- this(p, g, q, m, l, null, null);
- }
-
- public DHParameters(
- BigInteger p,
- BigInteger g,
- BigInteger q,
- BigInteger j,
- DHValidationParameters validation)
- {
- this(p, g, q, DEFAULT_MINIMUM_LENGTH, 0, j, validation);
- }
-
- public DHParameters(
- BigInteger p,
- BigInteger g,
- BigInteger q,
- int m,
- int l,
- BigInteger j,
- DHValidationParameters validation)
- {
- if (l != 0)
- {
- BigInteger bigL = BigInteger.valueOf(2L ^ (l - 1));
- if (bigL.compareTo(p) == 1)
- {
- throw new IllegalArgumentException("when l value specified, it must satisfy 2^(l-1) <= p");
- }
- if (l < m)
- {
- throw new IllegalArgumentException("when l value specified, it may not be less than m value");
- }
- }
-
- this.g = g;
- this.p = p;
- this.q = q;
- this.m = m;
- this.l = l;
- this.j = j;
- this.validation = validation;
- }
-
- public BigInteger getP()
- {
- return p;
- }
-
- public BigInteger getG()
- {
- return g;
- }
-
- public BigInteger getQ()
- {
- return q;
- }
-
- /**
- * Return the subgroup factor J.
- *
- * @return subgroup factor
- */
- public BigInteger getJ()
- {
- return j;
- }
-
- /**
- * Return the minimum length of the private value.
- *
- * @return the minimum length of the private value in bits.
- */
- public int getM()
- {
- return m;
- }
-
- /**
- * Return the private value length in bits - if set, zero otherwise
- *
- * @return the private value length in bits, zero otherwise.
- */
- public int getL()
- {
- return l;
- }
-
- public DHValidationParameters getValidationParameters()
- {
- return validation;
- }
-
- public boolean equals(
- Object obj)
- {
- if (!(obj instanceof DHParameters))
- {
- return false;
- }
-
- DHParameters pm = (DHParameters)obj;
-
- if (this.getQ() != null)
- {
- if (!this.getQ().equals(pm.getQ()))
- {
- return false;
- }
- }
- else
- {
- if (pm.getQ() != null)
- {
- return false;
- }
- }
-
- return pm.getP().equals(p) && pm.getG().equals(g);
- }
-
- public int hashCode()
- {
- return getP().hashCode() ^ getG().hashCode() ^ (getQ() != null ? getQ().hashCode() : 0);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/DHPrivateKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/DHPrivateKeyParameters.java
deleted file mode 100644
index ee1b34f9..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/DHPrivateKeyParameters.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-public class DHPrivateKeyParameters
- extends DHKeyParameters
-{
- private BigInteger x;
-
- public DHPrivateKeyParameters(
- BigInteger x,
- DHParameters params)
- {
- super(true, params);
-
- this.x = x;
- }
-
- public BigInteger getX()
- {
- return x;
- }
-
- public int hashCode()
- {
- return x.hashCode() ^ super.hashCode();
- }
-
- public boolean equals(
- Object obj)
- {
- if (!(obj instanceof DHPrivateKeyParameters))
- {
- return false;
- }
-
- DHPrivateKeyParameters other = (DHPrivateKeyParameters)obj;
-
- return other.getX().equals(this.x) && super.equals(obj);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/DHPublicKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/DHPublicKeyParameters.java
deleted file mode 100644
index ed531603..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/DHPublicKeyParameters.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-public class DHPublicKeyParameters
- extends DHKeyParameters
-{
- private BigInteger y;
-
- public DHPublicKeyParameters(
- BigInteger y,
- DHParameters params)
- {
- super(false, params);
-
- this.y = y;
- }
-
- public BigInteger getY()
- {
- return y;
- }
-
- public int hashCode()
- {
- return y.hashCode() ^ super.hashCode();
- }
-
- public boolean equals(
- Object obj)
- {
- if (!(obj instanceof DHPublicKeyParameters))
- {
- return false;
- }
-
- DHPublicKeyParameters other = (DHPublicKeyParameters)obj;
-
- return other.getY().equals(y) && super.equals(obj);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/DHValidationParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/DHValidationParameters.java
deleted file mode 100644
index b22f7a03..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/DHValidationParameters.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.util.Arrays;
-
-public class DHValidationParameters
-{
- private byte[] seed;
- private int counter;
-
- public DHValidationParameters(
- byte[] seed,
- int counter)
- {
- this.seed = seed;
- this.counter = counter;
- }
-
- public int getCounter()
- {
- return counter;
- }
-
- public byte[] getSeed()
- {
- return seed;
- }
-
- public boolean equals(
- Object o)
- {
- if (!(o instanceof DHValidationParameters))
- {
- return false;
- }
-
- DHValidationParameters other = (DHValidationParameters)o;
-
- if (other.counter != this.counter)
- {
- return false;
- }
-
- return Arrays.areEqual(this.seed, other.seed);
- }
-
- public int hashCode()
- {
- return counter ^ Arrays.hashCode(seed);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/DSAKeyGenerationParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/DSAKeyGenerationParameters.java
deleted file mode 100644
index 29fa91e6..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/DSAKeyGenerationParameters.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.KeyGenerationParameters;
-
-public class DSAKeyGenerationParameters
- extends KeyGenerationParameters
-{
- private DSAParameters params;
-
- public DSAKeyGenerationParameters(
- SecureRandom random,
- DSAParameters params)
- {
- super(random, params.getP().bitLength() - 1);
-
- this.params = params;
- }
-
- public DSAParameters getParameters()
- {
- return params;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/DSAKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/DSAKeyParameters.java
deleted file mode 100644
index 11bb9d97..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/DSAKeyParameters.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-public class DSAKeyParameters
- extends AsymmetricKeyParameter
-{
- private DSAParameters params;
-
- public DSAKeyParameters(
- boolean isPrivate,
- DSAParameters params)
- {
- super(isPrivate);
-
- this.params = params;
- }
-
- public DSAParameters getParameters()
- {
- return params;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/DSAParameterGenerationParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/DSAParameterGenerationParameters.java
deleted file mode 100644
index ba841b8e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/DSAParameterGenerationParameters.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.security.SecureRandom;
-
-public class DSAParameterGenerationParameters
-{
- public static final int DIGITAL_SIGNATURE_USAGE = 1;
- public static final int KEY_ESTABLISHMENT_USAGE = 2;
-
- private final int l;
- private final int n;
- private final int usageIndex;
- private final int certainty;
- private final SecureRandom random;
-
- /**
- * Construct without a usage index, this will do a random construction of G.
- *
- * @param L desired length of prime P in bits (the effective key size).
- * @param N desired length of prime Q in bits.
- * @param certainty certainty level for prime number generation.
- * @param random the source of randomness to use.
- */
- public DSAParameterGenerationParameters(
- int L,
- int N,
- int certainty,
- SecureRandom random)
- {
- this(L, N, certainty, random, -1);
- }
-
- /**
- * Construct for a specific usage index - this has the effect of using verifiable canonical generation of G.
- *
- * @param L desired length of prime P in bits (the effective key size).
- * @param N desired length of prime Q in bits.
- * @param certainty certainty level for prime number generation.
- * @param random the source of randomness to use.
- * @param usageIndex a valid usage index.
- */
- public DSAParameterGenerationParameters(
- int L,
- int N,
- int certainty,
- SecureRandom random,
- int usageIndex)
- {
- this.l = L;
- this.n = N;
- this.certainty = certainty;
- this.usageIndex = usageIndex;
- this.random = random;
- }
-
- public int getL()
- {
- return l;
- }
-
- public int getN()
- {
- return n;
- }
-
- public int getCertainty()
- {
- return certainty;
- }
-
- public SecureRandom getRandom()
- {
- return random;
- }
-
- public int getUsageIndex()
- {
- return usageIndex;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/DSAParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/DSAParameters.java
deleted file mode 100644
index 7f76d117..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/DSAParameters.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public class DSAParameters
- implements CipherParameters
-{
- private BigInteger g;
- private BigInteger q;
- private BigInteger p;
- private DSAValidationParameters validation;
-
- public DSAParameters(
- BigInteger p,
- BigInteger q,
- BigInteger g)
- {
- this.g = g;
- this.p = p;
- this.q = q;
- }
-
- public DSAParameters(
- BigInteger p,
- BigInteger q,
- BigInteger g,
- DSAValidationParameters params)
- {
- this.g = g;
- this.p = p;
- this.q = q;
- this.validation = params;
- }
-
- public BigInteger getP()
- {
- return p;
- }
-
- public BigInteger getQ()
- {
- return q;
- }
-
- public BigInteger getG()
- {
- return g;
- }
-
- public DSAValidationParameters getValidationParameters()
- {
- return validation;
- }
-
- public boolean equals(
- Object obj)
- {
- if (!(obj instanceof DSAParameters))
- {
- return false;
- }
-
- DSAParameters pm = (DSAParameters)obj;
-
- return (pm.getP().equals(p) && pm.getQ().equals(q) && pm.getG().equals(g));
- }
-
- public int hashCode()
- {
- return getP().hashCode() ^ getQ().hashCode() ^ getG().hashCode();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/DSAPrivateKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/DSAPrivateKeyParameters.java
deleted file mode 100644
index 3bef3f40..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/DSAPrivateKeyParameters.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-public class DSAPrivateKeyParameters
- extends DSAKeyParameters
-{
- private BigInteger x;
-
- public DSAPrivateKeyParameters(
- BigInteger x,
- DSAParameters params)
- {
- super(true, params);
-
- this.x = x;
- }
-
- public BigInteger getX()
- {
- return x;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/DSAPublicKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/DSAPublicKeyParameters.java
deleted file mode 100644
index c0066568..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/DSAPublicKeyParameters.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-public class DSAPublicKeyParameters
- extends DSAKeyParameters
-{
- private BigInteger y;
-
- public DSAPublicKeyParameters(
- BigInteger y,
- DSAParameters params)
- {
- super(false, params);
-
- this.y = y;
- }
-
- public BigInteger getY()
- {
- return y;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/DSAValidationParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/DSAValidationParameters.java
deleted file mode 100644
index 07d93d07..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/DSAValidationParameters.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.util.Arrays;
-
-public class DSAValidationParameters
-{
- private int usageIndex;
- private byte[] seed;
- private int counter;
-
- public DSAValidationParameters(
- byte[] seed,
- int counter)
- {
- this(seed, counter, -1);
- }
-
- public DSAValidationParameters(
- byte[] seed,
- int counter,
- int usageIndex)
- {
- this.seed = seed;
- this.counter = counter;
- this.usageIndex = usageIndex;
- }
-
- public int getCounter()
- {
- return counter;
- }
-
- public byte[] getSeed()
- {
- return seed;
- }
-
- public int getUsageIndex()
- {
- return usageIndex;
- }
-
- public int hashCode()
- {
- return counter ^ Arrays.hashCode(seed);
- }
-
- public boolean equals(
- Object o)
- {
- if (!(o instanceof DSAValidationParameters))
- {
- return false;
- }
-
- DSAValidationParameters other = (DSAValidationParameters)o;
-
- if (other.counter != this.counter)
- {
- return false;
- }
-
- return Arrays.areEqual(this.seed, other.seed);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java
deleted file mode 100644
index 9cc6e727..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.util.Arrays;
-
-public class ECDomainParameters
- implements ECConstants
-{
- private ECCurve curve;
- private byte[] seed;
- private ECPoint G;
- private BigInteger n;
- private BigInteger h;
-
- public ECDomainParameters(
- ECCurve curve,
- ECPoint G,
- BigInteger n)
- {
- this(curve, G, n, ONE, null);
- }
-
- public ECDomainParameters(
- ECCurve curve,
- ECPoint G,
- BigInteger n,
- BigInteger h)
- {
- this(curve, G, n, h, null);
- }
-
- public ECDomainParameters(
- ECCurve curve,
- ECPoint G,
- BigInteger n,
- BigInteger h,
- byte[] seed)
- {
- this.curve = curve;
- this.G = G.normalize();
- this.n = n;
- this.h = h;
- this.seed = seed;
- }
-
- public ECCurve getCurve()
- {
- return curve;
- }
-
- public ECPoint getG()
- {
- return G;
- }
-
- public BigInteger getN()
- {
- return n;
- }
-
- public BigInteger getH()
- {
- return h;
- }
-
- public byte[] getSeed()
- {
- return Arrays.clone(seed);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/ECKeyGenerationParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/ECKeyGenerationParameters.java
deleted file mode 100644
index be3f20f5..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/ECKeyGenerationParameters.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.KeyGenerationParameters;
-
-public class ECKeyGenerationParameters
- extends KeyGenerationParameters
-{
- private ECDomainParameters domainParams;
-
- public ECKeyGenerationParameters(
- ECDomainParameters domainParams,
- SecureRandom random)
- {
- super(random, domainParams.getN().bitLength());
-
- this.domainParams = domainParams;
- }
-
- public ECDomainParameters getDomainParameters()
- {
- return domainParams;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/ECKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/ECKeyParameters.java
deleted file mode 100644
index 19825c5b..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/ECKeyParameters.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-public class ECKeyParameters
- extends AsymmetricKeyParameter
-{
- ECDomainParameters params;
-
- protected ECKeyParameters(
- boolean isPrivate,
- ECDomainParameters params)
- {
- super(isPrivate);
-
- this.params = params;
- }
-
- public ECDomainParameters getParameters()
- {
- return params;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/ECNamedDomainParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/ECNamedDomainParameters.java
deleted file mode 100644
index 5b694bec..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/ECNamedDomainParameters.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECPoint;
-
-public class ECNamedDomainParameters
- extends ECDomainParameters
-{
- private ASN1ObjectIdentifier name;
-
- public ECNamedDomainParameters(ASN1ObjectIdentifier name, ECCurve curve, ECPoint G, BigInteger n)
- {
- this(name, curve, G, n, null, null);
- }
-
- public ECNamedDomainParameters(ASN1ObjectIdentifier name, ECCurve curve, ECPoint G, BigInteger n, BigInteger h)
- {
- this(name, curve, G, n, h, null);
- }
-
- public ECNamedDomainParameters(ASN1ObjectIdentifier name, ECCurve curve, ECPoint G, BigInteger n, BigInteger h, byte[] seed)
- {
- super(curve, G, n, h, seed);
-
- this.name = name;
- }
-
- public ASN1ObjectIdentifier getName()
- {
- return name;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/ECPrivateKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/ECPrivateKeyParameters.java
deleted file mode 100644
index 3e49983e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/ECPrivateKeyParameters.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-public class ECPrivateKeyParameters
- extends ECKeyParameters
-{
- BigInteger d;
-
- public ECPrivateKeyParameters(
- BigInteger d,
- ECDomainParameters params)
- {
- super(true, params);
- this.d = d;
- }
-
- public BigInteger getD()
- {
- return d;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java
deleted file mode 100644
index b6b3fb6d..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.math.ec.ECPoint;
-
-public class ECPublicKeyParameters
- extends ECKeyParameters
-{
- ECPoint Q;
-
- public ECPublicKeyParameters(
- ECPoint Q,
- ECDomainParameters params)
- {
- super(false, params);
- this.Q = Q.normalize();
- }
-
- public ECPoint getQ()
- {
- return Q;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/ElGamalKeyGenerationParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/ElGamalKeyGenerationParameters.java
deleted file mode 100644
index f5fbabd5..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/ElGamalKeyGenerationParameters.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.KeyGenerationParameters;
-
-public class ElGamalKeyGenerationParameters
- extends KeyGenerationParameters
-{
- private ElGamalParameters params;
-
- public ElGamalKeyGenerationParameters(
- SecureRandom random,
- ElGamalParameters params)
- {
- super(random, getStrength(params));
-
- this.params = params;
- }
-
- public ElGamalParameters getParameters()
- {
- return params;
- }
-
- static int getStrength(ElGamalParameters params)
- {
- return params.getL() != 0 ? params.getL() : params.getP().bitLength();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/ElGamalKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/ElGamalKeyParameters.java
deleted file mode 100644
index 72506931..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/ElGamalKeyParameters.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-
-public class ElGamalKeyParameters
- extends AsymmetricKeyParameter
-{
- private ElGamalParameters params;
-
- protected ElGamalKeyParameters(
- boolean isPrivate,
- ElGamalParameters params)
- {
- super(isPrivate);
-
- this.params = params;
- }
-
- public ElGamalParameters getParameters()
- {
- return params;
- }
-
- public int hashCode()
- {
- return (params != null) ? params.hashCode() : 0;
- }
-
- public boolean equals(
- Object obj)
- {
- if (!(obj instanceof ElGamalKeyParameters))
- {
- return false;
- }
-
- ElGamalKeyParameters dhKey = (ElGamalKeyParameters)obj;
-
- if (params == null)
- {
- return dhKey.getParameters() == null;
- }
- else
- {
- return params.equals(dhKey.getParameters());
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/ElGamalParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/ElGamalParameters.java
deleted file mode 100644
index 166eff35..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/ElGamalParameters.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public class ElGamalParameters
- implements CipherParameters
-{
- private BigInteger g;
- private BigInteger p;
- private int l;
-
- public ElGamalParameters(
- BigInteger p,
- BigInteger g)
- {
- this(p, g, 0);
- }
-
- public ElGamalParameters(
- BigInteger p,
- BigInteger g,
- int l)
- {
- this.g = g;
- this.p = p;
- this.l = l;
- }
-
- public BigInteger getP()
- {
- return p;
- }
-
- /**
- * return the generator - g
- */
- public BigInteger getG()
- {
- return g;
- }
-
- /**
- * return private value limit - l
- */
- public int getL()
- {
- return l;
- }
-
- public boolean equals(
- Object obj)
- {
- if (!(obj instanceof ElGamalParameters))
- {
- return false;
- }
-
- ElGamalParameters pm = (ElGamalParameters)obj;
-
- return pm.getP().equals(p) && pm.getG().equals(g) && pm.getL() == l;
- }
-
- public int hashCode()
- {
- return (getP().hashCode() ^ getG().hashCode()) + l;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/ElGamalPrivateKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/ElGamalPrivateKeyParameters.java
deleted file mode 100644
index b8fb529f..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/ElGamalPrivateKeyParameters.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-public class ElGamalPrivateKeyParameters
- extends ElGamalKeyParameters
-{
- private BigInteger x;
-
- public ElGamalPrivateKeyParameters(
- BigInteger x,
- ElGamalParameters params)
- {
- super(true, params);
-
- this.x = x;
- }
-
- public BigInteger getX()
- {
- return x;
- }
-
- public boolean equals(
- Object obj)
- {
- if (!(obj instanceof ElGamalPrivateKeyParameters))
- {
- return false;
- }
-
- ElGamalPrivateKeyParameters pKey = (ElGamalPrivateKeyParameters)obj;
-
- if (!pKey.getX().equals(x))
- {
- return false;
- }
-
- return super.equals(obj);
- }
-
- public int hashCode()
- {
- return getX().hashCode();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/ElGamalPublicKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/ElGamalPublicKeyParameters.java
deleted file mode 100644
index d7da7a93..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/ElGamalPublicKeyParameters.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-public class ElGamalPublicKeyParameters
- extends ElGamalKeyParameters
-{
- private BigInteger y;
-
- public ElGamalPublicKeyParameters(
- BigInteger y,
- ElGamalParameters params)
- {
- super(false, params);
-
- this.y = y;
- }
-
- public BigInteger getY()
- {
- return y;
- }
-
- public int hashCode()
- {
- return y.hashCode() ^ super.hashCode();
- }
-
- public boolean equals(
- Object obj)
- {
- if (!(obj instanceof ElGamalPublicKeyParameters))
- {
- return false;
- }
-
- ElGamalPublicKeyParameters other = (ElGamalPublicKeyParameters)obj;
-
- return other.getY().equals(y) && super.equals(obj);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/GOST3410KeyGenerationParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/GOST3410KeyGenerationParameters.java
deleted file mode 100644
index 74e05a96..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/GOST3410KeyGenerationParameters.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.KeyGenerationParameters;
-
-import java.security.SecureRandom;
-
-public class GOST3410KeyGenerationParameters
- extends KeyGenerationParameters
-{
- private GOST3410Parameters params;
-
- public GOST3410KeyGenerationParameters(
- SecureRandom random,
- GOST3410Parameters params)
- {
- super(random, params.getP().bitLength() - 1);
-
- this.params = params;
- }
-
- public GOST3410Parameters getParameters()
- {
- return params;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/GOST3410KeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/GOST3410KeyParameters.java
deleted file mode 100644
index 6716924a..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/GOST3410KeyParameters.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-public class GOST3410KeyParameters
- extends AsymmetricKeyParameter
-{
- private GOST3410Parameters params;
-
- public GOST3410KeyParameters(
- boolean isPrivate,
- GOST3410Parameters params)
- {
- super(isPrivate);
-
- this.params = params;
- }
-
- public GOST3410Parameters getParameters()
- {
- return params;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/GOST3410Parameters.java b/core/src/main/java/org/bouncycastle/crypto/params/GOST3410Parameters.java
deleted file mode 100644
index 07450f61..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/GOST3410Parameters.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-import java.math.BigInteger;
-
-public class GOST3410Parameters
- implements CipherParameters
-{
- private BigInteger p;
- private BigInteger q;
- private BigInteger a;
- private GOST3410ValidationParameters validation;
-
- public GOST3410Parameters(
- BigInteger p,
- BigInteger q,
- BigInteger a)
- {
- this.p = p;
- this.q = q;
- this.a = a;
- }
-
- public GOST3410Parameters(
- BigInteger p,
- BigInteger q,
- BigInteger a,
- GOST3410ValidationParameters params)
- {
- this.a = a;
- this.p = p;
- this.q = q;
- this.validation = params;
- }
-
- public BigInteger getP()
- {
- return p;
- }
-
- public BigInteger getQ()
- {
- return q;
- }
-
- public BigInteger getA()
- {
- return a;
- }
-
- public GOST3410ValidationParameters getValidationParameters()
- {
- return validation;
- }
-
- public int hashCode()
- {
- return p.hashCode() ^ q.hashCode() ^ a.hashCode();
- }
-
- public boolean equals(
- Object obj)
- {
- if (!(obj instanceof GOST3410Parameters))
- {
- return false;
- }
-
- GOST3410Parameters pm = (GOST3410Parameters)obj;
-
- return (pm.getP().equals(p) && pm.getQ().equals(q) && pm.getA().equals(a));
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/GOST3410PrivateKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/GOST3410PrivateKeyParameters.java
deleted file mode 100644
index 408e0657..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/GOST3410PrivateKeyParameters.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-public class GOST3410PrivateKeyParameters
- extends GOST3410KeyParameters
-{
- private BigInteger x;
-
- public GOST3410PrivateKeyParameters(
- BigInteger x,
- GOST3410Parameters params)
- {
- super(true, params);
-
- this.x = x;
- }
-
- public BigInteger getX()
- {
- return x;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/GOST3410PublicKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/GOST3410PublicKeyParameters.java
deleted file mode 100644
index 9dfd2d98..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/GOST3410PublicKeyParameters.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-public class GOST3410PublicKeyParameters
- extends GOST3410KeyParameters
-{
- private BigInteger y;
-
- public GOST3410PublicKeyParameters(
- BigInteger y,
- GOST3410Parameters params)
- {
- super(false, params);
-
- this.y = y;
- }
-
- public BigInteger getY()
- {
- return y;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/GOST3410ValidationParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/GOST3410ValidationParameters.java
deleted file mode 100644
index c2a4fb57..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/GOST3410ValidationParameters.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-public class GOST3410ValidationParameters
-{
- private int x0;
- private int c;
- private long x0L;
- private long cL;
-
-
- public GOST3410ValidationParameters(
- int x0,
- int c)
- {
- this.x0 = x0;
- this.c = c;
- }
-
- public GOST3410ValidationParameters(
- long x0L,
- long cL)
- {
- this.x0L = x0L;
- this.cL = cL;
- }
-
- public int getC()
- {
- return c;
- }
-
- public int getX0()
- {
- return x0;
- }
-
- public long getCL()
- {
- return cL;
- }
-
- public long getX0L()
- {
- return x0L;
- }
-
- public boolean equals(
- Object o)
- {
- if (!(o instanceof GOST3410ValidationParameters))
- {
- return false;
- }
-
- GOST3410ValidationParameters other = (GOST3410ValidationParameters)o;
-
- if (other.c != this.c)
- {
- return false;
- }
-
- if (other.x0 != this.x0)
- {
- return false;
- }
-
- if (other.cL != this.cL)
- {
- return false;
- }
-
- if (other.x0L != this.x0L)
- {
- return false;
- }
-
- return true;
- }
-
- public int hashCode()
- {
- return x0 ^ c ^ (int) x0L ^ (int)(x0L >> 32) ^ (int) cL ^ (int)(cL >> 32);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/HKDFParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/HKDFParameters.java
deleted file mode 100644
index 2db3ce61..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/HKDFParameters.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.DerivationParameters;
-import org.bouncycastle.util.Arrays;
-
-/**
- * Parameter class for the HKDFBytesGenerator class.
- */
-public class HKDFParameters
- implements DerivationParameters
-{
- private final byte[] ikm;
- private final boolean skipExpand;
- private final byte[] salt;
- private final byte[] info;
-
- private HKDFParameters(final byte[] ikm, final boolean skip,
- final byte[] salt, final byte[] info)
- {
- if (ikm == null)
- {
- throw new IllegalArgumentException(
- "IKM (input keying material) should not be null");
- }
-
- this.ikm = Arrays.clone(ikm);
-
- this.skipExpand = skip;
-
- if (salt == null || salt.length == 0)
- {
- this.salt = null;
- }
- else
- {
- this.salt = Arrays.clone(salt);
- }
-
- if (info == null)
- {
- this.info = new byte[0];
- }
- else
- {
- this.info = Arrays.clone(info);
- }
- }
-
- /**
- * Generates parameters for HKDF, specifying both the optional salt and
- * optional info. Step 1: Extract won't be skipped.
- *
- * @param ikm the input keying material or seed
- * @param salt the salt to use, may be null for a salt for hashLen zeros
- * @param info the info to use, may be null for an info field of zero bytes
- */
- public HKDFParameters(final byte[] ikm, final byte[] salt, final byte[] info)
- {
- this(ikm, false, salt, info);
- }
-
- /**
- * Factory method that makes the HKDF skip the extract part of the key
- * derivation function.
- *
- * @param ikm the input keying material or seed, directly used for step 2:
- * Expand
- * @param info the info to use, may be null for an info field of zero bytes
- * @return HKDFParameters that makes the implementation skip step 1
- */
- public static HKDFParameters skipExtractParameters(final byte[] ikm,
- final byte[] info)
- {
-
- return new HKDFParameters(ikm, true, null, info);
- }
-
- public static HKDFParameters defaultParameters(final byte[] ikm)
- {
- return new HKDFParameters(ikm, false, null, null);
- }
-
- /**
- * Returns the input keying material or seed.
- *
- * @return the keying material
- */
- public byte[] getIKM()
- {
- return Arrays.clone(ikm);
- }
-
- /**
- * Returns if step 1: extract has to be skipped or not
- *
- * @return true for skipping, false for no skipping of step 1
- */
- public boolean skipExtract()
- {
- return skipExpand;
- }
-
- /**
- * Returns the salt, or null if the salt should be generated as a byte array
- * of HashLen zeros.
- *
- * @return the salt, or null
- */
- public byte[] getSalt()
- {
- return Arrays.clone(salt);
- }
-
- /**
- * Returns the info field, which may be empty (null is converted to empty).
- *
- * @return the info field, never null
- */
- public byte[] getInfo()
- {
- return Arrays.clone(info);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/IESParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/IESParameters.java
deleted file mode 100644
index 0600b346..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/IESParameters.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-/**
- * parameters for using an integrated cipher in stream mode.
- */
-public class IESParameters
- implements CipherParameters
-{
- private byte[] derivation;
- private byte[] encoding;
- private int macKeySize;
-
- /**
- * @param derivation the derivation parameter for the KDF function.
- * @param encoding the encoding parameter for the KDF function.
- * @param macKeySize the size of the MAC key (in bits).
- */
- public IESParameters(
- byte[] derivation,
- byte[] encoding,
- int macKeySize)
- {
- this.derivation = derivation;
- this.encoding = encoding;
- this.macKeySize = macKeySize;
- }
-
- public byte[] getDerivationV()
- {
- return derivation;
- }
-
- public byte[] getEncodingV()
- {
- return encoding;
- }
-
- public int getMacKeySize()
- {
- return macKeySize;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/IESWithCipherParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/IESWithCipherParameters.java
deleted file mode 100644
index ef61b2cc..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/IESWithCipherParameters.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-
-public class IESWithCipherParameters
- extends IESParameters
-{
- private int cipherKeySize;
-
- /**
- * @param derivation the derivation parameter for the KDF function.
- * @param encoding the encoding parameter for the KDF function.
- * @param macKeySize the size of the MAC key (in bits).
- * @param cipherKeySize the size of the associated Cipher key (in bits).
- */
- public IESWithCipherParameters(
- byte[] derivation,
- byte[] encoding,
- int macKeySize,
- int cipherKeySize)
- {
- super(derivation, encoding, macKeySize);
-
- this.cipherKeySize = cipherKeySize;
- }
-
- public int getCipherKeySize()
- {
- return cipherKeySize;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/ISO18033KDFParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/ISO18033KDFParameters.java
deleted file mode 100644
index 8dffe2ee..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/ISO18033KDFParameters.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.DerivationParameters;
-
-/**
- * parameters for Key derivation functions for ISO-18033
- */
-public class ISO18033KDFParameters
- implements DerivationParameters
-{
- byte[] seed;
-
- public ISO18033KDFParameters(
- byte[] seed)
- {
- this.seed = seed;
- }
-
- public byte[] getSeed()
- {
- return seed;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/KDFCounterParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/KDFCounterParameters.java
deleted file mode 100644
index 29d8b369..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/KDFCounterParameters.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.DerivationParameters;
-import org.bouncycastle.util.Arrays;
-
-/**
- * This KDF has been defined by the publicly available NIST SP 800-108 specification.
- * NIST SP800-108 allows for alternative orderings of the input fields, meaning that the input can be formated in multiple ways.
- * There are 3 supported formats: - Below [i]_2 is a counter of r-bits length concatenated to the fixedInputData.
- * <ul>
- * <li>1: K(i) := PRF( KI, [i]_2 || Label || 0x00 || Context || [L]_2 ) with the counter at the very beginning of the fixedInputData (The default implementation has this format)</li>
- * <li>2: K(i) := PRF( KI, Label || 0x00 || Context || [L]_2 || [i]_2 ) with the counter at the very end of the fixedInputData</li>
- * <li>3a: K(i) := PRF( KI, Label || 0x00 || [i]_2 || Context || [L]_2 ) OR:</li>
- * <li>3b: K(i) := PRF( KI, Label || 0x00 || [i]_2 || [L]_2 || Context ) OR:</li>
- * <li>3c: K(i) := PRF( KI, Label || [i]_2 || 0x00 || Context || [L]_2 ) etc... with the counter somewhere in the 'middle' of the fixedInputData.</li>
- * </ul>
- * <p>
- * This function must be called with the following KDFCounterParameters():
- * - KI <br/>
- * - The part of the fixedInputData that comes BEFORE the counter OR null <br/>
- * - the part of the fixedInputData that comes AFTER the counter OR null <br/>
- * - the length of the counter in bits (not bytes) <br/>
- * </p>
- * Resulting function calls assuming an 8 bit counter.
- * <ul>
- * <li>1. KDFCounterParameters(ki, null, "Label || 0x00 || Context || [L]_2]", 8); </li>
- * <li>2. KDFCounterParameters(ki, "Label || 0x00 || Context || [L]_2]", null, 8); </li>
- * <li>3a. KDFCounterParameters(ki, "Label || 0x00", "Context || [L]_2]", 8); </li>
- * <li>3b. KDFCounterParameters(ki, "Label || 0x00", "[L]_2] || Context", 8);</li>
- * <li>3c. KDFCounterParameters(ki, "Label", "0x00 || Context || [L]_2]", 8); </li>
- * </ul>
- */
-public final class KDFCounterParameters
- implements DerivationParameters
-{
-
- private byte[] ki;
- private byte[] fixedInputDataCounterPrefix;
- private byte[] fixedInputDataCounterSuffix;
- private int r;
-
- /**
- * Base constructor - suffix fixed input data only.
- *
- * @param ki the KDF seed
- * @param fixedInputDataCounterSuffix fixed input data to follow counter.
- * @param r length of the counter in bits.
- */
- public KDFCounterParameters(byte[] ki, byte[] fixedInputDataCounterSuffix, int r)
- {
- this(ki, null, fixedInputDataCounterSuffix, r);
- }
-
- /**
- * Base constructor - prefix and suffix fixed input data.
- *
- * @param ki the KDF seed
- * @param fixedInputDataCounterPrefix fixed input data to precede counter
- * @param fixedInputDataCounterSuffix fixed input data to follow counter.
- * @param r length of the counter in bits.
- */
- public KDFCounterParameters(byte[] ki, byte[] fixedInputDataCounterPrefix, byte[] fixedInputDataCounterSuffix, int r)
- {
- if (ki == null)
- {
- throw new IllegalArgumentException("A KDF requires Ki (a seed) as input");
- }
- this.ki = Arrays.clone(ki);
-
- if (fixedInputDataCounterPrefix == null)
- {
- this.fixedInputDataCounterPrefix = new byte[0];
- }
- else
- {
- this.fixedInputDataCounterPrefix = Arrays.clone(fixedInputDataCounterPrefix);
- }
-
- if (fixedInputDataCounterSuffix == null)
- {
- this.fixedInputDataCounterSuffix = new byte[0];
- }
- else
- {
- this.fixedInputDataCounterSuffix = Arrays.clone(fixedInputDataCounterSuffix);
- }
-
- 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()
- {
- //Retained for backwards compatibility
- return Arrays.clone(fixedInputDataCounterSuffix);
- }
-
- public byte[] getFixedInputDataCounterPrefix()
- {
- return Arrays.clone(fixedInputDataCounterPrefix);
- }
-
- public byte[] getFixedInputDataCounterSuffix()
- {
- return Arrays.clone(fixedInputDataCounterSuffix);
- }
-
- public int getR()
- {
- return r;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/KDFDoublePipelineIterationParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/KDFDoublePipelineIterationParameters.java
deleted file mode 100644
index 383678aa..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/KDFDoublePipelineIterationParameters.java
+++ /dev/null
@@ -1,80 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/params/KDFFeedbackParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/KDFFeedbackParameters.java
deleted file mode 100644
index 8a6e7f57..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/KDFFeedbackParameters.java
+++ /dev/null
@@ -1,96 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/params/KDFParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/KDFParameters.java
deleted file mode 100644
index f3bac647..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/KDFParameters.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.DerivationParameters;
-
-/**
- * parameters for Key derivation functions for IEEE P1363a
- */
-public class KDFParameters
- implements DerivationParameters
-{
- byte[] iv;
- byte[] shared;
-
- public KDFParameters(
- byte[] shared,
- byte[] iv)
- {
- this.shared = shared;
- this.iv = iv;
- }
-
- public byte[] getSharedSecret()
- {
- return shared;
- }
-
- public byte[] getIV()
- {
- return iv;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/KeyParameter.java b/core/src/main/java/org/bouncycastle/crypto/params/KeyParameter.java
deleted file mode 100644
index 5c4fe0e0..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/KeyParameter.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public class KeyParameter
- implements CipherParameters
-{
- private byte[] key;
-
- public KeyParameter(
- byte[] key)
- {
- this(key, 0, key.length);
- }
-
- public KeyParameter(
- byte[] key,
- int keyOff,
- int keyLen)
- {
- this.key = new byte[keyLen];
-
- System.arraycopy(key, keyOff, this.key, 0, keyLen);
- }
-
- public byte[] getKey()
- {
- return key;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/MGFParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/MGFParameters.java
deleted file mode 100644
index 847bd989..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/MGFParameters.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.DerivationParameters;
-
-/**
- * parameters for mask derivation functions.
- */
-public class MGFParameters
- implements DerivationParameters
-{
- byte[] seed;
-
- public MGFParameters(
- byte[] seed)
- {
- this(seed, 0, seed.length);
- }
-
- public MGFParameters(
- byte[] seed,
- int off,
- int len)
- {
- this.seed = new byte[len];
- System.arraycopy(seed, off, this.seed, 0, len);
- }
-
- public byte[] getSeed()
- {
- return seed;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/MQVPrivateParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/MQVPrivateParameters.java
deleted file mode 100644
index 832c07fd..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/MQVPrivateParameters.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public class MQVPrivateParameters
- implements CipherParameters
-{
- private ECPrivateKeyParameters staticPrivateKey;
- private ECPrivateKeyParameters ephemeralPrivateKey;
- private ECPublicKeyParameters ephemeralPublicKey;
-
- public MQVPrivateParameters(
- ECPrivateKeyParameters staticPrivateKey,
- ECPrivateKeyParameters ephemeralPrivateKey)
- {
- this(staticPrivateKey, ephemeralPrivateKey, null);
- }
-
- public MQVPrivateParameters(
- ECPrivateKeyParameters staticPrivateKey,
- ECPrivateKeyParameters ephemeralPrivateKey,
- ECPublicKeyParameters ephemeralPublicKey)
- {
- this.staticPrivateKey = staticPrivateKey;
- this.ephemeralPrivateKey = ephemeralPrivateKey;
- this.ephemeralPublicKey = ephemeralPublicKey;
- }
-
- public ECPrivateKeyParameters getStaticPrivateKey()
- {
- return staticPrivateKey;
- }
-
- public ECPrivateKeyParameters getEphemeralPrivateKey()
- {
- return ephemeralPrivateKey;
- }
-
- public ECPublicKeyParameters getEphemeralPublicKey()
- {
- return ephemeralPublicKey;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/MQVPublicParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/MQVPublicParameters.java
deleted file mode 100644
index b3b24671..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/MQVPublicParameters.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public class MQVPublicParameters
- implements CipherParameters
-{
- private ECPublicKeyParameters staticPublicKey;
- private ECPublicKeyParameters ephemeralPublicKey;
-
- public MQVPublicParameters(
- ECPublicKeyParameters staticPublicKey,
- ECPublicKeyParameters ephemeralPublicKey)
- {
- this.staticPublicKey = staticPublicKey;
- this.ephemeralPublicKey = ephemeralPublicKey;
- }
-
- public ECPublicKeyParameters getStaticPublicKey()
- {
- return staticPublicKey;
- }
-
- public ECPublicKeyParameters getEphemeralPublicKey()
- {
- return ephemeralPublicKey;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/NaccacheSternKeyGenerationParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/NaccacheSternKeyGenerationParameters.java
deleted file mode 100644
index 758fcd79..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/NaccacheSternKeyGenerationParameters.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.KeyGenerationParameters;
-
-/**
- * Parameters for NaccacheStern public private key generation. For details on
- * this cipher, please see
- *
- * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
- */
-public class NaccacheSternKeyGenerationParameters extends KeyGenerationParameters
-{
-
- // private BigInteger publicExponent;
- private int certainty;
-
- private int cntSmallPrimes;
-
- private boolean debug = false;
-
- /**
- * Parameters for generating a NaccacheStern KeyPair.
- *
- * @param random
- * The source of randomness
- * @param strength
- * The desired strength of the Key in Bits
- * @param certainty
- * the probability that the generated primes are not really prime
- * as integer: 2^(-certainty) is then the probability
- * @param cntSmallPrimes
- * How many small key factors are desired
- */
- public NaccacheSternKeyGenerationParameters(SecureRandom random, int strength, int certainty, int cntSmallPrimes)
- {
- this(random, strength, certainty, cntSmallPrimes, false);
- }
-
- /**
- * Parameters for a NaccacheStern KeyPair.
- *
- * @param random
- * The source of randomness
- * @param strength
- * The desired strength of the Key in Bits
- * @param certainty
- * the probability that the generated primes are not really prime
- * as integer: 2^(-certainty) is then the probability
- * @param cntSmallPrimes
- * How many small key factors are desired
- * @param debug
- * Turn debugging on or off (reveals secret information, use with
- * caution)
- */
- public NaccacheSternKeyGenerationParameters(SecureRandom random,
- int strength, int certainty, int cntSmallPrimes, boolean debug)
- {
- super(random, strength);
-
- this.certainty = certainty;
- if (cntSmallPrimes % 2 == 1)
- {
- throw new IllegalArgumentException("cntSmallPrimes must be a multiple of 2");
- }
- if (cntSmallPrimes < 30)
- {
- throw new IllegalArgumentException("cntSmallPrimes must be >= 30 for security reasons");
- }
- this.cntSmallPrimes = cntSmallPrimes;
-
- this.debug = debug;
- }
-
- /**
- * @return Returns the certainty.
- */
- public int getCertainty()
- {
- return certainty;
- }
-
- /**
- * @return Returns the cntSmallPrimes.
- */
- public int getCntSmallPrimes()
- {
- return cntSmallPrimes;
- }
-
- public boolean isDebug()
- {
- return debug;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/NaccacheSternKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/NaccacheSternKeyParameters.java
deleted file mode 100644
index 21b6a286..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/NaccacheSternKeyParameters.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-/**
- * Public key parameters for NaccacheStern cipher. For details on this cipher,
- * please see
- *
- * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
- */
-public class NaccacheSternKeyParameters extends AsymmetricKeyParameter
-{
-
- private BigInteger g, n;
-
- int lowerSigmaBound;
-
- /**
- * @param privateKey
- */
- public NaccacheSternKeyParameters(boolean privateKey, BigInteger g, BigInteger n, int lowerSigmaBound)
- {
- super(privateKey);
- this.g = g;
- this.n = n;
- this.lowerSigmaBound = lowerSigmaBound;
- }
-
- /**
- * @return Returns the g.
- */
- public BigInteger getG()
- {
- return g;
- }
-
- /**
- * @return Returns the lowerSigmaBound.
- */
- public int getLowerSigmaBound()
- {
- return lowerSigmaBound;
- }
-
- /**
- * @return Returns the n.
- */
- public BigInteger getModulus()
- {
- return n;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/NaccacheSternPrivateKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/NaccacheSternPrivateKeyParameters.java
deleted file mode 100644
index 6d0ec486..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/NaccacheSternPrivateKeyParameters.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-import java.util.Vector;
-
-/**
- * Private key parameters for NaccacheStern cipher. For details on this cipher,
- * please see
- *
- * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
- */
-public class NaccacheSternPrivateKeyParameters extends NaccacheSternKeyParameters
-{
- private BigInteger phi_n;
- private Vector smallPrimes;
-
- /**
- * Constructs a NaccacheSternPrivateKey
- *
- * @param g
- * the public enryption parameter g
- * @param n
- * the public modulus n = p*q
- * @param lowerSigmaBound
- * the public lower sigma bound up to which data can be encrypted
- * @param smallPrimes
- * the small primes, of which sigma is constructed in the right
- * order
- * @param phi_n
- * the private modulus phi(n) = (p-1)(q-1)
- */
- public NaccacheSternPrivateKeyParameters(BigInteger g, BigInteger n,
- int lowerSigmaBound, Vector smallPrimes,
- BigInteger phi_n)
- {
- super(true, g, n, lowerSigmaBound);
- this.smallPrimes = smallPrimes;
- this.phi_n = phi_n;
- }
-
- public BigInteger getPhi_n()
- {
- return phi_n;
- }
-
- public Vector getSmallPrimes()
- {
- return smallPrimes;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/ParametersWithIV.java b/core/src/main/java/org/bouncycastle/crypto/params/ParametersWithIV.java
deleted file mode 100644
index 4a1e6e9a..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/ParametersWithIV.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public class ParametersWithIV
- implements CipherParameters
-{
- private byte[] iv;
- private CipherParameters parameters;
-
- public ParametersWithIV(
- CipherParameters parameters,
- byte[] iv)
- {
- this(parameters, iv, 0, iv.length);
- }
-
- public ParametersWithIV(
- CipherParameters parameters,
- byte[] iv,
- int ivOff,
- int ivLen)
- {
- this.iv = new byte[ivLen];
- this.parameters = parameters;
-
- System.arraycopy(iv, ivOff, this.iv, 0, ivLen);
- }
-
- public byte[] getIV()
- {
- return iv;
- }
-
- public CipherParameters getParameters()
- {
- return parameters;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/ParametersWithRandom.java b/core/src/main/java/org/bouncycastle/crypto/params/ParametersWithRandom.java
deleted file mode 100644
index a7b18e51..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/ParametersWithRandom.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-import java.security.SecureRandom;
-
-public class ParametersWithRandom
- implements CipherParameters
-{
- private SecureRandom random;
- private CipherParameters parameters;
-
- public ParametersWithRandom(
- CipherParameters parameters,
- SecureRandom random)
- {
- this.random = random;
- this.parameters = parameters;
- }
-
- public ParametersWithRandom(
- CipherParameters parameters)
- {
- this(parameters, new SecureRandom());
- }
-
- public SecureRandom getRandom()
- {
- return random;
- }
-
- public CipherParameters getParameters()
- {
- return parameters;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/ParametersWithSBox.java b/core/src/main/java/org/bouncycastle/crypto/params/ParametersWithSBox.java
deleted file mode 100644
index b226a9d9..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/ParametersWithSBox.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public class ParametersWithSBox
- implements CipherParameters
-{
- private CipherParameters parameters;
- private byte[] sBox;
-
- public ParametersWithSBox(
- CipherParameters parameters,
- byte[] sBox)
- {
- this.parameters = parameters;
- this.sBox = sBox;
- }
-
- public byte[] getSBox()
- {
- return sBox;
- }
-
- public CipherParameters getParameters()
- {
- return parameters;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/ParametersWithSalt.java b/core/src/main/java/org/bouncycastle/crypto/params/ParametersWithSalt.java
deleted file mode 100644
index 73765dd5..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/ParametersWithSalt.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-/**
- * Cipher parameters with a fixed salt value associated with them.
- */
-public class ParametersWithSalt
- implements CipherParameters
-{
- private byte[] salt;
- private CipherParameters parameters;
-
- public ParametersWithSalt(
- CipherParameters parameters,
- byte[] salt)
- {
- this(parameters, salt, 0, salt.length);
- }
-
- public ParametersWithSalt(
- CipherParameters parameters,
- byte[] salt,
- int saltOff,
- int saltLen)
- {
- this.salt = new byte[saltLen];
- this.parameters = parameters;
-
- System.arraycopy(salt, saltOff, this.salt, 0, saltLen);
- }
-
- public byte[] getSalt()
- {
- return salt;
- }
-
- public CipherParameters getParameters()
- {
- return parameters;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/RC2Parameters.java b/core/src/main/java/org/bouncycastle/crypto/params/RC2Parameters.java
deleted file mode 100644
index dc33ec5b..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/RC2Parameters.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public class RC2Parameters
- implements CipherParameters
-{
- private byte[] key;
- private int bits;
-
- public RC2Parameters(
- byte[] key)
- {
- this(key, (key.length > 128) ? 1024 : (key.length * 8));
- }
-
- public RC2Parameters(
- byte[] key,
- int bits)
- {
- this.key = new byte[key.length];
- this.bits = bits;
-
- System.arraycopy(key, 0, this.key, 0, key.length);
- }
-
- public byte[] getKey()
- {
- return key;
- }
-
- public int getEffectiveKeyBits()
- {
- return bits;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/RC5Parameters.java b/core/src/main/java/org/bouncycastle/crypto/params/RC5Parameters.java
deleted file mode 100644
index 6cbd57f1..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/RC5Parameters.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public class RC5Parameters
- implements CipherParameters
-{
- private byte[] key;
- private int rounds;
-
- public RC5Parameters(
- byte[] key,
- int rounds)
- {
- if (key.length > 255)
- {
- throw new IllegalArgumentException("RC5 key length can be no greater than 255");
- }
-
- this.key = new byte[key.length];
- this.rounds = rounds;
-
- System.arraycopy(key, 0, this.key, 0, key.length);
- }
-
- public byte[] getKey()
- {
- return key;
- }
-
- public int getRounds()
- {
- return rounds;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/RSABlindingParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/RSABlindingParameters.java
deleted file mode 100644
index c7fa6ba6..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/RSABlindingParameters.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-import java.math.BigInteger;
-
-public class RSABlindingParameters
- implements CipherParameters
-{
- private RSAKeyParameters publicKey;
- private BigInteger blindingFactor;
-
- public RSABlindingParameters(
- RSAKeyParameters publicKey,
- BigInteger blindingFactor)
- {
- if (publicKey instanceof RSAPrivateCrtKeyParameters)
- {
- throw new IllegalArgumentException("RSA parameters should be for a public key");
- }
-
- this.publicKey = publicKey;
- this.blindingFactor = blindingFactor;
- }
-
- public RSAKeyParameters getPublicKey()
- {
- return publicKey;
- }
-
- public BigInteger getBlindingFactor()
- {
- return blindingFactor;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/RSAKeyGenerationParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/RSAKeyGenerationParameters.java
deleted file mode 100644
index 38b55fcd..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/RSAKeyGenerationParameters.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.KeyGenerationParameters;
-
-public class RSAKeyGenerationParameters
- extends KeyGenerationParameters
-{
- private BigInteger publicExponent;
- private int certainty;
-
- public RSAKeyGenerationParameters(
- BigInteger publicExponent,
- SecureRandom random,
- int strength,
- int certainty)
- {
- super(random, strength);
-
- if (strength < 12)
- {
- throw new IllegalArgumentException("key strength too small");
- }
-
- //
- // public exponent cannot be even
- //
- if (!publicExponent.testBit(0))
- {
- throw new IllegalArgumentException("public exponent cannot be even");
- }
-
- this.publicExponent = publicExponent;
- this.certainty = certainty;
- }
-
- public BigInteger getPublicExponent()
- {
- return publicExponent;
- }
-
- public int getCertainty()
- {
- return certainty;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/RSAKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/RSAKeyParameters.java
deleted file mode 100644
index 4a2d9354..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/RSAKeyParameters.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-public class RSAKeyParameters
- extends AsymmetricKeyParameter
-{
- private BigInteger modulus;
- private BigInteger exponent;
-
- public RSAKeyParameters(
- boolean isPrivate,
- BigInteger modulus,
- BigInteger exponent)
- {
- super(isPrivate);
-
- this.modulus = modulus;
- this.exponent = exponent;
- }
-
- public BigInteger getModulus()
- {
- return modulus;
- }
-
- public BigInteger getExponent()
- {
- return exponent;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/RSAPrivateCrtKeyParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/RSAPrivateCrtKeyParameters.java
deleted file mode 100644
index b61cb5c4..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/RSAPrivateCrtKeyParameters.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-public class RSAPrivateCrtKeyParameters
- extends RSAKeyParameters
-{
- private BigInteger e;
- private BigInteger p;
- private BigInteger q;
- private BigInteger dP;
- private BigInteger dQ;
- private BigInteger qInv;
-
- /**
- *
- */
- public RSAPrivateCrtKeyParameters(
- BigInteger modulus,
- BigInteger publicExponent,
- BigInteger privateExponent,
- BigInteger p,
- BigInteger q,
- BigInteger dP,
- BigInteger dQ,
- BigInteger qInv)
- {
- super(true, modulus, privateExponent);
-
- this.e = publicExponent;
- this.p = p;
- this.q = q;
- this.dP = dP;
- this.dQ = dQ;
- this.qInv = qInv;
- }
-
- public BigInteger getPublicExponent()
- {
- return e;
- }
-
- public BigInteger getP()
- {
- return p;
- }
-
- public BigInteger getQ()
- {
- return q;
- }
-
- public BigInteger getDP()
- {
- return dP;
- }
-
- public BigInteger getDQ()
- {
- return dQ;
- }
-
- public BigInteger getQInv()
- {
- return qInv;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/params/SkeinParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/SkeinParameters.java
deleted file mode 100644
index 326e106c..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/SkeinParameters.java
+++ /dev/null
@@ -1,329 +0,0 @@
-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 java.util.Locale;
-
-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 &lt; {@value SkeinParameters#PARAM_TYPE_MESSAGE} are processed before
- * the message content, parameters with type &gt; {@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 the current builder.
- */
- 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);
- }
- }
-
- /**
- * Implements the recommended personalisation format for Skein defined in Section 4.11 of
- * the Skein 1.3 specification. You may need to use this method if the default locale
- * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible implementations.
- * <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 dateLocale locale to be used for date interpretation.
- * @param emailAddress the email address of the creation of the personalised application.
- * @param distinguisher an arbitrary personalisation string distinguishing the application.
- * @return the current builder.
- */
- public Builder setPersonalisation(Date date, Locale dateLocale, String emailAddress, String distinguisher)
- {
- try
- {
- final ByteArrayOutputStream bout = new ByteArrayOutputStream();
- final OutputStreamWriter out = new OutputStreamWriter(bout, "UTF-8");
- final DateFormat format = new SimpleDateFormat("YYYYMMDD", dateLocale);
- 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/core/src/main/java/org/bouncycastle/crypto/params/TweakableBlockCipherParameters.java b/core/src/main/java/org/bouncycastle/crypto/params/TweakableBlockCipherParameters.java
deleted file mode 100644
index fa16facd..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/params/TweakableBlockCipherParameters.java
+++ /dev/null
@@ -1,40 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/parsers/DHIESPublicKeyParser.java b/core/src/main/java/org/bouncycastle/crypto/parsers/DHIESPublicKeyParser.java
deleted file mode 100644
index 44f5b571..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/parsers/DHIESPublicKeyParser.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.bouncycastle.crypto.parsers;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.KeyParser;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.crypto.params.DHPublicKeyParameters;
-
-public class DHIESPublicKeyParser
- implements KeyParser
-{
- private DHParameters dhParams;
-
- public DHIESPublicKeyParser(DHParameters dhParams)
- {
- this.dhParams = dhParams;
- }
-
- public AsymmetricKeyParameter readKey(InputStream stream)
- throws IOException
- {
- byte[] V = new byte[(dhParams.getP().bitLength() + 7) / 8];
-
- stream.read(V, 0, V.length);
-
- return new DHPublicKeyParameters(new BigInteger(1, V), dhParams);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/parsers/ECIESPublicKeyParser.java b/core/src/main/java/org/bouncycastle/crypto/parsers/ECIESPublicKeyParser.java
deleted file mode 100644
index 1880a506..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/parsers/ECIESPublicKeyParser.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.bouncycastle.crypto.parsers;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.bouncycastle.crypto.KeyParser;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-
-public class ECIESPublicKeyParser
- implements KeyParser
-{
- private ECDomainParameters ecParams;
-
- public ECIESPublicKeyParser(ECDomainParameters ecParams)
- {
- this.ecParams = ecParams;
- }
-
- public AsymmetricKeyParameter readKey(InputStream stream)
- throws IOException
- {
- byte[] V;
- int first = stream.read();
-
- // Decode the public ephemeral key
- switch (first)
- {
- case 0x00: // infinity
- throw new IOException("Sender's public key invalid.");
-
- case 0x02: // compressed
- case 0x03: // Byte length calculated as in ECPoint.getEncoded();
- V = new byte[1 + (ecParams.getCurve().getFieldSize()+7)/8];
- break;
-
- case 0x04: // uncompressed or
- case 0x06: // hybrid
- case 0x07: // Byte length calculated as in ECPoint.getEncoded();
- V = new byte[1 + 2*((ecParams.getCurve().getFieldSize()+7)/8)];
- break;
-
- default:
- throw new IOException("Sender's public key has invalid point encoding 0x" + Integer.toString(first, 16));
- }
-
- V[0] = (byte)first;
- stream.read(V, 1, V.length - 1);
-
- return new ECPublicKeyParameters(ecParams.getCurve().decodePoint(V), ecParams);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/prng/BasicEntropySourceProvider.java b/core/src/main/java/org/bouncycastle/crypto/prng/BasicEntropySourceProvider.java
deleted file mode 100644
index 9f1d0427..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/prng/BasicEntropySourceProvider.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.bouncycastle.crypto.prng;
-
-import java.security.SecureRandom;
-
-/**
- * An EntropySourceProvider where entropy generation is based on a SecureRandom output using SecureRandom.generateSeed().
- */
-public class BasicEntropySourceProvider
- implements EntropySourceProvider
-{
- private final SecureRandom _sr;
- private final boolean _predictionResistant;
-
- /**
- * Create a entropy source provider based on the passed in SecureRandom.
- *
- * @param random the SecureRandom to base EntropySource construction on.
- * @param isPredictionResistant boolean indicating if the SecureRandom is based on prediction resistant entropy or not (true if it is).
- */
- public BasicEntropySourceProvider(SecureRandom random, boolean isPredictionResistant)
- {
- _sr = random;
- _predictionResistant = isPredictionResistant;
- }
-
- /**
- * Return an entropy source that will create bitsRequired bits of entropy on
- * each invocation of getEntropy().
- *
- * @param bitsRequired size (in bits) of entropy to be created by the provided source.
- * @return an EntropySource that generates bitsRequired bits of entropy on each call to its getEntropy() method.
- */
- public EntropySource get(final int bitsRequired)
- {
- return new EntropySource()
- {
- public boolean isPredictionResistant()
- {
- return _predictionResistant;
- }
-
- public byte[] getEntropy()
- {
- return _sr.generateSeed((bitsRequired + 7) / 8);
- }
-
- public int entropySize()
- {
- return bitsRequired;
- }
- };
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/prng/DRBGProvider.java b/core/src/main/java/org/bouncycastle/crypto/prng/DRBGProvider.java
deleted file mode 100644
index c39760c9..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/prng/DRBGProvider.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.bouncycastle.crypto.prng;
-
-import org.bouncycastle.crypto.prng.drbg.SP80090DRBG;
-
-interface DRBGProvider
-{
- SP80090DRBG get(EntropySource entropySource);
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/prng/DigestRandomGenerator.java b/core/src/main/java/org/bouncycastle/crypto/prng/DigestRandomGenerator.java
deleted file mode 100644
index f36b62c2..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/prng/DigestRandomGenerator.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package org.bouncycastle.crypto.prng;
-
-import org.bouncycastle.crypto.Digest;
-
-/**
- * Random generation based on the digest with counter. Calling addSeedMaterial will
- * always increase the entropy of the hash.
- * <p>
- * Internal access to the digest is synchronized so a single one of these can be shared.
- * </p>
- */
-public class DigestRandomGenerator
- implements RandomGenerator
-{
- private static long CYCLE_COUNT = 10;
-
- private long stateCounter;
- private long seedCounter;
- private Digest digest;
- private byte[] state;
- private byte[] seed;
-
- // public constructors
- public DigestRandomGenerator(
- Digest digest)
- {
- this.digest = digest;
-
- this.seed = new byte[digest.getDigestSize()];
- this.seedCounter = 1;
-
- this.state = new byte[digest.getDigestSize()];
- this.stateCounter = 1;
- }
-
- public void addSeedMaterial(byte[] inSeed)
- {
- synchronized (this)
- {
- digestUpdate(inSeed);
- digestUpdate(seed);
- digestDoFinal(seed);
- }
- }
-
- public void addSeedMaterial(long rSeed)
- {
- synchronized (this)
- {
- digestAddCounter(rSeed);
- digestUpdate(seed);
-
- digestDoFinal(seed);
- }
- }
-
- public void nextBytes(byte[] bytes)
- {
- nextBytes(bytes, 0, bytes.length);
- }
-
- public void nextBytes(byte[] bytes, int start, int len)
- {
- synchronized (this)
- {
- int stateOff = 0;
-
- generateState();
-
- int end = start + len;
- for (int i = start; i != end; i++)
- {
- if (stateOff == state.length)
- {
- generateState();
- stateOff = 0;
- }
- bytes[i] = state[stateOff++];
- }
- }
- }
-
- private void cycleSeed()
- {
- digestUpdate(seed);
- digestAddCounter(seedCounter++);
-
- digestDoFinal(seed);
- }
-
- private void generateState()
- {
- digestAddCounter(stateCounter++);
- digestUpdate(state);
- digestUpdate(seed);
-
- digestDoFinal(state);
-
- if ((stateCounter % CYCLE_COUNT) == 0)
- {
- cycleSeed();
- }
- }
-
- private void digestAddCounter(long seed)
- {
- for (int i = 0; i != 8; i++)
- {
- digest.update((byte)seed);
- seed >>>= 8;
- }
- }
-
- private void digestUpdate(byte[] inSeed)
- {
- digest.update(inSeed, 0, inSeed.length);
- }
-
- private void digestDoFinal(byte[] result)
- {
- digest.doFinal(result, 0);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/prng/EntropySource.java b/core/src/main/java/org/bouncycastle/crypto/prng/EntropySource.java
deleted file mode 100644
index 53bc549d..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/prng/EntropySource.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.crypto.prng;
-
-public interface EntropySource
-{
- /**
- * Return whether or not this entropy source is regarded as prediction resistant.
- *
- * @return true if it is, false otherwise.
- */
- boolean isPredictionResistant();
-
- /**
- * Return a byte array of entropy.
- *
- * @return entropy bytes.
- */
- byte[] getEntropy();
-
- /**
- * Return the number of bits of entropy this source can produce.
- *
- * @return size in bits of the return value of getEntropy.
- */
- int entropySize();
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/prng/EntropySourceProvider.java b/core/src/main/java/org/bouncycastle/crypto/prng/EntropySourceProvider.java
deleted file mode 100644
index 190bf624..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/prng/EntropySourceProvider.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.bouncycastle.crypto.prng;
-
-public interface EntropySourceProvider
-{
- EntropySource get(final int bitsRequired);
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/prng/FixedSecureRandom.java b/core/src/main/java/org/bouncycastle/crypto/prng/FixedSecureRandom.java
deleted file mode 100644
index 3245eabb..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/prng/FixedSecureRandom.java
+++ /dev/null
@@ -1,147 +0,0 @@
-package org.bouncycastle.crypto.prng;
-
-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
-{
- private byte[] _data;
-
- private int _index;
- private int _intPad;
-
- public FixedSecureRandom(byte[] value)
- {
- this(false, new byte[][] { value });
- }
-
- public FixedSecureRandom(
- byte[][] values)
- {
- this(false, values);
- }
-
- /**
- * Pad the data on integer boundaries. This is necessary for the classpath project's BigInteger
- * implementation.
- */
- public FixedSecureRandom(
- boolean intPad,
- byte[] value)
- {
- this(intPad, new byte[][] { value });
- }
-
- /**
- * Pad the data on integer boundaries. This is necessary for the classpath project's BigInteger
- * implementation.
- */
- public FixedSecureRandom(
- boolean intPad,
- byte[][] values)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- for (int i = 0; i != values.length; i++)
- {
- try
- {
- bOut.write(values[i]);
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("can't save value array.");
- }
- }
-
- _data = bOut.toByteArray();
-
- if (intPad)
- {
- _intPad = _data.length % 4;
- }
- }
-
- public void nextBytes(byte[] bytes)
- {
- System.arraycopy(_data, _index, bytes, 0, bytes.length);
-
- _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.
- //
- public int nextInt()
- {
- int val = 0;
-
- val |= nextValue() << 24;
- val |= nextValue() << 16;
-
- if (_intPad == 2)
- {
- _intPad--;
- }
- else
- {
- val |= nextValue() << 8;
- }
-
- if (_intPad == 1)
- {
- _intPad--;
- }
- else
- {
- val |= nextValue();
- }
-
- return val;
- }
-
- //
- // 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.
- //
- public long nextLong()
- {
- long val = 0;
-
- val |= (long)nextValue() << 56;
- val |= (long)nextValue() << 48;
- val |= (long)nextValue() << 40;
- val |= (long)nextValue() << 32;
- val |= (long)nextValue() << 24;
- val |= (long)nextValue() << 16;
- val |= (long)nextValue() << 8;
- val |= (long)nextValue();
-
- return val;
- }
-
- public boolean isExhausted()
- {
- return _index == _data.length;
- }
-
- private int nextValue()
- {
- return _data[_index++] & 0xff;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/prng/RandomGenerator.java b/core/src/main/java/org/bouncycastle/crypto/prng/RandomGenerator.java
deleted file mode 100644
index 47ff68e3..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/prng/RandomGenerator.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.bouncycastle.crypto.prng;
-
-/**
- * Generic interface for objects generating random bytes.
- */
-public interface RandomGenerator
-{
- /**
- * Add more seed material to the generator.
- *
- * @param seed a byte array to be mixed into the generator's state.
- */
- void addSeedMaterial(byte[] seed);
-
- /**
- * Add more seed material to the generator.
- *
- * @param seed a long value to be mixed into the generator's state.
- */
- void addSeedMaterial(long seed);
-
- /**
- * Fill bytes with random values.
- *
- * @param bytes byte array to be filled.
- */
- void nextBytes(byte[] bytes);
-
- /**
- * Fill part of bytes with random values.
- *
- * @param bytes byte array to be filled.
- * @param start index to start filling at.
- * @param len length of segment to fill.
- */
- void nextBytes(byte[] bytes, int start, int len);
-
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/prng/ReversedWindowGenerator.java b/core/src/main/java/org/bouncycastle/crypto/prng/ReversedWindowGenerator.java
deleted file mode 100644
index fbb2639c..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/prng/ReversedWindowGenerator.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package org.bouncycastle.crypto.prng;
-
-/**
- * Takes bytes generated by an underling RandomGenerator and reverses the order in
- * each small window (of configurable size).
- * <p>
- * Access to internals is synchronized so a single one of these can be shared.
- * </p>
- */
-public class ReversedWindowGenerator
- implements RandomGenerator
-{
- private final RandomGenerator generator;
-
- private byte[] window;
- private int windowCount;
-
- public ReversedWindowGenerator(
- RandomGenerator generator,
- int windowSize)
- {
- if (generator == null)
- {
- throw new IllegalArgumentException("generator cannot be null");
- }
- if (windowSize < 2)
- {
- throw new IllegalArgumentException("windowSize must be at least 2");
- }
-
- this.generator = generator;
- this.window = new byte[windowSize];
- }
-
- /**
- * Add more seed material to the generator.
- *
- * @param seed a byte array to be mixed into the generator's state.
- */
- public void addSeedMaterial(
- byte[] seed)
- {
- synchronized (this)
- {
- windowCount = 0;
- generator.addSeedMaterial(seed);
- }
- }
-
- /**
- * Add more seed material to the generator.
- *
- * @param seed a long value to be mixed into the generator's state.
- */
- public void addSeedMaterial(
- long seed)
- {
- synchronized (this)
- {
- windowCount = 0;
- generator.addSeedMaterial(seed);
- }
- }
-
- /**
- * Fill bytes with random values.
- *
- * @param bytes byte array to be filled.
- */
- public void nextBytes(
- byte[] bytes)
- {
- doNextBytes(bytes, 0, bytes.length);
- }
-
- /**
- * Fill part of bytes with random values.
- *
- * @param bytes byte array to be filled.
- * @param start index to start filling at.
- * @param len length of segment to fill.
- */
- public void nextBytes(
- byte[] bytes,
- int start,
- int len)
- {
- doNextBytes(bytes, start, len);
- }
-
- private void doNextBytes(
- byte[] bytes,
- int start,
- int len)
- {
- synchronized (this)
- {
- int done = 0;
- while (done < len)
- {
- if (windowCount < 1)
- {
- generator.nextBytes(window, 0, window.length);
- windowCount = window.length;
- }
-
- bytes[start + done++] = window[--windowCount];
- }
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/prng/SP800SecureRandom.java b/core/src/main/java/org/bouncycastle/crypto/prng/SP800SecureRandom.java
deleted file mode 100644
index e1ec6c28..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/prng/SP800SecureRandom.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package org.bouncycastle.crypto.prng;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.prng.drbg.SP80090DRBG;
-
-public class SP800SecureRandom
- extends SecureRandom
-{
- private final DRBGProvider drbgProvider;
- private final boolean predictionResistant;
- private final SecureRandom randomSource;
- private final EntropySource entropySource;
-
- private SP80090DRBG drbg;
-
- SP800SecureRandom(SecureRandom randomSource, EntropySource entropySource, DRBGProvider drbgProvider, boolean predictionResistant)
- {
- this.randomSource = randomSource;
- this.entropySource = entropySource;
- this.drbgProvider = drbgProvider;
- this.predictionResistant = predictionResistant;
- }
-
- public void setSeed(byte[] seed)
- {
- synchronized (this)
- {
- if (randomSource != null)
- {
- this.randomSource.setSeed(seed);
- }
- }
- }
-
- public void setSeed(long seed)
- {
- synchronized (this)
- {
- // this will happen when SecureRandom() is created
- if (randomSource != null)
- {
- this.randomSource.setSeed(seed);
- }
- }
- }
-
- public void nextBytes(byte[] bytes)
- {
- synchronized (this)
- {
- if (drbg == null)
- {
- drbg = drbgProvider.get(entropySource);
- }
-
- // check if a reseed is required...
- if (drbg.generate(bytes, null, predictionResistant) < 0)
- {
- drbg.reseed(entropySource.getEntropy());
- drbg.generate(bytes, null, predictionResistant);
- }
- }
- }
-
- public byte[] generateSeed(int numBytes)
- {
- byte[] bytes = new byte[numBytes];
-
- this.nextBytes(bytes);
-
- return bytes;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/prng/SP800SecureRandomBuilder.java b/core/src/main/java/org/bouncycastle/crypto/prng/SP800SecureRandomBuilder.java
deleted file mode 100644
index 59ea1010..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/prng/SP800SecureRandomBuilder.java
+++ /dev/null
@@ -1,290 +0,0 @@
-package org.bouncycastle.crypto.prng;
-
-import java.security.SecureRandom;
-
-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;
-import org.bouncycastle.crypto.prng.drbg.SP80090DRBG;
-
-/**
- * Builder class for making SecureRandom objects based on SP 800-90A Deterministic Random Bit Generators (DRBG).
- */
-public class SP800SecureRandomBuilder
-{
- private final SecureRandom random;
- private final EntropySourceProvider entropySourceProvider;
-
- private byte[] personalizationString;
- private int securityStrength = 256;
- private int entropyBitsRequired = 256;
-
- /**
- * Basic constructor, creates a builder using an EntropySourceProvider based on the default SecureRandom with
- * predictionResistant set to false.
- * <p>
- * Any SecureRandom created from a builder constructed like this will make use of input passed to SecureRandom.setSeed() if
- * the default SecureRandom does for its generateSeed() call.
- * </p>
- */
- public SP800SecureRandomBuilder()
- {
- this(new SecureRandom(), false);
- }
-
- /**
- * Construct a builder with an EntropySourceProvider based on the passed in SecureRandom and the passed in value
- * for prediction resistance.
- * <p>
- * Any SecureRandom created from a builder constructed like this will make use of input passed to SecureRandom.setSeed() if
- * the passed in SecureRandom does for its generateSeed() call.
- * </p>
- * @param entropySource
- * @param predictionResistant
- */
- public SP800SecureRandomBuilder(SecureRandom entropySource, boolean predictionResistant)
- {
- this.random = entropySource;
- this.entropySourceProvider = new BasicEntropySourceProvider(random, predictionResistant);
- }
-
- /**
- * Create a builder which makes creates the SecureRandom objects from a specified entropy source provider.
- * <p>
- * <b>Note:</b> If this constructor is used any calls to setSeed() in the resulting SecureRandom will be ignored.
- * </p>
- * @param entropySourceProvider a provider of EntropySource objects.
- */
- public SP800SecureRandomBuilder(EntropySourceProvider entropySourceProvider)
- {
- this.random = null;
- this.entropySourceProvider = entropySourceProvider;
- }
-
- /**
- * Set the personalization string for DRBG SecureRandoms created by this builder
- * @param personalizationString the personalisation string for the underlying DRBG.
- * @return the current builder.
- */
- public SP800SecureRandomBuilder setPersonalizationString(byte[] personalizationString)
- {
- this.personalizationString = personalizationString;
-
- return this;
- }
-
- /**
- * Set the security strength required for DRBGs used in building SecureRandom objects.
- *
- * @param securityStrength the security strength (in bits)
- * @return the current builder.
- */
- public SP800SecureRandomBuilder setSecurityStrength(int securityStrength)
- {
- this.securityStrength = securityStrength;
-
- return this;
- }
-
- /**
- * Set the amount of entropy bits required for seeding and reseeding DRBGs used in building SecureRandom objects.
- *
- * @param entropyBitsRequired the number of bits of entropy to be requested from the entropy source on each seed/reseed.
- * @return the current builder.
- */
- public SP800SecureRandomBuilder setEntropyBitsRequired(int entropyBitsRequired)
- {
- this.entropyBitsRequired = entropyBitsRequired;
-
- return this;
- }
-
- /**
- * Build a SecureRandom based on a SP 800-90A Hash DRBG.
- *
- * @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 Hash DRBG.
- */
- public SP800SecureRandom buildHash(Digest digest, byte[] nonce, boolean predictionResistant)
- {
- return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new HashDRBGProvider(digest, nonce, personalizationString, securityStrength), predictionResistant);
- }
-
- /**
- * Build a SecureRandom based on a SP 800-90A CTR DRBG.
- *
- * @param cipher the block cipher to base the DRBG on.
- * @param keySizeInBits key size in bits to be used with the block cipher.
- * @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 CTR DRBG.
- */
- public SP800SecureRandom buildCTR(BlockCipher cipher, int keySizeInBits, byte[] nonce, boolean predictionResistant)
- {
- return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new CTRDRBGProvider(cipher, keySizeInBits, nonce, personalizationString, securityStrength), predictionResistant);
- }
-
- /**
- * Build a SecureRandom based on a SP 800-90A HMAC DRBG.
- *
- * @param hMac HMAC 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 HMAC DRBG.
- */
- public SP800SecureRandom buildHMAC(Mac hMac, byte[] nonce, boolean predictionResistant)
- {
- return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new HMacDRBGProvider(hMac, nonce, personalizationString, securityStrength), predictionResistant);
- }
-
- /**
- * 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.
- * @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(Digest digest, byte[] nonce, boolean predictionResistant)
- {
- 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
- {
- private final Digest digest;
- private final byte[] nonce;
- private final byte[] personalizationString;
- private final int securityStrength;
-
- public HashDRBGProvider(Digest digest, byte[] nonce, byte[] personalizationString, int securityStrength)
- {
- this.digest = digest;
- this.nonce = nonce;
- this.personalizationString = personalizationString;
- this.securityStrength = securityStrength;
- }
-
- public SP80090DRBG get(EntropySource entropySource)
- {
- return new HashSP800DRBG(digest, securityStrength, entropySource, personalizationString, nonce);
- }
- }
-
- private static class DualECDRBGProvider
- implements DRBGProvider
- {
- private final Digest digest;
- private final byte[] nonce;
- private final byte[] personalizationString;
- private final int securityStrength;
-
- public DualECDRBGProvider(Digest digest, byte[] nonce, byte[] personalizationString, int securityStrength)
- {
- this.digest = digest;
- this.nonce = nonce;
- this.personalizationString = personalizationString;
- this.securityStrength = securityStrength;
- }
-
- public SP80090DRBG get(EntropySource entropySource)
- {
- return new DualECSP800DRBG(digest, securityStrength, entropySource, personalizationString, nonce);
- }
- }
-
- 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
- {
- private final Mac hMac;
- private final byte[] nonce;
- private final byte[] personalizationString;
- private final int securityStrength;
-
- public HMacDRBGProvider(Mac hMac, byte[] nonce, byte[] personalizationString, int securityStrength)
- {
- this.hMac = hMac;
- this.nonce = nonce;
- this.personalizationString = personalizationString;
- this.securityStrength = securityStrength;
- }
-
- public SP80090DRBG get(EntropySource entropySource)
- {
- return new HMacSP800DRBG(hMac, securityStrength, entropySource, personalizationString, nonce);
- }
- }
-
- private static class CTRDRBGProvider
- implements DRBGProvider
- {
-
- private final BlockCipher blockCipher;
- private final int keySizeInBits;
- private final byte[] nonce;
- private final byte[] personalizationString;
- private final int securityStrength;
-
- public CTRDRBGProvider(BlockCipher blockCipher, int keySizeInBits, byte[] nonce, byte[] personalizationString, int securityStrength)
- {
- this.blockCipher = blockCipher;
- this.keySizeInBits = keySizeInBits;
- this.nonce = nonce;
- this.personalizationString = personalizationString;
- this.securityStrength = securityStrength;
- }
-
- public SP80090DRBG get(EntropySource entropySource)
- {
- return new CTRSP800DRBG(blockCipher, keySizeInBits, securityStrength, entropySource, personalizationString, nonce);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/prng/ThreadedSeedGenerator.java b/core/src/main/java/org/bouncycastle/crypto/prng/ThreadedSeedGenerator.java
deleted file mode 100644
index 6b2d5ec2..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/prng/ThreadedSeedGenerator.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package org.bouncycastle.crypto.prng;
-
-/**
- * A thread based seed generator - one source of randomness.
- * <p>
- * Based on an idea from Marcus Lippert.
- * </p>
- */
-public class ThreadedSeedGenerator
-{
- private class SeedGenerator
- implements Runnable
- {
- private volatile int counter = 0;
- private volatile boolean stop = false;
-
- public void run()
- {
- while (!this.stop)
- {
- this.counter++;
- }
-
- }
-
- public byte[] generateSeed(
- int numbytes,
- boolean fast)
- {
- Thread t = new Thread(this);
- byte[] result = new byte[numbytes];
- this.counter = 0;
- this.stop = false;
- int last = 0;
- int end;
-
- t.start();
- if(fast)
- {
- end = numbytes;
- }
- else
- {
- end = numbytes * 8;
- }
- for (int i = 0; i < end; i++)
- {
- while (this.counter == last)
- {
- try
- {
- Thread.sleep(1);
- }
- catch (InterruptedException e)
- {
- // ignore
- }
- }
- last = this.counter;
- if (fast)
- {
- result[i] = (byte) (last & 0xff);
- }
- else
- {
- int bytepos = i/8;
- result[bytepos] = (byte) ((result[bytepos] << 1) | (last & 1));
- }
-
- }
- stop = true;
- return result;
- }
- }
-
- /**
- * Generate seed bytes. Set fast to false for best quality.
- * <p>
- * If fast is set to true, the code should be round about 8 times faster when
- * generating a long sequence of random bytes. 20 bytes of random values using
- * the fast mode take less than half a second on a Nokia e70. If fast is set to false,
- * it takes round about 2500 ms.
- * </p>
- * @param numBytes the number of bytes to generate
- * @param fast true if fast mode should be used
- */
- public byte[] generateSeed(
- int numBytes,
- boolean fast)
- {
- SeedGenerator gen = new SeedGenerator();
-
- return gen.generateSeed(numBytes, fast);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/prng/VMPCRandomGenerator.java b/core/src/main/java/org/bouncycastle/crypto/prng/VMPCRandomGenerator.java
deleted file mode 100644
index c7e420db..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/prng/VMPCRandomGenerator.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package org.bouncycastle.crypto.prng;
-
-import org.bouncycastle.util.Pack;
-
-public class VMPCRandomGenerator implements RandomGenerator
-{
- private byte n = 0;
-
- /**
- * Permutation generated by code: <code>
- * // First 1850 fractional digit of Pi number.
- * byte[] key = new BigInteger("14159265358979323846...5068006422512520511").toByteArray();
- * s = 0;
- * P = new byte[256];
- * for (int i = 0; i < 256; i++) {
- * P[i] = (byte) i;
- * }
- * for (int m = 0; m < 768; m++) {
- * s = P[(s + P[m & 0xff] + key[m % key.length]) & 0xff];
- * byte temp = P[m & 0xff];
- * P[m & 0xff] = P[s & 0xff];
- * P[s & 0xff] = temp;
- * } </code>
- */
- private byte[] P =
- {
- (byte) 0xbb, (byte) 0x2c, (byte) 0x62, (byte) 0x7f,
- (byte) 0xb5, (byte) 0xaa, (byte) 0xd4, (byte) 0x0d, (byte) 0x81,
- (byte) 0xfe, (byte) 0xb2, (byte) 0x82, (byte) 0xcb, (byte) 0xa0,
- (byte) 0xa1, (byte) 0x08, (byte) 0x18, (byte) 0x71, (byte) 0x56,
- (byte) 0xe8, (byte) 0x49, (byte) 0x02, (byte) 0x10, (byte) 0xc4,
- (byte) 0xde, (byte) 0x35, (byte) 0xa5, (byte) 0xec, (byte) 0x80,
- (byte) 0x12, (byte) 0xb8, (byte) 0x69, (byte) 0xda, (byte) 0x2f,
- (byte) 0x75, (byte) 0xcc, (byte) 0xa2, (byte) 0x09, (byte) 0x36,
- (byte) 0x03, (byte) 0x61, (byte) 0x2d, (byte) 0xfd, (byte) 0xe0,
- (byte) 0xdd, (byte) 0x05, (byte) 0x43, (byte) 0x90, (byte) 0xad,
- (byte) 0xc8, (byte) 0xe1, (byte) 0xaf, (byte) 0x57, (byte) 0x9b,
- (byte) 0x4c, (byte) 0xd8, (byte) 0x51, (byte) 0xae, (byte) 0x50,
- (byte) 0x85, (byte) 0x3c, (byte) 0x0a, (byte) 0xe4, (byte) 0xf3,
- (byte) 0x9c, (byte) 0x26, (byte) 0x23, (byte) 0x53, (byte) 0xc9,
- (byte) 0x83, (byte) 0x97, (byte) 0x46, (byte) 0xb1, (byte) 0x99,
- (byte) 0x64, (byte) 0x31, (byte) 0x77, (byte) 0xd5, (byte) 0x1d,
- (byte) 0xd6, (byte) 0x78, (byte) 0xbd, (byte) 0x5e, (byte) 0xb0,
- (byte) 0x8a, (byte) 0x22, (byte) 0x38, (byte) 0xf8, (byte) 0x68,
- (byte) 0x2b, (byte) 0x2a, (byte) 0xc5, (byte) 0xd3, (byte) 0xf7,
- (byte) 0xbc, (byte) 0x6f, (byte) 0xdf, (byte) 0x04, (byte) 0xe5,
- (byte) 0x95, (byte) 0x3e, (byte) 0x25, (byte) 0x86, (byte) 0xa6,
- (byte) 0x0b, (byte) 0x8f, (byte) 0xf1, (byte) 0x24, (byte) 0x0e,
- (byte) 0xd7, (byte) 0x40, (byte) 0xb3, (byte) 0xcf, (byte) 0x7e,
- (byte) 0x06, (byte) 0x15, (byte) 0x9a, (byte) 0x4d, (byte) 0x1c,
- (byte) 0xa3, (byte) 0xdb, (byte) 0x32, (byte) 0x92, (byte) 0x58,
- (byte) 0x11, (byte) 0x27, (byte) 0xf4, (byte) 0x59, (byte) 0xd0,
- (byte) 0x4e, (byte) 0x6a, (byte) 0x17, (byte) 0x5b, (byte) 0xac,
- (byte) 0xff, (byte) 0x07, (byte) 0xc0, (byte) 0x65, (byte) 0x79,
- (byte) 0xfc, (byte) 0xc7, (byte) 0xcd, (byte) 0x76, (byte) 0x42,
- (byte) 0x5d, (byte) 0xe7, (byte) 0x3a, (byte) 0x34, (byte) 0x7a,
- (byte) 0x30, (byte) 0x28, (byte) 0x0f, (byte) 0x73, (byte) 0x01,
- (byte) 0xf9, (byte) 0xd1, (byte) 0xd2, (byte) 0x19, (byte) 0xe9,
- (byte) 0x91, (byte) 0xb9, (byte) 0x5a, (byte) 0xed, (byte) 0x41,
- (byte) 0x6d, (byte) 0xb4, (byte) 0xc3, (byte) 0x9e, (byte) 0xbf,
- (byte) 0x63, (byte) 0xfa, (byte) 0x1f, (byte) 0x33, (byte) 0x60,
- (byte) 0x47, (byte) 0x89, (byte) 0xf0, (byte) 0x96, (byte) 0x1a,
- (byte) 0x5f, (byte) 0x93, (byte) 0x3d, (byte) 0x37, (byte) 0x4b,
- (byte) 0xd9, (byte) 0xa8, (byte) 0xc1, (byte) 0x1b, (byte) 0xf6,
- (byte) 0x39, (byte) 0x8b, (byte) 0xb7, (byte) 0x0c, (byte) 0x20,
- (byte) 0xce, (byte) 0x88, (byte) 0x6e, (byte) 0xb6, (byte) 0x74,
- (byte) 0x8e, (byte) 0x8d, (byte) 0x16, (byte) 0x29, (byte) 0xf2,
- (byte) 0x87, (byte) 0xf5, (byte) 0xeb, (byte) 0x70, (byte) 0xe3,
- (byte) 0xfb, (byte) 0x55, (byte) 0x9f, (byte) 0xc6, (byte) 0x44,
- (byte) 0x4a, (byte) 0x45, (byte) 0x7d, (byte) 0xe2, (byte) 0x6b,
- (byte) 0x5c, (byte) 0x6c, (byte) 0x66, (byte) 0xa9, (byte) 0x8c,
- (byte) 0xee, (byte) 0x84, (byte) 0x13, (byte) 0xa7, (byte) 0x1e,
- (byte) 0x9d, (byte) 0xdc, (byte) 0x67, (byte) 0x48, (byte) 0xba,
- (byte) 0x2e, (byte) 0xe6, (byte) 0xa4, (byte) 0xab, (byte) 0x7c,
- (byte) 0x94, (byte) 0x00, (byte) 0x21, (byte) 0xef, (byte) 0xea,
- (byte) 0xbe, (byte) 0xca, (byte) 0x72, (byte) 0x4f, (byte) 0x52,
- (byte) 0x98, (byte) 0x3f, (byte) 0xc2, (byte) 0x14, (byte) 0x7b,
- (byte) 0x3b, (byte) 0x54 };
-
- /**
- * Value generated in the same way as {@link VMPCRandomGenerator#P};
- */
- private byte s = (byte) 0xbe;
-
- public VMPCRandomGenerator()
- {
- }
-
- public void addSeedMaterial(byte[] seed)
- {
- for (int m = 0; m < seed.length; m++)
- {
- s = P[(s + P[n & 0xff] + seed[m]) & 0xff];
- byte temp = P[n & 0xff];
- P[n & 0xff] = P[s & 0xff];
- P[s & 0xff] = temp;
- n = (byte) ((n + 1) & 0xff);
- }
- }
-
- public void addSeedMaterial(long seed)
- {
- addSeedMaterial(Pack.longToBigEndian(seed));
- }
-
- public void nextBytes(byte[] bytes)
- {
- nextBytes(bytes, 0, bytes.length);
- }
-
- public void nextBytes(byte[] bytes, int start, int len)
- {
- synchronized (P)
- {
- int end = start + len;
- for (int i = start; i != end; i++)
- {
- s = P[(s + P[n & 0xff]) & 0xff];
- bytes[i] = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff];
- byte temp = P[n & 0xff];
- P[n & 0xff] = P[s & 0xff];
- P[s & 0xff] = temp;
- n = (byte) ((n + 1) & 0xff);
- }
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/prng/drbg/CTRSP800DRBG.java b/core/src/main/java/org/bouncycastle/crypto/prng/drbg/CTRSP800DRBG.java
deleted file mode 100644
index 5ab8f469..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/prng/drbg/CTRSP800DRBG.java
+++ /dev/null
@@ -1,478 +0,0 @@
-package org.bouncycastle.crypto.prng.drbg;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.prng.EntropySource;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-
-/**
- * A SP800-90A CTR DRBG.
- */
-public class CTRSP800DRBG
- implements SP80090DRBG
-{
- private static final long TDEA_RESEED_MAX = 1L << (32 - 1);
- private static final long AES_RESEED_MAX = 1L << (48 - 1);
- private static final int TDEA_MAX_BITS_REQUEST = 1 << (13 - 1);
- private static final int AES_MAX_BITS_REQUEST = 1 << (19 - 1);
-
- private EntropySource _entropySource;
- private BlockCipher _engine;
- private int _keySizeInBits;
- private int _seedLength;
-
- // internal state
- private byte[] _Key;
- private byte[] _V;
- private long _reseedCounter = 0;
- private boolean _isTDEA = false;
-
- /**
- * Construct a SP800-90A CTR DRBG.
- * <p>
- * Minimum entropy requirement is the security strength requested.
- * </p>
- * @param engine underlying block cipher to use to support DRBG
- * @param keySizeInBits size of the key to use with the block cipher.
- * @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 CTRSP800DRBG(BlockCipher engine, int keySizeInBits, int securityStrength, EntropySource entropySource, byte[] personalizationString, byte[] nonce)
- {
- _entropySource = entropySource;
- _engine = engine;
-
- _keySizeInBits = keySizeInBits;
- _seedLength = keySizeInBits + engine.getBlockSize() * 8;
- _isTDEA = isTDEA(engine);
-
- if (securityStrength > 256)
- {
- throw new IllegalArgumentException("Requested security strength is not supported by the derivation function");
- }
-
- if (getMaxSecurityStrength(engine, keySizeInBits) < securityStrength)
- {
- throw new IllegalArgumentException("Requested security strength is not supported by block cipher and key size");
- }
-
- if (entropySource.entropySize() < securityStrength)
- {
- throw new IllegalArgumentException("Not enough entropy for security strength required");
- }
-
- byte[] entropy = entropySource.getEntropy(); // Get_entropy_input
-
- CTR_DRBG_Instantiate_algorithm(entropy, nonce, personalizationString);
- }
-
- private void CTR_DRBG_Instantiate_algorithm(byte[] entropy, byte[] nonce,
- byte[] personalisationString)
- {
- byte[] seedMaterial = Arrays.concatenate(entropy, nonce, personalisationString);
- byte[] seed = Block_Cipher_df(seedMaterial, _seedLength);
-
- int outlen = _engine.getBlockSize();
-
- _Key = new byte[(_keySizeInBits + 7) / 8];
- _V = new byte[outlen];
-
- // _Key & _V are modified by this call
- CTR_DRBG_Update(seed, _Key, _V);
-
- _reseedCounter = 1;
- }
-
- private void CTR_DRBG_Update(byte[] seed, byte[] key, byte[] v)
- {
- byte[] temp = new byte[seed.length];
- byte[] outputBlock = new byte[_engine.getBlockSize()];
-
- int i=0;
- int outLen = _engine.getBlockSize();
-
- _engine.init(true, new KeyParameter(expandKey(key)));
- while (i*outLen < seed.length)
- {
- addOneTo(v);
- _engine.processBlock(v, 0, outputBlock, 0);
-
- int bytesToCopy = ((temp.length - i * outLen) > outLen)
- ? outLen : (temp.length - i * outLen);
-
- System.arraycopy(outputBlock, 0, temp, i * outLen, bytesToCopy);
- ++i;
- }
-
- XOR(temp, seed, temp, 0);
-
- System.arraycopy(temp, 0, key, 0, key.length);
- System.arraycopy(temp, key.length, v, 0, v.length);
- }
-
- private void CTR_DRBG_Reseed_algorithm(EntropySource entropy, byte[] additionalInput)
- {
- byte[] seedMaterial = Arrays.concatenate(entropy.getEntropy(), additionalInput);
-
- seedMaterial = Block_Cipher_df(seedMaterial, _seedLength);
-
- CTR_DRBG_Update(seedMaterial, _Key, _V);
-
- _reseedCounter = 1;
- }
-
- private void XOR(byte[] out, byte[] a, byte[] b, int bOff)
- {
- for (int i=0; i< out.length; i++)
- {
- out[i] = (byte)(a[i] ^ b[i+bOff]);
- }
- }
-
- private void addOneTo(byte[] longer)
- {
- int carry = 1;
- for (int i = 1; i <= longer.length; i++) // warning
- {
- int res = (longer[longer.length - i] & 0xff) + carry;
- carry = (res > 0xff) ? 1 : 0;
- longer[longer.length - i] = (byte)res;
- }
- }
-
- // -- Internal state migration ---
-
- private static final byte[] K_BITS = Hex.decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F");
-
- // 1. If (number_of_bits_to_return > max_number_of_bits), then return an
- // ERROR_FLAG.
- // 2. L = len (input_string)/8.
- // 3. N = number_of_bits_to_return/8.
- // Comment: L is the bitstring represention of
- // the integer resulting from len (input_string)/8.
- // L shall be represented as a 32-bit integer.
- //
- // Comment : N is the bitstring represention of
- // the integer resulting from
- // number_of_bits_to_return/8. N shall be
- // represented as a 32-bit integer.
- //
- // 4. S = L || N || input_string || 0x80.
- // 5. While (len (S) mod outlen)
- // Comment : Pad S with zeros, if necessary.
- // 0, S = S || 0x00.
- //
- // Comment : Compute the starting value.
- // 6. temp = the Null string.
- // 7. i = 0.
- // 8. K = Leftmost keylen bits of 0x00010203...1D1E1F.
- // 9. While len (temp) < keylen + outlen, do
- //
- // IV = i || 0outlen - len (i).
- //
- // 9.1
- //
- // temp = temp || BCC (K, (IV || S)).
- //
- // 9.2
- //
- // i = i + 1.
- //
- // 9.3
- //
- // Comment : i shall be represented as a 32-bit
- // integer, i.e., len (i) = 32.
- //
- // Comment: The 32-bit integer represenation of
- // i is padded with zeros to outlen bits.
- //
- // Comment: Compute the requested number of
- // bits.
- //
- // 10. K = Leftmost keylen bits of temp.
- //
- // 11. X = Next outlen bits of temp.
- //
- // 12. temp = the Null string.
- //
- // 13. While len (temp) < number_of_bits_to_return, do
- //
- // 13.1 X = Block_Encrypt (K, X).
- //
- // 13.2 temp = temp || X.
- //
- // 14. requested_bits = Leftmost number_of_bits_to_return of temp.
- //
- // 15. Return SUCCESS and requested_bits.
- private byte[] Block_Cipher_df(byte[] inputString, int bitLength)
- {
- int outLen = _engine.getBlockSize();
- int L = inputString.length; // already in bytes
- int N = bitLength / 8;
- // 4 S = L || N || inputstring || 0x80
- int sLen = 4 + 4 + L + 1;
- int blockLen = ((sLen + outLen - 1) / outLen) * outLen;
- byte[] S = new byte[blockLen];
- copyIntToByteArray(S, L, 0);
- copyIntToByteArray(S, N, 4);
- System.arraycopy(inputString, 0, S, 8, L);
- S[8 + L] = (byte)0x80;
- // S already padded with zeros
-
- byte[] temp = new byte[_keySizeInBits / 8 + outLen];
- byte[] bccOut = new byte[outLen];
-
- byte[] IV = new byte[outLen];
-
- int i = 0;
- byte[] K = new byte[_keySizeInBits / 8];
- System.arraycopy(K_BITS, 0, K, 0, K.length);
-
- while (i*outLen*8 < _keySizeInBits + outLen *8)
- {
- copyIntToByteArray(IV, i, 0);
- BCC(bccOut, K, IV, S);
-
- int bytesToCopy = ((temp.length - i * outLen) > outLen)
- ? outLen
- : (temp.length - i * outLen);
-
- System.arraycopy(bccOut, 0, temp, i * outLen, bytesToCopy);
- ++i;
- }
-
- byte[] X = new byte[outLen];
- System.arraycopy(temp, 0, K, 0, K.length);
- System.arraycopy(temp, K.length, X, 0, X.length);
-
- temp = new byte[bitLength / 2];
-
- i = 0;
- _engine.init(true, new KeyParameter(expandKey(K)));
-
- while (i * outLen < temp.length)
- {
- _engine.processBlock(X, 0, X, 0);
-
- int bytesToCopy = ((temp.length - i * outLen) > outLen)
- ? outLen
- : (temp.length - i * outLen);
-
- System.arraycopy(X, 0, temp, i * outLen, bytesToCopy);
- i++;
- }
-
- return temp;
- }
-
- /*
- * 1. chaining_value = 0^outlen
- * . Comment: Set the first chaining value to outlen zeros.
- * 2. n = len (data)/outlen.
- * 3. Starting with the leftmost bits of data, split the data into n blocks of outlen bits
- * each, forming block(1) to block(n).
- * 4. For i = 1 to n do
- * 4.1 input_block = chaining_value ^ block(i) .
- * 4.2 chaining_value = Block_Encrypt (Key, input_block).
- * 5. output_block = chaining_value.
- * 6. Return output_block.
- */
- private void BCC(byte[] bccOut, byte[] k, byte[] iV, byte[] data)
- {
- int outlen = _engine.getBlockSize();
- byte[] chainingValue = new byte[outlen]; // initial values = 0
- int n = data.length / outlen;
-
- byte[] inputBlock = new byte[outlen];
-
- _engine.init(true, new KeyParameter(expandKey(k)));
-
- _engine.processBlock(iV, 0, chainingValue, 0);
-
- for (int i = 0; i < n; i++)
- {
- XOR(inputBlock, chainingValue, data, i*outlen);
- _engine.processBlock(inputBlock, 0, chainingValue, 0);
- }
-
- System.arraycopy(chainingValue, 0, bccOut, 0, bccOut.length);
- }
-
- private void copyIntToByteArray(byte[] buf, int value, int offSet)
- {
- buf[offSet + 0] = ((byte)(value >> 24));
- buf[offSet + 1] = ((byte)(value >> 16));
- buf[offSet + 2] = ((byte)(value >> 8));
- buf[offSet + 3] = ((byte)(value));
- }
-
- /**
- * Return the block size (in bits) of the DRBG.
- *
- * @return the number of bits produced on each internal round of the DRBG.
- */
- public int getBlockSize()
- {
- return _V.length * 8;
- }
-
- /**
- * Populate a passed in array with random data.
- *
- * @param output output array for generated bits.
- * @param additionalInput additional input to be added to the DRBG in this step.
- * @param predictionResistant true if a reseed should be forced, false otherwise.
- *
- * @return number of bits generated, -1 if a reseed required.
- */
- public int generate(byte[] output, byte[] additionalInput, boolean predictionResistant)
- {
- if (_isTDEA)
- {
- if (_reseedCounter > TDEA_RESEED_MAX)
- {
- return -1;
- }
-
- if (Utils.isTooLarge(output, TDEA_MAX_BITS_REQUEST / 8))
- {
- throw new IllegalArgumentException("Number of bits per request limited to " + TDEA_MAX_BITS_REQUEST);
- }
- }
- else
- {
- if (_reseedCounter > AES_RESEED_MAX)
- {
- return -1;
- }
-
- if (Utils.isTooLarge(output, AES_MAX_BITS_REQUEST / 8))
- {
- throw new IllegalArgumentException("Number of bits per request limited to " + AES_MAX_BITS_REQUEST);
- }
- }
-
- if (predictionResistant)
- {
- CTR_DRBG_Reseed_algorithm(_entropySource, additionalInput);
- additionalInput = null;
- }
-
- if (additionalInput != null)
- {
- additionalInput = Block_Cipher_df(additionalInput, _seedLength);
- CTR_DRBG_Update(additionalInput, _Key, _V);
- }
- else
- {
- additionalInput = new byte[_seedLength];
- }
-
- byte[] out = new byte[_V.length];
-
- _engine.init(true, new KeyParameter(expandKey(_Key)));
-
- for (int i = 0; i < output.length / out.length; i++)
- {
- addOneTo(_V);
-
- _engine.processBlock(_V, 0, out, 0);
-
- int bytesToCopy = ((output.length - i * out.length) > out.length)
- ? out.length
- : (output.length - i * _V.length);
-
- System.arraycopy(out, 0, output, i * out.length, bytesToCopy);
- }
-
- CTR_DRBG_Update(additionalInput, _Key, _V);
-
- _reseedCounter++;
-
- return output.length * 8;
- }
-
- /**
- * Reseed the DRBG.
- *
- * @param additionalInput additional input to be added to the DRBG in this step.
- */
- public void reseed(byte[] additionalInput)
- {
- CTR_DRBG_Reseed_algorithm(_entropySource, additionalInput);
- }
-
- private boolean isTDEA(BlockCipher cipher)
- {
- return cipher.getAlgorithmName().equals("DESede") || cipher.getAlgorithmName().equals("TDEA");
- }
-
- private int getMaxSecurityStrength(BlockCipher cipher, int keySizeInBits)
- {
- if (isTDEA(cipher) && keySizeInBits == 168)
- {
- return 112;
- }
- if (cipher.getAlgorithmName().equals("AES"))
- {
- return keySizeInBits;
- }
-
- return -1;
- }
-
- byte[] expandKey(byte[] key)
- {
- if (_isTDEA)
- {
- // expand key to 192 bits.
- byte[] tmp = new byte[24];
-
- padKey(key, 0, tmp, 0);
- padKey(key, 7, tmp, 8);
- padKey(key, 14, tmp, 16);
-
- return tmp;
- }
- else
- {
- return key;
- }
- }
-
- /**
- * Pad out a key for TDEA, setting odd parity for each byte.
- *
- * @param keyMaster
- * @param keyOff
- * @param tmp
- * @param tmpOff
- */
- private void padKey(byte[] keyMaster, int keyOff, byte[] tmp, int tmpOff)
- {
- tmp[tmpOff + 0] = (byte)(keyMaster[keyOff + 0] & 0xfe);
- tmp[tmpOff + 1] = (byte)((keyMaster[keyOff + 0] << 7) | ((keyMaster[keyOff + 1] & 0xfc) >>> 1));
- tmp[tmpOff + 2] = (byte)((keyMaster[keyOff + 1] << 6) | ((keyMaster[keyOff + 2] & 0xf8) >>> 2));
- tmp[tmpOff + 3] = (byte)((keyMaster[keyOff + 2] << 5) | ((keyMaster[keyOff + 3] & 0xf0) >>> 3));
- tmp[tmpOff + 4] = (byte)((keyMaster[keyOff + 3] << 4) | ((keyMaster[keyOff + 4] & 0xe0) >>> 4));
- tmp[tmpOff + 5] = (byte)((keyMaster[keyOff + 4] << 3) | ((keyMaster[keyOff + 5] & 0xc0) >>> 5));
- tmp[tmpOff + 6] = (byte)((keyMaster[keyOff + 5] << 2) | ((keyMaster[keyOff + 6] & 0x80) >>> 6));
- tmp[tmpOff + 7] = (byte)(keyMaster[keyOff + 6] << 1);
-
- for (int i = tmpOff; i <= tmpOff + 7; i++)
- {
- int b = tmp[i];
- tmp[i] = (byte)((b & 0xfe) |
- ((((b >> 1) ^
- (b >> 2) ^
- (b >> 3) ^
- (b >> 4) ^
- (b >> 5) ^
- (b >> 6) ^
- (b >> 7)) ^ 0x01) & 0x01));
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/prng/drbg/DualECPoints.java b/core/src/main/java/org/bouncycastle/crypto/prng/drbg/DualECPoints.java
deleted file mode 100644
index 7dcfa94f..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/prng/drbg/DualECPoints.java
+++ /dev/null
@@ -1,82 +0,0 @@
-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>
- *
- * @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/core/src/main/java/org/bouncycastle/crypto/prng/drbg/DualECSP800DRBG.java b/core/src/main/java/org/bouncycastle/crypto/prng/drbg/DualECSP800DRBG.java
deleted file mode 100644
index 4e1b881d..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/prng/drbg/DualECSP800DRBG.java
+++ /dev/null
@@ -1,320 +0,0 @@
-package org.bouncycastle.crypto.prng.drbg;
-
-import java.math.BigInteger;
-
-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.ECMultiplier;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.ec.FixedPointCombMultiplier;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.BigIntegers;
-
-/**
- * A SP800-90A Dual EC DRBG.
- */
-public class DualECSP800DRBG
- implements SP80090DRBG
-{
- /*
- * Default P, Q values for each curve
- */
- private static final BigInteger p256_Px = new BigInteger("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16);
- private static final BigInteger p256_Py = new BigInteger("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16);
- private static final BigInteger p256_Qx = new BigInteger("c97445f45cdef9f0d3e05e1e585fc297235b82b5be8ff3efca67c59852018192", 16);
- private static final BigInteger p256_Qy = new BigInteger("b28ef557ba31dfcbdd21ac46e2a91e3c304f44cb87058ada2cb815151e610046", 16);
-
- private static final BigInteger p384_Px = new BigInteger("aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7", 16);
- private static final BigInteger p384_Py = new BigInteger("3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f", 16);
- private static final BigInteger p384_Qx = new BigInteger("8e722de3125bddb05580164bfe20b8b432216a62926c57502ceede31c47816edd1e89769124179d0b695106428815065", 16);
- private static final BigInteger p384_Qy = new BigInteger("023b1660dd701d0839fd45eec36f9ee7b32e13b315dc02610aa1b636e346df671f790f84c5e09b05674dbb7e45c803dd", 16);
-
- private static final BigInteger p521_Px = new BigInteger("c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", 16);
- private static final BigInteger p521_Py = new BigInteger("11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", 16);
- 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);
- private static final int MAX_PERSONALIZATION_STRING = 1 << (13 -1);
-
- private Digest _digest;
- private long _reseedCounter;
- private EntropySource _entropySource;
- private int _securityStrength;
- private int _seedlen;
- private int _outlen;
- private ECCurve.Fp _curve;
- private ECPoint _P;
- private ECPoint _Q;
- private byte[] _s;
- private int _sLength;
- private ECMultiplier _fixedPointMultiplier = new FixedPointCombMultiplier();
-
- /**
- * Construct a SP800-90A Dual EC DRBG.
- * <p>
- * Minimum entropy requirement is the security strength requested.
- * </p>
- * @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(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;
-
- if (Utils.isTooLarge(personalizationString, MAX_PERSONALIZATION_STRING / 8))
- {
- throw new IllegalArgumentException("Personalization string too large");
- }
-
- if (entropySource.entropySize() < securityStrength || entropySource.entropySize() > MAX_ENTROPY_LENGTH)
- {
- throw new IllegalArgumentException("EntropySource must provide between " + securityStrength + " and " + MAX_ENTROPY_LENGTH + " bits");
- }
-
- byte[] entropy = entropySource.getEntropy();
- byte[] seedMaterial = Arrays.concatenate(entropy, nonce, personalizationString);
-
- for (int i = 0; i != pointSet.length; i++)
- {
- if (securityStrength <= pointSet[i].getSecurityStrength())
- {
- 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;
- }
- }
-
- if (_P == null)
- {
- throw new IllegalArgumentException("security strength cannot be greater than 256 bits");
- }
-
- _s = Utils.hash_df(_digest, seedMaterial, _seedlen);
- _sLength = _s.length;
-
- _reseedCounter = 0;
- }
-
- /**
- * Return the block size (in bits) of the DRBG.
- *
- * @return the number of bits produced on each internal round of the DRBG.
- */
- public int getBlockSize()
- {
- return _outlen * 8;
- }
-
- /**
- * Populate a passed in array with random data.
- *
- * @param output output array for generated bits.
- * @param additionalInput additional input to be added to the DRBG in this step.
- * @param predictionResistant true if a reseed should be forced, false otherwise.
- *
- * @return number of bits generated, -1 if a reseed required.
- */
- public int generate(byte[] output, byte[] additionalInput, boolean predictionResistant)
- {
- int numberOfBits = output.length*8;
- int m = output.length / _outlen;
-
- if (Utils.isTooLarge(additionalInput, MAX_ADDITIONAL_INPUT / 8))
- {
- throw new IllegalArgumentException("Additional input too large");
- }
-
- if (_reseedCounter + m > RESEED_MAX)
- {
- return -1;
- }
-
- if (predictionResistant)
- {
- reseed(additionalInput);
- 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++)
- {
- s = getScalarMultipleXCoord(_P, s);
-
- //System.err.println("S: " + new String(Hex.encode(_s)));
-
- byte[] r = getScalarMultipleXCoord(_Q, s).toByteArray();
-
- if (r.length > _outlen)
- {
- System.arraycopy(r, r.length - _outlen, output, outOffset, _outlen);
- }
- else
- {
- System.arraycopy(r, 0, output, outOffset + (_outlen - r.length), r.length);
- }
-
- //System.err.println("R: " + new String(Hex.encode(r)));
- outOffset += _outlen;
-
- _reseedCounter++;
- }
-
- if (outOffset < output.length)
- {
- s = getScalarMultipleXCoord(_P, s);
-
- byte[] r = getScalarMultipleXCoord(_Q, s).toByteArray();
-
- int required = output.length - outOffset;
-
- 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, getScalarMultipleXCoord(_P, s));
-
- return numberOfBits;
- }
-
- /**
- * Reseed the DRBG.
- *
- * @param additionalInput additional input to be added to the DRBG in this step.
- */
- public void reseed(byte[] additionalInput)
- {
- if (Utils.isTooLarge(additionalInput, MAX_ADDITIONAL_INPUT / 8))
- {
- throw new IllegalArgumentException("Additional input string too large");
- }
-
- byte[] entropy = _entropySource.getEntropy();
- byte[] seedMaterial = Arrays.concatenate(pad8(_s, _seedlen), entropy, additionalInput);
-
- _s = Utils.hash_df(_digest, seedMaterial, _seedlen);
-
- _reseedCounter = 0;
- }
-
- private byte[] xor(byte[] a, byte[] b)
- {
- if (b == null)
- {
- return a;
- }
-
- byte[] rv = new byte[a.length];
-
- for (int i = 0; i != rv.length; i++)
- {
- rv[i] = (byte)(a[i] ^ b[i]);
- }
-
- return rv;
- }
-
- // Note: works in place
- private byte[] pad8(byte[] s, int seedlen)
- {
- if (seedlen % 8 == 0)
- {
- return s;
- }
-
- int shift = 8 - (seedlen % 8);
- int carry = 0;
-
- for (int i = s.length - 1; i >= 0; i--)
- {
- int b = s[i] & 0xff;
- s[i] = (byte)((b << shift) | (carry >> (8 - shift)));
- carry = b;
- }
-
- return s;
- }
-
- private BigInteger getScalarMultipleXCoord(ECPoint p, BigInteger s)
- {
- return _fixedPointMultiplier.multiply(p, s).normalize().getAffineXCoord().toBigInteger();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/prng/drbg/HMacSP800DRBG.java b/core/src/main/java/org/bouncycastle/crypto/prng/drbg/HMacSP800DRBG.java
deleted file mode 100644
index f4ef2c45..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/prng/drbg/HMacSP800DRBG.java
+++ /dev/null
@@ -1,181 +0,0 @@
-package org.bouncycastle.crypto.prng.drbg;
-
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.prng.EntropySource;
-import org.bouncycastle.util.Arrays;
-
-/**
- * A SP800-90A HMAC DRBG.
- */
-public class HMacSP800DRBG
- implements SP80090DRBG
-{
- private final static long RESEED_MAX = 1L << (48 - 1);
- private final static int MAX_BITS_REQUEST = 1 << (19 - 1);
-
- private byte[] _K;
- private byte[] _V;
- private long _reseedCounter;
- private EntropySource _entropySource;
- private Mac _hMac;
-
- /**
- * Construct a SP800-90A Hash DRBG.
- * <p>
- * Minimum entropy requirement is the security strength requested.
- * </p>
- * @param hMac Hash MAC to base the DRBG on.
- * @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 HMacSP800DRBG(Mac hMac, int securityStrength, EntropySource entropySource, byte[] personalizationString, byte[] nonce)
- {
- if (securityStrength > Utils.getMaxSecurityStrength(hMac))
- {
- throw new IllegalArgumentException("Requested security strength is not supported by the derivation function");
- }
-
- if (entropySource.entropySize() < securityStrength)
- {
- throw new IllegalArgumentException("Not enough entropy for security strength required");
- }
-
- _entropySource = entropySource;
- _hMac = hMac;
-
- byte[] entropy = entropySource.getEntropy();
- byte[] seedMaterial = Arrays.concatenate(entropy, nonce, personalizationString);
-
- _K = new byte[hMac.getMacSize()];
- _V = new byte[_K.length];
- Arrays.fill(_V, (byte)1);
-
- hmac_DRBG_Update(seedMaterial);
-
- _reseedCounter = 1;
- }
-
- private void hmac_DRBG_Update(byte[] seedMaterial)
- {
- hmac_DRBG_Update_Func(seedMaterial, (byte)0x00);
- if (seedMaterial != null)
- {
- hmac_DRBG_Update_Func(seedMaterial, (byte)0x01);
- }
- }
-
- private void hmac_DRBG_Update_Func(byte[] seedMaterial, byte vValue)
- {
- _hMac.init(new KeyParameter(_K));
-
- _hMac.update(_V, 0, _V.length);
- _hMac.update(vValue);
-
- if (seedMaterial != null)
- {
- _hMac.update(seedMaterial, 0, seedMaterial.length);
- }
-
- _hMac.doFinal(_K, 0);
-
- _hMac.init(new KeyParameter(_K));
- _hMac.update(_V, 0, _V.length);
-
- _hMac.doFinal(_V, 0);
- }
-
- /**
- * Return the block size (in bits) of the DRBG.
- *
- * @return the number of bits produced on each round of the DRBG.
- */
- public int getBlockSize()
- {
- return _V.length * 8;
- }
-
- /**
- * Populate a passed in array with random data.
- *
- * @param output output array for generated bits.
- * @param additionalInput additional input to be added to the DRBG in this step.
- * @param predictionResistant true if a reseed should be forced, false otherwise.
- *
- * @return number of bits generated, -1 if a reseed required.
- */
- public int generate(byte[] output, byte[] additionalInput, boolean predictionResistant)
- {
- int numberOfBits = output.length * 8;
-
- if (numberOfBits > MAX_BITS_REQUEST)
- {
- throw new IllegalArgumentException("Number of bits per request limited to " + MAX_BITS_REQUEST);
- }
-
- if (_reseedCounter > RESEED_MAX)
- {
- return -1;
- }
-
- if (predictionResistant)
- {
- reseed(additionalInput);
- additionalInput = null;
- }
-
- // 2.
- if (additionalInput != null)
- {
- hmac_DRBG_Update(additionalInput);
- }
-
- // 3.
- byte[] rv = new byte[output.length];
-
- int m = output.length / _V.length;
-
- _hMac.init(new KeyParameter(_K));
-
- for (int i = 0; i < m; i++)
- {
- _hMac.update(_V, 0, _V.length);
- _hMac.doFinal(_V, 0);
-
- System.arraycopy(_V, 0, rv, i * _V.length, _V.length);
- }
-
- if (m * _V.length < rv.length)
- {
- _hMac.update(_V, 0, _V.length);
- _hMac.doFinal(_V, 0);
-
- System.arraycopy(_V, 0, rv, m * _V.length, rv.length - (m * _V.length));
- }
-
- hmac_DRBG_Update(additionalInput);
-
- _reseedCounter++;
-
- System.arraycopy(rv, 0, output, 0, output.length);
-
- return numberOfBits;
- }
-
- /**
- * Reseed the DRBG.
- *
- * @param additionalInput additional input to be added to the DRBG in this step.
- */
- public void reseed(byte[] additionalInput)
- {
- byte[] entropy = _entropySource.getEntropy();
- byte[] seedMaterial = Arrays.concatenate(entropy, additionalInput);
-
- hmac_DRBG_Update(seedMaterial);
-
- _reseedCounter = 1;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/prng/drbg/HashSP800DRBG.java b/core/src/main/java/org/bouncycastle/crypto/prng/drbg/HashSP800DRBG.java
deleted file mode 100644
index d6ab4f53..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/prng/drbg/HashSP800DRBG.java
+++ /dev/null
@@ -1,284 +0,0 @@
-package org.bouncycastle.crypto.prng.drbg;
-
-import java.util.Hashtable;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.prng.EntropySource;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Integers;
-
-/**
- * A SP800-90A Hash DRBG.
- */
-public class HashSP800DRBG
- implements SP80090DRBG
-{
- private final static byte[] ONE = { 0x01 };
-
- private final static long RESEED_MAX = 1L << (48 - 1);
- private final static int MAX_BITS_REQUEST = 1 << (19 - 1);
-
- private final static Hashtable seedlens = new Hashtable();
-
- static
- {
- seedlens.put("SHA-1", Integers.valueOf(440));
- seedlens.put("SHA-224", Integers.valueOf(440));
- seedlens.put("SHA-256", Integers.valueOf(440));
- seedlens.put("SHA-512/256", Integers.valueOf(440));
- seedlens.put("SHA-512/224", Integers.valueOf(440));
- seedlens.put("SHA-384", Integers.valueOf(888));
- seedlens.put("SHA-512", Integers.valueOf(888));
- }
-
- private Digest _digest;
- private byte[] _V;
- private byte[] _C;
- private long _reseedCounter;
- private EntropySource _entropySource;
- private int _securityStrength;
- private int _seedLength;
-
- /**
- * Construct a SP800-90A Hash DRBG.
- * <p>
- * Minimum entropy requirement is the security strength requested.
- * </p>
- * @param digest source digest to use for 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 HashSP800DRBG(Digest digest, int securityStrength, EntropySource entropySource, byte[] personalizationString, byte[] nonce)
- {
- if (securityStrength > Utils.getMaxSecurityStrength(digest))
- {
- throw new IllegalArgumentException("Requested security strength is not supported by the derivation function");
- }
-
- if (entropySource.entropySize() < securityStrength)
- {
- throw new IllegalArgumentException("Not enough entropy for security strength required");
- }
-
- _digest = digest;
- _entropySource = entropySource;
- _securityStrength = securityStrength;
- _seedLength = ((Integer)seedlens.get(digest.getAlgorithmName())).intValue();
-
- // 1. seed_material = entropy_input || nonce || personalization_string.
- // 2. seed = Hash_df (seed_material, seedlen).
- // 3. V = seed.
- // 4. C = Hash_df ((0x00 || V), seedlen). Comment: Preceed V with a byte
- // of zeros.
- // 5. reseed_counter = 1.
- // 6. Return V, C, and reseed_counter as the initial_working_state
-
- byte[] entropy = entropySource.getEntropy();
- byte[] seedMaterial = Arrays.concatenate(entropy, nonce, personalizationString);
- byte[] seed = Utils.hash_df(_digest, seedMaterial, _seedLength);
-
- _V = seed;
- byte[] subV = new byte[_V.length + 1];
- System.arraycopy(_V, 0, subV, 1, _V.length);
- _C = Utils.hash_df(_digest, subV, _seedLength);
-
- _reseedCounter = 1;
- }
-
- /**
- * Return the block size (in bits) of the DRBG.
- *
- * @return the number of bits produced on each internal round of the DRBG.
- */
- public int getBlockSize()
- {
- return _digest.getDigestSize() * 8;
- }
-
- /**
- * Populate a passed in array with random data.
- *
- * @param output output array for generated bits.
- * @param additionalInput additional input to be added to the DRBG in this step.
- * @param predictionResistant true if a reseed should be forced, false otherwise.
- *
- * @return number of bits generated, -1 if a reseed required.
- */
- public int generate(byte[] output, byte[] additionalInput, boolean predictionResistant)
- {
- // 1. If reseed_counter > reseed_interval, then return an indication that a
- // reseed is required.
- // 2. If (additional_input != Null), then do
- // 2.1 w = Hash (0x02 || V || additional_input).
- // 2.2 V = (V + w) mod 2^seedlen
- // .
- // 3. (returned_bits) = Hashgen (requested_number_of_bits, V).
- // 4. H = Hash (0x03 || V).
- // 5. V = (V + H + C + reseed_counter) mod 2^seedlen
- // .
- // 6. reseed_counter = reseed_counter + 1.
- // 7. Return SUCCESS, returned_bits, and the new values of V, C, and
- // reseed_counter for the new_working_state.
- int numberOfBits = output.length*8;
-
- if (numberOfBits > MAX_BITS_REQUEST)
- {
- throw new IllegalArgumentException("Number of bits per request limited to " + MAX_BITS_REQUEST);
- }
-
- if (_reseedCounter > RESEED_MAX)
- {
- return -1;
- }
-
- if (predictionResistant)
- {
- reseed(additionalInput);
- additionalInput = null;
- }
-
- // 2.
- if (additionalInput != null)
- {
- byte[] newInput = new byte[1 + _V.length + additionalInput.length];
- newInput[0] = 0x02;
- System.arraycopy(_V, 0, newInput, 1, _V.length);
- // TODO: inOff / inLength
- System.arraycopy(additionalInput, 0, newInput, 1 + _V.length, additionalInput.length);
- byte[] w = hash(newInput);
-
- addTo(_V, w);
- }
-
- // 3.
- byte[] rv = hashgen(_V, numberOfBits);
-
- // 4.
- byte[] subH = new byte[_V.length + 1];
- System.arraycopy(_V, 0, subH, 1, _V.length);
- subH[0] = 0x03;
-
- byte[] H = hash(subH);
-
- // 5.
- addTo(_V, H);
- addTo(_V, _C);
- byte[] c = new byte[4];
- c[0] = (byte)(_reseedCounter >> 24);
- c[1] = (byte)(_reseedCounter >> 16);
- c[2] = (byte)(_reseedCounter >> 8);
- c[3] = (byte)_reseedCounter;
-
- addTo(_V, c);
-
- _reseedCounter++;
-
- System.arraycopy(rv, 0, output, 0, output.length);
-
- return numberOfBits;
- }
-
- // this will always add the shorter length byte array mathematically to the
- // longer length byte array.
- // be careful....
- private void addTo(byte[] longer, byte[] shorter)
- {
- int carry = 0;
- for (int i=1;i <= shorter.length; i++) // warning
- {
- int res = (longer[longer.length-i] & 0xff) + (shorter[shorter.length-i] & 0xff) + carry;
- carry = (res > 0xff) ? 1 : 0;
- longer[longer.length-i] = (byte)res;
- }
-
- for (int i=shorter.length+1;i <= longer.length; i++) // warning
- {
- int res = (longer[longer.length-i] & 0xff) + carry;
- carry = (res > 0xff) ? 1 : 0;
- longer[longer.length-i] = (byte)res;
- }
- }
-
- /**
- * Reseed the DRBG.
- *
- * @param additionalInput additional input to be added to the DRBG in this step.
- */
- public void reseed(byte[] additionalInput)
- {
- // 1. seed_material = 0x01 || V || entropy_input || additional_input.
- //
- // 2. seed = Hash_df (seed_material, seedlen).
- //
- // 3. V = seed.
- //
- // 4. C = Hash_df ((0x00 || V), seedlen).
- //
- // 5. reseed_counter = 1.
- //
- // 6. Return V, C, and reseed_counter for the new_working_state.
- //
- // Comment: Precede with a byte of all zeros.
- byte[] entropy = _entropySource.getEntropy();
- byte[] seedMaterial = Arrays.concatenate(ONE, _V, entropy, additionalInput);
- byte[] seed = Utils.hash_df(_digest, seedMaterial, _seedLength);
-
- _V = seed;
- byte[] subV = new byte[_V.length + 1];
- subV[0] = 0x00;
- System.arraycopy(_V, 0, subV, 1, _V.length);
- _C = Utils.hash_df(_digest, subV, _seedLength);
-
- _reseedCounter = 1;
- }
-
- private byte[] hash(byte[] input)
- {
- byte[] hash = new byte[_digest.getDigestSize()];
- doHash(input, hash);
- return hash;
- }
-
- private void doHash(byte[] input, byte[] output)
- {
- _digest.update(input, 0, input.length);
- _digest.doFinal(output, 0);
- }
-
- // 1. m = [requested_number_of_bits / outlen]
- // 2. data = V.
- // 3. W = the Null string.
- // 4. For i = 1 to m
- // 4.1 wi = Hash (data).
- // 4.2 W = W || wi.
- // 4.3 data = (data + 1) mod 2^seedlen
- // .
- // 5. returned_bits = Leftmost (requested_no_of_bits) bits of W.
- private byte[] hashgen(byte[] input, int lengthInBits)
- {
- int digestSize = _digest.getDigestSize();
- int m = (lengthInBits / 8) / digestSize;
-
- byte[] data = new byte[input.length];
- System.arraycopy(input, 0, data, 0, input.length);
-
- byte[] W = new byte[lengthInBits / 8];
-
- byte[] dig = new byte[_digest.getDigestSize()];
- for (int i = 0; i <= m; i++)
- {
- doHash(data, dig);
-
- int bytesToCopy = ((W.length - i * dig.length) > dig.length)
- ? dig.length
- : (W.length - i * dig.length);
- System.arraycopy(dig, 0, W, i * dig.length, bytesToCopy);
-
- addTo(data, ONE);
- }
-
- return W;
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/crypto/prng/drbg/SP80090DRBG.java b/core/src/main/java/org/bouncycastle/crypto/prng/drbg/SP80090DRBG.java
deleted file mode 100644
index 7a919f31..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/prng/drbg/SP80090DRBG.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.bouncycastle.crypto.prng.drbg;
-
-/**
- * Interface to SP800-90A deterministic random bit generators.
- */
-public interface SP80090DRBG
-{
- /**
- * Return the block size of the DRBG.
- *
- * @return the block size (in bits) produced by each round of the DRBG.
- */
- int getBlockSize();
-
- /**
- * Populate a passed in array with random data.
- *
- * @param output output array for generated bits.
- * @param additionalInput additional input to be added to the DRBG in this step.
- * @param predictionResistant true if a reseed should be forced, false otherwise.
- *
- * @return number of bits generated, -1 if a reseed required.
- */
- int generate(byte[] output, byte[] additionalInput, boolean predictionResistant);
-
- /**
- * Reseed the DRBG.
- *
- * @param additionalInput additional input to be added to the DRBG in this step.
- */
- void reseed(byte[] additionalInput);
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/prng/drbg/Utils.java b/core/src/main/java/org/bouncycastle/crypto/prng/drbg/Utils.java
deleted file mode 100644
index f7a41176..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/prng/drbg/Utils.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package org.bouncycastle.crypto.prng.drbg;
-
-import java.util.Hashtable;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.util.Integers;
-
-class Utils
-{
- static final Hashtable maxSecurityStrengths = new Hashtable();
-
- static
- {
- maxSecurityStrengths.put("SHA-1", Integers.valueOf(128));
-
- maxSecurityStrengths.put("SHA-224", Integers.valueOf(192));
- maxSecurityStrengths.put("SHA-256", Integers.valueOf(256));
- maxSecurityStrengths.put("SHA-384", Integers.valueOf(256));
- maxSecurityStrengths.put("SHA-512", Integers.valueOf(256));
-
- maxSecurityStrengths.put("SHA-512/224", Integers.valueOf(192));
- maxSecurityStrengths.put("SHA-512/256", Integers.valueOf(256));
- }
-
- static int getMaxSecurityStrength(Digest d)
- {
- return ((Integer)maxSecurityStrengths.get(d.getAlgorithmName())).intValue();
- }
-
- static int getMaxSecurityStrength(Mac m)
- {
- String name = m.getAlgorithmName();
-
- return ((Integer)maxSecurityStrengths.get(name.substring(0, name.indexOf("/")))).intValue();
- }
-
- /**
- * Used by both Dual EC and Hash.
- */
- static byte[] hash_df(Digest digest, byte[] seedMaterial, int seedLength)
- {
- // 1. temp = the Null string.
- // 2. .
- // 3. counter = an 8-bit binary value representing the integer "1".
- // 4. For i = 1 to len do
- // Comment : In step 4.1, no_of_bits_to_return
- // is used as a 32-bit string.
- // 4.1 temp = temp || Hash (counter || no_of_bits_to_return ||
- // input_string).
- // 4.2 counter = counter + 1.
- // 5. requested_bits = Leftmost (no_of_bits_to_return) of temp.
- // 6. Return SUCCESS and requested_bits.
- byte[] temp = new byte[(seedLength + 7) / 8];
-
- int len = temp.length / digest.getDigestSize();
- int counter = 1;
-
- byte[] dig = new byte[digest.getDigestSize()];
-
- for (int i = 0; i <= len; i++)
- {
- digest.update((byte)counter);
-
- digest.update((byte)(seedLength >> 24));
- digest.update((byte)(seedLength >> 16));
- digest.update((byte)(seedLength >> 8));
- digest.update((byte)seedLength);
-
- digest.update(seedMaterial, 0, seedMaterial.length);
-
- digest.doFinal(dig, 0);
-
- int bytesToCopy = ((temp.length - i * dig.length) > dig.length)
- ? dig.length
- : (temp.length - i * dig.length);
- System.arraycopy(dig, 0, temp, i * dig.length, bytesToCopy);
-
- counter++;
- }
-
- // do a left shift to get rid of excess bits.
- if (seedLength % 8 != 0)
- {
- int shift = 8 - (seedLength % 8);
- int carry = 0;
-
- for (int i = 0; i != temp.length; i++)
- {
- int b = temp[i] & 0xff;
- temp[i] = (byte)((b >>> shift) | (carry << (8 - shift)));
- carry = b;
- }
- }
-
- return temp;
- }
-
- static boolean isTooLarge(byte[] bytes, int maxBytes)
- {
- return bytes != null && bytes.length > maxBytes;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/signers/DSADigestSigner.java b/core/src/main/java/org/bouncycastle/crypto/signers/DSADigestSigner.java
deleted file mode 100644
index 684eb9c0..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/signers/DSADigestSigner.java
+++ /dev/null
@@ -1,163 +0,0 @@
-package org.bouncycastle.crypto.signers;
-
-import java.io.IOException;
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Encoding;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DSA;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.Signer;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-
-public class DSADigestSigner
- implements Signer
-{
- private final Digest digest;
- private final DSA dsaSigner;
- private boolean forSigning;
-
- public DSADigestSigner(
- DSA signer,
- Digest digest)
- {
- this.digest = digest;
- this.dsaSigner = signer;
- }
-
- public void init(
- boolean forSigning,
- CipherParameters parameters)
- {
- this.forSigning = forSigning;
-
- AsymmetricKeyParameter k;
-
- if (parameters instanceof ParametersWithRandom)
- {
- k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).getParameters();
- }
- else
- {
- k = (AsymmetricKeyParameter)parameters;
- }
-
- if (forSigning && !k.isPrivate())
- {
- throw new IllegalArgumentException("Signing Requires Private Key.");
- }
-
- if (!forSigning && k.isPrivate())
- {
- throw new IllegalArgumentException("Verification Requires Public Key.");
- }
-
- reset();
-
- dsaSigner.init(forSigning, parameters);
- }
-
- /**
- * update the internal digest with the byte b
- */
- public void update(
- byte input)
- {
- digest.update(input);
- }
-
- /**
- * update the internal digest with the byte array in
- */
- public void update(
- byte[] input,
- int inOff,
- int length)
- {
- digest.update(input, inOff, length);
- }
-
- /**
- * Generate a signature for the message we've been loaded with using
- * the key we were initialised with.
- */
- public byte[] generateSignature()
- {
- if (!forSigning)
- {
- throw new IllegalStateException("DSADigestSigner not initialised for signature generation.");
- }
-
- byte[] hash = new byte[digest.getDigestSize()];
- digest.doFinal(hash, 0);
-
- BigInteger[] sig = dsaSigner.generateSignature(hash);
-
- try
- {
- return derEncode(sig[0], sig[1]);
- }
- catch (IOException e)
- {
- throw new IllegalStateException("unable to encode signature");
- }
- }
-
- public boolean verifySignature(
- byte[] signature)
- {
- if (forSigning)
- {
- throw new IllegalStateException("DSADigestSigner not initialised for verification");
- }
-
- byte[] hash = new byte[digest.getDigestSize()];
- digest.doFinal(hash, 0);
-
- try
- {
- BigInteger[] sig = derDecode(signature);
- return dsaSigner.verifySignature(hash, sig[0], sig[1]);
- }
- catch (IOException e)
- {
- return false;
- }
- }
-
- public void reset()
- {
- digest.reset();
- }
-
- private byte[] derEncode(
- BigInteger r,
- BigInteger s)
- throws IOException
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- v.add(new ASN1Integer(r));
- v.add(new ASN1Integer(s));
-
- return new DERSequence(v).getEncoded(ASN1Encoding.DER);
- }
-
- private BigInteger[] derDecode(
- byte[] encoding)
- throws IOException
- {
- ASN1Sequence s = (ASN1Sequence)ASN1Primitive.fromByteArray(encoding);
-
- return new BigInteger[]
- {
- ((ASN1Integer)s.getObjectAt(0)).getValue(),
- ((ASN1Integer)s.getObjectAt(1)).getValue()
- };
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/signers/DSAKCalculator.java b/core/src/main/java/org/bouncycastle/crypto/signers/DSAKCalculator.java
deleted file mode 100644
index fced06ea..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/signers/DSAKCalculator.java
+++ /dev/null
@@ -1,41 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java b/core/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java
deleted file mode 100644
index f3614f39..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java
+++ /dev/null
@@ -1,168 +0,0 @@
-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;
-import org.bouncycastle.crypto.params.DSAParameters;
-import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
-import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-
-/**
- * The Digital Signature Algorithm - as described in "Handbook of Applied
- * Cryptography", pages 452 - 453.
- */
-public class DSASigner
- implements DSA
-{
- private final DSAKCalculator kCalculator;
-
- 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,
- CipherParameters param)
- {
- SecureRandom providedRandom = null;
-
- if (forSigning)
- {
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- this.key = (DSAPrivateKeyParameters)rParam.getParameters();
- providedRandom = rParam.getRandom();
- }
- else
- {
- this.key = (DSAPrivateKeyParameters)param;
- }
- }
- else
- {
- this.key = (DSAPublicKeyParameters)param;
- }
-
- this.random = initSecureRandom(forSigning && !kCalculator.isDeterministic(), providedRandom);
- }
-
- /**
- * generate a signature for the given message using the key we were
- * initialised with. For conventional DSA the message should be a SHA-1
- * hash of the message of interest.
- *
- * @param message the message that will be verified later.
- */
- public BigInteger[] generateSignature(
- byte[] message)
- {
- DSAParameters params = key.getParameters();
- BigInteger m = calculateE(params.getQ(), message);
-
- if (kCalculator.isDeterministic())
- {
- kCalculator.init(params.getQ(), ((DSAPrivateKeyParameters)key).getX(), message);
- }
- else
- {
- kCalculator.init(params.getQ(), random);
- }
-
- BigInteger k = kCalculator.nextK();
-
- BigInteger r = params.getG().modPow(k, params.getP()).mod(params.getQ());
-
- k = k.modInverse(params.getQ()).multiply(
- m.add(((DSAPrivateKeyParameters)key).getX().multiply(r)));
-
- BigInteger s = k.mod(params.getQ());
-
- BigInteger[] res = new BigInteger[2];
-
- res[0] = r;
- res[1] = s;
-
- return res;
- }
-
- /**
- * return true if the value r and s represent a DSA signature for
- * the passed in message for standard DSA the message should be a
- * SHA-1 hash of the real message to be verified.
- */
- public boolean verifySignature(
- byte[] message,
- BigInteger r,
- BigInteger s)
- {
- DSAParameters params = key.getParameters();
- BigInteger m = calculateE(params.getQ(), message);
- BigInteger zero = BigInteger.valueOf(0);
-
- if (zero.compareTo(r) >= 0 || params.getQ().compareTo(r) <= 0)
- {
- return false;
- }
-
- if (zero.compareTo(s) >= 0 || params.getQ().compareTo(s) <= 0)
- {
- return false;
- }
-
- BigInteger w = s.modInverse(params.getQ());
-
- BigInteger u1 = m.multiply(w).mod(params.getQ());
- BigInteger u2 = r.multiply(w).mod(params.getQ());
-
- u1 = params.getG().modPow(u1, params.getP());
- u2 = ((DSAPublicKeyParameters)key).getY().modPow(u2, params.getP());
-
- BigInteger v = u1.multiply(u2).mod(params.getP()).mod(params.getQ());
-
- return v.equals(r);
- }
-
- private BigInteger calculateE(BigInteger n, byte[] message)
- {
- if (n.bitLength() >= message.length * 8)
- {
- return new BigInteger(1, message);
- }
- else
- {
- byte[] trunc = new byte[n.bitLength() / 8];
-
- System.arraycopy(message, 0, trunc, 0, trunc.length);
-
- return new BigInteger(1, trunc);
- }
- }
-
- protected SecureRandom initSecureRandom(boolean needed, SecureRandom provided)
- {
- return !needed ? null : (provided != null) ? provided : new SecureRandom();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/signers/DSTU4145Signer.java b/core/src/main/java/org/bouncycastle/crypto/signers/DSTU4145Signer.java
deleted file mode 100644
index bceb8220..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/signers/DSTU4145Signer.java
+++ /dev/null
@@ -1,170 +0,0 @@
-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.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECKeyParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.math.ec.ECAlgorithms;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECMultiplier;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.ec.FixedPointCombMultiplier;
-import org.bouncycastle.util.Arrays;
-
-/**
- * DSTU 4145-2002
- * <p>
- * National Ukrainian standard of digital signature based on elliptic curves (DSTU 4145-2002).
- * </p>
- */
-public class DSTU4145Signer
- implements DSA
-{
- private static final BigInteger ONE = BigInteger.valueOf(1);
-
- private ECKeyParameters key;
- private SecureRandom random;
-
- public void init(boolean forSigning, CipherParameters param)
- {
- if (forSigning)
- {
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- this.random = rParam.getRandom();
- param = rParam.getParameters();
- }
- else
- {
- this.random = new SecureRandom();
- }
-
- this.key = (ECPrivateKeyParameters)param;
- }
- else
- {
- this.key = (ECPublicKeyParameters)param;
- }
-
- }
-
- public BigInteger[] generateSignature(byte[] message)
- {
- ECDomainParameters ec = key.getParameters();
-
- ECCurve curve = ec.getCurve();
-
- ECFieldElement h = hash2FieldElement(curve, message);
- if (h.isZero())
- {
- h = curve.fromBigInteger(ONE);
- }
-
- BigInteger n = ec.getN();
- BigInteger e, r, s;
- ECFieldElement Fe, y;
-
- BigInteger d = ((ECPrivateKeyParameters)key).getD();
-
- ECMultiplier basePointMultiplier = createBasePointMultiplier();
-
- do
- {
- do
- {
- do
- {
- e = generateRandomInteger(n, random);
- Fe = basePointMultiplier.multiply(ec.getG(), e).normalize().getAffineXCoord();
- }
- while (Fe.isZero());
-
- y = h.multiply(Fe);
- r = fieldElement2Integer(n, y);
- }
- while (r.signum() == 0);
-
- s = r.multiply(d).add(e).mod(n);
- }
- while (s.signum() == 0);
-
- return new BigInteger[]{r, s};
- }
-
- public boolean verifySignature(byte[] message, BigInteger r, BigInteger s)
- {
- if (r.signum() <= 0 || s.signum() <= 0)
- {
- return false;
- }
-
- ECDomainParameters parameters = key.getParameters();
-
- BigInteger n = parameters.getN();
- if (r.compareTo(n) >= 0 || s.compareTo(n) >= 0)
- {
- return false;
- }
-
- ECCurve curve = parameters.getCurve();
-
- ECFieldElement h = hash2FieldElement(curve, message);
- if (h.isZero())
- {
- h = curve.fromBigInteger(ONE);
- }
-
- ECPoint R = ECAlgorithms.sumOfTwoMultiplies(parameters.getG(), s, ((ECPublicKeyParameters)key).getQ(), r).normalize();
-
- // components must be bogus.
- if (R.isInfinity())
- {
- return false;
- }
-
- ECFieldElement y = h.multiply(R.getAffineXCoord());
- return fieldElement2Integer(n, y).compareTo(r) == 0;
- }
-
- protected ECMultiplier createBasePointMultiplier()
- {
- return new FixedPointCombMultiplier();
- }
-
- /**
- * Generates random integer such, than its bit length is less than that of n
- */
- private static BigInteger generateRandomInteger(BigInteger n, SecureRandom random)
- {
- return new BigInteger(n.bitLength() - 1, random);
- }
-
- private static ECFieldElement hash2FieldElement(ECCurve curve, byte[] hash)
- {
- byte[] data = Arrays.reverse(hash);
- return curve.fromBigInteger(truncate(new BigInteger(1, data), curve.getFieldSize()));
- }
-
- private static BigInteger fieldElement2Integer(BigInteger n, ECFieldElement fe)
- {
- return truncate(fe.toBigInteger(), n.bitLength() - 1);
- }
-
- private static BigInteger truncate(BigInteger x, int bitLength)
- {
- if (x.bitLength() > bitLength)
- {
- x = x.mod(ONE.shiftLeft(bitLength));
- }
- return x;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java b/core/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java
deleted file mode 100644
index 5fce1121..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java
+++ /dev/null
@@ -1,197 +0,0 @@
-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.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECKeyParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.math.ec.ECAlgorithms;
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECMultiplier;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.ec.FixedPointCombMultiplier;
-
-/**
- * EC-DSA as described in X9.62
- */
-public class ECDSASigner
- implements ECConstants, DSA
-{
- private final DSAKCalculator kCalculator;
-
- 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,
- CipherParameters param)
- {
- SecureRandom providedRandom = null;
-
- if (forSigning)
- {
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- this.key = (ECPrivateKeyParameters)rParam.getParameters();
- providedRandom = rParam.getRandom();
- }
- else
- {
- this.key = (ECPrivateKeyParameters)param;
- }
- }
- else
- {
- this.key = (ECPublicKeyParameters)param;
- }
-
- this.random = initSecureRandom(forSigning && !kCalculator.isDeterministic(), providedRandom);
- }
-
- // 5.3 pg 28
- /**
- * generate a signature for the given message using the key we were
- * initialised with. For conventional DSA the message should be a SHA-1
- * hash of the message of interest.
- *
- * @param message the message that will be verified later.
- */
- public BigInteger[] generateSignature(
- byte[] message)
- {
- ECDomainParameters ec = key.getParameters();
- BigInteger n = ec.getN();
- BigInteger e = calculateE(n, message);
- BigInteger d = ((ECPrivateKeyParameters)key).getD();
-
- if (kCalculator.isDeterministic())
- {
- kCalculator.init(n, d, message);
- }
- else
- {
- kCalculator.init(n, random);
- }
-
- BigInteger r, s;
-
- ECMultiplier basePointMultiplier = createBasePointMultiplier();
-
- // 5.3.2
- do // generate s
- {
- BigInteger k;
- do // generate r
- {
- k = kCalculator.nextK();
-
- ECPoint p = basePointMultiplier.multiply(ec.getG(), k).normalize();
-
- // 5.3.3
- r = p.getAffineXCoord().toBigInteger().mod(n);
- }
- while (r.equals(ZERO));
-
- s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n);
- }
- while (s.equals(ZERO));
-
- return new BigInteger[]{ r, s };
- }
-
- // 5.4 pg 29
- /**
- * return true if the value r and s represent a DSA signature for
- * the passed in message (for standard DSA the message should be
- * a SHA-1 hash of the real message to be verified).
- */
- public boolean verifySignature(
- byte[] message,
- BigInteger r,
- BigInteger s)
- {
- ECDomainParameters ec = key.getParameters();
- BigInteger n = ec.getN();
- BigInteger e = calculateE(n, message);
-
- // r in the range [1,n-1]
- if (r.compareTo(ONE) < 0 || r.compareTo(n) >= 0)
- {
- return false;
- }
-
- // s in the range [1,n-1]
- if (s.compareTo(ONE) < 0 || s.compareTo(n) >= 0)
- {
- return false;
- }
-
- BigInteger c = s.modInverse(n);
-
- BigInteger u1 = e.multiply(c).mod(n);
- BigInteger u2 = r.multiply(c).mod(n);
-
- ECPoint G = ec.getG();
- ECPoint Q = ((ECPublicKeyParameters)key).getQ();
-
- ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, u1, Q, u2).normalize();
-
- // components must be bogus.
- if (point.isInfinity())
- {
- return false;
- }
-
- BigInteger v = point.getAffineXCoord().toBigInteger().mod(n);
-
- return v.equals(r);
- }
-
- protected BigInteger calculateE(BigInteger n, byte[] message)
- {
- int log2n = n.bitLength();
- int messageBitLength = message.length * 8;
-
- BigInteger e = new BigInteger(1, message);
- if (log2n < messageBitLength)
- {
- e = e.shiftRight(messageBitLength - log2n);
- }
- return e;
- }
-
- protected ECMultiplier createBasePointMultiplier()
- {
- return new FixedPointCombMultiplier();
- }
-
- protected SecureRandom initSecureRandom(boolean needed, SecureRandom provided)
- {
- return !needed ? null : (provided != null) ? provided : new SecureRandom();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/signers/ECGOST3410Signer.java b/core/src/main/java/org/bouncycastle/crypto/signers/ECGOST3410Signer.java
deleted file mode 100644
index 0ef88762..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/signers/ECGOST3410Signer.java
+++ /dev/null
@@ -1,160 +0,0 @@
-package org.bouncycastle.crypto.signers;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DSA;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECKeyParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.math.ec.ECAlgorithms;
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECMultiplier;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.ec.FixedPointCombMultiplier;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-/**
- * GOST R 34.10-2001 Signature Algorithm
- */
-public class ECGOST3410Signer
- implements DSA
-{
- ECKeyParameters key;
-
- SecureRandom random;
-
- public void init(
- boolean forSigning,
- CipherParameters param)
- {
- if (forSigning)
- {
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- this.random = rParam.getRandom();
- this.key = (ECPrivateKeyParameters)rParam.getParameters();
- }
- else
- {
- this.random = new SecureRandom();
- this.key = (ECPrivateKeyParameters)param;
- }
- }
- else
- {
- this.key = (ECPublicKeyParameters)param;
- }
- }
-
- /**
- * generate a signature for the given message using the key we were
- * initialised with. For conventional GOST3410 the message should be a GOST3411
- * hash of the message of interest.
- *
- * @param message the message that will be verified later.
- */
- public BigInteger[] generateSignature(
- byte[] message)
- {
- byte[] mRev = new byte[message.length]; // conversion is little-endian
- for (int i = 0; i != mRev.length; i++)
- {
- mRev[i] = message[mRev.length - 1 - i];
- }
-
- BigInteger e = new BigInteger(1, mRev);
-
- ECDomainParameters ec = key.getParameters();
- BigInteger n = ec.getN();
- BigInteger d = ((ECPrivateKeyParameters)key).getD();
-
- BigInteger r, s;
-
- ECMultiplier basePointMultiplier = createBasePointMultiplier();
-
- do // generate s
- {
- BigInteger k;
- do // generate r
- {
- do
- {
- k = new BigInteger(n.bitLength(), random);
- }
- while (k.equals(ECConstants.ZERO));
-
- ECPoint p = basePointMultiplier.multiply(ec.getG(), k).normalize();
-
- r = p.getAffineXCoord().toBigInteger().mod(n);
- }
- while (r.equals(ECConstants.ZERO));
-
- s = (k.multiply(e)).add(d.multiply(r)).mod(n);
- }
- while (s.equals(ECConstants.ZERO));
-
- return new BigInteger[]{ r, s };
- }
-
- /**
- * return true if the value r and s represent a GOST3410 signature for
- * the passed in message (for standard GOST3410 the message should be
- * a GOST3411 hash of the real message to be verified).
- */
- public boolean verifySignature(
- byte[] message,
- BigInteger r,
- BigInteger s)
- {
- byte[] mRev = new byte[message.length]; // conversion is little-endian
- for (int i = 0; i != mRev.length; i++)
- {
- mRev[i] = message[mRev.length - 1 - i];
- }
-
- BigInteger e = new BigInteger(1, mRev);
- BigInteger n = key.getParameters().getN();
-
- // r in the range [1,n-1]
- if (r.compareTo(ECConstants.ONE) < 0 || r.compareTo(n) >= 0)
- {
- return false;
- }
-
- // s in the range [1,n-1]
- if (s.compareTo(ECConstants.ONE) < 0 || s.compareTo(n) >= 0)
- {
- return false;
- }
-
- BigInteger v = e.modInverse(n);
-
- BigInteger z1 = s.multiply(v).mod(n);
- BigInteger z2 = (n.subtract(r)).multiply(v).mod(n);
-
- ECPoint G = key.getParameters().getG(); // P
- ECPoint Q = ((ECPublicKeyParameters)key).getQ();
-
- ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, z1, Q, z2).normalize();
-
- // components must be bogus.
- if (point.isInfinity())
- {
- return false;
- }
-
- BigInteger R = point.getAffineXCoord().toBigInteger().mod(n);
-
- return R.equals(r);
- }
-
- protected ECMultiplier createBasePointMultiplier()
- {
- return new FixedPointCombMultiplier();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/signers/ECNRSigner.java b/core/src/main/java/org/bouncycastle/crypto/signers/ECNRSigner.java
deleted file mode 100644
index 3e839163..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/signers/ECNRSigner.java
+++ /dev/null
@@ -1,188 +0,0 @@
-package org.bouncycastle.crypto.signers;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DSA;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
-import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
-import org.bouncycastle.crypto.params.ECKeyParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.math.ec.ECAlgorithms;
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECPoint;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-/**
- * EC-NR as described in IEEE 1363-2000
- */
-public class ECNRSigner
- implements DSA
-{
- private boolean forSigning;
- private ECKeyParameters key;
- private SecureRandom random;
-
- public void init(
- boolean forSigning,
- CipherParameters param)
- {
- this.forSigning = forSigning;
-
- if (forSigning)
- {
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- this.random = rParam.getRandom();
- this.key = (ECPrivateKeyParameters)rParam.getParameters();
- }
- else
- {
- this.random = new SecureRandom();
- this.key = (ECPrivateKeyParameters)param;
- }
- }
- else
- {
- this.key = (ECPublicKeyParameters)param;
- }
- }
-
- // Section 7.2.5 ECSP-NR, pg 34
- /**
- * generate a signature for the given message using the key we were
- * initialised with. Generally, the order of the curve should be at
- * least as long as the hash of the message of interest, and with
- * ECNR it *must* be at least as long.
- *
- * @param digest the digest to be signed.
- * @exception DataLengthException if the digest is longer than the key allows
- */
- public BigInteger[] generateSignature(
- byte[] digest)
- {
- if (! this.forSigning)
- {
- throw new IllegalStateException("not initialised for signing");
- }
-
- BigInteger n = ((ECPrivateKeyParameters)this.key).getParameters().getN();
- int nBitLength = n.bitLength();
-
- BigInteger e = new BigInteger(1, digest);
- int eBitLength = e.bitLength();
-
- ECPrivateKeyParameters privKey = (ECPrivateKeyParameters)key;
-
- if (eBitLength > nBitLength)
- {
- throw new DataLengthException("input too large for ECNR key.");
- }
-
- BigInteger r = null;
- BigInteger s = null;
-
- AsymmetricCipherKeyPair tempPair;
- do // generate r
- {
- // generate another, but very temporary, key pair using
- // the same EC parameters
- ECKeyPairGenerator keyGen = new ECKeyPairGenerator();
-
- keyGen.init(new ECKeyGenerationParameters(privKey.getParameters(), this.random));
-
- tempPair = keyGen.generateKeyPair();
-
- // BigInteger Vx = tempPair.getPublic().getW().getAffineX();
- ECPublicKeyParameters V = (ECPublicKeyParameters)tempPair.getPublic(); // get temp's public key
- BigInteger Vx = V.getQ().getAffineXCoord().toBigInteger(); // get the point's x coordinate
-
- r = Vx.add(e).mod(n);
- }
- while (r.equals(ECConstants.ZERO));
-
- // generate s
- BigInteger x = privKey.getD(); // private key value
- BigInteger u = ((ECPrivateKeyParameters)tempPair.getPrivate()).getD(); // temp's private key value
- s = u.subtract(r.multiply(x)).mod(n);
-
- BigInteger[] res = new BigInteger[2];
- res[0] = r;
- res[1] = s;
-
- return res;
- }
-
- // Section 7.2.6 ECVP-NR, pg 35
- /**
- * return true if the value r and s represent a signature for the
- * message passed in. Generally, the order of the curve should be at
- * least as long as the hash of the message of interest, and with
- * ECNR, it *must* be at least as long. But just in case the signer
- * applied mod(n) to the longer digest, this implementation will
- * apply mod(n) during verification.
- *
- * @param digest the digest to be verified.
- * @param r the r value of the signature.
- * @param s the s value of the signature.
- * @exception DataLengthException if the digest is longer than the key allows
- */
- public boolean verifySignature(
- byte[] digest,
- BigInteger r,
- BigInteger s)
- {
- if (this.forSigning)
- {
- throw new IllegalStateException("not initialised for verifying");
- }
-
- ECPublicKeyParameters pubKey = (ECPublicKeyParameters)key;
- BigInteger n = pubKey.getParameters().getN();
- int nBitLength = n.bitLength();
-
- BigInteger e = new BigInteger(1, digest);
- int eBitLength = e.bitLength();
-
- if (eBitLength > nBitLength)
- {
- throw new DataLengthException("input too large for ECNR key.");
- }
-
- // r in the range [1,n-1]
- if (r.compareTo(ECConstants.ONE) < 0 || r.compareTo(n) >= 0)
- {
- return false;
- }
-
- // s in the range [0,n-1] NB: ECNR spec says 0
- if (s.compareTo(ECConstants.ZERO) < 0 || s.compareTo(n) >= 0)
- {
- return false;
- }
-
- // compute P = sG + rW
-
- ECPoint G = pubKey.getParameters().getG();
- ECPoint W = pubKey.getQ();
- // calculate P using Bouncy math
- ECPoint P = ECAlgorithms.sumOfTwoMultiplies(G, s, W, r).normalize();
-
- // components must be bogus.
- if (P.isInfinity())
- {
- return false;
- }
-
- BigInteger x = P.getAffineXCoord().toBigInteger();
- BigInteger t = r.subtract(x).mod(n);
-
- return t.equals(e);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/signers/GOST3410Signer.java b/core/src/main/java/org/bouncycastle/crypto/signers/GOST3410Signer.java
deleted file mode 100644
index 135f1857..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/signers/GOST3410Signer.java
+++ /dev/null
@@ -1,131 +0,0 @@
-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.GOST3410KeyParameters;
-import org.bouncycastle.crypto.params.GOST3410Parameters;
-import org.bouncycastle.crypto.params.GOST3410PrivateKeyParameters;
-import org.bouncycastle.crypto.params.GOST3410PublicKeyParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-
-/**
- * GOST R 34.10-94 Signature Algorithm
- */
-public class GOST3410Signer
- implements DSA
-{
- GOST3410KeyParameters key;
-
- SecureRandom random;
-
- public void init(
- boolean forSigning,
- CipherParameters param)
- {
- if (forSigning)
- {
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- this.random = rParam.getRandom();
- this.key = (GOST3410PrivateKeyParameters)rParam.getParameters();
- }
- else
- {
- this.random = new SecureRandom();
- this.key = (GOST3410PrivateKeyParameters)param;
- }
- }
- else
- {
- this.key = (GOST3410PublicKeyParameters)param;
- }
- }
-
- /**
- * generate a signature for the given message using the key we were
- * initialised with. For conventional GOST3410 the message should be a GOST3411
- * hash of the message of interest.
- *
- * @param message the message that will be verified later.
- */
- public BigInteger[] generateSignature(
- byte[] message)
- {
- byte[] mRev = new byte[message.length]; // conversion is little-endian
- for (int i = 0; i != mRev.length; i++)
- {
- mRev[i] = message[mRev.length - 1 - i];
- }
-
- BigInteger m = new BigInteger(1, mRev);
- GOST3410Parameters params = key.getParameters();
- BigInteger k;
-
- do
- {
- k = new BigInteger(params.getQ().bitLength(), random);
- }
- while (k.compareTo(params.getQ()) >= 0);
-
- BigInteger r = params.getA().modPow(k, params.getP()).mod(params.getQ());
-
- BigInteger s = k.multiply(m).
- add(((GOST3410PrivateKeyParameters)key).getX().multiply(r)).
- mod(params.getQ());
-
- BigInteger[] res = new BigInteger[2];
-
- res[0] = r;
- res[1] = s;
-
- return res;
- }
-
- /**
- * return true if the value r and s represent a GOST3410 signature for
- * the passed in message for standard GOST3410 the message should be a
- * GOST3411 hash of the real message to be verified.
- */
- public boolean verifySignature(
- byte[] message,
- BigInteger r,
- BigInteger s)
- {
- byte[] mRev = new byte[message.length]; // conversion is little-endian
- for (int i = 0; i != mRev.length; i++)
- {
- mRev[i] = message[mRev.length - 1 - i];
- }
-
- BigInteger m = new BigInteger(1, mRev);
- GOST3410Parameters params = key.getParameters();
- BigInteger zero = BigInteger.valueOf(0);
-
- if (zero.compareTo(r) >= 0 || params.getQ().compareTo(r) <= 0)
- {
- return false;
- }
-
- if (zero.compareTo(s) >= 0 || params.getQ().compareTo(s) <= 0)
- {
- return false;
- }
-
- BigInteger v = m.modPow(params.getQ().subtract(new BigInteger("2")),params.getQ());
-
- BigInteger z1 = s.multiply(v).mod(params.getQ());
- BigInteger z2 = (params.getQ().subtract(r)).multiply(v).mod(params.getQ());
-
- z1 = params.getA().modPow(z1, params.getP());
- z2 = ((GOST3410PublicKeyParameters)key).getY().modPow(z2, params.getP());
-
- BigInteger u = z1.multiply(z2).mod(params.getP()).mod(params.getQ());
-
- return u.equals(r);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/signers/GenericSigner.java b/core/src/main/java/org/bouncycastle/crypto/signers/GenericSigner.java
deleted file mode 100644
index 6819e141..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/signers/GenericSigner.java
+++ /dev/null
@@ -1,136 +0,0 @@
-package org.bouncycastle.crypto.signers;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.Signer;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.util.Arrays;
-
-public class GenericSigner
- implements Signer
-{
- private final AsymmetricBlockCipher engine;
- private final Digest digest;
- private boolean forSigning;
-
- public GenericSigner(
- AsymmetricBlockCipher engine,
- Digest digest)
- {
- this.engine = engine;
- this.digest = digest;
- }
-
- /**
- * initialise the signer for signing or verification.
- *
- * @param forSigning
- * true if for signing, false otherwise
- * @param parameters
- * necessary parameters.
- */
- public void init(
- boolean forSigning,
- CipherParameters parameters)
- {
- this.forSigning = forSigning;
- AsymmetricKeyParameter k;
-
- if (parameters instanceof ParametersWithRandom)
- {
- k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).getParameters();
- }
- else
- {
- k = (AsymmetricKeyParameter)parameters;
- }
-
- if (forSigning && !k.isPrivate())
- {
- throw new IllegalArgumentException("signing requires private key");
- }
-
- if (!forSigning && k.isPrivate())
- {
- throw new IllegalArgumentException("verification requires public key");
- }
-
- reset();
-
- engine.init(forSigning, parameters);
- }
-
- /**
- * update the internal digest with the byte b
- */
- public void update(
- byte input)
- {
- digest.update(input);
- }
-
- /**
- * update the internal digest with the byte array in
- */
- public void update(
- byte[] input,
- int inOff,
- int length)
- {
- digest.update(input, inOff, length);
- }
-
- /**
- * Generate a signature for the message we've been loaded with using the key
- * we were initialised with.
- */
- public byte[] generateSignature()
- throws CryptoException, DataLengthException
- {
- if (!forSigning)
- {
- throw new IllegalStateException("GenericSigner not initialised for signature generation.");
- }
-
- byte[] hash = new byte[digest.getDigestSize()];
- digest.doFinal(hash, 0);
-
- return engine.processBlock(hash, 0, hash.length);
- }
-
- /**
- * return true if the internal state represents the signature described in
- * the passed in array.
- */
- public boolean verifySignature(
- byte[] signature)
- {
- if (forSigning)
- {
- throw new IllegalStateException("GenericSigner not initialised for verification");
- }
-
- byte[] hash = new byte[digest.getDigestSize()];
- digest.doFinal(hash, 0);
-
- try
- {
- byte[] sig = engine.processBlock(signature, 0, signature.length);
-
- return Arrays.constantTimeAreEqual(sig, hash);
- }
- catch (Exception e)
- {
- return false;
- }
- }
-
- public void reset()
- {
- digest.reset();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/signers/HMacDSAKCalculator.java b/core/src/main/java/org/bouncycastle/crypto/signers/HMacDSAKCalculator.java
deleted file mode 100644
index db78d4a3..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/signers/HMacDSAKCalculator.java
+++ /dev/null
@@ -1,152 +0,0 @@
-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);
-
- int len = Math.min(t.length - tOff, V.length);
- System.arraycopy(V, 0, t, tOff, len);
- tOff += len;
- }
-
- BigInteger k = bitsToInt(t);
-
- if (k.compareTo(ZERO) > 0 && k.compareTo(n) < 0)
- {
- return k;
- }
-
- 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);
- }
- }
-
- 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/core/src/main/java/org/bouncycastle/crypto/signers/ISO9796d2PSSSigner.java b/core/src/main/java/org/bouncycastle/crypto/signers/ISO9796d2PSSSigner.java
deleted file mode 100644
index fcd5816a..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/signers/ISO9796d2PSSSigner.java
+++ /dev/null
@@ -1,668 +0,0 @@
-package org.bouncycastle.crypto.signers;
-
-import java.security.SecureRandom;
-import java.util.Hashtable;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.SignerWithRecovery;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.params.ParametersWithSalt;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Integers;
-
-/**
- * ISO9796-2 - mechanism using a hash function with recovery (scheme 2 and 3).
- * <p>
- * Note: the usual length for the salt is the length of the hash
- * function used in bytes.
- */
-public class ISO9796d2PSSSigner
- implements SignerWithRecovery
-{
- static final public int TRAILER_IMPLICIT = 0xBC;
- static final public int TRAILER_RIPEMD160 = 0x31CC;
- static final public int TRAILER_RIPEMD128 = 0x32CC;
- static final public int TRAILER_SHA1 = 0x33CC;
- static final public int TRAILER_SHA256 = 0x34CC;
- static final public int TRAILER_SHA512 = 0x35CC;
- static final public int TRAILER_SHA384 = 0x36CC;
- static final public int TRAILER_WHIRLPOOL = 0x37CC;
-
- private static Hashtable trailerMap = new Hashtable();
-
- static
- {
- trailerMap.put("RIPEMD128", Integers.valueOf(TRAILER_RIPEMD128));
- trailerMap.put("RIPEMD160", Integers.valueOf(TRAILER_RIPEMD160));
-
- trailerMap.put("SHA-1", Integers.valueOf(TRAILER_SHA1));
- trailerMap.put("SHA-256", Integers.valueOf(TRAILER_SHA256));
- trailerMap.put("SHA-384", Integers.valueOf(TRAILER_SHA384));
- trailerMap.put("SHA-512", Integers.valueOf(TRAILER_SHA512));
-
- trailerMap.put("Whirlpool", Integers.valueOf(TRAILER_WHIRLPOOL));
- }
-
- private Digest digest;
- private AsymmetricBlockCipher cipher;
-
- private SecureRandom random;
- private byte[] standardSalt;
-
- private int hLen;
- private int trailer;
- private int keyBits;
- private byte[] block;
- private byte[] mBuf;
- private int messageLength;
- private int saltLength;
- private boolean fullMessage;
- private byte[] recoveredMessage;
-
- private byte[] preSig;
- private byte[] preBlock;
- private int preMStart;
- private int preTLength;
-
- /**
- * Generate a signer for the with either implicit or explicit trailers
- * for ISO9796-2, scheme 2 or 3.
- *
- * @param cipher base cipher to use for signature creation/verification
- * @param digest digest to use.
- * @param saltLength length of salt in bytes.
- * @param implicit whether or not the trailer is implicit or gives the hash.
- */
- public ISO9796d2PSSSigner(
- AsymmetricBlockCipher cipher,
- Digest digest,
- int saltLength,
- boolean implicit)
- {
- this.cipher = cipher;
- this.digest = digest;
- this.hLen = digest.getDigestSize();
- this.saltLength = saltLength;
-
- if (implicit)
- {
- trailer = TRAILER_IMPLICIT;
- }
- else
- {
- Integer trailerObj = (Integer)trailerMap.get(digest.getAlgorithmName());
-
- if (trailerObj != null)
- {
- trailer = trailerObj.intValue();
- }
- else
- {
- throw new IllegalArgumentException("no valid trailer for digest");
- }
- }
- }
-
- /**
- * Constructor for a signer with an explicit digest trailer.
- *
- * @param cipher cipher to use.
- * @param digest digest to sign with.
- * @param saltLength length of salt in bytes.
- */
- public ISO9796d2PSSSigner(
- AsymmetricBlockCipher cipher,
- Digest digest,
- int saltLength)
- {
- this(cipher, digest, saltLength, false);
- }
-
- /**
- * Initialise the signer.
- *
- * @param forSigning true if for signing, false if for verification.
- * @param param parameters for signature generation/verification. If the
- * parameters are for generation they should be a ParametersWithRandom,
- * a ParametersWithSalt, or just an RSAKeyParameters object. If RSAKeyParameters
- * are passed in a SecureRandom will be created.
- * @throws IllegalArgumentException if wrong parameter type or a fixed
- * salt is passed in which is the wrong length.
- */
- public void init(
- boolean forSigning,
- CipherParameters param)
- {
- RSAKeyParameters kParam;
- int lengthOfSalt = saltLength;
-
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom p = (ParametersWithRandom)param;
-
- kParam = (RSAKeyParameters)p.getParameters();
- if (forSigning)
- {
- random = p.getRandom();
- }
- }
- else if (param instanceof ParametersWithSalt)
- {
- ParametersWithSalt p = (ParametersWithSalt)param;
-
- kParam = (RSAKeyParameters)p.getParameters();
- standardSalt = p.getSalt();
- lengthOfSalt = standardSalt.length;
- if (standardSalt.length != saltLength)
- {
- throw new IllegalArgumentException("Fixed salt is of wrong length");
- }
- }
- else
- {
- kParam = (RSAKeyParameters)param;
- if (forSigning)
- {
- random = new SecureRandom();
- }
- }
-
- cipher.init(forSigning, kParam);
-
- keyBits = kParam.getModulus().bitLength();
-
- block = new byte[(keyBits + 7) / 8];
-
- if (trailer == TRAILER_IMPLICIT)
- {
- mBuf = new byte[block.length - digest.getDigestSize() - lengthOfSalt - 1 - 1];
- }
- else
- {
- mBuf = new byte[block.length - digest.getDigestSize() - lengthOfSalt - 1 - 2];
- }
-
- reset();
- }
-
- /**
- * compare two byte arrays - constant time
- */
- private boolean isSameAs(
- byte[] a,
- byte[] b)
- {
- boolean isOkay = true;
-
- if (messageLength != b.length)
- {
- isOkay = false;
- }
-
- for (int i = 0; i != b.length; i++)
- {
- if (a[i] != b[i])
- {
- isOkay = false;
- }
- }
-
- return isOkay;
- }
-
- /**
- * clear possible sensitive data
- */
- private void clearBlock(
- byte[] block)
- {
- for (int i = 0; i != block.length; i++)
- {
- block[i] = 0;
- }
- }
-
- public void updateWithRecoveredMessage(byte[] signature)
- throws InvalidCipherTextException
- {
- byte[] block = cipher.processBlock(signature, 0, signature.length);
-
- //
- // adjust block size for leading zeroes if necessary
- //
- if (block.length < (keyBits + 7) / 8)
- {
- byte[] tmp = new byte[(keyBits + 7) / 8];
-
- System.arraycopy(block, 0, tmp, tmp.length - block.length, block.length);
- clearBlock(block);
- block = tmp;
- }
-
- int tLength;
-
- if (((block[block.length - 1] & 0xFF) ^ 0xBC) == 0)
- {
- tLength = 1;
- }
- else
- {
- int sigTrail = ((block[block.length - 2] & 0xFF) << 8) | (block[block.length - 1] & 0xFF);
-
- Integer trailerObj = (Integer)trailerMap.get(digest.getAlgorithmName());
-
- if (trailerObj != null)
- {
- if (sigTrail != trailerObj.intValue())
- {
- throw new IllegalStateException("signer initialised with wrong digest for trailer " + sigTrail);
- }
- }
- else
- {
- throw new IllegalArgumentException("unrecognised hash in signature");
- }
-
- tLength = 2;
- }
-
- //
- // calculate H(m2)
- //
- byte[] m2Hash = new byte[hLen];
- digest.doFinal(m2Hash, 0);
-
- //
- // remove the mask
- //
- byte[] dbMask = maskGeneratorFunction1(block, block.length - hLen - tLength, hLen, block.length - hLen - tLength);
- for (int i = 0; i != dbMask.length; i++)
- {
- block[i] ^= dbMask[i];
- }
-
- block[0] &= 0x7f;
-
- //
- // find out how much padding we've got
- //
- int mStart = 0;
- for (; mStart != block.length; mStart++)
- {
- if (block[mStart] == 0x01)
- {
- break;
- }
- }
-
- mStart++;
-
- if (mStart >= block.length)
- {
- clearBlock(block);
- }
-
- fullMessage = (mStart > 1);
-
- recoveredMessage = new byte[dbMask.length - mStart - saltLength];
-
- System.arraycopy(block, mStart, recoveredMessage, 0, recoveredMessage.length);
- System.arraycopy(recoveredMessage, 0, mBuf, 0, recoveredMessage.length);
-
- preSig = signature;
- preBlock = block;
- preMStart = mStart;
- preTLength = tLength;
- }
-
- /**
- * update the internal digest with the byte b
- */
- public void update(
- byte b)
- {
- if (preSig == null && messageLength < mBuf.length)
- {
- mBuf[messageLength++] = b;
- }
- else
- {
- digest.update(b);
- }
- }
-
- /**
- * update the internal digest with the byte array in
- */
- public void update(
- byte[] in,
- int off,
- int len)
- {
- if (preSig == null)
- {
- while (len > 0 && messageLength < mBuf.length)
- {
- this.update(in[off]);
- off++;
- len--;
- }
- }
-
- if (len > 0)
- {
- digest.update(in, off, len);
- }
- }
-
- /**
- * reset the internal state
- */
- public void reset()
- {
- digest.reset();
- messageLength = 0;
- if (mBuf != null)
- {
- clearBlock(mBuf);
- }
- if (recoveredMessage != null)
- {
- clearBlock(recoveredMessage);
- recoveredMessage = null;
- }
- fullMessage = false;
- if (preSig != null)
- {
- preSig = null;
- clearBlock(preBlock);
- preBlock = null;
- }
- }
-
- /**
- * generate a signature for the loaded message using the key we were
- * initialised with.
- */
- public byte[] generateSignature()
- throws CryptoException
- {
- int digSize = digest.getDigestSize();
-
- byte[] m2Hash = new byte[digSize];
-
- digest.doFinal(m2Hash, 0);
-
- byte[] C = new byte[8];
- LtoOSP(messageLength * 8, C);
-
- digest.update(C, 0, C.length);
-
- digest.update(mBuf, 0, messageLength);
-
- digest.update(m2Hash, 0, m2Hash.length);
-
- byte[] salt;
-
- if (standardSalt != null)
- {
- salt = standardSalt;
- }
- else
- {
- salt = new byte[saltLength];
- random.nextBytes(salt);
- }
-
- digest.update(salt, 0, salt.length);
-
- byte[] hash = new byte[digest.getDigestSize()];
-
- digest.doFinal(hash, 0);
-
- int tLength = 2;
- if (trailer == TRAILER_IMPLICIT)
- {
- tLength = 1;
- }
-
- int off = block.length - messageLength - salt.length - hLen - tLength - 1;
-
- block[off] = 0x01;
-
- System.arraycopy(mBuf, 0, block, off + 1, messageLength);
- System.arraycopy(salt, 0, block, off + 1 + messageLength, salt.length);
-
- byte[] dbMask = maskGeneratorFunction1(hash, 0, hash.length, block.length - hLen - tLength);
- for (int i = 0; i != dbMask.length; i++)
- {
- block[i] ^= dbMask[i];
- }
-
- System.arraycopy(hash, 0, block, block.length - hLen - tLength, hLen);
-
- if (trailer == TRAILER_IMPLICIT)
- {
- block[block.length - 1] = (byte)TRAILER_IMPLICIT;
- }
- else
- {
- block[block.length - 2] = (byte)(trailer >>> 8);
- block[block.length - 1] = (byte)trailer;
- }
-
- block[0] &= 0x7f;
-
- byte[] b = cipher.processBlock(block, 0, block.length);
-
- clearBlock(mBuf);
- clearBlock(block);
- messageLength = 0;
-
- return b;
- }
-
- /**
- * return true if the signature represents a ISO9796-2 signature
- * for the passed in message.
- */
- public boolean verifySignature(
- byte[] signature)
- {
- //
- // calculate H(m2)
- //
- byte[] m2Hash = new byte[hLen];
- digest.doFinal(m2Hash, 0);
-
- byte[] block;
- int tLength;
- int mStart = 0;
-
- if (preSig == null)
- {
- try
- {
- updateWithRecoveredMessage(signature);
- }
- catch (Exception e)
- {
- return false;
- }
- }
- else
- {
- if (!Arrays.areEqual(preSig, signature))
- {
- throw new IllegalStateException("updateWithRecoveredMessage called on different signature");
- }
- }
-
- block = preBlock;
- mStart = preMStart;
- tLength = preTLength;
-
- preSig = null;
- preBlock = null;
-
- //
- // check the hashes
- //
- byte[] C = new byte[8];
- LtoOSP(recoveredMessage.length * 8, C);
-
- digest.update(C, 0, C.length);
-
- if (recoveredMessage.length != 0)
- {
- digest.update(recoveredMessage, 0, recoveredMessage.length);
- }
-
- digest.update(m2Hash, 0, m2Hash.length);
-
- // Update for the salt
- digest.update(block, mStart + recoveredMessage.length, saltLength);
-
- byte[] hash = new byte[digest.getDigestSize()];
- digest.doFinal(hash, 0);
-
- int off = block.length - tLength - hash.length;
-
- boolean isOkay = true;
-
- for (int i = 0; i != hash.length; i++)
- {
- if (hash[i] != block[off + i])
- {
- isOkay = false;
- }
- }
-
- clearBlock(block);
- clearBlock(hash);
-
- if (!isOkay)
- {
- fullMessage = false;
- clearBlock(recoveredMessage);
- return false;
- }
-
- //
- // if they've input a message check what we've recovered against
- // what was input.
- //
- if (messageLength != 0)
- {
- if (!isSameAs(mBuf, recoveredMessage))
- {
- clearBlock(mBuf);
- return false;
- }
- messageLength = 0;
- }
-
- clearBlock(mBuf);
- return true;
- }
-
- /**
- * Return true if the full message was recoveredMessage.
- *
- * @return true on full message recovery, false otherwise, or if not sure.
- * @see org.bouncycastle.crypto.SignerWithRecovery#hasFullMessage()
- */
- public boolean hasFullMessage()
- {
- return fullMessage;
- }
-
- /**
- * Return a reference to the recoveredMessage message.
- *
- * @return the full/partial recoveredMessage message.
- * @see org.bouncycastle.crypto.SignerWithRecovery#getRecoveredMessage()
- */
- public byte[] getRecoveredMessage()
- {
- return recoveredMessage;
- }
-
- /**
- * int to octet string.
- */
- private void ItoOSP(
- int i,
- byte[] sp)
- {
- sp[0] = (byte)(i >>> 24);
- sp[1] = (byte)(i >>> 16);
- sp[2] = (byte)(i >>> 8);
- sp[3] = (byte)(i >>> 0);
- }
-
- /**
- * long to octet string.
- */
- private void LtoOSP(
- long l,
- byte[] sp)
- {
- sp[0] = (byte)(l >>> 56);
- sp[1] = (byte)(l >>> 48);
- sp[2] = (byte)(l >>> 40);
- sp[3] = (byte)(l >>> 32);
- sp[4] = (byte)(l >>> 24);
- sp[5] = (byte)(l >>> 16);
- sp[6] = (byte)(l >>> 8);
- sp[7] = (byte)(l >>> 0);
- }
-
- /**
- * mask generator function, as described in PKCS1v2.
- */
- private byte[] maskGeneratorFunction1(
- byte[] Z,
- int zOff,
- int zLen,
- int length)
- {
- byte[] mask = new byte[length];
- byte[] hashBuf = new byte[hLen];
- byte[] C = new byte[4];
- int counter = 0;
-
- digest.reset();
-
- while (counter < (length / hLen))
- {
- ItoOSP(counter, C);
-
- digest.update(Z, zOff, zLen);
- digest.update(C, 0, C.length);
- digest.doFinal(hashBuf, 0);
-
- System.arraycopy(hashBuf, 0, mask, counter * hLen, hLen);
-
- counter++;
- }
-
- if ((counter * hLen) < length)
- {
- ItoOSP(counter, C);
-
- digest.update(Z, zOff, zLen);
- digest.update(C, 0, C.length);
- digest.doFinal(hashBuf, 0);
-
- System.arraycopy(hashBuf, 0, mask, counter * hLen, mask.length - (counter * hLen));
- }
-
- return mask;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/signers/ISO9796d2Signer.java b/core/src/main/java/org/bouncycastle/crypto/signers/ISO9796d2Signer.java
deleted file mode 100644
index 563fae63..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/signers/ISO9796d2Signer.java
+++ /dev/null
@@ -1,618 +0,0 @@
-package org.bouncycastle.crypto.signers;
-
-import java.util.Hashtable;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.SignerWithRecovery;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Integers;
-
-/**
- * ISO9796-2 - mechanism using a hash function with recovery (scheme 1)
- */
-public class ISO9796d2Signer
- implements SignerWithRecovery
-{
- static final public int TRAILER_IMPLICIT = 0xBC;
- static final public int TRAILER_RIPEMD160 = 0x31CC;
- static final public int TRAILER_RIPEMD128 = 0x32CC;
- static final public int TRAILER_SHA1 = 0x33CC;
- static final public int TRAILER_SHA256 = 0x34CC;
- static final public int TRAILER_SHA512 = 0x35CC;
- static final public int TRAILER_SHA384 = 0x36CC;
- static final public int TRAILER_WHIRLPOOL = 0x37CC;
-
- private static Hashtable trailerMap = new Hashtable();
-
- static
- {
- trailerMap.put("RIPEMD128", Integers.valueOf(TRAILER_RIPEMD128));
- trailerMap.put("RIPEMD160", Integers.valueOf(TRAILER_RIPEMD160));
-
- trailerMap.put("SHA-1", Integers.valueOf(TRAILER_SHA1));
- trailerMap.put("SHA-256", Integers.valueOf(TRAILER_SHA256));
- trailerMap.put("SHA-384", Integers.valueOf(TRAILER_SHA384));
- trailerMap.put("SHA-512", Integers.valueOf(TRAILER_SHA512));
-
- trailerMap.put("Whirlpool", Integers.valueOf(TRAILER_WHIRLPOOL));
- }
-
- private Digest digest;
- private AsymmetricBlockCipher cipher;
-
- private int trailer;
- private int keyBits;
- private byte[] block;
- private byte[] mBuf;
- private int messageLength;
- private boolean fullMessage;
- private byte[] recoveredMessage;
-
- private byte[] preSig;
- private byte[] preBlock;
-
- /**
- * Generate a signer for the with either implicit or explicit trailers
- * for ISO9796-2.
- *
- * @param cipher base cipher to use for signature creation/verification
- * @param digest digest to use.
- * @param implicit whether or not the trailer is implicit or gives the hash.
- */
- public ISO9796d2Signer(
- AsymmetricBlockCipher cipher,
- Digest digest,
- boolean implicit)
- {
- this.cipher = cipher;
- this.digest = digest;
-
- if (implicit)
- {
- trailer = TRAILER_IMPLICIT;
- }
- else
- {
- Integer trailerObj = (Integer)trailerMap.get(digest.getAlgorithmName());
-
- if (trailerObj != null)
- {
- trailer = trailerObj.intValue();
- }
- else
- {
- throw new IllegalArgumentException("no valid trailer for digest");
- }
- }
- }
-
- /**
- * Constructor for a signer with an explicit digest trailer.
- *
- * @param cipher cipher to use.
- * @param digest digest to sign with.
- */
- public ISO9796d2Signer(
- AsymmetricBlockCipher cipher,
- Digest digest)
- {
- this(cipher, digest, false);
- }
-
- public void init(
- boolean forSigning,
- CipherParameters param)
- {
- RSAKeyParameters kParam = (RSAKeyParameters)param;
-
- cipher.init(forSigning, kParam);
-
- keyBits = kParam.getModulus().bitLength();
-
- block = new byte[(keyBits + 7) / 8];
-
- if (trailer == TRAILER_IMPLICIT)
- {
- mBuf = new byte[block.length - digest.getDigestSize() - 2];
- }
- else
- {
- mBuf = new byte[block.length - digest.getDigestSize() - 3];
- }
-
- reset();
- }
-
- /**
- * compare two byte arrays - constant time
- */
- private boolean isSameAs(
- byte[] a,
- byte[] b)
- {
- boolean isOkay = true;
-
- if (messageLength > mBuf.length)
- {
- if (mBuf.length > b.length)
- {
- isOkay = false;
- }
-
- for (int i = 0; i != mBuf.length; i++)
- {
- if (a[i] != b[i])
- {
- isOkay = false;
- }
- }
- }
- else
- {
- if (messageLength != b.length)
- {
- isOkay = false;
- }
-
- for (int i = 0; i != b.length; i++)
- {
- if (a[i] != b[i])
- {
- isOkay = false;
- }
- }
- }
-
- return isOkay;
- }
-
- /**
- * clear possible sensitive data
- */
- private void clearBlock(
- byte[] block)
- {
- for (int i = 0; i != block.length; i++)
- {
- block[i] = 0;
- }
- }
-
- public void updateWithRecoveredMessage(byte[] signature)
- throws InvalidCipherTextException
- {
- byte[] block = cipher.processBlock(signature, 0, signature.length);
-
- if (((block[0] & 0xC0) ^ 0x40) != 0)
- {
- throw new InvalidCipherTextException("malformed signature");
- }
-
- if (((block[block.length - 1] & 0xF) ^ 0xC) != 0)
- {
- throw new InvalidCipherTextException("malformed signature");
- }
-
- int delta = 0;
-
- if (((block[block.length - 1] & 0xFF) ^ 0xBC) == 0)
- {
- delta = 1;
- }
- else
- {
- int sigTrail = ((block[block.length - 2] & 0xFF) << 8) | (block[block.length - 1] & 0xFF);
- Integer trailerObj = (Integer)trailerMap.get(digest.getAlgorithmName());
-
- if (trailerObj != null)
- {
- if (sigTrail != trailerObj.intValue())
- {
- throw new IllegalStateException("signer initialised with wrong digest for trailer " + sigTrail);
- }
- }
- else
- {
- throw new IllegalArgumentException("unrecognised hash in signature");
- }
-
- delta = 2;
- }
-
- //
- // find out how much padding we've got
- //
- int mStart = 0;
-
- for (mStart = 0; mStart != block.length; mStart++)
- {
- if (((block[mStart] & 0x0f) ^ 0x0a) == 0)
- {
- break;
- }
- }
-
- mStart++;
-
- int off = block.length - delta - digest.getDigestSize();
-
- //
- // there must be at least one byte of message string
- //
- if ((off - mStart) <= 0)
- {
- throw new InvalidCipherTextException("malformed block");
- }
-
- //
- // if we contain the whole message as well, check the hash of that.
- //
- if ((block[0] & 0x20) == 0)
- {
- fullMessage = true;
-
- recoveredMessage = new byte[off - mStart];
- System.arraycopy(block, mStart, recoveredMessage, 0, recoveredMessage.length);
- }
- else
- {
- fullMessage = false;
-
- recoveredMessage = new byte[off - mStart];
- System.arraycopy(block, mStart, recoveredMessage, 0, recoveredMessage.length);
- }
-
- preSig = signature;
- preBlock = block;
-
- digest.update(recoveredMessage, 0, recoveredMessage.length);
- messageLength = recoveredMessage.length;
- System.arraycopy(recoveredMessage, 0, mBuf, 0, recoveredMessage.length);
- }
-
- /**
- * update the internal digest with the byte b
- */
- public void update(
- byte b)
- {
- digest.update(b);
-
- if (messageLength < mBuf.length)
- {
- mBuf[messageLength] = b;
- }
-
- messageLength++;
- }
-
- /**
- * update the internal digest with the byte array in
- */
- public void update(
- byte[] in,
- int off,
- int len)
- {
- while (len > 0 && messageLength < mBuf.length)
- {
- this.update(in[off]);
- off++;
- len--;
- }
-
- digest.update(in, off, len);
- messageLength += len;
- }
-
- /**
- * reset the internal state
- */
- public void reset()
- {
- digest.reset();
- messageLength = 0;
- clearBlock(mBuf);
-
- if (recoveredMessage != null)
- {
- clearBlock(recoveredMessage);
- }
-
- recoveredMessage = null;
- fullMessage = false;
-
- if (preSig != null)
- {
- preSig = null;
- clearBlock(preBlock);
- preBlock = null;
- }
- }
-
- /**
- * generate a signature for the loaded message using the key we were
- * initialised with.
- */
- public byte[] generateSignature()
- throws CryptoException
- {
- int digSize = digest.getDigestSize();
-
- int t = 0;
- int delta = 0;
-
- if (trailer == TRAILER_IMPLICIT)
- {
- t = 8;
- delta = block.length - digSize - 1;
- digest.doFinal(block, delta);
- block[block.length - 1] = (byte)TRAILER_IMPLICIT;
- }
- else
- {
- t = 16;
- delta = block.length - digSize - 2;
- digest.doFinal(block, delta);
- block[block.length - 2] = (byte)(trailer >>> 8);
- block[block.length - 1] = (byte)trailer;
- }
-
- byte header = 0;
- int x = (digSize + messageLength) * 8 + t + 4 - keyBits;
-
- if (x > 0)
- {
- int mR = messageLength - ((x + 7) / 8);
- header = 0x60;
-
- delta -= mR;
-
- System.arraycopy(mBuf, 0, block, delta, mR);
- }
- else
- {
- header = 0x40;
- delta -= messageLength;
-
- System.arraycopy(mBuf, 0, block, delta, messageLength);
- }
-
- if ((delta - 1) > 0)
- {
- for (int i = delta - 1; i != 0; i--)
- {
- block[i] = (byte)0xbb;
- }
- block[delta - 1] ^= (byte)0x01;
- block[0] = (byte)0x0b;
- block[0] |= header;
- }
- else
- {
- block[0] = (byte)0x0a;
- block[0] |= header;
- }
-
- byte[] b = cipher.processBlock(block, 0, block.length);
-
- clearBlock(mBuf);
- clearBlock(block);
-
- return b;
- }
-
- /**
- * return true if the signature represents a ISO9796-2 signature
- * for the passed in message.
- */
- public boolean verifySignature(
- byte[] signature)
- {
- byte[] block = null;
-
- if (preSig == null)
- {
- try
- {
- block = cipher.processBlock(signature, 0, signature.length);
- }
- catch (Exception e)
- {
- return false;
- }
- }
- else
- {
- if (!Arrays.areEqual(preSig, signature))
- {
- throw new IllegalStateException("updateWithRecoveredMessage called on different signature");
- }
-
- block = preBlock;
-
- preSig = null;
- preBlock = null;
- }
-
- if (((block[0] & 0xC0) ^ 0x40) != 0)
- {
- return returnFalse(block);
- }
-
- if (((block[block.length - 1] & 0xF) ^ 0xC) != 0)
- {
- return returnFalse(block);
- }
-
- int delta = 0;
-
- if (((block[block.length - 1] & 0xFF) ^ 0xBC) == 0)
- {
- delta = 1;
- }
- else
- {
- int sigTrail = ((block[block.length - 2] & 0xFF) << 8) | (block[block.length - 1] & 0xFF);
- Integer trailerObj = (Integer)trailerMap.get(digest.getAlgorithmName());
-
- if (trailerObj != null)
- {
- if (sigTrail != trailerObj.intValue())
- {
- throw new IllegalStateException("signer initialised with wrong digest for trailer " + sigTrail);
- }
- }
- else
- {
- throw new IllegalArgumentException("unrecognised hash in signature");
- }
-
- delta = 2;
- }
-
- //
- // find out how much padding we've got
- //
- int mStart = 0;
-
- for (mStart = 0; mStart != block.length; mStart++)
- {
- if (((block[mStart] & 0x0f) ^ 0x0a) == 0)
- {
- break;
- }
- }
-
- mStart++;
-
- //
- // check the hashes
- //
- byte[] hash = new byte[digest.getDigestSize()];
-
- int off = block.length - delta - hash.length;
-
- //
- // there must be at least one byte of message string
- //
- if ((off - mStart) <= 0)
- {
- return returnFalse(block);
- }
-
- //
- // if we contain the whole message as well, check the hash of that.
- //
- if ((block[0] & 0x20) == 0)
- {
- fullMessage = true;
-
- // check right number of bytes passed in.
- if (messageLength > off - mStart)
- {
- return returnFalse(block);
- }
-
- digest.reset();
- digest.update(block, mStart, off - mStart);
- digest.doFinal(hash, 0);
-
- boolean isOkay = true;
-
- for (int i = 0; i != hash.length; i++)
- {
- block[off + i] ^= hash[i];
- if (block[off + i] != 0)
- {
- isOkay = false;
- }
- }
-
- if (!isOkay)
- {
- return returnFalse(block);
- }
-
- recoveredMessage = new byte[off - mStart];
- System.arraycopy(block, mStart, recoveredMessage, 0, recoveredMessage.length);
- }
- else
- {
- fullMessage = false;
-
- digest.doFinal(hash, 0);
-
- boolean isOkay = true;
-
- for (int i = 0; i != hash.length; i++)
- {
- block[off + i] ^= hash[i];
- if (block[off + i] != 0)
- {
- isOkay = false;
- }
- }
-
- if (!isOkay)
- {
- return returnFalse(block);
- }
-
- recoveredMessage = new byte[off - mStart];
- System.arraycopy(block, mStart, recoveredMessage, 0, recoveredMessage.length);
- }
-
- //
- // if they've input a message check what we've recovered against
- // what was input.
- //
- if (messageLength != 0)
- {
- if (!isSameAs(mBuf, recoveredMessage))
- {
- return returnFalse(block);
- }
- }
-
- clearBlock(mBuf);
- clearBlock(block);
-
- return true;
- }
-
- private boolean returnFalse(byte[] block)
- {
- clearBlock(mBuf);
- clearBlock(block);
-
- return false;
- }
-
- /**
- * Return true if the full message was recoveredMessage.
- *
- * @return true on full message recovery, false otherwise.
- * @see org.bouncycastle.crypto.SignerWithRecovery#hasFullMessage()
- */
- public boolean hasFullMessage()
- {
- return fullMessage;
- }
-
- /**
- * Return a reference to the recoveredMessage message.
- *
- * @return the full/partial recoveredMessage message.
- * @see org.bouncycastle.crypto.SignerWithRecovery#getRecoveredMessage()
- */
- public byte[] getRecoveredMessage()
- {
- return recoveredMessage;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/signers/PSSSigner.java b/core/src/main/java/org/bouncycastle/crypto/signers/PSSSigner.java
deleted file mode 100644
index 8c9eb940..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/signers/PSSSigner.java
+++ /dev/null
@@ -1,348 +0,0 @@
-package org.bouncycastle.crypto.signers;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.Signer;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.params.RSABlindingParameters;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-
-/**
- * RSA-PSS as described in PKCS# 1 v 2.1.
- * <p>
- * Note: the usual value for the salt length is the number of
- * bytes in the hash function.
- */
-public class PSSSigner
- implements Signer
-{
- static final public byte TRAILER_IMPLICIT = (byte)0xBC;
-
- private Digest contentDigest;
- private Digest mgfDigest;
- private AsymmetricBlockCipher cipher;
- private SecureRandom random;
-
- private int hLen;
- private int mgfhLen;
- private int sLen;
- private int emBits;
- private byte[] salt;
- private byte[] mDash;
- private byte[] block;
- private byte trailer;
-
- /**
- * basic constructor
- *
- * @param cipher the asymmetric cipher to use.
- * @param digest the digest to use.
- * @param sLen the length of the salt to use (in bytes).
- */
- public PSSSigner(
- AsymmetricBlockCipher cipher,
- Digest digest,
- int sLen)
- {
- this(cipher, digest, sLen, TRAILER_IMPLICIT);
- }
-
- public PSSSigner(
- AsymmetricBlockCipher cipher,
- Digest contentDigest,
- Digest mgfDigest,
- int sLen)
- {
- this(cipher, contentDigest, mgfDigest, sLen, TRAILER_IMPLICIT);
- }
-
- public PSSSigner(
- AsymmetricBlockCipher cipher,
- Digest digest,
- int sLen,
- byte trailer)
- {
- this(cipher, digest, digest, sLen, trailer);
- }
-
- public PSSSigner(
- AsymmetricBlockCipher cipher,
- Digest contentDigest,
- Digest mgfDigest,
- int sLen,
- byte trailer)
- {
- this.cipher = cipher;
- this.contentDigest = contentDigest;
- this.mgfDigest = mgfDigest;
- this.hLen = contentDigest.getDigestSize();
- this.mgfhLen = mgfDigest.getDigestSize();
- this.sLen = sLen;
- this.salt = new byte[sLen];
- this.mDash = new byte[8 + sLen + hLen];
- this.trailer = trailer;
- }
-
- public void init(
- boolean forSigning,
- CipherParameters param)
- {
- CipherParameters params;
-
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom p = (ParametersWithRandom)param;
-
- params = p.getParameters();
- random = p.getRandom();
- }
- else
- {
- params = param;
- if (forSigning)
- {
- random = new SecureRandom();
- }
- }
-
- cipher.init(forSigning, params);
-
- RSAKeyParameters kParam;
-
- if (params instanceof RSABlindingParameters)
- {
- kParam = ((RSABlindingParameters)params).getPublicKey();
- }
- else
- {
- kParam = (RSAKeyParameters)params;
- }
-
- emBits = kParam.getModulus().bitLength() - 1;
-
- if (emBits < (8 * hLen + 8 * sLen + 9))
- {
- throw new IllegalArgumentException("key too small for specified hash and salt lengths");
- }
-
- block = new byte[(emBits + 7) / 8];
-
- reset();
- }
-
- /**
- * clear possible sensitive data
- */
- private void clearBlock(
- byte[] block)
- {
- for (int i = 0; i != block.length; i++)
- {
- block[i] = 0;
- }
- }
-
- /**
- * update the internal digest with the byte b
- */
- public void update(
- byte b)
- {
- contentDigest.update(b);
- }
-
- /**
- * update the internal digest with the byte array in
- */
- public void update(
- byte[] in,
- int off,
- int len)
- {
- contentDigest.update(in, off, len);
- }
-
- /**
- * reset the internal state
- */
- public void reset()
- {
- contentDigest.reset();
- }
-
- /**
- * generate a signature for the message we've been loaded with using
- * the key we were initialised with.
- */
- public byte[] generateSignature()
- throws CryptoException, DataLengthException
- {
- contentDigest.doFinal(mDash, mDash.length - hLen - sLen);
-
- if (sLen != 0)
- {
- random.nextBytes(salt);
-
- System.arraycopy(salt, 0, mDash, mDash.length - sLen, sLen);
- }
-
- byte[] h = new byte[hLen];
-
- contentDigest.update(mDash, 0, mDash.length);
-
- contentDigest.doFinal(h, 0);
-
- block[block.length - sLen - 1 - hLen - 1] = 0x01;
- System.arraycopy(salt, 0, block, block.length - sLen - hLen - 1, sLen);
-
- byte[] dbMask = maskGeneratorFunction1(h, 0, h.length, block.length - hLen - 1);
- for (int i = 0; i != dbMask.length; i++)
- {
- block[i] ^= dbMask[i];
- }
-
- block[0] &= (0xff >> ((block.length * 8) - emBits));
-
- System.arraycopy(h, 0, block, block.length - hLen - 1, hLen);
-
- block[block.length - 1] = trailer;
-
- byte[] b = cipher.processBlock(block, 0, block.length);
-
- clearBlock(block);
-
- return b;
- }
-
- /**
- * return true if the internal state represents the signature described
- * in the passed in array.
- */
- public boolean verifySignature(
- byte[] signature)
- {
- contentDigest.doFinal(mDash, mDash.length - hLen - sLen);
-
- try
- {
- byte[] b = cipher.processBlock(signature, 0, signature.length);
- System.arraycopy(b, 0, block, block.length - b.length, b.length);
- }
- catch (Exception e)
- {
- return false;
- }
-
- if (block[block.length - 1] != trailer)
- {
- clearBlock(block);
- return false;
- }
-
- byte[] dbMask = maskGeneratorFunction1(block, block.length - hLen - 1, hLen, block.length - hLen - 1);
-
- for (int i = 0; i != dbMask.length; i++)
- {
- block[i] ^= dbMask[i];
- }
-
- block[0] &= (0xff >> ((block.length * 8) - emBits));
-
- for (int i = 0; i != block.length - hLen - sLen - 2; i++)
- {
- if (block[i] != 0)
- {
- clearBlock(block);
- return false;
- }
- }
-
- if (block[block.length - hLen - sLen - 2] != 0x01)
- {
- clearBlock(block);
- return false;
- }
-
- System.arraycopy(block, block.length - sLen - hLen - 1, mDash, mDash.length - sLen, sLen);
-
- contentDigest.update(mDash, 0, mDash.length);
- contentDigest.doFinal(mDash, mDash.length - hLen);
-
- for (int i = block.length - hLen - 1, j = mDash.length - hLen;
- j != mDash.length; i++, j++)
- {
- if ((block[i] ^ mDash[j]) != 0)
- {
- clearBlock(mDash);
- clearBlock(block);
- return false;
- }
- }
-
- clearBlock(mDash);
- clearBlock(block);
-
- return true;
- }
-
- /**
- * int to octet string.
- */
- private void ItoOSP(
- int i,
- byte[] sp)
- {
- sp[0] = (byte)(i >>> 24);
- sp[1] = (byte)(i >>> 16);
- sp[2] = (byte)(i >>> 8);
- sp[3] = (byte)(i >>> 0);
- }
-
- /**
- * mask generator function, as described in PKCS1v2.
- */
- private byte[] maskGeneratorFunction1(
- byte[] Z,
- int zOff,
- int zLen,
- int length)
- {
- byte[] mask = new byte[length];
- byte[] hashBuf = new byte[mgfhLen];
- byte[] C = new byte[4];
- int counter = 0;
-
- mgfDigest.reset();
-
- while (counter < (length / mgfhLen))
- {
- ItoOSP(counter, C);
-
- mgfDigest.update(Z, zOff, zLen);
- mgfDigest.update(C, 0, C.length);
- mgfDigest.doFinal(hashBuf, 0);
-
- System.arraycopy(hashBuf, 0, mask, counter * mgfhLen, mgfhLen);
-
- counter++;
- }
-
- if ((counter * mgfhLen) < length)
- {
- ItoOSP(counter, C);
-
- mgfDigest.update(Z, zOff, zLen);
- mgfDigest.update(C, 0, C.length);
- mgfDigest.doFinal(hashBuf, 0);
-
- System.arraycopy(hashBuf, 0, mask, counter * mgfhLen, mask.length - (counter * mgfhLen));
- }
-
- return mask;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java b/core/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java
deleted file mode 100644
index f34b18c2..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java
+++ /dev/null
@@ -1,240 +0,0 @@
-package org.bouncycastle.crypto.signers;
-
-import java.io.IOException;
-import java.util.Hashtable;
-
-import org.bouncycastle.asn1.ASN1Encoding;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.DigestInfo;
-import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.Signer;
-import org.bouncycastle.crypto.encodings.PKCS1Encoding;
-import org.bouncycastle.crypto.engines.RSABlindedEngine;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.util.Arrays;
-
-public class RSADigestSigner
- implements Signer
-{
- private final AsymmetricBlockCipher rsaEngine = new PKCS1Encoding(new RSABlindedEngine());
- private final AlgorithmIdentifier algId;
- private final Digest digest;
- private boolean forSigning;
-
- private static final Hashtable oidMap = new Hashtable();
-
- /*
- * Load OID table.
- */
- static
- {
- oidMap.put("RIPEMD128", TeleTrusTObjectIdentifiers.ripemd128);
- oidMap.put("RIPEMD160", TeleTrusTObjectIdentifiers.ripemd160);
- oidMap.put("RIPEMD256", TeleTrusTObjectIdentifiers.ripemd256);
-
- oidMap.put("SHA-1", X509ObjectIdentifiers.id_SHA1);
- oidMap.put("SHA-224", NISTObjectIdentifiers.id_sha224);
- oidMap.put("SHA-256", NISTObjectIdentifiers.id_sha256);
- oidMap.put("SHA-384", NISTObjectIdentifiers.id_sha384);
- oidMap.put("SHA-512", NISTObjectIdentifiers.id_sha512);
- oidMap.put("SHA-512/224", NISTObjectIdentifiers.id_sha512_224);
- oidMap.put("SHA-512/256", NISTObjectIdentifiers.id_sha512_256);
-
- oidMap.put("MD2", PKCSObjectIdentifiers.md2);
- oidMap.put("MD4", PKCSObjectIdentifiers.md4);
- oidMap.put("MD5", PKCSObjectIdentifiers.md5);
- }
-
- public RSADigestSigner(
- Digest digest)
- {
- this(digest, (ASN1ObjectIdentifier)oidMap.get(digest.getAlgorithmName()));
- }
-
- public RSADigestSigner(
- Digest digest,
- ASN1ObjectIdentifier digestOid)
- {
- this.digest = digest;
- this.algId = new AlgorithmIdentifier(digestOid, DERNull.INSTANCE);
- }
-
- /**
- * @deprecated
- */
- public String getAlgorithmName()
- {
- return digest.getAlgorithmName() + "withRSA";
- }
-
- /**
- * initialise the signer for signing or verification.
- *
- * @param forSigning
- * true if for signing, false otherwise
- * @param parameters
- * necessary parameters.
- */
- public void init(
- boolean forSigning,
- CipherParameters parameters)
- {
- this.forSigning = forSigning;
- AsymmetricKeyParameter k;
-
- if (parameters instanceof ParametersWithRandom)
- {
- k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).getParameters();
- }
- else
- {
- k = (AsymmetricKeyParameter)parameters;
- }
-
- if (forSigning && !k.isPrivate())
- {
- throw new IllegalArgumentException("signing requires private key");
- }
-
- if (!forSigning && k.isPrivate())
- {
- throw new IllegalArgumentException("verification requires public key");
- }
-
- reset();
-
- rsaEngine.init(forSigning, parameters);
- }
-
- /**
- * update the internal digest with the byte b
- */
- public void update(
- byte input)
- {
- digest.update(input);
- }
-
- /**
- * update the internal digest with the byte array in
- */
- public void update(
- byte[] input,
- int inOff,
- int length)
- {
- digest.update(input, inOff, length);
- }
-
- /**
- * Generate a signature for the message we've been loaded with using the key
- * we were initialised with.
- */
- public byte[] generateSignature()
- throws CryptoException, DataLengthException
- {
- if (!forSigning)
- {
- throw new IllegalStateException("RSADigestSigner not initialised for signature generation.");
- }
-
- byte[] hash = new byte[digest.getDigestSize()];
- digest.doFinal(hash, 0);
-
- try
- {
- byte[] data = derEncode(hash);
- return rsaEngine.processBlock(data, 0, data.length);
- }
- catch (IOException e)
- {
- throw new CryptoException("unable to encode signature: " + e.getMessage(), e);
- }
- }
-
- /**
- * return true if the internal state represents the signature described in
- * the passed in array.
- */
- public boolean verifySignature(
- byte[] signature)
- {
- if (forSigning)
- {
- throw new IllegalStateException("RSADigestSigner not initialised for verification");
- }
-
- byte[] hash = new byte[digest.getDigestSize()];
-
- digest.doFinal(hash, 0);
-
- byte[] sig;
- byte[] expected;
-
- try
- {
- sig = rsaEngine.processBlock(signature, 0, signature.length);
- expected = derEncode(hash);
- }
- catch (Exception e)
- {
- return false;
- }
-
- if (sig.length == expected.length)
- {
- return Arrays.constantTimeAreEqual(sig, expected);
- }
- else if (sig.length == expected.length - 2) // NULL left out
- {
- int sigOffset = sig.length - hash.length - 2;
- int expectedOffset = expected.length - hash.length - 2;
-
- expected[1] -= 2; // adjust lengths
- expected[3] -= 2;
-
- int nonEqual = 0;
-
- for (int i = 0; i < hash.length; i++)
- {
- nonEqual |= (sig[sigOffset + i] ^ expected[expectedOffset + i]);
- }
-
- for (int i = 0; i < sigOffset; i++)
- {
- nonEqual |= (sig[i] ^ expected[i]); // check header less NULL
- }
-
- return nonEqual == 0;
- }
- else
- {
- return false;
- }
- }
-
- public void reset()
- {
- digest.reset();
- }
-
- private byte[] derEncode(
- byte[] hash)
- throws IOException
- {
- DigestInfo dInfo = new DigestInfo(algId, hash);
-
- return dInfo.getEncoded(ASN1Encoding.DER);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java b/core/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java
deleted file mode 100644
index bbd8cda6..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java
+++ /dev/null
@@ -1,43 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsAgreementCredentials.java b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsAgreementCredentials.java
deleted file mode 100644
index ef7f4fba..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsAgreementCredentials.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-public abstract class AbstractTlsAgreementCredentials
- extends AbstractTlsCredentials
- implements TlsAgreementCredentials
-{
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsCipherFactory.java b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsCipherFactory.java
deleted file mode 100644
index 71a2cab0..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsCipherFactory.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-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/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java
deleted file mode 100644
index 7d4fd033..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java
+++ /dev/null
@@ -1,235 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-import java.util.Hashtable;
-import java.util.Vector;
-
-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;
-
- public AbstractTlsClient()
- {
- this(new DefaultTlsCipherFactory());
- }
-
- public AbstractTlsClient(TlsCipherFactory cipherFactory)
- {
- this.cipherFactory = cipherFactory;
- }
-
- public void init(TlsClientContext context)
- {
- 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
- * version number supported by the client, and the value of ClientHello.client_version. No
- * single value will guarantee interoperability with all old servers, but this is a complex
- * topic beyond the scope of this document."
- */
- public ProtocolVersion getClientHelloRecordLayerVersion()
- {
- // "{03,00}"
- // return ProtocolVersion.SSLv3;
-
- // "the lowest version number supported by the client"
- // return getMinimumVersion();
-
- // "the value of ClientHello.client_version"
- return getClientVersion();
- }
-
- public ProtocolVersion getClientVersion()
- {
- return ProtocolVersion.TLSv12;
- }
-
- public Hashtable getClientExtensions()
- throws IOException
- {
- Hashtable clientExtensions = null;
-
- ProtocolVersion clientVersion = context.getClientVersion();
-
- /*
- * RFC 5246 7.4.1.4.1. Note: this extension is not meaningful for TLS versions prior to 1.2.
- * Clients MUST NOT offer it if they are offering prior versions.
- */
- 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 };
-
- // TODO Sort out ECDSA signatures and add them as the preferred option here
- short[] signatureAlgorithms = new short[]{ SignatureAlgorithm.rsa };
-
- this.supportedSignatureAlgorithms = new Vector();
- for (int i = 0; i < hashAlgorithms.length; ++i)
- {
- for (int j = 0; j < signatureAlgorithms.length; ++j)
- {
- this.supportedSignatureAlgorithms.addElement(new SignatureAndHashAlgorithm(hashAlgorithms[i],
- signatureAlgorithms[j]));
- }
- }
-
- /*
- * RFC 5264 7.4.3. Currently, DSA [DSS] may only be used with SHA-1.
- */
- this.supportedSignatureAlgorithms.addElement(new SignatureAndHashAlgorithm(HashAlgorithm.sha1,
- SignatureAlgorithm.dsa));
-
- 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;
- }
-
- public ProtocolVersion getMinimumVersion()
- {
- return ProtocolVersion.TLSv10;
- }
-
- public void notifyServerVersion(ProtocolVersion serverVersion)
- throws IOException
- {
- if (!getMinimumVersion().isEqualOrEarlierVersionOf(serverVersion))
- {
- throw new TlsFatalAlert(AlertDescription.protocol_version);
- }
- }
-
- public short[] getCompressionMethods()
- {
- return new short[]{CompressionMethod._null};
- }
-
- public void notifySessionID(byte[] sessionID)
- {
- // Currently ignored
- }
-
- public void notifySelectedCipherSuite(int selectedCipherSuite)
- {
- this.selectedCipherSuite = selectedCipherSuite;
- }
-
- public void notifySelectedCompressionMethod(short selectedCompressionMethod)
- {
- this.selectedCompressionMethod = selectedCompressionMethod;
- }
-
- public void processServerExtensions(Hashtable serverExtensions)
- throws IOException
- {
- /*
- * TlsProtocol implementation validates that any server extensions received correspond to
- * client extensions sent. By default, we don't send any, and this method is not called.
- */
- if (serverExtensions != null)
- {
- /*
- * RFC 5246 7.4.1.4.1. Servers MUST NOT send this extension.
- */
- if (serverExtensions.containsKey(TlsUtils.EXT_signature_algorithms))
- {
- 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);
- }
- }
- }
-
- public void processServerSupplementalData(Vector serverSupplementalData)
- throws IOException
- {
- if (serverSupplementalData != null)
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- }
-
- public Vector getClientSupplementalData()
- throws IOException
- {
- return null;
- }
-
- public TlsCompression getCompression()
- throws IOException
- {
- switch (selectedCompressionMethod)
- {
- case CompressionMethod._null:
- return new TlsNullCompression();
-
- default:
- /*
- * Note: internal error here; the TlsProtocol implementation verifies that the
- * server-selected compression method was in the list of client-offered compression
- * methods, so if we now can't produce an implementation, we shouldn't have offered it!
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- public void notifyNewSessionTicket(NewSessionTicket newSessionTicket)
- throws IOException
- {
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsContext.java b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsContext.java
deleted file mode 100644
index 0b9949f9..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsContext.java
+++ /dev/null
@@ -1,133 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.prng.DigestRandomGenerator;
-import org.bouncycastle.crypto.prng.RandomGenerator;
-import org.bouncycastle.util.Times;
-
-abstract class AbstractTlsContext
- implements TlsContext
-{
- private static long counter = Times.nanoTime();
-
- private synchronized static long nextCounterValue()
- {
- return ++counter;
- }
-
- private RandomGenerator nonceRandom;
- 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)
- {
- secureRandom.setSeed(nextCounterValue());
- secureRandom.setSeed(Times.nanoTime());
-
- this.nonceRandom = new DigestRandomGenerator(TlsUtils.createHash(HashAlgorithm.sha256));
- this.nonceRandom.addSeedMaterial(secureRandom.generateSeed(32));
-
- this.secureRandom = secureRandom;
- this.securityParameters = securityParameters;
- }
-
- public RandomGenerator getNonceRandomGenerator()
- {
- return nonceRandom;
- }
-
- public SecureRandom getSecureRandom()
- {
- return secureRandom;
- }
-
- public SecurityParameters getSecurityParameters()
- {
- return securityParameters;
- }
-
- public ProtocolVersion getClientVersion()
- {
- return clientVersion;
- }
-
- void setClientVersion(ProtocolVersion clientVersion)
- {
- this.clientVersion = clientVersion;
- }
-
- public ProtocolVersion getServerVersion()
- {
- return 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;
- }
-
- public void setUserObject(Object userObject)
- {
- this.userObject = userObject;
- }
-
- 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();
-
- int seedLength = cr.length + sr.length;
- if (context_value != null)
- {
- seedLength += (2 + context_value.length);
- }
-
- byte[] seed = new byte[seedLength];
- int seedPos = 0;
-
- System.arraycopy(cr, 0, seed, seedPos, cr.length);
- seedPos += cr.length;
- System.arraycopy(sr, 0, seed, seedPos, sr.length);
- seedPos += sr.length;
- if (context_value != null)
- {
- TlsUtils.writeUint16(context_value.length, seed, seedPos);
- seedPos += 2;
- System.arraycopy(context_value, 0, seed, seedPos, context_value.length);
- seedPos += context_value.length;
- }
-
- if (seedPos != seedLength)
- {
- throw new IllegalStateException("error in calculation of seed for export");
- }
-
- return TlsUtils.PRF(this, sp.getMasterSecret(), asciiLabel, seed, length);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsCredentials.java b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsCredentials.java
deleted file mode 100644
index b98743f3..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsCredentials.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-public abstract class AbstractTlsCredentials
- implements TlsCredentials
-{
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsEncryptionCredentials.java b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsEncryptionCredentials.java
deleted file mode 100644
index e6ff39ba..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsEncryptionCredentials.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-public abstract class AbstractTlsEncryptionCredentials
- extends AbstractTlsCredentials
- implements TlsEncryptionCredentials
-{
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsKeyExchange.java b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsKeyExchange.java
deleted file mode 100644
index 43e80e64..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsKeyExchange.java
+++ /dev/null
@@ -1,166 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Vector;
-
-public abstract class AbstractTlsKeyExchange
- implements TlsKeyExchange
-{
- protected int keyExchange;
- protected Vector supportedSignatureAlgorithms;
-
- protected TlsContext context;
-
- protected AbstractTlsKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms)
- {
- this.keyExchange = keyExchange;
- this.supportedSignatureAlgorithms = supportedSignatureAlgorithms;
- }
-
- public void init(TlsContext context)
- {
- this.context = context;
-
- ProtocolVersion clientVersion = context.getClientVersion();
-
- 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:
- *
- * - If the negotiated key exchange algorithm is one of (RSA, DHE_RSA, DH_RSA, RSA_PSK,
- * ECDH_RSA, ECDHE_RSA), behave as if client had sent the value {sha1,rsa}.
- *
- * - If the negotiated key exchange algorithm is one of (DHE_DSS, DH_DSS), behave as if
- * the client had sent the value {sha1,dsa}.
- *
- * - If the negotiated key exchange algorithm is one of (ECDH_ECDSA, ECDHE_ECDSA),
- * behave as if the client had sent value {sha1,ecdsa}.
- */
- if (this.supportedSignatureAlgorithms == null)
- {
- switch (keyExchange)
- {
- case KeyExchangeAlgorithm.DH_DSS:
- case KeyExchangeAlgorithm.DHE_DSS:
- case KeyExchangeAlgorithm.SRP_DSS:
- {
- this.supportedSignatureAlgorithms = TlsUtils.getDefaultDSSSignatureAlgorithms();
- break;
- }
-
- case KeyExchangeAlgorithm.ECDH_ECDSA:
- case KeyExchangeAlgorithm.ECDHE_ECDSA:
- {
- this.supportedSignatureAlgorithms = TlsUtils.getDefaultECDSASignatureAlgorithms();
- break;
- }
-
- case KeyExchangeAlgorithm.DH_RSA:
- case KeyExchangeAlgorithm.DHE_RSA:
- case KeyExchangeAlgorithm.ECDH_RSA:
- case KeyExchangeAlgorithm.ECDHE_RSA:
- case KeyExchangeAlgorithm.RSA:
- case KeyExchangeAlgorithm.RSA_PSK:
- case KeyExchangeAlgorithm.SRP_RSA:
- {
- this.supportedSignatureAlgorithms = TlsUtils.getDefaultRSASignatureAlgorithms();
- break;
- }
-
- case KeyExchangeAlgorithm.DHE_PSK:
- case KeyExchangeAlgorithm.ECDHE_PSK:
- case KeyExchangeAlgorithm.PSK:
- case KeyExchangeAlgorithm.SRP:
- break;
-
- default:
- throw new IllegalStateException("unsupported key exchange algorithm");
- }
- }
-
- }
- else if (this.supportedSignatureAlgorithms != null)
- {
- throw new IllegalStateException("supported_signature_algorithms not allowed for " + clientVersion);
- }
- }
-
- public void processServerCertificate(Certificate serverCertificate)
- throws IOException
- {
- if (supportedSignatureAlgorithms == null)
- {
- /*
- * TODO RFC 2264 7.4.2. Unless otherwise specified, the signing algorithm for the
- * certificate must be the same as the algorithm for the certificate key.
- */
- }
- else
- {
- /*
- * TODO RFC 5264 7.4.2. If the client provided a "signature_algorithms" extension, then
- * all certificates provided by the server MUST be signed by a hash/signature algorithm
- * pair that appears in that extension.
- */
- }
- }
-
- public void processServerCredentials(TlsCredentials serverCredentials)
- throws IOException
- {
- processServerCertificate(serverCredentials.getCertificate());
- }
-
- public boolean requiresServerKeyExchange()
- {
- return false;
- }
-
- public byte[] generateServerKeyExchange()
- throws IOException
- {
- if (requiresServerKeyExchange())
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- return null;
- }
-
- public void skipServerKeyExchange()
- throws IOException
- {
- if (requiresServerKeyExchange())
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- }
-
- public void processServerKeyExchange(InputStream input)
- throws IOException
- {
- if (!requiresServerKeyExchange())
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- }
-
- public void skipClientCredentials()
- throws IOException
- {
- }
-
- public void processClientCertificate(Certificate clientCertificate)
- throws IOException
- {
- }
-
- public void processClientKeyExchange(InputStream input)
- throws IOException
- {
- // Key exchange implementation MUST support client key exchange
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsPeer.java b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsPeer.java
deleted file mode 100644
index 26ad6d34..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsPeer.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-public abstract class AbstractTlsPeer
- implements TlsPeer
-{
- public boolean shouldUseGMTUnixTime()
- {
- /*
- * draft-mathewson-no-gmtunixtime-00 2. For the reasons we discuss above, we recommend that
- * TLS implementors MUST by default set the entire value the ClientHello.Random and
- * ServerHello.Random fields, including gmt_unix_time, to a cryptographically random
- * sequence.
- */
- return false;
- }
-
- 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)
- {
- }
-
- public void notifyAlertReceived(short alertLevel, short alertDescription)
- {
- }
-
- public void notifyHandshakeComplete() throws IOException
- {
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsServer.java b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsServer.java
deleted file mode 100644
index dd5c4409..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsServer.java
+++ /dev/null
@@ -1,335 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-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;
-
- protected ProtocolVersion clientVersion;
- protected int[] offeredCipherSuites;
- protected short[] offeredCompressionMethods;
- protected Hashtable clientExtensions;
-
- protected boolean encryptThenMACOffered;
- protected short maxFragmentLengthOffered;
- protected boolean truncatedHMacOffered;
- protected Vector supportedSignatureAlgorithms;
- protected boolean eccCipherSuitesOffered;
- protected int[] namedCurves;
- protected short[] clientECPointFormats, serverECPointFormats;
-
- protected ProtocolVersion serverVersion;
- protected int selectedCipherSuite;
- protected short selectedCompressionMethod;
- protected Hashtable serverExtensions;
-
- public AbstractTlsServer()
- {
- this(new DefaultTlsCipherFactory());
- }
-
- public AbstractTlsServer(TlsCipherFactory cipherFactory)
- {
- this.cipherFactory = cipherFactory;
- }
-
- protected boolean allowEncryptThenMAC()
- {
- return true;
- }
-
- protected boolean allowTruncatedHMac()
- {
- return false;
- }
-
- protected Hashtable checkServerExtensions()
- {
- return this.serverExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(this.serverExtensions);
- }
-
- protected abstract int[] getCipherSuites();
-
- protected short[] getCompressionMethods()
- {
- return new short[]{CompressionMethod._null};
- }
-
- protected ProtocolVersion getMaximumVersion()
- {
- return ProtocolVersion.TLSv11;
- }
-
- protected ProtocolVersion getMinimumVersion()
- {
- return ProtocolVersion.TLSv10;
- }
-
- 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)
- {
- /*
- * RFC 4492 4. A client that proposes ECC cipher suites may choose not to include these
- * extensions. In this case, the server is free to choose any one of the elliptic curves
- * or point formats [...].
- */
- return TlsECCUtils.hasAnySupportedNamedCurves();
- }
-
- for (int i = 0; i < namedCurves.length; ++i)
- {
- int namedCurve = namedCurves[i];
- if (NamedCurve.isValid(namedCurve)
- && (!NamedCurve.refersToASpecificNamedCurve(namedCurve) || TlsECCUtils.isSupportedNamedCurve(namedCurve)))
- {
- return true;
- }
- }
-
- return false;
- }
-
- public void init(TlsServerContext context)
- {
- this.context = context;
- }
-
- public void notifyClientVersion(ProtocolVersion clientVersion)
- throws IOException
- {
- this.clientVersion = clientVersion;
- }
-
- public void notifyOfferedCipherSuites(int[] offeredCipherSuites)
- throws IOException
- {
- this.offeredCipherSuites = offeredCipherSuites;
- this.eccCipherSuitesOffered = TlsECCUtils.containsECCCipherSuites(this.offeredCipherSuites);
- }
-
- public void notifyOfferedCompressionMethods(short[] offeredCompressionMethods)
- throws IOException
- {
- this.offeredCompressionMethods = offeredCompressionMethods;
- }
-
- public void processClientExtensions(Hashtable clientExtensions)
- throws IOException
- {
- this.clientExtensions = clientExtensions;
-
- if (clientExtensions != null)
- {
- this.encryptThenMACOffered = TlsExtensionsUtils.hasEncryptThenMACExtension(clientExtensions);
- this.maxFragmentLengthOffered = TlsExtensionsUtils.getMaxFragmentLengthExtension(clientExtensions);
- this.truncatedHMacOffered = TlsExtensionsUtils.hasTruncatedHMacExtension(clientExtensions);
-
- this.supportedSignatureAlgorithms = TlsUtils.getSignatureAlgorithmsExtension(clientExtensions);
- if (this.supportedSignatureAlgorithms != null)
- {
- /*
- * RFC 5246 7.4.1.4.1. Note: this extension is not meaningful for TLS versions prior
- * to 1.2. Clients MUST NOT offer it if they are offering prior versions.
- */
- if (!TlsUtils.isSignatureAlgorithmsExtensionAllowed(clientVersion))
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- }
-
- this.namedCurves = TlsECCUtils.getSupportedEllipticCurvesExtension(clientExtensions);
- this.clientECPointFormats = TlsECCUtils.getSupportedPointFormatsExtension(clientExtensions);
- }
-
- /*
- * RFC 4429 4. The client MUST NOT include these extensions in the ClientHello message if it
- * does not propose any ECC cipher suites.
- */
- if (!this.eccCipherSuitesOffered && (this.namedCurves != null || this.clientECPointFormats != null))
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- }
-
- public ProtocolVersion getServerVersion()
- throws IOException
- {
- if (getMinimumVersion().isEqualOrEarlierVersionOf(clientVersion))
- {
- ProtocolVersion maximumVersion = getMaximumVersion();
- if (clientVersion.isEqualOrEarlierVersionOf(maximumVersion))
- {
- return serverVersion = clientVersion;
- }
- if (clientVersion.isLaterVersionOf(maximumVersion))
- {
- return serverVersion = maximumVersion;
- }
- }
- throw new TlsFatalAlert(AlertDescription.protocol_version);
- }
-
- 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
- * somewhat inelegant but is a compromise designed to minimize changes to the original
- * cipher suite design.
- */
-
- /*
- * RFC 4429 5.1. A server that receives a ClientHello containing one or both of these
- * extensions MUST use the client's enumerated capabilities to guide its selection of an
- * appropriate cipher suite. One of the proposed ECC cipher suites must be negotiated only
- * if the server can successfully complete the handshake while using the curves and point
- * formats supported by the client [...].
- */
- boolean eccCipherSuitesEnabled = supportsClientECCCapabilities(this.namedCurves, this.clientECPointFormats);
-
- int[] cipherSuites = getCipherSuites();
- for (int i = 0; i < cipherSuites.length; ++i)
- {
- int cipherSuite = cipherSuites[i];
-
- if (Arrays.contains(this.offeredCipherSuites, cipherSuite)
- && (eccCipherSuitesEnabled || !TlsECCUtils.isECCCipherSuite(cipherSuite))
- && TlsUtils.isValidCipherSuiteForVersion(cipherSuite, serverVersion))
- {
- return this.selectedCipherSuite = cipherSuite;
- }
- }
- throw new TlsFatalAlert(AlertDescription.handshake_failure);
- }
-
- public short getSelectedCompressionMethod()
- throws IOException
- {
- short[] compressionMethods = getCompressionMethods();
- for (int i = 0; i < compressionMethods.length; ++i)
- {
- if (Arrays.contains(offeredCompressionMethods, compressionMethods[i]))
- {
- return this.selectedCompressionMethod = compressionMethods[i];
- }
- }
- throw new TlsFatalAlert(AlertDescription.handshake_failure);
- }
-
- // Hashtable is (Integer -> byte[])
- public Hashtable getServerExtensions()
- throws IOException
- {
- if (this.encryptThenMACOffered && allowEncryptThenMAC())
- {
- /*
- * draft-ietf-tls-encrypt-then-mac-03 3. If a server receives an encrypt-then-MAC
- * request extension from a client and then selects a stream or AEAD cipher suite, it
- * MUST NOT send an encrypt-then-MAC response extension back to the client.
- */
- if (TlsUtils.isBlockCipherSuite(this.selectedCipherSuite))
- {
- TlsExtensionsUtils.addEncryptThenMACExtension(checkServerExtensions());
- }
- }
-
- if (this.maxFragmentLengthOffered >= 0)
- {
- TlsExtensionsUtils.addMaxFragmentLengthExtension(checkServerExtensions(), this.maxFragmentLengthOffered);
- }
-
- if (this.truncatedHMacOffered && allowTruncatedHMac())
- {
- TlsExtensionsUtils.addTruncatedHMacExtension(checkServerExtensions());
- }
-
- if (this.clientECPointFormats != null && TlsECCUtils.isECCCipherSuite(this.selectedCipherSuite))
- {
- /*
- * RFC 4492 5.2. A server that selects an ECC cipher suite in response to a ClientHello
- * 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.uncompressed,
- ECPointFormat.ansiX962_compressed_prime, ECPointFormat.ansiX962_compressed_char2, };
-
- TlsECCUtils.addSupportedPointFormatsExtension(checkServerExtensions(), serverECPointFormats);
- }
-
- return serverExtensions;
- }
-
- public Vector getServerSupplementalData()
- throws IOException
- {
- return null;
- }
-
- public CertificateStatus getCertificateStatus()
- throws IOException
- {
- return null;
- }
-
- public CertificateRequest getCertificateRequest()
- throws IOException
- {
- return null;
- }
-
- public void processClientSupplementalData(Vector clientSupplementalData)
- throws IOException
- {
- if (clientSupplementalData != null)
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- }
-
- public void notifyClientCertificate(Certificate clientCertificate)
- throws IOException
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- public TlsCompression getCompression()
- throws IOException
- {
- switch (selectedCompressionMethod)
- {
- case CompressionMethod._null:
- return new TlsNullCompression();
-
- default:
- /*
- * Note: internal error here; we selected the compression method, so if we now can't
- * produce an implementation, we shouldn't have chosen it!
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- public NewSessionTicket getNewSessionTicket()
- throws IOException
- {
- /*
- * RFC 5077 3.3. If the server determines that it does not want to include a ticket after it
- * has included the SessionTicket extension in the ServerHello, then it sends a zero-length
- * ticket in the NewSessionTicket handshake message.
- */
- return new NewSessionTicket(0L, TlsUtils.EMPTY_BYTES);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsSigner.java b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsSigner.java
deleted file mode 100644
index 3a1d6319..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsSigner.java
+++ /dev/null
@@ -1,38 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsSignerCredentials.java b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsSignerCredentials.java
deleted file mode 100644
index 3452f527..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsSignerCredentials.java
+++ /dev/null
@@ -1,11 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/tls/AlertDescription.java b/core/src/main/java/org/bouncycastle/crypto/tls/AlertDescription.java
deleted file mode 100644
index 91366be0..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/AlertDescription.java
+++ /dev/null
@@ -1,216 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 5246 7.2.
- */
-public class AlertDescription
-{
- /**
- * This message notifies the recipient that the sender will not send any more messages on this
- * 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;
-
- /**
- * An inappropriate message was received. This alert is always fatal and should never be
- * observed in communication between proper implementations.
- */
- public static final short unexpected_message = 10;
-
- /**
- * This alert is returned if a record is received with an incorrect MAC. This alert also MUST be
- * returned if an alert is sent because a TLSCiphertext decrypted in an invalid way: either it
- * wasn't an even multiple of the block length, or its padding values, when checked, weren't
- * correct. This message is always fatal and should never be observed in communication between
- * proper implementations (except when messages were corrupted in the network).
- */
- public static final short bad_record_mac = 20;
-
- /**
- * This alert was used in some earlier versions of TLS, and may have permitted certain attacks
- * against the CBC mode [CBCATT]. It MUST NOT be sent by compliant implementations.
- */
- public static final short decryption_failed = 21;
-
- /**
- * A TLSCiphertext record was received that had a length more than 2^14+2048 bytes, or a record
- * decrypted to a TLSCompressed record with more than 2^14+1024 bytes. This message is always
- * fatal and should never be observed in communication between proper implementations (except
- * when messages were corrupted in the network).
- */
- public static final short record_overflow = 22;
-
- /**
- * The decompression function received improper input (e.g., data that would expand to excessive
- * length). This message is always fatal and should never be observed in communication between
- * proper implementations.
- */
- public static final short decompression_failure = 30;
-
- /**
- * Reception of a handshake_failure alert message indicates that the sender was unable to
- * negotiate an acceptable set of security parameters given the options available. This is a
- * fatal error.
- */
- public static final short handshake_failure = 40;
-
- /**
- * This alert was used in SSLv3 but not any version of TLS. It MUST NOT be sent by compliant
- * implementations.
- */
- public static final short no_certificate = 41;
-
- /**
- * A certificate was corrupt, contained signatures that did not verify correctly, etc.
- */
- public static final short bad_certificate = 42;
-
- /**
- * A certificate was of an unsupported type.
- */
- public static final short unsupported_certificate = 43;
-
- /**
- * A certificate was revoked by its signer.
- */
- public static final short certificate_revoked = 44;
-
- /**
- * A certificate has expired or is not currently valid.
- */
- public static final short certificate_expired = 45;
-
- /**
- * Some other (unspecified) issue arose in processing the certificate, rendering it
- * unacceptable.
- */
- public static final short certificate_unknown = 46;
-
- /**
- * A field in the handshake was out of range or inconsistent with other fields. This message is
- * always fatal.
- */
- public static final short illegal_parameter = 47;
-
- /**
- * A valid certificate chain or partial chain was received, but the certificate was not accepted
- * because the CA certificate could not be located or couldn't be matched with a known, trusted
- * CA. This message is always fatal.
- */
- public static final short unknown_ca = 48;
-
- /**
- * A valid certificate was received, but when access control was applied, the sender decided not
- * to proceed with negotiation. This message is always fatal.
- */
- public static final short access_denied = 49;
-
- /**
- * A message could not be decoded because some field was out of the specified range or the
- * length of the message was incorrect. This message is always fatal and should never be
- * observed in communication between proper implementations (except when messages were corrupted
- * in the network).
- */
- public static final short decode_error = 50;
-
- /**
- * A handshake cryptographic operation failed, including being unable to correctly verify a
- * signature or validate a Finished message. This message is always fatal.
- */
- public static final short decrypt_error = 51;
-
- /**
- * This alert was used in some earlier versions of TLS. It MUST NOT be sent by compliant
- * implementations.
- */
- public static final short export_restriction = 60;
-
- /**
- * The protocol version the client has attempted to negotiate is recognized but not supported.
- * (For example, old protocol versions might be avoided for security reasons.) This message is
- * always fatal.
- */
- public static final short protocol_version = 70;
-
- /**
- * Returned instead of handshake_failure when a negotiation has failed specifically because the
- * server requires ciphers more secure than those supported by the client. This message is
- * always fatal.
- */
- public static final short insufficient_security = 71;
-
- /**
- * An internal error unrelated to the peer or the correctness of the protocol (such as a memory
- * allocation failure) makes it impossible to continue. This message is always fatal.
- */
- public static final short internal_error = 80;
-
- /**
- * This handshake is being canceled for some reason unrelated to a protocol failure. If the user
- * cancels an operation after the handshake is complete, just closing the connection by sending
- * a close_notify is more appropriate. This alert should be followed by a close_notify. This
- * message is generally a warning.
- */
- public static final short user_canceled = 90;
-
- /**
- * Sent by the client in response to a hello request or by the server in response to a client
- * hello after initial handshaking. Either of these would normally lead to renegotiation; when
- * that is not appropriate, the recipient should respond with this alert. At that point, the
- * original requester can decide whether to proceed with the connection. One case where this
- * would be appropriate is where a server has spawned a process to satisfy a request; the
- * process might receive security parameters (key length, authentication, etc.) at startup, and
- * it might be difficult to communicate changes to these parameters after that point. This
- * message is always a warning.
- */
- public static final short no_renegotiation = 100;
-
- /**
- * Sent by clients that receive an extended server hello containing an extension that they did
- * not put in the corresponding client hello. This message is always fatal.
- */
- public static final short unsupported_extension = 110;
-
- /*
- * RFC 3546
- */
-
- /**
- * This alert is sent by servers who are unable to retrieve a certificate chain from the URL
- * supplied by the client (see Section 3.3). This message MAY be fatal - for example if client
- * authentication is required by the server for the handshake to continue and the server is
- * unable to retrieve the certificate chain, it may send a fatal alert.
- */
- public static final short certificate_unobtainable = 111;
-
- /**
- * This alert is sent by servers that receive a server_name extension request, but do not
- * recognize the server name. This message MAY be fatal.
- */
- public static final short unrecognized_name = 112;
-
- /**
- * This alert is sent by clients that receive an invalid certificate status response (see
- * Section 3.6). This message is always fatal.
- */
- public static final short bad_certificate_status_response = 113;
-
- /**
- * This alert is sent by servers when a certificate hash does not match a client provided
- * certificate_hash. This message is always fatal.
- */
- public static final short bad_certificate_hash_value = 114;
-
- /*
- * RFC 4279
- */
-
- /**
- * If the server does not recognize the PSK identity, it MAY respond with an
- * "unknown_psk_identity" alert message.
- */
- public static final short unknown_psk_identity = 115;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/AlertLevel.java b/core/src/main/java/org/bouncycastle/crypto/tls/AlertLevel.java
deleted file mode 100644
index 53e843a4..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/AlertLevel.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 5246 7.2
- */
-public class AlertLevel
-{
- public static final short warning = 1;
- public static final short fatal = 2;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/AlwaysValidVerifyer.java b/core/src/main/java/org/bouncycastle/crypto/tls/AlwaysValidVerifyer.java
deleted file mode 100644
index 961408ae..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/AlwaysValidVerifyer.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * A certificate verifyer, that will always return true.
- * <pre>
- * DO NOT USE THIS FILE UNLESS YOU KNOW EXACTLY WHAT YOU ARE DOING.
- * </pre>
- *
- * @deprecated Perform certificate verification in TlsAuthentication implementation
- */
-public class AlwaysValidVerifyer
- implements CertificateVerifyer
-{
- /**
- * Return true.
- *
- * @see org.bouncycastle.crypto.tls.CertificateVerifyer#isValid(org.bouncycastle.asn1.x509.Certificate[])
- */
- public boolean isValid(org.bouncycastle.asn1.x509.Certificate[] certs)
- {
- return true;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/BulkCipherAlgorithm.java b/core/src/main/java/org/bouncycastle/crypto/tls/BulkCipherAlgorithm.java
deleted file mode 100644
index 7f013b3a..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/BulkCipherAlgorithm.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 2246
- * <p>
- * Note that the values here are implementation-specific and arbitrary. It is recommended not to
- * depend on the particular values (e.g. serialization).
- */
-public class BulkCipherAlgorithm
-{
- public static final int _null = 0;
- public static final int rc4 = 1;
- public static final int rc2 = 2;
- public static final int des = 3;
- public static final int _3des = 4;
- public static final int des40 = 5;
-
- /*
- * RFC 4346
- */
- public static final int aes = 6;
- public static final int idea = 7;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/ByteQueue.java b/core/src/main/java/org/bouncycastle/crypto/tls/ByteQueue.java
deleted file mode 100644
index 560ea459..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/ByteQueue.java
+++ /dev/null
@@ -1,153 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * A queue for bytes. This file could be more optimized.
- */
-public class ByteQueue
-{
- /**
- * @return The smallest number which can be written as 2^x which is bigger than i.
- */
- public static int nextTwoPow(int i)
- {
- /*
- * This code is based of a lot of code I found on the Internet which mostly
- * referenced a book called "Hacking delight".
- */
- i |= (i >> 1);
- i |= (i >> 2);
- i |= (i >> 4);
- i |= (i >> 8);
- i |= (i >> 16);
- return i + 1;
- }
-
- /**
- * The initial size for our buffer.
- */
- private static final int DEFAULT_CAPACITY = 1024;
-
- /**
- * The buffer where we store our data.
- */
- private byte[] databuf;
-
- /**
- * How many bytes at the beginning of the buffer are skipped.
- */
- private int skipped = 0;
-
- /**
- * How many bytes in the buffer are valid data.
- */
- private int available = 0;
-
- public ByteQueue()
- {
- this(DEFAULT_CAPACITY);
- }
-
- public ByteQueue(int capacity)
- {
- databuf = new byte[capacity];
- }
-
- /**
- * Read data from the buffer.
- *
- * @param buf The buffer where the read data will be copied to.
- * @param offset 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 read(byte[] buf, int offset, int len, int skip)
- {
- if ((buf.length - offset) < len)
- {
- throw new IllegalArgumentException("Buffer size of " + buf.length
- + " is too small for a read of " + len + " bytes");
- }
- if ((available - skip) < len)
- {
- throw new IllegalStateException("Not enough data to read");
- }
- System.arraycopy(databuf, skipped + skip, buf, offset, len);
- }
-
- /**
- * Add some data to our buffer.
- *
- * @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[] buf, int off, int len)
- {
- if ((skipped + available + len) > databuf.length)
- {
- 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;
- }
-
- System.arraycopy(buf, off, databuf, skipped + available, len);
- available += len;
- }
-
- /**
- * Remove some bytes from our data from the beginning.
- *
- * @param i How many bytes to remove.
- */
- public void removeData(int i)
- {
- if (i > available)
- {
- throw new IllegalStateException("Cannot remove " + i + " bytes, only got " + available);
- }
-
- /*
- * Skip the data.
- */
- available -= i;
- skipped += i;
- }
-
- /**
- * 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;
- }
-
- /**
- * @return The number of bytes which are available in this buffer.
- */
- public int size()
- {
- return available;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/CertChainType.java b/core/src/main/java/org/bouncycastle/crypto/tls/CertChainType.java
deleted file mode 100644
index 8902ed79..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/CertChainType.java
+++ /dev/null
@@ -1,15 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/tls/Certificate.java b/core/src/main/java/org/bouncycastle/crypto/tls/Certificate.java
deleted file mode 100644
index 33a6edd4..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/Certificate.java
+++ /dev/null
@@ -1,148 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.ByteArrayInputStream;
-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.ASN1Primitive;
-
-/**
- * Parsing and encoding of a <i>Certificate</i> struct from RFC 4346.
- * <pre>
- * opaque ASN.1Cert&lt;2^24-1&gt;;
- *
- * struct {
- * ASN.1Cert certificate_list&lt;0..2^24-1&gt;;
- * } Certificate;
- * </pre>
- *
- * @see org.bouncycastle.asn1.x509.Certificate
- */
-public class Certificate
-{
- public static final Certificate EMPTY_CHAIN = new Certificate(
- new org.bouncycastle.asn1.x509.Certificate[0]);
-
- protected org.bouncycastle.asn1.x509.Certificate[] certificateList;
-
- public Certificate(org.bouncycastle.asn1.x509.Certificate[] certificateList)
- {
- if (certificateList == null)
- {
- throw new IllegalArgumentException("'certificateList' cannot be null");
- }
-
- this.certificateList = certificateList;
- }
-
- /**
- * @deprecated use {@link #getCertificateList()} instead
- */
- public org.bouncycastle.asn1.x509.Certificate[] getCerts()
- {
- return getCertificateList();
- }
-
- /**
- * @return an array of {@link org.bouncycastle.asn1.x509.Certificate} representing a certificate
- * chain.
- */
- public org.bouncycastle.asn1.x509.Certificate[] getCertificateList()
- {
- return cloneCertificateList();
- }
-
- public org.bouncycastle.asn1.x509.Certificate getCertificateAt(int index)
- {
- return certificateList[index];
- }
-
- public int getLength()
- {
- return certificateList.length;
- }
-
- /**
- * @return <code>true</code> if this certificate chain contains no certificates, or
- * <code>false</code> otherwise.
- */
- public boolean isEmpty()
- {
- return certificateList.length == 0;
- }
-
- /**
- * Encode this {@link Certificate} to an {@link OutputStream}.
- *
- * @param output the {@link OutputStream} to encode to.
- * @throws IOException
- */
- public void encode(OutputStream output)
- throws IOException
- {
- Vector derEncodings = new Vector(this.certificateList.length);
-
- int totalLength = 0;
- for (int i = 0; i < this.certificateList.length; ++i)
- {
- 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 < derEncodings.size(); ++i)
- {
- byte[] derEncoding = (byte[])derEncodings.elementAt(i);
- TlsUtils.writeOpaque24(derEncoding, output);
- }
- }
-
- /**
- * Parse a {@link Certificate} from an {@link InputStream}.
- *
- * @param input the {@link InputStream} to parse from.
- * @return a {@link Certificate} object.
- * @throws IOException
- */
- public static Certificate parse(InputStream input)
- throws IOException
- {
- int totalLength = TlsUtils.readUint24(input);
- if (totalLength == 0)
- {
- return EMPTY_CHAIN;
- }
-
- byte[] certListData = TlsUtils.readFully(totalLength, input);
-
- ByteArrayInputStream buf = new ByteArrayInputStream(certListData);
-
- 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));
- }
-
- org.bouncycastle.asn1.x509.Certificate[] certificateList = new org.bouncycastle.asn1.x509.Certificate[certificate_list.size()];
- for (int i = 0; i < certificate_list.size(); i++)
- {
- certificateList[i] = (org.bouncycastle.asn1.x509.Certificate)certificate_list.elementAt(i);
- }
- return new Certificate(certificateList);
- }
-
- protected org.bouncycastle.asn1.x509.Certificate[] cloneCertificateList()
- {
- 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/core/src/main/java/org/bouncycastle/crypto/tls/CertificateRequest.java b/core/src/main/java/org/bouncycastle/crypto/tls/CertificateRequest.java
deleted file mode 100644
index 68e051ea..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/CertificateRequest.java
+++ /dev/null
@@ -1,158 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.ByteArrayInputStream;
-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.ASN1Primitive;
-import org.bouncycastle.asn1.x500.X500Name;
-
-/**
- * Parsing and encoding of a <i>CertificateRequest</i> struct from RFC 4346.
- * <pre>
- * struct {
- * ClientCertificateType certificate_types&lt;1..2^8-1&gt;;
- * DistinguishedName certificate_authorities&lt;3..2^16-1&gt;;
- * } CertificateRequest;
- * </pre>
- *
- * @see ClientCertificateType
- * @see X500Name
- */
-public class CertificateRequest
-{
- protected short[] certificateTypes;
- protected Vector supportedSignatureAlgorithms;
- protected Vector certificateAuthorities;
-
- /**
- * @param certificateTypes see {@link ClientCertificateType} for valid constants.
- * @param certificateAuthorities a {@link Vector} of {@link X500Name}.
- */
- public CertificateRequest(short[] certificateTypes, Vector supportedSignatureAlgorithms, Vector certificateAuthorities)
- {
- this.certificateTypes = certificateTypes;
- this.supportedSignatureAlgorithms = supportedSignatureAlgorithms;
- this.certificateAuthorities = certificateAuthorities;
- }
-
- /**
- * @return an array of certificate types
- * @see ClientCertificateType
- */
- public short[] getCertificateTypes()
- {
- return certificateTypes;
- }
-
- /**
- * @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()
- {
- return certificateAuthorities;
- }
-
- /**
- * Encode this {@link CertificateRequest} to an {@link OutputStream}.
- *
- * @param output the {@link OutputStream} to encode to.
- * @throws IOException
- */
- public void encode(OutputStream output)
- throws IOException
- {
- if (certificateTypes == null || certificateTypes.length == 0)
- {
- TlsUtils.writeUint8(0, output);
- }
- else
- {
- 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())
- {
- TlsUtils.writeUint16(0, output);
- }
- else
- {
- Vector derEncodings = new Vector(certificateAuthorities.size());
-
- int totalLength = 0;
- for (int i = 0; i < certificateAuthorities.size(); ++i)
- {
- X500Name certificateAuthority = (X500Name)certificateAuthorities.elementAt(i);
- byte[] derEncoding = certificateAuthority.getEncoded(ASN1Encoding.DER);
- derEncodings.addElement(derEncoding);
- totalLength += derEncoding.length + 2;
- }
-
- TlsUtils.checkUint16(totalLength);
- TlsUtils.writeUint16(totalLength, output);
-
- for (int i = 0; i < derEncodings.size(); ++i)
- {
- byte[] derEncoding = (byte[])derEncodings.elementAt(i);
- TlsUtils.writeOpaque16(derEncoding, output);
- }
- }
- }
-
- /**
- * Parse a {@link CertificateRequest} from an {@link InputStream}.
- *
- * @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(TlsContext context, InputStream input)
- throws IOException
- {
- int numTypes = TlsUtils.readUint8(input);
- short[] certificateTypes = new short[numTypes];
- for (int i = 0; i < numTypes; ++i)
- {
- certificateTypes[i] = TlsUtils.readUint8(input);
- }
-
- Vector supportedSignatureAlgorithms = null;
- if (TlsUtils.isTLSv12(context))
- {
- // TODO Check whether SignatureAlgorithm.anonymous is allowed here
- supportedSignatureAlgorithms = TlsUtils.parseSupportedSignatureAlgorithms(false, input);
- }
-
- Vector certificateAuthorities = new Vector();
- byte[] certAuthData = TlsUtils.readOpaque16(input);
- ByteArrayInputStream bis = new ByteArrayInputStream(certAuthData);
- while (bis.available() > 0)
- {
- byte[] derEncoding = TlsUtils.readOpaque16(bis);
- ASN1Primitive asn1 = TlsUtils.readDERObject(derEncoding);
- certificateAuthorities.addElement(X500Name.getInstance(asn1));
- }
-
- return new CertificateRequest(certificateTypes, supportedSignatureAlgorithms, certificateAuthorities);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/CertificateStatus.java b/core/src/main/java/org/bouncycastle/crypto/tls/CertificateStatus.java
deleted file mode 100644
index 34a0284a..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/CertificateStatus.java
+++ /dev/null
@@ -1,105 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/tls/CertificateStatusRequest.java b/core/src/main/java/org/bouncycastle/crypto/tls/CertificateStatusRequest.java
deleted file mode 100644
index b947c488..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/CertificateStatusRequest.java
+++ /dev/null
@@ -1,98 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/tls/CertificateStatusType.java b/core/src/main/java/org/bouncycastle/crypto/tls/CertificateStatusType.java
deleted file mode 100644
index bfe82981..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/CertificateStatusType.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-public class CertificateStatusType
-{
- /*
- * RFC 3546 3.6
- */
- public static final short ocsp = 1;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/CertificateURL.java b/core/src/main/java/org/bouncycastle/crypto/tls/CertificateURL.java
deleted file mode 100644
index aab89087..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/CertificateURL.java
+++ /dev/null
@@ -1,133 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/tls/CertificateVerifyer.java b/core/src/main/java/org/bouncycastle/crypto/tls/CertificateVerifyer.java
deleted file mode 100644
index 2e3715c1..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/CertificateVerifyer.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * This should be implemented by any class which can find out, if a given certificate
- * chain is being accepted by an client.
- *
- * @deprecated Perform certificate verification in TlsAuthentication implementation
- */
-public interface CertificateVerifyer
-{
- /**
- * @param certs The certs, which are part of the chain.
- * @return True, if the chain is accepted, false otherwise.
- */
- public boolean isValid(org.bouncycastle.asn1.x509.Certificate[] certs);
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/Chacha20Poly1305.java b/core/src/main/java/org/bouncycastle/crypto/tls/Chacha20Poly1305.java
deleted file mode 100644
index a82045bf..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/Chacha20Poly1305.java
+++ /dev/null
@@ -1,156 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.engines.ChaChaEngine;
-import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
-import org.bouncycastle.crypto.macs.Poly1305;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Pack;
-
-public class Chacha20Poly1305 implements TlsCipher
-{
- protected TlsContext context;
-
- protected ChaChaEngine encryptCipher;
- protected ChaChaEngine decryptCipher;
-
- public Chacha20Poly1305(TlsContext context) throws IOException
- {
- if (!TlsUtils.isTLSv12(context))
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- this.context = context;
-
- byte[] key_block = TlsUtils.calculateKeyBlock(context, 64);
-
- KeyParameter client_write_key = new KeyParameter(key_block, 0, 32);
- KeyParameter server_write_key = new KeyParameter(key_block, 32, 32);
-
- this.encryptCipher = new ChaChaEngine(20);
- this.decryptCipher = new ChaChaEngine(20);
-
- KeyParameter encryptKey, decryptKey;
- if (context.isServer())
- {
- encryptKey = server_write_key;
- decryptKey = client_write_key;
- }
- else
- {
- encryptKey = client_write_key;
- decryptKey = server_write_key;
- }
-
- byte[] dummyNonce = new byte[8];
-
- this.encryptCipher.init(true, new ParametersWithIV(encryptKey, dummyNonce));
- this.decryptCipher.init(false, new ParametersWithIV(decryptKey, dummyNonce));
- }
-
- public int getPlaintextLimit(int ciphertextLimit)
- {
- return ciphertextLimit - 16;
- }
-
- public byte[] encodePlaintext(long seqNo, short type, byte[] plaintext, int offset, int len) throws IOException
- {
- int ciphertextLength = len + 16;
-
- KeyParameter macKey = initRecordMAC(encryptCipher, true, seqNo);
-
- byte[] output = new byte[ciphertextLength];
- encryptCipher.processBytes(plaintext, offset, len, output, 0);
-
- byte[] additionalData = getAdditionalData(seqNo, type, len);
- byte[] mac = calculateRecordMAC(macKey, additionalData, output, 0, len);
- System.arraycopy(mac, 0, output, len, mac.length);
-
- return output;
- }
-
- 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);
- }
-
- int plaintextLength = len - 16;
-
- byte[] receivedMAC = Arrays.copyOfRange(ciphertext, offset + plaintextLength, offset + len);
-
- KeyParameter macKey = initRecordMAC(decryptCipher, false, seqNo);
-
- byte[] additionalData = getAdditionalData(seqNo, type, plaintextLength);
- byte[] calculatedMAC = calculateRecordMAC(macKey, additionalData, ciphertext, offset, plaintextLength);
-
- if (!Arrays.constantTimeAreEqual(calculatedMAC, receivedMAC))
- {
- throw new TlsFatalAlert(AlertDescription.bad_record_mac);
- }
-
- byte[] output = new byte[plaintextLength];
- decryptCipher.processBytes(ciphertext, offset, plaintextLength, output, 0);
-
- return output;
- }
-
- protected KeyParameter initRecordMAC(ChaChaEngine cipher, boolean forEncryption, long seqNo)
- {
- byte[] nonce = new byte[8];
- TlsUtils.writeUint64(seqNo, nonce, 0);
-
- cipher.init(forEncryption, new ParametersWithIV(null, nonce));
-
- byte[] firstBlock = new byte[64];
- cipher.processBytes(firstBlock, 0, firstBlock.length, firstBlock, 0);
-
- // NOTE: The BC implementation puts 'r' after 'k'
- System.arraycopy(firstBlock, 0, firstBlock, 32, 16);
- KeyParameter macKey = new KeyParameter(firstBlock, 16, 32);
- Poly1305KeyGenerator.clamp(macKey.getKey());
- return macKey;
- }
-
- protected byte[] calculateRecordMAC(KeyParameter macKey, byte[] additionalData, byte[] buf, int off, int len)
- {
- Mac mac = new Poly1305();
- mac.init(macKey);
-
- updateRecordMAC(mac, additionalData, 0, additionalData.length);
- updateRecordMAC(mac, buf, off, len);
-
- byte[] output = new byte[mac.getMacSize()];
- mac.doFinal(output, 0);
- return output;
- }
-
- protected void updateRecordMAC(Mac mac, byte[] buf, int off, int len)
- {
- mac.update(buf, off, len);
-
- byte[] longLen = Pack.longToLittleEndian(len & 0xFFFFFFFFL);
- mac.update(longLen, 0, longLen.length);
- }
-
- protected byte[] getAdditionalData(long seqNo, short type, int len) throws IOException
- {
- /*
- * additional_data = seq_num + TLSCompressed.type + TLSCompressed.version +
- * TLSCompressed.length
- */
- byte[] additional_data = new byte[13];
- TlsUtils.writeUint64(seqNo, additional_data, 0);
- TlsUtils.writeUint8(type, additional_data, 8);
- TlsUtils.writeVersion(context.getServerVersion(), additional_data, 9);
- TlsUtils.writeUint16(len, additional_data, 11);
-
- return additional_data;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/ChangeCipherSpec.java b/core/src/main/java/org/bouncycastle/crypto/tls/ChangeCipherSpec.java
deleted file mode 100644
index a858deda..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/ChangeCipherSpec.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-public class ChangeCipherSpec
-{
- public static final short change_cipher_spec = 1;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/CipherSuite.java b/core/src/main/java/org/bouncycastle/crypto/tls/CipherSuite.java
deleted file mode 100644
index 3d4dccab..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/CipherSuite.java
+++ /dev/null
@@ -1,351 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 2246 A.5
- */
-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;
- public static final int TLS_RSA_EXPORT_WITH_RC4_40_MD5 = 0x0003;
- public static final int TLS_RSA_WITH_RC4_128_MD5 = 0x0004;
- public static final int TLS_RSA_WITH_RC4_128_SHA = 0x0005;
- public static final int TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 0x0006;
- public static final int TLS_RSA_WITH_IDEA_CBC_SHA = 0x0007;
- public static final int TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0008;
- public static final int TLS_RSA_WITH_DES_CBC_SHA = 0x0009;
- public static final int TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A;
- public static final int TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x000B;
- public static final int TLS_DH_DSS_WITH_DES_CBC_SHA = 0x000C;
- public static final int TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x000D;
- public static final int TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x000E;
- public static final int TLS_DH_RSA_WITH_DES_CBC_SHA = 0x000F;
- public static final int TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0010;
- public static final int TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x0011;
- public static final int TLS_DHE_DSS_WITH_DES_CBC_SHA = 0x0012;
- public static final int TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013;
- public static final int TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0014;
- public static final int TLS_DHE_RSA_WITH_DES_CBC_SHA = 0x0015;
- public static final int TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016;
- public static final int TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = 0x0017;
- public static final int TLS_DH_anon_WITH_RC4_128_MD5 = 0x0018;
- public static final int TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 0x0019;
- public static final int TLS_DH_anon_WITH_DES_CBC_SHA = 0x001A;
- public static final int TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0x001B;
-
- /*
- * Note: The cipher suite values { 0x00, 0x1C } and { 0x00, 0x1D } are reserved to avoid
- * collision with Fortezza-based cipher suites in SSL 3.
- */
-
- /*
- * RFC 3268
- */
- public static final int TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F;
- public static final int TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0x0030;
- public static final int TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0x0031;
- public static final int TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032;
- public static final int TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033;
- public static final int TLS_DH_anon_WITH_AES_128_CBC_SHA = 0x0034;
- public static final int TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035;
- public static final int TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0x0036;
- public static final int TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0x0037;
- public static final int TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038;
- public static final int TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039;
- public static final int TLS_DH_anon_WITH_AES_256_CBC_SHA = 0x003A;
-
- /*
- * RFC 5932
- */
- public static final int TLS_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0041;
- public static final int TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA = 0x0042;
- public static final int TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0043;
- public static final int TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA = 0x0044;
- public static final int TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0045;
- public static final int TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA = 0x0046;
-
- public static final int TLS_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0084;
- public static final int TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0085;
- public static final int TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0086;
- public static final int TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0087;
- public static final int TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0088;
- public static final int TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA = 0x0089;
-
- public static final int TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BA;
- public static final int TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BB;
- public static final int TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BC;
- public static final int TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BD;
- public static final int TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BE;
- public static final int TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BF;
-
- public static final int TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C0;
- public static final int TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C1;
- public static final int TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C2;
- public static final int TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C3;
- public static final int TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C4;
- public static final int TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C5;
-
- /*
- * RFC 4162
- */
- public static final int TLS_RSA_WITH_SEED_CBC_SHA = 0x0096;
- public static final int TLS_DH_DSS_WITH_SEED_CBC_SHA = 0x0097;
- public static final int TLS_DH_RSA_WITH_SEED_CBC_SHA = 0x0098;
- public static final int TLS_DHE_DSS_WITH_SEED_CBC_SHA = 0x0099;
- public static final int TLS_DHE_RSA_WITH_SEED_CBC_SHA = 0x009A;
- public static final int TLS_DH_anon_WITH_SEED_CBC_SHA = 0x009B;
-
- /*
- * RFC 4279
- */
- public static final int TLS_PSK_WITH_RC4_128_SHA = 0x008A;
- public static final int TLS_PSK_WITH_3DES_EDE_CBC_SHA = 0x008B;
- public static final int TLS_PSK_WITH_AES_128_CBC_SHA = 0x008C;
- public static final int TLS_PSK_WITH_AES_256_CBC_SHA = 0x008D;
- public static final int TLS_DHE_PSK_WITH_RC4_128_SHA = 0x008E;
- public static final int TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA = 0x008F;
- public static final int TLS_DHE_PSK_WITH_AES_128_CBC_SHA = 0x0090;
- public static final int TLS_DHE_PSK_WITH_AES_256_CBC_SHA = 0x0091;
- public static final int TLS_RSA_PSK_WITH_RC4_128_SHA = 0x0092;
- public static final int TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA = 0x0093;
- public static final int TLS_RSA_PSK_WITH_AES_128_CBC_SHA = 0x0094;
- public static final int TLS_RSA_PSK_WITH_AES_256_CBC_SHA = 0x0095;
-
- /*
- * RFC 4492
- */
- public static final int TLS_ECDH_ECDSA_WITH_NULL_SHA = 0xC001;
- public static final int TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 0xC002;
- public static final int TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC003;
- public static final int TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = 0xC004;
- public static final int TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0xC005;
- public static final int TLS_ECDHE_ECDSA_WITH_NULL_SHA = 0xC006;
- public static final int TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 0xC007;
- public static final int TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC008;
- public static final int TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009;
- public static final int TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A;
- public static final int TLS_ECDH_RSA_WITH_NULL_SHA = 0xC00B;
- public static final int TLS_ECDH_RSA_WITH_RC4_128_SHA = 0xC00C;
- public static final int TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = 0xC00D;
- public static final int TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = 0xC00E;
- public static final int TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = 0xC00F;
- public static final int TLS_ECDHE_RSA_WITH_NULL_SHA = 0xC010;
- public static final int TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xC011;
- public static final int TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xC012;
- public static final int TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013;
- public static final int TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014;
- public static final int TLS_ECDH_anon_WITH_NULL_SHA = 0xC015;
- public static final int TLS_ECDH_anon_WITH_RC4_128_SHA = 0xC016;
- public static final int TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA = 0xC017;
- public static final int TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 0xC018;
- public static final int TLS_ECDH_anon_WITH_AES_256_CBC_SHA = 0xC019;
-
- /*
- * RFC 4785
- */
- public static final int TLS_PSK_WITH_NULL_SHA = 0x002C;
- public static final int TLS_DHE_PSK_WITH_NULL_SHA = 0x002D;
- public static final int TLS_RSA_PSK_WITH_NULL_SHA = 0x002E;
-
- /*
- * RFC 5054
- */
- public static final int TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA = 0xC01A;
- public static final int TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA = 0xC01B;
- public static final int TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA = 0xC01C;
- public static final int TLS_SRP_SHA_WITH_AES_128_CBC_SHA = 0xC01D;
- public static final int TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA = 0xC01E;
- public static final int TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA = 0xC01F;
- public static final int TLS_SRP_SHA_WITH_AES_256_CBC_SHA = 0xC020;
- public static final int TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA = 0xC021;
- public static final int TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA = 0xC022;
-
- /*
- * RFC 5246
- */
- public static final int TLS_RSA_WITH_NULL_SHA256 = 0x003B;
- public static final int TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C;
- public static final int TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D;
- public static final int TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 0x003E;
- public static final int TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 0x003F;
- public static final int TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040;
- public static final int TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067;
- public static final int TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 0x0068;
- public static final int TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 0x0069;
- public static final int TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A;
- public static final int TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B;
- public static final int TLS_DH_anon_WITH_AES_128_CBC_SHA256 = 0x006C;
- public static final int TLS_DH_anon_WITH_AES_256_CBC_SHA256 = 0x006D;
-
- /*
- * RFC 5288
- */
- public static final int TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C;
- public static final int TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D;
- public static final int TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E;
- public static final int TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F;
- public static final int TLS_DH_RSA_WITH_AES_128_GCM_SHA256 = 0x00A0;
- public static final int TLS_DH_RSA_WITH_AES_256_GCM_SHA384 = 0x00A1;
- public static final int TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = 0x00A2;
- public static final int TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = 0x00A3;
- public static final int TLS_DH_DSS_WITH_AES_128_GCM_SHA256 = 0x00A4;
- public static final int TLS_DH_DSS_WITH_AES_256_GCM_SHA384 = 0x00A5;
- public static final int TLS_DH_anon_WITH_AES_128_GCM_SHA256 = 0x00A6;
- public static final int TLS_DH_anon_WITH_AES_256_GCM_SHA384 = 0x00A7;
-
- /*
- * RFC 5289
- */
- public static final int TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023;
- public static final int TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024;
- public static final int TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC025;
- public static final int TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC026;
- public static final int TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027;
- public static final int TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028;
- public static final int TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 = 0xC029;
- public static final int TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 = 0xC02A;
- public static final int TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B;
- public static final int TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C;
- public static final int TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02D;
- public static final int TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02E;
- public static final int TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F;
- public static final int TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030;
- public static final int TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 = 0xC031;
- 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 6367
- */
- public static final int TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC072;
- public static final int TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC073;
- public static final int TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC074;
- public static final int TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC075;
- public static final int TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC076;
- public static final int TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC077;
- public static final int TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC078;
- public static final int TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC079;
-
- public static final int TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07A;
- public static final int TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07B;
- public static final int TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07C;
- public static final int TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07D;
- public static final int TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07E;
- public static final int TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07F;
- public static final int TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 = 0xC080;
- public static final int TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 = 0xC081;
- public static final int TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256 = 0xC082;
- public static final int TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384 = 0xC083;
- public static final int TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256 = 0xC084;
- public static final int TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384 = 0xC085;
- public static final int TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC086;
- public static final int TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC087;
- public static final int TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC088;
- public static final int TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC089;
- public static final int TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08A;
- public static final int TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08B;
- public static final int TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08C;
- public static final int TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08D;
-
- public static final int TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08E;
- public static final int TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08F;
- public static final int TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC090;
- public static final int TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC091;
- public static final int TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC092;
- public static final int TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC093;
- public static final int TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC094;
- public static final int TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC095;
- public static final int TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC096;
- public static final int TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC097;
- public static final int TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC098;
- public static final int TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC099;
- public static final int TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC09A;
- public static final int TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC09B;
-
- /*
- * 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;
-
- /*
- * draft-agl-tls-chacha20poly1305-04
- */
- public static final int TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC13;
- public static final int TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC14;
- public static final int TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC15;
-
- /*
- * draft-josefsson-salsa20-tls-04
- */
- public static final int TLS_RSA_WITH_ESTREAM_SALSA20_SHA1 = 0xE410;
- public static final int TLS_RSA_WITH_SALSA20_SHA1 = 0xE411;
- public static final int TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1 = 0xE412;
- public static final int TLS_ECDHE_RSA_WITH_SALSA20_SHA1 = 0xE413;
- public static final int TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1 = 0xE414;
- public static final int TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1 = 0xE415;
- public static final int TLS_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xE416;
- public static final int TLS_PSK_WITH_SALSA20_SHA1 = 0xE417;
- public static final int TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xE418;
- public static final int TLS_ECDHE_PSK_WITH_SALSA20_SHA1 = 0xE419;
- public static final int TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xE41A;
- public static final int TLS_RSA_PSK_WITH_SALSA20_SHA1 = 0xE41B;
- public static final int TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xE41C;
- public static final int TLS_DHE_PSK_WITH_SALSA20_SHA1 = 0xE41D;
- public static final int TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1 = 0xE41E;
- public static final int TLS_DHE_RSA_WITH_SALSA20_SHA1 = 0xE41F;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/CipherType.java b/core/src/main/java/org/bouncycastle/crypto/tls/CipherType.java
deleted file mode 100644
index c6d845a6..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/CipherType.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 2246
- * <p>
- * Note that the values here are implementation-specific and arbitrary. It is recommended not to
- * depend on the particular values (e.g. serialization).
- */
-public class CipherType
-{
- public static final int stream = 0;
- public static final int block = 1;
-
- /*
- * RFC 5246
- */
- public static final int aead = 2;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/ClientAuthenticationType.java b/core/src/main/java/org/bouncycastle/crypto/tls/ClientAuthenticationType.java
deleted file mode 100644
index 77e64607..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/ClientAuthenticationType.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-public class ClientAuthenticationType
-{
- /*
- * RFC 5077 4
- */
- public static final short anonymous = 0;
- public static final short certificate_based = 1;
- public static final short psk = 2;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/ClientCertificateType.java b/core/src/main/java/org/bouncycastle/crypto/tls/ClientCertificateType.java
deleted file mode 100644
index 6bddfc0f..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/ClientCertificateType.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-public class ClientCertificateType
-{
- /*
- * RFC 4346 7.4.4
- */
- public static final short rsa_sign = 1;
- public static final short dss_sign = 2;
- public static final short rsa_fixed_dh = 3;
- public static final short dss_fixed_dh = 4;
- public static final short rsa_ephemeral_dh_RESERVED = 5;
- public static final short dss_ephemeral_dh_RESERVED = 6;
- public static final short fortezza_dms_RESERVED = 20;
-
- /*
- * RFC 4492 5.5
- */
- public static final short ecdsa_sign = 64;
- public static final short rsa_fixed_ecdh = 65;
- public static final short ecdsa_fixed_ecdh = 66;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/CombinedHash.java b/core/src/main/java/org/bouncycastle/crypto/tls/CombinedHash.java
deleted file mode 100644
index 43b73bff..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/CombinedHash.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import org.bouncycastle.crypto.Digest;
-
-/**
- * A combined hash, which implements md5(m) || sha1(m).
- */
-class CombinedHash
- implements TlsHandshakeHash
-{
- protected TlsContext context;
- protected Digest md5;
- protected Digest sha1;
-
- CombinedHash()
- {
- this.md5 = TlsUtils.createHash(HashAlgorithm.md5);
- this.sha1 = TlsUtils.createHash(HashAlgorithm.sha1);
- }
-
- CombinedHash(CombinedHash t)
- {
- this.context = t.context;
- this.md5 = TlsUtils.cloneHash(HashAlgorithm.md5, t.md5);
- this.sha1 = TlsUtils.cloneHash(HashAlgorithm.sha1, t.sha1);
- }
-
- public void init(TlsContext context)
- {
- this.context = context;
- }
-
- public TlsHandshakeHash notifyPRFDetermined()
- {
- return this;
- }
-
- 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()
- */
- public String getAlgorithmName()
- {
- return md5.getAlgorithmName() + " and " + sha1.getAlgorithmName();
- }
-
- /**
- * @see org.bouncycastle.crypto.Digest#getDigestSize()
- */
- public int getDigestSize()
- {
- return md5.getDigestSize() + sha1.getDigestSize();
- }
-
- /**
- * @see org.bouncycastle.crypto.Digest#update(byte)
- */
- public void update(byte in)
- {
- md5.update(in);
- sha1.update(in);
- }
-
- /**
- * @see org.bouncycastle.crypto.Digest#update(byte[], int, int)
- */
- public void update(byte[] in, int inOff, int len)
- {
- md5.update(in, inOff, len);
- sha1.update(in, inOff, len);
- }
-
- /**
- * @see org.bouncycastle.crypto.Digest#doFinal(byte[], int)
- */
- public int doFinal(byte[] out, int outOff)
- {
- if (context != null && TlsUtils.isSSL(context))
- {
- ssl3Complete(md5, SSL3Mac.IPAD, SSL3Mac.OPAD, 48);
- ssl3Complete(sha1, SSL3Mac.IPAD, SSL3Mac.OPAD, 40);
- }
-
- int i1 = md5.doFinal(out, outOff);
- int i2 = sha1.doFinal(out, outOff + i1);
- return i1 + i2;
- }
-
- /**
- * @see org.bouncycastle.crypto.Digest#reset()
- */
- public void reset()
- {
- md5.reset();
- sha1.reset();
- }
-
- protected void ssl3Complete(Digest d, byte[] ipad, byte[] opad, int padLength)
- {
- byte[] master_secret = context.getSecurityParameters().masterSecret;
-
- 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(master_secret, 0, master_secret.length);
- d.update(opad, 0, padLength);
- d.update(tmp, 0, tmp.length);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/CompressionMethod.java b/core/src/main/java/org/bouncycastle/crypto/tls/CompressionMethod.java
deleted file mode 100644
index 935d378f..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/CompressionMethod.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 2246 6.1
- */
-public class CompressionMethod
-{
- public static final short _null = 0;
-
- /**
- * @deprecated use '_null' instead
- */
- public static final short NULL = _null;
-
- /*
- * RFC 3749 2
- */
- public static final short DEFLATE = 1;
-
- /*
- * Values from 224 decimal (0xE0) through 255 decimal (0xFF)
- * inclusive are reserved for private use.
- */
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/ConnectionEnd.java b/core/src/main/java/org/bouncycastle/crypto/tls/ConnectionEnd.java
deleted file mode 100644
index bcbf607e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/ConnectionEnd.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 2246
- * <p>
- * Note that the values here are implementation-specific and arbitrary. It is recommended not to
- * depend on the particular values (e.g. serialization).
- */
-public class ConnectionEnd
-{
- public static final int server = 0;
- public static final int client = 1;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/ContentType.java b/core/src/main/java/org/bouncycastle/crypto/tls/ContentType.java
deleted file mode 100644
index 65ed9b60..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/ContentType.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 2246 6.2.1
- */
-public class ContentType
-{
- public static final short change_cipher_spec = 20;
- 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/core/src/main/java/org/bouncycastle/crypto/tls/DTLSClientProtocol.java b/core/src/main/java/org/bouncycastle/crypto/tls/DTLSClientProtocol.java
deleted file mode 100644
index b88d8f33..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/DTLSClientProtocol.java
+++ /dev/null
@@ -1,831 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.security.SecureRandom;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import org.bouncycastle.util.Arrays;
-
-public class DTLSClientProtocol
- extends DTLSProtocol
-{
- public DTLSClientProtocol(SecureRandom secureRandom)
- {
- super(secureRandom);
- }
-
- public DTLSTransport connect(TlsClient client, DatagramTransport transport)
- throws IOException
- {
- if (client == null)
- {
- throw new IllegalArgumentException("'client' cannot be null");
- }
- if (transport == null)
- {
- throw new IllegalArgumentException("'transport' cannot be null");
- }
-
- SecurityParameters securityParameters = new SecurityParameters();
- securityParameters.entity = ConnectionEnd.client;
-
- ClientHandshakeState state = new ClientHandshakeState();
- state.client = client;
- state.clientContext = new TlsClientContextImpl(secureRandom, securityParameters);
-
- securityParameters.clientRandom = TlsProtocol.createRandomBlock(client.shouldUseGMTUnixTime(),
- state.clientContext.getNonceRandomGenerator());
-
- client.init(state.clientContext);
-
- 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);
- }
- catch (TlsFatalAlert fatalAlert)
- {
- recordLayer.fail(fatalAlert.getAlertDescription());
- throw fatalAlert;
- }
- catch (IOException e)
- {
- recordLayer.fail(AlertDescription.internal_error);
- throw e;
- }
- catch (RuntimeException e)
- {
- recordLayer.fail(AlertDescription.internal_error);
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- protected DTLSTransport clientHandshake(ClientHandshakeState state, DTLSRecordLayer recordLayer)
- throws IOException
- {
- SecurityParameters securityParameters = state.clientContext.getSecurityParameters();
- DTLSReliableHandshake handshake = new DTLSReliableHandshake(state.clientContext, recordLayer);
-
- byte[] clientHelloBody = generateClientHello(state, state.client);
- handshake.sendMessage(HandshakeType.client_hello, clientHelloBody);
-
- DTLSReliableHandshake.Message serverMessage = handshake.receiveMessage();
-
- while (serverMessage.getType() == HandshakeType.hello_verify_request)
- {
- ProtocolVersion recordLayerVersion = recordLayer.resetDiscoveredPeerVersion();
- ProtocolVersion client_version = state.clientContext.getClientVersion();
-
- /*
- * 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);
- }
-
- byte[] cookie = processHelloVerifyRequest(state, serverMessage.getBody());
- byte[] patched = patchClientHelloWithCookie(clientHelloBody, cookie);
-
- handshake.resetHandshakeMessagesDigest();
- handshake.sendMessage(HandshakeType.client_hello, patched);
-
- serverMessage = handshake.receiveMessage();
- }
-
- if (serverMessage.getType() == HandshakeType.server_hello)
- {
- reportServerVersion(state, recordLayer.getDiscoveredPeerVersion());
-
- processServerHello(state, serverMessage.getBody());
- }
- else
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
-
- 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
- * a verify_data_length equal to 12. This includes all existing cipher suites.
- */
- securityParameters.verifyDataLength = 12;
-
- 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());
- serverMessage = handshake.receiveMessage();
- }
- else
- {
- state.client.processServerSupplementalData(null);
- }
-
- state.keyExchange = state.client.getKeyExchange();
- state.keyExchange.init(state.clientContext);
-
- Certificate serverCertificate = null;
-
- if (serverMessage.getType() == HandshakeType.certificate)
- {
- serverCertificate = processServerCertificate(state, serverMessage.getBody());
- serverMessage = handshake.receiveMessage();
- }
- else
- {
- // Okay, Certificate is optional
- 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());
- serverMessage = handshake.receiveMessage();
- }
- else
- {
- // Okay, ServerKeyExchange is optional
- state.keyExchange.skipServerKeyExchange();
- }
-
- 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
- {
- // Okay, CertificateRequest is optional
- }
-
- if (serverMessage.getType() == HandshakeType.server_hello_done)
- {
- if (serverMessage.getBody().length != 0)
- {
- throw new TlsFatalAlert(AlertDescription.decode_error);
- }
- }
- else
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
-
- handshake.getHandshakeHash().sealHashAlgorithms();
-
- Vector clientSupplementalData = state.client.getClientSupplementalData();
- if (clientSupplementalData != null)
- {
- byte[] supplementalDataBody = generateSupplementalData(clientSupplementalData);
- handshake.sendMessage(HandshakeType.supplemental_data, supplementalDataBody);
- }
-
- if (state.certificateRequest != null)
- {
- state.clientCredentials = state.authentication.getClientCredentials(state.certificateRequest);
-
- /*
- * RFC 5246 If no suitable certificate is available, the client MUST send a certificate
- * message containing no certificates.
- *
- * NOTE: In previous RFCs, this was SHOULD instead of MUST.
- */
- Certificate clientCertificate = null;
- if (state.clientCredentials != null)
- {
- clientCertificate = state.clientCredentials.getCertificate();
- }
- if (clientCertificate == null)
- {
- clientCertificate = Certificate.EMPTY_CHAIN;
- }
-
- byte[] certificateBody = generateCertificate(clientCertificate);
- handshake.sendMessage(HandshakeType.certificate, certificateBody);
- }
-
- if (state.clientCredentials != null)
- {
- state.keyExchange.processClientCredentials(state.clientCredentials);
- }
- else
- {
- state.keyExchange.skipClientCredentials();
- }
-
- byte[] clientKeyExchangeBody = generateClientKeyExchange(state);
- 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 != null && state.clientCredentials instanceof TlsSignerCredentials)
- {
- TlsSignerCredentials signerCredentials = (TlsSignerCredentials)state.clientCredentials;
-
- /*
- * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2
- */
- 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);
- }
-
- // 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);
-
- if (state.expectSessionTicket)
- {
- serverMessage = handshake.receiveMessage();
- if (serverMessage.getType() == HandshakeType.session_ticket)
- {
- processNewSessionTicket(state, serverMessage.getBody());
- }
- else
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- }
-
- // 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);
-
- handshake.finish();
-
- if (state.tlsSession != null)
- {
- state.sessionParameters = new SessionParameters.Builder()
- .setCipherSuite(securityParameters.cipherSuite)
- .setCompressionAlgorithm(securityParameters.compressionAlgorithm)
- .setMasterSecret(securityParameters.masterSecret)
- .setPeerCertificate(serverCertificate)
- .build();
-
- 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, DigitallySigned certificateVerify)
- throws IOException
- {
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
- certificateVerify.encode(buf);
- return buf.toByteArray();
- }
-
- protected byte[] generateClientHello(ClientHandshakeState state, TlsClient client)
- throws IOException
- {
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
-
- ProtocolVersion client_version = client.getClientVersion();
- if (!client_version.isDTLS())
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- state.clientContext.setClientVersion(client_version);
- TlsUtils.writeVersion(client_version, buf);
-
- buf.write(state.clientContext.getSecurityParameters().getClientRandom());
-
- // 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);
-
- /*
- * Cipher suites
- */
- state.offeredCipherSuites = client.getCipherSuites();
-
- // Integer -> byte[]
- state.clientExtensions = client.getClientExtensions();
-
- // Cipher Suites (and SCSV)
- {
- /*
- * RFC 5746 3.4. The client MUST include either an empty "renegotiation_info" extension,
- * or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling cipher suite value in the
- * ClientHello. Including both is NOT RECOMMENDED.
- */
- byte[] renegExtData = TlsUtils.getExtensionData(state.clientExtensions, TlsProtocol.EXT_RenegotiationInfo);
- boolean noRenegExt = (null == renegExtData);
-
- boolean noSCSV = !Arrays.contains(state.offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
-
- if (noRenegExt && noSCSV)
- {
- // 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 };
-
- TlsUtils.writeUint8ArrayWithUint8Length(state.offeredCompressionMethods, buf);
-
- // Extensions
- if (state.clientExtensions != null)
- {
- TlsProtocol.writeExtensions(buf, state.clientExtensions);
- }
-
- return buf.toByteArray();
- }
-
- 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)
- {
- /*
- * RFC 2246 7.4.4. It is a fatal handshake_failure alert for an anonymous server to
- * request client identification.
- */
- throw new TlsFatalAlert(AlertDescription.handshake_failure);
- }
-
- ByteArrayInputStream buf = new ByteArrayInputStream(body);
-
- state.certificateRequest = CertificateRequest.parse(state.clientContext, buf);
-
- TlsProtocol.assertEmpty(buf);
-
- state.keyExchange.validateCertificateRequest(state.certificateRequest);
- }
-
- 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);
-
- state.client.notifyNewSessionTicket(newSessionTicket);
- }
-
- protected Certificate processServerCertificate(ClientHandshakeState state, byte[] body)
- throws IOException
- {
- ByteArrayInputStream buf = new ByteArrayInputStream(body);
-
- Certificate serverCertificate = Certificate.parse(buf);
-
- TlsProtocol.assertEmpty(buf);
-
- 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);
-
- ProtocolVersion server_version = TlsUtils.readVersion(buf);
- reportServerVersion(state, server_version);
-
- securityParameters.serverRandom = TlsUtils.readFully(32, buf);
-
- state.selectedSessionID = TlsUtils.readOpaque8(buf);
- if (state.selectedSessionID.length > 32)
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- state.client.notifySessionID(state.selectedSessionID);
-
- state.selectedCipherSuite = TlsUtils.readUint16(buf);
- if (!Arrays.contains(state.offeredCipherSuites, state.selectedCipherSuite)
- || state.selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL
- || state.selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV
- || !TlsUtils.isValidCipherSuiteForVersion(state.selectedCipherSuite, server_version))
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- validateSelectedCipherSuite(state.selectedCipherSuite, AlertDescription.illegal_parameter);
-
- state.client.notifySelectedCipherSuite(state.selectedCipherSuite);
-
- state.selectedCompressionMethod = TlsUtils.readUint8(buf);
- if (!Arrays.contains(state.offeredCompressionMethods, state.selectedCompressionMethod))
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- state.client.notifySelectedCompressionMethod(state.selectedCompressionMethod);
-
- /*
- * RFC3546 2.2 The extended server hello message format MAY be sent in place of the server
- * hello message when the client has requested extended functionality via the extended
- * client hello message specified in Section 2.1. ... Note that the extended server hello
- * message is only sent in response to an extended client hello message. This prevents the
- * 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 = TlsProtocol.readExtensions(buf);
-
- /*
- * RFC 3546 2.2 Note that the extended server hello message is only sent in response to an
- * extended client hello message. However, see RFC 5746 exception below. We always include
- * the SCSV, so an Extended Server Hello is always allowed.
- */
- if (serverExtensions != null)
- {
- Enumeration e = serverExtensions.keys();
- while (e.hasMoreElements())
- {
- Integer extType = (Integer)e.nextElement();
-
- /*
- * RFC 5746 Note that sending a "renegotiation_info" extension in response to a
- * ClientHello containing only the SCSV is an explicit exception to the prohibition
- * in RFC 5246, Section 7.4.1.4, on the server sending unsolicited extensions and is
- * only allowed because the client is signaling its willingness to receive the
- * extension via the TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. TLS implementations
- * MUST continue to comply with Section 7.4.1.4 for all other extensions.
- */
- if (!extType.equals(TlsProtocol.EXT_RenegotiationInfo)
- && null == TlsUtils.getExtensionData(state.clientExtensions, extType))
- {
- /*
- * RFC 3546 2.3 Note that for all extension types (including those defined in
- * future), the extension type MUST NOT appear in the extended server hello
- * unless the same extension type appeared in the corresponding client hello.
- * Thus clients MUST abort the handshake if they receive an extension type in
- * the extended server hello that they did not request in the associated
- * (extended) client hello.
- */
- throw new TlsFatalAlert(AlertDescription.unsupported_extension);
- }
- }
-
- /*
- * 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 = (byte[])serverExtensions.get(TlsProtocol.EXT_RenegotiationInfo);
- if (renegExtData != 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).
- */
- state.secure_renegotiation = true;
-
- if (!Arrays.constantTimeAreEqual(renegExtData,
- TlsProtocol.createRenegotiationInfo(TlsUtils.EMPTY_BYTES)))
- {
- throw new TlsFatalAlert(AlertDescription.handshake_failure);
- }
- }
- }
-
- /*
- * draft-ietf-tls-encrypt-then-mac-03 3. If a server receives an encrypt-then-MAC
- * request extension from a client and then selects a stream or AEAD cipher suite, it
- * MUST NOT send an encrypt-then-MAC response extension back to the client.
- */
- boolean serverSentEncryptThenMAC = TlsExtensionsUtils.hasEncryptThenMACExtension(serverExtensions);
- if (serverSentEncryptThenMAC && !TlsUtils.isBlockCipherSuite(state.selectedCipherSuite))
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- securityParameters.encryptThenMAC = serverSentEncryptThenMAC;
-
- 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);
-
- if (state.clientExtensions != null)
- {
- state.client.processServerExtensions(serverExtensions);
- }
- }
-
- protected void processServerKeyExchange(ClientHandshakeState state, byte[] body)
- throws IOException
- {
- ByteArrayInputStream buf = new ByteArrayInputStream(body);
-
- state.keyExchange.processServerKeyExchange(buf);
-
- TlsProtocol.assertEmpty(buf);
- }
-
- protected void processServerSupplementalData(ClientHandshakeState state, byte[] body)
- throws IOException
- {
- ByteArrayInputStream buf = new ByteArrayInputStream(body);
- Vector serverSupplementalData = TlsProtocol.readSupplementalDataMessage(buf);
- state.client.processServerSupplementalData(serverSupplementalData);
- }
-
- protected void reportServerVersion(ClientHandshakeState state, ProtocolVersion server_version)
- throws IOException
- {
- 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);
- }
- }
-
- protected static byte[] patchClientHelloWithCookie(byte[] clientHelloBody, byte[] cookie)
- throws IOException
- {
- int sessionIDPos = 34;
- int sessionIDLength = TlsUtils.readUint8(clientHelloBody, sessionIDPos);
-
- int cookieLengthPos = sessionIDPos + 1 + sessionIDLength;
- int cookiePos = cookieLengthPos + 1;
-
- byte[] patched = new byte[clientHelloBody.length + cookie.length];
- System.arraycopy(clientHelloBody, 0, patched, 0, 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);
-
- return patched;
- }
-
- protected static class ClientHandshakeState
- {
- 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/core/src/main/java/org/bouncycastle/crypto/tls/DTLSEpoch.java b/core/src/main/java/org/bouncycastle/crypto/tls/DTLSEpoch.java
deleted file mode 100644
index 57dd42f6..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/DTLSEpoch.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-class DTLSEpoch
-{
- private final DTLSReplayWindow replayWindow = new DTLSReplayWindow();
-
- private final int epoch;
- private final TlsCipher cipher;
-
- private long sequence_number = 0;
-
- DTLSEpoch(int epoch, TlsCipher cipher)
- {
- if (epoch < 0)
- {
- throw new IllegalArgumentException("'epoch' must be >= 0");
- }
- if (cipher == null)
- {
- throw new IllegalArgumentException("'cipher' cannot be null");
- }
-
- this.epoch = epoch;
- this.cipher = cipher;
- }
-
- long allocateSequenceNumber()
- {
- // TODO Check for overflow
- return sequence_number++;
- }
-
- TlsCipher getCipher()
- {
- return cipher;
- }
-
- int getEpoch()
- {
- return epoch;
- }
-
- DTLSReplayWindow getReplayWindow()
- {
- return replayWindow;
- }
-
- long getSequence_number()
- {
- return sequence_number;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/DTLSHandshakeRetransmit.java b/core/src/main/java/org/bouncycastle/crypto/tls/DTLSHandshakeRetransmit.java
deleted file mode 100644
index 251d3a28..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/DTLSHandshakeRetransmit.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-interface DTLSHandshakeRetransmit
-{
- void receivedHandshakeRecord(int epoch, byte[] buf, int off, int len)
- throws IOException;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/DTLSProtocol.java b/core/src/main/java/org/bouncycastle/crypto/tls/DTLSProtocol.java
deleted file mode 100644
index db43011b..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/DTLSProtocol.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-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");
- }
-
- this.secureRandom = secureRandom;
- }
-
- 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);
-
- TlsProtocol.assertEmpty(buf);
-
- if (!Arrays.constantTimeAreEqual(expected_verify_data, verify_data))
- {
- throw new TlsFatalAlert(AlertDescription.handshake_failure);
- }
- }
-
- 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();
- }
-
- protected static byte[] generateSupplementalData(Vector supplementalData)
- throws IOException
- {
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
- TlsProtocol.writeSupplementalData(buf, supplementalData);
- return buf.toByteArray();
- }
-
- protected static void validateSelectedCipherSuite(int selectedCipherSuite, short alertDescription)
- throws IOException
- {
- switch (TlsUtils.getEncryptionAlgorithm(selectedCipherSuite))
- {
- case EncryptionAlgorithm.RC4_40:
- case EncryptionAlgorithm.RC4_128:
- throw new TlsFatalAlert(alertDescription);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/DTLSReassembler.java b/core/src/main/java/org/bouncycastle/crypto/tls/DTLSReassembler.java
deleted file mode 100644
index 788306c8..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/DTLSReassembler.java
+++ /dev/null
@@ -1,133 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.util.Vector;
-
-class DTLSReassembler
-{
- private final short msg_type;
- private final byte[] body;
-
- private Vector missing = new Vector();
-
- DTLSReassembler(short msg_type, int length)
- {
- this.msg_type = msg_type;
- this.body = new byte[length];
- this.missing.addElement(new Range(0, length));
- }
-
- short getType()
- {
- return msg_type;
- }
-
- byte[] getBodyIfComplete()
- {
- return missing.isEmpty() ? body : null;
- }
-
- void contributeFragment(short msg_type, int length, byte[] buf, int off, int fragment_offset,
- int fragment_length)
- {
- int fragment_end = fragment_offset + fragment_length;
-
- if (this.msg_type != msg_type || this.body.length != length || fragment_end > length)
- {
- return;
- }
-
- if (fragment_length == 0)
- {
- // NOTE: Empty messages still require an empty fragment to complete it
- if (fragment_offset == 0 && !missing.isEmpty())
- {
- Range firstRange = (Range)missing.firstElement();
- if (firstRange.getEnd() == 0)
- {
- missing.removeElementAt(0);
- }
- }
- return;
- }
-
- for (int i = 0; i < missing.size(); ++i)
- {
- Range range = (Range)missing.elementAt(i);
- if (range.getStart() >= fragment_end)
- {
- break;
- }
- if (range.getEnd() > fragment_offset)
- {
-
- int copyStart = Math.max(range.getStart(), fragment_offset);
- int copyEnd = Math.min(range.getEnd(), fragment_end);
- int copyLength = copyEnd - copyStart;
-
- System.arraycopy(buf, off + copyStart - fragment_offset, body, copyStart,
- copyLength);
-
- if (copyStart == range.getStart())
- {
- if (copyEnd == range.getEnd())
- {
- missing.removeElementAt(i--);
- }
- else
- {
- range.setStart(copyEnd);
- }
- }
- else
- {
- if (copyEnd == range.getEnd())
- {
- range.setEnd(copyStart);
- }
- else
- {
- missing.insertElementAt(new Range(copyEnd, range.getEnd()), ++i);
- range.setEnd(copyStart);
- }
- }
- }
- }
- }
-
- void reset()
- {
- this.missing.removeAllElements();
- this.missing.addElement(new Range(0, body.length));
- }
-
- private static class Range
- {
- private int start, end;
-
- Range(int start, int end)
- {
- this.start = start;
- this.end = end;
- }
-
- public int getStart()
- {
- return start;
- }
-
- public void setStart(int start)
- {
- this.start = start;
- }
-
- public int getEnd()
- {
- return end;
- }
-
- public void setEnd(int end)
- {
- this.end = end;
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/DTLSRecordLayer.java b/core/src/main/java/org/bouncycastle/crypto/tls/DTLSRecordLayer.java
deleted file mode 100644
index 15192395..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/DTLSRecordLayer.java
+++ /dev/null
@@ -1,516 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-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;
- private static final long RETRANSMIT_TIMEOUT = TCP_MSL * 2;
-
- private final DatagramTransport transport;
- private final TlsContext context;
- private final TlsPeer peer;
-
- private final ByteQueue recordQueue = new ByteQueue();
-
- private volatile boolean closed = false;
- 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;
-
- private DTLSHandshakeRetransmit retransmit = null;
- private DTLSEpoch retransmitEpoch = null;
- private long retransmitExpiry = 0;
-
- DTLSRecordLayer(DatagramTransport transport, TlsContext context, TlsPeer peer, short contentType)
- {
- this.transport = transport;
- this.context = context;
- this.peer = peer;
-
- this.inHandshake = true;
-
- this.currentEpoch = new DTLSEpoch(0, new TlsNullCipher(context));
- this.pendingEpoch = null;
- this.readEpoch = currentEpoch;
- this.writeEpoch = currentEpoch;
-
- setPlaintextLimit(MAX_FRAGMENT_LENGTH);
- }
-
- void setPlaintextLimit(int plaintextLimit)
- {
- this.plaintextLimit = plaintextLimit;
- }
-
- ProtocolVersion getDiscoveredPeerVersion()
- {
- return discoveredPeerVersion;
- }
-
- ProtocolVersion resetDiscoveredPeerVersion()
- {
- ProtocolVersion result = discoveredPeerVersion;
- discoveredPeerVersion = null;
- return result;
- }
-
- void initPendingEpoch(TlsCipher pendingCipher)
- {
- if (pendingEpoch != null)
- {
- throw new IllegalStateException();
- }
-
- /*
- * TODO "In order to ensure that any given sequence/epoch pair is unique, implementations
- * MUST NOT allow the same epoch value to be reused within two times the TCP maximum segment
- * lifetime."
- */
-
- // TODO Check for overflow
- this.pendingEpoch = new DTLSEpoch(writeEpoch.getEpoch() + 1, pendingCipher);
- }
-
- void handshakeSuccessful(DTLSHandshakeRetransmit retransmit)
- {
- if (readEpoch == currentEpoch || writeEpoch == currentEpoch)
- {
- // TODO
- throw new IllegalStateException();
- }
-
- if (retransmit != null)
- {
- this.retransmit = retransmit;
- this.retransmitEpoch = currentEpoch;
- this.retransmitExpiry = System.currentTimeMillis() + RETRANSMIT_TIMEOUT;
- }
-
- this.inHandshake = false;
- this.currentEpoch = pendingEpoch;
- this.pendingEpoch = null;
- }
-
- void resetWriteEpoch()
- {
- if (retransmitEpoch != null)
- {
- this.writeEpoch = retransmitEpoch;
- }
- else
- {
- this.writeEpoch = currentEpoch;
- }
- }
-
- public int getReceiveLimit()
- throws IOException
- {
- return Math.min(this.plaintextLimit,
- readEpoch.getCipher().getPlaintextLimit(transport.getReceiveLimit() - RECORD_HEADER_LENGTH));
- }
-
- public int getSendLimit()
- throws IOException
- {
- 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 (;;)
- {
- int receiveLimit = Math.min(len, getReceiveLimit()) + RECORD_HEADER_LENGTH;
- if (record == null || record.length < receiveLimit)
- {
- record = new byte[receiveLimit];
- }
-
- try
- {
- if (retransmit != null && System.currentTimeMillis() > retransmitExpiry)
- {
- retransmit = null;
- retransmitEpoch = null;
- }
-
- int received = receiveRecord(record, 0, receiveLimit, waitMillis);
- if (received < 0)
- {
- return received;
- }
- if (received < RECORD_HEADER_LENGTH)
- {
- continue;
- }
- int length = TlsUtils.readUint16(record, 11);
- if (received != (length + RECORD_HEADER_LENGTH))
- {
- continue;
- }
-
- short type = TlsUtils.readUint8(record, 0);
-
- // TODO Support user-specified custom protocols?
- switch (type)
- {
- case ContentType.alert:
- case ContentType.application_data:
- case ContentType.change_cipher_spec:
- case ContentType.handshake:
- case ContentType.heartbeat:
- break;
- default:
- // TODO Exception?
- continue;
- }
-
- int epoch = TlsUtils.readUint16(record, 3);
-
- DTLSEpoch recordEpoch = null;
- if (epoch == readEpoch.getEpoch())
- {
- recordEpoch = readEpoch;
- }
- else if (type == ContentType.handshake && retransmitEpoch != null
- && epoch == retransmitEpoch.getEpoch())
- {
- recordEpoch = retransmitEpoch;
- }
-
- if (recordEpoch == null)
- {
- continue;
- }
-
- long seq = TlsUtils.readUint48(record, 5);
- if (recordEpoch.getReplayWindow().shouldDiscard(seq))
- {
- continue;
- }
-
- ProtocolVersion version = TlsUtils.readVersion(record, 1);
- if (discoveredPeerVersion != null && !discoveredPeerVersion.equals(version))
- {
- continue;
- }
-
- byte[] plaintext = recordEpoch.getCipher().decodeCiphertext(
- getMacSequenceNumber(recordEpoch.getEpoch(), seq), type, record, RECORD_HEADER_LENGTH,
- received - RECORD_HEADER_LENGTH);
-
- recordEpoch.getReplayWindow().reportAuthenticated(seq);
-
- if (plaintext.length > this.plaintextLimit)
- {
- continue;
- }
-
- if (discoveredPeerVersion == null)
- {
- discoveredPeerVersion = version;
- }
-
- switch (type)
- {
- case ContentType.alert:
- {
- if (plaintext.length == 2)
- {
- short alertLevel = plaintext[0];
- short alertDescription = plaintext[1];
-
- peer.notifyAlertReceived(alertLevel, alertDescription);
-
- if (alertLevel == AlertLevel.fatal)
- {
- fail(alertDescription);
- throw new TlsFatalAlert(alertDescription);
- }
-
- // TODO Can close_notify be a fatal alert?
- if (alertDescription == AlertDescription.close_notify)
- {
- closeTransport();
- }
- }
-
- continue;
- }
- case ContentType.application_data:
- {
- if (inHandshake)
- {
- // TODO Consider buffering application data for new epoch that arrives
- // out-of-order with the Finished message
- continue;
- }
- break;
- }
- case ContentType.change_cipher_spec:
- {
- // Implicitly receive change_cipher_spec and change to pending cipher state
-
- for (int i = 0; i < plaintext.length; ++i)
- {
- short message = TlsUtils.readUint8(plaintext, i);
- if (message != ChangeCipherSpec.change_cipher_spec)
- {
- continue;
- }
-
- if (pendingEpoch != null)
- {
- readEpoch = pendingEpoch;
- }
- }
-
- continue;
- }
- case ContentType.handshake:
- {
- if (!inHandshake)
- {
- if (retransmit != null)
- {
- retransmit.receivedHandshakeRecord(epoch, plaintext, 0, plaintext.length);
- }
-
- // TODO Consider support for HelloRequest
- continue;
- }
- break;
- }
- case ContentType.heartbeat:
- {
- // TODO[RFC 6520]
- continue;
- }
- }
-
- /*
- * NOTE: If we receive any non-handshake data in the new epoch implies the peer has
- * received our final flight.
- */
- if (!inHandshake && retransmit != null)
- {
- this.retransmit = null;
- this.retransmitEpoch = null;
- }
-
- System.arraycopy(plaintext, 0, buf, off, plaintext.length);
- return plaintext.length;
- }
- catch (IOException e)
- {
- // NOTE: Assume this is a timeout for the moment
- throw e;
- }
- }
- }
-
- 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)
- {
- nextEpoch = pendingEpoch;
- }
- else if (this.writeEpoch == this.retransmitEpoch)
- {
- nextEpoch = currentEpoch;
- }
-
- if (nextEpoch == null)
- {
- // TODO
- throw new IllegalStateException();
- }
-
- // 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 };
- sendRecord(ContentType.change_cipher_spec, data, 0, data.length);
-
- writeEpoch = nextEpoch;
- }
- }
-
- sendRecord(contentType, buf, off, len);
- }
-
- public void close()
- throws IOException
- {
- if (!closed)
- {
- if (inHandshake)
- {
- warn(AlertDescription.user_canceled, "User canceled handshake");
- }
- closeTransport();
- }
- }
-
- void fail(short alertDescription)
- {
- if (!closed)
- {
- try
- {
- raiseAlert(AlertLevel.fatal, alertDescription, null, null);
- }
- catch (Exception e)
- {
- // Ignore
- }
-
- failed = true;
-
- closeTransport();
- }
- }
-
- void warn(short alertDescription, String message)
- throws IOException
- {
- raiseAlert(AlertLevel.warning, alertDescription, message, null);
- }
-
- private void closeTransport()
- {
- if (!closed)
- {
- /*
- * RFC 5246 7.2.1. Unless some other fatal alert has been transmitted, each party is
- * required to send a close_notify alert before closing the write side of the
- * connection. The other party MUST respond with a close_notify alert of its own and
- * close down the connection immediately, discarding any pending writes.
- */
-
- try
- {
- if (!failed)
- {
- warn(AlertDescription.close_notify, null);
- }
- transport.close();
- }
- catch (Exception e)
- {
- // Ignore
- }
-
- closed = true;
- }
- }
-
- private void raiseAlert(short alertLevel, short alertDescription, String message, Exception cause)
- throws IOException
- {
- peer.notifyAlertRaised(alertLevel, alertDescription, message, cause);
-
- byte[] error = new byte[2];
- error[0] = (byte)alertLevel;
- error[1] = (byte)alertDescription;
-
- sendRecord(ContentType.alert, error, 0, 2);
- }
-
- private int receiveRecord(byte[] buf, int off, int len, int waitMillis)
- throws IOException
- {
- if (recordQueue.size() > 0)
- {
- int length = 0;
- if (recordQueue.size() >= RECORD_HEADER_LENGTH)
- {
- byte[] lengthBytes = new byte[2];
- recordQueue.read(lengthBytes, 0, 2, 11);
- length = TlsUtils.readUint16(lengthBytes, 0);
- }
-
- int received = Math.min(recordQueue.size(), RECORD_HEADER_LENGTH + length);
- recordQueue.removeData(buf, off, received, 0);
- return received;
- }
-
- int received = transport.receive(buf, off, len, waitMillis);
- if (received >= RECORD_HEADER_LENGTH)
- {
- int fragmentLength = TlsUtils.readUint16(buf, off + 11);
- int recordLength = RECORD_HEADER_LENGTH + fragmentLength;
- if (received > recordLength)
- {
- recordQueue.addData(buf, off + recordLength, received - recordLength);
- received = recordLength;
- }
- }
-
- return received;
- }
-
- 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,
- * or ChangeCipherSpec content types.
- */
- if (len < 1 && contentType != ContentType.application_data)
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- int recordEpoch = writeEpoch.getEpoch();
- long recordSequenceNumber = writeEpoch.allocateSequenceNumber();
-
- byte[] ciphertext = writeEpoch.getCipher().encodePlaintext(
- getMacSequenceNumber(recordEpoch, recordSequenceNumber), contentType, buf, off, len);
-
- // TODO Check the ciphertext length?
-
- byte[] record = new byte[ciphertext.length + RECORD_HEADER_LENGTH];
- TlsUtils.writeUint8(contentType, record, 0);
- ProtocolVersion version = discoveredPeerVersion != null ? discoveredPeerVersion : context.getClientVersion();
- TlsUtils.writeVersion(version, record, 1);
- TlsUtils.writeUint16(recordEpoch, record, 3);
- TlsUtils.writeUint48(recordSequenceNumber, record, 5);
- TlsUtils.writeUint16(ciphertext.length, record, 11);
- System.arraycopy(ciphertext, 0, record, RECORD_HEADER_LENGTH, ciphertext.length);
-
- transport.send(record, 0, record.length);
- }
-
- private static long getMacSequenceNumber(int epoch, long sequence_number)
- {
- return ((epoch & 0xFFFFFFFFL) << 48) | sequence_number;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/DTLSReliableHandshake.java b/core/src/main/java/org/bouncycastle/crypto/tls/DTLSReliableHandshake.java
deleted file mode 100644
index 50a5eeac..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/DTLSReliableHandshake.java
+++ /dev/null
@@ -1,453 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import org.bouncycastle.util.Integers;
-
-class DTLSReliableHandshake
-{
- private final static int MAX_RECEIVE_AHEAD = 10;
-
- private final DTLSRecordLayer recordLayer;
-
- private TlsHandshakeHash handshakeHash;
-
- private Hashtable currentInboundFlight = new Hashtable();
- private Hashtable previousInboundFlight = null;
- private Vector outboundFlight = new Vector();
- private boolean sending = true;
-
- private int message_seq = 0, next_receive_seq = 0;
-
- DTLSReliableHandshake(TlsContext context, DTLSRecordLayer transport)
- {
- this.recordLayer = transport;
- this.handshakeHash = new DeferredHash();
- this.handshakeHash.init(context);
- }
-
- void notifyHelloComplete()
- {
- this.handshakeHash = handshakeHash.notifyPRFDetermined();
- }
-
- TlsHandshakeHash getHandshakeHash()
- {
- return handshakeHash;
- }
-
- TlsHandshakeHash prepareToFinish()
- {
- TlsHandshakeHash result = handshakeHash;
- this.handshakeHash = handshakeHash.stopTracking();
- return result;
- }
-
- void sendMessage(short msg_type, byte[] body)
- throws IOException
- {
- TlsUtils.checkUint24(body.length);
-
- if (!sending)
- {
- checkInboundFlight();
- sending = true;
- outboundFlight.removeAllElements();
- }
-
- Message message = new Message(message_seq++, msg_type, body);
-
- outboundFlight.addElement(message);
-
- writeMessage(message);
- updateHandshakeMessagesDigest(message);
- }
-
- 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;
- prepareInboundFlight();
- }
-
- // Check if we already have the next message waiting
- {
- DTLSReassembler next = (DTLSReassembler)currentInboundFlight.get(Integers.valueOf(next_receive_seq));
- if (next != null)
- {
- byte[] body = next.getBodyIfComplete();
- if (body != null)
- {
- previousInboundFlight = null;
- return updateHandshakeMessagesDigest(new Message(next_receive_seq++, next.getType(), body));
- }
- }
- }
-
- byte[] buf = null;
-
- // TODO Check the conditions under which we should reset this
- int readTimeoutMillis = 1000;
-
- for (;;)
- {
- int receiveLimit = recordLayer.getReceiveLimit();
- if (buf == null || buf.length < receiveLimit)
- {
- buf = new byte[receiveLimit];
- }
-
- // TODO Handle records containing multiple handshake messages
-
- try
- {
- for (; ; )
- {
- int received = recordLayer.receive(buf, 0, receiveLimit, readTimeoutMillis);
- if (received < 0)
- {
- break;
- }
- if (received < 12)
- {
- continue;
- }
- int fragment_length = TlsUtils.readUint24(buf, 9);
- if (received != (fragment_length + 12))
- {
- continue;
- }
- int seq = TlsUtils.readUint16(buf, 4);
- if (seq > (next_receive_seq + MAX_RECEIVE_AHEAD))
- {
- continue;
- }
- short msg_type = TlsUtils.readUint8(buf, 0);
- int length = TlsUtils.readUint24(buf, 1);
- int fragment_offset = TlsUtils.readUint24(buf, 6);
- if (fragment_offset + fragment_length > length)
- {
- continue;
- }
-
- if (seq < next_receive_seq)
- {
- /*
- * NOTE: If we receive the previous flight of incoming messages in full
- * again, retransmit our last flight
- */
- if (previousInboundFlight != null)
- {
- DTLSReassembler reassembler = (DTLSReassembler)previousInboundFlight.get(Integers
- .valueOf(seq));
- if (reassembler != null)
- {
- reassembler.contributeFragment(msg_type, length, buf, 12, fragment_offset,
- fragment_length);
-
- if (checkAll(previousInboundFlight))
- {
- resendOutboundFlight();
-
- /*
- * TODO[DTLS] implementations SHOULD back off handshake packet
- * size during the retransmit backoff.
- */
- readTimeoutMillis = Math.min(readTimeoutMillis * 2, 60000);
-
- resetAll(previousInboundFlight);
- }
- }
- }
- }
- else
- {
- DTLSReassembler reassembler = (DTLSReassembler)currentInboundFlight.get(Integers.valueOf(seq));
- if (reassembler == null)
- {
- reassembler = new DTLSReassembler(msg_type, length);
- currentInboundFlight.put(Integers.valueOf(seq), reassembler);
- }
-
- reassembler.contributeFragment(msg_type, length, buf, 12, fragment_offset, fragment_length);
-
- if (seq == next_receive_seq)
- {
- byte[] body = reassembler.getBodyIfComplete();
- if (body != null)
- {
- previousInboundFlight = null;
- return updateHandshakeMessagesDigest(new Message(next_receive_seq++,
- reassembler.getType(), body));
- }
- }
- }
- }
- }
- catch (IOException e)
- {
- // NOTE: Assume this is a timeout for the moment
- }
-
- resendOutboundFlight();
-
- /*
- * TODO[DTLS] implementations SHOULD back off handshake packet size during the
- * retransmit backoff.
- */
- readTimeoutMillis = Math.min(readTimeoutMillis * 2, 60000);
- }
- }
-
- void finish()
- {
- DTLSHandshakeRetransmit retransmit = null;
- if (!sending)
- {
- checkInboundFlight();
- }
- else if (currentInboundFlight != null)
- {
- /*
- * RFC 6347 4.2.4. In addition, for at least twice the default MSL defined for [TCP],
- * when in the FINISHED state, the node that transmits the last flight (the server in an
- * ordinary handshake or the client in a resumed handshake) MUST respond to a retransmit
- * of the peer's last flight with a retransmit of the last flight.
- */
- retransmit = new DTLSHandshakeRetransmit()
- {
- public void receivedHandshakeRecord(int epoch, byte[] buf, int off, int len)
- throws IOException
- {
- /*
- * TODO Need to handle the case where the previous inbound flight contains
- * messages from two epochs.
- */
- if (len < 12)
- {
- return;
- }
- int fragment_length = TlsUtils.readUint24(buf, off + 9);
- if (len != (fragment_length + 12))
- {
- return;
- }
- int seq = TlsUtils.readUint16(buf, off + 4);
- if (seq >= next_receive_seq)
- {
- return;
- }
-
- short msg_type = TlsUtils.readUint8(buf, off);
-
- // TODO This is a hack that only works until we try to support renegotiation
- int expectedEpoch = msg_type == HandshakeType.finished ? 1 : 0;
- if (epoch != expectedEpoch)
- {
- return;
- }
-
- int length = TlsUtils.readUint24(buf, off + 1);
- int fragment_offset = TlsUtils.readUint24(buf, off + 6);
- if (fragment_offset + fragment_length > length)
- {
- return;
- }
-
- DTLSReassembler reassembler = (DTLSReassembler)currentInboundFlight.get(Integers.valueOf(seq));
- if (reassembler != null)
- {
- reassembler.contributeFragment(msg_type, length, buf, off + 12, fragment_offset,
- fragment_length);
- if (checkAll(currentInboundFlight))
- {
- resendOutboundFlight();
- resetAll(currentInboundFlight);
- }
- }
- }
- };
- }
-
- recordLayer.handshakeSuccessful(retransmit);
- }
-
- void resetHandshakeMessagesDigest()
- {
- handshakeHash.reset();
- }
-
- /**
- * Check that there are no "extra" messages left in the current inbound flight
- */
- private void checkInboundFlight()
- {
- Enumeration e = currentInboundFlight.keys();
- while (e.hasMoreElements())
- {
- Integer key = (Integer)e.nextElement();
- if (key.intValue() >= next_receive_seq)
- {
- // TODO Should this be considered an error?
- }
- }
- }
-
- private void prepareInboundFlight()
- {
- resetAll(currentInboundFlight);
- previousInboundFlight = currentInboundFlight;
- currentInboundFlight = new Hashtable();
- }
-
- private void resendOutboundFlight()
- throws IOException
- {
- recordLayer.resetWriteEpoch();
- for (int i = 0; i < outboundFlight.size(); ++i)
- {
- writeMessage((Message)outboundFlight.elementAt(i));
- }
- }
-
- private Message updateHandshakeMessagesDigest(Message message)
- throws IOException
- {
- if (message.getType() != HandshakeType.hello_request)
- {
- byte[] body = message.getBody();
- byte[] buf = new byte[12];
- TlsUtils.writeUint8(message.getType(), buf, 0);
- TlsUtils.writeUint24(body.length, buf, 1);
- TlsUtils.writeUint16(message.getSeq(), buf, 4);
- TlsUtils.writeUint24(0, buf, 6);
- TlsUtils.writeUint24(body.length, buf, 9);
- handshakeHash.update(buf, 0, buf.length);
- handshakeHash.update(body, 0, body.length);
- }
- return message;
- }
-
- private void writeMessage(Message message)
- throws IOException
- {
- int sendLimit = recordLayer.getSendLimit();
- int fragmentLimit = sendLimit - 12;
-
- // TODO Support a higher minimum fragment size?
- if (fragmentLimit < 1)
- {
- // TODO Should we be throwing an exception here?
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- int length = message.getBody().length;
-
- // NOTE: Must still send a fragment if body is empty
- int fragment_offset = 0;
- do
- {
- int fragment_length = Math.min(length - fragment_offset, fragmentLimit);
- writeHandshakeFragment(message, fragment_offset, fragment_length);
- fragment_offset += fragment_length;
- }
- while (fragment_offset < length);
- }
-
- private void writeHandshakeFragment(Message message, int fragment_offset, int fragment_length)
- throws IOException
- {
- 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)
- {
- Enumeration e = inboundFlight.elements();
- while (e.hasMoreElements())
- {
- if (((DTLSReassembler)e.nextElement()).getBodyIfComplete() == null)
- {
- return false;
- }
- }
- return true;
- }
-
- private static void resetAll(Hashtable inboundFlight)
- {
- Enumeration e = inboundFlight.elements();
- while (e.hasMoreElements())
- {
- ((DTLSReassembler)e.nextElement()).reset();
- }
- }
-
- static class Message
- {
- private final int message_seq;
- private final short msg_type;
- private final byte[] body;
-
- private Message(int message_seq, short msg_type, byte[] body)
- {
- this.message_seq = message_seq;
- this.msg_type = msg_type;
- this.body = body;
- }
-
- public int getSeq()
- {
- return message_seq;
- }
-
- public short getType()
- {
- return msg_type;
- }
-
- public byte[] getBody()
- {
- 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/core/src/main/java/org/bouncycastle/crypto/tls/DTLSReplayWindow.java b/core/src/main/java/org/bouncycastle/crypto/tls/DTLSReplayWindow.java
deleted file mode 100644
index 00bbf147..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/DTLSReplayWindow.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 4347 4.1.2.5 Anti-replay
- * <p/>
- * Support fast rejection of duplicate records by maintaining a sliding receive window
- */
-class DTLSReplayWindow
-{
- private static final long VALID_SEQ_MASK = 0x0000FFFFFFFFFFFFL;
-
- private static final long WINDOW_SIZE = 64L;
-
- private long latestConfirmedSeq = -1;
- private long bitmap = 0;
-
- /**
- * Check whether a received record with the given sequence number should be rejected as a duplicate.
- *
- * @param seq the 48-bit DTLSPlainText.sequence_number field of a received record.
- * @return true if the record should be discarded without further processing.
- */
- boolean shouldDiscard(long seq)
- {
- if ((seq & VALID_SEQ_MASK) != seq)
- {
- return true;
- }
-
- if (seq <= latestConfirmedSeq)
- {
- long diff = latestConfirmedSeq - seq;
- if (diff >= WINDOW_SIZE)
- {
- return true;
- }
- if ((bitmap & (1L << diff)) != 0)
- {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Report that a received record with the given sequence number passed authentication checks.
- *
- * @param seq the 48-bit DTLSPlainText.sequence_number field of an authenticated record.
- */
- void reportAuthenticated(long seq)
- {
- if ((seq & VALID_SEQ_MASK) != seq)
- {
- throw new IllegalArgumentException("'seq' out of range");
- }
-
- if (seq <= latestConfirmedSeq)
- {
- long diff = latestConfirmedSeq - seq;
- if (diff < WINDOW_SIZE)
- {
- bitmap |= (1L << diff);
- }
- }
- else
- {
- long diff = seq - latestConfirmedSeq;
- if (diff >= WINDOW_SIZE)
- {
- bitmap = 1;
- }
- else
- {
- bitmap <<= (int)diff; // for earlier JDKs
- bitmap |= 1;
- }
- latestConfirmedSeq = seq;
- }
- }
-
- /**
- * When a new epoch begins, sequence numbers begin again at 0
- */
- void reset()
- {
- latestConfirmedSeq = -1;
- bitmap = 0;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/DTLSServerProtocol.java b/core/src/main/java/org/bouncycastle/crypto/tls/DTLSServerProtocol.java
deleted file mode 100644
index 5f86eff5..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/DTLSServerProtocol.java
+++ /dev/null
@@ -1,667 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-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.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.util.PublicKeyFactory;
-import org.bouncycastle.util.Arrays;
-
-public class DTLSServerProtocol
- extends DTLSProtocol
-{
- protected boolean verifyRequests = true;
-
- public DTLSServerProtocol(SecureRandom secureRandom)
- {
- super(secureRandom);
- }
-
- public boolean getVerifyRequests()
- {
- return verifyRequests;
- }
-
- public void setVerifyRequests(boolean verifyRequests)
- {
- this.verifyRequests = verifyRequests;
- }
-
- public DTLSTransport accept(TlsServer server, DatagramTransport transport)
- throws IOException
- {
- if (server == null)
- {
- throw new IllegalArgumentException("'server' cannot be null");
- }
- if (transport == null)
- {
- throw new IllegalArgumentException("'transport' cannot be null");
- }
-
- SecurityParameters securityParameters = new SecurityParameters();
- securityParameters.entity = ConnectionEnd.server;
-
- ServerHandshakeState state = new ServerHandshakeState();
- state.server = server;
- state.serverContext = new TlsServerContextImpl(secureRandom, securityParameters);
-
- securityParameters.serverRandom = TlsProtocol.createRandomBlock(server.shouldUseGMTUnixTime(),
- state.serverContext.getNonceRandomGenerator());
-
- server.init(state.serverContext);
-
- DTLSRecordLayer recordLayer = new DTLSRecordLayer(transport, state.serverContext, server, ContentType.handshake);
-
- // TODO Need to handle sending of HelloVerifyRequest without entering a full connection
-
- try
- {
- return serverHandshake(state, recordLayer);
- }
- catch (TlsFatalAlert fatalAlert)
- {
- recordLayer.fail(fatalAlert.getAlertDescription());
- throw fatalAlert;
- }
- catch (IOException e)
- {
- recordLayer.fail(AlertDescription.internal_error);
- throw e;
- }
- catch (RuntimeException e)
- {
- recordLayer.fail(AlertDescription.internal_error);
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- protected DTLSTransport serverHandshake(ServerHandshakeState state, DTLSRecordLayer recordLayer)
- throws IOException
- {
- SecurityParameters securityParameters = state.serverContext.getSecurityParameters();
- DTLSReliableHandshake handshake = new DTLSReliableHandshake(state.serverContext, recordLayer);
-
- DTLSReliableHandshake.Message clientMessage = handshake.receiveMessage();
-
- {
- // NOTE: After receiving a record from the client, we discover the record layer version
- ProtocolVersion client_version = recordLayer.getDiscoveredPeerVersion();
- // TODO Read RFCs for guidance on the expected record layer version number
- state.serverContext.setClientVersion(client_version);
- }
-
- if (clientMessage.getType() == HandshakeType.client_hello)
- {
- processClientHello(state, clientMessage.getBody());
- }
- else
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
-
- {
- 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.sendMessage(HandshakeType.server_hello, serverHelloBody);
- }
-
- handshake.notifyHelloComplete();
-
- Vector serverSupplementalData = state.server.getServerSupplementalData();
- if (serverSupplementalData != null)
- {
- byte[] supplementalDataBody = generateSupplementalData(serverSupplementalData);
- handshake.sendMessage(HandshakeType.supplemental_data, supplementalDataBody);
- }
-
- state.keyExchange = state.server.getKeyExchange();
- state.keyExchange.init(state.serverContext);
-
- state.serverCredentials = state.server.getCredentials();
-
- Certificate serverCertificate = null;
-
- if (state.serverCredentials == null)
- {
- state.keyExchange.skipServerCredentials();
- }
- else
- {
- state.keyExchange.processServerCredentials(state.serverCredentials);
-
- 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)
- {
- handshake.sendMessage(HandshakeType.server_key_exchange, serverKeyExchange);
- }
-
- if (state.serverCredentials != null)
- {
- state.certificateRequest = state.server.getCertificateRequest();
- if (state.certificateRequest != null)
- {
- state.keyExchange.validateCertificateRequest(state.certificateRequest);
-
- 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)
- {
- processClientSupplementalData(state, clientMessage.getBody());
- clientMessage = handshake.receiveMessage();
- }
- else
- {
- state.server.processClientSupplementalData(null);
- }
-
- if (state.certificateRequest == null)
- {
- state.keyExchange.skipClientCredentials();
- }
- else
- {
- if (clientMessage.getType() == HandshakeType.certificate)
- {
- processClientCertificate(state, clientMessage.getBody());
- clientMessage = handshake.receiveMessage();
- }
- else
- {
- if (TlsUtils.isTLSv12(state.serverContext))
- {
- /*
- * RFC 5246 If no suitable certificate is available, the client MUST send a
- * certificate message containing no certificates.
- *
- * NOTE: In previous RFCs, this was SHOULD instead of MUST.
- */
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
-
- notifyClientCertificate(state, Certificate.EMPTY_CHAIN);
- }
- }
-
- if (clientMessage.getType() == HandshakeType.client_key_exchange)
- {
- processClientKeyExchange(state, clientMessage.getBody());
- }
- else
- {
- 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
- * parameters).
- */
- if (expectCertificateVerifyMessage(state))
- {
- byte[] certificateVerifyBody = handshake.receiveMessageBody(HandshakeType.certificate_verify);
- processCertificateVerify(state, certificateVerifyBody, prepareFinishHash);
- }
-
- // NOTE: Calculated exclusive of the actual Finished message from the client
- 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)
- {
- NewSessionTicket newSessionTicket = state.server.getNewSessionTicket();
- byte[] newSessionTicketBody = generateNewSessionTicket(state, newSessionTicket);
- handshake.sendMessage(HandshakeType.session_ticket, newSessionTicketBody);
- }
-
- // NOTE: Calculated exclusive of the Finished message itself
- byte[] serverVerifyData = TlsUtils.calculateVerifyData(state.serverContext, ExporterLabel.server_finished,
- TlsProtocol.getCurrentPRFHash(state.serverContext, handshake.getHandshakeHash(), null));
- handshake.sendMessage(HandshakeType.finished, serverVerifyData);
-
- handshake.finish();
-
- state.server.notifyHandshakeComplete();
-
- return new DTLSTransport(recordLayer);
- }
-
- protected byte[] generateCertificateRequest(ServerHandshakeState state, CertificateRequest certificateRequest)
- throws IOException
- {
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
- certificateRequest.encode(buf);
- return buf.toByteArray();
- }
-
- 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();
- }
-
- protected byte[] generateServerHello(ServerHandshakeState state)
- throws IOException
- {
- SecurityParameters securityParameters = state.serverContext.getSecurityParameters();
-
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
-
- ProtocolVersion server_version = state.server.getServerVersion();
- if (!server_version.isEqualOrEarlierVersionOf(state.serverContext.getClientVersion()))
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- // TODO Read RFCs for guidance on the expected record layer version number
- // recordStream.setReadVersion(server_version);
- // recordStream.setWriteVersion(server_version);
- // recordStream.setRestrictReadVersion(true);
- state.serverContext.setServerVersion(server_version);
-
- TlsUtils.writeVersion(state.serverContext.getServerVersion(), buf);
-
- buf.write(securityParameters.getServerRandom());
-
- /*
- * 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);
-
- state.selectedCipherSuite = state.server.getSelectedCipherSuite();
- if (!Arrays.contains(state.offeredCipherSuites, state.selectedCipherSuite)
- || state.selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL
- || state.selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV
- || !TlsUtils.isValidCipherSuiteForVersion(state.selectedCipherSuite, server_version))
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- validateSelectedCipherSuite(state.selectedCipherSuite, AlertDescription.internal_error);
-
- state.selectedCompressionMethod = state.server.getSelectedCompressionMethod();
- if (!Arrays.contains(state.offeredCompressionMethods, state.selectedCompressionMethod))
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- TlsUtils.writeUint16(state.selectedCipherSuite, buf);
- TlsUtils.writeUint8(state.selectedCompressionMethod, buf);
-
- state.serverExtensions = state.server.getServerExtensions();
-
- /*
- * RFC 5746 3.6. Server Behavior: Initial Handshake
- */
- if (state.secure_renegotiation)
- {
- byte[] renegExtData = TlsUtils.getExtensionData(state.serverExtensions, TlsProtocol.EXT_RenegotiationInfo);
- boolean noRenegExt = (null == renegExtData);
-
- if (noRenegExt)
- {
- /*
- * Note that sending a "renegotiation_info" extension in response to a ClientHello
- * containing only the SCSV is an explicit exception to the prohibition in RFC 5246,
- * Section 7.4.1.4, on the server sending unsolicited extensions and is only allowed
- * because the client is signaling its willingness to receive the extension via the
- * TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV.
- */
-
- /*
- * 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));
- }
- }
-
- if (state.serverExtensions != null)
- {
- securityParameters.encryptThenMAC = TlsExtensionsUtils.hasEncryptThenMACExtension(state.serverExtensions);
-
- 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);
- }
-
- return buf.toByteArray();
- }
-
- protected void notifyClientCertificate(ServerHandshakeState state, Certificate clientCertificate)
- throws IOException
- {
- if (state.certificateRequest == null)
- {
- throw new IllegalStateException();
- }
-
- if (state.clientCertificate != null)
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
-
- state.clientCertificate = clientCertificate;
-
- if (clientCertificate.isEmpty())
- {
- state.keyExchange.skipClientCredentials();
- }
- else
- {
-
- /*
- * TODO RFC 5246 7.4.6. If the certificate_authorities list in the certificate request
- * message was non-empty, one of the certificates in the certificate chain SHOULD be
- * issued by one of the listed CAs.
- */
-
- state.clientCertificateType = TlsUtils.getClientCertificateType(clientCertificate,
- state.serverCredentials.getCertificate());
-
- state.keyExchange.processClientCertificate(clientCertificate);
- }
-
- /*
- * RFC 5246 7.4.6. If the client does not send any certificates, the server MAY at its
- * discretion either continue the handshake without client authentication, or respond with a
- * fatal handshake_failure alert. Also, if some aspect of the certificate chain was
- * unacceptable (e.g., it was not signed by a known, trusted CA), the server MAY at its
- * discretion either continue the handshake (considering the client unauthenticated) or send
- * a fatal alert.
- */
- state.server.notifyClientCertificate(clientCertificate);
- }
-
- protected void processClientCertificate(ServerHandshakeState state, byte[] body)
- throws IOException
- {
- ByteArrayInputStream buf = new ByteArrayInputStream(body);
-
- Certificate clientCertificate = Certificate.parse(buf);
-
- TlsProtocol.assertEmpty(buf);
-
- notifyClientCertificate(state, clientCertificate);
- }
-
- protected void processCertificateVerify(ServerHandshakeState state, byte[] body, TlsHandshakeHash prepareFinishHash)
- throws IOException
- {
- ByteArrayInputStream buf = new ByteArrayInputStream(body);
-
- DigitallySigned clientCertificateVerify = DigitallySigned.parse(state.serverContext, buf);
-
- TlsProtocol.assertEmpty(buf);
-
- // Verify the CertificateVerify message contains a correct signature.
- boolean verified = false;
- try
- {
- byte[] certificateVerifyHash;
- if (TlsUtils.isTLSv12(state.serverContext))
- {
- certificateVerifyHash = prepareFinishHash.getFinalHash(clientCertificateVerify.getAlgorithm().getHash());
- }
- else
- {
- 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 tlsSigner = TlsUtils.createTlsSigner(state.clientCertificateType);
- tlsSigner.init(state.serverContext);
- verified = tlsSigner.verifyRawSignature(clientCertificateVerify.getAlgorithm(),
- clientCertificateVerify.getSignature(), publicKey, certificateVerifyHash);
- }
- catch (Exception e)
- {
- }
-
- if (!verified)
- {
- throw new TlsFatalAlert(AlertDescription.decrypt_error);
- }
- }
-
- 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
- ProtocolVersion client_version = TlsUtils.readVersion(buf);
- if (!client_version.isDTLS())
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- /*
- * Read the client random
- */
- byte[] client_random = TlsUtils.readFully(32, buf);
-
- byte[] sessionID = TlsUtils.readOpaque8(buf);
- if (sessionID.length > 32)
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- // TODO RFC 4347 has the cookie length restricted to 32, but not in RFC 6347
- byte[] cookie = TlsUtils.readOpaque8(buf);
-
- int cipher_suites_length = TlsUtils.readUint16(buf);
- if (cipher_suites_length < 2 || (cipher_suites_length & 1) != 0)
- {
- throw new TlsFatalAlert(AlertDescription.decode_error);
- }
-
- /*
- * 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."
- */
- state.offeredCipherSuites = TlsUtils.readUint16Array(cipher_suites_length / 2, buf);
-
- int compression_methods_length = TlsUtils.readUint8(buf);
- if (compression_methods_length < 1)
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- state.offeredCompressionMethods = TlsUtils.readUint8Array(compression_methods_length, buf);
-
- /*
- * 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.
- */
- state.clientExtensions = TlsProtocol.readExtensions(buf);
-
- state.serverContext.setClientVersion(client_version);
-
- state.server.notifyClientVersion(client_version);
-
- state.serverContext.getSecurityParameters().clientRandom = client_random;
-
- state.server.notifyOfferedCipherSuites(state.offeredCipherSuites);
- state.server.notifyOfferedCompressionMethods(state.offeredCompressionMethods);
-
- /*
- * RFC 5746 3.6. Server Behavior: Initial Handshake
- */
- {
- /*
- * RFC 5746 3.4. The client MUST include either an empty "renegotiation_info" extension,
- * or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling cipher suite value in the
- * ClientHello. Including both is NOT RECOMMENDED.
- */
-
- /*
- * When a ClientHello is received, the server MUST check if it includes the
- * TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. If it does, set the secure_renegotiation flag
- * to TRUE.
- */
- if (Arrays.contains(state.offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV))
- {
- state.secure_renegotiation = true;
- }
-
- /*
- * The server MUST check if the "renegotiation_info" extension is included in the
- * ClientHello.
- */
- byte[] renegExtData = TlsUtils.getExtensionData(state.clientExtensions, TlsProtocol.EXT_RenegotiationInfo);
- if (renegExtData != 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 (!Arrays.constantTimeAreEqual(renegExtData, TlsProtocol.createRenegotiationInfo(TlsUtils.EMPTY_BYTES)))
- {
- throw new TlsFatalAlert(AlertDescription.handshake_failure);
- }
- }
- }
-
- state.server.notifySecureRenegotiation(state.secure_renegotiation);
-
- if (state.clientExtensions != null)
- {
- state.server.processClientExtensions(state.clientExtensions);
- }
- }
-
- protected void processClientKeyExchange(ServerHandshakeState state, byte[] body)
- throws IOException
- {
- ByteArrayInputStream buf = new ByteArrayInputStream(body);
-
- state.keyExchange.processClientKeyExchange(buf);
-
- TlsProtocol.assertEmpty(buf);
- }
-
- protected void processClientSupplementalData(ServerHandshakeState state, byte[] body)
- throws IOException
- {
- ByteArrayInputStream buf = new ByteArrayInputStream(body);
- Vector clientSupplementalData = TlsProtocol.readSupplementalDataMessage(buf);
- state.server.processClientSupplementalData(clientSupplementalData);
- }
-
- protected boolean expectCertificateVerifyMessage(ServerHandshakeState state)
- {
- return state.clientCertificateType >= 0 && TlsUtils.hasSigningCapability(state.clientCertificateType);
- }
-
- protected static class ServerHandshakeState
- {
- TlsServer server = null;
- TlsServerContextImpl serverContext = null;
- int[] offeredCipherSuites;
- short[] offeredCompressionMethods;
- Hashtable clientExtensions;
- 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;
- TlsCredentials serverCredentials = null;
- CertificateRequest certificateRequest = null;
- short clientCertificateType = -1;
- Certificate clientCertificate = null;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/DTLSTransport.java b/core/src/main/java/org/bouncycastle/crypto/tls/DTLSTransport.java
deleted file mode 100644
index 45c2d30d..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/DTLSTransport.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-public class DTLSTransport
- implements DatagramTransport
-{
- private final DTLSRecordLayer recordLayer;
-
- DTLSTransport(DTLSRecordLayer recordLayer)
- {
- this.recordLayer = recordLayer;
- }
-
- public int getReceiveLimit()
- throws IOException
- {
- return recordLayer.getReceiveLimit();
- }
-
- public int getSendLimit()
- throws IOException
- {
- return recordLayer.getSendLimit();
- }
-
- public int receive(byte[] buf, int off, int len, int waitMillis)
- throws IOException
- {
- try
- {
- return recordLayer.receive(buf, off, len, waitMillis);
- }
- catch (TlsFatalAlert fatalAlert)
- {
- recordLayer.fail(fatalAlert.getAlertDescription());
- throw fatalAlert;
- }
- catch (IOException e)
- {
- recordLayer.fail(AlertDescription.internal_error);
- throw e;
- }
- catch (RuntimeException e)
- {
- recordLayer.fail(AlertDescription.internal_error);
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- public void send(byte[] buf, int off, int len)
- throws IOException
- {
- try
- {
- recordLayer.send(buf, off, len);
- }
- catch (TlsFatalAlert fatalAlert)
- {
- recordLayer.fail(fatalAlert.getAlertDescription());
- throw fatalAlert;
- }
- catch (IOException e)
- {
- recordLayer.fail(AlertDescription.internal_error);
- throw e;
- }
- catch (RuntimeException e)
- {
- recordLayer.fail(AlertDescription.internal_error);
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- public void close()
- throws IOException
- {
- recordLayer.close();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/DatagramTransport.java b/core/src/main/java/org/bouncycastle/crypto/tls/DatagramTransport.java
deleted file mode 100644
index 14972146..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/DatagramTransport.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-public interface DatagramTransport
-{
- int getReceiveLimit()
- throws IOException;
-
- int getSendLimit()
- throws IOException;
-
- int receive(byte[] buf, int off, int len, int waitMillis)
- throws IOException;
-
- void send(byte[] buf, int off, int len)
- throws IOException;
-
- void close()
- throws IOException;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsAgreementCredentials.java b/core/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsAgreementCredentials.java
deleted file mode 100644
index 78afb418..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsAgreementCredentials.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.BasicAgreement;
-import org.bouncycastle.crypto.agreement.DHBasicAgreement;
-import org.bouncycastle.crypto.agreement.ECDHBasicAgreement;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.util.BigIntegers;
-
-public class DefaultTlsAgreementCredentials
- extends AbstractTlsAgreementCredentials
-{
- protected Certificate certificate;
- protected AsymmetricKeyParameter privateKey;
-
- protected BasicAgreement basicAgreement;
- protected boolean truncateAgreement;
-
- public DefaultTlsAgreementCredentials(Certificate certificate, AsymmetricKeyParameter privateKey)
- {
- if (certificate == null)
- {
- throw new IllegalArgumentException("'certificate' cannot be null");
- }
- if (certificate.isEmpty())
- {
- throw new IllegalArgumentException("'certificate' cannot be empty");
- }
- if (privateKey == null)
- {
- throw new IllegalArgumentException("'privateKey' cannot be null");
- }
- if (!privateKey.isPrivate())
- {
- throw new IllegalArgumentException("'privateKey' must be private");
- }
-
- if (privateKey instanceof DHPrivateKeyParameters)
- {
- basicAgreement = new DHBasicAgreement();
- truncateAgreement = true;
- }
- else if (privateKey instanceof ECPrivateKeyParameters)
- {
- basicAgreement = new ECDHBasicAgreement();
- truncateAgreement = false;
- }
- else
- {
- throw new IllegalArgumentException("'privateKey' type not supported: "
- + privateKey.getClass().getName());
- }
-
- this.certificate = certificate;
- this.privateKey = privateKey;
- }
-
- public Certificate getCertificate()
- {
- return certificate;
- }
-
- public byte[] generateAgreement(AsymmetricKeyParameter peerPublicKey)
- {
- basicAgreement.init(privateKey);
- BigInteger agreementValue = basicAgreement.calculateAgreement(peerPublicKey);
-
- if (truncateAgreement)
- {
- return BigIntegers.asUnsignedByteArray(agreementValue);
- }
-
- return BigIntegers.asUnsignedByteArray(basicAgreement.getFieldSize(), agreementValue);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsCipherFactory.java b/core/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsCipherFactory.java
deleted file mode 100644
index 92caeb50..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsCipherFactory.java
+++ /dev/null
@@ -1,237 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.StreamCipher;
-import org.bouncycastle.crypto.digests.MD5Digest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.digests.SHA384Digest;
-import org.bouncycastle.crypto.digests.SHA512Digest;
-import org.bouncycastle.crypto.engines.AESEngine;
-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.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.AEAD_CHACHA20_POLY1305:
- // NOTE: Ignores macAlgorithm
- return createChaCha20Poly1305(context);
- 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);
- case EncryptionAlgorithm.AES_256_CBC:
- return createAESCipher(context, 32, macAlgorithm);
- case EncryptionAlgorithm.AES_256_GCM:
- // NOTE: Ignores macAlgorithm
- return createCipher_AES_GCM(context, 32, 16);
- case EncryptionAlgorithm.CAMELLIA_128_CBC:
- return createCamelliaCipher(context, 16, macAlgorithm);
- case EncryptionAlgorithm.CAMELLIA_128_GCM:
- // NOTE: Ignores macAlgorithm
- return createCipher_Camellia_GCM(context, 16, 16);
- case EncryptionAlgorithm.CAMELLIA_256_CBC:
- return createCamelliaCipher(context, 32, macAlgorithm);
- case EncryptionAlgorithm.CAMELLIA_256_GCM:
- // NOTE: Ignores macAlgorithm
- return createCipher_Camellia_GCM(context, 32, 16);
- 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:
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- protected TlsBlockCipher createAESCipher(TlsContext context, int cipherKeySize, int macAlgorithm)
- throws IOException
- {
- return new TlsBlockCipher(context, createAESBlockCipher(), createAESBlockCipher(),
- createHMACDigest(macAlgorithm), createHMACDigest(macAlgorithm), cipherKeySize);
- }
-
- protected TlsBlockCipher createCamelliaCipher(TlsContext context, int cipherKeySize, int macAlgorithm)
- throws IOException
- {
- return new TlsBlockCipher(context, createCamelliaBlockCipher(),
- createCamelliaBlockCipher(), createHMACDigest(macAlgorithm),
- createHMACDigest(macAlgorithm), cipherKeySize);
- }
-
- protected TlsCipher createChaCha20Poly1305(TlsContext context) throws IOException
- {
- return new Chacha20Poly1305(context);
- }
-
- 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
- {
- return new TlsAEADCipher(context, createAEADBlockCipher_AES_GCM(),
- createAEADBlockCipher_AES_GCM(), cipherKeySize, macSize);
- }
-
- protected TlsAEADCipher createCipher_Camellia_GCM(TlsContext context, int cipherKeySize, int macSize)
- throws IOException
- {
- return new TlsAEADCipher(context, createAEADBlockCipher_Camellia_GCM(),
- createAEADBlockCipher_Camellia_GCM(), cipherKeySize, macSize);
- }
-
- 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
- {
- return new TlsNullCipher(context, createHMACDigest(macAlgorithm),
- createHMACDigest(macAlgorithm));
- }
-
- protected TlsStreamCipher createRC4Cipher(TlsContext context, int cipherKeySize, int macAlgorithm)
- throws IOException
- {
- return new TlsStreamCipher(context, createRC4StreamCipher(), createRC4StreamCipher(),
- createHMACDigest(macAlgorithm), createHMACDigest(macAlgorithm), cipherKeySize, false);
- }
-
- protected TlsStreamCipher createSalsa20Cipher(TlsContext context, int rounds, int cipherKeySize, int macAlgorithm)
- throws IOException
- {
- return new TlsStreamCipher(context, createSalsa20StreamCipher(rounds), createSalsa20StreamCipher(rounds),
- createHMACDigest(macAlgorithm), createHMACDigest(macAlgorithm), cipherKeySize, true);
- }
-
- protected TlsBlockCipher createSEEDCipher(TlsContext context, int macAlgorithm)
- throws IOException
- {
- return new TlsBlockCipher(context, createSEEDBlockCipher(), createSEEDBlockCipher(),
- createHMACDigest(macAlgorithm), createHMACDigest(macAlgorithm), 16);
- }
-
- protected BlockCipher createAESEngine()
- {
- return new AESEngine();
- }
-
- protected BlockCipher createCamelliaEngine()
- {
- return new CamelliaEngine();
- }
-
- protected BlockCipher createAESBlockCipher()
- {
- return new CBCBlockCipher(createAESEngine());
- }
-
- protected AEADBlockCipher createAEADBlockCipher_AES_CCM()
- {
- return new CCMBlockCipher(createAESEngine());
- }
-
- protected AEADBlockCipher createAEADBlockCipher_AES_GCM()
- {
- // TODO Consider allowing custom configuration of multiplier
- return new GCMBlockCipher(createAESEngine());
- }
-
- protected AEADBlockCipher createAEADBlockCipher_Camellia_GCM()
- {
- // TODO Consider allowing custom configuration of multiplier
- return new GCMBlockCipher(createCamelliaEngine());
- }
-
- protected BlockCipher createCamelliaBlockCipher()
- {
- return new CBCBlockCipher(createCamelliaEngine());
- }
-
- protected BlockCipher createDESedeBlockCipher()
- {
- 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
- {
- switch (macAlgorithm)
- {
- case MACAlgorithm._null:
- return null;
- case MACAlgorithm.hmac_md5:
- return TlsUtils.createHash(HashAlgorithm.md5);
- case MACAlgorithm.hmac_sha1:
- return TlsUtils.createHash(HashAlgorithm.sha1);
- case MACAlgorithm.hmac_sha256:
- return TlsUtils.createHash(HashAlgorithm.sha256);
- case MACAlgorithm.hmac_sha384:
- return TlsUtils.createHash(HashAlgorithm.sha384);
- case MACAlgorithm.hmac_sha512:
- return TlsUtils.createHash(HashAlgorithm.sha512);
- default:
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsClient.java b/core/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsClient.java
deleted file mode 100644
index 8f5b900e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsClient.java
+++ /dev/null
@@ -1,453 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-public abstract class DefaultTlsClient
- extends AbstractTlsClient
-{
- public DefaultTlsClient()
- {
- super();
- }
-
- public DefaultTlsClient(TlsCipherFactory cipherFactory)
- {
- super(cipherFactory);
- }
-
- public int[] getCipherSuites()
- {
- 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:
- case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA:
- return createDHKeyExchange(KeyExchangeAlgorithm.DH_DSS);
-
- case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
- 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_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA:
- return createDHKeyExchange(KeyExchangeAlgorithm.DH_RSA);
-
- case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
- 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_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA:
- return createDHEKeyExchange(KeyExchangeAlgorithm.DHE_DSS);
-
- 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_128_CBC_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
- case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1:
- case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
- return createDHEKeyExchange(KeyExchangeAlgorithm.DHE_RSA);
-
- case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
- return createECDHKeyExchange(KeyExchangeAlgorithm.ECDH_ECDSA);
-
- case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
- return createECDHKeyExchange(KeyExchangeAlgorithm.ECDH_RSA);
-
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
- 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_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
- 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:
- return createECDHEKeyExchange(KeyExchangeAlgorithm.ECDHE_ECDSA);
-
- case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
- 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_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
- 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:
- 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_128_CBC_SHA256:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1:
- 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_SEED_CBC_SHA:
- return createRSAKeyExchange();
-
- default:
- /*
- * Note: internal error here; the TlsProtocol implementation verifies that the
- * server-selected cipher suite was in the list of client-offered cipher suites, so if
- * we now can't produce an implementation, we shouldn't have offered it!
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- public TlsCipher getCipher()
- throws IOException
- {
- switch (selectedCipherSuite)
- {
- case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
- return cipherFactory.createCipher(context, EncryptionAlgorithm._3DES_EDE_CBC, MACAlgorithm.hmac_sha1);
-
- case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.AEAD_CHACHA20_POLY1305, MACAlgorithm._null);
-
- case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_CBC, MACAlgorithm.hmac_sha1);
-
- 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:
- 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:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_GCM, MACAlgorithm._null);
-
- case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_CBC, MACAlgorithm.hmac_sha1);
-
- 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:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_CBC, MACAlgorithm.hmac_sha256);
-
- 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:
- 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:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_GCM, MACAlgorithm._null);
-
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_CBC, MACAlgorithm.hmac_sha1);
-
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_CBC, MACAlgorithm.hmac_sha256);
-
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_GCM, MACAlgorithm._null);
-
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_CBC, MACAlgorithm.hmac_sha1);
-
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_CBC, MACAlgorithm.hmac_sha256);
-
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_GCM, MACAlgorithm._null);
-
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_CBC, MACAlgorithm.hmac_sha384);
-
- 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_RSA_WITH_NULL_MD5:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.NULL, MACAlgorithm.hmac_md5);
-
- case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
- case CipherSuite.TLS_RSA_WITH_NULL_SHA:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.NULL, MACAlgorithm.hmac_sha1);
-
- case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.NULL, MACAlgorithm.hmac_sha256);
-
- case CipherSuite.TLS_RSA_WITH_RC4_128_MD5:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.RC4_128, MACAlgorithm.hmac_md5);
-
- case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
- 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_DH_DSS_WITH_SEED_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
- case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.SEED_CBC, MACAlgorithm.hmac_sha1);
-
- default:
- /*
- * Note: internal error here; the TlsProtocol implementation verifies that the
- * server-selected cipher suite was in the list of client-offered cipher suites, so if
- * we now can't produce an implementation, we shouldn't have offered it!
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- protected TlsKeyExchange createDHKeyExchange(int keyExchange)
- {
- return new TlsDHKeyExchange(keyExchange, supportedSignatureAlgorithms, null);
- }
-
- protected TlsKeyExchange createDHEKeyExchange(int keyExchange)
- {
- return new TlsDHEKeyExchange(keyExchange, supportedSignatureAlgorithms, null);
- }
-
- protected TlsKeyExchange createECDHKeyExchange(int keyExchange)
- {
- return new TlsECDHKeyExchange(keyExchange, supportedSignatureAlgorithms, namedCurves, clientECPointFormats,
- serverECPointFormats);
- }
-
- protected TlsKeyExchange createECDHEKeyExchange(int keyExchange)
- {
- return new TlsECDHEKeyExchange(keyExchange, supportedSignatureAlgorithms, namedCurves, clientECPointFormats,
- serverECPointFormats);
- }
-
- protected TlsKeyExchange createRSAKeyExchange()
- {
- return new TlsRSAKeyExchange(supportedSignatureAlgorithms);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsEncryptionCredentials.java b/core/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsEncryptionCredentials.java
deleted file mode 100644
index 54bcd90c..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsEncryptionCredentials.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.encodings.PKCS1Encoding;
-import org.bouncycastle.crypto.engines.RSABlindedEngine;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-
-public class DefaultTlsEncryptionCredentials extends AbstractTlsEncryptionCredentials
-{
- protected TlsContext context;
- protected Certificate certificate;
- protected AsymmetricKeyParameter privateKey;
-
- public DefaultTlsEncryptionCredentials(TlsContext context, Certificate certificate,
- AsymmetricKeyParameter privateKey)
- {
- if (certificate == null)
- {
- throw new IllegalArgumentException("'certificate' cannot be null");
- }
- if (certificate.isEmpty())
- {
- throw new IllegalArgumentException("'certificate' cannot be empty");
- }
- if (privateKey == null)
- {
- throw new IllegalArgumentException("'privateKey' cannot be null");
- }
- if (!privateKey.isPrivate())
- {
- throw new IllegalArgumentException("'privateKey' must be private");
- }
-
- if (privateKey instanceof RSAKeyParameters)
- {
- }
- else
- {
- throw new IllegalArgumentException("'privateKey' type not supported: "
- + privateKey.getClass().getName());
- }
-
- this.context = context;
- this.certificate = certificate;
- this.privateKey = privateKey;
- }
-
- public Certificate getCertificate()
- {
- return certificate;
- }
-
- public byte[] decryptPreMasterSecret(byte[] encryptedPreMasterSecret)
- throws IOException
- {
- return TlsRSAUtils.safeDecryptPreMasterSecret(context, (RSAKeyParameters)privateKey, encryptedPreMasterSecret);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsServer.java b/core/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsServer.java
deleted file mode 100644
index f8f83465..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsServer.java
+++ /dev/null
@@ -1,550 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-import org.bouncycastle.crypto.agreement.DHStandardGroups;
-import org.bouncycastle.crypto.params.DHParameters;
-
-public abstract class DefaultTlsServer
- extends AbstractTlsServer
-{
- public DefaultTlsServer()
- {
- super();
- }
-
- public DefaultTlsServer(TlsCipherFactory cipherFactory)
- {
- super(cipherFactory);
- }
-
- protected TlsEncryptionCredentials getRSAEncryptionCredentials()
- throws IOException
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- protected TlsSignerCredentials getRSASignerCredentials()
- throws IOException
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- protected DHParameters getDHParameters()
- {
- return DHStandardGroups.rfc5114_1024_160;
- }
-
- protected int[] getCipherSuites()
- {
- return new int[]
- {
- CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
- CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
- CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
- CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
- CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
- CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
- CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384,
- CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256,
- CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256,
- CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256,
- CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA,
- CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,
- };
- }
-
- 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_128_CBC_SHA256:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- 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_SEED_CBC_SHA:
- return getRSAEncryptionCredentials();
-
- 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_128_CBC_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
- 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_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
- 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:
- return getRSASignerCredentials();
-
- default:
- /*
- * Note: internal error here; selected a key exchange we don't implement!
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- public TlsKeyExchange getKeyExchange()
- throws IOException
- {
- switch (selectedCipherSuite)
- {
- case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA:
- return createDHKeyExchange(KeyExchangeAlgorithm.DH_DSS);
-
- case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
- 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_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA:
- return createDHKeyExchange(KeyExchangeAlgorithm.DH_RSA);
-
- case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
- 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_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA:
- return createDHEKeyExchange(KeyExchangeAlgorithm.DHE_DSS);
-
- 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_128_CBC_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
- case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1:
- case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
- return createDHEKeyExchange(KeyExchangeAlgorithm.DHE_RSA);
-
- case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
- return createECDHKeyExchange(KeyExchangeAlgorithm.ECDH_ECDSA);
-
- case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
- return createECDHKeyExchange(KeyExchangeAlgorithm.ECDH_RSA);
-
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
- 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_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
- 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:
- return createECDHEKeyExchange(KeyExchangeAlgorithm.ECDHE_ECDSA);
-
- case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
- 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_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
- 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:
- 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_128_CBC_SHA256:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1:
- 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_SEED_CBC_SHA:
- return createRSAKeyExchange();
-
- default:
- /*
- * Note: internal error here; selected a key exchange we don't implement!
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- public TlsCipher getCipher()
- throws IOException
- {
- switch (selectedCipherSuite)
- {
- case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
- return cipherFactory.createCipher(context, EncryptionAlgorithm._3DES_EDE_CBC, MACAlgorithm.hmac_sha1);
-
- case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.AEAD_CHACHA20_POLY1305, MACAlgorithm._null);
-
- case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_CBC, MACAlgorithm.hmac_sha1);
-
- 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:
- 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:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_GCM, MACAlgorithm._null);
-
- case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_CBC, MACAlgorithm.hmac_sha1);
-
- 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:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_CBC, MACAlgorithm.hmac_sha256);
-
- 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:
- 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:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_GCM, MACAlgorithm._null);
-
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_CBC, MACAlgorithm.hmac_sha1);
-
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_CBC, MACAlgorithm.hmac_sha256);
-
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_GCM, MACAlgorithm._null);
-
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_CBC, MACAlgorithm.hmac_sha1);
-
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_CBC, MACAlgorithm.hmac_sha256);
-
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_GCM, MACAlgorithm._null);
-
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_CBC, MACAlgorithm.hmac_sha384);
-
- 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_RSA_WITH_NULL_MD5:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.NULL, MACAlgorithm.hmac_md5);
-
- case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
- case CipherSuite.TLS_RSA_WITH_NULL_SHA:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.NULL, MACAlgorithm.hmac_sha1);
-
- case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.NULL, MACAlgorithm.hmac_sha256);
-
- case CipherSuite.TLS_RSA_WITH_RC4_128_MD5:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.RC4_128, MACAlgorithm.hmac_md5);
-
- case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
- 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_DH_DSS_WITH_SEED_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
- case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.SEED_CBC, MACAlgorithm.hmac_sha1);
-
- default:
- /*
- * Note: internal error here; selected a cipher suite we don't implement!
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- protected TlsKeyExchange createDHKeyExchange(int keyExchange)
- {
- return new TlsDHKeyExchange(keyExchange, supportedSignatureAlgorithms, getDHParameters());
- }
-
- protected TlsKeyExchange createDHEKeyExchange(int keyExchange)
- {
- return new TlsDHEKeyExchange(keyExchange, supportedSignatureAlgorithms, getDHParameters());
- }
-
- protected TlsKeyExchange createECDHKeyExchange(int keyExchange)
- {
- return new TlsECDHKeyExchange(keyExchange, supportedSignatureAlgorithms, namedCurves, clientECPointFormats,
- serverECPointFormats);
- }
-
- protected TlsKeyExchange createECDHEKeyExchange(int keyExchange)
- {
- return new TlsECDHEKeyExchange(keyExchange, supportedSignatureAlgorithms, namedCurves, clientECPointFormats,
- serverECPointFormats);
- }
-
- protected TlsKeyExchange createRSAKeyExchange()
- {
- return new TlsRSAKeyExchange(supportedSignatureAlgorithms);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsSignerCredentials.java b/core/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsSignerCredentials.java
deleted file mode 100755
index 15bf4a40..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsSignerCredentials.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-
-public class DefaultTlsSignerCredentials
- 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");
- }
- if (certificate.isEmpty())
- {
- throw new IllegalArgumentException("'certificate' cannot be empty");
- }
- if (privateKey == null)
- {
- throw new IllegalArgumentException("'privateKey' cannot be null");
- }
- if (!privateKey.isPrivate())
- {
- 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)
- {
- this.signer = new TlsRSASigner();
- }
- else if (privateKey instanceof DSAPrivateKeyParameters)
- {
- this.signer = new TlsDSSSigner();
- }
- else if (privateKey instanceof ECPrivateKeyParameters)
- {
- this.signer = new TlsECDSASigner();
- }
- else
- {
- throw new IllegalArgumentException("'privateKey' type not supported: " + privateKey.getClass().getName());
- }
-
- this.signer.init(context);
-
- this.context = context;
- this.certificate = certificate;
- this.privateKey = privateKey;
- this.signatureAndHashAlgorithm = signatureAndHashAlgorithm;
- }
-
- public Certificate getCertificate()
- {
- return certificate;
- }
-
- public byte[] generateCertificateSignature(byte[] hash)
- throws IOException
- {
- try
- {
- 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/core/src/main/java/org/bouncycastle/crypto/tls/DeferredHash.java b/core/src/main/java/org/bouncycastle/crypto/tls/DeferredHash.java
deleted file mode 100644
index 274e69a3..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/DeferredHash.java
+++ /dev/null
@@ -1,207 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-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.
- */
-class DeferredHash
- implements TlsHandshakeHash
-{
- protected static final int BUFFERING_HASH_LIMIT = 4;
-
- protected TlsContext context;
-
- private DigestInputBuffer buf;
- private Hashtable hashes;
- private Short prfHashAlgorithm;
-
- DeferredHash()
- {
- this.buf = new DigestInputBuffer();
- this.hashes = new Hashtable();
- this.prfHashAlgorithm = null;
- }
-
- private DeferredHash(Short prfHashAlgorithm, Digest prfHash)
- {
- this.buf = null;
- this.hashes = new Hashtable();
- this.prfHashAlgorithm = prfHashAlgorithm;
- hashes.put(prfHashAlgorithm, prfHash);
- }
-
- public void init(TlsContext context)
- {
- this.context = context;
- }
-
- 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();
- }
-
- this.prfHashAlgorithm = Shorts.valueOf(TlsUtils.getHashAlgorithmForPRFAlgorithm(prfAlgorithm));
-
- checkTrackingHash(prfHashAlgorithm);
-
- return this;
- }
-
- public void trackHashAlgorithm(short hashAlgorithm)
- {
- if (buf == null)
- {
- throw new IllegalStateException("Too late to track more hash algorithms");
- }
-
- checkTrackingHash(Shorts.valueOf(hashAlgorithm));
- }
-
- public void sealHashAlgorithms()
- {
- checkStopBuffering();
- }
-
- public TlsHandshakeHash stopTracking()
- {
- 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()
- {
- throw new IllegalStateException("Use fork() to get a definite Digest");
- }
-
- public int getDigestSize()
- {
- throw new IllegalStateException("Use fork() to get a definite Digest");
- }
-
- public void update(byte input)
- {
- if (buf != null)
- {
- buf.write(input);
- return;
- }
-
- 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 (buf != null)
- {
- buf.write(input, inOff, len);
- return;
- }
-
- Enumeration e = hashes.elements();
- while (e.hasMoreElements())
- {
- Digest hash = (Digest)e.nextElement();
- hash.update(input, inOff, len);
- }
- }
-
- public int doFinal(byte[] output, int outOff)
- {
- throw new IllegalStateException("Use fork() to get a definite Digest");
- }
-
- public void reset()
- {
- if (buf != null)
- {
- buf.reset();
- return;
- }
-
- Enumeration e = hashes.elements();
- while (e.hasMoreElements())
- {
- Digest hash = (Digest)e.nextElement();
- hash.reset();
- }
- }
-
- 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 (!hashes.containsKey(hashAlgorithm))
- {
- Digest hash = TlsUtils.createHash(hashAlgorithm.shortValue());
- hashes.put(hashAlgorithm, hash);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/DigestAlgorithm.java b/core/src/main/java/org/bouncycastle/crypto/tls/DigestAlgorithm.java
deleted file mode 100644
index 8bb89a66..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/DigestAlgorithm.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 2246
- * <p>
- * Note that the values here are implementation-specific and arbitrary. It is recommended not to
- * depend on the particular values (e.g. serialization).
- *
- * @deprecated use MACAlgorithm constants instead
- */
-public class DigestAlgorithm
-{
- public static final int NULL = 0;
- public static final int MD5 = 1;
- public static final int SHA = 2;
-
- /*
- * RFC 5246
- */
- public static final int SHA256 = 3;
- public static final int SHA384 = 4;
- public static final int SHA512 = 5;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/DigestInputBuffer.java b/core/src/main/java/org/bouncycastle/crypto/tls/DigestInputBuffer.java
deleted file mode 100644
index 7cfa8909..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/DigestInputBuffer.java
+++ /dev/null
@@ -1,13 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/tls/DigitallySigned.java b/core/src/main/java/org/bouncycastle/crypto/tls/DigitallySigned.java
deleted file mode 100644
index c366ca9d..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/DigitallySigned.java
+++ /dev/null
@@ -1,72 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/tls/ECBasisType.java b/core/src/main/java/org/bouncycastle/crypto/tls/ECBasisType.java
deleted file mode 100644
index 630dfcd6..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/ECBasisType.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 4492 5.4. (Errata ID: 2389)
- */
-public class ECBasisType
-{
- public static final short ec_basis_trinomial = 1;
- public static final short ec_basis_pentanomial = 2;
-
- public static boolean isValid(short ecBasisType)
- {
- return ecBasisType >= ec_basis_trinomial && ecBasisType <= ec_basis_pentanomial;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/ECCurveType.java b/core/src/main/java/org/bouncycastle/crypto/tls/ECCurveType.java
deleted file mode 100644
index 0b6542fc..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/ECCurveType.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 4492 5.4
- */
-public class ECCurveType
-{
- /**
- * Indicates the elliptic curve domain parameters are conveyed verbosely, and the
- * underlying finite field is a prime field.
- */
- public static final short explicit_prime = 1;
-
- /**
- * Indicates the elliptic curve domain parameters are conveyed verbosely, and the
- * underlying finite field is a characteristic-2 field.
- */
- public static final short explicit_char2 = 2;
-
- /**
- * Indicates that a named curve is used. This option SHOULD be used when applicable.
- */
- public static final short named_curve = 3;
-
- /*
- * Values 248 through 255 are reserved for private use.
- */
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/ECPointFormat.java b/core/src/main/java/org/bouncycastle/crypto/tls/ECPointFormat.java
deleted file mode 100644
index 969d42ee..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/ECPointFormat.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 4492 5.1.2
- */
-public class ECPointFormat
-{
- public static final short uncompressed = 0;
- public static final short ansiX962_compressed_prime = 1;
- public static final short ansiX962_compressed_char2 = 2;
-
- /*
- * reserved (248..255)
- */
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/EncryptionAlgorithm.java b/core/src/main/java/org/bouncycastle/crypto/tls/EncryptionAlgorithm.java
deleted file mode 100644
index 2da2f76a..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/EncryptionAlgorithm.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 2246
- * <p>
- * Note that the values here are implementation-specific and arbitrary. It is recommended not to
- * depend on the particular values (e.g. serialization).
- */
-public class EncryptionAlgorithm
-{
- public static final int NULL = 0;
- public static final int RC4_40 = 1;
- public static final int RC4_128 = 2;
- public static final int RC2_CBC_40 = 3;
- public static final int IDEA_CBC = 4;
- public static final int DES40_CBC = 5;
- public static final int DES_CBC = 6;
- public static final int _3DES_EDE_CBC = 7;
-
- /*
- * RFC 3268
- */
- public static final int AES_128_CBC = 8;
- 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 5932
- */
- public static final int CAMELLIA_128_CBC = 12;
- public static final int CAMELLIA_256_CBC = 13;
-
- /*
- * RFC 4162
- */
- public static final int SEED_CBC = 14;
-
- /*
- * RFC 6655
- */
- 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;
-
- /*
- * RFC 6367
- */
- public static final int CAMELLIA_128_GCM = 19;
- public static final int CAMELLIA_256_GCM = 20;
-
- /*
- * draft-josefsson-salsa20-tls-04
- */
- public static final int ESTREAM_SALSA20 = 100;
- public static final int SALSA20 = 101;
-
- /*
- * draft-agl-tls-chacha20poly1305-04
- */
- public static final int AEAD_CHACHA20_POLY1305 = 102;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/ExporterLabel.java b/core/src/main/java/org/bouncycastle/crypto/tls/ExporterLabel.java
deleted file mode 100644
index 902720ac..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/ExporterLabel.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 5705
- */
-public class ExporterLabel
-{
- /*
- * RFC 5246
- */
- public static final String client_finished = "client finished";
- public static final String server_finished = "server finished";
- public static final String master_secret = "master secret";
- public static final String key_expansion = "key expansion";
-
- /*
- * RFC 5216
- */
- public static final String client_EAP_encryption = "client EAP encryption";
-
- /*
- * RFC 5281
- */
- public static final String ttls_keying_material = "ttls keying material";
- public static final String ttls_challenge = "ttls challenge";
-
- /*
- * RFC 5764
- */
- public static final String dtls_srtp = "EXTRACTOR-dtls_srtp";
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/ExtensionType.java b/core/src/main/java/org/bouncycastle/crypto/tls/ExtensionType.java
deleted file mode 100644
index c0a7a90a..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/ExtensionType.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-public class ExtensionType
-{
- /*
- * RFC 2546 2.3.
- */
- public static final int server_name = 0;
- public static final int max_fragment_length = 1;
- public static final int client_certificate_url = 2;
- public static final int trusted_ca_keys = 3;
- public static final int truncated_hmac = 4;
- public static final int status_request = 5;
-
- /*
- * RFC 4681
- */
- public static final int user_mapping = 6;
-
- /*
- * RFC 4492 5.1.
- */
- public static final int elliptic_curves = 10;
- public static final int ec_point_formats = 11;
-
- /*
- * RFC 5054 2.8.1.
- */
- public static final int srp = 12;
-
- /*
- * RFC 5246 7.4.1.4.
- */
- public static final int signature_algorithms = 13;
-
- /*
- * RFC 5764 9.
- */
- public static final int use_srtp = 14;
-
- /*
- * RFC 6520 6.
- */
- public static final int heartbeat = 15;
-
- /*
- * RFC 5077 7.
- */
- public static final int session_ticket = 35;
-
- /*
- * draft-ietf-tls-encrypt-then-mac-03
- */
- public static final int encrypt_then_mac = 22;
-
- /*
- * RFC 5746 3.2.
- */
- public static final int renegotiation_info = 0xff01;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/HandshakeType.java b/core/src/main/java/org/bouncycastle/crypto/tls/HandshakeType.java
deleted file mode 100644
index c81660a5..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/HandshakeType.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-public class HandshakeType
-{
- /*
- * RFC 2246 7.4
- */
- public static final short hello_request = 0;
- public static final short client_hello = 1;
- public static final short server_hello = 2;
- public static final short certificate = 11;
- public static final short server_key_exchange = 12;
- public static final short certificate_request = 13;
- public static final short server_hello_done = 14;
- public static final short certificate_verify = 15;
- public static final short client_key_exchange = 16;
- 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;
-
- /*
- * RFC 4680
- */
- public static final short supplemental_data = 23;
-
- /*
- * RFC 5077
- */
- public static final short session_ticket = 4;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/HashAlgorithm.java b/core/src/main/java/org/bouncycastle/crypto/tls/HashAlgorithm.java
deleted file mode 100644
index dc7482b8..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/HashAlgorithm.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 5246 7.4.1.4.1
- */
-public class HashAlgorithm
-{
- public static final short none = 0;
- public static final short md5 = 1;
- public static final short sha1 = 2;
- public static final short sha224 = 3;
- public static final short sha256 = 4;
- public static final short sha384 = 5;
- public static final short sha512 = 6;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/HeartbeatExtension.java b/core/src/main/java/org/bouncycastle/crypto/tls/HeartbeatExtension.java
deleted file mode 100644
index f9f3670e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/HeartbeatExtension.java
+++ /dev/null
@@ -1,56 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMessage.java b/core/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMessage.java
deleted file mode 100644
index c6a447fc..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMessage.java
+++ /dev/null
@@ -1,111 +0,0 @@
-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.getNonceRandomGenerator().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;
-
- /*
- * RFC 6520 4. The padding of a received HeartbeatMessage message MUST be ignored
- */
- 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/core/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMessageType.java b/core/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMessageType.java
deleted file mode 100644
index f1a3b43a..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMessageType.java
+++ /dev/null
@@ -1,15 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMode.java b/core/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMode.java
deleted file mode 100644
index 4024faaf..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMode.java
+++ /dev/null
@@ -1,15 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/tls/KeyExchangeAlgorithm.java b/core/src/main/java/org/bouncycastle/crypto/tls/KeyExchangeAlgorithm.java
deleted file mode 100644
index d862d769..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/KeyExchangeAlgorithm.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 2246
- * <p>
- * Note that the values here are implementation-specific and arbitrary. It is recommended not to
- * depend on the particular values (e.g. serialization).
- */
-public class KeyExchangeAlgorithm
-{
- public static final int NULL = 0;
- public static final int RSA = 1;
- public static final int RSA_EXPORT = 2;
- public static final int DHE_DSS = 3;
- public static final int DHE_DSS_EXPORT = 4;
- public static final int DHE_RSA = 5;
- public static final int DHE_RSA_EXPORT = 6;
- public static final int DH_DSS = 7;
- public static final int DH_DSS_EXPORT = 8;
- public static final int DH_RSA = 9;
- public static final int DH_RSA_EXPORT = 10;
- public static final int DH_anon = 11;
- public static final int DH_anon_EXPORT = 12;
-
- /*
- * RFC 4279
- */
- public static final int PSK = 13;
- public static final int DHE_PSK = 14;
- public static final int RSA_PSK = 15;
-
- /*
- * RFC 4429
- */
- public static final int ECDH_ECDSA = 16;
- public static final int ECDHE_ECDSA = 17;
- public static final int ECDH_RSA = 18;
- public static final int ECDHE_RSA = 19;
- public static final int ECDH_anon = 20;
-
- /*
- * RFC 5054
- */
- 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/core/src/main/java/org/bouncycastle/crypto/tls/LegacyTlsAuthentication.java b/core/src/main/java/org/bouncycastle/crypto/tls/LegacyTlsAuthentication.java
deleted file mode 100644
index f638714e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/LegacyTlsAuthentication.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-/**
- * A temporary class to wrap old CertificateVerifyer stuff for new TlsAuthentication
- *
- * @deprecated
- */
-public class LegacyTlsAuthentication
- extends ServerOnlyTlsAuthentication
-{
- protected CertificateVerifyer verifyer;
-
- public LegacyTlsAuthentication(CertificateVerifyer verifyer)
- {
- this.verifyer = verifyer;
- }
-
- public void notifyServerCertificate(Certificate serverCertificate)
- throws IOException
- {
- if (!this.verifyer.isValid(serverCertificate.getCertificateList()))
- {
- throw new TlsFatalAlert(AlertDescription.user_canceled);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/LegacyTlsClient.java b/core/src/main/java/org/bouncycastle/crypto/tls/LegacyTlsClient.java
deleted file mode 100644
index 33217ac4..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/LegacyTlsClient.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-/**
- * A temporary class to use LegacyTlsAuthentication
- *
- * @deprecated
- */
-public class LegacyTlsClient
- extends DefaultTlsClient
-{
- /**
- * @deprecated
- */
- protected CertificateVerifyer verifyer;
-
- /**
- * @deprecated
- */
- public LegacyTlsClient(CertificateVerifyer verifyer)
- {
- super();
-
- this.verifyer = verifyer;
- }
-
- public TlsAuthentication getAuthentication()
- throws IOException
- {
- return new LegacyTlsAuthentication(verifyer);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/MACAlgorithm.java b/core/src/main/java/org/bouncycastle/crypto/tls/MACAlgorithm.java
deleted file mode 100644
index bd13ab89..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/MACAlgorithm.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 2246
- * <p>
- * Note that the values here are implementation-specific and arbitrary. It is recommended not to
- * depend on the particular values (e.g. serialization).
- */
-public class MACAlgorithm
-{
- public static final int _null = 0;
- public static final int md5 = 1;
- public static final int sha = 2;
-
- /*
- * RFC 5246
- */
- public static final int hmac_md5 = md5;
- public static final int hmac_sha1 = sha;
- public static final int hmac_sha256 = 3;
- public static final int hmac_sha384 = 4;
- public static final int hmac_sha512 = 5;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/MaxFragmentLength.java b/core/src/main/java/org/bouncycastle/crypto/tls/MaxFragmentLength.java
deleted file mode 100644
index 6bc61b0c..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/MaxFragmentLength.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-public class MaxFragmentLength
-{
- /*
- * RFC 3546 3.2.
- */
- public static final short pow2_9 = 1;
- public static final short pow2_10 = 2;
- public static final short pow2_11 = 3;
- public static final short pow2_12 = 4;
-
- public static boolean isValid(short maxFragmentLength)
- {
- return maxFragmentLength >= pow2_9 && maxFragmentLength <= pow2_12;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/NameType.java b/core/src/main/java/org/bouncycastle/crypto/tls/NameType.java
deleted file mode 100644
index 9b0cd1b9..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/NameType.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-public class NameType
-{
- /*
- * RFC 3546 3.1.
- */
- public static final short host_name = 0;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/NamedCurve.java b/core/src/main/java/org/bouncycastle/crypto/tls/NamedCurve.java
deleted file mode 100644
index 49fc923a..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/NamedCurve.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 4492 5.1.1
- * <p>
- * The named curves defined here are those specified in SEC 2 [13]. Note that many of these curves
- * are also recommended in ANSI X9.62 [7] and FIPS 186-2 [11]. Values 0xFE00 through 0xFEFF are
- * reserved for private use. Values 0xFF01 and 0xFF02 indicate that the client supports arbitrary
- * prime and characteristic-2 curves, respectively (the curve parameters must be encoded explicitly
- * in ECParameters).
- */
-public class NamedCurve
-{
- public static final int sect163k1 = 1;
- public static final int sect163r1 = 2;
- public static final int sect163r2 = 3;
- public static final int sect193r1 = 4;
- public static final int sect193r2 = 5;
- public static final int sect233k1 = 6;
- public static final int sect233r1 = 7;
- public static final int sect239k1 = 8;
- public static final int sect283k1 = 9;
- public static final int sect283r1 = 10;
- public static final int sect409k1 = 11;
- public static final int sect409r1 = 12;
- public static final int sect571k1 = 13;
- public static final int sect571r1 = 14;
- public static final int secp160k1 = 15;
- public static final int secp160r1 = 16;
- public static final int secp160r2 = 17;
- public static final int secp192k1 = 18;
- public static final int secp192r1 = 19;
- public static final int secp224k1 = 20;
- public static final int secp224r1 = 21;
- public static final int secp256k1 = 22;
- 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)
- */
-
- public static final int arbitrary_explicit_prime_curves = 0xFF01;
- public static final int arbitrary_explicit_char2_curves = 0xFF02;
-
- public static boolean isValid(int namedCurve)
- {
- return (namedCurve >= sect163k1 && namedCurve <= brainpoolP512r1)
- || (namedCurve >= arbitrary_explicit_prime_curves && namedCurve <= arbitrary_explicit_char2_curves);
- }
-
- public static boolean refersToASpecificNamedCurve(int namedCurve)
- {
- switch (namedCurve)
- {
- case arbitrary_explicit_prime_curves:
- case arbitrary_explicit_char2_curves:
- return false;
- default:
- return true;
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/NewSessionTicket.java b/core/src/main/java/org/bouncycastle/crypto/tls/NewSessionTicket.java
deleted file mode 100644
index 8f87a65e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/NewSessionTicket.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-public class NewSessionTicket
-{
- protected long ticketLifetimeHint;
- protected byte[] ticket;
-
- public NewSessionTicket(long ticketLifetimeHint, byte[] ticket)
- {
- this.ticketLifetimeHint = ticketLifetimeHint;
- this.ticket = ticket;
- }
-
- public long getTicketLifetimeHint()
- {
- return ticketLifetimeHint;
- }
-
- public byte[] getTicket()
- {
- 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
- {
- TlsUtils.writeUint32(ticketLifetimeHint, output);
- 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
- {
- long ticketLifetimeHint = TlsUtils.readUint32(input);
- byte[] ticket = TlsUtils.readOpaque16(input);
- return new NewSessionTicket(ticketLifetimeHint, ticket);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/OCSPStatusRequest.java b/core/src/main/java/org/bouncycastle/crypto/tls/OCSPStatusRequest.java
deleted file mode 100644
index 473db23f..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/OCSPStatusRequest.java
+++ /dev/null
@@ -1,131 +0,0 @@
-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 an {@link OCSPStatusRequest} from an {@link InputStream}.
- *
- * @param input
- * the {@link InputStream} to parse from.
- * @return an {@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/core/src/main/java/org/bouncycastle/crypto/tls/PRFAlgorithm.java b/core/src/main/java/org/bouncycastle/crypto/tls/PRFAlgorithm.java
deleted file mode 100644
index 33c27c4a..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/PRFAlgorithm.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 5246
- * <p>
- * Note that the values here are implementation-specific and arbitrary. It is recommended not to
- * depend on the particular values (e.g. serialization).
- */
-public class PRFAlgorithm
-{
- /*
- * Placeholder to refer to the legacy TLS algorithm
- */
- public static final int tls_prf_legacy = 0;
-
- public static final int tls_prf_sha256 = 1;
-
- /*
- * Implied by RFC 5288
- */
- public static final int tls_prf_sha384 = 2;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/PSKTlsClient.java b/core/src/main/java/org/bouncycastle/crypto/tls/PSKTlsClient.java
deleted file mode 100644
index e442ce2f..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/PSKTlsClient.java
+++ /dev/null
@@ -1,256 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-public abstract class PSKTlsClient
- extends AbstractTlsClient
-{
- protected TlsPSKIdentity pskIdentity;
-
- public PSKTlsClient(TlsPSKIdentity pskIdentity)
- {
- super();
- this.pskIdentity = pskIdentity;
- }
-
- public PSKTlsClient(TlsCipherFactory cipherFactory, TlsPSKIdentity pskIdentity)
- {
- super(cipherFactory);
- this.pskIdentity = pskIdentity;
- }
-
- public int[] getCipherSuites()
- {
- 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
- {
- 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_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
- 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_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_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
- 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:
- 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_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1:
- 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:
- 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_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1:
- 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:
- return createPSKKeyExchange(KeyExchangeAlgorithm.RSA_PSK);
-
- default:
- /*
- * Note: internal error here; the TlsProtocol implementation verifies that the
- * server-selected cipher suite was in the list of client-offered cipher suites, so if
- * we now can't produce an implementation, we shouldn't have offered it!
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- 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:
- 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:
- 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:
- 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_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_CBC, MACAlgorithm.hmac_sha256);
-
- case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_GCM, MACAlgorithm._null);
-
- case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_CBC, MACAlgorithm.hmac_sha384);
-
- case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_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_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:
- 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:
- 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);
-
- default:
- /*
- * Note: internal error here; the TlsProtocol implementation verifies that the
- * server-selected cipher suite was in the list of client-offered cipher suites, so if
- * we now can't produce an implementation, we shouldn't have offered it!
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- protected TlsKeyExchange createPSKKeyExchange(int keyExchange)
- {
- return new TlsPSKKeyExchange(keyExchange, supportedSignatureAlgorithms, pskIdentity, null, namedCurves,
- clientECPointFormats, serverECPointFormats);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/ProtocolVersion.java b/core/src/main/java/org/bouncycastle/crypto/tls/ProtocolVersion.java
deleted file mode 100644
index 8be2bec0..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/ProtocolVersion.java
+++ /dev/null
@@ -1,158 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-import org.bouncycastle.util.Strings;
-
-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");
- public static final ProtocolVersion TLSv12 = new ProtocolVersion(0x0303, "TLS 1.2");
- public static final ProtocolVersion DTLSv10 = new ProtocolVersion(0xFEFF, "DTLS 1.0");
- public static final ProtocolVersion DTLSv12 = new ProtocolVersion(0xFEFD, "DTLS 1.2");
-
- private int version;
- private String name;
-
- private ProtocolVersion(int v, String name)
- {
- this.version = v & 0xffff;
- this.name = name;
- }
-
- public int getFullVersion()
- {
- return version;
- }
-
- public int getMajorVersion()
- {
- return version >> 8;
- }
-
- public int getMinorVersion()
- {
- return version & 0xff;
- }
-
- public boolean isDTLS()
- {
- return getMajorVersion() == 0xFE;
- }
-
- public boolean isSSL()
- {
- return this == SSLv3;
- }
-
- public boolean isTLS()
- {
- return getMajorVersion() == 0x03;
- }
-
- public ProtocolVersion getEquivalentTLSVersion()
- {
- if (!isDTLS())
- {
- return this;
- }
- if (this == DTLSv10)
- {
- return TLSv11;
- }
- return TLSv12;
- }
-
- public boolean isEqualOrEarlierVersionOf(ProtocolVersion version)
- {
- if (getMajorVersion() != version.getMajorVersion())
- {
- return false;
- }
- int diffMinorVersion = version.getMinorVersion() - getMinorVersion();
- return isDTLS() ? diffMinorVersion <= 0 : diffMinorVersion >= 0;
- }
-
- public boolean isLaterVersionOf(ProtocolVersion version)
- {
- if (getMajorVersion() != version.getMajorVersion())
- {
- return false;
- }
- int diffMinorVersion = version.getMinorVersion() - getMinorVersion();
- return isDTLS() ? diffMinorVersion > 0 : diffMinorVersion < 0;
- }
-
- public boolean equals(Object other)
- {
- return this == other || (other instanceof ProtocolVersion && equals((ProtocolVersion)other));
- }
-
- public boolean equals(ProtocolVersion other)
- {
- return other != null && this.version == other.version;
- }
-
- public int hashCode()
- {
- return version;
- }
-
- public static ProtocolVersion get(int major, int minor)
- throws IOException
- {
- switch (major)
- {
- case 0x03:
- {
- switch (minor)
- {
- case 0x00:
- return SSLv3;
- case 0x01:
- return TLSv10;
- case 0x02:
- return TLSv11;
- case 0x03:
- return TLSv12;
- }
- return getUnknownVersion(major, minor, "TLS");
- }
- case 0xFE:
- {
- switch (minor)
- {
- case 0xFF:
- return DTLSv10;
- case 0xFE:
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- case 0xFD:
- return DTLSv12;
- }
- return getUnknownVersion(major, minor, "DTLS");
- }
- default:
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- }
- }
-
- public String toString()
- {
- return name;
- }
-
- private static ProtocolVersion getUnknownVersion(int major, int minor, String prefix)
- throws IOException
- {
- TlsUtils.checkUint8(major);
- TlsUtils.checkUint8(minor);
-
- int v = (major << 8) | minor;
- String hex = Strings.toUpperCase(Integer.toHexString(0x10000 | v).substring(1));
- return new ProtocolVersion(v, prefix + " 0x" + hex);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/RecordStream.java b/core/src/main/java/org/bouncycastle/crypto/tls/RecordStream.java
deleted file mode 100644
index 922b951d..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/RecordStream.java
+++ /dev/null
@@ -1,365 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * An implementation of the TLS 1.0/1.1/1.2 record layer, allowing downgrade to SSLv3.
- */
-class RecordStream
-{
- private static int DEFAULT_PLAINTEXT_LIMIT = (1 << 14);
-
- private TlsProtocol handler;
- private InputStream input;
- private OutputStream output;
- private TlsCompression pendingCompression = null, readCompression = null, writeCompression = null;
- private TlsCipher pendingCipher = null, readCipher = null, writeCipher = null;
- private long readSeqNo = 0, writeSeqNo = 0;
- private ByteArrayOutputStream buffer = new ByteArrayOutputStream();
-
- private TlsContext context = 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;
- this.input = input;
- this.output = output;
- this.readCompression = new TlsNullCompression();
- 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.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()
- {
- return readVersion;
- }
-
- void setReadVersion(ProtocolVersion readVersion)
- {
- this.readVersion = readVersion;
- }
-
- void setWriteVersion(ProtocolVersion writeVersion)
- {
- this.writeVersion = writeVersion;
- }
-
- /**
- * RFC 5246 E.1. "Earlier versions of the TLS specification were not fully clear on what the
- * record layer version number (TLSPlaintext.version) should contain when sending ClientHello
- * (i.e., before it is known which version of the protocol will be employed). Thus, TLS servers
- * compliant with this specification MUST accept any value {03,XX} as the record layer version
- * number for ClientHello."
- */
- void setRestrictReadVersion(boolean enabled)
- {
- this.restrictReadVersion = enabled;
- }
-
- void setPendingConnectionState(TlsCompression tlsCompression, TlsCipher tlsCipher)
- {
- this.pendingCompression = tlsCompression;
- this.pendingCipher = tlsCipher;
- }
-
- void sentWriteCipherSpec()
- throws IOException
- {
- if (pendingCompression == null || pendingCipher == null)
- {
- throw new TlsFatalAlert(AlertDescription.handshake_failure);
- }
- this.writeCompression = this.pendingCompression;
- this.writeCipher = this.pendingCipher;
- this.writeSeqNo = 0;
- }
-
- void receivedReadCipherSpec()
- throws IOException
- {
- if (pendingCompression == null || pendingCipher == null)
- {
- throw new TlsFatalAlert(AlertDescription.handshake_failure);
- }
- this.readCompression = this.pendingCompression;
- this.readCipher = this.pendingCipher;
- this.readSeqNo = 0;
- }
-
- void finaliseHandshake()
- throws IOException
- {
- if (readCompression != pendingCompression || writeCompression != pendingCompression
- || readCipher != pendingCipher || writeCipher != pendingCipher)
- {
- throw new TlsFatalAlert(AlertDescription.handshake_failure);
- }
- pendingCompression = null;
- pendingCipher = null;
- }
-
- public boolean readRecord()
- throws IOException
- {
- byte[] recordHeader = TlsUtils.readAllOrNothing(5, input);
- if (recordHeader == null)
- {
- return false;
- }
-
- short type = TlsUtils.readUint8(recordHeader, 0);
-
- /*
- * RFC 5246 6. If a TLS implementation receives an unexpected record type, it MUST send an
- * unexpected_message alert.
- */
- checkType(type, AlertDescription.unexpected_message);
-
- if (!restrictReadVersion)
- {
- int version = TlsUtils.readVersionRaw(recordHeader, 1);
- if ((version & 0xffffff00) != 0x0300)
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- }
- else
- {
- ProtocolVersion version = TlsUtils.readVersion(recordHeader, 1);
- if (readVersion == null)
- {
- readVersion = version;
- }
- else if (!version.equals(readVersion))
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- }
-
- 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, ciphertextLimit, AlertDescription.record_overflow);
-
- byte[] buf = TlsUtils.readFully(len, input);
- byte[] decoded = readCipher.decodeCiphertext(readSeqNo++, type, buf, 0, buf.length);
-
- checkLength(decoded.length, compressedLimit, AlertDescription.record_overflow);
-
- /*
- * TODO RFC5264 6.2.2. Implementation note: Decompression functions are responsible for
- * ensuring that messages cannot cause internal buffer overflows.
- */
- OutputStream cOut = readCompression.decompress(buffer);
- if (cOut != buffer)
- {
- cOut.write(decoded, 0, decoded.length);
- cOut.flush();
- decoded = getBufferContents();
- }
-
- /*
- * RFC 5264 6.2.2. If the decompression function encounters a TLSCompressed.fragment that
- * would decompress to a length in excess of 2^14 bytes, it should report a fatal
- * decompression failure error.
- */
- 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;
- }
-
- protected void writeRecord(short type, byte[] plaintext, int plaintextOffset, int plaintextLength)
- throws IOException
- {
- // Never send anything until a valid ClientHello has been received
- if (writeVersion == null)
- {
- return;
- }
-
- /*
- * RFC 5264 6. Implementations MUST NOT send record types not defined in this document
- * unless negotiated by some extension.
- */
- checkType(type, AlertDescription.internal_error);
-
- /*
- * RFC 5264 6.2.1 The length should not exceed 2^14.
- */
- checkLength(plaintextLength, plaintextLimit, AlertDescription.internal_error);
-
- /*
- * RFC 5264 6.2.1 Implementations MUST NOT send zero-length fragments of Handshake, Alert,
- * or ChangeCipherSpec content types.
- */
- if (plaintextLength < 1 && type != ContentType.application_data)
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- if (type == ContentType.handshake)
- {
- updateHandshakeData(plaintext, plaintextOffset, plaintextLength);
- }
-
- OutputStream cOut = writeCompression.compress(buffer);
-
- byte[] ciphertext;
- if (cOut == buffer)
- {
- ciphertext = writeCipher.encodePlaintext(writeSeqNo++, type, plaintext, plaintextOffset, plaintextLength);
- }
- else
- {
- cOut.write(plaintext, plaintextOffset, plaintextLength);
- cOut.flush();
- byte[] compressed = getBufferContents();
-
- /*
- * RFC5264 6.2.2. Compression must be lossless and may not increase the content length
- * by more than 1024 bytes.
- */
- checkLength(compressed.length, plaintextLength + 1024, AlertDescription.internal_error);
-
- ciphertext = writeCipher.encodePlaintext(writeSeqNo++, type, compressed, 0, compressed.length);
- }
-
- /*
- * RFC 5264 6.2.3. The length may not exceed 2^14 + 2048.
- */
- checkLength(ciphertext.length, ciphertextLimit, AlertDescription.internal_error);
-
- byte[] record = new byte[ciphertext.length + 5];
- TlsUtils.writeUint8(type, record, 0);
- TlsUtils.writeVersion(writeVersion, record, 1);
- TlsUtils.writeUint16(ciphertext.length, record, 3);
- System.arraycopy(ciphertext, 0, record, 5, ciphertext.length);
- output.write(record);
- output.flush();
- }
-
- void notifyHelloComplete()
- {
- this.handshakeHash = handshakeHash.notifyPRFDetermined();
- }
-
- TlsHandshakeHash getHandshakeHash()
- {
- return handshakeHash;
- }
-
- TlsHandshakeHash prepareToFinish()
- {
- TlsHandshakeHash result = handshakeHash;
- this.handshakeHash = handshakeHash.stopTracking();
- return result;
- }
-
- void updateHandshakeData(byte[] message, int offset, int len)
- {
- handshakeHash.update(message, offset, len);
- }
-
- protected void safeClose()
- {
- try
- {
- input.close();
- }
- catch (IOException e)
- {
- }
-
- try
- {
- output.close();
- }
- catch (IOException e)
- {
- }
- }
-
- protected void flush()
- throws IOException
- {
- output.flush();
- }
-
- private byte[] getBufferContents()
- {
- byte[] contents = buffer.toByteArray();
- buffer.reset();
- return contents;
- }
-
- private static void checkType(short type, short alertDescription)
- throws IOException
- {
- switch (type)
- {
- case ContentType.application_data:
- case ContentType.alert:
- case ContentType.change_cipher_spec:
- case ContentType.handshake:
- case ContentType.heartbeat:
- break;
- default:
- throw new TlsFatalAlert(alertDescription);
- }
- }
-
- private static void checkLength(int length, int limit, short alertDescription)
- throws IOException
- {
- if (length > limit)
- {
- throw new TlsFatalAlert(alertDescription);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/SRPTlsClient.java b/core/src/main/java/org/bouncycastle/crypto/tls/SRPTlsClient.java
deleted file mode 100644
index 15295ea8..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/SRPTlsClient.java
+++ /dev/null
@@ -1,121 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-import java.util.Hashtable;
-
-import org.bouncycastle.util.Arrays;
-
-public abstract class SRPTlsClient
- extends AbstractTlsClient
-{
- /**
- * @deprecated use TlsSRPUtils.EXT_SRP instead
- */
- public static final Integer EXT_SRP = TlsSRPUtils.EXT_SRP;
-
- protected byte[] identity;
- protected byte[] password;
-
- public SRPTlsClient(byte[] identity, byte[] password)
- {
- super();
- this.identity = Arrays.clone(identity);
- this.password = Arrays.clone(password);
- }
-
- public SRPTlsClient(TlsCipherFactory cipherFactory, byte[] identity, byte[] password)
- {
- super(cipherFactory);
- this.identity = Arrays.clone(identity);
- this.password = Arrays.clone(password);
- }
-
- public int[] getCipherSuites()
- {
- return new int[] { CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA };
- }
-
- public Hashtable getClientExtensions()
- throws IOException
- {
- Hashtable clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(super.getClientExtensions());
- TlsSRPUtils.addSRPExtension(clientExtensions, this.identity);
- return clientExtensions;
- }
-
- public void processServerExtensions(Hashtable serverExtensions)
- throws IOException
- {
- if (!TlsUtils.hasExpectedEmptyExtensionData(serverExtensions, TlsSRPUtils.EXT_SRP, AlertDescription.illegal_parameter))
- {
- // No explicit guidance in RFC 5054 here; we allow an optional empty extension from server
- }
- }
-
- public TlsKeyExchange getKeyExchange()
- throws IOException
- {
-
- switch (selectedCipherSuite)
- {
- case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
- return createSRPKeyExchange(KeyExchangeAlgorithm.SRP);
-
- case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
- return createSRPKeyExchange(KeyExchangeAlgorithm.SRP_RSA);
-
- case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
- return createSRPKeyExchange(KeyExchangeAlgorithm.SRP_DSS);
-
- default:
- /*
- * Note: internal error here; the TlsProtocol implementation verifies that the
- * server-selected cipher suite was in the list of client-offered cipher suites, so if
- * we now can't produce an implementation, we shouldn't have offered it!
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- public TlsCipher getCipher()
- throws IOException
- {
-
- switch (selectedCipherSuite)
- {
- case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
- return cipherFactory.createCipher(context, EncryptionAlgorithm._3DES_EDE_CBC, MACAlgorithm.hmac_sha1);
-
- case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_CBC, MACAlgorithm.hmac_sha1);
-
- case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
- return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_CBC, MACAlgorithm.hmac_sha1);
-
- default:
- /*
- * Note: internal error here; the TlsProtocol implementation verifies that the
- * server-selected cipher suite was in the list of client-offered cipher suites, so if
- * we now can't produce an implementation, we shouldn't have offered it!
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- protected TlsKeyExchange createSRPKeyExchange(int keyExchange)
- {
- return new TlsSRPKeyExchange(keyExchange, supportedSignatureAlgorithms, identity, password);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/SRTPProtectionProfile.java b/core/src/main/java/org/bouncycastle/crypto/tls/SRTPProtectionProfile.java
deleted file mode 100644
index 1faac960..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/SRTPProtectionProfile.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-public class SRTPProtectionProfile
-{
- /*
- * RFC 5764 4.1.2.
- */
- public static final int SRTP_AES128_CM_HMAC_SHA1_80 = 0x0001;
- public static final int SRTP_AES128_CM_HMAC_SHA1_32 = 0x0002;
- public static final int SRTP_NULL_HMAC_SHA1_80 = 0x0005;
- public static final int SRTP_NULL_HMAC_SHA1_32 = 0x0006;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/SSL3Mac.java b/core/src/main/java/org/bouncycastle/crypto/tls/SSL3Mac.java
deleted file mode 100644
index 7d838590..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/SSL3Mac.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Arrays;
-
-/**
- * HMAC implementation based on original internet draft for HMAC (RFC 2104)
- * <p>
- * The difference is that padding is concatenated versus XORed with the key
- * <p>
- * H(K + opad, H(K + ipad, text))
- */
-public class SSL3Mac
- implements Mac
-{
- private final static byte IPAD_BYTE = (byte)0x36;
- private final static byte OPAD_BYTE = (byte)0x5C;
-
- static final byte[] IPAD = genPad(IPAD_BYTE, 48);
- static final byte[] OPAD = genPad(OPAD_BYTE, 48);
-
- private Digest digest;
-
- private byte[] secret;
- private int padLength;
-
- /**
- * Base constructor for one of the standard digest algorithms that the byteLength of
- * the algorithm is know for. Behaviour is undefined for digests other than MD5 or SHA1.
- *
- * @param digest the digest.
- */
- public SSL3Mac(Digest digest)
- {
- this.digest = digest;
-
- if (digest.getDigestSize() == 20)
- {
- this.padLength = 40;
- }
- else
- {
- this.padLength = 48;
- }
- }
-
- public String getAlgorithmName()
- {
- return digest.getAlgorithmName() + "/SSL3MAC";
- }
-
- public Digest getUnderlyingDigest()
- {
- return digest;
- }
-
- public void init(CipherParameters params)
- {
- secret = Arrays.clone(((KeyParameter)params).getKey());
-
- reset();
- }
-
- public int getMacSize()
- {
- return digest.getDigestSize();
- }
-
- public void update(byte in)
- {
- digest.update(in);
- }
-
- public void update(byte[] in, int inOff, int len)
- {
- digest.update(in, inOff, len);
- }
-
- public int doFinal(byte[] out, int outOff)
- {
- byte[] tmp = new byte[digest.getDigestSize()];
- digest.doFinal(tmp, 0);
-
- digest.update(secret, 0, secret.length);
- digest.update(OPAD, 0, padLength);
- digest.update(tmp, 0, tmp.length);
-
- int len = digest.doFinal(out, outOff);
-
- reset();
-
- return len;
- }
-
- /**
- * Reset the mac generator.
- */
- public void reset()
- {
- digest.reset();
- digest.update(secret, 0, secret.length);
- digest.update(IPAD, 0, padLength);
- }
-
- private static byte[] genPad(byte b, int count)
- {
- byte[] padding = new byte[count];
- Arrays.fill(padding, b);
- return padding;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/SecurityParameters.java b/core/src/main/java/org/bouncycastle/crypto/tls/SecurityParameters.java
deleted file mode 100644
index 6b0eb6db..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/SecurityParameters.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import org.bouncycastle.util.Arrays;
-
-public class SecurityParameters
-{
- int entity = -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;
- boolean encryptThenMAC = 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}
- */
- public int getEntity()
- {
- return entity;
- }
-
- /**
- * @return {@link CipherSuite}
- */
- public int getCipherSuite()
- {
- return cipherSuite;
- }
-
- /**
- * @return {@link CompressionMethod}
- */
- public short getCompressionAlgorithm()
- {
- return compressionAlgorithm;
- }
-
- /**
- * @return {@link PRFAlgorithm}
- */
- public int getPrfAlgorithm()
- {
- return prfAlgorithm;
- }
-
- public int getVerifyDataLength()
- {
- return verifyDataLength;
- }
-
- public byte[] getMasterSecret()
- {
- return masterSecret;
- }
-
- public byte[] getClientRandom()
- {
- return clientRandom;
- }
-
- public byte[] getServerRandom()
- {
- return serverRandom;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/ServerDHParams.java b/core/src/main/java/org/bouncycastle/crypto/tls/ServerDHParams.java
deleted file mode 100644
index c3050f1b..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/ServerDHParams.java
+++ /dev/null
@@ -1,63 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/tls/ServerName.java b/core/src/main/java/org/bouncycastle/crypto/tls/ServerName.java
deleted file mode 100644
index df9a4395..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/ServerName.java
+++ /dev/null
@@ -1,112 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/tls/ServerNameList.java b/core/src/main/java/org/bouncycastle/crypto/tls/ServerNameList.java
deleted file mode 100644
index 1dc81f01..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/ServerNameList.java
+++ /dev/null
@@ -1,86 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/tls/ServerOnlyTlsAuthentication.java b/core/src/main/java/org/bouncycastle/crypto/tls/ServerOnlyTlsAuthentication.java
deleted file mode 100644
index eccbb3f6..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/ServerOnlyTlsAuthentication.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-public abstract class ServerOnlyTlsAuthentication
- implements TlsAuthentication
-{
- public final TlsCredentials getClientCredentials(CertificateRequest certificateRequest)
- {
- return null;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/SessionParameters.java b/core/src/main/java/org/bouncycastle/crypto/tls/SessionParameters.java
deleted file mode 100644
index 68412f84..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/SessionParameters.java
+++ /dev/null
@@ -1,142 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/tls/SignatureAlgorithm.java b/core/src/main/java/org/bouncycastle/crypto/tls/SignatureAlgorithm.java
deleted file mode 100644
index 820c80cd..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/SignatureAlgorithm.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 5246 7.4.1.4.1 (in RFC 2246, there were no specific values assigned)
- */
-public class SignatureAlgorithm
-{
- public static final short anonymous = 0;
- public static final short rsa = 1;
- public static final short dsa = 2;
- public static final short ecdsa = 3;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/SignatureAndHashAlgorithm.java b/core/src/main/java/org/bouncycastle/crypto/tls/SignatureAndHashAlgorithm.java
deleted file mode 100644
index 9404a72f..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/SignatureAndHashAlgorithm.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * RFC 5246 7.4.1.4.1
- */
-public class SignatureAndHashAlgorithm
-{
- protected short hash;
- protected short signature;
-
- /**
- * @param hash {@link HashAlgorithm}
- * @param signature {@link SignatureAlgorithm}
- */
- public SignatureAndHashAlgorithm(short hash, short signature)
- {
- if (!TlsUtils.isValidUint8(hash))
- {
- throw new IllegalArgumentException("'hash' should be a uint8");
- }
- if (!TlsUtils.isValidUint8(signature))
- {
- throw new IllegalArgumentException("'signature' should be a uint8");
- }
- if (signature == SignatureAlgorithm.anonymous)
- {
- throw new IllegalArgumentException("'signature' MUST NOT be \"anonymous\"");
- }
-
- this.hash = hash;
- this.signature = signature;
- }
-
- /**
- * @return {@link HashAlgorithm}
- */
- public short getHash()
- {
- return hash;
- }
-
- /**
- * @return {@link SignatureAlgorithm}
- */
- public short getSignature()
- {
- return signature;
- }
-
- public boolean equals(Object obj)
- {
- if (!(obj instanceof SignatureAndHashAlgorithm))
- {
- return false;
- }
- SignatureAndHashAlgorithm other = (SignatureAndHashAlgorithm)obj;
- return other.getHash() == getHash() && other.getSignature() == getSignature();
- }
-
- public int hashCode()
- {
- return (getHash() << 16) | getSignature();
- }
-
- /**
- * Encode this {@link SignatureAndHashAlgorithm} to an {@link OutputStream}.
- *
- * @param output the {@link OutputStream} to encode to.
- * @throws IOException
- */
- public void encode(OutputStream output)
- throws IOException
- {
- TlsUtils.writeUint8(getHash(), output);
- TlsUtils.writeUint8(getSignature(), output);
- }
-
- /**
- * Parse a {@link SignatureAndHashAlgorithm} from an {@link InputStream}.
- *
- * @param input the {@link InputStream} to parse from.
- * @return a {@link SignatureAndHashAlgorithm} object.
- * @throws IOException
- */
- public static SignatureAndHashAlgorithm parse(InputStream input)
- throws IOException
- {
- short hash = TlsUtils.readUint8(input);
- short signature = TlsUtils.readUint8(input);
- return new SignatureAndHashAlgorithm(hash, signature);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/SignerInputBuffer.java b/core/src/main/java/org/bouncycastle/crypto/tls/SignerInputBuffer.java
deleted file mode 100644
index 8293135f..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/SignerInputBuffer.java
+++ /dev/null
@@ -1,13 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/tls/SupplementalDataEntry.java b/core/src/main/java/org/bouncycastle/crypto/tls/SupplementalDataEntry.java
deleted file mode 100644
index 4080aaa9..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/SupplementalDataEntry.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-public class SupplementalDataEntry
-{
- protected int dataType;
- protected byte[] data;
-
- public SupplementalDataEntry(int dataType, byte[] data)
- {
- this.dataType = dataType;
- this.data = data;
- }
-
- public int getDataType()
- {
- return dataType;
- }
-
- public byte[] getData()
- {
- return data;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/SupplementalDataType.java b/core/src/main/java/org/bouncycastle/crypto/tls/SupplementalDataType.java
deleted file mode 100644
index 218f36b1..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/SupplementalDataType.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 4680
- */
-public class SupplementalDataType
-{
- /*
- * RFC 4681
- */
- public static final int user_mapping_data = 0;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsAEADCipher.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsAEADCipher.java
deleted file mode 100644
index bb9306a1..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsAEADCipher.java
+++ /dev/null
@@ -1,193 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-import org.bouncycastle.crypto.modes.AEADBlockCipher;
-import org.bouncycastle.crypto.params.AEADParameters;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Arrays;
-
-public class TlsAEADCipher
- implements TlsCipher
-{
- protected TlsContext context;
- protected int macSize;
- protected int nonce_explicit_length;
-
- protected AEADBlockCipher encryptCipher;
- protected AEADBlockCipher decryptCipher;
-
- protected byte[] encryptImplicitNonce, decryptImplicitNonce;
-
- public TlsAEADCipher(TlsContext context, AEADBlockCipher clientWriteCipher, AEADBlockCipher serverWriteCipher,
- int cipherKeySize, int macSize) throws IOException
- {
- if (!TlsUtils.isTLSv12(context))
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- this.context = context;
- this.macSize = macSize;
-
- // 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
- int fixed_iv_length = 4;
-
- int key_block_size = (2 * cipherKeySize) + (2 * fixed_iv_length);
-
- byte[] key_block = TlsUtils.calculateKeyBlock(context, key_block_size);
-
- int offset = 0;
-
- KeyParameter client_write_key = new KeyParameter(key_block, offset, cipherKeySize);
- offset += cipherKeySize;
- KeyParameter server_write_key = new KeyParameter(key_block, offset, cipherKeySize);
- offset += cipherKeySize;
- byte[] client_write_IV = Arrays.copyOfRange(key_block, offset, offset + fixed_iv_length);
- offset += fixed_iv_length;
- byte[] server_write_IV = Arrays.copyOfRange(key_block, offset, offset + fixed_iv_length);
- offset += fixed_iv_length;
-
- if (offset != key_block_size)
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- KeyParameter encryptKey, decryptKey;
- if (context.isServer())
- {
- this.encryptCipher = serverWriteCipher;
- this.decryptCipher = clientWriteCipher;
- this.encryptImplicitNonce = server_write_IV;
- this.decryptImplicitNonce = client_write_IV;
- encryptKey = server_write_key;
- decryptKey = client_write_key;
- }
- else
- {
- this.encryptCipher = clientWriteCipher;
- this.decryptCipher = serverWriteCipher;
- this.encryptImplicitNonce = client_write_IV;
- this.decryptImplicitNonce = server_write_IV;
- encryptKey = client_write_key;
- decryptKey = server_write_key;
- }
-
- byte[] dummyNonce = new byte[fixed_iv_length + nonce_explicit_length];
-
- this.encryptCipher.init(true, new AEADParameters(encryptKey, 8 * macSize, dummyNonce));
- this.decryptCipher.init(false, new AEADParameters(decryptKey, 8 * macSize, dummyNonce));
- }
-
- public int getPlaintextLimit(int ciphertextLimit)
- {
- // TODO We ought to be able to ask the decryptCipher (independently of it's current state!)
- return ciphertextLimit - macSize - nonce_explicit_length;
- }
-
- 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/6655 The nonce_explicit MAY be the 64-bit sequence number.
- *
- * (May need review for other AEAD ciphers).
- */
- TlsUtils.writeUint64(seqNo, nonce, encryptImplicitNonce.length);
-
- int plaintextOffset = offset;
- int plaintextLength = len;
- int ciphertextLength = encryptCipher.getOutputSize(plaintextLength);
-
- byte[] output = new byte[nonce_explicit_length + ciphertextLength];
- System.arraycopy(nonce, encryptImplicitNonce.length, output, 0, nonce_explicit_length);
- int outputPos = nonce_explicit_length;
-
- byte[] additionalData = getAdditionalData(seqNo, type, plaintextLength);
- AEADParameters parameters = new AEADParameters(null, 8 * macSize, nonce, additionalData);
-
- try
- {
- encryptCipher.init(true, parameters);
- outputPos += encryptCipher.processBytes(plaintext, plaintextOffset, plaintextLength, output, outputPos);
- outputPos += encryptCipher.doFinal(output, outputPos);
- }
- catch (Exception e)
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- if (outputPos != output.length)
- {
- // NOTE: Existing AEAD cipher implementations all give exact output lengths
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- return output;
- }
-
- 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);
- }
-
- byte[] nonce = new byte[this.decryptImplicitNonce.length + nonce_explicit_length];
- System.arraycopy(decryptImplicitNonce, 0, nonce, 0, decryptImplicitNonce.length);
- System.arraycopy(ciphertext, offset, nonce, decryptImplicitNonce.length, nonce_explicit_length);
-
- int ciphertextOffset = offset + nonce_explicit_length;
- int ciphertextLength = len - nonce_explicit_length;
- int plaintextLength = decryptCipher.getOutputSize(ciphertextLength);
-
- byte[] output = new byte[plaintextLength];
- int outputPos = 0;
-
- 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)
- {
- throw new TlsFatalAlert(AlertDescription.bad_record_mac);
- }
-
- if (outputPos != output.length)
- {
- // NOTE: Existing AEAD cipher implementations all give exact output lengths
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- return output;
- }
-
- protected byte[] getAdditionalData(long seqNo, short type, int len)
- throws IOException
- {
- /*
- * additional_data = seq_num + TLSCompressed.type + TLSCompressed.version +
- * TLSCompressed.length
- */
-
- byte[] additional_data = new byte[13];
- TlsUtils.writeUint64(seqNo, additional_data, 0);
- TlsUtils.writeUint8(type, additional_data, 8);
- TlsUtils.writeVersion(context.getServerVersion(), additional_data, 9);
- TlsUtils.writeUint16(len, additional_data, 11);
-
- return additional_data;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsAgreementCredentials.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsAgreementCredentials.java
deleted file mode 100644
index 525cdb38..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsAgreementCredentials.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-
-public interface TlsAgreementCredentials
- extends TlsCredentials
-{
- byte[] generateAgreement(AsymmetricKeyParameter peerPublicKey)
- throws IOException;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsAuthentication.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsAuthentication.java
deleted file mode 100755
index 62c2616e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsAuthentication.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-public interface TlsAuthentication
-{
- /**
- * Called by the protocol handler to report the server certificate
- * Note: this method is responsible for certificate verification and validation
- *
- * @param serverCertificate the server certificate received
- * @throws IOException
- */
- void notifyServerCertificate(Certificate serverCertificate)
- throws IOException;
-
- /**
- * Return client credentials in response to server's certificate request
- *
- * @param certificateRequest details of the certificate request
- * @return a TlsCredentials object or null for no client authentication
- * @throws IOException
- */
- TlsCredentials getClientCredentials(CertificateRequest certificateRequest)
- throws IOException;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsBlockCipher.java
deleted file mode 100644
index 9a79226c..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsBlockCipher.java
+++ /dev/null
@@ -1,386 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Arrays;
-
-/**
- * A generic TLS 1.0-1.2 / SSLv3 block cipher. This can be used for AES or 3DES for example.
- */
-public class TlsBlockCipher
- implements TlsCipher
-{
- protected TlsContext context;
- protected byte[] randomData;
- protected boolean useExplicitIV;
- private boolean encryptThenMAC;
-
- protected BlockCipher encryptCipher;
- protected BlockCipher decryptCipher;
-
- protected TlsMac writeMac;
- protected TlsMac readMac;
-
- public TlsMac getWriteMac()
- {
- return writeMac;
- }
-
- public TlsMac getReadMac()
- {
- return readMac;
- }
-
- public TlsBlockCipher(TlsContext context, BlockCipher clientWriteCipher, BlockCipher serverWriteCipher,
- Digest clientWriteDigest, Digest serverWriteDigest, int cipherKeySize) throws IOException
- {
- this.context = context;
-
- this.randomData = new byte[256];
- context.getNonceRandomGenerator().nextBytes(randomData);
-
- this.useExplicitIV = TlsUtils.isTLSv11(context);
- this.encryptThenMAC = context.getSecurityParameters().encryptThenMAC;
-
- int key_block_size = (2 * cipherKeySize) + clientWriteDigest.getDigestSize()
- + serverWriteDigest.getDigestSize();
-
- // From TLS 1.1 onwards, block ciphers don't need client_write_IV
- if (!useExplicitIV)
- {
- key_block_size += clientWriteCipher.getBlockSize() + serverWriteCipher.getBlockSize();
- }
-
- byte[] key_block = TlsUtils.calculateKeyBlock(context, key_block_size);
-
- int offset = 0;
-
- TlsMac clientWriteMac = new TlsMac(context, clientWriteDigest, key_block, offset,
- clientWriteDigest.getDigestSize());
- offset += clientWriteDigest.getDigestSize();
- TlsMac serverWriteMac = new TlsMac(context, serverWriteDigest, key_block, offset,
- serverWriteDigest.getDigestSize());
- offset += serverWriteDigest.getDigestSize();
-
- KeyParameter client_write_key = new KeyParameter(key_block, offset, cipherKeySize);
- offset += cipherKeySize;
- KeyParameter server_write_key = new KeyParameter(key_block, offset, cipherKeySize);
- offset += cipherKeySize;
-
- byte[] client_write_IV, server_write_IV;
- if (useExplicitIV)
- {
- client_write_IV = new byte[clientWriteCipher.getBlockSize()];
- server_write_IV = new byte[serverWriteCipher.getBlockSize()];
- }
- else
- {
- client_write_IV = Arrays.copyOfRange(key_block, offset, offset + clientWriteCipher.getBlockSize());
- offset += clientWriteCipher.getBlockSize();
- server_write_IV = Arrays.copyOfRange(key_block, offset, offset + serverWriteCipher.getBlockSize());
- offset += serverWriteCipher.getBlockSize();
- }
-
- if (offset != key_block_size)
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- CipherParameters encryptParams, decryptParams;
- if (context.isServer())
- {
- this.writeMac = serverWriteMac;
- this.readMac = clientWriteMac;
- this.encryptCipher = serverWriteCipher;
- this.decryptCipher = clientWriteCipher;
- encryptParams = new ParametersWithIV(server_write_key, server_write_IV);
- decryptParams = new ParametersWithIV(client_write_key, client_write_IV);
- }
- else
- {
- this.writeMac = clientWriteMac;
- this.readMac = serverWriteMac;
- this.encryptCipher = clientWriteCipher;
- this.decryptCipher = serverWriteCipher;
- encryptParams = new ParametersWithIV(client_write_key, client_write_IV);
- decryptParams = new ParametersWithIV(server_write_key, server_write_IV);
- }
-
- this.encryptCipher.init(true, encryptParams);
- this.decryptCipher.init(false, decryptParams);
- }
-
- public int getPlaintextLimit(int ciphertextLimit)
- {
- int blockSize = encryptCipher.getBlockSize();
- int macSize = writeMac.getSize();
-
- int plaintextLimit = ciphertextLimit;
-
- // An explicit IV consumes 1 block
- if (useExplicitIV)
- {
- plaintextLimit -= blockSize;
- }
-
- // 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)
- {
- int blockSize = encryptCipher.getBlockSize();
- int macSize = writeMac.getSize();
-
- ProtocolVersion version = context.getServerVersion();
-
- 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())
- {
- // Add a random number of extra blocks worth of padding
- int maxExtraPadBlocks = (255 - padding_length) / blockSize;
- int actualExtraPadBlocks = chooseExtraPadBlocks(context.getSecureRandom(), maxExtraPadBlocks);
- padding_length += actualExtraPadBlocks * blockSize;
- }
-
- int totalSize = len + macSize + padding_length + 1;
- if (useExplicitIV)
- {
- totalSize += blockSize;
- }
-
- byte[] outBuf = new byte[totalSize];
- int outOff = 0;
-
- if (useExplicitIV)
- {
- byte[] explicitIV = new byte[blockSize];
- context.getNonceRandomGenerator().nextBytes(explicitIV);
-
- encryptCipher.init(true, new ParametersWithIV(null, explicitIV));
-
- System.arraycopy(explicitIV, 0, outBuf, outOff, blockSize);
- outOff += blockSize;
- }
-
- int blocks_start = outOff;
-
- System.arraycopy(plaintext, offset, outBuf, outOff, len);
- outOff += len;
-
- if (!encryptThenMAC)
- {
- byte[] mac = writeMac.calculateMac(seqNo, type, plaintext, offset, len);
- System.arraycopy(mac, 0, outBuf, outOff, mac.length);
- outOff += mac.length;
- }
-
- for (int i = 0; i <= padding_length; i++)
- {
- outBuf[outOff++] = (byte)padding_length;
- }
-
- for (int i = blocks_start; i < outOff; i += blockSize)
- {
- encryptCipher.processBlock(outBuf, i, outBuf, i);
- }
-
- 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)
- throws IOException
- {
- int blockSize = decryptCipher.getBlockSize();
- int macSize = readMac.getSize();
-
- int minLen = blockSize;
- if (encryptThenMAC)
- {
- minLen += macSize;
- }
- else
- {
- minLen = Math.max(minLen, macSize + 1);
- }
-
- if (useExplicitIV)
- {
- minLen += blockSize;
- }
-
- if (len < minLen)
- {
- throw new TlsFatalAlert(AlertDescription.decode_error);
- }
-
- 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;
- blocks_length -= 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, blocks_length, blockSize, encryptThenMAC ? 0 : macSize);
-
- int dec_output_length = blocks_length - totalPad;
-
- 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, receivedMac);
-
- if (badMac || totalPad == 0)
- {
- throw new TlsFatalAlert(AlertDescription.bad_record_mac);
- }
- }
-
- return Arrays.copyOfRange(ciphertext, offset, offset + dec_output_length);
- }
-
- protected int checkPaddingConstantTime(byte[] buf, int off, int len, int blockSize, int macSize)
- {
- int end = off + len;
- byte lastByte = buf[end - 1];
- int padlen = lastByte & 0xff;
- int totalPad = padlen + 1;
-
- int dummyIndex = 0;
- byte padDiff = 0;
-
- if ((TlsUtils.isSSL(context) && totalPad > blockSize) || (macSize + totalPad > len))
- {
- totalPad = 0;
- }
- else
- {
- int padPos = end - totalPad;
- do
- {
- padDiff |= (buf[padPos++] ^ lastByte);
- }
- while (padPos < end);
-
- dummyIndex = totalPad;
-
- if (padDiff != 0)
- {
- totalPad = 0;
- }
- }
-
- // Run some extra dummy checks so the number of checks is always constant
- {
- byte[] dummyPad = randomData;
- while (dummyIndex < 256)
- {
- padDiff |= (dummyPad[dummyIndex++] ^ lastByte);
- }
- // Ensure the above loop is not eliminated
- dummyPad[0] ^= padDiff;
- }
-
- return totalPad;
- }
-
- protected int chooseExtraPadBlocks(SecureRandom r, int max)
- {
- // return r.nextInt(max + 1);
-
- int x = r.nextInt();
- int n = lowestBitSet(x);
- return Math.min(n, max);
- }
-
- protected int lowestBitSet(int x)
- {
- if (x == 0)
- {
- return 32;
- }
-
- int n = 0;
- while ((x & 1) == 0)
- {
- ++n;
- x >>= 1;
- }
- return n;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsCipher.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsCipher.java
deleted file mode 100644
index 2f0af080..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsCipher.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-public interface TlsCipher
-{
- int getPlaintextLimit(int ciphertextLimit);
-
- byte[] encodePlaintext(long seqNo, short type, byte[] plaintext, int offset, int len)
- throws IOException;
-
- byte[] decodeCiphertext(long seqNo, short type, byte[] ciphertext, int offset, int len)
- throws IOException;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsCipherFactory.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsCipherFactory.java
deleted file mode 100644
index 74074747..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsCipherFactory.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-public interface TlsCipherFactory
-{
- /**
- * See enumeration classes EncryptionAlgorithm, MACAlgorithm for appropriate argument values
- */
- TlsCipher createCipher(TlsContext context, int encryptionAlgorithm, int macAlgorithm)
- throws IOException;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java
deleted file mode 100644
index 8b29c1f7..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-import java.util.Hashtable;
-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();
-
- int[] getCipherSuites();
-
- short[] getCompressionMethods();
-
- // Hashtable is (Integer -> byte[])
- Hashtable getClientExtensions()
- throws IOException;
-
- void notifyServerVersion(ProtocolVersion selectedVersion)
- throws IOException;
-
- /**
- * Notifies the client of the session_id sent in the ServerHello.
- *
- * @param sessionID
- * @see TlsContext#getResumableSession()
- */
- void notifySessionID(byte[] sessionID);
-
- void notifySelectedCipherSuite(int selectedCipherSuite);
-
- void notifySelectedCompressionMethod(short selectedCompressionMethod);
-
- // Hashtable is (Integer -> byte[])
- void processServerExtensions(Hashtable serverExtensions)
- throws IOException;
-
- // Vector is (SupplementalDataEntry)
- void processServerSupplementalData(Vector serverSupplementalData)
- throws IOException;
-
- TlsKeyExchange getKeyExchange()
- throws IOException;
-
- TlsAuthentication getAuthentication()
- throws IOException;
-
- // Vector is (SupplementalDataEntry)
- Vector getClientSupplementalData()
- throws IOException;
-
- /**
- * RFC 5077 3.3. NewSessionTicket Handshake Message
- * <p>
- * This method will be called (only) when a NewSessionTicket handshake message is received. The
- * ticket is opaque to the client and clients MUST NOT examine the ticket under the assumption
- * that it complies with e.g. <i>RFC 5077 4. Recommended Ticket Construction</i>.
- *
- * @param newSessionTicket The ticket.
- * @throws IOException
- */
- void notifyNewSessionTicket(NewSessionTicket newSessionTicket)
- throws IOException;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsClientContext.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsClientContext.java
deleted file mode 100644
index db9f15b7..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsClientContext.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-public interface TlsClientContext
- extends TlsContext
-{
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsClientContextImpl.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsClientContextImpl.java
deleted file mode 100644
index b3201443..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsClientContextImpl.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.security.SecureRandom;
-
-class TlsClientContextImpl
- extends AbstractTlsContext
- implements TlsClientContext
-{
- TlsClientContextImpl(SecureRandom secureRandom, SecurityParameters securityParameters)
- {
- super(secureRandom, securityParameters);
- }
-
- public boolean isServer()
- {
- return false;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsClientProtocol.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsClientProtocol.java
deleted file mode 100644
index d4d19ef7..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsClientProtocol.java
+++ /dev/null
@@ -1,917 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.security.SecureRandom;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import org.bouncycastle.crypto.prng.ThreadedSeedGenerator;
-import org.bouncycastle.util.Arrays;
-
-public class TlsClientProtocol
- extends TlsProtocol
-{
- protected TlsClient tlsClient = null;
- protected TlsClientContextImpl tlsClientContext = null;
-
- protected byte[] selectedSessionID = null;
-
- protected TlsKeyExchange keyExchange = null;
- protected TlsAuthentication authentication = null;
-
- protected CertificateStatus certificateStatus = null;
- protected CertificateRequest certificateRequest = null;
-
- private static SecureRandom createSecureRandom()
- {
- /*
- * We use our threaded seed generator to generate a good random seed. If the user has a
- * better random seed, he should use the constructor with a SecureRandom.
- */
- ThreadedSeedGenerator tsg = new ThreadedSeedGenerator();
- SecureRandom random = new SecureRandom();
-
- /*
- * Hopefully, 20 bytes in fast mode are good enough.
- */
- random.setSeed(tsg.generateSeed(20, true));
-
- return random;
- }
-
- /**
- * @deprecated use alternate constructor taking an explicit {@link SecureRandom}
- */
- public TlsClientProtocol(InputStream input, OutputStream output)
- {
- this(input, output, createSecureRandom());
- }
-
- public TlsClientProtocol(InputStream input, OutputStream output, SecureRandom secureRandom)
- {
- super(input, output, secureRandom);
- }
-
- /**
- * Initiates a TLS handshake in the role of client
- *
- * @param tlsClient The {@link TlsClient} to use for the handshake.
- * @throws IOException If handshake was not successful.
- */
- public void connect(TlsClient tlsClient) throws IOException
- {
- if (tlsClient == null)
- {
- throw new IllegalArgumentException("'tlsClient' cannot be null");
- }
- if (this.tlsClient != null)
- {
- throw new IllegalStateException("'connect' can only be called once");
- }
-
- this.tlsClient = tlsClient;
-
- this.securityParameters = new SecurityParameters();
- this.securityParameters.entity = ConnectionEnd.client;
-
- this.tlsClientContext = new TlsClientContextImpl(secureRandom, securityParameters);
-
- this.securityParameters.clientRandom = createRandomBlock(tlsClient.shouldUseGMTUnixTime(),
- tlsClientContext.getNonceRandomGenerator());
-
- 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();
- }
-
- protected void cleanupHandshake()
- {
- super.cleanupHandshake();
-
- this.selectedSessionID = null;
- this.keyExchange = null;
- this.authentication = null;
- this.certificateStatus = null;
- this.certificateRequest = null;
- }
-
- protected AbstractTlsContext getContext()
- {
- return tlsClientContext;
- }
-
- protected TlsPeer getPeer()
- {
- return tlsClient;
- }
-
- protected void handleHandshakeMessage(short type, byte[] data)
- throws IOException
- {
- ByteArrayInputStream buf = new ByteArrayInputStream(data);
-
- if (this.resumedSession)
- {
- if (type != HandshakeType.finished || this.connection_state != CS_SERVER_HELLO)
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
-
- processFinishedMessage(buf);
- this.connection_state = CS_SERVER_FINISHED;
-
- sendFinishedMessage();
- this.connection_state = CS_CLIENT_FINISHED;
- this.connection_state = CS_END;
-
- return;
- }
-
- switch (type)
- {
- case HandshakeType.certificate:
- {
- switch (this.connection_state)
- {
- case CS_SERVER_HELLO:
- {
- handleSupplementalData(null);
- // NB: Fall through to next case label
- }
- case CS_SERVER_SUPPLEMENTAL_DATA:
- {
- // Parse the Certificate message and send to cipher suite
-
- this.peerCertificate = Certificate.parse(buf);
-
- assertEmpty(buf);
-
- // 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(this.peerCertificate);
-
- break;
- }
- default:
- 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_CLIENT_FINISHED:
- {
- if (this.expectSessionTicket)
- {
- /*
- * RFC 5077 3.3. This message MUST be sent if the server included a
- * SessionTicket extension in the ServerHello.
- */
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
-
- // NB: Fall through to next case label
- }
- case CS_SERVER_SESSION_TICKET:
- {
- processFinishedMessage(buf);
- this.connection_state = CS_SERVER_FINISHED;
- this.connection_state = CS_END;
- break;
- }
- default:
- 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;
-
- 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.
- */
- this.securityParameters.verifyDataLength = 12;
-
- 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:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- break;
- }
- case HandshakeType.supplemental_data:
- {
- switch (this.connection_state)
- {
- case CS_SERVER_HELLO:
- {
- handleSupplementalData(readSupplementalDataMessage(buf));
- break;
- }
- default:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- break;
- }
- case HandshakeType.server_hello_done:
- {
- switch (this.connection_state)
- {
- case CS_SERVER_HELLO:
- {
- handleSupplementalData(null);
- // NB: Fall through to next case label
- }
- case CS_SERVER_SUPPLEMENTAL_DATA:
- {
- // There was no server certificate message; check it's OK
- this.keyExchange.skipServerCredentials();
- this.authentication = null;
-
- // 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)
- {
- sendSupplementalDataMessage(clientSupplementalData);
- }
- this.connection_state = CS_CLIENT_SUPPLEMENTAL_DATA;
-
- TlsCredentials clientCreds = null;
- if (certificateRequest == null)
- {
- this.keyExchange.skipClientCredentials();
- }
- else
- {
- clientCreds = this.authentication.getClientCredentials(certificateRequest);
-
- if (clientCreds == null)
- {
- this.keyExchange.skipClientCredentials();
-
- /*
- * RFC 5246 If no suitable certificate is available, the client MUST send a
- * certificate message containing no certificates.
- *
- * NOTE: In previous RFCs, this was SHOULD instead of MUST.
- */
- sendCertificateMessage(Certificate.EMPTY_CHAIN);
- }
- else
- {
- this.keyExchange.processClientCredentials(clientCreds);
-
- sendCertificateMessage(clientCreds.getCertificate());
- }
- }
-
- this.connection_state = CS_CLIENT_CERTIFICATE;
-
- /*
- * Send the client key exchange message, depending on the key exchange we are using
- * in our CipherSuite.
- */
- sendClientKeyExchangeMessage();
- this.connection_state = CS_CLIENT_KEY_EXCHANGE;
-
- establishMasterSecret(getContext(), keyExchange);
- recordStream.setPendingConnectionState(getPeer().getCompression(), getPeer().getCipher());
-
- TlsHandshakeHash prepareFinishHash = recordStream.prepareToFinish();
-
- if (clientCreds != null && clientCreds instanceof TlsSignerCredentials)
- {
- TlsSignerCredentials signerCredentials = (TlsSignerCredentials)clientCreds;
-
- /*
- * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2
- */
- 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();
- sendFinishedMessage();
- this.connection_state = CS_CLIENT_FINISHED;
- break;
- }
- default:
- throw new TlsFatalAlert(AlertDescription.handshake_failure);
- }
- break;
- }
- case HandshakeType.server_key_exchange:
- {
- switch (this.connection_state)
- {
- case CS_SERVER_HELLO:
- {
- handleSupplementalData(null);
- // NB: Fall through to next case label
- }
- case CS_SERVER_SUPPLEMENTAL_DATA:
- {
- // There was no server certificate message; check it's OK
- this.keyExchange.skipServerCredentials();
- this.authentication = null;
-
- // NB: Fall through to next case label
- }
- case CS_SERVER_CERTIFICATE:
- case CS_CERTIFICATE_STATUS:
- {
- this.keyExchange.processServerKeyExchange(buf);
-
- assertEmpty(buf);
- break;
- }
- default:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
-
- this.connection_state = CS_SERVER_KEY_EXCHANGE;
- break;
- }
- case HandshakeType.certificate_request:
- {
- 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)
- {
- /*
- * RFC 2246 7.4.4. It is a fatal handshake_failure alert for an anonymous server
- * to request client identification.
- */
- throw new TlsFatalAlert(AlertDescription.handshake_failure);
- }
-
- 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:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
-
- this.connection_state = CS_CERTIFICATE_REQUEST;
- break;
- }
- case HandshakeType.session_ticket:
- {
- 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.
- */
- 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:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- }
- case HandshakeType.hello_request:
- {
- assertEmpty(buf);
-
- /*
- * RFC 2246 7.4.1.1 Hello request This message will be ignored by the client if the
- * client is currently negotiating a session. This message may be ignored by the client
- * 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_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.hello_verify_request:
- default:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- }
-
- protected void handleSupplementalData(Vector serverSupplementalData)
- throws IOException
- {
- this.tlsClient.processServerSupplementalData(serverSupplementalData);
- this.connection_state = CS_SERVER_SUPPLEMENTAL_DATA;
-
- this.keyExchange = tlsClient.getKeyExchange();
- this.keyExchange.init(getContext());
- }
-
- protected void receiveNewSessionTicketMessage(ByteArrayInputStream buf)
- throws IOException
- {
- NewSessionTicket newSessionTicket = NewSessionTicket.parse(buf);
-
- TlsProtocol.assertEmpty(buf);
-
- tlsClient.notifyNewSessionTicket(newSessionTicket);
- }
-
- protected void receiveServerHelloMessage(ByteArrayInputStream buf)
- throws IOException
- {
- ProtocolVersion server_version = TlsUtils.readVersion(buf);
- if (server_version.isDTLS())
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- // Check that this matches what the server is sending in the record layer
- if (!server_version.equals(this.recordStream.getReadVersion()))
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- ProtocolVersion client_version = getContext().getClientVersion();
- if (!server_version.isEqualOrEarlierVersionOf(client_version))
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- this.recordStream.setWriteVersion(server_version);
- getContext().setServerVersion(server_version);
- this.tlsClient.notifyServerVersion(server_version);
-
- /*
- * Read the server random
- */
- this.securityParameters.serverRandom = TlsUtils.readFully(32, buf);
-
- this.selectedSessionID = TlsUtils.readOpaque8(buf);
- if (this.selectedSessionID.length > 32)
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- 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, and is a valid selection for the negotiated version.
- */
- 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
- || !TlsUtils.isValidCipherSuiteForVersion(selectedCipherSuite, server_version))
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- 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 (!Arrays.contains(this.offeredCompressionMethods, selectedCompressionMethod))
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- this.tlsClient.notifySelectedCompressionMethod(selectedCompressionMethod);
-
- /*
- * RFC3546 2.2 The extended server hello message format MAY be sent in place of the server
- * hello message when the client has requested extended functionality via the extended
- * client hello message specified in Section 2.1. ... Note that the extended server hello
- * message is only sent in response to an extended client hello message. This prevents the
- * possibility that the extended server hello message could "break" existing TLS 1.0
- * clients.
- */
- this.serverExtensions = readExtensions(buf);
-
- /*
- * RFC 3546 2.2 Note that the extended server hello message is only sent in response to an
- * extended client hello message.
- *
- * However, see RFC 5746 exception below. We always include the SCSV, so an Extended Server
- * Hello is always allowed.
- */
- if (this.serverExtensions != null)
- {
- Enumeration e = this.serverExtensions.keys();
- while (e.hasMoreElements())
- {
- Integer extType = (Integer)e.nextElement();
-
- /*
- * RFC 5746 3.6. Note that sending a "renegotiation_info" extension in response to a
- * ClientHello containing only the SCSV is an explicit exception to the prohibition
- * in RFC 5246, Section 7.4.1.4, on the server sending unsolicited extensions and is
- * 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))
- {
- 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
- */
- {
- /*
- * 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)
- {
- /*
- * 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;
-
- 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);
-
- 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();
- }
-
- this.securityParameters.cipherSuite = selectedCipherSuite;
- this.securityParameters.compressionAlgorithm = selectedCompressionMethod;
-
- if (sessionServerExtensions != null)
- {
- /*
- * draft-ietf-tls-encrypt-then-mac-03 3. If a server receives an encrypt-then-MAC
- * request extension from a client and then selects a stream or AEAD cipher suite, it
- * MUST NOT send an encrypt-then-MAC response extension back to the client.
- */
- boolean serverSentEncryptThenMAC = TlsExtensionsUtils.hasEncryptThenMACExtension(sessionServerExtensions);
- if (serverSentEncryptThenMAC && !TlsUtils.isBlockCipherSuite(selectedCipherSuite))
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- this.securityParameters.encryptThenMAC = serverSentEncryptThenMAC;
-
- 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)
- {
- this.tlsClient.processServerExtensions(sessionServerExtensions);
- }
- }
-
- protected void sendCertificateVerifyMessage(DigitallySigned certificateVerify)
- throws IOException
- {
- HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate_verify);
-
- certificateVerify.encode(message);
-
- message.writeToRecordStream();
- }
-
- protected void sendClientHelloMessage()
- throws IOException
- {
- this.recordStream.setWriteVersion(this.tlsClient.getClientHelloRecordLayerVersion());
-
- ProtocolVersion client_version = this.tlsClient.getClientVersion();
- if (client_version.isDTLS())
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- getContext().setClientVersion(client_version);
-
- /*
- * 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();
-
- 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)
- {
- /*
- * RFC 5746 3.4. The client MUST include either an empty "renegotiation_info" extension,
- * or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling cipher suite value in the
- * ClientHello. Including both is NOT RECOMMENDED.
- */
- byte[] renegExtData = TlsUtils.getExtensionData(clientExtensions, EXT_RenegotiationInfo);
- boolean noRenegExt = (null == renegExtData);
-
- boolean noSCSV = !Arrays.contains(offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
-
- if (noRenegExt && noSCSV)
- {
- // 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);
- }
-
- TlsUtils.writeUint16ArrayWithUint16Length(offeredCipherSuites, message);
- }
-
- TlsUtils.writeUint8ArrayWithUint8Length(offeredCompressionMethods, message);
-
- if (clientExtensions != null)
- {
- writeExtensions(message, clientExtensions);
- }
-
- message.writeToRecordStream();
- }
-
- protected void sendClientKeyExchangeMessage()
- throws IOException
- {
- HandshakeMessage message = new HandshakeMessage(HandshakeType.client_key_exchange);
-
- this.keyExchange.generateClientKeyExchange(message);
-
- message.writeToRecordStream();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsCompression.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsCompression.java
deleted file mode 100644
index cdeb7e33..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsCompression.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.OutputStream;
-
-public interface TlsCompression
-{
- OutputStream compress(OutputStream output);
-
- OutputStream decompress(OutputStream output);
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsContext.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsContext.java
deleted file mode 100644
index b3d7d985..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsContext.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.prng.RandomGenerator;
-
-public interface TlsContext
-{
- RandomGenerator getNonceRandomGenerator();
-
- SecureRandom getSecureRandom();
-
- SecurityParameters getSecurityParameters();
-
- boolean isServer();
-
- ProtocolVersion getClientVersion();
-
- 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 TlsPeer#notifyHandshakeComplete()
- */
- TlsSession getResumableSession();
-
- Object getUserObject();
-
- void setUserObject(Object userObject);
-
- /**
- * Export keying material according to RFC 5705: "Keying Material Exporters for TLS".
- *
- * @param asciiLabel indicates which application will use the exported keys.
- * @param context_value allows the application using the exporter to mix its own data with the TLS PRF for
- * the exporter output.
- * @param length the number of bytes to generate
- * @return a pseudorandom bit string of 'length' bytes generated from the master_secret.
- */
- byte[] exportKeyingMaterial(String asciiLabel, byte[] context_value, int length);
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsCredentials.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsCredentials.java
deleted file mode 100644
index b8a8747e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsCredentials.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-public interface TlsCredentials
-{
- Certificate getCertificate();
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsDHEKeyExchange.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsDHEKeyExchange.java
deleted file mode 100644
index 0abaee69..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsDHEKeyExchange.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Vector;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.Signer;
-import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.util.io.TeeInputStream;
-
-public class TlsDHEKeyExchange
- extends TlsDHKeyExchange
-{
- protected TlsSignerCredentials serverCredentials = null;
-
- public TlsDHEKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms, DHParameters dhParameters)
- {
- super(keyExchange, supportedSignatureAlgorithms, dhParameters);
- }
-
- public void processServerCredentials(TlsCredentials serverCredentials)
- throws IOException
- {
- if (!(serverCredentials instanceof TlsSignerCredentials))
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- processServerCertificate(serverCredentials.getCertificate());
-
- this.serverCredentials = (TlsSignerCredentials)serverCredentials;
- }
-
- public byte[] generateServerKeyExchange()
- throws IOException
- {
- if (this.dhParameters == null)
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- DigestInputBuffer buf = new DigestInputBuffer();
-
- this.dhAgreeServerPrivateKey = TlsDHUtils.generateEphemeralServerKeyExchange(context.getSecureRandom(),
- this.dhParameters, 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);
- }
-
- d = TlsUtils.createHash(signatureAndHashAlgorithm.getHash());
- }
- else
- {
- signatureAndHashAlgorithm = null;
- d = new CombinedHash();
- }
-
- SecurityParameters securityParameters = context.getSecurityParameters();
- d.update(securityParameters.clientRandom, 0, securityParameters.clientRandom.length);
- d.update(securityParameters.serverRandom, 0, securityParameters.serverRandom.length);
- buf.updateDigest(d);
-
- byte[] hash = new byte[d.getDigestSize()];
- d.doFinal(hash, 0);
-
- byte[] signature = serverCredentials.generateCertificateSignature(hash);
-
- DigitallySigned signed_params = new DigitallySigned(signatureAndHashAlgorithm, signature);
- signed_params.encode(buf);
-
- return buf.toByteArray();
- }
-
- public void processServerKeyExchange(InputStream input)
- throws IOException
- {
- SecurityParameters securityParameters = context.getSecurityParameters();
-
- SignerInputBuffer buf = new SignerInputBuffer();
- InputStream teeIn = new TeeInputStream(input, buf);
-
- ServerDHParams params = ServerDHParams.parse(teeIn);
-
- DigitallySigned signed_params = DigitallySigned.parse(context, input);
-
- 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 = TlsDHUtils.validateDHPublicKey(params.getPublicKey());
- }
-
- protected Signer initVerifyer(TlsSigner tlsSigner, SignatureAndHashAlgorithm algorithm, SecurityParameters securityParameters)
- {
- 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/core/src/main/java/org/bouncycastle/crypto/tls/TlsDHKeyExchange.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsDHKeyExchange.java
deleted file mode 100644
index 7d79f6a4..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsDHKeyExchange.java
+++ /dev/null
@@ -1,208 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.math.BigInteger;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.x509.KeyUsage;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
-import org.bouncycastle.crypto.params.DHPublicKeyParameters;
-import org.bouncycastle.crypto.util.PublicKeyFactory;
-
-/**
- * TLS 1.0/1.1 DH key exchange.
- */
-public class TlsDHKeyExchange
- extends AbstractTlsKeyExchange
-{
- protected static final BigInteger ONE = BigInteger.valueOf(1);
- protected static final BigInteger TWO = BigInteger.valueOf(2);
-
- protected TlsSigner tlsSigner;
- protected DHParameters dhParameters;
-
- protected AsymmetricKeyParameter serverPublicKey;
- protected DHPublicKeyParameters dhAgreeServerPublicKey;
- 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)
- {
- case KeyExchangeAlgorithm.DH_RSA:
- case KeyExchangeAlgorithm.DH_DSS:
- this.tlsSigner = null;
- break;
- case KeyExchangeAlgorithm.DHE_RSA:
- this.tlsSigner = new TlsRSASigner();
- break;
- case KeyExchangeAlgorithm.DHE_DSS:
- this.tlsSigner = new TlsDSSSigner();
- break;
- default:
- throw new IllegalArgumentException("unsupported key exchange algorithm");
- }
-
- this.dhParameters = dhParameters;
- }
-
- public void init(TlsContext context)
- {
- super.init(context);
-
- if (this.tlsSigner != null)
- {
- this.tlsSigner.init(context);
- }
- }
-
- public void skipServerCredentials()
- throws IOException
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
-
- public void processServerCertificate(Certificate serverCertificate)
- throws IOException
- {
- if (serverCertificate.isEmpty())
- {
- throw new TlsFatalAlert(AlertDescription.bad_certificate);
- }
-
- org.bouncycastle.asn1.x509.Certificate x509Cert = serverCertificate.getCertificateAt(0);
-
- SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo();
- try
- {
- this.serverPublicKey = PublicKeyFactory.createKey(keyInfo);
- }
- catch (RuntimeException e)
- {
- throw new TlsFatalAlert(AlertDescription.unsupported_certificate);
- }
-
- if (tlsSigner == null)
- {
- try
- {
- this.dhAgreeServerPublicKey = TlsDHUtils.validateDHPublicKey((DHPublicKeyParameters)this.serverPublicKey);
- }
- catch (ClassCastException e)
- {
- throw new TlsFatalAlert(AlertDescription.certificate_unknown);
- }
-
- TlsUtils.validateKeyUsage(x509Cert, KeyUsage.keyAgreement);
- }
- else
- {
- if (!tlsSigner.isValidPublicKey(this.serverPublicKey))
- {
- throw new TlsFatalAlert(AlertDescription.certificate_unknown);
- }
-
- TlsUtils.validateKeyUsage(x509Cert, KeyUsage.digitalSignature);
- }
-
- super.processServerCertificate(serverCertificate);
- }
-
- public boolean requiresServerKeyExchange()
- {
- switch (keyExchange)
- {
- case KeyExchangeAlgorithm.DHE_DSS:
- case KeyExchangeAlgorithm.DHE_RSA:
- case KeyExchangeAlgorithm.DH_anon:
- return true;
- default:
- return false;
- }
- }
-
- public void validateCertificateRequest(CertificateRequest certificateRequest)
- throws IOException
- {
- short[] types = certificateRequest.getCertificateTypes();
- for (int i = 0; i < types.length; ++i)
- {
- switch (types[i])
- {
- case ClientCertificateType.rsa_sign:
- case ClientCertificateType.dss_sign:
- case ClientCertificateType.rsa_fixed_dh:
- case ClientCertificateType.dss_fixed_dh:
- case ClientCertificateType.ecdsa_sign:
- break;
- default:
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- }
- }
-
- public void processClientCredentials(TlsCredentials clientCredentials)
- throws IOException
- {
- if (clientCredentials instanceof TlsAgreementCredentials)
- {
- // TODO Validate client cert has matching parameters (see 'areCompatibleParameters')?
-
- this.agreementCredentials = (TlsAgreementCredentials)clientCredentials;
- }
- else if (clientCredentials instanceof TlsSignerCredentials)
- {
- // OK
- }
- else
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- public void generateClientKeyExchange(OutputStream output)
- throws IOException
- {
- /*
- * RFC 2246 7.4.7.2 If the client certificate already contains a suitable Diffie-Hellman
- * key, then Yc is implicit and does not need to be sent again. In this case, the Client Key
- * Exchange message will be sent, but will be empty.
- */
- if (agreementCredentials == null)
- {
- this.dhAgreeClientPrivateKey = TlsDHUtils.generateEphemeralClientKeyExchange(context.getSecureRandom(),
- dhAgreeServerPublicKey.getParameters(), output);
- }
- }
-
- public byte[] generatePremasterSecret()
- throws IOException
- {
- if (agreementCredentials != null)
- {
- return agreementCredentials.generateAgreement(dhAgreeServerPublicKey);
- }
-
- if (dhAgreeServerPrivateKey != null)
- {
- return TlsDHUtils.calculateDHBasicAgreement(dhAgreeClientPublicKey, dhAgreeServerPrivateKey);
- }
-
- if (dhAgreeClientPrivateKey != null)
- {
- return TlsDHUtils.calculateDHBasicAgreement(dhAgreeServerPublicKey, dhAgreeClientPrivateKey);
- }
-
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsDHUtils.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsDHUtils.java
deleted file mode 100644
index 748c8797..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsDHUtils.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.agreement.DHBasicAgreement;
-import org.bouncycastle.crypto.generators.DHBasicKeyPairGenerator;
-import org.bouncycastle.crypto.params.DHKeyGenerationParameters;
-import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
-import org.bouncycastle.crypto.params.DHPublicKeyParameters;
-import org.bouncycastle.util.BigIntegers;
-
-public class TlsDHUtils
-{
- static final BigInteger ONE = BigInteger.valueOf(1);
- static final BigInteger TWO = BigInteger.valueOf(2);
-
- 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);
-
- /*
- * RFC 5246 8.1.2. Leading bytes of Z that contain all zero bits are stripped before it is
- * used as the pre_master_secret.
- */
- return BigIntegers.asUnsignedByteArray(agreementValue);
- }
-
- 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
- {
- AsymmetricCipherKeyPair kp = generateDHKeyPair(random, dhParams);
-
- DHPublicKeyParameters dh_public = (DHPublicKeyParameters) kp.getPublic();
- writeDHParameter(dh_public.getY(), output);
-
- return (DHPrivateKeyParameters) kp.getPrivate();
- }
-
- public static DHPrivateKeyParameters generateEphemeralServerKeyExchange(SecureRandom random, DHParameters dhParams,
- OutputStream output) throws IOException
- {
- AsymmetricCipherKeyPair kp = TlsDHUtils.generateDHKeyPair(random, dhParams);
-
- DHPublicKeyParameters dhPublicKey = (DHPublicKeyParameters)kp.getPublic();
- ServerDHParams params = new ServerDHParams(dhPublicKey);
- params.encode(output);
-
- return (DHPrivateKeyParameters)kp.getPrivate();
- }
-
- public static DHPublicKeyParameters validateDHPublicKey(DHPublicKeyParameters key) throws IOException
- {
- BigInteger Y = key.getY();
- DHParameters params = key.getParameters();
- BigInteger p = params.getP();
- BigInteger g = params.getG();
-
- if (!p.isProbablePrime(2))
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- if (g.compareTo(TWO) < 0 || g.compareTo(p.subtract(TWO)) > 0)
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- if (Y.compareTo(TWO) < 0 || Y.compareTo(p.subtract(ONE)) > 0)
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- // TODO See RFC 2631 for more discussion of Diffie-Hellman validation
-
- return key;
- }
-
- 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
- {
- TlsUtils.writeOpaque16(BigIntegers.asUnsignedByteArray(x), output);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsDSASigner.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsDSASigner.java
deleted file mode 100644
index caaad59a..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsDSASigner.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.CryptoException;
-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.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.signers.DSADigestSigner;
-
-public abstract class TlsDSASigner
- extends AbstractTlsSigner
-{
- public byte[] generateRawSignature(SignatureAndHashAlgorithm algorithm,
- AsymmetricKeyParameter privateKey, byte[] hash)
- throws CryptoException
- {
- Signer signer = makeSigner(algorithm, true, true,
- new ParametersWithRandom(privateKey, this.context.getSecureRandom()));
- 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(SignatureAndHashAlgorithm algorithm, byte[] sigBytes,
- AsymmetricKeyParameter publicKey, byte[] hash)
- throws CryptoException
- {
- 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(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter privateKey)
- {
- return makeSigner(algorithm, false, true, privateKey);
- }
-
- public Signer createVerifyer(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter publicKey)
- {
- return makeSigner(algorithm, false, false, publicKey);
- }
-
- protected CipherParameters makeInitParameters(boolean forSigning, CipherParameters cp)
- {
- return cp;
- }
-
- protected Signer makeSigner(SignatureAndHashAlgorithm algorithm, boolean raw, boolean forSigning,
- CipherParameters cp)
- {
- if ((algorithm != null) != TlsUtils.isTLSv12(context))
- {
- throw new IllegalStateException();
- }
-
- // TODO For TLS 1.2+, lift the SHA-1 restriction here
- if (algorithm != null
- && (algorithm.getHash() != HashAlgorithm.sha1 || algorithm.getSignature() != getSignatureAlgorithm()))
- {
- throw new IllegalStateException();
- }
-
- short hashAlgorithm = algorithm == null ? HashAlgorithm.sha1 : algorithm.getHash();
- Digest d = raw ? new NullDigest() : TlsUtils.createHash(hashAlgorithm);
-
- Signer s = new DSADigestSigner(createDSAImpl(hashAlgorithm), d);
- s.init(forSigning, makeInitParameters(forSigning, cp));
- return s;
- }
-
- protected abstract short getSignatureAlgorithm();
-
- protected abstract DSA createDSAImpl(short hashAlgorithm);
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsDSSSigner.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsDSSSigner.java
deleted file mode 100644
index 2914b7e4..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsDSSSigner.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import org.bouncycastle.crypto.DSA;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
-import org.bouncycastle.crypto.signers.DSASigner;
-import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
-
-public class TlsDSSSigner
- extends TlsDSASigner
-{
- public boolean isValidPublicKey(AsymmetricKeyParameter publicKey)
- {
- return publicKey instanceof DSAPublicKeyParameters;
- }
-
- protected DSA createDSAImpl(short hashAlgorithm)
- {
- return new DSASigner(new HMacDSAKCalculator(TlsUtils.createHash(hashAlgorithm)));
- }
-
- protected short getSignatureAlgorithm()
- {
- return SignatureAlgorithm.dsa;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsECCUtils.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsECCUtils.java
deleted file mode 100644
index e9f96f06..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsECCUtils.java
+++ /dev/null
@@ -1,690 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.math.BigInteger;
-import java.security.SecureRandom;
-import java.util.Hashtable;
-
-import org.bouncycastle.asn1.x9.ECNamedCurveTable;
-import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.agreement.ECDHBasicAgreement;
-import org.bouncycastle.crypto.ec.CustomNamedCurves;
-import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.math.ec.ECAlgorithms;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.field.PolynomialExtensionField;
-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",
- "sect193r2", "sect233k1", "sect233r1", "sect239k1", "sect283k1", "sect283r1", "sect409k1", "sect409r1",
- "sect571k1", "sect571r1", "secp160k1", "secp160r1", "secp160r2", "secp192k1", "secp192r1", "secp224k1",
- "secp224r1", "secp256k1", "secp256r1", "secp384r1", "secp521r1",
- "brainpoolP256r1", "brainpoolP384r1", "brainpoolP512r1"};
-
- 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
- {
- byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_elliptic_curves);
- return extensionData == null ? null : readSupportedEllipticCurvesExtension(extensionData);
- }
-
- public static short[] getSupportedPointFormatsExtension(Hashtable extensions) throws IOException
- {
- byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_ec_point_formats);
- return extensionData == null ? null : readSupportedPointFormatsExtension(extensionData);
- }
-
- public static byte[] createSupportedEllipticCurvesExtension(int[] namedCurves) throws IOException
- {
- if (namedCurves == null || namedCurves.length < 1)
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- return TlsUtils.encodeUint16ArrayWithUint16Length(namedCurves);
- }
-
- public static byte[] createSupportedPointFormatsExtension(short[] ecPointFormats) throws IOException
- {
- if (ecPointFormats == null || !Arrays.contains(ecPointFormats, ECPointFormat.uncompressed))
- {
- /*
- * RFC 4492 5.1. If the Supported Point Formats Extension is indeed sent, it MUST
- * contain the value 0 (uncompressed) as one of the items in the list of point formats.
- */
-
- // NOTE: We add it at the end (lowest preference)
- ecPointFormats = Arrays.append(ecPointFormats, ECPointFormat.uncompressed);
- }
-
- return TlsUtils.encodeUint8ArrayWithUint8Length(ecPointFormats);
- }
-
- public static int[] readSupportedEllipticCurvesExtension(byte[] extensionData) throws IOException
- {
- if (extensionData == null)
- {
- throw new IllegalArgumentException("'extensionData' cannot be null");
- }
-
- ByteArrayInputStream buf = new ByteArrayInputStream(extensionData);
-
- int length = TlsUtils.readUint16(buf);
- if (length < 2 || (length & 1) != 0)
- {
- throw new TlsFatalAlert(AlertDescription.decode_error);
- }
-
- int[] namedCurves = TlsUtils.readUint16Array(length / 2, buf);
-
- TlsProtocol.assertEmpty(buf);
-
- return namedCurves;
- }
-
- public static short[] readSupportedPointFormatsExtension(byte[] extensionData) throws IOException
- {
- if (extensionData == null)
- {
- throw new IllegalArgumentException("'extensionData' cannot be null");
- }
-
- ByteArrayInputStream buf = new ByteArrayInputStream(extensionData);
-
- short length = TlsUtils.readUint8(buf);
- if (length < 1)
- {
- throw new TlsFatalAlert(AlertDescription.decode_error);
- }
-
- short[] ecPointFormats = TlsUtils.readUint8Array(length, buf);
-
- TlsProtocol.assertEmpty(buf);
-
- if (!Arrays.contains(ecPointFormats, ECPointFormat.uncompressed))
- {
- /*
- * RFC 4492 5.1. If the Supported Point Formats Extension is indeed sent, it MUST
- * contain the value 0 (uncompressed) as one of the items in the list of point formats.
- */
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- return ecPointFormats;
- }
-
- public static String getNameOfNamedCurve(int namedCurve)
- {
- return isSupportedNamedCurve(namedCurve) ? curveNames[namedCurve - 1] : null;
- }
-
- public static ECDomainParameters getParametersForNamedCurve(int namedCurve)
- {
- String curveName = getNameOfNamedCurve(namedCurve);
- if (curveName == null)
- {
- return null;
- }
-
- // Parameters are lazily created the first time a particular curve is accessed
-
- X9ECParameters ecP = CustomNamedCurves.getByName(curveName);
- if (ecP == null)
- {
- ecP = ECNamedCurveTable.getByName(curveName);
- if (ecP == null)
- {
- return null;
- }
- }
-
- // It's a bit inefficient to do this conversion every time
- return new ECDomainParameters(ecP.getCurve(), ecP.getG(), ecP.getN(), ecP.getH(), ecP.getSeed());
- }
-
- public static boolean hasAnySupportedNamedCurves()
- {
- return curveNames.length > 0;
- }
-
- public static boolean containsECCCipherSuites(int[] cipherSuites)
- {
- for (int i = 0; i < cipherSuites.length; ++i)
- {
- if (isECCCipherSuite(cipherSuites[i]))
- {
- return true;
- }
- }
- return false;
- }
-
- public static boolean isECCCipherSuite(int cipherSuite)
- {
- 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:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_ECDH_anon_WITH_NULL_SHA:
- case CipherSuite.TLS_ECDH_anon_WITH_RC4_128_SHA:
- 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:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
- 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:
-
- /*
- * RFC 6367
- */
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
-
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
-
- case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
-
- /*
- * draft-agl-tls-chacha20poly1305-04
- */
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
-
- /*
- * draft-josefsson-salsa20-tls-04
- */
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1:
- case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
- case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1:
- case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
- case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1:
-
- return true;
-
- default:
- return false;
- }
- }
-
- public static boolean areOnSameCurve(ECDomainParameters a, ECDomainParameters b)
- {
- // TODO Move to ECDomainParameters.equals() or other utility method?
- return a.getCurve().equals(b.getCurve()) && a.getG().equals(b.getG()) && a.getN().equals(b.getN())
- && a.getH().equals(b.getH());
- }
-
- public static boolean isSupportedNamedCurve(int namedCurve)
- {
- return (namedCurve > 0 && namedCurve <= curveNames.length);
- }
-
- public static boolean isCompressionPreferred(short[] ecPointFormats, short compressionFormat)
- {
- if (ecPointFormats == null)
- {
- return false;
- }
- for (int i = 0; i < ecPointFormats.length; ++i)
- {
- short ecPointFormat = ecPointFormats[i];
- if (ecPointFormat == ECPointFormat.uncompressed)
- {
- return false;
- }
- if (ecPointFormat == compressionFormat)
- {
- return true;
- }
- }
- return false;
- }
-
- public static byte[] serializeECFieldElement(int fieldSize, BigInteger x) throws IOException
- {
- return BigIntegers.asUnsignedByteArray((fieldSize + 7) / 8, x);
- }
-
- public static byte[] serializeECPoint(short[] ecPointFormats, ECPoint point) throws IOException
- {
- ECCurve curve = point.getCurve();
-
- /*
- * RFC 4492 5.7. ...an elliptic curve point in uncompressed or compressed format. Here, the
- * format MUST conform to what the server has requested through a Supported Point Formats
- * Extension if this extension was used, and MUST be uncompressed if this extension was not
- * used.
- */
- boolean compressed = false;
- if (ECAlgorithms.isFpCurve(curve))
- {
- compressed = isCompressionPreferred(ecPointFormats, ECPointFormat.ansiX962_compressed_prime);
- }
- else if (ECAlgorithms.isF2mCurve(curve))
- {
- compressed = isCompressionPreferred(ecPointFormats, ECPointFormat.ansiX962_compressed_char2);
- }
- return point.getEncoded(compressed);
- }
-
- 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
- {
- int requiredLength = (fieldSize + 7) / 8;
- if (encoding.length != requiredLength)
- {
- throw new TlsFatalAlert(AlertDescription.decode_error);
- }
- return new BigInteger(1, encoding);
- }
-
- public static ECPoint deserializeECPoint(short[] ecPointFormats, ECCurve curve, byte[] encoding) throws IOException
- {
- if (encoding == null || encoding.length < 1)
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- short actualFormat;
- switch (encoding[0])
- {
- case 0x02: // compressed
- case 0x03: // compressed
- {
- if (ECAlgorithms.isF2mCurve(curve))
- {
- actualFormat = ECPointFormat.ansiX962_compressed_char2;
- }
- else if (ECAlgorithms.isFpCurve(curve))
- {
- actualFormat = ECPointFormat.ansiX962_compressed_prime;
- }
- else
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- break;
- }
- case 0x04: // uncompressed
- {
- actualFormat = ECPointFormat.uncompressed;
- break;
- }
- case 0x00: // infinity
- case 0x06: // hybrid
- case 0x07: // hybrid
- default:
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- if (!Arrays.contains(ecPointFormats, actualFormat))
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- return curve.decodePoint(encoding);
- }
-
- public static ECPublicKeyParameters deserializeECPublicKey(short[] ecPointFormats, ECDomainParameters curve_params,
- byte[] encoding) throws IOException
- {
- try
- {
- ECPoint Y = deserializeECPoint(ecPointFormats, curve_params.getCurve(), encoding);
- return new ECPublicKeyParameters(Y, curve_params);
- }
- catch (RuntimeException e)
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- }
-
- public static byte[] calculateECDHBasicAgreement(ECPublicKeyParameters publicKey, ECPrivateKeyParameters privateKey)
- {
- ECDHBasicAgreement basicAgreement = new ECDHBasicAgreement();
- basicAgreement.init(privateKey);
- BigInteger agreementValue = basicAgreement.calculateAgreement(publicKey);
-
- /*
- * RFC 4492 5.10. Note that this octet string (Z in IEEE 1363 terminology) as output by
- * FE2OSP, the Field Element to Octet String Conversion Primitive, has constant length for
- * any given field; leading zeros found in this octet string MUST NOT be truncated.
- */
- return BigIntegers.asUnsignedByteArray(basicAgreement.getFieldSize(), agreementValue);
- }
-
- public static AsymmetricCipherKeyPair generateECKeyPair(SecureRandom random, ECDomainParameters ecParams)
- {
- ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
- keyPairGenerator.init(new ECKeyGenerationParameters(ecParams, random));
- return keyPairGenerator.generateKeyPair();
- }
-
- public static ECPrivateKeyParameters generateEphemeralClientKeyExchange(SecureRandom random, short[] ecPointFormats,
- ECDomainParameters ecParams, OutputStream output) throws IOException
- {
- AsymmetricCipherKeyPair kp = 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
- {
- BigInteger K = readECParameter(input);
- if (K.bitLength() < 32)
- {
- int k = K.intValue();
- if (k > 0 && k < fieldSize)
- {
- return k;
- }
- }
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- public static BigInteger readECFieldElement(int fieldSize, InputStream input) throws IOException
- {
- return deserializeECFieldElement(fieldSize, TlsUtils.readOpaque8(input));
- }
-
- public static BigInteger readECParameter(InputStream input) throws IOException
- {
- // TODO Are leading zeroes okay here?
- return new BigInteger(1, TlsUtils.readOpaque8(input));
- }
-
- public static ECDomainParameters readECParameters(int[] namedCurves, short[] ecPointFormats, InputStream input)
- throws IOException
- {
- try
- {
- short curveType = TlsUtils.readUint8(input);
-
- switch (curveType)
- {
- 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);
- byte[] baseEncoding = TlsUtils.readOpaque8(input);
- BigInteger order = readECParameter(input);
- BigInteger cofactor = readECParameter(input);
- ECCurve curve = new ECCurve.Fp(prime_p, a, b, order, cofactor);
- ECPoint base = deserializeECPoint(ecPointFormats, curve, baseEncoding);
- return new ECDomainParameters(curve, base, order, cofactor);
- }
- case ECCurveType.explicit_char2:
- {
- checkNamedCurve(namedCurves, NamedCurve.arbitrary_explicit_char2_curves);
-
- int m = TlsUtils.readUint16(input);
- short basis = TlsUtils.readUint8(input);
- if (!ECBasisType.isValid(basis))
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- int k1 = readECExponent(m, input), k2 = -1, k3 = -1;
- if (basis == ECBasisType.ec_basis_pentanomial)
- {
- k2 = readECExponent(m, input);
- k3 = readECExponent(m, input);
- }
-
- BigInteger a = readECFieldElement(m, input);
- BigInteger b = readECFieldElement(m, input);
- byte[] baseEncoding = TlsUtils.readOpaque8(input);
- BigInteger order = readECParameter(input);
- BigInteger cofactor = readECParameter(input);
-
- ECCurve curve = (basis == ECBasisType.ec_basis_pentanomial)
- ? new ECCurve.F2m(m, k1, k2, k3, a, b, order, cofactor)
- : new ECCurve.F2m(m, k1, a, b, order, cofactor);
-
- ECPoint base = deserializeECPoint(ecPointFormats, curve, baseEncoding);
-
- return new ECDomainParameters(curve, base, order, cofactor);
- }
- case ECCurveType.named_curve:
- {
- int namedCurve = TlsUtils.readUint16(input);
- if (!NamedCurve.refersToASpecificNamedCurve(namedCurve))
- {
- /*
- * RFC 4492 5.4. All those values of NamedCurve are allowed that refer to a
- * specific curve. Values of NamedCurve that indicate support for a class of
- * explicitly defined curves are not allowed here [...].
- */
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- checkNamedCurve(namedCurves, namedCurve);
-
- return getParametersForNamedCurve(namedCurve);
- }
- default:
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- }
- catch (RuntimeException e)
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- }
-
- 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(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
- {
- TlsUtils.writeOpaque8(BigIntegers.asUnsignedByteArray(x), output);
- }
-
- public static void writeExplicitECParameters(short[] ecPointFormats, ECDomainParameters ecParameters,
- OutputStream output) throws IOException
- {
- ECCurve curve = ecParameters.getCurve();
-
- if (ECAlgorithms.isFpCurve(curve))
- {
- TlsUtils.writeUint8(ECCurveType.explicit_prime, output);
-
- writeECParameter(curve.getField().getCharacteristic(), output);
- }
- else if (ECAlgorithms.isF2mCurve(curve))
- {
- PolynomialExtensionField field = (PolynomialExtensionField)curve.getField();
- int[] exponents = field.getMinimalPolynomial().getExponentsPresent();
-
- TlsUtils.writeUint8(ECCurveType.explicit_char2, output);
-
- int m = exponents[exponents.length - 1];
- TlsUtils.checkUint16(m);
- TlsUtils.writeUint16(m, output);
-
- if (exponents.length == 3)
- {
- TlsUtils.writeUint8(ECBasisType.ec_basis_trinomial, output);
- writeECExponent(exponents[1], output);
- }
- else if (exponents.length == 5)
- {
- TlsUtils.writeUint8(ECBasisType.ec_basis_pentanomial, output);
- writeECExponent(exponents[1], output);
- writeECExponent(exponents[2], output);
- writeECExponent(exponents[3], output);
- }
- else
- {
- throw new IllegalArgumentException("Only trinomial and pentomial curves are supported");
- }
- }
- else
- {
- throw new IllegalArgumentException("'ecParameters' not a known curve type");
- }
-
- 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 writeECPoint(short[] ecPointFormats, ECPoint point, OutputStream output) throws IOException
- {
- TlsUtils.writeOpaque8(serializeECPoint(ecPointFormats, point), output);
- }
-
- public static void writeNamedECParameters(int namedCurve, OutputStream output) throws IOException
- {
- if (!NamedCurve.refersToASpecificNamedCurve(namedCurve))
- {
- /*
- * RFC 4492 5.4. All those values of NamedCurve are allowed that refer to a specific
- * curve. Values of NamedCurve that indicate support for a class of explicitly defined
- * curves are not allowed here [...].
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- TlsUtils.writeUint8(ECCurveType.named_curve, output);
- TlsUtils.checkUint16(namedCurve);
- TlsUtils.writeUint16(namedCurve, output);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsECDHEKeyExchange.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsECDHEKeyExchange.java
deleted file mode 100644
index b112af57..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsECDHEKeyExchange.java
+++ /dev/null
@@ -1,221 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Vector;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.Signer;
-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)
- */
-public class TlsECDHEKeyExchange
- extends TlsECDHKeyExchange
-{
- protected TlsSignerCredentials serverCredentials = null;
-
- public TlsECDHEKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms, int[] namedCurves,
- short[] clientECPointFormats, short[] serverECPointFormats)
- {
- super(keyExchange, supportedSignatureAlgorithms, namedCurves, clientECPointFormats, serverECPointFormats);
- }
-
- public void processServerCredentials(TlsCredentials serverCredentials)
- throws IOException
- {
- if (!(serverCredentials instanceof TlsSignerCredentials))
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- processServerCertificate(serverCredentials.getCertificate());
-
- this.serverCredentials = (TlsSignerCredentials)serverCredentials;
- }
-
- 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
- {
- for (int i = 0; i < namedCurves.length; ++i)
- {
- int entry = namedCurves[i];
- if (NamedCurve.isValid(entry) && TlsECCUtils.isSupportedNamedCurve(entry))
- {
- namedCurve = entry;
- break;
- }
- }
- }
-
- ECDomainParameters curve_params = null;
- if (namedCurve >= 0)
- {
- curve_params = TlsECCUtils.getParametersForNamedCurve(namedCurve);
- }
- else
- {
- /*
- * If no named curves are suitable, check if the client supports explicit curves.
- */
- if (Arrays.contains(namedCurves, NamedCurve.arbitrary_explicit_prime_curves))
- {
- curve_params = TlsECCUtils.getParametersForNamedCurve(NamedCurve.secp256r1);
- }
- else if (Arrays.contains(namedCurves, NamedCurve.arbitrary_explicit_char2_curves))
- {
- curve_params = TlsECCUtils.getParametersForNamedCurve(NamedCurve.sect283r1);
- }
- }
-
- if (curve_params == null)
- {
- /*
- * NOTE: We shouldn't have negotiated ECDHE key exchange since we apparently can't find
- * a suitable curve.
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- AsymmetricCipherKeyPair kp = TlsECCUtils.generateECKeyPair(context.getSecureRandom(), curve_params);
- this.ecAgreePrivateKey = (ECPrivateKeyParameters)kp.getPrivate();
-
- DigestInputBuffer buf = new DigestInputBuffer();
-
- if (namedCurve < 0)
- {
- TlsECCUtils.writeExplicitECParameters(clientECPointFormats, curve_params, buf);
- }
- else
- {
- TlsECCUtils.writeNamedECParameters(namedCurve, 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);
- }
-
- d = TlsUtils.createHash(signatureAndHashAlgorithm.getHash());
- }
- else
- {
- signatureAndHashAlgorithm = null;
- d = new CombinedHash();
- }
-
- SecurityParameters securityParameters = context.getSecurityParameters();
- d.update(securityParameters.clientRandom, 0, securityParameters.clientRandom.length);
- d.update(securityParameters.serverRandom, 0, securityParameters.serverRandom.length);
- buf.updateDigest(d);
-
- byte[] hash = new byte[d.getDigestSize()];
- d.doFinal(hash, 0);
-
- byte[] signature = serverCredentials.generateCertificateSignature(hash);
-
- DigitallySigned signed_params = new DigitallySigned(signatureAndHashAlgorithm, signature);
- signed_params.encode(buf);
-
- return buf.toByteArray();
- }
-
- public void processServerKeyExchange(InputStream input)
- throws IOException
- {
- SecurityParameters securityParameters = context.getSecurityParameters();
-
- SignerInputBuffer buf = new SignerInputBuffer();
- InputStream teeIn = new TeeInputStream(input, buf);
-
- ECDomainParameters curve_params = TlsECCUtils.readECParameters(namedCurves, clientECPointFormats, teeIn);
-
- byte[] point = TlsUtils.readOpaque8(teeIn);
-
- DigitallySigned signed_params = DigitallySigned.parse(context, input);
-
- Signer signer = initVerifyer(tlsSigner, signed_params.getAlgorithm(), securityParameters);
- buf.updateSigner(signer);
- if (!signer.verifySignature(signed_params.getSignature()))
- {
- throw new TlsFatalAlert(AlertDescription.decrypt_error);
- }
-
- this.ecAgreePublicKey = TlsECCUtils.validateECPublicKey(TlsECCUtils.deserializeECPublicKey(
- clientECPointFormats, curve_params, point));
- }
-
- public void validateCertificateRequest(CertificateRequest certificateRequest)
- throws IOException
- {
- /*
- * RFC 4492 3. [...] The ECDSA_fixed_ECDH and RSA_fixed_ECDH mechanisms are usable with
- * ECDH_ECDSA and ECDH_RSA. Their use with ECDHE_ECDSA and ECDHE_RSA is prohibited because
- * the use of a long-term ECDH client key would jeopardize the forward secrecy property of
- * these algorithms.
- */
- short[] types = certificateRequest.getCertificateTypes();
- for (int i = 0; i < types.length; ++i)
- {
- switch (types[i])
- {
- case ClientCertificateType.rsa_sign:
- case ClientCertificateType.dss_sign:
- case ClientCertificateType.ecdsa_sign:
- break;
- default:
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- }
- }
-
- public void processClientCredentials(TlsCredentials clientCredentials)
- throws IOException
- {
- if (clientCredentials instanceof TlsSignerCredentials)
- {
- // OK
- }
- else
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- protected Signer initVerifyer(TlsSigner tlsSigner, SignatureAndHashAlgorithm algorithm, SecurityParameters securityParameters)
- {
- 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/core/src/main/java/org/bouncycastle/crypto/tls/TlsECDHKeyExchange.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsECDHKeyExchange.java
deleted file mode 100644
index 94563520..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsECDHKeyExchange.java
+++ /dev/null
@@ -1,219 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.x509.KeyUsage;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.util.PublicKeyFactory;
-
-/**
- * ECDH key exchange (see RFC 4492)
- */
-public class TlsECDHKeyExchange extends AbstractTlsKeyExchange
-{
- protected TlsSigner tlsSigner;
- protected int[] namedCurves;
- protected short[] clientECPointFormats, serverECPointFormats;
-
- protected AsymmetricKeyParameter serverPublicKey;
- protected TlsAgreementCredentials agreementCredentials;
-
- protected ECPrivateKeyParameters ecAgreePrivateKey;
- protected ECPublicKeyParameters ecAgreePublicKey;
-
- public TlsECDHKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms, int[] namedCurves,
- short[] clientECPointFormats, short[] serverECPointFormats)
- {
- super(keyExchange, supportedSignatureAlgorithms);
-
- switch (keyExchange)
- {
- case KeyExchangeAlgorithm.ECDHE_RSA:
- this.tlsSigner = new TlsRSASigner();
- break;
- case KeyExchangeAlgorithm.ECDHE_ECDSA:
- this.tlsSigner = new TlsECDSASigner();
- break;
- case KeyExchangeAlgorithm.ECDH_RSA:
- case KeyExchangeAlgorithm.ECDH_ECDSA:
- this.tlsSigner = null;
- break;
- default:
- throw new IllegalArgumentException("unsupported key exchange algorithm");
- }
-
- this.keyExchange = keyExchange;
- this.namedCurves = namedCurves;
- this.clientECPointFormats = clientECPointFormats;
- this.serverECPointFormats = serverECPointFormats;
- }
-
- public void init(TlsContext context)
- {
- super.init(context);
-
- if (this.tlsSigner != null)
- {
- this.tlsSigner.init(context);
- }
- }
-
- public void skipServerCredentials() throws IOException
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
-
- public void processServerCertificate(Certificate serverCertificate) throws IOException
- {
- if (serverCertificate.isEmpty())
- {
- throw new TlsFatalAlert(AlertDescription.bad_certificate);
- }
-
- org.bouncycastle.asn1.x509.Certificate x509Cert = serverCertificate.getCertificateAt(0);
-
- SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo();
- try
- {
- this.serverPublicKey = PublicKeyFactory.createKey(keyInfo);
- }
- catch (RuntimeException e)
- {
- throw new TlsFatalAlert(AlertDescription.unsupported_certificate);
- }
-
- if (tlsSigner == null)
- {
- try
- {
- this.ecAgreePublicKey = TlsECCUtils.validateECPublicKey((ECPublicKeyParameters) this.serverPublicKey);
- }
- catch (ClassCastException e)
- {
- throw new TlsFatalAlert(AlertDescription.certificate_unknown);
- }
-
- TlsUtils.validateKeyUsage(x509Cert, KeyUsage.keyAgreement);
- }
- else
- {
- if (!tlsSigner.isValidPublicKey(this.serverPublicKey))
- {
- throw new TlsFatalAlert(AlertDescription.certificate_unknown);
- }
-
- TlsUtils.validateKeyUsage(x509Cert, KeyUsage.digitalSignature);
- }
-
- super.processServerCertificate(serverCertificate);
- }
-
- public boolean requiresServerKeyExchange()
- {
- switch (keyExchange)
- {
- case KeyExchangeAlgorithm.ECDHE_ECDSA:
- case KeyExchangeAlgorithm.ECDHE_RSA:
- case KeyExchangeAlgorithm.ECDH_anon:
- return true;
- default:
- return false;
- }
- }
-
- public void validateCertificateRequest(CertificateRequest certificateRequest) throws IOException
- {
- /*
- * RFC 4492 3. [...] The ECDSA_fixed_ECDH and RSA_fixed_ECDH mechanisms are usable with
- * ECDH_ECDSA and ECDH_RSA. Their use with ECDHE_ECDSA and ECDHE_RSA is prohibited because
- * the use of a long-term ECDH client key would jeopardize the forward secrecy property of
- * these algorithms.
- */
- short[] types = certificateRequest.getCertificateTypes();
- for (int i = 0; i < types.length; ++i)
- {
- switch (types[i])
- {
- case ClientCertificateType.rsa_sign:
- case ClientCertificateType.dss_sign:
- case ClientCertificateType.ecdsa_sign:
- case ClientCertificateType.rsa_fixed_ecdh:
- case ClientCertificateType.ecdsa_fixed_ecdh:
- break;
- default:
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- }
- }
-
- 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;
- }
- else if (clientCredentials instanceof TlsSignerCredentials)
- {
- // OK
- }
- else
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- public void generateClientKeyExchange(OutputStream output) throws IOException
- {
- if (agreementCredentials == null)
- {
- this.ecAgreePrivateKey = TlsECCUtils.generateEphemeralClientKeyExchange(context.getSecureRandom(),
- serverECPointFormats, ecAgreePublicKey.getParameters(), output);
- }
- }
-
- 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
- {
- if (ecAgreePublicKey != null)
- {
- // For ecdsa_fixed_ecdh and rsa_fixed_ecdh, the key arrived in the client certificate
- return;
- }
-
- byte[] point = TlsUtils.readOpaque8(input);
-
- ECDomainParameters curve_params = this.ecAgreePrivateKey.getParameters();
-
- this.ecAgreePublicKey = TlsECCUtils.validateECPublicKey(TlsECCUtils.deserializeECPublicKey(
- serverECPointFormats, curve_params, point));
- }
-
- public byte[] generatePremasterSecret() throws IOException
- {
- if (agreementCredentials != null)
- {
- return agreementCredentials.generateAgreement(ecAgreePublicKey);
- }
-
- if (ecAgreePrivateKey != null)
- {
- return TlsECCUtils.calculateECDHBasicAgreement(ecAgreePublicKey, ecAgreePrivateKey);
- }
-
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsECDSASigner.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsECDSASigner.java
deleted file mode 100644
index aa4c546e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsECDSASigner.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import org.bouncycastle.crypto.DSA;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.signers.ECDSASigner;
-import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
-
-public class TlsECDSASigner
- extends TlsDSASigner
-{
- public boolean isValidPublicKey(AsymmetricKeyParameter publicKey)
- {
- return publicKey instanceof ECPublicKeyParameters;
- }
-
- protected DSA createDSAImpl(short hashAlgorithm)
- {
- return new ECDSASigner(new HMacDSAKCalculator(TlsUtils.createHash(hashAlgorithm)));
- }
-
- protected short getSignatureAlgorithm()
- {
- return SignatureAlgorithm.ecdsa;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsEncryptionCredentials.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsEncryptionCredentials.java
deleted file mode 100644
index f2928963..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsEncryptionCredentials.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-public interface TlsEncryptionCredentials extends TlsCredentials
-{
- byte[] decryptPreMasterSecret(byte[] encryptedPreMasterSecret)
- throws IOException;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsExtensionsUtils.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsExtensionsUtils.java
deleted file mode 100644
index a59a1d5a..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsExtensionsUtils.java
+++ /dev/null
@@ -1,267 +0,0 @@
-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_encrypt_then_mac = Integers.valueOf(ExtensionType.encrypt_then_mac);
- 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 addEncryptThenMACExtension(Hashtable extensions)
- {
- extensions.put(EXT_encrypt_then_mac, createEncryptThenMACExtension());
- }
-
- 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 hasEncryptThenMACExtension(Hashtable extensions) throws IOException
- {
- byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_encrypt_then_mac);
- return extensionData == null ? false : readEncryptThenMACExtension(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[] createEncryptThenMACExtension()
- {
- return createEmptyExtensionData();
- }
-
- 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();
- }
-
- private static boolean readEmptyExtensionData(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;
- }
-
- public static boolean readEncryptThenMACExtension(byte[] extensionData) throws IOException
- {
- return readEmptyExtensionData(extensionData);
- }
-
- 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;
- }
-
- public static boolean readTruncatedHMacExtension(byte[] extensionData) throws IOException
- {
- return readEmptyExtensionData(extensionData);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsFatalAlert.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsFatalAlert.java
deleted file mode 100644
index 61cec318..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsFatalAlert.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-public class TlsFatalAlert
- extends IOException
-{
- private static final long serialVersionUID = 3584313123679111168L;
-
- private short alertDescription;
-
- public TlsFatalAlert(short alertDescription)
- {
- this.alertDescription = alertDescription;
- }
-
- public short getAlertDescription()
- {
- return alertDescription;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsHandshakeHash.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsHandshakeHash.java
deleted file mode 100644
index 4ccfe72b..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsHandshakeHash.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import org.bouncycastle.crypto.Digest;
-
-public interface TlsHandshakeHash
- extends Digest
-{
- void init(TlsContext context);
-
- TlsHandshakeHash notifyPRFDetermined();
-
- void trackHashAlgorithm(short hashAlgorithm);
-
- void sealHashAlgorithms();
-
- TlsHandshakeHash stopTracking();
-
- Digest forkPRFHash();
-
- byte[] getFinalHash(short hashAlgorithm);
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsInputStream.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsInputStream.java
deleted file mode 100644
index a2cf74e8..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsInputStream.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * An InputStream for an TLS 1.0 connection.
- */
-class TlsInputStream
- extends InputStream
-{
- private byte[] buf = new byte[1];
- private TlsProtocol handler = null;
-
- TlsInputStream(TlsProtocol handler)
- {
- this.handler = handler;
- }
-
- public int available()
- throws IOException
- {
- return this.handler.applicationDataAvailable();
- }
-
- public int read(byte[] buf, int offset, int len)
- throws IOException
- {
- return this.handler.readApplicationData(buf, offset, len);
- }
-
- public int read()
- throws IOException
- {
- if (this.read(buf) < 0)
- {
- return -1;
- }
- return buf[0] & 0xff;
- }
-
- public void close()
- throws IOException
- {
- handler.close();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsKeyExchange.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsKeyExchange.java
deleted file mode 100644
index 50455907..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsKeyExchange.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * A generic interface for key exchange implementations in TLS 1.0/1.1.
- */
-public interface TlsKeyExchange
-{
- void init(TlsContext context);
-
- void skipServerCredentials()
- throws IOException;
-
- void processServerCredentials(TlsCredentials serverCredentials)
- throws IOException;
-
- void processServerCertificate(Certificate serverCertificate)
- throws IOException;
-
- boolean requiresServerKeyExchange();
-
- byte[] generateServerKeyExchange()
- throws IOException;
-
- void skipServerKeyExchange()
- throws IOException;
-
- void processServerKeyExchange(InputStream input)
- throws IOException;
-
- void validateCertificateRequest(CertificateRequest certificateRequest)
- throws IOException;
-
- void skipClientCredentials()
- throws IOException;
-
- void processClientCredentials(TlsCredentials clientCredentials)
- throws IOException;
-
- void processClientCertificate(Certificate clientCertificate)
- throws IOException;
-
- void generateClientKeyExchange(OutputStream output)
- throws IOException;
-
- void processClientKeyExchange(InputStream input)
- throws IOException;
-
- byte[] generatePremasterSecret()
- throws IOException;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsMac.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsMac.java
deleted file mode 100644
index 00e0c79f..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsMac.java
+++ /dev/null
@@ -1,172 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.digests.LongDigest;
-import org.bouncycastle.crypto.macs.HMac;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Arrays;
-
-/**
- * A generic TLS MAC implementation, acting as an HMAC based on some underlying Digest.
- */
-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 keyOff The number of bytes to skip, before the key starts in the buffer.
- * @param keyLen The length of the key.
- */
- public TlsMac(TlsContext context, Digest digest, byte[] key, int keyOff, int keyLen)
- {
- this.context = context;
-
- KeyParameter keyParameter = new KeyParameter(key, keyOff, keyLen);
-
- this.secret = Arrays.clone(keyParameter.getKey());
-
- // TODO This should check the actual algorithm, not rely on the engine type
- if (digest instanceof LongDigest)
- {
- this.digestBlockSize = 128;
- this.digestOverhead = 16;
- }
- else
- {
- this.digestBlockSize = 64;
- this.digestOverhead = 8;
- }
-
- if (TlsUtils.isSSL(context))
- {
- this.mac = new SSL3Mac(digest);
-
- // TODO This should check the actual algorithm, not assume based on the digest size
- if (digest.getDigestSize() == 20)
- {
- /*
- * NOTE: When SHA-1 is used with the SSL 3.0 MAC, the secret + input pad is not
- * digest block-aligned.
- */
- this.digestOverhead = 4;
- }
- }
- else
- {
- this.mac = new HMac(digest);
-
- // NOTE: The input pad for HMAC is always a full digest block
- }
-
- this.mac.init(keyParameter);
-
- this.macLength = mac.getMacSize();
- if (context.getSecurityParameters().truncatedHMac)
- {
- this.macLength = Math.min(this.macLength, 10);
- }
- }
-
- /**
- * @return the MAC write secret
- */
- public byte[] getMACSecret()
- {
- return this.secret;
- }
-
- /**
- * @return The output length of this MAC.
- */
- public int getSize()
- {
- return macLength;
- }
-
- /**
- * Calculate the MAC for some given data.
- *
- * @param type The message type of the message.
- * @param message A byte-buffer containing the message.
- * @param offset The number of bytes to skip, before the message starts.
- * @param length The length of the message.
- * @return A new byte-buffer containing the MAC value.
- */
- public byte[] calculateMac(long seqNo, short type, byte[] message, int offset, int length)
- {
- ProtocolVersion serverVersion = context.getServerVersion();
- boolean isSSL = serverVersion.isSSL();
-
- byte[] macHeader = new byte[isSSL ? 11 : 13];
- TlsUtils.writeUint64(seqNo, macHeader, 0);
- TlsUtils.writeUint8(type, macHeader, 8);
- if (!isSSL)
- {
- TlsUtils.writeVersion(serverVersion, macHeader, 9);
- }
- TlsUtils.writeUint16(length, macHeader, macHeader.length - 2);
-
- mac.update(macHeader, 0, macHeader.length);
- mac.update(message, offset, length);
-
- byte[] result = new byte[mac.getMacSize()];
- mac.doFinal(result, 0);
- return truncate(result);
- }
-
- public byte[] calculateMacConstantTime(long seqNo, short type, byte[] message, int offset, int length,
- int fullLength, byte[] dummyData)
- {
- /*
- * Actual MAC only calculated on 'length' bytes...
- */
- byte[] result = calculateMac(seqNo, type, message, offset, length);
-
- /*
- * ...but ensure a constant number of complete digest blocks are processed (as many as would
- * be needed for 'fullLength' bytes of input).
- */
- 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);
-
- while (--extra >= 0)
- {
- mac.update(dummyData, 0, digestBlockSize);
- }
-
- // One more byte in case the implementation is "lazy" about processing blocks
- mac.update(dummyData[0]);
- mac.reset();
-
- return result;
- }
-
- 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/core/src/main/java/org/bouncycastle/crypto/tls/TlsNullCipher.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsNullCipher.java
deleted file mode 100644
index d1f6986b..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsNullCipher.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.util.Arrays;
-
-/**
- * A NULL CipherSuite with optional MAC
- */
-public class TlsNullCipher
- implements TlsCipher
-{
- protected TlsContext context;
-
- protected TlsMac writeMac;
- protected TlsMac readMac;
-
- public TlsNullCipher(TlsContext context)
- {
- this.context = context;
- this.writeMac = null;
- this.readMac = null;
- }
-
- public TlsNullCipher(TlsContext context, Digest clientWriteDigest, Digest serverWriteDigest)
- throws IOException
- {
- if ((clientWriteDigest == null) != (serverWriteDigest == null))
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- this.context = context;
-
- TlsMac clientWriteMac = null, serverWriteMac = null;
-
- if (clientWriteDigest != null)
- {
- int key_block_size = clientWriteDigest.getDigestSize()
- + serverWriteDigest.getDigestSize();
- byte[] key_block = TlsUtils.calculateKeyBlock(context, key_block_size);
-
- int offset = 0;
-
- clientWriteMac = new TlsMac(context, clientWriteDigest, key_block, offset,
- clientWriteDigest.getDigestSize());
- offset += clientWriteDigest.getDigestSize();
-
- serverWriteMac = new TlsMac(context, serverWriteDigest, key_block, offset,
- serverWriteDigest.getDigestSize());
- offset += serverWriteDigest.getDigestSize();
-
- if (offset != key_block_size)
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- if (context.isServer())
- {
- writeMac = serverWriteMac;
- readMac = clientWriteMac;
- }
- else
- {
- writeMac = clientWriteMac;
- readMac = serverWriteMac;
- }
- }
-
- public int getPlaintextLimit(int ciphertextLimit)
- {
- int result = ciphertextLimit;
- if (writeMac != null)
- {
- result -= writeMac.getSize();
- }
- return result;
- }
-
- 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);
- }
-
- byte[] mac = writeMac.calculateMac(seqNo, type, plaintext, offset, len);
- byte[] ciphertext = new byte[len + mac.length];
- System.arraycopy(plaintext, offset, ciphertext, 0, len);
- System.arraycopy(mac, 0, ciphertext, len, mac.length);
- return ciphertext;
- }
-
- 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);
- }
-
- int macSize = readMac.getSize();
- if (len < macSize)
- {
- throw new TlsFatalAlert(AlertDescription.decode_error);
- }
-
- int macInputLen = len - macSize;
-
- byte[] receivedMac = Arrays.copyOfRange(ciphertext, offset + macInputLen, offset + len);
- byte[] computedMac = readMac.calculateMac(seqNo, type, ciphertext, offset, macInputLen);
-
- if (!Arrays.constantTimeAreEqual(receivedMac, computedMac))
- {
- throw new TlsFatalAlert(AlertDescription.bad_record_mac);
- }
-
- return Arrays.copyOfRange(ciphertext, offset, offset + macInputLen);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsNullCompression.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsNullCompression.java
deleted file mode 100644
index 13a85abf..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsNullCompression.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.OutputStream;
-
-public class TlsNullCompression
- implements TlsCompression
-{
- public OutputStream compress(OutputStream output)
- {
- return output;
- }
-
- public OutputStream decompress(OutputStream output)
- {
- return output;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsOutputStream.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsOutputStream.java
deleted file mode 100644
index d9532414..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsOutputStream.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * An OutputStream for an TLS connection.
- */
-class TlsOutputStream
- extends OutputStream
-{
- private byte[] buf = new byte[1];
- private TlsProtocol handler;
-
- TlsOutputStream(TlsProtocol handler)
- {
- this.handler = handler;
- }
-
- public void write(byte buf[], int offset, int len)
- throws IOException
- {
- this.handler.writeData(buf, offset, len);
- }
-
- public void write(int arg0)
- throws IOException
- {
- buf[0] = (byte)arg0;
- this.write(buf, 0, 1);
- }
-
- public void close()
- throws IOException
- {
- handler.close();
- }
-
- public void flush()
- throws IOException
- {
- handler.flush();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsPSKIdentity.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsPSKIdentity.java
deleted file mode 100644
index 2f6eea26..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsPSKIdentity.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-public interface TlsPSKIdentity
-{
- void skipIdentityHint();
-
- void notifyIdentityHint(byte[] psk_identity_hint);
-
- byte[] getPSKIdentity();
-
- byte[] getPSK();
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsPSKKeyExchange.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsPSKKeyExchange.java
deleted file mode 100644
index 7217bac6..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsPSKKeyExchange.java
+++ /dev/null
@@ -1,285 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.x509.KeyUsage;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
-import org.bouncycastle.crypto.params.DHPublicKeyParameters;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.util.PublicKeyFactory;
-
-/**
- * TLS 1.0 PSK key exchange (RFC 4279).
- */
-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 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,
- 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:
- 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()
- throws IOException
- {
- if (keyExchange == KeyExchangeAlgorithm.RSA_PSK)
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- }
-
- 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);
- }
- if (serverCertificate.isEmpty())
- {
- throw new TlsFatalAlert(AlertDescription.bad_certificate);
- }
-
- org.bouncycastle.asn1.x509.Certificate x509Cert = serverCertificate.getCertificateAt(0);
-
- SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo();
- try
- {
- this.serverPublicKey = PublicKeyFactory.createKey(keyInfo);
- }
- catch (RuntimeException e)
- {
- throw new TlsFatalAlert(AlertDescription.unsupported_certificate);
- }
-
- // Sanity check the PublicKeyFactory
- if (this.serverPublicKey.isPrivate())
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- this.rsaServerPublicKey = validateRSAPublicKey((RSAKeyParameters)this.serverPublicKey);
-
- TlsUtils.validateKeyUsage(x509Cert, KeyUsage.keyEncipherment);
-
- super.processServerCertificate(serverCertificate);
- }
-
- public boolean requiresServerKeyExchange()
- {
- 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)
- {
- ServerDHParams serverDHParams = ServerDHParams.parse(input);
-
- this.dhAgreePublicKey = TlsDHUtils.validateDHPublicKey(serverDHParams.getPublicKey());
- }
- else if (this.keyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
- {
- // TODO[RFC 5489]
- }
- }
-
- public void validateCertificateRequest(CertificateRequest certificateRequest)
- throws IOException
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
-
- public void processClientCredentials(TlsCredentials clientCredentials)
- throws IOException
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- public void generateClientKeyExchange(OutputStream output)
- throws IOException
- {
- if (psk_identity_hint == null)
- {
- pskIdentity.skipIdentityHint();
- }
- else
- {
- pskIdentity.notifyIdentityHint(psk_identity_hint);
- }
-
- byte[] psk_identity = pskIdentity.getPSKIdentity();
-
- TlsUtils.writeOpaque16(psk_identity, output);
-
- if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK)
- {
- 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.RSA_PSK)
- {
- this.premasterSecret = TlsRSAUtils.generateEncryptedPreMasterSecret(context, this.rsaServerPublicKey,
- output);
- }
- }
-
- public byte[] generatePremasterSecret()
- throws IOException
- {
- byte[] psk = pskIdentity.getPSK();
- byte[] other_secret = generateOtherSecret(psk.length);
-
- ByteArrayOutputStream buf = new ByteArrayOutputStream(4 + other_secret.length + psk.length);
- TlsUtils.writeOpaque16(other_secret, buf);
- TlsUtils.writeOpaque16(psk, buf);
- return buf.toByteArray();
- }
-
- protected byte[] generateOtherSecret(int pskLength) throws IOException
- {
- if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK)
- {
- 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)
- {
- return this.premasterSecret;
- }
-
- return new byte[pskLength];
- }
-
- protected RSAKeyParameters validateRSAPublicKey(RSAKeyParameters key)
- throws IOException
- {
- // TODO What is the minimum bit length required?
- // key.getModulus().bitLength();
-
- if (!key.getExponent().isProbablePrime(2))
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- return key;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsPeer.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsPeer.java
deleted file mode 100644
index 1ee2e5fa..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsPeer.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-public interface TlsPeer
-{
- /**
- * draft-mathewson-no-gmtunixtime-00 2. "If existing users of a TLS implementation may rely on
- * gmt_unix_time containing the current time, we recommend that implementors MAY provide the
- * ability to set gmt_unix_time as an option only, off by default."
- *
- * @return <code>true</code> if the current time should be used in the gmt_unix_time field of
- * Random, or <code>false</code> if gmt_unix_time should contain a cryptographically
- * random value.
- */
- boolean shouldUseGMTUnixTime();
-
- 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.
- *
- * @param alertLevel {@link AlertLevel}
- * @param alertDescription {@link AlertDescription}
- * @param message A human-readable message explaining what caused this alert. May be null.
- * @param cause The exception that caused this alert to be raised. May be null.
- */
- void notifyAlertRaised(short alertLevel, short alertDescription, String message, Exception cause);
-
- /**
- * This method will be called when an alert is received from the remote peer.
- *
- * @param alertLevel {@link AlertLevel}
- * @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/core/src/main/java/org/bouncycastle/crypto/tls/TlsProtocol.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsProtocol.java
deleted file mode 100644
index 02629056..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsProtocol.java
+++ /dev/null
@@ -1,1184 +0,0 @@
-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;
-import java.security.SecureRandom;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.prng.RandomGenerator;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Integers;
-
-/**
- * An implementation of all high level protocols in TLS 1.0/1.1.
- */
-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);
-
- private static final String TLS_ERROR_MESSAGE = "Internal TLS error, this could be an attack";
-
- /*
- * Our Connection states
- */
- protected static final short CS_START = 0;
- protected static final short CS_CLIENT_HELLO = 1;
- 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_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_FINISHED = 15;
- protected static final short CS_END = 16;
-
- /*
- * Queues for data from some protocols.
- */
- private ByteQueue applicationDataQueue = new ByteQueue();
- private ByteQueue alertQueue = new ByteQueue(2);
- private ByteQueue handshakeQueue = new ByteQueue();
-// private ByteQueue heartbeatQueue = new ByteQueue();
-
- /*
- * The Record Stream we use
- */
- protected RecordStream recordStream;
- protected SecureRandom secureRandom;
-
- private TlsInputStream tlsInputStream = null;
- private TlsOutputStream tlsOutputStream = null;
-
- private volatile boolean closed = false;
- private volatile boolean failedWithError = false;
- private volatile boolean appDataReady = false;
- 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)
- {
- this.recordStream = new RecordStream(this, input, output);
- this.secureRandom = secureRandom;
- }
-
- protected abstract AbstractTlsContext getContext();
-
- protected abstract TlsPeer getPeer();
-
- protected void handleChangeCipherSpecMessage() throws IOException
- {
- }
-
- protected abstract void handleHandshakeMessage(short type, byte[] buf)
- throws IOException;
-
- 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?
- }
-
- safeReadRecord();
- }
-
- this.recordStream.finaliseHandshake();
-
- this.splitApplicationDataRecords = !TlsUtils.isTLSv11(getContext());
-
- /*
- * 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);
- }
-
- 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();
- }
- }
-
- protected void processRecord(short protocol, byte[] buf, int offset, int len)
- throws IOException
- {
- /*
- * Have a look at the protocol type, and add it to the correct queue.
- */
- switch (protocol)
- {
- case ContentType.alert:
- {
- alertQueue.addData(buf, offset, len);
- processAlert();
- break;
- }
- case ContentType.application_data:
- {
- if (!appDataReady)
- {
- 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:
- {
- if (!appDataReady)
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- // TODO[RFC 6520]
-// heartbeatQueue.addData(buf, offset, len);
-// processHeartbeat();
- }
- default:
- /*
- * Uh, we don't know this protocol.
- *
- * RFC2246 defines on page 13, that we should ignore this.
- */
- }
- }
-
- private void processHandshake()
- throws IOException
- {
- boolean read;
- do
- {
- read = false;
- /*
- * We need the first 4 bytes, they contain type and length of the message.
- */
- if (handshakeQueue.size() >= 4)
- {
- byte[] beginning = new byte[4];
- handshakeQueue.read(beginning, 0, 4, 0);
- ByteArrayInputStream bis = new ByteArrayInputStream(beginning);
- short type = TlsUtils.readUint8(bis);
- int len = TlsUtils.readUint24(bis);
-
- /*
- * Check if we have enough bytes in the buffer to read the full message.
- */
- if (handshakeQueue.size() >= (len + 4))
- {
- /*
- * Read the message.
- */
- byte[] buf = handshakeQueue.removeData(len, 4);
-
- /*
- * RFC 2246 7.4.9. The value handshake_messages includes all handshake messages
- * starting at client hello up to, but not including, this finished message.
- * [..] Note: [Also,] Hello Request messages are omitted from handshake hashes.
- */
- switch (type)
- {
- case HandshakeType.hello_request:
- break;
- case HandshakeType.finished:
- {
- if (this.expected_verify_data == null)
- {
- this.expected_verify_data = createVerifyData(!getContext().isServer());
- }
-
- // NB: Fall through to next case label
- }
- default:
- recordStream.updateHandshakeData(beginning, 0, 4);
- recordStream.updateHandshakeData(buf, 0, len);
- break;
- }
-
- /*
- * Now, parse the message.
- */
- handleHandshakeMessage(type, buf);
- read = true;
- }
- }
- }
- while (read);
- }
-
- private void processApplicationData()
- {
- /*
- * There is nothing we need to do here.
- *
- * This function could be used for callbacks when application data arrives in the future.
- */
- }
-
- private void processAlert()
- throws IOException
- {
- while (alertQueue.size() >= 2)
- {
- /*
- * An alert is always 2 bytes. Read the alert.
- */
- byte[] tmp = alertQueue.removeData(2, 0);
- short level = tmp[0];
- short description = tmp[1];
-
- getPeer().notifyAlertReceived(level, description);
-
- 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;
-
- recordStream.safeClose();
-
- throw new IOException(TLS_ERROR_MESSAGE);
- }
- else
- {
-
- /*
- * RFC 5246 7.2.1. The other party MUST respond with a close_notify alert of its own
- * and close down the connection immediately, discarding any pending writes.
- */
- // TODO Can close_notify be a fatal alert?
- if (description == AlertDescription.close_notify)
- {
- handleClose(false);
- }
-
- /*
- * If it is just a warning, we continue.
- */
- handleWarningMessage(description);
- }
- }
- }
-
- /**
- * This method is called, when a change cipher spec message is received.
- *
- * @throws IOException If the message has an invalid content or the handshake is not in the correct
- * state.
- */
- private void processChangeCipherSpec(byte[] buf, int off, int len)
- throws IOException
- {
- for (int i = 0; i < len; ++i)
- {
- short message = TlsUtils.readUint8(buf, off + i);
-
- if (message != ChangeCipherSpec.change_cipher_spec)
- {
- throw new TlsFatalAlert(AlertDescription.decode_error);
- }
-
- if (this.receivedChangeCipherSpec
- || alertQueue.size() > 0
- || handshakeQueue.size() > 0)
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
-
- recordStream.receivedReadCipherSpec();
-
- this.receivedChangeCipherSpec = true;
-
- handleChangeCipherSpecMessage();
- }
- }
-
- protected int applicationDataAvailable()
- throws IOException
- {
- return applicationDataQueue.size();
- }
-
- /**
- * Read data from the network. The method will return immediately, if there is still some data
- * left in the buffer, or block until some application data has been read from the network.
- *
- * @param buf The buffer where the data will be copied to.
- * @param offset The position where the data will be placed in the buffer.
- * @param len The maximum number of bytes to read.
- * @return The number of bytes read.
- * @throws IOException If something goes wrong during reading data.
- */
- protected int readApplicationData(byte[] buf, int offset, int len)
- throws IOException
- {
- if (len < 1)
- {
- return 0;
- }
-
- while (applicationDataQueue.size() == 0)
- {
- /*
- * We need to read some data.
- */
- if (this.closed)
- {
- if (this.failedWithError)
- {
- /*
- * Something went terribly wrong, we should throw an IOException
- */
- throw new IOException(TLS_ERROR_MESSAGE);
- }
-
- /*
- * Connection has been closed, there is no more data to read.
- */
- return -1;
- }
-
- safeReadRecord();
- }
-
- len = Math.min(len, applicationDataQueue.size());
- applicationDataQueue.removeData(buf, offset, len, 0);
- return len;
- }
-
- protected void safeReadRecord()
- throws IOException
- {
- try
- {
- 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(), "Failed to read record", e);
- }
- throw e;
- }
- catch (IOException e)
- {
- if (!this.closed)
- {
- this.failWithError(AlertLevel.fatal, AlertDescription.internal_error, "Failed to read record", e);
- }
- throw e;
- }
- catch (RuntimeException e)
- {
- if (!this.closed)
- {
- this.failWithError(AlertLevel.fatal, AlertDescription.internal_error, "Failed to read record", e);
- }
- throw e;
- }
- }
-
- protected void safeWriteRecord(short type, byte[] buf, int offset, int len)
- throws IOException
- {
- try
- {
- recordStream.writeRecord(type, buf, offset, len);
- }
- catch (TlsFatalAlert e)
- {
- if (!this.closed)
- {
- this.failWithError(AlertLevel.fatal, e.getAlertDescription(), "Failed to write record", e);
- }
- throw e;
- }
- catch (IOException e)
- {
- if (!closed)
- {
- this.failWithError(AlertLevel.fatal, AlertDescription.internal_error, "Failed to write record", e);
- }
- throw e;
- }
- catch (RuntimeException e)
- {
- if (!closed)
- {
- this.failWithError(AlertLevel.fatal, AlertDescription.internal_error, "Failed to write record", e);
- }
- throw e;
- }
- }
-
- /**
- * Send some application data to the remote system.
- * <p/>
- * The method will handle fragmentation internally.
- *
- * @param buf The buffer with the data.
- * @param offset The position in the buffer where the data is placed.
- * @param len The length of the data.
- * @throws IOException If something goes wrong during sending.
- */
- protected void writeData(byte[] buf, int offset, int len)
- throws IOException
- {
- if (this.closed)
- {
- if (this.failedWithError)
- {
- throw new IOException(TLS_ERROR_MESSAGE);
- }
-
- throw new IOException("Sorry, connection has been closed, you cannot write more data");
- }
-
- while (len > 0)
- {
- /*
- * 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.splitApplicationDataRecords)
- {
- /*
- * Protect against known IV attack!
- *
- * DO NOT REMOVE THIS CODE, EXCEPT YOU KNOW EXACTLY WHAT YOU ARE DOING HERE.
- */
- safeWriteRecord(ContentType.application_data, buf, offset, 1);
- ++offset;
- --len;
- }
-
- 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;
- }
- }
- }
-
- 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;
- }
- }
-
- /**
- * @return An OutputStream which can be used to send data.
- */
- public OutputStream getOutputStream()
- {
- return this.tlsOutputStream;
- }
-
- /**
- * @return An InputStream which can be used to read data.
- */
- public InputStream getInputStream()
- {
- return this.tlsInputStream;
- }
-
- /**
- * 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, String message, Exception cause)
- throws IOException
- {
- /*
- * Check if the connection is still open.
- */
- if (!closed)
- {
- /*
- * Prepare the message
- */
- this.closed = true;
-
- if (alertLevel == 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.
- */
- // 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, message, cause);
- recordStream.safeClose();
- if (alertLevel != AlertLevel.fatal)
- {
- return;
- }
- }
-
- throw new IOException(TLS_ERROR_MESSAGE);
- }
-
- protected void invalidateSession()
- {
- if (this.sessionParameters != null)
- {
- 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);
-
- /*
- * Compare both checksums.
- */
- if (!Arrays.constantTimeAreEqual(expected_verify_data, verify_data))
- {
- /*
- * Wrong checksum in the finished message.
- */
- 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];
- error[0] = (byte)alertLevel;
- error[1] = (byte)alertDescription;
-
- safeWriteRecord(ContentType.alert, error, 0, 2);
- }
-
- protected void raiseWarning(short alertDescription, String message)
- throws IOException
- {
- raiseAlert(AlertLevel.warning, alertDescription, message, null);
- }
-
- protected void sendCertificateMessage(Certificate certificate)
- throws IOException
- {
- if (certificate == null)
- {
- certificate = Certificate.EMPTY_CHAIN;
- }
-
- if (certificate.getLength() == 0)
- {
- TlsContext context = getContext();
- if (!context.isServer())
- {
- ProtocolVersion serverVersion = getContext().getServerVersion();
- if (serverVersion.isSSL())
- {
- String message = serverVersion.toString() + " client didn't provide credentials";
- raiseWarning(AlertDescription.no_certificate, message);
- return;
- }
- }
- }
-
- HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate);
-
- certificate.encode(message);
-
- message.writeToRecordStream();
- }
-
- protected void sendChangeCipherSpecMessage()
- throws IOException
- {
- byte[] message = new byte[]{ 1 };
- safeWriteRecord(ContentType.change_cipher_spec, message, 0, message.length);
- recordStream.sentWriteCipherSpec();
- }
-
- protected void sendFinishedMessage()
- throws IOException
- {
- byte[] verify_data = createVerifyData(getContext().isServer());
-
- HandshakeMessage message = new HandshakeMessage(HandshakeType.finished, verify_data.length);
-
- message.write(verify_data);
-
- message.writeToRecordStream();
- }
-
- protected void sendSupplementalDataMessage(Vector supplementalData)
- throws IOException
- {
- HandshakeMessage message = new HandshakeMessage(HandshakeType.supplemental_data);
-
- writeSupplementalData(message, supplementalData);
-
- message.writeToRecordStream();
- }
-
- protected byte[] createVerifyData(boolean isServer)
- {
- TlsContext context = getContext();
-
- if (isServer)
- {
- return TlsUtils.calculateVerifyData(context, ExporterLabel.server_finished,
- getCurrentPRFHash(getContext(), recordStream.getHandshakeHash(), TlsUtils.SSL_SERVER));
- }
-
- return TlsUtils.calculateVerifyData(context, ExporterLabel.client_finished,
- getCurrentPRFHash(getContext(), recordStream.getHandshakeHash(), TlsUtils.SSL_CLIENT));
- }
-
- /**
- * Closes this connection.
- *
- * @throws IOException If something goes wrong during closing.
- */
- public void close()
- throws IOException
- {
- handleClose(true);
- }
-
- protected void handleClose(boolean user_canceled)
- throws IOException
- {
- if (!closed)
- {
- if (user_canceled && !appDataReady)
- {
- raiseWarning(AlertDescription.user_canceled, "User canceled handshake");
- }
- this.failWithError(AlertLevel.warning, AlertDescription.close_notify, "Connection closed", null);
- }
- }
-
- protected void flush()
- throws IOException
- {
- recordStream.flush();
- }
-
- protected short processMaxFragmentLengthExtension(Hashtable clientExtensions, Hashtable serverExtensions, short alertDescription)
- throws IOException
- {
- short maxFragmentLength = TlsExtensionsUtils.getMaxFragmentLengthExtension(serverExtensions);
- if (maxFragmentLength >= 0 && !this.resumedSession)
- {
- if (maxFragmentLength != TlsExtensionsUtils.getMaxFragmentLengthExtension(clientExtensions))
- {
- throw new TlsFatalAlert(alertDescription);
- }
- }
- return maxFragmentLength;
- }
-
- /**
- * Make sure the InputStream 'buf' now empty. Fail otherwise.
- *
- * @param buf The InputStream to check.
- * @throws IOException If 'buf' is not empty.
- */
- protected static void assertEmpty(ByteArrayInputStream buf)
- throws IOException
- {
- if (buf.available() > 0)
- {
- throw new TlsFatalAlert(AlertDescription.decode_error);
- }
- }
-
- protected static byte[] createRandomBlock(boolean useGMTUnixTime, RandomGenerator randomGenerator)
- {
- byte[] result = new byte[32];
- randomGenerator.nextBytes(result);
-
- if (useGMTUnixTime)
- {
- TlsUtils.writeGMTUnixTime(result, 0);
- }
-
- return result;
- }
-
- protected static byte[] createRenegotiationInfo(byte[] renegotiated_connection)
- throws IOException
- {
- return TlsUtils.encodeOpaque8(renegotiated_connection);
- }
-
- protected static void establishMasterSecret(TlsContext context, TlsKeyExchange keyExchange)
- throws IOException
- {
- byte[] pre_master_secret = keyExchange.generatePremasterSecret();
-
- try
- {
- context.getSecurityParameters().masterSecret = TlsUtils.calculateMasterSecret(context, pre_master_secret);
- }
- finally
- {
- // TODO Is there a way to ensure the data is really overwritten?
- /*
- * RFC 2246 8.1. The pre_master_secret should be deleted from memory once the
- * master_secret has been computed.
- */
- if (pre_master_secret != null)
- {
- Arrays.fill(pre_master_secret, (byte)0);
- }
- }
- }
-
- /**
- * '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;
- }
-
- byte[] extBytes = TlsUtils.readOpaque16(input);
-
- assertEmpty(input);
-
- ByteArrayInputStream buf = new ByteArrayInputStream(extBytes);
-
- // Integer -> byte[]
- Hashtable extensions = new Hashtable();
-
- while (buf.available() > 0)
- {
- 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(extension_type, extension_data))
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- }
-
- return extensions;
- }
-
- protected static Vector readSupplementalDataMessage(ByteArrayInputStream input)
- throws IOException
- {
- byte[] supp_data = TlsUtils.readOpaque24(input);
-
- assertEmpty(input);
-
- ByteArrayInputStream buf = new ByteArrayInputStream(supp_data);
-
- Vector supplementalData = new Vector();
-
- while (buf.available() > 0)
- {
- int supp_data_type = TlsUtils.readUint16(buf);
- byte[] data = TlsUtils.readOpaque16(buf);
-
- supplementalData.addElement(new SupplementalDataEntry(supp_data_type, data));
- }
-
- return supplementalData;
- }
-
- protected static void writeExtensions(OutputStream output, Hashtable extensions)
- throws IOException
- {
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
-
- Enumeration keys = extensions.keys();
- while (keys.hasMoreElements())
- {
- Integer key = (Integer)keys.nextElement();
- int extension_type = key.intValue();
- byte[] extension_data = (byte[])extensions.get(key);
-
- TlsUtils.checkUint16(extension_type);
- TlsUtils.writeUint16(extension_type, buf);
- TlsUtils.writeOpaque16(extension_data, buf);
- }
-
- byte[] extBytes = buf.toByteArray();
-
- TlsUtils.writeOpaque16(extBytes, output);
- }
-
- 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);
-
- int supp_data_type = entry.getDataType();
- TlsUtils.checkUint16(supp_data_type);
- TlsUtils.writeUint16(supp_data_type, buf);
- TlsUtils.writeOpaque16(entry.getData(), buf);
- }
-
- byte[] supp_data = buf.toByteArray();
-
- TlsUtils.writeOpaque24(supp_data, output);
- }
-
- protected static int getPRFAlgorithm(TlsContext context, int ciphersuite) throws IOException
- {
- boolean isTLSv12 = TlsUtils.isTLSv12(context);
-
- switch (ciphersuite)
- {
- case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DH_DSS_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_DSS_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_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_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_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_DSS_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_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_PSK_WITH_CAMELLIA_128_GCM_SHA256:
- 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_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_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_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_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_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_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_PSK_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_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_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_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
- {
- if (isTLSv12)
- {
- return PRFAlgorithm.tls_prf_sha256;
- }
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_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_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_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_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_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_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_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_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_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_CAMELLIA_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_CAMELLIA_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_CAMELLIA_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_CAMELLIA_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/core/src/main/java/org/bouncycastle/crypto/tls/TlsProtocolHandler.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsProtocolHandler.java
deleted file mode 100644
index 6b9e8eb0..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsProtocolHandler.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.security.SecureRandom;
-
-/**
- * @deprecated use TlsClientProtocol instead
- */
-public class TlsProtocolHandler
- extends TlsClientProtocol
-{
- public TlsProtocolHandler(InputStream is, OutputStream os)
- {
- super(is, os);
- }
-
- public TlsProtocolHandler(InputStream is, OutputStream os, SecureRandom sr)
- {
- super(is, os, sr);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsRSAKeyExchange.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsRSAKeyExchange.java
deleted file mode 100644
index cd3eb0c3..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsRSAKeyExchange.java
+++ /dev/null
@@ -1,191 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.x509.KeyUsage;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.util.PublicKeyFactory;
-import org.bouncycastle.util.io.Streams;
-
-/**
- * TLS 1.0/1.1 and SSLv3 RSA key exchange.
- */
-public class TlsRSAKeyExchange
- extends AbstractTlsKeyExchange
-{
- protected AsymmetricKeyParameter serverPublicKey = null;
-
- protected RSAKeyParameters rsaServerPublicKey = null;
-
- protected TlsEncryptionCredentials serverCredentials = null;
-
- protected byte[] premasterSecret;
-
- public TlsRSAKeyExchange(Vector supportedSignatureAlgorithms)
- {
- super(KeyExchangeAlgorithm.RSA, supportedSignatureAlgorithms);
- }
-
- public void skipServerCredentials()
- throws IOException
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
-
- 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 void processServerCertificate(Certificate serverCertificate)
- throws IOException
- {
- if (serverCertificate.isEmpty())
- {
- throw new TlsFatalAlert(AlertDescription.bad_certificate);
- }
-
- org.bouncycastle.asn1.x509.Certificate x509Cert = serverCertificate.getCertificateAt(0);
-
- SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo();
- try
- {
- this.serverPublicKey = PublicKeyFactory.createKey(keyInfo);
- }
- catch (RuntimeException e)
- {
- throw new TlsFatalAlert(AlertDescription.unsupported_certificate);
- }
-
- // Sanity check the PublicKeyFactory
- if (this.serverPublicKey.isPrivate())
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- this.rsaServerPublicKey = validateRSAPublicKey((RSAKeyParameters)this.serverPublicKey);
-
- TlsUtils.validateKeyUsage(x509Cert, KeyUsage.keyEncipherment);
-
- super.processServerCertificate(serverCertificate);
- }
-
- public void validateCertificateRequest(CertificateRequest certificateRequest)
- throws IOException
- {
- short[] types = certificateRequest.getCertificateTypes();
- for (int i = 0; i < types.length; ++i)
- {
- switch (types[i])
- {
- case ClientCertificateType.rsa_sign:
- case ClientCertificateType.dss_sign:
- case ClientCertificateType.ecdsa_sign:
- break;
- default:
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- }
- }
-
- public void processClientCredentials(TlsCredentials clientCredentials)
- throws IOException
- {
- if (!(clientCredentials instanceof TlsSignerCredentials))
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- public void generateClientKeyExchange(OutputStream output)
- throws IOException
- {
- this.premasterSecret = TlsRSAUtils.generateEncryptedPreMasterSecret(context, rsaServerPublicKey, output);
- }
-
- public void processClientKeyExchange(InputStream input)
- throws IOException
- {
- byte[] encryptedPreMasterSecret;
- if (TlsUtils.isSSL(context))
- {
- // TODO Do any SSLv3 clients actually include the length?
- encryptedPreMasterSecret = Streams.readAll(input);
- }
- else
- {
- encryptedPreMasterSecret = TlsUtils.readOpaque16(input);
- }
-
- this.premasterSecret = serverCredentials.decryptPreMasterSecret(encryptedPreMasterSecret);
- }
-
- public byte[] generatePremasterSecret()
- throws IOException
- {
- if (this.premasterSecret == null)
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- byte[] tmp = this.premasterSecret;
- this.premasterSecret = null;
- return tmp;
- }
-
- // Would be needed to process RSA_EXPORT server key exchange
- // protected void processRSAServerKeyExchange(InputStream is, Signer signer) throws IOException
- // {
- // InputStream sigIn = is;
- // if (signer != null)
- // {
- // sigIn = new SignerInputStream(is, signer);
- // }
- //
- // byte[] modulusBytes = TlsUtils.readOpaque16(sigIn);
- // byte[] exponentBytes = TlsUtils.readOpaque16(sigIn);
- //
- // if (signer != null)
- // {
- // byte[] sigByte = TlsUtils.readOpaque16(is);
- //
- // if (!signer.verifySignature(sigByte))
- // {
- // handler.failWithError(AlertLevel.fatal, AlertDescription.bad_certificate);
- // }
- // }
- //
- // BigInteger modulus = new BigInteger(1, modulusBytes);
- // BigInteger exponent = new BigInteger(1, exponentBytes);
- //
- // this.rsaServerPublicKey = validateRSAPublicKey(new RSAKeyParameters(false, modulus,
- // exponent));
- // }
-
- protected RSAKeyParameters validateRSAPublicKey(RSAKeyParameters key)
- throws IOException
- {
- // TODO What is the minimum bit length required?
- // key.getModulus().bitLength();
-
- if (!key.getExponent().isProbablePrime(2))
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- return key;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsRSASigner.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsRSASigner.java
deleted file mode 100644
index 35538a70..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsRSASigner.java
+++ /dev/null
@@ -1,112 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-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;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.signers.GenericSigner;
-import org.bouncycastle.crypto.signers.RSADigestSigner;
-
-public class TlsRSASigner
- extends AbstractTlsSigner
-{
- public byte[] generateRawSignature(SignatureAndHashAlgorithm algorithm,
- AsymmetricKeyParameter privateKey, byte[] hash)
- throws CryptoException
- {
- Signer signer = makeSigner(algorithm, true, true,
- new ParametersWithRandom(privateKey, this.context.getSecureRandom()));
- signer.update(hash, 0, hash.length);
- return signer.generateSignature();
- }
-
- public boolean verifyRawSignature(SignatureAndHashAlgorithm algorithm, byte[] sigBytes,
- AsymmetricKeyParameter publicKey, byte[] hash)
- throws CryptoException
- {
- Signer signer = makeSigner(algorithm, true, false, publicKey);
- signer.update(hash, 0, hash.length);
- return signer.verifySignature(sigBytes);
- }
-
- public Signer createSigner(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter privateKey)
- {
- return makeSigner(algorithm, false, true, new ParametersWithRandom(privateKey, this.context.getSecureRandom()));
- }
-
- public Signer createVerifyer(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter publicKey)
- {
- return makeSigner(algorithm, false, false, publicKey);
- }
-
- public boolean isValidPublicKey(AsymmetricKeyParameter publicKey)
- {
- return publicKey instanceof RSAKeyParameters && !publicKey.isPrivate();
- }
-
- 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 (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, TlsUtils.getOIDForHashAlgorithm(algorithm.getHash()));
- }
- else
- {
- /*
- * RFC 5246 4.7. Note that earlier versions of TLS used a different RSA signature scheme
- * that did not include a DigestInfo encoding.
- */
- s = new GenericSigner(createRSAImpl(), d);
- }
- s.init(forSigning, cp);
- return s;
- }
-
- protected AsymmetricBlockCipher createRSAImpl()
- {
- /*
- * RFC 5264 7.4.7.1. Implementation note: It is now known that remote timing-based attacks
- * on TLS are possible, at least when the client and server are on the same LAN.
- * Accordingly, implementations that use static RSA keys MUST use RSA blinding or some other
- * anti-timing technique, as described in [TIMING].
- */
- return new PKCS1Encoding(new RSABlindedEngine());
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsRSAUtils.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsRSAUtils.java
deleted file mode 100644
index 1fe4fa52..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsRSAUtils.java
+++ /dev/null
@@ -1,140 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.encodings.PKCS1Encoding;
-import org.bouncycastle.crypto.engines.RSABlindedEngine;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.util.Arrays;
-
-public class TlsRSAUtils
-{
- public static byte[] generateEncryptedPreMasterSecret(TlsContext context, RSAKeyParameters rsaServerPublicKey,
- OutputStream output) throws IOException
- {
- /*
- * Choose a PremasterSecret and send it encrypted to the server
- */
- byte[] premasterSecret = new byte[48];
- context.getSecureRandom().nextBytes(premasterSecret);
- TlsUtils.writeVersion(context.getClientVersion(), premasterSecret, 0);
-
- PKCS1Encoding encoding = new PKCS1Encoding(new RSABlindedEngine());
- encoding.init(true, new ParametersWithRandom(rsaServerPublicKey, context.getSecureRandom()));
-
- try
- {
- byte[] encryptedPreMasterSecret = encoding.processBlock(premasterSecret, 0, premasterSecret.length);
-
- if (TlsUtils.isSSL(context))
- {
- // TODO Do any SSLv3 servers actually expect the length?
- output.write(encryptedPreMasterSecret);
- }
- else
- {
- TlsUtils.writeOpaque16(encryptedPreMasterSecret, output);
- }
- }
- catch (InvalidCipherTextException e)
- {
- /*
- * This should never happen, only during decryption.
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- return premasterSecret;
- }
-
- /**
- * @deprecated {@link TlsEncryptionCredentials#decryptPreMasterSecret(byte[])} is expected to decrypt safely
- */
- public static byte[] safeDecryptPreMasterSecret(TlsContext context, TlsEncryptionCredentials encryptionCredentials,
- byte[] encryptedPreMasterSecret) throws IOException
- {
- return encryptionCredentials.decryptPreMasterSecret(encryptedPreMasterSecret);
- }
-
- public static byte[] safeDecryptPreMasterSecret(TlsContext context, RSAKeyParameters rsaServerPrivateKey,
- byte[] encryptedPreMasterSecret)
- {
- /*
- * RFC 5246 7.4.7.1.
- */
- ProtocolVersion clientVersion = context.getClientVersion();
-
- // TODO Provide as configuration option?
- boolean versionNumberCheckDisabled = false;
-
- /*
- * Generate 48 random bytes we can use as a Pre-Master-Secret, if the
- * PKCS1 padding check should fail.
- */
- byte[] fallback = new byte[48];
- context.getSecureRandom().nextBytes(fallback);
-
- byte[] M = Arrays.clone(fallback);
- try
- {
- PKCS1Encoding encoding = new PKCS1Encoding(new RSABlindedEngine(), fallback);
- encoding.init(false,
- new ParametersWithRandom(rsaServerPrivateKey, context.getSecureRandom()));
-
- M = encoding.processBlock(encryptedPreMasterSecret, 0, encryptedPreMasterSecret.length);
- }
- catch (Exception e)
- {
- /*
- * This should never happen since the decryption should never throw an exception
- * and return a random value instead.
- *
- * 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 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.
- *
- * So there is nothing to do here.
- */
- }
- else
- {
- /*
- * OK, we need to compare the version number in the decrypted Pre-Master-Secret with the
- * clientVersion received during the handshake. If they don't match, we replace the
- * decrypted Pre-Master-Secret with a random one.
- */
- int correct = (clientVersion.getMajorVersion() ^ (M[0] & 0xff))
- | (clientVersion.getMinorVersion() ^ (M[1] & 0xff));
- correct |= correct >> 1;
- correct |= correct >> 2;
- correct |= correct >> 4;
- int mask = ~((correct & 1) - 1);
-
- /*
- * mask will be all bits set to 0xff if the version number differed.
- */
- for (int i = 0; i < 48; i++)
- {
- M[i] = (byte)((M[i] & (~mask)) | (fallback[i] & mask));
- }
- }
- return M;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsSRPKeyExchange.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsSRPKeyExchange.java
deleted file mode 100644
index 9e81fe67..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsSRPKeyExchange.java
+++ /dev/null
@@ -1,205 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-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;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.crypto.CryptoException;
-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.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
-{
- protected TlsSigner tlsSigner;
- protected byte[] identity;
- protected byte[] password;
-
- protected AsymmetricKeyParameter serverPublicKey = null;
-
- protected byte[] s = null;
- protected BigInteger B = null;
- protected SRP6Client srpClient = new SRP6Client();
-
- public TlsSRPKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms, byte[] identity, byte[] password)
- {
- super(keyExchange, supportedSignatureAlgorithms);
-
- switch (keyExchange)
- {
- case KeyExchangeAlgorithm.SRP:
- this.tlsSigner = null;
- break;
- case KeyExchangeAlgorithm.SRP_RSA:
- this.tlsSigner = new TlsRSASigner();
- break;
- case KeyExchangeAlgorithm.SRP_DSS:
- this.tlsSigner = new TlsDSSSigner();
- break;
- default:
- throw new IllegalArgumentException("unsupported key exchange algorithm");
- }
-
- this.keyExchange = keyExchange;
- this.identity = identity;
- this.password = password;
- }
-
- public void init(TlsContext context)
- {
- super.init(context);
-
- if (this.tlsSigner != null) {
- this.tlsSigner.init(context);
- }
- }
-
- public void skipServerCredentials() throws IOException
- {
- if (tlsSigner != null)
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- }
-
- public void processServerCertificate(Certificate serverCertificate) throws IOException
- {
- if (tlsSigner == null)
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- if (serverCertificate.isEmpty())
- {
- throw new TlsFatalAlert(AlertDescription.bad_certificate);
- }
-
- org.bouncycastle.asn1.x509.Certificate x509Cert = serverCertificate.getCertificateAt(0);
-
- SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo();
- try
- {
- this.serverPublicKey = PublicKeyFactory.createKey(keyInfo);
- }
- catch (RuntimeException e)
- {
- throw new TlsFatalAlert(AlertDescription.unsupported_certificate);
- }
-
- if (!tlsSigner.isValidPublicKey(this.serverPublicKey))
- {
- throw new TlsFatalAlert(AlertDescription.certificate_unknown);
- }
-
- TlsUtils.validateKeyUsage(x509Cert, KeyUsage.digitalSignature);
-
- super.processServerCertificate(serverCertificate);
- }
-
- public boolean requiresServerKeyExchange()
- {
- return true;
- }
-
- public void processServerKeyExchange(InputStream input) throws IOException
- {
- SecurityParameters securityParameters = context.getSecurityParameters();
-
- SignerInputBuffer buf = null;
- InputStream teeIn = input;
-
- if (tlsSigner != null)
- {
- buf = new SignerInputBuffer();
- teeIn = new TeeInputStream(input, buf);
- }
-
- byte[] NBytes = TlsUtils.readOpaque16(teeIn);
- byte[] gBytes = TlsUtils.readOpaque16(teeIn);
- byte[] sBytes = TlsUtils.readOpaque8(teeIn);
- byte[] BBytes = TlsUtils.readOpaque16(teeIn);
-
- if (buf != null)
- {
- DigitallySigned signed_params = DigitallySigned.parse(context, input);
-
- Signer signer = initVerifyer(tlsSigner, signed_params.getAlgorithm(), securityParameters);
- buf.updateSigner(signer);
- if (!signer.verifySignature(signed_params.getSignature()))
- {
- throw new TlsFatalAlert(AlertDescription.decrypt_error);
- }
- }
-
- BigInteger N = new BigInteger(1, NBytes);
- BigInteger g = new BigInteger(1, gBytes);
-
- // TODO Validate group parameters (see RFC 5054)
-// throw new TlsFatalAlert(AlertDescription.insufficient_security);
-
- this.s = sBytes;
-
- /*
- * RFC 5054 2.5.3: The client MUST abort the handshake with an "illegal_parameter" alert if
- * B % N = 0.
- */
- try
- {
- this.B = SRP6Util.validatePublicValue(N, new BigInteger(1, BBytes));
- }
- catch (CryptoException e)
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- this.srpClient.init(N, g, TlsUtils.createHash(HashAlgorithm.sha1), context.getSecureRandom());
- }
-
- public void validateCertificateRequest(CertificateRequest certificateRequest) throws IOException
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
-
- public void processClientCredentials(TlsCredentials clientCredentials) throws IOException
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- public void generateClientKeyExchange(OutputStream output) throws IOException
- {
- BigInteger A = srpClient.generateClientCredentials(s, this.identity, this.password);
- TlsUtils.writeOpaque16(BigIntegers.asUnsignedByteArray(A), output);
- }
-
- public byte[] generatePremasterSecret() throws IOException
- {
- try
- {
- // TODO Check if this needs to be a fixed size
- return BigIntegers.asUnsignedByteArray(srpClient.calculateSecret(B));
- }
- catch (CryptoException e)
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- }
-
- protected Signer initVerifyer(TlsSigner tlsSigner, SignatureAndHashAlgorithm algorithm, SecurityParameters securityParameters)
- {
- 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/core/src/main/java/org/bouncycastle/crypto/tls/TlsSRPUtils.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsSRPUtils.java
deleted file mode 100644
index c1b3365e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsSRPUtils.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.ByteArrayInputStream;
-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/core/src/main/java/org/bouncycastle/crypto/tls/TlsSRTPUtils.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsSRTPUtils.java
deleted file mode 100644
index da98b7a1..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsSRTPUtils.java
+++ /dev/null
@@ -1,74 +0,0 @@
-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;
-
-/**
- * RFC 5764 DTLS Extension to Establish Keys for SRTP.
- */
-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
- {
- 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");
- }
-
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
-
- // SRTPProtectionProfiles
- TlsUtils.writeUint16ArrayWithUint16Length(useSRTPData.getProtectionProfiles(), buf);
-
- // srtp_mki
- TlsUtils.writeOpaque8(useSRTPData.getMki(), buf);
-
- return buf.toByteArray();
- }
-
- public static UseSRTPData readUseSRTPExtension(byte[] extensionData)
- throws IOException
- {
- if (extensionData == null)
- {
- throw new IllegalArgumentException("'extensionData' cannot be null");
- }
-
- ByteArrayInputStream buf = new ByteArrayInputStream(extensionData);
-
- // SRTPProtectionProfiles
- int length = TlsUtils.readUint16(buf);
- if (length < 2 || (length & 1) != 0)
- {
- throw new TlsFatalAlert(AlertDescription.decode_error);
- }
- int[] protectionProfiles = TlsUtils.readUint16Array(length / 2, buf);
-
- // srtp_mki
- byte[] mki = TlsUtils.readOpaque8(buf);
-
- TlsProtocol.assertEmpty(buf);
-
- return new UseSRTPData(protectionProfiles, mki);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsServer.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsServer.java
deleted file mode 100644
index d97c16d5..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsServer.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-import java.util.Hashtable;
-import java.util.Vector;
-
-public interface TlsServer
- extends TlsPeer
-{
- void init(TlsServerContext context);
-
- void notifyClientVersion(ProtocolVersion clientVersion) throws IOException;
-
- void notifyOfferedCipherSuites(int[] offeredCipherSuites)
- throws IOException;
-
- void notifyOfferedCompressionMethods(short[] offeredCompressionMethods)
- throws IOException;
-
- // Hashtable is (Integer -> byte[])
- void processClientExtensions(Hashtable clientExtensions)
- throws IOException;
-
- ProtocolVersion getServerVersion()
- throws IOException;
-
- int getSelectedCipherSuite()
- throws IOException;
-
- short getSelectedCompressionMethod()
- throws IOException;
-
- // Hashtable is (Integer -> byte[])
- Hashtable getServerExtensions()
- throws IOException;
-
- // Vector is (SupplementalDataEntry)
- Vector getServerSupplementalData()
- throws IOException;
-
- 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()
- throws IOException;
-
- // Vector is (SupplementalDataEntry)
- void processClientSupplementalData(Vector clientSupplementalData)
- throws IOException;
-
- /**
- * 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;
-
- /**
- * RFC 5077 3.3. NewSessionTicket Handshake Message.
- * <p>
- * This method will be called (only) if a NewSessionTicket extension was sent by the server. See
- * <i>RFC 5077 4. Recommended Ticket Construction</i> for recommended format and protection.
- *
- * @return The ticket.
- * @throws IOException
- */
- NewSessionTicket getNewSessionTicket()
- throws IOException;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsServerContext.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsServerContext.java
deleted file mode 100644
index 37a0c952..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsServerContext.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-public interface TlsServerContext
- extends TlsContext
-{
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsServerContextImpl.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsServerContextImpl.java
deleted file mode 100644
index 48f028a0..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsServerContextImpl.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.security.SecureRandom;
-
-class TlsServerContextImpl
- extends AbstractTlsContext
- implements TlsServerContext
-{
- TlsServerContextImpl(SecureRandom secureRandom, SecurityParameters securityParameters)
- {
- super(secureRandom, securityParameters);
- }
-
- public boolean isServer()
- {
- return true;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsServerProtocol.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsServerProtocol.java
deleted file mode 100644
index 8499b83e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsServerProtocol.java
+++ /dev/null
@@ -1,778 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.security.SecureRandom;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.util.PublicKeyFactory;
-import org.bouncycastle.util.Arrays;
-
-public class TlsServerProtocol
- extends TlsProtocol
-{
- protected TlsServer tlsServer = null;
- protected TlsServerContextImpl tlsServerContext = null;
-
- protected TlsKeyExchange keyExchange = null;
- protected TlsCredentials serverCredentials = null;
- protected CertificateRequest certificateRequest = null;
-
- protected short clientCertificateType = -1;
- protected TlsHandshakeHash prepareFinishHash = null;
-
- public TlsServerProtocol(InputStream input, OutputStream output, SecureRandom secureRandom)
- {
- super(input, output, secureRandom);
- }
-
- /**
- * Receives a TLS handshake in the role of server
- *
- * @param tlsServer
- * @throws IOException If handshake was not successful.
- */
- 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");
- }
-
- this.tlsServer = tlsServer;
-
- this.securityParameters = new SecurityParameters();
- this.securityParameters.entity = ConnectionEnd.server;
-
- this.tlsServerContext = new TlsServerContextImpl(secureRandom, securityParameters);
-
- this.securityParameters.serverRandom = createRandomBlock(tlsServer.shouldUseGMTUnixTime(),
- tlsServerContext.getNonceRandomGenerator());
-
- this.tlsServer.init(tlsServerContext);
- this.recordStream.init(tlsServerContext);
-
- this.recordStream.setRestrictReadVersion(false);
-
- completeHandshake();
- }
-
- protected void cleanupHandshake()
- {
- super.cleanupHandshake();
-
- this.keyExchange = null;
- this.serverCredentials = null;
- this.certificateRequest = null;
- this.prepareFinishHash = null;
- }
-
- protected AbstractTlsContext getContext()
- {
- return tlsServerContext;
- }
-
- protected TlsPeer getPeer()
- {
- return tlsServer;
- }
-
- protected void handleHandshakeMessage(short type, byte[] data)
- throws IOException
- {
- ByteArrayInputStream buf = new ByteArrayInputStream(data);
-
- switch (type)
- {
- case HandshakeType.client_hello:
- {
- switch (this.connection_state)
- {
- case CS_START:
- {
- receiveClientHelloMessage(buf);
- this.connection_state = CS_CLIENT_HELLO;
-
- sendServerHelloMessage();
- this.connection_state = CS_SERVER_HELLO;
-
- Vector serverSupplementalData = tlsServer.getServerSupplementalData();
- if (serverSupplementalData != null)
- {
- sendSupplementalDataMessage(serverSupplementalData);
- }
- this.connection_state = CS_SERVER_SUPPLEMENTAL_DATA;
-
- this.keyExchange = tlsServer.getKeyExchange();
- this.keyExchange.init(getContext());
-
- this.serverCredentials = tlsServer.getCredentials();
-
- Certificate serverCertificate = null;
-
- if (this.serverCredentials == null)
- {
- this.keyExchange.skipServerCredentials();
- }
- else
- {
- this.keyExchange.processServerCredentials(this.serverCredentials);
-
- 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)
- {
- sendServerKeyExchangeMessage(serverKeyExchange);
- }
- this.connection_state = CS_SERVER_KEY_EXCHANGE;
-
- if (this.serverCredentials != null)
- {
- this.certificateRequest = tlsServer.getCertificateRequest();
- if (this.certificateRequest != null)
- {
- this.keyExchange.validateCertificateRequest(certificateRequest);
-
- sendCertificateRequestMessage(certificateRequest);
-
- TlsUtils.trackHashAlgorithms(this.recordStream.getHandshakeHash(),
- this.certificateRequest.getSupportedSignatureAlgorithms());
- }
- }
- this.connection_state = CS_CERTIFICATE_REQUEST;
-
- sendServerHelloDoneMessage();
- this.connection_state = CS_SERVER_HELLO_DONE;
-
- this.recordStream.getHandshakeHash().sealHashAlgorithms();
-
- break;
- }
- default:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- break;
- }
- case HandshakeType.supplemental_data:
- {
- switch (this.connection_state)
- {
- case CS_SERVER_HELLO_DONE:
- {
- tlsServer.processClientSupplementalData(readSupplementalDataMessage(buf));
- this.connection_state = CS_CLIENT_SUPPLEMENTAL_DATA;
- break;
- }
- default:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- break;
- }
- case HandshakeType.certificate:
- {
- switch (this.connection_state)
- {
- case CS_SERVER_HELLO_DONE:
- {
- tlsServer.processClientSupplementalData(null);
- // NB: Fall through to next case label
- }
- case CS_CLIENT_SUPPLEMENTAL_DATA:
- {
- if (this.certificateRequest == null)
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- receiveCertificateMessage(buf);
- this.connection_state = CS_CLIENT_CERTIFICATE;
- break;
- }
- default:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- break;
- }
- case HandshakeType.client_key_exchange:
- {
- switch (this.connection_state)
- {
- case CS_SERVER_HELLO_DONE:
- {
- tlsServer.processClientSupplementalData(null);
- // NB: Fall through to next case label
- }
- case CS_CLIENT_SUPPLEMENTAL_DATA:
- {
- if (this.certificateRequest == null)
- {
- this.keyExchange.skipClientCredentials();
- }
- else
- {
- if (TlsUtils.isTLSv12(getContext()))
- {
- /*
- * RFC 5246 If no suitable certificate is available, the client MUST send a
- * certificate message containing no certificates.
- *
- * NOTE: In previous RFCs, this was SHOULD instead of MUST.
- */
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- else if (TlsUtils.isSSL(getContext()))
- {
- if (this.peerCertificate == null)
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- }
- else
- {
- notifyClientCertificate(Certificate.EMPTY_CHAIN);
- }
- }
- // NB: Fall through to next case label
- }
- case CS_CLIENT_CERTIFICATE:
- {
- receiveClientKeyExchangeMessage(buf);
- this.connection_state = CS_CLIENT_KEY_EXCHANGE;
- break;
- }
- default:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- break;
- }
- case HandshakeType.certificate_verify:
- {
- switch (this.connection_state)
- {
- case CS_CLIENT_KEY_EXCHANGE:
- {
- /*
- * 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 parameters).
- */
- if (!expectCertificateVerifyMessage())
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
-
- receiveCertificateVerifyMessage(buf);
- this.connection_state = CS_CERTIFICATE_VERIFY;
-
- break;
- }
- default:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- break;
- }
- case HandshakeType.finished:
- {
- switch (this.connection_state)
- {
- 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 (this.expectSessionTicket)
- {
- sendNewSessionTicketMessage(tlsServer.getNewSessionTicket());
- sendChangeCipherSpecMessage();
- }
- this.connection_state = CS_SERVER_SESSION_TICKET;
-
- sendFinishedMessage();
- this.connection_state = CS_SERVER_FINISHED;
- this.connection_state = CS_END;
- break;
- }
- default:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- break;
- }
- case HandshakeType.hello_request:
- case HandshakeType.hello_verify_request:
- case HandshakeType.server_hello:
- case HandshakeType.server_key_exchange:
- case HandshakeType.certificate_request:
- case HandshakeType.server_hello_done:
- case HandshakeType.session_ticket:
- default:
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- }
-
- protected void handleWarningMessage(short description)
- throws IOException
- {
- switch (description)
- {
- case AlertDescription.no_certificate:
- {
- /*
- * 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 (TlsUtils.isSSL(getContext()) && certificateRequest != null)
- {
- notifyClientCertificate(Certificate.EMPTY_CHAIN);
- }
- break;
- }
- default:
- {
- super.handleWarningMessage(description);
- }
- }
- }
-
- protected void notifyClientCertificate(Certificate clientCertificate)
- throws IOException
- {
- if (certificateRequest == null)
- {
- throw new IllegalStateException();
- }
-
- if (this.peerCertificate != null)
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
-
- this.peerCertificate = clientCertificate;
-
- if (clientCertificate.isEmpty())
- {
- this.keyExchange.skipClientCredentials();
- }
- else
- {
-
- /*
- * TODO RFC 5246 7.4.6. If the certificate_authorities list in the certificate request
- * message was non-empty, one of the certificates in the certificate chain SHOULD be
- * issued by one of the listed CAs.
- */
-
- this.clientCertificateType = TlsUtils.getClientCertificateType(clientCertificate,
- this.serverCredentials.getCertificate());
-
- this.keyExchange.processClientCertificate(clientCertificate);
- }
-
- /*
- * RFC 5246 7.4.6. If the client does not send any certificates, the server MAY at its
- * discretion either continue the handshake without client authentication, or respond with a
- * fatal handshake_failure alert. Also, if some aspect of the certificate chain was
- * unacceptable (e.g., it was not signed by a known, trusted CA), the server MAY at its
- * discretion either continue the handshake (considering the client unauthenticated) or send
- * a fatal alert.
- */
- this.tlsServer.notifyClientCertificate(clientCertificate);
- }
-
- protected void receiveCertificateMessage(ByteArrayInputStream buf)
- throws IOException
- {
- Certificate clientCertificate = Certificate.parse(buf);
-
- assertEmpty(buf);
-
- notifyClientCertificate(clientCertificate);
- }
-
- protected void receiveCertificateVerifyMessage(ByteArrayInputStream buf)
- throws IOException
- {
- DigitallySigned clientCertificateVerify = DigitallySigned.parse(getContext(), buf);
-
- assertEmpty(buf);
-
- // Verify the CertificateVerify message contains a correct signature.
- boolean verified = false;
- try
- {
- byte[] certificateVerifyHash;
- if (TlsUtils.isTLSv12(getContext()))
- {
- certificateVerifyHash = prepareFinishHash.getFinalHash(clientCertificateVerify.getAlgorithm().getHash());
- }
- else
- {
- certificateVerifyHash = TlsProtocol.getCurrentPRFHash(getContext(), prepareFinishHash, null);
- }
-
- org.bouncycastle.asn1.x509.Certificate x509Cert = this.peerCertificate.getCertificateAt(0);
- SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo();
- AsymmetricKeyParameter publicKey = PublicKeyFactory.createKey(keyInfo);
-
- TlsSigner tlsSigner = TlsUtils.createTlsSigner(this.clientCertificateType);
- tlsSigner.init(getContext());
- verified = tlsSigner.verifyRawSignature(clientCertificateVerify.getAlgorithm(),
- clientCertificateVerify.getSignature(), publicKey, certificateVerifyHash);
- }
- catch (Exception e)
- {
- }
-
- if (!verified)
- {
- throw new TlsFatalAlert(AlertDescription.decrypt_error);
- }
- }
-
- protected void receiveClientHelloMessage(ByteArrayInputStream buf)
- throws IOException
- {
- ProtocolVersion client_version = TlsUtils.readVersion(buf);
- if (client_version.isDTLS())
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- 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)
- {
- 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)
- {
- throw new TlsFatalAlert(AlertDescription.decode_error);
- }
- this.offeredCipherSuites = TlsUtils.readUint16Array(cipher_suites_length / 2, buf);
-
- /*
- * 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.
- */
- int compression_methods_length = TlsUtils.readUint8(buf);
- if (compression_methods_length < 1)
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- this.offeredCompressionMethods = TlsUtils.readUint8Array(compression_methods_length, buf);
-
- /*
- * 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.
- */
- this.clientExtensions = readExtensions(buf);
-
- getContext().setClientVersion(client_version);
-
- tlsServer.notifyClientVersion(client_version);
-
- securityParameters.clientRandom = client_random;
-
- tlsServer.notifyOfferedCipherSuites(offeredCipherSuites);
- tlsServer.notifyOfferedCompressionMethods(offeredCompressionMethods);
-
- /*
- * RFC 5746 3.6. Server Behavior: Initial Handshake
- */
- {
- /*
- * RFC 5746 3.4. The client MUST include either an empty "renegotiation_info" extension,
- * or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling cipher suite value in the
- * ClientHello. Including both is NOT RECOMMENDED.
- */
-
- /*
- * When a ClientHello is received, the server MUST check if it includes the
- * TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. If it does, set the secure_renegotiation flag
- * to TRUE.
- */
- if (Arrays.contains(offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV))
- {
- this.secure_renegotiation = true;
- }
-
- /*
- * The server MUST check if the "renegotiation_info" extension is included in the
- * ClientHello.
- */
- byte[] renegExtData = TlsUtils.getExtensionData(clientExtensions, EXT_RenegotiationInfo);
- if (renegExtData != 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)))
- {
- throw new TlsFatalAlert(AlertDescription.handshake_failure);
- }
- }
- }
-
- tlsServer.notifySecureRenegotiation(this.secure_renegotiation);
-
- if (clientExtensions != null)
- {
- tlsServer.processClientExtensions(clientExtensions);
- }
- }
-
- protected void receiveClientKeyExchangeMessage(ByteArrayInputStream buf)
- throws IOException
- {
- this.keyExchange.processClientKeyExchange(buf);
-
- assertEmpty(buf);
-
- establishMasterSecret(getContext(), keyExchange);
- recordStream.setPendingConnectionState(getPeer().getCompression(), getPeer().getCipher());
-
- this.prepareFinishHash = recordStream.prepareToFinish();
-
- if (!expectSessionTicket)
- {
- sendChangeCipherSpecMessage();
- }
- }
-
- protected void sendCertificateRequestMessage(CertificateRequest certificateRequest)
- throws IOException
- {
- HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate_request);
-
- certificateRequest.encode(message);
-
- message.writeToRecordStream();
- }
-
- protected void sendCertificateStatusMessage(CertificateStatus certificateStatus)
- throws IOException
- {
- HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate_status);
-
- certificateStatus.encode(message);
-
- message.writeToRecordStream();
- }
-
- protected void sendNewSessionTicketMessage(NewSessionTicket newSessionTicket)
- throws IOException
- {
- if (newSessionTicket == null)
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- HandshakeMessage message = new HandshakeMessage(HandshakeType.session_ticket);
-
- newSessionTicket.encode(message);
-
- message.writeToRecordStream();
- }
-
- protected void sendServerHelloMessage()
- throws IOException
- {
- HandshakeMessage message = new HandshakeMessage(HandshakeType.server_hello);
-
- ProtocolVersion server_version = tlsServer.getServerVersion();
- if (!server_version.isEqualOrEarlierVersionOf(getContext().getClientVersion()))
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- recordStream.setReadVersion(server_version);
- recordStream.setWriteVersion(server_version);
- recordStream.setRestrictReadVersion(true);
- getContext().setServerVersion(server_version);
-
- TlsUtils.writeVersion(server_version, message);
-
- 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, message);
-
- int selectedCipherSuite = tlsServer.getSelectedCipherSuite();
- if (!Arrays.contains(this.offeredCipherSuites, selectedCipherSuite)
- || selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL
- || selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV
- || !TlsUtils.isValidCipherSuiteForVersion(selectedCipherSuite, server_version))
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- securityParameters.cipherSuite = selectedCipherSuite;
-
- short selectedCompressionMethod = tlsServer.getSelectedCompressionMethod();
- if (!Arrays.contains(this.offeredCompressionMethods, selectedCompressionMethod))
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- securityParameters.compressionAlgorithm = selectedCompressionMethod;
-
- TlsUtils.writeUint16(selectedCipherSuite, message);
- TlsUtils.writeUint8(selectedCompressionMethod, message);
-
- this.serverExtensions = tlsServer.getServerExtensions();
-
- /*
- * RFC 5746 3.6. Server Behavior: Initial Handshake
- */
- if (this.secure_renegotiation)
- {
- byte[] renegExtData = TlsUtils.getExtensionData(this.serverExtensions, EXT_RenegotiationInfo);
- boolean noRenegExt = (null == renegExtData);
-
- if (noRenegExt)
- {
- /*
- * Note that sending a "renegotiation_info" extension in response to a ClientHello
- * containing only the SCSV is an explicit exception to the prohibition in RFC 5246,
- * Section 7.4.1.4, on the server sending unsolicited extensions and is only allowed
- * because the client is signaling its willingness to receive the extension via the
- * TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV.
- */
-
- /*
- * 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.securityParameters.encryptThenMAC = TlsExtensionsUtils.hasEncryptThenMACExtension(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);
- }
-
- securityParameters.prfAlgorithm = getPRFAlgorithm(getContext(), 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;
-
- 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);
-
- writeHandshakeMessage(message, 0, message.length);
- }
-
- protected void sendServerKeyExchangeMessage(byte[] serverKeyExchange)
- throws IOException
- {
- HandshakeMessage message = new HandshakeMessage(HandshakeType.server_key_exchange, serverKeyExchange.length);
-
- message.write(serverKeyExchange);
-
- message.writeToRecordStream();
- }
-
- protected boolean expectCertificateVerifyMessage()
- {
- return this.clientCertificateType >= 0 && TlsUtils.hasSigningCapability(this.clientCertificateType);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsSession.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsSession.java
deleted file mode 100644
index 9b5ad460..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsSession.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-public interface TlsSession
-{
- SessionParameters exportSessionParameters();
-
- byte[] getSessionID();
-
- void invalidate();
-
- boolean isResumable();
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsSessionImpl.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsSessionImpl.java
deleted file mode 100644
index 615c4424..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsSessionImpl.java
+++ /dev/null
@@ -1,48 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/tls/TlsSigner.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsSigner.java
deleted file mode 100644
index 68826d2a..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsSigner.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.Signer;
-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/core/src/main/java/org/bouncycastle/crypto/tls/TlsSignerCredentials.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsSignerCredentials.java
deleted file mode 100644
index 39ee99c0..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsSignerCredentials.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-public interface TlsSignerCredentials
- extends TlsCredentials
-{
- byte[] generateCertificateSignature(byte[] hash)
- throws IOException;
-
- SignatureAndHashAlgorithm getSignatureAndHashAlgorithm();
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsStreamCipher.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsStreamCipher.java
deleted file mode 100644
index f8077aa6..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsStreamCipher.java
+++ /dev/null
@@ -1,178 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.StreamCipher;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Arrays;
-
-public class TlsStreamCipher
- implements TlsCipher
-{
- protected TlsContext context;
-
- protected StreamCipher encryptCipher;
- protected StreamCipher decryptCipher;
-
- protected TlsMac writeMac;
- protected TlsMac readMac;
-
- protected boolean usesNonce;
-
- /**
- * @deprecated Use version with additional 'usesNonce' argument
- */
- public TlsStreamCipher(TlsContext context, StreamCipher clientWriteCipher,
- StreamCipher serverWriteCipher, Digest clientWriteDigest, Digest serverWriteDigest,
- int cipherKeySize) throws IOException
- {
- this(context, clientWriteCipher, serverWriteCipher, clientWriteDigest, serverWriteDigest, cipherKeySize, false);
- }
-
- public TlsStreamCipher(TlsContext context, StreamCipher clientWriteCipher,
- StreamCipher serverWriteCipher, Digest clientWriteDigest, Digest serverWriteDigest,
- int cipherKeySize, boolean usesNonce) throws IOException
- {
- boolean isServer = context.isServer();
-
- this.context = context;
- this.usesNonce = usesNonce;
-
- this.encryptCipher = clientWriteCipher;
- this.decryptCipher = serverWriteCipher;
-
- int key_block_size = (2 * cipherKeySize) + clientWriteDigest.getDigestSize()
- + serverWriteDigest.getDigestSize();
-
- byte[] key_block = TlsUtils.calculateKeyBlock(context, key_block_size);
-
- int offset = 0;
-
- // Init MACs
- TlsMac clientWriteMac = new TlsMac(context, clientWriteDigest, key_block, offset,
- clientWriteDigest.getDigestSize());
- offset += clientWriteDigest.getDigestSize();
- TlsMac serverWriteMac = new TlsMac(context, serverWriteDigest, key_block, offset,
- serverWriteDigest.getDigestSize());
- offset += serverWriteDigest.getDigestSize();
-
- // Build keys
- KeyParameter clientWriteKey = new KeyParameter(key_block, offset, cipherKeySize);
- offset += cipherKeySize;
- KeyParameter serverWriteKey = new KeyParameter(key_block, offset, cipherKeySize);
- offset += cipherKeySize;
-
- if (offset != key_block_size)
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- CipherParameters encryptParams, decryptParams;
- if (isServer)
- {
- this.writeMac = serverWriteMac;
- this.readMac = clientWriteMac;
- this.encryptCipher = serverWriteCipher;
- this.decryptCipher = clientWriteCipher;
- encryptParams = serverWriteKey;
- decryptParams = clientWriteKey;
- }
- else
- {
- this.writeMac = clientWriteMac;
- this.readMac = serverWriteMac;
- this.encryptCipher = clientWriteCipher;
- this.decryptCipher = serverWriteCipher;
- encryptParams = clientWriteKey;
- decryptParams = serverWriteKey;
- }
-
- if (usesNonce)
- {
- byte[] dummyNonce = new byte[8];
- encryptParams = new ParametersWithIV(encryptParams, dummyNonce);
- decryptParams = new ParametersWithIV(decryptParams, dummyNonce);
- }
-
- this.encryptCipher.init(true, encryptParams);
- this.decryptCipher.init(false, decryptParams);
- }
-
- public int getPlaintextLimit(int ciphertextLimit)
- {
- return ciphertextLimit - writeMac.getSize();
- }
-
- public byte[] encodePlaintext(long seqNo, short type, byte[] plaintext, int offset, int len)
- {
- /*
- * draft-josefsson-salsa20-tls-04 2.1 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.
- */
- if (usesNonce)
- {
- updateIV(encryptCipher, true, seqNo);
- }
-
- byte[] outBuf = new byte[len + writeMac.getSize()];
-
- encryptCipher.processBytes(plaintext, offset, len, outBuf, 0);
-
- byte[] mac = writeMac.calculateMac(seqNo, type, plaintext, offset, len);
- encryptCipher.processBytes(mac, 0, mac.length, outBuf, len);
-
- return outBuf;
- }
-
- public byte[] decodeCiphertext(long seqNo, short type, byte[] ciphertext, int offset, int len)
- throws IOException
- {
- /*
- * draft-josefsson-salsa20-tls-04 2.1 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.
- */
- if (usesNonce)
- {
- updateIV(decryptCipher, false, seqNo);
- }
-
- int macSize = readMac.getSize();
- if (len < macSize)
- {
- throw new TlsFatalAlert(AlertDescription.decode_error);
- }
-
- int plaintextLength = len - macSize;
-
- 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);
- }
-
- 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);
- }
- }
-
- private void updateIV(StreamCipher cipher, boolean forEncryption, long seqNo)
- {
- byte[] nonce = new byte[8];
- TlsUtils.writeUint64(seqNo, nonce, 0);
- cipher.init(forEncryption, new ParametersWithIV(null, nonce));
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsUtils.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsUtils.java
deleted file mode 100644
index 7986647f..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsUtils.java
+++ /dev/null
@@ -1,1780 +0,0 @@
-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;
-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;
-import org.bouncycastle.asn1.x509.KeyUsage;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.MD5Digest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.SHA224Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.digests.SHA384Digest;
-import org.bouncycastle.crypto.digests.SHA512Digest;
-import org.bouncycastle.crypto.macs.HMac;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.util.PublicKeyFactory;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Integers;
-import org.bouncycastle.util.Strings;
-import org.bouncycastle.util.io.Streams;
-
-/**
- * Some helper functions for MicroTLS.
- */
-public class TlsUtils
-{
- public static final byte[] EMPTY_BYTES = new byte[0];
-
- 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 checkUint8(long 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 checkUint16(long 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 checkUint24(long 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 isValidUint8(long i)
- {
- return (i & 0xFFL) == i;
- }
-
- public static boolean isValidUint16(int i)
- {
- return (i & 0xFFFF) == i;
- }
-
- public static boolean isValidUint16(long i)
- {
- return (i & 0xFFFFL) == i;
- }
-
- public static boolean isValidUint24(int i)
- {
- return (i & 0xFFFFFF) == i;
- }
-
- public static boolean isValidUint24(long i)
- {
- return (i & 0xFFFFFFL) == i;
- }
-
- public static boolean isValidUint32(long i)
- {
- return (i & 0xFFFFFFFFL) == i;
- }
-
- public static boolean isValidUint48(long i)
- {
- return (i & 0xFFFFFFFFFFFFL) == i;
- }
-
- public static boolean isValidUint64(long i)
- {
- 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
- {
- output.write(i >>> 8);
- output.write(i);
- }
-
- public static void writeUint16(int i, byte[] buf, int offset)
- {
- buf[offset] = (byte)(i >>> 8);
- buf[offset + 1] = (byte)i;
- }
-
- public static void writeUint24(int i, OutputStream output)
- throws IOException
- {
- output.write((byte)(i >>> 16));
- output.write((byte)(i >>> 8));
- output.write((byte)i);
- }
-
- public static void writeUint24(int i, byte[] buf, int offset)
- {
- buf[offset] = (byte)(i >>> 16);
- buf[offset + 1] = (byte)(i >>> 8);
- buf[offset + 2] = (byte)i;
- }
-
- public static void writeUint32(long i, OutputStream output)
- throws IOException
- {
- output.write((byte)(i >>> 24));
- output.write((byte)(i >>> 16));
- output.write((byte)(i >>> 8));
- output.write((byte)i);
- }
-
- public static void writeUint32(long i, byte[] buf, int offset)
- {
- buf[offset] = (byte)(i >>> 24);
- buf[offset + 1] = (byte)(i >>> 16);
- buf[offset + 2] = (byte)(i >>> 8);
- 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);
- buf[offset + 1] = (byte)(i >>> 32);
- buf[offset + 2] = (byte)(i >>> 24);
- buf[offset + 3] = (byte)(i >>> 16);
- buf[offset + 4] = (byte)(i >>> 8);
- buf[offset + 5] = (byte)i;
- }
-
- public static void writeUint64(long i, OutputStream output)
- throws IOException
- {
- 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)
- {
- buf[offset] = (byte)(i >>> 56);
- buf[offset + 1] = (byte)(i >>> 48);
- buf[offset + 2] = (byte)(i >>> 40);
- buf[offset + 3] = (byte)(i >>> 32);
- buf[offset + 4] = (byte)(i >>> 24);
- buf[offset + 5] = (byte)(i >>> 16);
- buf[offset + 6] = (byte)(i >>> 8);
- buf[offset + 7] = (byte)i;
- }
-
- public static void writeOpaque8(byte[] buf, OutputStream output)
- throws IOException
- {
- 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);
- }
-
- public static void writeOpaque24(byte[] buf, OutputStream output)
- throws IOException
- {
- checkUint24(buf.length);
- writeUint24(buf.length, output);
- output.write(buf);
- }
-
- public static void writeUint8Array(short[] uints, OutputStream output)
- throws IOException
- {
- for (int i = 0; i < uints.length; ++i)
- {
- writeUint8(uints[i], output);
- }
- }
-
- 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
- {
- for (int i = 0; i < uints.length; ++i)
- {
- writeUint16(uints[i], output);
- }
- }
-
- 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
- {
- int i = input.read();
- if (i < 0)
- {
- throw new EOFException();
- }
- return (short)i;
- }
-
- public static short readUint8(byte[] buf, int offset)
- {
- return (short)buf[offset];
- }
-
- public static int readUint16(InputStream input)
- throws IOException
- {
- int i1 = input.read();
- int i2 = input.read();
- if (i2 < 0)
- {
- throw new EOFException();
- }
- return i1 << 8 | i2;
- }
-
- public static int readUint16(byte[] buf, int offset)
- {
- int n = (buf[offset] & 0xff) << 8;
- n |= (buf[++offset] & 0xff);
- return n;
- }
-
- public static int readUint24(InputStream input)
- throws IOException
- {
- int i1 = input.read();
- int i2 = input.read();
- int i3 = input.read();
- if (i3 < 0)
- {
- throw new EOFException();
- }
- return (i1 << 16) | (i2 << 8) | i3;
- }
-
- public static int readUint24(byte[] buf, int offset)
- {
- int n = (buf[offset] & 0xff) << 16;
- n |= (buf[++offset] & 0xff) << 8;
- n |= (buf[++offset] & 0xff);
- return n;
- }
-
- public static long readUint32(InputStream input)
- throws IOException
- {
- int i1 = input.read();
- int i2 = input.read();
- int i3 = input.read();
- int i4 = input.read();
- if (i4 < 0)
- {
- throw new EOFException();
- }
- return ((i1 << 2) | (i2 << 16) | (i3 << 8) | i4) & 0xFFFFFFFFL;
- }
-
- public static long readUint32(byte[] buf, int offset)
- {
- int n = (buf[offset] & 0xff) << 24;
- n |= (buf[++offset] & 0xff) << 16;
- n |= (buf[++offset] & 0xff) << 8;
- n |= (buf[++offset] & 0xff);
- return n & 0xFFFFFFFFL;
- }
-
- public static long readUint48(InputStream input)
- throws IOException
- {
- int hi = readUint24(input);
- int lo = readUint24(input);
- return ((long)(hi & 0xffffffffL) << 24) | (long)(lo & 0xffffffffL);
- }
-
- public static long readUint48(byte[] buf, int offset)
- {
- int hi = readUint24(buf, offset);
- int lo = readUint24(buf, offset + 3);
- 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
- {
- if (length < 1)
- {
- return EMPTY_BYTES;
- }
- byte[] buf = new byte[length];
- if (length != Streams.readFully(input, buf))
- {
- throw new EOFException();
- }
- return buf;
- }
-
- public static void readFully(byte[] buf, InputStream input)
- throws IOException
- {
- int length = buf.length;
- if (length > 0 && length != Streams.readFully(input, buf))
- {
- throw new EOFException();
- }
- }
-
- public static byte[] readOpaque8(InputStream input)
- throws IOException
- {
- short length = readUint8(input);
- return readFully(length, input);
- }
-
- public static byte[] readOpaque16(InputStream input)
- throws IOException
- {
- int length = readUint16(input);
- return readFully(length, input);
- }
-
- public static byte[] readOpaque24(InputStream input)
- throws IOException
- {
- int length = readUint24(input);
- return readFully(length, input);
- }
-
- public static short[] readUint8Array(int count, InputStream input)
- throws IOException
- {
- short[] uints = new short[count];
- for (int i = 0; i < count; ++i)
- {
- uints[i] = readUint8(input);
- }
- return uints;
- }
-
- public static int[] readUint16Array(int count, InputStream input)
- throws IOException
- {
- int[] uints = new int[count];
- for (int i = 0; i < count; ++i)
- {
- uints[i] = readUint16(input);
- }
- return uints;
- }
-
- public static ProtocolVersion readVersion(byte[] buf, int offset)
- throws IOException
- {
- return ProtocolVersion.get(buf[offset] & 0xFF, buf[offset + 1] & 0xFF);
- }
-
- public static ProtocolVersion readVersion(InputStream input)
- throws IOException
- {
- int i1 = input.read();
- int i2 = input.read();
- if (i2 < 0)
- {
- throw new EOFException();
- }
- 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
- {
- int i1 = input.read();
- int i2 = input.read();
- if (i2 < 0)
- {
- throw new EOFException();
- }
- 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);
- buf[offset] = (byte)(t >>> 24);
- buf[offset + 1] = (byte)(t >>> 16);
- buf[offset + 2] = (byte)(t >>> 8);
- buf[offset + 3] = (byte)t;
- }
-
- public static void writeVersion(ProtocolVersion version, OutputStream output)
- throws IOException
- {
- output.write(version.getMajorVersion());
- output.write(version.getMinorVersion());
- }
-
- public static void writeVersion(ProtocolVersion version, byte[] buf, int offset)
- {
- buf[offset] = (byte)version.getMajorVersion();
- buf[offset + 1] = (byte)version.getMinorVersion();
- }
-
- public static Vector getDefaultDSSSignatureAlgorithms()
- {
- return vectorOfOne(new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.dsa));
- }
-
- public static Vector getDefaultECDSASignatureAlgorithms()
- {
- return vectorOfOne(new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.ecdsa));
- }
-
- public static Vector getDefaultRSASignatureAlgorithms()
- {
- 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());
- }
-
- /**
- * Add a 'signature_algorithms' extension to existing extensions.
- *
- * @param extensions A {@link Hashtable} to add the extension to.
- * @param supportedSignatureAlgorithms {@link Vector} containing at least 1 {@link SignatureAndHashAlgorithm}.
- * @throws IOException
- */
- public static void addSignatureAlgorithmsExtension(Hashtable extensions, Vector supportedSignatureAlgorithms)
- throws IOException
- {
- extensions.put(EXT_signature_algorithms, createSignatureAlgorithmsExtension(supportedSignatureAlgorithms));
- }
-
- /**
- * Get a 'signature_algorithms' extension from extensions.
- *
- * @param extensions A {@link Hashtable} to get the extension from, if it is present.
- * @return A {@link Vector} containing at least 1 {@link SignatureAndHashAlgorithm}, or null.
- * @throws IOException
- */
- public static Vector getSignatureAlgorithmsExtension(Hashtable extensions)
- throws IOException
- {
- byte[] extensionData = getExtensionData(extensions, EXT_signature_algorithms);
- return extensionData == null ? null : readSignatureAlgorithmsExtension(extensionData);
- }
-
- /**
- * Create a 'signature_algorithms' extension value.
- *
- * @param supportedSignatureAlgorithms A {@link Vector} containing at least 1 {@link SignatureAndHashAlgorithm}.
- * @return A byte array suitable for use as an extension value.
- * @throws IOException
- */
- public static byte[] createSignatureAlgorithmsExtension(Vector supportedSignatureAlgorithms)
- throws IOException
- {
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
-
- // supported_signature_algorithms
- encodeSupportedSignatureAlgorithms(supportedSignatureAlgorithms, false, buf);
-
- return buf.toByteArray();
- }
-
- /**
- * Read 'signature_algorithms' extension data.
- *
- * @param extensionData The extension data.
- * @return A {@link Vector} containing at least 1 {@link SignatureAndHashAlgorithm}.
- * @throws IOException
- */
- public static Vector readSignatureAlgorithmsExtension(byte[] extensionData)
- throws IOException
- {
- if (extensionData == null)
- {
- throw new IllegalArgumentException("'extensionData' cannot be null");
- }
-
- ByteArrayInputStream buf = new ByteArrayInputStream(extensionData);
-
- // 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(
- "'supportedSignatureAlgorithms' must have length from 1 to (2^15 - 1)");
- }
-
- // 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(input);
- if (length < 2 || (length & 1) != 0)
- {
- throw new TlsFatalAlert(AlertDescription.decode_error);
- }
- int count = length / 2;
- Vector supportedSignatureAlgorithms = new Vector(count);
- for (int i = 0; i < count; ++i)
- {
- 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);
- }
- return supportedSignatureAlgorithms;
- }
-
- public static byte[] PRF(TlsContext context, byte[] secret, String asciiLabel, byte[] seed, int size)
- {
- ProtocolVersion version = context.getServerVersion();
-
- if (version.isSSL())
- {
- throw new IllegalStateException("No PRF available for SSLv3 session");
- }
-
- byte[] label = Strings.toByteArray(asciiLabel);
- byte[] labelSeed = concat(label, seed);
-
- int prfAlgorithm = context.getSecurityParameters().getPrfAlgorithm();
-
- if (prfAlgorithm == PRFAlgorithm.tls_prf_legacy)
- {
- return PRF_legacy(secret, label, labelSeed, size);
- }
-
- Digest prfDigest = createPRFHash(prfAlgorithm);
- byte[] buf = new byte[size];
- hmac_hash(prfDigest, secret, labelSeed, buf);
- return buf;
- }
-
- public static byte[] PRF_legacy(byte[] secret, String asciiLabel, byte[] seed, int size)
- {
- byte[] label = Strings.toByteArray(asciiLabel);
- byte[] labelSeed = concat(label, seed);
-
- return PRF_legacy(secret, label, labelSeed, size);
- }
-
- static byte[] PRF_legacy(byte[] secret, byte[] label, byte[] labelSeed, int size)
- {
- int s_half = (secret.length + 1) / 2;
- byte[] s1 = new byte[s_half];
- byte[] s2 = new byte[s_half];
- System.arraycopy(secret, 0, s1, 0, s_half);
- System.arraycopy(secret, secret.length - s_half, s2, 0, s_half);
-
- byte[] b1 = new byte[size];
- byte[] b2 = new byte[size];
- hmac_hash(createHash(HashAlgorithm.md5), s1, labelSeed, b1);
- hmac_hash(createHash(HashAlgorithm.sha1), s2, labelSeed, b2);
- for (int i = 0; i < size; i++)
- {
- b1[i] ^= b2[i];
- }
- return b1;
- }
-
- static byte[] concat(byte[] a, byte[] b)
- {
- byte[] c = new byte[a.length + b.length];
- System.arraycopy(a, 0, c, 0, a.length);
- System.arraycopy(b, 0, c, a.length, b.length);
- return c;
- }
-
- static void hmac_hash(Digest digest, byte[] secret, byte[] seed, byte[] out)
- {
- HMac mac = new HMac(digest);
- mac.init(new KeyParameter(secret));
- byte[] a = seed;
- int size = digest.getDigestSize();
- int iterations = (out.length + size - 1) / size;
- byte[] buf = new byte[mac.getMacSize()];
- byte[] buf2 = new byte[mac.getMacSize()];
- for (int i = 0; i < iterations; i++)
- {
- mac.update(a, 0, a.length);
- mac.doFinal(buf, 0);
- a = buf;
- mac.update(a, 0, a.length);
- mac.update(seed, 0, seed.length);
- mac.doFinal(buf2, 0);
- System.arraycopy(buf2, 0, out, (size * i), Math.min(size, out.length - (size * i)));
- }
- }
-
- static void validateKeyUsage(org.bouncycastle.asn1.x509.Certificate c, int keyUsageBits)
- throws IOException
- {
- Extensions exts = c.getTBSCertificate().getExtensions();
- if (exts != null)
- {
- KeyUsage ku = KeyUsage.fromExtensions(exts);
- if (ku != null)
- {
- int bits = ku.getBytes()[0] & 0xff;
- if ((bits & keyUsageBits) != keyUsageBits)
- {
- throw new TlsFatalAlert(AlertDescription.certificate_unknown);
- }
- }
- }
- }
-
- static byte[] calculateKeyBlock(TlsContext context, int size)
- {
- SecurityParameters securityParameters = context.getSecurityParameters();
- byte[] master_secret = securityParameters.getMasterSecret();
- byte[] seed = concat(securityParameters.getServerRandom(),
- securityParameters.getClientRandom());
-
- if (isSSL(context))
- {
- return calculateKeyBlock_SSL(master_secret, seed, size);
- }
-
- return PRF(context, master_secret, ExporterLabel.key_expansion, seed, size);
- }
-
- static byte[] calculateKeyBlock_SSL(byte[] master_secret, byte[] random, int size)
- {
- Digest md5 = createHash(HashAlgorithm.md5);
- Digest sha1 = createHash(HashAlgorithm.sha1);
- int md5Size = md5.getDigestSize();
- byte[] shatmp = new byte[sha1.getDigestSize()];
- byte[] tmp = new byte[size + md5Size];
-
- int i = 0, pos = 0;
- while (pos < size)
- {
- byte[] ssl3Const = SSL3_CONST[i];
-
- sha1.update(ssl3Const, 0, ssl3Const.length);
- sha1.update(master_secret, 0, master_secret.length);
- sha1.update(random, 0, random.length);
- sha1.doFinal(shatmp, 0);
-
- md5.update(master_secret, 0, master_secret.length);
- md5.update(shatmp, 0, shatmp.length);
- md5.doFinal(tmp, pos);
-
- pos += md5Size;
- ++i;
- }
-
- byte rval[] = new byte[size];
- System.arraycopy(tmp, 0, rval, 0, size);
- return rval;
- }
-
- static byte[] calculateMasterSecret(TlsContext context, byte[] pre_master_secret)
- {
- SecurityParameters securityParameters = context.getSecurityParameters();
- byte[] seed = concat(securityParameters.getClientRandom(), securityParameters.getServerRandom());
-
- if (isSSL(context))
- {
- return calculateMasterSecret_SSL(pre_master_secret, seed);
- }
-
- return PRF(context, pre_master_secret, ExporterLabel.master_secret, seed, 48);
- }
-
- static byte[] calculateMasterSecret_SSL(byte[] pre_master_secret, byte[] random)
- {
- Digest md5 = createHash(HashAlgorithm.md5);
- Digest sha1 = createHash(HashAlgorithm.sha1);
- int md5Size = md5.getDigestSize();
- byte[] shatmp = new byte[sha1.getDigestSize()];
-
- byte[] rval = new byte[md5Size * 3];
- int pos = 0;
-
- for (int i = 0; i < 3; ++i)
- {
- byte[] ssl3Const = SSL3_CONST[i];
-
- sha1.update(ssl3Const, 0, ssl3Const.length);
- sha1.update(pre_master_secret, 0, pre_master_secret.length);
- sha1.update(random, 0, random.length);
- sha1.doFinal(shatmp, 0);
-
- md5.update(pre_master_secret, 0, pre_master_secret.length);
- md5.update(shatmp, 0, shatmp.length);
- md5.doFinal(rval, pos);
-
- pos += md5Size;
- }
-
- return rval;
- }
-
- static byte[] calculateVerifyData(TlsContext context, String asciiLabel, byte[] handshakeHash)
- {
- if (isSSL(context))
- {
- return handshakeHash;
- }
-
- SecurityParameters securityParameters = context.getSecurityParameters();
- byte[] master_secret = securityParameters.getMasterSecret();
- int verify_data_length = securityParameters.getVerifyDataLength();
-
- return PRF(context, master_secret, asciiLabel, handshakeHash, verify_data_length);
- }
-
- public static Digest createHash(short hashAlgorithm)
- {
- switch (hashAlgorithm)
- {
- case HashAlgorithm.md5:
- return new MD5Digest();
- case HashAlgorithm.sha1:
- return new SHA1Digest();
- case HashAlgorithm.sha224:
- return new SHA224Digest();
- case HashAlgorithm.sha256:
- return new SHA256Digest();
- case HashAlgorithm.sha384:
- return new SHA384Digest();
- case HashAlgorithm.sha512:
- return new SHA512Digest();
- default:
- throw new IllegalArgumentException("unknown HashAlgorithm");
- }
- }
-
- public static Digest cloneHash(short hashAlgorithm, Digest hash)
- {
- switch (hashAlgorithm)
- {
- case HashAlgorithm.md5:
- return new MD5Digest((MD5Digest)hash);
- case HashAlgorithm.sha1:
- return new SHA1Digest((SHA1Digest)hash);
- case HashAlgorithm.sha224:
- return new SHA224Digest((SHA224Digest)hash);
- case HashAlgorithm.sha256:
- return new SHA256Digest((SHA256Digest)hash);
- case HashAlgorithm.sha384:
- return new SHA384Digest((SHA384Digest)hash);
- case HashAlgorithm.sha512:
- return new SHA512Digest((SHA512Digest)hash);
- default:
- throw new IllegalArgumentException("unknown HashAlgorithm");
- }
- }
-
- public static Digest createPRFHash(int prfAlgorithm)
- {
- switch (prfAlgorithm)
- {
- case PRFAlgorithm.tls_prf_legacy:
- return new CombinedHash();
- default:
- return createHash(getHashAlgorithmForPRFAlgorithm(prfAlgorithm));
- }
- }
-
- public static Digest clonePRFHash(int prfAlgorithm, Digest hash)
- {
- switch (prfAlgorithm)
- {
- case PRFAlgorithm.tls_prf_legacy:
- return new CombinedHash((CombinedHash)hash);
- default:
- return cloneHash(getHashAlgorithmForPRFAlgorithm(prfAlgorithm), hash);
- }
- }
-
- public static short getHashAlgorithmForPRFAlgorithm(int prfAlgorithm)
- {
- switch (prfAlgorithm)
- {
- case PRFAlgorithm.tls_prf_legacy:
- throw new IllegalArgumentException("legacy PRF not a valid algorithm");
- case PRFAlgorithm.tls_prf_sha256:
- return HashAlgorithm.sha256;
- case PRFAlgorithm.tls_prf_sha384:
- return HashAlgorithm.sha384;
- default:
- throw new IllegalArgumentException("unknown PRFAlgorithm");
- }
- }
-
- public static ASN1ObjectIdentifier getOIDForHashAlgorithm(short hashAlgorithm)
- {
- switch (hashAlgorithm)
- {
- case HashAlgorithm.md5:
- return PKCSObjectIdentifiers.md5;
- case HashAlgorithm.sha1:
- return X509ObjectIdentifiers.id_SHA1;
- case HashAlgorithm.sha224:
- return NISTObjectIdentifiers.id_sha224;
- case HashAlgorithm.sha256:
- return NISTObjectIdentifiers.id_sha256;
- case HashAlgorithm.sha384:
- return NISTObjectIdentifiers.id_sha384;
- case HashAlgorithm.sha512:
- return NISTObjectIdentifiers.id_sha512;
- default:
- throw new IllegalArgumentException("unknown HashAlgorithm");
- }
- }
-
- static short getClientCertificateType(Certificate clientCertificate, Certificate serverCertificate)
- throws IOException
- {
- if (clientCertificate.isEmpty())
- {
- return -1;
- }
-
- org.bouncycastle.asn1.x509.Certificate x509Cert = clientCertificate.getCertificateAt(0);
- SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo();
- try
- {
- AsymmetricKeyParameter publicKey = PublicKeyFactory.createKey(keyInfo);
- if (publicKey.isPrivate())
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- /*
- * TODO RFC 5246 7.4.6. The certificates MUST be signed using an acceptable hash/
- * signature algorithm pair, as described in Section 7.4.4. Note that this relaxes the
- * constraints on certificate-signing algorithms found in prior versions of TLS.
- */
-
- /*
- * RFC 5246 7.4.6. Client Certificate
- */
-
- /*
- * RSA public key; the certificate MUST allow the key to be used for signing with the
- * signature scheme and hash algorithm that will be employed in the certificate verify
- * message.
- */
- if (publicKey instanceof RSAKeyParameters)
- {
- validateKeyUsage(x509Cert, KeyUsage.digitalSignature);
- return ClientCertificateType.rsa_sign;
- }
-
- /*
- * DSA public key; the certificate MUST allow the key to be used for signing with the
- * hash algorithm that will be employed in the certificate verify message.
- */
- if (publicKey instanceof DSAPublicKeyParameters)
- {
- validateKeyUsage(x509Cert, KeyUsage.digitalSignature);
- return ClientCertificateType.dss_sign;
- }
-
- /*
- * ECDSA-capable public key; the certificate MUST allow the key to be used for signing
- * with the hash algorithm that will be employed in the certificate verify message; the
- * public key MUST use a curve and point format supported by the server.
- */
- if (publicKey instanceof ECPublicKeyParameters)
- {
- validateKeyUsage(x509Cert, KeyUsage.digitalSignature);
- // TODO Check the curve and point format
- return ClientCertificateType.ecdsa_sign;
- }
-
- // TODO Add support for ClientCertificateType.*_fixed_*
-
- }
- catch (Exception e)
- {
- }
-
- 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)
- {
- case ClientCertificateType.dss_sign:
- case ClientCertificateType.ecdsa_sign:
- case ClientCertificateType.rsa_sign:
- return true;
- default:
- return false;
- }
- }
-
- public static TlsSigner createTlsSigner(short clientCertificateType)
- {
- switch (clientCertificateType)
- {
- case ClientCertificateType.dss_sign:
- return new TlsDSSSigner();
- case ClientCertificateType.ecdsa_sign:
- return new TlsECDSASigner();
- case ClientCertificateType.rsa_sign:
- return new TlsRSASigner();
- default:
- throw new IllegalArgumentException("'clientCertificateType' is not a type with signing capability");
- }
- }
-
- static final byte[] SSL_CLIENT = {0x43, 0x4C, 0x4E, 0x54};
- static final byte[] SSL_SERVER = {0x53, 0x52, 0x56, 0x52};
-
- // SSL3 magic mix constants ("A", "BB", "CCC", ...)
- static final byte[][] SSL3_CONST = genConst();
-
- private static byte[][] genConst()
- {
- int n = 10;
- byte[][] arr = new byte[n][];
- for (int i = 0; i < n; i++)
- {
- byte[] b = new byte[i + 1];
- Arrays.fill(b, (byte)('A' + i));
- arr[i] = b;
- }
- return arr;
- }
-
- private static Vector vectorOfOne(Object obj)
- {
- Vector v = new Vector(1);
- v.addElement(obj);
- return v;
- }
-
- public static int getCipherType(int ciphersuite) throws IOException
- {
- switch (getEncryptionAlgorithm(ciphersuite))
- {
- case EncryptionAlgorithm.AES_128_GCM:
- case EncryptionAlgorithm.AES_256_GCM:
- case EncryptionAlgorithm.AES_128_CCM:
- case EncryptionAlgorithm.AES_128_CCM_8:
- case EncryptionAlgorithm.AES_256_CCM:
- case EncryptionAlgorithm.AES_256_CCM_8:
- case EncryptionAlgorithm.CAMELLIA_128_GCM:
- case EncryptionAlgorithm.CAMELLIA_256_GCM:
- case EncryptionAlgorithm.AEAD_CHACHA20_POLY1305:
- return CipherType.aead;
-
- case EncryptionAlgorithm.RC2_CBC_40:
- case EncryptionAlgorithm.IDEA_CBC:
- case EncryptionAlgorithm.DES40_CBC:
- case EncryptionAlgorithm.DES_CBC:
- case EncryptionAlgorithm._3DES_EDE_CBC:
- case EncryptionAlgorithm.AES_128_CBC:
- case EncryptionAlgorithm.AES_256_CBC:
- case EncryptionAlgorithm.CAMELLIA_128_CBC:
- case EncryptionAlgorithm.CAMELLIA_256_CBC:
- case EncryptionAlgorithm.SEED_CBC:
- return CipherType.block;
-
- case EncryptionAlgorithm.RC4_40:
- case EncryptionAlgorithm.RC4_128:
- case EncryptionAlgorithm.ESTREAM_SALSA20:
- case EncryptionAlgorithm.SALSA20:
- return CipherType.stream;
-
- default:
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- public static int getEncryptionAlgorithm(int ciphersuite) throws IOException
- {
- switch (ciphersuite)
- {
- case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_ECDHE_RSA_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_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
- return EncryptionAlgorithm._3DES_EDE_CBC;
-
- case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
- return EncryptionAlgorithm.AEAD_CHACHA20_POLY1305;
-
- case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_ECDHE_RSA_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_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
- return EncryptionAlgorithm.AES_128_CBC;
-
- 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_PSK_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_PSK_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
- return EncryptionAlgorithm.AES_128_CBC;
-
- case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
- case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
- case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
- return EncryptionAlgorithm.AES_128_CCM;
-
- case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
- case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
- case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
- case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
- return EncryptionAlgorithm.AES_128_CCM_8;
-
- 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:
- case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
- return EncryptionAlgorithm.AES_128_GCM;
-
- case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_ECDHE_RSA_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_RSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
- return EncryptionAlgorithm.AES_256_CBC;
-
- 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:
- return EncryptionAlgorithm.AES_256_CBC;
-
- case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
- 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_PSK_WITH_AES_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_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 EncryptionAlgorithm.AES_256_CBC;
-
- case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
- case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
- case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
- return EncryptionAlgorithm.AES_256_CCM;
-
- case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
- case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
- case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
- case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
- return EncryptionAlgorithm.AES_256_CCM_8;
-
- 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_GCM_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_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 EncryptionAlgorithm.AES_256_GCM;
-
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
- return EncryptionAlgorithm.CAMELLIA_128_CBC;
-
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- return EncryptionAlgorithm.CAMELLIA_128_CBC;
-
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- return EncryptionAlgorithm.CAMELLIA_128_GCM;
-
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
- return EncryptionAlgorithm.CAMELLIA_256_CBC;
-
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- return EncryptionAlgorithm.CAMELLIA_256_CBC;
-
- case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384:
- return EncryptionAlgorithm.CAMELLIA_256_CBC;
-
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- return EncryptionAlgorithm.CAMELLIA_256_GCM;
-
- case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
- case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
- case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
- case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
- case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1:
- case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1:
- case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1:
- return EncryptionAlgorithm.ESTREAM_SALSA20;
-
- case CipherSuite.TLS_RSA_WITH_NULL_MD5:
- return EncryptionAlgorithm.NULL;
-
- case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
- case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
- case CipherSuite.TLS_PSK_WITH_NULL_SHA:
- case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA:
- case CipherSuite.TLS_RSA_WITH_NULL_SHA:
- return EncryptionAlgorithm.NULL;
-
- 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:
- case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
- return EncryptionAlgorithm.NULL;
-
- 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 EncryptionAlgorithm.NULL;
-
- case CipherSuite.TLS_DH_anon_WITH_RC4_128_MD5:
- case CipherSuite.TLS_RSA_WITH_RC4_128_MD5:
- return EncryptionAlgorithm.RC4_128;
-
- case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA:
- case CipherSuite.TLS_ECDH_anon_WITH_RC4_128_SHA:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
- case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
- case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA:
- case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
- case CipherSuite.TLS_PSK_WITH_RC4_128_SHA:
- case CipherSuite.TLS_RSA_WITH_RC4_128_SHA:
- case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA:
- return EncryptionAlgorithm.RC4_128;
-
- case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1:
- case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1:
- case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1:
- case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1:
- case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1:
- case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1:
- case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1:
- return EncryptionAlgorithm.SALSA20;
-
- 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:
- case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
- case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA:
- return EncryptionAlgorithm.SEED_CBC;
-
- default:
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
-
- public static ProtocolVersion getMinimumVersion(int ciphersuite)
- {
- switch (ciphersuite)
- {
- case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DH_DSS_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_DSS_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
- 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_DH_RSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- 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_DSS_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
- 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_PSK_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
- 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_DHE_RSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
- 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_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
- 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_CAMELLIA_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_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_PSK_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
- case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
- 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_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_SHA256:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
- case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
- case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
- return ProtocolVersion.TLSv12;
-
- default:
- return ProtocolVersion.SSLv3;
- }
- }
-
- public static boolean isAEADCipherSuite(int ciphersuite) throws IOException
- {
- return CipherType.aead == getCipherType(ciphersuite);
- }
-
- public static boolean isBlockCipherSuite(int ciphersuite) throws IOException
- {
- return CipherType.block == getCipherType(ciphersuite);
- }
-
- public static boolean isStreamCipherSuite(int ciphersuite) throws IOException
- {
- return CipherType.stream == getCipherType(ciphersuite);
- }
-
- public static boolean isValidCipherSuiteForVersion(int cipherSuite, ProtocolVersion serverVersion)
- {
- return getMinimumVersion(cipherSuite).isEqualOrEarlierVersionOf(serverVersion.getEquivalentTLSVersion());
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/UDPTransport.java b/core/src/main/java/org/bouncycastle/crypto/tls/UDPTransport.java
deleted file mode 100644
index d5f0769e..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/UDPTransport.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-import java.net.DatagramPacket;
-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;
-
- 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");
- }
-
- this.socket = socket;
-
- // NOTE: As of JDK 1.6, can use NetworkInterface.getMTU
-
- this.receiveLimit = mtu - MIN_IP_OVERHEAD - UDP_OVERHEAD;
- this.sendLimit = mtu - MAX_IP_OVERHEAD - UDP_OVERHEAD;
- }
-
- public int getReceiveLimit()
- {
- return receiveLimit;
- }
-
- public int getSendLimit()
- {
- // TODO[DTLS] Implement Path-MTU discovery?
- return sendLimit;
- }
-
- public int receive(byte[] buf, int off, int len, int waitMillis)
- throws IOException
- {
- socket.setSoTimeout(waitMillis);
- DatagramPacket packet = new DatagramPacket(buf, off, len);
- socket.receive(packet);
- return packet.getLength();
- }
-
- public void send(byte[] buf, int off, int len)
- throws IOException
- {
- if (len > getSendLimit())
- {
- /*
- * RFC 4347 4.1.1. "If the application attempts to send a record larger than the MTU,
- * the DTLS implementation SHOULD generate an error, thus avoiding sending a packet
- * which will be fragmented."
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- DatagramPacket packet = new DatagramPacket(buf, off, len);
- socket.send(packet);
- }
-
- public void close()
- throws IOException
- {
- socket.close();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/URLAndHash.java b/core/src/main/java/org/bouncycastle/crypto/tls/URLAndHash.java
deleted file mode 100644
index c32a904a..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/URLAndHash.java
+++ /dev/null
@@ -1,104 +0,0 @@
-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/core/src/main/java/org/bouncycastle/crypto/tls/UseSRTPData.java b/core/src/main/java/org/bouncycastle/crypto/tls/UseSRTPData.java
deleted file mode 100644
index bc2cf10c..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/UseSRTPData.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 5764 4.1.1
- */
-public class UseSRTPData
-{
- private int[] protectionProfiles;
- private byte[] mki;
-
- /**
- * @param protectionProfiles see {@link SRTPProtectionProfile} for valid constants.
- * @param mki valid lengths from 0 to 255.
- */
- public UseSRTPData(int[] protectionProfiles, byte[] mki)
- {
- if (protectionProfiles == null || protectionProfiles.length < 1
- || protectionProfiles.length >= (1 << 15))
- {
- throw new IllegalArgumentException(
- "'protectionProfiles' must have length from 1 to (2^15 - 1)");
- }
-
- if (mki == null)
- {
- mki = TlsUtils.EMPTY_BYTES;
- }
- else if (mki.length > 255)
- {
- throw new IllegalArgumentException("'mki' cannot be longer than 255 bytes");
- }
-
- this.protectionProfiles = protectionProfiles;
- this.mki = mki;
- }
-
- /**
- * @return see {@link SRTPProtectionProfile} for valid constants.
- */
- public int[] getProtectionProfiles()
- {
- return protectionProfiles;
- }
-
- /**
- * @return valid lengths from 0 to 255.
- */
- public byte[] getMki()
- {
- return mki;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/UserMappingType.java b/core/src/main/java/org/bouncycastle/crypto/tls/UserMappingType.java
deleted file mode 100644
index 8f6ae7ba..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/tls/UserMappingType.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-/**
- * RFC 4681
- */
-public class UserMappingType
-{
- /*
- * RFC 4681
- */
- public static final short upn_domain_hint = 64;
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/util/Pack.java b/core/src/main/java/org/bouncycastle/crypto/util/Pack.java
deleted file mode 100644
index 2ded8efc..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/util/Pack.java
+++ /dev/null
@@ -1,204 +0,0 @@
-package org.bouncycastle.crypto.util;
-
-/**
- * @deprecated use org.bouncycastle.util.pack
- */
-public abstract class Pack
-{
- public static int bigEndianToInt(byte[] bs, int off)
- {
- int n = bs[ off] << 24;
- n |= (bs[++off] & 0xff) << 16;
- n |= (bs[++off] & 0xff) << 8;
- n |= (bs[++off] & 0xff);
- return n;
- }
-
- public static void bigEndianToInt(byte[] bs, int off, int[] ns)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- ns[i] = bigEndianToInt(bs, off);
- off += 4;
- }
- }
-
- public static byte[] intToBigEndian(int n)
- {
- byte[] bs = new byte[4];
- intToBigEndian(n, bs, 0);
- return bs;
- }
-
- public static void intToBigEndian(int n, byte[] bs, int off)
- {
- bs[ off] = (byte)(n >>> 24);
- bs[++off] = (byte)(n >>> 16);
- bs[++off] = (byte)(n >>> 8);
- bs[++off] = (byte)(n );
- }
-
- public static byte[] intToBigEndian(int[] ns)
- {
- byte[] bs = new byte[4 * ns.length];
- intToBigEndian(ns, bs, 0);
- return bs;
- }
-
- public static void intToBigEndian(int[] ns, byte[] bs, int off)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- intToBigEndian(ns[i], bs, off);
- off += 4;
- }
- }
-
- public static long bigEndianToLong(byte[] bs, int off)
- {
- int hi = bigEndianToInt(bs, off);
- int lo = bigEndianToInt(bs, off + 4);
- return ((long)(hi & 0xffffffffL) << 32) | (long)(lo & 0xffffffffL);
- }
-
- public static void bigEndianToLong(byte[] bs, int off, long[] ns)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- ns[i] = bigEndianToLong(bs, off);
- off += 8;
- }
- }
-
- public static byte[] longToBigEndian(long n)
- {
- byte[] bs = new byte[8];
- longToBigEndian(n, bs, 0);
- return bs;
- }
-
- public static void longToBigEndian(long n, byte[] bs, int off)
- {
- intToBigEndian((int)(n >>> 32), bs, off);
- intToBigEndian((int)(n & 0xffffffffL), bs, off + 4);
- }
-
- public static byte[] longToBigEndian(long[] ns)
- {
- byte[] bs = new byte[8 * ns.length];
- longToBigEndian(ns, bs, 0);
- return bs;
- }
-
- public static void longToBigEndian(long[] ns, byte[] bs, int off)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- longToBigEndian(ns[i], bs, off);
- off += 8;
- }
- }
-
- public static int littleEndianToInt(byte[] bs, int off)
- {
- int n = bs[ off] & 0xff;
- n |= (bs[++off] & 0xff) << 8;
- n |= (bs[++off] & 0xff) << 16;
- n |= bs[++off] << 24;
- return n;
- }
-
- public static void littleEndianToInt(byte[] bs, int off, int[] ns)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- ns[i] = littleEndianToInt(bs, off);
- off += 4;
- }
- }
-
- public static void littleEndianToInt(byte[] bs, int bOff, int[] ns, int nOff, int count)
- {
- for (int i = 0; i < count; ++i)
- {
- ns[nOff + i] = littleEndianToInt(bs, bOff);
- bOff += 4;
- }
- }
-
- public static byte[] intToLittleEndian(int n)
- {
- byte[] bs = new byte[4];
- intToLittleEndian(n, bs, 0);
- return bs;
- }
-
- public static void intToLittleEndian(int n, byte[] bs, int off)
- {
- bs[ off] = (byte)(n );
- bs[++off] = (byte)(n >>> 8);
- bs[++off] = (byte)(n >>> 16);
- bs[++off] = (byte)(n >>> 24);
- }
-
- public static byte[] intToLittleEndian(int[] ns)
- {
- byte[] bs = new byte[4 * ns.length];
- intToLittleEndian(ns, bs, 0);
- return bs;
- }
-
- public static void intToLittleEndian(int[] ns, byte[] bs, int off)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- intToLittleEndian(ns[i], bs, off);
- off += 4;
- }
- }
-
- public static long littleEndianToLong(byte[] bs, int off)
- {
- int lo = littleEndianToInt(bs, off);
- int hi = littleEndianToInt(bs, off + 4);
- return ((long)(hi & 0xffffffffL) << 32) | (long)(lo & 0xffffffffL);
- }
-
- public static void littleEndianToLong(byte[] bs, int off, long[] ns)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- ns[i] = littleEndianToLong(bs, off);
- off += 8;
- }
- }
-
- public static byte[] longToLittleEndian(long n)
- {
- byte[] bs = new byte[8];
- longToLittleEndian(n, bs, 0);
- return bs;
- }
-
- public static void longToLittleEndian(long n, byte[] bs, int off)
- {
- intToLittleEndian((int)(n & 0xffffffffL), bs, off);
- intToLittleEndian((int)(n >>> 32), bs, off + 4);
- }
-
- public static byte[] longToLittleEndian(long[] ns)
- {
- byte[] bs = new byte[8 * ns.length];
- longToLittleEndian(ns, bs, 0);
- return bs;
- }
-
- public static void longToLittleEndian(long[] ns, byte[] bs, int off)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- longToLittleEndian(ns[i], bs, off);
- off += 8;
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java b/core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java
deleted file mode 100644
index 92684ecc..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java
+++ /dev/null
@@ -1,159 +0,0 @@
-package org.bouncycastle.crypto.util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-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.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.ECNamedCurveTable;
-import org.bouncycastle.asn1.x9.X962Parameters;
-import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
-import org.bouncycastle.crypto.ec.CustomNamedCurves;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
-import org.bouncycastle.crypto.params.DSAParameters;
-import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECNamedDomainParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ElGamalParameters;
-import org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters;
-import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
-
-/**
- * Factory for creating private key objects from PKCS8 PrivateKeyInfo objects.
- */
-public class PrivateKeyFactory
-{
- /**
- * Create a private key parameter from a PKCS8 PrivateKeyInfo encoding.
- *
- * @param privateKeyInfoData the PrivateKeyInfo encoding
- * @return a suitable private key parameter
- * @throws IOException on an error decoding the key
- */
- public static AsymmetricKeyParameter createKey(byte[] privateKeyInfoData) throws IOException
- {
- return createKey(PrivateKeyInfo.getInstance(ASN1Primitive.fromByteArray(privateKeyInfoData)));
- }
-
- /**
- * Create a private key parameter from a PKCS8 PrivateKeyInfo encoding read from a
- * stream.
- *
- * @param inStr the stream to read the PrivateKeyInfo encoding from
- * @return a suitable private key parameter
- * @throws IOException on an error decoding the key
- */
- public static AsymmetricKeyParameter createKey(InputStream inStr) throws IOException
- {
- return createKey(PrivateKeyInfo.getInstance(new ASN1InputStream(inStr).readObject()));
- }
-
- /**
- * Create a private key parameter from the passed in PKCS8 PrivateKeyInfo object.
- *
- * @param keyInfo the PrivateKeyInfo object containing the key material
- * @return a suitable private key parameter
- * @throws IOException on an error decoding the key
- */
- public static AsymmetricKeyParameter createKey(PrivateKeyInfo keyInfo) throws IOException
- {
- AlgorithmIdentifier algId = keyInfo.getPrivateKeyAlgorithm();
-
- if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.rsaEncryption))
- {
- RSAPrivateKey keyStructure = RSAPrivateKey.getInstance(keyInfo.parsePrivateKey());
-
- return new RSAPrivateCrtKeyParameters(keyStructure.getModulus(),
- keyStructure.getPublicExponent(), keyStructure.getPrivateExponent(),
- keyStructure.getPrime1(), keyStructure.getPrime2(), keyStructure.getExponent1(),
- keyStructure.getExponent2(), keyStructure.getCoefficient());
- }
- // TODO?
-// else if (algId.getObjectId().equals(X9ObjectIdentifiers.dhpublicnumber))
- else if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.dhKeyAgreement))
- {
- DHParameter params = DHParameter.getInstance(algId.getParameters());
- ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey();
-
- BigInteger lVal = params.getL();
- int l = lVal == null ? 0 : lVal.intValue();
- DHParameters dhParams = new DHParameters(params.getP(), params.getG(), null, l);
-
- return new DHPrivateKeyParameters(derX.getValue(), dhParams);
- }
- else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm))
- {
- ElGamalParameter params = ElGamalParameter.getInstance(algId.getParameters());
- ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey();
-
- return new ElGamalPrivateKeyParameters(derX.getValue(), new ElGamalParameters(
- params.getP(), params.getG()));
- }
- else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_dsa))
- {
- ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey();
- ASN1Encodable de = algId.getParameters();
-
- DSAParameters parameters = null;
- if (de != null)
- {
- DSAParameter params = DSAParameter.getInstance(de.toASN1Primitive());
- parameters = new DSAParameters(params.getP(), params.getQ(), params.getG());
- }
-
- return new DSAPrivateKeyParameters(derX.getValue(), parameters);
- }
- else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_ecPublicKey))
- {
- X962Parameters params = new X962Parameters((ASN1Primitive)algId.getParameters());
-
- X9ECParameters x9;
- ECDomainParameters dParams;
-
- if (params.isNamedCurve())
- {
- ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters();
-
- x9 = CustomNamedCurves.getByOID(oid);
- if (x9 == null)
- {
- x9 = ECNamedCurveTable.getByOID(oid);
- }
- dParams = new ECNamedDomainParameters(
- oid, x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
- }
- else
- {
- x9 = X9ECParameters.getInstance(params.getParameters());
- dParams = new ECDomainParameters(
- x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
- }
-
- ECPrivateKey ec = ECPrivateKey.getInstance(keyInfo.parsePrivateKey());
- BigInteger d = ec.getKey();
-
- return new ECPrivateKeyParameters(d, dParams);
- }
- else
- {
- throw new RuntimeException("algorithm identifier in key not recognised");
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyInfoFactory.java b/core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyInfoFactory.java
deleted file mode 100644
index 9f791f4c..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyInfoFactory.java
+++ /dev/null
@@ -1,86 +0,0 @@
-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.ECNamedDomainParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
-
-/**
- * Factory to create ASN.1 private key info objects from lightweight private keys.
- */
-public class PrivateKeyInfoFactory
-{
- /**
- * Create a PrivateKeyInfo representation of a private key.
- *
- * @param privateKey the SubjectPublicKeyInfo encoding
- * @return the appropriate key parameter
- * @throws java.io.IOException on an error encoding the key
- */
- public static PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter privateKey) throws IOException
- {
- if (privateKey instanceof RSAKeyParameters)
- {
- RSAPrivateCrtKeyParameters priv = (RSAPrivateCrtKeyParameters)privateKey;
-
- return new PrivateKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE), new RSAPrivateKey(priv.getModulus(), priv.getPublicExponent(), priv.getExponent(), priv.getP(), priv.getQ(), priv.getDP(), priv.getDQ(), priv.getQInv()));
- }
- else if (privateKey instanceof DSAPrivateKeyParameters)
- {
- DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)privateKey;
- DSAParameters params = priv.getParameters();
-
- 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;
-
- if (domainParams == null)
- {
- params = new X962Parameters(DERNull.INSTANCE); // Implicitly CA
- }
- else if (domainParams instanceof ECNamedDomainParameters)
- {
- params = new X962Parameters(((ECNamedDomainParameters)domainParams).getName());
- }
- 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/core/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java b/core/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java
deleted file mode 100644
index cb130954..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java
+++ /dev/null
@@ -1,195 +0,0 @@
-package org.bouncycastle.crypto.util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.DEROctetString;
-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.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.DSAParameter;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
-import org.bouncycastle.asn1.x9.DHDomainParameters;
-import org.bouncycastle.asn1.x9.DHPublicKey;
-import org.bouncycastle.asn1.x9.DHValidationParms;
-import org.bouncycastle.asn1.x9.ECNamedCurveTable;
-import org.bouncycastle.asn1.x9.X962Parameters;
-import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.asn1.x9.X9ECPoint;
-import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
-import org.bouncycastle.crypto.ec.CustomNamedCurves;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.crypto.params.DHPublicKeyParameters;
-import org.bouncycastle.crypto.params.DHValidationParameters;
-import org.bouncycastle.crypto.params.DSAParameters;
-import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECNamedDomainParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.params.ElGamalParameters;
-import org.bouncycastle.crypto.params.ElGamalPublicKeyParameters;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-
-/**
- * Factory to create asymmetric public key parameters for asymmetric ciphers from range of
- * ASN.1 encoded SubjectPublicKeyInfo objects.
- */
-public class PublicKeyFactory
-{
- /**
- * Create a public key from a SubjectPublicKeyInfo encoding
- *
- * @param keyInfoData the SubjectPublicKeyInfo encoding
- * @return the appropriate key parameter
- * @throws IOException on an error decoding the key
- */
- public static AsymmetricKeyParameter createKey(byte[] keyInfoData) throws IOException
- {
- return createKey(SubjectPublicKeyInfo.getInstance(ASN1Primitive.fromByteArray(keyInfoData)));
- }
-
- /**
- * Create a public key from a SubjectPublicKeyInfo encoding read from a stream
- *
- * @param inStr the stream to read the SubjectPublicKeyInfo encoding from
- * @return the appropriate key parameter
- * @throws IOException on an error decoding the key
- */
- public static AsymmetricKeyParameter createKey(InputStream inStr) throws IOException
- {
- return createKey(SubjectPublicKeyInfo.getInstance(new ASN1InputStream(inStr).readObject()));
- }
-
- /**
- * Create a public key from the passed in SubjectPublicKeyInfo
- *
- * @param keyInfo the SubjectPublicKeyInfo containing the key data
- * @return the appropriate key parameter
- * @throws IOException on an error decoding the key
- */
- public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo) throws IOException
- {
- AlgorithmIdentifier algId = keyInfo.getAlgorithm();
-
- if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.rsaEncryption)
- || algId.getAlgorithm().equals(X509ObjectIdentifiers.id_ea_rsa))
- {
- RSAPublicKey pubKey = RSAPublicKey.getInstance(keyInfo.parsePublicKey());
-
- return new RSAKeyParameters(false, pubKey.getModulus(), pubKey.getPublicExponent());
- }
- else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.dhpublicnumber))
- {
- DHPublicKey dhPublicKey = DHPublicKey.getInstance(keyInfo.parsePublicKey());
-
- BigInteger y = dhPublicKey.getY().getValue();
-
- DHDomainParameters dhParams = DHDomainParameters.getInstance(algId.getParameters());
-
- BigInteger p = dhParams.getP().getValue();
- BigInteger g = dhParams.getG().getValue();
- BigInteger q = dhParams.getQ().getValue();
-
- BigInteger j = null;
- if (dhParams.getJ() != null)
- {
- j = dhParams.getJ().getValue();
- }
-
- DHValidationParameters validation = null;
- DHValidationParms dhValidationParms = dhParams.getValidationParms();
- if (dhValidationParms != null)
- {
- byte[] seed = dhValidationParms.getSeed().getBytes();
- BigInteger pgenCounter = dhValidationParms.getPgenCounter().getValue();
-
- // TODO Check pgenCounter size?
-
- validation = new DHValidationParameters(seed, pgenCounter.intValue());
- }
-
- return new DHPublicKeyParameters(y, new DHParameters(p, g, q, j, validation));
- }
- else if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.dhKeyAgreement))
- {
- DHParameter params = DHParameter.getInstance(algId.getParameters());
- ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey();
-
- BigInteger lVal = params.getL();
- int l = lVal == null ? 0 : lVal.intValue();
- DHParameters dhParams = new DHParameters(params.getP(), params.getG(), null, l);
-
- return new DHPublicKeyParameters(derY.getValue(), dhParams);
- }
- else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm))
- {
- ElGamalParameter params = ElGamalParameter.getInstance(algId.getParameters());
- ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey();
-
- return new ElGamalPublicKeyParameters(derY.getValue(), new ElGamalParameters(
- params.getP(), params.getG()));
- }
- else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_dsa)
- || algId.getAlgorithm().equals(OIWObjectIdentifiers.dsaWithSHA1))
- {
- ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey();
- ASN1Encodable de = algId.getParameters();
-
- DSAParameters parameters = null;
- if (de != null)
- {
- DSAParameter params = DSAParameter.getInstance(de.toASN1Primitive());
- parameters = new DSAParameters(params.getP(), params.getQ(), params.getG());
- }
-
- return new DSAPublicKeyParameters(derY.getValue(), parameters);
- }
- else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_ecPublicKey))
- {
- X962Parameters params = X962Parameters.getInstance(algId.getParameters());
-
- X9ECParameters x9;
- ECDomainParameters dParams;
-
- if (params.isNamedCurve())
- {
- ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters();
-
- x9 = CustomNamedCurves.getByOID(oid);
- if (x9 == null)
- {
- x9 = ECNamedCurveTable.getByOID(oid);
- }
- dParams = new ECNamedDomainParameters(
- oid, x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
- }
- else
- {
- x9 = X9ECParameters.getInstance(params.getParameters());
- dParams = new ECDomainParameters(
- x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
- }
-
- ASN1OctetString key = new DEROctetString(keyInfo.getPublicKeyData().getBytes());
- X9ECPoint derQ = new X9ECPoint(x9.getCurve(), key);
-
- return new ECPublicKeyParameters(derQ.getPoint(), dParams);
- }
- else
- {
- throw new RuntimeException("algorithm identifier in key not recognised");
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java b/core/src/main/java/org/bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java
deleted file mode 100644
index d2d42037..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package org.bouncycastle.crypto.util;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.asn1.pkcs.RSAPublicKey;
-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.X9ObjectIdentifiers;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECNamedDomainParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-
-/**
- * Factory to create ASN.1 subject public key info objects from lightweight public keys.
- */
-public class SubjectPublicKeyInfoFactory
-{
- /**
- * Create a SubjectPublicKeyInfo public key.
- *
- * @param publicKey the SubjectPublicKeyInfo encoding
- * @return the appropriate key parameter
- * @throws java.io.IOException on an error encoding the key
- */
- public static SubjectPublicKeyInfo createSubjectPublicKeyInfo(AsymmetricKeyParameter publicKey) throws IOException
- {
- if (publicKey instanceof RSAKeyParameters)
- {
- RSAKeyParameters pub = (RSAKeyParameters)publicKey;
-
- return new SubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE), new RSAPublicKey(pub.getModulus(), pub.getExponent()));
- }
- else if (publicKey instanceof DSAPublicKeyParameters)
- {
- DSAPublicKeyParameters pub = (DSAPublicKeyParameters)publicKey;
-
- return new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa), new ASN1Integer(pub.getY()));
- }
- else if (publicKey instanceof ECPublicKeyParameters)
- {
- ECPublicKeyParameters pub = (ECPublicKeyParameters)publicKey;
- ECDomainParameters domainParams = pub.getParameters();
- ASN1Encodable params;
-
- if (domainParams == null)
- {
- params = new X962Parameters(DERNull.INSTANCE); // Implicitly CA
- }
- else if (domainParams instanceof ECNamedDomainParameters)
- {
- params = new X962Parameters(((ECNamedDomainParameters)domainParams).getName());
- }
- else
- {
- X9ECParameters ecP = new X9ECParameters(
- domainParams.getCurve(),
- domainParams.getG(),
- domainParams.getN(),
- domainParams.getH(),
- domainParams.getSeed());
-
- params = new X962Parameters(ecP);
- }
-
- ASN1OctetString p = (ASN1OctetString)new X9ECPoint(pub.getQ()).toASN1Primitive();
-
- return new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), p.getOctets());
- }
- else
- {
- throw new IOException("key parameters not recognised.");
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/i18n/ErrorBundle.java b/core/src/main/java/org/bouncycastle/i18n/ErrorBundle.java
deleted file mode 100644
index 415b5e57..00000000
--- a/core/src/main/java/org/bouncycastle/i18n/ErrorBundle.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package org.bouncycastle.i18n;
-
-import java.io.UnsupportedEncodingException;
-import java.util.Locale;
-import java.util.TimeZone;
-
-public class ErrorBundle extends MessageBundle
-{
-
- /**
- * summary entry key
- */
- public static final String SUMMARY_ENTRY = "summary";
-
- /**
- * detail entry key
- */
- public static final String DETAIL_ENTRY = "details";
-
- /**
- * Constructs a new ErrorBundle using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- */
- public ErrorBundle(String resource, String id) throws NullPointerException
- {
- super(resource, id);
- }
-
- /**
- * Constructs a new ErrorBundle using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @param encoding the encoding of the resource file
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- * @throws UnsupportedEncodingException if the encoding is not supported
- */
- public ErrorBundle(String resource, String id, String encoding) throws NullPointerException, UnsupportedEncodingException
- {
- super(resource, id, encoding);
- }
-
- /**
- * Constructs a new ErrorBundle using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @param arguments an array containing the arguments for the message
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- */
- public ErrorBundle(String resource, String id, Object[] arguments) throws NullPointerException
- {
- super(resource, id, arguments);
- }
-
- /**
- * Constructs a new ErrorBundle using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @param encoding the encoding of the resource file
- * @param arguments an array containing the arguments for the message
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- * @throws UnsupportedEncodingException if the encoding is not supported
- */
- public ErrorBundle(String resource, String id, String encoding, Object[] arguments) throws NullPointerException, UnsupportedEncodingException
- {
- super(resource, id, encoding, arguments);
- }
-
- /**
- * Returns the summary message in the given locale and timezone.
- * @param loc the {@link Locale}
- * @param timezone the {@link TimeZone}
- * @return the summary message.
- * @throws MissingEntryException if the message is not available
- */
- public String getSummary(Locale loc, TimeZone timezone) throws MissingEntryException
- {
- return getEntry(SUMMARY_ENTRY,loc,timezone);
- }
-
- /**
- * Returns the summary message in the given locale and the default timezone.
- * @param loc the {@link Locale}
- * @return the summary message.
- * @throws MissingEntryException if the message is not available
- */
- public String getSummary(Locale loc) throws MissingEntryException
- {
- return getEntry(SUMMARY_ENTRY,loc,TimeZone.getDefault());
- }
-
- /**
- * Returns the detail message in the given locale and timezone.
- * @param loc the {@link Locale}
- * @param timezone the {@link TimeZone}
- * @return the detail message.
- * @throws MissingEntryException if the message is not available
- */
- public String getDetail(Locale loc, TimeZone timezone) throws MissingEntryException
- {
- return getEntry(DETAIL_ENTRY,loc,timezone);
- }
-
- /**
- * Returns the detail message in the given locale and the default timezone.
- * @param loc the {@link Locale}
- * @return the detail message.
- * @throws MissingEntryException if the message is not available
- */
- public String getDetail(Locale loc) throws MissingEntryException
- {
- return getEntry(DETAIL_ENTRY,loc,TimeZone.getDefault());
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/i18n/LocaleString.java b/core/src/main/java/org/bouncycastle/i18n/LocaleString.java
deleted file mode 100644
index ab898a9e..00000000
--- a/core/src/main/java/org/bouncycastle/i18n/LocaleString.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.bouncycastle.i18n;
-
-import java.io.UnsupportedEncodingException;
-import java.util.Locale;
-
-public class LocaleString extends LocalizedMessage
-{
-
- public LocaleString(String resource, String id)
- {
- super(resource, id);
- }
-
- public LocaleString(String resource, String id, String encoding) throws NullPointerException, UnsupportedEncodingException
- {
- 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)
- {
- return this.getEntry(null, locale, null);
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/i18n/LocalizedException.java b/core/src/main/java/org/bouncycastle/i18n/LocalizedException.java
deleted file mode 100644
index 373fd6ce..00000000
--- a/core/src/main/java/org/bouncycastle/i18n/LocalizedException.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package org.bouncycastle.i18n;
-
-import java.util.Locale;
-
-/**
- * Base class for all Exceptions with localized messages.
- */
-public class LocalizedException extends Exception
-{
-
- protected ErrorBundle message;
- private Throwable cause;
-
- /**
- * Constructs a new LocalizedException with the specified localized message.
- * @param message the {@link ErrorBundle} that contains the message for the exception
- */
- public LocalizedException(ErrorBundle message)
- {
- super(message.getText(Locale.getDefault()));
- this.message = message;
- }
-
- /**
- * Constructs a new LocalizedException with the specified localized message and cause.
- * @param message the {@link ErrorBundle} that contains the message for the exception
- * @param throwable the cause
- */
- public LocalizedException(ErrorBundle message, Throwable throwable)
- {
- super(message.getText(Locale.getDefault()));
- this.message = message;
- this.cause = throwable;
- }
-
- /**
- * Returns the localized error message of the exception.
- * @return the localized error message as {@link ErrorBundle}
- */
- public ErrorBundle getErrorMessage()
- {
- return message;
- }
-
- public Throwable getCause()
- {
- return cause;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/i18n/LocalizedMessage.java b/core/src/main/java/org/bouncycastle/i18n/LocalizedMessage.java
deleted file mode 100644
index d88c2291..00000000
--- a/core/src/main/java/org/bouncycastle/i18n/LocalizedMessage.java
+++ /dev/null
@@ -1,476 +0,0 @@
-package org.bouncycastle.i18n;
-
-import org.bouncycastle.i18n.filter.Filter;
-import org.bouncycastle.i18n.filter.TrustedInput;
-import org.bouncycastle.i18n.filter.UntrustedInput;
-import org.bouncycastle.i18n.filter.UntrustedUrlInput;
-
-import java.io.UnsupportedEncodingException;
-import java.nio.charset.Charset;
-import java.text.DateFormat;
-import java.text.Format;
-import java.text.MessageFormat;
-import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-import java.util.TimeZone;
-
-public class LocalizedMessage
-{
-
- protected final String id;
- protected final String resource;
-
- // ISO-8859-1 is the default encoding
- public static final String DEFAULT_ENCODING = "ISO-8859-1";
- protected String encoding = DEFAULT_ENCODING;
-
- protected FilteredArguments arguments;
- protected FilteredArguments extraArgs = null;
-
- protected Filter filter = null;
-
- protected ClassLoader loader = null;
-
- /**
- * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- */
- public LocalizedMessage(String resource,String id) throws NullPointerException
- {
- if (resource == null || id == null)
- {
- throw new NullPointerException();
- }
- this.id = id;
- this.resource = resource;
- arguments = new FilteredArguments();
- }
-
- /**
- * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @param encoding the encoding of the resource file
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- * @throws UnsupportedEncodingException if the encoding is not supported
- */
- public LocalizedMessage(String resource,String id, String encoding) throws NullPointerException, UnsupportedEncodingException
- {
- if (resource == null || id == null)
- {
- throw new NullPointerException();
- }
- this.id = id;
- this.resource = resource;
- arguments = new FilteredArguments();
- if (!Charset.isSupported(encoding))
- {
- throw new UnsupportedEncodingException("The encoding \"" + encoding + "\" is not supported.");
- }
- this.encoding = encoding;
- }
-
- /**
- * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @param arguments an array containing the arguments for the message
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- */
- public LocalizedMessage(String resource, String id, Object[] arguments) throws NullPointerException
- {
- if (resource == null || id == null || arguments == null)
- {
- throw new NullPointerException();
- }
- this.id = id;
- this.resource = resource;
- this.arguments = new FilteredArguments(arguments);
- }
-
- /**
- * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @param encoding the encoding of the resource file
- * @param arguments an array containing the arguments for the message
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- * @throws UnsupportedEncodingException if the encoding is not supported
- */
- public LocalizedMessage(String resource, String id, String encoding, Object[] arguments) throws NullPointerException, UnsupportedEncodingException
- {
- if (resource == null || id == null || arguments == null)
- {
- throw new NullPointerException();
- }
- this.id = id;
- this.resource = resource;
- this.arguments = new FilteredArguments(arguments);
- if (!Charset.isSupported(encoding))
- {
- throw new UnsupportedEncodingException("The encoding \"" + encoding + "\" is not supported.");
- }
- this.encoding = encoding;
- }
-
- /**
- * Reads the entry <code>id + "." + key</code> from the resource file and returns a
- * formated message for the given Locale and TimeZone.
- * @param key second part of the entry id
- * @param loc the used {@link Locale}
- * @param timezone the used {@link TimeZone}
- * @return a Strng containing the localized message
- * @throws MissingEntryException if the resource file is not available or the entry does not exist.
- */
- public String getEntry(String key,Locale loc, TimeZone timezone) throws MissingEntryException
- {
- String entry = id;
- if (key != null)
- {
- entry += "." + key;
- }
-
- try
- {
- ResourceBundle bundle;
- if (loader == null)
- {
- bundle = ResourceBundle.getBundle(resource,loc);
- }
- else
- {
- bundle = ResourceBundle.getBundle(resource, loc, loader);
- }
- String result = bundle.getString(entry);
- if (!encoding.equals(DEFAULT_ENCODING))
- {
- result = new String(result.getBytes(DEFAULT_ENCODING), encoding);
- }
- if (!arguments.isEmpty())
- {
- result = formatWithTimeZone(result,arguments.getFilteredArgs(loc),loc,timezone);
- }
- result = addExtraArgs(result, loc);
- return result;
- }
- catch (MissingResourceException mre)
- {
- throw new MissingEntryException("Can't find entry " + entry + " in resource file " + resource + ".",
- resource,
- entry,
- loc,
- loader != null ? loader : this.getClassLoader());
- }
- catch (UnsupportedEncodingException use)
- {
- // should never occur - cause we already test this in the constructor
- throw new RuntimeException(use);
- }
- }
-
- protected String formatWithTimeZone(
- String template,
- Object[] arguments,
- Locale locale,
- TimeZone timezone)
- {
- MessageFormat mf = new MessageFormat(" ");
- mf.setLocale(locale);
- mf.applyPattern(template);
- if (!timezone.equals(TimeZone.getDefault()))
- {
- Format[] formats = mf.getFormats();
- for (int i = 0; i < formats.length; i++)
- {
- if (formats[i] instanceof DateFormat)
- {
- DateFormat temp = (DateFormat) formats[i];
- temp.setTimeZone(timezone);
- mf.setFormat(i,temp);
- }
- }
- }
- return mf.format(arguments);
- }
-
- protected String addExtraArgs(String msg, Locale locale)
- {
- if (extraArgs != null)
- {
- StringBuffer sb = new StringBuffer(msg);
- Object[] filteredArgs = extraArgs.getFilteredArgs(locale);
- for (int i = 0; i < filteredArgs.length; i++)
- {
- sb.append(filteredArgs[i]);
- }
- msg = sb.toString();
- }
- return msg;
- }
-
- /**
- * Sets the {@link Filter} that is used to filter the arguments of this message
- * @param filter the {@link Filter} to use. <code>null</code> to disable filtering.
- */
- public void setFilter(Filter filter)
- {
- arguments.setFilter(filter);
- if (extraArgs != null)
- {
- extraArgs.setFilter(filter);
- }
- this.filter = filter;
- }
-
- /**
- * Returns the current filter.
- * @return the current filter
- */
- public Filter getFilter()
- {
- return filter;
- }
-
- /**
- * Set the {@link ClassLoader} which loads the resource files. If it is set to <code>null</code>
- * then the default {@link ClassLoader} is used.
- * @param loader the {@link ClassLoader} which loads the resource files
- */
- public void setClassLoader(ClassLoader loader)
- {
- this.loader = loader;
- }
-
- /**
- * Returns the {@link ClassLoader} which loads the resource files or <code>null</code>
- * if the default ClassLoader is used.
- * @return the {@link ClassLoader} which loads the resource files
- */
- public ClassLoader getClassLoader()
- {
- return loader;
- }
-
- /**
- * Returns the id of the message in the resource bundle.
- * @return the id of the message
- */
- public String getId()
- {
- return id;
- }
-
- /**
- * Returns the name of the resource bundle for this message
- * @return name of the resource file
- */
- public String getResource()
- {
- return resource;
- }
-
- /**
- * Returns an <code>Object[]</code> containing the message arguments.
- * @return the message arguments
- */
- public Object[] getArguments()
- {
- return arguments.getArguments();
- }
-
- /**
- *
- * @param extraArg
- */
- public void setExtraArgument(Object extraArg)
- {
- setExtraArguments(new Object[] {extraArg});
- }
-
- /**
- *
- * @param extraArgs
- */
- public void setExtraArguments(Object[] extraArgs)
- {
- if (extraArgs != null)
- {
- this.extraArgs = new FilteredArguments(extraArgs);
- this.extraArgs.setFilter(filter);
- }
- else
- {
- this.extraArgs = null;
- }
- }
-
- /**
- *
- * @return
- */
- public Object[] getExtraArgs()
- {
- return (extraArgs == null) ? null : extraArgs.getArguments();
- }
-
- protected class FilteredArguments
- {
- protected static final int NO_FILTER = 0;
- protected static final int FILTER = 1;
- protected static final int FILTER_URL = 2;
-
- protected Filter filter = null;
-
- protected boolean[] isLocaleSpecific;
- protected int[] argFilterType;
- protected Object[] arguments;
- protected Object[] unpackedArgs;
- protected Object[] filteredArgs;
-
- FilteredArguments()
- {
- this(new Object[0]);
- }
-
- FilteredArguments(Object[] args)
- {
- this.arguments = args;
- this.unpackedArgs = new Object[args.length];
- this.filteredArgs = new Object[args.length];
- this.isLocaleSpecific = new boolean[args.length];
- this.argFilterType = new int[args.length];
- for (int i = 0; i < args.length; i++)
- {
- if (args[i] instanceof TrustedInput)
- {
- this.unpackedArgs[i] = ((TrustedInput) args[i]).getInput();
- argFilterType[i] = NO_FILTER;
- }
- else if (args[i] instanceof UntrustedInput)
- {
- this.unpackedArgs[i] = ((UntrustedInput) args[i]).getInput();
- if (args[i] instanceof UntrustedUrlInput)
- {
- argFilterType[i] = FILTER_URL;
- }
- else
- {
- argFilterType[i] = FILTER;
- }
- }
- else
- {
- this.unpackedArgs[i] = args[i];
- argFilterType[i] = FILTER;
- }
-
- // locale specific
- this.isLocaleSpecific[i] = (this.unpackedArgs[i] instanceof LocaleString);
- }
- }
-
- public boolean isEmpty()
- {
- return unpackedArgs.length == 0;
- }
-
- public Object[] getArguments()
- {
- return arguments;
- }
-
- public Object[] getFilteredArgs(Locale locale)
- {
- Object[] result = new Object[unpackedArgs.length];
- for (int i = 0; i < unpackedArgs.length; i++)
- {
- Object arg;
- if (filteredArgs[i] != null)
- {
- arg = filteredArgs[i];
- }
- else
- {
- arg = unpackedArgs[i];
- if (isLocaleSpecific[i])
- {
- // get locale
- arg = ((LocaleString) arg).getLocaleString(locale);
- arg = filter(argFilterType[i], arg);
- }
- else
- {
- arg = filter(argFilterType[i], arg);
- filteredArgs[i] = arg;
- }
- }
- result[i] = arg;
- }
- return result;
- }
-
- private Object filter(int type, Object obj)
- {
- if (filter != null)
- {
- Object o = (null == obj) ? "null" : obj;
- switch (type)
- {
- case NO_FILTER:
- return o;
- case FILTER:
- return filter.doFilter(o.toString());
- case FILTER_URL:
- return filter.doFilterUrl(o.toString());
- default:
- return null;
- }
- }
- else
- {
- return obj;
- }
- }
-
- public Filter getFilter()
- {
- return filter;
- }
-
- public void setFilter(Filter filter)
- {
- if (filter != this.filter)
- {
- for (int i = 0; i < unpackedArgs.length; i++)
- {
- filteredArgs[i] = null;
- }
- }
- this.filter = filter;
- }
-
- }
-
- public String toString()
- {
- StringBuffer sb = new StringBuffer();
- sb.append("Resource: \"").append(resource);
- sb.append("\" Id: \"").append(id).append("\"");
- sb.append(" Arguments: ").append(arguments.getArguments().length).append(" normal");
- if (extraArgs != null && extraArgs.getArguments().length > 0)
- {
- sb.append(", ").append(extraArgs.getArguments().length).append(" extra");
- }
- sb.append(" Encoding: ").append(encoding);
- sb.append(" ClassLoader: ").append(loader);
- return sb.toString();
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/i18n/MessageBundle.java b/core/src/main/java/org/bouncycastle/i18n/MessageBundle.java
deleted file mode 100644
index de931fce..00000000
--- a/core/src/main/java/org/bouncycastle/i18n/MessageBundle.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package org.bouncycastle.i18n;
-
-import java.io.UnsupportedEncodingException;
-import java.util.Locale;
-import java.util.TimeZone;
-
-public class MessageBundle extends TextBundle
-{
-
- /**
- * title entry key
- */
- public static final String TITLE_ENTRY = "title";
-
- /**
- * Constructs a new MessageBundle using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- */
- public MessageBundle(String resource, String id) throws NullPointerException
- {
- super(resource, id);
- }
-
- /**
- * Constructs a new MessageBundle using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @param encoding the encoding of the resource file
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- * @throws UnsupportedEncodingException if the encoding is not supported
- */
- public MessageBundle(String resource, String id, String encoding) throws NullPointerException, UnsupportedEncodingException
- {
- super(resource, id, encoding);
- }
-
- /**
- * Constructs a new MessageBundle using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @param arguments an array containing the arguments for the message
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- */
- public MessageBundle(String resource, String id, Object[] arguments) throws NullPointerException
- {
- super(resource, id, arguments);
- }
-
- /**
- * Constructs a new MessageBundle using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @param encoding the encoding of the resource file
- * @param arguments an array containing the arguments for the message
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- * @throws UnsupportedEncodingException if the encoding is not supported
- */
- public MessageBundle(String resource, String id, String encoding, Object[] arguments) throws NullPointerException, UnsupportedEncodingException
- {
- super(resource, id, encoding, arguments);
- }
-
- /**
- * Returns the title message in the given locale and timezone.
- * @param loc the {@link Locale}
- * @param timezone the {@link TimeZone}
- * @return the title message.
- * @throws MissingEntryException if the message is not available
- */
- public String getTitle(Locale loc,TimeZone timezone) throws MissingEntryException
- {
- return getEntry(TITLE_ENTRY,loc,timezone);
- }
-
- /**
- * Returns the title message in the given locale and the default timezone.
- * @param loc the {@link Locale}
- * @return the title message.
- * @throws MissingEntryException if the message is not available
- */
- public String getTitle(Locale loc) throws MissingEntryException
- {
- return getEntry(TITLE_ENTRY,loc,TimeZone.getDefault());
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/i18n/MissingEntryException.java b/core/src/main/java/org/bouncycastle/i18n/MissingEntryException.java
deleted file mode 100644
index ffd4d543..00000000
--- a/core/src/main/java/org/bouncycastle/i18n/MissingEntryException.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package org.bouncycastle.i18n;
-
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.Locale;
-
-public class MissingEntryException extends RuntimeException
-{
-
- protected final String resource;
- protected final String key;
- protected final ClassLoader loader;
- protected final Locale locale;
-
- private String debugMsg;
-
- public MissingEntryException(String message, String resource, String key, Locale locale, ClassLoader loader)
- {
- super(message);
- this.resource = resource;
- this.key = key;
- this.locale = locale;
- this.loader = loader;
- }
-
- public MissingEntryException(String message, Throwable cause, String resource, String key, Locale locale, ClassLoader loader)
- {
- super(message, cause);
- this.resource = resource;
- this.key = key;
- this.locale = locale;
- this.loader = loader;
- }
-
- public String getKey()
- {
- return key;
- }
-
- public String getResource()
- {
- return resource;
- }
-
- public ClassLoader getClassLoader()
- {
- return loader;
- }
-
- public Locale getLocale()
- {
- return locale;
- }
-
- public String getDebugMsg()
- {
- if (debugMsg == null)
- {
- debugMsg = "Can not find entry " + key + " in resource file " + resource + " for the locale " + locale + ".";
- if (loader instanceof URLClassLoader)
- {
- URL[] urls = ((URLClassLoader) loader).getURLs();
- debugMsg += " The following entries in the classpath were searched: ";
- for (int i = 0; i != urls.length; i++)
- {
- debugMsg += urls[i] + " ";
- }
- }
- }
- return debugMsg;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/i18n/TextBundle.java b/core/src/main/java/org/bouncycastle/i18n/TextBundle.java
deleted file mode 100644
index d77e8417..00000000
--- a/core/src/main/java/org/bouncycastle/i18n/TextBundle.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package org.bouncycastle.i18n;
-
-import java.io.UnsupportedEncodingException;
-import java.util.Locale;
-import java.util.TimeZone;
-
-public class TextBundle extends LocalizedMessage
-{
-
- /**
- * text entry key
- */
- public static final String TEXT_ENTRY = "text";
-
- /**
- * Constructs a new TextBundle using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- */
- public TextBundle(String resource, String id) throws NullPointerException
- {
- super(resource, id);
- }
-
- /**
- * Constructs a new TextBundle using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @param encoding the encoding of the resource file
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- * @throws UnsupportedEncodingException if the encoding is not supported
- */
- public TextBundle(String resource, String id, String encoding) throws NullPointerException, UnsupportedEncodingException
- {
- super(resource, id, encoding);
- }
-
- /**
- * Constructs a new TextBundle using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @param arguments an array containing the arguments for the message
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- */
- public TextBundle(String resource, String id, Object[] arguments) throws NullPointerException
- {
- super(resource, id, arguments);
- }
-
- /**
- * Constructs a new TextBundle using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @param encoding the encoding of the resource file
- * @param arguments an array containing the arguments for the message
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- * @throws UnsupportedEncodingException if the encoding is not supported
- */
- public TextBundle(String resource, String id, String encoding, Object[] arguments) throws NullPointerException, UnsupportedEncodingException
- {
- super(resource, id, encoding, arguments);
- }
-
- /**
- * Returns the text message in the given locale and timezone.
- * @param loc the {@link Locale}
- * @param timezone the {@link TimeZone}
- * @return the text message.
- * @throws MissingEntryException if the message is not available
- */
- public String getText(Locale loc, TimeZone timezone) throws MissingEntryException
- {
- return getEntry(TEXT_ENTRY,loc,timezone);
- }
-
- /**
- * Returns the text message in the given locale and the defaut timezone.
- * @param loc the {@link Locale}
- * @return the text message.
- * @throws MissingEntryException if the message is not available
- */
- public String getText(Locale loc) throws MissingEntryException
- {
- return getEntry(TEXT_ENTRY,loc,TimeZone.getDefault());
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/i18n/filter/Filter.java b/core/src/main/java/org/bouncycastle/i18n/filter/Filter.java
deleted file mode 100644
index fc86aaa4..00000000
--- a/core/src/main/java/org/bouncycastle/i18n/filter/Filter.java
+++ /dev/null
@@ -1,21 +0,0 @@
-
-package org.bouncycastle.i18n.filter;
-
-public interface Filter
-{
-
- /**
- * Runs the filter on the input String and returns the filtered String
- * @param input input String
- * @return filtered String
- */
- public String doFilter(String input);
-
- /**
- * Runs the filter on the input url and returns the filtered String
- * @param input input url String
- * @return filtered String
- */
- public String doFilterUrl(String input);
-
-}
diff --git a/core/src/main/java/org/bouncycastle/i18n/filter/HTMLFilter.java b/core/src/main/java/org/bouncycastle/i18n/filter/HTMLFilter.java
deleted file mode 100644
index b9904bc7..00000000
--- a/core/src/main/java/org/bouncycastle/i18n/filter/HTMLFilter.java
+++ /dev/null
@@ -1,68 +0,0 @@
-
-package org.bouncycastle.i18n.filter;
-
-/**
- * HTML Filter
- */
-public class HTMLFilter implements Filter
-{
-
- public String doFilter(String input)
- {
- StringBuffer buf = new StringBuffer(input);
- int i = 0;
- while (i < buf.length())
- {
- char ch = buf.charAt(i);
- switch (ch)
- {
- case '<':
- buf.replace(i,i+1,"&#60");
- break;
- case '>':
- buf.replace(i,i+1,"&#62");
- break;
- case '(':
- buf.replace(i,i+1,"&#40");
- break;
- case ')':
- buf.replace(i,i+1,"&#41");
- break;
- case '#':
- buf.replace(i,i+1,"&#35");
- break;
- case '&':
- buf.replace(i,i+1,"&#38");
- break;
- case '\"':
- buf.replace(i,i+1,"&#34");
- break;
- case '\'':
- buf.replace(i,i+1,"&#39");
- break;
- case '%':
- buf.replace(i,i+1,"&#37");
- break;
- case ';':
- buf.replace(i,i+1,"&#59");
- break;
- case '+':
- buf.replace(i,i+1,"&#43");
- break;
- case '-':
- buf.replace(i,i+1,"&#45");
- break;
- default:
- i -= 3;
- }
- i += 4;
- }
- return buf.toString();
- }
-
- public String doFilterUrl(String input)
- {
- return doFilter(input);
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/i18n/filter/SQLFilter.java b/core/src/main/java/org/bouncycastle/i18n/filter/SQLFilter.java
deleted file mode 100644
index d55610b6..00000000
--- a/core/src/main/java/org/bouncycastle/i18n/filter/SQLFilter.java
+++ /dev/null
@@ -1,69 +0,0 @@
-
-package org.bouncycastle.i18n.filter;
-
-/**
- * Filter for strings to store in a SQL table.
- *
- * escapes ' " = - / \ ; \r \n
- */
-public class SQLFilter implements Filter
-{
-
- public String doFilter(String input)
- {
- StringBuffer buf = new StringBuffer(input);
- int i = 0;
- while (i < buf.length())
- {
- char ch = buf.charAt(i);
- switch (ch)
- {
- case '\'':
- buf.replace(i,i+1,"\\\'");
- i += 1;
- break;
- case '\"':
- buf.replace(i,i+1,"\\\"");
- i += 1;
- break;
- case '=':
- buf.replace(i,i+1,"\\=");
- i += 1;
- break;
- case '-':
- buf.replace(i,i+1,"\\-");
- i += 1;
- break;
- case '/':
- buf.replace(i,i+1,"\\/");
- i += 1;
- break;
- case '\\':
- buf.replace(i,i+1,"\\\\");
- i += 1;
- break;
- case ';':
- buf.replace(i,i+1,"\\;");
- i += 1;
- break;
- case '\r':
- buf.replace(i,i+1,"\\r");
- i += 1;
- break;
- case '\n':
- buf.replace(i,i+1,"\\n");
- i += 1;
- break;
- default:
- }
- i++;
- }
- return buf.toString();
- }
-
- public String doFilterUrl(String input)
- {
- return doFilter(input);
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/i18n/filter/TrustedInput.java b/core/src/main/java/org/bouncycastle/i18n/filter/TrustedInput.java
deleted file mode 100644
index 0feeeea7..00000000
--- a/core/src/main/java/org/bouncycastle/i18n/filter/TrustedInput.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.i18n.filter;
-
-public class TrustedInput
-{
-
- protected Object input;
-
- public TrustedInput(Object input)
- {
- this.input = input;
- }
-
- public Object getInput()
- {
- return input;
- }
-
- public String toString()
- {
- return input.toString();
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/i18n/filter/UntrustedInput.java b/core/src/main/java/org/bouncycastle/i18n/filter/UntrustedInput.java
deleted file mode 100644
index cc69ac49..00000000
--- a/core/src/main/java/org/bouncycastle/i18n/filter/UntrustedInput.java
+++ /dev/null
@@ -1,44 +0,0 @@
-
-package org.bouncycastle.i18n.filter;
-
-/**
- * Wrapper class to mark untrusted input.
- */
-public class UntrustedInput
-{
-
- protected Object input;
-
- /**
- * Construct a new UntrustedInput instance.
- * @param input the untrusted input Object
- */
- public UntrustedInput(Object input)
- {
- this.input = input;
- }
-
- /**
- * Returns the untrusted input as Object.
- * @return the <code>input</code> as Object
- */
- public Object getInput()
- {
- return input;
- }
-
- /**
- * Returns the untrusted input convertet to a String.
- * @return the <code>input</code> as String
- */
- public String getString()
- {
- return input.toString();
- }
-
- public String toString()
- {
- return input.toString();
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/i18n/filter/UntrustedUrlInput.java b/core/src/main/java/org/bouncycastle/i18n/filter/UntrustedUrlInput.java
deleted file mode 100644
index 98ee1e72..00000000
--- a/core/src/main/java/org/bouncycastle/i18n/filter/UntrustedUrlInput.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.bouncycastle.i18n.filter;
-
-/**
- *
- * Wrapper class to mark an untrusted Url
- */
-public class UntrustedUrlInput extends UntrustedInput
-{
- public UntrustedUrlInput(Object url)
- {
- super(url);
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java
deleted file mode 100644
index d1f35c56..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java
+++ /dev/null
@@ -1,26 +0,0 @@
-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());
- ECPoint result = sign > 0 ? positive : positive.negate();
-
- /*
- * Although the various multipliers ought not to produce invalid output under normal
- * circumstances, a final check here is advised to guard against fault attacks.
- */
- return ECAlgorithms.validatePoint(result);
- }
-
- protected abstract ECPoint multiplyPositive(ECPoint p, BigInteger k);
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/DoubleAddMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/DoubleAddMultiplier.java
deleted file mode 100644
index aae2e00f..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/DoubleAddMultiplier.java
+++ /dev/null
@@ -1,24 +0,0 @@
-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/core/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java b/core/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java
deleted file mode 100644
index 3b334d25..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java
+++ /dev/null
@@ -1,469 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.endo.ECEndomorphism;
-import org.bouncycastle.math.ec.endo.GLVEndomorphism;
-import org.bouncycastle.math.field.FiniteField;
-import org.bouncycastle.math.field.PolynomialExtensionField;
-
-public class ECAlgorithms
-{
- public static boolean isF2mCurve(ECCurve c)
- {
- FiniteField field = c.getField();
- return field.getDimension() > 1 && field.getCharacteristic().equals(ECConstants.TWO)
- && field instanceof PolynomialExtensionField;
- }
-
- public static boolean isFpCurve(ECCurve c)
- {
- return c.getField().getDimension() == 1;
- }
-
- public static ECPoint sumOfMultiplies(ECPoint[] ps, BigInteger[] ks)
- {
- if (ps == null || ks == null || ps.length != ks.length || ps.length < 1)
- {
- throw new IllegalArgumentException("point and scalar arrays should be non-null, and of equal, non-zero, length");
- }
-
- int count = ps.length;
- switch (count)
- {
- case 1:
- return ps[0].multiply(ks[0]);
- case 2:
- return sumOfTwoMultiplies(ps[0], ks[0], ps[1], ks[1]);
- default:
- break;
- }
-
- ECPoint p = ps[0];
- ECCurve c = p.getCurve();
-
- ECPoint[] imported = new ECPoint[count];
- imported[0] = p;
- for (int i = 1; i < count; ++i)
- {
- imported[i] = importPoint(c, ps[i]);
- }
-
- ECEndomorphism endomorphism = c.getEndomorphism();
- if (endomorphism instanceof GLVEndomorphism)
- {
- return validatePoint(implSumOfMultipliesGLV(imported, ks, (GLVEndomorphism)endomorphism));
- }
-
- return validatePoint(implSumOfMultiplies(imported, ks));
- }
-
- public static ECPoint sumOfTwoMultiplies(ECPoint P, BigInteger a,
- ECPoint Q, BigInteger b)
- {
- ECCurve cp = P.getCurve();
- Q = importPoint(cp, Q);
-
- // Point multiplication for Koblitz curves (using WTNAF) beats Shamir's trick
- if (cp instanceof ECCurve.F2m)
- {
- ECCurve.F2m f2mCurve = (ECCurve.F2m)cp;
- if (f2mCurve.isKoblitz())
- {
- return validatePoint(P.multiply(a).add(Q.multiply(b)));
- }
- }
-
- ECEndomorphism endomorphism = cp.getEndomorphism();
- if (endomorphism instanceof GLVEndomorphism)
- {
- return validatePoint(
- implSumOfMultipliesGLV(new ECPoint[]{ P, Q }, new BigInteger[]{ a, b }, (GLVEndomorphism)endomorphism));
- }
-
- return validatePoint(implShamirsTrickWNaf(P, a, Q, b));
- }
-
- /*
- * "Shamir's Trick", originally due to E. G. Straus
- * (Addition chains of vectors. American Mathematical Monthly,
- * 71(7):806-808, Aug./Sept. 1964)
- * <pre>
- * Input: The points P, Q, scalar k = (km?, ... , k1, k0)
- * and scalar l = (lm?, ... , l1, l0).
- * Output: R = k * P + l * Q.
- * 1: Z <- P + Q
- * 2: R <- O
- * 3: for i from m-1 down to 0 do
- * 4: R <- R + R {point doubling}
- * 5: if (ki = 1) and (li = 0) then R <- R + P end if
- * 6: if (ki = 0) and (li = 1) then R <- R + Q end if
- * 7: if (ki = 1) and (li = 1) then R <- R + Z end if
- * 8: end for
- * 9: return R
- * </pre>
- */
- public static ECPoint shamirsTrick(ECPoint P, BigInteger k,
- ECPoint Q, BigInteger l)
- {
- ECCurve cp = P.getCurve();
- Q = importPoint(cp, Q);
-
- return validatePoint(implShamirsTrickJsf(P, k, Q, l));
- }
-
- public static ECPoint importPoint(ECCurve c, ECPoint p)
- {
- ECCurve cp = p.getCurve();
- if (!c.equals(cp))
- {
- throw new IllegalArgumentException("Point must be on the same curve");
- }
- return c.importPoint(p);
- }
-
- public static void montgomeryTrick(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;
- }
-
- /**
- * Simple shift-and-add multiplication. Serves as reference implementation
- * to verify (possibly faster) implementations, and for very small scalars.
- *
- * @param p
- * The point to multiply.
- * @param k
- * The multiplier.
- * @return The result of the point multiplication <code>kP</code>.
- */
- public static ECPoint referenceMultiply(ECPoint p, BigInteger k)
- {
- BigInteger x = k.abs();
- ECPoint q = p.getCurve().getInfinity();
- int t = x.bitLength();
- if (t > 0)
- {
- if (x.testBit(0))
- {
- q = p;
- }
- for (int i = 1; i < t; i++)
- {
- p = p.twice();
- if (x.testBit(i))
- {
- q = q.add(p);
- }
- }
- }
- return k.signum() < 0 ? q.negate() : q;
- }
-
- public static ECPoint validatePoint(ECPoint p)
- {
- if (!p.isValid())
- {
- throw new IllegalArgumentException("Invalid point");
- }
-
- return p;
- }
-
- static ECPoint implShamirsTrickJsf(ECPoint P, BigInteger k,
- ECPoint Q, BigInteger l)
- {
- ECCurve curve = P.getCurve();
- 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);
-
- 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)
- {
- int jsfi = jsf[i];
-
- // NOTE: The shifting ensures the sign is extended correctly
- int kDigit = ((jsfi << 24) >> 28), lDigit = ((jsfi << 28) >> 28);
-
- int index = 4 + (kDigit * 3) + lDigit;
- R = R.twicePlus(table[index]);
- }
-
- return R;
- }
-
- static ECPoint implShamirsTrickWNaf(ECPoint P, BigInteger k,
- ECPoint Q, BigInteger l)
- {
- boolean negK = k.signum() < 0, negL = l.signum() < 0;
-
- k = k.abs();
- l = l.abs();
-
- int widthP = Math.max(2, Math.min(16, WNafUtil.getWindowSize(k.bitLength())));
- int widthQ = Math.max(2, Math.min(16, WNafUtil.getWindowSize(l.bitLength())));
-
- WNafPreCompInfo infoP = WNafUtil.precompute(P, widthP, true);
- WNafPreCompInfo infoQ = WNafUtil.precompute(Q, widthQ, true);
-
- ECPoint[] preCompP = negK ? infoP.getPreCompNeg() : infoP.getPreComp();
- ECPoint[] preCompQ = negL ? infoQ.getPreCompNeg() : infoQ.getPreComp();
- ECPoint[] preCompNegP = negK ? infoP.getPreComp() : infoP.getPreCompNeg();
- ECPoint[] preCompNegQ = negL ? infoQ.getPreComp() : infoQ.getPreCompNeg();
-
- byte[] wnafP = WNafUtil.generateWindowNaf(widthP, k);
- byte[] wnafQ = WNafUtil.generateWindowNaf(widthQ, l);
-
- return implShamirsTrickWNaf(preCompP, preCompNegP, wnafP, preCompQ, preCompNegQ, wnafQ);
- }
-
- static ECPoint implShamirsTrickWNaf(ECPoint P, BigInteger k, ECPointMap pointMapQ, BigInteger l)
- {
- boolean negK = k.signum() < 0, negL = l.signum() < 0;
-
- k = k.abs();
- l = l.abs();
-
- int width = Math.max(2, Math.min(16, WNafUtil.getWindowSize(Math.max(k.bitLength(), l.bitLength()))));
-
- ECPoint Q = WNafUtil.mapPointWithPrecomp(P, width, true, pointMapQ);
- WNafPreCompInfo infoP = WNafUtil.getWNafPreCompInfo(P);
- WNafPreCompInfo infoQ = WNafUtil.getWNafPreCompInfo(Q);
-
- ECPoint[] preCompP = negK ? infoP.getPreCompNeg() : infoP.getPreComp();
- ECPoint[] preCompQ = negL ? infoQ.getPreCompNeg() : infoQ.getPreComp();
- ECPoint[] preCompNegP = negK ? infoP.getPreComp() : infoP.getPreCompNeg();
- ECPoint[] preCompNegQ = negL ? infoQ.getPreComp() : infoQ.getPreCompNeg();
-
- byte[] wnafP = WNafUtil.generateWindowNaf(width, k);
- byte[] wnafQ = WNafUtil.generateWindowNaf(width, l);
-
- return implShamirsTrickWNaf(preCompP, preCompNegP, wnafP, preCompQ, preCompNegQ, wnafQ);
- }
-
- private static ECPoint implShamirsTrickWNaf(ECPoint[] preCompP, ECPoint[] preCompNegP, byte[] wnafP,
- ECPoint[] preCompQ, ECPoint[] preCompNegQ, byte[] wnafQ)
- {
- int len = Math.max(wnafP.length, wnafQ.length);
-
- ECCurve curve = preCompP[0].getCurve();
- ECPoint infinity = curve.getInfinity();
-
- ECPoint R = infinity;
- int zeroes = 0;
-
- for (int i = len - 1; i >= 0; --i)
- {
- int wiP = i < wnafP.length ? wnafP[i] : 0;
- int wiQ = i < wnafQ.length ? wnafQ[i] : 0;
-
- if ((wiP | wiQ) == 0)
- {
- ++zeroes;
- continue;
- }
-
- ECPoint r = infinity;
- if (wiP != 0)
- {
- int nP = Math.abs(wiP);
- ECPoint[] tableP = wiP < 0 ? preCompNegP : preCompP;
- r = r.add(tableP[nP >>> 1]);
- }
- if (wiQ != 0)
- {
- int nQ = Math.abs(wiQ);
- ECPoint[] tableQ = wiQ < 0 ? preCompNegQ : preCompQ;
- r = r.add(tableQ[nQ >>> 1]);
- }
-
- if (zeroes > 0)
- {
- R = R.timesPow2(zeroes);
- zeroes = 0;
- }
-
- R = R.twicePlus(r);
- }
-
- if (zeroes > 0)
- {
- R = R.timesPow2(zeroes);
- }
-
- return R;
- }
-
- static ECPoint implSumOfMultiplies(ECPoint[] ps, BigInteger[] ks)
- {
- int count = ps.length;
- boolean[] negs = new boolean[count];
- WNafPreCompInfo[] infos = new WNafPreCompInfo[count];
- byte[][] wnafs = new byte[count][];
-
- for (int i = 0; i < count; ++i)
- {
- BigInteger ki = ks[i]; negs[i] = ki.signum() < 0; ki = ki.abs();
-
- int width = Math.max(2, Math.min(16, WNafUtil.getWindowSize(ki.bitLength())));
- infos[i] = WNafUtil.precompute(ps[i], width, true);
- wnafs[i] = WNafUtil.generateWindowNaf(width, ki);
- }
-
- return implSumOfMultiplies(negs, infos, wnafs);
- }
-
- static ECPoint implSumOfMultipliesGLV(ECPoint[] ps, BigInteger[] ks, GLVEndomorphism glvEndomorphism)
- {
- BigInteger n = ps[0].getCurve().getOrder();
-
- int len = ps.length;
-
- BigInteger[] abs = new BigInteger[len << 1];
- for (int i = 0, j = 0; i < len; ++i)
- {
- BigInteger[] ab = glvEndomorphism.decomposeScalar(ks[i].mod(n));
- abs[j++] = ab[0];
- abs[j++] = ab[1];
- }
-
- ECPointMap pointMap = glvEndomorphism.getPointMap();
- if (glvEndomorphism.hasEfficientPointMap())
- {
- return ECAlgorithms.implSumOfMultiplies(ps, pointMap, abs);
- }
-
- ECPoint[] pqs = new ECPoint[len << 1];
- for (int i = 0, j = 0; i < len; ++i)
- {
- ECPoint p = ps[i], q = pointMap.map(p);
- pqs[j++] = p;
- pqs[j++] = q;
- }
-
- return ECAlgorithms.implSumOfMultiplies(pqs, abs);
-
- }
-
- static ECPoint implSumOfMultiplies(ECPoint[] ps, ECPointMap pointMap, BigInteger[] ks)
- {
- int halfCount = ps.length, fullCount = halfCount << 1;
-
- boolean[] negs = new boolean[fullCount];
- WNafPreCompInfo[] infos = new WNafPreCompInfo[fullCount];
- byte[][] wnafs = new byte[fullCount][];
-
- for (int i = 0; i < halfCount; ++i)
- {
- int j0 = i << 1, j1 = j0 + 1;
-
- BigInteger kj0 = ks[j0]; negs[j0] = kj0.signum() < 0; kj0 = kj0.abs();
- BigInteger kj1 = ks[j1]; negs[j1] = kj1.signum() < 0; kj1 = kj1.abs();
-
- int width = Math.max(2, Math.min(16, WNafUtil.getWindowSize(Math.max(kj0.bitLength(), kj1.bitLength()))));
-
- ECPoint P = ps[i], Q = WNafUtil.mapPointWithPrecomp(P, width, true, pointMap);
- infos[j0] = WNafUtil.getWNafPreCompInfo(P);
- infos[j1] = WNafUtil.getWNafPreCompInfo(Q);
- wnafs[j0] = WNafUtil.generateWindowNaf(width, kj0);
- wnafs[j1] = WNafUtil.generateWindowNaf(width, kj1);
- }
-
- return implSumOfMultiplies(negs, infos, wnafs);
- }
-
- private static ECPoint implSumOfMultiplies(boolean[] negs, WNafPreCompInfo[] infos, byte[][] wnafs)
- {
- int len = 0, count = wnafs.length;
- for (int i = 0; i < count; ++i)
- {
- len = Math.max(len, wnafs[i].length);
- }
-
- ECCurve curve = infos[0].getPreComp()[0].getCurve();
- ECPoint infinity = curve.getInfinity();
-
- ECPoint R = infinity;
- int zeroes = 0;
-
- for (int i = len - 1; i >= 0; --i)
- {
- ECPoint r = infinity;
-
- for (int j = 0; j < count; ++j)
- {
- byte[] wnaf = wnafs[j];
- int wi = i < wnaf.length ? wnaf[i] : 0;
- if (wi != 0)
- {
- int n = Math.abs(wi);
- WNafPreCompInfo info = infos[j];
- ECPoint[] table = (wi < 0 == negs[j]) ? info.getPreComp() : info.getPreCompNeg();
- r = r.add(table[n >>> 1]);
- }
- }
-
- if (r == infinity)
- {
- ++zeroes;
- continue;
- }
-
- if (zeroes > 0)
- {
- R = R.timesPow2(zeroes);
- zeroes = 0;
- }
-
- R = R.twicePlus(r);
- }
-
- if (zeroes > 0)
- {
- R = R.timesPow2(zeroes);
- }
-
- return R;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/ECConstants.java b/core/src/main/java/org/bouncycastle/math/ec/ECConstants.java
deleted file mode 100644
index 864f746d..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/ECConstants.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-public interface ECConstants
-{
- public static final BigInteger ZERO = BigInteger.valueOf(0);
- public static final BigInteger ONE = BigInteger.valueOf(1);
- public static final BigInteger TWO = BigInteger.valueOf(2);
- public static final BigInteger THREE = BigInteger.valueOf(3);
- public static final BigInteger FOUR = BigInteger.valueOf(4);
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/ECCurve.java b/core/src/main/java/org/bouncycastle/math/ec/ECCurve.java
deleted file mode 100644
index 4c658f20..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/ECCurve.java
+++ /dev/null
@@ -1,1113 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-import java.util.Hashtable;
-import java.util.Random;
-
-import org.bouncycastle.math.ec.endo.ECEndomorphism;
-import org.bouncycastle.math.ec.endo.GLVEndomorphism;
-import org.bouncycastle.math.field.FiniteField;
-import org.bouncycastle.math.field.FiniteFields;
-import org.bouncycastle.util.BigIntegers;
-import org.bouncycastle.util.Integers;
-
-/**
- * base class for an elliptic curve
- */
-public abstract class ECCurve
-{
- 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 ECEndomorphism endomorphism;
- protected ECMultiplier multiplier;
-
- Config(int coord, ECEndomorphism endomorphism, ECMultiplier multiplier)
- {
- this.coord = coord;
- this.endomorphism = endomorphism;
- this.multiplier = multiplier;
- }
-
- public Config setCoordinateSystem(int coord)
- {
- this.coord = coord;
- return this;
- }
-
- public Config setEndomorphism(ECEndomorphism endomorphism)
- {
- this.endomorphism = endomorphism;
- 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.endomorphism = endomorphism;
- c.multiplier = multiplier;
-
- return c;
- }
- }
-
- protected FiniteField field;
- protected ECFieldElement a, b;
- protected BigInteger order, cofactor;
-
- protected int coord = COORD_AFFINE;
- protected ECEndomorphism endomorphism = null;
- protected ECMultiplier multiplier = null;
-
- protected ECCurve(FiniteField field)
- {
- this.field = field;
- }
-
- public abstract int getFieldSize();
-
- public abstract ECFieldElement fromBigInteger(BigInteger x);
-
- public Config configure()
- {
- return new Config(this.coord, this.endomorphism, this.multiplier);
- }
-
- public ECPoint validatePoint(BigInteger x, BigInteger y)
- {
- ECPoint p = createPoint(x, y);
- if (!p.isValid())
- {
- throw new IllegalArgumentException("Invalid point coordinates");
- }
- return p;
- }
-
- /**
- * @deprecated per-point compression property will be removed, use {@link #validatePoint(BigInteger, BigInteger)}
- * and refer {@link ECPoint#getEncoded(boolean)}
- */
- public ECPoint validatePoint(BigInteger x, BigInteger y, boolean withCompression)
- {
- ECPoint p = createPoint(x, y, withCompression);
- if (!p.isValid())
- {
- throw new IllegalArgumentException("Invalid point coordinates");
- }
- return p;
- }
-
- public ECPoint createPoint(BigInteger x, BigInteger y)
- {
- 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 abstract ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression);
-
- protected ECMultiplier createDefaultMultiplier()
- {
- if (endomorphism instanceof GLVEndomorphism)
- {
- return new GLVMultiplier(this, (GLVEndomorphism)endomorphism);
- }
-
- return new WNafL2RMultiplier();
- }
-
- public boolean supportsCoordinateSystem(int coord)
- {
- return coord == COORD_AFFINE;
- }
-
- public PreCompInfo getPreCompInfo(ECPoint point, String name)
- {
- checkPoint(point);
- synchronized (point)
- {
- Hashtable table = point.preCompTable;
- return table == null ? null : (PreCompInfo)table.get(name);
- }
- }
-
- /**
- * Adds <code>PreCompInfo</code> for a point on this curve, under a given name. Used by
- * <code>ECMultiplier</code>s to save the precomputation for this <code>ECPoint</code> for use
- * by subsequent multiplication.
- *
- * @param point
- * The <code>ECPoint</code> to store precomputations for.
- * @param name
- * A <code>String</code> used to index precomputations of different types.
- * @param preCompInfo
- * The values precomputed by the <code>ECMultiplier</code>.
- */
- public void setPreCompInfo(ECPoint point, String name, PreCompInfo preCompInfo)
- {
- checkPoint(point);
- synchronized (point)
- {
- Hashtable table = point.preCompTable;
- if (null == table)
- {
- point.preCompTable = table = new Hashtable(4);
- }
- table.put(name, 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 validatePoint(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.montgomeryTrick(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();
-
- public FiniteField getField()
- {
- return field;
- }
-
- public ECFieldElement getA()
- {
- return a;
- }
-
- public ECFieldElement getB()
- {
- return b;
- }
-
- public BigInteger getOrder()
- {
- return order;
- }
-
- public BigInteger getCofactor()
- {
- return cofactor;
- }
-
- public int getCoordinateSystem()
- {
- return coord;
- }
-
- protected abstract ECPoint decompressPoint(int yTilde, BigInteger X1);
-
- public ECEndomorphism getEndomorphism()
- {
- return endomorphism;
- }
-
- /**
- * Sets the default <code>ECMultiplier</code>, unless already set.
- */
- public synchronized 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).
- * @return The decoded point.
- */
- public ECPoint decodePoint(byte[] encoded)
- {
- ECPoint p = null;
- int expectedLength = (getFieldSize() + 7) / 8;
-
- byte type = encoded[0];
- switch (type)
- {
- case 0x00: // infinity
- {
- if (encoded.length != 1)
- {
- throw new IllegalArgumentException("Incorrect length for infinity encoding");
- }
-
- p = getInfinity();
- break;
- }
- case 0x02: // compressed
- case 0x03: // compressed
- {
- if (encoded.length != (expectedLength + 1))
- {
- throw new IllegalArgumentException("Incorrect length for compressed encoding");
- }
-
- int yTilde = type & 1;
- BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength);
-
- p = decompressPoint(yTilde, X);
- if (!p.satisfiesCofactor())
- {
- throw new IllegalArgumentException("Invalid point");
- }
-
- break;
- }
- case 0x04: // uncompressed
- {
- if (encoded.length != (2 * expectedLength + 1))
- {
- throw new IllegalArgumentException("Incorrect length for uncompressed encoding");
- }
-
- BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength);
- BigInteger Y = BigIntegers.fromUnsignedByteArray(encoded, 1 + expectedLength, expectedLength);
-
- p = validatePoint(X, Y);
- break;
- }
- case 0x06: // hybrid
- case 0x07: // hybrid
- {
- if (encoded.length != (2 * expectedLength + 1))
- {
- throw new IllegalArgumentException("Incorrect length for hybrid encoding");
- }
-
- BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength);
- BigInteger Y = BigIntegers.fromUnsignedByteArray(encoded, 1 + expectedLength, expectedLength);
-
- if (Y.testBit(0) != (type == 0x07))
- {
- throw new IllegalArgumentException("Inconsistent Y coordinate in hybrid encoding");
- }
-
- p = validatePoint(X, Y);
- break;
- }
- default:
- throw new IllegalArgumentException("Invalid point encoding 0x" + Integer.toString(type, 16));
- }
-
- if (type != 0x00 && p.isInfinity())
- {
- throw new IllegalArgumentException("Invalid infinity encoding");
- }
-
- return p;
- }
-
- protected void checkPoint(ECPoint point)
- {
- 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");
- }
- }
- }
-
- public boolean equals(ECCurve other)
- {
- return this == other
- || (null != other
- && getField().equals(other.getField())
- && getA().toBigInteger().equals(other.getA().toBigInteger())
- && getB().toBigInteger().equals(other.getB().toBigInteger()));
- }
-
- public boolean equals(Object obj)
- {
- return this == obj || (obj instanceof ECCurve && equals((ECCurve)obj));
- }
-
- public int hashCode()
- {
- return getField().hashCode()
- ^ Integers.rotateLeft(getA().toBigInteger().hashCode(), 8)
- ^ Integers.rotateLeft(getB().toBigInteger().hashCode(), 16);
- }
-
- public static abstract class AbstractFp extends ECCurve
- {
- protected AbstractFp(BigInteger q)
- {
- super(FiniteFields.getPrimeField(q));
- }
-
- protected ECPoint decompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = this.fromBigInteger(X1);
- ECFieldElement rhs = x.square().add(a).multiply(x).add(b);
- ECFieldElement y = rhs.sqrt();
-
- /*
- * If y is not a square, then we haven't got a point on the curve
- */
- if (y == null)
- {
- throw new IllegalArgumentException("Invalid point compression");
- }
-
- if (y.testBitZero() != (yTilde == 1))
- {
- // Use the other root
- y = y.negate();
- }
-
- return this.createRawPoint(x, y, true);
- }
- }
-
- /**
- * Elliptic curve over Fp
- */
- public static class Fp extends AbstractFp
- {
- 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, a, b, null, null);
- }
-
- public Fp(BigInteger q, BigInteger a, BigInteger b, BigInteger order, BigInteger cofactor)
- {
- super(q);
-
- this.q = q;
- this.r = ECFieldElement.Fp.calculateResidue(q);
- this.infinity = new ECPoint.Fp(this, null, null);
-
- this.a = fromBigInteger(a);
- this.b = fromBigInteger(b);
- this.order = order;
- this.cofactor = cofactor;
- this.coord = FP_DEFAULT_COORDS;
- }
-
- protected Fp(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b)
- {
- this(q, r, a, b, null, null);
- }
-
- protected Fp(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b, BigInteger order, BigInteger cofactor)
- {
- super(q);
-
- this.q = q;
- this.r = r;
- this.infinity = new ECPoint.Fp(this, null, null);
-
- this.a = a;
- this.b = b;
- this.order = order;
- this.cofactor = cofactor;
- this.coord = FP_DEFAULT_COORDS;
- }
-
- protected ECCurve cloneCurve()
- {
- return new Fp(q, r, a, b, order, cofactor);
- }
-
- 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()
- {
- return q;
- }
-
- public int getFieldSize()
- {
- return q.bitLength();
- }
-
- public ECFieldElement fromBigInteger(BigInteger x)
- {
- return new ECFieldElement.Fp(this.q, this.r, x);
- }
-
- protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- return new ECPoint.Fp(this, x, y, withCompression);
- }
-
- protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
- {
- return new ECPoint.Fp(this, x, y, zs, withCompression);
- }
-
- public ECPoint importPoint(ECPoint p)
- {
- if (this != p.getCurve() && this.getCoordinateSystem() == COORD_JACOBIAN && !p.isInfinity())
- {
- 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);
- }
-
- public ECPoint getInfinity()
- {
- return infinity;
- }
- }
-
- public static abstract class AbstractF2m extends ECCurve
- {
- private static FiniteField buildField(int m, int k1, int k2, int k3)
- {
- if (k1 == 0)
- {
- throw new IllegalArgumentException("k1 must be > 0");
- }
-
- if (k2 == 0)
- {
- if (k3 != 0)
- {
- throw new IllegalArgumentException("k3 must be 0 if k2 == 0");
- }
-
- return FiniteFields.getBinaryExtensionField(new int[]{ 0, k1, m });
- }
-
- if (k2 <= k1)
- {
- throw new IllegalArgumentException("k2 must be > k1");
- }
-
- if (k3 <= k2)
- {
- throw new IllegalArgumentException("k3 must be > k2");
- }
-
- return FiniteFields.getBinaryExtensionField(new int[]{ 0, k1, k2, k3, m });
- }
-
- protected AbstractF2m(int m, int k1, int k2, int k3)
- {
- super(buildField(m, k1, k2, k3));
- }
- }
-
- /**
- * Elliptic curves over F2m. The Weierstrass equation is given by
- * <code>y<sup>2</sup> + xy = x<sup>3</sup> + ax<sup>2</sup> + b</code>.
- */
- public static class F2m extends AbstractF2m
- {
- private static final int F2M_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
-
- /**
- * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
- */
- private int m; // can't be final - JDK 1.1
-
- /**
- * TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
- * x<sup>k</sup> + 1</code> represents the reduction polynomial
- * <code>f(z)</code>.<br>
- * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.<br>
- */
- private int k1; // can't be final - JDK 1.1
-
- /**
- * TPB: Always set to <code>0</code><br>
- * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.<br>
- */
- private int k2; // can't be final - JDK 1.1
-
- /**
- * TPB: Always set to <code>0</code><br>
- * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.<br>
- */
- private int k3; // can't be final - JDK 1.1
-
- /**
- * The point at infinity on this curve.
- */
- private ECPoint.F2m infinity; // can't be final - JDK 1.1
-
- /**
- * The parameter <code>&mu;</code> of the elliptic curve if this is
- * a Koblitz curve.
- */
- private byte mu = 0;
-
- /**
- * The auxiliary values <code>s<sub>0</sub></code> and
- * <code>s<sub>1</sub></code> used for partial modular reduction for
- * Koblitz curves.
- */
- private BigInteger[] si = null;
-
- /**
- * Constructor for Trinomial Polynomial Basis (TPB).
- * @param m The exponent <code>m</code> of
- * <code>F<sub>2<sup>m</sup></sub></code>.
- * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
- * x<sup>k</sup> + 1</code> represents the reduction
- * polynomial <code>f(z)</code>.
- * @param a The coefficient <code>a</code> in the Weierstrass equation
- * for non-supersingular elliptic curves over
- * <code>F<sub>2<sup>m</sup></sub></code>.
- * @param b The coefficient <code>b</code> in the Weierstrass equation
- * for non-supersingular elliptic curves over
- * <code>F<sub>2<sup>m</sup></sub></code>.
- */
- public F2m(
- int m,
- int k,
- BigInteger a,
- BigInteger b)
- {
- this(m, k, 0, 0, a, b, null, null);
- }
-
- /**
- * Constructor for Trinomial Polynomial Basis (TPB).
- * @param m The exponent <code>m</code> of
- * <code>F<sub>2<sup>m</sup></sub></code>.
- * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
- * x<sup>k</sup> + 1</code> represents the reduction
- * polynomial <code>f(z)</code>.
- * @param a The coefficient <code>a</code> in the Weierstrass equation
- * for non-supersingular elliptic curves over
- * <code>F<sub>2<sup>m</sup></sub></code>.
- * @param b The coefficient <code>b</code> in the Weierstrass equation
- * for non-supersingular elliptic curves over
- * <code>F<sub>2<sup>m</sup></sub></code>.
- * @param order The order of the main subgroup of the elliptic curve.
- * @param cofactor The cofactor of the elliptic curve, i.e.
- * <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>.
- */
- public F2m(
- int m,
- int k,
- BigInteger a,
- BigInteger b,
- BigInteger order,
- BigInteger cofactor)
- {
- this(m, k, 0, 0, a, b, order, cofactor);
- }
-
- /**
- * Constructor for Pentanomial Polynomial Basis (PPB).
- * @param m The exponent <code>m</code> of
- * <code>F<sub>2<sup>m</sup></sub></code>.
- * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.
- * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.
- * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.
- * @param a The coefficient <code>a</code> in the Weierstrass equation
- * for non-supersingular elliptic curves over
- * <code>F<sub>2<sup>m</sup></sub></code>.
- * @param b The coefficient <code>b</code> in the Weierstrass equation
- * for non-supersingular elliptic curves over
- * <code>F<sub>2<sup>m</sup></sub></code>.
- */
- public F2m(
- int m,
- int k1,
- int k2,
- int k3,
- BigInteger a,
- BigInteger b)
- {
- this(m, k1, k2, k3, a, b, null, null);
- }
-
- /**
- * Constructor for Pentanomial Polynomial Basis (PPB).
- * @param m The exponent <code>m</code> of
- * <code>F<sub>2<sup>m</sup></sub></code>.
- * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.
- * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.
- * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.
- * @param a The coefficient <code>a</code> in the Weierstrass equation
- * for non-supersingular elliptic curves over
- * <code>F<sub>2<sup>m</sup></sub></code>.
- * @param b The coefficient <code>b</code> in the Weierstrass equation
- * for non-supersingular elliptic curves over
- * <code>F<sub>2<sup>m</sup></sub></code>.
- * @param order The order of the main subgroup of the elliptic curve.
- * @param cofactor The cofactor of the elliptic curve, i.e.
- * <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>.
- */
- public F2m(
- int m,
- int k1,
- int k2,
- int k3,
- BigInteger a,
- BigInteger b,
- BigInteger order,
- BigInteger cofactor)
- {
- super(m, k1, k2, k3);
-
- this.m = m;
- this.k1 = k1;
- this.k2 = k2;
- this.k3 = k3;
- this.order = order;
- this.cofactor = cofactor;
-
- 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 order, BigInteger cofactor)
- {
- super(m, k1, k2, k3);
-
- this.m = m;
- this.k1 = k1;
- this.k2 = k2;
- this.k3 = k3;
- this.order = order;
- this.cofactor = cofactor;
-
- 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, order, cofactor);
- }
-
- 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()
- {
- return m;
- }
-
- public ECFieldElement fromBigInteger(BigInteger x)
- {
- return new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, x);
- }
-
- public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression)
- {
- ECFieldElement X = fromBigInteger(x), Y = fromBigInteger(y);
-
- switch (this.getCoordinateSystem())
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- if (X.isZero())
- {
- if (!Y.square().equals(this.getB()))
- {
- throw new IllegalArgumentException();
- }
- }
- else
- {
- // Y becomes Lambda (X + Y/X) here
- Y = Y.divide(X).add(X);
- }
- break;
- }
- default:
- {
- break;
- }
- }
-
- return createRawPoint(X, Y, withCompression);
- }
-
- protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- return new ECPoint.F2m(this, x, y, withCompression);
- }
-
- protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
- {
- return new ECPoint.F2m(this, x, y, zs, withCompression);
- }
-
- public ECPoint getInfinity()
- {
- return infinity;
- }
-
- /**
- * Returns true if this is a Koblitz curve (ABC curve).
- * @return true if this is a Koblitz curve (ABC curve), false otherwise
- */
- public boolean isKoblitz()
- {
- return order != null && cofactor != null && b.isOne() && (a.isZero() || a.isOne());
- }
-
- /**
- * Returns the parameter <code>&mu;</code> of the elliptic curve.
- * @return <code>&mu;</code> of the elliptic curve.
- * @throws IllegalArgumentException if the given ECCurve is not a
- * Koblitz curve.
- */
- synchronized byte getMu()
- {
- if (mu == 0)
- {
- mu = Tnaf.getMu(this);
- }
- return mu;
- }
-
- /**
- * @return the auxiliary values <code>s<sub>0</sub></code> and
- * <code>s<sub>1</sub></code> used for partial modular reduction for
- * Koblitz curves.
- */
- synchronized BigInteger[] getSi()
- {
- if (si == null)
- {
- si = Tnaf.getSi(this);
- }
- return si;
- }
-
- /**
- * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
- *
- * @param yTilde
- * ~yp, an indication bit for the decompression of yp.
- * @param X1
- * The field element xp.
- * @return the decompressed point.
- */
- protected ECPoint decompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = fromBigInteger(X1), y = null;
- if (x.isZero())
- {
- y = b.sqrt();
- }
- else
- {
- ECFieldElement beta = x.square().invert().multiply(b).add(a).add(x);
- ECFieldElement z = solveQuadraticEquation(beta);
- if (z != null)
- {
- if (z.testBitZero() != (yTilde == 1))
- {
- z = z.addOne();
- }
-
- switch (this.getCoordinateSystem())
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- y = z.add(x);
- break;
- }
- default:
- {
- y = z.multiply(x);
- break;
- }
- }
- }
- }
-
- if (y == null)
- {
- throw new IllegalArgumentException("Invalid point compression");
- }
-
- return this.createRawPoint(x, y, true);
- }
-
- /**
- * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
- * D.1.6) The other solution is <code>z + 1</code>.
- *
- * @param beta
- * The value to solve the quadratic equation for.
- * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
- * <code>null</code> if no solution exists.
- */
- private ECFieldElement solveQuadraticEquation(ECFieldElement beta)
- {
- if (beta.isZero())
- {
- return beta;
- }
-
- ECFieldElement zeroElement = fromBigInteger(ECConstants.ZERO);
-
- ECFieldElement z = null;
- ECFieldElement gamma = null;
-
- Random rand = new Random();
- do
- {
- ECFieldElement t = fromBigInteger(new BigInteger(m, rand));
- z = zeroElement;
- ECFieldElement w = beta;
- for (int i = 1; i <= m - 1; i++)
- {
- ECFieldElement w2 = w.square();
- z = z.square().add(w2.multiply(t));
- w = w2.add(beta);
- }
- if (!w.isZero())
- {
- return null;
- }
- gamma = z.square().add(z);
- }
- while (gamma.isZero());
-
- return z;
- }
-
- public int getM()
- {
- return m;
- }
-
- /**
- * Return true if curve uses a Trinomial basis.
- *
- * @return true if curve Trinomial, false otherwise.
- */
- public boolean isTrinomial()
- {
- return k2 == 0 && k3 == 0;
- }
-
- public int getK1()
- {
- return k1;
- }
-
- public int getK2()
- {
- return k2;
- }
-
- public int getK3()
- {
- return k3;
- }
-
- /**
- * @deprecated use {@link #getOrder()} instead
- */
- public BigInteger getN()
- {
- return order;
- }
-
- /**
- * @deprecated use {@link #getCofactor()} instead
- */
- public BigInteger getH()
- {
- return cofactor;
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java b/core/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java
deleted file mode 100644
index 59438826..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java
+++ /dev/null
@@ -1,868 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-import java.util.Random;
-
-import org.bouncycastle.math.raw.Mod;
-import org.bouncycastle.math.raw.Nat;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.BigIntegers;
-
-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);
- public abstract ECFieldElement negate();
- public abstract ECFieldElement square();
- public abstract ECFieldElement invert();
- public abstract ECFieldElement sqrt();
-
- public int bitLength()
- {
- return toBigInteger().bitLength();
- }
-
- public boolean isOne()
- {
- return bitLength() == 1;
- }
-
- public boolean isZero()
- {
- return 0 == toBigInteger().signum();
- }
-
- public ECFieldElement multiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
- {
- return multiply(b).subtract(x.multiply(y));
- }
-
- public ECFieldElement multiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
- {
- return multiply(b).add(x.multiply(y));
- }
-
- public ECFieldElement squareMinusProduct(ECFieldElement x, ECFieldElement y)
- {
- return square().subtract(x.multiply(y));
- }
-
- public ECFieldElement squarePlusProduct(ECFieldElement x, ECFieldElement y)
- {
- return square().add(x.multiply(y));
- }
-
- public boolean testBitZero()
- {
- return toBigInteger().testBit(0);
- }
-
- public String toString()
- {
- return this.toBigInteger().toString(16);
- }
-
- public byte[] getEncoded()
- {
- return BigIntegers.asUnsignedByteArray((getFieldSize() + 7) / 8, toBigInteger());
- }
-
- public static class Fp extends ECFieldElement
- {
- BigInteger q, r, x;
-
- static BigInteger calculateResidue(BigInteger p)
- {
- int bitLength = p.bitLength();
- if (bitLength >= 96)
- {
- 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(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 invalid in Fp field element");
- }
-
- this.q = q;
- this.r = r;
- this.x = x;
- }
-
- public BigInteger toBigInteger()
- {
- return x;
- }
-
- /**
- * return the field name for this field.
- *
- * @return the string "Fp".
- */
- public String getFieldName()
- {
- return "Fp";
- }
-
- public int getFieldSize()
- {
- return q.bitLength();
- }
-
- public BigInteger getQ()
- {
- return q;
- }
-
- public ECFieldElement add(ECFieldElement b)
- {
- return new Fp(q, 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, r, modSubtract(x, b.toBigInteger()));
- }
-
- public ECFieldElement multiply(ECFieldElement b)
- {
- return new Fp(q, r, modMult(x, b.toBigInteger()));
- }
-
- public ECFieldElement multiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
- {
- BigInteger ax = this.x, bx = b.toBigInteger(), xx = x.toBigInteger(), yx = y.toBigInteger();
- BigInteger ab = ax.multiply(bx);
- BigInteger xy = xx.multiply(yx);
- return new Fp(q, r, modReduce(ab.subtract(xy)));
- }
-
- public ECFieldElement multiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
- {
- BigInteger ax = this.x, bx = b.toBigInteger(), xx = x.toBigInteger(), yx = y.toBigInteger();
- BigInteger ab = ax.multiply(bx);
- BigInteger xy = xx.multiply(yx);
- return new Fp(q, r, modReduce(ab.add(xy)));
- }
-
- public ECFieldElement divide(ECFieldElement b)
- {
- return new Fp(q, r, modMult(x, modInverse(b.toBigInteger())));
- }
-
- public ECFieldElement negate()
- {
- return x.signum() == 0 ? this : new Fp(q, r, q.subtract(x));
- }
-
- public ECFieldElement square()
- {
- return new Fp(q, r, modMult(x, x));
- }
-
- public ECFieldElement squareMinusProduct(ECFieldElement x, ECFieldElement y)
- {
- BigInteger ax = this.x, xx = x.toBigInteger(), yx = y.toBigInteger();
- BigInteger aa = ax.multiply(ax);
- BigInteger xy = xx.multiply(yx);
- return new Fp(q, r, modReduce(aa.subtract(xy)));
- }
-
- public ECFieldElement squarePlusProduct(ECFieldElement x, ECFieldElement y)
- {
- BigInteger ax = this.x, xx = x.toBigInteger(), yx = y.toBigInteger();
- BigInteger aa = ax.multiply(ax);
- BigInteger xy = xx.multiply(yx);
- return new Fp(q, r, modReduce(aa.add(xy)));
- }
-
- public ECFieldElement invert()
- {
- // TODO Modular inversion can be faster for a (Generalized) Mersenne Prime.
- return new Fp(q, r, modInverse(x));
- }
-
- // D.1.4 91
- /**
- * return a sqrt root - the routine verifies that the calculation
- * returns the right value - if none exists it returns null.
- */
- public ECFieldElement sqrt()
- {
- if (this.isZero() || this.isOne()) // earlier JDK compatibility
- {
- return this;
- }
-
- if (!q.testBit(0))
- {
- throw new RuntimeException("not done yet");
- }
-
- // note: even though this class implements ECConstants don't be tempted to
- // remove the explicit declaration, some J2ME environments don't cope.
-
- if (q.testBit(1)) // q == 4m + 3
- {
- BigInteger e = q.shiftRight(2).add(ECConstants.ONE);
- return checkSqrt(new Fp(q, r, x.modPow(e, q)));
- }
-
- if (q.testBit(2)) // q == 8m + 5
- {
- BigInteger t1 = x.modPow(q.shiftRight(3), q);
- BigInteger t2 = modMult(t1, x);
- BigInteger t3 = modMult(t2, t1);
-
- if (t3.equals(ECConstants.ONE))
- {
- return checkSqrt(new Fp(q, r, t2));
- }
-
- // TODO This is constant and could be precomputed
- BigInteger t4 = ECConstants.TWO.modPow(q.shiftRight(2), q);
-
- BigInteger y = modMult(t2, t4);
-
- return checkSqrt(new Fp(q, r, y));
- }
-
- // q == 8m + 1
-
- BigInteger legendreExponent = q.shiftRight(1);
- if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE)))
- {
- return null;
- }
-
- BigInteger X = this.x;
- BigInteger fourX = modDouble(modDouble(X));
-
- BigInteger k = legendreExponent.add(ECConstants.ONE), qMinusOne = q.subtract(ECConstants.ONE);
-
- BigInteger U, V;
- Random rand = new Random();
- do
- {
- BigInteger P;
- do
- {
- P = new BigInteger(q.bitLength(), rand);
- }
- while (P.compareTo(q) >= 0
- || !modReduce(P.multiply(P).subtract(fourX)).modPow(legendreExponent, q).equals(qMinusOne));
-
- BigInteger[] result = lucasSequence(P, X, k);
- U = result[0];
- V = result[1];
-
- if (modMult(V, V).equals(fourX))
- {
- return new ECFieldElement.Fp(q, r, modHalfAbs(V));
- }
- }
- while (U.equals(ECConstants.ONE) || U.equals(qMinusOne));
-
- return null;
- }
-
- private ECFieldElement checkSqrt(ECFieldElement z)
- {
- return z.square().equals(this) ? z : null;
- }
-
- private BigInteger[] lucasSequence(
- BigInteger P,
- BigInteger Q,
- BigInteger k)
- {
- // TODO Research and apply "common-multiplicand multiplication here"
-
- int n = k.bitLength();
- int s = k.getLowestSetBit();
-
- // assert k.testBit(s);
-
- BigInteger Uh = ECConstants.ONE;
- BigInteger Vl = ECConstants.TWO;
- BigInteger Vh = P;
- BigInteger Ql = ECConstants.ONE;
- BigInteger Qh = ECConstants.ONE;
-
- for (int j = n - 1; j >= s + 1; --j)
- {
- Ql = modMult(Ql, Qh);
-
- if (k.testBit(j))
- {
- 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 = 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 = 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 = 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 modHalf(BigInteger x)
- {
- if (x.testBit(0))
- {
- x = q.add(x);
- }
- return x.shiftRight(1);
- }
-
- protected BigInteger modHalfAbs(BigInteger x)
- {
- if (x.testBit(0))
- {
- x = q.subtract(x);
- }
- return x.shiftRight(1);
- }
-
- protected BigInteger modInverse(BigInteger x)
- {
- int bits = getFieldSize();
- int len = (bits + 31) >> 5;
- int[] p = Nat.fromBigInteger(bits, q);
- int[] n = Nat.fromBigInteger(bits, x);
- int[] z = Nat.create(len);
- Mod.invert(p, n, z);
- return Nat.toBigInteger(len, z);
- }
-
- protected BigInteger modMult(BigInteger x1, BigInteger x2)
- {
- return modReduce(x1.multiply(x2));
- }
-
- protected BigInteger modReduce(BigInteger x)
- {
- if (r != null)
- {
- boolean negative = x.signum() < 0;
- if (negative)
- {
- x = x.abs();
- }
- int qLen = q.bitLength();
- boolean rIsOne = r.equals(ECConstants.ONE);
- while (x.bitLength() > (qLen + 1))
- {
- BigInteger u = x.shiftRight(qLen);
- BigInteger v = x.subtract(u.shiftLeft(qLen));
- if (!rIsOne)
- {
- u = u.multiply(r);
- }
- x = u.add(v);
- }
- while (x.compareTo(q) >= 0)
- {
- x = x.subtract(q);
- }
- if (negative && x.signum() != 0)
- {
- x = q.subtract(x);
- }
- }
- else
- {
- x = x.mod(q);
- }
- return x;
- }
-
- protected BigInteger modSubtract(BigInteger x1, BigInteger x2)
- {
- BigInteger x3 = x1.subtract(x2);
- if (x3.signum() < 0)
- {
- x3 = x3.add(q);
- }
- return x3;
- }
-
- public boolean equals(Object other)
- {
- if (other == this)
- {
- return true;
- }
-
- if (!(other instanceof ECFieldElement.Fp))
- {
- return false;
- }
-
- ECFieldElement.Fp o = (ECFieldElement.Fp)other;
- return q.equals(o.q) && x.equals(o.x);
- }
-
- public int hashCode()
- {
- return q.hashCode() ^ x.hashCode();
- }
- }
-
- /**
- * Class representing the Elements of the finite field
- * <code>F<sub>2<sup>m</sup></sub></code> in polynomial basis (PB)
- * representation. Both trinomial (TPB) and pentanomial (PPB) polynomial
- * basis representations are supported. Gaussian normal basis (GNB)
- * representation is not supported.
- */
- public static class F2m extends ECFieldElement
- {
- /**
- * Indicates gaussian normal basis representation (GNB). Number chosen
- * according to X9.62. GNB is not implemented at present.
- */
- public static final int GNB = 1;
-
- /**
- * Indicates trinomial basis representation (TPB). Number chosen
- * according to X9.62.
- */
- public static final int TPB = 2;
-
- /**
- * Indicates pentanomial basis representation (PPB). Number chosen
- * according to X9.62.
- */
- public static final int PPB = 3;
-
- /**
- * TPB or PPB.
- */
- private int representation;
-
- /**
- * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
- */
- private int m;
-
- private int[] ks;
-
- /**
- * The <code>LongArray</code> holding the bits.
- */
- private LongArray x;
-
- /**
- * Constructor for PPB.
- * @param m The exponent <code>m</code> of
- * <code>F<sub>2<sup>m</sup></sub></code>.
- * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.
- * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.
- * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.
- * @param x The BigInteger representing the value of the field element.
- * @deprecated Use ECCurve.fromBigInteger to construct field elements
- */
- public F2m(
- int m,
- int k1,
- int k2,
- int k3,
- BigInteger x)
- {
- if ((k2 == 0) && (k3 == 0))
- {
- this.representation = TPB;
- this.ks = new int[]{ k1 };
- }
- else
- {
- if (k2 >= k3)
- {
- throw new IllegalArgumentException(
- "k2 must be smaller than k3");
- }
- if (k2 <= 0)
- {
- throw new IllegalArgumentException(
- "k2 must be larger than 0");
- }
- this.representation = PPB;
- this.ks = new int[]{ k1, k2, k3 };
- }
-
- this.m = m;
- this.x = new LongArray(x);
- }
-
- /**
- * Constructor for TPB.
- * @param m The exponent <code>m</code> of
- * <code>F<sub>2<sup>m</sup></sub></code>.
- * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
- * x<sup>k</sup> + 1</code> represents the reduction
- * polynomial <code>f(z)</code>.
- * @param x The BigInteger representing the value of the field element.
- * @deprecated Use ECCurve.fromBigInteger to construct field elements
- */
- public F2m(int m, int k, BigInteger x)
- {
- // Set k1 to k, and set k2 and k3 to 0
- this(m, k, 0, 0, x);
- }
-
- private F2m(int m, int[] ks, LongArray x)
- {
- this.m = m;
- this.representation = (ks.length == 1) ? TPB : PPB;
- this.ks = ks;
- this.x = x;
- }
-
- public int bitLength()
- {
- return x.degree();
- }
-
- public boolean isOne()
- {
- return x.isOne();
- }
-
- public boolean isZero()
- {
- return x.isZero();
- }
-
- public boolean testBitZero()
- {
- return x.testBitZero();
- }
-
- public BigInteger toBigInteger()
- {
- return x.toBigInteger();
- }
-
- public String getFieldName()
- {
- return "F2m";
- }
-
- public int getFieldSize()
- {
- return m;
- }
-
- /**
- * Checks, if the ECFieldElements <code>a</code> and <code>b</code>
- * are elements of the same field <code>F<sub>2<sup>m</sup></sub></code>
- * (having the same representation).
- * @param a field element.
- * @param b field element to be compared.
- * @throws IllegalArgumentException if <code>a</code> and <code>b</code>
- * are not elements of the same field
- * <code>F<sub>2<sup>m</sup></sub></code> (having the same
- * representation).
- */
- public static void checkFieldElements(
- ECFieldElement a,
- ECFieldElement b)
- {
- if ((!(a instanceof F2m)) || (!(b instanceof F2m)))
- {
- throw new IllegalArgumentException("Field elements are not "
- + "both instances of ECFieldElement.F2m");
- }
-
- ECFieldElement.F2m aF2m = (ECFieldElement.F2m)a;
- ECFieldElement.F2m bF2m = (ECFieldElement.F2m)b;
-
- if (aF2m.representation != bF2m.representation)
- {
- // Should never occur
- throw new IllegalArgumentException("One of the F2m field elements has incorrect representation");
- }
-
- if ((aF2m.m != bF2m.m) || !Arrays.areEqual(aF2m.ks, bF2m.ks))
- {
- throw new IllegalArgumentException("Field elements are not elements of the same field F2m");
- }
- }
-
- public ECFieldElement add(final ECFieldElement b)
- {
- // No check performed here for performance reasons. Instead the
- // elements involved are checked in ECPoint.F2m
- // checkFieldElements(this, b);
- LongArray iarrClone = (LongArray)this.x.clone();
- F2m bF2m = (F2m)b;
- 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)
- {
- // Addition and subtraction are the same in F2m
- return add(b);
- }
-
- public ECFieldElement multiply(final ECFieldElement b)
- {
- // 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);
- return new F2m(m, ks, x.modMultiply(((F2m)b).x, m, ks));
- }
-
- public ECFieldElement multiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
- {
- return multiplyPlusProduct(b, x, y);
- }
-
- public ECFieldElement multiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
- {
- LongArray ax = this.x, bx = ((F2m)b).x, xx = ((F2m)x).x, yx = ((F2m)y).x;
-
- LongArray ab = ax.multiply(bx, m, ks);
- LongArray xy = xx.multiply(yx, m, ks);
-
- if (ab == ax || ab == bx)
- {
- ab = (LongArray)ab.clone();
- }
-
- ab.addShiftedByWords(xy, 0);
- ab.reduce(m, ks);
-
- return new F2m(m, ks, ab);
- }
-
- public ECFieldElement divide(final ECFieldElement b)
- {
- // There may be more efficient implementations
- ECFieldElement bInv = b.invert();
- return multiply(bInv);
- }
-
- public ECFieldElement negate()
- {
- // -x == x holds for all x in F2m
- return this;
- }
-
- public ECFieldElement square()
- {
- return new F2m(m, ks, x.modSquare(m, ks));
- }
-
- public ECFieldElement squareMinusProduct(ECFieldElement x, ECFieldElement y)
- {
- return squarePlusProduct(x, y);
- }
-
- public ECFieldElement squarePlusProduct(ECFieldElement x, ECFieldElement y)
- {
- LongArray ax = this.x, xx = ((F2m)x).x, yx = ((F2m)y).x;
-
- LongArray aa = ax.square(m, ks);
- LongArray xy = xx.multiply(yx, m, ks);
-
- if (aa == ax)
- {
- aa = (LongArray)aa.clone();
- }
-
- aa.addShiftedByWords(xy, 0);
- aa.reduce(m, ks);
-
- return new F2m(m, ks, aa);
- }
-
- public ECFieldElement invert()
- {
- return new ECFieldElement.F2m(this.m, this.ks, this.x.modInverse(m, ks));
- }
-
- public ECFieldElement sqrt()
- {
- LongArray x1 = this.x;
- if (x1.isOne() || x1.isZero())
- {
- return this;
- }
-
- LongArray x2 = x1.modSquareN(m - 1, m, ks);
- return new ECFieldElement.F2m(m, ks, x2);
- }
-
- /**
- * @return the representation of the field
- * <code>F<sub>2<sup>m</sup></sub></code>, either of
- * TPB (trinomial
- * basis representation) or
- * PPB (pentanomial
- * basis representation).
- */
- public int getRepresentation()
- {
- return this.representation;
- }
-
- /**
- * @return the degree <code>m</code> of the reduction polynomial
- * <code>f(z)</code>.
- */
- public int getM()
- {
- return this.m;
- }
-
- /**
- * @return TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
- * x<sup>k</sup> + 1</code> represents the reduction polynomial
- * <code>f(z)</code>.<br>
- * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.<br>
- */
- public int getK1()
- {
- return this.ks[0];
- }
-
- /**
- * @return TPB: Always returns <code>0</code><br>
- * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.<br>
- */
- public int getK2()
- {
- return this.ks.length >= 2 ? this.ks[1] : 0;
- }
-
- /**
- * @return TPB: Always set to <code>0</code><br>
- * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.<br>
- */
- public int getK3()
- {
- return this.ks.length >= 3 ? this.ks[2] : 0;
- }
-
- public boolean equals(Object anObject)
- {
- if (anObject == this)
- {
- return true;
- }
-
- if (!(anObject instanceof ECFieldElement.F2m))
- {
- return false;
- }
-
- ECFieldElement.F2m b = (ECFieldElement.F2m)anObject;
-
- return ((this.m == b.m)
- && (this.representation == b.representation)
- && Arrays.areEqual(this.ks, b.ks)
- && (this.x.equals(b.x)));
- }
-
- public int hashCode()
- {
- return x.hashCode() ^ m ^ Arrays.hashCode(ks);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/ECMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/ECMultiplier.java
deleted file mode 100644
index da1013a7..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/ECMultiplier.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-/**
- * Interface for classes encapsulating a point multiplication algorithm
- * for <code>ECPoint</code>s.
- */
-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> is multiplied.
- * @return <code>p</code> multiplied by <code>k</code>.
- */
- ECPoint multiply(ECPoint p, BigInteger k);
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java b/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java
deleted file mode 100644
index 7cd04e46..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/ECPoint.java
+++ /dev/null
@@ -1,2122 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-import java.util.Hashtable;
-
-/**
- * base class for points on elliptic curves.
- */
-public abstract class ECPoint
-{
- protected static ECFieldElement[] EMPTY_ZS = new ECFieldElement[0];
-
- protected static ECFieldElement[] getInitialZCoords(ECCurve curve)
- {
- // Cope with null curve, most commonly used by implicitlyCa
- int coord = null == curve ? ECCurve.COORD_AFFINE : curve.getCoordinateSystem();
-
- switch (coord)
- {
- case ECCurve.COORD_AFFINE:
- case ECCurve.COORD_LAMBDA_AFFINE:
- return EMPTY_ZS;
- default:
- break;
- }
-
- ECFieldElement one = curve.fromBigInteger(ECConstants.ONE);
-
- 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;
-
- // Hashtable is (String -> PreCompInfo)
- protected Hashtable preCompTable = 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;
- }
-
- protected boolean satisfiesCofactor()
- {
- BigInteger h = curve.getCofactor();
- return h == null || h.equals(ECConstants.ONE) || !ECAlgorithms.referenceMultiply(this, h).isInfinity();
- }
-
- protected abstract boolean satisfiesCurveEquation();
-
- public final ECPoint getDetachedPoint()
- {
- return normalize().detach();
- }
-
- public ECCurve getCurve()
- {
- return curve;
- }
-
- protected abstract ECPoint detach();
-
- protected int getCurveCoordinateSystem()
- {
- // Cope with null curve, most commonly used by implicitlyCa
- 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 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 final ECFieldElement getRawXCoord()
- {
- return x;
- }
-
- protected final ECFieldElement getRawYCoord()
- {
- return y;
- }
-
- protected final ECFieldElement[] getRawZCoords()
- {
- return zs;
- }
-
- 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].isOne();
- }
-
- /**
- * 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.isOne())
- {
- 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 || (zs.length > 0 && zs[0].isZero());
- }
-
- public boolean isCompressed()
- {
- return this.withCompression;
- }
-
- public boolean isValid()
- {
- if (isInfinity())
- {
- return true;
- }
-
- // TODO Sanity-check the field elements
-
- ECCurve curve = getCurve();
- if (curve != null)
- {
- if (!satisfiesCurveEquation())
- {
- return false;
- }
-
- if (!satisfiesCofactor())
- {
- return false;
- }
- }
-
- return true;
- }
-
- public ECPoint scaleX(ECFieldElement scale)
- {
- return isInfinity()
- ? this
- : getCurve().createRawPoint(getRawXCoord().multiply(scale), getRawYCoord(), getRawZCoords(), this.withCompression);
- }
-
- public ECPoint scaleY(ECFieldElement scale)
- {
- return isInfinity()
- ? this
- : getCurve().createRawPoint(getRawXCoord(), getRawYCoord().multiply(scale), getRawZCoords(), this.withCompression);
- }
-
- public boolean equals(ECPoint other)
- {
- if (null == other)
- {
- 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)
- {
- if (other == this)
- {
- return true;
- }
-
- if (!(other instanceof ECPoint))
- {
- return false;
- }
-
- return equals((ECPoint)other);
- }
-
- public int hashCode()
- {
- ECCurve c = this.getCurve();
- int hc = (null == c) ? 0 : ~c.hashCode();
-
- if (!this.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 hc;
- }
-
- public String toString()
- {
- if (this.isInfinity())
- {
- return "INF";
- }
-
- 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();
- }
-
- public byte[] getEncoded()
- {
- return getEncoded(this.withCompression);
- }
-
- /**
- * return the field element encoded with point compression. (S 4.3.6)
- */
- public byte[] getEncoded(boolean compressed)
- {
- if (this.isInfinity())
- {
- return new byte[1];
- }
-
- 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;
- }
-
- protected abstract boolean getCompressionYTilde();
-
- public abstract ECPoint add(ECPoint b);
-
- public abstract ECPoint negate();
-
- public abstract ECPoint subtract(ECPoint b);
-
- public ECPoint timesPow2(int e)
- {
- if (e < 0)
- {
- throw new IllegalArgumentException("'e' cannot be negative");
- }
-
- ECPoint p = this;
- while (--e >= 0)
- {
- p = p.twice();
- }
- return p;
- }
-
- public abstract ECPoint twice();
-
- public ECPoint twicePlus(ECPoint b)
- {
- return twice().add(b);
- }
-
- public ECPoint threeTimes()
- {
- return twicePlus(this);
- }
-
- /**
- * Multiplies this <code>ECPoint</code> by the given number.
- * @param k The multiplicator.
- * @return <code>k * this</code>.
- */
- public ECPoint multiply(BigInteger k)
- {
- return this.getCurve().getMultiplier().multiply(this, k);
- }
-
- public static abstract class AbstractFp extends ECPoint
- {
- protected AbstractFp(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- super(curve, x, y);
- }
-
- protected AbstractFp(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs)
- {
- super(curve, x, y, zs);
- }
-
- protected boolean getCompressionYTilde()
- {
- return this.getAffineYCoord().testBitZero();
- }
-
- protected boolean satisfiesCurveEquation()
- {
- ECFieldElement X = this.x, Y = this.y, A = curve.getA(), B = curve.getB();
- ECFieldElement lhs = Y.square();
-
- switch (this.getCurveCoordinateSystem())
- {
- case ECCurve.COORD_AFFINE:
- break;
- case ECCurve.COORD_HOMOGENEOUS:
- {
- ECFieldElement Z = this.zs[0];
- if (!Z.isOne())
- {
- ECFieldElement Z2 = Z.square(), Z3 = Z.multiply(Z2);
- lhs = lhs.multiply(Z);
- A = A.multiply(Z2);
- B = B.multiply(Z3);
- }
- break;
- }
- case ECCurve.COORD_JACOBIAN:
- case ECCurve.COORD_JACOBIAN_CHUDNOVSKY:
- case ECCurve.COORD_JACOBIAN_MODIFIED:
- {
- ECFieldElement Z = this.zs[0];
- if (!Z.isOne())
- {
- ECFieldElement Z2 = Z.square(), Z4 = Z2.square(), Z6 = Z2.multiply(Z4);
- A = A.multiply(Z4);
- B = B.multiply(Z6);
- }
- break;
- }
- default:
- throw new IllegalStateException("unsupported coordinate system");
- }
-
- ECFieldElement rhs = X.square().add(A).multiply(X).add(B);
- return lhs.equals(rhs);
- }
-
- public ECPoint subtract(ECPoint b)
- {
- if (b.isInfinity())
- {
- return this;
- }
-
- // Add -b
- return this.add(b.negate());
- }
- }
-
- /**
- * Elliptic curve points over Fp
- */
- public static class Fp extends AbstractFp
- {
- /**
- * Create a point which encodes without point compression.
- *
- * @param curve the curve to use
- * @param x affine x co-ordinate
- * @param y affine y co-ordinate
- *
- * @deprecated Use ECCurve.createPoint to construct points
- */
- public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- this(curve, x, y, false);
- }
-
- /**
- * Create a point that encodes with or without point compression.
- *
- * @param curve the curve to use
- * @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)
- {
- super(curve, x, y);
-
- if ((x == null) != (y == null))
- {
- throw new IllegalArgumentException("Exactly one of the field elements is null");
- }
-
- this.withCompression = withCompression;
- }
-
- Fp(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
- {
- super(curve, x, y, zs);
-
- this.withCompression = withCompression;
- }
-
- protected ECPoint detach()
- {
- return new ECPoint.Fp(null, this.getAffineXCoord(), this.getAffineYCoord());
- }
-
- public ECFieldElement getZCoord(int index)
- {
- if (index == 1 && ECCurve.COORD_JACOBIAN_MODIFIED == this.getCurveCoordinateSystem())
- {
- return getJacobianModifiedW();
- }
-
- return super.getZCoord(index);
- }
-
- // B.3 pg 62
- public ECPoint add(ECPoint b)
- {
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return this;
- }
- if (this == b)
- {
- return twice();
- }
-
- ECCurve curve = this.getCurve();
- 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())
- {
- 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();
- }
-
- 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.isOne();
- boolean Z2IsOne = Z2.isOne();
-
- 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())
- {
- 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).multiplyMinusProduct(u, u2, vCubed);
- 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.isOne();
-
- 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.isOne();
- 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();
- }
-
- ECFieldElement HSquared = H.square();
- ECFieldElement G = HSquared.multiply(H);
- ECFieldElement V = HSquared.multiply(U1);
-
- X3 = R.square().add(G).subtract(two(V));
- Y3 = V.subtract(X3).multiplyMinusProduct(R, G, S1);
-
- 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);
- }
-
- 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:
- {
- ECFieldElement Z1 = this.zs[0];
-
- boolean Z1IsOne = Z1.isOne();
-
- // TODO Optimize for small negative a4 and -3
- ECFieldElement w = curve.getA();
- if (!w.isZero() && !Z1IsOne)
- {
- w = w.multiply(Z1.square());
- }
- w = w.add(three(X1.square()));
-
- 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 _2s = two(s);
- ECFieldElement X3 = h.multiply(_2s);
- ECFieldElement _2t = two(t);
- ECFieldElement Y3 = _4B.subtract(h).multiply(w).subtract(two(_2t.square()));
- ECFieldElement _4sSquared = Z1IsOne ? two(_2t) : _2s.square();
- ECFieldElement Z3 = two(_4sSquared).multiply(s);
-
- return new ECPoint.Fp(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
- }
-
- case ECCurve.COORD_JACOBIAN:
- {
- ECFieldElement Z1 = this.zs[0];
-
- boolean Z1IsOne = Z1.isOne();
-
- 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)))
- {
- ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.square();
- 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 if (!a4.isZero())
- {
- ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.square();
- 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));
- S = four(X1.multiply(Y1Squared));
- }
-
- 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);
- }
-
- // 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");
- }
- }
- }
-
- public ECPoint twicePlus(ECPoint b)
- {
- if (this == b)
- {
- return threeTimes();
- }
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return twice();
- }
-
- ECFieldElement Y1 = this.y;
- if (Y1.isZero())
- {
- return b;
- }
-
- ECCurve curve = this.getCurve();
- int coord = curve.getCoordinateSystem();
-
- switch (coord)
- {
- case ECCurve.COORD_AFFINE:
- {
- ECFieldElement X1 = this.x;
- ECFieldElement X2 = b.x, Y2 = b.y;
-
- ECFieldElement dx = X2.subtract(X1), dy = Y2.subtract(Y1);
-
- if (dx.isZero())
- {
- if (dy.isZero())
- {
- // this == b i.e. the result is 3P
- return threeTimes();
- }
-
- // this == -b, i.e. the result is P
- return this;
- }
-
- /*
- * Optimized calculation of 2P + Q, as described in "Trading Inversions for
- * Multiplications in Elliptic Curve Cryptography", by Ciet, Joye, Lauter, Montgomery.
- */
-
- ECFieldElement X = dx.square(), Y = dy.square();
- ECFieldElement d = X.multiply(two(X1).add(X2)).subtract(Y);
- if (d.isZero())
- {
- return curve.getInfinity();
- }
-
- 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, X4, Y4, this.withCompression);
- }
- case ECCurve.COORD_JACOBIAN_MODIFIED:
- {
- return twiceJacobianModified(false).add(b);
- }
- default:
- {
- return twice().add(b);
- }
- }
- }
-
- public ECPoint threeTimes()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- ECFieldElement Y1 = this.y;
- if (Y1.isZero())
- {
- return this;
- }
-
- ECCurve curve = this.getCurve();
- int coord = curve.getCoordinateSystem();
-
- switch (coord)
- {
- case ECCurve.COORD_AFFINE:
- {
- ECFieldElement X1 = this.x;
-
- 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);
- }
- }
- }
-
- public ECPoint timesPow2(int e)
- {
- if (e < 0)
- {
- throw new IllegalArgumentException("'e' cannot be negative");
- }
- if (e == 0 || this.isInfinity())
- {
- return this;
- }
- if (e == 1)
- {
- return twice();
- }
-
- ECCurve curve = this.getCurve();
-
- ECFieldElement Y1 = this.y;
- if (Y1.isZero())
- {
- return curve.getInfinity();
- }
-
- int coord = curve.getCoordinateSystem();
-
- ECFieldElement W1 = curve.getA();
- ECFieldElement X1 = this.x;
- ECFieldElement Z1 = this.zs.length < 1 ? curve.fromBigInteger(ECConstants.ONE) : this.zs[0];
-
- if (!Z1.isOne())
- {
- switch (coord)
- {
- case ECCurve.COORD_HOMOGENEOUS:
- ECFieldElement Z1Sq = Z1.square();
- X1 = X1.multiply(Z1);
- Y1 = Y1.multiply(Z1Sq);
- W1 = calculateJacobianModifiedW(Z1, Z1Sq);
- break;
- case ECCurve.COORD_JACOBIAN:
- W1 = calculateJacobianModifiedW(Z1, null);
- break;
- case ECCurve.COORD_JACOBIAN_MODIFIED:
- W1 = getJacobianModifiedW();
- break;
- }
- }
-
- for (int i = 0; i < e; ++i)
- {
- if (Y1.isZero())
- {
- return curve.getInfinity();
- }
-
- ECFieldElement X1Squared = X1.square();
- ECFieldElement M = three(X1Squared);
- ECFieldElement _2Y1 = two(Y1);
- ECFieldElement _2Y1Squared = _2Y1.multiply(Y1);
- ECFieldElement S = two(X1.multiply(_2Y1Squared));
- ECFieldElement _4T = _2Y1Squared.square();
- ECFieldElement _8T = two(_4T);
-
- if (!W1.isZero())
- {
- M = M.add(W1);
- W1 = two(_8T.multiply(W1));
- }
-
- X1 = M.square().subtract(two(S));
- Y1 = M.multiply(S.subtract(X1)).subtract(_8T);
- Z1 = Z1.isOne() ? _2Y1 : _2Y1.multiply(Z1);
- }
-
- switch (coord)
- {
- case ECCurve.COORD_AFFINE:
- ECFieldElement zInv = Z1.invert(), zInv2 = zInv.square(), zInv3 = zInv2.multiply(zInv);
- return new Fp(curve, X1.multiply(zInv2), Y1.multiply(zInv3), this.withCompression);
- case ECCurve.COORD_HOMOGENEOUS:
- X1 = X1.multiply(Z1);
- Z1 = Z1.multiply(Z1.square());
- return new Fp(curve, X1, Y1, new ECFieldElement[]{ Z1 }, this.withCompression);
- case ECCurve.COORD_JACOBIAN:
- return new Fp(curve, X1, Y1, new ECFieldElement[]{ Z1 }, this.withCompression);
- case ECCurve.COORD_JACOBIAN_MODIFIED:
- return new Fp(curve, X1, Y1, new ECFieldElement[]{ Z1, W1 }, this.withCompression);
- default:
- throw new IllegalStateException("unsupported coordinate system");
- }
- }
-
- protected ECFieldElement two(ECFieldElement x)
- {
- return x.add(x);
- }
-
- protected ECFieldElement three(ECFieldElement x)
- {
- return two(x).add(x);
- }
-
- protected ECFieldElement four(ECFieldElement x)
- {
- return two(two(x));
- }
-
- protected ECFieldElement eight(ECFieldElement x)
- {
- return four(two(x));
- }
-
- protected ECFieldElement doubleProductFromSquares(ECFieldElement a, ECFieldElement b,
- ECFieldElement aSquared, ECFieldElement bSquared)
- {
- /*
- * NOTE: If squaring in the field is faster than multiplication, then this is a quicker
- * way to calculate 2.A.B, if A^2 and B^2 are already known.
- */
- return a.add(b).square().subtract(aSquared).subtract(bSquared);
- }
-
- public ECPoint negate()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- 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);
- }
-
- protected ECFieldElement calculateJacobianModifiedW(ECFieldElement Z, ECFieldElement ZSquared)
- {
- ECFieldElement a4 = this.getCurve().getA();
- if (a4.isZero() || Z.isOne())
- {
- return a4;
- }
-
- if (ZSquared == null)
- {
- ZSquared = Z.square();
- }
-
- ECFieldElement W = ZSquared.square();
- ECFieldElement a4Neg = a4.negate();
- if (a4Neg.bitLength() < a4.bitLength())
- {
- 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 _2Y1 = two(Y1);
- ECFieldElement _2Y1Squared = _2Y1.multiply(Y1);
- ECFieldElement S = two(X1.multiply(_2Y1Squared));
- ECFieldElement X3 = M.square().subtract(two(S));
- ECFieldElement _4T = _2Y1Squared.square();
- ECFieldElement _8T = two(_4T);
- ECFieldElement Y3 = M.multiply(S.subtract(X3)).subtract(_8T);
- ECFieldElement W3 = calculateW ? two(_8T.multiply(W1)) : null;
- ECFieldElement Z3 = Z1.isOne() ? _2Y1 : _2Y1.multiply(Z1);
-
- return new ECPoint.Fp(this.getCurve(), X3, Y3, new ECFieldElement[]{ Z3, W3 }, this.withCompression);
- }
- }
-
- public static abstract class AbstractF2m extends ECPoint
- {
- protected AbstractF2m(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- super(curve, x, y);
- }
-
- protected AbstractF2m(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs)
- {
- super(curve, x, y, zs);
- }
-
- protected boolean satisfiesCurveEquation()
- {
- ECCurve curve = this.getCurve();
- ECFieldElement X = this.x, A = curve.getA(), B = curve.getB();
-
- int coord = curve.getCoordinateSystem();
- if (coord == ECCurve.COORD_LAMBDA_PROJECTIVE)
- {
- ECFieldElement Z = this.zs[0];
- boolean ZIsOne = Z.isOne();
-
- if (X.isZero())
- {
- // NOTE: For x == 0, we expect the affine-y instead of the lambda-y
- ECFieldElement Y = this.y;
- ECFieldElement lhs = Y.square(), rhs = B;
- if (!ZIsOne)
- {
- rhs = rhs.multiply(Z.square());
- }
- return lhs.equals(rhs);
- }
-
- ECFieldElement L = this.y, X2 = X.square();
- ECFieldElement lhs, rhs;
- if (ZIsOne)
- {
- lhs = L.square().add(L).add(A);
- rhs = X2.square().add(B);
- }
- else
- {
- ECFieldElement Z2 = Z.square(), Z4 = Z2.square();
- lhs = L.add(Z).multiplyPlusProduct(L, A, Z2);
- // TODO If sqrt(b) is precomputed this can be simplified to a single square
- rhs = X2.squarePlusProduct(B, Z4);
- }
- lhs = lhs.multiply(X2);
- return lhs.equals(rhs);
- }
-
- ECFieldElement Y = this.y;
- ECFieldElement lhs = Y.add(X).multiply(Y);
-
- switch (coord)
- {
- case ECCurve.COORD_AFFINE:
- break;
- case ECCurve.COORD_HOMOGENEOUS:
- {
- ECFieldElement Z = this.zs[0];
- if (!Z.isOne())
- {
- ECFieldElement Z2 = Z.square(), Z3 = Z.multiply(Z2);
- lhs = lhs.multiply(Z);
- A = A.multiply(Z);
- B = B.multiply(Z3);
- }
- break;
- }
- default:
- throw new IllegalStateException("unsupported coordinate system");
- }
-
- ECFieldElement rhs = X.add(A).multiply(X.square()).add(B);
- return lhs.equals(rhs);
- }
- }
-
- /**
- * Elliptic curve points over F2m
- */
- public static class F2m extends AbstractF2m
- {
- /**
- * @param curve base curve
- * @param x x point
- * @param y y point
- *
- * @deprecated Use ECCurve.createPoint to construct points
- */
- public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- this(curve, x, y, false);
- }
-
- /**
- * @param curve base curve
- * @param x x point
- * @param y y point
- * @param withCompression true if encode with point compression.
- *
- * @deprecated per-point compression property will be removed, refer {@link #getEncoded(boolean)}
- */
- public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- super(curve, x, y);
-
- if ((x == null) != (y == null))
- {
- throw new IllegalArgumentException("Exactly one of the field elements is null");
- }
-
- 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();
- }
-
- F2m(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
- {
- super(curve, x, y, zs);
-
- this.withCompression = withCompression;
-
-// checkCurveEquation();
- }
-
- protected ECPoint detach()
- {
- return new ECPoint.F2m(null, this.getAffineXCoord(), this.getAffineYCoord()); // earlier JDK
- }
-
- public ECFieldElement getYCoord()
- {
- int coord = this.getCurveCoordinateSystem();
-
- switch (coord)
- {
- case ECCurve.COORD_LAMBDA_AFFINE:
- case ECCurve.COORD_LAMBDA_PROJECTIVE:
- {
- ECFieldElement X = x, L = y;
-
- if (this.isInfinity() || X.isZero())
- {
- return L;
- }
-
- // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
- ECFieldElement Y = L.add(X).multiply(X);
- if (ECCurve.COORD_LAMBDA_PROJECTIVE == coord)
- {
- ECFieldElement Z = zs[0];
- if (!Z.isOne())
- {
- Y = Y.divide(Z);
- }
- }
- return Y;
- }
- default:
- {
- return y;
- }
- }
- }
-
- public ECPoint scaleX(ECFieldElement scale)
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- int coord = this.getCurveCoordinateSystem();
-
- switch (coord)
- {
- case ECCurve.COORD_LAMBDA_AFFINE:
- {
- // Y is actually Lambda (X + Y/X) here
- ECFieldElement X = this.getRawXCoord(), L = this.getRawYCoord(); // earlier JDK
-
- ECFieldElement X2 = X.multiply(scale);
- ECFieldElement L2 = L.add(X).divide(scale).add(X2);
-
- return this.getCurve().createRawPoint(X, L2, this.getRawZCoords(), this.withCompression); // earlier JDK
- }
- case ECCurve.COORD_LAMBDA_PROJECTIVE:
- {
- // Y is actually Lambda (X + Y/X) here
- ECFieldElement X = this.getRawXCoord(), L = this.getRawYCoord(), Z = this.getRawZCoords()[0]; // earlier JDK
-
- // We scale the Z coordinate also, to avoid an inversion
- ECFieldElement X2 = X.multiply(scale.square());
- ECFieldElement L2 = L.add(X).add(X2);
- ECFieldElement Z2 = Z.multiply(scale);
-
- return this.getCurve().createRawPoint(X2, L2, new ECFieldElement[]{ Z2 }, this.withCompression); // earlier JDK
- }
- default:
- {
- return super.scaleX(scale);
- }
- }
- }
-
- public ECPoint scaleY(ECFieldElement scale)
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- int coord = this.getCurveCoordinateSystem();
-
- switch (coord)
- {
- case ECCurve.COORD_LAMBDA_AFFINE:
- case ECCurve.COORD_LAMBDA_PROJECTIVE:
- {
- ECFieldElement X = this.getRawXCoord(), L = this.getRawYCoord(); // earlier JDK
-
- // Y is actually Lambda (X + Y/X) here
- ECFieldElement L2 = L.add(X).multiply(scale).add(X);
-
- return this.getCurve().createRawPoint(X, L2, this.getRawZCoords(), this.withCompression); // earlier JDK
- }
- default:
- {
- return super.scaleY(scale);
- }
- }
- }
-
- protected boolean getCompressionYTilde()
- {
- ECFieldElement X = this.getRawXCoord();
- if (X.isZero())
- {
- return false;
- }
-
- 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.testBitZero() != X.testBitZero();
- }
- default:
- {
- return Y.divide(X).testBitZero();
- }
- }
- }
-
- /**
- * Check, if two <code>ECPoint</code>s can be added or subtracted.
- * @param a The first <code>ECPoint</code> to check.
- * @param b The second <code>ECPoint</code> to check.
- * @throws IllegalArgumentException if <code>a</code> and <code>b</code>
- * cannot be added.
- */
- private static void checkPoints(ECPoint a, ECPoint b)
- {
- // Check, if points are on the same curve
- if (a.curve != b.curve)
- {
- throw new IllegalArgumentException("Only points on the same "
- + "curve can be added or subtracted");
- }
-
-// ECFieldElement.F2m.checkFieldElements(a.x, b.x);
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.math.ec.ECPoint#add(org.bouncycastle.math.ec.ECPoint)
- */
- public ECPoint add(ECPoint b)
- {
- checkPoints(this, b);
- return addSimple((ECPoint.F2m)b);
- }
-
- /**
- * Adds another <code>ECPoints.F2m</code> to <code>this</code> without
- * checking if both points are on the same curve. Used by multiplication
- * algorithms, because there all points are a multiple of the same point
- * and hence the checks can be omitted.
- * @param b The other <code>ECPoints.F2m</code> to add to
- * <code>this</code>.
- * @return <code>this + b</code>
- */
- public ECPoint.F2m addSimple(ECPoint.F2m b)
- {
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return this;
- }
-
- 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;
-
- ECFieldElement dx = X1.add(X2), dy = Y1.add(Y2);
- if (dx.isZero())
- {
- if (dy.isZero())
- {
- return (ECPoint.F2m)twice();
- }
-
- return (ECPoint.F2m)curve.getInfinity();
- }
-
- ECFieldElement L = dy.divide(dx);
-
- ECFieldElement X3 = L.square().add(L).add(dx).add(curve.getA());
- ECFieldElement Y3 = L.multiply(X1.add(X3)).add(X3).add(Y1);
-
- return new ECPoint.F2m(curve, X3, Y3, this.withCompression);
- }
- case ECCurve.COORD_HOMOGENEOUS:
- {
- ECFieldElement Y1 = this.y, Z1 = this.zs[0];
- ECFieldElement Y2 = b.y, Z2 = b.zs[0];
-
- boolean Z2IsOne = Z2.isOne();
-
- ECFieldElement U1 = Z1.multiply(Y2);
- ECFieldElement U2 = Z2IsOne ? Y1 : Y1.multiply(Z2);
- ECFieldElement U = U1.add(U2);
- ECFieldElement V1 = Z1.multiply(X2);
- ECFieldElement V2 = Z2IsOne ? X1 : X1.multiply(Z2);
- ECFieldElement V = V1.add(V2);
-
- if (V.isZero())
- {
- if (U.isZero())
- {
- return (ECPoint.F2m)twice();
- }
-
- return (ECPoint.F2m)curve.getInfinity();
- }
-
- ECFieldElement VSq = V.square();
- ECFieldElement VCu = VSq.multiply(V);
- ECFieldElement W = Z2IsOne ? Z1 : Z1.multiply(Z2);
- ECFieldElement uv = U.add(V);
- ECFieldElement A = uv.multiplyPlusProduct(U, VSq, curve.getA()).multiply(W).add(VCu);
-
- ECFieldElement X3 = V.multiply(A);
- ECFieldElement VSqZ2 = Z2IsOne ? VSq : VSq.multiply(Z2);
- ECFieldElement Y3 = U.multiplyPlusProduct(X1, V, Y1).multiplyPlusProduct(VSqZ2, uv, A);
- ECFieldElement Z3 = VCu.multiply(W);
-
- return new ECPoint.F2m(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
- }
- case ECCurve.COORD_LAMBDA_PROJECTIVE:
- {
- if (X1.isZero())
- {
- if (X2.isZero())
- {
- return (ECPoint.F2m)curve.getInfinity();
- }
-
- return b.addSimple(this);
- }
-
- ECFieldElement L1 = this.y, Z1 = this.zs[0];
- ECFieldElement L2 = b.y, Z2 = b.zs[0];
-
- boolean Z1IsOne = Z1.isOne();
- ECFieldElement U2 = X2, S2 = L2;
- if (!Z1IsOne)
- {
- U2 = U2.multiply(Z1);
- S2 = S2.multiply(Z1);
- }
-
- boolean Z2IsOne = Z2.isOne();
- ECFieldElement U1 = X1, S1 = L1;
- if (!Z2IsOne)
- {
- U1 = U1.multiply(Z2);
- S1 = S1.multiply(Z2);
- }
-
- ECFieldElement A = S1.add(S2);
- ECFieldElement B = U1.add(U2);
-
- 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
- ECPoint p = this.normalize();
- X1 = p.getXCoord();
- ECFieldElement Y1 = p.getYCoord();
-
- ECFieldElement Y2 = L2;
- ECFieldElement L = Y1.add(Y2).divide(X1);
-
- X3 = L.square().add(L).add(X1).add(curve.getA());
- if (X3.isZero())
- {
- return new ECPoint.F2m(curve, X3, curve.getB().sqrt(), this.withCompression);
- }
-
- ECFieldElement Y3 = L.multiply(X1.add(X3)).add(X3).add(Y1);
- L3 = Y3.divide(X3).add(X3);
- Z3 = curve.fromBigInteger(ECConstants.ONE);
- }
- else
- {
- B = B.square();
-
- ECFieldElement AU1 = A.multiply(U1);
- ECFieldElement AU2 = A.multiply(U2);
-
- X3 = AU1.multiply(AU2);
- if (X3.isZero())
- {
- return new ECPoint.F2m(curve, X3, curve.getB().sqrt(), this.withCompression);
- }
-
- ECFieldElement ABZ2 = A.multiply(B);
- if (!Z2IsOne)
- {
- ABZ2 = ABZ2.multiply(Z2);
- }
-
- L3 = AU2.add(B).squarePlusProduct(ABZ2, 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)
- * @see org.bouncycastle.math.ec.ECPoint#subtract(org.bouncycastle.math.ec.ECPoint)
- */
- public ECPoint subtract(ECPoint b)
- {
- checkPoints(this, b);
- return subtractSimple((ECPoint.F2m)b);
- }
-
- /**
- * Subtracts another <code>ECPoints.F2m</code> from <code>this</code>
- * without checking if both points are on the same curve. Used by
- * multiplication algorithms, because there all points are a multiple
- * of the same point and hence the checks can be omitted.
- * @param b The other <code>ECPoints.F2m</code> to subtract from
- * <code>this</code>.
- * @return <code>this - b</code>
- */
- public ECPoint.F2m subtractSimple(ECPoint.F2m b)
- {
- if (b.isInfinity())
- {
- return this;
- }
-
- // Add -b
- return addSimple((ECPoint.F2m)b.negate());
- }
-
- public ECPoint.F2m tau()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- ECCurve curve = this.getCurve();
- int coord = curve.getCoordinateSystem();
-
- ECFieldElement X1 = this.x;
-
- switch (coord)
- {
- case ECCurve.COORD_AFFINE:
- case ECCurve.COORD_LAMBDA_AFFINE:
- {
- ECFieldElement Y1 = this.y;
- return new ECPoint.F2m(curve, X1.square(), Y1.square(), this.withCompression);
- }
- case ECCurve.COORD_HOMOGENEOUS:
- case ECCurve.COORD_LAMBDA_PROJECTIVE:
- {
- ECFieldElement Y1 = this.y, Z1 = this.zs[0];
- return new ECPoint.F2m(curve, X1.square(), Y1.square(), new ECFieldElement[]{ Z1.square() }, this.withCompression);
- }
- default:
- {
- throw new IllegalStateException("unsupported coordinate system");
- }
- }
- }
-
- public ECPoint twice()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- ECCurve curve = this.getCurve();
-
- ECFieldElement X1 = this.x;
- if (X1.isZero())
- {
- // A point with X == 0 is it's own additive inverse
- return curve.getInfinity();
- }
-
- int coord = curve.getCoordinateSystem();
-
- switch (coord)
- {
- case ECCurve.COORD_AFFINE:
- {
- ECFieldElement Y1 = this.y;
-
- ECFieldElement L1 = Y1.divide(X1).add(X1);
-
- ECFieldElement X3 = L1.square().add(L1).add(curve.getA());
- ECFieldElement Y3 = X1.squarePlusProduct(X3, L1.addOne());
-
- return new ECPoint.F2m(curve, X3, Y3, this.withCompression);
- }
- case ECCurve.COORD_HOMOGENEOUS:
- {
- ECFieldElement Y1 = this.y, Z1 = this.zs[0];
-
- boolean Z1IsOne = Z1.isOne();
- 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 sv = S.add(V);
- ECFieldElement h = sv.multiplyPlusProduct(S, vSquared, curve.getA());
-
- ECFieldElement X3 = V.multiply(h);
- ECFieldElement Y3 = X1Sq.square().multiplyPlusProduct(V, h, sv);
- ECFieldElement Z3 = V.multiply(vSquared);
-
- return new ECPoint.F2m(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
- }
- case ECCurve.COORD_LAMBDA_PROJECTIVE:
- {
- ECFieldElement L1 = this.y, Z1 = this.zs[0];
-
- boolean Z1IsOne = Z1.isOne();
- ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.multiply(Z1);
- ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.square();
- ECFieldElement a = curve.getA();
- ECFieldElement aZ1Sq = Z1IsOne ? a : a.multiply(Z1Sq);
- ECFieldElement T = L1.square().add(L1Z1).add(aZ1Sq);
- if (T.isZero())
- {
- return new ECPoint.F2m(curve, T, curve.getB().sqrt(), withCompression);
- }
-
- ECFieldElement X3 = T.square();
- ECFieldElement Z3 = Z1IsOne ? T : T.multiply(Z1Sq);
-
- ECFieldElement b = curve.getB();
- ECFieldElement L3;
- if (b.bitLength() < (curve.getFieldSize() >> 1))
- {
- ECFieldElement t1 = L1.add(X1).square();
- ECFieldElement t2;
- if (b.isOne())
- {
- t2 = aZ1Sq.add(Z1Sq).square();
- }
- else
- {
- // TODO Can be calculated with one square if we pre-compute sqrt(b)
- t2 = aZ1Sq.squarePlusProduct(b, Z1Sq.square());
- }
- L3 = t1.add(T).add(Z1Sq).multiply(t1).add(t2).add(X3);
- if (a.isZero())
- {
- L3 = L3.add(Z3);
- }
- else if (!a.isOne())
- {
- L3 = L3.add(a.addOne().multiply(Z3));
- }
- }
- else
- {
- ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.multiply(Z1);
- L3 = X1Z1.squarePlusProduct(T, L1Z1).add(X3).add(Z3);
- }
-
- return new ECPoint.F2m(curve, X3, L3, new ECFieldElement[]{ Z3 }, this.withCompression);
- }
- default:
- {
- throw new IllegalStateException("unsupported coordinate system");
- }
- }
- }
-
- public ECPoint twicePlus(ECPoint b)
- {
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- 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.isOne())
- {
- return twice().add(b);
- }
-
- 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).multiplyPlusProduct(T, X1Sq, Z1Sq);
- ECFieldElement X2Z1Sq = X2.multiply(Z1Sq);
- ECFieldElement B = X2Z1Sq.add(T).square();
-
- if (B.isZero())
- {
- if (A.isZero())
- {
- return b.twice();
- }
-
- return curve.getInfinity();
- }
-
- if (A.isZero())
- {
- return new ECPoint.F2m(curve, A, curve.getB().sqrt(), withCompression);
- }
-
- ECFieldElement X3 = A.square().multiply(X2Z1Sq);
- ECFieldElement Z3 = A.multiply(B).multiply(Z1Sq);
- ECFieldElement L3 = A.add(B).square().multiplyPlusProduct(T, L2plus1, Z3);
-
- return new ECPoint.F2m(curve, X3, L3, new ECFieldElement[]{ Z3 }, this.withCompression);
- }
- default:
- {
- return twice().add(b);
- }
- }
- }
-
- 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/core/src/main/java/org/bouncycastle/math/ec/ECPointMap.java b/core/src/main/java/org/bouncycastle/math/ec/ECPointMap.java
deleted file mode 100644
index 439e8daa..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/ECPointMap.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.bouncycastle.math.ec;
-
-public interface ECPointMap
-{
- ECPoint map(ECPoint p);
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/FixedPointCombMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/FixedPointCombMultiplier.java
deleted file mode 100644
index 9fe00b9b..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/FixedPointCombMultiplier.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-public class FixedPointCombMultiplier extends AbstractECMultiplier
-{
- protected ECPoint multiplyPositive(ECPoint p, BigInteger k)
- {
- ECCurve c = p.getCurve();
- int size = FixedPointUtil.getCombSize(c);
-
- if (k.bitLength() > size)
- {
- /*
- * TODO The comb works best when the scalars are less than the (possibly unknown) order.
- * Still, if we want to handle larger scalars, we could allow customization of the comb
- * size, or alternatively we could deal with the 'extra' bits either by running the comb
- * multiple times as necessary, or by using an alternative multiplier as prelude.
- */
- throw new IllegalStateException("fixed-point comb doesn't support scalars larger than the curve order");
- }
-
- int minWidth = getWidthForCombSize(size);
-
- FixedPointPreCompInfo info = FixedPointUtil.precompute(p, minWidth);
- ECPoint[] lookupTable = info.getPreComp();
- int width = info.getWidth();
-
- int d = (size + width - 1) / width;
-
- ECPoint R = c.getInfinity();
-
- int top = d * width - 1;
- for (int i = 0; i < d; ++i)
- {
- int index = 0;
-
- for (int j = top - i; j >= 0; j -= d)
- {
- index <<= 1;
- if (k.testBit(j))
- {
- index |= 1;
- }
- }
-
- R = R.twicePlus(lookupTable[index]);
- }
-
- return R;
- }
-
- protected int getWidthForCombSize(int combSize)
- {
- return combSize > 257 ? 6 : 5;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/FixedPointPreCompInfo.java b/core/src/main/java/org/bouncycastle/math/ec/FixedPointPreCompInfo.java
deleted file mode 100644
index b7569aae..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/FixedPointPreCompInfo.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package org.bouncycastle.math.ec;
-
-/**
- * Class holding precomputation data for fixed-point multiplications.
- */
-public class FixedPointPreCompInfo implements PreCompInfo
-{
- /**
- * Array holding the precomputed <code>ECPoint</code>s used for a fixed
- * point multiplication.
- */
- protected ECPoint[] preComp = null;
-
- /**
- * The width used for the precomputation. If a larger width precomputation
- * is already available this may be larger than was requested, so calling
- * code should refer to the actual width.
- */
- protected int width = -1;
-
- public ECPoint[] getPreComp()
- {
- return preComp;
- }
-
- public void setPreComp(ECPoint[] preComp)
- {
- this.preComp = preComp;
- }
-
- public int getWidth()
- {
- return width;
- }
-
- public void setWidth(int width)
- {
- this.width = width;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/FixedPointUtil.java b/core/src/main/java/org/bouncycastle/math/ec/FixedPointUtil.java
deleted file mode 100644
index e4fbb8d0..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/FixedPointUtil.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-public class FixedPointUtil
-{
- public static final String PRECOMP_NAME = "bc_fixed_point";
-
- public static int getCombSize(ECCurve c)
- {
- BigInteger order = c.getOrder();
- return order == null ? c.getFieldSize() + 1 : order.bitLength();
- }
-
- public static FixedPointPreCompInfo getFixedPointPreCompInfo(PreCompInfo preCompInfo)
- {
- if ((preCompInfo != null) && (preCompInfo instanceof FixedPointPreCompInfo))
- {
- return (FixedPointPreCompInfo)preCompInfo;
- }
-
- return new FixedPointPreCompInfo();
- }
-
- public static FixedPointPreCompInfo precompute(ECPoint p, int minWidth)
- {
- ECCurve c = p.getCurve();
-
- int n = 1 << minWidth;
- FixedPointPreCompInfo info = getFixedPointPreCompInfo(c.getPreCompInfo(p, PRECOMP_NAME));
- ECPoint[] lookupTable = info.getPreComp();
-
- if (lookupTable == null || lookupTable.length < n)
- {
- int bits = getCombSize(c);
- int d = (bits + minWidth - 1) / minWidth;
-
- ECPoint[] pow2Table = new ECPoint[minWidth];
- pow2Table[0] = p;
- for (int i = 1; i < minWidth; ++i)
- {
- pow2Table[i] = pow2Table[i - 1].timesPow2(d);
- }
-
- c.normalizeAll(pow2Table);
-
- lookupTable = new ECPoint[n];
- lookupTable[0] = c.getInfinity();
-
- for (int bit = minWidth - 1; bit >= 0; --bit)
- {
- ECPoint pow2 = pow2Table[bit];
-
- int step = 1 << bit;
- for (int i = step; i < n; i += (step << 1))
- {
- lookupTable[i] = lookupTable[i - step].add(pow2);
- }
- }
-
- c.normalizeAll(lookupTable);
-
- info.setPreComp(lookupTable);
- info.setWidth(minWidth);
-
- c.setPreCompInfo(p, PRECOMP_NAME, info);
- }
-
- return info;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/GLVMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/GLVMultiplier.java
deleted file mode 100644
index 09b83668..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/GLVMultiplier.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.endo.GLVEndomorphism;
-
-public class GLVMultiplier extends AbstractECMultiplier
-{
- protected final ECCurve curve;
- protected final GLVEndomorphism glvEndomorphism;
-
- public GLVMultiplier(ECCurve curve, GLVEndomorphism glvEndomorphism)
- {
- if (curve == null || curve.getOrder() == null)
- {
- throw new IllegalArgumentException("Need curve with known group order");
- }
-
- this.curve = curve;
- this.glvEndomorphism = glvEndomorphism;
- }
-
- protected ECPoint multiplyPositive(ECPoint p, BigInteger k)
- {
- if (!curve.equals(p.getCurve()))
- {
- throw new IllegalStateException();
- }
-
- BigInteger n = p.getCurve().getOrder();
- BigInteger[] ab = glvEndomorphism.decomposeScalar(k.mod(n));
- BigInteger a = ab[0], b = ab[1];
-
- ECPointMap pointMap = glvEndomorphism.getPointMap();
- if (glvEndomorphism.hasEfficientPointMap())
- {
- return ECAlgorithms.implShamirsTrickWNaf(p, a, pointMap, b);
- }
-
- return ECAlgorithms.implShamirsTrickWNaf(p, a, pointMap.map(p), b);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/LongArray.java b/core/src/main/java/org/bouncycastle/math/ec/LongArray.java
deleted file mode 100644
index e3069dc0..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/LongArray.java
+++ /dev/null
@@ -1,2195 +0,0 @@
-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 isOne()
- {
- long[] a = m_ints;
- if (a[0] != 1L)
- {
- return false;
- }
- for (int i = 1; i < a.length; ++i)
- {
- if (a[i] != 0L)
- {
- return false;
- }
- }
- return true;
- }
-
- public boolean isZero()
- {
- long[] a = m_ints;
- 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) != 0L)
- {
- if ((a & 1L) != 0L)
- {
- long carry = addShiftedUp(c, cOff, b, 0, bLen, k);
- if (carry != 0L)
- {
- 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 a0 = A.m_ints[0];
- if (a0 == 1L)
- {
- return B;
- }
-
- /*
- * Fast path for small A, with performance dependent only on the number of set bits
- */
- long[] c0 = new long[cLen];
- multiplyWord(a0, B.m_ints, bLen, c0, 0);
-
- /*
- * Reduce the raw answer against the reduction coefficients
- */
- return reduceResult(c0, 0, cLen, m, ks);
- }
-
- /*
- * 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 a0 = A.m_ints[0];
- if (a0 == 1L)
- {
- return B;
- }
-
- /*
- * Fast path for small A, with performance dependent only on the number of set bits
- */
- long[] c0 = new long[cLen];
- multiplyWord(a0, B.m_ints, bLen, c0, 0);
-
- /*
- * Reduce the raw answer against the reduction coefficients
- */
- return reduceResult(c0, 0, cLen, m, ks);
- }
-
- /*
- * Determine if B will get bigger during shifting
- */
- int bMax = (bDeg + 7 + 63) >>> 6;
-
- /*
- * Lookup table for the offset of each B in the tables
- */
- int[] ti = new int[16];
-
- /*
- * Precompute table of all 4-bit products of B
- */
- long[] T0 = new long[bMax << 4];
- int tOff = bMax;
- ti[1] = tOff;
- System.arraycopy(B.m_ints, 0, T0, tOff, bLen);
- for (int i = 2; i < 16; ++i)
- {
- ti[i] = (tOff += bMax);
- if ((i & 1) == 0)
- {
- shiftUp(T0, tOff >>> 1, T0, tOff, bMax, 1);
- }
- else
- {
- add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax);
- }
- }
-
- /*
- * Second table with all 4-bit products of B shifted 4 bits
- */
- long[] T1 = new long[T0.length];
- shiftUp(T0, 0, T1, 0, T0.length, 4);
-// shiftUp(T0, bMax, T1, bMax, tOff, 4);
-
- long[] a = A.m_ints;
- long[] c = new long[cLen << 3];
-
- int MASK = 0xF;
-
- /*
- * Lopez-Dahab (Modified) algorithm
- */
-
- for (int aPos = 0; aPos < aLen; ++aPos)
- {
- long aVal = a[aPos];
- int cOff = aPos;
- for (;;)
- {
- int u = (int)aVal & MASK;
- aVal >>>= 4;
- int v = (int)aVal & MASK;
- addBoth(c, cOff, T0, ti[u], T1, ti[v], bMax);
- aVal >>>= 4;
- if (aVal == 0L)
- {
- break;
- }
- cOff += cLen;
- }
- }
-
- {
- int cOff = c.length;
- while ((cOff -= cLen) != 0)
- {
- addShiftedUp(c, cOff - cLen, c, cOff, cLen, 8);
- }
- }
-
- /*
- * Finally the raw answer is collected, reduce it against the reduction coefficients
- */
- return reduceResult(c, 0, cLen, m, ks);
- }
-
- 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 a0 = A.m_ints[0];
- if (a0 == 1L)
- {
- return B;
- }
-
- /*
- * Fast path for small A, with performance dependent only on the number of set bits
- */
- long[] c0 = new long[cLen];
- multiplyWord(a0, B.m_ints, bLen, c0, 0);
-
- /*
- * Reduce the raw answer against the reduction coefficients
- */
- return reduceResult(c0, 0, cLen, m, ks);
- }
-
- // 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);
- }
-
- public LongArray modReduce(int m, int[] ks)
- {
- long[] buf = Arrays.clone(m_ints);
- int rLen = reduceInPlace(buf, 0, buf.length, m, ks);
- return new LongArray(buf, 0, rLen);
- }
-
- public LongArray multiply(LongArray other, int m, int[] ks)
- {
- /*
- * Find out the degree of each argument and handle the zero cases
- */
- int aDeg = degree();
- if (aDeg == 0)
- {
- return this;
- }
- int bDeg = other.degree();
- if (bDeg == 0)
- {
- return other;
- }
-
- /*
- * Swap if necessary so that A is the smaller argument
- */
- LongArray A = this, B = other;
- if (aDeg > bDeg)
- {
- A = other; B = this;
- int tmp = aDeg; aDeg = bDeg; bDeg = tmp;
- }
-
- /*
- * Establish the word lengths of the arguments and result
- */
- int aLen = (aDeg + 63) >>> 6;
- int bLen = (bDeg + 63) >>> 6;
- int cLen = (aDeg + bDeg + 62) >>> 6;
-
- if (aLen == 1)
- {
- long a0 = A.m_ints[0];
- if (a0 == 1L)
- {
- return B;
- }
-
- /*
- * Fast path for small A, with performance dependent only on the number of set bits
- */
- long[] c0 = new long[cLen];
- multiplyWord(a0, B.m_ints, bLen, c0, 0);
-
- /*
- * Reduce the raw answer against the reduction coefficients
- */
-// return reduceResult(c0, 0, cLen, m, ks);
- return new LongArray(c0, 0, cLen);
- }
-
- /*
- * Determine if B will get bigger during shifting
- */
- int bMax = (bDeg + 7 + 63) >>> 6;
-
- /*
- * Lookup table for the offset of each B in the tables
- */
- int[] ti = new int[16];
-
- /*
- * Precompute table of all 4-bit products of B
- */
- long[] T0 = new long[bMax << 4];
- int tOff = bMax;
- ti[1] = tOff;
- System.arraycopy(B.m_ints, 0, T0, tOff, bLen);
- for (int i = 2; i < 16; ++i)
- {
- ti[i] = (tOff += bMax);
- if ((i & 1) == 0)
- {
- shiftUp(T0, tOff >>> 1, T0, tOff, bMax, 1);
- }
- else
- {
- add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax);
- }
- }
-
- /*
- * Second table with all 4-bit products of B shifted 4 bits
- */
- long[] T1 = new long[T0.length];
- shiftUp(T0, 0, T1, 0, T0.length, 4);
-// shiftUp(T0, bMax, T1, bMax, tOff, 4);
-
- long[] a = A.m_ints;
- long[] c = new long[cLen << 3];
-
- int MASK = 0xF;
-
- /*
- * Lopez-Dahab (Modified) algorithm
- */
-
- for (int aPos = 0; aPos < aLen; ++aPos)
- {
- long aVal = a[aPos];
- int cOff = aPos;
- for (;;)
- {
- int u = (int)aVal & MASK;
- aVal >>>= 4;
- int v = (int)aVal & MASK;
- addBoth(c, cOff, T0, ti[u], T1, ti[v], bMax);
- aVal >>>= 4;
- if (aVal == 0L)
- {
- break;
- }
- cOff += cLen;
- }
- }
-
- {
- int cOff = c.length;
- while ((cOff -= cLen) != 0)
- {
- addShiftedUp(c, cOff - cLen, c, cOff, cLen, 8);
- }
- }
-
- /*
- * Finally the raw answer is collected, reduce it against the reduction coefficients
- */
-// return reduceResult(c, 0, cLen, m, ks);
- return new LongArray(c, 0, cLen);
- }
-
- public void reduce(int m, int[] ks)
- {
- long[] buf = m_ints;
- int rLen = reduceInPlace(buf, 0, buf.length, m, ks);
- if (rLen < buf.length)
- {
- m_ints = new long[rLen];
- System.arraycopy(buf, 0, m_ints, 0, rLen);
- }
- }
-
- private static LongArray reduceResult(long[] buf, int off, int len, int m, int[] ks)
- {
- int rLen = reduceInPlace(buf, off, len, m, ks);
- 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 n = bit - m;
- int j = ks.length;
- while (--j >= 0)
- {
- flipBit(buf, off, ks[j] + n);
- }
- flipBit(buf, off, n);
- }
-
- 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));
- }
-
- public LongArray modSquareN(int n, int m, int[] ks)
- {
- int len = getUsedLength();
- if (len == 0)
- {
- return this;
- }
-
- int mLen = (m + 63) >>> 6;
- long[] r = new long[mLen << 1];
- System.arraycopy(m_ints, 0, r, 0, len);
-
- while (--n >= 0)
- {
- squareInPlace(r, len, m, ks);
- len = reduceInPlace(r, 0, r.length, m, ks);
- }
-
- return new LongArray(r, 0, len);
- }
-
- public LongArray square(int m, int[] ks)
- {
- int len = getUsedLength();
- if (len == 0)
- {
- return this;
- }
-
- int _2len = len << 1;
- long[] r = new long[_2len];
-
- int pos = 0;
- while (pos < _2len)
- {
- long mi = m_ints[pos >>> 1];
- r[pos++] = interleave2_32to64((int)mi);
- r[pos++] = interleave2_32to64((int)(mi >>> 32));
- }
-
- return new LongArray(r, 0, r.length);
- }
-
- private static void squareInPlace(long[] x, int xLen, int m, int[] ks)
- {
- int pos = xLen << 1;
- while (--xLen >= 0)
- {
- long xVal = x[xLen];
- x[--pos] = interleave2_32to64((int)(xVal >>> 32));
- x[--pos] = interleave2_32to64((int)xVal);
- }
- }
-
- private static void interleave(long[] x, int xOff, long[] z, int zOff, int count, int width)
- {
- 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 == 0)
- {
- throw new IllegalStateException();
- }
- 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/core/src/main/java/org/bouncycastle/math/ec/MixedNafR2LMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/MixedNafR2LMultiplier.java
deleted file mode 100644
index 6d5fe928..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/MixedNafR2LMultiplier.java
+++ /dev/null
@@ -1,77 +0,0 @@
-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/core/src/main/java/org/bouncycastle/math/ec/MontgomeryLadderMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/MontgomeryLadderMultiplier.java
deleted file mode 100644
index cd969b50..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/MontgomeryLadderMultiplier.java
+++ /dev/null
@@ -1,25 +0,0 @@
-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/core/src/main/java/org/bouncycastle/math/ec/NafL2RMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/NafL2RMultiplier.java
deleted file mode 100644
index 91d91d11..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/NafL2RMultiplier.java
+++ /dev/null
@@ -1,30 +0,0 @@
-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/core/src/main/java/org/bouncycastle/math/ec/NafR2LMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/NafR2LMultiplier.java
deleted file mode 100644
index aed2336b..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/NafR2LMultiplier.java
+++ /dev/null
@@ -1,31 +0,0 @@
-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/core/src/main/java/org/bouncycastle/math/ec/PreCompInfo.java b/core/src/main/java/org/bouncycastle/math/ec/PreCompInfo.java
deleted file mode 100644
index 38498581..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/PreCompInfo.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.bouncycastle.math.ec;
-
-/**
- * Interface for classes storing precomputation data for multiplication
- * algorithms. Used as a Memento (see GOF patterns) by e.g.
- * <code>WNafL2RMultiplier</code>.
- */
-public interface PreCompInfo
-{
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/ReferenceMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/ReferenceMultiplier.java
deleted file mode 100644
index 107e1937..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/ReferenceMultiplier.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-public class ReferenceMultiplier extends AbstractECMultiplier
-{
- protected ECPoint multiplyPositive(ECPoint p, BigInteger k)
- {
- return ECAlgorithms.referenceMultiply(p, k);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/ScaleXPointMap.java b/core/src/main/java/org/bouncycastle/math/ec/ScaleXPointMap.java
deleted file mode 100644
index 099f5fb3..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/ScaleXPointMap.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.bouncycastle.math.ec;
-
-public class ScaleXPointMap implements ECPointMap
-{
- protected final ECFieldElement scale;
-
- public ScaleXPointMap(ECFieldElement scale)
- {
- this.scale = scale;
- }
-
- public ECPoint map(ECPoint p)
- {
- return p.scaleX(scale);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/ScaleYPointMap.java b/core/src/main/java/org/bouncycastle/math/ec/ScaleYPointMap.java
deleted file mode 100644
index a7a87904..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/ScaleYPointMap.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.bouncycastle.math.ec;
-
-public class ScaleYPointMap implements ECPointMap
-{
- protected final ECFieldElement scale;
-
- public ScaleYPointMap(ECFieldElement scale)
- {
- this.scale = scale;
- }
-
- public ECPoint map(ECPoint p)
- {
- return p.scaleY(scale);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/SimpleBigDecimal.java b/core/src/main/java/org/bouncycastle/math/ec/SimpleBigDecimal.java
deleted file mode 100644
index 229fae47..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/SimpleBigDecimal.java
+++ /dev/null
@@ -1,247 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-/**
- * Class representing a simple version of a big decimal. A
- * <code>SimpleBigDecimal</code> is basically a
- * {@link java.math.BigInteger BigInteger} with a few digits on the right of
- * the decimal point. The number of (binary) digits on the right of the decimal
- * point is called the <code>scale</code> of the <code>SimpleBigDecimal</code>.
- * Unlike in {@link java.math.BigDecimal BigDecimal}, the scale is not adjusted
- * automatically, but must be set manually. All <code>SimpleBigDecimal</code>s
- * taking part in the same arithmetic operation must have equal scale. The
- * result of a multiplication of two <code>SimpleBigDecimal</code>s returns a
- * <code>SimpleBigDecimal</code> with double scale.
- */
-class SimpleBigDecimal
- //extends Number // not in J2ME - add compatibility class?
-{
- private static final long serialVersionUID = 1L;
-
- private final BigInteger bigInt;
- private final int scale;
-
- /**
- * Returns a <code>SimpleBigDecimal</code> representing the same numerical
- * value as <code>value</code>.
- * @param value The value of the <code>SimpleBigDecimal</code> to be
- * created.
- * @param scale The scale of the <code>SimpleBigDecimal</code> to be
- * created.
- * @return The such created <code>SimpleBigDecimal</code>.
- */
- public static SimpleBigDecimal getInstance(BigInteger value, int scale)
- {
- return new SimpleBigDecimal(value.shiftLeft(scale), scale);
- }
-
- /**
- * Constructor for <code>SimpleBigDecimal</code>. The value of the
- * constructed <code>SimpleBigDecimal</code> equals <code>bigInt /
- * 2<sup>scale</sup></code>.
- * @param bigInt The <code>bigInt</code> value parameter.
- * @param scale The scale of the constructed <code>SimpleBigDecimal</code>.
- */
- public SimpleBigDecimal(BigInteger bigInt, int scale)
- {
- if (scale < 0)
- {
- throw new IllegalArgumentException("scale may not be negative");
- }
-
- this.bigInt = bigInt;
- this.scale = scale;
- }
-
- private void checkScale(SimpleBigDecimal b)
- {
- if (scale != b.scale)
- {
- throw new IllegalArgumentException("Only SimpleBigDecimal of " +
- "same scale allowed in arithmetic operations");
- }
- }
-
- public SimpleBigDecimal adjustScale(int newScale)
- {
- if (newScale < 0)
- {
- throw new IllegalArgumentException("scale may not be negative");
- }
-
- if (newScale == scale)
- {
- return this;
- }
-
- return new SimpleBigDecimal(bigInt.shiftLeft(newScale - scale),
- newScale);
- }
-
- public SimpleBigDecimal add(SimpleBigDecimal b)
- {
- checkScale(b);
- return new SimpleBigDecimal(bigInt.add(b.bigInt), scale);
- }
-
- public SimpleBigDecimal add(BigInteger b)
- {
- return new SimpleBigDecimal(bigInt.add(b.shiftLeft(scale)), scale);
- }
-
- public SimpleBigDecimal negate()
- {
- return new SimpleBigDecimal(bigInt.negate(), scale);
- }
-
- public SimpleBigDecimal subtract(SimpleBigDecimal b)
- {
- return add(b.negate());
- }
-
- public SimpleBigDecimal subtract(BigInteger b)
- {
- return new SimpleBigDecimal(bigInt.subtract(b.shiftLeft(scale)),
- scale);
- }
-
- public SimpleBigDecimal multiply(SimpleBigDecimal b)
- {
- checkScale(b);
- return new SimpleBigDecimal(bigInt.multiply(b.bigInt), scale + scale);
- }
-
- public SimpleBigDecimal multiply(BigInteger b)
- {
- return new SimpleBigDecimal(bigInt.multiply(b), scale);
- }
-
- public SimpleBigDecimal divide(SimpleBigDecimal b)
- {
- checkScale(b);
- BigInteger dividend = bigInt.shiftLeft(scale);
- return new SimpleBigDecimal(dividend.divide(b.bigInt), scale);
- }
-
- public SimpleBigDecimal divide(BigInteger b)
- {
- return new SimpleBigDecimal(bigInt.divide(b), scale);
- }
-
- public SimpleBigDecimal shiftLeft(int n)
- {
- return new SimpleBigDecimal(bigInt.shiftLeft(n), scale);
- }
-
- public int compareTo(SimpleBigDecimal val)
- {
- checkScale(val);
- return bigInt.compareTo(val.bigInt);
- }
-
- public int compareTo(BigInteger val)
- {
- return bigInt.compareTo(val.shiftLeft(scale));
- }
-
- public BigInteger floor()
- {
- return bigInt.shiftRight(scale);
- }
-
- public BigInteger round()
- {
- SimpleBigDecimal oneHalf = new SimpleBigDecimal(ECConstants.ONE, 1);
- return add(oneHalf.adjustScale(scale)).floor();
- }
-
- public int intValue()
- {
- return floor().intValue();
- }
-
- public long longValue()
- {
- return floor().longValue();
- }
- /* NON-J2ME compliant.
- public double doubleValue()
- {
- return Double.valueOf(toString()).doubleValue();
- }
-
- public float floatValue()
- {
- return Float.valueOf(toString()).floatValue();
- }
- */
- public int getScale()
- {
- return scale;
- }
-
- public String toString()
- {
- if (scale == 0)
- {
- return bigInt.toString();
- }
-
- BigInteger floorBigInt = floor();
-
- BigInteger fract = bigInt.subtract(floorBigInt.shiftLeft(scale));
- if (bigInt.signum() == -1)
- {
- fract = ECConstants.ONE.shiftLeft(scale).subtract(fract);
- }
-
- if ((floorBigInt.signum() == -1) && (!(fract.equals(ECConstants.ZERO))))
- {
- floorBigInt = floorBigInt.add(ECConstants.ONE);
- }
- String leftOfPoint = floorBigInt.toString();
-
- char[] fractCharArr = new char[scale];
- String fractStr = fract.toString(2);
- int fractLen = fractStr.length();
- int zeroes = scale - fractLen;
- for (int i = 0; i < zeroes; i++)
- {
- fractCharArr[i] = '0';
- }
- for (int j = 0; j < fractLen; j++)
- {
- fractCharArr[zeroes + j] = fractStr.charAt(j);
- }
- String rightOfPoint = new String(fractCharArr);
-
- StringBuffer sb = new StringBuffer(leftOfPoint);
- sb.append(".");
- sb.append(rightOfPoint);
-
- return sb.toString();
- }
-
- public boolean equals(Object o)
- {
- if (this == o)
- {
- return true;
- }
-
- if (!(o instanceof SimpleBigDecimal))
- {
- return false;
- }
-
- SimpleBigDecimal other = (SimpleBigDecimal)o;
- return ((bigInt.equals(other.bigInt)) && (scale == other.scale));
- }
-
- public int hashCode()
- {
- return bigInt.hashCode() ^ scale;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/Tnaf.java b/core/src/main/java/org/bouncycastle/math/ec/Tnaf.java
deleted file mode 100644
index 236bbc8e..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/Tnaf.java
+++ /dev/null
@@ -1,823 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-/**
- * Class holding methods for point multiplication based on the window
- * &tau;-adic nonadjacent form (WTNAF). The algorithms are based on the
- * paper "Improved Algorithms for Arithmetic on Anomalous Binary Curves"
- * by Jerome A. Solinas. The paper first appeared in the Proceedings of
- * Crypto 1997.
- */
-class Tnaf
-{
- private static final BigInteger MINUS_ONE = ECConstants.ONE.negate();
- private static final BigInteger MINUS_TWO = ECConstants.TWO.negate();
- private static final BigInteger MINUS_THREE = ECConstants.THREE.negate();
-
- /**
- * The window width of WTNAF. The standard value of 4 is slightly less
- * than optimal for running time, but keeps space requirements for
- * precomputation low. For typical curves, a value of 5 or 6 results in
- * a better running time. When changing this value, the
- * <code>&alpha;<sub>u</sub></code>'s must be computed differently, see
- * e.g. "Guide to Elliptic Curve Cryptography", Darrel Hankerson,
- * Alfred Menezes, Scott Vanstone, Springer-Verlag New York Inc., 2004,
- * p. 121-122
- */
- public static final byte WIDTH = 4;
-
- /**
- * 2<sup>4</sup>
- */
- public static final byte POW_2_WIDTH = 16;
-
- /**
- * The <code>&alpha;<sub>u</sub></code>'s for <code>a=0</code> as an array
- * of <code>ZTauElement</code>s.
- */
- public static final ZTauElement[] alpha0 = {
- null,
- new ZTauElement(ECConstants.ONE, ECConstants.ZERO), null,
- new ZTauElement(MINUS_THREE, MINUS_ONE), null,
- new ZTauElement(MINUS_ONE, MINUS_ONE), null,
- new ZTauElement(ECConstants.ONE, MINUS_ONE), null
- };
-
- /**
- * The <code>&alpha;<sub>u</sub></code>'s for <code>a=0</code> as an array
- * of TNAFs.
- */
- public static final byte[][] alpha0Tnaf = {
- null, {1}, null, {-1, 0, 1}, null, {1, 0, 1}, null, {-1, 0, 0, 1}
- };
-
- /**
- * The <code>&alpha;<sub>u</sub></code>'s for <code>a=1</code> as an array
- * of <code>ZTauElement</code>s.
- */
- public static final ZTauElement[] alpha1 = {null,
- new ZTauElement(ECConstants.ONE, ECConstants.ZERO), null,
- new ZTauElement(MINUS_THREE, ECConstants.ONE), null,
- new ZTauElement(MINUS_ONE, ECConstants.ONE), null,
- new ZTauElement(ECConstants.ONE, ECConstants.ONE), null
- };
-
- /**
- * The <code>&alpha;<sub>u</sub></code>'s for <code>a=1</code> as an array
- * of TNAFs.
- */
- public static final byte[][] alpha1Tnaf = {
- null, {1}, null, {-1, 0, 1}, null, {1, 0, 1}, null, {-1, 0, 0, -1}
- };
-
- /**
- * Computes the norm of an element <code>&lambda;</code> of
- * <code><b>Z</b>[&tau;]</code>.
- * @param mu The parameter <code>&mu;</code> of the elliptic curve.
- * @param lambda The element <code>&lambda;</code> of
- * <code><b>Z</b>[&tau;]</code>.
- * @return The norm of <code>&lambda;</code>.
- */
- public static BigInteger norm(final byte mu, ZTauElement lambda)
- {
- BigInteger norm;
-
- // s1 = u^2
- BigInteger s1 = lambda.u.multiply(lambda.u);
-
- // s2 = u * v
- BigInteger s2 = lambda.u.multiply(lambda.v);
-
- // s3 = 2 * v^2
- BigInteger s3 = lambda.v.multiply(lambda.v).shiftLeft(1);
-
- if (mu == 1)
- {
- norm = s1.add(s2).add(s3);
- }
- else if (mu == -1)
- {
- norm = s1.subtract(s2).add(s3);
- }
- else
- {
- throw new IllegalArgumentException("mu must be 1 or -1");
- }
-
- return norm;
- }
-
- /**
- * Computes the norm of an element <code>&lambda;</code> of
- * <code><b>R</b>[&tau;]</code>, where <code>&lambda; = u + v&tau;</code>
- * and <code>u</code> and <code>u</code> are real numbers (elements of
- * <code><b>R</b></code>).
- * @param mu The parameter <code>&mu;</code> of the elliptic curve.
- * @param u The real part of the element <code>&lambda;</code> of
- * <code><b>R</b>[&tau;]</code>.
- * @param v The <code>&tau;</code>-adic part of the element
- * <code>&lambda;</code> of <code><b>R</b>[&tau;]</code>.
- * @return The norm of <code>&lambda;</code>.
- */
- public static SimpleBigDecimal norm(final byte mu, SimpleBigDecimal u,
- SimpleBigDecimal v)
- {
- SimpleBigDecimal norm;
-
- // s1 = u^2
- SimpleBigDecimal s1 = u.multiply(u);
-
- // s2 = u * v
- SimpleBigDecimal s2 = u.multiply(v);
-
- // s3 = 2 * v^2
- SimpleBigDecimal s3 = v.multiply(v).shiftLeft(1);
-
- if (mu == 1)
- {
- norm = s1.add(s2).add(s3);
- }
- else if (mu == -1)
- {
- norm = s1.subtract(s2).add(s3);
- }
- else
- {
- throw new IllegalArgumentException("mu must be 1 or -1");
- }
-
- return norm;
- }
-
- /**
- * Rounds an element <code>&lambda;</code> of <code><b>R</b>[&tau;]</code>
- * to an element of <code><b>Z</b>[&tau;]</code>, such that their difference
- * has minimal norm. <code>&lambda;</code> is given as
- * <code>&lambda; = &lambda;<sub>0</sub> + &lambda;<sub>1</sub>&tau;</code>.
- * @param lambda0 The component <code>&lambda;<sub>0</sub></code>.
- * @param lambda1 The component <code>&lambda;<sub>1</sub></code>.
- * @param mu The parameter <code>&mu;</code> of the elliptic curve. Must
- * equal 1 or -1.
- * @return The rounded element of <code><b>Z</b>[&tau;]</code>.
- * @throws IllegalArgumentException if <code>lambda0</code> and
- * <code>lambda1</code> do not have same scale.
- */
- public static ZTauElement round(SimpleBigDecimal lambda0,
- SimpleBigDecimal lambda1, byte mu)
- {
- int scale = lambda0.getScale();
- if (lambda1.getScale() != scale)
- {
- throw new IllegalArgumentException("lambda0 and lambda1 do not " +
- "have same scale");
- }
-
- if (!((mu == 1) || (mu == -1)))
- {
- throw new IllegalArgumentException("mu must be 1 or -1");
- }
-
- BigInteger f0 = lambda0.round();
- BigInteger f1 = lambda1.round();
-
- SimpleBigDecimal eta0 = lambda0.subtract(f0);
- SimpleBigDecimal eta1 = lambda1.subtract(f1);
-
- // eta = 2*eta0 + mu*eta1
- SimpleBigDecimal eta = eta0.add(eta0);
- if (mu == 1)
- {
- eta = eta.add(eta1);
- }
- else
- {
- // mu == -1
- eta = eta.subtract(eta1);
- }
-
- // check1 = eta0 - 3*mu*eta1
- // check2 = eta0 + 4*mu*eta1
- SimpleBigDecimal threeEta1 = eta1.add(eta1).add(eta1);
- SimpleBigDecimal fourEta1 = threeEta1.add(eta1);
- SimpleBigDecimal check1;
- SimpleBigDecimal check2;
- if (mu == 1)
- {
- check1 = eta0.subtract(threeEta1);
- check2 = eta0.add(fourEta1);
- }
- else
- {
- // mu == -1
- check1 = eta0.add(threeEta1);
- check2 = eta0.subtract(fourEta1);
- }
-
- byte h0 = 0;
- byte h1 = 0;
-
- // if eta >= 1
- if (eta.compareTo(ECConstants.ONE) >= 0)
- {
- if (check1.compareTo(MINUS_ONE) < 0)
- {
- h1 = mu;
- }
- else
- {
- h0 = 1;
- }
- }
- else
- {
- // eta < 1
- if (check2.compareTo(ECConstants.TWO) >= 0)
- {
- h1 = mu;
- }
- }
-
- // if eta < -1
- if (eta.compareTo(MINUS_ONE) < 0)
- {
- if (check1.compareTo(ECConstants.ONE) >= 0)
- {
- h1 = (byte)-mu;
- }
- else
- {
- h0 = -1;
- }
- }
- else
- {
- // eta >= -1
- if (check2.compareTo(MINUS_TWO) < 0)
- {
- h1 = (byte)-mu;
- }
- }
-
- BigInteger q0 = f0.add(BigInteger.valueOf(h0));
- BigInteger q1 = f1.add(BigInteger.valueOf(h1));
- return new ZTauElement(q0, q1);
- }
-
- /**
- * Approximate division by <code>n</code>. For an integer
- * <code>k</code>, the value <code>&lambda; = s k / n</code> is
- * computed to <code>c</code> bits of accuracy.
- * @param k The parameter <code>k</code>.
- * @param s The curve parameter <code>s<sub>0</sub></code> or
- * <code>s<sub>1</sub></code>.
- * @param vm The Lucas Sequence element <code>V<sub>m</sub></code>.
- * @param a The parameter <code>a</code> of the elliptic curve.
- * @param m The bit length of the finite field
- * <code><b>F</b><sub>m</sub></code>.
- * @param c The number of bits of accuracy, i.e. the scale of the returned
- * <code>SimpleBigDecimal</code>.
- * @return The value <code>&lambda; = s k / n</code> computed to
- * <code>c</code> bits of accuracy.
- */
- public static SimpleBigDecimal approximateDivisionByN(BigInteger k,
- BigInteger s, BigInteger vm, byte a, int m, int c)
- {
- int _k = (m + 5)/2 + c;
- BigInteger ns = k.shiftRight(m - _k - 2 + a);
-
- BigInteger gs = s.multiply(ns);
-
- BigInteger hs = gs.shiftRight(m);
-
- BigInteger js = vm.multiply(hs);
-
- BigInteger gsPlusJs = gs.add(js);
- BigInteger ls = gsPlusJs.shiftRight(_k-c);
- if (gsPlusJs.testBit(_k-c-1))
- {
- // round up
- ls = ls.add(ECConstants.ONE);
- }
-
- return new SimpleBigDecimal(ls, c);
- }
-
- /**
- * Computes the <code>&tau;</code>-adic NAF (non-adjacent form) of an
- * element <code>&lambda;</code> of <code><b>Z</b>[&tau;]</code>.
- * @param mu The parameter <code>&mu;</code> of the elliptic curve.
- * @param lambda The element <code>&lambda;</code> of
- * <code><b>Z</b>[&tau;]</code>.
- * @return The <code>&tau;</code>-adic NAF of <code>&lambda;</code>.
- */
- public static byte[] tauAdicNaf(byte mu, ZTauElement lambda)
- {
- if (!((mu == 1) || (mu == -1)))
- {
- throw new IllegalArgumentException("mu must be 1 or -1");
- }
-
- BigInteger norm = norm(mu, lambda);
-
- // Ceiling of log2 of the norm
- int log2Norm = norm.bitLength();
-
- // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52
- int maxLength = log2Norm > 30 ? log2Norm + 4 : 34;
-
- // The array holding the TNAF
- byte[] u = new byte[maxLength];
- int i = 0;
-
- // The actual length of the TNAF
- int length = 0;
-
- BigInteger r0 = lambda.u;
- BigInteger r1 = lambda.v;
-
- while(!((r0.equals(ECConstants.ZERO)) && (r1.equals(ECConstants.ZERO))))
- {
- // If r0 is odd
- if (r0.testBit(0))
- {
- u[i] = (byte) ECConstants.TWO.subtract((r0.subtract(r1.shiftLeft(1))).mod(ECConstants.FOUR)).intValue();
-
- // r0 = r0 - u[i]
- if (u[i] == 1)
- {
- r0 = r0.clearBit(0);
- }
- else
- {
- // u[i] == -1
- r0 = r0.add(ECConstants.ONE);
- }
- length = i;
- }
- else
- {
- u[i] = 0;
- }
-
- BigInteger t = r0;
- BigInteger s = r0.shiftRight(1);
- if (mu == 1)
- {
- r0 = r1.add(s);
- }
- else
- {
- // mu == -1
- r0 = r1.subtract(s);
- }
-
- r1 = t.shiftRight(1).negate();
- i++;
- }
-
- length++;
-
- // Reduce the TNAF array to its actual length
- byte[] tnaf = new byte[length];
- System.arraycopy(u, 0, tnaf, 0, length);
- return tnaf;
- }
-
- /**
- * Applies the operation <code>&tau;()</code> to an
- * <code>ECPoint.F2m</code>.
- * @param p The ECPoint.F2m to which <code>&tau;()</code> is applied.
- * @return <code>&tau;(p)</code>
- */
- public static ECPoint.F2m tau(ECPoint.F2m p)
- {
- return p.tau();
- }
-
- /**
- * Returns the parameter <code>&mu;</code> of the elliptic curve.
- * @param curve The elliptic curve from which to obtain <code>&mu;</code>.
- * The curve must be a Koblitz curve, i.e. <code>a</code> equals
- * <code>0</code> or <code>1</code> and <code>b</code> equals
- * <code>1</code>.
- * @return <code>&mu;</code> of the elliptic curve.
- * @throws IllegalArgumentException if the given ECCurve is not a Koblitz
- * curve.
- */
- public static byte getMu(ECCurve.F2m curve)
- {
- if (!curve.isKoblitz())
- {
- throw new IllegalArgumentException("No Koblitz curve (ABC), TNAF multiplication not possible");
- }
-
- if (curve.getA().isZero())
- {
- return -1;
- }
-
- return 1;
- }
-
- /**
- * Calculates the Lucas Sequence elements <code>U<sub>k-1</sub></code> and
- * <code>U<sub>k</sub></code> or <code>V<sub>k-1</sub></code> and
- * <code>V<sub>k</sub></code>.
- * @param mu The parameter <code>&mu;</code> of the elliptic curve.
- * @param k The index of the second element of the Lucas Sequence to be
- * returned.
- * @param doV If set to true, computes <code>V<sub>k-1</sub></code> and
- * <code>V<sub>k</sub></code>, otherwise <code>U<sub>k-1</sub></code> and
- * <code>U<sub>k</sub></code>.
- * @return An array with 2 elements, containing <code>U<sub>k-1</sub></code>
- * and <code>U<sub>k</sub></code> or <code>V<sub>k-1</sub></code>
- * and <code>V<sub>k</sub></code>.
- */
- public static BigInteger[] getLucas(byte mu, int k, boolean doV)
- {
- if (!((mu == 1) || (mu == -1)))
- {
- throw new IllegalArgumentException("mu must be 1 or -1");
- }
-
- BigInteger u0;
- BigInteger u1;
- BigInteger u2;
-
- if (doV)
- {
- u0 = ECConstants.TWO;
- u1 = BigInteger.valueOf(mu);
- }
- else
- {
- u0 = ECConstants.ZERO;
- u1 = ECConstants.ONE;
- }
-
- for (int i = 1; i < k; i++)
- {
- // u2 = mu*u1 - 2*u0;
- BigInteger s = null;
- if (mu == 1)
- {
- s = u1;
- }
- else
- {
- // mu == -1
- s = u1.negate();
- }
-
- u2 = s.subtract(u0.shiftLeft(1));
- u0 = u1;
- u1 = u2;
-// System.out.println(i + ": " + u2);
-// System.out.println();
- }
-
- BigInteger[] retVal = {u0, u1};
- return retVal;
- }
-
- /**
- * Computes the auxiliary value <code>t<sub>w</sub></code>. If the width is
- * 4, then for <code>mu = 1</code>, <code>t<sub>w</sub> = 6</code> and for
- * <code>mu = -1</code>, <code>t<sub>w</sub> = 10</code>
- * @param mu The parameter <code>&mu;</code> of the elliptic curve.
- * @param w The window width of the WTNAF.
- * @return the auxiliary value <code>t<sub>w</sub></code>
- */
- public static BigInteger getTw(byte mu, int w)
- {
- if (w == 4)
- {
- if (mu == 1)
- {
- return BigInteger.valueOf(6);
- }
- else
- {
- // mu == -1
- return BigInteger.valueOf(10);
- }
- }
- else
- {
- // For w <> 4, the values must be computed
- BigInteger[] us = getLucas(mu, w, false);
- BigInteger twoToW = ECConstants.ZERO.setBit(w);
- BigInteger u1invert = us[1].modInverse(twoToW);
- BigInteger tw;
- tw = ECConstants.TWO.multiply(us[0]).multiply(u1invert).mod(twoToW);
-// System.out.println("mu = " + mu);
-// System.out.println("tw = " + tw);
- return tw;
- }
- }
-
- /**
- * Computes the auxiliary values <code>s<sub>0</sub></code> and
- * <code>s<sub>1</sub></code> used for partial modular reduction.
- * @param curve The elliptic curve for which to compute
- * <code>s<sub>0</sub></code> and <code>s<sub>1</sub></code>.
- * @throws IllegalArgumentException if <code>curve</code> is not a
- * Koblitz curve (Anomalous Binary Curve, ABC).
- */
- public static BigInteger[] getSi(ECCurve.F2m curve)
- {
- if (!curve.isKoblitz())
- {
- throw new IllegalArgumentException("si is defined for Koblitz curves only");
- }
-
- int m = curve.getM();
- int a = curve.getA().toBigInteger().intValue();
- byte mu = curve.getMu();
- int shifts = getShiftsForCofactor(curve.getCofactor());
- int index = m + 3 - a;
- BigInteger[] ui = getLucas(mu, index, false);
- if (mu == 1)
- {
- ui[0] = ui[0].negate();
- ui[1] = ui[1].negate();
- }
-
- BigInteger dividend0 = ECConstants.ONE.add(ui[1]).shiftRight(shifts);
- BigInteger dividend1 = ECConstants.ONE.add(ui[0]).shiftRight(shifts).negate();
-
- return new BigInteger[] { dividend0, dividend1 };
- }
-
- protected static int getShiftsForCofactor(BigInteger h)
- {
- if (h != null)
- {
- if (h.equals(ECConstants.TWO))
- {
- return 1;
- }
- if (h.equals(ECConstants.FOUR))
- {
- return 2;
- }
- }
-
- throw new IllegalArgumentException("h (Cofactor) must be 2 or 4");
- }
-
- /**
- * Partial modular reduction modulo
- * <code>(&tau;<sup>m</sup> - 1)/(&tau; - 1)</code>.
- * @param k The integer to be reduced.
- * @param m The bitlength of the underlying finite field.
- * @param a The parameter <code>a</code> of the elliptic curve.
- * @param s The auxiliary values <code>s<sub>0</sub></code> and
- * <code>s<sub>1</sub></code>.
- * @param mu The parameter &mu; of the elliptic curve.
- * @param c The precision (number of bits of accuracy) of the partial
- * modular reduction.
- * @return <code>&rho; := k partmod (&tau;<sup>m</sup> - 1)/(&tau; - 1)</code>
- */
- public static ZTauElement partModReduction(BigInteger k, int m, byte a,
- BigInteger[] s, byte mu, byte c)
- {
- // d0 = s[0] + mu*s[1]; mu is either 1 or -1
- BigInteger d0;
- if (mu == 1)
- {
- d0 = s[0].add(s[1]);
- }
- else
- {
- d0 = s[0].subtract(s[1]);
- }
-
- BigInteger[] v = getLucas(mu, m, true);
- BigInteger vm = v[1];
-
- SimpleBigDecimal lambda0 = approximateDivisionByN(
- k, s[0], vm, a, m, c);
-
- SimpleBigDecimal lambda1 = approximateDivisionByN(
- k, s[1], vm, a, m, c);
-
- ZTauElement q = round(lambda0, lambda1, mu);
-
- // r0 = n - d0*q0 - 2*s1*q1
- BigInteger r0 = k.subtract(d0.multiply(q.u)).subtract(
- BigInteger.valueOf(2).multiply(s[1]).multiply(q.v));
-
- // r1 = s1*q0 - s0*q1
- BigInteger r1 = s[1].multiply(q.u).subtract(s[0].multiply(q.v));
-
- return new ZTauElement(r0, r1);
- }
-
- /**
- * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
- * by a <code>BigInteger</code> using the reduced <code>&tau;</code>-adic
- * NAF (RTNAF) method.
- * @param p The ECPoint.F2m to multiply.
- * @param k The <code>BigInteger</code> by which to multiply <code>p</code>.
- * @return <code>k * p</code>
- */
- public static ECPoint.F2m multiplyRTnaf(ECPoint.F2m p, BigInteger k)
- {
- ECCurve.F2m curve = (ECCurve.F2m) p.getCurve();
- int m = curve.getM();
- byte a = (byte) curve.getA().toBigInteger().intValue();
- byte mu = curve.getMu();
- BigInteger[] s = curve.getSi();
- ZTauElement rho = partModReduction(k, m, a, s, mu, (byte)10);
-
- return multiplyTnaf(p, rho);
- }
-
- /**
- * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
- * by an element <code>&lambda;</code> of <code><b>Z</b>[&tau;]</code>
- * using the <code>&tau;</code>-adic NAF (TNAF) method.
- * @param p The ECPoint.F2m to multiply.
- * @param lambda The element <code>&lambda;</code> of
- * <code><b>Z</b>[&tau;]</code>.
- * @return <code>&lambda; * p</code>
- */
- public static ECPoint.F2m multiplyTnaf(ECPoint.F2m p, ZTauElement lambda)
- {
- ECCurve.F2m curve = (ECCurve.F2m)p.getCurve();
- byte mu = curve.getMu();
- byte[] u = tauAdicNaf(mu, lambda);
-
- ECPoint.F2m q = multiplyFromTnaf(p, u);
-
- return q;
- }
-
- /**
- * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
- * by an element <code>&lambda;</code> of <code><b>Z</b>[&tau;]</code>
- * using the <code>&tau;</code>-adic NAF (TNAF) method, given the TNAF
- * of <code>&lambda;</code>.
- * @param p The ECPoint.F2m to multiply.
- * @param u The the TNAF of <code>&lambda;</code>..
- * @return <code>&lambda; * p</code>
- */
- public static ECPoint.F2m multiplyFromTnaf(ECPoint.F2m p, byte[] u)
- {
- ECCurve.F2m curve = (ECCurve.F2m)p.getCurve();
- ECPoint.F2m q = (ECPoint.F2m) curve.getInfinity();
- for (int i = u.length - 1; i >= 0; i--)
- {
- q = tau(q);
- if (u[i] == 1)
- {
- q = (ECPoint.F2m)q.addSimple(p);
- }
- else if (u[i] == -1)
- {
- q = (ECPoint.F2m)q.subtractSimple(p);
- }
- }
- return q;
- }
-
- /**
- * Computes the <code>[&tau;]</code>-adic window NAF of an element
- * <code>&lambda;</code> of <code><b>Z</b>[&tau;]</code>.
- * @param mu The parameter &mu; of the elliptic curve.
- * @param lambda The element <code>&lambda;</code> of
- * <code><b>Z</b>[&tau;]</code> of which to compute the
- * <code>[&tau;]</code>-adic NAF.
- * @param width The window width of the resulting WNAF.
- * @param pow2w 2<sup>width</sup>.
- * @param tw The auxiliary value <code>t<sub>w</sub></code>.
- * @param alpha The <code>&alpha;<sub>u</sub></code>'s for the window width.
- * @return The <code>[&tau;]</code>-adic window NAF of
- * <code>&lambda;</code>.
- */
- public static byte[] tauAdicWNaf(byte mu, ZTauElement lambda,
- byte width, BigInteger pow2w, BigInteger tw, ZTauElement[] alpha)
- {
- if (!((mu == 1) || (mu == -1)))
- {
- throw new IllegalArgumentException("mu must be 1 or -1");
- }
-
- BigInteger norm = norm(mu, lambda);
-
- // Ceiling of log2 of the norm
- int log2Norm = norm.bitLength();
-
- // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52
- int maxLength = log2Norm > 30 ? log2Norm + 4 + width : 34 + width;
-
- // The array holding the TNAF
- byte[] u = new byte[maxLength];
-
- // 2^(width - 1)
- BigInteger pow2wMin1 = pow2w.shiftRight(1);
-
- // Split lambda into two BigIntegers to simplify calculations
- BigInteger r0 = lambda.u;
- BigInteger r1 = lambda.v;
- int i = 0;
-
- // while lambda <> (0, 0)
- while (!((r0.equals(ECConstants.ZERO))&&(r1.equals(ECConstants.ZERO))))
- {
- // if r0 is odd
- if (r0.testBit(0))
- {
- // uUnMod = r0 + r1*tw mod 2^width
- BigInteger uUnMod
- = r0.add(r1.multiply(tw)).mod(pow2w);
-
- byte uLocal;
- // if uUnMod >= 2^(width - 1)
- if (uUnMod.compareTo(pow2wMin1) >= 0)
- {
- uLocal = (byte) uUnMod.subtract(pow2w).intValue();
- }
- else
- {
- uLocal = (byte) uUnMod.intValue();
- }
- // uLocal is now in [-2^(width-1), 2^(width-1)-1]
-
- u[i] = uLocal;
- boolean s = true;
- if (uLocal < 0)
- {
- s = false;
- uLocal = (byte)-uLocal;
- }
- // uLocal is now >= 0
-
- if (s)
- {
- r0 = r0.subtract(alpha[uLocal].u);
- r1 = r1.subtract(alpha[uLocal].v);
- }
- else
- {
- r0 = r0.add(alpha[uLocal].u);
- r1 = r1.add(alpha[uLocal].v);
- }
- }
- else
- {
- u[i] = 0;
- }
-
- BigInteger t = r0;
-
- if (mu == 1)
- {
- r0 = r1.add(r0.shiftRight(1));
- }
- else
- {
- // mu == -1
- r0 = r1.subtract(r0.shiftRight(1));
- }
- r1 = t.shiftRight(1).negate();
- i++;
- }
- return u;
- }
-
- /**
- * Does the precomputation for WTNAF multiplication.
- * @param p The <code>ECPoint</code> for which to do the precomputation.
- * @param a The parameter <code>a</code> of the elliptic curve.
- * @return The precomputation array for <code>p</code>.
- */
- public static ECPoint.F2m[] getPreComp(ECPoint.F2m p, byte a)
- {
- ECPoint.F2m[] pu;
- pu = new ECPoint.F2m[16];
- pu[1] = p;
- byte[][] alphaTnaf;
- if (a == 0)
- {
- alphaTnaf = Tnaf.alpha0Tnaf;
- }
- else
- {
- // a == 1
- alphaTnaf = Tnaf.alpha1Tnaf;
- }
-
- int precompLen = alphaTnaf.length;
- for (int i = 3; i < precompLen; i = i + 2)
- {
- pu[i] = Tnaf.multiplyFromTnaf(p, alphaTnaf[i]);
- }
-
- p.getCurve().normalizeAll(pu);
-
- return pu;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/WNafL2RMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/WNafL2RMultiplier.java
deleted file mode 100644
index 90b08475..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/WNafL2RMultiplier.java
+++ /dev/null
@@ -1,96 +0,0 @@
-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: We try to optimize 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;
-
- // Optimization can only be used for values in the lower half of the table
- if ((n << 2) < (1 << width))
- {
- int highest = LongArray.bitLengths[n];
-
- // TODO Get addition/doubling cost ratio from curve and compare to 'scale' to see if worth substituting?
- int scale = width - highest;
- int lowBits = n ^ (1 << (highest - 1));
-
- int i1 = ((1 << (width - 1)) - 1);
- int i2 = (lowBits << scale) + 1;
- 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/core/src/main/java/org/bouncycastle/math/ec/WNafPreCompInfo.java b/core/src/main/java/org/bouncycastle/math/ec/WNafPreCompInfo.java
deleted file mode 100644
index e8f16e65..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/WNafPreCompInfo.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package org.bouncycastle.math.ec;
-
-/**
- * Class holding precomputation data for the WNAF (Window Non-Adjacent Form)
- * algorithm.
- */
-public class WNafPreCompInfo implements PreCompInfo
-{
- /**
- * Array holding the precomputed <code>ECPoint</code>s used for a Window
- * NAF multiplication.
- */
- protected ECPoint[] preComp = null;
-
- /**
- * Array holding the negations of the precomputed <code>ECPoint</code>s used
- * for a Window NAF multiplication.
- */
- protected ECPoint[] preCompNeg = null;
-
- /**
- * Holds an <code>ECPoint</code> representing twice(this). Used for the
- * Window NAF multiplication to create or extend the precomputed values.
- */
- protected ECPoint twice = null;
-
- public ECPoint[] getPreComp()
- {
- return preComp;
- }
-
- public void setPreComp(ECPoint[] preComp)
- {
- this.preComp = preComp;
- }
-
- public ECPoint[] getPreCompNeg()
- {
- return preCompNeg;
- }
-
- public void setPreCompNeg(ECPoint[] preCompNeg)
- {
- this.preCompNeg = preCompNeg;
- }
-
- public ECPoint getTwice()
- {
- return twice;
- }
-
- public void setTwice(ECPoint twice)
- {
- this.twice = twice;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/WNafUtil.java b/core/src/main/java/org/bouncycastle/math/ec/WNafUtil.java
deleted file mode 100644
index 7ac3160c..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/WNafUtil.java
+++ /dev/null
@@ -1,485 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-public abstract class WNafUtil
-{
- public static final String PRECOMP_NAME = "bc_wnaf";
-
- private static final int[] DEFAULT_WINDOW_SIZE_CUTOFFS = new int[]{ 13, 41, 121, 337, 897, 2305 };
-
- private static final byte[] EMPTY_BYTES = new byte[0];
- private static final int[] EMPTY_INTS = new int[0];
-
- public static int[] generateCompactNaf(BigInteger k)
- {
- if ((k.bitLength() >>> 16) != 0)
- {
- throw new IllegalArgumentException("'k' must have bitlength < 2^16");
- }
- if (k.signum() == 0)
- {
- return EMPTY_INTS;
- }
-
- BigInteger _3k = k.shiftLeft(1).add(k);
-
- int bits = _3k.bitLength();
- int[] naf = new int[bits >> 1];
-
- BigInteger diff = _3k.xor(k);
-
- int highBit = bits - 1, length = 0, zeroes = 0;
- for (int i = 1; i < highBit; ++i)
- {
- if (!diff.testBit(i))
- {
- ++zeroes;
- continue;
- }
-
- int digit = k.testBit(i) ? -1 : 1;
- naf[length++] = (digit << 16) | zeroes;
- zeroes = 1;
- ++i;
- }
-
- naf[length++] = (1 << 16) | zeroes;
-
- if (naf.length > length)
- {
- naf = trim(naf, length);
- }
-
- 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");
- }
- if (k.signum() == 0)
- {
- return EMPTY_INTS;
- }
-
- 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;
-
- int offset = 0;
- while ((d0 | d1) != 0 || k0.bitLength() > offset || k1.bitLength() > offset)
- {
- int n0 = ((k0.intValue() >>> offset) + d0) & 7, n1 = ((k1.intValue() >>> offset) + 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;
- }
- if ((d1 << 1) == 1 + u1)
- {
- d1 ^= 1;
- }
-
- if (++offset == 30)
- {
- offset = 0;
- k0 = k0.shiftRight(30);
- k1 = k1.shiftRight(30);
- }
-
- 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)
- {
- if (k.signum() == 0)
- {
- return EMPTY_BYTES;
- }
-
- BigInteger _3k = k.shiftLeft(1).add(k);
-
- int digits = _3k.bitLength() - 1;
- byte[] naf = new byte[digits];
-
- BigInteger diff = _3k.xor(k);
-
- for (int i = 1; i < digits; ++i)
- {
- if (diff.testBit(i))
- {
- naf[i - 1] = (byte)(k.testBit(i) ? -1 : 1);
- ++i;
- }
- }
-
- naf[digits - 1] = 1;
-
- return naf;
- }
-
- /**
- * 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]");
- }
- if (k.signum() == 0)
- {
- return EMPTY_BYTES;
- }
-
- 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 int getNafWeight(BigInteger k)
- {
- if (k.signum() == 0)
- {
- return 0;
- }
-
- BigInteger _3k = k.shiftLeft(1).add(k);
- BigInteger diff = _3k.xor(k);
-
- return diff.bitCount();
- }
-
- public static WNafPreCompInfo getWNafPreCompInfo(ECPoint p)
- {
- return getWNafPreCompInfo(p.getCurve().getPreCompInfo(p, PRECOMP_NAME));
- }
-
- public static WNafPreCompInfo getWNafPreCompInfo(PreCompInfo preCompInfo)
- {
- if ((preCompInfo != null) && (preCompInfo instanceof WNafPreCompInfo))
- {
- 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 ECPoint mapPointWithPrecomp(ECPoint p, int width, boolean includeNegated,
- ECPointMap pointMap)
- {
- ECCurve c = p.getCurve();
- WNafPreCompInfo wnafPreCompP = precompute(p, width, includeNegated);
-
- ECPoint q = pointMap.map(p);
- WNafPreCompInfo wnafPreCompQ = getWNafPreCompInfo(c.getPreCompInfo(q, PRECOMP_NAME));
-
- ECPoint twiceP = wnafPreCompP.getTwice();
- if (twiceP != null)
- {
- ECPoint twiceQ = pointMap.map(twiceP);
- wnafPreCompQ.setTwice(twiceQ);
- }
-
- ECPoint[] preCompP = wnafPreCompP.getPreComp();
- ECPoint[] preCompQ = new ECPoint[preCompP.length];
- for (int i = 0; i < preCompP.length; ++i)
- {
- preCompQ[i] = pointMap.map(preCompP[i]);
- }
- wnafPreCompQ.setPreComp(preCompQ);
-
- if (includeNegated)
- {
- ECPoint[] preCompNegQ = new ECPoint[preCompQ.length];
- for (int i = 0; i < preCompNegQ.length; ++i)
- {
- preCompNegQ[i] = preCompQ[i].negate();
- }
- wnafPreCompQ.setPreCompNeg(preCompNegQ);
- }
-
- c.setPreCompInfo(q, PRECOMP_NAME, wnafPreCompQ);
-
- return q;
- }
-
- public static WNafPreCompInfo precompute(ECPoint p, int width, boolean includeNegated)
- {
- ECCurve c = p.getCurve();
- WNafPreCompInfo wnafPreCompInfo = getWNafPreCompInfo(c.getPreCompInfo(p, PRECOMP_NAME));
-
- 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)
- {
- preComp = resizeTable(preComp, reqPreCompLen);
- if (reqPreCompLen == 2)
- {
- preComp[1] = preComp[0].threeTimes();
- }
- else
- {
- ECPoint twiceP = wnafPreCompInfo.getTwice();
- if (twiceP == null)
- {
- twiceP = preComp[0].twice();
- wnafPreCompInfo.setTwice(twiceP);
- }
-
- for (int i = preCompLen; i < reqPreCompLen; i++)
- {
- /*
- * Compute the new ECPoints for the precomputation array. The values 1, 3, 5, ...,
- * 2^(width-1)-1 times p are computed
- */
- preComp[i] = twiceP.add(preComp[i - 1]);
- }
- }
-
- /*
- * 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, PRECOMP_NAME, 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/core/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java
deleted file mode 100644
index 93d03b46..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-/**
- * Class implementing the WTNAF (Window
- * <code>&tau;</code>-adic Non-Adjacent Form) algorithm.
- */
-public class WTauNafMultiplier extends AbstractECMultiplier
-{
- // TODO Create WTauNafUtil class and move various functionality into it
- static final String PRECOMP_NAME = "bc_wtnaf";
-
- /**
- * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
- * by <code>k</code> using the reduced <code>&tau;</code>-adic NAF (RTNAF)
- * method.
- * @param p The ECPoint.F2m to multiply.
- * @param k The integer by which to multiply <code>k</code>.
- * @return <code>p</code> multiplied by <code>k</code>.
- */
- protected ECPoint multiplyPositive(ECPoint point, BigInteger k)
- {
- if (!(point instanceof ECPoint.F2m))
- {
- throw new IllegalArgumentException("Only ECPoint.F2m can be " +
- "used in WTauNafMultiplier");
- }
-
- ECPoint.F2m p = (ECPoint.F2m)point;
- ECCurve.F2m curve = (ECCurve.F2m)p.getCurve();
- int m = curve.getM();
- byte a = curve.getA().toBigInteger().byteValue();
- byte mu = curve.getMu();
- BigInteger[] s = curve.getSi();
-
- ZTauElement rho = Tnaf.partModReduction(k, m, a, s, mu, (byte)10);
-
- return multiplyWTnaf(p, rho, curve.getPreCompInfo(p, PRECOMP_NAME), a, mu);
- }
-
- /**
- * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
- * by an element <code>&lambda;</code> of <code><b>Z</b>[&tau;]</code> using
- * the <code>&tau;</code>-adic NAF (TNAF) method.
- * @param p The ECPoint.F2m to multiply.
- * @param lambda The element <code>&lambda;</code> of
- * <code><b>Z</b>[&tau;]</code> of which to compute the
- * <code>[&tau;]</code>-adic NAF.
- * @return <code>p</code> multiplied by <code>&lambda;</code>.
- */
- private ECPoint.F2m multiplyWTnaf(ECPoint.F2m p, ZTauElement lambda,
- PreCompInfo preCompInfo, byte a, byte mu)
- {
- ZTauElement[] alpha = (a == 0) ? Tnaf.alpha0 : Tnaf.alpha1;
-
- BigInteger tw = Tnaf.getTw(mu, Tnaf.WIDTH);
-
- byte[]u = Tnaf.tauAdicWNaf(mu, lambda, Tnaf.WIDTH,
- BigInteger.valueOf(Tnaf.POW_2_WIDTH), tw, alpha);
-
- return multiplyFromWTnaf(p, u, preCompInfo);
- }
-
- /**
- * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
- * by an element <code>&lambda;</code> of <code><b>Z</b>[&tau;]</code>
- * using the window <code>&tau;</code>-adic NAF (TNAF) method, given the
- * WTNAF of <code>&lambda;</code>.
- * @param p The ECPoint.F2m to multiply.
- * @param u The the WTNAF of <code>&lambda;</code>..
- * @return <code>&lambda; * p</code>
- */
- private static ECPoint.F2m multiplyFromWTnaf(ECPoint.F2m p, byte[] u, PreCompInfo preCompInfo)
- {
- ECCurve.F2m curve = (ECCurve.F2m)p.getCurve();
- byte a = curve.getA().toBigInteger().byteValue();
-
- ECPoint.F2m[] pu;
- if ((preCompInfo == null) || !(preCompInfo instanceof WTauNafPreCompInfo))
- {
- pu = Tnaf.getPreComp(p, a);
-
- WTauNafPreCompInfo pre = new WTauNafPreCompInfo();
- pre.setPreComp(pu);
- curve.setPreCompInfo(p, PRECOMP_NAME, pre);
- }
- else
- {
- pu = ((WTauNafPreCompInfo)preCompInfo).getPreComp();
- }
-
- // q = infinity
- ECPoint.F2m q = (ECPoint.F2m) p.getCurve().getInfinity();
- for (int i = u.length - 1; i >= 0; i--)
- {
- q = Tnaf.tau(q);
- byte ui = u[i];
- if (ui != 0)
- {
- if (ui > 0)
- {
- q = q.addSimple(pu[ui]);
- }
- else
- {
- q = q.subtractSimple(pu[-ui]);
- }
- }
- }
-
- return q;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/WTauNafPreCompInfo.java b/core/src/main/java/org/bouncycastle/math/ec/WTauNafPreCompInfo.java
deleted file mode 100644
index 190eecba..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/WTauNafPreCompInfo.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.bouncycastle.math.ec;
-
-/**
- * Class holding precomputation data for the WTNAF (Window
- * <code>&tau;</code>-adic Non-Adjacent Form) algorithm.
- */
-public class WTauNafPreCompInfo implements PreCompInfo
-{
- /**
- * Array holding the precomputed <code>ECPoint.F2m</code>s used for the
- * WTNAF multiplication in <code>
- * {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply()
- * WTauNafMultiplier.multiply()}</code>.
- */
- protected ECPoint.F2m[] preComp = null;
-
- public ECPoint.F2m[] getPreComp()
- {
- return preComp;
- }
-
- public void setPreComp(ECPoint.F2m[] preComp)
- {
- this.preComp = preComp;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/ZSignedDigitL2RMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/ZSignedDigitL2RMultiplier.java
deleted file mode 100644
index b478dc70..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/ZSignedDigitL2RMultiplier.java
+++ /dev/null
@@ -1,29 +0,0 @@
-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/core/src/main/java/org/bouncycastle/math/ec/ZSignedDigitR2LMultiplier.java b/core/src/main/java/org/bouncycastle/math/ec/ZSignedDigitR2LMultiplier.java
deleted file mode 100644
index baa702f8..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/ZSignedDigitR2LMultiplier.java
+++ /dev/null
@@ -1,30 +0,0 @@
-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/core/src/main/java/org/bouncycastle/math/ec/ZTauElement.java b/core/src/main/java/org/bouncycastle/math/ec/ZTauElement.java
deleted file mode 100644
index 7402f222..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/ZTauElement.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-/**
- * Class representing an element of <code><b>Z</b>[&tau;]</code>. Let
- * <code>&lambda;</code> be an element of <code><b>Z</b>[&tau;]</code>. Then
- * <code>&lambda;</code> is given as <code>&lambda; = u + v&tau;</code>. The
- * components <code>u</code> and <code>v</code> may be used directly, there
- * are no accessor methods.
- * Immutable class.
- */
-class ZTauElement
-{
- /**
- * The &quot;real&quot; part of <code>&lambda;</code>.
- */
- public final BigInteger u;
-
- /**
- * The &quot;<code>&tau;</code>-adic&quot; part of <code>&lambda;</code>.
- */
- public final BigInteger v;
-
- /**
- * Constructor for an element <code>&lambda;</code> of
- * <code><b>Z</b>[&tau;]</code>.
- * @param u The &quot;real&quot; part of <code>&lambda;</code>.
- * @param v The &quot;<code>&tau;</code>-adic&quot; part of
- * <code>&lambda;</code>.
- */
- public ZTauElement(BigInteger u, BigInteger v)
- {
- this.u = u;
- this.v = v;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519.java b/core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519.java
deleted file mode 100644
index e7839ce2..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package org.bouncycastle.math.ec.custom.djb;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.raw.Nat256;
-import org.bouncycastle.util.encoders.Hex;
-
-public class Curve25519 extends ECCurve.AbstractFp
-{
- public static final BigInteger q = Nat256.toBigInteger(Curve25519Field.P);
-
- private static final int Curve25519_DEFAULT_COORDS = COORD_JACOBIAN_MODIFIED;
-
- protected Curve25519Point infinity;
-
- public Curve25519()
- {
- super(q);
-
- this.infinity = new Curve25519Point(this, null, null);
-
- this.a = fromBigInteger(new BigInteger(1,
- Hex.decode("2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA984914A144")));
- this.b = fromBigInteger(new BigInteger(1,
- Hex.decode("7B425ED097B425ED097B425ED097B425ED097B425ED097B4260B5E9C7710C864")));
- this.order = new BigInteger(1, Hex.decode("1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED"));
- this.cofactor = BigInteger.valueOf(8);
-
- this.coord = Curve25519_DEFAULT_COORDS;
- }
-
- protected ECCurve cloneCurve()
- {
- return new Curve25519();
- }
-
- public boolean supportsCoordinateSystem(int coord)
- {
- switch (coord)
- {
- case COORD_JACOBIAN_MODIFIED:
- return true;
- default:
- return false;
- }
- }
-
- public BigInteger getQ()
- {
- return q;
- }
-
- public int getFieldSize()
- {
- return q.bitLength();
- }
-
- public ECFieldElement fromBigInteger(BigInteger x)
- {
- return new Curve25519FieldElement(x);
- }
-
- protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- return new Curve25519Point(this, x, y, withCompression);
- }
-
- protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
- {
- return new Curve25519Point(this, x, y, zs, withCompression);
- }
-
- public ECPoint getInfinity()
- {
- return infinity;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519Field.java b/core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519Field.java
deleted file mode 100644
index 2e8e335d..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519Field.java
+++ /dev/null
@@ -1,254 +0,0 @@
-package org.bouncycastle.math.ec.custom.djb;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.raw.Nat;
-import org.bouncycastle.math.raw.Nat256;
-
-public class Curve25519Field
-{
- private static final long M = 0xFFFFFFFFL;
-
- // 2^255 - 2^4 - 2^1 - 1
- static final int[] P = new int[]{ 0xFFFFFFED, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
- 0xFFFFFFFF, 0x7FFFFFFF };
- private static final int P7 = 0x7FFFFFFF;
- private static final int[] PExt = new int[]{ 0x00000169, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFED, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
- 0xFFFFFFFF, 0x3FFFFFFF };
- private static final int PInv = 0x13;
-
- public static void add(int[] x, int[] y, int[] z)
- {
- Nat256.add(x, y, z);
- if (Nat256.gte(z, P))
- {
- subPFrom(z);
- }
- }
-
- public static void addExt(int[] xx, int[] yy, int[] zz)
- {
- Nat.add(16, xx, yy, zz);
- if (Nat.gte(16, zz, PExt))
- {
- subPExtFrom(zz);
- }
- }
-
- public static void addOne(int[] x, int[] z)
- {
- Nat.inc(8, x, z);
- if (Nat256.gte(z, P))
- {
- subPFrom(z);
- }
- }
-
- public static int[] fromBigInteger(BigInteger x)
- {
- int[] z = Nat256.fromBigInteger(x);
- while (Nat256.gte(z, P))
- {
- Nat256.subFrom(P, z);
- }
- return z;
- }
-
- public static void half(int[] x, int[] z)
- {
- if ((x[0] & 1) == 0)
- {
- Nat.shiftDownBit(8, x, 0, z);
- }
- else
- {
- Nat256.add(x, P, z);
- Nat.shiftDownBit(8, z, 0);
- }
- }
-
- public static void multiply(int[] x, int[] y, int[] z)
- {
- int[] tt = Nat256.createExt();
- Nat256.mul(x, y, tt);
- reduce(tt, z);
- }
-
- public static void multiplyAddToExt(int[] x, int[] y, int[] zz)
- {
- Nat256.mulAddTo(x, y, zz);
- if (Nat.gte(16, zz, PExt))
- {
- subPExtFrom(zz);
- }
- }
-
- public static void negate(int[] x, int[] z)
- {
- if (Nat256.isZero(x))
- {
- Nat256.zero(z);
- }
- else
- {
- Nat256.sub(P, x, z);
- }
- }
-
- public static void reduce(int[] xx, int[] z)
- {
-// assert xx[15] >>> 30 == 0;
-
- int xx07 = xx[7];
- Nat.shiftUpBit(8, xx, 8, xx07, z, 0);
- int c = Nat256.mulByWordAddTo(PInv, xx, z) << 1;
- int z7 = z[7];
- c += (z7 >>> 31) - (xx07 >>> 31);
- z7 &= P7;
- z7 += Nat.addWordTo(7, c * PInv, z);
- z[7] = z7;
- if (Nat256.gte(z, P))
- {
- subPFrom(z);
- }
- }
-
- public static void reduce27(int x, int[] z)
- {
-// assert x >>> 26 == 0;
-
- int z7 = z[7];
- int c = (x << 1 | z7 >>> 31);
- z7 &= P7;
- z7 += Nat.addWordTo(7, c * PInv, z);
- z[7] = z7;
- if (Nat256.gte(z, P))
- {
- subPFrom(z);
- }
- }
-
- public static void square(int[] x, int[] z)
- {
- int[] tt = Nat256.createExt();
- Nat256.square(x, tt);
- reduce(tt, z);
- }
-
- public static void squareN(int[] x, int n, int[] z)
- {
-// assert n > 0;
-
- int[] tt = Nat256.createExt();
- Nat256.square(x, tt);
- reduce(tt, z);
-
- while (--n > 0)
- {
- Nat256.square(z, tt);
- reduce(tt, z);
- }
- }
-
- public static void subtract(int[] x, int[] y, int[] z)
- {
- int c = Nat256.sub(x, y, z);
- if (c != 0)
- {
- addPTo(z);
- }
- }
-
- public static void subtractExt(int[] xx, int[] yy, int[] zz)
- {
- int c = Nat.sub(16, xx, yy, zz);
- if (c != 0)
- {
- addPExtTo(zz);
- }
- }
-
- public static void twice(int[] x, int[] z)
- {
- Nat.shiftUpBit(8, x, 0, z);
- if (Nat256.gte(z, P))
- {
- subPFrom(z);
- }
- }
-
- private static int addPTo(int[] z)
- {
- long c = (z[0] & M) - PInv;
- z[0] = (int)c;
- c >>= 32;
- if (c != 0)
- {
- c = Nat.decAt(7, z, 1);
- }
- c += (z[7] & M) + ((P7 + 1) & M);
- z[7] = (int)c;
- c >>= 32;
- return (int)c;
- }
-
- private static int addPExtTo(int[] zz)
- {
- long c = (zz[0] & M) + (PExt[0] & M);
- zz[0] = (int)c;
- c >>= 32;
- if (c != 0)
- {
- c = Nat.incAt(8, zz, 1);
- }
- c += (zz[8] & M) - PInv;
- zz[8] = (int)c;
- c >>= 32;
- if (c != 0)
- {
- c = Nat.decAt(15, zz, 9);
- }
- c += (zz[15] & M) + ((PExt[15] + 1) & M);
- zz[15] = (int)c;
- c >>= 32;
- return (int)c;
- }
-
- private static int subPFrom(int[] z)
- {
- long c = (z[0] & M) + PInv;
- z[0] = (int)c;
- c >>= 32;
- if (c != 0)
- {
- c = Nat.incAt(7, z, 1);
- }
- c += (z[7] & M) - ((P7 + 1) & M);
- z[7] = (int)c;
- c >>= 32;
- return (int)c;
- }
-
- private static int subPExtFrom(int[] zz)
- {
- long c = (zz[0] & M) - (PExt[0] & M);
- zz[0] = (int)c;
- c >>= 32;
- if (c != 0)
- {
- c = Nat.decAt(8, zz, 1);
- }
- c += (zz[8] & M) + PInv;
- zz[8] = (int)c;
- c >>= 32;
- if (c != 0)
- {
- c = Nat.incAt(15, zz, 9);
- }
- c += (zz[15] & M) - ((PExt[15] + 1) & M);
- zz[15] = (int)c;
- c >>= 32;
- return (int)c;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519FieldElement.java b/core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519FieldElement.java
deleted file mode 100644
index 010b6f55..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519FieldElement.java
+++ /dev/null
@@ -1,234 +0,0 @@
-package org.bouncycastle.math.ec.custom.djb;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.raw.Mod;
-import org.bouncycastle.math.raw.Nat256;
-import org.bouncycastle.util.Arrays;
-
-public class Curve25519FieldElement extends ECFieldElement
-{
- public static final BigInteger Q = Curve25519.q;
-
- // Calculated as ECConstants.TWO.modPow(Q.shiftRight(2), Q)
- private static final int[] PRECOMP_POW2 = new int[]{ 0x4a0ea0b0, 0xc4ee1b27, 0xad2fe478, 0x2f431806,
- 0x3dfbd7a7, 0x2b4d0099, 0x4fc1df0b, 0x2b832480 };
-
- protected int[] x;
-
- public Curve25519FieldElement(BigInteger x)
- {
- if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
- {
- throw new IllegalArgumentException("x value invalid for Curve25519FieldElement");
- }
-
- this.x = Curve25519Field.fromBigInteger(x);
- }
-
- public Curve25519FieldElement()
- {
- this.x = Nat256.create();
- }
-
- protected Curve25519FieldElement(int[] x)
- {
- this.x = x;
- }
-
- public boolean isZero()
- {
- return Nat256.isZero(x);
- }
-
- public boolean isOne()
- {
- return Nat256.isOne(x);
- }
-
- public boolean testBitZero()
- {
- return Nat256.getBit(x, 0) == 1;
- }
-
- public BigInteger toBigInteger()
- {
- return Nat256.toBigInteger(x);
- }
-
- public String getFieldName()
- {
- return "Curve25519Field";
- }
-
- public int getFieldSize()
- {
- return Q.bitLength();
- }
-
- public ECFieldElement add(ECFieldElement b)
- {
- int[] z = Nat256.create();
- Curve25519Field.add(x, ((Curve25519FieldElement)b).x, z);
- return new Curve25519FieldElement(z);
- }
-
- public ECFieldElement addOne()
- {
- int[] z = Nat256.create();
- Curve25519Field.addOne(x, z);
- return new Curve25519FieldElement(z);
- }
-
- public ECFieldElement subtract(ECFieldElement b)
- {
- int[] z = Nat256.create();
- Curve25519Field.subtract(x, ((Curve25519FieldElement)b).x, z);
- return new Curve25519FieldElement(z);
- }
-
- public ECFieldElement multiply(ECFieldElement b)
- {
- int[] z = Nat256.create();
- Curve25519Field.multiply(x, ((Curve25519FieldElement)b).x, z);
- return new Curve25519FieldElement(z);
- }
-
- public ECFieldElement divide(ECFieldElement b)
- {
-// return multiply(b.invert());
- int[] z = Nat256.create();
- Mod.invert(Curve25519Field.P, ((Curve25519FieldElement)b).x, z);
- Curve25519Field.multiply(z, x, z);
- return new Curve25519FieldElement(z);
- }
-
- public ECFieldElement negate()
- {
- int[] z = Nat256.create();
- Curve25519Field.negate(x, z);
- return new Curve25519FieldElement(z);
- }
-
- public ECFieldElement square()
- {
- int[] z = Nat256.create();
- Curve25519Field.square(x, z);
- return new Curve25519FieldElement(z);
- }
-
- public ECFieldElement invert()
- {
-// return new Curve25519FieldElement(toBigInteger().modInverse(Q));
- int[] z = Nat256.create();
- Mod.invert(Curve25519Field.P, x, z);
- return new Curve25519FieldElement(z);
- }
-
- /**
- * return a sqrt root - the routine verifies that the calculation returns the right value - if
- * none exists it returns null.
- */
- public ECFieldElement sqrt()
- {
- /*
- * Q == 8m + 5, so we use Pocklington's method for this case.
- *
- * First, raise this element to the exponent 2^252 - 2^1 (i.e. m + 1)
- *
- * Breaking up the exponent's binary representation into "repunits", we get:
- * { 251 1s } { 1 0s }
- *
- * Therefore we need an addition chain containing 251 (the lengths of the repunits)
- * We use: 1, 2, 3, 4, 7, 11, 15, 30, 60, 120, 131, [251]
- */
-
- int[] x1 = this.x;
- if (Nat256.isZero(x1) || Nat256.isOne(x1))
- {
- return this;
- }
-
- int[] x2 = Nat256.create();
- Curve25519Field.square(x1, x2);
- Curve25519Field.multiply(x2, x1, x2);
- int[] x3 = x2;
- Curve25519Field.square(x2, x3);
- Curve25519Field.multiply(x3, x1, x3);
- int[] x4 = Nat256.create();
- Curve25519Field.square(x3, x4);
- Curve25519Field.multiply(x4, x1, x4);
- int[] x7 = Nat256.create();
- Curve25519Field.squareN(x4, 3, x7);
- Curve25519Field.multiply(x7, x3, x7);
- int[] x11 = x3;
- Curve25519Field.squareN(x7, 4, x11);
- Curve25519Field.multiply(x11, x4, x11);
- int[] x15 = x7;
- Curve25519Field.squareN(x11, 4, x15);
- Curve25519Field.multiply(x15, x4, x15);
- int[] x30 = x4;
- Curve25519Field.squareN(x15, 15, x30);
- Curve25519Field.multiply(x30, x15, x30);
- int[] x60 = x15;
- Curve25519Field.squareN(x30, 30, x60);
- Curve25519Field.multiply(x60, x30, x60);
- int[] x120 = x30;
- Curve25519Field.squareN(x60, 60, x120);
- Curve25519Field.multiply(x120, x60, x120);
- int[] x131 = x60;
- Curve25519Field.squareN(x120, 11, x131);
- Curve25519Field.multiply(x131, x11, x131);
- int[] x251 = x11;
- Curve25519Field.squareN(x131, 120, x251);
- Curve25519Field.multiply(x251, x120, x251);
-
- int[] t1 = x251;
- Curve25519Field.square(t1, t1);
-
- int[] t2 = x120;
- Curve25519Field.square(t1, t2);
-
- if (Nat256.eq(x1, t2))
- {
- return new Curve25519FieldElement(t1);
- }
-
- /*
- * If the first guess is incorrect, we multiply by a precomputed power of 2 to get the second guess,
- * which is ((4x)^(m + 1))/2 mod Q
- */
- Curve25519Field.multiply(t1, PRECOMP_POW2, t1);
-
- Curve25519Field.square(t1, t2);
-
- if (Nat256.eq(x1, t2))
- {
- return new Curve25519FieldElement(t1);
- }
-
- return null;
- }
-
- public boolean equals(Object other)
- {
- if (other == this)
- {
- return true;
- }
-
- if (!(other instanceof Curve25519FieldElement))
- {
- return false;
- }
-
- Curve25519FieldElement o = (Curve25519FieldElement)other;
- return Nat256.eq(x, o.x);
- }
-
- public int hashCode()
- {
- return Q.hashCode() ^ Arrays.hashCode(x, 0, 8);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519Point.java b/core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519Point.java
deleted file mode 100644
index b2700e30..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/djb/Curve25519Point.java
+++ /dev/null
@@ -1,348 +0,0 @@
-package org.bouncycastle.math.ec.custom.djb;
-
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.raw.Nat256;
-
-public class Curve25519Point extends ECPoint.AbstractFp
-{
- /**
- * Create a point which encodes with point compression.
- *
- * @param curve the curve to use
- * @param x affine x co-ordinate
- * @param y affine y co-ordinate
- *
- * @deprecated Use ECCurve.createPoint to construct points
- */
- public Curve25519Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- this(curve, x, y, false);
- }
-
- /**
- * Create a point that encodes with or without point compresion.
- *
- * @param curve the curve to use
- * @param x affine x co-ordinate
- * @param y affine y co-ordinate
- * @param withCompression if true encode with point compression
- *
- * @deprecated per-point compression property will be removed, refer {@link #getEncoded(boolean)}
- */
- public Curve25519Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- super(curve, x, y);
-
- if ((x == null) != (y == null))
- {
- throw new IllegalArgumentException("Exactly one of the field elements is null");
- }
-
- this.withCompression = withCompression;
- }
-
- Curve25519Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
- {
- super(curve, x, y, zs);
-
- this.withCompression = withCompression;
- }
-
- protected ECPoint detach()
- {
- return new Curve25519Point(null, getAffineXCoord(), getAffineYCoord());
- }
-
- public ECFieldElement getZCoord(int index)
- {
- if (index == 1)
- {
- return getJacobianModifiedW();
- }
-
- return super.getZCoord(index);
- }
-
- public ECPoint add(ECPoint b)
- {
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return this;
- }
- if (this == b)
- {
- return twice();
- }
-
- ECCurve curve = this.getCurve();
-
- Curve25519FieldElement X1 = (Curve25519FieldElement)this.x, Y1 = (Curve25519FieldElement)this.y,
- Z1 = (Curve25519FieldElement)this.zs[0];
- Curve25519FieldElement X2 = (Curve25519FieldElement)b.getXCoord(), Y2 = (Curve25519FieldElement)b.getYCoord(),
- Z2 = (Curve25519FieldElement)b.getZCoord(0);
-
- int c;
- int[] tt1 = Nat256.createExt();
- int[] t2 = Nat256.create();
- int[] t3 = Nat256.create();
- int[] t4 = Nat256.create();
-
- boolean Z1IsOne = Z1.isOne();
- int[] U2, S2;
- if (Z1IsOne)
- {
- U2 = X2.x;
- S2 = Y2.x;
- }
- else
- {
- S2 = t3;
- Curve25519Field.square(Z1.x, S2);
-
- U2 = t2;
- Curve25519Field.multiply(S2, X2.x, U2);
-
- Curve25519Field.multiply(S2, Z1.x, S2);
- Curve25519Field.multiply(S2, Y2.x, S2);
- }
-
- boolean Z2IsOne = Z2.isOne();
- int[] U1, S1;
- if (Z2IsOne)
- {
- U1 = X1.x;
- S1 = Y1.x;
- }
- else
- {
- S1 = t4;
- Curve25519Field.square(Z2.x, S1);
-
- U1 = tt1;
- Curve25519Field.multiply(S1, X1.x, U1);
-
- Curve25519Field.multiply(S1, Z2.x, S1);
- Curve25519Field.multiply(S1, Y1.x, S1);
- }
-
- int[] H = Nat256.create();
- Curve25519Field.subtract(U1, U2, H);
-
- int[] R = t2;
- Curve25519Field.subtract(S1, S2, R);
-
- // Check if b == this or b == -this
- if (Nat256.isZero(H))
- {
- if (Nat256.isZero(R))
- {
- // this == b, i.e. this must be doubled
- return this.twice();
- }
-
- // this == -b, i.e. the result is the point at infinity
- return curve.getInfinity();
- }
-
- int[] HSquared = Nat256.create();
- Curve25519Field.square(H, HSquared);
-
- int[] G = Nat256.create();
- Curve25519Field.multiply(HSquared, H, G);
-
- int[] V = t3;
- Curve25519Field.multiply(HSquared, U1, V);
-
- Curve25519Field.negate(G, G);
- Nat256.mul(S1, G, tt1);
-
- c = Nat256.addBothTo(V, V, G);
- Curve25519Field.reduce27(c, G);
-
- Curve25519FieldElement X3 = new Curve25519FieldElement(t4);
- Curve25519Field.square(R, X3.x);
- Curve25519Field.subtract(X3.x, G, X3.x);
-
- Curve25519FieldElement Y3 = new Curve25519FieldElement(G);
- Curve25519Field.subtract(V, X3.x, Y3.x);
- Curve25519Field.multiplyAddToExt(Y3.x, R, tt1);
- Curve25519Field.reduce(tt1, Y3.x);
-
- Curve25519FieldElement Z3 = new Curve25519FieldElement(H);
- if (!Z1IsOne)
- {
- Curve25519Field.multiply(Z3.x, Z1.x, Z3.x);
- }
- if (!Z2IsOne)
- {
- Curve25519Field.multiply(Z3.x, Z2.x, Z3.x);
- }
-
- int[] Z3Squared = (Z1IsOne && Z2IsOne) ? HSquared : null;
-
- // TODO If the result will only be used in a subsequent addition, we don't need W3
- Curve25519FieldElement W3 = calculateJacobianModifiedW((Curve25519FieldElement)Z3, Z3Squared);
-
- ECFieldElement[] zs = new ECFieldElement[]{ Z3, W3 };
-
- return new Curve25519Point(curve, X3, Y3, zs, this.withCompression);
- }
-
- public ECPoint twice()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- ECCurve curve = this.getCurve();
-
- ECFieldElement Y1 = this.y;
- if (Y1.isZero())
- {
- return curve.getInfinity();
- }
-
- return twiceJacobianModified(true);
- }
-
- public ECPoint twicePlus(ECPoint b)
- {
- if (this == b)
- {
- return threeTimes();
- }
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return twice();
- }
-
- ECFieldElement Y1 = this.y;
- if (Y1.isZero())
- {
- return b;
- }
-
- return twiceJacobianModified(false).add(b);
- }
-
- public ECPoint threeTimes()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- ECFieldElement Y1 = this.y;
- if (Y1.isZero())
- {
- return this;
- }
-
- return twiceJacobianModified(false).add(this);
- }
-
- public ECPoint negate()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- return new Curve25519Point(this.getCurve(), this.x, this.y.negate(), this.zs, this.withCompression);
- }
-
- protected Curve25519FieldElement calculateJacobianModifiedW(Curve25519FieldElement Z, int[] ZSquared)
- {
- Curve25519FieldElement a4 = (Curve25519FieldElement)this.getCurve().getA();
- if (Z.isOne())
- {
- return a4;
- }
-
- Curve25519FieldElement W = new Curve25519FieldElement();
- if (ZSquared == null)
- {
- ZSquared = W.x;
- Curve25519Field.square(Z.x, ZSquared);
- }
- Curve25519Field.square(ZSquared, W.x);
- Curve25519Field.multiply(W.x, a4.x, W.x);
- return W;
- }
-
- protected Curve25519FieldElement getJacobianModifiedW()
- {
- Curve25519FieldElement W = (Curve25519FieldElement)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((Curve25519FieldElement)this.zs[0], null);
- }
- return W;
- }
-
- protected Curve25519Point twiceJacobianModified(boolean calculateW)
- {
- Curve25519FieldElement X1 = (Curve25519FieldElement)this.x, Y1 = (Curve25519FieldElement)this.y,
- Z1 = (Curve25519FieldElement)this.zs[0], W1 = getJacobianModifiedW();
-
- int c;
-
- int[] M = Nat256.create();
- Curve25519Field.square(X1.x, M);
- c = Nat256.addBothTo(M, M, M);
- c += Nat256.addTo(W1.x, M);
- Curve25519Field.reduce27(c, M);
-
- int[] _2Y1 = Nat256.create();
- Curve25519Field.twice(Y1.x, _2Y1);
-
- int[] _2Y1Squared = Nat256.create();
- Curve25519Field.multiply(_2Y1, Y1.x, _2Y1Squared);
-
- int[] S = Nat256.create();
- Curve25519Field.multiply(_2Y1Squared, X1.x, S);
- Curve25519Field.twice(S, S);
-
- int[] _8T = Nat256.create();
- Curve25519Field.square(_2Y1Squared, _8T);
- Curve25519Field.twice(_8T, _8T);
-
- Curve25519FieldElement X3 = new Curve25519FieldElement(_2Y1Squared);
- Curve25519Field.square(M, X3.x);
- Curve25519Field.subtract(X3.x, S, X3.x);
- Curve25519Field.subtract(X3.x, S, X3.x);
-
- Curve25519FieldElement Y3 = new Curve25519FieldElement(S);
- Curve25519Field.subtract(S, X3.x, Y3.x);
- Curve25519Field.multiply(Y3.x, M, Y3.x);
- Curve25519Field.subtract(Y3.x, _8T, Y3.x);
-
- Curve25519FieldElement Z3 = new Curve25519FieldElement(_2Y1);
- if (!Nat256.isOne(Z1.x))
- {
- Curve25519Field.multiply(Z3.x, Z1.x, Z3.x);
- }
-
- Curve25519FieldElement W3 = null;
- if (calculateW)
- {
- W3 = new Curve25519FieldElement(_8T);
- Curve25519Field.multiply(W3.x, W1.x, W3.x);
- Curve25519Field.twice(W3.x, W3.x);
- }
-
- return new Curve25519Point(this.getCurve(), X3, Y3, new ECFieldElement[]{ Z3, W3 }, this.withCompression);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Curve.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Curve.java
deleted file mode 100644
index b46cba6a..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Curve.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.util.encoders.Hex;
-
-public class SecP192K1Curve extends ECCurve.AbstractFp
-{
- public static final BigInteger q = new BigInteger(1,
- Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37"));
-
- private static final int SecP192K1_DEFAULT_COORDS = COORD_JACOBIAN;
-
- protected SecP192K1Point infinity;
-
- public SecP192K1Curve()
- {
- super(q);
-
- this.infinity = new SecP192K1Point(this, null, null);
-
- this.a = fromBigInteger(ECConstants.ZERO);
- this.b = fromBigInteger(BigInteger.valueOf(3));
- this.order = new BigInteger(1, Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D"));
- this.cofactor = BigInteger.valueOf(1);
-
- this.coord = SecP192K1_DEFAULT_COORDS;
- }
-
- protected ECCurve cloneCurve()
- {
- return new SecP192K1Curve();
- }
-
- public boolean supportsCoordinateSystem(int coord)
- {
- switch (coord)
- {
- case COORD_JACOBIAN:
- return true;
- default:
- return false;
- }
- }
-
- public BigInteger getQ()
- {
- return q;
- }
-
- public int getFieldSize()
- {
- return q.bitLength();
- }
-
- public ECFieldElement fromBigInteger(BigInteger x)
- {
- return new SecP192K1FieldElement(x);
- }
-
- protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- return new SecP192K1Point(this, x, y, withCompression);
- }
-
- protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
- {
- return new SecP192K1Point(this, x, y, zs, withCompression);
- }
-
- public ECPoint getInfinity()
- {
- return infinity;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Field.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Field.java
deleted file mode 100644
index 1a0bde81..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Field.java
+++ /dev/null
@@ -1,177 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.raw.Nat;
-import org.bouncycastle.math.raw.Nat192;
-
-public class SecP192K1Field
-{
- // 2^192 - 2^32 - 2^12 - 2^8 - 2^7 - 2^6 - 2^3 - 1
- static final int[] P = new int[]{ 0xFFFFEE37, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
- static final int[] PExt = new int[]{ 0x013C4FD1, 0x00002392, 0x00000001, 0x00000000, 0x00000000,
- 0x00000000, 0xFFFFDC6E, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
- private static final int[] PExtInv = new int[]{ 0xFEC3B02F, 0xFFFFDC6D, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF,
- 0xFFFFFFFF, 0x00002391, 0x00000002 };
- private static final int P5 = 0xFFFFFFFF;
- private static final int PExt11 = 0xFFFFFFFF;
- private static final int PInv33 = 0x11C9;
-
- public static void add(int[] x, int[] y, int[] z)
- {
- int c = Nat192.add(x, y, z);
- if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
- {
- Nat.add33To(6, PInv33, z);
- }
- }
-
- public static void addExt(int[] xx, int[] yy, int[] zz)
- {
- int c = Nat.add(12, xx, yy, zz);
- if (c != 0 || (zz[11] == PExt11 && Nat.gte(12, zz, PExt)))
- {
- if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
- {
- Nat.incAt(12, zz, PExtInv.length);
- }
- }
- }
-
- public static void addOne(int[] x, int[] z)
- {
- int c = Nat.inc(6, x, z);
- if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
- {
- Nat.add33To(6, PInv33, z);
- }
- }
-
- public static int[] fromBigInteger(BigInteger x)
- {
- int[] z = Nat192.fromBigInteger(x);
- if (z[5] == P5 && Nat192.gte(z, P))
- {
- Nat192.subFrom(P, z);
- }
- return z;
- }
-
- public static void half(int[] x, int[] z)
- {
- if ((x[0] & 1) == 0)
- {
- Nat.shiftDownBit(6, x, 0, z);
- }
- else
- {
- int c = Nat192.add(x, P, z);
- Nat.shiftDownBit(6, z, c);
- }
- }
-
- public static void multiply(int[] x, int[] y, int[] z)
- {
- int[] tt = Nat192.createExt();
- Nat192.mul(x, y, tt);
- reduce(tt, z);
- }
-
- public static void multiplyAddToExt(int[] x, int[] y, int[] zz)
- {
- int c = Nat192.mulAddTo(x, y, zz);
- if (c != 0 || (zz[11] == PExt11 && Nat.gte(12, zz, PExt)))
- {
- if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
- {
- Nat.incAt(12, zz, PExtInv.length);
- }
- }
- }
-
- public static void negate(int[] x, int[] z)
- {
- if (Nat192.isZero(x))
- {
- Nat192.zero(z);
- }
- else
- {
- Nat192.sub(P, x, z);
- }
- }
-
- public static void reduce(int[] xx, int[] z)
- {
- long cc = Nat192.mul33Add(PInv33, xx, 6, xx, 0, z, 0);
- int c = Nat192.mul33DWordAdd(PInv33, cc, z, 0);
-
- // assert c == 0L || c == 1L;
-
- if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
- {
- Nat.add33To(6, PInv33, z);
- }
- }
-
- public static void reduce32(int x, int[] z)
- {
- if ((x != 0 && Nat192.mul33WordAdd(PInv33, x, z, 0) != 0)
- || (z[5] == P5 && Nat192.gte(z, P)))
- {
- Nat.add33To(6, PInv33, z);
- }
- }
-
- public static void square(int[] x, int[] z)
- {
- int[] tt = Nat192.createExt();
- Nat192.square(x, tt);
- reduce(tt, z);
- }
-
- public static void squareN(int[] x, int n, int[] z)
- {
-// assert n > 0;
-
- int[] tt = Nat192.createExt();
- Nat192.square(x, tt);
- reduce(tt, z);
-
- while (--n > 0)
- {
- Nat192.square(z, tt);
- reduce(tt, z);
- }
- }
-
- public static void subtract(int[] x, int[] y, int[] z)
- {
- int c = Nat192.sub(x, y, z);
- if (c != 0)
- {
- Nat.sub33From(6, PInv33, z);
- }
- }
-
- public static void subtractExt(int[] xx, int[] yy, int[] zz)
- {
- int c = Nat.sub(12, xx, yy, zz);
- if (c != 0)
- {
- if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0)
- {
- Nat.decAt(12, zz, PExtInv.length);
- }
- }
- }
-
- public static void twice(int[] x, int[] z)
- {
- int c = Nat.shiftUpBit(6, x, 0, z);
- if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
- {
- Nat.add33To(6, PInv33, z);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1FieldElement.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1FieldElement.java
deleted file mode 100644
index 0032f357..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1FieldElement.java
+++ /dev/null
@@ -1,213 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.raw.Mod;
-import org.bouncycastle.math.raw.Nat192;
-import org.bouncycastle.util.Arrays;
-
-public class SecP192K1FieldElement extends ECFieldElement
-{
- public static final BigInteger Q = SecP192K1Curve.q;
-
- protected int[] x;
-
- public SecP192K1FieldElement(BigInteger x)
- {
- if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
- {
- throw new IllegalArgumentException("x value invalid for SecP192K1FieldElement");
- }
-
- this.x = SecP192K1Field.fromBigInteger(x);
- }
-
- public SecP192K1FieldElement()
- {
- this.x = Nat192.create();
- }
-
- protected SecP192K1FieldElement(int[] x)
- {
- this.x = x;
- }
-
- public boolean isZero()
- {
- return Nat192.isZero(x);
- }
-
- public boolean isOne()
- {
- return Nat192.isOne(x);
- }
-
- public boolean testBitZero()
- {
- return Nat192.getBit(x, 0) == 1;
- }
-
- public BigInteger toBigInteger()
- {
- return Nat192.toBigInteger(x);
- }
-
- public String getFieldName()
- {
- return "SecP192K1Field";
- }
-
- public int getFieldSize()
- {
- return Q.bitLength();
- }
-
- public ECFieldElement add(ECFieldElement b)
- {
- int[] z = Nat192.create();
- SecP192K1Field.add(x, ((SecP192K1FieldElement)b).x, z);
- return new SecP192K1FieldElement(z);
- }
-
- public ECFieldElement addOne()
- {
- int[] z = Nat192.create();
- SecP192K1Field.addOne(x, z);
- return new SecP192K1FieldElement(z);
- }
-
- public ECFieldElement subtract(ECFieldElement b)
- {
- int[] z = Nat192.create();
- SecP192K1Field.subtract(x, ((SecP192K1FieldElement)b).x, z);
- return new SecP192K1FieldElement(z);
- }
-
- public ECFieldElement multiply(ECFieldElement b)
- {
- int[] z = Nat192.create();
- SecP192K1Field.multiply(x, ((SecP192K1FieldElement)b).x, z);
- return new SecP192K1FieldElement(z);
- }
-
- public ECFieldElement divide(ECFieldElement b)
- {
-// return multiply(b.invert());
- int[] z = Nat192.create();
- Mod.invert(SecP192K1Field.P, ((SecP192K1FieldElement)b).x, z);
- SecP192K1Field.multiply(z, x, z);
- return new SecP192K1FieldElement(z);
- }
-
- public ECFieldElement negate()
- {
- int[] z = Nat192.create();
- SecP192K1Field.negate(x, z);
- return new SecP192K1FieldElement(z);
- }
-
- public ECFieldElement square()
- {
- int[] z = Nat192.create();
- SecP192K1Field.square(x, z);
- return new SecP192K1FieldElement(z);
- }
-
- public ECFieldElement invert()
- {
-// return new SecP192K1FieldElement(toBigInteger().modInverse(Q));
- int[] z = Nat192.create();
- Mod.invert(SecP192K1Field.P, x, z);
- return new SecP192K1FieldElement(z);
- }
-
- /**
- * return a sqrt root - the routine verifies that the calculation returns the right value - if
- * none exists it returns null.
- */
- public ECFieldElement sqrt()
- {
- /*
- * Raise this element to the exponent 2^190 - 2^30 - 2^10 - 2^6 - 2^5 - 2^4 - 2^1
- *
- * Breaking up the exponent's binary representation into "repunits", we get:
- * { 159 1s } { 1 0s } { 19 1s } { 1 0s } { 3 1s } { 3 0s} { 3 1s } { 1 0s }
- *
- * Therefore we need an addition chain containing 3, 19, 159 (the lengths of the repunits)
- * We use: 1, 2, [3], 6, 8, 16, [19], 35, 70, 140, [159]
- */
-
- int[] x1 = this.x;
- if (Nat192.isZero(x1) || Nat192.isOne(x1))
- {
- return this;
- }
-
- int[] x2 = Nat192.create();
- SecP192K1Field.square(x1, x2);
- SecP192K1Field.multiply(x2, x1, x2);
- int[] x3 = Nat192.create();
- SecP192K1Field.square(x2, x3);
- SecP192K1Field.multiply(x3, x1, x3);
- int[] x6 = Nat192.create();
- SecP192K1Field.squareN(x3, 3, x6);
- SecP192K1Field.multiply(x6, x3, x6);
- int[] x8 = x6;
- SecP192K1Field.squareN(x6, 2, x8);
- SecP192K1Field.multiply(x8, x2, x8);
- int[] x16 = x2;
- SecP192K1Field.squareN(x8, 8, x16);
- SecP192K1Field.multiply(x16, x8, x16);
- int[] x19 = x8;
- SecP192K1Field.squareN(x16, 3, x19);
- SecP192K1Field.multiply(x19, x3, x19);
- int[] x35 = Nat192.create();
- SecP192K1Field.squareN(x19, 16, x35);
- SecP192K1Field.multiply(x35, x16, x35);
- int[] x70 = x16;
- SecP192K1Field.squareN(x35, 35, x70);
- SecP192K1Field.multiply(x70, x35, x70);
- int[] x140 = x35;
- SecP192K1Field.squareN(x70, 70, x140);
- SecP192K1Field.multiply(x140, x70, x140);
- int[] x159 = x70;
- SecP192K1Field.squareN(x140, 19, x159);
- SecP192K1Field.multiply(x159, x19, x159);
-
- int[] t1 = x159;
- SecP192K1Field.squareN(t1, 20, t1);
- SecP192K1Field.multiply(t1, x19, t1);
- SecP192K1Field.squareN(t1, 4, t1);
- SecP192K1Field.multiply(t1, x3, t1);
- SecP192K1Field.squareN(t1, 6, t1);
- SecP192K1Field.multiply(t1, x3, t1);
- SecP192K1Field.square(t1, t1);
-
- int[] t2 = x3;
- SecP192K1Field.square(t1, t2);
-
- return Nat192.eq(x1, t2) ? new SecP192K1FieldElement(t1) : null;
- }
-
- public boolean equals(Object other)
- {
- if (other == this)
- {
- return true;
- }
-
- if (!(other instanceof SecP192K1FieldElement))
- {
- return false;
- }
-
- SecP192K1FieldElement o = (SecP192K1FieldElement)other;
- return Nat192.eq(x, o.x);
- }
-
- public int hashCode()
- {
- return Q.hashCode() ^ Arrays.hashCode(x, 0, 6);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Point.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Point.java
deleted file mode 100644
index eaa97277..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Point.java
+++ /dev/null
@@ -1,298 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.raw.Nat;
-import org.bouncycastle.math.raw.Nat192;
-
-public class SecP192K1Point extends ECPoint.AbstractFp
-{
- /**
- * Create a point which encodes with point compression.
- *
- * @param curve
- * the curve to use
- * @param x
- * affine x co-ordinate
- * @param y
- * affine y co-ordinate
- *
- * @deprecated Use ECCurve.createPoint to construct points
- */
- public SecP192K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- this(curve, x, y, false);
- }
-
- /**
- * Create a point that encodes with or without point compresion.
- *
- * @param curve
- * the curve to use
- * @param x
- * affine x co-ordinate
- * @param y
- * affine y co-ordinate
- * @param withCompression
- * if true encode with point compression
- *
- * @deprecated per-point compression property will be removed, refer
- * {@link #getEncoded(boolean)}
- */
- public SecP192K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- super(curve, x, y);
-
- if ((x == null) != (y == null))
- {
- throw new IllegalArgumentException("Exactly one of the field elements is null");
- }
-
- this.withCompression = withCompression;
- }
-
- SecP192K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs,
- boolean withCompression)
- {
- super(curve, x, y, zs);
-
- this.withCompression = withCompression;
- }
-
- protected ECPoint detach()
- {
- return new SecP192K1Point(null, getAffineXCoord(), getAffineYCoord());
- }
-
- // B.3 pg 62
- public ECPoint add(ECPoint b)
- {
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return this;
- }
- if (this == b)
- {
- return twice();
- }
-
- ECCurve curve = this.getCurve();
-
- SecP192K1FieldElement X1 = (SecP192K1FieldElement)this.x, Y1 = (SecP192K1FieldElement)this.y;
- SecP192K1FieldElement X2 = (SecP192K1FieldElement)b.getXCoord(), Y2 = (SecP192K1FieldElement)b.getYCoord();
-
- SecP192K1FieldElement Z1 = (SecP192K1FieldElement)this.zs[0];
- SecP192K1FieldElement Z2 = (SecP192K1FieldElement)b.getZCoord(0);
-
- int c;
- int[] tt1 = Nat192.createExt();
- int[] t2 = Nat192.create();
- int[] t3 = Nat192.create();
- int[] t4 = Nat192.create();
-
- boolean Z1IsOne = Z1.isOne();
- int[] U2, S2;
- if (Z1IsOne)
- {
- U2 = X2.x;
- S2 = Y2.x;
- }
- else
- {
- S2 = t3;
- SecP192K1Field.square(Z1.x, S2);
-
- U2 = t2;
- SecP192K1Field.multiply(S2, X2.x, U2);
-
- SecP192K1Field.multiply(S2, Z1.x, S2);
- SecP192K1Field.multiply(S2, Y2.x, S2);
- }
-
- boolean Z2IsOne = Z2.isOne();
- int[] U1, S1;
- if (Z2IsOne)
- {
- U1 = X1.x;
- S1 = Y1.x;
- }
- else
- {
- S1 = t4;
- SecP192K1Field.square(Z2.x, S1);
-
- U1 = tt1;
- SecP192K1Field.multiply(S1, X1.x, U1);
-
- SecP192K1Field.multiply(S1, Z2.x, S1);
- SecP192K1Field.multiply(S1, Y1.x, S1);
- }
-
- int[] H = Nat192.create();
- SecP192K1Field.subtract(U1, U2, H);
-
- int[] R = t2;
- SecP192K1Field.subtract(S1, S2, R);
-
- // Check if b == this or b == -this
- if (Nat192.isZero(H))
- {
- if (Nat192.isZero(R))
- {
- // this == b, i.e. this must be doubled
- return this.twice();
- }
-
- // this == -b, i.e. the result is the point at infinity
- return curve.getInfinity();
- }
-
- int[] HSquared = t3;
- SecP192K1Field.square(H, HSquared);
-
- int[] G = Nat192.create();
- SecP192K1Field.multiply(HSquared, H, G);
-
- int[] V = t3;
- SecP192K1Field.multiply(HSquared, U1, V);
-
- SecP192K1Field.negate(G, G);
- Nat192.mul(S1, G, tt1);
-
- c = Nat192.addBothTo(V, V, G);
- SecP192K1Field.reduce32(c, G);
-
- SecP192K1FieldElement X3 = new SecP192K1FieldElement(t4);
- SecP192K1Field.square(R, X3.x);
- SecP192K1Field.subtract(X3.x, G, X3.x);
-
- SecP192K1FieldElement Y3 = new SecP192K1FieldElement(G);
- SecP192K1Field.subtract(V, X3.x, Y3.x);
- SecP192K1Field.multiplyAddToExt(Y3.x, R, tt1);
- SecP192K1Field.reduce(tt1, Y3.x);
-
- SecP192K1FieldElement Z3 = new SecP192K1FieldElement(H);
- if (!Z1IsOne)
- {
- SecP192K1Field.multiply(Z3.x, Z1.x, Z3.x);
- }
- if (!Z2IsOne)
- {
- SecP192K1Field.multiply(Z3.x, Z2.x, Z3.x);
- }
-
- ECFieldElement[] zs = new ECFieldElement[] { Z3 };
-
- return new SecP192K1Point(curve, X3, Y3, zs, this.withCompression);
- }
-
- // B.3 pg 62
- public ECPoint twice()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- ECCurve curve = this.getCurve();
-
- SecP192K1FieldElement Y1 = (SecP192K1FieldElement)this.y;
- if (Y1.isZero())
- {
- return curve.getInfinity();
- }
-
- SecP192K1FieldElement X1 = (SecP192K1FieldElement)this.x, Z1 = (SecP192K1FieldElement)this.zs[0];
-
- int c;
-
- int[] Y1Squared = Nat192.create();
- SecP192K1Field.square(Y1.x, Y1Squared);
-
- int[] T = Nat192.create();
- SecP192K1Field.square(Y1Squared, T);
-
- int[] M = Nat192.create();
- SecP192K1Field.square(X1.x, M);
- c = Nat192.addBothTo(M, M, M);
- SecP192K1Field.reduce32(c, M);
-
- int[] S = Y1Squared;
- SecP192K1Field.multiply(Y1Squared, X1.x, S);
- c = Nat.shiftUpBits(6, S, 2, 0);
- SecP192K1Field.reduce32(c, S);
-
- int[] t1 = Nat192.create();
- c = Nat.shiftUpBits(6, T, 3, 0, t1);
- SecP192K1Field.reduce32(c, t1);
-
- SecP192K1FieldElement X3 = new SecP192K1FieldElement(T);
- SecP192K1Field.square(M, X3.x);
- SecP192K1Field.subtract(X3.x, S, X3.x);
- SecP192K1Field.subtract(X3.x, S, X3.x);
-
- SecP192K1FieldElement Y3 = new SecP192K1FieldElement(S);
- SecP192K1Field.subtract(S, X3.x, Y3.x);
- SecP192K1Field.multiply(Y3.x, M, Y3.x);
- SecP192K1Field.subtract(Y3.x, t1, Y3.x);
-
- SecP192K1FieldElement Z3 = new SecP192K1FieldElement(M);
- SecP192K1Field.twice(Y1.x, Z3.x);
- if (!Z1.isOne())
- {
- SecP192K1Field.multiply(Z3.x, Z1.x, Z3.x);
- }
-
- return new SecP192K1Point(curve, X3, Y3, new ECFieldElement[] { Z3 }, this.withCompression);
- }
-
- public ECPoint twicePlus(ECPoint b)
- {
- if (this == b)
- {
- return threeTimes();
- }
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return twice();
- }
-
- ECFieldElement Y1 = this.y;
- if (Y1.isZero())
- {
- return b;
- }
-
- return twice().add(b);
- }
-
- public ECPoint threeTimes()
- {
- if (this.isInfinity() || this.y.isZero())
- {
- return this;
- }
-
- // NOTE: Be careful about recursions between twicePlus and threeTimes
- return twice().add(this);
- }
-
- public ECPoint negate()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- return new SecP192K1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Curve.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Curve.java
deleted file mode 100644
index be67100a..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Curve.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.util.encoders.Hex;
-
-public class SecP192R1Curve extends ECCurve.AbstractFp
-{
- public static final BigInteger q = new BigInteger(1,
- Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF"));
-
- private static final int SecP192R1_DEFAULT_COORDS = COORD_JACOBIAN;
-
- protected SecP192R1Point infinity;
-
- public SecP192R1Curve()
- {
- super(q);
-
- this.infinity = new SecP192R1Point(this, null, null);
-
- this.a = fromBigInteger(new BigInteger(1,
- Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC")));
- this.b = fromBigInteger(new BigInteger(1,
- Hex.decode("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1")));
- this.order = new BigInteger(1, Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831"));
- this.cofactor = BigInteger.valueOf(1);
-
- this.coord = SecP192R1_DEFAULT_COORDS;
- }
-
- protected ECCurve cloneCurve()
- {
- return new SecP192R1Curve();
- }
-
- public boolean supportsCoordinateSystem(int coord)
- {
- switch (coord)
- {
- case COORD_JACOBIAN:
- return true;
- default:
- return false;
- }
- }
-
- public BigInteger getQ()
- {
- return q;
- }
-
- public int getFieldSize()
- {
- return q.bitLength();
- }
-
- public ECFieldElement fromBigInteger(BigInteger x)
- {
- return new SecP192R1FieldElement(x);
- }
-
- protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- return new SecP192R1Point(this, x, y, withCompression);
- }
-
- protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
- {
- return new SecP192R1Point(this, x, y, zs, withCompression);
- }
-
- public ECPoint getInfinity()
- {
- return infinity;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Field.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Field.java
deleted file mode 100644
index c8f5eed5..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Field.java
+++ /dev/null
@@ -1,286 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.raw.Nat;
-import org.bouncycastle.math.raw.Nat192;
-
-public class SecP192R1Field
-{
- private static final long M = 0xFFFFFFFFL;
-
- // 2^192 - 2^64 - 1
- static final int[] P = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
- static final int[] PExt = new int[]{ 0x00000001, 0x00000000, 0x00000002, 0x00000000, 0x00000001,
- 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
- private static final int[] PExtInv = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFE,
- 0xFFFFFFFF, 0x00000001, 0x00000000, 0x00000002 };
- private static final int P5 = 0xFFFFFFFF;
- private static final int PExt11 = 0xFFFFFFFF;
-
- public static void add(int[] x, int[] y, int[] z)
- {
- int c = Nat192.add(x, y, z);
- if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
- {
- addPInvTo(z);
- }
- }
-
- public static void addExt(int[] xx, int[] yy, int[] zz)
- {
- int c = Nat.add(12, xx, yy, zz);
- if (c != 0 || (zz[11] == PExt11 && Nat.gte(12, zz, PExt)))
- {
- if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
- {
- Nat.incAt(12, zz, PExtInv.length);
- }
- }
- }
-
- public static void addOne(int[] x, int[] z)
- {
- int c = Nat.inc(6, x, z);
- if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
- {
- addPInvTo(z);
- }
- }
-
- public static int[] fromBigInteger(BigInteger x)
- {
- int[] z = Nat192.fromBigInteger(x);
- if (z[5] == P5 && Nat192.gte(z, P))
- {
- Nat192.subFrom(P, z);
- }
- return z;
- }
-
- public static void half(int[] x, int[] z)
- {
- if ((x[0] & 1) == 0)
- {
- Nat.shiftDownBit(6, x, 0, z);
- }
- else
- {
- int c = Nat192.add(x, P, z);
- Nat.shiftDownBit(6, z, c);
- }
- }
-
- public static void multiply(int[] x, int[] y, int[] z)
- {
- int[] tt = Nat192.createExt();
- Nat192.mul(x, y, tt);
- reduce(tt, z);
- }
-
- public static void multiplyAddToExt(int[] x, int[] y, int[] zz)
- {
- int c = Nat192.mulAddTo(x, y, zz);
- if (c != 0 || (zz[11] == PExt11 && Nat.gte(12, zz, PExt)))
- {
- if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
- {
- Nat.incAt(12, zz, PExtInv.length);
- }
- }
- }
-
- public static void negate(int[] x, int[] z)
- {
- if (Nat192.isZero(x))
- {
- Nat192.zero(z);
- }
- else
- {
- Nat192.sub(P, x, z);
- }
- }
-
- public static void reduce(int[] xx, int[] z)
- {
- long xx06 = xx[6] & M, xx07 = xx[7] & M, xx08 = xx[8] & M;
- long xx09 = xx[9] & M, xx10 = xx[10] & M, xx11 = xx[11] & M;
-
- long t0 = xx06 + xx10;
- long t1 = xx07 + xx11;
-
- long cc = 0;
- cc += (xx[0] & M) + t0;
- int z0 = (int)cc;
- cc >>= 32;
- cc += (xx[1] & M) + t1;
- z[1] = (int)cc;
- cc >>= 32;
-
- t0 += xx08;
- t1 += xx09;
-
- cc += (xx[2] & M) + t0;
- long z2 = cc & M;
- cc >>= 32;
- cc += (xx[3] & M) + t1;
- z[3] = (int)cc;
- cc >>= 32;
-
- t0 -= xx06;
- t1 -= xx07;
-
- cc += (xx[4] & M) + t0;
- z[4] = (int)cc;
- cc >>= 32;
- cc += (xx[5] & M) + t1;
- z[5] = (int)cc;
- cc >>= 32;
-
- z2 += cc;
-
- cc += (z0 & M);
- z[0] = (int)cc;
- cc >>= 32;
- if (cc != 0)
- {
- cc += (z[1] & M);
- z[1] = (int)cc;
- z2 += cc >> 32;
- }
- z[2] = (int)z2;
- cc = z2 >> 32;
-
-// assert cc == 0 || cc == 1;
-
- if ((cc != 0 && Nat.incAt(6, z, 3) != 0)
- || (z[5] == P5 && Nat192.gte(z, P)))
- {
- addPInvTo(z);
- }
- }
-
- public static void reduce32(int x, int[] z)
- {
- long cc = 0;
-
- if (x != 0)
- {
- long xx06 = x & M;
-
- cc += (z[0] & M) + xx06;
- z[0] = (int)cc;
- cc >>= 32;
- if (cc != 0)
- {
- cc += (z[1] & M);
- z[1] = (int)cc;
- cc >>= 32;
- }
- cc += (z[2] & M) + xx06;
- z[2] = (int)cc;
- cc >>= 32;
-
-// assert cc == 0 || cc == 1;
- }
-
- if ((cc != 0 && Nat.incAt(6, z, 3) != 0)
- || (z[5] == P5 && Nat192.gte(z, P)))
- {
- addPInvTo(z);
- }
- }
-
- public static void square(int[] x, int[] z)
- {
- int[] tt = Nat192.createExt();
- Nat192.square(x, tt);
- reduce(tt, z);
- }
-
- public static void squareN(int[] x, int n, int[] z)
- {
-// assert n > 0;
-
- int[] tt = Nat192.createExt();
- Nat192.square(x, tt);
- reduce(tt, z);
-
- while (--n > 0)
- {
- Nat192.square(z, tt);
- reduce(tt, z);
- }
- }
-
- public static void subtract(int[] x, int[] y, int[] z)
- {
- int c = Nat192.sub(x, y, z);
- if (c != 0)
- {
- subPInvFrom(z);
- }
- }
-
- public static void subtractExt(int[] xx, int[] yy, int[] zz)
- {
- int c = Nat.sub(12, xx, yy, zz);
- if (c != 0)
- {
- if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0)
- {
- Nat.decAt(12, zz, PExtInv.length);
- }
- }
- }
-
- public static void twice(int[] x, int[] z)
- {
- int c = Nat.shiftUpBit(6, x, 0, z);
- if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
- {
- addPInvTo(z);
- }
- }
-
- private static void addPInvTo(int[] z)
- {
- long c = (z[0] & M) + 1;
- z[0] = (int)c;
- c >>= 32;
- if (c != 0)
- {
- c += (z[1] & M);
- z[1] = (int)c;
- c >>= 32;
- }
- c += (z[2] & M) + 1;
- z[2] = (int)c;
- c >>= 32;
- if (c != 0)
- {
- Nat.incAt(6, z, 3);
- }
- }
-
- private static void subPInvFrom(int[] z)
- {
- long c = (z[0] & M) - 1;
- z[0] = (int)c;
- c >>= 32;
- if (c != 0)
- {
- c += (z[1] & M);
- z[1] = (int)c;
- c >>= 32;
- }
- c += (z[2] & M) - 1;
- z[2] = (int)c;
- c >>= 32;
- if (c != 0)
- {
- Nat.decAt(6, z, 3);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1FieldElement.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1FieldElement.java
deleted file mode 100644
index 68c8080d..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1FieldElement.java
+++ /dev/null
@@ -1,190 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.raw.Mod;
-import org.bouncycastle.math.raw.Nat192;
-import org.bouncycastle.util.Arrays;
-
-public class SecP192R1FieldElement extends ECFieldElement
-{
- public static final BigInteger Q = SecP192R1Curve.q;
-
- protected int[] x;
-
- public SecP192R1FieldElement(BigInteger x)
- {
- if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
- {
- throw new IllegalArgumentException("x value invalid for SecP192R1FieldElement");
- }
-
- this.x = SecP192R1Field.fromBigInteger(x);
- }
-
- public SecP192R1FieldElement()
- {
- this.x = Nat192.create();
- }
-
- protected SecP192R1FieldElement(int[] x)
- {
- this.x = x;
- }
-
- public boolean isZero()
- {
- return Nat192.isZero(x);
- }
-
- public boolean isOne()
- {
- return Nat192.isOne(x);
- }
-
- public boolean testBitZero()
- {
- return Nat192.getBit(x, 0) == 1;
- }
-
- public BigInteger toBigInteger()
- {
- return Nat192.toBigInteger(x);
- }
-
- public String getFieldName()
- {
- return "SecP192R1Field";
- }
-
- public int getFieldSize()
- {
- return Q.bitLength();
- }
-
- public ECFieldElement add(ECFieldElement b)
- {
- int[] z = Nat192.create();
- SecP192R1Field.add(x, ((SecP192R1FieldElement)b).x, z);
- return new SecP192R1FieldElement(z);
- }
-
- public ECFieldElement addOne()
- {
- int[] z = Nat192.create();
- SecP192R1Field.addOne(x, z);
- return new SecP192R1FieldElement(z);
- }
-
- public ECFieldElement subtract(ECFieldElement b)
- {
- int[] z = Nat192.create();
- SecP192R1Field.subtract(x, ((SecP192R1FieldElement)b).x, z);
- return new SecP192R1FieldElement(z);
- }
-
- public ECFieldElement multiply(ECFieldElement b)
- {
- int[] z = Nat192.create();
- SecP192R1Field.multiply(x, ((SecP192R1FieldElement)b).x, z);
- return new SecP192R1FieldElement(z);
- }
-
- public ECFieldElement divide(ECFieldElement b)
- {
-// return multiply(b.invert());
- int[] z = Nat192.create();
- Mod.invert(SecP192R1Field.P, ((SecP192R1FieldElement)b).x, z);
- SecP192R1Field.multiply(z, x, z);
- return new SecP192R1FieldElement(z);
- }
-
- public ECFieldElement negate()
- {
- int[] z = Nat192.create();
- SecP192R1Field.negate(x, z);
- return new SecP192R1FieldElement(z);
- }
-
- public ECFieldElement square()
- {
- int[] z = Nat192.create();
- SecP192R1Field.square(x, z);
- return new SecP192R1FieldElement(z);
- }
-
- public ECFieldElement invert()
- {
-// return new SecP192R1FieldElement(toBigInteger().modInverse(Q));
- int[] z = Nat192.create();
- Mod.invert(SecP192R1Field.P, x, z);
- return new SecP192R1FieldElement(z);
- }
-
- // D.1.4 91
- /**
- * return a sqrt root - the routine verifies that the calculation returns the right value - if
- * none exists it returns null.
- */
- public ECFieldElement sqrt()
- {
- // Raise this element to the exponent 2^190 - 2^62
-
- int[] x1 = this.x;
- if (Nat192.isZero(x1) || Nat192.isOne(x1))
- {
- return this;
- }
-
- int[] t1 = Nat192.create();
- int[] t2 = Nat192.create();
-
- SecP192R1Field.square(x1, t1);
- SecP192R1Field.multiply(t1, x1, t1);
-
- SecP192R1Field.squareN(t1, 2, t2);
- SecP192R1Field.multiply(t2, t1, t2);
-
- SecP192R1Field.squareN(t2, 4, t1);
- SecP192R1Field.multiply(t1, t2, t1);
-
- SecP192R1Field.squareN(t1, 8, t2);
- SecP192R1Field.multiply(t2, t1, t2);
-
- SecP192R1Field.squareN(t2, 16, t1);
- SecP192R1Field.multiply(t1, t2, t1);
-
- SecP192R1Field.squareN(t1, 32, t2);
- SecP192R1Field.multiply(t2, t1, t2);
-
- SecP192R1Field.squareN(t2, 64, t1);
- SecP192R1Field.multiply(t1, t2, t1);
-
- SecP192R1Field.squareN(t1, 62, t1);
- SecP192R1Field.square(t1, t2);
-
- return Nat192.eq(x1, t2) ? new SecP192R1FieldElement(t1) : null;
- }
-
- public boolean equals(Object other)
- {
- if (other == this)
- {
- return true;
- }
-
- if (!(other instanceof SecP192R1FieldElement))
- {
- return false;
- }
-
- SecP192R1FieldElement o = (SecP192R1FieldElement)other;
- return Nat192.eq(x, o.x);
- }
-
- public int hashCode()
- {
- return Q.hashCode() ^ Arrays.hashCode(x, 0, 6);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Point.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Point.java
deleted file mode 100644
index 3ed72f85..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Point.java
+++ /dev/null
@@ -1,310 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.raw.Nat;
-import org.bouncycastle.math.raw.Nat192;
-
-public class SecP192R1Point extends ECPoint.AbstractFp
-{
- /**
- * Create a point which encodes with point compression.
- *
- * @param curve
- * the curve to use
- * @param x
- * affine x co-ordinate
- * @param y
- * affine y co-ordinate
- *
- * @deprecated Use ECCurve.createPoint to construct points
- */
- public SecP192R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- this(curve, x, y, false);
- }
-
- /**
- * Create a point that encodes with or without point compresion.
- *
- * @param curve
- * the curve to use
- * @param x
- * affine x co-ordinate
- * @param y
- * affine y co-ordinate
- * @param withCompression
- * if true encode with point compression
- *
- * @deprecated per-point compression property will be removed, refer
- * {@link #getEncoded(boolean)}
- */
- public SecP192R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- super(curve, x, y);
-
- if ((x == null) != (y == null))
- {
- throw new IllegalArgumentException("Exactly one of the field elements is null");
- }
-
- this.withCompression = withCompression;
- }
-
- SecP192R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
- {
- super(curve, x, y, zs);
-
- this.withCompression = withCompression;
- }
-
- protected ECPoint detach()
- {
- return new SecP192R1Point(null, getAffineXCoord(), getAffineYCoord());
- }
-
- // B.3 pg 62
- public ECPoint add(ECPoint b)
- {
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return this;
- }
- if (this == b)
- {
- return twice();
- }
-
- ECCurve curve = this.getCurve();
-
- SecP192R1FieldElement X1 = (SecP192R1FieldElement)this.x, Y1 = (SecP192R1FieldElement)this.y;
- SecP192R1FieldElement X2 = (SecP192R1FieldElement)b.getXCoord(), Y2 = (SecP192R1FieldElement)b.getYCoord();
-
- SecP192R1FieldElement Z1 = (SecP192R1FieldElement)this.zs[0];
- SecP192R1FieldElement Z2 = (SecP192R1FieldElement)b.getZCoord(0);
-
- int c;
- int[] tt1 = Nat192.createExt();
- int[] t2 = Nat192.create();
- int[] t3 = Nat192.create();
- int[] t4 = Nat192.create();
-
- boolean Z1IsOne = Z1.isOne();
- int[] U2, S2;
- if (Z1IsOne)
- {
- U2 = X2.x;
- S2 = Y2.x;
- }
- else
- {
- S2 = t3;
- SecP192R1Field.square(Z1.x, S2);
-
- U2 = t2;
- SecP192R1Field.multiply(S2, X2.x, U2);
-
- SecP192R1Field.multiply(S2, Z1.x, S2);
- SecP192R1Field.multiply(S2, Y2.x, S2);
- }
-
- boolean Z2IsOne = Z2.isOne();
- int[] U1, S1;
- if (Z2IsOne)
- {
- U1 = X1.x;
- S1 = Y1.x;
- }
- else
- {
- S1 = t4;
- SecP192R1Field.square(Z2.x, S1);
-
- U1 = tt1;
- SecP192R1Field.multiply(S1, X1.x, U1);
-
- SecP192R1Field.multiply(S1, Z2.x, S1);
- SecP192R1Field.multiply(S1, Y1.x, S1);
- }
-
- int[] H = Nat192.create();
- SecP192R1Field.subtract(U1, U2, H);
-
- int[] R = t2;
- SecP192R1Field.subtract(S1, S2, R);
-
- // Check if b == this or b == -this
- if (Nat192.isZero(H))
- {
- if (Nat192.isZero(R))
- {
- // this == b, i.e. this must be doubled
- return this.twice();
- }
-
- // this == -b, i.e. the result is the point at infinity
- return curve.getInfinity();
- }
-
- int[] HSquared = t3;
- SecP192R1Field.square(H, HSquared);
-
- int[] G = Nat192.create();
- SecP192R1Field.multiply(HSquared, H, G);
-
- int[] V = t3;
- SecP192R1Field.multiply(HSquared, U1, V);
-
- SecP192R1Field.negate(G, G);
- Nat192.mul(S1, G, tt1);
-
- c = Nat192.addBothTo(V, V, G);
- SecP192R1Field.reduce32(c, G);
-
- SecP192R1FieldElement X3 = new SecP192R1FieldElement(t4);
- SecP192R1Field.square(R, X3.x);
- SecP192R1Field.subtract(X3.x, G, X3.x);
-
- SecP192R1FieldElement Y3 = new SecP192R1FieldElement(G);
- SecP192R1Field.subtract(V, X3.x, Y3.x);
- SecP192R1Field.multiplyAddToExt(Y3.x, R, tt1);
- SecP192R1Field.reduce(tt1, Y3.x);
-
- SecP192R1FieldElement Z3 = new SecP192R1FieldElement(H);
- if (!Z1IsOne)
- {
- SecP192R1Field.multiply(Z3.x, Z1.x, Z3.x);
- }
- if (!Z2IsOne)
- {
- SecP192R1Field.multiply(Z3.x, Z2.x, Z3.x);
- }
-
- ECFieldElement[] zs = new ECFieldElement[]{ Z3 };
-
- return new SecP192R1Point(curve, X3, Y3, zs, this.withCompression);
- }
-
- // B.3 pg 62
- public ECPoint twice()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- ECCurve curve = this.getCurve();
-
- SecP192R1FieldElement Y1 = (SecP192R1FieldElement)this.y;
- if (Y1.isZero())
- {
- return curve.getInfinity();
- }
-
- SecP192R1FieldElement X1 = (SecP192R1FieldElement)this.x, Z1 = (SecP192R1FieldElement)this.zs[0];
-
- int c;
- int[] t1 = Nat192.create();
- int[] t2 = Nat192.create();
-
- int[] Y1Squared = Nat192.create();
- SecP192R1Field.square(Y1.x, Y1Squared);
-
- int[] T = Nat192.create();
- SecP192R1Field.square(Y1Squared, T);
-
- boolean Z1IsOne = Z1.isOne();
-
- int[] Z1Squared = Z1.x;
- if (!Z1IsOne)
- {
- Z1Squared = t2;
- SecP192R1Field.square(Z1.x, Z1Squared);
- }
-
- SecP192R1Field.subtract(X1.x, Z1Squared, t1);
-
- int[] M = t2;
- SecP192R1Field.add(X1.x, Z1Squared, M);
- SecP192R1Field.multiply(M, t1, M);
- c = Nat192.addBothTo(M, M, M);
- SecP192R1Field.reduce32(c, M);
-
- int[] S = Y1Squared;
- SecP192R1Field.multiply(Y1Squared, X1.x, S);
- c = Nat.shiftUpBits(6, S, 2, 0);
- SecP192R1Field.reduce32(c, S);
-
- c = Nat.shiftUpBits(6, T, 3, 0, t1);
- SecP192R1Field.reduce32(c, t1);
-
- SecP192R1FieldElement X3 = new SecP192R1FieldElement(T);
- SecP192R1Field.square(M, X3.x);
- SecP192R1Field.subtract(X3.x, S, X3.x);
- SecP192R1Field.subtract(X3.x, S, X3.x);
-
- SecP192R1FieldElement Y3 = new SecP192R1FieldElement(S);
- SecP192R1Field.subtract(S, X3.x, Y3.x);
- SecP192R1Field.multiply(Y3.x, M, Y3.x);
- SecP192R1Field.subtract(Y3.x, t1, Y3.x);
-
- SecP192R1FieldElement Z3 = new SecP192R1FieldElement(M);
- SecP192R1Field.twice(Y1.x, Z3.x);
- if (!Z1IsOne)
- {
- SecP192R1Field.multiply(Z3.x, Z1.x, Z3.x);
- }
-
- return new SecP192R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
- }
-
- public ECPoint twicePlus(ECPoint b)
- {
- if (this == b)
- {
- return threeTimes();
- }
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return twice();
- }
-
- ECFieldElement Y1 = this.y;
- if (Y1.isZero())
- {
- return b;
- }
-
- return twice().add(b);
- }
-
- public ECPoint threeTimes()
- {
- if (this.isInfinity() || this.y.isZero())
- {
- return this;
- }
-
- // NOTE: Be careful about recursions between twicePlus and threeTimes
- return twice().add(this);
- }
-
- public ECPoint negate()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- return new SecP192R1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Curve.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Curve.java
deleted file mode 100644
index ad733da6..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Curve.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.util.encoders.Hex;
-
-public class SecP224K1Curve extends ECCurve.AbstractFp
-{
- public static final BigInteger q = new BigInteger(1,
- Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D"));
-
- private static final int SECP224K1_DEFAULT_COORDS = COORD_JACOBIAN;
-
- protected SecP224K1Point infinity;
-
- public SecP224K1Curve()
- {
- super(q);
-
- this.infinity = new SecP224K1Point(this, null, null);
-
- this.a = fromBigInteger(ECConstants.ZERO);
- this.b = fromBigInteger(BigInteger.valueOf(5));
- this.order = new BigInteger(1, Hex.decode("010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7"));
- this.cofactor = BigInteger.valueOf(1);
- this.coord = SECP224K1_DEFAULT_COORDS;
- }
-
- protected ECCurve cloneCurve()
- {
- return new SecP224K1Curve();
- }
-
- public boolean supportsCoordinateSystem(int coord)
- {
- switch (coord)
- {
- case COORD_JACOBIAN:
- return true;
- default:
- return false;
- }
- }
-
- public BigInteger getQ()
- {
- return q;
- }
-
- public int getFieldSize()
- {
- return q.bitLength();
- }
-
- public ECFieldElement fromBigInteger(BigInteger x)
- {
- return new SecP224K1FieldElement(x);
- }
-
- protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- return new SecP224K1Point(this, x, y, withCompression);
- }
-
- protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
- {
- return new SecP224K1Point(this, x, y, zs, withCompression);
- }
-
- public ECPoint getInfinity()
- {
- return infinity;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Field.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Field.java
deleted file mode 100644
index 0146fec1..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Field.java
+++ /dev/null
@@ -1,178 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.raw.Nat;
-import org.bouncycastle.math.raw.Nat224;
-
-public class SecP224K1Field
-{
- // 2^224 - 2^32 - 2^12 - 2^11 - 2^9 - 2^7 - 2^4 - 2 - 1
- static final int[] P = new int[]{ 0xFFFFE56D, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
- 0xFFFFFFFF };
- static final int[] PExt = new int[]{ 0x02C23069, 0x00003526, 0x00000001, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0xFFFFCADA, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
- private static final int[] PExtInv = new int[]{ 0xFD3DCF97, 0xFFFFCAD9, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF,
- 0xFFFFFFFF, 0xFFFFFFFF, 0x00003525, 0x00000002 };
- private static final int P6 = 0xFFFFFFFF;
- private static final int PExt13 = 0xFFFFFFFF;
- private static final int PInv33 = 0x1A93;
-
- public static void add(int[] x, int[] y, int[] z)
- {
- int c = Nat224.add(x, y, z);
- if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
- {
- Nat.add33To(7, PInv33, z);
- }
- }
-
- public static void addExt(int[] xx, int[] yy, int[] zz)
- {
- int c = Nat.add(14, xx, yy, zz);
- if (c != 0 || (zz[13] == PExt13 && Nat.gte(14, zz, PExt)))
- {
- if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
- {
- Nat.incAt(14, zz, PExtInv.length);
- }
- }
- }
-
- public static void addOne(int[] x, int[] z)
- {
- int c = Nat.inc(7, x, z);
- if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
- {
- Nat.add33To(7, PInv33, z);
- }
- }
-
- public static int[] fromBigInteger(BigInteger x)
- {
- int[] z = Nat224.fromBigInteger(x);
- if (z[6] == P6 && Nat224.gte(z, P))
- {
- Nat.add33To(7, PInv33, z);
- }
- return z;
- }
-
- public static void half(int[] x, int[] z)
- {
- if ((x[0] & 1) == 0)
- {
- Nat.shiftDownBit(7, x, 0, z);
- }
- else
- {
- int c = Nat224.add(x, P, z);
- Nat.shiftDownBit(7, z, c);
- }
- }
-
- public static void multiply(int[] x, int[] y, int[] z)
- {
- int[] tt = Nat224.createExt();
- Nat224.mul(x, y, tt);
- reduce(tt, z);
- }
-
- public static void multiplyAddToExt(int[] x, int[] y, int[] zz)
- {
- int c = Nat224.mulAddTo(x, y, zz);
- if (c != 0 || (zz[13] == PExt13 && Nat.gte(14, zz, PExt)))
- {
- if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
- {
- Nat.incAt(14, zz, PExtInv.length);
- }
- }
- }
-
- public static void negate(int[] x, int[] z)
- {
- if (Nat224.isZero(x))
- {
- Nat224.zero(z);
- }
- else
- {
- Nat224.sub(P, x, z);
- }
- }
-
- public static void reduce(int[] xx, int[] z)
- {
- long cc = Nat224.mul33Add(PInv33, xx, 7, xx, 0, z, 0);
- int c = Nat224.mul33DWordAdd(PInv33, cc, z, 0);
-
- // assert c == 0L || c == 1L;
-
- if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
- {
- Nat.add33To(7, PInv33, z);
- }
- }
-
- public static void reduce32(int x, int[] z)
- {
- if ((x != 0 && Nat224.mul33WordAdd(PInv33, x, z, 0) != 0)
- || (z[6] == P6 && Nat224.gte(z, P)))
- {
- Nat.add33To(7, PInv33, z);
- }
- }
-
- public static void square(int[] x, int[] z)
- {
- int[] tt = Nat224.createExt();
- Nat224.square(x, tt);
- reduce(tt, z);
- }
-
- public static void squareN(int[] x, int n, int[] z)
- {
-// assert n > 0;
-
- int[] tt = Nat224.createExt();
- Nat224.square(x, tt);
- reduce(tt, z);
-
- while (--n > 0)
- {
- Nat224.square(z, tt);
- reduce(tt, z);
- }
- }
-
- public static void subtract(int[] x, int[] y, int[] z)
- {
- int c = Nat224.sub(x, y, z);
- if (c != 0)
- {
- Nat.sub33From(7, PInv33, z);
- }
- }
-
- public static void subtractExt(int[] xx, int[] yy, int[] zz)
- {
- int c = Nat.sub(14, xx, yy, zz);
- if (c != 0)
- {
- if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0)
- {
- Nat.decAt(14, zz, PExtInv.length);
- }
- }
- }
-
- public static void twice(int[] x, int[] z)
- {
- int c = Nat.shiftUpBit(7, x, 0, z);
- if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
- {
- Nat.add33To(7, PInv33, z);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1FieldElement.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1FieldElement.java
deleted file mode 100644
index 73f19993..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1FieldElement.java
+++ /dev/null
@@ -1,243 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.raw.Mod;
-import org.bouncycastle.math.raw.Nat224;
-import org.bouncycastle.util.Arrays;
-
-public class SecP224K1FieldElement extends ECFieldElement
-{
- public static final BigInteger Q = SecP224K1Curve.q;
-
- // Calculated as ECConstants.TWO.modPow(Q.shiftRight(2), Q)
- private static final int[] PRECOMP_POW2 = new int[]{ 0x33bfd202, 0xdcfad133, 0x2287624a, 0xc3811ba8,
- 0xa85558fc, 0x1eaef5d7, 0x8edf154c };
-
- protected int[] x;
-
- public SecP224K1FieldElement(BigInteger x)
- {
- if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
- {
- throw new IllegalArgumentException("x value invalid for SecP224K1FieldElement");
- }
-
- this.x = SecP224K1Field.fromBigInteger(x);
- }
-
- public SecP224K1FieldElement()
- {
- this.x = Nat224.create();
- }
-
- protected SecP224K1FieldElement(int[] x)
- {
- this.x = x;
- }
-
- public boolean isZero()
- {
- return Nat224.isZero(x);
- }
-
- public boolean isOne()
- {
- return Nat224.isOne(x);
- }
-
- public boolean testBitZero()
- {
- return Nat224.getBit(x, 0) == 1;
- }
-
- public BigInteger toBigInteger()
- {
- return Nat224.toBigInteger(x);
- }
-
- public String getFieldName()
- {
- return "SecP224K1Field";
- }
-
- public int getFieldSize()
- {
- return Q.bitLength();
- }
-
- public ECFieldElement add(ECFieldElement b)
- {
- int[] z = Nat224.create();
- SecP224K1Field.add(x, ((SecP224K1FieldElement)b).x, z);
- return new SecP224K1FieldElement(z);
- }
-
- public ECFieldElement addOne()
- {
- int[] z = Nat224.create();
- SecP224K1Field.addOne(x, z);
- return new SecP224K1FieldElement(z);
- }
-
- public ECFieldElement subtract(ECFieldElement b)
- {
- int[] z = Nat224.create();
- SecP224K1Field.subtract(x, ((SecP224K1FieldElement)b).x, z);
- return new SecP224K1FieldElement(z);
- }
-
- public ECFieldElement multiply(ECFieldElement b)
- {
- int[] z = Nat224.create();
- SecP224K1Field.multiply(x, ((SecP224K1FieldElement)b).x, z);
- return new SecP224K1FieldElement(z);
- }
-
- public ECFieldElement divide(ECFieldElement b)
- {
-// return multiply(b.invert());
- int[] z = Nat224.create();
- Mod.invert(SecP224K1Field.P, ((SecP224K1FieldElement)b).x, z);
- SecP224K1Field.multiply(z, x, z);
- return new SecP224K1FieldElement(z);
- }
-
- public ECFieldElement negate()
- {
- int[] z = Nat224.create();
- SecP224K1Field.negate(x, z);
- return new SecP224K1FieldElement(z);
- }
-
- public ECFieldElement square()
- {
- int[] z = Nat224.create();
- SecP224K1Field.square(x, z);
- return new SecP224K1FieldElement(z);
- }
-
- public ECFieldElement invert()
- {
-// return new SecP224K1FieldElement(toBigInteger().modInverse(Q));
- int[] z = Nat224.create();
- Mod.invert(SecP224K1Field.P, x, z);
- return new SecP224K1FieldElement(z);
- }
-
- // D.1.4 91
- /**
- * return a sqrt root - the routine verifies that the calculation returns the right value - if
- * none exists it returns null.
- */
- public ECFieldElement sqrt()
- {
- /*
- * Q == 8m + 5, so we use Pocklington's method for this case.
- *
- * First, raise this element to the exponent 2^221 - 2^29 - 2^9 - 2^8 - 2^6 - 2^4 - 2^1 (i.e. m + 1)
- *
- * Breaking up the exponent's binary representation into "repunits", we get:
- * { 191 1s } { 1 0s } { 19 1s } { 2 0s } { 1 1s } { 1 0s} { 1 1s } { 1 0s} { 3 1s } { 1 0s}
- *
- * Therefore we need an addition chain containing 1, 3, 19, 191 (the lengths of the repunits)
- * We use: [1], 2, [3], 4, 8, 11, [19], 23, 42, 84, 107, [191]
- */
-
- int[] x1 = this.x;
- if (Nat224.isZero(x1) || Nat224.isOne(x1))
- {
- return this;
- }
-
- int[] x2 = Nat224.create();
- SecP224K1Field.square(x1, x2);
- SecP224K1Field.multiply(x2, x1, x2);
- int[] x3 = x2;
- SecP224K1Field.square(x2, x3);
- SecP224K1Field.multiply(x3, x1, x3);
- int[] x4 = Nat224.create();
- SecP224K1Field.square(x3, x4);
- SecP224K1Field.multiply(x4, x1, x4);
- int[] x8 = Nat224.create();
- SecP224K1Field.squareN(x4, 4, x8);
- SecP224K1Field.multiply(x8, x4, x8);
- int[] x11 = Nat224.create();
- SecP224K1Field.squareN(x8, 3, x11);
- SecP224K1Field.multiply(x11, x3, x11);
- int[] x19 = x11;
- SecP224K1Field.squareN(x11, 8, x19);
- SecP224K1Field.multiply(x19, x8, x19);
- int[] x23 = x8;
- SecP224K1Field.squareN(x19, 4, x23);
- SecP224K1Field.multiply(x23, x4, x23);
- int[] x42 = x4;
- SecP224K1Field.squareN(x23, 19, x42);
- SecP224K1Field.multiply(x42, x19, x42);
- int[] x84 = Nat224.create();
- SecP224K1Field.squareN(x42, 42, x84);
- SecP224K1Field.multiply(x84, x42, x84);
- int[] x107 = x42;
- SecP224K1Field.squareN(x84, 23, x107);
- SecP224K1Field.multiply(x107, x23, x107);
- int[] x191 = x23;
- SecP224K1Field.squareN(x107, 84, x191);
- SecP224K1Field.multiply(x191, x84, x191);
-
- int[] t1 = x191;
- SecP224K1Field.squareN(t1, 20, t1);
- SecP224K1Field.multiply(t1, x19, t1);
- SecP224K1Field.squareN(t1, 3, t1);
- SecP224K1Field.multiply(t1, x1, t1);
- SecP224K1Field.squareN(t1, 2, t1);
- SecP224K1Field.multiply(t1, x1, t1);
- SecP224K1Field.squareN(t1, 4, t1);
- SecP224K1Field.multiply(t1, x3, t1);
- SecP224K1Field.square(t1, t1);
-
- int[] t2 = x84;
- SecP224K1Field.square(t1, t2);
-
- if (Nat224.eq(x1, t2))
- {
- return new SecP224K1FieldElement(t1);
- }
-
- /*
- * If the first guess is incorrect, we multiply by a precomputed power of 2 to get the second guess,
- * which is ((4x)^(m + 1))/2 mod Q
- */
- SecP224K1Field.multiply(t1, PRECOMP_POW2, t1);
-
- SecP224K1Field.square(t1, t2);
-
- if (Nat224.eq(x1, t2))
- {
- return new SecP224K1FieldElement(t1);
- }
-
- return null;
- }
-
- public boolean equals(Object other)
- {
- if (other == this)
- {
- return true;
- }
-
- if (!(other instanceof SecP224K1FieldElement))
- {
- return false;
- }
-
- SecP224K1FieldElement o = (SecP224K1FieldElement)other;
- return Nat224.eq(x, o.x);
- }
-
- public int hashCode()
- {
- return Q.hashCode() ^ Arrays.hashCode(x, 0, 7);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Point.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Point.java
deleted file mode 100644
index 114623dc..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Point.java
+++ /dev/null
@@ -1,298 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.raw.Nat;
-import org.bouncycastle.math.raw.Nat224;
-
-public class SecP224K1Point extends ECPoint.AbstractFp
-{
- /**
- * Create a point which encodes with point compression.
- *
- * @param curve
- * the curve to use
- * @param x
- * affine x co-ordinate
- * @param y
- * affine y co-ordinate
- *
- * @deprecated Use ECCurve.createPoint to construct points
- */
- public SecP224K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- this(curve, x, y, false);
- }
-
- /**
- * Create a point that encodes with or without point compresion.
- *
- * @param curve
- * the curve to use
- * @param x
- * affine x co-ordinate
- * @param y
- * affine y co-ordinate
- * @param withCompression
- * if true encode with point compression
- *
- * @deprecated per-point compression property will be removed, refer
- * {@link #getEncoded(boolean)}
- */
- public SecP224K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- super(curve, x, y);
-
- if ((x == null) != (y == null))
- {
- throw new IllegalArgumentException("Exactly one of the field elements is null");
- }
-
- this.withCompression = withCompression;
- }
-
- SecP224K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs,
- boolean withCompression)
- {
- super(curve, x, y, zs);
-
- this.withCompression = withCompression;
- }
-
- protected ECPoint detach()
- {
- return new SecP224K1Point(null, getAffineXCoord(), getAffineYCoord());
- }
-
- // B.3 pg 62
- public ECPoint add(ECPoint b)
- {
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return this;
- }
- if (this == b)
- {
- return twice();
- }
-
- ECCurve curve = this.getCurve();
-
- SecP224K1FieldElement X1 = (SecP224K1FieldElement)this.x, Y1 = (SecP224K1FieldElement)this.y;
- SecP224K1FieldElement X2 = (SecP224K1FieldElement)b.getXCoord(), Y2 = (SecP224K1FieldElement)b.getYCoord();
-
- SecP224K1FieldElement Z1 = (SecP224K1FieldElement)this.zs[0];
- SecP224K1FieldElement Z2 = (SecP224K1FieldElement)b.getZCoord(0);
-
- int c;
- int[] tt1 = Nat224.createExt();
- int[] t2 = Nat224.create();
- int[] t3 = Nat224.create();
- int[] t4 = Nat224.create();
-
- boolean Z1IsOne = Z1.isOne();
- int[] U2, S2;
- if (Z1IsOne)
- {
- U2 = X2.x;
- S2 = Y2.x;
- }
- else
- {
- S2 = t3;
- SecP224K1Field.square(Z1.x, S2);
-
- U2 = t2;
- SecP224K1Field.multiply(S2, X2.x, U2);
-
- SecP224K1Field.multiply(S2, Z1.x, S2);
- SecP224K1Field.multiply(S2, Y2.x, S2);
- }
-
- boolean Z2IsOne = Z2.isOne();
- int[] U1, S1;
- if (Z2IsOne)
- {
- U1 = X1.x;
- S1 = Y1.x;
- }
- else
- {
- S1 = t4;
- SecP224K1Field.square(Z2.x, S1);
-
- U1 = tt1;
- SecP224K1Field.multiply(S1, X1.x, U1);
-
- SecP224K1Field.multiply(S1, Z2.x, S1);
- SecP224K1Field.multiply(S1, Y1.x, S1);
- }
-
- int[] H = Nat224.create();
- SecP224K1Field.subtract(U1, U2, H);
-
- int[] R = t2;
- SecP224K1Field.subtract(S1, S2, R);
-
- // Check if b == this or b == -this
- if (Nat224.isZero(H))
- {
- if (Nat224.isZero(R))
- {
- // this == b, i.e. this must be doubled
- return this.twice();
- }
-
- // this == -b, i.e. the result is the point at infinity
- return curve.getInfinity();
- }
-
- int[] HSquared = t3;
- SecP224K1Field.square(H, HSquared);
-
- int[] G = Nat224.create();
- SecP224K1Field.multiply(HSquared, H, G);
-
- int[] V = t3;
- SecP224K1Field.multiply(HSquared, U1, V);
-
- SecP224K1Field.negate(G, G);
- Nat224.mul(S1, G, tt1);
-
- c = Nat224.addBothTo(V, V, G);
- SecP224K1Field.reduce32(c, G);
-
- SecP224K1FieldElement X3 = new SecP224K1FieldElement(t4);
- SecP224K1Field.square(R, X3.x);
- SecP224K1Field.subtract(X3.x, G, X3.x);
-
- SecP224K1FieldElement Y3 = new SecP224K1FieldElement(G);
- SecP224K1Field.subtract(V, X3.x, Y3.x);
- SecP224K1Field.multiplyAddToExt(Y3.x, R, tt1);
- SecP224K1Field.reduce(tt1, Y3.x);
-
- SecP224K1FieldElement Z3 = new SecP224K1FieldElement(H);
- if (!Z1IsOne)
- {
- SecP224K1Field.multiply(Z3.x, Z1.x, Z3.x);
- }
- if (!Z2IsOne)
- {
- SecP224K1Field.multiply(Z3.x, Z2.x, Z3.x);
- }
-
- ECFieldElement[] zs = new ECFieldElement[] { Z3 };
-
- return new SecP224K1Point(curve, X3, Y3, zs, this.withCompression);
- }
-
- // B.3 pg 62
- public ECPoint twice()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- ECCurve curve = this.getCurve();
-
- SecP224K1FieldElement Y1 = (SecP224K1FieldElement)this.y;
- if (Y1.isZero())
- {
- return curve.getInfinity();
- }
-
- SecP224K1FieldElement X1 = (SecP224K1FieldElement)this.x, Z1 = (SecP224K1FieldElement)this.zs[0];
-
- int c;
-
- int[] Y1Squared = Nat224.create();
- SecP224K1Field.square(Y1.x, Y1Squared);
-
- int[] T = Nat224.create();
- SecP224K1Field.square(Y1Squared, T);
-
- int[] M = Nat224.create();
- SecP224K1Field.square(X1.x, M);
- c = Nat224.addBothTo(M, M, M);
- SecP224K1Field.reduce32(c, M);
-
- int[] S = Y1Squared;
- SecP224K1Field.multiply(Y1Squared, X1.x, S);
- c = Nat.shiftUpBits(7, S, 2, 0);
- SecP224K1Field.reduce32(c, S);
-
- int[] t1 = Nat224.create();
- c = Nat.shiftUpBits(7, T, 3, 0, t1);
- SecP224K1Field.reduce32(c, t1);
-
- SecP224K1FieldElement X3 = new SecP224K1FieldElement(T);
- SecP224K1Field.square(M, X3.x);
- SecP224K1Field.subtract(X3.x, S, X3.x);
- SecP224K1Field.subtract(X3.x, S, X3.x);
-
- SecP224K1FieldElement Y3 = new SecP224K1FieldElement(S);
- SecP224K1Field.subtract(S, X3.x, Y3.x);
- SecP224K1Field.multiply(Y3.x, M, Y3.x);
- SecP224K1Field.subtract(Y3.x, t1, Y3.x);
-
- SecP224K1FieldElement Z3 = new SecP224K1FieldElement(M);
- SecP224K1Field.twice(Y1.x, Z3.x);
- if (!Z1.isOne())
- {
- SecP224K1Field.multiply(Z3.x, Z1.x, Z3.x);
- }
-
- return new SecP224K1Point(curve, X3, Y3, new ECFieldElement[] { Z3 }, this.withCompression);
- }
-
- public ECPoint twicePlus(ECPoint b)
- {
- if (this == b)
- {
- return threeTimes();
- }
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return twice();
- }
-
- ECFieldElement Y1 = this.y;
- if (Y1.isZero())
- {
- return b;
- }
-
- return twice().add(b);
- }
-
- public ECPoint threeTimes()
- {
- if (this.isInfinity() || this.y.isZero())
- {
- return this;
- }
-
- // NOTE: Be careful about recursions between twicePlus and threeTimes
- return twice().add(this);
- }
-
- public ECPoint negate()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- return new SecP224K1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Curve.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Curve.java
deleted file mode 100644
index c8443299..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Curve.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.util.encoders.Hex;
-
-public class SecP224R1Curve extends ECCurve.AbstractFp
-{
- public static final BigInteger q = new BigInteger(1,
- Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001"));
-
- private static final int SecP224R1_DEFAULT_COORDS = COORD_JACOBIAN;
-
- protected SecP224R1Point infinity;
-
- public SecP224R1Curve()
- {
- super(q);
-
- this.infinity = new SecP224R1Point(this, null, null);
-
- this.a = fromBigInteger(new BigInteger(1,
- Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE")));
- this.b = fromBigInteger(new BigInteger(1,
- Hex.decode("B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4")));
- this.order = new BigInteger(1, Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D"));
- this.cofactor = BigInteger.valueOf(1);
-
- this.coord = SecP224R1_DEFAULT_COORDS;
- }
-
- protected ECCurve cloneCurve()
- {
- return new SecP224R1Curve();
- }
-
- public boolean supportsCoordinateSystem(int coord)
- {
- switch (coord)
- {
- case COORD_JACOBIAN:
- return true;
- default:
- return false;
- }
- }
-
- public BigInteger getQ()
- {
- return q;
- }
-
- public int getFieldSize()
- {
- return q.bitLength();
- }
-
- public ECFieldElement fromBigInteger(BigInteger x)
- {
- return new SecP224R1FieldElement(x);
- }
-
- protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- return new SecP224R1Point(this, x, y, withCompression);
- }
-
- protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
- {
- return new SecP224R1Point(this, x, y, zs, withCompression);
- }
-
- public ECPoint getInfinity()
- {
- return infinity;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Field.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Field.java
deleted file mode 100644
index 02a86f0f..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Field.java
+++ /dev/null
@@ -1,298 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.raw.Nat;
-import org.bouncycastle.math.raw.Nat224;
-
-public class SecP224R1Field
-{
- private static final long M = 0xFFFFFFFFL;
-
- // 2^224 - 2^96 + 1
- static final int[] P = new int[]{ 0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
- static final int[] PExt = new int[]{ 0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF,
- 0xFFFFFFFF, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
- private static final int[] PExtInv = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001, 0x00000000,
- 0x00000000, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001 };
- private static final int P6 = 0xFFFFFFFF;
- private static final int PExt13 = 0xFFFFFFFF;
-
- public static void add(int[] x, int[] y, int[] z)
- {
- int c = Nat224.add(x, y, z);
- if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
- {
- addPInvTo(z);
- }
- }
-
- public static void addExt(int[] xx, int[] yy, int[] zz)
- {
- int c = Nat.add(14, xx, yy, zz);
- if (c != 0 || (zz[13] == PExt13 && Nat.gte(14, zz, PExt)))
- {
- if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
- {
- Nat.incAt(14, zz, PExtInv.length);
- }
- }
- }
-
- public static void addOne(int[] x, int[] z)
- {
- int c = Nat.inc(7, x, z);
- if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
- {
- addPInvTo(z);
- }
- }
-
- public static int[] fromBigInteger(BigInteger x)
- {
- int[] z = Nat224.fromBigInteger(x);
- if (z[6] == P6 && Nat224.gte(z, P))
- {
- Nat224.subFrom(P, z);
- }
- return z;
- }
-
- public static void half(int[] x, int[] z)
- {
- if ((x[0] & 1) == 0)
- {
- Nat.shiftDownBit(7, x, 0, z);
- }
- else
- {
- int c = Nat224.add(x, P, z);
- Nat.shiftDownBit(7, z, c);
- }
- }
-
- public static void multiply(int[] x, int[] y, int[] z)
- {
- int[] tt = Nat224.createExt();
- Nat224.mul(x, y, tt);
- reduce(tt, z);
- }
-
- public static void multiplyAddToExt(int[] x, int[] y, int[] zz)
- {
- int c = Nat224.mulAddTo(x, y, zz);
- if (c != 0 || (zz[13] == PExt13 && Nat.gte(14, zz, PExt)))
- {
- if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
- {
- Nat.incAt(14, zz, PExtInv.length);
- }
- }
- }
-
- public static void negate(int[] x, int[] z)
- {
- if (Nat224.isZero(x))
- {
- Nat224.zero(z);
- }
- else
- {
- Nat224.sub(P, x, z);
- }
- }
-
- public static void reduce(int[] xx, int[] z)
- {
- long xx10 = xx[10] & M, xx11 = xx[11] & M, xx12 = xx[12] & M, xx13 = xx[13] & M;
-
- final long n = 1;
-
- long t0 = (xx[7] & M) + xx11 - n;
- long t1 = (xx[8] & M) + xx12;
- long t2 = (xx[9] & M) + xx13;
-
- long cc = 0;
- cc += (xx[0] & M) - t0;
- long z0 = cc & M;
- cc >>= 32;
- cc += (xx[1] & M) - t1;
- z[1] = (int)cc;
- cc >>= 32;
- cc += (xx[2] & M) - t2;
- z[2] = (int)cc;
- cc >>= 32;
- cc += (xx[3] & M) + t0 - xx10;
- long z3 = cc & M;
- cc >>= 32;
- cc += (xx[4] & M) + t1 - xx11;
- z[4] = (int)cc;
- cc >>= 32;
- cc += (xx[5] & M) + t2 - xx12;
- z[5] = (int)cc;
- cc >>= 32;
- cc += (xx[6] & M) + xx10 - xx13;
- z[6] = (int)cc;
- cc >>= 32;
- cc += n;
-
-// assert cc >= 0;
-
- z3 += cc;
-
- z0 -= cc;
- z[0] = (int)z0;
- cc = z0 >> 32;
- if (cc != 0)
- {
- cc += (z[1] & M);
- z[1] = (int)cc;
- cc >>= 32;
- cc += (z[2] & M);
- z[2] = (int)cc;
- z3 += cc >> 32;
- }
- z[3] = (int)z3;
- cc = z3 >> 32;
-
-// assert cc == 0 || cc == 1;
-
- if ((cc != 0 && Nat.incAt(7, z, 4) != 0)
- || (z[6] == P6 && Nat224.gte(z, P)))
- {
- addPInvTo(z);
- }
- }
-
- public static void reduce32(int x, int[] z)
- {
- long cc = 0;
-
- if (x != 0)
- {
- long xx07 = x & M;
-
- cc += (z[0] & M) - xx07;
- z[0] = (int)cc;
- cc >>= 32;
- if (cc != 0)
- {
- cc += (z[1] & M);
- z[1] = (int)cc;
- cc >>= 32;
- cc += (z[2] & M);
- z[2] = (int)cc;
- cc >>= 32;
- }
- cc += (z[3] & M) + xx07;
- z[3] = (int)cc;
- cc >>= 32;
-
-// assert cc == 0 || cc == 1;
- }
-
- if ((cc != 0 && Nat.incAt(7, z, 4) != 0)
- || (z[6] == P6 && Nat224.gte(z, P)))
- {
- addPInvTo(z);
- }
- }
-
- public static void square(int[] x, int[] z)
- {
- int[] tt = Nat224.createExt();
- Nat224.square(x, tt);
- reduce(tt, z);
- }
-
- public static void squareN(int[] x, int n, int[] z)
- {
-// assert n > 0;
-
- int[] tt = Nat224.createExt();
- Nat224.square(x, tt);
- reduce(tt, z);
-
- while (--n > 0)
- {
- Nat224.square(z, tt);
- reduce(tt, z);
- }
- }
-
- public static void subtract(int[] x, int[] y, int[] z)
- {
- int c = Nat224.sub(x, y, z);
- if (c != 0)
- {
- subPInvFrom(z);
- }
- }
-
- public static void subtractExt(int[] xx, int[] yy, int[] zz)
- {
- int c = Nat.sub(14, xx, yy, zz);
- if (c != 0)
- {
- if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0)
- {
- Nat.decAt(14, zz, PExtInv.length);
- }
- }
- }
-
- public static void twice(int[] x, int[] z)
- {
- int c = Nat.shiftUpBit(7, x, 0, z);
- if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
- {
- addPInvTo(z);
- }
- }
-
- private static void addPInvTo(int[] z)
- {
- long c = (z[0] & M) - 1;
- z[0] = (int)c;
- c >>= 32;
- if (c != 0)
- {
- c += (z[1] & M);
- z[1] = (int)c;
- c >>= 32;
- c += (z[2] & M);
- z[2] = (int)c;
- c >>= 32;
- }
- c += (z[3] & M) + 1;
- z[3] = (int)c;
- c >>= 32;
- if (c != 0)
- {
- Nat.incAt(7, z, 4);
- }
- }
-
- private static void subPInvFrom(int[] z)
- {
- long c = (z[0] & M) + 1;
- z[0] = (int)c;
- c >>= 32;
- if (c != 0)
- {
- c += (z[1] & M);
- z[1] = (int)c;
- c >>= 32;
- c += (z[2] & M);
- z[2] = (int)c;
- c >>= 32;
- }
- c += (z[3] & M) - 1;
- z[3] = (int)c;
- c >>= 32;
- if (c != 0)
- {
- Nat.decAt(7, z, 4);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1FieldElement.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1FieldElement.java
deleted file mode 100644
index 4a28f3d0..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1FieldElement.java
+++ /dev/null
@@ -1,273 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.raw.Mod;
-import org.bouncycastle.math.raw.Nat;
-import org.bouncycastle.math.raw.Nat224;
-import org.bouncycastle.util.Arrays;
-
-public class SecP224R1FieldElement extends ECFieldElement
-{
- public static final BigInteger Q = SecP224R1Curve.q;
-
- protected int[] x;
-
- public SecP224R1FieldElement(BigInteger x)
- {
- if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
- {
- throw new IllegalArgumentException("x value invalid for SecP224R1FieldElement");
- }
-
- this.x = SecP224R1Field.fromBigInteger(x);
- }
-
- public SecP224R1FieldElement()
- {
- this.x = Nat224.create();
- }
-
- protected SecP224R1FieldElement(int[] x)
- {
- this.x = x;
- }
-
- public boolean isZero()
- {
- return Nat224.isZero(x);
- }
-
- public boolean isOne()
- {
- return Nat224.isOne(x);
- }
-
- public boolean testBitZero()
- {
- return Nat224.getBit(x, 0) == 1;
- }
-
- public BigInteger toBigInteger()
- {
- return Nat224.toBigInteger(x);
- }
-
- public String getFieldName()
- {
- return "SecP224R1Field";
- }
-
- public int getFieldSize()
- {
- return Q.bitLength();
- }
-
- public ECFieldElement add(ECFieldElement b)
- {
- int[] z = Nat224.create();
- SecP224R1Field.add(x, ((SecP224R1FieldElement)b).x, z);
- return new SecP224R1FieldElement(z);
- }
-
- public ECFieldElement addOne()
- {
- int[] z = Nat224.create();
- SecP224R1Field.addOne(x, z);
- return new SecP224R1FieldElement(z);
- }
-
- public ECFieldElement subtract(ECFieldElement b)
- {
- int[] z = Nat224.create();
- SecP224R1Field.subtract(x, ((SecP224R1FieldElement)b).x, z);
- return new SecP224R1FieldElement(z);
- }
-
- public ECFieldElement multiply(ECFieldElement b)
- {
- int[] z = Nat224.create();
- SecP224R1Field.multiply(x, ((SecP224R1FieldElement)b).x, z);
- return new SecP224R1FieldElement(z);
- }
-
- public ECFieldElement divide(ECFieldElement b)
- {
-// return multiply(b.invert());
- int[] z = Nat224.create();
- Mod.invert(SecP224R1Field.P, ((SecP224R1FieldElement)b).x, z);
- SecP224R1Field.multiply(z, x, z);
- return new SecP224R1FieldElement(z);
- }
-
- public ECFieldElement negate()
- {
- int[] z = Nat224.create();
- SecP224R1Field.negate(x, z);
- return new SecP224R1FieldElement(z);
- }
-
- public ECFieldElement square()
- {
- int[] z = Nat224.create();
- SecP224R1Field.square(x, z);
- return new SecP224R1FieldElement(z);
- }
-
- public ECFieldElement invert()
- {
-// return new SecP224R1FieldElement(toBigInteger().modInverse(Q));
- int[] z = Nat224.create();
- Mod.invert(SecP224R1Field.P, x, z);
- return new SecP224R1FieldElement(z);
- }
-
- /**
- * return a sqrt root - the routine verifies that the calculation returns the right value - if
- * none exists it returns null.
- */
- public ECFieldElement sqrt()
- {
- int[] c = this.x;
- if (Nat224.isZero(c) || Nat224.isOne(c))
- {
- return this;
- }
-
- int[] nc = Nat224.create();
- SecP224R1Field.negate(c, nc);
-
- int[] r = Mod.random(SecP224R1Field.P);
- int[] t = Nat224.create();
-
- if (!isSquare(c))
- {
- return null;
- }
-
- while (!trySqrt(nc, r, t))
- {
- SecP224R1Field.addOne(r, r);
- }
-
- SecP224R1Field.square(t, r);
-
- return Nat224.eq(c, r) ? new SecP224R1FieldElement(t) : null;
- }
-
- public boolean equals(Object other)
- {
- if (other == this)
- {
- return true;
- }
-
- if (!(other instanceof SecP224R1FieldElement))
- {
- return false;
- }
-
- SecP224R1FieldElement o = (SecP224R1FieldElement)other;
- return Nat224.eq(x, o.x);
- }
-
- public int hashCode()
- {
- return Q.hashCode() ^ Arrays.hashCode(x, 0, 7);
- }
-
- private static boolean isSquare(int[] x)
- {
- int[] t1 = Nat224.create();
- int[] t2 = Nat224.create();
- Nat224.copy(x, t1);
-
- for (int i = 0; i < 7; ++i)
- {
- Nat224.copy(t1, t2);
- SecP224R1Field.squareN(t1, 1 << i, t1);
- SecP224R1Field.multiply(t1, t2, t1);
- }
-
- SecP224R1Field.squareN(t1, 95, t1);
- return Nat224.isOne(t1);
- }
-
- private static void RM(int[] nc, int[] d0, int[] e0, int[] d1, int[] e1, int[] f1, int[] t)
- {
- SecP224R1Field.multiply(e1, e0, t);
- SecP224R1Field.multiply(t, nc, t);
- SecP224R1Field.multiply(d1, d0, f1);
- SecP224R1Field.add(f1, t, f1);
- SecP224R1Field.multiply(d1, e0, t);
- Nat224.copy(f1, d1);
- SecP224R1Field.multiply(e1, d0, e1);
- SecP224R1Field.add(e1, t, e1);
- SecP224R1Field.square(e1, f1);
- SecP224R1Field.multiply(f1, nc, f1);
- }
-
- private static void RP(int[] nc, int[] d1, int[] e1, int[] f1, int[] t)
- {
- Nat224.copy(nc, f1);
-
- int[] d0 = Nat224.create();
- int[] e0 = Nat224.create();
-
- for (int i = 0; i < 7; ++i)
- {
- Nat224.copy(d1, d0);
- Nat224.copy(e1, e0);
-
- int j = 1 << i;
- while (--j >= 0)
- {
- RS(d1, e1, f1, t);
- }
-
- RM(nc, d0, e0, d1, e1, f1, t);
- }
- }
-
- private static void RS(int[] d, int[] e, int[] f, int[] t)
- {
- SecP224R1Field.multiply(e, d, e);
- SecP224R1Field.twice(e, e);
- SecP224R1Field.square(d, t);
- SecP224R1Field.add(f, t, d);
- SecP224R1Field.multiply(f, t, f);
- int c = Nat.shiftUpBits(7, f, 2, 0);
- SecP224R1Field.reduce32(c, f);
- }
-
- private static boolean trySqrt(int[] nc, int[] r, int[] t)
- {
- int[] d1 = Nat224.create();
- Nat224.copy(r, d1);
- int[] e1 = Nat224.create();
- e1[0] = 1;
- int[] f1 = Nat224.create();
- RP(nc, d1, e1, f1, t);
-
- int[] d0 = Nat224.create();
- int[] e0 = Nat224.create();
-
- for (int k = 1; k < 96; ++k)
- {
- Nat224.copy(d1, d0);
- Nat224.copy(e1, e0);
-
- RS(d1, e1, f1, t);
-
- if (Nat224.isZero(d1))
- {
- Mod.invert(SecP224R1Field.P, e0, t);
- SecP224R1Field.multiply(t, d0, t);
- return true;
- }
- }
-
- return false;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Point.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Point.java
deleted file mode 100644
index df10b9b4..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Point.java
+++ /dev/null
@@ -1,308 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.raw.Nat;
-import org.bouncycastle.math.raw.Nat224;
-
-public class SecP224R1Point extends ECPoint.AbstractFp
-{
- /**
- * Create a point which encodes with point compression.
- *
- * @param curve
- * the curve to use
- * @param x
- * affine x co-ordinate
- * @param y
- * affine y co-ordinate
- *
- * @deprecated Use ECCurve.createPoint to construct points
- */
- public SecP224R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- this(curve, x, y, false);
- }
-
- /**
- * Create a point that encodes with or without point compresion.
- *
- * @param curve
- * the curve to use
- * @param x
- * affine x co-ordinate
- * @param y
- * affine y co-ordinate
- * @param withCompression
- * if true encode with point compression
- *
- * @deprecated per-point compression property will be removed, refer
- * {@link #getEncoded(boolean)}
- */
- public SecP224R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- super(curve, x, y);
-
- if ((x == null) != (y == null))
- {
- throw new IllegalArgumentException("Exactly one of the field elements is null");
- }
-
- this.withCompression = withCompression;
- }
-
- SecP224R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
- {
- super(curve, x, y, zs);
-
- this.withCompression = withCompression;
- }
-
- protected ECPoint detach()
- {
- return new SecP224R1Point(null, getAffineXCoord(), getAffineYCoord());
- }
-
- public ECPoint add(ECPoint b)
- {
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return this;
- }
- if (this == b)
- {
- return twice();
- }
-
- ECCurve curve = this.getCurve();
-
- SecP224R1FieldElement X1 = (SecP224R1FieldElement)this.x, Y1 = (SecP224R1FieldElement)this.y;
- SecP224R1FieldElement X2 = (SecP224R1FieldElement)b.getXCoord(), Y2 = (SecP224R1FieldElement)b.getYCoord();
-
- SecP224R1FieldElement Z1 = (SecP224R1FieldElement)this.zs[0];
- SecP224R1FieldElement Z2 = (SecP224R1FieldElement)b.getZCoord(0);
-
- int c;
- int[] tt1 = Nat224.createExt();
- int[] t2 = Nat224.create();
- int[] t3 = Nat224.create();
- int[] t4 = Nat224.create();
-
- boolean Z1IsOne = Z1.isOne();
- int[] U2, S2;
- if (Z1IsOne)
- {
- U2 = X2.x;
- S2 = Y2.x;
- }
- else
- {
- S2 = t3;
- SecP224R1Field.square(Z1.x, S2);
-
- U2 = t2;
- SecP224R1Field.multiply(S2, X2.x, U2);
-
- SecP224R1Field.multiply(S2, Z1.x, S2);
- SecP224R1Field.multiply(S2, Y2.x, S2);
- }
-
- boolean Z2IsOne = Z2.isOne();
- int[] U1, S1;
- if (Z2IsOne)
- {
- U1 = X1.x;
- S1 = Y1.x;
- }
- else
- {
- S1 = t4;
- SecP224R1Field.square(Z2.x, S1);
-
- U1 = tt1;
- SecP224R1Field.multiply(S1, X1.x, U1);
-
- SecP224R1Field.multiply(S1, Z2.x, S1);
- SecP224R1Field.multiply(S1, Y1.x, S1);
- }
-
- int[] H = Nat224.create();
- SecP224R1Field.subtract(U1, U2, H);
-
- int[] R = t2;
- SecP224R1Field.subtract(S1, S2, R);
-
- // Check if b == this or b == -this
- if (Nat224.isZero(H))
- {
- if (Nat224.isZero(R))
- {
- // this == b, i.e. this must be doubled
- return this.twice();
- }
-
- // this == -b, i.e. the result is the point at infinity
- return curve.getInfinity();
- }
-
- int[] HSquared = t3;
- SecP224R1Field.square(H, HSquared);
-
- int[] G = Nat224.create();
- SecP224R1Field.multiply(HSquared, H, G);
-
- int[] V = t3;
- SecP224R1Field.multiply(HSquared, U1, V);
-
- SecP224R1Field.negate(G, G);
- Nat224.mul(S1, G, tt1);
-
- c = Nat224.addBothTo(V, V, G);
- SecP224R1Field.reduce32(c, G);
-
- SecP224R1FieldElement X3 = new SecP224R1FieldElement(t4);
- SecP224R1Field.square(R, X3.x);
- SecP224R1Field.subtract(X3.x, G, X3.x);
-
- SecP224R1FieldElement Y3 = new SecP224R1FieldElement(G);
- SecP224R1Field.subtract(V, X3.x, Y3.x);
- SecP224R1Field.multiplyAddToExt(Y3.x, R, tt1);
- SecP224R1Field.reduce(tt1, Y3.x);
-
- SecP224R1FieldElement Z3 = new SecP224R1FieldElement(H);
- if (!Z1IsOne)
- {
- SecP224R1Field.multiply(Z3.x, Z1.x, Z3.x);
- }
- if (!Z2IsOne)
- {
- SecP224R1Field.multiply(Z3.x, Z2.x, Z3.x);
- }
-
- ECFieldElement[] zs = new ECFieldElement[]{ Z3 };
-
- return new SecP224R1Point(curve, X3, Y3, zs, this.withCompression);
- }
-
- public ECPoint twice()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- ECCurve curve = this.getCurve();
-
- SecP224R1FieldElement Y1 = (SecP224R1FieldElement)this.y;
- if (Y1.isZero())
- {
- return curve.getInfinity();
- }
-
- SecP224R1FieldElement X1 = (SecP224R1FieldElement)this.x, Z1 = (SecP224R1FieldElement)this.zs[0];
-
- int c;
- int[] t1 = Nat224.create();
- int[] t2 = Nat224.create();
-
- int[] Y1Squared = Nat224.create();
- SecP224R1Field.square(Y1.x, Y1Squared);
-
- int[] T = Nat224.create();
- SecP224R1Field.square(Y1Squared, T);
-
- boolean Z1IsOne = Z1.isOne();
-
- int[] Z1Squared = Z1.x;
- if (!Z1IsOne)
- {
- Z1Squared = t2;
- SecP224R1Field.square(Z1.x, Z1Squared);
- }
-
- SecP224R1Field.subtract(X1.x, Z1Squared, t1);
-
- int[] M = t2;
- SecP224R1Field.add(X1.x, Z1Squared, M);
- SecP224R1Field.multiply(M, t1, M);
- c = Nat224.addBothTo(M, M, M);
- SecP224R1Field.reduce32(c, M);
-
- int[] S = Y1Squared;
- SecP224R1Field.multiply(Y1Squared, X1.x, S);
- c = Nat.shiftUpBits(7, S, 2, 0);
- SecP224R1Field.reduce32(c, S);
-
- c = Nat.shiftUpBits(7, T, 3, 0, t1);
- SecP224R1Field.reduce32(c, t1);
-
- SecP224R1FieldElement X3 = new SecP224R1FieldElement(T);
- SecP224R1Field.square(M, X3.x);
- SecP224R1Field.subtract(X3.x, S, X3.x);
- SecP224R1Field.subtract(X3.x, S, X3.x);
-
- SecP224R1FieldElement Y3 = new SecP224R1FieldElement(S);
- SecP224R1Field.subtract(S, X3.x, Y3.x);
- SecP224R1Field.multiply(Y3.x, M, Y3.x);
- SecP224R1Field.subtract(Y3.x, t1, Y3.x);
-
- SecP224R1FieldElement Z3 = new SecP224R1FieldElement(M);
- SecP224R1Field.twice(Y1.x, Z3.x);
- if (!Z1IsOne)
- {
- SecP224R1Field.multiply(Z3.x, Z1.x, Z3.x);
- }
-
- return new SecP224R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
- }
-
- public ECPoint twicePlus(ECPoint b)
- {
- if (this == b)
- {
- return threeTimes();
- }
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return twice();
- }
-
- ECFieldElement Y1 = this.y;
- if (Y1.isZero())
- {
- return b;
- }
-
- return twice().add(b);
- }
-
- public ECPoint threeTimes()
- {
- if (this.isInfinity() || this.y.isZero())
- {
- return this;
- }
-
- // NOTE: Be careful about recursions between twicePlus and threeTimes
- return twice().add(this);
- }
-
- public ECPoint negate()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- return new SecP224R1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Curve.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Curve.java
deleted file mode 100644
index 9b885764..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Curve.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.util.encoders.Hex;
-
-public class SecP256K1Curve extends ECCurve.AbstractFp
-{
- public static final BigInteger q = new BigInteger(1,
- Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F"));
-
- private static final int SECP256K1_DEFAULT_COORDS = COORD_JACOBIAN;
-
- protected SecP256K1Point infinity;
-
- public SecP256K1Curve()
- {
- super(q);
-
- this.infinity = new SecP256K1Point(this, null, null);
-
- this.a = fromBigInteger(ECConstants.ZERO);
- this.b = fromBigInteger(BigInteger.valueOf(7));
- this.order = new BigInteger(1, Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"));
- this.cofactor = BigInteger.valueOf(1);
- this.coord = SECP256K1_DEFAULT_COORDS;
- }
-
- protected ECCurve cloneCurve()
- {
- return new SecP256K1Curve();
- }
-
- public boolean supportsCoordinateSystem(int coord)
- {
- switch (coord)
- {
- case COORD_JACOBIAN:
- return true;
- default:
- return false;
- }
- }
-
- public BigInteger getQ()
- {
- return q;
- }
-
- public int getFieldSize()
- {
- return q.bitLength();
- }
-
- public ECFieldElement fromBigInteger(BigInteger x)
- {
- return new SecP256K1FieldElement(x);
- }
-
- protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- return new SecP256K1Point(this, x, y, withCompression);
- }
-
- protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
- {
- return new SecP256K1Point(this, x, y, zs, withCompression);
- }
-
- public ECPoint getInfinity()
- {
- return infinity;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Field.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Field.java
deleted file mode 100644
index c7b4def1..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Field.java
+++ /dev/null
@@ -1,179 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.raw.Nat;
-import org.bouncycastle.math.raw.Nat256;
-
-public class SecP256K1Field
-{
- // 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
- static final int[] P = new int[]{ 0xFFFFFC2F, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
- 0xFFFFFFFF, 0xFFFFFFFF };
- static final int[] PExt = new int[]{ 0x000E90A1, 0x000007A2, 0x00000001, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0xFFFFF85E, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
- 0xFFFFFFFF, 0xFFFFFFFF };
- private static final int[] PExtInv = new int[]{ 0xFFF16F5F, 0xFFFFF85D, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF,
- 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000007A1, 0x00000002 };
- private static final int P7 = 0xFFFFFFFF;
- private static final int PExt15 = 0xFFFFFFFF;
- private static final int PInv33 = 0x3D1;
-
- public static void add(int[] x, int[] y, int[] z)
- {
- int c = Nat256.add(x, y, z);
- if (c != 0 || (z[7] == P7 && Nat256.gte(z, P)))
- {
- Nat.add33To(8, PInv33, z);
- }
- }
-
- public static void addExt(int[] xx, int[] yy, int[] zz)
- {
- int c = Nat.add(16, xx, yy, zz);
- if (c != 0 || (zz[15] == PExt15 && Nat.gte(16, zz, PExt)))
- {
- if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
- {
- Nat.incAt(16, zz, PExtInv.length);
- }
- }
- }
-
- public static void addOne(int[] x, int[] z)
- {
- int c = Nat.inc(8, x, z);
- if (c != 0 || (z[7] == P7 && Nat256.gte(z, P)))
- {
- Nat.add33To(8, PInv33, z);
- }
- }
-
- public static int[] fromBigInteger(BigInteger x)
- {
- int[] z = Nat256.fromBigInteger(x);
- if (z[7] == P7 && Nat256.gte(z, P))
- {
- Nat256.subFrom(P, z);
- }
- return z;
- }
-
- public static void half(int[] x, int[] z)
- {
- if ((x[0] & 1) == 0)
- {
- Nat.shiftDownBit(8, x, 0, z);
- }
- else
- {
- int c = Nat256.add(x, P, z);
- Nat.shiftDownBit(8, z, c);
- }
- }
-
- public static void multiply(int[] x, int[] y, int[] z)
- {
- int[] tt = Nat256.createExt();
- Nat256.mul(x, y, tt);
- reduce(tt, z);
- }
-
- public static void multiplyAddToExt(int[] x, int[] y, int[] zz)
- {
- int c = Nat256.mulAddTo(x, y, zz);
- if (c != 0 || (zz[15] == PExt15 && Nat.gte(16, zz, PExt)))
- {
- if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
- {
- Nat.incAt(16, zz, PExtInv.length);
- }
- }
- }
-
- public static void negate(int[] x, int[] z)
- {
- if (Nat256.isZero(x))
- {
- Nat256.zero(z);
- }
- else
- {
- Nat256.sub(P, x, z);
- }
- }
-
- public static void reduce(int[] xx, int[] z)
- {
- long cc = Nat256.mul33Add(PInv33, xx, 8, xx, 0, z, 0);
- int c = Nat256.mul33DWordAdd(PInv33, cc, z, 0);
-
- // assert c == 0L || c == 1L;
-
- if (c != 0 || (z[7] == P7 && Nat256.gte(z, P)))
- {
- Nat.add33To(8, PInv33, z);
- }
- }
-
- public static void reduce32(int x, int[] z)
- {
- if ((x != 0 && Nat256.mul33WordAdd(PInv33, x, z, 0) != 0)
- || (z[7] == P7 && Nat256.gte(z, P)))
- {
- Nat.add33To(8, PInv33, z);
- }
- }
-
- public static void square(int[] x, int[] z)
- {
- int[] tt = Nat256.createExt();
- Nat256.square(x, tt);
- reduce(tt, z);
- }
-
- public static void squareN(int[] x, int n, int[] z)
- {
-// assert n > 0;
-
- int[] tt = Nat256.createExt();
- Nat256.square(x, tt);
- reduce(tt, z);
-
- while (--n > 0)
- {
- Nat256.square(z, tt);
- reduce(tt, z);
- }
- }
-
- public static void subtract(int[] x, int[] y, int[] z)
- {
- int c = Nat256.sub(x, y, z);
- if (c != 0)
- {
- Nat.sub33From(8, PInv33, z);
- }
- }
-
- public static void subtractExt(int[] xx, int[] yy, int[] zz)
- {
- int c = Nat.sub(16, xx, yy, zz);
- if (c != 0)
- {
- if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0)
- {
- Nat.decAt(16, zz, PExtInv.length);
- }
- }
- }
-
- public static void twice(int[] x, int[] z)
- {
- int c = Nat.shiftUpBit(8, x, 0, z);
- if (c != 0 || (z[7] == P7 && Nat256.gte(z, P)))
- {
- Nat.add33To(8, PInv33, z);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1FieldElement.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1FieldElement.java
deleted file mode 100644
index 0f7e2951..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1FieldElement.java
+++ /dev/null
@@ -1,215 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.raw.Mod;
-import org.bouncycastle.math.raw.Nat256;
-import org.bouncycastle.util.Arrays;
-
-public class SecP256K1FieldElement extends ECFieldElement
-{
- public static final BigInteger Q = SecP256K1Curve.q;
-
- protected int[] x;
-
- public SecP256K1FieldElement(BigInteger x)
- {
- if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
- {
- throw new IllegalArgumentException("x value invalid for SecP256K1FieldElement");
- }
-
- this.x = SecP256K1Field.fromBigInteger(x);
- }
-
- public SecP256K1FieldElement()
- {
- this.x = Nat256.create();
- }
-
- protected SecP256K1FieldElement(int[] x)
- {
- this.x = x;
- }
-
- public boolean isZero()
- {
- return Nat256.isZero(x);
- }
-
- public boolean isOne()
- {
- return Nat256.isOne(x);
- }
-
- public boolean testBitZero()
- {
- return Nat256.getBit(x, 0) == 1;
- }
-
- public BigInteger toBigInteger()
- {
- return Nat256.toBigInteger(x);
- }
-
- public String getFieldName()
- {
- return "SecP256K1Field";
- }
-
- public int getFieldSize()
- {
- return Q.bitLength();
- }
-
- public ECFieldElement add(ECFieldElement b)
- {
- int[] z = Nat256.create();
- SecP256K1Field.add(x, ((SecP256K1FieldElement)b).x, z);
- return new SecP256K1FieldElement(z);
- }
-
- public ECFieldElement addOne()
- {
- int[] z = Nat256.create();
- SecP256K1Field.addOne(x, z);
- return new SecP256K1FieldElement(z);
- }
-
- public ECFieldElement subtract(ECFieldElement b)
- {
- int[] z = Nat256.create();
- SecP256K1Field.subtract(x, ((SecP256K1FieldElement)b).x, z);
- return new SecP256K1FieldElement(z);
- }
-
- public ECFieldElement multiply(ECFieldElement b)
- {
- int[] z = Nat256.create();
- SecP256K1Field.multiply(x, ((SecP256K1FieldElement)b).x, z);
- return new SecP256K1FieldElement(z);
- }
-
- public ECFieldElement divide(ECFieldElement b)
- {
-// return multiply(b.invert());
- int[] z = Nat256.create();
- Mod.invert(SecP256K1Field.P, ((SecP256K1FieldElement)b).x, z);
- SecP256K1Field.multiply(z, x, z);
- return new SecP256K1FieldElement(z);
- }
-
- public ECFieldElement negate()
- {
- int[] z = Nat256.create();
- SecP256K1Field.negate(x, z);
- return new SecP256K1FieldElement(z);
- }
-
- public ECFieldElement square()
- {
- int[] z = Nat256.create();
- SecP256K1Field.square(x, z);
- return new SecP256K1FieldElement(z);
- }
-
- public ECFieldElement invert()
- {
-// return new SecP256K1FieldElement(toBigInteger().modInverse(Q));
- int[] z = Nat256.create();
- Mod.invert(SecP256K1Field.P, x, z);
- return new SecP256K1FieldElement(z);
- }
-
- // D.1.4 91
- /**
- * return a sqrt root - the routine verifies that the calculation returns the right value - if
- * none exists it returns null.
- */
- public ECFieldElement sqrt()
- {
- /*
- * Raise this element to the exponent 2^254 - 2^30 - 2^7 - 2^6 - 2^5 - 2^4 - 2^2
- *
- * Breaking up the exponent's binary representation into "repunits", we get:
- * { 223 1s } { 1 0s } { 22 1s } { 4 0s } { 2 1s } { 2 0s}
- *
- * Therefore we need an addition chain containing 2, 22, 223 (the lengths of the repunits)
- * We use: 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223]
- */
-
- int[] x1 = this.x;
- if (Nat256.isZero(x1) || Nat256.isOne(x1))
- {
- return this;
- }
-
- int[] x2 = Nat256.create();
- SecP256K1Field.square(x1, x2);
- SecP256K1Field.multiply(x2, x1, x2);
- int[] x3 = Nat256.create();
- SecP256K1Field.square(x2, x3);
- SecP256K1Field.multiply(x3, x1, x3);
- int[] x6 = Nat256.create();
- SecP256K1Field.squareN(x3, 3, x6);
- SecP256K1Field.multiply(x6, x3, x6);
- int[] x9 = x6;
- SecP256K1Field.squareN(x6, 3, x9);
- SecP256K1Field.multiply(x9, x3, x9);
- int[] x11 = x9;
- SecP256K1Field.squareN(x9, 2, x11);
- SecP256K1Field.multiply(x11, x2, x11);
- int[] x22 = Nat256.create();
- SecP256K1Field.squareN(x11, 11, x22);
- SecP256K1Field.multiply(x22, x11, x22);
- int[] x44 = x11;
- SecP256K1Field.squareN(x22, 22, x44);
- SecP256K1Field.multiply(x44, x22, x44);
- int[] x88 = Nat256.create();
- SecP256K1Field.squareN(x44, 44, x88);
- SecP256K1Field.multiply(x88, x44, x88);
- int[] x176 = Nat256.create();
- SecP256K1Field.squareN(x88, 88, x176);
- SecP256K1Field.multiply(x176, x88, x176);
- int[] x220 = x88;
- SecP256K1Field.squareN(x176, 44, x220);
- SecP256K1Field.multiply(x220, x44, x220);
- int[] x223 = x44;
- SecP256K1Field.squareN(x220, 3, x223);
- SecP256K1Field.multiply(x223, x3, x223);
-
- int[] t1 = x223;
- SecP256K1Field.squareN(t1, 23, t1);
- SecP256K1Field.multiply(t1, x22, t1);
- SecP256K1Field.squareN(t1, 6, t1);
- SecP256K1Field.multiply(t1, x2, t1);
- SecP256K1Field.squareN(t1, 2, t1);
-
- int[] t2 = x2;
- SecP256K1Field.square(t1, t2);
-
- return Nat256.eq(x1, t2) ? new SecP256K1FieldElement(t1) : null;
- }
-
- public boolean equals(Object other)
- {
- if (other == this)
- {
- return true;
- }
-
- if (!(other instanceof SecP256K1FieldElement))
- {
- return false;
- }
-
- SecP256K1FieldElement o = (SecP256K1FieldElement)other;
- return Nat256.eq(x, o.x);
- }
-
- public int hashCode()
- {
- return Q.hashCode() ^ Arrays.hashCode(x, 0, 8);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Point.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Point.java
deleted file mode 100644
index f57b200a..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Point.java
+++ /dev/null
@@ -1,298 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.raw.Nat;
-import org.bouncycastle.math.raw.Nat256;
-
-public class SecP256K1Point extends ECPoint.AbstractFp
-{
- /**
- * Create a point which encodes with point compression.
- *
- * @param curve
- * the curve to use
- * @param x
- * affine x co-ordinate
- * @param y
- * affine y co-ordinate
- *
- * @deprecated Use ECCurve.createPoint to construct points
- */
- public SecP256K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- this(curve, x, y, false);
- }
-
- /**
- * Create a point that encodes with or without point compresion.
- *
- * @param curve
- * the curve to use
- * @param x
- * affine x co-ordinate
- * @param y
- * affine y co-ordinate
- * @param withCompression
- * if true encode with point compression
- *
- * @deprecated per-point compression property will be removed, refer
- * {@link #getEncoded(boolean)}
- */
- public SecP256K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- super(curve, x, y);
-
- if ((x == null) != (y == null))
- {
- throw new IllegalArgumentException("Exactly one of the field elements is null");
- }
-
- this.withCompression = withCompression;
- }
-
- SecP256K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs,
- boolean withCompression)
- {
- super(curve, x, y, zs);
-
- this.withCompression = withCompression;
- }
-
- protected ECPoint detach()
- {
- return new SecP256K1Point(null, getAffineXCoord(), getAffineYCoord());
- }
-
- // B.3 pg 62
- public ECPoint add(ECPoint b)
- {
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return this;
- }
- if (this == b)
- {
- return twice();
- }
-
- ECCurve curve = this.getCurve();
-
- SecP256K1FieldElement X1 = (SecP256K1FieldElement)this.x, Y1 = (SecP256K1FieldElement)this.y;
- SecP256K1FieldElement X2 = (SecP256K1FieldElement)b.getXCoord(), Y2 = (SecP256K1FieldElement)b.getYCoord();
-
- SecP256K1FieldElement Z1 = (SecP256K1FieldElement)this.zs[0];
- SecP256K1FieldElement Z2 = (SecP256K1FieldElement)b.getZCoord(0);
-
- int c;
- int[] tt1 = Nat256.createExt();
- int[] t2 = Nat256.create();
- int[] t3 = Nat256.create();
- int[] t4 = Nat256.create();
-
- boolean Z1IsOne = Z1.isOne();
- int[] U2, S2;
- if (Z1IsOne)
- {
- U2 = X2.x;
- S2 = Y2.x;
- }
- else
- {
- S2 = t3;
- SecP256K1Field.square(Z1.x, S2);
-
- U2 = t2;
- SecP256K1Field.multiply(S2, X2.x, U2);
-
- SecP256K1Field.multiply(S2, Z1.x, S2);
- SecP256K1Field.multiply(S2, Y2.x, S2);
- }
-
- boolean Z2IsOne = Z2.isOne();
- int[] U1, S1;
- if (Z2IsOne)
- {
- U1 = X1.x;
- S1 = Y1.x;
- }
- else
- {
- S1 = t4;
- SecP256K1Field.square(Z2.x, S1);
-
- U1 = tt1;
- SecP256K1Field.multiply(S1, X1.x, U1);
-
- SecP256K1Field.multiply(S1, Z2.x, S1);
- SecP256K1Field.multiply(S1, Y1.x, S1);
- }
-
- int[] H = Nat256.create();
- SecP256K1Field.subtract(U1, U2, H);
-
- int[] R = t2;
- SecP256K1Field.subtract(S1, S2, R);
-
- // Check if b == this or b == -this
- if (Nat256.isZero(H))
- {
- if (Nat256.isZero(R))
- {
- // this == b, i.e. this must be doubled
- return this.twice();
- }
-
- // this == -b, i.e. the result is the point at infinity
- return curve.getInfinity();
- }
-
- int[] HSquared = t3;
- SecP256K1Field.square(H, HSquared);
-
- int[] G = Nat256.create();
- SecP256K1Field.multiply(HSquared, H, G);
-
- int[] V = t3;
- SecP256K1Field.multiply(HSquared, U1, V);
-
- SecP256K1Field.negate(G, G);
- Nat256.mul(S1, G, tt1);
-
- c = Nat256.addBothTo(V, V, G);
- SecP256K1Field.reduce32(c, G);
-
- SecP256K1FieldElement X3 = new SecP256K1FieldElement(t4);
- SecP256K1Field.square(R, X3.x);
- SecP256K1Field.subtract(X3.x, G, X3.x);
-
- SecP256K1FieldElement Y3 = new SecP256K1FieldElement(G);
- SecP256K1Field.subtract(V, X3.x, Y3.x);
- SecP256K1Field.multiplyAddToExt(Y3.x, R, tt1);
- SecP256K1Field.reduce(tt1, Y3.x);
-
- SecP256K1FieldElement Z3 = new SecP256K1FieldElement(H);
- if (!Z1IsOne)
- {
- SecP256K1Field.multiply(Z3.x, Z1.x, Z3.x);
- }
- if (!Z2IsOne)
- {
- SecP256K1Field.multiply(Z3.x, Z2.x, Z3.x);
- }
-
- ECFieldElement[] zs = new ECFieldElement[] { Z3 };
-
- return new SecP256K1Point(curve, X3, Y3, zs, this.withCompression);
- }
-
- // B.3 pg 62
- public ECPoint twice()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- ECCurve curve = this.getCurve();
-
- SecP256K1FieldElement Y1 = (SecP256K1FieldElement)this.y;
- if (Y1.isZero())
- {
- return curve.getInfinity();
- }
-
- SecP256K1FieldElement X1 = (SecP256K1FieldElement)this.x, Z1 = (SecP256K1FieldElement)this.zs[0];
-
- int c;
-
- int[] Y1Squared = Nat256.create();
- SecP256K1Field.square(Y1.x, Y1Squared);
-
- int[] T = Nat256.create();
- SecP256K1Field.square(Y1Squared, T);
-
- int[] M = Nat256.create();
- SecP256K1Field.square(X1.x, M);
- c = Nat256.addBothTo(M, M, M);
- SecP256K1Field.reduce32(c, M);
-
- int[] S = Y1Squared;
- SecP256K1Field.multiply(Y1Squared, X1.x, S);
- c = Nat.shiftUpBits(8, S, 2, 0);
- SecP256K1Field.reduce32(c, S);
-
- int[] t1 = Nat256.create();
- c = Nat.shiftUpBits(8, T, 3, 0, t1);
- SecP256K1Field.reduce32(c, t1);
-
- SecP256K1FieldElement X3 = new SecP256K1FieldElement(T);
- SecP256K1Field.square(M, X3.x);
- SecP256K1Field.subtract(X3.x, S, X3.x);
- SecP256K1Field.subtract(X3.x, S, X3.x);
-
- SecP256K1FieldElement Y3 = new SecP256K1FieldElement(S);
- SecP256K1Field.subtract(S, X3.x, Y3.x);
- SecP256K1Field.multiply(Y3.x, M, Y3.x);
- SecP256K1Field.subtract(Y3.x, t1, Y3.x);
-
- SecP256K1FieldElement Z3 = new SecP256K1FieldElement(M);
- SecP256K1Field.twice(Y1.x, Z3.x);
- if (!Z1.isOne())
- {
- SecP256K1Field.multiply(Z3.x, Z1.x, Z3.x);
- }
-
- return new SecP256K1Point(curve, X3, Y3, new ECFieldElement[] { Z3 }, this.withCompression);
- }
-
- public ECPoint twicePlus(ECPoint b)
- {
- if (this == b)
- {
- return threeTimes();
- }
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return twice();
- }
-
- ECFieldElement Y1 = this.y;
- if (Y1.isZero())
- {
- return b;
- }
-
- return twice().add(b);
- }
-
- public ECPoint threeTimes()
- {
- if (this.isInfinity() || this.y.isZero())
- {
- return this;
- }
-
- // NOTE: Be careful about recursions between twicePlus and threeTimes
- return twice().add(this);
- }
-
- public ECPoint negate()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- return new SecP256K1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Curve.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Curve.java
deleted file mode 100644
index 5ff6a38d..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Curve.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.util.encoders.Hex;
-
-public class SecP256R1Curve extends ECCurve.AbstractFp
-{
- public static final BigInteger q = new BigInteger(1,
- Hex.decode("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"));
-
- private static final int SecP256R1_DEFAULT_COORDS = COORD_JACOBIAN;
-
- protected SecP256R1Point infinity;
-
- public SecP256R1Curve()
- {
- super(q);
-
- this.infinity = new SecP256R1Point(this, null, null);
-
- this.a = fromBigInteger(new BigInteger(1,
- Hex.decode("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC")));
- this.b = fromBigInteger(new BigInteger(1,
- Hex.decode("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B")));
- this.order = new BigInteger(1, Hex.decode("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"));
- this.cofactor = BigInteger.valueOf(1);
-
- this.coord = SecP256R1_DEFAULT_COORDS;
- }
-
- protected ECCurve cloneCurve()
- {
- return new SecP256R1Curve();
- }
-
- public boolean supportsCoordinateSystem(int coord)
- {
- switch (coord)
- {
- case COORD_JACOBIAN:
- return true;
- default:
- return false;
- }
- }
-
- public BigInteger getQ()
- {
- return q;
- }
-
- public int getFieldSize()
- {
- return q.bitLength();
- }
-
- public ECFieldElement fromBigInteger(BigInteger x)
- {
- return new SecP256R1FieldElement(x);
- }
-
- protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- return new SecP256R1Point(this, x, y, withCompression);
- }
-
- protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
- {
- return new SecP256R1Point(this, x, y, zs, withCompression);
- }
-
- public ECPoint getInfinity()
- {
- return infinity;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java
deleted file mode 100644
index 985cb0e2..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java
+++ /dev/null
@@ -1,312 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.raw.Nat;
-import org.bouncycastle.math.raw.Nat256;
-
-public class SecP256R1Field
-{
- private static final long M = 0xFFFFFFFFL;
-
- // 2^256 - 2^224 + 2^192 + 2^96 - 1
- static final int[] P = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000,
- 0x00000001, 0xFFFFFFFF };
- static final int[] PExt = new int[]{ 0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF,
- 0xFFFFFFFF, 0xFFFFFFFE, 0x00000001, 0xFFFFFFFE, 0x00000001, 0xFFFFFFFE, 0x00000001, 0x00000001, 0xFFFFFFFE,
- 0x00000002, 0xFFFFFFFE };
- private static final int P7 = 0xFFFFFFFF;
- private static final int PExt15 = 0xFFFFFFFF;
-
- public static void add(int[] x, int[] y, int[] z)
- {
- int c = Nat256.add(x, y, z);
- if (c != 0 || (z[7] == P7 && Nat256.gte(z, P)))
- {
- addPInvTo(z);
- }
- }
-
- public static void addExt(int[] xx, int[] yy, int[] zz)
- {
- int c = Nat.add(16, xx, yy, zz);
- if (c != 0 || ((zz[15] & PExt15) == PExt15 && Nat.gte(16, zz, PExt)))
- {
- Nat.subFrom(16, PExt, zz);
- }
- }
-
- public static void addOne(int[] x, int[] z)
- {
- int c = Nat.inc(8, x, z);
- if (c != 0 || (z[7] == P7 && Nat256.gte(z, P)))
- {
- addPInvTo(z);
- }
- }
-
- public static int[] fromBigInteger(BigInteger x)
- {
- int[] z = Nat256.fromBigInteger(x);
- if (z[7] == P7 && Nat256.gte(z, P))
- {
- Nat256.subFrom(P, z);
- }
- return z;
- }
-
- public static void half(int[] x, int[] z)
- {
- if ((x[0] & 1) == 0)
- {
- Nat.shiftDownBit(8, x, 0, z);
- }
- else
- {
- int c = Nat256.add(x, P, z);
- Nat.shiftDownBit(8, z, c);
- }
- }
-
- public static void multiply(int[] x, int[] y, int[] z)
- {
- int[] tt = Nat256.createExt();
- Nat256.mul(x, y, tt);
- reduce(tt, z);
- }
-
- public static void multiplyAddToExt(int[] x, int[] y, int[] zz)
- {
- int c = Nat256.mulAddTo(x, y, zz);
- if (c != 0 || ((zz[15] & PExt15) == PExt15 && Nat.gte(16, zz, PExt)))
- {
- Nat.subFrom(16, PExt, zz);
- }
- }
-
- public static void negate(int[] x, int[] z)
- {
- if (Nat256.isZero(x))
- {
- Nat256.zero(z);
- }
- else
- {
- Nat256.sub(P, x, z);
- }
- }
-
- public static void reduce(int[] xx, int[] z)
- {
- long xx08 = xx[8] & M, xx09 = xx[9] & M, xx10 = xx[10] & M, xx11 = xx[11] & M;
- long xx12 = xx[12] & M, xx13 = xx[13] & M, xx14 = xx[14] & M, xx15 = xx[15] & M;
-
- final long n = 6;
-
- xx08 -= n;
-
- long t0 = xx08 + xx09;
- long t1 = xx09 + xx10;
- long t2 = xx10 + xx11 - xx15;
- long t3 = xx11 + xx12;
- long t4 = xx12 + xx13;
- long t5 = xx13 + xx14;
- long t6 = xx14 + xx15;
-
- long cc = 0;
- cc += (xx[0] & M) + t0 - t3 - t5;
- z[0] = (int)cc;
- cc >>= 32;
- cc += (xx[1] & M) + t1 - t4 - t6;
- z[1] = (int)cc;
- cc >>= 32;
- cc += (xx[2] & M) + t2 - t5;
- z[2] = (int)cc;
- cc >>= 32;
- cc += (xx[3] & M) + (t3 << 1) + xx13 - xx15 - t0;
- z[3] = (int)cc;
- cc >>= 32;
- cc += (xx[4] & M) + (t4 << 1) + xx14 - t1;
- z[4] = (int)cc;
- cc >>= 32;
- cc += (xx[5] & M) + (t5 << 1) - t2;
- z[5] = (int)cc;
- cc >>= 32;
- cc += (xx[6] & M) + (t6 << 1) + t5 - t0;
- z[6] = (int)cc;
- cc >>= 32;
- cc += (xx[7] & M) + (xx15 << 1) + xx08 - t2 - t4;
- z[7] = (int)cc;
- cc >>= 32;
- cc += n;
-
-// assert cc >= 0;
-
- reduce32((int)cc, z);
- }
-
- public static void reduce32(int x, int[] z)
- {
- long cc = 0;
-
- if (x != 0)
- {
- long xx08 = x & M;
-
- cc += (z[0] & M) + xx08;
- z[0] = (int)cc;
- cc >>= 32;
- if (cc != 0)
- {
- cc += (z[1] & M);
- z[1] = (int)cc;
- cc >>= 32;
- cc += (z[2] & M);
- z[2] = (int)cc;
- cc >>= 32;
- }
- cc += (z[3] & M) - xx08;
- z[3] = (int)cc;
- cc >>= 32;
- if (cc != 0)
- {
- cc += (z[4] & M);
- z[4] = (int)cc;
- cc >>= 32;
- cc += (z[5] & M);
- z[5] = (int)cc;
- cc >>= 32;
- }
- cc += (z[6] & M) - xx08;
- z[6] = (int)cc;
- cc >>= 32;
- cc += (z[7] & M) + xx08;
- z[7] = (int)cc;
- cc >>= 32;
-
-// assert cc == 0 || cc == 1;
- }
-
- if (cc != 0 || (z[7] == P7 && Nat256.gte(z, P)))
- {
- addPInvTo(z);
- }
- }
-
- public static void square(int[] x, int[] z)
- {
- int[] tt = Nat256.createExt();
- Nat256.square(x, tt);
- reduce(tt, z);
- }
-
- public static void squareN(int[] x, int n, int[] z)
- {
-// assert n > 0;
-
- int[] tt = Nat256.createExt();
- Nat256.square(x, tt);
- reduce(tt, z);
-
- while (--n > 0)
- {
- Nat256.square(z, tt);
- reduce(tt, z);
- }
- }
-
- public static void subtract(int[] x, int[] y, int[] z)
- {
- int c = Nat256.sub(x, y, z);
- if (c != 0)
- {
- subPInvFrom(z);
- }
- }
-
- public static void subtractExt(int[] xx, int[] yy, int[] zz)
- {
- int c = Nat.sub(16, xx, yy, zz);
- if (c != 0)
- {
- Nat.addTo(16, PExt, zz);
- }
- }
-
- public static void twice(int[] x, int[] z)
- {
- int c = Nat.shiftUpBit(8, x, 0, z);
- if (c != 0 || (z[7] == P7 && Nat256.gte(z, P)))
- {
- addPInvTo(z);
- }
- }
-
- private static void addPInvTo(int[] z)
- {
- long c = (z[0] & M) + 1;
- z[0] = (int)c;
- c >>= 32;
- if (c != 0)
- {
- c += (z[1] & M);
- z[1] = (int)c;
- c >>= 32;
- c += (z[2] & M);
- z[2] = (int)c;
- c >>= 32;
- }
- c += (z[3] & M) - 1;
- z[3] = (int)c;
- c >>= 32;
- if (c != 0)
- {
- c += (z[4] & M);
- z[4] = (int)c;
- c >>= 32;
- c += (z[5] & M);
- z[5] = (int)c;
- c >>= 32;
- }
- c += (z[6] & M) - 1;
- z[6] = (int)c;
- c >>= 32;
- c += (z[7] & M) + 1;
- z[7] = (int)c;
-// c >>= 32;
- }
-
- private static void subPInvFrom(int[] z)
- {
- long c = (z[0] & M) - 1;
- z[0] = (int)c;
- c >>= 32;
- if (c != 0)
- {
- c += (z[1] & M);
- z[1] = (int)c;
- c >>= 32;
- c += (z[2] & M);
- z[2] = (int)c;
- c >>= 32;
- }
- c += (z[3] & M) + 1;
- z[3] = (int)c;
- c >>= 32;
- if (c != 0)
- {
- c += (z[4] & M);
- z[4] = (int)c;
- c >>= 32;
- c += (z[5] & M);
- z[5] = (int)c;
- c >>= 32;
- }
- c += (z[6] & M) + 1;
- z[6] = (int)c;
- c >>= 32;
- c += (z[7] & M) - 1;
- z[7] = (int)c;
-// c >>= 32;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1FieldElement.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1FieldElement.java
deleted file mode 100644
index be250d10..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1FieldElement.java
+++ /dev/null
@@ -1,189 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.raw.Mod;
-import org.bouncycastle.math.raw.Nat256;
-import org.bouncycastle.util.Arrays;
-
-public class SecP256R1FieldElement extends ECFieldElement
-{
- public static final BigInteger Q = SecP256R1Curve.q;
-
- protected int[] x;
-
- public SecP256R1FieldElement(BigInteger x)
- {
- if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
- {
- throw new IllegalArgumentException("x value invalid for SecP256R1FieldElement");
- }
-
- this.x = SecP256R1Field.fromBigInteger(x);
- }
-
- public SecP256R1FieldElement()
- {
- this.x = Nat256.create();
- }
-
- protected SecP256R1FieldElement(int[] x)
- {
- this.x = x;
- }
-
- public boolean isZero()
- {
- return Nat256.isZero(x);
- }
-
- public boolean isOne()
- {
- return Nat256.isOne(x);
- }
-
- public boolean testBitZero()
- {
- return Nat256.getBit(x, 0) == 1;
- }
-
- public BigInteger toBigInteger()
- {
- return Nat256.toBigInteger(x);
- }
-
- public String getFieldName()
- {
- return "SecP256R1Field";
- }
-
- public int getFieldSize()
- {
- return Q.bitLength();
- }
-
- public ECFieldElement add(ECFieldElement b)
- {
- int[] z = Nat256.create();
- SecP256R1Field.add(x, ((SecP256R1FieldElement)b).x, z);
- return new SecP256R1FieldElement(z);
- }
-
- public ECFieldElement addOne()
- {
- int[] z = Nat256.create();
- SecP256R1Field.addOne(x, z);
- return new SecP256R1FieldElement(z);
- }
-
- public ECFieldElement subtract(ECFieldElement b)
- {
- int[] z = Nat256.create();
- SecP256R1Field.subtract(x, ((SecP256R1FieldElement)b).x, z);
- return new SecP256R1FieldElement(z);
- }
-
- public ECFieldElement multiply(ECFieldElement b)
- {
- int[] z = Nat256.create();
- SecP256R1Field.multiply(x, ((SecP256R1FieldElement)b).x, z);
- return new SecP256R1FieldElement(z);
- }
-
- public ECFieldElement divide(ECFieldElement b)
- {
-// return multiply(b.invert());
- int[] z = Nat256.create();
- Mod.invert(SecP256R1Field.P, ((SecP256R1FieldElement)b).x, z);
- SecP256R1Field.multiply(z, x, z);
- return new SecP256R1FieldElement(z);
- }
-
- public ECFieldElement negate()
- {
- int[] z = Nat256.create();
- SecP256R1Field.negate(x, z);
- return new SecP256R1FieldElement(z);
- }
-
- public ECFieldElement square()
- {
- int[] z = Nat256.create();
- SecP256R1Field.square(x, z);
- return new SecP256R1FieldElement(z);
- }
-
- public ECFieldElement invert()
- {
-// return new SecP256R1FieldElement(toBigInteger().modInverse(Q));
- int[] z = Nat256.create();
- Mod.invert(SecP256R1Field.P, x, z);
- return new SecP256R1FieldElement(z);
- }
-
- /**
- * return a sqrt root - the routine verifies that the calculation returns the right value - if
- * none exists it returns null.
- */
- public ECFieldElement sqrt()
- {
- // Raise this element to the exponent 2^254 - 2^222 + 2^190 + 2^94
-
- int[] x1 = this.x;
- if (Nat256.isZero(x1) || Nat256.isOne(x1))
- {
- return this;
- }
-
- int[] t1 = Nat256.create();
- int[] t2 = Nat256.create();
-
- SecP256R1Field.square(x1, t1);
- SecP256R1Field.multiply(t1, x1, t1);
-
- SecP256R1Field.squareN(t1, 2, t2);
- SecP256R1Field.multiply(t2, t1, t2);
-
- SecP256R1Field.squareN(t2, 4, t1);
- SecP256R1Field.multiply(t1, t2, t1);
-
- SecP256R1Field.squareN(t1, 8, t2);
- SecP256R1Field.multiply(t2, t1, t2);
-
- SecP256R1Field.squareN(t2, 16, t1);
- SecP256R1Field.multiply(t1, t2, t1);
-
- SecP256R1Field.squareN(t1, 32, t1);
- SecP256R1Field.multiply(t1, x1, t1);
-
- SecP256R1Field.squareN(t1, 96, t1);
- SecP256R1Field.multiply(t1, x1, t1);
-
- SecP256R1Field.squareN(t1, 94, t1);
- SecP256R1Field.square(t1, t2);
-
- return Nat256.eq(x1, t2) ? new SecP256R1FieldElement(t1) : null;
- }
-
- public boolean equals(Object other)
- {
- if (other == this)
- {
- return true;
- }
-
- if (!(other instanceof SecP256R1FieldElement))
- {
- return false;
- }
-
- SecP256R1FieldElement o = (SecP256R1FieldElement)other;
- return Nat256.eq(x, o.x);
- }
-
- public int hashCode()
- {
- return Q.hashCode() ^ Arrays.hashCode(x, 0, 8);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Point.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Point.java
deleted file mode 100644
index 930fdc58..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Point.java
+++ /dev/null
@@ -1,308 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.raw.Nat;
-import org.bouncycastle.math.raw.Nat256;
-
-public class SecP256R1Point extends ECPoint.AbstractFp
-{
- /**
- * Create a point which encodes with point compression.
- *
- * @param curve
- * the curve to use
- * @param x
- * affine x co-ordinate
- * @param y
- * affine y co-ordinate
- *
- * @deprecated Use ECCurve.createPoint to construct points
- */
- public SecP256R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- this(curve, x, y, false);
- }
-
- /**
- * Create a point that encodes with or without point compresion.
- *
- * @param curve
- * the curve to use
- * @param x
- * affine x co-ordinate
- * @param y
- * affine y co-ordinate
- * @param withCompression
- * if true encode with point compression
- *
- * @deprecated per-point compression property will be removed, refer
- * {@link #getEncoded(boolean)}
- */
- public SecP256R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- super(curve, x, y);
-
- if ((x == null) != (y == null))
- {
- throw new IllegalArgumentException("Exactly one of the field elements is null");
- }
-
- this.withCompression = withCompression;
- }
-
- SecP256R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
- {
- super(curve, x, y, zs);
-
- this.withCompression = withCompression;
- }
-
- protected ECPoint detach()
- {
- return new SecP256R1Point(null, getAffineXCoord(), getAffineYCoord());
- }
-
- public ECPoint add(ECPoint b)
- {
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return this;
- }
- if (this == b)
- {
- return twice();
- }
-
- ECCurve curve = this.getCurve();
-
- SecP256R1FieldElement X1 = (SecP256R1FieldElement)this.x, Y1 = (SecP256R1FieldElement)this.y;
- SecP256R1FieldElement X2 = (SecP256R1FieldElement)b.getXCoord(), Y2 = (SecP256R1FieldElement)b.getYCoord();
-
- SecP256R1FieldElement Z1 = (SecP256R1FieldElement)this.zs[0];
- SecP256R1FieldElement Z2 = (SecP256R1FieldElement)b.getZCoord(0);
-
- int c;
- int[] tt1 = Nat256.createExt();
- int[] t2 = Nat256.create();
- int[] t3 = Nat256.create();
- int[] t4 = Nat256.create();
-
- boolean Z1IsOne = Z1.isOne();
- int[] U2, S2;
- if (Z1IsOne)
- {
- U2 = X2.x;
- S2 = Y2.x;
- }
- else
- {
- S2 = t3;
- SecP256R1Field.square(Z1.x, S2);
-
- U2 = t2;
- SecP256R1Field.multiply(S2, X2.x, U2);
-
- SecP256R1Field.multiply(S2, Z1.x, S2);
- SecP256R1Field.multiply(S2, Y2.x, S2);
- }
-
- boolean Z2IsOne = Z2.isOne();
- int[] U1, S1;
- if (Z2IsOne)
- {
- U1 = X1.x;
- S1 = Y1.x;
- }
- else
- {
- S1 = t4;
- SecP256R1Field.square(Z2.x, S1);
-
- U1 = tt1;
- SecP256R1Field.multiply(S1, X1.x, U1);
-
- SecP256R1Field.multiply(S1, Z2.x, S1);
- SecP256R1Field.multiply(S1, Y1.x, S1);
- }
-
- int[] H = Nat256.create();
- SecP256R1Field.subtract(U1, U2, H);
-
- int[] R = t2;
- SecP256R1Field.subtract(S1, S2, R);
-
- // Check if b == this or b == -this
- if (Nat256.isZero(H))
- {
- if (Nat256.isZero(R))
- {
- // this == b, i.e. this must be doubled
- return this.twice();
- }
-
- // this == -b, i.e. the result is the point at infinity
- return curve.getInfinity();
- }
-
- int[] HSquared = t3;
- SecP256R1Field.square(H, HSquared);
-
- int[] G = Nat256.create();
- SecP256R1Field.multiply(HSquared, H, G);
-
- int[] V = t3;
- SecP256R1Field.multiply(HSquared, U1, V);
-
- SecP256R1Field.negate(G, G);
- Nat256.mul(S1, G, tt1);
-
- c = Nat256.addBothTo(V, V, G);
- SecP256R1Field.reduce32(c, G);
-
- SecP256R1FieldElement X3 = new SecP256R1FieldElement(t4);
- SecP256R1Field.square(R, X3.x);
- SecP256R1Field.subtract(X3.x, G, X3.x);
-
- SecP256R1FieldElement Y3 = new SecP256R1FieldElement(G);
- SecP256R1Field.subtract(V, X3.x, Y3.x);
- SecP256R1Field.multiplyAddToExt(Y3.x, R, tt1);
- SecP256R1Field.reduce(tt1, Y3.x);
-
- SecP256R1FieldElement Z3 = new SecP256R1FieldElement(H);
- if (!Z1IsOne)
- {
- SecP256R1Field.multiply(Z3.x, Z1.x, Z3.x);
- }
- if (!Z2IsOne)
- {
- SecP256R1Field.multiply(Z3.x, Z2.x, Z3.x);
- }
-
- ECFieldElement[] zs = new ECFieldElement[]{ Z3 };
-
- return new SecP256R1Point(curve, X3, Y3, zs, this.withCompression);
- }
-
- public ECPoint twice()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- ECCurve curve = this.getCurve();
-
- SecP256R1FieldElement Y1 = (SecP256R1FieldElement)this.y;
- if (Y1.isZero())
- {
- return curve.getInfinity();
- }
-
- SecP256R1FieldElement X1 = (SecP256R1FieldElement)this.x, Z1 = (SecP256R1FieldElement)this.zs[0];
-
- int c;
- int[] t1 = Nat256.create();
- int[] t2 = Nat256.create();
-
- int[] Y1Squared = Nat256.create();
- SecP256R1Field.square(Y1.x, Y1Squared);
-
- int[] T = Nat256.create();
- SecP256R1Field.square(Y1Squared, T);
-
- boolean Z1IsOne = Z1.isOne();
-
- int[] Z1Squared = Z1.x;
- if (!Z1IsOne)
- {
- Z1Squared = t2;
- SecP256R1Field.square(Z1.x, Z1Squared);
- }
-
- SecP256R1Field.subtract(X1.x, Z1Squared, t1);
-
- int[] M = t2;
- SecP256R1Field.add(X1.x, Z1Squared, M);
- SecP256R1Field.multiply(M, t1, M);
- c = Nat256.addBothTo(M, M, M);
- SecP256R1Field.reduce32(c, M);
-
- int[] S = Y1Squared;
- SecP256R1Field.multiply(Y1Squared, X1.x, S);
- c = Nat.shiftUpBits(8, S, 2, 0);
- SecP256R1Field.reduce32(c, S);
-
- c = Nat.shiftUpBits(8, T, 3, 0, t1);
- SecP256R1Field.reduce32(c, t1);
-
- SecP256R1FieldElement X3 = new SecP256R1FieldElement(T);
- SecP256R1Field.square(M, X3.x);
- SecP256R1Field.subtract(X3.x, S, X3.x);
- SecP256R1Field.subtract(X3.x, S, X3.x);
-
- SecP256R1FieldElement Y3 = new SecP256R1FieldElement(S);
- SecP256R1Field.subtract(S, X3.x, Y3.x);
- SecP256R1Field.multiply(Y3.x, M, Y3.x);
- SecP256R1Field.subtract(Y3.x, t1, Y3.x);
-
- SecP256R1FieldElement Z3 = new SecP256R1FieldElement(M);
- SecP256R1Field.twice(Y1.x, Z3.x);
- if (!Z1IsOne)
- {
- SecP256R1Field.multiply(Z3.x, Z1.x, Z3.x);
- }
-
- return new SecP256R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
- }
-
- public ECPoint twicePlus(ECPoint b)
- {
- if (this == b)
- {
- return threeTimes();
- }
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return twice();
- }
-
- ECFieldElement Y1 = this.y;
- if (Y1.isZero())
- {
- return b;
- }
-
- return twice().add(b);
- }
-
- public ECPoint threeTimes()
- {
- if (this.isInfinity() || this.y.isZero())
- {
- return this;
- }
-
- // NOTE: Be careful about recursions between twicePlus and threeTimes
- return twice().add(this);
- }
-
- public ECPoint negate()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- return new SecP256R1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Curve.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Curve.java
deleted file mode 100644
index 27cbcdb2..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Curve.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.util.encoders.Hex;
-
-public class SecP384R1Curve extends ECCurve.AbstractFp
-{
- public static final BigInteger q = new BigInteger(1,
- Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF"));
-
- private static final int SecP384R1_DEFAULT_COORDS = COORD_JACOBIAN;
-
- protected SecP384R1Point infinity;
-
- public SecP384R1Curve()
- {
- super(q);
-
- this.infinity = new SecP384R1Point(this, null, null);
-
- this.a = fromBigInteger(new BigInteger(1,
- Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC")));
- this.b = fromBigInteger(new BigInteger(1,
- Hex.decode("B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF")));
- this.order = new BigInteger(1, Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973"));
- this.cofactor = BigInteger.valueOf(1);
-
- this.coord = SecP384R1_DEFAULT_COORDS;
- }
-
- protected ECCurve cloneCurve()
- {
- return new SecP384R1Curve();
- }
-
- public boolean supportsCoordinateSystem(int coord)
- {
- switch (coord)
- {
- case COORD_JACOBIAN:
- return true;
- default:
- return false;
- }
- }
-
- public BigInteger getQ()
- {
- return q;
- }
-
- public int getFieldSize()
- {
- return q.bitLength();
- }
-
- public ECFieldElement fromBigInteger(BigInteger x)
- {
- return new SecP384R1FieldElement(x);
- }
-
- protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- return new SecP384R1Point(this, x, y, withCompression);
- }
-
- protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
- {
- return new SecP384R1Point(this, x, y, zs, withCompression);
- }
-
- public ECPoint getInfinity()
- {
- return infinity;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Field.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Field.java
deleted file mode 100644
index f321a105..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Field.java
+++ /dev/null
@@ -1,295 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.raw.Nat;
-import org.bouncycastle.math.raw.Nat384;
-
-public class SecP384R1Field
-{
- private static final long M = 0xFFFFFFFFL;
-
- // 2^384 - 2^128 - 2^96 + 2^32 - 1
- static final int[] P = new int[]{ 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF,
- 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
- static final int[] PExt = new int[]{ 0x00000001, 0xFFFFFFFE, 0x00000000, 0x00000002, 0x00000000, 0xFFFFFFFE,
- 0x00000000, 0x00000002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFE, 0x00000001, 0x00000000,
- 0xFFFFFFFE, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
- private static final int[] PExtInv = new int[]{ 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0x00000001,
- 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001, 0xFFFFFFFE, 0xFFFFFFFF,
- 0x00000001, 0x00000002 };
- private static final int P11 = 0xFFFFFFFF;
- private static final int PExt23 = 0xFFFFFFFF;
-
- public static void add(int[] x, int[] y, int[] z)
- {
- int c = Nat.add(12, x, y, z);
- if (c != 0 || (z[11] == P11 && Nat.gte(12, z, P)))
- {
- addPInvTo(z);
- }
- }
-
- public static void addExt(int[] xx, int[] yy, int[] zz)
- {
- int c = Nat.add(24, xx, yy, zz);
- if (c != 0 || (zz[23] == PExt23 && Nat.gte(24, zz, PExt)))
- {
- if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
- {
- Nat.incAt(24, zz, PExtInv.length);
- }
- }
- }
-
- public static void addOne(int[] x, int[] z)
- {
- int c = Nat.inc(12, x, z);
- if (c != 0 || (z[11] == P11 && Nat.gte(12, z, P)))
- {
- addPInvTo(z);
- }
- }
-
- public static int[] fromBigInteger(BigInteger x)
- {
- int[] z = Nat.fromBigInteger(384, x);
- if (z[11] == P11 && Nat.gte(12, z, P))
- {
- Nat.subFrom(12, P, z);
- }
- return z;
- }
-
- public static void half(int[] x, int[] z)
- {
- if ((x[0] & 1) == 0)
- {
- Nat.shiftDownBit(12, x, 0, z);
- }
- else
- {
- int c = Nat.add(12, x, P, z);
- Nat.shiftDownBit(12, z, c);
- }
- }
-
- public static void multiply(int[] x, int[] y, int[] z)
- {
- int[] tt = Nat.create(24);
- Nat384.mul(x, y, tt);
- reduce(tt, z);
- }
-
- public static void negate(int[] x, int[] z)
- {
- if (Nat.isZero(12, x))
- {
- Nat.zero(12, z);
- }
- else
- {
- Nat.sub(12, P, x, z);
- }
- }
-
- public static void reduce(int[] xx, int[] z)
- {
- long xx16 = xx[16] & M, xx17 = xx[17] & M, xx18 = xx[18] & M, xx19 = xx[19] & M;
- long xx20 = xx[20] & M, xx21 = xx[21] & M, xx22 = xx[22] & M, xx23 = xx[23] & M;
-
- final long n = 1;
-
- long t0 = (xx[12] & M) + xx20 - n;
- long t1 = (xx[13] & M) + xx22;
- long t2 = (xx[14] & M) + xx22 + xx23;
- long t3 = (xx[15] & M) + xx23;
- long t4 = xx17 + xx21;
- long t5 = xx21 - xx23;
- long t6 = xx22 - xx23;
-
- long cc = 0;
- cc += (xx[0] & M) + t0 + t5;
- z[0] = (int)cc;
- cc >>= 32;
- cc += (xx[1] & M) + xx23 - t0 + t1;
- z[1] = (int)cc;
- cc >>= 32;
- cc += (xx[2] & M) - xx21 - t1 + t2;
- z[2] = (int)cc;
- cc >>= 32;
- cc += (xx[3] & M) + t0 - t2 + t3 + t5;
- z[3] = (int)cc;
- cc >>= 32;
- cc += (xx[4] & M) + xx16 + xx21 + t0 + t1 - t3 + t5;
- z[4] = (int)cc;
- cc >>= 32;
- cc += (xx[5] & M) - xx16 + t1 + t2 + t4;
- z[5] = (int)cc;
- cc >>= 32;
- cc += (xx[6] & M) + xx18 - xx17 + t2 + t3;
- z[6] = (int)cc;
- cc >>= 32;
- cc += (xx[7] & M) + xx16 + xx19 - xx18 + t3;
- z[7] = (int)cc;
- cc >>= 32;
- cc += (xx[8] & M) + xx16 + xx17 + xx20 - xx19;
- z[8] = (int)cc;
- cc >>= 32;
- cc += (xx[9] & M) + xx18 - xx20 + t4;
- z[9] = (int)cc;
- cc >>= 32;
- cc += (xx[10] & M) + xx18 + xx19 - t5 + t6;
- z[10] = (int)cc;
- cc >>= 32;
- cc += (xx[11] & M) + xx19 + xx20 - t6;
- z[11] = (int)cc;
- cc >>= 32;
- cc += n;
-
-// assert cc >= 0;
-
- reduce32((int)cc, z);
- }
-
- public static void reduce32(int x, int[] z)
- {
- long cc = 0;
-
- if (x != 0)
- {
- long xx12 = x & M;
-
- cc += (z[0] & M) + xx12;
- z[0] = (int)cc;
- cc >>= 32;
- cc += (z[1] & M) - xx12;
- z[1] = (int)cc;
- cc >>= 32;
- if (cc != 0)
- {
- cc += (z[2] & M);
- z[2] = (int)cc;
- cc >>= 32;
- }
- cc += (z[3] & M) + xx12;
- z[3] = (int)cc;
- cc >>= 32;
- cc += (z[4] & M) + xx12;
- z[4] = (int)cc;
- cc >>= 32;
-
-// assert cc == 0 || cc == 1;
- }
-
- if ((cc != 0 && Nat.incAt(12, z, 5) != 0)
- || (z[11] == P11 && Nat.gte(12, z, P)))
- {
- addPInvTo(z);
- }
- }
-
- public static void square(int[] x, int[] z)
- {
- int[] tt = Nat.create(24);
- Nat384.square(x, tt);
- reduce(tt, z);
- }
-
- public static void squareN(int[] x, int n, int[] z)
- {
-// assert n > 0;
-
- int[] tt = Nat.create(24);
- Nat384.square(x, tt);
- reduce(tt, z);
-
- while (--n > 0)
- {
- Nat384.square(z, tt);
- reduce(tt, z);
- }
- }
-
- public static void subtract(int[] x, int[] y, int[] z)
- {
- int c = Nat.sub(12, x, y, z);
- if (c != 0)
- {
- subPInvFrom(z);
- }
- }
-
- public static void subtractExt(int[] xx, int[] yy, int[] zz)
- {
- int c = Nat.sub(24, xx, yy, zz);
- if (c != 0)
- {
- if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0)
- {
- Nat.decAt(24, zz, PExtInv.length);
- }
- }
- }
-
- public static void twice(int[] x, int[] z)
- {
- int c = Nat.shiftUpBit(12, x, 0, z);
- if (c != 0 || (z[11] == P11 && Nat.gte(12, z, P)))
- {
- addPInvTo(z);
- }
- }
-
- private static void addPInvTo(int[] z)
- {
- long c = (z[0] & M) + 1;
- z[0] = (int)c;
- c >>= 32;
- c += (z[1] & M) - 1;
- z[1] = (int)c;
- c >>= 32;
- if (c != 0)
- {
- c += (z[2] & M);
- z[2] = (int)c;
- c >>= 32;
- }
- c += (z[3] & M) + 1;
- z[3] = (int)c;
- c >>= 32;
- c += (z[4] & M) + 1;
- z[4] = (int)c;
- c >>= 32;
- if (c != 0)
- {
- Nat.incAt(12, z, 5);
- }
- }
-
- private static void subPInvFrom(int[] z)
- {
- long c = (z[0] & M) - 1;
- z[0] = (int)c;
- c >>= 32;
- c += (z[1] & M) + 1;
- z[1] = (int)c;
- c >>= 32;
- if (c != 0)
- {
- c += (z[2] & M);
- z[2] = (int)c;
- c >>= 32;
- }
- c += (z[3] & M) - 1;
- z[3] = (int)c;
- c >>= 32;
- c += (z[4] & M) - 1;
- z[4] = (int)c;
- c >>= 32;
- if (c != 0)
- {
- Nat.decAt(12, z, 5);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1FieldElement.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1FieldElement.java
deleted file mode 100644
index 24e585d8..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1FieldElement.java
+++ /dev/null
@@ -1,211 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.raw.Mod;
-import org.bouncycastle.math.raw.Nat;
-import org.bouncycastle.util.Arrays;
-
-public class SecP384R1FieldElement extends ECFieldElement
-{
- public static final BigInteger Q = SecP384R1Curve.q;
-
- protected int[] x;
-
- public SecP384R1FieldElement(BigInteger x)
- {
- if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
- {
- throw new IllegalArgumentException("x value invalid for SecP384R1FieldElement");
- }
-
- this.x = SecP384R1Field.fromBigInteger(x);
- }
-
- public SecP384R1FieldElement()
- {
- this.x = Nat.create(12);
- }
-
- protected SecP384R1FieldElement(int[] x)
- {
- this.x = x;
- }
-
- public boolean isZero()
- {
- return Nat.isZero(12, x);
- }
-
- public boolean isOne()
- {
- return Nat.isOne(12, x);
- }
-
- public boolean testBitZero()
- {
- return Nat.getBit(x, 0) == 1;
- }
-
- public BigInteger toBigInteger()
- {
- return Nat.toBigInteger(12, x);
- }
-
- public String getFieldName()
- {
- return "SecP384R1Field";
- }
-
- public int getFieldSize()
- {
- return Q.bitLength();
- }
-
- public ECFieldElement add(ECFieldElement b)
- {
- int[] z = Nat.create(12);
- SecP384R1Field.add(x, ((SecP384R1FieldElement)b).x, z);
- return new SecP384R1FieldElement(z);
- }
-
- public ECFieldElement addOne()
- {
- int[] z = Nat.create(12);
- SecP384R1Field.addOne(x, z);
- return new SecP384R1FieldElement(z);
- }
-
- public ECFieldElement subtract(ECFieldElement b)
- {
- int[] z = Nat.create(12);
- SecP384R1Field.subtract(x, ((SecP384R1FieldElement)b).x, z);
- return new SecP384R1FieldElement(z);
- }
-
- public ECFieldElement multiply(ECFieldElement b)
- {
- int[] z = Nat.create(12);
- SecP384R1Field.multiply(x, ((SecP384R1FieldElement)b).x, z);
- return new SecP384R1FieldElement(z);
- }
-
- public ECFieldElement divide(ECFieldElement b)
- {
-// return multiply(b.invert());
- int[] z = Nat.create(12);
- Mod.invert(SecP384R1Field.P, ((SecP384R1FieldElement)b).x, z);
- SecP384R1Field.multiply(z, x, z);
- return new SecP384R1FieldElement(z);
- }
-
- public ECFieldElement negate()
- {
- int[] z = Nat.create(12);
- SecP384R1Field.negate(x, z);
- return new SecP384R1FieldElement(z);
- }
-
- public ECFieldElement square()
- {
- int[] z = Nat.create(12);
- SecP384R1Field.square(x, z);
- return new SecP384R1FieldElement(z);
- }
-
- public ECFieldElement invert()
- {
-// return new SecP384R1FieldElement(toBigInteger().modInverse(Q));
- int[] z = Nat.create(12);
- Mod.invert(SecP384R1Field.P, x, z);
- return new SecP384R1FieldElement(z);
- }
-
- /**
- * return a sqrt root - the routine verifies that the calculation returns the right value - if
- * none exists it returns null.
- */
- public ECFieldElement sqrt()
- {
- // Raise this element to the exponent 2^382 - 2^126 - 2^94 + 2^30
-
- int[] x1 = this.x;
- if (Nat.isZero(12, x1) || Nat.isOne(12, x1))
- {
- return this;
- }
-
- int[] t1 = Nat.create(12);
- int[] t2 = Nat.create(12);
- int[] t3 = Nat.create(12);
- int[] t4 = Nat.create(12);
-
- SecP384R1Field.square(x1, t1);
- SecP384R1Field.multiply(t1, x1, t1);
-
- SecP384R1Field.squareN(t1, 2, t2);
- SecP384R1Field.multiply(t2, t1, t2);
-
- SecP384R1Field.square(t2, t2);
- SecP384R1Field.multiply(t2, x1, t2);
-
- SecP384R1Field.squareN(t2, 5, t3);
- SecP384R1Field.multiply(t3, t2, t3);
-
- SecP384R1Field.squareN(t3, 5, t4);
- SecP384R1Field.multiply(t4, t2, t4);
-
- SecP384R1Field.squareN(t4, 15, t2);
- SecP384R1Field.multiply(t2, t4, t2);
-
- SecP384R1Field.squareN(t2, 2, t3);
- SecP384R1Field.multiply(t1, t3, t1);
-
- SecP384R1Field.squareN(t3, 28, t3);
- SecP384R1Field.multiply(t2, t3, t2);
-
- SecP384R1Field.squareN(t2, 60, t3);
- SecP384R1Field.multiply(t3, t2, t3);
-
- int[] r = t2;
-
- SecP384R1Field.squareN(t3, 120, r);
- SecP384R1Field.multiply(r, t3, r);
-
- SecP384R1Field.squareN(r, 15, r);
- SecP384R1Field.multiply(r, t4, r);
-
- SecP384R1Field.squareN(r, 33, r);
- SecP384R1Field.multiply(r, t1, r);
-
- SecP384R1Field.squareN(r, 64, r);
- SecP384R1Field.multiply(r, x1, r);
-
- SecP384R1Field.squareN(r, 30, t1);
- SecP384R1Field.square(t1, t2);
-
- return Nat.eq(12, x1, t2) ? new SecP384R1FieldElement(t1) : null;
- }
-
- public boolean equals(Object other)
- {
- if (other == this)
- {
- return true;
- }
-
- if (!(other instanceof SecP384R1FieldElement))
- {
- return false;
- }
-
- SecP384R1FieldElement o = (SecP384R1FieldElement)other;
- return Nat.eq(12, x, o.x);
- }
-
- public int hashCode()
- {
- return Q.hashCode() ^ Arrays.hashCode(x, 0, 12);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Point.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Point.java
deleted file mode 100644
index 89f6bf4f..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Point.java
+++ /dev/null
@@ -1,309 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.raw.Nat;
-import org.bouncycastle.math.raw.Nat384;
-
-public class SecP384R1Point extends ECPoint.AbstractFp
-{
- /**
- * Create a point which encodes with point compression.
- *
- * @param curve
- * the curve to use
- * @param x
- * affine x co-ordinate
- * @param y
- * affine y co-ordinate
- *
- * @deprecated Use ECCurve.createPoint to construct points
- */
- public SecP384R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- this(curve, x, y, false);
- }
-
- /**
- * Create a point that encodes with or without point compresion.
- *
- * @param curve
- * the curve to use
- * @param x
- * affine x co-ordinate
- * @param y
- * affine y co-ordinate
- * @param withCompression
- * if true encode with point compression
- *
- * @deprecated per-point compression property will be removed, refer
- * {@link #getEncoded(boolean)}
- */
- public SecP384R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- super(curve, x, y);
-
- if ((x == null) != (y == null))
- {
- throw new IllegalArgumentException("Exactly one of the field elements is null");
- }
-
- this.withCompression = withCompression;
- }
-
- SecP384R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
- {
- super(curve, x, y, zs);
-
- this.withCompression = withCompression;
- }
-
- protected ECPoint detach()
- {
- return new SecP384R1Point(null, getAffineXCoord(), getAffineYCoord());
- }
-
- public ECPoint add(ECPoint b)
- {
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return this;
- }
- if (this == b)
- {
- return twice();
- }
-
- ECCurve curve = this.getCurve();
-
- SecP384R1FieldElement X1 = (SecP384R1FieldElement)this.x, Y1 = (SecP384R1FieldElement)this.y;
- SecP384R1FieldElement X2 = (SecP384R1FieldElement)b.getXCoord(), Y2 = (SecP384R1FieldElement)b.getYCoord();
-
- SecP384R1FieldElement Z1 = (SecP384R1FieldElement)this.zs[0];
- SecP384R1FieldElement Z2 = (SecP384R1FieldElement)b.getZCoord(0);
-
- int c;
- int[] tt1 = Nat.create(24);
- int[] tt2 = Nat.create(24);
- int[] t3 = Nat.create(12);
- int[] t4 = Nat.create(12);
-
- boolean Z1IsOne = Z1.isOne();
- int[] U2, S2;
- if (Z1IsOne)
- {
- U2 = X2.x;
- S2 = Y2.x;
- }
- else
- {
- S2 = t3;
- SecP384R1Field.square(Z1.x, S2);
-
- U2 = tt2;
- SecP384R1Field.multiply(S2, X2.x, U2);
-
- SecP384R1Field.multiply(S2, Z1.x, S2);
- SecP384R1Field.multiply(S2, Y2.x, S2);
- }
-
- boolean Z2IsOne = Z2.isOne();
- int[] U1, S1;
- if (Z2IsOne)
- {
- U1 = X1.x;
- S1 = Y1.x;
- }
- else
- {
- S1 = t4;
- SecP384R1Field.square(Z2.x, S1);
-
- U1 = tt1;
- SecP384R1Field.multiply(S1, X1.x, U1);
-
- SecP384R1Field.multiply(S1, Z2.x, S1);
- SecP384R1Field.multiply(S1, Y1.x, S1);
- }
-
- int[] H = Nat.create(12);
- SecP384R1Field.subtract(U1, U2, H);
-
- int[] R = Nat.create(12);
- SecP384R1Field.subtract(S1, S2, R);
-
- // Check if b == this or b == -this
- if (Nat.isZero(12, H))
- {
- if (Nat.isZero(12, R))
- {
- // this == b, i.e. this must be doubled
- return this.twice();
- }
-
- // this == -b, i.e. the result is the point at infinity
- return curve.getInfinity();
- }
-
- int[] HSquared = t3;
- SecP384R1Field.square(H, HSquared);
-
- int[] G = Nat.create(12);
- SecP384R1Field.multiply(HSquared, H, G);
-
- int[] V = t3;
- SecP384R1Field.multiply(HSquared, U1, V);
-
- SecP384R1Field.negate(G, G);
- Nat384.mul(S1, G, tt1);
-
- c = Nat.addBothTo(12, V, V, G);
- SecP384R1Field.reduce32(c, G);
-
- SecP384R1FieldElement X3 = new SecP384R1FieldElement(t4);
- SecP384R1Field.square(R, X3.x);
- SecP384R1Field.subtract(X3.x, G, X3.x);
-
- SecP384R1FieldElement Y3 = new SecP384R1FieldElement(G);
- SecP384R1Field.subtract(V, X3.x, Y3.x);
- Nat384.mul(Y3.x, R, tt2);
- SecP384R1Field.addExt(tt1, tt2, tt1);
- SecP384R1Field.reduce(tt1, Y3.x);
-
- SecP384R1FieldElement Z3 = new SecP384R1FieldElement(H);
- if (!Z1IsOne)
- {
- SecP384R1Field.multiply(Z3.x, Z1.x, Z3.x);
- }
- if (!Z2IsOne)
- {
- SecP384R1Field.multiply(Z3.x, Z2.x, Z3.x);
- }
-
- ECFieldElement[] zs = new ECFieldElement[]{ Z3 };
-
- return new SecP384R1Point(curve, X3, Y3, zs, this.withCompression);
- }
-
- public ECPoint twice()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- ECCurve curve = this.getCurve();
-
- SecP384R1FieldElement Y1 = (SecP384R1FieldElement)this.y;
- if (Y1.isZero())
- {
- return curve.getInfinity();
- }
-
- SecP384R1FieldElement X1 = (SecP384R1FieldElement)this.x, Z1 = (SecP384R1FieldElement)this.zs[0];
-
- int c;
- int[] t1 = Nat.create(12);
- int[] t2 = Nat.create(12);
-
- int[] Y1Squared = Nat.create(12);
- SecP384R1Field.square(Y1.x, Y1Squared);
-
- int[] T = Nat.create(12);
- SecP384R1Field.square(Y1Squared, T);
-
- boolean Z1IsOne = Z1.isOne();
-
- int[] Z1Squared = Z1.x;
- if (!Z1IsOne)
- {
- Z1Squared = t2;
- SecP384R1Field.square(Z1.x, Z1Squared);
- }
-
- SecP384R1Field.subtract(X1.x, Z1Squared, t1);
-
- int[] M = t2;
- SecP384R1Field.add(X1.x, Z1Squared, M);
- SecP384R1Field.multiply(M, t1, M);
- c = Nat.addBothTo(12, M, M, M);
- SecP384R1Field.reduce32(c, M);
-
- int[] S = Y1Squared;
- SecP384R1Field.multiply(Y1Squared, X1.x, S);
- c = Nat.shiftUpBits(12, S, 2, 0);
- SecP384R1Field.reduce32(c, S);
-
- c = Nat.shiftUpBits(12, T, 3, 0, t1);
- SecP384R1Field.reduce32(c, t1);
-
- SecP384R1FieldElement X3 = new SecP384R1FieldElement(T);
- SecP384R1Field.square(M, X3.x);
- SecP384R1Field.subtract(X3.x, S, X3.x);
- SecP384R1Field.subtract(X3.x, S, X3.x);
-
- SecP384R1FieldElement Y3 = new SecP384R1FieldElement(S);
- SecP384R1Field.subtract(S, X3.x, Y3.x);
- SecP384R1Field.multiply(Y3.x, M, Y3.x);
- SecP384R1Field.subtract(Y3.x, t1, Y3.x);
-
- SecP384R1FieldElement Z3 = new SecP384R1FieldElement(M);
- SecP384R1Field.twice(Y1.x, Z3.x);
- if (!Z1IsOne)
- {
- SecP384R1Field.multiply(Z3.x, Z1.x, Z3.x);
- }
-
- return new SecP384R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
- }
-
- public ECPoint twicePlus(ECPoint b)
- {
- if (this == b)
- {
- return threeTimes();
- }
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return twice();
- }
-
- ECFieldElement Y1 = this.y;
- if (Y1.isZero())
- {
- return b;
- }
-
- return twice().add(b);
- }
-
- public ECPoint threeTimes()
- {
- if (this.isInfinity() || this.y.isZero())
- {
- return this;
- }
-
- // NOTE: Be careful about recursions between twicePlus and threeTimes
- return twice().add(this);
- }
-
- public ECPoint negate()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- return new SecP384R1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Curve.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Curve.java
deleted file mode 100644
index 16691b10..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Curve.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.util.encoders.Hex;
-
-public class SecP521R1Curve extends ECCurve.AbstractFp
-{
- public static final BigInteger q = new BigInteger(1,
- Hex.decode("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));
-
- private static final int SecP521R1_DEFAULT_COORDS = COORD_JACOBIAN;
-
- protected SecP521R1Point infinity;
-
- public SecP521R1Curve()
- {
- super(q);
-
- this.infinity = new SecP521R1Point(this, null, null);
-
- this.a = fromBigInteger(new BigInteger(1,
- Hex.decode("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC")));
- this.b = fromBigInteger(new BigInteger(1,
- Hex.decode("0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00")));
- this.order = new BigInteger(1, Hex.decode("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409"));
- this.cofactor = BigInteger.valueOf(1);
-
- this.coord = SecP521R1_DEFAULT_COORDS;
- }
-
- protected ECCurve cloneCurve()
- {
- return new SecP521R1Curve();
- }
-
- public boolean supportsCoordinateSystem(int coord)
- {
- switch (coord)
- {
- case COORD_JACOBIAN:
- return true;
- default:
- return false;
- }
- }
-
- public BigInteger getQ()
- {
- return q;
- }
-
- public int getFieldSize()
- {
- return q.bitLength();
- }
-
- public ECFieldElement fromBigInteger(BigInteger x)
- {
- return new SecP521R1FieldElement(x);
- }
-
- protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- return new SecP521R1Point(this, x, y, withCompression);
- }
-
- protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
- {
- return new SecP521R1Point(this, x, y, zs, withCompression);
- }
-
- public ECPoint getInfinity()
- {
- return infinity;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Field.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Field.java
deleted file mode 100644
index 00f10667..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Field.java
+++ /dev/null
@@ -1,156 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.raw.Nat;
-import org.bouncycastle.math.raw.Nat512;
-
-public class SecP521R1Field
-{
- // 2^521 - 1
- static final int[] P = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
- 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x1FF };
- private static final int P16 = 0x1FF;
-
- public static void add(int[] x, int[] y, int[] z)
- {
- int c = Nat.add(16, x, y, z) + x[16] + y[16];
- if (c > P16 || (c == P16 && Nat.eq(16, z, P)))
- {
- c += Nat.inc(16, z);
- c &= P16;
- }
- z[16] = c;
- }
-
- public static void addOne(int[] x, int[] z)
- {
- int c = Nat.inc(16, x, z) + x[16];
- if (c > P16 || (c == P16 && Nat.eq(16, z, P)))
- {
- c += Nat.inc(16, z);
- c &= P16;
- }
- z[16] = c;
- }
-
- public static int[] fromBigInteger(BigInteger x)
- {
- int[] z = Nat.fromBigInteger(521, x);
- if (Nat.eq(17, z, P))
- {
- Nat.zero(17, z);
- }
- return z;
- }
-
- public static void half(int[] x, int[] z)
- {
- int x16 = x[16];
- int c = Nat.shiftDownBit(16, x, x16, z);
- z[16] = (x16 >>> 1) | (c >>> 23);
- }
-
- public static void multiply(int[] x, int[] y, int[] z)
- {
- int[] tt = Nat.create(33);
- implMultiply(x, y, tt);
- reduce(tt, z);
- }
-
- public static void negate(int[] x, int[] z)
- {
- if (Nat.isZero(17, x))
- {
- Nat.zero(17, z);
- }
- else
- {
- Nat.sub(17, P, x, z);
- }
- }
-
- public static void reduce(int[] xx, int[] z)
- {
-// assert xx[32] >>> 18 == 0;
-
- int xx32 = xx[32];
- int c = Nat.shiftDownBits(16, xx, 16, 9, xx32, z, 0) >>> 23;
- c += xx32 >>> 9;
- c += Nat.addTo(16, xx, z);
- if (c > P16 || (c == P16 && Nat.eq(16, z, P)))
- {
- c += Nat.inc(16, z);
- c &= P16;
- }
- z[16] = c;
- }
-
- public static void reduce23(int[] z)
- {
- int z16 = z[16];
- int c = Nat.addWordTo(16, z16 >>> 9, z) + (z16 & P16);
- if (c > P16 || (c == P16 && Nat.eq(16, z, P)))
- {
- c += Nat.inc(16, z);
- c &= P16;
- }
- z[16] = c;
- }
-
- public static void square(int[] x, int[] z)
- {
- int[] tt = Nat.create(33);
- implSquare(x, tt);
- reduce(tt, z);
- }
-
- public static void squareN(int[] x, int n, int[] z)
- {
-// assert n > 0;
-
- int[] tt = Nat.create(33);
- implSquare(x, tt);
- reduce(tt, z);
-
- while (--n > 0)
- {
- implSquare(z, tt);
- reduce(tt, z);
- }
- }
-
- public static void subtract(int[] x, int[] y, int[] z)
- {
- int c = Nat.sub(16, x, y, z) + x[16] - y[16];
- if (c < 0)
- {
- c += Nat.dec(16, z);
- c &= P16;
- }
- z[16] = c;
- }
-
- public static void twice(int[] x, int[] z)
- {
- int x16 = x[16];
- int c = Nat.shiftUpBit(16, x, x16 << 23, z) | (x16 << 1);
- z[16] = c & P16;
- }
-
- protected static void implMultiply(int[] x, int[] y, int[] zz)
- {
- Nat512.mul(x, y, zz);
-
- int x16 = x[16], y16 = y[16];
- zz[32] = Nat.mul31BothAdd(16, x16, y, y16, x, zz, 16) + (x16 * y16);
- }
-
- protected static void implSquare(int[] x, int[] zz)
- {
- Nat512.square(x, zz);
-
- int x16 = x[16];
- zz[32] = Nat.mulWordAddTo(16, x16 << 1, x, 0, zz, 16) + (x16 * x16);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1FieldElement.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1FieldElement.java
deleted file mode 100644
index ce9b6392..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1FieldElement.java
+++ /dev/null
@@ -1,169 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.raw.Mod;
-import org.bouncycastle.math.raw.Nat;
-import org.bouncycastle.util.Arrays;
-
-public class SecP521R1FieldElement extends ECFieldElement
-{
- public static final BigInteger Q = SecP521R1Curve.q;
-
- protected int[] x;
-
- public SecP521R1FieldElement(BigInteger x)
- {
- if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
- {
- throw new IllegalArgumentException("x value invalid for SecP521R1FieldElement");
- }
-
- this.x = SecP521R1Field.fromBigInteger(x);
- }
-
- public SecP521R1FieldElement()
- {
- this.x = Nat.create(17);
- }
-
- protected SecP521R1FieldElement(int[] x)
- {
- this.x = x;
- }
-
- public boolean isZero()
- {
- return Nat.isZero(17, x);
- }
-
- public boolean isOne()
- {
- return Nat.isOne(17, x);
- }
-
- public boolean testBitZero()
- {
- return Nat.getBit(x, 0) == 1;
- }
-
- public BigInteger toBigInteger()
- {
- return Nat.toBigInteger(17, x);
- }
-
- public String getFieldName()
- {
- return "SecP521R1Field";
- }
-
- public int getFieldSize()
- {
- return Q.bitLength();
- }
-
- public ECFieldElement add(ECFieldElement b)
- {
- int[] z = Nat.create(17);
- SecP521R1Field.add(x, ((SecP521R1FieldElement)b).x, z);
- return new SecP521R1FieldElement(z);
- }
-
- public ECFieldElement addOne()
- {
- int[] z = Nat.create(17);
- SecP521R1Field.addOne(x, z);
- return new SecP521R1FieldElement(z);
- }
-
- public ECFieldElement subtract(ECFieldElement b)
- {
- int[] z = Nat.create(17);
- SecP521R1Field.subtract(x, ((SecP521R1FieldElement)b).x, z);
- return new SecP521R1FieldElement(z);
- }
-
- public ECFieldElement multiply(ECFieldElement b)
- {
- int[] z = Nat.create(17);
- SecP521R1Field.multiply(x, ((SecP521R1FieldElement)b).x, z);
- return new SecP521R1FieldElement(z);
- }
-
- public ECFieldElement divide(ECFieldElement b)
- {
-// return multiply(b.invert());
- int[] z = Nat.create(17);
- Mod.invert(SecP521R1Field.P, ((SecP521R1FieldElement)b).x, z);
- SecP521R1Field.multiply(z, x, z);
- return new SecP521R1FieldElement(z);
- }
-
- public ECFieldElement negate()
- {
- int[] z = Nat.create(17);
- SecP521R1Field.negate(x, z);
- return new SecP521R1FieldElement(z);
- }
-
- public ECFieldElement square()
- {
- int[] z = Nat.create(17);
- SecP521R1Field.square(x, z);
- return new SecP521R1FieldElement(z);
- }
-
- public ECFieldElement invert()
- {
-// return new SecP521R1FieldElement(toBigInteger().modInverse(Q));
- int[] z = Nat.create(17);
- Mod.invert(SecP521R1Field.P, x, z);
- return new SecP521R1FieldElement(z);
- }
-
- // D.1.4 91
- /**
- * return a sqrt root - the routine verifies that the calculation returns the right value - if
- * none exists it returns null.
- */
- public ECFieldElement sqrt()
- {
- // Raise this element to the exponent 2^519
-
- int[] x1 = this.x;
- if (Nat.isZero(17, x1) || Nat.isOne(17, x1))
- {
- return this;
- }
-
- int[] t1 = Nat.create(17);
- int[] t2 = Nat.create(17);
-
- SecP521R1Field.squareN(x1, 519, t1);
- SecP521R1Field.square(t1, t2);
-
- return Nat.eq(17, x1, t2) ? new SecP521R1FieldElement(t1) : null;
- }
-
- public boolean equals(Object other)
- {
- if (other == this)
- {
- return true;
- }
-
- if (!(other instanceof SecP521R1FieldElement))
- {
- return false;
- }
-
- SecP521R1FieldElement o = (SecP521R1FieldElement)other;
- return Nat.eq(17, x, o.x);
- }
-
- public int hashCode()
- {
- return Q.hashCode() ^ Arrays.hashCode(x, 0, 17);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Point.java b/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Point.java
deleted file mode 100644
index d9737152..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Point.java
+++ /dev/null
@@ -1,333 +0,0 @@
-package org.bouncycastle.math.ec.custom.sec;
-
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.raw.Nat;
-
-public class SecP521R1Point extends ECPoint.AbstractFp
-{
- /**
- * Create a point which encodes with point compression.
- *
- * @param curve
- * the curve to use
- * @param x
- * affine x co-ordinate
- * @param y
- * affine y co-ordinate
- *
- * @deprecated Use ECCurve.createPoint to construct points
- */
- public SecP521R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- this(curve, x, y, false);
- }
-
- /**
- * Create a point that encodes with or without point compresion.
- *
- * @param curve
- * the curve to use
- * @param x
- * affine x co-ordinate
- * @param y
- * affine y co-ordinate
- * @param withCompression
- * if true encode with point compression
- *
- * @deprecated per-point compression property will be removed, refer
- * {@link #getEncoded(boolean)}
- */
- public SecP521R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- super(curve, x, y);
-
- if ((x == null) != (y == null))
- {
- throw new IllegalArgumentException("Exactly one of the field elements is null");
- }
-
- this.withCompression = withCompression;
- }
-
- SecP521R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
- {
- super(curve, x, y, zs);
-
- this.withCompression = withCompression;
- }
-
- protected ECPoint detach()
- {
- return new SecP521R1Point(null, getAffineXCoord(), getAffineYCoord());
- }
-
- public ECPoint add(ECPoint b)
- {
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return this;
- }
- if (this == b)
- {
- return twice();
- }
-
- ECCurve curve = this.getCurve();
-
- SecP521R1FieldElement X1 = (SecP521R1FieldElement)this.x, Y1 = (SecP521R1FieldElement)this.y;
- SecP521R1FieldElement X2 = (SecP521R1FieldElement)b.getXCoord(), Y2 = (SecP521R1FieldElement)b.getYCoord();
-
- SecP521R1FieldElement Z1 = (SecP521R1FieldElement)this.zs[0];
- SecP521R1FieldElement Z2 = (SecP521R1FieldElement)b.getZCoord(0);
-
- int[] t1 = Nat.create(17);
- int[] t2 = Nat.create(17);
- int[] t3 = Nat.create(17);
- int[] t4 = Nat.create(17);
-
- boolean Z1IsOne = Z1.isOne();
- int[] U2, S2;
- if (Z1IsOne)
- {
- U2 = X2.x;
- S2 = Y2.x;
- }
- else
- {
- S2 = t3;
- SecP521R1Field.square(Z1.x, S2);
-
- U2 = t2;
- SecP521R1Field.multiply(S2, X2.x, U2);
-
- SecP521R1Field.multiply(S2, Z1.x, S2);
- SecP521R1Field.multiply(S2, Y2.x, S2);
- }
-
- boolean Z2IsOne = Z2.isOne();
- int[] U1, S1;
- if (Z2IsOne)
- {
- U1 = X1.x;
- S1 = Y1.x;
- }
- else
- {
- S1 = t4;
- SecP521R1Field.square(Z2.x, S1);
-
- U1 = t1;
- SecP521R1Field.multiply(S1, X1.x, U1);
-
- SecP521R1Field.multiply(S1, Z2.x, S1);
- SecP521R1Field.multiply(S1, Y1.x, S1);
- }
-
- int[] H = Nat.create(17);
- SecP521R1Field.subtract(U1, U2, H);
-
- int[] R = t2;
- SecP521R1Field.subtract(S1, S2, R);
-
- // Check if b == this or b == -this
- if (Nat.isZero(17, H))
- {
- if (Nat.isZero(17, R))
- {
- // this == b, i.e. this must be doubled
- return this.twice();
- }
-
- // this == -b, i.e. the result is the point at infinity
- return curve.getInfinity();
- }
-
- int[] HSquared = t3;
- SecP521R1Field.square(H, HSquared);
-
- int[] G = Nat.create(17);
- SecP521R1Field.multiply(HSquared, H, G);
-
- int[] V = t3;
- SecP521R1Field.multiply(HSquared, U1, V);
-
- SecP521R1Field.multiply(S1, G, t1);
-
- SecP521R1FieldElement X3 = new SecP521R1FieldElement(t4);
- SecP521R1Field.square(R, X3.x);
- SecP521R1Field.add(X3.x, G, X3.x);
- SecP521R1Field.subtract(X3.x, V, X3.x);
- SecP521R1Field.subtract(X3.x, V, X3.x);
-
- SecP521R1FieldElement Y3 = new SecP521R1FieldElement(G);
- SecP521R1Field.subtract(V, X3.x, Y3.x);
- SecP521R1Field.multiply(Y3.x, R, t2);
- SecP521R1Field.subtract(t2, t1, Y3.x);
-
- SecP521R1FieldElement Z3 = new SecP521R1FieldElement(H);
- if (!Z1IsOne)
- {
- SecP521R1Field.multiply(Z3.x, Z1.x, Z3.x);
- }
- if (!Z2IsOne)
- {
- SecP521R1Field.multiply(Z3.x, Z2.x, Z3.x);
- }
-
- ECFieldElement[] zs = new ECFieldElement[]{ Z3 };
-
- return new SecP521R1Point(curve, X3, Y3, zs, this.withCompression);
- }
-
- public ECPoint twice()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- ECCurve curve = this.getCurve();
-
- SecP521R1FieldElement Y1 = (SecP521R1FieldElement)this.y;
- if (Y1.isZero())
- {
- return curve.getInfinity();
- }
-
- SecP521R1FieldElement X1 = (SecP521R1FieldElement)this.x, Z1 = (SecP521R1FieldElement)this.zs[0];
-
- int[] t1 = Nat.create(17);
- int[] t2 = Nat.create(17);
-
- int[] Y1Squared = Nat.create(17);
- SecP521R1Field.square(Y1.x, Y1Squared);
-
- int[] T = Nat.create(17);
- SecP521R1Field.square(Y1Squared, T);
-
- boolean Z1IsOne = Z1.isOne();
-
- int[] Z1Squared = Z1.x;
- if (!Z1IsOne)
- {
- Z1Squared = t2;
- SecP521R1Field.square(Z1.x, Z1Squared);
- }
-
- SecP521R1Field.subtract(X1.x, Z1Squared, t1);
-
- int[] M = t2;
- SecP521R1Field.add(X1.x, Z1Squared, M);
- SecP521R1Field.multiply(M, t1, M);
- Nat.addBothTo(17, M, M, M);
- SecP521R1Field.reduce23(M);
-
- int[] S = Y1Squared;
- SecP521R1Field.multiply(Y1Squared, X1.x, S);
- Nat.shiftUpBits(17, S, 2, 0);
- SecP521R1Field.reduce23(S);
-
- Nat.shiftUpBits(17, T, 3, 0, t1);
- SecP521R1Field.reduce23(t1);
-
- SecP521R1FieldElement X3 = new SecP521R1FieldElement(T);
- SecP521R1Field.square(M, X3.x);
- SecP521R1Field.subtract(X3.x, S, X3.x);
- SecP521R1Field.subtract(X3.x, S, X3.x);
-
- SecP521R1FieldElement Y3 = new SecP521R1FieldElement(S);
- SecP521R1Field.subtract(S, X3.x, Y3.x);
- SecP521R1Field.multiply(Y3.x, M, Y3.x);
- SecP521R1Field.subtract(Y3.x, t1, Y3.x);
-
- SecP521R1FieldElement Z3 = new SecP521R1FieldElement(M);
- SecP521R1Field.twice(Y1.x, Z3.x);
- if (!Z1IsOne)
- {
- SecP521R1Field.multiply(Z3.x, Z1.x, Z3.x);
- }
-
- return new SecP521R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
- }
-
- public ECPoint twicePlus(ECPoint b)
- {
- if (this == b)
- {
- return threeTimes();
- }
- if (this.isInfinity())
- {
- return b;
- }
- if (b.isInfinity())
- {
- return twice();
- }
-
- ECFieldElement Y1 = this.y;
- if (Y1.isZero())
- {
- return b;
- }
-
- return twice().add(b);
- }
-
- public ECPoint threeTimes()
- {
- if (this.isInfinity() || this.y.isZero())
- {
- return this;
- }
-
- // NOTE: Be careful about recursions between twicePlus and threeTimes
- return twice().add(this);
- }
-
- protected ECFieldElement two(ECFieldElement x)
- {
- return x.add(x);
- }
-
- protected ECFieldElement three(ECFieldElement x)
- {
- return two(x).add(x);
- }
-
- protected ECFieldElement four(ECFieldElement x)
- {
- return two(two(x));
- }
-
- protected ECFieldElement eight(ECFieldElement x)
- {
- return four(two(x));
- }
-
- protected ECFieldElement doubleProductFromSquares(ECFieldElement a, ECFieldElement b,
- ECFieldElement aSquared, ECFieldElement bSquared)
- {
- /*
- * NOTE: If squaring in the field is faster than multiplication, then this is a quicker
- * way to calculate 2.A.B, if A^2 and B^2 are already known.
- */
- return a.add(b).square().subtract(aSquared).subtract(bSquared);
- }
-
- public ECPoint negate()
- {
- if (this.isInfinity())
- {
- return this;
- }
-
- return new SecP521R1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/endo/ECEndomorphism.java b/core/src/main/java/org/bouncycastle/math/ec/endo/ECEndomorphism.java
deleted file mode 100644
index 2be0c01d..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/endo/ECEndomorphism.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.bouncycastle.math.ec.endo;
-
-import org.bouncycastle.math.ec.ECPointMap;
-
-public interface ECEndomorphism
-{
- ECPointMap getPointMap();
-
- boolean hasEfficientPointMap();
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/endo/GLVEndomorphism.java b/core/src/main/java/org/bouncycastle/math/ec/endo/GLVEndomorphism.java
deleted file mode 100644
index 8897bb38..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/endo/GLVEndomorphism.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.bouncycastle.math.ec.endo;
-
-import java.math.BigInteger;
-
-public interface GLVEndomorphism extends ECEndomorphism
-{
- BigInteger[] decomposeScalar(BigInteger k);
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBEndomorphism.java b/core/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBEndomorphism.java
deleted file mode 100644
index ab710d1a..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBEndomorphism.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.bouncycastle.math.ec.endo;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECPointMap;
-import org.bouncycastle.math.ec.ScaleXPointMap;
-
-public class GLVTypeBEndomorphism implements GLVEndomorphism
-{
- protected final ECCurve curve;
- protected final GLVTypeBParameters parameters;
- protected final ECPointMap pointMap;
-
- public GLVTypeBEndomorphism(ECCurve curve, GLVTypeBParameters parameters)
- {
- this.curve = curve;
- this.parameters = parameters;
- this.pointMap = new ScaleXPointMap(curve.fromBigInteger(parameters.getBeta()));
- }
-
- public BigInteger[] decomposeScalar(BigInteger k)
- {
- int bits = parameters.getBits();
- BigInteger b1 = calculateB(k, parameters.getG1(), bits);
- BigInteger b2 = calculateB(k, parameters.getG2(), bits);
-
- BigInteger[] v1 = parameters.getV1(), v2 = parameters.getV2();
- BigInteger a = k.subtract((b1.multiply(v1[0])).add(b2.multiply(v2[0])));
- BigInteger b = (b1.multiply(v1[1])).add(b2.multiply(v2[1])).negate();
-
- return new BigInteger[]{ a, b };
- }
-
- public ECPointMap getPointMap()
- {
- return pointMap;
- }
-
- public boolean hasEfficientPointMap()
- {
- return true;
- }
-
- protected BigInteger calculateB(BigInteger k, BigInteger g, int t)
- {
- boolean negative = (g.signum() < 0);
- BigInteger b = k.multiply(g.abs());
- boolean extra = b.testBit(t - 1);
- b = b.shiftRight(t);
- if (extra)
- {
- b = b.add(ECConstants.ONE);
- }
- return negative ? b.negate() : b;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBParameters.java b/core/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBParameters.java
deleted file mode 100644
index f02a882f..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBParameters.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package org.bouncycastle.math.ec.endo;
-
-import java.math.BigInteger;
-
-public class GLVTypeBParameters
-{
- protected final BigInteger beta;
- protected final BigInteger lambda;
- protected final BigInteger[] v1, v2;
- protected final BigInteger g1, g2;
- protected final int bits;
-
- public GLVTypeBParameters(BigInteger beta, BigInteger lambda, BigInteger[] v1, BigInteger[] v2, BigInteger g1,
- BigInteger g2, int bits)
- {
- this.beta = beta;
- this.lambda = lambda;
- this.v1 = v1;
- this.v2 = v2;
- this.g1 = g1;
- this.g2 = g2;
- this.bits = bits;
- }
-
- public BigInteger getBeta()
- {
- return beta;
- }
-
- public BigInteger getLambda()
- {
- return lambda;
- }
-
- public BigInteger[] getV1()
- {
- return v1;
- }
-
- public BigInteger[] getV2()
- {
- return v2;
- }
-
- public BigInteger getG1()
- {
- return g1;
- }
-
- public BigInteger getG2()
- {
- return g2;
- }
-
- public int getBits()
- {
- return bits;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/ec/tools/DiscoverEndomorphisms.java b/core/src/main/java/org/bouncycastle/math/ec/tools/DiscoverEndomorphisms.java
deleted file mode 100644
index 4ee2de60..00000000
--- a/core/src/main/java/org/bouncycastle/math/ec/tools/DiscoverEndomorphisms.java
+++ /dev/null
@@ -1,373 +0,0 @@
-package org.bouncycastle.math.ec.tools;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.asn1.x9.ECNamedCurveTable;
-import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.math.ec.ECAlgorithms;
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.util.BigIntegers;
-
-public class DiscoverEndomorphisms
-{
- private static final int radix = 16;
-
- public static void main(String[] args)
- {
- if (args.length < 1)
- {
- System.err.println("Expected a list of curve names as arguments");
- return;
- }
-
- for (int i = 0; i < args.length; ++i)
- {
- discoverEndomorphism(args[i]);
- }
- }
-
- private static void discoverEndomorphism(String curveName)
- {
- X9ECParameters x9 = ECNamedCurveTable.getByName(curveName);
- if (x9 == null)
- {
- System.err.println("Unknown curve: " + curveName);
- return;
- }
-
- ECCurve c = x9.getCurve();
- if (ECAlgorithms.isFpCurve(c))
- {
- BigInteger characteristic = c.getField().getCharacteristic();
-
- if (c.getA().isZero() && characteristic.mod(ECConstants.THREE).equals(ECConstants.ONE))
- {
- System.out.println("Curve '" + curveName + "' has a 'GLV Type B' endomorphism with these parameters: ");
- printGLVTypeBParameters(x9);
- }
- }
- }
-
- private static void printGLVTypeBParameters(X9ECParameters x9)
- {
- BigInteger n = x9.getN();
- BigInteger[] v1 = null;
- BigInteger[] v2 = null;
-
- // x^2 + x + 1 = 0 mod n
- BigInteger lambda = solveQuadraticEquation(n, ECConstants.ONE, ECConstants.ONE);
-
- BigInteger[] rt = extEuclidGLV(n, lambda);
- v1 = new BigInteger[]{ rt[2], rt[3].negate() };
- v2 = chooseShortest(new BigInteger[]{ rt[0], rt[1].negate() }, new BigInteger[]{ rt[4], rt[5].negate() });
-
- /*
- * If elements of v2 are not bounded by sqrt(n), then if r1/t1 are relatively prime there
- * _may_ yet be a GLV generator, so search for it. See
- * "Integer Decomposition for Fast Scalar Multiplication on Elliptic Curves", D. Kim, S. Lim
- * (SAC 2002)
- */
- if (!isVectorBoundedBySqrt(v2, n) && areRelativelyPrime(v1[0], v1[1]))
- {
- BigInteger r = v1[0], t = v1[1], s = r.add(t.multiply(lambda)).divide(n);
-
- BigInteger[] vw = extEuclidBezout(new BigInteger[]{ s.abs(), t.abs() });
- BigInteger v = vw[0], w = vw[1];
-
- if (s.signum() < 0)
- {
- v = v.negate();
- }
- if (t.signum() > 0)
- {
- w = w.negate();
- }
-
- BigInteger check = s.multiply(v).subtract(t.multiply(w));
- if (!check.equals(ECConstants.ONE))
- {
- throw new IllegalStateException();
- }
-
- BigInteger x = w.multiply(n).subtract(v.multiply(lambda));
-
- BigInteger base1 = v.negate();
- BigInteger base2 = x.negate();
-
- /*
- * We calculate the range(s) conservatively large to avoid messy rounding issues, so
- * there may be spurious candidate generators, but we won't miss any.
- */
- BigInteger sqrtN = isqrt(n.subtract(ECConstants.ONE)).add(ECConstants.ONE);
-
- BigInteger[] I1 = calculateRange(base1, sqrtN, t);
- BigInteger[] I2 = calculateRange(base2, sqrtN, r);
-
- BigInteger[] range = intersect(I1, I2);
- if (range != null)
- {
- for (BigInteger alpha = range[0]; alpha.compareTo(range[1]) <= 0; alpha = alpha.add(ECConstants.ONE))
- {
- BigInteger[] candidate = new BigInteger[]{ x.add(alpha.multiply(r)), v.add(alpha.multiply(t)) };
- if (isShorter(candidate, v2))
- {
- v2 = candidate;
- }
- }
- }
- }
-
- /*
- * 'Beta' is a field element of order 3. There are only two such values besides 1; determine which of them
- * corresponds to our choice for 'Lambda'.
- */
- ECFieldElement beta;
- {
- ECPoint G = x9.getG().normalize();
- ECPoint mapG = G.multiply(lambda).normalize();
- if (!G.getYCoord().equals(mapG.getYCoord()))
- {
- throw new IllegalStateException("Derivation of GLV Type B parameters failed unexpectedly");
- }
-
- BigInteger q = x9.getCurve().getField().getCharacteristic();
- BigInteger e = q.divide(ECConstants.THREE);
-
- SecureRandom random = new SecureRandom();
- BigInteger b;
- do
- {
- BigInteger r = BigIntegers.createRandomInRange(ECConstants.TWO, q.subtract(ECConstants.TWO), random);
- b = r.modPow(e, q);
- }
- while (b.equals(ECConstants.ONE));
-
- beta = x9.getCurve().fromBigInteger(ECConstants.TWO.modPow(e, q));
-
- if (!G.getXCoord().multiply(beta).equals(mapG.getXCoord()))
- {
- beta = beta.square();
- if (!G.getXCoord().multiply(beta).equals(mapG.getXCoord()))
- {
- throw new IllegalStateException("Derivation of GLV Type B parameters failed unexpectedly");
- }
- }
- }
-
- /*
- * These parameters are used to avoid division when decomposing the scalar in a GLV point multiplication
- */
- BigInteger d = (v1[0].multiply(v2[1])).subtract(v1[1].multiply(v2[0]));
-
- int bits = n.bitLength() + 16 - (n.bitLength() & 7);
- BigInteger g1 = roundQuotient(v2[1].shiftLeft(bits), d);
- BigInteger g2 = roundQuotient(v1[1].shiftLeft(bits), d).negate();
-
- printProperty("Beta", beta.toBigInteger().toString(radix));
- printProperty("Lambda", lambda.toString(radix));
- printProperty("v1", "{ " + v1[0].toString(radix) + ", " + v1[1].toString(radix) + " }");
- printProperty("v2", "{ " + v2[0].toString(radix) + ", " + v2[1].toString(radix) + " }");
- printProperty("(OPT) g1", g1.toString(radix));
- printProperty("(OPT) g2", g2.toString(radix));
- printProperty("(OPT) bits", Integer.toString(bits));
- }
-
- private static void printProperty(String name, Object value)
- {
- StringBuffer sb = new StringBuffer(" ");
- sb.append(name);
- while (sb.length() < 20)
- {
- sb.append(' ');
- }
- sb.append("= ");
- sb.append(value.toString());
- System.out.println(sb.toString());
- }
-
- private static boolean areRelativelyPrime(BigInteger a, BigInteger b)
- {
- return a.gcd(b).equals(ECConstants.ONE);
- }
-
- private static BigInteger[] calculateRange(BigInteger mid, BigInteger off, BigInteger div)
- {
- BigInteger i1 = mid.subtract(off).divide(div);
- BigInteger i2 = mid.add(off).divide(div);
- return order(i1, i2);
- }
-
- private static BigInteger[] extEuclidBezout(BigInteger[] ab)
- {
- boolean swap = ab[0].compareTo(ab[1]) < 0;
- if (swap)
- {
- swap(ab);
- }
-
- BigInteger r0 = ab[0], r1 = ab[1];
- BigInteger s0 = ECConstants.ONE, s1 = ECConstants.ZERO;
- BigInteger t0 = ECConstants.ZERO, t1 = ECConstants.ONE;
-
- while (r1.compareTo(ECConstants.ONE) > 0)
- {
- BigInteger[] qr = r0.divideAndRemainder(r1);
- BigInteger q = qr[0], r2 = qr[1];
-
- BigInteger s2 = s0.subtract(q.multiply(s1));
- BigInteger t2 = t0.subtract(q.multiply(t1));
-
- r0 = r1;
- r1 = r2;
- s0 = s1;
- s1 = s2;
- t0 = t1;
- t1 = t2;
- }
-
- if (r1.signum() <= 0)
- {
- throw new IllegalStateException();
- }
-
- BigInteger[] st = new BigInteger[]{ s1, t1 };
- if (swap)
- {
- swap(st);
- }
- return st;
- }
-
- private static BigInteger[] extEuclidGLV(BigInteger n, BigInteger lambda)
- {
- BigInteger r0 = n, r1 = lambda;
- // BigInteger s0 = ECConstants.ONE, s1 = ECConstants.ZERO;
- BigInteger t0 = ECConstants.ZERO, t1 = ECConstants.ONE;
-
- for (;;)
- {
- BigInteger[] qr = r0.divideAndRemainder(r1);
- BigInteger q = qr[0], r2 = qr[1];
-
- // BigInteger s2 = s0.subtract(q.multiply(s1));
- BigInteger t2 = t0.subtract(q.multiply(t1));
-
- if (isLessThanSqrt(r1, n))
- {
- return new BigInteger[]{ r0, t0, r1, t1, r2, t2 };
- }
-
- r0 = r1;
- r1 = r2;
- // s0 = s1;
- // s1 = s2;
- t0 = t1;
- t1 = t2;
- }
- }
-
- private static BigInteger[] chooseShortest(BigInteger[] u, BigInteger[] v)
- {
- return isShorter(u, v) ? u : v;
- }
-
- private static BigInteger[] intersect(BigInteger[] ab, BigInteger[] cd)
- {
- BigInteger min = ab[0].max(cd[0]);
- BigInteger max = ab[1].min(cd[1]);
- if (min.compareTo(max) > 0)
- {
- return null;
- }
- return new BigInteger[]{ min, max };
- }
-
- private static boolean isLessThanSqrt(BigInteger a, BigInteger b)
- {
- a = a.abs();
- b = b.abs();
- int target = b.bitLength(), maxBits = a.bitLength() * 2, minBits = maxBits - 1;
- return minBits <= target && (maxBits < target || a.multiply(a).compareTo(b) < 0);
- }
-
- private static boolean isShorter(BigInteger[] u, BigInteger[] v)
- {
- BigInteger u1 = u[0].abs(), u2 = u[1].abs(), v1 = v[0].abs(), v2 = v[1].abs();
-
- // TODO Check whether "shorter" just means by rectangle norm:
- // return u1.max(u2).compareTo(v1.max(v2)) < 0;
-
- boolean c1 = u1.compareTo(v1) < 0, c2 = u2.compareTo(v2) < 0;
- if (c1 == c2)
- {
- return c1;
- }
-
- BigInteger du = u1.multiply(u1).add(u2.multiply(u2));
- BigInteger dv = v1.multiply(v1).add(v2.multiply(v2));
-
- return du.compareTo(dv) < 0;
- }
-
- private static boolean isVectorBoundedBySqrt(BigInteger[] v, BigInteger n)
- {
- BigInteger max = v[0].abs().max(v[1].abs());
- return isLessThanSqrt(max, n);
- }
-
- private static BigInteger[] order(BigInteger a, BigInteger b)
- {
- if (a.compareTo(b) <= 0)
- {
- return new BigInteger[]{ a, b };
- }
- return new BigInteger[]{ b, a };
- }
-
- private static BigInteger roundQuotient(BigInteger x, BigInteger y)
- {
- boolean negative = (x.signum() != y.signum());
- x = x.abs();
- y = y.abs();
- BigInteger result = x.add(y.shiftRight(1)).divide(y);
- return negative ? result.negate() : result;
- }
-
- private static BigInteger solveQuadraticEquation(BigInteger n, BigInteger r, BigInteger s)
- {
- BigInteger det = r.multiply(r).subtract(s.shiftLeft(2)).mod(n);
-
- BigInteger root = new ECFieldElement.Fp(n, det).sqrt().toBigInteger();
- if (!root.testBit(0))
- {
- root = n.subtract(root);
- }
-
- return root.shiftRight(1); // NOTE: implicit -1 of the low-bit
- }
-
- private static BigInteger isqrt(BigInteger x)
- {
- BigInteger g0 = x.shiftRight(x.bitLength() / 2);
- for (;;)
- {
- BigInteger g1 = g0.add(x.divide(g0)).shiftRight(1);
- if (g1.equals(g0))
- {
- return g1;
- }
- g0 = g1;
- }
- }
-
- private static void swap(BigInteger[] ab)
- {
- BigInteger tmp = ab[0];
- ab[0] = ab[1];
- ab[1] = tmp;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/field/ExtensionField.java b/core/src/main/java/org/bouncycastle/math/field/ExtensionField.java
deleted file mode 100644
index dfefba7e..00000000
--- a/core/src/main/java/org/bouncycastle/math/field/ExtensionField.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.bouncycastle.math.field;
-
-public interface ExtensionField extends FiniteField
-{
- FiniteField getSubfield();
-
- int getDegree();
-}
diff --git a/core/src/main/java/org/bouncycastle/math/field/FiniteField.java b/core/src/main/java/org/bouncycastle/math/field/FiniteField.java
deleted file mode 100644
index 0a5baa09..00000000
--- a/core/src/main/java/org/bouncycastle/math/field/FiniteField.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.bouncycastle.math.field;
-
-import java.math.BigInteger;
-
-public interface FiniteField
-{
- BigInteger getCharacteristic();
-
- int getDimension();
-}
diff --git a/core/src/main/java/org/bouncycastle/math/field/FiniteFields.java b/core/src/main/java/org/bouncycastle/math/field/FiniteFields.java
deleted file mode 100644
index 7197ffd0..00000000
--- a/core/src/main/java/org/bouncycastle/math/field/FiniteFields.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.bouncycastle.math.field;
-
-import java.math.BigInteger;
-
-public abstract class FiniteFields
-{
- static final FiniteField GF_2 = new PrimeField(BigInteger.valueOf(2));
- static final FiniteField GF_3 = new PrimeField(BigInteger.valueOf(3));
-
- public static PolynomialExtensionField getBinaryExtensionField(int[] exponents)
- {
- if (exponents[0] != 0)
- {
- throw new IllegalArgumentException("Irreducible polynomials in GF(2) must have constant term");
- }
- for (int i = 1; i < exponents.length; ++i)
- {
- if (exponents[i] <= exponents[i - 1])
- {
- throw new IllegalArgumentException("Polynomial exponents must be montonically increasing");
- }
- }
-
- return new GenericPolynomialExtensionField(GF_2, new GF2Polynomial(exponents));
- }
-
-// public static PolynomialExtensionField getTernaryExtensionField(Term[] terms)
-// {
-// return new GenericPolynomialExtensionField(GF_3, new GF3Polynomial(terms));
-// }
-
- public static FiniteField getPrimeField(BigInteger characteristic)
- {
- int bitLength = characteristic.bitLength();
- if (characteristic.signum() <= 0 || bitLength < 2)
- {
- throw new IllegalArgumentException("'characteristic' must be >= 2");
- }
-
- if (bitLength < 3)
- {
- switch (characteristic.intValue())
- {
- case 2:
- return GF_2;
- case 3:
- return GF_3;
- }
- }
-
- return new PrimeField(characteristic);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/field/GF2Polynomial.java b/core/src/main/java/org/bouncycastle/math/field/GF2Polynomial.java
deleted file mode 100644
index 73be7685..00000000
--- a/core/src/main/java/org/bouncycastle/math/field/GF2Polynomial.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.bouncycastle.math.field;
-
-import org.bouncycastle.util.Arrays;
-
-class GF2Polynomial implements Polynomial
-{
- protected final int[] exponents;
-
- GF2Polynomial(int[] exponents)
- {
- this.exponents = Arrays.clone(exponents);
- }
-
- public int getDegree()
- {
- return exponents[exponents.length - 1];
- }
-
- public int[] getExponentsPresent()
- {
- return Arrays.clone(exponents);
- }
-
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (!(obj instanceof GF2Polynomial))
- {
- return false;
- }
- GF2Polynomial other = (GF2Polynomial)obj;
- return Arrays.areEqual(exponents, other.exponents);
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(exponents);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/field/GenericPolynomialExtensionField.java b/core/src/main/java/org/bouncycastle/math/field/GenericPolynomialExtensionField.java
deleted file mode 100644
index 0b93a71a..00000000
--- a/core/src/main/java/org/bouncycastle/math/field/GenericPolynomialExtensionField.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package org.bouncycastle.math.field;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.util.Integers;
-
-class GenericPolynomialExtensionField implements PolynomialExtensionField
-{
- protected final FiniteField subfield;
- protected final Polynomial minimalPolynomial;
-
- GenericPolynomialExtensionField(FiniteField subfield, Polynomial polynomial)
- {
- this.subfield = subfield;
- this.minimalPolynomial = polynomial;
- }
-
- public BigInteger getCharacteristic()
- {
- return subfield.getCharacteristic();
- }
-
- public int getDimension()
- {
- return subfield.getDimension() * minimalPolynomial.getDegree();
- }
-
- public FiniteField getSubfield()
- {
- return subfield;
- }
-
- public int getDegree()
- {
- return minimalPolynomial.getDegree();
- }
-
- public Polynomial getMinimalPolynomial()
- {
- return minimalPolynomial;
- }
-
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (!(obj instanceof GenericPolynomialExtensionField))
- {
- return false;
- }
- GenericPolynomialExtensionField other = (GenericPolynomialExtensionField)obj;
- return subfield.equals(other.subfield) && minimalPolynomial.equals(other.minimalPolynomial);
- }
-
- public int hashCode()
- {
- return subfield.hashCode()
- ^ Integers.rotateLeft(minimalPolynomial.hashCode(), 16);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/field/Polynomial.java b/core/src/main/java/org/bouncycastle/math/field/Polynomial.java
deleted file mode 100644
index e5ccd61c..00000000
--- a/core/src/main/java/org/bouncycastle/math/field/Polynomial.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.bouncycastle.math.field;
-
-public interface Polynomial
-{
- int getDegree();
-
-// BigInteger[] getCoefficients();
-
- int[] getExponentsPresent();
-
-// Term[] getNonZeroTerms();
-}
diff --git a/core/src/main/java/org/bouncycastle/math/field/PolynomialExtensionField.java b/core/src/main/java/org/bouncycastle/math/field/PolynomialExtensionField.java
deleted file mode 100644
index aedcbee3..00000000
--- a/core/src/main/java/org/bouncycastle/math/field/PolynomialExtensionField.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.bouncycastle.math.field;
-
-public interface PolynomialExtensionField extends ExtensionField
-{
- Polynomial getMinimalPolynomial();
-}
diff --git a/core/src/main/java/org/bouncycastle/math/field/PrimeField.java b/core/src/main/java/org/bouncycastle/math/field/PrimeField.java
deleted file mode 100644
index fd1e2532..00000000
--- a/core/src/main/java/org/bouncycastle/math/field/PrimeField.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.bouncycastle.math.field;
-
-import java.math.BigInteger;
-
-class PrimeField implements FiniteField
-{
- protected final BigInteger characteristic;
-
- PrimeField(BigInteger characteristic)
- {
- this.characteristic = characteristic;
- }
-
- public BigInteger getCharacteristic()
- {
- return characteristic;
- }
-
- public int getDimension()
- {
- return 1;
- }
-
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (!(obj instanceof PrimeField))
- {
- return false;
- }
- PrimeField other = (PrimeField)obj;
- return characteristic.equals(other.characteristic);
- }
-
- public int hashCode()
- {
- return characteristic.hashCode();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/raw/Mod.java b/core/src/main/java/org/bouncycastle/math/raw/Mod.java
deleted file mode 100644
index 47e6d8c6..00000000
--- a/core/src/main/java/org/bouncycastle/math/raw/Mod.java
+++ /dev/null
@@ -1,199 +0,0 @@
-package org.bouncycastle.math.raw;
-
-import java.util.Random;
-
-import org.bouncycastle.util.Pack;
-
-public abstract class Mod
-{
- public static int inverse32(int d)
- {
-// int x = d + (((d + 1) & 4) << 1); // d.x == 1 mod 2**4
- int x = d; // d.x == 1 mod 2**3
- x *= 2 - d * x; // d.x == 1 mod 2**6
- x *= 2 - d * x; // d.x == 1 mod 2**12
- x *= 2 - d * x; // d.x == 1 mod 2**24
- x *= 2 - d * x; // d.x == 1 mod 2**48
-// assert d * x == 1;
- return x;
- }
-
- public static void invert(int[] p, int[] x, int[] z)
- {
- int len = p.length;
- if (Nat.isZero(len, x))
- {
- throw new IllegalArgumentException("'x' cannot be 0");
- }
- if (Nat.isOne(len, x))
- {
- System.arraycopy(x, 0, z, 0, len);
- return;
- }
-
- int[] u = Nat.copy(len, x);
- int[] a = Nat.create(len);
- a[0] = 1;
- int ac = 0;
-
- if ((u[0] & 1) == 0)
- {
- ac = inversionStep(p, u, len, a, ac);
- }
- if (Nat.isOne(len, u))
- {
- inversionResult(p, ac, a, z);
- return;
- }
-
- int[] v = Nat.copy(len, p);
- int[] b = Nat.create(len);
- int bc = 0;
-
- int uvLen = len;
-
- for (;;)
- {
- while (u[uvLen - 1] == 0 && v[uvLen - 1] == 0)
- {
- --uvLen;
- }
-
- if (Nat.gte(uvLen, u, v))
- {
- Nat.subFrom(uvLen, v, u);
-// assert (u[0] & 1) == 0;
- ac += Nat.subFrom(len, b, a) - bc;
- ac = inversionStep(p, u, uvLen, a, ac);
- if (Nat.isOne(uvLen, u))
- {
- inversionResult(p, ac, a, z);
- return;
- }
- }
- else
- {
- Nat.subFrom(uvLen, u, v);
-// assert (v[0] & 1) == 0;
- bc += Nat.subFrom(len, a, b) - ac;
- bc = inversionStep(p, v, uvLen, b, bc);
- if (Nat.isOne(uvLen, v))
- {
- inversionResult(p, bc, b, z);
- return;
- }
- }
- }
- }
-
- public static int[] random(int[] p)
- {
- int len = p.length;
- Random rand = new Random();
- int[] s = Nat.create(len);
-
- int m = p[len - 1];
- m |= m >>> 1;
- m |= m >>> 2;
- m |= m >>> 4;
- m |= m >>> 8;
- m |= m >>> 16;
-
- do
- {
- for (int i = 0; i != len; i++)
- {
- s[i] = rand.nextInt();
- }
- s[len - 1] &= m;
- }
- while (Nat.gte(len, s, p));
-
- return s;
- }
-
- public static void add(int[] p, int[] x, int[] y, int[] z)
- {
- int len = p.length;
- int c = Nat.add(len, x, y, z);
- if (c != 0)
- {
- Nat.subFrom(len, p, z);
- }
- }
-
- public static void subtract(int[] p, int[] x, int[] y, int[] z)
- {
- int len = p.length;
- int c = Nat.sub(len, x, y, z);
- if (c != 0)
- {
- Nat.addTo(len, p, z);
- }
- }
-
- private static void inversionResult(int[] p, int ac, int[] a, int[] z)
- {
- if (ac < 0)
- {
- Nat.add(p.length, a, p, z);
- }
- else
- {
- System.arraycopy(a, 0, z, 0, p.length);
- }
- }
-
- private static int inversionStep(int[] p, int[] u, int uLen, int[] x, int xc)
- {
- int len = p.length;
- int count = 0;
- while (u[0] == 0)
- {
- Nat.shiftDownWord(uLen, u, 0);
- count += 32;
- }
-
- {
- int zeroes = getTrailingZeroes(u[0]);
- if (zeroes > 0)
- {
- Nat.shiftDownBits(uLen, u, zeroes, 0);
- count += zeroes;
- }
- }
-
- for (int i = 0; i < count; ++i)
- {
- if ((x[0] & 1) != 0)
- {
- if (xc < 0)
- {
- xc += Nat.addTo(len, p, x);
- }
- else
- {
- xc += Nat.subFrom(len, p, x);
- }
- }
-
-// assert xc == 0 || xc == 1;
- Nat.shiftDownBit(len, x, xc);
- }
-
- return xc;
- }
-
- private static int getTrailingZeroes(int x)
- {
-// assert x != 0;
-
- int count = 0;
- while ((x & 1) == 0)
- {
- x >>>= 1;
- ++count;
- }
- return count;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/raw/Mont256.java b/core/src/main/java/org/bouncycastle/math/raw/Mont256.java
deleted file mode 100644
index 750221f1..00000000
--- a/core/src/main/java/org/bouncycastle/math/raw/Mont256.java
+++ /dev/null
@@ -1,152 +0,0 @@
-package org.bouncycastle.math.raw;
-
-public abstract class Mont256
-{
- private static final long M = 0xFFFFFFFFL;
-
- public static int inverse32(int x)
- {
- // assert (x & 1) == 1;
- int z = x; // x.z == 1 mod 2**3
- z *= 2 - x * z; // x.z == 1 mod 2**6
- z *= 2 - x * z; // x.z == 1 mod 2**12
- z *= 2 - x * z; // x.z == 1 mod 2**24
- z *= 2 - x * z; // x.z == 1 mod 2**48
- // assert x * z == 1;
- return z;
- }
-
- public static void multAdd(int[] x, int[] y, int[] z, int[] m, int mInv32)
- {
- int z_8 = 0;
- long y_0 = y[0] & M;
-
- for (int i = 0; i < 8; ++i)
- {
- long z_0 = z[0] & M;
- long x_i = x[i] & M;
-
- long prod1 = x_i * y_0;
- long carry = (prod1 & M) + z_0;
-
- long t = ((int)carry * mInv32) & M;
-
- long prod2 = t * (m[0] & M);
- carry += (prod2 & M);
- // assert (int)carry == 0;
- carry = (carry >>> 32) + (prod1 >>> 32) + (prod2 >>> 32);
-
- for (int j = 1; j < 8; ++j)
- {
- prod1 = x_i * (y[j] & M);
- prod2 = t * (m[j] & M);
-
- carry += (prod1 & M) + (prod2 & M) + (z[j] & M);
- z[j - 1] = (int)carry;
- carry = (carry >>> 32) + (prod1 >>> 32) + (prod2 >>> 32);
- }
-
- carry += (z_8 & M);
- z[7] = (int)carry;
- z_8 = (int)(carry >>> 32);
- }
-
- if (z_8 != 0 || Nat256.gte(z, m))
- {
- Nat256.sub(z, m, z);
- }
- }
-
- public static void multAddXF(int[] x, int[] y, int[] z, int[] m)
- {
- // assert m[0] == M;
-
- int z_8 = 0;
- long y_0 = y[0] & M;
-
- for (int i = 0; i < 8; ++i)
- {
- long x_i = x[i] & M;
-
- long carry = x_i * y_0 + (z[0] & M);
- long t = carry & M;
- carry = (carry >>> 32) + t;
-
- for (int j = 1; j < 8; ++j)
- {
- long prod1 = x_i * (y[j] & M);
- long prod2 = t * (m[j] & M);
-
- carry += (prod1 & M) + (prod2 & M) + (z[j] & M);
- z[j - 1] = (int)carry;
- carry = (carry >>> 32) + (prod1 >>> 32) + (prod2 >>> 32);
- }
-
- carry += (z_8 & M);
- z[7] = (int)carry;
- z_8 = (int)(carry >>> 32);
- }
-
- if (z_8 != 0 || Nat256.gte(z, m))
- {
- Nat256.sub(z, m, z);
- }
- }
-
- public static void reduce(int[] z, int[] m, int mInv32)
- {
- for (int i = 0; i < 8; ++i)
- {
- int z_0 = z[0];
-
- long t = (z_0 * mInv32) & M;
-
- long carry = t * (m[0] & M) + (z_0 & M);
- // assert (int)carry == 0;
- carry >>>= 32;
-
- for (int j = 1; j < 8; ++j)
- {
- carry += t * (m[j] & M) + (z[j] & M);
- z[j - 1] = (int)carry;
- carry >>>= 32;
- }
-
- z[7] = (int)carry;
- // assert carry >>> 32 == 0;
- }
-
- if (Nat256.gte(z, m))
- {
- Nat256.sub(z, m, z);
- }
- }
-
- public static void reduceXF(int[] z, int[] m)
- {
- // assert m[0] == M;
-
- for (int i = 0; i < 8; ++i)
- {
- int z_0 = z[0];
-
- long t = z_0 & M;
- long carry = t;
-
- for (int j = 1; j < 8; ++j)
- {
- carry += t * (m[j] & M) + (z[j] & M);
- z[j - 1] = (int)carry;
- carry >>>= 32;
- }
-
- z[7] = (int)carry;
- // assert carry >>> 32 == 0;
- }
-
- if (Nat256.gte(z, m))
- {
- Nat256.sub(z, m, z);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/raw/Nat.java b/core/src/main/java/org/bouncycastle/math/raw/Nat.java
deleted file mode 100644
index 75e15434..00000000
--- a/core/src/main/java/org/bouncycastle/math/raw/Nat.java
+++ /dev/null
@@ -1,1038 +0,0 @@
-package org.bouncycastle.math.raw;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.util.Pack;
-
-public abstract class Nat
-{
- private static final long M = 0xFFFFFFFFL;
-
- public static int add(int len, int[] x, int[] y, int[] z)
- {
- long c = 0;
- for (int i = 0; i < len; ++i)
- {
- c += (x[i] & M) + (y[i] & M);
- z[i] = (int)c;
- c >>>= 32;
- }
- return (int)c;
- }
-
- public static int add33At(int len, int x, int[] z, int zPos)
- {
- // assert zPos <= (len - 2);
- long c = (z[zPos + 0] & M) + (x & M);
- z[zPos + 0] = (int)c;
- c >>>= 32;
- c += (z[zPos + 1] & M) + 1L;
- z[zPos + 1] = (int)c;
- c >>>= 32;
- return c == 0 ? 0 : incAt(len, z, zPos + 2);
- }
-
- public static int add33At(int len, int x, int[] z, int zOff, int zPos)
- {
- // assert zPos <= (len - 2);
- long c = (z[zOff + zPos] & M) + (x & M);
- z[zOff + zPos] = (int)c;
- c >>>= 32;
- c += (z[zOff + zPos + 1] & M) + 1L;
- z[zOff + zPos + 1] = (int)c;
- c >>>= 32;
- return c == 0 ? 0 : incAt(len, z, zOff, zPos + 2);
- }
-
- public static int add33To(int len, int x, int[] z)
- {
- long c = (z[0] & M) + (x & M);
- z[0] = (int)c;
- c >>>= 32;
- c += (z[1] & M) + 1L;
- z[1] = (int)c;
- c >>>= 32;
- return c == 0 ? 0 : incAt(len, z, 2);
- }
-
- public static int add33To(int len, int x, int[] z, int zOff)
- {
- long c = (z[zOff + 0] & M) + (x & M);
- z[zOff + 0] = (int)c;
- c >>>= 32;
- c += (z[zOff + 1] & M) + 1L;
- z[zOff + 1] = (int)c;
- c >>>= 32;
- return c == 0 ? 0 : incAt(len, z, zOff, 2);
- }
-
- public static int addBothTo(int len, int[] x, int[] y, int[] z)
- {
- long c = 0;
- for (int i = 0; i < len; ++i)
- {
- c += (x[i] & M) + (y[i] & M) + (z[i] & M);
- z[i] = (int)c;
- c >>>= 32;
- }
- return (int)c;
- }
-
- public static int addBothTo(int len, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
- {
- long c = 0;
- for (int i = 0; i < len; ++i)
- {
- c += (x[xOff + i] & M) + (y[yOff + i] & M) + (z[zOff + i] & M);
- z[zOff + i] = (int)c;
- c >>>= 32;
- }
- return (int)c;
- }
-
- public static int addDWordAt(int len, long x, int[] z, int zPos)
- {
- // assert zPos <= (len - 2);
- long c = (z[zPos + 0] & M) + (x & M);
- z[zPos + 0] = (int)c;
- c >>>= 32;
- c += (z[zPos + 1] & M) + (x >>> 32);
- z[zPos + 1] = (int)c;
- c >>>= 32;
- return c == 0 ? 0 : incAt(len, z, zPos + 2);
- }
-
- public static int addDWordAt(int len, long x, int[] z, int zOff, int zPos)
- {
- // assert zPos <= (len - 2);
- long c = (z[zOff + zPos] & M) + (x & M);
- z[zOff + zPos] = (int)c;
- c >>>= 32;
- c += (z[zOff + zPos + 1] & M) + (x >>> 32);
- z[zOff + zPos + 1] = (int)c;
- c >>>= 32;
- return c == 0 ? 0 : incAt(len, z, zOff, zPos + 2);
- }
-
- public static int addDWordTo(int len, long x, int[] z)
- {
- long c = (z[0] & M) + (x & M);
- z[0] = (int)c;
- c >>>= 32;
- c += (z[1] & M) + (x >>> 32);
- z[1] = (int)c;
- c >>>= 32;
- return c == 0 ? 0 : incAt(len, z, 2);
- }
-
- public static int addDWordTo(int len, long x, int[] z, int zOff)
- {
- long c = (z[zOff + 0] & M) + (x & M);
- z[zOff + 0] = (int)c;
- c >>>= 32;
- c += (z[zOff + 1] & M) + (x >>> 32);
- z[zOff + 1] = (int)c;
- c >>>= 32;
- return c == 0 ? 0 : incAt(len, z, zOff, 2);
- }
-
- public static int addTo(int len, int[] x, int[] z)
- {
- long c = 0;
- for (int i = 0; i < len; ++i)
- {
- c += (x[i] & M) + (z[i] & M);
- z[i] = (int)c;
- c >>>= 32;
- }
- return (int)c;
- }
-
- public static int addTo(int len, int[] x, int xOff, int[] z, int zOff)
- {
- long c = 0;
- for (int i = 0; i < len; ++i)
- {
- c += (x[xOff + i] & M) + (z[zOff + i] & M);
- z[zOff + i] = (int)c;
- c >>>= 32;
- }
- return (int)c;
- }
-
- public static int addWordAt(int len, int x, int[] z, int zPos)
- {
- // assert zPos <= (len - 1);
- long c = (x & M) + (z[zPos] & M);
- z[zPos] = (int)c;
- c >>>= 32;
- return c == 0 ? 0 : incAt(len, z, zPos + 1);
- }
-
- public static int addWordAt(int len, int x, int[] z, int zOff, int zPos)
- {
- // assert zPos <= (len - 1);
- long c = (x & M) + (z[zOff + zPos] & M);
- z[zOff + zPos] = (int)c;
- c >>>= 32;
- return c == 0 ? 0 : incAt(len, z, zOff, zPos + 1);
- }
-
- public static int addWordTo(int len, int x, int[] z)
- {
- long c = (x & M) + (z[0] & M);
- z[0] = (int)c;
- c >>>= 32;
- return c == 0 ? 0 : incAt(len, z, 1);
- }
-
- public static int addWordTo(int len, int x, int[] z, int zOff)
- {
- long c = (x & M) + (z[zOff] & M);
- z[zOff] = (int)c;
- c >>>= 32;
- return c == 0 ? 0 : incAt(len, z, zOff, 1);
- }
-
- public static int[] copy(int len, int[] x)
- {
- int[] z = new int[len];
- System.arraycopy(x, 0, z, 0, len);
- return z;
- }
-
- public static void copy(int len, int[] x, int[] z)
- {
- System.arraycopy(x, 0, z, 0, len);
- }
-
- public static int[] create(int len)
- {
- return new int[len];
- }
-
- public static int dec(int len, int[] z)
- {
- for (int i = 0; i < len; ++i)
- {
- if (--z[i] != -1)
- {
- return 0;
- }
- }
- return -1;
- }
-
- public static int dec(int len, int[] x, int[] z)
- {
- int i = 0;
- while (i < len)
- {
- int c = x[i] - 1;
- z[i] = c;
- ++i;
- if (c != -1)
- {
- while (i < len)
- {
- z[i] = x[i];
- ++i;
- }
- return 0;
- }
- }
- return -1;
- }
-
- public static int decAt(int len, int[] z, int zPos)
- {
- // assert zPos <= len;
- for (int i = zPos; i < len; ++i)
- {
- if (--z[i] != -1)
- {
- return 0;
- }
- }
- return -1;
- }
-
- public static int decAt(int len, int[] z, int zOff, int zPos)
- {
- // assert zPos <= len;
- for (int i = zPos; i < len; ++i)
- {
- if (--z[zOff + i] != -1)
- {
- return 0;
- }
- }
- return -1;
- }
-
- public static boolean eq(int len, int[] x, int[] y)
- {
- for (int i = len - 1; i >= 0; --i)
- {
- if (x[i] != y[i])
- {
- return false;
- }
- }
- return true;
- }
-
- public static int[] fromBigInteger(int bits, BigInteger x)
- {
- if (x.signum() < 0 || x.bitLength() > bits)
- {
- throw new IllegalArgumentException();
- }
-
- int len = (bits + 31) >> 5;
- int[] z = create(len);
- int i = 0;
- while (x.signum() != 0)
- {
- z[i++] = x.intValue();
- x = x.shiftRight(32);
- }
- return z;
- }
-
- public static int getBit(int[] x, int bit)
- {
- if (bit == 0)
- {
- return x[0] & 1;
- }
- int w = bit >> 5;
- if (w < 0 || w >= x.length)
- {
- return 0;
- }
- int b = bit & 31;
- return (x[w] >>> b) & 1;
- }
-
- public static boolean gte(int len, int[] x, int[] y)
- {
- for (int i = len - 1; i >= 0; --i)
- {
- int x_i = x[i] ^ Integer.MIN_VALUE;
- int y_i = y[i] ^ Integer.MIN_VALUE;
- if (x_i < y_i)
- return false;
- if (x_i > y_i)
- return true;
- }
- return true;
- }
-
- public static int inc(int len, int[] z)
- {
- for (int i = 0; i < len; ++i)
- {
- if (++z[i] != 0)
- {
- return 0;
- }
- }
- return 1;
- }
-
- public static int inc(int len, int[] x, int[] z)
- {
- int i = 0;
- while (i < len)
- {
- int c = x[i] + 1;
- z[i] = c;
- ++i;
- if (c != 0)
- {
- while (i < len)
- {
- z[i] = x[i];
- ++i;
- }
- return 0;
- }
- }
- return 1;
- }
-
- public static int incAt(int len, int[] z, int zPos)
- {
- // assert zPos <= len;
- for (int i = zPos; i < len; ++i)
- {
- if (++z[i] != 0)
- {
- return 0;
- }
- }
- return 1;
- }
-
- public static int incAt(int len, int[] z, int zOff, int zPos)
- {
- // assert zPos <= len;
- for (int i = zPos; i < len; ++i)
- {
- if (++z[zOff + i] != 0)
- {
- return 0;
- }
- }
- return 1;
- }
-
- public static boolean isOne(int len, int[] x)
- {
- if (x[0] != 1)
- {
- return false;
- }
- for (int i = 1; i < len; ++i)
- {
- if (x[i] != 0)
- {
- return false;
- }
- }
- return true;
- }
-
- public static boolean isZero(int len, int[] x)
- {
- for (int i = 0; i < len; ++i)
- {
- if (x[i] != 0)
- {
- return false;
- }
- }
- return true;
- }
-
- public static void mul(int len, int[] x, int[] y, int[] zz)
- {
- zz[len] = mulWord(len, x[0], y, zz);
-
- for (int i = 1; i < len; ++i)
- {
- zz[i + len] = mulWordAddTo(len, x[i], y, 0, zz, i);
- }
- }
-
- public static void mul(int len, int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
- {
- zz[zzOff + len] = mulWord(len, x[xOff], y, yOff, zz, zzOff);
-
- for (int i = 1; i < len; ++i)
- {
- zz[zzOff + i + len] = mulWordAddTo(len, x[xOff + i], y, yOff, zz, zzOff + i);
- }
- }
-
- public static int mulAddTo(int len, int[] x, int[] y, int[] zz)
- {
- long zc = 0;
- for (int i = 0; i < len; ++i)
- {
- long c = mulWordAddTo(len, x[i], y, 0, zz, i) & M;
- c += zc + (zz[i + len] & M);
- zz[i + len] = (int)c;
- zc = c >>> 32;
- }
- return (int)zc;
- }
-
- public static int mulAddTo(int len, int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
- {
- long zc = 0;
- for (int i = 0; i < len; ++i)
- {
- long c = mulWordAddTo(len, x[xOff + i], y, yOff, zz, zzOff) & M;
- c += zc + (zz[zzOff + len] & M);
- zz[zzOff + len] = (int)c;
- zc = c >>> 32;
- ++zzOff;
- }
- return (int)zc;
- }
-
- public static int mul31BothAdd(int len, int a, int[] x, int b, int[] y, int[] z, int zOff)
- {
- long c = 0, aVal = a & M, bVal = b & M;
- int i = 0;
- do
- {
- c += aVal * (x[i] & M) + bVal * (y[i] & M) + (z[zOff + i] & M);
- z[zOff + i] = (int)c;
- c >>>= 32;
- }
- while (++i < len);
- return (int)c;
- }
-
- public static int mulWord(int len, int x, int[] y, int[] z)
- {
- long c = 0, xVal = x & M;
- int i = 0;
- do
- {
- c += xVal * (y[i] & M);
- z[i] = (int)c;
- c >>>= 32;
- }
- while (++i < len);
- return (int)c;
- }
-
- public static int mulWord(int len, int x, int[] y, int yOff, int[] z, int zOff)
- {
- long c = 0, xVal = x & M;
- int i = 0;
- do
- {
- c += xVal * (y[yOff + i] & M);
- z[zOff + i] = (int)c;
- c >>>= 32;
- }
- while (++i < len);
- return (int)c;
- }
-
- public static int mulWordAddTo(int len, int x, int[] y, int yOff, int[] z, int zOff)
- {
- long c = 0, xVal = x & M;
- int i = 0;
- do
- {
- c += xVal * (y[yOff + i] & M) + (z[zOff + i] & M);
- z[zOff + i] = (int)c;
- c >>>= 32;
- }
- while (++i < len);
- return (int)c;
- }
-
- public static int mulWordDwordAddAt(int len, int x, long y, int[] z, int zPos)
- {
- // assert zPos <= (len - 3);
- long c = 0, xVal = x & M;
- c += xVal * (y & M) + (z[zPos + 0] & M);
- z[zPos + 0] = (int)c;
- c >>>= 32;
- c += xVal * (y >>> 32) + (z[zPos + 1] & M);
- z[zPos + 1] = (int)c;
- c >>>= 32;
- c += (z[zPos + 2] & M);
- z[zPos + 2] = (int)c;
- c >>>= 32;
- return c == 0 ? 0 : incAt(len, z, zPos + 3);
- }
-
- public static int shiftDownBit(int len, int[] z, int c)
- {
- int i = len;
- while (--i >= 0)
- {
- int next = z[i];
- z[i] = (next >>> 1) | (c << 31);
- c = next;
- }
- return c << 31;
- }
-
- public static int shiftDownBit(int len, int[] z, int zOff, int c)
- {
- int i = len;
- while (--i >= 0)
- {
- int next = z[zOff + i];
- z[zOff + i] = (next >>> 1) | (c << 31);
- c = next;
- }
- return c << 31;
- }
-
- public static int shiftDownBit(int len, int[] x, int c, int[] z)
- {
- int i = len;
- while (--i >= 0)
- {
- int next = x[i];
- z[i] = (next >>> 1) | (c << 31);
- c = next;
- }
- return c << 31;
- }
-
- public static int shiftDownBit(int len, int[] x, int xOff, int c, int[] z, int zOff)
- {
- int i = len;
- while (--i >= 0)
- {
- int next = x[xOff + i];
- z[zOff + i] = (next >>> 1) | (c << 31);
- c = next;
- }
- return c << 31;
- }
-
- public static int shiftDownBits(int len, int[] z, int bits, int c)
- {
-// assert bits > 0 && bits < 32;
- int i = len;
- while (--i >= 0)
- {
- int next = z[i];
- z[i] = (next >>> bits) | (c << -bits);
- c = next;
- }
- return c << -bits;
- }
-
- public static int shiftDownBits(int len, int[] z, int zOff, int bits, int c)
- {
-// assert bits > 0 && bits < 32;
- int i = len;
- while (--i >= 0)
- {
- int next = z[zOff + i];
- z[zOff + i] = (next >>> bits) | (c << -bits);
- c = next;
- }
- return c << -bits;
- }
-
- public static int shiftDownBits(int len, int[] x, int bits, int c, int[] z)
- {
-// assert bits > 0 && bits < 32;
- int i = len;
- while (--i >= 0)
- {
- int next = x[i];
- z[i] = (next >>> bits) | (c << -bits);
- c = next;
- }
- return c << -bits;
- }
-
- public static int shiftDownBits(int len, int[] x, int xOff, int bits, int c, int[] z, int zOff)
- {
-// assert bits > 0 && bits < 32;
- int i = len;
- while (--i >= 0)
- {
- int next = x[xOff + i];
- z[zOff + i] = (next >>> bits) | (c << -bits);
- c = next;
- }
- return c << -bits;
- }
-
- public static int shiftDownWord(int len, int[] z, int c)
- {
- int i = len;
- while (--i >= 0)
- {
- int next = z[i];
- z[i] = c;
- c = next;
- }
- return c;
- }
-
- public static int shiftUpBit(int len, int[] z, int c)
- {
- for (int i = 0; i < len; ++i)
- {
- int next = z[i];
- z[i] = (next << 1) | (c >>> 31);
- c = next;
- }
- return c >>> 31;
- }
-
- public static int shiftUpBit(int len, int[] z, int zOff, int c)
- {
- for (int i = 0; i < len; ++i)
- {
- int next = z[zOff + i];
- z[zOff + i] = (next << 1) | (c >>> 31);
- c = next;
- }
- return c >>> 31;
- }
-
- public static int shiftUpBit(int len, int[] x, int c, int[] z)
- {
- for (int i = 0; i < len; ++i)
- {
- int next = x[i];
- z[i] = (next << 1) | (c >>> 31);
- c = next;
- }
- return c >>> 31;
- }
-
- public static int shiftUpBit(int len, int[] x, int xOff, int c, int[] z, int zOff)
- {
- for (int i = 0; i < len; ++i)
- {
- int next = x[xOff + i];
- z[zOff + i] = (next << 1) | (c >>> 31);
- c = next;
- }
- return c >>> 31;
- }
-
- public static int shiftUpBits(int len, int[] z, int bits, int c)
- {
-// assert bits > 0 && bits < 32;
- for (int i = 0; i < len; ++i)
- {
- int next = z[i];
- z[i] = (next << bits) | (c >>> -bits);
- c = next;
- }
- return c >>> -bits;
- }
-
- public static int shiftUpBits(int len, int[] z, int zOff, int bits, int c)
- {
-// assert bits > 0 && bits < 32;
- for (int i = 0; i < len; ++i)
- {
- int next = z[zOff + i];
- z[zOff + i] = (next << bits) | (c >>> -bits);
- c = next;
- }
- return c >>> -bits;
- }
-
- public static int shiftUpBits(int len, int[] x, int bits, int c, int[] z)
- {
-// assert bits > 0 && bits < 32;
- for (int i = 0; i < len; ++i)
- {
- int next = x[i];
- z[i] = (next << bits) | (c >>> -bits);
- c = next;
- }
- return c >>> -bits;
- }
-
- public static int shiftUpBits(int len, int[] x, int xOff, int bits, int c, int[] z, int zOff)
- {
-// assert bits > 0 && bits < 32;
- for (int i = 0; i < len; ++i)
- {
- int next = x[xOff + i];
- z[zOff + i] = (next << bits) | (c >>> -bits);
- c = next;
- }
- return c >>> -bits;
- }
-
- public static void square(int len, int[] x, int[] zz)
- {
- int extLen = len << 1;
- int c = 0;
- int j = len, k = extLen;
- do
- {
- long xVal = (x[--j] & M);
- long p = xVal * xVal;
- zz[--k] = (c << 31) | (int)(p >>> 33);
- zz[--k] = (int)(p >>> 1);
- c = (int)p;
- }
- while (j > 0);
-
- for (int i = 1; i < len; ++i)
- {
- c = squareWordAdd(x, i, zz);
- addWordAt(extLen, c, zz, i << 1);
- }
-
- shiftUpBit(extLen, zz, x[0] << 31);
- }
-
- public static void square(int len, int[] x, int xOff, int[] zz, int zzOff)
- {
- int extLen = len << 1;
- int c = 0;
- int j = len, k = extLen;
- do
- {
- long xVal = (x[xOff + --j] & M);
- long p = xVal * xVal;
- zz[zzOff + --k] = (c << 31) | (int)(p >>> 33);
- zz[zzOff + --k] = (int)(p >>> 1);
- c = (int)p;
- }
- while (j > 0);
-
- for (int i = 1; i < len; ++i)
- {
- c = squareWordAdd(x, xOff, i, zz, zzOff);
- addWordAt(extLen, c, zz, zzOff, i << 1);
- }
-
- shiftUpBit(extLen, zz, zzOff, x[xOff] << 31);
- }
-
- public static int squareWordAdd(int[] x, int xPos, int[] z)
- {
- long c = 0, xVal = x[xPos] & M;
- int i = 0;
- do
- {
- c += xVal * (x[i] & M) + (z[xPos + i] & M);
- z[xPos + i] = (int)c;
- c >>>= 32;
- }
- while (++i < xPos);
- return (int)c;
- }
-
- public static int squareWordAdd(int[] x, int xOff, int xPos, int[] z, int zOff)
- {
- long c = 0, xVal = x[xOff + xPos] & M;
- int i = 0;
- do
- {
- c += xVal * (x[xOff + i] & M) + (z[xPos + zOff] & M);
- z[xPos + zOff] = (int)c;
- c >>>= 32;
- ++zOff;
- }
- while (++i < xPos);
- return (int)c;
- }
-
- public static int sub(int len, int[] x, int[] y, int[] z)
- {
- long c = 0;
- for (int i = 0; i < len; ++i)
- {
- c += (x[i] & M) - (y[i] & M);
- z[i] = (int)c;
- c >>= 32;
- }
- return (int)c;
- }
-
- public static int sub(int len, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
- {
- long c = 0;
- for (int i = 0; i < len; ++i)
- {
- c += (x[xOff + i] & M) - (y[yOff + i] & M);
- z[zOff + i] = (int)c;
- c >>= 32;
- }
- return (int)c;
- }
-
- public static int sub33At(int len, int x, int[] z, int zPos)
- {
- // assert zPos <= (len - 2);
- long c = (z[zPos + 0] & M) - (x & M);
- z[zPos + 0] = (int)c;
- c >>= 32;
- c += (z[zPos + 1] & M) - 1;
- z[zPos + 1] = (int)c;
- c >>= 32;
- return c == 0 ? 0 : decAt(len, z, zPos + 2);
- }
-
- public static int sub33At(int len, int x, int[] z, int zOff, int zPos)
- {
- // assert zPos <= (len - 2);
- long c = (z[zOff + zPos] & M) - (x & M);
- z[zOff + zPos] = (int)c;
- c >>= 32;
- c += (z[zOff + zPos + 1] & M) - 1;
- z[zOff + zPos + 1] = (int)c;
- c >>= 32;
- return c == 0 ? 0 : decAt(len, z, zOff, zPos + 2);
- }
-
- public static int sub33From(int len, int x, int[] z)
- {
- long c = (z[0] & M) - (x & M);
- z[0] = (int)c;
- c >>= 32;
- c += (z[1] & M) - 1;
- z[1] = (int)c;
- c >>= 32;
- return c == 0 ? 0 : decAt(len, z, 2);
- }
-
- public static int sub33From(int len, int x, int[] z, int zOff)
- {
- long c = (z[zOff + 0] & M) - (x & M);
- z[zOff + 0] = (int)c;
- c >>= 32;
- c += (z[zOff + 1] & M) - 1;
- z[zOff + 1] = (int)c;
- c >>= 32;
- return c == 0 ? 0 : decAt(len, z, zOff, 2);
- }
-
- public static int subBothFrom(int len, int[] x, int[] y, int[] z)
- {
- long c = 0;
- for (int i = 0; i < len; ++i)
- {
- c += (z[i] & M) - (x[i] & M) - (y[i] & M);
- z[i] = (int)c;
- c >>= 32;
- }
- return (int)c;
- }
-
- public static int subBothFrom(int len, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
- {
- long c = 0;
- for (int i = 0; i < len; ++i)
- {
- c += (z[zOff + i] & M) - (x[xOff + i] & M) - (y[yOff + i] & M);
- z[zOff + i] = (int)c;
- c >>= 32;
- }
- return (int)c;
- }
-
- public static int subDWordAt(int len, long x, int[] z, int zPos)
- {
- // assert zPos <= (len - 2);
- long c = (z[zPos + 0] & M) - (x & M);
- z[zPos + 0] = (int)c;
- c >>= 32;
- c += (z[zPos + 1] & M) - (x >>> 32);
- z[zPos + 1] = (int)c;
- c >>= 32;
- return c == 0 ? 0 : decAt(len, z, zPos + 2);
- }
-
- public static int subDWordAt(int len, long x, int[] z, int zOff, int zPos)
- {
- // assert zPos <= (len - 2);
- long c = (z[zOff + zPos] & M) - (x & M);
- z[zOff + zPos] = (int)c;
- c >>= 32;
- c += (z[zOff + zPos + 1] & M) - (x >>> 32);
- z[zOff + zPos + 1] = (int)c;
- c >>= 32;
- return c == 0 ? 0 : decAt(len, z, zOff, zPos + 2);
- }
-
- public static int subDWordFrom(int len, long x, int[] z)
- {
- long c = (z[0] & M) - (x & M);
- z[0] = (int)c;
- c >>= 32;
- c += (z[1] & M) - (x >>> 32);
- z[1] = (int)c;
- c >>= 32;
- return c == 0 ? 0 : decAt(len, z, 2);
- }
-
- public static int subDWordFrom(int len, long x, int[] z, int zOff)
- {
- long c = (z[zOff + 0] & M) - (x & M);
- z[zOff + 0] = (int)c;
- c >>= 32;
- c += (z[zOff + 1] & M) - (x >>> 32);
- z[zOff + 1] = (int)c;
- c >>= 32;
- return c == 0 ? 0 : decAt(len, z, zOff, 2);
- }
-
- public static int subFrom(int len, int[] x, int[] z)
- {
- long c = 0;
- for (int i = 0; i < len; ++i)
- {
- c += (z[i] & M) - (x[i] & M);
- z[i] = (int)c;
- c >>= 32;
- }
- return (int)c;
- }
-
- public static int subFrom(int len, int[] x, int xOff, int[] z, int zOff)
- {
- long c = 0;
- for (int i = 0; i < len; ++i)
- {
- c += (z[zOff + i] & M) - (x[xOff + i] & M);
- z[zOff + i] = (int)c;
- c >>= 32;
- }
- return (int)c;
- }
-
- public static int subWordAt(int len, int x, int[] z, int zPos)
- {
- // assert zPos <= (len - 1);
- long c = (z[zPos] & M) - (x & M);
- z[zPos] = (int)c;
- c >>= 32;
- return c == 0 ? 0 : decAt(len, z, zPos + 1);
- }
-
- public static int subWordAt(int len, int x, int[] z, int zOff, int zPos)
- {
- // assert zPos <= (len - 1);
- long c = (z[zOff + zPos] & M) - (x & M);
- z[zOff + zPos] = (int)c;
- c >>= 32;
- return c == 0 ? 0 : decAt(len, z, zOff, zPos + 1);
- }
-
- public static int subWordFrom(int len, int x, int[] z)
- {
- long c = (z[0] & M) - (x & M);
- z[0] = (int)c;
- c >>= 32;
- return c == 0 ? 0 : decAt(len, z, 1);
- }
-
- public static int subWordFrom(int len, int x, int[] z, int zOff)
- {
- long c = (z[zOff + 0] & M) - (x & M);
- z[zOff + 0] = (int)c;
- c >>= 32;
- return c == 0 ? 0 : decAt(len, z, zOff, 1);
- }
-
- public static BigInteger toBigInteger(int len, int[] x)
- {
- byte[] bs = new byte[len << 2];
- for (int i = 0; i < len; ++i)
- {
- int x_i = x[i];
- if (x_i != 0)
- {
- Pack.intToBigEndian(x_i, bs, (len - 1 - i) << 2);
- }
- }
- return new BigInteger(1, bs);
- }
-
- public static void zero(int len, int[] z)
- {
- for (int i = 0; i < len; ++i)
- {
- z[i] = 0;
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/raw/Nat192.java b/core/src/main/java/org/bouncycastle/math/raw/Nat192.java
deleted file mode 100644
index e7e3dfa5..00000000
--- a/core/src/main/java/org/bouncycastle/math/raw/Nat192.java
+++ /dev/null
@@ -1,968 +0,0 @@
-package org.bouncycastle.math.raw;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.util.Pack;
-
-public abstract class Nat192
-{
- private static final long M = 0xFFFFFFFFL;
-
- public static int add(int[] x, int[] y, int[] z)
- {
- long c = 0;
- c += (x[0] & M) + (y[0] & M);
- z[0] = (int)c;
- c >>>= 32;
- c += (x[1] & M) + (y[1] & M);
- z[1] = (int)c;
- c >>>= 32;
- c += (x[2] & M) + (y[2] & M);
- z[2] = (int)c;
- c >>>= 32;
- c += (x[3] & M) + (y[3] & M);
- z[3] = (int)c;
- c >>>= 32;
- c += (x[4] & M) + (y[4] & M);
- z[4] = (int)c;
- c >>>= 32;
- c += (x[5] & M) + (y[5] & M);
- z[5] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static int addBothTo(int[] x, int[] y, int[] z)
- {
- long c = 0;
- c += (x[0] & M) + (y[0] & M) + (z[0] & M);
- z[0] = (int)c;
- c >>>= 32;
- c += (x[1] & M) + (y[1] & M) + (z[1] & M);
- z[1] = (int)c;
- c >>>= 32;
- c += (x[2] & M) + (y[2] & M) + (z[2] & M);
- z[2] = (int)c;
- c >>>= 32;
- c += (x[3] & M) + (y[3] & M) + (z[3] & M);
- z[3] = (int)c;
- c >>>= 32;
- c += (x[4] & M) + (y[4] & M) + (z[4] & M);
- z[4] = (int)c;
- c >>>= 32;
- c += (x[5] & M) + (y[5] & M) + (z[5] & M);
- z[5] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static int addTo(int[] x, int[] z)
- {
- long c = 0;
- c += (x[0] & M) + (z[0] & M);
- z[0] = (int)c;
- c >>>= 32;
- c += (x[1] & M) + (z[1] & M);
- z[1] = (int)c;
- c >>>= 32;
- c += (x[2] & M) + (z[2] & M);
- z[2] = (int)c;
- c >>>= 32;
- c += (x[3] & M) + (z[3] & M);
- z[3] = (int)c;
- c >>>= 32;
- c += (x[4] & M) + (z[4] & M);
- z[4] = (int)c;
- c >>>= 32;
- c += (x[5] & M) + (z[5] & M);
- z[5] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static int addTo(int[] x, int xOff, int[] z, int zOff, int cIn)
- {
- long c = cIn & M;
- c += (x[xOff + 0] & M) + (z[zOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>>= 32;
- c += (x[xOff + 1] & M) + (z[zOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>>= 32;
- c += (x[xOff + 2] & M) + (z[zOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>>= 32;
- c += (x[xOff + 3] & M) + (z[zOff + 3] & M);
- z[zOff + 3] = (int)c;
- c >>>= 32;
- c += (x[xOff + 4] & M) + (z[zOff + 4] & M);
- z[zOff + 4] = (int)c;
- c >>>= 32;
- c += (x[xOff + 5] & M) + (z[zOff + 5] & M);
- z[zOff + 5] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static int addToEachOther(int[] u, int uOff, int[] v, int vOff)
- {
- long c = 0;
- c += (u[uOff + 0] & M) + (v[vOff + 0] & M);
- u[uOff + 0] = (int)c;
- v[vOff + 0] = (int)c;
- c >>>= 32;
- c += (u[uOff + 1] & M) + (v[vOff + 1] & M);
- u[uOff + 1] = (int)c;
- v[vOff + 1] = (int)c;
- c >>>= 32;
- c += (u[uOff + 2] & M) + (v[vOff + 2] & M);
- u[uOff + 2] = (int)c;
- v[vOff + 2] = (int)c;
- c >>>= 32;
- c += (u[uOff + 3] & M) + (v[vOff + 3] & M);
- u[uOff + 3] = (int)c;
- v[vOff + 3] = (int)c;
- c >>>= 32;
- c += (u[uOff + 4] & M) + (v[vOff + 4] & M);
- u[uOff + 4] = (int)c;
- v[vOff + 4] = (int)c;
- c >>>= 32;
- c += (u[uOff + 5] & M) + (v[vOff + 5] & M);
- u[uOff + 5] = (int)c;
- v[vOff + 5] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static void copy(int[] x, int[] z)
- {
- z[0] = x[0];
- z[1] = x[1];
- z[2] = x[2];
- z[3] = x[3];
- z[4] = x[4];
- z[5] = x[5];
- }
-
- public static int[] create()
- {
- return new int[6];
- }
-
- public static int[] createExt()
- {
- return new int[12];
- }
-
- public static boolean diff(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
- {
- boolean pos = gte(x, xOff, y, yOff);
- if (pos)
- {
- sub(x, xOff, y, yOff, z, zOff);
- }
- else
- {
- sub(y, yOff, x, xOff, z, zOff);
- }
- return pos;
- }
-
- public static boolean eq(int[] x, int[] y)
- {
- for (int i = 5; i >= 0; --i)
- {
- if (x[i] != y[i])
- {
- return false;
- }
- }
- return true;
- }
-
- public static int[] fromBigInteger(BigInteger x)
- {
- if (x.signum() < 0 || x.bitLength() > 192)
- {
- throw new IllegalArgumentException();
- }
-
- int[] z = create();
- int i = 0;
- while (x.signum() != 0)
- {
- z[i++] = x.intValue();
- x = x.shiftRight(32);
- }
- return z;
- }
-
- public static int getBit(int[] x, int bit)
- {
- if (bit == 0)
- {
- return x[0] & 1;
- }
- int w = bit >> 5;
- if (w < 0 || w >= 6)
- {
- return 0;
- }
- int b = bit & 31;
- return (x[w] >>> b) & 1;
- }
-
- public static boolean gte(int[] x, int[] y)
- {
- for (int i = 5; i >= 0; --i)
- {
- int x_i = x[i] ^ Integer.MIN_VALUE;
- int y_i = y[i] ^ Integer.MIN_VALUE;
- if (x_i < y_i)
- return false;
- if (x_i > y_i)
- return true;
- }
- return true;
- }
-
- public static boolean gte(int[] x, int xOff, int[] y, int yOff)
- {
- for (int i = 5; i >= 0; --i)
- {
- int x_i = x[xOff + i] ^ Integer.MIN_VALUE;
- int y_i = y[yOff + i] ^ Integer.MIN_VALUE;
- if (x_i < y_i)
- return false;
- if (x_i > y_i)
- return true;
- }
- return true;
- }
-
- public static boolean isOne(int[] x)
- {
- if (x[0] != 1)
- {
- return false;
- }
- for (int i = 1; i < 6; ++i)
- {
- if (x[i] != 0)
- {
- return false;
- }
- }
- return true;
- }
-
- public static boolean isZero(int[] x)
- {
- for (int i = 0; i < 6; ++i)
- {
- if (x[i] != 0)
- {
- return false;
- }
- }
- return true;
- }
-
- public static void mul(int[] x, int[] y, int[] zz)
- {
- long y_0 = y[0] & M;
- long y_1 = y[1] & M;
- long y_2 = y[2] & M;
- long y_3 = y[3] & M;
- long y_4 = y[4] & M;
- long y_5 = y[5] & M;
-
- {
- long c = 0, x_0 = x[0] & M;
- c += x_0 * y_0;
- zz[0] = (int)c;
- c >>>= 32;
- c += x_0 * y_1;
- zz[1] = (int)c;
- c >>>= 32;
- c += x_0 * y_2;
- zz[2] = (int)c;
- c >>>= 32;
- c += x_0 * y_3;
- zz[3] = (int)c;
- c >>>= 32;
- c += x_0 * y_4;
- zz[4] = (int)c;
- c >>>= 32;
- c += x_0 * y_5;
- zz[5] = (int)c;
- c >>>= 32;
- zz[6] = (int)c;
- }
-
- for (int i = 1; i < 6; ++i)
- {
- long c = 0, x_i = x[i] & M;
- c += x_i * y_0 + (zz[i + 0] & M);
- zz[i + 0] = (int)c;
- c >>>= 32;
- c += x_i * y_1 + (zz[i + 1] & M);
- zz[i + 1] = (int)c;
- c >>>= 32;
- c += x_i * y_2 + (zz[i + 2] & M);
- zz[i + 2] = (int)c;
- c >>>= 32;
- c += x_i * y_3 + (zz[i + 3] & M);
- zz[i + 3] = (int)c;
- c >>>= 32;
- c += x_i * y_4 + (zz[i + 4] & M);
- zz[i + 4] = (int)c;
- c >>>= 32;
- c += x_i * y_5 + (zz[i + 5] & M);
- zz[i + 5] = (int)c;
- c >>>= 32;
- zz[i + 6] = (int)c;
- }
- }
-
- public static void mul(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
- {
- long y_0 = y[yOff + 0] & M;
- long y_1 = y[yOff + 1] & M;
- long y_2 = y[yOff + 2] & M;
- long y_3 = y[yOff + 3] & M;
- long y_4 = y[yOff + 4] & M;
- long y_5 = y[yOff + 5] & M;
-
- {
- long c = 0, x_0 = x[xOff + 0] & M;
- c += x_0 * y_0;
- zz[zzOff + 0] = (int)c;
- c >>>= 32;
- c += x_0 * y_1;
- zz[zzOff + 1] = (int)c;
- c >>>= 32;
- c += x_0 * y_2;
- zz[zzOff + 2] = (int)c;
- c >>>= 32;
- c += x_0 * y_3;
- zz[zzOff + 3] = (int)c;
- c >>>= 32;
- c += x_0 * y_4;
- zz[zzOff + 4] = (int)c;
- c >>>= 32;
- c += x_0 * y_5;
- zz[zzOff + 5] = (int)c;
- c >>>= 32;
- zz[zzOff + 6] = (int)c;
- }
-
- for (int i = 1; i < 6; ++i)
- {
- ++zzOff;
- long c = 0, x_i = x[xOff + i] & M;
- c += x_i * y_0 + (zz[zzOff + 0] & M);
- zz[zzOff + 0] = (int)c;
- c >>>= 32;
- c += x_i * y_1 + (zz[zzOff + 1] & M);
- zz[zzOff + 1] = (int)c;
- c >>>= 32;
- c += x_i * y_2 + (zz[zzOff + 2] & M);
- zz[zzOff + 2] = (int)c;
- c >>>= 32;
- c += x_i * y_3 + (zz[zzOff + 3] & M);
- zz[zzOff + 3] = (int)c;
- c >>>= 32;
- c += x_i * y_4 + (zz[zzOff + 4] & M);
- zz[zzOff + 4] = (int)c;
- c >>>= 32;
- c += x_i * y_5 + (zz[zzOff + 5] & M);
- zz[zzOff + 5] = (int)c;
- c >>>= 32;
- zz[zzOff + 6] = (int)c;
- }
- }
-
- public static int mulAddTo(int[] x, int[] y, int[] zz)
- {
- long y_0 = y[0] & M;
- long y_1 = y[1] & M;
- long y_2 = y[2] & M;
- long y_3 = y[3] & M;
- long y_4 = y[4] & M;
- long y_5 = y[5] & M;
-
- long zc = 0;
- for (int i = 0; i < 6; ++i)
- {
- long c = 0, x_i = x[i] & M;
- c += x_i * y_0 + (zz[i + 0] & M);
- zz[i + 0] = (int)c;
- c >>>= 32;
- c += x_i * y_1 + (zz[i + 1] & M);
- zz[i + 1] = (int)c;
- c >>>= 32;
- c += x_i * y_2 + (zz[i + 2] & M);
- zz[i + 2] = (int)c;
- c >>>= 32;
- c += x_i * y_3 + (zz[i + 3] & M);
- zz[i + 3] = (int)c;
- c >>>= 32;
- c += x_i * y_4 + (zz[i + 4] & M);
- zz[i + 4] = (int)c;
- c >>>= 32;
- c += x_i * y_5 + (zz[i + 5] & M);
- zz[i + 5] = (int)c;
- c >>>= 32;
- c += zc + (zz[i + 6] & M);
- zz[i + 6] = (int)c;
- zc = c >>> 32;
- }
- return (int)zc;
- }
-
- public static int mulAddTo(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
- {
- long y_0 = y[yOff + 0] & M;
- long y_1 = y[yOff + 1] & M;
- long y_2 = y[yOff + 2] & M;
- long y_3 = y[yOff + 3] & M;
- long y_4 = y[yOff + 4] & M;
- long y_5 = y[yOff + 5] & M;
-
- long zc = 0;
- for (int i = 0; i < 6; ++i)
- {
- long c = 0, x_i = x[xOff + i] & M;
- c += x_i * y_0 + (zz[zzOff + 0] & M);
- zz[zzOff + 0] = (int)c;
- c >>>= 32;
- c += x_i * y_1 + (zz[zzOff + 1] & M);
- zz[zzOff + 1] = (int)c;
- c >>>= 32;
- c += x_i * y_2 + (zz[zzOff + 2] & M);
- zz[zzOff + 2] = (int)c;
- c >>>= 32;
- c += x_i * y_3 + (zz[zzOff + 3] & M);
- zz[zzOff + 3] = (int)c;
- c >>>= 32;
- c += x_i * y_4 + (zz[zzOff + 4] & M);
- zz[zzOff + 4] = (int)c;
- c >>>= 32;
- c += x_i * y_5 + (zz[zzOff + 5] & M);
- zz[zzOff + 5] = (int)c;
- c >>>= 32;
- c += zc + (zz[zzOff + 6] & M);
- zz[zzOff + 6] = (int)c;
- zc = c >>> 32;
- ++zzOff;
- }
- return (int)zc;
- }
-
- public static long mul33Add(int w, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
- {
- // assert w >>> 31 == 0;
-
- long c = 0, wVal = w & M;
- long x0 = x[xOff + 0] & M;
- c += wVal * x0 + (y[yOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>>= 32;
- long x1 = x[xOff + 1] & M;
- c += wVal * x1 + x0 + (y[yOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>>= 32;
- long x2 = x[xOff + 2] & M;
- c += wVal * x2 + x1 + (y[yOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>>= 32;
- long x3 = x[xOff + 3] & M;
- c += wVal * x3 + x2 + (y[yOff + 3] & M);
- z[zOff + 3] = (int)c;
- c >>>= 32;
- long x4 = x[xOff + 4] & M;
- c += wVal * x4 + x3 + (y[yOff + 4] & M);
- z[zOff + 4] = (int)c;
- c >>>= 32;
- long x5 = x[xOff + 5] & M;
- c += wVal * x5 + x4 + (y[yOff + 5] & M);
- z[zOff + 5] = (int)c;
- c >>>= 32;
- c += x5;
- return c;
- }
-
- public static int mulWordAddExt(int x, int[] yy, int yyOff, int[] zz, int zzOff)
- {
- // assert yyOff <= 6;
- // assert zzOff <= 6;
- long c = 0, xVal = x & M;
- c += xVal * (yy[yyOff + 0] & M) + (zz[zzOff + 0] & M);
- zz[zzOff + 0] = (int)c;
- c >>>= 32;
- c += xVal * (yy[yyOff + 1] & M) + (zz[zzOff + 1] & M);
- zz[zzOff + 1] = (int)c;
- c >>>= 32;
- c += xVal * (yy[yyOff + 2] & M) + (zz[zzOff + 2] & M);
- zz[zzOff + 2] = (int)c;
- c >>>= 32;
- c += xVal * (yy[yyOff + 3] & M) + (zz[zzOff + 3] & M);
- zz[zzOff + 3] = (int)c;
- c >>>= 32;
- c += xVal * (yy[yyOff + 4] & M) + (zz[zzOff + 4] & M);
- zz[zzOff + 4] = (int)c;
- c >>>= 32;
- c += xVal * (yy[yyOff + 5] & M) + (zz[zzOff + 5] & M);
- zz[zzOff + 5] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static int mul33DWordAdd(int x, long y, int[] z, int zOff)
- {
- // assert x >>> 31 == 0;
- // assert zOff <= 2;
-
- long c = 0, xVal = x & M;
- long y00 = y & M;
- c += xVal * y00 + (z[zOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>>= 32;
- long y01 = y >>> 32;
- c += xVal * y01 + y00 + (z[zOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>>= 32;
- c += y01 + (z[zOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>>= 32;
- c += (z[zOff + 3] & M);
- z[zOff + 3] = (int)c;
- c >>>= 32;
- return c == 0 ? 0 : Nat.incAt(6, z, zOff, 4);
- }
-
- public static int mul33WordAdd(int x, int y, int[] z, int zOff)
- {
- // assert x >>> 31 == 0;
- // assert zOff <= 3;
-
- long c = 0, xVal = x & M, yVal = y & M;
- c += yVal * xVal + (z[zOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>>= 32;
- c += yVal + (z[zOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>>= 32;
- c += (z[zOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>>= 32;
- return c == 0 ? 0 : Nat.incAt(6, z, zOff, 3);
- }
-
- public static int mulWordDwordAdd(int x, long y, int[] z, int zOff)
- {
- // assert zOff <= 3;
- long c = 0, xVal = x & M;
- c += xVal * (y & M) + (z[zOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>>= 32;
- c += xVal * (y >>> 32) + (z[zOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>>= 32;
- c += (z[zOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>>= 32;
- return c == 0 ? 0 : Nat.incAt(6, z, zOff, 3);
- }
-
- public static int mulWord(int x, int[] y, int[] z, int zOff)
- {
- long c = 0, xVal = x & M;
- int i = 0;
- do
- {
- c += xVal * (y[i] & M);
- z[zOff + i] = (int)c;
- c >>>= 32;
- }
- while (++i < 6);
- return (int)c;
- }
-
- public static void square(int[] x, int[] zz)
- {
- long x_0 = x[0] & M;
- long zz_1;
-
- int c = 0, w;
- {
- int i = 5, j = 12;
- do
- {
- long xVal = (x[i--] & M);
- long p = xVal * xVal;
- zz[--j] = (c << 31) | (int)(p >>> 33);
- zz[--j] = (int)(p >>> 1);
- c = (int)p;
- }
- while (i > 0);
-
- {
- long p = x_0 * x_0;
- zz_1 = ((c << 31) & M) | (p >>> 33);
- zz[0] = (int)p;
- c = (int)(p >>> 32) & 1;
- }
- }
-
- long x_1 = x[1] & M;
- long zz_2 = zz[2] & M;
-
- {
- zz_1 += x_1 * x_0;
- w = (int)zz_1;
- zz[1] = (w << 1) | c;
- c = w >>> 31;
- zz_2 += zz_1 >>> 32;
- }
-
- long x_2 = x[2] & M;
- long zz_3 = zz[3] & M;
- long zz_4 = zz[4] & M;
- {
- zz_2 += x_2 * x_0;
- w = (int)zz_2;
- zz[2] = (w << 1) | c;
- c = w >>> 31;
- zz_3 += (zz_2 >>> 32) + x_2 * x_1;
- zz_4 += zz_3 >>> 32;
- zz_3 &= M;
- }
-
- long x_3 = x[3] & M;
- long zz_5 = zz[5] & M;
- long zz_6 = zz[6] & M;
- {
- zz_3 += x_3 * x_0;
- w = (int)zz_3;
- zz[3] = (w << 1) | c;
- c = w >>> 31;
- zz_4 += (zz_3 >>> 32) + x_3 * x_1;
- zz_5 += (zz_4 >>> 32) + x_3 * x_2;
- zz_4 &= M;
- zz_6 += zz_5 >>> 32;
- zz_5 &= M;
- }
-
- long x_4 = x[4] & M;
- long zz_7 = zz[7] & M;
- long zz_8 = zz[8] & M;
- {
- zz_4 += x_4 * x_0;
- w = (int)zz_4;
- zz[4] = (w << 1) | c;
- c = w >>> 31;
- zz_5 += (zz_4 >>> 32) + x_4 * x_1;
- zz_6 += (zz_5 >>> 32) + x_4 * x_2;
- zz_5 &= M;
- zz_7 += (zz_6 >>> 32) + x_4 * x_3;
- zz_6 &= M;
- zz_8 += zz_7 >>> 32;
- zz_7 &= M;
- }
-
- long x_5 = x[5] & M;
- long zz_9 = zz[9] & M;
- long zz_10 = zz[10] & M;
- {
- zz_5 += x_5 * x_0;
- w = (int)zz_5;
- zz[5] = (w << 1) | c;
- c = w >>> 31;
- zz_6 += (zz_5 >>> 32) + x_5 * x_1;
- zz_7 += (zz_6 >>> 32) + x_5 * x_2;
- zz_8 += (zz_7 >>> 32) + x_5 * x_3;
- zz_9 += (zz_8 >>> 32) + x_5 * x_4;
- zz_10 += zz_9 >>> 32;
- }
-
- w = (int)zz_6;
- zz[6] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_7;
- zz[7] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_8;
- zz[8] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_9;
- zz[9] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_10;
- zz[10] = (w << 1) | c;
- c = w >>> 31;
- w = zz[11] + (int)(zz_10 >> 32);
- zz[11] = (w << 1) | c;
- }
-
- public static void square(int[] x, int xOff, int[] zz, int zzOff)
- {
- long x_0 = x[xOff + 0] & M;
- long zz_1;
-
- int c = 0, w;
- {
- int i = 5, j = 12;
- do
- {
- long xVal = (x[xOff + i--] & M);
- long p = xVal * xVal;
- zz[zzOff + --j] = (c << 31) | (int)(p >>> 33);
- zz[zzOff + --j] = (int)(p >>> 1);
- c = (int)p;
- }
- while (i > 0);
-
- {
- long p = x_0 * x_0;
- zz_1 = ((c << 31) & M) | (p >>> 33);
- zz[zzOff + 0] = (int)p;
- c = (int)(p >>> 32) & 1;
- }
- }
-
- long x_1 = x[xOff + 1] & M;
- long zz_2 = zz[zzOff + 2] & M;
-
- {
- zz_1 += x_1 * x_0;
- w = (int)zz_1;
- zz[zzOff + 1] = (w << 1) | c;
- c = w >>> 31;
- zz_2 += zz_1 >>> 32;
- }
-
- long x_2 = x[xOff + 2] & M;
- long zz_3 = zz[zzOff + 3] & M;
- long zz_4 = zz[zzOff + 4] & M;
- {
- zz_2 += x_2 * x_0;
- w = (int)zz_2;
- zz[zzOff + 2] = (w << 1) | c;
- c = w >>> 31;
- zz_3 += (zz_2 >>> 32) + x_2 * x_1;
- zz_4 += zz_3 >>> 32;
- zz_3 &= M;
- }
-
- long x_3 = x[xOff + 3] & M;
- long zz_5 = zz[zzOff + 5] & M;
- long zz_6 = zz[zzOff + 6] & M;
- {
- zz_3 += x_3 * x_0;
- w = (int)zz_3;
- zz[zzOff + 3] = (w << 1) | c;
- c = w >>> 31;
- zz_4 += (zz_3 >>> 32) + x_3 * x_1;
- zz_5 += (zz_4 >>> 32) + x_3 * x_2;
- zz_4 &= M;
- zz_6 += zz_5 >>> 32;
- zz_5 &= M;
- }
-
- long x_4 = x[xOff + 4] & M;
- long zz_7 = zz[zzOff + 7] & M;
- long zz_8 = zz[zzOff + 8] & M;
- {
- zz_4 += x_4 * x_0;
- w = (int)zz_4;
- zz[zzOff + 4] = (w << 1) | c;
- c = w >>> 31;
- zz_5 += (zz_4 >>> 32) + x_4 * x_1;
- zz_6 += (zz_5 >>> 32) + x_4 * x_2;
- zz_5 &= M;
- zz_7 += (zz_6 >>> 32) + x_4 * x_3;
- zz_6 &= M;
- zz_8 += zz_7 >>> 32;
- zz_7 &= M;
- }
-
- long x_5 = x[xOff + 5] & M;
- long zz_9 = zz[zzOff + 9] & M;
- long zz_10 = zz[zzOff + 10] & M;
- {
- zz_5 += x_5 * x_0;
- w = (int)zz_5;
- zz[zzOff + 5] = (w << 1) | c;
- c = w >>> 31;
- zz_6 += (zz_5 >>> 32) + x_5 * x_1;
- zz_7 += (zz_6 >>> 32) + x_5 * x_2;
- zz_8 += (zz_7 >>> 32) + x_5 * x_3;
- zz_9 += (zz_8 >>> 32) + x_5 * x_4;
- zz_10 += zz_9 >>> 32;
- }
-
- w = (int)zz_6;
- zz[zzOff + 6] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_7;
- zz[zzOff + 7] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_8;
- zz[zzOff + 8] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_9;
- zz[zzOff + 9] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_10;
- zz[zzOff + 10] = (w << 1) | c;
- c = w >>> 31;
- w = zz[zzOff + 11] + (int)(zz_10 >> 32);
- zz[zzOff + 11] = (w << 1) | c;
- }
-
- public static int sub(int[] x, int[] y, int[] z)
- {
- long c = 0;
- c += (x[0] & M) - (y[0] & M);
- z[0] = (int)c;
- c >>= 32;
- c += (x[1] & M) - (y[1] & M);
- z[1] = (int)c;
- c >>= 32;
- c += (x[2] & M) - (y[2] & M);
- z[2] = (int)c;
- c >>= 32;
- c += (x[3] & M) - (y[3] & M);
- z[3] = (int)c;
- c >>= 32;
- c += (x[4] & M) - (y[4] & M);
- z[4] = (int)c;
- c >>= 32;
- c += (x[5] & M) - (y[5] & M);
- z[5] = (int)c;
- c >>= 32;
- return (int)c;
- }
-
- public static int sub(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
- {
- long c = 0;
- c += (x[xOff + 0] & M) - (y[yOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>= 32;
- c += (x[xOff + 1] & M) - (y[yOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>= 32;
- c += (x[xOff + 2] & M) - (y[yOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>= 32;
- c += (x[xOff + 3] & M) - (y[yOff + 3] & M);
- z[zOff + 3] = (int)c;
- c >>= 32;
- c += (x[xOff + 4] & M) - (y[yOff + 4] & M);
- z[zOff + 4] = (int)c;
- c >>= 32;
- c += (x[xOff + 5] & M) - (y[yOff + 5] & M);
- z[zOff + 5] = (int)c;
- c >>= 32;
- return (int)c;
- }
-
- public static int subBothFrom(int[] x, int[] y, int[] z)
- {
- long c = 0;
- c += (z[0] & M) - (x[0] & M) - (y[0] & M);
- z[0] = (int)c;
- c >>= 32;
- c += (z[1] & M) - (x[1] & M) - (y[1] & M);
- z[1] = (int)c;
- c >>= 32;
- c += (z[2] & M) - (x[2] & M) - (y[2] & M);
- z[2] = (int)c;
- c >>= 32;
- c += (z[3] & M) - (x[3] & M) - (y[3] & M);
- z[3] = (int)c;
- c >>= 32;
- c += (z[4] & M) - (x[4] & M) - (y[4] & M);
- z[4] = (int)c;
- c >>= 32;
- c += (z[5] & M) - (x[5] & M) - (y[5] & M);
- z[5] = (int)c;
- c >>= 32;
- return (int)c;
- }
-
- public static int subFrom(int[] x, int[] z)
- {
- long c = 0;
- c += (z[0] & M) - (x[0] & M);
- z[0] = (int)c;
- c >>= 32;
- c += (z[1] & M) - (x[1] & M);
- z[1] = (int)c;
- c >>= 32;
- c += (z[2] & M) - (x[2] & M);
- z[2] = (int)c;
- c >>= 32;
- c += (z[3] & M) - (x[3] & M);
- z[3] = (int)c;
- c >>= 32;
- c += (z[4] & M) - (x[4] & M);
- z[4] = (int)c;
- c >>= 32;
- c += (z[5] & M) - (x[5] & M);
- z[5] = (int)c;
- c >>= 32;
- return (int)c;
- }
-
- public static int subFrom(int[] x, int xOff, int[] z, int zOff)
- {
- long c = 0;
- c += (z[zOff + 0] & M) - (x[xOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>= 32;
- c += (z[zOff + 1] & M) - (x[xOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>= 32;
- c += (z[zOff + 2] & M) - (x[xOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>= 32;
- c += (z[zOff + 3] & M) - (x[xOff + 3] & M);
- z[zOff + 3] = (int)c;
- c >>= 32;
- c += (z[zOff + 4] & M) - (x[xOff + 4] & M);
- z[zOff + 4] = (int)c;
- c >>= 32;
- c += (z[zOff + 5] & M) - (x[xOff + 5] & M);
- z[zOff + 5] = (int)c;
- c >>= 32;
- return (int)c;
- }
-
- public static BigInteger toBigInteger(int[] x)
- {
- byte[] bs = new byte[24];
- for (int i = 0; i < 6; ++i)
- {
- int x_i = x[i];
- if (x_i != 0)
- {
- Pack.intToBigEndian(x_i, bs, (5 - i) << 2);
- }
- }
- return new BigInteger(1, bs);
- }
-
- public static void zero(int[] z)
- {
- z[0] = 0;
- z[1] = 0;
- z[2] = 0;
- z[3] = 0;
- z[4] = 0;
- z[5] = 0;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/raw/Nat224.java b/core/src/main/java/org/bouncycastle/math/raw/Nat224.java
deleted file mode 100644
index bbe81caa..00000000
--- a/core/src/main/java/org/bouncycastle/math/raw/Nat224.java
+++ /dev/null
@@ -1,1182 +0,0 @@
-package org.bouncycastle.math.raw;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.util.Pack;
-
-public abstract class Nat224
-{
- private static final long M = 0xFFFFFFFFL;
-
- public static int add(int[] x, int[] y, int[] z)
- {
- long c = 0;
- c += (x[0] & M) + (y[0] & M);
- z[0] = (int)c;
- c >>>= 32;
- c += (x[1] & M) + (y[1] & M);
- z[1] = (int)c;
- c >>>= 32;
- c += (x[2] & M) + (y[2] & M);
- z[2] = (int)c;
- c >>>= 32;
- c += (x[3] & M) + (y[3] & M);
- z[3] = (int)c;
- c >>>= 32;
- c += (x[4] & M) + (y[4] & M);
- z[4] = (int)c;
- c >>>= 32;
- c += (x[5] & M) + (y[5] & M);
- z[5] = (int)c;
- c >>>= 32;
- c += (x[6] & M) + (y[6] & M);
- z[6] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static int add(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
- {
- long c = 0;
- c += (x[xOff + 0] & M) + (y[yOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>>= 32;
- c += (x[xOff + 1] & M) + (y[yOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>>= 32;
- c += (x[xOff + 2] & M) + (y[yOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>>= 32;
- c += (x[xOff + 3] & M) + (y[yOff + 3] & M);
- z[zOff + 3] = (int)c;
- c >>>= 32;
- c += (x[xOff + 4] & M) + (y[yOff + 4] & M);
- z[zOff + 4] = (int)c;
- c >>>= 32;
- c += (x[xOff + 5] & M) + (y[yOff + 5] & M);
- z[zOff + 5] = (int)c;
- c >>>= 32;
- c += (x[xOff + 6] & M) + (y[yOff + 6] & M);
- z[zOff + 6] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static int addBothTo(int[] x, int[] y, int[] z)
- {
- long c = 0;
- c += (x[0] & M) + (y[0] & M) + (z[0] & M);
- z[0] = (int)c;
- c >>>= 32;
- c += (x[1] & M) + (y[1] & M) + (z[1] & M);
- z[1] = (int)c;
- c >>>= 32;
- c += (x[2] & M) + (y[2] & M) + (z[2] & M);
- z[2] = (int)c;
- c >>>= 32;
- c += (x[3] & M) + (y[3] & M) + (z[3] & M);
- z[3] = (int)c;
- c >>>= 32;
- c += (x[4] & M) + (y[4] & M) + (z[4] & M);
- z[4] = (int)c;
- c >>>= 32;
- c += (x[5] & M) + (y[5] & M) + (z[5] & M);
- z[5] = (int)c;
- c >>>= 32;
- c += (x[6] & M) + (y[6] & M) + (z[6] & M);
- z[6] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static int addBothTo(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
- {
- long c = 0;
- c += (x[xOff + 0] & M) + (y[yOff + 0] & M) + (z[zOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>>= 32;
- c += (x[xOff + 1] & M) + (y[yOff + 1] & M) + (z[zOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>>= 32;
- c += (x[xOff + 2] & M) + (y[yOff + 2] & M) + (z[zOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>>= 32;
- c += (x[xOff + 3] & M) + (y[yOff + 3] & M) + (z[zOff + 3] & M);
- z[zOff + 3] = (int)c;
- c >>>= 32;
- c += (x[xOff + 4] & M) + (y[yOff + 4] & M) + (z[zOff + 4] & M);
- z[zOff + 4] = (int)c;
- c >>>= 32;
- c += (x[xOff + 5] & M) + (y[yOff + 5] & M) + (z[zOff + 5] & M);
- z[zOff + 5] = (int)c;
- c >>>= 32;
- c += (x[xOff + 6] & M) + (y[yOff + 6] & M) + (z[zOff + 6] & M);
- z[zOff + 6] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static int addTo(int[] x, int[] z)
- {
- long c = 0;
- c += (x[0] & M) + (z[0] & M);
- z[0] = (int)c;
- c >>>= 32;
- c += (x[1] & M) + (z[1] & M);
- z[1] = (int)c;
- c >>>= 32;
- c += (x[2] & M) + (z[2] & M);
- z[2] = (int)c;
- c >>>= 32;
- c += (x[3] & M) + (z[3] & M);
- z[3] = (int)c;
- c >>>= 32;
- c += (x[4] & M) + (z[4] & M);
- z[4] = (int)c;
- c >>>= 32;
- c += (x[5] & M) + (z[5] & M);
- z[5] = (int)c;
- c >>>= 32;
- c += (x[6] & M) + (z[6] & M);
- z[6] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static int addTo(int[] x, int xOff, int[] z, int zOff, int cIn)
- {
- long c = cIn & M;
- c += (x[xOff + 0] & M) + (z[zOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>>= 32;
- c += (x[xOff + 1] & M) + (z[zOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>>= 32;
- c += (x[xOff + 2] & M) + (z[zOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>>= 32;
- c += (x[xOff + 3] & M) + (z[zOff + 3] & M);
- z[zOff + 3] = (int)c;
- c >>>= 32;
- c += (x[xOff + 4] & M) + (z[zOff + 4] & M);
- z[zOff + 4] = (int)c;
- c >>>= 32;
- c += (x[xOff + 5] & M) + (z[zOff + 5] & M);
- z[zOff + 5] = (int)c;
- c >>>= 32;
- c += (x[xOff + 6] & M) + (z[zOff + 6] & M);
- z[zOff + 6] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static int addToEachOther(int[] u, int uOff, int[] v, int vOff)
- {
- long c = 0;
- c += (u[uOff + 0] & M) + (v[vOff + 0] & M);
- u[uOff + 0] = (int)c;
- v[vOff + 0] = (int)c;
- c >>>= 32;
- c += (u[uOff + 1] & M) + (v[vOff + 1] & M);
- u[uOff + 1] = (int)c;
- v[vOff + 1] = (int)c;
- c >>>= 32;
- c += (u[uOff + 2] & M) + (v[vOff + 2] & M);
- u[uOff + 2] = (int)c;
- v[vOff + 2] = (int)c;
- c >>>= 32;
- c += (u[uOff + 3] & M) + (v[vOff + 3] & M);
- u[uOff + 3] = (int)c;
- v[vOff + 3] = (int)c;
- c >>>= 32;
- c += (u[uOff + 4] & M) + (v[vOff + 4] & M);
- u[uOff + 4] = (int)c;
- v[vOff + 4] = (int)c;
- c >>>= 32;
- c += (u[uOff + 5] & M) + (v[vOff + 5] & M);
- u[uOff + 5] = (int)c;
- v[vOff + 5] = (int)c;
- c >>>= 32;
- c += (u[uOff + 6] & M) + (v[vOff + 6] & M);
- u[uOff + 6] = (int)c;
- v[vOff + 6] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static void copy(int[] x, int[] z)
- {
- z[0] = x[0];
- z[1] = x[1];
- z[2] = x[2];
- z[3] = x[3];
- z[4] = x[4];
- z[5] = x[5];
- z[6] = x[6];
- }
-
- public static int[] create()
- {
- return new int[7];
- }
-
- public static int[] createExt()
- {
- return new int[14];
- }
-
- public static boolean diff(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
- {
- boolean pos = gte(x, xOff, y, yOff);
- if (pos)
- {
- sub(x, xOff, y, yOff, z, zOff);
- }
- else
- {
- sub(y, yOff, x, xOff, z, zOff);
- }
- return pos;
- }
-
- public static boolean eq(int[] x, int[] y)
- {
- for (int i = 6; i >= 0; --i)
- {
- if (x[i] != y[i])
- {
- return false;
- }
- }
- return true;
- }
-
- public static int[] fromBigInteger(BigInteger x)
- {
- if (x.signum() < 0 || x.bitLength() > 224)
- {
- throw new IllegalArgumentException();
- }
-
- int[] z = create();
- int i = 0;
- while (x.signum() != 0)
- {
- z[i++] = x.intValue();
- x = x.shiftRight(32);
- }
- return z;
- }
-
- public static int getBit(int[] x, int bit)
- {
- if (bit == 0)
- {
- return x[0] & 1;
- }
- int w = bit >> 5;
- if (w < 0 || w >= 7)
- {
- return 0;
- }
- int b = bit & 31;
- return (x[w] >>> b) & 1;
- }
-
- public static boolean gte(int[] x, int[] y)
- {
- for (int i = 6; i >= 0; --i)
- {
- int x_i = x[i] ^ Integer.MIN_VALUE;
- int y_i = y[i] ^ Integer.MIN_VALUE;
- if (x_i < y_i)
- return false;
- if (x_i > y_i)
- return true;
- }
- return true;
- }
-
- public static boolean gte(int[] x, int xOff, int[] y, int yOff)
- {
- for (int i = 6; i >= 0; --i)
- {
- int x_i = x[xOff + i] ^ Integer.MIN_VALUE;
- int y_i = y[yOff + i] ^ Integer.MIN_VALUE;
- if (x_i < y_i)
- return false;
- if (x_i > y_i)
- return true;
- }
- return true;
- }
-
- public static boolean isOne(int[] x)
- {
- if (x[0] != 1)
- {
- return false;
- }
- for (int i = 1; i < 7; ++i)
- {
- if (x[i] != 0)
- {
- return false;
- }
- }
- return true;
- }
-
- public static boolean isZero(int[] x)
- {
- for (int i = 0; i < 7; ++i)
- {
- if (x[i] != 0)
- {
- return false;
- }
- }
- return true;
- }
-
- public static void mul(int[] x, int[] y, int[] zz)
- {
- long y_0 = y[0] & M;
- long y_1 = y[1] & M;
- long y_2 = y[2] & M;
- long y_3 = y[3] & M;
- long y_4 = y[4] & M;
- long y_5 = y[5] & M;
- long y_6 = y[6] & M;
-
- {
- long c = 0, x_0 = x[0] & M;
- c += x_0 * y_0;
- zz[0] = (int)c;
- c >>>= 32;
- c += x_0 * y_1;
- zz[1] = (int)c;
- c >>>= 32;
- c += x_0 * y_2;
- zz[2] = (int)c;
- c >>>= 32;
- c += x_0 * y_3;
- zz[3] = (int)c;
- c >>>= 32;
- c += x_0 * y_4;
- zz[4] = (int)c;
- c >>>= 32;
- c += x_0 * y_5;
- zz[5] = (int)c;
- c >>>= 32;
- c += x_0 * y_6;
- zz[6] = (int)c;
- c >>>= 32;
- zz[7] = (int)c;
- }
-
- for (int i = 1; i < 7; ++i)
- {
- long c = 0, x_i = x[i] & M;
- c += x_i * y_0 + (zz[i + 0] & M);
- zz[i + 0] = (int)c;
- c >>>= 32;
- c += x_i * y_1 + (zz[i + 1] & M);
- zz[i + 1] = (int)c;
- c >>>= 32;
- c += x_i * y_2 + (zz[i + 2] & M);
- zz[i + 2] = (int)c;
- c >>>= 32;
- c += x_i * y_3 + (zz[i + 3] & M);
- zz[i + 3] = (int)c;
- c >>>= 32;
- c += x_i * y_4 + (zz[i + 4] & M);
- zz[i + 4] = (int)c;
- c >>>= 32;
- c += x_i * y_5 + (zz[i + 5] & M);
- zz[i + 5] = (int)c;
- c >>>= 32;
- c += x_i * y_6 + (zz[i + 6] & M);
- zz[i + 6] = (int)c;
- c >>>= 32;
- zz[i + 7] = (int)c;
- }
- }
-
- public static void mul(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
- {
- long y_0 = y[yOff + 0] & M;
- long y_1 = y[yOff + 1] & M;
- long y_2 = y[yOff + 2] & M;
- long y_3 = y[yOff + 3] & M;
- long y_4 = y[yOff + 4] & M;
- long y_5 = y[yOff + 5] & M;
- long y_6 = y[yOff + 6] & M;
-
- {
- long c = 0, x_0 = x[xOff + 0] & M;
- c += x_0 * y_0;
- zz[zzOff + 0] = (int)c;
- c >>>= 32;
- c += x_0 * y_1;
- zz[zzOff + 1] = (int)c;
- c >>>= 32;
- c += x_0 * y_2;
- zz[zzOff + 2] = (int)c;
- c >>>= 32;
- c += x_0 * y_3;
- zz[zzOff + 3] = (int)c;
- c >>>= 32;
- c += x_0 * y_4;
- zz[zzOff + 4] = (int)c;
- c >>>= 32;
- c += x_0 * y_5;
- zz[zzOff + 5] = (int)c;
- c >>>= 32;
- c += x_0 * y_6;
- zz[zzOff + 6] = (int)c;
- c >>>= 32;
- zz[zzOff + 7] = (int)c;
- }
-
- for (int i = 1; i < 7; ++i)
- {
- ++zzOff;
- long c = 0, x_i = x[xOff + i] & M;
- c += x_i * y_0 + (zz[zzOff + 0] & M);
- zz[zzOff + 0] = (int)c;
- c >>>= 32;
- c += x_i * y_1 + (zz[zzOff + 1] & M);
- zz[zzOff + 1] = (int)c;
- c >>>= 32;
- c += x_i * y_2 + (zz[zzOff + 2] & M);
- zz[zzOff + 2] = (int)c;
- c >>>= 32;
- c += x_i * y_3 + (zz[zzOff + 3] & M);
- zz[zzOff + 3] = (int)c;
- c >>>= 32;
- c += x_i * y_4 + (zz[zzOff + 4] & M);
- zz[zzOff + 4] = (int)c;
- c >>>= 32;
- c += x_i * y_5 + (zz[zzOff + 5] & M);
- zz[zzOff + 5] = (int)c;
- c >>>= 32;
- c += x_i * y_6 + (zz[zzOff + 6] & M);
- zz[zzOff + 6] = (int)c;
- c >>>= 32;
- zz[zzOff + 7] = (int)c;
- }
- }
-
- public static int mulAddTo(int[] x, int[] y, int[] zz)
- {
- long y_0 = y[0] & M;
- long y_1 = y[1] & M;
- long y_2 = y[2] & M;
- long y_3 = y[3] & M;
- long y_4 = y[4] & M;
- long y_5 = y[5] & M;
- long y_6 = y[6] & M;
-
- long zc = 0;
- for (int i = 0; i < 7; ++i)
- {
- long c = 0, x_i = x[i] & M;
- c += x_i * y_0 + (zz[i + 0] & M);
- zz[i + 0] = (int)c;
- c >>>= 32;
- c += x_i * y_1 + (zz[i + 1] & M);
- zz[i + 1] = (int)c;
- c >>>= 32;
- c += x_i * y_2 + (zz[i + 2] & M);
- zz[i + 2] = (int)c;
- c >>>= 32;
- c += x_i * y_3 + (zz[i + 3] & M);
- zz[i + 3] = (int)c;
- c >>>= 32;
- c += x_i * y_4 + (zz[i + 4] & M);
- zz[i + 4] = (int)c;
- c >>>= 32;
- c += x_i * y_5 + (zz[i + 5] & M);
- zz[i + 5] = (int)c;
- c >>>= 32;
- c += x_i * y_6 + (zz[i + 6] & M);
- zz[i + 6] = (int)c;
- c >>>= 32;
- c += zc + (zz[i + 7] & M);
- zz[i + 7] = (int)c;
- zc = c >>> 32;
- }
- return (int)zc;
- }
-
- public static int mulAddTo(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
- {
- long y_0 = y[yOff + 0] & M;
- long y_1 = y[yOff + 1] & M;
- long y_2 = y[yOff + 2] & M;
- long y_3 = y[yOff + 3] & M;
- long y_4 = y[yOff + 4] & M;
- long y_5 = y[yOff + 5] & M;
- long y_6 = y[yOff + 6] & M;
-
- long zc = 0;
- for (int i = 0; i < 7; ++i)
- {
- long c = 0, x_i = x[xOff + i] & M;
- c += x_i * y_0 + (zz[zzOff + 0] & M);
- zz[zzOff + 0] = (int)c;
- c >>>= 32;
- c += x_i * y_1 + (zz[zzOff + 1] & M);
- zz[zzOff + 1] = (int)c;
- c >>>= 32;
- c += x_i * y_2 + (zz[zzOff + 2] & M);
- zz[zzOff + 2] = (int)c;
- c >>>= 32;
- c += x_i * y_3 + (zz[zzOff + 3] & M);
- zz[zzOff + 3] = (int)c;
- c >>>= 32;
- c += x_i * y_4 + (zz[zzOff + 4] & M);
- zz[zzOff + 4] = (int)c;
- c >>>= 32;
- c += x_i * y_5 + (zz[zzOff + 5] & M);
- zz[zzOff + 5] = (int)c;
- c >>>= 32;
- c += x_i * y_6 + (zz[zzOff + 6] & M);
- zz[zzOff + 6] = (int)c;
- c >>>= 32;
- c += zc + (zz[zzOff + 7] & M);
- zz[zzOff + 7] = (int)c;
- zc = c >>> 32;
- ++zzOff;
- }
- return (int)zc;
- }
-
- public static long mul33Add(int w, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
- {
- // assert w >>> 31 == 0;
-
- long c = 0, wVal = w & M;
- long x0 = x[xOff + 0] & M;
- c += wVal * x0 + (y[yOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>>= 32;
- long x1 = x[xOff + 1] & M;
- c += wVal * x1 + x0 + (y[yOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>>= 32;
- long x2 = x[xOff + 2] & M;
- c += wVal * x2 + x1 + (y[yOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>>= 32;
- long x3 = x[xOff + 3] & M;
- c += wVal * x3 + x2 + (y[yOff + 3] & M);
- z[zOff + 3] = (int)c;
- c >>>= 32;
- long x4 = x[xOff + 4] & M;
- c += wVal * x4 + x3 + (y[yOff + 4] & M);
- z[zOff + 4] = (int)c;
- c >>>= 32;
- long x5 = x[xOff + 5] & M;
- c += wVal * x5 + x4 + (y[yOff + 5] & M);
- z[zOff + 5] = (int)c;
- c >>>= 32;
- long x6 = x[xOff + 6] & M;
- c += wVal * x6 + x5 + (y[yOff + 6] & M);
- z[zOff + 6] = (int)c;
- c >>>= 32;
- c += x6;
- return c;
- }
-
- public static int mulByWord(int x, int[] z)
- {
- long c = 0, xVal = x & M;
- c += xVal * (z[0] & M);
- z[0] = (int)c;
- c >>>= 32;
- c += xVal * (z[1] & M);
- z[1] = (int)c;
- c >>>= 32;
- c += xVal * (z[2] & M);
- z[2] = (int)c;
- c >>>= 32;
- c += xVal * (z[3] & M);
- z[3] = (int)c;
- c >>>= 32;
- c += xVal * (z[4] & M);
- z[4] = (int)c;
- c >>>= 32;
- c += xVal * (z[5] & M);
- z[5] = (int)c;
- c >>>= 32;
- c += xVal * (z[6] & M);
- z[6] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static int mulByWordAddTo(int x, int[] y, int[] z)
- {
- long c = 0, xVal = x & M;
- c += xVal * (z[0] & M) + (y[0] & M);
- z[0] = (int)c;
- c >>>= 32;
- c += xVal * (z[1] & M) + (y[1] & M);
- z[1] = (int)c;
- c >>>= 32;
- c += xVal * (z[2] & M) + (y[2] & M);
- z[2] = (int)c;
- c >>>= 32;
- c += xVal * (z[3] & M) + (y[3] & M);
- z[3] = (int)c;
- c >>>= 32;
- c += xVal * (z[4] & M) + (y[4] & M);
- z[4] = (int)c;
- c >>>= 32;
- c += xVal * (z[5] & M) + (y[5] & M);
- z[5] = (int)c;
- c >>>= 32;
- c += xVal * (z[6] & M) + (y[6] & M);
- z[6] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static int mulWordAddTo(int x, int[] y, int yOff, int[] z, int zOff)
- {
- long c = 0, xVal = x & M;
- c += xVal * (y[yOff + 0] & M) + (z[zOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>>= 32;
- c += xVal * (y[yOff + 1] & M) + (z[zOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>>= 32;
- c += xVal * (y[yOff + 2] & M) + (z[zOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>>= 32;
- c += xVal * (y[yOff + 3] & M) + (z[zOff + 3] & M);
- z[zOff + 3] = (int)c;
- c >>>= 32;
- c += xVal * (y[yOff + 4] & M) + (z[zOff + 4] & M);
- z[zOff + 4] = (int)c;
- c >>>= 32;
- c += xVal * (y[yOff + 5] & M) + (z[zOff + 5] & M);
- z[zOff + 5] = (int)c;
- c >>>= 32;
- c += xVal * (y[yOff + 6] & M) + (z[zOff + 6] & M);
- z[zOff + 6] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static int mul33DWordAdd(int x, long y, int[] z, int zOff)
- {
- // assert x >>> 31 == 0;
- // assert zOff <= 3;
-
- long c = 0, xVal = x & M;
- long y00 = y & M;
- c += xVal * y00 + (z[zOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>>= 32;
- long y01 = y >>> 32;
- c += xVal * y01 + y00 + (z[zOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>>= 32;
- c += y01 + (z[zOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>>= 32;
- c += (z[zOff + 3] & M);
- z[zOff + 3] = (int)c;
- c >>>= 32;
- return c == 0 ? 0 : Nat.incAt(7, z, zOff, 4);
- }
-
- public static int mul33WordAdd(int x, int y, int[] z, int zOff)
- {
- // assert x >>> 31 == 0;
- // assert zOff <= 4;
-
- long c = 0, xVal = x & M, yVal = y & M;
- c += yVal * xVal + (z[zOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>>= 32;
- c += yVal + (z[zOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>>= 32;
- c += (z[zOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>>= 32;
- return c == 0 ? 0 : Nat.incAt(7, z, zOff, 3);
- }
-
- public static int mulWordDwordAdd(int x, long y, int[] z, int zOff)
- {
- // assert zOff <= 4;
- long c = 0, xVal = x & M;
- c += xVal * (y & M) + (z[zOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>>= 32;
- c += xVal * (y >>> 32) + (z[zOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>>= 32;
- c += (z[zOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>>= 32;
- return c == 0 ? 0 : Nat.incAt(7, z, zOff, 3);
- }
-
- public static int mulWord(int x, int[] y, int[] z, int zOff)
- {
- long c = 0, xVal = x & M;
- int i = 0;
- do
- {
- c += xVal * (y[i] & M);
- z[zOff + i] = (int)c;
- c >>>= 32;
- }
- while (++i < 7);
- return (int)c;
- }
-
- public static void square(int[] x, int[] zz)
- {
- long x_0 = x[0] & M;
- long zz_1;
-
- int c = 0, w;
- {
- int i = 6, j = 14;
- do
- {
- long xVal = (x[i--] & M);
- long p = xVal * xVal;
- zz[--j] = (c << 31) | (int)(p >>> 33);
- zz[--j] = (int)(p >>> 1);
- c = (int)p;
- }
- while (i > 0);
-
- {
- long p = x_0 * x_0;
- zz_1 = ((c << 31) & M) | (p >>> 33);
- zz[0] = (int)p;
- c = (int)(p >>> 32) & 1;
- }
- }
-
- long x_1 = x[1] & M;
- long zz_2 = zz[2] & M;
-
- {
- zz_1 += x_1 * x_0;
- w = (int)zz_1;
- zz[1] = (w << 1) | c;
- c = w >>> 31;
- zz_2 += zz_1 >>> 32;
- }
-
- long x_2 = x[2] & M;
- long zz_3 = zz[3] & M;
- long zz_4 = zz[4] & M;
- {
- zz_2 += x_2 * x_0;
- w = (int)zz_2;
- zz[2] = (w << 1) | c;
- c = w >>> 31;
- zz_3 += (zz_2 >>> 32) + x_2 * x_1;
- zz_4 += zz_3 >>> 32;
- zz_3 &= M;
- }
-
- long x_3 = x[3] & M;
- long zz_5 = zz[5] & M;
- long zz_6 = zz[6] & M;
- {
- zz_3 += x_3 * x_0;
- w = (int)zz_3;
- zz[3] = (w << 1) | c;
- c = w >>> 31;
- zz_4 += (zz_3 >>> 32) + x_3 * x_1;
- zz_5 += (zz_4 >>> 32) + x_3 * x_2;
- zz_4 &= M;
- zz_6 += zz_5 >>> 32;
- zz_5 &= M;
- }
-
- long x_4 = x[4] & M;
- long zz_7 = zz[7] & M;
- long zz_8 = zz[8] & M;
- {
- zz_4 += x_4 * x_0;
- w = (int)zz_4;
- zz[4] = (w << 1) | c;
- c = w >>> 31;
- zz_5 += (zz_4 >>> 32) + x_4 * x_1;
- zz_6 += (zz_5 >>> 32) + x_4 * x_2;
- zz_5 &= M;
- zz_7 += (zz_6 >>> 32) + x_4 * x_3;
- zz_6 &= M;
- zz_8 += zz_7 >>> 32;
- zz_7 &= M;
- }
-
- long x_5 = x[5] & M;
- long zz_9 = zz[9] & M;
- long zz_10 = zz[10] & M;
- {
- zz_5 += x_5 * x_0;
- w = (int)zz_5;
- zz[5] = (w << 1) | c;
- c = w >>> 31;
- zz_6 += (zz_5 >>> 32) + x_5 * x_1;
- zz_7 += (zz_6 >>> 32) + x_5 * x_2;
- zz_6 &= M;
- zz_8 += (zz_7 >>> 32) + x_5 * x_3;
- zz_7 &= M;
- zz_9 += (zz_8 >>> 32) + x_5 * x_4;
- zz_8 &= M;
- zz_10 += zz_9 >>> 32;
- zz_9 &= M;
- }
-
- long x_6 = x[6] & M;
- long zz_11 = zz[11] & M;
- long zz_12 = zz[12] & M;
- {
- zz_6 += x_6 * x_0;
- w = (int)zz_6;
- zz[6] = (w << 1) | c;
- c = w >>> 31;
- zz_7 += (zz_6 >>> 32) + x_6 * x_1;
- zz_8 += (zz_7 >>> 32) + x_6 * x_2;
- zz_9 += (zz_8 >>> 32) + x_6 * x_3;
- zz_10 += (zz_9 >>> 32) + x_6 * x_4;
- zz_11 += (zz_10 >>> 32) + x_6 * x_5;
- zz_12 += zz_11 >>> 32;
- }
-
- w = (int)zz_7;
- zz[7] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_8;
- zz[8] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_9;
- zz[9] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_10;
- zz[10] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_11;
- zz[11] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_12;
- zz[12] = (w << 1) | c;
- c = w >>> 31;
- w = zz[13] + (int)(zz_12 >> 32);
- zz[13] = (w << 1) | c;
- }
-
- public static void square(int[] x, int xOff, int[] zz, int zzOff)
- {
- long x_0 = x[xOff + 0] & M;
- long zz_1;
-
- int c = 0, w;
- {
- int i = 6, j = 14;
- do
- {
- long xVal = (x[xOff + i--] & M);
- long p = xVal * xVal;
- zz[zzOff + --j] = (c << 31) | (int)(p >>> 33);
- zz[zzOff + --j] = (int)(p >>> 1);
- c = (int)p;
- }
- while (i > 0);
-
- {
- long p = x_0 * x_0;
- zz_1 = ((c << 31) & M) | (p >>> 33);
- zz[zzOff + 0] = (int)p;
- c = (int)(p >>> 32) & 1;
- }
- }
-
- long x_1 = x[xOff + 1] & M;
- long zz_2 = zz[zzOff + 2] & M;
-
- {
- zz_1 += x_1 * x_0;
- w = (int)zz_1;
- zz[zzOff + 1] = (w << 1) | c;
- c = w >>> 31;
- zz_2 += zz_1 >>> 32;
- }
-
- long x_2 = x[xOff + 2] & M;
- long zz_3 = zz[zzOff + 3] & M;
- long zz_4 = zz[zzOff + 4] & M;
- {
- zz_2 += x_2 * x_0;
- w = (int)zz_2;
- zz[zzOff + 2] = (w << 1) | c;
- c = w >>> 31;
- zz_3 += (zz_2 >>> 32) + x_2 * x_1;
- zz_4 += zz_3 >>> 32;
- zz_3 &= M;
- }
-
- long x_3 = x[xOff + 3] & M;
- long zz_5 = zz[zzOff + 5] & M;
- long zz_6 = zz[zzOff + 6] & M;
- {
- zz_3 += x_3 * x_0;
- w = (int)zz_3;
- zz[zzOff + 3] = (w << 1) | c;
- c = w >>> 31;
- zz_4 += (zz_3 >>> 32) + x_3 * x_1;
- zz_5 += (zz_4 >>> 32) + x_3 * x_2;
- zz_4 &= M;
- zz_6 += zz_5 >>> 32;
- zz_5 &= M;
- }
-
- long x_4 = x[xOff + 4] & M;
- long zz_7 = zz[zzOff + 7] & M;
- long zz_8 = zz[zzOff + 8] & M;
- {
- zz_4 += x_4 * x_0;
- w = (int)zz_4;
- zz[zzOff + 4] = (w << 1) | c;
- c = w >>> 31;
- zz_5 += (zz_4 >>> 32) + x_4 * x_1;
- zz_6 += (zz_5 >>> 32) + x_4 * x_2;
- zz_5 &= M;
- zz_7 += (zz_6 >>> 32) + x_4 * x_3;
- zz_6 &= M;
- zz_8 += zz_7 >>> 32;
- zz_7 &= M;
- }
-
- long x_5 = x[xOff + 5] & M;
- long zz_9 = zz[zzOff + 9] & M;
- long zz_10 = zz[zzOff + 10] & M;
- {
- zz_5 += x_5 * x_0;
- w = (int)zz_5;
- zz[zzOff + 5] = (w << 1) | c;
- c = w >>> 31;
- zz_6 += (zz_5 >>> 32) + x_5 * x_1;
- zz_7 += (zz_6 >>> 32) + x_5 * x_2;
- zz_6 &= M;
- zz_8 += (zz_7 >>> 32) + x_5 * x_3;
- zz_7 &= M;
- zz_9 += (zz_8 >>> 32) + x_5 * x_4;
- zz_8 &= M;
- zz_10 += zz_9 >>> 32;
- zz_9 &= M;
- }
-
- long x_6 = x[xOff + 6] & M;
- long zz_11 = zz[zzOff + 11] & M;
- long zz_12 = zz[zzOff + 12] & M;
- {
- zz_6 += x_6 * x_0;
- w = (int)zz_6;
- zz[zzOff + 6] = (w << 1) | c;
- c = w >>> 31;
- zz_7 += (zz_6 >>> 32) + x_6 * x_1;
- zz_8 += (zz_7 >>> 32) + x_6 * x_2;
- zz_9 += (zz_8 >>> 32) + x_6 * x_3;
- zz_10 += (zz_9 >>> 32) + x_6 * x_4;
- zz_11 += (zz_10 >>> 32) + x_6 * x_5;
- zz_12 += zz_11 >>> 32;
- }
-
- w = (int)zz_7;
- zz[zzOff + 7] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_8;
- zz[zzOff + 8] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_9;
- zz[zzOff + 9] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_10;
- zz[zzOff + 10] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_11;
- zz[zzOff + 11] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_12;
- zz[zzOff + 12] = (w << 1) | c;
- c = w >>> 31;
- w = zz[zzOff + 13] + (int)(zz_12 >> 32);
- zz[zzOff + 13] = (w << 1) | c;
- }
-
- public static int sub(int[] x, int[] y, int[] z)
- {
- long c = 0;
- c += (x[0] & M) - (y[0] & M);
- z[0] = (int)c;
- c >>= 32;
- c += (x[1] & M) - (y[1] & M);
- z[1] = (int)c;
- c >>= 32;
- c += (x[2] & M) - (y[2] & M);
- z[2] = (int)c;
- c >>= 32;
- c += (x[3] & M) - (y[3] & M);
- z[3] = (int)c;
- c >>= 32;
- c += (x[4] & M) - (y[4] & M);
- z[4] = (int)c;
- c >>= 32;
- c += (x[5] & M) - (y[5] & M);
- z[5] = (int)c;
- c >>= 32;
- c += (x[6] & M) - (y[6] & M);
- z[6] = (int)c;
- c >>= 32;
- return (int)c;
- }
-
- public static int sub(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
- {
- long c = 0;
- c += (x[xOff + 0] & M) - (y[yOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>= 32;
- c += (x[xOff + 1] & M) - (y[yOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>= 32;
- c += (x[xOff + 2] & M) - (y[yOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>= 32;
- c += (x[xOff + 3] & M) - (y[yOff + 3] & M);
- z[zOff + 3] = (int)c;
- c >>= 32;
- c += (x[xOff + 4] & M) - (y[yOff + 4] & M);
- z[zOff + 4] = (int)c;
- c >>= 32;
- c += (x[xOff + 5] & M) - (y[yOff + 5] & M);
- z[zOff + 5] = (int)c;
- c >>= 32;
- c += (x[xOff + 6] & M) - (y[yOff + 6] & M);
- z[zOff + 6] = (int)c;
- c >>= 32;
- return (int)c;
- }
-
- public static int subBothFrom(int[] x, int[] y, int[] z)
- {
- long c = 0;
- c += (z[0] & M) - (x[0] & M) - (y[0] & M);
- z[0] = (int)c;
- c >>= 32;
- c += (z[1] & M) - (x[1] & M) - (y[1] & M);
- z[1] = (int)c;
- c >>= 32;
- c += (z[2] & M) - (x[2] & M) - (y[2] & M);
- z[2] = (int)c;
- c >>= 32;
- c += (z[3] & M) - (x[3] & M) - (y[3] & M);
- z[3] = (int)c;
- c >>= 32;
- c += (z[4] & M) - (x[4] & M) - (y[4] & M);
- z[4] = (int)c;
- c >>= 32;
- c += (z[5] & M) - (x[5] & M) - (y[5] & M);
- z[5] = (int)c;
- c >>= 32;
- c += (z[6] & M) - (x[6] & M) - (y[6] & M);
- z[6] = (int)c;
- c >>= 32;
- return (int)c;
- }
-
- public static int subFrom(int[] x, int[] z)
- {
- long c = 0;
- c += (z[0] & M) - (x[0] & M);
- z[0] = (int)c;
- c >>= 32;
- c += (z[1] & M) - (x[1] & M);
- z[1] = (int)c;
- c >>= 32;
- c += (z[2] & M) - (x[2] & M);
- z[2] = (int)c;
- c >>= 32;
- c += (z[3] & M) - (x[3] & M);
- z[3] = (int)c;
- c >>= 32;
- c += (z[4] & M) - (x[4] & M);
- z[4] = (int)c;
- c >>= 32;
- c += (z[5] & M) - (x[5] & M);
- z[5] = (int)c;
- c >>= 32;
- c += (z[6] & M) - (x[6] & M);
- z[6] = (int)c;
- c >>= 32;
- return (int)c;
- }
-
- public static int subFrom(int[] x, int xOff, int[] z, int zOff)
- {
- long c = 0;
- c += (z[zOff + 0] & M) - (x[xOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>= 32;
- c += (z[zOff + 1] & M) - (x[xOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>= 32;
- c += (z[zOff + 2] & M) - (x[xOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>= 32;
- c += (z[zOff + 3] & M) - (x[xOff + 3] & M);
- z[zOff + 3] = (int)c;
- c >>= 32;
- c += (z[zOff + 4] & M) - (x[xOff + 4] & M);
- z[zOff + 4] = (int)c;
- c >>= 32;
- c += (z[zOff + 5] & M) - (x[xOff + 5] & M);
- z[zOff + 5] = (int)c;
- c >>= 32;
- c += (z[zOff + 6] & M) - (x[xOff + 6] & M);
- z[zOff + 6] = (int)c;
- c >>= 32;
- return (int)c;
- }
-
- public static BigInteger toBigInteger(int[] x)
- {
- byte[] bs = new byte[28];
- for (int i = 0; i < 7; ++i)
- {
- int x_i = x[i];
- if (x_i != 0)
- {
- Pack.intToBigEndian(x_i, bs, (6 - i) << 2);
- }
- }
- return new BigInteger(1, bs);
- }
-
- public static void zero(int[] z)
- {
- z[0] = 0;
- z[1] = 0;
- z[2] = 0;
- z[3] = 0;
- z[4] = 0;
- z[5] = 0;
- z[6] = 0;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/raw/Nat256.java b/core/src/main/java/org/bouncycastle/math/raw/Nat256.java
deleted file mode 100644
index 9886678a..00000000
--- a/core/src/main/java/org/bouncycastle/math/raw/Nat256.java
+++ /dev/null
@@ -1,1306 +0,0 @@
-package org.bouncycastle.math.raw;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.util.Pack;
-
-public abstract class Nat256
-{
- private static final long M = 0xFFFFFFFFL;
-
- public static int add(int[] x, int[] y, int[] z)
- {
- long c = 0;
- c += (x[0] & M) + (y[0] & M);
- z[0] = (int)c;
- c >>>= 32;
- c += (x[1] & M) + (y[1] & M);
- z[1] = (int)c;
- c >>>= 32;
- c += (x[2] & M) + (y[2] & M);
- z[2] = (int)c;
- c >>>= 32;
- c += (x[3] & M) + (y[3] & M);
- z[3] = (int)c;
- c >>>= 32;
- c += (x[4] & M) + (y[4] & M);
- z[4] = (int)c;
- c >>>= 32;
- c += (x[5] & M) + (y[5] & M);
- z[5] = (int)c;
- c >>>= 32;
- c += (x[6] & M) + (y[6] & M);
- z[6] = (int)c;
- c >>>= 32;
- c += (x[7] & M) + (y[7] & M);
- z[7] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static int add(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
- {
- long c = 0;
- c += (x[xOff + 0] & M) + (y[yOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>>= 32;
- c += (x[xOff + 1] & M) + (y[yOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>>= 32;
- c += (x[xOff + 2] & M) + (y[yOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>>= 32;
- c += (x[xOff + 3] & M) + (y[yOff + 3] & M);
- z[zOff + 3] = (int)c;
- c >>>= 32;
- c += (x[xOff + 4] & M) + (y[yOff + 4] & M);
- z[zOff + 4] = (int)c;
- c >>>= 32;
- c += (x[xOff + 5] & M) + (y[yOff + 5] & M);
- z[zOff + 5] = (int)c;
- c >>>= 32;
- c += (x[xOff + 6] & M) + (y[yOff + 6] & M);
- z[zOff + 6] = (int)c;
- c >>>= 32;
- c += (x[xOff + 7] & M) + (y[yOff + 7] & M);
- z[zOff + 7] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static int addBothTo(int[] x, int[] y, int[] z)
- {
- long c = 0;
- c += (x[0] & M) + (y[0] & M) + (z[0] & M);
- z[0] = (int)c;
- c >>>= 32;
- c += (x[1] & M) + (y[1] & M) + (z[1] & M);
- z[1] = (int)c;
- c >>>= 32;
- c += (x[2] & M) + (y[2] & M) + (z[2] & M);
- z[2] = (int)c;
- c >>>= 32;
- c += (x[3] & M) + (y[3] & M) + (z[3] & M);
- z[3] = (int)c;
- c >>>= 32;
- c += (x[4] & M) + (y[4] & M) + (z[4] & M);
- z[4] = (int)c;
- c >>>= 32;
- c += (x[5] & M) + (y[5] & M) + (z[5] & M);
- z[5] = (int)c;
- c >>>= 32;
- c += (x[6] & M) + (y[6] & M) + (z[6] & M);
- z[6] = (int)c;
- c >>>= 32;
- c += (x[7] & M) + (y[7] & M) + (z[7] & M);
- z[7] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static int addBothTo(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
- {
- long c = 0;
- c += (x[xOff + 0] & M) + (y[yOff + 0] & M) + (z[zOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>>= 32;
- c += (x[xOff + 1] & M) + (y[yOff + 1] & M) + (z[zOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>>= 32;
- c += (x[xOff + 2] & M) + (y[yOff + 2] & M) + (z[zOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>>= 32;
- c += (x[xOff + 3] & M) + (y[yOff + 3] & M) + (z[zOff + 3] & M);
- z[zOff + 3] = (int)c;
- c >>>= 32;
- c += (x[xOff + 4] & M) + (y[yOff + 4] & M) + (z[zOff + 4] & M);
- z[zOff + 4] = (int)c;
- c >>>= 32;
- c += (x[xOff + 5] & M) + (y[yOff + 5] & M) + (z[zOff + 5] & M);
- z[zOff + 5] = (int)c;
- c >>>= 32;
- c += (x[xOff + 6] & M) + (y[yOff + 6] & M) + (z[zOff + 6] & M);
- z[zOff + 6] = (int)c;
- c >>>= 32;
- c += (x[xOff + 7] & M) + (y[yOff + 7] & M) + (z[zOff + 7] & M);
- z[zOff + 7] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static int addTo(int[] x, int[] z)
- {
- long c = 0;
- c += (x[0] & M) + (z[0] & M);
- z[0] = (int)c;
- c >>>= 32;
- c += (x[1] & M) + (z[1] & M);
- z[1] = (int)c;
- c >>>= 32;
- c += (x[2] & M) + (z[2] & M);
- z[2] = (int)c;
- c >>>= 32;
- c += (x[3] & M) + (z[3] & M);
- z[3] = (int)c;
- c >>>= 32;
- c += (x[4] & M) + (z[4] & M);
- z[4] = (int)c;
- c >>>= 32;
- c += (x[5] & M) + (z[5] & M);
- z[5] = (int)c;
- c >>>= 32;
- c += (x[6] & M) + (z[6] & M);
- z[6] = (int)c;
- c >>>= 32;
- c += (x[7] & M) + (z[7] & M);
- z[7] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static int addTo(int[] x, int xOff, int[] z, int zOff, int cIn)
- {
- long c = cIn & M;
- c += (x[xOff + 0] & M) + (z[zOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>>= 32;
- c += (x[xOff + 1] & M) + (z[zOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>>= 32;
- c += (x[xOff + 2] & M) + (z[zOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>>= 32;
- c += (x[xOff + 3] & M) + (z[zOff + 3] & M);
- z[zOff + 3] = (int)c;
- c >>>= 32;
- c += (x[xOff + 4] & M) + (z[zOff + 4] & M);
- z[zOff + 4] = (int)c;
- c >>>= 32;
- c += (x[xOff + 5] & M) + (z[zOff + 5] & M);
- z[zOff + 5] = (int)c;
- c >>>= 32;
- c += (x[xOff + 6] & M) + (z[zOff + 6] & M);
- z[zOff + 6] = (int)c;
- c >>>= 32;
- c += (x[xOff + 7] & M) + (z[zOff + 7] & M);
- z[zOff + 7] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static int addToEachOther(int[] u, int uOff, int[] v, int vOff)
- {
- long c = 0;
- c += (u[uOff + 0] & M) + (v[vOff + 0] & M);
- u[uOff + 0] = (int)c;
- v[vOff + 0] = (int)c;
- c >>>= 32;
- c += (u[uOff + 1] & M) + (v[vOff + 1] & M);
- u[uOff + 1] = (int)c;
- v[vOff + 1] = (int)c;
- c >>>= 32;
- c += (u[uOff + 2] & M) + (v[vOff + 2] & M);
- u[uOff + 2] = (int)c;
- v[vOff + 2] = (int)c;
- c >>>= 32;
- c += (u[uOff + 3] & M) + (v[vOff + 3] & M);
- u[uOff + 3] = (int)c;
- v[vOff + 3] = (int)c;
- c >>>= 32;
- c += (u[uOff + 4] & M) + (v[vOff + 4] & M);
- u[uOff + 4] = (int)c;
- v[vOff + 4] = (int)c;
- c >>>= 32;
- c += (u[uOff + 5] & M) + (v[vOff + 5] & M);
- u[uOff + 5] = (int)c;
- v[vOff + 5] = (int)c;
- c >>>= 32;
- c += (u[uOff + 6] & M) + (v[vOff + 6] & M);
- u[uOff + 6] = (int)c;
- v[vOff + 6] = (int)c;
- c >>>= 32;
- c += (u[uOff + 7] & M) + (v[vOff + 7] & M);
- u[uOff + 7] = (int)c;
- v[vOff + 7] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static void copy(int[] x, int[] z)
- {
- z[0] = x[0];
- z[1] = x[1];
- z[2] = x[2];
- z[3] = x[3];
- z[4] = x[4];
- z[5] = x[5];
- z[6] = x[6];
- z[7] = x[7];
- }
-
- public static int[] create()
- {
- return new int[8];
- }
-
- public static int[] createExt()
- {
- return new int[16];
- }
-
- public static boolean diff(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
- {
- boolean pos = gte(x, xOff, y, yOff);
- if (pos)
- {
- sub(x, xOff, y, yOff, z, zOff);
- }
- else
- {
- sub(y, yOff, x, xOff, z, zOff);
- }
- return pos;
- }
-
- public static boolean eq(int[] x, int[] y)
- {
- for (int i = 7; i >= 0; --i)
- {
- if (x[i] != y[i])
- {
- return false;
- }
- }
- return true;
- }
-
- public static int[] fromBigInteger(BigInteger x)
- {
- if (x.signum() < 0 || x.bitLength() > 256)
- {
- throw new IllegalArgumentException();
- }
-
- int[] z = create();
- int i = 0;
- while (x.signum() != 0)
- {
- z[i++] = x.intValue();
- x = x.shiftRight(32);
- }
- return z;
- }
-
- public static int getBit(int[] x, int bit)
- {
- if (bit == 0)
- {
- return x[0] & 1;
- }
- if ((bit & 255) != bit)
- {
- return 0;
- }
- int w = bit >>> 5;
- int b = bit & 31;
- return (x[w] >>> b) & 1;
- }
-
- public static boolean gte(int[] x, int[] y)
- {
- for (int i = 7; i >= 0; --i)
- {
- int x_i = x[i] ^ Integer.MIN_VALUE;
- int y_i = y[i] ^ Integer.MIN_VALUE;
- if (x_i < y_i)
- return false;
- if (x_i > y_i)
- return true;
- }
- return true;
- }
-
- public static boolean gte(int[] x, int xOff, int[] y, int yOff)
- {
- for (int i = 7; i >= 0; --i)
- {
- int x_i = x[xOff + i] ^ Integer.MIN_VALUE;
- int y_i = y[yOff + i] ^ Integer.MIN_VALUE;
- if (x_i < y_i)
- return false;
- if (x_i > y_i)
- return true;
- }
- return true;
- }
-
- public static boolean isOne(int[] x)
- {
- if (x[0] != 1)
- {
- return false;
- }
- for (int i = 1; i < 8; ++i)
- {
- if (x[i] != 0)
- {
- return false;
- }
- }
- return true;
- }
-
- public static boolean isZero(int[] x)
- {
- for (int i = 0; i < 8; ++i)
- {
- if (x[i] != 0)
- {
- return false;
- }
- }
- return true;
- }
-
- public static void mul(int[] x, int[] y, int[] zz)
- {
- long y_0 = y[0] & M;
- long y_1 = y[1] & M;
- long y_2 = y[2] & M;
- long y_3 = y[3] & M;
- long y_4 = y[4] & M;
- long y_5 = y[5] & M;
- long y_6 = y[6] & M;
- long y_7 = y[7] & M;
-
- {
- long c = 0, x_0 = x[0] & M;
- c += x_0 * y_0;
- zz[0] = (int)c;
- c >>>= 32;
- c += x_0 * y_1;
- zz[1] = (int)c;
- c >>>= 32;
- c += x_0 * y_2;
- zz[2] = (int)c;
- c >>>= 32;
- c += x_0 * y_3;
- zz[3] = (int)c;
- c >>>= 32;
- c += x_0 * y_4;
- zz[4] = (int)c;
- c >>>= 32;
- c += x_0 * y_5;
- zz[5] = (int)c;
- c >>>= 32;
- c += x_0 * y_6;
- zz[6] = (int)c;
- c >>>= 32;
- c += x_0 * y_7;
- zz[7] = (int)c;
- c >>>= 32;
- zz[8] = (int)c;
- }
-
- for (int i = 1; i < 8; ++i)
- {
- long c = 0, x_i = x[i] & M;
- c += x_i * y_0 + (zz[i + 0] & M);
- zz[i + 0] = (int)c;
- c >>>= 32;
- c += x_i * y_1 + (zz[i + 1] & M);
- zz[i + 1] = (int)c;
- c >>>= 32;
- c += x_i * y_2 + (zz[i + 2] & M);
- zz[i + 2] = (int)c;
- c >>>= 32;
- c += x_i * y_3 + (zz[i + 3] & M);
- zz[i + 3] = (int)c;
- c >>>= 32;
- c += x_i * y_4 + (zz[i + 4] & M);
- zz[i + 4] = (int)c;
- c >>>= 32;
- c += x_i * y_5 + (zz[i + 5] & M);
- zz[i + 5] = (int)c;
- c >>>= 32;
- c += x_i * y_6 + (zz[i + 6] & M);
- zz[i + 6] = (int)c;
- c >>>= 32;
- c += x_i * y_7 + (zz[i + 7] & M);
- zz[i + 7] = (int)c;
- c >>>= 32;
- zz[i + 8] = (int)c;
- }
- }
-
- public static void mul(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
- {
- long y_0 = y[yOff + 0] & M;
- long y_1 = y[yOff + 1] & M;
- long y_2 = y[yOff + 2] & M;
- long y_3 = y[yOff + 3] & M;
- long y_4 = y[yOff + 4] & M;
- long y_5 = y[yOff + 5] & M;
- long y_6 = y[yOff + 6] & M;
- long y_7 = y[yOff + 7] & M;
-
- {
- long c = 0, x_0 = x[xOff + 0] & M;
- c += x_0 * y_0;
- zz[zzOff + 0] = (int)c;
- c >>>= 32;
- c += x_0 * y_1;
- zz[zzOff + 1] = (int)c;
- c >>>= 32;
- c += x_0 * y_2;
- zz[zzOff + 2] = (int)c;
- c >>>= 32;
- c += x_0 * y_3;
- zz[zzOff + 3] = (int)c;
- c >>>= 32;
- c += x_0 * y_4;
- zz[zzOff + 4] = (int)c;
- c >>>= 32;
- c += x_0 * y_5;
- zz[zzOff + 5] = (int)c;
- c >>>= 32;
- c += x_0 * y_6;
- zz[zzOff + 6] = (int)c;
- c >>>= 32;
- c += x_0 * y_7;
- zz[zzOff + 7] = (int)c;
- c >>>= 32;
- zz[zzOff + 8] = (int)c;
- }
-
- for (int i = 1; i < 8; ++i)
- {
- ++zzOff;
- long c = 0, x_i = x[xOff + i] & M;
- c += x_i * y_0 + (zz[zzOff + 0] & M);
- zz[zzOff + 0] = (int)c;
- c >>>= 32;
- c += x_i * y_1 + (zz[zzOff + 1] & M);
- zz[zzOff + 1] = (int)c;
- c >>>= 32;
- c += x_i * y_2 + (zz[zzOff + 2] & M);
- zz[zzOff + 2] = (int)c;
- c >>>= 32;
- c += x_i * y_3 + (zz[zzOff + 3] & M);
- zz[zzOff + 3] = (int)c;
- c >>>= 32;
- c += x_i * y_4 + (zz[zzOff + 4] & M);
- zz[zzOff + 4] = (int)c;
- c >>>= 32;
- c += x_i * y_5 + (zz[zzOff + 5] & M);
- zz[zzOff + 5] = (int)c;
- c >>>= 32;
- c += x_i * y_6 + (zz[zzOff + 6] & M);
- zz[zzOff + 6] = (int)c;
- c >>>= 32;
- c += x_i * y_7 + (zz[zzOff + 7] & M);
- zz[zzOff + 7] = (int)c;
- c >>>= 32;
- zz[zzOff + 8] = (int)c;
- }
- }
-
- public static int mulAddTo(int[] x, int[] y, int[] zz)
- {
- long y_0 = y[0] & M;
- long y_1 = y[1] & M;
- long y_2 = y[2] & M;
- long y_3 = y[3] & M;
- long y_4 = y[4] & M;
- long y_5 = y[5] & M;
- long y_6 = y[6] & M;
- long y_7 = y[7] & M;
-
- long zc = 0;
- for (int i = 0; i < 8; ++i)
- {
- long c = 0, x_i = x[i] & M;
- c += x_i * y_0 + (zz[i + 0] & M);
- zz[i + 0] = (int)c;
- c >>>= 32;
- c += x_i * y_1 + (zz[i + 1] & M);
- zz[i + 1] = (int)c;
- c >>>= 32;
- c += x_i * y_2 + (zz[i + 2] & M);
- zz[i + 2] = (int)c;
- c >>>= 32;
- c += x_i * y_3 + (zz[i + 3] & M);
- zz[i + 3] = (int)c;
- c >>>= 32;
- c += x_i * y_4 + (zz[i + 4] & M);
- zz[i + 4] = (int)c;
- c >>>= 32;
- c += x_i * y_5 + (zz[i + 5] & M);
- zz[i + 5] = (int)c;
- c >>>= 32;
- c += x_i * y_6 + (zz[i + 6] & M);
- zz[i + 6] = (int)c;
- c >>>= 32;
- c += x_i * y_7 + (zz[i + 7] & M);
- zz[i + 7] = (int)c;
- c >>>= 32;
- c += zc + (zz[i + 8] & M);
- zz[i + 8] = (int)c;
- zc = c >>> 32;
- }
- return (int)zc;
- }
-
- public static int mulAddTo(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
- {
- long y_0 = y[yOff + 0] & M;
- long y_1 = y[yOff + 1] & M;
- long y_2 = y[yOff + 2] & M;
- long y_3 = y[yOff + 3] & M;
- long y_4 = y[yOff + 4] & M;
- long y_5 = y[yOff + 5] & M;
- long y_6 = y[yOff + 6] & M;
- long y_7 = y[yOff + 7] & M;
-
- long zc = 0;
- for (int i = 0; i < 8; ++i)
- {
- long c = 0, x_i = x[xOff + i] & M;
- c += x_i * y_0 + (zz[zzOff + 0] & M);
- zz[zzOff + 0] = (int)c;
- c >>>= 32;
- c += x_i * y_1 + (zz[zzOff + 1] & M);
- zz[zzOff + 1] = (int)c;
- c >>>= 32;
- c += x_i * y_2 + (zz[zzOff + 2] & M);
- zz[zzOff + 2] = (int)c;
- c >>>= 32;
- c += x_i * y_3 + (zz[zzOff + 3] & M);
- zz[zzOff + 3] = (int)c;
- c >>>= 32;
- c += x_i * y_4 + (zz[zzOff + 4] & M);
- zz[zzOff + 4] = (int)c;
- c >>>= 32;
- c += x_i * y_5 + (zz[zzOff + 5] & M);
- zz[zzOff + 5] = (int)c;
- c >>>= 32;
- c += x_i * y_6 + (zz[zzOff + 6] & M);
- zz[zzOff + 6] = (int)c;
- c >>>= 32;
- c += x_i * y_7 + (zz[zzOff + 7] & M);
- zz[zzOff + 7] = (int)c;
- c >>>= 32;
- c += zc + (zz[zzOff + 8] & M);
- zz[zzOff + 8] = (int)c;
- zc = c >>> 32;
- ++zzOff;
- }
- return (int)zc;
- }
-
- public static long mul33Add(int w, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
- {
- // assert w >>> 31 == 0;
-
- long c = 0, wVal = w & M;
- long x0 = x[xOff + 0] & M;
- c += wVal * x0 + (y[yOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>>= 32;
- long x1 = x[xOff + 1] & M;
- c += wVal * x1 + x0 + (y[yOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>>= 32;
- long x2 = x[xOff + 2] & M;
- c += wVal * x2 + x1 + (y[yOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>>= 32;
- long x3 = x[xOff + 3] & M;
- c += wVal * x3 + x2 + (y[yOff + 3] & M);
- z[zOff + 3] = (int)c;
- c >>>= 32;
- long x4 = x[xOff + 4] & M;
- c += wVal * x4 + x3 + (y[yOff + 4] & M);
- z[zOff + 4] = (int)c;
- c >>>= 32;
- long x5 = x[xOff + 5] & M;
- c += wVal * x5 + x4 + (y[yOff + 5] & M);
- z[zOff + 5] = (int)c;
- c >>>= 32;
- long x6 = x[xOff + 6] & M;
- c += wVal * x6 + x5 + (y[yOff + 6] & M);
- z[zOff + 6] = (int)c;
- c >>>= 32;
- long x7 = x[xOff + 7] & M;
- c += wVal * x7 + x6 + (y[yOff + 7] & M);
- z[zOff + 7] = (int)c;
- c >>>= 32;
- c += x7;
- return c;
- }
-
- public static int mulByWord(int x, int[] z)
- {
- long c = 0, xVal = x & M;
- c += xVal * (z[0] & M);
- z[0] = (int)c;
- c >>>= 32;
- c += xVal * (z[1] & M);
- z[1] = (int)c;
- c >>>= 32;
- c += xVal * (z[2] & M);
- z[2] = (int)c;
- c >>>= 32;
- c += xVal * (z[3] & M);
- z[3] = (int)c;
- c >>>= 32;
- c += xVal * (z[4] & M);
- z[4] = (int)c;
- c >>>= 32;
- c += xVal * (z[5] & M);
- z[5] = (int)c;
- c >>>= 32;
- c += xVal * (z[6] & M);
- z[6] = (int)c;
- c >>>= 32;
- c += xVal * (z[7] & M);
- z[7] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static int mulByWordAddTo(int x, int[] y, int[] z)
- {
- long c = 0, xVal = x & M;
- c += xVal * (z[0] & M) + (y[0] & M);
- z[0] = (int)c;
- c >>>= 32;
- c += xVal * (z[1] & M) + (y[1] & M);
- z[1] = (int)c;
- c >>>= 32;
- c += xVal * (z[2] & M) + (y[2] & M);
- z[2] = (int)c;
- c >>>= 32;
- c += xVal * (z[3] & M) + (y[3] & M);
- z[3] = (int)c;
- c >>>= 32;
- c += xVal * (z[4] & M) + (y[4] & M);
- z[4] = (int)c;
- c >>>= 32;
- c += xVal * (z[5] & M) + (y[5] & M);
- z[5] = (int)c;
- c >>>= 32;
- c += xVal * (z[6] & M) + (y[6] & M);
- z[6] = (int)c;
- c >>>= 32;
- c += xVal * (z[7] & M) + (y[7] & M);
- z[7] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static int mulWordAddTo(int x, int[] y, int yOff, int[] z, int zOff)
- {
- long c = 0, xVal = x & M;
- c += xVal * (y[yOff + 0] & M) + (z[zOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>>= 32;
- c += xVal * (y[yOff + 1] & M) + (z[zOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>>= 32;
- c += xVal * (y[yOff + 2] & M) + (z[zOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>>= 32;
- c += xVal * (y[yOff + 3] & M) + (z[zOff + 3] & M);
- z[zOff + 3] = (int)c;
- c >>>= 32;
- c += xVal * (y[yOff + 4] & M) + (z[zOff + 4] & M);
- z[zOff + 4] = (int)c;
- c >>>= 32;
- c += xVal * (y[yOff + 5] & M) + (z[zOff + 5] & M);
- z[zOff + 5] = (int)c;
- c >>>= 32;
- c += xVal * (y[yOff + 6] & M) + (z[zOff + 6] & M);
- z[zOff + 6] = (int)c;
- c >>>= 32;
- c += xVal * (y[yOff + 7] & M) + (z[zOff + 7] & M);
- z[zOff + 7] = (int)c;
- c >>>= 32;
- return (int)c;
- }
-
- public static int mul33DWordAdd(int x, long y, int[] z, int zOff)
- {
- // assert x >>> 31 == 0;
- // assert zOff <= 4;
-
- long c = 0, xVal = x & M;
- long y00 = y & M;
- c += xVal * y00 + (z[zOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>>= 32;
- long y01 = y >>> 32;
- c += xVal * y01 + y00 + (z[zOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>>= 32;
- c += y01 + (z[zOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>>= 32;
- c += (z[zOff + 3] & M);
- z[zOff + 3] = (int)c;
- c >>>= 32;
- return c == 0 ? 0 : Nat.incAt(8, z, zOff, 4);
- }
-
- public static int mul33WordAdd(int x, int y, int[] z, int zOff)
- {
- // assert x >>> 31 == 0;
- // assert zOff <= 5;
-
- long c = 0, xVal = x & M, yVal = y & M;
- c += yVal * xVal + (z[zOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>>= 32;
- c += yVal + (z[zOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>>= 32;
- c += (z[zOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>>= 32;
- return c == 0 ? 0 : Nat.incAt(8, z, zOff, 3);
- }
-
- public static int mulWordDwordAdd(int x, long y, int[] z, int zOff)
- {
- // assert zOff <= 5;
- long c = 0, xVal = x & M;
- c += xVal * (y & M) + (z[zOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>>= 32;
- c += xVal * (y >>> 32) + (z[zOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>>= 32;
- c += (z[zOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>>= 32;
- return c == 0 ? 0 : Nat.incAt(8, z, zOff, 3);
- }
-
- public static int mulWord(int x, int[] y, int[] z, int zOff)
- {
- long c = 0, xVal = x & M;
- int i = 0;
- do
- {
- c += xVal * (y[i] & M);
- z[zOff + i] = (int)c;
- c >>>= 32;
- }
- while (++i < 8);
- return (int)c;
- }
-
- public static void square(int[] x, int[] zz)
- {
- long x_0 = x[0] & M;
- long zz_1;
-
- int c = 0, w;
- {
- int i = 7, j = 16;
- do
- {
- long xVal = (x[i--] & M);
- long p = xVal * xVal;
- zz[--j] = (c << 31) | (int)(p >>> 33);
- zz[--j] = (int)(p >>> 1);
- c = (int)p;
- }
- while (i > 0);
-
- {
- long p = x_0 * x_0;
- zz_1 = ((c << 31) & M) | (p >>> 33);
- zz[0] = (int)p;
- c = (int)(p >>> 32) & 1;
- }
- }
-
- long x_1 = x[1] & M;
- long zz_2 = zz[2] & M;
-
- {
- zz_1 += x_1 * x_0;
- w = (int)zz_1;
- zz[1] = (w << 1) | c;
- c = w >>> 31;
- zz_2 += zz_1 >>> 32;
- }
-
- long x_2 = x[2] & M;
- long zz_3 = zz[3] & M;
- long zz_4 = zz[4] & M;
- {
- zz_2 += x_2 * x_0;
- w = (int)zz_2;
- zz[2] = (w << 1) | c;
- c = w >>> 31;
- zz_3 += (zz_2 >>> 32) + x_2 * x_1;
- zz_4 += zz_3 >>> 32;
- zz_3 &= M;
- }
-
- long x_3 = x[3] & M;
- long zz_5 = zz[5] & M;
- long zz_6 = zz[6] & M;
- {
- zz_3 += x_3 * x_0;
- w = (int)zz_3;
- zz[3] = (w << 1) | c;
- c = w >>> 31;
- zz_4 += (zz_3 >>> 32) + x_3 * x_1;
- zz_5 += (zz_4 >>> 32) + x_3 * x_2;
- zz_4 &= M;
- zz_6 += zz_5 >>> 32;
- zz_5 &= M;
- }
-
- long x_4 = x[4] & M;
- long zz_7 = zz[7] & M;
- long zz_8 = zz[8] & M;
- {
- zz_4 += x_4 * x_0;
- w = (int)zz_4;
- zz[4] = (w << 1) | c;
- c = w >>> 31;
- zz_5 += (zz_4 >>> 32) + x_4 * x_1;
- zz_6 += (zz_5 >>> 32) + x_4 * x_2;
- zz_5 &= M;
- zz_7 += (zz_6 >>> 32) + x_4 * x_3;
- zz_6 &= M;
- zz_8 += zz_7 >>> 32;
- zz_7 &= M;
- }
-
- long x_5 = x[5] & M;
- long zz_9 = zz[9] & M;
- long zz_10 = zz[10] & M;
- {
- zz_5 += x_5 * x_0;
- w = (int)zz_5;
- zz[5] = (w << 1) | c;
- c = w >>> 31;
- zz_6 += (zz_5 >>> 32) + x_5 * x_1;
- zz_7 += (zz_6 >>> 32) + x_5 * x_2;
- zz_6 &= M;
- zz_8 += (zz_7 >>> 32) + x_5 * x_3;
- zz_7 &= M;
- zz_9 += (zz_8 >>> 32) + x_5 * x_4;
- zz_8 &= M;
- zz_10 += zz_9 >>> 32;
- zz_9 &= M;
- }
-
- long x_6 = x[6] & M;
- long zz_11 = zz[11] & M;
- long zz_12 = zz[12] & M;
- {
- zz_6 += x_6 * x_0;
- w = (int)zz_6;
- zz[6] = (w << 1) | c;
- c = w >>> 31;
- zz_7 += (zz_6 >>> 32) + x_6 * x_1;
- zz_8 += (zz_7 >>> 32) + x_6 * x_2;
- zz_7 &= M;
- zz_9 += (zz_8 >>> 32) + x_6 * x_3;
- zz_8 &= M;
- zz_10 += (zz_9 >>> 32) + x_6 * x_4;
- zz_9 &= M;
- zz_11 += (zz_10 >>> 32) + x_6 * x_5;
- zz_10 &= M;
- zz_12 += zz_11 >>> 32;
- zz_11 &= M;
- }
-
- long x_7 = x[7] & M;
- long zz_13 = zz[13] & M;
- long zz_14 = zz[14] & M;
- {
- zz_7 += x_7 * x_0;
- w = (int)zz_7;
- zz[7] = (w << 1) | c;
- c = w >>> 31;
- zz_8 += (zz_7 >>> 32) + x_7 * x_1;
- zz_9 += (zz_8 >>> 32) + x_7 * x_2;
- zz_10 += (zz_9 >>> 32) + x_7 * x_3;
- zz_11 += (zz_10 >>> 32) + x_7 * x_4;
- zz_12 += (zz_11 >>> 32) + x_7 * x_5;
- zz_13 += (zz_12 >>> 32) + x_7 * x_6;
- zz_14 += zz_13 >>> 32;
- }
-
- w = (int)zz_8;
- zz[8] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_9;
- zz[9] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_10;
- zz[10] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_11;
- zz[11] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_12;
- zz[12] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_13;
- zz[13] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_14;
- zz[14] = (w << 1) | c;
- c = w >>> 31;
- w = zz[15] + (int)(zz_14 >> 32);
- zz[15] = (w << 1) | c;
- }
-
- public static void square(int[] x, int xOff, int[] zz, int zzOff)
- {
- long x_0 = x[xOff + 0] & M;
- long zz_1;
-
- int c = 0, w;
- {
- int i = 7, j = 16;
- do
- {
- long xVal = (x[xOff + i--] & M);
- long p = xVal * xVal;
- zz[zzOff + --j] = (c << 31) | (int)(p >>> 33);
- zz[zzOff + --j] = (int)(p >>> 1);
- c = (int)p;
- }
- while (i > 0);
-
- {
- long p = x_0 * x_0;
- zz_1 = ((c << 31) & M) | (p >>> 33);
- zz[zzOff + 0] = (int)p;
- c = (int)(p >>> 32) & 1;
- }
- }
-
- long x_1 = x[xOff + 1] & M;
- long zz_2 = zz[zzOff + 2] & M;
-
- {
- zz_1 += x_1 * x_0;
- w = (int)zz_1;
- zz[zzOff + 1] = (w << 1) | c;
- c = w >>> 31;
- zz_2 += zz_1 >>> 32;
- }
-
- long x_2 = x[xOff + 2] & M;
- long zz_3 = zz[zzOff + 3] & M;
- long zz_4 = zz[zzOff + 4] & M;
- {
- zz_2 += x_2 * x_0;
- w = (int)zz_2;
- zz[zzOff + 2] = (w << 1) | c;
- c = w >>> 31;
- zz_3 += (zz_2 >>> 32) + x_2 * x_1;
- zz_4 += zz_3 >>> 32;
- zz_3 &= M;
- }
-
- long x_3 = x[xOff + 3] & M;
- long zz_5 = zz[zzOff + 5] & M;
- long zz_6 = zz[zzOff + 6] & M;
- {
- zz_3 += x_3 * x_0;
- w = (int)zz_3;
- zz[zzOff + 3] = (w << 1) | c;
- c = w >>> 31;
- zz_4 += (zz_3 >>> 32) + x_3 * x_1;
- zz_5 += (zz_4 >>> 32) + x_3 * x_2;
- zz_4 &= M;
- zz_6 += zz_5 >>> 32;
- zz_5 &= M;
- }
-
- long x_4 = x[xOff + 4] & M;
- long zz_7 = zz[zzOff + 7] & M;
- long zz_8 = zz[zzOff + 8] & M;
- {
- zz_4 += x_4 * x_0;
- w = (int)zz_4;
- zz[zzOff + 4] = (w << 1) | c;
- c = w >>> 31;
- zz_5 += (zz_4 >>> 32) + x_4 * x_1;
- zz_6 += (zz_5 >>> 32) + x_4 * x_2;
- zz_5 &= M;
- zz_7 += (zz_6 >>> 32) + x_4 * x_3;
- zz_6 &= M;
- zz_8 += zz_7 >>> 32;
- zz_7 &= M;
- }
-
- long x_5 = x[xOff + 5] & M;
- long zz_9 = zz[zzOff + 9] & M;
- long zz_10 = zz[zzOff + 10] & M;
- {
- zz_5 += x_5 * x_0;
- w = (int)zz_5;
- zz[zzOff + 5] = (w << 1) | c;
- c = w >>> 31;
- zz_6 += (zz_5 >>> 32) + x_5 * x_1;
- zz_7 += (zz_6 >>> 32) + x_5 * x_2;
- zz_6 &= M;
- zz_8 += (zz_7 >>> 32) + x_5 * x_3;
- zz_7 &= M;
- zz_9 += (zz_8 >>> 32) + x_5 * x_4;
- zz_8 &= M;
- zz_10 += zz_9 >>> 32;
- zz_9 &= M;
- }
-
- long x_6 = x[xOff + 6] & M;
- long zz_11 = zz[zzOff + 11] & M;
- long zz_12 = zz[zzOff + 12] & M;
- {
- zz_6 += x_6 * x_0;
- w = (int)zz_6;
- zz[zzOff + 6] = (w << 1) | c;
- c = w >>> 31;
- zz_7 += (zz_6 >>> 32) + x_6 * x_1;
- zz_8 += (zz_7 >>> 32) + x_6 * x_2;
- zz_7 &= M;
- zz_9 += (zz_8 >>> 32) + x_6 * x_3;
- zz_8 &= M;
- zz_10 += (zz_9 >>> 32) + x_6 * x_4;
- zz_9 &= M;
- zz_11 += (zz_10 >>> 32) + x_6 * x_5;
- zz_10 &= M;
- zz_12 += zz_11 >>> 32;
- zz_11 &= M;
- }
-
- long x_7 = x[xOff + 7] & M;
- long zz_13 = zz[zzOff + 13] & M;
- long zz_14 = zz[zzOff + 14] & M;
- {
- zz_7 += x_7 * x_0;
- w = (int)zz_7;
- zz[zzOff + 7] = (w << 1) | c;
- c = w >>> 31;
- zz_8 += (zz_7 >>> 32) + x_7 * x_1;
- zz_9 += (zz_8 >>> 32) + x_7 * x_2;
- zz_10 += (zz_9 >>> 32) + x_7 * x_3;
- zz_11 += (zz_10 >>> 32) + x_7 * x_4;
- zz_12 += (zz_11 >>> 32) + x_7 * x_5;
- zz_13 += (zz_12 >>> 32) + x_7 * x_6;
- zz_14 += zz_13 >>> 32;
- }
-
- w = (int)zz_8;
- zz[zzOff + 8] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_9;
- zz[zzOff + 9] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_10;
- zz[zzOff + 10] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_11;
- zz[zzOff + 11] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_12;
- zz[zzOff + 12] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_13;
- zz[zzOff + 13] = (w << 1) | c;
- c = w >>> 31;
- w = (int)zz_14;
- zz[zzOff + 14] = (w << 1) | c;
- c = w >>> 31;
- w = zz[zzOff + 15] + (int)(zz_14 >> 32);
- zz[zzOff + 15] = (w << 1) | c;
- }
-
- public static int sub(int[] x, int[] y, int[] z)
- {
- long c = 0;
- c += (x[0] & M) - (y[0] & M);
- z[0] = (int)c;
- c >>= 32;
- c += (x[1] & M) - (y[1] & M);
- z[1] = (int)c;
- c >>= 32;
- c += (x[2] & M) - (y[2] & M);
- z[2] = (int)c;
- c >>= 32;
- c += (x[3] & M) - (y[3] & M);
- z[3] = (int)c;
- c >>= 32;
- c += (x[4] & M) - (y[4] & M);
- z[4] = (int)c;
- c >>= 32;
- c += (x[5] & M) - (y[5] & M);
- z[5] = (int)c;
- c >>= 32;
- c += (x[6] & M) - (y[6] & M);
- z[6] = (int)c;
- c >>= 32;
- c += (x[7] & M) - (y[7] & M);
- z[7] = (int)c;
- c >>= 32;
- return (int)c;
- }
-
- public static int sub(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
- {
- long c = 0;
- c += (x[xOff + 0] & M) - (y[yOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>= 32;
- c += (x[xOff + 1] & M) - (y[yOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>= 32;
- c += (x[xOff + 2] & M) - (y[yOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>= 32;
- c += (x[xOff + 3] & M) - (y[yOff + 3] & M);
- z[zOff + 3] = (int)c;
- c >>= 32;
- c += (x[xOff + 4] & M) - (y[yOff + 4] & M);
- z[zOff + 4] = (int)c;
- c >>= 32;
- c += (x[xOff + 5] & M) - (y[yOff + 5] & M);
- z[zOff + 5] = (int)c;
- c >>= 32;
- c += (x[xOff + 6] & M) - (y[yOff + 6] & M);
- z[zOff + 6] = (int)c;
- c >>= 32;
- c += (x[xOff + 7] & M) - (y[yOff + 7] & M);
- z[zOff + 7] = (int)c;
- c >>= 32;
- return (int)c;
- }
-
- public static int subBothFrom(int[] x, int[] y, int[] z)
- {
- long c = 0;
- c += (z[0] & M) - (x[0] & M) - (y[0] & M);
- z[0] = (int)c;
- c >>= 32;
- c += (z[1] & M) - (x[1] & M) - (y[1] & M);
- z[1] = (int)c;
- c >>= 32;
- c += (z[2] & M) - (x[2] & M) - (y[2] & M);
- z[2] = (int)c;
- c >>= 32;
- c += (z[3] & M) - (x[3] & M) - (y[3] & M);
- z[3] = (int)c;
- c >>= 32;
- c += (z[4] & M) - (x[4] & M) - (y[4] & M);
- z[4] = (int)c;
- c >>= 32;
- c += (z[5] & M) - (x[5] & M) - (y[5] & M);
- z[5] = (int)c;
- c >>= 32;
- c += (z[6] & M) - (x[6] & M) - (y[6] & M);
- z[6] = (int)c;
- c >>= 32;
- c += (z[7] & M) - (x[7] & M) - (y[7] & M);
- z[7] = (int)c;
- c >>= 32;
- return (int)c;
- }
-
- public static int subFrom(int[] x, int[] z)
- {
- long c = 0;
- c += (z[0] & M) - (x[0] & M);
- z[0] = (int)c;
- c >>= 32;
- c += (z[1] & M) - (x[1] & M);
- z[1] = (int)c;
- c >>= 32;
- c += (z[2] & M) - (x[2] & M);
- z[2] = (int)c;
- c >>= 32;
- c += (z[3] & M) - (x[3] & M);
- z[3] = (int)c;
- c >>= 32;
- c += (z[4] & M) - (x[4] & M);
- z[4] = (int)c;
- c >>= 32;
- c += (z[5] & M) - (x[5] & M);
- z[5] = (int)c;
- c >>= 32;
- c += (z[6] & M) - (x[6] & M);
- z[6] = (int)c;
- c >>= 32;
- c += (z[7] & M) - (x[7] & M);
- z[7] = (int)c;
- c >>= 32;
- return (int)c;
- }
-
- public static int subFrom(int[] x, int xOff, int[] z, int zOff)
- {
- long c = 0;
- c += (z[zOff + 0] & M) - (x[xOff + 0] & M);
- z[zOff + 0] = (int)c;
- c >>= 32;
- c += (z[zOff + 1] & M) - (x[xOff + 1] & M);
- z[zOff + 1] = (int)c;
- c >>= 32;
- c += (z[zOff + 2] & M) - (x[xOff + 2] & M);
- z[zOff + 2] = (int)c;
- c >>= 32;
- c += (z[zOff + 3] & M) - (x[xOff + 3] & M);
- z[zOff + 3] = (int)c;
- c >>= 32;
- c += (z[zOff + 4] & M) - (x[xOff + 4] & M);
- z[zOff + 4] = (int)c;
- c >>= 32;
- c += (z[zOff + 5] & M) - (x[xOff + 5] & M);
- z[zOff + 5] = (int)c;
- c >>= 32;
- c += (z[zOff + 6] & M) - (x[xOff + 6] & M);
- z[zOff + 6] = (int)c;
- c >>= 32;
- c += (z[zOff + 7] & M) - (x[xOff + 7] & M);
- z[zOff + 7] = (int)c;
- c >>= 32;
- return (int)c;
- }
-
- public static BigInteger toBigInteger(int[] x)
- {
- byte[] bs = new byte[32];
- for (int i = 0; i < 8; ++i)
- {
- int x_i = x[i];
- if (x_i != 0)
- {
- Pack.intToBigEndian(x_i, bs, (7 - i) << 2);
- }
- }
- return new BigInteger(1, bs);
- }
-
- public static void zero(int[] z)
- {
- z[0] = 0;
- z[1] = 0;
- z[2] = 0;
- z[3] = 0;
- z[4] = 0;
- z[5] = 0;
- z[6] = 0;
- z[7] = 0;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/raw/Nat384.java b/core/src/main/java/org/bouncycastle/math/raw/Nat384.java
deleted file mode 100644
index 889550e5..00000000
--- a/core/src/main/java/org/bouncycastle/math/raw/Nat384.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.bouncycastle.math.raw;
-
-
-public abstract class Nat384
-{
- public static void mul(int[] x, int[] y, int[] zz)
- {
- Nat192.mul(x, y, zz);
- Nat192.mul(x, 6, y, 6, zz, 12);
-
- int c18 = Nat192.addToEachOther(zz, 6, zz, 12);
- int c12 = c18 + Nat192.addTo(zz, 0, zz, 6, 0);
- c18 += Nat192.addTo(zz, 18, zz, 12, c12);
-
- int[] dx = Nat192.create(), dy = Nat192.create();
- boolean neg = Nat192.diff(x, 6, x, 0, dx, 0) != Nat192.diff(y, 6, y, 0, dy, 0);
-
- int[] tt = Nat192.createExt();
- Nat192.mul(dx, dy, tt);
-
- c18 += neg ? Nat.addTo(12, tt, 0, zz, 6) : Nat.subFrom(12, tt, 0, zz, 6);
- Nat.addWordAt(24, c18, zz, 18);
- }
-
- public static void square(int[] x, int[] zz)
- {
- Nat192.square(x, zz);
- Nat192.square(x, 6, zz, 12);
-
- int c18 = Nat192.addToEachOther(zz, 6, zz, 12);
- int c12 = c18 + Nat192.addTo(zz, 0, zz, 6, 0);
- c18 += Nat192.addTo(zz, 18, zz, 12, c12);
-
- int[] dx = Nat192.create();
- Nat192.diff(x, 6, x, 0, dx, 0);
-
- int[] tt = Nat192.createExt();
- Nat192.square(dx, tt);
-
- c18 += Nat.subFrom(12, tt, 0, zz, 6);
- Nat.addWordAt(24, c18, zz, 18);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/math/raw/Nat512.java b/core/src/main/java/org/bouncycastle/math/raw/Nat512.java
deleted file mode 100644
index 594e8f50..00000000
--- a/core/src/main/java/org/bouncycastle/math/raw/Nat512.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.bouncycastle.math.raw;
-
-
-public abstract class Nat512
-{
- public static void mul(int[] x, int[] y, int[] zz)
- {
- Nat256.mul(x, y, zz);
- Nat256.mul(x, 8, y, 8, zz, 16);
-
- int c24 = Nat256.addToEachOther(zz, 8, zz, 16);
- int c16 = c24 + Nat256.addTo(zz, 0, zz, 8, 0);
- c24 += Nat256.addTo(zz, 24, zz, 16, c16);
-
- int[] dx = Nat256.create(), dy = Nat256.create();
- boolean neg = Nat256.diff(x, 8, x, 0, dx, 0) != Nat256.diff(y, 8, y, 0, dy, 0);
-
- int[] tt = Nat256.createExt();
- Nat256.mul(dx, dy, tt);
-
- c24 += neg ? Nat.addTo(16, tt, 0, zz, 8) : Nat.subFrom(16, tt, 0, zz, 8);
- Nat.addWordAt(32, c24, zz, 24);
- }
-
- public static void square(int[] x, int[] zz)
- {
- Nat256.square(x, zz);
- Nat256.square(x, 8, zz, 16);
-
- int c24 = Nat256.addToEachOther(zz, 8, zz, 16);
- int c16 = c24 + Nat256.addTo(zz, 0, zz, 8, 0);
- c24 += Nat256.addTo(zz, 24, zz, 16, c16);
-
- int[] dx = Nat256.create();
- Nat256.diff(x, 8, x, 0, dx, 0);
-
- int[] tt = Nat256.createExt();
- Nat256.square(dx, tt);
-
- c24 += Nat.subFrom(16, tt, 0, zz, 8);
- Nat.addWordAt(32, c24, zz, 24);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/asn1/GMSSPrivateKey.java b/core/src/main/java/org/bouncycastle/pqc/asn1/GMSSPrivateKey.java
deleted file mode 100644
index 4e182c59..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/asn1/GMSSPrivateKey.java
+++ /dev/null
@@ -1,1312 +0,0 @@
-package org.bouncycastle.pqc.asn1;
-
-import java.math.BigInteger;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.pqc.crypto.gmss.GMSSLeaf;
-import org.bouncycastle.pqc.crypto.gmss.GMSSParameters;
-import org.bouncycastle.pqc.crypto.gmss.GMSSRootCalc;
-import org.bouncycastle.pqc.crypto.gmss.GMSSRootSig;
-import org.bouncycastle.pqc.crypto.gmss.Treehash;
-
-public class GMSSPrivateKey
- extends ASN1Object
-{
- private ASN1Primitive primitive;
-
- private GMSSPrivateKey(ASN1Sequence mtsPrivateKey)
- {
- // --- Decode <index>.
- ASN1Sequence indexPart = (ASN1Sequence)mtsPrivateKey.getObjectAt(0);
- int[] index = new int[indexPart.size()];
- for (int i = 0; i < indexPart.size(); i++)
- {
- index[i] = checkBigIntegerInIntRange(indexPart.getObjectAt(i));
- }
-
- // --- Decode <curSeeds>.
- ASN1Sequence curSeedsPart = (ASN1Sequence)mtsPrivateKey.getObjectAt(1);
- byte[][] curSeeds = new byte[curSeedsPart.size()][];
- for (int i = 0; i < curSeeds.length; i++)
- {
- curSeeds[i] = ((DEROctetString)curSeedsPart.getObjectAt(i)).getOctets();
- }
-
- // --- Decode <nextNextSeeds>.
- ASN1Sequence nextNextSeedsPart = (ASN1Sequence)mtsPrivateKey.getObjectAt(2);
- byte[][] nextNextSeeds = new byte[nextNextSeedsPart.size()][];
- for (int i = 0; i < nextNextSeeds.length; i++)
- {
- nextNextSeeds[i] = ((DEROctetString)nextNextSeedsPart.getObjectAt(i)).getOctets();
- }
-
- // --- Decode <curAuth>.
- ASN1Sequence curAuthPart0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(3);
- ASN1Sequence curAuthPart1;
-
- byte[][][] curAuth = new byte[curAuthPart0.size()][][];
- for (int i = 0; i < curAuth.length; i++)
- {
- curAuthPart1 = (ASN1Sequence)curAuthPart0.getObjectAt(i);
- curAuth[i] = new byte[curAuthPart1.size()][];
- for (int j = 0; j < curAuth[i].length; j++)
- {
- curAuth[i][j] = ((DEROctetString)curAuthPart1.getObjectAt(j)).getOctets();
- }
- }
-
- // --- Decode <nextAuth>.
- ASN1Sequence nextAuthPart0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(4);
- ASN1Sequence nextAuthPart1;
-
- byte[][][] nextAuth = new byte[nextAuthPart0.size()][][];
- for (int i = 0; i < nextAuth.length; i++)
- {
- nextAuthPart1 = (ASN1Sequence)nextAuthPart0.getObjectAt(i);
- nextAuth[i] = new byte[nextAuthPart1.size()][];
- for (int j = 0; j < nextAuth[i].length; j++)
- {
- nextAuth[i][j] = ((DEROctetString)nextAuthPart1.getObjectAt(j)).getOctets();
- }
- }
-
- // --- Decode <curTreehash>.
- ASN1Sequence seqOfcurTreehash0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(5);
- ASN1Sequence seqOfcurTreehash1;
- ASN1Sequence seqOfcurTreehashStat;
- ASN1Sequence seqOfcurTreehashBytes;
- ASN1Sequence seqOfcurTreehashInts;
- ASN1Sequence seqOfcurTreehashString;
-
- Treehash[][] curTreehash = new Treehash[seqOfcurTreehash0.size()][];
- /*
- for (int i = 0; i < curTreehash.length; i++)
- {
- seqOfcurTreehash1 = (ASN1Sequence)seqOfcurTreehash0.getObjectAt(i);
- curTreehash[i] = new Treehash[seqOfcurTreehash1.size()];
- for (int j = 0; j < curTreehash[i].length; j++)
- {
- seqOfcurTreehashStat = (ASN1Sequence)seqOfcurTreehash1.getObjectAt(j);
- seqOfcurTreehashString = (ASN1Sequence)seqOfcurTreehashStat
- .getObjectAt(0);
- seqOfcurTreehashBytes = (ASN1Sequence)seqOfcurTreehashStat
- .getObjectAt(1);
- seqOfcurTreehashInts = (ASN1Sequence)seqOfcurTreehashStat
- .getObjectAt(2);
-
- String[] name = new String[2];
- name[0] = ((DERIA5String)seqOfcurTreehashString.getObjectAt(0)).getString();
- name[1] = ((DERIA5String)seqOfcurTreehashString.getObjectAt(1)).getString();
-
- int tailLength = checkBigIntegerInIntRange(seqOfcurTreehashInts.getObjectAt(1));
- byte[][] statByte = new byte[3 + tailLength][];
- statByte[0] = ((DEROctetString)seqOfcurTreehashBytes.getObjectAt(0)).getOctets();
-
- if (statByte[0].length == 0)
- { // if null was encoded
- statByte[0] = null;
- }
-
- statByte[1] = ((DEROctetString)seqOfcurTreehashBytes.getObjectAt(1)).getOctets();
- statByte[2] = ((DEROctetString)seqOfcurTreehashBytes.getObjectAt(2)).getOctets();
- for (int k = 0; k < tailLength; k++)
- {
- statByte[3 + k] = ((DEROctetString)seqOfcurTreehashBytes
- .getObjectAt(3 + k)).getOctets();
- }
- int[] statInt = new int[6 + tailLength];
- statInt[0] = checkBigIntegerInIntRange(seqOfcurTreehashInts.getObjectAt(0));
- statInt[1] = tailLength;
- statInt[2] = checkBigIntegerInIntRange(seqOfcurTreehashInts.getObjectAt(2));
- statInt[3] = checkBigIntegerInIntRange(seqOfcurTreehashInts.getObjectAt(3));
- statInt[4] = checkBigIntegerInIntRange(seqOfcurTreehashInts.getObjectAt(4));
- statInt[5] = checkBigIntegerInIntRange(seqOfcurTreehashInts.getObjectAt(5));
- for (int k = 0; k < tailLength; k++)
- {
- statInt[6 + k] = checkBigIntegerInIntRange(seqOfcurTreehashInts.getObjectAt(6 + k));
- }
-
- // TODO: Check if we can do better than throwing away name[1] !!!
- curTreehash[i][j] = new Treehash(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt);
- }
- }
-
-
- // --- Decode <nextTreehash>.
- ASN1Sequence seqOfNextTreehash0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(6);
- ASN1Sequence seqOfNextTreehash1;
- ASN1Sequence seqOfNextTreehashStat;
- ASN1Sequence seqOfNextTreehashBytes;
- ASN1Sequence seqOfNextTreehashInts;
- ASN1Sequence seqOfNextTreehashString;
-
- Treehash[][] nextTreehash = new Treehash[seqOfNextTreehash0.size()][];
-
- for (int i = 0; i < nextTreehash.length; i++)
- {
- seqOfNextTreehash1 = (ASN1Sequence)seqOfNextTreehash0.getObjectAt(i);
- nextTreehash[i] = new Treehash[seqOfNextTreehash1.size()];
- for (int j = 0; j < nextTreehash[i].length; j++)
- {
- seqOfNextTreehashStat = (ASN1Sequence)seqOfNextTreehash1
- .getObjectAt(j);
- seqOfNextTreehashString = (ASN1Sequence)seqOfNextTreehashStat
- .getObjectAt(0);
- seqOfNextTreehashBytes = (ASN1Sequence)seqOfNextTreehashStat
- .getObjectAt(1);
- seqOfNextTreehashInts = (ASN1Sequence)seqOfNextTreehashStat
- .getObjectAt(2);
-
- String[] name = new String[2];
- name[0] = ((DERIA5String)seqOfNextTreehashString.getObjectAt(0))
- .getString();
- name[1] = ((DERIA5String)seqOfNextTreehashString.getObjectAt(1))
- .getString();
-
- int tailLength = checkBigIntegerInIntRange(seqOfNextTreehashInts.getObjectAt(1));
-
- byte[][] statByte = new byte[3 + tailLength][];
- statByte[0] = ((DEROctetString)seqOfNextTreehashBytes.getObjectAt(0)).getOctets();
- if (statByte[0].length == 0)
- { // if null was encoded
- statByte[0] = null;
- }
-
- statByte[1] = ((DEROctetString)seqOfNextTreehashBytes.getObjectAt(1)).getOctets();
- statByte[2] = ((DEROctetString)seqOfNextTreehashBytes.getObjectAt(2)).getOctets();
- for (int k = 0; k < tailLength; k++)
- {
- statByte[3 + k] = ((DEROctetString)seqOfNextTreehashBytes
- .getObjectAt(3 + k)).getOctets();
- }
- int[] statInt = new int[6 + tailLength];
- statInt[0] = checkBigIntegerInIntRange(seqOfNextTreehashInts.getObjectAt(0));
-
- statInt[1] = tailLength;
- statInt[2] = checkBigIntegerInIntRange(seqOfNextTreehashInts.getObjectAt(2));
-
- statInt[3] = checkBigIntegerInIntRange(seqOfNextTreehashInts.getObjectAt(3));
-
- statInt[4] = checkBigIntegerInIntRange(seqOfNextTreehashInts.getObjectAt(4));
-
- statInt[5] = checkBigIntegerInIntRange(seqOfNextTreehashInts.getObjectAt(5));
-
- for (int k = 0; k < tailLength; k++)
- {
- statInt[6 + k] = checkBigIntegerInIntRange(seqOfNextTreehashInts.getObjectAt(6 + k));
-
- }
- nextTreehash[i][j] = new Treehash(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt);
- }
- }
-
-
- // --- Decode <keep>.
- ASN1Sequence keepPart0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(7);
- ASN1Sequence keepPart1;
-
- byte[][][] keep = new byte[keepPart0.size()][][];
- for (int i = 0; i < keep.length; i++)
- {
- keepPart1 = (ASN1Sequence)keepPart0.getObjectAt(i);
- keep[i] = new byte[keepPart1.size()][];
- for (int j = 0; j < keep[i].length; j++)
- {
- keep[i][j] = ((DEROctetString)keepPart1.getObjectAt(j)).getOctets();
- }
- }
-
- // --- Decode <curStack>.
- ASN1Sequence curStackPart0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(8);
- ASN1Sequence curStackPart1;
-
- Vector[] curStack = new Vector[curStackPart0.size()];
- for (int i = 0; i < curStack.length; i++)
- {
- curStackPart1 = (ASN1Sequence)curStackPart0.getObjectAt(i);
- curStack[i] = new Vector();
- for (int j = 0; j < curStackPart1.size(); j++)
- {
- curStack[i].addElement(((DEROctetString)curStackPart1.getObjectAt(j)).getOctets());
- }
- }
-
- // --- Decode <nextStack>.
- ASN1Sequence nextStackPart0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(9);
- ASN1Sequence nextStackPart1;
-
- Vector[] nextStack = new Vector[nextStackPart0.size()];
- for (int i = 0; i < nextStack.length; i++)
- {
- nextStackPart1 = (ASN1Sequence)nextStackPart0.getObjectAt(i);
- nextStack[i] = new Vector();
- for (int j = 0; j < nextStackPart1.size(); j++)
- {
- nextStack[i].addElement(((DEROctetString)nextStackPart1
- .getObjectAt(j)).getOctets());
- }
- }
-
- // --- Decode <curRetain>.
- ASN1Sequence curRetainPart0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(10);
- ASN1Sequence curRetainPart1;
- ASN1Sequence curRetainPart2;
-
- Vector[][] curRetain = new Vector[curRetainPart0.size()][];
- for (int i = 0; i < curRetain.length; i++)
- {
- curRetainPart1 = (ASN1Sequence)curRetainPart0.getObjectAt(i);
- curRetain[i] = new Vector[curRetainPart1.size()];
- for (int j = 0; j < curRetain[i].length; j++)
- {
- curRetainPart2 = (ASN1Sequence)curRetainPart1.getObjectAt(j);
- curRetain[i][j] = new Vector();
- for (int k = 0; k < curRetainPart2.size(); k++)
- {
- curRetain[i][j]
- .addElement(((DEROctetString)curRetainPart2
- .getObjectAt(k)).getOctets());
- }
- }
- }
-
- // --- Decode <nextRetain>.
- ASN1Sequence nextRetainPart0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(11);
- ASN1Sequence nextRetainPart1;
- ASN1Sequence nextRetainPart2;
-
- Vector[][] nextRetain = new Vector[nextRetainPart0.size()][];
- for (int i = 0; i < nextRetain.length; i++)
- {
- nextRetainPart1 = (ASN1Sequence)nextRetainPart0.getObjectAt(i);
- nextRetain[i] = new Vector[nextRetainPart1.size()];
- for (int j = 0; j < nextRetain[i].length; j++)
- {
- nextRetainPart2 = (ASN1Sequence)nextRetainPart1.getObjectAt(j);
- nextRetain[i][j] = new Vector();
- for (int k = 0; k < nextRetainPart2.size(); k++)
- {
- nextRetain[i][j]
- .addElement(((DEROctetString)nextRetainPart2
- .getObjectAt(k)).getOctets());
- }
- }
- }
-
- // --- Decode <nextNextLeaf>.
- ASN1Sequence seqOfLeafs = (ASN1Sequence)mtsPrivateKey.getObjectAt(12);
- ASN1Sequence seqOfLeafStat;
- ASN1Sequence seqOfLeafBytes;
- ASN1Sequence seqOfLeafInts;
- ASN1Sequence seqOfLeafString;
-
- GMSSLeaf[] nextNextLeaf = new GMSSLeaf[seqOfLeafs.size()];
-
- for (int i = 0; i < nextNextLeaf.length; i++)
- {
- seqOfLeafStat = (ASN1Sequence)seqOfLeafs.getObjectAt(i);
- // nextNextAuth[i]= new byte[nextNextAuthPart1.size()][];
- seqOfLeafString = (ASN1Sequence)seqOfLeafStat.getObjectAt(0);
- seqOfLeafBytes = (ASN1Sequence)seqOfLeafStat.getObjectAt(1);
- seqOfLeafInts = (ASN1Sequence)seqOfLeafStat.getObjectAt(2);
-
- String[] name = new String[2];
- name[0] = ((DERIA5String)seqOfLeafString.getObjectAt(0)).getString();
- name[1] = ((DERIA5String)seqOfLeafString.getObjectAt(1)).getString();
- byte[][] statByte = new byte[4][];
- statByte[0] = ((DEROctetString)seqOfLeafBytes.getObjectAt(0))
- .getOctets();
- statByte[1] = ((DEROctetString)seqOfLeafBytes.getObjectAt(1))
- .getOctets();
- statByte[2] = ((DEROctetString)seqOfLeafBytes.getObjectAt(2))
- .getOctets();
- statByte[3] = ((DEROctetString)seqOfLeafBytes.getObjectAt(3))
- .getOctets();
- int[] statInt = new int[4];
- statInt[0] = checkBigIntegerInIntRange(seqOfLeafInts.getObjectAt(0));
- statInt[1] = checkBigIntegerInIntRange(seqOfLeafInts.getObjectAt(1));
- statInt[2] = checkBigIntegerInIntRange(seqOfLeafInts.getObjectAt(2));
- statInt[3] = checkBigIntegerInIntRange(seqOfLeafInts.getObjectAt(3));
- nextNextLeaf[i] = new GMSSLeaf(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt);
- }
-
- // --- Decode <upperLeaf>.
- ASN1Sequence seqOfUpperLeafs = (ASN1Sequence)mtsPrivateKey.getObjectAt(13);
- ASN1Sequence seqOfUpperLeafStat;
- ASN1Sequence seqOfUpperLeafBytes;
- ASN1Sequence seqOfUpperLeafInts;
- ASN1Sequence seqOfUpperLeafString;
-
- GMSSLeaf[] upperLeaf = new GMSSLeaf[seqOfUpperLeafs.size()];
-
- for (int i = 0; i < upperLeaf.length; i++)
- {
- seqOfUpperLeafStat = (ASN1Sequence)seqOfUpperLeafs.getObjectAt(i);
- seqOfUpperLeafString = (ASN1Sequence)seqOfUpperLeafStat.getObjectAt(0);
- seqOfUpperLeafBytes = (ASN1Sequence)seqOfUpperLeafStat.getObjectAt(1);
- seqOfUpperLeafInts = (ASN1Sequence)seqOfUpperLeafStat.getObjectAt(2);
-
- String[] name = new String[2];
- name[0] = ((DERIA5String)seqOfUpperLeafString.getObjectAt(0)).getString();
- name[1] = ((DERIA5String)seqOfUpperLeafString.getObjectAt(1)).getString();
- byte[][] statByte = new byte[4][];
- statByte[0] = ((DEROctetString)seqOfUpperLeafBytes.getObjectAt(0))
- .getOctets();
- statByte[1] = ((DEROctetString)seqOfUpperLeafBytes.getObjectAt(1))
- .getOctets();
- statByte[2] = ((DEROctetString)seqOfUpperLeafBytes.getObjectAt(2))
- .getOctets();
- statByte[3] = ((DEROctetString)seqOfUpperLeafBytes.getObjectAt(3))
- .getOctets();
- int[] statInt = new int[4];
- statInt[0] = checkBigIntegerInIntRange(seqOfUpperLeafInts.getObjectAt(0));
- statInt[1] = checkBigIntegerInIntRange(seqOfUpperLeafInts.getObjectAt(1));
- statInt[2] = checkBigIntegerInIntRange(seqOfUpperLeafInts.getObjectAt(2));
- statInt[3] = checkBigIntegerInIntRange(seqOfUpperLeafInts.getObjectAt(3));
- upperLeaf[i] = new GMSSLeaf(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt);
- }
-
- // --- Decode <upperTreehashLeaf>.
- ASN1Sequence seqOfUpperTHLeafs = (ASN1Sequence)mtsPrivateKey.getObjectAt(14);
- ASN1Sequence seqOfUpperTHLeafStat;
- ASN1Sequence seqOfUpperTHLeafBytes;
- ASN1Sequence seqOfUpperTHLeafInts;
- ASN1Sequence seqOfUpperTHLeafString;
-
- GMSSLeaf[] upperTHLeaf = new GMSSLeaf[seqOfUpperTHLeafs.size()];
-
- for (int i = 0; i < upperTHLeaf.length; i++)
- {
- seqOfUpperTHLeafStat = (ASN1Sequence)seqOfUpperTHLeafs.getObjectAt(i);
- seqOfUpperTHLeafString = (ASN1Sequence)seqOfUpperTHLeafStat.getObjectAt(0);
- seqOfUpperTHLeafBytes = (ASN1Sequence)seqOfUpperTHLeafStat.getObjectAt(1);
- seqOfUpperTHLeafInts = (ASN1Sequence)seqOfUpperTHLeafStat.getObjectAt(2);
-
- String[] name = new String[2];
- name[0] = ((DERIA5String)seqOfUpperTHLeafString.getObjectAt(0))
- .getString();
- name[1] = ((DERIA5String)seqOfUpperTHLeafString.getObjectAt(1))
- .getString();
- byte[][] statByte = new byte[4][];
- statByte[0] = ((DEROctetString)seqOfUpperTHLeafBytes.getObjectAt(0))
- .getOctets();
- statByte[1] = ((DEROctetString)seqOfUpperTHLeafBytes.getObjectAt(1))
- .getOctets();
- statByte[2] = ((DEROctetString)seqOfUpperTHLeafBytes.getObjectAt(2))
- .getOctets();
- statByte[3] = ((DEROctetString)seqOfUpperTHLeafBytes.getObjectAt(3))
- .getOctets();
- int[] statInt = new int[4];
- statInt[0] = checkBigIntegerInIntRange(seqOfUpperTHLeafInts.getObjectAt(0));
- statInt[1] = checkBigIntegerInIntRange(seqOfUpperTHLeafInts.getObjectAt(1));
- statInt[2] = checkBigIntegerInIntRange(seqOfUpperTHLeafInts.getObjectAt(2));
- statInt[3] = checkBigIntegerInIntRange(seqOfUpperTHLeafInts.getObjectAt(3));
- upperTHLeaf[i] = new GMSSLeaf(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt);
- }
-
- // --- Decode <minTreehash>.
- ASN1Sequence minTreehashPart = (ASN1Sequence)mtsPrivateKey.getObjectAt(15);
- int[] minTreehash = new int[minTreehashPart.size()];
- for (int i = 0; i < minTreehashPart.size(); i++)
- {
- minTreehash[i] = checkBigIntegerInIntRange(minTreehashPart.getObjectAt(i));
- }
-
- // --- Decode <nextRoot>.
- ASN1Sequence seqOfnextRoots = (ASN1Sequence)mtsPrivateKey.getObjectAt(16);
- byte[][] nextRoot = new byte[seqOfnextRoots.size()][];
- for (int i = 0; i < nextRoot.length; i++)
- {
- nextRoot[i] = ((DEROctetString)seqOfnextRoots.getObjectAt(i))
- .getOctets();
- }
-
- // --- Decode <nextNextRoot>.
- ASN1Sequence seqOfnextNextRoot = (ASN1Sequence)mtsPrivateKey.getObjectAt(17);
- ASN1Sequence seqOfnextNextRootStat;
- ASN1Sequence seqOfnextNextRootBytes;
- ASN1Sequence seqOfnextNextRootInts;
- ASN1Sequence seqOfnextNextRootString;
- ASN1Sequence seqOfnextNextRootTreeH;
- ASN1Sequence seqOfnextNextRootRetain;
-
- GMSSRootCalc[] nextNextRoot = new GMSSRootCalc[seqOfnextNextRoot.size()];
-
- for (int i = 0; i < nextNextRoot.length; i++)
- {
- seqOfnextNextRootStat = (ASN1Sequence)seqOfnextNextRoot.getObjectAt(i);
- seqOfnextNextRootString = (ASN1Sequence)seqOfnextNextRootStat
- .getObjectAt(0);
- seqOfnextNextRootBytes = (ASN1Sequence)seqOfnextNextRootStat
- .getObjectAt(1);
- seqOfnextNextRootInts = (ASN1Sequence)seqOfnextNextRootStat.getObjectAt(2);
- seqOfnextNextRootTreeH = (ASN1Sequence)seqOfnextNextRootStat
- .getObjectAt(3);
- seqOfnextNextRootRetain = (ASN1Sequence)seqOfnextNextRootStat
- .getObjectAt(4);
-
- // decode treehash of nextNextRoot
- // ---------------------------------
- ASN1Sequence seqOfnextNextRootTreeHStat;
- ASN1Sequence seqOfnextNextRootTreeHBytes;
- ASN1Sequence seqOfnextNextRootTreeHInts;
- ASN1Sequence seqOfnextNextRootTreeHString;
-
- Treehash[] nnRTreehash = new Treehash[seqOfnextNextRootTreeH.size()];
-
- for (int k = 0; k < nnRTreehash.length; k++)
- {
- seqOfnextNextRootTreeHStat = (ASN1Sequence)seqOfnextNextRootTreeH
- .getObjectAt(k);
- seqOfnextNextRootTreeHString = (ASN1Sequence)seqOfnextNextRootTreeHStat
- .getObjectAt(0);
- seqOfnextNextRootTreeHBytes = (ASN1Sequence)seqOfnextNextRootTreeHStat
- .getObjectAt(1);
- seqOfnextNextRootTreeHInts = (ASN1Sequence)seqOfnextNextRootTreeHStat
- .getObjectAt(2);
-
- String[] name = new String[2];
- name[0] = ((DERIA5String)seqOfnextNextRootTreeHString.getObjectAt(0))
- .getString();
- name[1] = ((DERIA5String)seqOfnextNextRootTreeHString.getObjectAt(1))
- .getString();
-
- int tailLength = checkBigIntegerInIntRange(seqOfnextNextRootTreeHInts.getObjectAt(1));
-
- byte[][] statByte = new byte[3 + tailLength][];
- statByte[0] = ((DEROctetString)seqOfnextNextRootTreeHBytes
- .getObjectAt(0)).getOctets();
- if (statByte[0].length == 0)
- { // if null was encoded
- statByte[0] = null;
- }
-
- statByte[1] = ((DEROctetString)seqOfnextNextRootTreeHBytes
- .getObjectAt(1)).getOctets();
- statByte[2] = ((DEROctetString)seqOfnextNextRootTreeHBytes
- .getObjectAt(2)).getOctets();
- for (int j = 0; j < tailLength; j++)
- {
- statByte[3 + j] = ((DEROctetString)seqOfnextNextRootTreeHBytes
- .getObjectAt(3 + j)).getOctets();
- }
- int[] statInt = new int[6 + tailLength];
- statInt[0] = checkBigIntegerInIntRange(seqOfnextNextRootTreeHInts.getObjectAt(0));
-
- statInt[1] = tailLength;
- statInt[2] = checkBigIntegerInIntRange(seqOfnextNextRootTreeHInts.getObjectAt(2));
-
- statInt[3] = checkBigIntegerInIntRange(seqOfnextNextRootTreeHInts.getObjectAt(3));
-
- statInt[4] = checkBigIntegerInIntRange(seqOfnextNextRootTreeHInts.getObjectAt(4));
-
- statInt[5] = checkBigIntegerInIntRange(seqOfnextNextRootTreeHInts.getObjectAt(5));
-
- for (int j = 0; j < tailLength; j++)
- {
- statInt[6 + j] = checkBigIntegerInIntRange(seqOfnextNextRootTreeHInts
- .getObjectAt(6 + j));
- }
- nnRTreehash[k] = new Treehash(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt);
- }
- // ---------------------------------
-
- // decode retain of nextNextRoot
- // ---------------------------------
- // ASN1Sequence seqOfnextNextRootRetainPart0 =
- // (ASN1Sequence)seqOfnextNextRootRetain.get(0);
- ASN1Sequence seqOfnextNextRootRetainPart1;
-
- Vector[] nnRRetain = new Vector[seqOfnextNextRootRetain.size()];
- for (int j = 0; j < nnRRetain.length; j++)
- {
- seqOfnextNextRootRetainPart1 = (ASN1Sequence)seqOfnextNextRootRetain
- .getObjectAt(j);
- nnRRetain[j] = new Vector();
- for (int k = 0; k < seqOfnextNextRootRetainPart1.size(); k++)
- {
- nnRRetain[j]
- .addElement(((DEROctetString)seqOfnextNextRootRetainPart1
- .getObjectAt(k)).getOctets());
- }
- }
- // ---------------------------------
-
- String[] name = new String[2];
- name[0] = ((DERIA5String)seqOfnextNextRootString.getObjectAt(0))
- .getString();
- name[1] = ((DERIA5String)seqOfnextNextRootString.getObjectAt(1))
- .getString();
-
- int heightOfTree = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(0));
- int tailLength = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(7));
- byte[][] statByte = new byte[1 + heightOfTree + tailLength][];
- statByte[0] = ((DEROctetString)seqOfnextNextRootBytes.getObjectAt(0))
- .getOctets();
- for (int j = 0; j < heightOfTree; j++)
- {
- statByte[1 + j] = ((DEROctetString)seqOfnextNextRootBytes
- .getObjectAt(1 + j)).getOctets();
- }
- for (int j = 0; j < tailLength; j++)
- {
- statByte[1 + heightOfTree + j] = ((DEROctetString)seqOfnextNextRootBytes
- .getObjectAt(1 + heightOfTree + j)).getOctets();
- }
- int[] statInt = new int[8 + heightOfTree + tailLength];
- statInt[0] = heightOfTree;
- statInt[1] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(1));
- statInt[2] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(2));
- statInt[3] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(3));
- statInt[4] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(4));
- statInt[5] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(5));
- statInt[6] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(6));
- statInt[7] = tailLength;
- for (int j = 0; j < heightOfTree; j++)
- {
- statInt[8 + j] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(8 + j));
- }
- for (int j = 0; j < tailLength; j++)
- {
- statInt[8 + heightOfTree + j] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(8
- + heightOfTree + j));
- }
- nextNextRoot[i] = new GMSSRootCalc(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt,
- nnRTreehash, nnRRetain);
- }
-
- // --- Decode <curRootSig>.
- ASN1Sequence seqOfcurRootSig = (ASN1Sequence)mtsPrivateKey.getObjectAt(18);
- byte[][] curRootSig = new byte[seqOfcurRootSig.size()][];
- for (int i = 0; i < curRootSig.length; i++)
- {
- curRootSig[i] = ((DEROctetString)seqOfcurRootSig.getObjectAt(i))
- .getOctets();
- }
-
- // --- Decode <nextRootSig>.
- ASN1Sequence seqOfnextRootSigs = (ASN1Sequence)mtsPrivateKey.getObjectAt(19);
- ASN1Sequence seqOfnRSStats;
- ASN1Sequence seqOfnRSStrings;
- ASN1Sequence seqOfnRSInts;
- ASN1Sequence seqOfnRSBytes;
-
- GMSSRootSig[] nextRootSig = new GMSSRootSig[seqOfnextRootSigs.size()];
-
- for (int i = 0; i < nextRootSig.length; i++)
- {
- seqOfnRSStats = (ASN1Sequence)seqOfnextRootSigs.getObjectAt(i);
- // nextNextAuth[i]= new byte[nextNextAuthPart1.size()][];
- seqOfnRSStrings = (ASN1Sequence)seqOfnRSStats.getObjectAt(0);
- seqOfnRSBytes = (ASN1Sequence)seqOfnRSStats.getObjectAt(1);
- seqOfnRSInts = (ASN1Sequence)seqOfnRSStats.getObjectAt(2);
-
- String[] name = new String[2];
- name[0] = ((DERIA5String)seqOfnRSStrings.getObjectAt(0)).getString();
- name[1] = ((DERIA5String)seqOfnRSStrings.getObjectAt(1)).getString();
- byte[][] statByte = new byte[5][];
- statByte[0] = ((DEROctetString)seqOfnRSBytes.getObjectAt(0))
- .getOctets();
- statByte[1] = ((DEROctetString)seqOfnRSBytes.getObjectAt(1))
- .getOctets();
- statByte[2] = ((DEROctetString)seqOfnRSBytes.getObjectAt(2))
- .getOctets();
- statByte[3] = ((DEROctetString)seqOfnRSBytes.getObjectAt(3))
- .getOctets();
- statByte[4] = ((DEROctetString)seqOfnRSBytes.getObjectAt(4))
- .getOctets();
- int[] statInt = new int[9];
- statInt[0] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(0));
- statInt[1] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(1));
- statInt[2] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(2));
- statInt[3] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(3));
- statInt[4] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(4));
- statInt[5] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(5));
- statInt[6] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(6));
- statInt[7] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(7));
- statInt[8] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(8));
- nextRootSig[i] = new GMSSRootSig(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt);
- }
-
- // --- Decode <name>.
-
- // TODO: Really check, why there are multiple algorithms, we only
- // use the first one!!!
- ASN1Sequence namePart = (ASN1Sequence)mtsPrivateKey.getObjectAt(20);
- String[] name = new String[namePart.size()];
- for (int i = 0; i < name.length; i++)
- {
- name[i] = ((DERIA5String)namePart.getObjectAt(i)).getString();
- }
- */
- }
-
- public GMSSPrivateKey(int[] index, byte[][] currentSeed,
- byte[][] nextNextSeed, byte[][][] currentAuthPath,
- byte[][][] nextAuthPath, Treehash[][] currentTreehash,
- Treehash[][] nextTreehash, Vector[] currentStack,
- Vector[] nextStack, Vector[][] currentRetain,
- Vector[][] nextRetain, byte[][][] keep, GMSSLeaf[] nextNextLeaf,
- GMSSLeaf[] upperLeaf, GMSSLeaf[] upperTreehashLeaf,
- int[] minTreehash, byte[][] nextRoot, GMSSRootCalc[] nextNextRoot,
- byte[][] currentRootSig, GMSSRootSig[] nextRootSig,
- GMSSParameters gmssParameterset, AlgorithmIdentifier digestAlg)
- {
- AlgorithmIdentifier[] names = new AlgorithmIdentifier[] { digestAlg };
- this.primitive = encode(index, currentSeed, nextNextSeed, currentAuthPath, nextAuthPath, keep, currentTreehash, nextTreehash, currentStack, nextStack, currentRetain, nextRetain, nextNextLeaf, upperLeaf, upperTreehashLeaf, minTreehash, nextRoot, nextNextRoot, currentRootSig, nextRootSig, gmssParameterset, names);
- }
-
-
- // TODO: change method signature to something more integrated into BouncyCastle
-
- /**
- * @param index tree indices
- * @param currentSeeds seed for the generation of private OTS keys for the
- * current subtrees (TREE)
- * @param nextNextSeeds seed for the generation of private OTS keys for the
- * subtrees after next (TREE++)
- * @param currentAuthPaths array of current authentication paths (AUTHPATH)
- * @param nextAuthPaths array of next authentication paths (AUTHPATH+)
- * @param keep keep array for the authPath algorithm
- * @param currentTreehash treehash for authPath algorithm of current tree
- * @param nextTreehash treehash for authPath algorithm of next tree (TREE+)
- * @param currentStack shared stack for authPath algorithm of current tree
- * @param nextStack shared stack for authPath algorithm of next tree (TREE+)
- * @param currentRetain retain stack for authPath algorithm of current tree
- * @param nextRetain retain stack for authPath algorithm of next tree (TREE+)
- * @param nextNextLeaf array of upcoming leafs of the tree after next (LEAF++) of
- * each layer
- * @param upperLeaf needed for precomputation of upper nodes
- * @param upperTreehashLeaf needed for precomputation of upper treehash nodes
- * @param minTreehash index of next treehash instance to receive an update
- * @param nextRoot the roots of the next trees (ROOT+)
- * @param nextNextRoot the roots of the tree after next (ROOT++)
- * @param currentRootSig array of signatures of the roots of the current subtrees
- * (SIG)
- * @param nextRootSig array of signatures of the roots of the next subtree
- * (SIG+)
- * @param gmssParameterset the GMSS Parameterset
- * @param algorithms An array of algorithm identifiers, containing the hash function details
- */
- private ASN1Primitive encode(int[] index, byte[][] currentSeeds,
- byte[][] nextNextSeeds, byte[][][] currentAuthPaths,
- byte[][][] nextAuthPaths, byte[][][] keep,
- Treehash[][] currentTreehash, Treehash[][] nextTreehash,
- Vector[] currentStack, Vector[] nextStack,
- Vector[][] currentRetain, Vector[][] nextRetain,
- GMSSLeaf[] nextNextLeaf, GMSSLeaf[] upperLeaf,
- GMSSLeaf[] upperTreehashLeaf, int[] minTreehash, byte[][] nextRoot,
- GMSSRootCalc[] nextNextRoot, byte[][] currentRootSig,
- GMSSRootSig[] nextRootSig, GMSSParameters gmssParameterset,
- AlgorithmIdentifier[] algorithms)
- {
-
- ASN1EncodableVector result = new ASN1EncodableVector();
-
- // --- Encode <index>.
- ASN1EncodableVector indexPart = new ASN1EncodableVector();
- for (int i = 0; i < index.length; i++)
- {
- indexPart.add(new ASN1Integer(index[i]));
- }
- result.add(new DERSequence(indexPart));
-
- // --- Encode <curSeeds>.
- ASN1EncodableVector curSeedsPart = new ASN1EncodableVector();
- for (int i = 0; i < currentSeeds.length; i++)
- {
- curSeedsPart.add(new DEROctetString(currentSeeds[i]));
- }
- result.add(new DERSequence(curSeedsPart));
-
- // --- Encode <nextNextSeeds>.
- ASN1EncodableVector nextNextSeedsPart = new ASN1EncodableVector();
- for (int i = 0; i < nextNextSeeds.length; i++)
- {
- nextNextSeedsPart.add(new DEROctetString(nextNextSeeds[i]));
- }
- result.add(new DERSequence(nextNextSeedsPart));
-
- // --- Encode <curAuth>.
- ASN1EncodableVector curAuthPart0 = new ASN1EncodableVector();
- ASN1EncodableVector curAuthPart1 = new ASN1EncodableVector();
- for (int i = 0; i < currentAuthPaths.length; i++)
- {
- for (int j = 0; j < currentAuthPaths[i].length; j++)
- {
- curAuthPart0.add(new DEROctetString(currentAuthPaths[i][j]));
- }
- curAuthPart1.add(new DERSequence(curAuthPart0));
- curAuthPart0 = new ASN1EncodableVector();
- }
- result.add(new DERSequence(curAuthPart1));
-
- // --- Encode <nextAuth>.
- ASN1EncodableVector nextAuthPart0 = new ASN1EncodableVector();
- ASN1EncodableVector nextAuthPart1 = new ASN1EncodableVector();
- for (int i = 0; i < nextAuthPaths.length; i++)
- {
- for (int j = 0; j < nextAuthPaths[i].length; j++)
- {
- nextAuthPart0.add(new DEROctetString(nextAuthPaths[i][j]));
- }
- nextAuthPart1.add(new DERSequence(nextAuthPart0));
- nextAuthPart0 = new ASN1EncodableVector();
- }
- result.add(new DERSequence(nextAuthPart1));
-
- // --- Encode <curTreehash>.
- ASN1EncodableVector seqOfTreehash0 = new ASN1EncodableVector();
- ASN1EncodableVector seqOfTreehash1 = new ASN1EncodableVector();
- ASN1EncodableVector seqOfStat = new ASN1EncodableVector();
- ASN1EncodableVector seqOfByte = new ASN1EncodableVector();
- ASN1EncodableVector seqOfInt = new ASN1EncodableVector();
-
- for (int i = 0; i < currentTreehash.length; i++)
- {
- for (int j = 0; j < currentTreehash[i].length; j++)
- {
- seqOfStat.add(new DERSequence(algorithms[0]));
-
- int tailLength = currentTreehash[i][j].getStatInt()[1];
-
- seqOfByte.add(new DEROctetString(currentTreehash[i][j]
- .getStatByte()[0]));
- seqOfByte.add(new DEROctetString(currentTreehash[i][j]
- .getStatByte()[1]));
- seqOfByte.add(new DEROctetString(currentTreehash[i][j]
- .getStatByte()[2]));
- for (int k = 0; k < tailLength; k++)
- {
- seqOfByte.add(new DEROctetString(currentTreehash[i][j]
- .getStatByte()[3 + k]));
- }
- seqOfStat.add(new DERSequence(seqOfByte));
- seqOfByte = new ASN1EncodableVector();
-
- seqOfInt.add(new ASN1Integer(
- currentTreehash[i][j].getStatInt()[0]));
- seqOfInt.add(new ASN1Integer(tailLength));
- seqOfInt.add(new ASN1Integer(
- currentTreehash[i][j].getStatInt()[2]));
- seqOfInt.add(new ASN1Integer(
- currentTreehash[i][j].getStatInt()[3]));
- seqOfInt.add(new ASN1Integer(
- currentTreehash[i][j].getStatInt()[4]));
- seqOfInt.add(new ASN1Integer(
- currentTreehash[i][j].getStatInt()[5]));
- for (int k = 0; k < tailLength; k++)
- {
- seqOfInt.add(new ASN1Integer(currentTreehash[i][j]
- .getStatInt()[6 + k]));
- }
- seqOfStat.add(new DERSequence(seqOfInt));
- seqOfInt = new ASN1EncodableVector();
-
- seqOfTreehash1.add(new DERSequence(seqOfStat));
- seqOfStat = new ASN1EncodableVector();
- }
- seqOfTreehash0.add(new DERSequence(seqOfTreehash1));
- seqOfTreehash1 = new ASN1EncodableVector();
- }
- result.add(new DERSequence(seqOfTreehash0));
-
- // --- Encode <nextTreehash>.
- seqOfTreehash0 = new ASN1EncodableVector();
- seqOfTreehash1 = new ASN1EncodableVector();
- seqOfStat = new ASN1EncodableVector();
- seqOfByte = new ASN1EncodableVector();
- seqOfInt = new ASN1EncodableVector();
-
- for (int i = 0; i < nextTreehash.length; i++)
- {
- for (int j = 0; j < nextTreehash[i].length; j++)
- {
- seqOfStat.add(new DERSequence(algorithms[0]));
-
- int tailLength = nextTreehash[i][j].getStatInt()[1];
-
- seqOfByte.add(new DEROctetString(nextTreehash[i][j]
- .getStatByte()[0]));
- seqOfByte.add(new DEROctetString(nextTreehash[i][j]
- .getStatByte()[1]));
- seqOfByte.add(new DEROctetString(nextTreehash[i][j]
- .getStatByte()[2]));
- for (int k = 0; k < tailLength; k++)
- {
- seqOfByte.add(new DEROctetString(nextTreehash[i][j]
- .getStatByte()[3 + k]));
- }
- seqOfStat.add(new DERSequence(seqOfByte));
- seqOfByte = new ASN1EncodableVector();
-
- seqOfInt
- .add(new ASN1Integer(nextTreehash[i][j].getStatInt()[0]));
- seqOfInt.add(new ASN1Integer(tailLength));
- seqOfInt
- .add(new ASN1Integer(nextTreehash[i][j].getStatInt()[2]));
- seqOfInt
- .add(new ASN1Integer(nextTreehash[i][j].getStatInt()[3]));
- seqOfInt
- .add(new ASN1Integer(nextTreehash[i][j].getStatInt()[4]));
- seqOfInt
- .add(new ASN1Integer(nextTreehash[i][j].getStatInt()[5]));
- for (int k = 0; k < tailLength; k++)
- {
- seqOfInt.add(new ASN1Integer(nextTreehash[i][j]
- .getStatInt()[6 + k]));
- }
- seqOfStat.add(new DERSequence(seqOfInt));
- seqOfInt = new ASN1EncodableVector();
-
- seqOfTreehash1.add(new DERSequence(seqOfStat));
- seqOfStat = new ASN1EncodableVector();
- }
- seqOfTreehash0.add(new DERSequence(new DERSequence(seqOfTreehash1)));
- seqOfTreehash1 = new ASN1EncodableVector();
- }
- result.add(new DERSequence(seqOfTreehash0));
-
- // --- Encode <keep>.
- ASN1EncodableVector keepPart0 = new ASN1EncodableVector();
- ASN1EncodableVector keepPart1 = new ASN1EncodableVector();
- for (int i = 0; i < keep.length; i++)
- {
- for (int j = 0; j < keep[i].length; j++)
- {
- keepPart0.add(new DEROctetString(keep[i][j]));
- }
- keepPart1.add(new DERSequence(keepPart0));
- keepPart0 = new ASN1EncodableVector();
- }
- result.add(new DERSequence(keepPart1));
-
- // --- Encode <curStack>.
- ASN1EncodableVector curStackPart0 = new ASN1EncodableVector();
- ASN1EncodableVector curStackPart1 = new ASN1EncodableVector();
- for (int i = 0; i < currentStack.length; i++)
- {
- for (int j = 0; j < currentStack[i].size(); j++)
- {
- curStackPart0.add(new DEROctetString((byte[])currentStack[i]
- .elementAt(j)));
- }
- curStackPart1.add(new DERSequence(curStackPart0));
- curStackPart0 = new ASN1EncodableVector();
- }
- result.add(new DERSequence(curStackPart1));
-
- // --- Encode <nextStack>.
- ASN1EncodableVector nextStackPart0 = new ASN1EncodableVector();
- ASN1EncodableVector nextStackPart1 = new ASN1EncodableVector();
- for (int i = 0; i < nextStack.length; i++)
- {
- for (int j = 0; j < nextStack[i].size(); j++)
- {
- nextStackPart0.add(new DEROctetString((byte[])nextStack[i]
- .elementAt(j)));
- }
- nextStackPart1.add(new DERSequence(nextStackPart0));
- nextStackPart0 = new ASN1EncodableVector();
- }
- result.add(new DERSequence(nextStackPart1));
-
- // --- Encode <curRetain>.
- ASN1EncodableVector currentRetainPart0 = new ASN1EncodableVector();
- ASN1EncodableVector currentRetainPart1 = new ASN1EncodableVector();
- ASN1EncodableVector currentRetainPart2 = new ASN1EncodableVector();
- for (int i = 0; i < currentRetain.length; i++)
- {
- for (int j = 0; j < currentRetain[i].length; j++)
- {
- for (int k = 0; k < currentRetain[i][j].size(); k++)
- {
- currentRetainPart0.add(new DEROctetString(
- (byte[])currentRetain[i][j].elementAt(k)));
- }
- currentRetainPart1.add(new DERSequence(currentRetainPart0));
- currentRetainPart0 = new ASN1EncodableVector();
- }
- currentRetainPart2.add(new DERSequence(currentRetainPart1));
- currentRetainPart1 = new ASN1EncodableVector();
- }
- result.add(new DERSequence(currentRetainPart2));
-
- // --- Encode <nextRetain>.
- ASN1EncodableVector nextRetainPart0 = new ASN1EncodableVector();
- ASN1EncodableVector nextRetainPart1 = new ASN1EncodableVector();
- ASN1EncodableVector nextRetainPart2 = new ASN1EncodableVector();
- for (int i = 0; i < nextRetain.length; i++)
- {
- for (int j = 0; j < nextRetain[i].length; j++)
- {
- for (int k = 0; k < nextRetain[i][j].size(); k++)
- {
- nextRetainPart0.add(new DEROctetString(
- (byte[])nextRetain[i][j].elementAt(k)));
- }
- nextRetainPart1.add(new DERSequence(nextRetainPart0));
- nextRetainPart0 = new ASN1EncodableVector();
- }
- nextRetainPart2.add(new DERSequence(nextRetainPart1));
- nextRetainPart1 = new ASN1EncodableVector();
- }
- result.add(new DERSequence(nextRetainPart2));
-
- // --- Encode <nextNextLeaf>.
- ASN1EncodableVector seqOfLeaf = new ASN1EncodableVector();
- seqOfStat = new ASN1EncodableVector();
- seqOfByte = new ASN1EncodableVector();
- seqOfInt = new ASN1EncodableVector();
-
- for (int i = 0; i < nextNextLeaf.length; i++)
- {
- seqOfStat.add(new DERSequence(algorithms[0]));
-
- byte[][] tempByte = nextNextLeaf[i].getStatByte();
- seqOfByte.add(new DEROctetString(tempByte[0]));
- seqOfByte.add(new DEROctetString(tempByte[1]));
- seqOfByte.add(new DEROctetString(tempByte[2]));
- seqOfByte.add(new DEROctetString(tempByte[3]));
- seqOfStat.add(new DERSequence(seqOfByte));
- seqOfByte = new ASN1EncodableVector();
-
- int[] tempInt = nextNextLeaf[i].getStatInt();
- seqOfInt.add(new ASN1Integer(tempInt[0]));
- seqOfInt.add(new ASN1Integer(tempInt[1]));
- seqOfInt.add(new ASN1Integer(tempInt[2]));
- seqOfInt.add(new ASN1Integer(tempInt[3]));
- seqOfStat.add(new DERSequence(seqOfInt));
- seqOfInt = new ASN1EncodableVector();
-
- seqOfLeaf.add(new DERSequence(seqOfStat));
- seqOfStat = new ASN1EncodableVector();
- }
- result.add(new DERSequence(seqOfLeaf));
-
- // --- Encode <upperLEAF>.
- ASN1EncodableVector seqOfUpperLeaf = new ASN1EncodableVector();
- seqOfStat = new ASN1EncodableVector();
- seqOfByte = new ASN1EncodableVector();
- seqOfInt = new ASN1EncodableVector();
-
- for (int i = 0; i < upperLeaf.length; i++)
- {
- seqOfStat.add(new DERSequence(algorithms[0]));
-
- byte[][] tempByte = upperLeaf[i].getStatByte();
- seqOfByte.add(new DEROctetString(tempByte[0]));
- seqOfByte.add(new DEROctetString(tempByte[1]));
- seqOfByte.add(new DEROctetString(tempByte[2]));
- seqOfByte.add(new DEROctetString(tempByte[3]));
- seqOfStat.add(new DERSequence(seqOfByte));
- seqOfByte = new ASN1EncodableVector();
-
- int[] tempInt = upperLeaf[i].getStatInt();
- seqOfInt.add(new ASN1Integer(tempInt[0]));
- seqOfInt.add(new ASN1Integer(tempInt[1]));
- seqOfInt.add(new ASN1Integer(tempInt[2]));
- seqOfInt.add(new ASN1Integer(tempInt[3]));
- seqOfStat.add(new DERSequence(seqOfInt));
- seqOfInt = new ASN1EncodableVector();
-
- seqOfUpperLeaf.add(new DERSequence(seqOfStat));
- seqOfStat = new ASN1EncodableVector();
- }
- result.add(new DERSequence(seqOfUpperLeaf));
-
- // encode <upperTreehashLeaf>
- ASN1EncodableVector seqOfUpperTreehashLeaf = new ASN1EncodableVector();
- seqOfStat = new ASN1EncodableVector();
- seqOfByte = new ASN1EncodableVector();
- seqOfInt = new ASN1EncodableVector();
-
- for (int i = 0; i < upperTreehashLeaf.length; i++)
- {
- seqOfStat.add(new DERSequence(algorithms[0]));
-
- byte[][] tempByte = upperTreehashLeaf[i].getStatByte();
- seqOfByte.add(new DEROctetString(tempByte[0]));
- seqOfByte.add(new DEROctetString(tempByte[1]));
- seqOfByte.add(new DEROctetString(tempByte[2]));
- seqOfByte.add(new DEROctetString(tempByte[3]));
- seqOfStat.add(new DERSequence(seqOfByte));
- seqOfByte = new ASN1EncodableVector();
-
- int[] tempInt = upperTreehashLeaf[i].getStatInt();
- seqOfInt.add(new ASN1Integer(tempInt[0]));
- seqOfInt.add(new ASN1Integer(tempInt[1]));
- seqOfInt.add(new ASN1Integer(tempInt[2]));
- seqOfInt.add(new ASN1Integer(tempInt[3]));
- seqOfStat.add(new DERSequence(seqOfInt));
- seqOfInt = new ASN1EncodableVector();
-
- seqOfUpperTreehashLeaf.add(new DERSequence(seqOfStat));
- seqOfStat = new ASN1EncodableVector();
- }
- result.add(new DERSequence(seqOfUpperTreehashLeaf));
-
- // --- Encode <minTreehash>.
- ASN1EncodableVector minTreehashPart = new ASN1EncodableVector();
- for (int i = 0; i < minTreehash.length; i++)
- {
- minTreehashPart.add(new ASN1Integer(minTreehash[i]));
- }
- result.add(new DERSequence(minTreehashPart));
-
- // --- Encode <nextRoot>.
- ASN1EncodableVector nextRootPart = new ASN1EncodableVector();
- for (int i = 0; i < nextRoot.length; i++)
- {
- nextRootPart.add(new DEROctetString(nextRoot[i]));
- }
- result.add(new DERSequence(nextRootPart));
-
- // --- Encode <nextNextRoot>.
- ASN1EncodableVector seqOfnextNextRoot = new ASN1EncodableVector();
- ASN1EncodableVector seqOfnnRStats = new ASN1EncodableVector();
- ASN1EncodableVector seqOfnnRStrings = new ASN1EncodableVector();
- ASN1EncodableVector seqOfnnRBytes = new ASN1EncodableVector();
- ASN1EncodableVector seqOfnnRInts = new ASN1EncodableVector();
- ASN1EncodableVector seqOfnnRTreehash = new ASN1EncodableVector();
- ASN1EncodableVector seqOfnnRRetain = new ASN1EncodableVector();
-
- for (int i = 0; i < nextNextRoot.length; i++)
- {
- seqOfnnRStats.add(new DERSequence(algorithms[0]));
- seqOfnnRStrings = new ASN1EncodableVector();
-
- int heightOfTree = nextNextRoot[i].getStatInt()[0];
- int tailLength = nextNextRoot[i].getStatInt()[7];
-
- seqOfnnRBytes.add(new DEROctetString(
- nextNextRoot[i].getStatByte()[0]));
- for (int j = 0; j < heightOfTree; j++)
- {
- seqOfnnRBytes.add(new DEROctetString(nextNextRoot[i]
- .getStatByte()[1 + j]));
- }
- for (int j = 0; j < tailLength; j++)
- {
- seqOfnnRBytes.add(new DEROctetString(nextNextRoot[i]
- .getStatByte()[1 + heightOfTree + j]));
- }
-
- seqOfnnRStats.add(new DERSequence(seqOfnnRBytes));
- seqOfnnRBytes = new ASN1EncodableVector();
-
- seqOfnnRInts.add(new ASN1Integer(heightOfTree));
- seqOfnnRInts.add(new ASN1Integer(nextNextRoot[i].getStatInt()[1]));
- seqOfnnRInts.add(new ASN1Integer(nextNextRoot[i].getStatInt()[2]));
- seqOfnnRInts.add(new ASN1Integer(nextNextRoot[i].getStatInt()[3]));
- seqOfnnRInts.add(new ASN1Integer(nextNextRoot[i].getStatInt()[4]));
- seqOfnnRInts.add(new ASN1Integer(nextNextRoot[i].getStatInt()[5]));
- seqOfnnRInts.add(new ASN1Integer(nextNextRoot[i].getStatInt()[6]));
- seqOfnnRInts.add(new ASN1Integer(tailLength));
- for (int j = 0; j < heightOfTree; j++)
- {
- seqOfnnRInts.add(new ASN1Integer(
- nextNextRoot[i].getStatInt()[8 + j]));
- }
- for (int j = 0; j < tailLength; j++)
- {
- seqOfnnRInts.add(new ASN1Integer(nextNextRoot[i].getStatInt()[8
- + heightOfTree + j]));
- }
-
- seqOfnnRStats.add(new DERSequence(seqOfnnRInts));
- seqOfnnRInts = new ASN1EncodableVector();
-
- // add treehash of nextNextRoot object
- // ----------------------------
- seqOfStat = new ASN1EncodableVector();
- seqOfByte = new ASN1EncodableVector();
- seqOfInt = new ASN1EncodableVector();
-
- if (nextNextRoot[i].getTreehash() != null)
- {
- for (int j = 0; j < nextNextRoot[i].getTreehash().length; j++)
- {
- seqOfStat.add(new DERSequence(algorithms[0]));
-
- tailLength = nextNextRoot[i].getTreehash()[j].getStatInt()[1];
-
- seqOfByte.add(new DEROctetString(nextNextRoot[i]
- .getTreehash()[j].getStatByte()[0]));
- seqOfByte.add(new DEROctetString(nextNextRoot[i]
- .getTreehash()[j].getStatByte()[1]));
- seqOfByte.add(new DEROctetString(nextNextRoot[i]
- .getTreehash()[j].getStatByte()[2]));
- for (int k = 0; k < tailLength; k++)
- {
- seqOfByte.add(new DEROctetString(nextNextRoot[i]
- .getTreehash()[j].getStatByte()[3 + k]));
- }
- seqOfStat.add(new DERSequence(seqOfByte));
- seqOfByte = new ASN1EncodableVector();
-
- seqOfInt.add(new ASN1Integer(
- nextNextRoot[i].getTreehash()[j].getStatInt()[0]));
- seqOfInt.add(new ASN1Integer(tailLength));
- seqOfInt.add(new ASN1Integer(
- nextNextRoot[i].getTreehash()[j].getStatInt()[2]));
- seqOfInt.add(new ASN1Integer(
- nextNextRoot[i].getTreehash()[j].getStatInt()[3]));
- seqOfInt.add(new ASN1Integer(
- nextNextRoot[i].getTreehash()[j].getStatInt()[4]));
- seqOfInt.add(new ASN1Integer(
- nextNextRoot[i].getTreehash()[j].getStatInt()[5]));
- for (int k = 0; k < tailLength; k++)
- {
- seqOfInt.add(new ASN1Integer(nextNextRoot[i]
- .getTreehash()[j].getStatInt()[6 + k]));
- }
- seqOfStat.add(new DERSequence(seqOfInt));
- seqOfInt = new ASN1EncodableVector();
-
- seqOfnnRTreehash.add(new DERSequence(seqOfStat));
- seqOfStat = new ASN1EncodableVector();
- }
- }
- // ----------------------------
- seqOfnnRStats.add(new DERSequence(seqOfnnRTreehash));
- seqOfnnRTreehash = new ASN1EncodableVector();
-
- // encode retain of nextNextRoot
- // ----------------------------
- // --- Encode <curRetain>.
- currentRetainPart0 = new ASN1EncodableVector();
- if (nextNextRoot[i].getRetain() != null)
- {
- for (int j = 0; j < nextNextRoot[i].getRetain().length; j++)
- {
- for (int k = 0; k < nextNextRoot[i].getRetain()[j].size(); k++)
- {
- currentRetainPart0.add(new DEROctetString(
- (byte[])nextNextRoot[i].getRetain()[j]
- .elementAt(k)));
- }
- seqOfnnRRetain.add(new DERSequence(currentRetainPart0));
- currentRetainPart0 = new ASN1EncodableVector();
- }
- }
- // ----------------------------
- seqOfnnRStats.add(new DERSequence(seqOfnnRRetain));
- seqOfnnRRetain = new ASN1EncodableVector();
-
- seqOfnextNextRoot.add(new DERSequence(seqOfnnRStats));
- seqOfnnRStats = new ASN1EncodableVector();
- }
- result.add(new DERSequence(seqOfnextNextRoot));
-
- // --- Encode <curRootSig>.
- ASN1EncodableVector curRootSigPart = new ASN1EncodableVector();
- for (int i = 0; i < currentRootSig.length; i++)
- {
- curRootSigPart.add(new DEROctetString(currentRootSig[i]));
- }
- result.add(new DERSequence(curRootSigPart));
-
- // --- Encode <nextRootSig>.
- ASN1EncodableVector seqOfnextRootSigs = new ASN1EncodableVector();
- ASN1EncodableVector seqOfnRSStats = new ASN1EncodableVector();
- ASN1EncodableVector seqOfnRSStrings = new ASN1EncodableVector();
- ASN1EncodableVector seqOfnRSBytes = new ASN1EncodableVector();
- ASN1EncodableVector seqOfnRSInts = new ASN1EncodableVector();
-
- for (int i = 0; i < nextRootSig.length; i++)
- {
- seqOfnRSStats.add(new DERSequence(algorithms[0]));
- seqOfnRSStrings = new ASN1EncodableVector();
-
- seqOfnRSBytes.add(new DEROctetString(
- nextRootSig[i].getStatByte()[0]));
- seqOfnRSBytes.add(new DEROctetString(
- nextRootSig[i].getStatByte()[1]));
- seqOfnRSBytes.add(new DEROctetString(
- nextRootSig[i].getStatByte()[2]));
- seqOfnRSBytes.add(new DEROctetString(
- nextRootSig[i].getStatByte()[3]));
- seqOfnRSBytes.add(new DEROctetString(
- nextRootSig[i].getStatByte()[4]));
-
- seqOfnRSStats.add(new DERSequence(seqOfnRSBytes));
- seqOfnRSBytes = new ASN1EncodableVector();
-
- seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[0]));
- seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[1]));
- seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[2]));
- seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[3]));
- seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[4]));
- seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[5]));
- seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[6]));
- seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[7]));
- seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[8]));
-
- seqOfnRSStats.add(new DERSequence(seqOfnRSInts));
- seqOfnRSInts = new ASN1EncodableVector();
-
- seqOfnextRootSigs.add(new DERSequence(seqOfnRSStats));
- seqOfnRSStats = new ASN1EncodableVector();
- }
- result.add(new DERSequence(seqOfnextRootSigs));
-
- // --- Encode <parameterset>.
- ASN1EncodableVector parSetPart0 = new ASN1EncodableVector();
- ASN1EncodableVector parSetPart1 = new ASN1EncodableVector();
- ASN1EncodableVector parSetPart2 = new ASN1EncodableVector();
- ASN1EncodableVector parSetPart3 = new ASN1EncodableVector();
-
- for (int i = 0; i < gmssParameterset.getHeightOfTrees().length; i++)
- {
- parSetPart1.add(new ASN1Integer(
- gmssParameterset.getHeightOfTrees()[i]));
- parSetPart2.add(new ASN1Integer(gmssParameterset
- .getWinternitzParameter()[i]));
- parSetPart3.add(new ASN1Integer(gmssParameterset.getK()[i]));
- }
- parSetPart0.add(new ASN1Integer(gmssParameterset.getNumOfLayers()));
- parSetPart0.add(new DERSequence(parSetPart1));
- parSetPart0.add(new DERSequence(parSetPart2));
- parSetPart0.add(new DERSequence(parSetPart3));
- result.add(new DERSequence(parSetPart0));
-
- // --- Encode <names>.
- ASN1EncodableVector namesPart = new ASN1EncodableVector();
-
- for (int i = 0; i < algorithms.length; i++)
- {
- namesPart.add(algorithms[i]);
- }
-
- result.add(new DERSequence(namesPart));
- return new DERSequence(result);
-
- }
-
- private static int checkBigIntegerInIntRange(ASN1Encodable a)
- {
- BigInteger b = ((ASN1Integer)a).getValue();
- if ((b.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) ||
- (b.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0))
- {
- throw new IllegalArgumentException("BigInteger not in Range: " + b.toString());
- }
- return b.intValue();
- }
-
-
- public ASN1Primitive toASN1Primitive()
- {
- return this.primitive;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/asn1/GMSSPublicKey.java b/core/src/main/java/org/bouncycastle/pqc/asn1/GMSSPublicKey.java
deleted file mode 100644
index fc5c4f2b..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/asn1/GMSSPublicKey.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package org.bouncycastle.pqc.asn1;
-
-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;
-
-/**
- * This class implements an ASN.1 encoded GMSS public key. The ASN.1 definition
- * of this structure is:
- * <pre>
- * GMSSPublicKey ::= SEQUENCE{
- * version INTEGER
- * publicKey OCTET STRING
- * }
- * </pre>
- */
-public class GMSSPublicKey
- extends ASN1Object
-{
- private ASN1Integer version;
- private byte[] publicKey;
-
- private GMSSPublicKey(ASN1Sequence seq)
- {
- if (seq.size() != 2)
- {
- throw new IllegalArgumentException("size of seq = " + seq.size());
- }
-
- this.version = ASN1Integer.getInstance(seq.getObjectAt(0));
- this.publicKey = ASN1OctetString.getInstance(seq.getObjectAt(1)).getOctets();
- }
-
- public GMSSPublicKey(byte[] publicKeyBytes)
- {
- this.version = new ASN1Integer(0);
- this.publicKey = publicKeyBytes;
- }
-
- public static GMSSPublicKey getInstance(Object o)
- {
- if (o instanceof GMSSPublicKey)
- {
- return (GMSSPublicKey)o;
- }
- else if (o != null)
- {
- return new GMSSPublicKey(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public byte[] getPublicKey()
- {
- return Arrays.clone(publicKey);
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(version);
- v.add(new DEROctetString(publicKey));
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/asn1/McElieceCCA2PrivateKey.java b/core/src/main/java/org/bouncycastle/pqc/asn1/McElieceCCA2PrivateKey.java
deleted file mode 100644
index 192484f8..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/asn1/McElieceCCA2PrivateKey.java
+++ /dev/null
@@ -1,173 +0,0 @@
-package org.bouncycastle.pqc.asn1;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-
-import org.bouncycastle.pqc.math.linearalgebra.GF2Matrix;
-import org.bouncycastle.pqc.math.linearalgebra.GF2mField;
-import org.bouncycastle.pqc.math.linearalgebra.Permutation;
-import org.bouncycastle.pqc.math.linearalgebra.PolynomialGF2mSmallM;
-
-public class McElieceCCA2PrivateKey
- extends ASN1Object
-{
- private ASN1ObjectIdentifier oid;
- private int n;
- private int k;
- private byte[] encField;
- private byte[] encGp;
- private byte[] encP;
- private byte[] encH;
- private byte[][] encqInv;
-
-
- public McElieceCCA2PrivateKey(ASN1ObjectIdentifier oid, int n, int k, GF2mField field, PolynomialGF2mSmallM goppaPoly, Permutation p, GF2Matrix h, PolynomialGF2mSmallM[] qInv)
- {
- this.oid = oid;
- this.n = n;
- this.k = k;
- this.encField = field.getEncoded();
- this.encGp = goppaPoly.getEncoded();
- this.encP = p.getEncoded();
- this.encH = h.getEncoded();
- this.encqInv = new byte[qInv.length][];
-
- for (int i = 0; i != qInv.length; i++)
- {
- encqInv[i] = qInv[i].getEncoded();
- }
- }
-
- private McElieceCCA2PrivateKey(ASN1Sequence seq)
- {
- oid = ((ASN1ObjectIdentifier)seq.getObjectAt(0));
-
- BigInteger bigN = ((ASN1Integer)seq.getObjectAt(1)).getValue();
- n = bigN.intValue();
-
- BigInteger bigK = ((ASN1Integer)seq.getObjectAt(2)).getValue();
- k = bigK.intValue();
-
- encField = ((ASN1OctetString)seq.getObjectAt(3)).getOctets();
-
- encGp = ((ASN1OctetString)seq.getObjectAt(4)).getOctets();
-
- encP = ((ASN1OctetString)seq.getObjectAt(5)).getOctets();
-
- encH = ((ASN1OctetString)seq.getObjectAt(6)).getOctets();
-
- ASN1Sequence asnQInv = (ASN1Sequence)seq.getObjectAt(7);
- encqInv = new byte[asnQInv.size()][];
- for (int i = 0; i < asnQInv.size(); i++)
- {
- encqInv[i] = ((ASN1OctetString)asnQInv.getObjectAt(i)).getOctets();
- }
- }
-
- public ASN1ObjectIdentifier getOID()
- {
- return oid;
- }
-
- public int getN()
- {
- return n;
- }
-
- public int getK()
- {
- return k;
- }
-
- public GF2mField getField()
- {
- return new GF2mField(encField);
- }
-
- public PolynomialGF2mSmallM getGoppaPoly()
- {
- return new PolynomialGF2mSmallM(this.getField(), encGp);
- }
-
- public Permutation getP()
- {
- return new Permutation(encP);
- }
-
- public GF2Matrix getH()
- {
- return new GF2Matrix(encH);
- }
-
- public PolynomialGF2mSmallM[] getQInv()
- {
- PolynomialGF2mSmallM[] qInv = new PolynomialGF2mSmallM[encqInv.length];
- GF2mField field = this.getField();
-
- for (int i = 0; i < encqInv.length; i++)
- {
- qInv[i] = new PolynomialGF2mSmallM(field, encqInv[i]);
- }
-
- return qInv;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
-
- ASN1EncodableVector v = new ASN1EncodableVector();
- // encode <oidString>
- v.add(oid);
- // encode <n>
- v.add(new ASN1Integer(n));
-
- // encode <k>
- v.add(new ASN1Integer(k));
-
- // encode <field>
- v.add(new DEROctetString(encField));
-
- // encode <gp>
- v.add(new DEROctetString(encGp));
-
- // encode <p>
- v.add(new DEROctetString(encP));
-
- // encode <h>
- v.add(new DEROctetString(encH));
-
- // encode <q>
- ASN1EncodableVector asnQInv = new ASN1EncodableVector();
- for (int i = 0; i < encqInv.length; i++)
- {
- asnQInv.add(new DEROctetString(encqInv[i]));
- }
-
- v.add(new DERSequence(asnQInv));
-
- return new DERSequence(v);
- }
-
- public static McElieceCCA2PrivateKey getInstance(Object o)
- {
- if (o instanceof McElieceCCA2PrivateKey)
- {
- return (McElieceCCA2PrivateKey)o;
- }
- else if (o != null)
- {
- return new McElieceCCA2PrivateKey(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/asn1/McElieceCCA2PublicKey.java b/core/src/main/java/org/bouncycastle/pqc/asn1/McElieceCCA2PublicKey.java
deleted file mode 100644
index adb5e46a..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/asn1/McElieceCCA2PublicKey.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.bouncycastle.pqc.asn1;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.pqc.math.linearalgebra.GF2Matrix;
-
-public class McElieceCCA2PublicKey
- extends ASN1Object
-{
- private ASN1ObjectIdentifier oid;
- private int n;
- private int t;
-
- private byte[] matrixG;
-
- public McElieceCCA2PublicKey(ASN1ObjectIdentifier oid, int n, int t, GF2Matrix g)
- {
- this.oid = oid;
- this.n = n;
- this.t = t;
- this.matrixG = g.getEncoded();
- }
-
- private McElieceCCA2PublicKey(ASN1Sequence seq)
- {
- oid = ((ASN1ObjectIdentifier)seq.getObjectAt(0));
- BigInteger bigN = ((ASN1Integer)seq.getObjectAt(1)).getValue();
- n = bigN.intValue();
-
- BigInteger bigT = ((ASN1Integer)seq.getObjectAt(2)).getValue();
- t = bigT.intValue();
-
- matrixG = ((ASN1OctetString)seq.getObjectAt(3)).getOctets();
- }
-
- public ASN1ObjectIdentifier getOID()
- {
- return oid;
- }
-
- public int getN()
- {
- return n;
- }
-
- public int getT()
- {
- return t;
- }
-
- public GF2Matrix getG()
- {
- return new GF2Matrix(matrixG);
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- // encode <oidString>
- v.add(oid);
-
- // encode <n>
- v.add(new ASN1Integer(n));
-
- // encode <t>
- v.add(new ASN1Integer(t));
-
- // encode <matrixG>
- v.add(new DEROctetString(matrixG));
-
- return new DERSequence(v);
- }
-
- public static McElieceCCA2PublicKey getInstance(Object o)
- {
- if (o instanceof McElieceCCA2PublicKey)
- {
- return (McElieceCCA2PublicKey)o;
- }
- else if (o != null)
- {
- return new McElieceCCA2PublicKey(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/asn1/McEliecePrivateKey.java b/core/src/main/java/org/bouncycastle/pqc/asn1/McEliecePrivateKey.java
deleted file mode 100644
index 4bf2f822..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/asn1/McEliecePrivateKey.java
+++ /dev/null
@@ -1,197 +0,0 @@
-package org.bouncycastle.pqc.asn1;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.pqc.math.linearalgebra.GF2Matrix;
-import org.bouncycastle.pqc.math.linearalgebra.GF2mField;
-import org.bouncycastle.pqc.math.linearalgebra.Permutation;
-import org.bouncycastle.pqc.math.linearalgebra.PolynomialGF2mSmallM;
-
-public class McEliecePrivateKey
- extends ASN1Object
-{
- private ASN1ObjectIdentifier oid;
- private int n;
- private int k;
- private byte[] encField;
- private byte[] encGp;
- private byte[] encSInv;
- private byte[] encP1;
- private byte[] encP2;
- private byte[] encH;
- private byte[][] encqInv;
-
-
- public McEliecePrivateKey(ASN1ObjectIdentifier oid, int n, int k, GF2mField field, PolynomialGF2mSmallM goppaPoly, GF2Matrix sInv, Permutation p1, Permutation p2, GF2Matrix h, PolynomialGF2mSmallM[] qInv)
- {
- this.oid = oid;
- this.n = n;
- this.k = k;
- this.encField = field.getEncoded();
- this.encGp = goppaPoly.getEncoded();
- this.encSInv = sInv.getEncoded();
- this.encP1 = p1.getEncoded();
- this.encP2 = p2.getEncoded();
- this.encH = h.getEncoded();
- this.encqInv = new byte[qInv.length][];
-
- for (int i = 0; i != qInv.length; i++)
- {
- encqInv[i] = qInv[i].getEncoded();
- }
- }
-
- public static McEliecePrivateKey getInstance(Object o)
- {
- if (o instanceof McEliecePrivateKey)
- {
- return (McEliecePrivateKey)o;
- }
- else if (o != null)
- {
- return new McEliecePrivateKey(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- private McEliecePrivateKey(ASN1Sequence seq)
- {
- // <oidString>
- oid = ((ASN1ObjectIdentifier)seq.getObjectAt(0));
-
- BigInteger bigN = ((ASN1Integer)seq.getObjectAt(1)).getValue();
- n = bigN.intValue();
-
- BigInteger bigK = ((ASN1Integer)seq.getObjectAt(2)).getValue();
- k = bigK.intValue();
-
- encField = ((ASN1OctetString)seq.getObjectAt(3)).getOctets();
-
- encGp = ((ASN1OctetString)seq.getObjectAt(4)).getOctets();
-
- encSInv = ((ASN1OctetString)seq.getObjectAt(5)).getOctets();
-
- encP1 = ((ASN1OctetString)seq.getObjectAt(6)).getOctets();
-
- encP2 = ((ASN1OctetString)seq.getObjectAt(7)).getOctets();
-
- encH = ((ASN1OctetString)seq.getObjectAt(8)).getOctets();
-
- ASN1Sequence asnQInv = (ASN1Sequence)seq.getObjectAt(9);
- encqInv = new byte[asnQInv.size()][];
- for (int i = 0; i < asnQInv.size(); i++)
- {
- encqInv[i] = ((ASN1OctetString)asnQInv.getObjectAt(i)).getOctets();
- }
- }
-
- public ASN1ObjectIdentifier getOID()
- {
- return oid;
- }
-
- public int getN()
- {
- return n;
- }
-
- public int getK()
- {
- return k;
- }
-
- public GF2mField getField()
- {
- return new GF2mField(encField);
- }
-
- public PolynomialGF2mSmallM getGoppaPoly()
- {
- return new PolynomialGF2mSmallM(this.getField(), encGp);
- }
-
- public GF2Matrix getSInv()
- {
- return new GF2Matrix(encSInv);
- }
-
- public Permutation getP1()
- {
- return new Permutation(encP1);
- }
-
- public Permutation getP2()
- {
- return new Permutation(encP2);
- }
-
- public GF2Matrix getH()
- {
- return new GF2Matrix(encH);
- }
-
- public PolynomialGF2mSmallM[] getQInv()
- {
- PolynomialGF2mSmallM[] qInv = new PolynomialGF2mSmallM[encqInv.length];
- GF2mField field = this.getField();
-
- for (int i = 0; i < encqInv.length; i++)
- {
- qInv[i] = new PolynomialGF2mSmallM(field, encqInv[i]);
- }
-
- return qInv;
- }
-
- public ASN1Primitive toASN1Primitive()
- {
-
- ASN1EncodableVector v = new ASN1EncodableVector();
- // encode <oidString>
- v.add(oid);
- // encode <n>
- v.add(new ASN1Integer(n));
-
- // encode <k>
- v.add(new ASN1Integer(k));
-
- // encode <fieldPoly>
- v.add(new DEROctetString(encField));
-
- // encode <goppaPoly>
- v.add(new DEROctetString(encGp));
-
- // encode <sInv>
- v.add(new DEROctetString(encSInv));
-
- // encode <p1>
- v.add(new DEROctetString(encP1));
-
- // encode <p2>
- v.add(new DEROctetString(encP2));
-
- // encode <h>
- v.add(new DEROctetString(encH));
-
- // encode <q>
- ASN1EncodableVector asnQInv = new ASN1EncodableVector();
- for (int i = 0; i < encqInv.length; i++)
- {
- asnQInv.add(new DEROctetString(encqInv[i]));
- }
-
- v.add(new DERSequence(asnQInv));
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/asn1/McEliecePublicKey.java b/core/src/main/java/org/bouncycastle/pqc/asn1/McEliecePublicKey.java
deleted file mode 100644
index 6f1efc09..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/asn1/McEliecePublicKey.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package org.bouncycastle.pqc.asn1;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.pqc.math.linearalgebra.GF2Matrix;
-
-public class McEliecePublicKey
- extends ASN1Object
-{
-
- private ASN1ObjectIdentifier oid;
- private int n;
- private int t;
-
- private byte[] matrixG;
-
- public McEliecePublicKey(ASN1ObjectIdentifier oid, int n, int t, GF2Matrix g)
- {
- this.oid = oid;
- this.n = n;
- this.t = t;
- this.matrixG = g.getEncoded();
- }
-
- private McEliecePublicKey(ASN1Sequence seq)
- {
- oid = ((ASN1ObjectIdentifier)seq.getObjectAt(0));
- BigInteger bigN = ((ASN1Integer)seq.getObjectAt(1)).getValue();
- n = bigN.intValue();
-
- BigInteger bigT = ((ASN1Integer)seq.getObjectAt(2)).getValue();
- t = bigT.intValue();
-
- matrixG = ((ASN1OctetString)seq.getObjectAt(3)).getOctets();
- }
-
- public ASN1ObjectIdentifier getOID()
- {
- return oid;
- }
-
- public int getN()
- {
- return n;
- }
-
- public int getT()
- {
- return t;
- }
-
- public GF2Matrix getG()
- {
- return new GF2Matrix(matrixG);
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- // encode <oidString>
- v.add(oid);
-
- // encode <n>
- v.add(new ASN1Integer(n));
-
- // encode <t>
- v.add(new ASN1Integer(t));
-
- // encode <matrixG>
- v.add(new DEROctetString(matrixG));
-
- return new DERSequence(v);
- }
-
- public static McEliecePublicKey getInstance(Object o)
- {
- if (o instanceof McEliecePublicKey)
- {
- return (McEliecePublicKey)o;
- }
- else if (o != null)
- {
- return new McEliecePublicKey(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/asn1/PQCObjectIdentifiers.java b/core/src/main/java/org/bouncycastle/pqc/asn1/PQCObjectIdentifiers.java
deleted file mode 100644
index d93d9952..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/asn1/PQCObjectIdentifiers.java
+++ /dev/null
@@ -1,46 +0,0 @@
-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");
-
- /** 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");
-
- /** 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");
-
- /** 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");
-
- /** 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/core/src/main/java/org/bouncycastle/pqc/asn1/ParSet.java b/core/src/main/java/org/bouncycastle/pqc/asn1/ParSet.java
deleted file mode 100644
index dee56a52..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/asn1/ParSet.java
+++ /dev/null
@@ -1,140 +0,0 @@
-package org.bouncycastle.pqc.asn1;
-
-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.DERSequence;
-import org.bouncycastle.util.Arrays;
-
-/**
- * <pre>
- * ParSet ::= SEQUENCE {
- * T INTEGER
- * h SEQUENCE OF INTEGER
- * w SEQUENCE OF INTEGER
- * K SEQUENCE OF INTEGER
- * }
- * </pre>
- */
-public class ParSet
- extends ASN1Object
-{
- private static final BigInteger ZERO = BigInteger.valueOf(0);
-
- private int t;
- private int[] h;
- private int[] w;
- private int[] k;
-
- private static int checkBigIntegerInIntRangeAndPositive(BigInteger b)
- {
- if ((b.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) ||
- (b.compareTo(ZERO) <= 0))
- {
- throw new IllegalArgumentException("BigInteger not in Range: " + b.toString());
- }
- return b.intValue();
- }
-
- private ParSet(ASN1Sequence seq)
- {
- if (seq.size() != 4)
- {
- throw new IllegalArgumentException("sie of seqOfParams = " + seq.size());
- }
- BigInteger asn1int = ((ASN1Integer)seq.getObjectAt(0)).getValue();
-
- t = checkBigIntegerInIntRangeAndPositive(asn1int);
-
- ASN1Sequence seqOfPSh = (ASN1Sequence)seq.getObjectAt(1);
- ASN1Sequence seqOfPSw = (ASN1Sequence)seq.getObjectAt(2);
- ASN1Sequence seqOfPSK = (ASN1Sequence)seq.getObjectAt(3);
-
- if ((seqOfPSh.size() != t) ||
- (seqOfPSw.size() != t) ||
- (seqOfPSK.size() != t))
- {
- throw new IllegalArgumentException("invalid size of sequences");
- }
-
- h = new int[seqOfPSh.size()];
- w = new int[seqOfPSw.size()];
- k = new int[seqOfPSK.size()];
-
- for (int i = 0; i < t; i++)
- {
- h[i] = checkBigIntegerInIntRangeAndPositive((((ASN1Integer)seqOfPSh.getObjectAt(i))).getValue());
- w[i] = checkBigIntegerInIntRangeAndPositive((((ASN1Integer)seqOfPSw.getObjectAt(i))).getValue());
- k[i] = checkBigIntegerInIntRangeAndPositive((((ASN1Integer)seqOfPSK.getObjectAt(i))).getValue());
- }
- }
-
- public ParSet(int t, int[] h, int[] w, int[] k)
- {
- this.t = t;
- this.h = h;
- this.w = w;
- this.k = k;
- }
-
- public static ParSet getInstance(Object o)
- {
- if (o instanceof ParSet)
- {
- return (ParSet)o;
- }
- else if (o != null)
- {
- return new ParSet(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public int getT()
- {
- return t;
- }
-
- public int[] getH()
- {
- return Arrays.clone(h);
- }
-
- public int[] getW()
- {
- return Arrays.clone(w);
- }
-
- public int[] getK()
- {
- return Arrays.clone(k);
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector seqOfPSh = new ASN1EncodableVector();
- ASN1EncodableVector seqOfPSw = new ASN1EncodableVector();
- ASN1EncodableVector seqOfPSK = new ASN1EncodableVector();
-
- for (int i = 0; i < h.length; i++)
- {
- seqOfPSh.add(new ASN1Integer(h[i]));
- seqOfPSw.add(new ASN1Integer(w[i]));
- seqOfPSK.add(new ASN1Integer(k[i]));
- }
-
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(new ASN1Integer(t));
- v.add(new DERSequence(seqOfPSh));
- v.add(new DERSequence(seqOfPSw));
- v.add(new DERSequence(seqOfPSK));
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/asn1/RainbowPrivateKey.java b/core/src/main/java/org/bouncycastle/pqc/asn1/RainbowPrivateKey.java
deleted file mode 100644
index 7c21691d..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/asn1/RainbowPrivateKey.java
+++ /dev/null
@@ -1,349 +0,0 @@
-package org.bouncycastle.pqc.asn1;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.pqc.crypto.rainbow.Layer;
-import org.bouncycastle.pqc.crypto.rainbow.util.RainbowUtil;
-
-/**
- * Return the key data to encode in the PrivateKeyInfo structure.
- * <p>
- * The ASN.1 definition of the key structure is
- * <pre>
- * RainbowPrivateKey ::= SEQUENCE {
- * CHOICE
- * {
- * oid OBJECT IDENTIFIER -- OID identifying the algorithm
- * version INTEGER -- 0
- * }
- * A1inv SEQUENCE OF OCTET STRING -- inversed matrix of L1
- * b1 OCTET STRING -- translation vector of L1
- * A2inv SEQUENCE OF OCTET STRING -- inversed matrix of L2
- * b2 OCTET STRING -- translation vector of L2
- * vi OCTET STRING -- num of elmts in each Set S
- * layers SEQUENCE OF Layer -- layers of F
- * }
- *
- * Layer ::= SEQUENCE OF Poly
- *
- * Poly ::= SEQUENCE {
- * alpha SEQUENCE OF OCTET STRING
- * beta SEQUENCE OF OCTET STRING
- * gamma OCTET STRING
- * eta INTEGER
- * }
- * </pre>
- */
-public class RainbowPrivateKey
- extends ASN1Object
-{
- private ASN1Integer version;
- private ASN1ObjectIdentifier oid;
-
- private byte[][] invA1;
- private byte[] b1;
- private byte[][] invA2;
- private byte[] b2;
- private byte[] vi;
- private Layer[] layers;
-
- private RainbowPrivateKey(ASN1Sequence seq)
- {
- // <oidString> or version
- if (seq.getObjectAt(0) instanceof ASN1Integer)
- {
- version = ASN1Integer.getInstance(seq.getObjectAt(0));
- }
- else
- {
- oid = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
- }
-
- // <A1inv>
- ASN1Sequence asnA1 = (ASN1Sequence)seq.getObjectAt(1);
- invA1 = new byte[asnA1.size()][];
- for (int i = 0; i < asnA1.size(); i++)
- {
- invA1[i] = ((ASN1OctetString)asnA1.getObjectAt(i)).getOctets();
- }
-
- // <b1>
- ASN1Sequence asnb1 = (ASN1Sequence)seq.getObjectAt(2);
- b1 = ((ASN1OctetString)asnb1.getObjectAt(0)).getOctets();
-
- // <A2inv>
- ASN1Sequence asnA2 = (ASN1Sequence)seq.getObjectAt(3);
- invA2 = new byte[asnA2.size()][];
- for (int j = 0; j < asnA2.size(); j++)
- {
- invA2[j] = ((ASN1OctetString)asnA2.getObjectAt(j)).getOctets();
- }
-
- // <b2>
- ASN1Sequence asnb2 = (ASN1Sequence)seq.getObjectAt(4);
- b2 = ((ASN1OctetString)asnb2.getObjectAt(0)).getOctets();
-
- // <vi>
- ASN1Sequence asnvi = (ASN1Sequence)seq.getObjectAt(5);
- vi = ((ASN1OctetString)asnvi.getObjectAt(0)).getOctets();
-
- // <layers>
- ASN1Sequence asnLayers = (ASN1Sequence)seq.getObjectAt(6);
-
- byte[][][][] alphas = new byte[asnLayers.size()][][][];
- byte[][][][] betas = new byte[asnLayers.size()][][][];
- byte[][][] gammas = new byte[asnLayers.size()][][];
- byte[][] etas = new byte[asnLayers.size()][];
- // a layer:
- for (int l = 0; l < asnLayers.size(); l++)
- {
- ASN1Sequence asnLayer = (ASN1Sequence)asnLayers.getObjectAt(l);
-
- // alphas (num of alpha-2d-array = oi)
- ASN1Sequence alphas3d = (ASN1Sequence)asnLayer.getObjectAt(0);
- alphas[l] = new byte[alphas3d.size()][][];
- for (int m = 0; m < alphas3d.size(); m++)
- {
- ASN1Sequence alphas2d = (ASN1Sequence)alphas3d.getObjectAt(m);
- alphas[l][m] = new byte[alphas2d.size()][];
- for (int n = 0; n < alphas2d.size(); n++)
- {
- alphas[l][m][n] = ((ASN1OctetString)alphas2d.getObjectAt(n)).getOctets();
- }
- }
-
- // betas ....
- ASN1Sequence betas3d = (ASN1Sequence)asnLayer.getObjectAt(1);
- betas[l] = new byte[betas3d.size()][][];
- for (int mb = 0; mb < betas3d.size(); mb++)
- {
- ASN1Sequence betas2d = (ASN1Sequence)betas3d.getObjectAt(mb);
- betas[l][mb] = new byte[betas2d.size()][];
- for (int nb = 0; nb < betas2d.size(); nb++)
- {
- betas[l][mb][nb] = ((ASN1OctetString)betas2d.getObjectAt(nb)).getOctets();
- }
- }
-
- // gammas ...
- ASN1Sequence gammas2d = (ASN1Sequence)asnLayer.getObjectAt(2);
- gammas[l] = new byte[gammas2d.size()][];
- for (int mg = 0; mg < gammas2d.size(); mg++)
- {
- gammas[l][mg] = ((ASN1OctetString)gammas2d.getObjectAt(mg)).getOctets();
- }
-
- // eta ...
- etas[l] = ((ASN1OctetString)asnLayer.getObjectAt(3)).getOctets();
- }
-
- int numOfLayers = vi.length - 1;
- this.layers = new Layer[numOfLayers];
- for (int i = 0; i < numOfLayers; i++)
- {
- Layer l = new Layer(vi[i], vi[i + 1], RainbowUtil.convertArray(alphas[i]),
- RainbowUtil.convertArray(betas[i]), RainbowUtil.convertArray(gammas[i]), RainbowUtil.convertArray(etas[i]));
- this.layers[i] = l;
-
- }
- }
-
- public RainbowPrivateKey(short[][] invA1, short[] b1, short[][] invA2,
- short[] b2, int[] vi, Layer[] layers)
- {
- this.version = new ASN1Integer(1);
- this.invA1 = RainbowUtil.convertArray(invA1);
- this.b1 = RainbowUtil.convertArray(b1);
- this.invA2 = RainbowUtil.convertArray(invA2);
- this.b2 = RainbowUtil.convertArray(b2);
- this.vi = RainbowUtil.convertIntArray(vi);
- this.layers = layers;
- }
-
- public static RainbowPrivateKey getInstance(Object o)
- {
- if (o instanceof RainbowPrivateKey)
- {
- return (RainbowPrivateKey)o;
- }
- else if (o != null)
- {
- return new RainbowPrivateKey(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- /**
- * Getter for the inverse matrix of A1.
- *
- * @return the A1inv inverse
- */
- public short[][] getInvA1()
- {
- return RainbowUtil.convertArray(invA1);
- }
-
- /**
- * Getter for the translation part of the private quadratic map L1.
- *
- * @return b1 the translation part of L1
- */
- public short[] getB1()
- {
- return RainbowUtil.convertArray(b1);
- }
-
- /**
- * Getter for the translation part of the private quadratic map L2.
- *
- * @return b2 the translation part of L2
- */
- public short[] getB2()
- {
- return RainbowUtil.convertArray(b2);
- }
-
- /**
- * Getter for the inverse matrix of A2
- *
- * @return the A2inv
- */
- public short[][] getInvA2()
- {
- return RainbowUtil.convertArray(invA2);
- }
-
- /**
- * Returns the layers contained in the private key
- *
- * @return layers
- */
- public Layer[] getLayers()
- {
- return this.layers;
- }
-
- /**
- * Returns the array of vi-s
- *
- * @return the vi
- */
- public int[] getVi()
- {
- return RainbowUtil.convertArraytoInt(vi);
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- // encode <oidString> or version
- if (version != null)
- {
- v.add(version);
- }
- else
- {
- v.add(oid);
- }
-
- // encode <A1inv>
- ASN1EncodableVector asnA1 = new ASN1EncodableVector();
- for (int i = 0; i < invA1.length; i++)
- {
- asnA1.add(new DEROctetString(invA1[i]));
- }
- v.add(new DERSequence(asnA1));
-
- // encode <b1>
- ASN1EncodableVector asnb1 = new ASN1EncodableVector();
- asnb1.add(new DEROctetString(b1));
- v.add(new DERSequence(asnb1));
-
- // encode <A2inv>
- ASN1EncodableVector asnA2 = new ASN1EncodableVector();
- for (int i = 0; i < invA2.length; i++)
- {
- asnA2.add(new DEROctetString(invA2[i]));
- }
- v.add(new DERSequence(asnA2));
-
- // encode <b2>
- ASN1EncodableVector asnb2 = new ASN1EncodableVector();
- asnb2.add(new DEROctetString(b2));
- v.add(new DERSequence(asnb2));
-
- // encode <vi>
- ASN1EncodableVector asnvi = new ASN1EncodableVector();
- asnvi.add(new DEROctetString(vi));
- v.add(new DERSequence(asnvi));
-
- // encode <layers>
- ASN1EncodableVector asnLayers = new ASN1EncodableVector();
- // a layer:
- for (int l = 0; l < layers.length; l++)
- {
- ASN1EncodableVector aLayer = new ASN1EncodableVector();
-
- // alphas (num of alpha-2d-array = oi)
- byte[][][] alphas = RainbowUtil.convertArray(layers[l].getCoeffAlpha());
- ASN1EncodableVector alphas3d = new ASN1EncodableVector();
- for (int i = 0; i < alphas.length; i++)
- {
- ASN1EncodableVector alphas2d = new ASN1EncodableVector();
- for (int j = 0; j < alphas[i].length; j++)
- {
- alphas2d.add(new DEROctetString(alphas[i][j]));
- }
- alphas3d.add(new DERSequence(alphas2d));
- }
- aLayer.add(new DERSequence(alphas3d));
-
- // betas ....
- byte[][][] betas = RainbowUtil.convertArray(layers[l].getCoeffBeta());
- ASN1EncodableVector betas3d = new ASN1EncodableVector();
- for (int i = 0; i < betas.length; i++)
- {
- ASN1EncodableVector betas2d = new ASN1EncodableVector();
- for (int j = 0; j < betas[i].length; j++)
- {
- betas2d.add(new DEROctetString(betas[i][j]));
- }
- betas3d.add(new DERSequence(betas2d));
- }
- aLayer.add(new DERSequence(betas3d));
-
- // gammas ...
- byte[][] gammas = RainbowUtil.convertArray(layers[l].getCoeffGamma());
- ASN1EncodableVector asnG = new ASN1EncodableVector();
- for (int i = 0; i < gammas.length; i++)
- {
- asnG.add(new DEROctetString(gammas[i]));
- }
- aLayer.add(new DERSequence(asnG));
-
- // eta
- aLayer.add(new DEROctetString(RainbowUtil.convertArray(layers[l].getCoeffEta())));
-
- // now, layer built up. add it!
- asnLayers.add(new DERSequence(aLayer));
- }
-
- v.add(new DERSequence(asnLayers));
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/asn1/RainbowPublicKey.java b/core/src/main/java/org/bouncycastle/pqc/asn1/RainbowPublicKey.java
deleted file mode 100644
index febe5387..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/asn1/RainbowPublicKey.java
+++ /dev/null
@@ -1,174 +0,0 @@
-package org.bouncycastle.pqc.asn1;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.pqc.crypto.rainbow.util.RainbowUtil;
-
-/**
- * This class implements an ASN.1 encoded Rainbow public key. The ASN.1 definition
- * of this structure is:
- * <pre>
- * RainbowPublicKey ::= SEQUENCE {
- * CHOICE
- * {
- * oid OBJECT IDENTIFIER -- OID identifying the algorithm
- * version INTEGER -- 0
- * }
- * docLength Integer -- length of the code
- * coeffquadratic SEQUENCE OF OCTET STRING -- quadratic (mixed) coefficients
- * coeffsingular SEQUENCE OF OCTET STRING -- singular coefficients
- * coeffscalar SEQUENCE OF OCTET STRING -- scalar coefficients
- * }
- * </pre>
- */
-public class RainbowPublicKey
- extends ASN1Object
-{
- private ASN1Integer version;
- private ASN1ObjectIdentifier oid;
- private ASN1Integer docLength;
- private byte[][] coeffQuadratic;
- private byte[][] coeffSingular;
- private byte[] coeffScalar;
-
- private RainbowPublicKey(ASN1Sequence seq)
- {
- // <oidString> or version
- if (seq.getObjectAt(0) instanceof ASN1Integer)
- {
- version = ASN1Integer.getInstance(seq.getObjectAt(0));
- }
- else
- {
- oid = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
- }
-
- docLength = ASN1Integer.getInstance(seq.getObjectAt(1));
-
- ASN1Sequence asnCoeffQuad = ASN1Sequence.getInstance(seq.getObjectAt(2));
- coeffQuadratic = new byte[asnCoeffQuad.size()][];
- for (int quadSize = 0; quadSize < asnCoeffQuad.size(); quadSize++)
- {
- coeffQuadratic[quadSize] = ASN1OctetString.getInstance(asnCoeffQuad.getObjectAt(quadSize)).getOctets();
- }
-
- ASN1Sequence asnCoeffSing = (ASN1Sequence)seq.getObjectAt(3);
- coeffSingular = new byte[asnCoeffSing.size()][];
- for (int singSize = 0; singSize < asnCoeffSing.size(); singSize++)
- {
- coeffSingular[singSize] = ASN1OctetString.getInstance(asnCoeffSing.getObjectAt(singSize)).getOctets();
- }
-
- ASN1Sequence asnCoeffScalar = (ASN1Sequence)seq.getObjectAt(4);
- coeffScalar = ASN1OctetString.getInstance(asnCoeffScalar.getObjectAt(0)).getOctets();
- }
-
- public RainbowPublicKey(int docLength, short[][] coeffQuadratic, short[][] coeffSingular, short[] coeffScalar)
- {
- this.version = new ASN1Integer(0);
- this.docLength = new ASN1Integer(docLength);
- this.coeffQuadratic = RainbowUtil.convertArray(coeffQuadratic);
- this.coeffSingular = RainbowUtil.convertArray(coeffSingular);
- this.coeffScalar = RainbowUtil.convertArray(coeffScalar);
- }
-
- public static RainbowPublicKey getInstance(Object o)
- {
- if (o instanceof RainbowPublicKey)
- {
- return (RainbowPublicKey)o;
- }
- else if (o != null)
- {
- return new RainbowPublicKey(ASN1Sequence.getInstance(o));
- }
-
- return null;
- }
-
- public ASN1Integer getVersion()
- {
- return version;
- }
-
- /**
- * @return the docLength
- */
- public int getDocLength()
- {
- return this.docLength.getValue().intValue();
- }
-
- /**
- * @return the coeffquadratic
- */
- public short[][] getCoeffQuadratic()
- {
- return RainbowUtil.convertArray(coeffQuadratic);
- }
-
- /**
- * @return the coeffsingular
- */
- public short[][] getCoeffSingular()
- {
- return RainbowUtil.convertArray(coeffSingular);
- }
-
- /**
- * @return the coeffscalar
- */
- public short[] getCoeffScalar()
- {
- return RainbowUtil.convertArray(coeffScalar);
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- // encode <oidString> or version
- if (version != null)
- {
- v.add(version);
- }
- else
- {
- v.add(oid);
- }
-
- // encode <docLength>
- v.add(docLength);
-
- // encode <coeffQuadratic>
- ASN1EncodableVector asnCoeffQuad = new ASN1EncodableVector();
- for (int i = 0; i < coeffQuadratic.length; i++)
- {
- asnCoeffQuad.add(new DEROctetString(coeffQuadratic[i]));
- }
- v.add(new DERSequence(asnCoeffQuad));
-
- // encode <coeffSingular>
- ASN1EncodableVector asnCoeffSing = new ASN1EncodableVector();
- for (int i = 0; i < coeffSingular.length; i++)
- {
- asnCoeffSing.add(new DEROctetString(coeffSingular[i]));
- }
- v.add(new DERSequence(asnCoeffSing));
-
- // encode <coeffScalar>
- ASN1EncodableVector asnCoeffScalar = new ASN1EncodableVector();
- asnCoeffScalar.add(new DEROctetString(coeffScalar));
- v.add(new DERSequence(asnCoeffScalar));
-
-
- return new DERSequence(v);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/DigestingMessageSigner.java b/core/src/main/java/org/bouncycastle/pqc/crypto/DigestingMessageSigner.java
deleted file mode 100644
index 6b5b2515..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/DigestingMessageSigner.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package org.bouncycastle.pqc.crypto;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.Signer;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-
-
-/**
- * Implements the sign and verify functions for a Signature Scheme which can use a hash function.
- */
-public class DigestingMessageSigner
- implements Signer
-{
- private final Digest messDigest;
- private final MessageSigner messSigner;
- private boolean forSigning;
-
- public DigestingMessageSigner(MessageSigner messSigner, Digest messDigest)
- {
- this.messSigner = messSigner;
- this.messDigest = messDigest;
- }
-
- public void init(boolean forSigning,
- CipherParameters param)
- {
-
- this.forSigning = forSigning;
- AsymmetricKeyParameter k;
-
- if (param instanceof ParametersWithRandom)
- {
- k = (AsymmetricKeyParameter)((ParametersWithRandom)param).getParameters();
- }
- else
- {
- k = (AsymmetricKeyParameter)param;
- }
-
- if (forSigning && !k.isPrivate())
- {
- throw new IllegalArgumentException("Signing Requires Private Key.");
- }
-
- if (!forSigning && k.isPrivate())
- {
- throw new IllegalArgumentException("Verification Requires Public Key.");
- }
-
- reset();
-
- messSigner.init(forSigning, param);
- }
-
-
- /**
- * This function signs the message that has been updated, making use of the
- * private key.
- *
- * @return the signature of the message.
- */
- public byte[] generateSignature()
- {
- if (!forSigning)
- {
- throw new IllegalStateException("RainbowDigestSigner not initialised for signature generation.");
- }
-
- byte[] hash = new byte[messDigest.getDigestSize()];
- messDigest.doFinal(hash, 0);
-
- return messSigner.generateSignature(hash);
- }
-
- /**
- * This function verifies the signature of the message that has been
- * updated, with the aid of the public key.
- *
- * @param signature the signature of the message is given as a byte array.
- * @return true if the signature has been verified, false otherwise.
- */
- public boolean verify(byte[] signature)
- {
- if (forSigning)
- {
- throw new IllegalStateException("RainbowDigestSigner not initialised for verification");
- }
-
- byte[] hash = new byte[messDigest.getDigestSize()];
- messDigest.doFinal(hash, 0);
-
- return messSigner.verifySignature(hash, signature);
-
- }
-
- public void update(byte b)
- {
- messDigest.update(b);
- }
-
- public void update(byte[] in, int off, int len)
- {
- messDigest.update(in, off, len);
- }
-
- public void reset()
- {
- messDigest.reset();
- }
-
- public boolean verifySignature(byte[] signature)
- {
- return this.verify(signature);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/MessageEncryptor.java b/core/src/main/java/org/bouncycastle/pqc/crypto/MessageEncryptor.java
deleted file mode 100644
index 8d67c5cd..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/MessageEncryptor.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.bouncycastle.pqc.crypto;
-
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public interface MessageEncryptor
-{
-
- /**
- *
- * @param forEncrypting true if we are encrypting a signature, false
- * otherwise.
- * @param param key parameters for encryption or decryption.
- */
- public void init(boolean forEncrypting, CipherParameters param);
-
- /**
- *
- * @param message the message to be signed.
- * @throws Exception
- */
- public byte[] messageEncrypt(byte[] message) throws Exception;
-
- /**
- *
- * @param cipher the cipher text of the message
- * @throws Exception
- */
- public byte[] messageDecrypt(byte[] cipher) throws Exception;
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/MessageSigner.java b/core/src/main/java/org/bouncycastle/pqc/crypto/MessageSigner.java
deleted file mode 100644
index 50243f73..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/MessageSigner.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.bouncycastle.pqc.crypto;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public interface MessageSigner
-{
- /**
- * initialise the signer for signature generation or signature
- * verification.
- *
- * @param forSigning true if we are generating a signature, false
- * otherwise.
- * @param param key parameters for signature generation.
- */
- public void init(boolean forSigning, CipherParameters param);
-
- /**
- * sign the passed in message (usually the output of a hash function).
- *
- * @param message the message to be signed.
- * @return the signature of the message
- */
- public byte[] generateSignature(byte[] message);
-
- /**
- * verify the message message against the signature values r and s.
- *
- * @param message the message that was supposed to have been signed.
- * @param signature the signature of the message
- */
- public boolean verifySignature(byte[] message, byte[] signature);
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSDigestProvider.java b/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSDigestProvider.java
deleted file mode 100644
index 4af1a8b5..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSDigestProvider.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.bouncycastle.pqc.crypto.gmss;
-
-import org.bouncycastle.crypto.Digest;
-
-public interface GMSSDigestProvider
-{
- Digest get();
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSKeyGenerationParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSKeyGenerationParameters.java
deleted file mode 100644
index eace4d03..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSKeyGenerationParameters.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.bouncycastle.pqc.crypto.gmss;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.KeyGenerationParameters;
-
-public class GMSSKeyGenerationParameters
- extends KeyGenerationParameters
-{
-
- private GMSSParameters params;
-
- public GMSSKeyGenerationParameters(
- SecureRandom random,
- GMSSParameters params)
- {
- // XXX key size?
- super(random, 1);
- this.params = params;
- }
-
- public GMSSParameters getParameters()
- {
- return params;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSKeyPairGenerator.java b/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSKeyPairGenerator.java
deleted file mode 100644
index 013441ec..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSKeyPairGenerator.java
+++ /dev/null
@@ -1,476 +0,0 @@
-package org.bouncycastle.pqc.crypto.gmss;
-
-import java.security.SecureRandom;
-import java.util.Vector;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.pqc.crypto.gmss.util.GMSSRandom;
-import org.bouncycastle.pqc.crypto.gmss.util.WinternitzOTSVerify;
-import org.bouncycastle.pqc.crypto.gmss.util.WinternitzOTSignature;
-
-
-/**
- * This class implements key pair generation of the generalized Merkle signature
- * scheme (GMSS).
- *
- * @see GMSSSigner
- */
-public class GMSSKeyPairGenerator
- implements AsymmetricCipherKeyPairGenerator
-{
- /**
- * The source of randomness for OTS private key generation
- */
- private GMSSRandom gmssRandom;
-
- /**
- * The hash function used for the construction of the authentication trees
- */
- private Digest messDigestTree;
-
- /**
- * An array of the seeds for the PRGN (for main tree, and all current
- * subtrees)
- */
- private byte[][] currentSeeds;
-
- /**
- * An array of seeds for the PRGN (for all subtrees after next)
- */
- private byte[][] nextNextSeeds;
-
- /**
- * An array of the RootSignatures
- */
- private byte[][] currentRootSigs;
-
- /**
- * Class of hash function to use
- */
- private GMSSDigestProvider digestProvider;
-
- /**
- * The length of the seed for the PRNG
- */
- private int mdLength;
-
- /**
- * the number of Layers
- */
- private int numLayer;
-
-
- /**
- * Flag indicating if the class already has been initialized
- */
- private boolean initialized = false;
-
- /**
- * Instance of GMSSParameterset
- */
- private GMSSParameters gmssPS;
-
- /**
- * An array of the heights of the authentication trees of each layer
- */
- private int[] heightOfTrees;
-
- /**
- * An array of the Winternitz parameter 'w' of each layer
- */
- private int[] otsIndex;
-
- /**
- * The parameter K needed for the authentication path computation
- */
- private int[] K;
-
- private GMSSKeyGenerationParameters gmssParams;
-
- /**
- * The GMSS OID.
- */
- public static final String OID = "1.3.6.1.4.1.8301.3.1.3.3";
-
- /**
- * The standard constructor tries to generate the GMSS algorithm identifier
- * with the corresponding OID.
- *
- * @param digestProvider provider for digest implementations.
- */
- public GMSSKeyPairGenerator(GMSSDigestProvider digestProvider)
- {
- this.digestProvider = digestProvider;
- messDigestTree = digestProvider.get();
-
- // set mdLength
- this.mdLength = messDigestTree.getDigestSize();
- // construct randomizer
- this.gmssRandom = new GMSSRandom(messDigestTree);
-
- }
-
- /**
- * Generates the GMSS key pair. The public key is an instance of
- * JDKGMSSPublicKey, the private key is an instance of JDKGMSSPrivateKey.
- *
- * @return Key pair containing a JDKGMSSPublicKey and a JDKGMSSPrivateKey
- */
- private AsymmetricCipherKeyPair genKeyPair()
- {
- if (!initialized)
- {
- initializeDefault();
- }
-
- // initialize authenticationPaths and treehash instances
- byte[][][] currentAuthPaths = new byte[numLayer][][];
- byte[][][] nextAuthPaths = new byte[numLayer - 1][][];
- Treehash[][] currentTreehash = new Treehash[numLayer][];
- Treehash[][] nextTreehash = new Treehash[numLayer - 1][];
-
- Vector[] currentStack = new Vector[numLayer];
- Vector[] nextStack = new Vector[numLayer - 1];
-
- Vector[][] currentRetain = new Vector[numLayer][];
- Vector[][] nextRetain = new Vector[numLayer - 1][];
-
- for (int i = 0; i < numLayer; i++)
- {
- currentAuthPaths[i] = new byte[heightOfTrees[i]][mdLength];
- currentTreehash[i] = new Treehash[heightOfTrees[i] - K[i]];
-
- if (i > 0)
- {
- nextAuthPaths[i - 1] = new byte[heightOfTrees[i]][mdLength];
- nextTreehash[i - 1] = new Treehash[heightOfTrees[i] - K[i]];
- }
-
- currentStack[i] = new Vector();
- if (i > 0)
- {
- nextStack[i - 1] = new Vector();
- }
- }
-
- // initialize roots
- byte[][] currentRoots = new byte[numLayer][mdLength];
- byte[][] nextRoots = new byte[numLayer - 1][mdLength];
- // initialize seeds
- byte[][] seeds = new byte[numLayer][mdLength];
- // initialize seeds[] by copying starting-seeds of first trees of each
- // layer
- for (int i = 0; i < numLayer; i++)
- {
- System.arraycopy(currentSeeds[i], 0, seeds[i], 0, mdLength);
- }
-
- // initialize rootSigs
- currentRootSigs = new byte[numLayer - 1][mdLength];
-
- // -------------------------
- // -------------------------
- // --- calculation of current authpaths and current rootsigs (AUTHPATHS,
- // SIG)------
- // from bottom up to the root
- for (int h = numLayer - 1; h >= 0; h--)
- {
- GMSSRootCalc tree = new GMSSRootCalc(this.heightOfTrees[h], this.K[h], digestProvider);
- try
- {
- // on lowest layer no lower root is available, so just call
- // the method with null as first parameter
- if (h == numLayer - 1)
- {
- tree = this.generateCurrentAuthpathAndRoot(null, currentStack[h], seeds[h], h);
- }
- else
- // otherwise call the method with the former computed root
- // value
- {
- tree = this.generateCurrentAuthpathAndRoot(currentRoots[h + 1], currentStack[h], seeds[h], h);
- }
-
- }
- catch (Exception e1)
- {
- e1.printStackTrace();
- }
-
- // set initial values needed for the private key construction
- for (int i = 0; i < heightOfTrees[h]; i++)
- {
- System.arraycopy(tree.getAuthPath()[i], 0, currentAuthPaths[h][i], 0, mdLength);
- }
- currentRetain[h] = tree.getRetain();
- currentTreehash[h] = tree.getTreehash();
- System.arraycopy(tree.getRoot(), 0, currentRoots[h], 0, mdLength);
- }
-
- // --- calculation of next authpaths and next roots (AUTHPATHS+, ROOTS+)
- // ------
- for (int h = numLayer - 2; h >= 0; h--)
- {
- GMSSRootCalc tree = this.generateNextAuthpathAndRoot(nextStack[h], seeds[h + 1], h + 1);
-
- // set initial values needed for the private key construction
- for (int i = 0; i < heightOfTrees[h + 1]; i++)
- {
- System.arraycopy(tree.getAuthPath()[i], 0, nextAuthPaths[h][i], 0, mdLength);
- }
- nextRetain[h] = tree.getRetain();
- nextTreehash[h] = tree.getTreehash();
- System.arraycopy(tree.getRoot(), 0, nextRoots[h], 0, mdLength);
-
- // create seed for the Merkle tree after next (nextNextSeeds)
- // SEEDs++
- System.arraycopy(seeds[h + 1], 0, this.nextNextSeeds[h], 0, mdLength);
- }
- // ------------
-
- // generate JDKGMSSPublicKey
- GMSSPublicKeyParameters publicKey = new GMSSPublicKeyParameters(currentRoots[0], gmssPS);
-
- // generate the JDKGMSSPrivateKey
- GMSSPrivateKeyParameters privateKey = new GMSSPrivateKeyParameters(currentSeeds, nextNextSeeds, currentAuthPaths,
- nextAuthPaths, currentTreehash, nextTreehash, currentStack, nextStack, currentRetain, nextRetain, nextRoots, currentRootSigs, gmssPS, digestProvider);
-
- // return the KeyPair
- return (new AsymmetricCipherKeyPair(publicKey, privateKey));
- }
-
- /**
- * calculates the authpath for tree in layer h which starts with seed[h]
- * additionally computes the rootSignature of underlaying root
- *
- * @param currentStack stack used for the treehash instance created by this method
- * @param lowerRoot stores the root of the lower tree
- * @param seed starting seeds
- * @param h actual layer
- */
- private GMSSRootCalc generateCurrentAuthpathAndRoot(byte[] lowerRoot, Vector currentStack, byte[] seed, int h)
- {
- byte[] help = new byte[mdLength];
-
- byte[] OTSseed = new byte[mdLength];
- OTSseed = gmssRandom.nextSeed(seed);
-
- WinternitzOTSignature ots;
-
- // data structure that constructs the whole tree and stores
- // the initial values for treehash, Auth and retain
- GMSSRootCalc treeToConstruct = new GMSSRootCalc(this.heightOfTrees[h], this.K[h], digestProvider);
-
- treeToConstruct.initialize(currentStack);
-
- // generate the first leaf
- if (h == numLayer - 1)
- {
- ots = new WinternitzOTSignature(OTSseed, digestProvider.get(), otsIndex[h]);
- help = ots.getPublicKey();
- }
- else
- {
- // for all layers except the lowest, generate the signature of the
- // underlying root
- // and reuse this signature to compute the first leaf of acual layer
- // more efficiently (by verifiing the signature)
- ots = new WinternitzOTSignature(OTSseed, digestProvider.get(), otsIndex[h]);
- currentRootSigs[h] = ots.getSignature(lowerRoot);
- WinternitzOTSVerify otsver = new WinternitzOTSVerify(digestProvider.get(), otsIndex[h]);
- help = otsver.Verify(lowerRoot, currentRootSigs[h]);
- }
- // update the tree with the first leaf
- treeToConstruct.update(help);
-
- int seedForTreehashIndex = 3;
- int count = 0;
-
- // update the tree 2^(H) - 1 times, from the second to the last leaf
- for (int i = 1; i < (1 << this.heightOfTrees[h]); i++)
- {
- // initialize the seeds for the leaf generation with index 3 * 2^h
- if (i == seedForTreehashIndex && count < this.heightOfTrees[h] - this.K[h])
- {
- treeToConstruct.initializeTreehashSeed(seed, count);
- seedForTreehashIndex *= 2;
- count++;
- }
-
- OTSseed = gmssRandom.nextSeed(seed);
- ots = new WinternitzOTSignature(OTSseed, digestProvider.get(), otsIndex[h]);
- treeToConstruct.update(ots.getPublicKey());
- }
-
- if (treeToConstruct.wasFinished())
- {
- return treeToConstruct;
- }
- System.err.println("Baum noch nicht fertig konstruiert!!!");
- return null;
- }
-
- /**
- * calculates the authpath and root for tree in layer h which starts with
- * seed[h]
- *
- * @param nextStack stack used for the treehash instance created by this method
- * @param seed starting seeds
- * @param h actual layer
- */
- private GMSSRootCalc generateNextAuthpathAndRoot(Vector nextStack, byte[] seed, int h)
- {
- byte[] OTSseed = new byte[numLayer];
- WinternitzOTSignature ots;
-
- // data structure that constructs the whole tree and stores
- // the initial values for treehash, Auth and retain
- GMSSRootCalc treeToConstruct = new GMSSRootCalc(this.heightOfTrees[h], this.K[h], this.digestProvider);
- treeToConstruct.initialize(nextStack);
-
- int seedForTreehashIndex = 3;
- int count = 0;
-
- // update the tree 2^(H) times, from the first to the last leaf
- for (int i = 0; i < (1 << this.heightOfTrees[h]); i++)
- {
- // initialize the seeds for the leaf generation with index 3 * 2^h
- if (i == seedForTreehashIndex && count < this.heightOfTrees[h] - this.K[h])
- {
- treeToConstruct.initializeTreehashSeed(seed, count);
- seedForTreehashIndex *= 2;
- count++;
- }
-
- OTSseed = gmssRandom.nextSeed(seed);
- ots = new WinternitzOTSignature(OTSseed, digestProvider.get(), otsIndex[h]);
- treeToConstruct.update(ots.getPublicKey());
- }
-
- if (treeToConstruct.wasFinished())
- {
- return treeToConstruct;
- }
- System.err.println("N�chster Baum noch nicht fertig konstruiert!!!");
- return null;
- }
-
- /**
- * This method initializes the GMSS KeyPairGenerator using an integer value
- * <code>keySize</code> as input. It provides a simple use of the GMSS for
- * testing demands.
- * <p>
- * A given <code>keysize</code> of less than 10 creates an amount 2^10
- * signatures. A keySize between 10 and 20 creates 2^20 signatures. Given an
- * integer greater than 20 the key pair generator creates 2^40 signatures.
- *
- * @param keySize Assigns the parameters used for the GMSS signatures. There are
- * 3 choices:<br>
- * 1. keysize &lt;= 10: creates 2^10 signatures using the
- * parameterset<br>
- * P = (2, (5, 5), (3, 3), (3, 3))<br>
- * 2. keysize &gt; 10 and &lt;= 20: creates 2^20 signatures using the
- * parameterset<br>
- * P = (2, (10, 10), (5, 4), (2, 2))<br>
- * 3. keysize &gt; 20: creates 2^40 signatures using the
- * parameterset<br>
- * P = (2, (10, 10, 10, 10), (9, 9, 9, 3), (2, 2, 2, 2))
- * @param secureRandom not used by GMSS, the SHA1PRNG of the SUN Provider is always
- * used
- */
- public void initialize(int keySize, SecureRandom secureRandom)
- {
-
- KeyGenerationParameters kgp;
- if (keySize <= 10)
- { // create 2^10 keys
- int[] defh = {10};
- int[] defw = {3};
- int[] defk = {2};
- // XXX sec random neede?
- kgp = new GMSSKeyGenerationParameters(secureRandom, new GMSSParameters(defh.length, defh, defw, defk));
- }
- else if (keySize <= 20)
- { // create 2^20 keys
- int[] defh = {10, 10};
- int[] defw = {5, 4};
- int[] defk = {2, 2};
- kgp = new GMSSKeyGenerationParameters(secureRandom, new GMSSParameters(defh.length, defh, defw, defk));
- }
- else
- { // create 2^40 keys, keygen lasts around 80 seconds
- int[] defh = {10, 10, 10, 10};
- int[] defw = {9, 9, 9, 3};
- int[] defk = {2, 2, 2, 2};
- kgp = new GMSSKeyGenerationParameters(secureRandom, new GMSSParameters(defh.length, defh, defw, defk));
- }
-
- // call the initializer with the chosen parameters
- this.initialize(kgp);
-
- }
-
-
- /**
- * Initalizes the key pair generator using a parameter set as input
- */
- public void initialize(KeyGenerationParameters param)
- {
-
- this.gmssParams = (GMSSKeyGenerationParameters)param;
-
- // generate GMSSParameterset
- this.gmssPS = new GMSSParameters(gmssParams.getParameters().getNumOfLayers(), gmssParams.getParameters().getHeightOfTrees(),
- gmssParams.getParameters().getWinternitzParameter(), gmssParams.getParameters().getK());
-
- this.numLayer = gmssPS.getNumOfLayers();
- this.heightOfTrees = gmssPS.getHeightOfTrees();
- this.otsIndex = gmssPS.getWinternitzParameter();
- this.K = gmssPS.getK();
-
- // seeds
- this.currentSeeds = new byte[numLayer][mdLength];
- this.nextNextSeeds = new byte[numLayer - 1][mdLength];
-
- // construct SecureRandom for initial seed generation
- SecureRandom secRan = new SecureRandom();
-
- // generation of initial seeds
- for (int i = 0; i < numLayer; i++)
- {
- secRan.nextBytes(currentSeeds[i]);
- gmssRandom.nextSeed(currentSeeds[i]);
- }
-
- this.initialized = true;
- }
-
- /**
- * This method is called by generateKeyPair() in case that no other
- * initialization method has been called by the user
- */
- private void initializeDefault()
- {
- int[] defh = {10, 10, 10, 10};
- int[] defw = {3, 3, 3, 3};
- int[] defk = {2, 2, 2, 2};
-
- KeyGenerationParameters kgp = new GMSSKeyGenerationParameters(new SecureRandom(), new GMSSParameters(defh.length, defh, defw, defk));
- this.initialize(kgp);
-
- }
-
- public void init(KeyGenerationParameters param)
- {
- this.initialize(param);
-
- }
-
- public AsymmetricCipherKeyPair generateKeyPair()
- {
- return genKeyPair();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSKeyParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSKeyParameters.java
deleted file mode 100644
index 53f6e432..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSKeyParameters.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.bouncycastle.pqc.crypto.gmss;
-
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-
-public class GMSSKeyParameters
- extends AsymmetricKeyParameter
-{
- private GMSSParameters params;
-
- public GMSSKeyParameters(
- boolean isPrivate,
- GMSSParameters params)
- {
- super(isPrivate);
- this.params = params;
- }
-
- public GMSSParameters getParameters()
- {
- return params;
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSLeaf.java b/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSLeaf.java
deleted file mode 100644
index 6823ce3f..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSLeaf.java
+++ /dev/null
@@ -1,376 +0,0 @@
-package org.bouncycastle.pqc.crypto.gmss;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.pqc.crypto.gmss.util.GMSSRandom;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-
-
-/**
- * This class implements the distributed computation of the public key of the
- * Winternitz one-time signature scheme (OTSS). The class is used by the GMSS
- * classes for calculation of upcoming leafs.
- */
-public class GMSSLeaf
-{
-
- /**
- * The hash function used by the OTS and the PRNG
- */
- private Digest messDigestOTS;
-
- /**
- * The length of the message digest and private key
- */
- private int mdsize, keysize;
-
- /**
- * The source of randomness for OTS private key generation
- */
- private GMSSRandom gmssRandom;
-
- /**
- * Byte array for distributed computation of the upcoming leaf
- */
- private byte[] leaf;
-
- /**
- * Byte array for storing the concatenated hashes of private key parts
- */
- private byte[] concHashs;
-
- /**
- * indices for distributed computation
- */
- private int i, j;
-
- /**
- * storing 2^w
- */
- private int two_power_w;
-
- /**
- * Winternitz parameter w
- */
- private int w;
-
- /**
- * the amount of distributed computation steps when updateLeaf is called
- */
- private int steps;
-
- /**
- * the internal seed
- */
- private byte[] seed;
-
- /**
- * the OTS privateKey parts
- */
- byte[] privateKeyOTS;
-
- /**
- * This constructor regenerates a prior GMSSLeaf object
- *
- * @param digest an array of strings, containing the name of the used hash
- * function and PRNG and the name of the corresponding
- * provider
- * @param otsIndex status bytes
- * @param numLeafs status ints
- */
- public GMSSLeaf(Digest digest, byte[][] otsIndex, int[] numLeafs)
- {
- this.i = numLeafs[0];
- this.j = numLeafs[1];
- this.steps = numLeafs[2];
- this.w = numLeafs[3];
-
- messDigestOTS = digest;
-
- gmssRandom = new GMSSRandom(messDigestOTS);
-
- // calulate keysize for private key and the help array
- mdsize = messDigestOTS.getDigestSize();
- int mdsizeBit = mdsize << 3;
- int messagesize = (int)Math.ceil((double)(mdsizeBit) / (double)w);
- int checksumsize = getLog((messagesize << w) + 1);
- this.keysize = messagesize
- + (int)Math.ceil((double)checksumsize / (double)w);
- this.two_power_w = 1 << w;
-
- // calculate steps
- // ((2^w)-1)*keysize + keysize + 1 / (2^h -1)
-
- // initialize arrays
- this.privateKeyOTS = otsIndex[0];
- this.seed = otsIndex[1];
- this.concHashs = otsIndex[2];
- this.leaf = otsIndex[3];
- }
-
- /**
- * The constructor precomputes some needed variables for distributed leaf
- * calculation
- *
- * @param digest an array of strings, containing the digest of the used hash
- * function and PRNG and the digest of the corresponding
- * provider
- * @param w the winterniz parameter of that tree the leaf is computed
- * for
- * @param numLeafs the number of leafs of the tree from where the distributed
- * computation is called
- */
- GMSSLeaf(Digest digest, int w, int numLeafs)
- {
- this.w = w;
-
- messDigestOTS = digest;
-
- gmssRandom = new GMSSRandom(messDigestOTS);
-
- // calulate keysize for private key and the help array
- mdsize = messDigestOTS.getDigestSize();
- int mdsizeBit = mdsize << 3;
- int messagesize = (int)Math.ceil((double)(mdsizeBit) / (double)w);
- int checksumsize = getLog((messagesize << w) + 1);
- this.keysize = messagesize
- + (int)Math.ceil((double)checksumsize / (double)w);
- this.two_power_w = 1 << w;
-
- // calculate steps
- // ((2^w)-1)*keysize + keysize + 1 / (2^h -1)
- this.steps = (int)Math
- .ceil((double)(((1 << w) - 1) * keysize + 1 + keysize)
- / (double)(numLeafs));
-
- // initialize arrays
- this.seed = new byte[mdsize];
- this.leaf = new byte[mdsize];
- this.privateKeyOTS = new byte[mdsize];
- this.concHashs = new byte[mdsize * keysize];
- }
-
- public GMSSLeaf(Digest digest, int w, int numLeafs, byte[] seed0)
- {
- this.w = w;
-
- messDigestOTS = digest;
-
- gmssRandom = new GMSSRandom(messDigestOTS);
-
- // calulate keysize for private key and the help array
- mdsize = messDigestOTS.getDigestSize();
- int mdsizeBit = mdsize << 3;
- int messagesize = (int)Math.ceil((double)(mdsizeBit) / (double)w);
- int checksumsize = getLog((messagesize << w) + 1);
- this.keysize = messagesize
- + (int)Math.ceil((double)checksumsize / (double)w);
- this.two_power_w = 1 << w;
-
- // calculate steps
- // ((2^w)-1)*keysize + keysize + 1 / (2^h -1)
- this.steps = (int)Math
- .ceil((double)(((1 << w) - 1) * keysize + 1 + keysize)
- / (double)(numLeafs));
-
- // initialize arrays
- this.seed = new byte[mdsize];
- this.leaf = new byte[mdsize];
- this.privateKeyOTS = new byte[mdsize];
- this.concHashs = new byte[mdsize * keysize];
-
- initLeafCalc(seed0);
- }
-
- private GMSSLeaf(GMSSLeaf original)
- {
- this.messDigestOTS = original.messDigestOTS;
- this.mdsize = original.mdsize;
- this.keysize = original.keysize;
- this.gmssRandom = original.gmssRandom;
- this.leaf = Arrays.clone(original.leaf);
- this.concHashs = Arrays.clone(original.concHashs);
- this.i = original.i;
- this.j = original.j;
- this.two_power_w = original.two_power_w;
- this.w = original.w;
- this.steps = original.steps;
- this.seed = Arrays.clone(original.seed);
- this.privateKeyOTS = Arrays.clone(original.privateKeyOTS);
- }
-
- /**
- * initialize the distributed leaf calculation reset i,j and compute OTSseed
- * with seed0
- *
- * @param seed0 the starting seed
- */
- // TODO: this really looks like it should be either always called from a constructor or nextLeaf.
- void initLeafCalc(byte[] seed0)
- {
- this.i = 0;
- this.j = 0;
- byte[] dummy = new byte[mdsize];
- System.arraycopy(seed0, 0, dummy, 0, seed.length);
- this.seed = gmssRandom.nextSeed(dummy);
- }
-
- GMSSLeaf nextLeaf()
- {
- GMSSLeaf nextLeaf = new GMSSLeaf(this);
-
- nextLeaf.updateLeafCalc();
-
- return nextLeaf;
- }
-
- /**
- * Processes <code>steps</code> steps of distributed leaf calculation
- *
- * @return true if leaf is completed, else false
- */
- private void updateLeafCalc()
- {
- byte[] buf = new byte[messDigestOTS.getDigestSize()];
-
- // steps times do
- // TODO: this really needs to be looked at, the 10000 has been added as
- // prior to this the leaf value always ended up as zeros.
- for (int s = 0; s < steps + 10000; s++)
- {
- if (i == keysize && j == two_power_w - 1)
- { // [3] at last hash the
- // concatenation
- messDigestOTS.update(concHashs, 0, concHashs.length);
- leaf = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(leaf, 0);
- return;
- }
- else if (i == 0 || j == two_power_w - 1)
- { // [1] at the
- // beginning and
- // when [2] is
- // finished: get the
- // next private key
- // part
- i++;
- j = 0;
- // get next privKey part
- this.privateKeyOTS = gmssRandom.nextSeed(seed);
- }
- else
- { // [2] hash the privKey part
- messDigestOTS.update(privateKeyOTS, 0, privateKeyOTS.length);
- privateKeyOTS = buf;
- messDigestOTS.doFinal(privateKeyOTS, 0);
- j++;
- if (j == two_power_w - 1)
- { // after w hashes add to the
- // concatenated array
- System.arraycopy(privateKeyOTS, 0, concHashs, mdsize
- * (i - 1), mdsize);
- }
- }
- }
-
- throw new IllegalStateException("unable to updateLeaf in steps: " + steps + " " + i + " " + j);
- }
-
- /**
- * Returns the leaf value.
- *
- * @return the leaf value
- */
- public byte[] getLeaf()
- {
- return Arrays.clone(leaf);
- }
-
- /**
- * This method returns the least integer that is greater or equal to the
- * logarithm to the base 2 of an integer <code>intValue</code>.
- *
- * @param intValue an integer
- * @return The least integer greater or equal to the logarithm to the base 2
- * of <code>intValue</code>
- */
- private int getLog(int intValue)
- {
- int log = 1;
- int i = 2;
- while (i < intValue)
- {
- i <<= 1;
- log++;
- }
- return log;
- }
-
- /**
- * Returns the status byte array used by the GMSSPrivateKeyASN.1 class
- *
- * @return The status bytes
- */
- public byte[][] getStatByte()
- {
-
- byte[][] statByte = new byte[4][];
- statByte[0] = new byte[mdsize];
- statByte[1] = new byte[mdsize];
- statByte[2] = new byte[mdsize * keysize];
- statByte[3] = new byte[mdsize];
- statByte[0] = privateKeyOTS;
- statByte[1] = seed;
- statByte[2] = concHashs;
- statByte[3] = leaf;
-
- return statByte;
- }
-
- /**
- * Returns the status int array used by the GMSSPrivateKeyASN.1 class
- *
- * @return The status ints
- */
- public int[] getStatInt()
- {
-
- int[] statInt = new int[4];
- statInt[0] = i;
- statInt[1] = j;
- statInt[2] = steps;
- statInt[3] = w;
- return statInt;
- }
-
- /**
- * Returns a String representation of the main part of this element
- *
- * @return a String representation of the main part of this element
- */
- public String toString()
- {
- String out = "";
-
- for (int i = 0; i < 4; i++)
- {
- out = out + this.getStatInt()[i] + " ";
- }
- out = out + " " + this.mdsize + " " + this.keysize + " "
- + this.two_power_w + " ";
-
- byte[][] temp = this.getStatByte();
- for (int i = 0; i < 4; i++)
- {
- if (temp[i] != null)
- {
- out = out + new String(Hex.encode(temp[i])) + " ";
- }
- else
- {
- out = out + "null ";
- }
- }
- return out;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSParameters.java
deleted file mode 100644
index aa89f76a..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSParameters.java
+++ /dev/null
@@ -1,155 +0,0 @@
-package org.bouncycastle.pqc.crypto.gmss;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * This class provides a specification for the GMSS parameters that are used by
- * the GMSSKeyPairGenerator and GMSSSignature classes.
- *
- * @see org.bouncycastle.pqc.crypto.gmss.GMSSKeyPairGenerator
- */
-public class GMSSParameters
-{
- /**
- * The number of authentication tree layers.
- */
- private int numOfLayers;
-
- /**
- * The height of the authentication trees of each layer.
- */
- private int[] heightOfTrees;
-
- /**
- * The Winternitz Parameter 'w' of each layer.
- */
- private int[] winternitzParameter;
-
- /**
- * The parameter K needed for the authentication path computation
- */
- private int[] K;
-
- /**
- * The constructor for the parameters of the GMSSKeyPairGenerator.
- *
- * @param layers the number of authentication tree layers
- * @param heightOfTrees the height of the authentication trees
- * @param winternitzParameter the Winternitz Parameter 'w' of each layer
- * @param K parameter for authpath computation
- */
- public GMSSParameters(int layers, int[] heightOfTrees, int[] winternitzParameter, int[] K)
- throws IllegalArgumentException
- {
- init(layers, heightOfTrees, winternitzParameter, K);
- }
-
- private void init(int layers, int[] heightOfTrees,
- int[] winternitzParameter, int[] K)
- throws IllegalArgumentException
- {
- boolean valid = true;
- String errMsg = "";
- this.numOfLayers = layers;
- if ((numOfLayers != winternitzParameter.length)
- || (numOfLayers != heightOfTrees.length)
- || (numOfLayers != K.length))
- {
- valid = false;
- errMsg = "Unexpected parameterset format";
- }
- for (int i = 0; i < numOfLayers; i++)
- {
- if ((K[i] < 2) || ((heightOfTrees[i] - K[i]) % 2 != 0))
- {
- valid = false;
- errMsg = "Wrong parameter K (K >= 2 and H-K even required)!";
- }
-
- if ((heightOfTrees[i] < 4) || (winternitzParameter[i] < 2))
- {
- valid = false;
- errMsg = "Wrong parameter H or w (H > 3 and w > 1 required)!";
- }
- }
-
- if (valid)
- {
- this.heightOfTrees = Arrays.clone(heightOfTrees);
- this.winternitzParameter = Arrays.clone(winternitzParameter);
- this.K = Arrays.clone(K);
- }
- else
- {
- throw new IllegalArgumentException(errMsg);
- }
- }
-
- public GMSSParameters(int keySize)
- throws IllegalArgumentException
- {
- if (keySize <= 10)
- { // create 2^10 keys
- int[] defh = {10};
- int[] defw = {3};
- int[] defk = {2};
- this.init(defh.length, defh, defw, defk);
- }
- else if (keySize <= 20)
- { // create 2^20 keys
- int[] defh = {10, 10};
- int[] defw = {5, 4};
- int[] defk = {2, 2};
- this.init(defh.length, defh, defw, defk);
- }
- else
- { // create 2^40 keys, keygen lasts around 80 seconds
- int[] defh = {10, 10, 10, 10};
- int[] defw = {9, 9, 9, 3};
- int[] defk = {2, 2, 2, 2};
- this.init(defh.length, defh, defw, defk);
- }
- }
-
- /**
- * Returns the number of levels of the authentication trees.
- *
- * @return The number of levels of the authentication trees.
- */
- public int getNumOfLayers()
- {
- return numOfLayers;
- }
-
- /**
- * Returns the array of height (for each layer) of the authentication trees
- *
- * @return The array of height (for each layer) of the authentication trees
- */
- public int[] getHeightOfTrees()
- {
- return Arrays.clone(heightOfTrees);
- }
-
- /**
- * Returns the array of WinternitzParameter (for each layer) of the
- * authentication trees
- *
- * @return The array of WinternitzParameter (for each layer) of the
- * authentication trees
- */
- public int[] getWinternitzParameter()
- {
- return Arrays.clone(winternitzParameter);
- }
-
- /**
- * Returns the parameter K needed for authentication path computation
- *
- * @return The parameter K needed for authentication path computation
- */
- public int[] getK()
- {
- return Arrays.clone(K);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSPrivateKeyParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSPrivateKeyParameters.java
deleted file mode 100644
index 83cf7972..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSPrivateKeyParameters.java
+++ /dev/null
@@ -1,1041 +0,0 @@
-package org.bouncycastle.pqc.crypto.gmss;
-
-import java.util.Vector;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.pqc.crypto.gmss.util.GMSSRandom;
-import org.bouncycastle.pqc.crypto.gmss.util.WinternitzOTSignature;
-import org.bouncycastle.util.Arrays;
-
-
-/**
- * This class provides a specification for a GMSS private key.
- */
-public class GMSSPrivateKeyParameters
- extends GMSSKeyParameters
-{
- private int[] index;
-
- private byte[][] currentSeeds;
- private byte[][] nextNextSeeds;
-
- private byte[][][] currentAuthPaths;
- private byte[][][] nextAuthPaths;
-
- private Treehash[][] currentTreehash;
- private Treehash[][] nextTreehash;
-
- private Vector[] currentStack;
- private Vector[] nextStack;
-
- private Vector[][] currentRetain;
- private Vector[][] nextRetain;
-
- private byte[][][] keep;
-
- private GMSSLeaf[] nextNextLeaf;
- private GMSSLeaf[] upperLeaf;
- private GMSSLeaf[] upperTreehashLeaf;
-
- private int[] minTreehash;
-
- private GMSSParameters gmssPS;
-
- private byte[][] nextRoot;
- private GMSSRootCalc[] nextNextRoot;
-
- private byte[][] currentRootSig;
- private GMSSRootSig[] nextRootSig;
-
- private GMSSDigestProvider digestProvider;
-
- private boolean used = false;
-
- /**
- * An array of the heights of the authentication trees of each layer
- */
- private int[] heightOfTrees;
-
- /**
- * An array of the Winternitz parameter 'w' of each layer
- */
- private int[] otsIndex;
-
- /**
- * The parameter K needed for the authentication path computation
- */
- private int[] K;
-
- /**
- * the number of Layers
- */
- private int numLayer;
-
- /**
- * The hash function used to construct the authentication trees
- */
- private Digest messDigestTrees;
-
- /**
- * The message digest length
- */
- private int mdLength;
-
- /**
- * The PRNG used for private key generation
- */
- private GMSSRandom gmssRandom;
-
-
- /**
- * The number of leafs of one tree of each layer
- */
- private int[] numLeafs;
-
-
- /**
- * Generates a new GMSS private key
- *
- * @param currentSeed seed for the generation of private OTS keys for the
- * current subtrees
- * @param nextNextSeed seed for the generation of private OTS keys for the next
- * subtrees
- * @param currentAuthPath array of current authentication paths
- * @param nextAuthPath array of next authentication paths
- * @param currentTreehash array of current treehash instances
- * @param nextTreehash array of next treehash instances
- * @param currentStack array of current shared stacks
- * @param nextStack array of next shared stacks
- * @param currentRetain array of current retain stacks
- * @param nextRetain array of next retain stacks
- * @param nextRoot the roots of the next subtree
- * @param currentRootSig array of signatures of the roots of the current subtrees
- * @param gmssParameterset the GMSS Parameterset
- * @see org.bouncycastle.pqc.crypto.gmss.GMSSKeyPairGenerator
- */
-
- public GMSSPrivateKeyParameters(byte[][] currentSeed, byte[][] nextNextSeed,
- byte[][][] currentAuthPath, byte[][][] nextAuthPath,
- Treehash[][] currentTreehash, Treehash[][] nextTreehash,
- Vector[] currentStack, Vector[] nextStack,
- Vector[][] currentRetain, Vector[][] nextRetain, byte[][] nextRoot,
- byte[][] currentRootSig, GMSSParameters gmssParameterset,
- GMSSDigestProvider digestProvider)
- {
- this(null, currentSeed, nextNextSeed, currentAuthPath, nextAuthPath,
- null, currentTreehash, nextTreehash, currentStack, nextStack,
- currentRetain, nextRetain, null, null, null, null, nextRoot,
- null, currentRootSig, null, gmssParameterset, digestProvider);
- }
-
- /**
- * /**
- *
- * @param index tree indices
- * @param keep keep array for the authPath algorithm
- * @param currentTreehash treehash for authPath algorithm of current tree
- * @param nextTreehash treehash for authPath algorithm of next tree (TREE+)
- * @param currentStack shared stack for authPath algorithm of current tree
- * @param nextStack shared stack for authPath algorithm of next tree (TREE+)
- * @param currentRetain retain stack for authPath algorithm of current tree
- * @param nextRetain retain stack for authPath algorithm of next tree (TREE+)
- * @param nextNextLeaf array of upcoming leafs of the tree after next (LEAF++) of
- * each layer
- * @param upperLeaf needed for precomputation of upper nodes
- * @param upperTreehashLeaf needed for precomputation of upper treehash nodes
- * @param minTreehash index of next treehash instance to receive an update
- * @param nextRoot the roots of the next trees (ROOT+)
- * @param nextNextRoot the roots of the tree after next (ROOT++)
- * @param currentRootSig array of signatures of the roots of the current subtrees
- * (SIG)
- * @param nextRootSig array of signatures of the roots of the next subtree
- * (SIG+)
- * @param gmssParameterset the GMSS Parameterset
- */
- public GMSSPrivateKeyParameters(int[] index, byte[][] currentSeeds,
- byte[][] nextNextSeeds, byte[][][] currentAuthPaths,
- byte[][][] nextAuthPaths, byte[][][] keep,
- Treehash[][] currentTreehash, Treehash[][] nextTreehash,
- Vector[] currentStack, Vector[] nextStack,
- Vector[][] currentRetain, Vector[][] nextRetain,
- GMSSLeaf[] nextNextLeaf, GMSSLeaf[] upperLeaf,
- GMSSLeaf[] upperTreehashLeaf, int[] minTreehash, byte[][] nextRoot,
- GMSSRootCalc[] nextNextRoot, byte[][] currentRootSig,
- GMSSRootSig[] nextRootSig, GMSSParameters gmssParameterset,
- GMSSDigestProvider digestProvider)
- {
-
- super(true, gmssParameterset);
-
- // construct message digest
-
- this.messDigestTrees = digestProvider.get();
- this.mdLength = messDigestTrees.getDigestSize();
-
-
- // Parameter
- this.gmssPS = gmssParameterset;
- this.otsIndex = gmssParameterset.getWinternitzParameter();
- this.K = gmssParameterset.getK();
- this.heightOfTrees = gmssParameterset.getHeightOfTrees();
- // initialize numLayer
- this.numLayer = gmssPS.getNumOfLayers();
-
- // initialize index if null
- if (index == null)
- {
- this.index = new int[numLayer];
- for (int i = 0; i < numLayer; i++)
- {
- this.index[i] = 0;
- }
- }
- else
- {
- this.index = index;
- }
-
- this.currentSeeds = currentSeeds;
- this.nextNextSeeds = nextNextSeeds;
-
- this.currentAuthPaths = currentAuthPaths;
- this.nextAuthPaths = nextAuthPaths;
-
- // initialize keep if null
- if (keep == null)
- {
- this.keep = new byte[numLayer][][];
- for (int i = 0; i < numLayer; i++)
- {
- this.keep[i] = new byte[(int)Math.floor(heightOfTrees[i] / 2)][mdLength];
- }
- }
- else
- {
- this.keep = keep;
- }
-
- // initialize stack if null
- if (currentStack == null)
- {
- this.currentStack = new Vector[numLayer];
- for (int i = 0; i < numLayer; i++)
- {
- this.currentStack[i] = new Vector();
- }
- }
- else
- {
- this.currentStack = currentStack;
- }
-
- // initialize nextStack if null
- if (nextStack == null)
- {
- this.nextStack = new Vector[numLayer - 1];
- for (int i = 0; i < numLayer - 1; i++)
- {
- this.nextStack[i] = new Vector();
- }
- }
- else
- {
- this.nextStack = nextStack;
- }
-
- this.currentTreehash = currentTreehash;
- this.nextTreehash = nextTreehash;
-
- this.currentRetain = currentRetain;
- this.nextRetain = nextRetain;
-
- this.nextRoot = nextRoot;
-
- this.digestProvider = digestProvider;
-
- if (nextNextRoot == null)
- {
- this.nextNextRoot = new GMSSRootCalc[numLayer - 1];
- for (int i = 0; i < numLayer - 1; i++)
- {
- this.nextNextRoot[i] = new GMSSRootCalc(
- this.heightOfTrees[i + 1], this.K[i + 1], this.digestProvider);
- }
- }
- else
- {
- this.nextNextRoot = nextNextRoot;
- }
- this.currentRootSig = currentRootSig;
-
- // calculate numLeafs
- numLeafs = new int[numLayer];
- for (int i = 0; i < numLayer; i++)
- {
- numLeafs[i] = 1 << heightOfTrees[i];
- }
- // construct PRNG
- this.gmssRandom = new GMSSRandom(messDigestTrees);
-
- if (numLayer > 1)
- {
- // construct the nextNextLeaf (LEAFs++) array for upcoming leafs in
- // tree after next (TREE++)
- if (nextNextLeaf == null)
- {
- this.nextNextLeaf = new GMSSLeaf[numLayer - 2];
- for (int i = 0; i < numLayer - 2; i++)
- {
- this.nextNextLeaf[i] = new GMSSLeaf(digestProvider.get(), otsIndex[i + 1], numLeafs[i + 2], this.nextNextSeeds[i]);
- }
- }
- else
- {
- this.nextNextLeaf = nextNextLeaf;
- }
- }
- else
- {
- this.nextNextLeaf = new GMSSLeaf[0];
- }
-
- // construct the upperLeaf array for upcoming leafs in tree over the
- // actual
- if (upperLeaf == null)
- {
- this.upperLeaf = new GMSSLeaf[numLayer - 1];
- for (int i = 0; i < numLayer - 1; i++)
- {
- this.upperLeaf[i] = new GMSSLeaf(digestProvider.get(), otsIndex[i],
- numLeafs[i + 1], this.currentSeeds[i]);
- }
- }
- else
- {
- this.upperLeaf = upperLeaf;
- }
-
- // construct the leafs for upcoming leafs in treehashs in tree over the
- // actual
- if (upperTreehashLeaf == null)
- {
- this.upperTreehashLeaf = new GMSSLeaf[numLayer - 1];
- for (int i = 0; i < numLayer - 1; i++)
- {
- this.upperTreehashLeaf[i] = new GMSSLeaf(digestProvider.get(), otsIndex[i], numLeafs[i + 1]);
- }
- }
- else
- {
- this.upperTreehashLeaf = upperTreehashLeaf;
- }
-
- if (minTreehash == null)
- {
- this.minTreehash = new int[numLayer - 1];
- for (int i = 0; i < numLayer - 1; i++)
- {
- this.minTreehash[i] = -1;
- }
- }
- else
- {
- this.minTreehash = minTreehash;
- }
-
- // construct the nextRootSig (RootSig++)
- byte[] dummy = new byte[mdLength];
- byte[] OTSseed = new byte[mdLength];
- if (nextRootSig == null)
- {
- this.nextRootSig = new GMSSRootSig[numLayer - 1];
- for (int i = 0; i < numLayer - 1; i++)
- {
- System.arraycopy(currentSeeds[i], 0, dummy, 0, mdLength);
- gmssRandom.nextSeed(dummy);
- OTSseed = gmssRandom.nextSeed(dummy);
- this.nextRootSig[i] = new GMSSRootSig(digestProvider.get(), otsIndex[i],
- heightOfTrees[i + 1]);
- this.nextRootSig[i].initSign(OTSseed, nextRoot[i]);
- }
- }
- else
- {
- this.nextRootSig = nextRootSig;
- }
- }
-
- // we assume this only gets called from nextKey so used is never copied.
- private GMSSPrivateKeyParameters(GMSSPrivateKeyParameters original)
- {
- super(true, original.getParameters());
-
- this.index = Arrays.clone(original.index);
- this.currentSeeds = Arrays.clone(original.currentSeeds);
- this.nextNextSeeds = Arrays.clone(original.nextNextSeeds);
- this.currentAuthPaths = Arrays.clone(original.currentAuthPaths);
- this.nextAuthPaths = Arrays.clone(original.nextAuthPaths);
- this.currentTreehash = original.currentTreehash;
- this.nextTreehash = original.nextTreehash;
- this.currentStack = original.currentStack;
- this.nextStack = original.nextStack;
- this.currentRetain = original.currentRetain;
- this.nextRetain = original.nextRetain;
- this.keep = Arrays.clone(original.keep);
- this.nextNextLeaf = original.nextNextLeaf;
- this.upperLeaf = original.upperLeaf;
- this.upperTreehashLeaf = original.upperTreehashLeaf;
- this.minTreehash = original.minTreehash;
- this.gmssPS = original.gmssPS;
- this.nextRoot = Arrays.clone(original.nextRoot);
- this.nextNextRoot = original.nextNextRoot;
- this.currentRootSig = original.currentRootSig;
- this.nextRootSig = original.nextRootSig;
- this.digestProvider = original.digestProvider;
- this.heightOfTrees = original.heightOfTrees;
- this.otsIndex = original.otsIndex;
- this.K = original.K;
- this.numLayer = original.numLayer;
- this.messDigestTrees = original.messDigestTrees;
- this.mdLength = original.mdLength;
- this.gmssRandom = original.gmssRandom;
- this.numLeafs = original.numLeafs;
- }
-
- public boolean isUsed()
- {
- return this.used;
- }
-
- public void markUsed()
- {
- this.used = true;
- }
-
- public GMSSPrivateKeyParameters nextKey()
- {
- GMSSPrivateKeyParameters nKey = new GMSSPrivateKeyParameters(this);
-
- nKey.nextKey(gmssPS.getNumOfLayers() - 1);
-
- return nKey;
- }
-
- /**
- * This method updates the GMSS private key for the next signature
- *
- * @param layer the layer where the next key is processed
- */
- private void nextKey(int layer)
- {
- // only for lowest layer ( other layers indices are raised in nextTree()
- // method )
- if (layer == numLayer - 1)
- {
- index[layer]++;
- } // else System.out.println(" --- nextKey on layer " + layer + "
- // index is now : " + index[layer]);
-
- // if tree of this layer is depleted
- if (index[layer] == numLeafs[layer])
- {
- if (numLayer != 1)
- {
- nextTree(layer);
- index[layer] = 0;
- }
- }
- else
- {
- updateKey(layer);
- }
- }
-
- /**
- * Switch to next subtree if the current one is depleted
- *
- * @param layer the layer where the next tree is processed
- */
- private void nextTree(int layer)
- {
- // System.out.println("NextTree method called on layer " + layer);
- // dont create next tree for the top layer
- if (layer > 0)
- {
- // raise index for upper layer
- index[layer - 1]++;
-
- // test if it is already the last tree
- boolean lastTree = true;
- int z = layer;
- do
- {
- z--;
- if (index[z] < numLeafs[z])
- {
- lastTree = false;
- }
- }
- while (lastTree && (z > 0));
-
- // only construct next subtree if last one is not already in use
- if (!lastTree)
- {
- gmssRandom.nextSeed(currentSeeds[layer]);
-
- // last step of distributed signature calculation
- nextRootSig[layer - 1].updateSign();
-
- // last step of distributed leaf calculation for nextNextLeaf
- if (layer > 1)
- {
- nextNextLeaf[layer - 1 - 1] = nextNextLeaf[layer - 1 - 1].nextLeaf();
- }
-
- // last step of distributed leaf calculation for upper leaf
- upperLeaf[layer - 1] = upperLeaf[layer - 1].nextLeaf();
-
- // last step of distributed leaf calculation for all treehashs
-
- if (minTreehash[layer - 1] >= 0)
- {
- upperTreehashLeaf[layer - 1] = upperTreehashLeaf[layer - 1].nextLeaf();
- byte[] leaf = this.upperTreehashLeaf[layer - 1].getLeaf();
- // if update is required use the precomputed leaf to update
- // treehash
- try
- {
- currentTreehash[layer - 1][minTreehash[layer - 1]]
- .update(this.gmssRandom, leaf);
- // System.out.println("UUUpdated TH " +
- // minTreehash[layer - 1]);
- if (currentTreehash[layer - 1][minTreehash[layer - 1]]
- .wasFinished())
- {
- // System.out.println("FFFinished TH " +
- // minTreehash[layer - 1]);
- }
- }
- catch (Exception e)
- {
- System.out.println(e);
- }
- }
-
- // last step of nextNextAuthRoot calculation
- this.updateNextNextAuthRoot(layer);
-
- // ******************************************************** /
-
- // NOW: advance to next tree on layer 'layer'
-
- // NextRootSig --> currentRootSigs
- this.currentRootSig[layer - 1] = nextRootSig[layer - 1]
- .getSig();
-
- // -----------------------
-
- // nextTreehash --> currentTreehash
- // nextNextTreehash --> nextTreehash
- for (int i = 0; i < heightOfTrees[layer] - K[layer]; i++)
- {
- this.currentTreehash[layer][i] = this.nextTreehash[layer - 1][i];
- this.nextTreehash[layer - 1][i] = this.nextNextRoot[layer - 1]
- .getTreehash()[i];
- }
-
- // NextAuthPath --> currentAuthPath
- // nextNextAuthPath --> nextAuthPath
- for (int i = 0; i < heightOfTrees[layer]; i++)
- {
- System.arraycopy(nextAuthPaths[layer - 1][i], 0,
- currentAuthPaths[layer][i], 0, mdLength);
- System.arraycopy(nextNextRoot[layer - 1].getAuthPath()[i],
- 0, nextAuthPaths[layer - 1][i], 0, mdLength);
- }
-
- // nextRetain --> currentRetain
- // nextNextRetain --> nextRetain
- for (int i = 0; i < K[layer] - 1; i++)
- {
- this.currentRetain[layer][i] = this.nextRetain[layer - 1][i];
- this.nextRetain[layer - 1][i] = this.nextNextRoot[layer - 1]
- .getRetain()[i];
- }
-
- // nextStack --> currentStack
- this.currentStack[layer] = this.nextStack[layer - 1];
- // nextNextStack --> nextStack
- this.nextStack[layer - 1] = this.nextNextRoot[layer - 1]
- .getStack();
-
- // nextNextRoot --> nextRoot
- this.nextRoot[layer - 1] = this.nextNextRoot[layer - 1]
- .getRoot();
- // -----------------------
-
- // -----------------
- byte[] OTSseed = new byte[mdLength];
- byte[] dummy = new byte[mdLength];
- // gmssRandom.setSeed(currentSeeds[layer]);
- System
- .arraycopy(currentSeeds[layer - 1], 0, dummy, 0,
- mdLength);
- OTSseed = gmssRandom.nextSeed(dummy); // only need OTSSeed
- OTSseed = gmssRandom.nextSeed(dummy);
- OTSseed = gmssRandom.nextSeed(dummy);
- // nextWinSig[layer-1]=new
- // GMSSWinSig(OTSseed,algNames,otsIndex[layer-1],heightOfTrees[layer],nextRoot[layer-1]);
- nextRootSig[layer - 1].initSign(OTSseed, nextRoot[layer - 1]);
-
- // nextKey for upper layer
- nextKey(layer - 1);
- }
- }
- }
-
- /**
- * This method computes the authpath (AUTH) for the current tree,
- * Additionally the root signature for the next tree (SIG+), the authpath
- * (AUTH++) and root (ROOT++) for the tree after next in layer
- * <code>layer</code>, and the LEAF++^1 for the next next tree in the
- * layer above are updated This method is used by nextKey()
- *
- * @param layer
- */
- private void updateKey(int layer)
- {
- // ----------current tree processing of actual layer---------
- // compute upcoming authpath for current Tree (AUTH)
- computeAuthPaths(layer);
-
- // -----------distributed calculations part------------
- // not for highest tree layer
- if (layer > 0)
- {
-
- // compute (partial) next leaf on TREE++ (not on layer 1 and 0)
- if (layer > 1)
- {
- nextNextLeaf[layer - 1 - 1] = nextNextLeaf[layer - 1 - 1].nextLeaf();
- }
-
- // compute (partial) next leaf on tree above (not on layer 0)
- upperLeaf[layer - 1] = upperLeaf[layer - 1].nextLeaf();
-
- // compute (partial) next leaf for all treehashs on tree above (not
- // on layer 0)
-
- int t = (int)Math
- .floor((double)(this.getNumLeafs(layer) * 2)
- / (double)(this.heightOfTrees[layer - 1] - this.K[layer - 1]));
-
- if (index[layer] % t == 1)
- {
- // System.out.println(" layer: " + layer + " index: " +
- // index[layer] + " t : " + t);
-
- // take precomputed node for treehash update
- // ------------------------------------------------
- if (index[layer] > 1 && minTreehash[layer - 1] >= 0)
- {
- byte[] leaf = this.upperTreehashLeaf[layer - 1].getLeaf();
- // if update is required use the precomputed leaf to update
- // treehash
- try
- {
- currentTreehash[layer - 1][minTreehash[layer - 1]]
- .update(this.gmssRandom, leaf);
- // System.out.println("Updated TH " + minTreehash[layer
- // - 1]);
- if (currentTreehash[layer - 1][minTreehash[layer - 1]]
- .wasFinished())
- {
- // System.out.println("Finished TH " +
- // minTreehash[layer - 1]);
- }
- }
- catch (Exception e)
- {
- System.out.println(e);
- }
- // ------------------------------------------------
- }
-
- // initialize next leaf precomputation
- // ------------------------------------------------
-
- // get lowest index of treehashs
- this.minTreehash[layer - 1] = getMinTreehashIndex(layer - 1);
-
- if (this.minTreehash[layer - 1] >= 0)
- {
- // initialize leaf
- byte[] seed = this.currentTreehash[layer - 1][this.minTreehash[layer - 1]]
- .getSeedActive();
- this.upperTreehashLeaf[layer - 1] = new GMSSLeaf(
- this.digestProvider.get(), this.otsIndex[layer - 1], t, seed);
- this.upperTreehashLeaf[layer - 1] = this.upperTreehashLeaf[layer - 1].nextLeaf();
- // System.out.println("restarted treehashleaf (" + (layer -
- // 1) + "," + this.minTreehash[layer - 1] + ")");
- }
- // ------------------------------------------------
-
- }
- else
- {
- // update the upper leaf for the treehash one step
- if (this.minTreehash[layer - 1] >= 0)
- {
- this.upperTreehashLeaf[layer - 1] = this.upperTreehashLeaf[layer - 1].nextLeaf();
- // if (minTreehash[layer - 1] > 3)
- // System.out.print("#");
- }
- }
-
- // compute (partial) the signature of ROOT+ (RootSig+) (not on top
- // layer)
- nextRootSig[layer - 1].updateSign();
-
- // compute (partial) AUTHPATH++ & ROOT++ (not on top layer)
- if (index[layer] == 1)
- {
- // init root and authpath calculation for tree after next
- // (AUTH++, ROOT++)
- this.nextNextRoot[layer - 1].initialize(new Vector());
- }
-
- // update root and authpath calculation for tree after next (AUTH++,
- // ROOT++)
- this.updateNextNextAuthRoot(layer);
- }
- // ----------- end distributed calculations part-----------------
- }
-
- /**
- * This method returns the index of the next Treehash instance that should
- * receive an update
- *
- * @param layer the layer of the GMSS tree
- * @return index of the treehash instance that should get the update
- */
- private int getMinTreehashIndex(int layer)
- {
- int minTreehash = -1;
- for (int h = 0; h < heightOfTrees[layer] - K[layer]; h++)
- {
- if (currentTreehash[layer][h].wasInitialized()
- && !currentTreehash[layer][h].wasFinished())
- {
- if (minTreehash == -1)
- {
- minTreehash = h;
- }
- else if (currentTreehash[layer][h].getLowestNodeHeight() < currentTreehash[layer][minTreehash]
- .getLowestNodeHeight())
- {
- minTreehash = h;
- }
- }
- }
- return minTreehash;
- }
-
- /**
- * Computes the upcoming currentAuthpath of layer <code>layer</code> using
- * the revisited authentication path computation of Dahmen/Schneider 2008
- *
- * @param layer the actual layer
- */
- private void computeAuthPaths(int layer)
- {
-
- int Phi = index[layer];
- int H = heightOfTrees[layer];
- int K = this.K[layer];
-
- // update all nextSeeds for seed scheduling
- for (int i = 0; i < H - K; i++)
- {
- currentTreehash[layer][i].updateNextSeed(gmssRandom);
- }
-
- // STEP 1 of Algorithm
- int Tau = heightOfPhi(Phi);
-
- byte[] OTSseed = new byte[mdLength];
- OTSseed = gmssRandom.nextSeed(currentSeeds[layer]);
-
- // STEP 2 of Algorithm
- // if phi's parent on height tau + 1 if left node, store auth_tau
- // in keep_tau.
- // TODO check it, formerly was
- // int L = Phi / (int) Math.floor(Math.pow(2, Tau + 1));
- // L %= 2;
- int L = (Phi >>> (Tau + 1)) & 1;
-
- byte[] tempKeep = new byte[mdLength];
- // store the keep node not in keep[layer][tau/2] because it might be in
- // use
- // wait until the space is freed in step 4a
- if (Tau < H - 1 && L == 0)
- {
- System.arraycopy(currentAuthPaths[layer][Tau], 0, tempKeep, 0,
- mdLength);
- }
-
- byte[] help = new byte[mdLength];
- // STEP 3 of Algorithm
- // if phi is left child, compute and store leaf for next currentAuthPath
- // path,
- // (obtained by veriying current signature)
- if (Tau == 0)
- {
- // LEAFCALC !!!
- if (layer == numLayer - 1)
- { // lowest layer computes the
- // necessary leaf completely at this
- // time
- WinternitzOTSignature ots = new WinternitzOTSignature(OTSseed,
- digestProvider.get(), otsIndex[layer]);
- help = ots.getPublicKey();
- }
- else
- { // other layers use the precomputed leafs in
- // nextNextLeaf
- byte[] dummy = new byte[mdLength];
- System.arraycopy(currentSeeds[layer], 0, dummy, 0, mdLength);
- gmssRandom.nextSeed(dummy);
- help = upperLeaf[layer].getLeaf();
- this.upperLeaf[layer].initLeafCalc(dummy);
-
- // WinternitzOTSVerify otsver = new
- // WinternitzOTSVerify(algNames, otsIndex[layer]);
- // byte[] help2 = otsver.Verify(currentRoot[layer],
- // currentRootSig[layer]);
- // System.out.println(" --- " + layer + " " +
- // ByteUtils.toHexString(help) + " " +
- // ByteUtils.toHexString(help2));
- }
- System.arraycopy(help, 0, currentAuthPaths[layer][0], 0, mdLength);
- }
- else
- {
- // STEP 4a of Algorithm
- // get new left currentAuthPath node on height tau
- byte[] toBeHashed = new byte[mdLength << 1];
- System.arraycopy(currentAuthPaths[layer][Tau - 1], 0, toBeHashed,
- 0, mdLength);
- // free the shared keep[layer][tau/2]
- System.arraycopy(keep[layer][(int)Math.floor((Tau - 1) / 2)], 0,
- toBeHashed, mdLength, mdLength);
- messDigestTrees.update(toBeHashed, 0, toBeHashed.length);
- currentAuthPaths[layer][Tau] = new byte[messDigestTrees.getDigestSize()];
- messDigestTrees.doFinal(currentAuthPaths[layer][Tau], 0);
-
- // STEP 4b and 4c of Algorithm
- // copy right nodes to currentAuthPath on height 0..Tau-1
- for (int i = 0; i < Tau; i++)
- {
-
- // STEP 4b of Algorithm
- // 1st: copy from treehashs
- if (i < H - K)
- {
- if (currentTreehash[layer][i].wasFinished())
- {
- System.arraycopy(currentTreehash[layer][i]
- .getFirstNode(), 0, currentAuthPaths[layer][i],
- 0, mdLength);
- currentTreehash[layer][i].destroy();
- }
- else
- {
- System.err
- .println("Treehash ("
- + layer
- + ","
- + i
- + ") not finished when needed in AuthPathComputation");
- }
- }
-
- // 2nd: copy precomputed values from Retain
- if (i < H - 1 && i >= H - K)
- {
- if (currentRetain[layer][i - (H - K)].size() > 0)
- {
- // pop element from retain
- System.arraycopy(currentRetain[layer][i - (H - K)]
- .lastElement(), 0, currentAuthPaths[layer][i],
- 0, mdLength);
- currentRetain[layer][i - (H - K)]
- .removeElementAt(currentRetain[layer][i
- - (H - K)].size() - 1);
- }
- }
-
- // STEP 4c of Algorithm
- // initialize new stack at heights 0..Tau-1
- if (i < H - K)
- {
- // create stacks anew
- int startPoint = Phi + 3 * (1 << i);
- if (startPoint < numLeafs[layer])
- {
- // if (layer < 2) {
- // System.out.println("initialized TH " + i + " on layer
- // " + layer);
- // }
- currentTreehash[layer][i].initialize();
- }
- }
- }
- }
-
- // now keep space is free to use
- if (Tau < H - 1 && L == 0)
- {
- System.arraycopy(tempKeep, 0,
- keep[layer][(int)Math.floor(Tau / 2)], 0, mdLength);
- }
-
- // only update empty stack at height h if all other stacks have
- // tailnodes with height >h
- // finds active stack with lowest node height, choses lower index in
- // case of tie
-
- // on the lowest layer leafs must be computed at once, no precomputation
- // is possible. So all treehash updates are done at once here
- if (layer == numLayer - 1)
- {
- for (int tmp = 1; tmp <= (H - K) / 2; tmp++)
- {
- // index of the treehash instance that receives the next update
- int minTreehash = getMinTreehashIndex(layer);
-
- // if active treehash is found update with a leaf
- if (minTreehash >= 0)
- {
- try
- {
- byte[] seed = new byte[mdLength];
- System.arraycopy(
- this.currentTreehash[layer][minTreehash]
- .getSeedActive(), 0, seed, 0, mdLength);
- byte[] seed2 = gmssRandom.nextSeed(seed);
- WinternitzOTSignature ots = new WinternitzOTSignature(
- seed2, this.digestProvider.get(), this.otsIndex[layer]);
- byte[] leaf = ots.getPublicKey();
- currentTreehash[layer][minTreehash].update(
- this.gmssRandom, leaf);
- }
- catch (Exception e)
- {
- System.out.println(e);
- }
- }
- }
- }
- else
- { // on higher layers the updates are done later
- this.minTreehash[layer] = getMinTreehashIndex(layer);
- }
- }
-
- /**
- * Returns the largest h such that 2^h | Phi
- *
- * @param Phi the leaf index
- * @return The largest <code>h</code> with <code>2^h | Phi</code> if
- * <code>Phi!=0</code> else return <code>-1</code>
- */
- private int heightOfPhi(int Phi)
- {
- if (Phi == 0)
- {
- return -1;
- }
- int Tau = 0;
- int modul = 1;
- while (Phi % modul == 0)
- {
- modul *= 2;
- Tau += 1;
- }
- return Tau - 1;
- }
-
- /**
- * Updates the authentication path and root calculation for the tree after
- * next (AUTH++, ROOT++) in layer <code>layer</code>
- *
- * @param layer
- */
- private void updateNextNextAuthRoot(int layer)
- {
-
- byte[] OTSseed = new byte[mdLength];
- OTSseed = gmssRandom.nextSeed(nextNextSeeds[layer - 1]);
-
- // get the necessary leaf
- if (layer == numLayer - 1)
- { // lowest layer computes the necessary
- // leaf completely at this time
- WinternitzOTSignature ots = new WinternitzOTSignature(OTSseed,
- digestProvider.get(), otsIndex[layer]);
- this.nextNextRoot[layer - 1].update(nextNextSeeds[layer - 1], ots
- .getPublicKey());
- }
- else
- { // other layers use the precomputed leafs in nextNextLeaf
- this.nextNextRoot[layer - 1].update(nextNextSeeds[layer - 1], nextNextLeaf[layer - 1].getLeaf());
- this.nextNextLeaf[layer - 1].initLeafCalc(nextNextSeeds[layer - 1]);
- }
- }
-
- public int[] getIndex()
- {
- return index;
- }
-
- /**
- * @return The current index of layer i
- */
- public int getIndex(int i)
- {
- return index[i];
- }
-
- public byte[][] getCurrentSeeds()
- {
- return Arrays.clone(currentSeeds);
- }
-
- public byte[][][] getCurrentAuthPaths()
- {
- return Arrays.clone(currentAuthPaths);
- }
-
- /**
- * @return The one-time signature of the root of the current subtree
- */
- public byte[] getSubtreeRootSig(int i)
- {
- return currentRootSig[i];
- }
-
-
- public GMSSDigestProvider getName()
- {
- return digestProvider;
- }
-
- /**
- * @return The number of leafs of each tree of layer i
- */
- public int getNumLeafs(int i)
- {
- return numLeafs[i];
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSPublicKeyParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSPublicKeyParameters.java
deleted file mode 100644
index 492802d4..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSPublicKeyParameters.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.bouncycastle.pqc.crypto.gmss;
-
-
-public class GMSSPublicKeyParameters
- extends GMSSKeyParameters
-{
- /**
- * The GMSS public key
- */
- private byte[] gmssPublicKey;
-
- /**
- * The constructor.
- *
- * @param key a raw GMSS public key
- * @param gmssParameterSet an instance of GMSSParameterset
- */
- public GMSSPublicKeyParameters(byte[] key, GMSSParameters gmssParameterSet)
- {
- super(false, gmssParameterSet);
- this.gmssPublicKey = key;
- }
-
- /**
- * Returns the GMSS public key
- *
- * @return The GMSS public key
- */
- public byte[] getPublicKey()
- {
- return gmssPublicKey;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSRootCalc.java b/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSRootCalc.java
deleted file mode 100644
index 35ac2e32..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSRootCalc.java
+++ /dev/null
@@ -1,596 +0,0 @@
-package org.bouncycastle.pqc.crypto.gmss;
-
-import java.util.Enumeration;
-import java.util.Vector;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Integers;
-import org.bouncycastle.util.encoders.Hex;
-
-
-/**
- * This class computes a whole Merkle tree and saves the needed values for
- * AuthPath computation. It is used for precomputation of the root of a
- * following tree. After initialization, 2^H updates are required to complete
- * the root. Every update requires one leaf value as parameter. While computing
- * the root all initial values for the authentication path algorithm (treehash,
- * auth, retain) are stored for later use.
- */
-public class GMSSRootCalc
-{
-
- /**
- * max height of the tree
- */
- private int heightOfTree;
-
- /**
- * length of the messageDigest
- */
- private int mdLength;
-
- /**
- * the treehash instances of the tree
- */
- private Treehash[] treehash;
-
- /**
- * stores the retain nodes for authPath computation
- */
- private Vector[] retain;
-
- /**
- * finally stores the root of the tree when finished
- */
- private byte[] root;
-
- /**
- * stores the authentication path y_1(i), i = 0..H-1
- */
- private byte[][] AuthPath;
-
- /**
- * the value K for the authentication path computation
- */
- private int K;
-
- /**
- * Vector element that stores the nodes on the stack
- */
- private Vector tailStack;
-
- /**
- * stores the height of all nodes laying on the tailStack
- */
- private Vector heightOfNodes;
- /**
- * The hash function used for the construction of the authentication trees
- */
- private Digest messDigestTree;
-
- /**
- * An array of strings containing the name of the hash function used to
- * construct the authentication trees and used by the OTS.
- */
- private GMSSDigestProvider digestProvider;
-
- /**
- * stores the index of the current node on each height of the tree
- */
- private int[] index;
-
- /**
- * true if instance was already initialized, false otherwise
- */
- private boolean isInitialized;
-
- /**
- * true it instance was finished
- */
- private boolean isFinished;
-
- /**
- * Integer that stores the index of the next seed that has to be omitted to
- * the treehashs
- */
- private int indexForNextSeed;
-
- /**
- * temporary integer that stores the height of the next treehash instance
- * that gets initialized with a seed
- */
- private int heightOfNextSeed;
-
- /**
- * This constructor regenerates a prior treehash object
- *
- * @param digest an array of strings, containing the digest of the used hash
- * function and PRNG and the digest of the corresponding
- * provider
- * @param statByte status bytes
- * @param statInt status ints
- */
- public GMSSRootCalc(Digest digest, byte[][] statByte, int[] statInt,
- Treehash[] treeH, Vector[] ret)
- {
- this.messDigestTree = digestProvider.get();
- this.digestProvider = digestProvider;
- // decode statInt
- this.heightOfTree = statInt[0];
- this.mdLength = statInt[1];
- this.K = statInt[2];
- this.indexForNextSeed = statInt[3];
- this.heightOfNextSeed = statInt[4];
- if (statInt[5] == 1)
- {
- this.isFinished = true;
- }
- else
- {
- this.isFinished = false;
- }
- if (statInt[6] == 1)
- {
- this.isInitialized = true;
- }
- else
- {
- this.isInitialized = false;
- }
-
- int tailLength = statInt[7];
-
- this.index = new int[heightOfTree];
- for (int i = 0; i < heightOfTree; i++)
- {
- this.index[i] = statInt[8 + i];
- }
-
- this.heightOfNodes = new Vector();
- for (int i = 0; i < tailLength; i++)
- {
- this.heightOfNodes.addElement(Integers.valueOf(statInt[8 + heightOfTree
- + i]));
- }
-
- // decode statByte
- this.root = statByte[0];
-
- this.AuthPath = new byte[heightOfTree][mdLength];
- for (int i = 0; i < heightOfTree; i++)
- {
- this.AuthPath[i] = statByte[1 + i];
- }
-
- this.tailStack = new Vector();
- for (int i = 0; i < tailLength; i++)
- {
- this.tailStack.addElement(statByte[1 + heightOfTree + i]);
- }
-
- // decode treeH
- this.treehash = GMSSUtils.clone(treeH);
-
- // decode ret
- this.retain = GMSSUtils.clone(ret);
- }
-
- /**
- * Constructor
- *
- * @param heightOfTree maximal height of the tree
- * @param digestProvider an array of strings, containing the name of the used hash
- * function and PRNG and the name of the corresponding
- * provider
- */
- public GMSSRootCalc(int heightOfTree, int K, GMSSDigestProvider digestProvider)
- {
- this.heightOfTree = heightOfTree;
- this.digestProvider = digestProvider;
- this.messDigestTree = digestProvider.get();
- this.mdLength = messDigestTree.getDigestSize();
- this.K = K;
- this.index = new int[heightOfTree];
- this.AuthPath = new byte[heightOfTree][mdLength];
- this.root = new byte[mdLength];
- // this.treehash = new Treehash[this.heightOfTree - this.K];
- this.retain = new Vector[this.K - 1];
- for (int i = 0; i < K - 1; i++)
- {
- this.retain[i] = new Vector();
- }
-
- }
-
- /**
- * Initializes the calculation of a new root
- *
- * @param sharedStack the stack shared by all treehash instances of this tree
- */
- public void initialize(Vector sharedStack)
- {
- this.treehash = new Treehash[this.heightOfTree - this.K];
- for (int i = 0; i < this.heightOfTree - this.K; i++)
- {
- this.treehash[i] = new Treehash(sharedStack, i, this.digestProvider.get());
- }
-
- this.index = new int[heightOfTree];
- this.AuthPath = new byte[heightOfTree][mdLength];
- this.root = new byte[mdLength];
-
- this.tailStack = new Vector();
- this.heightOfNodes = new Vector();
- this.isInitialized = true;
- this.isFinished = false;
-
- for (int i = 0; i < heightOfTree; i++)
- {
- this.index[i] = -1;
- }
-
- this.retain = new Vector[this.K - 1];
- for (int i = 0; i < K - 1; i++)
- {
- this.retain[i] = new Vector();
- }
-
- this.indexForNextSeed = 3;
- this.heightOfNextSeed = 0;
- }
-
- /**
- * updates the root with one leaf and stores needed values in retain,
- * treehash or authpath. Additionally counts the seeds used. This method is
- * used when performing the updates for TREE++.
- *
- * @param seed the initial seed for treehash: seedNext
- * @param leaf the height of the treehash
- */
- public void update(byte[] seed, byte[] leaf)
- {
- if (this.heightOfNextSeed < (this.heightOfTree - this.K)
- && this.indexForNextSeed - 2 == index[0])
- {
- this.initializeTreehashSeed(seed, this.heightOfNextSeed);
- this.heightOfNextSeed++;
- this.indexForNextSeed *= 2;
- }
- // now call the simple update
- this.update(leaf);
- }
-
- /**
- * Updates the root with one leaf and stores the needed values in retain,
- * treehash or authpath
- */
- public void update(byte[] leaf)
- {
-
- if (isFinished)
- {
- System.out.print("Too much updates for Tree!!");
- return;
- }
- if (!isInitialized)
- {
- System.err.println("GMSSRootCalc not initialized!");
- return;
- }
-
- // a new leaf was omitted, so raise index on lowest layer
- index[0]++;
-
- // store the nodes on the lowest layer in treehash or authpath
- if (index[0] == 1)
- {
- System.arraycopy(leaf, 0, AuthPath[0], 0, mdLength);
- }
- else if (index[0] == 3)
- {
- // store in treehash only if K < H
- if (heightOfTree > K)
- {
- treehash[0].setFirstNode(leaf);
- }
- }
-
- if ((index[0] - 3) % 2 == 0 && index[0] >= 3)
- {
- // store in retain if K = H
- if (heightOfTree == K)
- // TODO: check it
- {
- retain[0].insertElementAt(leaf, 0);
- }
- }
-
- // if first update to this tree is made
- if (index[0] == 0)
- {
- tailStack.addElement(leaf);
- heightOfNodes.addElement(Integers.valueOf(0));
- }
- else
- {
-
- byte[] help = new byte[mdLength];
- byte[] toBeHashed = new byte[mdLength << 1];
-
- // store the new leaf in help
- System.arraycopy(leaf, 0, help, 0, mdLength);
- int helpHeight = 0;
- // while top to nodes have same height
- while (tailStack.size() > 0
- && helpHeight == ((Integer)heightOfNodes.lastElement())
- .intValue())
- {
-
- // help <-- hash(stack top element || help)
- System.arraycopy(tailStack.lastElement(), 0, toBeHashed, 0,
- mdLength);
- tailStack.removeElementAt(tailStack.size() - 1);
- heightOfNodes.removeElementAt(heightOfNodes.size() - 1);
- System.arraycopy(help, 0, toBeHashed, mdLength, mdLength);
-
- messDigestTree.update(toBeHashed, 0, toBeHashed.length);
- help = new byte[messDigestTree.getDigestSize()];
- messDigestTree.doFinal(help, 0);
-
- // the new help node is one step higher
- helpHeight++;
- if (helpHeight < heightOfTree)
- {
- index[helpHeight]++;
-
- // add index 1 element to initial authpath
- if (index[helpHeight] == 1)
- {
- System.arraycopy(help, 0, AuthPath[helpHeight], 0,
- mdLength);
- }
-
- if (helpHeight >= heightOfTree - K)
- {
- if (helpHeight == 0)
- {
- System.out.println("M���P");
- }
- // add help element to retain stack if it is a right
- // node
- // and not stored in treehash
- if ((index[helpHeight] - 3) % 2 == 0
- && index[helpHeight] >= 3)
- // TODO: check it
- {
- retain[helpHeight - (heightOfTree - K)]
- .insertElementAt(help, 0);
- }
- }
- else
- {
- // if element is third in his line add it to treehash
- if (index[helpHeight] == 3)
- {
- treehash[helpHeight].setFirstNode(help);
- }
- }
- }
- }
- // push help element to the stack
- tailStack.addElement(help);
- heightOfNodes.addElement(Integers.valueOf(helpHeight));
-
- // is the root calculation finished?
- if (helpHeight == heightOfTree)
- {
- isFinished = true;
- isInitialized = false;
- root = (byte[])tailStack.lastElement();
- }
- }
-
- }
-
- /**
- * initializes the seeds for the treehashs of the tree precomputed by this
- * class
- *
- * @param seed the initial seed for treehash: seedNext
- * @param index the height of the treehash
- */
- public void initializeTreehashSeed(byte[] seed, int index)
- {
- treehash[index].initializeSeed(seed);
- }
-
- /**
- * Method to check whether the instance has been initialized or not
- *
- * @return true if treehash was already initialized
- */
- public boolean wasInitialized()
- {
- return isInitialized;
- }
-
- /**
- * Method to check whether the instance has been finished or not
- *
- * @return true if tree has reached its maximum height
- */
- public boolean wasFinished()
- {
- return isFinished;
- }
-
- /**
- * returns the authentication path of the first leaf of the tree
- *
- * @return the authentication path of the first leaf of the tree
- */
- public byte[][] getAuthPath()
- {
- return GMSSUtils.clone(AuthPath);
- }
-
- /**
- * returns the initial treehash instances, storing value y_3(i)
- *
- * @return the initial treehash instances, storing value y_3(i)
- */
- public Treehash[] getTreehash()
- {
- return GMSSUtils.clone(treehash);
- }
-
- /**
- * returns the retain stacks storing all right nodes near to the root
- *
- * @return the retain stacks storing all right nodes near to the root
- */
- public Vector[] getRetain()
- {
- return GMSSUtils.clone(retain);
- }
-
- /**
- * returns the finished root value
- *
- * @return the finished root value
- */
- public byte[] getRoot()
- {
- return Arrays.clone(root);
- }
-
- /**
- * returns the shared stack
- *
- * @return the shared stack
- */
- public Vector getStack()
- {
- Vector copy = new Vector();
- for (Enumeration en = tailStack.elements(); en.hasMoreElements();)
- {
- copy.addElement(en.nextElement());
- }
- return copy;
- }
-
- /**
- * Returns the status byte array used by the GMSSPrivateKeyASN.1 class
- *
- * @return The status bytes
- */
- public byte[][] getStatByte()
- {
-
- int tailLength;
- if (tailStack == null)
- {
- tailLength = 0;
- }
- else
- {
- tailLength = tailStack.size();
- }
- byte[][] statByte = new byte[1 + heightOfTree + tailLength][64]; //FIXME: messDigestTree.getByteLength()
- statByte[0] = root;
-
- for (int i = 0; i < heightOfTree; i++)
- {
- statByte[1 + i] = AuthPath[i];
- }
- for (int i = 0; i < tailLength; i++)
- {
- statByte[1 + heightOfTree + i] = (byte[])tailStack.elementAt(i);
- }
-
- return statByte;
- }
-
- /**
- * Returns the status int array used by the GMSSPrivateKeyASN.1 class
- *
- * @return The status ints
- */
- public int[] getStatInt()
- {
-
- int tailLength;
- if (tailStack == null)
- {
- tailLength = 0;
- }
- else
- {
- tailLength = tailStack.size();
- }
- int[] statInt = new int[8 + heightOfTree + tailLength];
- statInt[0] = heightOfTree;
- statInt[1] = mdLength;
- statInt[2] = K;
- statInt[3] = indexForNextSeed;
- statInt[4] = heightOfNextSeed;
- if (isFinished)
- {
- statInt[5] = 1;
- }
- else
- {
- statInt[5] = 0;
- }
- if (isInitialized)
- {
- statInt[6] = 1;
- }
- else
- {
- statInt[6] = 0;
- }
- statInt[7] = tailLength;
-
- for (int i = 0; i < heightOfTree; i++)
- {
- statInt[8 + i] = index[i];
- }
- for (int i = 0; i < tailLength; i++)
- {
- statInt[8 + heightOfTree + i] = ((Integer)heightOfNodes
- .elementAt(i)).intValue();
- }
-
- return statInt;
- }
-
- /**
- * @return a human readable version of the structure
- */
- public String toString()
- {
- String out = "";
- int tailLength;
- if (tailStack == null)
- {
- tailLength = 0;
- }
- else
- {
- tailLength = tailStack.size();
- }
-
- for (int i = 0; i < 8 + heightOfTree + tailLength; i++)
- {
- out = out + getStatInt()[i] + " ";
- }
- for (int i = 0; i < 1 + heightOfTree + tailLength; i++)
- {
- out = out + new String(Hex.encode(getStatByte()[i])) + " ";
- }
- out = out + " " + digestProvider.get().getDigestSize();
- return out;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSRootSig.java b/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSRootSig.java
deleted file mode 100644
index 8a4796f0..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSRootSig.java
+++ /dev/null
@@ -1,666 +0,0 @@
-package org.bouncycastle.pqc.crypto.gmss;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.pqc.crypto.gmss.util.GMSSRandom;
-import org.bouncycastle.util.encoders.Hex;
-
-
-/**
- * This class implements the distributed signature generation of the Winternitz
- * one-time signature scheme (OTSS), described in C.Dods, N.P. Smart, and M.
- * Stam, "Hash Based Digital Signature Schemes", LNCS 3796, pages 96&#8211;115,
- * 2005. The class is used by the GMSS classes.
- */
-public class GMSSRootSig
-{
-
- /**
- * The hash function used by the OTS
- */
- private Digest messDigestOTS;
-
- /**
- * The length of the message digest and private key
- */
- private int mdsize, keysize;
-
- /**
- * The private key
- */
- private byte[] privateKeyOTS;
-
- /**
- * The message bytes
- */
- private byte[] hash;
-
- /**
- * The signature bytes
- */
- private byte[] sign;
-
- /**
- * The Winternitz parameter
- */
- private int w;
-
- /**
- * The source of randomness for OTS private key generation
- */
- private GMSSRandom gmssRandom;
-
- /**
- * Sizes of the message
- */
- private int messagesize;
-
- /**
- * Some precalculated values
- */
- private int k;
-
- /**
- * Some variables for storing the actual status of distributed signing
- */
- private int r, test, counter, ii;
-
- /**
- * variables for storing big numbers for the actual status of distributed
- * signing
- */
- private long test8, big8;
-
- /**
- * The necessary steps of each updateSign() call
- */
- private int steps;
-
- /**
- * The checksum part
- */
- private int checksum;
-
- /**
- * The height of the tree
- */
- private int height;
-
- /**
- * The current intern OTSseed
- */
- private byte[] seed;
-
- /**
- * This constructor regenerates a prior GMSSRootSig object used by the
- * GMSSPrivateKeyASN.1 class
- *
- * @param digest an array of strings, containing the digest of the used hash
- * function, the digest of the PRGN and the names of the
- * corresponding providers
- * @param statByte status byte array
- * @param statInt status int array
- */
- public GMSSRootSig(Digest digest, byte[][] statByte, int[] statInt)
- {
- messDigestOTS = digest;
- gmssRandom = new GMSSRandom(messDigestOTS);
-
- this.counter = statInt[0];
- this.test = statInt[1];
- this.ii = statInt[2];
- this.r = statInt[3];
- this.steps = statInt[4];
- this.keysize = statInt[5];
- this.height = statInt[6];
- this.w = statInt[7];
- this.checksum = statInt[8];
-
- this.mdsize = messDigestOTS.getDigestSize();
-
- this.k = (1 << w) - 1;
-
- int mdsizeBit = mdsize << 3;
- this.messagesize = (int)Math.ceil((double)(mdsizeBit) / (double)w);
-
- this.privateKeyOTS = statByte[0];
- this.seed = statByte[1];
- this.hash = statByte[2];
-
- this.sign = statByte[3];
-
- this.test8 = ((statByte[4][0] & 0xff))
- | ((long)(statByte[4][1] & 0xff) << 8)
- | ((long)(statByte[4][2] & 0xff) << 16)
- | ((long)(statByte[4][3] & 0xff)) << 24
- | ((long)(statByte[4][4] & 0xff)) << 32
- | ((long)(statByte[4][5] & 0xff)) << 40
- | ((long)(statByte[4][6] & 0xff)) << 48
- | ((long)(statByte[4][7] & 0xff)) << 56;
-
- this.big8 = ((statByte[4][8] & 0xff))
- | ((long)(statByte[4][9] & 0xff) << 8)
- | ((long)(statByte[4][10] & 0xff) << 16)
- | ((long)(statByte[4][11] & 0xff)) << 24
- | ((long)(statByte[4][12] & 0xff)) << 32
- | ((long)(statByte[4][13] & 0xff)) << 40
- | ((long)(statByte[4][14] & 0xff)) << 48
- | ((long)(statByte[4][15] & 0xff)) << 56;
- }
-
- /**
- * The constructor generates the PRNG and initializes some variables
- *
- * @param digest an array of strings, containing the digest of the used hash
- * function, the digest of the PRGN and the names of the
- * corresponding providers
- * @param w the winternitz parameter
- * @param height the heigth of the tree
- */
- public GMSSRootSig(Digest digest, int w, int height)
- {
- messDigestOTS = digest;
- gmssRandom = new GMSSRandom(messDigestOTS);
-
- this.mdsize = messDigestOTS.getDigestSize();
- this.w = w;
- this.height = height;
-
- this.k = (1 << w) - 1;
-
- int mdsizeBit = mdsize << 3;
- this.messagesize = (int)Math.ceil((double)(mdsizeBit) / (double)w);
- }
-
- /**
- * This method initializes the distributed sigature calculation. Variables
- * are reseted and necessary steps are calculated
- *
- * @param seed0 the initial OTSseed
- * @param message the massage which will be signed
- */
- public void initSign(byte[] seed0, byte[] message)
- {
-
- // create hash of message m
- this.hash = new byte[mdsize];
- messDigestOTS.update(message, 0, message.length);
- this.hash = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(this.hash, 0);
-
- // variables for calculation of steps
- byte[] messPart = new byte[mdsize];
- System.arraycopy(hash, 0, messPart, 0, mdsize);
- int checkPart = 0;
- int sumH = 0;
- int checksumsize = getLog((messagesize << w) + 1);
-
- // ------- calculation of necessary steps ------
- if (8 % w == 0)
- {
- int dt = 8 / w;
- // message part
- for (int a = 0; a < mdsize; a++)
- {
- // count necessary hashs in 'sumH'
- for (int b = 0; b < dt; b++)
- {
- sumH += messPart[a] & k;
- messPart[a] = (byte)(messPart[a] >>> w);
- }
- }
- // checksum part
- this.checksum = (messagesize << w) - sumH;
- checkPart = checksum;
- // count necessary hashs in 'sumH'
- for (int b = 0; b < checksumsize; b += w)
- {
- sumH += checkPart & k;
- checkPart >>>= w;
- }
- } // end if ( 8 % w == 0 )
- else if (w < 8)
- {
- long big8;
- int ii = 0;
- int dt = mdsize / w;
-
- // first d*w bytes of hash (main message part)
- for (int i = 0; i < dt; i++)
- {
- big8 = 0;
- for (int j = 0; j < w; j++)
- {
- big8 ^= (messPart[ii] & 0xff) << (j << 3);
- ii++;
- }
- // count necessary hashs in 'sumH'
- for (int j = 0; j < 8; j++)
- {
- sumH += (int)(big8 & k);
- big8 >>>= w;
- }
- }
- // rest of message part
- dt = mdsize % w;
- big8 = 0;
- for (int j = 0; j < dt; j++)
- {
- big8 ^= (messPart[ii] & 0xff) << (j << 3);
- ii++;
- }
- dt <<= 3;
- // count necessary hashs in 'sumH'
- for (int j = 0; j < dt; j += w)
- {
- sumH += (int)(big8 & k);
- big8 >>>= w;
- }
- // checksum part
- this.checksum = (messagesize << w) - sumH;
- checkPart = checksum;
- // count necessary hashs in 'sumH'
- for (int i = 0; i < checksumsize; i += w)
- {
- sumH += checkPart & k;
- checkPart >>>= w;
- }
- }// end if(w<8)
- else if (w < 57)
- {
- long big8;
- int r = 0;
- int s, f, rest, ii;
-
- // first a*w bits of hash where a*w <= 8*mdsize < (a+1)*w (main
- // message part)
- while (r <= ((mdsize << 3) - w))
- {
- s = r >>> 3;
- rest = r % 8;
- r += w;
- f = (r + 7) >>> 3;
- big8 = 0;
- ii = 0;
- for (int j = s; j < f; j++)
- {
- big8 ^= (messPart[j] & 0xff) << (ii << 3);
- ii++;
- }
- big8 >>>= rest;
- // count necessary hashs in 'sumH'
- sumH += (big8 & k);
-
- }
- // rest of message part
- s = r >>> 3;
- if (s < mdsize)
- {
- rest = r % 8;
- big8 = 0;
- ii = 0;
- for (int j = s; j < mdsize; j++)
- {
- big8 ^= (messPart[j] & 0xff) << (ii << 3);
- ii++;
- }
-
- big8 >>>= rest;
- // count necessary hashs in 'sumH'
- sumH += (big8 & k);
- }
- // checksum part
- this.checksum = (messagesize << w) - sumH;
- checkPart = checksum;
- // count necessary hashs in 'sumH'
- for (int i = 0; i < checksumsize; i += w)
- {
- sumH += (checkPart & k);
- checkPart >>>= w;
- }
- }// end if(w<57)
-
- // calculate keysize
- this.keysize = messagesize
- + (int)Math.ceil((double)checksumsize / (double)w);
-
- // calculate steps: 'keysize' times PRNG, 'sumH' times hashing,
- // (1<<height)-1 updateSign() calls
- this.steps = (int)Math.ceil((double)(keysize + sumH)
- / (double)((1 << height)));
- // ----------------------------
-
- // reset variables
- this.sign = new byte[keysize * mdsize];
- this.counter = 0;
- this.test = 0;
- this.ii = 0;
- this.test8 = 0;
- this.r = 0;
- // define the private key messagesize
- this.privateKeyOTS = new byte[mdsize];
- // copy the seed
- this.seed = new byte[mdsize];
- System.arraycopy(seed0, 0, this.seed, 0, mdsize);
-
- }
-
- /**
- * This Method performs <code>steps</code> steps of distributed signature
- * calculaion
- *
- * @return true if signature is generated completly, else false
- */
- public boolean updateSign()
- {
- // steps times do
-
- for (int s = 0; s < steps; s++)
- { // do 'step' times
-
- if (counter < keysize)
- { // generate the private key or perform
- // the next hash
- oneStep();
- }
- if (counter == keysize)
- {// finish
- return true;
- }
- }
-
- return false; // leaf not finished yet
- }
-
- /**
- * @return The private OTS key
- */
- public byte[] getSig()
- {
-
- return sign;
- }
-
- /**
- * @return The one-time signature of the message, generated step by step
- */
- private void oneStep()
- {
- // -------- if (8 % w == 0) ----------
- if (8 % w == 0)
- {
- if (test == 0)
- {
- // get current OTSprivateKey
- this.privateKeyOTS = gmssRandom.nextSeed(seed);
- // System.arraycopy(privateKeyOTS, 0, hlp, 0, mdsize);
-
- if (ii < mdsize)
- { // for main message part
- test = hash[ii] & k;
- hash[ii] = (byte)(hash[ii] >>> w);
- }
- else
- { // for checksum part
- test = checksum & k;
- checksum >>>= w;
- }
- }
- else if (test > 0)
- { // hash the private Key 'test' times (on
- // time each step)
- messDigestOTS.update(privateKeyOTS, 0, privateKeyOTS.length);
- privateKeyOTS = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(privateKeyOTS, 0);
- test--;
- }
- if (test == 0)
- { // if all hashes done copy result to siganture
- // array
- System.arraycopy(privateKeyOTS, 0, sign, counter * mdsize,
- mdsize);
- counter++;
-
- if (counter % (8 / w) == 0)
- { // raise array index for main
- // massage part
- ii++;
- }
- }
-
- }// ----- end if (8 % w == 0) -----
- // ---------- if ( w < 8 ) ----------------
- else if (w < 8)
- {
-
- if (test == 0)
- {
- if (counter % 8 == 0 && ii < mdsize)
- { // after every 8th "add
- // to signature"-step
- big8 = 0;
- if (counter < ((mdsize / w) << 3))
- {// main massage
- // (generate w*8 Bits
- // every time) part
- for (int j = 0; j < w; j++)
- {
- big8 ^= (hash[ii] & 0xff) << (j << 3);
- ii++;
- }
- }
- else
- { // rest of massage part (once)
- for (int j = 0; j < mdsize % w; j++)
- {
- big8 ^= (hash[ii] & 0xff) << (j << 3);
- ii++;
- }
- }
- }
- if (counter == messagesize)
- { // checksum part (once)
- big8 = checksum;
- }
-
- test = (int)(big8 & k);
- // generate current OTSprivateKey
- this.privateKeyOTS = gmssRandom.nextSeed(seed);
- // System.arraycopy(privateKeyOTS, 0, hlp, 0, mdsize);
-
- }
- else if (test > 0)
- { // hash the private Key 'test' times (on
- // time each step)
- messDigestOTS.update(privateKeyOTS, 0, privateKeyOTS.length);
- privateKeyOTS = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(privateKeyOTS, 0);
- test--;
- }
- if (test == 0)
- { // if all hashes done copy result to siganture
- // array
- System.arraycopy(privateKeyOTS, 0, sign, counter * mdsize,
- mdsize);
- big8 >>>= w;
- counter++;
- }
-
- }// ------- end if(w<8)--------------------------------
- // --------- if w < 57 -----------------------------
- else if (w < 57)
- {
-
- if (test8 == 0)
- {
- int s, f, rest;
- big8 = 0;
- ii = 0;
- rest = r % 8;
- s = r >>> 3;
- // --- message part---
- if (s < mdsize)
- {
- if (r <= ((mdsize << 3) - w))
- { // first message part
- r += w;
- f = (r + 7) >>> 3;
- }
- else
- { // rest of message part (once)
- f = mdsize;
- r += w;
- }
- // generate long 'big8' with minimum w next bits of the
- // message array
- for (int i = s; i < f; i++)
- {
- big8 ^= (hash[i] & 0xff) << (ii << 3);
- ii++;
- }
- // delete bits on the right side, which were used already by
- // the last loop
- big8 >>>= rest;
- test8 = (big8 & k);
- }
- // --- checksum part
- else
- {
- test8 = (checksum & k);
- checksum >>>= w;
- }
- // generate current OTSprivateKey
- this.privateKeyOTS = gmssRandom.nextSeed(seed);
- // System.arraycopy(privateKeyOTS, 0, hlp, 0, mdsize);
-
- }
- else if (test8 > 0)
- { // hash the private Key 'test' times (on
- // time each step)
- messDigestOTS.update(privateKeyOTS, 0, privateKeyOTS.length);
- privateKeyOTS = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(privateKeyOTS, 0);
- test8--;
- }
- if (test8 == 0)
- { // if all hashes done copy result to siganture
- // array
- System.arraycopy(privateKeyOTS, 0, sign, counter * mdsize,
- mdsize);
- counter++;
- }
-
- }
- }
-
- /**
- * This method returns the least integer that is greater or equal to the
- * logarithm to the base 2 of an integer <code>intValue</code>.
- *
- * @param intValue an integer
- * @return The least integer greater or equal to the logarithm to the base 2
- * of <code>intValue</code>
- */
- public int getLog(int intValue)
- {
- int log = 1;
- int i = 2;
- while (i < intValue)
- {
- i <<= 1;
- log++;
- }
- return log;
- }
-
- /**
- * This method returns the status byte array
- *
- * @return statBytes
- */
- public byte[][] getStatByte()
- {
-
- byte[][] statByte = new byte[5][mdsize];
- statByte[0] = privateKeyOTS;
- statByte[1] = seed;
- statByte[2] = hash;
- statByte[3] = sign;
- statByte[4] = this.getStatLong();
-
- return statByte;
- }
-
- /**
- * This method returns the status int array
- *
- * @return statInt
- */
- public int[] getStatInt()
- {
- int[] statInt = new int[9];
- statInt[0] = counter;
- statInt[1] = test;
- statInt[2] = ii;
- statInt[3] = r;
- statInt[4] = steps;
- statInt[5] = keysize;
- statInt[6] = height;
- statInt[7] = w;
- statInt[8] = checksum;
- return statInt;
- }
-
- /**
- * Converts the long parameters into byte arrays to store it in
- * statByte-Array
- */
- public byte[] getStatLong()
- {
- byte[] bytes = new byte[16];
-
- bytes[0] = (byte)((test8) & 0xff);
- bytes[1] = (byte)((test8 >> 8) & 0xff);
- bytes[2] = (byte)((test8 >> 16) & 0xff);
- bytes[3] = (byte)((test8 >> 24) & 0xff);
- bytes[4] = (byte)((test8) >> 32 & 0xff);
- bytes[5] = (byte)((test8 >> 40) & 0xff);
- bytes[6] = (byte)((test8 >> 48) & 0xff);
- bytes[7] = (byte)((test8 >> 56) & 0xff);
-
- bytes[8] = (byte)((big8) & 0xff);
- bytes[9] = (byte)((big8 >> 8) & 0xff);
- bytes[10] = (byte)((big8 >> 16) & 0xff);
- bytes[11] = (byte)((big8 >> 24) & 0xff);
- bytes[12] = (byte)((big8) >> 32 & 0xff);
- bytes[13] = (byte)((big8 >> 40) & 0xff);
- bytes[14] = (byte)((big8 >> 48) & 0xff);
- bytes[15] = (byte)((big8 >> 56) & 0xff);
-
- return bytes;
- }
-
- /**
- * returns a string representation of the instance
- *
- * @return a string representation of the instance
- */
- public String toString()
- {
- String out = "" + this.big8 + " ";
- int[] statInt = new int[9];
- statInt = this.getStatInt();
- byte[][] statByte = new byte[5][mdsize];
- statByte = this.getStatByte();
- for (int i = 0; i < 9; i++)
- {
- out = out + statInt[i] + " ";
- }
- for (int i = 0; i < 5; i++)
- {
- out = out + new String(Hex.encode(statByte[i])) + " ";
- }
-
- return out;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSSigner.java b/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSSigner.java
deleted file mode 100644
index 8832fb34..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSSigner.java
+++ /dev/null
@@ -1,403 +0,0 @@
-package org.bouncycastle.pqc.crypto.gmss;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.pqc.crypto.MessageSigner;
-import org.bouncycastle.pqc.crypto.gmss.util.GMSSRandom;
-import org.bouncycastle.pqc.crypto.gmss.util.GMSSUtil;
-import org.bouncycastle.pqc.crypto.gmss.util.WinternitzOTSVerify;
-import org.bouncycastle.pqc.crypto.gmss.util.WinternitzOTSignature;
-import org.bouncycastle.util.Arrays;
-
-/**
- * This class implements the GMSS signature scheme.
- */
-public class GMSSSigner
- implements MessageSigner
-{
-
- /**
- * Instance of GMSSParameterSpec
- */
- //private GMSSParameterSpec gmssParameterSpec;
-
- /**
- * Instance of GMSSUtilities
- */
- private GMSSUtil gmssUtil = new GMSSUtil();
-
-
- /**
- * The raw GMSS public key
- */
- private byte[] pubKeyBytes;
-
- /**
- * Hash function for the construction of the authentication trees
- */
- private Digest messDigestTrees;
-
- /**
- * The length of the hash function output
- */
- private int mdLength;
-
- /**
- * The number of tree layers
- */
- private int numLayer;
-
- /**
- * The hash function used by the OTS
- */
- private Digest messDigestOTS;
-
- /**
- * An instance of the Winternitz one-time signature
- */
- private WinternitzOTSignature ots;
-
- /**
- * Array of strings containing the name of the hash function used by the OTS
- * and the corresponding provider name
- */
- private GMSSDigestProvider digestProvider;
-
- /**
- * The current main tree and subtree indices
- */
- private int[] index;
-
- /**
- * Array of the authentication paths for the current trees of all layers
- */
- private byte[][][] currentAuthPaths;
-
- /**
- * The one-time signature of the roots of the current subtrees
- */
- private byte[][] subtreeRootSig;
-
-
- /**
- * The GMSSParameterset
- */
- private GMSSParameters gmssPS;
-
- /**
- * The PRNG
- */
- private GMSSRandom gmssRandom;
-
- GMSSKeyParameters key;
-
- // XXX needed? Source of randomness
- private SecureRandom random;
-
-
- /**
- * The standard constructor tries to generate the MerkleTree Algorithm
- * identifier with the corresponding OID.
- *
- * @param digest the digest to use
- */
- // TODO
- public GMSSSigner(GMSSDigestProvider digest)
- {
- digestProvider = digest;
- messDigestTrees = digest.get();
- messDigestOTS = messDigestTrees;
- mdLength = messDigestTrees.getDigestSize();
- gmssRandom = new GMSSRandom(messDigestTrees);
- }
-
- public void init(boolean forSigning,
- CipherParameters param)
- {
-
- if (forSigning)
- {
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- // XXX random needed?
- this.random = rParam.getRandom();
- this.key = (GMSSPrivateKeyParameters)rParam.getParameters();
- initSign();
-
- }
- else
- {
-
- this.random = new SecureRandom();
- this.key = (GMSSPrivateKeyParameters)param;
- initSign();
- }
- }
- else
- {
- this.key = (GMSSPublicKeyParameters)param;
- initVerify();
-
- }
-
- }
-
-
- /**
- * Initializes the signature algorithm for signing a message.
- */
- private void initSign()
- {
- messDigestTrees.reset();
- // set private key and take from it ots key, auth, tree and key
- // counter, rootSign
- GMSSPrivateKeyParameters gmssPrivateKey = (GMSSPrivateKeyParameters)key;
-
- if (gmssPrivateKey.isUsed())
- {
- throw new IllegalStateException("Private key already used");
- }
-
- // check if last signature has been generated
- if (gmssPrivateKey.getIndex(0) >= gmssPrivateKey.getNumLeafs(0))
- {
- throw new IllegalStateException("No more signatures can be generated");
- }
-
- // get Parameterset
- this.gmssPS = gmssPrivateKey.getParameters();
- // get numLayer
- this.numLayer = gmssPS.getNumOfLayers();
-
- // get OTS Instance of lowest layer
- byte[] seed = gmssPrivateKey.getCurrentSeeds()[numLayer - 1];
- byte[] OTSSeed = new byte[mdLength];
- byte[] dummy = new byte[mdLength];
- System.arraycopy(seed, 0, dummy, 0, mdLength);
- OTSSeed = gmssRandom.nextSeed(dummy); // secureRandom.nextBytes(currentSeeds[currentSeeds.length-1]);secureRandom.nextBytes(OTSseed);
- this.ots = new WinternitzOTSignature(OTSSeed, digestProvider.get(), gmssPS.getWinternitzParameter()[numLayer - 1]);
-
- byte[][][] helpCurrentAuthPaths = gmssPrivateKey.getCurrentAuthPaths();
- currentAuthPaths = new byte[numLayer][][];
-
- // copy the main tree authentication path
- for (int j = 0; j < numLayer; j++)
- {
- currentAuthPaths[j] = new byte[helpCurrentAuthPaths[j].length][mdLength];
- for (int i = 0; i < helpCurrentAuthPaths[j].length; i++)
- {
- System.arraycopy(helpCurrentAuthPaths[j][i], 0, currentAuthPaths[j][i], 0, mdLength);
- }
- }
-
- // copy index
- index = new int[numLayer];
- System.arraycopy(gmssPrivateKey.getIndex(), 0, index, 0, numLayer);
-
- // copy subtreeRootSig
- byte[] helpSubtreeRootSig;
- subtreeRootSig = new byte[numLayer - 1][];
- for (int i = 0; i < numLayer - 1; i++)
- {
- helpSubtreeRootSig = gmssPrivateKey.getSubtreeRootSig(i);
- subtreeRootSig[i] = new byte[helpSubtreeRootSig.length];
- System.arraycopy(helpSubtreeRootSig, 0, subtreeRootSig[i], 0, helpSubtreeRootSig.length);
- }
-
- gmssPrivateKey.markUsed();
- }
-
- /**
- * Signs a message.
- *
- * @return the signature.
- */
- public byte[] generateSignature(byte[] message)
- {
-
- byte[] otsSig = new byte[mdLength];
- byte[] authPathBytes;
- byte[] indexBytes;
-
- otsSig = ots.getSignature(message);
-
- // get concatenated lowest layer tree authentication path
- authPathBytes = gmssUtil.concatenateArray(currentAuthPaths[numLayer - 1]);
-
- // put lowest layer index into a byte array
- indexBytes = gmssUtil.intToBytesLittleEndian(index[numLayer - 1]);
-
- // create first part of GMSS signature
- byte[] gmssSigFirstPart = new byte[indexBytes.length + otsSig.length + authPathBytes.length];
- System.arraycopy(indexBytes, 0, gmssSigFirstPart, 0, indexBytes.length);
- System.arraycopy(otsSig, 0, gmssSigFirstPart, indexBytes.length, otsSig.length);
- System.arraycopy(authPathBytes, 0, gmssSigFirstPart, (indexBytes.length + otsSig.length), authPathBytes.length);
- // --- end first part
-
- // --- next parts of the signature
- // create initial array with length 0 for iteration
- byte[] gmssSigNextPart = new byte[0];
-
- for (int i = numLayer - 1 - 1; i >= 0; i--)
- {
-
- // get concatenated next tree authentication path
- authPathBytes = gmssUtil.concatenateArray(currentAuthPaths[i]);
-
- // put next tree index into a byte array
- indexBytes = gmssUtil.intToBytesLittleEndian(index[i]);
-
- // create next part of GMSS signature
-
- // create help array and copy actual gmssSig into it
- byte[] helpGmssSig = new byte[gmssSigNextPart.length];
- System.arraycopy(gmssSigNextPart, 0, helpGmssSig, 0, gmssSigNextPart.length);
- // adjust length of gmssSigNextPart for adding next part
- gmssSigNextPart = new byte[helpGmssSig.length + indexBytes.length + subtreeRootSig[i].length + authPathBytes.length];
-
- // copy old data (help array) and new data in gmssSigNextPart
- System.arraycopy(helpGmssSig, 0, gmssSigNextPart, 0, helpGmssSig.length);
- System.arraycopy(indexBytes, 0, gmssSigNextPart, helpGmssSig.length, indexBytes.length);
- System.arraycopy(subtreeRootSig[i], 0, gmssSigNextPart, (helpGmssSig.length + indexBytes.length), subtreeRootSig[i].length);
- System.arraycopy(authPathBytes, 0, gmssSigNextPart, (helpGmssSig.length + indexBytes.length + subtreeRootSig[i].length), authPathBytes.length);
-
- }
- // --- end next parts
-
- // concatenate the two parts of the GMSS signature
- byte[] gmssSig = new byte[gmssSigFirstPart.length + gmssSigNextPart.length];
- System.arraycopy(gmssSigFirstPart, 0, gmssSig, 0, gmssSigFirstPart.length);
- System.arraycopy(gmssSigNextPart, 0, gmssSig, gmssSigFirstPart.length, gmssSigNextPart.length);
-
- // return the GMSS signature
- return gmssSig;
- }
-
- /**
- * Initializes the signature algorithm for verifying a signature.
- */
- private void initVerify()
- {
- messDigestTrees.reset();
-
- GMSSPublicKeyParameters gmssPublicKey = (GMSSPublicKeyParameters)key;
- pubKeyBytes = gmssPublicKey.getPublicKey();
- gmssPS = gmssPublicKey.getParameters();
- // get numLayer
- this.numLayer = gmssPS.getNumOfLayers();
-
-
- }
-
- /**
- * This function verifies the signature of the message that has been
- * updated, with the aid of the public key.
- *
- * @param message the message
- * @param signature the signature associated with the message
- * @return true if the signature has been verified, false otherwise.
- */
- public boolean verifySignature(byte[] message, byte[] signature)
- {
-
- boolean success = false;
- // int halfSigLength = signature.length >>> 1;
- messDigestOTS.reset();
- WinternitzOTSVerify otsVerify;
- int otsSigLength;
-
- byte[] help = message;
-
- byte[] otsSig;
- byte[] otsPublicKey;
- byte[][] authPath;
- byte[] dest;
- int nextEntry = 0;
- int index;
- // Verify signature
-
- // --- begin with message = 'message that was signed'
- // and then in each step message = subtree root
- for (int j = numLayer - 1; j >= 0; j--)
- {
- otsVerify = new WinternitzOTSVerify(digestProvider.get(), gmssPS.getWinternitzParameter()[j]);
- otsSigLength = otsVerify.getSignatureLength();
-
- message = help;
- // get the subtree index
- index = gmssUtil.bytesToIntLittleEndian(signature, nextEntry);
-
- // 4 is the number of bytes in integer
- nextEntry += 4;
-
- // get one-time signature
- otsSig = new byte[otsSigLength];
- System.arraycopy(signature, nextEntry, otsSig, 0, otsSigLength);
- nextEntry += otsSigLength;
-
- // compute public OTS key from the one-time signature
- otsPublicKey = otsVerify.Verify(message, otsSig);
-
- // test if OTSsignature is correct
- if (otsPublicKey == null)
- {
- System.err.println("OTS Public Key is null in GMSSSignature.verify");
- return false;
- }
-
- // get authentication path from the signature
- authPath = new byte[gmssPS.getHeightOfTrees()[j]][mdLength];
- for (int i = 0; i < authPath.length; i++)
- {
- System.arraycopy(signature, nextEntry, authPath[i], 0, mdLength);
- nextEntry = nextEntry + mdLength;
- }
-
- // compute the root of the subtree from the authentication path
- help = new byte[mdLength];
-
- help = otsPublicKey;
-
- int count = 1 << authPath.length;
- count = count + index;
-
- for (int i = 0; i < authPath.length; i++)
- {
- dest = new byte[mdLength << 1];
-
- if ((count % 2) == 0)
- {
- System.arraycopy(help, 0, dest, 0, mdLength);
- System.arraycopy(authPath[i], 0, dest, mdLength, mdLength);
- count = count / 2;
- }
- else
- {
- System.arraycopy(authPath[i], 0, dest, 0, mdLength);
- System.arraycopy(help, 0, dest, mdLength, help.length);
- count = (count - 1) / 2;
- }
- messDigestTrees.update(dest, 0, dest.length);
- help = new byte[messDigestTrees.getDigestSize()];
- messDigestTrees.doFinal(help, 0);
- }
- }
-
- // now help contains the root of the maintree
-
- // test if help is equal to the GMSS public key
- if (Arrays.areEqual(pubKeyBytes, help))
- {
- success = true;
- }
-
- return success;
- }
-
-
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSUtils.java b/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSUtils.java
deleted file mode 100644
index 9d289513..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/GMSSUtils.java
+++ /dev/null
@@ -1,145 +0,0 @@
-package org.bouncycastle.pqc.crypto.gmss;
-
-import java.util.Enumeration;
-import java.util.Vector;
-
-import org.bouncycastle.util.Arrays;
-
-class GMSSUtils
-{
- static GMSSLeaf[] clone(GMSSLeaf[] data)
- {
- if (data == null)
- {
- return null;
- }
- GMSSLeaf[] copy = new GMSSLeaf[data.length];
-
- System.arraycopy(data, 0, copy, 0, data.length);
-
- return copy;
- }
-
- static GMSSRootCalc[] clone(GMSSRootCalc[] data)
- {
- if (data == null)
- {
- return null;
- }
- GMSSRootCalc[] copy = new GMSSRootCalc[data.length];
-
- System.arraycopy(data, 0, copy, 0, data.length);
-
- return copy;
- }
-
- static GMSSRootSig[] clone(GMSSRootSig[] data)
- {
- if (data == null)
- {
- return null;
- }
- GMSSRootSig[] copy = new GMSSRootSig[data.length];
-
- System.arraycopy(data, 0, copy, 0, data.length);
-
- return copy;
- }
-
- static byte[][] clone(byte[][] data)
- {
- if (data == null)
- {
- return null;
- }
- byte[][] copy = new byte[data.length][];
-
- for (int i = 0; i != data.length; i++)
- {
- copy[i] = Arrays.clone(data[i]);
- }
-
- return copy;
- }
-
- static byte[][][] clone(byte[][][] data)
- {
- if (data == null)
- {
- return null;
- }
- byte[][][] copy = new byte[data.length][][];
-
- for (int i = 0; i != data.length; i++)
- {
- copy[i] = clone(data[i]);
- }
-
- return copy;
- }
-
- static Treehash[] clone(Treehash[] data)
- {
- if (data == null)
- {
- return null;
- }
- Treehash[] copy = new Treehash[data.length];
-
- System.arraycopy(data, 0, copy, 0, data.length);
-
- return copy;
- }
-
- static Treehash[][] clone(Treehash[][] data)
- {
- if (data == null)
- {
- return null;
- }
- Treehash[][] copy = new Treehash[data.length][];
-
- for (int i = 0; i != data.length; i++)
- {
- copy[i] = clone(data[i]);
- }
-
- return copy;
- }
-
- static Vector[] clone(Vector[] data)
- {
- if (data == null)
- {
- return null;
- }
- Vector[] copy = new Vector[data.length];
-
- for (int i = 0; i != data.length; i++)
- {
- copy[i] = new Vector();
- for (Enumeration en = data[i].elements(); en.hasMoreElements();)
- {
- copy[i].addElement(en.nextElement());
- }
- }
-
- return copy;
- }
-
- static Vector[][] clone(Vector[][] data)
- {
- if (data == null)
- {
- return null;
- }
- Vector[][] copy = new Vector[data.length][];
-
- for (int i = 0; i != data.length; i++)
- {
- copy[i] = clone(data[i]);
- }
-
- return copy;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/Treehash.java b/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/Treehash.java
deleted file mode 100644
index 797355cb..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/Treehash.java
+++ /dev/null
@@ -1,525 +0,0 @@
-package org.bouncycastle.pqc.crypto.gmss;
-
-import java.util.Vector;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.pqc.crypto.gmss.util.GMSSRandom;
-import org.bouncycastle.util.Integers;
-import org.bouncycastle.util.encoders.Hex;
-
-
-/**
- * This class implements a treehash instance for the Merkle tree traversal
- * algorithm. The first node of the stack is stored in this instance itself,
- * additional tail nodes are stored on a tailstack.
- */
-public class Treehash
-{
-
- /**
- * max height of current treehash instance.
- */
- private int maxHeight;
-
- /**
- * Vector element that stores the nodes on the stack
- */
- private Vector tailStack;
-
- /**
- * Vector element that stores the height of the nodes on the stack
- */
- private Vector heightOfNodes;
-
- /**
- * the first node is stored in the treehash instance itself, not on stack
- */
- private byte[] firstNode;
-
- /**
- * seedActive needed for the actual node
- */
- private byte[] seedActive;
-
- /**
- * the seed needed for the next re-initialization of the treehash instance
- */
- private byte[] seedNext;
-
- /**
- * number of nodes stored on the stack and belonging to this treehash
- * instance
- */
- private int tailLength;
-
- /**
- * the height in the tree of the first node stored in treehash
- */
- private int firstNodeHeight;
-
- /**
- * true if treehash instance was already initialized, false otherwise
- */
- private boolean isInitialized;
-
- /**
- * true if the first node's height equals the maxHeight of the treehash
- */
- private boolean isFinished;
-
- /**
- * true if the nextSeed has been initialized with index 3*2^h needed for the
- * seed scheduling
- */
- private boolean seedInitialized;
-
- /**
- * denotes the Message Digest used by the tree to create nodes
- */
- private Digest messDigestTree;
-
- /**
- * This constructor regenerates a prior treehash object
- *
- * @param name an array of strings, containing the name of the used hash
- * function and PRNG and the name of the corresponding provider
- * @param statByte status bytes
- * @param statInt status ints
- */
- public Treehash(Digest name, byte[][] statByte, int[] statInt)
- {
- this.messDigestTree = name;
-
- // decode statInt
- this.maxHeight = statInt[0];
- this.tailLength = statInt[1];
- this.firstNodeHeight = statInt[2];
-
- if (statInt[3] == 1)
- {
- this.isFinished = true;
- }
- else
- {
- this.isFinished = false;
- }
- if (statInt[4] == 1)
- {
- this.isInitialized = true;
- }
- else
- {
- this.isInitialized = false;
- }
- if (statInt[5] == 1)
- {
- this.seedInitialized = true;
- }
- else
- {
- this.seedInitialized = false;
- }
-
- this.heightOfNodes = new Vector();
- for (int i = 0; i < tailLength; i++)
- {
- this.heightOfNodes.addElement(Integers.valueOf(statInt[6 + i]));
- }
-
- // decode statByte
- this.firstNode = statByte[0];
- this.seedActive = statByte[1];
- this.seedNext = statByte[2];
-
- this.tailStack = new Vector();
- for (int i = 0; i < tailLength; i++)
- {
- this.tailStack.addElement(statByte[3 + i]);
- }
- }
-
- /**
- * Constructor
- *
- * @param tailStack a vector element where the stack nodes are stored
- * @param maxHeight maximal height of the treehash instance
- * @param digest an array of strings, containing the name of the used hash
- * function and PRNG and the name of the corresponding provider
- */
- public Treehash(Vector tailStack, int maxHeight, Digest digest)
- {
- this.tailStack = tailStack;
- this.maxHeight = maxHeight;
- this.firstNode = null;
- this.isInitialized = false;
- this.isFinished = false;
- this.seedInitialized = false;
- this.messDigestTree = digest;
-
- this.seedNext = new byte[messDigestTree.getDigestSize()];
- this.seedActive = new byte[messDigestTree.getDigestSize()];
- }
-
- /**
- * Method to initialize the seeds needed for the precomputation of right
- * nodes. Should be initialized with index 3*2^i for treehash_i
- *
- * @param seedIn
- */
- public void initializeSeed(byte[] seedIn)
- {
- System.arraycopy(seedIn, 0, this.seedNext, 0, this.messDigestTree
- .getDigestSize());
- this.seedInitialized = true;
- }
-
- /**
- * initializes the treehash instance. The seeds must already have been
- * initialized to work correctly.
- */
- public void initialize()
- {
- if (!this.seedInitialized)
- {
- System.err.println("Seed " + this.maxHeight + " not initialized");
- return;
- }
-
- this.heightOfNodes = new Vector();
- this.tailLength = 0;
- this.firstNode = null;
- this.firstNodeHeight = -1;
- this.isInitialized = true;
- System.arraycopy(this.seedNext, 0, this.seedActive, 0, messDigestTree
- .getDigestSize());
- }
-
- /**
- * Calculates one update of the treehash instance, i.e. creates a new leaf
- * and hashes if possible
- *
- * @param gmssRandom an instance of the PRNG
- * @param leaf The byte value of the leaf needed for the update
- */
- public void update(GMSSRandom gmssRandom, byte[] leaf)
- {
-
- if (this.isFinished)
- {
- System.err
- .println("No more update possible for treehash instance!");
- return;
- }
- if (!this.isInitialized)
- {
- System.err
- .println("Treehash instance not initialized before update");
- return;
- }
-
- byte[] help = new byte[this.messDigestTree.getDigestSize()];
- int helpHeight = -1;
-
- gmssRandom.nextSeed(this.seedActive);
-
- // if treehash gets first update
- if (this.firstNode == null)
- {
- this.firstNode = leaf;
- this.firstNodeHeight = 0;
- }
- else
- {
- // store the new node in help array, do not push it on the stack
- help = leaf;
- helpHeight = 0;
-
- // hash the nodes on the stack if possible
- while (this.tailLength > 0
- && helpHeight == ((Integer)heightOfNodes.lastElement())
- .intValue())
- {
- // put top element of the stack and help node in array
- // 'tobehashed'
- // and hash them together, put result again in help array
- byte[] toBeHashed = new byte[this.messDigestTree
- .getDigestSize() << 1];
-
- // pop element from stack
- System.arraycopy(this.tailStack.lastElement(), 0, toBeHashed,
- 0, this.messDigestTree.getDigestSize());
- this.tailStack.removeElementAt(this.tailStack.size() - 1);
- this.heightOfNodes
- .removeElementAt(this.heightOfNodes.size() - 1);
-
- System.arraycopy(help, 0, toBeHashed, this.messDigestTree
- .getDigestSize(), this.messDigestTree
- .getDigestSize());
- messDigestTree.update(toBeHashed, 0, toBeHashed.length);
- help = new byte[messDigestTree.getDigestSize()];
- messDigestTree.doFinal(help, 0);
-
- // increase help height, stack was reduced by one element
- helpHeight++;
- this.tailLength--;
- }
-
- // push the new node on the stack
- this.tailStack.addElement(help);
- this.heightOfNodes.addElement(Integers.valueOf(helpHeight));
- this.tailLength++;
-
- // finally check whether the top node on stack and the first node
- // in treehash have same height. If so hash them together
- // and store them in treehash
- if (((Integer)heightOfNodes.lastElement()).intValue() == this.firstNodeHeight)
- {
- byte[] toBeHashed = new byte[this.messDigestTree
- .getDigestSize() << 1];
- System.arraycopy(this.firstNode, 0, toBeHashed, 0,
- this.messDigestTree.getDigestSize());
-
- // pop element from tailStack and copy it into help2 array
- System.arraycopy(this.tailStack.lastElement(), 0, toBeHashed,
- this.messDigestTree.getDigestSize(),
- this.messDigestTree.getDigestSize());
- this.tailStack.removeElementAt(this.tailStack.size() - 1);
- this.heightOfNodes
- .removeElementAt(this.heightOfNodes.size() - 1);
-
- // store new element in firstNode, stack is then empty
- messDigestTree.update(toBeHashed, 0, toBeHashed.length);
- this.firstNode = new byte[messDigestTree.getDigestSize()];
- messDigestTree.doFinal(this.firstNode, 0);
- this.firstNodeHeight++;
-
- // empty the stack
- this.tailLength = 0;
- }
- }
-
- // check if treehash instance is completed
- if (this.firstNodeHeight == this.maxHeight)
- {
- this.isFinished = true;
- }
- }
-
- /**
- * Destroys a treehash instance after the top node was taken for
- * authentication path.
- */
- public void destroy()
- {
- this.isInitialized = false;
- this.isFinished = false;
- this.firstNode = null;
- this.tailLength = 0;
- this.firstNodeHeight = -1;
- }
-
- /**
- * Returns the height of the lowest node stored either in treehash or on the
- * stack. It must not be set to infinity (as mentioned in the paper) because
- * this cases are considered in the computeAuthPaths method of
- * JDKGMSSPrivateKey
- *
- * @return Height of the lowest node
- */
- public int getLowestNodeHeight()
- {
- if (this.firstNode == null)
- {
- return this.maxHeight;
- }
- else if (this.tailLength == 0)
- {
- return this.firstNodeHeight;
- }
- else
- {
- return Math.min(this.firstNodeHeight, ((Integer)heightOfNodes
- .lastElement()).intValue());
- }
- }
-
- /**
- * Returns the top node height
- *
- * @return Height of the first node, the top node
- */
- public int getFirstNodeHeight()
- {
- if (firstNode == null)
- {
- return maxHeight;
- }
- return firstNodeHeight;
- }
-
- /**
- * Method to check whether the instance has been initialized or not
- *
- * @return true if treehash was already initialized
- */
- public boolean wasInitialized()
- {
- return this.isInitialized;
- }
-
- /**
- * Method to check whether the instance has been finished or not
- *
- * @return true if treehash has reached its maximum height
- */
- public boolean wasFinished()
- {
- return this.isFinished;
- }
-
- /**
- * returns the first node stored in treehash instance itself
- *
- * @return the first node stored in treehash instance itself
- */
- public byte[] getFirstNode()
- {
- return this.firstNode;
- }
-
- /**
- * returns the active seed
- *
- * @return the active seed
- */
- public byte[] getSeedActive()
- {
- return this.seedActive;
- }
-
- /**
- * This method sets the first node stored in the treehash instance itself
- *
- * @param hash
- */
- public void setFirstNode(byte[] hash)
- {
- if (!this.isInitialized)
- {
- this.initialize();
- }
- this.firstNode = hash;
- this.firstNodeHeight = this.maxHeight;
- this.isFinished = true;
- }
-
- /**
- * updates the nextSeed of this treehash instance one step needed for the
- * schedulng of the seeds
- *
- * @param gmssRandom the prng used for the seeds
- */
- public void updateNextSeed(GMSSRandom gmssRandom)
- {
- gmssRandom.nextSeed(seedNext);
- }
-
- /**
- * Returns the tailstack
- *
- * @return the tailstack
- */
- public Vector getTailStack()
- {
- return this.tailStack;
- }
-
- /**
- * Returns the status byte array used by the GMSSPrivateKeyASN.1 class
- *
- * @return The status bytes
- */
- public byte[][] getStatByte()
- {
-
- byte[][] statByte = new byte[3 + tailLength][this.messDigestTree
- .getDigestSize()];
- statByte[0] = firstNode;
- statByte[1] = seedActive;
- statByte[2] = seedNext;
- for (int i = 0; i < tailLength; i++)
- {
- statByte[3 + i] = (byte[])tailStack.elementAt(i);
- }
- return statByte;
- }
-
- /**
- * Returns the status int array used by the GMSSPrivateKeyASN.1 class
- *
- * @return The status ints
- */
- public int[] getStatInt()
- {
-
- int[] statInt = new int[6 + tailLength];
- statInt[0] = maxHeight;
- statInt[1] = tailLength;
- statInt[2] = firstNodeHeight;
- if (this.isFinished)
- {
- statInt[3] = 1;
- }
- else
- {
- statInt[3] = 0;
- }
- if (this.isInitialized)
- {
- statInt[4] = 1;
- }
- else
- {
- statInt[4] = 0;
- }
- if (this.seedInitialized)
- {
- statInt[5] = 1;
- }
- else
- {
- statInt[5] = 0;
- }
- for (int i = 0; i < tailLength; i++)
- {
- statInt[6 + i] = ((Integer)heightOfNodes.elementAt(i)).intValue();
- }
- return statInt;
- }
-
- /**
- * returns a String representation of the treehash instance
- */
- public String toString()
- {
- String out = "Treehash : ";
- for (int i = 0; i < 6 + tailLength; i++)
- {
- out = out + this.getStatInt()[i] + " ";
- }
- for (int i = 0; i < 3 + tailLength; i++)
- {
- if (this.getStatByte()[i] != null)
- {
- out = out + new String(Hex.encode((this.getStatByte()[i]))) + " ";
- }
- else
- {
- out = out + "null ";
- }
- }
- out = out + " " + this.messDigestTree.getDigestSize();
- return out;
- }
-
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/util/GMSSRandom.java b/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/util/GMSSRandom.java
deleted file mode 100644
index c6d30227..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/util/GMSSRandom.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.bouncycastle.pqc.crypto.gmss.util;
-
-import org.bouncycastle.crypto.Digest;
-
-/**
- * This class provides a PRNG for GMSS
- */
-public class GMSSRandom
-{
- /**
- * Hash function for the construction of the authentication trees
- */
- private Digest messDigestTree;
-
- /**
- * Constructor
- *
- * @param messDigestTree2
- */
- public GMSSRandom(Digest messDigestTree2)
- {
-
- this.messDigestTree = messDigestTree2;
- }
-
- /**
- * computes the next seed value, returns a random byte array and sets
- * outseed to the next value
- *
- * @param outseed byte array in which ((1 + SEEDin +RAND) mod 2^n) will be
- * stored
- * @return byte array of H(SEEDin)
- */
- public byte[] nextSeed(byte[] outseed)
- {
- // RAND <-- H(SEEDin)
- byte[] rand = new byte[outseed.length];
- messDigestTree.update(outseed, 0, outseed.length);
- rand = new byte[messDigestTree.getDigestSize()];
- messDigestTree.doFinal(rand, 0);
-
- // SEEDout <-- (1 + SEEDin +RAND) mod 2^n
- addByteArrays(outseed, rand);
- addOne(outseed);
-
- // System.arraycopy(outseed, 0, outseed, 0, outseed.length);
-
- return rand;
- }
-
- private void addByteArrays(byte[] a, byte[] b)
- {
-
- byte overflow = 0;
- int temp;
-
- for (int i = 0; i < a.length; i++)
- {
- temp = (0xFF & a[i]) + (0xFF & b[i]) + overflow;
- a[i] = (byte)temp;
- overflow = (byte)(temp >> 8);
- }
- }
-
- private void addOne(byte[] a)
- {
-
- byte overflow = 1;
- int temp;
-
- for (int i = 0; i < a.length; i++)
- {
- temp = (0xFF & a[i]) + overflow;
- a[i] = (byte)temp;
- overflow = (byte)(temp >> 8);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/util/GMSSUtil.java b/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/util/GMSSUtil.java
deleted file mode 100644
index 80f8828b..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/util/GMSSUtil.java
+++ /dev/null
@@ -1,151 +0,0 @@
-package org.bouncycastle.pqc.crypto.gmss.util;
-
-/**
- * This class provides several methods that are required by the GMSS classes.
- */
-public class GMSSUtil
-{
- /**
- * Converts a 32 bit integer into a byte array beginning at
- * <code>offset</code> (little-endian representation)
- *
- * @param value the integer to convert
- */
- public byte[] intToBytesLittleEndian(int value)
- {
- byte[] bytes = new byte[4];
-
- bytes[0] = (byte)((value) & 0xff);
- bytes[1] = (byte)((value >> 8) & 0xff);
- bytes[2] = (byte)((value >> 16) & 0xff);
- bytes[3] = (byte)((value >> 24) & 0xff);
- return bytes;
- }
-
- /**
- * Converts a byte array beginning at <code>offset</code> into a 32 bit
- * integer (little-endian representation)
- *
- * @param bytes the byte array
- * @return The resulting integer
- */
- public int bytesToIntLittleEndian(byte[] bytes)
- {
-
- return ((bytes[0] & 0xff)) | ((bytes[1] & 0xff) << 8)
- | ((bytes[2] & 0xff) << 16) | ((bytes[3] & 0xff)) << 24;
- }
-
- /**
- * Converts a byte array beginning at <code>offset</code> into a 32 bit
- * integer (little-endian representation)
- *
- * @param bytes the byte array
- * @param offset the integer offset into the byte array
- * @return The resulting integer
- */
- public int bytesToIntLittleEndian(byte[] bytes, int offset)
- {
- return ((bytes[offset++] & 0xff)) | ((bytes[offset++] & 0xff) << 8)
- | ((bytes[offset++] & 0xff) << 16)
- | ((bytes[offset] & 0xff)) << 24;
- }
-
- /**
- * This method concatenates a 2-dimensional byte array into a 1-dimensional
- * byte array
- *
- * @param arraycp a 2-dimensional byte array.
- * @return 1-dimensional byte array with concatenated input array
- */
- public byte[] concatenateArray(byte[][] arraycp)
- {
- byte[] dest = new byte[arraycp.length * arraycp[0].length];
- int indx = 0;
- for (int i = 0; i < arraycp.length; i++)
- {
- System.arraycopy(arraycp[i], 0, dest, indx, arraycp[i].length);
- indx = indx + arraycp[i].length;
- }
- return dest;
- }
-
- /**
- * This method prints the values of a 2-dimensional byte array
- *
- * @param text a String
- * @param array a 2-dimensional byte array
- */
- public void printArray(String text, byte[][] array)
- {
- System.out.println(text);
- int counter = 0;
- for (int i = 0; i < array.length; i++)
- {
- for (int j = 0; j < array[0].length; j++)
- {
- System.out.println(counter + "; " + array[i][j]);
- counter++;
- }
- }
- }
-
- /**
- * This method prints the values of a 1-dimensional byte array
- *
- * @param text a String
- * @param array a 1-dimensional byte array.
- */
- public void printArray(String text, byte[] array)
- {
- System.out.println(text);
- int counter = 0;
- for (int i = 0; i < array.length; i++)
- {
- System.out.println(counter + "; " + array[i]);
- counter++;
- }
- }
-
- /**
- * This method tests if an integer is a power of 2.
- *
- * @param testValue an integer
- * @return <code>TRUE</code> if <code>testValue</code> is a power of 2,
- * <code>FALSE</code> otherwise
- */
- public boolean testPowerOfTwo(int testValue)
- {
- int a = 1;
- while (a < testValue)
- {
- a <<= 1;
- }
- if (testValue == a)
- {
- return true;
- }
-
- return false;
- }
-
- /**
- * This method returns the least integer that is greater or equal to the
- * logarithm to the base 2 of an integer <code>intValue</code>.
- *
- * @param intValue an integer
- * @return The least integer greater or equal to the logarithm to the base 2
- * of <code>intValue</code>
- */
- public int getLog(int intValue)
- {
- int log = 1;
- int i = 2;
- while (i < intValue)
- {
- i <<= 1;
- log++;
- }
- return log;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/util/WinternitzOTSVerify.java b/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/util/WinternitzOTSVerify.java
deleted file mode 100644
index d012ce7c..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/util/WinternitzOTSVerify.java
+++ /dev/null
@@ -1,344 +0,0 @@
-package org.bouncycastle.pqc.crypto.gmss.util;
-
-import org.bouncycastle.crypto.Digest;
-
-/**
- * This class implements signature verification of the Winternitz one-time
- * signature scheme (OTSS), described in C.Dods, N.P. Smart, and M. Stam, "Hash
- * Based Digital Signature Schemes", LNCS 3796, pages 96&#8211;115, 2005. The
- * class is used by the GMSS classes.
- */
-public class WinternitzOTSVerify
-{
-
- private Digest messDigestOTS;
-
- /**
- * The Winternitz parameter
- */
- private int w;
-
- /**
- * The constructor
- *
- * @param digest the name of the hash function used by the OTS and the provider
- * name of the hash function
- * @param w the Winternitz parameter
- */
- public WinternitzOTSVerify(Digest digest, int w)
- {
- this.w = w;
-
- messDigestOTS = digest;
- }
-
- /**
- * @return The length of the one-time signature
- */
- public int getSignatureLength()
- {
- int mdsize = messDigestOTS.getDigestSize();
- int size = ((mdsize << 3) + (w - 1)) / w;
- int logs = getLog((size << w) + 1);
- size += (logs + w - 1) / w;
-
- return mdsize * size;
- }
-
- /**
- * This method computes the public OTS key from the one-time signature of a
- * message. This is *NOT* a complete OTS signature verification, but it
- * suffices for usage with CMSS.
- *
- * @param message the message
- * @param signature the one-time signature
- * @return The public OTS key
- */
- public byte[] Verify(byte[] message, byte[] signature)
- {
-
- int mdsize = messDigestOTS.getDigestSize();
- byte[] hash = new byte[mdsize]; // hash of message m
-
- // create hash of message m
- messDigestOTS.update(message, 0, message.length);
- hash = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(hash, 0);
-
- int size = ((mdsize << 3) + (w - 1)) / w;
- int logs = getLog((size << w) + 1);
- int keysize = size + (logs + w - 1) / w;
-
- int testKeySize = mdsize * keysize;
-
- if (testKeySize != signature.length)
- {
- return null;
- }
-
- byte[] testKey = new byte[testKeySize];
-
- int c = 0;
- int counter = 0;
- int test;
-
- if (8 % w == 0)
- {
- int d = 8 / w;
- int k = (1 << w) - 1;
- byte[] hlp = new byte[mdsize];
-
- // verify signature
- for (int i = 0; i < hash.length; i++)
- {
- for (int j = 0; j < d; j++)
- {
- test = hash[i] & k;
- c += test;
-
- System.arraycopy(signature, counter * mdsize, hlp, 0, mdsize);
-
- while (test < k)
- {
- messDigestOTS.update(hlp, 0, hlp.length);
- hlp = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(hlp, 0);
- test++;
- }
-
- System.arraycopy(hlp, 0, testKey, counter * mdsize, mdsize);
- hash[i] = (byte)(hash[i] >>> w);
- counter++;
- }
- }
-
- c = (size << w) - c;
- for (int i = 0; i < logs; i += w)
- {
- test = c & k;
-
- System.arraycopy(signature, counter * mdsize, hlp, 0, mdsize);
-
- while (test < k)
- {
- messDigestOTS.update(hlp, 0, hlp.length);
- hlp = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(hlp, 0);
- test++;
- }
- System.arraycopy(hlp, 0, testKey, counter * mdsize, mdsize);
- c >>>= w;
- counter++;
- }
- }
- else if (w < 8)
- {
- int d = mdsize / w;
- int k = (1 << w) - 1;
- byte[] hlp = new byte[mdsize];
- long big8;
- int ii = 0;
- // create signature
- // first d*w bytes of hash
- for (int i = 0; i < d; i++)
- {
- big8 = 0;
- for (int j = 0; j < w; j++)
- {
- big8 ^= (hash[ii] & 0xff) << (j << 3);
- ii++;
- }
- for (int j = 0; j < 8; j++)
- {
- test = (int)(big8 & k);
- c += test;
-
- System.arraycopy(signature, counter * mdsize, hlp, 0, mdsize);
-
- while (test < k)
- {
- messDigestOTS.update(hlp, 0, hlp.length);
- hlp = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(hlp, 0);
- test++;
- }
-
- System.arraycopy(hlp, 0, testKey, counter * mdsize, mdsize);
- big8 >>>= w;
- counter++;
- }
- }
- // rest of hash
- d = mdsize % w;
- big8 = 0;
- for (int j = 0; j < d; j++)
- {
- big8 ^= (hash[ii] & 0xff) << (j << 3);
- ii++;
- }
- d <<= 3;
- for (int j = 0; j < d; j += w)
- {
- test = (int)(big8 & k);
- c += test;
-
- System.arraycopy(signature, counter * mdsize, hlp, 0, mdsize);
-
- while (test < k)
- {
- messDigestOTS.update(hlp, 0, hlp.length);
- hlp = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(hlp, 0);
- test++;
- }
-
- System.arraycopy(hlp, 0, testKey, counter * mdsize, mdsize);
- big8 >>>= w;
- counter++;
- }
-
- // check bytes
- c = (size << w) - c;
- for (int i = 0; i < logs; i += w)
- {
- test = c & k;
-
- System.arraycopy(signature, counter * mdsize, hlp, 0, mdsize);
-
- while (test < k)
- {
- messDigestOTS.update(hlp, 0, hlp.length);
- hlp = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(hlp, 0);
- test++;
- }
-
- System.arraycopy(hlp, 0, testKey, counter * mdsize, mdsize);
- c >>>= w;
- counter++;
- }
- }// end if(w<8)
- else if (w < 57)
- {
- int d = (mdsize << 3) - w;
- int k = (1 << w) - 1;
- byte[] hlp = new byte[mdsize];
- long big8, test8;
- int r = 0;
- int s, f, rest, ii;
- // create signature
- // first a*w bits of hash where a*w <= 8*mdsize < (a+1)*w
- while (r <= d)
- {
- s = r >>> 3;
- rest = r % 8;
- r += w;
- f = (r + 7) >>> 3;
- big8 = 0;
- ii = 0;
- for (int j = s; j < f; j++)
- {
- big8 ^= (hash[j] & 0xff) << (ii << 3);
- ii++;
- }
-
- big8 >>>= rest;
- test8 = (big8 & k);
- c += test8;
-
- System.arraycopy(signature, counter * mdsize, hlp, 0, mdsize);
-
- while (test8 < k)
- {
- messDigestOTS.update(hlp, 0, hlp.length);
- hlp = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(hlp, 0);
- test8++;
- }
-
- System.arraycopy(hlp, 0, testKey, counter * mdsize, mdsize);
- counter++;
-
- }
- // rest of hash
- s = r >>> 3;
- if (s < mdsize)
- {
- rest = r % 8;
- big8 = 0;
- ii = 0;
- for (int j = s; j < mdsize; j++)
- {
- big8 ^= (hash[j] & 0xff) << (ii << 3);
- ii++;
- }
-
- big8 >>>= rest;
- test8 = (big8 & k);
- c += test8;
-
- System.arraycopy(signature, counter * mdsize, hlp, 0, mdsize);
-
- while (test8 < k)
- {
- messDigestOTS.update(hlp, 0, hlp.length);
- hlp = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(hlp, 0);
- test8++;
- }
-
- System.arraycopy(hlp, 0, testKey, counter * mdsize, mdsize);
- counter++;
- }
- // check bytes
- c = (size << w) - c;
- for (int i = 0; i < logs; i += w)
- {
- test8 = (c & k);
-
- System.arraycopy(signature, counter * mdsize, hlp, 0, mdsize);
-
- while (test8 < k)
- {
- messDigestOTS.update(hlp, 0, hlp.length);
- hlp = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(hlp, 0);
- test8++;
- }
-
- System.arraycopy(hlp, 0, testKey, counter * mdsize, mdsize);
- c >>>= w;
- counter++;
- }
- }// end if(w<57)
-
- byte[] TKey = new byte[mdsize];
- messDigestOTS.update(testKey, 0, testKey.length);
- TKey = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(TKey, 0);
-
- return TKey;
-
- }
-
- /**
- * This method returns the least integer that is greater or equal to the
- * logarithm to the base 2 of an integer <code>intValue</code>.
- *
- * @param intValue an integer
- * @return The least integer greater or equal to the logarithm to the base
- * 256 of <code>intValue</code>
- */
- public int getLog(int intValue)
- {
- int log = 1;
- int i = 2;
- while (i < intValue)
- {
- i <<= 1;
- log++;
- }
- return log;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/util/WinternitzOTSignature.java b/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/util/WinternitzOTSignature.java
deleted file mode 100644
index 23bf3fab..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/gmss/util/WinternitzOTSignature.java
+++ /dev/null
@@ -1,404 +0,0 @@
-package org.bouncycastle.pqc.crypto.gmss.util;
-
-import org.bouncycastle.crypto.Digest;
-
-/**
- * This class implements key pair generation and signature generation of the
- * Winternitz one-time signature scheme (OTSS), described in C.Dods, N.P. Smart,
- * and M. Stam, "Hash Based Digital Signature Schemes", LNCS 3796, pages
- * 96&#8211;115, 2005. The class is used by the GMSS classes.
- */
-
-public class WinternitzOTSignature
-{
-
- /**
- * The hash function used by the OTS
- */
- private Digest messDigestOTS;
-
- /**
- * The length of the message digest and private key
- */
- private int mdsize, keysize;
-
- /**
- * An array of strings, containing the name of the used hash function, the
- * name of the PRGN and the names of the corresponding providers
- */
- // private String[] name = new String[2];
- /**
- * The private key
- */
- private byte[][] privateKeyOTS;
-
- /**
- * The Winternitz parameter
- */
- private int w;
-
- /**
- * The source of randomness for OTS private key generation
- */
- private GMSSRandom gmssRandom;
-
- /**
- * Sizes of the message and the checksum, both
- */
- private int messagesize, checksumsize;
-
- /**
- * The constructor generates an OTS key pair, using <code>seed0</code> and
- * the PRNG
- *
- * @param seed0 the seed for the PRGN
- * @param digest an array of strings, containing the name of the used hash
- * function, the name of the PRGN and the names of the
- * corresponding providers
- * @param w the Winternitz parameter
- */
- public WinternitzOTSignature(byte[] seed0, Digest digest, int w)
- {
- // this.name = name;
- this.w = w;
-
- messDigestOTS = digest;
-
- gmssRandom = new GMSSRandom(messDigestOTS);
-
- // calulate keysize for private and public key and also the help
- // array
-
- mdsize = messDigestOTS.getDigestSize();
- int mdsizeBit = mdsize << 3;
- messagesize = (int)Math.ceil((double)(mdsizeBit) / (double)w);
-
- checksumsize = getLog((messagesize << w) + 1);
-
- keysize = messagesize
- + (int)Math.ceil((double)checksumsize / (double)w);
-
- /*
- * mdsize = messDigestOTS.getDigestLength(); messagesize =
- * ((mdsize<<3)+(w-1))/w;
- *
- * checksumsize = getlog((messagesize<<w)+1);
- *
- * keysize = messagesize + (checksumsize+w-1)/w;
- */
- // define the private key messagesize
- privateKeyOTS = new byte[keysize][mdsize];
-
- // gmssRandom.setSeed(seed0);
- byte[] dummy = new byte[mdsize];
- System.arraycopy(seed0, 0, dummy, 0, dummy.length);
-
- // generate random bytes and
- // assign them to the private key
- for (int i = 0; i < keysize; i++)
- {
- privateKeyOTS[i] = gmssRandom.nextSeed(dummy);
- }
- }
-
- /**
- * @return The private OTS key
- */
- public byte[][] getPrivateKey()
- {
- return privateKeyOTS;
- }
-
- /**
- * @return The public OTS key
- */
- public byte[] getPublicKey()
- {
- byte[] helppubKey = new byte[keysize * mdsize];
-
- byte[] help = new byte[mdsize];
- int two_power_t = 1 << w;
-
- for (int i = 0; i < keysize; i++)
- {
- // hash w-1 time the private key and assign it to the public key
- messDigestOTS.update(privateKeyOTS[i], 0, privateKeyOTS[i].length);
- help = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(help, 0);
- for (int j = 2; j < two_power_t; j++)
- {
- messDigestOTS.update(help, 0, help.length);
- help = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(help, 0);
- }
- System.arraycopy(help, 0, helppubKey, mdsize * i, mdsize);
- }
-
- messDigestOTS.update(helppubKey, 0, helppubKey.length);
- byte[] tmp = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(tmp, 0);
- return tmp;
- }
-
- /**
- * @return The one-time signature of the message, generated with the private
- * key
- */
- public byte[] getSignature(byte[] message)
- {
- byte[] sign = new byte[keysize * mdsize];
- // byte [] message; // message m as input
- byte[] hash = new byte[mdsize]; // hash of message m
- int counter = 0;
- int c = 0;
- int test = 0;
- // create hash of message m
- messDigestOTS.update(message, 0, message.length);
- hash = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(hash, 0);
-
- if (8 % w == 0)
- {
- int d = 8 / w;
- int k = (1 << w) - 1;
- byte[] hlp = new byte[mdsize];
-
- // create signature
- for (int i = 0; i < hash.length; i++)
- {
- for (int j = 0; j < d; j++)
- {
- test = hash[i] & k;
- c += test;
-
- System.arraycopy(privateKeyOTS[counter], 0, hlp, 0, mdsize);
-
- while (test > 0)
- {
- messDigestOTS.update(hlp, 0, hlp.length);
- hlp = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(hlp, 0);
- test--;
- }
- System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize);
- hash[i] = (byte)(hash[i] >>> w);
- counter++;
- }
- }
-
- c = (messagesize << w) - c;
- for (int i = 0; i < checksumsize; i += w)
- {
- test = c & k;
-
- System.arraycopy(privateKeyOTS[counter], 0, hlp, 0, mdsize);
-
- while (test > 0)
- {
- messDigestOTS.update(hlp, 0, hlp.length);
- hlp = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(hlp, 0);
- test--;
- }
- System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize);
- c >>>= w;
- counter++;
- }
- }
- else if (w < 8)
- {
- int d = mdsize / w;
- int k = (1 << w) - 1;
- byte[] hlp = new byte[mdsize];
- long big8;
- int ii = 0;
- // create signature
- // first d*w bytes of hash
- for (int i = 0; i < d; i++)
- {
- big8 = 0;
- for (int j = 0; j < w; j++)
- {
- big8 ^= (hash[ii] & 0xff) << (j << 3);
- ii++;
- }
- for (int j = 0; j < 8; j++)
- {
- test = (int)(big8 & k);
- c += test;
-
- System.arraycopy(privateKeyOTS[counter], 0, hlp, 0, mdsize);
-
- while (test > 0)
- {
- messDigestOTS.update(hlp, 0, hlp.length);
- hlp = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(hlp, 0);
- test--;
- }
- System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize);
- big8 >>>= w;
- counter++;
- }
- }
- // rest of hash
- d = mdsize % w;
- big8 = 0;
- for (int j = 0; j < d; j++)
- {
- big8 ^= (hash[ii] & 0xff) << (j << 3);
- ii++;
- }
- d <<= 3;
- for (int j = 0; j < d; j += w)
- {
- test = (int)(big8 & k);
- c += test;
-
- System.arraycopy(privateKeyOTS[counter], 0, hlp, 0, mdsize);
-
- while (test > 0)
- {
- messDigestOTS.update(hlp, 0, hlp.length);
- hlp = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(hlp, 0);
- test--;
- }
- System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize);
- big8 >>>= w;
- counter++;
- }
-
- // check bytes
- c = (messagesize << w) - c;
- for (int i = 0; i < checksumsize; i += w)
- {
- test = c & k;
-
- System.arraycopy(privateKeyOTS[counter], 0, hlp, 0, mdsize);
-
- while (test > 0)
- {
- messDigestOTS.update(hlp, 0, hlp.length);
- hlp = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(hlp, 0);
- test--;
- }
- System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize);
- c >>>= w;
- counter++;
- }
- }// end if(w<8)
- else if (w < 57)
- {
- int d = (mdsize << 3) - w;
- int k = (1 << w) - 1;
- byte[] hlp = new byte[mdsize];
- long big8, test8;
- int r = 0;
- int s, f, rest, ii;
- // create signature
- // first a*w bits of hash where a*w <= 8*mdsize < (a+1)*w
- while (r <= d)
- {
- s = r >>> 3;
- rest = r % 8;
- r += w;
- f = (r + 7) >>> 3;
- big8 = 0;
- ii = 0;
- for (int j = s; j < f; j++)
- {
- big8 ^= (hash[j] & 0xff) << (ii << 3);
- ii++;
- }
-
- big8 >>>= rest;
- test8 = (big8 & k);
- c += test8;
-
- System.arraycopy(privateKeyOTS[counter], 0, hlp, 0, mdsize);
- while (test8 > 0)
- {
- messDigestOTS.update(hlp, 0, hlp.length);
- hlp = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(hlp, 0);
- test8--;
- }
- System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize);
- counter++;
-
- }
- // rest of hash
- s = r >>> 3;
- if (s < mdsize)
- {
- rest = r % 8;
- big8 = 0;
- ii = 0;
- for (int j = s; j < mdsize; j++)
- {
- big8 ^= (hash[j] & 0xff) << (ii << 3);
- ii++;
- }
-
- big8 >>>= rest;
- test8 = (big8 & k);
- c += test8;
-
- System.arraycopy(privateKeyOTS[counter], 0, hlp, 0, mdsize);
- while (test8 > 0)
- {
- messDigestOTS.update(hlp, 0, hlp.length);
- hlp = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(hlp, 0);
- test8--;
- }
- System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize);
- counter++;
- }
- // check bytes
- c = (messagesize << w) - c;
- for (int i = 0; i < checksumsize; i += w)
- {
- test8 = (c & k);
-
- System.arraycopy(privateKeyOTS[counter], 0, hlp, 0, mdsize);
-
- while (test8 > 0)
- {
- messDigestOTS.update(hlp, 0, hlp.length);
- hlp = new byte[messDigestOTS.getDigestSize()];
- messDigestOTS.doFinal(hlp, 0);
- test8--;
- }
- System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize);
- c >>>= w;
- counter++;
- }
- }// end if(w<57)
-
- return sign;
- }
-
- /**
- * This method returns the least integer that is greater or equal to the
- * logarithm to the base 2 of an integer <code>intValue</code>.
- *
- * @param intValue an integer
- * @return The least integer greater or equal to the logarithm to the base 2
- * of <code>intValue</code>
- */
- public int getLog(int intValue)
- {
- int log = 1;
- int i = 2;
- while (i < intValue)
- {
- i <<= 1;
- log++;
- }
- return log;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/Conversions.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/Conversions.java
deleted file mode 100644
index 752d51cc..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/Conversions.java
+++ /dev/null
@@ -1,236 +0,0 @@
-package org.bouncycastle.pqc.crypto.mceliece;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.pqc.math.linearalgebra.BigIntUtils;
-import org.bouncycastle.pqc.math.linearalgebra.GF2Vector;
-import org.bouncycastle.pqc.math.linearalgebra.IntegerFunctions;
-
-
-/**
- * Provides methods for CCA2-Secure Conversions of McEliece PKCS
- */
-final class Conversions
-{
- private static final BigInteger ZERO = BigInteger.valueOf(0);
- private static final BigInteger ONE = BigInteger.valueOf(1);
-
- /**
- * Default constructor (private).
- */
- private Conversions()
- {
- }
-
- /**
- * Encode a number between 0 and (n|t) (binomial coefficient) into a binary
- * vector of length n with weight t. The number is given as a byte array.
- * Only the first s bits are used, where s = floor[log(n|t)].
- *
- * @param n integer
- * @param t integer
- * @param m the message as a byte array
- * @return the encoded message as {@link GF2Vector}
- */
- public static GF2Vector encode(final int n, final int t, final byte[] m)
- {
- if (n < t)
- {
- throw new IllegalArgumentException("n < t");
- }
-
- // compute the binomial c = (n|t)
- BigInteger c = IntegerFunctions.binomial(n, t);
- // get the number encoded in m
- BigInteger i = new BigInteger(1, m);
- // compare
- if (i.compareTo(c) >= 0)
- {
- throw new IllegalArgumentException("Encoded number too large.");
- }
-
- GF2Vector result = new GF2Vector(n);
-
- int nn = n;
- int tt = t;
- for (int j = 0; j < n; j++)
- {
- c = c.multiply(BigInteger.valueOf(nn - tt)).divide(
- BigInteger.valueOf(nn));
- nn--;
- if (c.compareTo(i) <= 0)
- {
- result.setBit(j);
- i = i.subtract(c);
- tt--;
- if (nn == tt)
- {
- c = ONE;
- }
- else
- {
- c = (c.multiply(BigInteger.valueOf(tt + 1)))
- .divide(BigInteger.valueOf(nn - tt));
- }
- }
- }
-
- return result;
- }
-
- /**
- * Decode a binary vector of length n and weight t into a number between 0
- * and (n|t) (binomial coefficient). The result is given as a byte array of
- * length floor[(s+7)/8], where s = floor[log(n|t)].
- *
- * @param n integer
- * @param t integer
- * @param vec the binary vector
- * @return the decoded vector as a byte array
- */
- public static byte[] decode(int n, int t, GF2Vector vec)
- {
- if ((vec.getLength() != n) || (vec.getHammingWeight() != t))
- {
- throw new IllegalArgumentException(
- "vector has wrong length or hamming weight");
- }
- int[] vecArray = vec.getVecArray();
-
- BigInteger bc = IntegerFunctions.binomial(n, t);
- BigInteger d = ZERO;
- int nn = n;
- int tt = t;
- for (int i = 0; i < n; i++)
- {
- bc = bc.multiply(BigInteger.valueOf(nn - tt)).divide(
- BigInteger.valueOf(nn));
- nn--;
-
- int q = i >> 5;
- int e = vecArray[q] & (1 << (i & 0x1f));
- if (e != 0)
- {
- d = d.add(bc);
- tt--;
- if (nn == tt)
- {
- bc = ONE;
- }
- else
- {
- bc = bc.multiply(BigInteger.valueOf(tt + 1)).divide(
- BigInteger.valueOf(nn - tt));
- }
-
- }
- }
-
- return BigIntUtils.toMinimalByteArray(d);
- }
-
- /**
- * Compute a message representative of a message given as a vector of length
- * <tt>n</tt> bit and of hamming weight <tt>t</tt>. The result is a
- * byte array of length <tt>(s+7)/8</tt>, where
- * <tt>s = floor[log(n|t)]</tt>.
- *
- * @param n integer
- * @param t integer
- * @param m the message vector as a byte array
- * @return a message representative for <tt>m</tt>
- */
- public static byte[] signConversion(int n, int t, byte[] m)
- {
- if (n < t)
- {
- throw new IllegalArgumentException("n < t");
- }
-
- BigInteger bc = IntegerFunctions.binomial(n, t);
- // finds s = floor[log(binomial(n,t))]
- int s = bc.bitLength() - 1;
- // s = sq*8 + sr;
- int sq = s >> 3;
- int sr = s & 7;
- if (sr == 0)
- {
- sq--;
- sr = 8;
- }
-
- // n = nq*8+nr;
- int nq = n >> 3;
- int nr = n & 7;
- if (nr == 0)
- {
- nq--;
- nr = 8;
- }
- // take s bit from m
- byte[] data = new byte[nq + 1];
- if (m.length < data.length)
- {
- System.arraycopy(m, 0, data, 0, m.length);
- for (int i = m.length; i < data.length; i++)
- {
- data[i] = 0;
- }
- }
- else
- {
- System.arraycopy(m, 0, data, 0, nq);
- int h = (1 << nr) - 1;
- data[nq] = (byte)(h & m[nq]);
- }
-
- BigInteger d = ZERO;
- int nn = n;
- int tt = t;
- for (int i = 0; i < n; i++)
- {
- bc = (bc.multiply(new BigInteger(Integer.toString(nn - tt))))
- .divide(new BigInteger(Integer.toString(nn)));
- nn--;
-
- int q = i >>> 3;
- int r = i & 7;
- r = 1 << r;
- byte e = (byte)(r & data[q]);
- if (e != 0)
- {
- d = d.add(bc);
- tt--;
- if (nn == tt)
- {
- bc = ONE;
- }
- else
- {
- bc = (bc
- .multiply(new BigInteger(Integer.toString(tt + 1))))
- .divide(new BigInteger(Integer.toString(nn - tt)));
- }
- }
- }
-
- byte[] result = new byte[sq + 1];
- byte[] help = d.toByteArray();
- if (help.length < result.length)
- {
- System.arraycopy(help, 0, result, 0, help.length);
- for (int i = help.length; i < result.length; i++)
- {
- result[i] = 0;
- }
- }
- else
- {
- System.arraycopy(help, 0, result, 0, sq);
- result[sq] = (byte)(((1 << sr) - 1) & help[sq]);
- }
-
- return result;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2KeyGenerationParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2KeyGenerationParameters.java
deleted file mode 100644
index dbd5a82a..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2KeyGenerationParameters.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.pqc.crypto.mceliece;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.KeyGenerationParameters;
-
-public class McElieceCCA2KeyGenerationParameters
- extends KeyGenerationParameters
-{
- private McElieceCCA2Parameters params;
-
- public McElieceCCA2KeyGenerationParameters(
- SecureRandom random,
- McElieceCCA2Parameters params)
- {
- // XXX key size?
- super(random, 128);
- this.params = params;
- }
-
- public McElieceCCA2Parameters getParameters()
- {
- return params;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2KeyPairGenerator.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2KeyPairGenerator.java
deleted file mode 100644
index 198e5d29..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2KeyPairGenerator.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package org.bouncycastle.pqc.crypto.mceliece;
-
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.pqc.math.linearalgebra.GF2Matrix;
-import org.bouncycastle.pqc.math.linearalgebra.GF2mField;
-import org.bouncycastle.pqc.math.linearalgebra.GoppaCode;
-import org.bouncycastle.pqc.math.linearalgebra.GoppaCode.MaMaPe;
-import org.bouncycastle.pqc.math.linearalgebra.Permutation;
-import org.bouncycastle.pqc.math.linearalgebra.PolynomialGF2mSmallM;
-import org.bouncycastle.pqc.math.linearalgebra.PolynomialRingGF2m;
-
-
-/**
- * This class implements key pair generation of the McEliece Public Key
- * Cryptosystem (McEliecePKC).
- */
-public class McElieceCCA2KeyPairGenerator
- implements AsymmetricCipherKeyPairGenerator
-{
-
-
- /**
- * The OID of the algorithm.
- */
- public static final String OID = "1.3.6.1.4.1.8301.3.1.3.4.2";
-
- private McElieceCCA2KeyGenerationParameters mcElieceCCA2Params;
-
- // the extension degree of the finite field GF(2^m)
- private int m;
-
- // the length of the code
- private int n;
-
- // the error correction capability
- private int t;
-
- // the field polynomial
- private int fieldPoly;
-
- // the source of randomness
- private SecureRandom random;
-
- // flag indicating whether the key pair generator has been initialized
- private boolean initialized = false;
-
- /**
- * Default initialization of the key pair generator.
- */
- private void initializeDefault()
- {
- McElieceCCA2KeyGenerationParameters mcCCA2Params = new McElieceCCA2KeyGenerationParameters(new SecureRandom(), new McElieceCCA2Parameters());
- init(mcCCA2Params);
- }
-
- // TODO
- public void init(
- KeyGenerationParameters param)
- {
- this.mcElieceCCA2Params = (McElieceCCA2KeyGenerationParameters)param;
-
- // set source of randomness
- this.random = new SecureRandom();
-
- this.m = this.mcElieceCCA2Params.getParameters().getM();
- this.n = this.mcElieceCCA2Params.getParameters().getN();
- this.t = this.mcElieceCCA2Params.getParameters().getT();
- this.fieldPoly = this.mcElieceCCA2Params.getParameters().getFieldPoly();
- this.initialized = true;
- }
-
-
- public AsymmetricCipherKeyPair generateKeyPair()
- {
-
- if (!initialized)
- {
- initializeDefault();
- }
-
- // finite field GF(2^m)
- GF2mField field = new GF2mField(m, fieldPoly);
-
- // irreducible Goppa polynomial
- PolynomialGF2mSmallM gp = new PolynomialGF2mSmallM(field, t,
- PolynomialGF2mSmallM.RANDOM_IRREDUCIBLE_POLYNOMIAL, random);
- PolynomialRingGF2m ring = new PolynomialRingGF2m(field, gp);
-
- // matrix for computing square roots in (GF(2^m))^t
- PolynomialGF2mSmallM[] qInv = ring.getSquareRootMatrix();
-
- // generate canonical check matrix
- GF2Matrix h = GoppaCode.createCanonicalCheckMatrix(field, gp);
-
- // compute short systematic form of check matrix
- MaMaPe mmp = GoppaCode.computeSystematicForm(h, random);
- GF2Matrix shortH = mmp.getSecondMatrix();
- Permutation p = mmp.getPermutation();
-
- // compute short systematic form of generator matrix
- GF2Matrix shortG = (GF2Matrix)shortH.computeTranspose();
-
- // obtain number of rows of G (= dimension of the code)
- int k = shortG.getNumRows();
-
- // generate keys
- McElieceCCA2PublicKeyParameters pubKey = new McElieceCCA2PublicKeyParameters(OID, n, t, shortG, mcElieceCCA2Params.getParameters());
- McElieceCCA2PrivateKeyParameters privKey = new McElieceCCA2PrivateKeyParameters(OID, n, k,
- field, gp, p, h, qInv, mcElieceCCA2Params.getParameters());
-
- // return key pair
- return new AsymmetricCipherKeyPair(pubKey, privKey);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2KeyParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2KeyParameters.java
deleted file mode 100644
index 80114767..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2KeyParameters.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.pqc.crypto.mceliece;
-
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-
-
-public class McElieceCCA2KeyParameters
- extends AsymmetricKeyParameter
-{
- private McElieceCCA2Parameters params;
-
- public McElieceCCA2KeyParameters(
- boolean isPrivate,
- McElieceCCA2Parameters params)
- {
- super(isPrivate);
- this.params = params;
- }
-
-
- public McElieceCCA2Parameters getParameters()
- {
- return params;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2Parameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2Parameters.java
deleted file mode 100644
index 7f800106..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2Parameters.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package org.bouncycastle.pqc.crypto.mceliece;
-
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-
-/**
- * This class provides a specification for the parameters of the CCA2-secure
- * variants of the McEliece PKCS that are used with
- * {@link McElieceFujisakiCipher}, {@link McElieceKobaraImaiCipher}, and
- * {@link McEliecePointchevalCipher}.
- *
- * @see McElieceFujisakiCipher
- * @see McElieceKobaraImaiCipher
- * @see McEliecePointchevalCipher
- */
-public class McElieceCCA2Parameters
- extends McElieceParameters
-{
-
-
- public Digest digest;
-
-
- /**
- * Construct the default parameters.
- * The default message digest is SHA256.
- */
- public McElieceCCA2Parameters()
- {
- this.digest = new SHA256Digest();
- }
-
- public McElieceCCA2Parameters(int m, int t)
- {
- super(m, t);
- this.digest = new SHA256Digest();
- }
-
- public McElieceCCA2Parameters(Digest digest)
- {
- this.digest = digest;
- }
-
- public Digest getDigest()
- {
- return this.digest;
- }
-
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2Primitives.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2Primitives.java
deleted file mode 100644
index 726add15..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2Primitives.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.bouncycastle.pqc.crypto.mceliece;
-
-import org.bouncycastle.pqc.math.linearalgebra.GF2Matrix;
-import org.bouncycastle.pqc.math.linearalgebra.GF2Vector;
-import org.bouncycastle.pqc.math.linearalgebra.GF2mField;
-import org.bouncycastle.pqc.math.linearalgebra.GoppaCode;
-import org.bouncycastle.pqc.math.linearalgebra.Permutation;
-import org.bouncycastle.pqc.math.linearalgebra.PolynomialGF2mSmallM;
-import org.bouncycastle.pqc.math.linearalgebra.Vector;
-
-/**
- * Core operations for the CCA-secure variants of McEliece.
- */
-public final class McElieceCCA2Primitives
-{
-
- /**
- * Default constructor (private).
- */
- private McElieceCCA2Primitives()
- {
- }
-
- /**
- * The McEliece encryption primitive.
- *
- * @param pubKey the public key
- * @param m the message vector
- * @param z the error vector
- * @return <tt>m*G + z</tt>
- */
-
-
- public static GF2Vector encryptionPrimitive(McElieceCCA2PublicKeyParameters pubKey,
- GF2Vector m, GF2Vector z)
- {
-
- GF2Matrix matrixG = pubKey.getMatrixG();
- Vector mG = matrixG.leftMultiplyLeftCompactForm(m);
- return (GF2Vector)mG.add(z);
- }
-
- /**
- * The McEliece decryption primitive.
- *
- * @param privKey the private key
- * @param c the ciphertext vector <tt>c = m*G + z</tt>
- * @return the message vector <tt>m</tt> and the error vector <tt>z</tt>
- */
- public static GF2Vector[] decryptionPrimitive(
- McElieceCCA2PrivateKeyParameters privKey, GF2Vector c)
- {
-
- // obtain values from private key
- int k = privKey.getK();
- Permutation p = privKey.getP();
- GF2mField field = privKey.getField();
- PolynomialGF2mSmallM gp = privKey.getGoppaPoly();
- GF2Matrix h = privKey.getH();
- PolynomialGF2mSmallM[] q = privKey.getQInv();
-
- // compute inverse permutation P^-1
- Permutation pInv = p.computeInverse();
-
- // multiply c with permutation P^-1
- GF2Vector cPInv = (GF2Vector)c.multiply(pInv);
-
- // compute syndrome of cP^-1
- GF2Vector syndVec = (GF2Vector)h.rightMultiply(cPInv);
-
- // decode syndrome
- GF2Vector errors = GoppaCode.syndromeDecode(syndVec, field, gp, q);
- GF2Vector mG = (GF2Vector)cPInv.add(errors);
-
- // multiply codeword and error vector with P
- mG = (GF2Vector)mG.multiply(p);
- errors = (GF2Vector)errors.multiply(p);
-
- // extract plaintext vector (last k columns of mG)
- GF2Vector m = mG.extractRightVector(k);
-
- // return vectors
- return new GF2Vector[]{m, errors};
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2PrivateKeyParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2PrivateKeyParameters.java
deleted file mode 100644
index 980ecdc9..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2PrivateKeyParameters.java
+++ /dev/null
@@ -1,172 +0,0 @@
-package org.bouncycastle.pqc.crypto.mceliece;
-
-
-import org.bouncycastle.pqc.math.linearalgebra.GF2Matrix;
-import org.bouncycastle.pqc.math.linearalgebra.GF2mField;
-import org.bouncycastle.pqc.math.linearalgebra.Permutation;
-import org.bouncycastle.pqc.math.linearalgebra.PolynomialGF2mSmallM;
-
-/**
- *
- *
- *
- */
-public class McElieceCCA2PrivateKeyParameters
- extends McElieceCCA2KeyParameters
-{
-
- // the OID of the algorithm
- private String oid;
-
- // the length of the code
- private int n;
-
- // the dimension of the code
- private int k;
-
- // the finte field GF(2^m)
- private GF2mField field;
-
- // the irreducible Goppa polynomial
- private PolynomialGF2mSmallM goppaPoly;
-
- // the permutation
- private Permutation p;
-
- // the canonical check matrix
- private GF2Matrix h;
-
- // the matrix used to compute square roots in (GF(2^m))^t
- private PolynomialGF2mSmallM[] qInv;
-
- /**
- * Constructor.
- *
- * @param n the length of the code
- * @param k the dimension of the code
- * @param field the finite field <tt>GF(2<sup>m</sup>)</tt>
- * @param gp the irreducible Goppa polynomial
- * @param p the permutation
- * @param h the canonical check matrix
- * @param qInv the matrix used to compute square roots in
- * <tt>(GF(2^m))^t</tt>
- * @param params McElieceCCA2Parameters
- */
- public McElieceCCA2PrivateKeyParameters(String oid, int n, int k, GF2mField field,
- PolynomialGF2mSmallM gp, Permutation p, GF2Matrix h,
- PolynomialGF2mSmallM[] qInv, McElieceCCA2Parameters params)
- {
- super(true, params);
- this.oid = oid;
- this.n = n;
- this.k = k;
- this.field = field;
- this.goppaPoly = gp;
- this.p = p;
- this.h = h;
- this.qInv = qInv;
- }
-
- /**
- * Constructor used by the {@link McElieceKeyFactory}.
- *
- * @param n the length of the code
- * @param k the dimension of the code
- * @param encFieldPoly the encoded field polynomial defining the finite field
- * <tt>GF(2<sup>m</sup>)</tt>
- * @param encGoppaPoly the encoded irreducible Goppa polynomial
- * @param encP the encoded permutation
- * @param encH the encoded canonical check matrix
- * @param encQInv the encoded matrix used to compute square roots in
- * <tt>(GF(2^m))^t</tt>
- * @param params McElieceCCA2Parameters
- */
- public McElieceCCA2PrivateKeyParameters(String oid, int n, int k, byte[] encFieldPoly,
- byte[] encGoppaPoly, byte[] encP, byte[] encH, byte[][] encQInv, McElieceCCA2Parameters params)
- {
- super(true, params);
- this.oid = oid;
- this.n = n;
- this.k = k;
- field = new GF2mField(encFieldPoly);
- goppaPoly = new PolynomialGF2mSmallM(field, encGoppaPoly);
- p = new Permutation(encP);
- h = new GF2Matrix(encH);
- qInv = new PolynomialGF2mSmallM[encQInv.length];
- for (int i = 0; i < encQInv.length; i++)
- {
- qInv[i] = new PolynomialGF2mSmallM(field, encQInv[i]);
- }
- }
-
- /**
- * @return the length of the code
- */
- public int getN()
- {
- return n;
- }
-
- /**
- * @return the dimension of the code
- */
- public int getK()
- {
- return k;
- }
-
- /**
- * @return the degree of the Goppa polynomial (error correcting capability)
- */
- public int getT()
- {
- return goppaPoly.getDegree();
- }
-
- /**
- * @return the finite field
- */
- public GF2mField getField()
- {
- return field;
- }
-
- /**
- * @return the irreducible Goppa polynomial
- */
- public PolynomialGF2mSmallM getGoppaPoly()
- {
- return goppaPoly;
- }
-
- /**
- * @return the permutation P
- */
- public Permutation getP()
- {
- return p;
- }
-
- /**
- * @return the canonical check matrix H
- */
- public GF2Matrix getH()
- {
- return h;
- }
-
- /**
- * @return the matrix used to compute square roots in <tt>(GF(2^m))^t</tt>
- */
- public PolynomialGF2mSmallM[] getQInv()
- {
- return qInv;
- }
-
- public String getOIDString()
- {
- return oid;
-
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2PublicKeyParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2PublicKeyParameters.java
deleted file mode 100644
index e63377c3..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceCCA2PublicKeyParameters.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package org.bouncycastle.pqc.crypto.mceliece;
-
-import org.bouncycastle.pqc.math.linearalgebra.GF2Matrix;
-
-/**
- *
- *
- *
- */
-public class McElieceCCA2PublicKeyParameters
- extends McElieceCCA2KeyParameters
-{
-
- // the OID of the algorithm
- private String oid;
-
- // the length of the code
- private int n;
-
- // the error correction capability of the code
- private int t;
-
- // the generator matrix
- private GF2Matrix matrixG;
-
- /**
- * Constructor.
- *
- * @param n length of the code
- * @param t error correction capability
- * @param matrix generator matrix
- * @param params McElieceCCA2Parameters
- */
- public McElieceCCA2PublicKeyParameters(String oid, int n, int t, GF2Matrix matrix, McElieceCCA2Parameters params)
- {
- super(false, params);
- this.oid = oid;
- this.n = n;
- this.t = t;
- this.matrixG = new GF2Matrix(matrix);
- }
-
- /**
- * Constructor (used by {@link McElieceKeyFactory}).
- *
- * @param n length of the code
- * @param t error correction capability of the code
- * @param encMatrix encoded generator matrix
- * @param params McElieceCCA2Parameters
- */
- public McElieceCCA2PublicKeyParameters(String oid, int n, int t, byte[] encMatrix, McElieceCCA2Parameters params)
- {
- super(false, params);
- this.oid = oid;
- this.n = n;
- this.t = t;
- this.matrixG = new GF2Matrix(encMatrix);
- }
-
- /**
- * @return the length of the code
- */
- public int getN()
- {
- return n;
- }
-
- /**
- * @return the error correction capability of the code
- */
- public int getT()
- {
- return t;
- }
-
- /**
- * @return the generator matrix
- */
- public GF2Matrix getMatrixG()
- {
- return matrixG;
- }
-
- /**
- * @return the dimension of the code
- */
- public int getK()
- {
- return matrixG.getNumRows();
- }
-
- public String getOIDString()
- {
- return oid;
-
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceFujisakiCipher.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceFujisakiCipher.java
deleted file mode 100644
index c414540f..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceFujisakiCipher.java
+++ /dev/null
@@ -1,218 +0,0 @@
-package org.bouncycastle.pqc.crypto.mceliece;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.prng.DigestRandomGenerator;
-import org.bouncycastle.pqc.crypto.MessageEncryptor;
-import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
-import org.bouncycastle.pqc.math.linearalgebra.GF2Vector;
-
-/**
- * This class implements the Fujisaki/Okamoto conversion of the McEliecePKCS.
- * Fujisaki and Okamoto propose hybrid encryption that merges a symmetric
- * encryption scheme which is secure in the find-guess model with an asymmetric
- * one-way encryption scheme which is sufficiently probabilistic to obtain a
- * public key cryptosystem which is CCA2-secure. For details, see D. Engelbert,
- * R. Overbeck, A. Schmidt, "A summary of the development of the McEliece
- * Cryptosystem", technical report.
- */
-public class McElieceFujisakiCipher
- implements MessageEncryptor
-{
-
-
- /**
- * The OID of the algorithm.
- */
- public static final String OID = "1.3.6.1.4.1.8301.3.1.3.4.2.1";
-
- private static final String DEFAULT_PRNG_NAME = "SHA1PRNG";
-
- private Digest messDigest;
-
- private SecureRandom sr;
-
- /**
- * The McEliece main parameters
- */
- private int n, k, t;
-
- McElieceCCA2KeyParameters key;
-
-
- public void init(boolean forSigning,
- CipherParameters param)
- {
-
- if (forSigning)
- {
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- this.sr = rParam.getRandom();
- this.key = (McElieceCCA2PublicKeyParameters)rParam.getParameters();
- this.initCipherEncrypt((McElieceCCA2PublicKeyParameters)key);
-
- }
- else
- {
- this.sr = new SecureRandom();
- this.key = (McElieceCCA2PublicKeyParameters)param;
- this.initCipherEncrypt((McElieceCCA2PublicKeyParameters)key);
- }
- }
- else
- {
- this.key = (McElieceCCA2PrivateKeyParameters)param;
- this.initCipherDecrypt((McElieceCCA2PrivateKeyParameters)key);
- }
-
- }
-
-
- public int getKeySize(McElieceCCA2KeyParameters key)
- throws IllegalArgumentException
- {
-
- if (key instanceof McElieceCCA2PublicKeyParameters)
- {
- return ((McElieceCCA2PublicKeyParameters)key).getN();
-
- }
- if (key instanceof McElieceCCA2PrivateKeyParameters)
- {
- return ((McElieceCCA2PrivateKeyParameters)key).getN();
- }
- throw new IllegalArgumentException("unsupported type");
-
- }
-
-
- private void initCipherEncrypt(McElieceCCA2PublicKeyParameters pubKey)
- {
- this.sr = sr != null ? sr : new SecureRandom();
- this.messDigest = pubKey.getParameters().getDigest();
- n = pubKey.getN();
- k = pubKey.getK();
- t = pubKey.getT();
- }
-
-
- public void initCipherDecrypt(McElieceCCA2PrivateKeyParameters privKey)
- {
- this.messDigest = privKey.getParameters().getDigest();
- n = privKey.getN();
- t = privKey.getT();
- }
-
-
- public byte[] messageEncrypt(byte[] input)
- throws Exception
- {
-
- // generate random vector r of length k bits
- GF2Vector r = new GF2Vector(k, sr);
-
- // convert r to byte array
- byte[] rBytes = r.getEncoded();
-
- // compute (r||input)
- byte[] rm = ByteUtils.concatenate(rBytes, input);
-
- // compute H(r||input)
- messDigest.update(rm, 0, rm.length);
- byte[] hrm = new byte[messDigest.getDigestSize()];
- messDigest.doFinal(hrm, 0);
-
- // convert H(r||input) to error vector z
- GF2Vector z = Conversions.encode(n, t, hrm);
-
- // compute c1 = E(r, z)
- byte[] c1 = McElieceCCA2Primitives.encryptionPrimitive((McElieceCCA2PublicKeyParameters)key, r, z)
- .getEncoded();
-
- // get PRNG object
- DigestRandomGenerator sr0 = new DigestRandomGenerator(new SHA1Digest());
-
- // seed PRNG with r'
- sr0.addSeedMaterial(rBytes);
-
- // generate random c2
- byte[] c2 = new byte[input.length];
- sr0.nextBytes(c2);
-
- // XOR with input
- for (int i = 0; i < input.length; i++)
- {
- c2[i] ^= input[i];
- }
-
- // return (c1||c2)
- return ByteUtils.concatenate(c1, c2);
- }
-
- public byte[] messageDecrypt(byte[] input)
- throws Exception
- {
-
- int c1Len = (n + 7) >> 3;
- int c2Len = input.length - c1Len;
-
- // split ciphertext (c1||c2)
- byte[][] c1c2 = ByteUtils.split(input, c1Len);
- byte[] c1 = c1c2[0];
- byte[] c2 = c1c2[1];
-
- // decrypt c1 ...
- GF2Vector hrmVec = GF2Vector.OS2VP(n, c1);
- GF2Vector[] decC1 = McElieceCCA2Primitives.decryptionPrimitive((McElieceCCA2PrivateKeyParameters)key,
- hrmVec);
- byte[] rBytes = decC1[0].getEncoded();
- // ... and obtain error vector z
- GF2Vector z = decC1[1];
-
- // get PRNG object
- DigestRandomGenerator sr0 = new DigestRandomGenerator(new SHA1Digest());
-
- // seed PRNG with r'
- sr0.addSeedMaterial(rBytes);
-
- // generate random sequence
- byte[] mBytes = new byte[c2Len];
- sr0.nextBytes(mBytes);
-
- // XOR with c2 to obtain m
- for (int i = 0; i < c2Len; i++)
- {
- mBytes[i] ^= c2[i];
- }
-
- // compute H(r||m)
- byte[] rmBytes = ByteUtils.concatenate(rBytes, mBytes);
- byte[] hrm = new byte[messDigest.getDigestSize()];
- messDigest.update(rmBytes, 0, rmBytes.length);
- messDigest.doFinal(hrm, 0);
-
-
- // compute Conv(H(r||m))
- hrmVec = Conversions.encode(n, t, hrm);
-
- // check that Conv(H(m||r)) = z
- if (!hrmVec.equals(z))
- {
-
- throw new Exception("Bad Padding: invalid ciphertext");
-
- }
-
- // return plaintext m
- return mBytes;
- }
-
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceFujisakiDigestCipher.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceFujisakiDigestCipher.java
deleted file mode 100644
index 423e6ff8..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceFujisakiDigestCipher.java
+++ /dev/null
@@ -1,128 +0,0 @@
-package org.bouncycastle.pqc.crypto.mceliece;
-
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.pqc.crypto.MessageEncryptor;
-
-// TODO should implement some interface?
-public class McElieceFujisakiDigestCipher
-{
-
- private final Digest messDigest;
-
- private final MessageEncryptor mcElieceCCA2Cipher;
-
- private boolean forEncrypting;
-
-
- public McElieceFujisakiDigestCipher(MessageEncryptor mcElieceCCA2Cipher, Digest messDigest)
- {
- this.mcElieceCCA2Cipher = mcElieceCCA2Cipher;
- this.messDigest = messDigest;
- }
-
-
- public void init(boolean forEncrypting,
- CipherParameters param)
- {
-
- this.forEncrypting = forEncrypting;
- AsymmetricKeyParameter k;
-
- if (param instanceof ParametersWithRandom)
- {
- k = (AsymmetricKeyParameter)((ParametersWithRandom)param).getParameters();
- }
- else
- {
- k = (AsymmetricKeyParameter)param;
- }
-
- if (forEncrypting && k.isPrivate())
- {
- throw new IllegalArgumentException("Encrypting Requires Public Key.");
- }
-
- if (!forEncrypting && !k.isPrivate())
- {
- throw new IllegalArgumentException("Decrypting Requires Private Key.");
- }
-
- reset();
-
- mcElieceCCA2Cipher.init(forEncrypting, param);
- }
-
-
- public byte[] messageEncrypt()
- {
- if (!forEncrypting)
- {
- throw new IllegalStateException("McElieceFujisakiDigestCipher not initialised for encrypting.");
- }
-
- byte[] hash = new byte[messDigest.getDigestSize()];
- messDigest.doFinal(hash, 0);
- byte[] enc = null;
-
- try
- {
- enc = mcElieceCCA2Cipher.messageEncrypt(hash);
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
-
-
- return enc;
- }
-
-
- public byte[] messageDecrypt(byte[] ciphertext)
- {
- byte[] output = null;
- if (forEncrypting)
- {
- throw new IllegalStateException("McElieceFujisakiDigestCipher not initialised for decrypting.");
- }
-
-
- try
- {
- output = mcElieceCCA2Cipher.messageDecrypt(ciphertext);
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
-
-
- return output;
- }
-
-
- public void update(byte b)
- {
- messDigest.update(b);
-
- }
-
- public void update(byte[] in, int off, int len)
- {
- messDigest.update(in, off, len);
-
- }
-
-
- public void reset()
- {
- messDigest.reset();
-
- }
-
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceKeyGenerationParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceKeyGenerationParameters.java
deleted file mode 100644
index 1b1fa658..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceKeyGenerationParameters.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.pqc.crypto.mceliece;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.KeyGenerationParameters;
-
-public class McElieceKeyGenerationParameters
- extends KeyGenerationParameters
-{
- private McElieceParameters params;
-
- public McElieceKeyGenerationParameters(
- SecureRandom random,
- McElieceParameters params)
- {
- // XXX key size?
- super(random, 256);
- this.params = params;
- }
-
- public McElieceParameters getParameters()
- {
- return params;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceKeyPairGenerator.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceKeyPairGenerator.java
deleted file mode 100644
index 6ad7fc2f..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceKeyPairGenerator.java
+++ /dev/null
@@ -1,151 +0,0 @@
-package org.bouncycastle.pqc.crypto.mceliece;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.pqc.math.linearalgebra.GF2Matrix;
-import org.bouncycastle.pqc.math.linearalgebra.GF2mField;
-import org.bouncycastle.pqc.math.linearalgebra.GoppaCode;
-import org.bouncycastle.pqc.math.linearalgebra.GoppaCode.MaMaPe;
-import org.bouncycastle.pqc.math.linearalgebra.Permutation;
-import org.bouncycastle.pqc.math.linearalgebra.PolynomialGF2mSmallM;
-import org.bouncycastle.pqc.math.linearalgebra.PolynomialRingGF2m;
-
-
-/**
- * This class implements key pair generation of the McEliece Public Key
- * Cryptosystem (McEliecePKC).
- */
-public class McElieceKeyPairGenerator
- implements AsymmetricCipherKeyPairGenerator
-{
-
-
- public McElieceKeyPairGenerator()
- {
-
- }
-
-
- /**
- * The OID of the algorithm.
- */
- private static final String OID = "1.3.6.1.4.1.8301.3.1.3.4.1";
-
- private McElieceKeyGenerationParameters mcElieceParams;
-
- // the extension degree of the finite field GF(2^m)
- private int m;
-
- // the length of the code
- private int n;
-
- // the error correction capability
- private int t;
-
- // the field polynomial
- private int fieldPoly;
-
- // the source of randomness
- private SecureRandom random;
-
- // flag indicating whether the key pair generator has been initialized
- private boolean initialized = false;
-
-
- /**
- * Default initialization of the key pair generator.
- */
- private void initializeDefault()
- {
- McElieceKeyGenerationParameters mcParams = new McElieceKeyGenerationParameters(new SecureRandom(), new McElieceParameters());
- initialize(mcParams);
- }
-
- private void initialize(
- KeyGenerationParameters param)
- {
- this.mcElieceParams = (McElieceKeyGenerationParameters)param;
-
- // set source of randomness
- this.random = new SecureRandom();
-
- this.m = this.mcElieceParams.getParameters().getM();
- this.n = this.mcElieceParams.getParameters().getN();
- this.t = this.mcElieceParams.getParameters().getT();
- this.fieldPoly = this.mcElieceParams.getParameters().getFieldPoly();
- this.initialized = true;
- }
-
-
- private AsymmetricCipherKeyPair genKeyPair()
- {
-
- if (!initialized)
- {
- initializeDefault();
- }
-
- // finite field GF(2^m)
- GF2mField field = new GF2mField(m, fieldPoly);
-
- // irreducible Goppa polynomial
- PolynomialGF2mSmallM gp = new PolynomialGF2mSmallM(field, t,
- PolynomialGF2mSmallM.RANDOM_IRREDUCIBLE_POLYNOMIAL, random);
- PolynomialRingGF2m ring = new PolynomialRingGF2m(field, gp);
-
- // matrix used to compute square roots in (GF(2^m))^t
- PolynomialGF2mSmallM[] sqRootMatrix = ring.getSquareRootMatrix();
-
- // generate canonical check matrix
- GF2Matrix h = GoppaCode.createCanonicalCheckMatrix(field, gp);
-
- // compute short systematic form of check matrix
- MaMaPe mmp = GoppaCode.computeSystematicForm(h, random);
- GF2Matrix shortH = mmp.getSecondMatrix();
- Permutation p1 = mmp.getPermutation();
-
- // compute short systematic form of generator matrix
- GF2Matrix shortG = (GF2Matrix)shortH.computeTranspose();
-
- // extend to full systematic form
- GF2Matrix gPrime = shortG.extendLeftCompactForm();
-
- // obtain number of rows of G (= dimension of the code)
- int k = shortG.getNumRows();
-
- // generate random invertible (k x k)-matrix S and its inverse S^-1
- GF2Matrix[] matrixSandInverse = GF2Matrix
- .createRandomRegularMatrixAndItsInverse(k, random);
-
- // generate random permutation P2
- Permutation p2 = new Permutation(n, random);
-
- // compute public matrix G=S*G'*P2
- GF2Matrix g = (GF2Matrix)matrixSandInverse[0].rightMultiply(gPrime);
- g = (GF2Matrix)g.rightMultiply(p2);
-
-
- // generate keys
- McEliecePublicKeyParameters pubKey = new McEliecePublicKeyParameters(OID, n, t, g, mcElieceParams.getParameters());
- McEliecePrivateKeyParameters privKey = new McEliecePrivateKeyParameters(OID, n, k,
- field, gp, matrixSandInverse[1], p1, p2, h, sqRootMatrix, mcElieceParams.getParameters());
-
- // return key pair
- return new AsymmetricCipherKeyPair(pubKey, privKey);
- }
-
- public void init(KeyGenerationParameters param)
- {
- this.initialize(param);
-
- }
-
- public AsymmetricCipherKeyPair generateKeyPair()
- {
- return genKeyPair();
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceKeyParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceKeyParameters.java
deleted file mode 100644
index 007e743e..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceKeyParameters.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.pqc.crypto.mceliece;
-
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-
-
-public class McElieceKeyParameters
- extends AsymmetricKeyParameter
-{
- private McElieceParameters params;
-
- public McElieceKeyParameters(
- boolean isPrivate,
- McElieceParameters params)
- {
- super(isPrivate);
- this.params = params;
- }
-
-
- public McElieceParameters getParameters()
- {
- return params;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceKobaraImaiCipher.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceKobaraImaiCipher.java
deleted file mode 100644
index fe3ebf94..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceKobaraImaiCipher.java
+++ /dev/null
@@ -1,319 +0,0 @@
-package org.bouncycastle.pqc.crypto.mceliece;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.prng.DigestRandomGenerator;
-import org.bouncycastle.pqc.crypto.MessageEncryptor;
-import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
-import org.bouncycastle.pqc.math.linearalgebra.GF2Vector;
-import org.bouncycastle.pqc.math.linearalgebra.IntegerFunctions;
-
-/**
- * This class implements the Kobara/Imai conversion of the McEliecePKCS. This is
- * a conversion of the McEliecePKCS which is CCA2-secure. For details, see D.
- * Engelbert, R. Overbeck, A. Schmidt, "A summary of the development of the
- * McEliece Cryptosystem", technical report.
- */
-public class McElieceKobaraImaiCipher
- implements MessageEncryptor
-{
-
- /**
- * The OID of the algorithm.
- */
- public static final String OID = "1.3.6.1.4.1.8301.3.1.3.4.2.3";
-
- private static final String DEFAULT_PRNG_NAME = "SHA1PRNG";
-
- /**
- * A predetermined public constant.
- */
- public static final byte[] PUBLIC_CONSTANT = "a predetermined public constant"
- .getBytes();
-
-
- private Digest messDigest;
-
- private SecureRandom sr;
-
- McElieceCCA2KeyParameters key;
-
- /**
- * The McEliece main parameters
- */
- private int n, k, t;
-
-
- public void init(boolean forSigning,
- CipherParameters param)
- {
-
- if (forSigning)
- {
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- this.sr = rParam.getRandom();
- this.key = (McElieceCCA2PublicKeyParameters)rParam.getParameters();
- this.initCipherEncrypt((McElieceCCA2PublicKeyParameters)key);
-
- }
- else
- {
- this.sr = new SecureRandom();
- this.key = (McElieceCCA2PublicKeyParameters)param;
- this.initCipherEncrypt((McElieceCCA2PublicKeyParameters)key);
- }
- }
- else
- {
- this.key = (McElieceCCA2PrivateKeyParameters)param;
- this.initCipherDecrypt((McElieceCCA2PrivateKeyParameters)key);
- }
-
- }
-
- /**
- * Return the key size of the given key object.
- *
- * @param key the McElieceCCA2KeyParameters object
- * @return the key size of the given key object
- */
- public int getKeySize(McElieceCCA2KeyParameters key)
- {
- if (key instanceof McElieceCCA2PublicKeyParameters)
- {
- return ((McElieceCCA2PublicKeyParameters)key).getN();
-
- }
- if (key instanceof McElieceCCA2PrivateKeyParameters)
- {
- return ((McElieceCCA2PrivateKeyParameters)key).getN();
- }
- throw new IllegalArgumentException("unsupported type");
- }
-
- private void initCipherEncrypt(McElieceCCA2PublicKeyParameters pubKey)
- {
- this.messDigest = pubKey.getParameters().getDigest();
- n = pubKey.getN();
- k = pubKey.getK();
- t = pubKey.getT();
-
- }
-
- public void initCipherDecrypt(McElieceCCA2PrivateKeyParameters privKey)
- {
- this.messDigest = privKey.getParameters().getDigest();
- n = privKey.getN();
- k = privKey.getK();
- t = privKey.getT();
- }
-
- public byte[] messageEncrypt(byte[] input)
- throws Exception
- {
-
- int c2Len = messDigest.getDigestSize();
- int c4Len = k >> 3;
- int c5Len = (IntegerFunctions.binomial(n, t).bitLength() - 1) >> 3;
-
-
- int mLen = c4Len + c5Len - c2Len - PUBLIC_CONSTANT.length;
- if (input.length > mLen)
- {
- mLen = input.length;
- }
-
- int c1Len = mLen + PUBLIC_CONSTANT.length;
- int c6Len = c1Len + c2Len - c4Len - c5Len;
-
- // compute (m||const)
- byte[] mConst = new byte[c1Len];
- System.arraycopy(input, 0, mConst, 0, input.length);
- System.arraycopy(PUBLIC_CONSTANT, 0, mConst, mLen,
- PUBLIC_CONSTANT.length);
-
- // generate random r of length c2Len bytes
- byte[] r = new byte[c2Len];
- sr.nextBytes(r);
-
- // get PRNG object
- // get PRNG object
- DigestRandomGenerator sr0 = new DigestRandomGenerator(new SHA1Digest());
-
- // seed PRNG with r'
- sr0.addSeedMaterial(r);
-
- // generate random sequence ...
- byte[] c1 = new byte[c1Len];
- sr0.nextBytes(c1);
-
- // ... and XOR with (m||const) to obtain c1
- for (int i = c1Len - 1; i >= 0; i--)
- {
- c1[i] ^= mConst[i];
- }
-
- // compute H(c1) ...
- byte[] c2 = new byte[messDigest.getDigestSize()];
- messDigest.update(c1, 0, c1.length);
- messDigest.doFinal(c2, 0);
-
- // ... and XOR with r
- for (int i = c2Len - 1; i >= 0; i--)
- {
- c2[i] ^= r[i];
- }
-
- // compute (c2||c1)
- byte[] c2c1 = ByteUtils.concatenate(c2, c1);
-
- // split (c2||c1) into (c6||c5||c4), where c4Len is k/8 bytes, c5Len is
- // floor[log(n|t)]/8 bytes, and c6Len is c1Len+c2Len-c4Len-c5Len (may be
- // 0).
- byte[] c6 = new byte[0];
- if (c6Len > 0)
- {
- c6 = new byte[c6Len];
- System.arraycopy(c2c1, 0, c6, 0, c6Len);
- }
-
- byte[] c5 = new byte[c5Len];
- System.arraycopy(c2c1, c6Len, c5, 0, c5Len);
-
- byte[] c4 = new byte[c4Len];
- System.arraycopy(c2c1, c6Len + c5Len, c4, 0, c4Len);
-
- // convert c4 to vector over GF(2)
- GF2Vector c4Vec = GF2Vector.OS2VP(k, c4);
-
- // convert c5 to error vector z
- GF2Vector z = Conversions.encode(n, t, c5);
-
- // compute encC4 = E(c4, z)
- byte[] encC4 = McElieceCCA2Primitives.encryptionPrimitive((McElieceCCA2PublicKeyParameters)key,
- c4Vec, z).getEncoded();
-
- // if c6Len > 0
- if (c6Len > 0)
- {
- // return (c6||encC4)
- return ByteUtils.concatenate(c6, encC4);
- }
- // else, return encC4
- return encC4;
- }
-
-
- public byte[] messageDecrypt(byte[] input)
- throws Exception
- {
-
- int nDiv8 = n >> 3;
-
- if (input.length < nDiv8)
- {
- throw new Exception("Bad Padding: Ciphertext too short.");
- }
-
- int c2Len = messDigest.getDigestSize();
- int c4Len = k >> 3;
- int c6Len = input.length - nDiv8;
-
- // split cipher text (c6||encC4), where c6 may be empty
- byte[] c6, encC4;
- if (c6Len > 0)
- {
- byte[][] c6EncC4 = ByteUtils.split(input, c6Len);
- c6 = c6EncC4[0];
- encC4 = c6EncC4[1];
- }
- else
- {
- c6 = new byte[0];
- encC4 = input;
- }
-
- // convert encC4 into vector over GF(2)
- GF2Vector encC4Vec = GF2Vector.OS2VP(n, encC4);
-
- // decrypt encC4Vec to obtain c4 and error vector z
- GF2Vector[] c4z = McElieceCCA2Primitives.decryptionPrimitive((McElieceCCA2PrivateKeyParameters)key,
- encC4Vec);
- byte[] c4 = c4z[0].getEncoded();
- GF2Vector z = c4z[1];
-
- // if length of c4 is greater than c4Len (because of padding) ...
- if (c4.length > c4Len)
- {
- // ... truncate the padding bytes
- c4 = ByteUtils.subArray(c4, 0, c4Len);
- }
-
- // compute c5 = Conv^-1(z)
- byte[] c5 = Conversions.decode(n, t, z);
-
- // compute (c6||c5||c4)
- byte[] c6c5c4 = ByteUtils.concatenate(c6, c5);
- c6c5c4 = ByteUtils.concatenate(c6c5c4, c4);
-
- // split (c6||c5||c4) into (c2||c1), where c2Len = mdLen and c1Len =
- // input.length-c2Len bytes.
- int c1Len = c6c5c4.length - c2Len;
- byte[][] c2c1 = ByteUtils.split(c6c5c4, c2Len);
- byte[] c2 = c2c1[0];
- byte[] c1 = c2c1[1];
-
- // compute H(c1) ...
- byte[] rPrime = new byte[messDigest.getDigestSize()];
- messDigest.update(c1, 0, c1.length);
- messDigest.doFinal(rPrime, 0);
-
- // ... and XOR with c2 to obtain r'
- for (int i = c2Len - 1; i >= 0; i--)
- {
- rPrime[i] ^= c2[i];
- }
-
- // get PRNG object
- DigestRandomGenerator sr0 = new DigestRandomGenerator(new SHA1Digest());
-
- // seed PRNG with r'
- sr0.addSeedMaterial(rPrime);
-
- // generate random sequence R(r') ...
- byte[] mConstPrime = new byte[c1Len];
- sr0.nextBytes(mConstPrime);
-
- // ... and XOR with c1 to obtain (m||const')
- for (int i = c1Len - 1; i >= 0; i--)
- {
- mConstPrime[i] ^= c1[i];
- }
-
- if (mConstPrime.length < c1Len)
- {
- throw new Exception("Bad Padding: invalid ciphertext");
- }
-
- byte[][] temp = ByteUtils.split(mConstPrime, c1Len
- - PUBLIC_CONSTANT.length);
- byte[] mr = temp[0];
- byte[] constPrime = temp[1];
-
- if (!ByteUtils.equals(constPrime, PUBLIC_CONSTANT))
- {
- throw new Exception("Bad Padding: invalid ciphertext");
- }
-
- return mr;
- }
-
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceKobaraImaiDigestCipher.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceKobaraImaiDigestCipher.java
deleted file mode 100644
index 365f387c..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceKobaraImaiDigestCipher.java
+++ /dev/null
@@ -1,128 +0,0 @@
-package org.bouncycastle.pqc.crypto.mceliece;
-
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.pqc.crypto.MessageEncryptor;
-
-// TODO should implement some interface?
-public class McElieceKobaraImaiDigestCipher
-{
-
- private final Digest messDigest;
-
- private final MessageEncryptor mcElieceCCA2Cipher;
-
- private boolean forEncrypting;
-
-
- public McElieceKobaraImaiDigestCipher(MessageEncryptor mcElieceCCA2Cipher, Digest messDigest)
- {
- this.mcElieceCCA2Cipher = mcElieceCCA2Cipher;
- this.messDigest = messDigest;
- }
-
-
- public void init(boolean forEncrypting,
- CipherParameters param)
- {
-
- this.forEncrypting = forEncrypting;
- AsymmetricKeyParameter k;
-
- if (param instanceof ParametersWithRandom)
- {
- k = (AsymmetricKeyParameter)((ParametersWithRandom)param).getParameters();
- }
- else
- {
- k = (AsymmetricKeyParameter)param;
- }
-
- if (forEncrypting && k.isPrivate())
- {
- throw new IllegalArgumentException("Encrypting Requires Public Key.");
- }
-
- if (!forEncrypting && !k.isPrivate())
- {
- throw new IllegalArgumentException("Decrypting Requires Private Key.");
- }
-
- reset();
-
- mcElieceCCA2Cipher.init(forEncrypting, param);
- }
-
-
- public byte[] messageEncrypt()
- {
- if (!forEncrypting)
- {
- throw new IllegalStateException("McElieceKobaraImaiDigestCipher not initialised for encrypting.");
- }
-
- byte[] hash = new byte[messDigest.getDigestSize()];
- messDigest.doFinal(hash, 0);
- byte[] enc = null;
-
- try
- {
- enc = mcElieceCCA2Cipher.messageEncrypt(hash);
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
-
-
- return enc;
- }
-
-
- public byte[] messageDecrypt(byte[] ciphertext)
- {
- byte[] output = null;
- if (forEncrypting)
- {
- throw new IllegalStateException("McElieceKobaraImaiDigestCipher not initialised for decrypting.");
- }
-
-
- try
- {
- output = mcElieceCCA2Cipher.messageDecrypt(ciphertext);
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
-
-
- return output;
- }
-
-
- public void update(byte b)
- {
- messDigest.update(b);
-
- }
-
- public void update(byte[] in, int off, int len)
- {
- messDigest.update(in, off, len);
-
- }
-
-
- public void reset()
- {
- messDigest.reset();
-
- }
-
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePKCSCipher.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePKCSCipher.java
deleted file mode 100644
index 7a6be1be..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePKCSCipher.java
+++ /dev/null
@@ -1,224 +0,0 @@
-package org.bouncycastle.pqc.crypto.mceliece;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.pqc.crypto.MessageEncryptor;
-import org.bouncycastle.pqc.math.linearalgebra.GF2Matrix;
-import org.bouncycastle.pqc.math.linearalgebra.GF2Vector;
-import org.bouncycastle.pqc.math.linearalgebra.GF2mField;
-import org.bouncycastle.pqc.math.linearalgebra.GoppaCode;
-import org.bouncycastle.pqc.math.linearalgebra.Permutation;
-import org.bouncycastle.pqc.math.linearalgebra.PolynomialGF2mSmallM;
-import org.bouncycastle.pqc.math.linearalgebra.Vector;
-
-/**
- * This class implements the McEliece Public Key cryptosystem (McEliecePKCS). It
- * was first described in R.J. McEliece, "A public key cryptosystem based on
- * algebraic coding theory", DSN progress report, 42-44:114-116, 1978. The
- * McEliecePKCS is the first cryptosystem which is based on error correcting
- * codes. The trapdoor for the McEliece cryptosystem using Goppa codes is the
- * knowledge of the Goppa polynomial used to generate the code.
- */
-public class McEliecePKCSCipher
- implements MessageEncryptor
-{
-
- /**
- * The OID of the algorithm.
- */
- public static final String OID = "1.3.6.1.4.1.8301.3.1.3.4.1";
-
-
- // the source of randomness
- private SecureRandom sr;
-
- // the McEliece main parameters
- private int n, k, t;
-
- // The maximum number of bytes the cipher can decrypt
- public int maxPlainTextSize;
-
- // The maximum number of bytes the cipher can encrypt
- public int cipherTextSize;
-
- McElieceKeyParameters key;
-
-
- public void init(boolean forSigning,
- CipherParameters param)
- {
-
- if (forSigning)
- {
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- this.sr = rParam.getRandom();
- this.key = (McEliecePublicKeyParameters)rParam.getParameters();
- this.initCipherEncrypt((McEliecePublicKeyParameters)key);
-
- }
- else
- {
- this.sr = new SecureRandom();
- this.key = (McEliecePublicKeyParameters)param;
- this.initCipherEncrypt((McEliecePublicKeyParameters)key);
- }
- }
- else
- {
- this.key = (McEliecePrivateKeyParameters)param;
- this.initCipherDecrypt((McEliecePrivateKeyParameters)key);
- }
-
- }
-
-
- /**
- * Return the key size of the given key object.
- *
- * @param key the McElieceKeyParameters object
- * @return the keysize of the given key object
- */
-
- public int getKeySize(McElieceKeyParameters key)
- {
-
- if (key instanceof McEliecePublicKeyParameters)
- {
- return ((McEliecePublicKeyParameters)key).getN();
-
- }
- if (key instanceof McEliecePrivateKeyParameters)
- {
- return ((McEliecePrivateKeyParameters)key).getN();
- }
- throw new IllegalArgumentException("unsupported type");
-
- }
-
-
- public void initCipherEncrypt(McEliecePublicKeyParameters pubKey)
- {
- this.sr = sr != null ? sr : new SecureRandom();
- n = pubKey.getN();
- k = pubKey.getK();
- t = pubKey.getT();
- cipherTextSize = n >> 3;
- maxPlainTextSize = (k >> 3);
- }
-
-
- public void initCipherDecrypt(McEliecePrivateKeyParameters privKey)
- {
- n = privKey.getN();
- k = privKey.getK();
-
- maxPlainTextSize = (k >> 3);
- cipherTextSize = n >> 3;
- }
-
- /**
- * Encrypt a plain text.
- *
- * @param input the plain text
- * @return the cipher text
- */
- public byte[] messageEncrypt(byte[] input)
- {
- GF2Vector m = computeMessageRepresentative(input);
- GF2Vector z = new GF2Vector(n, t, sr);
-
- GF2Matrix g = ((McEliecePublicKeyParameters)key).getG();
- Vector mG = g.leftMultiply(m);
- GF2Vector mGZ = (GF2Vector)mG.add(z);
-
- return mGZ.getEncoded();
- }
-
- private GF2Vector computeMessageRepresentative(byte[] input)
- {
- byte[] data = new byte[maxPlainTextSize + ((k & 0x07) != 0 ? 1 : 0)];
- System.arraycopy(input, 0, data, 0, input.length);
- data[input.length] = 0x01;
- return GF2Vector.OS2VP(k, data);
- }
-
- /**
- * Decrypt a cipher text.
- *
- * @param input the cipher text
- * @return the plain text
- * @throws Exception if the cipher text is invalid.
- */
- public byte[] messageDecrypt(byte[] input)
- throws Exception
- {
- GF2Vector vec = GF2Vector.OS2VP(n, input);
- McEliecePrivateKeyParameters privKey = (McEliecePrivateKeyParameters)key;
- GF2mField field = privKey.getField();
- PolynomialGF2mSmallM gp = privKey.getGoppaPoly();
- GF2Matrix sInv = privKey.getSInv();
- Permutation p1 = privKey.getP1();
- Permutation p2 = privKey.getP2();
- GF2Matrix h = privKey.getH();
- PolynomialGF2mSmallM[] qInv = privKey.getQInv();
-
- // compute permutation P = P1 * P2
- Permutation p = p1.rightMultiply(p2);
-
- // compute P^-1
- Permutation pInv = p.computeInverse();
-
- // compute c P^-1
- GF2Vector cPInv = (GF2Vector)vec.multiply(pInv);
-
- // compute syndrome of c P^-1
- GF2Vector syndrome = (GF2Vector)h.rightMultiply(cPInv);
-
- // decode syndrome
- GF2Vector z = GoppaCode.syndromeDecode(syndrome, field, gp, qInv);
- GF2Vector mSG = (GF2Vector)cPInv.add(z);
-
- // multiply codeword with P1 and error vector with P
- mSG = (GF2Vector)mSG.multiply(p1);
- z = (GF2Vector)z.multiply(p);
-
- // extract mS (last k columns of mSG)
- GF2Vector mS = mSG.extractRightVector(k);
-
- // compute plaintext vector
- GF2Vector mVec = (GF2Vector)sInv.leftMultiply(mS);
-
- // compute and return plaintext
- return computeMessage(mVec);
- }
-
- private byte[] computeMessage(GF2Vector mr)
- throws Exception
- {
- byte[] mrBytes = mr.getEncoded();
- // find first non-zero byte
- int index;
- for (index = mrBytes.length - 1; index >= 0 && mrBytes[index] == 0; index--)
- {
- ;
- }
-
- // check if padding byte is valid
- if (mrBytes[index] != 0x01)
- {
- throw new Exception("Bad Padding: invalid ciphertext");
- }
-
- // extract and return message
- byte[] mBytes = new byte[index];
- System.arraycopy(mrBytes, 0, mBytes, 0, index);
- return mBytes;
- }
-
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePKCSDigestCipher.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePKCSDigestCipher.java
deleted file mode 100644
index d8e6ba25..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePKCSDigestCipher.java
+++ /dev/null
@@ -1,128 +0,0 @@
-package org.bouncycastle.pqc.crypto.mceliece;
-
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.pqc.crypto.MessageEncryptor;
-
-// TODO should implement some interface?
-public class McEliecePKCSDigestCipher
-{
-
- private final Digest messDigest;
-
- private final MessageEncryptor mcElieceCipher;
-
- private boolean forEncrypting;
-
-
- public McEliecePKCSDigestCipher(MessageEncryptor mcElieceCipher, Digest messDigest)
- {
- this.mcElieceCipher = mcElieceCipher;
- this.messDigest = messDigest;
- }
-
-
- public void init(boolean forEncrypting,
- CipherParameters param)
- {
-
- this.forEncrypting = forEncrypting;
- AsymmetricKeyParameter k;
-
- if (param instanceof ParametersWithRandom)
- {
- k = (AsymmetricKeyParameter)((ParametersWithRandom)param).getParameters();
- }
- else
- {
- k = (AsymmetricKeyParameter)param;
- }
-
- if (forEncrypting && k.isPrivate())
- {
- throw new IllegalArgumentException("Encrypting Requires Public Key.");
- }
-
- if (!forEncrypting && !k.isPrivate())
- {
- throw new IllegalArgumentException("Decrypting Requires Private Key.");
- }
-
- reset();
-
- mcElieceCipher.init(forEncrypting, param);
- }
-
-
- public byte[] messageEncrypt()
- {
- if (!forEncrypting)
- {
- throw new IllegalStateException("McEliecePKCSDigestCipher not initialised for encrypting.");
- }
-
- byte[] hash = new byte[messDigest.getDigestSize()];
- messDigest.doFinal(hash, 0);
- byte[] enc = null;
-
- try
- {
- enc = mcElieceCipher.messageEncrypt(hash);
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
-
-
- return enc;
- }
-
-
- public byte[] messageDecrypt(byte[] ciphertext)
- {
- byte[] output = null;
- if (forEncrypting)
- {
- throw new IllegalStateException("McEliecePKCSDigestCipher not initialised for decrypting.");
- }
-
-
- try
- {
- output = mcElieceCipher.messageDecrypt(ciphertext);
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
-
-
- return output;
- }
-
-
- public void update(byte b)
- {
- messDigest.update(b);
-
- }
-
- public void update(byte[] in, int off, int len)
- {
- messDigest.update(in, off, len);
-
- }
-
-
- public void reset()
- {
- messDigest.reset();
-
- }
-
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceParameters.java
deleted file mode 100644
index e90c7846..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McElieceParameters.java
+++ /dev/null
@@ -1,181 +0,0 @@
-package org.bouncycastle.pqc.crypto.mceliece;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.pqc.math.linearalgebra.PolynomialRingGF2;
-
-public class McElieceParameters
- implements CipherParameters
-{
-
- /**
- * The default extension degree
- */
- public static final int DEFAULT_M = 11;
-
- /**
- * The default error correcting capability.
- */
- public static final int DEFAULT_T = 50;
-
- /**
- * extension degree of the finite field GF(2^m)
- */
- private int m;
-
- /**
- * error correction capability of the code
- */
- private int t;
-
- /**
- * length of the code
- */
- private int n;
-
- /**
- * the field polynomial
- */
- private int fieldPoly;
-
- /**
- * Constructor. Set the default parameters: extension degree.
- */
- public McElieceParameters()
- {
- this(DEFAULT_M, DEFAULT_T);
- }
-
- /**
- * Constructor.
- *
- * @param keysize the length of a Goppa code
- * @throws IllegalArgumentException if <tt>keysize &lt; 1</tt>.
- */
- public McElieceParameters(int keysize)
- throws IllegalArgumentException
- {
- if (keysize < 1)
- {
- throw new IllegalArgumentException("key size must be positive");
- }
- m = 0;
- n = 1;
- while (n < keysize)
- {
- n <<= 1;
- m++;
- }
- t = n >>> 1;
- t /= m;
- fieldPoly = PolynomialRingGF2.getIrreduciblePolynomial(m);
- }
-
- /**
- * Constructor.
- *
- * @param m degree of the finite field GF(2^m)
- * @param t error correction capability of the code
- * @throws IllegalArgumentException if <tt>m &lt; 1</tt> or <tt>m &gt; 32</tt> or
- * <tt>t &lt; 0</tt> or <tt>t &gt; n</tt>.
- */
- public McElieceParameters(int m, int t)
- throws IllegalArgumentException
- {
- if (m < 1)
- {
- throw new IllegalArgumentException("m must be positive");
- }
- if (m > 32)
- {
- throw new IllegalArgumentException("m is too large");
- }
- this.m = m;
- n = 1 << m;
- if (t < 0)
- {
- throw new IllegalArgumentException("t must be positive");
- }
- if (t > n)
- {
- throw new IllegalArgumentException("t must be less than n = 2^m");
- }
- this.t = t;
- fieldPoly = PolynomialRingGF2.getIrreduciblePolynomial(m);
- }
-
- /**
- * Constructor.
- *
- * @param m degree of the finite field GF(2^m)
- * @param t error correction capability of the code
- * @param poly the field polynomial
- * @throws IllegalArgumentException if <tt>m &lt; 1</tt> or <tt>m &gt; 32</tt> or
- * <tt>t &lt; 0</tt> or <tt>t &gt; n</tt> or
- * <tt>poly</tt> is not an irreducible field polynomial.
- */
- public McElieceParameters(int m, int t, int poly)
- throws IllegalArgumentException
- {
- this.m = m;
- if (m < 1)
- {
- throw new IllegalArgumentException("m must be positive");
- }
- if (m > 32)
- {
- throw new IllegalArgumentException(" m is too large");
- }
- this.n = 1 << m;
- this.t = t;
- if (t < 0)
- {
- throw new IllegalArgumentException("t must be positive");
- }
- if (t > n)
- {
- throw new IllegalArgumentException("t must be less than n = 2^m");
- }
- if ((PolynomialRingGF2.degree(poly) == m)
- && (PolynomialRingGF2.isIrreducible(poly)))
- {
- this.fieldPoly = poly;
- }
- else
- {
- throw new IllegalArgumentException(
- "polynomial is not a field polynomial for GF(2^m)");
- }
- }
-
- /**
- * @return the extension degree of the finite field GF(2^m)
- */
- public int getM()
- {
- return m;
- }
-
- /**
- * @return the length of the code
- */
- public int getN()
- {
- return n;
- }
-
- /**
- * @return the error correction capability of the code
- */
- public int getT()
- {
- return t;
- }
-
- /**
- * @return the field polynomial
- */
- public int getFieldPoly()
- {
- return fieldPoly;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePointchevalCipher.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePointchevalCipher.java
deleted file mode 100644
index 854d79e0..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePointchevalCipher.java
+++ /dev/null
@@ -1,241 +0,0 @@
-package org.bouncycastle.pqc.crypto.mceliece;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.prng.DigestRandomGenerator;
-import org.bouncycastle.pqc.crypto.MessageEncryptor;
-import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
-import org.bouncycastle.pqc.math.linearalgebra.GF2Vector;
-
-/**
- * This class implements the Pointcheval conversion of the McEliecePKCS.
- * Pointcheval presents a generic technique to make a CCA2-secure cryptosystem
- * from any partially trapdoor one-way function in the random oracle model. For
- * details, see D. Engelbert, R. Overbeck, A. Schmidt, "A summary of the
- * development of the McEliece Cryptosystem", technical report.
- */
-public class McEliecePointchevalCipher
- implements MessageEncryptor
-{
-
-
- /**
- * The OID of the algorithm.
- */
- public static final String OID = "1.3.6.1.4.1.8301.3.1.3.4.2.2";
-
- private Digest messDigest;
-
- private SecureRandom sr;
-
- /**
- * The McEliece main parameters
- */
- private int n, k, t;
-
- McElieceCCA2KeyParameters key;
-
- public void init(boolean forSigning,
- CipherParameters param)
- {
-
- if (forSigning)
- {
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- this.sr = rParam.getRandom();
- this.key = (McElieceCCA2PublicKeyParameters)rParam.getParameters();
- this.initCipherEncrypt((McElieceCCA2PublicKeyParameters)key);
-
- }
- else
- {
- this.sr = new SecureRandom();
- this.key = (McElieceCCA2PublicKeyParameters)param;
- this.initCipherEncrypt((McElieceCCA2PublicKeyParameters)key);
- }
- }
- else
- {
- this.key = (McElieceCCA2PrivateKeyParameters)param;
- this.initCipherDecrypt((McElieceCCA2PrivateKeyParameters)key);
- }
-
- }
-
- /**
- * Return the key size of the given key object.
- *
- * @param key the McElieceCCA2KeyParameters object
- * @return the key size of the given key object
- * @throws IllegalArgumentException if the key is invalid
- */
- public int getKeySize(McElieceCCA2KeyParameters key)
- throws IllegalArgumentException
- {
-
- if (key instanceof McElieceCCA2PublicKeyParameters)
- {
- return ((McElieceCCA2PublicKeyParameters)key).getN();
-
- }
- if (key instanceof McElieceCCA2PrivateKeyParameters)
- {
- return ((McElieceCCA2PrivateKeyParameters)key).getN();
- }
- throw new IllegalArgumentException("unsupported type");
-
- }
-
-
- protected int decryptOutputSize(int inLen)
- {
- return 0;
- }
-
- protected int encryptOutputSize(int inLen)
- {
- return 0;
- }
-
-
- public void initCipherEncrypt(McElieceCCA2PublicKeyParameters pubKey)
- {
- this.sr = sr != null ? sr : new SecureRandom();
- this.messDigest = pubKey.getParameters().getDigest();
- n = pubKey.getN();
- k = pubKey.getK();
- t = pubKey.getT();
- }
-
- public void initCipherDecrypt(McElieceCCA2PrivateKeyParameters privKey)
- {
- this.messDigest = privKey.getParameters().getDigest();
- n = privKey.getN();
- k = privKey.getK();
- t = privKey.getT();
- }
-
- public byte[] messageEncrypt(byte[] input)
- throws Exception
- {
-
- int kDiv8 = k >> 3;
-
- // generate random r of length k div 8 bytes
- byte[] r = new byte[kDiv8];
- sr.nextBytes(r);
-
- // generate random vector r' of length k bits
- GF2Vector rPrime = new GF2Vector(k, sr);
-
- // convert r' to byte array
- byte[] rPrimeBytes = rPrime.getEncoded();
-
- // compute (input||r)
- byte[] mr = ByteUtils.concatenate(input, r);
-
- // compute H(input||r)
- messDigest.update(mr, 0, mr.length);
- byte[] hmr = new byte[messDigest.getDigestSize()];
- messDigest.doFinal(hmr, 0);
-
-
- // convert H(input||r) to error vector z
- GF2Vector z = Conversions.encode(n, t, hmr);
-
- // compute c1 = E(rPrime, z)
- byte[] c1 = McElieceCCA2Primitives.encryptionPrimitive((McElieceCCA2PublicKeyParameters)key, rPrime,
- z).getEncoded();
-
- // get PRNG object
- DigestRandomGenerator sr0 = new DigestRandomGenerator(new SHA1Digest());
-
- // seed PRNG with r'
- sr0.addSeedMaterial(rPrimeBytes);
-
- // generate random c2
- byte[] c2 = new byte[input.length + kDiv8];
- sr0.nextBytes(c2);
-
- // XOR with input
- for (int i = 0; i < input.length; i++)
- {
- c2[i] ^= input[i];
- }
- // XOR with r
- for (int i = 0; i < kDiv8; i++)
- {
- c2[input.length + i] ^= r[i];
- }
-
- // return (c1||c2)
- return ByteUtils.concatenate(c1, c2);
- }
-
- public byte[] messageDecrypt(byte[] input)
- throws Exception
- {
-
- int c1Len = (n + 7) >> 3;
- int c2Len = input.length - c1Len;
-
- // split cipher text (c1||c2)
- byte[][] c1c2 = ByteUtils.split(input, c1Len);
- byte[] c1 = c1c2[0];
- byte[] c2 = c1c2[1];
-
- // decrypt c1 ...
- GF2Vector c1Vec = GF2Vector.OS2VP(n, c1);
- GF2Vector[] c1Dec = McElieceCCA2Primitives.decryptionPrimitive((McElieceCCA2PrivateKeyParameters)key,
- c1Vec);
- byte[] rPrimeBytes = c1Dec[0].getEncoded();
- // ... and obtain error vector z
- GF2Vector z = c1Dec[1];
-
- // get PRNG object
- DigestRandomGenerator sr0 = new DigestRandomGenerator(new SHA1Digest());
-
- // seed PRNG with r'
- sr0.addSeedMaterial(rPrimeBytes);
-
- // generate random sequence
- byte[] mrBytes = new byte[c2Len];
- sr0.nextBytes(mrBytes);
-
- // XOR with c2 to obtain (m||r)
- for (int i = 0; i < c2Len; i++)
- {
- mrBytes[i] ^= c2[i];
- }
-
- // compute H(m||r)
- messDigest.update(mrBytes, 0, mrBytes.length);
- byte[] hmr = new byte[messDigest.getDigestSize()];
- messDigest.doFinal(hmr, 0);
-
- // compute Conv(H(m||r))
- c1Vec = Conversions.encode(n, t, hmr);
-
- // check that Conv(H(m||r)) = z
- if (!c1Vec.equals(z))
- {
- throw new Exception("Bad Padding: Invalid ciphertext.");
- }
-
- // split (m||r) to obtain m
- int kDiv8 = k >> 3;
- byte[][] mr = ByteUtils.split(mrBytes, c2Len - kDiv8);
-
- // return plain text m
- return mr[0];
- }
-
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePointchevalDigestCipher.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePointchevalDigestCipher.java
deleted file mode 100644
index 8a1ed62a..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePointchevalDigestCipher.java
+++ /dev/null
@@ -1,128 +0,0 @@
-package org.bouncycastle.pqc.crypto.mceliece;
-
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.pqc.crypto.MessageEncryptor;
-
-// TODO should implement some interface?
-public class McEliecePointchevalDigestCipher
-{
-
- private final Digest messDigest;
-
- private final MessageEncryptor mcElieceCCA2Cipher;
-
- private boolean forEncrypting;
-
-
- public McEliecePointchevalDigestCipher(MessageEncryptor mcElieceCCA2Cipher, Digest messDigest)
- {
- this.mcElieceCCA2Cipher = mcElieceCCA2Cipher;
- this.messDigest = messDigest;
- }
-
-
- public void init(boolean forEncrypting,
- CipherParameters param)
- {
-
- this.forEncrypting = forEncrypting;
- AsymmetricKeyParameter k;
-
- if (param instanceof ParametersWithRandom)
- {
- k = (AsymmetricKeyParameter)((ParametersWithRandom)param).getParameters();
- }
- else
- {
- k = (AsymmetricKeyParameter)param;
- }
-
- if (forEncrypting && k.isPrivate())
- {
- throw new IllegalArgumentException("Encrypting Requires Public Key.");
- }
-
- if (!forEncrypting && !k.isPrivate())
- {
- throw new IllegalArgumentException("Decrypting Requires Private Key.");
- }
-
- reset();
-
- mcElieceCCA2Cipher.init(forEncrypting, param);
- }
-
-
- public byte[] messageEncrypt()
- {
- if (!forEncrypting)
- {
- throw new IllegalStateException("McEliecePointchevalDigestCipher not initialised for encrypting.");
- }
-
- byte[] hash = new byte[messDigest.getDigestSize()];
- messDigest.doFinal(hash, 0);
- byte[] enc = null;
-
- try
- {
- enc = mcElieceCCA2Cipher.messageEncrypt(hash);
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
-
-
- return enc;
- }
-
-
- public byte[] messageDecrypt(byte[] ciphertext)
- {
- byte[] output = null;
- if (forEncrypting)
- {
- throw new IllegalStateException("McEliecePointchevalDigestCipher not initialised for decrypting.");
- }
-
-
- try
- {
- output = mcElieceCCA2Cipher.messageDecrypt(ciphertext);
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
-
-
- return output;
- }
-
-
- public void update(byte b)
- {
- messDigest.update(b);
-
- }
-
- public void update(byte[] in, int off, int len)
- {
- messDigest.update(in, off, len);
-
- }
-
-
- public void reset()
- {
- messDigest.reset();
-
- }
-
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePrivateKeyParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePrivateKeyParameters.java
deleted file mode 100644
index 762c2a25..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePrivateKeyParameters.java
+++ /dev/null
@@ -1,197 +0,0 @@
-package org.bouncycastle.pqc.crypto.mceliece;
-
-import org.bouncycastle.pqc.math.linearalgebra.GF2Matrix;
-import org.bouncycastle.pqc.math.linearalgebra.GF2mField;
-import org.bouncycastle.pqc.math.linearalgebra.Permutation;
-import org.bouncycastle.pqc.math.linearalgebra.PolynomialGF2mSmallM;
-
-
-public class McEliecePrivateKeyParameters
- extends McElieceKeyParameters
-{
-
- // the OID of the algorithm
- private String oid;
-
- // the length of the code
- private int n;
-
- // the dimension of the code, where <tt>k &gt;= n - mt</tt>
- private int k;
-
- // the underlying finite field
- private GF2mField field;
-
- // the irreducible Goppa polynomial
- private PolynomialGF2mSmallM goppaPoly;
-
- // a k x k random binary non-singular matrix
- private GF2Matrix sInv;
-
- // the permutation used to generate the systematic check matrix
- private Permutation p1;
-
- // the permutation used to compute the public generator matrix
- private Permutation p2;
-
- // the canonical check matrix of the code
- private GF2Matrix h;
-
- // the matrix used to compute square roots in <tt>(GF(2^m))^t</tt>
- private PolynomialGF2mSmallM[] qInv;
-
- /**
- * Constructor.
- *
- * @param oid
- * @param n the length of the code
- * @param k the dimension of the code
- * @param field the field polynomial defining the finite field
- * <tt>GF(2<sup>m</sup>)</tt>
- * @param goppaPoly the irreducible Goppa polynomial
- * @param sInv the matrix <tt>S<sup>-1</sup></tt>
- * @param p1 the permutation used to generate the systematic check
- * matrix
- * @param p2 the permutation used to compute the public generator
- * matrix
- * @param h the canonical check matrix
- * @param qInv the matrix used to compute square roots in
- * <tt>(GF(2<sup>m</sup>))<sup>t</sup></tt>
- * @param params McElieceParameters
- */
- public McEliecePrivateKeyParameters(String oid, int n, int k, GF2mField field,
- PolynomialGF2mSmallM goppaPoly, GF2Matrix sInv, Permutation p1,
- Permutation p2, GF2Matrix h, PolynomialGF2mSmallM[] qInv, McElieceParameters params)
- {
- super(true, params);
- this.oid = oid;
- this.k = k;
- this.n = n;
- this.field = field;
- this.goppaPoly = goppaPoly;
- this.sInv = sInv;
- this.p1 = p1;
- this.p2 = p2;
- this.h = h;
- this.qInv = qInv;
- }
-
- /**
- * Constructor (used by the {@link McElieceKeyFactory}).
- *
- * @param oid
- * @param n the length of the code
- * @param k the dimension of the code
- * @param encField the encoded field polynomial defining the finite field
- * <tt>GF(2<sup>m</sup>)</tt>
- * @param encGoppaPoly the encoded irreducible Goppa polynomial
- * @param encSInv the encoded matrix <tt>S<sup>-1</sup></tt>
- * @param encP1 the encoded permutation used to generate the systematic
- * check matrix
- * @param encP2 the encoded permutation used to compute the public
- * generator matrix
- * @param encH the encoded canonical check matrix
- * @param encQInv the encoded matrix used to compute square roots in
- * <tt>(GF(2<sup>m</sup>))<sup>t</sup></tt>
- * @param params McElieceParameters
- */
- public McEliecePrivateKeyParameters(String oid, int n, int k, byte[] encField,
- byte[] encGoppaPoly, byte[] encSInv, byte[] encP1, byte[] encP2,
- byte[] encH, byte[][] encQInv, McElieceParameters params)
- {
- super(true, params);
- this.oid = oid;
- this.n = n;
- this.k = k;
- field = new GF2mField(encField);
- goppaPoly = new PolynomialGF2mSmallM(field, encGoppaPoly);
- sInv = new GF2Matrix(encSInv);
- p1 = new Permutation(encP1);
- p2 = new Permutation(encP2);
- h = new GF2Matrix(encH);
- qInv = new PolynomialGF2mSmallM[encQInv.length];
- for (int i = 0; i < encQInv.length; i++)
- {
- qInv[i] = new PolynomialGF2mSmallM(field, encQInv[i]);
- }
- }
-
- /**
- * @return the length of the code
- */
- public int getN()
- {
- return n;
- }
-
- /**
- * @return the dimension of the code
- */
- public int getK()
- {
- return k;
- }
-
- /**
- * @return the finite field <tt>GF(2<sup>m</sup>)</tt>
- */
- public GF2mField getField()
- {
- return field;
- }
-
- /**
- * @return the irreducible Goppa polynomial
- */
- public PolynomialGF2mSmallM getGoppaPoly()
- {
- return goppaPoly;
- }
-
- /**
- * @return the k x k random binary non-singular matrix S^-1
- */
- public GF2Matrix getSInv()
- {
- return sInv;
- }
-
- /**
- * @return the permutation used to generate the systematic check matrix
- */
- public Permutation getP1()
- {
- return p1;
- }
-
- /**
- * @return the permutation used to compute the public generator matrix
- */
- public Permutation getP2()
- {
- return p2;
- }
-
- /**
- * @return the canonical check matrix H
- */
- public GF2Matrix getH()
- {
- return h;
- }
-
- /**
- * @return the matrix used to compute square roots in
- * <tt>(GF(2<sup>m</sup>))<sup>t</sup></tt>
- */
- public PolynomialGF2mSmallM[] getQInv()
- {
- return qInv;
- }
-
- public String getOIDString()
- {
- return oid;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePublicKeyParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePublicKeyParameters.java
deleted file mode 100644
index 6059e2e8..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/mceliece/McEliecePublicKeyParameters.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.bouncycastle.pqc.crypto.mceliece;
-
-import org.bouncycastle.pqc.math.linearalgebra.GF2Matrix;
-
-
-public class McEliecePublicKeyParameters
- extends McElieceKeyParameters
-{
-
- // the OID of the algorithm
- private String oid;
-
- // the length of the code
- private int n;
-
- // the error correction capability of the code
- private int t;
-
- // the generator matrix
- private GF2Matrix g;
-
- /**
- * Constructor (used by {@link McElieceKeyFactory}).
- *
- * @param oid
- * @param n the length of the code
- * @param t the error correction capability of the code
- * @param g the generator matrix
- * @param params McElieceParameters
- */
- public McEliecePublicKeyParameters(String oid, int n, int t, GF2Matrix g, McElieceParameters params)
- {
- super(false, params);
- this.oid = oid;
- this.n = n;
- this.t = t;
- this.g = new GF2Matrix(g);
- }
-
- /**
- * Constructor (used by {@link McElieceKeyFactory}).
- *
- * @param oid
- * @param n the length of the code
- * @param t the error correction capability of the code
- * @param encG the encoded generator matrix
- * @param params McElieceParameters
- */
- public McEliecePublicKeyParameters(String oid, int t, int n, byte[] encG, McElieceParameters params)
- {
- super(false, params);
- this.oid = oid;
- this.n = n;
- this.t = t;
- this.g = new GF2Matrix(encG);
- }
-
- /**
- * @return the length of the code
- */
- public int getN()
- {
- return n;
- }
-
- /**
- * @return the error correction capability of the code
- */
- public int getT()
- {
- return t;
- }
-
- /**
- * @return the generator matrix
- */
- public GF2Matrix getG()
- {
- return g;
- }
-
- public String getOIDString()
- {
- return oid;
-
- }
-
- /**
- * @return the dimension of the code
- */
- public int getK()
- {
- return g.getNumRows();
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/IndexGenerator.java b/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/IndexGenerator.java
deleted file mode 100644
index 82974b30..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/IndexGenerator.java
+++ /dev/null
@@ -1,239 +0,0 @@
-package org.bouncycastle.pqc.crypto.ntru;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.util.Arrays;
-
-/**
- * An implementation of the Index Generation Function in IEEE P1363.1.
- */
-public class IndexGenerator
-{
- private byte[] seed;
- private int N;
- private int c;
- private int minCallsR;
- private int totLen;
- private int remLen;
- private BitString buf;
- private int counter;
- private boolean initialized;
- private Digest hashAlg;
- private int hLen;
-
- /**
- * Constructs a new index generator.
- *
- * @param seed a seed of arbitrary length to initialize the index generator with
- * @param params NtruEncrypt parameters
- */
- IndexGenerator(byte[] seed, NTRUEncryptionParameters params)
- {
- this.seed = seed;
- N = params.N;
- c = params.c;
- minCallsR = params.minCallsR;
-
- totLen = 0;
- remLen = 0;
- counter = 0;
- hashAlg = params.hashAlg;
-
- hLen = hashAlg.getDigestSize(); // hash length
- initialized = false;
- }
-
- /**
- * Returns a number <code>i</code> such that <code>0 &lt;= i &lt; N</code>.
- *
- * @return
- */
- int nextIndex()
- {
- if (!initialized)
- {
- buf = new BitString();
- byte[] hash = new byte[hashAlg.getDigestSize()];
- while (counter < minCallsR)
- {
- appendHash(buf, hash);
- counter++;
- }
- totLen = minCallsR * 8 * hLen;
- remLen = totLen;
- initialized = true;
- }
-
- while (true)
- {
- totLen += c;
- BitString M = buf.getTrailing(remLen);
- if (remLen < c)
- {
- int tmpLen = c - remLen;
- int cThreshold = counter + (tmpLen + hLen - 1) / hLen;
- byte[] hash = new byte[hashAlg.getDigestSize()];
- while (counter < cThreshold)
- {
- appendHash(M, hash);
- counter++;
- if (tmpLen > 8 * hLen)
- {
- tmpLen -= 8 * hLen;
- }
- }
- remLen = 8 * hLen - tmpLen;
- buf = new BitString();
- buf.appendBits(hash);
- }
- else
- {
- remLen -= c;
- }
-
- int i = M.getLeadingAsInt(c); // assume c<32
- if (i < (1 << c) - ((1 << c) % N))
- {
- return i % N;
- }
- }
- }
-
- private void appendHash(BitString m, byte[] hash)
- {
- hashAlg.update(seed, 0, seed.length);
-
- putInt(hashAlg, counter);
-
- hashAlg.doFinal(hash, 0);
-
- m.appendBits(hash);
- }
-
- private void putInt(Digest hashAlg, int counter)
- {
- hashAlg.update((byte)(counter >> 24));
- hashAlg.update((byte)(counter >> 16));
- hashAlg.update((byte)(counter >> 8));
- hashAlg.update((byte)counter);
- }
-
- /**
- * Represents a string of bits and supports appending, reading the head, and reading the tail.
- */
- public static class BitString
- {
- byte[] bytes = new byte[4];
- int numBytes; // includes the last byte even if only some of its bits are used
- int lastByteBits; // lastByteBits <= 8
-
- /**
- * Appends all bits in a byte array to the end of the bit string.
- *
- * @param bytes a byte array
- */
- void appendBits(byte[] bytes)
- {
- for (int i = 0; i != bytes.length; i++)
- {
- appendBits(bytes[i]);
- }
- }
-
- /**
- * Appends all bits in a byte to the end of the bit string.
- *
- * @param b a byte
- */
- public void appendBits(byte b)
- {
- if (numBytes == bytes.length)
- {
- bytes = copyOf(bytes, 2 * bytes.length);
- }
-
- if (numBytes == 0)
- {
- numBytes = 1;
- bytes[0] = b;
- lastByteBits = 8;
- }
- else if (lastByteBits == 8)
- {
- bytes[numBytes++] = b;
- }
- else
- {
- int s = 8 - lastByteBits;
- bytes[numBytes - 1] |= (b & 0xFF) << lastByteBits;
- bytes[numBytes++] = (byte)((b & 0xFF) >> s);
- }
- }
-
- /**
- * Returns the last <code>numBits</code> bits from the end of the bit string.
- *
- * @param numBits number of bits
- * @return a new <code>BitString</code> of length <code>numBits</code>
- */
- public BitString getTrailing(int numBits)
- {
- BitString newStr = new BitString();
- newStr.numBytes = (numBits + 7) / 8;
- newStr.bytes = new byte[newStr.numBytes];
- for (int i = 0; i < newStr.numBytes; i++)
- {
- newStr.bytes[i] = bytes[i];
- }
-
- newStr.lastByteBits = numBits % 8;
- if (newStr.lastByteBits == 0)
- {
- newStr.lastByteBits = 8;
- }
- else
- {
- int s = 32 - newStr.lastByteBits;
- newStr.bytes[newStr.numBytes - 1] = (byte)(newStr.bytes[newStr.numBytes - 1] << s >>> s);
- }
-
- return newStr;
- }
-
- /**
- * Returns up to 32 bits from the beginning of the bit string.
- *
- * @param numBits number of bits
- * @return an <code>int</code> whose lower <code>numBits</code> bits are the beginning of the bit string
- */
- public int getLeadingAsInt(int numBits)
- {
- int startBit = (numBytes - 1) * 8 + lastByteBits - numBits;
- int startByte = startBit / 8;
-
- int startBitInStartByte = startBit % 8;
- int sum = (bytes[startByte] & 0xFF) >>> startBitInStartByte;
- int shift = 8 - startBitInStartByte;
- for (int i = startByte + 1; i < numBytes; i++)
- {
- sum |= (bytes[i] & 0xFF) << shift;
- shift += 8;
- }
-
- return sum;
- }
-
- public byte[] getBytes()
- {
- return Arrays.clone(bytes);
- }
- }
-
- private static byte[] copyOf(byte[] src, int len)
- {
- byte[] tmp = new byte[len];
-
- System.arraycopy(src, 0, tmp, 0, len < src.length ? len : src.length);
-
- return tmp;
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionKeyGenerationParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionKeyGenerationParameters.java
deleted file mode 100644
index 8d64ae29..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionKeyGenerationParameters.java
+++ /dev/null
@@ -1,463 +0,0 @@
-package org.bouncycastle.pqc.crypto.ntru;
-
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.security.SecureRandom;
-import java.util.Arrays;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.digests.SHA512Digest;
-
-/**
- * A set of parameters for NtruEncrypt. Several predefined parameter sets are available and new ones can be created as well.
- */
-public class NTRUEncryptionKeyGenerationParameters
- extends KeyGenerationParameters
- implements Cloneable
-{
- /**
- * A conservative (in terms of security) parameter set that gives 256 bits of security and is optimized for key size.
- */
- public static final NTRUEncryptionKeyGenerationParameters EES1087EP2 = new NTRUEncryptionKeyGenerationParameters(1087, 2048, 120, 120, 256, 13, 25, 14, true, new byte[]{0, 6, 3}, true, false, new SHA512Digest());
-
- /**
- * A conservative (in terms of security) parameter set that gives 256 bits of security and is a tradeoff between key size and encryption/decryption speed.
- */
- public static final NTRUEncryptionKeyGenerationParameters EES1171EP1 = new NTRUEncryptionKeyGenerationParameters(1171, 2048, 106, 106, 256, 13, 20, 15, true, new byte[]{0, 6, 4}, true, false, new SHA512Digest());
-
- /**
- * A conservative (in terms of security) parameter set that gives 256 bits of security and is optimized for encryption/decryption speed.
- */
- public static final NTRUEncryptionKeyGenerationParameters EES1499EP1 = new NTRUEncryptionKeyGenerationParameters(1499, 2048, 79, 79, 256, 13, 17, 19, true, new byte[]{0, 6, 5}, true, false, new SHA512Digest());
-
- /**
- * A parameter set that gives 128 bits of security and uses simple ternary polynomials.
- */
- public static final NTRUEncryptionKeyGenerationParameters APR2011_439 = new NTRUEncryptionKeyGenerationParameters(439, 2048, 146, 130, 128, 9, 32, 9, true, new byte[]{0, 7, 101}, true, false, new SHA256Digest());
-
- /**
- * Like <code>APR2011_439</code>, this parameter set gives 128 bits of security but uses product-form polynomials and <code>f=1+pF</code>.
- */
- public static final NTRUEncryptionKeyGenerationParameters APR2011_439_FAST = new NTRUEncryptionKeyGenerationParameters(439, 2048, 9, 8, 5, 130, 128, 9, 32, 9, true, new byte[]{0, 7, 101}, true, true, new SHA256Digest());
-
- /**
- * A parameter set that gives 256 bits of security and uses simple ternary polynomials.
- */
- public static final NTRUEncryptionKeyGenerationParameters APR2011_743 = new NTRUEncryptionKeyGenerationParameters(743, 2048, 248, 220, 256, 10, 27, 14, true, new byte[]{0, 7, 105}, false, false, new SHA512Digest());
-
- /**
- * Like <code>APR2011_743</code>, this parameter set gives 256 bits of security but uses product-form polynomials and <code>f=1+pF</code>.
- */
- public static final NTRUEncryptionKeyGenerationParameters APR2011_743_FAST = new NTRUEncryptionKeyGenerationParameters(743, 2048, 11, 11, 15, 220, 256, 10, 27, 14, true, new byte[]{0, 7, 105}, false, true, new SHA512Digest());
-
- public int N, q, df, df1, df2, df3;
- public int dr;
- public int dr1;
- public int dr2;
- public int dr3;
- public int dg;
- int llen;
- public int maxMsgLenBytes;
- public int db;
- public int bufferLenBits;
- int bufferLenTrits;
- public int dm0;
- public int pkLen;
- public int c;
- public int minCallsR;
- public int minCallsMask;
- public boolean hashSeed;
- public byte[] oid;
- public boolean sparse;
- public boolean fastFp;
- public int polyType;
- public Digest hashAlg;
-
- /**
- * Constructs a parameter set that uses ternary private keys (i.e. <code>polyType=SIMPLE</code>).
- *
- * @param N number of polynomial coefficients
- * @param q modulus
- * @param df number of ones in the private polynomial <code>f</code>
- * @param dm0 minimum acceptable number of -1's, 0's, and 1's in the polynomial <code>m'</code> in the last encryption step
- * @param db number of random bits to prepend to the message
- * @param c a parameter for the Index Generation Function ({@link org.bouncycastle.pqc.crypto.ntru.IndexGenerator})
- * @param minCallsR minimum number of hash calls for the IGF to make
- * @param minCallsMask minimum number of calls to generate the masking polynomial
- * @param hashSeed whether to hash the seed in the MGF first (true) or use the seed directly (false)
- * @param oid three bytes that uniquely identify the parameter set
- * @param sparse whether to treat ternary polynomials as sparsely populated ({@link org.bouncycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial} vs {@link org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial})
- * @param fastFp whether <code>f=1+p*F</code> for a ternary <code>F</code> (true) or <code>f</code> is ternary (false)
- * @param hashAlg a valid identifier for a <code>java.security.MessageDigest</code> instance such as <code>SHA-256</code>. The <code>MessageDigest</code> must support the <code>getDigestLength()</code> method.
- */
- public NTRUEncryptionKeyGenerationParameters(int N, int q, int df, int dm0, int db, int c, int minCallsR, int minCallsMask, boolean hashSeed, byte[] oid, boolean sparse, boolean fastFp, Digest hashAlg)
- {
- super(new SecureRandom(), db);
- this.N = N;
- this.q = q;
- this.df = df;
- this.db = db;
- this.dm0 = dm0;
- this.c = c;
- this.minCallsR = minCallsR;
- this.minCallsMask = minCallsMask;
- this.hashSeed = hashSeed;
- this.oid = oid;
- this.sparse = sparse;
- this.fastFp = fastFp;
- this.polyType = NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE;
- this.hashAlg = hashAlg;
- init();
- }
-
- /**
- * Constructs a parameter set that uses product-form private keys (i.e. <code>polyType=PRODUCT</code>).
- *
- * @param N number of polynomial coefficients
- * @param q modulus
- * @param df1 number of ones in the private polynomial <code>f1</code>
- * @param df2 number of ones in the private polynomial <code>f2</code>
- * @param df3 number of ones in the private polynomial <code>f3</code>
- * @param dm0 minimum acceptable number of -1's, 0's, and 1's in the polynomial <code>m'</code> in the last encryption step
- * @param db number of random bits to prepend to the message
- * @param c a parameter for the Index Generation Function ({@link org.bouncycastle.pqc.crypto.ntru.IndexGenerator})
- * @param minCallsR minimum number of hash calls for the IGF to make
- * @param minCallsMask minimum number of calls to generate the masking polynomial
- * @param hashSeed whether to hash the seed in the MGF first (true) or use the seed directly (false)
- * @param oid three bytes that uniquely identify the parameter set
- * @param sparse whether to treat ternary polynomials as sparsely populated ({@link org.bouncycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial} vs {@link org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial})
- * @param fastFp whether <code>f=1+p*F</code> for a ternary <code>F</code> (true) or <code>f</code> is ternary (false)
- * @param hashAlg a valid identifier for a <code>java.security.MessageDigest</code> instance such as <code>SHA-256</code>
- */
- public NTRUEncryptionKeyGenerationParameters(int N, int q, int df1, int df2, int df3, int dm0, int db, int c, int minCallsR, int minCallsMask, boolean hashSeed, byte[] oid, boolean sparse, boolean fastFp, Digest hashAlg)
- {
- super(new SecureRandom(), db);
-
- this.N = N;
- this.q = q;
- this.df1 = df1;
- this.df2 = df2;
- this.df3 = df3;
- this.db = db;
- this.dm0 = dm0;
- this.c = c;
- this.minCallsR = minCallsR;
- this.minCallsMask = minCallsMask;
- this.hashSeed = hashSeed;
- this.oid = oid;
- this.sparse = sparse;
- this.fastFp = fastFp;
- this.polyType = NTRUParameters.TERNARY_POLYNOMIAL_TYPE_PRODUCT;
- this.hashAlg = hashAlg;
- init();
- }
-
- private void init()
- {
- dr = df;
- dr1 = df1;
- dr2 = df2;
- dr3 = df3;
- dg = N / 3;
- llen = 1; // ceil(log2(maxMsgLenBytes))
- maxMsgLenBytes = N * 3 / 2 / 8 - llen - db / 8 - 1;
- bufferLenBits = (N * 3 / 2 + 7) / 8 * 8 + 1;
- bufferLenTrits = N - 1;
- pkLen = db;
- }
-
- /**
- * Reads a parameter set from an input stream.
- *
- * @param is an input stream
- * @throws java.io.IOException
- */
- public NTRUEncryptionKeyGenerationParameters(InputStream is)
- throws IOException
- {
- super(new SecureRandom(), -1);
- DataInputStream dis = new DataInputStream(is);
- N = dis.readInt();
- q = dis.readInt();
- df = dis.readInt();
- df1 = dis.readInt();
- df2 = dis.readInt();
- df3 = dis.readInt();
- db = dis.readInt();
- dm0 = dis.readInt();
- c = dis.readInt();
- minCallsR = dis.readInt();
- minCallsMask = dis.readInt();
- hashSeed = dis.readBoolean();
- oid = new byte[3];
- dis.read(oid);
- sparse = dis.readBoolean();
- fastFp = dis.readBoolean();
- polyType = dis.read();
-
- String alg = dis.readUTF();
-
- if ("SHA-512".equals(alg))
- {
- hashAlg = new SHA512Digest();
- }
- else if ("SHA-256".equals(alg))
- {
- hashAlg = new SHA256Digest();
- }
-
- init();
- }
-
- public NTRUEncryptionParameters getEncryptionParameters()
- {
- if (polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE)
- {
- return new NTRUEncryptionParameters(N, q, df, dm0, db, c, minCallsR, minCallsMask, hashSeed, oid, sparse, fastFp, hashAlg);
- }
- else
- {
- return new NTRUEncryptionParameters(N, q, df1, df2, df3, dm0, db, c, minCallsR, minCallsMask, hashSeed, oid, sparse, fastFp, hashAlg);
- }
- }
-
- public NTRUEncryptionKeyGenerationParameters clone()
- {
- if (polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE)
- {
- return new NTRUEncryptionKeyGenerationParameters(N, q, df, dm0, db, c, minCallsR, minCallsMask, hashSeed, oid, sparse, fastFp, hashAlg);
- }
- else
- {
- return new NTRUEncryptionKeyGenerationParameters(N, q, df1, df2, df3, dm0, db, c, minCallsR, minCallsMask, hashSeed, oid, sparse, fastFp, hashAlg);
- }
- }
-
- /**
- * Returns the maximum length a plaintext message can be with this parameter set.
- *
- * @return the maximum length in bytes
- */
- public int getMaxMessageLength()
- {
- return maxMsgLenBytes;
- }
-
- /**
- * Writes the parameter set to an output stream
- *
- * @param os an output stream
- * @throws java.io.IOException
- */
- public void writeTo(OutputStream os)
- throws IOException
- {
- DataOutputStream dos = new DataOutputStream(os);
- dos.writeInt(N);
- dos.writeInt(q);
- dos.writeInt(df);
- dos.writeInt(df1);
- dos.writeInt(df2);
- dos.writeInt(df3);
- dos.writeInt(db);
- dos.writeInt(dm0);
- dos.writeInt(c);
- dos.writeInt(minCallsR);
- dos.writeInt(minCallsMask);
- dos.writeBoolean(hashSeed);
- dos.write(oid);
- dos.writeBoolean(sparse);
- dos.writeBoolean(fastFp);
- dos.write(polyType);
- dos.writeUTF(hashAlg.getAlgorithmName());
- }
-
-
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = prime * result + N;
- result = prime * result + bufferLenBits;
- result = prime * result + bufferLenTrits;
- result = prime * result + c;
- result = prime * result + db;
- result = prime * result + df;
- result = prime * result + df1;
- result = prime * result + df2;
- result = prime * result + df3;
- result = prime * result + dg;
- result = prime * result + dm0;
- result = prime * result + dr;
- result = prime * result + dr1;
- result = prime * result + dr2;
- result = prime * result + dr3;
- result = prime * result + (fastFp ? 1231 : 1237);
- result = prime * result + ((hashAlg == null) ? 0 : hashAlg.getAlgorithmName().hashCode());
- result = prime * result + (hashSeed ? 1231 : 1237);
- result = prime * result + llen;
- result = prime * result + maxMsgLenBytes;
- result = prime * result + minCallsMask;
- result = prime * result + minCallsR;
- result = prime * result + Arrays.hashCode(oid);
- result = prime * result + pkLen;
- result = prime * result + polyType;
- result = prime * result + q;
- result = prime * result + (sparse ? 1231 : 1237);
- return result;
- }
-
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj == null)
- {
- return false;
- }
- if (getClass() != obj.getClass())
- {
- return false;
- }
- NTRUEncryptionKeyGenerationParameters other = (NTRUEncryptionKeyGenerationParameters)obj;
- if (N != other.N)
- {
- return false;
- }
- if (bufferLenBits != other.bufferLenBits)
- {
- return false;
- }
- if (bufferLenTrits != other.bufferLenTrits)
- {
- return false;
- }
- if (c != other.c)
- {
- return false;
- }
- if (db != other.db)
- {
- return false;
- }
- if (df != other.df)
- {
- return false;
- }
- if (df1 != other.df1)
- {
- return false;
- }
- if (df2 != other.df2)
- {
- return false;
- }
- if (df3 != other.df3)
- {
- return false;
- }
- if (dg != other.dg)
- {
- return false;
- }
- if (dm0 != other.dm0)
- {
- return false;
- }
- if (dr != other.dr)
- {
- return false;
- }
- if (dr1 != other.dr1)
- {
- return false;
- }
- if (dr2 != other.dr2)
- {
- return false;
- }
- if (dr3 != other.dr3)
- {
- return false;
- }
- if (fastFp != other.fastFp)
- {
- return false;
- }
- if (hashAlg == null)
- {
- if (other.hashAlg != null)
- {
- return false;
- }
- }
- else if (!hashAlg.getAlgorithmName().equals(other.hashAlg.getAlgorithmName()))
- {
- return false;
- }
- if (hashSeed != other.hashSeed)
- {
- return false;
- }
- if (llen != other.llen)
- {
- return false;
- }
- if (maxMsgLenBytes != other.maxMsgLenBytes)
- {
- return false;
- }
- if (minCallsMask != other.minCallsMask)
- {
- return false;
- }
- if (minCallsR != other.minCallsR)
- {
- return false;
- }
- if (!Arrays.equals(oid, other.oid))
- {
- return false;
- }
- if (pkLen != other.pkLen)
- {
- return false;
- }
- if (polyType != other.polyType)
- {
- return false;
- }
- if (q != other.q)
- {
- return false;
- }
- if (sparse != other.sparse)
- {
- return false;
- }
- return true;
- }
-
- public String toString()
- {
- StringBuilder output = new StringBuilder("EncryptionParameters(N=" + N + " q=" + q);
- if (polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE)
- {
- output.append(" polyType=SIMPLE df=" + df);
- }
- else
- {
- output.append(" polyType=PRODUCT df1=" + df1 + " df2=" + df2 + " df3=" + df3);
- }
- output.append(" dm0=" + dm0 + " db=" + db + " c=" + c + " minCallsR=" + minCallsR + " minCallsMask=" + minCallsMask +
- " hashSeed=" + hashSeed + " hashAlg=" + hashAlg + " oid=" + Arrays.toString(oid) + " sparse=" + sparse + ")");
- return output.toString();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionKeyPairGenerator.java b/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionKeyPairGenerator.java
deleted file mode 100644
index f2751caa..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionKeyPairGenerator.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package org.bouncycastle.pqc.crypto.ntru;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.Polynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.ProductFormPolynomial;
-import org.bouncycastle.pqc.math.ntru.util.Util;
-
-/**
- * Generates key pairs.<br>
- * The parameter p is hardcoded to 3.
- */
-public class NTRUEncryptionKeyPairGenerator
- implements AsymmetricCipherKeyPairGenerator
-{
- private NTRUEncryptionKeyGenerationParameters params;
-
- /**
- * Constructs a new instance with a set of encryption parameters.
- *
- * @param param encryption parameters
- */
- public void init(KeyGenerationParameters param)
- {
- this.params = (NTRUEncryptionKeyGenerationParameters)param;
- }
-
- /**
- * Generates a new encryption key pair.
- *
- * @return a key pair
- */
- public AsymmetricCipherKeyPair generateKeyPair()
- {
- int N = params.N;
- int q = params.q;
- int df = params.df;
- int df1 = params.df1;
- int df2 = params.df2;
- int df3 = params.df3;
- int dg = params.dg;
- boolean fastFp = params.fastFp;
- boolean sparse = params.sparse;
-
- Polynomial t;
- IntegerPolynomial fq;
- IntegerPolynomial fp = null;
-
- // choose a random f that is invertible mod 3 and q
- while (true)
- {
- IntegerPolynomial f;
-
- // choose random t, calculate f and fp
- if (fastFp)
- {
- // if fastFp=true, f is always invertible mod 3
- t = params.polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE ? Util.generateRandomTernary(N, df, df, sparse, params.getRandom()) : ProductFormPolynomial.generateRandom(N, df1, df2, df3, df3, params.getRandom());
- f = t.toIntegerPolynomial();
- f.mult(3);
- f.coeffs[0] += 1;
- }
- else
- {
- t = params.polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE ? Util.generateRandomTernary(N, df, df - 1, sparse, params.getRandom()) : ProductFormPolynomial.generateRandom(N, df1, df2, df3, df3 - 1, params.getRandom());
- f = t.toIntegerPolynomial();
- fp = f.invertF3();
- if (fp == null)
- {
- continue;
- }
- }
-
- fq = f.invertFq(q);
- if (fq == null)
- {
- continue;
- }
- break;
- }
-
- // if fastFp=true, fp=1
- if (fastFp)
- {
- fp = new IntegerPolynomial(N);
- fp.coeffs[0] = 1;
- }
-
- // choose a random g that is invertible mod q
- DenseTernaryPolynomial g;
- while (true)
- {
- g = DenseTernaryPolynomial.generateRandom(N, dg, dg - 1, params.getRandom());
- if (g.invertFq(q) != null)
- {
- break;
- }
- }
-
- IntegerPolynomial h = g.mult(fq, q);
- h.mult3(q);
- h.ensurePositive(q);
- g.clear();
- fq.clear();
-
- NTRUEncryptionPrivateKeyParameters priv = new NTRUEncryptionPrivateKeyParameters(h, t, fp, params.getEncryptionParameters());
- NTRUEncryptionPublicKeyParameters pub = new NTRUEncryptionPublicKeyParameters(h, params.getEncryptionParameters());
- return new AsymmetricCipherKeyPair(pub, priv);
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionKeyParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionKeyParameters.java
deleted file mode 100644
index 27a7987c..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionKeyParameters.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.bouncycastle.pqc.crypto.ntru;
-
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-
-public class NTRUEncryptionKeyParameters
- extends AsymmetricKeyParameter
-{
- final protected NTRUEncryptionParameters params;
-
- public NTRUEncryptionKeyParameters(boolean privateKey, NTRUEncryptionParameters params)
- {
- super(privateKey);
- this.params = params;
- }
-
- public NTRUEncryptionParameters getParameters()
- {
- return params;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionParameters.java
deleted file mode 100644
index b387bc24..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionParameters.java
+++ /dev/null
@@ -1,410 +0,0 @@
-package org.bouncycastle.pqc.crypto.ntru;
-
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Arrays;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.digests.SHA512Digest;
-
-/**
- * A set of parameters for NtruEncrypt. Several predefined parameter sets are available and new ones can be created as well.
- */
-public class NTRUEncryptionParameters
- implements Cloneable
-{
-
- public int N, q, df, df1, df2, df3;
- public int dr;
- public int dr1;
- public int dr2;
- public int dr3;
- public int dg;
- int llen;
- public int maxMsgLenBytes;
- public int db;
- public int bufferLenBits;
- int bufferLenTrits;
- public int dm0;
- public int pkLen;
- public int c;
- public int minCallsR;
- public int minCallsMask;
- public boolean hashSeed;
- public byte[] oid;
- public boolean sparse;
- public boolean fastFp;
- public int polyType;
- public Digest hashAlg;
-
- /**
- * Constructs a parameter set that uses ternary private keys (i.e. <code>polyType=SIMPLE</code>).
- *
- * @param N number of polynomial coefficients
- * @param q modulus
- * @param df number of ones in the private polynomial <code>f</code>
- * @param dm0 minimum acceptable number of -1's, 0's, and 1's in the polynomial <code>m'</code> in the last encryption step
- * @param db number of random bits to prepend to the message
- * @param c a parameter for the Index Generation Function ({@link org.bouncycastle.pqc.crypto.ntru.IndexGenerator})
- * @param minCallsR minimum number of hash calls for the IGF to make
- * @param minCallsMask minimum number of calls to generate the masking polynomial
- * @param hashSeed whether to hash the seed in the MGF first (true) or use the seed directly (false)
- * @param oid three bytes that uniquely identify the parameter set
- * @param sparse whether to treat ternary polynomials as sparsely populated ({@link org.bouncycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial} vs {@link org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial})
- * @param fastFp whether <code>f=1+p*F</code> for a ternary <code>F</code> (true) or <code>f</code> is ternary (false)
- * @param hashAlg a valid identifier for a <code>java.security.MessageDigest</code> instance such as <code>SHA-256</code>. The <code>MessageDigest</code> must support the <code>getDigestLength()</code> method.
- */
- public NTRUEncryptionParameters(int N, int q, int df, int dm0, int db, int c, int minCallsR, int minCallsMask, boolean hashSeed, byte[] oid, boolean sparse, boolean fastFp, Digest hashAlg)
- {
- this.N = N;
- this.q = q;
- this.df = df;
- this.db = db;
- this.dm0 = dm0;
- this.c = c;
- this.minCallsR = minCallsR;
- this.minCallsMask = minCallsMask;
- this.hashSeed = hashSeed;
- this.oid = oid;
- this.sparse = sparse;
- this.fastFp = fastFp;
- this.polyType = NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE;
- this.hashAlg = hashAlg;
- init();
- }
-
- /**
- * Constructs a parameter set that uses product-form private keys (i.e. <code>polyType=PRODUCT</code>).
- *
- * @param N number of polynomial coefficients
- * @param q modulus
- * @param df1 number of ones in the private polynomial <code>f1</code>
- * @param df2 number of ones in the private polynomial <code>f2</code>
- * @param df3 number of ones in the private polynomial <code>f3</code>
- * @param dm0 minimum acceptable number of -1's, 0's, and 1's in the polynomial <code>m'</code> in the last encryption step
- * @param db number of random bits to prepend to the message
- * @param c a parameter for the Index Generation Function ({@link org.bouncycastle.pqc.crypto.ntru.IndexGenerator})
- * @param minCallsR minimum number of hash calls for the IGF to make
- * @param minCallsMask minimum number of calls to generate the masking polynomial
- * @param hashSeed whether to hash the seed in the MGF first (true) or use the seed directly (false)
- * @param oid three bytes that uniquely identify the parameter set
- * @param sparse whether to treat ternary polynomials as sparsely populated ({@link org.bouncycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial} vs {@link org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial})
- * @param fastFp whether <code>f=1+p*F</code> for a ternary <code>F</code> (true) or <code>f</code> is ternary (false)
- * @param hashAlg a valid identifier for a <code>java.security.MessageDigest</code> instance such as <code>SHA-256</code>
- */
- public NTRUEncryptionParameters(int N, int q, int df1, int df2, int df3, int dm0, int db, int c, int minCallsR, int minCallsMask, boolean hashSeed, byte[] oid, boolean sparse, boolean fastFp, Digest hashAlg)
- {
- this.N = N;
- this.q = q;
- this.df1 = df1;
- this.df2 = df2;
- this.df3 = df3;
- this.db = db;
- this.dm0 = dm0;
- this.c = c;
- this.minCallsR = minCallsR;
- this.minCallsMask = minCallsMask;
- this.hashSeed = hashSeed;
- this.oid = oid;
- this.sparse = sparse;
- this.fastFp = fastFp;
- this.polyType = NTRUParameters.TERNARY_POLYNOMIAL_TYPE_PRODUCT;
- this.hashAlg = hashAlg;
- init();
- }
-
- private void init()
- {
- dr = df;
- dr1 = df1;
- dr2 = df2;
- dr3 = df3;
- dg = N / 3;
- llen = 1; // ceil(log2(maxMsgLenBytes))
- maxMsgLenBytes = N * 3 / 2 / 8 - llen - db / 8 - 1;
- bufferLenBits = (N * 3 / 2 + 7) / 8 * 8 + 1;
- bufferLenTrits = N - 1;
- pkLen = db;
- }
-
- /**
- * Reads a parameter set from an input stream.
- *
- * @param is an input stream
- * @throws IOException
- */
- public NTRUEncryptionParameters(InputStream is)
- throws IOException
- {
- DataInputStream dis = new DataInputStream(is);
- N = dis.readInt();
- q = dis.readInt();
- df = dis.readInt();
- df1 = dis.readInt();
- df2 = dis.readInt();
- df3 = dis.readInt();
- db = dis.readInt();
- dm0 = dis.readInt();
- c = dis.readInt();
- minCallsR = dis.readInt();
- minCallsMask = dis.readInt();
- hashSeed = dis.readBoolean();
- oid = new byte[3];
- dis.read(oid);
- sparse = dis.readBoolean();
- fastFp = dis.readBoolean();
- polyType = dis.read();
-
- String alg = dis.readUTF();
-
- if ("SHA-512".equals(alg))
- {
- hashAlg = new SHA512Digest();
- }
- else if ("SHA-256".equals(alg))
- {
- hashAlg = new SHA256Digest();
- }
-
- init();
- }
-
- public NTRUEncryptionParameters clone()
- {
- if (polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE)
- {
- return new NTRUEncryptionParameters(N, q, df, dm0, db, c, minCallsR, minCallsMask, hashSeed, oid, sparse, fastFp, hashAlg);
- }
- else
- {
- return new NTRUEncryptionParameters(N, q, df1, df2, df3, dm0, db, c, minCallsR, minCallsMask, hashSeed, oid, sparse, fastFp, hashAlg);
- }
- }
-
- /**
- * Returns the maximum length a plaintext message can be with this parameter set.
- *
- * @return the maximum length in bytes
- */
- public int getMaxMessageLength()
- {
- return maxMsgLenBytes;
- }
-
- /**
- * Writes the parameter set to an output stream
- *
- * @param os an output stream
- * @throws IOException
- */
- public void writeTo(OutputStream os)
- throws IOException
- {
- DataOutputStream dos = new DataOutputStream(os);
- dos.writeInt(N);
- dos.writeInt(q);
- dos.writeInt(df);
- dos.writeInt(df1);
- dos.writeInt(df2);
- dos.writeInt(df3);
- dos.writeInt(db);
- dos.writeInt(dm0);
- dos.writeInt(c);
- dos.writeInt(minCallsR);
- dos.writeInt(minCallsMask);
- dos.writeBoolean(hashSeed);
- dos.write(oid);
- dos.writeBoolean(sparse);
- dos.writeBoolean(fastFp);
- dos.write(polyType);
- dos.writeUTF(hashAlg.getAlgorithmName());
- }
-
-
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = prime * result + N;
- result = prime * result + bufferLenBits;
- result = prime * result + bufferLenTrits;
- result = prime * result + c;
- result = prime * result + db;
- result = prime * result + df;
- result = prime * result + df1;
- result = prime * result + df2;
- result = prime * result + df3;
- result = prime * result + dg;
- result = prime * result + dm0;
- result = prime * result + dr;
- result = prime * result + dr1;
- result = prime * result + dr2;
- result = prime * result + dr3;
- result = prime * result + (fastFp ? 1231 : 1237);
- result = prime * result + ((hashAlg == null) ? 0 : hashAlg.getAlgorithmName().hashCode());
- result = prime * result + (hashSeed ? 1231 : 1237);
- result = prime * result + llen;
- result = prime * result + maxMsgLenBytes;
- result = prime * result + minCallsMask;
- result = prime * result + minCallsR;
- result = prime * result + Arrays.hashCode(oid);
- result = prime * result + pkLen;
- result = prime * result + polyType;
- result = prime * result + q;
- result = prime * result + (sparse ? 1231 : 1237);
- return result;
- }
-
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj == null)
- {
- return false;
- }
- if (getClass() != obj.getClass())
- {
- return false;
- }
- NTRUEncryptionParameters other = (NTRUEncryptionParameters)obj;
- if (N != other.N)
- {
- return false;
- }
- if (bufferLenBits != other.bufferLenBits)
- {
- return false;
- }
- if (bufferLenTrits != other.bufferLenTrits)
- {
- return false;
- }
- if (c != other.c)
- {
- return false;
- }
- if (db != other.db)
- {
- return false;
- }
- if (df != other.df)
- {
- return false;
- }
- if (df1 != other.df1)
- {
- return false;
- }
- if (df2 != other.df2)
- {
- return false;
- }
- if (df3 != other.df3)
- {
- return false;
- }
- if (dg != other.dg)
- {
- return false;
- }
- if (dm0 != other.dm0)
- {
- return false;
- }
- if (dr != other.dr)
- {
- return false;
- }
- if (dr1 != other.dr1)
- {
- return false;
- }
- if (dr2 != other.dr2)
- {
- return false;
- }
- if (dr3 != other.dr3)
- {
- return false;
- }
- if (fastFp != other.fastFp)
- {
- return false;
- }
- if (hashAlg == null)
- {
- if (other.hashAlg != null)
- {
- return false;
- }
- }
- else if (!hashAlg.getAlgorithmName().equals(other.hashAlg.getAlgorithmName()))
- {
- return false;
- }
- if (hashSeed != other.hashSeed)
- {
- return false;
- }
- if (llen != other.llen)
- {
- return false;
- }
- if (maxMsgLenBytes != other.maxMsgLenBytes)
- {
- return false;
- }
- if (minCallsMask != other.minCallsMask)
- {
- return false;
- }
- if (minCallsR != other.minCallsR)
- {
- return false;
- }
- if (!Arrays.equals(oid, other.oid))
- {
- return false;
- }
- if (pkLen != other.pkLen)
- {
- return false;
- }
- if (polyType != other.polyType)
- {
- return false;
- }
- if (q != other.q)
- {
- return false;
- }
- if (sparse != other.sparse)
- {
- return false;
- }
- return true;
- }
-
- public String toString()
- {
- StringBuilder output = new StringBuilder("EncryptionParameters(N=" + N + " q=" + q);
- if (polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE)
- {
- output.append(" polyType=SIMPLE df=" + df);
- }
- else
- {
- output.append(" polyType=PRODUCT df1=" + df1 + " df2=" + df2 + " df3=" + df3);
- }
- output.append(" dm0=" + dm0 + " db=" + db + " c=" + c + " minCallsR=" + minCallsR + " minCallsMask=" + minCallsMask +
- " hashSeed=" + hashSeed + " hashAlg=" + hashAlg + " oid=" + Arrays.toString(oid) + " sparse=" + sparse + ")");
- return output.toString();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionPrivateKeyParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionPrivateKeyParameters.java
deleted file mode 100644
index bcf9418e..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionPrivateKeyParameters.java
+++ /dev/null
@@ -1,199 +0,0 @@
-package org.bouncycastle.pqc.crypto.ntru;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.Polynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.ProductFormPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial;
-
-/**
- * A NtruEncrypt private key is essentially a polynomial named <code>f</code>
- * which takes different forms depending on whether product-form polynomials are used,
- * and on <code>fastP</code><br>
- * The inverse of <code>f</code> modulo <code>p</code> is precomputed on initialization.
- */
-public class NTRUEncryptionPrivateKeyParameters
- extends NTRUEncryptionKeyParameters
-{
- public Polynomial t;
- public IntegerPolynomial fp;
- public IntegerPolynomial h;
-
- /**
- * Constructs a new private key from a polynomial
- *
- * @param h the public polynomial for the key.
- * @param t the polynomial which determines the key: if <code>fastFp=true</code>, <code>f=1+3t</code>; otherwise, <code>f=t</code>
- * @param fp the inverse of <code>f</code>
- * @param params the NtruEncrypt parameters to use
- */
- public NTRUEncryptionPrivateKeyParameters(IntegerPolynomial h, Polynomial t, IntegerPolynomial fp, NTRUEncryptionParameters params)
- {
- super(true, params);
-
- this.h = h;
- this.t = t;
- this.fp = fp;
- }
-
- /**
- * Converts a byte array to a polynomial <code>f</code> and constructs a new private key
- *
- * @param b an encoded polynomial
- * @param params the NtruEncrypt parameters to use
- * @see #getEncoded()
- */
- public NTRUEncryptionPrivateKeyParameters(byte[] b, NTRUEncryptionParameters params)
- throws IOException
- {
- this(new ByteArrayInputStream(b), params);
- }
-
- /**
- * Reads a polynomial <code>f</code> from an input stream and constructs a new private key
- *
- * @param is an input stream
- * @param params the NtruEncrypt parameters to use
- * @see #writeTo(OutputStream)
- */
- public NTRUEncryptionPrivateKeyParameters(InputStream is, NTRUEncryptionParameters params)
- throws IOException
- {
- super(true, params);
-
- if (params.polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_PRODUCT)
- {
- int N = params.N;
- int df1 = params.df1;
- int df2 = params.df2;
- int df3Ones = params.df3;
- int df3NegOnes = params.fastFp ? params.df3 : params.df3 - 1;
- h = IntegerPolynomial.fromBinary(is, params.N, params.q);
- t = ProductFormPolynomial.fromBinary(is, N, df1, df2, df3Ones, df3NegOnes);
- }
- else
- {
- h = IntegerPolynomial.fromBinary(is, params.N, params.q);
- IntegerPolynomial fInt = IntegerPolynomial.fromBinary3Tight(is, params.N);
- t = params.sparse ? new SparseTernaryPolynomial(fInt) : new DenseTernaryPolynomial(fInt);
- }
-
- init();
- }
-
- /**
- * Initializes <code>fp</code> from t.
- */
- private void init()
- {
- if (params.fastFp)
- {
- fp = new IntegerPolynomial(params.N);
- fp.coeffs[0] = 1;
- }
- else
- {
- fp = t.toIntegerPolynomial().invertF3();
- }
- }
-
- /**
- * Converts the key to a byte array
- *
- * @return the encoded key
- * @see #NTRUEncryptionPrivateKeyParameters(byte[], NTRUEncryptionParameters)
- */
- public byte[] getEncoded()
- {
- byte[] hBytes = h.toBinary(params.q);
- byte[] tBytes;
-
- if (t instanceof ProductFormPolynomial)
- {
- tBytes = ((ProductFormPolynomial)t).toBinary();
- }
- else
- {
- tBytes = t.toIntegerPolynomial().toBinary3Tight();
- }
-
- byte[] res = new byte[hBytes.length + tBytes.length];
-
- System.arraycopy(hBytes, 0, res, 0, hBytes.length);
- System.arraycopy(tBytes, 0, res, hBytes.length, tBytes.length);
-
- return res;
- }
-
- /**
- * Writes the key to an output stream
- *
- * @param os an output stream
- * @throws IOException
- * @see #NTRUEncryptionPrivateKeyParameters(InputStream, NTRUEncryptionParameters)
- */
- public void writeTo(OutputStream os)
- throws IOException
- {
- os.write(getEncoded());
- }
-
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((params == null) ? 0 : params.hashCode());
- result = prime * result + ((t == null) ? 0 : t.hashCode());
- result = prime * result + ((h == null) ? 0 : h.hashCode());
- return result;
- }
-
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj == null)
- {
- return false;
- }
- if (!(obj instanceof NTRUEncryptionPrivateKeyParameters))
- {
- return false;
- }
- NTRUEncryptionPrivateKeyParameters other = (NTRUEncryptionPrivateKeyParameters)obj;
- if (params == null)
- {
- if (other.params != null)
- {
- return false;
- }
- }
- else if (!params.equals(other.params))
- {
- return false;
- }
- if (t == null)
- {
- if (other.t != null)
- {
- return false;
- }
- }
- else if (!t.equals(other.t))
- {
- return false;
- }
- if (!h.equals(other.h))
- {
- return false;
- }
- return true;
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionPublicKeyParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionPublicKeyParameters.java
deleted file mode 100644
index 0aa03573..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEncryptionPublicKeyParameters.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package org.bouncycastle.pqc.crypto.ntru;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-
-/**
- * A NtruEncrypt public key is essentially a polynomial named <code>h</code>.
- */
-public class NTRUEncryptionPublicKeyParameters
- extends NTRUEncryptionKeyParameters
-{
- public IntegerPolynomial h;
-
- /**
- * Constructs a new public key from a polynomial
- *
- * @param h the polynomial <code>h</code> which determines the key
- * @param params the NtruEncrypt parameters to use
- */
- public NTRUEncryptionPublicKeyParameters(IntegerPolynomial h, NTRUEncryptionParameters params)
- {
- super(false, params);
-
- this.h = h;
- }
-
- /**
- * Converts a byte array to a polynomial <code>h</code> and constructs a new public key
- *
- * @param b an encoded polynomial
- * @param params the NtruEncrypt parameters to use
- * @see #getEncoded()
- */
- public NTRUEncryptionPublicKeyParameters(byte[] b, NTRUEncryptionParameters params)
- {
- super(false, params);
-
- h = IntegerPolynomial.fromBinary(b, params.N, params.q);
- }
-
- /**
- * Reads a polynomial <code>h</code> from an input stream and constructs a new public key
- *
- * @param is an input stream
- * @param params the NtruEncrypt parameters to use
- * @see #writeTo(OutputStream)
- */
- public NTRUEncryptionPublicKeyParameters(InputStream is, NTRUEncryptionParameters params)
- throws IOException
- {
- super(false, params);
-
- h = IntegerPolynomial.fromBinary(is, params.N, params.q);
- }
-
- /**
- * Converts the key to a byte array
- *
- * @return the encoded key
- * @see #NTRUEncryptionPublicKeyParameters(byte[], NTRUEncryptionParameters)
- */
- public byte[] getEncoded()
- {
- return h.toBinary(params.q);
- }
-
- /**
- * Writes the key to an output stream
- *
- * @param os an output stream
- * @throws IOException
- * @see #NTRUEncryptionPublicKeyParameters(InputStream, NTRUEncryptionParameters)
- */
- public void writeTo(OutputStream os)
- throws IOException
- {
- os.write(getEncoded());
- }
-
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((h == null) ? 0 : h.hashCode());
- result = prime * result + ((params == null) ? 0 : params.hashCode());
- return result;
- }
-
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj == null)
- {
- return false;
- }
- if (!(obj instanceof NTRUEncryptionPublicKeyParameters))
- {
- return false;
- }
- NTRUEncryptionPublicKeyParameters other = (NTRUEncryptionPublicKeyParameters)obj;
- if (h == null)
- {
- if (other.h != null)
- {
- return false;
- }
- }
- else if (!h.equals(other.h))
- {
- return false;
- }
- if (params == null)
- {
- if (other.params != null)
- {
- return false;
- }
- }
- else if (!params.equals(other.params))
- {
- return false;
- }
- return true;
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEngine.java b/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEngine.java
deleted file mode 100644
index 6c5fe811..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUEngine.java
+++ /dev/null
@@ -1,495 +0,0 @@
-package org.bouncycastle.pqc.crypto.ntru;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.Polynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.ProductFormPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.TernaryPolynomial;
-import org.bouncycastle.util.Arrays;
-
-/**
- * Encrypts, decrypts data and generates key pairs.<br>
- * The parameter p is hardcoded to 3.
- */
-public class NTRUEngine
- implements AsymmetricBlockCipher
-{
- private boolean forEncryption;
- private NTRUEncryptionParameters params;
- private NTRUEncryptionPublicKeyParameters pubKey;
- private NTRUEncryptionPrivateKeyParameters privKey;
- private SecureRandom random;
-
- /**
- * Constructs a new instance with a set of encryption parameters.
- *
- */
- public NTRUEngine()
- {
- }
-
- public void init(boolean forEncryption, CipherParameters parameters)
- {
- this.forEncryption = forEncryption;
- if (forEncryption)
- {
- if (parameters instanceof ParametersWithRandom)
- {
- ParametersWithRandom p = (ParametersWithRandom)parameters;
-
- this.random = p.getRandom();
- this.pubKey = (NTRUEncryptionPublicKeyParameters)p.getParameters();
- }
- else
- {
- this.random = new SecureRandom();
- this.pubKey = (NTRUEncryptionPublicKeyParameters)parameters;
- }
-
- this.params = pubKey.getParameters();
- }
- else
- {
- this.privKey = (NTRUEncryptionPrivateKeyParameters)parameters;
- this.params = privKey.getParameters();
- }
- }
-
- public int getInputBlockSize()
- {
- return params.maxMsgLenBytes;
- }
-
- public int getOutputBlockSize()
- {
- return ((params.N * log2(params.q)) + 7) / 8;
- }
-
- public byte[] processBlock(byte[] in, int inOff, int len)
- throws InvalidCipherTextException
- {
- byte[] tmp = new byte[len];
-
- System.arraycopy(in, inOff, tmp, 0, len);
-
- if (forEncryption)
- {
- return encrypt(tmp, pubKey);
- }
- else
- {
- return decrypt(tmp, privKey);
- }
- }
-
- /**
- * Encrypts a message.<br/>
- * See P1363.1 section 9.2.2.
- *
- * @param m The message to encrypt
- * @param pubKey the public key to encrypt the message with
- * @return the encrypted message
- */
- private byte[] encrypt(byte[] m, NTRUEncryptionPublicKeyParameters pubKey)
- {
- IntegerPolynomial pub = pubKey.h;
- int N = params.N;
- int q = params.q;
-
- int maxLenBytes = params.maxMsgLenBytes;
- int db = params.db;
- int bufferLenBits = params.bufferLenBits;
- int dm0 = params.dm0;
- int pkLen = params.pkLen;
- int minCallsMask = params.minCallsMask;
- boolean hashSeed = params.hashSeed;
- byte[] oid = params.oid;
-
- int l = m.length;
- if (maxLenBytes > 255)
- {
- throw new IllegalArgumentException("llen values bigger than 1 are not supported");
- }
- if (l > maxLenBytes)
- {
- throw new DataLengthException("Message too long: " + l + ">" + maxLenBytes);
- }
-
- while (true)
- {
- // M = b|octL|m|p0
- byte[] b = new byte[db / 8];
- random.nextBytes(b);
- byte[] p0 = new byte[maxLenBytes + 1 - l];
- byte[] M = new byte[bufferLenBits / 8];
-
- System.arraycopy(b, 0, M, 0, b.length);
- M[b.length] = (byte)l;
- System.arraycopy(m, 0, M, b.length + 1, m.length);
- System.arraycopy(p0, 0, M, b.length + 1 + m.length, p0.length);
-
- IntegerPolynomial mTrin = IntegerPolynomial.fromBinary3Sves(M, N);
-
- // sData = OID|m|b|hTrunc
- byte[] bh = pub.toBinary(q);
- byte[] hTrunc = copyOf(bh, pkLen / 8);
- byte[] sData = buildSData(oid, m, l, b, hTrunc);
-
- Polynomial r = generateBlindingPoly(sData, M);
- IntegerPolynomial R = r.mult(pub, q);
- IntegerPolynomial R4 = (IntegerPolynomial)R.clone();
- R4.modPositive(4);
- byte[] oR4 = R4.toBinary(4);
- IntegerPolynomial mask = MGF(oR4, N, minCallsMask, hashSeed);
- mTrin.add(mask);
- mTrin.mod3();
-
- if (mTrin.count(-1) < dm0)
- {
- continue;
- }
- if (mTrin.count(0) < dm0)
- {
- continue;
- }
- if (mTrin.count(1) < dm0)
- {
- continue;
- }
-
- R.add(mTrin, q);
- R.ensurePositive(q);
- return R.toBinary(q);
- }
- }
-
- private byte[] buildSData(byte[] oid, byte[] m, int l, byte[] b, byte[] hTrunc)
- {
- byte[] sData = new byte[oid.length + l + b.length + hTrunc.length];
-
- System.arraycopy(oid, 0, sData, 0, oid.length);
- System.arraycopy(m, 0, sData, oid.length, m.length);
- System.arraycopy(b, 0, sData, oid.length + m.length, b.length);
- System.arraycopy(hTrunc, 0, sData, oid.length + m.length + b.length, hTrunc.length);
- return sData;
- }
-
- protected IntegerPolynomial encrypt(IntegerPolynomial m, TernaryPolynomial r, IntegerPolynomial pubKey)
- {
- IntegerPolynomial e = r.mult(pubKey, params.q);
- e.add(m, params.q);
- e.ensurePositive(params.q);
- return e;
- }
-
- /**
- * Deterministically generates a blinding polynomial from a seed and a message representative.
- *
- * @param seed
- * @param M message representative
- * @return a blinding polynomial
- */
- private Polynomial generateBlindingPoly(byte[] seed, byte[] M)
- {
- IndexGenerator ig = new IndexGenerator(seed, params);
-
- if (params.polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_PRODUCT)
- {
- SparseTernaryPolynomial r1 = new SparseTernaryPolynomial(generateBlindingCoeffs(ig, params.dr1));
- SparseTernaryPolynomial r2 = new SparseTernaryPolynomial(generateBlindingCoeffs(ig, params.dr2));
- SparseTernaryPolynomial r3 = new SparseTernaryPolynomial(generateBlindingCoeffs(ig, params.dr3));
- return new ProductFormPolynomial(r1, r2, r3);
- }
- else
- {
- int dr = params.dr;
- boolean sparse = params.sparse;
- int[] r = generateBlindingCoeffs(ig, dr);
- if (sparse)
- {
- return new SparseTernaryPolynomial(r);
- }
- else
- {
- return new DenseTernaryPolynomial(r);
- }
- }
- }
-
- /**
- * Generates an <code>int</code> array containing <code>dr</code> elements equal to <code>1</code>
- * and <code>dr</code> elements equal to <code>-1</code> using an index generator.
- *
- * @param ig an index generator
- * @param dr number of ones / negative ones
- * @return an array containing numbers between <code>-1</code> and <code>1</code>
- */
- private int[] generateBlindingCoeffs(IndexGenerator ig, int dr)
- {
- int N = params.N;
-
- int[] r = new int[N];
- for (int coeff = -1; coeff <= 1; coeff += 2)
- {
- int t = 0;
- while (t < dr)
- {
- int i = ig.nextIndex();
- if (r[i] == 0)
- {
- r[i] = coeff;
- t++;
- }
- }
- }
-
- return r;
- }
-
- /**
- * An implementation of MGF-TP-1 from P1363.1 section 8.4.1.1.
- *
- * @param seed
- * @param N
- * @param minCallsR
- * @param hashSeed whether to hash the seed
- * @return
- */
- private IntegerPolynomial MGF(byte[] seed, int N, int minCallsR, boolean hashSeed)
- {
- Digest hashAlg = params.hashAlg;
- int hashLen = hashAlg.getDigestSize();
- byte[] buf = new byte[minCallsR * hashLen];
- byte[] Z = hashSeed ? calcHash(hashAlg, seed) : seed;
- int counter = 0;
- while (counter < minCallsR)
- {
- hashAlg.update(Z, 0, Z.length);
- putInt(hashAlg, counter);
-
- byte[] hash = calcHash(hashAlg);
- System.arraycopy(hash, 0, buf, counter * hashLen, hashLen);
- counter++;
- }
-
- IntegerPolynomial i = new IntegerPolynomial(N);
- while (true)
- {
- int cur = 0;
- for (int index = 0; index != buf.length; index++)
- {
- int O = (int)buf[index] & 0xFF;
- if (O >= 243) // 243 = 3^5
- {
- continue;
- }
-
- for (int terIdx = 0; terIdx < 4; terIdx++)
- {
- int rem3 = O % 3;
- i.coeffs[cur] = rem3 - 1;
- cur++;
- if (cur == N)
- {
- return i;
- }
- O = (O - rem3) / 3;
- }
-
- i.coeffs[cur] = O - 1;
- cur++;
- if (cur == N)
- {
- return i;
- }
- }
-
- if (cur >= N)
- {
- return i;
- }
-
- hashAlg.update(Z, 0, Z.length);
- putInt(hashAlg, counter);
-
- byte[] hash = calcHash(hashAlg);
-
- buf = hash;
-
- counter++;
- }
- }
-
- private void putInt(Digest hashAlg, int counter)
- {
- hashAlg.update((byte)(counter >> 24));
- hashAlg.update((byte)(counter >> 16));
- hashAlg.update((byte)(counter >> 8));
- hashAlg.update((byte)counter);
- }
-
- private byte[] calcHash(Digest hashAlg)
- {
- byte[] tmp = new byte[hashAlg.getDigestSize()];
-
- hashAlg.doFinal(tmp, 0);
-
- return tmp;
- }
-
- private byte[] calcHash(Digest hashAlg, byte[] input)
- {
- byte[] tmp = new byte[hashAlg.getDigestSize()];
-
- hashAlg.update(input, 0, input.length);
- hashAlg.doFinal(tmp, 0);
-
- return tmp;
- }
- /**
- * Decrypts a message.<br/>
- * See P1363.1 section 9.2.3.
- *
- * @param data The message to decrypt
- * @param privKey the corresponding private key
- * @return the decrypted message
- * @throws InvalidCipherTextException if the encrypted data is invalid, or <code>maxLenBytes</code> is greater than 255
- */
- private byte[] decrypt(byte[] data, NTRUEncryptionPrivateKeyParameters privKey)
- throws InvalidCipherTextException
- {
- Polynomial priv_t = privKey.t;
- IntegerPolynomial priv_fp = privKey.fp;
- IntegerPolynomial pub = privKey.h;
- int N = params.N;
- int q = params.q;
- int db = params.db;
- int maxMsgLenBytes = params.maxMsgLenBytes;
- int dm0 = params.dm0;
- int pkLen = params.pkLen;
- int minCallsMask = params.minCallsMask;
- boolean hashSeed = params.hashSeed;
- byte[] oid = params.oid;
-
- if (maxMsgLenBytes > 255)
- {
- throw new DataLengthException("maxMsgLenBytes values bigger than 255 are not supported");
- }
-
- int bLen = db / 8;
-
- IntegerPolynomial e = IntegerPolynomial.fromBinary(data, N, q);
- IntegerPolynomial ci = decrypt(e, priv_t, priv_fp);
-
- if (ci.count(-1) < dm0)
- {
- throw new InvalidCipherTextException("Less than dm0 coefficients equal -1");
- }
- if (ci.count(0) < dm0)
- {
- throw new InvalidCipherTextException("Less than dm0 coefficients equal 0");
- }
- if (ci.count(1) < dm0)
- {
- throw new InvalidCipherTextException("Less than dm0 coefficients equal 1");
- }
-
- IntegerPolynomial cR = (IntegerPolynomial)e.clone();
- cR.sub(ci);
- cR.modPositive(q);
- IntegerPolynomial cR4 = (IntegerPolynomial)cR.clone();
- cR4.modPositive(4);
- byte[] coR4 = cR4.toBinary(4);
- IntegerPolynomial mask = MGF(coR4, N, minCallsMask, hashSeed);
- IntegerPolynomial cMTrin = ci;
- cMTrin.sub(mask);
- cMTrin.mod3();
- byte[] cM = cMTrin.toBinary3Sves();
-
- byte[] cb = new byte[bLen];
- System.arraycopy(cM, 0, cb, 0, bLen);
- int cl = cM[bLen] & 0xFF; // llen=1, so read one byte
- if (cl > maxMsgLenBytes)
- {
- throw new InvalidCipherTextException("Message too long: " + cl + ">" + maxMsgLenBytes);
- }
- byte[] cm = new byte[cl];
- System.arraycopy(cM, bLen + 1, cm, 0, cl);
- byte[] p0 = new byte[cM.length - (bLen + 1 + cl)];
- System.arraycopy(cM, bLen + 1 + cl, p0, 0, p0.length);
- if (!Arrays.areEqual(p0, new byte[p0.length]))
- {
- throw new InvalidCipherTextException("The message is not followed by zeroes");
- }
-
- // sData = OID|m|b|hTrunc
- byte[] bh = pub.toBinary(q);
- byte[] hTrunc = copyOf(bh, pkLen / 8);
- byte[] sData = buildSData(oid, cm, cl, cb, hTrunc);
-
- Polynomial cr = generateBlindingPoly(sData, cm);
- IntegerPolynomial cRPrime = cr.mult(pub);
- cRPrime.modPositive(q);
- if (!cRPrime.equals(cR))
- {
- throw new InvalidCipherTextException("Invalid message encoding");
- }
-
- return cm;
- }
-
- /**
- * @param e
- * @param priv_t a polynomial such that if <code>fastFp=true</code>, <code>f=1+3*priv_t</code>; otherwise, <code>f=priv_t</code>
- * @param priv_fp
- * @return
- */
- protected IntegerPolynomial decrypt(IntegerPolynomial e, Polynomial priv_t, IntegerPolynomial priv_fp)
- {
- IntegerPolynomial a;
- if (params.fastFp)
- {
- a = priv_t.mult(e, params.q);
- a.mult(3);
- a.add(e);
- }
- else
- {
- a = priv_t.mult(e, params.q);
- }
- a.center0(params.q);
- a.mod3();
-
- IntegerPolynomial c = params.fastFp ? a : new DenseTernaryPolynomial(a).mult(priv_fp, 3);
- c.center0(3);
- return c;
- }
-
- private byte[] copyOf(byte[] src, int len)
- {
- byte[] tmp = new byte[len];
-
- System.arraycopy(src, 0, tmp, 0, len < src.length ? len : src.length);
-
- return tmp;
- }
-
- private int log2(int value)
- {
- if (value == 2048)
- {
- return 11;
- }
-
- throw new IllegalStateException("log2 not fully implemented");
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUParameters.java
deleted file mode 100644
index 158c0386..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUParameters.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.bouncycastle.pqc.crypto.ntru;
-
-public class NTRUParameters
-{
- public static final int TERNARY_POLYNOMIAL_TYPE_SIMPLE = 0;
- public static final int TERNARY_POLYNOMIAL_TYPE_PRODUCT = 1;
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigner.java b/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigner.java
deleted file mode 100644
index 19bf8024..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigner.java
+++ /dev/null
@@ -1,263 +0,0 @@
-package org.bouncycastle.pqc.crypto.ntru;
-
-import java.nio.ByteBuffer;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.Polynomial;
-
-/**
-* Signs, verifies data and generates key pairs.
-* @deprecated the NTRUSigner algorithm was broken in 2012 by Ducas and Nguyen. See
-* <a href="http://www.di.ens.fr/~ducas/NTRUSign_Cryptanalysis/DucasNguyen_Learning.pdf">
-* http://www.di.ens.fr/~ducas/NTRUSign_Cryptanalysis/DucasNguyen_Learning.pdf</a>
-* for details.
-*/
-public class NTRUSigner
-{
- private NTRUSigningParameters params;
- private Digest hashAlg;
- private NTRUSigningPrivateKeyParameters signingKeyPair;
- private NTRUSigningPublicKeyParameters verificationKey;
-
- /**
- * Constructs a new instance with a set of signature parameters.
- *
- * @param params signature parameters
- */
- public NTRUSigner(NTRUSigningParameters params)
- {
- this.params = params;
- }
-
- /**
- * Resets the engine for signing a message.
- *
- * @param forSigning
- * @param params
- */
- public void init(boolean forSigning, CipherParameters params)
- {
- if (forSigning)
- {
- this.signingKeyPair = (NTRUSigningPrivateKeyParameters)params;
- }
- else
- {
- this.verificationKey = (NTRUSigningPublicKeyParameters)params;
- }
- hashAlg = this.params.hashAlg;
- hashAlg.reset();
- }
-
- /**
- * Adds data to sign or verify.
- *
- * @param b data
- */
- public void update(byte b)
- {
- if (hashAlg == null)
- {
- throw new IllegalStateException("Call initSign or initVerify first!");
- }
-
- hashAlg.update(b);
- }
-
- /**
- * Adds data to sign or verify.
- *
- * @param m data
- * @param off offset
- * @param length number of bytes
- */
- public void update(byte[] m, int off, int length)
- {
- if (hashAlg == null)
- {
- throw new IllegalStateException("Call initSign or initVerify first!");
- }
-
- hashAlg.update(m, off, length);
- }
-
- /**
- * Adds data to sign and computes a signature over this data and any data previously added via {@link #update(byte[], int, int)}.
- *
- * @return a signature
- * @throws IllegalStateException if <code>initSign</code> was not called
- */
- public byte[] generateSignature()
- {
- if (hashAlg == null || signingKeyPair == null)
- {
- throw new IllegalStateException("Call initSign first!");
- }
-
- byte[] msgHash = new byte[hashAlg.getDigestSize()];
-
- hashAlg.doFinal(msgHash, 0);
- return signHash(msgHash, signingKeyPair);
- }
-
- private byte[] signHash(byte[] msgHash, NTRUSigningPrivateKeyParameters kp)
- {
- int r = 0;
- IntegerPolynomial s;
- IntegerPolynomial i;
-
- NTRUSigningPublicKeyParameters kPub = kp.getPublicKey();
- do
- {
- r++;
- if (r > params.signFailTolerance)
- {
- throw new IllegalStateException("Signing failed: too many retries (max=" + params.signFailTolerance + ")");
- }
- i = createMsgRep(msgHash, r);
- s = sign(i, kp);
- }
- while (!verify(i, s, kPub.h));
-
- byte[] rawSig = s.toBinary(params.q);
- ByteBuffer sbuf = ByteBuffer.allocate(rawSig.length + 4);
- sbuf.put(rawSig);
- sbuf.putInt(r);
- return sbuf.array();
- }
-
- private IntegerPolynomial sign(IntegerPolynomial i, NTRUSigningPrivateKeyParameters kp)
- {
- int N = params.N;
- int q = params.q;
- int perturbationBases = params.B;
-
- NTRUSigningPrivateKeyParameters kPriv = kp;
- NTRUSigningPublicKeyParameters kPub = kp.getPublicKey();
-
- IntegerPolynomial s = new IntegerPolynomial(N);
- int iLoop = perturbationBases;
- while (iLoop >= 1)
- {
- Polynomial f = kPriv.getBasis(iLoop).f;
- Polynomial fPrime = kPriv.getBasis(iLoop).fPrime;
-
- IntegerPolynomial y = f.mult(i);
- y.div(q);
- y = fPrime.mult(y);
-
- IntegerPolynomial x = fPrime.mult(i);
- x.div(q);
- x = f.mult(x);
-
- IntegerPolynomial si = y;
- si.sub(x);
- s.add(si);
-
- IntegerPolynomial hi = (IntegerPolynomial)kPriv.getBasis(iLoop).h.clone();
- if (iLoop > 1)
- {
- hi.sub(kPriv.getBasis(iLoop - 1).h);
- }
- else
- {
- hi.sub(kPub.h);
- }
- i = si.mult(hi, q);
-
- iLoop--;
- }
-
- Polynomial f = kPriv.getBasis(0).f;
- Polynomial fPrime = kPriv.getBasis(0).fPrime;
-
- IntegerPolynomial y = f.mult(i);
- y.div(q);
- y = fPrime.mult(y);
-
- IntegerPolynomial x = fPrime.mult(i);
- x.div(q);
- x = f.mult(x);
-
- y.sub(x);
- s.add(y);
- s.modPositive(q);
- return s;
- }
-
- /**
- * Verifies a signature for any data previously added via {@link #update(byte[], int, int)}.
- *
- * @param sig a signature
- * @return whether the signature is valid
- * @throws IllegalStateException if <code>initVerify</code> was not called
- */
- public boolean verifySignature(byte[] sig)
- {
- if (hashAlg == null || verificationKey == null)
- {
- throw new IllegalStateException("Call initVerify first!");
- }
-
- byte[] msgHash = new byte[hashAlg.getDigestSize()];
-
- hashAlg.doFinal(msgHash, 0);
-
- return verifyHash(msgHash, sig, verificationKey);
- }
-
- private boolean verifyHash(byte[] msgHash, byte[] sig, NTRUSigningPublicKeyParameters pub)
- {
- ByteBuffer sbuf = ByteBuffer.wrap(sig);
- byte[] rawSig = new byte[sig.length - 4];
- sbuf.get(rawSig);
- IntegerPolynomial s = IntegerPolynomial.fromBinary(rawSig, params.N, params.q);
- int r = sbuf.getInt();
- return verify(createMsgRep(msgHash, r), s, pub.h);
- }
-
- private boolean verify(IntegerPolynomial i, IntegerPolynomial s, IntegerPolynomial h)
- {
- int q = params.q;
- double normBoundSq = params.normBoundSq;
- double betaSq = params.betaSq;
-
- IntegerPolynomial t = h.mult(s, q);
- t.sub(i);
- long centeredNormSq = (long)(s.centeredNormSq(q) + betaSq * t.centeredNormSq(q));
- return centeredNormSq <= normBoundSq;
- }
-
- protected IntegerPolynomial createMsgRep(byte[] msgHash, int r)
- {
- int N = params.N;
- int q = params.q;
-
- int c = 31 - Integer.numberOfLeadingZeros(q);
- int B = (c + 7) / 8;
- IntegerPolynomial i = new IntegerPolynomial(N);
-
- ByteBuffer cbuf = ByteBuffer.allocate(msgHash.length + 4);
- cbuf.put(msgHash);
- cbuf.putInt(r);
- NTRUSignerPrng prng = new NTRUSignerPrng(cbuf.array(), params.hashAlg);
-
- for (int t = 0; t < N; t++)
- {
- byte[] o = prng.nextBytes(B);
- int hi = o[o.length - 1];
- hi >>= 8 * B - c;
- hi <<= 8 * B - c;
- o[o.length - 1] = (byte)hi;
-
- ByteBuffer obuf = ByteBuffer.allocate(4);
- obuf.put(o);
- obuf.rewind();
- // reverse byte order so it matches the endianness of java ints
- i.coeffs[t] = Integer.reverseBytes(obuf.getInt());
- }
- return i;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSignerPrng.java b/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSignerPrng.java
deleted file mode 100644
index 77ed63a2..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSignerPrng.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.bouncycastle.pqc.crypto.ntru;
-
-import java.nio.ByteBuffer;
-
-import org.bouncycastle.crypto.Digest;
-
-/**
- * An implementation of the deterministic pseudo-random generator in EESS section 3.7.3.1
- */
-public class NTRUSignerPrng
-{
- private int counter;
- private byte[] seed;
- private Digest hashAlg;
-
- /**
- * Constructs a new PRNG and seeds it with a byte array.
- *
- * @param seed a seed
- * @param hashAlg the hash algorithm to use
- */
- NTRUSignerPrng(byte[] seed, Digest hashAlg)
- {
- counter = 0;
- this.seed = seed;
- this.hashAlg = hashAlg;
- }
-
- /**
- * Returns <code>n</code> random bytes
- *
- * @param n number of bytes to return
- * @return the next <code>n</code> random bytes
- */
- byte[] nextBytes(int n)
- {
- ByteBuffer buf = ByteBuffer.allocate(n);
-
- while (buf.hasRemaining())
- {
- ByteBuffer cbuf = ByteBuffer.allocate(seed.length + 4);
- cbuf.put(seed);
- cbuf.putInt(counter);
- byte[] array = cbuf.array();
- byte[] hash = new byte[hashAlg.getDigestSize()];
-
- hashAlg.update(array, 0, array.length);
-
- hashAlg.doFinal(hash, 0);
-
- if (buf.remaining() < hash.length)
- {
- buf.put(hash, 0, buf.remaining());
- }
- else
- {
- buf.put(hash);
- }
- counter++;
- }
-
- return buf.array();
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningKeyGenerationParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningKeyGenerationParameters.java
deleted file mode 100644
index b6ff8c5a..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningKeyGenerationParameters.java
+++ /dev/null
@@ -1,407 +0,0 @@
-package org.bouncycastle.pqc.crypto.ntru;
-
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.security.SecureRandom;
-import java.text.DecimalFormat;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.digests.SHA512Digest;
-
-/**
- * A set of parameters for NtruSign. Several predefined parameter sets are available and new ones can be created as well.
- */
-public class NTRUSigningKeyGenerationParameters
- extends KeyGenerationParameters
- implements Cloneable
-{
- public static final int BASIS_TYPE_STANDARD = 0;
- public static final int BASIS_TYPE_TRANSPOSE = 1;
-
- public static final int KEY_GEN_ALG_RESULTANT = 0;
- public static final int KEY_GEN_ALG_FLOAT = 1;
-
- /**
- * Gives 128 bits of security
- */
- public static final NTRUSigningKeyGenerationParameters APR2011_439 = new NTRUSigningKeyGenerationParameters(439, 2048, 146, 1, BASIS_TYPE_TRANSPOSE, 0.165, 490, 280, false, true, KEY_GEN_ALG_RESULTANT, new SHA256Digest());
-
- /**
- * Like <code>APR2011_439</code>, this parameter set gives 128 bits of security but uses product-form polynomials
- */
- public static final NTRUSigningKeyGenerationParameters APR2011_439_PROD = new NTRUSigningKeyGenerationParameters(439, 2048, 9, 8, 5, 1, BASIS_TYPE_TRANSPOSE, 0.165, 490, 280, false, true, KEY_GEN_ALG_RESULTANT, new SHA256Digest());
-
- /**
- * Gives 256 bits of security
- */
- public static final NTRUSigningKeyGenerationParameters APR2011_743 = new NTRUSigningKeyGenerationParameters(743, 2048, 248, 1, BASIS_TYPE_TRANSPOSE, 0.127, 560, 360, true, false, KEY_GEN_ALG_RESULTANT, new SHA512Digest());
-
- /**
- * Like <code>APR2011_439</code>, this parameter set gives 256 bits of security but uses product-form polynomials
- */
- public static final NTRUSigningKeyGenerationParameters APR2011_743_PROD = new NTRUSigningKeyGenerationParameters(743, 2048, 11, 11, 15, 1, BASIS_TYPE_TRANSPOSE, 0.127, 560, 360, true, false, KEY_GEN_ALG_RESULTANT, new SHA512Digest());
-
- /**
- * Generates key pairs quickly. Use for testing only.
- */
- public static final NTRUSigningKeyGenerationParameters TEST157 = new NTRUSigningKeyGenerationParameters(157, 256, 29, 1, BASIS_TYPE_TRANSPOSE, 0.38, 200, 80, false, false, KEY_GEN_ALG_RESULTANT, new SHA256Digest());
- /**
- * Generates key pairs quickly. Use for testing only.
- */
- public static final NTRUSigningKeyGenerationParameters TEST157_PROD = new NTRUSigningKeyGenerationParameters(157, 256, 5, 5, 8, 1, BASIS_TYPE_TRANSPOSE, 0.38, 200, 80, false, false, KEY_GEN_ALG_RESULTANT, new SHA256Digest());
-
-
- public int N;
- public int q;
- public int d, d1, d2, d3, B;
- double beta;
- public double betaSq;
- double normBound;
- public double normBoundSq;
- public int signFailTolerance = 100;
- double keyNormBound;
- public double keyNormBoundSq;
- public boolean primeCheck; // true if N and 2N+1 are prime
- public int basisType;
- int bitsF = 6; // max #bits needed to encode one coefficient of the polynomial F
- public boolean sparse; // whether to treat ternary polynomials as sparsely populated
- public int keyGenAlg;
- public Digest hashAlg;
- public int polyType;
-
- /**
- * Constructs a parameter set that uses ternary private keys (i.e. <code>polyType=SIMPLE</code>).
- *
- * @param N number of polynomial coefficients
- * @param q modulus
- * @param d number of -1's in the private polynomials <code>f</code> and <code>g</code>
- * @param B number of perturbations
- * @param basisType whether to use the standard or transpose lattice
- * @param beta balancing factor for the transpose lattice
- * @param normBound maximum norm for valid signatures
- * @param keyNormBound maximum norm for the ploynomials <code>F</code> and <code>G</code>
- * @param primeCheck whether <code>2N+1</code> is prime
- * @param sparse whether to treat ternary polynomials as sparsely populated ({@link org.bouncycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial} vs {@link org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial})
- * @param keyGenAlg <code>RESULTANT</code> produces better bases, <code>FLOAT</code> is slightly faster. <code>RESULTANT</code> follows the EESS standard while <code>FLOAT</code> is described in Hoffstein et al: An Introduction to Mathematical Cryptography.
- * @param hashAlg a valid identifier for a <code>java.security.MessageDigest</code> instance such as <code>SHA-256</code>. The <code>MessageDigest</code> must support the <code>getDigestLength()</code> method.
- */
- public NTRUSigningKeyGenerationParameters(int N, int q, int d, int B, int basisType, double beta, double normBound, double keyNormBound, boolean primeCheck, boolean sparse, int keyGenAlg, Digest hashAlg)
- {
- super(new SecureRandom(), N);
- this.N = N;
- this.q = q;
- this.d = d;
- this.B = B;
- this.basisType = basisType;
- this.beta = beta;
- this.normBound = normBound;
- this.keyNormBound = keyNormBound;
- this.primeCheck = primeCheck;
- this.sparse = sparse;
- this.keyGenAlg = keyGenAlg;
- this.hashAlg = hashAlg;
- polyType = NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE;
- init();
- }
-
- /**
- * Constructs a parameter set that uses product-form private keys (i.e. <code>polyType=PRODUCT</code>).
- *
- * @param N number of polynomial coefficients
- * @param q modulus
- * @param d1 number of -1's in the private polynomials <code>f</code> and <code>g</code>
- * @param d2 number of -1's in the private polynomials <code>f</code> and <code>g</code>
- * @param d3 number of -1's in the private polynomials <code>f</code> and <code>g</code>
- * @param B number of perturbations
- * @param basisType whether to use the standard or transpose lattice
- * @param beta balancing factor for the transpose lattice
- * @param normBound maximum norm for valid signatures
- * @param keyNormBound maximum norm for the ploynomials <code>F</code> and <code>G</code>
- * @param primeCheck whether <code>2N+1</code> is prime
- * @param sparse whether to treat ternary polynomials as sparsely populated ({@link org.bouncycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial} vs {@link org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial})
- * @param keyGenAlg <code>RESULTANT</code> produces better bases, <code>FLOAT</code> is slightly faster. <code>RESULTANT</code> follows the EESS standard while <code>FLOAT</code> is described in Hoffstein et al: An Introduction to Mathematical Cryptography.
- * @param hashAlg a valid identifier for a <code>java.security.MessageDigest</code> instance such as <code>SHA-256</code>. The <code>MessageDigest</code> must support the <code>getDigestLength()</code> method.
- */
- public NTRUSigningKeyGenerationParameters(int N, int q, int d1, int d2, int d3, int B, int basisType, double beta, double normBound, double keyNormBound, boolean primeCheck, boolean sparse, int keyGenAlg, Digest hashAlg)
- {
- super(new SecureRandom(), N);
- this.N = N;
- this.q = q;
- this.d1 = d1;
- this.d2 = d2;
- this.d3 = d3;
- this.B = B;
- this.basisType = basisType;
- this.beta = beta;
- this.normBound = normBound;
- this.keyNormBound = keyNormBound;
- this.primeCheck = primeCheck;
- this.sparse = sparse;
- this.keyGenAlg = keyGenAlg;
- this.hashAlg = hashAlg;
- polyType = NTRUParameters.TERNARY_POLYNOMIAL_TYPE_PRODUCT;
- init();
- }
-
- private void init()
- {
- betaSq = beta * beta;
- normBoundSq = normBound * normBound;
- keyNormBoundSq = keyNormBound * keyNormBound;
- }
-
- /**
- * Reads a parameter set from an input stream.
- *
- * @param is an input stream
- * @throws java.io.IOException
- */
- public NTRUSigningKeyGenerationParameters(InputStream is)
- throws IOException
- {
- super(new SecureRandom(), 0); // TODO:
- DataInputStream dis = new DataInputStream(is);
- N = dis.readInt();
- q = dis.readInt();
- d = dis.readInt();
- d1 = dis.readInt();
- d2 = dis.readInt();
- d3 = dis.readInt();
- B = dis.readInt();
- basisType = dis.readInt();
- beta = dis.readDouble();
- normBound = dis.readDouble();
- keyNormBound = dis.readDouble();
- signFailTolerance = dis.readInt();
- primeCheck = dis.readBoolean();
- sparse = dis.readBoolean();
- bitsF = dis.readInt();
- keyGenAlg = dis.read();
- String alg = dis.readUTF();
- if ("SHA-512".equals(alg))
- {
- hashAlg = new SHA512Digest();
- }
- else if ("SHA-256".equals(alg))
- {
- hashAlg = new SHA256Digest();
- }
- polyType = dis.read();
- init();
- }
-
- /**
- * Writes the parameter set to an output stream
- *
- * @param os an output stream
- * @throws java.io.IOException
- */
- public void writeTo(OutputStream os)
- throws IOException
- {
- DataOutputStream dos = new DataOutputStream(os);
- dos.writeInt(N);
- dos.writeInt(q);
- dos.writeInt(d);
- dos.writeInt(d1);
- dos.writeInt(d2);
- dos.writeInt(d3);
- dos.writeInt(B);
- dos.writeInt(basisType);
- dos.writeDouble(beta);
- dos.writeDouble(normBound);
- dos.writeDouble(keyNormBound);
- dos.writeInt(signFailTolerance);
- dos.writeBoolean(primeCheck);
- dos.writeBoolean(sparse);
- dos.writeInt(bitsF);
- dos.write(keyGenAlg);
- dos.writeUTF(hashAlg.getAlgorithmName());
- dos.write(polyType);
- }
-
- public NTRUSigningParameters getSigningParameters()
- {
- return new NTRUSigningParameters(N, q, d, B, beta, normBound, hashAlg);
- }
-
- public NTRUSigningKeyGenerationParameters clone()
- {
- if (polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE)
- {
- return new NTRUSigningKeyGenerationParameters(N, q, d, B, basisType, beta, normBound, keyNormBound, primeCheck, sparse, keyGenAlg, hashAlg);
- }
- else
- {
- return new NTRUSigningKeyGenerationParameters(N, q, d1, d2, d3, B, basisType, beta, normBound, keyNormBound, primeCheck, sparse, keyGenAlg, hashAlg);
- }
- }
-
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = prime * result + B;
- result = prime * result + N;
- result = prime * result + basisType;
- long temp;
- temp = Double.doubleToLongBits(beta);
- result = prime * result + (int)(temp ^ (temp >>> 32));
- temp = Double.doubleToLongBits(betaSq);
- result = prime * result + (int)(temp ^ (temp >>> 32));
- result = prime * result + bitsF;
- result = prime * result + d;
- result = prime * result + d1;
- result = prime * result + d2;
- result = prime * result + d3;
- result = prime * result + ((hashAlg == null) ? 0 : hashAlg.getAlgorithmName().hashCode());
- result = prime * result + keyGenAlg;
- temp = Double.doubleToLongBits(keyNormBound);
- result = prime * result + (int)(temp ^ (temp >>> 32));
- temp = Double.doubleToLongBits(keyNormBoundSq);
- result = prime * result + (int)(temp ^ (temp >>> 32));
- temp = Double.doubleToLongBits(normBound);
- result = prime * result + (int)(temp ^ (temp >>> 32));
- temp = Double.doubleToLongBits(normBoundSq);
- result = prime * result + (int)(temp ^ (temp >>> 32));
- result = prime * result + polyType;
- result = prime * result + (primeCheck ? 1231 : 1237);
- result = prime * result + q;
- result = prime * result + signFailTolerance;
- result = prime * result + (sparse ? 1231 : 1237);
- return result;
- }
-
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj == null)
- {
- return false;
- }
- if (!(obj instanceof NTRUSigningKeyGenerationParameters))
- {
- return false;
- }
- NTRUSigningKeyGenerationParameters other = (NTRUSigningKeyGenerationParameters)obj;
- if (B != other.B)
- {
- return false;
- }
- if (N != other.N)
- {
- return false;
- }
- if (basisType != other.basisType)
- {
- return false;
- }
- if (Double.doubleToLongBits(beta) != Double.doubleToLongBits(other.beta))
- {
- return false;
- }
- if (Double.doubleToLongBits(betaSq) != Double.doubleToLongBits(other.betaSq))
- {
- return false;
- }
- if (bitsF != other.bitsF)
- {
- return false;
- }
- if (d != other.d)
- {
- return false;
- }
- if (d1 != other.d1)
- {
- return false;
- }
- if (d2 != other.d2)
- {
- return false;
- }
- if (d3 != other.d3)
- {
- return false;
- }
- if (hashAlg == null)
- {
- if (other.hashAlg != null)
- {
- return false;
- }
- }
- else if (!hashAlg.getAlgorithmName().equals(other.hashAlg.getAlgorithmName()))
- {
- return false;
- }
- if (keyGenAlg != other.keyGenAlg)
- {
- return false;
- }
- if (Double.doubleToLongBits(keyNormBound) != Double.doubleToLongBits(other.keyNormBound))
- {
- return false;
- }
- if (Double.doubleToLongBits(keyNormBoundSq) != Double.doubleToLongBits(other.keyNormBoundSq))
- {
- return false;
- }
- if (Double.doubleToLongBits(normBound) != Double.doubleToLongBits(other.normBound))
- {
- return false;
- }
- if (Double.doubleToLongBits(normBoundSq) != Double.doubleToLongBits(other.normBoundSq))
- {
- return false;
- }
- if (polyType != other.polyType)
- {
- return false;
- }
- if (primeCheck != other.primeCheck)
- {
- return false;
- }
- if (q != other.q)
- {
- return false;
- }
- if (signFailTolerance != other.signFailTolerance)
- {
- return false;
- }
- if (sparse != other.sparse)
- {
- return false;
- }
- return true;
- }
-
- public String toString()
- {
- DecimalFormat format = new DecimalFormat("0.00");
-
- StringBuilder output = new StringBuilder("SignatureParameters(N=" + N + " q=" + q);
- if (polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE)
- {
- output.append(" polyType=SIMPLE d=" + d);
- }
- else
- {
- output.append(" polyType=PRODUCT d1=" + d1 + " d2=" + d2 + " d3=" + d3);
- }
- output.append(" B=" + B + " basisType=" + basisType + " beta=" + format.format(beta) +
- " normBound=" + format.format(normBound) + " keyNormBound=" + format.format(keyNormBound) +
- " prime=" + primeCheck + " sparse=" + sparse + " keyGenAlg=" + keyGenAlg + " hashAlg=" + hashAlg + ")");
- return output.toString();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningKeyPairGenerator.java b/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningKeyPairGenerator.java
deleted file mode 100644
index 1471509a..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningKeyPairGenerator.java
+++ /dev/null
@@ -1,357 +0,0 @@
-package org.bouncycastle.pqc.crypto.ntru;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.security.SecureRandom;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.pqc.math.ntru.euclid.BigIntEuclidean;
-import org.bouncycastle.pqc.math.ntru.polynomial.BigDecimalPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.BigIntPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.Polynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.ProductFormPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.Resultant;
-
-import static java.math.BigInteger.ONE;
-import static java.math.BigInteger.ZERO;
-
-public class NTRUSigningKeyPairGenerator
- implements AsymmetricCipherKeyPairGenerator
-{
- private NTRUSigningKeyGenerationParameters params;
-
- public void init(KeyGenerationParameters param)
- {
- this.params = (NTRUSigningKeyGenerationParameters)param;
- }
-
- /**
- * Generates a new signature key pair. Starts <code>B+1</code> threads.
- *
- * @return a key pair
- */
- public AsymmetricCipherKeyPair generateKeyPair()
- {
- NTRUSigningPublicKeyParameters pub = null;
- ExecutorService executor = Executors.newCachedThreadPool();
- List<Future<NTRUSigningPrivateKeyParameters.Basis>> bases = new ArrayList<Future<NTRUSigningPrivateKeyParameters.Basis>>();
- for (int k = params.B; k >= 0; k--)
- {
- bases.add(executor.submit(new BasisGenerationTask()));
- }
- executor.shutdown();
-
- List<NTRUSigningPrivateKeyParameters.Basis> basises = new ArrayList<NTRUSigningPrivateKeyParameters.Basis>();
-
- for (int k = params.B; k >= 0; k--)
- {
- Future<NTRUSigningPrivateKeyParameters.Basis> basis = bases.get(k);
- try
- {
- basises.add(basis.get());
- if (k == params.B)
- {
- pub = new NTRUSigningPublicKeyParameters(basis.get().h, params.getSigningParameters());
- }
- }
- catch (Exception e)
- {
- throw new IllegalStateException(e);
- }
- }
- NTRUSigningPrivateKeyParameters priv = new NTRUSigningPrivateKeyParameters(basises, pub);
- AsymmetricCipherKeyPair kp = new AsymmetricCipherKeyPair(pub, priv);
- return kp;
- }
-
- /**
- * Generates a new signature key pair. Runs in a single thread.
- *
- * @return a key pair
- */
- public AsymmetricCipherKeyPair generateKeyPairSingleThread()
- {
- List<NTRUSigningPrivateKeyParameters.Basis> basises = new ArrayList<NTRUSigningPrivateKeyParameters.Basis>();
- NTRUSigningPublicKeyParameters pub = null;
- for (int k = params.B; k >= 0; k--)
- {
- NTRUSigningPrivateKeyParameters.Basis basis = generateBoundedBasis();
- basises.add(basis);
- if (k == 0)
- {
- pub = new NTRUSigningPublicKeyParameters(basis.h, params.getSigningParameters());
- }
- }
- NTRUSigningPrivateKeyParameters priv = new NTRUSigningPrivateKeyParameters(basises, pub);
- return new AsymmetricCipherKeyPair(pub, priv);
- }
-
-
- /**
- * Implementation of the optional steps 20 through 26 in EESS1v2.pdf, section 3.5.1.1.
- * This doesn't seem to have much of an effect and sometimes actually increases the
- * norm of F, but on average it slightly reduces the norm.<br/>
- * This method changes <code>F</code> and <code>g</code> but leaves <code>f</code> and
- * <code>g</code> unchanged.
- *
- * @param f
- * @param g
- * @param F
- * @param G
- * @param N
- */
- private void minimizeFG(IntegerPolynomial f, IntegerPolynomial g, IntegerPolynomial F, IntegerPolynomial G, int N)
- {
- int E = 0;
- for (int j = 0; j < N; j++)
- {
- E += 2 * N * (f.coeffs[j] * f.coeffs[j] + g.coeffs[j] * g.coeffs[j]);
- }
-
- // [f(1)+g(1)]^2 = 4
- E -= 4;
-
- IntegerPolynomial u = (IntegerPolynomial)f.clone();
- IntegerPolynomial v = (IntegerPolynomial)g.clone();
- int j = 0;
- int k = 0;
- int maxAdjustment = N;
- while (k < maxAdjustment && j < N)
- {
- int D = 0;
- int i = 0;
- while (i < N)
- {
- int D1 = F.coeffs[i] * f.coeffs[i];
- int D2 = G.coeffs[i] * g.coeffs[i];
- int D3 = 4 * N * (D1 + D2);
- D += D3;
- i++;
- }
- // f(1)+g(1) = 2
- int D1 = 4 * (F.sumCoeffs() + G.sumCoeffs());
- D -= D1;
-
- if (D > E)
- {
- F.sub(u);
- G.sub(v);
- k++;
- j = 0;
- }
- else if (D < -E)
- {
- F.add(u);
- G.add(v);
- k++;
- j = 0;
- }
- j++;
- u.rotate1();
- v.rotate1();
- }
- }
-
- /**
- * Creates a NTRUSigner basis consisting of polynomials <code>f, g, F, G, h</code>.<br/>
- * If <code>KeyGenAlg=FLOAT</code>, the basis may not be valid and this method must be rerun if that is the case.<br/>
- *
- * @see #generateBoundedBasis()
- */
- private FGBasis generateBasis()
- {
- int N = params.N;
- int q = params.q;
- int d = params.d;
- int d1 = params.d1;
- int d2 = params.d2;
- int d3 = params.d3;
- int basisType = params.basisType;
-
- Polynomial f;
- IntegerPolynomial fInt;
- Polynomial g;
- IntegerPolynomial gInt;
- IntegerPolynomial fq;
- Resultant rf;
- Resultant rg;
- BigIntEuclidean r;
-
- int _2n1 = 2 * N + 1;
- boolean primeCheck = params.primeCheck;
-
- do
- {
- do
- {
- f = params.polyType== NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE ? DenseTernaryPolynomial.generateRandom(N, d + 1, d, new SecureRandom()) : ProductFormPolynomial.generateRandom(N, d1, d2, d3 + 1, d3, new SecureRandom());
- fInt = f.toIntegerPolynomial();
- }
- while (primeCheck && fInt.resultant(_2n1).res.equals(ZERO));
- fq = fInt.invertFq(q);
- }
- while (fq == null);
- rf = fInt.resultant();
-
- do
- {
- do
- {
- do
- {
- g = params.polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE ? DenseTernaryPolynomial.generateRandom(N, d + 1, d, new SecureRandom()) : ProductFormPolynomial.generateRandom(N, d1, d2, d3 + 1, d3, new SecureRandom());
- gInt = g.toIntegerPolynomial();
- }
- while (primeCheck && gInt.resultant(_2n1).res.equals(ZERO));
- }
- while (gInt.invertFq(q) == null);
- rg = gInt.resultant();
- r = BigIntEuclidean.calculate(rf.res, rg.res);
- }
- while (!r.gcd.equals(ONE));
-
- BigIntPolynomial A = (BigIntPolynomial)rf.rho.clone();
- A.mult(r.x.multiply(BigInteger.valueOf(q)));
- BigIntPolynomial B = (BigIntPolynomial)rg.rho.clone();
- B.mult(r.y.multiply(BigInteger.valueOf(-q)));
-
- BigIntPolynomial C;
- if (params.keyGenAlg == NTRUSigningKeyGenerationParameters.KEY_GEN_ALG_RESULTANT)
- {
- int[] fRevCoeffs = new int[N];
- int[] gRevCoeffs = new int[N];
- fRevCoeffs[0] = fInt.coeffs[0];
- gRevCoeffs[0] = gInt.coeffs[0];
- for (int i = 1; i < N; i++)
- {
- fRevCoeffs[i] = fInt.coeffs[N - i];
- gRevCoeffs[i] = gInt.coeffs[N - i];
- }
- IntegerPolynomial fRev = new IntegerPolynomial(fRevCoeffs);
- IntegerPolynomial gRev = new IntegerPolynomial(gRevCoeffs);
-
- IntegerPolynomial t = f.mult(fRev);
- t.add(g.mult(gRev));
- Resultant rt = t.resultant();
- C = fRev.mult(B); // fRev.mult(B) is actually faster than new SparseTernaryPolynomial(fRev).mult(B), possibly due to cache locality?
- C.add(gRev.mult(A));
- C = C.mult(rt.rho);
- C.div(rt.res);
- }
- else
- { // KeyGenAlg.FLOAT
- // calculate ceil(log10(N))
- int log10N = 0;
- for (int i = 1; i < N; i *= 10)
- {
- log10N++;
- }
-
- // * Cdec needs to be accurate to 1 decimal place so it can be correctly rounded;
- // * fInv loses up to (#digits of longest coeff of B) places in fInv.mult(B);
- // * multiplying fInv by B also multiplies the rounding error by a factor of N;
- // so make #decimal places of fInv the sum of the above.
- BigDecimalPolynomial fInv = rf.rho.div(new BigDecimal(rf.res), B.getMaxCoeffLength() + 1 + log10N);
- BigDecimalPolynomial gInv = rg.rho.div(new BigDecimal(rg.res), A.getMaxCoeffLength() + 1 + log10N);
-
- BigDecimalPolynomial Cdec = fInv.mult(B);
- Cdec.add(gInv.mult(A));
- Cdec.halve();
- C = Cdec.round();
- }
-
- BigIntPolynomial F = (BigIntPolynomial)B.clone();
- F.sub(f.mult(C));
- BigIntPolynomial G = (BigIntPolynomial)A.clone();
- G.sub(g.mult(C));
-
- IntegerPolynomial FInt = new IntegerPolynomial(F);
- IntegerPolynomial GInt = new IntegerPolynomial(G);
- minimizeFG(fInt, gInt, FInt, GInt, N);
-
- Polynomial fPrime;
- IntegerPolynomial h;
- if (basisType == NTRUSigningKeyGenerationParameters.BASIS_TYPE_STANDARD)
- {
- fPrime = FInt;
- h = g.mult(fq, q);
- }
- else
- {
- fPrime = g;
- h = FInt.mult(fq, q);
- }
- h.modPositive(q);
-
- return new FGBasis(f, fPrime, h, FInt, GInt, params);
- }
-
- /**
- * Creates a basis such that <code>|F| &lt; keyNormBound</code> and <code>|G| &lt; keyNormBound</code>
- *
- * @return a NTRUSigner basis
- */
- public NTRUSigningPrivateKeyParameters.Basis generateBoundedBasis()
- {
- while (true)
- {
- FGBasis basis = generateBasis();
- if (basis.isNormOk())
- {
- return basis;
- }
- }
- }
-
- private class BasisGenerationTask
- implements Callable<NTRUSigningPrivateKeyParameters.Basis>
- {
-
-
- public NTRUSigningPrivateKeyParameters.Basis call()
- throws Exception
- {
- return generateBoundedBasis();
- }
- }
-
- /**
- * A subclass of Basis that additionally contains the polynomials <code>F</code> and <code>G</code>.
- */
- public class FGBasis
- extends NTRUSigningPrivateKeyParameters.Basis
- {
- public IntegerPolynomial F;
- public IntegerPolynomial G;
-
- FGBasis(Polynomial f, Polynomial fPrime, IntegerPolynomial h, IntegerPolynomial F, IntegerPolynomial G, NTRUSigningKeyGenerationParameters params)
- {
- super(f, fPrime, h, params);
- this.F = F;
- this.G = G;
- }
-
- /**
- * Returns <code>true</code> if the norms of the polynomials <code>F</code> and <code>G</code>
- * are within {@link NTRUSigningKeyGenerationParameters#keyNormBound}.
- *
- * @return
- */
- boolean isNormOk()
- {
- double keyNormBoundSq = params.keyNormBoundSq;
- int q = params.q;
- return (F.centeredNormSq(q) < keyNormBoundSq && G.centeredNormSq(q) < keyNormBoundSq);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningParameters.java
deleted file mode 100644
index 2f018b0f..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningParameters.java
+++ /dev/null
@@ -1,269 +0,0 @@
-package org.bouncycastle.pqc.crypto.ntru;
-
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.text.DecimalFormat;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.digests.SHA512Digest;
-
-/**
- * A set of parameters for NtruSign. Several predefined parameter sets are available and new ones can be created as well.
- */
-public class NTRUSigningParameters
- implements Cloneable
-{
- public int N;
- public int q;
- public int d, d1, d2, d3, B;
- double beta;
- public double betaSq;
- double normBound;
- public double normBoundSq;
- public int signFailTolerance = 100;
- int bitsF = 6; // max #bits needed to encode one coefficient of the polynomial F
- public Digest hashAlg;
-
- /**
- * Constructs a parameter set that uses ternary private keys (i.e. <code>polyType=SIMPLE</code>).
- *
- * @param N number of polynomial coefficients
- * @param q modulus
- * @param d number of -1's in the private polynomials <code>f</code> and <code>g</code>
- * @param B number of perturbations
- * @param beta balancing factor for the transpose lattice
- * @param normBound maximum norm for valid signatures
- * @param hashAlg a valid identifier for a <code>java.security.MessageDigest</code> instance such as <code>SHA-256</code>. The <code>MessageDigest</code> must support the <code>getDigestLength()</code> method.
- */
- public NTRUSigningParameters(int N, int q, int d, int B, double beta, double normBound, Digest hashAlg)
- {
- this.N = N;
- this.q = q;
- this.d = d;
- this.B = B;
- this.beta = beta;
- this.normBound = normBound;
- this.hashAlg = hashAlg;
- init();
- }
-
- /**
- * Constructs a parameter set that uses product-form private keys (i.e. <code>polyType=PRODUCT</code>).
- *
- * @param N number of polynomial coefficients
- * @param q modulus
- * @param d1 number of -1's in the private polynomials <code>f</code> and <code>g</code>
- * @param d2 number of -1's in the private polynomials <code>f</code> and <code>g</code>
- * @param d3 number of -1's in the private polynomials <code>f</code> and <code>g</code>
- * @param B number of perturbations
- * @param beta balancing factor for the transpose lattice
- * @param normBound maximum norm for valid signatures
- * @param keyNormBound maximum norm for the ploynomials <code>F</code> and <code>G</code>
- * @param hashAlg a valid identifier for a <code>java.security.MessageDigest</code> instance such as <code>SHA-256</code>. The <code>MessageDigest</code> must support the <code>getDigestLength()</code> method.
- */
- public NTRUSigningParameters(int N, int q, int d1, int d2, int d3, int B, double beta, double normBound, double keyNormBound, Digest hashAlg)
- {
- this.N = N;
- this.q = q;
- this.d1 = d1;
- this.d2 = d2;
- this.d3 = d3;
- this.B = B;
- this.beta = beta;
- this.normBound = normBound;
- this.hashAlg = hashAlg;
- init();
- }
-
- private void init()
- {
- betaSq = beta * beta;
- normBoundSq = normBound * normBound;
- }
-
- /**
- * Reads a parameter set from an input stream.
- *
- * @param is an input stream
- * @throws IOException
- */
- public NTRUSigningParameters(InputStream is)
- throws IOException
- {
- DataInputStream dis = new DataInputStream(is);
- N = dis.readInt();
- q = dis.readInt();
- d = dis.readInt();
- d1 = dis.readInt();
- d2 = dis.readInt();
- d3 = dis.readInt();
- B = dis.readInt();
- beta = dis.readDouble();
- normBound = dis.readDouble();
- signFailTolerance = dis.readInt();
- bitsF = dis.readInt();
- String alg = dis.readUTF();
- if ("SHA-512".equals(alg))
- {
- hashAlg = new SHA512Digest();
- }
- else if ("SHA-256".equals(alg))
- {
- hashAlg = new SHA256Digest();
- }
- init();
- }
-
- /**
- * Writes the parameter set to an output stream
- *
- * @param os an output stream
- * @throws IOException
- */
- public void writeTo(OutputStream os)
- throws IOException
- {
- DataOutputStream dos = new DataOutputStream(os);
- dos.writeInt(N);
- dos.writeInt(q);
- dos.writeInt(d);
- dos.writeInt(d1);
- dos.writeInt(d2);
- dos.writeInt(d3);
- dos.writeInt(B);
- dos.writeDouble(beta);
- dos.writeDouble(normBound);
- dos.writeInt(signFailTolerance);
- dos.writeInt(bitsF);
- dos.writeUTF(hashAlg.getAlgorithmName());
- }
-
- public NTRUSigningParameters clone()
- {
- return new NTRUSigningParameters(N, q, d, B, beta, normBound, hashAlg);
- }
-
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = prime * result + B;
- result = prime * result + N;
- long temp;
- temp = Double.doubleToLongBits(beta);
- result = prime * result + (int)(temp ^ (temp >>> 32));
- temp = Double.doubleToLongBits(betaSq);
- result = prime * result + (int)(temp ^ (temp >>> 32));
- result = prime * result + bitsF;
- result = prime * result + d;
- result = prime * result + d1;
- result = prime * result + d2;
- result = prime * result + d3;
- result = prime * result + ((hashAlg == null) ? 0 : hashAlg.getAlgorithmName().hashCode());
- temp = Double.doubleToLongBits(normBound);
- result = prime * result + (int)(temp ^ (temp >>> 32));
- temp = Double.doubleToLongBits(normBoundSq);
- result = prime * result + (int)(temp ^ (temp >>> 32));
- result = prime * result + q;
- result = prime * result + signFailTolerance;
- return result;
- }
-
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj == null)
- {
- return false;
- }
- if (!(obj instanceof NTRUSigningParameters))
- {
- return false;
- }
- NTRUSigningParameters other = (NTRUSigningParameters)obj;
- if (B != other.B)
- {
- return false;
- }
- if (N != other.N)
- {
- return false;
- }
- if (Double.doubleToLongBits(beta) != Double.doubleToLongBits(other.beta))
- {
- return false;
- }
- if (Double.doubleToLongBits(betaSq) != Double.doubleToLongBits(other.betaSq))
- {
- return false;
- }
- if (bitsF != other.bitsF)
- {
- return false;
- }
- if (d != other.d)
- {
- return false;
- }
- if (d1 != other.d1)
- {
- return false;
- }
- if (d2 != other.d2)
- {
- return false;
- }
- if (d3 != other.d3)
- {
- return false;
- }
- if (hashAlg == null)
- {
- if (other.hashAlg != null)
- {
- return false;
- }
- }
- else if (!hashAlg.getAlgorithmName().equals(other.hashAlg.getAlgorithmName()))
- {
- return false;
- }
- if (Double.doubleToLongBits(normBound) != Double.doubleToLongBits(other.normBound))
- {
- return false;
- }
- if (Double.doubleToLongBits(normBoundSq) != Double.doubleToLongBits(other.normBoundSq))
- {
- return false;
- }
- if (q != other.q)
- {
- return false;
- }
- if (signFailTolerance != other.signFailTolerance)
- {
- return false;
- }
-
- return true;
- }
-
- public String toString()
- {
- DecimalFormat format = new DecimalFormat("0.00");
-
- StringBuilder output = new StringBuilder("SignatureParameters(N=" + N + " q=" + q);
-
- output.append(" B=" + B + " beta=" + format.format(beta) +
- " normBound=" + format.format(normBound) +
- " hashAlg=" + hashAlg + ")");
- return output.toString();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningPrivateKeyParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningPrivateKeyParameters.java
deleted file mode 100644
index 515f3562..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningPrivateKeyParameters.java
+++ /dev/null
@@ -1,385 +0,0 @@
-package org.bouncycastle.pqc.crypto.ntru;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.Polynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.ProductFormPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial;
-
-/**
- * A NtruSign private key comprises one or more {@link NTRUSigningPrivateKeyParameters.Basis} of three polynomials each,
- * except the zeroth basis for which <code>h</code> is undefined.
- */
-public class NTRUSigningPrivateKeyParameters
- extends AsymmetricKeyParameter
-{
- private List<Basis> bases;
- private NTRUSigningPublicKeyParameters publicKey;
-
- /**
- * Constructs a new private key from a byte array
- *
- * @param b an encoded private key
- * @param params the NtruSign parameters to use
- */
- public NTRUSigningPrivateKeyParameters(byte[] b, NTRUSigningKeyGenerationParameters params)
- throws IOException
- {
- this(new ByteArrayInputStream(b), params);
- }
-
- /**
- * Constructs a new private key from an input stream
- *
- * @param is an input stream
- * @param params the NtruSign parameters to use
- */
- public NTRUSigningPrivateKeyParameters(InputStream is, NTRUSigningKeyGenerationParameters params)
- throws IOException
- {
- super(true);
- bases = new ArrayList<Basis>();
- for (int i = 0; i <= params.B; i++)
- // include a public key h[i] in all bases except for the first one
- {
- add(new Basis(is, params, i != 0));
- }
- publicKey = new NTRUSigningPublicKeyParameters(is, params.getSigningParameters());
- }
-
- public NTRUSigningPrivateKeyParameters(List<Basis> bases, NTRUSigningPublicKeyParameters publicKey)
- {
- super(true);
- this.bases = new ArrayList<Basis>(bases);
- this.publicKey = publicKey;
- }
-
- /**
- * Adds a basis to the key.
- *
- * @param b a NtruSign basis
- */
- private void add(Basis b)
- {
- bases.add(b);
- }
-
- /**
- * Returns the <code>i</code>-th basis
- *
- * @param i the index
- * @return the basis at index <code>i</code>
- */
- public Basis getBasis(int i)
- {
- return bases.get(i);
- }
-
- public NTRUSigningPublicKeyParameters getPublicKey()
- {
- return publicKey;
- }
-
- /**
- * Converts the key to a byte array
- *
- * @return the encoded key
- */
- public byte[] getEncoded()
- throws IOException
- {
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- for (int i = 0; i < bases.size(); i++)
- {
- // all bases except for the first one contain a public key
- bases.get(i).encode(os, i != 0);
- }
-
- os.write(publicKey.getEncoded());
-
- return os.toByteArray();
- }
-
- /**
- * Writes the key to an output stream
- *
- * @param os an output stream
- * @throws IOException
- */
- public void writeTo(OutputStream os)
- throws IOException
- {
- os.write(getEncoded());
- }
-
- @Override
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((bases == null) ? 0 : bases.hashCode());
- for (Basis basis : bases)
- {
- result += basis.hashCode();
- }
- return result;
- }
-
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj == null)
- {
- return false;
- }
- if (getClass() != obj.getClass())
- {
- return false;
- }
- NTRUSigningPrivateKeyParameters other = (NTRUSigningPrivateKeyParameters)obj;
- if (bases == null)
- {
- if (other.bases != null)
- {
- return false;
- }
- }
- if (bases.size() != other.bases.size())
- {
- return false;
- }
- for (int i = 0; i < bases.size(); i++)
- {
- Basis basis1 = bases.get(i);
- Basis basis2 = other.bases.get(i);
- if (!basis1.f.equals(basis2.f))
- {
- return false;
- }
- if (!basis1.fPrime.equals(basis2.fPrime))
- {
- return false;
- }
- if (i != 0 && !basis1.h.equals(basis2.h)) // don't compare h for the 0th basis
- {
- return false;
- }
- if (!basis1.params.equals(basis2.params))
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * A NtruSign basis. Contains three polynomials <code>f, f', h</code>.
- */
- public static class Basis
- {
- public Polynomial f;
- public Polynomial fPrime;
- public IntegerPolynomial h;
- NTRUSigningKeyGenerationParameters params;
-
- /**
- * Constructs a new basis from polynomials <code>f, f', h</code>.
- *
- * @param f
- * @param fPrime
- * @param h
- * @param params NtruSign parameters
- */
- protected Basis(Polynomial f, Polynomial fPrime, IntegerPolynomial h, NTRUSigningKeyGenerationParameters params)
- {
- this.f = f;
- this.fPrime = fPrime;
- this.h = h;
- this.params = params;
- }
-
- /**
- * Reads a basis from an input stream and constructs a new basis.
- *
- * @param is an input stream
- * @param params NtruSign parameters
- * @param include_h whether to read the polynomial <code>h</code> (<code>true</code>) or only <code>f</code> and <code>f'</code> (<code>false</code>)
- */
- Basis(InputStream is, NTRUSigningKeyGenerationParameters params, boolean include_h)
- throws IOException
- {
- int N = params.N;
- int q = params.q;
- int d1 = params.d1;
- int d2 = params.d2;
- int d3 = params.d3;
- boolean sparse = params.sparse;
- this.params = params;
-
- if (params.polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_PRODUCT)
- {
- f = ProductFormPolynomial.fromBinary(is, N, d1, d2, d3 + 1, d3);
- }
- else
- {
- IntegerPolynomial fInt = IntegerPolynomial.fromBinary3Tight(is, N);
- f = sparse ? new SparseTernaryPolynomial(fInt) : new DenseTernaryPolynomial(fInt);
- }
-
- if (params.basisType == NTRUSigningKeyGenerationParameters.BASIS_TYPE_STANDARD)
- {
- IntegerPolynomial fPrimeInt = IntegerPolynomial.fromBinary(is, N, q);
- for (int i = 0; i < fPrimeInt.coeffs.length; i++)
- {
- fPrimeInt.coeffs[i] -= q / 2;
- }
- fPrime = fPrimeInt;
- }
- else if (params.polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_PRODUCT)
- {
- fPrime = ProductFormPolynomial.fromBinary(is, N, d1, d2, d3 + 1, d3);
- }
- else
- {
- fPrime = IntegerPolynomial.fromBinary3Tight(is, N);
- }
-
- if (include_h)
- {
- h = IntegerPolynomial.fromBinary(is, N, q);
- }
- }
-
- /**
- * Writes the basis to an output stream
- *
- * @param os an output stream
- * @param include_h whether to write the polynomial <code>h</code> (<code>true</code>) or only <code>f</code> and <code>f'</code> (<code>false</code>)
- * @throws IOException
- */
- void encode(OutputStream os, boolean include_h)
- throws IOException
- {
- int q = params.q;
-
- os.write(getEncoded(f));
- if (params.basisType == NTRUSigningKeyGenerationParameters.BASIS_TYPE_STANDARD)
- {
- IntegerPolynomial fPrimeInt = fPrime.toIntegerPolynomial();
- for (int i = 0; i < fPrimeInt.coeffs.length; i++)
- {
- fPrimeInt.coeffs[i] += q / 2;
- }
- os.write(fPrimeInt.toBinary(q));
- }
- else
- {
- os.write(getEncoded(fPrime));
- }
- if (include_h)
- {
- os.write(h.toBinary(q));
- }
- }
-
- private byte[] getEncoded(Polynomial p)
- {
- if (p instanceof ProductFormPolynomial)
- {
- return ((ProductFormPolynomial)p).toBinary();
- }
- else
- {
- return p.toIntegerPolynomial().toBinary3Tight();
- }
- }
-
- @Override
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((f == null) ? 0 : f.hashCode());
- result = prime * result + ((fPrime == null) ? 0 : fPrime.hashCode());
- result = prime * result + ((h == null) ? 0 : h.hashCode());
- result = prime * result + ((params == null) ? 0 : params.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj == null)
- {
- return false;
- }
- if (!(obj instanceof Basis))
- {
- return false;
- }
- Basis other = (Basis)obj;
- if (f == null)
- {
- if (other.f != null)
- {
- return false;
- }
- }
- else if (!f.equals(other.f))
- {
- return false;
- }
- if (fPrime == null)
- {
- if (other.fPrime != null)
- {
- return false;
- }
- }
- else if (!fPrime.equals(other.fPrime))
- {
- return false;
- }
- if (h == null)
- {
- if (other.h != null)
- {
- return false;
- }
- }
- else if (!h.equals(other.h))
- {
- return false;
- }
- if (params == null)
- {
- if (other.params != null)
- {
- return false;
- }
- }
- else if (!params.equals(other.params))
- {
- return false;
- }
- return true;
- }
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningPublicKeyParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningPublicKeyParameters.java
deleted file mode 100644
index be51d0af..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningPublicKeyParameters.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package org.bouncycastle.pqc.crypto.ntru;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-
-/**
- * A NtruSign public key is essentially a polynomial named <code>h</code>.
- */
-public class NTRUSigningPublicKeyParameters
- extends AsymmetricKeyParameter
-{
- private NTRUSigningParameters params;
- public IntegerPolynomial h;
-
- /**
- * Constructs a new public key from a polynomial
- *
- * @param h the polynomial <code>h</code> which determines the key
- * @param params the NtruSign parameters to use
- */
- public NTRUSigningPublicKeyParameters(IntegerPolynomial h, NTRUSigningParameters params)
- {
- super(false);
- this.h = h;
- this.params = params;
- }
-
- /**
- * Converts a byte array to a polynomial <code>h</code> and constructs a new public key
- *
- * @param b an encoded polynomial
- * @param params the NtruSign parameters to use
- */
- public NTRUSigningPublicKeyParameters(byte[] b, NTRUSigningParameters params)
- {
- super(false);
- h = IntegerPolynomial.fromBinary(b, params.N, params.q);
- this.params = params;
- }
-
- /**
- * Reads a polynomial <code>h</code> from an input stream and constructs a new public key
- *
- * @param is an input stream
- * @param params the NtruSign parameters to use
- */
- public NTRUSigningPublicKeyParameters(InputStream is, NTRUSigningParameters params)
- throws IOException
- {
- super(false);
- h = IntegerPolynomial.fromBinary(is, params.N, params.q);
- this.params = params;
- }
-
-
- /**
- * Converts the key to a byte array
- *
- * @return the encoded key
- */
- public byte[] getEncoded()
- {
- return h.toBinary(params.q);
- }
-
- /**
- * Writes the key to an output stream
- *
- * @param os an output stream
- * @throws IOException
- */
- public void writeTo(OutputStream os)
- throws IOException
- {
- os.write(getEncoded());
- }
-
- @Override
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((h == null) ? 0 : h.hashCode());
- result = prime * result + ((params == null) ? 0 : params.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj == null)
- {
- return false;
- }
- if (getClass() != obj.getClass())
- {
- return false;
- }
- NTRUSigningPublicKeyParameters other = (NTRUSigningPublicKeyParameters)obj;
- if (h == null)
- {
- if (other.h != null)
- {
- return false;
- }
- }
- else if (!h.equals(other.h))
- {
- return false;
- }
- if (params == null)
- {
- if (other.params != null)
- {
- return false;
- }
- }
- else if (!params.equals(other.params))
- {
- return false;
- }
- return true;
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/Layer.java b/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/Layer.java
deleted file mode 100644
index ae76922c..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/Layer.java
+++ /dev/null
@@ -1,322 +0,0 @@
-package org.bouncycastle.pqc.crypto.rainbow;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.pqc.crypto.rainbow.util.GF2Field;
-import org.bouncycastle.pqc.crypto.rainbow.util.RainbowUtil;
-import org.bouncycastle.util.Arrays;
-
-
-/**
- * This class represents a layer of the Rainbow Oil- and Vinegar Map. Each Layer
- * consists of oi polynomials with their coefficients, generated at random.
- * <p>
- * To sign a document, we solve a LES (linear equation system) for each layer in
- * order to find the oil variables of that layer and to be able to use the
- * variables to compute the signature. This functionality is implemented in the
- * RainbowSignature-class, by the aid of the private key.
- * <p>
- * Each layer is a part of the private key.
- * <p>
- * More information about the layer can be found in the paper of Jintai Ding,
- * Dieter Schmidt: Rainbow, a New Multivariable Polynomial Signature Scheme.
- * ACNS 2005: 164-175 (http://dx.doi.org/10.1007/11496137_12)
- */
-public class Layer
-{
- private int vi; // number of vinegars in this layer
- private int viNext; // number of vinegars in next layer
- private int oi; // number of oils in this layer
-
- /*
- * k : index of polynomial
- *
- * i,j : indices of oil and vinegar variables
- */
- private short[/* k */][/* i */][/* j */] coeff_alpha;
- private short[/* k */][/* i */][/* j */] coeff_beta;
- private short[/* k */][/* i */] coeff_gamma;
- private short[/* k */] coeff_eta;
-
- /**
- * Constructor
- *
- * @param vi number of vinegar variables of this layer
- * @param viNext number of vinegar variables of next layer. It's the same as
- * (num of oils) + (num of vinegars) of this layer.
- * @param coeffAlpha alpha-coefficients in the polynomials of this layer
- * @param coeffBeta beta-coefficients in the polynomials of this layer
- * @param coeffGamma gamma-coefficients in the polynomials of this layer
- * @param coeffEta eta-coefficients in the polynomials of this layer
- */
- public Layer(byte vi, byte viNext, short[][][] coeffAlpha,
- short[][][] coeffBeta, short[][] coeffGamma, short[] coeffEta)
- {
- this.vi = vi & 0xff;
- this.viNext = viNext & 0xff;
- this.oi = this.viNext - this.vi;
-
- // the secret coefficients of all polynomials in this layer
- this.coeff_alpha = coeffAlpha;
- this.coeff_beta = coeffBeta;
- this.coeff_gamma = coeffGamma;
- this.coeff_eta = coeffEta;
- }
-
- /**
- * This function generates the coefficients of all polynomials in this layer
- * at random using random generator.
- *
- * @param sr the random generator which is to be used
- */
- public Layer(int vi, int viNext, SecureRandom sr)
- {
- this.vi = vi;
- this.viNext = viNext;
- this.oi = viNext - vi;
-
- // the coefficients of all polynomials in this layer
- this.coeff_alpha = new short[this.oi][this.oi][this.vi];
- this.coeff_beta = new short[this.oi][this.vi][this.vi];
- this.coeff_gamma = new short[this.oi][this.viNext];
- this.coeff_eta = new short[this.oi];
-
- int numOfPoly = this.oi; // number of polynomials per layer
-
- // Alpha coeffs
- for (int k = 0; k < numOfPoly; k++)
- {
- for (int i = 0; i < this.oi; i++)
- {
- for (int j = 0; j < this.vi; j++)
- {
- coeff_alpha[k][i][j] = (short)(sr.nextInt() & GF2Field.MASK);
- }
- }
- }
- // Beta coeffs
- for (int k = 0; k < numOfPoly; k++)
- {
- for (int i = 0; i < this.vi; i++)
- {
- for (int j = 0; j < this.vi; j++)
- {
- coeff_beta[k][i][j] = (short)(sr.nextInt() & GF2Field.MASK);
- }
- }
- }
- // Gamma coeffs
- for (int k = 0; k < numOfPoly; k++)
- {
- for (int i = 0; i < this.viNext; i++)
- {
- coeff_gamma[k][i] = (short)(sr.nextInt() & GF2Field.MASK);
- }
- }
- // Eta
- for (int k = 0; k < numOfPoly; k++)
- {
- coeff_eta[k] = (short)(sr.nextInt() & GF2Field.MASK);
- }
- }
-
- /**
- * This method plugs in the vinegar variables into the polynomials of this
- * layer and computes the coefficients of the Oil-variables as well as the
- * free coefficient in each polynomial.
- * <p>
- * It is needed for computing the Oil variables while signing.
- *
- * @param x vinegar variables of this layer that should be plugged into
- * the polynomials.
- * @return coeff the coefficients of Oil variables and the free coeff in the
- * polynomials of this layer.
- */
- public short[][] plugInVinegars(short[] x)
- {
- // temporary variable needed for the multiplication
- short tmpMult = 0;
- // coeff: 1st index = which polynomial, 2nd index=which variable
- short[][] coeff = new short[oi][oi + 1]; // gets returned
- // free coefficient per polynomial
- short[] sum = new short[oi];
-
- /*
- * evaluate the beta-part of the polynomials (it contains no oil
- * variables)
- */
- for (int k = 0; k < oi; k++)
- {
- for (int i = 0; i < vi; i++)
- {
- for (int j = 0; j < vi; j++)
- {
- // tmp = beta * xi (plug in)
- tmpMult = GF2Field.multElem(coeff_beta[k][i][j], x[i]);
- // tmp = tmp * xj
- tmpMult = GF2Field.multElem(tmpMult, x[j]);
- // accumulate into the array for the free coefficients.
- sum[k] = GF2Field.addElem(sum[k], tmpMult);
- }
- }
- }
-
- /* evaluate the alpha-part (it contains oils) */
- for (int k = 0; k < oi; k++)
- {
- for (int i = 0; i < oi; i++)
- {
- for (int j = 0; j < vi; j++)
- {
- // alpha * xj (plug in)
- tmpMult = GF2Field.multElem(coeff_alpha[k][i][j], x[j]);
- // accumulate
- coeff[k][i] = GF2Field.addElem(coeff[k][i], tmpMult);
- }
- }
- }
- /* evaluate the gama-part of the polynomial (containing no oils) */
- for (int k = 0; k < oi; k++)
- {
- for (int i = 0; i < vi; i++)
- {
- // gamma * xi (plug in)
- tmpMult = GF2Field.multElem(coeff_gamma[k][i], x[i]);
- // accumulate in the array for the free coefficients (per
- // polynomial).
- sum[k] = GF2Field.addElem(sum[k], tmpMult);
- }
- }
- /* evaluate the gama-part of the polynomial (but containing oils) */
- for (int k = 0; k < oi; k++)
- {
- for (int i = vi; i < viNext; i++)
- { // oils
- // accumulate the coefficients of the oil variables (per
- // polynomial).
- coeff[k][i - vi] = GF2Field.addElem(coeff_gamma[k][i],
- coeff[k][i - vi]);
- }
- }
- /* evaluate the eta-part of the polynomial */
- for (int k = 0; k < oi; k++)
- {
- // accumulate in the array for the free coefficients per polynomial.
- sum[k] = GF2Field.addElem(sum[k], coeff_eta[k]);
- }
-
- /* put the free coefficients (sum) into the coeff-array as last column */
- for (int k = 0; k < oi; k++)
- {
- coeff[k][oi] = sum[k];
- }
- return coeff;
- }
-
- /**
- * Getter for the number of vinegar variables of this layer.
- *
- * @return the number of vinegar variables of this layer.
- */
- public int getVi()
- {
- return vi;
- }
-
- /**
- * Getter for the number of vinegar variables of the next layer.
- *
- * @return the number of vinegar variables of the next layer.
- */
- public int getViNext()
- {
- return viNext;
- }
-
- /**
- * Getter for the number of Oil variables of this layer.
- *
- * @return the number of oil variables of this layer.
- */
- public int getOi()
- {
- return oi;
- }
-
- /**
- * Getter for the alpha-coefficients of the polynomials in this layer.
- *
- * @return the coefficients of alpha-terms of this layer.
- */
- public short[][][] getCoeffAlpha()
- {
- return coeff_alpha;
- }
-
- /**
- * Getter for the beta-coefficients of the polynomials in this layer.
- *
- * @return the coefficients of beta-terms of this layer.
- */
-
- public short[][][] getCoeffBeta()
- {
- return coeff_beta;
- }
-
- /**
- * Getter for the gamma-coefficients of the polynomials in this layer.
- *
- * @return the coefficients of gamma-terms of this layer
- */
- public short[][] getCoeffGamma()
- {
- return coeff_gamma;
- }
-
- /**
- * Getter for the eta-coefficients of the polynomials in this layer.
- *
- * @return the coefficients eta of this layer
- */
- public short[] getCoeffEta()
- {
- return coeff_eta;
- }
-
- /**
- * This function compares this Layer with another object.
- *
- * @param other the other object
- * @return the result of the comparison
- */
- public boolean equals(Object other)
- {
- if (other == null || !(other instanceof Layer))
- {
- return false;
- }
- Layer otherLayer = (Layer)other;
-
- return vi == otherLayer.getVi()
- && viNext == otherLayer.getViNext()
- && oi == otherLayer.getOi()
- && RainbowUtil.equals(coeff_alpha, otherLayer.getCoeffAlpha())
- && RainbowUtil.equals(coeff_beta, otherLayer.getCoeffBeta())
- && RainbowUtil.equals(coeff_gamma, otherLayer.getCoeffGamma())
- && RainbowUtil.equals(coeff_eta, otherLayer.getCoeffEta());
- }
-
- public int hashCode()
- {
- int hash = vi;
- hash = hash * 37 + viNext;
- hash = hash * 37 + oi;
- hash = hash * 37 + Arrays.hashCode(coeff_alpha);
- hash = hash * 37 + Arrays.hashCode(coeff_beta);
- hash = hash * 37 + Arrays.hashCode(coeff_gamma);
- hash = hash * 37 + Arrays.hashCode(coeff_eta);
-
- return hash;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowKeyGenerationParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowKeyGenerationParameters.java
deleted file mode 100644
index b634f9cc..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowKeyGenerationParameters.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.bouncycastle.pqc.crypto.rainbow;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.KeyGenerationParameters;
-
-public class RainbowKeyGenerationParameters
- extends KeyGenerationParameters
-{
- private RainbowParameters params;
-
- public RainbowKeyGenerationParameters(
- SecureRandom random,
- RainbowParameters params)
- {
- // TODO: key size?
- super(random, params.getVi()[params.getVi().length - 1] - params.getVi()[0]);
- this.params = params;
- }
-
- public RainbowParameters getParameters()
- {
- return params;
- }
-}
-
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowKeyPairGenerator.java b/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowKeyPairGenerator.java
deleted file mode 100644
index 8ef15337..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowKeyPairGenerator.java
+++ /dev/null
@@ -1,413 +0,0 @@
-package org.bouncycastle.pqc.crypto.rainbow;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.pqc.crypto.rainbow.util.ComputeInField;
-import org.bouncycastle.pqc.crypto.rainbow.util.GF2Field;
-
-/**
- * This class implements AsymmetricCipherKeyPairGenerator. It is used
- * as a generator for the private and public key of the Rainbow Signature
- * Scheme.
- * <p>
- * Detailed information about the key generation is to be found in the paper of
- * Jintai Ding, Dieter Schmidt: Rainbow, a New Multivariable Polynomial
- * Signature Scheme. ACNS 2005: 164-175 (http://dx.doi.org/10.1007/11496137_12)
- */
-public class RainbowKeyPairGenerator
- implements AsymmetricCipherKeyPairGenerator
-{
- private boolean initialized = false;
- private SecureRandom sr;
- private RainbowKeyGenerationParameters rainbowParams;
-
- /* linear affine map L1: */
- private short[][] A1; // matrix of the lin. affine map L1(n-v1 x n-v1 matrix)
- private short[][] A1inv; // inverted A1
- private short[] b1; // translation element of the lin.affine map L1
-
- /* linear affine map L2: */
- private short[][] A2; // matrix of the lin. affine map (n x n matrix)
- private short[][] A2inv; // inverted A2
- private short[] b2; // translation elemt of the lin.affine map L2
-
- /* components of F: */
- private int numOfLayers; // u (number of sets S)
- private Layer layers[]; // layers of polynomials of F
- private int[] vi; // set of vinegar vars per layer.
-
- /* components of Public Key */
- private short[][] pub_quadratic; // quadratic(mixed) coefficients
- private short[][] pub_singular; // singular coefficients
- private short[] pub_scalar; // scalars
-
- // TODO
-
- /**
- * The standard constructor tries to generate the Rainbow algorithm identifier
- * with the corresponding OID.
- */
- public RainbowKeyPairGenerator()
- {
- }
-
-
- /**
- * This function generates a Rainbow key pair.
- *
- * @return the generated key pair
- */
- public AsymmetricCipherKeyPair genKeyPair()
- {
- RainbowPrivateKeyParameters privKey;
- RainbowPublicKeyParameters pubKey;
-
- if (!initialized)
- {
- initializeDefault();
- }
-
- /* choose all coefficients at random */
- keygen();
-
- /* now marshall them to PrivateKey */
- privKey = new RainbowPrivateKeyParameters(A1inv, b1, A2inv, b2, vi, layers);
-
-
- /* marshall to PublicKey */
- pubKey = new RainbowPublicKeyParameters(vi[vi.length - 1] - vi[0], pub_quadratic, pub_singular, pub_scalar);
-
- return new AsymmetricCipherKeyPair(pubKey, privKey);
- }
-
- // TODO
- public void initialize(
- KeyGenerationParameters param)
- {
- this.rainbowParams = (RainbowKeyGenerationParameters)param;
-
- // set source of randomness
- this.sr = new SecureRandom();
-
- // unmarshalling:
- this.vi = this.rainbowParams.getParameters().getVi();
- this.numOfLayers = this.rainbowParams.getParameters().getNumOfLayers();
-
- this.initialized = true;
- }
-
- private void initializeDefault()
- {
- RainbowKeyGenerationParameters rbKGParams = new RainbowKeyGenerationParameters(new SecureRandom(), new RainbowParameters());
- initialize(rbKGParams);
- }
-
- /**
- * This function calls the functions for the random generation of the coefficients
- * and the matrices needed for the private key and the method for computing the public key.
- */
- private void keygen()
- {
- generateL1();
- generateL2();
- generateF();
- computePublicKey();
- }
-
- /**
- * This function generates the invertible affine linear map L1 = A1*x + b1
- * <p/>
- * The translation part b1, is stored in a separate array. The inverse of
- * the matrix-part of L1 A1inv is also computed here.
- * <p/>
- * This linear map hides the output of the map F. It is on k^(n-v1).
- */
- private void generateL1()
- {
-
- // dimension = n-v1 = vi[last] - vi[first]
- int dim = vi[vi.length - 1] - vi[0];
- this.A1 = new short[dim][dim];
- this.A1inv = null;
- ComputeInField c = new ComputeInField();
-
- /* generation of A1 at random */
- while (A1inv == null)
- {
- for (int i = 0; i < dim; i++)
- {
- for (int j = 0; j < dim; j++)
- {
- A1[i][j] = (short)(sr.nextInt() & GF2Field.MASK);
- }
- }
- A1inv = c.inverse(A1);
- }
-
- /* generation of the translation vector at random */
- b1 = new short[dim];
- for (int i = 0; i < dim; i++)
- {
- b1[i] = (short)(sr.nextInt() & GF2Field.MASK);
- }
- }
-
- /**
- * This function generates the invertible affine linear map L2 = A2*x + b2
- * <p/>
- * The translation part b2, is stored in a separate array. The inverse of
- * the matrix-part of L2 A2inv is also computed here.
- * <p/>
- * This linear map hides the output of the map F. It is on k^(n).
- */
- private void generateL2()
- {
-
- // dimension = n = vi[last]
- int dim = vi[vi.length - 1];
- this.A2 = new short[dim][dim];
- this.A2inv = null;
- ComputeInField c = new ComputeInField();
-
- /* generation of A2 at random */
- while (this.A2inv == null)
- {
- for (int i = 0; i < dim; i++)
- {
- for (int j = 0; j < dim; j++)
- { // one col extra for b
- A2[i][j] = (short)(sr.nextInt() & GF2Field.MASK);
- }
- }
- this.A2inv = c.inverse(A2);
- }
- /* generation of the translation vector at random */
- b2 = new short[dim];
- for (int i = 0; i < dim; i++)
- {
- b2[i] = (short)(sr.nextInt() & GF2Field.MASK);
- }
-
- }
-
- /**
- * This function generates the private map F, which consists of u-1 layers.
- * Each layer consists of oi polynomials where oi = vi[i+1]-vi[i].
- * <p/>
- * The methods for the generation of the coefficients of these polynomials
- * are called here.
- */
- private void generateF()
- {
-
- this.layers = new Layer[this.numOfLayers];
- for (int i = 0; i < this.numOfLayers; i++)
- {
- layers[i] = new Layer(this.vi[i], this.vi[i + 1], sr);
- }
- }
-
- /**
- * This function computes the public key from the private key.
- * <p/>
- * The composition of F with L2 is computed, followed by applying L1 to the
- * composition's result. The singular and scalar values constitute to the
- * public key as is, the quadratic terms are compacted in
- * <tt>compactPublicKey()</tt>
- */
- private void computePublicKey()
- {
-
- ComputeInField c = new ComputeInField();
- int rows = this.vi[this.vi.length - 1] - this.vi[0];
- int vars = this.vi[this.vi.length - 1];
- // Fpub
- short[][][] coeff_quadratic_3dim = new short[rows][vars][vars];
- this.pub_singular = new short[rows][vars];
- this.pub_scalar = new short[rows];
-
- // Coefficients of layers of Private Key F
- short[][][] coeff_alpha;
- short[][][] coeff_beta;
- short[][] coeff_gamma;
- short[] coeff_eta;
-
- // Needed for counters;
- int oils = 0;
- int vins = 0;
- int crnt_row = 0; // current row (polynomial)
-
- short vect_tmp[] = new short[vars]; // vector tmp;
- short sclr_tmp = 0;
-
- // Composition of F and L2: Insert L2 = A2*x+b2 in F
- for (int l = 0; l < this.layers.length; l++)
- {
- // get coefficients of current layer
- coeff_alpha = this.layers[l].getCoeffAlpha();
- coeff_beta = this.layers[l].getCoeffBeta();
- coeff_gamma = this.layers[l].getCoeffGamma();
- coeff_eta = this.layers[l].getCoeffEta();
- oils = coeff_alpha[0].length;// this.layers[l].getOi();
- vins = coeff_beta[0].length;// this.layers[l].getVi();
- // compute polynomials of layer
- for (int p = 0; p < oils; p++)
- {
- // multiply alphas
- for (int x1 = 0; x1 < oils; x1++)
- {
- for (int x2 = 0; x2 < vins; x2++)
- {
- // multiply polynomial1 with polynomial2
- vect_tmp = c.multVect(coeff_alpha[p][x1][x2],
- this.A2[x1 + vins]);
- coeff_quadratic_3dim[crnt_row + p] = c.addSquareMatrix(
- coeff_quadratic_3dim[crnt_row + p], c
- .multVects(vect_tmp, this.A2[x2]));
- // mul poly1 with scalar2
- vect_tmp = c.multVect(this.b2[x2], vect_tmp);
- this.pub_singular[crnt_row + p] = c.addVect(vect_tmp,
- this.pub_singular[crnt_row + p]);
- // mul scalar1 with poly2
- vect_tmp = c.multVect(coeff_alpha[p][x1][x2],
- this.A2[x2]);
- vect_tmp = c.multVect(b2[x1 + vins], vect_tmp);
- this.pub_singular[crnt_row + p] = c.addVect(vect_tmp,
- this.pub_singular[crnt_row + p]);
- // mul scalar1 with scalar2
- sclr_tmp = GF2Field.multElem(coeff_alpha[p][x1][x2],
- this.b2[x1 + vins]);
- this.pub_scalar[crnt_row + p] = GF2Field.addElem(
- this.pub_scalar[crnt_row + p], GF2Field
- .multElem(sclr_tmp, this.b2[x2]));
- }
- }
- // multiply betas
- for (int x1 = 0; x1 < vins; x1++)
- {
- for (int x2 = 0; x2 < vins; x2++)
- {
- // multiply polynomial1 with polynomial2
- vect_tmp = c.multVect(coeff_beta[p][x1][x2],
- this.A2[x1]);
- coeff_quadratic_3dim[crnt_row + p] = c.addSquareMatrix(
- coeff_quadratic_3dim[crnt_row + p], c
- .multVects(vect_tmp, this.A2[x2]));
- // mul poly1 with scalar2
- vect_tmp = c.multVect(this.b2[x2], vect_tmp);
- this.pub_singular[crnt_row + p] = c.addVect(vect_tmp,
- this.pub_singular[crnt_row + p]);
- // mul scalar1 with poly2
- vect_tmp = c.multVect(coeff_beta[p][x1][x2],
- this.A2[x2]);
- vect_tmp = c.multVect(this.b2[x1], vect_tmp);
- this.pub_singular[crnt_row + p] = c.addVect(vect_tmp,
- this.pub_singular[crnt_row + p]);
- // mul scalar1 with scalar2
- sclr_tmp = GF2Field.multElem(coeff_beta[p][x1][x2],
- this.b2[x1]);
- this.pub_scalar[crnt_row + p] = GF2Field.addElem(
- this.pub_scalar[crnt_row + p], GF2Field
- .multElem(sclr_tmp, this.b2[x2]));
- }
- }
- // multiply gammas
- for (int n = 0; n < vins + oils; n++)
- {
- // mul poly with scalar
- vect_tmp = c.multVect(coeff_gamma[p][n], this.A2[n]);
- this.pub_singular[crnt_row + p] = c.addVect(vect_tmp,
- this.pub_singular[crnt_row + p]);
- // mul scalar with scalar
- this.pub_scalar[crnt_row + p] = GF2Field.addElem(
- this.pub_scalar[crnt_row + p], GF2Field.multElem(
- coeff_gamma[p][n], this.b2[n]));
- }
- // add eta
- this.pub_scalar[crnt_row + p] = GF2Field.addElem(
- this.pub_scalar[crnt_row + p], coeff_eta[p]);
- }
- crnt_row = crnt_row + oils;
- }
-
- // Apply L1 = A1*x+b1 to composition of F and L2
- {
- // temporary coefficient arrays
- short[][][] tmp_c_quad = new short[rows][vars][vars];
- short[][] tmp_c_sing = new short[rows][vars];
- short[] tmp_c_scal = new short[rows];
- for (int r = 0; r < rows; r++)
- {
- for (int q = 0; q < A1.length; q++)
- {
- tmp_c_quad[r] = c.addSquareMatrix(tmp_c_quad[r], c
- .multMatrix(A1[r][q], coeff_quadratic_3dim[q]));
- tmp_c_sing[r] = c.addVect(tmp_c_sing[r], c.multVect(
- A1[r][q], this.pub_singular[q]));
- tmp_c_scal[r] = GF2Field.addElem(tmp_c_scal[r], GF2Field
- .multElem(A1[r][q], this.pub_scalar[q]));
- }
- tmp_c_scal[r] = GF2Field.addElem(tmp_c_scal[r], b1[r]);
- }
- // set public key
- coeff_quadratic_3dim = tmp_c_quad;
- this.pub_singular = tmp_c_sing;
- this.pub_scalar = tmp_c_scal;
- }
- compactPublicKey(coeff_quadratic_3dim);
- }
-
- /**
- * The quadratic (or mixed) terms of the public key are compacted from a n x
- * n matrix per polynomial to an upper diagonal matrix stored in one integer
- * array of n (n + 1) / 2 elements per polynomial. The ordering of elements
- * is lexicographic and the result is updating <tt>this.pub_quadratic</tt>,
- * which stores the quadratic elements of the public key.
- *
- * @param coeff_quadratic_to_compact 3-dimensional array containing a n x n Matrix for each of the
- * n - v1 polynomials
- */
- private void compactPublicKey(short[][][] coeff_quadratic_to_compact)
- {
- int polynomials = coeff_quadratic_to_compact.length;
- int n = coeff_quadratic_to_compact[0].length;
- int entries = n * (n + 1) / 2;// the small gauss
- this.pub_quadratic = new short[polynomials][entries];
- int offset = 0;
-
- for (int p = 0; p < polynomials; p++)
- {
- offset = 0;
- for (int x = 0; x < n; x++)
- {
- for (int y = x; y < n; y++)
- {
- if (y == x)
- {
- this.pub_quadratic[p][offset] = coeff_quadratic_to_compact[p][x][y];
- }
- else
- {
- this.pub_quadratic[p][offset] = GF2Field.addElem(
- coeff_quadratic_to_compact[p][x][y],
- coeff_quadratic_to_compact[p][y][x]);
- }
- offset++;
- }
- }
- }
- }
-
- public void init(KeyGenerationParameters param)
- {
- this.initialize(param);
- }
-
- public AsymmetricCipherKeyPair generateKeyPair()
- {
- return genKeyPair();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowKeyParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowKeyParameters.java
deleted file mode 100644
index 9dec6853..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowKeyParameters.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.pqc.crypto.rainbow;
-
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-
-public class RainbowKeyParameters
- extends AsymmetricKeyParameter
-{
- private int docLength;
-
- public RainbowKeyParameters(
- boolean isPrivate,
- int docLength)
- {
- super(isPrivate);
- this.docLength = docLength;
- }
-
- /**
- * @return the docLength
- */
- public int getDocLength()
- {
- return this.docLength;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowParameters.java
deleted file mode 100644
index 147c55e9..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowParameters.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package org.bouncycastle.pqc.crypto.rainbow;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public class RainbowParameters
- implements CipherParameters
-{
-
- /**
- * DEFAULT PARAMS
- */
- /*
- * Vi = vinegars per layer whereas n is vu (vu = 33 = n) such that
- *
- * v1 = 6; o1 = 12-6 = 6
- *
- * v2 = 12; o2 = 17-12 = 5
- *
- * v3 = 17; o3 = 22-17 = 5
- *
- * v4 = 22; o4 = 33-22 = 11
- *
- * v5 = 33; (o5 = 0)
- */
- private final int[] DEFAULT_VI = {6, 12, 17, 22, 33};
-
- private int[] vi;// set of vinegar vars per layer.
-
- /**
- * Default Constructor The elements of the array containing the number of
- * Vinegar variables in each layer are set to the default values here.
- */
- public RainbowParameters()
- {
- this.vi = this.DEFAULT_VI;
- }
-
- /**
- * Constructor with parameters
- *
- * @param vi The elements of the array containing the number of Vinegar
- * variables per layer are set to the values of the input array.
- */
- public RainbowParameters(int[] vi)
- {
- this.vi = vi;
- try
- {
- checkParams();
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- }
-
- private void checkParams()
- throws Exception
- {
- if (vi == null)
- {
- throw new Exception("no layers defined.");
- }
- if (vi.length > 1)
- {
- for (int i = 0; i < vi.length - 1; i++)
- {
- if (vi[i] >= vi[i + 1])
- {
- throw new Exception(
- "v[i] has to be smaller than v[i+1]");
- }
- }
- }
- else
- {
- throw new Exception(
- "Rainbow needs at least 1 layer, such that v1 < v2.");
- }
- }
-
- /**
- * Getter for the number of layers
- *
- * @return the number of layers
- */
- public int getNumOfLayers()
- {
- return this.vi.length - 1;
- }
-
- /**
- * Getter for the number of all the polynomials in Rainbow
- *
- * @return the number of the polynomials
- */
- public int getDocLength()
- {
- return vi[vi.length - 1] - vi[0];
- }
-
- /**
- * Getter for the array containing the number of Vinegar-variables per layer
- *
- * @return the numbers of vinegars per layer
- */
- public int[] getVi()
- {
- return this.vi;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowPrivateKeyParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowPrivateKeyParameters.java
deleted file mode 100644
index 98768820..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowPrivateKeyParameters.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package org.bouncycastle.pqc.crypto.rainbow;
-
-public class RainbowPrivateKeyParameters
- extends RainbowKeyParameters
-{
- /**
- * Constructor
- *
- * @param A1inv the inverse of A1(the matrix part of the affine linear map L1)
- * (n-v1 x n-v1 matrix)
- * @param b1 translation vector, part of the linear affine map L1
- * @param A2inv the inverse of A2(the matrix part of the affine linear map L2)
- * (n x n matrix)
- * @param b2 translation vector, part of the linear affine map L2
- * @param vi the number of Vinegar-variables per layer
- * @param layers the polynomials with their coefficients of private map F
- */
- public RainbowPrivateKeyParameters(short[][] A1inv, short[] b1,
- short[][] A2inv, short[] b2, int[] vi, Layer[] layers)
- {
- super(true, vi[vi.length - 1] - vi[0]);
-
- this.A1inv = A1inv;
- this.b1 = b1;
- this.A2inv = A2inv;
- this.b2 = b2;
- this.vi = vi;
- this.layers = layers;
- }
-
- /*
- * invertible affine linear map L1
- */
- // the inverse of A1, (n-v1 x n-v1 matrix)
- private short[][] A1inv;
-
- // translation vector of L1
- private short[] b1;
-
- /*
- * invertible affine linear map L2
- */
- // the inverse of A2, (n x n matrix)
- private short[][] A2inv;
-
- // translation vector of L2
- private short[] b2;
-
- /*
- * components of F
- */
- // the number of Vinegar-variables per layer.
- private int[] vi;
-
- // contains the polynomials with their coefficients of private map F
- private Layer[] layers;
-
- /**
- * Getter for the translation part of the private quadratic map L1.
- *
- * @return b1 the translation part of L1
- */
- public short[] getB1()
- {
- return this.b1;
- }
-
- /**
- * Getter for the inverse matrix of A1.
- *
- * @return the A1inv inverse
- */
- public short[][] getInvA1()
- {
- return this.A1inv;
- }
-
- /**
- * Getter for the translation part of the private quadratic map L2.
- *
- * @return b2 the translation part of L2
- */
- public short[] getB2()
- {
- return this.b2;
- }
-
- /**
- * Getter for the inverse matrix of A2
- *
- * @return the A2inv
- */
- public short[][] getInvA2()
- {
- return this.A2inv;
- }
-
- /**
- * Returns the layers contained in the private key
- *
- * @return layers
- */
- public Layer[] getLayers()
- {
- return this.layers;
- }
-
- /**
- * /** Returns the array of vi-s
- *
- * @return the vi
- */
- public int[] getVi()
- {
- return vi;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowPublicKeyParameters.java b/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowPublicKeyParameters.java
deleted file mode 100644
index 6f3e46f2..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowPublicKeyParameters.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.bouncycastle.pqc.crypto.rainbow;
-
-public class RainbowPublicKeyParameters
- extends RainbowKeyParameters
-{
- private short[][] coeffquadratic;
- private short[][] coeffsingular;
- private short[] coeffscalar;
-
- /**
- * Constructor
- *
- * @param docLength
- * @param coeffQuadratic
- * @param coeffSingular
- * @param coeffScalar
- */
- public RainbowPublicKeyParameters(int docLength,
- short[][] coeffQuadratic, short[][] coeffSingular,
- short[] coeffScalar)
- {
- super(false, docLength);
-
- this.coeffquadratic = coeffQuadratic;
- this.coeffsingular = coeffSingular;
- this.coeffscalar = coeffScalar;
-
- }
-
- /**
- * @return the coeffquadratic
- */
- public short[][] getCoeffQuadratic()
- {
- return coeffquadratic;
- }
-
- /**
- * @return the coeffsingular
- */
- public short[][] getCoeffSingular()
- {
- return coeffsingular;
- }
-
- /**
- * @return the coeffscalar
- */
- public short[] getCoeffScalar()
- {
- return coeffscalar;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowSigner.java b/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowSigner.java
deleted file mode 100644
index 979e759b..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/RainbowSigner.java
+++ /dev/null
@@ -1,301 +0,0 @@
-package org.bouncycastle.pqc.crypto.rainbow;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.pqc.crypto.MessageSigner;
-import org.bouncycastle.pqc.crypto.rainbow.util.ComputeInField;
-import org.bouncycastle.pqc.crypto.rainbow.util.GF2Field;
-
-/**
- * It implements the sign and verify functions for the Rainbow Signature Scheme.
- * Here the message, which has to be signed, is updated. The use of
- * different hash functions is possible.
- * <p>
- * Detailed information about the signature and the verify-method is to be found
- * in the paper of Jintai Ding, Dieter Schmidt: Rainbow, a New Multivariable
- * Polynomial Signature Scheme. ACNS 2005: 164-175
- * (http://dx.doi.org/10.1007/11496137_12)
- */
-public class RainbowSigner
- implements MessageSigner
-{
- // Source of randomness
- private SecureRandom random;
-
- // The length of a document that can be signed with the privKey
- int signableDocumentLength;
-
- // Container for the oil and vinegar variables of all the layers
- private short[] x;
-
- private ComputeInField cf = new ComputeInField();
-
- RainbowKeyParameters key;
-
- public void init(boolean forSigning,
- CipherParameters param)
- {
- if (forSigning)
- {
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- this.random = rParam.getRandom();
- this.key = (RainbowPrivateKeyParameters)rParam.getParameters();
-
- }
- else
- {
-
- this.random = new SecureRandom();
- this.key = (RainbowPrivateKeyParameters)param;
- }
- }
- else
- {
- this.key = (RainbowPublicKeyParameters)param;
- }
-
- this.signableDocumentLength = this.key.getDocLength();
- }
-
-
- /**
- * initial operations before solving the Linear equation system.
- *
- * @param layer the current layer for which a LES is to be solved.
- * @param msg the message that should be signed.
- * @return Y_ the modified document needed for solving LES, (Y_ =
- * A1^{-1}*(Y-b1)) linear map L1 = A1 x + b1.
- */
- private short[] initSign(Layer[] layer, short[] msg)
- {
-
- /* preparation: Modifies the document with the inverse of L1 */
- // tmp = Y - b1:
- short[] tmpVec = new short[msg.length];
-
- tmpVec = cf.addVect(((RainbowPrivateKeyParameters)this.key).getB1(), msg);
-
- // Y_ = A1^{-1} * (Y - b1) :
- short[] Y_ = cf.multiplyMatrix(((RainbowPrivateKeyParameters)this.key).getInvA1(), tmpVec);
-
- /* generates the vinegar vars of the first layer at random */
- for (int i = 0; i < layer[0].getVi(); i++)
- {
- x[i] = (short)random.nextInt();
- x[i] = (short)(x[i] & GF2Field.MASK);
- }
-
- return Y_;
- }
-
- /**
- * This function signs the message that has been updated, making use of the
- * private key.
- * <p>
- * For computing the signature, L1 and L2 are needed, as well as LES should
- * be solved for each layer in order to find the Oil-variables in the layer.
- * <p>
- * The Vinegar-variables of the first layer are random generated.
- *
- * @param message the message
- * @return the signature of the message.
- */
- public byte[] generateSignature(byte[] message)
- {
- Layer[] layer = ((RainbowPrivateKeyParameters)this.key).getLayers();
- int numberOfLayers = layer.length;
-
- x = new short[((RainbowPrivateKeyParameters)this.key).getInvA2().length]; // all variables
-
- short[] Y_; // modified document
- short[] y_i; // part of Y_ each polynomial
- int counter; // index of the current part of the doc
-
- short[] solVec; // the solution of LES pro layer
- short[] tmpVec;
-
- // the signature as an array of shorts:
- short[] signature;
- // the signature as a byte-array:
- byte[] S = new byte[layer[numberOfLayers - 1].getViNext()];
-
- short[] msgHashVals = makeMessageRepresentative(message);
-
- // shows if an exception is caught
- boolean ok;
- do
- {
- ok = true;
- counter = 0;
- try
- {
- Y_ = initSign(layer, msgHashVals);
-
- for (int i = 0; i < numberOfLayers; i++)
- {
-
- y_i = new short[layer[i].getOi()];
- solVec = new short[layer[i].getOi()]; // solution of LES
-
- /* copy oi elements of Y_ into y_i */
- for (int k = 0; k < layer[i].getOi(); k++)
- {
- y_i[k] = Y_[counter];
- counter++; // current index of Y_
- }
-
- /*
- * plug in the vars of the previous layer in order to get
- * the vars of the current layer
- */
- solVec = cf.solveEquation(layer[i].plugInVinegars(x), y_i);
-
- if (solVec == null)
- { // LES is not solveable
- throw new Exception("LES is not solveable!");
- }
-
- /* copy the new vars into the x-array */
- for (int j = 0; j < solVec.length; j++)
- {
- x[layer[i].getVi() + j] = solVec[j];
- }
- }
-
- /* apply the inverse of L2: (signature = A2^{-1}*(b2+x)) */
- tmpVec = cf.addVect(((RainbowPrivateKeyParameters)this.key).getB2(), x);
- signature = cf.multiplyMatrix(((RainbowPrivateKeyParameters)this.key).getInvA2(), tmpVec);
-
- /* cast signature from short[] to byte[] */
- for (int i = 0; i < S.length; i++)
- {
- S[i] = ((byte)signature[i]);
- }
- }
- catch (Exception se)
- {
- // if one of the LESs was not solveable - sign again
- ok = false;
- }
- }
- while (!ok);
- /* return the signature in bytes */
- return S;
- }
-
- /**
- * This function verifies the signature of the message that has been
- * updated, with the aid of the public key.
- *
- * @param message the message
- * @param signature the signature of the message
- * @return true if the signature has been verified, false otherwise.
- */
- public boolean verifySignature(byte[] message, byte[] signature)
- {
- short[] sigInt = new short[signature.length];
- short tmp;
-
- for (int i = 0; i < signature.length; i++)
- {
- tmp = (short)signature[i];
- tmp &= (short)0xff;
- sigInt[i] = tmp;
- }
-
- short[] msgHashVal = makeMessageRepresentative(message);
-
- // verify
- short[] verificationResult = verifySignatureIntern(sigInt);
-
- // compare
- boolean verified = true;
- if (msgHashVal.length != verificationResult.length)
- {
- return false;
- }
- for (int i = 0; i < msgHashVal.length; i++)
- {
- verified = verified && msgHashVal[i] == verificationResult[i];
- }
-
- return verified;
- }
-
- /**
- * Signature verification using public key
- *
- * @param signature vector of dimension n
- * @return document hash of length n - v1
- */
- private short[] verifySignatureIntern(short[] signature)
- {
-
- short[][] coeff_quadratic = ((RainbowPublicKeyParameters)this.key).getCoeffQuadratic();
- short[][] coeff_singular = ((RainbowPublicKeyParameters)this.key).getCoeffSingular();
- short[] coeff_scalar = ((RainbowPublicKeyParameters)this.key).getCoeffScalar();
-
- short[] rslt = new short[coeff_quadratic.length];// n - v1
- int n = coeff_singular[0].length;
- int offset = 0; // array position
- short tmp = 0; // for scalar
-
- for (int p = 0; p < coeff_quadratic.length; p++)
- { // no of polynomials
- offset = 0;
- for (int x = 0; x < n; x++)
- {
- // calculate quadratic terms
- for (int y = x; y < n; y++)
- {
- tmp = GF2Field.multElem(coeff_quadratic[p][offset],
- GF2Field.multElem(signature[x], signature[y]));
- rslt[p] = GF2Field.addElem(rslt[p], tmp);
- offset++;
- }
- // calculate singular terms
- tmp = GF2Field.multElem(coeff_singular[p][x], signature[x]);
- rslt[p] = GF2Field.addElem(rslt[p], tmp);
- }
- // add scalar
- rslt[p] = GF2Field.addElem(rslt[p], coeff_scalar[p]);
- }
-
- return rslt;
- }
-
- /**
- * This function creates the representative of the message which gets signed
- * or verified.
- *
- * @param message the message
- * @return message representative
- */
- private short[] makeMessageRepresentative(byte[] message)
- {
- // the message representative
- short[] output = new short[this.signableDocumentLength];
-
- int h = 0;
- int i = 0;
- do
- {
- if (i >= message.length)
- {
- break;
- }
- output[i] = (short)message[h];
- output[i] &= (short)0xff;
- h++;
- i++;
- }
- while (i < output.length);
-
- return output;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/util/ComputeInField.java b/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/util/ComputeInField.java
deleted file mode 100644
index 3517ba30..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/util/ComputeInField.java
+++ /dev/null
@@ -1,490 +0,0 @@
-package org.bouncycastle.pqc.crypto.rainbow.util;
-
-/**
- * This class offers different operations on matrices in field GF2^8.
- * <p>
- * Implemented are functions:
- * - finding inverse of a matrix
- * - solving linear equation systems using the Gauss-Elimination method
- * - basic operations like matrix multiplication, addition and so on.
- */
-
-public class ComputeInField
-{
-
- private short[][] A; // used by solveEquation and inverse
- short[] x;
-
- /**
- * Constructor with no parameters
- */
- public ComputeInField()
- {
- }
-
-
- /**
- * This function finds a solution of the equation Bx = b.
- * Exception is thrown if the linear equation system has no solution
- *
- * @param B this matrix is the left part of the
- * equation (B in the equation above)
- * @param b the right part of the equation
- * (b in the equation above)
- * @return x the solution of the equation if it is solvable
- * null otherwise
- * @throws RuntimeException if LES is not solvable
- */
- public short[] solveEquation(short[][] B, short[] b)
- {
- try
- {
-
- if (B.length != b.length)
- {
- throw new RuntimeException(
- "The equation system is not solvable");
- }
-
- /** initialize **/
- // this matrix stores B and b from the equation B*x = b
- // b is stored as the last column.
- // B contains one column more than rows.
- // In this column we store a free coefficient that should be later subtracted from b
- A = new short[B.length][B.length + 1];
- // stores the solution of the LES
- x = new short[B.length];
-
- /** copy B into the global matrix A **/
- for (int i = 0; i < B.length; i++)
- { // rows
- for (int j = 0; j < B[0].length; j++)
- { // cols
- A[i][j] = B[i][j];
- }
- }
-
- /** copy the vector b into the global A **/
- //the free coefficient, stored in the last column of A( A[i][b.length]
- // is to be subtracted from b
- for (int i = 0; i < b.length; i++)
- {
- A[i][b.length] = GF2Field.addElem(b[i], A[i][b.length]);
- }
-
- /** call the methods for gauss elimination and backward substitution **/
- computeZerosUnder(false); // obtain zeros under the diagonal
- substitute();
-
- return x;
-
- }
- catch (RuntimeException rte)
- {
- return null; // the LES is not solvable!
- }
- }
-
- /**
- * This function computes the inverse of a given matrix using the Gauss-
- * Elimination method.
- * <p>
- * An exception is thrown if the matrix has no inverse
- *
- * @param coef the matrix which inverse matrix is needed
- * @return inverse matrix of the input matrix.
- * If the matrix is singular, null is returned.
- * @throws RuntimeException if the given matrix is not invertible
- */
- public short[][] inverse(short[][] coef)
- {
- try
- {
- /** Initialization: **/
- short factor;
- short[][] inverse;
- A = new short[coef.length][2 * coef.length];
- if (coef.length != coef[0].length)
- {
- throw new RuntimeException(
- "The matrix is not invertible. Please choose another one!");
- }
-
- /** prepare: Copy coef and the identity matrix into the global A. **/
- for (int i = 0; i < coef.length; i++)
- {
- for (int j = 0; j < coef.length; j++)
- {
- //copy the input matrix coef into A
- A[i][j] = coef[i][j];
- }
- // copy the identity matrix into A.
- for (int j = coef.length; j < 2 * coef.length; j++)
- {
- A[i][j] = 0;
- }
- A[i][i + A.length] = 1;
- }
-
- /** Elimination operations to get the identity matrix from the left side of A. **/
- // modify A to get 0s under the diagonal.
- computeZerosUnder(true);
-
- // modify A to get only 1s on the diagonal: A[i][j] =A[i][j]/A[i][i].
- for (int i = 0; i < A.length; i++)
- {
- factor = GF2Field.invElem(A[i][i]);
- for (int j = i; j < 2 * A.length; j++)
- {
- A[i][j] = GF2Field.multElem(A[i][j], factor);
- }
- }
-
- //modify A to get only 0s above the diagonal.
- computeZerosAbove();
-
- // copy the result (the second half of A) in the matrix inverse.
- inverse = new short[A.length][A.length];
- for (int i = 0; i < A.length; i++)
- {
- for (int j = A.length; j < 2 * A.length; j++)
- {
- inverse[i][j - A.length] = A[i][j];
- }
- }
- return inverse;
-
- }
- catch (RuntimeException rte)
- {
- // The matrix is not invertible! A new one should be generated!
- return null;
- }
- }
-
- /**
- * Elimination under the diagonal.
- * This function changes a matrix so that it contains only zeros under the
- * diagonal(Ai,i) using only Gauss-Elimination operations.
- * <p/>
- * It is used in solveEquaton as well as in the function for
- * finding an inverse of a matrix: {@link}inverse. Both of them use the
- * Gauss-Elimination Method.
- * <p/>
- * The result is stored in the global matrix A
- *
- * @param usedForInverse This parameter shows if the function is used by the
- * solveEquation-function or by the inverse-function and according
- * to this creates matrices of different sizes.
- * @throws RuntimeException in case a multiplicative inverse of 0 is needed
- */
- private void computeZerosUnder(boolean usedForInverse)
- throws RuntimeException
- {
-
- //the number of columns in the global A where the tmp results are stored
- int length;
- short tmp = 0;
-
- //the function is used in inverse() - A should have 2 times more columns than rows
- if (usedForInverse)
- {
- length = 2 * A.length;
- }
- //the function is used in solveEquation - A has 1 column more than rows
- else
- {
- length = A.length + 1;
- }
-
- //elimination operations to modify A so that that it contains only 0s under the diagonal
- for (int k = 0; k < A.length - 1; k++)
- { // the fixed row
- for (int i = k + 1; i < A.length; i++)
- { // rows
- short factor1 = A[i][k];
- short factor2 = GF2Field.invElem(A[k][k]);
-
- //The element which multiplicative inverse is needed, is 0
- //in this case is the input matrix not invertible
- if (factor2 == 0)
- {
- throw new RuntimeException("Matrix not invertible! We have to choose another one!");
- }
-
- for (int j = k; j < length; j++)
- {// columns
- // tmp=A[k,j] / A[k,k]
- tmp = GF2Field.multElem(A[k][j], factor2);
- // tmp = A[i,k] * A[k,j] / A[k,k]
- tmp = GF2Field.multElem(factor1, tmp);
- // A[i,j]=A[i,j]-A[i,k]/A[k,k]*A[k,j];
- A[i][j] = GF2Field.addElem(A[i][j], tmp);
- }
- }
- }
- }
-
- /**
- * Elimination above the diagonal.
- * This function changes a matrix so that it contains only zeros above the
- * diagonal(Ai,i) using only Gauss-Elimination operations.
- * <p/>
- * It is used in the inverse-function
- * The result is stored in the global matrix A
- *
- * @throws RuntimeException in case a multiplicative inverse of 0 is needed
- */
- private void computeZerosAbove()
- throws RuntimeException
- {
- short tmp = 0;
- for (int k = A.length - 1; k > 0; k--)
- { // the fixed row
- for (int i = k - 1; i >= 0; i--)
- { // rows
- short factor1 = A[i][k];
- short factor2 = GF2Field.invElem(A[k][k]);
- if (factor2 == 0)
- {
- throw new RuntimeException("The matrix is not invertible");
- }
- for (int j = k; j < 2 * A.length; j++)
- { // columns
- // tmp = A[k,j] / A[k,k]
- tmp = GF2Field.multElem(A[k][j], factor2);
- // tmp = A[i,k] * A[k,j] / A[k,k]
- tmp = GF2Field.multElem(factor1, tmp);
- // A[i,j] = A[i,j] - A[i,k] / A[k,k] * A[k,j];
- A[i][j] = GF2Field.addElem(A[i][j], tmp);
- }
- }
- }
- }
-
-
- /**
- * This function uses backward substitution to find x
- * of the linear equation system (LES) B*x = b,
- * where A a triangle-matrix is (contains only zeros under the diagonal)
- * and b is a vector
- * <p/>
- * If the multiplicative inverse of 0 is needed, an exception is thrown.
- * In this case is the LES not solvable
- *
- * @throws RuntimeException in case a multiplicative inverse of 0 is needed
- */
- private void substitute()
- throws RuntimeException
- {
-
- // for the temporary results of the operations in field
- short tmp, temp;
-
- temp = GF2Field.invElem(A[A.length - 1][A.length - 1]);
- if (temp == 0)
- {
- throw new RuntimeException("The equation system is not solvable");
- }
-
- /** backward substitution **/
- x[A.length - 1] = GF2Field.multElem(A[A.length - 1][A.length], temp);
- for (int i = A.length - 2; i >= 0; i--)
- {
- tmp = A[i][A.length];
- for (int j = A.length - 1; j > i; j--)
- {
- temp = GF2Field.multElem(A[i][j], x[j]);
- tmp = GF2Field.addElem(tmp, temp);
- }
-
- temp = GF2Field.invElem(A[i][i]);
- if (temp == 0)
- {
- throw new RuntimeException("Not solvable equation system");
- }
- x[i] = GF2Field.multElem(tmp, temp);
- }
- }
-
-
- /**
- * This function multiplies two given matrices.
- * If the given matrices cannot be multiplied due
- * to different sizes, an exception is thrown.
- *
- * @param M1 -the 1st matrix
- * @param M2 -the 2nd matrix
- * @return A = M1*M2
- * @throws RuntimeException in case the given matrices cannot be multiplied
- * due to different dimensions.
- */
- public short[][] multiplyMatrix(short[][] M1, short[][] M2)
- throws RuntimeException
- {
-
- if (M1[0].length != M2.length)
- {
- throw new RuntimeException("Multiplication is not possible!");
- }
- short tmp = 0;
- A = new short[M1.length][M2[0].length];
- for (int i = 0; i < M1.length; i++)
- {
- for (int j = 0; j < M2.length; j++)
- {
- for (int k = 0; k < M2[0].length; k++)
- {
- tmp = GF2Field.multElem(M1[i][j], M2[j][k]);
- A[i][k] = GF2Field.addElem(A[i][k], tmp);
- }
- }
- }
- return A;
- }
-
- /**
- * This function multiplies a given matrix with a one-dimensional array.
- * <p>
- * An exception is thrown, if the number of columns in the matrix and
- * the number of rows in the one-dim. array differ.
- *
- * @param M1 the matrix to be multiplied
- * @param m the one-dimensional array to be multiplied
- * @return M1*m
- * @throws RuntimeException in case of dimension inconsistency
- */
- public short[] multiplyMatrix(short[][] M1, short[] m)
- throws RuntimeException
- {
- if (M1[0].length != m.length)
- {
- throw new RuntimeException("Multiplication is not possible!");
- }
- short tmp = 0;
- short[] B = new short[M1.length];
- for (int i = 0; i < M1.length; i++)
- {
- for (int j = 0; j < m.length; j++)
- {
- tmp = GF2Field.multElem(M1[i][j], m[j]);
- B[i] = GF2Field.addElem(B[i], tmp);
- }
- }
- return B;
- }
-
- /**
- * Addition of two vectors
- *
- * @param vector1 first summand, always of dim n
- * @param vector2 second summand, always of dim n
- * @return addition of vector1 and vector2
- * @throws RuntimeException in case the addition is impossible
- * due to inconsistency in the dimensions
- */
- public short[] addVect(short[] vector1, short[] vector2)
- {
- if (vector1.length != vector2.length)
- {
- throw new RuntimeException("Multiplication is not possible!");
- }
- short rslt[] = new short[vector1.length];
- for (int n = 0; n < rslt.length; n++)
- {
- rslt[n] = GF2Field.addElem(vector1[n], vector2[n]);
- }
- return rslt;
- }
-
- /**
- * Multiplication of column vector with row vector
- *
- * @param vector1 column vector, always n x 1
- * @param vector2 row vector, always 1 x n
- * @return resulting n x n matrix of multiplication
- * @throws RuntimeException in case the multiplication is impossible due to
- * inconsistency in the dimensions
- */
- public short[][] multVects(short[] vector1, short[] vector2)
- {
- if (vector1.length != vector2.length)
- {
- throw new RuntimeException("Multiplication is not possible!");
- }
- short rslt[][] = new short[vector1.length][vector2.length];
- for (int i = 0; i < vector1.length; i++)
- {
- for (int j = 0; j < vector2.length; j++)
- {
- rslt[i][j] = GF2Field.multElem(vector1[i], vector2[j]);
- }
- }
- return rslt;
- }
-
- /**
- * Multiplies vector with scalar
- *
- * @param scalar galois element to multiply vector with
- * @param vector vector to be multiplied
- * @return vector multiplied with scalar
- */
- public short[] multVect(short scalar, short[] vector)
- {
- short rslt[] = new short[vector.length];
- for (int n = 0; n < rslt.length; n++)
- {
- rslt[n] = GF2Field.multElem(scalar, vector[n]);
- }
- return rslt;
- }
-
- /**
- * Multiplies matrix with scalar
- *
- * @param scalar galois element to multiply matrix with
- * @param matrix 2-dim n x n matrix to be multiplied
- * @return matrix multiplied with scalar
- */
- public short[][] multMatrix(short scalar, short[][] matrix)
- {
- short[][] rslt = new short[matrix.length][matrix[0].length];
- for (int i = 0; i < matrix.length; i++)
- {
- for (int j = 0; j < matrix[0].length; j++)
- {
- rslt[i][j] = GF2Field.multElem(scalar, matrix[i][j]);
- }
- }
- return rslt;
- }
-
- /**
- * Adds the n x n matrices matrix1 and matrix2
- *
- * @param matrix1 first summand
- * @param matrix2 second summand
- * @return addition of matrix1 and matrix2; both having the dimensions n x n
- * @throws RuntimeException in case the addition is not possible because of
- * different dimensions of the matrices
- */
- public short[][] addSquareMatrix(short[][] matrix1, short[][] matrix2)
- {
- if (matrix1.length != matrix2.length || matrix1[0].length != matrix2[0].length)
- {
- throw new RuntimeException("Addition is not possible!");
- }
-
- short[][] rslt = new short[matrix1.length][matrix1.length];//
- for (int i = 0; i < matrix1.length; i++)
- {
- for (int j = 0; j < matrix2.length; j++)
- {
- rslt[i][j] = GF2Field.addElem(matrix1[i][j], matrix2[i][j]);
- }
- }
- return rslt;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/util/GF2Field.java b/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/util/GF2Field.java
deleted file mode 100644
index 8d542799..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/util/GF2Field.java
+++ /dev/null
@@ -1,139 +0,0 @@
-package org.bouncycastle.pqc.crypto.rainbow.util;
-
-/**
- * This class provides the basic operations like addition, multiplication and
- * finding the multiplicative inverse of an element in GF2^8.
- * <p>
- * The operations are implemented using the irreducible polynomial
- * 1+x^2+x^3+x^6+x^8 ( 1 0100 1101 = 0x14d )
- * <p>
- * This class makes use of lookup tables(exps and logs) for implementing the
- * operations in order to increase the efficiency of Rainbow.
- */
-public class GF2Field
-{
-
- public static final int MASK = 0xff;
-
- /*
- * this lookup table is needed for multiplication and computing the
- * multiplicative inverse
- */
- static final short exps[] = {1, 2, 4, 8, 16, 32, 64, 128, 77, 154, 121, 242,
- 169, 31, 62, 124, 248, 189, 55, 110, 220, 245, 167, 3, 6, 12, 24,
- 48, 96, 192, 205, 215, 227, 139, 91, 182, 33, 66, 132, 69, 138, 89,
- 178, 41, 82, 164, 5, 10, 20, 40, 80, 160, 13, 26, 52, 104, 208,
- 237, 151, 99, 198, 193, 207, 211, 235, 155, 123, 246, 161, 15, 30,
- 60, 120, 240, 173, 23, 46, 92, 184, 61, 122, 244, 165, 7, 14, 28,
- 56, 112, 224, 141, 87, 174, 17, 34, 68, 136, 93, 186, 57, 114, 228,
- 133, 71, 142, 81, 162, 9, 18, 36, 72, 144, 109, 218, 249, 191, 51,
- 102, 204, 213, 231, 131, 75, 150, 97, 194, 201, 223, 243, 171, 27,
- 54, 108, 216, 253, 183, 35, 70, 140, 85, 170, 25, 50, 100, 200,
- 221, 247, 163, 11, 22, 44, 88, 176, 45, 90, 180, 37, 74, 148, 101,
- 202, 217, 255, 179, 43, 86, 172, 21, 42, 84, 168, 29, 58, 116, 232,
- 157, 119, 238, 145, 111, 222, 241, 175, 19, 38, 76, 152, 125, 250,
- 185, 63, 126, 252, 181, 39, 78, 156, 117, 234, 153, 127, 254, 177,
- 47, 94, 188, 53, 106, 212, 229, 135, 67, 134, 65, 130, 73, 146,
- 105, 210, 233, 159, 115, 230, 129, 79, 158, 113, 226, 137, 95, 190,
- 49, 98, 196, 197, 199, 195, 203, 219, 251, 187, 59, 118, 236, 149,
- 103, 206, 209, 239, 147, 107, 214, 225, 143, 83, 166, 1};
-
- /*
- * this lookup table is needed for multiplication and computing the
- * multiplicative inverse
- */
- static final short logs[] = {0, 0, 1, 23, 2, 46, 24, 83, 3, 106, 47, 147,
- 25, 52, 84, 69, 4, 92, 107, 182, 48, 166, 148, 75, 26, 140, 53,
- 129, 85, 170, 70, 13, 5, 36, 93, 135, 108, 155, 183, 193, 49, 43,
- 167, 163, 149, 152, 76, 202, 27, 230, 141, 115, 54, 205, 130, 18,
- 86, 98, 171, 240, 71, 79, 14, 189, 6, 212, 37, 210, 94, 39, 136,
- 102, 109, 214, 156, 121, 184, 8, 194, 223, 50, 104, 44, 253, 168,
- 138, 164, 90, 150, 41, 153, 34, 77, 96, 203, 228, 28, 123, 231, 59,
- 142, 158, 116, 244, 55, 216, 206, 249, 131, 111, 19, 178, 87, 225,
- 99, 220, 172, 196, 241, 175, 72, 10, 80, 66, 15, 186, 190, 199, 7,
- 222, 213, 120, 38, 101, 211, 209, 95, 227, 40, 33, 137, 89, 103,
- 252, 110, 177, 215, 248, 157, 243, 122, 58, 185, 198, 9, 65, 195,
- 174, 224, 219, 51, 68, 105, 146, 45, 82, 254, 22, 169, 12, 139,
- 128, 165, 74, 91, 181, 151, 201, 42, 162, 154, 192, 35, 134, 78,
- 188, 97, 239, 204, 17, 229, 114, 29, 61, 124, 235, 232, 233, 60,
- 234, 143, 125, 159, 236, 117, 30, 245, 62, 56, 246, 217, 63, 207,
- 118, 250, 31, 132, 160, 112, 237, 20, 144, 179, 126, 88, 251, 226,
- 32, 100, 208, 221, 119, 173, 218, 197, 64, 242, 57, 176, 247, 73,
- 180, 11, 127, 81, 21, 67, 145, 16, 113, 187, 238, 191, 133, 200,
- 161};
-
- /**
- * This function calculates the sum of two elements as an operation in GF2^8
- *
- * @param x the first element that is to be added
- * @param y the second element that should be add
- * @return the sum of the two elements x and y in GF2^8
- */
- public static short addElem(short x, short y)
- {
- return (short)(x ^ y);
- }
-
- /**
- * This function computes the multiplicative inverse of a given element in
- * GF2^8 The 0 has no multiplicative inverse and in this case 0 is returned.
- *
- * @param x the element which multiplicative inverse is to be computed
- * @return the multiplicative inverse of the given element, in case it
- * exists or 0, otherwise
- */
- public static short invElem(short x)
- {
- if (x == 0)
- {
- return 0;
- }
- return (exps[255 - logs[x]]);
- }
-
- /**
- * This function multiplies two elements in GF2^8. If one of the two
- * elements is 0, 0 is returned.
- *
- * @param x the first element to be multiplied.
- * @param y the second element to be multiplied.
- * @return the product of the two input elements in GF2^8.
- */
- public static short multElem(short x, short y)
- {
- if (x == 0 || y == 0)
- {
- return 0;
- }
- else
- {
- return (exps[(logs[x] + logs[y]) % 255]);
- }
- }
-
- /**
- * This function returns the values of exps-lookup table which correspond to
- * the input
- *
- * @param x the index in the lookup table exps
- * @return exps-value, corresponding to the input
- */
- public static short getExp(short x)
- {
- return exps[x];
- }
-
- /**
- * This function returns the values of logs-lookup table which correspond to
- * the input
- *
- * @param x the index in the lookup table logs
- * @return logs-value, corresponding to the input
- */
- public static short getLog(short x)
- {
- return logs[x];
- }
-
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/util/RainbowUtil.java b/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/util/RainbowUtil.java
deleted file mode 100644
index 2b073b1b..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/crypto/rainbow/util/RainbowUtil.java
+++ /dev/null
@@ -1,230 +0,0 @@
-package org.bouncycastle.pqc.crypto.rainbow.util;
-
-/**
- * This class is needed for the conversions while encoding and decoding, as well as for
- * comparison between arrays of some dimensions
- */
-public class RainbowUtil
-{
-
- /**
- * This function converts an one-dimensional array of bytes into a
- * one-dimensional array of int
- *
- * @param in the array to be converted
- * @return out
- * the one-dimensional int-array that corresponds the input
- */
- public static int[] convertArraytoInt(byte[] in)
- {
- int[] out = new int[in.length];
- for (int i = 0; i < in.length; i++)
- {
- out[i] = in[i] & GF2Field.MASK;
- }
- return out;
- }
-
- /**
- * This function converts an one-dimensional array of bytes into a
- * one-dimensional array of type short
- *
- * @param in the array to be converted
- * @return out
- * one-dimensional short-array that corresponds the input
- */
- public static short[] convertArray(byte[] in)
- {
- short[] out = new short[in.length];
- for (int i = 0; i < in.length; i++)
- {
- out[i] = (short)(in[i] & GF2Field.MASK);
- }
- return out;
- }
-
- /**
- * This function converts a matrix of bytes into a matrix of type short
- *
- * @param in the matrix to be converted
- * @return out
- * short-matrix that corresponds the input
- */
- public static short[][] convertArray(byte[][] in)
- {
- short[][] out = new short[in.length][in[0].length];
- for (int i = 0; i < in.length; i++)
- {
- for (int j = 0; j < in[0].length; j++)
- {
- out[i][j] = (short)(in[i][j] & GF2Field.MASK);
- }
- }
- return out;
- }
-
- /**
- * This function converts a 3-dimensional array of bytes into a 3-dimensional array of type short
- *
- * @param in the array to be converted
- * @return out
- * short-array that corresponds the input
- */
- public static short[][][] convertArray(byte[][][] in)
- {
- short[][][] out = new short[in.length][in[0].length][in[0][0].length];
- for (int i = 0; i < in.length; i++)
- {
- for (int j = 0; j < in[0].length; j++)
- {
- for (int k = 0; k < in[0][0].length; k++)
- {
- out[i][j][k] = (short)(in[i][j][k] & GF2Field.MASK);
- }
- }
- }
- return out;
- }
-
- /**
- * This function converts an array of type int into an array of type byte
- *
- * @param in the array to be converted
- * @return out
- * the byte-array that corresponds the input
- */
- public static byte[] convertIntArray(int[] in)
- {
- byte[] out = new byte[in.length];
- for (int i = 0; i < in.length; i++)
- {
- out[i] = (byte)in[i];
- }
- return out;
- }
-
-
- /**
- * This function converts an array of type short into an array of type byte
- *
- * @param in the array to be converted
- * @return out
- * the byte-array that corresponds the input
- */
- public static byte[] convertArray(short[] in)
- {
- byte[] out = new byte[in.length];
- for (int i = 0; i < in.length; i++)
- {
- out[i] = (byte)in[i];
- }
- return out;
- }
-
- /**
- * This function converts a matrix of type short into a matrix of type byte
- *
- * @param in the matrix to be converted
- * @return out
- * the byte-matrix that corresponds the input
- */
- public static byte[][] convertArray(short[][] in)
- {
- byte[][] out = new byte[in.length][in[0].length];
- for (int i = 0; i < in.length; i++)
- {
- for (int j = 0; j < in[0].length; j++)
- {
- out[i][j] = (byte)in[i][j];
- }
- }
- return out;
- }
-
- /**
- * This function converts a 3-dimensional array of type short into a 3-dimensional array of type byte
- *
- * @param in the array to be converted
- * @return out
- * the byte-array that corresponds the input
- */
- public static byte[][][] convertArray(short[][][] in)
- {
- byte[][][] out = new byte[in.length][in[0].length][in[0][0].length];
- for (int i = 0; i < in.length; i++)
- {
- for (int j = 0; j < in[0].length; j++)
- {
- for (int k = 0; k < in[0][0].length; k++)
- {
- out[i][j][k] = (byte)in[i][j][k];
- }
- }
- }
- return out;
- }
-
- /**
- * Compare two short arrays. No null checks are performed.
- *
- * @param left the first short array
- * @param right the second short array
- * @return the result of the comparison
- */
- public static boolean equals(short[] left, short[] right)
- {
- if (left.length != right.length)
- {
- return false;
- }
- boolean result = true;
- for (int i = left.length - 1; i >= 0; i--)
- {
- result &= left[i] == right[i];
- }
- return result;
- }
-
- /**
- * Compare two two-dimensional short arrays. No null checks are performed.
- *
- * @param left the first short array
- * @param right the second short array
- * @return the result of the comparison
- */
- public static boolean equals(short[][] left, short[][] right)
- {
- if (left.length != right.length)
- {
- return false;
- }
- boolean result = true;
- for (int i = left.length - 1; i >= 0; i--)
- {
- result &= equals(left[i], right[i]);
- }
- return result;
- }
-
- /**
- * Compare two three-dimensional short arrays. No null checks are performed.
- *
- * @param left the first short array
- * @param right the second short array
- * @return the result of the comparison
- */
- public static boolean equals(short[][][] left, short[][][] right)
- {
- if (left.length != right.length)
- {
- return false;
- }
- boolean result = true;
- for (int i = left.length - 1; i >= 0; i--)
- {
- result &= equals(left[i], right[i]);
- }
- return result;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/BigEndianConversions.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/BigEndianConversions.java
deleted file mode 100644
index 90926f67..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/BigEndianConversions.java
+++ /dev/null
@@ -1,306 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-
-/**
- * This is a utility class containing data type conversions using big-endian
- * byte order.
- *
- * @see LittleEndianConversions
- */
-public final class BigEndianConversions
-{
-
- /**
- * Default constructor (private).
- */
- private BigEndianConversions()
- {
- // empty
- }
-
- /**
- * Convert an integer to an octet string of length 4 according to IEEE 1363,
- * Section 5.5.3.
- *
- * @param x the integer to convert
- * @return the converted integer
- */
- public static byte[] I2OSP(int x)
- {
- byte[] result = new byte[4];
- result[0] = (byte)(x >>> 24);
- result[1] = (byte)(x >>> 16);
- result[2] = (byte)(x >>> 8);
- result[3] = (byte)x;
- return result;
- }
-
- /**
- * Convert an integer to an octet string according to IEEE 1363, Section
- * 5.5.3. Length checking is performed.
- *
- * @param x the integer to convert
- * @param oLen the desired length of the octet string
- * @return an octet string of length <tt>oLen</tt> representing the
- * integer <tt>x</tt>, or <tt>null</tt> if the integer is
- * negative
- * @throws ArithmeticException if <tt>x</tt> can't be encoded into <tt>oLen</tt>
- * octets.
- */
- public static byte[] I2OSP(int x, int oLen)
- throws ArithmeticException
- {
- if (x < 0)
- {
- return null;
- }
- int octL = IntegerFunctions.ceilLog256(x);
- if (octL > oLen)
- {
- throw new ArithmeticException(
- "Cannot encode given integer into specified number of octets.");
- }
- byte[] result = new byte[oLen];
- for (int i = oLen - 1; i >= oLen - octL; i--)
- {
- result[i] = (byte)(x >>> (8 * (oLen - 1 - i)));
- }
- return result;
- }
-
- /**
- * Convert an integer to an octet string of length 4 according to IEEE 1363,
- * Section 5.5.3.
- *
- * @param input the integer to convert
- * @param output byte array holding the output
- * @param outOff offset in output array where the result is stored
- */
- public static void I2OSP(int input, byte[] output, int outOff)
- {
- output[outOff++] = (byte)(input >>> 24);
- output[outOff++] = (byte)(input >>> 16);
- output[outOff++] = (byte)(input >>> 8);
- output[outOff] = (byte)input;
- }
-
- /**
- * Convert an integer to an octet string of length 8 according to IEEE 1363,
- * Section 5.5.3.
- *
- * @param input the integer to convert
- * @return the converted integer
- */
- public static byte[] I2OSP(long input)
- {
- byte[] output = new byte[8];
- output[0] = (byte)(input >>> 56);
- output[1] = (byte)(input >>> 48);
- output[2] = (byte)(input >>> 40);
- output[3] = (byte)(input >>> 32);
- output[4] = (byte)(input >>> 24);
- output[5] = (byte)(input >>> 16);
- output[6] = (byte)(input >>> 8);
- output[7] = (byte)input;
- return output;
- }
-
- /**
- * Convert an integer to an octet string of length 8 according to IEEE 1363,
- * Section 5.5.3.
- *
- * @param input the integer to convert
- * @param output byte array holding the output
- * @param outOff offset in output array where the result is stored
- */
- public static void I2OSP(long input, byte[] output, int outOff)
- {
- output[outOff++] = (byte)(input >>> 56);
- output[outOff++] = (byte)(input >>> 48);
- output[outOff++] = (byte)(input >>> 40);
- output[outOff++] = (byte)(input >>> 32);
- output[outOff++] = (byte)(input >>> 24);
- output[outOff++] = (byte)(input >>> 16);
- output[outOff++] = (byte)(input >>> 8);
- output[outOff] = (byte)input;
- }
-
- /**
- * Convert an integer to an octet string of the specified length according
- * to IEEE 1363, Section 5.5.3. No length checking is performed (i.e., if
- * the integer cannot be encoded into <tt>length</tt> octets, it is
- * truncated).
- *
- * @param input the integer to convert
- * @param output byte array holding the output
- * @param outOff offset in output array where the result is stored
- * @param length the length of the encoding
- */
- public static void I2OSP(int input, byte[] output, int outOff, int length)
- {
- for (int i = length - 1; i >= 0; i--)
- {
- output[outOff + i] = (byte)(input >>> (8 * (length - 1 - i)));
- }
- }
-
- /**
- * Convert an octet string to an integer according to IEEE 1363, Section
- * 5.5.3.
- *
- * @param input the byte array holding the octet string
- * @return an integer representing the octet string <tt>input</tt>, or
- * <tt>0</tt> if the represented integer is negative or too large
- * or the byte array is empty
- * @throws ArithmeticException if the length of the given octet string is larger than 4.
- */
- public static int OS2IP(byte[] input)
- {
- if (input.length > 4)
- {
- throw new ArithmeticException("invalid input length");
- }
- if (input.length == 0)
- {
- return 0;
- }
- int result = 0;
- for (int j = 0; j < input.length; j++)
- {
- result |= (input[j] & 0xff) << (8 * (input.length - 1 - j));
- }
- return result;
- }
-
- /**
- * Convert a byte array of length 4 beginning at <tt>offset</tt> into an
- * integer.
- *
- * @param input the byte array
- * @param inOff the offset into the byte array
- * @return the resulting integer
- */
- public static int OS2IP(byte[] input, int inOff)
- {
- int result = (input[inOff++] & 0xff) << 24;
- result |= (input[inOff++] & 0xff) << 16;
- result |= (input[inOff++] & 0xff) << 8;
- result |= input[inOff] & 0xff;
- return result;
- }
-
- /**
- * Convert an octet string to an integer according to IEEE 1363, Section
- * 5.5.3.
- *
- * @param input the byte array holding the octet string
- * @param inOff the offset in the input byte array where the octet string
- * starts
- * @param inLen the length of the encoded integer
- * @return an integer representing the octet string <tt>bytes</tt>, or
- * <tt>0</tt> if the represented integer is negative or too large
- * or the byte array is empty
- */
- public static int OS2IP(byte[] input, int inOff, int inLen)
- {
- if ((input.length == 0) || input.length < inOff + inLen - 1)
- {
- return 0;
- }
- int result = 0;
- for (int j = 0; j < inLen; j++)
- {
- result |= (input[inOff + j] & 0xff) << (8 * (inLen - j - 1));
- }
- return result;
- }
-
- /**
- * Convert a byte array of length 8 beginning at <tt>inOff</tt> into a
- * long integer.
- *
- * @param input the byte array
- * @param inOff the offset into the byte array
- * @return the resulting long integer
- */
- public static long OS2LIP(byte[] input, int inOff)
- {
- long result = ((long)input[inOff++] & 0xff) << 56;
- result |= ((long)input[inOff++] & 0xff) << 48;
- result |= ((long)input[inOff++] & 0xff) << 40;
- result |= ((long)input[inOff++] & 0xff) << 32;
- result |= ((long)input[inOff++] & 0xff) << 24;
- result |= (input[inOff++] & 0xff) << 16;
- result |= (input[inOff++] & 0xff) << 8;
- result |= input[inOff] & 0xff;
- return result;
- }
-
- /**
- * Convert an int array into a byte array.
- *
- * @param input the int array
- * @return the converted array
- */
- public static byte[] toByteArray(final int[] input)
- {
- byte[] result = new byte[input.length << 2];
- for (int i = 0; i < input.length; i++)
- {
- I2OSP(input[i], result, i << 2);
- }
- return result;
- }
-
- /**
- * Convert an int array into a byte array of the specified length. No length
- * checking is performed (i.e., if the last integer cannot be encoded into
- * <tt>length % 4</tt> octets, it is truncated).
- *
- * @param input the int array
- * @param length the length of the converted array
- * @return the converted array
- */
- public static byte[] toByteArray(final int[] input, int length)
- {
- final int intLen = input.length;
- byte[] result = new byte[length];
- int index = 0;
- for (int i = 0; i <= intLen - 2; i++, index += 4)
- {
- I2OSP(input[i], result, index);
- }
- I2OSP(input[intLen - 1], result, index, length - index);
- return result;
- }
-
- /**
- * Convert a byte array into an int array.
- *
- * @param input the byte array
- * @return the converted array
- */
- public static int[] toIntArray(byte[] input)
- {
- final int intLen = (input.length + 3) / 4;
- final int lastLen = input.length & 0x03;
- int[] result = new int[intLen];
-
- int index = 0;
- for (int i = 0; i <= intLen - 2; i++, index += 4)
- {
- result[i] = OS2IP(input, index);
- }
- if (lastLen != 0)
- {
- result[intLen - 1] = OS2IP(input, index, lastLen);
- }
- else
- {
- result[intLen - 1] = OS2IP(input, index);
- }
-
- return result;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/BigIntUtils.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/BigIntUtils.java
deleted file mode 100644
index b99ed41b..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/BigIntUtils.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-import java.math.BigInteger;
-
-/**
- * FIXME: is this really necessary?!
- */
-public final class BigIntUtils
-{
-
- /**
- * Default constructor (private).
- */
- private BigIntUtils()
- {
- // empty
- }
-
- /**
- * Checks if two BigInteger arrays contain the same entries
- *
- * @param a first BigInteger array
- * @param b second BigInteger array
- * @return true or false
- */
- public static boolean equals(BigInteger[] a, BigInteger[] b)
- {
- int flag = 0;
-
- if (a.length != b.length)
- {
- return false;
- }
- for (int i = 0; i < a.length; i++)
- {
- // avoid branches here!
- // problem: compareTo on BigIntegers is not
- // guaranteed constant-time!
- flag |= a[i].compareTo(b[i]);
- }
- return flag == 0;
- }
-
- /**
- * Fill the given BigInteger array with the given value.
- *
- * @param array the array
- * @param value the value
- */
- public static void fill(BigInteger[] array, BigInteger value)
- {
- for (int i = array.length - 1; i >= 0; i--)
- {
- array[i] = value;
- }
- }
-
- /**
- * Generates a subarray of a given BigInteger array.
- *
- * @param input -
- * the input BigInteger array
- * @param start -
- * the start index
- * @param end -
- * the end index
- * @return a subarray of <tt>input</tt>, ranging from <tt>start</tt> to
- * <tt>end</tt>
- */
- public static BigInteger[] subArray(BigInteger[] input, int start, int end)
- {
- BigInteger[] result = new BigInteger[end - start];
- System.arraycopy(input, start, result, 0, end - start);
- return result;
- }
-
- /**
- * Converts a BigInteger array into an integer array
- *
- * @param input -
- * the BigInteger array
- * @return the integer array
- */
- public static int[] toIntArray(BigInteger[] input)
- {
- int[] result = new int[input.length];
- for (int i = 0; i < input.length; i++)
- {
- result[i] = input[i].intValue();
- }
- return result;
- }
-
- /**
- * Converts a BigInteger array into an integer array, reducing all
- * BigIntegers mod q.
- *
- * @param q -
- * the modulus
- * @param input -
- * the BigInteger array
- * @return the integer array
- */
- public static int[] toIntArrayModQ(int q, BigInteger[] input)
- {
- BigInteger bq = BigInteger.valueOf(q);
- int[] result = new int[input.length];
- for (int i = 0; i < input.length; i++)
- {
- result[i] = input[i].mod(bq).intValue();
- }
- return result;
- }
-
- /**
- * Return the value of <tt>big</tt> as a byte array. Although BigInteger
- * has such a method, it uses an extra bit to indicate the sign of the
- * number. For elliptic curve cryptography, the numbers usually are
- * positive. Thus, this helper method returns a byte array of minimal
- * length, ignoring the sign of the number.
- *
- * @param value the <tt>BigInteger</tt> value to be converted to a byte
- * array
- * @return the value <tt>big</tt> as byte array
- */
- public static byte[] toMinimalByteArray(BigInteger value)
- {
- byte[] valBytes = value.toByteArray();
- if ((valBytes.length == 1) || (value.bitLength() & 0x07) != 0)
- {
- return valBytes;
- }
- byte[] result = new byte[value.bitLength() >> 3];
- System.arraycopy(valBytes, 1, result, 0, result.length);
- return result;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/ByteUtils.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/ByteUtils.java
deleted file mode 100644
index 5ad91f41..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/ByteUtils.java
+++ /dev/null
@@ -1,414 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-/**
- * This class is a utility class for manipulating byte arrays.
- */
-public final class ByteUtils
-{
-
- private static final char[] HEX_CHARS = {'0', '1', '2', '3', '4', '5',
- '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
-
- /**
- * Default constructor (private)
- */
- private ByteUtils()
- {
- // empty
- }
-
- /**
- * Compare two byte arrays (perform null checks beforehand).
- *
- * @param left the first byte array
- * @param right the second byte array
- * @return the result of the comparison
- */
- public static boolean equals(byte[] left, byte[] right)
- {
- if (left == null)
- {
- return right == null;
- }
- if (right == null)
- {
- return false;
- }
-
- if (left.length != right.length)
- {
- return false;
- }
- boolean result = true;
- for (int i = left.length - 1; i >= 0; i--)
- {
- result &= left[i] == right[i];
- }
- return result;
- }
-
- /**
- * Compare two two-dimensional byte arrays. No null checks are performed.
- *
- * @param left the first byte array
- * @param right the second byte array
- * @return the result of the comparison
- */
- public static boolean equals(byte[][] left, byte[][] right)
- {
- if (left.length != right.length)
- {
- return false;
- }
-
- boolean result = true;
- for (int i = left.length - 1; i >= 0; i--)
- {
- result &= ByteUtils.equals(left[i], right[i]);
- }
-
- return result;
- }
-
- /**
- * Compare two three-dimensional byte arrays. No null checks are performed.
- *
- * @param left the first byte array
- * @param right the second byte array
- * @return the result of the comparison
- */
- public static boolean equals(byte[][][] left, byte[][][] right)
- {
- if (left.length != right.length)
- {
- return false;
- }
-
- boolean result = true;
- for (int i = left.length - 1; i >= 0; i--)
- {
- if (left[i].length != right[i].length)
- {
- return false;
- }
- for (int j = left[i].length - 1; j >= 0; j--)
- {
- result &= ByteUtils.equals(left[i][j], right[i][j]);
- }
- }
-
- return result;
- }
-
- /**
- * Computes a hashcode based on the contents of a one-dimensional byte array
- * rather than its identity.
- *
- * @param array the array to compute the hashcode of
- * @return the hashcode
- */
- public static int deepHashCode(byte[] array)
- {
- int result = 1;
- for (int i = 0; i < array.length; i++)
- {
- result = 31 * result + array[i];
- }
- return result;
- }
-
- /**
- * Computes a hashcode based on the contents of a two-dimensional byte array
- * rather than its identity.
- *
- * @param array the array to compute the hashcode of
- * @return the hashcode
- */
- public static int deepHashCode(byte[][] array)
- {
- int result = 1;
- for (int i = 0; i < array.length; i++)
- {
- result = 31 * result + deepHashCode(array[i]);
- }
- return result;
- }
-
- /**
- * Computes a hashcode based on the contents of a three-dimensional byte
- * array rather than its identity.
- *
- * @param array the array to compute the hashcode of
- * @return the hashcode
- */
- public static int deepHashCode(byte[][][] array)
- {
- int result = 1;
- for (int i = 0; i < array.length; i++)
- {
- result = 31 * result + deepHashCode(array[i]);
- }
- return result;
- }
-
-
- /**
- * Return a clone of the given byte array (performs null check beforehand).
- *
- * @param array the array to clone
- * @return the clone of the given array, or <tt>null</tt> if the array is
- * <tt>null</tt>
- */
- public static byte[] clone(byte[] array)
- {
- if (array == null)
- {
- return null;
- }
- byte[] result = new byte[array.length];
- System.arraycopy(array, 0, result, 0, array.length);
- return result;
- }
-
- /**
- * Convert a string containing hexadecimal characters to a byte-array.
- *
- * @param s a hex string
- * @return a byte array with the corresponding value
- */
- public static byte[] fromHexString(String s)
- {
- char[] rawChars = s.toUpperCase().toCharArray();
-
- int hexChars = 0;
- for (int i = 0; i < rawChars.length; i++)
- {
- if ((rawChars[i] >= '0' && rawChars[i] <= '9')
- || (rawChars[i] >= 'A' && rawChars[i] <= 'F'))
- {
- hexChars++;
- }
- }
-
- byte[] byteString = new byte[(hexChars + 1) >> 1];
-
- int pos = hexChars & 1;
-
- for (int i = 0; i < rawChars.length; i++)
- {
- if (rawChars[i] >= '0' && rawChars[i] <= '9')
- {
- byteString[pos >> 1] <<= 4;
- byteString[pos >> 1] |= rawChars[i] - '0';
- }
- else if (rawChars[i] >= 'A' && rawChars[i] <= 'F')
- {
- byteString[pos >> 1] <<= 4;
- byteString[pos >> 1] |= rawChars[i] - 'A' + 10;
- }
- else
- {
- continue;
- }
- pos++;
- }
-
- return byteString;
- }
-
- /**
- * Convert a byte array to the corresponding hexstring.
- *
- * @param input the byte array to be converted
- * @return the corresponding hexstring
- */
- public static String toHexString(byte[] input)
- {
- String result = "";
- for (int i = 0; i < input.length; i++)
- {
- result += HEX_CHARS[(input[i] >>> 4) & 0x0f];
- result += HEX_CHARS[(input[i]) & 0x0f];
- }
- return result;
- }
-
- /**
- * Convert a byte array to the corresponding hex string.
- *
- * @param input the byte array to be converted
- * @param prefix the prefix to put at the beginning of the hex string
- * @param seperator a separator string
- * @return the corresponding hex string
- */
- public static String toHexString(byte[] input, String prefix,
- String seperator)
- {
- String result = new String(prefix);
- for (int i = 0; i < input.length; i++)
- {
- result += HEX_CHARS[(input[i] >>> 4) & 0x0f];
- result += HEX_CHARS[(input[i]) & 0x0f];
- if (i < input.length - 1)
- {
- result += seperator;
- }
- }
- return result;
- }
-
- /**
- * Convert a byte array to the corresponding bit string.
- *
- * @param input the byte array to be converted
- * @return the corresponding bit string
- */
- public static String toBinaryString(byte[] input)
- {
- String result = "";
- int i;
- for (i = 0; i < input.length; i++)
- {
- int e = input[i];
- for (int ii = 0; ii < 8; ii++)
- {
- int b = (e >>> ii) & 1;
- result += b;
- }
- if (i != input.length - 1)
- {
- result += " ";
- }
- }
- return result;
- }
-
- /**
- * Compute the bitwise XOR of two arrays of bytes. The arrays have to be of
- * same length. No length checking is performed.
- *
- * @param x1 the first array
- * @param x2 the second array
- * @return x1 XOR x2
- */
- public static byte[] xor(byte[] x1, byte[] x2)
- {
- byte[] out = new byte[x1.length];
-
- for (int i = x1.length - 1; i >= 0; i--)
- {
- out[i] = (byte)(x1[i] ^ x2[i]);
- }
- return out;
- }
-
- /**
- * Concatenate two byte arrays. No null checks are performed.
- *
- * @param x1 the first array
- * @param x2 the second array
- * @return (x2||x1) (little-endian order, i.e. x1 is at lower memory
- * addresses)
- */
- public static byte[] concatenate(byte[] x1, byte[] x2)
- {
- byte[] result = new byte[x1.length + x2.length];
-
- System.arraycopy(x1, 0, result, 0, x1.length);
- System.arraycopy(x2, 0, result, x1.length, x2.length);
-
- return result;
- }
-
- /**
- * Convert a 2-dimensional byte array into a 1-dimensional byte array by
- * concatenating all entries.
- *
- * @param array a 2-dimensional byte array
- * @return the concatenated input array
- */
- public static byte[] concatenate(byte[][] array)
- {
- int rowLength = array[0].length;
- byte[] result = new byte[array.length * rowLength];
- int index = 0;
- for (int i = 0; i < array.length; i++)
- {
- System.arraycopy(array[i], 0, result, index, rowLength);
- index += rowLength;
- }
- return result;
- }
-
- /**
- * Split a byte array <tt>input</tt> into two arrays at <tt>index</tt>,
- * i.e. the first array will have the lower <tt>index</tt> bytes, the
- * second one the higher <tt>input.length - index</tt> bytes.
- *
- * @param input the byte array to be split
- * @param index the index where the byte array is split
- * @return the splitted input array as an array of two byte arrays
- * @throws ArrayIndexOutOfBoundsException if <tt>index</tt> is out of bounds
- */
- public static byte[][] split(byte[] input, int index)
- throws ArrayIndexOutOfBoundsException
- {
- if (index > input.length)
- {
- throw new ArrayIndexOutOfBoundsException();
- }
- byte[][] result = new byte[2][];
- result[0] = new byte[index];
- result[1] = new byte[input.length - index];
- System.arraycopy(input, 0, result[0], 0, index);
- System.arraycopy(input, index, result[1], 0, input.length - index);
- return result;
- }
-
- /**
- * Generate a subarray of a given byte array.
- *
- * @param input the input byte array
- * @param start the start index
- * @param end the end index
- * @return a subarray of <tt>input</tt>, ranging from <tt>start</tt>
- * (inclusively) to <tt>end</tt> (exclusively)
- */
- public static byte[] subArray(byte[] input, int start, int end)
- {
- byte[] result = new byte[end - start];
- System.arraycopy(input, start, result, 0, end - start);
- return result;
- }
-
- /**
- * Generate a subarray of a given byte array.
- *
- * @param input the input byte array
- * @param start the start index
- * @return a subarray of <tt>input</tt>, ranging from <tt>start</tt> to
- * the end of the array
- */
- public static byte[] subArray(byte[] input, int start)
- {
- return subArray(input, start, input.length);
- }
-
- /**
- * Rewrite a byte array as a char array
- *
- * @param input -
- * the byte array
- * @return char array
- */
- public static char[] toCharArray(byte[] input)
- {
- char[] result = new char[input.length];
- for (int i = 0; i < input.length; i++)
- {
- result[i] = (char)input[i];
- }
- return result;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/CharUtils.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/CharUtils.java
deleted file mode 100644
index 1800685d..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/CharUtils.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-public final class CharUtils
-{
-
- /**
- * Default constructor (private)
- */
- private CharUtils()
- {
- // empty
- }
-
- /**
- * Return a clone of the given char array. No null checks are performed.
- *
- * @param array the array to clone
- * @return the clone of the given array
- */
- public static char[] clone(char[] array)
- {
- char[] result = new char[array.length];
- System.arraycopy(array, 0, result, 0, array.length);
- return result;
- }
-
- /**
- * Convert the given char array into a byte array.
- *
- * @param chars the char array
- * @return the converted array
- */
- public static byte[] toByteArray(char[] chars)
- {
- byte[] result = new byte[chars.length];
- for (int i = chars.length - 1; i >= 0; i--)
- {
- result[i] = (byte)chars[i];
- }
- return result;
- }
-
- /**
- * Convert the given char array into a
- * byte array for use with PBE encryption.
- *
- * @param chars the char array
- * @return the converted array
- */
- public static byte[] toByteArrayForPBE(char[] chars)
- {
-
- byte[] out = new byte[chars.length];
-
- for (int i = 0; i < chars.length; i++)
- {
- out[i] = (byte)chars[i];
- }
-
- int length = out.length * 2;
- byte[] ret = new byte[length + 2];
-
- int j = 0;
- for (int i = 0; i < out.length; i++)
- {
- j = i * 2;
- ret[j] = 0;
- ret[j + 1] = out[i];
- }
-
- ret[length] = 0;
- ret[length + 1] = 0;
-
- return ret;
- }
-
- /**
- * Compare two char arrays. No null checks are performed.
- *
- * @param left the char byte array
- * @param right the second char array
- * @return the result of the comparison
- */
- public static boolean equals(char[] left, char[] right)
- {
- if (left.length != right.length)
- {
- return false;
- }
- boolean result = true;
- for (int i = left.length - 1; i >= 0; i--)
- {
- result &= left[i] == right[i];
- }
- return result;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Matrix.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Matrix.java
deleted file mode 100644
index a61f9507..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Matrix.java
+++ /dev/null
@@ -1,1323 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-import java.security.SecureRandom;
-
-/**
- * This class describes some operations with matrices over finite field GF(2)
- * and is used in ecc and MQ-PKC (also has some specific methods and
- * implementation)
- */
-public class GF2Matrix
- extends Matrix
-{
-
- /**
- * For the matrix representation the array of type int[][] is used, thus one
- * element of the array keeps 32 elements of the matrix (from one row and 32
- * columns)
- */
- private int[][] matrix;
-
- /**
- * the length of each array representing a row of this matrix, computed as
- * <tt>(numColumns + 31) / 32</tt>
- */
- private int length;
-
- /**
- * Create the matrix from encoded form.
- *
- * @param enc the encoded matrix
- */
- public GF2Matrix(byte[] enc)
- {
- if (enc.length < 9)
- {
- throw new ArithmeticException(
- "given array is not an encoded matrix over GF(2)");
- }
-
- numRows = LittleEndianConversions.OS2IP(enc, 0);
- numColumns = LittleEndianConversions.OS2IP(enc, 4);
-
- int n = ((numColumns + 7) >>> 3) * numRows;
-
- if ((numRows <= 0) || (n != (enc.length - 8)))
- {
- throw new ArithmeticException(
- "given array is not an encoded matrix over GF(2)");
- }
-
- length = (numColumns + 31) >>> 5;
- matrix = new int[numRows][length];
-
- // number of "full" integer
- int q = numColumns >> 5;
- // number of bits in non-full integer
- int r = numColumns & 0x1f;
-
- int count = 8;
- for (int i = 0; i < numRows; i++)
- {
- for (int j = 0; j < q; j++, count += 4)
- {
- matrix[i][j] = LittleEndianConversions.OS2IP(enc, count);
- }
- for (int j = 0; j < r; j += 8)
- {
- matrix[i][q] ^= (enc[count++] & 0xff) << j;
- }
- }
- }
-
- /**
- * Create the matrix with the contents of the given array. The matrix is not
- * copied. Unused coefficients are masked out.
- *
- * @param numColumns the number of columns
- * @param matrix the element array
- */
- public GF2Matrix(int numColumns, int[][] matrix)
- {
- if (matrix[0].length != (numColumns + 31) >> 5)
- {
- throw new ArithmeticException(
- "Int array does not match given number of columns.");
- }
- this.numColumns = numColumns;
- numRows = matrix.length;
- length = matrix[0].length;
- int rest = numColumns & 0x1f;
- int bitMask;
- if (rest == 0)
- {
- bitMask = 0xffffffff;
- }
- else
- {
- bitMask = (1 << rest) - 1;
- }
- for (int i = 0; i < numRows; i++)
- {
- matrix[i][length - 1] &= bitMask;
- }
- this.matrix = matrix;
- }
-
- /**
- * Create an nxn matrix of the given type.
- *
- * @param n the number of rows (and columns)
- * @param typeOfMatrix the martix type (see {@link Matrix} for predefined
- * constants)
- */
- public GF2Matrix(int n, char typeOfMatrix)
- {
- this(n, typeOfMatrix, new java.security.SecureRandom());
- }
-
- /**
- * Create an nxn matrix of the given type.
- *
- * @param n the matrix size
- * @param typeOfMatrix the matrix type
- * @param sr the source of randomness
- */
- public GF2Matrix(int n, char typeOfMatrix, SecureRandom sr)
- {
- if (n <= 0)
- {
- throw new ArithmeticException("Size of matrix is non-positive.");
- }
-
- switch (typeOfMatrix)
- {
-
- case Matrix.MATRIX_TYPE_ZERO:
- assignZeroMatrix(n, n);
- break;
-
- case Matrix.MATRIX_TYPE_UNIT:
- assignUnitMatrix(n);
- break;
-
- case Matrix.MATRIX_TYPE_RANDOM_LT:
- assignRandomLowerTriangularMatrix(n, sr);
- break;
-
- case Matrix.MATRIX_TYPE_RANDOM_UT:
- assignRandomUpperTriangularMatrix(n, sr);
- break;
-
- case Matrix.MATRIX_TYPE_RANDOM_REGULAR:
- assignRandomRegularMatrix(n, sr);
- break;
-
- default:
- throw new ArithmeticException("Unknown matrix type.");
- }
- }
-
- /**
- * Copy constructor.
- *
- * @param a another {@link GF2Matrix}
- */
- public GF2Matrix(GF2Matrix a)
- {
- numColumns = a.getNumColumns();
- numRows = a.getNumRows();
- length = a.length;
- matrix = new int[a.matrix.length][];
- for (int i = 0; i < matrix.length; i++)
- {
- matrix[i] = IntUtils.clone(a.matrix[i]);
- }
-
- }
-
- /**
- * create the mxn zero matrix
- */
- private GF2Matrix(int m, int n)
- {
- if ((n <= 0) || (m <= 0))
- {
- throw new ArithmeticException("size of matrix is non-positive");
- }
-
- assignZeroMatrix(m, n);
- }
-
- /**
- * Create the mxn zero matrix.
- *
- * @param m number of rows
- * @param n number of columns
- */
- private void assignZeroMatrix(int m, int n)
- {
- numRows = m;
- numColumns = n;
- length = (n + 31) >>> 5;
- matrix = new int[numRows][length];
- for (int i = 0; i < numRows; i++)
- {
- for (int j = 0; j < length; j++)
- {
- matrix[i][j] = 0;
- }
- }
- }
-
- /**
- * Create the mxn unit matrix.
- *
- * @param n number of rows (and columns)
- */
- private void assignUnitMatrix(int n)
- {
- numRows = n;
- numColumns = n;
- length = (n + 31) >>> 5;
- matrix = new int[numRows][length];
- for (int i = 0; i < numRows; i++)
- {
- for (int j = 0; j < length; j++)
- {
- matrix[i][j] = 0;
- }
- }
- for (int i = 0; i < numRows; i++)
- {
- int rest = i & 0x1f;
- matrix[i][i >>> 5] = 1 << rest;
- }
- }
-
- /**
- * Create a nxn random lower triangular matrix.
- *
- * @param n number of rows (and columns)
- * @param sr source of randomness
- */
- private void assignRandomLowerTriangularMatrix(int n, SecureRandom sr)
- {
- numRows = n;
- numColumns = n;
- length = (n + 31) >>> 5;
- matrix = new int[numRows][length];
- for (int i = 0; i < numRows; i++)
- {
- int q = i >>> 5;
- int r = i & 0x1f;
- int s = 31 - r;
- r = 1 << r;
- for (int j = 0; j < q; j++)
- {
- matrix[i][j] = sr.nextInt();
- }
- matrix[i][q] = (sr.nextInt() >>> s) | r;
- for (int j = q + 1; j < length; j++)
- {
- matrix[i][j] = 0;
- }
-
- }
-
- }
-
- /**
- * Create a nxn random upper triangular matrix.
- *
- * @param n number of rows (and columns)
- * @param sr source of randomness
- */
- private void assignRandomUpperTriangularMatrix(int n, SecureRandom sr)
- {
- numRows = n;
- numColumns = n;
- length = (n + 31) >>> 5;
- matrix = new int[numRows][length];
- int rest = n & 0x1f;
- int help;
- if (rest == 0)
- {
- help = 0xffffffff;
- }
- else
- {
- help = (1 << rest) - 1;
- }
- for (int i = 0; i < numRows; i++)
- {
- int q = i >>> 5;
- int r = i & 0x1f;
- int s = r;
- r = 1 << r;
- for (int j = 0; j < q; j++)
- {
- matrix[i][j] = 0;
- }
- matrix[i][q] = (sr.nextInt() << s) | r;
- for (int j = q + 1; j < length; j++)
- {
- matrix[i][j] = sr.nextInt();
- }
- matrix[i][length - 1] &= help;
- }
-
- }
-
- /**
- * Create an nxn random regular matrix.
- *
- * @param n number of rows (and columns)
- * @param sr source of randomness
- */
- private void assignRandomRegularMatrix(int n, SecureRandom sr)
- {
- numRows = n;
- numColumns = n;
- length = (n + 31) >>> 5;
- matrix = new int[numRows][length];
- GF2Matrix lm = new GF2Matrix(n, Matrix.MATRIX_TYPE_RANDOM_LT, sr);
- GF2Matrix um = new GF2Matrix(n, Matrix.MATRIX_TYPE_RANDOM_UT, sr);
- GF2Matrix rm = (GF2Matrix)lm.rightMultiply(um);
- Permutation perm = new Permutation(n, sr);
- int[] p = perm.getVector();
- for (int i = 0; i < n; i++)
- {
- System.arraycopy(rm.matrix[i], 0, matrix[p[i]], 0, length);
- }
- }
-
- /**
- * Create a nxn random regular matrix and its inverse.
- *
- * @param n number of rows (and columns)
- * @param sr source of randomness
- * @return the created random regular matrix and its inverse
- */
- public static GF2Matrix[] createRandomRegularMatrixAndItsInverse(int n,
- SecureRandom sr)
- {
-
- GF2Matrix[] result = new GF2Matrix[2];
-
- // ------------------------------------
- // First part: create regular matrix
- // ------------------------------------
-
- // ------
- int length = (n + 31) >> 5;
- GF2Matrix lm = new GF2Matrix(n, Matrix.MATRIX_TYPE_RANDOM_LT, sr);
- GF2Matrix um = new GF2Matrix(n, Matrix.MATRIX_TYPE_RANDOM_UT, sr);
- GF2Matrix rm = (GF2Matrix)lm.rightMultiply(um);
- Permutation p = new Permutation(n, sr);
- int[] pVec = p.getVector();
-
- int[][] matrix = new int[n][length];
- for (int i = 0; i < n; i++)
- {
- System.arraycopy(rm.matrix[pVec[i]], 0, matrix[i], 0, length);
- }
-
- result[0] = new GF2Matrix(n, matrix);
-
- // ------------------------------------
- // Second part: create inverse matrix
- // ------------------------------------
-
- // inverse to lm
- GF2Matrix invLm = new GF2Matrix(n, Matrix.MATRIX_TYPE_UNIT);
- for (int i = 0; i < n; i++)
- {
- int rest = i & 0x1f;
- int q = i >>> 5;
- int r = 1 << rest;
- for (int j = i + 1; j < n; j++)
- {
- int b = (lm.matrix[j][q]) & r;
- if (b != 0)
- {
- for (int k = 0; k <= q; k++)
- {
- invLm.matrix[j][k] ^= invLm.matrix[i][k];
- }
- }
- }
- }
- // inverse to um
- GF2Matrix invUm = new GF2Matrix(n, Matrix.MATRIX_TYPE_UNIT);
- for (int i = n - 1; i >= 0; i--)
- {
- int rest = i & 0x1f;
- int q = i >>> 5;
- int r = 1 << rest;
- for (int j = i - 1; j >= 0; j--)
- {
- int b = (um.matrix[j][q]) & r;
- if (b != 0)
- {
- for (int k = q; k < length; k++)
- {
- invUm.matrix[j][k] ^= invUm.matrix[i][k];
- }
- }
- }
- }
-
- // inverse matrix
- result[1] = (GF2Matrix)invUm.rightMultiply(invLm.rightMultiply(p));
-
- return result;
- }
-
- /**
- * @return the array keeping the matrix elements
- */
- public int[][] getIntArray()
- {
- return matrix;
- }
-
- /**
- * @return the length of each array representing a row of this matrix
- */
- public int getLength()
- {
- return length;
- }
-
- /**
- * Return the row of this matrix with the given index.
- *
- * @param index the index
- * @return the row of this matrix with the given index
- */
- public int[] getRow(int index)
- {
- return matrix[index];
- }
-
- /**
- * Returns encoded matrix, i.e., this matrix in byte array form
- *
- * @return the encoded matrix
- */
- public byte[] getEncoded()
- {
- int n = (numColumns + 7) >>> 3;
- n *= numRows;
- n += 8;
- byte[] enc = new byte[n];
-
- LittleEndianConversions.I2OSP(numRows, enc, 0);
- LittleEndianConversions.I2OSP(numColumns, enc, 4);
-
- // number of "full" integer
- int q = numColumns >>> 5;
- // number of bits in non-full integer
- int r = numColumns & 0x1f;
-
- int count = 8;
- for (int i = 0; i < numRows; i++)
- {
- for (int j = 0; j < q; j++, count += 4)
- {
- LittleEndianConversions.I2OSP(matrix[i][j], enc, count);
- }
- for (int j = 0; j < r; j += 8)
- {
- enc[count++] = (byte)((matrix[i][q] >>> j) & 0xff);
- }
-
- }
- return enc;
- }
-
-
- /**
- * Returns the percentage of the number of "ones" in this matrix.
- *
- * @return the Hamming weight of this matrix (as a ratio).
- */
- public double getHammingWeight()
- {
- double counter = 0.0;
- double elementCounter = 0.0;
- int rest = numColumns & 0x1f;
- int d;
- if (rest == 0)
- {
- d = length;
- }
- else
- {
- d = length - 1;
- }
-
- for (int i = 0; i < numRows; i++)
- {
-
- for (int j = 0; j < d; j++)
- {
- int a = matrix[i][j];
- for (int k = 0; k < 32; k++)
- {
- int b = (a >>> k) & 1;
- counter = counter + b;
- elementCounter = elementCounter + 1;
- }
- }
- int a = matrix[i][length - 1];
- for (int k = 0; k < rest; k++)
- {
- int b = (a >>> k) & 1;
- counter = counter + b;
- elementCounter = elementCounter + 1;
- }
- }
-
- return counter / elementCounter;
- }
-
- /**
- * Check if this is the zero matrix (i.e., all entries are zero).
- *
- * @return <tt>true</tt> if this is the zero matrix
- */
- public boolean isZero()
- {
- for (int i = 0; i < numRows; i++)
- {
- for (int j = 0; j < length; j++)
- {
- if (matrix[i][j] != 0)
- {
- return false;
- }
- }
- }
- return true;
- }
-
- /**
- * Get the quadratic submatrix of this matrix consisting of the leftmost
- * <tt>numRows</tt> columns.
- *
- * @return the <tt>(numRows x numRows)</tt> submatrix
- */
- public GF2Matrix getLeftSubMatrix()
- {
- if (numColumns <= numRows)
- {
- throw new ArithmeticException("empty submatrix");
- }
- int length = (numRows + 31) >> 5;
- int[][] result = new int[numRows][length];
- int bitMask = (1 << (numRows & 0x1f)) - 1;
- if (bitMask == 0)
- {
- bitMask = -1;
- }
- for (int i = numRows - 1; i >= 0; i--)
- {
- System.arraycopy(matrix[i], 0, result[i], 0, length);
- result[i][length - 1] &= bitMask;
- }
- return new GF2Matrix(numRows, result);
- }
-
- /**
- * Compute the full form matrix <tt>(this | Id)</tt> from this matrix in
- * left compact form, where <tt>Id</tt> is the <tt>k x k</tt> identity
- * matrix and <tt>k</tt> is the number of rows of this matrix.
- *
- * @return <tt>(this | Id)</tt>
- */
- public GF2Matrix extendLeftCompactForm()
- {
- int newNumColumns = numColumns + numRows;
- GF2Matrix result = new GF2Matrix(numRows, newNumColumns);
-
- int ind = numRows - 1 + numColumns;
- for (int i = numRows - 1; i >= 0; i--, ind--)
- {
- // copy this matrix to first columns
- System.arraycopy(matrix[i], 0, result.matrix[i], 0, length);
- // store the identity in last columns
- result.matrix[i][ind >> 5] |= 1 << (ind & 0x1f);
- }
-
- return result;
- }
-
- /**
- * Get the submatrix of this matrix consisting of the rightmost
- * <tt>numColumns-numRows</tt> columns.
- *
- * @return the <tt>(numRows x (numColumns-numRows))</tt> submatrix
- */
- public GF2Matrix getRightSubMatrix()
- {
- if (numColumns <= numRows)
- {
- throw new ArithmeticException("empty submatrix");
- }
-
- int q = numRows >> 5;
- int r = numRows & 0x1f;
-
- GF2Matrix result = new GF2Matrix(numRows, numColumns - numRows);
-
- for (int i = numRows - 1; i >= 0; i--)
- {
- // if words have to be shifted
- if (r != 0)
- {
- int ind = q;
- // process all but last word
- for (int j = 0; j < result.length - 1; j++)
- {
- // shift to correct position
- result.matrix[i][j] = (matrix[i][ind++] >>> r)
- | (matrix[i][ind] << (32 - r));
- }
- // process last word
- result.matrix[i][result.length - 1] = matrix[i][ind++] >>> r;
- if (ind < length)
- {
- result.matrix[i][result.length - 1] |= matrix[i][ind] << (32 - r);
- }
- }
- else
- {
- // no shifting necessary
- System.arraycopy(matrix[i], q, result.matrix[i], 0,
- result.length);
- }
- }
- return result;
- }
-
- /**
- * Compute the full form matrix <tt>(Id | this)</tt> from this matrix in
- * right compact form, where <tt>Id</tt> is the <tt>k x k</tt> identity
- * matrix and <tt>k</tt> is the number of rows of this matrix.
- *
- * @return <tt>(Id | this)</tt>
- */
- public GF2Matrix extendRightCompactForm()
- {
- GF2Matrix result = new GF2Matrix(numRows, numRows + numColumns);
-
- int q = numRows >> 5;
- int r = numRows & 0x1f;
-
- for (int i = numRows - 1; i >= 0; i--)
- {
- // store the identity in first columns
- result.matrix[i][i >> 5] |= 1 << (i & 0x1f);
-
- // copy this matrix to last columns
-
- // if words have to be shifted
- if (r != 0)
- {
- int ind = q;
- // process all but last word
- for (int j = 0; j < length - 1; j++)
- {
- // obtain matrix word
- int mw = matrix[i][j];
- // shift to correct position
- result.matrix[i][ind++] |= mw << r;
- result.matrix[i][ind] |= mw >>> (32 - r);
- }
- // process last word
- int mw = matrix[i][length - 1];
- result.matrix[i][ind++] |= mw << r;
- if (ind < result.length)
- {
- result.matrix[i][ind] |= mw >>> (32 - r);
- }
- }
- else
- {
- // no shifting necessary
- System.arraycopy(matrix[i], 0, result.matrix[i], q, length);
- }
- }
-
- return result;
- }
-
- /**
- * Compute the transpose of this matrix.
- *
- * @return <tt>(this)<sup>T</sup></tt>
- */
- public Matrix computeTranspose()
- {
- int[][] result = new int[numColumns][(numRows + 31) >>> 5];
- for (int i = 0; i < numRows; i++)
- {
- for (int j = 0; j < numColumns; j++)
- {
- int qs = j >>> 5;
- int rs = j & 0x1f;
- int b = (matrix[i][qs] >>> rs) & 1;
- int qt = i >>> 5;
- int rt = i & 0x1f;
- if (b == 1)
- {
- result[j][qt] |= 1 << rt;
- }
- }
- }
-
- return new GF2Matrix(numRows, result);
- }
-
- /**
- * Compute the inverse of this matrix.
- *
- * @return the inverse of this matrix (newly created).
- * @throws ArithmeticException if this matrix is not invertible.
- */
- public Matrix computeInverse()
- {
- if (numRows != numColumns)
- {
- throw new ArithmeticException("Matrix is not invertible.");
- }
-
- // clone this matrix
- int[][] tmpMatrix = new int[numRows][length];
- for (int i = numRows - 1; i >= 0; i--)
- {
- tmpMatrix[i] = IntUtils.clone(matrix[i]);
- }
-
- // initialize inverse matrix as unit matrix
- int[][] invMatrix = new int[numRows][length];
- for (int i = numRows - 1; i >= 0; i--)
- {
- int q = i >> 5;
- int r = i & 0x1f;
- invMatrix[i][q] = 1 << r;
- }
-
- // simultaneously compute Gaussian reduction of tmpMatrix and unit
- // matrix
- for (int i = 0; i < numRows; i++)
- {
- // i = q * 32 + (i mod 32)
- int q = i >> 5;
- int bitMask = 1 << (i & 0x1f);
- // if diagonal element is zero
- if ((tmpMatrix[i][q] & bitMask) == 0)
- {
- boolean foundNonZero = false;
- // find a non-zero element in the same column
- for (int j = i + 1; j < numRows; j++)
- {
- if ((tmpMatrix[j][q] & bitMask) != 0)
- {
- // found it, swap rows ...
- foundNonZero = true;
- swapRows(tmpMatrix, i, j);
- swapRows(invMatrix, i, j);
- // ... and quit searching
- j = numRows;
- continue;
- }
- }
- // if no non-zero element was found ...
- if (!foundNonZero)
- {
- // ... the matrix is not invertible
- throw new ArithmeticException("Matrix is not invertible.");
- }
- }
-
- // normalize all but i-th row
- for (int j = numRows - 1; j >= 0; j--)
- {
- if ((j != i) && ((tmpMatrix[j][q] & bitMask) != 0))
- {
- addToRow(tmpMatrix[i], tmpMatrix[j], q);
- addToRow(invMatrix[i], invMatrix[j], 0);
- }
- }
- }
-
- return new GF2Matrix(numColumns, invMatrix);
- }
-
- /**
- * Compute the product of a permutation matrix (which is generated from an
- * n-permutation) and this matrix.
- *
- * @param p the permutation
- * @return {@link GF2Matrix} <tt>P*this</tt>
- */
- public Matrix leftMultiply(Permutation p)
- {
- int[] pVec = p.getVector();
- if (pVec.length != numRows)
- {
- throw new ArithmeticException("length mismatch");
- }
-
- int[][] result = new int[numRows][];
-
- for (int i = numRows - 1; i >= 0; i--)
- {
- result[i] = IntUtils.clone(matrix[pVec[i]]);
- }
-
- return new GF2Matrix(numRows, result);
- }
-
- /**
- * compute product a row vector and this matrix
- *
- * @param vec a vector over GF(2)
- * @return Vector product a*matrix
- */
- public Vector leftMultiply(Vector vec)
- {
-
- if (!(vec instanceof GF2Vector))
- {
- throw new ArithmeticException("vector is not defined over GF(2)");
- }
-
- if (vec.length != numRows)
- {
- throw new ArithmeticException("length mismatch");
- }
-
- int[] v = ((GF2Vector)vec).getVecArray();
- int[] res = new int[length];
-
- int q = numRows >> 5;
- int r = 1 << (numRows & 0x1f);
-
- // compute scalar products with full words of vector
- int row = 0;
- for (int i = 0; i < q; i++)
- {
- int bitMask = 1;
- do
- {
- int b = v[i] & bitMask;
- if (b != 0)
- {
- for (int j = 0; j < length; j++)
- {
- res[j] ^= matrix[row][j];
- }
- }
- row++;
- bitMask <<= 1;
- }
- while (bitMask != 0);
- }
-
- // compute scalar products with last word of vector
- int bitMask = 1;
- while (bitMask != r)
- {
- int b = v[q] & bitMask;
- if (b != 0)
- {
- for (int j = 0; j < length; j++)
- {
- res[j] ^= matrix[row][j];
- }
- }
- row++;
- bitMask <<= 1;
- }
-
- return new GF2Vector(res, numColumns);
- }
-
- /**
- * Compute the product of the matrix <tt>(this | Id)</tt> and a column
- * vector, where <tt>Id</tt> is a <tt>(numRows x numRows)</tt> unit
- * matrix.
- *
- * @param vec the vector over GF(2)
- * @return <tt>(this | Id)*vector</tt>
- */
- public Vector leftMultiplyLeftCompactForm(Vector vec)
- {
- if (!(vec instanceof GF2Vector))
- {
- throw new ArithmeticException("vector is not defined over GF(2)");
- }
-
- if (vec.length != numRows)
- {
- throw new ArithmeticException("length mismatch");
- }
-
- int[] v = ((GF2Vector)vec).getVecArray();
- int[] res = new int[(numRows + numColumns + 31) >>> 5];
-
- // process full words of vector
- int words = numRows >>> 5;
- int row = 0;
- for (int i = 0; i < words; i++)
- {
- int bitMask = 1;
- do
- {
- int b = v[i] & bitMask;
- if (b != 0)
- {
- // compute scalar product part
- for (int j = 0; j < length; j++)
- {
- res[j] ^= matrix[row][j];
- }
- // set last bit
- int q = (numColumns + row) >>> 5;
- int r = (numColumns + row) & 0x1f;
- res[q] |= 1 << r;
- }
- row++;
- bitMask <<= 1;
- }
- while (bitMask != 0);
- }
-
- // process last word of vector
- int rem = 1 << (numRows & 0x1f);
- int bitMask = 1;
- while (bitMask != rem)
- {
- int b = v[words] & bitMask;
- if (b != 0)
- {
- // compute scalar product part
- for (int j = 0; j < length; j++)
- {
- res[j] ^= matrix[row][j];
- }
- // set last bit
- int q = (numColumns + row) >>> 5;
- int r = (numColumns + row) & 0x1f;
- res[q] |= 1 << r;
- }
- row++;
- bitMask <<= 1;
- }
-
- return new GF2Vector(res, numRows + numColumns);
- }
-
- /**
- * Compute the product of this matrix and a matrix A over GF(2).
- *
- * @param mat a matrix A over GF(2)
- * @return matrix product <tt>this*matrixA</tt>
- */
- public Matrix rightMultiply(Matrix mat)
- {
- if (!(mat instanceof GF2Matrix))
- {
- throw new ArithmeticException("matrix is not defined over GF(2)");
- }
-
- if (mat.numRows != numColumns)
- {
- throw new ArithmeticException("length mismatch");
- }
-
- GF2Matrix a = (GF2Matrix)mat;
- GF2Matrix result = new GF2Matrix(numRows, mat.numColumns);
-
- int d;
- int rest = numColumns & 0x1f;
- if (rest == 0)
- {
- d = length;
- }
- else
- {
- d = length - 1;
- }
- for (int i = 0; i < numRows; i++)
- {
- int count = 0;
- for (int j = 0; j < d; j++)
- {
- int e = matrix[i][j];
- for (int h = 0; h < 32; h++)
- {
- int b = e & (1 << h);
- if (b != 0)
- {
- for (int g = 0; g < a.length; g++)
- {
- result.matrix[i][g] ^= a.matrix[count][g];
- }
- }
- count++;
- }
- }
- int e = matrix[i][length - 1];
- for (int h = 0; h < rest; h++)
- {
- int b = e & (1 << h);
- if (b != 0)
- {
- for (int g = 0; g < a.length; g++)
- {
- result.matrix[i][g] ^= a.matrix[count][g];
- }
- }
- count++;
- }
-
- }
-
- return result;
- }
-
- /**
- * Compute the product of this matrix and a permutation matrix which is
- * generated from an n-permutation.
- *
- * @param p the permutation
- * @return {@link GF2Matrix} <tt>this*P</tt>
- */
- public Matrix rightMultiply(Permutation p)
- {
-
- int[] pVec = p.getVector();
- if (pVec.length != numColumns)
- {
- throw new ArithmeticException("length mismatch");
- }
-
- GF2Matrix result = new GF2Matrix(numRows, numColumns);
-
- for (int i = numColumns - 1; i >= 0; i--)
- {
- int q = i >>> 5;
- int r = i & 0x1f;
- int pq = pVec[i] >>> 5;
- int pr = pVec[i] & 0x1f;
- for (int j = numRows - 1; j >= 0; j--)
- {
- result.matrix[j][q] |= ((matrix[j][pq] >>> pr) & 1) << r;
- }
- }
-
- return result;
- }
-
- /**
- * Compute the product of this matrix and the given column vector.
- *
- * @param vec the vector over GF(2)
- * @return <tt>this*vector</tt>
- */
- public Vector rightMultiply(Vector vec)
- {
- if (!(vec instanceof GF2Vector))
- {
- throw new ArithmeticException("vector is not defined over GF(2)");
- }
-
- if (vec.length != numColumns)
- {
- throw new ArithmeticException("length mismatch");
- }
-
- int[] v = ((GF2Vector)vec).getVecArray();
- int[] res = new int[(numRows + 31) >>> 5];
-
- for (int i = 0; i < numRows; i++)
- {
- // compute full word scalar products
- int help = 0;
- for (int j = 0; j < length; j++)
- {
- help ^= matrix[i][j] & v[j];
- }
- // compute single word scalar product
- int bitValue = 0;
- for (int j = 0; j < 32; j++)
- {
- bitValue ^= (help >>> j) & 1;
- }
- // set result bit
- if (bitValue == 1)
- {
- res[i >>> 5] |= 1 << (i & 0x1f);
- }
- }
-
- return new GF2Vector(res, numRows);
- }
-
- /**
- * Compute the product of the matrix <tt>(Id | this)</tt> and a column
- * vector, where <tt>Id</tt> is a <tt>(numRows x numRows)</tt> unit
- * matrix.
- *
- * @param vec the vector over GF(2)
- * @return <tt>(Id | this)*vector</tt>
- */
- public Vector rightMultiplyRightCompactForm(Vector vec)
- {
- if (!(vec instanceof GF2Vector))
- {
- throw new ArithmeticException("vector is not defined over GF(2)");
- }
-
- if (vec.length != numColumns + numRows)
- {
- throw new ArithmeticException("length mismatch");
- }
-
- int[] v = ((GF2Vector)vec).getVecArray();
- int[] res = new int[(numRows + 31) >>> 5];
-
- int q = numRows >> 5;
- int r = numRows & 0x1f;
-
- // for all rows
- for (int i = 0; i < numRows; i++)
- {
- // get vector bit
- int help = (v[i >> 5] >>> (i & 0x1f)) & 1;
-
- // compute full word scalar products
- int vInd = q;
- // if words have to be shifted
- if (r != 0)
- {
- int vw = 0;
- // process all but last word
- for (int j = 0; j < length - 1; j++)
- {
- // shift to correct position
- vw = (v[vInd++] >>> r) | (v[vInd] << (32 - r));
- help ^= matrix[i][j] & vw;
- }
- // process last word
- vw = v[vInd++] >>> r;
- if (vInd < v.length)
- {
- vw |= v[vInd] << (32 - r);
- }
- help ^= matrix[i][length - 1] & vw;
- }
- else
- {
- // no shifting necessary
- for (int j = 0; j < length; j++)
- {
- help ^= matrix[i][j] & v[vInd++];
- }
- }
-
- // compute single word scalar product
- int bitValue = 0;
- for (int j = 0; j < 32; j++)
- {
- bitValue ^= help & 1;
- help >>>= 1;
- }
-
- // set result bit
- if (bitValue == 1)
- {
- res[i >> 5] |= 1 << (i & 0x1f);
- }
- }
-
- return new GF2Vector(res, numRows);
- }
-
- /**
- * Compare this matrix with another object.
- *
- * @param other another object
- * @return the result of the comparison
- */
- public boolean equals(Object other)
- {
-
- if (!(other instanceof GF2Matrix))
- {
- return false;
- }
- GF2Matrix otherMatrix = (GF2Matrix)other;
-
- if ((numRows != otherMatrix.numRows)
- || (numColumns != otherMatrix.numColumns)
- || (length != otherMatrix.length))
- {
- return false;
- }
-
- for (int i = 0; i < numRows; i++)
- {
- if (!IntUtils.equals(matrix[i], otherMatrix.matrix[i]))
- {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * @return the hash code of this matrix
- */
- public int hashCode()
- {
- int hash = (numRows * 31 + numColumns) * 31 + length;
- for (int i = 0; i < numRows; i++)
- {
- hash = hash * 31 + matrix[i].hashCode();
- }
- return hash;
- }
-
- /**
- * @return a human readable form of the matrix
- */
- public String toString()
- {
- int rest = numColumns & 0x1f;
- int d;
- if (rest == 0)
- {
- d = length;
- }
- else
- {
- d = length - 1;
- }
-
- StringBuffer buf = new StringBuffer();
- for (int i = 0; i < numRows; i++)
- {
- buf.append(i + ": ");
- for (int j = 0; j < d; j++)
- {
- int a = matrix[i][j];
- for (int k = 0; k < 32; k++)
- {
- int b = (a >>> k) & 1;
- if (b == 0)
- {
- buf.append('0');
- }
- else
- {
- buf.append('1');
- }
- }
- buf.append(' ');
- }
- int a = matrix[i][length - 1];
- for (int k = 0; k < rest; k++)
- {
- int b = (a >>> k) & 1;
- if (b == 0)
- {
- buf.append('0');
- }
- else
- {
- buf.append('1');
- }
- }
- buf.append('\n');
- }
-
- return buf.toString();
- }
-
- /**
- * Swap two rows of the given matrix.
- *
- * @param matrix the matrix
- * @param first the index of the first row
- * @param second the index of the second row
- */
- private static void swapRows(int[][] matrix, int first, int second)
- {
- int[] tmp = matrix[first];
- matrix[first] = matrix[second];
- matrix[second] = tmp;
- }
-
- /**
- * Partially add one row to another.
- *
- * @param fromRow the addend
- * @param toRow the row to add to
- * @param startIndex the array index to start from
- */
- private static void addToRow(int[] fromRow, int[] toRow, int startIndex)
- {
- for (int i = toRow.length - 1; i >= startIndex; i--)
- {
- toRow[i] = fromRow[i] ^ toRow[i];
- }
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Polynomial.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Polynomial.java
deleted file mode 100644
index 3ef1fbbc..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Polynomial.java
+++ /dev/null
@@ -1,2039 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-
-import java.math.BigInteger;
-import java.util.Random;
-
-
-/**
- * This class stores very long strings of bits and does some basic arithmetics.
- * It is used by <tt>GF2nField</tt>, <tt>GF2nPolynomialField</tt> and
- * <tt>GFnPolynomialElement</tt>.
- *
- * @see GF2nPolynomialElement
- * @see GF2nField
- */
-public class GF2Polynomial
-{
-
- // number of bits stored in this GF2Polynomial
- private int len;
-
- // number of int used in value
- private int blocks;
-
- // storage
- private int[] value;
-
- // Random source
- private static Random rand = new Random();
-
- // Lookup-Table for vectorMult: parity[a]= #1(a) mod 2 == 1
- private static final boolean[] parity = {false, true, true, false, true,
- false, false, true, true, false, false, true, false, true, true,
- false, true, false, false, true, false, true, true, false, false,
- true, true, false, true, false, false, true, true, false, false,
- true, false, true, true, false, false, true, true, false, true,
- false, false, true, false, true, true, false, true, false, false,
- true, true, false, false, true, false, true, true, false, true,
- false, false, true, false, true, true, false, false, true, true,
- false, true, false, false, true, false, true, true, false, true,
- false, false, true, true, false, false, true, false, true, true,
- false, false, true, true, false, true, false, false, true, true,
- false, false, true, false, true, true, false, true, false, false,
- true, false, true, true, false, false, true, true, false, true,
- false, false, true, true, false, false, true, false, true, true,
- false, false, true, true, false, true, false, false, true, false,
- true, true, false, true, false, false, true, true, false, false,
- true, false, true, true, false, false, true, true, false, true,
- false, false, true, true, false, false, true, false, true, true,
- false, true, false, false, true, false, true, true, false, false,
- true, true, false, true, false, false, true, false, true, true,
- false, true, false, false, true, true, false, false, true, false,
- true, true, false, true, false, false, true, false, true, true,
- false, false, true, true, false, true, false, false, true, true,
- false, false, true, false, true, true, false, false, true, true,
- false, true, false, false, true, false, true, true, false, true,
- false, false, true, true, false, false, true, false, true, true,
- false};
-
- // Lookup-Table for Squaring: squaringTable[a]=a^2
- private static final short[] squaringTable = {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};
-
- // pre-computed Bitmask for fast masking, bitMask[a]=0x1 << a
- private static final int[] bitMask = {0x00000001, 0x00000002, 0x00000004,
- 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080,
- 0x00000100, 0x00000200, 0x00000400, 0x00000800, 0x00001000,
- 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000,
- 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000,
- 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000,
- 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x00000000};
-
- // pre-computed Bitmask for fast masking, rightMask[a]=0xffffffff >>> (32-a)
- private static final int[] reverseRightMask = {0x00000000, 0x00000001,
- 0x00000003, 0x00000007, 0x0000000f, 0x0000001f, 0x0000003f,
- 0x0000007f, 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
- 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
- 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff, 0x001fffff,
- 0x003fffff, 0x007fffff, 0x00ffffff, 0x01ffffff, 0x03ffffff,
- 0x07ffffff, 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
- 0xffffffff};
-
- /**
- * Creates a new GF2Polynomial of the given <i>length</i> and value zero.
- *
- * @param length the desired number of bits to store
- */
- public GF2Polynomial(int length)
- {
- int l = length;
- if (l < 1)
- {
- l = 1;
- }
- blocks = ((l - 1) >> 5) + 1;
- value = new int[blocks];
- len = l;
- }
-
- /**
- * Creates a new GF2Polynomial of the given <i>length</i> and random value.
- *
- * @param length the desired number of bits to store
- * @param rand SecureRandom to use for randomization
- */
- public GF2Polynomial(int length, Random rand)
- {
- int l = length;
- if (l < 1)
- {
- l = 1;
- }
- blocks = ((l - 1) >> 5) + 1;
- value = new int[blocks];
- len = l;
- randomize(rand);
- }
-
- /**
- * Creates a new GF2Polynomial of the given <i>length</i> and value
- * selected by <i>value</i>:
- * <UL>
- * <LI>ZERO</LI>
- * <LI>ONE</LI>
- * <LI>RANDOM</LI>
- * <LI>X</LI>
- * <LI>ALL</LI>
- * </UL>
- *
- * @param length the desired number of bits to store
- * @param value the value described by a String
- */
- public GF2Polynomial(int length, String value)
- {
- int l = length;
- if (l < 1)
- {
- l = 1;
- }
- blocks = ((l - 1) >> 5) + 1;
- this.value = new int[blocks];
- len = l;
- if (value.equalsIgnoreCase("ZERO"))
- {
- assignZero();
- }
- else if (value.equalsIgnoreCase("ONE"))
- {
- assignOne();
- }
- else if (value.equalsIgnoreCase("RANDOM"))
- {
- randomize();
- }
- else if (value.equalsIgnoreCase("X"))
- {
- assignX();
- }
- else if (value.equalsIgnoreCase("ALL"))
- {
- assignAll();
- }
- else
- {
- throw new IllegalArgumentException(
- "Error: GF2Polynomial was called using " + value
- + " as value!");
- }
-
- }
-
- /**
- * Creates a new GF2Polynomial of the given <i>length</i> using the given
- * int[]. LSB is contained in bs[0].
- *
- * @param length the desired number of bits to store
- * @param bs contains the desired value, LSB in bs[0]
- */
- public GF2Polynomial(int length, int[] bs)
- {
- int leng = length;
- if (leng < 1)
- {
- leng = 1;
- }
- blocks = ((leng - 1) >> 5) + 1;
- value = new int[blocks];
- len = leng;
- int l = Math.min(blocks, bs.length);
- System.arraycopy(bs, 0, value, 0, l);
- zeroUnusedBits();
- }
-
- /**
- * Creates a new GF2Polynomial by converting the given byte[] <i>os</i>
- * according to 1363 and using the given <i>length</i>.
- *
- * @param length the intended length of this polynomial
- * @param os the octet string to assign to this polynomial
- * @see "P1363 5.5.2 p22f, OS2BSP"
- */
- public GF2Polynomial(int length, byte[] os)
- {
- int l = length;
- if (l < 1)
- {
- l = 1;
- }
- blocks = ((l - 1) >> 5) + 1;
- value = new int[blocks];
- len = l;
- int i, m;
- int k = Math.min(((os.length - 1) >> 2) + 1, blocks);
- for (i = 0; i < k - 1; i++)
- {
- m = os.length - (i << 2) - 1;
- value[i] = (os[m]) & 0x000000ff;
- value[i] |= (os[m - 1] << 8) & 0x0000ff00;
- value[i] |= (os[m - 2] << 16) & 0x00ff0000;
- value[i] |= (os[m - 3] << 24) & 0xff000000;
- }
- i = k - 1;
- m = os.length - (i << 2) - 1;
- value[i] = os[m] & 0x000000ff;
- if (m > 0)
- {
- value[i] |= (os[m - 1] << 8) & 0x0000ff00;
- }
- if (m > 1)
- {
- value[i] |= (os[m - 2] << 16) & 0x00ff0000;
- }
- if (m > 2)
- {
- value[i] |= (os[m - 3] << 24) & 0xff000000;
- }
- zeroUnusedBits();
- reduceN();
- }
-
- /**
- * Creates a new GF2Polynomial by converting the given FlexiBigInt <i>bi</i>
- * according to 1363 and using the given <i>length</i>.
- *
- * @param length the intended length of this polynomial
- * @param bi the FlexiBigInt to assign to this polynomial
- * @see "P1363 5.5.1 p22, I2BSP"
- */
- public GF2Polynomial(int length, BigInteger bi)
- {
- int l = length;
- if (l < 1)
- {
- l = 1;
- }
- blocks = ((l - 1) >> 5) + 1;
- value = new int[blocks];
- len = l;
- int i;
- byte[] val = bi.toByteArray();
- if (val[0] == 0)
- {
- byte[] dummy = new byte[val.length - 1];
- System.arraycopy(val, 1, dummy, 0, dummy.length);
- val = dummy;
- }
- int ov = val.length & 0x03;
- int k = ((val.length - 1) >> 2) + 1;
- for (i = 0; i < ov; i++)
- {
- value[k - 1] |= (val[i] & 0x000000ff) << ((ov - 1 - i) << 3);
- }
- int m = 0;
- for (i = 0; i <= (val.length - 4) >> 2; i++)
- {
- m = val.length - 1 - (i << 2);
- value[i] = (val[m]) & 0x000000ff;
- value[i] |= ((val[m - 1]) << 8) & 0x0000ff00;
- value[i] |= ((val[m - 2]) << 16) & 0x00ff0000;
- value[i] |= ((val[m - 3]) << 24) & 0xff000000;
- }
- if ((len & 0x1f) != 0)
- {
- value[blocks - 1] &= reverseRightMask[len & 0x1f];
- }
- reduceN();
- }
-
- /**
- * Creates a new GF2Polynomial by cloneing the given GF2Polynomial <i>b</i>.
- *
- * @param b the GF2Polynomial to clone
- */
- public GF2Polynomial(GF2Polynomial b)
- {
- len = b.len;
- blocks = b.blocks;
- value = IntUtils.clone(b.value);
- }
-
- /**
- * @return a copy of this GF2Polynomial
- */
- public Object clone()
- {
- return new GF2Polynomial(this);
- }
-
- /**
- * Returns the length of this GF2Polynomial. The length can be greater than
- * the degree. To get the degree call reduceN() before calling getLength().
- *
- * @return the length of this GF2Polynomial
- */
- public int getLength()
- {
- return len;
- }
-
- /**
- * Returns the value of this GF2Polynomial in an int[].
- *
- * @return the value of this GF2Polynomial in a new int[], LSB in int[0]
- */
- public int[] toIntegerArray()
- {
- int[] result;
- result = new int[blocks];
- System.arraycopy(value, 0, result, 0, blocks);
- return result;
- }
-
- /**
- * Returns a string representing this GF2Polynomials value using hexadecimal
- * or binary radix in MSB-first order.
- *
- * @param radix the radix to use (2 or 16, otherwise 2 is used)
- * @return a String representing this GF2Polynomials value.
- */
- public String toString(int radix)
- {
- final char[] HEX_CHARS = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
- '9', 'a', 'b', 'c', 'd', 'e', 'f'};
- final String[] BIN_CHARS = {"0000", "0001", "0010", "0011", "0100",
- "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100",
- "1101", "1110", "1111"};
- String res;
- int i;
- res = new String();
- if (radix == 16)
- {
- for (i = blocks - 1; i >= 0; i--)
- {
- res += HEX_CHARS[(value[i] >>> 28) & 0x0f];
- res += HEX_CHARS[(value[i] >>> 24) & 0x0f];
- res += HEX_CHARS[(value[i] >>> 20) & 0x0f];
- res += HEX_CHARS[(value[i] >>> 16) & 0x0f];
- res += HEX_CHARS[(value[i] >>> 12) & 0x0f];
- res += HEX_CHARS[(value[i] >>> 8) & 0x0f];
- res += HEX_CHARS[(value[i] >>> 4) & 0x0f];
- res += HEX_CHARS[(value[i]) & 0x0f];
- res += " ";
- }
- }
- else
- {
- for (i = blocks - 1; i >= 0; i--)
- {
- res += BIN_CHARS[(value[i] >>> 28) & 0x0f];
- res += BIN_CHARS[(value[i] >>> 24) & 0x0f];
- res += BIN_CHARS[(value[i] >>> 20) & 0x0f];
- res += BIN_CHARS[(value[i] >>> 16) & 0x0f];
- res += BIN_CHARS[(value[i] >>> 12) & 0x0f];
- res += BIN_CHARS[(value[i] >>> 8) & 0x0f];
- res += BIN_CHARS[(value[i] >>> 4) & 0x0f];
- res += BIN_CHARS[(value[i]) & 0x0f];
- res += " ";
- }
- }
- return res;
- }
-
- /**
- * Converts this polynomial to a byte[] (octet string) according to 1363.
- *
- * @return a byte[] representing the value of this polynomial
- * @see "P1363 5.5.2 p22f, BS2OSP"
- */
- public byte[] toByteArray()
- {
- int k = ((len - 1) >> 3) + 1;
- int ov = k & 0x03;
- int m;
- byte[] res = new byte[k];
- int i;
- for (i = 0; i < (k >> 2); i++)
- {
- m = k - (i << 2) - 1;
- res[m] = (byte)((value[i] & 0x000000ff));
- res[m - 1] = (byte)((value[i] & 0x0000ff00) >>> 8);
- res[m - 2] = (byte)((value[i] & 0x00ff0000) >>> 16);
- res[m - 3] = (byte)((value[i] & 0xff000000) >>> 24);
- }
- for (i = 0; i < ov; i++)
- {
- m = (ov - i - 1) << 3;
- res[i] = (byte)((value[blocks - 1] & (0x000000ff << m)) >>> m);
- }
- return res;
- }
-
- /**
- * Converts this polynomial to an integer according to 1363.
- *
- * @return a FlexiBigInt representing the value of this polynomial
- * @see "P1363 5.5.1 p22, BS2IP"
- */
- public BigInteger toFlexiBigInt()
- {
- if (len == 0 || isZero())
- {
- return new BigInteger(0, new byte[0]);
- }
- return new BigInteger(1, toByteArray());
- }
-
- /**
- * Sets the LSB to 1 and all other to 0, assigning 'one' to this
- * GF2Polynomial.
- */
- public void assignOne()
- {
- int i;
- for (i = 1; i < blocks; i++)
- {
- value[i] = 0x00;
- }
- value[0] = 0x01;
- }
-
- /**
- * Sets Bit 1 to 1 and all other to 0, assigning 'x' to this GF2Polynomial.
- */
- public void assignX()
- {
- int i;
- for (i = 1; i < blocks; i++)
- {
- value[i] = 0x00;
- }
- value[0] = 0x02;
- }
-
- /**
- * Sets all Bits to 1.
- */
- public void assignAll()
- {
- int i;
- for (i = 0; i < blocks; i++)
- {
- value[i] = 0xffffffff;
- }
- zeroUnusedBits();
- }
-
- /**
- * Resets all bits to zero.
- */
- public void assignZero()
- {
- int i;
- for (i = 0; i < blocks; i++)
- {
- value[i] = 0x00;
- }
- }
-
- /**
- * Fills all len bits of this GF2Polynomial with random values.
- */
- public void randomize()
- {
- int i;
- for (i = 0; i < blocks; i++)
- {
- value[i] = rand.nextInt();
- }
- zeroUnusedBits();
- }
-
- /**
- * Fills all len bits of this GF2Polynomial with random values using the
- * specified source of randomness.
- *
- * @param rand the source of randomness
- */
- public void randomize(Random rand)
- {
- int i;
- for (i = 0; i < blocks; i++)
- {
- value[i] = rand.nextInt();
- }
- zeroUnusedBits();
- }
-
- /**
- * Returns true if two GF2Polynomials have the same size and value and thus
- * are equal.
- *
- * @param other the other GF2Polynomial
- * @return true if this GF2Polynomial equals <i>b</i> (<i>this</i> ==
- * <i>b</i>)
- */
- public boolean equals(Object other)
- {
- if (other == null || !(other instanceof GF2Polynomial))
- {
- return false;
- }
-
- GF2Polynomial otherPol = (GF2Polynomial)other;
-
- if (len != otherPol.len)
- {
- return false;
- }
- for (int i = 0; i < blocks; i++)
- {
- if (value[i] != otherPol.value[i])
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * @return the hash code of this polynomial
- */
- public int hashCode()
- {
- return len + value.hashCode();
- }
-
- /**
- * Tests if all bits equal zero.
- *
- * @return true if this GF2Polynomial equals 'zero' (<i>this</i> == 0)
- */
- public boolean isZero()
- {
- int i;
- if (len == 0)
- {
- return true;
- }
- for (i = 0; i < blocks; i++)
- {
- if (value[i] != 0)
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Tests if all bits are reset to 0 and LSB is set to 1.
- *
- * @return true if this GF2Polynomial equals 'one' (<i>this</i> == 1)
- */
- public boolean isOne()
- {
- int i;
- for (i = 1; i < blocks; i++)
- {
- if (value[i] != 0)
- {
- return false;
- }
- }
- if (value[0] != 0x01)
- {
- return false;
- }
- return true;
- }
-
- /**
- * Adds <i>b</i> to this GF2Polynomial and assigns the result to this
- * GF2Polynomial. <i>b</i> can be of different size.
- *
- * @param b GF2Polynomial to add to this GF2Polynomial
- */
- public void addToThis(GF2Polynomial b)
- {
- expandN(b.len);
- xorThisBy(b);
- }
-
- /**
- * Adds two GF2Polynomials, <i>this</i> and <i>b</i>, and returns the
- * result. <i>this</i> and <i>b</i> can be of different size.
- *
- * @param b a GF2Polynomial
- * @return a new GF2Polynomial (<i>this</i> + <i>b</i>)
- */
- public GF2Polynomial add(GF2Polynomial b)
- {
- return xor(b);
- }
-
- /**
- * Subtracts <i>b</i> from this GF2Polynomial and assigns the result to
- * this GF2Polynomial. <i>b</i> can be of different size.
- *
- * @param b a GF2Polynomial
- */
- public void subtractFromThis(GF2Polynomial b)
- {
- expandN(b.len);
- xorThisBy(b);
- }
-
- /**
- * Subtracts two GF2Polynomials, <i>this</i> and <i>b</i>, and returns the
- * result in a new GF2Polynomial. <i>this</i> and <i>b</i> can be of
- * different size.
- *
- * @param b a GF2Polynomial
- * @return a new GF2Polynomial (<i>this</i> - <i>b</i>)
- */
- public GF2Polynomial subtract(GF2Polynomial b)
- {
- return xor(b);
- }
-
- /**
- * Toggles the LSB of this GF2Polynomial, increasing its value by 'one'.
- */
- public void increaseThis()
- {
- xorBit(0);
- }
-
- /**
- * Toggles the LSB of this GF2Polynomial, increasing the value by 'one' and
- * returns the result in a new GF2Polynomial.
- *
- * @return <tt>this + 1</tt>
- */
- public GF2Polynomial increase()
- {
- GF2Polynomial result = new GF2Polynomial(this);
- result.increaseThis();
- return result;
- }
-
- /**
- * Multiplies this GF2Polynomial with <i>b</i> and returns the result in a
- * new GF2Polynomial. This method does not reduce the result in GF(2^N).
- * This method uses classic multiplication (schoolbook).
- *
- * @param b a GF2Polynomial
- * @return a new GF2Polynomial (<i>this</i> * <i>b</i>)
- */
- public GF2Polynomial multiplyClassic(GF2Polynomial b)
- {
- GF2Polynomial result = new GF2Polynomial(Math.max(len, b.len) << 1);
- GF2Polynomial[] m = new GF2Polynomial[32];
- int i, j;
- m[0] = new GF2Polynomial(this);
- for (i = 1; i <= 31; i++)
- {
- m[i] = m[i - 1].shiftLeft();
- }
- for (i = 0; i < b.blocks; i++)
- {
- for (j = 0; j <= 31; j++)
- {
- if ((b.value[i] & bitMask[j]) != 0)
- {
- result.xorThisBy(m[j]);
- }
- }
- for (j = 0; j <= 31; j++)
- {
- m[j].shiftBlocksLeft();
- }
- }
- return result;
- }
-
- /**
- * Multiplies this GF2Polynomial with <i>b</i> and returns the result in a
- * new GF2Polynomial. This method does not reduce the result in GF(2^N).
- * This method uses Karatzuba multiplication.
- *
- * @param b a GF2Polynomial
- * @return a new GF2Polynomial (<i>this</i> * <i>b</i>)
- */
- public GF2Polynomial multiply(GF2Polynomial b)
- {
- int n = Math.max(len, b.len);
- expandN(n);
- b.expandN(n);
- return karaMult(b);
- }
-
- /**
- * Does the recursion for Karatzuba multiplication.
- */
- private GF2Polynomial karaMult(GF2Polynomial b)
- {
- GF2Polynomial result = new GF2Polynomial(len << 1);
- if (len <= 32)
- {
- result.value = mult32(value[0], b.value[0]);
- return result;
- }
- if (len <= 64)
- {
- result.value = mult64(value, b.value);
- return result;
- }
- if (len <= 128)
- {
- result.value = mult128(value, b.value);
- return result;
- }
- if (len <= 256)
- {
- result.value = mult256(value, b.value);
- return result;
- }
- if (len <= 512)
- {
- result.value = mult512(value, b.value);
- return result;
- }
-
- int n = IntegerFunctions.floorLog(len - 1);
- n = bitMask[n];
-
- GF2Polynomial a0 = lower(((n - 1) >> 5) + 1);
- GF2Polynomial a1 = upper(((n - 1) >> 5) + 1);
- GF2Polynomial b0 = b.lower(((n - 1) >> 5) + 1);
- GF2Polynomial b1 = b.upper(((n - 1) >> 5) + 1);
-
- GF2Polynomial c = a1.karaMult(b1); // c = a1*b1
- GF2Polynomial e = a0.karaMult(b0); // e = a0*b0
- a0.addToThis(a1); // a0 = a0 + a1
- b0.addToThis(b1); // b0 = b0 + b1
- GF2Polynomial d = a0.karaMult(b0); // d = (a0+a1)*(b0+b1)
-
- result.shiftLeftAddThis(c, n << 1);
- result.shiftLeftAddThis(c, n);
- result.shiftLeftAddThis(d, n);
- result.shiftLeftAddThis(e, n);
- result.addToThis(e);
- return result;
- }
-
- /**
- * 16-Integer Version of Karatzuba multiplication.
- */
- private static int[] mult512(int[] a, int[] b)
- {
- int[] result = new int[32];
- int[] a0 = new int[8];
- System.arraycopy(a, 0, a0, 0, Math.min(8, a.length));
- int[] a1 = new int[8];
- if (a.length > 8)
- {
- System.arraycopy(a, 8, a1, 0, Math.min(8, a.length - 8));
- }
- int[] b0 = new int[8];
- System.arraycopy(b, 0, b0, 0, Math.min(8, b.length));
- int[] b1 = new int[8];
- if (b.length > 8)
- {
- System.arraycopy(b, 8, b1, 0, Math.min(8, b.length - 8));
- }
- int[] c = mult256(a1, b1);
- result[31] ^= c[15];
- result[30] ^= c[14];
- result[29] ^= c[13];
- result[28] ^= c[12];
- result[27] ^= c[11];
- result[26] ^= c[10];
- result[25] ^= c[9];
- result[24] ^= c[8];
- result[23] ^= c[7] ^ c[15];
- result[22] ^= c[6] ^ c[14];
- result[21] ^= c[5] ^ c[13];
- result[20] ^= c[4] ^ c[12];
- result[19] ^= c[3] ^ c[11];
- result[18] ^= c[2] ^ c[10];
- result[17] ^= c[1] ^ c[9];
- result[16] ^= c[0] ^ c[8];
- result[15] ^= c[7];
- result[14] ^= c[6];
- result[13] ^= c[5];
- result[12] ^= c[4];
- result[11] ^= c[3];
- result[10] ^= c[2];
- result[9] ^= c[1];
- result[8] ^= c[0];
- a1[0] ^= a0[0];
- a1[1] ^= a0[1];
- a1[2] ^= a0[2];
- a1[3] ^= a0[3];
- a1[4] ^= a0[4];
- a1[5] ^= a0[5];
- a1[6] ^= a0[6];
- a1[7] ^= a0[7];
- b1[0] ^= b0[0];
- b1[1] ^= b0[1];
- b1[2] ^= b0[2];
- b1[3] ^= b0[3];
- b1[4] ^= b0[4];
- b1[5] ^= b0[5];
- b1[6] ^= b0[6];
- b1[7] ^= b0[7];
- int[] d = mult256(a1, b1);
- result[23] ^= d[15];
- result[22] ^= d[14];
- result[21] ^= d[13];
- result[20] ^= d[12];
- result[19] ^= d[11];
- result[18] ^= d[10];
- result[17] ^= d[9];
- result[16] ^= d[8];
- result[15] ^= d[7];
- result[14] ^= d[6];
- result[13] ^= d[5];
- result[12] ^= d[4];
- result[11] ^= d[3];
- result[10] ^= d[2];
- result[9] ^= d[1];
- result[8] ^= d[0];
- int[] e = mult256(a0, b0);
- result[23] ^= e[15];
- result[22] ^= e[14];
- result[21] ^= e[13];
- result[20] ^= e[12];
- result[19] ^= e[11];
- result[18] ^= e[10];
- result[17] ^= e[9];
- result[16] ^= e[8];
- result[15] ^= e[7] ^ e[15];
- result[14] ^= e[6] ^ e[14];
- result[13] ^= e[5] ^ e[13];
- result[12] ^= e[4] ^ e[12];
- result[11] ^= e[3] ^ e[11];
- result[10] ^= e[2] ^ e[10];
- result[9] ^= e[1] ^ e[9];
- result[8] ^= e[0] ^ e[8];
- result[7] ^= e[7];
- result[6] ^= e[6];
- result[5] ^= e[5];
- result[4] ^= e[4];
- result[3] ^= e[3];
- result[2] ^= e[2];
- result[1] ^= e[1];
- result[0] ^= e[0];
- return result;
- }
-
- /**
- * 8-Integer Version of Karatzuba multiplication.
- */
- private static int[] mult256(int[] a, int[] b)
- {
- int[] result = new int[16];
- int[] a0 = new int[4];
- System.arraycopy(a, 0, a0, 0, Math.min(4, a.length));
- int[] a1 = new int[4];
- if (a.length > 4)
- {
- System.arraycopy(a, 4, a1, 0, Math.min(4, a.length - 4));
- }
- int[] b0 = new int[4];
- System.arraycopy(b, 0, b0, 0, Math.min(4, b.length));
- int[] b1 = new int[4];
- if (b.length > 4)
- {
- System.arraycopy(b, 4, b1, 0, Math.min(4, b.length - 4));
- }
- if (a1[3] == 0 && a1[2] == 0 && b1[3] == 0 && b1[2] == 0)
- {
- if (a1[1] == 0 && b1[1] == 0)
- {
- if (a1[0] != 0 || b1[0] != 0)
- { // [3]=[2]=[1]=0, [0]!=0
- int[] c = mult32(a1[0], b1[0]);
- result[9] ^= c[1];
- result[8] ^= c[0];
- result[5] ^= c[1];
- result[4] ^= c[0];
- }
- }
- else
- { // [3]=[2]=0 [1]!=0, [0]!=0
- int[] c = mult64(a1, b1);
- result[11] ^= c[3];
- result[10] ^= c[2];
- result[9] ^= c[1];
- result[8] ^= c[0];
- result[7] ^= c[3];
- result[6] ^= c[2];
- result[5] ^= c[1];
- result[4] ^= c[0];
- }
- }
- else
- { // [3]!=0 [2]!=0 [1]!=0, [0]!=0
- int[] c = mult128(a1, b1);
- result[15] ^= c[7];
- result[14] ^= c[6];
- result[13] ^= c[5];
- result[12] ^= c[4];
- result[11] ^= c[3] ^ c[7];
- result[10] ^= c[2] ^ c[6];
- result[9] ^= c[1] ^ c[5];
- result[8] ^= c[0] ^ c[4];
- result[7] ^= c[3];
- result[6] ^= c[2];
- result[5] ^= c[1];
- result[4] ^= c[0];
- }
- a1[0] ^= a0[0];
- a1[1] ^= a0[1];
- a1[2] ^= a0[2];
- a1[3] ^= a0[3];
- b1[0] ^= b0[0];
- b1[1] ^= b0[1];
- b1[2] ^= b0[2];
- b1[3] ^= b0[3];
- int[] d = mult128(a1, b1);
- result[11] ^= d[7];
- result[10] ^= d[6];
- result[9] ^= d[5];
- result[8] ^= d[4];
- result[7] ^= d[3];
- result[6] ^= d[2];
- result[5] ^= d[1];
- result[4] ^= d[0];
- int[] e = mult128(a0, b0);
- result[11] ^= e[7];
- result[10] ^= e[6];
- result[9] ^= e[5];
- result[8] ^= e[4];
- result[7] ^= e[3] ^ e[7];
- result[6] ^= e[2] ^ e[6];
- result[5] ^= e[1] ^ e[5];
- result[4] ^= e[0] ^ e[4];
- result[3] ^= e[3];
- result[2] ^= e[2];
- result[1] ^= e[1];
- result[0] ^= e[0];
- return result;
- }
-
- /**
- * 4-Integer Version of Karatzuba multiplication.
- */
- private static int[] mult128(int[] a, int[] b)
- {
- int[] result = new int[8];
- int[] a0 = new int[2];
- System.arraycopy(a, 0, a0, 0, Math.min(2, a.length));
- int[] a1 = new int[2];
- if (a.length > 2)
- {
- System.arraycopy(a, 2, a1, 0, Math.min(2, a.length - 2));
- }
- int[] b0 = new int[2];
- System.arraycopy(b, 0, b0, 0, Math.min(2, b.length));
- int[] b1 = new int[2];
- if (b.length > 2)
- {
- System.arraycopy(b, 2, b1, 0, Math.min(2, b.length - 2));
- }
- if (a1[1] == 0 && b1[1] == 0)
- {
- if (a1[0] != 0 || b1[0] != 0)
- {
- int[] c = mult32(a1[0], b1[0]);
- result[5] ^= c[1];
- result[4] ^= c[0];
- result[3] ^= c[1];
- result[2] ^= c[0];
- }
- }
- else
- {
- int[] c = mult64(a1, b1);
- result[7] ^= c[3];
- result[6] ^= c[2];
- result[5] ^= c[1] ^ c[3];
- result[4] ^= c[0] ^ c[2];
- result[3] ^= c[1];
- result[2] ^= c[0];
- }
- a1[0] ^= a0[0];
- a1[1] ^= a0[1];
- b1[0] ^= b0[0];
- b1[1] ^= b0[1];
- if (a1[1] == 0 && b1[1] == 0)
- {
- int[] d = mult32(a1[0], b1[0]);
- result[3] ^= d[1];
- result[2] ^= d[0];
- }
- else
- {
- int[] d = mult64(a1, b1);
- result[5] ^= d[3];
- result[4] ^= d[2];
- result[3] ^= d[1];
- result[2] ^= d[0];
- }
- if (a0[1] == 0 && b0[1] == 0)
- {
- int[] e = mult32(a0[0], b0[0]);
- result[3] ^= e[1];
- result[2] ^= e[0];
- result[1] ^= e[1];
- result[0] ^= e[0];
- }
- else
- {
- int[] e = mult64(a0, b0);
- result[5] ^= e[3];
- result[4] ^= e[2];
- result[3] ^= e[1] ^ e[3];
- result[2] ^= e[0] ^ e[2];
- result[1] ^= e[1];
- result[0] ^= e[0];
- }
- return result;
- }
-
- /**
- * 2-Integer Version of Karatzuba multiplication.
- */
- private static int[] mult64(int[] a, int[] b)
- {
- int[] result = new int[4];
- int a0 = a[0];
- int a1 = 0;
- if (a.length > 1)
- {
- a1 = a[1];
- }
- int b0 = b[0];
- int b1 = 0;
- if (b.length > 1)
- {
- b1 = b[1];
- }
- if (a1 != 0 || b1 != 0)
- {
- int[] c = mult32(a1, b1);
- result[3] ^= c[1];
- result[2] ^= c[0] ^ c[1];
- result[1] ^= c[0];
- }
- int[] d = mult32(a0 ^ a1, b0 ^ b1);
- result[2] ^= d[1];
- result[1] ^= d[0];
- int[] e = mult32(a0, b0);
- result[2] ^= e[1];
- result[1] ^= e[0] ^ e[1];
- result[0] ^= e[0];
- return result;
- }
-
- /**
- * 4-Byte Version of Karatzuba multiplication. Here the actual work is done.
- */
- private static int[] mult32(int a, int b)
- {
- int[] result = new int[2];
- if (a == 0 || b == 0)
- {
- return result;
- }
- long b2 = b;
- b2 &= 0x00000000ffffffffL;
- int i;
- long h = 0;
- for (i = 1; i <= 32; i++)
- {
- if ((a & bitMask[i - 1]) != 0)
- {
- h ^= b2;
- }
- b2 <<= 1;
- }
- result[1] = (int)(h >>> 32);
- result[0] = (int)(h & 0x00000000ffffffffL);
- return result;
- }
-
- /**
- * Returns a new GF2Polynomial containing the upper <i>k</i> bytes of this
- * GF2Polynomial.
- *
- * @param k
- * @return a new GF2Polynomial containing the upper <i>k</i> bytes of this
- * GF2Polynomial
- * @see GF2Polynomial#karaMult
- */
- private GF2Polynomial upper(int k)
- {
- int j = Math.min(k, blocks - k);
- GF2Polynomial result = new GF2Polynomial(j << 5);
- if (blocks >= k)
- {
- System.arraycopy(value, k, result.value, 0, j);
- }
- return result;
- }
-
- /**
- * Returns a new GF2Polynomial containing the lower <i>k</i> bytes of this
- * GF2Polynomial.
- *
- * @param k
- * @return a new GF2Polynomial containing the lower <i>k</i> bytes of this
- * GF2Polynomial
- * @see GF2Polynomial#karaMult
- */
- private GF2Polynomial lower(int k)
- {
- GF2Polynomial result = new GF2Polynomial(k << 5);
- System.arraycopy(value, 0, result.value, 0, Math.min(k, blocks));
- return result;
- }
-
- /**
- * Returns the remainder of <i>this</i> divided by <i>g</i> in a new
- * GF2Polynomial.
- *
- * @param g GF2Polynomial != 0
- * @return a new GF2Polynomial (<i>this</i> % <i>g</i>)
- * @throws PolynomialIsZeroException if <i>g</i> equals zero
- */
- public GF2Polynomial remainder(GF2Polynomial g)
- throws RuntimeException
- {
- /* a div b = q / r */
- GF2Polynomial a = new GF2Polynomial(this);
- GF2Polynomial b = new GF2Polynomial(g);
- GF2Polynomial j;
- int i;
- if (b.isZero())
- {
- throw new RuntimeException();
- }
- a.reduceN();
- b.reduceN();
- if (a.len < b.len)
- {
- return a;
- }
- i = a.len - b.len;
- while (i >= 0)
- {
- j = b.shiftLeft(i);
- a.subtractFromThis(j);
- a.reduceN();
- i = a.len - b.len;
- }
- return a;
- }
-
- /**
- * Returns the absolute quotient of <i>this</i> divided by <i>g</i> in a
- * new GF2Polynomial.
- *
- * @param g GF2Polynomial != 0
- * @return a new GF2Polynomial |_ <i>this</i> / <i>g</i> _|
- * @throws PolynomialIsZeroException if <i>g</i> equals zero
- */
- public GF2Polynomial quotient(GF2Polynomial g)
- throws RuntimeException
- {
- /* a div b = q / r */
- GF2Polynomial q = new GF2Polynomial(len);
- GF2Polynomial a = new GF2Polynomial(this);
- GF2Polynomial b = new GF2Polynomial(g);
- GF2Polynomial j;
- int i;
- if (b.isZero())
- {
- throw new RuntimeException();
- }
- a.reduceN();
- b.reduceN();
- if (a.len < b.len)
- {
- return new GF2Polynomial(0);
- }
- i = a.len - b.len;
- q.expandN(i + 1);
-
- while (i >= 0)
- {
- j = b.shiftLeft(i);
- a.subtractFromThis(j);
- a.reduceN();
- q.xorBit(i);
- i = a.len - b.len;
- }
-
- return q;
- }
-
- /**
- * Divides <i>this</i> by <i>g</i> and returns the quotient and remainder
- * in a new GF2Polynomial[2], quotient in [0], remainder in [1].
- *
- * @param g GF2Polynomial != 0
- * @return a new GF2Polynomial[2] containing quotient and remainder
- * @throws PolynomialIsZeroException if <i>g</i> equals zero
- */
- public GF2Polynomial[] divide(GF2Polynomial g)
- throws RuntimeException
- {
- /* a div b = q / r */
- GF2Polynomial[] result = new GF2Polynomial[2];
- GF2Polynomial q = new GF2Polynomial(len);
- GF2Polynomial a = new GF2Polynomial(this);
- GF2Polynomial b = new GF2Polynomial(g);
- GF2Polynomial j;
- int i;
- if (b.isZero())
- {
- throw new RuntimeException();
- }
- a.reduceN();
- b.reduceN();
- if (a.len < b.len)
- {
- result[0] = new GF2Polynomial(0);
- result[1] = a;
- return result;
- }
- i = a.len - b.len;
- q.expandN(i + 1);
-
- while (i >= 0)
- {
- j = b.shiftLeft(i);
- a.subtractFromThis(j);
- a.reduceN();
- q.xorBit(i);
- i = a.len - b.len;
- }
-
- result[0] = q;
- result[1] = a;
- return result;
- }
-
- /**
- * Returns the greatest common divisor of <i>this</i> and <i>g</i> in a
- * new GF2Polynomial.
- *
- * @param g GF2Polynomial != 0
- * @return a new GF2Polynomial gcd(<i>this</i>,<i>g</i>)
- * @throws ArithmeticException if <i>this</i> and <i>g</i> both are equal to zero
- * @throws PolynomialIsZeroException to be API-compliant (should never be thrown).
- */
- public GF2Polynomial gcd(GF2Polynomial g)
- throws RuntimeException
- {
- if (isZero() && g.isZero())
- {
- throw new ArithmeticException("Both operands of gcd equal zero.");
- }
- if (isZero())
- {
- return new GF2Polynomial(g);
- }
- if (g.isZero())
- {
- return new GF2Polynomial(this);
- }
- GF2Polynomial a = new GF2Polynomial(this);
- GF2Polynomial b = new GF2Polynomial(g);
- GF2Polynomial c;
-
- while (!b.isZero())
- {
- c = a.remainder(b);
- a = b;
- b = c;
- }
-
- return a;
- }
-
- /**
- * Checks if <i>this</i> is irreducible, according to IEEE P1363, A.5.5,
- * p103.<br>
- * Note: The algorithm from IEEE P1363, A5.5 can be used to check a
- * polynomial with coefficients in GF(2^r) for irreducibility. As this class
- * only represents polynomials with coefficients in GF(2), the algorithm is
- * adapted to the case r=1.
- *
- * @return true if <i>this</i> is irreducible
- * @see "P1363, A.5.5, p103"
- */
- public boolean isIrreducible()
- {
- if (isZero())
- {
- return false;
- }
- GF2Polynomial f = new GF2Polynomial(this);
- int d, i;
- GF2Polynomial u, g;
- GF2Polynomial dummy;
- f.reduceN();
- d = f.len - 1;
- u = new GF2Polynomial(f.len, "X");
-
- for (i = 1; i <= (d >> 1); i++)
- {
- u.squareThisPreCalc();
- u = u.remainder(f);
- dummy = u.add(new GF2Polynomial(32, "X"));
- if (!dummy.isZero())
- {
- g = f.gcd(dummy);
- if (!g.isOne())
- {
- return false;
- }
- }
- else
- {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Reduces this GF2Polynomial using the trinomial x^<i>m</i> + x^<i>tc</i> +
- * 1.
- *
- * @param m the degree of the used field
- * @param tc degree of the middle x in the trinomial
- */
- void reduceTrinomial(int m, int tc)
- {
- int i;
- int p0, p1;
- int q0, q1;
- long t;
- p0 = m >>> 5; // block which contains 2^m
- q0 = 32 - (m & 0x1f); // (32-index) of 2^m within block p0
- p1 = (m - tc) >>> 5; // block which contains 2^tc
- q1 = 32 - ((m - tc) & 0x1f); // (32-index) of 2^tc within block q1
- int max = ((m << 1) - 2) >>> 5; // block which contains 2^(2m-2)
- int min = p0; // block which contains 2^m
- for (i = max; i > min; i--)
- { // for i = maxBlock to minBlock
- // reduce coefficients contained in t
- // t = block[i]
- t = value[i] & 0x00000000ffffffffL;
- // block[i-p0-1] ^= t << q0
- value[i - p0 - 1] ^= (int)(t << q0);
- // block[i-p0] ^= t >>> (32-q0)
- value[i - p0] ^= t >>> (32 - q0);
- // block[i-p1-1] ^= << q1
- value[i - p1 - 1] ^= (int)(t << q1);
- // block[i-p1] ^= t >>> (32-q1)
- value[i - p1] ^= t >>> (32 - q1);
- value[i] = 0x00;
- }
- // reduce last coefficients in block containing 2^m
- t = value[min] & 0x00000000ffffffffL & (0xffffffffL << (m & 0x1f)); // t
- // contains the last coefficients > m
- value[0] ^= t >>> (32 - q0);
- if (min - p1 - 1 >= 0)
- {
- value[min - p1 - 1] ^= (int)(t << q1);
- }
- value[min - p1] ^= t >>> (32 - q1);
-
- value[min] &= reverseRightMask[m & 0x1f];
- blocks = ((m - 1) >>> 5) + 1;
- len = m;
- }
-
- /**
- * Reduces this GF2Polynomial using the pentanomial x^<i>m</i> + x^<i>pc[2]</i> +
- * x^<i>pc[1]</i> + x^<i>pc[0]</i> + 1.
- *
- * @param m the degree of the used field
- * @param pc degrees of the middle x's in the pentanomial
- */
- void reducePentanomial(int m, int[] pc)
- {
- int i;
- int p0, p1, p2, p3;
- int q0, q1, q2, q3;
- long t;
- p0 = m >>> 5;
- q0 = 32 - (m & 0x1f);
- p1 = (m - pc[0]) >>> 5;
- q1 = 32 - ((m - pc[0]) & 0x1f);
- p2 = (m - pc[1]) >>> 5;
- q2 = 32 - ((m - pc[1]) & 0x1f);
- p3 = (m - pc[2]) >>> 5;
- q3 = 32 - ((m - pc[2]) & 0x1f);
- int max = ((m << 1) - 2) >>> 5;
- int min = p0;
- for (i = max; i > min; i--)
- {
- t = value[i] & 0x00000000ffffffffL;
- value[i - p0 - 1] ^= (int)(t << q0);
- value[i - p0] ^= t >>> (32 - q0);
- value[i - p1 - 1] ^= (int)(t << q1);
- value[i - p1] ^= t >>> (32 - q1);
- value[i - p2 - 1] ^= (int)(t << q2);
- value[i - p2] ^= t >>> (32 - q2);
- value[i - p3 - 1] ^= (int)(t << q3);
- value[i - p3] ^= t >>> (32 - q3);
- value[i] = 0;
- }
- t = value[min] & 0x00000000ffffffffL & (0xffffffffL << (m & 0x1f));
- value[0] ^= t >>> (32 - q0);
- if (min - p1 - 1 >= 0)
- {
- value[min - p1 - 1] ^= (int)(t << q1);
- }
- value[min - p1] ^= t >>> (32 - q1);
- if (min - p2 - 1 >= 0)
- {
- value[min - p2 - 1] ^= (int)(t << q2);
- }
- value[min - p2] ^= t >>> (32 - q2);
- if (min - p3 - 1 >= 0)
- {
- value[min - p3 - 1] ^= (int)(t << q3);
- }
- value[min - p3] ^= t >>> (32 - q3);
- value[min] &= reverseRightMask[m & 0x1f];
-
- blocks = ((m - 1) >>> 5) + 1;
- len = m;
- }
-
- /**
- * Reduces len by finding the most significant bit set to one and reducing
- * len and blocks.
- */
- public void reduceN()
- {
- int i, j, h;
- i = blocks - 1;
- while ((value[i] == 0) && (i > 0))
- {
- i--;
- }
- h = value[i];
- j = 0;
- while (h != 0)
- {
- h >>>= 1;
- j++;
- }
- len = (i << 5) + j;
- blocks = i + 1;
- }
-
- /**
- * Expands len and int[] value to <i>i</i>. This is useful before adding
- * two GF2Polynomials of different size.
- *
- * @param i the intended length
- */
- public void expandN(int i)
- {
- int k;
- int[] bs;
- if (len >= i)
- {
- return;
- }
- len = i;
- k = ((i - 1) >>> 5) + 1;
- if (blocks >= k)
- {
- return;
- }
- if (value.length >= k)
- {
- int j;
- for (j = blocks; j < k; j++)
- {
- value[j] = 0;
- }
- blocks = k;
- return;
- }
- bs = new int[k];
- System.arraycopy(value, 0, bs, 0, blocks);
- blocks = k;
- value = null;
- value = bs;
- }
-
- /**
- * Squares this GF2Polynomial and expands it accordingly. This method does
- * not reduce the result in GF(2^N). There exists a faster method for
- * squaring in GF(2^N).
- *
- * @see GF2nPolynomialElement#square
- */
- public void squareThisBitwise()
- {
- int i, h, j, k;
- if (isZero())
- {
- return;
- }
- int[] result = new int[blocks << 1];
- for (i = blocks - 1; i >= 0; i--)
- {
- h = value[i];
- j = 0x00000001;
- for (k = 0; k < 16; k++)
- {
- if ((h & 0x01) != 0)
- {
- result[i << 1] |= j;
- }
- if ((h & 0x00010000) != 0)
- {
- result[(i << 1) + 1] |= j;
- }
- j <<= 2;
- h >>>= 1;
- }
- }
- value = null;
- value = result;
- blocks = result.length;
- len = (len << 1) - 1;
- }
-
- /**
- * Squares this GF2Polynomial by using precomputed values of squaringTable.
- * This method does not reduce the result in GF(2^N).
- */
- public void squareThisPreCalc()
- {
- int i;
- if (isZero())
- {
- return;
- }
- if (value.length >= (blocks << 1))
- {
- for (i = blocks - 1; i >= 0; i--)
- {
- value[(i << 1) + 1] = GF2Polynomial.squaringTable[(value[i] & 0x00ff0000) >>> 16]
- | (GF2Polynomial.squaringTable[(value[i] & 0xff000000) >>> 24] << 16);
- value[i << 1] = GF2Polynomial.squaringTable[value[i] & 0x000000ff]
- | (GF2Polynomial.squaringTable[(value[i] & 0x0000ff00) >>> 8] << 16);
- }
- blocks <<= 1;
- len = (len << 1) - 1;
- }
- else
- {
- int[] result = new int[blocks << 1];
- for (i = 0; i < blocks; i++)
- {
- result[i << 1] = GF2Polynomial.squaringTable[value[i] & 0x000000ff]
- | (GF2Polynomial.squaringTable[(value[i] & 0x0000ff00) >>> 8] << 16);
- result[(i << 1) + 1] = GF2Polynomial.squaringTable[(value[i] & 0x00ff0000) >>> 16]
- | (GF2Polynomial.squaringTable[(value[i] & 0xff000000) >>> 24] << 16);
- }
- value = null;
- value = result;
- blocks <<= 1;
- len = (len << 1) - 1;
- }
- }
-
- /**
- * Does a vector-multiplication modulo 2 and returns the result as boolean.
- *
- * @param b GF2Polynomial
- * @return this x <i>b</i> as boolean (1-&gt;true, 0-&gt;false)
- * @throws PolynomialsHaveDifferentLengthException if <i>this</i> and <i>b</i> have a different length and
- * thus cannot be vector-multiplied
- */
- public boolean vectorMult(GF2Polynomial b)
- throws RuntimeException
- {
- int i;
- int h;
- boolean result = false;
- if (len != b.len)
- {
- throw new RuntimeException();
- }
- for (i = 0; i < blocks; i++)
- {
- h = value[i] & b.value[i];
- result ^= parity[h & 0x000000ff];
- result ^= parity[(h >>> 8) & 0x000000ff];
- result ^= parity[(h >>> 16) & 0x000000ff];
- result ^= parity[(h >>> 24) & 0x000000ff];
- }
- return result;
- }
-
- /**
- * Returns the bitwise exclusive-or of <i>this</i> and <i>b</i> in a new
- * GF2Polynomial. <i>this</i> and <i>b</i> can be of different size.
- *
- * @param b GF2Polynomial
- * @return a new GF2Polynomial (<i>this</i> ^ <i>b</i>)
- */
- public GF2Polynomial xor(GF2Polynomial b)
- {
- int i;
- GF2Polynomial result;
- int k = Math.min(blocks, b.blocks);
- if (len >= b.len)
- {
- result = new GF2Polynomial(this);
- for (i = 0; i < k; i++)
- {
- result.value[i] ^= b.value[i];
- }
- }
- else
- {
- result = new GF2Polynomial(b);
- for (i = 0; i < k; i++)
- {
- result.value[i] ^= value[i];
- }
- }
- // If we xor'ed some bits too many by proceeding blockwise,
- // restore them to zero:
- result.zeroUnusedBits();
- return result;
- }
-
- /**
- * Computes the bitwise exclusive-or of this GF2Polynomial and <i>b</i> and
- * stores the result in this GF2Polynomial. <i>b</i> can be of different
- * size.
- *
- * @param b GF2Polynomial
- */
- public void xorThisBy(GF2Polynomial b)
- {
- int i;
- for (i = 0; i < Math.min(blocks, b.blocks); i++)
- {
- value[i] ^= b.value[i];
- }
- // If we xor'ed some bits too many by proceeding blockwise,
- // restore them to zero:
- zeroUnusedBits();
- }
-
- /**
- * If {@link #len} is not a multiple of the block size (32), some extra bits
- * of the last block might have been modified during a blockwise operation.
- * This method compensates for that by restoring these "extra" bits to zero.
- */
- private void zeroUnusedBits()
- {
- if ((len & 0x1f) != 0)
- {
- value[blocks - 1] &= reverseRightMask[len & 0x1f];
- }
- }
-
- /**
- * Sets the bit at position <i>i</i>.
- *
- * @param i int
- * @throws BitDoesNotExistException if (<i>i</i> &lt; 0) || (<i>i</i> &gt; (len - 1))
- */
- public void setBit(int i)
- throws RuntimeException
- {
- if (i < 0 || i > (len - 1))
- {
- throw new RuntimeException();
- }
- if (i > (len - 1))
- {
- return;
- }
- value[i >>> 5] |= bitMask[i & 0x1f];
- return;
- }
-
- /**
- * Returns the bit at position <i>i</i>.
- *
- * @param i int
- * @return the bit at position <i>i</i> if <i>i</i> is a valid position, 0
- * otherwise.
- */
- public int getBit(int i)
- {
- if (i < 0 || i > (len - 1))
- {
- return 0;
- }
- return ((value[i >>> 5] & bitMask[i & 0x1f]) != 0) ? 1 : 0;
- }
-
- /**
- * Resets the bit at position <i>i</i>.
- *
- * @param i int
- * @throws BitDoesNotExistException if (<i>i</i> &lt; 0) || (<i>i</i> &gt; (len - 1))
- */
- public void resetBit(int i)
- throws RuntimeException
- {
- if (i < 0 || i > (len - 1))
- {
- throw new RuntimeException();
- }
- if (i > (len - 1))
- {
- return;
- }
- value[i >>> 5] &= ~bitMask[i & 0x1f];
- }
-
- /**
- * Xors the bit at position <i>i</i>.
- *
- * @param i int
- * @throws BitDoesNotExistException if (<i>i</i> &lt; 0) || (<i>i</i> &gt; (len - 1))
- */
- public void xorBit(int i)
- throws RuntimeException
- {
- if (i < 0 || i > (len - 1))
- {
- throw new RuntimeException();
- }
- if (i > (len - 1))
- {
- return;
- }
- value[i >>> 5] ^= bitMask[i & 0x1f];
- }
-
- /**
- * Tests the bit at position <i>i</i>.
- *
- * @param i the position of the bit to be tested
- * @return true if the bit at position <i>i</i> is set (a(<i>i</i>) ==
- * 1). False if (<i>i</i> &lt; 0) || (<i>i</i> &gt; (len - 1))
- */
- public boolean testBit(int i)
- {
- if (i < 0 || i > (len - 1))
- {
- return false;
- }
- return (value[i >>> 5] & bitMask[i & 0x1f]) != 0;
- }
-
- /**
- * Returns this GF2Polynomial shift-left by 1 in a new GF2Polynomial.
- *
- * @return a new GF2Polynomial (this &lt;&lt; 1)
- */
- public GF2Polynomial shiftLeft()
- {
- GF2Polynomial result = new GF2Polynomial(len + 1, value);
- int i;
- for (i = result.blocks - 1; i >= 1; i--)
- {
- result.value[i] <<= 1;
- result.value[i] |= result.value[i - 1] >>> 31;
- }
- result.value[0] <<= 1;
- return result;
- }
-
- /**
- * Shifts-left this by one and enlarges the size of value if necesary.
- */
- public void shiftLeftThis()
- {
- /** @todo This is untested. */
- int i;
- if ((len & 0x1f) == 0)
- { // check if blocks increases
- len += 1;
- blocks += 1;
- if (blocks > value.length)
- { // enlarge value
- int[] bs = new int[blocks];
- System.arraycopy(value, 0, bs, 0, value.length);
- value = null;
- value = bs;
- }
- for (i = blocks - 1; i >= 1; i--)
- {
- value[i] |= value[i - 1] >>> 31;
- value[i - 1] <<= 1;
- }
- }
- else
- {
- len += 1;
- for (i = blocks - 1; i >= 1; i--)
- {
- value[i] <<= 1;
- value[i] |= value[i - 1] >>> 31;
- }
- value[0] <<= 1;
- }
- }
-
- /**
- * Returns this GF2Polynomial shift-left by <i>k</i> in a new
- * GF2Polynomial.
- *
- * @param k int
- * @return a new GF2Polynomial (this &lt;&lt; <i>k</i>)
- */
- public GF2Polynomial shiftLeft(int k)
- {
- // Variant 2, requiring a modified shiftBlocksLeft(k)
- // In case of modification, consider a rename to doShiftBlocksLeft()
- // with an explicit note that this method assumes that the polynomial
- // has already been resized. Or consider doing things inline.
- // Construct the resulting polynomial of appropriate length:
- GF2Polynomial result = new GF2Polynomial(len + k, value);
- // Shift left as many multiples of the block size as possible:
- if (k >= 32)
- {
- result.doShiftBlocksLeft(k >>> 5);
- }
- // Shift left by the remaining (<32) amount:
- final int remaining = k & 0x1f;
- if (remaining != 0)
- {
- for (int i = result.blocks - 1; i >= 1; i--)
- {
- result.value[i] <<= remaining;
- result.value[i] |= result.value[i - 1] >>> (32 - remaining);
- }
- result.value[0] <<= remaining;
- }
- return result;
- }
-
- /**
- * Shifts left b and adds the result to Its a fast version of
- * <tt>this = add(b.shl(k));</tt>
- *
- * @param b GF2Polynomial to shift and add to this
- * @param k the amount to shift
- * @see GF2nPolynomialElement#invertEEA
- */
- public void shiftLeftAddThis(GF2Polynomial b, int k)
- {
- if (k == 0)
- {
- addToThis(b);
- return;
- }
- int i;
- expandN(b.len + k);
- int d = k >>> 5;
- for (i = b.blocks - 1; i >= 0; i--)
- {
- if ((i + d + 1 < blocks) && ((k & 0x1f) != 0))
- {
- value[i + d + 1] ^= b.value[i] >>> (32 - (k & 0x1f));
- }
- value[i + d] ^= b.value[i] << (k & 0x1f);
- }
- }
-
- /**
- * Shifts-left this GF2Polynomial's value blockwise 1 block resulting in a
- * shift-left by 32.
- *
- * @see GF2Polynomial#multiply
- */
- void shiftBlocksLeft()
- {
- blocks += 1;
- len += 32;
- if (blocks <= value.length)
- {
- int i;
- for (i = blocks - 1; i >= 1; i--)
- {
- value[i] = value[i - 1];
- }
- value[0] = 0x00;
- }
- else
- {
- int[] result = new int[blocks];
- System.arraycopy(value, 0, result, 1, blocks - 1);
- value = null;
- value = result;
- }
- }
-
- /**
- * Shifts left this GF2Polynomial's value blockwise <i>b</i> blocks
- * resulting in a shift-left by b*32. This method assumes that {@link #len}
- * and {@link #blocks} have already been updated to reflect the final state.
- *
- * @param b shift amount (in blocks)
- */
- private void doShiftBlocksLeft(int b)
- {
- if (blocks <= value.length)
- {
- int i;
- for (i = blocks - 1; i >= b; i--)
- {
- value[i] = value[i - b];
- }
- for (i = 0; i < b; i++)
- {
- value[i] = 0x00;
- }
- }
- else
- {
- int[] result = new int[blocks];
- System.arraycopy(value, 0, result, b, blocks - b);
- value = null;
- value = result;
- }
- }
-
- /**
- * Returns this GF2Polynomial shift-right by 1 in a new GF2Polynomial.
- *
- * @return a new GF2Polynomial (this &lt;&lt; 1)
- */
- public GF2Polynomial shiftRight()
- {
- GF2Polynomial result = new GF2Polynomial(len - 1);
- int i;
- System.arraycopy(value, 0, result.value, 0, result.blocks);
- for (i = 0; i <= result.blocks - 2; i++)
- {
- result.value[i] >>>= 1;
- result.value[i] |= result.value[i + 1] << 31;
- }
- result.value[result.blocks - 1] >>>= 1;
- if (result.blocks < blocks)
- {
- result.value[result.blocks - 1] |= value[result.blocks] << 31;
- }
- return result;
- }
-
- /**
- * Shifts-right this GF2Polynomial by 1.
- */
- public void shiftRightThis()
- {
- int i;
- len -= 1;
- blocks = ((len - 1) >>> 5) + 1;
- for (i = 0; i <= blocks - 2; i++)
- {
- value[i] >>>= 1;
- value[i] |= value[i + 1] << 31;
- }
- value[blocks - 1] >>>= 1;
- if ((len & 0x1f) == 0)
- {
- value[blocks - 1] |= value[blocks] << 31;
- }
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Vector.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Vector.java
deleted file mode 100644
index ec35b682..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Vector.java
+++ /dev/null
@@ -1,539 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-import java.security.SecureRandom;
-
-/**
- * This class implements the abstract class <tt>Vector</tt> for the case of
- * vectors over the finite field GF(2). <br>
- * For the vector representation the array of type int[] is used, thus one
- * element of the array holds 32 elements of the vector.
- *
- * @see Vector
- */
-public class GF2Vector
- extends Vector
-{
-
- /**
- * holds the elements of this vector
- */
- private int[] v;
-
- /**
- * Construct the zero vector of the given length.
- *
- * @param length the length of the vector
- */
- public GF2Vector(int length)
- {
- if (length < 0)
- {
- throw new ArithmeticException("Negative length.");
- }
- this.length = length;
- v = new int[(length + 31) >> 5];
- }
-
- /**
- * Construct a random GF2Vector of the given length.
- *
- * @param length the length of the vector
- * @param sr the source of randomness
- */
- public GF2Vector(int length, SecureRandom sr)
- {
- this.length = length;
-
- int size = (length + 31) >> 5;
- v = new int[size];
-
- // generate random elements
- for (int i = size - 1; i >= 0; i--)
- {
- v[i] = sr.nextInt();
- }
-
- // erase unused bits
- int r = length & 0x1f;
- if (r != 0)
- {
- // erase unused bits
- v[size - 1] &= (1 << r) - 1;
- }
- }
-
- /**
- * Construct a random GF2Vector of the given length with the specified
- * number of non-zero coefficients.
- *
- * @param length the length of the vector
- * @param t the number of non-zero coefficients
- * @param sr the source of randomness
- */
- public GF2Vector(int length, int t, SecureRandom sr)
- {
- if (t > length)
- {
- throw new ArithmeticException(
- "The hamming weight is greater than the length of vector.");
- }
- this.length = length;
-
- int size = (length + 31) >> 5;
- v = new int[size];
-
- int[] help = new int[length];
- for (int i = 0; i < length; i++)
- {
- help[i] = i;
- }
-
- int m = length;
- for (int i = 0; i < t; i++)
- {
- int j = RandUtils.nextInt(sr, m);
- setBit(help[j]);
- m--;
- help[j] = help[m];
- }
- }
-
- /**
- * Construct a GF2Vector of the given length and with elements from the
- * given array. The array is copied and unused bits are masked out.
- *
- * @param length the length of the vector
- * @param v the element array
- */
- public GF2Vector(int length, int[] v)
- {
- if (length < 0)
- {
- throw new ArithmeticException("negative length");
- }
- this.length = length;
-
- int size = (length + 31) >> 5;
-
- if (v.length != size)
- {
- throw new ArithmeticException("length mismatch");
- }
-
- this.v = IntUtils.clone(v);
-
- int r = length & 0x1f;
- if (r != 0)
- {
- // erase unused bits
- this.v[size - 1] &= (1 << r) - 1;
- }
- }
-
- /**
- * Copy constructor.
- *
- * @param other another {@link GF2Vector}
- */
- public GF2Vector(GF2Vector other)
- {
- this.length = other.length;
- this.v = IntUtils.clone(other.v);
- }
-
- /**
- * Construct a new {@link GF2Vector} of the given length and with the given
- * element array. The array is not changed and only a reference to the array
- * is stored. No length checking is performed either.
- *
- * @param v the element array
- * @param length the length of the vector
- */
- protected GF2Vector(int[] v, int length)
- {
- this.v = v;
- this.length = length;
- }
-
- /**
- * Construct a new GF2Vector with the given length out of the encoded
- * vector.
- *
- * @param length the length of the vector
- * @param encVec the encoded vector
- * @return the decoded vector
- */
- public static GF2Vector OS2VP(int length, byte[] encVec)
- {
- if (length < 0)
- {
- throw new ArithmeticException("negative length");
- }
-
- int byteLen = (length + 7) >> 3;
-
- if (encVec.length > byteLen)
- {
- throw new ArithmeticException("length mismatch");
- }
-
- return new GF2Vector(length, LittleEndianConversions.toIntArray(encVec));
- }
-
- /**
- * Encode this vector as byte array.
- *
- * @return the encoded vector
- */
- public byte[] getEncoded()
- {
- int byteLen = (length + 7) >> 3;
- return LittleEndianConversions.toByteArray(v, byteLen);
- }
-
- /**
- * @return the int array representation of this vector
- */
- public int[] getVecArray()
- {
- return v;
- }
-
- /**
- * Return the Hamming weight of this vector, i.e., compute the number of
- * units of this vector.
- *
- * @return the Hamming weight of this vector
- */
- public int getHammingWeight()
- {
- int weight = 0;
- for (int i = 0; i < v.length; i++)
- {
- int e = v[i];
- for (int j = 0; j < 32; j++)
- {
- int b = e & 1;
- if (b != 0)
- {
- weight++;
- }
- e >>>= 1;
- }
- }
- return weight;
- }
-
- /**
- * @return whether this is the zero vector (i.e., all elements are zero)
- */
- public boolean isZero()
- {
- for (int i = v.length - 1; i >= 0; i--)
- {
- if (v[i] != 0)
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Return the value of the bit of this vector at the specified index.
- *
- * @param index the index
- * @return the value of the bit (0 or 1)
- */
- public int getBit(int index)
- {
- if (index >= length)
- {
- throw new IndexOutOfBoundsException();
- }
- int q = index >> 5;
- int r = index & 0x1f;
- return (v[q] & (1 << r)) >>> r;
- }
-
- /**
- * Set the coefficient at the given index to 1. If the index is out of
- * bounds, do nothing.
- *
- * @param index the index of the coefficient to set
- */
- public void setBit(int index)
- {
- if (index >= length)
- {
- throw new IndexOutOfBoundsException();
- }
- v[index >> 5] |= 1 << (index & 0x1f);
- }
-
- /**
- * Adds another GF2Vector to this vector.
- *
- * @param other another GF2Vector
- * @return <tt>this + other</tt>
- * @throws ArithmeticException if the other vector is not a GF2Vector or has another
- * length.
- */
- public Vector add(Vector other)
- {
- if (!(other instanceof GF2Vector))
- {
- throw new ArithmeticException("vector is not defined over GF(2)");
- }
-
- GF2Vector otherVec = (GF2Vector)other;
- if (length != otherVec.length)
- {
- throw new ArithmeticException("length mismatch");
- }
-
- int[] vec = IntUtils.clone(((GF2Vector)other).v);
-
- for (int i = vec.length - 1; i >= 0; i--)
- {
- vec[i] ^= v[i];
- }
-
- return new GF2Vector(length, vec);
- }
-
- /**
- * Multiply this vector with a permutation.
- *
- * @param p the permutation
- * @return <tt>this*p = p*this</tt>
- */
- public Vector multiply(Permutation p)
- {
- int[] pVec = p.getVector();
- if (length != pVec.length)
- {
- throw new ArithmeticException("length mismatch");
- }
-
- GF2Vector result = new GF2Vector(length);
-
- for (int i = 0; i < pVec.length; i++)
- {
- int e = v[pVec[i] >> 5] & (1 << (pVec[i] & 0x1f));
- if (e != 0)
- {
- result.v[i >> 5] |= 1 << (i & 0x1f);
- }
- }
-
- return result;
- }
-
- /**
- * Return a new vector consisting of the elements of this vector with the
- * indices given by the set <tt>setJ</tt>.
- *
- * @param setJ the set of indices of elements to extract
- * @return the new {@link GF2Vector}
- * <tt>[this_setJ[0], this_setJ[1], ..., this_setJ[#setJ-1]]</tt>
- */
- public GF2Vector extractVector(int[] setJ)
- {
- int k = setJ.length;
- if (setJ[k - 1] > length)
- {
- throw new ArithmeticException("invalid index set");
- }
-
- GF2Vector result = new GF2Vector(k);
-
- for (int i = 0; i < k; i++)
- {
- int e = v[setJ[i] >> 5] & (1 << (setJ[i] & 0x1f));
- if (e != 0)
- {
- result.v[i >> 5] |= 1 << (i & 0x1f);
- }
- }
-
- return result;
- }
-
- /**
- * Return a new vector consisting of the first <tt>k</tt> elements of this
- * vector.
- *
- * @param k the number of elements to extract
- * @return a new {@link GF2Vector} consisting of the first <tt>k</tt>
- * elements of this vector
- */
- public GF2Vector extractLeftVector(int k)
- {
- if (k > length)
- {
- throw new ArithmeticException("invalid length");
- }
-
- if (k == length)
- {
- return new GF2Vector(this);
- }
-
- GF2Vector result = new GF2Vector(k);
-
- int q = k >> 5;
- int r = k & 0x1f;
-
- System.arraycopy(v, 0, result.v, 0, q);
- if (r != 0)
- {
- result.v[q] = v[q] & ((1 << r) - 1);
- }
-
- return result;
- }
-
- /**
- * Return a new vector consisting of the last <tt>k</tt> elements of this
- * vector.
- *
- * @param k the number of elements to extract
- * @return a new {@link GF2Vector} consisting of the last <tt>k</tt>
- * elements of this vector
- */
- public GF2Vector extractRightVector(int k)
- {
- if (k > length)
- {
- throw new ArithmeticException("invalid length");
- }
-
- if (k == length)
- {
- return new GF2Vector(this);
- }
-
- GF2Vector result = new GF2Vector(k);
-
- int q = (length - k) >> 5;
- int r = (length - k) & 0x1f;
- int length = (k + 31) >> 5;
-
- int ind = q;
- // if words have to be shifted
- if (r != 0)
- {
- // process all but last word
- for (int i = 0; i < length - 1; i++)
- {
- result.v[i] = (v[ind++] >>> r) | (v[ind] << (32 - r));
- }
- // process last word
- result.v[length - 1] = v[ind++] >>> r;
- if (ind < v.length)
- {
- result.v[length - 1] |= v[ind] << (32 - r);
- }
- }
- else
- {
- // no shift necessary
- System.arraycopy(v, q, result.v, 0, length);
- }
-
- return result;
- }
-
- /**
- * Rewrite this vector as a vector over <tt>GF(2<sup>m</sup>)</tt> with
- * <tt>t</tt> elements.
- *
- * @param field the finite field <tt>GF(2<sup>m</sup>)</tt>
- * @return the converted vector over <tt>GF(2<sup>m</sup>)</tt>
- */
- public GF2mVector toExtensionFieldVector(GF2mField field)
- {
- int m = field.getDegree();
- if ((length % m) != 0)
- {
- throw new ArithmeticException("conversion is impossible");
- }
-
- int t = length / m;
- int[] result = new int[t];
- int count = 0;
- for (int i = t - 1; i >= 0; i--)
- {
- for (int j = field.getDegree() - 1; j >= 0; j--)
- {
- int q = count >>> 5;
- int r = count & 0x1f;
-
- int e = (v[q] >>> r) & 1;
- if (e == 1)
- {
- result[i] ^= 1 << j;
- }
- count++;
- }
- }
- return new GF2mVector(field, result);
- }
-
- /**
- * Check if the given object is equal to this vector.
- *
- * @param other vector
- * @return the result of the comparison
- */
- public boolean equals(Object other)
- {
-
- if (!(other instanceof GF2Vector))
- {
- return false;
- }
- GF2Vector otherVec = (GF2Vector)other;
-
- return (length == otherVec.length) && IntUtils.equals(v, otherVec.v);
- }
-
- /**
- * @return the hash code of this vector
- */
- public int hashCode()
- {
- int hash = length;
- hash = hash * 31 + v.hashCode();
- return hash;
- }
-
- /**
- * @return a human readable form of this vector
- */
- public String toString()
- {
- StringBuffer buf = new StringBuffer();
- for (int i = 0; i < length; i++)
- {
- if ((i != 0) && ((i & 0x1f) == 0))
- {
- buf.append(' ');
- }
- int q = i >> 5;
- int r = i & 0x1f;
- int bit = v[q] & (1 << r);
- if (bit == 0)
- {
- buf.append('0');
- }
- else
- {
- buf.append('1');
- }
- }
- return buf.toString();
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mField.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mField.java
deleted file mode 100644
index 37298a1e..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mField.java
+++ /dev/null
@@ -1,365 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-import java.security.SecureRandom;
-
-/**
- * This class describes operations with elements from the finite field F =
- * GF(2^m). ( GF(2^m)= GF(2)[A] where A is a root of irreducible polynomial with
- * degree m, each field element B has a polynomial basis representation, i.e. it
- * is represented by a different binary polynomial of degree less than m, B =
- * poly(A) ) All operations are defined only for field with 1&lt; m &lt;32. For the
- * representation of field elements the map f: F-&gt;Z, poly(A)-&gt;poly(2) is used,
- * where integers have the binary representation. For example: A^7+A^3+A+1 -&gt;
- * (00...0010001011)=139 Also for elements type Integer is used.
- *
- * @see PolynomialRingGF2
- */
-public class GF2mField
-{
-
- /*
- * degree - degree of the field polynomial - the field polynomial ring -
- * polynomial ring over the finite field GF(2)
- */
-
- private int degree = 0;
-
- private int polynomial;
-
- /**
- * create a finite field GF(2^m)
- *
- * @param degree the degree of the field
- */
- public GF2mField(int degree)
- {
- if (degree >= 32)
- {
- throw new IllegalArgumentException(
- " Error: the degree of field is too large ");
- }
- if (degree < 1)
- {
- throw new IllegalArgumentException(
- " Error: the degree of field is non-positive ");
- }
- this.degree = degree;
- polynomial = PolynomialRingGF2.getIrreduciblePolynomial(degree);
- }
-
- /**
- * create a finite field GF(2^m) with the fixed field polynomial
- *
- * @param degree the degree of the field
- * @param poly the field polynomial
- */
- public GF2mField(int degree, int poly)
- {
- if (degree != PolynomialRingGF2.degree(poly))
- {
- throw new IllegalArgumentException(
- " Error: the degree is not correct");
- }
- if (!PolynomialRingGF2.isIrreducible(poly))
- {
- throw new IllegalArgumentException(
- " Error: given polynomial is reducible");
- }
- this.degree = degree;
- polynomial = poly;
-
- }
-
- public GF2mField(byte[] enc)
- {
- if (enc.length != 4)
- {
- throw new IllegalArgumentException(
- "byte array is not an encoded finite field");
- }
- polynomial = LittleEndianConversions.OS2IP(enc);
- if (!PolynomialRingGF2.isIrreducible(polynomial))
- {
- throw new IllegalArgumentException(
- "byte array is not an encoded finite field");
- }
-
- degree = PolynomialRingGF2.degree(polynomial);
- }
-
- public GF2mField(GF2mField field)
- {
- degree = field.degree;
- polynomial = field.polynomial;
- }
-
- /**
- * return degree of the field
- *
- * @return degree of the field
- */
- public int getDegree()
- {
- return degree;
- }
-
- /**
- * return the field polynomial
- *
- * @return the field polynomial
- */
- public int getPolynomial()
- {
- return polynomial;
- }
-
- /**
- * return the encoded form of this field
- *
- * @return the field in byte array form
- */
- public byte[] getEncoded()
- {
- return LittleEndianConversions.I2OSP(polynomial);
- }
-
- /**
- * Return sum of two elements
- *
- * @param a
- * @param b
- * @return a+b
- */
- public int add(int a, int b)
- {
- return a ^ b;
- }
-
- /**
- * Return product of two elements
- *
- * @param a
- * @param b
- * @return a*b
- */
- public int mult(int a, int b)
- {
- return PolynomialRingGF2.modMultiply(a, b, polynomial);
- }
-
- /**
- * compute exponentiation a^k
- *
- * @param a a field element a
- * @param k k degree
- * @return a^k
- */
- public int exp(int a, int k)
- {
- if (a == 0)
- {
- return 0;
- }
- if (a == 1)
- {
- return 1;
- }
- int result = 1;
- if (k < 0)
- {
- a = inverse(a);
- k = -k;
- }
- while (k != 0)
- {
- if ((k & 1) == 1)
- {
- result = mult(result, a);
- }
- a = mult(a, a);
- k >>>= 1;
- }
- return result;
- }
-
- /**
- * compute the multiplicative inverse of a
- *
- * @param a a field element a
- * @return a<sup>-1</sup>
- */
- public int inverse(int a)
- {
- int d = (1 << degree) - 2;
-
- return exp(a, d);
- }
-
- /**
- * compute the square root of an integer
- *
- * @param a a field element a
- * @return a<sup>1/2</sup>
- */
- public int sqRoot(int a)
- {
- for (int i = 1; i < degree; i++)
- {
- a = mult(a, a);
- }
- return a;
- }
-
- /**
- * create a random field element using PRNG sr
- *
- * @param sr SecureRandom
- * @return a random element
- */
- public int getRandomElement(SecureRandom sr)
- {
- int result = RandUtils.nextInt(sr, 1 << degree);
- return result;
- }
-
- /**
- * create a random non-zero field element
- *
- * @return a random element
- */
- public int getRandomNonZeroElement()
- {
- return getRandomNonZeroElement(new SecureRandom());
- }
-
- /**
- * create a random non-zero field element using PRNG sr
- *
- * @param sr SecureRandom
- * @return a random non-zero element
- */
- public int getRandomNonZeroElement(SecureRandom sr)
- {
- int controltime = 1 << 20;
- int count = 0;
- int result = RandUtils.nextInt(sr, 1 << degree);
- while ((result == 0) && (count < controltime))
- {
- result = RandUtils.nextInt(sr, 1 << degree);
- count++;
- }
- if (count == controltime)
- {
- result = 1;
- }
- return result;
- }
-
- /**
- * @return true if e is encoded element of this field and false otherwise
- */
- public boolean isElementOfThisField(int e)
- {
- // e is encoded element of this field iff 0<= e < |2^m|
- if (degree == 31)
- {
- return e >= 0;
- }
- return e >= 0 && e < (1 << degree);
- }
-
- /*
- * help method for visual control
- */
- public String elementToStr(int a)
- {
- String s = "";
- for (int i = 0; i < degree; i++)
- {
- if (((byte)a & 0x01) == 0)
- {
- s = "0" + s;
- }
- else
- {
- s = "1" + s;
- }
- a >>>= 1;
- }
- return s;
- }
-
- /**
- * checks if given object is equal to this field.
- * <p>
- * The method returns false whenever the given object is not GF2m.
- *
- * @param other object
- * @return true or false
- */
- public boolean equals(Object other)
- {
- if ((other == null) || !(other instanceof GF2mField))
- {
- return false;
- }
-
- GF2mField otherField = (GF2mField)other;
-
- if ((degree == otherField.degree)
- && (polynomial == otherField.polynomial))
- {
- return true;
- }
-
- return false;
- }
-
- public int hashCode()
- {
- return polynomial;
- }
-
- /**
- * Returns a human readable form of this field.
- *
- * @return a human readable form of this field.
- */
- public String toString()
- {
- String str = "Finite Field GF(2^" + degree + ") = " + "GF(2)[X]/<"
- + polyToString(polynomial) + "> ";
- return str;
- }
-
- private static String polyToString(int p)
- {
- String str = "";
- if (p == 0)
- {
- str = "0";
- }
- else
- {
- byte b = (byte)(p & 0x01);
- if (b == 1)
- {
- str = "1";
- }
- p >>>= 1;
- int i = 1;
- while (p != 0)
- {
- b = (byte)(p & 0x01);
- if (b == 1)
- {
- str = str + "+x^" + i;
- }
- p >>>= 1;
- i++;
- }
- }
- return str;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mMatrix.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mMatrix.java
deleted file mode 100644
index 8dfdb9b1..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mMatrix.java
+++ /dev/null
@@ -1,377 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-/**
- * This class describes some operations with matrices over finite field <i>GF(2<sup>m</sup>)</i>
- * with small <i>m</i> (1&lt; m &lt;32).
- *
- * @see Matrix
- */
-public class GF2mMatrix
- extends Matrix
-{
-
- /**
- * finite field GF(2^m)
- */
- protected GF2mField field;
-
- /**
- * For the matrix representation the array of type int[][] is used, thus
- * every element of the array keeps one element of the matrix (element from
- * finite field GF(2^m))
- */
- protected int[][] matrix;
-
- /**
- * Constructor.
- *
- * @param field a finite field GF(2^m)
- * @param enc byte[] matrix in byte array form
- */
- public GF2mMatrix(GF2mField field, byte[] enc)
- {
-
- this.field = field;
-
- // decode matrix
- int d = 8;
- int count = 1;
- while (field.getDegree() > d)
- {
- count++;
- d += 8;
- }
-
- if (enc.length < 5)
- {
- throw new IllegalArgumentException(
- " Error: given array is not encoded matrix over GF(2^m)");
- }
-
- this.numRows = ((enc[3] & 0xff) << 24) ^ ((enc[2] & 0xff) << 16)
- ^ ((enc[1] & 0xff) << 8) ^ (enc[0] & 0xff);
-
- int n = count * this.numRows;
-
- if ((this.numRows <= 0) || (((enc.length - 4) % n) != 0))
- {
- throw new IllegalArgumentException(
- " Error: given array is not encoded matrix over GF(2^m)");
- }
-
- this.numColumns = (enc.length - 4) / n;
-
- matrix = new int[this.numRows][this.numColumns];
- count = 4;
- for (int i = 0; i < this.numRows; i++)
- {
- for (int j = 0; j < this.numColumns; j++)
- {
- for (int jj = 0; jj < d; jj += 8)
- {
- matrix[i][j] ^= (enc[count++] & 0x000000ff) << jj;
- }
- if (!this.field.isElementOfThisField(matrix[i][j]))
- {
- throw new IllegalArgumentException(
- " Error: given array is not encoded matrix over GF(2^m)");
- }
- }
- }
- }
-
- /**
- * Copy constructor.
- *
- * @param other another {@link GF2mMatrix}
- */
- public GF2mMatrix(GF2mMatrix other)
- {
- numRows = other.numRows;
- numColumns = other.numColumns;
- field = other.field;
- matrix = new int[numRows][];
- for (int i = 0; i < numRows; i++)
- {
- matrix[i] = IntUtils.clone(other.matrix[i]);
- }
- }
-
- /**
- * Constructor.
- *
- * @param field a finite field GF(2^m)
- * @param matrix the matrix as int array. Only the reference is copied.
- */
- protected GF2mMatrix(GF2mField field, int[][] matrix)
- {
- this.field = field;
- this.matrix = matrix;
- numRows = matrix.length;
- numColumns = matrix[0].length;
- }
-
- /**
- * @return a byte array encoding of this matrix
- */
- public byte[] getEncoded()
- {
- int d = 8;
- int count = 1;
- while (field.getDegree() > d)
- {
- count++;
- d += 8;
- }
-
- byte[] bf = new byte[this.numRows * this.numColumns * count + 4];
- bf[0] = (byte)(this.numRows & 0xff);
- bf[1] = (byte)((this.numRows >>> 8) & 0xff);
- bf[2] = (byte)((this.numRows >>> 16) & 0xff);
- bf[3] = (byte)((this.numRows >>> 24) & 0xff);
-
- count = 4;
- for (int i = 0; i < this.numRows; i++)
- {
- for (int j = 0; j < this.numColumns; j++)
- {
- for (int jj = 0; jj < d; jj += 8)
- {
- bf[count++] = (byte)(matrix[i][j] >>> jj);
- }
- }
- }
-
- return bf;
- }
-
- /**
- * Check if this is the zero matrix (i.e., all entries are zero).
- *
- * @return <tt>true</tt> if this is the zero matrix
- */
- public boolean isZero()
- {
- for (int i = 0; i < numRows; i++)
- {
- for (int j = 0; j < numColumns; j++)
- {
- if (matrix[i][j] != 0)
- {
- return false;
- }
- }
- }
- return true;
- }
-
- /**
- * Compute the inverse of this matrix.
- *
- * @return the inverse of this matrix (newly created).
- */
- public Matrix computeInverse()
- {
- if (numRows != numColumns)
- {
- throw new ArithmeticException("Matrix is not invertible.");
- }
-
- // clone this matrix
- int[][] tmpMatrix = new int[numRows][numRows];
- for (int i = numRows - 1; i >= 0; i--)
- {
- tmpMatrix[i] = IntUtils.clone(matrix[i]);
- }
-
- // initialize inverse matrix as unit matrix
- int[][] invMatrix = new int[numRows][numRows];
- for (int i = numRows - 1; i >= 0; i--)
- {
- invMatrix[i][i] = 1;
- }
-
- // simultaneously compute Gaussian reduction of tmpMatrix and unit
- // matrix
- for (int i = 0; i < numRows; i++)
- {
- // if diagonal element is zero
- if (tmpMatrix[i][i] == 0)
- {
- boolean foundNonZero = false;
- // find a non-zero element in the same column
- for (int j = i + 1; j < numRows; j++)
- {
- if (tmpMatrix[j][i] != 0)
- {
- // found it, swap rows ...
- foundNonZero = true;
- swapColumns(tmpMatrix, i, j);
- swapColumns(invMatrix, i, j);
- // ... and quit searching
- j = numRows;
- continue;
- }
- }
- // if no non-zero element was found
- if (!foundNonZero)
- {
- // the matrix is not invertible
- throw new ArithmeticException("Matrix is not invertible.");
- }
- }
-
- // normalize i-th row
- int coef = tmpMatrix[i][i];
- int invCoef = field.inverse(coef);
- multRowWithElementThis(tmpMatrix[i], invCoef);
- multRowWithElementThis(invMatrix[i], invCoef);
-
- // normalize all other rows
- for (int j = 0; j < numRows; j++)
- {
- if (j != i)
- {
- coef = tmpMatrix[j][i];
- if (coef != 0)
- {
- int[] tmpRow = multRowWithElement(tmpMatrix[i], coef);
- int[] tmpInvRow = multRowWithElement(invMatrix[i], coef);
- addToRow(tmpRow, tmpMatrix[j]);
- addToRow(tmpInvRow, invMatrix[j]);
- }
- }
- }
- }
-
- return new GF2mMatrix(field, invMatrix);
- }
-
- private static void swapColumns(int[][] matrix, int first, int second)
- {
- int[] tmp = matrix[first];
- matrix[first] = matrix[second];
- matrix[second] = tmp;
- }
-
- private void multRowWithElementThis(int[] row, int element)
- {
- for (int i = row.length - 1; i >= 0; i--)
- {
- row[i] = field.mult(row[i], element);
- }
- }
-
- private int[] multRowWithElement(int[] row, int element)
- {
- int[] result = new int[row.length];
- for (int i = row.length - 1; i >= 0; i--)
- {
- result[i] = field.mult(row[i], element);
- }
- return result;
- }
-
- /**
- * Add one row to another.
- *
- * @param fromRow the addend
- * @param toRow the row to add to
- */
- private void addToRow(int[] fromRow, int[] toRow)
- {
- for (int i = toRow.length - 1; i >= 0; i--)
- {
- toRow[i] = field.add(fromRow[i], toRow[i]);
- }
- }
-
- public Matrix rightMultiply(Matrix a)
- {
- throw new RuntimeException("Not implemented.");
- }
-
- public Matrix rightMultiply(Permutation perm)
- {
- throw new RuntimeException("Not implemented.");
- }
-
- public Vector leftMultiply(Vector vector)
- {
- throw new RuntimeException("Not implemented.");
- }
-
- public Vector rightMultiply(Vector vector)
- {
- throw new RuntimeException("Not implemented.");
- }
-
- /**
- * Checks if given object is equal to this matrix. The method returns false
- * whenever the given object is not a matrix over GF(2^m).
- *
- * @param other object
- * @return true or false
- */
- public boolean equals(Object other)
- {
-
- if (other == null || !(other instanceof GF2mMatrix))
- {
- return false;
- }
-
- GF2mMatrix otherMatrix = (GF2mMatrix)other;
-
- if ((!this.field.equals(otherMatrix.field))
- || (otherMatrix.numRows != this.numColumns)
- || (otherMatrix.numColumns != this.numColumns))
- {
- return false;
- }
-
- for (int i = 0; i < this.numRows; i++)
- {
- for (int j = 0; j < this.numColumns; j++)
- {
- if (this.matrix[i][j] != otherMatrix.matrix[i][j])
- {
- return false;
- }
- }
- }
-
- return true;
- }
-
- public int hashCode()
- {
- int hash = (this.field.hashCode() * 31 + numRows) * 31 + numColumns;
- for (int i = 0; i < this.numRows; i++)
- {
- for (int j = 0; j < this.numColumns; j++)
- {
- hash = hash * 31 + matrix[i][j];
- }
- }
- return hash;
- }
-
- public String toString()
- {
- String str = this.numRows + " x " + this.numColumns + " Matrix over "
- + this.field.toString() + ": \n";
-
- for (int i = 0; i < this.numRows; i++)
- {
- for (int j = 0; j < this.numColumns; j++)
- {
- str = str + this.field.elementToStr(matrix[i][j]) + " : ";
- }
- str = str + "\n";
- }
-
- return str;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mVector.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mVector.java
deleted file mode 100644
index f2527f67..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mVector.java
+++ /dev/null
@@ -1,256 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-
-/**
- * This class implements vectors over the finite field
- * <tt>GF(2<sup>m</sup>)</tt> for small <tt>m</tt> (i.e.,
- * <tt>1&lt;m&lt;32</tt>). It extends the abstract class {@link Vector}.
- */
-public class GF2mVector
- extends Vector
-{
-
- /**
- * the finite field this vector is defined over
- */
- private GF2mField field;
-
- /**
- * the element array
- */
- private int[] vector;
-
- /**
- * creates the vector over GF(2^m) of given length and with elements from
- * array v (beginning at the first bit)
- *
- * @param field finite field
- * @param v array with elements of vector
- */
- public GF2mVector(GF2mField field, byte[] v)
- {
- this.field = new GF2mField(field);
-
- // decode vector
- int d = 8;
- int count = 1;
- while (field.getDegree() > d)
- {
- count++;
- d += 8;
- }
-
- if ((v.length % count) != 0)
- {
- throw new IllegalArgumentException(
- "Byte array is not an encoded vector over the given finite field.");
- }
-
- length = v.length / count;
- vector = new int[length];
- count = 0;
- for (int i = 0; i < vector.length; i++)
- {
- for (int j = 0; j < d; j += 8)
- {
- vector[i] |= (v[count++] & 0xff) << j;
- }
- if (!field.isElementOfThisField(vector[i]))
- {
- throw new IllegalArgumentException(
- "Byte array is not an encoded vector over the given finite field.");
- }
- }
- }
-
- /**
- * Create a new vector over <tt>GF(2<sup>m</sup>)</tt> of the given
- * length and element array.
- *
- * @param field the finite field <tt>GF(2<sup>m</sup>)</tt>
- * @param vector the element array
- */
- public GF2mVector(GF2mField field, int[] vector)
- {
- this.field = field;
- length = vector.length;
- for (int i = vector.length - 1; i >= 0; i--)
- {
- if (!field.isElementOfThisField(vector[i]))
- {
- throw new ArithmeticException(
- "Element array is not specified over the given finite field.");
- }
- }
- this.vector = IntUtils.clone(vector);
- }
-
- /**
- * Copy constructor.
- *
- * @param other another {@link GF2mVector}
- */
- public GF2mVector(GF2mVector other)
- {
- field = new GF2mField(other.field);
- length = other.length;
- vector = IntUtils.clone(other.vector);
- }
-
- /**
- * @return the finite field this vector is defined over
- */
- public GF2mField getField()
- {
- return field;
- }
-
- /**
- * @return int[] form of this vector
- */
- public int[] getIntArrayForm()
- {
- return IntUtils.clone(vector);
- }
-
- /**
- * @return a byte array encoding of this vector
- */
- public byte[] getEncoded()
- {
- int d = 8;
- int count = 1;
- while (field.getDegree() > d)
- {
- count++;
- d += 8;
- }
-
- byte[] res = new byte[vector.length * count];
- count = 0;
- for (int i = 0; i < vector.length; i++)
- {
- for (int j = 0; j < d; j += 8)
- {
- res[count++] = (byte)(vector[i] >>> j);
- }
- }
-
- return res;
- }
-
- /**
- * @return whether this is the zero vector (i.e., all elements are zero)
- */
- public boolean isZero()
- {
- for (int i = vector.length - 1; i >= 0; i--)
- {
- if (vector[i] != 0)
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Add another vector to this vector. Method is not yet implemented.
- *
- * @param addend the other vector
- * @return <tt>this + addend</tt>
- * @throws ArithmeticException if the other vector is not defined over the same field as
- * this vector.
- * <p>
- * TODO: implement this method
- */
- public Vector add(Vector addend)
- {
- throw new RuntimeException("not implemented");
- }
-
- /**
- * Multiply this vector with a permutation.
- *
- * @param p the permutation
- * @return <tt>this*p = p*this</tt>
- */
- public Vector multiply(Permutation p)
- {
- int[] pVec = p.getVector();
- if (length != pVec.length)
- {
- throw new ArithmeticException(
- "permutation size and vector size mismatch");
- }
-
- int[] result = new int[length];
- for (int i = 0; i < pVec.length; i++)
- {
- result[i] = vector[pVec[i]];
- }
-
- return new GF2mVector(field, result);
- }
-
- /**
- * Compare this vector with another object.
- *
- * @param other the other object
- * @return the result of the comparison
- */
- public boolean equals(Object other)
- {
-
- if (!(other instanceof GF2mVector))
- {
- return false;
- }
- GF2mVector otherVec = (GF2mVector)other;
-
- if (!field.equals(otherVec.field))
- {
- return false;
- }
-
- return IntUtils.equals(vector, otherVec.vector);
- }
-
- /**
- * @return the hash code of this vector
- */
- public int hashCode()
- {
- int hash = this.field.hashCode();
- hash = hash * 31 + vector.hashCode();
- return hash;
- }
-
- /**
- * @return a human readable form of this vector
- */
- public String toString()
- {
- StringBuffer buf = new StringBuffer();
- for (int i = 0; i < vector.length; i++)
- {
- for (int j = 0; j < field.getDegree(); j++)
- {
- int r = j & 0x1f;
- int bitMask = 1 << r;
- int coeff = vector[i] & bitMask;
- if (coeff != 0)
- {
- buf.append('1');
- }
- else
- {
- buf.append('0');
- }
- }
- buf.append(' ');
- }
- return buf.toString();
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nElement.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nElement.java
deleted file mode 100644
index faa99dcb..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nElement.java
+++ /dev/null
@@ -1,186 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-
-/**
- * This abstract class implements an element of the finite field <i>GF(2)<sup>n
- * </sup></i> in either <i>optimal normal basis</i> representation (<i>ONB</i>)
- * or in <i>polynomial</i> representation. It is extended by the classes <a
- * href = GF2nONBElement.html><tt> GF2nONBElement</tt></a> and <a href =
- * GF2nPolynomialElement.html> <tt>GF2nPolynomialElement</tt> </a>.
- *
- * @see GF2nPolynomialElement
- * @see GF2nONBElement
- * @see GF2nONBField
- */
-public abstract class GF2nElement
- implements GFElement
-{
-
- // /////////////////////////////////////////////////////////////////////
- // member variables
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * holds a pointer to this element's corresponding field.
- */
- protected GF2nField mField;
-
- /**
- * holds the extension degree <i>n</i> of this element's corresponding
- * field.
- */
- protected int mDegree;
-
- // /////////////////////////////////////////////////////////////////////
- // pseudo-constructors
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * @return a copy of this GF2nElement
- */
- public abstract Object clone();
-
- // /////////////////////////////////////////////////////////////////////
- // assignments
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Assign the value 0 to this element.
- */
- abstract void assignZero();
-
- /**
- * Assigns the value 1 to this element.
- */
- abstract void assignOne();
-
- // /////////////////////////////////////////////////////////////////////
- // access
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Returns whether the rightmost bit of the bit representation is set. This
- * is needed for data conversion according to 1363.
- *
- * @return true if the rightmost bit of this element is set
- */
- public abstract boolean testRightmostBit();
-
- /**
- * Checks whether the indexed bit of the bit representation is set
- *
- * @param index the index of the bit to test
- * @return <tt>true</tt> if the indexed bit is set
- */
- abstract boolean testBit(int index);
-
- /**
- * Returns the field of this element.
- *
- * @return the field of this element
- */
- public final GF2nField getField()
- {
- return mField;
- }
-
- // /////////////////////////////////////////////////////////////////////
- // arithmetic
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Returns <tt>this</tt> element + 1.
- *
- * @return <tt>this</tt> + 1
- */
- public abstract GF2nElement increase();
-
- /**
- * Increases this element by one.
- */
- public abstract void increaseThis();
-
- /**
- * Compute the difference of this element and <tt>minuend</tt>.
- *
- * @param minuend the minuend
- * @return <tt>this - minuend</tt> (newly created)
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- public final GFElement subtract(GFElement minuend)
- throws RuntimeException
- {
- return add(minuend);
- }
-
- /**
- * Compute the difference of this element and <tt>minuend</tt>,
- * overwriting this element.
- *
- * @param minuend the minuend
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- public final void subtractFromThis(GFElement minuend)
- {
- addToThis(minuend);
- }
-
- /**
- * Returns <tt>this</tt> element to the power of 2.
- *
- * @return <tt>this</tt><sup>2</sup>
- */
- public abstract GF2nElement square();
-
- /**
- * Squares <tt>this</tt> element.
- */
- public abstract void squareThis();
-
- /**
- * Compute the square root of this element and return the result in a new
- * {@link GF2nElement}.
- *
- * @return <tt>this<sup>1/2</sup></tt> (newly created)
- */
- public abstract GF2nElement squareRoot();
-
- /**
- * Compute the square root of this element.
- */
- public abstract void squareRootThis();
-
- /**
- * Performs a basis transformation of this element to the given GF2nField
- * <tt>basis</tt>.
- *
- * @param basis the GF2nField representation to transform this element to
- * @return this element in the representation of <tt>basis</tt>
- * @throws DifferentFieldsException if <tt>this</tt> cannot be converted according to
- * <tt>basis</tt>.
- */
- public final GF2nElement convert(GF2nField basis)
- throws RuntimeException
- {
- return mField.convert(this, basis);
- }
-
- /**
- * Returns the trace of this element.
- *
- * @return the trace of this element
- */
- public abstract int trace();
-
- /**
- * Solves a quadratic equation.<br>
- * Let z<sup>2</sup> + z = <tt>this</tt>. Then this method returns z.
- *
- * @return z with z<sup>2</sup> + z = <tt>this</tt>
- * @throws NoSolutionException if z<sup>2</sup> + z = <tt>this</tt> does not have a
- * solution
- */
- public abstract GF2nElement solveQuadraticEquation()
- throws RuntimeException;
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nField.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nField.java
deleted file mode 100644
index 907afd76..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nField.java
+++ /dev/null
@@ -1,292 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-
-import java.util.Vector;
-
-
-/**
- * This abstract class defines the finite field <i>GF(2<sup>n</sup>)</i>. It
- * holds the extension degree <i>n</i>, the characteristic, the irreducible
- * fieldpolynomial and conversion matrices. GF2nField is implemented by the
- * classes GF2nPolynomialField and GF2nONBField.
- *
- * @see GF2nONBField
- * @see GF2nPolynomialField
- */
-public abstract class GF2nField
-{
-
- /**
- * the degree of this field
- */
- protected int mDegree;
-
- /**
- * the irreducible fieldPolynomial stored in normal order (also for ONB)
- */
- protected GF2Polynomial fieldPolynomial;
-
- /**
- * holds a list of GF2nFields to which elements have been converted and thus
- * a COB-Matrix exists
- */
- protected Vector fields;
-
- /**
- * the COB matrices
- */
- protected Vector matrices;
-
- /**
- * Returns the degree <i>n</i> of this field.
- *
- * @return the degree <i>n</i> of this field
- */
- public final int getDegree()
- {
- return mDegree;
- }
-
- /**
- * Returns the fieldpolynomial as a new Bitstring.
- *
- * @return a copy of the fieldpolynomial as a new Bitstring
- */
- public final GF2Polynomial getFieldPolynomial()
- {
- if (fieldPolynomial == null)
- {
- computeFieldPolynomial();
- }
- return new GF2Polynomial(fieldPolynomial);
- }
-
- /**
- * Decides whether the given object <tt>other</tt> is the same as this
- * field.
- *
- * @param other another object
- * @return (this == other)
- */
- public final boolean equals(Object other)
- {
- if (other == null || !(other instanceof GF2nField))
- {
- return false;
- }
-
- GF2nField otherField = (GF2nField)other;
-
- if (otherField.mDegree != mDegree)
- {
- return false;
- }
- if (!fieldPolynomial.equals(otherField.fieldPolynomial))
- {
- return false;
- }
- if ((this instanceof GF2nPolynomialField)
- && !(otherField instanceof GF2nPolynomialField))
- {
- return false;
- }
- if ((this instanceof GF2nONBField)
- && !(otherField instanceof GF2nONBField))
- {
- return false;
- }
- return true;
- }
-
- /**
- * @return the hash code of this field
- */
- public int hashCode()
- {
- return mDegree + fieldPolynomial.hashCode();
- }
-
- /**
- * Computes a random root from the given irreducible fieldpolynomial
- * according to IEEE 1363 algorithm A.5.6. This cal take very long for big
- * degrees.
- *
- * @param B0FieldPolynomial the fieldpolynomial if the other basis as a Bitstring
- * @return a random root of BOFieldPolynomial in representation according to
- * this field
- * @see "P1363 A.5.6, p103f"
- */
- protected abstract GF2nElement getRandomRoot(GF2Polynomial B0FieldPolynomial);
-
- /**
- * Computes the change-of-basis matrix for basis conversion according to
- * 1363. The result is stored in the lists fields and matrices.
- *
- * @param B1 the GF2nField to convert to
- * @see "P1363 A.7.3, p111ff"
- */
- protected abstract void computeCOBMatrix(GF2nField B1);
-
- /**
- * Computes the fieldpolynomial. This can take a long time for big degrees.
- */
- protected abstract void computeFieldPolynomial();
-
- /**
- * Inverts the given matrix represented as bitstrings.
- *
- * @param matrix the matrix to invert as a Bitstring[]
- * @return matrix^(-1)
- */
- protected final GF2Polynomial[] invertMatrix(GF2Polynomial[] matrix)
- {
- GF2Polynomial[] a = new GF2Polynomial[matrix.length];
- GF2Polynomial[] inv = new GF2Polynomial[matrix.length];
- GF2Polynomial dummy;
- int i, j;
- // initialize a as a copy of matrix and inv as E(inheitsmatrix)
- for (i = 0; i < mDegree; i++)
- {
- try
- {
- a[i] = new GF2Polynomial(matrix[i]);
- inv[i] = new GF2Polynomial(mDegree);
- inv[i].setBit(mDegree - 1 - i);
- }
- catch (RuntimeException BDNEExc)
- {
- BDNEExc.printStackTrace();
- }
- }
- // construct triangle matrix so that for each a[i] the first i bits are
- // zero
- for (i = 0; i < mDegree - 1; i++)
- {
- // find column where bit i is set
- j = i;
- while ((j < mDegree) && !a[j].testBit(mDegree - 1 - i))
- {
- j++;
- }
- if (j >= mDegree)
- {
- throw new RuntimeException(
- "GF2nField.invertMatrix: Matrix cannot be inverted!");
- }
- if (i != j)
- { // swap a[i]/a[j] and inv[i]/inv[j]
- dummy = a[i];
- a[i] = a[j];
- a[j] = dummy;
- dummy = inv[i];
- inv[i] = inv[j];
- inv[j] = dummy;
- }
- for (j = i + 1; j < mDegree; j++)
- { // add column i to all columns>i
- // having their i-th bit set
- if (a[j].testBit(mDegree - 1 - i))
- {
- a[j].addToThis(a[i]);
- inv[j].addToThis(inv[i]);
- }
- }
- }
- // construct Einheitsmatrix from a
- for (i = mDegree - 1; i > 0; i--)
- {
- for (j = i - 1; j >= 0; j--)
- { // eliminate the i-th bit in all
- // columns < i
- if (a[j].testBit(mDegree - 1 - i))
- {
- a[j].addToThis(a[i]);
- inv[j].addToThis(inv[i]);
- }
- }
- }
- return inv;
- }
-
- /**
- * Converts the given element in representation according to this field to a
- * new element in representation according to B1 using the change-of-basis
- * matrix calculated by computeCOBMatrix.
- *
- * @param elem the GF2nElement to convert
- * @param basis the basis to convert <tt>elem</tt> to
- * @return <tt>elem</tt> converted to a new element representation
- * according to <tt>basis</tt>
- * @throws DifferentFieldsException if <tt>elem</tt> cannot be converted according to
- * <tt>basis</tt>.
- * @see GF2nField#computeCOBMatrix
- * @see GF2nField#getRandomRoot
- * @see GF2nPolynomial
- * @see "P1363 A.7 p109ff"
- */
- public final GF2nElement convert(GF2nElement elem, GF2nField basis)
- throws RuntimeException
- {
- if (basis == this)
- {
- return (GF2nElement)elem.clone();
- }
- if (fieldPolynomial.equals(basis.fieldPolynomial))
- {
- return (GF2nElement)elem.clone();
- }
- if (mDegree != basis.mDegree)
- {
- throw new RuntimeException("GF2nField.convert: B1 has a"
- + " different degree and thus cannot be coverted to!");
- }
-
- int i;
- GF2Polynomial[] COBMatrix;
- i = fields.indexOf(basis);
- if (i == -1)
- {
- computeCOBMatrix(basis);
- i = fields.indexOf(basis);
- }
- COBMatrix = (GF2Polynomial[])matrices.elementAt(i);
-
- GF2nElement elemCopy = (GF2nElement)elem.clone();
- if (elemCopy instanceof GF2nONBElement)
- {
- // remember: ONB treats its bits in reverse order
- ((GF2nONBElement)elemCopy).reverseOrder();
- }
- GF2Polynomial bs = new GF2Polynomial(mDegree, elemCopy.toFlexiBigInt());
- bs.expandN(mDegree);
- GF2Polynomial result = new GF2Polynomial(mDegree);
- for (i = 0; i < mDegree; i++)
- {
- if (bs.vectorMult(COBMatrix[i]))
- {
- result.setBit(mDegree - 1 - i);
- }
- }
- if (basis instanceof GF2nPolynomialField)
- {
- return new GF2nPolynomialElement((GF2nPolynomialField)basis,
- result);
- }
- else if (basis instanceof GF2nONBField)
- {
- GF2nONBElement res = new GF2nONBElement((GF2nONBField)basis,
- result.toFlexiBigInt());
- // TODO Remember: ONB treats its Bits in reverse order !!!
- res.reverseOrder();
- return res;
- }
- else
- {
- throw new RuntimeException(
- "GF2nField.convert: B1 must be an instance of "
- + "GF2nPolynomialField or GF2nONBField!");
- }
-
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nONBElement.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nONBElement.java
deleted file mode 100644
index 8b4b473f..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nONBElement.java
+++ /dev/null
@@ -1,1154 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-
-import java.math.BigInteger;
-import java.util.Random;
-
-/**
- * This class implements an element of the finite field <i>GF(2<sup>n </sup>)</i>.
- * It is represented in an optimal normal basis representation and holds the
- * pointer <tt>mField</tt> to its corresponding field.
- *
- * @see GF2nField
- * @see GF2nElement
- */
-public class GF2nONBElement
- extends GF2nElement
-{
-
- // /////////////////////////////////////////////////////////////////////
- // member variables
- // /////////////////////////////////////////////////////////////////////
-
- private static final long[] mBitmask = new long[]{0x0000000000000001L,
- 0x0000000000000002L, 0x0000000000000004L, 0x0000000000000008L,
- 0x0000000000000010L, 0x0000000000000020L, 0x0000000000000040L,
- 0x0000000000000080L, 0x0000000000000100L, 0x0000000000000200L,
- 0x0000000000000400L, 0x0000000000000800L, 0x0000000000001000L,
- 0x0000000000002000L, 0x0000000000004000L, 0x0000000000008000L,
- 0x0000000000010000L, 0x0000000000020000L, 0x0000000000040000L,
- 0x0000000000080000L, 0x0000000000100000L, 0x0000000000200000L,
- 0x0000000000400000L, 0x0000000000800000L, 0x0000000001000000L,
- 0x0000000002000000L, 0x0000000004000000L, 0x0000000008000000L,
- 0x0000000010000000L, 0x0000000020000000L, 0x0000000040000000L,
- 0x0000000080000000L, 0x0000000100000000L, 0x0000000200000000L,
- 0x0000000400000000L, 0x0000000800000000L, 0x0000001000000000L,
- 0x0000002000000000L, 0x0000004000000000L, 0x0000008000000000L,
- 0x0000010000000000L, 0x0000020000000000L, 0x0000040000000000L,
- 0x0000080000000000L, 0x0000100000000000L, 0x0000200000000000L,
- 0x0000400000000000L, 0x0000800000000000L, 0x0001000000000000L,
- 0x0002000000000000L, 0x0004000000000000L, 0x0008000000000000L,
- 0x0010000000000000L, 0x0020000000000000L, 0x0040000000000000L,
- 0x0080000000000000L, 0x0100000000000000L, 0x0200000000000000L,
- 0x0400000000000000L, 0x0800000000000000L, 0x1000000000000000L,
- 0x2000000000000000L, 0x4000000000000000L, 0x8000000000000000L};
-
- private static final long[] mMaxmask = new long[]{0x0000000000000001L,
- 0x0000000000000003L, 0x0000000000000007L, 0x000000000000000FL,
- 0x000000000000001FL, 0x000000000000003FL, 0x000000000000007FL,
- 0x00000000000000FFL, 0x00000000000001FFL, 0x00000000000003FFL,
- 0x00000000000007FFL, 0x0000000000000FFFL, 0x0000000000001FFFL,
- 0x0000000000003FFFL, 0x0000000000007FFFL, 0x000000000000FFFFL,
- 0x000000000001FFFFL, 0x000000000003FFFFL, 0x000000000007FFFFL,
- 0x00000000000FFFFFL, 0x00000000001FFFFFL, 0x00000000003FFFFFL,
- 0x00000000007FFFFFL, 0x0000000000FFFFFFL, 0x0000000001FFFFFFL,
- 0x0000000003FFFFFFL, 0x0000000007FFFFFFL, 0x000000000FFFFFFFL,
- 0x000000001FFFFFFFL, 0x000000003FFFFFFFL, 0x000000007FFFFFFFL,
- 0x00000000FFFFFFFFL, 0x00000001FFFFFFFFL, 0x00000003FFFFFFFFL,
- 0x00000007FFFFFFFFL, 0x0000000FFFFFFFFFL, 0x0000001FFFFFFFFFL,
- 0x0000003FFFFFFFFFL, 0x0000007FFFFFFFFFL, 0x000000FFFFFFFFFFL,
- 0x000001FFFFFFFFFFL, 0x000003FFFFFFFFFFL, 0x000007FFFFFFFFFFL,
- 0x00000FFFFFFFFFFFL, 0x00001FFFFFFFFFFFL, 0x00003FFFFFFFFFFFL,
- 0x00007FFFFFFFFFFFL, 0x0000FFFFFFFFFFFFL, 0x0001FFFFFFFFFFFFL,
- 0x0003FFFFFFFFFFFFL, 0x0007FFFFFFFFFFFFL, 0x000FFFFFFFFFFFFFL,
- 0x001FFFFFFFFFFFFFL, 0x003FFFFFFFFFFFFFL, 0x007FFFFFFFFFFFFFL,
- 0x00FFFFFFFFFFFFFFL, 0x01FFFFFFFFFFFFFFL, 0x03FFFFFFFFFFFFFFL,
- 0x07FFFFFFFFFFFFFFL, 0x0FFFFFFFFFFFFFFFL, 0x1FFFFFFFFFFFFFFFL,
- 0x3FFFFFFFFFFFFFFFL, 0x7FFFFFFFFFFFFFFFL, 0xFFFFFFFFFFFFFFFFL};
-
- // mIBy64[j * 16 + i] = (j * 16 + i)/64
- // i =
- // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- //
- private static final int[] mIBY64 = new int[]{
- // j =
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 8
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 9
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 10
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 11
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 12
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 13
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 14
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 15
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 16
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 17
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 18
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 19
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 20
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 21
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 22
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 // 23
- };
-
- private static final int MAXLONG = 64;
-
- /**
- * holds the lenght of the polynomial with 64 bit sized fields.
- */
- private int mLength;
-
- /**
- * holds the value of mDeg % MAXLONG.
- */
- private int mBit;
-
- /**
- * holds this element in ONB representation.
- */
- private long[] mPol;
-
- // /////////////////////////////////////////////////////////////////////
- // constructors
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Construct a random element over the field <tt>gf2n</tt>, using the
- * specified source of randomness.
- *
- * @param gf2n the field
- * @param rand the source of randomness
- */
- public GF2nONBElement(GF2nONBField gf2n, Random rand)
- {
- mField = gf2n;
- mDegree = mField.getDegree();
- mLength = gf2n.getONBLength();
- mBit = gf2n.getONBBit();
- mPol = new long[mLength];
- if (mLength > 1)
- {
- for (int j = 0; j < mLength - 1; j++)
- {
- mPol[j] = rand.nextLong();
- }
- long last = rand.nextLong();
- mPol[mLength - 1] = last >>> (MAXLONG - mBit);
- }
- else
- {
- mPol[0] = rand.nextLong();
- mPol[0] = mPol[0] >>> (MAXLONG - mBit);
- }
- }
-
- /**
- * Construct a new GF2nONBElement from its encoding.
- *
- * @param gf2n the field
- * @param e the encoded element
- */
- public GF2nONBElement(GF2nONBField gf2n, byte[] e)
- {
- mField = gf2n;
- mDegree = mField.getDegree();
- mLength = gf2n.getONBLength();
- mBit = gf2n.getONBBit();
- mPol = new long[mLength];
- assign(e);
- }
-
- /**
- * Construct the element of the field <tt>gf2n</tt> with the specified
- * value <tt>val</tt>.
- *
- * @param gf2n the field
- * @param val the value represented by a BigInteger
- */
- public GF2nONBElement(GF2nONBField gf2n, BigInteger val)
- {
- mField = gf2n;
- mDegree = mField.getDegree();
- mLength = gf2n.getONBLength();
- mBit = gf2n.getONBBit();
- mPol = new long[mLength];
- assign(val);
- }
-
- /**
- * Construct the element of the field <tt>gf2n</tt> with the specified
- * value <tt>val</tt>.
- *
- * @param gf2n the field
- * @param val the value in ONB representation
- */
- private GF2nONBElement(GF2nONBField gf2n, long[] val)
- {
- mField = gf2n;
- mDegree = mField.getDegree();
- mLength = gf2n.getONBLength();
- mBit = gf2n.getONBBit();
- mPol = val;
- }
-
- // /////////////////////////////////////////////////////////////////////
- // pseudo-constructors
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Copy constructor.
- *
- * @param gf2n the field
- */
- public GF2nONBElement(GF2nONBElement gf2n)
- {
-
- mField = gf2n.mField;
- mDegree = mField.getDegree();
- mLength = ((GF2nONBField)mField).getONBLength();
- mBit = ((GF2nONBField)mField).getONBBit();
- mPol = new long[mLength];
- assign(gf2n.getElement());
- }
-
- /**
- * Create a new GF2nONBElement by cloning this GF2nPolynomialElement.
- *
- * @return a copy of this element
- */
- public Object clone()
- {
- return new GF2nONBElement(this);
- }
-
- /**
- * Create the zero element.
- *
- * @param gf2n the finite field
- * @return the zero element in the given finite field
- */
- public static GF2nONBElement ZERO(GF2nONBField gf2n)
- {
- long[] polynomial = new long[gf2n.getONBLength()];
- return new GF2nONBElement(gf2n, polynomial);
- }
-
- /**
- * Create the one element.
- *
- * @param gf2n the finite field
- * @return the one element in the given finite field
- */
- public static GF2nONBElement ONE(GF2nONBField gf2n)
- {
- int mLength = gf2n.getONBLength();
- long[] polynomial = new long[mLength];
-
- // fill mDegree coefficients with one's
- for (int i = 0; i < mLength - 1; i++)
- {
- polynomial[i] = 0xffffffffffffffffL;
- }
- polynomial[mLength - 1] = mMaxmask[gf2n.getONBBit() - 1];
-
- return new GF2nONBElement(gf2n, polynomial);
- }
-
- // /////////////////////////////////////////////////////////////////////
- // assignments
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * assigns to this element the zero element
- */
- void assignZero()
- {
- mPol = new long[mLength];
- }
-
- /**
- * assigns to this element the one element
- */
- void assignOne()
- {
- // fill mDegree coefficients with one's
- for (int i = 0; i < mLength - 1; i++)
- {
- mPol[i] = 0xffffffffffffffffL;
- }
- mPol[mLength - 1] = mMaxmask[mBit - 1];
- }
-
- /**
- * assigns to this element the value <tt>val</tt>.
- *
- * @param val the value represented by a BigInteger
- */
- private void assign(BigInteger val)
- {
- assign(val.toByteArray());
- }
-
- /**
- * assigns to this element the value <tt>val</tt>.
- *
- * @param val the value in ONB representation
- */
- private void assign(long[] val)
- {
- System.arraycopy(val, 0, mPol, 0, mLength);
- }
-
- /**
- * assigns to this element the value <tt>val</tt>. First: inverting the
- * order of val into reversed[]. That means: reversed[0] = val[length - 1],
- * ..., reversed[reversed.length - 1] = val[0]. Second: mPol[0] = sum{i = 0,
- * ... 7} (val[i]<<(i*8)) .... mPol[1] = sum{i = 8, ... 15} (val[i]<<(i*8))
- *
- * @param val the value in ONB representation
- */
- private void assign(byte[] val)
- {
- int j;
- mPol = new long[mLength];
- for (j = 0; j < val.length; j++)
- {
- mPol[j >>> 3] |= (val[val.length - 1 - j] & 0x00000000000000ffL) << ((j & 0x07) << 3);
- }
- }
-
- // /////////////////////////////////////////////////////////////////
- // comparison
- // /////////////////////////////////////////////////////////////////
-
- /**
- * Checks whether this element is zero.
- *
- * @return <tt>true</tt> if <tt>this</tt> is the zero element
- */
- public boolean isZero()
- {
-
- boolean result = true;
-
- for (int i = 0; i < mLength && result; i++)
- {
- result = result && ((mPol[i] & 0xFFFFFFFFFFFFFFFFL) == 0);
- }
-
- return result;
- }
-
- /**
- * Checks whether this element is one.
- *
- * @return <tt>true</tt> if <tt>this</tt> is the one element
- */
- public boolean isOne()
- {
-
- boolean result = true;
-
- for (int i = 0; i < mLength - 1 && result; i++)
- {
- result = result
- && ((mPol[i] & 0xFFFFFFFFFFFFFFFFL) == 0xFFFFFFFFFFFFFFFFL);
- }
-
- if (result)
- {
- result = result
- && ((mPol[mLength - 1] & mMaxmask[mBit - 1]) == mMaxmask[mBit - 1]);
- }
-
- return result;
- }
-
- /**
- * Compare this element with another object.
- *
- * @param other the other object
- * @return <tt>true</tt> if the two objects are equal, <tt>false</tt>
- * otherwise
- */
- public boolean equals(Object other)
- {
- if (other == null || !(other instanceof GF2nONBElement))
- {
- return false;
- }
-
- GF2nONBElement otherElem = (GF2nONBElement)other;
-
- for (int i = 0; i < mLength; i++)
- {
- if (mPol[i] != otherElem.mPol[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * @return the hash code of this element
- */
- public int hashCode()
- {
- return mPol.hashCode();
- }
-
- // /////////////////////////////////////////////////////////////////////
- // access
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Returns whether the highest bit of the bit representation is set
- *
- * @return true, if the highest bit of mPol is set, false, otherwise
- */
- public boolean testRightmostBit()
- {
- // due to the reverse bit order (compared to 1363) this method returns
- // the value of the leftmost bit
- return (mPol[mLength - 1] & mBitmask[mBit - 1]) != 0L;
- }
-
- /**
- * Checks whether the indexed bit of the bit representation is set. Warning:
- * GF2nONBElement currently stores its bits in reverse order (compared to
- * 1363) !!!
- *
- * @param index the index of the bit to test
- * @return <tt>true</tt> if the indexed bit of mPol is set, <tt>false</tt>
- * otherwise.
- */
- boolean testBit(int index)
- {
- if (index < 0 || index > mDegree)
- {
- return false;
- }
- long test = mPol[index >>> 6] & mBitmask[index & 0x3f];
- return test != 0x0L;
- }
-
- /**
- * @return this element in its ONB representation
- */
- private long[] getElement()
- {
-
- long[] result = new long[mPol.length];
- System.arraycopy(mPol, 0, result, 0, mPol.length);
-
- return result;
- }
-
- /**
- * Returns the ONB representation of this element. The Bit-Order is
- * exchanged (according to 1363)!
- *
- * @return this element in its representation and reverse bit-order
- */
- private long[] getElementReverseOrder()
- {
- long[] result = new long[mPol.length];
- for (int i = 0; i < mDegree; i++)
- {
- if (testBit(mDegree - i - 1))
- {
- result[i >>> 6] |= mBitmask[i & 0x3f];
- }
- }
- return result;
- }
-
- /**
- * Reverses the bit-order in this element(according to 1363). This is a
- * hack!
- */
- void reverseOrder()
- {
- mPol = getElementReverseOrder();
- }
-
- // /////////////////////////////////////////////////////////////////////
- // arithmetic
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Compute the sum of this element and <tt>addend</tt>.
- *
- * @param addend the addend
- * @return <tt>this + other</tt> (newly created)
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- public GFElement add(GFElement addend)
- throws RuntimeException
- {
- GF2nONBElement result = new GF2nONBElement(this);
- result.addToThis(addend);
- return result;
- }
-
- /**
- * Compute <tt>this + addend</tt> (overwrite <tt>this</tt>).
- *
- * @param addend the addend
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- public void addToThis(GFElement addend)
- throws RuntimeException
- {
- if (!(addend instanceof GF2nONBElement))
- {
- throw new RuntimeException();
- }
- if (!mField.equals(((GF2nONBElement)addend).mField))
- {
- throw new RuntimeException();
- }
-
- for (int i = 0; i < mLength; i++)
- {
- mPol[i] ^= ((GF2nONBElement)addend).mPol[i];
- }
- }
-
- /**
- * returns <tt>this</tt> element + 1.
- *
- * @return <tt>this</tt> + 1
- */
- public GF2nElement increase()
- {
- GF2nONBElement result = new GF2nONBElement(this);
- result.increaseThis();
- return result;
- }
-
- /**
- * increases <tt>this</tt> element.
- */
- public void increaseThis()
- {
- addToThis(ONE((GF2nONBField)mField));
- }
-
- /**
- * Compute the product of this element and <tt>factor</tt>.
- *
- * @param factor the factor
- * @return <tt>this * factor</tt> (newly created)
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- public GFElement multiply(GFElement factor)
- throws RuntimeException
- {
- GF2nONBElement result = new GF2nONBElement(this);
- result.multiplyThisBy(factor);
- return result;
- }
-
- /**
- * Compute <tt>this * factor</tt> (overwrite <tt>this</tt>).
- *
- * @param factor the factor
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- public void multiplyThisBy(GFElement factor)
- throws RuntimeException
- {
-
- if (!(factor instanceof GF2nONBElement))
- {
- throw new RuntimeException("The elements have different"
- + " representation: not yet" + " implemented");
- }
- if (!mField.equals(((GF2nONBElement)factor).mField))
- {
- throw new RuntimeException();
- }
-
- if (equals(factor))
- {
- squareThis();
- }
- else
- {
-
- long[] a = mPol;
- long[] b = ((GF2nONBElement)factor).mPol;
- long[] c = new long[mLength];
-
- int[][] m = ((GF2nONBField)mField).mMult;
-
- int degf, degb, s, fielda, fieldb, bita, bitb;
- degf = mLength - 1;
- degb = mBit - 1;
- s = 0;
-
- long TWOTOMAXLONGM1 = mBitmask[MAXLONG - 1];
- long TWOTODEGB = mBitmask[degb];
-
- boolean old, now;
-
- // the product c of a and b (a*b = c) is calculated in mDegree
- // cicles
- // in every cicle one coefficient of c is calculated and stored
- // k indicates the coefficient
- //
- for (int k = 0; k < mDegree; k++)
- {
-
- s = 0;
-
- for (int i = 0; i < mDegree; i++)
- {
-
- // fielda = i / MAXLONG
- //
- fielda = mIBY64[i];
-
- // bita = i % MAXLONG
- //
- bita = i & (MAXLONG - 1);
-
- // fieldb = m[i][0] / MAXLONG
- //
- fieldb = mIBY64[m[i][0]];
-
- // bitb = m[i][0] % MAXLONG
- //
- bitb = m[i][0] & (MAXLONG - 1);
-
- if ((a[fielda] & mBitmask[bita]) != 0)
- {
-
- if ((b[fieldb] & mBitmask[bitb]) != 0)
- {
- s ^= 1;
- }
-
- if (m[i][1] != -1)
- {
-
- // fieldb = m[i][1] / MAXLONG
- //
- fieldb = mIBY64[m[i][1]];
-
- // bitb = m[i][1] % MAXLONG
- //
- bitb = m[i][1] & (MAXLONG - 1);
-
- if ((b[fieldb] & mBitmask[bitb]) != 0)
- {
- s ^= 1;
- }
-
- }
- }
- }
- fielda = mIBY64[k];
- bita = k & (MAXLONG - 1);
-
- if (s != 0)
- {
- c[fielda] ^= mBitmask[bita];
- }
-
- // Circular shift of x and y one bit to the right,
- // respectively.
-
- if (mLength > 1)
- {
-
- // Shift x.
- //
- old = (a[degf] & 1) == 1;
-
- for (int i = degf - 1; i >= 0; i--)
- {
- now = (a[i] & 1) != 0;
-
- a[i] = a[i] >>> 1;
-
- if (old)
- {
- a[i] ^= TWOTOMAXLONGM1;
- }
-
- old = now;
- }
- a[degf] = a[degf] >>> 1;
-
- if (old)
- {
- a[degf] ^= TWOTODEGB;
- }
-
- // Shift y.
- //
- old = (b[degf] & 1) == 1;
-
- for (int i = degf - 1; i >= 0; i--)
- {
- now = (b[i] & 1) != 0;
-
- b[i] = b[i] >>> 1;
-
- if (old)
- {
- b[i] ^= TWOTOMAXLONGM1;
- }
-
- old = now;
- }
-
- b[degf] = b[degf] >>> 1;
-
- if (old)
- {
- b[degf] ^= TWOTODEGB;
- }
- }
- else
- {
- old = (a[0] & 1) == 1;
- a[0] = a[0] >>> 1;
-
- if (old)
- {
- a[0] ^= TWOTODEGB;
- }
-
- old = (b[0] & 1) == 1;
- b[0] = b[0] >>> 1;
-
- if (old)
- {
- b[0] ^= TWOTODEGB;
- }
- }
- }
- assign(c);
- }
- }
-
- /**
- * returns <tt>this</tt> element to the power of 2.
- *
- * @return <tt>this</tt><sup>2</sup>
- */
- public GF2nElement square()
- {
- GF2nONBElement result = new GF2nONBElement(this);
- result.squareThis();
- return result;
- }
-
- /**
- * squares <tt>this</tt> element.
- */
- public void squareThis()
- {
-
- long[] pol = getElement();
-
- int f = mLength - 1;
- int b = mBit - 1;
-
- // Shift the coefficients one bit to the left.
- //
- long TWOTOMAXLONGM1 = mBitmask[MAXLONG - 1];
- boolean old, now;
-
- old = (pol[f] & mBitmask[b]) != 0;
-
- for (int i = 0; i < f; i++)
- {
-
- now = (pol[i] & TWOTOMAXLONGM1) != 0;
-
- pol[i] = pol[i] << 1;
-
- if (old)
- {
- pol[i] ^= 1;
- }
-
- old = now;
- }
- now = (pol[f] & mBitmask[b]) != 0;
-
- pol[f] = pol[f] << 1;
-
- if (old)
- {
- pol[f] ^= 1;
- }
-
- // Set the bit with index mDegree to zero.
- //
- if (now)
- {
- pol[f] ^= mBitmask[b + 1];
- }
-
- assign(pol);
- }
-
- /**
- * Compute the multiplicative inverse of this element.
- *
- * @return <tt>this<sup>-1</sup></tt> (newly created)
- * @throws ArithmeticException if <tt>this</tt> is the zero element.
- */
- public GFElement invert()
- throws ArithmeticException
- {
- GF2nONBElement result = new GF2nONBElement(this);
- result.invertThis();
- return result;
- }
-
- /**
- * Multiplicatively invert of this element (overwrite <tt>this</tt>).
- *
- * @throws ArithmeticException if <tt>this</tt> is the zero element.
- */
- public void invertThis()
- throws ArithmeticException
- {
-
- if (isZero())
- {
- throw new ArithmeticException();
- }
- int r = 31; // mDegree kann nur 31 Bits lang sein!!!
-
- // Bitlaenge von mDegree:
- for (boolean found = false; !found && r >= 0; r--)
- {
-
- if (((mDegree - 1) & mBitmask[r]) != 0)
- {
- found = true;
- }
- }
- r++;
-
- GF2nElement m = ZERO((GF2nONBField)mField);
- GF2nElement n = new GF2nONBElement(this);
-
- int k = 1;
-
- for (int i = r - 1; i >= 0; i--)
- {
- m = (GF2nElement)n.clone();
- for (int j = 1; j <= k; j++)
- {
- m.squareThis();
- }
-
- n.multiplyThisBy(m);
-
- k <<= 1;
- if (((mDegree - 1) & mBitmask[i]) != 0)
- {
- n.squareThis();
-
- n.multiplyThisBy(this);
-
- k++;
- }
- }
- n.squareThis();
- }
-
- /**
- * returns the root of<tt>this</tt> element.
- *
- * @return <tt>this</tt><sup>1/2</sup>
- */
- public GF2nElement squareRoot()
- {
- GF2nONBElement result = new GF2nONBElement(this);
- result.squareRootThis();
- return result;
- }
-
- /**
- * square roots <tt>this</tt> element.
- */
- public void squareRootThis()
- {
-
- long[] pol = getElement();
-
- int f = mLength - 1;
- int b = mBit - 1;
-
- // Shift the coefficients one bit to the right.
- //
- long TWOTOMAXLONGM1 = mBitmask[MAXLONG - 1];
- boolean old, now;
-
- old = (pol[0] & 1) != 0;
-
- for (int i = f; i >= 0; i--)
- {
- now = (pol[i] & 1) != 0;
- pol[i] = pol[i] >>> 1;
-
- if (old)
- {
- if (i == f)
- {
- pol[i] ^= mBitmask[b];
- }
- else
- {
- pol[i] ^= TWOTOMAXLONGM1;
- }
- }
- old = now;
- }
- assign(pol);
- }
-
- /**
- * Returns the trace of this element.
- *
- * @return the trace of this element
- */
- public int trace()
- {
-
- // trace = sum of coefficients
- //
-
- int result = 0;
-
- int max = mLength - 1;
-
- for (int i = 0; i < max; i++)
- {
-
- for (int j = 0; j < MAXLONG; j++)
- {
-
- if ((mPol[i] & mBitmask[j]) != 0)
- {
- result ^= 1;
- }
- }
- }
-
- int b = mBit;
-
- for (int j = 0; j < b; j++)
- {
-
- if ((mPol[max] & mBitmask[j]) != 0)
- {
- result ^= 1;
- }
- }
- return result;
- }
-
- /**
- * Solves a quadratic equation.<br>
- * Let z<sup>2</sup> + z = <tt>this</tt>. Then this method returns z.
- *
- * @return z with z<sup>2</sup> + z = <tt>this</tt>
- * @throws NoSolutionException if z<sup>2</sup> + z = <tt>this</tt> does not have a
- * solution
- */
- public GF2nElement solveQuadraticEquation()
- throws RuntimeException
- {
-
- if (trace() == 1)
- {
- throw new RuntimeException();
- }
-
- long TWOTOMAXLONGM1 = mBitmask[MAXLONG - 1];
- long ZERO = 0L;
- long ONE = 1L;
-
- long[] p = new long[mLength];
- long z = 0L;
- int j = 1;
- for (int i = 0; i < mLength - 1; i++)
- {
-
- for (j = 1; j < MAXLONG; j++)
- {
-
- //
- if (!((((mBitmask[j] & mPol[i]) != ZERO) && ((z & mBitmask[j - 1]) != ZERO)) || (((mPol[i] & mBitmask[j]) == ZERO) && ((z & mBitmask[j - 1]) == ZERO))))
- {
- z ^= mBitmask[j];
- }
- }
- p[i] = z;
-
- if (((TWOTOMAXLONGM1 & z) != ZERO && (ONE & mPol[i + 1]) == ONE)
- || ((TWOTOMAXLONGM1 & z) == ZERO && (ONE & mPol[i + 1]) == ZERO))
- {
- z = ZERO;
- }
- else
- {
- z = ONE;
- }
- }
-
- int b = mDegree & (MAXLONG - 1);
-
- long LASTLONG = mPol[mLength - 1];
-
- for (j = 1; j < b; j++)
- {
- if (!((((mBitmask[j] & LASTLONG) != ZERO) && ((mBitmask[j - 1] & z) != ZERO)) || (((mBitmask[j] & LASTLONG) == ZERO) && ((mBitmask[j - 1] & z) == ZERO))))
- {
- z ^= mBitmask[j];
- }
- }
- p[mLength - 1] = z;
- return new GF2nONBElement((GF2nONBField)mField, p);
- }
-
- // /////////////////////////////////////////////////////////////////
- // conversion
- // /////////////////////////////////////////////////////////////////
-
- /**
- * Returns a String representation of this element.
- *
- * @return String representation of this element with the specified radix
- */
- public String toString()
- {
- return toString(16);
- }
-
- /**
- * Returns a String representation of this element. <tt>radix</tt>
- * specifies the radix of the String representation.<br>
- * NOTE: ONLY <tt>radix = 2</tt> or <tt>radix = 16</tt> IS IMPLEMENTED
- *
- * @param radix specifies the radix of the String representation
- * @return String representation of this element with the specified radix
- */
- public String toString(int radix)
- {
- String s = "";
-
- long[] a = getElement();
- int b = mBit;
-
- if (radix == 2)
- {
-
- for (int j = b - 1; j >= 0; j--)
- {
- if ((a[a.length - 1] & ((long)1 << j)) == 0)
- {
- s += "0";
- }
- else
- {
- s += "1";
- }
- }
-
- for (int i = a.length - 2; i >= 0; i--)
- {
- for (int j = MAXLONG - 1; j >= 0; j--)
- {
- if ((a[i] & mBitmask[j]) == 0)
- {
- s += "0";
- }
- else
- {
- s += "1";
- }
- }
- }
- }
- else if (radix == 16)
- {
- final char[] HEX_CHARS = {'0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
- for (int i = a.length - 1; i >= 0; i--)
- {
- s += HEX_CHARS[(int)(a[i] >>> 60) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 56) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 52) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 48) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 44) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 40) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 36) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 32) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 28) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 24) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 20) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 16) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 12) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 8) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 4) & 0x0f];
- s += HEX_CHARS[(int)(a[i]) & 0x0f];
- s += " ";
- }
- }
- return s;
- }
-
- /**
- * Returns this element as FlexiBigInt. The conversion is <a href =
- * "http://grouper.ieee.org/groups/1363/">P1363</a>-conform.
- *
- * @return this element as BigInteger
- */
- public BigInteger toFlexiBigInt()
- {
- /** @todo this method does not reverse the bit-order as it should!!! */
-
- return new BigInteger(1, toByteArray());
- }
-
- /**
- * Returns this element as byte array. The conversion is <a href =
- * "http://grouper.ieee.org/groups/1363/">P1363</a>-conform.
- *
- * @return this element as byte array
- */
- public byte[] toByteArray()
- {
- /** @todo this method does not reverse the bit-order as it should!!! */
-
- int k = ((mDegree - 1) >> 3) + 1;
- byte[] result = new byte[k];
- int i;
- for (i = 0; i < k; i++)
- {
- result[k - i - 1] = (byte)((mPol[i >>> 3] & (0x00000000000000ffL << ((i & 0x07) << 3))) >>> ((i & 0x07) << 3));
- }
- return result;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nONBField.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nONBField.java
deleted file mode 100644
index 1e4c8b26..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nONBField.java
+++ /dev/null
@@ -1,546 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-
-import java.util.Random;
-import java.util.Vector;
-
-
-/**
- * This class implements the abstract class <tt>GF2nField</tt> for ONB
- * representation. It computes the fieldpolynomial, multiplication matrix and
- * one of its roots mONBRoot, (see for example <a
- * href=http://www2.certicom.com/ecc/intro.htm>Certicoms Whitepapers</a>).
- * GF2nField is used by GF2nONBElement which implements the elements of this
- * field.
- *
- * @see GF2nField
- * @see GF2nONBElement
- */
-public class GF2nONBField
- extends GF2nField
-{
-
- // ///////////////////////////////////////////////////////////////////
- // Hashtable for irreducible normal polynomials //
- // ///////////////////////////////////////////////////////////////////
-
- // i*5 + 0 i*5 + 1 i*5 + 2 i*5 + 3 i*5 + 4
- /*
- * private static int[][] mNB = {{0, 0, 0}, {0, 0, 0}, {1, 0, 0}, {1, 0, 0},
- * {1, 0, 0}, // i = 0 {2, 0, 0}, {1, 0, 0}, {1, 0, 0}, {4, 3, 1}, {1, 0,
- * 0}, // i = 1 {3, 0, 0}, {2, 0, 0}, {3, 0, 0}, {4, 3, 1}, {5, 0, 0}, // i =
- * 2 {1, 0, 0}, {5, 3, 1}, {3, 0, 0}, {3, 0, 0}, {5, 2, 1}, // i = 3 {3, 0,
- * 0}, {2, 0, 0}, {1, 0, 0}, {5, 0, 0}, {4, 3, 1}, // i = 4 {3, 0, 0}, {4,
- * 3, 1}, {5, 2, 1}, {1, 0, 0}, {2, 0, 0}, // i = 5 {1, 0, 0}, {3, 0, 0},
- * {7, 3, 2}, {10, 0, 0}, {7, 0, 0}, // i = 6 {2, 0, 0}, {9, 0, 0}, {6, 4,
- * 1}, {6, 5, 1}, {4, 0, 0}, // i = 7 {5, 4, 3}, {3, 0, 0}, {7, 0, 0}, {6,
- * 4, 3}, {5, 0, 0}, // i = 8 {4, 3, 1}, {1, 0, 0}, {5, 0, 0}, {5, 3, 2},
- * {9, 0, 0}, // i = 9 {4, 3, 2}, {6, 3, 1}, {3, 0, 0}, {6, 2, 1}, {9, 0,
- * 0}, // i = 10 {7, 0, 0}, {7, 4, 2}, {4, 0, 0}, {19, 0, 0}, {7, 4, 2}, //
- * i = 11 {1, 0, 0}, {5, 2, 1}, {29, 0, 0}, {1, 0, 0}, {4, 3, 1}, // i = 12
- * {18, 0, 0}, {3, 0, 0}, {5, 2, 1}, {9, 0, 0}, {6, 5, 2}, // i = 13 {5, 3,
- * 1}, {6, 0, 0}, {10, 9, 3}, {25, 0, 0}, {35, 0, 0}, // i = 14 {6, 3, 1},
- * {21, 0, 0}, {6, 5, 2}, {6, 5, 3}, {9, 0, 0}, // i = 15 {9, 4, 2}, {4, 0,
- * 0}, {8, 3, 1}, {7, 4, 2}, {5, 0, 0}, // i = 16 {8, 2, 1}, {21, 0, 0},
- * {13, 0, 0}, {7, 6, 2}, {38, 0, 0}, // i = 17 {27, 0, 0}, {8, 5, 1}, {21,
- * 0, 0}, {2, 0, 0}, {21, 0, 0}, // i = 18 {11, 0, 0}, {10, 9, 6}, {6, 0,
- * 0}, {11, 0, 0}, {6, 3, 1}, // i = 19 {15, 0, 0}, {7, 6, 1}, {29, 0, 0},
- * {9, 0, 0}, {4, 3, 1}, // i = 20 {4, 0, 0}, {15, 0, 0}, {9, 7, 4}, {17, 0,
- * 0}, {5, 4, 2}, // i = 21 {33, 0, 0}, {10, 0, 0}, {5, 4, 3}, {9, 0, 0},
- * {5, 3, 2}, // i = 22 {8, 7, 5}, {4, 2, 1}, {5, 2, 1}, {33, 0, 0}, {8, 0,
- * 0}, // i = 23 {4, 3, 1}, {18, 0, 0}, {6, 2, 1}, {2, 0, 0}, {19, 0, 0}, //
- * i = 24 {7, 6, 5}, {21, 0, 0}, {1, 0, 0}, {7, 2, 1}, {5, 0, 0}, // i = 25
- * {3, 0, 0}, {8, 3, 2}, {17, 0, 0}, {9, 8, 2}, {57, 0, 0}, // i = 26 {11,
- * 0, 0}, {5, 3, 2}, {21, 0, 0}, {8, 7, 1}, {8, 5, 3}, // i = 27 {15, 0, 0},
- * {10, 4, 1}, {21, 0, 0}, {5, 3, 2}, {7, 4, 2}, // i = 28 {52, 0, 0}, {71,
- * 0, 0}, {14, 0, 0}, {27, 0, 0}, {10, 9, 7}, // i = 29 {53, 0, 0}, {3, 0,
- * 0}, {6, 3, 2}, {1, 0, 0}, {15, 0, 0}, // i = 30 {62, 0, 0}, {9, 0, 0},
- * {6, 5, 2}, {8, 6, 5}, {31, 0, 0}, // i = 31 {5, 3, 2}, {18, 0, 0 }, {27,
- * 0, 0}, {7, 6, 3}, {10, 8, 7}, // i = 32 {9, 8, 3}, {37, 0, 0}, {6, 0, 0},
- * {15, 3, 2}, {34, 0, 0}, // i = 33 {11, 0, 0}, {6, 5, 2}, {1, 0, 0}, {8,
- * 5, 2}, {13, 0, 0}, // i = 34 {6, 0, 0}, {11, 3, 2}, {8, 0, 0}, {31, 0,
- * 0}, {4, 2, 1}, // i = 35 {3, 0, 0}, {7, 6, 1}, {81, 0, 0}, {56, 0, 0},
- * {9, 8, 7}, // i = 36 {24, 0, 0}, {11, 0, 0}, {7, 6, 5}, {6, 5, 2}, {6, 5,
- * 2}, // i = 37 {8, 7, 6}, {9, 0, 0}, {7, 2, 1}, {15, 0, 0}, {87, 0, 0}, //
- * i = 38 {8, 3, 2}, {3, 0, 0}, {9, 4, 2}, {9, 0, 0}, {34, 0, 0}, // i = 39
- * {5, 3, 2}, {14, 0, 0}, {55, 0, 0}, {8, 7, 1}, {27, 0, 0}, // i = 40 {9,
- * 5, 2}, {10, 9, 5}, {43, 0, 0}, {8, 6, 2}, {6, 0, 0}, // i = 41 {7, 0, 0},
- * {11, 10, 8}, {105, 0, 0}, {6, 5, 2}, {73, 0, 0}}; // i = 42
- */
- // /////////////////////////////////////////////////////////////////////
- // member variables
- // /////////////////////////////////////////////////////////////////////
- private static final int MAXLONG = 64;
-
- /**
- * holds the length of the array-representation of degree mDegree.
- */
- private int mLength;
-
- /**
- * holds the number of relevant bits in mONBPol[mLength-1].
- */
- private int mBit;
-
- /**
- * holds the type of mONB
- */
- private int mType;
-
- /**
- * holds the multiplication matrix
- */
- int[][] mMult;
-
- // /////////////////////////////////////////////////////////////////////
- // constructors
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * constructs an instance of the finite field with 2<sup>deg</sup>
- * elements and characteristic 2.
- *
- * @param deg -
- * the extention degree of this field
- * @throws NoSuchBasisException if an ONB-implementation other than type 1 or type 2 is
- * requested.
- */
- public GF2nONBField(int deg)
- throws RuntimeException
- {
- if (deg < 3)
- {
- throw new IllegalArgumentException("k must be at least 3");
- }
-
- mDegree = deg;
- mLength = mDegree / MAXLONG;
- mBit = mDegree & (MAXLONG - 1);
- if (mBit == 0)
- {
- mBit = MAXLONG;
- }
- else
- {
- mLength++;
- }
-
- computeType();
-
- // only ONB-implementations for type 1 and type 2
- //
- if (mType < 3)
- {
- mMult = new int[mDegree][2];
- for (int i = 0; i < mDegree; i++)
- {
- mMult[i][0] = -1;
- mMult[i][1] = -1;
- }
- computeMultMatrix();
- }
- else
- {
- throw new RuntimeException("\nThe type of this field is "
- + mType);
- }
- computeFieldPolynomial();
- fields = new Vector();
- matrices = new Vector();
- }
-
- // /////////////////////////////////////////////////////////////////////
- // access
- // /////////////////////////////////////////////////////////////////////
-
- int getONBLength()
- {
- return mLength;
- }
-
- int getONBBit()
- {
- return mBit;
- }
-
- // /////////////////////////////////////////////////////////////////////
- // arithmetic
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Computes a random root of the given polynomial.
- *
- * @param polynomial a polynomial
- * @return a random root of the polynomial
- * @see "P1363 A.5.6, p103f"
- */
- protected GF2nElement getRandomRoot(GF2Polynomial polynomial)
- {
- // We are in B1!!!
- GF2nPolynomial c;
- GF2nPolynomial ut;
- GF2nElement u;
- GF2nPolynomial h;
- int hDegree;
- // 1. Set g(t) <- f(t)
- GF2nPolynomial g = new GF2nPolynomial(polynomial, this);
- int gDegree = g.getDegree();
- int i;
-
- // 2. while deg(g) > 1
- while (gDegree > 1)
- {
- do
- {
- // 2.1 choose random u (element of) GF(2^m)
- u = new GF2nONBElement(this, new Random());
- ut = new GF2nPolynomial(2, GF2nONBElement.ZERO(this));
- // 2.2 Set c(t) <- ut
- ut.set(1, u);
- c = new GF2nPolynomial(ut);
- // 2.3 For i from 1 to m-1 do
- for (i = 1; i <= mDegree - 1; i++)
- {
- // 2.3.1 c(t) <- (c(t)^2 + ut) mod g(t)
- c = c.multiplyAndReduce(c, g);
- c = c.add(ut);
- }
- // 2.4 set h(t) <- GCD(c(t), g(t))
- h = c.gcd(g);
- // 2.5 if h(t) is constant or deg(g) = deg(h) then go to
- // step 2.1
- hDegree = h.getDegree();
- gDegree = g.getDegree();
- }
- while ((hDegree == 0) || (hDegree == gDegree));
- // 2.6 If 2deg(h) > deg(g) then set g(t) <- g(t)/h(t) ...
- if ((hDegree << 1) > gDegree)
- {
- g = g.quotient(h);
- }
- else
- {
- // ... else g(t) <- h(t)
- g = new GF2nPolynomial(h);
- }
- gDegree = g.getDegree();
- }
- // 3. Output g(0)
- return g.at(0);
-
- }
-
- /**
- * Computes the change-of-basis matrix for basis conversion according to
- * 1363. The result is stored in the lists fields and matrices.
- *
- * @param B1 the GF2nField to convert to
- * @see "P1363 A.7.3, p111ff"
- */
- protected void computeCOBMatrix(GF2nField B1)
- {
- // we are in B0 here!
- if (mDegree != B1.mDegree)
- {
- throw new IllegalArgumentException(
- "GF2nField.computeCOBMatrix: B1 has a "
- + "different degree and thus cannot be coverted to!");
- }
- int i, j;
- GF2nElement[] gamma;
- GF2nElement u;
- GF2Polynomial[] COBMatrix = new GF2Polynomial[mDegree];
- for (i = 0; i < mDegree; i++)
- {
- COBMatrix[i] = new GF2Polynomial(mDegree);
- }
-
- // find Random Root
- do
- {
- // u is in representation according to B1
- u = B1.getRandomRoot(fieldPolynomial);
- }
- while (u.isZero());
-
- gamma = new GF2nPolynomialElement[mDegree];
- // build gamma matrix by squaring
- gamma[0] = (GF2nElement)u.clone();
- for (i = 1; i < mDegree; i++)
- {
- gamma[i] = gamma[i - 1].square();
- }
- // convert horizontal gamma matrix by vertical Bitstrings
- for (i = 0; i < mDegree; i++)
- {
- for (j = 0; j < mDegree; j++)
- {
- if (gamma[i].testBit(j))
- {
- COBMatrix[mDegree - j - 1].setBit(mDegree - i - 1);
- }
- }
- }
-
- fields.addElement(B1);
- matrices.addElement(COBMatrix);
- B1.fields.addElement(this);
- B1.matrices.addElement(invertMatrix(COBMatrix));
- }
-
- /**
- * Computes the field polynomial for a ONB according to IEEE 1363 A.7.2
- * (p110f).
- *
- * @see "P1363 A.7.2, p110f"
- */
- protected void computeFieldPolynomial()
- {
- if (mType == 1)
- {
- fieldPolynomial = new GF2Polynomial(mDegree + 1, "ALL");
- }
- else if (mType == 2)
- {
- // 1. q = 1
- GF2Polynomial q = new GF2Polynomial(mDegree + 1, "ONE");
- // 2. p = t+1
- GF2Polynomial p = new GF2Polynomial(mDegree + 1, "X");
- p.addToThis(q);
- GF2Polynomial r;
- int i;
- // 3. for i = 1 to (m-1) do
- for (i = 1; i < mDegree; i++)
- {
- // r <- q
- r = q;
- // q <- p
- q = p;
- // p = tq+r
- p = q.shiftLeft();
- p.addToThis(r);
- }
- fieldPolynomial = p;
- }
- }
-
- /**
- * Compute the inverse of a matrix <tt>a</tt>.
- *
- * @param a the matrix
- * @return <tt>a<sup>-1</sup></tt>
- */
- int[][] invMatrix(int[][] a)
- {
-
- int[][] A = new int[mDegree][mDegree];
- A = a;
- int[][] inv = new int[mDegree][mDegree];
-
- for (int i = 0; i < mDegree; i++)
- {
- inv[i][i] = 1;
- }
-
- for (int i = 0; i < mDegree; i++)
- {
- for (int j = i; j < mDegree; j++)
- {
- A[mDegree - 1 - i][j] = A[i][i];
- }
- }
- return null;
- }
-
- private void computeType()
- throws RuntimeException
- {
- if ((mDegree & 7) == 0)
- {
- throw new RuntimeException(
- "The extension degree is divisible by 8!");
- }
- // checking for the type
- int s = 0;
- int k = 0;
- mType = 1;
- for (int d = 0; d != 1; mType++)
- {
- s = mType * mDegree + 1;
- if (IntegerFunctions.isPrime(s))
- {
- k = IntegerFunctions.order(2, s);
- d = IntegerFunctions.gcd(mType * mDegree / k, mDegree);
- }
- }
- mType--;
- if (mType == 1)
- {
- s = (mDegree << 1) + 1;
- if (IntegerFunctions.isPrime(s))
- {
- k = IntegerFunctions.order(2, s);
- int d = IntegerFunctions.gcd((mDegree << 1) / k, mDegree);
- if (d == 1)
- {
- mType++;
- }
- }
- }
- }
-
- private void computeMultMatrix()
- {
-
- if ((mType & 7) != 0)
- {
- int p = mType * mDegree + 1;
-
- // compute sequence F[1] ... F[p-1] via A.3.7. of 1363.
- // F[0] will not be filled!
- //
- int[] F = new int[p];
-
- int u;
- if (mType == 1)
- {
- u = 1;
- }
- else if (mType == 2)
- {
- u = p - 1;
- }
- else
- {
- u = elementOfOrder(mType, p);
- }
-
- int w = 1;
- int n;
- for (int j = 0; j < mType; j++)
- {
- n = w;
-
- for (int i = 0; i < mDegree; i++)
- {
- F[n] = i;
- n = (n << 1) % p;
- if (n < 0)
- {
- n += p;
- }
- }
- w = u * w % p;
- if (w < 0)
- {
- w += p;
- }
- }
-
- // building the matrix (mDegree * 2)
- //
- if (mType == 1)
- {
- for (int k = 1; k < p - 1; k++)
- {
- if (mMult[F[k + 1]][0] == -1)
- {
- mMult[F[k + 1]][0] = F[p - k];
- }
- else
- {
- mMult[F[k + 1]][1] = F[p - k];
- }
- }
-
- int m_2 = mDegree >> 1;
- for (int k = 1; k <= m_2; k++)
- {
-
- if (mMult[k - 1][0] == -1)
- {
- mMult[k - 1][0] = m_2 + k - 1;
- }
- else
- {
- mMult[k - 1][1] = m_2 + k - 1;
- }
-
- if (mMult[m_2 + k - 1][0] == -1)
- {
- mMult[m_2 + k - 1][0] = k - 1;
- }
- else
- {
- mMult[m_2 + k - 1][1] = k - 1;
- }
- }
- }
- else if (mType == 2)
- {
- for (int k = 1; k < p - 1; k++)
- {
- if (mMult[F[k + 1]][0] == -1)
- {
- mMult[F[k + 1]][0] = F[p - k];
- }
- else
- {
- mMult[F[k + 1]][1] = F[p - k];
- }
- }
- }
- else
- {
- throw new RuntimeException("only type 1 or type 2 implemented");
- }
- }
- else
- {
- throw new RuntimeException("bisher nur fuer Gausssche Normalbasen"
- + " implementiert");
- }
- }
-
- private int elementOfOrder(int k, int p)
- {
- Random random = new Random();
- int m = 0;
- while (m == 0)
- {
- m = random.nextInt();
- m %= p - 1;
- if (m < 0)
- {
- m += p - 1;
- }
- }
-
- int l = IntegerFunctions.order(m, p);
-
- while (l % k != 0 || l == 0)
- {
- while (m == 0)
- {
- m = random.nextInt();
- m %= p - 1;
- if (m < 0)
- {
- m += p - 1;
- }
- }
- l = IntegerFunctions.order(m, p);
- }
- int r = m;
-
- l = k / l;
-
- for (int i = 2; i <= l; i++)
- {
- r *= m;
- }
-
- return r;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomial.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomial.java
deleted file mode 100644
index f122be03..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomial.java
+++ /dev/null
@@ -1,587 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-
-/**
- * This class implements polynomials over GF2nElements.
- *
- * @see GF2nElement
- */
-
-public class GF2nPolynomial
-{
-
- private GF2nElement[] coeff; // keeps the coefficients of this polynomial
-
- private int size; // the size of this polynomial
-
- /**
- * Creates a new PolynomialGF2n of size <i>deg</i> and elem as
- * coefficients.
- *
- * @param deg -
- * the maximum degree + 1
- * @param elem -
- * a GF2nElement
- */
- public GF2nPolynomial(int deg, GF2nElement elem)
- {
- size = deg;
- coeff = new GF2nElement[size];
- for (int i = 0; i < size; i++)
- {
- coeff[i] = (GF2nElement)elem.clone();
- }
- }
-
- /**
- * Creates a new PolynomialGF2n of size <i>deg</i>.
- *
- * @param deg the maximum degree + 1
- */
- private GF2nPolynomial(int deg)
- {
- size = deg;
- coeff = new GF2nElement[size];
- }
-
- /**
- * Creates a new PolynomialGF2n by cloning the given PolynomialGF2n <i>a</i>.
- *
- * @param a the PolynomialGF2n to clone
- */
- public GF2nPolynomial(GF2nPolynomial a)
- {
- int i;
- coeff = new GF2nElement[a.size];
- size = a.size;
- for (i = 0; i < size; i++)
- {
- coeff[i] = (GF2nElement)a.coeff[i].clone();
- }
- }
-
- /**
- * Creates a new PolynomialGF2n from the given Bitstring <i>polynomial</i>
- * over the GF2nField <i>B1</i>.
- *
- * @param polynomial the Bitstring to use
- * @param B1 the field
- */
- public GF2nPolynomial(GF2Polynomial polynomial, GF2nField B1)
- {
- size = B1.getDegree() + 1;
- coeff = new GF2nElement[size];
- int i;
- if (B1 instanceof GF2nONBField)
- {
- for (i = 0; i < size; i++)
- {
- if (polynomial.testBit(i))
- {
- coeff[i] = GF2nONBElement.ONE((GF2nONBField)B1);
- }
- else
- {
- coeff[i] = GF2nONBElement.ZERO((GF2nONBField)B1);
- }
- }
- }
- else if (B1 instanceof GF2nPolynomialField)
- {
- for (i = 0; i < size; i++)
- {
- if (polynomial.testBit(i))
- {
- coeff[i] = GF2nPolynomialElement
- .ONE((GF2nPolynomialField)B1);
- }
- else
- {
- coeff[i] = GF2nPolynomialElement
- .ZERO((GF2nPolynomialField)B1);
- }
- }
- }
- else
- {
- throw new IllegalArgumentException(
- "PolynomialGF2n(Bitstring, GF2nField): B1 must be "
- + "an instance of GF2nONBField or GF2nPolynomialField!");
- }
- }
-
- public final void assignZeroToElements()
- {
- int i;
- for (i = 0; i < size; i++)
- {
- coeff[i].assignZero();
- }
- }
-
- /**
- * Returns the size (=maximum degree + 1) of this PolynomialGF2n. This is
- * not the degree, use getDegree instead.
- *
- * @return the size (=maximum degree + 1) of this PolynomialGF2n.
- */
- public final int size()
- {
- return size;
- }
-
- /**
- * Returns the degree of this PolynomialGF2n.
- *
- * @return the degree of this PolynomialGF2n.
- */
- public final int getDegree()
- {
- int i;
- for (i = size - 1; i >= 0; i--)
- {
- if (!coeff[i].isZero())
- {
- return i;
- }
- }
- return -1;
- }
-
- /**
- * Enlarges the size of this PolynomialGF2n to <i>k</i> + 1.
- *
- * @param k the new maximum degree
- */
- public final void enlarge(int k)
- {
- if (k <= size)
- {
- return;
- }
- int i;
- GF2nElement[] res = new GF2nElement[k];
- System.arraycopy(coeff, 0, res, 0, size);
- GF2nField f = coeff[0].getField();
- if (coeff[0] instanceof GF2nPolynomialElement)
- {
- for (i = size; i < k; i++)
- {
- res[i] = GF2nPolynomialElement.ZERO((GF2nPolynomialField)f);
- }
- }
- else if (coeff[0] instanceof GF2nONBElement)
- {
- for (i = size; i < k; i++)
- {
- res[i] = GF2nONBElement.ZERO((GF2nONBField)f);
- }
- }
- size = k;
- coeff = res;
- }
-
- public final void shrink()
- {
- int i = size - 1;
- while (coeff[i].isZero() && (i > 0))
- {
- i--;
- }
- i++;
- if (i < size)
- {
- GF2nElement[] res = new GF2nElement[i];
- System.arraycopy(coeff, 0, res, 0, i);
- coeff = res;
- size = i;
- }
- }
-
- /**
- * Sets the coefficient at <i>index</i> to <i>elem</i>.
- *
- * @param index the index
- * @param elem the GF2nElement to store as coefficient <i>index</i>
- */
- public final void set(int index, GF2nElement elem)
- {
- if (!(elem instanceof GF2nPolynomialElement)
- && !(elem instanceof GF2nONBElement))
- {
- throw new IllegalArgumentException(
- "PolynomialGF2n.set f must be an "
- + "instance of either GF2nPolynomialElement or GF2nONBElement!");
- }
- coeff[index] = (GF2nElement)elem.clone();
- }
-
- /**
- * Returns the coefficient at <i>index</i>.
- *
- * @param index the index
- * @return the GF2nElement stored as coefficient <i>index</i>
- */
- public final GF2nElement at(int index)
- {
- return coeff[index];
- }
-
- /**
- * Returns true if all coefficients equal zero.
- *
- * @return true if all coefficients equal zero.
- */
- public final boolean isZero()
- {
- int i;
- for (i = 0; i < size; i++)
- {
- if (coeff[i] != null)
- {
- if (!coeff[i].isZero())
- {
- return false;
- }
- }
- }
- return true;
- }
-
- public final boolean equals(Object other)
- {
- if (other == null || !(other instanceof GF2nPolynomial))
- {
- return false;
- }
-
- GF2nPolynomial otherPol = (GF2nPolynomial)other;
-
- if (getDegree() != otherPol.getDegree())
- {
- return false;
- }
- int i;
- for (i = 0; i < size; i++)
- {
- if (!coeff[i].equals(otherPol.coeff[i]))
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * @return the hash code of this polynomial
- */
- public int hashCode()
- {
- return getDegree() + coeff.hashCode();
- }
-
- /**
- * Adds the PolynomialGF2n <tt>b</tt> to <tt>this</tt> and returns the
- * result in a new <tt>PolynomialGF2n</tt>.
- *
- * @param b -
- * the <tt>PolynomialGF2n</tt> to add
- * @return <tt>this + b</tt>
- * @throws DifferentFieldsException if <tt>this</tt> and <tt>b</tt> are not defined over
- * the same field.
- */
- public final GF2nPolynomial add(GF2nPolynomial b)
- throws RuntimeException
- {
- GF2nPolynomial result;
- if (size() >= b.size())
- {
- result = new GF2nPolynomial(size());
- int i;
- for (i = 0; i < b.size(); i++)
- {
- result.coeff[i] = (GF2nElement)coeff[i].add(b.coeff[i]);
- }
- for (; i < size(); i++)
- {
- result.coeff[i] = coeff[i];
- }
- }
- else
- {
- result = new GF2nPolynomial(b.size());
- int i;
- for (i = 0; i < size(); i++)
- {
- result.coeff[i] = (GF2nElement)coeff[i].add(b.coeff[i]);
- }
- for (; i < b.size(); i++)
- {
- result.coeff[i] = b.coeff[i];
- }
- }
- return result;
- }
-
- /**
- * Multiplies the scalar <i>s</i> to each coefficient of this
- * PolynomialGF2n and returns the result in a new PolynomialGF2n.
- *
- * @param s the scalar to multiply
- * @return <i>this</i> x <i>s</i>
- * @throws DifferentFieldsException if <tt>this</tt> and <tt>s</tt> are not defined over
- * the same field.
- */
- public final GF2nPolynomial scalarMultiply(GF2nElement s)
- throws RuntimeException
- {
- GF2nPolynomial result = new GF2nPolynomial(size());
- int i;
- for (i = 0; i < size(); i++)
- {
- result.coeff[i] = (GF2nElement)coeff[i].multiply(s); // result[i]
- // =
- // a[i]*s
- }
- return result;
- }
-
- /**
- * Multiplies <i>this</i> by <i>b</i> and returns the result in a new
- * PolynomialGF2n.
- *
- * @param b the PolynomialGF2n to multiply
- * @return <i>this</i> * <i>b</i>
- * @throws DifferentFieldsException if <tt>this</tt> and <tt>b</tt> are not defined over
- * the same field.
- */
- public final GF2nPolynomial multiply(GF2nPolynomial b)
- throws RuntimeException
- {
- int i, j;
- int aDegree = size();
- int bDegree = b.size();
- if (aDegree != bDegree)
- {
- throw new IllegalArgumentException(
- "PolynomialGF2n.multiply: this and b must "
- + "have the same size!");
- }
- GF2nPolynomial result = new GF2nPolynomial((aDegree << 1) - 1);
- for (i = 0; i < size(); i++)
- {
- for (j = 0; j < b.size(); j++)
- {
- if (result.coeff[i + j] == null)
- {
- result.coeff[i + j] = (GF2nElement)coeff[i]
- .multiply(b.coeff[j]);
- }
- else
- {
- result.coeff[i + j] = (GF2nElement)result.coeff[i + j]
- .add(coeff[i].multiply(b.coeff[j]));
- }
- }
- }
- return result;
- }
-
- /**
- * Multiplies <i>this</i> by <i>b</i>, reduces the result by <i>g</i> and
- * returns it in a new PolynomialGF2n.
- *
- * @param b the PolynomialGF2n to multiply
- * @param g the modul
- * @return <i>this</i> * <i>b</i> mod <i>g</i>
- * @throws DifferentFieldsException if <tt>this</tt>, <tt>b</tt> and <tt>g</tt> are
- * not all defined over the same field.
- */
- public final GF2nPolynomial multiplyAndReduce(GF2nPolynomial b,
- GF2nPolynomial g)
- throws RuntimeException,
- ArithmeticException
- {
- return multiply(b).reduce(g);
- }
-
- /**
- * Reduces <i>this</i> by <i>g</i> and returns the result in a new
- * PolynomialGF2n.
- *
- * @param g -
- * the modulus
- * @return <i>this</i> % <i>g</i>
- * @throws DifferentFieldsException if <tt>this</tt> and <tt>g</tt> are not defined over
- * the same field.
- */
- public final GF2nPolynomial reduce(GF2nPolynomial g)
- throws RuntimeException, ArithmeticException
- {
- return remainder(g); // return this % g
- }
-
- /**
- * Shifts left <i>this</i> by <i>amount</i> and stores the result in
- * <i>this</i> PolynomialGF2n.
- *
- * @param amount the amount to shift the coefficients
- */
- public final void shiftThisLeft(int amount)
- {
- if (amount > 0)
- {
- int i;
- int oldSize = size;
- GF2nField f = coeff[0].getField();
- enlarge(size + amount);
- for (i = oldSize - 1; i >= 0; i--)
- {
- coeff[i + amount] = coeff[i];
- }
- if (coeff[0] instanceof GF2nPolynomialElement)
- {
- for (i = amount - 1; i >= 0; i--)
- {
- coeff[i] = GF2nPolynomialElement
- .ZERO((GF2nPolynomialField)f);
- }
- }
- else if (coeff[0] instanceof GF2nONBElement)
- {
- for (i = amount - 1; i >= 0; i--)
- {
- coeff[i] = GF2nONBElement.ZERO((GF2nONBField)f);
- }
- }
- }
- }
-
- public final GF2nPolynomial shiftLeft(int amount)
- {
- if (amount <= 0)
- {
- return new GF2nPolynomial(this);
- }
- GF2nPolynomial result = new GF2nPolynomial(size + amount, coeff[0]);
- result.assignZeroToElements();
- for (int i = 0; i < size; i++)
- {
- result.coeff[i + amount] = coeff[i];
- }
- return result;
- }
-
- /**
- * Divides <i>this</i> by <i>b</i> and stores the result in a new
- * PolynomialGF2n[2], quotient in result[0] and remainder in result[1].
- *
- * @param b the divisor
- * @return the quotient and remainder of <i>this</i> / <i>b</i>
- * @throws DifferentFieldsException if <tt>this</tt> and <tt>b</tt> are not defined over
- * the same field.
- */
- public final GF2nPolynomial[] divide(GF2nPolynomial b)
- throws RuntimeException, ArithmeticException
- {
- GF2nPolynomial[] result = new GF2nPolynomial[2];
- GF2nPolynomial a = new GF2nPolynomial(this);
- a.shrink();
- GF2nPolynomial shift;
- GF2nElement factor;
- int bDegree = b.getDegree();
- GF2nElement inv = (GF2nElement)b.coeff[bDegree].invert();
- if (a.getDegree() < bDegree)
- {
- result[0] = new GF2nPolynomial(this);
- result[0].assignZeroToElements();
- result[0].shrink();
- result[1] = new GF2nPolynomial(this);
- result[1].shrink();
- return result;
- }
- result[0] = new GF2nPolynomial(this);
- result[0].assignZeroToElements();
- int i = a.getDegree() - bDegree;
- while (i >= 0)
- {
- factor = (GF2nElement)a.coeff[a.getDegree()].multiply(inv);
- shift = b.scalarMultiply(factor);
- shift.shiftThisLeft(i);
- a = a.add(shift);
- a.shrink();
- result[0].coeff[i] = (GF2nElement)factor.clone();
- i = a.getDegree() - bDegree;
- }
- result[1] = a;
- result[0].shrink();
- return result;
- }
-
- /**
- * Divides <i>this</i> by <i>b</i> and stores the remainder in a new
- * PolynomialGF2n.
- *
- * @param b the divisor
- * @return the remainder <i>this</i> % <i>b</i>
- * @throws DifferentFieldsException if <tt>this</tt> and <tt>b</tt> are not defined over
- * the same field.
- */
- public final GF2nPolynomial remainder(GF2nPolynomial b)
- throws RuntimeException, ArithmeticException
- {
- GF2nPolynomial[] result = new GF2nPolynomial[2];
- result = divide(b);
- return result[1];
- }
-
- /**
- * Divides <i>this</i> by <i>b</i> and stores the quotient in a new
- * PolynomialGF2n.
- *
- * @param b the divisor
- * @return the quotient <i>this</i> / <i>b</i>
- * @throws DifferentFieldsException if <tt>this</tt> and <tt>b</tt> are not defined over
- * the same field.
- */
- public final GF2nPolynomial quotient(GF2nPolynomial b)
- throws RuntimeException, ArithmeticException
- {
- GF2nPolynomial[] result = new GF2nPolynomial[2];
- result = divide(b);
- return result[0];
- }
-
- /**
- * Computes the greatest common divisor of <i>this</i> and <i>g</i> and
- * returns the result in a new PolynomialGF2n.
- *
- * @param g -
- * a GF2nPolynomial
- * @return gcd(<i>this</i>, <i>g</i>)
- * @throws DifferentFieldsException if the coefficients of <i>this</i> and <i>g</i> use
- * different fields
- * @throws ArithmeticException if coefficients are zero.
- */
- public final GF2nPolynomial gcd(GF2nPolynomial g)
- throws RuntimeException, ArithmeticException
- {
- GF2nPolynomial a = new GF2nPolynomial(this);
- GF2nPolynomial b = new GF2nPolynomial(g);
- a.shrink();
- b.shrink();
- GF2nPolynomial c;
- GF2nPolynomial result;
- GF2nElement alpha;
- while (!b.isZero())
- {
- c = a.remainder(b);
- a = b;
- b = c;
- }
- alpha = a.coeff[a.getDegree()];
- result = a.scalarMultiply((GF2nElement)alpha.invert());
- return result;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomialElement.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomialElement.java
deleted file mode 100644
index f1753653..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomialElement.java
+++ /dev/null
@@ -1,1021 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-
-import java.math.BigInteger;
-import java.util.Random;
-
-
-/**
- * This class implements elements of finite binary fields <i>GF(2<sup>n</sup>)</i>
- * using polynomial representation. For more information on the arithmetic see
- * for example IEEE Standard 1363 or <a
- * href=http://www.certicom.com/research/online.html> Certicom online-tutorial</a>.
- *
- * @see "GF2nField"
- * @see GF2nPolynomialField
- * @see GF2nONBElement
- * @see GF2Polynomial
- */
-public class GF2nPolynomialElement
- extends GF2nElement
-{
-
- // pre-computed Bitmask for fast masking, bitMask[a]=0x1 << a
- private static final int[] bitMask = {0x00000001, 0x00000002, 0x00000004,
- 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080,
- 0x00000100, 0x00000200, 0x00000400, 0x00000800, 0x00001000,
- 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000,
- 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000,
- 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000,
- 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x00000000};
-
- // the used GF2Polynomial which stores the coefficients
- private GF2Polynomial polynomial;
-
- /**
- * Create a new random GF2nPolynomialElement using the given field and
- * source of randomness.
- *
- * @param f the GF2nField to use
- * @param rand the source of randomness
- */
- public GF2nPolynomialElement(GF2nPolynomialField f, Random rand)
- {
- mField = f;
- mDegree = mField.getDegree();
- polynomial = new GF2Polynomial(mDegree);
- randomize(rand);
- }
-
- /**
- * Creates a new GF2nPolynomialElement using the given field and Bitstring.
- *
- * @param f the GF2nPolynomialField to use
- * @param bs the desired value as Bitstring
- */
- public GF2nPolynomialElement(GF2nPolynomialField f, GF2Polynomial bs)
- {
- mField = f;
- mDegree = mField.getDegree();
- polynomial = new GF2Polynomial(bs);
- polynomial.expandN(mDegree);
- }
-
- /**
- * Creates a new GF2nPolynomialElement using the given field <i>f</i> and
- * byte[] <i>os</i> as value. The conversion is done according to 1363.
- *
- * @param f the GF2nField to use
- * @param os the octet string to assign to this GF2nPolynomialElement
- * @see "P1363 5.5.5 p23, OS2FEP/OS2BSP"
- */
- public GF2nPolynomialElement(GF2nPolynomialField f, byte[] os)
- {
- mField = f;
- mDegree = mField.getDegree();
- polynomial = new GF2Polynomial(mDegree, os);
- polynomial.expandN(mDegree);
- }
-
- /**
- * Creates a new GF2nPolynomialElement using the given field <i>f</i> and
- * int[] <i>is</i> as value.
- *
- * @param f the GF2nField to use
- * @param is the integer string to assign to this GF2nPolynomialElement
- */
- public GF2nPolynomialElement(GF2nPolynomialField f, int[] is)
- {
- mField = f;
- mDegree = mField.getDegree();
- polynomial = new GF2Polynomial(mDegree, is);
- polynomial.expandN(f.mDegree);
- }
-
- /**
- * Creates a new GF2nPolynomialElement by cloning the given
- * GF2nPolynomialElement <i>b</i>.
- *
- * @param other the GF2nPolynomialElement to clone
- */
- public GF2nPolynomialElement(GF2nPolynomialElement other)
- {
- mField = other.mField;
- mDegree = other.mDegree;
- polynomial = new GF2Polynomial(other.polynomial);
- }
-
- // /////////////////////////////////////////////////////////////////////
- // pseudo-constructors
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Creates a new GF2nPolynomialElement by cloning this
- * GF2nPolynomialElement.
- *
- * @return a copy of this element
- */
- public Object clone()
- {
- return new GF2nPolynomialElement(this);
- }
-
- // /////////////////////////////////////////////////////////////////////
- // assignments
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Assigns the value 'zero' to this Polynomial.
- */
- void assignZero()
- {
- polynomial.assignZero();
- }
-
- /**
- * Create the zero element.
- *
- * @param f the finite field
- * @return the zero element in the given finite field
- */
- public static GF2nPolynomialElement ZERO(GF2nPolynomialField f)
- {
- GF2Polynomial polynomial = new GF2Polynomial(f.getDegree());
- return new GF2nPolynomialElement(f, polynomial);
- }
-
- /**
- * Create the one element.
- *
- * @param f the finite field
- * @return the one element in the given finite field
- */
- public static GF2nPolynomialElement ONE(GF2nPolynomialField f)
- {
- GF2Polynomial polynomial = new GF2Polynomial(f.getDegree(),
- new int[]{1});
- return new GF2nPolynomialElement(f, polynomial);
- }
-
- /**
- * Assigns the value 'one' to this Polynomial.
- */
- void assignOne()
- {
- polynomial.assignOne();
- }
-
- /**
- * Assign a random value to this GF2nPolynomialElement using the specified
- * source of randomness.
- *
- * @param rand the source of randomness
- */
- private void randomize(Random rand)
- {
- polynomial.expandN(mDegree);
- polynomial.randomize(rand);
- }
-
- // /////////////////////////////////////////////////////////////////////
- // comparison
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Checks whether this element is zero.
- *
- * @return <tt>true</tt> if <tt>this</tt> is the zero element
- */
- public boolean isZero()
- {
- return polynomial.isZero();
- }
-
- /**
- * Tests if the GF2nPolynomialElement has 'one' as value.
- *
- * @return true if <i>this</i> equals one (this == 1)
- */
- public boolean isOne()
- {
- return polynomial.isOne();
- }
-
- /**
- * Compare this element with another object.
- *
- * @param other the other object
- * @return <tt>true</tt> if the two objects are equal, <tt>false</tt>
- * otherwise
- */
- public boolean equals(Object other)
- {
- if (other == null || !(other instanceof GF2nPolynomialElement))
- {
- return false;
- }
- GF2nPolynomialElement otherElem = (GF2nPolynomialElement)other;
-
- if (mField != otherElem.mField)
- {
- if (!mField.getFieldPolynomial().equals(
- otherElem.mField.getFieldPolynomial()))
- {
- return false;
- }
- }
-
- return polynomial.equals(otherElem.polynomial);
- }
-
- /**
- * @return the hash code of this element
- */
- public int hashCode()
- {
- return mField.hashCode() + polynomial.hashCode();
- }
-
- // /////////////////////////////////////////////////////////////////////
- // access
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Returns the value of this GF2nPolynomialElement in a new Bitstring.
- *
- * @return the value of this GF2nPolynomialElement in a new Bitstring
- */
- private GF2Polynomial getGF2Polynomial()
- {
- return new GF2Polynomial(polynomial);
- }
-
- /**
- * Checks whether the indexed bit of the bit representation is set.
- *
- * @param index the index of the bit to test
- * @return <tt>true</tt> if the indexed bit is set
- */
- boolean testBit(int index)
- {
- return polynomial.testBit(index);
- }
-
- /**
- * Returns whether the rightmost bit of the bit representation is set. This
- * is needed for data conversion according to 1363.
- *
- * @return true if the rightmost bit of this element is set
- */
- public boolean testRightmostBit()
- {
- return polynomial.testBit(0);
- }
-
- /**
- * Compute the sum of this element and <tt>addend</tt>.
- *
- * @param addend the addend
- * @return <tt>this + other</tt> (newly created)
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- public GFElement add(GFElement addend)
- throws RuntimeException
- {
- GF2nPolynomialElement result = new GF2nPolynomialElement(this);
- result.addToThis(addend);
- return result;
- }
-
- /**
- * Compute <tt>this + addend</tt> (overwrite <tt>this</tt>).
- *
- * @param addend the addend
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- public void addToThis(GFElement addend)
- throws RuntimeException
- {
- if (!(addend instanceof GF2nPolynomialElement))
- {
- throw new RuntimeException();
- }
- if (!mField.equals(((GF2nPolynomialElement)addend).mField))
- {
- throw new RuntimeException();
- }
- polynomial.addToThis(((GF2nPolynomialElement)addend).polynomial);
- }
-
- /**
- * Returns <tt>this</tt> element + 'one".
- *
- * @return <tt>this</tt> + 'one'
- */
- public GF2nElement increase()
- {
- GF2nPolynomialElement result = new GF2nPolynomialElement(this);
- result.increaseThis();
- return result;
- }
-
- /**
- * Increases this element by 'one'.
- */
- public void increaseThis()
- {
- polynomial.increaseThis();
- }
-
- /**
- * Compute the product of this element and <tt>factor</tt>.
- *
- * @param factor the factor
- * @return <tt>this * factor</tt> (newly created)
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- public GFElement multiply(GFElement factor)
- throws RuntimeException
- {
- GF2nPolynomialElement result = new GF2nPolynomialElement(this);
- result.multiplyThisBy(factor);
- return result;
- }
-
- /**
- * Compute <tt>this * factor</tt> (overwrite <tt>this</tt>).
- *
- * @param factor the factor
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- public void multiplyThisBy(GFElement factor)
- throws RuntimeException
- {
- if (!(factor instanceof GF2nPolynomialElement))
- {
- throw new RuntimeException();
- }
- if (!mField.equals(((GF2nPolynomialElement)factor).mField))
- {
- throw new RuntimeException();
- }
- if (equals(factor))
- {
- squareThis();
- return;
- }
- polynomial = polynomial
- .multiply(((GF2nPolynomialElement)factor).polynomial);
- reduceThis();
- }
-
- /**
- * Compute the multiplicative inverse of this element.
- *
- * @return <tt>this<sup>-1</sup></tt> (newly created)
- * @throws ArithmeticException if <tt>this</tt> is the zero element.
- * @see GF2nPolynomialElement#invertMAIA
- * @see GF2nPolynomialElement#invertEEA
- * @see GF2nPolynomialElement#invertSquare
- */
- public GFElement invert()
- throws ArithmeticException
- {
- return invertMAIA();
- }
-
- /**
- * Calculates the multiplicative inverse of <i>this</i> and returns the
- * result in a new GF2nPolynomialElement.
- *
- * @return <i>this</i>^(-1)
- * @throws ArithmeticException if <i>this</i> equals zero
- */
- public GF2nPolynomialElement invertEEA()
- throws ArithmeticException
- {
- if (isZero())
- {
- throw new ArithmeticException();
- }
- GF2Polynomial b = new GF2Polynomial(mDegree + 32, "ONE");
- b.reduceN();
- GF2Polynomial c = new GF2Polynomial(mDegree + 32);
- c.reduceN();
- GF2Polynomial u = getGF2Polynomial();
- GF2Polynomial v = mField.getFieldPolynomial();
- GF2Polynomial h;
- int j;
- u.reduceN();
- while (!u.isOne())
- {
- u.reduceN();
- v.reduceN();
- j = u.getLength() - v.getLength();
- if (j < 0)
- {
- h = u;
- u = v;
- v = h;
- h = b;
- b = c;
- c = h;
- j = -j;
- c.reduceN(); // this increases the performance
- }
- u.shiftLeftAddThis(v, j);
- b.shiftLeftAddThis(c, j);
- }
- b.reduceN();
- return new GF2nPolynomialElement((GF2nPolynomialField)mField, b);
- }
-
- /**
- * Calculates the multiplicative inverse of <i>this</i> and returns the
- * result in a new GF2nPolynomialElement.
- *
- * @return <i>this</i>^(-1)
- * @throws ArithmeticException if <i>this</i> equals zero
- */
- public GF2nPolynomialElement invertSquare()
- throws ArithmeticException
- {
- GF2nPolynomialElement n;
- GF2nPolynomialElement u;
- int i, j, k, b;
-
- if (isZero())
- {
- throw new ArithmeticException();
- }
- // b = (n-1)
- b = mField.getDegree() - 1;
- // n = a
- n = new GF2nPolynomialElement(this);
- n.polynomial.expandN((mDegree << 1) + 32); // increase performance
- n.polynomial.reduceN();
- // k = 1
- k = 1;
-
- // for i = (r-1) downto 0 do, r=bitlength(b)
- for (i = IntegerFunctions.floorLog(b) - 1; i >= 0; i--)
- {
- // u = n
- u = new GF2nPolynomialElement(n);
- // for j = 1 to k do
- for (j = 1; j <= k; j++)
- {
- // u = u^2
- u.squareThisPreCalc();
- }
- // n = nu
- n.multiplyThisBy(u);
- // k = 2k
- k <<= 1;
- // if b(i)==1
- if ((b & bitMask[i]) != 0)
- {
- // n = n^2 * b
- n.squareThisPreCalc();
- n.multiplyThisBy(this);
- // k = k+1
- k += 1;
- }
- }
-
- // outpur n^2
- n.squareThisPreCalc();
- return n;
- }
-
- /**
- * Calculates the multiplicative inverse of <i>this</i> using the modified
- * almost inverse algorithm and returns the result in a new
- * GF2nPolynomialElement.
- *
- * @return <i>this</i>^(-1)
- * @throws ArithmeticException if <i>this</i> equals zero
- */
- public GF2nPolynomialElement invertMAIA()
- throws ArithmeticException
- {
- if (isZero())
- {
- throw new ArithmeticException();
- }
- GF2Polynomial b = new GF2Polynomial(mDegree, "ONE");
- GF2Polynomial c = new GF2Polynomial(mDegree);
- GF2Polynomial u = getGF2Polynomial();
- GF2Polynomial v = mField.getFieldPolynomial();
- GF2Polynomial h;
- while (true)
- {
- while (!u.testBit(0))
- { // x|u (x divides u)
- u.shiftRightThis(); // u = u / x
- if (!b.testBit(0))
- {
- b.shiftRightThis();
- }
- else
- {
- b.addToThis(mField.getFieldPolynomial());
- b.shiftRightThis();
- }
- }
- if (u.isOne())
- {
- return new GF2nPolynomialElement((GF2nPolynomialField)mField,
- b);
- }
- u.reduceN();
- v.reduceN();
- if (u.getLength() < v.getLength())
- {
- h = u;
- u = v;
- v = h;
- h = b;
- b = c;
- c = h;
- }
- u.addToThis(v);
- b.addToThis(c);
- }
- }
-
- /**
- * This method is used internally to map the square()-calls within
- * GF2nPolynomialElement to one of the possible squaring methods.
- *
- * @return <tt>this<sup>2</sup></tt> (newly created)
- * @see GF2nPolynomialElement#squarePreCalc
- */
- public GF2nElement square()
- {
- return squarePreCalc();
- }
-
- /**
- * This method is used internally to map the square()-calls within
- * GF2nPolynomialElement to one of the possible squaring methods.
- */
- public void squareThis()
- {
- squareThisPreCalc();
- }
-
- /**
- * Squares this GF2nPolynomialElement using GF2nField's squaring matrix.
- * This is supposed to be fast when using a polynomial (no tri- or
- * pentanomial) as fieldpolynomial. Use squarePreCalc when using a tri- or
- * pentanomial as fieldpolynomial instead.
- *
- * @return <tt>this<sup>2</sup></tt> (newly created)
- * @see GF2Polynomial#vectorMult
- * @see GF2nPolynomialElement#squarePreCalc
- * @see GF2nPolynomialElement#squareBitwise
- */
- public GF2nPolynomialElement squareMatrix()
- {
- GF2nPolynomialElement result = new GF2nPolynomialElement(this);
- result.squareThisMatrix();
- result.reduceThis();
- return result;
- }
-
- /**
- * Squares this GF2nPolynomialElement using GF2nFields squaring matrix. This
- * is supposed to be fast when using a polynomial (no tri- or pentanomial)
- * as fieldpolynomial. Use squarePreCalc when using a tri- or pentanomial as
- * fieldpolynomial instead.
- *
- * @see GF2Polynomial#vectorMult
- * @see GF2nPolynomialElement#squarePreCalc
- * @see GF2nPolynomialElement#squareBitwise
- */
- public void squareThisMatrix()
- {
- GF2Polynomial result = new GF2Polynomial(mDegree);
- for (int i = 0; i < mDegree; i++)
- {
- if (polynomial
- .vectorMult(((GF2nPolynomialField)mField).squaringMatrix[mDegree
- - i - 1]))
- {
- result.setBit(i);
-
- }
- }
- polynomial = result;
- }
-
- /**
- * Squares this GF2nPolynomialElement by shifting left its Bitstring and
- * reducing. This is supposed to be the slowest method. Use squarePreCalc or
- * squareMatrix instead.
- *
- * @return <tt>this<sup>2</sup></tt> (newly created)
- * @see GF2nPolynomialElement#squareMatrix
- * @see GF2nPolynomialElement#squarePreCalc
- * @see GF2Polynomial#squareThisBitwise
- */
- public GF2nPolynomialElement squareBitwise()
- {
- GF2nPolynomialElement result = new GF2nPolynomialElement(this);
- result.squareThisBitwise();
- result.reduceThis();
- return result;
- }
-
- /**
- * Squares this GF2nPolynomialElement by shifting left its Bitstring and
- * reducing. This is supposed to be the slowest method. Use squarePreCalc or
- * squareMatrix instead.
- *
- * @see GF2nPolynomialElement#squareMatrix
- * @see GF2nPolynomialElement#squarePreCalc
- * @see GF2Polynomial#squareThisBitwise
- */
- public void squareThisBitwise()
- {
- polynomial.squareThisBitwise();
- reduceThis();
- }
-
- /**
- * Squares this GF2nPolynomialElement by using precalculated values and
- * reducing. This is supposed to de fastest when using a trinomial or
- * pentanomial as field polynomial. Use squareMatrix when using a ordinary
- * polynomial as field polynomial.
- *
- * @return <tt>this<sup>2</sup></tt> (newly created)
- * @see GF2nPolynomialElement#squareMatrix
- * @see GF2Polynomial#squareThisPreCalc
- */
- public GF2nPolynomialElement squarePreCalc()
- {
- GF2nPolynomialElement result = new GF2nPolynomialElement(this);
- result.squareThisPreCalc();
- result.reduceThis();
- return result;
- }
-
- /**
- * Squares this GF2nPolynomialElement by using precalculated values and
- * reducing. This is supposed to de fastest when using a tri- or pentanomial
- * as fieldpolynomial. Use squareMatrix when using a ordinary polynomial as
- * fieldpolynomial.
- *
- * @see GF2nPolynomialElement#squareMatrix
- * @see GF2Polynomial#squareThisPreCalc
- */
- public void squareThisPreCalc()
- {
- polynomial.squareThisPreCalc();
- reduceThis();
- }
-
- /**
- * Calculates <i>this</i> to the power of <i>k</i> and returns the result
- * in a new GF2nPolynomialElement.
- *
- * @param k the power
- * @return <i>this</i>^<i>k</i> in a new GF2nPolynomialElement
- */
- public GF2nPolynomialElement power(int k)
- {
- if (k == 1)
- {
- return new GF2nPolynomialElement(this);
- }
-
- GF2nPolynomialElement result = GF2nPolynomialElement
- .ONE((GF2nPolynomialField)mField);
- if (k == 0)
- {
- return result;
- }
-
- GF2nPolynomialElement x = new GF2nPolynomialElement(this);
- x.polynomial.expandN((x.mDegree << 1) + 32); // increase performance
- x.polynomial.reduceN();
-
- for (int i = 0; i < mDegree; i++)
- {
- if ((k & (1 << i)) != 0)
- {
- result.multiplyThisBy(x);
- }
- x.square();
- }
-
- return result;
- }
-
- /**
- * Compute the square root of this element and return the result in a new
- * {@link GF2nPolynomialElement}.
- *
- * @return <tt>this<sup>1/2</sup></tt> (newly created)
- */
- public GF2nElement squareRoot()
- {
- GF2nPolynomialElement result = new GF2nPolynomialElement(this);
- result.squareRootThis();
- return result;
- }
-
- /**
- * Compute the square root of this element.
- */
- public void squareRootThis()
- {
- // increase performance
- polynomial.expandN((mDegree << 1) + 32);
- polynomial.reduceN();
- for (int i = 0; i < mField.getDegree() - 1; i++)
- {
- squareThis();
- }
- }
-
- /**
- * Solves the quadratic equation <tt>z<sup>2</sup> + z = this</tt> if
- * such a solution exists. This method returns one of the two possible
- * solutions. The other solution is <tt>z + 1</tt>. Use z.increase() to
- * compute this solution.
- *
- * @return a GF2nPolynomialElement representing one z satisfying the
- * equation <tt>z<sup>2</sup> + z = this</tt>
- * @throws NoSolutionException if no solution exists
- * @see "IEEE 1363, Annex A.4.7"
- */
- public GF2nElement solveQuadraticEquation()
- throws RuntimeException
- {
- if (isZero())
- {
- return ZERO((GF2nPolynomialField)mField);
- }
-
- if ((mDegree & 1) == 1)
- {
- return halfTrace();
- }
-
- // TODO this can be sped-up by precomputation of p and w's
- GF2nPolynomialElement z, w;
- do
- {
- // step 1.
- GF2nPolynomialElement p = new GF2nPolynomialElement(
- (GF2nPolynomialField)mField, new Random());
- // step 2.
- z = ZERO((GF2nPolynomialField)mField);
- w = (GF2nPolynomialElement)p.clone();
- // step 3.
- for (int i = 1; i < mDegree; i++)
- {
- // compute z = z^2 + w^2 * this
- // and w = w^2 + p
- z.squareThis();
- w.squareThis();
- z.addToThis(w.multiply(this));
- w.addToThis(p);
- }
- }
- while (w.isZero()); // step 4.
-
- if (!equals(z.square().add(z)))
- {
- throw new RuntimeException();
- }
-
- // step 5.
- return z;
- }
-
- /**
- * Returns the trace of this GF2nPolynomialElement.
- *
- * @return the trace of this GF2nPolynomialElement
- */
- public int trace()
- {
- GF2nPolynomialElement t = new GF2nPolynomialElement(this);
- int i;
-
- for (i = 1; i < mDegree; i++)
- {
- t.squareThis();
- t.addToThis(this);
- }
-
- if (t.isOne())
- {
- return 1;
- }
- return 0;
- }
-
- /**
- * Returns the half-trace of this GF2nPolynomialElement.
- *
- * @return a GF2nPolynomialElement representing the half-trace of this
- * GF2nPolynomialElement.
- * @throws DegreeIsEvenException if the degree of this GF2nPolynomialElement is even.
- */
- private GF2nPolynomialElement halfTrace()
- throws RuntimeException
- {
- if ((mDegree & 0x01) == 0)
- {
- throw new RuntimeException();
- }
- int i;
- GF2nPolynomialElement h = new GF2nPolynomialElement(this);
-
- for (i = 1; i <= ((mDegree - 1) >> 1); i++)
- {
- h.squareThis();
- h.squareThis();
- h.addToThis(this);
- }
-
- return h;
- }
-
- /**
- * Reduces this GF2nPolynomialElement modulo the field-polynomial.
- *
- * @see GF2Polynomial#reduceTrinomial
- * @see GF2Polynomial#reducePentanomial
- */
- private void reduceThis()
- {
- if (polynomial.getLength() > mDegree)
- { // really reduce ?
- if (((GF2nPolynomialField)mField).isTrinomial())
- { // fieldpolonomial
- // is trinomial
- int tc;
- try
- {
- tc = ((GF2nPolynomialField)mField).getTc();
- }
- catch (RuntimeException NATExc)
- {
- throw new RuntimeException(
- "GF2nPolynomialElement.reduce: the field"
- + " polynomial is not a trinomial");
- }
- if (((mDegree - tc) <= 32) // do we have to use slow
- // bitwise reduction ?
- || (polynomial.getLength() > (mDegree << 1)))
- {
- reduceTrinomialBitwise(tc);
- return;
- }
- polynomial.reduceTrinomial(mDegree, tc);
- return;
- }
- else if (((GF2nPolynomialField)mField).isPentanomial())
- { // fieldpolynomial
- // is
- // pentanomial
- int[] pc;
- try
- {
- pc = ((GF2nPolynomialField)mField).getPc();
- }
- catch (RuntimeException NATExc)
- {
- throw new RuntimeException(
- "GF2nPolynomialElement.reduce: the field"
- + " polynomial is not a pentanomial");
- }
- if (((mDegree - pc[2]) <= 32) // do we have to use slow
- // bitwise reduction ?
- || (polynomial.getLength() > (mDegree << 1)))
- {
- reducePentanomialBitwise(pc);
- return;
- }
- polynomial.reducePentanomial(mDegree, pc);
- return;
- }
- else
- { // fieldpolynomial is something else
- polynomial = polynomial.remainder(mField.getFieldPolynomial());
- polynomial.expandN(mDegree);
- return;
- }
- }
- if (polynomial.getLength() < mDegree)
- {
- polynomial.expandN(mDegree);
- }
- }
-
- /**
- * Reduce this GF2nPolynomialElement using the trinomial x^n + x^tc + 1 as
- * fieldpolynomial. The coefficients are reduced bit by bit.
- */
- private void reduceTrinomialBitwise(int tc)
- {
- int i;
- int k = mDegree - tc;
- for (i = polynomial.getLength() - 1; i >= mDegree; i--)
- {
- if (polynomial.testBit(i))
- {
-
- polynomial.xorBit(i);
- polynomial.xorBit(i - k);
- polynomial.xorBit(i - mDegree);
-
- }
- }
- polynomial.reduceN();
- polynomial.expandN(mDegree);
- }
-
- /**
- * Reduce this GF2nPolynomialElement using the pentanomial x^n + x^pc[2] +
- * x^pc[1] + x^pc[0] + 1 as fieldpolynomial. The coefficients are reduced
- * bit by bit.
- */
- private void reducePentanomialBitwise(int[] pc)
- {
- int i;
- int k = mDegree - pc[2];
- int l = mDegree - pc[1];
- int m = mDegree - pc[0];
- for (i = polynomial.getLength() - 1; i >= mDegree; i--)
- {
- if (polynomial.testBit(i))
- {
- polynomial.xorBit(i);
- polynomial.xorBit(i - k);
- polynomial.xorBit(i - l);
- polynomial.xorBit(i - m);
- polynomial.xorBit(i - mDegree);
-
- }
- }
- polynomial.reduceN();
- polynomial.expandN(mDegree);
- }
-
- // /////////////////////////////////////////////////////////////////////
- // conversion
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Returns a string representing this Bitstrings value using hexadecimal
- * radix in MSB-first order.
- *
- * @return a String representing this Bitstrings value.
- */
- public String toString()
- {
- return polynomial.toString(16);
- }
-
- /**
- * Returns a string representing this Bitstrings value using hexadecimal or
- * binary radix in MSB-first order.
- *
- * @param radix the radix to use (2 or 16, otherwise 2 is used)
- * @return a String representing this Bitstrings value.
- */
- public String toString(int radix)
- {
- return polynomial.toString(radix);
- }
-
- /**
- * Converts this GF2nPolynomialElement to a byte[] according to 1363.
- *
- * @return a byte[] representing the value of this GF2nPolynomialElement
- * @see "P1363 5.5.2 p22f BS2OSP, FE2OSP"
- */
- public byte[] toByteArray()
- {
- return polynomial.toByteArray();
- }
-
- /**
- * Converts this GF2nPolynomialElement to an integer according to 1363.
- *
- * @return a BigInteger representing the value of this
- * GF2nPolynomialElement
- * @see "P1363 5.5.1 p22 BS2IP"
- */
- public BigInteger toFlexiBigInt()
- {
- return polynomial.toFlexiBigInt();
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomialField.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomialField.java
deleted file mode 100644
index f66ec20a..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomialField.java
+++ /dev/null
@@ -1,553 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-
-import java.util.Random;
-import java.util.Vector;
-
-
-/**
- * This class implements the abstract class <tt>GF2nField</tt> for polynomial
- * representation. It computes the field polynomial and the squaring matrix.
- * GF2nField is used by GF2nPolynomialElement which implements the elements of
- * this field.
- *
- * @see GF2nField
- * @see GF2nPolynomialElement
- */
-public class GF2nPolynomialField
- extends GF2nField
-{
-
- /**
- * Matrix used for fast squaring
- */
- GF2Polynomial[] squaringMatrix;
-
- // field polynomial is a trinomial
- private boolean isTrinomial = false;
-
- // field polynomial is a pentanomial
- private boolean isPentanomial = false;
-
- // middle coefficient of the field polynomial in case it is a trinomial
- private int tc;
-
- // middle 3 coefficients of the field polynomial in case it is a pentanomial
- private int[] pc = new int[3];
-
- /**
- * constructs an instance of the finite field with 2<sup>deg</sup>
- * elements and characteristic 2.
- *
- * @param deg the extention degree of this field
- */
- public GF2nPolynomialField(int deg)
- {
- if (deg < 3)
- {
- throw new IllegalArgumentException("k must be at least 3");
- }
- mDegree = deg;
- computeFieldPolynomial();
- computeSquaringMatrix();
- fields = new Vector();
- matrices = new Vector();
- }
-
- /**
- * constructs an instance of the finite field with 2<sup>deg</sup>
- * elements and characteristic 2.
- *
- * @param deg the degree of this field
- * @param file true if you want to read the field polynomial from the
- * file false if you want to use a random fielpolynomial
- * (this can take very long for huge degrees)
- */
- public GF2nPolynomialField(int deg, boolean file)
- {
- if (deg < 3)
- {
- throw new IllegalArgumentException("k must be at least 3");
- }
- mDegree = deg;
- if (file)
- {
- computeFieldPolynomial();
- }
- else
- {
- computeFieldPolynomial2();
- }
- computeSquaringMatrix();
- fields = new Vector();
- matrices = new Vector();
- }
-
- /**
- * Creates a new GF2nField of degree <i>i</i> and uses the given
- * <i>polynomial</i> as field polynomial. The <i>polynomial</i> is checked
- * whether it is irreducible. This can take some time if <i>i</i> is huge!
- *
- * @param deg degree of the GF2nField
- * @param polynomial the field polynomial to use
- * @throws PolynomialIsNotIrreducibleException if the given polynomial is not irreducible in GF(2^<i>i</i>)
- */
- public GF2nPolynomialField(int deg, GF2Polynomial polynomial)
- throws RuntimeException
- {
- if (deg < 3)
- {
- throw new IllegalArgumentException("degree must be at least 3");
- }
- if (polynomial.getLength() != deg + 1)
- {
- throw new RuntimeException();
- }
- if (!polynomial.isIrreducible())
- {
- throw new RuntimeException();
- }
- mDegree = deg;
- // fieldPolynomial = new Bitstring(polynomial);
- fieldPolynomial = polynomial;
- computeSquaringMatrix();
- int k = 2; // check if the polynomial is a trinomial or pentanomial
- for (int j = 1; j < fieldPolynomial.getLength() - 1; j++)
- {
- if (fieldPolynomial.testBit(j))
- {
- k++;
- if (k == 3)
- {
- tc = j;
- }
- if (k <= 5)
- {
- pc[k - 3] = j;
- }
- }
- }
- if (k == 3)
- {
- isTrinomial = true;
- }
- if (k == 5)
- {
- isPentanomial = true;
- }
- fields = new Vector();
- matrices = new Vector();
- }
-
- /**
- * Returns true if the field polynomial is a trinomial. The coefficient can
- * be retrieved using getTc().
- *
- * @return true if the field polynomial is a trinomial
- */
- public boolean isTrinomial()
- {
- return isTrinomial;
- }
-
- /**
- * Returns true if the field polynomial is a pentanomial. The coefficients
- * can be retrieved using getPc().
- *
- * @return true if the field polynomial is a pentanomial
- */
- public boolean isPentanomial()
- {
- return isPentanomial;
- }
-
- /**
- * Returns the degree of the middle coefficient of the used field trinomial
- * (x^n + x^(getTc()) + 1).
- *
- * @return the middle coefficient of the used field trinomial
- * @throws GFException if the field polynomial is not a trinomial
- */
- public int getTc()
- throws RuntimeException
- {
- if (!isTrinomial)
- {
- throw new RuntimeException();
- }
- return tc;
- }
-
- /**
- * Returns the degree of the middle coefficients of the used field
- * pentanomial (x^n + x^(getPc()[2]) + x^(getPc()[1]) + x^(getPc()[0]) + 1).
- *
- * @return the middle coefficients of the used field pentanomial
- * @throws GFException if the field polynomial is not a pentanomial
- */
- public int[] getPc()
- throws RuntimeException
- {
- if (!isPentanomial)
- {
- throw new RuntimeException();
- }
- int[] result = new int[3];
- System.arraycopy(pc, 0, result, 0, 3);
- return result;
- }
-
- /**
- * Return row vector i of the squaring matrix.
- *
- * @param i the index of the row vector to return
- * @return a copy of squaringMatrix[i]
- * @see GF2nPolynomialElement#squareMatrix
- */
- public GF2Polynomial getSquaringVector(int i)
- {
- return new GF2Polynomial(squaringMatrix[i]);
- }
-
- /**
- * Compute a random root of the given GF2Polynomial.
- *
- * @param polynomial the polynomial
- * @return a random root of <tt>polynomial</tt>
- */
- protected GF2nElement getRandomRoot(GF2Polynomial polynomial)
- {
- // We are in B1!!!
- GF2nPolynomial c;
- GF2nPolynomial ut;
- GF2nElement u;
- GF2nPolynomial h;
- int hDegree;
- // 1. Set g(t) <- f(t)
- GF2nPolynomial g = new GF2nPolynomial(polynomial, this);
- int gDegree = g.getDegree();
- int i;
-
- // 2. while deg(g) > 1
- while (gDegree > 1)
- {
- do
- {
- // 2.1 choose random u (element of) GF(2^m)
- u = new GF2nPolynomialElement(this, new Random());
- ut = new GF2nPolynomial(2, GF2nPolynomialElement.ZERO(this));
- // 2.2 Set c(t) <- ut
- ut.set(1, u);
- c = new GF2nPolynomial(ut);
- // 2.3 For i from 1 to m-1 do
- for (i = 1; i <= mDegree - 1; i++)
- {
- // 2.3.1 c(t) <- (c(t)^2 + ut) mod g(t)
- c = c.multiplyAndReduce(c, g);
- c = c.add(ut);
- }
- // 2.4 set h(t) <- GCD(c(t), g(t))
- h = c.gcd(g);
- // 2.5 if h(t) is constant or deg(g) = deg(h) then go to
- // step 2.1
- hDegree = h.getDegree();
- gDegree = g.getDegree();
- }
- while ((hDegree == 0) || (hDegree == gDegree));
- // 2.6 If 2deg(h) > deg(g) then set g(t) <- g(t)/h(t) ...
- if ((hDegree << 1) > gDegree)
- {
- g = g.quotient(h);
- }
- else
- {
- // ... else g(t) <- h(t)
- g = new GF2nPolynomial(h);
- }
- gDegree = g.getDegree();
- }
- // 3. Output g(0)
- return g.at(0);
-
- }
-
- /**
- * Computes the change-of-basis matrix for basis conversion according to
- * 1363. The result is stored in the lists fields and matrices.
- *
- * @param B1 the GF2nField to convert to
- * @see "P1363 A.7.3, p111ff"
- */
- protected void computeCOBMatrix(GF2nField B1)
- {
- // we are in B0 here!
- if (mDegree != B1.mDegree)
- {
- throw new IllegalArgumentException(
- "GF2nPolynomialField.computeCOBMatrix: B1 has a different "
- + "degree and thus cannot be coverted to!");
- }
- if (B1 instanceof GF2nONBField)
- {
- // speedup (calculation is done in PolynomialElements instead of
- // ONB)
- B1.computeCOBMatrix(this);
- return;
- }
- int i, j;
- GF2nElement[] gamma;
- GF2nElement u;
- GF2Polynomial[] COBMatrix = new GF2Polynomial[mDegree];
- for (i = 0; i < mDegree; i++)
- {
- COBMatrix[i] = new GF2Polynomial(mDegree);
- }
-
- // find Random Root
- do
- {
- // u is in representation according to B1
- u = B1.getRandomRoot(fieldPolynomial);
- }
- while (u.isZero());
-
- // build gamma matrix by multiplying by u
- if (u instanceof GF2nONBElement)
- {
- gamma = new GF2nONBElement[mDegree];
- gamma[mDegree - 1] = GF2nONBElement.ONE((GF2nONBField)B1);
- }
- else
- {
- gamma = new GF2nPolynomialElement[mDegree];
- gamma[mDegree - 1] = GF2nPolynomialElement
- .ONE((GF2nPolynomialField)B1);
- }
- gamma[mDegree - 2] = u;
- for (i = mDegree - 3; i >= 0; i--)
- {
- gamma[i] = (GF2nElement)gamma[i + 1].multiply(u);
- }
- if (B1 instanceof GF2nONBField)
- {
- // convert horizontal gamma matrix by vertical Bitstrings
- for (i = 0; i < mDegree; i++)
- {
- for (j = 0; j < mDegree; j++)
- {
- // TODO remember: ONB treats its Bits in reverse order !!!
- if (gamma[i].testBit(mDegree - j - 1))
- {
- COBMatrix[mDegree - j - 1].setBit(mDegree - i - 1);
- }
- }
- }
- }
- else
- {
- // convert horizontal gamma matrix by vertical Bitstrings
- for (i = 0; i < mDegree; i++)
- {
- for (j = 0; j < mDegree; j++)
- {
- if (gamma[i].testBit(j))
- {
- COBMatrix[mDegree - j - 1].setBit(mDegree - i - 1);
- }
- }
- }
- }
-
- // store field and matrix for further use
- fields.addElement(B1);
- matrices.addElement(COBMatrix);
- // store field and inverse matrix for further use in B1
- B1.fields.addElement(this);
- B1.matrices.addElement(invertMatrix(COBMatrix));
- }
-
- /**
- * Computes a new squaring matrix used for fast squaring.
- *
- * @see GF2nPolynomialElement#square
- */
- private void computeSquaringMatrix()
- {
- GF2Polynomial[] d = new GF2Polynomial[mDegree - 1];
- int i, j;
- squaringMatrix = new GF2Polynomial[mDegree];
- for (i = 0; i < squaringMatrix.length; i++)
- {
- squaringMatrix[i] = new GF2Polynomial(mDegree, "ZERO");
- }
-
- for (i = 0; i < mDegree - 1; i++)
- {
- d[i] = new GF2Polynomial(1, "ONE").shiftLeft(mDegree + i)
- .remainder(fieldPolynomial);
- }
- for (i = 1; i <= Math.abs(mDegree >> 1); i++)
- {
- for (j = 1; j <= mDegree; j++)
- {
- if (d[mDegree - (i << 1)].testBit(mDegree - j))
- {
- squaringMatrix[j - 1].setBit(mDegree - i);
- }
- }
- }
- for (i = Math.abs(mDegree >> 1) + 1; i <= mDegree; i++)
- {
- squaringMatrix[(i << 1) - mDegree - 1].setBit(mDegree - i);
- }
-
- }
-
- /**
- * Computes the field polynomial. This can take a long time for big degrees.
- */
- protected void computeFieldPolynomial()
- {
- if (testTrinomials())
- {
- return;
- }
- if (testPentanomials())
- {
- return;
- }
- testRandom();
- }
-
- /**
- * Computes the field polynomial. This can take a long time for big degrees.
- */
- protected void computeFieldPolynomial2()
- {
- if (testTrinomials())
- {
- return;
- }
- if (testPentanomials())
- {
- return;
- }
- testRandom();
- }
-
- /**
- * Tests all trinomials of degree (n+1) until a irreducible is found and
- * stores the result in <i>field polynomial</i>. Returns false if no
- * irreducible trinomial exists in GF(2^n). This can take very long for huge
- * degrees.
- *
- * @return true if an irreducible trinomial is found
- */
- private boolean testTrinomials()
- {
- int i, l;
- boolean done = false;
- l = 0;
-
- fieldPolynomial = new GF2Polynomial(mDegree + 1);
- fieldPolynomial.setBit(0);
- fieldPolynomial.setBit(mDegree);
- for (i = 1; (i < mDegree) && !done; i++)
- {
- fieldPolynomial.setBit(i);
- done = fieldPolynomial.isIrreducible();
- l++;
- if (done)
- {
- isTrinomial = true;
- tc = i;
- return done;
- }
- fieldPolynomial.resetBit(i);
- done = fieldPolynomial.isIrreducible();
- }
-
- return done;
- }
-
- /**
- * Tests all pentanomials of degree (n+1) until a irreducible is found and
- * stores the result in <i>field polynomial</i>. Returns false if no
- * irreducible pentanomial exists in GF(2^n). This can take very long for
- * huge degrees.
- *
- * @return true if an irreducible pentanomial is found
- */
- private boolean testPentanomials()
- {
- int i, j, k, l;
- boolean done = false;
- l = 0;
-
- fieldPolynomial = new GF2Polynomial(mDegree + 1);
- fieldPolynomial.setBit(0);
- fieldPolynomial.setBit(mDegree);
- for (i = 1; (i <= (mDegree - 3)) && !done; i++)
- {
- fieldPolynomial.setBit(i);
- for (j = i + 1; (j <= (mDegree - 2)) && !done; j++)
- {
- fieldPolynomial.setBit(j);
- for (k = j + 1; (k <= (mDegree - 1)) && !done; k++)
- {
- fieldPolynomial.setBit(k);
- if (((mDegree & 1) != 0) | ((i & 1) != 0) | ((j & 1) != 0)
- | ((k & 1) != 0))
- {
- done = fieldPolynomial.isIrreducible();
- l++;
- if (done)
- {
- isPentanomial = true;
- pc[0] = i;
- pc[1] = j;
- pc[2] = k;
- return done;
- }
- }
- fieldPolynomial.resetBit(k);
- }
- fieldPolynomial.resetBit(j);
- }
- fieldPolynomial.resetBit(i);
- }
-
- return done;
- }
-
- /**
- * Tests random polynomials of degree (n+1) until an irreducible is found
- * and stores the result in <i>field polynomial</i>. This can take very
- * long for huge degrees.
- *
- * @return true
- */
- private boolean testRandom()
- {
- int l;
- boolean done = false;
-
- fieldPolynomial = new GF2Polynomial(mDegree + 1);
- l = 0;
- while (!done)
- {
- l++;
- fieldPolynomial.randomize();
- fieldPolynomial.setBit(mDegree);
- fieldPolynomial.setBit(0);
- if (fieldPolynomial.isIrreducible())
- {
- done = true;
- return done;
- }
- }
-
- return done;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GFElement.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GFElement.java
deleted file mode 100644
index 1e93e158..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GFElement.java
+++ /dev/null
@@ -1,158 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-import java.math.BigInteger;
-
-
-/**
- * This interface defines a finite field element. It is implemented by the
- * classes {@link GFPElement} and {@link GF2nElement}.
- *
- * @see GFPElement
- * @see GF2nElement
- */
-public interface GFElement
-{
-
- /**
- * @return a copy of this GFElement
- */
- Object clone();
-
- // /////////////////////////////////////////////////////////////////
- // comparison
- // /////////////////////////////////////////////////////////////////
-
- /**
- * Compare this curve with another object.
- *
- * @param other the other object
- * @return the result of the comparison
- */
- boolean equals(Object other);
-
- /**
- * @return the hash code of this element
- */
- int hashCode();
-
- /**
- * Checks whether this element is zero.
- *
- * @return <tt>true</tt> if <tt>this</tt> is the zero element
- */
- boolean isZero();
-
- /**
- * Checks whether this element is one.
- *
- * @return <tt>true</tt> if <tt>this</tt> is the one element
- */
- boolean isOne();
-
- // /////////////////////////////////////////////////////////////////////
- // arithmetic
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Compute the sum of this element and the addend.
- *
- * @param addend the addend
- * @return <tt>this + other</tt> (newly created)
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- GFElement add(GFElement addend)
- throws RuntimeException;
-
- /**
- * Compute the sum of this element and the addend, overwriting this element.
- *
- * @param addend the addend
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- void addToThis(GFElement addend)
- throws RuntimeException;
-
- /**
- * Compute the difference of this element and <tt>minuend</tt>.
- *
- * @param minuend the minuend
- * @return <tt>this - minuend</tt> (newly created)
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- GFElement subtract(GFElement minuend)
- throws RuntimeException;
-
- /**
- * Compute the difference of this element and <tt>minuend</tt>,
- * overwriting this element.
- *
- * @param minuend the minuend
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- void subtractFromThis(GFElement minuend);
-
- /**
- * Compute the product of this element and <tt>factor</tt>.
- *
- * @param factor the factor
- * @return <tt>this * factor</tt> (newly created)
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- GFElement multiply(GFElement factor)
- throws RuntimeException;
-
- /**
- * Compute <tt>this * factor</tt> (overwrite <tt>this</tt>).
- *
- * @param factor the factor
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- void multiplyThisBy(GFElement factor)
- throws RuntimeException;
-
- /**
- * Compute the multiplicative inverse of this element.
- *
- * @return <tt>this<sup>-1</sup></tt> (newly created)
- * @throws ArithmeticException if <tt>this</tt> is the zero element.
- */
- GFElement invert()
- throws ArithmeticException;
-
- // /////////////////////////////////////////////////////////////////////
- // conversion
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Returns this element as FlexiBigInt. The conversion is <a
- * href="http://grouper.ieee.org/groups/1363/">P1363</a>-conform.
- *
- * @return this element as BigInt
- */
- BigInteger toFlexiBigInt();
-
- /**
- * Returns this element as byte array. The conversion is <a href =
- * "http://grouper.ieee.org/groups/1363/">P1363</a>-conform.
- *
- * @return this element as byte array
- */
- byte[] toByteArray();
-
- /**
- * Return a String representation of this element.
- *
- * @return String representation of this element
- */
- String toString();
-
- /**
- * Return a String representation of this element. <tt>radix</tt>
- * specifies the radix of the String representation.
- *
- * @param radix specifies the radix of the String representation
- * @return String representation of this element with the specified radix
- */
- String toString(int radix);
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GoppaCode.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GoppaCode.java
deleted file mode 100644
index cf82eaea..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GoppaCode.java
+++ /dev/null
@@ -1,310 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-import java.security.SecureRandom;
-
-/**
- * This class describes decoding operations of an irreducible binary Goppa code.
- * A check matrix H of the Goppa code and an irreducible Goppa polynomial are
- * used the operations are worked over a finite field GF(2^m)
- *
- * @see GF2mField
- * @see PolynomialGF2mSmallM
- */
-public final class GoppaCode
-{
-
- /**
- * Default constructor (private).
- */
- private GoppaCode()
- {
- // empty
- }
-
- /**
- * This class is a container for two instances of {@link GF2Matrix} and one
- * instance of {@link Permutation}. It is used to hold the systematic form
- * <tt>S*H*P = (Id|M)</tt> of the check matrix <tt>H</tt> as returned by
- * {@link GoppaCode#computeSystematicForm(GF2Matrix, SecureRandom)}.
- *
- * @see GF2Matrix
- * @see Permutation
- */
- public static class MaMaPe
- {
-
- private GF2Matrix s, h;
-
- private Permutation p;
-
- /**
- * Construct a new {@link MaMaPe} container with the given parameters.
- *
- * @param s the first matrix
- * @param h the second matrix
- * @param p the permutation
- */
- public MaMaPe(GF2Matrix s, GF2Matrix h, Permutation p)
- {
- this.s = s;
- this.h = h;
- this.p = p;
- }
-
- /**
- * @return the first matrix
- */
- public GF2Matrix getFirstMatrix()
- {
- return s;
- }
-
- /**
- * @return the second matrix
- */
- public GF2Matrix getSecondMatrix()
- {
- return h;
- }
-
- /**
- * @return the permutation
- */
- public Permutation getPermutation()
- {
- return p;
- }
- }
-
- /**
- * This class is a container for an instance of {@link GF2Matrix} and one
- * int[]. It is used to hold a generator matrix and the set of indices such
- * that the submatrix of the generator matrix consisting of the specified
- * columns is the identity.
- *
- * @see GF2Matrix
- * @see Permutation
- */
- public static class MatrixSet
- {
-
- private GF2Matrix g;
-
- private int[] setJ;
-
- /**
- * Construct a new {@link MatrixSet} container with the given
- * parameters.
- *
- * @param g the generator matrix
- * @param setJ the set of indices such that the submatrix of the
- * generator matrix consisting of the specified columns
- * is the identity
- */
- public MatrixSet(GF2Matrix g, int[] setJ)
- {
- this.g = g;
- this.setJ = setJ;
- }
-
- /**
- * @return the generator matrix
- */
- public GF2Matrix getG()
- {
- return g;
- }
-
- /**
- * @return the set of indices such that the submatrix of the generator
- * matrix consisting of the specified columns is the identity
- */
- public int[] getSetJ()
- {
- return setJ;
- }
- }
-
- /**
- * Construct the check matrix of a Goppa code in canonical form from the
- * irreducible Goppa polynomial over the finite field
- * <tt>GF(2<sup>m</sup>)</tt>.
- *
- * @param field the finite field
- * @param gp the irreducible Goppa polynomial
- */
- public static GF2Matrix createCanonicalCheckMatrix(GF2mField field,
- PolynomialGF2mSmallM gp)
- {
- int m = field.getDegree();
- int n = 1 << m;
- int t = gp.getDegree();
-
- /* create matrix H over GF(2^m) */
-
- int[][] hArray = new int[t][n];
-
- // create matrix YZ
- int[][] yz = new int[t][n];
- for (int j = 0; j < n; j++)
- {
- // here j is used as index and as element of field GF(2^m)
- yz[0][j] = field.inverse(gp.evaluateAt(j));
- }
-
- for (int i = 1; i < t; i++)
- {
- for (int j = 0; j < n; j++)
- {
- // here j is used as index and as element of field GF(2^m)
- yz[i][j] = field.mult(yz[i - 1][j], j);
- }
- }
-
- // create matrix H = XYZ
- for (int i = 0; i < t; i++)
- {
- for (int j = 0; j < n; j++)
- {
- for (int k = 0; k <= i; k++)
- {
- hArray[i][j] = field.add(hArray[i][j], field.mult(yz[k][j],
- gp.getCoefficient(t + k - i)));
- }
- }
- }
-
- /* convert to matrix over GF(2) */
-
- int[][] result = new int[t * m][(n + 31) >>> 5];
-
- for (int j = 0; j < n; j++)
- {
- int q = j >>> 5;
- int r = 1 << (j & 0x1f);
- for (int i = 0; i < t; i++)
- {
- int e = hArray[i][j];
- for (int u = 0; u < m; u++)
- {
- int b = (e >>> u) & 1;
- if (b != 0)
- {
- int ind = (i + 1) * m - u - 1;
- result[ind][q] ^= r;
- }
- }
- }
- }
-
- return new GF2Matrix(n, result);
- }
-
- /**
- * Given a check matrix <tt>H</tt>, compute matrices <tt>S</tt>,
- * <tt>M</tt>, and a random permutation <tt>P</tt> such that
- * <tt>S*H*P = (Id|M)</tt>. Return <tt>S^-1</tt>, <tt>M</tt>, and
- * <tt>P</tt> as {@link MaMaPe}. The matrix <tt>(Id | M)</tt> is called
- * the systematic form of H.
- *
- * @param h the check matrix
- * @param sr a source of randomness
- * @return the tuple <tt>(S^-1, M, P)</tt>
- */
- public static MaMaPe computeSystematicForm(GF2Matrix h, SecureRandom sr)
- {
- int n = h.getNumColumns();
- GF2Matrix hp, sInv;
- GF2Matrix s = null;
- Permutation p;
- boolean found = false;
-
- do
- {
- p = new Permutation(n, sr);
- hp = (GF2Matrix)h.rightMultiply(p);
- sInv = hp.getLeftSubMatrix();
- try
- {
- found = true;
- s = (GF2Matrix)sInv.computeInverse();
- }
- catch (ArithmeticException ae)
- {
- found = false;
- }
- }
- while (!found);
-
- GF2Matrix shp = (GF2Matrix)s.rightMultiply(hp);
- GF2Matrix m = shp.getRightSubMatrix();
-
- return new MaMaPe(sInv, m, p);
- }
-
- /**
- * Find an error vector <tt>e</tt> over <tt>GF(2)</tt> from an input
- * syndrome <tt>s</tt> over <tt>GF(2<sup>m</sup>)</tt>.
- *
- * @param syndVec the syndrome
- * @param field the finite field
- * @param gp the irreducible Goppa polynomial
- * @param sqRootMatrix the matrix for computing square roots in
- * <tt>(GF(2<sup>m</sup>))<sup>t</sup></tt>
- * @return the error vector
- */
- public static GF2Vector syndromeDecode(GF2Vector syndVec, GF2mField field,
- PolynomialGF2mSmallM gp, PolynomialGF2mSmallM[] sqRootMatrix)
- {
-
- int n = 1 << field.getDegree();
-
- // the error vector
- GF2Vector errors = new GF2Vector(n);
-
- // if the syndrome vector is zero, the error vector is also zero
- if (!syndVec.isZero())
- {
- // convert syndrome vector to polynomial over GF(2^m)
- PolynomialGF2mSmallM syndrome = new PolynomialGF2mSmallM(syndVec
- .toExtensionFieldVector(field));
-
- // compute T = syndrome^-1 mod gp
- PolynomialGF2mSmallM t = syndrome.modInverse(gp);
-
- // compute tau = sqRoot(T + X) mod gp
- PolynomialGF2mSmallM tau = t.addMonomial(1);
- tau = tau.modSquareRootMatrix(sqRootMatrix);
-
- // compute polynomials a and b satisfying a + b*tau = 0 mod gp
- PolynomialGF2mSmallM[] ab = tau.modPolynomialToFracton(gp);
-
- // compute the polynomial a^2 + X*b^2
- PolynomialGF2mSmallM a2 = ab[0].multiply(ab[0]);
- PolynomialGF2mSmallM b2 = ab[1].multiply(ab[1]);
- PolynomialGF2mSmallM xb2 = b2.multWithMonomial(1);
- PolynomialGF2mSmallM a2plusXb2 = a2.add(xb2);
-
- // normalize a^2 + X*b^2 to obtain the error locator polynomial
- int headCoeff = a2plusXb2.getHeadCoefficient();
- int invHeadCoeff = field.inverse(headCoeff);
- PolynomialGF2mSmallM elp = a2plusXb2.multWithElement(invHeadCoeff);
-
- // for all elements i of GF(2^m)
- for (int i = 0; i < n; i++)
- {
- // evaluate the error locator polynomial at i
- int z = elp.evaluateAt(i);
- // if polynomial evaluates to zero
- if (z == 0)
- {
- // set the i-th coefficient of the error vector
- errors.setBit(i);
- }
- }
- }
-
- return errors;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/IntUtils.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/IntUtils.java
deleted file mode 100644
index 90a3c60d..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/IntUtils.java
+++ /dev/null
@@ -1,202 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-import java.math.BigInteger;
-
-/**
- *
- *
- *
- */
-public final class IntUtils
-{
-
- /**
- * Default constructor (private).
- */
- private IntUtils()
- {
- // empty
- }
-
- /**
- * Compare two int arrays. No null checks are performed.
- *
- * @param left the first int array
- * @param right the second int array
- * @return the result of the comparison
- */
- public static boolean equals(int[] left, int[] right)
- {
- if (left.length != right.length)
- {
- return false;
- }
- boolean result = true;
- for (int i = left.length - 1; i >= 0; i--)
- {
- result &= left[i] == right[i];
- }
- return result;
- }
-
- /**
- * Return a clone of the given int array. No null checks are performed.
- *
- * @param array the array to clone
- * @return the clone of the given array
- */
- public static int[] clone(int[] array)
- {
- int[] result = new int[array.length];
- System.arraycopy(array, 0, result, 0, array.length);
- return result;
- }
-
- /**
- * Fill the given int array with the given value.
- *
- * @param array the array
- * @param value the value
- */
- public static void fill(int[] array, int value)
- {
- for (int i = array.length - 1; i >= 0; i--)
- {
- array[i] = value;
- }
- }
-
- /**
- * Sorts this array of integers according to the Quicksort algorithm. After
- * calling this method this array is sorted in ascending order with the
- * smallest integer taking position 0 in the array.
- * <p>
- * This implementation is based on the quicksort algorithm as described in
- * <code>Data Structures In Java</code> by Thomas A. Standish, Chapter 10,
- * ISBN 0-201-30564-X.
- *
- * @param source the array of integers that needs to be sorted.
- */
- public static void quicksort(int[] source)
- {
- quicksort(source, 0, source.length - 1);
- }
-
- /**
- * Sort a subarray of a source array. The subarray is specified by its start
- * and end index.
- *
- * @param source the int array to be sorted
- * @param left the start index of the subarray
- * @param right the end index of the subarray
- */
- public static void quicksort(int[] source, int left, int right)
- {
- if (right > left)
- {
- int index = partition(source, left, right, right);
- quicksort(source, left, index - 1);
- quicksort(source, index + 1, right);
- }
- }
-
- /**
- * Split a subarray of a source array into two partitions. The left
- * partition contains elements that have value less than or equal to the
- * pivot element, the right partition contains the elements that have larger
- * value.
- *
- * @param source the int array whose subarray will be splitted
- * @param left the start position of the subarray
- * @param right the end position of the subarray
- * @param pivotIndex the index of the pivot element inside the array
- * @return the new index of the pivot element inside the array
- */
- private static int partition(int[] source, int left, int right,
- int pivotIndex)
- {
-
- int pivot = source[pivotIndex];
- source[pivotIndex] = source[right];
- source[right] = pivot;
-
- int index = left;
-
- for (int i = left; i < right; i++)
- {
- if (source[i] <= pivot)
- {
- int tmp = source[index];
- source[index] = source[i];
- source[i] = tmp;
- index++;
- }
- }
-
- int tmp = source[index];
- source[index] = source[right];
- source[right] = tmp;
-
- return index;
- }
-
- /**
- * Generates a subarray of a given int array.
- *
- * @param input -
- * the input int array
- * @param start -
- * the start index
- * @param end -
- * the end index
- * @return a subarray of <tt>input</tt>, ranging from <tt>start</tt> to
- * <tt>end</tt>
- */
- public static int[] subArray(final int[] input, final int start,
- final int end)
- {
- int[] result = new int[end - start];
- System.arraycopy(input, start, result, 0, end - start);
- return result;
- }
-
- /**
- * Convert an int array to a {@link FlexiBigInt} array.
- *
- * @param input the int array
- * @return the {@link FlexiBigInt} array
- */
- public static BigInteger[] toFlexiBigIntArray(int[] input)
- {
- BigInteger[] result = new BigInteger[input.length];
- for (int i = 0; i < input.length; i++)
- {
- result[i] = BigInteger.valueOf(input[i]);
- }
- return result;
- }
-
- /**
- * @param input an int array
- * @return a human readable form of the given int array
- */
- public static String toString(int[] input)
- {
- String result = "";
- for (int i = 0; i < input.length; i++)
- {
- result += input[i] + " ";
- }
- return result;
- }
-
- /**
- * @param input an int arary
- * @return the int array as hex string
- */
- public static String toHexString(int[] input)
- {
- return ByteUtils.toHexString(BigEndianConversions.toByteArray(input));
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/IntegerFunctions.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/IntegerFunctions.java
deleted file mode 100644
index 779f384a..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/IntegerFunctions.java
+++ /dev/null
@@ -1,1423 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-/**
- * Class of number-theory related functions for use with integers represented as
- * <tt>int</tt>'s or <tt>BigInteger</tt> objects.
- */
-public final class IntegerFunctions
-{
-
- private static final BigInteger ZERO = BigInteger.valueOf(0);
-
- private static final BigInteger ONE = BigInteger.valueOf(1);
-
- private static final BigInteger TWO = BigInteger.valueOf(2);
-
- private static final BigInteger FOUR = BigInteger.valueOf(4);
-
- private static final int[] SMALL_PRIMES = {3, 5, 7, 11, 13, 17, 19, 23,
- 29, 31, 37, 41};
-
- private static final long SMALL_PRIME_PRODUCT = 3L * 5 * 7 * 11 * 13 * 17
- * 19 * 23 * 29 * 31 * 37 * 41;
-
- private static SecureRandom sr = null;
-
- // the jacobi function uses this lookup table
- private static final int[] jacobiTable = {0, 1, 0, -1, 0, -1, 0, 1};
-
- private IntegerFunctions()
- {
- // empty
- }
-
- /**
- * Computes the value of the Jacobi symbol (A|B). The following properties
- * hold for the Jacobi symbol which makes it a very efficient way to
- * evaluate the Legendre symbol
- * <p>
- * (A|B) = 0 IF gcd(A,B) &gt; 1<br>
- * (-1|B) = 1 IF n = 1 (mod 1)<br>
- * (-1|B) = -1 IF n = 3 (mod 4)<br>
- * (A|B) (C|B) = (AC|B)<br>
- * (A|B) (A|C) = (A|CB)<br>
- * (A|B) = (C|B) IF A = C (mod B)<br>
- * (2|B) = 1 IF N = 1 OR 7 (mod 8)<br>
- * (2|B) = 1 IF N = 3 OR 5 (mod 8)
- *
- * @param A integer value
- * @param B integer value
- * @return value of the jacobi symbol (A|B)
- */
- public static int jacobi(BigInteger A, BigInteger B)
- {
- BigInteger a, b, v;
- long k = 1;
-
- k = 1;
-
- // test trivial cases
- if (B.equals(ZERO))
- {
- a = A.abs();
- return a.equals(ONE) ? 1 : 0;
- }
-
- if (!A.testBit(0) && !B.testBit(0))
- {
- return 0;
- }
-
- a = A;
- b = B;
-
- if (b.signum() == -1)
- { // b < 0
- b = b.negate(); // b = -b
- if (a.signum() == -1)
- {
- k = -1;
- }
- }
-
- v = ZERO;
- while (!b.testBit(0))
- {
- v = v.add(ONE); // v = v + 1
- b = b.divide(TWO); // b = b/2
- }
-
- if (v.testBit(0))
- {
- k = k * jacobiTable[a.intValue() & 7];
- }
-
- if (a.signum() < 0)
- { // a < 0
- if (b.testBit(1))
- {
- k = -k; // k = -k
- }
- a = a.negate(); // a = -a
- }
-
- // main loop
- while (a.signum() != 0)
- {
- v = ZERO;
- while (!a.testBit(0))
- { // a is even
- v = v.add(ONE);
- a = a.divide(TWO);
- }
- if (v.testBit(0))
- {
- k = k * jacobiTable[b.intValue() & 7];
- }
-
- if (a.compareTo(b) < 0)
- { // a < b
- // swap and correct intermediate result
- BigInteger x = a;
- a = b;
- b = x;
- if (a.testBit(1) && b.testBit(1))
- {
- k = -k;
- }
- }
- a = a.subtract(b);
- }
-
- return b.equals(ONE) ? (int)k : 0;
- }
-
- /**
- * Computes the square root of a BigInteger modulo a prime employing the
- * Shanks-Tonelli algorithm.
- *
- * @param a value out of which we extract the square root
- * @param p prime modulus that determines the underlying field
- * @return a number <tt>b</tt> such that b<sup>2</sup> = a (mod p) if
- * <tt>a</tt> is a quadratic residue modulo <tt>p</tt>.
- * @throws NoQuadraticResidueException if <tt>a</tt> is a quadratic non-residue modulo <tt>p</tt>
- */
- public static BigInteger ressol(BigInteger a, BigInteger p)
- throws IllegalArgumentException
- {
-
- BigInteger v = null;
-
- if (a.compareTo(ZERO) < 0)
- {
- a = a.add(p);
- }
-
- if (a.equals(ZERO))
- {
- return ZERO;
- }
-
- if (p.equals(TWO))
- {
- return a;
- }
-
- // p = 3 mod 4
- if (p.testBit(0) && p.testBit(1))
- {
- if (jacobi(a, p) == 1)
- { // a quadr. residue mod p
- v = p.add(ONE); // v = p+1
- v = v.shiftRight(2); // v = v/4
- return a.modPow(v, p); // return a^v mod p
- // return --> a^((p+1)/4) mod p
- }
- throw new IllegalArgumentException("No quadratic residue: " + a + ", " + p);
- }
-
- long t = 0;
-
- // initialization
- // compute k and s, where p = 2^s (2k+1) +1
-
- BigInteger k = p.subtract(ONE); // k = p-1
- long s = 0;
- while (!k.testBit(0))
- { // while k is even
- s++; // s = s+1
- k = k.shiftRight(1); // k = k/2
- }
-
- k = k.subtract(ONE); // k = k - 1
- k = k.shiftRight(1); // k = k/2
-
- // initial values
- BigInteger r = a.modPow(k, p); // r = a^k mod p
-
- BigInteger n = r.multiply(r).remainder(p); // n = r^2 % p
- n = n.multiply(a).remainder(p); // n = n * a % p
- r = r.multiply(a).remainder(p); // r = r * a %p
-
- if (n.equals(ONE))
- {
- return r;
- }
-
- // non-quadratic residue
- BigInteger z = TWO; // z = 2
- while (jacobi(z, p) == 1)
- {
- // while z quadratic residue
- z = z.add(ONE); // z = z + 1
- }
-
- v = k;
- v = v.multiply(TWO); // v = 2k
- v = v.add(ONE); // v = 2k + 1
- BigInteger c = z.modPow(v, p); // c = z^v mod p
-
- // iteration
- while (n.compareTo(ONE) == 1)
- { // n > 1
- k = n; // k = n
- t = s; // t = s
- s = 0;
-
- while (!k.equals(ONE))
- { // k != 1
- k = k.multiply(k).mod(p); // k = k^2 % p
- s++; // s = s + 1
- }
-
- t -= s; // t = t - s
- if (t == 0)
- {
- throw new IllegalArgumentException("No quadratic residue: " + a + ", " + p);
- }
-
- v = ONE;
- for (long i = 0; i < t - 1; i++)
- {
- v = v.shiftLeft(1); // v = 1 * 2^(t - 1)
- }
- c = c.modPow(v, p); // c = c^v mod p
- r = r.multiply(c).remainder(p); // r = r * c % p
- c = c.multiply(c).remainder(p); // c = c^2 % p
- n = n.multiply(c).mod(p); // n = n * c % p
- }
- return r;
- }
-
- /**
- * Computes the greatest common divisor of the two specified integers
- *
- * @param u - first integer
- * @param v - second integer
- * @return gcd(a, b)
- */
- public static int gcd(int u, int v)
- {
- return BigInteger.valueOf(u).gcd(BigInteger.valueOf(v)).intValue();
- }
-
- /**
- * Extended euclidian algorithm (computes gcd and representation).
- *
- * @param a the first integer
- * @param b the second integer
- * @return <tt>(g,u,v)</tt>, where <tt>g = gcd(abs(a),abs(b)) = ua + vb</tt>
- */
- public static int[] extGCD(int a, int b)
- {
- BigInteger ba = BigInteger.valueOf(a);
- BigInteger bb = BigInteger.valueOf(b);
- BigInteger[] bresult = extgcd(ba, bb);
- int[] result = new int[3];
- result[0] = bresult[0].intValue();
- result[1] = bresult[1].intValue();
- result[2] = bresult[2].intValue();
- return result;
- }
-
- public static BigInteger divideAndRound(BigInteger a, BigInteger b)
- {
- if (a.signum() < 0)
- {
- return divideAndRound(a.negate(), b).negate();
- }
- if (b.signum() < 0)
- {
- return divideAndRound(a, b.negate()).negate();
- }
- return a.shiftLeft(1).add(b).divide(b.shiftLeft(1));
- }
-
- public static BigInteger[] divideAndRound(BigInteger[] a, BigInteger b)
- {
- BigInteger[] out = new BigInteger[a.length];
- for (int i = 0; i < a.length; i++)
- {
- out[i] = divideAndRound(a[i], b);
- }
- return out;
- }
-
- /**
- * Compute the smallest integer that is greater than or equal to the
- * logarithm to the base 2 of the given BigInteger.
- *
- * @param a the integer
- * @return ceil[log(a)]
- */
- public static int ceilLog(BigInteger a)
- {
- int result = 0;
- BigInteger p = ONE;
- while (p.compareTo(a) < 0)
- {
- result++;
- p = p.shiftLeft(1);
- }
- return result;
- }
-
- /**
- * Compute the smallest integer that is greater than or equal to the
- * logarithm to the base 2 of the given integer.
- *
- * @param a the integer
- * @return ceil[log(a)]
- */
- public static int ceilLog(int a)
- {
- int log = 0;
- int i = 1;
- while (i < a)
- {
- i <<= 1;
- log++;
- }
- return log;
- }
-
- /**
- * Compute <tt>ceil(log_256 n)</tt>, the number of bytes needed to encode
- * the integer <tt>n</tt>.
- *
- * @param n the integer
- * @return the number of bytes needed to encode <tt>n</tt>
- */
- public static int ceilLog256(int n)
- {
- if (n == 0)
- {
- return 1;
- }
- int m;
- if (n < 0)
- {
- m = -n;
- }
- else
- {
- m = n;
- }
-
- int d = 0;
- while (m > 0)
- {
- d++;
- m >>>= 8;
- }
- return d;
- }
-
- /**
- * Compute <tt>ceil(log_256 n)</tt>, the number of bytes needed to encode
- * the long integer <tt>n</tt>.
- *
- * @param n the long integer
- * @return the number of bytes needed to encode <tt>n</tt>
- */
- public static int ceilLog256(long n)
- {
- if (n == 0)
- {
- return 1;
- }
- long m;
- if (n < 0)
- {
- m = -n;
- }
- else
- {
- m = n;
- }
-
- int d = 0;
- while (m > 0)
- {
- d++;
- m >>>= 8;
- }
- return d;
- }
-
- /**
- * Compute the integer part of the logarithm to the base 2 of the given
- * integer.
- *
- * @param a the integer
- * @return floor[log(a)]
- */
- public static int floorLog(BigInteger a)
- {
- int result = -1;
- BigInteger p = ONE;
- while (p.compareTo(a) <= 0)
- {
- result++;
- p = p.shiftLeft(1);
- }
- return result;
- }
-
- /**
- * Compute the integer part of the logarithm to the base 2 of the given
- * integer.
- *
- * @param a the integer
- * @return floor[log(a)]
- */
- public static int floorLog(int a)
- {
- int h = 0;
- if (a <= 0)
- {
- return -1;
- }
- int p = a >>> 1;
- while (p > 0)
- {
- h++;
- p >>>= 1;
- }
-
- return h;
- }
-
- /**
- * Compute the largest <tt>h</tt> with <tt>2^h | a</tt> if <tt>a!=0</tt>.
- *
- * @param a an integer
- * @return the largest <tt>h</tt> with <tt>2^h | a</tt> if <tt>a!=0</tt>,
- * <tt>0</tt> otherwise
- */
- public static int maxPower(int a)
- {
- int h = 0;
- if (a != 0)
- {
- int p = 1;
- while ((a & p) == 0)
- {
- h++;
- p <<= 1;
- }
- }
-
- return h;
- }
-
- /**
- * @param a an integer
- * @return the number of ones in the binary representation of an integer
- * <tt>a</tt>
- */
- public static int bitCount(int a)
- {
- int h = 0;
- while (a != 0)
- {
- h += a & 1;
- a >>>= 1;
- }
-
- return h;
- }
-
- /**
- * determines the order of g modulo p, p prime and 1 &lt; g &lt; p. This algorithm
- * is only efficient for small p (see X9.62-1998, p. 68).
- *
- * @param g an integer with 1 &lt; g &lt; p
- * @param p a prime
- * @return the order k of g (that is k is the smallest integer with
- * g<sup>k</sup> = 1 mod p
- */
- public static int order(int g, int p)
- {
- int b, j;
-
- b = g % p; // Reduce g mod p first.
- j = 1;
-
- // Check whether g == 0 mod p (avoiding endless loop).
- if (b == 0)
- {
- throw new IllegalArgumentException(g + " is not an element of Z/("
- + p + "Z)^*; it is not meaningful to compute its order.");
- }
-
- // Compute the order of g mod p:
- while (b != 1)
- {
- b *= g;
- b %= p;
- if (b < 0)
- {
- b += p;
- }
- j++;
- }
-
- return j;
- }
-
- /**
- * Reduces an integer into a given interval
- *
- * @param n - the integer
- * @param begin - left bound of the interval
- * @param end - right bound of the interval
- * @return <tt>n</tt> reduced into <tt>[begin,end]</tt>
- */
- public static BigInteger reduceInto(BigInteger n, BigInteger begin,
- BigInteger end)
- {
- return n.subtract(begin).mod(end.subtract(begin)).add(begin);
- }
-
- /**
- * Compute <tt>a<sup>e</sup></tt>.
- *
- * @param a the base
- * @param e the exponent
- * @return <tt>a<sup>e</sup></tt>
- */
- public static int pow(int a, int e)
- {
- int result = 1;
- while (e > 0)
- {
- if ((e & 1) == 1)
- {
- result *= a;
- }
- a *= a;
- e >>>= 1;
- }
- return result;
- }
-
- /**
- * Compute <tt>a<sup>e</sup></tt>.
- *
- * @param a the base
- * @param e the exponent
- * @return <tt>a<sup>e</sup></tt>
- */
- public static long pow(long a, int e)
- {
- long result = 1;
- while (e > 0)
- {
- if ((e & 1) == 1)
- {
- result *= a;
- }
- a *= a;
- e >>>= 1;
- }
- return result;
- }
-
- /**
- * Compute <tt>a<sup>e</sup> mod n</tt>.
- *
- * @param a the base
- * @param e the exponent
- * @param n the modulus
- * @return <tt>a<sup>e</sup> mod n</tt>
- */
- public static int modPow(int a, int e, int n)
- {
- if (n <= 0 || (n * n) > Integer.MAX_VALUE || e < 0)
- {
- return 0;
- }
- int result = 1;
- a = (a % n + n) % n;
- while (e > 0)
- {
- if ((e & 1) == 1)
- {
- result = (result * a) % n;
- }
- a = (a * a) % n;
- e >>>= 1;
- }
- return result;
- }
-
- /**
- * Extended euclidian algorithm (computes gcd and representation).
- *
- * @param a - the first integer
- * @param b - the second integer
- * @return <tt>(d,u,v)</tt>, where <tt>d = gcd(a,b) = ua + vb</tt>
- */
- public static BigInteger[] extgcd(BigInteger a, BigInteger b)
- {
- BigInteger u = ONE;
- BigInteger v = ZERO;
- BigInteger d = a;
- if (b.signum() != 0)
- {
- BigInteger v1 = ZERO;
- BigInteger v3 = b;
- while (v3.signum() != 0)
- {
- BigInteger[] tmp = d.divideAndRemainder(v3);
- BigInteger q = tmp[0];
- BigInteger t3 = tmp[1];
- BigInteger t1 = u.subtract(q.multiply(v1));
- u = v1;
- d = v3;
- v1 = t1;
- v3 = t3;
- }
- v = d.subtract(a.multiply(u)).divide(b);
- }
- return new BigInteger[]{d, u, v};
- }
-
- /**
- * Computation of the least common multiple of a set of BigIntegers.
- *
- * @param numbers - the set of numbers
- * @return the lcm(numbers)
- */
- public static BigInteger leastCommonMultiple(BigInteger[] numbers)
- {
- int n = numbers.length;
- BigInteger result = numbers[0];
- for (int i = 1; i < n; i++)
- {
- BigInteger gcd = result.gcd(numbers[i]);
- result = result.multiply(numbers[i]).divide(gcd);
- }
- return result;
- }
-
- /**
- * Returns a long integer whose value is <tt>(a mod m</tt>). This method
- * differs from <tt>%</tt> in that it always returns a <i>non-negative</i>
- * integer.
- *
- * @param a value on which the modulo operation has to be performed.
- * @param m the modulus.
- * @return <tt>a mod m</tt>
- */
- public static long mod(long a, long m)
- {
- long result = a % m;
- if (result < 0)
- {
- result += m;
- }
- return result;
- }
-
- /**
- * Computes the modular inverse of an integer a
- *
- * @param a - the integer to invert
- * @param mod - the modulus
- * @return <tt>a<sup>-1</sup> mod n</tt>
- */
- public static int modInverse(int a, int mod)
- {
- return BigInteger.valueOf(a).modInverse(BigInteger.valueOf(mod))
- .intValue();
- }
-
- /**
- * Computes the modular inverse of an integer a
- *
- * @param a - the integer to invert
- * @param mod - the modulus
- * @return <tt>a<sup>-1</sup> mod n</tt>
- */
- public static long modInverse(long a, long mod)
- {
- return BigInteger.valueOf(a).modInverse(BigInteger.valueOf(mod))
- .longValue();
- }
-
- /**
- * Tests whether an integer <tt>a</tt> is power of another integer
- * <tt>p</tt>.
- *
- * @param a - the first integer
- * @param p - the second integer
- * @return n if a = p^n or -1 otherwise
- */
- public static int isPower(int a, int p)
- {
- if (a <= 0)
- {
- return -1;
- }
- int n = 0;
- int d = a;
- while (d > 1)
- {
- if (d % p != 0)
- {
- return -1;
- }
- d /= p;
- n++;
- }
- return n;
- }
-
- /**
- * Find and return the least non-trivial divisor of an integer <tt>a</tt>.
- *
- * @param a - the integer
- * @return divisor p &gt;1 or 1 if a = -1,0,1
- */
- public static int leastDiv(int a)
- {
- if (a < 0)
- {
- a = -a;
- }
- if (a == 0)
- {
- return 1;
- }
- if ((a & 1) == 0)
- {
- return 2;
- }
- int p = 3;
- while (p <= (a / p))
- {
- if ((a % p) == 0)
- {
- return p;
- }
- p += 2;
- }
-
- return a;
- }
-
- /**
- * Miller-Rabin-Test, determines wether the given integer is probably prime
- * or composite. This method returns <tt>true</tt> if the given integer is
- * prime with probability <tt>1 - 2<sup>-20</sup></tt>.
- *
- * @param n the integer to test for primality
- * @return <tt>true</tt> if the given integer is prime with probability
- * 2<sup>-100</sup>, <tt>false</tt> otherwise
- */
- public static boolean isPrime(int n)
- {
- if (n < 2)
- {
- return false;
- }
- if (n == 2)
- {
- return true;
- }
- if ((n & 1) == 0)
- {
- return false;
- }
- if (n < 42)
- {
- for (int i = 0; i < SMALL_PRIMES.length; i++)
- {
- if (n == SMALL_PRIMES[i])
- {
- return true;
- }
- }
- }
-
- if ((n % 3 == 0) || (n % 5 == 0) || (n % 7 == 0) || (n % 11 == 0)
- || (n % 13 == 0) || (n % 17 == 0) || (n % 19 == 0)
- || (n % 23 == 0) || (n % 29 == 0) || (n % 31 == 0)
- || (n % 37 == 0) || (n % 41 == 0))
- {
- return false;
- }
-
- return BigInteger.valueOf(n).isProbablePrime(20);
- }
-
- /**
- * Short trial-division test to find out whether a number is not prime. This
- * test is usually used before a Miller-Rabin primality test.
- *
- * @param candidate the number to test
- * @return <tt>true</tt> if the number has no factor of the tested primes,
- * <tt>false</tt> if the number is definitely composite
- */
- public static boolean passesSmallPrimeTest(BigInteger candidate)
- {
- final int[] smallPrime = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37,
- 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103,
- 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167,
- 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
- 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307,
- 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379,
- 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449,
- 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523,
- 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607,
- 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677,
- 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761,
- 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853,
- 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937,
- 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019,
- 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087,
- 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153,
- 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229,
- 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297,
- 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381,
- 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453,
- 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499};
-
- for (int i = 0; i < smallPrime.length; i++)
- {
- if (candidate.mod(BigInteger.valueOf(smallPrime[i])).equals(
- ZERO))
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Returns the largest prime smaller than the given integer
- *
- * @param n - upper bound
- * @return the largest prime smaller than <tt>n</tt>, or <tt>1</tt> if
- * <tt>n &lt;= 2</tt>
- */
- public static int nextSmallerPrime(int n)
- {
- if (n <= 2)
- {
- return 1;
- }
-
- if (n == 3)
- {
- return 2;
- }
-
- if ((n & 1) == 0)
- {
- n--;
- }
- else
- {
- n -= 2;
- }
-
- while (n > 3 & !isPrime(n))
- {
- n -= 2;
- }
- return n;
- }
-
- /**
- * Compute the next probable prime greater than <tt>n</tt> with the
- * specified certainty.
- *
- * @param n a integer number
- * @param certainty the certainty that the generated number is prime
- * @return the next prime greater than <tt>n</tt>
- */
- public static BigInteger nextProbablePrime(BigInteger n, int certainty)
- {
-
- if (n.signum() < 0 || n.signum() == 0 || n.equals(ONE))
- {
- return TWO;
- }
-
- BigInteger result = n.add(ONE);
-
- // Ensure an odd number
- if (!result.testBit(0))
- {
- result = result.add(ONE);
- }
-
- while (true)
- {
- // Do cheap "pre-test" if applicable
- if (result.bitLength() > 6)
- {
- long r = result.remainder(
- BigInteger.valueOf(SMALL_PRIME_PRODUCT)).longValue();
- if ((r % 3 == 0) || (r % 5 == 0) || (r % 7 == 0)
- || (r % 11 == 0) || (r % 13 == 0) || (r % 17 == 0)
- || (r % 19 == 0) || (r % 23 == 0) || (r % 29 == 0)
- || (r % 31 == 0) || (r % 37 == 0) || (r % 41 == 0))
- {
- result = result.add(TWO);
- continue; // Candidate is composite; try another
- }
- }
-
- // All candidates of bitLength 2 and 3 are prime by this point
- if (result.bitLength() < 4)
- {
- return result;
- }
-
- // The expensive test
- if (result.isProbablePrime(certainty))
- {
- return result;
- }
-
- result = result.add(TWO);
- }
- }
-
- /**
- * Compute the next probable prime greater than <tt>n</tt> with the default
- * certainty (20).
- *
- * @param n a integer number
- * @return the next prime greater than <tt>n</tt>
- */
- public static BigInteger nextProbablePrime(BigInteger n)
- {
- return nextProbablePrime(n, 20);
- }
-
- /**
- * Computes the next prime greater than n.
- *
- * @param n a integer number
- * @return the next prime greater than n
- */
- public static BigInteger nextPrime(long n)
- {
- long i;
- boolean found = false;
- long result = 0;
-
- if (n <= 1)
- {
- return BigInteger.valueOf(2);
- }
- if (n == 2)
- {
- return BigInteger.valueOf(3);
- }
-
- for (i = n + 1 + (n & 1); (i <= n << 1) && !found; i += 2)
- {
- for (long j = 3; (j <= i >> 1) && !found; j += 2)
- {
- if (i % j == 0)
- {
- found = true;
- }
- }
- if (found)
- {
- found = false;
- }
- else
- {
- result = i;
- found = true;
- }
- }
- return BigInteger.valueOf(result);
- }
-
- /**
- * Computes the binomial coefficient (n|t) ("n over t"). Formula:
- * <ul>
- * <li>if n !=0 and t != 0 then (n|t) = Mult(i=1, t): (n-(i-1))/i</li>
- * <li>if t = 0 then (n|t) = 1</li>
- * <li>if n = 0 and t &gt; 0 then (n|t) = 0</li>
- * </ul>
- *
- * @param n - the "upper" integer
- * @param t - the "lower" integer
- * @return the binomialcoefficient "n over t" as BigInteger
- */
- public static BigInteger binomial(int n, int t)
- {
-
- BigInteger result = ONE;
-
- if (n == 0)
- {
- if (t == 0)
- {
- return result;
- }
- return ZERO;
- }
-
- // the property (n|t) = (n|n-t) be used to reduce numbers of operations
- if (t > (n >>> 1))
- {
- t = n - t;
- }
-
- for (int i = 1; i <= t; i++)
- {
- result = (result.multiply(BigInteger.valueOf(n - (i - 1))))
- .divide(BigInteger.valueOf(i));
- }
-
- return result;
- }
-
- public static BigInteger randomize(BigInteger upperBound)
- {
- if (sr == null)
- {
- sr = new SecureRandom();
- }
- return randomize(upperBound, sr);
- }
-
- public static BigInteger randomize(BigInteger upperBound,
- SecureRandom prng)
- {
- int blen = upperBound.bitLength();
- BigInteger randomNum = BigInteger.valueOf(0);
-
- if (prng == null)
- {
- prng = sr != null ? sr : new SecureRandom();
- }
-
- for (int i = 0; i < 20; i++)
- {
- randomNum = new BigInteger(blen, prng);
- if (randomNum.compareTo(upperBound) < 0)
- {
- return randomNum;
- }
- }
- return randomNum.mod(upperBound);
- }
-
- /**
- * Extract the truncated square root of a BigInteger.
- *
- * @param a - value out of which we extract the square root
- * @return the truncated square root of <tt>a</tt>
- */
- public static BigInteger squareRoot(BigInteger a)
- {
- int bl;
- BigInteger result, remainder, b;
-
- if (a.compareTo(ZERO) < 0)
- {
- throw new ArithmeticException(
- "cannot extract root of negative number" + a + ".");
- }
-
- bl = a.bitLength();
- result = ZERO;
- remainder = ZERO;
-
- // if the bit length is odd then extra step
- if ((bl & 1) != 0)
- {
- result = result.add(ONE);
- bl--;
- }
-
- while (bl > 0)
- {
- remainder = remainder.multiply(FOUR);
- remainder = remainder.add(BigInteger.valueOf((a.testBit(--bl) ? 2
- : 0)
- + (a.testBit(--bl) ? 1 : 0)));
- b = result.multiply(FOUR).add(ONE);
- result = result.multiply(TWO);
- if (remainder.compareTo(b) != -1)
- {
- result = result.add(ONE);
- remainder = remainder.subtract(b);
- }
- }
-
- return result;
- }
-
- /**
- * Takes an approximation of the root from an integer base, using newton's
- * algorithm
- *
- * @param base the base to take the root from
- * @param root the root, for example 2 for a square root
- */
- public static float intRoot(int base, int root)
- {
- float gNew = base / root;
- float gOld = 0;
- int counter = 0;
- while (Math.abs(gOld - gNew) > 0.0001)
- {
- float gPow = floatPow(gNew, root);
- while (Float.isInfinite(gPow))
- {
- gNew = (gNew + gOld) / 2;
- gPow = floatPow(gNew, root);
- }
- counter += 1;
- gOld = gNew;
- gNew = gOld - (gPow - base) / (root * floatPow(gOld, root - 1));
- }
- return gNew;
- }
-
- /**
- * Calculation of a logarithmus of a float param
- *
- * @param param
- * @return
- */
- public static float floatLog(float param)
- {
- double arg = (param - 1) / (param + 1);
- double arg2 = arg;
- int counter = 1;
- float result = (float)arg;
-
- while (arg2 > 0.001)
- {
- counter += 2;
- arg2 *= arg * arg;
- result += (1. / counter) * arg2;
- }
- return 2 * result;
- }
-
- /**
- * int power of a base float, only use for small ints
- *
- * @param f
- * @param i
- * @return
- */
- public static float floatPow(float f, int i)
- {
- float g = 1;
- for (; i > 0; i--)
- {
- g *= f;
- }
- return g;
- }
-
- /**
- * calculate the logarithm to the base 2.
- *
- * @param x any double value
- * @return log_2(x)
- * @deprecated use MathFunctions.log(double) instead
- */
- public static double log(double x)
- {
- if (x > 0 && x < 1)
- {
- double d = 1 / x;
- double result = -log(d);
- return result;
- }
-
- int tmp = 0;
- double tmp2 = 1;
- double d = x;
-
- while (d > 2)
- {
- d = d / 2;
- tmp += 1;
- tmp2 *= 2;
- }
- double rem = x / tmp2;
- rem = logBKM(rem);
- return tmp + rem;
- }
-
- /**
- * calculate the logarithm to the base 2.
- *
- * @param x any long value &gt;=1
- * @return log_2(x)
- * @deprecated use MathFunctions.log(long) instead
- */
- public static double log(long x)
- {
- int tmp = floorLog(BigInteger.valueOf(x));
- long tmp2 = 1 << tmp;
- double rem = (double)x / (double)tmp2;
- rem = logBKM(rem);
- return tmp + rem;
- }
-
- /**
- * BKM Algorithm to calculate logarithms to the base 2.
- *
- * @param arg a double value with 1<= arg<= 4.768462058
- * @return log_2(arg)
- * @deprecated use MathFunctions.logBKM(double) instead
- */
- private static double logBKM(double arg)
- {
- double ae[] = // A_e[k] = log_2 (1 + 0.5^k)
- {
- 1.0000000000000000000000000000000000000000000000000000000000000000000000000000,
- 0.5849625007211561814537389439478165087598144076924810604557526545410982276485,
- 0.3219280948873623478703194294893901758648313930245806120547563958159347765589,
- 0.1699250014423123629074778878956330175196288153849621209115053090821964552970,
- 0.0874628412503394082540660108104043540112672823448206881266090643866965081686,
- 0.0443941193584534376531019906736094674630459333742491317685543002674288465967,
- 0.0223678130284545082671320837460849094932677948156179815932199216587899627785,
- 0.0112272554232541203378805844158839407281095943600297940811823651462712311786,
- 0.0056245491938781069198591026740666017211096815383520359072957784732489771013,
- 0.0028150156070540381547362547502839489729507927389771959487826944878598909400,
- 0.0014081943928083889066101665016890524233311715793462235597709051792834906001,
- 0.0007042690112466432585379340422201964456668872087249334581924550139514213168,
- 0.0003521774803010272377989609925281744988670304302127133979341729842842377649,
- 0.0001760994864425060348637509459678580940163670081839283659942864068257522373,
- 0.0000880524301221769086378699983597183301490534085738474534831071719854721939,
- 0.0000440268868273167176441087067175806394819146645511899503059774914593663365,
- 0.0000220136113603404964890728830697555571275493801909791504158295359319433723,
- 0.0000110068476674814423006223021573490183469930819844945565597452748333526464,
- 0.0000055034343306486037230640321058826431606183125807276574241540303833251704,
- 0.0000027517197895612831123023958331509538486493412831626219340570294203116559,
- 0.0000013758605508411382010566802834037147561973553922354232704569052932922954,
- 0.0000006879304394358496786728937442939160483304056131990916985043387874690617,
- 0.0000003439652607217645360118314743718005315334062644619363447395987584138324,
- 0.0000001719826406118446361936972479533123619972434705828085978955697643547921,
- 0.0000000859913228686632156462565208266682841603921494181830811515318381744650,
- 0.0000000429956620750168703982940244684787907148132725669106053076409624949917,
- 0.0000000214978311976797556164155504126645192380395989504741781512309853438587,
- 0.0000000107489156388827085092095702361647949603617203979413516082280717515504,
- 0.0000000053744578294520620044408178949217773318785601260677517784797554422804,
- 0.0000000026872289172287079490026152352638891824761667284401180026908031182361,
- 0.0000000013436144592400232123622589569799954658536700992739887706412976115422,
- 0.0000000006718072297764289157920422846078078155859484240808550018085324187007,
- 0.0000000003359036149273187853169587152657145221968468364663464125722491530858,
- 0.0000000001679518074734354745159899223037458278711244127245990591908996412262,
- 0.0000000000839759037391617577226571237484864917411614198675604731728132152582,
- 0.0000000000419879518701918839775296677020135040214077417929807824842667285938,
- 0.0000000000209939759352486932678195559552767641474249812845414125580747434389,
- 0.0000000000104969879676625344536740142096218372850561859495065136990936290929,
- 0.0000000000052484939838408141817781356260462777942148580518406975851213868092,
- 0.0000000000026242469919227938296243586262369156865545638305682553644113887909,
- 0.0000000000013121234959619935994960031017850191710121890821178731821983105443,
- 0.0000000000006560617479811459709189576337295395590603644549624717910616347038,
- 0.0000000000003280308739906102782522178545328259781415615142931952662153623493,
- 0.0000000000001640154369953144623242936888032768768777422997704541618141646683,
- 0.0000000000000820077184976595619616930350508356401599552034612281802599177300,
- 0.0000000000000410038592488303636807330652208397742314215159774270270147020117,
- 0.0000000000000205019296244153275153381695384157073687186580546938331088730952,
- 0.0000000000000102509648122077001764119940017243502120046885379813510430378661,
- 0.0000000000000051254824061038591928917243090559919209628584150482483994782302,
- 0.0000000000000025627412030519318726172939815845367496027046030028595094737777,
- 0.0000000000000012813706015259665053515049475574143952543145124550608158430592,
- 0.0000000000000006406853007629833949364669629701200556369782295210193569318434,
- 0.0000000000000003203426503814917330334121037829290364330169106716787999052925,
- 0.0000000000000001601713251907458754080007074659337446341494733882570243497196,
- 0.0000000000000000800856625953729399268240176265844257044861248416330071223615,
- 0.0000000000000000400428312976864705191179247866966320469710511619971334577509,
- 0.0000000000000000200214156488432353984854413866994246781519154793320684126179,
- 0.0000000000000000100107078244216177339743404416874899847406043033792202127070,
- 0.0000000000000000050053539122108088756700751579281894640362199287591340285355,
- 0.0000000000000000025026769561054044400057638132352058574658089256646014899499,
- 0.0000000000000000012513384780527022205455634651853807110362316427807660551208,
- 0.0000000000000000006256692390263511104084521222346348012116229213309001913762,
- 0.0000000000000000003128346195131755552381436585278035120438976487697544916191,
- 0.0000000000000000001564173097565877776275512286165232838833090480508502328437,
- 0.0000000000000000000782086548782938888158954641464170239072244145219054734086,
- 0.0000000000000000000391043274391469444084776945327473574450334092075712154016,
- 0.0000000000000000000195521637195734722043713378812583900953755962557525252782,
- 0.0000000000000000000097760818597867361022187915943503728909029699365320287407,
- 0.0000000000000000000048880409298933680511176764606054809062553340323879609794,
- 0.0000000000000000000024440204649466840255609083961603140683286362962192177597,
- 0.0000000000000000000012220102324733420127809717395445504379645613448652614939,
- 0.0000000000000000000006110051162366710063906152551383735699323415812152114058,
- 0.0000000000000000000003055025581183355031953399739107113727036860315024588989,
- 0.0000000000000000000001527512790591677515976780735407368332862218276873443537,
- 0.0000000000000000000000763756395295838757988410584167137033767056170417508383,
- 0.0000000000000000000000381878197647919378994210346199431733717514843471513618,
- 0.0000000000000000000000190939098823959689497106436628681671067254111334889005,
- 0.0000000000000000000000095469549411979844748553534196582286585751228071408728,
- 0.0000000000000000000000047734774705989922374276846068851506055906657137209047,
- 0.0000000000000000000000023867387352994961187138442777065843718711089344045782,
- 0.0000000000000000000000011933693676497480593569226324192944532044984865894525,
- 0.0000000000000000000000005966846838248740296784614396011477934194852481410926,
- 0.0000000000000000000000002983423419124370148392307506484490384140516252814304,
- 0.0000000000000000000000001491711709562185074196153830361933046331030629430117,
- 0.0000000000000000000000000745855854781092537098076934460888486730708440475045,
- 0.0000000000000000000000000372927927390546268549038472050424734256652501673274,
- 0.0000000000000000000000000186463963695273134274519237230207489851150821191330,
- 0.0000000000000000000000000093231981847636567137259618916352525606281553180093,
- 0.0000000000000000000000000046615990923818283568629809533488457973317312233323,
- 0.0000000000000000000000000023307995461909141784314904785572277779202790023236,
- 0.0000000000000000000000000011653997730954570892157452397493151087737428485431,
- 0.0000000000000000000000000005826998865477285446078726199923328593402722606924,
- 0.0000000000000000000000000002913499432738642723039363100255852559084863397344,
- 0.0000000000000000000000000001456749716369321361519681550201473345138307215067,
- 0.0000000000000000000000000000728374858184660680759840775119123438968122488047,
- 0.0000000000000000000000000000364187429092330340379920387564158411083803465567,
- 0.0000000000000000000000000000182093714546165170189960193783228378441837282509,
- 0.0000000000000000000000000000091046857273082585094980096891901482445902524441,
- 0.0000000000000000000000000000045523428636541292547490048446022564529197237262,
- 0.0000000000000000000000000000022761714318270646273745024223029238091160103901};
- int n = 53;
- double x = 1;
- double y = 0;
- double z;
- double s = 1;
- int k;
-
- for (k = 0; k < n; k++)
- {
- z = x + x * s;
- if (z <= arg)
- {
- x = z;
- y += ae[k];
- }
- s *= 0.5;
- }
- return y;
- }
-
- public static boolean isIncreasing(int[] a)
- {
- for (int i = 1; i < a.length; i++)
- {
- if (a[i - 1] >= a[i])
- {
- System.out.println("a[" + (i - 1) + "] = " + a[i - 1] + " >= "
- + a[i] + " = a[" + i + "]");
- return false;
- }
- }
- return true;
- }
-
- public static byte[] integerToOctets(BigInteger val)
- {
- byte[] valBytes = val.abs().toByteArray();
-
- // check whether the array includes a sign bit
- if ((val.bitLength() & 7) != 0)
- {
- return valBytes;
- }
- // get rid of the sign bit (first byte)
- byte[] tmp = new byte[val.bitLength() >> 3];
- System.arraycopy(valBytes, 1, tmp, 0, tmp.length);
- return tmp;
- }
-
- public static BigInteger octetsToInteger(byte[] data, int offset,
- int length)
- {
- byte[] val = new byte[length + 1];
-
- val[0] = 0;
- System.arraycopy(data, offset, val, 1, length);
- return new BigInteger(val);
- }
-
- public static BigInteger octetsToInteger(byte[] data)
- {
- return octetsToInteger(data, 0, data.length);
- }
-
- public static void main(String[] args)
- {
- System.out.println("test");
- // System.out.println(intRoot(37, 5));
- // System.out.println(floatPow((float)2.5, 4));
- System.out.println(floatLog(10));
- System.out.println("test2");
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/LittleEndianConversions.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/LittleEndianConversions.java
deleted file mode 100644
index c97fdc58..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/LittleEndianConversions.java
+++ /dev/null
@@ -1,230 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-/**
- * This is a utility class containing data type conversions using little-endian
- * byte order.
- *
- * @see BigEndianConversions
- */
-public final class LittleEndianConversions
-{
-
- /**
- * Default constructor (private).
- */
- private LittleEndianConversions()
- {
- // empty
- }
-
- /**
- * Convert an octet string of length 4 to an integer. No length checking is
- * performed.
- *
- * @param input the byte array holding the octet string
- * @return an integer representing the octet string <tt>input</tt>
- * @throws ArithmeticException if the length of the given octet string is larger than 4.
- */
- public static int OS2IP(byte[] input)
- {
- return ((input[0] & 0xff)) | ((input[1] & 0xff) << 8)
- | ((input[2] & 0xff) << 16) | ((input[3] & 0xff)) << 24;
- }
-
- /**
- * Convert an byte array of length 4 beginning at <tt>offset</tt> into an
- * integer.
- *
- * @param input the byte array
- * @param inOff the offset into the byte array
- * @return the resulting integer
- */
- public static int OS2IP(byte[] input, int inOff)
- {
- int result = input[inOff++] & 0xff;
- result |= (input[inOff++] & 0xff) << 8;
- result |= (input[inOff++] & 0xff) << 16;
- result |= (input[inOff] & 0xff) << 24;
- return result;
- }
-
- /**
- * Convert a byte array of the given length beginning at <tt>offset</tt>
- * into an integer.
- *
- * @param input the byte array
- * @param inOff the offset into the byte array
- * @param inLen the length of the encoding
- * @return the resulting integer
- */
- public static int OS2IP(byte[] input, int inOff, int inLen)
- {
- int result = 0;
- for (int i = inLen - 1; i >= 0; i--)
- {
- result |= (input[inOff + i] & 0xff) << (8 * i);
- }
- return result;
- }
-
- /**
- * Convert a byte array of length 8 beginning at <tt>inOff</tt> into a
- * long integer.
- *
- * @param input the byte array
- * @param inOff the offset into the byte array
- * @return the resulting long integer
- */
- public static long OS2LIP(byte[] input, int inOff)
- {
- long result = input[inOff++] & 0xff;
- result |= (input[inOff++] & 0xff) << 8;
- result |= (input[inOff++] & 0xff) << 16;
- result |= ((long)input[inOff++] & 0xff) << 24;
- result |= ((long)input[inOff++] & 0xff) << 32;
- result |= ((long)input[inOff++] & 0xff) << 40;
- result |= ((long)input[inOff++] & 0xff) << 48;
- result |= ((long)input[inOff++] & 0xff) << 56;
- return result;
- }
-
- /**
- * Convert an integer to an octet string of length 4.
- *
- * @param x the integer to convert
- * @return the converted integer
- */
- public static byte[] I2OSP(int x)
- {
- byte[] result = new byte[4];
- result[0] = (byte)x;
- result[1] = (byte)(x >>> 8);
- result[2] = (byte)(x >>> 16);
- result[3] = (byte)(x >>> 24);
- return result;
- }
-
- /**
- * Convert an integer into a byte array beginning at the specified offset.
- *
- * @param value the integer to convert
- * @param output the byte array to hold the result
- * @param outOff the integer offset into the byte array
- */
- public static void I2OSP(int value, byte[] output, int outOff)
- {
- output[outOff++] = (byte)value;
- output[outOff++] = (byte)(value >>> 8);
- output[outOff++] = (byte)(value >>> 16);
- output[outOff++] = (byte)(value >>> 24);
- }
-
- /**
- * Convert an integer to a byte array beginning at the specified offset. No
- * length checking is performed (i.e., if the integer cannot be encoded with
- * <tt>length</tt> octets, it is truncated).
- *
- * @param value the integer to convert
- * @param output the byte array to hold the result
- * @param outOff the integer offset into the byte array
- * @param outLen the length of the encoding
- */
- public static void I2OSP(int value, byte[] output, int outOff, int outLen)
- {
- for (int i = outLen - 1; i >= 0; i--)
- {
- output[outOff + i] = (byte)(value >>> (8 * i));
- }
- }
-
- /**
- * Convert an integer to a byte array of length 8.
- *
- * @param input the integer to convert
- * @return the converted integer
- */
- public static byte[] I2OSP(long input)
- {
- byte[] output = new byte[8];
- output[0] = (byte)input;
- output[1] = (byte)(input >>> 8);
- output[2] = (byte)(input >>> 16);
- output[3] = (byte)(input >>> 24);
- output[4] = (byte)(input >>> 32);
- output[5] = (byte)(input >>> 40);
- output[6] = (byte)(input >>> 48);
- output[7] = (byte)(input >>> 56);
- return output;
- }
-
- /**
- * Convert an integer to a byte array of length 8.
- *
- * @param input the integer to convert
- * @param output byte array holding the output
- * @param outOff offset in output array where the result is stored
- */
- public static void I2OSP(long input, byte[] output, int outOff)
- {
- output[outOff++] = (byte)input;
- output[outOff++] = (byte)(input >>> 8);
- output[outOff++] = (byte)(input >>> 16);
- output[outOff++] = (byte)(input >>> 24);
- output[outOff++] = (byte)(input >>> 32);
- output[outOff++] = (byte)(input >>> 40);
- output[outOff++] = (byte)(input >>> 48);
- output[outOff] = (byte)(input >>> 56);
- }
-
- /**
- * Convert an int array to a byte array of the specified length. No length
- * checking is performed (i.e., if the last integer cannot be encoded with
- * <tt>length % 4</tt> octets, it is truncated).
- *
- * @param input the int array
- * @param outLen the length of the converted array
- * @return the converted array
- */
- public static byte[] toByteArray(int[] input, int outLen)
- {
- int intLen = input.length;
- byte[] result = new byte[outLen];
- int index = 0;
- for (int i = 0; i <= intLen - 2; i++, index += 4)
- {
- I2OSP(input[i], result, index);
- }
- I2OSP(input[intLen - 1], result, index, outLen - index);
- return result;
- }
-
- /**
- * Convert a byte array to an int array.
- *
- * @param input the byte array
- * @return the converted array
- */
- public static int[] toIntArray(byte[] input)
- {
- int intLen = (input.length + 3) / 4;
- int lastLen = input.length & 0x03;
- int[] result = new int[intLen];
-
- int index = 0;
- for (int i = 0; i <= intLen - 2; i++, index += 4)
- {
- result[i] = OS2IP(input, index);
- }
- if (lastLen != 0)
- {
- result[intLen - 1] = OS2IP(input, index, lastLen);
- }
- else
- {
- result[intLen - 1] = OS2IP(input, index);
- }
-
- return result;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Matrix.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Matrix.java
deleted file mode 100644
index 2c9a0eb6..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Matrix.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-/**
- * This abstract class defines matrices. It holds the number of rows and the
- * number of columns of the matrix and defines some basic methods.
- */
-public abstract class Matrix
-{
-
- /**
- * number of rows
- */
- protected int numRows;
-
- /**
- * number of columns
- */
- protected int numColumns;
-
- // ----------------------------------------------------
- // some constants (matrix types)
- // ----------------------------------------------------
-
- /**
- * zero matrix
- */
- public static final char MATRIX_TYPE_ZERO = 'Z';
-
- /**
- * unit matrix
- */
- public static final char MATRIX_TYPE_UNIT = 'I';
-
- /**
- * random lower triangular matrix
- */
- public static final char MATRIX_TYPE_RANDOM_LT = 'L';
-
- /**
- * random upper triangular matrix
- */
- public static final char MATRIX_TYPE_RANDOM_UT = 'U';
-
- /**
- * random regular matrix
- */
- public static final char MATRIX_TYPE_RANDOM_REGULAR = 'R';
-
- // ----------------------------------------------------
- // getters
- // ----------------------------------------------------
-
- /**
- * @return the number of rows in the matrix
- */
- public int getNumRows()
- {
- return numRows;
- }
-
- /**
- * @return the number of columns in the binary matrix
- */
- public int getNumColumns()
- {
- return numColumns;
- }
-
- /**
- * @return the encoded matrix, i.e., this matrix in byte array form.
- */
- public abstract byte[] getEncoded();
-
- // ----------------------------------------------------
- // arithmetic
- // ----------------------------------------------------
-
- /**
- * Compute the inverse of this matrix.
- *
- * @return the inverse of this matrix (newly created).
- */
- public abstract Matrix computeInverse();
-
- /**
- * Check if this is the zero matrix (i.e., all entries are zero).
- *
- * @return <tt>true</tt> if this is the zero matrix
- */
- public abstract boolean isZero();
-
- /**
- * Compute the product of this matrix and another matrix.
- *
- * @param a the other matrix
- * @return <tt>this * a</tt> (newly created)
- */
- public abstract Matrix rightMultiply(Matrix a);
-
- /**
- * Compute the product of this matrix and a permutation.
- *
- * @param p the permutation
- * @return <tt>this * p</tt> (newly created)
- */
- public abstract Matrix rightMultiply(Permutation p);
-
- /**
- * Compute the product of a vector and this matrix. If the length of the
- * vector is greater than the number of rows of this matrix, the matrix is
- * multiplied by each m-bit part of the vector.
- *
- * @param vector a vector
- * @return <tt>vector * this</tt> (newly created)
- */
- public abstract Vector leftMultiply(Vector vector);
-
- /**
- * Compute the product of this matrix and a vector.
- *
- * @param vector a vector
- * @return <tt>this * vector</tt> (newly created)
- */
- public abstract Vector rightMultiply(Vector vector);
-
- /**
- * @return a human readable form of the matrix.
- */
- public abstract String toString();
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Permutation.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Permutation.java
deleted file mode 100644
index 28b58d34..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Permutation.java
+++ /dev/null
@@ -1,247 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-import java.security.SecureRandom;
-
-/**
- * This class implements permutations of the set {0,1,...,n-1} for some given n
- * &gt; 0, i.e., ordered sequences containing each number <tt>m</tt> (<tt>0 &lt;=
- * m &lt; n</tt>)
- * once and only once.
- */
-public class Permutation
-{
-
- /**
- * perm holds the elements of the permutation vector, i.e. <tt>[perm(0),
- * perm(1), ..., perm(n-1)]</tt>
- */
- private int[] perm;
-
- /**
- * Create the identity permutation of the given size.
- *
- * @param n the size of the permutation
- */
- public Permutation(int n)
- {
- if (n <= 0)
- {
- throw new IllegalArgumentException("invalid length");
- }
-
- perm = new int[n];
- for (int i = n - 1; i >= 0; i--)
- {
- perm[i] = i;
- }
- }
-
- /**
- * Create a permutation using the given permutation vector.
- *
- * @param perm the permutation vector
- */
- public Permutation(int[] perm)
- {
- if (!isPermutation(perm))
- {
- throw new IllegalArgumentException(
- "array is not a permutation vector");
- }
-
- this.perm = IntUtils.clone(perm);
- }
-
- /**
- * Create a permutation from an encoded permutation.
- *
- * @param enc the encoded permutation
- */
- public Permutation(byte[] enc)
- {
- if (enc.length <= 4)
- {
- throw new IllegalArgumentException("invalid encoding");
- }
-
- int n = LittleEndianConversions.OS2IP(enc, 0);
- int size = IntegerFunctions.ceilLog256(n - 1);
-
- if (enc.length != 4 + n * size)
- {
- throw new IllegalArgumentException("invalid encoding");
- }
-
- perm = new int[n];
- for (int i = 0; i < n; i++)
- {
- perm[i] = LittleEndianConversions.OS2IP(enc, 4 + i * size, size);
- }
-
- if (!isPermutation(perm))
- {
- throw new IllegalArgumentException("invalid encoding");
- }
-
- }
-
- /**
- * Create a random permutation of the given size.
- *
- * @param n the size of the permutation
- * @param sr the source of randomness
- */
- public Permutation(int n, SecureRandom sr)
- {
- if (n <= 0)
- {
- throw new IllegalArgumentException("invalid length");
- }
-
- perm = new int[n];
-
- int[] help = new int[n];
- for (int i = 0; i < n; i++)
- {
- help[i] = i;
- }
-
- int k = n;
- for (int j = 0; j < n; j++)
- {
- int i = RandUtils.nextInt(sr, k);
- k--;
- perm[j] = help[i];
- help[i] = help[k];
- }
- }
-
- /**
- * Encode this permutation as byte array.
- *
- * @return the encoded permutation
- */
- public byte[] getEncoded()
- {
- int n = perm.length;
- int size = IntegerFunctions.ceilLog256(n - 1);
- byte[] result = new byte[4 + n * size];
- LittleEndianConversions.I2OSP(n, result, 0);
- for (int i = 0; i < n; i++)
- {
- LittleEndianConversions.I2OSP(perm[i], result, 4 + i * size, size);
- }
- return result;
- }
-
- /**
- * @return the permutation vector <tt>(perm(0),perm(1),...,perm(n-1))</tt>
- */
- public int[] getVector()
- {
- return IntUtils.clone(perm);
- }
-
- /**
- * Compute the inverse permutation <tt>P<sup>-1</sup></tt>.
- *
- * @return <tt>this<sup>-1</sup></tt>
- */
- public Permutation computeInverse()
- {
- Permutation result = new Permutation(perm.length);
- for (int i = perm.length - 1; i >= 0; i--)
- {
- result.perm[perm[i]] = i;
- }
- return result;
- }
-
- /**
- * Compute the product of this permutation and another permutation.
- *
- * @param p the other permutation
- * @return <tt>this * p</tt>
- */
- public Permutation rightMultiply(Permutation p)
- {
- if (p.perm.length != perm.length)
- {
- throw new IllegalArgumentException("length mismatch");
- }
- Permutation result = new Permutation(perm.length);
- for (int i = perm.length - 1; i >= 0; i--)
- {
- result.perm[i] = perm[p.perm[i]];
- }
- return result;
- }
-
- /**
- * checks if given object is equal to this permutation.
- * <p>
- * The method returns false whenever the given object is not permutation.
- *
- * @param other -
- * permutation
- * @return true or false
- */
- public boolean equals(Object other)
- {
-
- if (!(other instanceof Permutation))
- {
- return false;
- }
- Permutation otherPerm = (Permutation)other;
-
- return IntUtils.equals(perm, otherPerm.perm);
- }
-
- /**
- * @return a human readable form of the permutation
- */
- public String toString()
- {
- String result = "[" + perm[0];
- for (int i = 1; i < perm.length; i++)
- {
- result += ", " + perm[i];
- }
- result += "]";
- return result;
- }
-
- /**
- * @return the hash code of this permutation
- */
- public int hashCode()
- {
- return perm.hashCode();
- }
-
- /**
- * Check that the given array corresponds to a permutation of the set
- * <tt>{0, 1, ..., n-1}</tt>.
- *
- * @param perm permutation vector
- * @return true if perm represents an n-permutation and false otherwise
- */
- private boolean isPermutation(int[] perm)
- {
- int n = perm.length;
- boolean[] onlyOnce = new boolean[n];
-
- for (int i = 0; i < n; i++)
- {
- if ((perm[i] < 0) || (perm[i] >= n) || onlyOnce[perm[i]])
- {
- return false;
- }
- onlyOnce[perm[i]] = true;
- }
-
- return true;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialGF2mSmallM.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialGF2mSmallM.java
deleted file mode 100644
index 866b6f7c..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialGF2mSmallM.java
+++ /dev/null
@@ -1,1124 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-import java.security.SecureRandom;
-
-/**
- * This class describes operations with polynomials from the ring R =
- * GF(2^m)[X], where 2 &lt;= m &lt;=31.
- *
- * @see GF2mField
- * @see PolynomialRingGF2m
- */
-public class PolynomialGF2mSmallM
-{
-
- /**
- * the finite field GF(2^m)
- */
- private GF2mField field;
-
- /**
- * the degree of this polynomial
- */
- private int degree;
-
- /**
- * For the polynomial representation the map f: R->Z*,
- * <tt>poly(X) -> [coef_0, coef_1, ...]</tt> is used, where
- * <tt>coef_i</tt> is the <tt>i</tt>th coefficient of the polynomial
- * represented as int (see {@link GF2mField}). The polynomials are stored
- * as int arrays.
- */
- private int[] coefficients;
-
- /*
- * some types of polynomials
- */
-
- /**
- * Constant used for polynomial construction (see constructor
- * {@link #PolynomialGF2mSmallM(GF2mField, int, char, SecureRandom)}).
- */
- public static final char RANDOM_IRREDUCIBLE_POLYNOMIAL = 'I';
-
- /**
- * Construct the zero polynomial over the finite field GF(2^m).
- *
- * @param field the finite field GF(2^m)
- */
- public PolynomialGF2mSmallM(GF2mField field)
- {
- this.field = field;
- degree = -1;
- coefficients = new int[1];
- }
-
- /**
- * Construct a polynomial over the finite field GF(2^m).
- *
- * @param field the finite field GF(2^m)
- * @param deg degree of polynomial
- * @param typeOfPolynomial type of polynomial
- * @param sr PRNG
- */
- public PolynomialGF2mSmallM(GF2mField field, int deg,
- char typeOfPolynomial, SecureRandom sr)
- {
- this.field = field;
-
- switch (typeOfPolynomial)
- {
- case PolynomialGF2mSmallM.RANDOM_IRREDUCIBLE_POLYNOMIAL:
- coefficients = createRandomIrreduciblePolynomial(deg, sr);
- break;
- default:
- throw new IllegalArgumentException(" Error: type "
- + typeOfPolynomial
- + " is not defined for GF2smallmPolynomial");
- }
- computeDegree();
- }
-
- /**
- * Create an irreducible polynomial with the given degree over the field
- * <tt>GF(2^m)</tt>.
- *
- * @param deg polynomial degree
- * @param sr source of randomness
- * @return the generated irreducible polynomial
- */
- private int[] createRandomIrreduciblePolynomial(int deg, SecureRandom sr)
- {
- int[] resCoeff = new int[deg + 1];
- resCoeff[deg] = 1;
- resCoeff[0] = field.getRandomNonZeroElement(sr);
- for (int i = 1; i < deg; i++)
- {
- resCoeff[i] = field.getRandomElement(sr);
- }
- while (!isIrreducible(resCoeff))
- {
- int n = RandUtils.nextInt(sr, deg);
- if (n == 0)
- {
- resCoeff[0] = field.getRandomNonZeroElement(sr);
- }
- else
- {
- resCoeff[n] = field.getRandomElement(sr);
- }
- }
- return resCoeff;
- }
-
- /**
- * Construct a monomial of the given degree over the finite field GF(2^m).
- *
- * @param field the finite field GF(2^m)
- * @param degree the degree of the monomial
- */
- public PolynomialGF2mSmallM(GF2mField field, int degree)
- {
- this.field = field;
- this.degree = degree;
- coefficients = new int[degree + 1];
- coefficients[degree] = 1;
- }
-
- /**
- * Construct the polynomial over the given finite field GF(2^m) from the
- * given coefficient vector.
- *
- * @param field finite field GF2m
- * @param coeffs the coefficient vector
- */
- public PolynomialGF2mSmallM(GF2mField field, int[] coeffs)
- {
- this.field = field;
- coefficients = normalForm(coeffs);
- computeDegree();
- }
-
- /**
- * Create a polynomial over the finite field GF(2^m).
- *
- * @param field the finite field GF(2^m)
- * @param enc byte[] polynomial in byte array form
- */
- public PolynomialGF2mSmallM(GF2mField field, byte[] enc)
- {
- this.field = field;
-
- // decodes polynomial
- int d = 8;
- int count = 1;
- while (field.getDegree() > d)
- {
- count++;
- d += 8;
- }
-
- if ((enc.length % count) != 0)
- {
- throw new IllegalArgumentException(
- " Error: byte array is not encoded polynomial over given finite field GF2m");
- }
-
- coefficients = new int[enc.length / count];
- count = 0;
- for (int i = 0; i < coefficients.length; i++)
- {
- for (int j = 0; j < d; j += 8)
- {
- coefficients[i] ^= (enc[count++] & 0x000000ff) << j;
- }
- if (!this.field.isElementOfThisField(coefficients[i]))
- {
- throw new IllegalArgumentException(
- " Error: byte array is not encoded polynomial over given finite field GF2m");
- }
- }
- // if HC = 0 for non-zero polynomial, returns error
- if ((coefficients.length != 1)
- && (coefficients[coefficients.length - 1] == 0))
- {
- throw new IllegalArgumentException(
- " Error: byte array is not encoded polynomial over given finite field GF2m");
- }
- computeDegree();
- }
-
- /**
- * Copy constructor.
- *
- * @param other another {@link PolynomialGF2mSmallM}
- */
- public PolynomialGF2mSmallM(PolynomialGF2mSmallM other)
- {
- // field needs not to be cloned since it is immutable
- field = other.field;
- degree = other.degree;
- coefficients = IntUtils.clone(other.coefficients);
- }
-
- /**
- * Create a polynomial over the finite field GF(2^m) out of the given
- * coefficient vector. The finite field is also obtained from the
- * {@link GF2mVector}.
- *
- * @param vect the coefficient vector
- */
- public PolynomialGF2mSmallM(GF2mVector vect)
- {
- this(vect.getField(), vect.getIntArrayForm());
- }
-
- /*
- * ------------------------
- */
-
- /**
- * Return the degree of this polynomial
- *
- * @return int degree of this polynomial if this is zero polynomial return
- * -1
- */
- public int getDegree()
- {
- int d = coefficients.length - 1;
- if (coefficients[d] == 0)
- {
- return -1;
- }
- return d;
- }
-
- /**
- * @return the head coefficient of this polynomial
- */
- public int getHeadCoefficient()
- {
- if (degree == -1)
- {
- return 0;
- }
- return coefficients[degree];
- }
-
- /**
- * Return the head coefficient of a polynomial.
- *
- * @param a the polynomial
- * @return the head coefficient of <tt>a</tt>
- */
- private static int headCoefficient(int[] a)
- {
- int degree = computeDegree(a);
- if (degree == -1)
- {
- return 0;
- }
- return a[degree];
- }
-
- /**
- * Return the coefficient with the given index.
- *
- * @param index the index
- * @return the coefficient with the given index
- */
- public int getCoefficient(int index)
- {
- if ((index < 0) || (index > degree))
- {
- return 0;
- }
- return coefficients[index];
- }
-
- /**
- * Returns encoded polynomial, i.e., this polynomial in byte array form
- *
- * @return the encoded polynomial
- */
- public byte[] getEncoded()
- {
- int d = 8;
- int count = 1;
- while (field.getDegree() > d)
- {
- count++;
- d += 8;
- }
-
- byte[] res = new byte[coefficients.length * count];
- count = 0;
- for (int i = 0; i < coefficients.length; i++)
- {
- for (int j = 0; j < d; j += 8)
- {
- res[count++] = (byte)(coefficients[i] >>> j);
- }
- }
-
- return res;
- }
-
- /**
- * Evaluate this polynomial <tt>p</tt> at a value <tt>e</tt> (in
- * <tt>GF(2^m)</tt>) with the Horner scheme.
- *
- * @param e the element of the finite field GF(2^m)
- * @return <tt>this(e)</tt>
- */
- public int evaluateAt(int e)
- {
- int result = coefficients[degree];
- for (int i = degree - 1; i >= 0; i--)
- {
- result = field.mult(result, e) ^ coefficients[i];
- }
- return result;
- }
-
- /**
- * Compute the sum of this polynomial and the given polynomial.
- *
- * @param addend the addend
- * @return <tt>this + a</tt> (newly created)
- */
- public PolynomialGF2mSmallM add(PolynomialGF2mSmallM addend)
- {
- int[] resultCoeff = add(coefficients, addend.coefficients);
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Add the given polynomial to this polynomial (overwrite this).
- *
- * @param addend the addend
- */
- public void addToThis(PolynomialGF2mSmallM addend)
- {
- coefficients = add(coefficients, addend.coefficients);
- computeDegree();
- }
-
- /**
- * Compute the sum of two polynomials a and b over the finite field
- * <tt>GF(2^m)</tt>.
- *
- * @param a the first polynomial
- * @param b the second polynomial
- * @return a + b
- */
- private int[] add(int[] a, int[] b)
- {
- int[] result, addend;
- if (a.length < b.length)
- {
- result = new int[b.length];
- System.arraycopy(b, 0, result, 0, b.length);
- addend = a;
- }
- else
- {
- result = new int[a.length];
- System.arraycopy(a, 0, result, 0, a.length);
- addend = b;
- }
-
- for (int i = addend.length - 1; i >= 0; i--)
- {
- result[i] = field.add(result[i], addend[i]);
- }
-
- return result;
- }
-
- /**
- * Compute the sum of this polynomial and the monomial of the given degree.
- *
- * @param degree the degree of the monomial
- * @return <tt>this + X^k</tt>
- */
- public PolynomialGF2mSmallM addMonomial(int degree)
- {
- int[] monomial = new int[degree + 1];
- monomial[degree] = 1;
- int[] resultCoeff = add(coefficients, monomial);
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Compute the product of this polynomial with an element from GF(2^m).
- *
- * @param element an element of the finite field GF(2^m)
- * @return <tt>this * element</tt> (newly created)
- * @throws ArithmeticException if <tt>element</tt> is not an element of the finite
- * field this polynomial is defined over.
- */
- public PolynomialGF2mSmallM multWithElement(int element)
- {
- if (!field.isElementOfThisField(element))
- {
- throw new ArithmeticException(
- "Not an element of the finite field this polynomial is defined over.");
- }
- int[] resultCoeff = multWithElement(coefficients, element);
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Multiply this polynomial with an element from GF(2^m).
- *
- * @param element an element of the finite field GF(2^m)
- * @throws ArithmeticException if <tt>element</tt> is not an element of the finite
- * field this polynomial is defined over.
- */
- public void multThisWithElement(int element)
- {
- if (!field.isElementOfThisField(element))
- {
- throw new ArithmeticException(
- "Not an element of the finite field this polynomial is defined over.");
- }
- coefficients = multWithElement(coefficients, element);
- computeDegree();
- }
-
- /**
- * Compute the product of a polynomial a with an element from the finite
- * field <tt>GF(2^m)</tt>.
- *
- * @param a the polynomial
- * @param element an element of the finite field GF(2^m)
- * @return <tt>a * element</tt>
- */
- private int[] multWithElement(int[] a, int element)
- {
- int degree = computeDegree(a);
- if (degree == -1 || element == 0)
- {
- return new int[1];
- }
-
- if (element == 1)
- {
- return IntUtils.clone(a);
- }
-
- int[] result = new int[degree + 1];
- for (int i = degree; i >= 0; i--)
- {
- result[i] = field.mult(a[i], element);
- }
-
- return result;
- }
-
- /**
- * Compute the product of this polynomial with a monomial X^k.
- *
- * @param k the degree of the monomial
- * @return <tt>this * X^k</tt>
- */
- public PolynomialGF2mSmallM multWithMonomial(int k)
- {
- int[] resultCoeff = multWithMonomial(coefficients, k);
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Compute the product of a polynomial with a monomial X^k.
- *
- * @param a the polynomial
- * @param k the degree of the monomial
- * @return <tt>a * X^k</tt>
- */
- private static int[] multWithMonomial(int[] a, int k)
- {
- int d = computeDegree(a);
- if (d == -1)
- {
- return new int[1];
- }
- int[] result = new int[d + k + 1];
- System.arraycopy(a, 0, result, k, d + 1);
- return result;
- }
-
- /**
- * Divide this polynomial by the given polynomial.
- *
- * @param f a polynomial
- * @return polynomial pair = {q,r} where this = q*f+r and deg(r) &lt;
- * deg(f);
- */
- public PolynomialGF2mSmallM[] div(PolynomialGF2mSmallM f)
- {
- int[][] resultCoeffs = div(coefficients, f.coefficients);
- return new PolynomialGF2mSmallM[]{
- new PolynomialGF2mSmallM(field, resultCoeffs[0]),
- new PolynomialGF2mSmallM(field, resultCoeffs[1])};
- }
-
- /**
- * Compute the result of the division of two polynomials over the field
- * <tt>GF(2^m)</tt>.
- *
- * @param a the first polynomial
- * @param f the second polynomial
- * @return int[][] {q,r}, where a = q*f+r and deg(r) &lt; deg(f);
- */
- private int[][] div(int[] a, int[] f)
- {
- int df = computeDegree(f);
- int da = computeDegree(a) + 1;
- if (df == -1)
- {
- throw new ArithmeticException("Division by zero.");
- }
- int[][] result = new int[2][];
- result[0] = new int[1];
- result[1] = new int[da];
- int hc = headCoefficient(f);
- hc = field.inverse(hc);
- result[0][0] = 0;
- System.arraycopy(a, 0, result[1], 0, result[1].length);
- while (df <= computeDegree(result[1]))
- {
- int[] q;
- int[] coeff = new int[1];
- coeff[0] = field.mult(headCoefficient(result[1]), hc);
- q = multWithElement(f, coeff[0]);
- int n = computeDegree(result[1]) - df;
- q = multWithMonomial(q, n);
- coeff = multWithMonomial(coeff, n);
- result[0] = add(coeff, result[0]);
- result[1] = add(q, result[1]);
- }
- return result;
- }
-
- /**
- * Return the greatest common divisor of this and a polynomial <i>f</i>
- *
- * @param f polynomial
- * @return GCD(this, f)
- */
- public PolynomialGF2mSmallM gcd(PolynomialGF2mSmallM f)
- {
- int[] resultCoeff = gcd(coefficients, f.coefficients);
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Return the greatest common divisor of two polynomials over the field
- * <tt>GF(2^m)</tt>.
- *
- * @param f the first polynomial
- * @param g the second polynomial
- * @return <tt>gcd(f, g)</tt>
- */
- private int[] gcd(int[] f, int[] g)
- {
- int[] a = f;
- int[] b = g;
- if (computeDegree(a) == -1)
- {
- return b;
- }
- while (computeDegree(b) != -1)
- {
- int[] c = mod(a, b);
- a = new int[b.length];
- System.arraycopy(b, 0, a, 0, a.length);
- b = new int[c.length];
- System.arraycopy(c, 0, b, 0, b.length);
- }
- int coeff = field.inverse(headCoefficient(a));
- return multWithElement(a, coeff);
- }
-
- /**
- * Compute the product of this polynomial and the given factor using a
- * Karatzuba like scheme.
- *
- * @param factor the polynomial
- * @return <tt>this * factor</tt>
- */
- public PolynomialGF2mSmallM multiply(PolynomialGF2mSmallM factor)
- {
- int[] resultCoeff = multiply(coefficients, factor.coefficients);
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Compute the product of two polynomials over the field <tt>GF(2^m)</tt>
- * using a Karatzuba like multiplication.
- *
- * @param a the first polynomial
- * @param b the second polynomial
- * @return a * b
- */
- private int[] multiply(int[] a, int[] b)
- {
- int[] mult1, mult2;
- if (computeDegree(a) < computeDegree(b))
- {
- mult1 = b;
- mult2 = a;
- }
- else
- {
- mult1 = a;
- mult2 = b;
- }
-
- mult1 = normalForm(mult1);
- mult2 = normalForm(mult2);
-
- if (mult2.length == 1)
- {
- return multWithElement(mult1, mult2[0]);
- }
-
- int d1 = mult1.length;
- int d2 = mult2.length;
- int[] result = new int[d1 + d2 - 1];
-
- if (d2 != d1)
- {
- int[] res1 = new int[d2];
- int[] res2 = new int[d1 - d2];
- System.arraycopy(mult1, 0, res1, 0, res1.length);
- System.arraycopy(mult1, d2, res2, 0, res2.length);
- res1 = multiply(res1, mult2);
- res2 = multiply(res2, mult2);
- res2 = multWithMonomial(res2, d2);
- result = add(res1, res2);
- }
- else
- {
- d2 = (d1 + 1) >>> 1;
- int d = d1 - d2;
- int[] firstPartMult1 = new int[d2];
- int[] firstPartMult2 = new int[d2];
- int[] secondPartMult1 = new int[d];
- int[] secondPartMult2 = new int[d];
- System
- .arraycopy(mult1, 0, firstPartMult1, 0,
- firstPartMult1.length);
- System.arraycopy(mult1, d2, secondPartMult1, 0,
- secondPartMult1.length);
- System
- .arraycopy(mult2, 0, firstPartMult2, 0,
- firstPartMult2.length);
- System.arraycopy(mult2, d2, secondPartMult2, 0,
- secondPartMult2.length);
- int[] helpPoly1 = add(firstPartMult1, secondPartMult1);
- int[] helpPoly2 = add(firstPartMult2, secondPartMult2);
- int[] res1 = multiply(firstPartMult1, firstPartMult2);
- int[] res2 = multiply(helpPoly1, helpPoly2);
- int[] res3 = multiply(secondPartMult1, secondPartMult2);
- res2 = add(res2, res1);
- res2 = add(res2, res3);
- res3 = multWithMonomial(res3, d2);
- result = add(res2, res3);
- result = multWithMonomial(result, d2);
- result = add(result, res1);
- }
-
- return result;
- }
-
- /*
- * ---------------- PART II ----------------
- *
- */
-
- /**
- * Check a polynomial for irreducibility over the field <tt>GF(2^m)</tt>.
- *
- * @param a the polynomial to check
- * @return true if a is irreducible, false otherwise
- */
- private boolean isIrreducible(int[] a)
- {
- if (a[0] == 0)
- {
- return false;
- }
- int d = computeDegree(a) >> 1;
- int[] u = {0, 1};
- final int[] Y = {0, 1};
- int fieldDegree = field.getDegree();
- for (int i = 0; i < d; i++)
- {
- for (int j = fieldDegree - 1; j >= 0; j--)
- {
- u = modMultiply(u, u, a);
- }
- u = normalForm(u);
- int[] g = gcd(add(u, Y), a);
- if (computeDegree(g) != 0)
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Reduce this polynomial modulo another polynomial.
- *
- * @param f the reduction polynomial
- * @return <tt>this mod f</tt>
- */
- public PolynomialGF2mSmallM mod(PolynomialGF2mSmallM f)
- {
- int[] resultCoeff = mod(coefficients, f.coefficients);
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Reduce a polynomial modulo another polynomial.
- *
- * @param a the polynomial
- * @param f the reduction polynomial
- * @return <tt>a mod f</tt>
- */
- private int[] mod(int[] a, int[] f)
- {
- int df = computeDegree(f);
- if (df == -1)
- {
- throw new ArithmeticException("Division by zero");
- }
- int[] result = new int[a.length];
- int hc = headCoefficient(f);
- hc = field.inverse(hc);
- System.arraycopy(a, 0, result, 0, result.length);
- while (df <= computeDegree(result))
- {
- int[] q;
- int coeff = field.mult(headCoefficient(result), hc);
- q = multWithMonomial(f, computeDegree(result) - df);
- q = multWithElement(q, coeff);
- result = add(q, result);
- }
- return result;
- }
-
- /**
- * Compute the product of this polynomial and another polynomial modulo a
- * third polynomial.
- *
- * @param a another polynomial
- * @param b the reduction polynomial
- * @return <tt>this * a mod b</tt>
- */
- public PolynomialGF2mSmallM modMultiply(PolynomialGF2mSmallM a,
- PolynomialGF2mSmallM b)
- {
- int[] resultCoeff = modMultiply(coefficients, a.coefficients,
- b.coefficients);
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Square this polynomial using a squaring matrix.
- *
- * @param matrix the squaring matrix
- * @return <tt>this^2</tt> modulo the reduction polynomial implicitly
- * given via the squaring matrix
- */
- public PolynomialGF2mSmallM modSquareMatrix(PolynomialGF2mSmallM[] matrix)
- {
-
- int length = matrix.length;
-
- int[] resultCoeff = new int[length];
- int[] thisSquare = new int[length];
-
- // square each entry of this polynomial
- for (int i = 0; i < coefficients.length; i++)
- {
- thisSquare[i] = field.mult(coefficients[i], coefficients[i]);
- }
-
- // do matrix-vector multiplication
- for (int i = 0; i < length; i++)
- {
- // compute scalar product of i-th row and coefficient vector
- for (int j = 0; j < length; j++)
- {
- if (i >= matrix[j].coefficients.length)
- {
- continue;
- }
- int scalarTerm = field.mult(matrix[j].coefficients[i],
- thisSquare[j]);
- resultCoeff[i] = field.add(resultCoeff[i], scalarTerm);
- }
- }
-
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Compute the product of two polynomials modulo a third polynomial over the
- * finite field <tt>GF(2^m)</tt>.
- *
- * @param a the first polynomial
- * @param b the second polynomial
- * @param g the reduction polynomial
- * @return <tt>a * b mod g</tt>
- */
- private int[] modMultiply(int[] a, int[] b, int[] g)
- {
- return mod(multiply(a, b), g);
- }
-
- /**
- * Compute the square root of this polynomial modulo the given polynomial.
- *
- * @param a the reduction polynomial
- * @return <tt>this^(1/2) mod a</tt>
- */
- public PolynomialGF2mSmallM modSquareRoot(PolynomialGF2mSmallM a)
- {
- int[] resultCoeff = IntUtils.clone(coefficients);
- int[] help = modMultiply(resultCoeff, resultCoeff, a.coefficients);
- while (!isEqual(help, coefficients))
- {
- resultCoeff = normalForm(help);
- help = modMultiply(resultCoeff, resultCoeff, a.coefficients);
- }
-
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Compute the square root of this polynomial using a square root matrix.
- *
- * @param matrix the matrix for computing square roots in
- * <tt>(GF(2^m))^t</tt> the polynomial ring defining the
- * square root matrix
- * @return <tt>this^(1/2)</tt> modulo the reduction polynomial implicitly
- * given via the square root matrix
- */
- public PolynomialGF2mSmallM modSquareRootMatrix(
- PolynomialGF2mSmallM[] matrix)
- {
-
- int length = matrix.length;
-
- int[] resultCoeff = new int[length];
-
- // do matrix multiplication
- for (int i = 0; i < length; i++)
- {
- // compute scalar product of i-th row and j-th column
- for (int j = 0; j < length; j++)
- {
- if (i >= matrix[j].coefficients.length)
- {
- continue;
- }
- if (j < coefficients.length)
- {
- int scalarTerm = field.mult(matrix[j].coefficients[i],
- coefficients[j]);
- resultCoeff[i] = field.add(resultCoeff[i], scalarTerm);
- }
- }
- }
-
- // compute the square root of each entry of the result coefficients
- for (int i = 0; i < length; i++)
- {
- resultCoeff[i] = field.sqRoot(resultCoeff[i]);
- }
-
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Compute the result of the division of this polynomial by another
- * polynomial modulo a third polynomial.
- *
- * @param divisor the divisor
- * @param modulus the reduction polynomial
- * @return <tt>this * divisor^(-1) mod modulus</tt>
- */
- public PolynomialGF2mSmallM modDiv(PolynomialGF2mSmallM divisor,
- PolynomialGF2mSmallM modulus)
- {
- int[] resultCoeff = modDiv(coefficients, divisor.coefficients,
- modulus.coefficients);
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Compute the result of the division of two polynomials modulo a third
- * polynomial over the field <tt>GF(2^m)</tt>.
- *
- * @param a the first polynomial
- * @param b the second polynomial
- * @param g the reduction polynomial
- * @return <tt>a * b^(-1) mod g</tt>
- */
- private int[] modDiv(int[] a, int[] b, int[] g)
- {
- int[] r0 = normalForm(g);
- int[] r1 = mod(b, g);
- int[] s0 = {0};
- int[] s1 = mod(a, g);
- int[] s2;
- int[][] q;
- while (computeDegree(r1) != -1)
- {
- q = div(r0, r1);
- r0 = normalForm(r1);
- r1 = normalForm(q[1]);
- s2 = add(s0, modMultiply(q[0], s1, g));
- s0 = normalForm(s1);
- s1 = normalForm(s2);
-
- }
- int hc = headCoefficient(r0);
- s0 = multWithElement(s0, field.inverse(hc));
- return s0;
- }
-
- /**
- * Compute the inverse of this polynomial modulo the given polynomial.
- *
- * @param a the reduction polynomial
- * @return <tt>this^(-1) mod a</tt>
- */
- public PolynomialGF2mSmallM modInverse(PolynomialGF2mSmallM a)
- {
- int[] unit = {1};
- int[] resultCoeff = modDiv(unit, coefficients, a.coefficients);
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Compute a polynomial pair (a,b) from this polynomial and the given
- * polynomial g with the property b*this = a mod g and deg(a)&lt;=deg(g)/2.
- *
- * @param g the reduction polynomial
- * @return PolynomialGF2mSmallM[] {a,b} with b*this = a mod g and deg(a)&lt;=
- * deg(g)/2
- */
- public PolynomialGF2mSmallM[] modPolynomialToFracton(PolynomialGF2mSmallM g)
- {
- int dg = g.degree >> 1;
- int[] a0 = normalForm(g.coefficients);
- int[] a1 = mod(coefficients, g.coefficients);
- int[] b0 = {0};
- int[] b1 = {1};
- while (computeDegree(a1) > dg)
- {
- int[][] q = div(a0, a1);
- a0 = a1;
- a1 = q[1];
- int[] b2 = add(b0, modMultiply(q[0], b1, g.coefficients));
- b0 = b1;
- b1 = b2;
- }
-
- return new PolynomialGF2mSmallM[]{
- new PolynomialGF2mSmallM(field, a1),
- new PolynomialGF2mSmallM(field, b1)};
- }
-
- /**
- * checks if given object is equal to this polynomial.
- * <p>
- * The method returns false whenever the given object is not polynomial over
- * GF(2^m).
- *
- * @param other object
- * @return true or false
- */
- public boolean equals(Object other)
- {
-
- if (other == null || !(other instanceof PolynomialGF2mSmallM))
- {
- return false;
- }
-
- PolynomialGF2mSmallM p = (PolynomialGF2mSmallM)other;
-
- if ((field.equals(p.field)) && (degree == p.degree)
- && (isEqual(coefficients, p.coefficients)))
- {
- return true;
- }
-
- return false;
- }
-
- /**
- * Compare two polynomials given as int arrays.
- *
- * @param a the first polynomial
- * @param b the second polynomial
- * @return <tt>true</tt> if <tt>a</tt> and <tt>b</tt> represent the
- * same polynomials, <tt>false</tt> otherwise
- */
- private static boolean isEqual(int[] a, int[] b)
- {
- int da = computeDegree(a);
- int db = computeDegree(b);
- if (da != db)
- {
- return false;
- }
- for (int i = 0; i <= da; i++)
- {
- if (a[i] != b[i])
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * @return the hash code of this polynomial
- */
- public int hashCode()
- {
- int hash = field.hashCode();
- for (int j = 0; j < coefficients.length; j++)
- {
- hash = hash * 31 + coefficients[j];
- }
- return hash;
- }
-
- /**
- * Returns a human readable form of the polynomial.
- *
- * @return a human readable form of the polynomial.
- */
- public String toString()
- {
- String str = " Polynomial over " + field.toString() + ": \n";
-
- for (int i = 0; i < coefficients.length; i++)
- {
- str = str + field.elementToStr(coefficients[i]) + "Y^" + i + "+";
- }
- str = str + ";";
-
- return str;
- }
-
- /**
- * Compute the degree of this polynomial. If this is the zero polynomial,
- * the degree is -1.
- */
- private void computeDegree()
- {
- for (degree = coefficients.length - 1; degree >= 0
- && coefficients[degree] == 0; degree--)
- {
- ;
- }
- }
-
- /**
- * Compute the degree of a polynomial.
- *
- * @param a the polynomial
- * @return the degree of the polynomial <tt>a</tt>. If <tt>a</tt> is
- * the zero polynomial, return -1.
- */
- private static int computeDegree(int[] a)
- {
- int degree;
- for (degree = a.length - 1; degree >= 0 && a[degree] == 0; degree--)
- {
- ;
- }
- return degree;
- }
-
- /**
- * Strip leading zero coefficients from the given polynomial.
- *
- * @param a the polynomial
- * @return the reduced polynomial
- */
- private static int[] normalForm(int[] a)
- {
- int d = computeDegree(a);
-
- // if a is the zero polynomial
- if (d == -1)
- {
- // return new zero polynomial
- return new int[1];
- }
-
- // if a already is in normal form
- if (a.length == d + 1)
- {
- // return a clone of a
- return IntUtils.clone(a);
- }
-
- // else, reduce a
- int[] result = new int[d + 1];
- System.arraycopy(a, 0, result, 0, d + 1);
- return result;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialRingGF2.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialRingGF2.java
deleted file mode 100644
index a0e2bacc..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialRingGF2.java
+++ /dev/null
@@ -1,278 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-/**
- * This class describes operations with polynomials over finite field GF(2), i e
- * polynomial ring R = GF(2)[X]. All operations are defined only for polynomials
- * with degree &lt;=32. For the polynomial representation the map f: R-&gt;Z,
- * poly(X)-&gt;poly(2) is used, where integers have the binary representation. For
- * example: X^7+X^3+X+1 -&gt; (00...0010001011)=139 Also for polynomials type
- * Integer is used.
- *
- * @see GF2mField
- */
-public final class PolynomialRingGF2
-{
-
- /**
- * Default constructor (private).
- */
- private PolynomialRingGF2()
- {
- // empty
- }
-
- /**
- * Return sum of two polyomials
- *
- * @param p polynomial
- * @param q polynomial
- * @return p+q
- */
-
- public static int add(int p, int q)
- {
- return p ^ q;
- }
-
- /**
- * Return product of two polynomials
- *
- * @param p polynomial
- * @param q polynomial
- * @return p*q
- */
-
- public static long multiply(int p, int q)
- {
- long result = 0;
- if (q != 0)
- {
- long q1 = q & 0x00000000ffffffffL;
-
- while (p != 0)
- {
- byte b = (byte)(p & 0x01);
- if (b == 1)
- {
- result ^= q1;
- }
- p >>>= 1;
- q1 <<= 1;
-
- }
- }
- return result;
- }
-
- /**
- * Compute the product of two polynomials modulo a third polynomial.
- *
- * @param a the first polynomial
- * @param b the second polynomial
- * @param r the reduction polynomial
- * @return <tt>a * b mod r</tt>
- */
- public static int modMultiply(int a, int b, int r)
- {
- int result = 0;
- int p = remainder(a, r);
- int q = remainder(b, r);
- if (q != 0)
- {
- int d = 1 << degree(r);
-
- while (p != 0)
- {
- byte pMod2 = (byte)(p & 0x01);
- if (pMod2 == 1)
- {
- result ^= q;
- }
- p >>>= 1;
- q <<= 1;
- if (q >= d)
- {
- q ^= r;
- }
- }
- }
- return result;
- }
-
- /**
- * Return the degree of a polynomial
- *
- * @param p polynomial p
- * @return degree(p)
- */
-
- public static int degree(int p)
- {
- int result = -1;
- while (p != 0)
- {
- result++;
- p >>>= 1;
- }
- return result;
- }
-
- /**
- * Return the degree of a polynomial
- *
- * @param p polynomial p
- * @return degree(p)
- */
-
- public static int degree(long p)
- {
- int result = 0;
- while (p != 0)
- {
- result++;
- p >>>= 1;
- }
- return result - 1;
- }
-
- /**
- * Return the remainder of a polynomial division of two polynomials.
- *
- * @param p dividend
- * @param q divisor
- * @return <tt>p mod q</tt>
- */
- public static int remainder(int p, int q)
- {
- int result = p;
-
- if (q == 0)
- {
- System.err.println("Error: to be divided by 0");
- return 0;
- }
-
- while (degree(result) >= degree(q))
- {
- result ^= q << (degree(result) - degree(q));
- }
-
- return result;
- }
-
- /**
- * Return the rest of devision two polynomials
- *
- * @param p polinomial
- * @param q polinomial
- * @return p mod q
- */
-
- public static int rest(long p, int q)
- {
- long p1 = p;
- if (q == 0)
- {
- System.err.println("Error: to be divided by 0");
- return 0;
- }
- long q1 = q & 0x00000000ffffffffL;
- while ((p1 >>> 32) != 0)
- {
- p1 ^= q1 << (degree(p1) - degree(q1));
- }
-
- int result = (int)(p1 & 0xffffffff);
- while (degree(result) >= degree(q))
- {
- result ^= q << (degree(result) - degree(q));
- }
-
- return result;
- }
-
- /**
- * Return the greatest common divisor of two polynomials
- *
- * @param p polinomial
- * @param q polinomial
- * @return GCD(p, q)
- */
-
- public static int gcd(int p, int q)
- {
- int a, b, c;
- a = p;
- b = q;
- while (b != 0)
- {
- c = remainder(a, b);
- a = b;
- b = c;
-
- }
- return a;
- }
-
- /**
- * Checking polynomial for irreducibility
- *
- * @param p polinomial
- * @return true if p is irreducible and false otherwise
- */
-
- public static boolean isIrreducible(int p)
- {
- if (p == 0)
- {
- return false;
- }
- int d = degree(p) >>> 1;
- int u = 2;
- for (int i = 0; i < d; i++)
- {
- u = modMultiply(u, u, p);
- if (gcd(u ^ 2, p) != 1)
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Creates irreducible polynomial with degree d
- *
- * @param deg polynomial degree
- * @return irreducible polynomial p
- */
- public static int getIrreduciblePolynomial(int deg)
- {
- if (deg < 0)
- {
- System.err.println("The Degree is negative");
- return 0;
- }
- if (deg > 31)
- {
- System.err.println("The Degree is more then 31");
- return 0;
- }
- if (deg == 0)
- {
- return 1;
- }
- int a = 1 << deg;
- a++;
- int b = 1 << (deg + 1);
- for (int i = a; i < b; i += 2)
- {
- if (isIrreducible(i))
- {
- return i;
- }
- }
- return 0;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialRingGF2m.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialRingGF2m.java
deleted file mode 100644
index 9e5d4139..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialRingGF2m.java
+++ /dev/null
@@ -1,175 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-/**
- * This class represents polynomial rings <tt>GF(2^m)[X]/p(X)</tt> for
- * <tt>m&lt;32</tt>. If <tt>p(X)</tt> is irreducible, the polynomial ring
- * is in fact an extension field of <tt>GF(2^m)</tt>.
- */
-public class PolynomialRingGF2m
-{
-
- /**
- * the finite field this polynomial ring is defined over
- */
- private GF2mField field;
-
- /**
- * the reduction polynomial
- */
- private PolynomialGF2mSmallM p;
-
- /**
- * the squaring matrix for this polynomial ring (given as the array of its
- * row vectors)
- */
- protected PolynomialGF2mSmallM[] sqMatrix;
-
- /**
- * the matrix for computing square roots in this polynomial ring (given as
- * the array of its row vectors). This matrix is computed as the inverse of
- * the squaring matrix.
- */
- protected PolynomialGF2mSmallM[] sqRootMatrix;
-
- /**
- * Constructor.
- *
- * @param field the finite field
- * @param p the reduction polynomial
- */
- public PolynomialRingGF2m(GF2mField field, PolynomialGF2mSmallM p)
- {
- this.field = field;
- this.p = p;
- computeSquaringMatrix();
- computeSquareRootMatrix();
- }
-
- /**
- * @return the squaring matrix for this polynomial ring
- */
- public PolynomialGF2mSmallM[] getSquaringMatrix()
- {
- return sqMatrix;
- }
-
- /**
- * @return the matrix for computing square roots for this polynomial ring
- */
- public PolynomialGF2mSmallM[] getSquareRootMatrix()
- {
- return sqRootMatrix;
- }
-
- /**
- * Compute the squaring matrix for this polynomial ring, using the base
- * field and the reduction polynomial.
- */
- private void computeSquaringMatrix()
- {
- int numColumns = p.getDegree();
- sqMatrix = new PolynomialGF2mSmallM[numColumns];
- for (int i = 0; i < numColumns >> 1; i++)
- {
- int[] monomCoeffs = new int[(i << 1) + 1];
- monomCoeffs[i << 1] = 1;
- sqMatrix[i] = new PolynomialGF2mSmallM(field, monomCoeffs);
- }
- for (int i = numColumns >> 1; i < numColumns; i++)
- {
- int[] monomCoeffs = new int[(i << 1) + 1];
- monomCoeffs[i << 1] = 1;
- PolynomialGF2mSmallM monomial = new PolynomialGF2mSmallM(field,
- monomCoeffs);
- sqMatrix[i] = monomial.mod(p);
- }
- }
-
- /**
- * Compute the matrix for computing square roots in this polynomial ring by
- * inverting the squaring matrix.
- */
- private void computeSquareRootMatrix()
- {
- int numColumns = p.getDegree();
-
- // clone squaring matrix
- PolynomialGF2mSmallM[] tmpMatrix = new PolynomialGF2mSmallM[numColumns];
- for (int i = numColumns - 1; i >= 0; i--)
- {
- tmpMatrix[i] = new PolynomialGF2mSmallM(sqMatrix[i]);
- }
-
- // initialize square root matrix as unit matrix
- sqRootMatrix = new PolynomialGF2mSmallM[numColumns];
- for (int i = numColumns - 1; i >= 0; i--)
- {
- sqRootMatrix[i] = new PolynomialGF2mSmallM(field, i);
- }
-
- // simultaneously compute Gaussian reduction of squaring matrix and unit
- // matrix
- for (int i = 0; i < numColumns; i++)
- {
- // if diagonal element is zero
- if (tmpMatrix[i].getCoefficient(i) == 0)
- {
- boolean foundNonZero = false;
- // find a non-zero element in the same row
- for (int j = i + 1; j < numColumns; j++)
- {
- if (tmpMatrix[j].getCoefficient(i) != 0)
- {
- // found it, swap columns ...
- foundNonZero = true;
- swapColumns(tmpMatrix, i, j);
- swapColumns(sqRootMatrix, i, j);
- // ... and quit searching
- j = numColumns;
- continue;
- }
- }
- // if no non-zero element was found
- if (!foundNonZero)
- {
- // the matrix is not invertible
- throw new ArithmeticException(
- "Squaring matrix is not invertible.");
- }
- }
-
- // normalize i-th column
- int coef = tmpMatrix[i].getCoefficient(i);
- int invCoef = field.inverse(coef);
- tmpMatrix[i].multThisWithElement(invCoef);
- sqRootMatrix[i].multThisWithElement(invCoef);
-
- // normalize all other columns
- for (int j = 0; j < numColumns; j++)
- {
- if (j != i)
- {
- coef = tmpMatrix[j].getCoefficient(i);
- if (coef != 0)
- {
- PolynomialGF2mSmallM tmpSqColumn = tmpMatrix[i]
- .multWithElement(coef);
- PolynomialGF2mSmallM tmpInvColumn = sqRootMatrix[i]
- .multWithElement(coef);
- tmpMatrix[j].addToThis(tmpSqColumn);
- sqRootMatrix[j].addToThis(tmpInvColumn);
- }
- }
- }
- }
- }
-
- private static void swapColumns(PolynomialGF2mSmallM[] matrix, int first,
- int second)
- {
- PolynomialGF2mSmallM tmp = matrix[first];
- matrix[first] = matrix[second];
- matrix[second] = tmp;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/RandUtils.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/RandUtils.java
deleted file mode 100644
index dbb1d4a8..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/RandUtils.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-import java.security.SecureRandom;
-
-public class RandUtils
-{
- static int nextInt(SecureRandom rand, int n)
- {
-
- if ((n & -n) == n) // i.e., n is a power of 2
- {
- return (int)((n * (long)(rand.nextInt() >>> 1)) >> 31);
- }
-
- int bits, value;
- do
- {
- bits = rand.nextInt() >>> 1;
- value = bits % n;
- }
- while (bits - value + (n - 1) < 0);
-
- return value;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Vector.java b/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Vector.java
deleted file mode 100644
index 7e171643..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Vector.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-/**
- * This abstract class defines vectors. It holds the length of vector.
- */
-public abstract class Vector
-{
-
- /**
- * the length of this vector
- */
- protected int length;
-
- /**
- * @return the length of this vector
- */
- public final int getLength()
- {
- return length;
- }
-
- /**
- * @return this vector as byte array
- */
- public abstract byte[] getEncoded();
-
- /**
- * Return whether this is the zero vector (i.e., all elements are zero).
- *
- * @return <tt>true</tt> if this is the zero vector, <tt>false</tt>
- * otherwise
- */
- public abstract boolean isZero();
-
- /**
- * Add another vector to this vector.
- *
- * @param addend the other vector
- * @return <tt>this + addend</tt>
- */
- public abstract Vector add(Vector addend);
-
- /**
- * Multiply this vector with a permutation.
- *
- * @param p the permutation
- * @return <tt>this*p = p*this</tt>
- */
- public abstract Vector multiply(Permutation p);
-
- /**
- * Check if the given object is equal to this vector.
- *
- * @param other vector
- * @return the result of the comparison
- */
- public abstract boolean equals(Object other);
-
- /**
- * @return the hash code of this vector
- */
- public abstract int hashCode();
-
- /**
- * @return a human readable form of this vector
- */
- public abstract String toString();
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/BigIntEuclidean.java b/core/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/BigIntEuclidean.java
deleted file mode 100644
index 5fb30584..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/BigIntEuclidean.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.euclid;
-
-import java.math.BigInteger;
-
-/**
- * Extended Euclidean Algorithm in <code>BigInteger</code>s
- */
-public class BigIntEuclidean
-{
- public BigInteger x, y, gcd;
-
- private BigIntEuclidean()
- {
- }
-
- /**
- * Runs the EEA on two <code>BigInteger</code>s<br>
- * Implemented from pseudocode on <a href="http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm">Wikipedia</a>.
- *
- * @param a
- * @param b
- * @return a <code>BigIntEuclidean</code> object that contains the result in the variables <code>x</code>, <code>y</code>, and <code>gcd</code>
- */
- public static BigIntEuclidean calculate(BigInteger a, BigInteger b)
- {
- BigInteger x = BigInteger.ZERO;
- BigInteger lastx = BigInteger.ONE;
- BigInteger y = BigInteger.ONE;
- BigInteger lasty = BigInteger.ZERO;
- while (!b.equals(BigInteger.ZERO))
- {
- BigInteger[] quotientAndRemainder = a.divideAndRemainder(b);
- BigInteger quotient = quotientAndRemainder[0];
-
- BigInteger temp = a;
- a = b;
- b = quotientAndRemainder[1];
-
- temp = x;
- x = lastx.subtract(quotient.multiply(x));
- lastx = temp;
-
- temp = y;
- y = lasty.subtract(quotient.multiply(y));
- lasty = temp;
- }
-
- BigIntEuclidean result = new BigIntEuclidean();
- result.x = lastx;
- result.y = lasty;
- result.gcd = a;
- return result;
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/IntEuclidean.java b/core/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/IntEuclidean.java
deleted file mode 100644
index c959a26d..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/IntEuclidean.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.euclid;
-
-/**
- * Extended Euclidean Algorithm in <code>int</code>s
- */
-public class IntEuclidean
-{
- public int x, y, gcd;
-
- private IntEuclidean()
- {
- }
-
- /**
- * Runs the EEA on two <code>int</code>s<br>
- * Implemented from pseudocode on <a href="http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm">Wikipedia</a>.
- *
- * @param a
- * @param b
- * @return a <code>IntEuclidean</code> object that contains the result in the variables <code>x</code>, <code>y</code>, and <code>gcd</code>
- */
- public static IntEuclidean calculate(int a, int b)
- {
- int x = 0;
- int lastx = 1;
- int y = 1;
- int lasty = 0;
- while (b != 0)
- {
- int quotient = a / b;
-
- int temp = a;
- a = b;
- b = temp % b;
-
- temp = x;
- x = lastx - quotient * x;
- lastx = temp;
-
- temp = y;
- y = lasty - quotient * y;
- lasty = temp;
- }
-
- IntEuclidean result = new IntEuclidean();
- result.x = lastx;
- result.y = lasty;
- result.gcd = a;
- return result;
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/BigDecimalPolynomial.java b/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/BigDecimalPolynomial.java
deleted file mode 100644
index 697f51a6..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/BigDecimalPolynomial.java
+++ /dev/null
@@ -1,258 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-import java.math.BigDecimal;
-
-/**
- * A polynomial with {@link BigDecimal} coefficients.
- * Some methods (like <code>add</code>) change the polynomial, others (like <code>mult</code>) do
- * not but return the result as a new polynomial.
- */
-public class BigDecimalPolynomial
-{
- private static final BigDecimal ZERO = new BigDecimal("0");
- private static final BigDecimal ONE_HALF = new BigDecimal("0.5");
-
- BigDecimal[] coeffs;
-
- /**
- * Constructs a new polynomial with <code>N</code> coefficients initialized to 0.
- *
- * @param N the number of coefficients
- */
- BigDecimalPolynomial(int N)
- {
- coeffs = new BigDecimal[N];
- for (int i = 0; i < N; i++)
- {
- coeffs[i] = ZERO;
- }
- }
-
- /**
- * Constructs a new polynomial with a given set of coefficients.
- *
- * @param coeffs the coefficients
- */
- BigDecimalPolynomial(BigDecimal[] coeffs)
- {
- this.coeffs = coeffs;
- }
-
- /**
- * Constructs a <code>BigDecimalPolynomial</code> from a <code>BigIntPolynomial</code>. The two polynomials are independent of each other.
- *
- * @param p the original polynomial
- */
- public BigDecimalPolynomial(BigIntPolynomial p)
- {
- int N = p.coeffs.length;
- coeffs = new BigDecimal[N];
- for (int i = 0; i < N; i++)
- {
- coeffs[i] = new BigDecimal(p.coeffs[i]);
- }
- }
-
- /**
- * Divides all coefficients by 2.
- */
- public void halve()
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] = coeffs[i].multiply(ONE_HALF);
- }
- }
-
- /**
- * Multiplies the polynomial by another. Does not change this polynomial
- * but returns the result as a new polynomial.
- *
- * @param poly2 the polynomial to multiply by
- * @return a new polynomial
- */
- public BigDecimalPolynomial mult(BigIntPolynomial poly2)
- {
- return mult(new BigDecimalPolynomial(poly2));
- }
-
- /**
- * Multiplies the polynomial by another, taking the indices mod N. Does not
- * change this polynomial but returns the result as a new polynomial.
- *
- * @param poly2 the polynomial to multiply by
- * @return a new polynomial
- */
- public BigDecimalPolynomial mult(BigDecimalPolynomial poly2)
- {
- int N = coeffs.length;
- if (poly2.coeffs.length != N)
- {
- throw new IllegalArgumentException("Number of coefficients must be the same");
- }
-
- BigDecimalPolynomial c = multRecursive(poly2);
-
- if (c.coeffs.length > N)
- {
- for (int k = N; k < c.coeffs.length; k++)
- {
- c.coeffs[k - N] = c.coeffs[k - N].add(c.coeffs[k]);
- }
- c.coeffs = copyOf(c.coeffs, N);
- }
- return c;
- }
-
- /**
- * Karazuba multiplication
- */
- private BigDecimalPolynomial multRecursive(BigDecimalPolynomial poly2)
- {
- BigDecimal[] a = coeffs;
- BigDecimal[] b = poly2.coeffs;
-
- int n = poly2.coeffs.length;
- if (n <= 1)
- {
- BigDecimal[] c = coeffs.clone();
- for (int i = 0; i < coeffs.length; i++)
- {
- c[i] = c[i].multiply(poly2.coeffs[0]);
- }
- return new BigDecimalPolynomial(c);
- }
- else
- {
- int n1 = n / 2;
-
- BigDecimalPolynomial a1 = new BigDecimalPolynomial(copyOf(a, n1));
- BigDecimalPolynomial a2 = new BigDecimalPolynomial(copyOfRange(a, n1, n));
- BigDecimalPolynomial b1 = new BigDecimalPolynomial(copyOf(b, n1));
- BigDecimalPolynomial b2 = new BigDecimalPolynomial(copyOfRange(b, n1, n));
-
- BigDecimalPolynomial A = (BigDecimalPolynomial)a1.clone();
- A.add(a2);
- BigDecimalPolynomial B = (BigDecimalPolynomial)b1.clone();
- B.add(b2);
-
- BigDecimalPolynomial c1 = a1.multRecursive(b1);
- BigDecimalPolynomial c2 = a2.multRecursive(b2);
- BigDecimalPolynomial c3 = A.multRecursive(B);
- c3.sub(c1);
- c3.sub(c2);
-
- BigDecimalPolynomial c = new BigDecimalPolynomial(2 * n - 1);
- for (int i = 0; i < c1.coeffs.length; i++)
- {
- c.coeffs[i] = c1.coeffs[i];
- }
- for (int i = 0; i < c3.coeffs.length; i++)
- {
- c.coeffs[n1 + i] = c.coeffs[n1 + i].add(c3.coeffs[i]);
- }
- for (int i = 0; i < c2.coeffs.length; i++)
- {
- c.coeffs[2 * n1 + i] = c.coeffs[2 * n1 + i].add(c2.coeffs[i]);
- }
- return c;
- }
- }
-
- /**
- * Adds another polynomial which can have a different number of coefficients.
- *
- * @param b another polynomial
- */
- public void add(BigDecimalPolynomial b)
- {
- if (b.coeffs.length > coeffs.length)
- {
- int N = coeffs.length;
- coeffs = copyOf(coeffs, b.coeffs.length);
- for (int i = N; i < coeffs.length; i++)
- {
- coeffs[i] = ZERO;
- }
- }
- for (int i = 0; i < b.coeffs.length; i++)
- {
- coeffs[i] = coeffs[i].add(b.coeffs[i]);
- }
- }
-
- /**
- * Subtracts another polynomial which can have a different number of coefficients.
- *
- * @param b
- */
- void sub(BigDecimalPolynomial b)
- {
- if (b.coeffs.length > coeffs.length)
- {
- int N = coeffs.length;
- coeffs = copyOf(coeffs, b.coeffs.length);
- for (int i = N; i < coeffs.length; i++)
- {
- coeffs[i] = ZERO;
- }
- }
- for (int i = 0; i < b.coeffs.length; i++)
- {
- coeffs[i] = coeffs[i].subtract(b.coeffs[i]);
- }
- }
-
- /**
- * Rounds all coefficients to the nearest integer.
- *
- * @return a new polynomial with <code>BigInteger</code> coefficients
- */
- public BigIntPolynomial round()
- {
- int N = coeffs.length;
- BigIntPolynomial p = new BigIntPolynomial(N);
- for (int i = 0; i < N; i++)
- {
- p.coeffs[i] = coeffs[i].setScale(0, BigDecimal.ROUND_HALF_EVEN).toBigInteger();
- }
- return p;
- }
-
- /**
- * Makes a copy of the polynomial that is independent of the original.
- */
- public Object clone()
- {
- return new BigDecimalPolynomial(coeffs.clone());
- }
-
- private BigDecimal[] copyOf(BigDecimal[] a, int length)
- {
- BigDecimal[] tmp = new BigDecimal[length];
-
- System.arraycopy(a, 0, tmp, 0, a.length < length ? a.length : length);
-
- return tmp;
- }
-
- private BigDecimal[] copyOfRange(BigDecimal[] a, int from, int to)
- {
- int newLength = to - from;
- BigDecimal[] tmp = new BigDecimal[to - from];
-
- System.arraycopy(a, from, tmp, 0, (a.length - from) < newLength ? (a.length - from) : newLength);
-
- return tmp;
- }
-
- public BigDecimal[] getCoeffs()
- {
- BigDecimal[] tmp = new BigDecimal[coeffs.length];
-
- System.arraycopy(coeffs, 0, tmp, 0, coeffs.length);
-
- return tmp;
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/BigIntPolynomial.java b/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/BigIntPolynomial.java
deleted file mode 100644
index 3c79b2e9..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/BigIntPolynomial.java
+++ /dev/null
@@ -1,394 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.security.SecureRandom;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * A polynomial with {@link BigInteger} coefficients.<br>
- * Some methods (like <code>add</code>) change the polynomial, others (like <code>mult</code>) do
- * not but return the result as a new polynomial.
- */
-public class BigIntPolynomial
-{
- private final static double LOG_10_2 = Math.log10(2);
-
- BigInteger[] coeffs;
-
- /**
- * Constructs a new polynomial with <code>N</code> coefficients initialized to 0.
- *
- * @param N the number of coefficients
- */
- BigIntPolynomial(int N)
- {
- coeffs = new BigInteger[N];
- for (int i = 0; i < N; i++)
- {
- coeffs[i] = Constants.BIGINT_ZERO;
- }
- }
-
- /**
- * Constructs a new polynomial with a given set of coefficients.
- *
- * @param coeffs the coefficients
- */
- BigIntPolynomial(BigInteger[] coeffs)
- {
- this.coeffs = coeffs;
- }
-
- /**
- * Constructs a <code>BigIntPolynomial</code> from a <code>IntegerPolynomial</code>. The two polynomials are
- * independent of each other.
- *
- * @param p the original polynomial
- */
- public BigIntPolynomial(IntegerPolynomial p)
- {
- coeffs = new BigInteger[p.coeffs.length];
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] = BigInteger.valueOf(p.coeffs[i]);
- }
- }
-
- /**
- * Generates a random polynomial with <code>numOnes</code> coefficients equal to 1,
- * <code>numNegOnes</code> coefficients equal to -1, and the rest equal to 0.
- *
- * @param N number of coefficients
- * @param numOnes number of 1's
- * @param numNegOnes number of -1's
- * @return
- */
- static BigIntPolynomial generateRandomSmall(int N, int numOnes, int numNegOnes)
- {
- List coeffs = new ArrayList();
- for (int i = 0; i < numOnes; i++)
- {
- coeffs.add(Constants.BIGINT_ONE);
- }
- for (int i = 0; i < numNegOnes; i++)
- {
- coeffs.add(BigInteger.valueOf(-1));
- }
- while (coeffs.size() < N)
- {
- coeffs.add(Constants.BIGINT_ZERO);
- }
- Collections.shuffle(coeffs, new SecureRandom());
-
- BigIntPolynomial poly = new BigIntPolynomial(N);
- for (int i = 0; i < coeffs.size(); i++)
- {
- poly.coeffs[i] = (BigInteger)coeffs.get(i);
- }
- return poly;
- }
-
- /**
- * Multiplies the polynomial by another, taking the indices mod N. Does not
- * change this polynomial but returns the result as a new polynomial.<br>
- * Both polynomials must have the same number of coefficients.
- *
- * @param poly2 the polynomial to multiply by
- * @return a new polynomial
- */
- public BigIntPolynomial mult(BigIntPolynomial poly2)
- {
- int N = coeffs.length;
- if (poly2.coeffs.length != N)
- {
- throw new IllegalArgumentException("Number of coefficients must be the same");
- }
-
- BigIntPolynomial c = multRecursive(poly2);
-
- if (c.coeffs.length > N)
- {
- for (int k = N; k < c.coeffs.length; k++)
- {
- c.coeffs[k - N] = c.coeffs[k - N].add(c.coeffs[k]);
- }
- c.coeffs = Arrays.copyOf(c.coeffs, N);
- }
- return c;
- }
-
- /**
- * Karazuba multiplication
- */
- private BigIntPolynomial multRecursive(BigIntPolynomial poly2)
- {
- BigInteger[] a = coeffs;
- BigInteger[] b = poly2.coeffs;
-
- int n = poly2.coeffs.length;
- if (n <= 1)
- {
- BigInteger[] c = Arrays.clone(coeffs);
- for (int i = 0; i < coeffs.length; i++)
- {
- c[i] = c[i].multiply(poly2.coeffs[0]);
- }
- return new BigIntPolynomial(c);
- }
- else
- {
- int n1 = n / 2;
-
- BigIntPolynomial a1 = new BigIntPolynomial(Arrays.copyOf(a, n1));
- BigIntPolynomial a2 = new BigIntPolynomial(Arrays.copyOfRange(a, n1, n));
- BigIntPolynomial b1 = new BigIntPolynomial(Arrays.copyOf(b, n1));
- BigIntPolynomial b2 = new BigIntPolynomial(Arrays.copyOfRange(b, n1, n));
-
- BigIntPolynomial A = (BigIntPolynomial)a1.clone();
- A.add(a2);
- BigIntPolynomial B = (BigIntPolynomial)b1.clone();
- B.add(b2);
-
- BigIntPolynomial c1 = a1.multRecursive(b1);
- BigIntPolynomial c2 = a2.multRecursive(b2);
- BigIntPolynomial c3 = A.multRecursive(B);
- c3.sub(c1);
- c3.sub(c2);
-
- BigIntPolynomial c = new BigIntPolynomial(2 * n - 1);
- for (int i = 0; i < c1.coeffs.length; i++)
- {
- c.coeffs[i] = c1.coeffs[i];
- }
- for (int i = 0; i < c3.coeffs.length; i++)
- {
- c.coeffs[n1 + i] = c.coeffs[n1 + i].add(c3.coeffs[i]);
- }
- for (int i = 0; i < c2.coeffs.length; i++)
- {
- c.coeffs[2 * n1 + i] = c.coeffs[2 * n1 + i].add(c2.coeffs[i]);
- }
- return c;
- }
- }
-
- /**
- * Adds another polynomial which can have a different number of coefficients,
- * and takes the coefficient values mod <code>modulus</code>.
- *
- * @param b another polynomial
- */
- void add(BigIntPolynomial b, BigInteger modulus)
- {
- add(b);
- mod(modulus);
- }
-
- /**
- * Adds another polynomial which can have a different number of coefficients.
- *
- * @param b another polynomial
- */
- public void add(BigIntPolynomial b)
- {
- if (b.coeffs.length > coeffs.length)
- {
- int N = coeffs.length;
- coeffs = Arrays.copyOf(coeffs, b.coeffs.length);
- for (int i = N; i < coeffs.length; i++)
- {
- coeffs[i] = Constants.BIGINT_ZERO;
- }
- }
- for (int i = 0; i < b.coeffs.length; i++)
- {
- coeffs[i] = coeffs[i].add(b.coeffs[i]);
- }
- }
-
- /**
- * Subtracts another polynomial which can have a different number of coefficients.
- *
- * @param b another polynomial
- */
- public void sub(BigIntPolynomial b)
- {
- if (b.coeffs.length > coeffs.length)
- {
- int N = coeffs.length;
- coeffs = Arrays.copyOf(coeffs, b.coeffs.length);
- for (int i = N; i < coeffs.length; i++)
- {
- coeffs[i] = Constants.BIGINT_ZERO;
- }
- }
- for (int i = 0; i < b.coeffs.length; i++)
- {
- coeffs[i] = coeffs[i].subtract(b.coeffs[i]);
- }
- }
-
- /**
- * Multiplies each coefficient by a <code>BigInteger</code>. Does not return a new polynomial but modifies this polynomial.
- *
- * @param factor
- */
- public void mult(BigInteger factor)
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] = coeffs[i].multiply(factor);
- }
- }
-
- /**
- * Multiplies each coefficient by a <code>int</code>. Does not return a new polynomial but modifies this polynomial.
- *
- * @param factor
- */
- void mult(int factor)
- {
- mult(BigInteger.valueOf(factor));
- }
-
- /**
- * Divides each coefficient by a <code>BigInteger</code> and rounds the result to the nearest whole number.<br>
- * Does not return a new polynomial but modifies this polynomial.
- *
- * @param divisor the number to divide by
- */
- public void div(BigInteger divisor)
- {
- BigInteger d = divisor.add(Constants.BIGINT_ONE).divide(BigInteger.valueOf(2));
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] = coeffs[i].compareTo(Constants.BIGINT_ZERO) > 0 ? coeffs[i].add(d) : coeffs[i].add(d.negate());
- coeffs[i] = coeffs[i].divide(divisor);
- }
- }
-
- /**
- * Divides each coefficient by a <code>BigDecimal</code> and rounds the result to <code>decimalPlaces</code> places.
- *
- * @param divisor the number to divide by
- * @param decimalPlaces the number of fractional digits to round the result to
- * @return a new <code>BigDecimalPolynomial</code>
- */
- public BigDecimalPolynomial div(BigDecimal divisor, int decimalPlaces)
- {
- BigInteger max = maxCoeffAbs();
- int coeffLength = (int)(max.bitLength() * LOG_10_2) + 1;
- // factor = 1/divisor
- BigDecimal factor = Constants.BIGDEC_ONE.divide(divisor, coeffLength + decimalPlaces + 1, BigDecimal.ROUND_HALF_EVEN);
-
- // multiply each coefficient by factor
- BigDecimalPolynomial p = new BigDecimalPolynomial(coeffs.length);
- for (int i = 0; i < coeffs.length; i++)
- // multiply, then truncate after decimalPlaces so subsequent operations aren't slowed down
- {
- p.coeffs[i] = new BigDecimal(coeffs[i]).multiply(factor).setScale(decimalPlaces, BigDecimal.ROUND_HALF_EVEN);
- }
-
- return p;
- }
-
- /**
- * Returns the base10 length of the largest coefficient.
- *
- * @return length of the longest coefficient
- */
- public int getMaxCoeffLength()
- {
- return (int)(maxCoeffAbs().bitLength() * LOG_10_2) + 1;
- }
-
- private BigInteger maxCoeffAbs()
- {
- BigInteger max = coeffs[0].abs();
- for (int i = 1; i < coeffs.length; i++)
- {
- BigInteger coeff = coeffs[i].abs();
- if (coeff.compareTo(max) > 0)
- {
- max = coeff;
- }
- }
- return max;
- }
-
- /**
- * Takes each coefficient modulo a number.
- *
- * @param modulus
- */
- public void mod(BigInteger modulus)
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] = coeffs[i].mod(modulus);
- }
- }
-
- /**
- * Returns the sum of all coefficients, i.e. evaluates the polynomial at 0.
- *
- * @return the sum of all coefficients
- */
- BigInteger sumCoeffs()
- {
- BigInteger sum = Constants.BIGINT_ZERO;
- for (int i = 0; i < coeffs.length; i++)
- {
- sum = sum.add(coeffs[i]);
- }
- return sum;
- }
-
- /**
- * Makes a copy of the polynomial that is independent of the original.
- */
- public Object clone()
- {
- return new BigIntPolynomial(coeffs.clone());
- }
-
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = prime * result + Arrays.hashCode(coeffs);
- return result;
- }
-
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj == null)
- {
- return false;
- }
- if (getClass() != obj.getClass())
- {
- return false;
- }
- BigIntPolynomial other = (BigIntPolynomial)obj;
- if (!Arrays.areEqual(coeffs, other.coeffs))
- {
- return false;
- }
- return true;
- }
-
- public BigInteger[] getCoeffs()
- {
- return Arrays.clone(coeffs);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Constants.java b/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Constants.java
deleted file mode 100644
index 2b41b19a..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Constants.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-
-public class Constants
-{
- static final BigInteger BIGINT_ZERO = BigInteger.valueOf(0);
- static final BigInteger BIGINT_ONE = BigInteger.valueOf(1);
-
- static final BigDecimal BIGDEC_ONE = BigDecimal.valueOf(1);
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/DenseTernaryPolynomial.java b/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/DenseTernaryPolynomial.java
deleted file mode 100644
index 85730dab..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/DenseTernaryPolynomial.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.pqc.math.ntru.util.Util;
-import org.bouncycastle.util.Arrays;
-
-/**
- * A <code>TernaryPolynomial</code> with a "high" number of nonzero coefficients.
- */
-public class DenseTernaryPolynomial
- extends IntegerPolynomial
- implements TernaryPolynomial
-{
-
- /**
- * Constructs a new <code>DenseTernaryPolynomial</code> with <code>N</code> coefficients.
- *
- * @param N the number of coefficients
- */
- DenseTernaryPolynomial(int N)
- {
- super(N);
- checkTernarity();
- }
-
- /**
- * Constructs a <code>DenseTernaryPolynomial</code> from a <code>IntegerPolynomial</code>. The two polynomials are
- * independent of each other.
- *
- * @param intPoly the original polynomial
- */
- public DenseTernaryPolynomial(IntegerPolynomial intPoly)
- {
- this(intPoly.coeffs);
- }
-
- /**
- * Constructs a new <code>DenseTernaryPolynomial</code> with a given set of coefficients.
- *
- * @param coeffs the coefficients
- */
- public DenseTernaryPolynomial(int[] coeffs)
- {
- super(coeffs);
- checkTernarity();
- }
-
- private void checkTernarity()
- {
- for (int i = 0; i != coeffs.length; i++)
- {
- int c = coeffs[i];
- if (c < -1 || c > 1)
- {
- throw new IllegalStateException("Illegal value: " + c + ", must be one of {-1, 0, 1}");
- }
- }
- }
-
- /**
- * Generates a random polynomial with <code>numOnes</code> coefficients equal to 1,
- * <code>numNegOnes</code> coefficients equal to -1, and the rest equal to 0.
- *
- * @param N number of coefficients
- * @param numOnes number of 1's
- * @param numNegOnes number of -1's
- */
- public static DenseTernaryPolynomial generateRandom(int N, int numOnes, int numNegOnes, SecureRandom random)
- {
- int[] coeffs = Util.generateRandomTernary(N, numOnes, numNegOnes, random);
- return new DenseTernaryPolynomial(coeffs);
- }
-
- /**
- * Generates a polynomial with coefficients randomly selected from <code>{-1, 0, 1}</code>.
- *
- * @param N number of coefficients
- */
- public static DenseTernaryPolynomial generateRandom(int N, SecureRandom random)
- {
- DenseTernaryPolynomial poly = new DenseTernaryPolynomial(N);
- for (int i = 0; i < N; i++)
- {
- poly.coeffs[i] = random.nextInt(3) - 1;
- }
- return poly;
- }
-
- public IntegerPolynomial mult(IntegerPolynomial poly2, int modulus)
- {
- // even on 32-bit systems, LongPolynomial5 multiplies faster than IntegerPolynomial
- if (modulus == 2048)
- {
- IntegerPolynomial poly2Pos = (IntegerPolynomial)poly2.clone();
- poly2Pos.modPositive(2048);
- LongPolynomial5 poly5 = new LongPolynomial5(poly2Pos);
- return poly5.mult(this).toIntegerPolynomial();
- }
- else
- {
- return super.mult(poly2, modulus);
- }
- }
-
- public int[] getOnes()
- {
- int N = coeffs.length;
- int[] ones = new int[N];
- int onesIdx = 0;
- for (int i = 0; i < N; i++)
- {
- int c = coeffs[i];
- if (c == 1)
- {
- ones[onesIdx++] = i;
- }
- }
- return Arrays.copyOf(ones, onesIdx);
- }
-
- public int[] getNegOnes()
- {
- int N = coeffs.length;
- int[] negOnes = new int[N];
- int negOnesIdx = 0;
- for (int i = 0; i < N; i++)
- {
- int c = coeffs[i];
- if (c == -1)
- {
- negOnes[negOnesIdx++] = i;
- }
- }
- return Arrays.copyOf(negOnes, negOnesIdx);
- }
-
- public int size()
- {
- return coeffs.length;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/IntegerPolynomial.java b/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/IntegerPolynomial.java
deleted file mode 100644
index c6bd7fbc..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/IntegerPolynomial.java
+++ /dev/null
@@ -1,1358 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.LinkedBlockingQueue;
-
-import org.bouncycastle.pqc.math.ntru.euclid.BigIntEuclidean;
-import org.bouncycastle.pqc.math.ntru.util.ArrayEncoder;
-import org.bouncycastle.pqc.math.ntru.util.Util;
-import org.bouncycastle.util.Arrays;
-
-/**
- * A polynomial with <code>int</code> coefficients.<br>
- * Some methods (like <code>add</code>) change the polynomial, others (like <code>mult</code>) do
- * not but return the result as a new polynomial.
- */
-public class IntegerPolynomial
- implements Polynomial
-{
- private static final int NUM_EQUAL_RESULTANTS = 3;
- /**
- * Prime numbers &gt; 4500 for resultant computation. Starting them below ~4400 causes incorrect results occasionally.
- * Fortunately, 4500 is about the optimum number for performance.<br/>
- * This array contains enough prime numbers so primes never have to be computed on-line for any standard {@link org.bouncycastle.pqc.crypto.ntru.NTRUSigningParameters}.
- */
- private static final int[] PRIMES = new int[]{
- 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583,
- 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657,
- 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751,
- 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831,
- 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937,
- 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003,
- 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087,
- 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179,
- 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279,
- 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387,
- 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443,
- 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521,
- 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639,
- 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693,
- 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791,
- 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857,
- 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939,
- 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053,
- 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133,
- 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221,
- 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301,
- 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367,
- 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473,
- 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571,
- 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673,
- 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761,
- 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833,
- 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917,
- 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997,
- 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103,
- 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207,
- 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297,
- 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411,
- 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499,
- 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561,
- 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643,
- 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723,
- 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829,
- 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919,
- 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017,
- 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111,
- 8117, 8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209, 8219,
- 8221, 8231, 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291,
- 8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, 8377, 8387,
- 8389, 8419, 8423, 8429, 8431, 8443, 8447, 8461, 8467, 8501,
- 8513, 8521, 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597,
- 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677,
- 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741,
- 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831,
- 8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929,
- 8933, 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011,
- 9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109,
- 9127, 9133, 9137, 9151, 9157, 9161, 9173, 9181, 9187, 9199,
- 9203, 9209, 9221, 9227, 9239, 9241, 9257, 9277, 9281, 9283,
- 9293, 9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377,
- 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439,
- 9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521, 9533,
- 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629, 9631,
- 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733,
- 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811,
- 9817, 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887,
- 9901, 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973};
- private static final List BIGINT_PRIMES;
-
- static
- {
- BIGINT_PRIMES = new ArrayList();
- for (int i = 0; i != PRIMES.length; i++)
- {
- BIGINT_PRIMES.add(BigInteger.valueOf(PRIMES[i]));
- }
- }
-
- public int[] coeffs;
-
- /**
- * Constructs a new polynomial with <code>N</code> coefficients initialized to 0.
- *
- * @param N the number of coefficients
- */
- public IntegerPolynomial(int N)
- {
- coeffs = new int[N];
- }
-
- /**
- * Constructs a new polynomial with a given set of coefficients.
- *
- * @param coeffs the coefficients
- */
- public IntegerPolynomial(int[] coeffs)
- {
- this.coeffs = coeffs;
- }
-
- /**
- * Constructs a <code>IntegerPolynomial</code> from a <code>BigIntPolynomial</code>. The two polynomials are independent of each other.
- *
- * @param p the original polynomial
- */
- public IntegerPolynomial(BigIntPolynomial p)
- {
- coeffs = new int[p.coeffs.length];
- for (int i = 0; i < p.coeffs.length; i++)
- {
- coeffs[i] = p.coeffs[i].intValue();
- }
- }
-
- /**
- * Decodes a byte array to a polynomial with <code>N</code> ternary coefficients<br>
- * Ignores any excess bytes.
- *
- * @param data an encoded ternary polynomial
- * @param N number of coefficients
- * @return the decoded polynomial
- */
- public static IntegerPolynomial fromBinary3Sves(byte[] data, int N)
- {
- return new IntegerPolynomial(ArrayEncoder.decodeMod3Sves(data, N));
- }
-
- /**
- * Converts a byte array produced by {@link #toBinary3Tight()} to a polynomial.
- *
- * @param b a byte array
- * @param N number of coefficients
- * @return the decoded polynomial
- */
- public static IntegerPolynomial fromBinary3Tight(byte[] b, int N)
- {
- return new IntegerPolynomial(ArrayEncoder.decodeMod3Tight(b, N));
- }
-
- /**
- * Reads data produced by {@link #toBinary3Tight()} from an input stream and converts it to a polynomial.
- *
- * @param is an input stream
- * @param N number of coefficients
- * @return the decoded polynomial
- */
- public static IntegerPolynomial fromBinary3Tight(InputStream is, int N)
- throws IOException
- {
- return new IntegerPolynomial(ArrayEncoder.decodeMod3Tight(is, N));
- }
-
- /**
- * Returns a polynomial with N coefficients between <code>0</code> and <code>q-1</code>.<br>
- * <code>q</code> must be a power of 2.<br>
- * Ignores any excess bytes.
- *
- * @param data an encoded ternary polynomial
- * @param N number of coefficients
- * @param q
- * @return the decoded polynomial
- */
- public static IntegerPolynomial fromBinary(byte[] data, int N, int q)
- {
- return new IntegerPolynomial(ArrayEncoder.decodeModQ(data, N, q));
- }
-
- /**
- * Returns a polynomial with N coefficients between <code>0</code> and <code>q-1</code>.<br>
- * <code>q</code> must be a power of 2.<br>
- * Ignores any excess bytes.
- *
- * @param is an encoded ternary polynomial
- * @param N number of coefficients
- * @param q
- * @return the decoded polynomial
- */
- public static IntegerPolynomial fromBinary(InputStream is, int N, int q)
- throws IOException
- {
- return new IntegerPolynomial(ArrayEncoder.decodeModQ(is, N, q));
- }
-
- /**
- * Encodes a polynomial with ternary coefficients to binary.
- * <code>coeffs[2*i]</code> and <code>coeffs[2*i+1]</code> must not both equal -1 for any integer <code>i</code>,
- * so this method is only safe to use with polynomials produced by <code>fromBinary3Sves()</code>.
- *
- * @return the encoded polynomial
- */
- public byte[] toBinary3Sves()
- {
- return ArrayEncoder.encodeMod3Sves(coeffs);
- }
-
- /**
- * Converts a polynomial with ternary coefficients to binary.
- *
- * @return the encoded polynomial
- */
- public byte[] toBinary3Tight()
- {
- BigInteger sum = Constants.BIGINT_ZERO;
- for (int i = coeffs.length - 1; i >= 0; i--)
- {
- sum = sum.multiply(BigInteger.valueOf(3));
- sum = sum.add(BigInteger.valueOf(coeffs[i] + 1));
- }
-
- int size = (BigInteger.valueOf(3).pow(coeffs.length).bitLength() + 7) / 8;
- byte[] arr = sum.toByteArray();
-
- if (arr.length < size)
- {
- // pad with leading zeros so arr.length==size
- byte[] arr2 = new byte[size];
- System.arraycopy(arr, 0, arr2, size - arr.length, arr.length);
- return arr2;
- }
-
- if (arr.length > size)
- // drop sign bit
- {
- arr = Arrays.copyOfRange(arr, 1, arr.length);
- }
- return arr;
- }
-
- /**
- * Encodes a polynomial whose coefficients are between 0 and q, to binary. q must be a power of 2.
- *
- * @param q
- * @return the encoded polynomial
- */
- public byte[] toBinary(int q)
- {
- return ArrayEncoder.encodeModQ(coeffs, q);
- }
-
- /**
- * Multiplies the polynomial with another, taking the values mod modulus and the indices mod N
- */
- public IntegerPolynomial mult(IntegerPolynomial poly2, int modulus)
- {
- IntegerPolynomial c = mult(poly2);
- c.mod(modulus);
- return c;
- }
-
- /**
- * Multiplies the polynomial with another, taking the indices mod N
- */
- public IntegerPolynomial mult(IntegerPolynomial poly2)
- {
- int N = coeffs.length;
- if (poly2.coeffs.length != N)
- {
- throw new IllegalArgumentException("Number of coefficients must be the same");
- }
-
- IntegerPolynomial c = multRecursive(poly2);
-
- if (c.coeffs.length > N)
- {
- for (int k = N; k < c.coeffs.length; k++)
- {
- c.coeffs[k - N] += c.coeffs[k];
- }
- c.coeffs = Arrays.copyOf(c.coeffs, N);
- }
- return c;
- }
-
- public BigIntPolynomial mult(BigIntPolynomial poly2)
- {
- return new BigIntPolynomial(this).mult(poly2);
- }
-
- /**
- * Karazuba multiplication
- */
- private IntegerPolynomial multRecursive(IntegerPolynomial poly2)
- {
- int[] a = coeffs;
- int[] b = poly2.coeffs;
-
- int n = poly2.coeffs.length;
- if (n <= 32)
- {
- int cn = 2 * n - 1;
- IntegerPolynomial c = new IntegerPolynomial(new int[cn]);
- for (int k = 0; k < cn; k++)
- {
- for (int i = Math.max(0, k - n + 1); i <= Math.min(k, n - 1); i++)
- {
- c.coeffs[k] += b[i] * a[k - i];
- }
- }
- return c;
- }
- else
- {
- int n1 = n / 2;
-
- IntegerPolynomial a1 = new IntegerPolynomial(Arrays.copyOf(a, n1));
- IntegerPolynomial a2 = new IntegerPolynomial(Arrays.copyOfRange(a, n1, n));
- IntegerPolynomial b1 = new IntegerPolynomial(Arrays.copyOf(b, n1));
- IntegerPolynomial b2 = new IntegerPolynomial(Arrays.copyOfRange(b, n1, n));
-
- IntegerPolynomial A = (IntegerPolynomial)a1.clone();
- A.add(a2);
- IntegerPolynomial B = (IntegerPolynomial)b1.clone();
- B.add(b2);
-
- IntegerPolynomial c1 = a1.multRecursive(b1);
- IntegerPolynomial c2 = a2.multRecursive(b2);
- IntegerPolynomial c3 = A.multRecursive(B);
- c3.sub(c1);
- c3.sub(c2);
-
- IntegerPolynomial c = new IntegerPolynomial(2 * n - 1);
- for (int i = 0; i < c1.coeffs.length; i++)
- {
- c.coeffs[i] = c1.coeffs[i];
- }
- for (int i = 0; i < c3.coeffs.length; i++)
- {
- c.coeffs[n1 + i] += c3.coeffs[i];
- }
- for (int i = 0; i < c2.coeffs.length; i++)
- {
- c.coeffs[2 * n1 + i] += c2.coeffs[i];
- }
- return c;
- }
- }
-
- /**
- * Computes the inverse mod <code>q; q</code> must be a power of 2.<br>
- * Returns <code>null</code> if the polynomial is not invertible.
- *
- * @param q the modulus
- * @return a new polynomial
- */
- public IntegerPolynomial invertFq(int q)
- {
- int N = coeffs.length;
- int k = 0;
- IntegerPolynomial b = new IntegerPolynomial(N + 1);
- b.coeffs[0] = 1;
- IntegerPolynomial c = new IntegerPolynomial(N + 1);
- IntegerPolynomial f = new IntegerPolynomial(N + 1);
- f.coeffs = Arrays.copyOf(coeffs, N + 1);
- f.modPositive(2);
- // set g(x) = x^N − 1
- IntegerPolynomial g = new IntegerPolynomial(N + 1);
- g.coeffs[0] = 1;
- g.coeffs[N] = 1;
- while (true)
- {
- while (f.coeffs[0] == 0)
- {
- for (int i = 1; i <= N; i++)
- {
- f.coeffs[i - 1] = f.coeffs[i]; // f(x) = f(x) / x
- c.coeffs[N + 1 - i] = c.coeffs[N - i]; // c(x) = c(x) * x
- }
- f.coeffs[N] = 0;
- c.coeffs[0] = 0;
- k++;
- if (f.equalsZero())
- {
- return null; // not invertible
- }
- }
- if (f.equalsOne())
- {
- break;
- }
- if (f.degree() < g.degree())
- {
- // exchange f and g
- IntegerPolynomial temp = f;
- f = g;
- g = temp;
- // exchange b and c
- temp = b;
- b = c;
- c = temp;
- }
- f.add(g, 2);
- b.add(c, 2);
- }
-
- if (b.coeffs[N] != 0)
- {
- return null;
- }
- // Fq(x) = x^(N-k) * b(x)
- IntegerPolynomial Fq = new IntegerPolynomial(N);
- int j = 0;
- k %= N;
- for (int i = N - 1; i >= 0; i--)
- {
- j = i - k;
- if (j < 0)
- {
- j += N;
- }
- Fq.coeffs[j] = b.coeffs[i];
- }
-
- return mod2ToModq(Fq, q);
- }
-
- /**
- * Computes the inverse mod q from the inverse mod 2
- *
- * @param Fq
- * @param q
- * @return The inverse of this polynomial mod q
- */
- private IntegerPolynomial mod2ToModq(IntegerPolynomial Fq, int q)
- {
- if (Util.is64BitJVM() && q == 2048)
- {
- LongPolynomial2 thisLong = new LongPolynomial2(this);
- LongPolynomial2 FqLong = new LongPolynomial2(Fq);
- int v = 2;
- while (v < q)
- {
- v *= 2;
- LongPolynomial2 temp = (LongPolynomial2)FqLong.clone();
- temp.mult2And(v - 1);
- FqLong = thisLong.mult(FqLong).mult(FqLong);
- temp.subAnd(FqLong, v - 1);
- FqLong = temp;
- }
- return FqLong.toIntegerPolynomial();
- }
- else
- {
- int v = 2;
- while (v < q)
- {
- v *= 2;
- IntegerPolynomial temp = new IntegerPolynomial(Arrays.copyOf(Fq.coeffs, Fq.coeffs.length));
- temp.mult2(v);
- Fq = mult(Fq, v).mult(Fq, v);
- temp.sub(Fq, v);
- Fq = temp;
- }
- return Fq;
- }
- }
-
- /**
- * Computes the inverse mod 3.
- * Returns <code>null</code> if the polynomial is not invertible.
- *
- * @return a new polynomial
- */
- public IntegerPolynomial invertF3()
- {
- int N = coeffs.length;
- int k = 0;
- IntegerPolynomial b = new IntegerPolynomial(N + 1);
- b.coeffs[0] = 1;
- IntegerPolynomial c = new IntegerPolynomial(N + 1);
- IntegerPolynomial f = new IntegerPolynomial(N + 1);
- f.coeffs = Arrays.copyOf(coeffs, N + 1);
- f.modPositive(3);
- // set g(x) = x^N − 1
- IntegerPolynomial g = new IntegerPolynomial(N + 1);
- g.coeffs[0] = -1;
- g.coeffs[N] = 1;
- while (true)
- {
- while (f.coeffs[0] == 0)
- {
- for (int i = 1; i <= N; i++)
- {
- f.coeffs[i - 1] = f.coeffs[i]; // f(x) = f(x) / x
- c.coeffs[N + 1 - i] = c.coeffs[N - i]; // c(x) = c(x) * x
- }
- f.coeffs[N] = 0;
- c.coeffs[0] = 0;
- k++;
- if (f.equalsZero())
- {
- return null; // not invertible
- }
- }
- if (f.equalsAbsOne())
- {
- break;
- }
- if (f.degree() < g.degree())
- {
- // exchange f and g
- IntegerPolynomial temp = f;
- f = g;
- g = temp;
- // exchange b and c
- temp = b;
- b = c;
- c = temp;
- }
- if (f.coeffs[0] == g.coeffs[0])
- {
- f.sub(g, 3);
- b.sub(c, 3);
- }
- else
- {
- f.add(g, 3);
- b.add(c, 3);
- }
- }
-
- if (b.coeffs[N] != 0)
- {
- return null;
- }
- // Fp(x) = [+-] x^(N-k) * b(x)
- IntegerPolynomial Fp = new IntegerPolynomial(N);
- int j = 0;
- k %= N;
- for (int i = N - 1; i >= 0; i--)
- {
- j = i - k;
- if (j < 0)
- {
- j += N;
- }
- Fp.coeffs[j] = f.coeffs[0] * b.coeffs[i];
- }
-
- Fp.ensurePositive(3);
- return Fp;
- }
-
- /**
- * Resultant of this polynomial with <code>x^n-1</code> using a probabilistic algorithm.
- * <p>
- * Unlike EESS, this implementation does not compute all resultants modulo primes
- * such that their product exceeds the maximum possible resultant, but rather stops
- * when <code>NUM_EQUAL_RESULTANTS</code> consecutive modular resultants are equal.<br>
- * This means the return value may be incorrect. Experiments show this happens in
- * about 1 out of 100 cases when <code>N=439</code> and <code>NUM_EQUAL_RESULTANTS=2</code>,
- * so the likelyhood of leaving the loop too early is <code>(1/100)^(NUM_EQUAL_RESULTANTS-1)</code>.
- * <p>
- * Because of the above, callers must verify the output and try a different polynomial if necessary.
- *
- * @return <code>(rho, res)</code> satisfying <code>res = rho*this + t*(x^n-1)</code> for some integer <code>t</code>.
- */
- public Resultant resultant()
- {
- int N = coeffs.length;
-
- // Compute resultants modulo prime numbers. Continue until NUM_EQUAL_RESULTANTS consecutive modular resultants are equal.
- LinkedList<ModularResultant> modResultants = new LinkedList<ModularResultant>();
- BigInteger prime = null;
- BigInteger pProd = Constants.BIGINT_ONE;
- BigInteger res = Constants.BIGINT_ONE;
- int numEqual = 1; // number of consecutive modular resultants equal to each other
- Iterator<BigInteger> primes = BIGINT_PRIMES.iterator();
- while (true)
- {
- prime = primes.hasNext() ? primes.next() : prime.nextProbablePrime();
- ModularResultant crr = resultant(prime.intValue());
- modResultants.add(crr);
-
- BigInteger temp = pProd.multiply(prime);
- BigIntEuclidean er = BigIntEuclidean.calculate(prime, pProd);
- BigInteger resPrev = res;
- res = res.multiply(er.x.multiply(prime));
- BigInteger res2 = crr.res.multiply(er.y.multiply(pProd));
- res = res.add(res2).mod(temp);
- pProd = temp;
-
- BigInteger pProd2 = pProd.divide(BigInteger.valueOf(2));
- BigInteger pProd2n = pProd2.negate();
- if (res.compareTo(pProd2) > 0)
- {
- res = res.subtract(pProd);
- }
- else if (res.compareTo(pProd2n) < 0)
- {
- res = res.add(pProd);
- }
-
- if (res.equals(resPrev))
- {
- numEqual++;
- if (numEqual >= NUM_EQUAL_RESULTANTS)
- {
- break;
- }
- }
- else
- {
- numEqual = 1;
- }
- }
-
- // Combine modular rho's to obtain the final rho.
- // For efficiency, first combine all pairs of small resultants to bigger resultants,
- // then combine pairs of those, etc. until only one is left.
- while (modResultants.size() > 1)
- {
- ModularResultant modRes1 = modResultants.removeFirst();
- ModularResultant modRes2 = modResultants.removeFirst();
- ModularResultant modRes3 = ModularResultant.combineRho(modRes1, modRes2);
- modResultants.addLast(modRes3);
- }
- BigIntPolynomial rhoP = modResultants.getFirst().rho;
-
- BigInteger pProd2 = pProd.divide(BigInteger.valueOf(2));
- BigInteger pProd2n = pProd2.negate();
- if (res.compareTo(pProd2) > 0)
- {
- res = res.subtract(pProd);
- }
- if (res.compareTo(pProd2n) < 0)
- {
- res = res.add(pProd);
- }
-
- for (int i = 0; i < N; i++)
- {
- BigInteger c = rhoP.coeffs[i];
- if (c.compareTo(pProd2) > 0)
- {
- rhoP.coeffs[i] = c.subtract(pProd);
- }
- if (c.compareTo(pProd2n) < 0)
- {
- rhoP.coeffs[i] = c.add(pProd);
- }
- }
-
- return new Resultant(rhoP, res);
- }
-
- /**
- * Multithreaded version of {@link #resultant()}.
- *
- * @return <code>(rho, res)</code> satisfying <code>res = rho*this + t*(x^n-1)</code> for some integer <code>t</code>.
- */
- public Resultant resultantMultiThread()
- {
- int N = coeffs.length;
-
- // upper bound for resultant(f, g) = ||f, 2||^deg(g) * ||g, 2||^deg(f) = squaresum(f)^(N/2) * 2^(deg(f)/2) because g(x)=x^N-1
- // see http://jondalon.mathematik.uni-osnabrueck.de/staff/phpages/brunsw/CompAlg.pdf chapter 3
- BigInteger max = squareSum().pow((N + 1) / 2);
- max = max.multiply(BigInteger.valueOf(2).pow((degree() + 1) / 2));
- BigInteger max2 = max.multiply(BigInteger.valueOf(2));
-
- // compute resultants modulo prime numbers
- BigInteger prime = BigInteger.valueOf(10000);
- BigInteger pProd = Constants.BIGINT_ONE;
- LinkedBlockingQueue<Future<ModularResultant>> resultantTasks = new LinkedBlockingQueue<Future<ModularResultant>>();
- Iterator<BigInteger> primes = BIGINT_PRIMES.iterator();
- ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
- while (pProd.compareTo(max2) < 0)
- {
- if (primes.hasNext())
- {
- prime = primes.next();
- }
- else
- {
- prime = prime.nextProbablePrime();
- }
- Future<ModularResultant> task = executor.submit(new ModResultantTask(prime.intValue()));
- resultantTasks.add(task);
- pProd = pProd.multiply(prime);
- }
-
- // Combine modular resultants to obtain the resultant.
- // For efficiency, first combine all pairs of small resultants to bigger resultants,
- // then combine pairs of those, etc. until only one is left.
- ModularResultant overallResultant = null;
- while (!resultantTasks.isEmpty())
- {
- try
- {
- Future<ModularResultant> modRes1 = resultantTasks.take();
- Future<ModularResultant> modRes2 = resultantTasks.poll();
- if (modRes2 == null)
- {
- // modRes1 is the only one left
- overallResultant = modRes1.get();
- break;
- }
- Future<ModularResultant> newTask = executor.submit(new CombineTask(modRes1.get(), modRes2.get()));
- resultantTasks.add(newTask);
- }
- catch (Exception e)
- {
- throw new IllegalStateException(e.toString());
- }
- }
- executor.shutdown();
- BigInteger res = overallResultant.res;
- BigIntPolynomial rhoP = overallResultant.rho;
-
- BigInteger pProd2 = pProd.divide(BigInteger.valueOf(2));
- BigInteger pProd2n = pProd2.negate();
-
- if (res.compareTo(pProd2) > 0)
- {
- res = res.subtract(pProd);
- }
- if (res.compareTo(pProd2n) < 0)
- {
- res = res.add(pProd);
- }
-
- for (int i = 0; i < N; i++)
- {
- BigInteger c = rhoP.coeffs[i];
- if (c.compareTo(pProd2) > 0)
- {
- rhoP.coeffs[i] = c.subtract(pProd);
- }
- if (c.compareTo(pProd2n) < 0)
- {
- rhoP.coeffs[i] = c.add(pProd);
- }
- }
-
- return new Resultant(rhoP, res);
- }
-
- /**
- * Resultant of this polynomial with <code>x^n-1 mod p</code>.
- *
- * @return <code>(rho, res)</code> satisfying <code>res = rho*this + t*(x^n-1) mod p</code> for some integer <code>t</code>.
- */
- public ModularResultant resultant(int p)
- {
- // Add a coefficient as the following operations involve polynomials of degree deg(f)+1
- int[] fcoeffs = Arrays.copyOf(coeffs, coeffs.length + 1);
- IntegerPolynomial f = new IntegerPolynomial(fcoeffs);
- int N = fcoeffs.length;
-
- IntegerPolynomial a = new IntegerPolynomial(N);
- a.coeffs[0] = -1;
- a.coeffs[N - 1] = 1;
- IntegerPolynomial b = new IntegerPolynomial(f.coeffs);
- IntegerPolynomial v1 = new IntegerPolynomial(N);
- IntegerPolynomial v2 = new IntegerPolynomial(N);
- v2.coeffs[0] = 1;
- int da = N - 1;
- int db = b.degree();
- int ta = da;
- int c = 0;
- int r = 1;
- while (db > 0)
- {
- c = Util.invert(b.coeffs[db], p);
- c = (c * a.coeffs[da]) % p;
- a.multShiftSub(b, c, da - db, p);
- v1.multShiftSub(v2, c, da - db, p);
-
- da = a.degree();
- if (da < db)
- {
- r *= Util.pow(b.coeffs[db], ta - da, p);
- r %= p;
- if (ta % 2 == 1 && db % 2 == 1)
- {
- r = (-r) % p;
- }
- IntegerPolynomial temp = a;
- a = b;
- b = temp;
- int tempdeg = da;
- da = db;
- temp = v1;
- v1 = v2;
- v2 = temp;
- ta = db;
- db = tempdeg;
- }
- }
- r *= Util.pow(b.coeffs[0], da, p);
- r %= p;
- c = Util.invert(b.coeffs[0], p);
- v2.mult(c);
- v2.mod(p);
- v2.mult(r);
- v2.mod(p);
-
- // drop the highest coefficient so #coeffs matches the original input
- v2.coeffs = Arrays.copyOf(v2.coeffs, v2.coeffs.length - 1);
- return new ModularResultant(new BigIntPolynomial(v2), BigInteger.valueOf(r), BigInteger.valueOf(p));
- }
-
- /**
- * Computes <code>this-b*c*(x^k) mod p</code> and stores the result in this polynomial.<br/>
- * See steps 4a,4b in EESS algorithm 2.2.7.1.
- *
- * @param b
- * @param c
- * @param k
- * @param p
- */
- private void multShiftSub(IntegerPolynomial b, int c, int k, int p)
- {
- int N = coeffs.length;
- for (int i = k; i < N; i++)
- {
- coeffs[i] = (coeffs[i] - b.coeffs[i - k] * c) % p;
- }
- }
-
- /**
- * Adds the squares of all coefficients.
- *
- * @return the sum of squares
- */
- private BigInteger squareSum()
- {
- BigInteger sum = Constants.BIGINT_ZERO;
- for (int i = 0; i < coeffs.length; i++)
- {
- sum = sum.add(BigInteger.valueOf(coeffs[i] * coeffs[i]));
- }
- return sum;
- }
-
- /**
- * Returns the degree of the polynomial
- *
- * @return the degree
- */
- int degree()
- {
- int degree = coeffs.length - 1;
- while (degree > 0 && coeffs[degree] == 0)
- {
- degree--;
- }
- return degree;
- }
-
- /**
- * Adds another polynomial which can have a different number of coefficients,
- * and takes the coefficient values mod <code>modulus</code>.
- *
- * @param b another polynomial
- */
- public void add(IntegerPolynomial b, int modulus)
- {
- add(b);
- mod(modulus);
- }
-
- /**
- * Adds another polynomial which can have a different number of coefficients.
- *
- * @param b another polynomial
- */
- public void add(IntegerPolynomial b)
- {
- if (b.coeffs.length > coeffs.length)
- {
- coeffs = Arrays.copyOf(coeffs, b.coeffs.length);
- }
- for (int i = 0; i < b.coeffs.length; i++)
- {
- coeffs[i] += b.coeffs[i];
- }
- }
-
- /**
- * Subtracts another polynomial which can have a different number of coefficients,
- * and takes the coefficient values mod <code>modulus</code>.
- *
- * @param b another polynomial
- */
- public void sub(IntegerPolynomial b, int modulus)
- {
- sub(b);
- mod(modulus);
- }
-
- /**
- * Subtracts another polynomial which can have a different number of coefficients.
- *
- * @param b another polynomial
- */
- public void sub(IntegerPolynomial b)
- {
- if (b.coeffs.length > coeffs.length)
- {
- coeffs = Arrays.copyOf(coeffs, b.coeffs.length);
- }
- for (int i = 0; i < b.coeffs.length; i++)
- {
- coeffs[i] -= b.coeffs[i];
- }
- }
-
- /**
- * Subtracts a <code>int</code> from each coefficient. Does not return a new polynomial but modifies this polynomial.
- *
- * @param b
- */
- void sub(int b)
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] -= b;
- }
- }
-
- /**
- * Multiplies each coefficient by a <code>int</code>. Does not return a new polynomial but modifies this polynomial.
- *
- * @param factor
- */
- public void mult(int factor)
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] *= factor;
- }
- }
-
- /**
- * Multiplies each coefficient by a 2 and applies a modulus. Does not return a new polynomial but modifies this polynomial.
- *
- * @param modulus a modulus
- */
- private void mult2(int modulus)
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] *= 2;
- coeffs[i] %= modulus;
- }
- }
-
- /**
- * Multiplies each coefficient by a 2 and applies a modulus. Does not return a new polynomial but modifies this polynomial.
- *
- * @param modulus a modulus
- */
- public void mult3(int modulus)
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] *= 3;
- coeffs[i] %= modulus;
- }
- }
-
- /**
- * Divides each coefficient by <code>k</code> and rounds to the nearest integer. Does not return a new polynomial but modifies this polynomial.
- *
- * @param k the divisor
- */
- public void div(int k)
- {
- int k2 = (k + 1) / 2;
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] += coeffs[i] > 0 ? k2 : -k2;
- coeffs[i] /= k;
- }
- }
-
- /**
- * Takes each coefficient modulo 3 such that all coefficients are ternary.
- */
- public void mod3()
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] %= 3;
- if (coeffs[i] > 1)
- {
- coeffs[i] -= 3;
- }
- if (coeffs[i] < -1)
- {
- coeffs[i] += 3;
- }
- }
- }
-
- /**
- * Ensures all coefficients are between 0 and <code>modulus-1</code>
- *
- * @param modulus a modulus
- */
- public void modPositive(int modulus)
- {
- mod(modulus);
- ensurePositive(modulus);
- }
-
- /**
- * Reduces all coefficients to the interval [-modulus/2, modulus/2)
- */
- void modCenter(int modulus)
- {
- mod(modulus);
- for (int j = 0; j < coeffs.length; j++)
- {
- while (coeffs[j] < modulus / 2)
- {
- coeffs[j] += modulus;
- }
- while (coeffs[j] >= modulus / 2)
- {
- coeffs[j] -= modulus;
- }
- }
- }
-
- /**
- * Takes each coefficient modulo <code>modulus</code>.
- */
- public void mod(int modulus)
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] %= modulus;
- }
- }
-
- /**
- * Adds <code>modulus</code> until all coefficients are above 0.
- *
- * @param modulus a modulus
- */
- public void ensurePositive(int modulus)
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- while (coeffs[i] < 0)
- {
- coeffs[i] += modulus;
- }
- }
- }
-
- /**
- * Computes the centered euclidean norm of the polynomial.
- *
- * @param q a modulus
- * @return the centered norm
- */
- public long centeredNormSq(int q)
- {
- int N = coeffs.length;
- IntegerPolynomial p = (IntegerPolynomial)clone();
- p.shiftGap(q);
-
- long sum = 0;
- long sqSum = 0;
- for (int i = 0; i != p.coeffs.length; i++)
- {
- int c = p.coeffs[i];
- sum += c;
- sqSum += c * c;
- }
-
- long centeredNormSq = sqSum - sum * sum / N;
- return centeredNormSq;
- }
-
- /**
- * Shifts all coefficients so the largest gap is centered around <code>-q/2</code>.
- *
- * @param q a modulus
- */
- void shiftGap(int q)
- {
- modCenter(q);
-
- int[] sorted = Arrays.clone(coeffs);
-
- sort(sorted);
-
- int maxrange = 0;
- int maxrangeStart = 0;
- for (int i = 0; i < sorted.length - 1; i++)
- {
- int range = sorted[i + 1] - sorted[i];
- if (range > maxrange)
- {
- maxrange = range;
- maxrangeStart = sorted[i];
- }
- }
-
- int pmin = sorted[0];
- int pmax = sorted[sorted.length - 1];
-
- int j = q - pmax + pmin;
- int shift;
- if (j > maxrange)
- {
- shift = (pmax + pmin) / 2;
- }
- else
- {
- shift = maxrangeStart + maxrange / 2 + q / 2;
- }
-
- sub(shift);
- }
-
- private void sort(int[] ints)
- {
- boolean swap = true;
-
- while (swap)
- {
- swap = false;
- for (int i = 0; i != ints.length - 1; i++)
- {
- if (ints[i] > ints[i+1])
- {
- int tmp = ints[i];
- ints[i] = ints[i+1];
- ints[i+1] = tmp;
- swap = true;
- }
- }
- }
- }
-
- /**
- * Shifts the values of all coefficients to the interval <code>[-q/2, q/2]</code>.
- *
- * @param q a modulus
- */
- public void center0(int q)
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- while (coeffs[i] < -q / 2)
- {
- coeffs[i] += q;
- }
- while (coeffs[i] > q / 2)
- {
- coeffs[i] -= q;
- }
- }
- }
-
- /**
- * Returns the sum of all coefficients, i.e. evaluates the polynomial at 0.
- *
- * @return the sum of all coefficients
- */
- public int sumCoeffs()
- {
- int sum = 0;
- for (int i = 0; i < coeffs.length; i++)
- {
- sum += coeffs[i];
- }
- return sum;
- }
-
- /**
- * Tests if <code>p(x) = 0</code>.
- *
- * @return true iff all coefficients are zeros
- */
- private boolean equalsZero()
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- if (coeffs[i] != 0)
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Tests if <code>p(x) = 1</code>.
- *
- * @return true iff all coefficients are equal to zero, except for the lowest coefficient which must equal 1
- */
- public boolean equalsOne()
- {
- for (int i = 1; i < coeffs.length; i++)
- {
- if (coeffs[i] != 0)
- {
- return false;
- }
- }
- return coeffs[0] == 1;
- }
-
- /**
- * Tests if <code>|p(x)| = 1</code>.
- *
- * @return true iff all coefficients are equal to zero, except for the lowest coefficient which must equal 1 or -1
- */
- private boolean equalsAbsOne()
- {
- for (int i = 1; i < coeffs.length; i++)
- {
- if (coeffs[i] != 0)
- {
- return false;
- }
- }
- return Math.abs(coeffs[0]) == 1;
- }
-
- /**
- * Counts the number of coefficients equal to an integer
- *
- * @param value an integer
- * @return the number of coefficients equal to <code>value</code>
- */
- public int count(int value)
- {
- int count = 0;
- for (int i = 0; i != coeffs.length; i++)
- {
- if (coeffs[i] == value)
- {
- count++;
- }
- }
- return count;
- }
-
- /**
- * Multiplication by <code>X</code> in <code>Z[X]/Z[X^n-1]</code>.
- */
- public void rotate1()
- {
- int clast = coeffs[coeffs.length - 1];
- for (int i = coeffs.length - 1; i > 0; i--)
- {
- coeffs[i] = coeffs[i - 1];
- }
- coeffs[0] = clast;
- }
-
- public void clear()
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] = 0;
- }
- }
-
- public IntegerPolynomial toIntegerPolynomial()
- {
- return (IntegerPolynomial)clone();
- }
-
- public Object clone()
- {
- return new IntegerPolynomial(coeffs.clone());
- }
-
- public boolean equals(Object obj)
- {
- if (obj instanceof IntegerPolynomial)
- {
- return Arrays.areEqual(coeffs, ((IntegerPolynomial)obj).coeffs);
- }
- else
- {
- return false;
- }
- }
-
- /**
- * Calls {@link IntegerPolynomial#resultant(int)
- */
- private class ModResultantTask
- implements Callable<ModularResultant>
- {
- private int modulus;
-
- private ModResultantTask(int modulus)
- {
- this.modulus = modulus;
- }
-
- public ModularResultant call()
- {
- return resultant(modulus);
- }
- }
-
- /**
- * Calls {@link ModularResultant#combineRho(ModularResultant, ModularResultant)
- */
- private class CombineTask
- implements Callable<ModularResultant>
- {
- private ModularResultant modRes1;
- private ModularResultant modRes2;
-
- private CombineTask(ModularResultant modRes1, ModularResultant modRes2)
- {
- this.modRes1 = modRes1;
- this.modRes2 = modRes2;
- }
-
- public ModularResultant call()
- {
- return ModularResultant.combineRho(modRes1, modRes2);
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/LongPolynomial2.java b/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/LongPolynomial2.java
deleted file mode 100644
index d71615a3..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/LongPolynomial2.java
+++ /dev/null
@@ -1,255 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * A polynomial class that combines two coefficients into one <code>long</code> value for
- * faster multiplication in 64 bit environments.<br>
- * Coefficients can be between 0 and 2047 and are stored in pairs in the bits 0..10 and 24..34 of a <code>long</code> number.
- */
-public class LongPolynomial2
-{
- private long[] coeffs; // each representing two coefficients in the original IntegerPolynomial
- private int numCoeffs;
-
- /**
- * Constructs a <code>LongPolynomial2</code> from a <code>IntegerPolynomial</code>. The two polynomials are independent of each other.
- *
- * @param p the original polynomial. Coefficients must be between 0 and 2047.
- */
- public LongPolynomial2(IntegerPolynomial p)
- {
- numCoeffs = p.coeffs.length;
- coeffs = new long[(numCoeffs + 1) / 2];
- int idx = 0;
- for (int pIdx = 0; pIdx < numCoeffs; )
- {
- int c0 = p.coeffs[pIdx++];
- while (c0 < 0)
- {
- c0 += 2048;
- }
- long c1 = pIdx < numCoeffs ? p.coeffs[pIdx++] : 0;
- while (c1 < 0)
- {
- c1 += 2048;
- }
- coeffs[idx] = c0 + (c1 << 24);
- idx++;
- }
- }
-
- private LongPolynomial2(long[] coeffs)
- {
- this.coeffs = coeffs;
- }
-
- private LongPolynomial2(int N)
- {
- coeffs = new long[N];
- }
-
- /**
- * Multiplies the polynomial with another, taking the indices mod N and the values mod 2048.
- */
- public LongPolynomial2 mult(LongPolynomial2 poly2)
- {
- int N = coeffs.length;
- if (poly2.coeffs.length != N || numCoeffs != poly2.numCoeffs)
- {
- throw new IllegalArgumentException("Number of coefficients must be the same");
- }
-
- LongPolynomial2 c = multRecursive(poly2);
-
- if (c.coeffs.length > N)
- {
- if (numCoeffs % 2 == 0)
- {
- for (int k = N; k < c.coeffs.length; k++)
- {
- c.coeffs[k - N] = (c.coeffs[k - N] + c.coeffs[k]) & 0x7FF0007FFL;
- }
- c.coeffs = Arrays.copyOf(c.coeffs, N);
- }
- else
- {
- for (int k = N; k < c.coeffs.length; k++)
- {
- c.coeffs[k - N] = c.coeffs[k - N] + (c.coeffs[k - 1] >> 24);
- c.coeffs[k - N] = c.coeffs[k - N] + ((c.coeffs[k] & 2047) << 24);
- c.coeffs[k - N] &= 0x7FF0007FFL;
- }
- c.coeffs = Arrays.copyOf(c.coeffs, N);
- c.coeffs[c.coeffs.length - 1] &= 2047;
- }
- }
-
- c = new LongPolynomial2(c.coeffs);
- c.numCoeffs = numCoeffs;
- return c;
- }
-
- public IntegerPolynomial toIntegerPolynomial()
- {
- int[] intCoeffs = new int[numCoeffs];
- int uIdx = 0;
- for (int i = 0; i < coeffs.length; i++)
- {
- intCoeffs[uIdx++] = (int)(coeffs[i] & 2047);
- if (uIdx < numCoeffs)
- {
- intCoeffs[uIdx++] = (int)((coeffs[i] >> 24) & 2047);
- }
- }
- return new IntegerPolynomial(intCoeffs);
- }
-
- /**
- * Karazuba multiplication
- */
- private LongPolynomial2 multRecursive(LongPolynomial2 poly2)
- {
- long[] a = coeffs;
- long[] b = poly2.coeffs;
-
- int n = poly2.coeffs.length;
- if (n <= 32)
- {
- int cn = 2 * n;
- LongPolynomial2 c = new LongPolynomial2(new long[cn]);
- for (int k = 0; k < cn; k++)
- {
- for (int i = Math.max(0, k - n + 1); i <= Math.min(k, n - 1); i++)
- {
- long c0 = a[k - i] * b[i];
- long cu = c0 & 0x7FF000000L + (c0 & 2047);
- long co = (c0 >>> 48) & 2047;
-
- c.coeffs[k] = (c.coeffs[k] + cu) & 0x7FF0007FFL;
- c.coeffs[k + 1] = (c.coeffs[k + 1] + co) & 0x7FF0007FFL;
- }
- }
- return c;
- }
- else
- {
- int n1 = n / 2;
-
- LongPolynomial2 a1 = new LongPolynomial2(Arrays.copyOf(a, n1));
- LongPolynomial2 a2 = new LongPolynomial2(Arrays.copyOfRange(a, n1, n));
- LongPolynomial2 b1 = new LongPolynomial2(Arrays.copyOf(b, n1));
- LongPolynomial2 b2 = new LongPolynomial2(Arrays.copyOfRange(b, n1, n));
-
- LongPolynomial2 A = (LongPolynomial2)a1.clone();
- A.add(a2);
- LongPolynomial2 B = (LongPolynomial2)b1.clone();
- B.add(b2);
-
- LongPolynomial2 c1 = a1.multRecursive(b1);
- LongPolynomial2 c2 = a2.multRecursive(b2);
- LongPolynomial2 c3 = A.multRecursive(B);
- c3.sub(c1);
- c3.sub(c2);
-
- LongPolynomial2 c = new LongPolynomial2(2 * n);
- for (int i = 0; i < c1.coeffs.length; i++)
- {
- c.coeffs[i] = c1.coeffs[i] & 0x7FF0007FFL;
- }
- for (int i = 0; i < c3.coeffs.length; i++)
- {
- c.coeffs[n1 + i] = (c.coeffs[n1 + i] + c3.coeffs[i]) & 0x7FF0007FFL;
- }
- for (int i = 0; i < c2.coeffs.length; i++)
- {
- c.coeffs[2 * n1 + i] = (c.coeffs[2 * n1 + i] + c2.coeffs[i]) & 0x7FF0007FFL;
- }
- return c;
- }
- }
-
- /**
- * Adds another polynomial which can have a different number of coefficients.
- *
- * @param b another polynomial
- */
- private void add(LongPolynomial2 b)
- {
- if (b.coeffs.length > coeffs.length)
- {
- coeffs = Arrays.copyOf(coeffs, b.coeffs.length);
- }
- for (int i = 0; i < b.coeffs.length; i++)
- {
- coeffs[i] = (coeffs[i] + b.coeffs[i]) & 0x7FF0007FFL;
- }
- }
-
- /**
- * Subtracts another polynomial which can have a different number of coefficients.
- *
- * @param b another polynomial
- */
- private void sub(LongPolynomial2 b)
- {
- if (b.coeffs.length > coeffs.length)
- {
- coeffs = Arrays.copyOf(coeffs, b.coeffs.length);
- }
- for (int i = 0; i < b.coeffs.length; i++)
- {
- coeffs[i] = (0x0800000800000L + coeffs[i] - b.coeffs[i]) & 0x7FF0007FFL;
- }
- }
-
- /**
- * Subtracts another polynomial which must have the same number of coefficients,
- * and applies an AND mask to the upper and lower halves of each coefficients.
- *
- * @param b another polynomial
- * @param mask a bit mask less than 2048 to apply to each 11-bit coefficient
- */
- public void subAnd(LongPolynomial2 b, int mask)
- {
- long longMask = (((long)mask) << 24) + mask;
- for (int i = 0; i < b.coeffs.length; i++)
- {
- coeffs[i] = (0x0800000800000L + coeffs[i] - b.coeffs[i]) & longMask;
- }
- }
-
- /**
- * Multiplies this polynomial by 2 and applies an AND mask to the upper and
- * lower halves of each coefficients.
- *
- * @param mask a bit mask less than 2048 to apply to each 11-bit coefficient
- */
- public void mult2And(int mask)
- {
- long longMask = (((long)mask) << 24) + mask;
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] = (coeffs[i] << 1) & longMask;
- }
- }
-
- public Object clone()
- {
- LongPolynomial2 p = new LongPolynomial2(coeffs.clone());
- p.numCoeffs = numCoeffs;
- return p;
- }
-
- public boolean equals(Object obj)
- {
- if (obj instanceof LongPolynomial2)
- {
- return Arrays.areEqual(coeffs, ((LongPolynomial2)obj).coeffs);
- }
- else
- {
- return false;
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/LongPolynomial5.java b/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/LongPolynomial5.java
deleted file mode 100644
index c804cc8d..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/LongPolynomial5.java
+++ /dev/null
@@ -1,149 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * A polynomial class that combines five coefficients into one <code>long</code> value for
- * faster multiplication by a ternary polynomial.<br>
- * Coefficients can be between 0 and 2047 and are stored in bits 0..11, 12..23, ..., 48..59 of a <code>long</code> number.
- */
-public class LongPolynomial5
-{
- private long[] coeffs; // groups of 5 coefficients
- private int numCoeffs;
-
- /**
- * Constructs a <code>LongPolynomial5</code> from a <code>IntegerPolynomial</code>. The two polynomials are independent of each other.
- *
- * @param p the original polynomial. Coefficients must be between 0 and 2047.
- */
- public LongPolynomial5(IntegerPolynomial p)
- {
- numCoeffs = p.coeffs.length;
-
- coeffs = new long[(numCoeffs + 4) / 5];
- int cIdx = 0;
- int shift = 0;
- for (int i = 0; i < numCoeffs; i++)
- {
- coeffs[cIdx] |= ((long)p.coeffs[i]) << shift;
- shift += 12;
- if (shift >= 60)
- {
- shift = 0;
- cIdx++;
- }
- }
- }
-
- private LongPolynomial5(long[] coeffs, int numCoeffs)
- {
- this.coeffs = coeffs;
- this.numCoeffs = numCoeffs;
- }
-
- /**
- * Multiplies the polynomial with a <code>TernaryPolynomial</code>, taking the indices mod N and the values mod 2048.
- */
- public LongPolynomial5 mult(TernaryPolynomial poly2)
- {
- long[][] prod = new long[5][coeffs.length + (poly2.size() + 4) / 5 - 1]; // intermediate results, the subarrays are shifted by 0,...,4 coefficients
-
- // multiply ones
- int[] ones = poly2.getOnes();
- for (int idx = 0; idx != ones.length; idx++)
- {
- int pIdx = ones[idx];
- int cIdx = pIdx / 5;
- int m = pIdx - cIdx * 5; // m = pIdx % 5
- for (int i = 0; i < coeffs.length; i++)
- {
- prod[m][cIdx] = (prod[m][cIdx] + coeffs[i]) & 0x7FF7FF7FF7FF7FFL;
- cIdx++;
- }
- }
-
- // multiply negative ones
- int[] negOnes = poly2.getNegOnes();
- for (int idx = 0; idx != negOnes.length; idx++)
- {
- int pIdx = negOnes[idx];
- int cIdx = pIdx / 5;
- int m = pIdx - cIdx * 5; // m = pIdx % 5
- for (int i = 0; i < coeffs.length; i++)
- {
- prod[m][cIdx] = (0x800800800800800L + prod[m][cIdx] - coeffs[i]) & 0x7FF7FF7FF7FF7FFL;
- cIdx++;
- }
- }
-
- // combine shifted coefficients (5 arrays) into a single array of length prod[*].length+1
- long[] cCoeffs = Arrays.copyOf(prod[0], prod[0].length + 1);
- for (int m = 1; m <= 4; m++)
- {
- int shift = m * 12;
- int shift60 = 60 - shift;
- long mask = (1L << shift60) - 1;
- int pLen = prod[m].length;
- for (int i = 0; i < pLen; i++)
- {
- long upper, lower;
- upper = prod[m][i] >> shift60;
- lower = prod[m][i] & mask;
-
- cCoeffs[i] = (cCoeffs[i] + (lower << shift)) & 0x7FF7FF7FF7FF7FFL;
- int nextIdx = i + 1;
- cCoeffs[nextIdx] = (cCoeffs[nextIdx] + upper) & 0x7FF7FF7FF7FF7FFL;
- }
- }
-
- // reduce indices of cCoeffs modulo numCoeffs
- int shift = 12 * (numCoeffs % 5);
- for (int cIdx = coeffs.length - 1; cIdx < cCoeffs.length; cIdx++)
- {
- long iCoeff; // coefficient to shift into the [0..numCoeffs-1] range
- int newIdx;
- if (cIdx == coeffs.length - 1)
- {
- iCoeff = numCoeffs == 5 ? 0 : cCoeffs[cIdx] >> shift;
- newIdx = 0;
- }
- else
- {
- iCoeff = cCoeffs[cIdx];
- newIdx = cIdx * 5 - numCoeffs;
- }
-
- int base = newIdx / 5;
- int m = newIdx - base * 5; // m = newIdx % 5
- long lower = iCoeff << (12 * m);
- long upper = iCoeff >> (12 * (5 - m));
- cCoeffs[base] = (cCoeffs[base] + lower) & 0x7FF7FF7FF7FF7FFL;
- int base1 = base + 1;
- if (base1 < coeffs.length)
- {
- cCoeffs[base1] = (cCoeffs[base1] + upper) & 0x7FF7FF7FF7FF7FFL;
- }
- }
-
- return new LongPolynomial5(cCoeffs, numCoeffs);
- }
-
- public IntegerPolynomial toIntegerPolynomial()
- {
- int[] intCoeffs = new int[numCoeffs];
- int cIdx = 0;
- int shift = 0;
- for (int i = 0; i < numCoeffs; i++)
- {
- intCoeffs[i] = (int)((coeffs[cIdx] >> shift) & 2047);
- shift += 12;
- if (shift >= 60)
- {
- shift = 0;
- cIdx++;
- }
- }
- return new IntegerPolynomial(intCoeffs);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/ModularResultant.java b/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/ModularResultant.java
deleted file mode 100644
index 5f77192d..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/ModularResultant.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.pqc.math.ntru.euclid.BigIntEuclidean;
-
-/**
- * A resultant modulo a <code>BigInteger</code>
- */
-public class ModularResultant
- extends Resultant
-{
- BigInteger modulus;
-
- ModularResultant(BigIntPolynomial rho, BigInteger res, BigInteger modulus)
- {
- super(rho, res);
- this.modulus = modulus;
- }
-
- /**
- * Calculates a <code>rho</code> modulo <code>m1*m2</code> from
- * two resultants whose <code>rho</code>s are modulo <code>m1</code> and <code>m2</code>.<br/>
- * </code>res</code> is set to <code>null</code>.
- *
- * @param modRes1
- * @param modRes2
- * @return <code>rho</code> modulo <code>modRes1.modulus * modRes2.modulus</code>, and <code>null</code> for </code>res</code>.
- */
- static ModularResultant combineRho(ModularResultant modRes1, ModularResultant modRes2)
- {
- BigInteger mod1 = modRes1.modulus;
- BigInteger mod2 = modRes2.modulus;
- BigInteger prod = mod1.multiply(mod2);
- BigIntEuclidean er = BigIntEuclidean.calculate(mod2, mod1);
-
- BigIntPolynomial rho1 = (BigIntPolynomial)modRes1.rho.clone();
- rho1.mult(er.x.multiply(mod2));
- BigIntPolynomial rho2 = (BigIntPolynomial)modRes2.rho.clone();
- rho2.mult(er.y.multiply(mod1));
- rho1.add(rho2);
- rho1.mod(prod);
-
- return new ModularResultant(rho1, null, prod);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Polynomial.java b/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Polynomial.java
deleted file mode 100644
index 69193e39..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Polynomial.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-public interface Polynomial
-{
-
- /**
- * Multiplies the polynomial by an <code>IntegerPolynomial</code>,
- * taking the indices mod <code>N</code>.
- *
- * @param poly2 a polynomial
- * @return the product of the two polynomials
- */
- IntegerPolynomial mult(IntegerPolynomial poly2);
-
- /**
- * Multiplies the polynomial by an <code>IntegerPolynomial</code>,
- * taking the coefficient values mod <code>modulus</code> and the indices mod <code>N</code>.
- *
- * @param poly2 a polynomial
- * @param modulus a modulus to apply
- * @return the product of the two polynomials
- */
- IntegerPolynomial mult(IntegerPolynomial poly2, int modulus);
-
- /**
- * Returns a polynomial that is equal to this polynomial (in the sense that {@link #mult(IntegerPolynomial, int)}
- * returns equal <code>IntegerPolynomial</code>s). The new polynomial is guaranteed to be independent of the original.
- *
- * @return a new <code>IntegerPolynomial</code>.
- */
- IntegerPolynomial toIntegerPolynomial();
-
- /**
- * Multiplies the polynomial by a <code>BigIntPolynomial</code>, taking the indices mod N. Does not
- * change this polynomial but returns the result as a new polynomial.<br>
- * Both polynomials must have the same number of coefficients.
- *
- * @param poly2 the polynomial to multiply by
- * @return a new polynomial
- */
- BigIntPolynomial mult(BigIntPolynomial poly2);
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/ProductFormPolynomial.java b/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/ProductFormPolynomial.java
deleted file mode 100644
index dd18902e..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/ProductFormPolynomial.java
+++ /dev/null
@@ -1,153 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.SecureRandom;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * A polynomial of the form <code>f1*f2+f3</code>, where
- * <code>f1,f2,f3</code> are very sparsely populated ternary polynomials.
- */
-public class ProductFormPolynomial
- implements Polynomial
-{
- private SparseTernaryPolynomial f1, f2, f3;
-
- public ProductFormPolynomial(SparseTernaryPolynomial f1, SparseTernaryPolynomial f2, SparseTernaryPolynomial f3)
- {
- this.f1 = f1;
- this.f2 = f2;
- this.f3 = f3;
- }
-
- public static ProductFormPolynomial generateRandom(int N, int df1, int df2, int df3Ones, int df3NegOnes, SecureRandom random)
- {
- SparseTernaryPolynomial f1 = SparseTernaryPolynomial.generateRandom(N, df1, df1, random);
- SparseTernaryPolynomial f2 = SparseTernaryPolynomial.generateRandom(N, df2, df2, random);
- SparseTernaryPolynomial f3 = SparseTernaryPolynomial.generateRandom(N, df3Ones, df3NegOnes, random);
- return new ProductFormPolynomial(f1, f2, f3);
- }
-
- public static ProductFormPolynomial fromBinary(byte[] data, int N, int df1, int df2, int df3Ones, int df3NegOnes)
- throws IOException
- {
- return fromBinary(new ByteArrayInputStream(data), N, df1, df2, df3Ones, df3NegOnes);
- }
-
- public static ProductFormPolynomial fromBinary(InputStream is, int N, int df1, int df2, int df3Ones, int df3NegOnes)
- throws IOException
- {
- SparseTernaryPolynomial f1;
-
- f1 = SparseTernaryPolynomial.fromBinary(is, N, df1, df1);
- SparseTernaryPolynomial f2 = SparseTernaryPolynomial.fromBinary(is, N, df2, df2);
- SparseTernaryPolynomial f3 = SparseTernaryPolynomial.fromBinary(is, N, df3Ones, df3NegOnes);
- return new ProductFormPolynomial(f1, f2, f3);
- }
-
- public byte[] toBinary()
- {
- byte[] f1Bin = f1.toBinary();
- byte[] f2Bin = f2.toBinary();
- byte[] f3Bin = f3.toBinary();
-
- byte[] all = Arrays.copyOf(f1Bin, f1Bin.length + f2Bin.length + f3Bin.length);
- System.arraycopy(f2Bin, 0, all, f1Bin.length, f2Bin.length);
- System.arraycopy(f3Bin, 0, all, f1Bin.length + f2Bin.length, f3Bin.length);
- return all;
- }
-
- public IntegerPolynomial mult(IntegerPolynomial b)
- {
- IntegerPolynomial c = f1.mult(b);
- c = f2.mult(c);
- c.add(f3.mult(b));
- return c;
- }
-
- public BigIntPolynomial mult(BigIntPolynomial b)
- {
- BigIntPolynomial c = f1.mult(b);
- c = f2.mult(c);
- c.add(f3.mult(b));
- return c;
- }
-
- public IntegerPolynomial toIntegerPolynomial()
- {
- IntegerPolynomial i = f1.mult(f2.toIntegerPolynomial());
- i.add(f3.toIntegerPolynomial());
- return i;
- }
-
- public IntegerPolynomial mult(IntegerPolynomial poly2, int modulus)
- {
- IntegerPolynomial c = mult(poly2);
- c.mod(modulus);
- return c;
- }
-
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((f1 == null) ? 0 : f1.hashCode());
- result = prime * result + ((f2 == null) ? 0 : f2.hashCode());
- result = prime * result + ((f3 == null) ? 0 : f3.hashCode());
- return result;
- }
-
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj == null)
- {
- return false;
- }
- if (getClass() != obj.getClass())
- {
- return false;
- }
- ProductFormPolynomial other = (ProductFormPolynomial)obj;
- if (f1 == null)
- {
- if (other.f1 != null)
- {
- return false;
- }
- }
- else if (!f1.equals(other.f1))
- {
- return false;
- }
- if (f2 == null)
- {
- if (other.f2 != null)
- {
- return false;
- }
- }
- else if (!f2.equals(other.f2))
- {
- return false;
- }
- if (f3 == null)
- {
- if (other.f3 != null)
- {
- return false;
- }
- }
- else if (!f3.equals(other.f3))
- {
- return false;
- }
- return true;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Resultant.java b/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Resultant.java
deleted file mode 100644
index ec585779..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Resultant.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-import java.math.BigInteger;
-
-/**
- * Contains a resultant and a polynomial <code>rho</code> such that
- * <code>res = rho*this + t*(x^n-1) for some integer t</code>.
- *
- * @see IntegerPolynomial#resultant()
- * @see IntegerPolynomial#resultant(int)
- */
-public class Resultant
-{
- /**
- * A polynomial such that <code>res = rho*this + t*(x^n-1) for some integer t</code>
- */
- public BigIntPolynomial rho;
- /**
- * Resultant of a polynomial with <code>x^n-1</code>
- */
- public BigInteger res;
-
- Resultant(BigIntPolynomial rho, BigInteger res)
- {
- this.rho = rho;
- this.res = res;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/SparseTernaryPolynomial.java b/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/SparseTernaryPolynomial.java
deleted file mode 100644
index 3c913397..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/SparseTernaryPolynomial.java
+++ /dev/null
@@ -1,320 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.pqc.math.ntru.util.ArrayEncoder;
-import org.bouncycastle.pqc.math.ntru.util.Util;
-import org.bouncycastle.util.Arrays;
-
-/**
- * A <code>TernaryPolynomial</code> with a "low" number of nonzero coefficients.
- */
-public class SparseTernaryPolynomial
- implements TernaryPolynomial
-{
- /**
- * Number of bits to use for each coefficient. Determines the upper bound for <code>N</code>.
- */
- private static final int BITS_PER_INDEX = 11;
-
- private int N;
- private int[] ones;
- private int[] negOnes;
-
- /**
- * Constructs a new polynomial.
- *
- * @param N total number of coefficients including zeros
- * @param ones indices of coefficients equal to 1
- * @param negOnes indices of coefficients equal to -1
- */
- SparseTernaryPolynomial(int N, int[] ones, int[] negOnes)
- {
- this.N = N;
- this.ones = ones;
- this.negOnes = negOnes;
- }
-
- /**
- * Constructs a <code>DenseTernaryPolynomial</code> from a <code>IntegerPolynomial</code>. The two polynomials are
- * independent of each other.
- *
- * @param intPoly the original polynomial
- */
- public SparseTernaryPolynomial(IntegerPolynomial intPoly)
- {
- this(intPoly.coeffs);
- }
-
- /**
- * Constructs a new <code>SparseTernaryPolynomial</code> with a given set of coefficients.
- *
- * @param coeffs the coefficients
- */
- public SparseTernaryPolynomial(int[] coeffs)
- {
- N = coeffs.length;
- ones = new int[N];
- negOnes = new int[N];
- int onesIdx = 0;
- int negOnesIdx = 0;
- for (int i = 0; i < N; i++)
- {
- int c = coeffs[i];
- switch (c)
- {
- case 1:
- ones[onesIdx++] = i;
- break;
- case -1:
- negOnes[negOnesIdx++] = i;
- break;
- case 0:
- break;
- default:
- throw new IllegalArgumentException("Illegal value: " + c + ", must be one of {-1, 0, 1}");
- }
- }
- ones = Arrays.copyOf(ones, onesIdx);
- negOnes = Arrays.copyOf(negOnes, negOnesIdx);
- }
-
- /**
- * Decodes a byte array encoded with {@link #toBinary()} to a ploynomial.
- *
- * @param is an input stream containing an encoded polynomial
- * @param N number of coefficients including zeros
- * @param numOnes number of coefficients equal to 1
- * @param numNegOnes number of coefficients equal to -1
- * @return the decoded polynomial
- * @throws IOException
- */
- public static SparseTernaryPolynomial fromBinary(InputStream is, int N, int numOnes, int numNegOnes)
- throws IOException
- {
- int maxIndex = 1 << BITS_PER_INDEX;
- int bitsPerIndex = 32 - Integer.numberOfLeadingZeros(maxIndex - 1);
-
- int data1Len = (numOnes * bitsPerIndex + 7) / 8;
- byte[] data1 = Util.readFullLength(is, data1Len);
- int[] ones = ArrayEncoder.decodeModQ(data1, numOnes, maxIndex);
-
- int data2Len = (numNegOnes * bitsPerIndex + 7) / 8;
- byte[] data2 = Util.readFullLength(is, data2Len);
- int[] negOnes = ArrayEncoder.decodeModQ(data2, numNegOnes, maxIndex);
-
- return new SparseTernaryPolynomial(N, ones, negOnes);
- }
-
- /**
- * Generates a random polynomial with <code>numOnes</code> coefficients equal to 1,
- * <code>numNegOnes</code> coefficients equal to -1, and the rest equal to 0.
- *
- * @param N number of coefficients
- * @param numOnes number of 1's
- * @param numNegOnes number of -1's
- */
- public static SparseTernaryPolynomial generateRandom(int N, int numOnes, int numNegOnes, SecureRandom random)
- {
- int[] coeffs = Util.generateRandomTernary(N, numOnes, numNegOnes, random);
- return new SparseTernaryPolynomial(coeffs);
- }
-
- public IntegerPolynomial mult(IntegerPolynomial poly2)
- {
- int[] b = poly2.coeffs;
- if (b.length != N)
- {
- throw new IllegalArgumentException("Number of coefficients must be the same");
- }
-
- int[] c = new int[N];
- for (int idx = 0; idx != ones.length; idx++)
- {
- int i = ones[idx];
- int j = N - 1 - i;
- for (int k = N - 1; k >= 0; k--)
- {
- c[k] += b[j];
- j--;
- if (j < 0)
- {
- j = N - 1;
- }
- }
- }
-
- for (int idx = 0; idx != negOnes.length; idx++)
- {
- int i = negOnes[idx];
- int j = N - 1 - i;
- for (int k = N - 1; k >= 0; k--)
- {
- c[k] -= b[j];
- j--;
- if (j < 0)
- {
- j = N - 1;
- }
- }
- }
-
- return new IntegerPolynomial(c);
- }
-
- public IntegerPolynomial mult(IntegerPolynomial poly2, int modulus)
- {
- IntegerPolynomial c = mult(poly2);
- c.mod(modulus);
- return c;
- }
-
- public BigIntPolynomial mult(BigIntPolynomial poly2)
- {
- BigInteger[] b = poly2.coeffs;
- if (b.length != N)
- {
- throw new IllegalArgumentException("Number of coefficients must be the same");
- }
-
- BigInteger[] c = new BigInteger[N];
- for (int i = 0; i < N; i++)
- {
- c[i] = BigInteger.ZERO;
- }
-
- for (int idx = 0; idx != ones.length; idx++)
- {
- int i = ones[idx];
- int j = N - 1 - i;
- for (int k = N - 1; k >= 0; k--)
- {
- c[k] = c[k].add(b[j]);
- j--;
- if (j < 0)
- {
- j = N - 1;
- }
- }
- }
-
- for (int idx = 0; idx != negOnes.length; idx++)
- {
- int i = negOnes[idx];
- int j = N - 1 - i;
- for (int k = N - 1; k >= 0; k--)
- {
- c[k] = c[k].subtract(b[j]);
- j--;
- if (j < 0)
- {
- j = N - 1;
- }
- }
- }
-
- return new BigIntPolynomial(c);
- }
-
- public int[] getOnes()
- {
- return ones;
- }
-
- public int[] getNegOnes()
- {
- return negOnes;
- }
-
- /**
- * Encodes the polynomial to a byte array writing <code>BITS_PER_INDEX</code> bits for each coefficient.
- *
- * @return the encoded polynomial
- */
- public byte[] toBinary()
- {
- int maxIndex = 1 << BITS_PER_INDEX;
- byte[] bin1 = ArrayEncoder.encodeModQ(ones, maxIndex);
- byte[] bin2 = ArrayEncoder.encodeModQ(negOnes, maxIndex);
-
- byte[] bin = Arrays.copyOf(bin1, bin1.length + bin2.length);
- System.arraycopy(bin2, 0, bin, bin1.length, bin2.length);
- return bin;
- }
-
- public IntegerPolynomial toIntegerPolynomial()
- {
- int[] coeffs = new int[N];
- for (int idx = 0; idx != ones.length; idx++)
- {
- int i = ones[idx];
- coeffs[i] = 1;
- }
- for (int idx = 0; idx != negOnes.length; idx++)
- {
- int i = negOnes[idx];
- coeffs[i] = -1;
- }
- return new IntegerPolynomial(coeffs);
- }
-
- public int size()
- {
- return N;
- }
-
- public void clear()
- {
- for (int i = 0; i < ones.length; i++)
- {
- ones[i] = 0;
- }
- for (int i = 0; i < negOnes.length; i++)
- {
- negOnes[i] = 0;
- }
- }
-
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = prime * result + N;
- result = prime * result + Arrays.hashCode(negOnes);
- result = prime * result + Arrays.hashCode(ones);
- return result;
- }
-
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj == null)
- {
- return false;
- }
- if (getClass() != obj.getClass())
- {
- return false;
- }
- SparseTernaryPolynomial other = (SparseTernaryPolynomial)obj;
- if (N != other.N)
- {
- return false;
- }
- if (!Arrays.areEqual(negOnes, other.negOnes))
- {
- return false;
- }
- if (!Arrays.areEqual(ones, other.ones))
- {
- return false;
- }
- return true;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/TernaryPolynomial.java b/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/TernaryPolynomial.java
deleted file mode 100644
index 822b64b4..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/TernaryPolynomial.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-/**
- * A polynomial whose coefficients are all equal to -1, 0, or 1
- */
-public interface TernaryPolynomial
- extends Polynomial
-{
-
- /**
- * Multiplies the polynomial by an <code>IntegerPolynomial</code>, taking the indices mod N
- */
- IntegerPolynomial mult(IntegerPolynomial poly2);
-
- int[] getOnes();
-
- int[] getNegOnes();
-
- /**
- * Returns the maximum number of coefficients the polynomial can have
- */
- int size();
-
- void clear();
-}
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/ntru/util/ArrayEncoder.java b/core/src/main/java/org/bouncycastle/pqc/math/ntru/util/ArrayEncoder.java
deleted file mode 100644
index a437d48a..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/ntru/util/ArrayEncoder.java
+++ /dev/null
@@ -1,292 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * Converts a coefficient array to a compact byte array and vice versa.
- */
-public class ArrayEncoder
-{
- /**
- * Bit string to coefficient conversion table from P1363.1. Also found at
- * {@link http://stackoverflow.com/questions/1562548/how-to-make-a-message-into-a-polynomial}
- * <p/>
- * Convert each three-bit quantity to two ternary coefficients as follows, and concatenate the resulting
- * ternary quantities to obtain [the output].
- * <p/>
- * <code>
- * {0, 0, 0} -> {0, 0}<br/>
- * {0, 0, 1} -> {0, 1}<br/>
- * {0, 1, 0} -> {0, -1}<br/>
- * {0, 1, 1} -> {1, 0}<br/>
- * {1, 0, 0} -> {1, 1}<br/>
- * {1, 0, 1} -> {1, -1}<br/>
- * {1, 1, 0} -> {-1, 0}<br/>
- * {1, 1, 1} -> {-1, 1}<br/>
- * </code>
- */
- private static final int[] COEFF1_TABLE = {0, 0, 0, 1, 1, 1, -1, -1};
- private static final int[] COEFF2_TABLE = {0, 1, -1, 0, 1, -1, 0, 1};
- /**
- * Coefficient to bit string conversion table from P1363.1. Also found at
- * {@link http://stackoverflow.com/questions/1562548/how-to-make-a-message-into-a-polynomial}
- * <p/>
- * Convert each set of two ternary coefficients to three bits as follows, and concatenate the resulting bit
- * quantities to obtain [the output]:
- * <p/>
- * <code>
- * {-1, -1} -> set "fail" to 1 and set bit string to {1, 1, 1}
- * {-1, 0} -> {1, 1, 0}<br/>
- * {-1, 1} -> {1, 1, 1}<br/>
- * {0, -1} -> {0, 1, 0}<br/>
- * {0, 0} -> {0, 0, 0}<br/>
- * {0, 1} -> {0, 0, 1}<br/>
- * {1, -1} -> {1, 0, 1}<br/>
- * {1, 0} -> {0, 1, 1}<br/>
- * {1, 1} -> {1, 0, 0}<br/>
- * </code>
- */
- private static final int[] BIT1_TABLE = {1, 1, 1, 0, 0, 0, 1, 0, 1};
- private static final int[] BIT2_TABLE = {1, 1, 1, 1, 0, 0, 0, 1, 0};
- private static final int[] BIT3_TABLE = {1, 0, 1, 0, 0, 1, 1, 1, 0};
-
- /**
- * Encodes an int array whose elements are between 0 and <code>q</code>,
- * to a byte array leaving no gaps between bits.<br>
- * <code>q</code> must be a power of 2.
- *
- * @param a the input array
- * @param q the modulus
- * @return the encoded array
- */
- public static byte[] encodeModQ(int[] a, int q)
- {
- int bitsPerCoeff = 31 - Integer.numberOfLeadingZeros(q);
- int numBits = a.length * bitsPerCoeff;
- int numBytes = (numBits + 7) / 8;
- byte[] data = new byte[numBytes];
- int bitIndex = 0;
- int byteIndex = 0;
- for (int i = 0; i < a.length; i++)
- {
- for (int j = 0; j < bitsPerCoeff; j++)
- {
- int currentBit = (a[i] >> j) & 1;
- data[byteIndex] |= currentBit << bitIndex;
- if (bitIndex == 7)
- {
- bitIndex = 0;
- byteIndex++;
- }
- else
- {
- bitIndex++;
- }
- }
- }
- return data;
- }
-
- /**
- * Decodes a <code>byte</code> array encoded with {@link #encodeModQ(int[], int)} back to an <code>int</code> array.<br>
- * <code>N</code> is the number of coefficients. <code>q</code> must be a power of <code>2</code>.<br>
- * Ignores any excess bytes.
- *
- * @param data an encoded ternary polynomial
- * @param N number of coefficients
- * @param q
- * @return an array containing <code>N</code> coefficients between <code>0</code> and <code>q-1</code>
- */
- public static int[] decodeModQ(byte[] data, int N, int q)
- {
- int[] coeffs = new int[N];
- int bitsPerCoeff = 31 - Integer.numberOfLeadingZeros(q);
- int numBits = N * bitsPerCoeff;
- int coeffIndex = 0;
- for (int bitIndex = 0; bitIndex < numBits; bitIndex++)
- {
- if (bitIndex > 0 && bitIndex % bitsPerCoeff == 0)
- {
- coeffIndex++;
- }
- int bit = getBit(data, bitIndex);
- coeffs[coeffIndex] += bit << (bitIndex % bitsPerCoeff);
- }
- return coeffs;
- }
-
- /**
- * Decodes data encoded with {@link #encodeModQ(int[], int)} back to an <code>int</code> array.<br>
- * <code>N</code> is the number of coefficients. <code>q</code> must be a power of <code>2</code>.<br>
- * Ignores any excess bytes.
- *
- * @param is an encoded ternary polynomial
- * @param N number of coefficients
- * @param q
- * @return the decoded polynomial
- */
- public static int[] decodeModQ(InputStream is, int N, int q)
- throws IOException
- {
- int qBits = 31 - Integer.numberOfLeadingZeros(q);
- int size = (N * qBits + 7) / 8;
- byte[] arr = Util.readFullLength(is, size);
- return decodeModQ(arr, N, q);
- }
-
- /**
- * Decodes a <code>byte</code> array encoded with {@link #encodeMod3Sves(int[])} back to an <code>int</code> array
- * with <code>N</code> coefficients between <code>-1</code> and <code>1</code>.<br>
- * Ignores any excess bytes.<br>
- * See P1363.1 section 9.2.2.
- *
- * @param data an encoded ternary polynomial
- * @param N number of coefficients
- * @return the decoded coefficients
- */
- public static int[] decodeMod3Sves(byte[] data, int N)
- {
- int[] coeffs = new int[N];
- int coeffIndex = 0;
- for (int bitIndex = 0; bitIndex < data.length * 8; )
- {
- int bit1 = getBit(data, bitIndex++);
- int bit2 = getBit(data, bitIndex++);
- int bit3 = getBit(data, bitIndex++);
- int coeffTableIndex = bit1 * 4 + bit2 * 2 + bit3;
- coeffs[coeffIndex++] = COEFF1_TABLE[coeffTableIndex];
- coeffs[coeffIndex++] = COEFF2_TABLE[coeffTableIndex];
- // ignore bytes that can't fit
- if (coeffIndex > N - 2)
- {
- break;
- }
- }
- return coeffs;
- }
-
- /**
- * Encodes an <code>int</code> array whose elements are between <code>-1</code> and <code>1</code>, to a byte array.
- * <code>coeffs[2*i]</code> and <code>coeffs[2*i+1]</code> must not both equal -1 for any integer <code>i</code>,
- * so this method is only safe to use with arrays produced by {@link #decodeMod3Sves(byte[], int)}.<br>
- * See P1363.1 section 9.2.3.
- *
- * @param arr
- * @return the encoded array
- */
- public static byte[] encodeMod3Sves(int[] arr)
- {
- int numBits = (arr.length * 3 + 1) / 2;
- int numBytes = (numBits + 7) / 8;
- byte[] data = new byte[numBytes];
- int bitIndex = 0;
- int byteIndex = 0;
- for (int i = 0; i < arr.length / 2 * 2; )
- { // if length is an odd number, throw away the highest coeff
- int coeff1 = arr[i++] + 1;
- int coeff2 = arr[i++] + 1;
- if (coeff1 == 0 && coeff2 == 0)
- {
- throw new IllegalStateException("Illegal encoding!");
- }
- int bitTableIndex = coeff1 * 3 + coeff2;
- int[] bits = new int[]{BIT1_TABLE[bitTableIndex], BIT2_TABLE[bitTableIndex], BIT3_TABLE[bitTableIndex]};
- for (int j = 0; j < 3; j++)
- {
- data[byteIndex] |= bits[j] << bitIndex;
- if (bitIndex == 7)
- {
- bitIndex = 0;
- byteIndex++;
- }
- else
- {
- bitIndex++;
- }
- }
- }
- return data;
- }
-
- /**
- * Encodes an <code>int</code> array whose elements are between <code>-1</code> and <code>1</code>, to a byte array.
- *
- * @return the encoded array
- */
- public static byte[] encodeMod3Tight(int[] intArray)
- {
- BigInteger sum = BigInteger.ZERO;
- for (int i = intArray.length - 1; i >= 0; i--)
- {
- sum = sum.multiply(BigInteger.valueOf(3));
- sum = sum.add(BigInteger.valueOf(intArray[i] + 1));
- }
-
- int size = (BigInteger.valueOf(3).pow(intArray.length).bitLength() + 7) / 8;
- byte[] arr = sum.toByteArray();
-
- if (arr.length < size)
- {
- // pad with leading zeros so arr.length==size
- byte[] arr2 = new byte[size];
- System.arraycopy(arr, 0, arr2, size - arr.length, arr.length);
- return arr2;
- }
-
- if (arr.length > size)
- // drop sign bit
- {
- arr = Arrays.copyOfRange(arr, 1, arr.length);
- }
- return arr;
- }
-
- /**
- * Converts a byte array produced by {@link #encodeMod3Tight(int[])} back to an <code>int</code> array.
- *
- * @param b a byte array
- * @param N number of coefficients
- * @return the decoded array
- */
- public static int[] decodeMod3Tight(byte[] b, int N)
- {
- BigInteger sum = new BigInteger(1, b);
- int[] coeffs = new int[N];
- for (int i = 0; i < N; i++)
- {
- coeffs[i] = sum.mod(BigInteger.valueOf(3)).intValue() - 1;
- if (coeffs[i] > 1)
- {
- coeffs[i] -= 3;
- }
- sum = sum.divide(BigInteger.valueOf(3));
- }
- return coeffs;
- }
-
- /**
- * Converts data produced by {@link #encodeMod3Tight(int[])} back to an <code>int</code> array.
- *
- * @param is an input stream containing the data to decode
- * @param N number of coefficients
- * @return the decoded array
- */
- public static int[] decodeMod3Tight(InputStream is, int N)
- throws IOException
- {
- int size = (int)Math.ceil(N * Math.log(3) / Math.log(2) / 8);
- byte[] arr = Util.readFullLength(is, size);
- return decodeMod3Tight(arr, N);
- }
-
- private static int getBit(byte[] arr, int bitIndex)
- {
- int byteIndex = bitIndex / 8;
- int arrElem = arr[byteIndex] & 0xFF;
- return (arrElem >> (bitIndex % 8)) & 1;
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/pqc/math/ntru/util/Util.java b/core/src/main/java/org/bouncycastle/pqc/math/ntru/util/Util.java
deleted file mode 100644
index 92c2ed4d..00000000
--- a/core/src/main/java/org/bouncycastle/pqc/math/ntru/util/Util.java
+++ /dev/null
@@ -1,158 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.SecureRandom;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import org.bouncycastle.pqc.math.ntru.euclid.IntEuclidean;
-import org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.TernaryPolynomial;
-import org.bouncycastle.util.Integers;
-
-public class Util
-{
- private static volatile boolean IS_64_BITNESS_KNOWN;
- private static volatile boolean IS_64_BIT_JVM;
-
- /**
- * Calculates the inverse of n mod modulus
- */
- public static int invert(int n, int modulus)
- {
- n %= modulus;
- if (n < 0)
- {
- n += modulus;
- }
- return IntEuclidean.calculate(n, modulus).x;
- }
-
- /**
- * Calculates a^b mod modulus
- */
- public static int pow(int a, int b, int modulus)
- {
- int p = 1;
- for (int i = 0; i < b; i++)
- {
- p = (p * a) % modulus;
- }
- return p;
- }
-
- /**
- * Calculates a^b mod modulus
- */
- public static long pow(long a, int b, long modulus)
- {
- long p = 1;
- for (int i = 0; i < b; i++)
- {
- p = (p * a) % modulus;
- }
- return p;
- }
-
- /**
- * Generates a "sparse" or "dense" polynomial containing numOnes ints equal to 1,
- * numNegOnes int equal to -1, and the rest equal to 0.
- *
- * @param N
- * @param numOnes
- * @param numNegOnes
- * @param sparse whether to create a {@link SparseTernaryPolynomial} or {@link DenseTernaryPolynomial}
- * @return a ternary polynomial
- */
- public static TernaryPolynomial generateRandomTernary(int N, int numOnes, int numNegOnes, boolean sparse, SecureRandom random)
- {
- if (sparse)
- {
- return SparseTernaryPolynomial.generateRandom(N, numOnes, numNegOnes, random);
- }
- else
- {
- return DenseTernaryPolynomial.generateRandom(N, numOnes, numNegOnes, random);
- }
- }
-
- /**
- * Generates an array containing numOnes ints equal to 1,
- * numNegOnes int equal to -1, and the rest equal to 0.
- *
- * @param N
- * @param numOnes
- * @param numNegOnes
- * @return an array of integers
- */
- public static int[] generateRandomTernary(int N, int numOnes, int numNegOnes, SecureRandom random)
- {
- Integer one = Integers.valueOf(1);
- Integer minusOne = Integers.valueOf(-1);
- Integer zero = Integers.valueOf(0);
-
- List list = new ArrayList();
- for (int i = 0; i < numOnes; i++)
- {
- list.add(one);
- }
- for (int i = 0; i < numNegOnes; i++)
- {
- list.add(minusOne);
- }
- while (list.size() < N)
- {
- list.add(zero);
- }
-
- Collections.shuffle(list, random);
-
- int[] arr = new int[N];
- for (int i = 0; i < N; i++)
- {
- arr[i] = ((Integer)list.get(i)).intValue();
- }
- return arr;
- }
-
- /**
- * Takes an educated guess as to whether 64 bits are supported by the JVM.
- *
- * @return <code>true</code> if 64-bit support detected, <code>false</code> otherwise
- */
- public static boolean is64BitJVM()
- {
- if (!IS_64_BITNESS_KNOWN)
- {
- String arch = System.getProperty("os.arch");
- String sunModel = System.getProperty("sun.arch.data.model");
- IS_64_BIT_JVM = "amd64".equals(arch) || "x86_64".equals(arch) || "ppc64".equals(arch) || "64".equals(sunModel);
- IS_64_BITNESS_KNOWN = true;
- }
- return IS_64_BIT_JVM;
- }
-
- /**
- * Reads a given number of bytes from an <code>InputStream</code>.
- * If there are not enough bytes in the stream, an <code>IOException</code>
- * is thrown.
- *
- * @param is
- * @param length
- * @return an array of length <code>length</code>
- * @throws IOException
- */
- public static byte[] readFullLength(InputStream is, int length)
- throws IOException
- {
- byte[] arr = new byte[length];
- if (is.read(arr) != arr.length)
- {
- throw new IOException("Not enough bytes to read.");
- }
- return arr;
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/util/Arrays.java b/core/src/main/java/org/bouncycastle/util/Arrays.java
deleted file mode 100644
index 64ce17c1..00000000
--- a/core/src/main/java/org/bouncycastle/util/Arrays.java
+++ /dev/null
@@ -1,971 +0,0 @@
-package org.bouncycastle.util;
-
-import java.math.BigInteger;
-
-/**
- * General array utilities.
- */
-public final class Arrays
-{
- private Arrays()
- {
- // static class, hide constructor
- }
-
- public static boolean areEqual(
- boolean[] a,
- boolean[] 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] != b[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- public static boolean areEqual(
- char[] a,
- char[] 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] != b[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- public static boolean areEqual(
- byte[] a,
- byte[] 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] != b[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * A constant time equals comparison - does not terminate early if
- * test will fail.
- *
- * @param a first array
- * @param b second array
- * @return true if arrays equal, false otherwise.
- */
- public static boolean constantTimeAreEqual(
- byte[] a,
- byte[] b)
- {
- if (a == b)
- {
- return true;
- }
-
- if (a == null || b == null)
- {
- return false;
- }
-
- if (a.length != b.length)
- {
- return false;
- }
-
- int nonEqual = 0;
-
- for (int i = 0; i != a.length; i++)
- {
- nonEqual |= (a[i] ^ b[i]);
- }
-
- return nonEqual == 0;
- }
-
- public static boolean areEqual(
- int[] a,
- int[] 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] != b[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- public static boolean areEqual(
- long[] a,
- long[] 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] != b[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- 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++)
- {
- 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)
- {
- for (int i = 0; i < array.length; i++)
- {
- array[i] = value;
- }
- }
-
- public static void fill(
- char[] array,
- char value)
- {
- for (int i = 0; i < array.length; i++)
- {
- array[i] = value;
- }
- }
-
- public static void fill(
- long[] array,
- long value)
- {
- for (int i = 0; i < array.length; i++)
- {
- array[i] = value;
- }
- }
-
- public static void fill(
- short[] array,
- short value)
- {
- for (int i = 0; i < array.length; i++)
- {
- array[i] = value;
- }
- }
-
- public static void fill(
- int[] array,
- int value)
- {
- for (int i = 0; i < array.length; i++)
- {
- array[i] = value;
- }
- }
-
- public static int hashCode(byte[] data)
- {
- if (data == null)
- {
- return 0;
- }
-
- int i = data.length;
- int hc = i + 1;
-
- while (--i >= 0)
- {
- hc *= 257;
- hc ^= data[i];
- }
-
- return hc;
- }
-
- public static int hashCode(byte[] data, int off, int len)
- {
- if (data == null)
- {
- return 0;
- }
-
- int i = len;
- int hc = i + 1;
-
- while (--i >= 0)
- {
- hc *= 257;
- hc ^= data[off + i];
- }
-
- return hc;
- }
-
- public static int hashCode(char[] data)
- {
- if (data == null)
- {
- return 0;
- }
-
- int i = data.length;
- int hc = i + 1;
-
- while (--i >= 0)
- {
- hc *= 257;
- hc ^= data[i];
- }
-
- return hc;
- }
-
- public static int hashCode(int[][] ints)
- {
- int hc = 0;
-
- for (int i = 0; i != ints.length; i++)
- {
- hc = hc * 257 + hashCode(ints[i]);
- }
-
- return hc;
- }
-
- public static int hashCode(int[] data)
- {
- if (data == null)
- {
- return 0;
- }
-
- int i = data.length;
- int hc = i + 1;
-
- while (--i >= 0)
- {
- hc *= 257;
- hc ^= data[i];
- }
-
- return hc;
- }
-
- public static int hashCode(int[] data, int off, int len)
- {
- if (data == null)
- {
- return 0;
- }
-
- int i = len;
- int hc = i + 1;
-
- while (--i >= 0)
- {
- hc *= 257;
- hc ^= data[off + i];
- }
-
- return hc;
- }
-
- public static int hashCode(short[][][] shorts)
- {
- int hc = 0;
-
- for (int i = 0; i != shorts.length; i++)
- {
- hc = hc * 257 + hashCode(shorts[i]);
- }
-
- return hc;
- }
-
- public static int hashCode(short[][] shorts)
- {
- int hc = 0;
-
- for (int i = 0; i != shorts.length; i++)
- {
- hc = hc * 257 + hashCode(shorts[i]);
- }
-
- return hc;
- }
-
- public static int hashCode(short[] data)
- {
- if (data == null)
- {
- return 0;
- }
-
- int i = data.length;
- int hc = i + 1;
-
- while (--i >= 0)
- {
- hc *= 257;
- hc ^= (data[i] & 0xff);
- }
-
- return hc;
- }
-
- public static int hashCode(Object[] data)
- {
- if (data == null)
- {
- return 0;
- }
-
- int i = data.length;
- int hc = i + 1;
-
- while (--i >= 0)
- {
- hc *= 257;
- hc ^= data[i].hashCode();
- }
-
- return hc;
- }
-
- public static byte[] clone(byte[] data)
- {
- if (data == null)
- {
- return null;
- }
- byte[] copy = new byte[data.length];
-
- System.arraycopy(data, 0, copy, 0, data.length);
-
- 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)
- {
- return null;
- }
-
- byte[][] copy = new byte[data.length][];
-
- for (int i = 0; i != copy.length; i++)
- {
- copy[i] = clone(data[i]);
- }
-
- return copy;
- }
-
- public static byte[][][] clone(byte[][][] data)
- {
- if (data == null)
- {
- return null;
- }
-
- byte[][][] copy = new byte[data.length][][];
-
- for (int i = 0; i != copy.length; i++)
- {
- copy[i] = clone(data[i]);
- }
-
- return copy;
- }
-
- public static int[] clone(int[] data)
- {
- if (data == null)
- {
- return null;
- }
- int[] copy = new int[data.length];
-
- System.arraycopy(data, 0, copy, 0, data.length);
-
- 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)
- {
- return null;
- }
- short[] copy = new short[data.length];
-
- System.arraycopy(data, 0, copy, 0, data.length);
-
- return copy;
- }
-
- public static BigInteger[] clone(BigInteger[] data)
- {
- if (data == null)
- {
- return null;
- }
- BigInteger[] copy = new BigInteger[data.length];
-
- System.arraycopy(data, 0, copy, 0, data.length);
-
- return copy;
- }
-
- public static byte[] copyOf(byte[] data, int newLength)
- {
- byte[] tmp = new byte[newLength];
-
- if (newLength < data.length)
- {
- System.arraycopy(data, 0, tmp, 0, newLength);
- }
- else
- {
- System.arraycopy(data, 0, tmp, 0, data.length);
- }
-
- return tmp;
- }
-
- public static char[] copyOf(char[] data, int newLength)
- {
- char[] tmp = new char[newLength];
-
- if (newLength < data.length)
- {
- System.arraycopy(data, 0, tmp, 0, newLength);
- }
- else
- {
- System.arraycopy(data, 0, tmp, 0, data.length);
- }
-
- return tmp;
- }
-
- public static int[] copyOf(int[] data, int newLength)
- {
- int[] tmp = new int[newLength];
-
- if (newLength < data.length)
- {
- System.arraycopy(data, 0, tmp, 0, newLength);
- }
- else
- {
- System.arraycopy(data, 0, tmp, 0, data.length);
- }
-
- return tmp;
- }
-
- public static long[] copyOf(long[] data, int newLength)
- {
- long[] tmp = new long[newLength];
-
- if (newLength < data.length)
- {
- System.arraycopy(data, 0, tmp, 0, newLength);
- }
- else
- {
- System.arraycopy(data, 0, tmp, 0, data.length);
- }
-
- return tmp;
- }
-
- public static BigInteger[] copyOf(BigInteger[] data, int newLength)
- {
- BigInteger[] tmp = new BigInteger[newLength];
-
- if (newLength < data.length)
- {
- System.arraycopy(data, 0, tmp, 0, newLength);
- }
- else
- {
- System.arraycopy(data, 0, tmp, 0, data.length);
- }
-
- 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);
-
- byte[] tmp = new byte[newLength];
-
- if (data.length - from < newLength)
- {
- System.arraycopy(data, from, tmp, 0, data.length - from);
- }
- else
- {
- System.arraycopy(data, from, tmp, 0, newLength);
- }
-
- return tmp;
- }
-
- public static int[] copyOfRange(int[] data, int from, int to)
- {
- int newLength = getLength(from, to);
-
- int[] tmp = new int[newLength];
-
- if (data.length - from < newLength)
- {
- System.arraycopy(data, from, tmp, 0, data.length - from);
- }
- else
- {
- System.arraycopy(data, from, tmp, 0, newLength);
- }
-
- return tmp;
- }
-
- public static long[] copyOfRange(long[] data, int from, int to)
- {
- int newLength = getLength(from, to);
-
- long[] tmp = new long[newLength];
-
- if (data.length - from < newLength)
- {
- System.arraycopy(data, from, tmp, 0, data.length - from);
- }
- else
- {
- System.arraycopy(data, from, tmp, 0, newLength);
- }
-
- return tmp;
- }
-
- public static BigInteger[] copyOfRange(BigInteger[] data, int from, int to)
- {
- int newLength = getLength(from, to);
-
- BigInteger[] tmp = new BigInteger[newLength];
-
- if (data.length - from < newLength)
- {
- System.arraycopy(data, from, tmp, 0, data.length - from);
- }
- else
- {
- System.arraycopy(data, from, tmp, 0, newLength);
- }
-
- return tmp;
- }
-
- private static int getLength(int from, int to)
- {
- int newLength = to - from;
- if (newLength < 0)
- {
- StringBuffer sb = new StringBuffer(from);
- sb.append(" > ").append(to);
- throw new IllegalArgumentException(sb.toString());
- }
- 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 short[] append(short[] a, short b)
- {
- if (a == null)
- {
- return new short[]{ b };
- }
-
- int length = a.length;
- short[] result = new short[length + 1];
- System.arraycopy(a, 0, result, 0, length);
- result[length] = b;
- return result;
- }
-
- public static int[] append(int[] a, int b)
- {
- if (a == null)
- {
- 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)
- {
- byte[] rv = new byte[a.length + b.length];
-
- System.arraycopy(a, 0, rv, 0, a.length);
- System.arraycopy(b, 0, rv, a.length, b.length);
-
- return rv;
- }
- else if (b != null)
- {
- return clone(b);
- }
- else
- {
- return clone(a);
- }
- }
-
- public static byte[] concatenate(byte[] a, byte[] b, byte[] c)
- {
- if (a != null && b != null && c != null)
- {
- byte[] rv = new byte[a.length + b.length + c.length];
-
- System.arraycopy(a, 0, rv, 0, a.length);
- System.arraycopy(b, 0, rv, a.length, b.length);
- System.arraycopy(c, 0, rv, a.length + b.length, c.length);
-
- return rv;
- }
- else if (b == null)
- {
- return concatenate(a, c);
- }
- else
- {
- return concatenate(a, b);
- }
- }
-
- public static byte[] concatenate(byte[] a, byte[] b, byte[] c, byte[] d)
- {
- if (a != null && b != null && c != null && d != null)
- {
- byte[] rv = new byte[a.length + b.length + c.length + d.length];
-
- System.arraycopy(a, 0, rv, 0, a.length);
- System.arraycopy(b, 0, rv, a.length, b.length);
- System.arraycopy(c, 0, rv, a.length + b.length, c.length);
- System.arraycopy(d, 0, rv, a.length + b.length + c.length, d.length);
-
- return rv;
- }
- else if (d == null)
- {
- return concatenate(a, b, c);
- }
- else if (c == null)
- {
- return concatenate(a, b, d);
- }
- else if (b == null)
- {
- return concatenate(a, c, d);
- }
- else
- {
- return concatenate(b, c, d);
- }
- }
-
- public static int[] concatenate(int[] a, int[] b)
- {
- if (a == null)
- {
- return clone(b);
- }
- if (b == null)
- {
- return clone(a);
- }
-
- int[] c = new int[a.length + b.length];
- System.arraycopy(a, 0, c, 0, a.length);
- System.arraycopy(b, 0, c, a.length, b.length);
- return c;
- }
-
- public static byte[] prepend(byte[] a, byte b)
- {
- if (a == null)
- {
- 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;
- }
-
- public static short[] prepend(short[] a, short b)
- {
- if (a == null)
- {
- return new short[]{ b };
- }
-
- int length = a.length;
- short[] result = new short[length + 1];
- System.arraycopy(a, 0, result, 1, length);
- result[0] = b;
- return result;
- }
-
- public static int[] prepend(int[] a, int b)
- {
- if (a == null)
- {
- return new int[]{ b };
- }
-
- int length = a.length;
- int[] result = new int[length + 1];
- System.arraycopy(a, 0, result, 1, length);
- result[0] = b;
- return result;
- }
-
- public static byte[] reverse(byte[] a)
- {
- if (a == null)
- {
- return null;
- }
-
- int p1 = 0, p2 = a.length;
- byte[] result = new byte[p2];
-
- while (--p2 >= 0)
- {
- result[p2] = a[p1++];
- }
-
- return result;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/BigIntegers.java b/core/src/main/java/org/bouncycastle/util/BigIntegers.java
deleted file mode 100644
index f7f7e68b..00000000
--- a/core/src/main/java/org/bouncycastle/util/BigIntegers.java
+++ /dev/null
@@ -1,121 +0,0 @@
-package org.bouncycastle.util;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-/**
- * BigInteger utilities.
- */
-public final class BigIntegers
-{
- private static final int MAX_ITERATIONS = 1000;
- private static final BigInteger ZERO = BigInteger.valueOf(0);
-
- /**
- * Return the passed in value as an unsigned byte array.
- *
- * @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(
- BigInteger value)
- {
- byte[] bytes = value.toByteArray();
-
- if (bytes[0] == 0)
- {
- byte[] tmp = new byte[bytes.length - 1];
-
- System.arraycopy(bytes, 1, tmp, 0, tmp.length);
-
- return tmp;
- }
-
- return bytes;
- }
-
- /**
- * Return the passed in value as an unsigned byte array.
- *
- * @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)
- {
- byte[] bytes = value.toByteArray();
- if (bytes.length == length)
- {
- return bytes;
- }
-
- int start = bytes[0] == 0 ? 1 : 0;
- int count = bytes.length - start;
-
- 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;
- }
-
- /**
- * Return a random BigInteger not less than 'min' and not greater than 'max'
- *
- * @param min the least value that may be generated
- * @param max the greatest value that may be generated
- * @param random the source of randomness
- * @return a random BigInteger value in the range [min,max]
- */
- public static BigInteger createRandomInRange(
- BigInteger min,
- BigInteger max,
- SecureRandom random)
- {
- int cmp = min.compareTo(max);
- if (cmp >= 0)
- {
- if (cmp > 0)
- {
- throw new IllegalArgumentException("'min' may not be greater than 'max'");
- }
-
- return min;
- }
-
- if (min.bitLength() > max.bitLength() / 2)
- {
- return createRandomInRange(ZERO, max.subtract(min), random).add(min);
- }
-
- for (int i = 0; i < MAX_ITERATIONS; ++i)
- {
- BigInteger x = new BigInteger(max.bitLength(), random);
- if (x.compareTo(min) >= 0 && x.compareTo(max) <= 0)
- {
- return x;
- }
- }
-
- // 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/core/src/main/java/org/bouncycastle/util/CollectionStore.java b/core/src/main/java/org/bouncycastle/util/CollectionStore.java
deleted file mode 100644
index 91aba146..00000000
--- a/core/src/main/java/org/bouncycastle/util/CollectionStore.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.bouncycastle.util;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * A simple collection backed store.
- */
-public class CollectionStore
- implements Store
-{
- private Collection _local;
-
- /**
- * Basic constructor.
- *
- * @param collection - initial contents for the store, this is copied.
- */
- public CollectionStore(
- Collection collection)
- {
- _local = new ArrayList(collection);
- }
-
- /**
- * Return the matches in the collection for the passed in selector.
- *
- * @param selector the selector to match against.
- * @return a possibly empty collection of matching objects.
- */
- public Collection getMatches(Selector selector)
- {
- if (selector == null)
- {
- return new ArrayList(_local);
- }
- else
- {
- List col = new ArrayList();
- Iterator iter = _local.iterator();
-
- while (iter.hasNext())
- {
- Object obj = iter.next();
-
- if (selector.match(obj))
- {
- col.add(obj);
- }
- }
-
- return col;
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/IPAddress.java b/core/src/main/java/org/bouncycastle/util/IPAddress.java
deleted file mode 100644
index 9f5d1cbc..00000000
--- a/core/src/main/java/org/bouncycastle/util/IPAddress.java
+++ /dev/null
@@ -1,188 +0,0 @@
-package org.bouncycastle.util;
-
-public class IPAddress
-{
- /**
- * Validate the given IPv4 or IPv6 address.
- *
- * @param address the IP address as a String.
- *
- * @return true if a valid address, false otherwise
- */
- public static boolean isValid(
- String address)
- {
- return isValidIPv4(address) || isValidIPv6(address);
- }
-
- /**
- * Validate the given IPv4 or IPv6 address and netmask.
- *
- * @param address the IP address as a String.
- *
- * @return true if a valid address with netmask, false otherwise
- */
- public static boolean isValidWithNetMask(
- String address)
- {
- return isValidIPv4WithNetmask(address) || isValidIPv6WithNetmask(address);
- }
-
- /**
- * Validate the given IPv4 address.
- *
- * @param address the IP address as a String.
- *
- * @return true if a valid IPv4 address, false otherwise
- */
- public static boolean isValidIPv4(
- String address)
- {
- if (address.length() == 0)
- {
- return false;
- }
-
- int octet;
- int octets = 0;
-
- String temp = address+".";
-
- int pos;
- int start = 0;
- while (start < temp.length()
- && (pos = temp.indexOf('.', start)) > start)
- {
- if (octets == 4)
- {
- return false;
- }
- try
- {
- octet = Integer.parseInt(temp.substring(start, pos));
- }
- catch (NumberFormatException ex)
- {
- return false;
- }
- if (octet < 0 || octet > 255)
- {
- return false;
- }
- start = pos + 1;
- octets++;
- }
-
- return octets == 4;
- }
-
- public static boolean isValidIPv4WithNetmask(
- String address)
- {
- int index = address.indexOf("/");
- String mask = address.substring(index + 1);
-
- return (index > 0) && isValidIPv4(address.substring(0, index))
- && (isValidIPv4(mask) || isMaskValue(mask, 32));
- }
-
- public static boolean isValidIPv6WithNetmask(
- String address)
- {
- int index = address.indexOf("/");
- String mask = address.substring(index + 1);
-
- return (index > 0) && (isValidIPv6(address.substring(0, index))
- && (isValidIPv6(mask) || isMaskValue(mask, 128)));
- }
-
- private static boolean isMaskValue(String component, int size)
- {
- try
- {
- int value = Integer.parseInt(component);
-
- return value >= 0 && value <= size;
- }
- catch (NumberFormatException e)
- {
- return false;
- }
- }
-
- /**
- * Validate the given IPv6 address.
- *
- * @param address the IP address as a String.
- *
- * @return true if a valid IPv4 address, false otherwise
- */
- public static boolean isValidIPv6(
- String address)
- {
- if (address.length() == 0)
- {
- return false;
- }
-
- int octet;
- int octets = 0;
-
- String temp = address + ":";
- boolean doubleColonFound = false;
- int pos;
- int start = 0;
- while (start < temp.length()
- && (pos = temp.indexOf(':', start)) >= start)
- {
- if (octets == 8)
- {
- return false;
- }
-
- if (start != pos)
- {
- String value = temp.substring(start, pos);
-
- if (pos == (temp.length() - 1) && value.indexOf('.') > 0)
- {
- if (!isValidIPv4(value))
- {
- return false;
- }
-
- octets++; // add an extra one as address covers 2 words.
- }
- else
- {
- try
- {
- octet = Integer.parseInt(temp.substring(start, pos), 16);
- }
- catch (NumberFormatException ex)
- {
- return false;
- }
- if (octet < 0 || octet > 0xffff)
- {
- return false;
- }
- }
- }
- else
- {
- if (pos != 1 && pos != temp.length() - 1 && doubleColonFound)
- {
- return false;
- }
- doubleColonFound = true;
- }
- start = pos + 1;
- octets++;
- }
-
- return octets == 8 || doubleColonFound;
- }
-}
-
-
diff --git a/core/src/main/java/org/bouncycastle/util/Integers.java b/core/src/main/java/org/bouncycastle/util/Integers.java
deleted file mode 100644
index f52baf52..00000000
--- a/core/src/main/java/org/bouncycastle/util/Integers.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.bouncycastle.util;
-
-public class Integers
-{
- public static int rotateLeft(int i, int distance)
- {
- return Integer.rotateLeft(i, distance);
- }
-
- public static int rotateRight(int i, int distance)
- {
- return Integer.rotateRight(i, distance);
- }
-
- public static Integer valueOf(int value)
- {
- return Integer.valueOf(value);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/Memoable.java b/core/src/main/java/org/bouncycastle/util/Memoable.java
deleted file mode 100644
index ee0bedac..00000000
--- a/core/src/main/java/org/bouncycastle/util/Memoable.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.util;
-
-public interface Memoable
-{
- /**
- * Produce a copy of this object with its configuration and in its current state.
- * <p>
- * The returned object may be used simply to store the state, or may be used as a similar object
- * starting from the copied state.
- */
- public Memoable copy();
-
- /**
- * Restore a copied object state into this object.
- * <p>
- * Implementations of this method <em>should</em> try to avoid or minimise memory allocation to perform the reset.
- *
- * @param other an object originally {@link #copy() copied} from an object of the same type as this instance.
- * @throws ClassCastException if the provided object is not of the correct type.
- * @throws MemoableResetException if the <b>other</b> parameter is in some other way invalid.
- */
- public void reset(Memoable other);
-}
diff --git a/core/src/main/java/org/bouncycastle/util/MemoableResetException.java b/core/src/main/java/org/bouncycastle/util/MemoableResetException.java
deleted file mode 100644
index 6552bd49..00000000
--- a/core/src/main/java/org/bouncycastle/util/MemoableResetException.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.bouncycastle.util;
-
-/**
- * Exception to be thrown on a failure to reset an object implementing Memoable.
- * <p>
- * The exception extends ClassCastException to enable users to have a single handling case,
- * only introducing specific handling of this one if required.
- * </p>
- */
-public class MemoableResetException
- extends ClassCastException
-{
- /**
- * Basic Constructor.
- *
- * @param msg message to be associated with this exception.
- */
- public MemoableResetException(String msg)
- {
- super(msg);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/Pack.java b/core/src/main/java/org/bouncycastle/util/Pack.java
deleted file mode 100644
index 2f96af84..00000000
--- a/core/src/main/java/org/bouncycastle/util/Pack.java
+++ /dev/null
@@ -1,201 +0,0 @@
-package org.bouncycastle.util;
-
-public abstract class Pack
-{
- public static int bigEndianToInt(byte[] bs, int off)
- {
- int n = bs[ off] << 24;
- n |= (bs[++off] & 0xff) << 16;
- n |= (bs[++off] & 0xff) << 8;
- n |= (bs[++off] & 0xff);
- return n;
- }
-
- public static void bigEndianToInt(byte[] bs, int off, int[] ns)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- ns[i] = bigEndianToInt(bs, off);
- off += 4;
- }
- }
-
- public static byte[] intToBigEndian(int n)
- {
- byte[] bs = new byte[4];
- intToBigEndian(n, bs, 0);
- return bs;
- }
-
- public static void intToBigEndian(int n, byte[] bs, int off)
- {
- bs[ off] = (byte)(n >>> 24);
- bs[++off] = (byte)(n >>> 16);
- bs[++off] = (byte)(n >>> 8);
- bs[++off] = (byte)(n );
- }
-
- public static byte[] intToBigEndian(int[] ns)
- {
- byte[] bs = new byte[4 * ns.length];
- intToBigEndian(ns, bs, 0);
- return bs;
- }
-
- public static void intToBigEndian(int[] ns, byte[] bs, int off)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- intToBigEndian(ns[i], bs, off);
- off += 4;
- }
- }
-
- public static long bigEndianToLong(byte[] bs, int off)
- {
- int hi = bigEndianToInt(bs, off);
- int lo = bigEndianToInt(bs, off + 4);
- return ((long)(hi & 0xffffffffL) << 32) | (long)(lo & 0xffffffffL);
- }
-
- public static void bigEndianToLong(byte[] bs, int off, long[] ns)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- ns[i] = bigEndianToLong(bs, off);
- off += 8;
- }
- }
-
- public static byte[] longToBigEndian(long n)
- {
- byte[] bs = new byte[8];
- longToBigEndian(n, bs, 0);
- return bs;
- }
-
- public static void longToBigEndian(long n, byte[] bs, int off)
- {
- intToBigEndian((int)(n >>> 32), bs, off);
- intToBigEndian((int)(n & 0xffffffffL), bs, off + 4);
- }
-
- public static byte[] longToBigEndian(long[] ns)
- {
- byte[] bs = new byte[8 * ns.length];
- longToBigEndian(ns, bs, 0);
- return bs;
- }
-
- public static void longToBigEndian(long[] ns, byte[] bs, int off)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- longToBigEndian(ns[i], bs, off);
- off += 8;
- }
- }
-
- public static int littleEndianToInt(byte[] bs, int off)
- {
- int n = bs[ off] & 0xff;
- n |= (bs[++off] & 0xff) << 8;
- n |= (bs[++off] & 0xff) << 16;
- n |= bs[++off] << 24;
- return n;
- }
-
- public static void littleEndianToInt(byte[] bs, int off, int[] ns)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- ns[i] = littleEndianToInt(bs, off);
- off += 4;
- }
- }
-
- public static void littleEndianToInt(byte[] bs, int bOff, int[] ns, int nOff, int count)
- {
- for (int i = 0; i < count; ++i)
- {
- ns[nOff + i] = littleEndianToInt(bs, bOff);
- bOff += 4;
- }
- }
-
- public static byte[] intToLittleEndian(int n)
- {
- byte[] bs = new byte[4];
- intToLittleEndian(n, bs, 0);
- return bs;
- }
-
- public static void intToLittleEndian(int n, byte[] bs, int off)
- {
- bs[ off] = (byte)(n );
- bs[++off] = (byte)(n >>> 8);
- bs[++off] = (byte)(n >>> 16);
- bs[++off] = (byte)(n >>> 24);
- }
-
- public static byte[] intToLittleEndian(int[] ns)
- {
- byte[] bs = new byte[4 * ns.length];
- intToLittleEndian(ns, bs, 0);
- return bs;
- }
-
- public static void intToLittleEndian(int[] ns, byte[] bs, int off)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- intToLittleEndian(ns[i], bs, off);
- off += 4;
- }
- }
-
- public static long littleEndianToLong(byte[] bs, int off)
- {
- int lo = littleEndianToInt(bs, off);
- int hi = littleEndianToInt(bs, off + 4);
- return ((long)(hi & 0xffffffffL) << 32) | (long)(lo & 0xffffffffL);
- }
-
- public static void littleEndianToLong(byte[] bs, int off, long[] ns)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- ns[i] = littleEndianToLong(bs, off);
- off += 8;
- }
- }
-
- public static byte[] longToLittleEndian(long n)
- {
- byte[] bs = new byte[8];
- longToLittleEndian(n, bs, 0);
- return bs;
- }
-
- public static void longToLittleEndian(long n, byte[] bs, int off)
- {
- intToLittleEndian((int)(n & 0xffffffffL), bs, off);
- intToLittleEndian((int)(n >>> 32), bs, off + 4);
- }
-
- public static byte[] longToLittleEndian(long[] ns)
- {
- byte[] bs = new byte[8 * ns.length];
- longToLittleEndian(ns, bs, 0);
- return bs;
- }
-
- public static void longToLittleEndian(long[] ns, byte[] bs, int off)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- longToLittleEndian(ns[i], bs, off);
- off += 8;
- }
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/Selector.java b/core/src/main/java/org/bouncycastle/util/Selector.java
deleted file mode 100644
index 7ad86bf4..00000000
--- a/core/src/main/java/org/bouncycastle/util/Selector.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.bouncycastle.util;
-
-public interface Selector
- extends Cloneable
-{
- boolean match(Object obj);
-
- Object clone();
-}
diff --git a/core/src/main/java/org/bouncycastle/util/Shorts.java b/core/src/main/java/org/bouncycastle/util/Shorts.java
deleted file mode 100644
index 258e01e5..00000000
--- a/core/src/main/java/org/bouncycastle/util/Shorts.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.bouncycastle.util;
-
-public class Shorts
-{
- public static Short valueOf(short value)
- {
- return Short.valueOf(value);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/Store.java b/core/src/main/java/org/bouncycastle/util/Store.java
deleted file mode 100644
index b994c926..00000000
--- a/core/src/main/java/org/bouncycastle/util/Store.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.bouncycastle.util;
-
-import java.util.Collection;
-
-public interface Store
-{
- Collection getMatches(Selector selector)
- throws StoreException;
-}
diff --git a/core/src/main/java/org/bouncycastle/util/StoreException.java b/core/src/main/java/org/bouncycastle/util/StoreException.java
deleted file mode 100644
index 5ea09e80..00000000
--- a/core/src/main/java/org/bouncycastle/util/StoreException.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.bouncycastle.util;
-
-public class StoreException
- extends RuntimeException
-{
- private Throwable _e;
-
- public StoreException(String s, Throwable e)
- {
- super(s);
- _e = e;
- }
-
- public Throwable getCause()
- {
- return _e;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/StreamParser.java b/core/src/main/java/org/bouncycastle/util/StreamParser.java
deleted file mode 100644
index 13f2b163..00000000
--- a/core/src/main/java/org/bouncycastle/util/StreamParser.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.bouncycastle.util;
-
-import java.util.Collection;
-
-public interface StreamParser
-{
- Object read() throws StreamParsingException;
-
- Collection readAll() throws StreamParsingException;
-}
diff --git a/core/src/main/java/org/bouncycastle/util/StreamParsingException.java b/core/src/main/java/org/bouncycastle/util/StreamParsingException.java
deleted file mode 100644
index 0a76378a..00000000
--- a/core/src/main/java/org/bouncycastle/util/StreamParsingException.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.bouncycastle.util;
-
-public class StreamParsingException
- extends Exception
-{
- Throwable _e;
-
- public StreamParsingException(String message, Throwable e)
- {
- super(message);
- _e = e;
- }
-
- public Throwable getCause()
- {
- return _e;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/Strings.java b/core/src/main/java/org/bouncycastle/util/Strings.java
deleted file mode 100644
index 770edaa6..00000000
--- a/core/src/main/java/org/bouncycastle/util/Strings.java
+++ /dev/null
@@ -1,314 +0,0 @@
-package org.bouncycastle.util;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Vector;
-
-public final class Strings
-{
- public static String fromUTF8ByteArray(byte[] bytes)
- {
- int i = 0;
- int length = 0;
-
- while (i < bytes.length)
- {
- length++;
- if ((bytes[i] & 0xf0) == 0xf0)
- {
- // surrogate pair
- length++;
- i += 4;
- }
- else if ((bytes[i] & 0xe0) == 0xe0)
- {
- i += 3;
- }
- else if ((bytes[i] & 0xc0) == 0xc0)
- {
- i += 2;
- }
- else
- {
- i += 1;
- }
- }
-
- char[] cs = new char[length];
-
- i = 0;
- length = 0;
-
- while (i < bytes.length)
- {
- char ch;
-
- if ((bytes[i] & 0xf0) == 0xf0)
- {
- int codePoint = ((bytes[i] & 0x03) << 18) | ((bytes[i+1] & 0x3F) << 12) | ((bytes[i+2] & 0x3F) << 6) | (bytes[i+3] & 0x3F);
- int U = codePoint - 0x10000;
- char W1 = (char)(0xD800 | (U >> 10));
- char W2 = (char)(0xDC00 | (U & 0x3FF));
- cs[length++] = W1;
- ch = W2;
- i += 4;
- }
- else if ((bytes[i] & 0xe0) == 0xe0)
- {
- ch = (char)(((bytes[i] & 0x0f) << 12)
- | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f));
- i += 3;
- }
- else if ((bytes[i] & 0xd0) == 0xd0)
- {
- ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f));
- i += 2;
- }
- else if ((bytes[i] & 0xc0) == 0xc0)
- {
- ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f));
- i += 2;
- }
- else
- {
- ch = (char)(bytes[i] & 0xff);
- i += 1;
- }
-
- cs[length++] = ch;
- }
-
- return new String(cs);
- }
-
- public static byte[] toUTF8ByteArray(String string)
- {
- return toUTF8ByteArray(string.toCharArray());
- }
-
- public static byte[] toUTF8ByteArray(char[] string)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- try
- {
- toUTF8ByteArray(string, bOut);
- }
- catch (IOException e)
- {
- throw new IllegalStateException("cannot encode string to byte array!");
- }
-
- return bOut.toByteArray();
- }
-
- public static void toUTF8ByteArray(char[] string, OutputStream sOut)
- throws IOException
- {
- char[] c = string;
- int i = 0;
-
- while (i < c.length)
- {
- char ch = c[i];
-
- if (ch < 0x0080)
- {
- sOut.write(ch);
- }
- else if (ch < 0x0800)
- {
- sOut.write(0xc0 | (ch >> 6));
- sOut.write(0x80 | (ch & 0x3f));
- }
- // surrogate pair
- else if (ch >= 0xD800 && ch <= 0xDFFF)
- {
- // in error - can only happen, if the Java String class has a
- // bug.
- if (i + 1 >= c.length)
- {
- throw new IllegalStateException("invalid UTF-16 codepoint");
- }
- char W1 = ch;
- ch = c[++i];
- char W2 = ch;
- // in error - can only happen, if the Java String class has a
- // bug.
- if (W1 > 0xDBFF)
- {
- throw new IllegalStateException("invalid UTF-16 codepoint");
- }
- int codePoint = (((W1 & 0x03FF) << 10) | (W2 & 0x03FF)) + 0x10000;
- sOut.write(0xf0 | (codePoint >> 18));
- sOut.write(0x80 | ((codePoint >> 12) & 0x3F));
- sOut.write(0x80 | ((codePoint >> 6) & 0x3F));
- sOut.write(0x80 | (codePoint & 0x3F));
- }
- else
- {
- sOut.write(0xe0 | (ch >> 12));
- sOut.write(0x80 | ((ch >> 6) & 0x3F));
- sOut.write(0x80 | (ch & 0x3F));
- }
-
- i++;
- }
- }
-
- /**
- * A locale independent version of toUpperCase.
- *
- * @param string input to be converted
- * @return a US Ascii uppercase version
- */
- public static String toUpperCase(String string)
- {
- boolean changed = false;
- char[] chars = string.toCharArray();
-
- for (int i = 0; i != chars.length; i++)
- {
- char ch = chars[i];
- if ('a' <= ch && 'z' >= ch)
- {
- changed = true;
- chars[i] = (char)(ch - 'a' + 'A');
- }
- }
-
- if (changed)
- {
- return new String(chars);
- }
-
- return string;
- }
-
- /**
- * A locale independent version of toLowerCase.
- *
- * @param string input to be converted
- * @return a US ASCII lowercase version
- */
- public static String toLowerCase(String string)
- {
- boolean changed = false;
- char[] chars = string.toCharArray();
-
- for (int i = 0; i != chars.length; i++)
- {
- char ch = chars[i];
- if ('A' <= ch && 'Z' >= ch)
- {
- changed = true;
- chars[i] = (char)(ch - 'A' + 'a');
- }
- }
-
- if (changed)
- {
- return new String(chars);
- }
-
- return string;
- }
-
- public static byte[] toByteArray(char[] chars)
- {
- byte[] bytes = new byte[chars.length];
-
- for (int i = 0; i != bytes.length; i++)
- {
- bytes[i] = (byte)chars[i];
- }
-
- return bytes;
- }
-
- public static byte[] toByteArray(String string)
- {
- byte[] bytes = new byte[string.length()];
-
- for (int i = 0; i != bytes.length; i++)
- {
- char ch = string.charAt(i);
-
- bytes[i] = (byte)ch;
- }
-
- return bytes;
- }
-
- public static int toByteArray(String s, byte[] buf, int off)
- {
- int count = s.length();
- for (int i = 0; i < count; ++i)
- {
- char c = s.charAt(i);
- buf[off + i] = (byte)c;
- }
- return count;
- }
-
- /**
- * Convert an array of 8 bit characters into a string.
- *
- * @param bytes 8 bit characters.
- * @return resulting String.
- */
- public static String fromByteArray(byte[] bytes)
- {
- return new String(asCharArray(bytes));
- }
-
- /**
- * Do a simple conversion of an array of 8 bit characters into a string.
- *
- * @param bytes 8 bit characters.
- * @return resulting String.
- */
- public static char[] asCharArray(byte[] bytes)
- {
- char[] chars = new char[bytes.length];
-
- for (int i = 0; i != chars.length; i++)
- {
- chars[i] = (char)(bytes[i] & 0xff);
- }
-
- return chars;
- }
-
- public static String[] split(String input, char delimiter)
- {
- Vector v = new Vector();
- boolean moreTokens = true;
- String subString;
-
- while (moreTokens)
- {
- int tokenLocation = input.indexOf(delimiter);
- if (tokenLocation > 0)
- {
- subString = input.substring(0, tokenLocation);
- v.addElement(subString);
- input = input.substring(tokenLocation + 1);
- }
- else
- {
- moreTokens = false;
- v.addElement(input);
- }
- }
-
- String[] res = new String[v.size()];
-
- for (int i = 0; i != res.length; i++)
- {
- res[i] = (String)v.elementAt(i);
- }
- return res;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/Times.java b/core/src/main/java/org/bouncycastle/util/Times.java
deleted file mode 100644
index 617d00bd..00000000
--- a/core/src/main/java/org/bouncycastle/util/Times.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.bouncycastle.util;
-
-public final class Times
-{
- public static long nanoTime()
- {
- return System.nanoTime();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/encoders/Base64.java b/core/src/main/java/org/bouncycastle/util/encoders/Base64.java
deleted file mode 100644
index c04a8cc1..00000000
--- a/core/src/main/java/org/bouncycastle/util/encoders/Base64.java
+++ /dev/null
@@ -1,154 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.bouncycastle.util.Strings;
-
-/**
- * Utility class for converting Base64 data to bytes and back again.
- */
-public class Base64
-{
- private static final Encoder encoder = new Base64Encoder();
-
- public static String toBase64String(
- byte[] data)
- {
- return toBase64String(data, 0, data.length);
- }
-
- public static String toBase64String(
- byte[] data,
- int off,
- int length)
- {
- byte[] encoded = encode(data, off, length);
- return Strings.fromByteArray(encoded);
- }
-
- /**
- * encode the input data producing a base 64 encoded byte array.
- *
- * @return a byte array containing the base 64 encoded data.
- */
- public static byte[] encode(
- byte[] data)
- {
- return encode(data, 0, data.length);
- }
-
- /**
- * encode the input data producing a base 64 encoded byte array.
- *
- * @return a byte array containing the base 64 encoded data.
- */
- public static byte[] encode(
- byte[] data,
- int off,
- int length)
- {
- int len = (length + 2) / 3 * 4;
- ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);
-
- try
- {
- encoder.encode(data, off, length, bOut);
- }
- catch (Exception e)
- {
- throw new EncoderException("exception encoding base64 string: " + e.getMessage(), e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * Encode the byte data to base 64 writing it to the given output stream.
- *
- * @return the number of bytes produced.
- */
- public static int encode(
- byte[] data,
- OutputStream out)
- throws IOException
- {
- return encoder.encode(data, 0, data.length, out);
- }
-
- /**
- * Encode the byte data to base 64 writing it to the given output stream.
- *
- * @return the number of bytes produced.
- */
- public static int encode(
- byte[] data,
- int off,
- int length,
- OutputStream out)
- throws IOException
- {
- return encoder.encode(data, off, length, out);
- }
-
- /**
- * decode the base 64 encoded input data. It is assumed the input data is valid.
- *
- * @return a byte array representing the decoded data.
- */
- public static byte[] decode(
- byte[] data)
- {
- int len = data.length / 4 * 3;
- ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);
-
- try
- {
- encoder.decode(data, 0, data.length, bOut);
- }
- catch (Exception e)
- {
- throw new DecoderException("unable to decode base64 data: " + e.getMessage(), e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * decode the base 64 encoded String data - whitespace will be ignored.
- *
- * @return a byte array representing the decoded data.
- */
- public static byte[] decode(
- String data)
- {
- int len = data.length() / 4 * 3;
- ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);
-
- try
- {
- encoder.decode(data, bOut);
- }
- catch (Exception e)
- {
- throw new DecoderException("unable to decode base64 string: " + e.getMessage(), e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * decode the base 64 encoded String data writing it to the given output stream,
- * whitespace characters will be ignored.
- *
- * @return the number of bytes produced.
- */
- public static int decode(
- String data,
- OutputStream out)
- throws IOException
- {
- return encoder.decode(data, out);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/encoders/Base64Encoder.java b/core/src/main/java/org/bouncycastle/util/encoders/Base64Encoder.java
deleted file mode 100644
index abad02c5..00000000
--- a/core/src/main/java/org/bouncycastle/util/encoders/Base64Encoder.java
+++ /dev/null
@@ -1,331 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * A streaming Base64 encoder.
- */
-public class Base64Encoder
- implements Encoder
-{
- protected final byte[] encodingTable =
- {
- (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
- (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
- (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
- (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
- (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
- (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
- (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
- (byte)'v',
- (byte)'w', (byte)'x', (byte)'y', (byte)'z',
- (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6',
- (byte)'7', (byte)'8', (byte)'9',
- (byte)'+', (byte)'/'
- };
-
- protected byte padding = (byte)'=';
-
- /*
- * set up the decoding table.
- */
- protected final byte[] decodingTable = new byte[128];
-
- protected void initialiseDecodingTable()
- {
- for (int i = 0; i < decodingTable.length; i++)
- {
- decodingTable[i] = (byte)0xff;
- }
-
- for (int i = 0; i < encodingTable.length; i++)
- {
- decodingTable[encodingTable[i]] = (byte)i;
- }
- }
-
- public Base64Encoder()
- {
- initialiseDecodingTable();
- }
-
- /**
- * encode the input data producing a base 64 output stream.
- *
- * @return the number of bytes produced.
- */
- public int encode(
- byte[] data,
- int off,
- int length,
- OutputStream out)
- throws IOException
- {
- int modulus = length % 3;
- int dataLength = (length - modulus);
- int a1, a2, a3;
-
- for (int i = off; i < off + dataLength; i += 3)
- {
- a1 = data[i] & 0xff;
- a2 = data[i + 1] & 0xff;
- a3 = data[i + 2] & 0xff;
-
- out.write(encodingTable[(a1 >>> 2) & 0x3f]);
- out.write(encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f]);
- out.write(encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f]);
- out.write(encodingTable[a3 & 0x3f]);
- }
-
- /*
- * process the tail end.
- */
- int b1, b2, b3;
- int d1, d2;
-
- switch (modulus)
- {
- case 0: /* nothing left to do */
- break;
- case 1:
- d1 = data[off + dataLength] & 0xff;
- b1 = (d1 >>> 2) & 0x3f;
- b2 = (d1 << 4) & 0x3f;
-
- out.write(encodingTable[b1]);
- out.write(encodingTable[b2]);
- out.write(padding);
- out.write(padding);
- break;
- case 2:
- d1 = data[off + dataLength] & 0xff;
- d2 = data[off + dataLength + 1] & 0xff;
-
- b1 = (d1 >>> 2) & 0x3f;
- b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f;
- b3 = (d2 << 2) & 0x3f;
-
- out.write(encodingTable[b1]);
- out.write(encodingTable[b2]);
- out.write(encodingTable[b3]);
- out.write(padding);
- break;
- }
-
- return (dataLength / 3) * 4 + ((modulus == 0) ? 0 : 4);
- }
-
- private boolean ignore(
- char c)
- {
- return (c == '\n' || c =='\r' || c == '\t' || c == ' ');
- }
-
- /**
- * decode the base 64 encoded byte data writing it to the given output stream,
- * whitespace characters will be ignored.
- *
- * @return the number of bytes produced.
- */
- public int decode(
- byte[] data,
- int off,
- int length,
- OutputStream out)
- throws IOException
- {
- byte b1, b2, b3, b4;
- int outLen = 0;
-
- int end = off + length;
-
- while (end > off)
- {
- if (!ignore((char)data[end - 1]))
- {
- break;
- }
-
- end--;
- }
-
- int i = off;
- int finish = end - 4;
-
- i = nextI(data, i, finish);
-
- while (i < finish)
- {
- b1 = decodingTable[data[i++]];
-
- i = nextI(data, i, finish);
-
- b2 = decodingTable[data[i++]];
-
- i = nextI(data, i, finish);
-
- b3 = decodingTable[data[i++]];
-
- i = nextI(data, i, finish);
-
- b4 = decodingTable[data[i++]];
-
- if ((b1 | b2 | b3 | b4) < 0)
- {
- throw new IOException("invalid characters encountered in base64 data");
- }
-
- out.write((b1 << 2) | (b2 >> 4));
- out.write((b2 << 4) | (b3 >> 2));
- out.write((b3 << 6) | b4);
-
- outLen += 3;
-
- i = nextI(data, i, finish);
- }
-
- outLen += decodeLastBlock(out, (char)data[end - 4], (char)data[end - 3], (char)data[end - 2], (char)data[end - 1]);
-
- return outLen;
- }
-
- private int nextI(byte[] data, int i, int finish)
- {
- while ((i < finish) && ignore((char)data[i]))
- {
- i++;
- }
- return i;
- }
-
- /**
- * decode the base 64 encoded String data writing it to the given output stream,
- * whitespace characters will be ignored.
- *
- * @return the number of bytes produced.
- */
- public int decode(
- String data,
- OutputStream out)
- throws IOException
- {
- byte b1, b2, b3, b4;
- int length = 0;
-
- int end = data.length();
-
- while (end > 0)
- {
- if (!ignore(data.charAt(end - 1)))
- {
- break;
- }
-
- end--;
- }
-
- int i = 0;
- int finish = end - 4;
-
- i = nextI(data, i, finish);
-
- while (i < finish)
- {
- b1 = decodingTable[data.charAt(i++)];
-
- i = nextI(data, i, finish);
-
- b2 = decodingTable[data.charAt(i++)];
-
- i = nextI(data, i, finish);
-
- b3 = decodingTable[data.charAt(i++)];
-
- i = nextI(data, i, finish);
-
- b4 = decodingTable[data.charAt(i++)];
-
- if ((b1 | b2 | b3 | b4) < 0)
- {
- throw new IOException("invalid characters encountered in base64 data");
- }
-
- out.write((b1 << 2) | (b2 >> 4));
- out.write((b2 << 4) | (b3 >> 2));
- out.write((b3 << 6) | b4);
-
- length += 3;
-
- i = nextI(data, i, finish);
- }
-
- length += decodeLastBlock(out, data.charAt(end - 4), data.charAt(end - 3), data.charAt(end - 2), data.charAt(end - 1));
-
- return length;
- }
-
- private int decodeLastBlock(OutputStream out, char c1, char c2, char c3, char c4)
- throws IOException
- {
- byte b1, b2, b3, b4;
-
- if (c3 == padding)
- {
- b1 = decodingTable[c1];
- b2 = decodingTable[c2];
-
- if ((b1 | b2) < 0)
- {
- throw new IOException("invalid characters encountered at end of base64 data");
- }
-
- out.write((b1 << 2) | (b2 >> 4));
-
- return 1;
- }
- else if (c4 == padding)
- {
- b1 = decodingTable[c1];
- b2 = decodingTable[c2];
- b3 = decodingTable[c3];
-
- if ((b1 | b2 | b3) < 0)
- {
- throw new IOException("invalid characters encountered at end of base64 data");
- }
-
- out.write((b1 << 2) | (b2 >> 4));
- out.write((b2 << 4) | (b3 >> 2));
-
- return 2;
- }
- else
- {
- b1 = decodingTable[c1];
- b2 = decodingTable[c2];
- b3 = decodingTable[c3];
- b4 = decodingTable[c4];
-
- if ((b1 | b2 | b3 | b4) < 0)
- {
- throw new IOException("invalid characters encountered at end of base64 data");
- }
-
- out.write((b1 << 2) | (b2 >> 4));
- out.write((b2 << 4) | (b3 >> 2));
- out.write((b3 << 6) | b4);
-
- return 3;
- }
- }
-
- private int nextI(String data, int i, int finish)
- {
- while ((i < finish) && ignore(data.charAt(i)))
- {
- i++;
- }
- return i;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/encoders/BufferedDecoder.java b/core/src/main/java/org/bouncycastle/util/encoders/BufferedDecoder.java
deleted file mode 100644
index eea85b9f..00000000
--- a/core/src/main/java/org/bouncycastle/util/encoders/BufferedDecoder.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-
-/**
- * A buffering class to allow translation from one format to another to
- * be done in discrete chunks.
- */
-public class BufferedDecoder
-{
- protected byte[] buf;
- protected int bufOff;
-
- protected Translator translator;
-
- /**
- * @param translator the translator to use.
- * @param bufSize amount of input to buffer for each chunk.
- */
- public BufferedDecoder(
- Translator translator,
- int bufSize)
- {
- this.translator = translator;
-
- if ((bufSize % translator.getEncodedBlockSize()) != 0)
- {
- throw new IllegalArgumentException("buffer size not multiple of input block size");
- }
-
- buf = new byte[bufSize];
- bufOff = 0;
- }
-
- public int processByte(
- byte in,
- byte[] out,
- int outOff)
- {
- int resultLen = 0;
-
- buf[bufOff++] = in;
-
- if (bufOff == buf.length)
- {
- resultLen = translator.decode(buf, 0, buf.length, out, outOff);
- bufOff = 0;
- }
-
- return resultLen;
- }
-
- public int processBytes(
- byte[] in,
- int inOff,
- int len,
- byte[] out,
- int outOff)
- {
- if (len < 0)
- {
- throw new IllegalArgumentException("Can't have a negative input length!");
- }
-
- int resultLen = 0;
- int gapLen = buf.length - bufOff;
-
- if (len > gapLen)
- {
- System.arraycopy(in, inOff, buf, bufOff, gapLen);
-
- resultLen += translator.decode(buf, 0, buf.length, out, outOff);
-
- bufOff = 0;
-
- len -= gapLen;
- inOff += gapLen;
- outOff += resultLen;
-
- int chunkSize = len - (len % buf.length);
-
- resultLen += translator.decode(in, inOff, chunkSize, out, outOff);
-
- len -= chunkSize;
- inOff += chunkSize;
- }
-
- if (len != 0)
- {
- System.arraycopy(in, inOff, buf, bufOff, len);
-
- bufOff += len;
- }
-
- return resultLen;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/encoders/BufferedEncoder.java b/core/src/main/java/org/bouncycastle/util/encoders/BufferedEncoder.java
deleted file mode 100644
index 60a098de..00000000
--- a/core/src/main/java/org/bouncycastle/util/encoders/BufferedEncoder.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-
-/**
- * A buffering class to allow translation from one format to another to
- * be done in discrete chunks.
- */
-public class BufferedEncoder
-{
- protected byte[] buf;
- protected int bufOff;
-
- protected Translator translator;
-
- /**
- * @param translator the translator to use.
- * @param bufSize amount of input to buffer for each chunk.
- */
- public BufferedEncoder(
- Translator translator,
- int bufSize)
- {
- this.translator = translator;
-
- if ((bufSize % translator.getEncodedBlockSize()) != 0)
- {
- throw new IllegalArgumentException("buffer size not multiple of input block size");
- }
-
- buf = new byte[bufSize];
- bufOff = 0;
- }
-
- public int processByte(
- byte in,
- byte[] out,
- int outOff)
- {
- int resultLen = 0;
-
- buf[bufOff++] = in;
-
- if (bufOff == buf.length)
- {
- resultLen = translator.encode(buf, 0, buf.length, out, outOff);
- bufOff = 0;
- }
-
- return resultLen;
- }
-
- public int processBytes(
- byte[] in,
- int inOff,
- int len,
- byte[] out,
- int outOff)
- {
- if (len < 0)
- {
- throw new IllegalArgumentException("Can't have a negative input length!");
- }
-
- int resultLen = 0;
- int gapLen = buf.length - bufOff;
-
- if (len > gapLen)
- {
- System.arraycopy(in, inOff, buf, bufOff, gapLen);
-
- resultLen += translator.encode(buf, 0, buf.length, out, outOff);
-
- bufOff = 0;
-
- len -= gapLen;
- inOff += gapLen;
- outOff += resultLen;
-
- int chunkSize = len - (len % buf.length);
-
- resultLen += translator.encode(in, inOff, chunkSize, out, outOff);
-
- len -= chunkSize;
- inOff += chunkSize;
- }
-
- if (len != 0)
- {
- System.arraycopy(in, inOff, buf, bufOff, len);
-
- bufOff += len;
- }
-
- return resultLen;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/encoders/DecoderException.java b/core/src/main/java/org/bouncycastle/util/encoders/DecoderException.java
deleted file mode 100644
index 1e6782a5..00000000
--- a/core/src/main/java/org/bouncycastle/util/encoders/DecoderException.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-/**
- * Exception thrown if an attempt is made to decode invalid data, or some other failure occurs.
- */
-public class DecoderException
- extends IllegalStateException
-{
- private Throwable cause;
-
- DecoderException(String msg, Throwable cause)
- {
- super(msg);
-
- this.cause = cause;
- }
-
- public Throwable getCause()
- {
- return cause;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/encoders/Encoder.java b/core/src/main/java/org/bouncycastle/util/encoders/Encoder.java
deleted file mode 100644
index b0661210..00000000
--- a/core/src/main/java/org/bouncycastle/util/encoders/Encoder.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * Encode and decode byte arrays (typically from binary to 7-bit ASCII
- * encodings).
- */
-public interface Encoder
-{
- int encode(byte[] data, int off, int length, OutputStream out) throws IOException;
-
- int decode(byte[] data, int off, int length, OutputStream out) throws IOException;
-
- int decode(String data, OutputStream out) throws IOException;
-}
diff --git a/core/src/main/java/org/bouncycastle/util/encoders/EncoderException.java b/core/src/main/java/org/bouncycastle/util/encoders/EncoderException.java
deleted file mode 100644
index a1eb411e..00000000
--- a/core/src/main/java/org/bouncycastle/util/encoders/EncoderException.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-/**
- * Exception thrown if an attempt is made to encode invalid data, or some other failure occurs.
- */
-public class EncoderException
- extends IllegalStateException
-{
- private Throwable cause;
-
- EncoderException(String msg, Throwable cause)
- {
- super(msg);
-
- this.cause = cause;
- }
-
- public Throwable getCause()
- {
- return cause;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/encoders/Hex.java b/core/src/main/java/org/bouncycastle/util/encoders/Hex.java
deleted file mode 100644
index 63e9c713..00000000
--- a/core/src/main/java/org/bouncycastle/util/encoders/Hex.java
+++ /dev/null
@@ -1,151 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.bouncycastle.util.Strings;
-
-/**
- * Utility class for converting hex data to bytes and back again.
- */
-public class Hex
-{
- private static final Encoder encoder = new HexEncoder();
-
- public static String toHexString(
- byte[] data)
- {
- return toHexString(data, 0, data.length);
- }
-
- public static String toHexString(
- byte[] data,
- int off,
- int length)
- {
- byte[] encoded = encode(data, off, length);
- return Strings.fromByteArray(encoded);
- }
-
- /**
- * encode the input data producing a Hex encoded byte array.
- *
- * @return a byte array containing the Hex encoded data.
- */
- public static byte[] encode(
- byte[] data)
- {
- return encode(data, 0, data.length);
- }
-
- /**
- * encode the input data producing a Hex encoded byte array.
- *
- * @return a byte array containing the Hex encoded data.
- */
- public static byte[] encode(
- byte[] data,
- int off,
- int length)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- try
- {
- encoder.encode(data, off, length, bOut);
- }
- catch (Exception e)
- {
- throw new EncoderException("exception encoding Hex string: " + e.getMessage(), e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * Hex encode the byte data writing it to the given output stream.
- *
- * @return the number of bytes produced.
- */
- public static int encode(
- byte[] data,
- OutputStream out)
- throws IOException
- {
- return encoder.encode(data, 0, data.length, out);
- }
-
- /**
- * Hex encode the byte data writing it to the given output stream.
- *
- * @return the number of bytes produced.
- */
- public static int encode(
- byte[] data,
- int off,
- int length,
- OutputStream out)
- throws IOException
- {
- return encoder.encode(data, off, length, out);
- }
-
- /**
- * decode the Hex encoded input data. It is assumed the input data is valid.
- *
- * @return a byte array representing the decoded data.
- */
- public static byte[] decode(
- byte[] data)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- try
- {
- encoder.decode(data, 0, data.length, bOut);
- }
- catch (Exception e)
- {
- throw new DecoderException("exception decoding Hex data: " + e.getMessage(), e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * decode the Hex encoded String data - whitespace will be ignored.
- *
- * @return a byte array representing the decoded data.
- */
- public static byte[] decode(
- String data)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- try
- {
- encoder.decode(data, bOut);
- }
- catch (Exception e)
- {
- throw new DecoderException("exception decoding Hex string: " + e.getMessage(), e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * decode the Hex encoded String data writing it to the given output stream,
- * whitespace characters will be ignored.
- *
- * @return the number of bytes produced.
- */
- public static int decode(
- String data,
- OutputStream out)
- throws IOException
- {
- return encoder.decode(data, out);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/encoders/HexEncoder.java b/core/src/main/java/org/bouncycastle/util/encoders/HexEncoder.java
deleted file mode 100644
index 52f8fa6d..00000000
--- a/core/src/main/java/org/bouncycastle/util/encoders/HexEncoder.java
+++ /dev/null
@@ -1,190 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * A streaming Hex encoder.
- */
-public class HexEncoder
- implements Encoder
-{
- protected final byte[] encodingTable =
- {
- (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
- (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'
- };
-
- /*
- * set up the decoding table.
- */
- protected final byte[] decodingTable = new byte[128];
-
- protected void initialiseDecodingTable()
- {
- for (int i = 0; i < decodingTable.length; i++)
- {
- decodingTable[i] = (byte)0xff;
- }
-
- for (int i = 0; i < encodingTable.length; i++)
- {
- decodingTable[encodingTable[i]] = (byte)i;
- }
-
- decodingTable['A'] = decodingTable['a'];
- decodingTable['B'] = decodingTable['b'];
- decodingTable['C'] = decodingTable['c'];
- decodingTable['D'] = decodingTable['d'];
- decodingTable['E'] = decodingTable['e'];
- decodingTable['F'] = decodingTable['f'];
- }
-
- public HexEncoder()
- {
- initialiseDecodingTable();
- }
-
- /**
- * encode the input data producing a Hex output stream.
- *
- * @return the number of bytes produced.
- */
- public int encode(
- byte[] data,
- int off,
- int length,
- OutputStream out)
- throws IOException
- {
- for (int i = off; i < (off + length); i++)
- {
- int v = data[i] & 0xff;
-
- out.write(encodingTable[(v >>> 4)]);
- out.write(encodingTable[v & 0xf]);
- }
-
- return length * 2;
- }
-
- private static boolean ignore(
- char c)
- {
- return c == '\n' || c =='\r' || c == '\t' || c == ' ';
- }
-
- /**
- * decode the Hex encoded byte data writing it to the given output stream,
- * whitespace characters will be ignored.
- *
- * @return the number of bytes produced.
- */
- public int decode(
- byte[] data,
- int off,
- int length,
- OutputStream out)
- throws IOException
- {
- byte b1, b2;
- int outLen = 0;
-
- int end = off + length;
-
- while (end > off)
- {
- if (!ignore((char)data[end - 1]))
- {
- break;
- }
-
- end--;
- }
-
- int i = off;
- while (i < end)
- {
- while (i < end && ignore((char)data[i]))
- {
- i++;
- }
-
- b1 = decodingTable[data[i++]];
-
- while (i < end && ignore((char)data[i]))
- {
- i++;
- }
-
- b2 = decodingTable[data[i++]];
-
- if ((b1 | b2) < 0)
- {
- throw new IOException("invalid characters encountered in Hex data");
- }
-
- out.write((b1 << 4) | b2);
-
- outLen++;
- }
-
- return outLen;
- }
-
- /**
- * decode the Hex encoded String data writing it to the given output stream,
- * whitespace characters will be ignored.
- *
- * @return the number of bytes produced.
- */
- public int decode(
- String data,
- OutputStream out)
- throws IOException
- {
- byte b1, b2;
- int length = 0;
-
- int end = data.length();
-
- while (end > 0)
- {
- if (!ignore(data.charAt(end - 1)))
- {
- break;
- }
-
- end--;
- }
-
- int i = 0;
- while (i < end)
- {
- while (i < end && ignore(data.charAt(i)))
- {
- i++;
- }
-
- b1 = decodingTable[data.charAt(i++)];
-
- while (i < end && ignore(data.charAt(i)))
- {
- i++;
- }
-
- b2 = decodingTable[data.charAt(i++)];
-
- if ((b1 | b2) < 0)
- {
- throw new IOException("invalid characters encountered in Hex string");
- }
-
- out.write((b1 << 4) | b2);
-
- length++;
- }
-
- return length;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/encoders/HexTranslator.java b/core/src/main/java/org/bouncycastle/util/encoders/HexTranslator.java
deleted file mode 100644
index 3fff65a6..00000000
--- a/core/src/main/java/org/bouncycastle/util/encoders/HexTranslator.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-/**
- * Converters for going from hex to binary and back. Note: this class assumes ASCII processing.
- */
-public class HexTranslator
- implements Translator
-{
- private static final byte[] hexTable =
- {
- (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
- (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'
- };
-
- /**
- * size of the output block on encoding produced by getDecodedBlockSize()
- * bytes.
- */
- public int getEncodedBlockSize()
- {
- return 2;
- }
-
- public int encode(
- byte[] in,
- int inOff,
- int length,
- byte[] out,
- int outOff)
- {
- for (int i = 0, j = 0; i < length; i++, j += 2)
- {
- out[outOff + j] = hexTable[(in[inOff] >> 4) & 0x0f];
- out[outOff + j + 1] = hexTable[in[inOff] & 0x0f];
-
- inOff++;
- }
-
- return length * 2;
- }
-
- /**
- * size of the output block on decoding produced by getEncodedBlockSize()
- * bytes.
- */
- public int getDecodedBlockSize()
- {
- return 1;
- }
-
- public int decode(
- byte[] in,
- int inOff,
- int length,
- byte[] out,
- int outOff)
- {
- int halfLength = length / 2;
- byte left, right;
- for (int i = 0; i < halfLength; i++)
- {
- left = in[inOff + i * 2];
- right = in[inOff + i * 2 + 1];
-
- if (left < (byte)'a')
- {
- out[outOff] = (byte)((left - '0') << 4);
- }
- else
- {
- out[outOff] = (byte)((left - 'a' + 10) << 4);
- }
- if (right < (byte)'a')
- {
- out[outOff] += (byte)(right - '0');
- }
- else
- {
- out[outOff] += (byte)(right - 'a' + 10);
- }
-
- outOff++;
- }
-
- return halfLength;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/encoders/Translator.java b/core/src/main/java/org/bouncycastle/util/encoders/Translator.java
deleted file mode 100644
index 96381bcf..00000000
--- a/core/src/main/java/org/bouncycastle/util/encoders/Translator.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-/**
- * General interface for an translator.
- */
-public interface Translator
-{
- /**
- * size of the output block on encoding produced by getDecodedBlockSize()
- * bytes.
- */
- public int getEncodedBlockSize();
-
- public int encode(byte[] in, int inOff, int length, byte[] out, int outOff);
-
- /**
- * size of the output block on decoding produced by getEncodedBlockSize()
- * bytes.
- */
- public int getDecodedBlockSize();
-
- public int decode(byte[] in, int inOff, int length, byte[] out, int outOff);
-}
diff --git a/core/src/main/java/org/bouncycastle/util/encoders/UrlBase64.java b/core/src/main/java/org/bouncycastle/util/encoders/UrlBase64.java
deleted file mode 100644
index 3b83e956..00000000
--- a/core/src/main/java/org/bouncycastle/util/encoders/UrlBase64.java
+++ /dev/null
@@ -1,129 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * Convert binary data to and from UrlBase64 encoding. This is identical to
- * Base64 encoding, except that the padding character is "." and the other
- * non-alphanumeric characters are "-" and "_" instead of "+" and "/".
- * <p>
- * The purpose of UrlBase64 encoding is to provide a compact encoding of binary
- * data that is safe for use as an URL parameter. Base64 encoding does not
- * produce encoded values that are safe for use in URLs, since "/" can be
- * interpreted as a path delimiter; "+" is the encoded form of a space; and
- * "=" is used to separate a name from the corresponding value in an URL
- * parameter.
- */
-public class UrlBase64
-{
- private static final Encoder encoder = new UrlBase64Encoder();
-
- /**
- * Encode the input data producing a URL safe base 64 encoded byte array.
- *
- * @return a byte array containing the URL safe base 64 encoded data.
- */
- public static byte[] encode(
- byte[] data)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- try
- {
- encoder.encode(data, 0, data.length, bOut);
- }
- catch (Exception e)
- {
- throw new EncoderException("exception encoding URL safe base64 data: " + e.getMessage(), e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * Encode the byte data writing it to the given output stream.
- *
- * @return the number of bytes produced.
- */
- public static int encode(
- byte[] data,
- OutputStream out)
- throws IOException
- {
- return encoder.encode(data, 0, data.length, out);
- }
-
- /**
- * Decode the URL safe base 64 encoded input data - white space will be ignored.
- *
- * @return a byte array representing the decoded data.
- */
- public static byte[] decode(
- byte[] data)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- try
- {
- encoder.decode(data, 0, data.length, bOut);
- }
- catch (Exception e)
- {
- throw new DecoderException("exception decoding URL safe base64 string: " + e.getMessage(), e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * decode the URL safe base 64 encoded byte data writing it to the given output stream,
- * whitespace characters will be ignored.
- *
- * @return the number of bytes produced.
- */
- public static int decode(
- byte[] data,
- OutputStream out)
- throws IOException
- {
- return encoder.decode(data, 0, data.length, out);
- }
-
- /**
- * decode the URL safe base 64 encoded String data - whitespace will be ignored.
- *
- * @return a byte array representing the decoded data.
- */
- public static byte[] decode(
- String data)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- try
- {
- encoder.decode(data, bOut);
- }
- catch (Exception e)
- {
- throw new DecoderException("exception decoding URL safe base64 string: " + e.getMessage(), e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * Decode the URL safe base 64 encoded String data writing it to the given output stream,
- * whitespace characters will be ignored.
- *
- * @return the number of bytes produced.
- */
- public static int decode(
- String data,
- OutputStream out)
- throws IOException
- {
- return encoder.decode(data, out);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/encoders/UrlBase64Encoder.java b/core/src/main/java/org/bouncycastle/util/encoders/UrlBase64Encoder.java
deleted file mode 100644
index a5fff5ec..00000000
--- a/core/src/main/java/org/bouncycastle/util/encoders/UrlBase64Encoder.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-/**
- * Convert binary data to and from UrlBase64 encoding. This is identical to
- * Base64 encoding, except that the padding character is "." and the other
- * non-alphanumeric characters are "-" and "_" instead of "+" and "/".
- * <p>
- * The purpose of UrlBase64 encoding is to provide a compact encoding of binary
- * data that is safe for use as an URL parameter. Base64 encoding does not
- * produce encoded values that are safe for use in URLs, since "/" can be
- * interpreted as a path delimiter; "+" is the encoded form of a space; and
- * "=" is used to separate a name from the corresponding value in an URL
- * parameter.
- */
-public class UrlBase64Encoder extends Base64Encoder
-{
- public UrlBase64Encoder()
- {
- encodingTable[encodingTable.length - 2] = (byte) '-';
- encodingTable[encodingTable.length - 1] = (byte) '_';
- padding = (byte) '.';
- // we must re-create the decoding table with the new encoded values.
- initialiseDecodingTable();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/io/BufferingOutputStream.java b/core/src/main/java/org/bouncycastle/util/io/BufferingOutputStream.java
deleted file mode 100644
index 9d5fe142..00000000
--- a/core/src/main/java/org/bouncycastle/util/io/BufferingOutputStream.java
+++ /dev/null
@@ -1,108 +0,0 @@
-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/core/src/main/java/org/bouncycastle/util/io/StreamOverflowException.java b/core/src/main/java/org/bouncycastle/util/io/StreamOverflowException.java
deleted file mode 100644
index ed5518d7..00000000
--- a/core/src/main/java/org/bouncycastle/util/io/StreamOverflowException.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.bouncycastle.util.io;
-
-import java.io.IOException;
-
-/**
- * Exception thrown when too much data is written to an InputStream
- */
-public class StreamOverflowException
- extends IOException
-{
- public StreamOverflowException(String msg)
- {
- super(msg);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/io/Streams.java b/core/src/main/java/org/bouncycastle/util/io/Streams.java
deleted file mode 100644
index 0dea2369..00000000
--- a/core/src/main/java/org/bouncycastle/util/io/Streams.java
+++ /dev/null
@@ -1,145 +0,0 @@
-package org.bouncycastle.util.io;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * Utility methods to assist with stream processing.
- */
-public final class Streams
-{
- private static int BUFFER_SIZE = 512;
-
- /**
- * Read stream till EOF is encountered.
- *
- * @param inStr stream to be emptied.
- * @throws IOException in case of underlying IOException.
- */
- public static void drain(InputStream inStr)
- throws IOException
- {
- byte[] bs = new byte[BUFFER_SIZE];
- while (inStr.read(bs, 0, bs.length) >= 0)
- {
- }
- }
-
- /**
- * Read stream fully, returning contents in a byte array.
- *
- * @param inStr stream to be read.
- * @return a byte array representing the contents of inStr.
- * @throws IOException in case of underlying IOException.
- */
- public static byte[] readAll(InputStream inStr)
- throws IOException
- {
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
- pipeAll(inStr, buf);
- return buf.toByteArray();
- }
-
- /**
- * Read from inStr up to a maximum number of bytes, throwing an exception if more the maximum amount
- * of requested data is available.
- *
- * @param inStr stream to be read.
- * @param limit maximum number of bytes that can be read.
- * @return a byte array representing the contents of inStr.
- * @throws IOException in case of underlying IOException, or if limit is reached on inStr still has data in it.
- */
- public static byte[] readAllLimited(InputStream inStr, int limit)
- throws IOException
- {
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
- pipeAllLimited(inStr, limit, buf);
- return buf.toByteArray();
- }
-
- /**
- * Fully read in buf's length in data, or up to EOF, whichever occurs first,
- *
- * @param inStr the stream to be read.
- * @param buf the buffer to be read into.
- * @return the number of bytes read into the buffer.
- * @throws IOException in case of underlying IOException.
- */
- public static int readFully(InputStream inStr, byte[] buf)
- throws IOException
- {
- return readFully(inStr, buf, 0, buf.length);
- }
-
- /**
- * Fully read in len's bytes of data into buf, or up to EOF, whichever occurs first,
- *
- * @param inStr the stream to be read.
- * @param buf the buffer to be read into.
- * @param off offset into buf to start putting bytes into.
- * @param len the number of bytes to be read.
- * @return the number of bytes read into the buffer.
- * @throws IOException in case of underlying IOException.
- */
- public static int readFully(InputStream inStr, byte[] buf, int off, int len)
- throws IOException
- {
- int totalRead = 0;
- while (totalRead < len)
- {
- int numRead = inStr.read(buf, off + totalRead, len - totalRead);
- if (numRead < 0)
- {
- break;
- }
- totalRead += numRead;
- }
- return totalRead;
- }
-
- /**
- * Write the full contents of inStr to the destination stream outStr.
- *
- * @param inStr source input stream.
- * @param outStr destination output stream.
- * @throws IOException in case of underlying IOException.
- */
- public static void pipeAll(InputStream inStr, OutputStream outStr)
- throws IOException
- {
- byte[] bs = new byte[BUFFER_SIZE];
- int numRead;
- while ((numRead = inStr.read(bs, 0, bs.length)) >= 0)
- {
- outStr.write(bs, 0, numRead);
- }
- }
-
- /**
- * Write up to limit bytes of data from inStr to the destination stream outStr.
- *
- * @param inStr source input stream.
- * @param limit the maximum number of bytes allowed to be read.
- * @param outStr destination output stream.
- * @throws IOException in case of underlying IOException, or if limit is reached on inStr still has data in it.
- */
- public static long pipeAllLimited(InputStream inStr, long limit, OutputStream outStr)
- throws IOException
- {
- long total = 0;
- byte[] bs = new byte[BUFFER_SIZE];
- int numRead;
- while ((numRead = inStr.read(bs, 0, bs.length)) >= 0)
- {
- total += numRead;
- if (total > limit)
- {
- throw new StreamOverflowException("Data Overflow");
- }
- outStr.write(bs, 0, numRead);
- }
- return total;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/io/TeeInputStream.java b/core/src/main/java/org/bouncycastle/util/io/TeeInputStream.java
deleted file mode 100644
index 96da1694..00000000
--- a/core/src/main/java/org/bouncycastle/util/io/TeeInputStream.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.bouncycastle.util.io;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * An input stream which copies anything read through it to another stream.
- */
-public class TeeInputStream
- extends InputStream
-{
- private final InputStream input;
- private final OutputStream output;
-
- /**
- * Base constructor.
- *
- * @param input input stream to be wrapped.
- * @param output output stream to copy any input read to.
- */
- public TeeInputStream(InputStream input, OutputStream output)
- {
- this.input = input;
- this.output = output;
- }
-
- public int read(byte[] buf)
- throws IOException
- {
- return read(buf, 0, buf.length);
- }
-
- public int read(byte[] buf, int off, int len)
- throws IOException
- {
- int i = input.read(buf, off, len);
-
- if (i > 0)
- {
- output.write(buf, off, i);
- }
-
- return i;
- }
-
- public int read()
- throws IOException
- {
- int i = input.read();
-
- if (i >= 0)
- {
- output.write(i);
- }
-
- return i;
- }
-
- public void close()
- throws IOException
- {
- this.input.close();
- this.output.close();
- }
-
- public OutputStream getOutputStream()
- {
- return output;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/io/TeeOutputStream.java b/core/src/main/java/org/bouncycastle/util/io/TeeOutputStream.java
deleted file mode 100644
index 05b2b563..00000000
--- a/core/src/main/java/org/bouncycastle/util/io/TeeOutputStream.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package org.bouncycastle.util.io;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-
-/**
- * An output stream which copies anything written into it to another stream.
- */
-public class TeeOutputStream
- extends OutputStream
-{
- private OutputStream output1;
- private OutputStream output2;
-
- /**
- * Base constructor.
- *
- * @param output1 the output stream that is wrapped.
- * @param output2 a secondary stream that anything written to output1 is also written to.
- */
- public TeeOutputStream(OutputStream output1, OutputStream output2)
- {
- this.output1 = output1;
- this.output2 = output2;
- }
-
- public void write(byte[] buf)
- throws IOException
- {
- this.output1.write(buf);
- this.output2.write(buf);
- }
-
- public void write(byte[] buf, int off, int len)
- throws IOException
- {
- this.output1.write(buf, off, len);
- this.output2.write(buf, off, len);
- }
-
- public void write(int b)
- throws IOException
- {
- this.output1.write(b);
- this.output2.write(b);
- }
-
- public void flush()
- throws IOException
- {
- this.output1.flush();
- this.output2.flush();
- }
-
- public void close()
- throws IOException
- {
- this.output1.close();
- this.output2.close();
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/org/bouncycastle/util/io/pem/PemGenerationException.java b/core/src/main/java/org/bouncycastle/util/io/pem/PemGenerationException.java
deleted file mode 100644
index 63f61f2d..00000000
--- a/core/src/main/java/org/bouncycastle/util/io/pem/PemGenerationException.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.bouncycastle.util.io.pem;
-
-import java.io.IOException;
-
-/**
- * Exception thrown on failure to generate a PEM object.
- */
-public class PemGenerationException
- extends IOException
-{
- private Throwable cause;
-
- public PemGenerationException(String message, Throwable cause)
- {
- super(message);
- this.cause = cause;
- }
-
- public PemGenerationException(String message)
- {
- super(message);
- }
-
- public Throwable getCause()
- {
- return cause;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/io/pem/PemHeader.java b/core/src/main/java/org/bouncycastle/util/io/pem/PemHeader.java
deleted file mode 100644
index bbc6108e..00000000
--- a/core/src/main/java/org/bouncycastle/util/io/pem/PemHeader.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package org.bouncycastle.util.io.pem;
-
-/**
- * Class representing a PEM header (name, value) pair.
- */
-public class PemHeader
-{
- private String name;
- private String value;
-
- /**
- * Base constructor.
- *
- * @param name name of the header property.
- * @param value value of the header property.
- */
- public PemHeader(String name, String value)
- {
- this.name = name;
- this.value = value;
- }
-
- public String getName()
- {
- return name;
- }
-
- public String getValue()
- {
- return value;
- }
-
- public int hashCode()
- {
- return getHashCode(this.name) + 31 * getHashCode(this.value);
- }
-
- public boolean equals(Object o)
- {
- if (!(o instanceof PemHeader))
- {
- return false;
- }
-
- PemHeader other = (PemHeader)o;
-
- return other == this || (isEqual(this.name, other.name) && isEqual(this.value, other.value));
- }
-
- private int getHashCode(String s)
- {
- if (s == null)
- {
- return 1;
- }
-
- return s.hashCode();
- }
-
- private boolean isEqual(String s1, String s2)
- {
- if (s1 == s2)
- {
- return true;
- }
-
- if (s1 == null || s2 == null)
- {
- return false;
- }
-
- return s1.equals(s2);
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/util/io/pem/PemObject.java b/core/src/main/java/org/bouncycastle/util/io/pem/PemObject.java
deleted file mode 100644
index 606330d8..00000000
--- a/core/src/main/java/org/bouncycastle/util/io/pem/PemObject.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.bouncycastle.util.io.pem;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * A generic PEM object - type, header properties, and byte content.
- */
-public class PemObject
- implements PemObjectGenerator
-{
- private static final List EMPTY_LIST = Collections.unmodifiableList(new ArrayList());
-
- private String type;
- private List headers;
- private byte[] content;
-
- /**
- * Generic constructor for object without headers.
- *
- * @param type pem object type.
- * @param content the binary content of the object.
- */
- public PemObject(String type, byte[] content)
- {
- this(type, EMPTY_LIST, content);
- }
-
- /**
- * Generic constructor for object with headers.
- *
- * @param type pem object type.
- * @param headers a list of PemHeader objects.
- * @param content the binary content of the object.
- */
- public PemObject(String type, List headers, byte[] content)
- {
- this.type = type;
- this.headers = Collections.unmodifiableList(headers);
- this.content = content;
- }
-
- public String getType()
- {
- return type;
- }
-
- public List getHeaders()
- {
- return headers;
- }
-
- public byte[] getContent()
- {
- return content;
- }
-
- public PemObject generate()
- throws PemGenerationException
- {
- return this;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/io/pem/PemObjectGenerator.java b/core/src/main/java/org/bouncycastle/util/io/pem/PemObjectGenerator.java
deleted file mode 100644
index 96646392..00000000
--- a/core/src/main/java/org/bouncycastle/util/io/pem/PemObjectGenerator.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.bouncycastle.util.io.pem;
-
-/**
- * Base interface for generators of PEM objects.
- */
-public interface PemObjectGenerator
-{
- /**
- * Generate a PEM object.
- *
- * @return the generated object.
- * @throws PemGenerationException on failure.
- */
- PemObject generate()
- throws PemGenerationException;
-}
diff --git a/core/src/main/java/org/bouncycastle/util/io/pem/PemObjectParser.java b/core/src/main/java/org/bouncycastle/util/io/pem/PemObjectParser.java
deleted file mode 100644
index 933da6ab..00000000
--- a/core/src/main/java/org/bouncycastle/util/io/pem/PemObjectParser.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.bouncycastle.util.io.pem;
-
-import java.io.IOException;
-
-/**
- * Base interface for parsers to convert PEM objects into specific objects.
- */
-public interface PemObjectParser
-{
- /**
- * Parse an object out of the PEM object passed in.
- *
- * @param obj the PEM object containing the details for the specific object.
- * @return a specific object represented by the PEM object.
- * @throws IOException on a parsing error.
- */
- Object parseObject(PemObject obj)
- throws IOException;
-}
diff --git a/core/src/main/java/org/bouncycastle/util/io/pem/PemReader.java b/core/src/main/java/org/bouncycastle/util/io/pem/PemReader.java
deleted file mode 100644
index 3045b4d0..00000000
--- a/core/src/main/java/org/bouncycastle/util/io/pem/PemReader.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package org.bouncycastle.util.io.pem;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.bouncycastle.util.encoders.Base64;
-
-/**
- * A generic PEM reader, based on the format outlined in RFC 1421
- */
-public class PemReader
- extends BufferedReader
-{
- private static final String BEGIN = "-----BEGIN ";
- private static final String END = "-----END ";
-
- public PemReader(Reader reader)
- {
- super(reader);
- }
-
- public PemObject readPemObject()
- throws IOException
- {
- String line = readLine();
-
- while (line != null && !line.startsWith(BEGIN))
- {
- line = readLine();
- }
-
- if (line != null)
- {
- line = line.substring(BEGIN.length());
- int index = line.indexOf('-');
- String type = line.substring(0, index);
-
- if (index > 0)
- {
- return loadObject(type);
- }
- }
-
- return null;
- }
-
- private PemObject loadObject(String type)
- throws IOException
- {
- String line;
- String endMarker = END + type;
- StringBuffer buf = new StringBuffer();
- List headers = new ArrayList();
-
- while ((line = readLine()) != null)
- {
- if (line.indexOf(":") >= 0)
- {
- int index = line.indexOf(':');
- String hdr = line.substring(0, index);
- String value = line.substring(index + 1).trim();
-
- headers.add(new PemHeader(hdr, value));
-
- continue;
- }
-
- if (line.indexOf(endMarker) != -1)
- {
- break;
- }
-
- buf.append(line.trim());
- }
-
- if (line == null)
- {
- throw new IOException(endMarker + " not found");
- }
-
- return new PemObject(type, headers, Base64.decode(buf.toString()));
- }
-
-}
diff --git a/core/src/main/java/org/bouncycastle/util/io/pem/PemWriter.java b/core/src/main/java/org/bouncycastle/util/io/pem/PemWriter.java
deleted file mode 100644
index ccefa36e..00000000
--- a/core/src/main/java/org/bouncycastle/util/io/pem/PemWriter.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package org.bouncycastle.util.io.pem;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Iterator;
-
-import org.bouncycastle.util.encoders.Base64;
-
-/**
- * A generic PEM writer, based on RFC 1421
- */
-public class PemWriter
- extends BufferedWriter
-{
- private static final int LINE_LENGTH = 64;
-
- private final int nlLength;
- private char[] buf = new char[LINE_LENGTH];
-
- /**
- * Base constructor.
- *
- * @param out output stream to use.
- */
- public PemWriter(Writer out)
- {
- super(out);
-
- String nl = System.getProperty("line.separator");
- if (nl != null)
- {
- nlLength = nl.length();
- }
- else
- {
- nlLength = 2;
- }
- }
-
- /**
- * Return the number of bytes or characters required to contain the
- * passed in object if it is PEM encoded.
- *
- * @param obj pem object to be output
- * @return an estimate of the number of bytes
- */
- public int getOutputSize(PemObject obj)
- {
- // BEGIN and END boundaries.
- int size = (2 * (obj.getType().length() + 10 + nlLength)) + 6 + 4;
-
- if (!obj.getHeaders().isEmpty())
- {
- for (Iterator it = obj.getHeaders().iterator(); it.hasNext();)
- {
- PemHeader hdr = (PemHeader)it.next();
-
- size += hdr.getName().length() + ": ".length() + hdr.getValue().length() + nlLength;
- }
-
- size += nlLength;
- }
-
- // base64 encoding
- int dataLen = ((obj.getContent().length + 2) / 3) * 4;
-
- size += dataLen + (((dataLen + LINE_LENGTH - 1) / LINE_LENGTH) * nlLength);
-
- return size;
- }
-
- public void writeObject(PemObjectGenerator objGen)
- throws IOException
- {
- PemObject obj = objGen.generate();
-
- writePreEncapsulationBoundary(obj.getType());
-
- if (!obj.getHeaders().isEmpty())
- {
- for (Iterator it = obj.getHeaders().iterator(); it.hasNext();)
- {
- PemHeader hdr = (PemHeader)it.next();
-
- this.write(hdr.getName());
- this.write(": ");
- this.write(hdr.getValue());
- this.newLine();
- }
-
- this.newLine();
- }
-
- writeEncoded(obj.getContent());
- writePostEncapsulationBoundary(obj.getType());
- }
-
- private void writeEncoded(byte[] bytes)
- throws IOException
- {
- bytes = Base64.encode(bytes);
-
- for (int i = 0; i < bytes.length; i += buf.length)
- {
- int index = 0;
-
- while (index != buf.length)
- {
- if ((i + index) >= bytes.length)
- {
- break;
- }
- buf[index] = (char)bytes[i + index];
- index++;
- }
- this.write(buf, 0, index);
- this.newLine();
- }
- }
-
- private void writePreEncapsulationBoundary(
- String type)
- throws IOException
- {
- this.write("-----BEGIN " + type + "-----");
- this.newLine();
- }
-
- private void writePostEncapsulationBoundary(
- String type)
- throws IOException
- {
- this.write("-----END " + type + "-----");
- this.newLine();
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/test/FixedSecureRandom.java b/core/src/main/java/org/bouncycastle/util/test/FixedSecureRandom.java
deleted file mode 100644
index 49bd7301..00000000
--- a/core/src/main/java/org/bouncycastle/util/test/FixedSecureRandom.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package org.bouncycastle.util.test;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.security.SecureRandom;
-
-public class FixedSecureRandom
- extends SecureRandom
-{
- private byte[] _data;
-
- private int _index;
- private int _intPad;
-
- public FixedSecureRandom(byte[] value)
- {
- this(false, new byte[][] { value });
- }
-
- public FixedSecureRandom(
- byte[][] values)
- {
- this(false, values);
- }
-
- /**
- * Pad the data on integer boundaries. This is necessary for the classpath project's BigInteger
- * implementation.
- */
- public FixedSecureRandom(
- boolean intPad,
- byte[] value)
- {
- this(intPad, new byte[][] { value });
- }
-
- /**
- * Pad the data on integer boundaries. This is necessary for the classpath project's BigInteger
- * implementation.
- */
- public FixedSecureRandom(
- boolean intPad,
- byte[][] values)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- for (int i = 0; i != values.length; i++)
- {
- try
- {
- bOut.write(values[i]);
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("can't save value array.");
- }
- }
-
- _data = bOut.toByteArray();
-
- if (intPad)
- {
- _intPad = _data.length % 4;
- }
- }
-
- public void nextBytes(byte[] bytes)
- {
- System.arraycopy(_data, _index, bytes, 0, bytes.length);
-
- _index += bytes.length;
- }
-
- //
- // 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.
- //
- public int nextInt()
- {
- int val = 0;
-
- val |= nextValue() << 24;
- val |= nextValue() << 16;
-
- if (_intPad == 2)
- {
- _intPad--;
- }
- else
- {
- val |= nextValue() << 8;
- }
-
- if (_intPad == 1)
- {
- _intPad--;
- }
- else
- {
- val |= nextValue();
- }
-
- return val;
- }
-
- //
- // 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.
- //
- public long nextLong()
- {
- long val = 0;
-
- val |= (long)nextValue() << 56;
- val |= (long)nextValue() << 48;
- val |= (long)nextValue() << 40;
- val |= (long)nextValue() << 32;
- val |= (long)nextValue() << 24;
- val |= (long)nextValue() << 16;
- val |= (long)nextValue() << 8;
- val |= (long)nextValue();
-
- return val;
- }
-
- public boolean isExhausted()
- {
- return _index == _data.length;
- }
-
- private int nextValue()
- {
- return _data[_index++] & 0xff;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/test/NumberParsing.java b/core/src/main/java/org/bouncycastle/util/test/NumberParsing.java
deleted file mode 100644
index a060dd8e..00000000
--- a/core/src/main/java/org/bouncycastle/util/test/NumberParsing.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.bouncycastle.util.test;
-
-/**
- * Parsing
- */
-public final class NumberParsing
-{
- private NumberParsing()
- {
- // Hide constructor
- }
-
- public static long decodeLongFromHex(String longAsString)
- {
- if ((longAsString.charAt(1) == 'x')
- || (longAsString.charAt(1) == 'X'))
- {
- return Long.parseLong(longAsString.substring(2), 16);
- }
-
- return Long.parseLong(longAsString, 16);
- }
-
- public static int decodeIntFromHex(String intAsString)
- {
- if ((intAsString.charAt(1) == 'x')
- || (intAsString.charAt(1) == 'X'))
- {
- return Integer.parseInt(intAsString.substring(2), 16);
- }
-
- return Integer.parseInt(intAsString, 16);
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/test/SimpleTest.java b/core/src/main/java/org/bouncycastle/util/test/SimpleTest.java
deleted file mode 100644
index ef8ee617..00000000
--- a/core/src/main/java/org/bouncycastle/util/test/SimpleTest.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package org.bouncycastle.util.test;
-
-import java.io.PrintStream;
-
-import org.bouncycastle.util.Arrays;
-
-public abstract class SimpleTest
- implements Test
-{
- public abstract String getName();
-
- private TestResult success()
- {
- return SimpleTestResult.successful(this, "Okay");
- }
-
- protected void fail(
- String message)
- {
- throw new TestFailedException(SimpleTestResult.failed(this, message));
- }
-
- protected void fail(
- String message,
- Throwable throwable)
- {
- throw new TestFailedException(SimpleTestResult.failed(this, message, throwable));
- }
-
- protected void fail(
- String message,
- Object expected,
- Object found)
- {
- throw new TestFailedException(SimpleTestResult.failed(this, message, expected, found));
- }
-
- protected boolean areEqual(
- byte[] a,
- byte[] b)
- {
- return Arrays.areEqual(a, b);
- }
-
- public TestResult perform()
- {
- try
- {
- performTest();
-
- return success();
- }
- catch (TestFailedException e)
- {
- return e.getResult();
- }
- catch (Exception e)
- {
- return SimpleTestResult.failed(this, "Exception: " + e, e);
- }
- }
-
- protected static void runTest(
- Test test)
- {
- runTest(test, System.out);
- }
-
- protected static void runTest(
- Test test,
- PrintStream out)
- {
- TestResult result = test.perform();
-
- out.println(result.toString());
- if (result.getException() != null)
- {
- result.getException().printStackTrace(out);
- }
- }
-
- public abstract void performTest()
- throws Exception;
-}
diff --git a/core/src/main/java/org/bouncycastle/util/test/SimpleTestResult.java b/core/src/main/java/org/bouncycastle/util/test/SimpleTestResult.java
deleted file mode 100644
index bd69fe8e..00000000
--- a/core/src/main/java/org/bouncycastle/util/test/SimpleTestResult.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package org.bouncycastle.util.test;
-
-public class SimpleTestResult implements TestResult
-{
- private static final String SEPARATOR = System.getProperty("line.separator");
-
- private boolean success;
- private String message;
- private Throwable exception;
-
- public SimpleTestResult(boolean success, String message)
- {
- this.success = success;
- this.message = message;
- }
-
- public SimpleTestResult(boolean success, String message, Throwable exception)
- {
- this.success = success;
- this.message = message;
- this.exception = exception;
- }
-
- public static TestResult successful(
- Test test,
- String message)
- {
- return new SimpleTestResult(true, test.getName() + ": " + message);
- }
-
- public static TestResult failed(
- Test test,
- String message)
- {
- return new SimpleTestResult(false, test.getName() + ": " + message);
- }
-
- public static TestResult failed(
- Test test,
- String message,
- Throwable t)
- {
- return new SimpleTestResult(false, test.getName() + ": " + message, t);
- }
-
- public static TestResult failed(
- Test test,
- String message,
- Object expected,
- Object found)
- {
- return failed(test, message + SEPARATOR + "Expected: " + expected + SEPARATOR + "Found : " + found);
- }
-
- public static String failedMessage(String algorithm, String testName, String expected,
- String actual)
- {
- StringBuffer sb = new StringBuffer(algorithm);
- sb.append(" failing ").append(testName);
- sb.append(SEPARATOR).append(" expected: ").append(expected);
- sb.append(SEPARATOR).append(" got : ").append(actual);
-
- return sb.toString();
- }
-
- public boolean isSuccessful()
- {
- return success;
- }
-
- public String toString()
- {
- return message;
- }
-
- public Throwable getException()
- {
- return exception;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/test/Test.java b/core/src/main/java/org/bouncycastle/util/test/Test.java
deleted file mode 100644
index e631cd02..00000000
--- a/core/src/main/java/org/bouncycastle/util/test/Test.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.bouncycastle.util.test;
-
-public interface Test
-{
- String getName();
-
- TestResult perform();
-}
diff --git a/core/src/main/java/org/bouncycastle/util/test/TestFailedException.java b/core/src/main/java/org/bouncycastle/util/test/TestFailedException.java
deleted file mode 100644
index 21e95d37..00000000
--- a/core/src/main/java/org/bouncycastle/util/test/TestFailedException.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.bouncycastle.util.test;
-
-public class TestFailedException
- extends RuntimeException
-{
- private TestResult _result;
-
- public TestFailedException(
- TestResult result)
- {
- _result = result;
- }
-
- public TestResult getResult()
- {
- return _result;
- }
-}
diff --git a/core/src/main/java/org/bouncycastle/util/test/TestResult.java b/core/src/main/java/org/bouncycastle/util/test/TestResult.java
deleted file mode 100644
index 0a1885f0..00000000
--- a/core/src/main/java/org/bouncycastle/util/test/TestResult.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.bouncycastle.util.test;
-
-public interface TestResult
-{
- public boolean isSuccessful();
-
- public Throwable getException();
-
- public String toString();
-}
diff --git a/core/src/main/java/org/bouncycastle/util/test/UncloseableOutputStream.java b/core/src/main/java/org/bouncycastle/util/test/UncloseableOutputStream.java
deleted file mode 100644
index 89073d71..00000000
--- a/core/src/main/java/org/bouncycastle/util/test/UncloseableOutputStream.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.util.test;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class UncloseableOutputStream extends FilterOutputStream
-{
- public UncloseableOutputStream(OutputStream s)
- {
- super(s);
- }
-
- public void close()
- {
- throw new RuntimeException("close() called on UncloseableOutputStream");
- }
-
- public void write(byte[] b, int off, int len) throws IOException
- {
- out.write(b, off, len);
- }
- }
diff --git a/core/src/main/java/org/spongycastle/LICENSE.java b/core/src/main/java/org/spongycastle/LICENSE.java
new file mode 100644
index 00000000..9733cc57
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/LICENSE.java
@@ -0,0 +1,63 @@
+package org.spongycastle;
+
+/**
+ * The Bouncy Castle License
+ *
+ * Copyright (c) 2000-2014 The Legion Of The Bouncy Castle Inc. (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,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ * <p>
+ * The above copyright notice and this permission notice shall be included in all copies or substantial
+ * portions of the Software.
+ * <p>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+public class LICENSE
+{
+ public static String licenseText =
+ "Copyright (c) 2000-2014 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 "
+ + System.getProperty("line.separator")
+ + "and associated documentation files (the \"Software\"), to deal in the Software without restriction, "
+ + System.getProperty("line.separator")
+ + "including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, "
+ + System.getProperty("line.separator")
+ + "and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,"
+ + System.getProperty("line.separator")
+ + "subject to the following conditions:"
+ + System.getProperty("line.separator")
+ + System.getProperty("line.separator")
+ + "The above copyright notice and this permission notice shall be included in all copies or substantial"
+ + System.getProperty("line.separator")
+ + "portions of the Software."
+ + System.getProperty("line.separator")
+ + System.getProperty("line.separator")
+ + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,"
+ + System.getProperty("line.separator")
+ + "INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR"
+ + System.getProperty("line.separator")
+ + "PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE"
+ + System.getProperty("line.separator")
+ + "LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR"
+ + System.getProperty("line.separator")
+ + "OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER"
+ + System.getProperty("line.separator")
+ + "DEALINGS IN THE SOFTWARE.";
+
+ public static void main(
+ String[] args)
+ {
+ System.out.println(licenseText);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1ApplicationSpecificParser.java b/core/src/main/java/org/spongycastle/asn1/ASN1ApplicationSpecificParser.java
new file mode 100644
index 00000000..4f643349
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1ApplicationSpecificParser.java
@@ -0,0 +1,19 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * Interface to parse ASN.1 application specific objects.
+ */
+public interface ASN1ApplicationSpecificParser
+ extends ASN1Encodable, InMemoryRepresentable
+{
+ /**
+ * Read the next object in the parser.
+ *
+ * @return an ASN1Encodable
+ * @throws IOException on a parsing or decoding error.
+ */
+ ASN1Encodable readObject()
+ throws IOException;
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1Boolean.java b/core/src/main/java/org/spongycastle/asn1/ASN1Boolean.java
new file mode 100644
index 00000000..47091bd9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1Boolean.java
@@ -0,0 +1,204 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+import org.spongycastle.util.Arrays;
+
+/**
+ * Public facade of ASN.1 Boolean data.
+ * <p>
+ * Use following to place a new instance of ASN.1 Boolean in your dataset:
+ * </p>
+ * <ul>
+ * <li> ASN1Boolean.TRUE literal</li>
+ * <li> ASN1Boolean.FALSE literal</li>
+ * <li> {@link ASN1Boolean#getInstance(boolean) ASN1Boolean.getInstance(boolean)}</li>
+ * <li> {@link ASN1Boolean#getInstance(int) ASN1Boolean.getInstance(int)}</li>
+ * </ul>
+ * </p>
+ */
+public class ASN1Boolean
+ extends ASN1Primitive
+{
+ private static final byte[] TRUE_VALUE = new byte[] { (byte)0xff };
+ private static final byte[] FALSE_VALUE = new byte[] { 0 };
+
+ private byte[] value;
+
+ public static final ASN1Boolean FALSE = new ASN1Boolean(false);
+ public static final ASN1Boolean TRUE = new ASN1Boolean(true);
+
+ /**
+ * return a boolean from the passed in object.
+ *
+ * @param obj an ASN1Boolean or an object that can be converted into one.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ * @return an ASN1Boolean instance.
+ */
+ public static ASN1Boolean getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1Boolean)
+ {
+ return (ASN1Boolean)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ byte[] enc = (byte[])obj;
+ try
+ {
+ return (ASN1Boolean)fromByteArray(enc);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("failed to construct boolean from byte[]: " + e.getMessage());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an ASN1Boolean from the passed in boolean.
+ * @return an ASN1Boolean instance.
+ */
+ public static ASN1Boolean getInstance(
+ boolean value)
+ {
+ return (value ? TRUE : FALSE);
+ }
+
+ /**
+ * return an ASN1Boolean from the passed in value.
+ * @return an ASN1Boolean instance.
+ */
+ public static ASN1Boolean getInstance(
+ int value)
+ {
+ return (value != 0 ? TRUE : FALSE);
+ }
+
+ /**
+ * return a Boolean from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ * @return an ASN1Boolean instance.
+ */
+ public static ASN1Boolean getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof ASN1Boolean)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return ASN1Boolean.fromOctetString(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ ASN1Boolean(
+ byte[] value)
+ {
+ if (value.length != 1)
+ {
+ throw new IllegalArgumentException("byte value should have 1 byte in it");
+ }
+
+ if (value[0] == 0)
+ {
+ this.value = FALSE_VALUE;
+ }
+ else if ((value[0] & 0xff) == 0xff)
+ {
+ this.value = TRUE_VALUE;
+ }
+ else
+ {
+ this.value = Arrays.clone(value);
+ }
+ }
+
+ /**
+ * @deprecated use getInstance(boolean) method.
+ * @param value true or false.
+ */
+ public ASN1Boolean(
+ boolean value)
+ {
+ this.value = (value) ? TRUE_VALUE : FALSE_VALUE;
+ }
+
+ public boolean isTrue()
+ {
+ return (value[0] != 0);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 3;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.BOOLEAN, value);
+ }
+
+ protected boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (o instanceof ASN1Boolean)
+ {
+ return (value[0] == ((ASN1Boolean)o).value[0]);
+ }
+
+ return false;
+ }
+
+ public int hashCode()
+ {
+ return value[0];
+ }
+
+
+ public String toString()
+ {
+ return (value[0] != 0) ? "TRUE" : "FALSE";
+ }
+
+ static ASN1Boolean fromOctetString(byte[] value)
+ {
+ if (value.length != 1)
+ {
+ throw new IllegalArgumentException("BOOLEAN value should have 1 byte in it");
+ }
+
+ if (value[0] == 0)
+ {
+ return FALSE;
+ }
+ else if ((value[0] & 0xff) == 0xff)
+ {
+ return TRUE;
+ }
+ else
+ {
+ return new ASN1Boolean(value);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1Choice.java b/core/src/main/java/org/spongycastle/asn1/ASN1Choice.java
new file mode 100644
index 00000000..233c5543
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1Choice.java
@@ -0,0 +1,28 @@
+package org.spongycastle.asn1;
+
+/**
+ * Marker interface for CHOICE objects - if you implement this in a role your
+ * own object any attempt to tag the object implicitly will convert the tag to
+ * an explicit one as the encoding rules require.
+ * <p>
+ * If you use this interface your class should also implement the getInstance()
+ * pattern which takes a tag object and the tagging mode used.
+ * <p>
+ * <hr>
+ * <p><b>X.690</b></p>
+ * <p><b>8: Basic encoding rules</b></p>
+ * <p><b>8.13 Encoding of a choice value </b></p>
+ * <p>
+ * The encoding of a choice value shall be the same as the encoding of a value of the chosen type.
+ * <blockquote>
+ * NOTE 1 &mdash; The encoding may be primitive or constructed depending on the chosen type.
+ * <p>
+ * NOTE 2 &mdash; The tag used in the identifier octets is the tag of the chosen type,
+ * as specified in the ASN.1 definition of the choice type.
+ * </blockquote>
+ * </p>
+ */
+public interface ASN1Choice
+{
+ // marker interface
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1Encodable.java b/core/src/main/java/org/spongycastle/asn1/ASN1Encodable.java
new file mode 100644
index 00000000..60a57e38
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1Encodable.java
@@ -0,0 +1,13 @@
+package org.spongycastle.asn1;
+
+/**
+ * Basic interface to produce serialisers for ASN.1 encodings.
+ */
+public interface ASN1Encodable
+{
+ /**
+ * Return an object, possibly constructed, of ASN.1 primitives
+ * @return an ASN.1 primitive.
+ */
+ ASN1Primitive toASN1Primitive();
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1EncodableVector.java b/core/src/main/java/org/spongycastle/asn1/ASN1EncodableVector.java
new file mode 100644
index 00000000..61984aa4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1EncodableVector.java
@@ -0,0 +1,63 @@
+package org.spongycastle.asn1;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+/**
+ * Mutable class for building ASN.1 constructed objects.
+ */
+public class ASN1EncodableVector
+{
+ Vector v = new Vector();
+
+ /**
+ * Base constructor.
+ */
+ public ASN1EncodableVector()
+ {
+ }
+
+ /**
+ * Add an encodable to the vector.
+ *
+ * @param obj the encodable to add.
+ */
+ public void add(ASN1Encodable obj)
+ {
+ v.addElement(obj);
+ }
+
+ /**
+ * Add the contents of another vector.
+ *
+ * @param other the vector to add.
+ */
+ public void addAll(ASN1EncodableVector other)
+ {
+ for (Enumeration en = other.v.elements(); en.hasMoreElements();)
+ {
+ v.addElement(en.nextElement());
+ }
+ }
+
+ /**
+ * Return the object at position i in this vector.
+ *
+ * @param i the index of the object of interest.
+ * @return the object at position i.
+ */
+ public ASN1Encodable get(int i)
+ {
+ return (ASN1Encodable)v.elementAt(i);
+ }
+
+ /**
+ * Return the size of the vector.
+ *
+ * @return the object count in the vector.
+ */
+ public int size()
+ {
+ return v.size();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1Encoding.java b/core/src/main/java/org/spongycastle/asn1/ASN1Encoding.java
new file mode 100644
index 00000000..683e752d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1Encoding.java
@@ -0,0 +1,22 @@
+package org.spongycastle.asn1;
+
+/**
+ * Supported encoding formats.
+ */
+public interface ASN1Encoding
+{
+ /**
+ * DER - distinguished encoding rules.
+ */
+ static final String DER = "DER";
+
+ /**
+ * DL - definite length encoding.
+ */
+ static final String DL = "DL";
+
+ /**
+ * BER - basic encoding rules.
+ */
+ static final String BER = "BER";
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1Enumerated.java b/core/src/main/java/org/spongycastle/asn1/ASN1Enumerated.java
new file mode 100644
index 00000000..bb9f15eb
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1Enumerated.java
@@ -0,0 +1,174 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+import org.spongycastle.util.Arrays;
+
+/**
+ * Class representing the ASN.1 ENUMERATED type.
+ */
+public class ASN1Enumerated
+ extends ASN1Primitive
+{
+ byte[] bytes;
+
+ /**
+ * return an enumerated from the passed in object
+ *
+ * @param obj an ASN1Enumerated or an object that can be converted into one.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ * @return an ASN1Enumerated instance, or null.
+ */
+ public static ASN1Enumerated getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1Enumerated)
+ {
+ return (ASN1Enumerated)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (ASN1Enumerated)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an Enumerated from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ * @return an ASN1Enumerated instance, or null.
+ */
+ public static ASN1Enumerated getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof ASN1Enumerated)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return fromOctetString(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ /**
+ * Constructor from int.
+ *
+ * @param value the value of this enumerated.
+ */
+ public ASN1Enumerated(
+ int value)
+ {
+ bytes = BigInteger.valueOf(value).toByteArray();
+ }
+
+ /**
+ * Constructor from BigInteger
+ *
+ * @param value the value of this enumerated.
+ */
+ public ASN1Enumerated(
+ BigInteger value)
+ {
+ bytes = value.toByteArray();
+ }
+
+ /**
+ * Constructor from encoded BigInteger.
+ *
+ * @param bytes the value of this enumerated as an encoded BigInteger (signed).
+ */
+ public ASN1Enumerated(
+ byte[] bytes)
+ {
+ this.bytes = bytes;
+ }
+
+ public BigInteger getValue()
+ {
+ return new BigInteger(bytes);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(bytes.length) + bytes.length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.ENUMERATED, bytes);
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1Enumerated))
+ {
+ return false;
+ }
+
+ ASN1Enumerated other = (ASN1Enumerated)o;
+
+ return Arrays.areEqual(this.bytes, other.bytes);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(bytes);
+ }
+
+ private static ASN1Enumerated[] cache = new ASN1Enumerated[12];
+
+ static ASN1Enumerated fromOctetString(byte[] enc)
+ {
+ if (enc.length > 1)
+ {
+ return new ASN1Enumerated(Arrays.clone(enc));
+ }
+
+ if (enc.length == 0)
+ {
+ throw new IllegalArgumentException("ENUMERATED has zero length");
+ }
+ int value = enc[0] & 0xff;
+
+ if (value >= cache.length)
+ {
+ return new ASN1Enumerated(Arrays.clone(enc));
+ }
+
+ ASN1Enumerated possibleMatch = cache[value];
+
+ if (possibleMatch == null)
+ {
+ possibleMatch = cache[value] = new ASN1Enumerated(Arrays.clone(enc));
+ }
+
+ return possibleMatch;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1Exception.java b/core/src/main/java/org/spongycastle/asn1/ASN1Exception.java
new file mode 100644
index 00000000..20c8a934
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1Exception.java
@@ -0,0 +1,25 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+public class ASN1Exception
+ extends IOException
+{
+ private Throwable cause;
+
+ ASN1Exception(String message)
+ {
+ super(message);
+ }
+
+ ASN1Exception(String message, Throwable cause)
+ {
+ super(message);
+ this.cause = cause;
+ }
+
+ public Throwable getCause()
+ {
+ return cause;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1GeneralizedTime.java b/core/src/main/java/org/spongycastle/asn1/ASN1GeneralizedTime.java
new file mode 100644
index 00000000..c69720a1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1GeneralizedTime.java
@@ -0,0 +1,373 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.SimpleTimeZone;
+import java.util.TimeZone;
+
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Strings;
+
+/**
+ * Base class representing the ASN.1 GeneralizedTime type.
+ * <p>
+ * The main difference between these and UTC time is a 4 digit year.
+ * </p>
+ */
+public class ASN1GeneralizedTime
+ extends ASN1Primitive
+{
+ private byte[] time;
+
+ /**
+ * return a generalized time from the passed in object
+ *
+ * @param obj an ASN1GeneralizedTime or an object that can be converted into one.
+ * @return an ASN1GeneralizedTime instance, or null.
+ * @throws IllegalArgumentException if the object cannot be converted.
+ */
+ public static ASN1GeneralizedTime getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1GeneralizedTime)
+ {
+ return (ASN1GeneralizedTime)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (ASN1GeneralizedTime)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return a Generalized Time object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @return an ASN1GeneralizedTime instance.
+ * @throws IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static ASN1GeneralizedTime getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof ASN1GeneralizedTime)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new ASN1GeneralizedTime(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ /**
+ * The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z
+ * for local time, or Z+-HHMM on the end, for difference between local
+ * time and UTC time. The fractional second amount f must consist of at
+ * least one number with trailing zeroes removed.
+ *
+ * @param time the time string.
+ * @throws IllegalArgumentException if String is an illegal format.
+ */
+ public ASN1GeneralizedTime(
+ String time)
+ {
+ this.time = Strings.toByteArray(time);
+ try
+ {
+ this.getDate();
+ }
+ catch (ParseException e)
+ {
+ throw new IllegalArgumentException("invalid date string: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Base constructor from a java.util.date object
+ *
+ * @param time a date object representing the time of interest.
+ */
+ public ASN1GeneralizedTime(
+ Date time)
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
+
+ dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
+
+ this.time = Strings.toByteArray(dateF.format(time));
+ }
+
+ /**
+ * Base constructor from a java.util.date and Locale - you may need to use this if the default locale
+ * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible with other ASN.1 implementations.
+ *
+ * @param time a date object representing the time of interest.
+ * @param locale an appropriate Locale for producing an ASN.1 GeneralizedTime value.
+ */
+ public ASN1GeneralizedTime(
+ Date time,
+ Locale locale)
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'", locale);
+
+ dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
+
+ this.time = Strings.toByteArray(dateF.format(time));
+ }
+
+ ASN1GeneralizedTime(
+ byte[] bytes)
+ {
+ this.time = bytes;
+ }
+
+ /**
+ * Return the time.
+ *
+ * @return The time string as it appeared in the encoded object.
+ */
+ public String getTimeString()
+ {
+ return Strings.fromByteArray(time);
+ }
+
+ /**
+ * return the time - always in the form of
+ * YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
+ * <p/>
+ * Normally in a certificate we would expect "Z" rather than "GMT",
+ * however adding the "GMT" means we can just use:
+ * <pre>
+ * dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
+ * </pre>
+ * To read in the time and get a date which is compatible with our local
+ * time zone.
+ */
+ public String getTime()
+ {
+ String stime = Strings.fromByteArray(time);
+
+ //
+ // standardise the format.
+ //
+ if (stime.charAt(stime.length() - 1) == 'Z')
+ {
+ return stime.substring(0, stime.length() - 1) + "GMT+00:00";
+ }
+ else
+ {
+ int signPos = stime.length() - 5;
+ char sign = stime.charAt(signPos);
+ if (sign == '-' || sign == '+')
+ {
+ return stime.substring(0, signPos)
+ + "GMT"
+ + stime.substring(signPos, signPos + 3)
+ + ":"
+ + stime.substring(signPos + 3);
+ }
+ else
+ {
+ signPos = stime.length() - 3;
+ sign = stime.charAt(signPos);
+ if (sign == '-' || sign == '+')
+ {
+ return stime.substring(0, signPos)
+ + "GMT"
+ + stime.substring(signPos)
+ + ":00";
+ }
+ }
+ }
+ return stime + calculateGMTOffset();
+ }
+
+ private String calculateGMTOffset()
+ {
+ String sign = "+";
+ TimeZone timeZone = TimeZone.getDefault();
+ int offset = timeZone.getRawOffset();
+ if (offset < 0)
+ {
+ sign = "-";
+ offset = -offset;
+ }
+ int hours = offset / (60 * 60 * 1000);
+ int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000);
+
+ try
+ {
+ if (timeZone.useDaylightTime() && timeZone.inDaylightTime(this.getDate()))
+ {
+ hours += sign.equals("+") ? 1 : -1;
+ }
+ }
+ catch (ParseException e)
+ {
+ // we'll do our best and ignore daylight savings
+ }
+
+ return "GMT" + sign + convert(hours) + ":" + convert(minutes);
+ }
+
+ private String convert(int time)
+ {
+ if (time < 10)
+ {
+ return "0" + time;
+ }
+
+ return Integer.toString(time);
+ }
+
+ public Date getDate()
+ throws ParseException
+ {
+ SimpleDateFormat dateF;
+ String stime = Strings.fromByteArray(time);
+ String d = stime;
+
+ if (stime.endsWith("Z"))
+ {
+ if (hasFractionalSeconds())
+ {
+ dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS'Z'");
+ }
+ else
+ {
+ dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
+ }
+
+ dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
+ }
+ else if (stime.indexOf('-') > 0 || stime.indexOf('+') > 0)
+ {
+ d = this.getTime();
+ if (hasFractionalSeconds())
+ {
+ dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSz");
+ }
+ else
+ {
+ dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
+ }
+
+ dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
+ }
+ else
+ {
+ if (hasFractionalSeconds())
+ {
+ dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS");
+ }
+ else
+ {
+ dateF = new SimpleDateFormat("yyyyMMddHHmmss");
+ }
+
+ dateF.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID()));
+ }
+
+ if (hasFractionalSeconds())
+ {
+ // java misinterprets extra digits as being milliseconds...
+ String frac = d.substring(14);
+ int index;
+ for (index = 1; index < frac.length(); index++)
+ {
+ char ch = frac.charAt(index);
+ if (!('0' <= ch && ch <= '9'))
+ {
+ break;
+ }
+ }
+
+ if (index - 1 > 3)
+ {
+ frac = frac.substring(0, 4) + frac.substring(index);
+ d = d.substring(0, 14) + frac;
+ }
+ else if (index - 1 == 1)
+ {
+ frac = frac.substring(0, index) + "00" + frac.substring(index);
+ d = d.substring(0, 14) + frac;
+ }
+ else if (index - 1 == 2)
+ {
+ frac = frac.substring(0, index) + "0" + frac.substring(index);
+ d = d.substring(0, 14) + frac;
+ }
+ }
+
+ return dateF.parse(d);
+ }
+
+ private boolean hasFractionalSeconds()
+ {
+ for (int i = 0; i != time.length; i++)
+ {
+ if (time[i] == '.')
+ {
+ if (i == 14)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ int length = time.length;
+
+ return 1 + StreamUtil.calculateBodyLength(length) + length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.GENERALIZED_TIME, time);
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1GeneralizedTime))
+ {
+ return false;
+ }
+
+ return Arrays.areEqual(time, ((ASN1GeneralizedTime)o).time);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(time);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1Generator.java b/core/src/main/java/org/spongycastle/asn1/ASN1Generator.java
new file mode 100644
index 00000000..c5c087f6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1Generator.java
@@ -0,0 +1,15 @@
+package org.spongycastle.asn1;
+
+import java.io.OutputStream;
+
+public abstract class ASN1Generator
+{
+ protected OutputStream _out;
+
+ public ASN1Generator(OutputStream out)
+ {
+ _out = out;
+ }
+
+ public abstract OutputStream getRawOutputStream();
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1InputStream.java b/core/src/main/java/org/spongycastle/asn1/ASN1InputStream.java
new file mode 100644
index 00000000..71eaf433
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1InputStream.java
@@ -0,0 +1,472 @@
+package org.spongycastle.asn1;
+
+import java.io.ByteArrayInputStream;
+import java.io.EOFException;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.spongycastle.util.io.Streams;
+
+/**
+ * a general purpose ASN.1 decoder - note: this class differs from the
+ * others in that it returns null after it has read the last object in
+ * the stream. If an ASN.1 NULL is encountered a DER/BER Null object is
+ * returned.
+ */
+public class ASN1InputStream
+ extends FilterInputStream
+ implements BERTags
+{
+ private final int limit;
+ private final boolean lazyEvaluate;
+
+ private final byte[][] tmpBuffers;
+
+ public ASN1InputStream(
+ InputStream is)
+ {
+ this(is, StreamUtil.findLimit(is));
+ }
+
+ /**
+ * Create an ASN1InputStream based on the input byte array. The length of DER objects in
+ * the stream is automatically limited to the length of the input array.
+ *
+ * @param input array containing ASN.1 encoded data.
+ */
+ public ASN1InputStream(
+ byte[] input)
+ {
+ this(new ByteArrayInputStream(input), input.length);
+ }
+
+ /**
+ * Create an ASN1InputStream based on the input byte array. The length of DER objects in
+ * the stream is automatically limited to the length of the input array.
+ *
+ * @param input array containing ASN.1 encoded data.
+ * @param lazyEvaluate true if parsing inside constructed objects can be delayed.
+ */
+ public ASN1InputStream(
+ byte[] input,
+ boolean lazyEvaluate)
+ {
+ this(new ByteArrayInputStream(input), input.length, lazyEvaluate);
+ }
+
+ /**
+ * Create an ASN1InputStream where no DER object will be longer than limit.
+ *
+ * @param input stream containing ASN.1 encoded data.
+ * @param limit maximum size of a DER encoded object.
+ */
+ public ASN1InputStream(
+ InputStream input,
+ int limit)
+ {
+ this(input, limit, false);
+ }
+
+ /**
+ * Create an ASN1InputStream where no DER object will be longer than limit, and constructed
+ * objects such as sequences will be parsed lazily.
+ *
+ * @param input stream containing ASN.1 encoded data.
+ * @param lazyEvaluate true if parsing inside constructed objects can be delayed.
+ */
+ public ASN1InputStream(
+ InputStream input,
+ boolean lazyEvaluate)
+ {
+ this(input, StreamUtil.findLimit(input), lazyEvaluate);
+ }
+
+ /**
+ * Create an ASN1InputStream where no DER object will be longer than limit, and constructed
+ * objects such as sequences will be parsed lazily.
+ *
+ * @param input stream containing ASN.1 encoded data.
+ * @param limit maximum size of a DER encoded object.
+ * @param lazyEvaluate true if parsing inside constructed objects can be delayed.
+ */
+ public ASN1InputStream(
+ InputStream input,
+ int limit,
+ boolean lazyEvaluate)
+ {
+ super(input);
+ this.limit = limit;
+ this.lazyEvaluate = lazyEvaluate;
+ this.tmpBuffers = new byte[11][];
+ }
+
+ int getLimit()
+ {
+ return limit;
+ }
+
+ protected int readLength()
+ throws IOException
+ {
+ return readLength(this, limit);
+ }
+
+ protected void readFully(
+ byte[] bytes)
+ throws IOException
+ {
+ if (Streams.readFully(this, bytes) != bytes.length)
+ {
+ throw new EOFException("EOF encountered in middle of object");
+ }
+ }
+
+ /**
+ * build an object given its tag and the number of bytes to construct it from.
+ *
+ * @param tag the full tag details.
+ * @param tagNo the tagNo defined.
+ * @param length the length of the object.
+ * @return the resulting primitive.
+ * @throws java.io.IOException on processing exception.
+ */
+ protected ASN1Primitive buildObject(
+ int tag,
+ int tagNo,
+ int length)
+ throws IOException
+ {
+ boolean isConstructed = (tag & CONSTRUCTED) != 0;
+
+ DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this, length);
+
+ if ((tag & APPLICATION) != 0)
+ {
+ return new DERApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
+ }
+
+ if ((tag & TAGGED) != 0)
+ {
+ return new ASN1StreamParser(defIn).readTaggedObject(isConstructed, tagNo);
+ }
+
+ if (isConstructed)
+ {
+ // TODO There are other tags that may be constructed (e.g. BIT_STRING)
+ switch (tagNo)
+ {
+ case OCTET_STRING:
+ //
+ // yes, people actually do this...
+ //
+ ASN1EncodableVector v = buildDEREncodableVector(defIn);
+ ASN1OctetString[] strings = new ASN1OctetString[v.size()];
+
+ for (int i = 0; i != strings.length; i++)
+ {
+ strings[i] = (ASN1OctetString)v.get(i);
+ }
+
+ return new BEROctetString(strings);
+ case SEQUENCE:
+ if (lazyEvaluate)
+ {
+ return new LazyEncodedSequence(defIn.toByteArray());
+ }
+ else
+ {
+ return DERFactory.createSequence(buildDEREncodableVector(defIn));
+ }
+ case SET:
+ return DERFactory.createSet(buildDEREncodableVector(defIn));
+ case EXTERNAL:
+ return new DERExternal(buildDEREncodableVector(defIn));
+ default:
+ throw new IOException("unknown tag " + tagNo + " encountered");
+ }
+ }
+
+ return createPrimitiveDERObject(tagNo, defIn, tmpBuffers);
+ }
+
+ ASN1EncodableVector buildEncodableVector()
+ throws IOException
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ ASN1Primitive o;
+
+ while ((o = readObject()) != null)
+ {
+ v.add(o);
+ }
+
+ return v;
+ }
+
+ ASN1EncodableVector buildDEREncodableVector(
+ DefiniteLengthInputStream dIn) throws IOException
+ {
+ return new ASN1InputStream(dIn).buildEncodableVector();
+ }
+
+ public ASN1Primitive readObject()
+ throws IOException
+ {
+ int tag = read();
+ if (tag <= 0)
+ {
+ if (tag == 0)
+ {
+ throw new IOException("unexpected end-of-contents marker");
+ }
+
+ return null;
+ }
+
+ //
+ // calculate tag number
+ //
+ int tagNo = readTagNumber(this, tag);
+
+ boolean isConstructed = (tag & CONSTRUCTED) != 0;
+
+ //
+ // calculate length
+ //
+ int length = readLength();
+
+ if (length < 0) // indefinite length method
+ {
+ if (!isConstructed)
+ {
+ throw new IOException("indefinite length primitive encoding encountered");
+ }
+
+ IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this, limit);
+ ASN1StreamParser sp = new ASN1StreamParser(indIn, limit);
+
+ if ((tag & APPLICATION) != 0)
+ {
+ return new BERApplicationSpecificParser(tagNo, sp).getLoadedObject();
+ }
+
+ if ((tag & TAGGED) != 0)
+ {
+ return new BERTaggedObjectParser(true, tagNo, sp).getLoadedObject();
+ }
+
+ // TODO There are other tags that may be constructed (e.g. BIT_STRING)
+ switch (tagNo)
+ {
+ case OCTET_STRING:
+ return new BEROctetStringParser(sp).getLoadedObject();
+ case SEQUENCE:
+ return new BERSequenceParser(sp).getLoadedObject();
+ case SET:
+ return new BERSetParser(sp).getLoadedObject();
+ case EXTERNAL:
+ return new DERExternalParser(sp).getLoadedObject();
+ default:
+ throw new IOException("unknown BER object encountered");
+ }
+ }
+ else
+ {
+ try
+ {
+ return buildObject(tag, tagNo, length);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new ASN1Exception("corrupted stream detected", e);
+ }
+ }
+ }
+
+ static int readTagNumber(InputStream s, int tag)
+ throws IOException
+ {
+ int tagNo = tag & 0x1f;
+
+ //
+ // with tagged object tag number is bottom 5 bits, or stored at the start of the content
+ //
+ if (tagNo == 0x1f)
+ {
+ tagNo = 0;
+
+ int b = s.read();
+
+ // X.690-0207 8.1.2.4.2
+ // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
+ if ((b & 0x7f) == 0) // Note: -1 will pass
+ {
+ throw new IOException("corrupted stream - invalid high tag number found");
+ }
+
+ while ((b >= 0) && ((b & 0x80) != 0))
+ {
+ tagNo |= (b & 0x7f);
+ tagNo <<= 7;
+ b = s.read();
+ }
+
+ if (b < 0)
+ {
+ throw new EOFException("EOF found inside tag value.");
+ }
+
+ tagNo |= (b & 0x7f);
+ }
+
+ return tagNo;
+ }
+
+ static int readLength(InputStream s, int limit)
+ throws IOException
+ {
+ int length = s.read();
+ if (length < 0)
+ {
+ throw new EOFException("EOF found when length expected");
+ }
+
+ if (length == 0x80)
+ {
+ return -1; // indefinite-length encoding
+ }
+
+ if (length > 127)
+ {
+ int size = length & 0x7f;
+
+ // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
+ if (size > 4)
+ {
+ throw new IOException("DER length more than 4 bytes: " + size);
+ }
+
+ length = 0;
+ for (int i = 0; i < size; i++)
+ {
+ int next = s.read();
+
+ if (next < 0)
+ {
+ throw new EOFException("EOF found reading length");
+ }
+
+ length = (length << 8) + next;
+ }
+
+ if (length < 0)
+ {
+ throw new IOException("corrupted stream - negative length found");
+ }
+
+ if (length >= limit) // after all we must have read at least 1 byte
+ {
+ throw new IOException("corrupted stream - out of bounds length found");
+ }
+ }
+
+ return length;
+ }
+
+ private static byte[] getBuffer(DefiniteLengthInputStream defIn, byte[][] tmpBuffers)
+ throws IOException
+ {
+ int len = defIn.getRemaining();
+ if (defIn.getRemaining() < tmpBuffers.length)
+ {
+ byte[] buf = tmpBuffers[len];
+
+ if (buf == null)
+ {
+ buf = tmpBuffers[len] = new byte[len];
+ }
+
+ Streams.readFully(defIn, buf);
+
+ return buf;
+ }
+ else
+ {
+ return defIn.toByteArray();
+ }
+ }
+
+ private static char[] getBMPCharBuffer(DefiniteLengthInputStream defIn)
+ throws IOException
+ {
+ int len = defIn.getRemaining() / 2;
+ char[] buf = new char[len];
+ int totalRead = 0;
+ while (totalRead < len)
+ {
+ int ch1 = defIn.read();
+ if (ch1 < 0)
+ {
+ break;
+ }
+ int ch2 = defIn.read();
+ if (ch2 < 0)
+ {
+ break;
+ }
+ buf[totalRead++] = (char)((ch1 << 8) | (ch2 & 0xff));
+ }
+
+ return buf;
+ }
+
+ static ASN1Primitive createPrimitiveDERObject(
+ int tagNo,
+ DefiniteLengthInputStream defIn,
+ byte[][] tmpBuffers)
+ throws IOException
+ {
+ switch (tagNo)
+ {
+ case BIT_STRING:
+ return DERBitString.fromInputStream(defIn.getRemaining(), defIn);
+ case BMP_STRING:
+ return new DERBMPString(getBMPCharBuffer(defIn));
+ case BOOLEAN:
+ return ASN1Boolean.fromOctetString(getBuffer(defIn, tmpBuffers));
+ case ENUMERATED:
+ return ASN1Enumerated.fromOctetString(getBuffer(defIn, tmpBuffers));
+ case GENERALIZED_TIME:
+ return new ASN1GeneralizedTime(defIn.toByteArray());
+ case GENERAL_STRING:
+ return new DERGeneralString(defIn.toByteArray());
+ case IA5_STRING:
+ return new DERIA5String(defIn.toByteArray());
+ case INTEGER:
+ return new ASN1Integer(defIn.toByteArray(), false);
+ case NULL:
+ return DERNull.INSTANCE; // actual content is ignored (enforce 0 length?)
+ case NUMERIC_STRING:
+ return new DERNumericString(defIn.toByteArray());
+ case OBJECT_IDENTIFIER:
+ return ASN1ObjectIdentifier.fromOctetString(getBuffer(defIn, tmpBuffers));
+ case OCTET_STRING:
+ return new DEROctetString(defIn.toByteArray());
+ case PRINTABLE_STRING:
+ return new DERPrintableString(defIn.toByteArray());
+ case T61_STRING:
+ return new DERT61String(defIn.toByteArray());
+ case UNIVERSAL_STRING:
+ return new DERUniversalString(defIn.toByteArray());
+ case UTC_TIME:
+ return new ASN1UTCTime(defIn.toByteArray());
+ case UTF8_STRING:
+ return new DERUTF8String(defIn.toByteArray());
+ case VISIBLE_STRING:
+ return new DERVisibleString(defIn.toByteArray());
+ default:
+ throw new IOException("unknown tag " + tagNo + " encountered");
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1Integer.java b/core/src/main/java/org/spongycastle/asn1/ASN1Integer.java
new file mode 100644
index 00000000..1b852176
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1Integer.java
@@ -0,0 +1,157 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+import org.spongycastle.util.Arrays;
+
+/**
+ * Class representing the ASN.1 INTEGER type.
+ */
+public class ASN1Integer
+ extends ASN1Primitive
+{
+ byte[] bytes;
+
+ /**
+ * return an integer from the passed in object
+ *
+ * @param obj an ASN1Integer or an object that can be converted into one.
+ * @throws IllegalArgumentException if the object cannot be converted.
+ * @return an ASN1Integer instance.
+ */
+ public static ASN1Integer getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1Integer)
+ {
+ return (ASN1Integer)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (ASN1Integer)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an Integer from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @throws IllegalArgumentException if the tagged object cannot
+ * be converted.
+ * @return an ASN1Integer instance.
+ */
+ public static ASN1Integer getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof ASN1Integer)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new ASN1Integer(ASN1OctetString.getInstance(obj.getObject()).getOctets());
+ }
+ }
+
+ public ASN1Integer(
+ long value)
+ {
+ bytes = BigInteger.valueOf(value).toByteArray();
+ }
+
+ public ASN1Integer(
+ BigInteger value)
+ {
+ bytes = value.toByteArray();
+ }
+
+ public ASN1Integer(
+ byte[] bytes)
+ {
+ this(bytes, true);
+ }
+
+ ASN1Integer(byte[] bytes, boolean clone)
+ {
+ this.bytes = (clone) ? Arrays.clone(bytes) : bytes;
+ }
+
+ public BigInteger getValue()
+ {
+ return new BigInteger(bytes);
+ }
+
+ /**
+ * in some cases positive values get crammed into a space,
+ * that's not quite big enough...
+ * @return the BigInteger that results from treating this ASN.1 INTEGER as unsigned.
+ */
+ public BigInteger getPositiveValue()
+ {
+ return new BigInteger(1, bytes);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(bytes.length) + bytes.length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.INTEGER, bytes);
+ }
+
+ public int hashCode()
+ {
+ int value = 0;
+
+ for (int i = 0; i != bytes.length; i++)
+ {
+ value ^= (bytes[i] & 0xff) << (i % 4);
+ }
+
+ return value;
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1Integer))
+ {
+ return false;
+ }
+
+ ASN1Integer other = (ASN1Integer)o;
+
+ return Arrays.areEqual(bytes, other.bytes);
+ }
+
+ public String toString()
+ {
+ return getValue().toString();
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1Null.java b/core/src/main/java/org/spongycastle/asn1/ASN1Null.java
new file mode 100644
index 00000000..f1bd726a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1Null.java
@@ -0,0 +1,75 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * A NULL object - use DERNull.INSTANCE for populating structures.
+ */
+public abstract class ASN1Null
+ extends ASN1Primitive
+{
+ /**
+ * Return an instance of ASN.1 NULL from the passed in object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link ASN1Null} object
+ * <li> a byte[] containing ASN.1 NULL object
+ * </ul>
+ * </p>
+ *
+ * @param o object to be converted.
+ * @return an instance of ASN1Null, or null.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static ASN1Null getInstance(Object o)
+ {
+ if (o instanceof ASN1Null)
+ {
+ return (ASN1Null)o;
+ }
+
+ if (o != null)
+ {
+ try
+ {
+ return ASN1Null.getInstance(ASN1Primitive.fromByteArray((byte[])o));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("failed to construct NULL from byte[]: " + e.getMessage());
+ }
+ catch (ClassCastException e)
+ {
+ throw new IllegalArgumentException("unknown object in getInstance(): " + o.getClass().getName());
+ }
+ }
+
+ return null;
+ }
+
+ public int hashCode()
+ {
+ return -1;
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1Null))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ abstract void encode(ASN1OutputStream out)
+ throws IOException;
+
+ public String toString()
+ {
+ return "NULL";
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1Object.java b/core/src/main/java/org/spongycastle/asn1/ASN1Object.java
new file mode 100644
index 00000000..1dbfd26a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1Object.java
@@ -0,0 +1,111 @@
+package org.spongycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * Base class for defining an ASN.1 object.
+ */
+public abstract class ASN1Object
+ implements ASN1Encodable
+{
+ /**
+ * Return the default BER or DER encoding for this object.
+ *
+ * @return BER/DER byte encoded object.
+ * @throws java.io.IOException on encoding error.
+ */
+ public byte[] getEncoded()
+ throws IOException
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ aOut.writeObject(this);
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * Return either the default for "BER" or a DER encoding if "DER" is specified.
+ *
+ * @param encoding name of encoding to use.
+ * @return byte encoded object.
+ * @throws IOException on encoding error.
+ */
+ public byte[] getEncoded(
+ String encoding)
+ throws IOException
+ {
+ if (encoding.equals(ASN1Encoding.DER))
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ DEROutputStream dOut = new DEROutputStream(bOut);
+
+ dOut.writeObject(this);
+
+ return bOut.toByteArray();
+ }
+ else if (encoding.equals(ASN1Encoding.DL))
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ DLOutputStream dOut = new DLOutputStream(bOut);
+
+ dOut.writeObject(this);
+
+ return bOut.toByteArray();
+ }
+
+ return this.getEncoded();
+ }
+
+ public int hashCode()
+ {
+ return this.toASN1Primitive().hashCode();
+ }
+
+ public boolean equals(
+ Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+
+ if (!(o instanceof ASN1Encodable))
+ {
+ return false;
+ }
+
+ ASN1Encodable other = (ASN1Encodable)o;
+
+ return this.toASN1Primitive().equals(other.toASN1Primitive());
+ }
+
+ /**
+ * @deprecated use toASN1Primitive()
+ * @return the underlying primitive type.
+ */
+ public ASN1Primitive toASN1Object()
+ {
+ return this.toASN1Primitive();
+ }
+
+ /**
+ * Return true if obj is a byte array and represents an object with the given tag value.
+ *
+ * @param obj object of interest.
+ * @param tagValue tag value to check for.
+ * @return true if obj is a byte encoding starting with the given tag value, false otherwise.
+ */
+ protected static boolean hasEncodedTagValue(Object obj, int tagValue)
+ {
+ return (obj instanceof byte[]) && ((byte[])obj)[0] == tagValue;
+ }
+
+ /**
+ * Method providing a primitive representation of this object suitable for encoding.
+ * @return a primitive representation of this object.
+ */
+ public abstract ASN1Primitive toASN1Primitive();
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1ObjectIdentifier.java b/core/src/main/java/org/spongycastle/asn1/ASN1ObjectIdentifier.java
new file mode 100644
index 00000000..10353214
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1ObjectIdentifier.java
@@ -0,0 +1,472 @@
+package org.spongycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+
+import org.spongycastle.util.Arrays;
+
+/**
+ * Class representing the ASN.1 OBJECT IDENTIFIER type.
+ */
+public class ASN1ObjectIdentifier
+ extends ASN1Primitive
+{
+ String identifier;
+
+ private byte[] body;
+
+ /**
+ * return an OID from the passed in object
+ * @param obj an ASN1ObjectIdentifier or an object that can be converted into one.
+ * @throws IllegalArgumentException if the object cannot be converted.
+ * @return an ASN1ObjectIdentifier instance, or null.
+ */
+ public static ASN1ObjectIdentifier getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1ObjectIdentifier)
+ {
+ return (ASN1ObjectIdentifier)obj;
+ }
+
+ if (obj instanceof ASN1Encodable && ((ASN1Encodable)obj).toASN1Primitive() instanceof ASN1ObjectIdentifier)
+ {
+ return (ASN1ObjectIdentifier)((ASN1Encodable)obj).toASN1Primitive();
+ }
+
+ if (obj instanceof byte[])
+ {
+ byte[] enc = (byte[])obj;
+ try
+ {
+ return (ASN1ObjectIdentifier)fromByteArray(enc);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("failed to construct object identifier from byte[]: " + e.getMessage());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an Object Identifier from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @throws IllegalArgumentException if the tagged object cannot
+ * be converted.
+ * @return an ASN1ObjectIdentifier instance, or null.
+ */
+ public static ASN1ObjectIdentifier getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof ASN1ObjectIdentifier)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return ASN1ObjectIdentifier.fromOctetString(ASN1OctetString.getInstance(obj.getObject()).getOctets());
+ }
+ }
+
+ private static final long LONG_LIMIT = (Long.MAX_VALUE >> 7) - 0x7f;
+
+ ASN1ObjectIdentifier(
+ byte[] bytes)
+ {
+ StringBuffer objId = new StringBuffer();
+ long value = 0;
+ BigInteger bigValue = null;
+ boolean first = true;
+
+ for (int i = 0; i != bytes.length; i++)
+ {
+ int b = bytes[i] & 0xff;
+
+ if (value <= LONG_LIMIT)
+ {
+ value += (b & 0x7f);
+ if ((b & 0x80) == 0) // end of number reached
+ {
+ if (first)
+ {
+ if (value < 40)
+ {
+ objId.append('0');
+ }
+ else if (value < 80)
+ {
+ objId.append('1');
+ value -= 40;
+ }
+ else
+ {
+ objId.append('2');
+ value -= 80;
+ }
+ first = false;
+ }
+
+ objId.append('.');
+ objId.append(value);
+ value = 0;
+ }
+ else
+ {
+ value <<= 7;
+ }
+ }
+ else
+ {
+ if (bigValue == null)
+ {
+ bigValue = BigInteger.valueOf(value);
+ }
+ bigValue = bigValue.or(BigInteger.valueOf(b & 0x7f));
+ if ((b & 0x80) == 0)
+ {
+ if (first)
+ {
+ objId.append('2');
+ bigValue = bigValue.subtract(BigInteger.valueOf(80));
+ first = false;
+ }
+
+ objId.append('.');
+ objId.append(bigValue);
+ bigValue = null;
+ value = 0;
+ }
+ else
+ {
+ bigValue = bigValue.shiftLeft(7);
+ }
+ }
+ }
+
+ this.identifier = objId.toString();
+ this.body = Arrays.clone(bytes);
+ }
+
+ /**
+ * Create an OID based on the passed in String.
+ *
+ * @param identifier a string representation of an OID.
+ */
+ public ASN1ObjectIdentifier(
+ String identifier)
+ {
+ if (identifier == null)
+ {
+ throw new IllegalArgumentException("'identifier' cannot be null");
+ }
+ if (!isValidIdentifier(identifier))
+ {
+ throw new IllegalArgumentException("string " + identifier + " not an OID");
+ }
+
+ this.identifier = identifier;
+ }
+
+ /**
+ * Create an OID that creates a branch under the current one.
+ *
+ * @param branchID node numbers for the new branch.
+ * @return the OID for the new created branch.
+ */
+ ASN1ObjectIdentifier(ASN1ObjectIdentifier oid, String branchID)
+ {
+ if (!isValidBranchID(branchID, 0))
+ {
+ throw new IllegalArgumentException("string " + branchID + " not a valid OID branch");
+ }
+
+ this.identifier = oid.getId() + "." + branchID;
+ }
+
+ /**
+ * Return the OID as a string.
+ *
+ * @return the string representation of the OID carried by this object.
+ */
+ public String getId()
+ {
+ return identifier;
+ }
+
+ /**
+ * Return an OID that creates a branch under the current one.
+ *
+ * @param branchID node numbers for the new branch.
+ * @return the OID for the new created branch.
+ */
+ public ASN1ObjectIdentifier branch(String branchID)
+ {
+ return new ASN1ObjectIdentifier(this, branchID);
+ }
+
+ /**
+ * Return true if this oid is an extension of the passed in branch, stem.
+ *
+ * @param stem the arc or branch that is a possible parent.
+ * @return true if the branch is on the passed in stem, false otherwise.
+ */
+ public boolean on(ASN1ObjectIdentifier stem)
+ {
+ String id = getId(), stemId = stem.getId();
+ return id.length() > stemId.length() && id.charAt(stemId.length()) == '.' && id.startsWith(stemId);
+ }
+
+ private void writeField(
+ ByteArrayOutputStream out,
+ long fieldValue)
+ {
+ byte[] result = new byte[9];
+ int pos = 8;
+ result[pos] = (byte)((int)fieldValue & 0x7f);
+ while (fieldValue >= (1L << 7))
+ {
+ fieldValue >>= 7;
+ result[--pos] = (byte)((int)fieldValue & 0x7f | 0x80);
+ }
+ out.write(result, pos, 9 - pos);
+ }
+
+ private void writeField(
+ ByteArrayOutputStream out,
+ BigInteger fieldValue)
+ {
+ int byteCount = (fieldValue.bitLength() + 6) / 7;
+ if (byteCount == 0)
+ {
+ out.write(0);
+ }
+ else
+ {
+ BigInteger tmpValue = fieldValue;
+ byte[] tmp = new byte[byteCount];
+ for (int i = byteCount - 1; i >= 0; i--)
+ {
+ tmp[i] = (byte)((tmpValue.intValue() & 0x7f) | 0x80);
+ tmpValue = tmpValue.shiftRight(7);
+ }
+ tmp[byteCount - 1] &= 0x7f;
+ out.write(tmp, 0, tmp.length);
+ }
+ }
+
+ private void doOutput(ByteArrayOutputStream aOut)
+ {
+ OIDTokenizer tok = new OIDTokenizer(identifier);
+ int first = Integer.parseInt(tok.nextToken()) * 40;
+
+ String secondToken = tok.nextToken();
+ if (secondToken.length() <= 18)
+ {
+ writeField(aOut, first + Long.parseLong(secondToken));
+ }
+ else
+ {
+ writeField(aOut, new BigInteger(secondToken).add(BigInteger.valueOf(first)));
+ }
+
+ while (tok.hasMoreTokens())
+ {
+ String token = tok.nextToken();
+ if (token.length() <= 18)
+ {
+ writeField(aOut, Long.parseLong(token));
+ }
+ else
+ {
+ writeField(aOut, new BigInteger(token));
+ }
+ }
+ }
+
+ protected synchronized byte[] getBody()
+ {
+ if (body == null)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ doOutput(bOut);
+
+ body = bOut.toByteArray();
+ }
+
+ return body;
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ int length = getBody().length;
+
+ return 1 + StreamUtil.calculateBodyLength(length) + length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ byte[] enc = getBody();
+
+ out.write(BERTags.OBJECT_IDENTIFIER);
+ out.writeLength(enc.length);
+ out.write(enc);
+ }
+
+ public int hashCode()
+ {
+ return identifier.hashCode();
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1ObjectIdentifier))
+ {
+ return false;
+ }
+
+ return identifier.equals(((ASN1ObjectIdentifier)o).identifier);
+ }
+
+ public String toString()
+ {
+ return getId();
+ }
+
+ private static boolean isValidBranchID(
+ String branchID, int start)
+ {
+ boolean periodAllowed = false;
+
+ int pos = branchID.length();
+ while (--pos >= start)
+ {
+ char ch = branchID.charAt(pos);
+
+ // TODO Leading zeroes?
+ if ('0' <= ch && ch <= '9')
+ {
+ periodAllowed = true;
+ continue;
+ }
+
+ if (ch == '.')
+ {
+ if (!periodAllowed)
+ {
+ return false;
+ }
+
+ periodAllowed = false;
+ continue;
+ }
+
+ return false;
+ }
+
+ return periodAllowed;
+ }
+
+ private static boolean isValidIdentifier(
+ String identifier)
+ {
+ if (identifier.length() < 3 || identifier.charAt(1) != '.')
+ {
+ return false;
+ }
+
+ char first = identifier.charAt(0);
+ if (first < '0' || first > '2')
+ {
+ return false;
+ }
+
+ return isValidBranchID(identifier, 2);
+ }
+
+ private static ASN1ObjectIdentifier[][] cache = new ASN1ObjectIdentifier[256][];
+
+ static ASN1ObjectIdentifier fromOctetString(byte[] enc)
+ {
+ if (enc.length < 3)
+ {
+ return new ASN1ObjectIdentifier(enc);
+ }
+
+ int idx1 = enc[enc.length - 2] & 0xff;
+ // in this case top bit is always zero
+ int idx2 = enc[enc.length - 1] & 0x7f;
+
+ ASN1ObjectIdentifier possibleMatch;
+
+ synchronized (cache)
+ {
+ ASN1ObjectIdentifier[] first = cache[idx1];
+ if (first == null)
+ {
+ first = cache[idx1] = new ASN1ObjectIdentifier[128];
+ }
+
+ possibleMatch = first[idx2];
+ if (possibleMatch == null)
+ {
+ return first[idx2] = new ASN1ObjectIdentifier(enc);
+ }
+
+ if (Arrays.areEqual(enc, possibleMatch.getBody()))
+ {
+ return possibleMatch;
+ }
+
+ idx1 = (idx1 + 1) & 0xff;
+ first = cache[idx1];
+ if (first == null)
+ {
+ first = cache[idx1] = new ASN1ObjectIdentifier[128];
+ }
+
+ possibleMatch = first[idx2];
+ if (possibleMatch == null)
+ {
+ return first[idx2] = new ASN1ObjectIdentifier(enc);
+ }
+
+ if (Arrays.areEqual(enc, possibleMatch.getBody()))
+ {
+ return possibleMatch;
+ }
+
+ idx2 = (idx2 + 1) & 0x7f;
+ possibleMatch = first[idx2];
+ if (possibleMatch == null)
+ {
+ return first[idx2] = new ASN1ObjectIdentifier(enc);
+ }
+ }
+
+ if (Arrays.areEqual(enc, possibleMatch.getBody()))
+ {
+ return possibleMatch;
+ }
+
+ return new ASN1ObjectIdentifier(enc);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1OctetString.java b/core/src/main/java/org/spongycastle/asn1/ASN1OctetString.java
new file mode 100644
index 00000000..8068f80d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1OctetString.java
@@ -0,0 +1,251 @@
+package org.spongycastle.asn1;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+
+/**
+ * Abstract base for the ASN.1 OCTET STRING data type
+ * <p>
+ * This supports BER, and DER forms of the data.
+ * </p><p>
+ * DER form is always primitive single OCTET STRING, while
+ * BER support includes the constructed forms.
+ * </p>
+ * <hr>
+ * <p><b>X.690</b></p>
+ * <p><b>8: Basic encoding rules</b></p>
+ * <p><b>8.7 Encoding of an octetstring value</b></p>
+ * <p>
+ * <b>8.7.1</b> The encoding of an octetstring value shall be
+ * either primitive or constructed at the option of the sender.
+ * <blockquote>
+ * NOTE &mdash; Where it is necessary to transfer part of an octet string
+ * before the entire OCTET STRING is available, the constructed encoding
+ * is used.
+ * </blockquote>
+ * <p>
+ * <b>8.7.2</b> The primitive encoding contains zero,
+ * one or more contents octets equal in value to the octets
+ * in the data value, in the order they appear in the data value,
+ * and with the most significant bit of an octet of the data value
+ * aligned with the most significant bit of an octet of the contents octets.
+ * </p>
+ * <p>
+ * <b>8.7.3</b> The contents octets for the constructed encoding shall consist
+ * of zero, one, or more encodings.
+ * <blockquote>
+ * NOTE &mdash; Each such encoding includes identifier, length, and contents octets,
+ * and may include end-of-contents octets if it is constructed.
+ * </blockquote>
+ * </p>
+ * <p>
+ * <b>8.7.3.1</b> To encode an octetstring value in this way,
+ * it is segmented. Each segment shall consist of a series of
+ * consecutive octets of the value. There shall be no significance
+ * placed on the segment boundaries.
+ * <blockquote>
+ * NOTE &mdash; A segment may be of size zero, i.e. contain no octets.
+ * </blockquote>
+ * </p>
+ * <p>
+ * <b>8.7.3.2</b> Each encoding in the contents octets shall represent
+ * a segment of the overall octetstring, the encoding arising from
+ * a recursive application of this subclause.
+ * In this recursive application, each segment is treated as if it were
+ * a octetstring value. The encodings of the segments shall appear in the contents
+ * octets in the order in which their octets appear in the overall value.
+ * <blockquote>
+ * NOTE 1 &mdash; As a consequence of this recursion,
+ * each encoding in the contents octets may itself
+ * be primitive or constructed.
+ * However, such encodings will usually be primitive.
+ * </p><p>
+ * NOTE 2 &mdash; In particular, the tags in the contents octets are always universal class, number 4.
+ * </blockquote>
+ * </p>
+ * <p><b>9: Canonical encoding rules</b></p>
+ * <p><b>9.1 Length forms</b></p>
+ * <p>
+ * If the encoding is constructed, it shall employ the indefinite length form.
+ * If the encoding is primitive, it shall include the fewest length octets necessary.
+ * [Contrast with 8.1.3.2 b).]
+ * </p>
+ * <p><b>9.2 String encoding forms</b></p>
+ * <p>
+ * BIT STRING, OCTET STRING,and restricted character string
+ * values shall be encoded with a primitive encoding if they would
+ * require no more than 1000 contents octets, and as a constructed
+ * encoding otherwise. The string fragments contained in
+ * the constructed encoding shall be encoded with a primitive encoding.
+ * The encoding of each fragment, except possibly
+ * the last, shall have 1000 contents octets. (Contrast with 8.21.6.)
+ * </p>
+ * <b>10: Distinguished encoding rules</b>
+ * </p><p>
+ * <b>10.1 Length forms</b>
+ * The definite form of length encoding shall be used,
+ * encoded in the minimum number of octets.
+ * [Contrast with 8.1.3.2 b).]
+ * </p><p>
+ * <b>10.2 String encoding forms</b>
+ * For BIT STRING, OCTET STRING and restricted character string types,
+ * the constructed form of encoding shall not be used.
+ * (Contrast with 8.21.6.)
+ * </p>
+ */
+public abstract class ASN1OctetString
+ extends ASN1Primitive
+ implements ASN1OctetStringParser
+{
+ byte[] string;
+
+ /**
+ * return an Octet String from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static ASN1OctetString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof ASN1OctetString)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return BEROctetString.fromSequence(ASN1Sequence.getInstance(o));
+ }
+ }
+
+ /**
+ * return an Octet String from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static ASN1OctetString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1OctetString)
+ {
+ return (ASN1OctetString)obj;
+ }
+ else if (obj instanceof byte[])
+ {
+ try
+ {
+ return ASN1OctetString.getInstance(ASN1Primitive.fromByteArray((byte[])obj));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("failed to construct OCTET STRING from byte[]: " + e.getMessage());
+ }
+ }
+ else if (obj instanceof ASN1Encodable)
+ {
+ ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive();
+
+ if (primitive instanceof ASN1OctetString)
+ {
+ return (ASN1OctetString)primitive;
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * @param string the octets making up the octet string.
+ */
+ public ASN1OctetString(
+ byte[] string)
+ {
+ if (string == null)
+ {
+ throw new NullPointerException("string cannot be null");
+ }
+ this.string = string;
+ }
+
+ /**
+ * Return the content of the OCTET STRING as an InputStream.
+ *
+ * @return an InputStream representing the OCTET STRING's content.
+ */
+ public InputStream getOctetStream()
+ {
+ return new ByteArrayInputStream(string);
+ }
+
+ /**
+ * Return the parser associated with this object.
+ *
+ * @return a parser based on this OCTET STRING
+ */
+ public ASN1OctetStringParser parser()
+ {
+ return this;
+ }
+
+ /**
+ * Return the content of the OCTET STRING as a byte array.
+ *
+ * @return the byte[] representing the OCTET STRING's content.
+ */
+ public byte[] getOctets()
+ {
+ return string;
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(this.getOctets());
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1OctetString))
+ {
+ return false;
+ }
+
+ ASN1OctetString other = (ASN1OctetString)o;
+
+ return Arrays.areEqual(string, other.string);
+ }
+
+ public ASN1Primitive getLoadedObject()
+ {
+ return this.toASN1Primitive();
+ }
+
+ ASN1Primitive toDERObject()
+ {
+ return new DEROctetString(string);
+ }
+
+ ASN1Primitive toDLObject()
+ {
+ return new DEROctetString(string);
+ }
+
+ abstract void encode(ASN1OutputStream out)
+ throws IOException;
+
+ public String toString()
+ {
+ return "#"+new String(Hex.encode(string));
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1OctetStringParser.java b/core/src/main/java/org/spongycastle/asn1/ASN1OctetStringParser.java
new file mode 100644
index 00000000..f268b17f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1OctetStringParser.java
@@ -0,0 +1,17 @@
+package org.spongycastle.asn1;
+
+import java.io.InputStream;
+
+/**
+ * A basic parser for an OCTET STRING object
+ */
+public interface ASN1OctetStringParser
+ extends ASN1Encodable, InMemoryRepresentable
+{
+ /**
+ * Return the content of the OCTET STRING as an InputStream.
+ *
+ * @return an InputStream representing the OCTET STRING's content.
+ */
+ public InputStream getOctetStream();
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1OutputStream.java b/core/src/main/java/org/spongycastle/asn1/ASN1OutputStream.java
new file mode 100644
index 00000000..8e663ac1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1OutputStream.java
@@ -0,0 +1,194 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Stream that produces output based on the default encoding for the passed in objects.
+ */
+public class ASN1OutputStream
+{
+ private OutputStream os;
+
+ public ASN1OutputStream(
+ OutputStream os)
+ {
+ this.os = os;
+ }
+
+ void writeLength(
+ int length)
+ throws IOException
+ {
+ if (length > 127)
+ {
+ int size = 1;
+ int val = length;
+
+ while ((val >>>= 8) != 0)
+ {
+ size++;
+ }
+
+ write((byte)(size | 0x80));
+
+ for (int i = (size - 1) * 8; i >= 0; i -= 8)
+ {
+ write((byte)(length >> i));
+ }
+ }
+ else
+ {
+ write((byte)length);
+ }
+ }
+
+ void write(int b)
+ throws IOException
+ {
+ os.write(b);
+ }
+
+ void write(byte[] bytes)
+ throws IOException
+ {
+ os.write(bytes);
+ }
+
+ void write(byte[] bytes, int off, int len)
+ throws IOException
+ {
+ os.write(bytes, off, len);
+ }
+
+ void writeEncoded(
+ int tag,
+ byte[] bytes)
+ throws IOException
+ {
+ write(tag);
+ writeLength(bytes.length);
+ write(bytes);
+ }
+
+ void writeTag(int flags, int tagNo)
+ throws IOException
+ {
+ if (tagNo < 31)
+ {
+ write(flags | tagNo);
+ }
+ else
+ {
+ write(flags | 0x1f);
+ if (tagNo < 128)
+ {
+ write(tagNo);
+ }
+ else
+ {
+ byte[] stack = new byte[5];
+ int pos = stack.length;
+
+ stack[--pos] = (byte)(tagNo & 0x7F);
+
+ do
+ {
+ tagNo >>= 7;
+ stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
+ }
+ while (tagNo > 127);
+
+ write(stack, pos, stack.length - pos);
+ }
+ }
+ }
+
+ void writeEncoded(int flags, int tagNo, byte[] bytes)
+ throws IOException
+ {
+ writeTag(flags, tagNo);
+ writeLength(bytes.length);
+ write(bytes);
+ }
+
+ protected void writeNull()
+ throws IOException
+ {
+ os.write(BERTags.NULL);
+ os.write(0x00);
+ }
+
+ public void writeObject(
+ ASN1Encodable obj)
+ throws IOException
+ {
+ if (obj != null)
+ {
+ obj.toASN1Primitive().encode(this);
+ }
+ else
+ {
+ throw new IOException("null object detected");
+ }
+ }
+
+ void writeImplicitObject(ASN1Primitive obj)
+ throws IOException
+ {
+ if (obj != null)
+ {
+ obj.encode(new ImplicitOutputStream(os));
+ }
+ else
+ {
+ throw new IOException("null object detected");
+ }
+ }
+
+ public void close()
+ throws IOException
+ {
+ os.close();
+ }
+
+ public void flush()
+ throws IOException
+ {
+ os.flush();
+ }
+
+ ASN1OutputStream getDERSubStream()
+ {
+ return new DEROutputStream(os);
+ }
+
+ ASN1OutputStream getDLSubStream()
+ {
+ return new DLOutputStream(os);
+ }
+
+ private class ImplicitOutputStream
+ extends ASN1OutputStream
+ {
+ private boolean first = true;
+
+ public ImplicitOutputStream(OutputStream os)
+ {
+ super(os);
+ }
+
+ public void write(int b)
+ throws IOException
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ super.write(b);
+ }
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1ParsingException.java b/core/src/main/java/org/spongycastle/asn1/ASN1ParsingException.java
new file mode 100644
index 00000000..77e5cf21
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1ParsingException.java
@@ -0,0 +1,23 @@
+package org.spongycastle.asn1;
+
+public class ASN1ParsingException
+ extends IllegalStateException
+{
+ private Throwable cause;
+
+ public ASN1ParsingException(String message)
+ {
+ super(message);
+ }
+
+ public ASN1ParsingException(String message, Throwable cause)
+ {
+ super(message);
+ this.cause = cause;
+ }
+
+ public Throwable getCause()
+ {
+ return cause;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1Primitive.java b/core/src/main/java/org/spongycastle/asn1/ASN1Primitive.java
new file mode 100644
index 00000000..dd626887
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1Primitive.java
@@ -0,0 +1,82 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * Base class for ASN.1 primitive objects. These are the actual objects used to generate byte encodings.
+ */
+public abstract class ASN1Primitive
+ extends ASN1Object
+{
+ ASN1Primitive()
+ {
+
+ }
+
+ /**
+ * Create a base ASN.1 object from a byte stream.
+ *
+ * @param data the byte stream to parse.
+ * @return the base ASN.1 object represented by the byte stream.
+ * @exception IOException if there is a problem parsing the data.
+ */
+ public static ASN1Primitive fromByteArray(byte[] data)
+ throws IOException
+ {
+ ASN1InputStream aIn = new ASN1InputStream(data);
+
+ try
+ {
+ return aIn.readObject();
+ }
+ catch (ClassCastException e)
+ {
+ throw new IOException("cannot recognise object in stream");
+ }
+ }
+
+ public final boolean equals(Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+
+ return (o instanceof ASN1Encodable) && asn1Equals(((ASN1Encodable)o).toASN1Primitive());
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return this;
+ }
+
+ /**
+ * Return the current object as one which encodes using Distinguished Encoding Rules.
+ *
+ * @return a DER version of this.
+ */
+ ASN1Primitive toDERObject()
+ {
+ return this;
+ }
+
+ /**
+ * Return the current object as one which encodes using Definite Length encoding.
+ *
+ * @return a DL version of this.
+ */
+ ASN1Primitive toDLObject()
+ {
+ return this;
+ }
+
+ public abstract int hashCode();
+
+ abstract boolean isConstructed();
+
+ abstract int encodedLength() throws IOException;
+
+ abstract void encode(ASN1OutputStream out) throws IOException;
+
+ abstract boolean asn1Equals(ASN1Primitive o);
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1Sequence.java b/core/src/main/java/org/spongycastle/asn1/ASN1Sequence.java
new file mode 100644
index 00000000..1de4e315
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1Sequence.java
@@ -0,0 +1,382 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+/**
+ * ASN.1 <code>SEQUENCE</code> and <code>SEQUENCE OF</code> constructs.
+ * <p>
+ * DER form is always definite form length fields, while
+ * BER support uses indefinite form.
+ * <hr>
+ * <p><b>X.690</b></p>
+ * <p><b>8: Basic encoding rules</b></p>
+ * <p><b>8.9 Encoding of a sequence value </b></p>
+ * 8.9.1 The encoding of a sequence value shall be constructed.
+ * <p>
+ * <b>8.9.2</b> The contents octets shall consist of the complete
+ * encoding of one data value from each of the types listed in
+ * the ASN.1 definition of the sequence type, in the order of
+ * their appearance in the definition, unless the type was referenced
+ * with the keyword <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
+ * </p><p>
+ * <b>8.9.3</b> The encoding of a data value may, but need not,
+ * be present for a type which was referenced with the keyword
+ * <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
+ * If present, it shall appear in the encoding at the point
+ * corresponding to the appearance of the type in the ASN.1 definition.
+ * </p><p>
+ * <b>8.10 Encoding of a sequence-of value </b>
+ * </p><p>
+ * <b>8.10.1</b> The encoding of a sequence-of value shall be constructed.
+ * <p>
+ * <b>8.10.2</b> The contents octets shall consist of zero,
+ * one or more complete encodings of data values from the type listed in
+ * the ASN.1 definition.
+ * <p>
+ * <b>8.10.3</b> The order of the encodings of the data values shall be
+ * the same as the order of the data values in the sequence-of value to
+ * be encoded.
+ * </p>
+ * <p><b>9: Canonical encoding rules</b></p>
+ * <p><b>9.1 Length forms</b></p>
+ * If the encoding is constructed, it shall employ the indefinite length form.
+ * If the encoding is primitive, it shall include the fewest length octets necessary.
+ * [Contrast with 8.1.3.2 b).]
+ *
+ * <p><b>11: Restrictions on BER employed by both CER and DER</b></p>
+ * <p><b>11.5 Set and sequence components with default value</b></p>
+ * The encoding of a set value or sequence value shall not include
+ * an encoding for any component value which is equal to
+ * its default value.
+ */
+public abstract class ASN1Sequence
+ extends ASN1Primitive
+{
+ protected Vector seq = new Vector();
+
+ /**
+ * Return an ASN1Sequence from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ * @return an ASN1Sequence instance, or null.
+ */
+ public static ASN1Sequence getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1Sequence)
+ {
+ return (ASN1Sequence)obj;
+ }
+ else if (obj instanceof ASN1SequenceParser)
+ {
+ return ASN1Sequence.getInstance(((ASN1SequenceParser)obj).toASN1Primitive());
+ }
+ else if (obj instanceof byte[])
+ {
+ try
+ {
+ return ASN1Sequence.getInstance(fromByteArray((byte[])obj));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("failed to construct sequence from byte[]: " + e.getMessage());
+ }
+ }
+ else if (obj instanceof ASN1Encodable)
+ {
+ ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive();
+
+ if (primitive instanceof ASN1Sequence)
+ {
+ return (ASN1Sequence)primitive;
+ }
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * Return an ASN1 sequence from a tagged object. There is a special
+ * case here, if an object appears to have been explicitly tagged on
+ * reading but we were expecting it to be implicitly tagged in the
+ * normal course of events it indicates that we lost the surrounding
+ * sequence - so we need to add it back (this will happen if the tagged
+ * object is a sequence that contains other sequences). If you are
+ * dealing with implicitly tagged sequences you really <b>should</b>
+ * be using this method.
+ *
+ * @param obj the tagged object.
+ * @param explicit true if the object is meant to be explicitly tagged,
+ * false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ * @return an ASN1Sequence instance.
+ */
+ public static ASN1Sequence getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ if (explicit)
+ {
+ if (!obj.isExplicit())
+ {
+ throw new IllegalArgumentException("object implicit - explicit expected.");
+ }
+
+ return ASN1Sequence.getInstance(obj.getObject().toASN1Primitive());
+ }
+ else
+ {
+ //
+ // constructed object which appears to be explicitly tagged
+ // when it should be implicit means we have to add the
+ // surrounding sequence.
+ //
+ if (obj.isExplicit())
+ {
+ if (obj instanceof BERTaggedObject)
+ {
+ return new BERSequence(obj.getObject());
+ }
+ else
+ {
+ return new DLSequence(obj.getObject());
+ }
+ }
+ else
+ {
+ if (obj.getObject() instanceof ASN1Sequence)
+ {
+ return (ASN1Sequence)obj.getObject();
+ }
+ }
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * Create an empty sequence
+ */
+ protected ASN1Sequence()
+ {
+ }
+
+ /**
+ * Create a sequence containing one object
+ * @param obj the object to be put in the SEQUENCE.
+ */
+ protected ASN1Sequence(
+ ASN1Encodable obj)
+ {
+ seq.addElement(obj);
+ }
+
+ /**
+ * Create a sequence containing a vector of objects.
+ * @param v the vector of objects to be put in the SEQUENCE
+ */
+ protected ASN1Sequence(
+ ASN1EncodableVector v)
+ {
+ for (int i = 0; i != v.size(); i++)
+ {
+ seq.addElement(v.get(i));
+ }
+ }
+
+ /**
+ * Create a sequence containing a vector of objects.
+ */
+ protected ASN1Sequence(
+ ASN1Encodable[] array)
+ {
+ for (int i = 0; i != array.length; i++)
+ {
+ seq.addElement(array[i]);
+ }
+ }
+
+ public ASN1Encodable[] toArray()
+ {
+ ASN1Encodable[] values = new ASN1Encodable[this.size()];
+
+ for (int i = 0; i != this.size(); i++)
+ {
+ values[i] = this.getObjectAt(i);
+ }
+
+ return values;
+ }
+
+ public Enumeration getObjects()
+ {
+ return seq.elements();
+ }
+
+ public ASN1SequenceParser parser()
+ {
+ final ASN1Sequence outer = this;
+
+ return new ASN1SequenceParser()
+ {
+ private final int max = size();
+
+ private int index;
+
+ public ASN1Encodable readObject() throws IOException
+ {
+ if (index == max)
+ {
+ return null;
+ }
+
+ ASN1Encodable obj = getObjectAt(index++);
+ if (obj instanceof ASN1Sequence)
+ {
+ return ((ASN1Sequence)obj).parser();
+ }
+ if (obj instanceof ASN1Set)
+ {
+ return ((ASN1Set)obj).parser();
+ }
+
+ return obj;
+ }
+
+ public ASN1Primitive getLoadedObject()
+ {
+ return outer;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return outer;
+ }
+ };
+ }
+
+ /**
+ * Return the object at the sequence position indicated by index.
+ *
+ * @param index the sequence number (starting at zero) of the object
+ * @return the object at the sequence position indicated by index.
+ */
+ public ASN1Encodable getObjectAt(
+ int index)
+ {
+ return (ASN1Encodable)seq.elementAt(index);
+ }
+
+ /**
+ * Return the number of objects in this sequence.
+ *
+ * @return the number of objects in this sequence.
+ */
+ public int size()
+ {
+ return seq.size();
+ }
+
+ public int hashCode()
+ {
+ Enumeration e = this.getObjects();
+ int hashCode = size();
+
+ while (e.hasMoreElements())
+ {
+ Object o = getNext(e);
+ hashCode *= 17;
+
+ hashCode ^= o.hashCode();
+ }
+
+ return hashCode;
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1Sequence))
+ {
+ return false;
+ }
+
+ ASN1Sequence other = (ASN1Sequence)o;
+
+ if (this.size() != other.size())
+ {
+ return false;
+ }
+
+ Enumeration s1 = this.getObjects();
+ Enumeration s2 = other.getObjects();
+
+ while (s1.hasMoreElements())
+ {
+ ASN1Encodable obj1 = getNext(s1);
+ ASN1Encodable obj2 = getNext(s2);
+
+ ASN1Primitive o1 = obj1.toASN1Primitive();
+ ASN1Primitive o2 = obj2.toASN1Primitive();
+
+ if (o1 == o2 || o1.equals(o2))
+ {
+ continue;
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ private ASN1Encodable getNext(Enumeration e)
+ {
+ ASN1Encodable encObj = (ASN1Encodable)e.nextElement();
+
+ return encObj;
+ }
+
+ /**
+ * Change current SEQUENCE object to be encoded as {@link DERSequence}.
+ * This is part of Distinguished Encoding Rules form serialization.
+ */
+ ASN1Primitive toDERObject()
+ {
+ ASN1Sequence derSeq = new DERSequence();
+
+ derSeq.seq = this.seq;
+
+ return derSeq;
+ }
+
+ /**
+ * Change current SEQUENCE object to be encoded as {@link DLSequence}.
+ * This is part of Direct Length form serialization.
+ */
+ ASN1Primitive toDLObject()
+ {
+ ASN1Sequence dlSeq = new DLSequence();
+
+ dlSeq.seq = this.seq;
+
+ return dlSeq;
+ }
+
+ boolean isConstructed()
+ {
+ return true;
+ }
+
+ abstract void encode(ASN1OutputStream out)
+ throws IOException;
+
+ public String toString()
+ {
+ return seq.toString();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1SequenceParser.java b/core/src/main/java/org/spongycastle/asn1/ASN1SequenceParser.java
new file mode 100644
index 00000000..2997acdc
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1SequenceParser.java
@@ -0,0 +1,19 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * A basic parser for a SEQUENCE object
+ */
+public interface ASN1SequenceParser
+ extends ASN1Encodable, InMemoryRepresentable
+{
+ /**
+ * Read the next object from the underlying object representing a SEQUENCE.
+ *
+ * @throws IOException for bad input stream.
+ * @return the next object, null if we are at the end.
+ */
+ ASN1Encodable readObject()
+ throws IOException;
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1Set.java b/core/src/main/java/org/spongycastle/asn1/ASN1Set.java
new file mode 100644
index 00000000..0bc92547
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1Set.java
@@ -0,0 +1,560 @@
+package org.spongycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+/**
+ * ASN.1 <code>SET</code> and <code>SET OF</code> constructs.
+ * <p>
+ * Note: This does not know which syntax the set is!
+ * (The difference: ordering of SET elements or not ordering.)
+ * <p>
+ * DER form is always definite form length fields, while
+ * BER support uses indefinite form.
+ * <p>
+ * The CER form support does not exist.
+ * <p>
+ * <hr>
+ * <h2>X.690</h2>
+ * <h3>8: Basic encoding rules</h3>
+ * <h4>8.11 Encoding of a set value </h4>
+ * <b>8.11.1</b> The encoding of a set value shall be constructed
+ * <p>
+ * <b>8.11.2</b> The contents octets shall consist of the complete
+ * encoding of a data value from each of the types listed in the
+ * ASN.1 definition of the set type, in an order chosen by the sender,
+ * unless the type was referenced with the keyword
+ * <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
+ * <p>
+ * <b>8.11.3</b> The encoding of a data value may, but need not,
+ * be present for a type which was referenced with the keyword
+ * <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
+ * <blockquote>
+ * NOTE &mdash; The order of data values in a set value is not significant,
+ * and places no constraints on the order during transfer
+ * </blockquote>
+ * <h4>8.12 Encoding of a set-of value</h4>
+ * <b>8.12.1</b> The encoding of a set-of value shall be constructed.
+ * <p>
+ * <b>8.12.2</b> The text of 8.10.2 applies:
+ * <i>The contents octets shall consist of zero,
+ * one or more complete encodings of data values from the type listed in
+ * the ASN.1 definition.</i>
+ * <p>
+ * <b>8.12.3</b> The order of data values need not be preserved by
+ * the encoding and subsequent decoding.
+ *
+ * <h3>9: Canonical encoding rules</h3>
+ * <h4>9.1 Length forms</h4>
+ * If the encoding is constructed, it shall employ the indefinite length form.
+ * If the encoding is primitive, it shall include the fewest length octets necessary.
+ * [Contrast with 8.1.3.2 b).]
+ * <h4>9.3 Set components</h4>
+ * The encodings of the component values of a set value shall
+ * appear in an order determined by their tags as specified
+ * in 8.6 of ITU-T Rec. X.680 | ISO/IEC 8824-1.
+ * Additionally, for the purposes of determining the order in which
+ * components are encoded when one or more component is an untagged
+ * choice type, each untagged choice type is ordered as though it
+ * has a tag equal to that of the smallest tag in that choice type
+ * or any untagged choice types nested within.
+ *
+ * <h3>10: Distinguished encoding rules</h3>
+ * <h4>10.1 Length forms</h4>
+ * The definite form of length encoding shall be used,
+ * encoded in the minimum number of octets.
+ * [Contrast with 8.1.3.2 b).]
+ * <h4>10.3 Set components</h4>
+ * The encodings of the component values of a set value shall appear
+ * in an order determined by their tags as specified
+ * in 8.6 of ITU-T Rec. X.680 | ISO/IEC 8824-1.
+ * <blockquote>
+ * NOTE &mdash; Where a component of the set is an untagged choice type,
+ * the location of that component in the ordering will depend on
+ * the tag of the choice component being encoded.
+ * </blockquote>
+ *
+ * <h3>11: Restrictions on BER employed by both CER and DER</h3>
+ * <h4>11.5 Set and sequence components with default value </h4>
+ * The encoding of a set value or sequence value shall not include
+ * an encoding for any component value which is equal to
+ * its default value.
+ * <h4>11.6 Set-of components </h4>
+ * <p>
+ * The encodings of the component values of a set-of value
+ * shall appear in ascending order, the encodings being compared
+ * as octet strings with the shorter components being padded at
+ * their trailing end with 0-octets.
+ * <blockquote>
+ * NOTE &mdash; The padding octets are for comparison purposes only
+ * and do not appear in the encodings.
+ * </blockquote>
+ */
+public abstract class ASN1Set
+ extends ASN1Primitive
+{
+ private Vector set = new Vector();
+ private boolean isSorted = false;
+
+ /**
+ * return an ASN1Set from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ * @return an ASN1Set instance, or null.
+ */
+ public static ASN1Set getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1Set)
+ {
+ return (ASN1Set)obj;
+ }
+ else if (obj instanceof ASN1SetParser)
+ {
+ return ASN1Set.getInstance(((ASN1SetParser)obj).toASN1Primitive());
+ }
+ else if (obj instanceof byte[])
+ {
+ try
+ {
+ return ASN1Set.getInstance(ASN1Primitive.fromByteArray((byte[])obj));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("failed to construct set from byte[]: " + e.getMessage());
+ }
+ }
+ else if (obj instanceof ASN1Encodable)
+ {
+ ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive();
+
+ if (primitive instanceof ASN1Set)
+ {
+ return (ASN1Set)primitive;
+ }
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * Return an ASN1 set from a tagged object. There is a special
+ * case here, if an object appears to have been explicitly tagged on
+ * reading but we were expecting it to be implicitly tagged in the
+ * normal course of events it indicates that we lost the surrounding
+ * set - so we need to add it back (this will happen if the tagged
+ * object is a sequence that contains other sequences). If you are
+ * dealing with implicitly tagged sets you really <b>should</b>
+ * be using this method.
+ *
+ * @param obj the tagged object.
+ * @param explicit true if the object is meant to be explicitly tagged
+ * false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ * @return an ASN1Set instance.
+ */
+ public static ASN1Set getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ if (explicit)
+ {
+ if (!obj.isExplicit())
+ {
+ throw new IllegalArgumentException("object implicit - explicit expected.");
+ }
+
+ return (ASN1Set)obj.getObject();
+ }
+ else
+ {
+ //
+ // constructed object which appears to be explicitly tagged
+ // and it's really implicit means we have to add the
+ // surrounding set.
+ //
+ if (obj.isExplicit())
+ {
+ if (obj instanceof BERTaggedObject)
+ {
+ return new BERSet(obj.getObject());
+ }
+ else
+ {
+ return new DLSet(obj.getObject());
+ }
+ }
+ else
+ {
+ if (obj.getObject() instanceof ASN1Set)
+ {
+ return (ASN1Set)obj.getObject();
+ }
+
+ //
+ // in this case the parser returns a sequence, convert it
+ // into a set.
+ //
+ if (obj.getObject() instanceof ASN1Sequence)
+ {
+ ASN1Sequence s = (ASN1Sequence)obj.getObject();
+
+ if (obj instanceof BERTaggedObject)
+ {
+ return new BERSet(s.toArray());
+ }
+ else
+ {
+ return new DLSet(s.toArray());
+ }
+ }
+ }
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
+ }
+
+ protected ASN1Set()
+ {
+ }
+
+ /**
+ * create a sequence containing one object
+ * @param obj object to be added to the SET.
+ */
+ protected ASN1Set(
+ ASN1Encodable obj)
+ {
+ set.addElement(obj);
+ }
+
+ /**
+ * create a sequence containing a vector of objects.
+ * @param v a vector of objects to make up the SET.
+ * @param doSort true if should be sorted DER style, false otherwise.
+ */
+ protected ASN1Set(
+ ASN1EncodableVector v,
+ boolean doSort)
+ {
+ for (int i = 0; i != v.size(); i++)
+ {
+ set.addElement(v.get(i));
+ }
+
+ if (doSort)
+ {
+ this.sort();
+ }
+ }
+
+ /**
+ * create a sequence containing a vector of objects.
+ */
+ protected ASN1Set(
+ ASN1Encodable[] array,
+ boolean doSort)
+ {
+ for (int i = 0; i != array.length; i++)
+ {
+ set.addElement(array[i]);
+ }
+
+ if (doSort)
+ {
+ this.sort();
+ }
+ }
+
+ public Enumeration getObjects()
+ {
+ return set.elements();
+ }
+
+ /**
+ * return the object at the set position indicated by index.
+ *
+ * @param index the set number (starting at zero) of the object
+ * @return the object at the set position indicated by index.
+ */
+ public ASN1Encodable getObjectAt(
+ int index)
+ {
+ return (ASN1Encodable)set.elementAt(index);
+ }
+
+ /**
+ * return the number of objects in this set.
+ *
+ * @return the number of objects in this set.
+ */
+ public int size()
+ {
+ return set.size();
+ }
+
+ public ASN1Encodable[] toArray()
+ {
+ ASN1Encodable[] values = new ASN1Encodable[this.size()];
+
+ for (int i = 0; i != this.size(); i++)
+ {
+ values[i] = this.getObjectAt(i);
+ }
+
+ return values;
+ }
+
+ public ASN1SetParser parser()
+ {
+ final ASN1Set outer = this;
+
+ return new ASN1SetParser()
+ {
+ private final int max = size();
+
+ private int index;
+
+ public ASN1Encodable readObject() throws IOException
+ {
+ if (index == max)
+ {
+ return null;
+ }
+
+ ASN1Encodable obj = getObjectAt(index++);
+ if (obj instanceof ASN1Sequence)
+ {
+ return ((ASN1Sequence)obj).parser();
+ }
+ if (obj instanceof ASN1Set)
+ {
+ return ((ASN1Set)obj).parser();
+ }
+
+ return obj;
+ }
+
+ public ASN1Primitive getLoadedObject()
+ {
+ return outer;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return outer;
+ }
+ };
+ }
+
+ public int hashCode()
+ {
+ Enumeration e = this.getObjects();
+ int hashCode = size();
+
+ while (e.hasMoreElements())
+ {
+ Object o = getNext(e);
+ hashCode *= 17;
+
+ hashCode ^= o.hashCode();
+ }
+
+ return hashCode;
+ }
+
+ /**
+ * Change current SET object to be encoded as {@link DERSet}.
+ * This is part of Distinguished Encoding Rules form serialization.
+ */
+ ASN1Primitive toDERObject()
+ {
+ if (isSorted)
+ {
+ ASN1Set derSet = new DERSet();
+
+ derSet.set = this.set;
+
+ return derSet;
+ }
+ else
+ {
+ Vector v = new Vector();
+
+ for (int i = 0; i != set.size(); i++)
+ {
+ v.addElement(set.elementAt(i));
+ }
+
+ ASN1Set derSet = new DERSet();
+
+ derSet.set = v;
+
+ derSet.sort();
+
+ return derSet;
+ }
+ }
+
+ /**
+ * Change current SET object to be encoded as {@link DLSet}.
+ * This is part of Direct Length form serialization.
+ */
+ ASN1Primitive toDLObject()
+ {
+ ASN1Set derSet = new DLSet();
+
+ derSet.set = this.set;
+
+ return derSet;
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1Set))
+ {
+ return false;
+ }
+
+ ASN1Set other = (ASN1Set)o;
+
+ if (this.size() != other.size())
+ {
+ return false;
+ }
+
+ Enumeration s1 = this.getObjects();
+ Enumeration s2 = other.getObjects();
+
+ while (s1.hasMoreElements())
+ {
+ ASN1Encodable obj1 = getNext(s1);
+ ASN1Encodable obj2 = getNext(s2);
+
+ ASN1Primitive o1 = obj1.toASN1Primitive();
+ ASN1Primitive o2 = obj2.toASN1Primitive();
+
+ if (o1 == o2 || o1.equals(o2))
+ {
+ continue;
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ private ASN1Encodable getNext(Enumeration e)
+ {
+ ASN1Encodable encObj = (ASN1Encodable)e.nextElement();
+
+ // unfortunately null was allowed as a substitute for DER null
+ if (encObj == null)
+ {
+ return DERNull.INSTANCE;
+ }
+
+ return encObj;
+ }
+
+ /**
+ * return true if a <= b (arrays are assumed padded with zeros).
+ */
+ private boolean lessThanOrEqual(
+ byte[] a,
+ byte[] b)
+ {
+ int len = Math.min(a.length, b.length);
+ for (int i = 0; i != len; ++i)
+ {
+ if (a[i] != b[i])
+ {
+ return (a[i] & 0xff) < (b[i] & 0xff);
+ }
+ }
+ return len == a.length;
+ }
+
+ private byte[] getEncoded(
+ ASN1Encodable obj)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ try
+ {
+ aOut.writeObject(obj);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("cannot encode object added to SET");
+ }
+
+ return bOut.toByteArray();
+ }
+
+ protected void sort()
+ {
+ if (!isSorted)
+ {
+ isSorted = true;
+ if (set.size() > 1)
+ {
+ boolean swapped = true;
+ int lastSwap = set.size() - 1;
+
+ while (swapped)
+ {
+ int index = 0;
+ int swapIndex = 0;
+ byte[] a = getEncoded((ASN1Encodable)set.elementAt(0));
+
+ swapped = false;
+
+ while (index != lastSwap)
+ {
+ byte[] b = getEncoded((ASN1Encodable)set.elementAt(index + 1));
+
+ if (lessThanOrEqual(a, b))
+ {
+ a = b;
+ }
+ else
+ {
+ Object o = set.elementAt(index);
+
+ set.setElementAt(set.elementAt(index + 1), index);
+ set.setElementAt(o, index + 1);
+
+ swapped = true;
+ swapIndex = index;
+ }
+
+ index++;
+ }
+
+ lastSwap = swapIndex;
+ }
+ }
+ }
+ }
+
+ boolean isConstructed()
+ {
+ return true;
+ }
+
+ abstract void encode(ASN1OutputStream out)
+ throws IOException;
+
+ public String toString()
+ {
+ return set.toString();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1SetParser.java b/core/src/main/java/org/spongycastle/asn1/ASN1SetParser.java
new file mode 100644
index 00000000..649e968a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1SetParser.java
@@ -0,0 +1,19 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * A basic parser for a SET object
+ */
+public interface ASN1SetParser
+ extends ASN1Encodable, InMemoryRepresentable
+{
+ /**
+ * Read the next object from the underlying object representing a SET.
+ *
+ * @throws IOException for bad input stream.
+ * @return the next object, null if we are at the end.
+ */
+ public ASN1Encodable readObject()
+ throws IOException;
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1StreamParser.java b/core/src/main/java/org/spongycastle/asn1/ASN1StreamParser.java
new file mode 100644
index 00000000..e5875b52
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1StreamParser.java
@@ -0,0 +1,250 @@
+package org.spongycastle.asn1;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A parser for ASN.1 streams which also returns, where possible, parsers for the objects it encounters.
+ */
+public class ASN1StreamParser
+{
+ private final InputStream _in;
+ private final int _limit;
+ private final byte[][] tmpBuffers;
+
+ public ASN1StreamParser(
+ InputStream in)
+ {
+ this(in, StreamUtil.findLimit(in));
+ }
+
+ public ASN1StreamParser(
+ InputStream in,
+ int limit)
+ {
+ this._in = in;
+ this._limit = limit;
+
+ this.tmpBuffers = new byte[11][];
+ }
+
+ public ASN1StreamParser(
+ byte[] encoding)
+ {
+ this(new ByteArrayInputStream(encoding), encoding.length);
+ }
+
+ ASN1Encodable readIndef(int tagValue) throws IOException
+ {
+ // Note: INDEF => CONSTRUCTED
+
+ // TODO There are other tags that may be constructed (e.g. BIT_STRING)
+ switch (tagValue)
+ {
+ case BERTags.EXTERNAL:
+ return new DERExternalParser(this);
+ case BERTags.OCTET_STRING:
+ return new BEROctetStringParser(this);
+ case BERTags.SEQUENCE:
+ return new BERSequenceParser(this);
+ case BERTags.SET:
+ return new BERSetParser(this);
+ default:
+ throw new ASN1Exception("unknown BER object encountered: 0x" + Integer.toHexString(tagValue));
+ }
+ }
+
+ ASN1Encodable readImplicit(boolean constructed, int tag) throws IOException
+ {
+ if (_in instanceof IndefiniteLengthInputStream)
+ {
+ if (!constructed)
+ {
+ throw new IOException("indefinite length primitive encoding encountered");
+ }
+
+ return readIndef(tag);
+ }
+
+ if (constructed)
+ {
+ switch (tag)
+ {
+ case BERTags.SET:
+ return new DERSetParser(this);
+ case BERTags.SEQUENCE:
+ return new DERSequenceParser(this);
+ case BERTags.OCTET_STRING:
+ return new BEROctetStringParser(this);
+ }
+ }
+ else
+ {
+ switch (tag)
+ {
+ case BERTags.SET:
+ throw new ASN1Exception("sequences must use constructed encoding (see X.690 8.9.1/8.10.1)");
+ case BERTags.SEQUENCE:
+ throw new ASN1Exception("sets must use constructed encoding (see X.690 8.11.1/8.12.1)");
+ case BERTags.OCTET_STRING:
+ return new DEROctetStringParser((DefiniteLengthInputStream)_in);
+ }
+ }
+
+ // TODO ASN1Exception
+ throw new RuntimeException("implicit tagging not implemented");
+ }
+
+ ASN1Primitive readTaggedObject(boolean constructed, int tag) throws IOException
+ {
+ if (!constructed)
+ {
+ // Note: !CONSTRUCTED => IMPLICIT
+ DefiniteLengthInputStream defIn = (DefiniteLengthInputStream)_in;
+ return new DERTaggedObject(false, tag, new DEROctetString(defIn.toByteArray()));
+ }
+
+ ASN1EncodableVector v = readVector();
+
+ if (_in instanceof IndefiniteLengthInputStream)
+ {
+ return v.size() == 1
+ ? new BERTaggedObject(true, tag, v.get(0))
+ : new BERTaggedObject(false, tag, BERFactory.createSequence(v));
+ }
+
+ return v.size() == 1
+ ? new DERTaggedObject(true, tag, v.get(0))
+ : new DERTaggedObject(false, tag, DERFactory.createSequence(v));
+ }
+
+ public ASN1Encodable readObject()
+ throws IOException
+ {
+ int tag = _in.read();
+ if (tag == -1)
+ {
+ return null;
+ }
+
+ //
+ // turn of looking for "00" while we resolve the tag
+ //
+ set00Check(false);
+
+ //
+ // calculate tag number
+ //
+ int tagNo = ASN1InputStream.readTagNumber(_in, tag);
+
+ boolean isConstructed = (tag & BERTags.CONSTRUCTED) != 0;
+
+ //
+ // calculate length
+ //
+ int length = ASN1InputStream.readLength(_in, _limit);
+
+ if (length < 0) // indefinite length method
+ {
+ if (!isConstructed)
+ {
+ throw new IOException("indefinite length primitive encoding encountered");
+ }
+
+ IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in, _limit);
+ ASN1StreamParser sp = new ASN1StreamParser(indIn, _limit);
+
+ if ((tag & BERTags.APPLICATION) != 0)
+ {
+ return new BERApplicationSpecificParser(tagNo, sp);
+ }
+
+ if ((tag & BERTags.TAGGED) != 0)
+ {
+ return new BERTaggedObjectParser(true, tagNo, sp);
+ }
+
+ return sp.readIndef(tagNo);
+ }
+ else
+ {
+ DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length);
+
+ if ((tag & BERTags.APPLICATION) != 0)
+ {
+ return new DERApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
+ }
+
+ if ((tag & BERTags.TAGGED) != 0)
+ {
+ return new BERTaggedObjectParser(isConstructed, tagNo, new ASN1StreamParser(defIn));
+ }
+
+ if (isConstructed)
+ {
+ // TODO There are other tags that may be constructed (e.g. BIT_STRING)
+ switch (tagNo)
+ {
+ case BERTags.OCTET_STRING:
+ //
+ // yes, people actually do this...
+ //
+ return new BEROctetStringParser(new ASN1StreamParser(defIn));
+ case BERTags.SEQUENCE:
+ return new DERSequenceParser(new ASN1StreamParser(defIn));
+ case BERTags.SET:
+ return new DERSetParser(new ASN1StreamParser(defIn));
+ case BERTags.EXTERNAL:
+ return new DERExternalParser(new ASN1StreamParser(defIn));
+ default:
+ throw new IOException("unknown tag " + tagNo + " encountered");
+ }
+ }
+
+ // Some primitive encodings can be handled by parsers too...
+ switch (tagNo)
+ {
+ case BERTags.OCTET_STRING:
+ return new DEROctetStringParser(defIn);
+ }
+
+ try
+ {
+ return ASN1InputStream.createPrimitiveDERObject(tagNo, defIn, tmpBuffers);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new ASN1Exception("corrupted stream detected", e);
+ }
+ }
+ }
+
+ private void set00Check(boolean enabled)
+ {
+ if (_in instanceof IndefiniteLengthInputStream)
+ {
+ ((IndefiniteLengthInputStream)_in).setEofOn00(enabled);
+ }
+ }
+
+ ASN1EncodableVector readVector() throws IOException
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ ASN1Encodable obj;
+ while ((obj = readObject()) != null)
+ {
+ if (obj instanceof InMemoryRepresentable)
+ {
+ v.add(((InMemoryRepresentable)obj).getLoadedObject());
+ }
+ else
+ {
+ v.add(obj.toASN1Primitive());
+ }
+ }
+
+ return v;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1String.java b/core/src/main/java/org/spongycastle/asn1/ASN1String.java
new file mode 100644
index 00000000..84166d40
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1String.java
@@ -0,0 +1,6 @@
+package org.spongycastle.asn1;
+
+public interface ASN1String
+{
+ public String getString();
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1TaggedObject.java b/core/src/main/java/org/spongycastle/asn1/ASN1TaggedObject.java
new file mode 100644
index 00000000..af778816
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1TaggedObject.java
@@ -0,0 +1,236 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * ASN.1 TaggedObject - in ASN.1 notation this is any object preceded by
+ * a [n] where n is some number - these are assumed to follow the construction
+ * rules (as with sequences).
+ */
+public abstract class ASN1TaggedObject
+ extends ASN1Primitive
+ implements ASN1TaggedObjectParser
+{
+ int tagNo;
+ boolean empty = false;
+ boolean explicit = true;
+ ASN1Encodable obj = null;
+
+ static public ASN1TaggedObject getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ if (explicit)
+ {
+ return (ASN1TaggedObject)obj.getObject();
+ }
+
+ throw new IllegalArgumentException("implicitly tagged tagged object");
+ }
+
+ static public ASN1TaggedObject getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1TaggedObject)
+ {
+ return (ASN1TaggedObject)obj;
+ }
+ else if (obj instanceof byte[])
+ {
+ try
+ {
+ return ASN1TaggedObject.getInstance(fromByteArray((byte[])obj));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("failed to construct tagged object from byte[]: " + e.getMessage());
+ }
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * Create a tagged object with the style given by the value of explicit.
+ * <p>
+ * If the object implements ASN1Choice the tag style will always be changed
+ * to explicit in accordance with the ASN.1 encoding rules.
+ * </p>
+ * @param explicit true if the object is explicitly tagged.
+ * @param tagNo the tag number for this object.
+ * @param obj the tagged object.
+ */
+ public ASN1TaggedObject(
+ boolean explicit,
+ int tagNo,
+ ASN1Encodable obj)
+ {
+ if (obj instanceof ASN1Choice)
+ {
+ this.explicit = true;
+ }
+ else
+ {
+ this.explicit = explicit;
+ }
+
+ this.tagNo = tagNo;
+
+ if (this.explicit)
+ {
+ this.obj = obj;
+ }
+ else
+ {
+ ASN1Primitive prim = obj.toASN1Primitive();
+
+ if (prim instanceof ASN1Set)
+ {
+ ASN1Set s = null;
+ }
+
+ this.obj = obj;
+ }
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1TaggedObject))
+ {
+ return false;
+ }
+
+ ASN1TaggedObject other = (ASN1TaggedObject)o;
+
+ if (tagNo != other.tagNo || empty != other.empty || explicit != other.explicit)
+ {
+ return false;
+ }
+
+ if(obj == null)
+ {
+ if (other.obj != null)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (!(obj.toASN1Primitive().equals(other.obj.toASN1Primitive())))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public int hashCode()
+ {
+ int code = tagNo;
+
+ // TODO: actually this is wrong - the problem is that a re-encoded
+ // object may end up with a different hashCode due to implicit
+ // tagging. As implicit tagging is ambiguous if a sequence is involved
+ // it seems the only correct method for both equals and hashCode is to
+ // compare the encodings...
+ if (obj != null)
+ {
+ code ^= obj.hashCode();
+ }
+
+ return code;
+ }
+
+ public int getTagNo()
+ {
+ return tagNo;
+ }
+
+ /**
+ * return whether or not the object may be explicitly tagged.
+ * <p>
+ * Note: if the object has been read from an input stream, the only
+ * time you can be sure if isExplicit is returning the true state of
+ * affairs is if it returns false. An implicitly tagged object may appear
+ * to be explicitly tagged, so you need to understand the context under
+ * which the reading was done as well, see getObject below.
+ */
+ public boolean isExplicit()
+ {
+ return explicit;
+ }
+
+ public boolean isEmpty()
+ {
+ return empty;
+ }
+
+ /**
+ * return whatever was following the tag.
+ * <p>
+ * Note: tagged objects are generally context dependent if you're
+ * trying to extract a tagged object you should be going via the
+ * appropriate getInstance method.
+ */
+ public ASN1Primitive getObject()
+ {
+ if (obj != null)
+ {
+ return obj.toASN1Primitive();
+ }
+
+ return null;
+ }
+
+ /**
+ * Return the object held in this tagged object as a parser assuming it has
+ * the type of the passed in tag. If the object doesn't have a parser
+ * associated with it, the base object is returned.
+ */
+ public ASN1Encodable getObjectParser(
+ int tag,
+ boolean isExplicit)
+ {
+ switch (tag)
+ {
+ case BERTags.SET:
+ return ASN1Set.getInstance(this, isExplicit).parser();
+ case BERTags.SEQUENCE:
+ return ASN1Sequence.getInstance(this, isExplicit).parser();
+ case BERTags.OCTET_STRING:
+ return ASN1OctetString.getInstance(this, isExplicit).parser();
+ }
+
+ if (isExplicit)
+ {
+ return getObject();
+ }
+
+ throw new RuntimeException("implicit tagging not implemented for tag: " + tag);
+ }
+
+ public ASN1Primitive getLoadedObject()
+ {
+ return this.toASN1Primitive();
+ }
+
+ ASN1Primitive toDERObject()
+ {
+ return new DERTaggedObject(explicit, tagNo, obj);
+ }
+
+ ASN1Primitive toDLObject()
+ {
+ return new DLTaggedObject(explicit, tagNo, obj);
+ }
+
+ abstract void encode(ASN1OutputStream out)
+ throws IOException;
+
+ public String toString()
+ {
+ return "[" + tagNo + "]" + obj;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1TaggedObjectParser.java b/core/src/main/java/org/spongycastle/asn1/ASN1TaggedObjectParser.java
new file mode 100644
index 00000000..2710954e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1TaggedObjectParser.java
@@ -0,0 +1,12 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+public interface ASN1TaggedObjectParser
+ extends ASN1Encodable, InMemoryRepresentable
+{
+ public int getTagNo();
+
+ public ASN1Encodable getObjectParser(int tag, boolean isExplicit)
+ throws IOException;
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ASN1UTCTime.java b/core/src/main/java/org/spongycastle/asn1/ASN1UTCTime.java
new file mode 100644
index 00000000..2f96041f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ASN1UTCTime.java
@@ -0,0 +1,314 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.SimpleTimeZone;
+
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Strings;
+
+/**
+- * UTC time object.
+ * Internal facade of {@link ASN1UTCTime}.
+ * <p>
+ * This datatype is valid only from 1950-01-01 00:00:00 UTC until 2049-12-31 23:59:59 UTC.
+ * <p>
+ * <hr>
+ * <p><b>X.690</b></p>
+ * <p><b>11: Restrictions on BER employed by both CER and DER</b></p>
+ * <p><b>11.8 UTCTime </b></p>
+ * <b>11.8.1</b> The encoding shall terminate with "Z",
+ * as described in the ITU-T X.680 | ISO/IEC 8824-1 clause on UTCTime.
+ * <p>
+ * <b>11.8.2</b> The seconds element shall always be present.
+ * <p>
+ * <b>11.8.3</b> Midnight (GMT) shall be represented in the form:
+ * <blockquote>
+ * "YYMMDD000000Z"
+ * </blockquote>
+ * where "YYMMDD" represents the day following the midnight in question.
+ */
+public class ASN1UTCTime
+ extends ASN1Primitive
+{
+ private byte[] time;
+
+ /**
+ * return an UTC Time from the passed in object.
+ *
+ * @param obj an ASN1UTCTime or an object that can be converted into one.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ * @return an ASN1UTCTime instance, or null.
+ */
+ public static ASN1UTCTime getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1UTCTime)
+ {
+ return (ASN1UTCTime)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (ASN1UTCTime)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an UTC Time from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ * @return an ASN1UTCTime instance, or null.
+ */
+ public static ASN1UTCTime getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Object o = obj.getObject();
+
+ if (explicit || o instanceof ASN1UTCTime)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new ASN1UTCTime(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ /**
+ * The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
+ * never encoded. When you're creating one of these objects from scratch, that's
+ * what you want to use, otherwise we'll try to deal with whatever gets read from
+ * the input stream... (this is why the input format is different from the getTime()
+ * method output).
+ * <p>
+ *
+ * @param time the time string.
+ */
+ public ASN1UTCTime(
+ String time)
+ {
+ this.time = Strings.toByteArray(time);
+ try
+ {
+ this.getDate();
+ }
+ catch (ParseException e)
+ {
+ throw new IllegalArgumentException("invalid date string: " + e.getMessage());
+ }
+ }
+
+ /**
+ * base constructor from a java.util.date object
+ * @param time the Date to build the time from.
+ */
+ public ASN1UTCTime(
+ Date time)
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'");
+
+ dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
+
+ this.time = Strings.toByteArray(dateF.format(time));
+ }
+
+ /**
+ * Base constructor from a java.util.date and Locale - you may need to use this if the default locale
+ * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible with other ASN.1 implementations.
+ *
+ * @param time a date object representing the time of interest.
+ * @param locale an appropriate Locale for producing an ASN.1 UTCTime value.
+ */
+ public ASN1UTCTime(
+ Date time,
+ Locale locale)
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'", locale);
+
+ dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
+
+ this.time = Strings.toByteArray(dateF.format(time));
+ }
+
+ ASN1UTCTime(
+ byte[] time)
+ {
+ this.time = time;
+ }
+
+ /**
+ * return the time as a date based on whatever a 2 digit year will return. For
+ * standardised processing use getAdjustedDate().
+ *
+ * @return the resulting date
+ * @exception ParseException if the date string cannot be parsed.
+ */
+ public Date getDate()
+ throws ParseException
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmssz");
+
+ return dateF.parse(getTime());
+ }
+
+ /**
+ * return the time as an adjusted date
+ * in the range of 1950 - 2049.
+ *
+ * @return a date in the range of 1950 to 2049.
+ * @exception ParseException if the date string cannot be parsed.
+ */
+ public Date getAdjustedDate()
+ throws ParseException
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
+
+ dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
+
+ return dateF.parse(getAdjustedTime());
+ }
+
+ /**
+ * return the time - always in the form of
+ * YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
+ * <p>
+ * Normally in a certificate we would expect "Z" rather than "GMT",
+ * however adding the "GMT" means we can just use:
+ * <pre>
+ * dateF = new SimpleDateFormat("yyMMddHHmmssz");
+ * </pre>
+ * To read in the time and get a date which is compatible with our local
+ * time zone.
+ * <p>
+ * <b>Note:</b> In some cases, due to the local date processing, this
+ * may lead to unexpected results. If you want to stick the normal
+ * convention of 1950 to 2049 use the getAdjustedTime() method.
+ */
+ public String getTime()
+ {
+ String stime = Strings.fromByteArray(time);
+
+ //
+ // standardise the format.
+ //
+ if (stime.indexOf('-') < 0 && stime.indexOf('+') < 0)
+ {
+ if (stime.length() == 11)
+ {
+ return stime.substring(0, 10) + "00GMT+00:00";
+ }
+ else
+ {
+ return stime.substring(0, 12) + "GMT+00:00";
+ }
+ }
+ else
+ {
+ int index = stime.indexOf('-');
+ if (index < 0)
+ {
+ index = stime.indexOf('+');
+ }
+ String d = stime;
+
+ if (index == stime.length() - 3)
+ {
+ d += "00";
+ }
+
+ if (index == 10)
+ {
+ return d.substring(0, 10) + "00GMT" + d.substring(10, 13) + ":" + d.substring(13, 15);
+ }
+ else
+ {
+ return d.substring(0, 12) + "GMT" + d.substring(12, 15) + ":" + d.substring(15, 17);
+ }
+ }
+ }
+
+ /**
+ * return a time string as an adjusted date with a 4 digit year. This goes
+ * in the range of 1950 - 2049.
+ */
+ public String getAdjustedTime()
+ {
+ String d = this.getTime();
+
+ if (d.charAt(0) < '5')
+ {
+ return "20" + d;
+ }
+ else
+ {
+ return "19" + d;
+ }
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ int length = time.length;
+
+ return 1 + StreamUtil.calculateBodyLength(length) + length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.write(BERTags.UTC_TIME);
+
+ int length = time.length;
+
+ out.writeLength(length);
+
+ for (int i = 0; i != length; i++)
+ {
+ out.write((byte)time[i]);
+ }
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1UTCTime))
+ {
+ return false;
+ }
+
+ return Arrays.areEqual(time, ((ASN1UTCTime)o).time);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(time);
+ }
+
+ public String toString()
+ {
+ return Strings.fromByteArray(time);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/BERApplicationSpecific.java b/core/src/main/java/org/spongycastle/asn1/BERApplicationSpecific.java
new file mode 100644
index 00000000..743b2200
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/BERApplicationSpecific.java
@@ -0,0 +1,10 @@
+package org.spongycastle.asn1;
+
+public class BERApplicationSpecific
+ extends DERApplicationSpecific
+{
+ public BERApplicationSpecific(int tagNo, ASN1EncodableVector vec)
+ {
+ super(tagNo, vec);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/BERApplicationSpecificParser.java b/core/src/main/java/org/spongycastle/asn1/BERApplicationSpecificParser.java
new file mode 100644
index 00000000..b77f81d0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/BERApplicationSpecificParser.java
@@ -0,0 +1,41 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+public class BERApplicationSpecificParser
+ implements ASN1ApplicationSpecificParser
+{
+ private final int tag;
+ private final ASN1StreamParser parser;
+
+ BERApplicationSpecificParser(int tag, ASN1StreamParser parser)
+ {
+ this.tag = tag;
+ this.parser = parser;
+ }
+
+ public ASN1Encodable readObject()
+ throws IOException
+ {
+ return parser.readObject();
+ }
+
+ public ASN1Primitive getLoadedObject()
+ throws IOException
+ {
+ return new BERApplicationSpecific(tag, parser.readVector());
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ try
+ {
+ return getLoadedObject();
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException(e.getMessage(), e);
+ }
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/BERConstructedOctetString.java b/core/src/main/java/org/spongycastle/asn1/BERConstructedOctetString.java
new file mode 100644
index 00000000..cd9289f2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/BERConstructedOctetString.java
@@ -0,0 +1,144 @@
+package org.spongycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+/**
+ * @deprecated use BEROctetString
+ */
+public class BERConstructedOctetString
+ extends BEROctetString
+{
+ private static final int MAX_LENGTH = 1000;
+
+ /**
+ * convert a vector of octet strings into a single byte string
+ */
+ static private byte[] toBytes(
+ Vector octs)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ for (int i = 0; i != octs.size(); i++)
+ {
+ try
+ {
+ DEROctetString o = (DEROctetString)octs.elementAt(i);
+
+ bOut.write(o.getOctets());
+ }
+ catch (ClassCastException e)
+ {
+ throw new IllegalArgumentException(octs.elementAt(i).getClass().getName() + " found in input should only contain DEROctetString");
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("exception converting octets " + e.toString());
+ }
+ }
+
+ return bOut.toByteArray();
+ }
+
+ private Vector octs;
+
+ /**
+ * @param string the octets making up the octet string.
+ */
+ public BERConstructedOctetString(
+ byte[] string)
+ {
+ super(string);
+ }
+
+ public BERConstructedOctetString(
+ Vector octs)
+ {
+ super(toBytes(octs));
+
+ this.octs = octs;
+ }
+
+ public BERConstructedOctetString(
+ ASN1Primitive obj)
+ {
+ super(toByteArray(obj));
+ }
+
+ private static byte[] toByteArray(ASN1Primitive obj)
+ {
+ try
+ {
+ return obj.getEncoded();
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("Unable to encode object");
+ }
+ }
+
+ public BERConstructedOctetString(
+ ASN1Encodable obj)
+ {
+ this(obj.toASN1Primitive());
+ }
+
+ public byte[] getOctets()
+ {
+ return string;
+ }
+
+ /**
+ * return the DER octets that make up this string.
+ */
+ public Enumeration getObjects()
+ {
+ if (octs == null)
+ {
+ return generateOcts().elements();
+ }
+
+ return octs.elements();
+ }
+
+ private Vector generateOcts()
+ {
+ Vector vec = new Vector();
+ for (int i = 0; i < string.length; i += MAX_LENGTH)
+ {
+ int end;
+
+ if (i + MAX_LENGTH > string.length)
+ {
+ end = string.length;
+ }
+ else
+ {
+ end = i + MAX_LENGTH;
+ }
+
+ byte[] nStr = new byte[end - i];
+
+ System.arraycopy(string, i, nStr, 0, nStr.length);
+
+ vec.addElement(new DEROctetString(nStr));
+ }
+
+ return vec;
+ }
+
+ public static BEROctetString fromSequence(ASN1Sequence seq)
+ {
+ Vector v = new Vector();
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ v.addElement(e.nextElement());
+ }
+
+ return new BERConstructedOctetString(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/BERFactory.java b/core/src/main/java/org/spongycastle/asn1/BERFactory.java
new file mode 100644
index 00000000..a444eac6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/BERFactory.java
@@ -0,0 +1,17 @@
+package org.spongycastle.asn1;
+
+class BERFactory
+{
+ static final BERSequence EMPTY_SEQUENCE = new BERSequence();
+ static final BERSet EMPTY_SET = new BERSet();
+
+ static BERSequence createSequence(ASN1EncodableVector v)
+ {
+ return v.size() < 1 ? EMPTY_SEQUENCE : new BERSequence(v);
+ }
+
+ static BERSet createSet(ASN1EncodableVector v)
+ {
+ return v.size() < 1 ? EMPTY_SET : new BERSet(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/BERGenerator.java b/core/src/main/java/org/spongycastle/asn1/BERGenerator.java
new file mode 100644
index 00000000..0cca35c3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/BERGenerator.java
@@ -0,0 +1,100 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class BERGenerator
+ extends ASN1Generator
+{
+ private boolean _tagged = false;
+ private boolean _isExplicit;
+ private int _tagNo;
+
+ protected BERGenerator(
+ OutputStream out)
+ {
+ super(out);
+ }
+
+ public BERGenerator(
+ OutputStream out,
+ int tagNo,
+ boolean isExplicit)
+ {
+ super(out);
+
+ _tagged = true;
+ _isExplicit = isExplicit;
+ _tagNo = tagNo;
+ }
+
+ public OutputStream getRawOutputStream()
+ {
+ return _out;
+ }
+
+ private void writeHdr(
+ int tag)
+ throws IOException
+ {
+ _out.write(tag);
+ _out.write(0x80);
+ }
+
+ protected void writeBERHeader(
+ int tag)
+ throws IOException
+ {
+ if (_tagged)
+ {
+ int tagNum = _tagNo | BERTags.TAGGED;
+
+ if (_isExplicit)
+ {
+ writeHdr(tagNum | BERTags.CONSTRUCTED);
+ writeHdr(tag);
+ }
+ else
+ {
+ if ((tag & BERTags.CONSTRUCTED) != 0)
+ {
+ writeHdr(tagNum | BERTags.CONSTRUCTED);
+ }
+ else
+ {
+ writeHdr(tagNum);
+ }
+ }
+ }
+ else
+ {
+ writeHdr(tag);
+ }
+ }
+
+ protected void writeBERBody(
+ InputStream contentStream)
+ throws IOException
+ {
+ int ch;
+
+ while ((ch = contentStream.read()) >= 0)
+ {
+ _out.write(ch);
+ }
+ }
+
+ protected void writeBEREnd()
+ throws IOException
+ {
+ _out.write(0x00);
+ _out.write(0x00);
+
+ if (_tagged && _isExplicit) // write extra end for tag header
+ {
+ _out.write(0x00);
+ _out.write(0x00);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/BEROctetString.java b/core/src/main/java/org/spongycastle/asn1/BEROctetString.java
new file mode 100644
index 00000000..b32f5c53
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/BEROctetString.java
@@ -0,0 +1,168 @@
+package org.spongycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class BEROctetString
+ extends ASN1OctetString
+{
+ private static final int MAX_LENGTH = 1000;
+
+ private ASN1OctetString[] octs;
+
+ /**
+ * convert a vector of octet strings into a single byte string
+ */
+ static private byte[] toBytes(
+ ASN1OctetString[] octs)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ for (int i = 0; i != octs.length; i++)
+ {
+ try
+ {
+ DEROctetString o = (DEROctetString)octs[i];
+
+ bOut.write(o.getOctets());
+ }
+ catch (ClassCastException e)
+ {
+ throw new IllegalArgumentException(octs[i].getClass().getName() + " found in input should only contain DEROctetString");
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("exception converting octets " + e.toString());
+ }
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * @param string the octets making up the octet string.
+ */
+ public BEROctetString(
+ byte[] string)
+ {
+ super(string);
+ }
+
+ public BEROctetString(
+ ASN1OctetString[] octs)
+ {
+ super(toBytes(octs));
+
+ this.octs = octs;
+ }
+
+ public byte[] getOctets()
+ {
+ return string;
+ }
+
+ /**
+ * return the DER octets that make up this string.
+ */
+ public Enumeration getObjects()
+ {
+ if (octs == null)
+ {
+ return generateOcts().elements();
+ }
+
+ return new Enumeration()
+ {
+ int counter = 0;
+
+ public boolean hasMoreElements()
+ {
+ return counter < octs.length;
+ }
+
+ public Object nextElement()
+ {
+ return octs[counter++];
+ }
+ };
+ }
+
+ private Vector generateOcts()
+ {
+ Vector vec = new Vector();
+ for (int i = 0; i < string.length; i += MAX_LENGTH)
+ {
+ int end;
+
+ if (i + MAX_LENGTH > string.length)
+ {
+ end = string.length;
+ }
+ else
+ {
+ end = i + MAX_LENGTH;
+ }
+
+ byte[] nStr = new byte[end - i];
+
+ System.arraycopy(string, i, nStr, 0, nStr.length);
+
+ vec.addElement(new DEROctetString(nStr));
+ }
+
+ return vec;
+ }
+
+ boolean isConstructed()
+ {
+ return true;
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ int length = 0;
+ for (Enumeration e = getObjects(); e.hasMoreElements();)
+ {
+ length += ((ASN1Encodable)e.nextElement()).toASN1Primitive().encodedLength();
+ }
+
+ return 2 + length + 2;
+ }
+
+ public void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.write(BERTags.CONSTRUCTED | BERTags.OCTET_STRING);
+
+ out.write(0x80);
+
+ //
+ // write out the octet array
+ //
+ for (Enumeration e = getObjects(); e.hasMoreElements();)
+ {
+ out.writeObject((ASN1Encodable)e.nextElement());
+ }
+
+ out.write(0x00);
+ out.write(0x00);
+ }
+
+ static BEROctetString fromSequence(ASN1Sequence seq)
+ {
+ ASN1OctetString[] v = new ASN1OctetString[seq.size()];
+ Enumeration e = seq.getObjects();
+ int index = 0;
+
+ while (e.hasMoreElements())
+ {
+ v[index++] = (ASN1OctetString)e.nextElement();
+ }
+
+ return new BEROctetString(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/BEROctetStringGenerator.java b/core/src/main/java/org/spongycastle/asn1/BEROctetStringGenerator.java
new file mode 100644
index 00000000..47d1a0eb
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/BEROctetStringGenerator.java
@@ -0,0 +1,102 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class BEROctetStringGenerator
+ extends BERGenerator
+{
+ public BEROctetStringGenerator(OutputStream out)
+ throws IOException
+ {
+ super(out);
+
+ writeBERHeader(BERTags.CONSTRUCTED | BERTags.OCTET_STRING);
+ }
+
+ public BEROctetStringGenerator(
+ OutputStream out,
+ int tagNo,
+ boolean isExplicit)
+ throws IOException
+ {
+ super(out, tagNo, isExplicit);
+
+ writeBERHeader(BERTags.CONSTRUCTED | BERTags.OCTET_STRING);
+ }
+
+ public OutputStream getOctetOutputStream()
+ {
+ return getOctetOutputStream(new byte[1000]); // limit for CER encoding.
+ }
+
+ public OutputStream getOctetOutputStream(
+ byte[] buf)
+ {
+ return new BufferedBEROctetStream(buf);
+ }
+
+ private class BufferedBEROctetStream
+ extends OutputStream
+ {
+ private byte[] _buf;
+ private int _off;
+ private DEROutputStream _derOut;
+
+ BufferedBEROctetStream(
+ byte[] buf)
+ {
+ _buf = buf;
+ _off = 0;
+ _derOut = new DEROutputStream(_out);
+ }
+
+ public void write(
+ int b)
+ throws IOException
+ {
+ _buf[_off++] = (byte)b;
+
+ if (_off == _buf.length)
+ {
+ DEROctetString.encode(_derOut, _buf);
+ _off = 0;
+ }
+ }
+
+ public void write(byte[] b, int off, int len) throws IOException
+ {
+ while (len > 0)
+ {
+ int numToCopy = Math.min(len, _buf.length - _off);
+ System.arraycopy(b, off, _buf, _off, numToCopy);
+
+ _off += numToCopy;
+ if (_off < _buf.length)
+ {
+ break;
+ }
+
+ DEROctetString.encode(_derOut, _buf);
+ _off = 0;
+
+ off += numToCopy;
+ len -= numToCopy;
+ }
+ }
+
+ public void close()
+ throws IOException
+ {
+ if (_off != 0)
+ {
+ byte[] bytes = new byte[_off];
+ System.arraycopy(_buf, 0, bytes, 0, _off);
+
+ DEROctetString.encode(_derOut, bytes);
+ }
+
+ writeBEREnd();
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/BEROctetStringParser.java b/core/src/main/java/org/spongycastle/asn1/BEROctetStringParser.java
new file mode 100644
index 00000000..6cf20fcf
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/BEROctetStringParser.java
@@ -0,0 +1,41 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.spongycastle.util.io.Streams;
+
+public class BEROctetStringParser
+ implements ASN1OctetStringParser
+{
+ private ASN1StreamParser _parser;
+
+ BEROctetStringParser(
+ ASN1StreamParser parser)
+ {
+ _parser = parser;
+ }
+
+ public InputStream getOctetStream()
+ {
+ return new ConstructedOctetStream(_parser);
+ }
+
+ public ASN1Primitive getLoadedObject()
+ throws IOException
+ {
+ return new BEROctetString(Streams.readAll(getOctetStream()));
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ try
+ {
+ return getLoadedObject();
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException("IOException converting stream to byte array: " + e.getMessage(), e);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/BEROutputStream.java b/core/src/main/java/org/spongycastle/asn1/BEROutputStream.java
new file mode 100644
index 00000000..13b20d52
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/BEROutputStream.java
@@ -0,0 +1,36 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class BEROutputStream
+ extends DEROutputStream
+{
+ public BEROutputStream(
+ OutputStream os)
+ {
+ super(os);
+ }
+
+ public void writeObject(
+ Object obj)
+ throws IOException
+ {
+ if (obj == null)
+ {
+ writeNull();
+ }
+ else if (obj instanceof ASN1Primitive)
+ {
+ ((ASN1Primitive)obj).encode(this);
+ }
+ else if (obj instanceof ASN1Encodable)
+ {
+ ((ASN1Encodable)obj).toASN1Primitive().encode(this);
+ }
+ else
+ {
+ throw new IOException("object not BEREncodable");
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/BERSequence.java b/core/src/main/java/org/spongycastle/asn1/BERSequence.java
new file mode 100644
index 00000000..d034af1a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/BERSequence.java
@@ -0,0 +1,73 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+public class BERSequence
+ extends ASN1Sequence
+{
+ /**
+ * create an empty sequence
+ */
+ public BERSequence()
+ {
+ }
+
+ /**
+ * create a sequence containing one object
+ */
+ public BERSequence(
+ ASN1Encodable obj)
+ {
+ super(obj);
+ }
+
+ /**
+ * create a sequence containing a vector of objects.
+ */
+ public BERSequence(
+ ASN1EncodableVector v)
+ {
+ super(v);
+ }
+
+ /**
+ * create a sequence containing an array of objects.
+ */
+ public BERSequence(
+ ASN1Encodable[] array)
+ {
+ super(array);
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ int length = 0;
+ for (Enumeration e = getObjects(); e.hasMoreElements();)
+ {
+ length += ((ASN1Encodable)e.nextElement()).toASN1Primitive().encodedLength();
+ }
+
+ return 2 + length + 2;
+ }
+
+ /*
+ */
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.write(BERTags.SEQUENCE | BERTags.CONSTRUCTED);
+ out.write(0x80);
+
+ Enumeration e = getObjects();
+ while (e.hasMoreElements())
+ {
+ out.writeObject((ASN1Encodable)e.nextElement());
+ }
+
+ out.write(0x00);
+ out.write(0x00);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/BERSequenceGenerator.java b/core/src/main/java/org/spongycastle/asn1/BERSequenceGenerator.java
new file mode 100644
index 00000000..5d759ddd
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/BERSequenceGenerator.java
@@ -0,0 +1,41 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class BERSequenceGenerator
+ extends BERGenerator
+{
+ public BERSequenceGenerator(
+ OutputStream out)
+ throws IOException
+ {
+ super(out);
+
+ writeBERHeader(BERTags.CONSTRUCTED | BERTags.SEQUENCE);
+ }
+
+ public BERSequenceGenerator(
+ OutputStream out,
+ int tagNo,
+ boolean isExplicit)
+ throws IOException
+ {
+ super(out, tagNo, isExplicit);
+
+ writeBERHeader(BERTags.CONSTRUCTED | BERTags.SEQUENCE);
+ }
+
+ public void addObject(
+ ASN1Encodable object)
+ throws IOException
+ {
+ object.toASN1Primitive().encode(new BEROutputStream(_out));
+ }
+
+ public void close()
+ throws IOException
+ {
+ writeBEREnd();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/BERSequenceParser.java b/core/src/main/java/org/spongycastle/asn1/BERSequenceParser.java
new file mode 100644
index 00000000..3bfadff5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/BERSequenceParser.java
@@ -0,0 +1,38 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+public class BERSequenceParser
+ implements ASN1SequenceParser
+{
+ private ASN1StreamParser _parser;
+
+ BERSequenceParser(ASN1StreamParser parser)
+ {
+ this._parser = parser;
+ }
+
+ public ASN1Encodable readObject()
+ throws IOException
+ {
+ return _parser.readObject();
+ }
+
+ public ASN1Primitive getLoadedObject()
+ throws IOException
+ {
+ return new BERSequence(_parser.readVector());
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ try
+ {
+ return getLoadedObject();
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException(e.getMessage());
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/BERSet.java b/core/src/main/java/org/spongycastle/asn1/BERSet.java
new file mode 100644
index 00000000..ed0c3f52
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/BERSet.java
@@ -0,0 +1,73 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+public class BERSet
+ extends ASN1Set
+{
+ /**
+ * create an empty sequence
+ */
+ public BERSet()
+ {
+ }
+
+ /**
+ * @param obj - a single object that makes up the set.
+ */
+ public BERSet(
+ ASN1Encodable obj)
+ {
+ super(obj);
+ }
+
+ /**
+ * @param v - a vector of objects making up the set.
+ */
+ public BERSet(
+ ASN1EncodableVector v)
+ {
+ super(v, false);
+ }
+
+ /**
+ * create a set from an array of objects.
+ */
+ public BERSet(
+ ASN1Encodable[] a)
+ {
+ super(a, false);
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ int length = 0;
+ for (Enumeration e = getObjects(); e.hasMoreElements();)
+ {
+ length += ((ASN1Encodable)e.nextElement()).toASN1Primitive().encodedLength();
+ }
+
+ return 2 + length + 2;
+ }
+
+ /*
+ */
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.write(BERTags.SET | BERTags.CONSTRUCTED);
+ out.write(0x80);
+
+ Enumeration e = getObjects();
+ while (e.hasMoreElements())
+ {
+ out.writeObject((ASN1Encodable)e.nextElement());
+ }
+
+ out.write(0x00);
+ out.write(0x00);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/BERSetParser.java b/core/src/main/java/org/spongycastle/asn1/BERSetParser.java
new file mode 100644
index 00000000..0b649f29
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/BERSetParser.java
@@ -0,0 +1,38 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+public class BERSetParser
+ implements ASN1SetParser
+{
+ private ASN1StreamParser _parser;
+
+ BERSetParser(ASN1StreamParser parser)
+ {
+ this._parser = parser;
+ }
+
+ public ASN1Encodable readObject()
+ throws IOException
+ {
+ return _parser.readObject();
+ }
+
+ public ASN1Primitive getLoadedObject()
+ throws IOException
+ {
+ return new BERSet(_parser.readVector());
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ try
+ {
+ return getLoadedObject();
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException(e.getMessage(), e);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/BERTaggedObject.java b/core/src/main/java/org/spongycastle/asn1/BERTaggedObject.java
new file mode 100644
index 00000000..bd55e597
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/BERTaggedObject.java
@@ -0,0 +1,147 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+/**
+ * BER TaggedObject - in ASN.1 notation this is any object preceded by
+ * a [n] where n is some number - these are assumed to follow the construction
+ * rules (as with sequences).
+ */
+public class BERTaggedObject
+ extends ASN1TaggedObject
+{
+ /**
+ * @param tagNo the tag number for this object.
+ * @param obj the tagged object.
+ */
+ public BERTaggedObject(
+ int tagNo,
+ ASN1Encodable obj)
+ {
+ super(true, tagNo, obj);
+ }
+
+ /**
+ * @param explicit true if an explicitly tagged object.
+ * @param tagNo the tag number for this object.
+ * @param obj the tagged object.
+ */
+ public BERTaggedObject(
+ boolean explicit,
+ int tagNo,
+ ASN1Encodable obj)
+ {
+ super(explicit, tagNo, obj);
+ }
+
+ /**
+ * create an implicitly tagged object that contains a zero
+ * length sequence.
+ */
+ public BERTaggedObject(
+ int tagNo)
+ {
+ super(false, tagNo, new BERSequence());
+ }
+
+ boolean isConstructed()
+ {
+ if (!empty)
+ {
+ if (explicit)
+ {
+ return true;
+ }
+ else
+ {
+ ASN1Primitive primitive = obj.toASN1Primitive().toDERObject();
+
+ return primitive.isConstructed();
+ }
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ if (!empty)
+ {
+ ASN1Primitive primitive = obj.toASN1Primitive();
+ int length = primitive.encodedLength();
+
+ if (explicit)
+ {
+ return StreamUtil.calculateTagLength(tagNo) + StreamUtil.calculateBodyLength(length) + length;
+ }
+ else
+ {
+ // header length already in calculation
+ length = length - 1;
+
+ return StreamUtil.calculateTagLength(tagNo) + length;
+ }
+ }
+ else
+ {
+ return StreamUtil.calculateTagLength(tagNo) + 1;
+ }
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeTag(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo);
+ out.write(0x80);
+
+ if (!empty)
+ {
+ if (!explicit)
+ {
+ Enumeration e;
+ if (obj instanceof ASN1OctetString)
+ {
+ if (obj instanceof BEROctetString)
+ {
+ e = ((BEROctetString)obj).getObjects();
+ }
+ else
+ {
+ ASN1OctetString octs = (ASN1OctetString)obj;
+ BEROctetString berO = new BEROctetString(octs.getOctets());
+ e = berO.getObjects();
+ }
+ }
+ else if (obj instanceof ASN1Sequence)
+ {
+ e = ((ASN1Sequence)obj).getObjects();
+ }
+ else if (obj instanceof ASN1Set)
+ {
+ e = ((ASN1Set)obj).getObjects();
+ }
+ else
+ {
+ throw new RuntimeException("not implemented: " + obj.getClass().getName());
+ }
+
+ while (e.hasMoreElements())
+ {
+ out.writeObject((ASN1Encodable)e.nextElement());
+ }
+ }
+ else
+ {
+ out.writeObject(obj);
+ }
+ }
+
+ out.write(0x00);
+ out.write(0x00);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/BERTaggedObjectParser.java b/core/src/main/java/org/spongycastle/asn1/BERTaggedObjectParser.java
new file mode 100644
index 00000000..cb7f13ff
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/BERTaggedObjectParser.java
@@ -0,0 +1,66 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+public class BERTaggedObjectParser
+ implements ASN1TaggedObjectParser
+{
+ private boolean _constructed;
+ private int _tagNumber;
+ private ASN1StreamParser _parser;
+
+ BERTaggedObjectParser(
+ boolean constructed,
+ int tagNumber,
+ ASN1StreamParser parser)
+ {
+ _constructed = constructed;
+ _tagNumber = tagNumber;
+ _parser = parser;
+ }
+
+ public boolean isConstructed()
+ {
+ return _constructed;
+ }
+
+ public int getTagNo()
+ {
+ return _tagNumber;
+ }
+
+ public ASN1Encodable getObjectParser(
+ int tag,
+ boolean isExplicit)
+ throws IOException
+ {
+ if (isExplicit)
+ {
+ if (!_constructed)
+ {
+ throw new IOException("Explicit tags must be constructed (see X.690 8.14.2)");
+ }
+ return _parser.readObject();
+ }
+
+ return _parser.readImplicit(_constructed, tag);
+ }
+
+ public ASN1Primitive getLoadedObject()
+ throws IOException
+ {
+ return _parser.readTaggedObject(_constructed, _tagNumber);
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ try
+ {
+ return this.getLoadedObject();
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException(e.getMessage());
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/BERTags.java b/core/src/main/java/org/spongycastle/asn1/BERTags.java
new file mode 100644
index 00000000..4b25e716
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/BERTags.java
@@ -0,0 +1,36 @@
+package org.spongycastle.asn1;
+
+public interface BERTags
+{
+ public static final int BOOLEAN = 0x01;
+ public static final int INTEGER = 0x02;
+ public static final int BIT_STRING = 0x03;
+ public static final int OCTET_STRING = 0x04;
+ public static final int NULL = 0x05;
+ public static final int OBJECT_IDENTIFIER = 0x06;
+ public static final int EXTERNAL = 0x08;
+ public static final int ENUMERATED = 0x0a;
+ public static final int SEQUENCE = 0x10;
+ public static final int 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 - used to model a SET of the same type.
+
+
+ public static final int NUMERIC_STRING = 0x12;
+ public static final int PRINTABLE_STRING = 0x13;
+ public static final int T61_STRING = 0x14;
+ public static final int VIDEOTEX_STRING = 0x15;
+ public static final int IA5_STRING = 0x16;
+ public static final int UTC_TIME = 0x17;
+ public static final int GENERALIZED_TIME = 0x18;
+ public static final int GRAPHIC_STRING = 0x19;
+ public static final int VISIBLE_STRING = 0x1a;
+ public static final int GENERAL_STRING = 0x1b;
+ public static final int UNIVERSAL_STRING = 0x1c;
+ public static final int BMP_STRING = 0x1e;
+ public static final int UTF8_STRING = 0x0c;
+
+ public static final int CONSTRUCTED = 0x20;
+ public static final int APPLICATION = 0x40;
+ public static final int TAGGED = 0x80;
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ConstructedOctetStream.java b/core/src/main/java/org/spongycastle/asn1/ConstructedOctetStream.java
new file mode 100644
index 00000000..21c3ac36
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ConstructedOctetStream.java
@@ -0,0 +1,111 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+class ConstructedOctetStream
+ extends InputStream
+{
+ private final ASN1StreamParser _parser;
+
+ private boolean _first = true;
+ private InputStream _currentStream;
+
+ ConstructedOctetStream(
+ ASN1StreamParser parser)
+ {
+ _parser = parser;
+ }
+
+ public int read(byte[] b, int off, int len) throws IOException
+ {
+ if (_currentStream == null)
+ {
+ if (!_first)
+ {
+ return -1;
+ }
+
+ ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();
+
+ if (s == null)
+ {
+ return -1;
+ }
+
+ _first = false;
+ _currentStream = s.getOctetStream();
+ }
+
+ int totalRead = 0;
+
+ for (;;)
+ {
+ int numRead = _currentStream.read(b, off + totalRead, len - totalRead);
+
+ if (numRead >= 0)
+ {
+ totalRead += numRead;
+
+ if (totalRead == len)
+ {
+ return totalRead;
+ }
+ }
+ else
+ {
+ ASN1OctetStringParser aos = (ASN1OctetStringParser)_parser.readObject();
+
+ if (aos == null)
+ {
+ _currentStream = null;
+ return totalRead < 1 ? -1 : totalRead;
+ }
+
+ _currentStream = aos.getOctetStream();
+ }
+ }
+ }
+
+ public int read()
+ throws IOException
+ {
+ if (_currentStream == null)
+ {
+ if (!_first)
+ {
+ return -1;
+ }
+
+ ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();
+
+ if (s == null)
+ {
+ return -1;
+ }
+
+ _first = false;
+ _currentStream = s.getOctetStream();
+ }
+
+ for (;;)
+ {
+ int b = _currentStream.read();
+
+ if (b >= 0)
+ {
+ return b;
+ }
+
+ ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();
+
+ if (s == null)
+ {
+ _currentStream = null;
+ return -1;
+ }
+
+ _currentStream = s.getOctetStream();
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERApplicationSpecific.java b/core/src/main/java/org/spongycastle/asn1/DERApplicationSpecific.java
new file mode 100644
index 00000000..d3b40e03
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERApplicationSpecific.java
@@ -0,0 +1,267 @@
+package org.spongycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import org.spongycastle.util.Arrays;
+
+/**
+ * Base class for an application specific object
+ */
+public class DERApplicationSpecific
+ extends ASN1Primitive
+{
+ private final boolean isConstructed;
+ private final int tag;
+ private final byte[] octets;
+
+ DERApplicationSpecific(
+ boolean isConstructed,
+ int tag,
+ byte[] octets)
+ {
+ this.isConstructed = isConstructed;
+ this.tag = tag;
+ this.octets = octets;
+ }
+
+ public DERApplicationSpecific(
+ int tag,
+ byte[] octets)
+ {
+ this(false, tag, octets);
+ }
+
+ public DERApplicationSpecific(
+ int tag,
+ ASN1Encodable object)
+ throws IOException
+ {
+ this(true, tag, object);
+ }
+
+ public DERApplicationSpecific(
+ boolean explicit,
+ int tag,
+ ASN1Encodable object)
+ throws IOException
+ {
+ ASN1Primitive primitive = object.toASN1Primitive();
+
+ byte[] data = primitive.getEncoded(ASN1Encoding.DER);
+
+ this.isConstructed = explicit || (primitive instanceof ASN1Set || primitive instanceof ASN1Sequence);
+ this.tag = tag;
+
+ if (explicit)
+ {
+ this.octets = data;
+ }
+ else
+ {
+ int lenBytes = getLengthOfHeader(data);
+ byte[] tmp = new byte[data.length - lenBytes];
+ System.arraycopy(data, lenBytes, tmp, 0, tmp.length);
+ this.octets = tmp;
+ }
+ }
+
+ public DERApplicationSpecific(int tagNo, ASN1EncodableVector vec)
+ {
+ this.tag = tagNo;
+ this.isConstructed = true;
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ for (int i = 0; i != vec.size(); i++)
+ {
+ try
+ {
+ bOut.write(((ASN1Object)vec.get(i)).getEncoded(ASN1Encoding.DER));
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException("malformed object: " + e, e);
+ }
+ }
+ this.octets = bOut.toByteArray();
+ }
+
+ public static DERApplicationSpecific getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof DERApplicationSpecific)
+ {
+ return (DERApplicationSpecific)obj;
+ }
+ else if (obj instanceof byte[])
+ {
+ try
+ {
+ return DERApplicationSpecific.getInstance(ASN1Primitive.fromByteArray((byte[])obj));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("failed to construct object from byte[]: " + e.getMessage());
+ }
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
+ }
+
+ private int getLengthOfHeader(byte[] data)
+ {
+ int length = data[1] & 0xff; // TODO: assumes 1 byte tag
+
+ if (length == 0x80)
+ {
+ return 2; // indefinite-length encoding
+ }
+
+ if (length > 127)
+ {
+ int size = length & 0x7f;
+
+ // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
+ if (size > 4)
+ {
+ throw new IllegalStateException("DER length more than 4 bytes: " + size);
+ }
+
+ return size + 2;
+ }
+
+ return 2;
+ }
+
+ public boolean isConstructed()
+ {
+ return isConstructed;
+ }
+
+ public byte[] getContents()
+ {
+ return octets;
+ }
+
+ public int getApplicationTag()
+ {
+ return tag;
+ }
+
+ /**
+ * Return the enclosed object assuming explicit tagging.
+ *
+ * @return the resulting object
+ * @throws IOException if reconstruction fails.
+ */
+ public ASN1Primitive getObject()
+ throws IOException
+ {
+ return new ASN1InputStream(getContents()).readObject();
+ }
+
+ /**
+ * Return the enclosed object assuming implicit tagging.
+ *
+ * @param derTagNo the type tag that should be applied to the object's contents.
+ * @return the resulting object
+ * @throws IOException if reconstruction fails.
+ */
+ public ASN1Primitive getObject(int derTagNo)
+ throws IOException
+ {
+ if (derTagNo >= 0x1f)
+ {
+ throw new IOException("unsupported tag number");
+ }
+
+ byte[] orig = this.getEncoded();
+ byte[] tmp = replaceTagNumber(derTagNo, orig);
+
+ if ((orig[0] & BERTags.CONSTRUCTED) != 0)
+ {
+ tmp[0] |= BERTags.CONSTRUCTED;
+ }
+
+ return new ASN1InputStream(tmp).readObject();
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ return StreamUtil.calculateTagLength(tag) + StreamUtil.calculateBodyLength(octets.length) + octets.length;
+ }
+
+ /* (non-Javadoc)
+ * @see org.spongycastle.asn1.ASN1Primitive#encode(org.spongycastle.asn1.DEROutputStream)
+ */
+ void encode(ASN1OutputStream out) throws IOException
+ {
+ int classBits = BERTags.APPLICATION;
+ if (isConstructed)
+ {
+ classBits |= BERTags.CONSTRUCTED;
+ }
+
+ out.writeEncoded(classBits, tag, octets);
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERApplicationSpecific))
+ {
+ return false;
+ }
+
+ DERApplicationSpecific other = (DERApplicationSpecific)o;
+
+ return isConstructed == other.isConstructed
+ && tag == other.tag
+ && Arrays.areEqual(octets, other.octets);
+ }
+
+ public int hashCode()
+ {
+ return (isConstructed ? 1 : 0) ^ tag ^ Arrays.hashCode(octets);
+ }
+
+ private byte[] replaceTagNumber(int newTag, byte[] input)
+ throws IOException
+ {
+ int tagNo = input[0] & 0x1f;
+ int index = 1;
+ //
+ // with tagged object tag number is bottom 5 bits, or stored at the start of the content
+ //
+ if (tagNo == 0x1f)
+ {
+ tagNo = 0;
+
+ int b = input[index++] & 0xff;
+
+ // X.690-0207 8.1.2.4.2
+ // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
+ if ((b & 0x7f) == 0) // Note: -1 will pass
+ {
+ throw new ASN1ParsingException("corrupted stream - invalid high tag number found");
+ }
+
+ while ((b >= 0) && ((b & 0x80) != 0))
+ {
+ tagNo |= (b & 0x7f);
+ tagNo <<= 7;
+ b = input[index++] & 0xff;
+ }
+
+ tagNo |= (b & 0x7f);
+ }
+
+ byte[] tmp = new byte[input.length - index + 1];
+
+ System.arraycopy(input, index, tmp, 1, tmp.length - 1);
+
+ tmp[0] = (byte)newTag;
+
+ return tmp;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERBMPString.java b/core/src/main/java/org/spongycastle/asn1/DERBMPString.java
new file mode 100644
index 00000000..ad752583
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERBMPString.java
@@ -0,0 +1,157 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+import org.spongycastle.util.Arrays;
+
+/**
+ * DER BMPString object.
+ */
+public class DERBMPString
+ extends ASN1Primitive
+ implements ASN1String
+{
+ private char[] string;
+
+ /**
+ * return a BMP String from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ * @return a DERBMPString instance, or null.
+ */
+ public static DERBMPString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERBMPString)
+ {
+ return (DERBMPString)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (DERBMPString)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return a BMP String from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ * @return a DERBMPString instance.
+ */
+ public static DERBMPString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERBMPString)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new DERBMPString(ASN1OctetString.getInstance(o).getOctets());
+ }
+ }
+
+ /**
+ * basic constructor - byte encoded string.
+ * @param string the encoded BMP STRING to wrap.
+ */
+ DERBMPString(
+ byte[] string)
+ {
+ char[] cs = new char[string.length / 2];
+
+ for (int i = 0; i != cs.length; i++)
+ {
+ cs[i] = (char)((string[2 * i] << 8) | (string[2 * i + 1] & 0xff));
+ }
+
+ this.string = cs;
+ }
+
+ DERBMPString(char[] string)
+ {
+ this.string = string;
+ }
+
+ /**
+ * basic constructor
+ * @param string a String to wrap as a BMP STRING.
+ */
+ public DERBMPString(
+ String string)
+ {
+ this.string = string.toCharArray();
+ }
+
+ public String getString()
+ {
+ return new String(string);
+ }
+
+ public String toString()
+ {
+ return getString();
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(string);
+ }
+
+ protected boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERBMPString))
+ {
+ return false;
+ }
+
+ DERBMPString s = (DERBMPString)o;
+
+ return Arrays.areEqual(string, s.string);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(string.length * 2) + (string.length * 2);
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.write(BERTags.BMP_STRING);
+ out.writeLength(string.length * 2);
+
+ for (int i = 0; i != string.length; i++)
+ {
+ char c = string[i];
+
+ out.write((byte)(c >> 8));
+ out.write((byte)c);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERBitString.java b/core/src/main/java/org/spongycastle/asn1/DERBitString.java
new file mode 100644
index 00000000..9a2d2d03
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERBitString.java
@@ -0,0 +1,318 @@
+package org.spongycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.io.Streams;
+
+public class DERBitString
+ extends ASN1Primitive
+ implements ASN1String
+{
+ private static final char[] table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+ protected byte[] data;
+ protected int padBits;
+
+ /**
+ * @param bitString an int containing the BIT STRING
+ * @return the correct number of pad bits for a bit string defined in
+ * a 32 bit constant
+ */
+ static protected int getPadBits(
+ int bitString)
+ {
+ int val = 0;
+ for (int i = 3; i >= 0; i--)
+ {
+ //
+ // this may look a little odd, but if it isn't done like this pre jdk1.2
+ // JVM's break!
+ //
+ if (i != 0)
+ {
+ if ((bitString >> (i * 8)) != 0)
+ {
+ val = (bitString >> (i * 8)) & 0xFF;
+ break;
+ }
+ }
+ else
+ {
+ if (bitString != 0)
+ {
+ val = bitString & 0xFF;
+ break;
+ }
+ }
+ }
+
+ if (val == 0)
+ {
+ return 7;
+ }
+
+
+ int bits = 1;
+
+ while (((val <<= 1) & 0xFF) != 0)
+ {
+ bits++;
+ }
+
+ return 8 - bits;
+ }
+
+ /**
+ * @param bitString an int containing the BIT STRING
+ * @return the correct number of bytes for a bit string defined in
+ * a 32 bit constant
+ */
+ static protected byte[] getBytes(int bitString)
+ {
+ int bytes = 4;
+ for (int i = 3; i >= 1; i--)
+ {
+ if ((bitString & (0xFF << (i * 8))) != 0)
+ {
+ break;
+ }
+ bytes--;
+ }
+
+ byte[] result = new byte[bytes];
+ for (int i = 0; i < bytes; i++)
+ {
+ result[i] = (byte) ((bitString >> (i * 8)) & 0xFF);
+ }
+
+ return result;
+ }
+
+ /**
+ * return a Bit String from the passed in object
+ *
+ * @param obj a DERBitString or an object that can be converted into one.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ * @return a DERBitString instance, or null.
+ */
+ public static DERBitString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERBitString)
+ {
+ return (DERBitString)obj;
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return a Bit String from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ * @return a DERBitString instance, or null.
+ */
+ public static DERBitString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERBitString)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return fromOctetString(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ protected DERBitString(
+ byte data,
+ int padBits)
+ {
+ this.data = new byte[1];
+ this.data[0] = data;
+ this.padBits = padBits;
+ }
+
+ /**
+ * @param data the octets making up the bit string.
+ * @param padBits the number of extra bits at the end of the string.
+ */
+ public DERBitString(
+ byte[] data,
+ int padBits)
+ {
+ this.data = data;
+ this.padBits = padBits;
+ }
+
+ public DERBitString(
+ byte[] data)
+ {
+ this(data, 0);
+ }
+
+ public DERBitString(
+ int value)
+ {
+ this.data = getBytes(value);
+ this.padBits = getPadBits(value);
+ }
+
+ public DERBitString(
+ ASN1Encodable obj)
+ throws IOException
+ {
+ this.data = obj.toASN1Primitive().getEncoded(ASN1Encoding.DER);
+ this.padBits = 0;
+ }
+
+ public byte[] getBytes()
+ {
+ return data;
+ }
+
+ public int getPadBits()
+ {
+ return padBits;
+ }
+
+
+ /**
+ * @return the value of the bit string as an int (truncating if necessary)
+ */
+ public int intValue()
+ {
+ int value = 0;
+
+ for (int i = 0; i != data.length && i != 4; i++)
+ {
+ value |= (data[i] & 0xff) << (8 * i);
+ }
+
+ return value;
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(data.length + 1) + data.length + 1;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ byte[] bytes = new byte[getBytes().length + 1];
+
+ bytes[0] = (byte)getPadBits();
+ System.arraycopy(getBytes(), 0, bytes, 1, bytes.length - 1);
+
+ out.writeEncoded(BERTags.BIT_STRING, bytes);
+ }
+
+ public int hashCode()
+ {
+ return padBits ^ Arrays.hashCode(data);
+ }
+
+ protected boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERBitString))
+ {
+ return false;
+ }
+
+ DERBitString other = (DERBitString)o;
+
+ return this.padBits == other.padBits
+ && Arrays.areEqual(this.data, other.data);
+ }
+
+ public String getString()
+ {
+ StringBuffer buf = new StringBuffer("#");
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ try
+ {
+ aOut.writeObject(this);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("internal error encoding BitString");
+ }
+
+ byte[] string = bOut.toByteArray();
+
+ for (int i = 0; i != string.length; i++)
+ {
+ buf.append(table[(string[i] >>> 4) & 0xf]);
+ buf.append(table[string[i] & 0xf]);
+ }
+
+ return buf.toString();
+ }
+
+ public String toString()
+ {
+ return getString();
+ }
+
+ static DERBitString fromOctetString(byte[] bytes)
+ {
+ if (bytes.length < 1)
+ {
+ throw new IllegalArgumentException("truncated BIT STRING detected");
+ }
+
+ int padBits = bytes[0];
+ byte[] data = new byte[bytes.length - 1];
+
+ if (data.length != 0)
+ {
+ System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
+ }
+
+ return new DERBitString(data, padBits);
+ }
+
+ static DERBitString fromInputStream(int length, InputStream stream)
+ throws IOException
+ {
+ if (length < 1)
+ {
+ throw new IllegalArgumentException("truncated BIT STRING detected");
+ }
+
+ int padBits = stream.read();
+ byte[] data = new byte[length - 1];
+
+ if (data.length != 0)
+ {
+ if (Streams.readFully(stream, data) != data.length)
+ {
+ throw new EOFException("EOF encountered in middle of BIT STRING");
+ }
+ }
+
+ return new DERBitString(data, padBits);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERBoolean.java b/core/src/main/java/org/spongycastle/asn1/DERBoolean.java
new file mode 100644
index 00000000..9e101c45
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERBoolean.java
@@ -0,0 +1,22 @@
+package org.spongycastle.asn1;
+
+/**
+ * @deprecated use ASN1Boolean
+ */
+public class DERBoolean
+ extends ASN1Boolean
+{
+ /**
+ * @deprecated use getInstance(boolean) method.
+ * @param value
+ */
+ public DERBoolean(boolean value)
+ {
+ super(value);
+ }
+
+ DERBoolean(byte[] value)
+ {
+ super(value);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DEREncodableVector.java b/core/src/main/java/org/spongycastle/asn1/DEREncodableVector.java
new file mode 100644
index 00000000..f381a6c1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DEREncodableVector.java
@@ -0,0 +1,18 @@
+package org.spongycastle.asn1;
+
+/**
+ * a general class for building up a vector of DER encodable objects -
+ * this will eventually be superceded by ASN1EncodableVector so you should
+ * use that class in preference.
+ */
+public class DEREncodableVector
+ extends ASN1EncodableVector
+{
+ /**
+ * @deprecated use ASN1EncodableVector instead.
+ */
+ public DEREncodableVector()
+ {
+
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DEREnumerated.java b/core/src/main/java/org/spongycastle/asn1/DEREnumerated.java
new file mode 100644
index 00000000..833c091b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DEREnumerated.java
@@ -0,0 +1,37 @@
+package org.spongycastle.asn1;
+
+import java.math.BigInteger;
+
+/**
+ * @deprecated Use ASN1Enumerated instead of this.
+ */
+public class DEREnumerated
+ extends ASN1Enumerated
+{
+ /**
+ * @param bytes the value of this enumerated as an encoded BigInteger (signed).
+ * @deprecated use ASN1Enumerated
+ */
+ DEREnumerated(byte[] bytes)
+ {
+ super(bytes);
+ }
+
+ /**
+ * @param value the value of this enumerated.
+ * @deprecated use ASN1Enumerated
+ */
+ public DEREnumerated(BigInteger value)
+ {
+ super(value);
+ }
+
+ /**
+ * @param value the value of this enumerated.
+ * @deprecated use ASN1Enumerated
+ */
+ public DEREnumerated(int value)
+ {
+ super(value);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERExternal.java b/core/src/main/java/org/spongycastle/asn1/DERExternal.java
new file mode 100644
index 00000000..5cf48f0f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERExternal.java
@@ -0,0 +1,294 @@
+package org.spongycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * Class representing the DER-type External
+ */
+public class DERExternal
+ extends ASN1Primitive
+{
+ private ASN1ObjectIdentifier directReference;
+ private ASN1Integer indirectReference;
+ private ASN1Primitive dataValueDescriptor;
+ private int encoding;
+ private ASN1Primitive externalContent;
+
+ public DERExternal(ASN1EncodableVector vector)
+ {
+ int offset = 0;
+
+ ASN1Primitive enc = getObjFromVector(vector, offset);
+ if (enc instanceof ASN1ObjectIdentifier)
+ {
+ directReference = (ASN1ObjectIdentifier)enc;
+ offset++;
+ enc = getObjFromVector(vector, offset);
+ }
+ if (enc instanceof ASN1Integer)
+ {
+ indirectReference = (ASN1Integer) enc;
+ offset++;
+ enc = getObjFromVector(vector, offset);
+ }
+ if (!(enc instanceof DERTaggedObject))
+ {
+ dataValueDescriptor = (ASN1Primitive) enc;
+ offset++;
+ enc = getObjFromVector(vector, offset);
+ }
+
+ if (vector.size() != offset + 1)
+ {
+ throw new IllegalArgumentException("input vector too large");
+ }
+
+ if (!(enc instanceof DERTaggedObject))
+ {
+ throw new IllegalArgumentException("No tagged object found in vector. Structure doesn't seem to be of type External");
+ }
+ DERTaggedObject obj = (DERTaggedObject)enc;
+ setEncoding(obj.getTagNo());
+ externalContent = obj.getObject();
+ }
+
+ private ASN1Primitive getObjFromVector(ASN1EncodableVector v, int index)
+ {
+ if (v.size() <= index)
+ {
+ throw new IllegalArgumentException("too few objects in input vector");
+ }
+
+ return v.get(index).toASN1Primitive();
+ }
+ /**
+ * Creates a new instance of DERExternal
+ * See X.690 for more informations about the meaning of these parameters
+ * @param directReference The direct reference or <code>null</code> if not set.
+ * @param indirectReference The indirect reference or <code>null</code> if not set.
+ * @param dataValueDescriptor The data value descriptor or <code>null</code> if not set.
+ * @param externalData The external data in its encoded form.
+ */
+ public DERExternal(ASN1ObjectIdentifier directReference, ASN1Integer indirectReference, ASN1Primitive dataValueDescriptor, DERTaggedObject externalData)
+ {
+ this(directReference, indirectReference, dataValueDescriptor, externalData.getTagNo(), externalData.toASN1Primitive());
+ }
+
+ /**
+ * Creates a new instance of DERExternal.
+ * See X.690 for more informations about the meaning of these parameters
+ * @param directReference The direct reference or <code>null</code> if not set.
+ * @param indirectReference The indirect reference or <code>null</code> if not set.
+ * @param dataValueDescriptor The data value descriptor or <code>null</code> if not set.
+ * @param encoding The encoding to be used for the external data
+ * @param externalData The external data
+ */
+ public DERExternal(ASN1ObjectIdentifier directReference, ASN1Integer indirectReference, ASN1Primitive dataValueDescriptor, int encoding, ASN1Primitive externalData)
+ {
+ setDirectReference(directReference);
+ setIndirectReference(indirectReference);
+ setDataValueDescriptor(dataValueDescriptor);
+ setEncoding(encoding);
+ setExternalContent(externalData.toASN1Primitive());
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode()
+ {
+ int ret = 0;
+ if (directReference != null)
+ {
+ ret = directReference.hashCode();
+ }
+ if (indirectReference != null)
+ {
+ ret ^= indirectReference.hashCode();
+ }
+ if (dataValueDescriptor != null)
+ {
+ ret ^= dataValueDescriptor.hashCode();
+ }
+ ret ^= externalContent.hashCode();
+ return ret;
+ }
+
+ boolean isConstructed()
+ {
+ return true;
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ return this.getEncoded().length;
+ }
+
+ /* (non-Javadoc)
+ * @see org.spongycastle.asn1.ASN1Primitive#encode(org.spongycastle.asn1.DEROutputStream)
+ */
+ void encode(ASN1OutputStream out)
+ throws IOException
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ if (directReference != null)
+ {
+ baos.write(directReference.getEncoded(ASN1Encoding.DER));
+ }
+ if (indirectReference != null)
+ {
+ baos.write(indirectReference.getEncoded(ASN1Encoding.DER));
+ }
+ if (dataValueDescriptor != null)
+ {
+ baos.write(dataValueDescriptor.getEncoded(ASN1Encoding.DER));
+ }
+ DERTaggedObject obj = new DERTaggedObject(true, encoding, externalContent);
+ baos.write(obj.getEncoded(ASN1Encoding.DER));
+ out.writeEncoded(BERTags.CONSTRUCTED, BERTags.EXTERNAL, baos.toByteArray());
+ }
+
+ /* (non-Javadoc)
+ * @see org.spongycastle.asn1.ASN1Primitive#asn1Equals(org.spongycastle.asn1.ASN1Primitive)
+ */
+ boolean asn1Equals(ASN1Primitive o)
+ {
+ if (!(o instanceof DERExternal))
+ {
+ return false;
+ }
+ if (this == o)
+ {
+ return true;
+ }
+ DERExternal other = (DERExternal)o;
+ if (directReference != null)
+ {
+ if (other.directReference == null || !other.directReference.equals(directReference))
+ {
+ return false;
+ }
+ }
+ if (indirectReference != null)
+ {
+ if (other.indirectReference == null || !other.indirectReference.equals(indirectReference))
+ {
+ return false;
+ }
+ }
+ if (dataValueDescriptor != null)
+ {
+ if (other.dataValueDescriptor == null || !other.dataValueDescriptor.equals(dataValueDescriptor))
+ {
+ return false;
+ }
+ }
+ return externalContent.equals(other.externalContent);
+ }
+
+ /**
+ * Returns the data value descriptor
+ * @return The descriptor
+ */
+ public ASN1Primitive getDataValueDescriptor()
+ {
+ return dataValueDescriptor;
+ }
+
+ /**
+ * Returns the direct reference of the external element
+ * @return The reference
+ */
+ public ASN1ObjectIdentifier getDirectReference()
+ {
+ return directReference;
+ }
+
+ /**
+ * Returns the encoding of the content. Valid values are
+ * <ul>
+ * <li><code>0</code> single-ASN1-type</li>
+ * <li><code>1</code> OCTET STRING</li>
+ * <li><code>2</code> BIT STRING</li>
+ * </ul>
+ * @return The encoding
+ */
+ public int getEncoding()
+ {
+ return encoding;
+ }
+
+ /**
+ * Returns the content of this element
+ * @return The content
+ */
+ public ASN1Primitive getExternalContent()
+ {
+ return externalContent;
+ }
+
+ /**
+ * Returns the indirect reference of this element
+ * @return The reference
+ */
+ public ASN1Integer getIndirectReference()
+ {
+ return indirectReference;
+ }
+
+ /**
+ * Sets the data value descriptor
+ * @param dataValueDescriptor The descriptor
+ */
+ private void setDataValueDescriptor(ASN1Primitive dataValueDescriptor)
+ {
+ this.dataValueDescriptor = dataValueDescriptor;
+ }
+
+ /**
+ * Sets the direct reference of the external element
+ * @param directReferemce The reference
+ */
+ private void setDirectReference(ASN1ObjectIdentifier directReferemce)
+ {
+ this.directReference = directReferemce;
+ }
+
+ /**
+ * Sets the encoding of the content. Valid values are
+ * <ul>
+ * <li><code>0</code> single-ASN1-type</li>
+ * <li><code>1</code> OCTET STRING</li>
+ * <li><code>2</code> BIT STRING</li>
+ * </ul>
+ * @param encoding The encoding
+ */
+ private void setEncoding(int encoding)
+ {
+ if (encoding < 0 || encoding > 2)
+ {
+ throw new IllegalArgumentException("invalid encoding value: " + encoding);
+ }
+ this.encoding = encoding;
+ }
+
+ /**
+ * Sets the content of this element
+ * @param externalContent The content
+ */
+ private void setExternalContent(ASN1Primitive externalContent)
+ {
+ this.externalContent = externalContent;
+ }
+
+ /**
+ * Sets the indirect reference of this element
+ * @param indirectReference The reference
+ */
+ private void setIndirectReference(ASN1Integer indirectReference)
+ {
+ this.indirectReference = indirectReference;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERExternalParser.java b/core/src/main/java/org/spongycastle/asn1/DERExternalParser.java
new file mode 100644
index 00000000..39f46b52
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERExternalParser.java
@@ -0,0 +1,52 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+public class DERExternalParser
+ implements ASN1Encodable, InMemoryRepresentable
+{
+ private ASN1StreamParser _parser;
+
+ /**
+ *
+ */
+ public DERExternalParser(ASN1StreamParser parser)
+ {
+ this._parser = parser;
+ }
+
+ public ASN1Encodable readObject()
+ throws IOException
+ {
+ return _parser.readObject();
+ }
+
+ public ASN1Primitive getLoadedObject()
+ throws IOException
+ {
+ try
+ {
+ return new DERExternal(_parser.readVector());
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new ASN1Exception(e.getMessage(), e);
+ }
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ try
+ {
+ return getLoadedObject();
+ }
+ catch (IOException ioe)
+ {
+ throw new ASN1ParsingException("unable to get DER object", ioe);
+ }
+ catch (IllegalArgumentException ioe)
+ {
+ throw new ASN1ParsingException("unable to get DER object", ioe);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERFactory.java b/core/src/main/java/org/spongycastle/asn1/DERFactory.java
new file mode 100644
index 00000000..2900ddb9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERFactory.java
@@ -0,0 +1,17 @@
+package org.spongycastle.asn1;
+
+class DERFactory
+{
+ static final ASN1Sequence EMPTY_SEQUENCE = new DERSequence();
+ static final ASN1Set EMPTY_SET = new DERSet();
+
+ static ASN1Sequence createSequence(ASN1EncodableVector v)
+ {
+ return v.size() < 1 ? EMPTY_SEQUENCE : new DLSequence(v);
+ }
+
+ static ASN1Set createSet(ASN1EncodableVector v)
+ {
+ return v.size() < 1 ? EMPTY_SET : new DLSet(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERGeneralString.java b/core/src/main/java/org/spongycastle/asn1/DERGeneralString.java
new file mode 100644
index 00000000..1c8435c7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERGeneralString.java
@@ -0,0 +1,110 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Strings;
+
+public class DERGeneralString
+ extends ASN1Primitive
+ implements ASN1String
+{
+ private byte[] string;
+
+ public static DERGeneralString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERGeneralString)
+ {
+ return (DERGeneralString) obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (DERGeneralString)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ public static DERGeneralString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERGeneralString)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new DERGeneralString(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ DERGeneralString(byte[] string)
+ {
+ this.string = string;
+ }
+
+ public DERGeneralString(String string)
+ {
+ this.string = Strings.toByteArray(string);
+ }
+
+ public String getString()
+ {
+ return Strings.fromByteArray(string);
+ }
+
+ public String toString()
+ {
+ return getString();
+ }
+
+ public byte[] getOctets()
+ {
+ return Arrays.clone(string);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
+ }
+
+ void encode(ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.GENERAL_STRING, string);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(string);
+ }
+
+ boolean asn1Equals(ASN1Primitive o)
+ {
+ if (!(o instanceof DERGeneralString))
+ {
+ return false;
+ }
+ DERGeneralString s = (DERGeneralString)o;
+
+ return Arrays.areEqual(string, s.string);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERGeneralizedTime.java b/core/src/main/java/org/spongycastle/asn1/DERGeneralizedTime.java
new file mode 100644
index 00000000..b61f6b0d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERGeneralizedTime.java
@@ -0,0 +1,28 @@
+package org.spongycastle.asn1;
+
+import java.util.Date;
+
+/**
+ * DER Generalized time object.
+ */
+public class DERGeneralizedTime
+ extends ASN1GeneralizedTime
+{
+
+ DERGeneralizedTime(byte[] bytes)
+ {
+ super(bytes);
+ }
+
+ public DERGeneralizedTime(Date time)
+ {
+ super(time);
+ }
+
+ public DERGeneralizedTime(String time)
+ {
+ super(time);
+ }
+
+ // TODO: create proper DER encoding.
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERGenerator.java b/core/src/main/java/org/spongycastle/asn1/DERGenerator.java
new file mode 100644
index 00000000..da6d6545
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERGenerator.java
@@ -0,0 +1,119 @@
+package org.spongycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.spongycastle.util.io.Streams;
+
+public abstract class DERGenerator
+ extends ASN1Generator
+{
+ private boolean _tagged = false;
+ private boolean _isExplicit;
+ private int _tagNo;
+
+ protected DERGenerator(
+ OutputStream out)
+ {
+ super(out);
+ }
+
+ public DERGenerator(
+ OutputStream out,
+ int tagNo,
+ boolean isExplicit)
+ {
+ super(out);
+
+ _tagged = true;
+ _isExplicit = isExplicit;
+ _tagNo = tagNo;
+ }
+
+ private void writeLength(
+ OutputStream out,
+ int length)
+ throws IOException
+ {
+ if (length > 127)
+ {
+ int size = 1;
+ int val = length;
+
+ while ((val >>>= 8) != 0)
+ {
+ size++;
+ }
+
+ out.write((byte)(size | 0x80));
+
+ for (int i = (size - 1) * 8; i >= 0; i -= 8)
+ {
+ out.write((byte)(length >> i));
+ }
+ }
+ else
+ {
+ out.write((byte)length);
+ }
+ }
+
+ void writeDEREncoded(
+ OutputStream out,
+ int tag,
+ byte[] bytes)
+ throws IOException
+ {
+ out.write(tag);
+ writeLength(out, bytes.length);
+ out.write(bytes);
+ }
+
+ void writeDEREncoded(
+ int tag,
+ byte[] bytes)
+ throws IOException
+ {
+ if (_tagged)
+ {
+ int tagNum = _tagNo | BERTags.TAGGED;
+
+ if (_isExplicit)
+ {
+ int newTag = _tagNo | BERTags.CONSTRUCTED | BERTags.TAGGED;
+
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ writeDEREncoded(bOut, tag, bytes);
+
+ writeDEREncoded(_out, newTag, bOut.toByteArray());
+ }
+ else
+ {
+ if ((tag & BERTags.CONSTRUCTED) != 0)
+ {
+ writeDEREncoded(_out, tagNum | BERTags.CONSTRUCTED, bytes);
+ }
+ else
+ {
+ writeDEREncoded(_out, tagNum, bytes);
+ }
+ }
+ }
+ else
+ {
+ writeDEREncoded(_out, tag, bytes);
+ }
+ }
+
+ void writeDEREncoded(
+ OutputStream out,
+ int tag,
+ InputStream in)
+ throws IOException
+ {
+ writeDEREncoded(out, tag, Streams.readAll(in));
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERIA5String.java b/core/src/main/java/org/spongycastle/asn1/DERIA5String.java
new file mode 100644
index 00000000..1ff1c7ac
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERIA5String.java
@@ -0,0 +1,189 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Strings;
+
+/**
+ * DER IA5String object - this is an ascii string.
+ */
+public class DERIA5String
+ extends ASN1Primitive
+ implements ASN1String
+{
+ private byte[] string;
+
+ /**
+ * return a IA5 string from the passed in object
+ *
+ * @param obj a DERIA5String or an object that can be converted into one.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ * @return a DERIA5String instance, or null.
+ */
+ public static DERIA5String getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERIA5String)
+ {
+ return (DERIA5String)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (DERIA5String)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an IA5 String from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ * @return a DERIA5String instance, or null.
+ */
+ public static DERIA5String getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERIA5String)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new DERIA5String(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ /**
+ * basic constructor - with bytes.
+ * @param string the byte encoding of the characters making up the string.
+ */
+ DERIA5String(
+ byte[] string)
+ {
+ this.string = string;
+ }
+
+ /**
+ * basic constructor - without validation.
+ * @param string the base string to use..
+ */
+ public DERIA5String(
+ String string)
+ {
+ this(string, false);
+ }
+
+ /**
+ * Constructor with optional validation.
+ *
+ * @param string the base string to wrap.
+ * @param validate whether or not to check the string.
+ * @throws IllegalArgumentException if validate is true and the string
+ * contains characters that should not be in an IA5String.
+ */
+ public DERIA5String(
+ String string,
+ boolean validate)
+ {
+ if (string == null)
+ {
+ throw new NullPointerException("string cannot be null");
+ }
+ if (validate && !isIA5String(string))
+ {
+ throw new IllegalArgumentException("string contains illegal characters");
+ }
+
+ this.string = Strings.toByteArray(string);
+ }
+
+ public String getString()
+ {
+ return Strings.fromByteArray(string);
+ }
+
+ public String toString()
+ {
+ return getString();
+ }
+
+ public byte[] getOctets()
+ {
+ return Arrays.clone(string);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.IA5_STRING, string);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(string);
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERIA5String))
+ {
+ return false;
+ }
+
+ DERIA5String s = (DERIA5String)o;
+
+ return Arrays.areEqual(string, s.string);
+ }
+
+ /**
+ * return true if the passed in String can be represented without
+ * loss as an IA5String, false otherwise.
+ *
+ * @param str the string to check.
+ * @return true if character set in IA5String set, false otherwise.
+ */
+ public static boolean isIA5String(
+ String str)
+ {
+ for (int i = str.length() - 1; i >= 0; i--)
+ {
+ char ch = str.charAt(i);
+
+ if (ch > 0x007f)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERInteger.java b/core/src/main/java/org/spongycastle/asn1/DERInteger.java
new file mode 100644
index 00000000..3cc465d3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERInteger.java
@@ -0,0 +1,30 @@
+package org.spongycastle.asn1;
+
+import java.math.BigInteger;
+
+/**
+ * @deprecated Use ASN1Integer instead of this,
+ */
+public class DERInteger
+ extends ASN1Integer
+{
+ /**
+ * Constructor from a byte array containing a signed representation of the number.
+ *
+ * @param bytes a byte array containing the signed number.A copy is made of the byte array.
+ */
+ public DERInteger(byte[] bytes)
+ {
+ super(bytes, true);
+ }
+
+ public DERInteger(BigInteger value)
+ {
+ super(value);
+ }
+
+ public DERInteger(long value)
+ {
+ super(value);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERNull.java b/core/src/main/java/org/spongycastle/asn1/DERNull.java
new file mode 100644
index 00000000..f093cd27
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERNull.java
@@ -0,0 +1,38 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * A NULL object.
+ */
+public class DERNull
+ extends ASN1Null
+{
+ public static final DERNull INSTANCE = new DERNull();
+
+ private static final byte[] zeroBytes = new byte[0];
+
+ /**
+ * @deprecated use DERNull.INSTANCE
+ */
+ public DERNull()
+ {
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 2;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.NULL, zeroBytes);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERNumericString.java b/core/src/main/java/org/spongycastle/asn1/DERNumericString.java
new file mode 100644
index 00000000..3835927d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERNumericString.java
@@ -0,0 +1,189 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Strings;
+
+/**
+ * DER NumericString object - this is an ascii string of characters {0,1,2,3,4,5,6,7,8,9, }.
+ */
+public class DERNumericString
+ extends ASN1Primitive
+ implements ASN1String
+{
+ private byte[] string;
+
+ /**
+ * return a Numeric string from the passed in object
+ *
+ * @param obj a DERNumericString or an object that can be converted into one.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ * @return a DERNumericString instance, or null
+ */
+ public static DERNumericString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERNumericString)
+ {
+ return (DERNumericString)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (DERNumericString)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an Numeric String from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ * @return a DERNumericString instance, or null.
+ */
+ public static DERNumericString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERNumericString)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new DERNumericString(ASN1OctetString.getInstance(o).getOctets());
+ }
+ }
+
+ /**
+ * basic constructor - with bytes.
+ */
+ DERNumericString(
+ byte[] string)
+ {
+ this.string = string;
+ }
+
+ /**
+ * basic constructor - without validation..
+ */
+ public DERNumericString(
+ String string)
+ {
+ this(string, false);
+ }
+
+ /**
+ * Constructor with optional validation.
+ *
+ * @param string the base string to wrap.
+ * @param validate whether or not to check the string.
+ * @throws IllegalArgumentException if validate is true and the string
+ * contains characters that should not be in a NumericString.
+ */
+ public DERNumericString(
+ String string,
+ boolean validate)
+ {
+ if (validate && !isNumericString(string))
+ {
+ throw new IllegalArgumentException("string contains illegal characters");
+ }
+
+ this.string = Strings.toByteArray(string);
+ }
+
+ public String getString()
+ {
+ return Strings.fromByteArray(string);
+ }
+
+ public String toString()
+ {
+ return getString();
+ }
+
+ public byte[] getOctets()
+ {
+ return Arrays.clone(string);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.NUMERIC_STRING, string);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(string);
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERNumericString))
+ {
+ return false;
+ }
+
+ DERNumericString s = (DERNumericString)o;
+
+ return Arrays.areEqual(string, s.string);
+ }
+
+ /**
+ * Return true if the string can be represented as a NumericString ('0'..'9', ' ')
+ *
+ * @param str string to validate.
+ * @return true if numeric, fale otherwise.
+ */
+ public static boolean isNumericString(
+ String str)
+ {
+ for (int i = str.length() - 1; i >= 0; i--)
+ {
+ char ch = str.charAt(i);
+
+ if (ch > 0x007f)
+ {
+ return false;
+ }
+
+ if (('0' <= ch && ch <= '9') || ch == ' ')
+ {
+ continue;
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERObjectIdentifier.java b/core/src/main/java/org/spongycastle/asn1/DERObjectIdentifier.java
new file mode 100644
index 00000000..cf75640b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERObjectIdentifier.java
@@ -0,0 +1,24 @@
+package org.spongycastle.asn1;
+
+/**
+ *
+ * @deprecated Use ASN1ObjectIdentifier instead of this,
+ */
+public class DERObjectIdentifier
+ extends ASN1ObjectIdentifier
+{
+ public DERObjectIdentifier(String identifier)
+ {
+ super(identifier);
+ }
+
+ DERObjectIdentifier(byte[] bytes)
+ {
+ super(bytes);
+ }
+
+ DERObjectIdentifier(ASN1ObjectIdentifier oid, String branch)
+ {
+ super(oid, branch);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DEROctetString.java b/core/src/main/java/org/spongycastle/asn1/DEROctetString.java
new file mode 100644
index 00000000..68ae920a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DEROctetString.java
@@ -0,0 +1,48 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+public class DEROctetString
+ extends ASN1OctetString
+{
+ /**
+ * @param string the octets making up the octet string.
+ */
+ public DEROctetString(
+ byte[] string)
+ {
+ super(string);
+ }
+
+ public DEROctetString(
+ ASN1Encodable obj)
+ throws IOException
+ {
+ super(obj.toASN1Primitive().getEncoded(ASN1Encoding.DER));
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.OCTET_STRING, string);
+ }
+
+ static void encode(
+ DEROutputStream derOut,
+ byte[] bytes)
+ throws IOException
+ {
+ derOut.writeEncoded(BERTags.OCTET_STRING, bytes);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DEROctetStringParser.java b/core/src/main/java/org/spongycastle/asn1/DEROctetStringParser.java
new file mode 100644
index 00000000..59a82cd8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DEROctetStringParser.java
@@ -0,0 +1,39 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class DEROctetStringParser
+ implements ASN1OctetStringParser
+{
+ private DefiniteLengthInputStream stream;
+
+ DEROctetStringParser(
+ DefiniteLengthInputStream stream)
+ {
+ this.stream = stream;
+ }
+
+ public InputStream getOctetStream()
+ {
+ return stream;
+ }
+
+ public ASN1Primitive getLoadedObject()
+ throws IOException
+ {
+ return new DEROctetString(stream.toByteArray());
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ try
+ {
+ return getLoadedObject();
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException("IOException converting stream to byte array: " + e.getMessage(), e);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DEROutputStream.java b/core/src/main/java/org/spongycastle/asn1/DEROutputStream.java
new file mode 100644
index 00000000..b94fc7b0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DEROutputStream.java
@@ -0,0 +1,41 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Stream that outputs encoding based on distinguished encoding rules.
+ */
+public class DEROutputStream
+ extends ASN1OutputStream
+{
+ public DEROutputStream(
+ OutputStream os)
+ {
+ super(os);
+ }
+
+ public void writeObject(
+ ASN1Encodable obj)
+ throws IOException
+ {
+ if (obj != null)
+ {
+ obj.toASN1Primitive().toDERObject().encode(this);
+ }
+ else
+ {
+ throw new IOException("null object detected");
+ }
+ }
+
+ ASN1OutputStream getDERSubStream()
+ {
+ return this;
+ }
+
+ ASN1OutputStream getDLSubStream()
+ {
+ return this;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERPrintableString.java b/core/src/main/java/org/spongycastle/asn1/DERPrintableString.java
new file mode 100644
index 00000000..cda1c666
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERPrintableString.java
@@ -0,0 +1,216 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Strings;
+
+/**
+ * DER PrintableString object.
+ */
+public class DERPrintableString
+ extends ASN1Primitive
+ implements ASN1String
+{
+ private byte[] string;
+
+ /**
+ * return a printable string from the passed in object.
+ *
+ * @param obj a DERPrintableString or an object that can be converted into one.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ * @return a DERPrintableString instance, or null.
+ */
+ public static DERPrintableString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERPrintableString)
+ {
+ return (DERPrintableString)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (DERPrintableString)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return a Printable String from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ * @return a DERPrintableString instance, or null.
+ */
+ public static DERPrintableString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERPrintableString)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new DERPrintableString(ASN1OctetString.getInstance(o).getOctets());
+ }
+ }
+
+ /**
+ * basic constructor - byte encoded string.
+ */
+ DERPrintableString(
+ byte[] string)
+ {
+ this.string = string;
+ }
+
+ /**
+ * basic constructor - this does not validate the string
+ */
+ public DERPrintableString(
+ String string)
+ {
+ this(string, false);
+ }
+
+ /**
+ * Constructor with optional validation.
+ *
+ * @param string the base string to wrap.
+ * @param validate whether or not to check the string.
+ * @throws IllegalArgumentException if validate is true and the string
+ * contains characters that should not be in a PrintableString.
+ */
+ public DERPrintableString(
+ String string,
+ boolean validate)
+ {
+ if (validate && !isPrintableString(string))
+ {
+ throw new IllegalArgumentException("string contains illegal characters");
+ }
+
+ this.string = Strings.toByteArray(string);
+ }
+
+ public String getString()
+ {
+ return Strings.fromByteArray(string);
+ }
+
+ public byte[] getOctets()
+ {
+ return Arrays.clone(string);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.PRINTABLE_STRING, string);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(string);
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERPrintableString))
+ {
+ return false;
+ }
+
+ DERPrintableString s = (DERPrintableString)o;
+
+ return Arrays.areEqual(string, s.string);
+ }
+
+ public String toString()
+ {
+ return getString();
+ }
+
+ /**
+ * return true if the passed in String can be represented without
+ * loss as a PrintableString, false otherwise.
+ *
+ * @return true if in printable set, false otherwise.
+ */
+ public static boolean isPrintableString(
+ String str)
+ {
+ for (int i = str.length() - 1; i >= 0; i--)
+ {
+ char ch = str.charAt(i);
+
+ if (ch > 0x007f)
+ {
+ return false;
+ }
+
+ if ('a' <= ch && ch <= 'z')
+ {
+ continue;
+ }
+
+ if ('A' <= ch && ch <= 'Z')
+ {
+ continue;
+ }
+
+ if ('0' <= ch && ch <= '9')
+ {
+ continue;
+ }
+
+ switch (ch)
+ {
+ case ' ':
+ case '\'':
+ case '(':
+ case ')':
+ case '+':
+ case '-':
+ case '.':
+ case ':':
+ case '=':
+ case '?':
+ case '/':
+ case ',':
+ continue;
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERSequence.java b/core/src/main/java/org/spongycastle/asn1/DERSequence.java
new file mode 100644
index 00000000..df171ca5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERSequence.java
@@ -0,0 +1,98 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+public class DERSequence
+ extends ASN1Sequence
+{
+ private int bodyLength = -1;
+
+ /**
+ * create an empty sequence
+ */
+ public DERSequence()
+ {
+ }
+
+ /**
+ * create a sequence containing one object
+ */
+ public DERSequence(
+ ASN1Encodable obj)
+ {
+ super(obj);
+ }
+
+ /**
+ * create a sequence containing a vector of objects.
+ */
+ public DERSequence(
+ ASN1EncodableVector v)
+ {
+ super(v);
+ }
+
+ /**
+ * create a sequence containing an array of objects.
+ */
+ public DERSequence(
+ ASN1Encodable[] array)
+ {
+ super(array);
+ }
+
+ private int getBodyLength()
+ throws IOException
+ {
+ if (bodyLength < 0)
+ {
+ int length = 0;
+
+ for (Enumeration e = this.getObjects(); e.hasMoreElements();)
+ {
+ Object obj = e.nextElement();
+
+ length += ((ASN1Encodable)obj).toASN1Primitive().toDERObject().encodedLength();
+ }
+
+ bodyLength = length;
+ }
+
+ return bodyLength;
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ int length = getBodyLength();
+
+ return 1 + StreamUtil.calculateBodyLength(length) + length;
+ }
+
+ /*
+ * A note on the implementation:
+ * <p>
+ * As DER requires the constructed, definite-length model to
+ * be used for structured types, this varies slightly from the
+ * ASN.1 descriptions given. Rather than just outputting SEQUENCE,
+ * we also have to specify CONSTRUCTED, and the objects length.
+ */
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ ASN1OutputStream dOut = out.getDERSubStream();
+ int length = getBodyLength();
+
+ out.write(BERTags.SEQUENCE | BERTags.CONSTRUCTED);
+ out.writeLength(length);
+
+ for (Enumeration e = this.getObjects(); e.hasMoreElements();)
+ {
+ Object obj = e.nextElement();
+
+ dOut.writeObject((ASN1Encodable)obj);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERSequenceGenerator.java b/core/src/main/java/org/spongycastle/asn1/DERSequenceGenerator.java
new file mode 100644
index 00000000..39c43032
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERSequenceGenerator.java
@@ -0,0 +1,45 @@
+package org.spongycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class DERSequenceGenerator
+ extends DERGenerator
+{
+ private final ByteArrayOutputStream _bOut = new ByteArrayOutputStream();
+
+ public DERSequenceGenerator(
+ OutputStream out)
+ throws IOException
+ {
+ super(out);
+ }
+
+ public DERSequenceGenerator(
+ OutputStream out,
+ int tagNo,
+ boolean isExplicit)
+ throws IOException
+ {
+ super(out, tagNo, isExplicit);
+ }
+
+ public void addObject(
+ ASN1Encodable object)
+ throws IOException
+ {
+ object.toASN1Primitive().encode(new DEROutputStream(_bOut));
+ }
+
+ public OutputStream getRawOutputStream()
+ {
+ return _bOut;
+ }
+
+ public void close()
+ throws IOException
+ {
+ writeDEREncoded(BERTags.CONSTRUCTED | BERTags.SEQUENCE, _bOut.toByteArray());
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERSequenceParser.java b/core/src/main/java/org/spongycastle/asn1/DERSequenceParser.java
new file mode 100644
index 00000000..95f66e6f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERSequenceParser.java
@@ -0,0 +1,38 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+public class DERSequenceParser
+ implements ASN1SequenceParser
+{
+ private ASN1StreamParser _parser;
+
+ DERSequenceParser(ASN1StreamParser parser)
+ {
+ this._parser = parser;
+ }
+
+ public ASN1Encodable readObject()
+ throws IOException
+ {
+ return _parser.readObject();
+ }
+
+ public ASN1Primitive getLoadedObject()
+ throws IOException
+ {
+ return new DERSequence(_parser.readVector());
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ try
+ {
+ return getLoadedObject();
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException(e.getMessage());
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERSet.java b/core/src/main/java/org/spongycastle/asn1/DERSet.java
new file mode 100644
index 00000000..b504a8fd
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERSet.java
@@ -0,0 +1,108 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+/**
+ * A DER encoded set object
+ */
+public class DERSet
+ extends ASN1Set
+{
+ private int bodyLength = -1;
+
+ /**
+ * create an empty set
+ */
+ public DERSet()
+ {
+ }
+
+ /**
+ * @param obj - a single object that makes up the set.
+ */
+ public DERSet(
+ ASN1Encodable obj)
+ {
+ super(obj);
+ }
+
+ /**
+ * @param v - a vector of objects making up the set.
+ */
+ public DERSet(
+ ASN1EncodableVector v)
+ {
+ super(v, true);
+ }
+
+ /**
+ * create a set from an array of objects.
+ */
+ public DERSet(
+ ASN1Encodable[] a)
+ {
+ super(a, true);
+ }
+
+ DERSet(
+ ASN1EncodableVector v,
+ boolean doSort)
+ {
+ super(v, doSort);
+ }
+
+ private int getBodyLength()
+ throws IOException
+ {
+ if (bodyLength < 0)
+ {
+ int length = 0;
+
+ for (Enumeration e = this.getObjects(); e.hasMoreElements();)
+ {
+ Object obj = e.nextElement();
+
+ length += ((ASN1Encodable)obj).toASN1Primitive().toDERObject().encodedLength();
+ }
+
+ bodyLength = length;
+ }
+
+ return bodyLength;
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ int length = getBodyLength();
+
+ return 1 + StreamUtil.calculateBodyLength(length) + length;
+ }
+
+ /*
+ * A note on the implementation:
+ * <p>
+ * As DER requires the constructed, definite-length model to
+ * be used for structured types, this varies slightly from the
+ * ASN.1 descriptions given. Rather than just outputting SET,
+ * we also have to specify CONSTRUCTED, and the objects length.
+ */
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ ASN1OutputStream dOut = out.getDERSubStream();
+ int length = getBodyLength();
+
+ out.write(BERTags.SET | BERTags.CONSTRUCTED);
+ out.writeLength(length);
+
+ for (Enumeration e = this.getObjects(); e.hasMoreElements();)
+ {
+ Object obj = e.nextElement();
+
+ dOut.writeObject((ASN1Encodable)obj);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERSetParser.java b/core/src/main/java/org/spongycastle/asn1/DERSetParser.java
new file mode 100644
index 00000000..adae3041
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERSetParser.java
@@ -0,0 +1,38 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+public class DERSetParser
+ implements ASN1SetParser
+{
+ private ASN1StreamParser _parser;
+
+ DERSetParser(ASN1StreamParser parser)
+ {
+ this._parser = parser;
+ }
+
+ public ASN1Encodable readObject()
+ throws IOException
+ {
+ return _parser.readObject();
+ }
+
+ public ASN1Primitive getLoadedObject()
+ throws IOException
+ {
+ return new DERSet(_parser.readVector(), false);
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ try
+ {
+ return getLoadedObject();
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException(e.getMessage(), e);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERT61String.java b/core/src/main/java/org/spongycastle/asn1/DERT61String.java
new file mode 100644
index 00000000..bdcff1d2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERT61String.java
@@ -0,0 +1,151 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Strings;
+
+/**
+ * DER T61String (also the teletex string), try not to use this if you don't need to. The standard support the encoding for
+ * this has been withdrawn.
+ */
+public class DERT61String
+ extends ASN1Primitive
+ implements ASN1String
+{
+ private byte[] string;
+
+ /**
+ * return a T61 string from the passed in object.
+ *
+ * @param obj a DERT61String or an object that can be converted into one.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ * @return a DERT61String instance, or null
+ */
+ public static DERT61String getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERT61String)
+ {
+ return (DERT61String)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (DERT61String)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an T61 String from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ * @return a DERT61String instance, or null
+ */
+ public static DERT61String getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERT61String)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new DERT61String(ASN1OctetString.getInstance(o).getOctets());
+ }
+ }
+
+ /**
+ * basic constructor - string encoded as a sequence of bytes.
+ *
+ * @param string the byte encoding of the string to be wrapped.
+ */
+ public DERT61String(
+ byte[] string)
+ {
+ this.string = string;
+ }
+
+ /**
+ * basic constructor - with string 8 bit assumed.
+ *
+ * @param string the string to be wrapped.
+ */
+ public DERT61String(
+ String string)
+ {
+ this(Strings.toByteArray(string));
+ }
+
+ /**
+ * Decode the encoded string and return it, 8 bit encoding assumed.
+ * @return the decoded String
+ */
+ public String getString()
+ {
+ return Strings.fromByteArray(string);
+ }
+
+ public String toString()
+ {
+ return getString();
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.T61_STRING, string);
+ }
+
+ /**
+ * Return the encoded string as a byte array.
+ * @return the actual bytes making up the encoded body of the T61 string.
+ */
+ public byte[] getOctets()
+ {
+ return Arrays.clone(string);
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERT61String))
+ {
+ return false;
+ }
+
+ return Arrays.areEqual(string, ((DERT61String)o).string);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(string);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERT61UTF8String.java b/core/src/main/java/org/spongycastle/asn1/DERT61UTF8String.java
new file mode 100644
index 00000000..4496cb70
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERT61UTF8String.java
@@ -0,0 +1,154 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Strings;
+
+/**
+ * DER T61String (also the teletex string) - a "modern" encapsulation that uses UTF-8. If at all possible, avoid this one! It's only for emergencies.
+ * Use UTF8String instead.
+ */
+public class DERT61UTF8String
+ extends ASN1Primitive
+ implements ASN1String
+{
+ private byte[] string;
+
+ /**
+ * return a T61 string from the passed in object. UTF-8 Encoding is assumed in this case.
+ *
+ * @param obj a DERT61UTF8String or an object that can be converted into one.
+ * @throws IllegalArgumentException if the object cannot be converted.
+ * @return a DERT61UTF8String instance, or null
+ */
+ public static DERT61UTF8String getInstance(
+ Object obj)
+ {
+ if (obj instanceof DERT61String)
+ {
+ return new DERT61UTF8String(((DERT61String)obj).getOctets());
+ }
+
+ if (obj == null || obj instanceof DERT61UTF8String)
+ {
+ return (DERT61UTF8String)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return new DERT61UTF8String(((DERT61String)fromByteArray((byte[])obj)).getOctets());
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an T61 String from a tagged object. UTF-8 encoding is assumed in this case.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @throws IllegalArgumentException if the tagged object cannot
+ * be converted.
+ * @return a DERT61UTF8String instance, or null
+ */
+ public static DERT61UTF8String getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERT61String || o instanceof DERT61UTF8String)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new DERT61UTF8String(ASN1OctetString.getInstance(o).getOctets());
+ }
+ }
+
+ /**
+ * basic constructor - string encoded as a sequence of bytes.
+ */
+ public DERT61UTF8String(
+ byte[] string)
+ {
+ this.string = string;
+ }
+
+ /**
+ * basic constructor - with string UTF8 conversion assumed.
+ */
+ public DERT61UTF8String(
+ String string)
+ {
+ this(Strings.toUTF8ByteArray(string));
+ }
+
+ /**
+ * Decode the encoded string and return it, UTF8 assumed.
+ *
+ * @return the decoded String
+ */
+ public String getString()
+ {
+ return Strings.fromUTF8ByteArray(string);
+ }
+
+ public String toString()
+ {
+ return getString();
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.T61_STRING, string);
+ }
+
+ /**
+ * Return the encoded string as a byte array.
+ *
+ * @return the actual bytes making up the encoded body of the T61 string.
+ */
+ public byte[] getOctets()
+ {
+ return Arrays.clone(string);
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERT61UTF8String))
+ {
+ return false;
+ }
+
+ return Arrays.areEqual(string, ((DERT61UTF8String)o).string);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(string);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERTaggedObject.java b/core/src/main/java/org/spongycastle/asn1/DERTaggedObject.java
new file mode 100644
index 00000000..3ea7d984
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERTaggedObject.java
@@ -0,0 +1,118 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * DER TaggedObject - in ASN.1 notation this is any object preceded by
+ * a [n] where n is some number - these are assumed to follow the construction
+ * rules (as with sequences).
+ */
+public class DERTaggedObject
+ extends ASN1TaggedObject
+{
+ private static final byte[] ZERO_BYTES = new byte[0];
+
+ /**
+ * @param explicit true if an explicitly tagged object.
+ * @param tagNo the tag number for this object.
+ * @param obj the tagged object.
+ */
+ public DERTaggedObject(
+ boolean explicit,
+ int tagNo,
+ ASN1Encodable obj)
+ {
+ super(explicit, tagNo, obj);
+ }
+
+ public DERTaggedObject(int tagNo, ASN1Encodable encodable)
+ {
+ super(true, tagNo, encodable);
+ }
+
+ boolean isConstructed()
+ {
+ if (!empty)
+ {
+ if (explicit)
+ {
+ return true;
+ }
+ else
+ {
+ ASN1Primitive primitive = obj.toASN1Primitive().toDERObject();
+
+ return primitive.isConstructed();
+ }
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ if (!empty)
+ {
+ ASN1Primitive primitive = obj.toASN1Primitive().toDERObject();
+ int length = primitive.encodedLength();
+
+ if (explicit)
+ {
+ return StreamUtil.calculateTagLength(tagNo) + StreamUtil.calculateBodyLength(length) + length;
+ }
+ else
+ {
+ // header length already in calculation
+ length = length - 1;
+
+ return StreamUtil.calculateTagLength(tagNo) + length;
+ }
+ }
+ else
+ {
+ return StreamUtil.calculateTagLength(tagNo) + 1;
+ }
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ if (!empty)
+ {
+ ASN1Primitive primitive = obj.toASN1Primitive().toDERObject();
+
+ if (explicit)
+ {
+ out.writeTag(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo);
+ out.writeLength(primitive.encodedLength());
+ out.writeObject(primitive);
+ }
+ else
+ {
+ //
+ // need to mark constructed types...
+ //
+ int flags;
+ if (primitive.isConstructed())
+ {
+ flags = BERTags.CONSTRUCTED | BERTags.TAGGED;
+ }
+ else
+ {
+ flags = BERTags.TAGGED;
+ }
+
+ out.writeTag(flags, tagNo);
+ out.writeImplicitObject(primitive);
+ }
+ }
+ else
+ {
+ out.writeEncoded(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo, ZERO_BYTES);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERTags.java b/core/src/main/java/org/spongycastle/asn1/DERTags.java
new file mode 100644
index 00000000..4a5dd664
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERTags.java
@@ -0,0 +1,9 @@
+package org.spongycastle.asn1;
+
+/**
+ * @deprecated use BERTags
+ */
+public interface DERTags
+ extends BERTags
+{
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERUTCTime.java b/core/src/main/java/org/spongycastle/asn1/DERUTCTime.java
new file mode 100644
index 00000000..32260f28
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERUTCTime.java
@@ -0,0 +1,27 @@
+package org.spongycastle.asn1;
+
+import java.util.Date;
+
+/**
+ * DER UTC time object.
+ */
+public class DERUTCTime
+ extends ASN1UTCTime
+{
+ DERUTCTime(byte[] bytes)
+ {
+ super(bytes);
+ }
+
+ public DERUTCTime(Date time)
+ {
+ super(time);
+ }
+
+ public DERUTCTime(String time)
+ {
+ super(time);
+ }
+
+ // TODO: create proper DER encoding.
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERUTF8String.java b/core/src/main/java/org/spongycastle/asn1/DERUTF8String.java
new file mode 100644
index 00000000..6bb235d8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERUTF8String.java
@@ -0,0 +1,135 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Strings;
+
+/**
+ * DER UTF8String object.
+ */
+public class DERUTF8String
+ extends ASN1Primitive
+ implements ASN1String
+{
+ private byte[] string;
+
+ /**
+ * Return an UTF8 string from the passed in object.
+ *
+ * @param obj a DERUTF8String or an object that can be converted into one.
+ * @exception IllegalArgumentException
+ * if the object cannot be converted.
+ * @return a DERUTF8String instance, or null
+ */
+ public static DERUTF8String getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof DERUTF8String)
+ {
+ return (DERUTF8String)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (DERUTF8String)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ /**
+ * Return an UTF8 String from a tagged object.
+ *
+ * @param obj
+ * the tagged object holding the object we want
+ * @param explicit
+ * true if the object is meant to be explicitly tagged false
+ * otherwise.
+ * @exception IllegalArgumentException
+ * if the tagged object cannot be converted.
+ * @return a DERUTF8String instance, or null
+ */
+ public static DERUTF8String getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERUTF8String)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new DERUTF8String(ASN1OctetString.getInstance(o).getOctets());
+ }
+ }
+
+ /**
+ * Basic constructor - byte encoded string.
+ */
+ DERUTF8String(byte[] string)
+ {
+ this.string = string;
+ }
+
+ /**
+ * Basic constructor
+ */
+ public DERUTF8String(String string)
+ {
+ this.string = Strings.toUTF8ByteArray(string);
+ }
+
+ public String getString()
+ {
+ return Strings.fromUTF8ByteArray(string);
+ }
+
+ public String toString()
+ {
+ return getString();
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(string);
+ }
+
+ boolean asn1Equals(ASN1Primitive o)
+ {
+ if (!(o instanceof DERUTF8String))
+ {
+ return false;
+ }
+
+ DERUTF8String s = (DERUTF8String)o;
+
+ return Arrays.areEqual(string, s.string);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
+ }
+
+ void encode(ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.UTF8_STRING, string);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERUniversalString.java b/core/src/main/java/org/spongycastle/asn1/DERUniversalString.java
new file mode 100644
index 00000000..cc613510
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERUniversalString.java
@@ -0,0 +1,151 @@
+package org.spongycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import org.spongycastle.util.Arrays;
+
+/**
+ * DER UniversalString object.
+ */
+public class DERUniversalString
+ extends ASN1Primitive
+ implements ASN1String
+{
+ private static final char[] table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+ private byte[] string;
+
+ /**
+ * return a Universal String from the passed in object.
+ *
+ * @param obj a DERUniversalString or an object that can be converted into one.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ * @return a DERUniversalString instance, or null
+ */
+ public static DERUniversalString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERUniversalString)
+ {
+ return (DERUniversalString)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (DERUniversalString)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return a Universal String from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ * @return a DERUniversalString instance, or null
+ */
+ public static DERUniversalString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERUniversalString)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new DERUniversalString(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ /**
+ * basic constructor - byte encoded string.
+ */
+ public DERUniversalString(
+ byte[] string)
+ {
+ this.string = string;
+ }
+
+ public String getString()
+ {
+ StringBuffer buf = new StringBuffer("#");
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ try
+ {
+ aOut.writeObject(this);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("internal error encoding BitString");
+ }
+
+ byte[] string = bOut.toByteArray();
+
+ for (int i = 0; i != string.length; i++)
+ {
+ buf.append(table[(string[i] >>> 4) & 0xf]);
+ buf.append(table[string[i] & 0xf]);
+ }
+
+ return buf.toString();
+ }
+
+ public String toString()
+ {
+ return getString();
+ }
+
+ public byte[] getOctets()
+ {
+ return string;
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.UNIVERSAL_STRING, this.getOctets());
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERUniversalString))
+ {
+ return false;
+ }
+
+ return Arrays.areEqual(string, ((DERUniversalString)o).string);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(string);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DERVisibleString.java b/core/src/main/java/org/spongycastle/asn1/DERVisibleString.java
new file mode 100644
index 00000000..b44ddb79
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DERVisibleString.java
@@ -0,0 +1,141 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Strings;
+
+/**
+ * DER VisibleString object encoding ISO 646 (ASCII) character code points 32 to 126.
+ * <p>
+ * Explicit character set escape sequences are not allowed.
+ * </p>
+ */
+public class DERVisibleString
+ extends ASN1Primitive
+ implements ASN1String
+{
+ private byte[] string;
+
+ /**
+ * Return a Visible String from the passed in object.
+ *
+ * @param obj a DERVisibleString or an object that can be converted into one.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ * @return a DERVisibleString instance, or null
+ */
+ public static DERVisibleString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERVisibleString)
+ {
+ return (DERVisibleString)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (DERVisibleString)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * Return a Visible String from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ * @return a DERVisibleString instance, or null
+ */
+ public static DERVisibleString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERVisibleString)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new DERVisibleString(ASN1OctetString.getInstance(o).getOctets());
+ }
+ }
+
+ /**
+ * Basic constructor - byte encoded string.
+ */
+ DERVisibleString(
+ byte[] string)
+ {
+ this.string = string;
+ }
+
+ /**
+ * Basic constructor
+ */
+ public DERVisibleString(
+ String string)
+ {
+ this.string = Strings.toByteArray(string);
+ }
+
+ public String getString()
+ {
+ return Strings.fromByteArray(string);
+ }
+
+ public String toString()
+ {
+ return getString();
+ }
+
+ public byte[] getOctets()
+ {
+ return Arrays.clone(string);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.VISIBLE_STRING, this.string);
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERVisibleString))
+ {
+ return false;
+ }
+
+ return Arrays.areEqual(string, ((DERVisibleString)o).string);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(string);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DLOutputStream.java b/core/src/main/java/org/spongycastle/asn1/DLOutputStream.java
new file mode 100644
index 00000000..cb401e83
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DLOutputStream.java
@@ -0,0 +1,31 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Stream that outputs encoding based on definite length.
+ */
+public class DLOutputStream
+ extends ASN1OutputStream
+{
+ public DLOutputStream(
+ OutputStream os)
+ {
+ super(os);
+ }
+
+ public void writeObject(
+ ASN1Encodable obj)
+ throws IOException
+ {
+ if (obj != null)
+ {
+ obj.toASN1Primitive().toDLObject().encode(this);
+ }
+ else
+ {
+ throw new IOException("null object detected");
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DLSequence.java b/core/src/main/java/org/spongycastle/asn1/DLSequence.java
new file mode 100644
index 00000000..1c621cba
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DLSequence.java
@@ -0,0 +1,101 @@
+package org.spongycastle.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
+ */
+ public DLSequence()
+ {
+ }
+
+ /**
+ * Create a sequence containing one object
+ */
+ public DLSequence(
+ ASN1Encodable obj)
+ {
+ super(obj);
+ }
+
+ /**
+ * Create a sequence containing a vector of objects.
+ */
+ public DLSequence(
+ ASN1EncodableVector v)
+ {
+ super(v);
+ }
+
+ /**
+ * Create a sequence containing an array of objects.
+ */
+ public DLSequence(
+ ASN1Encodable[] array)
+ {
+ super(array);
+ }
+
+ private int getBodyLength()
+ throws IOException
+ {
+ if (bodyLength < 0)
+ {
+ int length = 0;
+
+ for (Enumeration e = this.getObjects(); e.hasMoreElements();)
+ {
+ Object obj = e.nextElement();
+
+ length += ((ASN1Encodable)obj).toASN1Primitive().toDLObject().encodedLength();
+ }
+
+ bodyLength = length;
+ }
+
+ return bodyLength;
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ int length = getBodyLength();
+
+ return 1 + StreamUtil.calculateBodyLength(length) + length;
+ }
+
+ /**
+ * A note on the implementation:
+ * <p>
+ * As DL requires the constructed, definite-length model to
+ * be used for structured types, this varies slightly from the
+ * ASN.1 descriptions given. Rather than just outputting SEQUENCE,
+ * we also have to specify CONSTRUCTED, and the objects length.
+ */
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ 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();
+
+ dOut.writeObject((ASN1Encodable)obj);
+ }
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/asn1/DLSet.java b/core/src/main/java/org/spongycastle/asn1/DLSet.java
new file mode 100644
index 00000000..071c29e2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DLSet.java
@@ -0,0 +1,146 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+/**
+ * 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
+{
+ private int bodyLength = -1;
+
+ /**
+ * create an empty set
+ */
+ public DLSet()
+ {
+ }
+
+ /**
+ * @param obj - a single object that makes up the set.
+ */
+ public DLSet(
+ ASN1Encodable obj)
+ {
+ super(obj);
+ }
+
+ /**
+ * @param v - a vector of objects making up the set.
+ */
+ public DLSet(
+ ASN1EncodableVector v)
+ {
+ super(v, false);
+ }
+
+ /**
+ * create a set from an array of objects.
+ */
+ public DLSet(
+ ASN1Encodable[] a)
+ {
+ super(a, false);
+ }
+
+ private int getBodyLength()
+ throws IOException
+ {
+ if (bodyLength < 0)
+ {
+ int length = 0;
+
+ for (Enumeration e = this.getObjects(); e.hasMoreElements();)
+ {
+ Object obj = e.nextElement();
+
+ length += ((ASN1Encodable)obj).toASN1Primitive().toDLObject().encodedLength();
+ }
+
+ bodyLength = length;
+ }
+
+ return bodyLength;
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ int length = getBodyLength();
+
+ return 1 + StreamUtil.calculateBodyLength(length) + length;
+ }
+
+ /**
+ * A note on the implementation:
+ * <p>
+ * As DL requires the constructed, definite-length model to
+ * be used for structured types, this varies slightly from the
+ * ASN.1 descriptions given. Rather than just outputting SET,
+ * we also have to specify CONSTRUCTED, and the objects length.
+ */
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ 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();
+
+ dOut.writeObject((ASN1Encodable)obj);
+ }
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/asn1/DLTaggedObject.java b/core/src/main/java/org/spongycastle/asn1/DLTaggedObject.java
new file mode 100644
index 00000000..505c8cca
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DLTaggedObject.java
@@ -0,0 +1,112 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * Definite Length TaggedObject - in ASN.1 notation this is any object preceded by
+ * a [n] where n is some number - these are assumed to follow the construction
+ * rules (as with sequences).
+ */
+public class DLTaggedObject
+ extends ASN1TaggedObject
+{
+ private static final byte[] ZERO_BYTES = new byte[0];
+
+ /**
+ * @param explicit true if an explicitly tagged object.
+ * @param tagNo the tag number for this object.
+ * @param obj the tagged object.
+ */
+ public DLTaggedObject(
+ boolean explicit,
+ int tagNo,
+ ASN1Encodable obj)
+ {
+ super(explicit, tagNo, obj);
+ }
+
+ boolean isConstructed()
+ {
+ if (!empty)
+ {
+ if (explicit)
+ {
+ return true;
+ }
+ else
+ {
+ ASN1Primitive primitive = obj.toASN1Primitive().toDLObject();
+
+ return primitive.isConstructed();
+ }
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ if (!empty)
+ {
+ int length = obj.toASN1Primitive().toDLObject().encodedLength();
+
+ if (explicit)
+ {
+ return StreamUtil.calculateTagLength(tagNo) + StreamUtil.calculateBodyLength(length) + length;
+ }
+ else
+ {
+ // header length already in calculation
+ length = length - 1;
+
+ return StreamUtil.calculateTagLength(tagNo) + length;
+ }
+ }
+ else
+ {
+ return StreamUtil.calculateTagLength(tagNo) + 1;
+ }
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ if (!empty)
+ {
+ ASN1Primitive primitive = obj.toASN1Primitive().toDLObject();
+
+ if (explicit)
+ {
+ out.writeTag(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo);
+ out.writeLength(primitive.encodedLength());
+ out.writeObject(primitive);
+ }
+ else
+ {
+ //
+ // need to mark constructed types...
+ //
+ int flags;
+ if (primitive.isConstructed())
+ {
+ flags = BERTags.CONSTRUCTED | BERTags.TAGGED;
+ }
+ else
+ {
+ flags = BERTags.TAGGED;
+ }
+
+ out.writeTag(flags, tagNo);
+ out.writeImplicitObject(primitive);
+ }
+ }
+ else
+ {
+ out.writeEncoded(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo, ZERO_BYTES);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/DefiniteLengthInputStream.java b/core/src/main/java/org/spongycastle/asn1/DefiniteLengthInputStream.java
new file mode 100644
index 00000000..711f173d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/DefiniteLengthInputStream.java
@@ -0,0 +1,105 @@
+package org.spongycastle.asn1;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.spongycastle.util.io.Streams;
+
+class DefiniteLengthInputStream
+ extends LimitedInputStream
+{
+ private static final byte[] EMPTY_BYTES = new byte[0];
+
+ private final int _originalLength;
+ private int _remaining;
+
+ DefiniteLengthInputStream(
+ InputStream in,
+ int length)
+ {
+ super(in, length);
+
+ if (length < 0)
+ {
+ throw new IllegalArgumentException("negative lengths not allowed");
+ }
+
+ this._originalLength = length;
+ this._remaining = length;
+
+ if (length == 0)
+ {
+ setParentEofDetect(true);
+ }
+ }
+
+ int getRemaining()
+ {
+ return _remaining;
+ }
+
+ public int read()
+ throws IOException
+ {
+ if (_remaining == 0)
+ {
+ return -1;
+ }
+
+ int b = _in.read();
+
+ if (b < 0)
+ {
+ throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
+ }
+
+ if (--_remaining == 0)
+ {
+ setParentEofDetect(true);
+ }
+
+ return b;
+ }
+
+ public int read(byte[] buf, int off, int len)
+ throws IOException
+ {
+ if (_remaining == 0)
+ {
+ return -1;
+ }
+
+ int toRead = Math.min(len, _remaining);
+ int numRead = _in.read(buf, off, toRead);
+
+ if (numRead < 0)
+ {
+ throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
+ }
+
+ if ((_remaining -= numRead) == 0)
+ {
+ setParentEofDetect(true);
+ }
+
+ return numRead;
+ }
+
+ byte[] toByteArray()
+ throws IOException
+ {
+ if (_remaining == 0)
+ {
+ return EMPTY_BYTES;
+ }
+
+ byte[] bytes = new byte[_remaining];
+ if ((_remaining -= Streams.readFully(_in, bytes)) != 0)
+ {
+ throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
+ }
+ setParentEofDetect(true);
+ return bytes;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/InMemoryRepresentable.java b/core/src/main/java/org/spongycastle/asn1/InMemoryRepresentable.java
new file mode 100644
index 00000000..9f052204
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/InMemoryRepresentable.java
@@ -0,0 +1,16 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * Interface implemented by objects that can be converted from streaming to in-memory objects.
+ */
+public interface InMemoryRepresentable
+{
+ /**
+ * Get the in-memory representation of the ASN.1 object.
+ * @throws IOException for bad input data.
+ */
+ ASN1Primitive getLoadedObject()
+ throws IOException;
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/IndefiniteLengthInputStream.java b/core/src/main/java/org/spongycastle/asn1/IndefiniteLengthInputStream.java
new file mode 100644
index 00000000..39e003a4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/IndefiniteLengthInputStream.java
@@ -0,0 +1,111 @@
+package org.spongycastle.asn1;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+
+class IndefiniteLengthInputStream
+ extends LimitedInputStream
+{
+ private int _b1;
+ private int _b2;
+ private boolean _eofReached = false;
+ private boolean _eofOn00 = true;
+
+ IndefiniteLengthInputStream(
+ InputStream in,
+ int limit)
+ throws IOException
+ {
+ super(in, limit);
+
+ _b1 = in.read();
+ _b2 = in.read();
+
+ if (_b2 < 0)
+ {
+ // Corrupted stream
+ throw new EOFException();
+ }
+
+ checkForEof();
+ }
+
+ void setEofOn00(
+ boolean eofOn00)
+ {
+ _eofOn00 = eofOn00;
+ checkForEof();
+ }
+
+ private boolean checkForEof()
+ {
+ if (!_eofReached && _eofOn00 && (_b1 == 0x00 && _b2 == 0x00))
+ {
+ _eofReached = true;
+ setParentEofDetect(true);
+ }
+ return _eofReached;
+ }
+
+ public int read(byte[] b, int off, int len)
+ throws IOException
+ {
+ // Only use this optimisation if we aren't checking for 00
+ if (_eofOn00 || len < 3)
+ {
+ return super.read(b, off, len);
+ }
+
+ if (_eofReached)
+ {
+ return -1;
+ }
+
+ int numRead = _in.read(b, off + 2, len - 2);
+
+ if (numRead < 0)
+ {
+ // Corrupted stream
+ throw new EOFException();
+ }
+
+ b[off] = (byte)_b1;
+ b[off + 1] = (byte)_b2;
+
+ _b1 = _in.read();
+ _b2 = _in.read();
+
+ if (_b2 < 0)
+ {
+ // Corrupted stream
+ throw new EOFException();
+ }
+
+ return numRead + 2;
+ }
+
+ public int read()
+ throws IOException
+ {
+ if (checkForEof())
+ {
+ return -1;
+ }
+
+ int b = _in.read();
+
+ if (b < 0)
+ {
+ // Corrupted stream
+ throw new EOFException();
+ }
+
+ int v = _b1;
+
+ _b1 = _b2;
+ _b2 = b;
+
+ return v;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/LazyConstructionEnumeration.java b/core/src/main/java/org/spongycastle/asn1/LazyConstructionEnumeration.java
new file mode 100644
index 00000000..036dbc21
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/LazyConstructionEnumeration.java
@@ -0,0 +1,43 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+class LazyConstructionEnumeration
+ implements Enumeration
+{
+ private ASN1InputStream aIn;
+ private Object nextObj;
+
+ public LazyConstructionEnumeration(byte[] encoded)
+ {
+ aIn = new ASN1InputStream(encoded, true);
+ nextObj = readObject();
+ }
+
+ public boolean hasMoreElements()
+ {
+ return nextObj != null;
+ }
+
+ public Object nextElement()
+ {
+ Object o = nextObj;
+
+ nextObj = readObject();
+
+ return o;
+ }
+
+ private Object readObject()
+ {
+ try
+ {
+ return aIn.readObject();
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException("malformed DER construction: " + e, e);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/LazyEncodedSequence.java b/core/src/main/java/org/spongycastle/asn1/LazyEncodedSequence.java
new file mode 100644
index 00000000..70f13853
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/LazyEncodedSequence.java
@@ -0,0 +1,109 @@
+package org.spongycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+/**
+ * Note: this class is for processing DER/DL encoded sequences only.
+ */
+class LazyEncodedSequence
+ extends ASN1Sequence
+{
+ private byte[] encoded;
+
+ LazyEncodedSequence(
+ byte[] encoded)
+ throws IOException
+ {
+ this.encoded = encoded;
+ }
+
+ private void parse()
+ {
+ Enumeration en = new LazyConstructionEnumeration(encoded);
+
+ while (en.hasMoreElements())
+ {
+ seq.addElement(en.nextElement());
+ }
+
+ encoded = null;
+ }
+
+ public synchronized ASN1Encodable getObjectAt(int index)
+ {
+ if (encoded != null)
+ {
+ parse();
+ }
+
+ return super.getObjectAt(index);
+ }
+
+ public synchronized Enumeration getObjects()
+ {
+ if (encoded == null)
+ {
+ return super.getObjects();
+ }
+
+ return new LazyConstructionEnumeration(encoded);
+ }
+
+ public synchronized int size()
+ {
+ if (encoded != null)
+ {
+ parse();
+ }
+
+ return super.size();
+ }
+
+ ASN1Primitive toDERObject()
+ {
+ if (encoded != null)
+ {
+ parse();
+ }
+
+ return super.toDERObject();
+ }
+
+ ASN1Primitive toDLObject()
+ {
+ if (encoded != null)
+ {
+ parse();
+ }
+
+ return super.toDLObject();
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ if (encoded != null)
+ {
+ return 1 + StreamUtil.calculateBodyLength(encoded.length) + encoded.length;
+ }
+ else
+ {
+ return super.toDLObject().encodedLength();
+ }
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ if (encoded != null)
+ {
+ out.writeEncoded(BERTags.SEQUENCE | BERTags.CONSTRUCTED, encoded);
+ }
+ else
+ {
+ super.toDLObject().encode(out);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/LimitedInputStream.java b/core/src/main/java/org/spongycastle/asn1/LimitedInputStream.java
new file mode 100644
index 00000000..cc3273bf
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/LimitedInputStream.java
@@ -0,0 +1,32 @@
+package org.spongycastle.asn1;
+
+import java.io.InputStream;
+
+abstract class LimitedInputStream
+ extends InputStream
+{
+ protected final InputStream _in;
+ private int _limit;
+
+ LimitedInputStream(
+ InputStream in,
+ int limit)
+ {
+ this._in = in;
+ this._limit = limit;
+ }
+
+ int getRemaining()
+ {
+ // TODO: maybe one day this can become more accurate
+ return _limit;
+ }
+
+ protected void setParentEofDetect(boolean on)
+ {
+ if (_in instanceof IndefiniteLengthInputStream)
+ {
+ ((IndefiniteLengthInputStream)_in).setEofOn00(on);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/OIDTokenizer.java b/core/src/main/java/org/spongycastle/asn1/OIDTokenizer.java
new file mode 100644
index 00000000..e618f4b9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/OIDTokenizer.java
@@ -0,0 +1,48 @@
+package org.spongycastle.asn1;
+
+/**
+ * class for breaking up an OID into it's component tokens, ala
+ * java.util.StringTokenizer. We need this class as some of the
+ * lightweight Java environment don't support classes like
+ * StringTokenizer.
+ */
+public class OIDTokenizer
+{
+ private String oid;
+ private int index;
+
+ public OIDTokenizer(
+ String oid)
+ {
+ this.oid = oid;
+ this.index = 0;
+ }
+
+ public boolean hasMoreTokens()
+ {
+ return (index != -1);
+ }
+
+ public String nextToken()
+ {
+ if (index == -1)
+ {
+ return null;
+ }
+
+ String token;
+ int end = oid.indexOf('.', index);
+
+ if (end == -1)
+ {
+ token = oid.substring(index);
+ index = -1;
+ return token;
+ }
+
+ token = oid.substring(index, end);
+
+ index = end + 1;
+ return token;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/StreamUtil.java b/core/src/main/java/org/spongycastle/asn1/StreamUtil.java
new file mode 100644
index 00000000..cf92c511
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/StreamUtil.java
@@ -0,0 +1,114 @@
+package org.spongycastle.asn1;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.channels.FileChannel;
+
+class StreamUtil
+{
+ private static final long MAX_MEMORY = Runtime.getRuntime().maxMemory();
+
+ /**
+ * Find out possible longest length...
+ *
+ * @param in input stream of interest
+ * @return length calculation or MAX_VALUE.
+ */
+ static int findLimit(InputStream in)
+ {
+ if (in instanceof LimitedInputStream)
+ {
+ return ((LimitedInputStream)in).getRemaining();
+ }
+ else if (in instanceof ASN1InputStream)
+ {
+ return ((ASN1InputStream)in).getLimit();
+ }
+ else if (in instanceof ByteArrayInputStream)
+ {
+ return ((ByteArrayInputStream)in).available();
+ }
+ else if (in instanceof FileInputStream)
+ {
+ try
+ {
+ FileChannel channel = ((FileInputStream)in).getChannel();
+ long size = (channel != null) ? channel.size() : Integer.MAX_VALUE;
+
+ if (size < Integer.MAX_VALUE)
+ {
+ return (int)size;
+ }
+ }
+ catch (IOException e)
+ {
+ // ignore - they'll find out soon enough!
+ }
+ }
+
+ if (MAX_MEMORY > Integer.MAX_VALUE)
+ {
+ return Integer.MAX_VALUE;
+ }
+
+ return (int)MAX_MEMORY;
+ }
+
+ static int calculateBodyLength(
+ int length)
+ {
+ int count = 1;
+
+ if (length > 127)
+ {
+ int size = 1;
+ int val = length;
+
+ while ((val >>>= 8) != 0)
+ {
+ size++;
+ }
+
+ for (int i = (size - 1) * 8; i >= 0; i -= 8)
+ {
+ count++;
+ }
+ }
+
+ return count;
+ }
+
+ static int calculateTagLength(int tagNo)
+ throws IOException
+ {
+ int length = 1;
+
+ if (tagNo >= 31)
+ {
+ if (tagNo < 128)
+ {
+ length++;
+ }
+ else
+ {
+ byte[] stack = new byte[5];
+ int pos = stack.length;
+
+ stack[--pos] = (byte)(tagNo & 0x7F);
+
+ do
+ {
+ tagNo >>= 7;
+ stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
+ }
+ while (tagNo > 127);
+
+ length += stack.length - pos;
+ }
+ }
+
+ return length;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/bc/BCObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/bc/BCObjectIdentifiers.java
new file mode 100644
index 00000000..9e0b2848
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/bc/BCObjectIdentifiers.java
@@ -0,0 +1,71 @@
+package org.spongycastle.asn1.bc;
+
+import org.spongycastle.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 = bc.branch("1");
+
+ /**
+ * SHA-1(1)
+ * <p>
+ * 1.3.6.1.4.1.22554.1.1
+ */
+ public static final ASN1ObjectIdentifier bc_pbe_sha1 = bc_pbe.branch("1");
+
+ /** 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)
+ */
+ /** 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");
+
+ /** 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))
+ */
+ /** 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");
+
+ /** 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/core/src/main/java/org/spongycastle/asn1/bsi/BSIObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/bsi/BSIObjectIdentifiers.java
new file mode 100644
index 00000000..e9bd0ca2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/bsi/BSIObjectIdentifiers.java
@@ -0,0 +1,35 @@
+package org.spongycastle.asn1.bsi;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+
+/**
+ * See https://www.bsi.bund.de/cae/servlet/contentblob/471398/publicationFile/30615/BSI-TR-03111_pdf.pdf
+ */
+public interface BSIObjectIdentifiers
+{
+ static final ASN1ObjectIdentifier bsi_de = new ASN1ObjectIdentifier("0.4.0.127.0.7");
+
+ /* 0.4.0.127.0.7.1.1 */
+ static final ASN1ObjectIdentifier id_ecc = bsi_de.branch("1.1");
+
+ /* 0.4.0.127.0.7.1.1.4.1 */
+ static final ASN1ObjectIdentifier ecdsa_plain_signatures = id_ecc.branch("4.1");
+
+ /* 0.4.0.127.0.7.1.1.4.1.1 */
+ static final ASN1ObjectIdentifier ecdsa_plain_SHA1 = ecdsa_plain_signatures.branch("1");
+
+ /* 0.4.0.127.0.7.1.1.4.1.2 */
+ static final ASN1ObjectIdentifier ecdsa_plain_SHA224 = ecdsa_plain_signatures.branch("2");
+
+ /* 0.4.0.127.0.7.1.1.4.1.3 */
+ static final ASN1ObjectIdentifier ecdsa_plain_SHA256 = ecdsa_plain_signatures.branch("3");
+
+ /* 0.4.0.127.0.7.1.1.4.1.4 */
+ static final ASN1ObjectIdentifier ecdsa_plain_SHA384 = ecdsa_plain_signatures.branch("4");
+
+ /* 0.4.0.127.0.7.1.1.4.1.5 */
+ static final ASN1ObjectIdentifier ecdsa_plain_SHA512 = ecdsa_plain_signatures.branch("5");
+
+ /* 0.4.0.127.0.7.1.1.4.1.6 */
+ static final ASN1ObjectIdentifier ecdsa_plain_RIPEMD160 = ecdsa_plain_signatures.branch("6");
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/CAKeyUpdAnnContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/CAKeyUpdAnnContent.java
new file mode 100644
index 00000000..ddc4c252
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/CAKeyUpdAnnContent.java
@@ -0,0 +1,80 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class CAKeyUpdAnnContent
+ extends ASN1Object
+{
+ private CMPCertificate oldWithNew;
+ private CMPCertificate newWithOld;
+ private CMPCertificate newWithNew;
+
+ private CAKeyUpdAnnContent(ASN1Sequence seq)
+ {
+ oldWithNew = CMPCertificate.getInstance(seq.getObjectAt(0));
+ newWithOld = CMPCertificate.getInstance(seq.getObjectAt(1));
+ newWithNew = CMPCertificate.getInstance(seq.getObjectAt(2));
+ }
+
+ public static CAKeyUpdAnnContent getInstance(Object o)
+ {
+ if (o instanceof CAKeyUpdAnnContent)
+ {
+ return (CAKeyUpdAnnContent)o;
+ }
+
+ if (o != null)
+ {
+ return new CAKeyUpdAnnContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CAKeyUpdAnnContent(CMPCertificate oldWithNew, CMPCertificate newWithOld, CMPCertificate newWithNew)
+ {
+ this.oldWithNew = oldWithNew;
+ this.newWithOld = newWithOld;
+ this.newWithNew = newWithNew;
+ }
+
+ public CMPCertificate getOldWithNew()
+ {
+ return oldWithNew;
+ }
+
+ public CMPCertificate getNewWithOld()
+ {
+ return newWithOld;
+ }
+
+ public CMPCertificate getNewWithNew()
+ {
+ return newWithNew;
+ }
+
+ /**
+ * <pre>
+ * CAKeyUpdAnnContent ::= SEQUENCE {
+ * oldWithNew CMPCertificate, -- old pub signed with new priv
+ * newWithOld CMPCertificate, -- new pub signed with old priv
+ * newWithNew CMPCertificate -- new pub signed with new priv
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(oldWithNew);
+ v.add(newWithOld);
+ v.add(newWithNew);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/CMPCertificate.java b/core/src/main/java/org/spongycastle/asn1/cmp/CMPCertificate.java
new file mode 100644
index 00000000..22dcb3b8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/CMPCertificate.java
@@ -0,0 +1,92 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.AttributeCertificate;
+import org.spongycastle.asn1.x509.Certificate;
+
+public class CMPCertificate
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private Certificate x509v3PKCert;
+ private AttributeCertificate x509v2AttrCert;
+
+ /**
+ * Note: the addition of attribute certificates is a BC extension.
+ */
+ public CMPCertificate(AttributeCertificate x509v2AttrCert)
+ {
+ this.x509v2AttrCert = x509v2AttrCert;
+ }
+
+ public CMPCertificate(Certificate x509v3PKCert)
+ {
+ if (x509v3PKCert.getVersionNumber() != 3)
+ {
+ throw new IllegalArgumentException("only version 3 certificates allowed");
+ }
+
+ this.x509v3PKCert = x509v3PKCert;
+ }
+
+ public static CMPCertificate getInstance(Object o)
+ {
+ if (o == null || o instanceof CMPCertificate)
+ {
+ return (CMPCertificate)o;
+ }
+
+ if (o instanceof ASN1Sequence || o instanceof byte[])
+ {
+ return new CMPCertificate(Certificate.getInstance(o));
+ }
+
+ if (o instanceof ASN1TaggedObject)
+ {
+ return new CMPCertificate(AttributeCertificate.getInstance(((ASN1TaggedObject)o).getObject()));
+ }
+
+ throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
+ }
+
+ public boolean isX509v3PKCert()
+ {
+ return x509v3PKCert != null;
+ }
+
+ public Certificate getX509v3PKCert()
+ {
+ return x509v3PKCert;
+ }
+
+ public AttributeCertificate getX509v2AttrCert()
+ {
+ return x509v2AttrCert;
+ }
+
+ /**
+ * <pre>
+ * CMPCertificate ::= CHOICE {
+ * x509v3PKCert Certificate
+ * x509v2AttrCert [1] AttributeCertificate
+ * }
+ * </pre>
+ * Note: the addition of attribute certificates is a BC extension.
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (x509v2AttrCert != null)
+ { // explicit following CMP conventions
+ return new DERTaggedObject(true, 1, x509v2AttrCert);
+ }
+
+ return x509v3PKCert.toASN1Primitive();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/CMPObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/cmp/CMPObjectIdentifiers.java
new file mode 100644
index 00000000..c7cbc5a5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/CMPObjectIdentifiers.java
@@ -0,0 +1,141 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+
+public interface CMPObjectIdentifiers
+{
+ // RFC 4210
+
+ /** 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} */
+ static final ASN1ObjectIdentifier dhBasedMac = new ASN1ObjectIdentifier("1.2.840.113533.7.66.30");
+
+ // Example InfoTypeAndValue contents include, but are not limited
+ // to, the following (un-comment in this ASN.1 module and use as
+ // appropriate for a given environment):
+ //
+ // id-it-caProtEncCert OBJECT IDENTIFIER ::= {id-it 1}
+ // CAProtEncCertValue ::= CMPCertificate
+ // id-it-signKeyPairTypes OBJECT IDENTIFIER ::= {id-it 2}
+ // SignKeyPairTypesValue ::= SEQUENCE OF AlgorithmIdentifier
+ // id-it-encKeyPairTypes OBJECT IDENTIFIER ::= {id-it 3}
+ // EncKeyPairTypesValue ::= SEQUENCE OF AlgorithmIdentifier
+ // id-it-preferredSymmAlg OBJECT IDENTIFIER ::= {id-it 4}
+ // PreferredSymmAlgValue ::= AlgorithmIdentifier
+ // id-it-caKeyUpdateInfo OBJECT IDENTIFIER ::= {id-it 5}
+ // CAKeyUpdateInfoValue ::= CAKeyUpdAnnContent
+ // id-it-currentCRL OBJECT IDENTIFIER ::= {id-it 6}
+ // CurrentCRLValue ::= CertificateList
+ // id-it-unsupportedOIDs OBJECT IDENTIFIER ::= {id-it 7}
+ // UnsupportedOIDsValue ::= SEQUENCE OF OBJECT IDENTIFIER
+ // id-it-keyPairParamReq OBJECT IDENTIFIER ::= {id-it 10}
+ // KeyPairParamReqValue ::= OBJECT IDENTIFIER
+ // id-it-keyPairParamRep OBJECT IDENTIFIER ::= {id-it 11}
+ // KeyPairParamRepValue ::= AlgorithmIdentifer
+ // id-it-revPassphrase OBJECT IDENTIFIER ::= {id-it 12}
+ // RevPassphraseValue ::= EncryptedValue
+ // id-it-implicitConfirm OBJECT IDENTIFIER ::= {id-it 13}
+ // ImplicitConfirmValue ::= NULL
+ // id-it-confirmWaitTime OBJECT IDENTIFIER ::= {id-it 14}
+ // ConfirmWaitTimeValue ::= GeneralizedTime
+ // id-it-origPKIMessage OBJECT IDENTIFIER ::= {id-it 15}
+ // OrigPKIMessageValue ::= PKIMessages
+ // id-it-suppLangTags OBJECT IDENTIFIER ::= {id-it 16}
+ // SuppLangTagsValue ::= SEQUENCE OF UTF8String
+ //
+ // where
+ //
+ // id-pkix OBJECT IDENTIFIER ::= {
+ // iso(1) identified-organization(3)
+ // 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
+
+ // id-pkix OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
+ // dod(6) internet(1) security(5) mechanisms(5) pkix(7) }
+ //
+ // arc for Internet X.509 PKI protocols and their components
+ // id-pkip OBJECT IDENTIFIER :: { id-pkix pkip(5) }
+ //
+ // arc for Registration Controls in CRMF
+ // id-regCtrl OBJECT IDENTIFIER ::= { id-pkip regCtrl(1) }
+ //
+ // 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}; 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");
+
+ /**
+ * 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/core/src/main/java/org/spongycastle/asn1/cmp/CRLAnnContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/CRLAnnContent.java
new file mode 100644
index 00000000..513baeb9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/CRLAnnContent.java
@@ -0,0 +1,61 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.CertificateList;
+
+public class CRLAnnContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private CRLAnnContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static CRLAnnContent getInstance(Object o)
+ {
+ if (o instanceof CRLAnnContent)
+ {
+ return (CRLAnnContent)o;
+ }
+
+ if (o != null)
+ {
+ return new CRLAnnContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CRLAnnContent(CertificateList crl)
+ {
+ this.content = new DERSequence(crl);
+ }
+
+ public CertificateList[] getCertificateLists()
+ {
+ CertificateList[] result = new CertificateList[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = CertificateList.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ * <pre>
+ * CRLAnnContent ::= SEQUENCE OF CertificateList
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/CertConfirmContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/CertConfirmContent.java
new file mode 100644
index 00000000..974eb757
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/CertConfirmContent.java
@@ -0,0 +1,54 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+
+public class CertConfirmContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private CertConfirmContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static CertConfirmContent getInstance(Object o)
+ {
+ if (o instanceof CertConfirmContent)
+ {
+ return (CertConfirmContent)o;
+ }
+
+ if (o != null)
+ {
+ return new CertConfirmContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CertStatus[] toCertStatusArray()
+ {
+ CertStatus[] result = new CertStatus[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = CertStatus.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ * <pre>
+ * CertConfirmContent ::= SEQUENCE OF CertStatus
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/CertOrEncCert.java b/core/src/main/java/org/spongycastle/asn1/cmp/CertOrEncCert.java
new file mode 100644
index 00000000..ed16a650
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/CertOrEncCert.java
@@ -0,0 +1,96 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.crmf.EncryptedValue;
+
+public class CertOrEncCert
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private CMPCertificate certificate;
+ private EncryptedValue encryptedCert;
+
+ private CertOrEncCert(ASN1TaggedObject tagged)
+ {
+ if (tagged.getTagNo() == 0)
+ {
+ certificate = CMPCertificate.getInstance(tagged.getObject());
+ }
+ else if (tagged.getTagNo() == 1)
+ {
+ encryptedCert = EncryptedValue.getInstance(tagged.getObject());
+ }
+ else
+ {
+ throw new IllegalArgumentException("unknown tag: " + tagged.getTagNo());
+ }
+ }
+
+ public static CertOrEncCert getInstance(Object o)
+ {
+ if (o instanceof CertOrEncCert)
+ {
+ return (CertOrEncCert)o;
+ }
+
+ if (o instanceof ASN1TaggedObject)
+ {
+ return new CertOrEncCert((ASN1TaggedObject)o);
+ }
+
+ return null;
+ }
+
+ public CertOrEncCert(CMPCertificate certificate)
+ {
+ if (certificate == null)
+ {
+ throw new IllegalArgumentException("'certificate' cannot be null");
+ }
+
+ this.certificate = certificate;
+ }
+
+ public CertOrEncCert(EncryptedValue encryptedCert)
+ {
+ if (encryptedCert == null)
+ {
+ throw new IllegalArgumentException("'encryptedCert' cannot be null");
+ }
+
+ this.encryptedCert = encryptedCert;
+ }
+
+ public CMPCertificate getCertificate()
+ {
+ return certificate;
+ }
+
+ public EncryptedValue getEncryptedCert()
+ {
+ return encryptedCert;
+ }
+
+ /**
+ * <pre>
+ * CertOrEncCert ::= CHOICE {
+ * certificate [0] CMPCertificate,
+ * encryptedCert [1] EncryptedValue
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (certificate != null)
+ {
+ return new DERTaggedObject(true, 0, certificate);
+ }
+
+ return new DERTaggedObject(true, 1, encryptedCert);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/CertRepMessage.java b/core/src/main/java/org/spongycastle/asn1/cmp/CertRepMessage.java
new file mode 100644
index 00000000..3f63a4ac
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/CertRepMessage.java
@@ -0,0 +1,123 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+public class CertRepMessage
+ extends ASN1Object
+{
+ private ASN1Sequence caPubs;
+ private ASN1Sequence response;
+
+ private CertRepMessage(ASN1Sequence seq)
+ {
+ int index = 0;
+
+ if (seq.size() > 1)
+ {
+ caPubs = ASN1Sequence.getInstance((ASN1TaggedObject)seq.getObjectAt(index++), true);
+ }
+
+ response = ASN1Sequence.getInstance(seq.getObjectAt(index));
+ }
+
+ public static CertRepMessage getInstance(Object o)
+ {
+ if (o instanceof CertRepMessage)
+ {
+ return (CertRepMessage)o;
+ }
+
+ if (o != null)
+ {
+ return new CertRepMessage(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CertRepMessage(CMPCertificate[] caPubs, CertResponse[] response)
+ {
+ if (response == null)
+ {
+ throw new IllegalArgumentException("'response' cannot be null");
+ }
+
+ if (caPubs != null)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < caPubs.length; i++)
+ {
+ v.add(caPubs[i]);
+ }
+ this.caPubs = new DERSequence(v);
+ }
+
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < response.length; i++)
+ {
+ v.add(response[i]);
+ }
+ this.response = new DERSequence(v);
+ }
+ }
+
+ public CMPCertificate[] getCaPubs()
+ {
+ if (caPubs == null)
+ {
+ return null;
+ }
+
+ CMPCertificate[] results = new CMPCertificate[caPubs.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = CMPCertificate.getInstance(caPubs.getObjectAt(i));
+ }
+
+ return results;
+ }
+
+ public CertResponse[] getResponse()
+ {
+ CertResponse[] results = new CertResponse[response.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = CertResponse.getInstance(response.getObjectAt(i));
+ }
+
+ return results;
+ }
+
+ /**
+ * <pre>
+ * CertRepMessage ::= SEQUENCE {
+ * caPubs [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
+ * OPTIONAL,
+ * response SEQUENCE OF CertResponse
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (caPubs != null)
+ {
+ v.add(new DERTaggedObject(true, 1, caPubs));
+ }
+
+ v.add(response);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/CertResponse.java b/core/src/main/java/org/spongycastle/asn1/cmp/CertResponse.java
new file mode 100644
index 00000000..9efcff68
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/CertResponse.java
@@ -0,0 +1,139 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class CertResponse
+ extends ASN1Object
+{
+ private ASN1Integer certReqId;
+ private PKIStatusInfo status;
+ private CertifiedKeyPair certifiedKeyPair;
+ private ASN1OctetString rspInfo;
+
+ private CertResponse(ASN1Sequence seq)
+ {
+ certReqId = ASN1Integer.getInstance(seq.getObjectAt(0));
+ status = PKIStatusInfo.getInstance(seq.getObjectAt(1));
+
+ if (seq.size() >= 3)
+ {
+ if (seq.size() == 3)
+ {
+ ASN1Encodable o = seq.getObjectAt(2);
+ if (o instanceof ASN1OctetString)
+ {
+ rspInfo = ASN1OctetString.getInstance(o);
+ }
+ else
+ {
+ certifiedKeyPair = CertifiedKeyPair.getInstance(o);
+ }
+ }
+ else
+ {
+ certifiedKeyPair = CertifiedKeyPair.getInstance(seq.getObjectAt(2));
+ rspInfo = ASN1OctetString.getInstance(seq.getObjectAt(3));
+ }
+ }
+ }
+
+ public static CertResponse getInstance(Object o)
+ {
+ if (o instanceof CertResponse)
+ {
+ return (CertResponse)o;
+ }
+
+ if (o != null)
+ {
+ return new CertResponse(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CertResponse(
+ ASN1Integer certReqId,
+ PKIStatusInfo status)
+ {
+ this(certReqId, status, null, null);
+ }
+
+ public CertResponse(
+ ASN1Integer certReqId,
+ PKIStatusInfo status,
+ CertifiedKeyPair certifiedKeyPair,
+ ASN1OctetString rspInfo)
+ {
+ if (certReqId == null)
+ {
+ throw new IllegalArgumentException("'certReqId' cannot be null");
+ }
+ if (status == null)
+ {
+ throw new IllegalArgumentException("'status' cannot be null");
+ }
+ this.certReqId = certReqId;
+ this.status = status;
+ this.certifiedKeyPair = certifiedKeyPair;
+ this.rspInfo = rspInfo;
+ }
+
+ public ASN1Integer getCertReqId()
+ {
+ return certReqId;
+ }
+
+ public PKIStatusInfo getStatus()
+ {
+ return status;
+ }
+
+ public CertifiedKeyPair getCertifiedKeyPair()
+ {
+ return certifiedKeyPair;
+ }
+
+ /**
+ * <pre>
+ * CertResponse ::= SEQUENCE {
+ * certReqId INTEGER,
+ * -- to match this response with corresponding request (a value
+ * -- of -1 is to be used if certReqId is not specified in the
+ * -- corresponding request)
+ * status PKIStatusInfo,
+ * certifiedKeyPair CertifiedKeyPair OPTIONAL,
+ * rspInfo OCTET STRING OPTIONAL
+ * -- analogous to the id-regInfo-utf8Pairs string defined
+ * -- for regInfo in CertReqMsg [CRMF]
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certReqId);
+ v.add(status);
+
+ if (certifiedKeyPair != null)
+ {
+ v.add(certifiedKeyPair);
+ }
+
+ if (rspInfo != null)
+ {
+ v.add(rspInfo);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/CertStatus.java b/core/src/main/java/org/spongycastle/asn1/cmp/CertStatus.java
new file mode 100644
index 00000000..86664eed
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/CertStatus.java
@@ -0,0 +1,102 @@
+package org.spongycastle.asn1.cmp;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+
+public class CertStatus
+ extends ASN1Object
+{
+ private ASN1OctetString certHash;
+ private ASN1Integer certReqId;
+ private PKIStatusInfo statusInfo;
+
+ private CertStatus(ASN1Sequence seq)
+ {
+ certHash = ASN1OctetString.getInstance(seq.getObjectAt(0));
+ certReqId = ASN1Integer.getInstance(seq.getObjectAt(1));
+
+ if (seq.size() > 2)
+ {
+ statusInfo = PKIStatusInfo.getInstance(seq.getObjectAt(2));
+ }
+ }
+
+ public CertStatus(byte[] certHash, BigInteger certReqId)
+ {
+ this.certHash = new DEROctetString(certHash);
+ this.certReqId = new ASN1Integer(certReqId);
+ }
+
+ public CertStatus(byte[] certHash, BigInteger certReqId, PKIStatusInfo statusInfo)
+ {
+ this.certHash = new DEROctetString(certHash);
+ this.certReqId = new ASN1Integer(certReqId);
+ this.statusInfo = statusInfo;
+ }
+
+ public static CertStatus getInstance(Object o)
+ {
+ if (o instanceof CertStatus)
+ {
+ return (CertStatus)o;
+ }
+
+ if (o != null)
+ {
+ return new CertStatus(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public ASN1OctetString getCertHash()
+ {
+ return certHash;
+ }
+
+ public ASN1Integer getCertReqId()
+ {
+ return certReqId;
+ }
+
+ public PKIStatusInfo getStatusInfo()
+ {
+ return statusInfo;
+ }
+
+ /**
+ * <pre>
+ * CertStatus ::= SEQUENCE {
+ * certHash OCTET STRING,
+ * -- the hash of the certificate, using the same hash algorithm
+ * -- as is used to create and verify the certificate signature
+ * certReqId INTEGER,
+ * -- to match this confirmation with the corresponding req/rep
+ * statusInfo PKIStatusInfo OPTIONAL
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certHash);
+ v.add(certReqId);
+
+ if (statusInfo != null)
+ {
+ v.add(statusInfo);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/CertifiedKeyPair.java b/core/src/main/java/org/spongycastle/asn1/cmp/CertifiedKeyPair.java
new file mode 100644
index 00000000..500c9d03
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/CertifiedKeyPair.java
@@ -0,0 +1,127 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.crmf.EncryptedValue;
+import org.spongycastle.asn1.crmf.PKIPublicationInfo;
+
+public class CertifiedKeyPair
+ extends ASN1Object
+{
+ private CertOrEncCert certOrEncCert;
+ private EncryptedValue privateKey;
+ private PKIPublicationInfo publicationInfo;
+
+ private CertifiedKeyPair(ASN1Sequence seq)
+ {
+ certOrEncCert = CertOrEncCert.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() >= 2)
+ {
+ if (seq.size() == 2)
+ {
+ ASN1TaggedObject tagged = ASN1TaggedObject.getInstance(seq.getObjectAt(1));
+ if (tagged.getTagNo() == 0)
+ {
+ privateKey = EncryptedValue.getInstance(tagged.getObject());
+ }
+ else
+ {
+ publicationInfo = PKIPublicationInfo.getInstance(tagged.getObject());
+ }
+ }
+ else
+ {
+ privateKey = EncryptedValue.getInstance(ASN1TaggedObject.getInstance(seq.getObjectAt(1)));
+ publicationInfo = PKIPublicationInfo.getInstance(ASN1TaggedObject.getInstance(seq.getObjectAt(2)));
+ }
+ }
+ }
+
+ public static CertifiedKeyPair getInstance(Object o)
+ {
+ if (o instanceof CertifiedKeyPair)
+ {
+ return (CertifiedKeyPair)o;
+ }
+
+ if (o != null)
+ {
+ return new CertifiedKeyPair(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CertifiedKeyPair(
+ CertOrEncCert certOrEncCert)
+ {
+ this(certOrEncCert, null, null);
+ }
+
+ public CertifiedKeyPair(
+ CertOrEncCert certOrEncCert,
+ EncryptedValue privateKey,
+ PKIPublicationInfo publicationInfo
+ )
+ {
+ if (certOrEncCert == null)
+ {
+ throw new IllegalArgumentException("'certOrEncCert' cannot be null");
+ }
+
+ this.certOrEncCert = certOrEncCert;
+ this.privateKey = privateKey;
+ this.publicationInfo = publicationInfo;
+ }
+
+ public CertOrEncCert getCertOrEncCert()
+ {
+ return certOrEncCert;
+ }
+
+ public EncryptedValue getPrivateKey()
+ {
+ return privateKey;
+ }
+
+ public PKIPublicationInfo getPublicationInfo()
+ {
+ return publicationInfo;
+ }
+
+ /**
+ * <pre>
+ * CertifiedKeyPair ::= SEQUENCE {
+ * certOrEncCert CertOrEncCert,
+ * privateKey [0] EncryptedValue OPTIONAL,
+ * -- see [CRMF] for comment on encoding
+ * publicationInfo [1] PKIPublicationInfo OPTIONAL
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certOrEncCert);
+
+ if (privateKey != null)
+ {
+ v.add(new DERTaggedObject(true, 0, privateKey));
+ }
+
+ if (publicationInfo != null)
+ {
+ v.add(new DERTaggedObject(true, 1, publicationInfo));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/Challenge.java b/core/src/main/java/org/spongycastle/asn1/cmp/Challenge.java
new file mode 100644
index 00000000..ef02b28b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/Challenge.java
@@ -0,0 +1,120 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+public class Challenge
+ extends ASN1Object
+{
+ private AlgorithmIdentifier owf;
+ private ASN1OctetString witness;
+ private ASN1OctetString challenge;
+
+ private Challenge(ASN1Sequence seq)
+ {
+ int index = 0;
+
+ if (seq.size() == 3)
+ {
+ owf = AlgorithmIdentifier.getInstance(seq.getObjectAt(index++));
+ }
+
+ witness = ASN1OctetString.getInstance(seq.getObjectAt(index++));
+ challenge = ASN1OctetString.getInstance(seq.getObjectAt(index));
+ }
+
+ public static Challenge getInstance(Object o)
+ {
+ if (o instanceof Challenge)
+ {
+ return (Challenge)o;
+ }
+
+ if (o != null)
+ {
+ return new Challenge(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public Challenge(byte[] witness, byte[] challenge)
+ {
+ this(null, witness, challenge);
+ }
+
+ public Challenge(AlgorithmIdentifier owf, byte[] witness, byte[] challenge)
+ {
+ this.owf = owf;
+ this.witness = new DEROctetString(witness);
+ this.challenge = new DEROctetString(challenge);
+ }
+
+ public AlgorithmIdentifier getOwf()
+ {
+ return owf;
+ }
+
+ public byte[] getWitness()
+ {
+ return witness.getOctets();
+ }
+
+ public byte[] getChallenge()
+ {
+ return challenge.getOctets();
+ }
+
+ /**
+ * <pre>
+ * Challenge ::= SEQUENCE {
+ * owf AlgorithmIdentifier OPTIONAL,
+ *
+ * -- MUST be present in the first Challenge; MAY be omitted in
+ * -- any subsequent Challenge in POPODecKeyChallContent (if
+ * -- omitted, then the owf used in the immediately preceding
+ * -- Challenge is to be used).
+ *
+ * witness OCTET STRING,
+ * -- the result of applying the one-way function (owf) to a
+ * -- randomly-generated INTEGER, A. [Note that a different
+ * -- INTEGER MUST be used for each Challenge.]
+ * challenge OCTET STRING
+ * -- the encryption (under the public key for which the cert.
+ * -- request is being made) of Rand, where Rand is specified as
+ * -- Rand ::= SEQUENCE {
+ * -- int INTEGER,
+ * -- - the randomly-generated INTEGER A (above)
+ * -- sender GeneralName
+ * -- - the sender's name (as included in PKIHeader)
+ * -- }
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ addOptional(v, owf);
+ v.add(witness);
+ v.add(challenge);
+
+ return new DERSequence(v);
+ }
+
+ private void addOptional(ASN1EncodableVector v, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(obj);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/ErrorMsgContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/ErrorMsgContent.java
new file mode 100644
index 00000000..e7ef5716
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/ErrorMsgContent.java
@@ -0,0 +1,121 @@
+package org.spongycastle.asn1.cmp;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class ErrorMsgContent
+ extends ASN1Object
+{
+ private PKIStatusInfo pkiStatusInfo;
+ private ASN1Integer errorCode;
+ private PKIFreeText errorDetails;
+
+ private ErrorMsgContent(ASN1Sequence seq)
+ {
+ Enumeration en = seq.getObjects();
+
+ pkiStatusInfo = PKIStatusInfo.getInstance(en.nextElement());
+
+ while (en.hasMoreElements())
+ {
+ Object o = en.nextElement();
+
+ if (o instanceof ASN1Integer)
+ {
+ errorCode = ASN1Integer.getInstance(o);
+ }
+ else
+ {
+ errorDetails = PKIFreeText.getInstance(o);
+ }
+ }
+ }
+
+ public static ErrorMsgContent getInstance(Object o)
+ {
+ if (o instanceof ErrorMsgContent)
+ {
+ return (ErrorMsgContent)o;
+ }
+
+ if (o != null)
+ {
+ return new ErrorMsgContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public ErrorMsgContent(PKIStatusInfo pkiStatusInfo)
+ {
+ this(pkiStatusInfo, null, null);
+ }
+
+ public ErrorMsgContent(
+ PKIStatusInfo pkiStatusInfo,
+ ASN1Integer errorCode,
+ PKIFreeText errorDetails)
+ {
+ if (pkiStatusInfo == null)
+ {
+ throw new IllegalArgumentException("'pkiStatusInfo' cannot be null");
+ }
+
+ this.pkiStatusInfo = pkiStatusInfo;
+ this.errorCode = errorCode;
+ this.errorDetails = errorDetails;
+ }
+
+ public PKIStatusInfo getPKIStatusInfo()
+ {
+ return pkiStatusInfo;
+ }
+
+ public ASN1Integer getErrorCode()
+ {
+ return errorCode;
+ }
+
+ public PKIFreeText getErrorDetails()
+ {
+ return errorDetails;
+ }
+
+ /**
+ * <pre>
+ * ErrorMsgContent ::= SEQUENCE {
+ * pKIStatusInfo PKIStatusInfo,
+ * errorCode INTEGER OPTIONAL,
+ * -- implementation-specific error codes
+ * errorDetails PKIFreeText OPTIONAL
+ * -- implementation-specific error details
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(pkiStatusInfo);
+ addOptional(v, errorCode);
+ addOptional(v, errorDetails);
+
+ return new DERSequence(v);
+ }
+
+ private void addOptional(ASN1EncodableVector v, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(obj);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/GenMsgContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/GenMsgContent.java
new file mode 100644
index 00000000..5d65e0d1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/GenMsgContent.java
@@ -0,0 +1,71 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class GenMsgContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private GenMsgContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static GenMsgContent getInstance(Object o)
+ {
+ if (o instanceof GenMsgContent)
+ {
+ return (GenMsgContent)o;
+ }
+
+ if (o != null)
+ {
+ return new GenMsgContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public GenMsgContent(InfoTypeAndValue itv)
+ {
+ content = new DERSequence(itv);
+ }
+
+ public GenMsgContent(InfoTypeAndValue[] itv)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < itv.length; i++)
+ {
+ v.add(itv[i]);
+ }
+ content = new DERSequence(v);
+ }
+
+ public InfoTypeAndValue[] toInfoTypeAndValueArray()
+ {
+ InfoTypeAndValue[] result = new InfoTypeAndValue[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = InfoTypeAndValue.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ * <pre>
+ * GenMsgContent ::= SEQUENCE OF InfoTypeAndValue
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/GenRepContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/GenRepContent.java
new file mode 100644
index 00000000..a6a2f4db
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/GenRepContent.java
@@ -0,0 +1,71 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class GenRepContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private GenRepContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static GenRepContent getInstance(Object o)
+ {
+ if (o instanceof GenRepContent)
+ {
+ return (GenRepContent)o;
+ }
+
+ if (o != null)
+ {
+ return new GenRepContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public GenRepContent(InfoTypeAndValue itv)
+ {
+ content = new DERSequence(itv);
+ }
+
+ public GenRepContent(InfoTypeAndValue[] itv)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < itv.length; i++)
+ {
+ v.add(itv[i]);
+ }
+ content = new DERSequence(v);
+ }
+
+ public InfoTypeAndValue[] toInfoTypeAndValueArray()
+ {
+ InfoTypeAndValue[] result = new InfoTypeAndValue[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = InfoTypeAndValue.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ * <pre>
+ * GenRepContent ::= SEQUENCE OF InfoTypeAndValue
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/InfoTypeAndValue.java b/core/src/main/java/org/spongycastle/asn1/cmp/InfoTypeAndValue.java
new file mode 100644
index 00000000..3f99d1e1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/InfoTypeAndValue.java
@@ -0,0 +1,132 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * Example InfoTypeAndValue contents include, but are not limited
+ * to, the following (un-comment in this ASN.1 module and use as
+ * appropriate for a given environment):
+ * <pre>
+ * id-it-caProtEncCert OBJECT IDENTIFIER ::= {id-it 1}
+ * CAProtEncCertValue ::= CMPCertificate
+ * id-it-signKeyPairTypes OBJECT IDENTIFIER ::= {id-it 2}
+ * SignKeyPairTypesValue ::= SEQUENCE OF AlgorithmIdentifier
+ * id-it-encKeyPairTypes OBJECT IDENTIFIER ::= {id-it 3}
+ * EncKeyPairTypesValue ::= SEQUENCE OF AlgorithmIdentifier
+ * id-it-preferredSymmAlg OBJECT IDENTIFIER ::= {id-it 4}
+ * PreferredSymmAlgValue ::= AlgorithmIdentifier
+ * id-it-caKeyUpdateInfo OBJECT IDENTIFIER ::= {id-it 5}
+ * CAKeyUpdateInfoValue ::= CAKeyUpdAnnContent
+ * id-it-currentCRL OBJECT IDENTIFIER ::= {id-it 6}
+ * CurrentCRLValue ::= CertificateList
+ * id-it-unsupportedOIDs OBJECT IDENTIFIER ::= {id-it 7}
+ * UnsupportedOIDsValue ::= SEQUENCE OF OBJECT IDENTIFIER
+ * id-it-keyPairParamReq OBJECT IDENTIFIER ::= {id-it 10}
+ * KeyPairParamReqValue ::= OBJECT IDENTIFIER
+ * id-it-keyPairParamRep OBJECT IDENTIFIER ::= {id-it 11}
+ * KeyPairParamRepValue ::= AlgorithmIdentifer
+ * id-it-revPassphrase OBJECT IDENTIFIER ::= {id-it 12}
+ * RevPassphraseValue ::= EncryptedValue
+ * id-it-implicitConfirm OBJECT IDENTIFIER ::= {id-it 13}
+ * ImplicitConfirmValue ::= NULL
+ * id-it-confirmWaitTime OBJECT IDENTIFIER ::= {id-it 14}
+ * ConfirmWaitTimeValue ::= GeneralizedTime
+ * id-it-origPKIMessage OBJECT IDENTIFIER ::= {id-it 15}
+ * OrigPKIMessageValue ::= PKIMessages
+ * id-it-suppLangTags OBJECT IDENTIFIER ::= {id-it 16}
+ * SuppLangTagsValue ::= SEQUENCE OF UTF8String
+ *
+ * where
+ *
+ * id-pkix OBJECT IDENTIFIER ::= {
+ * iso(1) identified-organization(3)
+ * dod(6) internet(1) security(5) mechanisms(5) pkix(7)}
+ * and
+ * id-it OBJECT IDENTIFIER ::= {id-pkix 4}
+ * </pre>
+ */
+public class InfoTypeAndValue
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier infoType;
+ private ASN1Encodable infoValue;
+
+ private InfoTypeAndValue(ASN1Sequence seq)
+ {
+ infoType = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() > 1)
+ {
+ infoValue = (ASN1Encodable)seq.getObjectAt(1);
+ }
+ }
+
+ public static InfoTypeAndValue getInstance(Object o)
+ {
+ if (o instanceof InfoTypeAndValue)
+ {
+ return (InfoTypeAndValue)o;
+ }
+
+ if (o != null)
+ {
+ return new InfoTypeAndValue(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public InfoTypeAndValue(
+ ASN1ObjectIdentifier infoType)
+ {
+ this.infoType = infoType;
+ this.infoValue = null;
+ }
+
+ public InfoTypeAndValue(
+ ASN1ObjectIdentifier infoType,
+ ASN1Encodable optionalValue)
+ {
+ this.infoType = infoType;
+ this.infoValue = optionalValue;
+ }
+
+ public ASN1ObjectIdentifier getInfoType()
+ {
+ return infoType;
+ }
+
+ public ASN1Encodable getInfoValue()
+ {
+ return infoValue;
+ }
+
+ /**
+ * <pre>
+ * InfoTypeAndValue ::= SEQUENCE {
+ * infoType OBJECT IDENTIFIER,
+ * infoValue ANY DEFINED BY infoType OPTIONAL
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(infoType);
+
+ if (infoValue != null)
+ {
+ v.add(infoValue);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/KeyRecRepContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/KeyRecRepContent.java
new file mode 100644
index 00000000..903352e5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/KeyRecRepContent.java
@@ -0,0 +1,142 @@
+package org.spongycastle.asn1.cmp;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+public class KeyRecRepContent
+ extends ASN1Object
+{
+ private PKIStatusInfo status;
+ private CMPCertificate newSigCert;
+ private ASN1Sequence caCerts;
+ private ASN1Sequence keyPairHist;
+
+ private KeyRecRepContent(ASN1Sequence seq)
+ {
+ Enumeration en = seq.getObjects();
+
+ status = PKIStatusInfo.getInstance(en.nextElement());
+
+ while (en.hasMoreElements())
+ {
+ ASN1TaggedObject tObj = ASN1TaggedObject.getInstance(en.nextElement());
+
+ switch (tObj.getTagNo())
+ {
+ case 0:
+ newSigCert = CMPCertificate.getInstance(tObj.getObject());
+ break;
+ case 1:
+ caCerts = ASN1Sequence.getInstance(tObj.getObject());
+ break;
+ case 2:
+ keyPairHist = ASN1Sequence.getInstance(tObj.getObject());
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag number: " + tObj.getTagNo());
+ }
+ }
+ }
+
+ public static KeyRecRepContent getInstance(Object o)
+ {
+ if (o instanceof KeyRecRepContent)
+ {
+ return (KeyRecRepContent)o;
+ }
+
+ if (o != null)
+ {
+ return new KeyRecRepContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+
+ public PKIStatusInfo getStatus()
+ {
+ return status;
+ }
+
+ public CMPCertificate getNewSigCert()
+ {
+ return newSigCert;
+ }
+
+ public CMPCertificate[] getCaCerts()
+ {
+ if (caCerts == null)
+ {
+ return null;
+ }
+
+ CMPCertificate[] results = new CMPCertificate[caCerts.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = CMPCertificate.getInstance(caCerts.getObjectAt(i));
+ }
+
+ return results;
+ }
+
+ public CertifiedKeyPair[] getKeyPairHist()
+ {
+ if (keyPairHist == null)
+ {
+ return null;
+ }
+
+ CertifiedKeyPair[] results = new CertifiedKeyPair[keyPairHist.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = CertifiedKeyPair.getInstance(keyPairHist.getObjectAt(i));
+ }
+
+ return results;
+ }
+
+ /**
+ * <pre>
+ * KeyRecRepContent ::= SEQUENCE {
+ * status PKIStatusInfo,
+ * newSigCert [0] CMPCertificate OPTIONAL,
+ * caCerts [1] SEQUENCE SIZE (1..MAX) OF
+ * CMPCertificate OPTIONAL,
+ * keyPairHist [2] SEQUENCE SIZE (1..MAX) OF
+ * CertifiedKeyPair OPTIONAL
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(status);
+
+ addOptional(v, 0, newSigCert);
+ addOptional(v, 1, caCerts);
+ addOptional(v, 2, keyPairHist);
+
+ return new DERSequence(v);
+ }
+
+ private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(new DERTaggedObject(true, tagNo, obj));
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/OOBCertHash.java b/core/src/main/java/org/spongycastle/asn1/cmp/OOBCertHash.java
new file mode 100644
index 00000000..dc81e7ec
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/OOBCertHash.java
@@ -0,0 +1,117 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.crmf.CertId;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+public class OOBCertHash
+ extends ASN1Object
+{
+ private AlgorithmIdentifier hashAlg;
+ private CertId certId;
+ private DERBitString hashVal;
+
+ private OOBCertHash(ASN1Sequence seq)
+ {
+ int index = seq.size() - 1;
+
+ hashVal = DERBitString.getInstance(seq.getObjectAt(index--));
+
+ for (int i = index; i >= 0; i--)
+ {
+ ASN1TaggedObject tObj = (ASN1TaggedObject)seq.getObjectAt(i);
+
+ if (tObj.getTagNo() == 0)
+ {
+ hashAlg = AlgorithmIdentifier.getInstance(tObj, true);
+ }
+ else
+ {
+ certId = CertId.getInstance(tObj, true);
+ }
+ }
+
+ }
+
+ public static OOBCertHash getInstance(Object o)
+ {
+ if (o instanceof OOBCertHash)
+ {
+ return (OOBCertHash)o;
+ }
+
+ if (o != null)
+ {
+ return new OOBCertHash(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public OOBCertHash(AlgorithmIdentifier hashAlg, CertId certId, byte[] hashVal)
+ {
+ this(hashAlg, certId, new DERBitString(hashVal));
+ }
+
+ public OOBCertHash(AlgorithmIdentifier hashAlg, CertId certId, DERBitString hashVal)
+ {
+ this.hashAlg = hashAlg;
+ this.certId = certId;
+ this.hashVal = hashVal;
+ }
+
+ public AlgorithmIdentifier getHashAlg()
+ {
+ return hashAlg;
+ }
+
+ public CertId getCertId()
+ {
+ return certId;
+ }
+
+ public DERBitString getHashVal()
+ {
+ return hashVal;
+ }
+
+ /**
+ * <pre>
+ * OOBCertHash ::= SEQUENCE {
+ * hashAlg [0] AlgorithmIdentifier OPTIONAL,
+ * certId [1] CertId OPTIONAL,
+ * hashVal BIT STRING
+ * -- hashVal is calculated over the DER encoding of the
+ * -- self-signed certificate with the identifier certID.
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ addOptional(v, 0, hashAlg);
+ addOptional(v, 1, certId);
+
+ v.add(hashVal);
+
+ return new DERSequence(v);
+ }
+
+ private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(new DERTaggedObject(true, tagNo, obj));
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/PBMParameter.java b/core/src/main/java/org/spongycastle/asn1/cmp/PBMParameter.java
new file mode 100644
index 00000000..83c443cf
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PBMParameter.java
@@ -0,0 +1,117 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+public class PBMParameter
+ extends ASN1Object
+{
+ private ASN1OctetString salt;
+ private AlgorithmIdentifier owf;
+ private ASN1Integer iterationCount;
+ private AlgorithmIdentifier mac;
+
+ private PBMParameter(ASN1Sequence seq)
+ {
+ salt = ASN1OctetString.getInstance(seq.getObjectAt(0));
+ owf = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
+ iterationCount = ASN1Integer.getInstance(seq.getObjectAt(2));
+ mac = AlgorithmIdentifier.getInstance(seq.getObjectAt(3));
+ }
+
+ public static PBMParameter getInstance(Object o)
+ {
+ if (o instanceof PBMParameter)
+ {
+ return (PBMParameter)o;
+ }
+
+ if (o != null)
+ {
+ return new PBMParameter(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public PBMParameter(
+ byte[] salt,
+ AlgorithmIdentifier owf,
+ int iterationCount,
+ AlgorithmIdentifier mac)
+ {
+ this(new DEROctetString(salt), owf,
+ new ASN1Integer(iterationCount), mac);
+ }
+
+ public PBMParameter(
+ ASN1OctetString salt,
+ AlgorithmIdentifier owf,
+ ASN1Integer iterationCount,
+ AlgorithmIdentifier mac)
+ {
+ this.salt = salt;
+ this.owf = owf;
+ this.iterationCount = iterationCount;
+ this.mac = mac;
+ }
+
+ public ASN1OctetString getSalt()
+ {
+ return salt;
+ }
+
+ public AlgorithmIdentifier getOwf()
+ {
+ return owf;
+ }
+
+ public ASN1Integer getIterationCount()
+ {
+ return iterationCount;
+ }
+
+ public AlgorithmIdentifier getMac()
+ {
+ return mac;
+ }
+
+ /**
+ * <pre>
+ * PBMParameter ::= SEQUENCE {
+ * salt OCTET STRING,
+ * -- note: implementations MAY wish to limit acceptable sizes
+ * -- of this string to values appropriate for their environment
+ * -- in order to reduce the risk of denial-of-service attacks
+ * owf AlgorithmIdentifier,
+ * -- AlgId for a One-Way Function (SHA-1 recommended)
+ * iterationCount INTEGER,
+ * -- number of times the OWF is applied
+ * -- note: implementations MAY wish to limit acceptable sizes
+ * -- of this integer to values appropriate for their environment
+ * -- in order to reduce the risk of denial-of-service attacks
+ * mac AlgorithmIdentifier
+ * -- the MAC AlgId (e.g., DES-MAC, Triple-DES-MAC [PKCS11],
+ * } -- or HMAC [RFC2104, RFC2202])
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(salt);
+ v.add(owf);
+ v.add(iterationCount);
+ v.add(mac);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/PKIBody.java b/core/src/main/java/org/spongycastle/asn1/cmp/PKIBody.java
new file mode 100644
index 00000000..95b6a11c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PKIBody.java
@@ -0,0 +1,194 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.crmf.CertReqMessages;
+import org.spongycastle.asn1.pkcs.CertificationRequest;
+
+public class PKIBody
+ extends ASN1Object
+ implements ASN1Choice
+{
+ public static final int TYPE_INIT_REQ = 0;
+ public static final int TYPE_INIT_REP = 1;
+ public static final int TYPE_CERT_REQ = 2;
+ public static final int TYPE_CERT_REP = 3;
+ public static final int TYPE_P10_CERT_REQ = 4;
+ public static final int TYPE_POPO_CHALL = 5;
+ public static final int TYPE_POPO_REP = 6;
+ public static final int TYPE_KEY_UPDATE_REQ = 7;
+ public static final int TYPE_KEY_UPDATE_REP = 8;
+ public static final int TYPE_KEY_RECOVERY_REQ = 9;
+ public static final int TYPE_KEY_RECOVERY_REP = 10;
+ public static final int TYPE_REVOCATION_REQ = 11;
+ public static final int TYPE_REVOCATION_REP = 12;
+ public static final int TYPE_CROSS_CERT_REQ = 13;
+ public static final int TYPE_CROSS_CERT_REP = 14;
+ public static final int TYPE_CA_KEY_UPDATE_ANN = 15;
+ public static final int TYPE_CERT_ANN = 16;
+ public static final int TYPE_REVOCATION_ANN = 17;
+ public static final int TYPE_CRL_ANN = 18;
+ public static final int TYPE_CONFIRM = 19;
+ public static final int TYPE_NESTED = 20;
+ public static final int TYPE_GEN_MSG = 21;
+ public static final int TYPE_GEN_REP = 22;
+ public static final int TYPE_ERROR = 23;
+ public static final int TYPE_CERT_CONFIRM = 24;
+ public static final int TYPE_POLL_REQ = 25;
+ public static final int TYPE_POLL_REP = 26;
+
+ private int tagNo;
+ private ASN1Encodable body;
+
+ public static PKIBody getInstance(Object o)
+ {
+ if (o == null || o instanceof PKIBody)
+ {
+ return (PKIBody)o;
+ }
+
+ if (o instanceof ASN1TaggedObject)
+ {
+ return new PKIBody((ASN1TaggedObject)o);
+ }
+
+ throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
+ }
+
+ private PKIBody(ASN1TaggedObject tagged)
+ {
+ tagNo = tagged.getTagNo();
+ body = getBodyForType(tagNo, tagged.getObject());
+ }
+
+ /**
+ * Creates a new PKIBody.
+ * @param type one of the TYPE_* constants
+ * @param content message content
+ */
+ public PKIBody(
+ int type,
+ ASN1Encodable content)
+ {
+ tagNo = type;
+ body = getBodyForType(type, content);
+ }
+
+ private static ASN1Encodable getBodyForType(
+ int type,
+ ASN1Encodable o)
+ {
+ switch (type)
+ {
+ case TYPE_INIT_REQ:
+ return CertReqMessages.getInstance(o);
+ case TYPE_INIT_REP:
+ return CertRepMessage.getInstance(o);
+ case TYPE_CERT_REQ:
+ return CertReqMessages.getInstance(o);
+ case TYPE_CERT_REP:
+ return CertRepMessage.getInstance(o);
+ case TYPE_P10_CERT_REQ:
+ return CertificationRequest.getInstance(o);
+ case TYPE_POPO_CHALL:
+ return POPODecKeyChallContent.getInstance(o);
+ case TYPE_POPO_REP:
+ return POPODecKeyRespContent.getInstance(o);
+ case TYPE_KEY_UPDATE_REQ:
+ return CertReqMessages.getInstance(o);
+ case TYPE_KEY_UPDATE_REP:
+ return CertRepMessage.getInstance(o);
+ case TYPE_KEY_RECOVERY_REQ:
+ return CertReqMessages.getInstance(o);
+ case TYPE_KEY_RECOVERY_REP:
+ return KeyRecRepContent.getInstance(o);
+ case TYPE_REVOCATION_REQ:
+ return RevReqContent.getInstance(o);
+ case TYPE_REVOCATION_REP:
+ return RevRepContent.getInstance(o);
+ case TYPE_CROSS_CERT_REQ:
+ return CertReqMessages.getInstance(o);
+ case TYPE_CROSS_CERT_REP:
+ return CertRepMessage.getInstance(o);
+ case TYPE_CA_KEY_UPDATE_ANN:
+ return CAKeyUpdAnnContent.getInstance(o);
+ case TYPE_CERT_ANN:
+ return CMPCertificate.getInstance(o);
+ case TYPE_REVOCATION_ANN:
+ return RevAnnContent.getInstance(o);
+ case TYPE_CRL_ANN:
+ return CRLAnnContent.getInstance(o);
+ case TYPE_CONFIRM:
+ return PKIConfirmContent.getInstance(o);
+ case TYPE_NESTED:
+ return PKIMessages.getInstance(o);
+ case TYPE_GEN_MSG:
+ return GenMsgContent.getInstance(o);
+ case TYPE_GEN_REP:
+ return GenRepContent.getInstance(o);
+ case TYPE_ERROR:
+ return ErrorMsgContent.getInstance(o);
+ case TYPE_CERT_CONFIRM:
+ return CertConfirmContent.getInstance(o);
+ case TYPE_POLL_REQ:
+ return PollReqContent.getInstance(o);
+ case TYPE_POLL_REP:
+ return PollRepContent.getInstance(o);
+ default:
+ throw new IllegalArgumentException("unknown tag number: " + type);
+ }
+ }
+
+ public int getType()
+ {
+ return tagNo;
+ }
+
+ public ASN1Encodable getContent()
+ {
+ return body;
+ }
+
+ /**
+ * <pre>
+ * PKIBody ::= CHOICE { -- message-specific body elements
+ * ir [0] CertReqMessages, --Initialization Request
+ * ip [1] CertRepMessage, --Initialization Response
+ * cr [2] CertReqMessages, --Certification Request
+ * cp [3] CertRepMessage, --Certification Response
+ * p10cr [4] CertificationRequest, --imported from [PKCS10]
+ * popdecc [5] POPODecKeyChallContent, --pop Challenge
+ * popdecr [6] POPODecKeyRespContent, --pop Response
+ * kur [7] CertReqMessages, --Key Update Request
+ * kup [8] CertRepMessage, --Key Update Response
+ * krr [9] CertReqMessages, --Key Recovery Request
+ * krp [10] KeyRecRepContent, --Key Recovery Response
+ * rr [11] RevReqContent, --Revocation Request
+ * rp [12] RevRepContent, --Revocation Response
+ * ccr [13] CertReqMessages, --Cross-Cert. Request
+ * ccp [14] CertRepMessage, --Cross-Cert. Response
+ * ckuann [15] CAKeyUpdAnnContent, --CA Key Update Ann.
+ * cann [16] CertAnnContent, --Certificate Ann.
+ * rann [17] RevAnnContent, --Revocation Ann.
+ * crlann [18] CRLAnnContent, --CRL Announcement
+ * pkiconf [19] PKIConfirmContent, --Confirmation
+ * nested [20] NestedMessageContent, --Nested Message
+ * genm [21] GenMsgContent, --General Message
+ * genp [22] GenRepContent, --General Response
+ * error [23] ErrorMsgContent, --Error Message
+ * certConf [24] CertConfirmContent, --Certificate confirm
+ * pollReq [25] PollReqContent, --Polling request
+ * pollRep [26] PollRepContent --Polling response
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERTaggedObject(true, tagNo, body);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/PKIConfirmContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/PKIConfirmContent.java
new file mode 100644
index 00000000..4019779f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PKIConfirmContent.java
@@ -0,0 +1,48 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Null;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DERNull;
+
+public class PKIConfirmContent
+ extends ASN1Object
+{
+ private ASN1Null val;
+
+ private PKIConfirmContent(ASN1Null val)
+ {
+ this.val = val;
+ }
+
+ public static PKIConfirmContent getInstance(Object o)
+ {
+ if (o == null || o instanceof PKIConfirmContent)
+ {
+ return (PKIConfirmContent)o;
+ }
+
+ if (o instanceof ASN1Null)
+ {
+ return new PKIConfirmContent((ASN1Null)o);
+ }
+
+ throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
+ }
+
+ public PKIConfirmContent()
+ {
+ val = DERNull.INSTANCE;
+ }
+
+ /**
+ * <pre>
+ * PKIConfirmContent ::= NULL
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return val;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/PKIFailureInfo.java b/core/src/main/java/org/spongycastle/asn1/cmp/PKIFailureInfo.java
new file mode 100644
index 00000000..03dd5574
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PKIFailureInfo.java
@@ -0,0 +1,126 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.DERBitString;
+
+/**
+ * <pre>
+ * PKIFailureInfo ::= BIT STRING {
+ * badAlg (0),
+ * -- unrecognized or unsupported Algorithm Identifier
+ * badMessageCheck (1), -- integrity check failed (e.g., signature did not verify)
+ * badRequest (2),
+ * -- transaction not permitted or supported
+ * badTime (3), -- messageTime was not sufficiently close to the system time, as defined by local policy
+ * badCertId (4), -- no certificate could be found matching the provided criteria
+ * badDataFormat (5),
+ * -- the data submitted has the wrong format
+ * wrongAuthority (6), -- the authority indicated in the request is different from the one creating the response token
+ * incorrectData (7), -- the requester's data is incorrect (for notary services)
+ * missingTimeStamp (8), -- when the timestamp is missing but should be there (by policy)
+ * badPOP (9) -- the proof-of-possession failed
+ * certRevoked (10),
+ * certConfirmed (11),
+ * wrongIntegrity (12),
+ * badRecipientNonce (13),
+ * timeNotAvailable (14),
+ * -- the TSA's time source is not available
+ * unacceptedPolicy (15),
+ * -- the requested TSA policy is not supported by the TSA
+ * unacceptedExtension (16),
+ * -- the requested extension is not supported by the TSA
+ * addInfoNotAvailable (17)
+ * -- the additional information requested could not be understood
+ * -- or is not available
+ * badSenderNonce (18),
+ * badCertTemplate (19),
+ * signerNotTrusted (20),
+ * transactionIdInUse (21),
+ * unsupportedVersion (22),
+ * notAuthorized (23),
+ * systemUnavail (24),
+ * systemFailure (25),
+ * -- the request cannot be handled due to system failure
+ * duplicateCertReq (26)
+ * </pre>
+ */
+public class PKIFailureInfo
+ extends DERBitString
+{
+ public static final int badAlg = (1 << 7); // unrecognized or unsupported Algorithm Identifier
+ public static final int badMessageCheck = (1 << 6); // integrity check failed (e.g., signature did not verify)
+ public static final int badRequest = (1 << 5);
+ public static final int badTime = (1 << 4); // -- messageTime was not sufficiently close to the system time, as defined by local policy
+ public static final int badCertId = (1 << 3); // no certificate could be found matching the provided criteria
+ public static final int badDataFormat = (1 << 2);
+ public static final int wrongAuthority = (1 << 1); // the authority indicated in the request is different from the one creating the response token
+ public static final int incorrectData = 1; // the requester's data is incorrect (for notary services)
+ public static final int missingTimeStamp = (1 << 15); // when the timestamp is missing but should be there (by policy)
+ public static final int badPOP = (1 << 14); // the proof-of-possession failed
+ public static final int certRevoked = (1 << 13);
+ public static final int certConfirmed = (1 << 12);
+ public static final int wrongIntegrity = (1 << 11);
+ public static final int badRecipientNonce = (1 << 10);
+ public static final int timeNotAvailable = (1 << 9); // the TSA's time source is not available
+ public static final int unacceptedPolicy = (1 << 8); // the requested TSA policy is not supported by the TSA
+ public static final int unacceptedExtension = (1 << 23); //the requested extension is not supported by the TSA
+ public static final int addInfoNotAvailable = (1 << 22); //the additional information requested could not be understood or is not available
+ public static final int badSenderNonce = (1 << 21);
+ public static final int badCertTemplate = (1 << 20);
+ public static final int signerNotTrusted = (1 << 19);
+ public static final int transactionIdInUse = (1 << 18);
+ public static final int unsupportedVersion = (1 << 17);
+ public static final int notAuthorized = (1 << 16);
+ public static final int systemUnavail = (1 << 31);
+ public static final int systemFailure = (1 << 30); //the request cannot be handled due to system failure
+ public static final int duplicateCertReq = (1 << 29);
+
+ /** @deprecated use lower case version */
+ public static final int BAD_ALG = badAlg; // unrecognized or unsupported Algorithm Identifier
+ /** @deprecated use lower case version */
+ public static final int BAD_MESSAGE_CHECK = badMessageCheck;
+ /** @deprecated use lower case version */
+ public static final int BAD_REQUEST = badRequest; // transaction not permitted or supported
+ /** @deprecated use lower case version */
+ public static final int BAD_TIME = badTime;
+ /** @deprecated use lower case version */
+ public static final int BAD_CERT_ID = badCertId;
+ /** @deprecated use lower case version */
+ public static final int BAD_DATA_FORMAT = badDataFormat; // the data submitted has the wrong format
+ /** @deprecated use lower case version */
+ public static final int WRONG_AUTHORITY = wrongAuthority;
+ /** @deprecated use lower case version */
+ public static final int INCORRECT_DATA = incorrectData;
+ /** @deprecated use lower case version */
+ public static final int MISSING_TIME_STAMP = missingTimeStamp;
+ /** @deprecated use lower case version */
+ public static final int BAD_POP = badPOP;
+ /** @deprecated use lower case version */
+ public static final int TIME_NOT_AVAILABLE = timeNotAvailable;
+ /** @deprecated use lower case version */
+ public static final int UNACCEPTED_POLICY = unacceptedPolicy;
+ /** @deprecated use lower case version */
+ public static final int UNACCEPTED_EXTENSION = unacceptedExtension;
+ /** @deprecated use lower case version */
+ public static final int ADD_INFO_NOT_AVAILABLE = addInfoNotAvailable;
+ /** @deprecated use lower case version */
+ public static final int SYSTEM_FAILURE = systemFailure;
+ /**
+ * Basic constructor.
+ */
+ public PKIFailureInfo(
+ int info)
+ {
+ super(getBytes(info), getPadBits(info));
+ }
+
+ public PKIFailureInfo(
+ DERBitString info)
+ {
+ super(info.getBytes(), info.getPadBits());
+ }
+
+ public String toString()
+ {
+ return "PKIFailureInfo: 0x" + Integer.toHexString(this.intValue());
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/PKIFreeText.java b/core/src/main/java/org/spongycastle/asn1/cmp/PKIFreeText.java
new file mode 100644
index 00000000..8a10714f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PKIFreeText.java
@@ -0,0 +1,115 @@
+package org.spongycastle.asn1.cmp;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERUTF8String;
+
+public class PKIFreeText
+ extends ASN1Object
+{
+ ASN1Sequence strings;
+
+ public static PKIFreeText getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static PKIFreeText getInstance(
+ Object obj)
+ {
+ if (obj instanceof PKIFreeText)
+ {
+ return (PKIFreeText)obj;
+ }
+ else if (obj != null)
+ {
+ return new PKIFreeText(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private PKIFreeText(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+ while (e.hasMoreElements())
+ {
+ if (!(e.nextElement() instanceof DERUTF8String))
+ {
+ throw new IllegalArgumentException("attempt to insert non UTF8 STRING into PKIFreeText");
+ }
+ }
+
+ strings = seq;
+ }
+
+ public PKIFreeText(
+ DERUTF8String p)
+ {
+ strings = new DERSequence(p);
+ }
+
+ public PKIFreeText(
+ String p)
+ {
+ this(new DERUTF8String(p));
+ }
+
+ public PKIFreeText(
+ DERUTF8String[] strs)
+ {
+ strings = new DERSequence(strs);
+ }
+
+ public PKIFreeText(
+ String[] strs)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < strs.length; i++)
+ {
+ v.add(new DERUTF8String(strs[i]));
+ }
+ strings = new DERSequence(v);
+ }
+
+ /**
+ * Return the number of string elements present.
+ *
+ * @return number of elements present.
+ */
+ public int size()
+ {
+ return strings.size();
+ }
+
+ /**
+ * Return the UTF8STRING at index i.
+ *
+ * @param i index of the string of interest
+ * @return the string at index i.
+ */
+ public DERUTF8String getStringAt(
+ int i)
+ {
+ return (DERUTF8String)strings.getObjectAt(i);
+ }
+
+ /**
+ * <pre>
+ * PKIFreeText ::= SEQUENCE SIZE (1..MAX) OF UTF8String
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return strings;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/PKIHeader.java b/core/src/main/java/org/spongycastle/asn1/cmp/PKIHeader.java
new file mode 100644
index 00000000..afcd7767
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PKIHeader.java
@@ -0,0 +1,260 @@
+package org.spongycastle.asn1.cmp;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x500.X500Name;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.GeneralName;
+
+public class PKIHeader
+ extends ASN1Object
+{
+ /**
+ * Value for a "null" recipient or sender.
+ */
+ public static final GeneralName NULL_NAME = new GeneralName(X500Name.getInstance(new DERSequence()));
+
+ public static final int CMP_1999 = 1;
+ public static final int CMP_2000 = 2;
+
+ private ASN1Integer pvno;
+ private GeneralName sender;
+ private GeneralName recipient;
+ private ASN1GeneralizedTime messageTime;
+ private AlgorithmIdentifier protectionAlg;
+ private ASN1OctetString senderKID; // KeyIdentifier
+ private ASN1OctetString recipKID; // KeyIdentifier
+ private ASN1OctetString transactionID;
+ private ASN1OctetString senderNonce;
+ private ASN1OctetString recipNonce;
+ private PKIFreeText freeText;
+ private ASN1Sequence generalInfo;
+
+ private PKIHeader(ASN1Sequence seq)
+ {
+ Enumeration en = seq.getObjects();
+
+ pvno = ASN1Integer.getInstance(en.nextElement());
+ sender = GeneralName.getInstance(en.nextElement());
+ recipient = GeneralName.getInstance(en.nextElement());
+
+ while (en.hasMoreElements())
+ {
+ ASN1TaggedObject tObj = (ASN1TaggedObject)en.nextElement();
+
+ switch (tObj.getTagNo())
+ {
+ case 0:
+ messageTime = ASN1GeneralizedTime.getInstance(tObj, true);
+ break;
+ case 1:
+ protectionAlg = AlgorithmIdentifier.getInstance(tObj, true);
+ break;
+ case 2:
+ senderKID = ASN1OctetString.getInstance(tObj, true);
+ break;
+ case 3:
+ recipKID = ASN1OctetString.getInstance(tObj, true);
+ break;
+ case 4:
+ transactionID = ASN1OctetString.getInstance(tObj, true);
+ break;
+ case 5:
+ senderNonce = ASN1OctetString.getInstance(tObj, true);
+ break;
+ case 6:
+ recipNonce = ASN1OctetString.getInstance(tObj, true);
+ break;
+ case 7:
+ freeText = PKIFreeText.getInstance(tObj, true);
+ break;
+ case 8:
+ generalInfo = ASN1Sequence.getInstance(tObj, true);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag number: " + tObj.getTagNo());
+ }
+ }
+ }
+
+ public static PKIHeader getInstance(Object o)
+ {
+ if (o instanceof PKIHeader)
+ {
+ return (PKIHeader)o;
+ }
+
+ if (o != null)
+ {
+ return new PKIHeader(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public PKIHeader(
+ int pvno,
+ GeneralName sender,
+ GeneralName recipient)
+ {
+ this(new ASN1Integer(pvno), sender, recipient);
+ }
+
+ private PKIHeader(
+ ASN1Integer pvno,
+ GeneralName sender,
+ GeneralName recipient)
+ {
+ this.pvno = pvno;
+ this.sender = sender;
+ this.recipient = recipient;
+ }
+
+ public ASN1Integer getPvno()
+ {
+ return pvno;
+ }
+
+ public GeneralName getSender()
+ {
+ return sender;
+ }
+
+ public GeneralName getRecipient()
+ {
+ return recipient;
+ }
+
+ public ASN1GeneralizedTime getMessageTime()
+ {
+ return messageTime;
+ }
+
+ public AlgorithmIdentifier getProtectionAlg()
+ {
+ return protectionAlg;
+ }
+
+ public ASN1OctetString getSenderKID()
+ {
+ return senderKID;
+ }
+
+ public ASN1OctetString getRecipKID()
+ {
+ return recipKID;
+ }
+
+ public ASN1OctetString getTransactionID()
+ {
+ return transactionID;
+ }
+
+ public ASN1OctetString getSenderNonce()
+ {
+ return senderNonce;
+ }
+
+ public ASN1OctetString getRecipNonce()
+ {
+ return recipNonce;
+ }
+
+ public PKIFreeText getFreeText()
+ {
+ return freeText;
+ }
+
+ public InfoTypeAndValue[] getGeneralInfo()
+ {
+ if (generalInfo == null)
+ {
+ return null;
+ }
+ InfoTypeAndValue[] results = new InfoTypeAndValue[generalInfo.size()];
+ for (int i = 0; i < results.length; i++)
+ {
+ results[i]
+ = InfoTypeAndValue.getInstance(generalInfo.getObjectAt(i));
+ }
+ return results;
+ }
+
+ /**
+ * <pre>
+ * PKIHeader ::= SEQUENCE {
+ * pvno INTEGER { cmp1999(1), cmp2000(2) },
+ * sender GeneralName,
+ * -- identifies the sender
+ * recipient GeneralName,
+ * -- identifies the intended recipient
+ * messageTime [0] GeneralizedTime OPTIONAL,
+ * -- time of production of this message (used when sender
+ * -- believes that the transport will be "suitable"; i.e.,
+ * -- that the time will still be meaningful upon receipt)
+ * protectionAlg [1] AlgorithmIdentifier OPTIONAL,
+ * -- algorithm used for calculation of protection bits
+ * senderKID [2] KeyIdentifier OPTIONAL,
+ * recipKID [3] KeyIdentifier OPTIONAL,
+ * -- to identify specific keys used for protection
+ * transactionID [4] OCTET STRING OPTIONAL,
+ * -- identifies the transaction; i.e., this will be the same in
+ * -- corresponding request, response, certConf, and PKIConf
+ * -- messages
+ * senderNonce [5] OCTET STRING OPTIONAL,
+ * recipNonce [6] OCTET STRING OPTIONAL,
+ * -- nonces used to provide replay protection, senderNonce
+ * -- is inserted by the creator of this message; recipNonce
+ * -- is a nonce previously inserted in a related message by
+ * -- the intended recipient of this message
+ * freeText [7] PKIFreeText OPTIONAL,
+ * -- this may be used to indicate context-specific instructions
+ * -- (this field is intended for human consumption)
+ * generalInfo [8] SEQUENCE SIZE (1..MAX) OF
+ * InfoTypeAndValue OPTIONAL
+ * -- this may be used to convey context-specific information
+ * -- (this field not primarily intended for human consumption)
+ * }
+ * </pre>
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(pvno);
+ v.add(sender);
+ v.add(recipient);
+ addOptional(v, 0, messageTime);
+ addOptional(v, 1, protectionAlg);
+ addOptional(v, 2, senderKID);
+ addOptional(v, 3, recipKID);
+ addOptional(v, 4, transactionID);
+ addOptional(v, 5, senderNonce);
+ addOptional(v, 6, recipNonce);
+ addOptional(v, 7, freeText);
+ addOptional(v, 8, generalInfo);
+
+ return new DERSequence(v);
+ }
+
+ private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(new DERTaggedObject(true, tagNo, obj));
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/PKIHeaderBuilder.java b/core/src/main/java/org/spongycastle/asn1/cmp/PKIHeaderBuilder.java
new file mode 100644
index 00000000..5249c5e0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PKIHeaderBuilder.java
@@ -0,0 +1,243 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.GeneralName;
+
+public class PKIHeaderBuilder
+{
+ private ASN1Integer pvno;
+ private GeneralName sender;
+ private GeneralName recipient;
+ private ASN1GeneralizedTime messageTime;
+ private AlgorithmIdentifier protectionAlg;
+ private ASN1OctetString senderKID; // KeyIdentifier
+ private ASN1OctetString recipKID; // KeyIdentifier
+ private ASN1OctetString transactionID;
+ private ASN1OctetString senderNonce;
+ private ASN1OctetString recipNonce;
+ private PKIFreeText freeText;
+ private ASN1Sequence generalInfo;
+
+ public PKIHeaderBuilder(
+ int pvno,
+ GeneralName sender,
+ GeneralName recipient)
+ {
+ this(new ASN1Integer(pvno), sender, recipient);
+ }
+
+ private PKIHeaderBuilder(
+ ASN1Integer pvno,
+ GeneralName sender,
+ GeneralName recipient)
+ {
+ this.pvno = pvno;
+ this.sender = sender;
+ this.recipient = recipient;
+ }
+
+ public PKIHeaderBuilder setMessageTime(ASN1GeneralizedTime time)
+ {
+ messageTime = time;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setProtectionAlg(AlgorithmIdentifier aid)
+ {
+ protectionAlg = aid;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setSenderKID(byte[] kid)
+ {
+ return setSenderKID(kid == null ? null : new DEROctetString(kid));
+ }
+
+ public PKIHeaderBuilder setSenderKID(ASN1OctetString kid)
+ {
+ senderKID = kid;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setRecipKID(byte[] kid)
+ {
+ return setRecipKID(kid == null ? null : new DEROctetString(kid));
+ }
+
+ public PKIHeaderBuilder setRecipKID(DEROctetString kid)
+ {
+ recipKID = kid;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setTransactionID(byte[] tid)
+ {
+ return setTransactionID(tid == null ? null : new DEROctetString(tid));
+ }
+
+ public PKIHeaderBuilder setTransactionID(ASN1OctetString tid)
+ {
+ transactionID = tid;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setSenderNonce(byte[] nonce)
+ {
+ return setSenderNonce(nonce == null ? null : new DEROctetString(nonce));
+ }
+
+ public PKIHeaderBuilder setSenderNonce(ASN1OctetString nonce)
+ {
+ senderNonce = nonce;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setRecipNonce(byte[] nonce)
+ {
+ return setRecipNonce(nonce == null ? null : new DEROctetString(nonce));
+ }
+
+ public PKIHeaderBuilder setRecipNonce(ASN1OctetString nonce)
+ {
+ recipNonce = nonce;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setFreeText(PKIFreeText text)
+ {
+ freeText = text;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setGeneralInfo(InfoTypeAndValue genInfo)
+ {
+ return setGeneralInfo(makeGeneralInfoSeq(genInfo));
+ }
+
+ public PKIHeaderBuilder setGeneralInfo(InfoTypeAndValue[] genInfos)
+ {
+ return setGeneralInfo(makeGeneralInfoSeq(genInfos));
+ }
+
+ public PKIHeaderBuilder setGeneralInfo(ASN1Sequence seqOfInfoTypeAndValue)
+ {
+ generalInfo = seqOfInfoTypeAndValue;
+
+ return this;
+ }
+
+ private static ASN1Sequence makeGeneralInfoSeq(
+ InfoTypeAndValue generalInfo)
+ {
+ return new DERSequence(generalInfo);
+ }
+
+ private static ASN1Sequence makeGeneralInfoSeq(
+ InfoTypeAndValue[] generalInfos)
+ {
+ ASN1Sequence genInfoSeq = null;
+ if (generalInfos != null)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < generalInfos.length; i++)
+ {
+ v.add(generalInfos[i]);
+ }
+ genInfoSeq = new DERSequence(v);
+ }
+ return genInfoSeq;
+ }
+
+ /**
+ * <pre>
+ * PKIHeader ::= SEQUENCE {
+ * pvno INTEGER { cmp1999(1), cmp2000(2) },
+ * sender GeneralName,
+ * -- identifies the sender
+ * recipient GeneralName,
+ * -- identifies the intended recipient
+ * messageTime [0] GeneralizedTime OPTIONAL,
+ * -- time of production of this message (used when sender
+ * -- believes that the transport will be "suitable"; i.e.,
+ * -- that the time will still be meaningful upon receipt)
+ * protectionAlg [1] AlgorithmIdentifier OPTIONAL,
+ * -- algorithm used for calculation of protection bits
+ * senderKID [2] KeyIdentifier OPTIONAL,
+ * recipKID [3] KeyIdentifier OPTIONAL,
+ * -- to identify specific keys used for protection
+ * transactionID [4] OCTET STRING OPTIONAL,
+ * -- identifies the transaction; i.e., this will be the same in
+ * -- corresponding request, response, certConf, and PKIConf
+ * -- messages
+ * senderNonce [5] OCTET STRING OPTIONAL,
+ * recipNonce [6] OCTET STRING OPTIONAL,
+ * -- nonces used to provide replay protection, senderNonce
+ * -- is inserted by the creator of this message; recipNonce
+ * -- is a nonce previously inserted in a related message by
+ * -- the intended recipient of this message
+ * freeText [7] PKIFreeText OPTIONAL,
+ * -- this may be used to indicate context-specific instructions
+ * -- (this field is intended for human consumption)
+ * generalInfo [8] SEQUENCE SIZE (1..MAX) OF
+ * InfoTypeAndValue OPTIONAL
+ * -- this may be used to convey context-specific information
+ * -- (this field not primarily intended for human consumption)
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public PKIHeader build()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(pvno);
+ v.add(sender);
+ v.add(recipient);
+ addOptional(v, 0, messageTime);
+ addOptional(v, 1, protectionAlg);
+ addOptional(v, 2, senderKID);
+ addOptional(v, 3, recipKID);
+ addOptional(v, 4, transactionID);
+ addOptional(v, 5, senderNonce);
+ addOptional(v, 6, recipNonce);
+ addOptional(v, 7, freeText);
+ addOptional(v, 8, generalInfo);
+
+ messageTime = null;
+ protectionAlg = null;
+ senderKID = null;
+ recipKID = null;
+ transactionID = null;
+ senderNonce = null;
+ recipNonce = null;
+ freeText = null;
+ generalInfo = null;
+
+ return PKIHeader.getInstance(new DERSequence(v));
+ }
+
+ private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(new DERTaggedObject(true, tagNo, obj));
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/PKIMessage.java b/core/src/main/java/org/spongycastle/asn1/cmp/PKIMessage.java
new file mode 100644
index 00000000..fbb4dfe7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PKIMessage.java
@@ -0,0 +1,166 @@
+package org.spongycastle.asn1.cmp;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+public class PKIMessage
+ extends ASN1Object
+{
+ private PKIHeader header;
+ private PKIBody body;
+ private DERBitString protection;
+ private ASN1Sequence extraCerts;
+
+ private PKIMessage(ASN1Sequence seq)
+ {
+ Enumeration en = seq.getObjects();
+
+ header = PKIHeader.getInstance(en.nextElement());
+ body = PKIBody.getInstance(en.nextElement());
+
+ while (en.hasMoreElements())
+ {
+ ASN1TaggedObject tObj = (ASN1TaggedObject)en.nextElement();
+
+ if (tObj.getTagNo() == 0)
+ {
+ protection = DERBitString.getInstance(tObj, true);
+ }
+ else
+ {
+ extraCerts = ASN1Sequence.getInstance(tObj, true);
+ }
+ }
+ }
+
+ public static PKIMessage getInstance(Object o)
+ {
+ if (o instanceof PKIMessage)
+ {
+ return (PKIMessage)o;
+ }
+ else if (o != null)
+ {
+ return new PKIMessage(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ /**
+ * Creates a new PKIMessage.
+ *
+ * @param header message header
+ * @param body message body
+ * @param protection message protection (may be null)
+ * @param extraCerts extra certificates (may be null)
+ */
+ public PKIMessage(
+ PKIHeader header,
+ PKIBody body,
+ DERBitString protection,
+ CMPCertificate[] extraCerts)
+ {
+ this.header = header;
+ this.body = body;
+ this.protection = protection;
+ if (extraCerts != null)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < extraCerts.length; i++)
+ {
+ v.add(extraCerts[i]);
+ }
+ this.extraCerts = new DERSequence(v);
+ }
+ }
+
+ public PKIMessage(
+ PKIHeader header,
+ PKIBody body,
+ DERBitString protection)
+ {
+ this(header, body, protection, null);
+ }
+
+ public PKIMessage(
+ PKIHeader header,
+ PKIBody body)
+ {
+ this(header, body, null, null);
+ }
+
+ public PKIHeader getHeader()
+ {
+ return header;
+ }
+
+ public PKIBody getBody()
+ {
+ return body;
+ }
+
+ public DERBitString getProtection()
+ {
+ return protection;
+ }
+
+ public CMPCertificate[] getExtraCerts()
+ {
+ if (extraCerts == null)
+ {
+ return null;
+ }
+
+ CMPCertificate[] results = new CMPCertificate[extraCerts.size()];
+
+ for (int i = 0; i < results.length; i++)
+ {
+ results[i] = CMPCertificate.getInstance(extraCerts.getObjectAt(i));
+ }
+ return results;
+ }
+
+ /**
+ * <pre>
+ * PKIMessage ::= SEQUENCE {
+ * header PKIHeader,
+ * body PKIBody,
+ * protection [0] PKIProtection OPTIONAL,
+ * extraCerts [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
+ * OPTIONAL
+ * }
+ * </pre>
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(header);
+ v.add(body);
+
+ addOptional(v, 0, protection);
+ addOptional(v, 1, extraCerts);
+
+ return new DERSequence(v);
+ }
+
+ private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(new DERTaggedObject(true, tagNo, obj));
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/PKIMessages.java b/core/src/main/java/org/spongycastle/asn1/cmp/PKIMessages.java
new file mode 100644
index 00000000..33b47323
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PKIMessages.java
@@ -0,0 +1,71 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class PKIMessages
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private PKIMessages(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static PKIMessages getInstance(Object o)
+ {
+ if (o instanceof PKIMessages)
+ {
+ return (PKIMessages)o;
+ }
+
+ if (o != null)
+ {
+ return new PKIMessages(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public PKIMessages(PKIMessage msg)
+ {
+ content = new DERSequence(msg);
+ }
+
+ public PKIMessages(PKIMessage[] msgs)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < msgs.length; i++)
+ {
+ v.add(msgs[i]);
+ }
+ content = new DERSequence(v);
+ }
+
+ public PKIMessage[] toPKIMessageArray()
+ {
+ PKIMessage[] result = new PKIMessage[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = PKIMessage.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ * <pre>
+ * PKIMessages ::= SEQUENCE SIZE (1..MAX) OF PKIMessage
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/PKIStatus.java b/core/src/main/java/org/spongycastle/asn1/cmp/PKIStatus.java
new file mode 100644
index 00000000..af4235f1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PKIStatus.java
@@ -0,0 +1,64 @@
+package org.spongycastle.asn1.cmp;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+
+public class PKIStatus
+ extends ASN1Object
+{
+ public static final int GRANTED = 0;
+ public static final int GRANTED_WITH_MODS = 1;
+ public static final int REJECTION = 2;
+ public static final int WAITING = 3;
+ public static final int REVOCATION_WARNING = 4;
+ public static final int REVOCATION_NOTIFICATION = 5;
+ public static final int KEY_UPDATE_WARNING = 6;
+
+ public static final PKIStatus granted = new PKIStatus(GRANTED);
+ public static final PKIStatus grantedWithMods = new PKIStatus(GRANTED_WITH_MODS);
+ public static final PKIStatus rejection = new PKIStatus(REJECTION);
+ public static final PKIStatus waiting = new PKIStatus(WAITING);
+ public static final PKIStatus revocationWarning = new PKIStatus(REVOCATION_WARNING);
+ public static final PKIStatus revocationNotification = new PKIStatus(REVOCATION_NOTIFICATION);
+ public static final PKIStatus keyUpdateWaiting = new PKIStatus(KEY_UPDATE_WARNING);
+
+ private ASN1Integer value;
+
+ private PKIStatus(int value)
+ {
+ this(new ASN1Integer(value));
+ }
+
+ private PKIStatus(ASN1Integer value)
+ {
+ this.value = value;
+ }
+
+ public static PKIStatus getInstance(Object o)
+ {
+ if (o instanceof PKIStatus)
+ {
+ return (PKIStatus)o;
+ }
+
+ if (o != null)
+ {
+ return new PKIStatus(ASN1Integer.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public BigInteger getValue()
+ {
+ return value.getValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return value;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/PKIStatusInfo.java b/core/src/main/java/org/spongycastle/asn1/cmp/PKIStatusInfo.java
new file mode 100644
index 00000000..5deae95f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PKIStatusInfo.java
@@ -0,0 +1,165 @@
+package org.spongycastle.asn1.cmp;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+
+public class PKIStatusInfo
+ extends ASN1Object
+{
+ ASN1Integer status;
+ PKIFreeText statusString;
+ DERBitString failInfo;
+
+ public static PKIStatusInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static PKIStatusInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof PKIStatusInfo)
+ {
+ return (PKIStatusInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new PKIStatusInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private PKIStatusInfo(
+ ASN1Sequence seq)
+ {
+ this.status = ASN1Integer.getInstance(seq.getObjectAt(0));
+
+ this.statusString = null;
+ this.failInfo = null;
+
+ if (seq.size() > 2)
+ {
+ this.statusString = PKIFreeText.getInstance(seq.getObjectAt(1));
+ this.failInfo = DERBitString.getInstance(seq.getObjectAt(2));
+ }
+ else if (seq.size() > 1)
+ {
+ Object obj = seq.getObjectAt(1);
+ if (obj instanceof DERBitString)
+ {
+ this.failInfo = DERBitString.getInstance(obj);
+ }
+ else
+ {
+ this.statusString = PKIFreeText.getInstance(obj);
+ }
+ }
+ }
+
+ /**
+ * @param status
+ */
+ public PKIStatusInfo(PKIStatus status)
+ {
+ this.status = ASN1Integer.getInstance(status.toASN1Primitive());
+ }
+
+ /**
+ *
+ * @param status
+ * @param statusString
+ */
+ public PKIStatusInfo(
+ PKIStatus status,
+ PKIFreeText statusString)
+ {
+ this.status = ASN1Integer.getInstance(status.toASN1Primitive());
+ this.statusString = statusString;
+ }
+
+ public PKIStatusInfo(
+ PKIStatus status,
+ PKIFreeText statusString,
+ PKIFailureInfo failInfo)
+ {
+ this.status = ASN1Integer.getInstance(status.toASN1Primitive());
+ this.statusString = statusString;
+ this.failInfo = failInfo;
+ }
+
+ public BigInteger getStatus()
+ {
+ return status.getValue();
+ }
+
+ public PKIFreeText getStatusString()
+ {
+ return statusString;
+ }
+
+ public DERBitString getFailInfo()
+ {
+ return failInfo;
+ }
+
+ /**
+ * <pre>
+ * PKIStatusInfo ::= SEQUENCE {
+ * status PKIStatus, (INTEGER)
+ * statusString PKIFreeText OPTIONAL,
+ * failInfo PKIFailureInfo OPTIONAL (BIT STRING)
+ * }
+ *
+ * PKIStatus:
+ * granted (0), -- you got exactly what you asked for
+ * grantedWithMods (1), -- you got something like what you asked for
+ * rejection (2), -- you don't get it, more information elsewhere in the message
+ * waiting (3), -- the request body part has not yet been processed, expect to hear more later
+ * revocationWarning (4), -- this message contains a warning that a revocation is imminent
+ * revocationNotification (5), -- notification that a revocation has occurred
+ * keyUpdateWarning (6) -- update already done for the oldCertId specified in CertReqMsg
+ *
+ * PKIFailureInfo:
+ * badAlg (0), -- unrecognized or unsupported Algorithm Identifier
+ * badMessageCheck (1), -- integrity check failed (e.g., signature did not verify)
+ * badRequest (2), -- transaction not permitted or supported
+ * badTime (3), -- messageTime was not sufficiently close to the system time, as defined by local policy
+ * badCertId (4), -- no certificate could be found matching the provided criteria
+ * badDataFormat (5), -- the data submitted has the wrong format
+ * wrongAuthority (6), -- the authority indicated in the request is different from the one creating the response token
+ * incorrectData (7), -- the requester's data is incorrect (for notary services)
+ * missingTimeStamp (8), -- when the timestamp is missing but should be there (by policy)
+ * badPOP (9) -- the proof-of-possession failed
+ *
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(status);
+
+ if (statusString != null)
+ {
+ v.add(statusString);
+ }
+
+ if (failInfo!= null)
+ {
+ v.add(failInfo);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/POPODecKeyChallContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/POPODecKeyChallContent.java
new file mode 100644
index 00000000..2c636143
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/POPODecKeyChallContent.java
@@ -0,0 +1,54 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+
+public class POPODecKeyChallContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private POPODecKeyChallContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static POPODecKeyChallContent getInstance(Object o)
+ {
+ if (o instanceof POPODecKeyChallContent)
+ {
+ return (POPODecKeyChallContent)o;
+ }
+
+ if (o != null)
+ {
+ return new POPODecKeyChallContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public Challenge[] toChallengeArray()
+ {
+ Challenge[] result = new Challenge[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = Challenge.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ * <pre>
+ * POPODecKeyChallContent ::= SEQUENCE OF Challenge
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/POPODecKeyRespContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/POPODecKeyRespContent.java
new file mode 100644
index 00000000..48466b89
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/POPODecKeyRespContent.java
@@ -0,0 +1,55 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+
+public class POPODecKeyRespContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private POPODecKeyRespContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static POPODecKeyRespContent getInstance(Object o)
+ {
+ if (o instanceof POPODecKeyRespContent)
+ {
+ return (POPODecKeyRespContent)o;
+ }
+
+ if (o != null)
+ {
+ return new POPODecKeyRespContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer[] toASN1IntegerArray()
+ {
+ ASN1Integer[] result = new ASN1Integer[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = ASN1Integer.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ * <pre>
+ * POPODecKeyRespContent ::= SEQUENCE OF INTEGER
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/PollRepContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/PollRepContent.java
new file mode 100644
index 00000000..d2116b9a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PollRepContent.java
@@ -0,0 +1,119 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class PollRepContent
+ extends ASN1Object
+{
+ private ASN1Integer[] certReqId;
+ private ASN1Integer[] checkAfter;
+ private PKIFreeText[] reason;
+
+ private PollRepContent(ASN1Sequence seq)
+ {
+ certReqId = new ASN1Integer[seq.size()];
+ checkAfter = new ASN1Integer[seq.size()];
+ reason = new PKIFreeText[seq.size()];
+
+ for (int i = 0; i != seq.size(); i++)
+ {
+ ASN1Sequence s = ASN1Sequence.getInstance(seq.getObjectAt(i));
+
+ certReqId[i] = ASN1Integer.getInstance(s.getObjectAt(0));
+ checkAfter[i] = ASN1Integer.getInstance(s.getObjectAt(1));
+
+ if (s.size() > 2)
+ {
+ reason[i] = PKIFreeText.getInstance(s.getObjectAt(2));
+ }
+ }
+ }
+
+ public static PollRepContent getInstance(Object o)
+ {
+ if (o instanceof PollRepContent)
+ {
+ return (PollRepContent)o;
+ }
+
+ if (o != null)
+ {
+ return new PollRepContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public PollRepContent(ASN1Integer certReqId, ASN1Integer checkAfter)
+ {
+ this(certReqId, checkAfter, null);
+ }
+
+ public PollRepContent(ASN1Integer certReqId, ASN1Integer checkAfter, PKIFreeText reason)
+ {
+ this.certReqId = new ASN1Integer[1];
+ this.checkAfter = new ASN1Integer[1];
+ this.reason = new PKIFreeText[1];
+
+ this.certReqId[0] = certReqId;
+ this.checkAfter[0] = checkAfter;
+ this.reason[0] = reason;
+ }
+
+ public int size()
+ {
+ return certReqId.length;
+ }
+
+ public ASN1Integer getCertReqId(int index)
+ {
+ return certReqId[index];
+ }
+
+ public ASN1Integer getCheckAfter(int index)
+ {
+ return checkAfter[index];
+ }
+
+ public PKIFreeText getReason(int index)
+ {
+ return reason[index];
+ }
+
+ /**
+ * <pre>
+ * PollRepContent ::= SEQUENCE OF SEQUENCE {
+ * certReqId INTEGER,
+ * checkAfter INTEGER, -- time in seconds
+ * reason PKIFreeText OPTIONAL
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector outer = new ASN1EncodableVector();
+
+ for (int i = 0; i != certReqId.length; i++)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certReqId[i]);
+ v.add(checkAfter[i]);
+
+ if (reason[i] != null)
+ {
+ v.add(reason[i]);
+ }
+
+ outer.add(new DERSequence(v));
+ }
+
+ return new DERSequence(outer);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/PollReqContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/PollReqContent.java
new file mode 100644
index 00000000..58bfbd08
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/PollReqContent.java
@@ -0,0 +1,80 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class PollReqContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private PollReqContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static PollReqContent getInstance(Object o)
+ {
+ if (o instanceof PollReqContent)
+ {
+ return (PollReqContent)o;
+ }
+
+ if (o != null)
+ {
+ return new PollReqContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ /**
+ * Create a pollReqContent for a single certReqId.
+ *
+ * @param certReqId the certificate request ID.
+ */
+ public PollReqContent(ASN1Integer certReqId)
+ {
+ this(new DERSequence(new DERSequence(certReqId)));
+ }
+
+ public ASN1Integer[][] getCertReqIds()
+ {
+ ASN1Integer[][] result = new ASN1Integer[content.size()][];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = sequenceToASN1IntegerArray((ASN1Sequence)content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ private static ASN1Integer[] sequenceToASN1IntegerArray(ASN1Sequence seq)
+ {
+ ASN1Integer[] result = new ASN1Integer[seq.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = ASN1Integer.getInstance(seq.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ * <pre>
+ * PollReqContent ::= SEQUENCE OF SEQUENCE {
+ * certReqId INTEGER
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/ProtectedPart.java b/core/src/main/java/org/spongycastle/asn1/cmp/ProtectedPart.java
new file mode 100644
index 00000000..7594e8ec
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/ProtectedPart.java
@@ -0,0 +1,70 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class ProtectedPart
+ extends ASN1Object
+{
+ private PKIHeader header;
+ private PKIBody body;
+
+ private ProtectedPart(ASN1Sequence seq)
+ {
+ header = PKIHeader.getInstance(seq.getObjectAt(0));
+ body = PKIBody.getInstance(seq.getObjectAt(1));
+ }
+
+ public static ProtectedPart getInstance(Object o)
+ {
+ if (o instanceof ProtectedPart)
+ {
+ return (ProtectedPart)o;
+ }
+
+ if (o != null)
+ {
+ return new ProtectedPart(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public ProtectedPart(PKIHeader header, PKIBody body)
+ {
+ this.header = header;
+ this.body = body;
+ }
+
+ public PKIHeader getHeader()
+ {
+ return header;
+ }
+
+ public PKIBody getBody()
+ {
+ return body;
+ }
+
+ /**
+ * <pre>
+ * ProtectedPart ::= SEQUENCE {
+ * header PKIHeader,
+ * body PKIBody
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(header);
+ v.add(body);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/RevAnnContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/RevAnnContent.java
new file mode 100644
index 00000000..39d4de9e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/RevAnnContent.java
@@ -0,0 +1,103 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.crmf.CertId;
+import org.spongycastle.asn1.x509.Extensions;
+
+public class RevAnnContent
+ extends ASN1Object
+{
+ private PKIStatus status;
+ private CertId certId;
+ private ASN1GeneralizedTime willBeRevokedAt;
+ private ASN1GeneralizedTime badSinceDate;
+ private Extensions crlDetails;
+
+ private RevAnnContent(ASN1Sequence seq)
+ {
+ status = PKIStatus.getInstance(seq.getObjectAt(0));
+ certId = CertId.getInstance(seq.getObjectAt(1));
+ willBeRevokedAt = ASN1GeneralizedTime.getInstance(seq.getObjectAt(2));
+ badSinceDate = ASN1GeneralizedTime.getInstance(seq.getObjectAt(3));
+
+ if (seq.size() > 4)
+ {
+ crlDetails = Extensions.getInstance(seq.getObjectAt(4));
+ }
+ }
+
+ public static RevAnnContent getInstance(Object o)
+ {
+ if (o instanceof RevAnnContent)
+ {
+ return (RevAnnContent)o;
+ }
+
+ if (o != null)
+ {
+ return new RevAnnContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public PKIStatus getStatus()
+ {
+ return status;
+ }
+
+ public CertId getCertId()
+ {
+ return certId;
+ }
+
+ public ASN1GeneralizedTime getWillBeRevokedAt()
+ {
+ return willBeRevokedAt;
+ }
+
+ public ASN1GeneralizedTime getBadSinceDate()
+ {
+ return badSinceDate;
+ }
+
+ public Extensions getCrlDetails()
+ {
+ return crlDetails;
+ }
+
+ /**
+ * <pre>
+ * RevAnnContent ::= SEQUENCE {
+ * status PKIStatus,
+ * certId CertId,
+ * willBeRevokedAt GeneralizedTime,
+ * badSinceDate GeneralizedTime,
+ * crlDetails Extensions OPTIONAL
+ * -- extra CRL details (e.g., crl number, reason, location, etc.)
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(status);
+ v.add(certId);
+ v.add(willBeRevokedAt);
+ v.add(badSinceDate);
+
+ if (crlDetails != null)
+ {
+ v.add(crlDetails);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/RevDetails.java b/core/src/main/java/org/spongycastle/asn1/cmp/RevDetails.java
new file mode 100644
index 00000000..6009a3be
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/RevDetails.java
@@ -0,0 +1,100 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.crmf.CertTemplate;
+import org.spongycastle.asn1.x509.Extensions;
+import org.spongycastle.asn1.x509.X509Extensions;
+
+public class RevDetails
+ extends ASN1Object
+{
+ private CertTemplate certDetails;
+ private Extensions crlEntryDetails;
+
+ private RevDetails(ASN1Sequence seq)
+ {
+ certDetails = CertTemplate.getInstance(seq.getObjectAt(0));
+ if (seq.size() > 1)
+ {
+ crlEntryDetails = Extensions.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ public static RevDetails getInstance(Object o)
+ {
+ if (o instanceof RevDetails)
+ {
+ return (RevDetails)o;
+ }
+
+ if (o != null)
+ {
+ return new RevDetails(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public RevDetails(CertTemplate certDetails)
+ {
+ this.certDetails = certDetails;
+ }
+
+ /**
+ * @deprecated use method taking Extensions
+ * @param certDetails
+ * @param crlEntryDetails
+ */
+ public RevDetails(CertTemplate certDetails, X509Extensions crlEntryDetails)
+ {
+ this.certDetails = certDetails;
+ this.crlEntryDetails = Extensions.getInstance(crlEntryDetails.toASN1Primitive());
+ }
+
+ public RevDetails(CertTemplate certDetails, Extensions crlEntryDetails)
+ {
+ this.certDetails = certDetails;
+ this.crlEntryDetails = crlEntryDetails;
+ }
+
+ public CertTemplate getCertDetails()
+ {
+ return certDetails;
+ }
+
+ public Extensions getCrlEntryDetails()
+ {
+ return crlEntryDetails;
+ }
+
+ /**
+ * <pre>
+ * RevDetails ::= SEQUENCE {
+ * certDetails CertTemplate,
+ * -- allows requester to specify as much as they can about
+ * -- the cert. for which revocation is requested
+ * -- (e.g., for cases in which serialNumber is not available)
+ * crlEntryDetails Extensions OPTIONAL
+ * -- requested crlEntryExtensions
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certDetails);
+
+ if (crlEntryDetails != null)
+ {
+ v.add(crlEntryDetails);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/RevRepContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/RevRepContent.java
new file mode 100644
index 00000000..b6774193
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/RevRepContent.java
@@ -0,0 +1,137 @@
+package org.spongycastle.asn1.cmp;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.crmf.CertId;
+import org.spongycastle.asn1.x509.CertificateList;
+
+public class RevRepContent
+ extends ASN1Object
+{
+ private ASN1Sequence status;
+ private ASN1Sequence revCerts;
+ private ASN1Sequence crls;
+
+ private RevRepContent(ASN1Sequence seq)
+ {
+ Enumeration en = seq.getObjects();
+
+ status = ASN1Sequence.getInstance(en.nextElement());
+ while (en.hasMoreElements())
+ {
+ ASN1TaggedObject tObj = ASN1TaggedObject.getInstance(en.nextElement());
+
+ if (tObj.getTagNo() == 0)
+ {
+ revCerts = ASN1Sequence.getInstance(tObj, true);
+ }
+ else
+ {
+ crls = ASN1Sequence.getInstance(tObj, true);
+ }
+ }
+ }
+
+ public static RevRepContent getInstance(Object o)
+ {
+ if (o instanceof RevRepContent)
+ {
+ return (RevRepContent)o;
+ }
+
+ if (o != null)
+ {
+ return new RevRepContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public PKIStatusInfo[] getStatus()
+ {
+ PKIStatusInfo[] results = new PKIStatusInfo[status.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = PKIStatusInfo.getInstance(status.getObjectAt(i));
+ }
+
+ return results;
+ }
+
+ public CertId[] getRevCerts()
+ {
+ if (revCerts == null)
+ {
+ return null;
+ }
+
+ CertId[] results = new CertId[revCerts.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = CertId.getInstance(revCerts.getObjectAt(i));
+ }
+
+ return results;
+ }
+
+ public CertificateList[] getCrls()
+ {
+ if (crls == null)
+ {
+ return null;
+ }
+
+ CertificateList[] results = new CertificateList[crls.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = CertificateList.getInstance(crls.getObjectAt(i));
+ }
+
+ return results;
+ }
+
+ /**
+ * <pre>
+ * RevRepContent ::= SEQUENCE {
+ * status SEQUENCE SIZE (1..MAX) OF PKIStatusInfo,
+ * -- in same order as was sent in RevReqContent
+ * revCerts [0] SEQUENCE SIZE (1..MAX) OF CertId OPTIONAL,
+ * -- IDs for which revocation was requested
+ * -- (same order as status)
+ * crls [1] SEQUENCE SIZE (1..MAX) OF CertificateList OPTIONAL
+ * -- the resulting CRLs (there may be more than one)
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(status);
+
+ addOptional(v, 0, revCerts);
+ addOptional(v, 1, crls);
+
+ return new DERSequence(v);
+ }
+
+ private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(new DERTaggedObject(true, tagNo, obj));
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/RevRepContentBuilder.java b/core/src/main/java/org/spongycastle/asn1/cmp/RevRepContentBuilder.java
new file mode 100644
index 00000000..d154f17c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/RevRepContentBuilder.java
@@ -0,0 +1,59 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.crmf.CertId;
+import org.spongycastle.asn1.x509.CertificateList;
+
+public class RevRepContentBuilder
+{
+ private ASN1EncodableVector status = new ASN1EncodableVector();
+ private ASN1EncodableVector revCerts = new ASN1EncodableVector();
+ private ASN1EncodableVector crls = new ASN1EncodableVector();
+
+ public RevRepContentBuilder add(PKIStatusInfo status)
+ {
+ this.status.add(status);
+
+ return this;
+ }
+
+ public RevRepContentBuilder add(PKIStatusInfo status, CertId certId)
+ {
+ if (this.status.size() != this.revCerts.size())
+ {
+ throw new IllegalStateException("status and revCerts sequence must be in common order");
+ }
+ this.status.add(status);
+ this.revCerts.add(certId);
+
+ return this;
+ }
+
+ public RevRepContentBuilder addCrl(CertificateList crl)
+ {
+ this.crls.add(crl);
+
+ return this;
+ }
+
+ public RevRepContent build()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new DERSequence(status));
+
+ if (revCerts.size() != 0)
+ {
+ v.add(new DERTaggedObject(true, 0, new DERSequence(revCerts)));
+ }
+
+ if (crls.size() != 0)
+ {
+ v.add(new DERTaggedObject(true, 1, new DERSequence(crls)));
+ }
+
+ return RevRepContent.getInstance(new DERSequence(v));
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cmp/RevReqContent.java b/core/src/main/java/org/spongycastle/asn1/cmp/RevReqContent.java
new file mode 100644
index 00000000..e232417b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cmp/RevReqContent.java
@@ -0,0 +1,73 @@
+package org.spongycastle.asn1.cmp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class RevReqContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private RevReqContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static RevReqContent getInstance(Object o)
+ {
+ if (o instanceof RevReqContent)
+ {
+ return (RevReqContent)o;
+ }
+
+ if (o != null)
+ {
+ return new RevReqContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public RevReqContent(RevDetails revDetails)
+ {
+ this.content = new DERSequence(revDetails);
+ }
+
+ public RevReqContent(RevDetails[] revDetailsArray)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ for (int i = 0; i != revDetailsArray.length; i++)
+ {
+ v.add(revDetailsArray[i]);
+ }
+
+ this.content = new DERSequence(v);
+ }
+
+ public RevDetails[] toRevDetailsArray()
+ {
+ RevDetails[] result = new RevDetails[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = RevDetails.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ * <pre>
+ * RevReqContent ::= SEQUENCE OF RevDetails
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/Attribute.java b/core/src/main/java/org/spongycastle/asn1/cms/Attribute.java
new file mode 100644
index 00000000..59b8772c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/Attribute.java
@@ -0,0 +1,110 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.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
+{
+ private ASN1ObjectIdentifier attrType;
+ private ASN1Set attrValues;
+
+ /**
+ * Return an Attribute object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link Attribute} object
+ * <li> {@link org.spongycastle.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.
+ */
+ public static Attribute getInstance(
+ Object o)
+ {
+ if (o instanceof Attribute)
+ {
+ return (Attribute)o;
+ }
+
+ if (o != null)
+ {
+ return new Attribute(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ private Attribute(
+ ASN1Sequence seq)
+ {
+ attrType = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ attrValues = (ASN1Set)seq.getObjectAt(1);
+ }
+
+ public Attribute(
+ ASN1ObjectIdentifier attrType,
+ ASN1Set attrValues)
+ {
+ this.attrType = attrType;
+ this.attrValues = attrValues;
+ }
+
+ public ASN1ObjectIdentifier getAttrType()
+ {
+ return attrType;
+ }
+
+ public ASN1Set getAttrValues()
+ {
+ return attrValues;
+ }
+
+ public ASN1Encodable[] getAttributeValues()
+ {
+ return attrValues.toArray();
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(attrType);
+ v.add(attrValues);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/AttributeTable.java b/core/src/main/java/org/spongycastle/asn1/cms/AttributeTable.java
new file mode 100644
index 00000000..69e0988d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/AttributeTable.java
@@ -0,0 +1,240 @@
+package org.spongycastle.asn1.cms;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.DERSet;
+
+/**
+ * This is helper tool to construct {@link Attributes} sets.
+ */
+public class AttributeTable
+{
+ private Hashtable attributes = new Hashtable();
+
+ public AttributeTable(
+ Hashtable attrs)
+ {
+ attributes = copyTable(attrs);
+ }
+
+ public AttributeTable(
+ ASN1EncodableVector v)
+ {
+ for (int i = 0; i != v.size(); i++)
+ {
+ Attribute a = Attribute.getInstance(v.get(i));
+
+ addAttribute(a.getAttrType(), a);
+ }
+ }
+
+ public AttributeTable(
+ ASN1Set s)
+ {
+ for (int i = 0; i != s.size(); i++)
+ {
+ Attribute a = Attribute.getInstance(s.getObjectAt(i));
+
+ addAttribute(a.getAttrType(), a);
+ }
+ }
+
+ public AttributeTable(
+ Attribute attr)
+ {
+ addAttribute(attr.getAttrType(), attr);
+ }
+
+ public AttributeTable(
+ Attributes attrs)
+ {
+ this(ASN1Set.getInstance(attrs.toASN1Primitive()));
+ }
+
+ private void addAttribute(
+ ASN1ObjectIdentifier oid,
+ Attribute a)
+ {
+ Object value = attributes.get(oid);
+
+ if (value == null)
+ {
+ attributes.put(oid, a);
+ }
+ else
+ {
+ Vector v;
+
+ if (value instanceof Attribute)
+ {
+ v = new Vector();
+
+ v.addElement(value);
+ v.addElement(a);
+ }
+ else
+ {
+ v = (Vector)value;
+
+ v.addElement(a);
+ }
+
+ attributes.put(oid, v);
+ }
+ }
+
+ /**
+ * Return the first attribute matching the OBJECT IDENTIFIER oid.
+ *
+ * @param oid type of attribute required.
+ * @return first attribute found of type oid.
+ */
+ public Attribute get(
+ ASN1ObjectIdentifier oid)
+ {
+ Object value = attributes.get(oid);
+
+ if (value instanceof Vector)
+ {
+ return (Attribute)((Vector)value).elementAt(0);
+ }
+
+ return (Attribute)value;
+ }
+
+ /**
+ * Return all the attributes matching the OBJECT IDENTIFIER oid. The vector will be
+ * empty if there are no attributes of the required type present.
+ *
+ * @param oid type of attribute required.
+ * @return a vector of all the attributes found of type oid.
+ */
+ public ASN1EncodableVector getAll(
+ ASN1ObjectIdentifier oid)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ Object value = attributes.get(oid);
+
+ if (value instanceof Vector)
+ {
+ Enumeration e = ((Vector)value).elements();
+
+ while (e.hasMoreElements())
+ {
+ v.add((Attribute)e.nextElement());
+ }
+ }
+ else if (value != null)
+ {
+ v.add((Attribute)value);
+ }
+
+ return v;
+ }
+
+ public int size()
+ {
+ int size = 0;
+
+ for (Enumeration en = attributes.elements(); en.hasMoreElements();)
+ {
+ Object o = en.nextElement();
+
+ if (o instanceof Vector)
+ {
+ size += ((Vector)o).size();
+ }
+ else
+ {
+ size++;
+ }
+ }
+
+ return size;
+ }
+
+ public Hashtable toHashtable()
+ {
+ return copyTable(attributes);
+ }
+
+ public ASN1EncodableVector toASN1EncodableVector()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ Enumeration e = attributes.elements();
+
+ while (e.hasMoreElements())
+ {
+ Object value = e.nextElement();
+
+ if (value instanceof Vector)
+ {
+ Enumeration en = ((Vector)value).elements();
+
+ while (en.hasMoreElements())
+ {
+ v.add(Attribute.getInstance(en.nextElement()));
+ }
+ }
+ else
+ {
+ v.add(Attribute.getInstance(value));
+ }
+ }
+
+ return v;
+ }
+
+ public Attributes toASN1Structure()
+ {
+ return new Attributes(this.toASN1EncodableVector());
+ }
+
+ private Hashtable copyTable(
+ Hashtable in)
+ {
+ Hashtable out = new Hashtable();
+ Enumeration e = in.keys();
+
+ while (e.hasMoreElements())
+ {
+ Object key = e.nextElement();
+
+ out.put(key, in.get(key));
+ }
+
+ return out;
+ }
+
+ /**
+ * Return a new table with the passed in attribute added.
+ *
+ * @param attrType
+ * @param attrValue
+ * @return
+ */
+ public AttributeTable add(ASN1ObjectIdentifier attrType, ASN1Encodable attrValue)
+ {
+ AttributeTable newTable = new AttributeTable(attributes);
+
+ newTable.addAttribute(attrType, new Attribute(attrType, new DERSet(attrValue)));
+
+ return newTable;
+ }
+
+ public AttributeTable remove(ASN1ObjectIdentifier attrType)
+ {
+ AttributeTable newTable = new AttributeTable(attributes);
+
+ newTable.attributes.remove(attrType);
+
+ return newTable;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/Attributes.java b/core/src/main/java/org/spongycastle/asn1/cms/Attributes.java
new file mode 100644
index 00000000..55ac61e9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/Attributes.java
@@ -0,0 +1,85 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.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
+{
+ private ASN1Set attributes;
+
+ private Attributes(ASN1Set set)
+ {
+ attributes = set;
+ }
+
+ public Attributes(ASN1EncodableVector v)
+ {
+ 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.spongycastle.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)
+ {
+ return (Attributes)obj;
+ }
+ else if (obj != null)
+ {
+ return new Attributes(ASN1Set.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public Attribute[] getAttributes()
+ {
+ Attribute[] rv = new Attribute[attributes.size()];
+
+ for (int i = 0; i != rv.length; i++)
+ {
+ rv[i] = Attribute.getInstance(attributes.getObjectAt(i));
+ }
+
+ return rv;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return attributes;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/AuthEnvelopedData.java b/core/src/main/java/org/spongycastle/asn1/cms/AuthEnvelopedData.java
new file mode 100644
index 00000000..df691133
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/AuthEnvelopedData.java
@@ -0,0 +1,248 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.BERSequence;
+import org.spongycastle.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
+{
+ private ASN1Integer version;
+ private OriginatorInfo originatorInfo;
+ private ASN1Set recipientInfos;
+ private EncryptedContentInfo authEncryptedContentInfo;
+ private ASN1Set authAttrs;
+ private ASN1OctetString mac;
+ private ASN1Set unauthAttrs;
+
+ public AuthEnvelopedData(
+ OriginatorInfo originatorInfo,
+ ASN1Set recipientInfos,
+ EncryptedContentInfo authEncryptedContentInfo,
+ ASN1Set authAttrs,
+ ASN1OctetString mac,
+ ASN1Set unauthAttrs)
+ {
+ // "It MUST be set to 0."
+ this.version = new ASN1Integer(0);
+
+ this.originatorInfo = originatorInfo;
+
+ // TODO
+ // "There MUST be at least one element in the collection."
+ this.recipientInfos = recipientInfos;
+
+ this.authEncryptedContentInfo = authEncryptedContentInfo;
+
+ // TODO
+ // "The authAttrs MUST be present if the content type carried in
+ // EncryptedContentInfo is not id-data."
+ this.authAttrs = authAttrs;
+
+ this.mac = mac;
+
+ this.unauthAttrs = unauthAttrs;
+ }
+
+ /**
+ * Constructs AuthEnvelopedData by parsing supplied ASN1Sequence
+ * <p>
+ * @param seq An ASN1Sequence with AuthEnvelopedData
+ * @deprecated use getInstance().
+ */
+ public AuthEnvelopedData(
+ ASN1Sequence seq)
+ {
+ int index = 0;
+
+ // TODO
+ // "It MUST be set to 0."
+ ASN1Primitive tmp = seq.getObjectAt(index++).toASN1Primitive();
+ version = (ASN1Integer)tmp;
+
+ tmp = seq.getObjectAt(index++).toASN1Primitive();
+ if (tmp instanceof ASN1TaggedObject)
+ {
+ originatorInfo = OriginatorInfo.getInstance((ASN1TaggedObject)tmp, false);
+ tmp = seq.getObjectAt(index++).toASN1Primitive();
+ }
+
+ // TODO
+ // "There MUST be at least one element in the collection."
+ recipientInfos = ASN1Set.getInstance(tmp);
+
+ tmp = seq.getObjectAt(index++).toASN1Primitive();
+ authEncryptedContentInfo = EncryptedContentInfo.getInstance(tmp);
+
+ tmp = seq.getObjectAt(index++).toASN1Primitive();
+ if (tmp instanceof ASN1TaggedObject)
+ {
+ authAttrs = ASN1Set.getInstance((ASN1TaggedObject)tmp, false);
+ tmp = seq.getObjectAt(index++).toASN1Primitive();
+ }
+ else
+ {
+ // TODO
+ // "The authAttrs MUST be present if the content type carried in
+ // EncryptedContentInfo is not id-data."
+ }
+
+ mac = ASN1OctetString.getInstance(tmp);
+
+ if (seq.size() > index)
+ {
+ tmp = seq.getObjectAt(index++).toASN1Primitive();
+ unauthAttrs = ASN1Set.getInstance((ASN1TaggedObject)tmp, false);
+ }
+ }
+
+ /**
+ * Return an AuthEnvelopedData object from a tagged object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> {@link org.spongycastle.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.
+ * @throws IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static AuthEnvelopedData getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * Return an AuthEnvelopedData object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link AuthEnvelopedData} object
+ * <li> {@link ASN1Sequence org.spongycastle.asn1.ASN1Sequence} input formats with AuthEnvelopedData structure inside
+ * </ul>
+ *
+ * @param obj The object we want converted.
+ * @throws IllegalArgumentException if the object cannot be converted, or was null.
+ */
+ public static AuthEnvelopedData getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof AuthEnvelopedData)
+ {
+ return (AuthEnvelopedData)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new AuthEnvelopedData((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid AuthEnvelopedData: " + obj.getClass().getName());
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public OriginatorInfo getOriginatorInfo()
+ {
+ return originatorInfo;
+ }
+
+ public ASN1Set getRecipientInfos()
+ {
+ return recipientInfos;
+ }
+
+ public EncryptedContentInfo getAuthEncryptedContentInfo()
+ {
+ return authEncryptedContentInfo;
+ }
+
+ public ASN1Set getAuthAttrs()
+ {
+ return authAttrs;
+ }
+
+ public ASN1OctetString getMac()
+ {
+ return mac;
+ }
+
+ public ASN1Set getUnauthAttrs()
+ {
+ return unauthAttrs;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+
+ if (originatorInfo != null)
+ {
+ v.add(new DERTaggedObject(false, 0, originatorInfo));
+ }
+
+ v.add(recipientInfos);
+ v.add(authEncryptedContentInfo);
+
+ // "authAttrs optionally contains the authenticated attributes."
+ if (authAttrs != null)
+ {
+ // "AuthAttributes MUST be DER encoded, even if the rest of the
+ // AuthEnvelopedData structure is BER encoded."
+ v.add(new DERTaggedObject(false, 1, authAttrs));
+ }
+
+ v.add(mac);
+
+ // "unauthAttrs optionally contains the unauthenticated attributes."
+ if (unauthAttrs != null)
+ {
+ v.add(new DERTaggedObject(false, 2, unauthAttrs));
+ }
+
+ return new BERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/AuthEnvelopedDataParser.java b/core/src/main/java/org/spongycastle/asn1/cms/AuthEnvelopedDataParser.java
new file mode 100644
index 00000000..99b238c0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/AuthEnvelopedDataParser.java
@@ -0,0 +1,157 @@
+package org.spongycastle.asn1.cms;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1SequenceParser;
+import org.spongycastle.asn1.ASN1SetParser;
+import org.spongycastle.asn1.ASN1TaggedObjectParser;
+import org.spongycastle.asn1.BERTags;
+
+/**
+ * Parse {@link AuthEnvelopedData} input stream.
+ *
+ * <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 class AuthEnvelopedDataParser
+{
+ private ASN1SequenceParser seq;
+ private ASN1Integer version;
+ private ASN1Encodable nextObject;
+ private boolean originatorInfoCalled;
+
+ public AuthEnvelopedDataParser(ASN1SequenceParser seq) throws IOException
+ {
+ this.seq = seq;
+
+ // TODO
+ // "It MUST be set to 0."
+ this.version = ASN1Integer.getInstance(seq.readObject());
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public OriginatorInfo getOriginatorInfo()
+ throws IOException
+ {
+ originatorInfoCalled = true;
+
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ if (nextObject instanceof ASN1TaggedObjectParser && ((ASN1TaggedObjectParser)nextObject).getTagNo() == 0)
+ {
+ ASN1SequenceParser originatorInfo = (ASN1SequenceParser) ((ASN1TaggedObjectParser)nextObject).getObjectParser(BERTags.SEQUENCE, false);
+ nextObject = null;
+ return OriginatorInfo.getInstance(originatorInfo.toASN1Primitive());
+ }
+
+ return null;
+ }
+
+ public ASN1SetParser getRecipientInfos()
+ throws IOException
+ {
+ if (!originatorInfoCalled)
+ {
+ getOriginatorInfo();
+ }
+
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ ASN1SetParser recipientInfos = (ASN1SetParser)nextObject;
+ nextObject = null;
+ return recipientInfos;
+ }
+
+ public EncryptedContentInfoParser getAuthEncryptedContentInfo()
+ throws IOException
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ if (nextObject != null)
+ {
+ ASN1SequenceParser o = (ASN1SequenceParser) nextObject;
+ nextObject = null;
+ return new EncryptedContentInfoParser(o);
+ }
+
+ return null;
+ }
+
+ public ASN1SetParser getAuthAttrs()
+ throws IOException
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ if (nextObject instanceof ASN1TaggedObjectParser)
+ {
+ ASN1Encodable o = nextObject;
+ nextObject = null;
+ return (ASN1SetParser)((ASN1TaggedObjectParser)o).getObjectParser(BERTags.SET, false);
+ }
+
+ // TODO
+ // "The authAttrs MUST be present if the content type carried in
+ // EncryptedContentInfo is not id-data."
+
+ return null;
+ }
+
+ public ASN1OctetString getMac()
+ throws IOException
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ ASN1Encodable o = nextObject;
+ nextObject = null;
+
+ return ASN1OctetString.getInstance(o.toASN1Primitive());
+ }
+
+ public ASN1SetParser getUnauthAttrs()
+ throws IOException
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ if (nextObject != null)
+ {
+ ASN1Encodable o = nextObject;
+ nextObject = null;
+ return (ASN1SetParser)((ASN1TaggedObjectParser)o).getObjectParser(BERTags.SET, false);
+ }
+
+ return null;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/AuthenticatedData.java b/core/src/main/java/org/spongycastle/asn1/cms/AuthenticatedData.java
new file mode 100644
index 00000000..474e5216
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/AuthenticatedData.java
@@ -0,0 +1,312 @@
+package org.spongycastle.asn1.cms;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.BERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.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
+{
+ private ASN1Integer version;
+ private OriginatorInfo originatorInfo;
+ private ASN1Set recipientInfos;
+ private AlgorithmIdentifier macAlgorithm;
+ private AlgorithmIdentifier digestAlgorithm;
+ private ContentInfo encapsulatedContentInfo;
+ private ASN1Set authAttrs;
+ private ASN1OctetString mac;
+ private ASN1Set unauthAttrs;
+
+ public AuthenticatedData(
+ OriginatorInfo originatorInfo,
+ ASN1Set recipientInfos,
+ AlgorithmIdentifier macAlgorithm,
+ AlgorithmIdentifier digestAlgorithm,
+ ContentInfo encapsulatedContent,
+ ASN1Set authAttrs,
+ ASN1OctetString mac,
+ ASN1Set unauthAttrs)
+ {
+ if (digestAlgorithm != null || authAttrs != null)
+ {
+ if (digestAlgorithm == null || authAttrs == null)
+ {
+ throw new IllegalArgumentException("digestAlgorithm and authAttrs must be set together");
+ }
+ }
+
+ version = new ASN1Integer(calculateVersion(originatorInfo));
+
+ this.originatorInfo = originatorInfo;
+ this.macAlgorithm = macAlgorithm;
+ this.digestAlgorithm = digestAlgorithm;
+ this.recipientInfos = recipientInfos;
+ this.encapsulatedContentInfo = encapsulatedContent;
+ this.authAttrs = authAttrs;
+ this.mac = mac;
+ this.unauthAttrs = unauthAttrs;
+ }
+
+ /**
+ * @deprecated use getInstance()
+ */
+ public AuthenticatedData(
+ ASN1Sequence seq)
+ {
+ int index = 0;
+
+ version = (ASN1Integer)seq.getObjectAt(index++);
+
+ Object tmp = seq.getObjectAt(index++);
+
+ if (tmp instanceof ASN1TaggedObject)
+ {
+ originatorInfo = OriginatorInfo.getInstance((ASN1TaggedObject)tmp, false);
+ tmp = seq.getObjectAt(index++);
+ }
+
+ recipientInfos = ASN1Set.getInstance(tmp);
+ macAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(index++));
+
+ tmp = seq.getObjectAt(index++);
+
+ if (tmp instanceof ASN1TaggedObject)
+ {
+ digestAlgorithm = AlgorithmIdentifier.getInstance((ASN1TaggedObject)tmp, false);
+ tmp = seq.getObjectAt(index++);
+ }
+
+ encapsulatedContentInfo = ContentInfo.getInstance(tmp);
+
+ tmp = seq.getObjectAt(index++);
+
+ if (tmp instanceof ASN1TaggedObject)
+ {
+ authAttrs = ASN1Set.getInstance((ASN1TaggedObject)tmp, false);
+ tmp = seq.getObjectAt(index++);
+ }
+
+ mac = ASN1OctetString.getInstance(tmp);
+
+ if (seq.size() > index)
+ {
+ unauthAttrs = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(index), false);
+ }
+ }
+
+ /**
+ * 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
+ * tagged false otherwise.
+ * @throws IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static AuthenticatedData getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * Return an AuthenticatedData object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link AuthenticatedData} object
+ * <li> {@link org.spongycastle.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.
+ */
+ public static AuthenticatedData getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof AuthenticatedData)
+ {
+ return (AuthenticatedData)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new AuthenticatedData((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid AuthenticatedData: " + obj.getClass().getName());
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public OriginatorInfo getOriginatorInfo()
+ {
+ return originatorInfo;
+ }
+
+ public ASN1Set getRecipientInfos()
+ {
+ return recipientInfos;
+ }
+
+ public AlgorithmIdentifier getMacAlgorithm()
+ {
+ return macAlgorithm;
+ }
+
+ public AlgorithmIdentifier getDigestAlgorithm()
+ {
+ return digestAlgorithm;
+ }
+
+ public ContentInfo getEncapsulatedContentInfo()
+ {
+ return encapsulatedContentInfo;
+ }
+
+ public ASN1Set getAuthAttrs()
+ {
+ return authAttrs;
+ }
+
+ public ASN1OctetString getMac()
+ {
+ return mac;
+ }
+
+ public ASN1Set getUnauthAttrs()
+ {
+ return unauthAttrs;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+
+ if (originatorInfo != null)
+ {
+ v.add(new DERTaggedObject(false, 0, originatorInfo));
+ }
+
+ v.add(recipientInfos);
+ v.add(macAlgorithm);
+
+ if (digestAlgorithm != null)
+ {
+ v.add(new DERTaggedObject(false, 1, digestAlgorithm));
+ }
+
+ v.add(encapsulatedContentInfo);
+
+ if (authAttrs != null)
+ {
+ v.add(new DERTaggedObject(false, 2, authAttrs));
+ }
+
+ v.add(mac);
+
+ if (unauthAttrs != null)
+ {
+ v.add(new DERTaggedObject(false, 3, unauthAttrs));
+ }
+
+ return new BERSequence(v);
+ }
+
+ public static int calculateVersion(OriginatorInfo origInfo)
+ {
+ if (origInfo == null)
+ {
+ return 0;
+ }
+ else
+ {
+ int ver = 0;
+
+ for (Enumeration e = origInfo.getCertificates().getObjects(); e.hasMoreElements();)
+ {
+ Object obj = e.nextElement();
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tag = (ASN1TaggedObject)obj;
+
+ if (tag.getTagNo() == 2)
+ {
+ ver = 1;
+ }
+ else if (tag.getTagNo() == 3)
+ {
+ ver = 3;
+ break;
+ }
+ }
+ }
+
+ if (origInfo.getCRLs() != null)
+ {
+ for (Enumeration e = origInfo.getCRLs().getObjects(); e.hasMoreElements();)
+ {
+ Object obj = e.nextElement();
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tag = (ASN1TaggedObject)obj;
+
+ if (tag.getTagNo() == 1)
+ {
+ ver = 3;
+ break;
+ }
+ }
+ }
+ }
+
+ return ver;
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/AuthenticatedDataParser.java b/core/src/main/java/org/spongycastle/asn1/cms/AuthenticatedDataParser.java
new file mode 100644
index 00000000..ea1d4028
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/AuthenticatedDataParser.java
@@ -0,0 +1,206 @@
+package org.spongycastle.asn1.cms;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1SequenceParser;
+import org.spongycastle.asn1.ASN1SetParser;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.ASN1TaggedObjectParser;
+import org.spongycastle.asn1.BERTags;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * Parse {@link AuthenticatedData} stream.
+ * <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 AuthenticatedDataParser
+{
+ private ASN1SequenceParser seq;
+ private ASN1Integer version;
+ private ASN1Encodable nextObject;
+ private boolean originatorInfoCalled;
+
+ public AuthenticatedDataParser(
+ ASN1SequenceParser seq)
+ throws IOException
+ {
+ this.seq = seq;
+ this.version = ASN1Integer.getInstance(seq.readObject());
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public OriginatorInfo getOriginatorInfo()
+ throws IOException
+ {
+ originatorInfoCalled = true;
+
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ if (nextObject instanceof ASN1TaggedObjectParser && ((ASN1TaggedObjectParser)nextObject).getTagNo() == 0)
+ {
+ ASN1SequenceParser originatorInfo = (ASN1SequenceParser) ((ASN1TaggedObjectParser)nextObject).getObjectParser(BERTags.SEQUENCE, false);
+ nextObject = null;
+ return OriginatorInfo.getInstance(originatorInfo.toASN1Primitive());
+ }
+
+ return null;
+ }
+
+ public ASN1SetParser getRecipientInfos()
+ throws IOException
+ {
+ if (!originatorInfoCalled)
+ {
+ getOriginatorInfo();
+ }
+
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ ASN1SetParser recipientInfos = (ASN1SetParser)nextObject;
+ nextObject = null;
+ return recipientInfos;
+ }
+
+ public AlgorithmIdentifier getMacAlgorithm()
+ throws IOException
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ if (nextObject != null)
+ {
+ ASN1SequenceParser o = (ASN1SequenceParser)nextObject;
+ nextObject = null;
+ return AlgorithmIdentifier.getInstance(o.toASN1Primitive());
+ }
+
+ return null;
+ }
+
+ public AlgorithmIdentifier getDigestAlgorithm()
+ throws IOException
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ if (nextObject instanceof ASN1TaggedObjectParser)
+ {
+ AlgorithmIdentifier obj = AlgorithmIdentifier.getInstance((ASN1TaggedObject)nextObject.toASN1Primitive(), false);
+ nextObject = null;
+ return obj;
+ }
+
+ return null;
+ }
+
+ /**
+ * @deprecated use getEncapsulatedContentInfo()
+ */
+ public ContentInfoParser getEnapsulatedContentInfo()
+ throws IOException
+ {
+ return getEncapsulatedContentInfo();
+ }
+
+ public ContentInfoParser getEncapsulatedContentInfo()
+ throws IOException
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ if (nextObject != null)
+ {
+ ASN1SequenceParser o = (ASN1SequenceParser)nextObject;
+ nextObject = null;
+ return new ContentInfoParser(o);
+ }
+
+ return null;
+ }
+
+ public ASN1SetParser getAuthAttrs()
+ throws IOException
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ if (nextObject instanceof ASN1TaggedObjectParser)
+ {
+ ASN1Encodable o = nextObject;
+ nextObject = null;
+ return (ASN1SetParser)((ASN1TaggedObjectParser)o).getObjectParser(BERTags.SET, false);
+ }
+
+ return null;
+ }
+
+ public ASN1OctetString getMac()
+ throws IOException
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ ASN1Encodable o = nextObject;
+ nextObject = null;
+
+ return ASN1OctetString.getInstance(o.toASN1Primitive());
+ }
+
+ public ASN1SetParser getUnauthAttrs()
+ throws IOException
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ if (nextObject != null)
+ {
+ ASN1Encodable o = nextObject;
+ nextObject = null;
+ return (ASN1SetParser)((ASN1TaggedObjectParser)o).getObjectParser(BERTags.SET, false);
+ }
+
+ return null;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/CCMParameters.java b/core/src/main/java/org/spongycastle/asn1/cms/CCMParameters.java
new file mode 100644
index 00000000..1c505449
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/CCMParameters.java
@@ -0,0 +1,102 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.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.spongycastle.asn1.cms.CCMParameters} object
+ * <li> {@link org.spongycastle.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/core/src/main/java/org/spongycastle/asn1/cms/CMSAttributes.java b/core/src/main/java/org/spongycastle/asn1/cms/CMSAttributes.java
new file mode 100644
index 00000000..f1b85b59
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/CMSAttributes.java
@@ -0,0 +1,30 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.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/core/src/main/java/org/spongycastle/asn1/cms/CMSObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/cms/CMSObjectIdentifiers.java
new file mode 100644
index 00000000..9e38740f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/CMSObjectIdentifiers.java
@@ -0,0 +1,43 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.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) }
+ * </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/core/src/main/java/org/spongycastle/asn1/cms/CompressedData.java b/core/src/main/java/org/spongycastle/asn1/cms/CompressedData.java
new file mode 100644
index 00000000..88d3c458
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/CompressedData.java
@@ -0,0 +1,117 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.BERSequence;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * <a href="http://tools.ietf.org/html/rfc3274">RFC 3274</a>: CMS Compressed Data.
+ *
+ * <pre>
+ * CompressedData ::= SEQUENCE {
+ * version CMSVersion,
+ * compressionAlgorithm CompressionAlgorithmIdentifier,
+ * encapContentInfo EncapsulatedContentInfo
+ * }
+ * </pre>
+ */
+public class CompressedData
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private AlgorithmIdentifier compressionAlgorithm;
+ private ContentInfo encapContentInfo;
+
+ public CompressedData(
+ AlgorithmIdentifier compressionAlgorithm,
+ ContentInfo encapContentInfo)
+ {
+ this.version = new ASN1Integer(0);
+ this.compressionAlgorithm = compressionAlgorithm;
+ this.encapContentInfo = encapContentInfo;
+ }
+
+ private CompressedData(
+ ASN1Sequence seq)
+ {
+ 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.
+ *
+ * @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 isExplicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(ato, isExplicit));
+ }
+
+ /**
+ * Return a CompressedData object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link CompressedData} object
+ * <li> {@link org.spongycastle.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.
+ */
+ public static CompressedData getInstance(
+ Object obj)
+ {
+ if (obj instanceof CompressedData)
+ {
+ return (CompressedData)obj;
+ }
+
+ if (obj != null)
+ {
+ return new CompressedData(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public AlgorithmIdentifier getCompressionAlgorithmIdentifier()
+ {
+ return compressionAlgorithm;
+ }
+
+ public ContentInfo getEncapContentInfo()
+ {
+ return encapContentInfo;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(compressionAlgorithm);
+ v.add(encapContentInfo);
+
+ return new BERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/CompressedDataParser.java b/core/src/main/java/org/spongycastle/asn1/cms/CompressedDataParser.java
new file mode 100644
index 00000000..913cecb8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/CompressedDataParser.java
@@ -0,0 +1,49 @@
+package org.spongycastle.asn1.cms;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1SequenceParser;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * 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
+ * }
+ * </pre>
+ */
+public class CompressedDataParser
+{
+ private ASN1Integer _version;
+ private AlgorithmIdentifier _compressionAlgorithm;
+ private ContentInfoParser _encapContentInfo;
+
+ public CompressedDataParser(
+ ASN1SequenceParser seq)
+ throws IOException
+ {
+ this._version = (ASN1Integer)seq.readObject();
+ this._compressionAlgorithm = AlgorithmIdentifier.getInstance(seq.readObject().toASN1Primitive());
+ this._encapContentInfo = new ContentInfoParser((ASN1SequenceParser)seq.readObject());
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return _version;
+ }
+
+ public AlgorithmIdentifier getCompressionAlgorithmIdentifier()
+ {
+ return _compressionAlgorithm;
+ }
+
+ public ContentInfoParser getEncapContentInfo()
+ {
+ return _encapContentInfo;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/ContentInfo.java b/core/src/main/java/org/spongycastle/asn1/cms/ContentInfo.java
new file mode 100644
index 00000000..7616a7e5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/ContentInfo.java
@@ -0,0 +1,130 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.BERSequence;
+import org.spongycastle.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
+{
+ 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.spongycastle.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)
+ {
+ if (obj instanceof ContentInfo)
+ {
+ return (ContentInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new ContentInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static ContentInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * @deprecated use getInstance()
+ */
+ public ContentInfo(
+ ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ contentType = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+
+ if (seq.size() > 1)
+ {
+ ASN1TaggedObject tagged = (ASN1TaggedObject)seq.getObjectAt(1);
+ if (!tagged.isExplicit() || tagged.getTagNo() != 0)
+ {
+ throw new IllegalArgumentException("Bad tag for 'content'");
+ }
+
+ content = tagged.getObject();
+ }
+ }
+
+ public ContentInfo(
+ ASN1ObjectIdentifier contentType,
+ ASN1Encodable content)
+ {
+ this.contentType = contentType;
+ this.content = content;
+ }
+
+ public ASN1ObjectIdentifier getContentType()
+ {
+ return contentType;
+ }
+
+ public ASN1Encodable getContent()
+ {
+ return content;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(contentType);
+
+ if (content != null)
+ {
+ v.add(new BERTaggedObject(0, content));
+ }
+
+ return new BERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/ContentInfoParser.java b/core/src/main/java/org/spongycastle/asn1/cms/ContentInfoParser.java
new file mode 100644
index 00000000..3951a4ed
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/ContentInfoParser.java
@@ -0,0 +1,48 @@
+package org.spongycastle.asn1.cms;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1SequenceParser;
+import org.spongycastle.asn1.ASN1TaggedObjectParser;
+
+/**
+ * <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 }
+ * </pre>
+ */
+public class ContentInfoParser
+{
+ private ASN1ObjectIdentifier contentType;
+ private ASN1TaggedObjectParser content;
+
+ public ContentInfoParser(
+ ASN1SequenceParser seq)
+ throws IOException
+ {
+ contentType = (ASN1ObjectIdentifier)seq.readObject();
+ content = (ASN1TaggedObjectParser)seq.readObject();
+ }
+
+ public ASN1ObjectIdentifier getContentType()
+ {
+ return contentType;
+ }
+
+ public ASN1Encodable getContent(
+ int tag)
+ throws IOException
+ {
+ if (content != null)
+ {
+ return content.getObjectParser(tag, true);
+ }
+
+ return null;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/DigestedData.java b/core/src/main/java/org/spongycastle/asn1/cms/DigestedData.java
new file mode 100644
index 00000000..e20a4178
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/DigestedData.java
@@ -0,0 +1,128 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.BERSequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * <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 }
+ * </pre>
+ */
+public class DigestedData
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private AlgorithmIdentifier digestAlgorithm;
+ private ContentInfo encapContentInfo;
+ private ASN1OctetString digest;
+
+ public DigestedData(
+ AlgorithmIdentifier digestAlgorithm,
+ ContentInfo encapContentInfo,
+ byte[] digest)
+ {
+ this.version = new ASN1Integer(0);
+ this.digestAlgorithm = digestAlgorithm;
+ this.encapContentInfo = encapContentInfo;
+ this.digest = new DEROctetString(digest);
+ }
+
+ private DigestedData(
+ ASN1Sequence seq)
+ {
+ this.version = (ASN1Integer)seq.getObjectAt(0);
+ this.digestAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
+ this.encapContentInfo = ContentInfo.getInstance(seq.getObjectAt(2));
+ this.digest = ASN1OctetString.getInstance(seq.getObjectAt(3));
+ }
+
+ /**
+ * Return a DigestedData object from a tagged object.
+ *
+ * @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 isExplicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(ato, isExplicit));
+ }
+
+ /**
+ * Return a DigestedData object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link DigestedData} object
+ * <li> {@link org.spongycastle.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.
+ */
+ public static DigestedData getInstance(
+ Object obj)
+ {
+ if (obj instanceof DigestedData)
+ {
+ return (DigestedData)obj;
+ }
+
+ if (obj != null)
+ {
+ return new DigestedData(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public AlgorithmIdentifier getDigestAlgorithm()
+ {
+ return digestAlgorithm;
+ }
+
+ public ContentInfo getEncapContentInfo()
+ {
+ return encapContentInfo;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(digestAlgorithm);
+ v.add(encapContentInfo);
+ v.add(digest);
+
+ return new BERSequence(v);
+ }
+
+ public byte[] getDigest()
+ {
+ return digest.getOctets();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/EncryptedContentInfo.java b/core/src/main/java/org/spongycastle/asn1/cms/EncryptedContentInfo.java
new file mode 100644
index 00000000..9fcd591c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/EncryptedContentInfo.java
@@ -0,0 +1,120 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.BERSequence;
+import org.spongycastle.asn1.BERTaggedObject;
+import org.spongycastle.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
+{
+ private ASN1ObjectIdentifier contentType;
+ private AlgorithmIdentifier contentEncryptionAlgorithm;
+ private ASN1OctetString encryptedContent;
+
+ public EncryptedContentInfo(
+ ASN1ObjectIdentifier contentType,
+ AlgorithmIdentifier contentEncryptionAlgorithm,
+ ASN1OctetString encryptedContent)
+ {
+ this.contentType = contentType;
+ this.contentEncryptionAlgorithm = contentEncryptionAlgorithm;
+ this.encryptedContent = encryptedContent;
+ }
+
+ private EncryptedContentInfo(
+ ASN1Sequence seq)
+ {
+ if (seq.size() < 2)
+ {
+ throw new IllegalArgumentException("Truncated Sequence Found");
+ }
+
+ contentType = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ contentEncryptionAlgorithm = AlgorithmIdentifier.getInstance(
+ seq.getObjectAt(1));
+ if (seq.size() > 2)
+ {
+ encryptedContent = ASN1OctetString.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(2), false);
+ }
+ }
+
+ /**
+ * Return an EncryptedContentInfo object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link EncryptedContentInfo} object
+ * <li> {@link org.spongycastle.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.
+ */
+ public static EncryptedContentInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof EncryptedContentInfo)
+ {
+ return (EncryptedContentInfo)obj;
+ }
+ if (obj != null)
+ {
+ return new EncryptedContentInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1ObjectIdentifier getContentType()
+ {
+ return contentType;
+ }
+
+ public AlgorithmIdentifier getContentEncryptionAlgorithm()
+ {
+ return contentEncryptionAlgorithm;
+ }
+
+ public ASN1OctetString getEncryptedContent()
+ {
+ return encryptedContent;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(contentType);
+ v.add(contentEncryptionAlgorithm);
+
+ if (encryptedContent != null)
+ {
+ v.add(new BERTaggedObject(false, 0, encryptedContent));
+ }
+
+ return new BERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/EncryptedContentInfoParser.java b/core/src/main/java/org/spongycastle/asn1/cms/EncryptedContentInfoParser.java
new file mode 100644
index 00000000..9c5f38d2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/EncryptedContentInfoParser.java
@@ -0,0 +1,53 @@
+package org.spongycastle.asn1.cms;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1SequenceParser;
+import org.spongycastle.asn1.ASN1TaggedObjectParser;
+import org.spongycastle.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,
+ * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
+ * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
+ * }
+ * </pre>
+ */
+public class EncryptedContentInfoParser
+{
+ private ASN1ObjectIdentifier _contentType;
+ private AlgorithmIdentifier _contentEncryptionAlgorithm;
+ private ASN1TaggedObjectParser _encryptedContent;
+
+ public EncryptedContentInfoParser(
+ ASN1SequenceParser seq)
+ throws IOException
+ {
+ _contentType = (ASN1ObjectIdentifier)seq.readObject();
+ _contentEncryptionAlgorithm = AlgorithmIdentifier.getInstance(seq.readObject().toASN1Primitive());
+ _encryptedContent = (ASN1TaggedObjectParser)seq.readObject();
+ }
+
+ public ASN1ObjectIdentifier getContentType()
+ {
+ return _contentType;
+ }
+
+ public AlgorithmIdentifier getContentEncryptionAlgorithm()
+ {
+ return _contentEncryptionAlgorithm;
+ }
+
+ public ASN1Encodable getEncryptedContent(
+ int tag)
+ throws IOException
+ {
+ return _encryptedContent.getObjectParser(tag, false);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/EncryptedData.java b/core/src/main/java/org/spongycastle/asn1/cms/EncryptedData.java
new file mode 100644
index 00000000..69b86781
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/EncryptedData.java
@@ -0,0 +1,111 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.BERSequence;
+import org.spongycastle.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
+{
+ private ASN1Integer version;
+ 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.spongycastle.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)
+ {
+ return (EncryptedData)o;
+ }
+
+ if (o != null)
+ {
+ return new EncryptedData(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public EncryptedData(EncryptedContentInfo encInfo)
+ {
+ this(encInfo, null);
+ }
+
+ public EncryptedData(EncryptedContentInfo encInfo, ASN1Set unprotectedAttrs)
+ {
+ this.version = new ASN1Integer((unprotectedAttrs == null) ? 0 : 2);
+ this.encryptedContentInfo = encInfo;
+ this.unprotectedAttrs = unprotectedAttrs;
+ }
+
+ private EncryptedData(ASN1Sequence seq)
+ {
+ this.version = ASN1Integer.getInstance(seq.getObjectAt(0));
+ this.encryptedContentInfo = EncryptedContentInfo.getInstance(seq.getObjectAt(1));
+
+ if (seq.size() == 3)
+ {
+ this.unprotectedAttrs = ASN1Set.getInstance(seq.getObjectAt(2));
+ }
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public EncryptedContentInfo getEncryptedContentInfo()
+ {
+ return encryptedContentInfo;
+ }
+
+ public ASN1Set getUnprotectedAttrs()
+ {
+ return unprotectedAttrs;
+ }
+
+ /**
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(encryptedContentInfo);
+ if (unprotectedAttrs != null)
+ {
+ v.add(new BERTaggedObject(false, 1, unprotectedAttrs));
+ }
+
+ return new BERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/EnvelopedData.java b/core/src/main/java/org/spongycastle/asn1/cms/EnvelopedData.java
new file mode 100644
index 00000000..ac9b483f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/EnvelopedData.java
@@ -0,0 +1,215 @@
+package org.spongycastle.asn1.cms;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.BERSequence;
+import org.spongycastle.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
+{
+ private ASN1Integer version;
+ private OriginatorInfo originatorInfo;
+ private ASN1Set recipientInfos;
+ private EncryptedContentInfo encryptedContentInfo;
+ private ASN1Set unprotectedAttrs;
+
+ public EnvelopedData(
+ OriginatorInfo originatorInfo,
+ ASN1Set recipientInfos,
+ EncryptedContentInfo encryptedContentInfo,
+ ASN1Set unprotectedAttrs)
+ {
+ version = new ASN1Integer(calculateVersion(originatorInfo, recipientInfos, unprotectedAttrs));
+
+ this.originatorInfo = originatorInfo;
+ this.recipientInfos = recipientInfos;
+ this.encryptedContentInfo = encryptedContentInfo;
+ this.unprotectedAttrs = unprotectedAttrs;
+ }
+
+ public EnvelopedData(
+ OriginatorInfo originatorInfo,
+ ASN1Set recipientInfos,
+ EncryptedContentInfo encryptedContentInfo,
+ Attributes unprotectedAttrs)
+ {
+ version = new ASN1Integer(calculateVersion(originatorInfo, recipientInfos, ASN1Set.getInstance(unprotectedAttrs)));
+
+ this.originatorInfo = originatorInfo;
+ this.recipientInfos = recipientInfos;
+ this.encryptedContentInfo = encryptedContentInfo;
+ this.unprotectedAttrs = ASN1Set.getInstance(unprotectedAttrs);
+ }
+
+ /**
+ * @deprecated use getInstance()
+ */
+ public EnvelopedData(
+ ASN1Sequence seq)
+ {
+ int index = 0;
+
+ version = (ASN1Integer)seq.getObjectAt(index++);
+
+ Object tmp = seq.getObjectAt(index++);
+
+ if (tmp instanceof ASN1TaggedObject)
+ {
+ originatorInfo = OriginatorInfo.getInstance((ASN1TaggedObject)tmp, false);
+ tmp = seq.getObjectAt(index++);
+ }
+
+ recipientInfos = ASN1Set.getInstance(tmp);
+
+ encryptedContentInfo = EncryptedContentInfo.getInstance(seq.getObjectAt(index++));
+
+ if(seq.size() > index)
+ {
+ unprotectedAttrs = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(index), false);
+ }
+ }
+
+ /**
+ * 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
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static EnvelopedData getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * Return an EnvelopedData object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link EnvelopedData} object
+ * <li> {@link org.spongycastle.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.
+ */
+ public static EnvelopedData getInstance(
+ Object obj)
+ {
+ if (obj instanceof EnvelopedData)
+ {
+ return (EnvelopedData)obj;
+ }
+
+ if (obj != null)
+ {
+ return new EnvelopedData(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public OriginatorInfo getOriginatorInfo()
+ {
+ return originatorInfo;
+ }
+
+ public ASN1Set getRecipientInfos()
+ {
+ return recipientInfos;
+ }
+
+ public EncryptedContentInfo getEncryptedContentInfo()
+ {
+ return encryptedContentInfo;
+ }
+
+ public ASN1Set getUnprotectedAttrs()
+ {
+ return unprotectedAttrs;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+
+ if (originatorInfo != null)
+ {
+ v.add(new DERTaggedObject(false, 0, originatorInfo));
+ }
+
+ v.add(recipientInfos);
+ v.add(encryptedContentInfo);
+
+ if (unprotectedAttrs != null)
+ {
+ v.add(new DERTaggedObject(false, 1, unprotectedAttrs));
+ }
+
+ return new BERSequence(v);
+ }
+
+ public static int calculateVersion(OriginatorInfo originatorInfo, ASN1Set recipientInfos, ASN1Set unprotectedAttrs)
+ {
+ int version;
+
+ if (originatorInfo != null || unprotectedAttrs != null)
+ {
+ version = 2;
+ }
+ else
+ {
+ version = 0;
+
+ Enumeration e = recipientInfos.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ RecipientInfo ri = RecipientInfo.getInstance(e.nextElement());
+
+ if (ri.getVersion().getValue().intValue() != version)
+ {
+ version = 2;
+ break;
+ }
+ }
+ }
+
+ return version;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/EnvelopedDataParser.java b/core/src/main/java/org/spongycastle/asn1/cms/EnvelopedDataParser.java
new file mode 100644
index 00000000..534a27c0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/EnvelopedDataParser.java
@@ -0,0 +1,120 @@
+package org.spongycastle.asn1.cms;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1SequenceParser;
+import org.spongycastle.asn1.ASN1SetParser;
+import org.spongycastle.asn1.ASN1TaggedObjectParser;
+import org.spongycastle.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,
+ * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+ * recipientInfos RecipientInfos,
+ * encryptedContentInfo EncryptedContentInfo,
+ * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL
+ * }
+ * </pre>
+ */
+public class EnvelopedDataParser
+{
+ private ASN1SequenceParser _seq;
+ private ASN1Integer _version;
+ private ASN1Encodable _nextObject;
+ private boolean _originatorInfoCalled;
+
+ public EnvelopedDataParser(
+ ASN1SequenceParser seq)
+ throws IOException
+ {
+ this._seq = seq;
+ this._version = ASN1Integer.getInstance(seq.readObject());
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return _version;
+ }
+
+ public OriginatorInfo getOriginatorInfo()
+ throws IOException
+ {
+ _originatorInfoCalled = true;
+
+ if (_nextObject == null)
+ {
+ _nextObject = _seq.readObject();
+ }
+
+ if (_nextObject instanceof ASN1TaggedObjectParser && ((ASN1TaggedObjectParser)_nextObject).getTagNo() == 0)
+ {
+ ASN1SequenceParser originatorInfo = (ASN1SequenceParser) ((ASN1TaggedObjectParser)_nextObject).getObjectParser(BERTags.SEQUENCE, false);
+ _nextObject = null;
+ return OriginatorInfo.getInstance(originatorInfo.toASN1Primitive());
+ }
+
+ return null;
+ }
+
+ public ASN1SetParser getRecipientInfos()
+ throws IOException
+ {
+ if (!_originatorInfoCalled)
+ {
+ getOriginatorInfo();
+ }
+
+ if (_nextObject == null)
+ {
+ _nextObject = _seq.readObject();
+ }
+
+ ASN1SetParser recipientInfos = (ASN1SetParser)_nextObject;
+ _nextObject = null;
+ return recipientInfos;
+ }
+
+ public EncryptedContentInfoParser getEncryptedContentInfo()
+ throws IOException
+ {
+ if (_nextObject == null)
+ {
+ _nextObject = _seq.readObject();
+ }
+
+
+ if (_nextObject != null)
+ {
+ ASN1SequenceParser o = (ASN1SequenceParser) _nextObject;
+ _nextObject = null;
+ return new EncryptedContentInfoParser(o);
+ }
+
+ return null;
+ }
+
+ public ASN1SetParser getUnprotectedAttrs()
+ throws IOException
+ {
+ if (_nextObject == null)
+ {
+ _nextObject = _seq.readObject();
+ }
+
+
+ if (_nextObject != null)
+ {
+ ASN1Encodable o = _nextObject;
+ _nextObject = null;
+ return (ASN1SetParser)((ASN1TaggedObjectParser)o).getObjectParser(BERTags.SET, false);
+ }
+
+ return null;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/Evidence.java b/core/src/main/java/org/spongycastle/asn1/cms/Evidence.java
new file mode 100644
index 00000000..a8b173f9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/Evidence.java
@@ -0,0 +1,80 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.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
+{
+ private TimeStampTokenEvidence tstEvidence;
+
+ public Evidence(TimeStampTokenEvidence tstEvidence)
+ {
+ this.tstEvidence = tstEvidence;
+ }
+
+ private Evidence(ASN1TaggedObject tagged)
+ {
+ if (tagged.getTagNo() == 0)
+ {
+ this.tstEvidence = TimeStampTokenEvidence.getInstance(tagged, false);
+ }
+ }
+
+ /**
+ * Return an Evidence object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> {@link Evidence} object
+ * <li> {@link org.spongycastle.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)
+ {
+ return (Evidence)obj;
+ }
+ else if (obj instanceof ASN1TaggedObject)
+ {
+ return new Evidence(ASN1TaggedObject.getInstance(obj));
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance");
+ }
+
+ public TimeStampTokenEvidence getTstEvidence()
+ {
+ return tstEvidence;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (tstEvidence != null)
+ {
+ return new DERTaggedObject(false, 0, tstEvidence);
+ }
+
+ return null;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/GCMParameters.java b/core/src/main/java/org/spongycastle/asn1/cms/GCMParameters.java
new file mode 100644
index 00000000..131b1899
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/GCMParameters.java
@@ -0,0 +1,102 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.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.spongycastle.asn1.cms.GCMParameters} object
+ * <li> {@link org.spongycastle.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/core/src/main/java/org/spongycastle/asn1/cms/IssuerAndSerialNumber.java b/core/src/main/java/org/spongycastle/asn1/cms/IssuerAndSerialNumber.java
new file mode 100644
index 00000000..2b32efbe
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/IssuerAndSerialNumber.java
@@ -0,0 +1,138 @@
+package org.spongycastle.asn1.cms;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x500.X500Name;
+import org.spongycastle.asn1.x509.Certificate;
+import org.spongycastle.asn1.x509.X509CertificateStructure;
+import org.spongycastle.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.spongycastle.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)
+ {
+ if (obj instanceof IssuerAndSerialNumber)
+ {
+ return (IssuerAndSerialNumber)obj;
+ }
+ else if (obj != null)
+ {
+ return new IssuerAndSerialNumber(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * @deprecated use getInstance() method.
+ */
+ public IssuerAndSerialNumber(
+ ASN1Sequence seq)
+ {
+ this.name = X500Name.getInstance(seq.getObjectAt(0));
+ this.serialNumber = (ASN1Integer)seq.getObjectAt(1);
+ }
+
+ public IssuerAndSerialNumber(
+ Certificate certificate)
+ {
+ this.name = certificate.getIssuer();
+ this.serialNumber = certificate.getSerialNumber();
+ }
+
+ /**
+ * @deprecated use constructor taking Certificate
+ */
+ public IssuerAndSerialNumber(
+ X509CertificateStructure certificate)
+ {
+ this.name = certificate.getIssuer();
+ this.serialNumber = certificate.getSerialNumber();
+ }
+
+ public IssuerAndSerialNumber(
+ X500Name name,
+ BigInteger serialNumber)
+ {
+ this.name = name;
+ this.serialNumber = new ASN1Integer(serialNumber);
+ }
+
+ /**
+ * @deprecated use X500Name constructor
+ */
+ public IssuerAndSerialNumber(
+ X509Name name,
+ BigInteger serialNumber)
+ {
+ this.name = X500Name.getInstance(name);
+ this.serialNumber = new ASN1Integer(serialNumber);
+ }
+
+ /**
+ * @deprecated use X500Name constructor
+ */
+ public IssuerAndSerialNumber(
+ X509Name name,
+ ASN1Integer serialNumber)
+ {
+ this.name = X500Name.getInstance(name);
+ this.serialNumber = serialNumber;
+ }
+
+ public X500Name getName()
+ {
+ return name;
+ }
+
+ public ASN1Integer getSerialNumber()
+ {
+ return serialNumber;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(name);
+ v.add(serialNumber);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/KEKIdentifier.java b/core/src/main/java/org/spongycastle/asn1/cms/KEKIdentifier.java
new file mode 100644
index 00000000..951c3ce7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/KEKIdentifier.java
@@ -0,0 +1,151 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.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
+{
+ private ASN1OctetString keyIdentifier;
+ private ASN1GeneralizedTime date;
+ private OtherKeyAttribute other;
+
+ public KEKIdentifier(
+ byte[] keyIdentifier,
+ ASN1GeneralizedTime date,
+ OtherKeyAttribute other)
+ {
+ this.keyIdentifier = new DEROctetString(keyIdentifier);
+ this.date = date;
+ this.other = other;
+ }
+
+ private KEKIdentifier(
+ ASN1Sequence seq)
+ {
+ keyIdentifier = (ASN1OctetString)seq.getObjectAt(0);
+
+ switch (seq.size())
+ {
+ case 1:
+ break;
+ case 2:
+ if (seq.getObjectAt(1) instanceof ASN1GeneralizedTime)
+ {
+ date = (ASN1GeneralizedTime)seq.getObjectAt(1);
+ }
+ else
+ {
+ other = OtherKeyAttribute.getInstance(seq.getObjectAt(1));
+ }
+ break;
+ case 3:
+ date = (ASN1GeneralizedTime)seq.getObjectAt(1);
+ other = OtherKeyAttribute.getInstance(seq.getObjectAt(2));
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid KEKIdentifier");
+ }
+ }
+
+ /**
+ * 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
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static KEKIdentifier getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * Return a KEKIdentifier object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link KEKIdentifier} object
+ * <li> {@link org.spongycastle.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.
+ */
+ public static KEKIdentifier getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof KEKIdentifier)
+ {
+ return (KEKIdentifier)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new KEKIdentifier((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid KEKIdentifier: " + obj.getClass().getName());
+ }
+
+ public ASN1OctetString getKeyIdentifier()
+ {
+ return keyIdentifier;
+ }
+
+ public ASN1GeneralizedTime getDate()
+ {
+ return date;
+ }
+
+ public OtherKeyAttribute getOther()
+ {
+ return other;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(keyIdentifier);
+
+ if (date != null)
+ {
+ v.add(date);
+ }
+
+ if (other != null)
+ {
+ v.add(other);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/KEKRecipientInfo.java b/core/src/main/java/org/spongycastle/asn1/cms/KEKRecipientInfo.java
new file mode 100644
index 00000000..42151ce4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/KEKRecipientInfo.java
@@ -0,0 +1,133 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.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
+{
+ private ASN1Integer version;
+ private KEKIdentifier kekid;
+ private AlgorithmIdentifier keyEncryptionAlgorithm;
+ private ASN1OctetString encryptedKey;
+
+ public KEKRecipientInfo(
+ KEKIdentifier kekid,
+ AlgorithmIdentifier keyEncryptionAlgorithm,
+ ASN1OctetString encryptedKey)
+ {
+ this.version = new ASN1Integer(4);
+ this.kekid = kekid;
+ this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
+ this.encryptedKey = encryptedKey;
+ }
+
+ public KEKRecipientInfo(
+ ASN1Sequence seq)
+ {
+ version = (ASN1Integer)seq.getObjectAt(0);
+ kekid = KEKIdentifier.getInstance(seq.getObjectAt(1));
+ keyEncryptionAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(2));
+ encryptedKey = (ASN1OctetString)seq.getObjectAt(3);
+ }
+
+ /**
+ * 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
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static KEKRecipientInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * Return a KEKRecipientInfo object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link KEKRecipientInfo} object
+ * <li> {@link org.spongycastle.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.
+ */
+ public static KEKRecipientInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof KEKRecipientInfo)
+ {
+ return (KEKRecipientInfo)obj;
+ }
+
+ if (obj != null)
+ {
+ return new KEKRecipientInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public KEKIdentifier getKekid()
+ {
+ return kekid;
+ }
+
+ public AlgorithmIdentifier getKeyEncryptionAlgorithm()
+ {
+ return keyEncryptionAlgorithm;
+ }
+
+ public ASN1OctetString getEncryptedKey()
+ {
+ return encryptedKey;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(kekid);
+ v.add(keyEncryptionAlgorithm);
+ v.add(encryptedKey);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/KeyAgreeRecipientIdentifier.java b/core/src/main/java/org/spongycastle/asn1/cms/KeyAgreeRecipientIdentifier.java
new file mode 100644
index 00000000..f3de2bc1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/KeyAgreeRecipientIdentifier.java
@@ -0,0 +1,116 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.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
+{
+ private IssuerAndSerialNumber issuerSerial;
+ private RecipientKeyIdentifier rKeyID;
+
+ /**
+ * 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
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static KeyAgreeRecipientIdentifier getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * Return an KeyAgreeRecipientIdentifier object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> {@link KeyAgreeRecipientIdentifier} object
+ * <li> {@link org.spongycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with IssuerAndSerialNumber structure inside
+ * <li> {@link org.spongycastle.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.
+ */
+ public static KeyAgreeRecipientIdentifier getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof KeyAgreeRecipientIdentifier)
+ {
+ return (KeyAgreeRecipientIdentifier)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new KeyAgreeRecipientIdentifier(IssuerAndSerialNumber.getInstance(obj));
+ }
+
+ if (obj instanceof ASN1TaggedObject && ((ASN1TaggedObject)obj).getTagNo() == 0)
+ {
+ return new KeyAgreeRecipientIdentifier(RecipientKeyIdentifier.getInstance(
+ (ASN1TaggedObject)obj, false));
+ }
+
+ throw new IllegalArgumentException("Invalid KeyAgreeRecipientIdentifier: " + obj.getClass().getName());
+ }
+
+ public KeyAgreeRecipientIdentifier(
+ IssuerAndSerialNumber issuerSerial)
+ {
+ this.issuerSerial = issuerSerial;
+ this.rKeyID = null;
+ }
+
+ public KeyAgreeRecipientIdentifier(
+ RecipientKeyIdentifier rKeyID)
+ {
+ this.issuerSerial = null;
+ this.rKeyID = rKeyID;
+ }
+
+ public IssuerAndSerialNumber getIssuerAndSerialNumber()
+ {
+ return issuerSerial;
+ }
+
+ public RecipientKeyIdentifier getRKeyID()
+ {
+ return rKeyID;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (issuerSerial != null)
+ {
+ return issuerSerial.toASN1Primitive();
+ }
+
+ return new DERTaggedObject(false, 0, rKeyID);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/KeyAgreeRecipientInfo.java b/core/src/main/java/org/spongycastle/asn1/cms/KeyAgreeRecipientInfo.java
new file mode 100644
index 00000000..28a1edc2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/KeyAgreeRecipientInfo.java
@@ -0,0 +1,166 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.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
+{
+ private ASN1Integer version;
+ private OriginatorIdentifierOrKey originator;
+ private ASN1OctetString ukm;
+ private AlgorithmIdentifier keyEncryptionAlgorithm;
+ private ASN1Sequence recipientEncryptedKeys;
+
+ public KeyAgreeRecipientInfo(
+ OriginatorIdentifierOrKey originator,
+ ASN1OctetString ukm,
+ AlgorithmIdentifier keyEncryptionAlgorithm,
+ ASN1Sequence recipientEncryptedKeys)
+ {
+ this.version = new ASN1Integer(3);
+ this.originator = originator;
+ this.ukm = ukm;
+ this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
+ this.recipientEncryptedKeys = recipientEncryptedKeys;
+ }
+
+ /**
+ * @deprecated use getInstance()
+ */
+ public KeyAgreeRecipientInfo(
+ ASN1Sequence seq)
+ {
+ int index = 0;
+
+ version = (ASN1Integer)seq.getObjectAt(index++);
+ originator = OriginatorIdentifierOrKey.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(index++), true);
+
+ if (seq.getObjectAt(index) instanceof ASN1TaggedObject)
+ {
+ ukm = ASN1OctetString.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(index++), true);
+ }
+
+ keyEncryptionAlgorithm = AlgorithmIdentifier.getInstance(
+ seq.getObjectAt(index++));
+
+ recipientEncryptedKeys = (ASN1Sequence)seq.getObjectAt(index++);
+ }
+
+ /**
+ * 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
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static KeyAgreeRecipientInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * Return a KeyAgreeRecipientInfo object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link KeyAgreeRecipientInfo} object
+ * <li> {@link org.spongycastle.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.
+ */
+ public static KeyAgreeRecipientInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof KeyAgreeRecipientInfo)
+ {
+ return (KeyAgreeRecipientInfo)obj;
+ }
+
+ if (obj != null)
+ {
+ return new KeyAgreeRecipientInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public OriginatorIdentifierOrKey getOriginator()
+ {
+ return originator;
+ }
+
+ public ASN1OctetString getUserKeyingMaterial()
+ {
+ return ukm;
+ }
+
+ public AlgorithmIdentifier getKeyEncryptionAlgorithm()
+ {
+ return keyEncryptionAlgorithm;
+ }
+
+ public ASN1Sequence getRecipientEncryptedKeys()
+ {
+ return recipientEncryptedKeys;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(new DERTaggedObject(true, 0, originator));
+
+ if (ukm != null)
+ {
+ v.add(new DERTaggedObject(true, 1, ukm));
+ }
+
+ v.add(keyEncryptionAlgorithm);
+ v.add(recipientEncryptedKeys);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/KeyTransRecipientInfo.java b/core/src/main/java/org/spongycastle/asn1/cms/KeyTransRecipientInfo.java
new file mode 100644
index 00000000..e031dce5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/KeyTransRecipientInfo.java
@@ -0,0 +1,127 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.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
+{
+ private ASN1Integer version;
+ private RecipientIdentifier rid;
+ private AlgorithmIdentifier keyEncryptionAlgorithm;
+ private ASN1OctetString encryptedKey;
+
+ public KeyTransRecipientInfo(
+ RecipientIdentifier rid,
+ AlgorithmIdentifier keyEncryptionAlgorithm,
+ ASN1OctetString encryptedKey)
+ {
+ if (rid.toASN1Primitive() instanceof ASN1TaggedObject)
+ {
+ this.version = new ASN1Integer(2);
+ }
+ else
+ {
+ this.version = new ASN1Integer(0);
+ }
+
+ this.rid = rid;
+ this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
+ this.encryptedKey = encryptedKey;
+ }
+
+ /**
+ * @deprecated use getInstance()
+ */
+ public KeyTransRecipientInfo(
+ ASN1Sequence seq)
+ {
+ this.version = (ASN1Integer)seq.getObjectAt(0);
+ this.rid = RecipientIdentifier.getInstance(seq.getObjectAt(1));
+ this.keyEncryptionAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(2));
+ this.encryptedKey = (ASN1OctetString)seq.getObjectAt(3);
+ }
+
+ /**
+ * Return a KeyTransRecipientInfo object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link KeyTransRecipientInfo} object
+ * <li> {@link org.spongycastle.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.
+ */
+ public static KeyTransRecipientInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof KeyTransRecipientInfo)
+ {
+ return (KeyTransRecipientInfo)obj;
+ }
+
+ if(obj != null)
+ {
+ return new KeyTransRecipientInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public RecipientIdentifier getRecipientIdentifier()
+ {
+ return rid;
+ }
+
+ public AlgorithmIdentifier getKeyEncryptionAlgorithm()
+ {
+ return keyEncryptionAlgorithm;
+ }
+
+ public ASN1OctetString getEncryptedKey()
+ {
+ return encryptedKey;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(rid);
+ v.add(keyEncryptionAlgorithm);
+ v.add(encryptedKey);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/MetaData.java b/core/src/main/java/org/spongycastle/asn1/cms/MetaData.java
new file mode 100644
index 00000000..92cf468d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/MetaData.java
@@ -0,0 +1,135 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1Boolean;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.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
+{
+ private ASN1Boolean hashProtected;
+ private DERUTF8String fileName;
+ private DERIA5String mediaType;
+ private Attributes otherMetaData;
+
+ public MetaData(
+ ASN1Boolean hashProtected,
+ DERUTF8String fileName,
+ DERIA5String mediaType,
+ Attributes otherMetaData)
+ {
+ this.hashProtected = hashProtected;
+ this.fileName = fileName;
+ this.mediaType = mediaType;
+ this.otherMetaData = otherMetaData;
+ }
+
+ private MetaData(ASN1Sequence seq)
+ {
+ this.hashProtected = ASN1Boolean.getInstance(seq.getObjectAt(0));
+
+ int index = 1;
+
+ if (index < seq.size() && seq.getObjectAt(index) instanceof DERUTF8String)
+ {
+ this.fileName = DERUTF8String.getInstance(seq.getObjectAt(index++));
+ }
+ if (index < seq.size() && seq.getObjectAt(index) instanceof DERIA5String)
+ {
+ this.mediaType = DERIA5String.getInstance(seq.getObjectAt(index++));
+ }
+ if (index < seq.size())
+ {
+ this.otherMetaData = Attributes.getInstance(seq.getObjectAt(index++));
+ }
+ }
+
+ /**
+ * Return a MetaData object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link MetaData} object
+ * <li> {@link org.spongycastle.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)
+ {
+ return (MetaData)obj;
+ }
+ else if (obj != null)
+ {
+ return new MetaData(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(hashProtected);
+
+ if (fileName != null)
+ {
+ v.add(fileName);
+ }
+
+ if (mediaType != null)
+ {
+ v.add(mediaType);
+ }
+
+ if (otherMetaData != null)
+ {
+ v.add(otherMetaData);
+ }
+
+ return new DERSequence(v);
+ }
+
+ public boolean isHashProtected()
+ {
+ return hashProtected.isTrue();
+ }
+
+ public DERUTF8String getFileName()
+ {
+ return this.fileName;
+ }
+
+ public DERIA5String getMediaType()
+ {
+ return this.mediaType;
+ }
+
+ public Attributes getOtherMetaData()
+ {
+ return otherMetaData;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/OriginatorIdentifierOrKey.java b/core/src/main/java/org/spongycastle/asn1/cms/OriginatorIdentifierOrKey.java
new file mode 100644
index 00000000..042daff8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/OriginatorIdentifierOrKey.java
@@ -0,0 +1,179 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.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
+{
+ private ASN1Encodable id;
+
+ public OriginatorIdentifierOrKey(
+ IssuerAndSerialNumber id)
+ {
+ this.id = id;
+ }
+
+ /**
+ * @deprecated use version taking a SubjectKeyIdentifier
+ */
+ public OriginatorIdentifierOrKey(
+ ASN1OctetString id)
+ {
+ this(new SubjectKeyIdentifier(id.getOctets()));
+ }
+
+ public OriginatorIdentifierOrKey(
+ SubjectKeyIdentifier id)
+ {
+ this.id = new DERTaggedObject(false, 0, id);
+ }
+
+ public OriginatorIdentifierOrKey(
+ OriginatorPublicKey id)
+ {
+ this.id = new DERTaggedObject(false, 1, id);
+ }
+
+ /**
+ * @deprecated use more specific version
+ */
+ public OriginatorIdentifierOrKey(
+ ASN1Primitive id)
+ {
+ this.id = id;
+ }
+
+ /**
+ * 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
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static OriginatorIdentifierOrKey getInstance(
+ ASN1TaggedObject o,
+ boolean explicit)
+ {
+ if (!explicit)
+ {
+ throw new IllegalArgumentException(
+ "Can't implicitly tag OriginatorIdentifierOrKey");
+ }
+
+ return getInstance(o.getObject());
+ }
+
+ /**
+ * 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.spongycastle.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.
+ */
+ public static OriginatorIdentifierOrKey getInstance(
+ Object o)
+ {
+ if (o == null || o instanceof OriginatorIdentifierOrKey)
+ {
+ return (OriginatorIdentifierOrKey)o;
+ }
+
+ if (o instanceof IssuerAndSerialNumber)
+ {
+ return new OriginatorIdentifierOrKey((IssuerAndSerialNumber)o);
+ }
+
+ if (o instanceof SubjectKeyIdentifier)
+ {
+ return new OriginatorIdentifierOrKey((SubjectKeyIdentifier)o);
+ }
+
+ if (o instanceof OriginatorPublicKey)
+ {
+ return new OriginatorIdentifierOrKey((OriginatorPublicKey)o);
+ }
+
+ if (o instanceof ASN1TaggedObject)
+ {
+ // TODO Add validation
+ return new OriginatorIdentifierOrKey((ASN1TaggedObject)o);
+ }
+
+ throw new IllegalArgumentException("Invalid OriginatorIdentifierOrKey: " + o.getClass().getName());
+ }
+
+ public ASN1Encodable getId()
+ {
+ return id;
+ }
+
+ public IssuerAndSerialNumber getIssuerAndSerialNumber()
+ {
+ if (id instanceof IssuerAndSerialNumber)
+ {
+ return (IssuerAndSerialNumber)id;
+ }
+
+ return null;
+ }
+
+ public SubjectKeyIdentifier getSubjectKeyIdentifier()
+ {
+ if (id instanceof ASN1TaggedObject && ((ASN1TaggedObject)id).getTagNo() == 0)
+ {
+ return SubjectKeyIdentifier.getInstance((ASN1TaggedObject)id, false);
+ }
+
+ return null;
+ }
+
+ public OriginatorPublicKey getOriginatorKey()
+ {
+ if (id instanceof ASN1TaggedObject && ((ASN1TaggedObject)id).getTagNo() == 1)
+ {
+ return OriginatorPublicKey.getInstance((ASN1TaggedObject)id, false);
+ }
+
+ return null;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return id.toASN1Primitive();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/OriginatorInfo.java b/core/src/main/java/org/spongycastle/asn1/cms/OriginatorInfo.java
new file mode 100644
index 00000000..88d2e630
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/OriginatorInfo.java
@@ -0,0 +1,159 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.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
+{
+ private ASN1Set certs;
+ private ASN1Set crls;
+
+ public OriginatorInfo(
+ ASN1Set certs,
+ ASN1Set crls)
+ {
+ this.certs = certs;
+ this.crls = crls;
+ }
+
+ private OriginatorInfo(
+ ASN1Sequence seq)
+ {
+ switch (seq.size())
+ {
+ case 0: // empty
+ break;
+ case 1:
+ ASN1TaggedObject o = (ASN1TaggedObject)seq.getObjectAt(0);
+ switch (o.getTagNo())
+ {
+ case 0 :
+ certs = ASN1Set.getInstance(o, false);
+ break;
+ case 1 :
+ crls = ASN1Set.getInstance(o, false);
+ break;
+ default:
+ throw new IllegalArgumentException("Bad tag in OriginatorInfo: " + o.getTagNo());
+ }
+ break;
+ case 2:
+ certs = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(0), false);
+ crls = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(1), false);
+ break;
+ default:
+ throw new IllegalArgumentException("OriginatorInfo too big");
+ }
+ }
+
+ /**
+ * 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
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static OriginatorInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * Return an OriginatorInfo object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link OriginatorInfo} object
+ * <li> {@link org.spongycastle.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.
+ */
+ public static OriginatorInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof OriginatorInfo)
+ {
+ return (OriginatorInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new OriginatorInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1Set getCertificates()
+ {
+ return certs;
+ }
+
+ public ASN1Set getCRLs()
+ {
+ return crls;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (certs != null)
+ {
+ v.add(new DERTaggedObject(false, 0, certs));
+ }
+
+ if (crls != null)
+ {
+ v.add(new DERTaggedObject(false, 1, crls));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/OriginatorPublicKey.java b/core/src/main/java/org/spongycastle/asn1/cms/OriginatorPublicKey.java
new file mode 100644
index 00000000..e5edcf3e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/OriginatorPublicKey.java
@@ -0,0 +1,114 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.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
+{
+ private AlgorithmIdentifier algorithm;
+ private DERBitString publicKey;
+
+ public OriginatorPublicKey(
+ AlgorithmIdentifier algorithm,
+ byte[] publicKey)
+ {
+ this.algorithm = algorithm;
+ this.publicKey = new DERBitString(publicKey);
+ }
+
+ /**
+ * @deprecated use getInstance()
+ */
+ public OriginatorPublicKey(
+ ASN1Sequence seq)
+ {
+ algorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(0));
+ publicKey = (DERBitString)seq.getObjectAt(1);
+ }
+
+ /**
+ * 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
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static OriginatorPublicKey getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * Return an OriginatorPublicKey object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link OriginatorPublicKey} object
+ * <li> {@link org.spongycastle.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.
+ */
+ public static OriginatorPublicKey getInstance(
+ Object obj)
+ {
+ if (obj instanceof OriginatorPublicKey)
+ {
+ return (OriginatorPublicKey)obj;
+ }
+
+ if (obj != null)
+ {
+ return new OriginatorPublicKey(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public AlgorithmIdentifier getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ public DERBitString getPublicKey()
+ {
+ return publicKey;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(algorithm);
+ v.add(publicKey);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/OtherKeyAttribute.java b/core/src/main/java/org/spongycastle/asn1/cms/OtherKeyAttribute.java
new file mode 100644
index 00000000..cc9db1c7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/OtherKeyAttribute.java
@@ -0,0 +1,96 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.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
+{
+ private ASN1ObjectIdentifier keyAttrId;
+ private ASN1Encodable keyAttr;
+
+ /**
+ * Return an OtherKeyAttribute object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link OtherKeyAttribute} object
+ * <li> {@link org.spongycastle.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.
+ */
+ public static OtherKeyAttribute getInstance(
+ Object o)
+ {
+ if (o instanceof OtherKeyAttribute)
+ {
+ return (OtherKeyAttribute)o;
+ }
+
+ if (o != null)
+ {
+ return new OtherKeyAttribute(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ /**
+ * @deprecated use getInstance()
+ */
+ public OtherKeyAttribute(
+ ASN1Sequence seq)
+ {
+ keyAttrId = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ keyAttr = seq.getObjectAt(1);
+ }
+
+ public OtherKeyAttribute(
+ ASN1ObjectIdentifier keyAttrId,
+ ASN1Encodable keyAttr)
+ {
+ this.keyAttrId = keyAttrId;
+ this.keyAttr = keyAttr;
+ }
+
+ public ASN1ObjectIdentifier getKeyAttrId()
+ {
+ return keyAttrId;
+ }
+
+ public ASN1Encodable getKeyAttr()
+ {
+ return keyAttr;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(keyAttrId);
+ v.add(keyAttr);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/OtherRecipientInfo.java b/core/src/main/java/org/spongycastle/asn1/cms/OtherRecipientInfo.java
new file mode 100644
index 00000000..2f95e85c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/OtherRecipientInfo.java
@@ -0,0 +1,112 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.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
+{
+ private ASN1ObjectIdentifier oriType;
+ private ASN1Encodable oriValue;
+
+ public OtherRecipientInfo(
+ ASN1ObjectIdentifier oriType,
+ ASN1Encodable oriValue)
+ {
+ this.oriType = oriType;
+ this.oriValue = oriValue;
+ }
+
+ /**
+ * @deprecated use getInstance().
+ */
+ public OtherRecipientInfo(
+ ASN1Sequence seq)
+ {
+ oriType = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+ oriValue = seq.getObjectAt(1);
+ }
+
+ /**
+ * 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
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static OtherRecipientInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * Return a OtherRecipientInfo object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link PasswordRecipientInfo} object
+ * <li> {@link org.spongycastle.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.
+ */
+ public static OtherRecipientInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof OtherRecipientInfo)
+ {
+ return (OtherRecipientInfo)obj;
+ }
+
+ if (obj != null)
+ {
+ return new OtherRecipientInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1ObjectIdentifier getType()
+ {
+ return oriType;
+ }
+
+ public ASN1Encodable getValue()
+ {
+ return oriValue;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(oriType);
+ v.add(oriValue);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/OtherRevocationInfoFormat.java b/core/src/main/java/org/spongycastle/asn1/cms/OtherRevocationInfoFormat.java
new file mode 100644
index 00000000..178fd991
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/OtherRevocationInfoFormat.java
@@ -0,0 +1,109 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.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
+{
+ private ASN1ObjectIdentifier otherRevInfoFormat;
+ private ASN1Encodable otherRevInfo;
+
+ public OtherRevocationInfoFormat(
+ ASN1ObjectIdentifier otherRevInfoFormat,
+ ASN1Encodable otherRevInfo)
+ {
+ this.otherRevInfoFormat = otherRevInfoFormat;
+ this.otherRevInfo = otherRevInfo;
+ }
+
+ private OtherRevocationInfoFormat(
+ ASN1Sequence seq)
+ {
+ otherRevInfoFormat = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+ otherRevInfo = seq.getObjectAt(1);
+ }
+
+ /**
+ * 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
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static OtherRevocationInfoFormat getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * Return a OtherRevocationInfoFormat object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link OtherRevocationInfoFormat} object
+ * <li> {@link org.spongycastle.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.
+ */
+ public static OtherRevocationInfoFormat getInstance(
+ Object obj)
+ {
+ if (obj instanceof OtherRevocationInfoFormat)
+ {
+ return (OtherRevocationInfoFormat)obj;
+ }
+
+ if (obj != null)
+ {
+ return new OtherRevocationInfoFormat(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1ObjectIdentifier getInfoFormat()
+ {
+ return otherRevInfoFormat;
+ }
+
+ public ASN1Encodable getInfo()
+ {
+ return otherRevInfo;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(otherRevInfoFormat);
+ v.add(otherRevInfo);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/PasswordRecipientInfo.java b/core/src/main/java/org/spongycastle/asn1/cms/PasswordRecipientInfo.java
new file mode 100644
index 00000000..26dd78f5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/PasswordRecipientInfo.java
@@ -0,0 +1,157 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.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
+{
+ private ASN1Integer version;
+ private AlgorithmIdentifier keyDerivationAlgorithm;
+ private AlgorithmIdentifier keyEncryptionAlgorithm;
+ private ASN1OctetString encryptedKey;
+
+ public PasswordRecipientInfo(
+ AlgorithmIdentifier keyEncryptionAlgorithm,
+ ASN1OctetString encryptedKey)
+ {
+ this.version = new ASN1Integer(0);
+ this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
+ this.encryptedKey = encryptedKey;
+ }
+
+ public PasswordRecipientInfo(
+ AlgorithmIdentifier keyDerivationAlgorithm,
+ AlgorithmIdentifier keyEncryptionAlgorithm,
+ ASN1OctetString encryptedKey)
+ {
+ this.version = new ASN1Integer(0);
+ this.keyDerivationAlgorithm = keyDerivationAlgorithm;
+ this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
+ this.encryptedKey = encryptedKey;
+ }
+
+ /**
+ * @deprecated use getInstance() method.
+ */
+ public PasswordRecipientInfo(
+ ASN1Sequence seq)
+ {
+ version = (ASN1Integer)seq.getObjectAt(0);
+ if (seq.getObjectAt(1) instanceof ASN1TaggedObject)
+ {
+ keyDerivationAlgorithm = AlgorithmIdentifier.getInstance((ASN1TaggedObject)seq.getObjectAt(1), false);
+ keyEncryptionAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(2));
+ encryptedKey = (ASN1OctetString)seq.getObjectAt(3);
+ }
+ else
+ {
+ keyEncryptionAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
+ encryptedKey = (ASN1OctetString)seq.getObjectAt(2);
+ }
+ }
+
+ /**
+ * 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
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static PasswordRecipientInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * Return a PasswordRecipientInfo object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link PasswordRecipientInfo} object
+ * <li> {@link org.spongycastle.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.
+ */
+ public static PasswordRecipientInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof PasswordRecipientInfo)
+ {
+ return (PasswordRecipientInfo)obj;
+ }
+
+ if (obj != null)
+ {
+ return new PasswordRecipientInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public AlgorithmIdentifier getKeyDerivationAlgorithm()
+ {
+ return keyDerivationAlgorithm;
+ }
+
+ public AlgorithmIdentifier getKeyEncryptionAlgorithm()
+ {
+ return keyEncryptionAlgorithm;
+ }
+
+ public ASN1OctetString getEncryptedKey()
+ {
+ return encryptedKey;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+
+ if (keyDerivationAlgorithm != null)
+ {
+ v.add(new DERTaggedObject(false, 0, keyDerivationAlgorithm));
+ }
+ v.add(keyEncryptionAlgorithm);
+ v.add(encryptedKey);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/RecipientEncryptedKey.java b/core/src/main/java/org/spongycastle/asn1/cms/RecipientEncryptedKey.java
new file mode 100644
index 00000000..a51a13a5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/RecipientEncryptedKey.java
@@ -0,0 +1,109 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.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
+{
+ private KeyAgreeRecipientIdentifier identifier;
+ private ASN1OctetString encryptedKey;
+
+ private RecipientEncryptedKey(
+ ASN1Sequence seq)
+ {
+ identifier = KeyAgreeRecipientIdentifier.getInstance(seq.getObjectAt(0));
+ encryptedKey = (ASN1OctetString)seq.getObjectAt(1);
+ }
+
+ /**
+ * 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
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static RecipientEncryptedKey getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * Return a RecipientEncryptedKey object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link RecipientEncryptedKey} object
+ * <li> {@link org.spongycastle.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.
+ */
+ public static RecipientEncryptedKey getInstance(
+ Object obj)
+ {
+ if (obj instanceof RecipientEncryptedKey)
+ {
+ return (RecipientEncryptedKey)obj;
+ }
+
+ if (obj != null)
+ {
+ return new RecipientEncryptedKey(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public RecipientEncryptedKey(
+ KeyAgreeRecipientIdentifier id,
+ ASN1OctetString encryptedKey)
+ {
+ this.identifier = id;
+ this.encryptedKey = encryptedKey;
+ }
+
+ public KeyAgreeRecipientIdentifier getIdentifier()
+ {
+ return identifier;
+ }
+
+ public ASN1OctetString getEncryptedKey()
+ {
+ return encryptedKey;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(identifier);
+ v.add(encryptedKey);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/RecipientIdentifier.java b/core/src/main/java/org/spongycastle/asn1/cms/RecipientIdentifier.java
new file mode 100644
index 00000000..cbf52625
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/RecipientIdentifier.java
@@ -0,0 +1,111 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.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
+{
+ private ASN1Encodable id;
+
+ public RecipientIdentifier(
+ IssuerAndSerialNumber id)
+ {
+ this.id = id;
+ }
+
+ public RecipientIdentifier(
+ ASN1OctetString id)
+ {
+ this.id = new DERTaggedObject(false, 0, id);
+ }
+
+ public RecipientIdentifier(
+ ASN1Primitive id)
+ {
+ this.id = id;
+ }
+
+ /**
+ * 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.spongycastle.asn1.ASN1OctetString#getInstance(java.lang.Object) ASN1OctetString} input formats (OctetString, byte[]) with value of KeyIdentifier in DER form
+ * <li> {@link org.spongycastle.asn1.ASN1Primitive ASN1Primitive} for RecipientIdentifier constructor
+ * </ul>
+ *
+ * @param o the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static RecipientIdentifier getInstance(
+ Object o)
+ {
+ if (o == null || o instanceof RecipientIdentifier)
+ {
+ return (RecipientIdentifier)o;
+ }
+
+ if (o instanceof IssuerAndSerialNumber)
+ {
+ return new RecipientIdentifier((IssuerAndSerialNumber)o);
+ }
+
+ if (o instanceof ASN1OctetString)
+ {
+ return new RecipientIdentifier((ASN1OctetString)o);
+ }
+
+ if (o instanceof ASN1Primitive)
+ {
+ return new RecipientIdentifier((ASN1Primitive)o);
+ }
+
+ throw new IllegalArgumentException(
+ "Illegal object in RecipientIdentifier: " + o.getClass().getName());
+ }
+
+ public boolean isTagged()
+ {
+ return (id instanceof ASN1TaggedObject);
+ }
+
+ public ASN1Encodable getId()
+ {
+ if (id instanceof ASN1TaggedObject)
+ {
+ return ASN1OctetString.getInstance((ASN1TaggedObject)id, false);
+ }
+
+ return IssuerAndSerialNumber.getInstance(id);
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return id.toASN1Primitive();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/RecipientInfo.java b/core/src/main/java/org/spongycastle/asn1/cms/RecipientInfo.java
new file mode 100644
index 00000000..d6b5c802
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/RecipientInfo.java
@@ -0,0 +1,173 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.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
+{
+ ASN1Encodable info;
+
+ public RecipientInfo(
+ KeyTransRecipientInfo info)
+ {
+ this.info = info;
+ }
+
+ public RecipientInfo(
+ KeyAgreeRecipientInfo info)
+ {
+ this.info = new DERTaggedObject(false, 1, info);
+ }
+
+ public RecipientInfo(
+ KEKRecipientInfo info)
+ {
+ this.info = new DERTaggedObject(false, 2, info);
+ }
+
+ public RecipientInfo(
+ PasswordRecipientInfo info)
+ {
+ this.info = new DERTaggedObject(false, 3, info);
+ }
+
+ public RecipientInfo(
+ OtherRecipientInfo info)
+ {
+ this.info = new DERTaggedObject(false, 4, info);
+ }
+
+ public RecipientInfo(
+ ASN1Primitive info)
+ {
+ 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.spongycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with RecipientInfo structure inside
+ * <li> {@link org.spongycastle.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)
+ {
+ if (o == null || o instanceof RecipientInfo)
+ {
+ return (RecipientInfo)o;
+ }
+ else if (o instanceof ASN1Sequence)
+ {
+ return new RecipientInfo((ASN1Sequence)o);
+ }
+ else if (o instanceof ASN1TaggedObject)
+ {
+ return new RecipientInfo((ASN1TaggedObject)o);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: "
+ + o.getClass().getName());
+ }
+
+ public ASN1Integer getVersion()
+ {
+ if (info instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject o = (ASN1TaggedObject)info;
+
+ switch (o.getTagNo())
+ {
+ case 1:
+ return KeyAgreeRecipientInfo.getInstance(o, false).getVersion();
+ case 2:
+ return getKEKInfo(o).getVersion();
+ case 3:
+ return PasswordRecipientInfo.getInstance(o, false).getVersion();
+ case 4:
+ return new ASN1Integer(0); // no syntax version for OtherRecipientInfo
+ default:
+ throw new IllegalStateException("unknown tag");
+ }
+ }
+
+ return KeyTransRecipientInfo.getInstance(info).getVersion();
+ }
+
+ public boolean isTagged()
+ {
+ return (info instanceof ASN1TaggedObject);
+ }
+
+ public ASN1Encodable getInfo()
+ {
+ if (info instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject o = (ASN1TaggedObject)info;
+
+ switch (o.getTagNo())
+ {
+ case 1:
+ return KeyAgreeRecipientInfo.getInstance(o, false);
+ case 2:
+ return getKEKInfo(o);
+ case 3:
+ return PasswordRecipientInfo.getInstance(o, false);
+ case 4:
+ return OtherRecipientInfo.getInstance(o, false);
+ default:
+ throw new IllegalStateException("unknown tag");
+ }
+ }
+
+ return KeyTransRecipientInfo.getInstance(info);
+ }
+
+ private KEKRecipientInfo getKEKInfo(ASN1TaggedObject o)
+ {
+ if (o.isExplicit())
+ { // compatibilty with erroneous version
+ return KEKRecipientInfo.getInstance(o, true);
+ }
+ else
+ {
+ return KEKRecipientInfo.getInstance(o, false);
+ }
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return info.toASN1Primitive();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/RecipientKeyIdentifier.java b/core/src/main/java/org/spongycastle/asn1/cms/RecipientKeyIdentifier.java
new file mode 100644
index 00000000..16d9312f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/RecipientKeyIdentifier.java
@@ -0,0 +1,171 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.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
+{
+ private ASN1OctetString subjectKeyIdentifier;
+ private ASN1GeneralizedTime date;
+ private OtherKeyAttribute other;
+
+ public RecipientKeyIdentifier(
+ ASN1OctetString subjectKeyIdentifier,
+ ASN1GeneralizedTime date,
+ OtherKeyAttribute other)
+ {
+ this.subjectKeyIdentifier = subjectKeyIdentifier;
+ this.date = date;
+ this.other = other;
+ }
+
+ public RecipientKeyIdentifier(
+ byte[] subjectKeyIdentifier,
+ ASN1GeneralizedTime date,
+ OtherKeyAttribute other)
+ {
+ this.subjectKeyIdentifier = new DEROctetString(subjectKeyIdentifier);
+ this.date = date;
+ this.other = other;
+ }
+
+ public RecipientKeyIdentifier(
+ byte[] subjectKeyIdentifier)
+ {
+ this(subjectKeyIdentifier, null, null);
+ }
+
+ /**
+ * @deprecated use getInstance()
+ */
+ public RecipientKeyIdentifier(
+ ASN1Sequence seq)
+ {
+ subjectKeyIdentifier = ASN1OctetString.getInstance(
+ seq.getObjectAt(0));
+
+ switch(seq.size())
+ {
+ case 1:
+ break;
+ case 2:
+ if (seq.getObjectAt(1) instanceof ASN1GeneralizedTime)
+ {
+ date = ASN1GeneralizedTime.getInstance(seq.getObjectAt(1));
+ }
+ else
+ {
+ other = OtherKeyAttribute.getInstance(seq.getObjectAt(2));
+ }
+ break;
+ case 3:
+ date = ASN1GeneralizedTime.getInstance(seq.getObjectAt(1));
+ other = OtherKeyAttribute.getInstance(seq.getObjectAt(2));
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid RecipientKeyIdentifier");
+ }
+ }
+
+ /**
+ * Return a RecipientKeyIdentifier object from a tagged object.
+ *
+ * @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 isExplicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(ato, isExplicit));
+ }
+
+ /**
+ * Return a RecipientKeyIdentifier object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link RecipientKeyIdentifier} object
+ * <li> {@link org.spongycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with RecipientKeyIdentifier structure inside
+ * </ul>
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static RecipientKeyIdentifier getInstance(Object obj)
+ {
+ if (obj instanceof RecipientKeyIdentifier)
+ {
+ return (RecipientKeyIdentifier)obj;
+ }
+
+ if(obj != null)
+ {
+ return new RecipientKeyIdentifier(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1OctetString getSubjectKeyIdentifier()
+ {
+ return subjectKeyIdentifier;
+ }
+
+ public ASN1GeneralizedTime getDate()
+ {
+ return date;
+ }
+
+ public OtherKeyAttribute getOtherKeyAttribute()
+ {
+ return other;
+ }
+
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(subjectKeyIdentifier);
+
+ if (date != null)
+ {
+ v.add(date);
+ }
+
+ if (other != null)
+ {
+ v.add(other);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/SCVPReqRes.java b/core/src/main/java/org/spongycastle/asn1/cms/SCVPReqRes.java
new file mode 100644
index 00000000..0b702e8c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/SCVPReqRes.java
@@ -0,0 +1,108 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.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.spongycastle.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)
+ {
+ if (obj instanceof SCVPReqRes)
+ {
+ return (SCVPReqRes)obj;
+ }
+ else if (obj != null)
+ {
+ return new SCVPReqRes(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private SCVPReqRes(
+ ASN1Sequence seq)
+ {
+ if (seq.getObjectAt(0) instanceof ASN1TaggedObject)
+ {
+ this.request = ContentInfo.getInstance(ASN1TaggedObject.getInstance(seq.getObjectAt(0)), true);
+ this.response = ContentInfo.getInstance(seq.getObjectAt(1));
+ }
+ else
+ {
+ this.request = null;
+ this.response = ContentInfo.getInstance(seq.getObjectAt(0));
+ }
+ }
+
+ public SCVPReqRes(ContentInfo response)
+ {
+ this.request = null; // use of this confuses earlier JDKs
+ this.response = response;
+ }
+
+ public SCVPReqRes(ContentInfo request, ContentInfo response)
+ {
+ this.request = request;
+ this.response = response;
+ }
+
+ public ContentInfo getRequest()
+ {
+ return request;
+ }
+
+ public ContentInfo getResponse()
+ {
+ return response;
+ }
+
+ /**
+ * @return the ASN.1 primitive representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (request != null)
+ {
+ v.add(new DERTaggedObject(true, 0, request));
+ }
+
+ v.add(response);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/SignedData.java b/core/src/main/java/org/spongycastle/asn1/cms/SignedData.java
new file mode 100644
index 00000000..c564b391
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/SignedData.java
@@ -0,0 +1,330 @@
+package org.spongycastle.asn1.cms;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.BERSequence;
+import org.spongycastle.asn1.BERSet;
+import org.spongycastle.asn1.BERTaggedObject;
+import org.spongycastle.asn1.DERTaggedObject;
+
+/**
+ * <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
+{
+ private static final ASN1Integer VERSION_1 = new ASN1Integer(1);
+ private static final ASN1Integer VERSION_3 = new ASN1Integer(3);
+ private static final ASN1Integer VERSION_4 = new ASN1Integer(4);
+ private static final ASN1Integer VERSION_5 = new ASN1Integer(5);
+
+ private ASN1Integer version;
+ private ASN1Set digestAlgorithms;
+ private ContentInfo contentInfo;
+ private ASN1Set certificates;
+ private ASN1Set crls;
+ private ASN1Set signerInfos;
+ 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.spongycastle.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)
+ {
+ if (o instanceof SignedData)
+ {
+ return (SignedData)o;
+ }
+ else if (o != null)
+ {
+ return new SignedData(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public SignedData(
+ ASN1Set digestAlgorithms,
+ ContentInfo contentInfo,
+ ASN1Set certificates,
+ ASN1Set crls,
+ ASN1Set signerInfos)
+ {
+ this.version = calculateVersion(contentInfo.getContentType(), certificates, crls, signerInfos);
+ this.digestAlgorithms = digestAlgorithms;
+ this.contentInfo = contentInfo;
+ this.certificates = certificates;
+ this.crls = crls;
+ this.signerInfos = signerInfos;
+ this.crlsBer = crls instanceof BERSet;
+ this.certsBer = certificates instanceof BERSet;
+ }
+
+
+ private ASN1Integer calculateVersion(
+ ASN1ObjectIdentifier contentOid,
+ ASN1Set certs,
+ ASN1Set crls,
+ ASN1Set signerInfs)
+ {
+ boolean otherCert = false;
+ boolean otherCrl = false;
+ boolean attrCertV1Found = false;
+ boolean attrCertV2Found = false;
+
+ if (certs != null)
+ {
+ for (Enumeration en = certs.getObjects(); en.hasMoreElements();)
+ {
+ Object obj = en.nextElement();
+ if (obj instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tagged = ASN1TaggedObject.getInstance(obj);
+
+ if (tagged.getTagNo() == 1)
+ {
+ attrCertV1Found = true;
+ }
+ else if (tagged.getTagNo() == 2)
+ {
+ attrCertV2Found = true;
+ }
+ else if (tagged.getTagNo() == 3)
+ {
+ otherCert = true;
+ }
+ }
+ }
+ }
+
+ if (otherCert)
+ {
+ return new ASN1Integer(5);
+ }
+
+ if (crls != null) // no need to check if otherCert is true
+ {
+ for (Enumeration en = crls.getObjects(); en.hasMoreElements();)
+ {
+ Object obj = en.nextElement();
+ if (obj instanceof ASN1TaggedObject)
+ {
+ otherCrl = true;
+ }
+ }
+ }
+
+ if (otherCrl)
+ {
+ return VERSION_5;
+ }
+
+ if (attrCertV2Found)
+ {
+ return VERSION_4;
+ }
+
+ if (attrCertV1Found)
+ {
+ return VERSION_3;
+ }
+
+ if (checkForVersion3(signerInfs))
+ {
+ return VERSION_3;
+ }
+
+ if (!CMSObjectIdentifiers.data.equals(contentOid))
+ {
+ return VERSION_3;
+ }
+
+ return VERSION_1;
+ }
+
+ private boolean checkForVersion3(ASN1Set signerInfs)
+ {
+ for (Enumeration e = signerInfs.getObjects(); e.hasMoreElements();)
+ {
+ SignerInfo s = SignerInfo.getInstance(e.nextElement());
+
+ if (s.getVersion().getValue().intValue() == 3)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private SignedData(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ version = ASN1Integer.getInstance(e.nextElement());
+ digestAlgorithms = ((ASN1Set)e.nextElement());
+ contentInfo = ContentInfo.getInstance(e.nextElement());
+
+ while (e.hasMoreElements())
+ {
+ ASN1Primitive o = (ASN1Primitive)e.nextElement();
+
+ //
+ // an interesting feature of SignedData is that there appear
+ // to be varying implementations...
+ // for the moment we ignore anything which doesn't fit.
+ //
+ if (o instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tagged = (ASN1TaggedObject)o;
+
+ switch (tagged.getTagNo())
+ {
+ case 0:
+ certsBer = tagged instanceof BERTaggedObject;
+ certificates = ASN1Set.getInstance(tagged, false);
+ break;
+ case 1:
+ crlsBer = tagged instanceof BERTaggedObject;
+ crls = ASN1Set.getInstance(tagged, false);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag value " + tagged.getTagNo());
+ }
+ }
+ else
+ {
+ signerInfos = (ASN1Set)o;
+ }
+ }
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public ASN1Set getDigestAlgorithms()
+ {
+ return digestAlgorithms;
+ }
+
+ public ContentInfo getEncapContentInfo()
+ {
+ return contentInfo;
+ }
+
+ public ASN1Set getCertificates()
+ {
+ return certificates;
+ }
+
+ public ASN1Set getCRLs()
+ {
+ return crls;
+ }
+
+ public ASN1Set getSignerInfos()
+ {
+ return signerInfos;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(digestAlgorithms);
+ v.add(contentInfo);
+
+ if (certificates != null)
+ {
+ if (certsBer)
+ {
+ v.add(new BERTaggedObject(false, 0, certificates));
+ }
+ else
+ {
+ v.add(new DERTaggedObject(false, 0, certificates));
+ }
+ }
+
+ if (crls != null)
+ {
+ if (crlsBer)
+ {
+ v.add(new BERTaggedObject(false, 1, crls));
+ }
+ else
+ {
+ v.add(new DERTaggedObject(false, 1, crls));
+ }
+ }
+
+ v.add(signerInfos);
+
+ return new BERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/SignedDataParser.java b/core/src/main/java/org/spongycastle/asn1/cms/SignedDataParser.java
new file mode 100644
index 00000000..7e79a7bf
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/SignedDataParser.java
@@ -0,0 +1,141 @@
+package org.spongycastle.asn1.cms;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1SequenceParser;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.ASN1SetParser;
+import org.spongycastle.asn1.ASN1TaggedObjectParser;
+import org.spongycastle.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,
+ * digestAlgorithms DigestAlgorithmIdentifiers,
+ * encapContentInfo EncapsulatedContentInfo,
+ * certificates [0] IMPLICIT CertificateSet OPTIONAL,
+ * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+ * signerInfos SignerInfos
+ * }
+ * </pre>
+ */
+public class SignedDataParser
+{
+ private ASN1SequenceParser _seq;
+ private ASN1Integer _version;
+ private Object _nextObject;
+ private boolean _certsCalled;
+ private boolean _crlsCalled;
+
+ public static SignedDataParser getInstance(
+ Object o)
+ throws IOException
+ {
+ if (o instanceof ASN1Sequence)
+ {
+ return new SignedDataParser(((ASN1Sequence)o).parser());
+ }
+ if (o instanceof ASN1SequenceParser)
+ {
+ return new SignedDataParser((ASN1SequenceParser)o);
+ }
+
+ throw new IOException("unknown object encountered: " + o.getClass().getName());
+ }
+
+ private SignedDataParser(
+ ASN1SequenceParser seq)
+ throws IOException
+ {
+ this._seq = seq;
+ this._version = (ASN1Integer)seq.readObject();
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return _version;
+ }
+
+ public ASN1SetParser getDigestAlgorithms()
+ throws IOException
+ {
+ Object o = _seq.readObject();
+
+ if (o instanceof ASN1Set)
+ {
+ return ((ASN1Set)o).parser();
+ }
+
+ return (ASN1SetParser)o;
+ }
+
+ public ContentInfoParser getEncapContentInfo()
+ throws IOException
+ {
+ return new ContentInfoParser((ASN1SequenceParser)_seq.readObject());
+ }
+
+ public ASN1SetParser getCertificates()
+ throws IOException
+ {
+ _certsCalled = true;
+ _nextObject = _seq.readObject();
+
+ if (_nextObject instanceof ASN1TaggedObjectParser && ((ASN1TaggedObjectParser)_nextObject).getTagNo() == 0)
+ {
+ ASN1SetParser certs = (ASN1SetParser)((ASN1TaggedObjectParser)_nextObject).getObjectParser(BERTags.SET, false);
+ _nextObject = null;
+
+ return certs;
+ }
+
+ return null;
+ }
+
+ public ASN1SetParser getCrls()
+ throws IOException
+ {
+ if (!_certsCalled)
+ {
+ throw new IOException("getCerts() has not been called.");
+ }
+
+ _crlsCalled = true;
+
+ if (_nextObject == null)
+ {
+ _nextObject = _seq.readObject();
+ }
+
+ if (_nextObject instanceof ASN1TaggedObjectParser && ((ASN1TaggedObjectParser)_nextObject).getTagNo() == 1)
+ {
+ ASN1SetParser crls = (ASN1SetParser)((ASN1TaggedObjectParser)_nextObject).getObjectParser(BERTags.SET, false);
+ _nextObject = null;
+
+ return crls;
+ }
+
+ return null;
+ }
+
+ public ASN1SetParser getSignerInfos()
+ throws IOException
+ {
+ if (!_certsCalled || !_crlsCalled)
+ {
+ throw new IOException("getCerts() and/or getCrls() has not been called.");
+ }
+
+ if (_nextObject == null)
+ {
+ _nextObject = _seq.readObject();
+ }
+
+ return (ASN1SetParser)_nextObject;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/SignerIdentifier.java b/core/src/main/java/org/spongycastle/asn1/cms/SignerIdentifier.java
new file mode 100644
index 00000000..a2ab088b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/SignerIdentifier.java
@@ -0,0 +1,114 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.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
+{
+ private ASN1Encodable id;
+
+ public SignerIdentifier(
+ IssuerAndSerialNumber id)
+ {
+ this.id = id;
+ }
+
+ public SignerIdentifier(
+ ASN1OctetString id)
+ {
+ this.id = new DERTaggedObject(false, 0, id);
+ }
+
+ public SignerIdentifier(
+ ASN1Primitive id)
+ {
+ this.id = id;
+ }
+
+ /**
+ * 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.spongycastle.asn1.ASN1OctetString#getInstance(java.lang.Object) ASN1OctetString} input formats with SignerIdentifier structure inside
+ * <li> {@link org.spongycastle.asn1.ASN1Primitive ASN1Primitive} for SignerIdentifier constructor.
+ * </ul>
+ *
+ * @param o the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static SignerIdentifier getInstance(
+ Object o)
+ {
+ if (o == null || o instanceof SignerIdentifier)
+ {
+ return (SignerIdentifier)o;
+ }
+
+ if (o instanceof IssuerAndSerialNumber)
+ {
+ return new SignerIdentifier((IssuerAndSerialNumber)o);
+ }
+
+ if (o instanceof ASN1OctetString)
+ {
+ return new SignerIdentifier((ASN1OctetString)o);
+ }
+
+ if (o instanceof ASN1Primitive)
+ {
+ return new SignerIdentifier((ASN1Primitive)o);
+ }
+
+ throw new IllegalArgumentException(
+ "Illegal object in SignerIdentifier: " + o.getClass().getName());
+ }
+
+ public boolean isTagged()
+ {
+ return (id instanceof ASN1TaggedObject);
+ }
+
+ public ASN1Encodable getId()
+ {
+ if (id instanceof ASN1TaggedObject)
+ {
+ return ASN1OctetString.getInstance((ASN1TaggedObject)id, false);
+ }
+
+ return id;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return id.toASN1Primitive();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/SignerInfo.java b/core/src/main/java/org/spongycastle/asn1/cms/SignerInfo.java
new file mode 100644
index 00000000..301f26e3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/SignerInfo.java
@@ -0,0 +1,282 @@
+package org.spongycastle.asn1.cms;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.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
+{
+ private ASN1Integer version;
+ private SignerIdentifier sid;
+ private AlgorithmIdentifier digAlgorithm;
+ private ASN1Set authenticatedAttributes;
+ private AlgorithmIdentifier digEncryptionAlgorithm;
+ 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.spongycastle.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 instanceof SignerInfo)
+ {
+ return (SignerInfo)o;
+ }
+ else if (o != null)
+ {
+ return new SignerInfo(ASN1Sequence.getInstance(o));
+ }
+
+ 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,
+ ASN1Set authenticatedAttributes,
+ AlgorithmIdentifier digEncryptionAlgorithm,
+ ASN1OctetString encryptedDigest,
+ ASN1Set unauthenticatedAttributes)
+ {
+ if (sid.isTagged())
+ {
+ this.version = new ASN1Integer(3);
+ }
+ else
+ {
+ this.version = new ASN1Integer(1);
+ }
+
+ this.sid = sid;
+ this.digAlgorithm = digAlgorithm;
+ this.authenticatedAttributes = authenticatedAttributes;
+ this.digEncryptionAlgorithm = digEncryptionAlgorithm;
+ this.encryptedDigest = encryptedDigest;
+ 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,
+ Attributes authenticatedAttributes,
+ AlgorithmIdentifier digEncryptionAlgorithm,
+ ASN1OctetString encryptedDigest,
+ Attributes unauthenticatedAttributes)
+ {
+ if (sid.isTagged())
+ {
+ this.version = new ASN1Integer(3);
+ }
+ else
+ {
+ this.version = new ASN1Integer(1);
+ }
+
+ this.sid = sid;
+ this.digAlgorithm = digAlgorithm;
+ this.authenticatedAttributes = ASN1Set.getInstance(authenticatedAttributes);
+ this.digEncryptionAlgorithm = digEncryptionAlgorithm;
+ this.encryptedDigest = encryptedDigest;
+ this.unauthenticatedAttributes = ASN1Set.getInstance(unauthenticatedAttributes);
+ }
+
+ /**
+ * @deprecated use getInstance() method.
+ */
+ public SignerInfo(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ version = (ASN1Integer)e.nextElement();
+ sid = SignerIdentifier.getInstance(e.nextElement());
+ digAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement());
+
+ Object obj = e.nextElement();
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ authenticatedAttributes = ASN1Set.getInstance((ASN1TaggedObject)obj, false);
+
+ digEncryptionAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement());
+ }
+ else
+ {
+ authenticatedAttributes = null;
+ digEncryptionAlgorithm = AlgorithmIdentifier.getInstance(obj);
+ }
+
+ encryptedDigest = DEROctetString.getInstance(e.nextElement());
+
+ if (e.hasMoreElements())
+ {
+ unauthenticatedAttributes = ASN1Set.getInstance((ASN1TaggedObject)e.nextElement(), false);
+ }
+ else
+ {
+ unauthenticatedAttributes = null;
+ }
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public SignerIdentifier getSID()
+ {
+ return sid;
+ }
+
+ public ASN1Set getAuthenticatedAttributes()
+ {
+ return authenticatedAttributes;
+ }
+
+ public AlgorithmIdentifier getDigestAlgorithm()
+ {
+ return digAlgorithm;
+ }
+
+ public ASN1OctetString getEncryptedDigest()
+ {
+ return encryptedDigest;
+ }
+
+ public AlgorithmIdentifier getDigestEncryptionAlgorithm()
+ {
+ return digEncryptionAlgorithm;
+ }
+
+ public ASN1Set getUnauthenticatedAttributes()
+ {
+ return unauthenticatedAttributes;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(sid);
+ v.add(digAlgorithm);
+
+ if (authenticatedAttributes != null)
+ {
+ v.add(new DERTaggedObject(false, 0, authenticatedAttributes));
+ }
+
+ v.add(digEncryptionAlgorithm);
+ v.add(encryptedDigest);
+
+ if (unauthenticatedAttributes != null)
+ {
+ v.add(new DERTaggedObject(false, 1, unauthenticatedAttributes));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/Time.java b/core/src/main/java/org/spongycastle/asn1/cms/Time.java
new file mode 100644
index 00000000..1dccff36
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/Time.java
@@ -0,0 +1,198 @@
+package org.spongycastle.asn1.cms;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.SimpleTimeZone;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.ASN1UTCTime;
+import org.spongycastle.asn1.DERGeneralizedTime;
+import org.spongycastle.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.spongycastle.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.spongycastle.asn1.DERGeneralizedTime DERGeneralizedTime}.
+ */
+public class Time
+ extends ASN1Object
+ implements ASN1Choice
+{
+ ASN1Primitive time;
+
+ public static Time getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject());
+ }
+
+ /**
+ * @deprecated use getInstance()
+ */
+ public Time(
+ ASN1Primitive time)
+ {
+ if (!(time instanceof ASN1UTCTime)
+ && !(time instanceof ASN1GeneralizedTime))
+ {
+ throw new IllegalArgumentException("unknown object passed to Time");
+ }
+
+ this.time = time;
+ }
+
+ /**
+ * Creates a time object from a given date - if the date is between 1950
+ * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
+ * is used.
+ *
+ * @param time a date object representing the time of interest.
+ */
+ public Time(
+ Date time)
+ {
+ SimpleTimeZone tz = new SimpleTimeZone(0, "Z");
+ SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss");
+
+ dateF.setTimeZone(tz);
+
+ String d = dateF.format(time) + "Z";
+ int year = Integer.parseInt(d.substring(0, 4));
+
+ if (year < 1950 || year > 2049)
+ {
+ this.time = new DERGeneralizedTime(d);
+ }
+ else
+ {
+ this.time = new DERUTCTime(d.substring(2));
+ }
+ }
+
+ /**
+ * Creates a time object from a given date and locale - if the date is between 1950
+ * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
+ * is used. You may need to use this constructor if the default locale
+ * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible with other ASN.1 implementations.
+ *
+ * @param time a date object representing the time of interest.
+ * @param locale an appropriate Locale for producing an ASN.1 GeneralizedTime value.
+ */
+ public Time(
+ Date time,
+ Locale locale)
+ {
+ SimpleTimeZone tz = new SimpleTimeZone(0, "Z");
+ SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss", locale);
+
+ dateF.setTimeZone(tz);
+
+ String d = dateF.format(time) + "Z";
+ int year = Integer.parseInt(d.substring(0, 4));
+
+ if (year < 1950 || year > 2049)
+ {
+ this.time = new DERGeneralizedTime(d);
+ }
+ else
+ {
+ this.time = new DERUTCTime(d.substring(2));
+ }
+ }
+
+ /**
+ * Return a Time object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link Time} object
+ * <li> {@link org.spongycastle.asn1.DERUTCTime DERUTCTime} object
+ * <li> {@link org.spongycastle.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)
+ {
+ if (obj == null || obj instanceof Time)
+ {
+ return (Time)obj;
+ }
+ else if (obj instanceof ASN1UTCTime)
+ {
+ return new Time((ASN1UTCTime)obj);
+ }
+ else if (obj instanceof ASN1GeneralizedTime)
+ {
+ return new Time((ASN1GeneralizedTime)obj);
+ }
+
+ 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 ASN1UTCTime)
+ {
+ return ((ASN1UTCTime)time).getAdjustedTime();
+ }
+ else
+ {
+ return ((ASN1GeneralizedTime)time).getTime();
+ }
+ }
+
+ /**
+ * Get java.util.Date version of date+time.
+ */
+ public Date getDate()
+ {
+ try
+ {
+ if (time instanceof ASN1UTCTime)
+ {
+ return ((ASN1UTCTime)time).getAdjustedDate();
+ }
+ else
+ {
+ return ((ASN1GeneralizedTime)time).getDate();
+ }
+ }
+ catch (ParseException e)
+ { // this should never happen
+ throw new IllegalStateException("invalid date string: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return time;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/TimeStampAndCRL.java b/core/src/main/java/org/spongycastle/asn1/cms/TimeStampAndCRL.java
new file mode 100644
index 00000000..af5d3bef
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/TimeStampAndCRL.java
@@ -0,0 +1,96 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.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
+{
+ private ContentInfo timeStamp;
+ private CertificateList crl;
+
+ public TimeStampAndCRL(ContentInfo timeStamp)
+ {
+ this.timeStamp = timeStamp;
+ }
+
+ private TimeStampAndCRL(ASN1Sequence seq)
+ {
+ this.timeStamp = ContentInfo.getInstance(seq.getObjectAt(0));
+ if (seq.size() == 2)
+ {
+ this.crl = CertificateList.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ /**
+ * Return a TimeStampAndCRL object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link TimeStampAndCRL} object
+ * <li> {@link org.spongycastle.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)
+ {
+ return (TimeStampAndCRL)obj;
+ }
+ else if (obj != null)
+ {
+ return new TimeStampAndCRL(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ContentInfo getTimeStampToken()
+ {
+ return this.timeStamp;
+ }
+
+ /** @deprecated use getCRL() */
+ public CertificateList getCertificateList()
+ {
+ return this.crl;
+ }
+
+ public CertificateList getCRL()
+ {
+ return this.crl;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(timeStamp);
+
+ if (crl != null)
+ {
+ v.add(crl);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/TimeStampTokenEvidence.java b/core/src/main/java/org/spongycastle/asn1/cms/TimeStampTokenEvidence.java
new file mode 100644
index 00000000..1a2e622d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/TimeStampTokenEvidence.java
@@ -0,0 +1,98 @@
+package org.spongycastle.asn1.cms;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.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
+{
+ private TimeStampAndCRL[] timeStampAndCRLs;
+
+ public TimeStampTokenEvidence(TimeStampAndCRL[] timeStampAndCRLs)
+ {
+ this.timeStampAndCRLs = timeStampAndCRLs;
+ }
+
+ public TimeStampTokenEvidence(TimeStampAndCRL timeStampAndCRL)
+ {
+ this.timeStampAndCRLs = new TimeStampAndCRL[1];
+
+ timeStampAndCRLs[0] = timeStampAndCRL;
+ }
+
+ private TimeStampTokenEvidence(ASN1Sequence seq)
+ {
+ this.timeStampAndCRLs = new TimeStampAndCRL[seq.size()];
+
+ int count = 0;
+
+ for (Enumeration en = seq.getObjects(); en.hasMoreElements();)
+ {
+ timeStampAndCRLs[count++] = TimeStampAndCRL.getInstance(en.nextElement());
+ }
+ }
+
+ public static TimeStampTokenEvidence getInstance(ASN1TaggedObject tagged, boolean explicit)
+ {
+ 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.spongycastle.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)
+ {
+ return (TimeStampTokenEvidence)obj;
+ }
+ else if (obj != null)
+ {
+ return new TimeStampTokenEvidence(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public TimeStampAndCRL[] toTimeStampAndCRLArray()
+ {
+ return timeStampAndCRLs;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ for (int i = 0; i != timeStampAndCRLs.length; i++)
+ {
+ v.add(timeStampAndCRLs[i]);
+ }
+
+ return new DERSequence(v);
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/TimeStampedData.java b/core/src/main/java/org/spongycastle/asn1/cms/TimeStampedData.java
new file mode 100644
index 00000000..ab201dca
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/TimeStampedData.java
@@ -0,0 +1,131 @@
+package org.spongycastle.asn1.cms;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.BERSequence;
+import org.spongycastle.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
+{
+ private ASN1Integer version;
+ private DERIA5String dataUri;
+ private MetaData metaData;
+ private ASN1OctetString content;
+ private Evidence temporalEvidence;
+
+ public TimeStampedData(DERIA5String dataUri, MetaData metaData, ASN1OctetString content, Evidence temporalEvidence)
+ {
+ this.version = new ASN1Integer(1);
+ this.dataUri = dataUri;
+ this.metaData = metaData;
+ this.content = content;
+ this.temporalEvidence = temporalEvidence;
+ }
+
+ private TimeStampedData(ASN1Sequence seq)
+ {
+ this.version = ASN1Integer.getInstance(seq.getObjectAt(0));
+
+ int index = 1;
+ if (seq.getObjectAt(index) instanceof DERIA5String)
+ {
+ this.dataUri = DERIA5String.getInstance(seq.getObjectAt(index++));
+ }
+ if (seq.getObjectAt(index) instanceof MetaData || seq.getObjectAt(index) instanceof ASN1Sequence)
+ {
+ this.metaData = MetaData.getInstance(seq.getObjectAt(index++));
+ }
+ if (seq.getObjectAt(index) instanceof ASN1OctetString)
+ {
+ this.content = ASN1OctetString.getInstance(seq.getObjectAt(index++));
+ }
+ 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.spongycastle.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 == null || obj instanceof TimeStampedData)
+ {
+ return (TimeStampedData)obj;
+ }
+ return new TimeStampedData(ASN1Sequence.getInstance(obj));
+ }
+
+ public DERIA5String getDataUri()
+ {
+ return dataUri;
+ }
+
+ public MetaData getMetaData()
+ {
+ return metaData;
+ }
+
+ public ASN1OctetString getContent()
+ {
+ return content;
+ }
+
+ public Evidence getTemporalEvidence()
+ {
+ return temporalEvidence;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+
+ if (dataUri != null)
+ {
+ v.add(dataUri);
+ }
+
+ if (metaData != null)
+ {
+ v.add(metaData);
+ }
+
+ if (content != null)
+ {
+ v.add(content);
+ }
+
+ v.add(temporalEvidence);
+
+ return new BERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/TimeStampedDataParser.java b/core/src/main/java/org/spongycastle/asn1/cms/TimeStampedDataParser.java
new file mode 100644
index 00000000..bf5d288a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/TimeStampedDataParser.java
@@ -0,0 +1,141 @@
+package org.spongycastle.asn1.cms;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1OctetStringParser;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1SequenceParser;
+import org.spongycastle.asn1.BERSequence;
+import org.spongycastle.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;
+ private DERIA5String dataUri;
+ private MetaData metaData;
+ private ASN1OctetStringParser content;
+ private Evidence temporalEvidence;
+ private ASN1SequenceParser parser;
+
+ private TimeStampedDataParser(ASN1SequenceParser parser)
+ throws IOException
+ {
+ this.parser = parser;
+ this.version = ASN1Integer.getInstance(parser.readObject());
+
+ ASN1Encodable obj = parser.readObject();
+
+ if (obj instanceof DERIA5String)
+ {
+ this.dataUri = DERIA5String.getInstance(obj);
+ obj = parser.readObject();
+ }
+ if (obj instanceof MetaData || obj instanceof ASN1SequenceParser)
+ {
+ this.metaData = MetaData.getInstance(obj.toASN1Primitive());
+ obj = parser.readObject();
+ }
+ if (obj instanceof ASN1OctetStringParser)
+ {
+ this.content = (ASN1OctetStringParser)obj;
+ }
+ }
+
+ public static TimeStampedDataParser getInstance(Object obj)
+ throws IOException
+ {
+ if (obj instanceof ASN1Sequence)
+ {
+ return new TimeStampedDataParser(((ASN1Sequence)obj).parser());
+ }
+ if (obj instanceof ASN1SequenceParser)
+ {
+ return new TimeStampedDataParser((ASN1SequenceParser)obj);
+ }
+
+ return null;
+ }
+
+ public DERIA5String getDataUri()
+ {
+ return dataUri;
+ }
+
+ public MetaData getMetaData()
+ {
+ return metaData;
+ }
+
+ public ASN1OctetStringParser getContent()
+ {
+ return content;
+ }
+
+ public Evidence getTemporalEvidence()
+ throws IOException
+ {
+ if (temporalEvidence == null)
+ {
+ temporalEvidence = Evidence.getInstance(parser.readObject().toASN1Primitive());
+ }
+
+ return temporalEvidence;
+ }
+
+ /**
+ * <pre>
+ * TimeStampedData ::= SEQUENCE {
+ * version INTEGER { v1(1) },
+ * dataUri IA5String OPTIONAL,
+ * metaData MetaData OPTIONAL,
+ * content OCTET STRING OPTIONAL,
+ * temporalEvidence Evidence
+ * }
+ * </pre>
+ * @return
+ * @deprecated will be removed
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+
+ if (dataUri != null)
+ {
+ v.add(dataUri);
+ }
+
+ if (metaData != null)
+ {
+ v.add(metaData);
+ }
+
+ if (content != null)
+ {
+ v.add(content);
+ }
+
+ v.add(temporalEvidence);
+
+ return new BERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cms/ecc/MQVuserKeyingMaterial.java b/core/src/main/java/org/spongycastle/asn1/cms/ecc/MQVuserKeyingMaterial.java
new file mode 100644
index 00000000..ae95a3d9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cms/ecc/MQVuserKeyingMaterial.java
@@ -0,0 +1,122 @@
+package org.spongycastle.asn1.cms.ecc;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.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
+{
+ private OriginatorPublicKey ephemeralPublicKey;
+ private ASN1OctetString addedukm;
+
+ public MQVuserKeyingMaterial(
+ OriginatorPublicKey ephemeralPublicKey,
+ ASN1OctetString addedukm)
+ {
+ // TODO Check ephemeralPublicKey not null
+
+ this.ephemeralPublicKey = ephemeralPublicKey;
+ this.addedukm = addedukm;
+ }
+
+ private MQVuserKeyingMaterial(
+ ASN1Sequence seq)
+ {
+ // TODO Check seq has either 1 or 2 elements
+
+ this.ephemeralPublicKey = OriginatorPublicKey.getInstance(
+ seq.getObjectAt(0));
+
+ if (seq.size() > 1)
+ {
+ this.addedukm = ASN1OctetString.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(1), true);
+ }
+ }
+
+ /**
+ * 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
+ * tagged false otherwise.
+ * @throws IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static MQVuserKeyingMaterial getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * Return an MQVuserKeyingMaterial object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link MQVuserKeyingMaterial} object
+ * <li> {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence} with MQVuserKeyingMaterial inside it.
+ * </ul>
+ *
+ * @param obj the object we want converted.
+ * @throws IllegalArgumentException if the object cannot be converted.
+ */
+ public static MQVuserKeyingMaterial getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof MQVuserKeyingMaterial)
+ {
+ return (MQVuserKeyingMaterial)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new MQVuserKeyingMaterial((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid MQVuserKeyingMaterial: " + obj.getClass().getName());
+ }
+
+ public OriginatorPublicKey getEphemeralPublicKey()
+ {
+ return ephemeralPublicKey;
+ }
+
+ public ASN1OctetString getAddedukm()
+ {
+ return addedukm;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(ephemeralPublicKey);
+
+ if (addedukm != null)
+ {
+ v.add(new DERTaggedObject(true, 0, addedukm));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/crmf/AttributeTypeAndValue.java b/core/src/main/java/org/spongycastle/asn1/crmf/AttributeTypeAndValue.java
new file mode 100644
index 00000000..1120e7f7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/crmf/AttributeTypeAndValue.java
@@ -0,0 +1,80 @@
+package org.spongycastle.asn1.crmf;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class AttributeTypeAndValue
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier type;
+ private ASN1Encodable value;
+
+ private AttributeTypeAndValue(ASN1Sequence seq)
+ {
+ type = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ value = (ASN1Encodable)seq.getObjectAt(1);
+ }
+
+ public static AttributeTypeAndValue getInstance(Object o)
+ {
+ if (o instanceof AttributeTypeAndValue)
+ {
+ return (AttributeTypeAndValue)o;
+ }
+
+ if (o != null)
+ {
+ return new AttributeTypeAndValue(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public AttributeTypeAndValue(
+ String oid,
+ ASN1Encodable value)
+ {
+ this(new ASN1ObjectIdentifier(oid), value);
+ }
+
+ public AttributeTypeAndValue(
+ ASN1ObjectIdentifier type,
+ ASN1Encodable value)
+ {
+ this.type = type;
+ this.value = value;
+ }
+
+ public ASN1ObjectIdentifier getType()
+ {
+ return type;
+ }
+
+ public ASN1Encodable getValue()
+ {
+ return value;
+ }
+
+ /**
+ * <pre>
+ * AttributeTypeAndValue ::= SEQUENCE {
+ * type OBJECT IDENTIFIER,
+ * value ANY DEFINED BY type }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(type);
+ v.add(value);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/crmf/CRMFObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/crmf/CRMFObjectIdentifiers.java
new file mode 100644
index 00000000..3911ad4a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/crmf/CRMFObjectIdentifiers.java
@@ -0,0 +1,29 @@
+package org.spongycastle.asn1.crmf;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.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
+
+ /** 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");
+ /** 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");
+ /** 1.3.6.1.5.5.7.1.4 */
+ static final ASN1ObjectIdentifier id_regCtrl_pkiArchiveOptions = id_regCtrl.branch("4");
+
+ /** 1.2.840.113549.1.9.16.1,21 */
+ static final ASN1ObjectIdentifier id_ct_encKeyWithID = PKCSObjectIdentifiers.id_ct.branch("21");
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/crmf/CertId.java b/core/src/main/java/org/spongycastle/asn1/crmf/CertId.java
new file mode 100644
index 00000000..7a29236e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/crmf/CertId.java
@@ -0,0 +1,84 @@
+package org.spongycastle.asn1.crmf;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.GeneralName;
+
+public class CertId
+ extends ASN1Object
+{
+ private GeneralName issuer;
+ private ASN1Integer serialNumber;
+
+ private CertId(ASN1Sequence seq)
+ {
+ issuer = GeneralName.getInstance(seq.getObjectAt(0));
+ serialNumber = ASN1Integer.getInstance(seq.getObjectAt(1));
+ }
+
+ public static CertId getInstance(Object o)
+ {
+ if (o instanceof CertId)
+ {
+ return (CertId)o;
+ }
+
+ if (o != null)
+ {
+ return new CertId(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public static CertId getInstance(ASN1TaggedObject obj, boolean isExplicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, isExplicit));
+ }
+
+ public CertId(GeneralName issuer, BigInteger serialNumber)
+ {
+ this(issuer, new ASN1Integer(serialNumber));
+ }
+
+ public CertId(GeneralName issuer, ASN1Integer serialNumber)
+ {
+ this.issuer = issuer;
+ this.serialNumber = serialNumber;
+ }
+
+ public GeneralName getIssuer()
+ {
+ return issuer;
+ }
+
+ public ASN1Integer getSerialNumber()
+ {
+ return serialNumber;
+ }
+
+ /**
+ * <pre>
+ * CertId ::= SEQUENCE {
+ * issuer GeneralName,
+ * serialNumber INTEGER }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(issuer);
+ v.add(serialNumber);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/crmf/CertReqMessages.java b/core/src/main/java/org/spongycastle/asn1/crmf/CertReqMessages.java
new file mode 100644
index 00000000..1be5fd86
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/crmf/CertReqMessages.java
@@ -0,0 +1,74 @@
+package org.spongycastle.asn1.crmf;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class CertReqMessages
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private CertReqMessages(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static CertReqMessages getInstance(Object o)
+ {
+ if (o instanceof CertReqMessages)
+ {
+ return (CertReqMessages)o;
+ }
+
+ if (o != null)
+ {
+ return new CertReqMessages(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CertReqMessages(
+ CertReqMsg msg)
+ {
+ content = new DERSequence(msg);
+ }
+
+ public CertReqMessages(
+ CertReqMsg[] msgs)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < msgs.length; i++)
+ {
+ v.add(msgs[i]);
+ }
+ content = new DERSequence(v);
+ }
+
+ public CertReqMsg[] toCertReqMsgArray()
+ {
+ CertReqMsg[] result = new CertReqMsg[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = CertReqMsg.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ * <pre>
+ * CertReqMessages ::= SEQUENCE SIZE (1..MAX) OF CertReqMsg
+ * </pre>
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/crmf/CertReqMsg.java b/core/src/main/java/org/spongycastle/asn1/crmf/CertReqMsg.java
new file mode 100644
index 00000000..9e563c8b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/crmf/CertReqMsg.java
@@ -0,0 +1,145 @@
+package org.spongycastle.asn1.crmf;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+
+public class CertReqMsg
+ extends ASN1Object
+{
+ private CertRequest certReq;
+ private ProofOfPossession pop;
+ private ASN1Sequence regInfo;
+
+ private CertReqMsg(ASN1Sequence seq)
+ {
+ Enumeration en = seq.getObjects();
+
+ certReq = CertRequest.getInstance(en.nextElement());
+ while (en.hasMoreElements())
+ {
+ Object o = en.nextElement();
+
+ if (o instanceof ASN1TaggedObject || o instanceof ProofOfPossession)
+ {
+ pop = ProofOfPossession.getInstance(o);
+ }
+ else
+ {
+ regInfo = ASN1Sequence.getInstance(o);
+ }
+ }
+ }
+
+ public static CertReqMsg getInstance(Object o)
+ {
+ if (o instanceof CertReqMsg)
+ {
+ return (CertReqMsg)o;
+ }
+ else if (o != null)
+ {
+ return new CertReqMsg(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ /**
+ * Creates a new CertReqMsg.
+ * @param certReq CertRequest
+ * @param pop may be null
+ * @param regInfo may be null
+ */
+ public CertReqMsg(
+ CertRequest certReq,
+ ProofOfPossession pop,
+ AttributeTypeAndValue[] regInfo)
+ {
+ if (certReq == null)
+ {
+ throw new IllegalArgumentException("'certReq' cannot be null");
+ }
+
+ this.certReq = certReq;
+ this.pop = pop;
+
+ if (regInfo != null)
+ {
+ this.regInfo = new DERSequence(regInfo);
+ }
+ }
+
+ public CertRequest getCertReq()
+ {
+ return certReq;
+ }
+
+
+ /**
+ * @deprecated use getPopo
+ */
+ public ProofOfPossession getPop()
+ {
+ return pop;
+ }
+
+
+ public ProofOfPossession getPopo()
+ {
+ return pop;
+ }
+
+ public AttributeTypeAndValue[] getRegInfo()
+ {
+ if (regInfo == null)
+ {
+ return null;
+ }
+
+ AttributeTypeAndValue[] results = new AttributeTypeAndValue[regInfo.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = AttributeTypeAndValue.getInstance(regInfo.getObjectAt(i));
+ }
+
+ return results;
+ }
+
+ /**
+ * <pre>
+ * CertReqMsg ::= SEQUENCE {
+ * certReq CertRequest,
+ * popo ProofOfPossession OPTIONAL,
+ * -- content depends upon key type
+ * regInfo SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue OPTIONAL }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certReq);
+
+ addOptional(v, pop);
+ addOptional(v, regInfo);
+
+ return new DERSequence(v);
+ }
+
+ private void addOptional(ASN1EncodableVector v, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(obj);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/crmf/CertRequest.java b/core/src/main/java/org/spongycastle/asn1/crmf/CertRequest.java
new file mode 100644
index 00000000..7497aa65
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/crmf/CertRequest.java
@@ -0,0 +1,97 @@
+package org.spongycastle.asn1.crmf;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class CertRequest
+ extends ASN1Object
+{
+ private ASN1Integer certReqId;
+ private CertTemplate certTemplate;
+ private Controls controls;
+
+ private CertRequest(ASN1Sequence seq)
+ {
+ certReqId = new ASN1Integer(ASN1Integer.getInstance(seq.getObjectAt(0)).getValue());
+ certTemplate = CertTemplate.getInstance(seq.getObjectAt(1));
+ if (seq.size() > 2)
+ {
+ controls = Controls.getInstance(seq.getObjectAt(2));
+ }
+ }
+
+ public static CertRequest getInstance(Object o)
+ {
+ if (o instanceof CertRequest)
+ {
+ return (CertRequest)o;
+ }
+ else if (o != null)
+ {
+ return new CertRequest(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CertRequest(
+ int certReqId,
+ CertTemplate certTemplate,
+ Controls controls)
+ {
+ this(new ASN1Integer(certReqId), certTemplate, controls);
+ }
+
+ public CertRequest(
+ ASN1Integer certReqId,
+ CertTemplate certTemplate,
+ Controls controls)
+ {
+ this.certReqId = certReqId;
+ this.certTemplate = certTemplate;
+ this.controls = controls;
+ }
+
+ public ASN1Integer getCertReqId()
+ {
+ return certReqId;
+ }
+
+ public CertTemplate getCertTemplate()
+ {
+ return certTemplate;
+ }
+
+ public Controls getControls()
+ {
+ return controls;
+ }
+
+ /**
+ * <pre>
+ * CertRequest ::= SEQUENCE {
+ * certReqId INTEGER, -- ID for matching request and reply
+ * certTemplate CertTemplate, -- Selected fields of cert to be issued
+ * controls Controls OPTIONAL } -- Attributes affecting issuance
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certReqId);
+ v.add(certTemplate);
+
+ if (controls != null)
+ {
+ v.add(controls);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/crmf/CertTemplate.java b/core/src/main/java/org/spongycastle/asn1/crmf/CertTemplate.java
new file mode 100644
index 00000000..cb32d3f5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/crmf/CertTemplate.java
@@ -0,0 +1,163 @@
+package org.spongycastle.asn1.crmf;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.x500.X500Name;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.Extensions;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+
+public class CertTemplate
+ extends ASN1Object
+{
+ private ASN1Sequence seq;
+
+ private ASN1Integer version;
+ private ASN1Integer serialNumber;
+ private AlgorithmIdentifier signingAlg;
+ private X500Name issuer;
+ private OptionalValidity validity;
+ private X500Name subject;
+ private SubjectPublicKeyInfo publicKey;
+ private DERBitString issuerUID;
+ private DERBitString subjectUID;
+ private Extensions extensions;
+
+ private CertTemplate(ASN1Sequence seq)
+ {
+ this.seq = seq;
+
+ Enumeration en = seq.getObjects();
+ while (en.hasMoreElements())
+ {
+ ASN1TaggedObject tObj = (ASN1TaggedObject)en.nextElement();
+
+ switch (tObj.getTagNo())
+ {
+ case 0:
+ version = ASN1Integer.getInstance(tObj, false);
+ break;
+ case 1:
+ serialNumber = ASN1Integer.getInstance(tObj, false);
+ break;
+ case 2:
+ signingAlg = AlgorithmIdentifier.getInstance(tObj, false);
+ break;
+ case 3:
+ issuer = X500Name.getInstance(tObj, true); // CHOICE
+ break;
+ case 4:
+ validity = OptionalValidity.getInstance(ASN1Sequence.getInstance(tObj, false));
+ break;
+ case 5:
+ subject = X500Name.getInstance(tObj, true); // CHOICE
+ break;
+ case 6:
+ publicKey = SubjectPublicKeyInfo.getInstance(tObj, false);
+ break;
+ case 7:
+ issuerUID = DERBitString.getInstance(tObj, false);
+ break;
+ case 8:
+ subjectUID = DERBitString.getInstance(tObj, false);
+ break;
+ case 9:
+ extensions = Extensions.getInstance(tObj, false);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag: " + tObj.getTagNo());
+ }
+ }
+ }
+
+ public static CertTemplate getInstance(Object o)
+ {
+ if (o instanceof CertTemplate)
+ {
+ return (CertTemplate)o;
+ }
+ else if (o != null)
+ {
+ return new CertTemplate(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public int getVersion()
+ {
+ return version.getValue().intValue();
+ }
+
+ public ASN1Integer getSerialNumber()
+ {
+ return serialNumber;
+ }
+
+ public AlgorithmIdentifier getSigningAlg()
+ {
+ return signingAlg;
+ }
+
+ public X500Name getIssuer()
+ {
+ return issuer;
+ }
+
+ public OptionalValidity getValidity()
+ {
+ return validity;
+ }
+
+ public X500Name getSubject()
+ {
+ return subject;
+ }
+
+ public SubjectPublicKeyInfo getPublicKey()
+ {
+ return publicKey;
+ }
+
+ public DERBitString getIssuerUID()
+ {
+ return issuerUID;
+ }
+
+ public DERBitString getSubjectUID()
+ {
+ return subjectUID;
+ }
+
+ public Extensions getExtensions()
+ {
+ return extensions;
+ }
+
+ /**
+ * <pre>
+ * CertTemplate ::= SEQUENCE {
+ * version [0] Version OPTIONAL,
+ * serialNumber [1] INTEGER OPTIONAL,
+ * signingAlg [2] AlgorithmIdentifier OPTIONAL,
+ * issuer [3] Name OPTIONAL,
+ * validity [4] OptionalValidity OPTIONAL,
+ * subject [5] Name OPTIONAL,
+ * publicKey [6] SubjectPublicKeyInfo OPTIONAL,
+ * issuerUID [7] UniqueIdentifier OPTIONAL,
+ * subjectUID [8] UniqueIdentifier OPTIONAL,
+ * extensions [9] Extensions OPTIONAL }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return seq;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/crmf/CertTemplateBuilder.java b/core/src/main/java/org/spongycastle/asn1/crmf/CertTemplateBuilder.java
new file mode 100644
index 00000000..4d595775
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/crmf/CertTemplateBuilder.java
@@ -0,0 +1,152 @@
+package org.spongycastle.asn1.crmf;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x500.X500Name;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.Extensions;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.spongycastle.asn1.x509.X509Extensions;
+
+public class CertTemplateBuilder
+{
+ private ASN1Integer version;
+ private ASN1Integer serialNumber;
+ private AlgorithmIdentifier signingAlg;
+ private X500Name issuer;
+ private OptionalValidity validity;
+ private X500Name subject;
+ private SubjectPublicKeyInfo publicKey;
+ private DERBitString issuerUID;
+ private DERBitString subjectUID;
+ private Extensions extensions;
+
+ /** Sets the X.509 version. Note: for X509v3, use 2 here. */
+ public CertTemplateBuilder setVersion(int ver)
+ {
+ version = new ASN1Integer(ver);
+
+ return this;
+ }
+
+ public CertTemplateBuilder setSerialNumber(ASN1Integer ser)
+ {
+ serialNumber = ser;
+
+ return this;
+ }
+
+ public CertTemplateBuilder setSigningAlg(AlgorithmIdentifier aid)
+ {
+ signingAlg = aid;
+
+ return this;
+ }
+
+ public CertTemplateBuilder setIssuer(X500Name name)
+ {
+ issuer = name;
+
+ return this;
+ }
+
+ public CertTemplateBuilder setValidity(OptionalValidity v)
+ {
+ validity = v;
+
+ return this;
+ }
+
+ public CertTemplateBuilder setSubject(X500Name name)
+ {
+ subject = name;
+
+ return this;
+ }
+
+ public CertTemplateBuilder setPublicKey(SubjectPublicKeyInfo spki)
+ {
+ publicKey = spki;
+
+ return this;
+ }
+
+ /** Sets the issuer unique ID (deprecated in X.509v3) */
+ public CertTemplateBuilder setIssuerUID(DERBitString uid)
+ {
+ issuerUID = uid;
+
+ return this;
+ }
+
+ /** Sets the subject unique ID (deprecated in X.509v3) */
+ public CertTemplateBuilder setSubjectUID(DERBitString uid)
+ {
+ subjectUID = uid;
+
+ return this;
+ }
+
+ /**
+ * @deprecated use method taking Extensions
+ * @param extens
+ * @return
+ */
+ public CertTemplateBuilder setExtensions(X509Extensions extens)
+ {
+ return setExtensions(Extensions.getInstance(extens));
+ }
+
+ public CertTemplateBuilder setExtensions(Extensions extens)
+ {
+ extensions = extens;
+
+ return this;
+ }
+
+ /**
+ * <pre>
+ * CertTemplate ::= SEQUENCE {
+ * version [0] Version OPTIONAL,
+ * serialNumber [1] INTEGER OPTIONAL,
+ * signingAlg [2] AlgorithmIdentifier OPTIONAL,
+ * issuer [3] Name OPTIONAL,
+ * validity [4] OptionalValidity OPTIONAL,
+ * subject [5] Name OPTIONAL,
+ * publicKey [6] SubjectPublicKeyInfo OPTIONAL,
+ * issuerUID [7] UniqueIdentifier OPTIONAL,
+ * subjectUID [8] UniqueIdentifier OPTIONAL,
+ * extensions [9] Extensions OPTIONAL }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public CertTemplate build()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ addOptional(v, 0, false, version);
+ addOptional(v, 1, false, serialNumber);
+ addOptional(v, 2, false, signingAlg);
+ addOptional(v, 3, true, issuer); // CHOICE
+ addOptional(v, 4, false, validity);
+ addOptional(v, 5, true, subject); // CHOICE
+ addOptional(v, 6, false, publicKey);
+ addOptional(v, 7, false, issuerUID);
+ addOptional(v, 8, false, subjectUID);
+ addOptional(v, 9, false, extensions);
+
+ return CertTemplate.getInstance(new DERSequence(v));
+ }
+
+ private void addOptional(ASN1EncodableVector v, int tagNo, boolean isExplicit, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(new DERTaggedObject(isExplicit, tagNo, obj));
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/crmf/Controls.java b/core/src/main/java/org/spongycastle/asn1/crmf/Controls.java
new file mode 100644
index 00000000..89b1f2da
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/crmf/Controls.java
@@ -0,0 +1,72 @@
+package org.spongycastle.asn1.crmf;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class Controls
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private Controls(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static Controls getInstance(Object o)
+ {
+ if (o instanceof Controls)
+ {
+ return (Controls)o;
+ }
+
+ if (o != null)
+ {
+ return new Controls(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public Controls(AttributeTypeAndValue atv)
+ {
+ content = new DERSequence(atv);
+ }
+
+ public Controls(AttributeTypeAndValue[] atvs)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < atvs.length; i++)
+ {
+ v.add(atvs[i]);
+ }
+ content = new DERSequence(v);
+ }
+
+ public AttributeTypeAndValue[] toAttributeTypeAndValueArray()
+ {
+ AttributeTypeAndValue[] result = new AttributeTypeAndValue[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = AttributeTypeAndValue.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ * <pre>
+ * Controls ::= SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue
+ * </pre>
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/crmf/EncKeyWithID.java b/core/src/main/java/org/spongycastle/asn1/crmf/EncKeyWithID.java
new file mode 100644
index 00000000..a89aa6b5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/crmf/EncKeyWithID.java
@@ -0,0 +1,117 @@
+package org.spongycastle.asn1.crmf;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERUTF8String;
+import org.spongycastle.asn1.pkcs.PrivateKeyInfo;
+import org.spongycastle.asn1.x509.GeneralName;
+
+public class EncKeyWithID
+ extends ASN1Object
+{
+ private final PrivateKeyInfo privKeyInfo;
+ private final ASN1Encodable identifier;
+
+ public static EncKeyWithID getInstance(Object o)
+ {
+ if (o instanceof EncKeyWithID)
+ {
+ return (EncKeyWithID)o;
+ }
+ else if (o != null)
+ {
+ return new EncKeyWithID(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ private EncKeyWithID(ASN1Sequence seq)
+ {
+ this.privKeyInfo = PrivateKeyInfo.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() > 1)
+ {
+ if (!(seq.getObjectAt(1) instanceof DERUTF8String))
+ {
+ this.identifier = GeneralName.getInstance(seq.getObjectAt(1));
+ }
+ else
+ {
+ this.identifier = (ASN1Encodable)seq.getObjectAt(1);
+ }
+ }
+ else
+ {
+ this.identifier = null;
+ }
+ }
+
+ public EncKeyWithID(PrivateKeyInfo privKeyInfo)
+ {
+ this.privKeyInfo = privKeyInfo;
+ this.identifier = null;
+ }
+
+ public EncKeyWithID(PrivateKeyInfo privKeyInfo, DERUTF8String str)
+ {
+ this.privKeyInfo = privKeyInfo;
+ this.identifier = str;
+ }
+
+ public EncKeyWithID(PrivateKeyInfo privKeyInfo, GeneralName generalName)
+ {
+ this.privKeyInfo = privKeyInfo;
+ this.identifier = generalName;
+ }
+
+ public PrivateKeyInfo getPrivateKey()
+ {
+ return privKeyInfo;
+ }
+
+ public boolean hasIdentifier()
+ {
+ return identifier != null;
+ }
+
+ public boolean isIdentifierUTF8String()
+ {
+ return identifier instanceof DERUTF8String;
+ }
+
+ public ASN1Encodable getIdentifier()
+ {
+ return identifier;
+ }
+
+ /**
+ * <pre>
+ * EncKeyWithID ::= SEQUENCE {
+ * privateKey PrivateKeyInfo,
+ * identifier CHOICE {
+ * string UTF8String,
+ * generalName GeneralName
+ * } OPTIONAL
+ * }
+ * </pre>
+ * @return
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(privKeyInfo);
+
+ if (identifier != null)
+ {
+ v.add(identifier);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/crmf/EncryptedKey.java b/core/src/main/java/org/spongycastle/asn1/crmf/EncryptedKey.java
new file mode 100644
index 00000000..d62aee76
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/crmf/EncryptedKey.java
@@ -0,0 +1,81 @@
+package org.spongycastle.asn1.crmf;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.cms.EnvelopedData;
+
+public class EncryptedKey
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private EnvelopedData envelopedData;
+ private EncryptedValue encryptedValue;
+
+ public static EncryptedKey getInstance(Object o)
+ {
+ if (o instanceof EncryptedKey)
+ {
+ return (EncryptedKey)o;
+ }
+ else if (o instanceof ASN1TaggedObject)
+ {
+ return new EncryptedKey(EnvelopedData.getInstance((ASN1TaggedObject)o, false));
+ }
+ else if (o instanceof EncryptedValue)
+ {
+ return new EncryptedKey((EncryptedValue)o);
+ }
+ else
+ {
+ return new EncryptedKey(EncryptedValue.getInstance(o));
+ }
+ }
+
+ public EncryptedKey(EnvelopedData envelopedData)
+ {
+ this.envelopedData = envelopedData;
+ }
+
+ public EncryptedKey(EncryptedValue encryptedValue)
+ {
+ this.encryptedValue = encryptedValue;
+ }
+
+ public boolean isEncryptedValue()
+ {
+ return encryptedValue != null;
+ }
+
+ public ASN1Encodable getValue()
+ {
+ if (encryptedValue != null)
+ {
+ return encryptedValue;
+ }
+
+ return envelopedData;
+ }
+
+ /**
+ * <pre>
+ * EncryptedKey ::= CHOICE {
+ * encryptedValue EncryptedValue, -- deprecated
+ * envelopedData [0] EnvelopedData }
+ * -- The encrypted private key MUST be placed in the envelopedData
+ * -- encryptedContentInfo encryptedContent OCTET STRING.
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (encryptedValue != null)
+ {
+ return encryptedValue.toASN1Primitive();
+ }
+
+ return new DERTaggedObject(false, 0, envelopedData);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/crmf/EncryptedValue.java b/core/src/main/java/org/spongycastle/asn1/crmf/EncryptedValue.java
new file mode 100644
index 00000000..6191e3dc
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/crmf/EncryptedValue.java
@@ -0,0 +1,164 @@
+package org.spongycastle.asn1.crmf;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+public class EncryptedValue
+ extends ASN1Object
+{
+ private AlgorithmIdentifier intendedAlg;
+ private AlgorithmIdentifier symmAlg;
+ private DERBitString encSymmKey;
+ private AlgorithmIdentifier keyAlg;
+ private ASN1OctetString valueHint;
+ private DERBitString encValue;
+
+ private EncryptedValue(ASN1Sequence seq)
+ {
+ int index = 0;
+ while (seq.getObjectAt(index) instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tObj = (ASN1TaggedObject)seq.getObjectAt(index);
+
+ switch (tObj.getTagNo())
+ {
+ case 0:
+ intendedAlg = AlgorithmIdentifier.getInstance(tObj, false);
+ break;
+ case 1:
+ symmAlg = AlgorithmIdentifier.getInstance(tObj, false);
+ break;
+ case 2:
+ encSymmKey = DERBitString.getInstance(tObj, false);
+ break;
+ case 3:
+ keyAlg = AlgorithmIdentifier.getInstance(tObj, false);
+ break;
+ case 4:
+ valueHint = ASN1OctetString.getInstance(tObj, false);
+ break;
+ }
+ index++;
+ }
+
+ encValue = DERBitString.getInstance(seq.getObjectAt(index));
+ }
+
+ public static EncryptedValue getInstance(Object o)
+ {
+ if (o instanceof EncryptedValue)
+ {
+ return (EncryptedValue)o;
+ }
+ else if (o != null)
+ {
+ return new EncryptedValue(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public EncryptedValue(
+ AlgorithmIdentifier intendedAlg,
+ AlgorithmIdentifier symmAlg,
+ DERBitString encSymmKey,
+ AlgorithmIdentifier keyAlg,
+ ASN1OctetString valueHint,
+ DERBitString encValue)
+ {
+ if (encValue == null)
+ {
+ throw new IllegalArgumentException("'encValue' cannot be null");
+ }
+
+ this.intendedAlg = intendedAlg;
+ this.symmAlg = symmAlg;
+ this.encSymmKey = encSymmKey;
+ this.keyAlg = keyAlg;
+ this.valueHint = valueHint;
+ this.encValue = encValue;
+ }
+
+ public AlgorithmIdentifier getIntendedAlg()
+ {
+ return intendedAlg;
+ }
+
+ public AlgorithmIdentifier getSymmAlg()
+ {
+ return symmAlg;
+ }
+
+ public DERBitString getEncSymmKey()
+ {
+ return encSymmKey;
+ }
+
+ public AlgorithmIdentifier getKeyAlg()
+ {
+ return keyAlg;
+ }
+
+ public ASN1OctetString getValueHint()
+ {
+ return valueHint;
+ }
+
+ public DERBitString getEncValue()
+ {
+ return encValue;
+ }
+
+ /**
+ * <pre>
+ * EncryptedValue ::= SEQUENCE {
+ * intendedAlg [0] AlgorithmIdentifier OPTIONAL,
+ * -- the intended algorithm for which the value will be used
+ * symmAlg [1] AlgorithmIdentifier OPTIONAL,
+ * -- the symmetric algorithm used to encrypt the value
+ * encSymmKey [2] BIT STRING OPTIONAL,
+ * -- the (encrypted) symmetric key used to encrypt the value
+ * keyAlg [3] AlgorithmIdentifier OPTIONAL,
+ * -- algorithm used to encrypt the symmetric key
+ * valueHint [4] OCTET STRING OPTIONAL,
+ * -- a brief description or identifier of the encValue content
+ * -- (may be meaningful only to the sending entity, and used only
+ * -- if EncryptedValue might be re-examined by the sending entity
+ * -- in the future)
+ * encValue BIT STRING }
+ * -- the encrypted value itself
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ addOptional(v, 0, intendedAlg);
+ addOptional(v, 1, symmAlg);
+ addOptional(v, 2, encSymmKey);
+ addOptional(v, 3, keyAlg);
+ addOptional(v, 4, valueHint);
+
+ v.add(encValue);
+
+ return new DERSequence(v);
+ }
+
+ private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(new DERTaggedObject(false, tagNo, obj));
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/crmf/OptionalValidity.java b/core/src/main/java/org/spongycastle/asn1/crmf/OptionalValidity.java
new file mode 100644
index 00000000..240d03b3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/crmf/OptionalValidity.java
@@ -0,0 +1,98 @@
+package org.spongycastle.asn1.crmf;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.Time;
+
+public class OptionalValidity
+ extends ASN1Object
+{
+ private Time notBefore;
+ private Time notAfter;
+
+ private OptionalValidity(ASN1Sequence seq)
+ {
+ Enumeration en = seq.getObjects();
+ while (en.hasMoreElements())
+ {
+ ASN1TaggedObject tObj = (ASN1TaggedObject)en.nextElement();
+
+ if (tObj.getTagNo() == 0)
+ {
+ notBefore = Time.getInstance(tObj, true);
+ }
+ else
+ {
+ notAfter = Time.getInstance(tObj, true);
+ }
+ }
+ }
+
+ public static OptionalValidity getInstance(Object o)
+ {
+ if (o instanceof OptionalValidity)
+ {
+ return (OptionalValidity)o;
+ }
+
+ if (o != null)
+ {
+ return new OptionalValidity(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public OptionalValidity(Time notBefore, Time notAfter)
+ {
+ if (notBefore == null && notAfter == null)
+ {
+ throw new IllegalArgumentException("at least one of notBefore/notAfter must not be null.");
+ }
+
+ this.notBefore = notBefore;
+ this.notAfter = notAfter;
+ }
+
+ public Time getNotBefore()
+ {
+ return notBefore;
+ }
+
+ public Time getNotAfter()
+ {
+ return notAfter;
+ }
+
+ /**
+ * <pre>
+ * OptionalValidity ::= SEQUENCE {
+ * notBefore [0] Time OPTIONAL,
+ * notAfter [1] Time OPTIONAL } --at least one MUST be present
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (notBefore != null)
+ {
+ v.add(new DERTaggedObject(true, 0, notBefore));
+ }
+
+ if (notAfter != null)
+ {
+ v.add(new DERTaggedObject(true, 1, notAfter));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/crmf/PKIArchiveOptions.java b/core/src/main/java/org/spongycastle/asn1/crmf/PKIArchiveOptions.java
new file mode 100644
index 00000000..3c374fb0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/crmf/PKIArchiveOptions.java
@@ -0,0 +1,116 @@
+package org.spongycastle.asn1.crmf;
+
+import org.spongycastle.asn1.ASN1Boolean;
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERTaggedObject;
+
+public class PKIArchiveOptions
+ extends ASN1Object
+ implements ASN1Choice
+{
+ public static final int encryptedPrivKey = 0;
+ public static final int keyGenParameters = 1;
+ public static final int archiveRemGenPrivKey = 2;
+
+ private ASN1Encodable value;
+
+ public static PKIArchiveOptions getInstance(Object o)
+ {
+ if (o == null || o instanceof PKIArchiveOptions)
+ {
+ return (PKIArchiveOptions)o;
+ }
+ else if (o instanceof ASN1TaggedObject)
+ {
+ return new PKIArchiveOptions((ASN1TaggedObject)o);
+ }
+
+ throw new IllegalArgumentException("unknown object: " + o);
+ }
+
+ private PKIArchiveOptions(ASN1TaggedObject tagged)
+ {
+ switch (tagged.getTagNo())
+ {
+ case encryptedPrivKey:
+ value = EncryptedKey.getInstance(tagged.getObject());
+ break;
+ case keyGenParameters:
+ value = ASN1OctetString.getInstance(tagged, false);
+ break;
+ case archiveRemGenPrivKey:
+ value = ASN1Boolean.getInstance(tagged, false);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag number: " + tagged.getTagNo());
+ }
+ }
+
+ public PKIArchiveOptions(EncryptedKey encKey)
+ {
+ this.value = encKey;
+ }
+
+ public PKIArchiveOptions(ASN1OctetString keyGenParameters)
+ {
+ this.value = keyGenParameters;
+ }
+
+ public PKIArchiveOptions(boolean archiveRemGenPrivKey)
+ {
+ this.value = ASN1Boolean.getInstance(archiveRemGenPrivKey);
+ }
+
+ public int getType()
+ {
+ if (value instanceof EncryptedKey)
+ {
+ return encryptedPrivKey;
+ }
+
+ if (value instanceof ASN1OctetString)
+ {
+ return keyGenParameters;
+ }
+
+ return archiveRemGenPrivKey;
+ }
+
+ public ASN1Encodable getValue()
+ {
+ return value;
+ }
+
+ /**
+ * <pre>
+ * PKIArchiveOptions ::= CHOICE {
+ * encryptedPrivKey [0] EncryptedKey,
+ * -- the actual value of the private key
+ * keyGenParameters [1] KeyGenParameters,
+ * -- parameters which allow the private key to be re-generated
+ * archiveRemGenPrivKey [2] BOOLEAN }
+ * -- set to TRUE if sender wishes receiver to archive the private
+ * -- key of a key pair that the receiver generates in response to
+ * -- this request; set to FALSE if no archival is desired.
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (value instanceof EncryptedKey)
+ {
+ return new DERTaggedObject(true, encryptedPrivKey, value); // choice
+ }
+
+ if (value instanceof ASN1OctetString)
+ {
+ return new DERTaggedObject(false, keyGenParameters, value);
+ }
+
+ return new DERTaggedObject(false, archiveRemGenPrivKey, value);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/crmf/PKIPublicationInfo.java b/core/src/main/java/org/spongycastle/asn1/crmf/PKIPublicationInfo.java
new file mode 100644
index 00000000..d19d3f64
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/crmf/PKIPublicationInfo.java
@@ -0,0 +1,81 @@
+package org.spongycastle.asn1.crmf;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class PKIPublicationInfo
+ extends ASN1Object
+{
+ private ASN1Integer action;
+ private ASN1Sequence pubInfos;
+
+ private PKIPublicationInfo(ASN1Sequence seq)
+ {
+ action = ASN1Integer.getInstance(seq.getObjectAt(0));
+ pubInfos = ASN1Sequence.getInstance(seq.getObjectAt(1));
+ }
+
+ public static PKIPublicationInfo getInstance(Object o)
+ {
+ if (o instanceof PKIPublicationInfo)
+ {
+ return (PKIPublicationInfo)o;
+ }
+
+ if (o != null)
+ {
+ return new PKIPublicationInfo(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer getAction()
+ {
+ return action;
+ }
+
+ public SinglePubInfo[] getPubInfos()
+ {
+ if (pubInfos == null)
+ {
+ return null;
+ }
+
+ SinglePubInfo[] results = new SinglePubInfo[pubInfos.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = SinglePubInfo.getInstance(pubInfos.getObjectAt(i));
+ }
+
+ return results;
+ }
+
+ /**
+ * <pre>
+ * PKIPublicationInfo ::= SEQUENCE {
+ * action INTEGER {
+ * dontPublish (0),
+ * pleasePublish (1) },
+ * pubInfos SEQUENCE SIZE (1..MAX) OF SinglePubInfo OPTIONAL }
+ * -- pubInfos MUST NOT be present if action is "dontPublish"
+ * -- (if action is "pleasePublish" and pubInfos is omitted,
+ * -- "dontCare" is assumed)
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(action);
+ v.add(pubInfos);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/crmf/PKMACValue.java b/core/src/main/java/org/spongycastle/asn1/crmf/PKMACValue.java
new file mode 100644
index 00000000..c3481df0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/crmf/PKMACValue.java
@@ -0,0 +1,104 @@
+package org.spongycastle.asn1.crmf;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.cmp.CMPObjectIdentifiers;
+import org.spongycastle.asn1.cmp.PBMParameter;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * Password-based MAC value for use with POPOSigningKeyInput.
+ */
+public class PKMACValue
+ extends ASN1Object
+{
+ private AlgorithmIdentifier algId;
+ private DERBitString value;
+
+ private PKMACValue(ASN1Sequence seq)
+ {
+ algId = AlgorithmIdentifier.getInstance(seq.getObjectAt(0));
+ value = DERBitString.getInstance(seq.getObjectAt(1));
+ }
+
+ public static PKMACValue getInstance(Object o)
+ {
+ if (o instanceof PKMACValue)
+ {
+ return (PKMACValue)o;
+ }
+
+ if (o != null)
+ {
+ return new PKMACValue(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public static PKMACValue getInstance(ASN1TaggedObject obj, boolean isExplicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, isExplicit));
+ }
+
+ /**
+ * Creates a new PKMACValue.
+ * @param params parameters for password-based MAC
+ * @param value MAC of the DER-encoded SubjectPublicKeyInfo
+ */
+ public PKMACValue(
+ PBMParameter params,
+ DERBitString value)
+ {
+ this(new AlgorithmIdentifier(
+ CMPObjectIdentifiers.passwordBasedMac, params), value);
+ }
+
+ /**
+ * Creates a new PKMACValue.
+ * @param aid CMPObjectIdentifiers.passwordBasedMAC, with PBMParameter
+ * @param value MAC of the DER-encoded SubjectPublicKeyInfo
+ */
+ public PKMACValue(
+ AlgorithmIdentifier aid,
+ DERBitString value)
+ {
+ this.algId = aid;
+ this.value = value;
+ }
+
+ public AlgorithmIdentifier getAlgId()
+ {
+ return algId;
+ }
+
+ public DERBitString getValue()
+ {
+ return value;
+ }
+
+ /**
+ * <pre>
+ * PKMACValue ::= SEQUENCE {
+ * algId AlgorithmIdentifier,
+ * -- algorithm value shall be PasswordBasedMac 1.2.840.113533.7.66.13
+ * -- parameter value is PBMParameter
+ * value BIT STRING }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(algId);
+ v.add(value);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/crmf/POPOPrivKey.java b/core/src/main/java/org/spongycastle/asn1/crmf/POPOPrivKey.java
new file mode 100644
index 00000000..4b32bceb
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/crmf/POPOPrivKey.java
@@ -0,0 +1,104 @@
+package org.spongycastle.asn1.crmf;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.cms.EnvelopedData;
+
+public class POPOPrivKey
+ extends ASN1Object
+ implements ASN1Choice
+{
+ public static final int thisMessage = 0;
+ public static final int subsequentMessage = 1;
+ public static final int dhMAC = 2;
+ public static final int agreeMAC = 3;
+ public static final int encryptedKey = 4;
+
+ private int tagNo;
+ private ASN1Encodable obj;
+
+ private POPOPrivKey(ASN1TaggedObject obj)
+ {
+ this.tagNo = obj.getTagNo();
+
+ switch (tagNo)
+ {
+ case thisMessage:
+ this.obj = DERBitString.getInstance(obj, false);
+ break;
+ case subsequentMessage:
+ this.obj = SubsequentMessage.valueOf(ASN1Integer.getInstance(obj, false).getValue().intValue());
+ break;
+ case dhMAC:
+ this.obj = DERBitString.getInstance(obj, false);
+ break;
+ case agreeMAC:
+ this.obj = PKMACValue.getInstance(obj, false);
+ break;
+ case encryptedKey:
+ this.obj = EnvelopedData.getInstance(obj, false);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag in POPOPrivKey");
+ }
+ }
+
+ public static POPOPrivKey getInstance(Object obj)
+ {
+ if (obj instanceof POPOPrivKey)
+ {
+ return (POPOPrivKey)obj;
+ }
+ if (obj != null)
+ {
+ return new POPOPrivKey(ASN1TaggedObject.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static POPOPrivKey getInstance(ASN1TaggedObject obj, boolean explicit)
+ {
+ return getInstance(ASN1TaggedObject.getInstance(obj, explicit));
+ }
+
+ public POPOPrivKey(SubsequentMessage msg)
+ {
+ this.tagNo = subsequentMessage;
+ this.obj = msg;
+ }
+
+ public int getType()
+ {
+ return tagNo;
+ }
+
+ public ASN1Encodable getValue()
+ {
+ return obj;
+ }
+
+ /**
+ * <pre>
+ * POPOPrivKey ::= CHOICE {
+ * thisMessage [0] BIT STRING, -- Deprecated
+ * -- possession is proven in this message (which contains the private
+ * -- key itself (encrypted for the CA))
+ * subsequentMessage [1] SubsequentMessage,
+ * -- possession will be proven in a subsequent message
+ * dhMAC [2] BIT STRING, -- Deprecated
+ * agreeMAC [3] PKMACValue,
+ * encryptedKey [4] EnvelopedData }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERTaggedObject(false, tagNo, obj);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/crmf/POPOSigningKey.java b/core/src/main/java/org/spongycastle/asn1/crmf/POPOSigningKey.java
new file mode 100644
index 00000000..9f300c0d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/crmf/POPOSigningKey.java
@@ -0,0 +1,127 @@
+package org.spongycastle.asn1.crmf;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+public class POPOSigningKey
+ extends ASN1Object
+{
+ private POPOSigningKeyInput poposkInput;
+ private AlgorithmIdentifier algorithmIdentifier;
+ private DERBitString signature;
+
+ private POPOSigningKey(ASN1Sequence seq)
+ {
+ int index = 0;
+
+ if (seq.getObjectAt(index) instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tagObj
+ = (ASN1TaggedObject)seq.getObjectAt(index++);
+ if (tagObj.getTagNo() != 0)
+ {
+ throw new IllegalArgumentException(
+ "Unknown POPOSigningKeyInput tag: " + tagObj.getTagNo());
+ }
+ poposkInput = POPOSigningKeyInput.getInstance(tagObj.getObject());
+ }
+ algorithmIdentifier = AlgorithmIdentifier.getInstance(seq.getObjectAt(index++));
+ signature = DERBitString.getInstance(seq.getObjectAt(index));
+ }
+
+ public static POPOSigningKey getInstance(Object o)
+ {
+ if (o instanceof POPOSigningKey)
+ {
+ return (POPOSigningKey)o;
+ }
+
+ if (o != null)
+ {
+ return new POPOSigningKey(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public static POPOSigningKey getInstance(ASN1TaggedObject obj, boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * Creates a new Proof of Possession object for a signing key.
+ *
+ * @param poposkIn the POPOSigningKeyInput structure, or null if the
+ * CertTemplate includes both subject and publicKey values.
+ * @param aid the AlgorithmIdentifier used to sign the proof of possession.
+ * @param signature a signature over the DER-encoded value of poposkIn,
+ * or the DER-encoded value of certReq if poposkIn is null.
+ */
+ public POPOSigningKey(
+ POPOSigningKeyInput poposkIn,
+ AlgorithmIdentifier aid,
+ DERBitString signature)
+ {
+ this.poposkInput = poposkIn;
+ this.algorithmIdentifier = aid;
+ this.signature = signature;
+ }
+
+ public POPOSigningKeyInput getPoposkInput()
+ {
+ return poposkInput;
+ }
+
+ public AlgorithmIdentifier getAlgorithmIdentifier()
+ {
+ return algorithmIdentifier;
+ }
+
+ public DERBitString getSignature()
+ {
+ return signature;
+ }
+
+ /**
+ * <pre>
+ * POPOSigningKey ::= SEQUENCE {
+ * poposkInput [0] POPOSigningKeyInput OPTIONAL,
+ * algorithmIdentifier AlgorithmIdentifier,
+ * signature BIT STRING }
+ * -- The signature (using "algorithmIdentifier") is on the
+ * -- DER-encoded value of poposkInput. NOTE: If the CertReqMsg
+ * -- certReq CertTemplate contains the subject and publicKey values,
+ * -- then poposkInput MUST be omitted and the signature MUST be
+ * -- computed on the DER-encoded value of CertReqMsg certReq. If
+ * -- the CertReqMsg certReq CertTemplate does not contain the public
+ * -- key and subject values, then poposkInput MUST be present and
+ * -- MUST be signed. This strategy ensures that the public key is
+ * -- not present in both the poposkInput and CertReqMsg certReq
+ * -- CertTemplate fields.
+ * </pre>
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (poposkInput != null)
+ {
+ v.add(new DERTaggedObject(false, 0, poposkInput));
+ }
+
+ v.add(algorithmIdentifier);
+ v.add(signature);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/crmf/POPOSigningKeyInput.java b/core/src/main/java/org/spongycastle/asn1/crmf/POPOSigningKeyInput.java
new file mode 100644
index 00000000..5b0c90f3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/crmf/POPOSigningKeyInput.java
@@ -0,0 +1,134 @@
+package org.spongycastle.asn1.crmf;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.GeneralName;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+
+public class POPOSigningKeyInput
+ extends ASN1Object
+{
+ private GeneralName sender;
+ private PKMACValue publicKeyMAC;
+ private SubjectPublicKeyInfo publicKey;
+
+ private POPOSigningKeyInput(ASN1Sequence seq)
+ {
+ ASN1Encodable authInfo = (ASN1Encodable)seq.getObjectAt(0);
+
+ if (authInfo instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tagObj = (ASN1TaggedObject)authInfo;
+ if (tagObj.getTagNo() != 0)
+ {
+ throw new IllegalArgumentException(
+ "Unknown authInfo tag: " + tagObj.getTagNo());
+ }
+ sender = GeneralName.getInstance(tagObj.getObject());
+ }
+ else
+ {
+ publicKeyMAC = PKMACValue.getInstance(authInfo);
+ }
+
+ publicKey = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(1));
+ }
+
+ public static POPOSigningKeyInput getInstance(Object o)
+ {
+ if (o instanceof POPOSigningKeyInput)
+ {
+ return (POPOSigningKeyInput)o;
+ }
+
+ if (o != null)
+ {
+ return new POPOSigningKeyInput(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ /**
+ * Creates a new POPOSigningKeyInput with sender name as authInfo.
+ */
+ public POPOSigningKeyInput(
+ GeneralName sender,
+ SubjectPublicKeyInfo spki)
+ {
+ this.sender = sender;
+ this.publicKey = spki;
+ }
+
+ /**
+ * Creates a new POPOSigningKeyInput using password-based MAC.
+ */
+ public POPOSigningKeyInput(
+ PKMACValue pkmac,
+ SubjectPublicKeyInfo spki)
+ {
+ this.publicKeyMAC = pkmac;
+ this.publicKey = spki;
+ }
+
+ /**
+ * Returns the sender field, or null if authInfo is publicKeyMAC
+ */
+ public GeneralName getSender()
+ {
+ return sender;
+ }
+
+ /**
+ * Returns the publicKeyMAC field, or null if authInfo is sender
+ */
+ public PKMACValue getPublicKeyMAC()
+ {
+ return publicKeyMAC;
+ }
+
+ public SubjectPublicKeyInfo getPublicKey()
+ {
+ return publicKey;
+ }
+
+ /**
+ * <pre>
+ * POPOSigningKeyInput ::= SEQUENCE {
+ * authInfo CHOICE {
+ * sender [0] GeneralName,
+ * -- used only if an authenticated identity has been
+ * -- established for the sender (e.g., a DN from a
+ * -- previously-issued and currently-valid certificate
+ * publicKeyMAC PKMACValue },
+ * -- used if no authenticated GeneralName currently exists for
+ * -- the sender; publicKeyMAC contains a password-based MAC
+ * -- on the DER-encoded value of publicKey
+ * publicKey SubjectPublicKeyInfo } -- from CertTemplate
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (sender != null)
+ {
+ v.add(new DERTaggedObject(false, 0, sender));
+ }
+ else
+ {
+ v.add(publicKeyMAC);
+ }
+
+ v.add(publicKey);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/crmf/ProofOfPossession.java b/core/src/main/java/org/spongycastle/asn1/crmf/ProofOfPossession.java
new file mode 100644
index 00000000..e1ace116
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/crmf/ProofOfPossession.java
@@ -0,0 +1,108 @@
+package org.spongycastle.asn1.crmf;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERNull;
+import org.spongycastle.asn1.DERTaggedObject;
+
+public class ProofOfPossession
+ extends ASN1Object
+ implements ASN1Choice
+{
+ public static final int TYPE_RA_VERIFIED = 0;
+ public static final int TYPE_SIGNING_KEY = 1;
+ public static final int TYPE_KEY_ENCIPHERMENT = 2;
+ public static final int TYPE_KEY_AGREEMENT = 3;
+
+ private int tagNo;
+ private ASN1Encodable obj;
+
+ private ProofOfPossession(ASN1TaggedObject tagged)
+ {
+ tagNo = tagged.getTagNo();
+ switch (tagNo)
+ {
+ case 0:
+ obj = DERNull.INSTANCE;
+ break;
+ case 1:
+ obj = POPOSigningKey.getInstance(tagged, false);
+ break;
+ case 2:
+ case 3:
+ obj = POPOPrivKey.getInstance(tagged, true);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag: " + tagNo);
+ }
+ }
+
+ public static ProofOfPossession getInstance(Object o)
+ {
+ if (o == null || o instanceof ProofOfPossession)
+ {
+ return (ProofOfPossession)o;
+ }
+
+ if (o instanceof ASN1TaggedObject)
+ {
+ return new ProofOfPossession((ASN1TaggedObject)o);
+ }
+
+ throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
+ }
+
+ /** Creates a ProofOfPossession with type raVerified. */
+ public ProofOfPossession()
+ {
+ tagNo = TYPE_RA_VERIFIED;
+ obj = DERNull.INSTANCE;
+ }
+
+ /** Creates a ProofOfPossession for a signing key. */
+ public ProofOfPossession(POPOSigningKey poposk)
+ {
+ tagNo = TYPE_SIGNING_KEY;
+ obj = poposk;
+ }
+
+ /**
+ * Creates a ProofOfPossession for key encipherment or agreement.
+ * @param type one of TYPE_KEY_ENCIPHERMENT or TYPE_KEY_AGREEMENT
+ */
+ public ProofOfPossession(int type, POPOPrivKey privkey)
+ {
+ tagNo = type;
+ obj = privkey;
+ }
+
+ public int getType()
+ {
+ return tagNo;
+ }
+
+ public ASN1Encodable getObject()
+ {
+ return obj;
+ }
+
+ /**
+ * <pre>
+ * ProofOfPossession ::= CHOICE {
+ * raVerified [0] NULL,
+ * -- used if the RA has already verified that the requester is in
+ * -- possession of the private key
+ * signature [1] POPOSigningKey,
+ * keyEncipherment [2] POPOPrivKey,
+ * keyAgreement [3] POPOPrivKey }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERTaggedObject(false, tagNo, obj);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/crmf/SinglePubInfo.java b/core/src/main/java/org/spongycastle/asn1/crmf/SinglePubInfo.java
new file mode 100644
index 00000000..52f21c99
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/crmf/SinglePubInfo.java
@@ -0,0 +1,72 @@
+package org.spongycastle.asn1.crmf;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.GeneralName;
+
+public class SinglePubInfo
+ extends ASN1Object
+{
+ private ASN1Integer pubMethod;
+ private GeneralName pubLocation;
+
+ private SinglePubInfo(ASN1Sequence seq)
+ {
+ pubMethod = ASN1Integer.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() == 2)
+ {
+ pubLocation = GeneralName.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ public static SinglePubInfo getInstance(Object o)
+ {
+ if (o instanceof SinglePubInfo)
+ {
+ return (SinglePubInfo)o;
+ }
+
+ if (o != null)
+ {
+ return new SinglePubInfo(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public GeneralName getPubLocation()
+ {
+ return pubLocation;
+ }
+
+ /**
+ * <pre>
+ * SinglePubInfo ::= SEQUENCE {
+ * pubMethod INTEGER {
+ * dontCare (0),
+ * x500 (1),
+ * web (2),
+ * ldap (3) },
+ * pubLocation GeneralName OPTIONAL }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(pubMethod);
+
+ if (pubLocation != null)
+ {
+ v.add(pubLocation);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/crmf/SubsequentMessage.java b/core/src/main/java/org/spongycastle/asn1/crmf/SubsequentMessage.java
new file mode 100644
index 00000000..c646faf5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/crmf/SubsequentMessage.java
@@ -0,0 +1,29 @@
+package org.spongycastle.asn1.crmf;
+
+import org.spongycastle.asn1.ASN1Integer;
+
+public class SubsequentMessage
+ extends ASN1Integer
+{
+ public static final SubsequentMessage encrCert = new SubsequentMessage(0);
+ public static final SubsequentMessage challengeResp = new SubsequentMessage(1);
+
+ private SubsequentMessage(int value)
+ {
+ super(value);
+ }
+
+ public static SubsequentMessage valueOf(int value)
+ {
+ if (value == 0)
+ {
+ return encrCert;
+ }
+ if (value == 1)
+ {
+ return challengeResp;
+ }
+
+ throw new IllegalArgumentException("unknown value: " + value);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cryptopro/CryptoProObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/cryptopro/CryptoProObjectIdentifiers.java
new file mode 100644
index 00000000..bdcf9284
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cryptopro/CryptoProObjectIdentifiers.java
@@ -0,0 +1,101 @@
+package org.spongycastle.asn1.cryptopro;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+
+/**
+ * <pre>
+ * GOST Algorithms OBJECT IDENTIFIERS :
+ * { iso(1) member-body(2) ru(643) rans(2) cryptopro(2)}
+ * </pre>
+ */
+public interface CryptoProObjectIdentifiers
+{
+ /** 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");
+
+ /** 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");
+
+ /** 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");
+
+ /** 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/core/src/main/java/org/spongycastle/asn1/cryptopro/ECGOST3410NamedCurves.java b/core/src/main/java/org/spongycastle/asn1/cryptopro/ECGOST3410NamedCurves.java
new file mode 100644
index 00000000..db64c138
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cryptopro/ECGOST3410NamedCurves.java
@@ -0,0 +1,177 @@
+package org.spongycastle.asn1.cryptopro;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.math.ec.ECConstants;
+import org.spongycastle.math.ec.ECCurve;
+
+/**
+ * table of the available named parameters for GOST 3410-2001.
+ */
+public class ECGOST3410NamedCurves
+{
+ static final Hashtable objIds = new Hashtable();
+ static final Hashtable params = new Hashtable();
+ static final Hashtable names = new Hashtable();
+
+ static
+ {
+ 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
+ new BigInteger("166"), // b
+ mod_q,
+ ECConstants.ONE);
+
+ ECDomainParameters ecParams = new ECDomainParameters(
+ curve,
+ 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_q,
+ ECConstants.ONE);
+
+ ecParams = new ECDomainParameters(
+ 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
+ new BigInteger("28091019353058090096996979000309560759124368558014865957655842872397301267595"), // b
+ mod_q,
+ ECConstants.ONE);
+
+ ecParams = new ECDomainParameters(
+ curve,
+ 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_q,
+ ECConstants.ONE);
+
+ ecParams = new ECDomainParameters(
+ 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(
+ mod_p, // p
+ new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502616"), // a
+ new BigInteger("32858"), // b
+ mod_q,
+ ECConstants.ONE);
+
+ ecParams = new ECDomainParameters(
+ curve,
+ 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");
+ names.put(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_XchA, "GostR3410-2001-CryptoPro-XchA");
+ names.put(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_XchB, "GostR3410-2001-CryptoPro-XchB");
+ }
+
+ /**
+ * return the ECDomainParameters object for the given OID, null if it
+ * isn't present.
+ *
+ * @param oid an object identifier representing a named parameters, if present.
+ */
+ public static ECDomainParameters getByOID(
+ ASN1ObjectIdentifier oid)
+ {
+ return (ECDomainParameters)params.get(oid);
+ }
+
+ /**
+ * returns an enumeration containing the name strings for parameters
+ * contained in this structure.
+ */
+ public static Enumeration getNames()
+ {
+ return objIds.keys();
+ }
+
+ public static ECDomainParameters getByName(
+ String name)
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)objIds.get(name);
+
+ if (oid != null)
+ {
+ return (ECDomainParameters)params.get(oid);
+ }
+
+ return null;
+ }
+
+ /**
+ * return the named curve name represented by the given object identifier.
+ */
+ public static String getName(
+ ASN1ObjectIdentifier oid)
+ {
+ return (String)names.get(oid);
+ }
+
+ public static ASN1ObjectIdentifier getOID(String name)
+ {
+ return (ASN1ObjectIdentifier)objIds.get(name);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cryptopro/ECGOST3410ParamSetParameters.java b/core/src/main/java/org/spongycastle/asn1/cryptopro/ECGOST3410ParamSetParameters.java
new file mode 100644
index 00000000..3cd676c1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cryptopro/ECGOST3410ParamSetParameters.java
@@ -0,0 +1,99 @@
+package org.spongycastle.asn1.cryptopro;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+
+public class ECGOST3410ParamSetParameters
+ extends ASN1Object
+{
+ ASN1Integer p, q, a, b, x, y;
+
+ public static ECGOST3410ParamSetParameters getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static ECGOST3410ParamSetParameters getInstance(
+ Object obj)
+ {
+ if(obj == null || obj instanceof ECGOST3410ParamSetParameters)
+ {
+ return (ECGOST3410ParamSetParameters)obj;
+ }
+
+ if(obj instanceof ASN1Sequence)
+ {
+ return new ECGOST3410ParamSetParameters((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid GOST3410Parameter: " + obj.getClass().getName());
+ }
+
+ public ECGOST3410ParamSetParameters(
+ BigInteger a,
+ BigInteger b,
+ BigInteger p,
+ BigInteger q,
+ int x,
+ BigInteger y)
+ {
+ this.a = new ASN1Integer(a);
+ this.b = new ASN1Integer(b);
+ this.p = new ASN1Integer(p);
+ this.q = new ASN1Integer(q);
+ this.x = new ASN1Integer(x);
+ this.y = new ASN1Integer(y);
+ }
+
+ public ECGOST3410ParamSetParameters(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ a = (ASN1Integer)e.nextElement();
+ b = (ASN1Integer)e.nextElement();
+ p = (ASN1Integer)e.nextElement();
+ q = (ASN1Integer)e.nextElement();
+ x = (ASN1Integer)e.nextElement();
+ y = (ASN1Integer)e.nextElement();
+ }
+
+ public BigInteger getP()
+ {
+ return p.getPositiveValue();
+ }
+
+ public BigInteger getQ()
+ {
+ return q.getPositiveValue();
+ }
+
+ public BigInteger getA()
+ {
+ return a.getPositiveValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(a);
+ v.add(b);
+ v.add(p);
+ v.add(q);
+ v.add(x);
+ v.add(y);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cryptopro/GOST28147Parameters.java b/core/src/main/java/org/spongycastle/asn1/cryptopro/GOST28147Parameters.java
new file mode 100644
index 00000000..7db9e235
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cryptopro/GOST28147Parameters.java
@@ -0,0 +1,98 @@
+package org.spongycastle.asn1.cryptopro;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * ASN.1 algorithm identifier parameters for GOST-28147
+ */
+public class GOST28147Parameters
+ extends ASN1Object
+{
+ private ASN1OctetString iv;
+ private ASN1ObjectIdentifier paramSet;
+
+ public static GOST28147Parameters getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static GOST28147Parameters getInstance(
+ Object obj)
+ {
+ if (obj instanceof GOST28147Parameters)
+ {
+ return (GOST28147Parameters)obj;
+ }
+
+ if (obj != null)
+ {
+ return new GOST28147Parameters(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * @deprecated use the getInstance() method. This constructor will vanish!
+ */
+ public GOST28147Parameters(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ iv = (ASN1OctetString)e.nextElement();
+ paramSet = (ASN1ObjectIdentifier)e.nextElement();
+ }
+
+ /**
+ * <pre>
+ * Gost28147-89-Parameters ::=
+ * SEQUENCE {
+ * iv Gost28147-89-IV,
+ * encryptionParamSet OBJECT IDENTIFIER
+ * }
+ *
+ * Gost28147-89-IV ::= OCTET STRING (SIZE (8))
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(iv);
+ v.add(paramSet);
+
+ 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/core/src/main/java/org/spongycastle/asn1/cryptopro/GOST3410NamedParameters.java b/core/src/main/java/org/spongycastle/asn1/cryptopro/GOST3410NamedParameters.java
new file mode 100644
index 00000000..f6c6f3ca
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cryptopro/GOST3410NamedParameters.java
@@ -0,0 +1,116 @@
+package org.spongycastle.asn1.cryptopro;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+
+/**
+ * table of the available named parameters for GOST 3410-94.
+ */
+public class GOST3410NamedParameters
+{
+ static final Hashtable objIds = new Hashtable();
+ static final Hashtable params = new Hashtable();
+ static final Hashtable names = new Hashtable();
+
+ static private GOST3410ParamSetParameters cryptoProA = new GOST3410ParamSetParameters(
+ 1024,
+ new BigInteger("127021248288932417465907042777176443525787653508916535812817507265705031260985098497423188333483401180925999995120988934130659205614996724254121049274349357074920312769561451689224110579311248812610229678534638401693520013288995000362260684222750813532307004517341633685004541062586971416883686778842537820383"),
+ new BigInteger("68363196144955700784444165611827252895102170888761442055095051287550314083023"),
+ new BigInteger("100997906755055304772081815535925224869841082572053457874823515875577147990529272777244152852699298796483356699682842027972896052747173175480590485607134746852141928680912561502802222185647539190902656116367847270145019066794290930185446216399730872221732889830323194097355403213400972588322876850946740663962")
+// validationAlgorithm {
+// algorithm
+// id-GostR3410-94-bBis,
+// parameters
+// GostR3410-94-ValidationBisParameters: {
+// x0 1376285941,
+// c 3996757427
+// }
+// }
+
+ );
+
+ static private GOST3410ParamSetParameters cryptoProB = new GOST3410ParamSetParameters(
+ 1024,
+ new BigInteger("139454871199115825601409655107690713107041707059928031797758001454375765357722984094124368522288239833039114681648076688236921220737322672160740747771700911134550432053804647694904686120113087816240740184800477047157336662926249423571248823968542221753660143391485680840520336859458494803187341288580489525163"),
+ new BigInteger("79885141663410976897627118935756323747307951916507639758300472692338873533959"),
+ new BigInteger("42941826148615804143873447737955502392672345968607143066798112994089471231420027060385216699563848719957657284814898909770759462613437669456364882730370838934791080835932647976778601915343474400961034231316672578686920482194932878633360203384797092684342247621055760235016132614780652761028509445403338652341")
+// validationAlgorithm {
+// algorithm
+// id-GostR3410-94-bBis,
+// parameters
+// GostR3410-94-ValidationBisParameters: {
+// x0 1536654555,
+// c 1855361757,
+// d 14408629386140014567655
+//4902939282056547857802241461782996702017713059974755104394739915140
+//6115284791024439062735788342744854120601660303926203867703556828005
+//8957203818114895398976594425537561271800850306
+// }
+// }
+//}
+ );
+
+ static private GOST3410ParamSetParameters cryptoProXchA = new GOST3410ParamSetParameters(
+ 1024,
+ new BigInteger("142011741597563481196368286022318089743276138395243738762872573441927459393512718973631166078467600360848946623567625795282774719212241929071046134208380636394084512691828894000571524625445295769349356752728956831541775441763139384457191755096847107846595662547942312293338483924514339614727760681880609734239"),
+ new BigInteger("91771529896554605945588149018382750217296858393520724172743325725474374979801"),
+ new BigInteger("133531813272720673433859519948319001217942375967847486899482359599369642528734712461590403327731821410328012529253871914788598993103310567744136196364803064721377826656898686468463277710150809401182608770201615324990468332931294920912776241137878030224355746606283971659376426832674269780880061631528163475887")
+ );
+
+ static
+ {
+ params.put(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_A, cryptoProA);
+ params.put(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_B, cryptoProB);
+// params.put(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_C, cryptoProC);
+// params.put(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_D, cryptoProD);
+ params.put(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_XchA, cryptoProXchA);
+// params.put(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_XchB, cryptoProXchA);
+// params.put(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_XchC, cryptoProXchA);
+
+ objIds.put("GostR3410-94-CryptoPro-A", CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_A);
+ objIds.put("GostR3410-94-CryptoPro-B", CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_B);
+ objIds.put("GostR3410-94-CryptoPro-XchA", CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_XchA);
+ }
+
+ /**
+ * return the GOST3410ParamSetParameters object for the given OID, null if it
+ * isn't present.
+ *
+ * @param oid an object identifier representing a named parameters, if present.
+ */
+ public static GOST3410ParamSetParameters getByOID(
+ ASN1ObjectIdentifier oid)
+ {
+ return (GOST3410ParamSetParameters)params.get(oid);
+ }
+
+ /**
+ * returns an enumeration containing the name strings for parameters
+ * contained in this structure.
+ */
+ public static Enumeration getNames()
+ {
+ return objIds.keys();
+ }
+
+ public static GOST3410ParamSetParameters getByName(
+ String name)
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)objIds.get(name);
+
+ if (oid != null)
+ {
+ return (GOST3410ParamSetParameters)params.get(oid);
+ }
+
+ return null;
+ }
+
+ public static ASN1ObjectIdentifier getOID(String name)
+ {
+ return (ASN1ObjectIdentifier)objIds.get(name);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cryptopro/GOST3410ParamSetParameters.java b/core/src/main/java/org/spongycastle/asn1/cryptopro/GOST3410ParamSetParameters.java
new file mode 100644
index 00000000..783bb687
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cryptopro/GOST3410ParamSetParameters.java
@@ -0,0 +1,105 @@
+package org.spongycastle.asn1.cryptopro;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+
+public class GOST3410ParamSetParameters
+ extends ASN1Object
+{
+ int keySize;
+ ASN1Integer p, q, a;
+
+ public static GOST3410ParamSetParameters getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static GOST3410ParamSetParameters getInstance(
+ Object obj)
+ {
+ if(obj == null || obj instanceof GOST3410ParamSetParameters)
+ {
+ return (GOST3410ParamSetParameters)obj;
+ }
+
+ if(obj instanceof ASN1Sequence)
+ {
+ return new GOST3410ParamSetParameters((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid GOST3410Parameter: " + obj.getClass().getName());
+ }
+
+ public GOST3410ParamSetParameters(
+ int keySize,
+ BigInteger p,
+ BigInteger q,
+ BigInteger a)
+ {
+ this.keySize = keySize;
+ this.p = new ASN1Integer(p);
+ this.q = new ASN1Integer(q);
+ this.a = new ASN1Integer(a);
+ }
+
+ public GOST3410ParamSetParameters(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ keySize = ((ASN1Integer)e.nextElement()).getValue().intValue();
+ p = (ASN1Integer)e.nextElement();
+ q = (ASN1Integer)e.nextElement();
+ a = (ASN1Integer)e.nextElement();
+ }
+
+ /**
+ * @deprecated use getKeySize
+ */
+ public int getLKeySize()
+ {
+ return keySize;
+ }
+
+ public int getKeySize()
+ {
+ return keySize;
+ }
+
+ public BigInteger getP()
+ {
+ return p.getPositiveValue();
+ }
+
+ public BigInteger getQ()
+ {
+ return q.getPositiveValue();
+ }
+
+ public BigInteger getA()
+ {
+ return a.getPositiveValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(keySize));
+ v.add(p);
+ v.add(q);
+ v.add(a);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/cryptopro/GOST3410PublicKeyAlgParameters.java b/core/src/main/java/org/spongycastle/asn1/cryptopro/GOST3410PublicKeyAlgParameters.java
new file mode 100644
index 00000000..d17ac1e2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/cryptopro/GOST3410PublicKeyAlgParameters.java
@@ -0,0 +1,104 @@
+package org.spongycastle.asn1.cryptopro;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+
+public class GOST3410PublicKeyAlgParameters
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier publicKeyParamSet;
+ private ASN1ObjectIdentifier digestParamSet;
+ private ASN1ObjectIdentifier encryptionParamSet;
+
+ public static GOST3410PublicKeyAlgParameters getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static GOST3410PublicKeyAlgParameters getInstance(
+ Object obj)
+ {
+ if (obj instanceof GOST3410PublicKeyAlgParameters)
+ {
+ return (GOST3410PublicKeyAlgParameters)obj;
+ }
+
+ if(obj != null)
+ {
+ return new GOST3410PublicKeyAlgParameters(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public GOST3410PublicKeyAlgParameters(
+ ASN1ObjectIdentifier publicKeyParamSet,
+ ASN1ObjectIdentifier digestParamSet)
+ {
+ this.publicKeyParamSet = publicKeyParamSet;
+ this.digestParamSet = digestParamSet;
+ this.encryptionParamSet = null;
+ }
+
+ public GOST3410PublicKeyAlgParameters(
+ ASN1ObjectIdentifier publicKeyParamSet,
+ ASN1ObjectIdentifier digestParamSet,
+ ASN1ObjectIdentifier encryptionParamSet)
+ {
+ this.publicKeyParamSet = publicKeyParamSet;
+ this.digestParamSet = digestParamSet;
+ this.encryptionParamSet = encryptionParamSet;
+ }
+
+ /**
+ * @deprecated use getInstance()
+ */
+ public GOST3410PublicKeyAlgParameters(
+ ASN1Sequence seq)
+ {
+ this.publicKeyParamSet = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ this.digestParamSet = (ASN1ObjectIdentifier)seq.getObjectAt(1);
+
+ if (seq.size() > 2)
+ {
+ this.encryptionParamSet = (ASN1ObjectIdentifier)seq.getObjectAt(2);
+ }
+ }
+
+ public ASN1ObjectIdentifier getPublicKeyParamSet()
+ {
+ return publicKeyParamSet;
+ }
+
+ public ASN1ObjectIdentifier getDigestParamSet()
+ {
+ return digestParamSet;
+ }
+
+ public ASN1ObjectIdentifier getEncryptionParamSet()
+ {
+ return encryptionParamSet;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(publicKeyParamSet);
+ v.add(digestParamSet);
+
+ if (encryptionParamSet != null)
+ {
+ v.add(encryptionParamSet);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/dvcs/CertEtcToken.java b/core/src/main/java/org/spongycastle/asn1/dvcs/CertEtcToken.java
new file mode 100644
index 00000000..7774ade8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/dvcs/CertEtcToken.java
@@ -0,0 +1,171 @@
+package org.spongycastle.asn1.dvcs;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.cmp.PKIStatusInfo;
+import org.spongycastle.asn1.cms.ContentInfo;
+import org.spongycastle.asn1.ess.ESSCertID;
+import org.spongycastle.asn1.ocsp.CertID;
+import org.spongycastle.asn1.ocsp.CertStatus;
+import org.spongycastle.asn1.ocsp.OCSPResponse;
+import org.spongycastle.asn1.smime.SMIMECapabilities;
+import org.spongycastle.asn1.x509.Certificate;
+import org.spongycastle.asn1.x509.CertificateList;
+import org.spongycastle.asn1.x509.Extension;
+
+/**
+ * <pre>
+ * CertEtcToken ::= CHOICE {
+ * certificate [0] IMPLICIT Certificate ,
+ * esscertid [1] ESSCertId ,
+ * pkistatus [2] IMPLICIT PKIStatusInfo ,
+ * assertion [3] ContentInfo ,
+ * crl [4] IMPLICIT CertificateList,
+ * ocspcertstatus [5] CertStatus,
+ * oscpcertid [6] IMPLICIT CertId ,
+ * oscpresponse [7] IMPLICIT OCSPResponse,
+ * capabilities [8] SMIMECapabilities,
+ * extension Extension
+ * }
+ * </pre>
+ */
+public class CertEtcToken
+ extends ASN1Object
+ implements ASN1Choice
+{
+ public static final int TAG_CERTIFICATE = 0;
+ public static final int TAG_ESSCERTID = 1;
+ public static final int TAG_PKISTATUS = 2;
+ public static final int TAG_ASSERTION = 3;
+ public static final int TAG_CRL = 4;
+ public static final int TAG_OCSPCERTSTATUS = 5;
+ public static final int TAG_OCSPCERTID = 6;
+ public static final int TAG_OCSPRESPONSE = 7;
+ public static final int TAG_CAPABILITIES = 8;
+
+ private static final boolean[] explicit = new boolean[]
+ {
+ false, true, false, true, false, true, false, false, true
+ };
+
+ private int tagNo;
+ private ASN1Encodable value;
+ private Extension extension;
+
+ public CertEtcToken(int tagNo, ASN1Encodable value)
+ {
+ this.tagNo = tagNo;
+ this.value = value;
+ }
+
+ public CertEtcToken(Extension extension)
+ {
+ this.tagNo = -1;
+ this.extension = extension;
+ }
+
+ private CertEtcToken(ASN1TaggedObject choice)
+ {
+ this.tagNo = choice.getTagNo();
+
+ switch (tagNo)
+ {
+ case TAG_CERTIFICATE:
+ value = Certificate.getInstance(choice, false);
+ break;
+ case TAG_ESSCERTID:
+ value = ESSCertID.getInstance(choice.getObject());
+ break;
+ case TAG_PKISTATUS:
+ value = PKIStatusInfo.getInstance(choice, false);
+ break;
+ case TAG_ASSERTION:
+ value = ContentInfo.getInstance(choice.getObject());
+ break;
+ case TAG_CRL:
+ value = CertificateList.getInstance(choice, false);
+ break;
+ case TAG_OCSPCERTSTATUS:
+ value = CertStatus.getInstance(choice.getObject());
+ break;
+ case TAG_OCSPCERTID:
+ value = CertID.getInstance(choice, false);
+ break;
+ case TAG_OCSPRESPONSE:
+ value = OCSPResponse.getInstance(choice, false);
+ break;
+ case TAG_CAPABILITIES:
+ value = SMIMECapabilities.getInstance(choice.getObject());
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown tag: " + tagNo);
+ }
+ }
+
+ public static CertEtcToken getInstance(Object obj)
+ {
+ if (obj instanceof CertEtcToken)
+ {
+ return (CertEtcToken)obj;
+ }
+ else if (obj instanceof ASN1TaggedObject)
+ {
+ return new CertEtcToken((ASN1TaggedObject)obj);
+ }
+ else if (obj != null)
+ {
+ return new CertEtcToken(Extension.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (extension == null)
+ {
+ return new DERTaggedObject(explicit[tagNo], tagNo, value);
+ }
+ else
+ {
+ return extension.toASN1Primitive();
+ }
+ }
+
+ public int getTagNo()
+ {
+ return tagNo;
+ }
+
+ public ASN1Encodable getValue()
+ {
+ return value;
+ }
+
+ public Extension getExtension()
+ {
+ return extension;
+ }
+
+ public String toString()
+ {
+ return "CertEtcToken {\n" + value + "}\n";
+ }
+
+ public static CertEtcToken[] arrayFromSequence(ASN1Sequence seq)
+ {
+ CertEtcToken[] tmp = new CertEtcToken[seq.size()];
+
+ for (int i = 0; i != tmp.length; i++)
+ {
+ tmp[i] = CertEtcToken.getInstance(seq.getObjectAt(i));
+ }
+
+ return tmp;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSCertInfo.java b/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSCertInfo.java
new file mode 100644
index 00000000..3c231b44
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSCertInfo.java
@@ -0,0 +1,302 @@
+package org.spongycastle.asn1.dvcs;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.cmp.PKIStatusInfo;
+import org.spongycastle.asn1.x509.DigestInfo;
+import org.spongycastle.asn1.x509.Extensions;
+import org.spongycastle.asn1.x509.PolicyInformation;
+
+/**
+ * <pre>
+ * DVCSCertInfo::= SEQUENCE {
+ * version Integer DEFAULT 1 ,
+ * dvReqInfo DVCSRequestInformation,
+ * messageImprint DigestInfo,
+ * serialNumber Integer,
+ * responseTime DVCSTime,
+ * dvStatus [0] PKIStatusInfo OPTIONAL,
+ * policy [1] PolicyInformation OPTIONAL,
+ * reqSignature [2] SignerInfos OPTIONAL,
+ * certs [3] SEQUENCE SIZE (1..MAX) OF
+ * TargetEtcChain OPTIONAL,
+ * extensions Extensions OPTIONAL
+ * }
+ * </pre>
+ */
+
+public class DVCSCertInfo
+ extends ASN1Object
+{
+
+ private int version = DEFAULT_VERSION;
+ private DVCSRequestInformation dvReqInfo;
+ private DigestInfo messageImprint;
+ private ASN1Integer serialNumber;
+ private DVCSTime responseTime;
+ private PKIStatusInfo dvStatus;
+ private PolicyInformation policy;
+ private ASN1Set reqSignature;
+ private ASN1Sequence certs;
+ private Extensions extensions;
+
+ private static final int DEFAULT_VERSION = 1;
+ private static final int TAG_DV_STATUS = 0;
+ private static final int TAG_POLICY = 1;
+ private static final int TAG_REQ_SIGNATURE = 2;
+ private static final int TAG_CERTS = 3;
+
+ public DVCSCertInfo(
+ DVCSRequestInformation dvReqInfo,
+ DigestInfo messageImprint,
+ ASN1Integer serialNumber,
+ DVCSTime responseTime)
+ {
+ this.dvReqInfo = dvReqInfo;
+ this.messageImprint = messageImprint;
+ this.serialNumber = serialNumber;
+ this.responseTime = responseTime;
+ }
+
+ private DVCSCertInfo(ASN1Sequence seq)
+ {
+ int i = 0;
+ ASN1Encodable x = seq.getObjectAt(i++);
+ try
+ {
+ ASN1Integer encVersion = ASN1Integer.getInstance(x);
+ this.version = encVersion.getValue().intValue();
+ x = seq.getObjectAt(i++);
+ }
+ catch (IllegalArgumentException e)
+ {
+ }
+
+ this.dvReqInfo = DVCSRequestInformation.getInstance(x);
+ x = seq.getObjectAt(i++);
+ this.messageImprint = DigestInfo.getInstance(x);
+ x = seq.getObjectAt(i++);
+ this.serialNumber = ASN1Integer.getInstance(x);
+ x = seq.getObjectAt(i++);
+ this.responseTime = DVCSTime.getInstance(x);
+
+ while (i < seq.size())
+ {
+
+ x = seq.getObjectAt(i++);
+
+ try
+ {
+ ASN1TaggedObject t = ASN1TaggedObject.getInstance(x);
+ int tagNo = t.getTagNo();
+
+ switch (tagNo)
+ {
+ case TAG_DV_STATUS:
+ this.dvStatus = PKIStatusInfo.getInstance(t, false);
+ break;
+ case TAG_POLICY:
+ this.policy = PolicyInformation.getInstance(ASN1Sequence.getInstance(t, false));
+ break;
+ case TAG_REQ_SIGNATURE:
+ this.reqSignature = ASN1Set.getInstance(t, false);
+ break;
+ case TAG_CERTS:
+ this.certs = ASN1Sequence.getInstance(t, false);
+ break;
+ }
+
+ continue;
+
+ }
+ catch (IllegalArgumentException e)
+ {
+ }
+
+ try
+ {
+ this.extensions = Extensions.getInstance(x);
+ }
+ catch (IllegalArgumentException e)
+ {
+ }
+
+ }
+
+ }
+
+ public static DVCSCertInfo getInstance(Object obj)
+ {
+ if (obj instanceof DVCSCertInfo)
+ {
+ return (DVCSCertInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new DVCSCertInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static DVCSCertInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (version != DEFAULT_VERSION)
+ {
+ v.add(new ASN1Integer(version));
+ }
+ v.add(dvReqInfo);
+ v.add(messageImprint);
+ v.add(serialNumber);
+ v.add(responseTime);
+ if (dvStatus != null)
+ {
+ v.add(new DERTaggedObject(false, TAG_DV_STATUS, dvStatus));
+ }
+ if (policy != null)
+ {
+ v.add(new DERTaggedObject(false, TAG_POLICY, policy));
+ }
+ if (reqSignature != null)
+ {
+ v.add(new DERTaggedObject(false, TAG_REQ_SIGNATURE, reqSignature));
+ }
+ if (certs != null)
+ {
+ v.add(new DERTaggedObject(false, TAG_CERTS, certs));
+ }
+ if (extensions != null)
+ {
+ v.add(extensions);
+ }
+
+ return new DERSequence(v);
+ }
+
+ public String toString()
+ {
+ StringBuffer s = new StringBuffer();
+
+ s.append("DVCSCertInfo {\n");
+
+ if (version != DEFAULT_VERSION)
+ {
+ s.append("version: " + version + "\n");
+ }
+ s.append("dvReqInfo: " + dvReqInfo + "\n");
+ s.append("messageImprint: " + messageImprint + "\n");
+ s.append("serialNumber: " + serialNumber + "\n");
+ s.append("responseTime: " + responseTime + "\n");
+ if (dvStatus != null)
+ {
+ s.append("dvStatus: " + dvStatus + "\n");
+ }
+ if (policy != null)
+ {
+ s.append("policy: " + policy + "\n");
+ }
+ if (reqSignature != null)
+ {
+ s.append("reqSignature: " + reqSignature + "\n");
+ }
+ if (certs != null)
+ {
+ s.append("certs: " + certs + "\n");
+ }
+ if (extensions != null)
+ {
+ s.append("extensions: " + extensions + "\n");
+ }
+
+ s.append("}\n");
+ return s.toString();
+ }
+
+ public int getVersion()
+ {
+ return version;
+ }
+
+ private void setVersion(int version)
+ {
+ this.version = version;
+ }
+
+ public DVCSRequestInformation getDvReqInfo()
+ {
+ return dvReqInfo;
+ }
+
+ private void setDvReqInfo(DVCSRequestInformation dvReqInfo)
+ {
+ this.dvReqInfo = dvReqInfo;
+ }
+
+ public DigestInfo getMessageImprint()
+ {
+ return messageImprint;
+ }
+
+ private void setMessageImprint(DigestInfo messageImprint)
+ {
+ this.messageImprint = messageImprint;
+ }
+
+ public ASN1Integer getSerialNumber()
+ {
+ return serialNumber;
+ }
+
+ public DVCSTime getResponseTime()
+ {
+ return responseTime;
+ }
+
+ public PKIStatusInfo getDvStatus()
+ {
+ return dvStatus;
+ }
+
+ public PolicyInformation getPolicy()
+ {
+ return policy;
+ }
+
+ public ASN1Set getReqSignature()
+ {
+ return reqSignature;
+ }
+
+ public TargetEtcChain[] getCerts()
+ {
+ if (certs != null)
+ {
+ return TargetEtcChain.arrayFromSequence(certs);
+ }
+
+ return null;
+ }
+
+ public Extensions getExtensions()
+ {
+ return extensions;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSCertInfoBuilder.java b/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSCertInfoBuilder.java
new file mode 100644
index 00000000..47ba84e4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSCertInfoBuilder.java
@@ -0,0 +1,151 @@
+package org.spongycastle.asn1.dvcs;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.cmp.PKIStatusInfo;
+import org.spongycastle.asn1.x509.DigestInfo;
+import org.spongycastle.asn1.x509.Extensions;
+import org.spongycastle.asn1.x509.PolicyInformation;
+
+/**
+ * <pre>
+ * DVCSCertInfo::= SEQUENCE {
+ * version Integer DEFAULT 1 ,
+ * dvReqInfo DVCSRequestInformation,
+ * messageImprint DigestInfo,
+ * serialNumber Integer,
+ * responseTime DVCSTime,
+ * dvStatus [0] PKIStatusInfo OPTIONAL,
+ * policy [1] PolicyInformation OPTIONAL,
+ * reqSignature [2] SignerInfos OPTIONAL,
+ * certs [3] SEQUENCE SIZE (1..MAX) OF
+ * TargetEtcChain OPTIONAL,
+ * extensions Extensions OPTIONAL
+ * }
+ * </pre>
+ */
+
+public class DVCSCertInfoBuilder
+{
+
+ private int version = DEFAULT_VERSION;
+ private DVCSRequestInformation dvReqInfo;
+ private DigestInfo messageImprint;
+ private ASN1Integer serialNumber;
+ private DVCSTime responseTime;
+ private PKIStatusInfo dvStatus;
+ private PolicyInformation policy;
+ private ASN1Set reqSignature;
+ private ASN1Sequence certs;
+ private Extensions extensions;
+
+ private static final int DEFAULT_VERSION = 1;
+ private static final int TAG_DV_STATUS = 0;
+ private static final int TAG_POLICY = 1;
+ private static final int TAG_REQ_SIGNATURE = 2;
+ private static final int TAG_CERTS = 3;
+
+ public DVCSCertInfoBuilder(
+ DVCSRequestInformation dvReqInfo,
+ DigestInfo messageImprint,
+ ASN1Integer serialNumber,
+ DVCSTime responseTime)
+ {
+ this.dvReqInfo = dvReqInfo;
+ this.messageImprint = messageImprint;
+ this.serialNumber = serialNumber;
+ this.responseTime = responseTime;
+ }
+
+ public DVCSCertInfo build()
+ {
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (version != DEFAULT_VERSION)
+ {
+ v.add(new ASN1Integer(version));
+ }
+ v.add(dvReqInfo);
+ v.add(messageImprint);
+ v.add(serialNumber);
+ v.add(responseTime);
+ if (dvStatus != null)
+ {
+ v.add(new DERTaggedObject(false, TAG_DV_STATUS, dvStatus));
+ }
+ if (policy != null)
+ {
+ v.add(new DERTaggedObject(false, TAG_POLICY, policy));
+ }
+ if (reqSignature != null)
+ {
+ v.add(new DERTaggedObject(false, TAG_REQ_SIGNATURE, reqSignature));
+ }
+ if (certs != null)
+ {
+ v.add(new DERTaggedObject(false, TAG_CERTS, certs));
+ }
+ if (extensions != null)
+ {
+ v.add(extensions);
+ }
+
+ return DVCSCertInfo.getInstance(new DERSequence(v));
+ }
+
+ public void setVersion(int version)
+ {
+ this.version = version;
+ }
+
+ public void setDvReqInfo(DVCSRequestInformation dvReqInfo)
+ {
+ this.dvReqInfo = dvReqInfo;
+ }
+
+ public void setMessageImprint(DigestInfo messageImprint)
+ {
+ this.messageImprint = messageImprint;
+ }
+
+ public void setSerialNumber(ASN1Integer serialNumber)
+ {
+ this.serialNumber = serialNumber;
+ }
+
+ public void setResponseTime(DVCSTime responseTime)
+ {
+ this.responseTime = responseTime;
+ }
+
+ public void setDvStatus(PKIStatusInfo dvStatus)
+ {
+ this.dvStatus = dvStatus;
+ }
+
+ public void setPolicy(PolicyInformation policy)
+ {
+ this.policy = policy;
+ }
+
+ public void setReqSignature(ASN1Set reqSignature)
+ {
+ this.reqSignature = reqSignature;
+ }
+
+ public void setCerts(TargetEtcChain[] certs)
+ {
+ this.certs = new DERSequence(certs);
+ }
+
+ public void setExtensions(Extensions extensions)
+ {
+ this.extensions = extensions;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSErrorNotice.java b/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSErrorNotice.java
new file mode 100644
index 00000000..2bd13ea9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSErrorNotice.java
@@ -0,0 +1,96 @@
+package org.spongycastle.asn1.dvcs;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.cmp.PKIStatusInfo;
+import org.spongycastle.asn1.x509.GeneralName;
+
+/**
+ * <pre>
+ * DVCSErrorNotice ::= SEQUENCE {
+ * transactionStatus PKIStatusInfo ,
+ * transactionIdentifier GeneralName OPTIONAL
+ * }
+ * </pre>
+ */
+public class DVCSErrorNotice
+ extends ASN1Object
+{
+ private PKIStatusInfo transactionStatus;
+ private GeneralName transactionIdentifier;
+
+ public DVCSErrorNotice(PKIStatusInfo status)
+ {
+ this(status, null);
+ }
+
+ public DVCSErrorNotice(PKIStatusInfo status, GeneralName transactionIdentifier)
+ {
+ this.transactionStatus = status;
+ this.transactionIdentifier = transactionIdentifier;
+ }
+
+ private DVCSErrorNotice(ASN1Sequence seq)
+ {
+ this.transactionStatus = PKIStatusInfo.getInstance(seq.getObjectAt(0));
+ if (seq.size() > 1)
+ {
+ this.transactionIdentifier = GeneralName.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ public static DVCSErrorNotice getInstance(Object obj)
+ {
+ if (obj instanceof DVCSErrorNotice)
+ {
+ return (DVCSErrorNotice)obj;
+ }
+ else if (obj != null)
+ {
+ return new DVCSErrorNotice(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static DVCSErrorNotice getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(transactionStatus);
+ if (transactionIdentifier != null)
+ {
+ v.add(transactionIdentifier);
+ }
+ return new DERSequence(v);
+ }
+
+ public String toString()
+ {
+ return "DVCSErrorNotice {\n" +
+ "transactionStatus: " + transactionStatus + "\n" +
+ (transactionIdentifier != null ? "transactionIdentifier: " + transactionIdentifier + "\n" : "") +
+ "}\n";
+ }
+
+
+ public PKIStatusInfo getTransactionStatus()
+ {
+ return transactionStatus;
+ }
+
+ public GeneralName getTransactionIdentifier()
+ {
+ return transactionIdentifier;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSObjectIdentifiers.java
new file mode 100644
index 00000000..02915089
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSObjectIdentifiers.java
@@ -0,0 +1,29 @@
+package org.spongycastle.asn1.dvcs;
+
+import org.spongycastle.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");
+
+ /** 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");
+
+ /** 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");
+
+ /** 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");
+
+ /** 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/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSRequest.java b/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSRequest.java
new file mode 100644
index 00000000..7be8221c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSRequest.java
@@ -0,0 +1,107 @@
+package org.spongycastle.asn1.dvcs;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.GeneralName;
+
+/**
+ * <pre>
+ * DVCSRequest ::= SEQUENCE {
+ * requestInformation DVCSRequestInformation,
+ * data Data,
+ * transactionIdentifier GeneralName OPTIONAL
+ * }
+ * </pre>
+ */
+
+public class DVCSRequest
+ extends ASN1Object
+{
+
+ private DVCSRequestInformation requestInformation;
+ private Data data;
+ private GeneralName transactionIdentifier;
+
+ public DVCSRequest(DVCSRequestInformation requestInformation, Data data)
+ {
+ this(requestInformation, data, null);
+ }
+
+ public DVCSRequest(DVCSRequestInformation requestInformation, Data data, GeneralName transactionIdentifier)
+ {
+ this.requestInformation = requestInformation;
+ this.data = data;
+ this.transactionIdentifier = transactionIdentifier;
+ }
+
+ private DVCSRequest(ASN1Sequence seq)
+ {
+ requestInformation = DVCSRequestInformation.getInstance(seq.getObjectAt(0));
+ data = Data.getInstance(seq.getObjectAt(1));
+ if (seq.size() > 2)
+ {
+ transactionIdentifier = GeneralName.getInstance(seq.getObjectAt(2));
+ }
+ }
+
+ public static DVCSRequest getInstance(Object obj)
+ {
+ if (obj instanceof DVCSRequest)
+ {
+ return (DVCSRequest)obj;
+ }
+ else if (obj != null)
+ {
+ return new DVCSRequest(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static DVCSRequest getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(requestInformation);
+ v.add(data);
+ if (transactionIdentifier != null)
+ {
+ v.add(transactionIdentifier);
+ }
+ return new DERSequence(v);
+ }
+
+ public String toString()
+ {
+ return "DVCSRequest {\n" +
+ "requestInformation: " + requestInformation + "\n" +
+ "data: " + data + "\n" +
+ (transactionIdentifier != null ? "transactionIdentifier: " + transactionIdentifier + "\n" : "") +
+ "}\n";
+ }
+
+ public Data getData()
+ {
+ return data;
+ }
+
+ public DVCSRequestInformation getRequestInformation()
+ {
+ return requestInformation;
+ }
+
+ public GeneralName getTransactionIdentifier()
+ {
+ return transactionIdentifier;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSRequestInformation.java b/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSRequestInformation.java
new file mode 100644
index 00000000..374df9db
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSRequestInformation.java
@@ -0,0 +1,271 @@
+package org.spongycastle.asn1.dvcs;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.Extensions;
+import org.spongycastle.asn1.x509.GeneralNames;
+import org.spongycastle.asn1.x509.PolicyInformation;
+
+/**
+ * <pre>
+ * DVCSRequestInformation ::= SEQUENCE {
+ * version INTEGER DEFAULT 1 ,
+ * service ServiceType,
+ * nonce Nonce OPTIONAL,
+ * requestTime DVCSTime OPTIONAL,
+ * requester [0] GeneralNames OPTIONAL,
+ * requestPolicy [1] PolicyInformation OPTIONAL,
+ * dvcs [2] GeneralNames OPTIONAL,
+ * dataLocations [3] GeneralNames OPTIONAL,
+ * extensions [4] IMPLICIT Extensions OPTIONAL
+ * }
+ * </pre>
+ */
+
+public class DVCSRequestInformation
+ extends ASN1Object
+{
+ private int version = DEFAULT_VERSION;
+ private ServiceType service;
+ private BigInteger nonce;
+ private DVCSTime requestTime;
+ private GeneralNames requester;
+ private PolicyInformation requestPolicy;
+ private GeneralNames dvcs;
+ private GeneralNames dataLocations;
+ private Extensions extensions;
+
+ private static final int DEFAULT_VERSION = 1;
+ private static final int TAG_REQUESTER = 0;
+ private static final int TAG_REQUEST_POLICY = 1;
+ private static final int TAG_DVCS = 2;
+ private static final int TAG_DATA_LOCATIONS = 3;
+ private static final int TAG_EXTENSIONS = 4;
+
+ private DVCSRequestInformation(ASN1Sequence seq)
+ {
+ int i = 0;
+
+ if (seq.getObjectAt(0) instanceof ASN1Integer)
+ {
+ ASN1Integer encVersion = ASN1Integer.getInstance(seq.getObjectAt(i++));
+ this.version = encVersion.getValue().intValue();
+ }
+ else
+ {
+ this.version = 1;
+ }
+
+ this.service = ServiceType.getInstance(seq.getObjectAt(i++));
+
+ while (i < seq.size())
+ {
+ ASN1Encodable x = seq.getObjectAt(i);
+
+ if (x instanceof ASN1Integer)
+ {
+ this.nonce = ASN1Integer.getInstance(x).getValue();
+ }
+ else if (x instanceof ASN1GeneralizedTime)
+ {
+ this.requestTime = DVCSTime.getInstance(x);
+ }
+ else if (x instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject t = ASN1TaggedObject.getInstance(x);
+ int tagNo = t.getTagNo();
+
+ switch (tagNo)
+ {
+ case TAG_REQUESTER:
+ this.requester = GeneralNames.getInstance(t, false);
+ break;
+ case TAG_REQUEST_POLICY:
+ this.requestPolicy = PolicyInformation.getInstance(ASN1Sequence.getInstance(t, false));
+ break;
+ case TAG_DVCS:
+ this.dvcs = GeneralNames.getInstance(t, false);
+ break;
+ case TAG_DATA_LOCATIONS:
+ this.dataLocations = GeneralNames.getInstance(t, false);
+ break;
+ case TAG_EXTENSIONS:
+ this.extensions = Extensions.getInstance(t, false);
+ break;
+ }
+ }
+ else
+ {
+ this.requestTime = DVCSTime.getInstance(x);
+ }
+
+ i++;
+ }
+ }
+
+ public static DVCSRequestInformation getInstance(Object obj)
+ {
+ if (obj instanceof DVCSRequestInformation)
+ {
+ return (DVCSRequestInformation)obj;
+ }
+ else if (obj != null)
+ {
+ return new DVCSRequestInformation(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static DVCSRequestInformation getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (version != DEFAULT_VERSION)
+ {
+ v.add(new ASN1Integer(version));
+ }
+ v.add(service);
+ if (nonce != null)
+ {
+ v.add(new ASN1Integer(nonce));
+ }
+ if (requestTime != null)
+ {
+ v.add(requestTime);
+ }
+
+ int[] tags = new int[]{
+ TAG_REQUESTER,
+ TAG_REQUEST_POLICY,
+ TAG_DVCS,
+ TAG_DATA_LOCATIONS,
+ TAG_EXTENSIONS
+ };
+ ASN1Encodable[] taggedObjects = new ASN1Encodable[]{
+ requester,
+ requestPolicy,
+ dvcs,
+ dataLocations,
+ extensions
+ };
+ for (int i = 0; i < tags.length; i++)
+ {
+ int tag = tags[i];
+ ASN1Encodable taggedObject = taggedObjects[i];
+ if (taggedObject != null)
+ {
+ v.add(new DERTaggedObject(false, tag, taggedObject));
+ }
+ }
+
+ return new DERSequence(v);
+ }
+
+ public String toString()
+ {
+
+ StringBuffer s = new StringBuffer();
+
+ s.append("DVCSRequestInformation {\n");
+
+ if (version != DEFAULT_VERSION)
+ {
+ s.append("version: " + version + "\n");
+ }
+ s.append("service: " + service + "\n");
+ if (nonce != null)
+ {
+ s.append("nonce: " + nonce + "\n");
+ }
+ if (requestTime != null)
+ {
+ s.append("requestTime: " + requestTime + "\n");
+ }
+ if (requester != null)
+ {
+ s.append("requester: " + requester + "\n");
+ }
+ if (requestPolicy != null)
+ {
+ s.append("requestPolicy: " + requestPolicy + "\n");
+ }
+ if (dvcs != null)
+ {
+ s.append("dvcs: " + dvcs + "\n");
+ }
+ if (dataLocations != null)
+ {
+ s.append("dataLocations: " + dataLocations + "\n");
+ }
+ if (extensions != null)
+ {
+ s.append("extensions: " + extensions + "\n");
+ }
+
+ s.append("}\n");
+ return s.toString();
+ }
+
+ public int getVersion()
+ {
+ return version;
+ }
+
+ public ServiceType getService()
+ {
+ return service;
+ }
+
+ public BigInteger getNonce()
+ {
+ return nonce;
+ }
+
+ public DVCSTime getRequestTime()
+ {
+ return requestTime;
+ }
+
+ public GeneralNames getRequester()
+ {
+ return requester;
+ }
+
+ public PolicyInformation getRequestPolicy()
+ {
+ return requestPolicy;
+ }
+
+ public GeneralNames getDVCS()
+ {
+ return dvcs;
+ }
+
+ public GeneralNames getDataLocations()
+ {
+ return dataLocations;
+ }
+
+ public Extensions getExtensions()
+ {
+ return extensions;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSRequestInformationBuilder.java b/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSRequestInformationBuilder.java
new file mode 100644
index 00000000..8815fe37
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSRequestInformationBuilder.java
@@ -0,0 +1,224 @@
+package org.spongycastle.asn1.dvcs;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.Extensions;
+import org.spongycastle.asn1.x509.GeneralName;
+import org.spongycastle.asn1.x509.GeneralNames;
+import org.spongycastle.asn1.x509.PolicyInformation;
+import org.spongycastle.util.BigIntegers;
+
+/**
+ * <pre>
+ * DVCSRequestInformation ::= SEQUENCE {
+ * version INTEGER DEFAULT 1 ,
+ * service ServiceType,
+ * nonce Nonce OPTIONAL,
+ * requestTime DVCSTime OPTIONAL,
+ * requester [0] GeneralNames OPTIONAL,
+ * requestPolicy [1] PolicyInformation OPTIONAL,
+ * dvcs [2] GeneralNames OPTIONAL,
+ * dataLocations [3] GeneralNames OPTIONAL,
+ * extensions [4] IMPLICIT Extensions OPTIONAL
+ * }
+ * </pre>
+ */
+public class DVCSRequestInformationBuilder
+{
+ private int version = DEFAULT_VERSION;
+
+ private final ServiceType service;
+ private DVCSRequestInformation initialInfo;
+
+ private BigInteger nonce;
+ private DVCSTime requestTime;
+ private GeneralNames requester;
+ private PolicyInformation requestPolicy;
+ private GeneralNames dvcs;
+ private GeneralNames dataLocations;
+ private Extensions extensions;
+
+ private static final int DEFAULT_VERSION = 1;
+ private static final int TAG_REQUESTER = 0;
+ private static final int TAG_REQUEST_POLICY = 1;
+ private static final int TAG_DVCS = 2;
+ private static final int TAG_DATA_LOCATIONS = 3;
+ private static final int TAG_EXTENSIONS = 4;
+
+ public DVCSRequestInformationBuilder(ServiceType service)
+ {
+ this.service = service;
+ }
+
+ public DVCSRequestInformationBuilder(DVCSRequestInformation initialInfo)
+ {
+ this.initialInfo = initialInfo;
+ this.service = initialInfo.getService();
+ this.version = initialInfo.getVersion();
+ this.nonce = initialInfo.getNonce();
+ this.requestTime = initialInfo.getRequestTime();
+ this.requestPolicy = initialInfo.getRequestPolicy();
+ this.dvcs = initialInfo.getDVCS();
+ this.dataLocations = initialInfo.getDataLocations();
+ }
+
+ public DVCSRequestInformation build()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (version != DEFAULT_VERSION)
+ {
+ v.add(new ASN1Integer(version));
+ }
+ v.add(service);
+ if (nonce != null)
+ {
+ v.add(new ASN1Integer(nonce));
+ }
+ if (requestTime != null)
+ {
+ v.add(requestTime);
+ }
+
+ int[] tags = new int[]{
+ TAG_REQUESTER,
+ TAG_REQUEST_POLICY,
+ TAG_DVCS,
+ TAG_DATA_LOCATIONS,
+ TAG_EXTENSIONS
+ };
+ ASN1Encodable[] taggedObjects = new ASN1Encodable[]{
+ requester,
+ requestPolicy,
+ dvcs,
+ dataLocations,
+ extensions
+ };
+ for (int i = 0; i < tags.length; i++)
+ {
+ int tag = tags[i];
+ ASN1Encodable taggedObject = taggedObjects[i];
+ if (taggedObject != null)
+ {
+ v.add(new DERTaggedObject(false, tag, taggedObject));
+ }
+ }
+
+ return DVCSRequestInformation.getInstance(new DERSequence(v));
+ }
+
+ public void setVersion(int version)
+ {
+ if (initialInfo != null)
+ {
+ throw new IllegalStateException("cannot change version in existing DVCSRequestInformation");
+ }
+
+ this.version = version;
+ }
+
+ public void setNonce(BigInteger nonce)
+ {
+ // RFC 3029, 9.1: The DVCS MAY modify the fields
+ // 'dvcs', 'requester', 'dataLocations', and 'nonce' of the ReqInfo structure
+
+ // RFC 3029, 9.1: The only modification
+ // allowed to a 'nonce' is the inclusion of a new field if it was not
+ // present, or to concatenate other data to the end (right) of an
+ // existing value.
+ if (initialInfo != null)
+ {
+ if (initialInfo.getNonce() == null)
+ {
+ this.nonce = nonce;
+ }
+ else
+ {
+ byte[] initialBytes = initialInfo.getNonce().toByteArray();
+ byte[] newBytes = BigIntegers.asUnsignedByteArray(nonce);
+ byte[] nonceBytes = new byte[initialBytes.length + newBytes.length];
+
+ System.arraycopy(initialBytes, 0, nonceBytes, 0, initialBytes.length);
+ System.arraycopy(newBytes, 0, nonceBytes, initialBytes.length, newBytes.length);
+
+ this.nonce = new BigInteger(nonceBytes);
+ }
+ }
+
+ this.nonce = nonce;
+ }
+
+ public void setRequestTime(DVCSTime requestTime)
+ {
+ if (initialInfo != null)
+ {
+ throw new IllegalStateException("cannot change request time in existing DVCSRequestInformation");
+ }
+
+ this.requestTime = requestTime;
+ }
+
+ public void setRequester(GeneralName requester)
+ {
+ this.setRequester(new GeneralNames(requester));
+ }
+
+ public void setRequester(GeneralNames requester)
+ {
+ // RFC 3029, 9.1: The DVCS MAY modify the fields
+ // 'dvcs', 'requester', 'dataLocations', and 'nonce' of the ReqInfo structure
+
+ this.requester = requester;
+ }
+
+ public void setRequestPolicy(PolicyInformation requestPolicy)
+ {
+ if (initialInfo != null)
+ {
+ throw new IllegalStateException("cannot change request policy in existing DVCSRequestInformation");
+ }
+
+ this.requestPolicy = requestPolicy;
+ }
+
+ public void setDVCS(GeneralName dvcs)
+ {
+ this.setDVCS(new GeneralNames(dvcs));
+ }
+
+ public void setDVCS(GeneralNames dvcs)
+ {
+ // RFC 3029, 9.1: The DVCS MAY modify the fields
+ // 'dvcs', 'requester', 'dataLocations', and 'nonce' of the ReqInfo structure
+
+ this.dvcs = dvcs;
+ }
+
+ public void setDataLocations(GeneralName dataLocation)
+ {
+ this.setDataLocations(new GeneralNames(dataLocation));
+ }
+
+ public void setDataLocations(GeneralNames dataLocations)
+ {
+ // RFC 3029, 9.1: The DVCS MAY modify the fields
+ // 'dvcs', 'requester', 'dataLocations', and 'nonce' of the ReqInfo structure
+
+ this.dataLocations = dataLocations;
+ }
+
+ public void setExtensions(Extensions extensions)
+ {
+ if (initialInfo != null)
+ {
+ throw new IllegalStateException("cannot change extensions in existing DVCSRequestInformation");
+ }
+
+ this.extensions = extensions;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSResponse.java b/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSResponse.java
new file mode 100644
index 00000000..6100bd30
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSResponse.java
@@ -0,0 +1,117 @@
+package org.spongycastle.asn1.dvcs;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERTaggedObject;
+
+/**
+ * <pre>
+ * DVCSResponse ::= CHOICE
+ * {
+ * dvCertInfo DVCSCertInfo ,
+ * dvErrorNote [0] DVCSErrorNotice
+ * }
+ * </pre>
+ */
+
+public class DVCSResponse
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private DVCSCertInfo dvCertInfo;
+ private DVCSErrorNotice dvErrorNote;
+
+ public DVCSResponse(DVCSCertInfo dvCertInfo)
+ {
+ this.dvCertInfo = dvCertInfo;
+ }
+
+ public DVCSResponse(DVCSErrorNotice dvErrorNote)
+ {
+ this.dvErrorNote = dvErrorNote;
+ }
+
+ public static DVCSResponse getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof DVCSResponse)
+ {
+ return (DVCSResponse)obj;
+ }
+ else
+ {
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return getInstance(ASN1Primitive.fromByteArray((byte[])obj));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("failed to construct sequence from byte[]: " + e.getMessage());
+ }
+ }
+ if (obj instanceof ASN1Sequence)
+ {
+ DVCSCertInfo dvCertInfo = DVCSCertInfo.getInstance(obj);
+
+ return new DVCSResponse(dvCertInfo);
+ }
+ if (obj instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject t = ASN1TaggedObject.getInstance(obj);
+ DVCSErrorNotice dvErrorNote = DVCSErrorNotice.getInstance(t, false);
+
+ return new DVCSResponse(dvErrorNote);
+ }
+ }
+
+ throw new IllegalArgumentException("Couldn't convert from object to DVCSResponse: " + obj.getClass().getName());
+ }
+
+ public static DVCSResponse getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public DVCSCertInfo getCertInfo()
+ {
+ return dvCertInfo;
+ }
+
+ public DVCSErrorNotice getErrorNotice()
+ {
+ return dvErrorNote;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (dvCertInfo != null)
+ {
+ return dvCertInfo.toASN1Primitive();
+ }
+ else
+ {
+ return new DERTaggedObject(0, dvErrorNote);
+ }
+ }
+
+ public String toString()
+ {
+ if (dvCertInfo != null)
+ {
+ return "DVCSResponse {\ndvCertInfo: " + dvCertInfo.toString() + "}\n";
+ }
+ if (dvErrorNote != null)
+ {
+ return "DVCSResponse {\ndvErrorNote: " + dvErrorNote.toString() + "}\n";
+ }
+ return null;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSTime.java b/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSTime.java
new file mode 100644
index 00000000..f8bf2f90
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/dvcs/DVCSTime.java
@@ -0,0 +1,111 @@
+package org.spongycastle.asn1.dvcs;
+
+import java.util.Date;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.cms.ContentInfo;
+
+/**
+ * <pre>
+ * DVCSTime ::= CHOICE {
+ * genTime GeneralizedTime,
+ * timeStampToken ContentInfo
+ * }
+ * </pre>
+ */
+public class DVCSTime
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private ASN1GeneralizedTime genTime;
+ private ContentInfo timeStampToken;
+ private Date time;
+
+ // constructors:
+
+ public DVCSTime(Date time)
+ {
+ this(new ASN1GeneralizedTime(time));
+ }
+
+ public DVCSTime(ASN1GeneralizedTime genTime)
+ {
+ this.genTime = genTime;
+ }
+
+ public DVCSTime(ContentInfo timeStampToken)
+ {
+ this.timeStampToken = timeStampToken;
+ }
+
+ public static DVCSTime getInstance(Object obj)
+ {
+ if (obj instanceof DVCSTime)
+ {
+ return (DVCSTime)obj;
+ }
+ else if (obj instanceof ASN1GeneralizedTime)
+ {
+ return new DVCSTime(ASN1GeneralizedTime.getInstance(obj));
+ }
+ else if (obj != null)
+ {
+ return new DVCSTime(ContentInfo.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static DVCSTime getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject()); // must be explicitly tagged
+ }
+
+
+ // selectors:
+
+ public ASN1GeneralizedTime getGenTime()
+ {
+ return genTime;
+ }
+
+ public ContentInfo getTimeStampToken()
+ {
+ return timeStampToken;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+
+ if (genTime != null)
+ {
+ return genTime;
+ }
+
+ if (timeStampToken != null)
+ {
+ return timeStampToken.toASN1Primitive();
+ }
+
+ return null;
+ }
+
+ public String toString()
+ {
+ if (genTime != null)
+ {
+ return genTime.toString();
+ }
+ if (timeStampToken != null)
+ {
+ return timeStampToken.toString();
+ }
+ return null;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/dvcs/Data.java b/core/src/main/java/org/spongycastle/asn1/dvcs/Data.java
new file mode 100644
index 00000000..8d00f33f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/dvcs/Data.java
@@ -0,0 +1,149 @@
+package org.spongycastle.asn1.dvcs;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.DigestInfo;
+
+/**
+ * <pre>
+ * Data ::= CHOICE {
+ * message OCTET STRING ,
+ * messageImprint DigestInfo,
+ * certs [0] SEQUENCE SIZE (1..MAX) OF
+ * TargetEtcChain
+ * }
+ * </pre>
+ */
+
+public class Data
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private ASN1OctetString message;
+ private DigestInfo messageImprint;
+ private ASN1Sequence certs;
+
+ public Data(byte[] messageBytes)
+ {
+ this.message = new DEROctetString(messageBytes);
+ }
+
+ public Data(ASN1OctetString message)
+ {
+ this.message = message;
+ }
+
+ public Data(DigestInfo messageImprint)
+ {
+ this.messageImprint = messageImprint;
+ }
+
+ public Data(TargetEtcChain cert)
+ {
+ this.certs = new DERSequence(cert);
+ }
+
+ public Data(TargetEtcChain[] certs)
+ {
+ this.certs = new DERSequence(certs);
+ }
+
+ private Data(ASN1Sequence certs)
+ {
+ this.certs = certs;
+ }
+
+ public static Data getInstance(Object obj)
+ {
+ if (obj instanceof Data)
+ {
+ return (Data)obj;
+ }
+ else if (obj instanceof ASN1OctetString)
+ {
+ return new Data((ASN1OctetString)obj);
+ }
+ else if (obj instanceof ASN1Sequence)
+ {
+ return new Data(DigestInfo.getInstance(obj));
+ }
+ else if (obj instanceof ASN1TaggedObject)
+ {
+ return new Data(ASN1Sequence.getInstance((ASN1TaggedObject)obj, false));
+ }
+ throw new IllegalArgumentException("Unknown object submitted to getInstance: " + obj.getClass().getName());
+ }
+
+ public static Data getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject());
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (message != null)
+ {
+ return message.toASN1Primitive();
+ }
+ if (messageImprint != null)
+ {
+ return messageImprint.toASN1Primitive();
+ }
+ else
+ {
+ return new DERTaggedObject(false, 0, certs);
+ }
+ }
+
+ public String toString()
+ {
+ if (message != null)
+ {
+ return "Data {\n" + message + "}\n";
+ }
+ if (messageImprint != null)
+ {
+ return "Data {\n" + messageImprint + "}\n";
+ }
+ else
+ {
+ return "Data {\n" + certs + "}\n";
+ }
+ }
+
+ public ASN1OctetString getMessage()
+ {
+ return message;
+ }
+
+ public DigestInfo getMessageImprint()
+ {
+ return messageImprint;
+ }
+
+ public TargetEtcChain[] getCerts()
+ {
+ if (certs == null)
+ {
+ return null;
+ }
+
+ TargetEtcChain[] tmp = new TargetEtcChain[certs.size()];
+
+ for (int i = 0; i != tmp.length; i++)
+ {
+ tmp[i] = TargetEtcChain.getInstance(certs.getObjectAt(i));
+ }
+
+ return tmp;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/dvcs/PathProcInput.java b/core/src/main/java/org/spongycastle/asn1/dvcs/PathProcInput.java
new file mode 100644
index 00000000..2c5b8875
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/dvcs/PathProcInput.java
@@ -0,0 +1,180 @@
+package org.spongycastle.asn1.dvcs;
+
+import org.spongycastle.asn1.ASN1Boolean;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.PolicyInformation;
+
+/**
+ * <pre>
+ * PathProcInput ::= SEQUENCE {
+ * acceptablePolicySet SEQUENCE SIZE (1..MAX) OF
+ * PolicyInformation,
+ * inhibitPolicyMapping BOOLEAN DEFAULT FALSE,
+ * explicitPolicyReqd [0] BOOLEAN DEFAULT FALSE ,
+ * inhibitAnyPolicy [1] BOOLEAN DEFAULT FALSE
+ * }
+ * </pre>
+ */
+public class PathProcInput
+ extends ASN1Object
+{
+
+ private PolicyInformation[] acceptablePolicySet;
+ private boolean inhibitPolicyMapping = false;
+ private boolean explicitPolicyReqd = false;
+ private boolean inhibitAnyPolicy = false;
+
+ public PathProcInput(PolicyInformation[] acceptablePolicySet)
+ {
+ this.acceptablePolicySet = acceptablePolicySet;
+ }
+
+ public PathProcInput(PolicyInformation[] acceptablePolicySet, boolean inhibitPolicyMapping, boolean explicitPolicyReqd, boolean inhibitAnyPolicy)
+ {
+ this.acceptablePolicySet = acceptablePolicySet;
+ this.inhibitPolicyMapping = inhibitPolicyMapping;
+ this.explicitPolicyReqd = explicitPolicyReqd;
+ this.inhibitAnyPolicy = inhibitAnyPolicy;
+ }
+
+ private static PolicyInformation[] fromSequence(ASN1Sequence seq)
+ {
+ PolicyInformation[] tmp = new PolicyInformation[seq.size()];
+
+ for (int i = 0; i != tmp.length; i++)
+ {
+ tmp[i] = PolicyInformation.getInstance(seq.getObjectAt(i));
+ }
+
+ return tmp;
+ }
+
+ public static PathProcInput getInstance(Object obj)
+ {
+ if (obj instanceof PathProcInput)
+ {
+ return (PathProcInput)obj;
+ }
+ else if (obj != null)
+ {
+ ASN1Sequence seq = ASN1Sequence.getInstance(obj);
+ ASN1Sequence policies = ASN1Sequence.getInstance(seq.getObjectAt(0));
+ PathProcInput result = new PathProcInput(fromSequence(policies));
+
+ for (int i = 1; i < seq.size(); i++)
+ {
+ Object o = seq.getObjectAt(i);
+
+ if (o instanceof ASN1Boolean)
+ {
+ ASN1Boolean x = ASN1Boolean.getInstance(o);
+ result.setInhibitPolicyMapping(x.isTrue());
+ }
+ else if (o instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject t = ASN1TaggedObject.getInstance(o);
+ ASN1Boolean x;
+ switch (t.getTagNo())
+ {
+ case 0:
+ x = ASN1Boolean.getInstance(t, false);
+ result.setExplicitPolicyReqd(x.isTrue());
+ break;
+ case 1:
+ x = ASN1Boolean.getInstance(t, false);
+ result.setInhibitAnyPolicy(x.isTrue());
+ }
+ }
+ }
+ return result;
+ }
+
+ return null;
+ }
+
+ public static PathProcInput getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ ASN1EncodableVector pV = new ASN1EncodableVector();
+
+ for (int i = 0; i != acceptablePolicySet.length; i++)
+ {
+ pV.add(acceptablePolicySet[i]);
+ }
+
+ v.add(new DERSequence(pV));
+
+ if (inhibitPolicyMapping)
+ {
+ v.add(new ASN1Boolean(inhibitPolicyMapping));
+ }
+ if (explicitPolicyReqd)
+ {
+ v.add(new DERTaggedObject(false, 0, new ASN1Boolean(explicitPolicyReqd)));
+ }
+ if (inhibitAnyPolicy)
+ {
+ v.add(new DERTaggedObject(false, 1, new ASN1Boolean(inhibitAnyPolicy)));
+ }
+
+ return new DERSequence(v);
+ }
+
+ public String toString()
+ {
+ return "PathProcInput: {\n" +
+ "acceptablePolicySet: " + acceptablePolicySet + "\n" +
+ "inhibitPolicyMapping: " + inhibitPolicyMapping + "\n" +
+ "explicitPolicyReqd: " + explicitPolicyReqd + "\n" +
+ "inhibitAnyPolicy: " + inhibitAnyPolicy + "\n" +
+ "}\n";
+ }
+
+ public PolicyInformation[] getAcceptablePolicySet()
+ {
+ return acceptablePolicySet;
+ }
+
+ public boolean isInhibitPolicyMapping()
+ {
+ return inhibitPolicyMapping;
+ }
+
+ private void setInhibitPolicyMapping(boolean inhibitPolicyMapping)
+ {
+ this.inhibitPolicyMapping = inhibitPolicyMapping;
+ }
+
+ public boolean isExplicitPolicyReqd()
+ {
+ return explicitPolicyReqd;
+ }
+
+ private void setExplicitPolicyReqd(boolean explicitPolicyReqd)
+ {
+ this.explicitPolicyReqd = explicitPolicyReqd;
+ }
+
+ public boolean isInhibitAnyPolicy()
+ {
+ return inhibitAnyPolicy;
+ }
+
+ private void setInhibitAnyPolicy(boolean inhibitAnyPolicy)
+ {
+ this.inhibitAnyPolicy = inhibitAnyPolicy;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/dvcs/ServiceType.java b/core/src/main/java/org/spongycastle/asn1/dvcs/ServiceType.java
new file mode 100644
index 00000000..0cc4acc1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/dvcs/ServiceType.java
@@ -0,0 +1,92 @@
+package org.spongycastle.asn1.dvcs;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1Enumerated;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+
+
+/**
+ * ServiceType ::= ENUMERATED { cpd(1), vsd(2), cpkc(3), ccpd(4) }
+ */
+
+public class ServiceType
+ extends ASN1Object
+{
+ /**
+ * Identifier of CPD service (Certify Possession of Data).
+ */
+ public static final ServiceType CPD = new ServiceType(1);
+
+ /**
+ * Identifier of VSD service (Verify Signed Document).
+ */
+ public static final ServiceType VSD = new ServiceType(2);
+
+ /**
+ * Identifier of VPKC service (Verify Public Key Certificates (also referred to as CPKC)).
+ */
+ public static final ServiceType VPKC = new ServiceType(3);
+
+ /**
+ * Identifier of CCPD service (Certify Claim of Possession of Data).
+ */
+ public static final ServiceType CCPD = new ServiceType(4);
+
+ private ASN1Enumerated value;
+
+ public ServiceType(int value)
+ {
+ this.value = new ASN1Enumerated(value);
+ }
+
+ private ServiceType(ASN1Enumerated value)
+ {
+ this.value = value;
+ }
+
+ public static ServiceType getInstance(Object obj)
+ {
+ if (obj instanceof ServiceType)
+ {
+ return (ServiceType)obj;
+ }
+ else if (obj != null)
+ {
+ return new ServiceType(ASN1Enumerated.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static ServiceType getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Enumerated.getInstance(obj, explicit));
+ }
+
+ public BigInteger getValue()
+ {
+ return value.getValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return value;
+ }
+
+ public String toString()
+ {
+ int num = value.getValue().intValue();
+ return "" + num + (
+ num == CPD.getValue().intValue() ? "(CPD)" :
+ num == VSD.getValue().intValue() ? "(VSD)" :
+ num == VPKC.getValue().intValue() ? "(VPKC)" :
+ num == CCPD.getValue().intValue() ? "(CCPD)" :
+ "?");
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/dvcs/TargetEtcChain.java b/core/src/main/java/org/spongycastle/asn1/dvcs/TargetEtcChain.java
new file mode 100644
index 00000000..264a6c26
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/dvcs/TargetEtcChain.java
@@ -0,0 +1,191 @@
+package org.spongycastle.asn1.dvcs;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+/**
+ * <pre>
+ * TargetEtcChain ::= SEQUENCE {
+ * target CertEtcToken,
+ * chain SEQUENCE SIZE (1..MAX) OF
+ * CertEtcToken OPTIONAL,
+ * pathProcInput [0] PathProcInput OPTIONAL
+ * }
+ * </pre>
+ */
+
+public class TargetEtcChain
+ extends ASN1Object
+{
+ private CertEtcToken target;
+ private ASN1Sequence chain;
+ private PathProcInput pathProcInput;
+
+ public TargetEtcChain(CertEtcToken target)
+ {
+ this(target, null, null);
+ }
+
+ public TargetEtcChain(CertEtcToken target, CertEtcToken[] chain)
+ {
+ this(target, chain, null);
+ }
+
+ public TargetEtcChain(CertEtcToken target, PathProcInput pathProcInput)
+ {
+ this(target, null, pathProcInput);
+ }
+
+ public TargetEtcChain(CertEtcToken target, CertEtcToken[] chain, PathProcInput pathProcInput)
+ {
+ this.target = target;
+
+ if (chain != null)
+ {
+ this.chain = new DERSequence(chain);
+ }
+
+ this.pathProcInput = pathProcInput;
+ }
+
+ private TargetEtcChain(ASN1Sequence seq)
+ {
+ int i = 0;
+ ASN1Encodable obj = seq.getObjectAt(i++);
+ this.target = CertEtcToken.getInstance(obj);
+
+ try
+ {
+ obj = seq.getObjectAt(i++);
+ this.chain = ASN1Sequence.getInstance(obj);
+ }
+ catch (IllegalArgumentException e)
+ {
+ }
+ catch (IndexOutOfBoundsException e)
+ {
+ return;
+ }
+
+ try
+ {
+ obj = seq.getObjectAt(i++);
+ ASN1TaggedObject tagged = ASN1TaggedObject.getInstance(obj);
+ switch (tagged.getTagNo())
+ {
+ case 0:
+ this.pathProcInput = PathProcInput.getInstance(tagged, false);
+ break;
+ }
+ }
+ catch (IllegalArgumentException e)
+ {
+ }
+ catch (IndexOutOfBoundsException e)
+ {
+ }
+ }
+
+ public static TargetEtcChain getInstance(Object obj)
+ {
+ if (obj instanceof TargetEtcChain)
+ {
+ return (TargetEtcChain)obj;
+ }
+ else if (obj != null)
+ {
+ return new TargetEtcChain(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static TargetEtcChain getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(target);
+ if (chain != null)
+ {
+ v.add(chain);
+ }
+ if (pathProcInput != null)
+ {
+ v.add(new DERTaggedObject(false, 0, pathProcInput));
+ }
+
+ return new DERSequence(v);
+ }
+
+ public String toString()
+ {
+ StringBuffer s = new StringBuffer();
+ s.append("TargetEtcChain {\n");
+ s.append("target: " + target + "\n");
+ if (chain != null)
+ {
+ s.append("chain: " + chain + "\n");
+ }
+ if (pathProcInput != null)
+ {
+ s.append("pathProcInput: " + pathProcInput + "\n");
+ }
+ s.append("}\n");
+ return s.toString();
+ }
+
+
+ public CertEtcToken getTarget()
+ {
+ return target;
+ }
+
+ public CertEtcToken[] getChain()
+ {
+ if (chain != null)
+ {
+ return CertEtcToken.arrayFromSequence(chain);
+ }
+
+ return null;
+ }
+
+ private void setChain(ASN1Sequence chain)
+ {
+ this.chain = chain;
+ }
+
+ public PathProcInput getPathProcInput()
+ {
+ return pathProcInput;
+ }
+
+ private void setPathProcInput(PathProcInput pathProcInput)
+ {
+ this.pathProcInput = pathProcInput;
+ }
+
+ public static TargetEtcChain[] arrayFromSequence(ASN1Sequence seq)
+ {
+ TargetEtcChain[] tmp = new TargetEtcChain[seq.size()];
+
+ for (int i = 0; i != tmp.length; i++)
+ {
+ tmp[i] = TargetEtcChain.getInstance(seq.getObjectAt(i));
+ }
+
+ return tmp;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/eac/BidirectionalMap.java b/core/src/main/java/org/spongycastle/asn1/eac/BidirectionalMap.java
new file mode 100644
index 00000000..479677c0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/eac/BidirectionalMap.java
@@ -0,0 +1,23 @@
+package org.spongycastle.asn1.eac;
+
+import java.util.Hashtable;
+
+public class BidirectionalMap
+ extends Hashtable
+{
+ private static final long serialVersionUID = -7457289971962812909L;
+
+ Hashtable reverseMap = new Hashtable();
+
+ public Object getReverse(Object o)
+ {
+ return reverseMap.get(o);
+ }
+
+ public Object put(Object key, Object o)
+ {
+ reverseMap.put(o, key);
+ return super.put(key, o);
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/eac/CVCertificate.java b/core/src/main/java/org/spongycastle/asn1/eac/CVCertificate.java
new file mode 100644
index 00000000..63e02d4e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/eac/CVCertificate.java
@@ -0,0 +1,313 @@
+package org.spongycastle.asn1.eac;
+
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1ParsingException;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DERApplicationSpecific;
+import org.spongycastle.asn1.DEROctetString;
+
+
+/**
+ * an iso7816Certificate structure.
+ * <pre>
+ * Certificate ::= SEQUENCE {
+ * CertificateBody Iso7816CertificateBody,
+ * signature DER Application specific
+ * }
+ * </pre>
+ */
+public class CVCertificate
+ extends ASN1Object
+{
+ private CertificateBody certificateBody;
+ private byte[] signature;
+ private int valid;
+ private static int bodyValid = 0x01;
+ private static int signValid = 0x02;
+ public static final byte version_1 = 0x0;
+
+ public static String ReferenceEncoding = "ISO-8859-1";
+
+ /**
+ * Sets the values of the certificate (body and signature).
+ *
+ * @param appSpe is a DERApplicationSpecific object containing body and signature.
+ * @throws IOException if tags or value are incorrect.
+ */
+ private void setPrivateData(DERApplicationSpecific appSpe)
+ throws IOException
+ {
+ valid = 0;
+ if (appSpe.getApplicationTag() == EACTags.CARDHOLDER_CERTIFICATE)
+ {
+ ASN1InputStream content = new ASN1InputStream(appSpe.getContents());
+ ASN1Primitive tmpObj;
+ while ((tmpObj = content.readObject()) != null)
+ {
+ DERApplicationSpecific aSpe;
+ if (tmpObj instanceof DERApplicationSpecific)
+ {
+ aSpe = (DERApplicationSpecific)tmpObj;
+ switch (aSpe.getApplicationTag())
+ {
+ case EACTags.CERTIFICATE_CONTENT_TEMPLATE:
+ certificateBody = CertificateBody.getInstance(aSpe);
+ valid |= bodyValid;
+ break;
+ case EACTags.STATIC_INTERNAL_AUTHENTIFICATION_ONE_STEP:
+ signature = aSpe.getContents();
+ valid |= signValid;
+ break;
+ default:
+ throw new IOException("Invalid tag, not an Iso7816CertificateStructure :" + aSpe.getApplicationTag());
+ }
+ }
+ else
+ {
+ throw new IOException("Invalid Object, not an Iso7816CertificateStructure");
+ }
+ }
+ }
+ else
+ {
+ throw new IOException("not a CARDHOLDER_CERTIFICATE :" + appSpe.getApplicationTag());
+ }
+ }
+
+ /**
+ * Create an iso7816Certificate structure from an ASN1InputStream.
+ *
+ * @param aIS the byte stream to parse.
+ * @throws IOException if there is a problem parsing the data.
+ */
+ public CVCertificate(ASN1InputStream aIS)
+ throws IOException
+ {
+ initFrom(aIS);
+ }
+
+ private void initFrom(ASN1InputStream aIS)
+ throws IOException
+ {
+ ASN1Primitive obj;
+ while ((obj = aIS.readObject()) != null)
+ {
+ if (obj instanceof DERApplicationSpecific)
+ {
+ setPrivateData((DERApplicationSpecific)obj);
+ }
+ else
+ {
+ throw new IOException("Invalid Input Stream for creating an Iso7816CertificateStructure");
+ }
+ }
+ }
+
+ /**
+ * Create an iso7816Certificate structure from a DERApplicationSpecific.
+ *
+ * @param appSpe the DERApplicationSpecific object.
+ * @return the Iso7816CertificateStructure represented by the DERApplicationSpecific object.
+ * @throws IOException if there is a problem parsing the data.
+ */
+ private CVCertificate(DERApplicationSpecific appSpe)
+ throws IOException
+ {
+ setPrivateData(appSpe);
+ }
+
+ /**
+ * Create an iso7816Certificate structure from a body and its signature.
+ *
+ * @param body the Iso7816CertificateBody object containing the body.
+ * @param signature the byte array containing the signature
+ * @throws IOException if there is a problem parsing the data.
+ */
+ public CVCertificate(CertificateBody body, byte[] signature)
+ throws IOException
+ {
+ certificateBody = body;
+ this.signature = signature;
+ // patch remi
+ valid |= bodyValid;
+ valid |= signValid;
+ }
+
+ /**
+ * Create an iso7816Certificate structure from an object.
+ *
+ * @param obj the Object to extract the certificate from.
+ * @return the Iso7816CertificateStructure represented by the byte stream.
+ */
+ public static CVCertificate getInstance(Object obj)
+ {
+ if (obj instanceof CVCertificate)
+ {
+ return (CVCertificate)obj;
+ }
+ else if (obj != null)
+ {
+ try
+ {
+ return new CVCertificate(DERApplicationSpecific.getInstance(obj));
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException("unable to parse data: " + e.getMessage(), e);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Gives the signature of the whole body. Type of signature is given in
+ * the Iso7816CertificateBody.Iso7816PublicKey.ASN1ObjectIdentifier
+ *
+ * @return the signature of the body.
+ */
+ public byte[] getSignature()
+ {
+ return signature;
+ }
+
+ /**
+ * Gives the body of the certificate.
+ *
+ * @return the body.
+ */
+ public CertificateBody getBody()
+ {
+ return certificateBody;
+ }
+
+ /**
+ * @see org.spongycastle.asn1.ASN1Object#toASN1Primitive()
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (valid != (signValid | bodyValid))
+ {
+ return null;
+ }
+ v.add(certificateBody);
+
+ try
+ {
+ v.add(new DERApplicationSpecific(false, EACTags.STATIC_INTERNAL_AUTHENTIFICATION_ONE_STEP, new DEROctetString(signature)));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("unable to convert signature!");
+ }
+
+ return new DERApplicationSpecific(EACTags.CARDHOLDER_CERTIFICATE, v);
+ }
+
+ /**
+ * @return the Holder authorization and role (CVCA, DV, IS).
+ */
+ public ASN1ObjectIdentifier getHolderAuthorization()
+ throws IOException
+ {
+ CertificateHolderAuthorization cha = certificateBody.getCertificateHolderAuthorization();
+ return cha.getOid();
+ }
+
+ /**
+ * @return the date of the certificate generation
+ */
+ public PackedDate getEffectiveDate()
+ throws IOException
+ {
+ return certificateBody.getCertificateEffectiveDate();
+ }
+
+
+ /**
+ * @return the type of certificate (request or profile)
+ * value is either Iso7816CertificateBody.profileType
+ * or Iso7816CertificateBody.requestType. Any other value
+ * is not valid.
+ */
+ public int getCertificateType()
+ {
+ return this.certificateBody.getCertificateType();
+ }
+
+ /**
+ * @return the date of the certificate generation
+ */
+ public PackedDate getExpirationDate()
+ throws IOException
+ {
+ return certificateBody.getCertificateExpirationDate();
+ }
+
+
+ /**
+ * return a bits field coded on one byte. For signification of the
+ * several bit see Iso7816CertificateHolderAuthorization
+ *
+ * @return role and access rigth
+ * @throws IOException
+ * @see CertificateHolderAuthorization
+ */
+ public int getRole()
+ throws IOException
+ {
+ CertificateHolderAuthorization cha = certificateBody.getCertificateHolderAuthorization();
+ return cha.getAccessRights();
+ }
+
+ /**
+ * @return the Authority Reference field of the certificate
+ * @throws IOException
+ */
+ public CertificationAuthorityReference getAuthorityReference()
+ throws IOException
+ {
+ return certificateBody.getCertificationAuthorityReference();
+ }
+
+ /**
+ * @return the Holder Reference Field of the certificate
+ * @throws IOException
+ */
+ public CertificateHolderReference getHolderReference()
+ throws IOException
+ {
+ return certificateBody.getCertificateHolderReference();
+ }
+
+ /**
+ * @return the bits corresponding to the role intented for the certificate
+ * See Iso7816CertificateHolderAuthorization static int for values
+ * @throws IOException
+ */
+ public int getHolderAuthorizationRole()
+ throws IOException
+ {
+ int rights = certificateBody.getCertificateHolderAuthorization().getAccessRights();
+ return rights & 0xC0;
+ }
+
+ /**
+ * @return the bits corresponding the authorizations contained in the certificate
+ * See Iso7816CertificateHolderAuthorization static int for values
+ * @throws IOException
+ */
+ public Flags getHolderAuthorizationRights()
+ throws IOException
+ {
+ return new Flags(certificateBody.getCertificateHolderAuthorization().getAccessRights() & 0x1F);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/eac/CVCertificateRequest.java b/core/src/main/java/org/spongycastle/asn1/eac/CVCertificateRequest.java
new file mode 100644
index 00000000..4170d6e4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/eac/CVCertificateRequest.java
@@ -0,0 +1,170 @@
+package org.spongycastle.asn1.eac;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1ParsingException;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.BERTags;
+import org.spongycastle.asn1.DERApplicationSpecific;
+import org.spongycastle.asn1.DEROctetString;
+
+//import java.math.BigInteger;
+
+
+public class CVCertificateRequest
+ extends ASN1Object
+{
+ private CertificateBody certificateBody;
+
+ private byte[] innerSignature = null;
+ private byte[] outerSignature = null;
+
+ private int valid;
+
+ private static int bodyValid = 0x01;
+ private static int signValid = 0x02;
+
+ private CVCertificateRequest(DERApplicationSpecific request)
+ throws IOException
+ {
+ if (request.getApplicationTag() == EACTags.AUTHENTIFICATION_DATA)
+ {
+ ASN1Sequence seq = ASN1Sequence.getInstance(request.getObject(BERTags.SEQUENCE));
+
+ initCertBody(DERApplicationSpecific.getInstance(seq.getObjectAt(0)));
+
+ outerSignature = DERApplicationSpecific.getInstance(seq.getObjectAt(seq.size() - 1)).getContents();
+ }
+ else
+ {
+ initCertBody(request);
+ }
+ }
+
+ private void initCertBody(DERApplicationSpecific request)
+ throws IOException
+ {
+ if (request.getApplicationTag() == EACTags.CARDHOLDER_CERTIFICATE)
+ {
+ ASN1Sequence seq = ASN1Sequence.getInstance(request.getObject(BERTags.SEQUENCE));
+ for (Enumeration en = seq.getObjects(); en.hasMoreElements();)
+ {
+ DERApplicationSpecific obj = DERApplicationSpecific.getInstance(en.nextElement());
+ switch (obj.getApplicationTag())
+ {
+ case EACTags.CERTIFICATE_CONTENT_TEMPLATE:
+ certificateBody = CertificateBody.getInstance(obj);
+ valid |= bodyValid;
+ break;
+ case EACTags.STATIC_INTERNAL_AUTHENTIFICATION_ONE_STEP:
+ innerSignature = obj.getContents();
+ valid |= signValid;
+ break;
+ default:
+ throw new IOException("Invalid tag, not an CV Certificate Request element:" + obj.getApplicationTag());
+ }
+ }
+ }
+ else
+ {
+ throw new IOException("not a CARDHOLDER_CERTIFICATE in request:" + request.getApplicationTag());
+ }
+ }
+
+ public static CVCertificateRequest getInstance(Object obj)
+ {
+ if (obj instanceof CVCertificateRequest)
+ {
+ return (CVCertificateRequest)obj;
+ }
+ else if (obj != null)
+ {
+ try
+ {
+ return new CVCertificateRequest(DERApplicationSpecific.getInstance(obj));
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException("unable to parse data: " + e.getMessage(), e);
+ }
+ }
+
+ return null;
+ }
+
+ ASN1ObjectIdentifier signOid = null;
+ ASN1ObjectIdentifier keyOid = null;
+
+ public static byte[] ZeroArray = new byte[]{0};
+
+
+ String strCertificateHolderReference;
+
+ byte[] encodedAuthorityReference;
+
+ int ProfileId;
+
+ /**
+ * Returns the body of the certificate template
+ *
+ * @return the body.
+ */
+ public CertificateBody getCertificateBody()
+ {
+ return certificateBody;
+ }
+
+ /**
+ * Return the public key data object carried in the request
+ * @return the public key
+ */
+ public PublicKeyDataObject getPublicKey()
+ {
+ return certificateBody.getPublicKey();
+ }
+
+ public byte[] getInnerSignature()
+ {
+ return innerSignature;
+ }
+
+ public byte[] getOuterSignature()
+ {
+ return outerSignature;
+ }
+
+ byte[] certificate = null;
+ protected String overSignerReference = null;
+
+ public boolean hasOuterSignature()
+ {
+ return outerSignature != null;
+ }
+
+ byte[] encoded;
+
+ PublicKeyDataObject iso7816PubKey = null;
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certificateBody);
+
+ try
+ {
+ v.add(new DERApplicationSpecific(false, EACTags.STATIC_INTERNAL_AUTHENTIFICATION_ONE_STEP, new DEROctetString(innerSignature)));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("unable to convert signature!");
+ }
+
+ return new DERApplicationSpecific(EACTags.CARDHOLDER_CERTIFICATE, v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/eac/CertificateBody.java b/core/src/main/java/org/spongycastle/asn1/eac/CertificateBody.java
new file mode 100644
index 00000000..a64ec682
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/eac/CertificateBody.java
@@ -0,0 +1,472 @@
+package org.spongycastle.asn1.eac;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.BERTags;
+import org.spongycastle.asn1.DERApplicationSpecific;
+import org.spongycastle.asn1.DEROctetString;
+
+
+/**
+ * an Iso7816CertificateBody structure.
+ * <pre>
+ * CertificateBody ::= SEQUENCE {
+ * // version of the certificate format. Must be 0 (version 1)
+ * CertificateProfileIdentifer DERApplicationSpecific,
+ * //uniquely identifies the issuinng CA's signature key pair
+ * // contains the iso3166-1 alpha2 encoded country code, the
+ * // name of issuer and the sequence number of the key pair.
+ * CertificationAuthorityReference DERApplicationSpecific,
+ * // stores the encoded public key
+ * PublicKey Iso7816PublicKey,
+ * //associates the public key contained in the certificate with a unique name
+ * // contains the iso3166-1 alpha2 encoded country code, the
+ * // name of the holder and the sequence number of the key pair.
+ * certificateHolderReference DERApplicationSpecific,
+ * // Encodes the role of the holder (i.e. CVCA, DV, IS) and assigns read/write
+ * // access rights to data groups storing sensitive data
+ * certificateHolderAuthorization Iso7816CertificateHolderAuthorization,
+ * // the date of the certificate generation
+ * CertificateEffectiveDate DERApplicationSpecific,
+ * // the date after wich the certificate expires
+ * certificateExpirationDate DERApplicationSpecific
+ * }
+ * </pre>
+ */
+public class CertificateBody
+ extends ASN1Object
+{
+ ASN1InputStream seq;
+ private DERApplicationSpecific certificateProfileIdentifier;// version of the certificate format. Must be 0 (version 1)
+ private DERApplicationSpecific certificationAuthorityReference;//uniquely identifies the issuinng CA's signature key pair
+ private PublicKeyDataObject publicKey;// stores the encoded public key
+ private DERApplicationSpecific certificateHolderReference;//associates the public key contained in the certificate with a unique name
+ private CertificateHolderAuthorization certificateHolderAuthorization;// Encodes the role of the holder (i.e. CVCA, DV, IS) and assigns read/write access rights to data groups storing sensitive data
+ private DERApplicationSpecific certificateEffectiveDate;// the date of the certificate generation
+ private DERApplicationSpecific certificateExpirationDate;// the date after wich the certificate expires
+ private int certificateType = 0;// bit field of initialized data. This will tell us if the data are valid.
+ private static final int CPI = 0x01;//certificate Profile Identifier
+ private static final int CAR = 0x02;//certification Authority Reference
+ private static final int PK = 0x04;//public Key
+ private static final int CHR = 0x08;//certificate Holder Reference
+ private static final int CHA = 0x10;//certificate Holder Authorization
+ private static final int CEfD = 0x20;//certificate Effective Date
+ private static final int CExD = 0x40;//certificate Expiration Date
+
+ public static final int profileType = 0x7f;//Profile type Certificate
+ public static final int requestType = 0x0D;// Request type Certificate
+
+ private void setIso7816CertificateBody(DERApplicationSpecific appSpe)
+ throws IOException
+ {
+ byte[] content;
+ if (appSpe.getApplicationTag() == EACTags.CERTIFICATE_CONTENT_TEMPLATE)
+ {
+ content = appSpe.getContents();
+ }
+ else
+ {
+ throw new IOException("Bad tag : not an iso7816 CERTIFICATE_CONTENT_TEMPLATE");
+ }
+ ASN1InputStream aIS = new ASN1InputStream(content);
+ ASN1Primitive obj;
+ while ((obj = aIS.readObject()) != null)
+ {
+ DERApplicationSpecific aSpe;
+
+ if (obj instanceof DERApplicationSpecific)
+ {
+ aSpe = (DERApplicationSpecific)obj;
+ }
+ else
+ {
+ throw new IOException("Not a valid iso7816 content : not a DERApplicationSpecific Object :" + EACTags.encodeTag(appSpe) + obj.getClass());
+ }
+ switch (aSpe.getApplicationTag())
+ {
+ case EACTags.INTERCHANGE_PROFILE:
+ setCertificateProfileIdentifier(aSpe);
+ break;
+ case EACTags.ISSUER_IDENTIFICATION_NUMBER:
+ setCertificationAuthorityReference(aSpe);
+ break;
+ case EACTags.CARDHOLDER_PUBLIC_KEY_TEMPLATE:
+ setPublicKey(PublicKeyDataObject.getInstance(aSpe.getObject(BERTags.SEQUENCE)));
+ break;
+ case EACTags.CARDHOLDER_NAME:
+ setCertificateHolderReference(aSpe);
+ break;
+ case EACTags.CERTIFICATE_HOLDER_AUTHORIZATION_TEMPLATE:
+ setCertificateHolderAuthorization(new CertificateHolderAuthorization(aSpe));
+ break;
+ case EACTags.APPLICATION_EFFECTIVE_DATE:
+ setCertificateEffectiveDate(aSpe);
+ break;
+ case EACTags.APPLICATION_EXPIRATION_DATE:
+ setCertificateExpirationDate(aSpe);
+ break;
+ default:
+ certificateType = 0;
+ throw new IOException("Not a valid iso7816 DERApplicationSpecific tag " + aSpe.getApplicationTag());
+ }
+ }
+ }
+
+ /**
+ * builds an Iso7816CertificateBody by settings each parameters.
+ *
+ * @param certificateProfileIdentifier
+ * @param certificationAuthorityReference
+ *
+ * @param publicKey
+ * @param certificateHolderReference
+ * @param certificateHolderAuthorization
+ * @param certificateEffectiveDate
+ * @param certificateExpirationDate
+ */
+ public CertificateBody(
+ DERApplicationSpecific certificateProfileIdentifier,
+ CertificationAuthorityReference certificationAuthorityReference,
+ PublicKeyDataObject publicKey,
+ CertificateHolderReference certificateHolderReference,
+ CertificateHolderAuthorization certificateHolderAuthorization,
+ PackedDate certificateEffectiveDate,
+ PackedDate certificateExpirationDate
+ )
+ {
+ setCertificateProfileIdentifier(certificateProfileIdentifier);
+ setCertificationAuthorityReference(new DERApplicationSpecific(
+ EACTags.ISSUER_IDENTIFICATION_NUMBER, certificationAuthorityReference.getEncoded()));
+ setPublicKey(publicKey);
+ setCertificateHolderReference(new DERApplicationSpecific(
+ EACTags.CARDHOLDER_NAME, certificateHolderReference.getEncoded()));
+ setCertificateHolderAuthorization(certificateHolderAuthorization);
+ try
+ {
+ setCertificateEffectiveDate(new DERApplicationSpecific(
+ false, EACTags.APPLICATION_EFFECTIVE_DATE, new DEROctetString(certificateEffectiveDate.getEncoding())));
+ setCertificateExpirationDate(new DERApplicationSpecific(
+ false, EACTags.APPLICATION_EXPIRATION_DATE, new DEROctetString(certificateExpirationDate.getEncoding())));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("unable to encode dates: " + e.getMessage());
+ }
+ }
+
+ /**
+ * builds an Iso7816CertificateBody with an ASN1InputStream.
+ *
+ * @param obj DERApplicationSpecific containing the whole body.
+ * @throws IOException if the body is not valid.
+ */
+ private CertificateBody(DERApplicationSpecific obj)
+ throws IOException
+ {
+ setIso7816CertificateBody(obj);
+ }
+
+ /**
+ * create a profile type Iso7816CertificateBody.
+ *
+ * @return return the "profile" type certificate body.
+ * @throws IOException if the DERApplicationSpecific cannot be created.
+ */
+ private ASN1Primitive profileToASN1Object()
+ throws IOException
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certificateProfileIdentifier);
+ v.add(certificationAuthorityReference);
+ v.add(new DERApplicationSpecific(false, EACTags.CARDHOLDER_PUBLIC_KEY_TEMPLATE, publicKey));
+ v.add(certificateHolderReference);
+ v.add(certificateHolderAuthorization);
+ v.add(certificateEffectiveDate);
+ v.add(certificateExpirationDate);
+ return new DERApplicationSpecific(EACTags.CERTIFICATE_CONTENT_TEMPLATE, v);
+ }
+
+ private void setCertificateProfileIdentifier(DERApplicationSpecific certificateProfileIdentifier)
+ throws IllegalArgumentException
+ {
+ if (certificateProfileIdentifier.getApplicationTag() == EACTags.INTERCHANGE_PROFILE)
+ {
+ this.certificateProfileIdentifier = certificateProfileIdentifier;
+ certificateType |= CPI;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Not an Iso7816Tags.INTERCHANGE_PROFILE tag :" + EACTags.encodeTag(certificateProfileIdentifier));
+ }
+ }
+
+ private void setCertificateHolderReference(DERApplicationSpecific certificateHolderReference)
+ throws IllegalArgumentException
+ {
+ if (certificateHolderReference.getApplicationTag() == EACTags.CARDHOLDER_NAME)
+ {
+ this.certificateHolderReference = certificateHolderReference;
+ certificateType |= CHR;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Not an Iso7816Tags.CARDHOLDER_NAME tag");
+ }
+ }
+
+ /**
+ * set the CertificationAuthorityReference.
+ *
+ * @param certificationAuthorityReference
+ * the DERApplicationSpecific containing the CertificationAuthorityReference.
+ * @throws IllegalArgumentException if the DERApplicationSpecific is not valid.
+ */
+ private void setCertificationAuthorityReference(
+ DERApplicationSpecific certificationAuthorityReference)
+ throws IllegalArgumentException
+ {
+ if (certificationAuthorityReference.getApplicationTag() == EACTags.ISSUER_IDENTIFICATION_NUMBER)
+ {
+ this.certificationAuthorityReference = certificationAuthorityReference;
+ certificateType |= CAR;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Not an Iso7816Tags.ISSUER_IDENTIFICATION_NUMBER tag");
+ }
+ }
+
+ /**
+ * set the public Key
+ *
+ * @param publicKey : the DERApplicationSpecific containing the public key
+ * @throws java.io.IOException
+ */
+ private void setPublicKey(PublicKeyDataObject publicKey)
+ {
+ this.publicKey = PublicKeyDataObject.getInstance(publicKey);
+ this.certificateType |= PK;
+ }
+
+ /**
+ * create a request type Iso7816CertificateBody.
+ *
+ * @return return the "request" type certificate body.
+ * @throws IOException if the DERApplicationSpecific cannot be created.
+ */
+ private ASN1Primitive requestToASN1Object()
+ throws IOException
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certificateProfileIdentifier);
+ v.add(new DERApplicationSpecific(false, EACTags.CARDHOLDER_PUBLIC_KEY_TEMPLATE, publicKey));
+ v.add(certificateHolderReference);
+ return new DERApplicationSpecific(EACTags.CERTIFICATE_CONTENT_TEMPLATE, v);
+ }
+
+ /**
+ * create a "request" or "profile" type Iso7816CertificateBody according to the variables sets.
+ *
+ * @return return the ASN1Primitive representing the "request" or "profile" type certificate body.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ try
+ {
+ if (certificateType == profileType)
+ {
+ return profileToASN1Object();
+ }
+ if (certificateType == requestType)
+ {
+ return requestToASN1Object();
+ }
+ }
+ catch (IOException e)
+ {
+ return null;
+ }
+ return null;
+ }
+
+ /**
+ * gives the type of the certificate (value should be profileType or requestType if all data are set).
+ *
+ * @return the int representing the data already set.
+ */
+ public int getCertificateType()
+ {
+ return certificateType;
+ }
+
+ /**
+ * Gives an instance of Iso7816CertificateBody taken from Object obj
+ *
+ * @param obj is the Object to extract the certificate body from.
+ * @return the Iso7816CertificateBody taken from Object obj.
+ * @throws IOException if object is not valid.
+ */
+ public static CertificateBody getInstance(Object obj)
+ throws IOException
+ {
+ if (obj instanceof CertificateBody)
+ {
+ return (CertificateBody)obj;
+ }
+ else if (obj != null)
+ {
+ return new CertificateBody(DERApplicationSpecific.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * @return the date of the certificate generation
+ */
+ public PackedDate getCertificateEffectiveDate()
+ {
+ if ((this.certificateType & CertificateBody.CEfD) ==
+ CertificateBody.CEfD)
+ {
+ return new PackedDate(certificateEffectiveDate.getContents());
+ }
+ return null;
+ }
+
+ /**
+ * set the date of the certificate generation
+ *
+ * @param ced DERApplicationSpecific containing the date of the certificate generation
+ * @throws IllegalArgumentException if the tag is not Iso7816Tags.APPLICATION_EFFECTIVE_DATE
+ */
+ private void setCertificateEffectiveDate(DERApplicationSpecific ced)
+ throws IllegalArgumentException
+ {
+ if (ced.getApplicationTag() == EACTags.APPLICATION_EFFECTIVE_DATE)
+ {
+ this.certificateEffectiveDate = ced;
+ certificateType |= CEfD;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Not an Iso7816Tags.APPLICATION_EFFECTIVE_DATE tag :" + EACTags.encodeTag(ced));
+ }
+ }
+
+ /**
+ * @return the date after wich the certificate expires
+ */
+ public PackedDate getCertificateExpirationDate()
+ throws IOException
+ {
+ if ((this.certificateType & CertificateBody.CExD) ==
+ CertificateBody.CExD)
+ {
+ return new PackedDate(certificateExpirationDate.getContents());
+ }
+ throw new IOException("certificate Expiration Date not set");
+ }
+
+ /**
+ * set the date after wich the certificate expires
+ *
+ * @param ced DERApplicationSpecific containing the date after wich the certificate expires
+ * @throws IllegalArgumentException if the tag is not Iso7816Tags.APPLICATION_EXPIRATION_DATE
+ */
+ private void setCertificateExpirationDate(DERApplicationSpecific ced)
+ throws IllegalArgumentException
+ {
+ if (ced.getApplicationTag() == EACTags.APPLICATION_EXPIRATION_DATE)
+ {
+ this.certificateExpirationDate = ced;
+ certificateType |= CExD;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Not an Iso7816Tags.APPLICATION_EXPIRATION_DATE tag");
+ }
+ }
+
+ /**
+ * the Iso7816CertificateHolderAuthorization encodes the role of the holder
+ * (i.e. CVCA, DV, IS) and assigns read/write access rights to data groups
+ * storing sensitive data. This functions returns the Certificate Holder
+ * Authorization
+ *
+ * @return the Iso7816CertificateHolderAuthorization
+ */
+ public CertificateHolderAuthorization getCertificateHolderAuthorization()
+ throws IOException
+ {
+ if ((this.certificateType & CertificateBody.CHA) ==
+ CertificateBody.CHA)
+ {
+ return certificateHolderAuthorization;
+ }
+ throw new IOException("Certificate Holder Authorisation not set");
+ }
+
+ /**
+ * set the CertificateHolderAuthorization
+ *
+ * @param cha the Certificate Holder Authorization
+ */
+ private void setCertificateHolderAuthorization(
+ CertificateHolderAuthorization cha)
+ {
+ this.certificateHolderAuthorization = cha;
+ certificateType |= CHA;
+ }
+
+ /**
+ * certificateHolderReference : associates the public key contained in the certificate with a unique name
+ *
+ * @return the certificateHolderReference.
+ */
+ public CertificateHolderReference getCertificateHolderReference()
+ {
+ return new CertificateHolderReference(certificateHolderReference.getContents());
+ }
+
+ /**
+ * CertificateProfileIdentifier : version of the certificate format. Must be 0 (version 1)
+ *
+ * @return the CertificateProfileIdentifier
+ */
+ public DERApplicationSpecific getCertificateProfileIdentifier()
+ {
+ return certificateProfileIdentifier;
+ }
+
+ /**
+ * get the certificationAuthorityReference
+ * certificationAuthorityReference : uniquely identifies the issuinng CA's signature key pair
+ *
+ * @return the certificationAuthorityReference
+ */
+ public CertificationAuthorityReference getCertificationAuthorityReference()
+ throws IOException
+ {
+ if ((this.certificateType & CertificateBody.CAR) ==
+ CertificateBody.CAR)
+ {
+ return new CertificationAuthorityReference(certificationAuthorityReference.getContents());
+ }
+ throw new IOException("Certification authority reference not set");
+ }
+
+ /**
+ * @return the PublicKey
+ */
+ public PublicKeyDataObject getPublicKey()
+ {
+ return publicKey;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/eac/CertificateHolderAuthorization.java b/core/src/main/java/org/spongycastle/asn1/eac/CertificateHolderAuthorization.java
new file mode 100644
index 00000000..b70b181f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/eac/CertificateHolderAuthorization.java
@@ -0,0 +1,184 @@
+package org.spongycastle.asn1.eac;
+
+import java.io.IOException;
+import java.util.Hashtable;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DERApplicationSpecific;
+import org.spongycastle.util.Integers;
+
+/**
+ * an Iso7816CertificateHolderAuthorization structure.
+ * <pre>
+ * Certificate Holder Authorization ::= SEQUENCE {
+ * // specifies the format and the rules for the evaluation of the authorization
+ * // level
+ * ASN1ObjectIdentifier oid,
+ * // access rights
+ * DERApplicationSpecific accessRights,
+ * }
+ * </pre>
+ */
+public class CertificateHolderAuthorization
+ extends ASN1Object
+{
+ ASN1ObjectIdentifier oid;
+ DERApplicationSpecific accessRights;
+ public static final ASN1ObjectIdentifier id_role_EAC = EACObjectIdentifiers.bsi_de.branch("3.1.2.1");
+ public static final int CVCA = 0xC0;
+ public static final int DV_DOMESTIC = 0x80;
+ public static final int DV_FOREIGN = 0x40;
+ public static final int IS = 0;
+ public static final int RADG4 = 0x02;//Read Access to DG4 (Iris)
+ public static final int RADG3 = 0x01;//Read Access to DG3 (fingerprint)
+
+ static Hashtable RightsDecodeMap = new Hashtable();
+ static BidirectionalMap AuthorizationRole = new BidirectionalMap();
+ static Hashtable ReverseMap = new Hashtable();
+
+ static
+ {
+ RightsDecodeMap.put(Integers.valueOf(RADG4), "RADG4");
+ RightsDecodeMap.put(Integers.valueOf(RADG3), "RADG3");
+
+ AuthorizationRole.put(Integers.valueOf(CVCA), "CVCA");
+ AuthorizationRole.put(Integers.valueOf(DV_DOMESTIC), "DV_DOMESTIC");
+ AuthorizationRole.put(Integers.valueOf(DV_FOREIGN), "DV_FOREIGN");
+ AuthorizationRole.put(Integers.valueOf(IS), "IS");
+
+ /*
+ for (int i : RightsDecodeMap.keySet())
+ ReverseMap.put(RightsDecodeMap.get(i), i);
+
+ for (int i : AuthorizationRole.keySet())
+ ReverseMap.put(AuthorizationRole.get(i), i);
+ */
+ }
+
+ public static String GetRoleDescription(int i)
+ {
+ return (String)AuthorizationRole.get(Integers.valueOf(i));
+ }
+
+ public static int GetFlag(String description)
+ {
+ Integer i = (Integer)AuthorizationRole.getReverse(description);
+ if (i == null)
+ {
+ throw new IllegalArgumentException("Unknown value " + description);
+ }
+
+ return i.intValue();
+ }
+
+ private void setPrivateData(ASN1InputStream cha)
+ throws IOException
+ {
+ ASN1Primitive obj;
+ obj = cha.readObject();
+ if (obj instanceof ASN1ObjectIdentifier)
+ {
+ this.oid = (ASN1ObjectIdentifier)obj;
+ }
+ else
+ {
+ throw new IllegalArgumentException("no Oid in CerticateHolderAuthorization");
+ }
+ obj = cha.readObject();
+ if (obj instanceof DERApplicationSpecific)
+ {
+ this.accessRights = (DERApplicationSpecific)obj;
+ }
+ else
+ {
+ throw new IllegalArgumentException("No access rights in CerticateHolderAuthorization");
+ }
+ }
+
+
+ /**
+ * create an Iso7816CertificateHolderAuthorization according to the parameters
+ *
+ * @param oid Object Identifier : specifies the format and the rules for the
+ * evaluatioin of the authorization level.
+ * @param rights specifies the access rights
+ * @throws IOException
+ */
+ public CertificateHolderAuthorization(ASN1ObjectIdentifier oid, int rights)
+ throws IOException
+ {
+ setOid(oid);
+ setAccessRights((byte)rights);
+ }
+
+ /**
+ * create an Iso7816CertificateHolderAuthorization according to the {@link DERApplicationSpecific}
+ *
+ * @param aSpe the DERApplicationSpecific containing the data
+ * @throws IOException
+ */
+ public CertificateHolderAuthorization(DERApplicationSpecific aSpe)
+ throws IOException
+ {
+ if (aSpe.getApplicationTag() == EACTags.CERTIFICATE_HOLDER_AUTHORIZATION_TEMPLATE)
+ {
+ setPrivateData(new ASN1InputStream(aSpe.getContents()));
+ }
+ }
+
+ /**
+ * @return containing the access rights
+ */
+ public int getAccessRights()
+ {
+ return accessRights.getContents()[0] & 0xff;
+ }
+
+ /**
+ * create a DERApplicationSpecific and set the access rights to "rights"
+ *
+ * @param rights byte containing the rights.
+ */
+ private void setAccessRights(byte rights)
+ {
+ byte[] accessRights = new byte[1];
+ accessRights[0] = rights;
+ this.accessRights = new DERApplicationSpecific(
+ EACTags.getTag(EACTags.DISCRETIONARY_DATA), accessRights);
+ }
+
+ /**
+ * @return the Object identifier
+ */
+ public ASN1ObjectIdentifier getOid()
+ {
+ return oid;
+ }
+
+ /**
+ * set the Object Identifier
+ *
+ * @param oid {@link ASN1ObjectIdentifier} containing the Object Identifier
+ */
+ private void setOid(ASN1ObjectIdentifier oid)
+ {
+ this.oid = oid;
+ }
+
+ /**
+ * return the Certificate Holder Authorization as a DERApplicationSpecific Object
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(oid);
+ v.add(accessRights);
+
+ return new DERApplicationSpecific(EACTags.CERTIFICATE_HOLDER_AUTHORIZATION_TEMPLATE, v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/eac/CertificateHolderReference.java b/core/src/main/java/org/spongycastle/asn1/eac/CertificateHolderReference.java
new file mode 100644
index 00000000..01651ff7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/eac/CertificateHolderReference.java
@@ -0,0 +1,66 @@
+package org.spongycastle.asn1.eac;
+
+import java.io.UnsupportedEncodingException;
+
+public class CertificateHolderReference
+{
+ private static final String ReferenceEncoding = "ISO-8859-1";
+
+ private String countryCode;
+ private String holderMnemonic;
+ private String sequenceNumber;
+
+ public CertificateHolderReference(String countryCode, String holderMnemonic, String sequenceNumber)
+ {
+ this.countryCode = countryCode;
+ this.holderMnemonic = holderMnemonic;
+ this.sequenceNumber = sequenceNumber;
+ }
+
+ CertificateHolderReference(byte[] contents)
+ {
+ try
+ {
+ String concat = new String(contents, ReferenceEncoding);
+
+ this.countryCode = concat.substring(0, 2);
+ this.holderMnemonic = concat.substring(2, concat.length() - 5);
+
+ this.sequenceNumber = concat.substring(concat.length() - 5);
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new IllegalStateException(e.toString());
+ }
+ }
+
+ public String getCountryCode()
+ {
+ return countryCode;
+ }
+
+ public String getHolderMnemonic()
+ {
+ return holderMnemonic;
+ }
+
+ public String getSequenceNumber()
+ {
+ return sequenceNumber;
+ }
+
+
+ public byte[] getEncoded()
+ {
+ String ref = countryCode + holderMnemonic + sequenceNumber;
+
+ try
+ {
+ return ref.getBytes(ReferenceEncoding);
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new IllegalStateException(e.toString());
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/eac/CertificationAuthorityReference.java b/core/src/main/java/org/spongycastle/asn1/eac/CertificationAuthorityReference.java
new file mode 100644
index 00000000..993cf729
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/eac/CertificationAuthorityReference.java
@@ -0,0 +1,15 @@
+package org.spongycastle.asn1.eac;
+
+public class CertificationAuthorityReference
+ extends CertificateHolderReference
+{
+ public CertificationAuthorityReference(String countryCode, String holderMnemonic, String sequenceNumber)
+ {
+ super(countryCode, holderMnemonic, sequenceNumber);
+ }
+
+ CertificationAuthorityReference(byte[] contents)
+ {
+ super(contents);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/eac/EACObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/eac/EACObjectIdentifiers.java
new file mode 100644
index 00000000..94e8b21c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/eac/EACObjectIdentifiers.java
@@ -0,0 +1,110 @@
+package org.spongycastle.asn1.eac;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+
+/**
+ * German Federal Office for Information Security
+ * (Bundesamt f&uuml;r Sicherheit in der Informationstechnik)
+ * <a href="http://www.bsi.bund.de/">http://www.bsi.bund.de/</a>
+ * <p>
+ * <a href="https://www.bsi.bund.de/EN/Publications/TechnicalGuidelines/TR03110/BSITR03110.html">BSI TR-03110</a>
+ * Technical Guideline Advanced Security Mechanisms for Machine Readable Travel Documents
+ * <p>
+ * <a href="https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/TechGuidelines/TR03110/TR-03110_v2.1_P3pdf.pdf">
+ * Technical Guideline TR-03110-3</a>
+ * Advanced Security Mechanisms for Machine Readable Travel Documents;
+ * Part 3: Common Specifications.
+ */
+public interface EACObjectIdentifiers
+{
+ /**
+ * <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");
+
+ /**
+ * <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");
+
+ /** 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");
+
+ /**
+ * <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");
+
+ /**
+ * <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");
+
+ /** 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");
+ /** 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");
+ /** 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
+ * }
+ * </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/core/src/main/java/org/spongycastle/asn1/eac/EACTags.java b/core/src/main/java/org/spongycastle/asn1/eac/EACTags.java
new file mode 100644
index 00000000..f061ebe6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/eac/EACTags.java
@@ -0,0 +1,209 @@
+package org.spongycastle.asn1.eac;
+
+import org.spongycastle.asn1.BERTags;
+import org.spongycastle.asn1.DERApplicationSpecific;
+
+public class EACTags
+{
+ public static final int OBJECT_IDENTIFIER = 0x06;
+ public static final int COUNTRY_CODE_NATIONAL_DATA = 0x41;
+ public static final int ISSUER_IDENTIFICATION_NUMBER = 0x02; //0x42;
+ public static final int CARD_SERVICE_DATA = 0x43;
+ public static final int INITIAL_ACCESS_DATA = 0x44;
+ public static final int CARD_ISSUER_DATA = 0x45;
+ public static final int PRE_ISSUING_DATA = 0x46;
+ public static final int CARD_CAPABILITIES = 0x47;
+ public static final int STATUS_INFORMATION = 0x48;
+ public static final int EXTENDED_HEADER_LIST = 0x4D;
+ public static final int APPLICATION_IDENTIFIER = 0x4F;
+ public static final int APPLICATION_LABEL = 0x50;
+ public static final int FILE_REFERENCE = 0x51;
+ public static final int COMMAND_TO_PERFORM = 0x52;
+ public static final int DISCRETIONARY_DATA = 0x53;
+ public static final int OFFSET_DATA_OBJECT = 0x54;
+ public static final int TRACK1_APPLICATION = 0x56;
+ public static final int TRACK2_APPLICATION = 0x57;
+ public static final int TRACK3_APPLICATION = 0x58;
+ public static final int CARD_EXPIRATION_DATA = 0x59;
+ public static final int PRIMARY_ACCOUNT_NUMBER = 0x5A;// PAN
+ public static final int NAME = 0x5B;
+ public static final int TAG_LIST = 0x5C;
+ public static final int HEADER_LIST = 0x5D;
+ public static final int LOGIN_DATA = 0x5E;
+ public static final int CARDHOLDER_NAME = 0x20; // 0x5F20;
+ public static final int TRACK1_CARD = 0x5F21;
+ public static final int TRACK2_CARD = 0x5F22;
+ public static final int TRACK3_CARD = 0x5F23;
+ public static final int APPLICATION_EXPIRATION_DATE = 0x24; // 0x5F24;
+ public static final int APPLICATION_EFFECTIVE_DATE = 0x25; // 0x5F25;
+ public static final int CARD_EFFECTIVE_DATE = 0x5F26;
+ public static final int INTERCHANGE_CONTROL = 0x5F27;
+ public static final int COUNTRY_CODE = 0x5F28;
+ public static final int INTERCHANGE_PROFILE = 0x29; // 0x5F29;
+ public static final int CURRENCY_CODE = 0x5F2A;
+ public static final int DATE_OF_BIRTH = 0x5F2B;
+ public static final int CARDHOLDER_NATIONALITY = 0x5F2C;
+ public static final int LANGUAGE_PREFERENCES = 0x5F2D;
+ public static final int CARDHOLDER_BIOMETRIC_DATA = 0x5F2E;
+ public static final int PIN_USAGE_POLICY = 0x5F2F;
+ public static final int SERVICE_CODE = 0x5F30;
+ public static final int TRANSACTION_COUNTER = 0x5F32;
+ public static final int TRANSACTION_DATE = 0x5F33;
+ public static final int CARD_SEQUENCE_NUMBER = 0x5F34;
+ public static final int SEX = 0x5F35;
+ public static final int CURRENCY_EXPONENT = 0x5F36;
+ public static final int STATIC_INTERNAL_AUTHENTIFICATION_ONE_STEP = 0x37; // 0x5F37;
+ public static final int SIGNATURE = 0x5F37;
+ public static final int STATIC_INTERNAL_AUTHENTIFICATION_FIRST_DATA = 0x5F38;
+ public static final int STATIC_INTERNAL_AUTHENTIFICATION_SECOND_DATA = 0x5F39;
+ public static final int DYNAMIC_INTERNAL_AUTHENTIFICATION = 0x5F3A;
+ public static final int DYNAMIC_EXTERNAL_AUTHENTIFICATION = 0x5F3B;
+ public static final int DYNAMIC_MUTUAL_AUTHENTIFICATION = 0x5F3C;
+ public static final int CARDHOLDER_PORTRAIT_IMAGE = 0x5F40;
+ public static final int ELEMENT_LIST = 0x5F41;
+ public static final int ADDRESS = 0x5F42;
+ public static final int CARDHOLDER_HANDWRITTEN_SIGNATURE = 0x5F43;
+ public static final int APPLICATION_IMAGE = 0x5F44;
+ public static final int DISPLAY_IMAGE = 0x5F45;
+ public static final int TIMER = 0x5F46;
+ public static final int MESSAGE_REFERENCE = 0x5F47;
+ public static final int CARDHOLDER_PRIVATE_KEY = 0x5F48;
+ public static final int CARDHOLDER_PUBLIC_KEY = 0x5F49;
+ public static final int CERTIFICATION_AUTHORITY_PUBLIC_KEY = 0x5F4A;
+ public static final int DEPRECATED = 0x5F4B;
+ public static final int CERTIFICATE_HOLDER_AUTHORIZATION = 0x5F4C;// Not yet defined in iso7816. The allocation is requested
+ public static final int INTEGRATED_CIRCUIT_MANUFACTURER_ID = 0x5F4D;
+ public static final int CERTIFICATE_CONTENT = 0x5F4E;
+ public static final int UNIFORM_RESOURCE_LOCATOR = 0x5F50;
+ public static final int ANSWER_TO_RESET = 0x5F51;
+ public static final int HISTORICAL_BYTES = 0x5F52;
+ public static final int DIGITAL_SIGNATURE = 0x5F3D;
+ public static final int APPLICATION_TEMPLATE = 0x61;
+ public static final int FCP_TEMPLATE = 0x62;
+ public static final int WRAPPER = 0x63;
+ public static final int FMD_TEMPLATE = 0x64;
+ public static final int CARDHOLDER_RELATIVE_DATA = 0x65;
+ public static final int CARD_DATA = 0x66;
+ public static final int AUTHENTIFICATION_DATA = 0x67;
+ public static final int SPECIAL_USER_REQUIREMENTS = 0x68;
+ public static final int LOGIN_TEMPLATE = 0x6A;
+ public static final int QUALIFIED_NAME = 0x6B;
+ public static final int CARDHOLDER_IMAGE_TEMPLATE = 0x6C;
+ public static final int APPLICATION_IMAGE_TEMPLATE = 0x6D;
+ public static final int APPLICATION_RELATED_DATA = 0x6E;
+ public static final int FCI_TEMPLATE = 0x6F;
+ public static final int DISCRETIONARY_DATA_OBJECTS = 0x73;
+ public static final int COMPATIBLE_TAG_ALLOCATION_AUTHORITY = 0x78;
+ public static final int COEXISTANT_TAG_ALLOCATION_AUTHORITY = 0x79;
+ public static final int SECURITY_SUPPORT_TEMPLATE = 0x7A;
+ public static final int SECURITY_ENVIRONMENT_TEMPLATE = 0x7B;
+ public static final int DYNAMIC_AUTHENTIFICATION_TEMPLATE = 0x7C;
+ public static final int SECURE_MESSAGING_TEMPLATE = 0x7D;
+ public static final int NON_INTERINDUSTRY_DATA_OBJECT_NESTING_TEMPLATE = 0x7E;
+ public static final int DISPLAY_CONTROL = 0x7F20;
+ public static final int CARDHOLDER_CERTIFICATE = 0x21; // 0x7F21;
+ public static final int CV_CERTIFICATE = 0x7F21;
+ public static final int CARDHOLER_REQUIREMENTS_INCLUDED_FEATURES = 0x7F22;
+ public static final int CARDHOLER_REQUIREMENTS_EXCLUDED_FEATURES = 0x7F23;
+ public static final int BIOMETRIC_DATA_TEMPLATE = 0x7F2E;
+ public static final int DIGITAL_SIGNATURE_BLOCK = 0x7F3D;
+ public static final int CARDHOLDER_PRIVATE_KEY_TEMPLATE = 0x7F48;
+ public static final int CARDHOLDER_PUBLIC_KEY_TEMPLATE = 0x49; // 0x7F49;
+ public static final int CERTIFICATE_HOLDER_AUTHORIZATION_TEMPLATE = 0x4C; // 0x7F4C;
+ public static final int CERTIFICATE_CONTENT_TEMPLATE = 0x4E; // 0x7F4E;
+ public static final int CERTIFICATE_BODY = 0x4E; // 0x7F4E;
+ public static final int BIOMETRIC_INFORMATION_TEMPLATE = 0x7F60;
+ public static final int BIOMETRIC_INFORMATION_GROUP_TEMPLATE = 0x7F61;
+
+ public static int getTag(int encodedTag)
+ {
+ /*
+ int i;
+ for (i = 24; i>=0; i-=8) {
+ if (((0xFF<<i) & tag) != 0)
+ return (((0xFF<<i) & tag) >> i);
+ }
+ return 0;
+ */
+ return decodeTag(encodedTag);
+ }
+
+ public static int getTagNo(int tag)
+ {
+ int i;
+ for (i = 24; i >= 0; i -= 8)
+ {
+ if (((0xFF << i) & tag) != 0)
+ {
+ return ((~(0xFF << i)) & tag);
+ }
+ }
+ return 0;
+ }
+
+ public static int encodeTag(DERApplicationSpecific spec)
+ {
+ int retValue = BERTags.APPLICATION;
+ boolean constructed = spec.isConstructed();
+ if (constructed)
+ {
+ retValue |= BERTags.CONSTRUCTED;
+ }
+
+ int tag = spec.getApplicationTag();
+
+ if (tag > 31)
+ {
+ retValue |= 0x1F;
+ retValue <<= 8;
+
+ int currentByte = tag & 0x7F;
+ retValue |= currentByte;
+ tag >>= 7;
+
+ while (tag > 0)
+ {
+ retValue |= 0x80;
+ retValue <<= 8;
+
+ currentByte = tag & 0x7F;
+ tag >>= 7;
+ }
+ }
+ else
+ {
+ retValue |= tag;
+ }
+
+ return retValue;
+ }
+
+ public static int decodeTag(int tag)
+ {
+ int retValue = 0;
+ boolean multiBytes = false;
+ for (int i = 24; i >= 0; i -= 8)
+ {
+ int currentByte = tag >> i & 0xFF;
+ if (currentByte == 0)
+ {
+ continue;
+ }
+
+ if (multiBytes)
+ {
+ retValue <<= 7;
+ retValue |= currentByte & 0x7F;
+ }
+ else if ((currentByte & 0x1F) == 0x1F)
+ {
+ multiBytes = true;
+ }
+ else
+ {
+ return currentByte & 0x1F; // higher order bit are for DER.Constructed and type
+ }
+ }
+ return retValue;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/eac/ECDSAPublicKey.java b/core/src/main/java/org/spongycastle/asn1/eac/ECDSAPublicKey.java
new file mode 100644
index 00000000..c241de2d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/eac/ECDSAPublicKey.java
@@ -0,0 +1,340 @@
+package org.spongycastle.asn1.eac;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+/**
+ * an Iso7816ECDSAPublicKeyStructure structure.
+ * <pre>
+ * Certificate Holder Authorization ::= SEQUENCE {
+ * ASN1TaggedObject primeModulusP; // OPTIONAL
+ * ASN1TaggedObject firstCoefA; // OPTIONAL
+ * ASN1TaggedObject secondCoefB; // OPTIONAL
+ * ASN1TaggedObject basePointG; // OPTIONAL
+ * ASN1TaggedObject orderOfBasePointR; // OPTIONAL
+ * ASN1TaggedObject publicPointY; //REQUIRED
+ * ASN1TaggedObject cofactorF; // OPTIONAL
+ * }
+ * </pre>
+ */
+public class ECDSAPublicKey
+ extends PublicKeyDataObject
+{
+ private ASN1ObjectIdentifier usage;
+ private BigInteger primeModulusP; // OPTIONAL
+ private BigInteger firstCoefA; // OPTIONAL
+ private BigInteger secondCoefB; // OPTIONAL
+ private byte[] basePointG; // OPTIONAL
+ private BigInteger orderOfBasePointR; // OPTIONAL
+ private byte[] publicPointY; //REQUIRED
+ private BigInteger cofactorF; // OPTIONAL
+ private int options;
+ private static final int P = 0x01;
+ private static final int A = 0x02;
+ private static final int B = 0x04;
+ private static final int G = 0x08;
+ private static final int R = 0x10;
+ private static final int Y = 0x20;
+ private static final int F = 0x40;
+
+ ECDSAPublicKey(ASN1Sequence seq)
+ throws IllegalArgumentException
+ {
+ Enumeration en = seq.getObjects();
+
+ this.usage = ASN1ObjectIdentifier.getInstance(en.nextElement());
+
+ options = 0;
+ while (en.hasMoreElements())
+ {
+ Object obj = en.nextElement();
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject to = (ASN1TaggedObject)obj;
+ switch (to.getTagNo())
+ {
+ case 0x1:
+ setPrimeModulusP(UnsignedInteger.getInstance(to).getValue());
+ break;
+ case 0x2:
+ setFirstCoefA(UnsignedInteger.getInstance(to).getValue());
+ break;
+ case 0x3:
+ setSecondCoefB(UnsignedInteger.getInstance(to).getValue());
+ break;
+ case 0x4:
+ setBasePointG(ASN1OctetString.getInstance(to, false));
+ break;
+ case 0x5:
+ setOrderOfBasePointR(UnsignedInteger.getInstance(to).getValue());
+ break;
+ case 0x6:
+ setPublicPointY(ASN1OctetString.getInstance(to, false));
+ break;
+ case 0x7:
+ setCofactorF(UnsignedInteger.getInstance(to).getValue());
+ break;
+ default:
+ options = 0;
+ throw new IllegalArgumentException("Unknown Object Identifier!");
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("Unknown Object Identifier!");
+ }
+ }
+ if (options != 0x20 && options != 0x7F)
+ {
+ throw new IllegalArgumentException("All options must be either present or absent!");
+ }
+ }
+
+ public ECDSAPublicKey(ASN1ObjectIdentifier usage, byte[] ppY)
+ throws IllegalArgumentException
+ {
+ this.usage = usage;
+ setPublicPointY(new DEROctetString(ppY));
+ }
+
+ public ECDSAPublicKey(ASN1ObjectIdentifier usage, BigInteger p, BigInteger a, BigInteger b, byte[] basePoint, BigInteger order, byte[] publicPoint, int cofactor)
+ {
+ this.usage = usage;
+ setPrimeModulusP(p);
+ setFirstCoefA(a);
+ setSecondCoefB(b);
+ setBasePointG(new DEROctetString(basePoint));
+ setOrderOfBasePointR(order);
+ setPublicPointY(new DEROctetString(publicPoint));
+ setCofactorF(BigInteger.valueOf(cofactor));
+ }
+
+ public ASN1ObjectIdentifier getUsage()
+ {
+ return usage;
+ }
+
+ public byte[] getBasePointG()
+ {
+ if ((options & G) != 0)
+ {
+ return basePointG;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ private void setBasePointG(ASN1OctetString basePointG)
+ throws IllegalArgumentException
+ {
+ if ((options & G) == 0)
+ {
+ options |= G;
+ this.basePointG = basePointG.getOctets();
+ }
+ else
+ {
+ throw new IllegalArgumentException("Base Point G already set");
+ }
+ }
+
+ public BigInteger getCofactorF()
+ {
+ if ((options & F) != 0)
+ {
+ return cofactorF;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ private void setCofactorF(BigInteger cofactorF)
+ throws IllegalArgumentException
+ {
+ if ((options & F) == 0)
+ {
+ options |= F;
+ this.cofactorF = cofactorF;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Cofactor F already set");
+ }
+ }
+
+ public BigInteger getFirstCoefA()
+ {
+ if ((options & A) != 0)
+ {
+ return firstCoefA;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ private void setFirstCoefA(BigInteger firstCoefA)
+ throws IllegalArgumentException
+ {
+ if ((options & A) == 0)
+ {
+ options |= A;
+ this.firstCoefA = firstCoefA;
+ }
+ else
+ {
+ throw new IllegalArgumentException("First Coef A already set");
+ }
+ }
+
+ public BigInteger getOrderOfBasePointR()
+ {
+ if ((options & R) != 0)
+ {
+ return orderOfBasePointR;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ private void setOrderOfBasePointR(BigInteger orderOfBasePointR)
+ throws IllegalArgumentException
+ {
+ if ((options & R) == 0)
+ {
+ options |= R;
+ this.orderOfBasePointR = orderOfBasePointR;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Order of base point R already set");
+ }
+ }
+
+ public BigInteger getPrimeModulusP()
+ {
+ if ((options & P) != 0)
+ {
+ return primeModulusP;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ private void setPrimeModulusP(BigInteger primeModulusP)
+ {
+ if ((options & P) == 0)
+ {
+ options |= P;
+ this.primeModulusP = primeModulusP;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Prime Modulus P already set");
+ }
+ }
+
+ public byte[] getPublicPointY()
+ {
+ if ((options & Y) != 0)
+ {
+ return publicPointY;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ private void setPublicPointY(ASN1OctetString publicPointY)
+ throws IllegalArgumentException
+ {
+ if ((options & Y) == 0)
+ {
+ options |= Y;
+ this.publicPointY = publicPointY.getOctets();
+ }
+ else
+ {
+ throw new IllegalArgumentException("Public Point Y already set");
+ }
+ }
+
+ public BigInteger getSecondCoefB()
+ {
+ if ((options & B) != 0)
+ {
+ return secondCoefB;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ private void setSecondCoefB(BigInteger secondCoefB)
+ throws IllegalArgumentException
+ {
+ if ((options & B) == 0)
+ {
+ options |= B;
+ this.secondCoefB = secondCoefB;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Second Coef B already set");
+ }
+ }
+
+ public boolean hasParameters()
+ {
+ return primeModulusP != null;
+ }
+
+ public ASN1EncodableVector getASN1EncodableVector(ASN1ObjectIdentifier oid, boolean publicPointOnly)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(oid);
+
+ if (!publicPointOnly)
+ {
+ v.add(new UnsignedInteger(0x01, getPrimeModulusP()));
+ v.add(new UnsignedInteger(0x02, getFirstCoefA()));
+ v.add(new UnsignedInteger(0x03, getSecondCoefB()));
+ v.add(new DERTaggedObject(false, 0x04, new DEROctetString(getBasePointG())));
+ v.add(new UnsignedInteger(0x05, getOrderOfBasePointR()));
+ }
+ v.add(new DERTaggedObject(false, 0x06, new DEROctetString(getPublicPointY())));
+ if (!publicPointOnly)
+ {
+ v.add(new UnsignedInteger(0x07, getCofactorF()));
+ }
+
+ return v;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERSequence(getASN1EncodableVector(usage, false));
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/eac/Flags.java b/core/src/main/java/org/spongycastle/asn1/eac/Flags.java
new file mode 100644
index 00000000..13b56a93
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/eac/Flags.java
@@ -0,0 +1,96 @@
+package org.spongycastle.asn1.eac;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+
+public class Flags
+{
+
+ int value = 0;
+
+ public Flags()
+ {
+
+ }
+
+ public Flags(int v)
+ {
+ value = v;
+ }
+
+ public void set(int flag)
+ {
+ value |= flag;
+ }
+
+ public boolean isSet(int flag)
+ {
+ return (value & flag) != 0;
+ }
+
+ public int getFlags()
+ {
+ return value;
+ }
+
+ /* Java 1.5
+ String decode(Map<Integer, String> decodeMap)
+ {
+ StringJoiner joiner = new StringJoiner(" ");
+ for (int i : decodeMap.keySet())
+ {
+ if (isSet(i))
+ joiner.add(decodeMap.get(i));
+ }
+ return joiner.toString();
+ }
+ */
+
+ String decode(Hashtable decodeMap)
+ {
+ StringJoiner joiner = new StringJoiner(" ");
+ Enumeration e = decodeMap.keys();
+ while (e.hasMoreElements())
+ {
+ Integer i = (Integer)e.nextElement();
+ if (isSet(i.intValue()))
+ {
+ joiner.add((String)decodeMap.get(i));
+ }
+ }
+ return joiner.toString();
+ }
+
+ private class StringJoiner
+ {
+
+ String mSeparator;
+ boolean First = true;
+ StringBuffer b = new StringBuffer();
+
+ public StringJoiner(String separator)
+ {
+ mSeparator = separator;
+ }
+
+ public void add(String str)
+ {
+ if (First)
+ {
+ First = false;
+ }
+ else
+ {
+ b.append(mSeparator);
+ }
+
+ b.append(str);
+ }
+
+ public String toString()
+ {
+ return b.toString();
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/eac/PackedDate.java b/core/src/main/java/org/spongycastle/asn1/eac/PackedDate.java
new file mode 100644
index 00000000..bdb02271
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/eac/PackedDate.java
@@ -0,0 +1,124 @@
+package org.spongycastle.asn1.eac;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.SimpleTimeZone;
+
+import org.spongycastle.util.Arrays;
+
+/**
+ * EAC encoding date object
+ */
+public class PackedDate
+{
+ private byte[] time;
+
+ public PackedDate(
+ String time)
+ {
+ this.time = convert(time);
+ }
+
+ /**
+ * Base constructor from a java.util.date object.
+ *
+ * @param time a date object representing the time of interest.
+ */
+ public PackedDate(
+ Date time)
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyMMdd'Z'");
+
+ dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
+
+ this.time = convert(dateF.format(time));
+ }
+
+ /**
+ * Base constructor from a java.util.date object. You may need to use this constructor if the default locale
+ * doesn't use a Gregorian calender so that the PackedDate produced is compatible with other ASN.1 implementations.
+ *
+ * @param time a date object representing the time of interest.
+ * @param locale an appropriate Locale for producing an ASN.1 GeneralizedTime value.
+ */
+ public PackedDate(
+ Date time,
+ Locale locale)
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyMMdd'Z'", locale);
+
+ dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
+
+ this.time = convert(dateF.format(time));
+ }
+
+ private byte[] convert(String sTime)
+ {
+ char[] digs = sTime.toCharArray();
+ byte[] date = new byte[6];
+
+ for (int i = 0; i != 6; i++)
+ {
+ date[i] = (byte)(digs[i] - '0');
+ }
+
+ return date;
+ }
+
+ PackedDate(
+ byte[] bytes)
+ {
+ this.time = bytes;
+ }
+
+ /**
+ * return the time as a date based on whatever a 2 digit year will return. For
+ * standardised processing use getAdjustedDate().
+ *
+ * @return the resulting date
+ * @exception java.text.ParseException if the date string cannot be parsed.
+ */
+ public Date getDate()
+ throws ParseException
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMdd");
+
+ return dateF.parse("20" + toString());
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(time);
+ }
+
+ public boolean equals(Object o)
+ {
+ if (!(o instanceof PackedDate))
+ {
+ return false;
+ }
+
+ PackedDate other = (PackedDate)o;
+
+ return Arrays.areEqual(time, other.time);
+ }
+
+ public String toString()
+ {
+ char[] dateC = new char[time.length];
+
+ for (int i = 0; i != dateC.length; i++)
+ {
+ dateC[i] = (char)((time[i] & 0xff) + '0');
+ }
+
+ return new String(dateC);
+ }
+
+ public byte[] getEncoding()
+ {
+ return time;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/eac/PublicKeyDataObject.java b/core/src/main/java/org/spongycastle/asn1/eac/PublicKeyDataObject.java
new file mode 100644
index 00000000..88c6c56c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/eac/PublicKeyDataObject.java
@@ -0,0 +1,35 @@
+package org.spongycastle.asn1.eac;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Sequence;
+
+public abstract class PublicKeyDataObject
+ extends ASN1Object
+{
+ public static PublicKeyDataObject getInstance(Object obj)
+ {
+ if (obj instanceof PublicKeyDataObject)
+ {
+ return (PublicKeyDataObject)obj;
+ }
+ if (obj != null)
+ {
+ ASN1Sequence seq = ASN1Sequence.getInstance(obj);
+ ASN1ObjectIdentifier usage = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+
+ if (usage.on(EACObjectIdentifiers.id_TA_ECDSA))
+ {
+ return new ECDSAPublicKey(seq);
+ }
+ else
+ {
+ return new RSAPublicKey(seq);
+ }
+ }
+
+ return null;
+ }
+
+ public abstract ASN1ObjectIdentifier getUsage();
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/eac/RSAPublicKey.java b/core/src/main/java/org/spongycastle/asn1/eac/RSAPublicKey.java
new file mode 100644
index 00000000..6142c645
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/eac/RSAPublicKey.java
@@ -0,0 +1,120 @@
+package org.spongycastle.asn1.eac;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+
+/**
+ * an Iso7816RSAPublicKeyStructure structure.
+ * <pre>
+ * Certificate Holder Authorization ::= SEQUENCE {
+ * // modulus should be at least 1024bit and a multiple of 512.
+ * DERTaggedObject modulus,
+ * // access rights exponent
+ * DERTaggedObject accessRights,
+ * }
+ * </pre>
+ */
+public class RSAPublicKey
+ extends PublicKeyDataObject
+{
+ private ASN1ObjectIdentifier usage;
+ private BigInteger modulus;
+ private BigInteger exponent;
+ private int valid = 0;
+ private static int modulusValid = 0x01;
+ private static int exponentValid = 0x02;
+
+ RSAPublicKey(ASN1Sequence seq)
+ {
+ Enumeration en = seq.getObjects();
+
+ this.usage = ASN1ObjectIdentifier.getInstance(en.nextElement());
+
+ while (en.hasMoreElements())
+ {
+ UnsignedInteger val = UnsignedInteger.getInstance(en.nextElement());
+
+ switch (val.getTagNo())
+ {
+ case 0x1:
+ setModulus(val);
+ break;
+ case 0x2:
+ setExponent(val);
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown DERTaggedObject :" + val.getTagNo() + "-> not an Iso7816RSAPublicKeyStructure");
+ }
+ }
+ if (valid != 0x3)
+ {
+ throw new IllegalArgumentException("missing argument -> not an Iso7816RSAPublicKeyStructure");
+ }
+ }
+
+ public RSAPublicKey(ASN1ObjectIdentifier usage, BigInteger modulus, BigInteger exponent)
+ {
+ this.usage = usage;
+ this.modulus = modulus;
+ this.exponent = exponent;
+ }
+
+ public ASN1ObjectIdentifier getUsage()
+ {
+ return usage;
+ }
+
+ public BigInteger getModulus()
+ {
+ return modulus;
+ }
+
+ public BigInteger getPublicExponent()
+ {
+ return exponent;
+ }
+
+ private void setModulus(UnsignedInteger modulus)
+ {
+ if ((valid & modulusValid) == 0)
+ {
+ valid |= modulusValid;
+ this.modulus = modulus.getValue();
+ }
+ else
+ {
+ throw new IllegalArgumentException("Modulus already set");
+ }
+ }
+
+ private void setExponent(UnsignedInteger exponent)
+ {
+ if ((valid & exponentValid) == 0)
+ {
+ valid |= exponentValid;
+ this.exponent = exponent.getValue();
+ }
+ else
+ {
+ throw new IllegalArgumentException("Exponent already set");
+ }
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(usage);
+ v.add(new UnsignedInteger(0x01, getModulus()));
+ v.add(new UnsignedInteger(0x02, getPublicExponent()));
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/eac/UnsignedInteger.java b/core/src/main/java/org/spongycastle/asn1/eac/UnsignedInteger.java
new file mode 100644
index 00000000..96fc739a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/eac/UnsignedInteger.java
@@ -0,0 +1,74 @@
+package org.spongycastle.asn1.eac;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERTaggedObject;
+
+public class UnsignedInteger
+ extends ASN1Object
+{
+ private int tagNo;
+ private BigInteger value;
+
+ public UnsignedInteger(int tagNo, BigInteger value)
+ {
+ this.tagNo = tagNo;
+ this.value = value;
+ }
+
+ private UnsignedInteger(ASN1TaggedObject obj)
+ {
+ this.tagNo = obj.getTagNo();
+ this.value = new BigInteger(1, ASN1OctetString.getInstance(obj, false).getOctets());
+ }
+
+ public static UnsignedInteger getInstance(Object obj)
+ {
+ if (obj instanceof UnsignedInteger)
+ {
+ return (UnsignedInteger)obj;
+ }
+ if (obj != null)
+ {
+ return new UnsignedInteger(ASN1TaggedObject.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private byte[] convertValue()
+ {
+ byte[] v = value.toByteArray();
+
+ if (v[0] == 0)
+ {
+ byte[] tmp = new byte[v.length - 1];
+
+ System.arraycopy(v, 1, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+
+ return v;
+ }
+
+ public int getTagNo()
+ {
+ return tagNo;
+ }
+
+ public BigInteger getValue()
+ {
+ return value;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERTaggedObject(false, tagNo, new DEROctetString(convertValue()));
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/CommitmentTypeIdentifier.java b/core/src/main/java/org/spongycastle/asn1/esf/CommitmentTypeIdentifier.java
new file mode 100644
index 00000000..7941bcd0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/CommitmentTypeIdentifier.java
@@ -0,0 +1,14 @@
+package org.spongycastle.asn1.esf;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+
+public interface CommitmentTypeIdentifier
+{
+ public static final ASN1ObjectIdentifier proofOfOrigin = PKCSObjectIdentifiers.id_cti_ets_proofOfOrigin;
+ public static final ASN1ObjectIdentifier proofOfReceipt = PKCSObjectIdentifiers.id_cti_ets_proofOfReceipt;
+ public static final ASN1ObjectIdentifier proofOfDelivery = PKCSObjectIdentifiers.id_cti_ets_proofOfDelivery;
+ public static final ASN1ObjectIdentifier proofOfSender = PKCSObjectIdentifiers.id_cti_ets_proofOfSender;
+ public static final ASN1ObjectIdentifier proofOfApproval = PKCSObjectIdentifiers.id_cti_ets_proofOfApproval;
+ public static final ASN1ObjectIdentifier proofOfCreation = PKCSObjectIdentifiers.id_cti_ets_proofOfCreation;
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/CommitmentTypeIndication.java b/core/src/main/java/org/spongycastle/asn1/esf/CommitmentTypeIndication.java
new file mode 100644
index 00000000..1caec133
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/CommitmentTypeIndication.java
@@ -0,0 +1,83 @@
+package org.spongycastle.asn1.esf;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class CommitmentTypeIndication
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier commitmentTypeId;
+ private ASN1Sequence commitmentTypeQualifier;
+
+ private CommitmentTypeIndication(
+ ASN1Sequence seq)
+ {
+ commitmentTypeId = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+
+ if (seq.size() > 1)
+ {
+ commitmentTypeQualifier = (ASN1Sequence)seq.getObjectAt(1);
+ }
+ }
+
+ public CommitmentTypeIndication(
+ ASN1ObjectIdentifier commitmentTypeId)
+ {
+ this.commitmentTypeId = commitmentTypeId;
+ }
+
+ public CommitmentTypeIndication(
+ ASN1ObjectIdentifier commitmentTypeId,
+ ASN1Sequence commitmentTypeQualifier)
+ {
+ this.commitmentTypeId = commitmentTypeId;
+ this.commitmentTypeQualifier = commitmentTypeQualifier;
+ }
+
+ public static CommitmentTypeIndication getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof CommitmentTypeIndication)
+ {
+ return (CommitmentTypeIndication)obj;
+ }
+
+ return new CommitmentTypeIndication(ASN1Sequence.getInstance(obj));
+ }
+
+ public ASN1ObjectIdentifier getCommitmentTypeId()
+ {
+ return commitmentTypeId;
+ }
+
+ public ASN1Sequence getCommitmentTypeQualifier()
+ {
+ return commitmentTypeQualifier;
+ }
+
+ /**
+ * <pre>
+ * CommitmentTypeIndication ::= SEQUENCE {
+ * commitmentTypeId CommitmentTypeIdentifier,
+ * commitmentTypeQualifier SEQUENCE SIZE (1..MAX) OF
+ * CommitmentTypeQualifier OPTIONAL }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(commitmentTypeId);
+
+ if (commitmentTypeQualifier != null)
+ {
+ v.add(commitmentTypeQualifier);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/CommitmentTypeQualifier.java b/core/src/main/java/org/spongycastle/asn1/esf/CommitmentTypeQualifier.java
new file mode 100644
index 00000000..d4b909c2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/CommitmentTypeQualifier.java
@@ -0,0 +1,108 @@
+package org.spongycastle.asn1.esf;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * Commitment type qualifiers, used in the Commitment-Type-Indication attribute (RFC3126).
+ *
+ * <pre>
+ * CommitmentTypeQualifier ::= SEQUENCE {
+ * commitmentTypeIdentifier CommitmentTypeIdentifier,
+ * qualifier ANY DEFINED BY commitmentTypeIdentifier OPTIONAL }
+ * </pre>
+ */
+public class CommitmentTypeQualifier
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier commitmentTypeIdentifier;
+ private ASN1Encodable qualifier;
+
+ /**
+ * Creates a new <code>CommitmentTypeQualifier</code> instance.
+ *
+ * @param commitmentTypeIdentifier a <code>CommitmentTypeIdentifier</code> value
+ */
+ public CommitmentTypeQualifier(
+ ASN1ObjectIdentifier commitmentTypeIdentifier)
+ {
+ this(commitmentTypeIdentifier, null);
+ }
+
+ /**
+ * Creates a new <code>CommitmentTypeQualifier</code> instance.
+ *
+ * @param commitmentTypeIdentifier a <code>CommitmentTypeIdentifier</code> value
+ * @param qualifier the qualifier, defined by the above field.
+ */
+ public CommitmentTypeQualifier(
+ ASN1ObjectIdentifier commitmentTypeIdentifier,
+ ASN1Encodable qualifier)
+ {
+ this.commitmentTypeIdentifier = commitmentTypeIdentifier;
+ this.qualifier = qualifier;
+ }
+
+ /**
+ * Creates a new <code>CommitmentTypeQualifier</code> instance.
+ *
+ * @param as <code>CommitmentTypeQualifier</code> structure
+ * encoded as an ASN1Sequence.
+ */
+ private CommitmentTypeQualifier(
+ ASN1Sequence as)
+ {
+ commitmentTypeIdentifier = (ASN1ObjectIdentifier)as.getObjectAt(0);
+
+ if (as.size() > 1)
+ {
+ qualifier = as.getObjectAt(1);
+ }
+ }
+
+ public static CommitmentTypeQualifier getInstance(Object as)
+ {
+ if (as instanceof CommitmentTypeQualifier)
+ {
+ return (CommitmentTypeQualifier)as;
+ }
+ else if (as != null)
+ {
+ return new CommitmentTypeQualifier(ASN1Sequence.getInstance(as));
+ }
+
+ return null;
+ }
+
+ public ASN1ObjectIdentifier getCommitmentTypeIdentifier()
+ {
+ return commitmentTypeIdentifier;
+ }
+
+ public ASN1Encodable getQualifier()
+ {
+ return qualifier;
+ }
+
+ /**
+ * Returns a DER-encodable representation of this instance.
+ *
+ * @return a <code>ASN1Primitive</code> value
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector dev = new ASN1EncodableVector();
+ dev.add(commitmentTypeIdentifier);
+ if (qualifier != null)
+ {
+ dev.add(qualifier);
+ }
+
+ return new DERSequence(dev);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/CompleteRevocationRefs.java b/core/src/main/java/org/spongycastle/asn1/esf/CompleteRevocationRefs.java
new file mode 100644
index 00000000..1fb4771b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/CompleteRevocationRefs.java
@@ -0,0 +1,65 @@
+package org.spongycastle.asn1.esf;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * <pre>
+ * CompleteRevocationRefs ::= SEQUENCE OF CrlOcspRef
+ * </pre>
+ */
+public class CompleteRevocationRefs
+ extends ASN1Object
+{
+
+ private ASN1Sequence crlOcspRefs;
+
+ public static CompleteRevocationRefs getInstance(Object obj)
+ {
+ if (obj instanceof CompleteRevocationRefs)
+ {
+ return (CompleteRevocationRefs)obj;
+ }
+ else if (obj != null)
+ {
+ return new CompleteRevocationRefs(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private CompleteRevocationRefs(ASN1Sequence seq)
+ {
+ Enumeration seqEnum = seq.getObjects();
+ while (seqEnum.hasMoreElements())
+ {
+ CrlOcspRef.getInstance(seqEnum.nextElement());
+ }
+ this.crlOcspRefs = seq;
+ }
+
+ public CompleteRevocationRefs(CrlOcspRef[] crlOcspRefs)
+ {
+ this.crlOcspRefs = new DERSequence(crlOcspRefs);
+ }
+
+ public CrlOcspRef[] getCrlOcspRefs()
+ {
+ CrlOcspRef[] result = new CrlOcspRef[this.crlOcspRefs.size()];
+ for (int idx = 0; idx < result.length; idx++)
+ {
+ result[idx] = CrlOcspRef.getInstance(this.crlOcspRefs
+ .getObjectAt(idx));
+ }
+ return result;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return this.crlOcspRefs;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/CrlIdentifier.java b/core/src/main/java/org/spongycastle/asn1/esf/CrlIdentifier.java
new file mode 100644
index 00000000..10968b97
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/CrlIdentifier.java
@@ -0,0 +1,106 @@
+package org.spongycastle.asn1.esf;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1UTCTime;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x500.X500Name;
+
+/**
+ * <pre>
+ * CrlIdentifier ::= SEQUENCE
+ * {
+ * crlissuer Name,
+ * crlIssuedTime UTCTime,
+ * crlNumber INTEGER OPTIONAL
+ * }
+ * </pre>
+ */
+public class CrlIdentifier
+ extends ASN1Object
+{
+ private X500Name crlIssuer;
+ private ASN1UTCTime crlIssuedTime;
+ private ASN1Integer crlNumber;
+
+ public static CrlIdentifier getInstance(Object obj)
+ {
+ if (obj instanceof CrlIdentifier)
+ {
+ return (CrlIdentifier)obj;
+ }
+ else if (obj != null)
+ {
+ return new CrlIdentifier(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private CrlIdentifier(ASN1Sequence seq)
+ {
+ if (seq.size() < 2 || seq.size() > 3)
+ {
+ throw new IllegalArgumentException();
+ }
+ this.crlIssuer = X500Name.getInstance(seq.getObjectAt(0));
+ this.crlIssuedTime = ASN1UTCTime.getInstance(seq.getObjectAt(1));
+ if (seq.size() > 2)
+ {
+ this.crlNumber = ASN1Integer.getInstance(seq.getObjectAt(2));
+ }
+ }
+
+ public CrlIdentifier(X500Name crlIssuer, ASN1UTCTime crlIssuedTime)
+ {
+ this(crlIssuer, crlIssuedTime, null);
+ }
+
+ public CrlIdentifier(X500Name crlIssuer, ASN1UTCTime crlIssuedTime,
+ BigInteger crlNumber)
+ {
+ this.crlIssuer = crlIssuer;
+ this.crlIssuedTime = crlIssuedTime;
+ if (null != crlNumber)
+ {
+ this.crlNumber = new ASN1Integer(crlNumber);
+ }
+ }
+
+ public X500Name getCrlIssuer()
+ {
+ return this.crlIssuer;
+ }
+
+ public ASN1UTCTime getCrlIssuedTime()
+ {
+ return this.crlIssuedTime;
+ }
+
+ public BigInteger getCrlNumber()
+ {
+ if (null == this.crlNumber)
+ {
+ return null;
+ }
+ return this.crlNumber.getValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(this.crlIssuer.toASN1Primitive());
+ v.add(this.crlIssuedTime);
+ if (null != this.crlNumber)
+ {
+ v.add(this.crlNumber);
+ }
+ return new DERSequence(v);
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/CrlListID.java b/core/src/main/java/org/spongycastle/asn1/esf/CrlListID.java
new file mode 100644
index 00000000..f474d833
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/CrlListID.java
@@ -0,0 +1,66 @@
+package org.spongycastle.asn1.esf;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * <pre>
+ * CRLListID ::= SEQUENCE {
+ * crls SEQUENCE OF CrlValidatedID }
+ * </pre>
+ */
+public class CrlListID
+ extends ASN1Object
+{
+
+ private ASN1Sequence crls;
+
+ public static CrlListID getInstance(Object obj)
+ {
+ if (obj instanceof CrlListID)
+ {
+ return (CrlListID)obj;
+ }
+ else if (obj != null)
+ {
+ return new CrlListID(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private CrlListID(ASN1Sequence seq)
+ {
+ this.crls = (ASN1Sequence)seq.getObjectAt(0);
+ Enumeration e = this.crls.getObjects();
+ while (e.hasMoreElements())
+ {
+ CrlValidatedID.getInstance(e.nextElement());
+ }
+ }
+
+ public CrlListID(CrlValidatedID[] crls)
+ {
+ this.crls = new DERSequence(crls);
+ }
+
+ public CrlValidatedID[] getCrls()
+ {
+ CrlValidatedID[] result = new CrlValidatedID[this.crls.size()];
+ for (int idx = 0; idx < result.length; idx++)
+ {
+ result[idx] = CrlValidatedID
+ .getInstance(this.crls.getObjectAt(idx));
+ }
+ return result;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERSequence(this.crls);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/CrlOcspRef.java b/core/src/main/java/org/spongycastle/asn1/esf/CrlOcspRef.java
new file mode 100644
index 00000000..6d57769f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/CrlOcspRef.java
@@ -0,0 +1,106 @@
+package org.spongycastle.asn1.esf;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+/**
+ * <pre>
+ * CrlOcspRef ::= SEQUENCE {
+ * crlids [0] CRLListID OPTIONAL,
+ * ocspids [1] OcspListID OPTIONAL,
+ * otherRev [2] OtherRevRefs OPTIONAL
+ * }
+ * </pre>
+ */
+public class CrlOcspRef
+ extends ASN1Object
+{
+
+ private CrlListID crlids;
+ private OcspListID ocspids;
+ private OtherRevRefs otherRev;
+
+ public static CrlOcspRef getInstance(Object obj)
+ {
+ if (obj instanceof CrlOcspRef)
+ {
+ return (CrlOcspRef)obj;
+ }
+ else if (obj != null)
+ {
+ return new CrlOcspRef(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private CrlOcspRef(ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+ while (e.hasMoreElements())
+ {
+ DERTaggedObject o = (DERTaggedObject)e.nextElement();
+ switch (o.getTagNo())
+ {
+ case 0:
+ this.crlids = CrlListID.getInstance(o.getObject());
+ break;
+ case 1:
+ this.ocspids = OcspListID.getInstance(o.getObject());
+ break;
+ case 2:
+ this.otherRev = OtherRevRefs.getInstance(o.getObject());
+ break;
+ default:
+ throw new IllegalArgumentException("illegal tag");
+ }
+ }
+ }
+
+ public CrlOcspRef(CrlListID crlids, OcspListID ocspids,
+ OtherRevRefs otherRev)
+ {
+ this.crlids = crlids;
+ this.ocspids = ocspids;
+ this.otherRev = otherRev;
+ }
+
+ public CrlListID getCrlids()
+ {
+ return this.crlids;
+ }
+
+ public OcspListID getOcspids()
+ {
+ return this.ocspids;
+ }
+
+ public OtherRevRefs getOtherRev()
+ {
+ return this.otherRev;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ if (null != this.crlids)
+ {
+ v.add(new DERTaggedObject(true, 0, this.crlids.toASN1Primitive()));
+ }
+ if (null != this.ocspids)
+ {
+ v.add(new DERTaggedObject(true, 1, this.ocspids.toASN1Primitive()));
+ }
+ if (null != this.otherRev)
+ {
+ v.add(new DERTaggedObject(true, 2, this.otherRev.toASN1Primitive()));
+ }
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/CrlValidatedID.java b/core/src/main/java/org/spongycastle/asn1/esf/CrlValidatedID.java
new file mode 100644
index 00000000..32f12284
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/CrlValidatedID.java
@@ -0,0 +1,82 @@
+package org.spongycastle.asn1.esf;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * <pre>
+ * CrlValidatedID ::= SEQUENCE {
+ * crlHash OtherHash,
+ * crlIdentifier CrlIdentifier OPTIONAL }
+ * </pre>
+ */
+public class CrlValidatedID
+ extends ASN1Object
+{
+
+ private OtherHash crlHash;
+ private CrlIdentifier crlIdentifier;
+
+ public static CrlValidatedID getInstance(Object obj)
+ {
+ if (obj instanceof CrlValidatedID)
+ {
+ return (CrlValidatedID)obj;
+ }
+ else if (obj != null)
+ {
+ return new CrlValidatedID(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private CrlValidatedID(ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ this.crlHash = OtherHash.getInstance(seq.getObjectAt(0));
+ if (seq.size() > 1)
+ {
+ this.crlIdentifier = CrlIdentifier.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ public CrlValidatedID(OtherHash crlHash)
+ {
+ this(crlHash, null);
+ }
+
+ public CrlValidatedID(OtherHash crlHash, CrlIdentifier crlIdentifier)
+ {
+ this.crlHash = crlHash;
+ this.crlIdentifier = crlIdentifier;
+ }
+
+ public OtherHash getCrlHash()
+ {
+ return this.crlHash;
+ }
+
+ public CrlIdentifier getCrlIdentifier()
+ {
+ return this.crlIdentifier;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(this.crlHash.toASN1Primitive());
+ if (null != this.crlIdentifier)
+ {
+ v.add(this.crlIdentifier.toASN1Primitive());
+ }
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/ESFAttributes.java b/core/src/main/java/org/spongycastle/asn1/esf/ESFAttributes.java
new file mode 100644
index 00000000..2d7d2e87
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/ESFAttributes.java
@@ -0,0 +1,22 @@
+package org.spongycastle.asn1.esf;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+
+public interface ESFAttributes
+{
+ public static final ASN1ObjectIdentifier sigPolicyId = PKCSObjectIdentifiers.id_aa_ets_sigPolicyId;
+ public static final ASN1ObjectIdentifier commitmentType = PKCSObjectIdentifiers.id_aa_ets_commitmentType;
+ public static final ASN1ObjectIdentifier signerLocation = PKCSObjectIdentifiers.id_aa_ets_signerLocation;
+ public static final ASN1ObjectIdentifier signerAttr = PKCSObjectIdentifiers.id_aa_ets_signerAttr;
+ public static final ASN1ObjectIdentifier otherSigCert = PKCSObjectIdentifiers.id_aa_ets_otherSigCert;
+ public static final ASN1ObjectIdentifier contentTimestamp = PKCSObjectIdentifiers.id_aa_ets_contentTimestamp;
+ public static final ASN1ObjectIdentifier certificateRefs = PKCSObjectIdentifiers.id_aa_ets_certificateRefs;
+ public static final ASN1ObjectIdentifier revocationRefs = PKCSObjectIdentifiers.id_aa_ets_revocationRefs;
+ public static final ASN1ObjectIdentifier certValues = PKCSObjectIdentifiers.id_aa_ets_certValues;
+ public static final ASN1ObjectIdentifier revocationValues = PKCSObjectIdentifiers.id_aa_ets_revocationValues;
+ public static final ASN1ObjectIdentifier escTimeStamp = PKCSObjectIdentifiers.id_aa_ets_escTimeStamp;
+ public static final ASN1ObjectIdentifier certCRLTimestamp = PKCSObjectIdentifiers.id_aa_ets_certCRLTimestamp;
+ public static final ASN1ObjectIdentifier archiveTimestamp = PKCSObjectIdentifiers.id_aa_ets_archiveTimestamp;
+ public static final ASN1ObjectIdentifier archiveTimestampV2 = PKCSObjectIdentifiers.id_aa.branch("48");
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/OcspIdentifier.java b/core/src/main/java/org/spongycastle/asn1/esf/OcspIdentifier.java
new file mode 100644
index 00000000..80989249
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/OcspIdentifier.java
@@ -0,0 +1,73 @@
+package org.spongycastle.asn1.esf;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.ocsp.ResponderID;
+
+/**
+ * <pre>
+ * OcspIdentifier ::= SEQUENCE {
+ * ocspResponderID ResponderID, -- As in OCSP response data
+ * producedAt GeneralizedTime -- As in OCSP response data
+ * }
+ * </pre>
+ */
+public class OcspIdentifier
+ extends ASN1Object
+{
+ private ResponderID ocspResponderID;
+ private ASN1GeneralizedTime producedAt;
+
+ public static OcspIdentifier getInstance(Object obj)
+ {
+ if (obj instanceof OcspIdentifier)
+ {
+ return (OcspIdentifier)obj;
+ }
+ else if (obj != null)
+ {
+ return new OcspIdentifier(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private OcspIdentifier(ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ this.ocspResponderID = ResponderID.getInstance(seq.getObjectAt(0));
+ this.producedAt = (ASN1GeneralizedTime)seq.getObjectAt(1);
+ }
+
+ public OcspIdentifier(ResponderID ocspResponderID, ASN1GeneralizedTime producedAt)
+ {
+ this.ocspResponderID = ocspResponderID;
+ this.producedAt = producedAt;
+ }
+
+ public ResponderID getOcspResponderID()
+ {
+ return this.ocspResponderID;
+ }
+
+ public ASN1GeneralizedTime getProducedAt()
+ {
+ return this.producedAt;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(this.ocspResponderID);
+ v.add(this.producedAt);
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/OcspListID.java b/core/src/main/java/org/spongycastle/asn1/esf/OcspListID.java
new file mode 100644
index 00000000..d0e2a5ba
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/OcspListID.java
@@ -0,0 +1,72 @@
+package org.spongycastle.asn1.esf;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * <pre>
+ * OcspListID ::= SEQUENCE {
+ * ocspResponses SEQUENCE OF OcspResponsesID
+ * }
+ * </pre>
+ */
+public class OcspListID
+ extends ASN1Object
+{
+ private ASN1Sequence ocspResponses;
+
+ public static OcspListID getInstance(Object obj)
+ {
+ if (obj instanceof OcspListID)
+ {
+ return (OcspListID)obj;
+ }
+ else if (obj != null)
+ {
+ return new OcspListID(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private OcspListID(ASN1Sequence seq)
+ {
+ if (seq.size() != 1)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ this.ocspResponses = (ASN1Sequence)seq.getObjectAt(0);
+ Enumeration e = this.ocspResponses.getObjects();
+ while (e.hasMoreElements())
+ {
+ OcspResponsesID.getInstance(e.nextElement());
+ }
+ }
+
+ public OcspListID(OcspResponsesID[] ocspResponses)
+ {
+ this.ocspResponses = new DERSequence(ocspResponses);
+ }
+
+ public OcspResponsesID[] getOcspResponses()
+ {
+ OcspResponsesID[] result = new OcspResponsesID[this.ocspResponses
+ .size()];
+ for (int idx = 0; idx < result.length; idx++)
+ {
+ result[idx] = OcspResponsesID.getInstance(this.ocspResponses
+ .getObjectAt(idx));
+ }
+ return result;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERSequence(this.ocspResponses);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/OcspResponsesID.java b/core/src/main/java/org/spongycastle/asn1/esf/OcspResponsesID.java
new file mode 100644
index 00000000..4dc0be1e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/OcspResponsesID.java
@@ -0,0 +1,83 @@
+package org.spongycastle.asn1.esf;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * <pre>
+ * OcspResponsesID ::= SEQUENCE {
+ * ocspIdentifier OcspIdentifier,
+ * ocspRepHash OtherHash OPTIONAL
+ * }
+ * </pre>
+ */
+public class OcspResponsesID
+ extends ASN1Object
+{
+
+ private OcspIdentifier ocspIdentifier;
+ private OtherHash ocspRepHash;
+
+ public static OcspResponsesID getInstance(Object obj)
+ {
+ if (obj instanceof OcspResponsesID)
+ {
+ return (OcspResponsesID)obj;
+ }
+ else if (obj != null)
+ {
+ return new OcspResponsesID(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private OcspResponsesID(ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ this.ocspIdentifier = OcspIdentifier.getInstance(seq.getObjectAt(0));
+ if (seq.size() > 1)
+ {
+ this.ocspRepHash = OtherHash.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ public OcspResponsesID(OcspIdentifier ocspIdentifier)
+ {
+ this(ocspIdentifier, null);
+ }
+
+ public OcspResponsesID(OcspIdentifier ocspIdentifier, OtherHash ocspRepHash)
+ {
+ this.ocspIdentifier = ocspIdentifier;
+ this.ocspRepHash = ocspRepHash;
+ }
+
+ public OcspIdentifier getOcspIdentifier()
+ {
+ return this.ocspIdentifier;
+ }
+
+ public OtherHash getOcspRepHash()
+ {
+ return this.ocspRepHash;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(this.ocspIdentifier);
+ if (null != this.ocspRepHash)
+ {
+ v.add(this.ocspRepHash);
+ }
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/OtherHash.java b/core/src/main/java/org/spongycastle/asn1/esf/OtherHash.java
new file mode 100644
index 00000000..2b8a355e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/OtherHash.java
@@ -0,0 +1,81 @@
+package org.spongycastle.asn1.esf;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.oiw.OIWObjectIdentifiers;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * <pre>
+ * OtherHash ::= CHOICE {
+ * sha1Hash OtherHashValue, -- This contains a SHA-1 hash
+ * otherHash OtherHashAlgAndValue
+ * }
+ * </pre>
+ */
+public class OtherHash
+ extends ASN1Object
+ implements ASN1Choice
+{
+
+ private ASN1OctetString sha1Hash;
+ private OtherHashAlgAndValue otherHash;
+
+ public static OtherHash getInstance(Object obj)
+ {
+ if (obj instanceof OtherHash)
+ {
+ return (OtherHash)obj;
+ }
+ if (obj instanceof ASN1OctetString)
+ {
+ return new OtherHash((ASN1OctetString)obj);
+ }
+ return new OtherHash(OtherHashAlgAndValue.getInstance(obj));
+ }
+
+ private OtherHash(ASN1OctetString sha1Hash)
+ {
+ this.sha1Hash = sha1Hash;
+ }
+
+ public OtherHash(OtherHashAlgAndValue otherHash)
+ {
+ this.otherHash = otherHash;
+ }
+
+ public OtherHash(byte[] sha1Hash)
+ {
+ this.sha1Hash = new DEROctetString(sha1Hash);
+ }
+
+ public AlgorithmIdentifier getHashAlgorithm()
+ {
+ if (null == this.otherHash)
+ {
+ return new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1);
+ }
+ return this.otherHash.getHashAlgorithm();
+ }
+
+ public byte[] getHashValue()
+ {
+ if (null == this.otherHash)
+ {
+ return this.sha1Hash.getOctets();
+ }
+ return this.otherHash.getHashValue().getOctets();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (null == this.otherHash)
+ {
+ return this.sha1Hash;
+ }
+ return this.otherHash.toASN1Primitive();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/OtherHashAlgAndValue.java b/core/src/main/java/org/spongycastle/asn1/esf/OtherHashAlgAndValue.java
new file mode 100644
index 00000000..6c445bf4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/OtherHashAlgAndValue.java
@@ -0,0 +1,81 @@
+package org.spongycastle.asn1.esf;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+public class OtherHashAlgAndValue
+ extends ASN1Object
+{
+ private AlgorithmIdentifier hashAlgorithm;
+ private ASN1OctetString hashValue;
+
+
+ public static OtherHashAlgAndValue getInstance(
+ Object obj)
+ {
+ if (obj instanceof OtherHashAlgAndValue)
+ {
+ return (OtherHashAlgAndValue) obj;
+ }
+ else if (obj != null)
+ {
+ return new OtherHashAlgAndValue(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private OtherHashAlgAndValue(
+ ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ hashAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(0));
+ hashValue = ASN1OctetString.getInstance(seq.getObjectAt(1));
+ }
+
+ public OtherHashAlgAndValue(
+ AlgorithmIdentifier hashAlgorithm,
+ ASN1OctetString hashValue)
+ {
+ this.hashAlgorithm = hashAlgorithm;
+ this.hashValue = hashValue;
+ }
+
+ public AlgorithmIdentifier getHashAlgorithm()
+ {
+ return hashAlgorithm;
+ }
+
+ public ASN1OctetString getHashValue()
+ {
+ return hashValue;
+ }
+
+ /**
+ * <pre>
+ * OtherHashAlgAndValue ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * hashValue OtherHashValue }
+ *
+ * OtherHashValue ::= OCTET STRING
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(hashAlgorithm);
+ v.add(hashValue);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/OtherRevRefs.java b/core/src/main/java/org/spongycastle/asn1/esf/OtherRevRefs.java
new file mode 100644
index 00000000..82d449d0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/OtherRevRefs.java
@@ -0,0 +1,87 @@
+package org.spongycastle.asn1.esf;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Encoding;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * <pre>
+ * OtherRevRefs ::= SEQUENCE {
+ * otherRevRefType OtherRevRefType,
+ * otherRevRefs ANY DEFINED BY otherRevRefType
+ * }
+ *
+ * OtherRevRefType ::= OBJECT IDENTIFIER
+ * </pre>
+ */
+public class OtherRevRefs
+ extends ASN1Object
+{
+
+ private ASN1ObjectIdentifier otherRevRefType;
+ private ASN1Encodable otherRevRefs;
+
+ public static OtherRevRefs getInstance(Object obj)
+ {
+ if (obj instanceof OtherRevRefs)
+ {
+ return (OtherRevRefs)obj;
+ }
+ else if (obj != null)
+ {
+ return new OtherRevRefs(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private OtherRevRefs(ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ this.otherRevRefType = new ASN1ObjectIdentifier(((ASN1ObjectIdentifier)seq.getObjectAt(0)).getId());
+ try
+ {
+ this.otherRevRefs = ASN1Primitive.fromByteArray(seq.getObjectAt(1)
+ .toASN1Primitive().getEncoded(ASN1Encoding.DER));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException();
+ }
+ }
+
+ public OtherRevRefs(ASN1ObjectIdentifier otherRevRefType, ASN1Encodable otherRevRefs)
+ {
+ this.otherRevRefType = otherRevRefType;
+ this.otherRevRefs = otherRevRefs;
+ }
+
+ public ASN1ObjectIdentifier getOtherRevRefType()
+ {
+ return this.otherRevRefType;
+ }
+
+ public ASN1Encodable getOtherRevRefs()
+ {
+ return this.otherRevRefs;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(this.otherRevRefType);
+ v.add(this.otherRevRefs);
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/OtherRevVals.java b/core/src/main/java/org/spongycastle/asn1/esf/OtherRevVals.java
new file mode 100644
index 00000000..bd26799e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/OtherRevVals.java
@@ -0,0 +1,89 @@
+package org.spongycastle.asn1.esf;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Encoding;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * <pre>
+ * OtherRevVals ::= SEQUENCE {
+ * otherRevValType OtherRevValType,
+ * otherRevVals ANY DEFINED BY OtherRevValType
+ * }
+ *
+ * OtherRevValType ::= OBJECT IDENTIFIER
+ * </pre>
+ */
+public class OtherRevVals
+ extends ASN1Object
+{
+
+ private ASN1ObjectIdentifier otherRevValType;
+
+ private ASN1Encodable otherRevVals;
+
+ public static OtherRevVals getInstance(Object obj)
+ {
+ if (obj instanceof OtherRevVals)
+ {
+ return (OtherRevVals)obj;
+ }
+ if (obj != null)
+ {
+ return new OtherRevVals(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private OtherRevVals(ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ this.otherRevValType = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ try
+ {
+ this.otherRevVals = ASN1Primitive.fromByteArray(seq.getObjectAt(1)
+ .toASN1Primitive().getEncoded(ASN1Encoding.DER));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException();
+ }
+ }
+
+ public OtherRevVals(ASN1ObjectIdentifier otherRevValType,
+ ASN1Encodable otherRevVals)
+ {
+ this.otherRevValType = otherRevValType;
+ this.otherRevVals = otherRevVals;
+ }
+
+ public ASN1ObjectIdentifier getOtherRevValType()
+ {
+ return this.otherRevValType;
+ }
+
+ public ASN1Encodable getOtherRevVals()
+ {
+ return this.otherRevVals;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(this.otherRevValType);
+ v.add(this.otherRevVals);
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/RevocationValues.java b/core/src/main/java/org/spongycastle/asn1/esf/RevocationValues.java
new file mode 100644
index 00000000..87e0217d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/RevocationValues.java
@@ -0,0 +1,151 @@
+package org.spongycastle.asn1.esf;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.ocsp.BasicOCSPResponse;
+import org.spongycastle.asn1.x509.CertificateList;
+
+/**
+ * <pre>
+ * RevocationValues ::= SEQUENCE {
+ * crlVals [0] SEQUENCE OF CertificateList OPTIONAL,
+ * ocspVals [1] SEQUENCE OF BasicOCSPResponse OPTIONAL,
+ * otherRevVals [2] OtherRevVals OPTIONAL}
+ * </pre>
+ */
+public class RevocationValues
+ extends ASN1Object
+{
+
+ private ASN1Sequence crlVals;
+ private ASN1Sequence ocspVals;
+ private OtherRevVals otherRevVals;
+
+ public static RevocationValues getInstance(Object obj)
+ {
+ if (obj instanceof RevocationValues)
+ {
+ return (RevocationValues)obj;
+ }
+ else if (obj != null)
+ {
+ return new RevocationValues(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private RevocationValues(ASN1Sequence seq)
+ {
+ if (seq.size() > 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ Enumeration e = seq.getObjects();
+ while (e.hasMoreElements())
+ {
+ DERTaggedObject o = (DERTaggedObject)e.nextElement();
+ switch (o.getTagNo())
+ {
+ case 0:
+ ASN1Sequence crlValsSeq = (ASN1Sequence)o.getObject();
+ Enumeration crlValsEnum = crlValsSeq.getObjects();
+ while (crlValsEnum.hasMoreElements())
+ {
+ CertificateList.getInstance(crlValsEnum.nextElement());
+ }
+ this.crlVals = crlValsSeq;
+ break;
+ case 1:
+ ASN1Sequence ocspValsSeq = (ASN1Sequence)o.getObject();
+ Enumeration ocspValsEnum = ocspValsSeq.getObjects();
+ while (ocspValsEnum.hasMoreElements())
+ {
+ BasicOCSPResponse.getInstance(ocspValsEnum.nextElement());
+ }
+ this.ocspVals = ocspValsSeq;
+ break;
+ case 2:
+ this.otherRevVals = OtherRevVals.getInstance(o.getObject());
+ break;
+ default:
+ throw new IllegalArgumentException("invalid tag: "
+ + o.getTagNo());
+ }
+ }
+ }
+
+ public RevocationValues(CertificateList[] crlVals,
+ BasicOCSPResponse[] ocspVals, OtherRevVals otherRevVals)
+ {
+ if (null != crlVals)
+ {
+ this.crlVals = new DERSequence(crlVals);
+ }
+ if (null != ocspVals)
+ {
+ this.ocspVals = new DERSequence(ocspVals);
+ }
+ this.otherRevVals = otherRevVals;
+ }
+
+ public CertificateList[] getCrlVals()
+ {
+ if (null == this.crlVals)
+ {
+ return new CertificateList[0];
+ }
+ CertificateList[] result = new CertificateList[this.crlVals.size()];
+ for (int idx = 0; idx < result.length; idx++)
+ {
+ result[idx] = CertificateList.getInstance(this.crlVals
+ .getObjectAt(idx));
+ }
+ return result;
+ }
+
+ public BasicOCSPResponse[] getOcspVals()
+ {
+ if (null == this.ocspVals)
+ {
+ return new BasicOCSPResponse[0];
+ }
+ BasicOCSPResponse[] result = new BasicOCSPResponse[this.ocspVals.size()];
+ for (int idx = 0; idx < result.length; idx++)
+ {
+ result[idx] = BasicOCSPResponse.getInstance(this.ocspVals
+ .getObjectAt(idx));
+ }
+ return result;
+ }
+
+ public OtherRevVals getOtherRevVals()
+ {
+ return this.otherRevVals;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ if (null != this.crlVals)
+ {
+ v.add(new DERTaggedObject(true, 0, this.crlVals));
+ }
+ if (null != this.ocspVals)
+ {
+ v.add(new DERTaggedObject(true, 1, this.ocspVals));
+ }
+ if (null != this.otherRevVals)
+ {
+ v.add(new DERTaggedObject(true, 2, this.otherRevVals.toASN1Primitive()));
+ }
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/SPUserNotice.java b/core/src/main/java/org/spongycastle/asn1/esf/SPUserNotice.java
new file mode 100644
index 00000000..759227fd
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/SPUserNotice.java
@@ -0,0 +1,99 @@
+package org.spongycastle.asn1.esf;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1String;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.DisplayText;
+import org.spongycastle.asn1.x509.NoticeReference;
+
+public class SPUserNotice
+ extends ASN1Object
+{
+ private NoticeReference noticeRef;
+ private DisplayText explicitText;
+
+ public static SPUserNotice getInstance(
+ Object obj)
+ {
+ if (obj instanceof SPUserNotice)
+ {
+ return (SPUserNotice)obj;
+ }
+ else if (obj != null)
+ {
+ return new SPUserNotice(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private SPUserNotice(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+ while (e.hasMoreElements())
+ {
+ ASN1Encodable object = (ASN1Encodable)e.nextElement();
+ if (object instanceof DisplayText || object instanceof ASN1String)
+ {
+ explicitText = DisplayText.getInstance(object);
+ }
+ else if (object instanceof NoticeReference || object instanceof ASN1Sequence)
+ {
+ noticeRef = NoticeReference.getInstance(object);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Invalid element in 'SPUserNotice': " + object.getClass().getName());
+ }
+ }
+ }
+
+ public SPUserNotice(
+ NoticeReference noticeRef,
+ DisplayText explicitText)
+ {
+ this.noticeRef = noticeRef;
+ this.explicitText = explicitText;
+ }
+
+ public NoticeReference getNoticeRef()
+ {
+ return noticeRef;
+ }
+
+ public DisplayText getExplicitText()
+ {
+ return explicitText;
+ }
+
+ /**
+ * <pre>
+ * SPUserNotice ::= SEQUENCE {
+ * noticeRef NoticeReference OPTIONAL,
+ * explicitText DisplayText OPTIONAL }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (noticeRef != null)
+ {
+ v.add(noticeRef);
+ }
+
+ if (explicitText != null)
+ {
+ v.add(explicitText);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/SPuri.java b/core/src/main/java/org/spongycastle/asn1/esf/SPuri.java
new file mode 100644
index 00000000..1de95227
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/SPuri.java
@@ -0,0 +1,45 @@
+package org.spongycastle.asn1.esf;
+
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DERIA5String;
+
+public class SPuri
+{
+ private DERIA5String uri;
+
+ public static SPuri getInstance(
+ Object obj)
+ {
+ if (obj instanceof SPuri)
+ {
+ return (SPuri) obj;
+ }
+ else if (obj instanceof DERIA5String)
+ {
+ return new SPuri(DERIA5String.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public SPuri(
+ DERIA5String uri)
+ {
+ this.uri = uri;
+ }
+
+ public DERIA5String getUri()
+ {
+ return uri;
+ }
+
+ /**
+ * <pre>
+ * SPuri ::= IA5String
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return uri.toASN1Primitive();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/SigPolicyQualifierInfo.java b/core/src/main/java/org/spongycastle/asn1/esf/SigPolicyQualifierInfo.java
new file mode 100644
index 00000000..3e88ab4a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/SigPolicyQualifierInfo.java
@@ -0,0 +1,75 @@
+package org.spongycastle.asn1.esf;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class SigPolicyQualifierInfo
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier sigPolicyQualifierId;
+ private ASN1Encodable sigQualifier;
+
+ public SigPolicyQualifierInfo(
+ ASN1ObjectIdentifier sigPolicyQualifierId,
+ ASN1Encodable sigQualifier)
+ {
+ this.sigPolicyQualifierId = sigPolicyQualifierId;
+ this.sigQualifier = sigQualifier;
+ }
+
+ private SigPolicyQualifierInfo(
+ ASN1Sequence seq)
+ {
+ sigPolicyQualifierId = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+ sigQualifier = seq.getObjectAt(1);
+ }
+
+ public static SigPolicyQualifierInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof SigPolicyQualifierInfo)
+ {
+ return (SigPolicyQualifierInfo) obj;
+ }
+ else if (obj != null)
+ {
+ return new SigPolicyQualifierInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1ObjectIdentifier getSigPolicyQualifierId()
+ {
+ return new ASN1ObjectIdentifier(sigPolicyQualifierId.getId());
+ }
+
+ public ASN1Encodable getSigQualifier()
+ {
+ return sigQualifier;
+ }
+
+ /**
+ * <pre>
+ * SigPolicyQualifierInfo ::= SEQUENCE {
+ * sigPolicyQualifierId SigPolicyQualifierId,
+ * sigQualifier ANY DEFINED BY sigPolicyQualifierId }
+ *
+ * SigPolicyQualifierId ::= OBJECT IDENTIFIER
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(sigPolicyQualifierId);
+ v.add(sigQualifier);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/SigPolicyQualifiers.java b/core/src/main/java/org/spongycastle/asn1/esf/SigPolicyQualifiers.java
new file mode 100644
index 00000000..dd53b0aa
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/SigPolicyQualifiers.java
@@ -0,0 +1,77 @@
+package org.spongycastle.asn1.esf;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class SigPolicyQualifiers
+ extends ASN1Object
+{
+ ASN1Sequence qualifiers;
+
+ public static SigPolicyQualifiers getInstance(
+ Object obj)
+ {
+ if (obj instanceof SigPolicyQualifiers)
+ {
+ return (SigPolicyQualifiers) obj;
+ }
+ else if (obj instanceof ASN1Sequence)
+ {
+ return new SigPolicyQualifiers(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private SigPolicyQualifiers(
+ ASN1Sequence seq)
+ {
+ qualifiers = seq;
+ }
+
+ public SigPolicyQualifiers(
+ SigPolicyQualifierInfo[] qualifierInfos)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i=0; i < qualifierInfos.length; i++)
+ {
+ v.add(qualifierInfos[i]);
+ }
+ qualifiers = new DERSequence(v);
+ }
+
+ /**
+ * Return the number of qualifier info elements present.
+ *
+ * @return number of elements present.
+ */
+ public int size()
+ {
+ return qualifiers.size();
+ }
+
+ /**
+ * Return the SigPolicyQualifierInfo at index i.
+ *
+ * @param i index of the info of interest
+ * @return the info at index i.
+ */
+ public SigPolicyQualifierInfo getInfoAt(
+ int i)
+ {
+ return SigPolicyQualifierInfo.getInstance(qualifiers.getObjectAt(i));
+ }
+
+ /**
+ * <pre>
+ * SigPolicyQualifiers ::= SEQUENCE SIZE (1..MAX) OF SigPolicyQualifierInfo
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return qualifiers;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/SignaturePolicyId.java b/core/src/main/java/org/spongycastle/asn1/esf/SignaturePolicyId.java
new file mode 100644
index 00000000..9df4f3ed
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/SignaturePolicyId.java
@@ -0,0 +1,103 @@
+package org.spongycastle.asn1.esf;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class SignaturePolicyId
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier sigPolicyId;
+ private OtherHashAlgAndValue sigPolicyHash;
+ private SigPolicyQualifiers sigPolicyQualifiers;
+
+
+ public static SignaturePolicyId getInstance(
+ Object obj)
+ {
+ if (obj instanceof SignaturePolicyId)
+ {
+ return (SignaturePolicyId)obj;
+ }
+ else if (obj != null)
+ {
+ return new SignaturePolicyId(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private SignaturePolicyId(
+ ASN1Sequence seq)
+ {
+ if (seq.size() != 2 && seq.size() != 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ sigPolicyId = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+ sigPolicyHash = OtherHashAlgAndValue.getInstance(seq.getObjectAt(1));
+
+ if (seq.size() == 3)
+ {
+ sigPolicyQualifiers = SigPolicyQualifiers.getInstance(seq.getObjectAt(2));
+ }
+ }
+
+ public SignaturePolicyId(
+ ASN1ObjectIdentifier sigPolicyIdentifier,
+ OtherHashAlgAndValue sigPolicyHash)
+ {
+ this(sigPolicyIdentifier, sigPolicyHash, null);
+ }
+
+ public SignaturePolicyId(
+ ASN1ObjectIdentifier sigPolicyId,
+ OtherHashAlgAndValue sigPolicyHash,
+ SigPolicyQualifiers sigPolicyQualifiers)
+ {
+ this.sigPolicyId = sigPolicyId;
+ this.sigPolicyHash = sigPolicyHash;
+ this.sigPolicyQualifiers = sigPolicyQualifiers;
+ }
+
+ public ASN1ObjectIdentifier getSigPolicyId()
+ {
+ return new ASN1ObjectIdentifier(sigPolicyId.getId());
+ }
+
+ public OtherHashAlgAndValue getSigPolicyHash()
+ {
+ return sigPolicyHash;
+ }
+
+ public SigPolicyQualifiers getSigPolicyQualifiers()
+ {
+ return sigPolicyQualifiers;
+ }
+
+ /**
+ * <pre>
+ * SignaturePolicyId ::= SEQUENCE {
+ * sigPolicyId SigPolicyId,
+ * sigPolicyHash SigPolicyHash,
+ * sigPolicyQualifiers SEQUENCE SIZE (1..MAX) OF SigPolicyQualifierInfo OPTIONAL}
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(sigPolicyId);
+ v.add(sigPolicyHash);
+ if (sigPolicyQualifiers != null)
+ {
+ v.add(sigPolicyQualifiers);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/SignaturePolicyIdentifier.java b/core/src/main/java/org/spongycastle/asn1/esf/SignaturePolicyIdentifier.java
new file mode 100644
index 00000000..ace0860c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/SignaturePolicyIdentifier.java
@@ -0,0 +1,76 @@
+package org.spongycastle.asn1.esf;
+
+import org.spongycastle.asn1.ASN1Null;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.BERTags;
+import org.spongycastle.asn1.DERNull;
+
+public class SignaturePolicyIdentifier
+ extends ASN1Object
+{
+ private SignaturePolicyId signaturePolicyId;
+ private boolean isSignaturePolicyImplied;
+
+ public static SignaturePolicyIdentifier getInstance(
+ Object obj)
+ {
+ if (obj instanceof SignaturePolicyIdentifier)
+ {
+ return (SignaturePolicyIdentifier)obj;
+ }
+ else if (obj instanceof ASN1Null || hasEncodedTagValue(obj, BERTags.NULL))
+ {
+ return new SignaturePolicyIdentifier();
+ }
+ else if (obj != null)
+ {
+ return new SignaturePolicyIdentifier(SignaturePolicyId.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public SignaturePolicyIdentifier()
+ {
+ this.isSignaturePolicyImplied = true;
+ }
+
+ public SignaturePolicyIdentifier(
+ SignaturePolicyId signaturePolicyId)
+ {
+ this.signaturePolicyId = signaturePolicyId;
+ this.isSignaturePolicyImplied = false;
+ }
+
+ public SignaturePolicyId getSignaturePolicyId()
+ {
+ return signaturePolicyId;
+ }
+
+ public boolean isSignaturePolicyImplied()
+ {
+ return isSignaturePolicyImplied;
+ }
+
+ /**
+ * <pre>
+ * SignaturePolicyIdentifier ::= CHOICE{
+ * SignaturePolicyId SignaturePolicyId,
+ * SignaturePolicyImplied SignaturePolicyImplied }
+ *
+ * SignaturePolicyImplied ::= NULL
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (isSignaturePolicyImplied)
+ {
+ return DERNull.INSTANCE;
+ }
+ else
+ {
+ return signaturePolicyId.toASN1Primitive();
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/SignerAttribute.java b/core/src/main/java/org/spongycastle/asn1/esf/SignerAttribute.java
new file mode 100644
index 00000000..664db344
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/SignerAttribute.java
@@ -0,0 +1,123 @@
+package org.spongycastle.asn1.esf;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.Attribute;
+import org.spongycastle.asn1.x509.AttributeCertificate;
+
+
+public class SignerAttribute
+ extends ASN1Object
+{
+ private Object[] values;
+
+ public static SignerAttribute getInstance(
+ Object o)
+ {
+ if (o instanceof SignerAttribute)
+ {
+ return (SignerAttribute) o;
+ }
+ else if (o != null)
+ {
+ return new SignerAttribute(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ private SignerAttribute(
+ ASN1Sequence seq)
+ {
+ int index = 0;
+ values = new Object[seq.size()];
+
+ for (Enumeration e = seq.getObjects(); e.hasMoreElements();)
+ {
+ ASN1TaggedObject taggedObject = ASN1TaggedObject.getInstance(e.nextElement());
+
+ if (taggedObject.getTagNo() == 0)
+ {
+ ASN1Sequence attrs = ASN1Sequence.getInstance(taggedObject, true);
+ Attribute[] attributes = new Attribute[attrs.size()];
+
+ for (int i = 0; i != attributes.length; i++)
+ {
+ attributes[i] = Attribute.getInstance(attrs.getObjectAt(i));
+ }
+ values[index] = attributes;
+ }
+ else if (taggedObject.getTagNo() == 1)
+ {
+ values[index] = AttributeCertificate.getInstance(ASN1Sequence.getInstance(taggedObject, true));
+ }
+ else
+ {
+ throw new IllegalArgumentException("illegal tag: " + taggedObject.getTagNo());
+ }
+ index++;
+ }
+ }
+
+ public SignerAttribute(
+ Attribute[] claimedAttributes)
+ {
+ this.values = new Object[1];
+ this.values[0] = claimedAttributes;
+ }
+
+ public SignerAttribute(
+ AttributeCertificate certifiedAttributes)
+ {
+ this.values = new Object[1];
+ this.values[0] = certifiedAttributes;
+ }
+
+ /**
+ * Return the sequence of choices - the array elements will either be of
+ * type Attribute[] or AttributeCertificate depending on what tag was used.
+ *
+ * @return array of choices.
+ */
+ public Object[] getValues()
+ {
+ return values;
+ }
+
+ /**
+ *
+ * <pre>
+ * SignerAttribute ::= SEQUENCE OF CHOICE {
+ * claimedAttributes [0] ClaimedAttributes,
+ * certifiedAttributes [1] CertifiedAttributes }
+ *
+ * ClaimedAttributes ::= SEQUENCE OF Attribute
+ * CertifiedAttributes ::= AttributeCertificate -- as defined in RFC 3281: see clause 4.1.
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ for (int i = 0; i != values.length; i++)
+ {
+ if (values[i] instanceof Attribute[])
+ {
+ v.add(new DERTaggedObject(0, new DERSequence((Attribute[])values[i])));
+ }
+ else
+ {
+ v.add(new DERTaggedObject(1, (AttributeCertificate)values[i]));
+ }
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/esf/SignerLocation.java b/core/src/main/java/org/spongycastle/asn1/esf/SignerLocation.java
new file mode 100644
index 00000000..ebf693e0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/esf/SignerLocation.java
@@ -0,0 +1,162 @@
+package org.spongycastle.asn1.esf;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.DERUTF8String;
+import org.spongycastle.asn1.x500.DirectoryString;
+
+/**
+ * Signer-Location attribute (RFC3126).
+ *
+ * <pre>
+ * SignerLocation ::= SEQUENCE {
+ * countryName [0] DirectoryString OPTIONAL,
+ * localityName [1] DirectoryString OPTIONAL,
+ * postalAddress [2] PostalAddress OPTIONAL }
+ *
+ * PostalAddress ::= SEQUENCE SIZE(1..6) OF DirectoryString
+ * </pre>
+ */
+public class SignerLocation
+ extends ASN1Object
+{
+ private DERUTF8String countryName;
+ private DERUTF8String localityName;
+ private ASN1Sequence postalAddress;
+
+ private SignerLocation(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ DERTaggedObject o = (DERTaggedObject)e.nextElement();
+
+ switch (o.getTagNo())
+ {
+ case 0:
+ DirectoryString countryNameDirectoryString = DirectoryString.getInstance(o, true);
+ this.countryName = new DERUTF8String(countryNameDirectoryString.getString());
+ break;
+ case 1:
+ DirectoryString localityNameDirectoryString = DirectoryString.getInstance(o, true);
+ this.localityName = new DERUTF8String(localityNameDirectoryString.getString());
+ break;
+ case 2:
+ if (o.isExplicit())
+ {
+ this.postalAddress = ASN1Sequence.getInstance(o, true);
+ }
+ else // handle erroneous implicitly tagged sequences
+ {
+ this.postalAddress = ASN1Sequence.getInstance(o, false);
+ }
+ if (postalAddress != null && postalAddress.size() > 6)
+ {
+ throw new IllegalArgumentException("postal address must contain less than 6 strings");
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("illegal tag");
+ }
+ }
+ }
+
+ public SignerLocation(
+ DERUTF8String countryName,
+ DERUTF8String localityName,
+ ASN1Sequence postalAddress)
+ {
+ if (postalAddress != null && postalAddress.size() > 6)
+ {
+ throw new IllegalArgumentException("postal address must contain less than 6 strings");
+ }
+
+ if (countryName != null)
+ {
+ this.countryName = DERUTF8String.getInstance(countryName.toASN1Primitive());
+ }
+
+ if (localityName != null)
+ {
+ this.localityName = DERUTF8String.getInstance(localityName.toASN1Primitive());
+ }
+
+ if (postalAddress != null)
+ {
+ this.postalAddress = ASN1Sequence.getInstance(postalAddress.toASN1Primitive());
+ }
+ }
+
+ public static SignerLocation getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof SignerLocation)
+ {
+ return (SignerLocation)obj;
+ }
+
+ return new SignerLocation(ASN1Sequence.getInstance(obj));
+ }
+
+ public DERUTF8String getCountryName()
+ {
+ return countryName;
+ }
+
+ public DERUTF8String getLocalityName()
+ {
+ return localityName;
+ }
+
+ public ASN1Sequence getPostalAddress()
+ {
+ return postalAddress;
+ }
+
+ /**
+ * <pre>
+ * SignerLocation ::= SEQUENCE {
+ * countryName [0] DirectoryString OPTIONAL,
+ * localityName [1] DirectoryString OPTIONAL,
+ * postalAddress [2] PostalAddress OPTIONAL }
+ *
+ * PostalAddress ::= SEQUENCE SIZE(1..6) OF DirectoryString
+ *
+ * DirectoryString ::= CHOICE {
+ * teletexString TeletexString (SIZE (1..MAX)),
+ * printableString PrintableString (SIZE (1..MAX)),
+ * universalString UniversalString (SIZE (1..MAX)),
+ * utf8String UTF8String (SIZE (1.. MAX)),
+ * bmpString BMPString (SIZE (1..MAX)) }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (countryName != null)
+ {
+ v.add(new DERTaggedObject(true, 0, countryName));
+ }
+
+ if (localityName != null)
+ {
+ v.add(new DERTaggedObject(true, 1, localityName));
+ }
+
+ if (postalAddress != null)
+ {
+ v.add(new DERTaggedObject(true, 2, postalAddress));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ess/ContentHints.java b/core/src/main/java/org/spongycastle/asn1/ess/ContentHints.java
new file mode 100644
index 00000000..aebb16e8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ess/ContentHints.java
@@ -0,0 +1,94 @@
+package org.spongycastle.asn1.ess;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERUTF8String;
+
+public class ContentHints
+ extends ASN1Object
+{
+ private DERUTF8String contentDescription;
+ private ASN1ObjectIdentifier contentType;
+
+ public static ContentHints getInstance(Object o)
+ {
+ if (o instanceof ContentHints)
+ {
+ return (ContentHints)o;
+ }
+ else if (o != null)
+ {
+ return new ContentHints(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ /**
+ * constructor
+ */
+ private ContentHints(ASN1Sequence seq)
+ {
+ ASN1Encodable field = seq.getObjectAt(0);
+ if (field.toASN1Primitive() instanceof DERUTF8String)
+ {
+ contentDescription = DERUTF8String.getInstance(field);
+ contentType = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(1));
+ }
+ else
+ {
+ contentType = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+ }
+ }
+
+ public ContentHints(
+ ASN1ObjectIdentifier contentType)
+ {
+ this.contentType = contentType;
+ this.contentDescription = null;
+ }
+
+ public ContentHints(
+ ASN1ObjectIdentifier contentType,
+ DERUTF8String contentDescription)
+ {
+ this.contentType = contentType;
+ this.contentDescription = contentDescription;
+ }
+
+ public ASN1ObjectIdentifier getContentType()
+ {
+ return contentType;
+ }
+
+ public DERUTF8String getContentDescription()
+ {
+ return contentDescription;
+ }
+
+ /**
+ * <pre>
+ * ContentHints ::= SEQUENCE {
+ * contentDescription UTF8String (SIZE (1..MAX)) OPTIONAL,
+ * contentType ContentType }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (contentDescription != null)
+ {
+ v.add(contentDescription);
+ }
+
+ v.add(contentType);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ess/ContentIdentifier.java b/core/src/main/java/org/spongycastle/asn1/ess/ContentIdentifier.java
new file mode 100644
index 00000000..7082a43a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ess/ContentIdentifier.java
@@ -0,0 +1,63 @@
+package org.spongycastle.asn1.ess;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DEROctetString;
+
+public class ContentIdentifier
+ extends ASN1Object
+{
+ ASN1OctetString value;
+
+ public static ContentIdentifier getInstance(Object o)
+ {
+ if (o instanceof ContentIdentifier)
+ {
+ return (ContentIdentifier) o;
+ }
+ else if (o != null)
+ {
+ return new ContentIdentifier(ASN1OctetString.getInstance(o));
+ }
+
+ return null;
+ }
+
+ /**
+ * Create from OCTET STRING whose octets represent the identifier.
+ */
+ private ContentIdentifier(
+ ASN1OctetString value)
+ {
+ this.value = value;
+ }
+
+ /**
+ * Create from byte array representing the identifier.
+ */
+ public ContentIdentifier(
+ byte[] value)
+ {
+ this(new DEROctetString(value));
+ }
+
+ public ASN1OctetString getValue()
+ {
+ return value;
+ }
+
+ /**
+ * The definition of ContentIdentifier is
+ * <pre>
+ * ContentIdentifier ::= OCTET STRING
+ * </pre>
+ * id-aa-contentIdentifier OBJECT IDENTIFIER ::= { iso(1)
+ * member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+ * smime(16) id-aa(2) 7 }
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return value;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ess/ESSCertID.java b/core/src/main/java/org/spongycastle/asn1/ess/ESSCertID.java
new file mode 100644
index 00000000..e63b6963
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ess/ESSCertID.java
@@ -0,0 +1,95 @@
+package org.spongycastle.asn1.ess;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.IssuerSerial;
+
+public class ESSCertID
+ extends ASN1Object
+{
+ private ASN1OctetString certHash;
+
+ private IssuerSerial issuerSerial;
+
+ public static ESSCertID getInstance(Object o)
+ {
+ if (o instanceof ESSCertID)
+ {
+ return (ESSCertID)o;
+ }
+ else if (o != null)
+ {
+ return new ESSCertID(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ /**
+ * constructor
+ */
+ private ESSCertID(ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ certHash = ASN1OctetString.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() > 1)
+ {
+ issuerSerial = IssuerSerial.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ public ESSCertID(
+ byte[] hash)
+ {
+ certHash = new DEROctetString(hash);
+ }
+
+ public ESSCertID(
+ byte[] hash,
+ IssuerSerial issuerSerial)
+ {
+ this.certHash = new DEROctetString(hash);
+ this.issuerSerial = issuerSerial;
+ }
+
+ public byte[] getCertHash()
+ {
+ return certHash.getOctets();
+ }
+
+ public IssuerSerial getIssuerSerial()
+ {
+ return issuerSerial;
+ }
+
+ /**
+ * <pre>
+ * ESSCertID ::= SEQUENCE {
+ * certHash Hash,
+ * issuerSerial IssuerSerial OPTIONAL }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certHash);
+
+ if (issuerSerial != null)
+ {
+ v.add(issuerSerial);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ess/ESSCertIDv2.java b/core/src/main/java/org/spongycastle/asn1/ess/ESSCertIDv2.java
new file mode 100644
index 00000000..dbafd904
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ess/ESSCertIDv2.java
@@ -0,0 +1,155 @@
+package org.spongycastle.asn1.ess;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.nist.NISTObjectIdentifiers;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.IssuerSerial;
+
+public class ESSCertIDv2
+ extends ASN1Object
+{
+ private AlgorithmIdentifier hashAlgorithm;
+ private byte[] certHash;
+ private IssuerSerial issuerSerial;
+ private static final AlgorithmIdentifier DEFAULT_ALG_ID = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256);
+
+ public static ESSCertIDv2 getInstance(
+ Object o)
+ {
+ if (o instanceof ESSCertIDv2)
+ {
+ return (ESSCertIDv2) o;
+ }
+ else if (o != null)
+ {
+ return new ESSCertIDv2(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ private ESSCertIDv2(
+ ASN1Sequence seq)
+ {
+ if (seq.size() > 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ int count = 0;
+
+ if (seq.getObjectAt(0) instanceof ASN1OctetString)
+ {
+ // Default value
+ this.hashAlgorithm = DEFAULT_ALG_ID;
+ }
+ else
+ {
+ this.hashAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(count++).toASN1Primitive());
+ }
+
+ this.certHash = ASN1OctetString.getInstance(seq.getObjectAt(count++).toASN1Primitive()).getOctets();
+
+ if (seq.size() > count)
+ {
+ this.issuerSerial = IssuerSerial.getInstance(seq.getObjectAt(count));
+ }
+ }
+
+ public ESSCertIDv2(
+ byte[] certHash)
+ {
+ this(null, certHash, null);
+ }
+
+ public ESSCertIDv2(
+ AlgorithmIdentifier algId,
+ byte[] certHash)
+ {
+ this(algId, certHash, null);
+ }
+
+ public ESSCertIDv2(
+ byte[] certHash,
+ IssuerSerial issuerSerial)
+ {
+ this(null, certHash, issuerSerial);
+ }
+
+ public ESSCertIDv2(
+ AlgorithmIdentifier algId,
+ byte[] certHash,
+ IssuerSerial issuerSerial)
+ {
+ if (algId == null)
+ {
+ // Default value
+ this.hashAlgorithm = DEFAULT_ALG_ID;
+ }
+ else
+ {
+ this.hashAlgorithm = algId;
+ }
+
+ this.certHash = certHash;
+ this.issuerSerial = issuerSerial;
+ }
+
+ public AlgorithmIdentifier getHashAlgorithm()
+ {
+ return this.hashAlgorithm;
+ }
+
+ public byte[] getCertHash()
+ {
+ return certHash;
+ }
+
+ public IssuerSerial getIssuerSerial()
+ {
+ return issuerSerial;
+ }
+
+ /**
+ * <pre>
+ * ESSCertIDv2 ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier
+ * DEFAULT {algorithm id-sha256},
+ * certHash Hash,
+ * issuerSerial IssuerSerial OPTIONAL
+ * }
+ *
+ * Hash ::= OCTET STRING
+ *
+ * IssuerSerial ::= SEQUENCE {
+ * issuer GeneralNames,
+ * serialNumber CertificateSerialNumber
+ * }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (!hashAlgorithm.equals(DEFAULT_ALG_ID))
+ {
+ v.add(hashAlgorithm);
+ }
+
+ v.add(new DEROctetString(certHash).toASN1Primitive());
+
+ if (issuerSerial != null)
+ {
+ v.add(issuerSerial);
+ }
+
+ return new DERSequence(v);
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ess/OtherCertID.java b/core/src/main/java/org/spongycastle/asn1/ess/OtherCertID.java
new file mode 100644
index 00000000..530491f7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ess/OtherCertID.java
@@ -0,0 +1,137 @@
+package org.spongycastle.asn1.ess;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.DigestInfo;
+import org.spongycastle.asn1.x509.IssuerSerial;
+
+public class OtherCertID
+ extends ASN1Object
+{
+ private ASN1Encodable otherCertHash;
+ private IssuerSerial issuerSerial;
+
+ public static OtherCertID getInstance(Object o)
+ {
+ if (o instanceof OtherCertID)
+ {
+ return (OtherCertID) o;
+ }
+ else if (o != null)
+ {
+ return new OtherCertID(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ /**
+ * constructor
+ */
+ private OtherCertID(ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ if (seq.getObjectAt(0).toASN1Primitive() instanceof ASN1OctetString)
+ {
+ otherCertHash = ASN1OctetString.getInstance(seq.getObjectAt(0));
+ }
+ else
+ {
+ otherCertHash = DigestInfo.getInstance(seq.getObjectAt(0));
+
+ }
+
+ if (seq.size() > 1)
+ {
+ issuerSerial = IssuerSerial.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ public OtherCertID(
+ AlgorithmIdentifier algId,
+ byte[] digest)
+ {
+ this.otherCertHash = new DigestInfo(algId, digest);
+ }
+
+ public OtherCertID(
+ AlgorithmIdentifier algId,
+ byte[] digest,
+ IssuerSerial issuerSerial)
+ {
+ this.otherCertHash = new DigestInfo(algId, digest);
+ this.issuerSerial = issuerSerial;
+ }
+
+ public AlgorithmIdentifier getAlgorithmHash()
+ {
+ if (otherCertHash.toASN1Primitive() instanceof ASN1OctetString)
+ {
+ // SHA-1
+ return new AlgorithmIdentifier("1.3.14.3.2.26");
+ }
+ else
+ {
+ return DigestInfo.getInstance(otherCertHash).getAlgorithmId();
+ }
+ }
+
+ public byte[] getCertHash()
+ {
+ if (otherCertHash.toASN1Primitive() instanceof ASN1OctetString)
+ {
+ // SHA-1
+ return ((ASN1OctetString)otherCertHash.toASN1Primitive()).getOctets();
+ }
+ else
+ {
+ return DigestInfo.getInstance(otherCertHash).getDigest();
+ }
+ }
+
+ public IssuerSerial getIssuerSerial()
+ {
+ return issuerSerial;
+ }
+
+ /**
+ * <pre>
+ * OtherCertID ::= SEQUENCE {
+ * otherCertHash OtherHash,
+ * issuerSerial IssuerSerial OPTIONAL }
+ *
+ * OtherHash ::= CHOICE {
+ * sha1Hash OCTET STRING,
+ * otherHash OtherHashAlgAndValue }
+ *
+ * OtherHashAlgAndValue ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * hashValue OCTET STRING }
+ *
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(otherCertHash);
+
+ if (issuerSerial != null)
+ {
+ v.add(issuerSerial);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ess/OtherSigningCertificate.java b/core/src/main/java/org/spongycastle/asn1/ess/OtherSigningCertificate.java
new file mode 100644
index 00000000..2198d1a0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ess/OtherSigningCertificate.java
@@ -0,0 +1,109 @@
+package org.spongycastle.asn1.ess;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.PolicyInformation;
+
+public class OtherSigningCertificate
+ extends ASN1Object
+{
+ ASN1Sequence certs;
+ ASN1Sequence policies;
+
+ public static OtherSigningCertificate getInstance(Object o)
+ {
+ if (o instanceof OtherSigningCertificate)
+ {
+ return (OtherSigningCertificate) o;
+ }
+ else if (o != null)
+ {
+ return new OtherSigningCertificate(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ /**
+ * constructeurs
+ */
+ private OtherSigningCertificate(ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ this.certs = ASN1Sequence.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() > 1)
+ {
+ this.policies = ASN1Sequence.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ public OtherSigningCertificate(
+ OtherCertID otherCertID)
+ {
+ certs = new DERSequence(otherCertID);
+ }
+
+ public OtherCertID[] getCerts()
+ {
+ OtherCertID[] cs = new OtherCertID[certs.size()];
+
+ for (int i = 0; i != certs.size(); i++)
+ {
+ cs[i] = OtherCertID.getInstance(certs.getObjectAt(i));
+ }
+
+ return cs;
+ }
+
+ public PolicyInformation[] getPolicies()
+ {
+ if (policies == null)
+ {
+ return null;
+ }
+
+ PolicyInformation[] ps = new PolicyInformation[policies.size()];
+
+ for (int i = 0; i != policies.size(); i++)
+ {
+ ps[i] = PolicyInformation.getInstance(policies.getObjectAt(i));
+ }
+
+ return ps;
+ }
+
+ /**
+ * The definition of OtherSigningCertificate is
+ * <pre>
+ * OtherSigningCertificate ::= SEQUENCE {
+ * certs SEQUENCE OF OtherCertID,
+ * policies SEQUENCE OF PolicyInformation OPTIONAL
+ * }
+ * </pre>
+ * id-aa-ets-otherSigCert OBJECT IDENTIFIER ::= { iso(1)
+ * member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+ * smime(16) id-aa(2) 19 }
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certs);
+
+ if (policies != null)
+ {
+ v.add(policies);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ess/SigningCertificate.java b/core/src/main/java/org/spongycastle/asn1/ess/SigningCertificate.java
new file mode 100644
index 00000000..87a9881b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ess/SigningCertificate.java
@@ -0,0 +1,109 @@
+package org.spongycastle.asn1.ess;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.PolicyInformation;
+
+
+public class SigningCertificate
+ extends ASN1Object
+{
+ ASN1Sequence certs;
+ ASN1Sequence policies;
+
+ public static SigningCertificate getInstance(Object o)
+ {
+ if (o instanceof SigningCertificate)
+ {
+ return (SigningCertificate) o;
+ }
+ else if (o != null)
+ {
+ return new SigningCertificate(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ /**
+ * constructeurs
+ */
+ private SigningCertificate(ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ this.certs = ASN1Sequence.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() > 1)
+ {
+ this.policies = ASN1Sequence.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ public SigningCertificate(
+ ESSCertID essCertID)
+ {
+ certs = new DERSequence(essCertID);
+ }
+
+ public ESSCertID[] getCerts()
+ {
+ ESSCertID[] cs = new ESSCertID[certs.size()];
+
+ for (int i = 0; i != certs.size(); i++)
+ {
+ cs[i] = ESSCertID.getInstance(certs.getObjectAt(i));
+ }
+
+ return cs;
+ }
+
+ public PolicyInformation[] getPolicies()
+ {
+ if (policies == null)
+ {
+ return null;
+ }
+
+ PolicyInformation[] ps = new PolicyInformation[policies.size()];
+
+ for (int i = 0; i != policies.size(); i++)
+ {
+ ps[i] = PolicyInformation.getInstance(policies.getObjectAt(i));
+ }
+
+ return ps;
+ }
+
+ /**
+ * The definition of SigningCertificate is
+ * <pre>
+ * SigningCertificate ::= SEQUENCE {
+ * certs SEQUENCE OF ESSCertID,
+ * policies SEQUENCE OF PolicyInformation OPTIONAL
+ * }
+ * </pre>
+ * id-aa-signingCertificate OBJECT IDENTIFIER ::= { iso(1)
+ * member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+ * smime(16) id-aa(2) 12 }
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certs);
+
+ if (policies != null)
+ {
+ v.add(policies);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ess/SigningCertificateV2.java b/core/src/main/java/org/spongycastle/asn1/ess/SigningCertificateV2.java
new file mode 100644
index 00000000..3af8c731
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ess/SigningCertificateV2.java
@@ -0,0 +1,136 @@
+package org.spongycastle.asn1.ess;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.PolicyInformation;
+
+public class SigningCertificateV2
+ extends ASN1Object
+{
+ ASN1Sequence certs;
+ ASN1Sequence policies;
+
+ public static SigningCertificateV2 getInstance(
+ Object o)
+ {
+ if (o == null || o instanceof SigningCertificateV2)
+ {
+ return (SigningCertificateV2) o;
+ }
+ else if (o instanceof ASN1Sequence)
+ {
+ return new SigningCertificateV2((ASN1Sequence) o);
+ }
+
+ return null;
+ }
+
+ private SigningCertificateV2(
+ ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ this.certs = ASN1Sequence.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() > 1)
+ {
+ this.policies = ASN1Sequence.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ public SigningCertificateV2(
+ ESSCertIDv2 cert)
+ {
+ this.certs = new DERSequence(cert);
+ }
+
+ public SigningCertificateV2(
+ ESSCertIDv2[] certs)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i=0; i < certs.length; i++)
+ {
+ v.add(certs[i]);
+ }
+ this.certs = new DERSequence(v);
+ }
+
+ public SigningCertificateV2(
+ ESSCertIDv2[] certs,
+ PolicyInformation[] policies)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i=0; i < certs.length; i++)
+ {
+ v.add(certs[i]);
+ }
+ this.certs = new DERSequence(v);
+
+ if (policies != null)
+ {
+ v = new ASN1EncodableVector();
+ for (int i=0; i < policies.length; i++)
+ {
+ v.add(policies[i]);
+ }
+ this.policies = new DERSequence(v);
+ }
+ }
+
+ public ESSCertIDv2[] getCerts()
+ {
+ ESSCertIDv2[] certIds = new ESSCertIDv2[certs.size()];
+ for (int i = 0; i != certs.size(); i++)
+ {
+ certIds[i] = ESSCertIDv2.getInstance(certs.getObjectAt(i));
+ }
+ return certIds;
+ }
+
+ public PolicyInformation[] getPolicies()
+ {
+ if (policies == null)
+ {
+ return null;
+ }
+
+ PolicyInformation[] policyInformations = new PolicyInformation[policies.size()];
+ for (int i = 0; i != policies.size(); i++)
+ {
+ policyInformations[i] = PolicyInformation.getInstance(policies.getObjectAt(i));
+ }
+ return policyInformations;
+ }
+
+ /**
+ * The definition of SigningCertificateV2 is
+ * <pre>
+ * SigningCertificateV2 ::= SEQUENCE {
+ * certs SEQUENCE OF ESSCertIDv2,
+ * policies SEQUENCE OF PolicyInformation OPTIONAL
+ * }
+ * </pre>
+ * id-aa-signingCertificateV2 OBJECT IDENTIFIER ::= { iso(1)
+ * member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+ * smime(16) id-aa(2) 47 }
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certs);
+
+ if (policies != null)
+ {
+ v.add(policies);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/gnu/GNUObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/gnu/GNUObjectIdentifiers.java
new file mode 100644
index 00000000..fd3cf240
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/gnu/GNUObjectIdentifiers.java
@@ -0,0 +1,58 @@
+package org.spongycastle.asn1.gnu;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+
+/**
+ * GNU project OID collection<p>
+ * { iso(1) identifier-organization(3) dod(6) internet(1) private(4) } == IETF defined things
+ */
+public interface GNUObjectIdentifiers
+{
+ /** 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/core/src/main/java/org/spongycastle/asn1/iana/IANAObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/iana/IANAObjectIdentifiers.java
new file mode 100644
index 00000000..731fdfb4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/iana/IANAObjectIdentifiers.java
@@ -0,0 +1,60 @@
+package org.spongycastle.asn1.iana;
+
+import org.spongycastle.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)}
+ //
+
+
+ /** 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");
+
+ /** IPSEC ISAKMP-Oakley hmacTIGER OID: 1.3.6.1.5.5.8.1.3 */
+ static final ASN1ObjectIdentifier hmacTIGER = isakmpOakley.branch("3");
+
+ /** IPSEC ISAKMP-Oakley hmacRIPEMD160 OID: 1.3.6.1.5.5.8.1.4 */
+ static final ASN1ObjectIdentifier hmacRIPEMD160 = isakmpOakley.branch("4");
+
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/icao/CscaMasterList.java b/core/src/main/java/org/spongycastle/asn1/icao/CscaMasterList.java
new file mode 100644
index 00000000..4ad1300c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/icao/CscaMasterList.java
@@ -0,0 +1,114 @@
+package org.spongycastle.asn1.icao;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERSet;
+import org.spongycastle.asn1.x509.Certificate;
+
+/**
+ * The CscaMasterList object. This object can be wrapped in a
+ * CMSSignedData to be published in LDAP.
+ *
+ * <pre>
+ * CscaMasterList ::= SEQUENCE {
+ * version CscaMasterListVersion,
+ * certList SET OF Certificate }
+ *
+ * CscaMasterListVersion :: INTEGER {v0(0)}
+ * </pre>
+ */
+
+public class CscaMasterList
+ extends ASN1Object
+{
+ private ASN1Integer version = new ASN1Integer(0);
+ private Certificate[] certList;
+
+ public static CscaMasterList getInstance(
+ Object obj)
+ {
+ if (obj instanceof CscaMasterList)
+ {
+ return (CscaMasterList)obj;
+ }
+ else if (obj != null)
+ {
+ return new CscaMasterList(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private CscaMasterList(
+ ASN1Sequence seq)
+ {
+ if (seq == null || seq.size() == 0)
+ {
+ throw new IllegalArgumentException(
+ "null or empty sequence passed.");
+ }
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException(
+ "Incorrect sequence size: " + seq.size());
+ }
+
+ version = ASN1Integer.getInstance(seq.getObjectAt(0));
+ ASN1Set certSet = ASN1Set.getInstance(seq.getObjectAt(1));
+ certList = new Certificate[certSet.size()];
+ for (int i = 0; i < certList.length; i++)
+ {
+ certList[i]
+ = Certificate.getInstance(certSet.getObjectAt(i));
+ }
+ }
+
+ public CscaMasterList(
+ Certificate[] certStructs)
+ {
+ certList = copyCertList(certStructs);
+ }
+
+ public int getVersion()
+ {
+ return version.getValue().intValue();
+ }
+
+ public Certificate[] getCertStructs()
+ {
+ return copyCertList(certList);
+ }
+
+ private Certificate[] copyCertList(Certificate[] orig)
+ {
+ Certificate[] certs = new Certificate[orig.length];
+
+ for (int i = 0; i != certs.length; i++)
+ {
+ certs[i] = orig[i];
+ }
+
+ return certs;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector seq = new ASN1EncodableVector();
+
+ seq.add(version);
+
+ ASN1EncodableVector certSet = new ASN1EncodableVector();
+ for (int i = 0; i < certList.length; i++)
+ {
+ certSet.add(certList[i]);
+ }
+ seq.add(new DERSet(certSet));
+
+ return new DERSequence(seq);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/icao/DataGroupHash.java b/core/src/main/java/org/spongycastle/asn1/icao/DataGroupHash.java
new file mode 100644
index 00000000..51a1ce2e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/icao/DataGroupHash.java
@@ -0,0 +1,97 @@
+package org.spongycastle.asn1.icao;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * The DataGroupHash object.
+ * <pre>
+ * DataGroupHash ::= SEQUENCE {
+ * dataGroupNumber DataGroupNumber,
+ * dataGroupHashValue OCTET STRING }
+ *
+ * DataGroupNumber ::= INTEGER {
+ * dataGroup1 (1),
+ * dataGroup1 (2),
+ * dataGroup1 (3),
+ * dataGroup1 (4),
+ * dataGroup1 (5),
+ * dataGroup1 (6),
+ * dataGroup1 (7),
+ * dataGroup1 (8),
+ * dataGroup1 (9),
+ * dataGroup1 (10),
+ * dataGroup1 (11),
+ * dataGroup1 (12),
+ * dataGroup1 (13),
+ * dataGroup1 (14),
+ * dataGroup1 (15),
+ * dataGroup1 (16) }
+ *
+ * </pre>
+ */
+public class DataGroupHash
+ extends ASN1Object
+{
+ ASN1Integer dataGroupNumber;
+ ASN1OctetString dataGroupHashValue;
+
+ public static DataGroupHash getInstance(
+ Object obj)
+ {
+ if (obj instanceof DataGroupHash)
+ {
+ return (DataGroupHash)obj;
+ }
+ else if (obj != null)
+ {
+ return new DataGroupHash(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private DataGroupHash(ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ // dataGroupNumber
+ dataGroupNumber = ASN1Integer.getInstance(e.nextElement());
+ // dataGroupHashValue
+ dataGroupHashValue = ASN1OctetString.getInstance(e.nextElement());
+ }
+
+ public DataGroupHash(
+ int dataGroupNumber,
+ ASN1OctetString dataGroupHashValue)
+ {
+ this.dataGroupNumber = new ASN1Integer(dataGroupNumber);
+ this.dataGroupHashValue = dataGroupHashValue;
+ }
+
+ public int getDataGroupNumber()
+ {
+ return dataGroupNumber.getValue().intValue();
+ }
+
+ public ASN1OctetString getDataGroupHashValue()
+ {
+ return dataGroupHashValue;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector seq = new ASN1EncodableVector();
+ seq.add(dataGroupNumber);
+ seq.add(dataGroupHashValue);
+
+ return new DERSequence(seq);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/icao/ICAOObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/icao/ICAOObjectIdentifiers.java
new file mode 100644
index 00000000..ffa29307
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/icao/ICAOObjectIdentifiers.java
@@ -0,0 +1,49 @@
+package org.spongycastle.asn1.icao;
+
+import org.spongycastle.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<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<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 <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<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<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/core/src/main/java/org/spongycastle/asn1/icao/LDSSecurityObject.java b/core/src/main/java/org/spongycastle/asn1/icao/LDSSecurityObject.java
new file mode 100644
index 00000000..f09f2923
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/icao/LDSSecurityObject.java
@@ -0,0 +1,159 @@
+package org.spongycastle.asn1.icao;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * The LDSSecurityObject object (V1.8).
+ * <pre>
+ * LDSSecurityObject ::= SEQUENCE {
+ * version LDSSecurityObjectVersion,
+ * hashAlgorithm DigestAlgorithmIdentifier,
+ * dataGroupHashValues SEQUENCE SIZE (2..ub-DataGroups) OF DataHashGroup,
+ * ldsVersionInfo LDSVersionInfo OPTIONAL
+ * -- if present, version MUST be v1 }
+ *
+ * DigestAlgorithmIdentifier ::= AlgorithmIdentifier,
+ *
+ * LDSSecurityObjectVersion :: INTEGER {V0(0)}
+ * </pre>
+ */
+
+public class LDSSecurityObject
+ extends ASN1Object
+ implements ICAOObjectIdentifiers
+{
+ public static final int ub_DataGroups = 16;
+
+ private ASN1Integer version = new ASN1Integer(0);
+ private AlgorithmIdentifier digestAlgorithmIdentifier;
+ private DataGroupHash[] datagroupHash;
+ private LDSVersionInfo versionInfo;
+
+ public static LDSSecurityObject getInstance(
+ Object obj)
+ {
+ if (obj instanceof LDSSecurityObject)
+ {
+ return (LDSSecurityObject)obj;
+ }
+ else if (obj != null)
+ {
+ return new LDSSecurityObject(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private LDSSecurityObject(
+ ASN1Sequence seq)
+ {
+ if (seq == null || seq.size() == 0)
+ {
+ throw new IllegalArgumentException("null or empty sequence passed.");
+ }
+
+ Enumeration e = seq.getObjects();
+
+ // version
+ version = ASN1Integer.getInstance(e.nextElement());
+ // digestAlgorithmIdentifier
+ digestAlgorithmIdentifier = AlgorithmIdentifier.getInstance(e.nextElement());
+
+ ASN1Sequence datagroupHashSeq = ASN1Sequence.getInstance(e.nextElement());
+
+ if (version.getValue().intValue() == 1)
+ {
+ versionInfo = LDSVersionInfo.getInstance(e.nextElement());
+ }
+
+ checkDatagroupHashSeqSize(datagroupHashSeq.size());
+
+ datagroupHash = new DataGroupHash[datagroupHashSeq.size()];
+ for (int i= 0; i< datagroupHashSeq.size();i++)
+ {
+ datagroupHash[i] = DataGroupHash.getInstance(datagroupHashSeq.getObjectAt(i));
+ }
+ }
+
+ public LDSSecurityObject(
+ AlgorithmIdentifier digestAlgorithmIdentifier,
+ DataGroupHash[] datagroupHash)
+ {
+ this.version = new ASN1Integer(0);
+ this.digestAlgorithmIdentifier = digestAlgorithmIdentifier;
+ this.datagroupHash = datagroupHash;
+
+ checkDatagroupHashSeqSize(datagroupHash.length);
+ }
+
+ public LDSSecurityObject(
+ AlgorithmIdentifier digestAlgorithmIdentifier,
+ DataGroupHash[] datagroupHash,
+ LDSVersionInfo versionInfo)
+ {
+ this.version = new ASN1Integer(1);
+ this.digestAlgorithmIdentifier = digestAlgorithmIdentifier;
+ this.datagroupHash = datagroupHash;
+ this.versionInfo = versionInfo;
+
+ checkDatagroupHashSeqSize(datagroupHash.length);
+ }
+
+ private void checkDatagroupHashSeqSize(int size)
+ {
+ if ((size < 2) || (size > ub_DataGroups))
+ {
+ throw new IllegalArgumentException("wrong size in DataGroupHashValues : not in (2.."+ ub_DataGroups +")");
+ }
+ }
+
+ public int getVersion()
+ {
+ return version.getValue().intValue();
+ }
+
+ public AlgorithmIdentifier getDigestAlgorithmIdentifier()
+ {
+ return digestAlgorithmIdentifier;
+ }
+
+ public DataGroupHash[] getDatagroupHash()
+ {
+ return datagroupHash;
+ }
+
+ public LDSVersionInfo getVersionInfo()
+ {
+ return versionInfo;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector seq = new ASN1EncodableVector();
+
+ seq.add(version);
+ seq.add(digestAlgorithmIdentifier);
+
+ ASN1EncodableVector seqname = new ASN1EncodableVector();
+ for (int i = 0; i < datagroupHash.length; i++)
+ {
+ seqname.add(datagroupHash[i]);
+ }
+ seq.add(new DERSequence(seqname));
+
+ if (versionInfo != null)
+ {
+ seq.add(versionInfo);
+ }
+
+ return new DERSequence(seq);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/icao/LDSVersionInfo.java b/core/src/main/java/org/spongycastle/asn1/icao/LDSVersionInfo.java
new file mode 100644
index 00000000..e4cafc29
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/icao/LDSVersionInfo.java
@@ -0,0 +1,75 @@
+package org.spongycastle.asn1.icao;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERPrintableString;
+import org.spongycastle.asn1.DERSequence;
+
+public class LDSVersionInfo
+ extends ASN1Object
+{
+ private DERPrintableString ldsVersion;
+ private DERPrintableString unicodeVersion;
+
+ public LDSVersionInfo(String ldsVersion, String unicodeVersion)
+ {
+ this.ldsVersion = new DERPrintableString(ldsVersion);
+ this.unicodeVersion = new DERPrintableString(unicodeVersion);
+ }
+
+ private LDSVersionInfo(ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("sequence wrong size for LDSVersionInfo");
+ }
+
+ this.ldsVersion = DERPrintableString.getInstance(seq.getObjectAt(0));
+ this.unicodeVersion = DERPrintableString.getInstance(seq.getObjectAt(1));
+ }
+
+ public static LDSVersionInfo getInstance(Object obj)
+ {
+ if (obj instanceof LDSVersionInfo)
+ {
+ return (LDSVersionInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new LDSVersionInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public String getLdsVersion()
+ {
+ return ldsVersion.getString();
+ }
+
+ public String getUnicodeVersion()
+ {
+ return unicodeVersion.getString();
+ }
+
+ /**
+ * <pre>
+ * LDSVersionInfo ::= SEQUENCE {
+ * ldsVersion PRINTABLE STRING
+ * unicodeVersion PRINTABLE STRING
+ * }
+ * </pre>
+ * @return
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(ldsVersion);
+ v.add(unicodeVersion);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/isismtt/ISISMTTObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/isismtt/ISISMTTObjectIdentifiers.java
new file mode 100644
index 00000000..3add7dc9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/isismtt/ISISMTTObjectIdentifiers.java
@@ -0,0 +1,210 @@
+package org.spongycastle.asn1.isismtt;
+
+import org.spongycastle.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");
+
+ /**
+ * The id-isismtt-cp-accredited OID indicates that the certificate is a
+ * qualified certificate according to Directive 1999/93/EC of the European
+ * 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
+ * </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");
+
+ /**
+ * Monetary limit for transactions. The QcEuMonetaryLimit QC statement MUST
+ * be used in new certificates in place of the extension/attribute
+ * 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))
+ * </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".
+ * <pre>
+ * 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");
+
+ /**
+ * 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))
+ * </pre>
+ * <p>
+ * OID: 1.3.36.8.3.8
+ *
+ * @see org.spongycastle.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
+ * </pre>
+ * <p>
+ * OID: 1.3.36.8.3.9
+ */
+ static final ASN1ObjectIdentifier id_isismtt_at_retrieveIfAllowed = id_isismtt_at.branch("9");
+
+ /**
+ * 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.spongycastle.asn1.isismtt.ocsp.RequestedCertificate
+ */
+ static final ASN1ObjectIdentifier id_isismtt_at_requestedCertificate = id_isismtt_at.branch("10");
+
+ /**
+ * 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");
+
+ /**
+ * SingleOCSPResponse extension: Date, when certificate has been published
+ * in the directory and status information has become available. Currently,
+ * accrediting authorities enforce that SigG-conforming OCSP servers include
+ * this extension in the responses.
+ *
+ * <pre>
+ * 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.spongycastle.asn1.isismtt.ocsp.CertHash
+ */
+ static final ASN1ObjectIdentifier id_isismtt_at_certHash = id_isismtt_at.branch("13");
+
+ /**
+ * <pre>
+ * NameAtBirth ::= DirectoryString(SIZE(1..64)
+ * </pre>
+ *
+ * Used in
+ * {@link org.spongycastle.asn1.x509.SubjectDirectoryAttributes SubjectDirectoryAttributes}
+ * <p>
+ * OID: 1.3.36.8.3.14
+ */
+ static final ASN1ObjectIdentifier id_isismtt_at_nameAtBirth = id_isismtt_at.branch("14");
+
+ /**
+ * Some other information of non-restrictive nature regarding the usage of
+ * this certificate. May be used as attribute in atribute certificate or as
+ * extension in a certificate.
+ *
+ * <pre>
+ * AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
+ * </pre>
+ * <p>
+ * OID: 1.3.36.8.3.15
+ *
+ * @see org.spongycastle.asn1.isismtt.x509.AdditionalInformationSyntax
+ */
+ static final ASN1ObjectIdentifier id_isismtt_at_additionalInformation = id_isismtt_at.branch("15");
+
+ /**
+ * Indicates that an attribute certificate exists, which limits the
+ * usability of this public key certificate. Whenever verifying a signature
+ * with the help of this certificate, the content of the corresponding
+ * attribute certificate should be concerned. This extension MUST be
+ * included in a PKC, if a corresponding attribute certificate (having the
+ * 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
+ * </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/core/src/main/java/org/spongycastle/asn1/isismtt/ocsp/CertHash.java b/core/src/main/java/org/spongycastle/asn1/isismtt/ocsp/CertHash.java
new file mode 100644
index 00000000..83a85695
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/isismtt/ocsp/CertHash.java
@@ -0,0 +1,121 @@
+package org.spongycastle.asn1.isismtt.ocsp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * ISIS-MTT PROFILE: The responder may include this extension in a response to
+ * send the hash of the requested certificate to the responder. This hash is
+ * cryptographically bound to the certificate and serves as evidence that the
+ * certificate is known to the responder (i.e. it has been issued and is present
+ * in the directory). Hence, this extension is a means to provide a positive
+ * statement of availability as described in T8.[8]. As explained in T13.[1],
+ * clients may rely on this information to be able to validate signatures after
+ * the expiry of the corresponding certificate. Hence, clients MUST support this
+ * extension. If a positive statement of availability is to be delivered, this
+ * extension syntax and OID MUST be used.
+ * <pre>
+ * CertHash ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * certificateHash OCTET STRING
+ * }
+ * </pre>
+ */
+public class CertHash
+ extends ASN1Object
+{
+
+ private AlgorithmIdentifier hashAlgorithm;
+ private byte[] certificateHash;
+
+ public static CertHash getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof CertHash)
+ {
+ return (CertHash)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new CertHash((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ * <p/>
+ * The sequence is of type CertHash:
+ * <p/>
+ * <pre>
+ * CertHash ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * certificateHash OCTET STRING
+ * }
+ * </pre>
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private CertHash(ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ hashAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(0));
+ certificateHash = DEROctetString.getInstance(seq.getObjectAt(1)).getOctets();
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param hashAlgorithm The hash algorithm identifier.
+ * @param certificateHash The hash of the whole DER encoding of the certificate.
+ */
+ public CertHash(AlgorithmIdentifier hashAlgorithm, byte[] certificateHash)
+ {
+ this.hashAlgorithm = hashAlgorithm;
+ this.certificateHash = new byte[certificateHash.length];
+ System.arraycopy(certificateHash, 0, this.certificateHash, 0,
+ certificateHash.length);
+ }
+
+ public AlgorithmIdentifier getHashAlgorithm()
+ {
+ return hashAlgorithm;
+ }
+
+ public byte[] getCertificateHash()
+ {
+ return certificateHash;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <p>
+ * Returns:
+ * <pre>
+ * CertHash ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * certificateHash OCTET STRING
+ * }
+ * </pre>
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+ vec.add(hashAlgorithm);
+ vec.add(new DEROctetString(certificateHash));
+ return new DERSequence(vec);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/isismtt/ocsp/RequestedCertificate.java b/core/src/main/java/org/spongycastle/asn1/isismtt/ocsp/RequestedCertificate.java
new file mode 100644
index 00000000..c00e3721
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/isismtt/ocsp/RequestedCertificate.java
@@ -0,0 +1,181 @@
+package org.spongycastle.asn1.isismtt.ocsp;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.Certificate;
+
+/**
+ * ISIS-MTT-Optional: The certificate requested by the client by inserting the
+ * RetrieveIfAllowed extension in the request, will be returned in this
+ * extension.
+ * <p>
+ * ISIS-MTT-SigG: The signature act allows publishing certificates only then,
+ * when the certificate owner gives his explicit permission. Accordingly, there
+ * may be �nondownloadable� certificates, about which the responder must provide
+ * status information, but MUST NOT include them in the response. Clients may
+ * get therefore the following three kind of answers on a single request
+ * including the RetrieveIfAllowed extension:
+ * <ul>
+ * <li> a) the responder supports the extension and is allowed to publish the
+ * certificate: RequestedCertificate returned including the requested
+ * certificate
+ * <li>b) the responder supports the extension but is NOT allowed to publish
+ * the certificate: RequestedCertificate returned including an empty OCTET
+ * STRING
+ * <li>c) the responder does not support the extension: RequestedCertificate is
+ * not included in the response
+ * </ul>
+ * Clients requesting RetrieveIfAllowed MUST be able to handle these cases. If
+ * any of the OCTET STRING options is used, it MUST contain the DER encoding of
+ * the requested certificate.
+ * <pre>
+ * RequestedCertificate ::= CHOICE {
+ * Certificate Certificate,
+ * publicKeyCertificate [0] EXPLICIT OCTET STRING,
+ * attributeCertificate [1] EXPLICIT OCTET STRING
+ * }
+ * </pre>
+ */
+public class RequestedCertificate
+ extends ASN1Object
+ implements ASN1Choice
+{
+ public static final int certificate = -1;
+ public static final int publicKeyCertificate = 0;
+ public static final int attributeCertificate = 1;
+
+ private Certificate cert;
+ private byte[] publicKeyCert;
+ private byte[] attributeCert;
+
+ public static RequestedCertificate getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof RequestedCertificate)
+ {
+ return (RequestedCertificate)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new RequestedCertificate(Certificate.getInstance(obj));
+ }
+ if (obj instanceof ASN1TaggedObject)
+ {
+ return new RequestedCertificate((ASN1TaggedObject)obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ public static RequestedCertificate getInstance(ASN1TaggedObject obj, boolean explicit)
+ {
+ if (!explicit)
+ {
+ throw new IllegalArgumentException("choice item must be explicitly tagged");
+ }
+
+ return getInstance(obj.getObject());
+ }
+
+ private RequestedCertificate(ASN1TaggedObject tagged)
+ {
+ if (tagged.getTagNo() == publicKeyCertificate)
+ {
+ publicKeyCert = ASN1OctetString.getInstance(tagged, true).getOctets();
+ }
+ else if (tagged.getTagNo() == attributeCertificate)
+ {
+ attributeCert = ASN1OctetString.getInstance(tagged, true).getOctets();
+ }
+ else
+ {
+ throw new IllegalArgumentException("unknown tag number: " + tagged.getTagNo());
+ }
+ }
+
+ /**
+ * Constructor from a given details.
+ * <p>
+ * Only one parameter can be given. All other must be <code>null</code>.
+ *
+ * @param certificate Given as Certificate
+ */
+ public RequestedCertificate(Certificate certificate)
+ {
+ this.cert = certificate;
+ }
+
+ public RequestedCertificate(int type, byte[] certificateOctets)
+ {
+ this(new DERTaggedObject(type, new DEROctetString(certificateOctets)));
+ }
+
+ public int getType()
+ {
+ if (cert != null)
+ {
+ return certificate;
+ }
+ if (publicKeyCert != null)
+ {
+ return publicKeyCertificate;
+ }
+ return attributeCertificate;
+ }
+
+ public byte[] getCertificateBytes()
+ {
+ if (cert != null)
+ {
+ try
+ {
+ return cert.getEncoded();
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("can't decode certificate: " + e);
+ }
+ }
+ if (publicKeyCert != null)
+ {
+ return publicKeyCert;
+ }
+ return attributeCert;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <p>
+ * Returns:
+ * <pre>
+ * RequestedCertificate ::= CHOICE {
+ * Certificate Certificate,
+ * publicKeyCertificate [0] EXPLICIT OCTET STRING,
+ * attributeCertificate [1] EXPLICIT OCTET STRING
+ * }
+ * </pre>
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (publicKeyCert != null)
+ {
+ return new DERTaggedObject(0, new DEROctetString(publicKeyCert));
+ }
+ if (attributeCert != null)
+ {
+ return new DERTaggedObject(1, new DEROctetString(attributeCert));
+ }
+ return cert.toASN1Primitive();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/isismtt/x509/AdditionalInformationSyntax.java b/core/src/main/java/org/spongycastle/asn1/isismtt/x509/AdditionalInformationSyntax.java
new file mode 100644
index 00000000..948f5ba4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/isismtt/x509/AdditionalInformationSyntax.java
@@ -0,0 +1,69 @@
+package org.spongycastle.asn1.isismtt.x509;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.x500.DirectoryString;
+
+/**
+ * Some other information of non-restrictive nature regarding the usage of this
+ * certificate.
+ *
+ * <pre>
+ * AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
+ * </pre>
+ */
+public class AdditionalInformationSyntax
+ extends ASN1Object
+{
+ private DirectoryString information;
+
+ public static AdditionalInformationSyntax getInstance(Object obj)
+ {
+ if (obj instanceof AdditionalInformationSyntax)
+ {
+ return (AdditionalInformationSyntax)obj;
+ }
+
+ if (obj != null)
+ {
+ return new AdditionalInformationSyntax(DirectoryString.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private AdditionalInformationSyntax(DirectoryString information)
+ {
+ this.information = information;
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param information The describtion of the information.
+ */
+ public AdditionalInformationSyntax(String information)
+ {
+ this(new DirectoryString(information));
+ }
+
+ public DirectoryString getInformation()
+ {
+ return information;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <p>
+ * Returns:
+ * <pre>
+ * AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
+ * </pre>
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return information.toASN1Primitive();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/isismtt/x509/AdmissionSyntax.java b/core/src/main/java/org/spongycastle/asn1/isismtt/x509/AdmissionSyntax.java
new file mode 100644
index 00000000..bc4a667f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/isismtt/x509/AdmissionSyntax.java
@@ -0,0 +1,276 @@
+package org.spongycastle.asn1.isismtt.x509;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.GeneralName;
+
+/**
+ * Attribute to indicate admissions to certain professions.
+ *
+ * <pre>
+ * AdmissionSyntax ::= SEQUENCE
+ * {
+ * admissionAuthority GeneralName OPTIONAL,
+ * contentsOfAdmissions SEQUENCE OF Admissions
+ * }
+ *
+ * Admissions ::= SEQUENCE
+ * {
+ * admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+ * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+ * professionInfos SEQUENCE OF ProfessionInfo
+ * }
+ *
+ * NamingAuthority ::= SEQUENCE
+ * {
+ * namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
+ * namingAuthorityUrl IA5String OPTIONAL,
+ * namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+ * }
+ *
+ * ProfessionInfo ::= SEQUENCE
+ * {
+ * namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+ * professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+ * professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+ * registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+ * addProfessionInfo OCTET STRING OPTIONAL
+ * }
+ * </pre>
+ * <p>
+ * ISIS-MTT PROFILE: The relatively complex structure of AdmissionSyntax
+ * supports the following concepts and requirements:
+ * <ul>
+ * <li> External institutions (e.g. professional associations, chambers, unions,
+ * administrative bodies, companies, etc.), which are responsible for granting
+ * and verifying professional admissions, are indicated by means of the data
+ * field admissionAuthority. An admission authority is indicated by a
+ * GeneralName object. Here an X.501 directory name (distinguished name) can be
+ * indicated in the field directoryName, a URL address can be indicated in the
+ * field uniformResourceIdentifier, and an object identifier can be indicated in
+ * the field registeredId.
+ * <li> The names of authorities which are responsible for the administration of
+ * title registers are indicated in the data field namingAuthority. The name of
+ * the authority can be identified by an object identifier in the field
+ * namingAuthorityId, by means of a text string in the field
+ * namingAuthorityText, by means of a URL address in the field
+ * namingAuthorityUrl, or by a combination of them. For example, the text string
+ * can contain the name of the authority, the country and the name of the title
+ * register. The URL-option refers to a web page which contains lists with
+ * �officially� registered professions (text and possibly OID) as well as
+ * further information on these professions. Object identifiers for the
+ * component namingAuthorityId are grouped under the OID-branch
+ * id-isis-at-namingAuthorities and must be applied for.
+ * <li>See
+ * http://www.teletrust.de/anwend.asp?Id=30200&amp;Sprache=E_&amp;HomePG=0 for
+ * an application form and http://www.teletrust.de/links.asp?id=30220,11
+ * for an overview of registered naming authorities.
+ * <li> By means of the data type ProfessionInfo certain professions,
+ * specializations, disciplines, fields of activity, etc. are identified. A
+ * profession is represented by one or more text strings, resp. profession OIDs
+ * in the fields professionItems and professionOIDs and by a registration number
+ * in the field registrationNumber. An indication in text form must always be
+ * present, whereas the other indications are optional. The component
+ * addProfessionInfo may contain additional applicationspecific information in
+ * DER-encoded form.
+ * </ul>
+ * <p>
+ * By means of different namingAuthority-OIDs or profession OIDs hierarchies of
+ * professions, specializations, disciplines, fields of activity, etc. can be
+ * expressed. The issuing admission authority should always be indicated (field
+ * admissionAuthority), whenever a registration number is presented. Still,
+ * information on admissions can be given without indicating an admission or a
+ * naming authority by the exclusive use of the component professionItems. In
+ * this case the certification authority is responsible for the verification of
+ * the admission information.
+ * <p>
+ * This attribute is single-valued. Still, several admissions can be captured in
+ * the sequence structure of the component contentsOfAdmissions of
+ * AdmissionSyntax or in the component professionInfos of Admissions. The
+ * component admissionAuthority of AdmissionSyntax serves as default value for
+ * the component admissionAuthority of Admissions. Within the latter component
+ * the default value can be overwritten, in case that another authority is
+ * responsible. The component namingAuthority of Admissions serves as a default
+ * value for the component namingAuthority of ProfessionInfo. Within the latter
+ * component the default value can be overwritten, in case that another naming
+ * authority needs to be recorded.
+ * <p>
+ * The length of the string objects is limited to 128 characters. It is
+ * recommended to indicate a namingAuthorityURL in all issued attribute
+ * certificates. If a namingAuthorityURL is indicated, the field professionItems
+ * of ProfessionInfo should contain only registered titles. If the field
+ * professionOIDs exists, it has to contain the OIDs of the professions listed
+ * in professionItems in the same order. In general, the field professionInfos
+ * should contain only one entry, unless the admissions that are to be listed
+ * are logically connected (e.g. they have been issued under the same admission
+ * number).
+ *
+ * @see org.spongycastle.asn1.isismtt.x509.Admissions
+ * @see org.spongycastle.asn1.isismtt.x509.ProfessionInfo
+ * @see org.spongycastle.asn1.isismtt.x509.NamingAuthority
+ */
+public class AdmissionSyntax
+ extends ASN1Object
+{
+
+ private GeneralName admissionAuthority;
+
+ private ASN1Sequence contentsOfAdmissions;
+
+ public static AdmissionSyntax getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof AdmissionSyntax)
+ {
+ return (AdmissionSyntax)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new AdmissionSyntax((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ * <p/>
+ * The sequence is of type ProcurationSyntax:
+ * <p/>
+ * <pre>
+ * AdmissionSyntax ::= SEQUENCE
+ * {
+ * admissionAuthority GeneralName OPTIONAL,
+ * contentsOfAdmissions SEQUENCE OF Admissions
+ * }
+ * <p/>
+ * Admissions ::= SEQUENCE
+ * {
+ * admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+ * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+ * professionInfos SEQUENCE OF ProfessionInfo
+ * }
+ * <p/>
+ * NamingAuthority ::= SEQUENCE
+ * {
+ * namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
+ * namingAuthorityUrl IA5String OPTIONAL,
+ * namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+ * }
+ * <p/>
+ * ProfessionInfo ::= SEQUENCE
+ * {
+ * namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+ * professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+ * professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+ * registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+ * addProfessionInfo OCTET STRING OPTIONAL
+ * }
+ * </pre>
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private AdmissionSyntax(ASN1Sequence seq)
+ {
+ switch (seq.size())
+ {
+ case 1:
+ contentsOfAdmissions = DERSequence.getInstance(seq.getObjectAt(0));
+ break;
+ case 2:
+ admissionAuthority = GeneralName.getInstance(seq.getObjectAt(0));
+ contentsOfAdmissions = DERSequence.getInstance(seq.getObjectAt(1));
+ break;
+ default:
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+ }
+
+ /**
+ * Constructor from given details.
+ *
+ * @param admissionAuthority The admission authority.
+ * @param contentsOfAdmissions The admissions.
+ */
+ public AdmissionSyntax(GeneralName admissionAuthority, ASN1Sequence contentsOfAdmissions)
+ {
+ this.admissionAuthority = admissionAuthority;
+ this.contentsOfAdmissions = contentsOfAdmissions;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <p>
+ * Returns:
+ * <pre>
+ * AdmissionSyntax ::= SEQUENCE
+ * {
+ * admissionAuthority GeneralName OPTIONAL,
+ * contentsOfAdmissions SEQUENCE OF Admissions
+ * }
+ *
+ * Admissions ::= SEQUENCE
+ * {
+ * admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+ * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+ * professionInfos SEQUENCE OF ProfessionInfo
+ * }
+ *
+ * NamingAuthority ::= SEQUENCE
+ * {
+ * namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
+ * namingAuthorityUrl IA5String OPTIONAL,
+ * namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+ * }
+ *
+ * ProfessionInfo ::= SEQUENCE
+ * {
+ * namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+ * professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+ * professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+ * registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+ * addProfessionInfo OCTET STRING OPTIONAL
+ * }
+ * </pre>
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+ if (admissionAuthority != null)
+ {
+ vec.add(admissionAuthority);
+ }
+ vec.add(contentsOfAdmissions);
+ return new DERSequence(vec);
+ }
+
+ /**
+ * @return Returns the admissionAuthority if present, null otherwise.
+ */
+ public GeneralName getAdmissionAuthority()
+ {
+ return admissionAuthority;
+ }
+
+ /**
+ * @return Returns the contentsOfAdmissions.
+ */
+ public Admissions[] getContentsOfAdmissions()
+ {
+ Admissions[] admissions = new Admissions[contentsOfAdmissions.size()];
+ int count = 0;
+ for (Enumeration e = contentsOfAdmissions.getObjects(); e.hasMoreElements();)
+ {
+ admissions[count++] = Admissions.getInstance(e.nextElement());
+ }
+ return admissions;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/isismtt/x509/Admissions.java b/core/src/main/java/org/spongycastle/asn1/isismtt/x509/Admissions.java
new file mode 100644
index 00000000..db0cefa3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/isismtt/x509/Admissions.java
@@ -0,0 +1,185 @@
+package org.spongycastle.asn1.isismtt.x509;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.GeneralName;
+
+/**
+ * An Admissions structure.
+ * <pre>
+ * Admissions ::= SEQUENCE
+ * {
+ * admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+ * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+ * professionInfos SEQUENCE OF ProfessionInfo
+ * }
+ * </pre>
+ *
+ * @see org.spongycastle.asn1.isismtt.x509.AdmissionSyntax
+ * @see org.spongycastle.asn1.isismtt.x509.ProfessionInfo
+ * @see org.spongycastle.asn1.isismtt.x509.NamingAuthority
+ */
+public class Admissions
+ extends ASN1Object
+{
+
+ private GeneralName admissionAuthority;
+
+ private NamingAuthority namingAuthority;
+
+ private ASN1Sequence professionInfos;
+
+ public static Admissions getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof Admissions)
+ {
+ return (Admissions)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new Admissions((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ * <p/>
+ * The sequence is of type ProcurationSyntax:
+ * <p/>
+ * <pre>
+ * Admissions ::= SEQUENCE
+ * {
+ * admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+ * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+ * professionInfos SEQUENCE OF ProfessionInfo
+ * }
+ * </pre>
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private Admissions(ASN1Sequence seq)
+ {
+ if (seq.size() > 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ Enumeration e = seq.getObjects();
+
+ ASN1Encodable o = (ASN1Encodable)e.nextElement();
+ if (o instanceof ASN1TaggedObject)
+ {
+ switch (((ASN1TaggedObject)o).getTagNo())
+ {
+ case 0:
+ admissionAuthority = GeneralName.getInstance((ASN1TaggedObject)o, true);
+ break;
+ case 1:
+ namingAuthority = NamingAuthority.getInstance((ASN1TaggedObject)o, true);
+ break;
+ default:
+ throw new IllegalArgumentException("Bad tag number: " + ((ASN1TaggedObject)o).getTagNo());
+ }
+ o = (ASN1Encodable)e.nextElement();
+ }
+ if (o instanceof ASN1TaggedObject)
+ {
+ switch (((ASN1TaggedObject)o).getTagNo())
+ {
+ case 1:
+ namingAuthority = NamingAuthority.getInstance((ASN1TaggedObject)o, true);
+ break;
+ default:
+ throw new IllegalArgumentException("Bad tag number: " + ((ASN1TaggedObject)o).getTagNo());
+ }
+ o = (ASN1Encodable)e.nextElement();
+ }
+ professionInfos = ASN1Sequence.getInstance(o);
+ if (e.hasMoreElements())
+ {
+ throw new IllegalArgumentException("Bad object encountered: "
+ + e.nextElement().getClass());
+ }
+ }
+
+ /**
+ * Constructor from a given details.
+ * <p>
+ * Parameter <code>professionInfos</code> is mandatory.
+ *
+ * @param admissionAuthority The admission authority.
+ * @param namingAuthority The naming authority.
+ * @param professionInfos The profession infos.
+ */
+ public Admissions(GeneralName admissionAuthority,
+ NamingAuthority namingAuthority, ProfessionInfo[] professionInfos)
+ {
+ this.admissionAuthority = admissionAuthority;
+ this.namingAuthority = namingAuthority;
+ this.professionInfos = new DERSequence(professionInfos);
+ }
+
+ public GeneralName getAdmissionAuthority()
+ {
+ return admissionAuthority;
+ }
+
+ public NamingAuthority getNamingAuthority()
+ {
+ return namingAuthority;
+ }
+
+ public ProfessionInfo[] getProfessionInfos()
+ {
+ ProfessionInfo[] infos = new ProfessionInfo[professionInfos.size()];
+ int count = 0;
+ for (Enumeration e = professionInfos.getObjects(); e.hasMoreElements();)
+ {
+ infos[count++] = ProfessionInfo.getInstance(e.nextElement());
+ }
+ return infos;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <p>
+ * Returns:
+ * <pre>
+ * Admissions ::= SEQUENCE
+ * {
+ * admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+ * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+ * professionInfos SEQUENCE OF ProfessionInfo
+ * }
+ * </pre>
+ *
+ * @return an ASN1Primitive
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+
+ if (admissionAuthority != null)
+ {
+ vec.add(new DERTaggedObject(true, 0, admissionAuthority));
+ }
+ if (namingAuthority != null)
+ {
+ vec.add(new DERTaggedObject(true, 1, namingAuthority));
+ }
+ vec.add(professionInfos);
+
+ return new DERSequence(vec);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/isismtt/x509/DeclarationOfMajority.java b/core/src/main/java/org/spongycastle/asn1/isismtt/x509/DeclarationOfMajority.java
new file mode 100644
index 00000000..900f4c08
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/isismtt/x509/DeclarationOfMajority.java
@@ -0,0 +1,163 @@
+package org.spongycastle.asn1.isismtt.x509;
+
+import org.spongycastle.asn1.ASN1Boolean;
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERPrintableString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+/**
+ * A declaration of majority.
+ *
+ * <pre>
+ * DeclarationOfMajoritySyntax ::= CHOICE
+ * {
+ * notYoungerThan [0] IMPLICIT INTEGER,
+ * fullAgeAtCountry [1] IMPLICIT SEQUENCE
+ * {
+ * fullAge BOOLEAN DEFAULT TRUE,
+ * country PrintableString (SIZE(2))
+ * }
+ * dateOfBirth [2] IMPLICIT GeneralizedTime
+ * }
+ * </pre>
+ * <p>
+ * fullAgeAtCountry indicates the majority of the owner with respect to the laws
+ * of a specific country.
+ */
+public class DeclarationOfMajority
+ extends ASN1Object
+ implements ASN1Choice
+{
+ public static final int notYoungerThan = 0;
+ public static final int fullAgeAtCountry = 1;
+ public static final int dateOfBirth = 2;
+
+ private ASN1TaggedObject declaration;
+
+ public DeclarationOfMajority(int notYoungerThan)
+ {
+ declaration = new DERTaggedObject(false, 0, new ASN1Integer(notYoungerThan));
+ }
+
+ public DeclarationOfMajority(boolean fullAge, String country)
+ {
+ if (country.length() > 2)
+ {
+ throw new IllegalArgumentException("country can only be 2 characters");
+ }
+
+ if (fullAge)
+ {
+ declaration = new DERTaggedObject(false, 1, new DERSequence(new DERPrintableString(country, true)));
+ }
+ else
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(ASN1Boolean.FALSE);
+ v.add(new DERPrintableString(country, true));
+
+ declaration = new DERTaggedObject(false, 1, new DERSequence(v));
+ }
+ }
+
+ public DeclarationOfMajority(ASN1GeneralizedTime dateOfBirth)
+ {
+ declaration = new DERTaggedObject(false, 2, dateOfBirth);
+ }
+
+ public static DeclarationOfMajority getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof DeclarationOfMajority)
+ {
+ return (DeclarationOfMajority)obj;
+ }
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ return new DeclarationOfMajority((ASN1TaggedObject)obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ private DeclarationOfMajority(ASN1TaggedObject o)
+ {
+ if (o.getTagNo() > 2)
+ {
+ throw new IllegalArgumentException("Bad tag number: " + o.getTagNo());
+ }
+ declaration = o;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <p>
+ * Returns:
+ * <pre>
+ * DeclarationOfMajoritySyntax ::= CHOICE
+ * {
+ * notYoungerThan [0] IMPLICIT INTEGER,
+ * fullAgeAtCountry [1] IMPLICIT SEQUENCE
+ * {
+ * fullAge BOOLEAN DEFAULT TRUE,
+ * country PrintableString (SIZE(2))
+ * }
+ * dateOfBirth [2] IMPLICIT GeneralizedTime
+ * }
+ * </pre>
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return declaration;
+ }
+
+ public int getType()
+ {
+ return declaration.getTagNo();
+ }
+
+ /**
+ * @return notYoungerThan if that's what we are, -1 otherwise
+ */
+ public int notYoungerThan()
+ {
+ if (declaration.getTagNo() != 0)
+ {
+ return -1;
+ }
+
+ return ASN1Integer.getInstance(declaration, false).getValue().intValue();
+ }
+
+ public ASN1Sequence fullAgeAtCountry()
+ {
+ if (declaration.getTagNo() != 1)
+ {
+ return null;
+ }
+
+ return ASN1Sequence.getInstance(declaration, false);
+ }
+
+ public ASN1GeneralizedTime getDateOfBirth()
+ {
+ if (declaration.getTagNo() != 2)
+ {
+ return null;
+ }
+
+ return ASN1GeneralizedTime.getInstance(declaration, false);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/isismtt/x509/MonetaryLimit.java b/core/src/main/java/org/spongycastle/asn1/isismtt/x509/MonetaryLimit.java
new file mode 100644
index 00000000..71f08dd1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/isismtt/x509/MonetaryLimit.java
@@ -0,0 +1,128 @@
+package org.spongycastle.asn1.isismtt.x509;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERPrintableString;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * Monetary limit for transactions. The QcEuMonetaryLimit QC statement MUST be
+ * used in new certificates in place of the extension/attribute MonetaryLimit
+ * since January 1, 2004. For the sake of backward compatibility with
+ * certificates already in use, components SHOULD support MonetaryLimit (as well
+ * as QcEuLimitValue).
+ * <p>
+ * Indicates a monetary limit within which the certificate holder is authorized
+ * to act. (This value DOES NOT express a limit on the liability of the
+ * certification authority).
+ * <pre>
+ * MonetaryLimitSyntax ::= SEQUENCE
+ * {
+ * currency PrintableString (SIZE(3)),
+ * amount INTEGER,
+ * exponent INTEGER
+ * }
+ * </pre>
+ * <p>
+ * currency must be the ISO code.
+ * <p>
+ * value = amount�10*exponent
+ */
+public class MonetaryLimit
+ extends ASN1Object
+{
+ DERPrintableString currency;
+ ASN1Integer amount;
+ ASN1Integer exponent;
+
+ public static MonetaryLimit getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof MonetaryLimit)
+ {
+ return (MonetaryLimit)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new MonetaryLimit(ASN1Sequence.getInstance(obj));
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance");
+ }
+
+ private MonetaryLimit(ASN1Sequence seq)
+ {
+ if (seq.size() != 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ Enumeration e = seq.getObjects();
+ currency = DERPrintableString.getInstance(e.nextElement());
+ amount = ASN1Integer.getInstance(e.nextElement());
+ exponent = ASN1Integer.getInstance(e.nextElement());
+ }
+
+ /**
+ * Constructor from a given details.
+ * <p>
+ * value = amount�10^exponent
+ *
+ * @param currency The currency. Must be the ISO code.
+ * @param amount The amount
+ * @param exponent The exponent
+ */
+ public MonetaryLimit(String currency, int amount, int exponent)
+ {
+ this.currency = new DERPrintableString(currency, true);
+ this.amount = new ASN1Integer(amount);
+ this.exponent = new ASN1Integer(exponent);
+ }
+
+ public String getCurrency()
+ {
+ return currency.getString();
+ }
+
+ public BigInteger getAmount()
+ {
+ return amount.getValue();
+ }
+
+ public BigInteger getExponent()
+ {
+ return exponent.getValue();
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <p>
+ * Returns:
+ * <pre>
+ * MonetaryLimitSyntax ::= SEQUENCE
+ * {
+ * currency PrintableString (SIZE(3)),
+ * amount INTEGER,
+ * exponent INTEGER
+ * }
+ * </pre>
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector seq = new ASN1EncodableVector();
+ seq.add(currency);
+ seq.add(amount);
+ seq.add(exponent);
+
+ return new DERSequence(seq);
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/isismtt/x509/NamingAuthority.java b/core/src/main/java/org/spongycastle/asn1/isismtt/x509/NamingAuthority.java
new file mode 100644
index 00000000..944a0c31
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/isismtt/x509/NamingAuthority.java
@@ -0,0 +1,224 @@
+package org.spongycastle.asn1.isismtt.x509;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1String;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.isismtt.ISISMTTObjectIdentifiers;
+import org.spongycastle.asn1.x500.DirectoryString;
+
+/**
+ * Names of authorities which are responsible for the administration of title
+ * registers.
+ *
+ * <pre>
+ * NamingAuthority ::= SEQUENCE
+ * {
+ * namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
+ * namingAuthorityUrl IA5String OPTIONAL,
+ * namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+ * }
+ * </pre>
+ * @see org.spongycastle.asn1.isismtt.x509.AdmissionSyntax
+ *
+ */
+public class NamingAuthority
+ extends ASN1Object
+{
+
+ /**
+ * Profession OIDs should always be defined under the OID branch of the
+ * responsible naming authority. At the time of this writing, the work group
+ * �Recht, Wirtschaft, Steuern� (�Law, Economy, Taxes�) is registered as the
+ * first naming authority under the OID id-isismtt-at-namingAuthorities.
+ */
+ public static final ASN1ObjectIdentifier id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern =
+ new ASN1ObjectIdentifier(ISISMTTObjectIdentifiers.id_isismtt_at_namingAuthorities + ".1");
+
+ private ASN1ObjectIdentifier namingAuthorityId;
+ private String namingAuthorityUrl;
+ private DirectoryString namingAuthorityText;
+
+ public static NamingAuthority getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof NamingAuthority)
+ {
+ return (NamingAuthority)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new NamingAuthority((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ public static NamingAuthority getInstance(ASN1TaggedObject obj, boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ * <p/>
+ * <p/>
+ * <pre>
+ * NamingAuthority ::= SEQUENCE
+ * {
+ * namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
+ * namingAuthorityUrl IA5String OPTIONAL,
+ * namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+ * }
+ * </pre>
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private NamingAuthority(ASN1Sequence seq)
+ {
+
+ if (seq.size() > 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ Enumeration e = seq.getObjects();
+
+ if (e.hasMoreElements())
+ {
+ ASN1Encodable o = (ASN1Encodable)e.nextElement();
+ if (o instanceof ASN1ObjectIdentifier)
+ {
+ namingAuthorityId = (ASN1ObjectIdentifier)o;
+ }
+ else if (o instanceof DERIA5String)
+ {
+ namingAuthorityUrl = DERIA5String.getInstance(o).getString();
+ }
+ else if (o instanceof ASN1String)
+ {
+ namingAuthorityText = DirectoryString.getInstance(o);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad object encountered: "
+ + o.getClass());
+ }
+ }
+ if (e.hasMoreElements())
+ {
+ ASN1Encodable o = (ASN1Encodable)e.nextElement();
+ if (o instanceof DERIA5String)
+ {
+ namingAuthorityUrl = DERIA5String.getInstance(o).getString();
+ }
+ else if (o instanceof ASN1String)
+ {
+ namingAuthorityText = DirectoryString.getInstance(o);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad object encountered: "
+ + o.getClass());
+ }
+ }
+ if (e.hasMoreElements())
+ {
+ ASN1Encodable o = (ASN1Encodable)e.nextElement();
+ if (o instanceof ASN1String)
+ {
+ namingAuthorityText = DirectoryString.getInstance(o);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad object encountered: "
+ + o.getClass());
+ }
+
+ }
+ }
+
+ /**
+ * @return Returns the namingAuthorityId.
+ */
+ public ASN1ObjectIdentifier getNamingAuthorityId()
+ {
+ return namingAuthorityId;
+ }
+
+ /**
+ * @return Returns the namingAuthorityText.
+ */
+ public DirectoryString getNamingAuthorityText()
+ {
+ return namingAuthorityText;
+ }
+
+ /**
+ * @return Returns the namingAuthorityUrl.
+ */
+ public String getNamingAuthorityUrl()
+ {
+ return namingAuthorityUrl;
+ }
+
+ /**
+ * Constructor from given details.
+ * <p>
+ * All parameters can be combined.
+ *
+ * @param namingAuthorityId ObjectIdentifier for naming authority.
+ * @param namingAuthorityUrl URL for naming authority.
+ * @param namingAuthorityText Textual representation of naming authority.
+ */
+ public NamingAuthority(ASN1ObjectIdentifier namingAuthorityId,
+ String namingAuthorityUrl, DirectoryString namingAuthorityText)
+ {
+ this.namingAuthorityId = namingAuthorityId;
+ this.namingAuthorityUrl = namingAuthorityUrl;
+ this.namingAuthorityText = namingAuthorityText;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <p>
+ * Returns:
+ * <pre>
+ * NamingAuthority ::= SEQUENCE
+ * {
+ * namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
+ * namingAuthorityUrl IA5String OPTIONAL,
+ * namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+ * }
+ * </pre>
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+ if (namingAuthorityId != null)
+ {
+ vec.add(namingAuthorityId);
+ }
+ if (namingAuthorityUrl != null)
+ {
+ vec.add(new DERIA5String(namingAuthorityUrl, true));
+ }
+ if (namingAuthorityText != null)
+ {
+ vec.add(namingAuthorityText);
+ }
+ return new DERSequence(vec);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/isismtt/x509/ProcurationSyntax.java b/core/src/main/java/org/spongycastle/asn1/isismtt/x509/ProcurationSyntax.java
new file mode 100644
index 00000000..5e4ecca5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/isismtt/x509/ProcurationSyntax.java
@@ -0,0 +1,237 @@
+package org.spongycastle.asn1.isismtt.x509;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERPrintableString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x500.DirectoryString;
+import org.spongycastle.asn1.x509.GeneralName;
+import org.spongycastle.asn1.x509.IssuerSerial;
+
+/**
+ * Attribute to indicate that the certificate holder may sign in the name of a
+ * third person.
+ * <p>
+ * ISIS-MTT PROFILE: The corresponding ProcurationSyntax contains either the
+ * name of the person who is represented (subcomponent thirdPerson) or a
+ * reference to his/her base certificate (in the component signingFor,
+ * subcomponent certRef), furthermore the optional components country and
+ * typeSubstitution to indicate the country whose laws apply, and respectively
+ * the type of procuration (e.g. manager, procuration, custody).
+ * <p>
+ * ISIS-MTT PROFILE: The GeneralName MUST be of type directoryName and MAY only
+ * contain: - RFC3039 attributes, except pseudonym (countryName, commonName,
+ * surname, givenName, serialNumber, organizationName, organizationalUnitName,
+ * stateOrProvincename, localityName, postalAddress) and - SubjectDirectoryName
+ * attributes (title, dateOfBirth, placeOfBirth, gender, countryOfCitizenship,
+ * countryOfResidence and NameAtBirth).
+ *
+ * <pre>
+ * ProcurationSyntax ::= SEQUENCE {
+ * country [1] EXPLICIT PrintableString(SIZE(2)) OPTIONAL,
+ * typeOfSubstitution [2] EXPLICIT DirectoryString (SIZE(1..128)) OPTIONAL,
+ * signingFor [3] EXPLICIT SigningFor
+ * }
+ *
+ * SigningFor ::= CHOICE
+ * {
+ * thirdPerson GeneralName,
+ * certRef IssuerSerial
+ * }
+ * </pre>
+ *
+ */
+public class ProcurationSyntax
+ extends ASN1Object
+{
+ private String country;
+ private DirectoryString typeOfSubstitution;
+
+ private GeneralName thirdPerson;
+ private IssuerSerial certRef;
+
+ public static ProcurationSyntax getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof ProcurationSyntax)
+ {
+ return (ProcurationSyntax)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new ProcurationSyntax((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ * <p/>
+ * The sequence is of type ProcurationSyntax:
+ * <p/>
+ * <pre>
+ * ProcurationSyntax ::= SEQUENCE {
+ * country [1] EXPLICIT PrintableString(SIZE(2)) OPTIONAL,
+ * typeOfSubstitution [2] EXPLICIT DirectoryString (SIZE(1..128)) OPTIONAL,
+ * signingFor [3] EXPLICIT SigningFor
+ * }
+ * <p/>
+ * SigningFor ::= CHOICE
+ * {
+ * thirdPerson GeneralName,
+ * certRef IssuerSerial
+ * }
+ * </pre>
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private ProcurationSyntax(ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ ASN1TaggedObject o = ASN1TaggedObject.getInstance(e.nextElement());
+ switch (o.getTagNo())
+ {
+ case 1:
+ country = DERPrintableString.getInstance(o, true).getString();
+ break;
+ case 2:
+ typeOfSubstitution = DirectoryString.getInstance(o, true);
+ break;
+ case 3:
+ ASN1Encodable signingFor = o.getObject();
+ if (signingFor instanceof ASN1TaggedObject)
+ {
+ thirdPerson = GeneralName.getInstance(signingFor);
+ }
+ else
+ {
+ certRef = IssuerSerial.getInstance(signingFor);
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Bad tag number: " + o.getTagNo());
+ }
+ }
+ }
+
+ /**
+ * Constructor from a given details.
+ * <p>
+ * Either <code>generalName</code> or <code>certRef</code> MUST be
+ * <code>null</code>.
+ *
+ * @param country The country code whose laws apply.
+ * @param typeOfSubstitution The type of procuration.
+ * @param certRef Reference to certificate of the person who is represented.
+ */
+ public ProcurationSyntax(
+ String country,
+ DirectoryString typeOfSubstitution,
+ IssuerSerial certRef)
+ {
+ this.country = country;
+ this.typeOfSubstitution = typeOfSubstitution;
+ this.thirdPerson = null;
+ this.certRef = certRef;
+ }
+
+ /**
+ * Constructor from a given details.
+ * <p>
+ * Either <code>generalName</code> or <code>certRef</code> MUST be
+ * <code>null</code>.
+ *
+ * @param country The country code whose laws apply.
+ * @param typeOfSubstitution The type of procuration.
+ * @param thirdPerson The GeneralName of the person who is represented.
+ */
+ public ProcurationSyntax(
+ String country,
+ DirectoryString typeOfSubstitution,
+ GeneralName thirdPerson)
+ {
+ this.country = country;
+ this.typeOfSubstitution = typeOfSubstitution;
+ this.thirdPerson = thirdPerson;
+ this.certRef = null;
+ }
+
+ public String getCountry()
+ {
+ return country;
+ }
+
+ public DirectoryString getTypeOfSubstitution()
+ {
+ return typeOfSubstitution;
+ }
+
+ public GeneralName getThirdPerson()
+ {
+ return thirdPerson;
+ }
+
+ public IssuerSerial getCertRef()
+ {
+ return certRef;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <p>
+ * Returns:
+ * <pre>
+ * ProcurationSyntax ::= SEQUENCE {
+ * country [1] EXPLICIT PrintableString(SIZE(2)) OPTIONAL,
+ * typeOfSubstitution [2] EXPLICIT DirectoryString (SIZE(1..128)) OPTIONAL,
+ * signingFor [3] EXPLICIT SigningFor
+ * }
+ *
+ * SigningFor ::= CHOICE
+ * {
+ * thirdPerson GeneralName,
+ * certRef IssuerSerial
+ * }
+ * </pre>
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+ if (country != null)
+ {
+ vec.add(new DERTaggedObject(true, 1, new DERPrintableString(country, true)));
+ }
+ if (typeOfSubstitution != null)
+ {
+ vec.add(new DERTaggedObject(true, 2, typeOfSubstitution));
+ }
+ if (thirdPerson != null)
+ {
+ vec.add(new DERTaggedObject(true, 3, thirdPerson));
+ }
+ else
+ {
+ vec.add(new DERTaggedObject(true, 3, certRef));
+ }
+
+ return new DERSequence(vec);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/isismtt/x509/ProfessionInfo.java b/core/src/main/java/org/spongycastle/asn1/isismtt/x509/ProfessionInfo.java
new file mode 100644
index 00000000..79b2b525
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/isismtt/x509/ProfessionInfo.java
@@ -0,0 +1,407 @@
+package org.spongycastle.asn1.isismtt.x509;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERPrintableString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x500.DirectoryString;
+
+/**
+ * Professions, specializations, disciplines, fields of activity, etc.
+ *
+ * <pre>
+ * ProfessionInfo ::= SEQUENCE
+ * {
+ * namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+ * professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+ * professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+ * registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+ * addProfessionInfo OCTET STRING OPTIONAL
+ * }
+ * </pre>
+ *
+ * @see org.spongycastle.asn1.isismtt.x509.AdmissionSyntax
+ */
+public class ProfessionInfo
+ extends ASN1Object
+{
+
+ /**
+ * Rechtsanw�ltin
+ */
+ public static final ASN1ObjectIdentifier Rechtsanwltin = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".1");
+
+ /**
+ * Rechtsanwalt
+ */
+ public static final ASN1ObjectIdentifier Rechtsanwalt = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".2");
+
+ /**
+ * Rechtsbeistand
+ */
+ public static final ASN1ObjectIdentifier Rechtsbeistand = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".3");
+
+ /**
+ * Steuerberaterin
+ */
+ public static final ASN1ObjectIdentifier Steuerberaterin = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".4");
+
+ /**
+ * Steuerberater
+ */
+ public static final ASN1ObjectIdentifier Steuerberater = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".5");
+
+ /**
+ * Steuerbevollm�chtigte
+ */
+ public static final ASN1ObjectIdentifier Steuerbevollmchtigte = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".6");
+
+ /**
+ * Steuerbevollm�chtigter
+ */
+ public static final ASN1ObjectIdentifier Steuerbevollmchtigter = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".7");
+
+ /**
+ * Notarin
+ */
+ public static final ASN1ObjectIdentifier Notarin = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".8");
+
+ /**
+ * Notar
+ */
+ public static final ASN1ObjectIdentifier Notar = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".9");
+
+ /**
+ * Notarvertreterin
+ */
+ public static final ASN1ObjectIdentifier Notarvertreterin = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".10");
+
+ /**
+ * Notarvertreter
+ */
+ public static final ASN1ObjectIdentifier Notarvertreter = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".11");
+
+ /**
+ * Notariatsverwalterin
+ */
+ public static final ASN1ObjectIdentifier Notariatsverwalterin = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".12");
+
+ /**
+ * Notariatsverwalter
+ */
+ public static final ASN1ObjectIdentifier Notariatsverwalter = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".13");
+
+ /**
+ * Wirtschaftspr�ferin
+ */
+ public static final ASN1ObjectIdentifier Wirtschaftsprferin = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".14");
+
+ /**
+ * Wirtschaftspr�fer
+ */
+ public static final ASN1ObjectIdentifier Wirtschaftsprfer = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".15");
+
+ /**
+ * Vereidigte Buchpr�ferin
+ */
+ public static final ASN1ObjectIdentifier VereidigteBuchprferin = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".16");
+
+ /**
+ * Vereidigter Buchpr�fer
+ */
+ public static final ASN1ObjectIdentifier VereidigterBuchprfer = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".17");
+
+ /**
+ * Patentanw�ltin
+ */
+ public static final ASN1ObjectIdentifier Patentanwltin = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".18");
+
+ /**
+ * Patentanwalt
+ */
+ public static final ASN1ObjectIdentifier Patentanwalt = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".19");
+
+ private NamingAuthority namingAuthority;
+
+ private ASN1Sequence professionItems;
+
+ private ASN1Sequence professionOIDs;
+
+ private String registrationNumber;
+
+ private ASN1OctetString addProfessionInfo;
+
+ public static ProfessionInfo getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof ProfessionInfo)
+ {
+ return (ProfessionInfo)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new ProfessionInfo((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ * <p/>
+ * <p/>
+ * <pre>
+ * ProfessionInfo ::= SEQUENCE
+ * {
+ * namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+ * professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+ * professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+ * registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+ * addProfessionInfo OCTET STRING OPTIONAL
+ * }
+ * </pre>
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private ProfessionInfo(ASN1Sequence seq)
+ {
+ if (seq.size() > 5)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ Enumeration e = seq.getObjects();
+
+ ASN1Encodable o = (ASN1Encodable)e.nextElement();
+
+ if (o instanceof ASN1TaggedObject)
+ {
+ if (((ASN1TaggedObject)o).getTagNo() != 0)
+ {
+ throw new IllegalArgumentException("Bad tag number: "
+ + ((ASN1TaggedObject)o).getTagNo());
+ }
+ namingAuthority = NamingAuthority.getInstance((ASN1TaggedObject)o, true);
+ o = (ASN1Encodable)e.nextElement();
+ }
+
+ professionItems = ASN1Sequence.getInstance(o);
+
+ if (e.hasMoreElements())
+ {
+ o = (ASN1Encodable)e.nextElement();
+ if (o instanceof ASN1Sequence)
+ {
+ professionOIDs = ASN1Sequence.getInstance(o);
+ }
+ else if (o instanceof DERPrintableString)
+ {
+ registrationNumber = DERPrintableString.getInstance(o).getString();
+ }
+ else if (o instanceof ASN1OctetString)
+ {
+ addProfessionInfo = ASN1OctetString.getInstance(o);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad object encountered: "
+ + o.getClass());
+ }
+ }
+ if (e.hasMoreElements())
+ {
+ o = (ASN1Encodable)e.nextElement();
+ if (o instanceof DERPrintableString)
+ {
+ registrationNumber = DERPrintableString.getInstance(o).getString();
+ }
+ else if (o instanceof DEROctetString)
+ {
+ addProfessionInfo = (DEROctetString)o;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad object encountered: "
+ + o.getClass());
+ }
+ }
+ if (e.hasMoreElements())
+ {
+ o = (ASN1Encodable)e.nextElement();
+ if (o instanceof DEROctetString)
+ {
+ addProfessionInfo = (DEROctetString)o;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad object encountered: "
+ + o.getClass());
+ }
+ }
+
+ }
+
+ /**
+ * Constructor from given details.
+ * <p>
+ * <code>professionItems</code> is mandatory, all other parameters are
+ * optional.
+ *
+ * @param namingAuthority The naming authority.
+ * @param professionItems Directory strings of the profession.
+ * @param professionOIDs DERObjectIdentfier objects for the
+ * profession.
+ * @param registrationNumber Registration number.
+ * @param addProfessionInfo Additional infos in encoded form.
+ */
+ public ProfessionInfo(NamingAuthority namingAuthority,
+ DirectoryString[] professionItems, ASN1ObjectIdentifier[] professionOIDs,
+ String registrationNumber, ASN1OctetString addProfessionInfo)
+ {
+ this.namingAuthority = namingAuthority;
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i != professionItems.length; i++)
+ {
+ v.add(professionItems[i]);
+ }
+ this.professionItems = new DERSequence(v);
+ if (professionOIDs != null)
+ {
+ v = new ASN1EncodableVector();
+ for (int i = 0; i != professionOIDs.length; i++)
+ {
+ v.add(professionOIDs[i]);
+ }
+ this.professionOIDs = new DERSequence(v);
+ }
+ this.registrationNumber = registrationNumber;
+ this.addProfessionInfo = addProfessionInfo;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <p>
+ * Returns:
+ * <pre>
+ * ProfessionInfo ::= SEQUENCE
+ * {
+ * namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+ * professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+ * professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+ * registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+ * addProfessionInfo OCTET STRING OPTIONAL
+ * }
+ * </pre>
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+ if (namingAuthority != null)
+ {
+ vec.add(new DERTaggedObject(true, 0, namingAuthority));
+ }
+ vec.add(professionItems);
+ if (professionOIDs != null)
+ {
+ vec.add(professionOIDs);
+ }
+ if (registrationNumber != null)
+ {
+ vec.add(new DERPrintableString(registrationNumber, true));
+ }
+ if (addProfessionInfo != null)
+ {
+ vec.add(addProfessionInfo);
+ }
+ return new DERSequence(vec);
+ }
+
+ /**
+ * @return Returns the addProfessionInfo.
+ */
+ public ASN1OctetString getAddProfessionInfo()
+ {
+ return addProfessionInfo;
+ }
+
+ /**
+ * @return Returns the namingAuthority.
+ */
+ public NamingAuthority getNamingAuthority()
+ {
+ return namingAuthority;
+ }
+
+ /**
+ * @return Returns the professionItems.
+ */
+ public DirectoryString[] getProfessionItems()
+ {
+ DirectoryString[] items = new DirectoryString[professionItems.size()];
+ int count = 0;
+ for (Enumeration e = professionItems.getObjects(); e.hasMoreElements();)
+ {
+ items[count++] = DirectoryString.getInstance(e.nextElement());
+ }
+ return items;
+ }
+
+ /**
+ * @return Returns the professionOIDs.
+ */
+ public ASN1ObjectIdentifier[] getProfessionOIDs()
+ {
+ if (professionOIDs == null)
+ {
+ return new ASN1ObjectIdentifier[0];
+ }
+ ASN1ObjectIdentifier[] oids = new ASN1ObjectIdentifier[professionOIDs.size()];
+ int count = 0;
+ for (Enumeration e = professionOIDs.getObjects(); e.hasMoreElements();)
+ {
+ oids[count++] = ASN1ObjectIdentifier.getInstance(e.nextElement());
+ }
+ return oids;
+ }
+
+ /**
+ * @return Returns the registrationNumber.
+ */
+ public String getRegistrationNumber()
+ {
+ return registrationNumber;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/isismtt/x509/Restriction.java b/core/src/main/java/org/spongycastle/asn1/isismtt/x509/Restriction.java
new file mode 100644
index 00000000..bd3f782b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/isismtt/x509/Restriction.java
@@ -0,0 +1,79 @@
+package org.spongycastle.asn1.isismtt.x509;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.x500.DirectoryString;
+
+/**
+ * Some other restriction regarding the usage of this certificate.
+ *
+ * <pre>
+ * RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+ * </pre>
+ */
+public class Restriction
+ extends ASN1Object
+{
+ private DirectoryString restriction;
+
+ public static Restriction getInstance(Object obj)
+ {
+ if (obj instanceof Restriction)
+ {
+ return (Restriction)obj;
+ }
+
+ if (obj != null)
+ {
+ return new Restriction(DirectoryString.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Constructor from DirectoryString.
+ * <p/>
+ * The DirectoryString is of type RestrictionSyntax:
+ * <p/>
+ * <pre>
+ * RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+ * </pre>
+ *
+ * @param restriction A DirectoryString.
+ */
+ private Restriction(DirectoryString restriction)
+ {
+ this.restriction = restriction;
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param restriction The describtion of the restriction.
+ */
+ public Restriction(String restriction)
+ {
+ this.restriction = new DirectoryString(restriction);
+ }
+
+ public DirectoryString getRestriction()
+ {
+ return restriction;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <p>
+ * Returns:
+ * <pre>
+ * RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+ * </pre>
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return restriction.toASN1Primitive();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/kisa/KISAObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/kisa/KISAObjectIdentifiers.java
new file mode 100644
index 00000000..986b2a0a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/kisa/KISAObjectIdentifiers.java
@@ -0,0 +1,31 @@
+package org.spongycastle.asn1.kisa;
+
+import org.spongycastle.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
+{
+ /** 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/core/src/main/java/org/spongycastle/asn1/microsoft/MicrosoftObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/microsoft/MicrosoftObjectIdentifiers.java
new file mode 100644
index 00000000..44b5653e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/microsoft/MicrosoftObjectIdentifiers.java
@@ -0,0 +1,28 @@
+package org.spongycastle.asn1.microsoft;
+
+import org.spongycastle.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
+{
+ /** 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/core/src/main/java/org/spongycastle/asn1/misc/CAST5CBCParameters.java b/core/src/main/java/org/spongycastle/asn1/misc/CAST5CBCParameters.java
new file mode 100644
index 00000000..b611ccd6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/misc/CAST5CBCParameters.java
@@ -0,0 +1,78 @@
+package org.spongycastle.asn1.misc;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+
+public class CAST5CBCParameters
+ extends ASN1Object
+{
+ ASN1Integer keyLength;
+ ASN1OctetString iv;
+
+ public static CAST5CBCParameters getInstance(
+ Object o)
+ {
+ if (o instanceof CAST5CBCParameters)
+ {
+ return (CAST5CBCParameters)o;
+ }
+ else if (o != null)
+ {
+ return new CAST5CBCParameters(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CAST5CBCParameters(
+ byte[] iv,
+ int keyLength)
+ {
+ this.iv = new DEROctetString(iv);
+ this.keyLength = new ASN1Integer(keyLength);
+ }
+
+ public CAST5CBCParameters(
+ ASN1Sequence seq)
+ {
+ iv = (ASN1OctetString)seq.getObjectAt(0);
+ keyLength = (ASN1Integer)seq.getObjectAt(1);
+ }
+
+ public byte[] getIV()
+ {
+ return iv.getOctets();
+ }
+
+ public int getKeyLength()
+ {
+ return keyLength.getValue().intValue();
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * cast5CBCParameters ::= SEQUENCE {
+ * iv OCTET STRING DEFAULT 0,
+ * -- Initialization vector
+ * keyLength INTEGER
+ * -- Key length, in bits
+ * }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(iv);
+ v.add(keyLength);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/misc/IDEACBCPar.java b/core/src/main/java/org/spongycastle/asn1/misc/IDEACBCPar.java
new file mode 100644
index 00000000..cb6ab3c0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/misc/IDEACBCPar.java
@@ -0,0 +1,81 @@
+package org.spongycastle.asn1.misc;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+
+public class IDEACBCPar
+ extends ASN1Object
+{
+ ASN1OctetString iv;
+
+ public static IDEACBCPar getInstance(
+ Object o)
+ {
+ if (o instanceof IDEACBCPar)
+ {
+ return (IDEACBCPar)o;
+ }
+ else if (o != null)
+ {
+ return new IDEACBCPar(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public IDEACBCPar(
+ byte[] iv)
+ {
+ this.iv = new DEROctetString(iv);
+ }
+
+ public IDEACBCPar(
+ ASN1Sequence seq)
+ {
+ if (seq.size() == 1)
+ {
+ iv = (ASN1OctetString)seq.getObjectAt(0);
+ }
+ else
+ {
+ iv = null;
+ }
+ }
+
+ public byte[] getIV()
+ {
+ if (iv != null)
+ {
+ return iv.getOctets();
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * IDEA-CBCPar ::= SEQUENCE {
+ * iv OCTET STRING OPTIONAL -- exactly 8 octets
+ * }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (iv != null)
+ {
+ v.add(iv);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/misc/MiscObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/misc/MiscObjectIdentifiers.java
new file mode 100644
index 00000000..016cef25
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/misc/MiscObjectIdentifiers.java
@@ -0,0 +1,59 @@
+package org.spongycastle.asn1.misc;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+
+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");
+
+ /** Verisign CZAG (Country,Zip,Age,Gender) Extension OID: 2.16.840.1.113733.1.6.3 */
+ static final ASN1ObjectIdentifier verisignCzagExtension = verisign.branch("6.3");
+ /** Verisign D&amp;B D-U-N-S number Extension OID: 2.16.840.1.113733.1.6.15 */
+ static final ASN1ObjectIdentifier verisignDnbDunsNumber = verisign.branch("6.15");
+
+ //
+ // 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/core/src/main/java/org/spongycastle/asn1/misc/NetscapeCertType.java b/core/src/main/java/org/spongycastle/asn1/misc/NetscapeCertType.java
new file mode 100644
index 00000000..03fdf231
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/misc/NetscapeCertType.java
@@ -0,0 +1,54 @@
+package org.spongycastle.asn1.misc;
+
+import org.spongycastle.asn1.DERBitString;
+
+/**
+ * The NetscapeCertType object.
+ * <pre>
+ * NetscapeCertType ::= BIT STRING {
+ * SSLClient (0),
+ * SSLServer (1),
+ * S/MIME (2),
+ * Object Signing (3),
+ * Reserved (4),
+ * SSL CA (5),
+ * S/MIME CA (6),
+ * Object Signing CA (7) }
+ * </pre>
+ */
+public class NetscapeCertType
+ extends DERBitString
+{
+ public static final int sslClient = (1 << 7);
+ public static final int sslServer = (1 << 6);
+ public static final int smime = (1 << 5);
+ public static final int objectSigning = (1 << 4);
+ public static final int reserved = (1 << 3);
+ public static final int sslCA = (1 << 2);
+ public static final int smimeCA = (1 << 1);
+ public static final int objectSigningCA = (1 << 0);
+
+ /**
+ * Basic constructor.
+ *
+ * @param usage - the bitwise OR of the Key Usage flags giving the
+ * allowed uses for the key.
+ * e.g. (X509NetscapeCertType.sslCA | X509NetscapeCertType.smimeCA)
+ */
+ public NetscapeCertType(
+ int usage)
+ {
+ super(getBytes(usage), getPadBits(usage));
+ }
+
+ public NetscapeCertType(
+ DERBitString usage)
+ {
+ super(usage.getBytes(), usage.getPadBits());
+ }
+
+ public String toString()
+ {
+ return "NetscapeCertType: 0x" + Integer.toHexString(data[0] & 0xff);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/misc/NetscapeRevocationURL.java b/core/src/main/java/org/spongycastle/asn1/misc/NetscapeRevocationURL.java
new file mode 100644
index 00000000..2ae83774
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/misc/NetscapeRevocationURL.java
@@ -0,0 +1,18 @@
+package org.spongycastle.asn1.misc;
+
+import org.spongycastle.asn1.DERIA5String;
+
+public class NetscapeRevocationURL
+ extends DERIA5String
+{
+ public NetscapeRevocationURL(
+ DERIA5String str)
+ {
+ super(str.getString());
+ }
+
+ public String toString()
+ {
+ return "NetscapeRevocationURL: " + this.getString();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/misc/VerisignCzagExtension.java b/core/src/main/java/org/spongycastle/asn1/misc/VerisignCzagExtension.java
new file mode 100644
index 00000000..810b1608
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/misc/VerisignCzagExtension.java
@@ -0,0 +1,18 @@
+package org.spongycastle.asn1.misc;
+
+import org.spongycastle.asn1.DERIA5String;
+
+public class VerisignCzagExtension
+ extends DERIA5String
+{
+ public VerisignCzagExtension(
+ DERIA5String str)
+ {
+ super(str.getString());
+ }
+
+ public String toString()
+ {
+ return "VerisignCzagExtension: " + this.getString();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/mozilla/PublicKeyAndChallenge.java b/core/src/main/java/org/spongycastle/asn1/mozilla/PublicKeyAndChallenge.java
new file mode 100644
index 00000000..93902fa8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/mozilla/PublicKeyAndChallenge.java
@@ -0,0 +1,63 @@
+package org.spongycastle.asn1.mozilla;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+
+/**
+ * This is designed to parse
+ * the PublicKeyAndChallenge created by the KEYGEN tag included by
+ * Mozilla based browsers.
+ * <pre>
+ * PublicKeyAndChallenge ::= SEQUENCE {
+ * spki SubjectPublicKeyInfo,
+ * challenge IA5STRING
+ * }
+ *
+ * </pre>
+ */
+public class PublicKeyAndChallenge
+ extends ASN1Object
+{
+ private ASN1Sequence pkacSeq;
+ private SubjectPublicKeyInfo spki;
+ private DERIA5String challenge;
+
+ public static PublicKeyAndChallenge getInstance(Object obj)
+ {
+ if (obj instanceof PublicKeyAndChallenge)
+ {
+ return (PublicKeyAndChallenge)obj;
+ }
+ else if (obj != null)
+ {
+ return new PublicKeyAndChallenge(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private PublicKeyAndChallenge(ASN1Sequence seq)
+ {
+ pkacSeq = seq;
+ spki = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(0));
+ challenge = DERIA5String.getInstance(seq.getObjectAt(1));
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return pkacSeq;
+ }
+
+ public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
+ {
+ return spki;
+ }
+
+ public DERIA5String getChallenge()
+ {
+ return challenge;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/nist/NISTNamedCurves.java b/core/src/main/java/org/spongycastle/asn1/nist/NISTNamedCurves.java
new file mode 100644
index 00000000..9ddc6a3a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/nist/NISTNamedCurves.java
@@ -0,0 +1,99 @@
+package org.spongycastle.asn1.nist;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.sec.SECNamedCurves;
+import org.spongycastle.asn1.sec.SECObjectIdentifiers;
+import org.spongycastle.asn1.x9.X9ECParameters;
+import org.spongycastle.util.Strings;
+
+/**
+ * Utility class for fetching curves using their NIST names as published in FIPS-PUB 186-3
+ */
+public class NISTNamedCurves
+{
+ static final Hashtable objIds = new Hashtable();
+ static final Hashtable names = new Hashtable();
+
+ static void defineCurve(String name, ASN1ObjectIdentifier oid)
+ {
+ objIds.put(name, oid);
+ names.put(oid, name);
+ }
+
+ static
+ {
+ defineCurve("B-571", SECObjectIdentifiers.sect571r1);
+ defineCurve("B-409", SECObjectIdentifiers.sect409r1);
+ defineCurve("B-283", SECObjectIdentifiers.sect283r1);
+ defineCurve("B-233", SECObjectIdentifiers.sect233r1);
+ defineCurve("B-163", SECObjectIdentifiers.sect163r2);
+ defineCurve("K-571", SECObjectIdentifiers.sect571k1);
+ defineCurve("K-409", SECObjectIdentifiers.sect409k1);
+ defineCurve("K-283", SECObjectIdentifiers.sect283k1);
+ defineCurve("K-233", SECObjectIdentifiers.sect233k1);
+ defineCurve("K-163", SECObjectIdentifiers.sect163k1);
+ defineCurve("P-521", SECObjectIdentifiers.secp521r1);
+ defineCurve("P-384", SECObjectIdentifiers.secp384r1);
+ defineCurve("P-256", SECObjectIdentifiers.secp256r1);
+ defineCurve("P-224", SECObjectIdentifiers.secp224r1);
+ defineCurve("P-192", SECObjectIdentifiers.secp192r1);
+ }
+
+ public static X9ECParameters getByName(
+ String name)
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)objIds.get(Strings.toUpperCase(name));
+
+ if (oid != null)
+ {
+ return getByOID(oid);
+ }
+
+ return null;
+ }
+
+ /**
+ * return the X9ECParameters object for the named curve represented by
+ * the passed in object identifier. Null if the curve isn't present.
+ *
+ * @param oid an object identifier representing a named curve, if present.
+ */
+ public static X9ECParameters getByOID(
+ ASN1ObjectIdentifier oid)
+ {
+ return SECNamedCurves.getByOID(oid);
+ }
+
+ /**
+ * return the object identifier signified by the passed in name. Null
+ * if there is no object identifier associated with name.
+ *
+ * @return the object identifier associated with name, if present.
+ */
+ public static ASN1ObjectIdentifier getOID(
+ String name)
+ {
+ return (ASN1ObjectIdentifier)objIds.get(Strings.toUpperCase(name));
+ }
+
+ /**
+ * return the named curve name represented by the given object identifier.
+ */
+ public static String getName(
+ ASN1ObjectIdentifier oid)
+ {
+ return (String)names.get(oid);
+ }
+
+ /**
+ * returns an enumeration containing the name strings for curves
+ * contained in this structure.
+ */
+ public static Enumeration getNames()
+ {
+ return objIds.keys();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/nist/NISTObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/nist/NISTObjectIdentifiers.java
new file mode 100644
index 00000000..a488008d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/nist/NISTObjectIdentifiers.java
@@ -0,0 +1,96 @@
+package org.spongycastle.asn1.nist;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+
+/**
+ *
+ * NIST:
+ * iso/itu(2) joint-assign(16) us(840) organization(1) gov(101) csor(3)
+ */
+public interface NISTObjectIdentifiers
+{
+ //
+ // 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");
+
+ /** 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/core/src/main/java/org/spongycastle/asn1/ntt/NTTObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/ntt/NTTObjectIdentifiers.java
new file mode 100644
index 00000000..3eced423
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ntt/NTTObjectIdentifiers.java
@@ -0,0 +1,25 @@
+package org.spongycastle.asn1.ntt;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+
+/**
+ * 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
+{
+ /** 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");
+
+ /** 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/core/src/main/java/org/spongycastle/asn1/ocsp/BasicOCSPResponse.java b/core/src/main/java/org/spongycastle/asn1/ocsp/BasicOCSPResponse.java
new file mode 100644
index 00000000..9fa235e9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ocsp/BasicOCSPResponse.java
@@ -0,0 +1,112 @@
+package org.spongycastle.asn1.ocsp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+public class BasicOCSPResponse
+ extends ASN1Object
+{
+ private ResponseData tbsResponseData;
+ private AlgorithmIdentifier signatureAlgorithm;
+ private DERBitString signature;
+ private ASN1Sequence certs;
+
+ public BasicOCSPResponse(
+ ResponseData tbsResponseData,
+ AlgorithmIdentifier signatureAlgorithm,
+ DERBitString signature,
+ ASN1Sequence certs)
+ {
+ this.tbsResponseData = tbsResponseData;
+ this.signatureAlgorithm = signatureAlgorithm;
+ this.signature = signature;
+ this.certs = certs;
+ }
+
+ private BasicOCSPResponse(
+ ASN1Sequence seq)
+ {
+ this.tbsResponseData = ResponseData.getInstance(seq.getObjectAt(0));
+ this.signatureAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
+ this.signature = (DERBitString)seq.getObjectAt(2);
+
+ if (seq.size() > 3)
+ {
+ this.certs = ASN1Sequence.getInstance((ASN1TaggedObject)seq.getObjectAt(3), true);
+ }
+ }
+
+ public static BasicOCSPResponse getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static BasicOCSPResponse getInstance(
+ Object obj)
+ {
+ if (obj instanceof BasicOCSPResponse)
+ {
+ return (BasicOCSPResponse)obj;
+ }
+ else if (obj != null)
+ {
+ return new BasicOCSPResponse(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ResponseData getTbsResponseData()
+ {
+ return tbsResponseData;
+ }
+
+ public AlgorithmIdentifier getSignatureAlgorithm()
+ {
+ return signatureAlgorithm;
+ }
+
+ public DERBitString getSignature()
+ {
+ return signature;
+ }
+
+ public ASN1Sequence getCerts()
+ {
+ return certs;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * BasicOCSPResponse ::= SEQUENCE {
+ * tbsResponseData ResponseData,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING,
+ * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(tbsResponseData);
+ v.add(signatureAlgorithm);
+ v.add(signature);
+ if (certs != null)
+ {
+ v.add(new DERTaggedObject(true, 0, certs));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ocsp/CertID.java b/core/src/main/java/org/spongycastle/asn1/ocsp/CertID.java
new file mode 100644
index 00000000..35a13b07
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ocsp/CertID.java
@@ -0,0 +1,105 @@
+package org.spongycastle.asn1.ocsp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+public class CertID
+ extends ASN1Object
+{
+ AlgorithmIdentifier hashAlgorithm;
+ ASN1OctetString issuerNameHash;
+ ASN1OctetString issuerKeyHash;
+ ASN1Integer serialNumber;
+
+ public CertID(
+ AlgorithmIdentifier hashAlgorithm,
+ ASN1OctetString issuerNameHash,
+ ASN1OctetString issuerKeyHash,
+ ASN1Integer serialNumber)
+ {
+ this.hashAlgorithm = hashAlgorithm;
+ this.issuerNameHash = issuerNameHash;
+ this.issuerKeyHash = issuerKeyHash;
+ this.serialNumber = serialNumber;
+ }
+
+ private CertID(
+ ASN1Sequence seq)
+ {
+ hashAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(0));
+ issuerNameHash = (ASN1OctetString)seq.getObjectAt(1);
+ issuerKeyHash = (ASN1OctetString)seq.getObjectAt(2);
+ serialNumber = (ASN1Integer)seq.getObjectAt(3);
+ }
+
+ public static CertID getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static CertID getInstance(
+ Object obj)
+ {
+ if (obj instanceof CertID)
+ {
+ return (CertID)obj;
+ }
+ else if (obj != null)
+ {
+ return new CertID(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public AlgorithmIdentifier getHashAlgorithm()
+ {
+ return hashAlgorithm;
+ }
+
+ public ASN1OctetString getIssuerNameHash()
+ {
+ return issuerNameHash;
+ }
+
+ public ASN1OctetString getIssuerKeyHash()
+ {
+ return issuerKeyHash;
+ }
+
+ public ASN1Integer getSerialNumber()
+ {
+ return serialNumber;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * CertID ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * issuerNameHash OCTET STRING, -- Hash of Issuer's DN
+ * issuerKeyHash OCTET STRING, -- Hash of Issuers public key
+ * serialNumber CertificateSerialNumber }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(hashAlgorithm);
+ v.add(issuerNameHash);
+ v.add(issuerKeyHash);
+ v.add(serialNumber);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ocsp/CertStatus.java b/core/src/main/java/org/spongycastle/asn1/ocsp/CertStatus.java
new file mode 100644
index 00000000..d0f508c4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ocsp/CertStatus.java
@@ -0,0 +1,105 @@
+package org.spongycastle.asn1.ocsp;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERNull;
+import org.spongycastle.asn1.DERTaggedObject;
+
+public class CertStatus
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private int tagNo;
+ private ASN1Encodable value;
+
+ /**
+ * create a CertStatus object with a tag of zero.
+ */
+ public CertStatus()
+ {
+ tagNo = 0;
+ value = DERNull.INSTANCE;
+ }
+
+ public CertStatus(
+ RevokedInfo info)
+ {
+ tagNo = 1;
+ value = info;
+ }
+
+ public CertStatus(
+ int tagNo,
+ ASN1Encodable value)
+ {
+ this.tagNo = tagNo;
+ this.value = value;
+ }
+
+ public CertStatus(
+ ASN1TaggedObject choice)
+ {
+ this.tagNo = choice.getTagNo();
+
+ switch (choice.getTagNo())
+ {
+ case 0:
+ value = DERNull.INSTANCE;
+ break;
+ case 1:
+ value = RevokedInfo.getInstance(choice, false);
+ break;
+ case 2:
+ value = DERNull.INSTANCE;
+ }
+ }
+
+ public static CertStatus getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof CertStatus)
+ {
+ return (CertStatus)obj;
+ }
+ else if (obj instanceof ASN1TaggedObject)
+ {
+ return new CertStatus((ASN1TaggedObject)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
+ }
+
+ public static CertStatus getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject()); // must be explicitly tagged
+ }
+
+ public int getTagNo()
+ {
+ return tagNo;
+ }
+
+ public ASN1Encodable getStatus()
+ {
+ return value;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * CertStatus ::= CHOICE {
+ * good [0] IMPLICIT NULL,
+ * revoked [1] IMPLICIT RevokedInfo,
+ * unknown [2] IMPLICIT UnknownInfo }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERTaggedObject(false, tagNo, value);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ocsp/CrlID.java b/core/src/main/java/org/spongycastle/asn1/ocsp/CrlID.java
new file mode 100644
index 00000000..d2ea42f8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ocsp/CrlID.java
@@ -0,0 +1,110 @@
+package org.spongycastle.asn1.ocsp;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+public class CrlID
+ extends ASN1Object
+{
+ private DERIA5String crlUrl;
+ private ASN1Integer crlNum;
+ private ASN1GeneralizedTime crlTime;
+
+ private CrlID(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ ASN1TaggedObject o = (ASN1TaggedObject)e.nextElement();
+
+ switch (o.getTagNo())
+ {
+ case 0:
+ crlUrl = DERIA5String.getInstance(o, true);
+ break;
+ case 1:
+ crlNum = ASN1Integer.getInstance(o, true);
+ break;
+ case 2:
+ crlTime = ASN1GeneralizedTime.getInstance(o, true);
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "unknown tag number: " + o.getTagNo());
+ }
+ }
+ }
+
+ public static CrlID getInstance(
+ Object obj)
+ {
+ if (obj instanceof CrlID)
+ {
+ return (CrlID)obj;
+ }
+ else if (obj != null)
+ {
+ return new CrlID(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public DERIA5String getCrlUrl()
+ {
+ return crlUrl;
+ }
+
+ public ASN1Integer getCrlNum()
+ {
+ return crlNum;
+ }
+
+ public ASN1GeneralizedTime getCrlTime()
+ {
+ return crlTime;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * CrlID ::= SEQUENCE {
+ * crlUrl [0] EXPLICIT IA5String OPTIONAL,
+ * crlNum [1] EXPLICIT INTEGER OPTIONAL,
+ * crlTime [2] EXPLICIT GeneralizedTime OPTIONAL }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (crlUrl != null)
+ {
+ v.add(new DERTaggedObject(true, 0, crlUrl));
+ }
+
+ if (crlNum != null)
+ {
+ v.add(new DERTaggedObject(true, 1, crlNum));
+ }
+
+ if (crlTime != null)
+ {
+ v.add(new DERTaggedObject(true, 2, crlTime));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ocsp/OCSPObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/ocsp/OCSPObjectIdentifiers.java
new file mode 100644
index 00000000..6e306c68
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ocsp/OCSPObjectIdentifiers.java
@@ -0,0 +1,29 @@
+package org.spongycastle.asn1.ocsp;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+
+/**
+ * OIDs for <a href="http://tools.ietf.org/html/rfc2560">RFC 2560</a>
+ * Online Certificate Status Protocol - OCSP.
+ */
+public interface OCSPObjectIdentifiers
+{
+ /** 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");
+
+ /** 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");
+
+ /** 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/core/src/main/java/org/spongycastle/asn1/ocsp/OCSPRequest.java b/core/src/main/java/org/spongycastle/asn1/ocsp/OCSPRequest.java
new file mode 100644
index 00000000..ba8d8c46
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ocsp/OCSPRequest.java
@@ -0,0 +1,90 @@
+package org.spongycastle.asn1.ocsp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+public class OCSPRequest
+ extends ASN1Object
+{
+ TBSRequest tbsRequest;
+ Signature optionalSignature;
+
+ public OCSPRequest(
+ TBSRequest tbsRequest,
+ Signature optionalSignature)
+ {
+ this.tbsRequest = tbsRequest;
+ this.optionalSignature = optionalSignature;
+ }
+
+ private OCSPRequest(
+ ASN1Sequence seq)
+ {
+ tbsRequest = TBSRequest.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() == 2)
+ {
+ optionalSignature = Signature.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(1), true);
+ }
+ }
+
+ public static OCSPRequest getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static OCSPRequest getInstance(
+ Object obj)
+ {
+ if (obj instanceof OCSPRequest)
+ {
+ return (OCSPRequest)obj;
+ }
+ else if (obj != null)
+ {
+ return new OCSPRequest(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public TBSRequest getTbsRequest()
+ {
+ return tbsRequest;
+ }
+
+ public Signature getOptionalSignature()
+ {
+ return optionalSignature;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * OCSPRequest ::= SEQUENCE {
+ * tbsRequest TBSRequest,
+ * optionalSignature [0] EXPLICIT Signature OPTIONAL }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(tbsRequest);
+
+ if (optionalSignature != null)
+ {
+ v.add(new DERTaggedObject(true, 0, optionalSignature));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ocsp/OCSPResponse.java b/core/src/main/java/org/spongycastle/asn1/ocsp/OCSPResponse.java
new file mode 100644
index 00000000..c3bf5813
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ocsp/OCSPResponse.java
@@ -0,0 +1,90 @@
+package org.spongycastle.asn1.ocsp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+public class OCSPResponse
+ extends ASN1Object
+{
+ OCSPResponseStatus responseStatus;
+ ResponseBytes responseBytes;
+
+ public OCSPResponse(
+ OCSPResponseStatus responseStatus,
+ ResponseBytes responseBytes)
+ {
+ this.responseStatus = responseStatus;
+ this.responseBytes = responseBytes;
+ }
+
+ private OCSPResponse(
+ ASN1Sequence seq)
+ {
+ responseStatus = OCSPResponseStatus.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() == 2)
+ {
+ responseBytes = ResponseBytes.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(1), true);
+ }
+ }
+
+ public static OCSPResponse getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static OCSPResponse getInstance(
+ Object obj)
+ {
+ if (obj instanceof OCSPResponse)
+ {
+ return (OCSPResponse)obj;
+ }
+ else if (obj != null)
+ {
+ return new OCSPResponse(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public OCSPResponseStatus getResponseStatus()
+ {
+ return responseStatus;
+ }
+
+ public ResponseBytes getResponseBytes()
+ {
+ return responseBytes;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * OCSPResponse ::= SEQUENCE {
+ * responseStatus OCSPResponseStatus,
+ * responseBytes [0] EXPLICIT ResponseBytes OPTIONAL }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(responseStatus);
+
+ if (responseBytes != null)
+ {
+ v.add(new DERTaggedObject(true, 0, responseBytes));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ocsp/OCSPResponseStatus.java b/core/src/main/java/org/spongycastle/asn1/ocsp/OCSPResponseStatus.java
new file mode 100644
index 00000000..b9729ce3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ocsp/OCSPResponseStatus.java
@@ -0,0 +1,71 @@
+package org.spongycastle.asn1.ocsp;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1Enumerated;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+
+public class OCSPResponseStatus
+ extends ASN1Object
+{
+ public static final int SUCCESSFUL = 0;
+ public static final int MALFORMED_REQUEST = 1;
+ public static final int INTERNAL_ERROR = 2;
+ public static final int TRY_LATER = 3;
+ public static final int SIG_REQUIRED = 5;
+ public static final int UNAUTHORIZED = 6;
+
+ private ASN1Enumerated value;
+
+ /**
+ * The OCSPResponseStatus enumeration.
+ * <pre>
+ * OCSPResponseStatus ::= ENUMERATED {
+ * successful (0), --Response has valid confirmations
+ * malformedRequest (1), --Illegal confirmation request
+ * internalError (2), --Internal error in issuer
+ * tryLater (3), --Try again later
+ * --(4) is not used
+ * sigRequired (5), --Must sign the request
+ * unauthorized (6) --Request unauthorized
+ * }
+ * </pre>
+ */
+ public OCSPResponseStatus(
+ int value)
+ {
+ this(new ASN1Enumerated(value));
+ }
+
+ private OCSPResponseStatus(
+ ASN1Enumerated value)
+ {
+ this.value = value;
+ }
+
+ public static OCSPResponseStatus getInstance(
+ Object obj)
+ {
+ if (obj instanceof OCSPResponseStatus)
+ {
+ return (OCSPResponseStatus)obj;
+ }
+ else if (obj != null)
+ {
+ return new OCSPResponseStatus(ASN1Enumerated.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public BigInteger getValue()
+ {
+ return value.getValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return value;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ocsp/Request.java b/core/src/main/java/org/spongycastle/asn1/ocsp/Request.java
new file mode 100644
index 00000000..62e7fb22
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ocsp/Request.java
@@ -0,0 +1,91 @@
+package org.spongycastle.asn1.ocsp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.Extensions;
+
+public class Request
+ extends ASN1Object
+{
+ CertID reqCert;
+ Extensions singleRequestExtensions;
+
+ public Request(
+ CertID reqCert,
+ Extensions singleRequestExtensions)
+ {
+ this.reqCert = reqCert;
+ this.singleRequestExtensions = singleRequestExtensions;
+ }
+
+ private Request(
+ ASN1Sequence seq)
+ {
+ reqCert = CertID.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() == 2)
+ {
+ singleRequestExtensions = Extensions.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(1), true);
+ }
+ }
+
+ public static Request getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static Request getInstance(
+ Object obj)
+ {
+ if (obj instanceof Request)
+ {
+ return (Request)obj;
+ }
+ else if (obj != null)
+ {
+ return new Request(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public CertID getReqCert()
+ {
+ return reqCert;
+ }
+
+ public Extensions getSingleRequestExtensions()
+ {
+ return singleRequestExtensions;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * Request ::= SEQUENCE {
+ * reqCert CertID,
+ * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(reqCert);
+
+ if (singleRequestExtensions != null)
+ {
+ v.add(new DERTaggedObject(true, 0, singleRequestExtensions));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ocsp/ResponderID.java b/core/src/main/java/org/spongycastle/asn1/ocsp/ResponderID.java
new file mode 100644
index 00000000..d53eb7a3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ocsp/ResponderID.java
@@ -0,0 +1,104 @@
+package org.spongycastle.asn1.ocsp;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x500.X500Name;
+
+public class ResponderID
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private ASN1Encodable value;
+
+ public ResponderID(
+ ASN1OctetString value)
+ {
+ this.value = value;
+ }
+
+ public ResponderID(
+ X500Name value)
+ {
+ this.value = value;
+ }
+
+ public static ResponderID getInstance(
+ Object obj)
+ {
+ if (obj instanceof ResponderID)
+ {
+ return (ResponderID)obj;
+ }
+ else if (obj instanceof DEROctetString)
+ {
+ return new ResponderID((DEROctetString)obj);
+ }
+ else if (obj instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject o = (ASN1TaggedObject)obj;
+
+ if (o.getTagNo() == 1)
+ {
+ return new ResponderID(X500Name.getInstance(o, true));
+ }
+ else
+ {
+ return new ResponderID(ASN1OctetString.getInstance(o, true));
+ }
+ }
+
+ return new ResponderID(X500Name.getInstance(obj));
+ }
+
+ public static ResponderID getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject()); // must be explicitly tagged
+ }
+
+ public byte[] getKeyHash()
+ {
+ if (this.value instanceof ASN1OctetString)
+ {
+ ASN1OctetString octetString = (ASN1OctetString)this.value;
+ return octetString.getOctets();
+ }
+
+ return null;
+ }
+
+ public X500Name getName()
+ {
+ if (this.value instanceof ASN1OctetString)
+ {
+ return null;
+ }
+
+ return X500Name.getInstance(value);
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * ResponderID ::= CHOICE {
+ * byName [1] Name,
+ * byKey [2] KeyHash }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (value instanceof ASN1OctetString)
+ {
+ return new DERTaggedObject(true, 2, value);
+ }
+
+ return new DERTaggedObject(true, 1, value);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ocsp/ResponseBytes.java b/core/src/main/java/org/spongycastle/asn1/ocsp/ResponseBytes.java
new file mode 100644
index 00000000..790ebee8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ocsp/ResponseBytes.java
@@ -0,0 +1,82 @@
+package org.spongycastle.asn1.ocsp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+
+public class ResponseBytes
+ extends ASN1Object
+{
+ ASN1ObjectIdentifier responseType;
+ ASN1OctetString response;
+
+ public ResponseBytes(
+ ASN1ObjectIdentifier responseType,
+ ASN1OctetString response)
+ {
+ this.responseType = responseType;
+ this.response = response;
+ }
+
+ public ResponseBytes(
+ ASN1Sequence seq)
+ {
+ responseType = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ response = (ASN1OctetString)seq.getObjectAt(1);
+ }
+
+ public static ResponseBytes getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static ResponseBytes getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ResponseBytes)
+ {
+ return (ResponseBytes)obj;
+ }
+ else if (obj instanceof ASN1Sequence)
+ {
+ return new ResponseBytes((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
+ }
+
+ public ASN1ObjectIdentifier getResponseType()
+ {
+ return responseType;
+ }
+
+ public ASN1OctetString getResponse()
+ {
+ return response;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * ResponseBytes ::= SEQUENCE {
+ * responseType OBJECT IDENTIFIER,
+ * response OCTET STRING }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(responseType);
+ v.add(response);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ocsp/ResponseData.java b/core/src/main/java/org/spongycastle/asn1/ocsp/ResponseData.java
new file mode 100644
index 00000000..69f716ba
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ocsp/ResponseData.java
@@ -0,0 +1,181 @@
+package org.spongycastle.asn1.ocsp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.Extensions;
+import org.spongycastle.asn1.x509.X509Extensions;
+
+public class ResponseData
+ extends ASN1Object
+{
+ private static final ASN1Integer V1 = new ASN1Integer(0);
+
+ private boolean versionPresent;
+
+ private ASN1Integer version;
+ private ResponderID responderID;
+ private ASN1GeneralizedTime producedAt;
+ private ASN1Sequence responses;
+ private Extensions responseExtensions;
+
+ public ResponseData(
+ ASN1Integer version,
+ ResponderID responderID,
+ ASN1GeneralizedTime producedAt,
+ ASN1Sequence responses,
+ Extensions responseExtensions)
+ {
+ this.version = version;
+ this.responderID = responderID;
+ this.producedAt = producedAt;
+ this.responses = responses;
+ this.responseExtensions = responseExtensions;
+ }
+
+ /**
+ * @deprecated use method taking Extensions
+ * @param responderID
+ * @param producedAt
+ * @param responses
+ * @param responseExtensions
+ */
+ public ResponseData(
+ ResponderID responderID,
+ ASN1GeneralizedTime producedAt,
+ ASN1Sequence responses,
+ X509Extensions responseExtensions)
+ {
+ this(V1, responderID, ASN1GeneralizedTime.getInstance(producedAt), responses, Extensions.getInstance(responseExtensions));
+ }
+
+ public ResponseData(
+ ResponderID responderID,
+ ASN1GeneralizedTime producedAt,
+ ASN1Sequence responses,
+ Extensions responseExtensions)
+ {
+ this(V1, responderID, producedAt, responses, responseExtensions);
+ }
+
+ private ResponseData(
+ ASN1Sequence seq)
+ {
+ int index = 0;
+
+ if (seq.getObjectAt(0) instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject o = (ASN1TaggedObject)seq.getObjectAt(0);
+
+ if (o.getTagNo() == 0)
+ {
+ this.versionPresent = true;
+ this.version = ASN1Integer.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(0), true);
+ index++;
+ }
+ else
+ {
+ this.version = V1;
+ }
+ }
+ else
+ {
+ this.version = V1;
+ }
+
+ this.responderID = ResponderID.getInstance(seq.getObjectAt(index++));
+ this.producedAt = ASN1GeneralizedTime.getInstance(seq.getObjectAt(index++));
+ this.responses = (ASN1Sequence)seq.getObjectAt(index++);
+
+ if (seq.size() > index)
+ {
+ this.responseExtensions = Extensions.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(index), true);
+ }
+ }
+
+ public static ResponseData getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static ResponseData getInstance(
+ Object obj)
+ {
+ if (obj instanceof ResponseData)
+ {
+ return (ResponseData)obj;
+ }
+ else if (obj != null)
+ {
+ return new ResponseData(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public ResponderID getResponderID()
+ {
+ return responderID;
+ }
+
+ public ASN1GeneralizedTime getProducedAt()
+ {
+ return producedAt;
+ }
+
+ public ASN1Sequence getResponses()
+ {
+ return responses;
+ }
+
+ public Extensions getResponseExtensions()
+ {
+ return responseExtensions;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * ResponseData ::= SEQUENCE {
+ * version [0] EXPLICIT Version DEFAULT v1,
+ * responderID ResponderID,
+ * producedAt GeneralizedTime,
+ * responses SEQUENCE OF SingleResponse,
+ * responseExtensions [1] EXPLICIT Extensions OPTIONAL }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (versionPresent || !version.equals(V1))
+ {
+ v.add(new DERTaggedObject(true, 0, version));
+ }
+
+ v.add(responderID);
+ v.add(producedAt);
+ v.add(responses);
+ if (responseExtensions != null)
+ {
+ v.add(new DERTaggedObject(true, 1, responseExtensions));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ocsp/RevokedInfo.java b/core/src/main/java/org/spongycastle/asn1/ocsp/RevokedInfo.java
new file mode 100644
index 00000000..bf9eca77
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ocsp/RevokedInfo.java
@@ -0,0 +1,92 @@
+package org.spongycastle.asn1.ocsp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Enumerated;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.CRLReason;
+
+public class RevokedInfo
+ extends ASN1Object
+{
+ private ASN1GeneralizedTime revocationTime;
+ private CRLReason revocationReason;
+
+ public RevokedInfo(
+ ASN1GeneralizedTime revocationTime,
+ CRLReason revocationReason)
+ {
+ this.revocationTime = revocationTime;
+ this.revocationReason = revocationReason;
+ }
+
+ private RevokedInfo(
+ ASN1Sequence seq)
+ {
+ this.revocationTime = ASN1GeneralizedTime.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() > 1)
+ {
+ this.revocationReason = CRLReason.getInstance(ASN1Enumerated.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(1), true));
+ }
+ }
+
+ public static RevokedInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static RevokedInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof RevokedInfo)
+ {
+ return (RevokedInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new RevokedInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1GeneralizedTime getRevocationTime()
+ {
+ return revocationTime;
+ }
+
+ public CRLReason getRevocationReason()
+ {
+ return revocationReason;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * RevokedInfo ::= SEQUENCE {
+ * revocationTime GeneralizedTime,
+ * revocationReason [0] EXPLICIT CRLReason OPTIONAL }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(revocationTime);
+ if (revocationReason != null)
+ {
+ v.add(new DERTaggedObject(true, 0, revocationReason));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ocsp/ServiceLocator.java b/core/src/main/java/org/spongycastle/asn1/ocsp/ServiceLocator.java
new file mode 100644
index 00000000..32aa9b7e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ocsp/ServiceLocator.java
@@ -0,0 +1,36 @@
+package org.spongycastle.asn1.ocsp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x500.X500Name;
+
+public class ServiceLocator
+ extends ASN1Object
+{
+ X500Name issuer;
+ ASN1Primitive locator;
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * ServiceLocator ::= SEQUENCE {
+ * issuer Name,
+ * locator AuthorityInfoAccessSyntax OPTIONAL }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(issuer);
+
+ if (locator != null)
+ {
+ v.add(locator);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ocsp/Signature.java b/core/src/main/java/org/spongycastle/asn1/ocsp/Signature.java
new file mode 100644
index 00000000..776f7066
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ocsp/Signature.java
@@ -0,0 +1,111 @@
+package org.spongycastle.asn1.ocsp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+public class Signature
+ extends ASN1Object
+{
+ AlgorithmIdentifier signatureAlgorithm;
+ DERBitString signature;
+ ASN1Sequence certs;
+
+ public Signature(
+ AlgorithmIdentifier signatureAlgorithm,
+ DERBitString signature)
+ {
+ this.signatureAlgorithm = signatureAlgorithm;
+ this.signature = signature;
+ }
+
+ public Signature(
+ AlgorithmIdentifier signatureAlgorithm,
+ DERBitString signature,
+ ASN1Sequence certs)
+ {
+ this.signatureAlgorithm = signatureAlgorithm;
+ this.signature = signature;
+ this.certs = certs;
+ }
+
+ private Signature(
+ ASN1Sequence seq)
+ {
+ signatureAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(0));
+ signature = (DERBitString)seq.getObjectAt(1);
+
+ if (seq.size() == 3)
+ {
+ certs = ASN1Sequence.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(2), true);
+ }
+ }
+
+ public static Signature getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static Signature getInstance(
+ Object obj)
+ {
+ if (obj instanceof Signature)
+ {
+ return (Signature)obj;
+ }
+ else if (obj != null)
+ {
+ return new Signature(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public AlgorithmIdentifier getSignatureAlgorithm()
+ {
+ return signatureAlgorithm;
+ }
+
+ public DERBitString getSignature()
+ {
+ return signature;
+ }
+
+ public ASN1Sequence getCerts()
+ {
+ return certs;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * Signature ::= SEQUENCE {
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING,
+ * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL}
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(signatureAlgorithm);
+ v.add(signature);
+
+ if (certs != null)
+ {
+ v.add(new DERTaggedObject(true, 0, certs));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ocsp/SingleResponse.java b/core/src/main/java/org/spongycastle/asn1/ocsp/SingleResponse.java
new file mode 100644
index 00000000..b11a9a24
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ocsp/SingleResponse.java
@@ -0,0 +1,162 @@
+package org.spongycastle.asn1.ocsp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.Extensions;
+import org.spongycastle.asn1.x509.X509Extensions;
+
+public class SingleResponse
+ extends ASN1Object
+{
+ private CertID certID;
+ private CertStatus certStatus;
+ private ASN1GeneralizedTime thisUpdate;
+ private ASN1GeneralizedTime nextUpdate;
+ private Extensions singleExtensions;
+
+ /**
+ * @deprecated use method taking ASN1GeneralizedTime and Extensions
+ * @param certID
+ * @param certStatus
+ * @param thisUpdate
+ * @param nextUpdate
+ * @param singleExtensions
+ */
+ public SingleResponse(
+ CertID certID,
+ CertStatus certStatus,
+ ASN1GeneralizedTime thisUpdate,
+ ASN1GeneralizedTime nextUpdate,
+ X509Extensions singleExtensions)
+ {
+ this(certID, certStatus, thisUpdate, nextUpdate, Extensions.getInstance(singleExtensions));
+ }
+
+ public SingleResponse(
+ CertID certID,
+ CertStatus certStatus,
+ ASN1GeneralizedTime thisUpdate,
+ ASN1GeneralizedTime nextUpdate,
+ Extensions singleExtensions)
+ {
+ this.certID = certID;
+ this.certStatus = certStatus;
+ this.thisUpdate = thisUpdate;
+ this.nextUpdate = nextUpdate;
+ this.singleExtensions = singleExtensions;
+ }
+
+ private SingleResponse(
+ ASN1Sequence seq)
+ {
+ this.certID = CertID.getInstance(seq.getObjectAt(0));
+ this.certStatus = CertStatus.getInstance(seq.getObjectAt(1));
+ this.thisUpdate = ASN1GeneralizedTime.getInstance(seq.getObjectAt(2));
+
+ if (seq.size() > 4)
+ {
+ this.nextUpdate = ASN1GeneralizedTime.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(3), true);
+ this.singleExtensions = Extensions.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(4), true);
+ }
+ else if (seq.size() > 3)
+ {
+ ASN1TaggedObject o = (ASN1TaggedObject)seq.getObjectAt(3);
+
+ if (o.getTagNo() == 0)
+ {
+ this.nextUpdate = ASN1GeneralizedTime.getInstance(o, true);
+ }
+ else
+ {
+ this.singleExtensions = Extensions.getInstance(o, true);
+ }
+ }
+ }
+
+ public static SingleResponse getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static SingleResponse getInstance(
+ Object obj)
+ {
+ if (obj instanceof SingleResponse)
+ {
+ return (SingleResponse)obj;
+ }
+ else if (obj != null)
+ {
+ return new SingleResponse(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public CertID getCertID()
+ {
+ return certID;
+ }
+
+ public CertStatus getCertStatus()
+ {
+ return certStatus;
+ }
+
+ public ASN1GeneralizedTime getThisUpdate()
+ {
+ return thisUpdate;
+ }
+
+ public ASN1GeneralizedTime getNextUpdate()
+ {
+ return nextUpdate;
+ }
+
+ public Extensions getSingleExtensions()
+ {
+ return singleExtensions;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * SingleResponse ::= SEQUENCE {
+ * certID CertID,
+ * certStatus CertStatus,
+ * thisUpdate GeneralizedTime,
+ * nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
+ * singleExtensions [1] EXPLICIT Extensions OPTIONAL }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certID);
+ v.add(certStatus);
+ v.add(thisUpdate);
+
+ if (nextUpdate != null)
+ {
+ v.add(new DERTaggedObject(true, 0, nextUpdate));
+ }
+
+ if (singleExtensions != null)
+ {
+ v.add(new DERTaggedObject(true, 1, singleExtensions));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ocsp/TBSRequest.java b/core/src/main/java/org/spongycastle/asn1/ocsp/TBSRequest.java
new file mode 100644
index 00000000..6c4220bb
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ocsp/TBSRequest.java
@@ -0,0 +1,172 @@
+package org.spongycastle.asn1.ocsp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.Extensions;
+import org.spongycastle.asn1.x509.GeneralName;
+import org.spongycastle.asn1.x509.X509Extensions;
+
+public class TBSRequest
+ extends ASN1Object
+{
+ private static final ASN1Integer V1 = new ASN1Integer(0);
+
+ ASN1Integer version;
+ GeneralName requestorName;
+ ASN1Sequence requestList;
+ Extensions requestExtensions;
+
+ boolean versionSet;
+
+ /**
+ * @deprecated use method taking Extensions
+ * @param requestorName
+ * @param requestList
+ * @param requestExtensions
+ */
+ public TBSRequest(
+ GeneralName requestorName,
+ ASN1Sequence requestList,
+ X509Extensions requestExtensions)
+ {
+ this.version = V1;
+ this.requestorName = requestorName;
+ this.requestList = requestList;
+ this.requestExtensions = Extensions.getInstance(requestExtensions);
+ }
+
+ public TBSRequest(
+ GeneralName requestorName,
+ ASN1Sequence requestList,
+ Extensions requestExtensions)
+ {
+ this.version = V1;
+ this.requestorName = requestorName;
+ this.requestList = requestList;
+ this.requestExtensions = requestExtensions;
+ }
+
+ private TBSRequest(
+ ASN1Sequence seq)
+ {
+ int index = 0;
+
+ if (seq.getObjectAt(0) instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject o = (ASN1TaggedObject)seq.getObjectAt(0);
+
+ if (o.getTagNo() == 0)
+ {
+ versionSet = true;
+ version = ASN1Integer.getInstance((ASN1TaggedObject)seq.getObjectAt(0), true);
+ index++;
+ }
+ else
+ {
+ version = V1;
+ }
+ }
+ else
+ {
+ version = V1;
+ }
+
+ if (seq.getObjectAt(index) instanceof ASN1TaggedObject)
+ {
+ requestorName = GeneralName.getInstance((ASN1TaggedObject)seq.getObjectAt(index++), true);
+ }
+
+ requestList = (ASN1Sequence)seq.getObjectAt(index++);
+
+ if (seq.size() == (index + 1))
+ {
+ requestExtensions = Extensions.getInstance((ASN1TaggedObject)seq.getObjectAt(index), true);
+ }
+ }
+
+ public static TBSRequest getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static TBSRequest getInstance(
+ Object obj)
+ {
+ if (obj instanceof TBSRequest)
+ {
+ return (TBSRequest)obj;
+ }
+ else if (obj != null)
+ {
+ return new TBSRequest(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public GeneralName getRequestorName()
+ {
+ return requestorName;
+ }
+
+ public ASN1Sequence getRequestList()
+ {
+ return requestList;
+ }
+
+ public Extensions getRequestExtensions()
+ {
+ return requestExtensions;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * TBSRequest ::= SEQUENCE {
+ * version [0] EXPLICIT Version DEFAULT v1,
+ * requestorName [1] EXPLICIT GeneralName OPTIONAL,
+ * requestList SEQUENCE OF Request,
+ * requestExtensions [2] EXPLICIT Extensions OPTIONAL }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ //
+ // if default don't include - unless explicitly provided. Not strictly correct
+ // but required for some requests
+ //
+ if (!version.equals(V1) || versionSet)
+ {
+ v.add(new DERTaggedObject(true, 0, version));
+ }
+
+ if (requestorName != null)
+ {
+ v.add(new DERTaggedObject(true, 1, requestorName));
+ }
+
+ v.add(requestList);
+
+ if (requestExtensions != null)
+ {
+ v.add(new DERTaggedObject(true, 2, requestExtensions));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/oiw/ElGamalParameter.java b/core/src/main/java/org/spongycastle/asn1/oiw/ElGamalParameter.java
new file mode 100644
index 00000000..24dcde2c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/oiw/ElGamalParameter.java
@@ -0,0 +1,68 @@
+package org.spongycastle.asn1.oiw;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class ElGamalParameter
+ extends ASN1Object
+{
+ ASN1Integer p, g;
+
+ public ElGamalParameter(
+ BigInteger p,
+ BigInteger g)
+ {
+ this.p = new ASN1Integer(p);
+ this.g = new ASN1Integer(g);
+ }
+
+ private ElGamalParameter(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ p = (ASN1Integer)e.nextElement();
+ g = (ASN1Integer)e.nextElement();
+ }
+
+ public static ElGamalParameter getInstance(Object o)
+ {
+ if (o instanceof ElGamalParameter)
+ {
+ return (ElGamalParameter)o;
+ }
+ else if (o != null)
+ {
+ return new ElGamalParameter(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public BigInteger getP()
+ {
+ return p.getPositiveValue();
+ }
+
+ public BigInteger getG()
+ {
+ return g.getPositiveValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(p);
+ v.add(g);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/oiw/OIWObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/oiw/OIWObjectIdentifiers.java
new file mode 100644
index 00000000..18bf44b2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/oiw/OIWObjectIdentifiers.java
@@ -0,0 +1,50 @@
+package org.spongycastle.asn1.oiw;
+
+import org.spongycastle.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
+{
+ /** 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");
+
+ /**
+ * <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/core/src/main/java/org/spongycastle/asn1/pkcs/Attribute.java b/core/src/main/java/org/spongycastle/asn1/pkcs/Attribute.java
new file mode 100644
index 00000000..ea010e74
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/Attribute.java
@@ -0,0 +1,88 @@
+package org.spongycastle.asn1.pkcs;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.DERSequence;
+
+public class Attribute
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier attrType;
+ private ASN1Set attrValues;
+
+ /**
+ * return an Attribute object from the given object.
+ *
+ * @param o the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static Attribute getInstance(
+ Object o)
+ {
+ if (o == null || o instanceof Attribute)
+ {
+ return (Attribute)o;
+ }
+
+ if (o instanceof ASN1Sequence)
+ {
+ return new Attribute((ASN1Sequence)o);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + o.getClass().getName());
+ }
+
+ public Attribute(
+ ASN1Sequence seq)
+ {
+ attrType = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ attrValues = (ASN1Set)seq.getObjectAt(1);
+ }
+
+ public Attribute(
+ ASN1ObjectIdentifier attrType,
+ ASN1Set attrValues)
+ {
+ this.attrType = attrType;
+ this.attrValues = attrValues;
+ }
+
+ public ASN1ObjectIdentifier getAttrType()
+ {
+ return attrType;
+ }
+
+ public ASN1Set getAttrValues()
+ {
+ return attrValues;
+ }
+
+ public ASN1Encodable[] getAttributeValues()
+ {
+ return attrValues.toArray();
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * Attribute ::= SEQUENCE {
+ * attrType OBJECT IDENTIFIER,
+ * attrValues SET OF AttributeValue
+ * }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(attrType);
+ v.add(attrValues);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/AuthenticatedSafe.java b/core/src/main/java/org/spongycastle/asn1/pkcs/AuthenticatedSafe.java
new file mode 100644
index 00000000..c4a824ae
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/AuthenticatedSafe.java
@@ -0,0 +1,74 @@
+package org.spongycastle.asn1.pkcs;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.BERSequence;
+import org.spongycastle.asn1.DLSequence;
+
+public class AuthenticatedSafe
+ extends ASN1Object
+{
+ private ContentInfo[] info;
+ private boolean isBer = true;
+
+ private AuthenticatedSafe(
+ ASN1Sequence seq)
+ {
+ info = new ContentInfo[seq.size()];
+
+ for (int i = 0; i != info.length; i++)
+ {
+ info[i] = ContentInfo.getInstance(seq.getObjectAt(i));
+ }
+
+ isBer = seq instanceof BERSequence;
+ }
+
+ public static AuthenticatedSafe getInstance(
+ Object o)
+ {
+ if (o instanceof AuthenticatedSafe)
+ {
+ return (AuthenticatedSafe)o;
+ }
+
+ if (o != null)
+ {
+ return new AuthenticatedSafe(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public AuthenticatedSafe(
+ ContentInfo[] info)
+ {
+ this.info = info;
+ }
+
+ public ContentInfo[] getContentInfo()
+ {
+ return info;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ for (int i = 0; i != info.length; i++)
+ {
+ v.add(info[i]);
+ }
+
+ if (isBer)
+ {
+ return new BERSequence(v);
+ }
+ else
+ {
+ return new DLSequence(v);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/CRLBag.java b/core/src/main/java/org/spongycastle/asn1/pkcs/CRLBag.java
new file mode 100644
index 00000000..0110ee8b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/CRLBag.java
@@ -0,0 +1,82 @@
+package org.spongycastle.asn1.pkcs;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+public class CRLBag
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier crlId;
+ private ASN1Encodable crlValue;
+
+ private CRLBag(
+ ASN1Sequence seq)
+ {
+ this.crlId = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ this.crlValue = ((DERTaggedObject)seq.getObjectAt(1)).getObject();
+ }
+
+ public static CRLBag getInstance(Object o)
+ {
+ if (o instanceof CRLBag)
+ {
+ return (CRLBag)o;
+ }
+ else if (o != null)
+ {
+ return new CRLBag(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CRLBag(
+ ASN1ObjectIdentifier crlId,
+ ASN1Encodable crlValue)
+ {
+ this.crlId = crlId;
+ this.crlValue = crlValue;
+ }
+
+ public ASN1ObjectIdentifier getcrlId()
+ {
+ return crlId;
+ }
+
+ public ASN1Encodable getCRLValue()
+ {
+ return crlValue;
+ }
+
+ /**
+ * <pre>
+ * CRLBag ::= SEQUENCE {
+ * crlId BAG-TYPE.&amp;id ({CRLTypes}),
+ * crlValue [0] EXPLICIT BAG-TYPE.&amp;Type ({CRLTypes}{@crlId})
+ * }
+ *
+ * x509CRL BAG-TYPE ::= {OCTET STRING IDENTIFIED BY {certTypes 1}
+ * -- DER-encoded X.509 CRL stored in OCTET STRING
+ *
+ * CRLTypes BAG-TYPE ::= {
+ * x509CRL,
+ * ... -- For future extensions
+ * }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(crlId);
+ v.add(new DERTaggedObject(0, crlValue));
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/CertBag.java b/core/src/main/java/org/spongycastle/asn1/pkcs/CertBag.java
new file mode 100644
index 00000000..40dd02ed
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/CertBag.java
@@ -0,0 +1,66 @@
+package org.spongycastle.asn1.pkcs;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+public class CertBag
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier certId;
+ private ASN1Encodable certValue;
+
+ private CertBag(
+ ASN1Sequence seq)
+ {
+ this.certId = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ this.certValue = ((DERTaggedObject)seq.getObjectAt(1)).getObject();
+ }
+
+ public static CertBag getInstance(Object o)
+ {
+ if (o instanceof CertBag)
+ {
+ return (CertBag)o;
+ }
+ else if (o != null)
+ {
+ return new CertBag(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CertBag(
+ ASN1ObjectIdentifier certId,
+ ASN1Encodable certValue)
+ {
+ this.certId = certId;
+ this.certValue = certValue;
+ }
+
+ public ASN1ObjectIdentifier getCertId()
+ {
+ return certId;
+ }
+
+ public ASN1Encodable getCertValue()
+ {
+ return certValue;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certId);
+ v.add(new DERTaggedObject(0, certValue));
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/CertificationRequest.java b/core/src/main/java/org/spongycastle/asn1/pkcs/CertificationRequest.java
new file mode 100644
index 00000000..68d1d265
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/CertificationRequest.java
@@ -0,0 +1,91 @@
+package org.spongycastle.asn1.pkcs;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * PKCS10 Certification request object.
+ * <pre>
+ * CertificationRequest ::= SEQUENCE {
+ * certificationRequestInfo CertificationRequestInfo,
+ * signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }},
+ * signature BIT STRING
+ * }
+ * </pre>
+ */
+public class CertificationRequest
+ extends ASN1Object
+{
+ protected CertificationRequestInfo reqInfo = null;
+ protected AlgorithmIdentifier sigAlgId = null;
+ protected DERBitString sigBits = null;
+
+ public static CertificationRequest getInstance(Object o)
+ {
+ if (o instanceof CertificationRequest)
+ {
+ return (CertificationRequest)o;
+ }
+
+ if (o != null)
+ {
+ return new CertificationRequest(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ protected CertificationRequest()
+ {
+ }
+
+ public CertificationRequest(
+ CertificationRequestInfo requestInfo,
+ AlgorithmIdentifier algorithm,
+ DERBitString signature)
+ {
+ this.reqInfo = requestInfo;
+ this.sigAlgId = algorithm;
+ this.sigBits = signature;
+ }
+
+ public CertificationRequest(
+ ASN1Sequence seq)
+ {
+ reqInfo = CertificationRequestInfo.getInstance(seq.getObjectAt(0));
+ sigAlgId = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
+ sigBits = (DERBitString)seq.getObjectAt(2);
+ }
+
+ public CertificationRequestInfo getCertificationRequestInfo()
+ {
+ return reqInfo;
+ }
+
+ public AlgorithmIdentifier getSignatureAlgorithm()
+ {
+ return sigAlgId;
+ }
+
+ public DERBitString getSignature()
+ {
+ return sigBits;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ // Construct the CertificateRequest
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(reqInfo);
+ v.add(sigAlgId);
+ v.add(sigBits);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/CertificationRequestInfo.java b/core/src/main/java/org/spongycastle/asn1/pkcs/CertificationRequestInfo.java
new file mode 100644
index 00000000..35703140
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/CertificationRequestInfo.java
@@ -0,0 +1,164 @@
+package org.spongycastle.asn1.pkcs;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x500.X500Name;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.spongycastle.asn1.x509.X509Name;
+
+/**
+ * PKCS10 CertificationRequestInfo object.
+ * <pre>
+ * CertificationRequestInfo ::= SEQUENCE {
+ * version INTEGER { v1(0) } (v1,...),
+ * subject Name,
+ * subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
+ * attributes [0] Attributes{{ CRIAttributes }}
+ * }
+ *
+ * Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }}
+ *
+ * Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
+ * type ATTRIBUTE.&amp;id({IOSet}),
+ * values SET SIZE(1..MAX) OF ATTRIBUTE.&amp;Type({IOSet}{\@type})
+ * }
+ * </pre>
+ */
+public class CertificationRequestInfo
+ extends ASN1Object
+{
+ ASN1Integer version = new ASN1Integer(0);
+ X500Name subject;
+ SubjectPublicKeyInfo subjectPKInfo;
+ ASN1Set attributes = null;
+
+ public static CertificationRequestInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof CertificationRequestInfo)
+ {
+ return (CertificationRequestInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new CertificationRequestInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Basic constructor.
+ * <p>
+ * Note: Early on a lot of CAs would only accept messages with attributes missing. As the ASN.1 def shows
+ * the attributes field is not optional so should always at least contain an empty set. If a fully compliant
+ * request is required, pass in an empty set, the class will otherwise interpret a null as it should
+ * encode the request with the field missing.
+ * </p>
+ *
+ * @param subject subject to be associated with the public key
+ * @param pkInfo public key to be associated with subject
+ * @param attributes any attributes to be associated with the request.
+ */
+ public CertificationRequestInfo(
+ X500Name subject,
+ SubjectPublicKeyInfo pkInfo,
+ ASN1Set attributes)
+ {
+ this.subject = subject;
+ this.subjectPKInfo = pkInfo;
+ this.attributes = attributes;
+
+ if ((subject == null) || (version == null) || (subjectPKInfo == null))
+ {
+ throw new IllegalArgumentException("Not all mandatory fields set in CertificationRequestInfo generator.");
+ }
+ }
+
+ /**
+ * @deprecated use X500Name method.
+ */
+ public CertificationRequestInfo(
+ X509Name subject,
+ SubjectPublicKeyInfo pkInfo,
+ ASN1Set attributes)
+ {
+ this.subject = X500Name.getInstance(subject.toASN1Primitive());
+ this.subjectPKInfo = pkInfo;
+ this.attributes = attributes;
+
+ if ((subject == null) || (version == null) || (subjectPKInfo == null))
+ {
+ throw new IllegalArgumentException("Not all mandatory fields set in CertificationRequestInfo generator.");
+ }
+ }
+
+ /**
+ * @deprecated use getInstance().
+ */
+ public CertificationRequestInfo(
+ ASN1Sequence seq)
+ {
+ version = (ASN1Integer)seq.getObjectAt(0);
+
+ subject = X500Name.getInstance(seq.getObjectAt(1));
+ subjectPKInfo = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(2));
+
+ //
+ // some CertificationRequestInfo objects seem to treat this field
+ // as optional.
+ //
+ if (seq.size() > 3)
+ {
+ DERTaggedObject tagobj = (DERTaggedObject)seq.getObjectAt(3);
+ attributes = ASN1Set.getInstance(tagobj, false);
+ }
+
+ if ((subject == null) || (version == null) || (subjectPKInfo == null))
+ {
+ throw new IllegalArgumentException("Not all mandatory fields set in CertificationRequestInfo generator.");
+ }
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public X500Name getSubject()
+ {
+ return subject;
+ }
+
+ public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
+ {
+ return subjectPKInfo;
+ }
+
+ public ASN1Set getAttributes()
+ {
+ return attributes;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(subject);
+ v.add(subjectPKInfo);
+
+ if (attributes != null)
+ {
+ v.add(new DERTaggedObject(false, 0, attributes));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/ContentInfo.java b/core/src/main/java/org/spongycastle/asn1/pkcs/ContentInfo.java
new file mode 100644
index 00000000..a325f0fd
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/ContentInfo.java
@@ -0,0 +1,102 @@
+package org.spongycastle.asn1.pkcs;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.BERSequence;
+import org.spongycastle.asn1.BERTaggedObject;
+import org.spongycastle.asn1.DLSequence;
+
+public class ContentInfo
+ extends ASN1Object
+ implements PKCSObjectIdentifiers
+{
+ private ASN1ObjectIdentifier contentType;
+ private ASN1Encodable content;
+ private boolean isBer = true;
+
+ public static ContentInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof ContentInfo)
+ {
+ return (ContentInfo)obj;
+ }
+
+ if (obj != null)
+ {
+ return new ContentInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private ContentInfo(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ contentType = (ASN1ObjectIdentifier)e.nextElement();
+
+ if (e.hasMoreElements())
+ {
+ content = ((ASN1TaggedObject)e.nextElement()).getObject();
+ }
+
+ isBer = seq instanceof BERSequence;
+ }
+
+ public ContentInfo(
+ ASN1ObjectIdentifier contentType,
+ ASN1Encodable content)
+ {
+ this.contentType = contentType;
+ this.content = content;
+ }
+
+ public ASN1ObjectIdentifier getContentType()
+ {
+ return contentType;
+ }
+
+ public ASN1Encodable getContent()
+ {
+ return content;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * ContentInfo ::= SEQUENCE {
+ * contentType ContentType,
+ * content
+ * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(contentType);
+
+ if (content != null)
+ {
+ v.add(new BERTaggedObject(true, 0, content));
+ }
+
+ if (isBer)
+ {
+ return new BERSequence(v);
+ }
+ else
+ {
+ return new DLSequence(v);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/DHParameter.java b/core/src/main/java/org/spongycastle/asn1/pkcs/DHParameter.java
new file mode 100644
index 00000000..a427ca21
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/DHParameter.java
@@ -0,0 +1,104 @@
+package org.spongycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class DHParameter
+ extends ASN1Object
+{
+ ASN1Integer p, g, l;
+
+ public DHParameter(
+ BigInteger p,
+ BigInteger g,
+ int l)
+ {
+ this.p = new ASN1Integer(p);
+ this.g = new ASN1Integer(g);
+
+ if (l != 0)
+ {
+ this.l = new ASN1Integer(l);
+ }
+ else
+ {
+ this.l = null;
+ }
+ }
+
+ public static DHParameter getInstance(
+ Object obj)
+ {
+ if (obj instanceof DHParameter)
+ {
+ return (DHParameter)obj;
+ }
+
+ if (obj != null)
+ {
+ return new DHParameter(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private DHParameter(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ p = ASN1Integer.getInstance(e.nextElement());
+ g = ASN1Integer.getInstance(e.nextElement());
+
+ if (e.hasMoreElements())
+ {
+ l = (ASN1Integer)e.nextElement();
+ }
+ else
+ {
+ l = null;
+ }
+ }
+
+ public BigInteger getP()
+ {
+ return p.getPositiveValue();
+ }
+
+ public BigInteger getG()
+ {
+ return g.getPositiveValue();
+ }
+
+ public BigInteger getL()
+ {
+ if (l == null)
+ {
+ return null;
+ }
+
+ return l.getPositiveValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(p);
+ v.add(g);
+
+ if (this.getL() != null)
+ {
+ v.add(l);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/EncryptedData.java b/core/src/main/java/org/spongycastle/asn1/pkcs/EncryptedData.java
new file mode 100644
index 00000000..397758a8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/EncryptedData.java
@@ -0,0 +1,115 @@
+package org.spongycastle.asn1.pkcs;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.BERSequence;
+import org.spongycastle.asn1.BERTaggedObject;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * The EncryptedData object.
+ * <pre>
+ * EncryptedData ::= SEQUENCE {
+ * version Version,
+ * encryptedContentInfo EncryptedContentInfo
+ * }
+ *
+ *
+ * EncryptedContentInfo ::= SEQUENCE {
+ * contentType ContentType,
+ * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
+ * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
+ * }
+ *
+ * EncryptedContent ::= OCTET STRING
+ * </pre>
+ */
+public class EncryptedData
+ extends ASN1Object
+{
+ ASN1Sequence data;
+ ASN1ObjectIdentifier bagId;
+ ASN1Primitive bagValue;
+
+ public static EncryptedData getInstance(
+ Object obj)
+ {
+ if (obj instanceof EncryptedData)
+ {
+ return (EncryptedData)obj;
+ }
+
+ if (obj != null)
+ {
+ return new EncryptedData(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private EncryptedData(
+ ASN1Sequence seq)
+ {
+ int version = ((ASN1Integer)seq.getObjectAt(0)).getValue().intValue();
+
+ if (version != 0)
+ {
+ throw new IllegalArgumentException("sequence not version 0");
+ }
+
+ this.data = ASN1Sequence.getInstance(seq.getObjectAt(1));
+ }
+
+ public EncryptedData(
+ ASN1ObjectIdentifier contentType,
+ AlgorithmIdentifier encryptionAlgorithm,
+ ASN1Encodable content)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(contentType);
+ v.add(encryptionAlgorithm.toASN1Primitive());
+ v.add(new BERTaggedObject(false, 0, content));
+
+ data = new BERSequence(v);
+ }
+
+ public ASN1ObjectIdentifier getContentType()
+ {
+ return ASN1ObjectIdentifier.getInstance(data.getObjectAt(0));
+ }
+
+ public AlgorithmIdentifier getEncryptionAlgorithm()
+ {
+ return AlgorithmIdentifier.getInstance(data.getObjectAt(1));
+ }
+
+ public ASN1OctetString getContent()
+ {
+ if (data.size() == 3)
+ {
+ ASN1TaggedObject o = ASN1TaggedObject.getInstance(data.getObjectAt(2));
+
+ return ASN1OctetString.getInstance(o, false);
+ }
+
+ return null;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(0));
+ v.add(data);
+
+ return new BERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/EncryptedPrivateKeyInfo.java b/core/src/main/java/org/spongycastle/asn1/pkcs/EncryptedPrivateKeyInfo.java
new file mode 100644
index 00000000..1e48a621
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/EncryptedPrivateKeyInfo.java
@@ -0,0 +1,86 @@
+package org.spongycastle.asn1.pkcs;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+public class EncryptedPrivateKeyInfo
+ extends ASN1Object
+{
+ private AlgorithmIdentifier algId;
+ private ASN1OctetString data;
+
+ private EncryptedPrivateKeyInfo(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ algId = AlgorithmIdentifier.getInstance(e.nextElement());
+ data = ASN1OctetString.getInstance(e.nextElement());
+ }
+
+ public EncryptedPrivateKeyInfo(
+ AlgorithmIdentifier algId,
+ byte[] encoding)
+ {
+ this.algId = algId;
+ this.data = new DEROctetString(encoding);
+ }
+
+ public static EncryptedPrivateKeyInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof EncryptedPrivateKeyInfo)
+ {
+ return (EncryptedPrivateKeyInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new EncryptedPrivateKeyInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public AlgorithmIdentifier getEncryptionAlgorithm()
+ {
+ return algId;
+ }
+
+ public byte[] getEncryptedData()
+ {
+ return data.getOctets();
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * EncryptedPrivateKeyInfo ::= SEQUENCE {
+ * encryptionAlgorithm AlgorithmIdentifier {{KeyEncryptionAlgorithms}},
+ * encryptedData EncryptedData
+ * }
+ *
+ * EncryptedData ::= OCTET STRING
+ *
+ * KeyEncryptionAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * ... -- For local profiles
+ * }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(algId);
+ v.add(data);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/EncryptionScheme.java b/core/src/main/java/org/spongycastle/asn1/pkcs/EncryptionScheme.java
new file mode 100644
index 00000000..47bdaaff
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/EncryptionScheme.java
@@ -0,0 +1,56 @@
+package org.spongycastle.asn1.pkcs;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+public class EncryptionScheme
+ extends ASN1Object
+{
+ private AlgorithmIdentifier algId;
+
+ public EncryptionScheme(
+ ASN1ObjectIdentifier objectId,
+ ASN1Encodable parameters)
+ {
+ this.algId = new AlgorithmIdentifier(objectId, parameters);
+ }
+
+ private EncryptionScheme(
+ ASN1Sequence seq)
+ {
+ this.algId = AlgorithmIdentifier.getInstance(seq);
+ }
+
+ public static EncryptionScheme getInstance(Object obj)
+ {
+ if (obj instanceof EncryptionScheme)
+ {
+ return (EncryptionScheme)obj;
+ }
+ else if (obj != null)
+ {
+ return new EncryptionScheme(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1ObjectIdentifier getAlgorithm()
+ {
+ return algId.getAlgorithm();
+ }
+
+ public ASN1Encodable getParameters()
+ {
+ return algId.getParameters();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return algId.toASN1Primitive();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/IssuerAndSerialNumber.java b/core/src/main/java/org/spongycastle/asn1/pkcs/IssuerAndSerialNumber.java
new file mode 100644
index 00000000..1764694b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/IssuerAndSerialNumber.java
@@ -0,0 +1,85 @@
+package org.spongycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x500.X500Name;
+import org.spongycastle.asn1.x509.X509Name;
+
+public class IssuerAndSerialNumber
+ extends ASN1Object
+{
+ X500Name name;
+ ASN1Integer certSerialNumber;
+
+ public static IssuerAndSerialNumber getInstance(
+ Object obj)
+ {
+ if (obj instanceof IssuerAndSerialNumber)
+ {
+ return (IssuerAndSerialNumber)obj;
+ }
+ else if (obj != null)
+ {
+ return new IssuerAndSerialNumber(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private IssuerAndSerialNumber(
+ ASN1Sequence seq)
+ {
+ this.name = X500Name.getInstance(seq.getObjectAt(0));
+ this.certSerialNumber = (ASN1Integer)seq.getObjectAt(1);
+ }
+
+ public IssuerAndSerialNumber(
+ X509Name name,
+ BigInteger certSerialNumber)
+ {
+ this.name = X500Name.getInstance(name.toASN1Primitive());
+ this.certSerialNumber = new ASN1Integer(certSerialNumber);
+ }
+
+ public IssuerAndSerialNumber(
+ X509Name name,
+ ASN1Integer certSerialNumber)
+ {
+ this.name = X500Name.getInstance(name.toASN1Primitive());
+ this.certSerialNumber = certSerialNumber;
+ }
+
+ public IssuerAndSerialNumber(
+ X500Name name,
+ BigInteger certSerialNumber)
+ {
+ this.name = name;
+ this.certSerialNumber = new ASN1Integer(certSerialNumber);
+ }
+
+ public X500Name getName()
+ {
+ return name;
+ }
+
+ public ASN1Integer getCertificateSerialNumber()
+ {
+ return certSerialNumber;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(name);
+ v.add(certSerialNumber);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/KeyDerivationFunc.java b/core/src/main/java/org/spongycastle/asn1/pkcs/KeyDerivationFunc.java
new file mode 100644
index 00000000..9b9c72b5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/KeyDerivationFunc.java
@@ -0,0 +1,56 @@
+package org.spongycastle.asn1.pkcs;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+public class KeyDerivationFunc
+ extends ASN1Object
+{
+ private AlgorithmIdentifier algId;
+
+ public KeyDerivationFunc(
+ ASN1ObjectIdentifier objectId,
+ ASN1Encodable parameters)
+ {
+ this.algId = new AlgorithmIdentifier(objectId, parameters);
+ }
+
+ private KeyDerivationFunc(
+ ASN1Sequence seq)
+ {
+ this.algId = AlgorithmIdentifier.getInstance(seq);
+ }
+
+ public static KeyDerivationFunc getInstance(Object obj)
+ {
+ if (obj instanceof KeyDerivationFunc)
+ {
+ return (KeyDerivationFunc)obj;
+ }
+ else if (obj != null)
+ {
+ return new KeyDerivationFunc(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1ObjectIdentifier getAlgorithm()
+ {
+ return algId.getAlgorithm();
+ }
+
+ public ASN1Encodable getParameters()
+ {
+ return algId.getParameters();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return algId.toASN1Primitive();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/MacData.java b/core/src/main/java/org/spongycastle/asn1/pkcs/MacData.java
new file mode 100644
index 00000000..e1dda07b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/MacData.java
@@ -0,0 +1,106 @@
+package org.spongycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.DigestInfo;
+
+public class MacData
+ extends ASN1Object
+{
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ DigestInfo digInfo;
+ byte[] salt;
+ BigInteger iterationCount;
+
+ public static MacData getInstance(
+ Object obj)
+ {
+ if (obj instanceof MacData)
+ {
+ return (MacData)obj;
+ }
+ else if (obj != null)
+ {
+ return new MacData(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private MacData(
+ ASN1Sequence seq)
+ {
+ this.digInfo = DigestInfo.getInstance(seq.getObjectAt(0));
+
+ this.salt = ((ASN1OctetString)seq.getObjectAt(1)).getOctets();
+
+ if (seq.size() == 3)
+ {
+ this.iterationCount = ((ASN1Integer)seq.getObjectAt(2)).getValue();
+ }
+ else
+ {
+ this.iterationCount = ONE;
+ }
+ }
+
+ public MacData(
+ DigestInfo digInfo,
+ byte[] salt,
+ int iterationCount)
+ {
+ this.digInfo = digInfo;
+ this.salt = salt;
+ this.iterationCount = BigInteger.valueOf(iterationCount);
+ }
+
+ public DigestInfo getMac()
+ {
+ return digInfo;
+ }
+
+ public byte[] getSalt()
+ {
+ return salt;
+ }
+
+ public BigInteger getIterationCount()
+ {
+ return iterationCount;
+ }
+
+ /**
+ * <pre>
+ * MacData ::= SEQUENCE {
+ * mac DigestInfo,
+ * macSalt OCTET STRING,
+ * iterations INTEGER DEFAULT 1
+ * -- Note: The default is for historic reasons and its use is deprecated. A
+ * -- higher value, like 1024 is recommended.
+ * </pre>
+ * @return the basic ASN1Primitive construction.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(digInfo);
+ v.add(new DEROctetString(salt));
+
+ if (!iterationCount.equals(ONE))
+ {
+ v.add(new ASN1Integer(iterationCount));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/PBEParameter.java b/core/src/main/java/org/spongycastle/asn1/pkcs/PBEParameter.java
new file mode 100644
index 00000000..c70c0654
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/PBEParameter.java
@@ -0,0 +1,73 @@
+package org.spongycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+
+public class PBEParameter
+ extends ASN1Object
+{
+ ASN1Integer iterations;
+ ASN1OctetString salt;
+
+ public PBEParameter(
+ byte[] salt,
+ int iterations)
+ {
+ if (salt.length != 8)
+ {
+ throw new IllegalArgumentException("salt length must be 8");
+ }
+ this.salt = new DEROctetString(salt);
+ this.iterations = new ASN1Integer(iterations);
+ }
+
+ private PBEParameter(
+ ASN1Sequence seq)
+ {
+ salt = (ASN1OctetString)seq.getObjectAt(0);
+ iterations = (ASN1Integer)seq.getObjectAt(1);
+ }
+
+ public static PBEParameter getInstance(
+ Object obj)
+ {
+ if (obj instanceof PBEParameter)
+ {
+ return (PBEParameter)obj;
+ }
+ else if (obj != null)
+ {
+ return new PBEParameter(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public BigInteger getIterationCount()
+ {
+ return iterations.getValue();
+ }
+
+ public byte[] getSalt()
+ {
+ return salt.getOctets();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(salt);
+ v.add(iterations);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/PBES2Algorithms.java b/core/src/main/java/org/spongycastle/asn1/pkcs/PBES2Algorithms.java
new file mode 100644
index 00000000..1a8d9773
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/PBES2Algorithms.java
@@ -0,0 +1,77 @@
+package org.spongycastle.asn1.pkcs;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * @deprecated - use AlgorithmIdentifier and PBES2Parameters
+ */
+public class PBES2Algorithms
+ extends AlgorithmIdentifier implements PKCSObjectIdentifiers
+{
+ private ASN1ObjectIdentifier objectId;
+ private KeyDerivationFunc func;
+ private EncryptionScheme scheme;
+
+ public PBES2Algorithms(
+ ASN1Sequence obj)
+ {
+ super(obj);
+
+ Enumeration e = obj.getObjects();
+
+ objectId = (ASN1ObjectIdentifier)e.nextElement();
+
+ ASN1Sequence seq = (ASN1Sequence)e.nextElement();
+
+ e = seq.getObjects();
+
+ ASN1Sequence funcSeq = (ASN1Sequence)e.nextElement();
+
+ if (funcSeq.getObjectAt(0).equals(id_PBKDF2))
+ {
+ func = new KeyDerivationFunc(id_PBKDF2, PBKDF2Params.getInstance(funcSeq.getObjectAt(1)));
+ }
+ else
+ {
+ func = KeyDerivationFunc.getInstance(funcSeq);
+ }
+
+ scheme = EncryptionScheme.getInstance(e.nextElement());
+ }
+
+ public ASN1ObjectIdentifier getObjectId()
+ {
+ return objectId;
+ }
+
+ public KeyDerivationFunc getKeyDerivationFunc()
+ {
+ return func;
+ }
+
+ public EncryptionScheme getEncryptionScheme()
+ {
+ return scheme;
+ }
+
+ public ASN1Primitive getASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ ASN1EncodableVector subV = new ASN1EncodableVector();
+
+ v.add(objectId);
+
+ subV.add(func);
+ subV.add(scheme);
+ v.add(new DERSequence(subV));
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/PBES2Parameters.java b/core/src/main/java/org/spongycastle/asn1/pkcs/PBES2Parameters.java
new file mode 100644
index 00000000..97c1a8de
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/PBES2Parameters.java
@@ -0,0 +1,77 @@
+package org.spongycastle.asn1.pkcs;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class PBES2Parameters
+ extends ASN1Object
+ implements PKCSObjectIdentifiers
+{
+ private KeyDerivationFunc func;
+ private EncryptionScheme scheme;
+
+ public static PBES2Parameters getInstance(
+ Object obj)
+ {
+ if (obj instanceof PBES2Parameters)
+ {
+ return (PBES2Parameters)obj;
+ }
+ if (obj != null)
+ {
+ return new PBES2Parameters(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public PBES2Parameters(KeyDerivationFunc keyDevFunc, EncryptionScheme encScheme)
+ {
+ this.func = keyDevFunc;
+ this.scheme = encScheme;
+ }
+
+ private PBES2Parameters(
+ ASN1Sequence obj)
+ {
+ Enumeration e = obj.getObjects();
+ ASN1Sequence funcSeq = ASN1Sequence.getInstance(((ASN1Encodable)e.nextElement()).toASN1Primitive());
+
+ if (funcSeq.getObjectAt(0).equals(id_PBKDF2))
+ {
+ func = new KeyDerivationFunc(id_PBKDF2, PBKDF2Params.getInstance(funcSeq.getObjectAt(1)));
+ }
+ else
+ {
+ func = KeyDerivationFunc.getInstance(funcSeq);
+ }
+
+ scheme = EncryptionScheme.getInstance(e.nextElement());
+ }
+
+ public KeyDerivationFunc getKeyDerivationFunc()
+ {
+ return func;
+ }
+
+ public EncryptionScheme getEncryptionScheme()
+ {
+ return scheme;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(func);
+ v.add(scheme);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/PBKDF2Params.java b/core/src/main/java/org/spongycastle/asn1/pkcs/PBKDF2Params.java
new file mode 100644
index 00000000..e825888d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/PBKDF2Params.java
@@ -0,0 +1,248 @@
+package org.spongycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERNull;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.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)
+ {
+ if (obj instanceof PBKDF2Params)
+ {
+ return (PBKDF2Params)obj;
+ }
+
+ if (obj != null)
+ {
+ return new PBKDF2Params(ASN1Sequence.getInstance(obj));
+ }
+
+ 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)
+ {
+ this.octStr = new DEROctetString(salt);
+ 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,
+ int keyLength)
+ {
+ this(salt, iterationCount);
+
+ 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)
+ {
+ Enumeration e = seq.getObjects();
+
+ octStr = (ASN1OctetString)e.nextElement();
+ iterationCount = (ASN1Integer)e.nextElement();
+
+ if (e.hasMoreElements())
+ {
+ 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)
+ {
+ return keyLength.getValue();
+ }
+
+ 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();
+
+ v.add(octStr);
+ v.add(iterationCount);
+
+ if (keyLength != null)
+ {
+ v.add(keyLength);
+ }
+
+ if (prf != null && !prf.equals(algid_hmacWithSHA1))
+ {
+ v.add(prf);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/PKCS12PBEParams.java b/core/src/main/java/org/spongycastle/asn1/pkcs/PKCS12PBEParams.java
new file mode 100644
index 00000000..dd6400e2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/PKCS12PBEParams.java
@@ -0,0 +1,69 @@
+package org.spongycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+
+public class PKCS12PBEParams
+ extends ASN1Object
+{
+ ASN1Integer iterations;
+ ASN1OctetString iv;
+
+ public PKCS12PBEParams(
+ byte[] salt,
+ int iterations)
+ {
+ this.iv = new DEROctetString(salt);
+ this.iterations = new ASN1Integer(iterations);
+ }
+
+ private PKCS12PBEParams(
+ ASN1Sequence seq)
+ {
+ iv = (ASN1OctetString)seq.getObjectAt(0);
+ iterations = ASN1Integer.getInstance(seq.getObjectAt(1));
+ }
+
+ public static PKCS12PBEParams getInstance(
+ Object obj)
+ {
+ if (obj instanceof PKCS12PBEParams)
+ {
+ return (PKCS12PBEParams)obj;
+ }
+ else if (obj != null)
+ {
+ return new PKCS12PBEParams(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public BigInteger getIterations()
+ {
+ return iterations.getValue();
+ }
+
+ public byte[] getIV()
+ {
+ return iv.getOctets();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(iv);
+ v.add(iterations);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/PKCSObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/pkcs/PKCSObjectIdentifiers.java
new file mode 100644
index 00000000..f9acf081
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/PKCSObjectIdentifiers.java
@@ -0,0 +1,390 @@
+package org.spongycastle.asn1.pkcs;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+
+/**
+ * pkcs-1 OBJECT IDENTIFIER ::=<p>
+ * { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
+ *
+ */
+public interface PKCSObjectIdentifiers
+{
+ /** 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}
+ //
+ /** 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}
+ //
+ /** 1.2.840.113549.2.5 */
+ static final ASN1ObjectIdentifier md5 = digestAlgorithm.branch("5");
+
+ /** 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 }
+ //
+ /** 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");
+
+ /** 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");
+ /** 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");
+
+ /** 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");
+
+ //
+ // 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");
+
+ /** 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");
+ /** 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");
+
+ /** 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}
+ *
+ */
+ /** 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;
+ /** @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;
+
+ /**
+ * 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";
+
+ /** 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");
+
+ /** PKCS#12: 1.2.840.113549.1.12.1 */
+ static final ASN1ObjectIdentifier pkcs_12PbeIds = pkcs_12.branch("1");
+
+ /** PKCS#12: 1.2.840.113549.1.12.1.1 */
+ static final ASN1ObjectIdentifier pbeWithSHAAnd128BitRC4 = pkcs_12PbeIds.branch("1");
+ /** 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");
+ /** 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");
+ /** 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/core/src/main/java/org/spongycastle/asn1/pkcs/Pfx.java b/core/src/main/java/org/spongycastle/asn1/pkcs/Pfx.java
new file mode 100644
index 00000000..77a8f405
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/Pfx.java
@@ -0,0 +1,87 @@
+package org.spongycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.BERSequence;
+
+/**
+ * the infamous Pfx from PKCS12
+ */
+public class Pfx
+ extends ASN1Object
+ implements PKCSObjectIdentifiers
+{
+ private ContentInfo contentInfo;
+ private MacData macData = null;
+
+ private Pfx(
+ ASN1Sequence seq)
+ {
+ BigInteger version = ((ASN1Integer)seq.getObjectAt(0)).getValue();
+ if (version.intValue() != 3)
+ {
+ throw new IllegalArgumentException("wrong version for PFX PDU");
+ }
+
+ contentInfo = ContentInfo.getInstance(seq.getObjectAt(1));
+
+ if (seq.size() == 3)
+ {
+ macData = MacData.getInstance(seq.getObjectAt(2));
+ }
+ }
+
+ public static Pfx getInstance(
+ Object obj)
+ {
+ if (obj instanceof Pfx)
+ {
+ return (Pfx)obj;
+ }
+
+ if (obj != null)
+ {
+ return new Pfx(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public Pfx(
+ ContentInfo contentInfo,
+ MacData macData)
+ {
+ this.contentInfo = contentInfo;
+ this.macData = macData;
+ }
+
+ public ContentInfo getAuthSafe()
+ {
+ return contentInfo;
+ }
+
+ public MacData getMacData()
+ {
+ return macData;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(3));
+ v.add(contentInfo);
+
+ if (macData != null)
+ {
+ v.add(macData);
+ }
+
+ return new BERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/PrivateKeyInfo.java b/core/src/main/java/org/spongycastle/asn1/pkcs/PrivateKeyInfo.java
new file mode 100644
index 00000000..323b02b1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/PrivateKeyInfo.java
@@ -0,0 +1,164 @@
+package org.spongycastle.asn1.pkcs;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Encoding;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+public class PrivateKeyInfo
+ extends ASN1Object
+{
+ private ASN1OctetString privKey;
+ private AlgorithmIdentifier algId;
+ private ASN1Set attributes;
+
+ public static PrivateKeyInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static PrivateKeyInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof PrivateKeyInfo)
+ {
+ return (PrivateKeyInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new PrivateKeyInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public PrivateKeyInfo(
+ AlgorithmIdentifier algId,
+ ASN1Encodable privateKey)
+ throws IOException
+ {
+ this(algId, privateKey, null);
+ }
+
+ public PrivateKeyInfo(
+ AlgorithmIdentifier algId,
+ ASN1Encodable privateKey,
+ ASN1Set attributes)
+ throws IOException
+ {
+ this.privKey = new DEROctetString(privateKey.toASN1Primitive().getEncoded(ASN1Encoding.DER));
+ this.algId = algId;
+ this.attributes = attributes;
+ }
+
+ /**
+ * @deprecated use PrivateKeyInfo.getInstance()
+ * @param seq
+ */
+ public PrivateKeyInfo(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ BigInteger version = ((ASN1Integer)e.nextElement()).getValue();
+ if (version.intValue() != 0)
+ {
+ throw new IllegalArgumentException("wrong version for private key info");
+ }
+
+ algId = AlgorithmIdentifier.getInstance(e.nextElement());
+ privKey = ASN1OctetString.getInstance(e.nextElement());
+
+ if (e.hasMoreElements())
+ {
+ attributes = ASN1Set.getInstance((ASN1TaggedObject)e.nextElement(), false);
+ }
+ }
+
+ public AlgorithmIdentifier getPrivateKeyAlgorithm()
+ {
+ return algId;
+ }
+ /**
+ * @deprecated use getPrivateKeyAlgorithm()
+ */
+ public AlgorithmIdentifier getAlgorithmId()
+ {
+ return algId;
+ }
+
+ public ASN1Encodable parsePrivateKey()
+ throws IOException
+ {
+ return ASN1Primitive.fromByteArray(privKey.getOctets());
+ }
+
+ /**
+ * @deprecated use parsePrivateKey()
+ */
+ public ASN1Primitive getPrivateKey()
+ {
+ try
+ {
+ return parsePrivateKey().toASN1Primitive();
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("unable to parse private key");
+ }
+ }
+
+ public ASN1Set getAttributes()
+ {
+ return attributes;
+ }
+
+ /**
+ * write out an RSA private key with its associated information
+ * as described in PKCS8.
+ * <pre>
+ * PrivateKeyInfo ::= SEQUENCE {
+ * version Version,
+ * privateKeyAlgorithm AlgorithmIdentifier {{PrivateKeyAlgorithms}},
+ * privateKey PrivateKey,
+ * attributes [0] IMPLICIT Attributes OPTIONAL
+ * }
+ * Version ::= INTEGER {v1(0)} (v1,...)
+ *
+ * PrivateKey ::= OCTET STRING
+ *
+ * Attributes ::= SET OF Attribute
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(0));
+ v.add(algId);
+ v.add(privKey);
+
+ if (attributes != null)
+ {
+ v.add(new DERTaggedObject(false, 0, attributes));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/RC2CBCParameter.java b/core/src/main/java/org/spongycastle/asn1/pkcs/RC2CBCParameter.java
new file mode 100644
index 00000000..c054c56e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/RC2CBCParameter.java
@@ -0,0 +1,93 @@
+package org.spongycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+
+public class RC2CBCParameter
+ extends ASN1Object
+{
+ ASN1Integer version;
+ ASN1OctetString iv;
+
+ public static RC2CBCParameter getInstance(
+ Object o)
+ {
+ if (o instanceof RC2CBCParameter)
+ {
+ return (RC2CBCParameter)o;
+ }
+ if (o != null)
+ {
+ return new RC2CBCParameter(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public RC2CBCParameter(
+ byte[] iv)
+ {
+ this.version = null;
+ this.iv = new DEROctetString(iv);
+ }
+
+ public RC2CBCParameter(
+ int parameterVersion,
+ byte[] iv)
+ {
+ this.version = new ASN1Integer(parameterVersion);
+ this.iv = new DEROctetString(iv);
+ }
+
+ private RC2CBCParameter(
+ ASN1Sequence seq)
+ {
+ if (seq.size() == 1)
+ {
+ version = null;
+ iv = (ASN1OctetString)seq.getObjectAt(0);
+ }
+ else
+ {
+ version = (ASN1Integer)seq.getObjectAt(0);
+ iv = (ASN1OctetString)seq.getObjectAt(1);
+ }
+ }
+
+ public BigInteger getRC2ParameterVersion()
+ {
+ if (version == null)
+ {
+ return null;
+ }
+
+ return version.getValue();
+ }
+
+ public byte[] getIV()
+ {
+ return iv.getOctets();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (version != null)
+ {
+ v.add(version);
+ }
+
+ v.add(iv);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/RSAESOAEPparams.java b/core/src/main/java/org/spongycastle/asn1/pkcs/RSAESOAEPparams.java
new file mode 100644
index 00000000..3b735f19
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/RSAESOAEPparams.java
@@ -0,0 +1,155 @@
+package org.spongycastle.asn1.pkcs;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERNull;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.oiw.OIWObjectIdentifiers;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+public class RSAESOAEPparams
+ extends ASN1Object
+{
+ private AlgorithmIdentifier hashAlgorithm;
+ private AlgorithmIdentifier maskGenAlgorithm;
+ private AlgorithmIdentifier pSourceAlgorithm;
+
+ public final static AlgorithmIdentifier DEFAULT_HASH_ALGORITHM = new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE);
+ public final static AlgorithmIdentifier DEFAULT_MASK_GEN_FUNCTION = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_mgf1, DEFAULT_HASH_ALGORITHM);
+ public final static AlgorithmIdentifier DEFAULT_P_SOURCE_ALGORITHM = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_pSpecified, new DEROctetString(new byte[0]));
+
+ public static RSAESOAEPparams getInstance(
+ Object obj)
+ {
+ if (obj instanceof RSAESOAEPparams)
+ {
+ return (RSAESOAEPparams)obj;
+ }
+ else if (obj != null)
+ {
+ return new RSAESOAEPparams(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * The default version
+ */
+ public RSAESOAEPparams()
+ {
+ hashAlgorithm = DEFAULT_HASH_ALGORITHM;
+ maskGenAlgorithm = DEFAULT_MASK_GEN_FUNCTION;
+ pSourceAlgorithm = DEFAULT_P_SOURCE_ALGORITHM;
+ }
+
+ public RSAESOAEPparams(
+ AlgorithmIdentifier hashAlgorithm,
+ AlgorithmIdentifier maskGenAlgorithm,
+ AlgorithmIdentifier pSourceAlgorithm)
+ {
+ this.hashAlgorithm = hashAlgorithm;
+ this.maskGenAlgorithm = maskGenAlgorithm;
+ this.pSourceAlgorithm = pSourceAlgorithm;
+ }
+
+ /**
+ * @deprecated use getInstance()
+ * @param seq
+ */
+ public RSAESOAEPparams(
+ ASN1Sequence seq)
+ {
+ hashAlgorithm = DEFAULT_HASH_ALGORITHM;
+ maskGenAlgorithm = DEFAULT_MASK_GEN_FUNCTION;
+ pSourceAlgorithm = DEFAULT_P_SOURCE_ALGORITHM;
+
+ for (int i = 0; i != seq.size(); i++)
+ {
+ ASN1TaggedObject o = (ASN1TaggedObject)seq.getObjectAt(i);
+
+ switch (o.getTagNo())
+ {
+ case 0:
+ hashAlgorithm = AlgorithmIdentifier.getInstance(o, true);
+ break;
+ case 1:
+ maskGenAlgorithm = AlgorithmIdentifier.getInstance(o, true);
+ break;
+ case 2:
+ pSourceAlgorithm = AlgorithmIdentifier.getInstance(o, true);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag");
+ }
+ }
+ }
+
+ public AlgorithmIdentifier getHashAlgorithm()
+ {
+ return hashAlgorithm;
+ }
+
+ public AlgorithmIdentifier getMaskGenAlgorithm()
+ {
+ return maskGenAlgorithm;
+ }
+
+ public AlgorithmIdentifier getPSourceAlgorithm()
+ {
+ return pSourceAlgorithm;
+ }
+
+ /**
+ * <pre>
+ * RSAES-OAEP-params ::= SEQUENCE {
+ * hashAlgorithm [0] OAEP-PSSDigestAlgorithms DEFAULT sha1,
+ * maskGenAlgorithm [1] PKCS1MGFAlgorithms DEFAULT mgf1SHA1,
+ * pSourceAlgorithm [2] PKCS1PSourceAlgorithms DEFAULT pSpecifiedEmpty
+ * }
+ *
+ * OAEP-PSSDigestAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * { OID id-sha1 PARAMETERS NULL }|
+ * { OID id-sha256 PARAMETERS NULL }|
+ * { OID id-sha384 PARAMETERS NULL }|
+ * { OID id-sha512 PARAMETERS NULL },
+ * ... -- Allows for future expansion --
+ * }
+ * PKCS1MGFAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * { OID id-mgf1 PARAMETERS OAEP-PSSDigestAlgorithms },
+ * ... -- Allows for future expansion --
+ * }
+ * PKCS1PSourceAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * { OID id-pSpecified PARAMETERS OCTET STRING },
+ * ... -- Allows for future expansion --
+ * }
+ * </pre>
+ * @return the asn1 primitive representing the parameters.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (!hashAlgorithm.equals(DEFAULT_HASH_ALGORITHM))
+ {
+ v.add(new DERTaggedObject(true, 0, hashAlgorithm));
+ }
+
+ if (!maskGenAlgorithm.equals(DEFAULT_MASK_GEN_FUNCTION))
+ {
+ v.add(new DERTaggedObject(true, 1, maskGenAlgorithm));
+ }
+
+ if (!pSourceAlgorithm.equals(DEFAULT_P_SOURCE_ALGORITHM))
+ {
+ v.add(new DERTaggedObject(true, 2, pSourceAlgorithm));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/RSAPrivateKey.java b/core/src/main/java/org/spongycastle/asn1/pkcs/RSAPrivateKey.java
new file mode 100644
index 00000000..28d7b945
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/RSAPrivateKey.java
@@ -0,0 +1,187 @@
+package org.spongycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+
+public class RSAPrivateKey
+ extends ASN1Object
+{
+ private BigInteger version;
+ private BigInteger modulus;
+ private BigInteger publicExponent;
+ private BigInteger privateExponent;
+ private BigInteger prime1;
+ private BigInteger prime2;
+ private BigInteger exponent1;
+ private BigInteger exponent2;
+ private BigInteger coefficient;
+ private ASN1Sequence otherPrimeInfos = null;
+
+ public static RSAPrivateKey getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static RSAPrivateKey getInstance(
+ Object obj)
+ {
+ if (obj instanceof RSAPrivateKey)
+ {
+ return (RSAPrivateKey)obj;
+ }
+
+ if (obj != null)
+ {
+ return new RSAPrivateKey(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public RSAPrivateKey(
+ BigInteger modulus,
+ BigInteger publicExponent,
+ BigInteger privateExponent,
+ BigInteger prime1,
+ BigInteger prime2,
+ BigInteger exponent1,
+ BigInteger exponent2,
+ BigInteger coefficient)
+ {
+ this.version = BigInteger.valueOf(0);
+ this.modulus = modulus;
+ this.publicExponent = publicExponent;
+ this.privateExponent = privateExponent;
+ this.prime1 = prime1;
+ this.prime2 = prime2;
+ this.exponent1 = exponent1;
+ this.exponent2 = exponent2;
+ this.coefficient = coefficient;
+ }
+
+ private RSAPrivateKey(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ BigInteger v = ((ASN1Integer)e.nextElement()).getValue();
+ if (v.intValue() != 0 && v.intValue() != 1)
+ {
+ throw new IllegalArgumentException("wrong version for RSA private key");
+ }
+
+ version = v;
+ modulus = ((ASN1Integer)e.nextElement()).getValue();
+ publicExponent = ((ASN1Integer)e.nextElement()).getValue();
+ privateExponent = ((ASN1Integer)e.nextElement()).getValue();
+ prime1 = ((ASN1Integer)e.nextElement()).getValue();
+ prime2 = ((ASN1Integer)e.nextElement()).getValue();
+ exponent1 = ((ASN1Integer)e.nextElement()).getValue();
+ exponent2 = ((ASN1Integer)e.nextElement()).getValue();
+ coefficient = ((ASN1Integer)e.nextElement()).getValue();
+
+ if (e.hasMoreElements())
+ {
+ otherPrimeInfos = (ASN1Sequence)e.nextElement();
+ }
+ }
+
+ public BigInteger getVersion()
+ {
+ return version;
+ }
+
+ public BigInteger getModulus()
+ {
+ return modulus;
+ }
+
+ public BigInteger getPublicExponent()
+ {
+ return publicExponent;
+ }
+
+ public BigInteger getPrivateExponent()
+ {
+ return privateExponent;
+ }
+
+ public BigInteger getPrime1()
+ {
+ return prime1;
+ }
+
+ public BigInteger getPrime2()
+ {
+ return prime2;
+ }
+
+ public BigInteger getExponent1()
+ {
+ return exponent1;
+ }
+
+ public BigInteger getExponent2()
+ {
+ return exponent2;
+ }
+
+ public BigInteger getCoefficient()
+ {
+ return coefficient;
+ }
+
+ /**
+ * This outputs the key in PKCS1v2 format.
+ * <pre>
+ * RSAPrivateKey ::= SEQUENCE {
+ * version Version,
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER, -- e
+ * privateExponent INTEGER, -- d
+ * prime1 INTEGER, -- p
+ * prime2 INTEGER, -- q
+ * exponent1 INTEGER, -- d mod (p-1)
+ * exponent2 INTEGER, -- d mod (q-1)
+ * coefficient INTEGER, -- (inverse of q) mod p
+ * otherPrimeInfos OtherPrimeInfos OPTIONAL
+ * }
+ *
+ * Version ::= INTEGER { two-prime(0), multi(1) }
+ * (CONSTRAINED BY {-- version must be multi if otherPrimeInfos present --})
+ * </pre>
+ * <p>
+ * This routine is written to output PKCS1 version 2.1, private keys.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(version)); // version
+ v.add(new ASN1Integer(getModulus()));
+ v.add(new ASN1Integer(getPublicExponent()));
+ v.add(new ASN1Integer(getPrivateExponent()));
+ v.add(new ASN1Integer(getPrime1()));
+ v.add(new ASN1Integer(getPrime2()));
+ v.add(new ASN1Integer(getExponent1()));
+ v.add(new ASN1Integer(getExponent2()));
+ v.add(new ASN1Integer(getCoefficient()));
+
+ if (otherPrimeInfos != null)
+ {
+ v.add(otherPrimeInfos);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/RSAPrivateKeyStructure.java b/core/src/main/java/org/spongycastle/asn1/pkcs/RSAPrivateKeyStructure.java
new file mode 100644
index 00000000..7671a518
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/RSAPrivateKeyStructure.java
@@ -0,0 +1,189 @@
+package org.spongycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * @deprecated use RSAPrivateKey
+ */
+public class RSAPrivateKeyStructure
+ extends ASN1Object
+{
+ private int version;
+ private BigInteger modulus;
+ private BigInteger publicExponent;
+ private BigInteger privateExponent;
+ private BigInteger prime1;
+ private BigInteger prime2;
+ private BigInteger exponent1;
+ private BigInteger exponent2;
+ private BigInteger coefficient;
+ private ASN1Sequence otherPrimeInfos = null;
+
+ public static RSAPrivateKeyStructure getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static RSAPrivateKeyStructure getInstance(
+ Object obj)
+ {
+ if (obj instanceof RSAPrivateKeyStructure)
+ {
+ return (RSAPrivateKeyStructure)obj;
+ }
+ else if (obj instanceof ASN1Sequence)
+ {
+ return new RSAPrivateKeyStructure((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
+ }
+
+ public RSAPrivateKeyStructure(
+ BigInteger modulus,
+ BigInteger publicExponent,
+ BigInteger privateExponent,
+ BigInteger prime1,
+ BigInteger prime2,
+ BigInteger exponent1,
+ BigInteger exponent2,
+ BigInteger coefficient)
+ {
+ this.version = 0;
+ this.modulus = modulus;
+ this.publicExponent = publicExponent;
+ this.privateExponent = privateExponent;
+ this.prime1 = prime1;
+ this.prime2 = prime2;
+ this.exponent1 = exponent1;
+ this.exponent2 = exponent2;
+ this.coefficient = coefficient;
+ }
+
+ public RSAPrivateKeyStructure(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ BigInteger v = ((ASN1Integer)e.nextElement()).getValue();
+ if (v.intValue() != 0 && v.intValue() != 1)
+ {
+ throw new IllegalArgumentException("wrong version for RSA private key");
+ }
+
+ version = v.intValue();
+ modulus = ((ASN1Integer)e.nextElement()).getValue();
+ publicExponent = ((ASN1Integer)e.nextElement()).getValue();
+ privateExponent = ((ASN1Integer)e.nextElement()).getValue();
+ prime1 = ((ASN1Integer)e.nextElement()).getValue();
+ prime2 = ((ASN1Integer)e.nextElement()).getValue();
+ exponent1 = ((ASN1Integer)e.nextElement()).getValue();
+ exponent2 = ((ASN1Integer)e.nextElement()).getValue();
+ coefficient = ((ASN1Integer)e.nextElement()).getValue();
+
+ if (e.hasMoreElements())
+ {
+ otherPrimeInfos = (ASN1Sequence)e.nextElement();
+ }
+ }
+
+ public int getVersion()
+ {
+ return version;
+ }
+
+ public BigInteger getModulus()
+ {
+ return modulus;
+ }
+
+ public BigInteger getPublicExponent()
+ {
+ return publicExponent;
+ }
+
+ public BigInteger getPrivateExponent()
+ {
+ return privateExponent;
+ }
+
+ public BigInteger getPrime1()
+ {
+ return prime1;
+ }
+
+ public BigInteger getPrime2()
+ {
+ return prime2;
+ }
+
+ public BigInteger getExponent1()
+ {
+ return exponent1;
+ }
+
+ public BigInteger getExponent2()
+ {
+ return exponent2;
+ }
+
+ public BigInteger getCoefficient()
+ {
+ return coefficient;
+ }
+
+ /**
+ * This outputs the key in PKCS1v2 format.
+ * <pre>
+ * RSAPrivateKey ::= SEQUENCE {
+ * version Version,
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER, -- e
+ * privateExponent INTEGER, -- d
+ * prime1 INTEGER, -- p
+ * prime2 INTEGER, -- q
+ * exponent1 INTEGER, -- d mod (p-1)
+ * exponent2 INTEGER, -- d mod (q-1)
+ * coefficient INTEGER, -- (inverse of q) mod p
+ * otherPrimeInfos OtherPrimeInfos OPTIONAL
+ * }
+ *
+ * Version ::= INTEGER { two-prime(0), multi(1) }
+ * (CONSTRAINED BY {-- version must be multi if otherPrimeInfos present --})
+ * </pre>
+ * <p>
+ * This routine is written to output PKCS1 version 2.1, private keys.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(version)); // version
+ v.add(new ASN1Integer(getModulus()));
+ v.add(new ASN1Integer(getPublicExponent()));
+ v.add(new ASN1Integer(getPrivateExponent()));
+ v.add(new ASN1Integer(getPrime1()));
+ v.add(new ASN1Integer(getPrime2()));
+ v.add(new ASN1Integer(getExponent1()));
+ v.add(new ASN1Integer(getExponent2()));
+ v.add(new ASN1Integer(getCoefficient()));
+
+ if (otherPrimeInfos != null)
+ {
+ v.add(otherPrimeInfos);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/RSAPublicKey.java b/core/src/main/java/org/spongycastle/asn1/pkcs/RSAPublicKey.java
new file mode 100644
index 00000000..5ea0172a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/RSAPublicKey.java
@@ -0,0 +1,95 @@
+package org.spongycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+
+public class RSAPublicKey
+ extends ASN1Object
+{
+ private BigInteger modulus;
+ private BigInteger publicExponent;
+
+ public static RSAPublicKey getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static RSAPublicKey getInstance(
+ Object obj)
+ {
+ if (obj instanceof RSAPublicKey)
+ {
+ return (RSAPublicKey)obj;
+ }
+
+ if (obj != null)
+ {
+ return new RSAPublicKey(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public RSAPublicKey(
+ BigInteger modulus,
+ BigInteger publicExponent)
+ {
+ this.modulus = modulus;
+ this.publicExponent = publicExponent;
+ }
+
+ private RSAPublicKey(
+ ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ Enumeration e = seq.getObjects();
+
+ modulus = ASN1Integer.getInstance(e.nextElement()).getPositiveValue();
+ publicExponent = ASN1Integer.getInstance(e.nextElement()).getPositiveValue();
+ }
+
+ public BigInteger getModulus()
+ {
+ return modulus;
+ }
+
+ public BigInteger getPublicExponent()
+ {
+ return publicExponent;
+ }
+
+ /**
+ * This outputs the key in PKCS1v2 format.
+ * <pre>
+ * RSAPublicKey ::= SEQUENCE {
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER, -- e
+ * }
+ * </pre>
+ * <p>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(getModulus()));
+ v.add(new ASN1Integer(getPublicExponent()));
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/RSASSAPSSparams.java b/core/src/main/java/org/spongycastle/asn1/pkcs/RSASSAPSSparams.java
new file mode 100644
index 00000000..bca4e8c0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/RSASSAPSSparams.java
@@ -0,0 +1,172 @@
+package org.spongycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERNull;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.oiw.OIWObjectIdentifiers;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+public class RSASSAPSSparams
+ extends ASN1Object
+{
+ private AlgorithmIdentifier hashAlgorithm;
+ private AlgorithmIdentifier maskGenAlgorithm;
+ private ASN1Integer saltLength;
+ private ASN1Integer trailerField;
+
+ public final static AlgorithmIdentifier DEFAULT_HASH_ALGORITHM = new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE);
+ public final static AlgorithmIdentifier DEFAULT_MASK_GEN_FUNCTION = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_mgf1, DEFAULT_HASH_ALGORITHM);
+ public final static ASN1Integer DEFAULT_SALT_LENGTH = new ASN1Integer(20);
+ public final static ASN1Integer DEFAULT_TRAILER_FIELD = new ASN1Integer(1);
+
+ public static RSASSAPSSparams getInstance(
+ Object obj)
+ {
+ if (obj instanceof RSASSAPSSparams)
+ {
+ return (RSASSAPSSparams)obj;
+ }
+ else if (obj != null)
+ {
+ return new RSASSAPSSparams(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * The default version
+ */
+ public RSASSAPSSparams()
+ {
+ hashAlgorithm = DEFAULT_HASH_ALGORITHM;
+ maskGenAlgorithm = DEFAULT_MASK_GEN_FUNCTION;
+ saltLength = DEFAULT_SALT_LENGTH;
+ trailerField = DEFAULT_TRAILER_FIELD;
+ }
+
+ public RSASSAPSSparams(
+ AlgorithmIdentifier hashAlgorithm,
+ AlgorithmIdentifier maskGenAlgorithm,
+ ASN1Integer saltLength,
+ ASN1Integer trailerField)
+ {
+ this.hashAlgorithm = hashAlgorithm;
+ this.maskGenAlgorithm = maskGenAlgorithm;
+ this.saltLength = saltLength;
+ this.trailerField = trailerField;
+ }
+
+ private RSASSAPSSparams(
+ ASN1Sequence seq)
+ {
+ hashAlgorithm = DEFAULT_HASH_ALGORITHM;
+ maskGenAlgorithm = DEFAULT_MASK_GEN_FUNCTION;
+ saltLength = DEFAULT_SALT_LENGTH;
+ trailerField = DEFAULT_TRAILER_FIELD;
+
+ for (int i = 0; i != seq.size(); i++)
+ {
+ ASN1TaggedObject o = (ASN1TaggedObject)seq.getObjectAt(i);
+
+ switch (o.getTagNo())
+ {
+ case 0:
+ hashAlgorithm = AlgorithmIdentifier.getInstance(o, true);
+ break;
+ case 1:
+ maskGenAlgorithm = AlgorithmIdentifier.getInstance(o, true);
+ break;
+ case 2:
+ saltLength = ASN1Integer.getInstance(o, true);
+ break;
+ case 3:
+ trailerField = ASN1Integer.getInstance(o, true);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag");
+ }
+ }
+ }
+
+ public AlgorithmIdentifier getHashAlgorithm()
+ {
+ return hashAlgorithm;
+ }
+
+ public AlgorithmIdentifier getMaskGenAlgorithm()
+ {
+ return maskGenAlgorithm;
+ }
+
+ public BigInteger getSaltLength()
+ {
+ return saltLength.getValue();
+ }
+
+ public BigInteger getTrailerField()
+ {
+ return trailerField.getValue();
+ }
+
+ /**
+ * <pre>
+ * RSASSA-PSS-params ::= SEQUENCE {
+ * hashAlgorithm [0] OAEP-PSSDigestAlgorithms DEFAULT sha1,
+ * maskGenAlgorithm [1] PKCS1MGFAlgorithms DEFAULT mgf1SHA1,
+ * saltLength [2] INTEGER DEFAULT 20,
+ * trailerField [3] TrailerField DEFAULT trailerFieldBC
+ * }
+ *
+ * OAEP-PSSDigestAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * { OID id-sha1 PARAMETERS NULL }|
+ * { OID id-sha256 PARAMETERS NULL }|
+ * { OID id-sha384 PARAMETERS NULL }|
+ * { OID id-sha512 PARAMETERS NULL },
+ * ... -- Allows for future expansion --
+ * }
+ *
+ * PKCS1MGFAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * { OID id-mgf1 PARAMETERS OAEP-PSSDigestAlgorithms },
+ * ... -- Allows for future expansion --
+ * }
+ *
+ * TrailerField ::= INTEGER { trailerFieldBC(1) }
+ * </pre>
+ * @return the asn1 primitive representing the parameters.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (!hashAlgorithm.equals(DEFAULT_HASH_ALGORITHM))
+ {
+ v.add(new DERTaggedObject(true, 0, hashAlgorithm));
+ }
+
+ if (!maskGenAlgorithm.equals(DEFAULT_MASK_GEN_FUNCTION))
+ {
+ v.add(new DERTaggedObject(true, 1, maskGenAlgorithm));
+ }
+
+ if (!saltLength.equals(DEFAULT_SALT_LENGTH))
+ {
+ v.add(new DERTaggedObject(true, 2, saltLength));
+ }
+
+ if (!trailerField.equals(DEFAULT_TRAILER_FIELD))
+ {
+ v.add(new DERTaggedObject(true, 3, trailerField));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/SafeBag.java b/core/src/main/java/org/spongycastle/asn1/pkcs/SafeBag.java
new file mode 100644
index 00000000..b2201413
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/SafeBag.java
@@ -0,0 +1,96 @@
+package org.spongycastle.asn1.pkcs;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DLSequence;
+import org.spongycastle.asn1.DLTaggedObject;
+
+public class SafeBag
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier bagId;
+ private ASN1Encodable bagValue;
+ private ASN1Set bagAttributes;
+
+ public SafeBag(
+ ASN1ObjectIdentifier oid,
+ ASN1Encodable obj)
+ {
+ this.bagId = oid;
+ this.bagValue = obj;
+ this.bagAttributes = null;
+ }
+
+ public SafeBag(
+ ASN1ObjectIdentifier oid,
+ ASN1Encodable obj,
+ ASN1Set bagAttributes)
+ {
+ this.bagId = oid;
+ this.bagValue = obj;
+ this.bagAttributes = bagAttributes;
+ }
+
+ public static SafeBag getInstance(
+ Object obj)
+ {
+ if (obj instanceof SafeBag)
+ {
+ return (SafeBag)obj;
+ }
+
+ if (obj != null)
+ {
+ return new SafeBag(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private SafeBag(
+ ASN1Sequence seq)
+ {
+ this.bagId = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ this.bagValue = ((ASN1TaggedObject)seq.getObjectAt(1)).getObject();
+ if (seq.size() == 3)
+ {
+ this.bagAttributes = (ASN1Set)seq.getObjectAt(2);
+ }
+ }
+
+ public ASN1ObjectIdentifier getBagId()
+ {
+ return bagId;
+ }
+
+ public ASN1Encodable getBagValue()
+ {
+ return bagValue;
+ }
+
+ public ASN1Set getBagAttributes()
+ {
+ return bagAttributes;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(bagId);
+ v.add(new DLTaggedObject(true, 0, bagValue));
+
+ if (bagAttributes != null)
+ {
+ v.add(bagAttributes);
+ }
+
+ return new DLSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/SignedData.java b/core/src/main/java/org/spongycastle/asn1/pkcs/SignedData.java
new file mode 100644
index 00000000..c99fe692
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/SignedData.java
@@ -0,0 +1,167 @@
+package org.spongycastle.asn1.pkcs;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.BERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+/**
+ * a PKCS#7 signed data object.
+ */
+public class SignedData
+ extends ASN1Object
+ implements PKCSObjectIdentifiers
+{
+ private ASN1Integer version;
+ private ASN1Set digestAlgorithms;
+ private ContentInfo contentInfo;
+ private ASN1Set certificates;
+ private ASN1Set crls;
+ private ASN1Set signerInfos;
+
+ public static SignedData getInstance(
+ Object o)
+ {
+ if (o instanceof SignedData)
+ {
+ return (SignedData)o;
+ }
+ else if (o != null)
+ {
+ return new SignedData(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public SignedData(
+ ASN1Integer _version,
+ ASN1Set _digestAlgorithms,
+ ContentInfo _contentInfo,
+ ASN1Set _certificates,
+ ASN1Set _crls,
+ ASN1Set _signerInfos)
+ {
+ version = _version;
+ digestAlgorithms = _digestAlgorithms;
+ contentInfo = _contentInfo;
+ certificates = _certificates;
+ crls = _crls;
+ signerInfos = _signerInfos;
+ }
+
+ public SignedData(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ version = (ASN1Integer)e.nextElement();
+ digestAlgorithms = ((ASN1Set)e.nextElement());
+ contentInfo = ContentInfo.getInstance(e.nextElement());
+
+ while (e.hasMoreElements())
+ {
+ ASN1Primitive o = (ASN1Primitive)e.nextElement();
+
+ //
+ // an interesting feature of SignedData is that there appear to be varying implementations...
+ // for the moment we ignore anything which doesn't fit.
+ //
+ if (o instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tagged = (ASN1TaggedObject)o;
+
+ switch (tagged.getTagNo())
+ {
+ case 0:
+ certificates = ASN1Set.getInstance(tagged, false);
+ break;
+ case 1:
+ crls = ASN1Set.getInstance(tagged, false);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag value " + tagged.getTagNo());
+ }
+ }
+ else
+ {
+ signerInfos = (ASN1Set)o;
+ }
+ }
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public ASN1Set getDigestAlgorithms()
+ {
+ return digestAlgorithms;
+ }
+
+ public ContentInfo getContentInfo()
+ {
+ return contentInfo;
+ }
+
+ public ASN1Set getCertificates()
+ {
+ return certificates;
+ }
+
+ public ASN1Set getCRLs()
+ {
+ return crls;
+ }
+
+ public ASN1Set getSignerInfos()
+ {
+ return signerInfos;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * SignedData ::= SEQUENCE {
+ * version Version,
+ * digestAlgorithms DigestAlgorithmIdentifiers,
+ * contentInfo ContentInfo,
+ * certificates
+ * [0] IMPLICIT ExtendedCertificatesAndCertificates
+ * OPTIONAL,
+ * crls
+ * [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+ * signerInfos SignerInfos }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(digestAlgorithms);
+ v.add(contentInfo);
+
+ if (certificates != null)
+ {
+ v.add(new DERTaggedObject(false, 0, certificates));
+ }
+
+ if (crls != null)
+ {
+ v.add(new DERTaggedObject(false, 1, crls));
+ }
+
+ v.add(signerInfos);
+
+ return new BERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/pkcs/SignerInfo.java b/core/src/main/java/org/spongycastle/asn1/pkcs/SignerInfo.java
new file mode 100644
index 00000000..9285d0b3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/pkcs/SignerInfo.java
@@ -0,0 +1,178 @@
+package org.spongycastle.asn1.pkcs;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * a PKCS#7 signer info object.
+ */
+public class SignerInfo
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private IssuerAndSerialNumber issuerAndSerialNumber;
+ private AlgorithmIdentifier digAlgorithm;
+ private ASN1Set authenticatedAttributes;
+ private AlgorithmIdentifier digEncryptionAlgorithm;
+ private ASN1OctetString encryptedDigest;
+ private ASN1Set unauthenticatedAttributes;
+
+ public static SignerInfo getInstance(
+ Object o)
+ {
+ if (o instanceof SignerInfo)
+ {
+ return (SignerInfo)o;
+ }
+ else if (o instanceof ASN1Sequence)
+ {
+ return new SignerInfo((ASN1Sequence)o);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + o.getClass().getName());
+ }
+
+ public SignerInfo(
+ ASN1Integer version,
+ IssuerAndSerialNumber issuerAndSerialNumber,
+ AlgorithmIdentifier digAlgorithm,
+ ASN1Set authenticatedAttributes,
+ AlgorithmIdentifier digEncryptionAlgorithm,
+ ASN1OctetString encryptedDigest,
+ ASN1Set unauthenticatedAttributes)
+ {
+ this.version = version;
+ this.issuerAndSerialNumber = issuerAndSerialNumber;
+ this.digAlgorithm = digAlgorithm;
+ this.authenticatedAttributes = authenticatedAttributes;
+ this.digEncryptionAlgorithm = digEncryptionAlgorithm;
+ this.encryptedDigest = encryptedDigest;
+ this.unauthenticatedAttributes = unauthenticatedAttributes;
+ }
+
+ public SignerInfo(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ version = (ASN1Integer)e.nextElement();
+ issuerAndSerialNumber = IssuerAndSerialNumber.getInstance(e.nextElement());
+ digAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement());
+
+ Object obj = e.nextElement();
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ authenticatedAttributes = ASN1Set.getInstance((ASN1TaggedObject)obj, false);
+
+ digEncryptionAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement());
+ }
+ else
+ {
+ authenticatedAttributes = null;
+ digEncryptionAlgorithm = AlgorithmIdentifier.getInstance(obj);
+ }
+
+ encryptedDigest = DEROctetString.getInstance(e.nextElement());
+
+ if (e.hasMoreElements())
+ {
+ unauthenticatedAttributes = ASN1Set.getInstance((ASN1TaggedObject)e.nextElement(), false);
+ }
+ else
+ {
+ unauthenticatedAttributes = null;
+ }
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public IssuerAndSerialNumber getIssuerAndSerialNumber()
+ {
+ return issuerAndSerialNumber;
+ }
+
+ public ASN1Set getAuthenticatedAttributes()
+ {
+ return authenticatedAttributes;
+ }
+
+ public AlgorithmIdentifier getDigestAlgorithm()
+ {
+ return digAlgorithm;
+ }
+
+ public ASN1OctetString getEncryptedDigest()
+ {
+ return encryptedDigest;
+ }
+
+ public AlgorithmIdentifier getDigestEncryptionAlgorithm()
+ {
+ return digEncryptionAlgorithm;
+ }
+
+ public ASN1Set getUnauthenticatedAttributes()
+ {
+ return unauthenticatedAttributes;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * SignerInfo ::= SEQUENCE {
+ * version Version,
+ * issuerAndSerialNumber IssuerAndSerialNumber,
+ * 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()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(issuerAndSerialNumber);
+ v.add(digAlgorithm);
+
+ if (authenticatedAttributes != null)
+ {
+ v.add(new DERTaggedObject(false, 0, authenticatedAttributes));
+ }
+
+ v.add(digEncryptionAlgorithm);
+ v.add(encryptedDigest);
+
+ if (unauthenticatedAttributes != null)
+ {
+ v.add(new DERTaggedObject(false, 1, unauthenticatedAttributes));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/sec/ECPrivateKey.java b/core/src/main/java/org/spongycastle/asn1/sec/ECPrivateKey.java
new file mode 100644
index 00000000..288ec9d0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/sec/ECPrivateKey.java
@@ -0,0 +1,143 @@
+package org.spongycastle.asn1.sec;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.util.BigIntegers;
+
+/**
+ * the elliptic curve private key object from SEC 1
+ */
+public class ECPrivateKey
+ extends ASN1Object
+{
+ private ASN1Sequence seq;
+
+ private ECPrivateKey(
+ ASN1Sequence seq)
+ {
+ this.seq = seq;
+ }
+
+ public static ECPrivateKey getInstance(
+ Object obj)
+ {
+ if (obj instanceof ECPrivateKey)
+ {
+ return (ECPrivateKey)obj;
+ }
+
+ if (obj != null)
+ {
+ return new ECPrivateKey(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ECPrivateKey(
+ BigInteger key)
+ {
+ byte[] bytes = BigIntegers.asUnsignedByteArray(key);
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(1));
+ v.add(new DEROctetString(bytes));
+
+ seq = new DERSequence(v);
+ }
+
+ public ECPrivateKey(
+ BigInteger key,
+ ASN1Encodable parameters)
+ {
+ this(key, null, parameters);
+ }
+
+ public ECPrivateKey(
+ BigInteger key,
+ DERBitString publicKey,
+ ASN1Encodable parameters)
+ {
+ byte[] bytes = BigIntegers.asUnsignedByteArray(key);
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(1));
+ v.add(new DEROctetString(bytes));
+
+ if (parameters != null)
+ {
+ v.add(new DERTaggedObject(true, 0, parameters));
+ }
+
+ if (publicKey != null)
+ {
+ v.add(new DERTaggedObject(true, 1, publicKey));
+ }
+
+ seq = new DERSequence(v);
+ }
+
+ public BigInteger getKey()
+ {
+ ASN1OctetString octs = (ASN1OctetString)seq.getObjectAt(1);
+
+ return new BigInteger(1, octs.getOctets());
+ }
+
+ public DERBitString getPublicKey()
+ {
+ return (DERBitString)getObjectInTag(1);
+ }
+
+ public ASN1Primitive getParameters()
+ {
+ return getObjectInTag(0);
+ }
+
+ private ASN1Primitive getObjectInTag(int tagNo)
+ {
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ ASN1Encodable obj = (ASN1Encodable)e.nextElement();
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tag = (ASN1TaggedObject)obj;
+ if (tag.getTagNo() == tagNo)
+ {
+ return tag.getObject().toASN1Primitive();
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * ECPrivateKey ::= SEQUENCE {
+ * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
+ * privateKey OCTET STRING,
+ * parameters [0] Parameters OPTIONAL,
+ * publicKey [1] BIT STRING OPTIONAL }
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return seq;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/sec/ECPrivateKeyStructure.java b/core/src/main/java/org/spongycastle/asn1/sec/ECPrivateKeyStructure.java
new file mode 100644
index 00000000..a1f637c7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/sec/ECPrivateKeyStructure.java
@@ -0,0 +1,128 @@
+package org.spongycastle.asn1.sec;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.util.BigIntegers;
+
+/**
+ * the elliptic curve private key object from SEC 1
+ * @deprecated use ECPrivateKey
+ */
+public class ECPrivateKeyStructure
+ extends ASN1Object
+{
+ private ASN1Sequence seq;
+
+ public ECPrivateKeyStructure(
+ ASN1Sequence seq)
+ {
+ this.seq = seq;
+ }
+
+ public ECPrivateKeyStructure(
+ BigInteger key)
+ {
+ byte[] bytes = BigIntegers.asUnsignedByteArray(key);
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(1));
+ v.add(new DEROctetString(bytes));
+
+ seq = new DERSequence(v);
+ }
+
+ public ECPrivateKeyStructure(
+ BigInteger key,
+ ASN1Encodable parameters)
+ {
+ this(key, null, parameters);
+ }
+
+ public ECPrivateKeyStructure(
+ BigInteger key,
+ DERBitString publicKey,
+ ASN1Encodable parameters)
+ {
+ byte[] bytes = BigIntegers.asUnsignedByteArray(key);
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(1));
+ v.add(new DEROctetString(bytes));
+
+ if (parameters != null)
+ {
+ v.add(new DERTaggedObject(true, 0, parameters));
+ }
+
+ if (publicKey != null)
+ {
+ v.add(new DERTaggedObject(true, 1, publicKey));
+ }
+
+ seq = new DERSequence(v);
+ }
+
+ public BigInteger getKey()
+ {
+ ASN1OctetString octs = (ASN1OctetString)seq.getObjectAt(1);
+
+ return new BigInteger(1, octs.getOctets());
+ }
+
+ public DERBitString getPublicKey()
+ {
+ return (DERBitString)getObjectInTag(1);
+ }
+
+ public ASN1Primitive getParameters()
+ {
+ return getObjectInTag(0);
+ }
+
+ private ASN1Primitive getObjectInTag(int tagNo)
+ {
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ ASN1Encodable obj = (ASN1Encodable)e.nextElement();
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tag = (ASN1TaggedObject)obj;
+ if (tag.getTagNo() == tagNo)
+ {
+ return (ASN1Primitive)((ASN1Encodable)tag.getObject()).toASN1Primitive();
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * ECPrivateKey ::= SEQUENCE {
+ * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
+ * privateKey OCTET STRING,
+ * parameters [0] Parameters OPTIONAL,
+ * publicKey [1] BIT STRING OPTIONAL }
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return seq;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/sec/SECNamedCurves.java b/core/src/main/java/org/spongycastle/asn1/sec/SECNamedCurves.java
new file mode 100644
index 00000000..f33732a9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/sec/SECNamedCurves.java
@@ -0,0 +1,1094 @@
+package org.spongycastle.asn1.sec;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.x9.X9ECParameters;
+import org.spongycastle.asn1.x9.X9ECParametersHolder;
+import org.spongycastle.math.ec.ECConstants;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.ec.endo.GLVTypeBEndomorphism;
+import org.spongycastle.math.ec.endo.GLVTypeBParameters;
+import org.spongycastle.util.Strings;
+import org.spongycastle.util.encoders.Hex;
+
+public class SECNamedCurves
+{
+ private static ECCurve configureCurve(ECCurve curve)
+ {
+ return curve;
+ }
+
+ private static ECCurve configureCurveGLV(ECCurve c, GLVTypeBParameters p)
+ {
+ return c.configure().setEndomorphism(new GLVTypeBEndomorphism(c, p)).create();
+ }
+
+ private static BigInteger fromHex(
+ String hex)
+ {
+ return new BigInteger(1, Hex.decode(hex));
+ }
+
+ /*
+ * secp112r1
+ */
+ static X9ECParametersHolder secp112r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = (2^128 - 3) / 76439
+ BigInteger p = fromHex("DB7C2ABF62E35E668076BEAD208B");
+ BigInteger a = fromHex("DB7C2ABF62E35E668076BEAD2088");
+ BigInteger b = fromHex("659EF8BA043916EEDE8911702B22");
+ byte[] S = Hex.decode("00F50B028E4D696E676875615175290472783FB1");
+ BigInteger n = fromHex("DB7C2ABF62E35E7628DFAC6561C5");
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
+ //ECPoint G = curve.decodePoint(Hex.decode("02"
+ //+ "09487239995A5EE76B55F9C2F098"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "09487239995A5EE76B55F9C2F098"
+ + "A89CE5AF8724C0A23E0E0FF77500"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp112r2
+ */
+ static X9ECParametersHolder secp112r2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = (2^128 - 3) / 76439
+ BigInteger p = fromHex("DB7C2ABF62E35E668076BEAD208B");
+ BigInteger a = fromHex("6127C24C05F38A0AAAF65C0EF02C");
+ BigInteger b = fromHex("51DEF1815DB5ED74FCC34C85D709");
+ byte[] S = Hex.decode("002757A1114D696E6768756151755316C05E0BD4");
+ BigInteger n = fromHex("36DF0AAFD8B8D7597CA10520D04B");
+ BigInteger h = BigInteger.valueOf(4);
+
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "4BA30AB5E892B4E1649DD0928643"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "4BA30AB5E892B4E1649DD0928643"
+ + "ADCD46F5882E3747DEF36E956E97"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp128r1
+ */
+ static X9ECParametersHolder secp128r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^128 - 2^97 - 1
+ BigInteger p = fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF");
+ BigInteger a = fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC");
+ BigInteger b = fromHex("E87579C11079F43DD824993C2CEE5ED3");
+ byte[] S = Hex.decode("000E0D4D696E6768756151750CC03A4473D03679");
+ BigInteger n = fromHex("FFFFFFFE0000000075A30D1B9038A115");
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "161FF7528B899B2D0C28607CA52C5B86"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "161FF7528B899B2D0C28607CA52C5B86"
+ + "CF5AC8395BAFEB13C02DA292DDED7A83"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp128r2
+ */
+ static X9ECParametersHolder secp128r2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^128 - 2^97 - 1
+ BigInteger p = fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF");
+ BigInteger a = fromHex("D6031998D1B3BBFEBF59CC9BBFF9AEE1");
+ BigInteger b = fromHex("5EEEFCA380D02919DC2C6558BB6D8A5D");
+ byte[] S = Hex.decode("004D696E67687561517512D8F03431FCE63B88F4");
+ BigInteger n = fromHex("3FFFFFFF7FFFFFFFBE0024720613B5A3");
+ BigInteger h = BigInteger.valueOf(4);
+
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
+ //ECPoint G = curve.decodePoint(Hex.decode("02"
+ //+ "7B6AA5D85E572983E6FB32A7CDEBC140"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "7B6AA5D85E572983E6FB32A7CDEBC140"
+ + "27B6916A894D3AEE7106FE805FC34B44"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp160k1
+ */
+ static X9ECParametersHolder secp160k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^160 - 2^32 - 2^14 - 2^12 - 2^9 - 2^8 - 2^7 - 2^3 - 2^2 - 1
+ BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73");
+ BigInteger a = ECConstants.ZERO;
+ BigInteger b = BigInteger.valueOf(7);
+ byte[] S = null;
+ BigInteger n = fromHex("0100000000000000000001B8FA16DFAB9ACA16B6B3");
+ BigInteger h = BigInteger.valueOf(1);
+
+ GLVTypeBParameters glv = new GLVTypeBParameters(
+ new BigInteger("9ba48cba5ebcb9b6bd33b92830b2a2e0e192f10a", 16),
+ new BigInteger("c39c6c3b3a36d7701b9c71a1f5804ae5d0003f4", 16),
+ new BigInteger[]{
+ new BigInteger("9162fbe73984472a0a9e", 16),
+ new BigInteger("-96341f1138933bc2f505", 16) },
+ new BigInteger[]{
+ new BigInteger("127971af8721782ecffa3", 16),
+ new BigInteger("9162fbe73984472a0a9e", 16) },
+ new BigInteger("9162fbe73984472a0a9d0590", 16),
+ new BigInteger("96341f1138933bc2f503fd44", 16),
+ 176);
+
+ ECCurve curve = configureCurveGLV(new ECCurve.Fp(p, a, b, n, h), glv);
+// ECPoint G = curve.decodePoint(Hex.decode("02"
+// + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB"
+ + "938CF935318FDCED6BC28286531733C3F03C4FEE"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp160r1
+ */
+ static X9ECParametersHolder secp160r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^160 - 2^31 - 1
+ BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF");
+ BigInteger a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC");
+ BigInteger b = fromHex("1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45");
+ byte[] S = Hex.decode("1053CDE42C14D696E67687561517533BF3F83345");
+ BigInteger n = fromHex("0100000000000000000001F4C8F927AED3CA752257");
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
+ //ECPoint G = curve.decodePoint(Hex.decode("02"
+ //+ "4A96B5688EF573284664698968C38BB913CBFC82"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "4A96B5688EF573284664698968C38BB913CBFC82"
+ + "23A628553168947D59DCC912042351377AC5FB32"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp160r2
+ */
+ static X9ECParametersHolder secp160r2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^160 - 2^32 - 2^14 - 2^12 - 2^9 - 2^8 - 2^7 - 2^3 - 2^2 - 1
+ BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73");
+ BigInteger a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70");
+ BigInteger b = fromHex("B4E134D3FB59EB8BAB57274904664D5AF50388BA");
+ byte[] S = Hex.decode("B99B99B099B323E02709A4D696E6768756151751");
+ BigInteger n = fromHex("0100000000000000000000351EE786A818F3A1A16B");
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
+ //ECPoint G = curve.decodePoint(Hex.decode("02"
+ //+ "52DCB034293A117E1F4FF11B30F7199D3144CE6D"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "52DCB034293A117E1F4FF11B30F7199D3144CE6D"
+ + "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp192k1
+ */
+ static X9ECParametersHolder secp192k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^192 - 2^32 - 2^12 - 2^8 - 2^7 - 2^6 - 2^3 - 1
+ BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37");
+ BigInteger a = ECConstants.ZERO;
+ BigInteger b = BigInteger.valueOf(3);
+ byte[] S = null;
+ BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D");
+ BigInteger h = BigInteger.valueOf(1);
+
+ GLVTypeBParameters glv = new GLVTypeBParameters(
+ new BigInteger("bb85691939b869c1d087f601554b96b80cb4f55b35f433c2", 16),
+ new BigInteger("3d84f26c12238d7b4f3d516613c1759033b1a5800175d0b1", 16),
+ new BigInteger[]{
+ new BigInteger("71169be7330b3038edb025f1", 16),
+ new BigInteger("-b3fb3400dec5c4adceb8655c", 16) },
+ new BigInteger[]{
+ new BigInteger("12511cfe811d0f4e6bc688b4d", 16),
+ new BigInteger("71169be7330b3038edb025f1", 16) },
+ new BigInteger("71169be7330b3038edb025f1d0f9", 16),
+ new BigInteger("b3fb3400dec5c4adceb8655d4c94", 16),
+ 208);
+
+ ECCurve curve = configureCurveGLV(new ECCurve.Fp(p, a, b, n, h), glv);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"
+ + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp192r1
+ */
+ static X9ECParametersHolder secp192r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^192 - 2^64 - 1
+ BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF");
+ BigInteger a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC");
+ BigInteger b = fromHex("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1");
+ byte[] S = Hex.decode("3045AE6FC8422F64ED579528D38120EAE12196D5");
+ BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831");
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"
+ + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp224k1
+ */
+ static X9ECParametersHolder secp224k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^224 - 2^32 - 2^12 - 2^11 - 2^9 - 2^7 - 2^4 - 2 - 1
+ BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D");
+ BigInteger a = ECConstants.ZERO;
+ BigInteger b = BigInteger.valueOf(5);
+ byte[] S = null;
+ BigInteger n = fromHex("010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7");
+ BigInteger h = BigInteger.valueOf(1);
+
+ GLVTypeBParameters glv = new GLVTypeBParameters(
+ new BigInteger("fe0e87005b4e83761908c5131d552a850b3f58b749c37cf5b84d6768", 16),
+ new BigInteger("60dcd2104c4cbc0be6eeefc2bdd610739ec34e317f9b33046c9e4788", 16),
+ new BigInteger[]{
+ new BigInteger("6b8cf07d4ca75c88957d9d670591", 16),
+ new BigInteger("-b8adf1378a6eb73409fa6c9c637d", 16) },
+ new BigInteger[]{
+ new BigInteger("1243ae1b4d71613bc9f780a03690e", 16),
+ new BigInteger("6b8cf07d4ca75c88957d9d670591", 16) },
+ new BigInteger("6b8cf07d4ca75c88957d9d67059037a4", 16),
+ new BigInteger("b8adf1378a6eb73409fa6c9c637ba7f5", 16),
+ 240);
+
+ ECCurve curve = configureCurveGLV(new ECCurve.Fp(p, a, b, n, h), glv);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"
+ + "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp224r1
+ */
+ static X9ECParametersHolder secp224r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^224 - 2^96 + 1
+ BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001");
+ BigInteger a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE");
+ BigInteger b = fromHex("B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4");
+ byte[] S = Hex.decode("BD71344799D5C7FCDC45B59FA3B9AB8F6A948BC5");
+ BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D");
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
+ //ECPoint G = curve.decodePoint(Hex.decode("02"
+ //+ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"
+ + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp256k1
+ */
+ static X9ECParametersHolder secp256k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
+ BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F");
+ BigInteger a = ECConstants.ZERO;
+ BigInteger b = BigInteger.valueOf(7);
+ byte[] S = null;
+ BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
+ BigInteger h = BigInteger.valueOf(1);
+
+ GLVTypeBParameters glv = new GLVTypeBParameters(
+ new BigInteger("7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee", 16),
+ new BigInteger("5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72", 16),
+ new BigInteger[]{
+ new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16),
+ new BigInteger("-e4437ed6010e88286f547fa90abfe4c3", 16) },
+ new BigInteger[]{
+ new BigInteger("114ca50f7a8e2f3f657c1108d9d44cfd8", 16),
+ new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16) },
+ new BigInteger("3086d221a7d46bcde86c90e49284eb153dab", 16),
+ new BigInteger("e4437ed6010e88286f547fa90abfe4c42212", 16),
+ 272);
+
+ ECCurve curve = configureCurveGLV(new ECCurve.Fp(p, a, b, n, h), glv);
+ //ECPoint G = curve.decodePoint(Hex.decode("02"
+ //+ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
+ + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp256r1
+ */
+ static X9ECParametersHolder secp256r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^224 (2^32 - 1) + 2^192 + 2^96 - 1
+ BigInteger p = fromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF");
+ BigInteger a = fromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC");
+ BigInteger b = fromHex("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B");
+ byte[] S = Hex.decode("C49D360886E704936A6678E1139D26B7819F7E90");
+ BigInteger n = fromHex("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551");
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"
+ + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp384r1
+ */
+ static X9ECParametersHolder secp384r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^384 - 2^128 - 2^96 + 2^32 - 1
+ BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF");
+ BigInteger a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC");
+ BigInteger b = fromHex("B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF");
+ byte[] S = Hex.decode("A335926AA319A27A1D00896A6773A4827ACDAC73");
+ BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973");
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"
+ + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp521r1
+ */
+ static X9ECParametersHolder secp521r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^521 - 1
+ BigInteger p = fromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
+ BigInteger a = fromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC");
+ BigInteger b = fromHex("0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00");
+ byte[] S = Hex.decode("D09E8800291CB85396CC6717393284AAA0DA64BA");
+ BigInteger n = fromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409");
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
+
+ //ECPoint G = curve.decodePoint(Hex.decode("02"
+ //+ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"
+ + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect113r1
+ */
+ static X9ECParametersHolder sect113r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 113;
+ int k = 9;
+
+ BigInteger a = fromHex("003088250CA6E7C7FE649CE85820F7");
+ BigInteger b = fromHex("00E8BEE4D3E2260744188BE0E9C723");
+ byte[] S = Hex.decode("10E723AB14D696E6768756151756FEBF8FCB49A9");
+ BigInteger n = fromHex("0100000000000000D9CCEC8A39E56F");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = 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"
+ + "009D73616F35F4AB1407D73562C10F"
+ + "00A52830277958EE84D1315ED31886"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect113r2
+ */
+ static X9ECParametersHolder sect113r2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 113;
+ int k = 9;
+
+ BigInteger a = fromHex("00689918DBEC7E5A0DD6DFC0AA55C7");
+ BigInteger b = fromHex("0095E9A9EC9B297BD4BF36E059184F");
+ byte[] S = Hex.decode("10C0FB15760860DEF1EEF4D696E676875615175D");
+ BigInteger n = fromHex("010000000000000108789B2496AF93");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = 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"
+ + "01A57A6A7B26CA5EF52FCDB8164797"
+ + "00B3ADC94ED1FE674C06E695BABA1D"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect131r1
+ */
+ static X9ECParametersHolder sect131r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 131;
+ int k1 = 2;
+ int k2 = 3;
+ int k3 = 8;
+
+ BigInteger a = fromHex("07A11B09A76B562144418FF3FF8C2570B8");
+ BigInteger b = fromHex("0217C05610884B63B9C6C7291678F9D341");
+ byte[] S = Hex.decode("4D696E676875615175985BD3ADBADA21B43A97E2");
+ BigInteger n = fromHex("0400000000000000023123953A9464B54D");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = 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"
+ + "0081BAF91FDF9833C40F9C181343638399"
+ + "078C6E7EA38C001F73C8134B1B4EF9E150"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect131r2
+ */
+ static X9ECParametersHolder sect131r2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 131;
+ int k1 = 2;
+ int k2 = 3;
+ int k3 = 8;
+
+ BigInteger a = fromHex("03E5A88919D7CAFCBF415F07C2176573B2");
+ BigInteger b = fromHex("04B8266A46C55657AC734CE38F018F2192");
+ byte[] S = Hex.decode("985BD3ADBAD4D696E676875615175A21B43A97E3");
+ BigInteger n = fromHex("0400000000000000016954A233049BA98F");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = 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"
+ + "0356DCD8F2F95031AD652D23951BB366A8"
+ + "0648F06D867940A5366D9E265DE9EB240F"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect163k1
+ */
+ static X9ECParametersHolder sect163k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 163;
+ int k1 = 3;
+ int k2 = 6;
+ int k3 = 7;
+
+ BigInteger a = BigInteger.valueOf(1);
+ BigInteger b = BigInteger.valueOf(1);
+ byte[] S = null;
+ BigInteger n = fromHex("04000000000000000000020108A2E0CC0D99F8A5EF");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = 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"
+ + "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8"
+ + "0289070FB05D38FF58321F2E800536D538CCDAA3D9"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect163r1
+ */
+ static X9ECParametersHolder sect163r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 163;
+ int k1 = 3;
+ int k2 = 6;
+ int k3 = 7;
+
+ BigInteger a = fromHex("07B6882CAAEFA84F9554FF8428BD88E246D2782AE2");
+ BigInteger b = fromHex("0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9");
+ byte[] S = Hex.decode("24B7B137C8A14D696E6768756151756FD0DA2E5C");
+ BigInteger n = fromHex("03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = 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"
+ + "0369979697AB43897789566789567F787A7876A654"
+ + "00435EDB42EFAFB2989D51FEFCE3C80988F41FF883"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect163r2
+ */
+ static X9ECParametersHolder sect163r2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 163;
+ int k1 = 3;
+ int k2 = 6;
+ int k3 = 7;
+
+ BigInteger a = BigInteger.valueOf(1);
+ BigInteger b = fromHex("020A601907B8C953CA1481EB10512F78744A3205FD");
+ byte[] S = Hex.decode("85E25BFE5C86226CDB12016F7553F9D0E693A268");
+ BigInteger n = fromHex("040000000000000000000292FE77E70C12A4234C33");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = 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"
+ + "03F0EBA16286A2D57EA0991168D4994637E8343E36"
+ + "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect193r1
+ */
+ static X9ECParametersHolder sect193r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 193;
+ int k = 15;
+
+ BigInteger a = fromHex("0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01");
+ BigInteger b = fromHex("00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814");
+ byte[] S = Hex.decode("103FAEC74D696E676875615175777FC5B191EF30");
+ BigInteger n = fromHex("01000000000000000000000000C7F34A778F443ACC920EBA49");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = 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"
+ + "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1"
+ + "0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect193r2
+ */
+ static X9ECParametersHolder sect193r2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 193;
+ int k = 15;
+
+ BigInteger a = fromHex("0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B");
+ BigInteger b = fromHex("00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE");
+ byte[] S = Hex.decode("10B7B4D696E676875615175137C8A16FD0DA2211");
+ BigInteger n = fromHex("010000000000000000000000015AAB561B005413CCD4EE99D5");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = 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"
+ + "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F"
+ + "01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect233k1
+ */
+ static X9ECParametersHolder sect233k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 233;
+ int k = 74;
+
+ BigInteger a = ECConstants.ZERO;
+ BigInteger b = BigInteger.valueOf(1);
+ byte[] S = null;
+ BigInteger n = fromHex("8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF");
+ BigInteger h = BigInteger.valueOf(4);
+
+ ECCurve curve = 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"
+ + "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126"
+ + "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect233r1
+ */
+ static X9ECParametersHolder sect233r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 233;
+ int k = 74;
+
+ BigInteger a = BigInteger.valueOf(1);
+ BigInteger b = fromHex("0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD");
+ byte[] S = Hex.decode("74D59FF07F6B413D0EA14B344B20A2DB049B50C3");
+ BigInteger n = fromHex("01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = 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"
+ + "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B"
+ + "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect239k1
+ */
+ static X9ECParametersHolder sect239k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 239;
+ int k = 158;
+
+ BigInteger a = ECConstants.ZERO;
+ BigInteger b = BigInteger.valueOf(1);
+ byte[] S = null;
+ BigInteger n = fromHex("2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5");
+ BigInteger h = BigInteger.valueOf(4);
+
+ ECCurve curve = 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"
+ + "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC"
+ + "76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect283k1
+ */
+ static X9ECParametersHolder sect283k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 283;
+ int k1 = 5;
+ int k2 = 7;
+ int k3 = 12;
+
+ BigInteger a = ECConstants.ZERO;
+ BigInteger b = BigInteger.valueOf(1);
+ byte[] S = null;
+ BigInteger n = fromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61");
+ BigInteger h = BigInteger.valueOf(4);
+
+ ECCurve curve = 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"
+ + "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836"
+ + "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect283r1
+ */
+ static X9ECParametersHolder sect283r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 283;
+ int k1 = 5;
+ int k2 = 7;
+ int k3 = 12;
+
+ BigInteger a = BigInteger.valueOf(1);
+ BigInteger b = fromHex("027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5");
+ byte[] S = Hex.decode("77E2B07370EB0F832A6DD5B62DFC88CD06BB84BE");
+ BigInteger n = fromHex("03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = 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"
+ + "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053"
+ + "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect409k1
+ */
+ static X9ECParametersHolder sect409k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 409;
+ int k = 87;
+
+ BigInteger a = ECConstants.ZERO;
+ BigInteger b = BigInteger.valueOf(1);
+ byte[] S = null;
+ BigInteger n = fromHex("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF");
+ BigInteger h = BigInteger.valueOf(4);
+
+ ECCurve curve = 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"
+ + "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746"
+ + "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect409r1
+ */
+ static X9ECParametersHolder sect409r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 409;
+ int k = 87;
+
+ BigInteger a = BigInteger.valueOf(1);
+ BigInteger b = fromHex("0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F");
+ byte[] S = Hex.decode("4099B5A457F9D69F79213D094C4BCD4D4262210B");
+ BigInteger n = fromHex("010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = 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"
+ + "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7"
+ + "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect571k1
+ */
+ static X9ECParametersHolder sect571k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 571;
+ int k1 = 2;
+ int k2 = 5;
+ int k3 = 10;
+
+ BigInteger a = ECConstants.ZERO;
+ BigInteger b = BigInteger.valueOf(1);
+ byte[] S = null;
+ BigInteger n = fromHex("020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001");
+ BigInteger h = BigInteger.valueOf(4);
+
+ ECCurve curve = 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"
+ + "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972"
+ + "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect571r1
+ */
+ static X9ECParametersHolder sect571r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 571;
+ int k1 = 2;
+ int k2 = 5;
+ int k3 = 10;
+
+ BigInteger a = BigInteger.valueOf(1);
+ BigInteger b = fromHex("02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A");
+ byte[] S = Hex.decode("2AA058F73A0E33AB486B0F610410C53A7F132310");
+ BigInteger n = fromHex("03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = 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"
+ + "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19"
+ + "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+
+ static final Hashtable objIds = new Hashtable();
+ static final Hashtable curves = new Hashtable();
+ static final Hashtable names = new Hashtable();
+
+ static void defineCurve(String name, ASN1ObjectIdentifier oid, X9ECParametersHolder holder)
+ {
+ objIds.put(name, oid);
+ names.put(oid, name);
+ curves.put(oid, holder);
+ }
+
+ static
+ {
+ defineCurve("secp112r1", SECObjectIdentifiers.secp112r1, secp112r1);
+ defineCurve("secp112r2", SECObjectIdentifiers.secp112r2, secp112r2);
+ defineCurve("secp128r1", SECObjectIdentifiers.secp128r1, secp128r1);
+ defineCurve("secp128r2", SECObjectIdentifiers.secp128r2, secp128r2);
+ defineCurve("secp160k1", SECObjectIdentifiers.secp160k1, secp160k1);
+ defineCurve("secp160r1", SECObjectIdentifiers.secp160r1, secp160r1);
+ defineCurve("secp160r2", SECObjectIdentifiers.secp160r2, secp160r2);
+ defineCurve("secp192k1", SECObjectIdentifiers.secp192k1, secp192k1);
+ defineCurve("secp192r1", SECObjectIdentifiers.secp192r1, secp192r1);
+ defineCurve("secp224k1", SECObjectIdentifiers.secp224k1, secp224k1);
+ defineCurve("secp224r1", SECObjectIdentifiers.secp224r1, secp224r1);
+ defineCurve("secp256k1", SECObjectIdentifiers.secp256k1, secp256k1);
+ defineCurve("secp256r1", SECObjectIdentifiers.secp256r1, secp256r1);
+ defineCurve("secp384r1", SECObjectIdentifiers.secp384r1, secp384r1);
+ defineCurve("secp521r1", SECObjectIdentifiers.secp521r1, secp521r1);
+
+ defineCurve("sect113r1", SECObjectIdentifiers.sect113r1, sect113r1);
+ defineCurve("sect113r2", SECObjectIdentifiers.sect113r2, sect113r2);
+ defineCurve("sect131r1", SECObjectIdentifiers.sect131r1, sect131r1);
+ defineCurve("sect131r2", SECObjectIdentifiers.sect131r2, sect131r2);
+ defineCurve("sect163k1", SECObjectIdentifiers.sect163k1, sect163k1);
+ defineCurve("sect163r1", SECObjectIdentifiers.sect163r1, sect163r1);
+ defineCurve("sect163r2", SECObjectIdentifiers.sect163r2, sect163r2);
+ defineCurve("sect193r1", SECObjectIdentifiers.sect193r1, sect193r1);
+ defineCurve("sect193r2", SECObjectIdentifiers.sect193r2, sect193r2);
+ defineCurve("sect233k1", SECObjectIdentifiers.sect233k1, sect233k1);
+ defineCurve("sect233r1", SECObjectIdentifiers.sect233r1, sect233r1);
+ defineCurve("sect239k1", SECObjectIdentifiers.sect239k1, sect239k1);
+ defineCurve("sect283k1", SECObjectIdentifiers.sect283k1, sect283k1);
+ defineCurve("sect283r1", SECObjectIdentifiers.sect283r1, sect283r1);
+ defineCurve("sect409k1", SECObjectIdentifiers.sect409k1, sect409k1);
+ defineCurve("sect409r1", SECObjectIdentifiers.sect409r1, sect409r1);
+ defineCurve("sect571k1", SECObjectIdentifiers.sect571k1, sect571k1);
+ defineCurve("sect571r1", SECObjectIdentifiers.sect571r1, sect571r1);
+ }
+
+ public static X9ECParameters getByName(
+ String name)
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)objIds.get(Strings.toLowerCase(name));
+
+ if (oid != null)
+ {
+ return getByOID(oid);
+ }
+
+ return null;
+ }
+
+ /**
+ * return the X9ECParameters object for the named curve represented by
+ * the passed in object identifier. Null if the curve isn't present.
+ *
+ * @param oid an object identifier representing a named curve, if present.
+ */
+ public static X9ECParameters getByOID(
+ ASN1ObjectIdentifier oid)
+ {
+ X9ECParametersHolder holder = (X9ECParametersHolder)curves.get(oid);
+
+ if (holder != null)
+ {
+ return holder.getParameters();
+ }
+
+ return null;
+ }
+
+ /**
+ * return the object identifier signified by the passed in name. Null
+ * if there is no object identifier associated with name.
+ *
+ * @return the object identifier associated with name, if present.
+ */
+ public static ASN1ObjectIdentifier getOID(
+ String name)
+ {
+ return (ASN1ObjectIdentifier)objIds.get(Strings.toLowerCase(name));
+ }
+
+ /**
+ * return the named curve name represented by the given object identifier.
+ */
+ public static String getName(
+ ASN1ObjectIdentifier oid)
+ {
+ return (String)names.get(oid);
+ }
+
+ /**
+ * returns an enumeration containing the name strings for curves
+ * contained in this structure.
+ */
+ public static Enumeration getNames()
+ {
+ return objIds.keys();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/sec/SECObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/sec/SECObjectIdentifiers.java
new file mode 100644
index 00000000..b5c48b94
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/sec/SECObjectIdentifiers.java
@@ -0,0 +1,87 @@
+package org.spongycastle.asn1.sec;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.x9.X9ObjectIdentifiers;
+
+/**
+ * Certicom object identifiers
+ * <pre>
+ * ellipticCurve OBJECT IDENTIFIER ::= {
+ * iso(1) identified-organization(3) certicom(132) curve(0)
+ * }
+ * </pre>
+ */
+public interface SECObjectIdentifiers
+{
+ /** 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/core/src/main/java/org/spongycastle/asn1/smime/SMIMEAttributes.java b/core/src/main/java/org/spongycastle/asn1/smime/SMIMEAttributes.java
new file mode 100644
index 00000000..cf3f57e3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/smime/SMIMEAttributes.java
@@ -0,0 +1,10 @@
+package org.spongycastle.asn1.smime;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+
+public interface SMIMEAttributes
+{
+ public static final ASN1ObjectIdentifier smimeCapabilities = PKCSObjectIdentifiers.pkcs_9_at_smimeCapabilities;
+ public static final ASN1ObjectIdentifier encrypKeyPref = PKCSObjectIdentifiers.id_aa_encrypKeyPref;
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/smime/SMIMECapabilities.java b/core/src/main/java/org/spongycastle/asn1/smime/SMIMECapabilities.java
new file mode 100644
index 00000000..e25f5eb3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/smime/SMIMECapabilities.java
@@ -0,0 +1,115 @@
+package org.spongycastle.asn1.smime;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.cms.Attribute;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+
+/**
+ * Handler class for dealing with S/MIME Capabilities
+ */
+public class SMIMECapabilities
+ extends ASN1Object
+{
+ /**
+ * general preferences
+ */
+ public static final ASN1ObjectIdentifier preferSignedData = PKCSObjectIdentifiers.preferSignedData;
+ public static final ASN1ObjectIdentifier canNotDecryptAny = PKCSObjectIdentifiers.canNotDecryptAny;
+ public static final ASN1ObjectIdentifier sMIMECapabilitesVersions = PKCSObjectIdentifiers.sMIMECapabilitiesVersions;
+
+ /**
+ * encryption algorithms preferences
+ */
+ public static final ASN1ObjectIdentifier dES_CBC = new ASN1ObjectIdentifier("1.3.14.3.2.7");
+ public static final ASN1ObjectIdentifier dES_EDE3_CBC = PKCSObjectIdentifiers.des_EDE3_CBC;
+ public static final ASN1ObjectIdentifier rC2_CBC = PKCSObjectIdentifiers.RC2_CBC;
+
+ private ASN1Sequence capabilities;
+
+ /**
+ * return an Attribute object from the given object.
+ *
+ * @param o the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static SMIMECapabilities getInstance(
+ Object o)
+ {
+ if (o == null || o instanceof SMIMECapabilities)
+ {
+ return (SMIMECapabilities)o;
+ }
+
+ if (o instanceof ASN1Sequence)
+ {
+ return new SMIMECapabilities((ASN1Sequence)o);
+ }
+
+ if (o instanceof Attribute)
+ {
+ return new SMIMECapabilities(
+ (ASN1Sequence)(((Attribute)o).getAttrValues().getObjectAt(0)));
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + o.getClass().getName());
+ }
+
+ public SMIMECapabilities(
+ ASN1Sequence seq)
+ {
+ capabilities = seq;
+ }
+
+ /**
+ * returns a vector with 0 or more objects of all the capabilities
+ * matching the passed in capability OID. If the OID passed is null the
+ * entire set is returned.
+ */
+ public Vector getCapabilities(
+ ASN1ObjectIdentifier capability)
+ {
+ Enumeration e = capabilities.getObjects();
+ Vector list = new Vector();
+
+ if (capability == null)
+ {
+ while (e.hasMoreElements())
+ {
+ SMIMECapability cap = SMIMECapability.getInstance(e.nextElement());
+
+ list.addElement(cap);
+ }
+ }
+ else
+ {
+ while (e.hasMoreElements())
+ {
+ SMIMECapability cap = SMIMECapability.getInstance(e.nextElement());
+
+ if (capability.equals(cap.getCapabilityID()))
+ {
+ list.addElement(cap);
+ }
+ }
+ }
+
+ return list;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * SMIMECapabilities ::= SEQUENCE OF SMIMECapability
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return capabilities;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/smime/SMIMECapabilitiesAttribute.java b/core/src/main/java/org/spongycastle/asn1/smime/SMIMECapabilitiesAttribute.java
new file mode 100644
index 00000000..53e749aa
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/smime/SMIMECapabilitiesAttribute.java
@@ -0,0 +1,16 @@
+package org.spongycastle.asn1.smime;
+
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERSet;
+import org.spongycastle.asn1.cms.Attribute;
+
+public class SMIMECapabilitiesAttribute
+ extends Attribute
+{
+ public SMIMECapabilitiesAttribute(
+ SMIMECapabilityVector capabilities)
+ {
+ super(SMIMEAttributes.smimeCapabilities,
+ new DERSet(new DERSequence(capabilities.toASN1EncodableVector())));
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/smime/SMIMECapability.java b/core/src/main/java/org/spongycastle/asn1/smime/SMIMECapability.java
new file mode 100644
index 00000000..c3c4a999
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/smime/SMIMECapability.java
@@ -0,0 +1,103 @@
+package org.spongycastle.asn1.smime;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.nist.NISTObjectIdentifiers;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+
+public class SMIMECapability
+ extends ASN1Object
+{
+ /**
+ * general preferences
+ */
+ public static final ASN1ObjectIdentifier preferSignedData = PKCSObjectIdentifiers.preferSignedData;
+ public static final ASN1ObjectIdentifier canNotDecryptAny = PKCSObjectIdentifiers.canNotDecryptAny;
+ public static final ASN1ObjectIdentifier sMIMECapabilitiesVersions = PKCSObjectIdentifiers.sMIMECapabilitiesVersions;
+
+ /**
+ * encryption algorithms preferences
+ */
+ public static final ASN1ObjectIdentifier dES_CBC = new ASN1ObjectIdentifier("1.3.14.3.2.7");
+ public static final ASN1ObjectIdentifier dES_EDE3_CBC = PKCSObjectIdentifiers.des_EDE3_CBC;
+ public static final ASN1ObjectIdentifier rC2_CBC = PKCSObjectIdentifiers.RC2_CBC;
+ public static final ASN1ObjectIdentifier aES128_CBC = NISTObjectIdentifiers.id_aes128_CBC;
+ public static final ASN1ObjectIdentifier aES192_CBC = NISTObjectIdentifiers.id_aes192_CBC;
+ public static final ASN1ObjectIdentifier aES256_CBC = NISTObjectIdentifiers.id_aes256_CBC;
+
+ private ASN1ObjectIdentifier capabilityID;
+ private ASN1Encodable parameters;
+
+ public SMIMECapability(
+ ASN1Sequence seq)
+ {
+ capabilityID = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+
+ if (seq.size() > 1)
+ {
+ parameters = (ASN1Primitive)seq.getObjectAt(1);
+ }
+ }
+
+ public SMIMECapability(
+ ASN1ObjectIdentifier capabilityID,
+ ASN1Encodable parameters)
+ {
+ this.capabilityID = capabilityID;
+ this.parameters = parameters;
+ }
+
+ public static SMIMECapability getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof SMIMECapability)
+ {
+ return (SMIMECapability)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new SMIMECapability((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid SMIMECapability");
+ }
+
+ public ASN1ObjectIdentifier getCapabilityID()
+ {
+ return capabilityID;
+ }
+
+ public ASN1Encodable getParameters()
+ {
+ return parameters;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * SMIMECapability ::= SEQUENCE {
+ * capabilityID OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY capabilityID OPTIONAL
+ * }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(capabilityID);
+
+ if (parameters != null)
+ {
+ v.add(parameters);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/smime/SMIMECapabilityVector.java b/core/src/main/java/org/spongycastle/asn1/smime/SMIMECapabilityVector.java
new file mode 100644
index 00000000..91834e38
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/smime/SMIMECapabilityVector.java
@@ -0,0 +1,50 @@
+package org.spongycastle.asn1.smime;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * Handler for creating a vector S/MIME Capabilities
+ */
+public class SMIMECapabilityVector
+{
+ private ASN1EncodableVector capabilities = new ASN1EncodableVector();
+
+ public void addCapability(
+ ASN1ObjectIdentifier capability)
+ {
+ capabilities.add(new DERSequence(capability));
+ }
+
+ public void addCapability(
+ ASN1ObjectIdentifier capability,
+ int value)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(capability);
+ v.add(new ASN1Integer(value));
+
+ capabilities.add(new DERSequence(v));
+ }
+
+ public void addCapability(
+ ASN1ObjectIdentifier capability,
+ ASN1Encodable params)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(capability);
+ v.add(params);
+
+ capabilities.add(new DERSequence(v));
+ }
+
+ public ASN1EncodableVector toASN1EncodableVector()
+ {
+ return capabilities;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/smime/SMIMEEncryptionKeyPreferenceAttribute.java b/core/src/main/java/org/spongycastle/asn1/smime/SMIMEEncryptionKeyPreferenceAttribute.java
new file mode 100644
index 00000000..2eacdee9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/smime/SMIMEEncryptionKeyPreferenceAttribute.java
@@ -0,0 +1,48 @@
+package org.spongycastle.asn1.smime;
+
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.DERSet;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.cms.Attribute;
+import org.spongycastle.asn1.cms.IssuerAndSerialNumber;
+import org.spongycastle.asn1.cms.RecipientKeyIdentifier;
+
+/**
+ * The SMIMEEncryptionKeyPreference object.
+ * <pre>
+ * SMIMEEncryptionKeyPreference ::= CHOICE {
+ * issuerAndSerialNumber [0] IssuerAndSerialNumber,
+ * receipentKeyId [1] RecipientKeyIdentifier,
+ * subjectAltKeyIdentifier [2] SubjectKeyIdentifier
+ * }
+ * </pre>
+ */
+public class SMIMEEncryptionKeyPreferenceAttribute
+ extends Attribute
+{
+ public SMIMEEncryptionKeyPreferenceAttribute(
+ IssuerAndSerialNumber issAndSer)
+ {
+ super(SMIMEAttributes.encrypKeyPref,
+ new DERSet(new DERTaggedObject(false, 0, issAndSer)));
+ }
+
+ public SMIMEEncryptionKeyPreferenceAttribute(
+ RecipientKeyIdentifier rKeyId)
+ {
+
+ super(SMIMEAttributes.encrypKeyPref,
+ new DERSet(new DERTaggedObject(false, 1, rKeyId)));
+ }
+
+ /**
+ * @param sKeyId the subjectKeyIdentifier value (normally the X.509 one)
+ */
+ public SMIMEEncryptionKeyPreferenceAttribute(
+ ASN1OctetString sKeyId)
+ {
+
+ super(SMIMEAttributes.encrypKeyPref,
+ new DERSet(new DERTaggedObject(false, 2, sKeyId)));
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/teletrust/TeleTrusTNamedCurves.java b/core/src/main/java/org/spongycastle/asn1/teletrust/TeleTrusTNamedCurves.java
new file mode 100644
index 00000000..003a3640
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/teletrust/TeleTrusTNamedCurves.java
@@ -0,0 +1,398 @@
+package org.spongycastle.asn1.teletrust;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.x9.X9ECParameters;
+import org.spongycastle.asn1.x9.X9ECParametersHolder;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.util.Strings;
+import org.spongycastle.util.encoders.Hex;
+
+/**
+ * elliptic curves defined in "ECC Brainpool Standard Curves and Curve Generation"
+ * http://www.ecc-brainpool.org/download/draft_pkix_additional_ecc_dp.txt
+ */
+public class TeleTrusTNamedCurves
+{
+ private static ECCurve configureCurve(ECCurve curve)
+ {
+ return curve;
+ }
+
+ static X9ECParametersHolder brainpoolP160r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger n = new BigInteger("E95E4A5F737059DC60DF5991D45029409E60FC09", 16);
+ BigInteger h = new BigInteger("01", 16);
+
+ ECCurve curve = configureCurve(new ECCurve.Fp(
+ new BigInteger("E95E4A5F737059DC60DFC7AD95B3D8139515620F", 16), // q
+ new BigInteger("340E7BE2A280EB74E2BE61BADA745D97E8F7C300", 16), // a
+ new BigInteger("1E589A8595423412134FAA2DBDEC95C8D8675E58", 16), // b
+ n, h));
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("04BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC31667CB477A1A8EC338F94741669C976316DA6321")), // G
+ n, h);
+ }
+ };
+
+ static X9ECParametersHolder brainpoolP160t1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger n = new BigInteger("E95E4A5F737059DC60DF5991D45029409E60FC09", 16);
+ BigInteger h = new BigInteger("01", 16);
+
+ 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'
+ n, h));
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("04B199B13B9B34EFC1397E64BAEB05ACC265FF2378ADD6718B7C7C1961F0991B842443772152C9E0AD")), // G
+ n, h);
+ }
+ };
+
+ static X9ECParametersHolder brainpoolP192r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger n = new BigInteger("C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", 16);
+ BigInteger h = new BigInteger("01", 16);
+
+ ECCurve curve = configureCurve(new ECCurve.Fp(
+ new BigInteger("C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", 16), // q
+ new BigInteger("6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", 16), // a
+ new BigInteger("469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", 16), // b
+ n, h));
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("04C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD614B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F")), // G
+ n, h);
+ }
+ };
+
+ static X9ECParametersHolder brainpoolP192t1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger n = new BigInteger("C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", 16);
+ BigInteger h = new BigInteger("01", 16);
+
+ 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'
+ n, h));
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("043AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9")), // G'
+ n, h);
+ }
+ };
+
+ static X9ECParametersHolder brainpoolP224r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger n = new BigInteger("D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", 16);
+ BigInteger h = new BigInteger("01", 16);
+
+ ECCurve curve = configureCurve(new ECCurve.Fp(
+ new BigInteger("D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", 16), // q
+ new BigInteger("68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", 16), // a
+ new BigInteger("2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", 16), // b
+ n, h));
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD")), // G
+ n, h);
+ }
+ };
+ static X9ECParametersHolder brainpoolP224t1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger n = new BigInteger("D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", 16);
+ BigInteger h = new BigInteger("01", 16);
+
+ 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'
+ n, h));
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("046AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D5800374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C")), // G'
+ n, h);
+ }
+ };
+ static X9ECParametersHolder brainpoolP256r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger n = new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 16);
+ BigInteger h = new BigInteger("01", 16);
+
+ ECCurve curve = configureCurve(new ECCurve.Fp(
+ new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", 16), // q
+ new BigInteger("7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", 16), // a
+ new BigInteger("26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", 16), // b
+ n, h));
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997")), // G
+ n, h);
+ }
+ };
+ static X9ECParametersHolder brainpoolP256t1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger n = new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 16);
+ BigInteger h = new BigInteger("01", 16);
+
+ 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'
+ n, h));
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("04A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F42D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE")), // G'
+ n, h);
+ }
+ };
+ static X9ECParametersHolder brainpoolP320r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger n = new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", 16);
+ BigInteger h = new BigInteger("01", 16);
+
+ ECCurve curve = configureCurve(new ECCurve.Fp(
+ new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", 16), // q
+ new BigInteger("3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", 16), // a
+ new BigInteger("520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", 16), // b
+ n, h));
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("0443BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E2061114FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1")), // G
+ n, h);
+ }
+ };
+ static X9ECParametersHolder brainpoolP320t1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger n = new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", 16);
+ BigInteger h = new BigInteger("01", 16);
+
+ 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'
+ n, h));
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("04925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED5263BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3")), // G'
+ n, h);
+ }
+ };
+ static X9ECParametersHolder brainpoolP384r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger n = new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 16);
+ BigInteger h = new BigInteger("01", 16);
+
+ ECCurve curve = configureCurve(new ECCurve.Fp(
+ new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", 16), // q
+ new BigInteger("7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", 16), // a
+ new BigInteger("4A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", 16), // b
+ n, h));
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("041D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315")), // G
+ n, h);
+ }
+ };
+ static X9ECParametersHolder brainpoolP384t1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger n = new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 16);
+ BigInteger h = new BigInteger("01", 16);
+
+ 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'
+ n, h));
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("0418DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928")), // G'
+ n, h);
+ }
+ };
+ static X9ECParametersHolder brainpoolP512r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger n = new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 16);
+ BigInteger h = new BigInteger("01", 16);
+
+ ECCurve curve = configureCurve(new ECCurve.Fp(
+ new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", 16), // q
+ new BigInteger("7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", 16), // a
+ new BigInteger("3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", 16), // b
+ n, h));
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("0481AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F8227DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892")), // G
+ n, h);
+ }
+ };
+ static X9ECParametersHolder brainpoolP512t1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger n = new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 16);
+ BigInteger h = new BigInteger("01", 16);
+
+ 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'
+ n, h));
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("04640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332")), // G'
+ n, h);
+ }
+ };
+
+ static final Hashtable objIds = new Hashtable();
+ static final Hashtable curves = new Hashtable();
+ static final Hashtable names = new Hashtable();
+
+ static void defineCurve(String name, ASN1ObjectIdentifier oid, X9ECParametersHolder holder)
+ {
+ objIds.put(name, oid);
+ names.put(oid, name);
+ curves.put(oid, holder);
+ }
+
+ static
+ {
+ defineCurve("brainpoolp160r1", TeleTrusTObjectIdentifiers.brainpoolP160r1, brainpoolP160r1);
+ defineCurve("brainpoolp160t1", TeleTrusTObjectIdentifiers.brainpoolP160t1, brainpoolP160t1);
+ defineCurve("brainpoolp192r1", TeleTrusTObjectIdentifiers.brainpoolP192r1, brainpoolP192r1);
+ defineCurve("brainpoolp192t1", TeleTrusTObjectIdentifiers.brainpoolP192t1, brainpoolP192t1);
+ defineCurve("brainpoolp224r1", TeleTrusTObjectIdentifiers.brainpoolP224r1, brainpoolP224r1);
+ defineCurve("brainpoolp224t1", TeleTrusTObjectIdentifiers.brainpoolP224t1, brainpoolP224t1);
+ defineCurve("brainpoolp256r1", TeleTrusTObjectIdentifiers.brainpoolP256r1, brainpoolP256r1);
+ defineCurve("brainpoolp256t1", TeleTrusTObjectIdentifiers.brainpoolP256t1, brainpoolP256t1);
+ defineCurve("brainpoolp320r1", TeleTrusTObjectIdentifiers.brainpoolP320r1, brainpoolP320r1);
+ defineCurve("brainpoolp320t1", TeleTrusTObjectIdentifiers.brainpoolP320t1, brainpoolP320t1);
+ defineCurve("brainpoolp384r1", TeleTrusTObjectIdentifiers.brainpoolP384r1, brainpoolP384r1);
+ defineCurve("brainpoolp384t1", TeleTrusTObjectIdentifiers.brainpoolP384t1, brainpoolP384t1);
+ defineCurve("brainpoolp512r1", TeleTrusTObjectIdentifiers.brainpoolP512r1, brainpoolP512r1);
+ defineCurve("brainpoolp512t1", TeleTrusTObjectIdentifiers.brainpoolP512t1, brainpoolP512t1);
+ }
+
+ public static X9ECParameters getByName(
+ String name)
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)objIds.get(Strings.toLowerCase(name));
+
+ if (oid != null)
+ {
+ return getByOID(oid);
+ }
+
+ return null;
+ }
+
+ /**
+ * return the X9ECParameters object for the named curve represented by
+ * the passed in object identifier. Null if the curve isn't present.
+ *
+ * @param oid an object identifier representing a named curve, if present.
+ */
+ public static X9ECParameters getByOID(
+ ASN1ObjectIdentifier oid)
+ {
+ X9ECParametersHolder holder = (X9ECParametersHolder)curves.get(oid);
+
+ if (holder != null)
+ {
+ return holder.getParameters();
+ }
+
+ return null;
+ }
+
+ /**
+ * return the object identifier signified by the passed in name. Null
+ * if there is no object identifier associated with name.
+ *
+ * @return the object identifier associated with name, if present.
+ */
+ public static ASN1ObjectIdentifier getOID(
+ String name)
+ {
+ return (ASN1ObjectIdentifier)objIds.get(Strings.toLowerCase(name));
+ }
+
+ /**
+ * return the named curve name represented by the given object identifier.
+ */
+ public static String getName(
+ ASN1ObjectIdentifier oid)
+ {
+ return (String)names.get(oid);
+ }
+
+ /**
+ * returns an enumeration containing the name strings for curves
+ * contained in this structure.
+ */
+ public static Enumeration getNames()
+ {
+ return objIds.keys();
+ }
+
+ public static ASN1ObjectIdentifier getOID(short curvesize, boolean twisted)
+ {
+ return getOID("brainpoolP" + curvesize + (twisted ? "t" : "r") + "1");
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java
new file mode 100644
index 00000000..1876000e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java
@@ -0,0 +1,75 @@
+package org.spongycastle.asn1.teletrust;
+
+import org.spongycastle.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");
+
+ /** 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");
+
+ /** 1.3.36.3.3.2 */
+ static final ASN1ObjectIdentifier ecSign = teleTrusTAlgorithm.branch("3.2");
+
+ /** 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.1 */
+ static final ASN1ObjectIdentifier versionOne = ellipticCurve.branch("1");
+
+ /** 1.3.36.3.3.2.8.1.1.1 */
+ static final ASN1ObjectIdentifier brainpoolP160r1 = versionOne.branch("1");
+ /** 1.3.36.3.3.2.8.1.1.2 */
+ static final ASN1ObjectIdentifier brainpoolP160t1 = versionOne.branch("2");
+ /** 1.3.36.3.3.2.8.1.1.3 */
+ static final ASN1ObjectIdentifier brainpoolP192r1 = versionOne.branch("3");
+ /** 1.3.36.3.3.2.8.1.1.4 */
+ static final ASN1ObjectIdentifier brainpoolP192t1 = versionOne.branch("4");
+ /** 1.3.36.3.3.2.8.1.1.5 */
+ static final ASN1ObjectIdentifier brainpoolP224r1 = versionOne.branch("5");
+ /** 1.3.36.3.3.2.8.1.1.6 */
+ static final ASN1ObjectIdentifier brainpoolP224t1 = versionOne.branch("6");
+ /** 1.3.36.3.3.2.8.1.1.7 */
+ static final ASN1ObjectIdentifier brainpoolP256r1 = versionOne.branch("7");
+ /** 1.3.36.3.3.2.8.1.1.8 */
+ static final ASN1ObjectIdentifier brainpoolP256t1 = versionOne.branch("8");
+ /** 1.3.36.3.3.2.8.1.1.9 */
+ static final ASN1ObjectIdentifier brainpoolP320r1 = versionOne.branch("9");
+ /** 1.3.36.3.3.2.8.1.1.10 */
+ static final ASN1ObjectIdentifier brainpoolP320t1 = versionOne.branch("10");
+ /** 1.3.36.3.3.2.8.1.1.11 */
+ static final ASN1ObjectIdentifier brainpoolP384r1 = versionOne.branch("11");
+ /** 1.3.36.3.3.2.8.1.1.12 */
+ static final ASN1ObjectIdentifier brainpoolP384t1 = versionOne.branch("12");
+ /** 1.3.36.3.3.2.8.1.1.13 */
+ static final ASN1ObjectIdentifier brainpoolP512r1 = versionOne.branch("13");
+ /** 1.3.36.3.3.2.8.1.1.14 */
+ static final ASN1ObjectIdentifier brainpoolP512t1 = versionOne.branch("14");
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/tsp/Accuracy.java b/core/src/main/java/org/spongycastle/asn1/tsp/Accuracy.java
new file mode 100644
index 00000000..910d22c1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/tsp/Accuracy.java
@@ -0,0 +1,173 @@
+package org.spongycastle.asn1.tsp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+
+public class Accuracy
+ extends ASN1Object
+{
+ ASN1Integer seconds;
+
+ ASN1Integer millis;
+
+ ASN1Integer micros;
+
+ // constantes
+ protected static final int MIN_MILLIS = 1;
+
+ protected static final int MAX_MILLIS = 999;
+
+ protected static final int MIN_MICROS = 1;
+
+ protected static final int MAX_MICROS = 999;
+
+ protected Accuracy()
+ {
+ }
+
+ public Accuracy(
+ ASN1Integer seconds,
+ ASN1Integer millis,
+ ASN1Integer micros)
+ {
+ this.seconds = seconds;
+
+ //Verifications
+ if (millis != null
+ && (millis.getValue().intValue() < MIN_MILLIS || millis
+ .getValue().intValue() > MAX_MILLIS))
+ {
+ throw new IllegalArgumentException(
+ "Invalid millis field : not in (1..999)");
+ }
+ else
+ {
+ this.millis = millis;
+ }
+
+ if (micros != null
+ && (micros.getValue().intValue() < MIN_MICROS || micros
+ .getValue().intValue() > MAX_MICROS))
+ {
+ throw new IllegalArgumentException(
+ "Invalid micros field : not in (1..999)");
+ }
+ else
+ {
+ this.micros = micros;
+ }
+
+ }
+
+ private Accuracy(ASN1Sequence seq)
+ {
+ seconds = null;
+ millis = null;
+ micros = null;
+
+ for (int i = 0; i < seq.size(); i++)
+ {
+ // seconds
+ if (seq.getObjectAt(i) instanceof ASN1Integer)
+ {
+ seconds = (ASN1Integer) seq.getObjectAt(i);
+ }
+ else if (seq.getObjectAt(i) instanceof DERTaggedObject)
+ {
+ DERTaggedObject extra = (DERTaggedObject) seq.getObjectAt(i);
+
+ switch (extra.getTagNo())
+ {
+ case 0:
+ millis = ASN1Integer.getInstance(extra, false);
+ if (millis.getValue().intValue() < MIN_MILLIS
+ || millis.getValue().intValue() > MAX_MILLIS)
+ {
+ throw new IllegalArgumentException(
+ "Invalid millis field : not in (1..999).");
+ }
+ break;
+ case 1:
+ micros = ASN1Integer.getInstance(extra, false);
+ if (micros.getValue().intValue() < MIN_MICROS
+ || micros.getValue().intValue() > MAX_MICROS)
+ {
+ throw new IllegalArgumentException(
+ "Invalid micros field : not in (1..999).");
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Invalig tag number");
+ }
+ }
+ }
+ }
+
+ public static Accuracy getInstance(Object o)
+ {
+ if (o instanceof Accuracy)
+ {
+ return (Accuracy) o;
+ }
+
+ if (o != null)
+ {
+ return new Accuracy(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer getSeconds()
+ {
+ return seconds;
+ }
+
+ public ASN1Integer getMillis()
+ {
+ return millis;
+ }
+
+ public ASN1Integer getMicros()
+ {
+ return micros;
+ }
+
+ /**
+ * <pre>
+ * Accuracy ::= SEQUENCE {
+ * seconds INTEGER OPTIONAL,
+ * millis [0] INTEGER (1..999) OPTIONAL,
+ * micros [1] INTEGER (1..999) OPTIONAL
+ * }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (seconds != null)
+ {
+ v.add(seconds);
+ }
+
+ if (millis != null)
+ {
+ v.add(new DERTaggedObject(false, 0, millis));
+ }
+
+ if (micros != null)
+ {
+ v.add(new DERTaggedObject(false, 1, micros));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/tsp/MessageImprint.java b/core/src/main/java/org/spongycastle/asn1/tsp/MessageImprint.java
new file mode 100644
index 00000000..05830447
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/tsp/MessageImprint.java
@@ -0,0 +1,78 @@
+package org.spongycastle.asn1.tsp;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+public class MessageImprint
+ extends ASN1Object
+{
+ AlgorithmIdentifier hashAlgorithm;
+ byte[] hashedMessage;
+
+ /**
+ * @param o
+ * @return a MessageImprint object.
+ */
+ public static MessageImprint getInstance(Object o)
+ {
+ if (o instanceof MessageImprint)
+ {
+ return (MessageImprint)o;
+ }
+
+ if (o != null)
+ {
+ return new MessageImprint(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ private MessageImprint(
+ ASN1Sequence seq)
+ {
+ this.hashAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(0));
+ this.hashedMessage = ASN1OctetString.getInstance(seq.getObjectAt(1)).getOctets();
+ }
+
+ public MessageImprint(
+ AlgorithmIdentifier hashAlgorithm,
+ byte[] hashedMessage)
+ {
+ this.hashAlgorithm = hashAlgorithm;
+ this.hashedMessage = hashedMessage;
+ }
+
+ public AlgorithmIdentifier getHashAlgorithm()
+ {
+ return hashAlgorithm;
+ }
+
+ public byte[] getHashedMessage()
+ {
+ return hashedMessage;
+ }
+
+ /**
+ * <pre>
+ * MessageImprint ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * hashedMessage OCTET STRING }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(hashAlgorithm);
+ v.add(new DEROctetString(hashedMessage));
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/tsp/TSTInfo.java b/core/src/main/java/org/spongycastle/asn1/tsp/TSTInfo.java
new file mode 100644
index 00000000..71587414
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/tsp/TSTInfo.java
@@ -0,0 +1,233 @@
+package org.spongycastle.asn1.tsp;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Boolean;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.Extensions;
+import org.spongycastle.asn1.x509.GeneralName;
+
+public class TSTInfo
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private ASN1ObjectIdentifier tsaPolicyId;
+ private MessageImprint messageImprint;
+ private ASN1Integer serialNumber;
+ private ASN1GeneralizedTime genTime;
+ private Accuracy accuracy;
+ private ASN1Boolean ordering;
+ private ASN1Integer nonce;
+ private GeneralName tsa;
+ private Extensions extensions;
+
+ public static TSTInfo getInstance(Object o)
+ {
+ if (o instanceof TSTInfo)
+ {
+ return (TSTInfo)o;
+ }
+ else if (o != null)
+ {
+ return new TSTInfo(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ private TSTInfo(ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ // version
+ version = ASN1Integer.getInstance(e.nextElement());
+
+ // tsaPolicy
+ tsaPolicyId = ASN1ObjectIdentifier.getInstance(e.nextElement());
+
+ // messageImprint
+ messageImprint = MessageImprint.getInstance(e.nextElement());
+
+ // serialNumber
+ serialNumber = ASN1Integer.getInstance(e.nextElement());
+
+ // genTime
+ genTime = ASN1GeneralizedTime.getInstance(e.nextElement());
+
+ // default for ordering
+ ordering = ASN1Boolean.getInstance(false);
+
+ while (e.hasMoreElements())
+ {
+ ASN1Object o = (ASN1Object) e.nextElement();
+
+ if (o instanceof ASN1TaggedObject)
+ {
+ DERTaggedObject tagged = (DERTaggedObject) o;
+
+ switch (tagged.getTagNo())
+ {
+ case 0:
+ tsa = GeneralName.getInstance(tagged, true);
+ break;
+ case 1:
+ extensions = Extensions.getInstance(tagged, false);
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown tag value " + tagged.getTagNo());
+ }
+ }
+ else if (o instanceof ASN1Sequence || o instanceof Accuracy)
+ {
+ accuracy = Accuracy.getInstance(o);
+ }
+ else if (o instanceof ASN1Boolean)
+ {
+ ordering = ASN1Boolean.getInstance(o);
+ }
+ else if (o instanceof ASN1Integer)
+ {
+ nonce = ASN1Integer.getInstance(o);
+ }
+
+ }
+ }
+
+ public TSTInfo(ASN1ObjectIdentifier tsaPolicyId, MessageImprint messageImprint,
+ ASN1Integer serialNumber, ASN1GeneralizedTime genTime,
+ Accuracy accuracy, ASN1Boolean ordering, ASN1Integer nonce,
+ GeneralName tsa, Extensions extensions)
+ {
+ version = new ASN1Integer(1);
+ this.tsaPolicyId = tsaPolicyId;
+ this.messageImprint = messageImprint;
+ this.serialNumber = serialNumber;
+ this.genTime = genTime;
+
+ this.accuracy = accuracy;
+ this.ordering = ordering;
+ this.nonce = nonce;
+ this.tsa = tsa;
+ this.extensions = extensions;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public MessageImprint getMessageImprint()
+ {
+ return messageImprint;
+ }
+
+ public ASN1ObjectIdentifier getPolicy()
+ {
+ return tsaPolicyId;
+ }
+
+ public ASN1Integer getSerialNumber()
+ {
+ return serialNumber;
+ }
+
+ public Accuracy getAccuracy()
+ {
+ return accuracy;
+ }
+
+ public ASN1GeneralizedTime getGenTime()
+ {
+ return genTime;
+ }
+
+ public ASN1Boolean getOrdering()
+ {
+ return ordering;
+ }
+
+ public ASN1Integer getNonce()
+ {
+ return nonce;
+ }
+
+ public GeneralName getTsa()
+ {
+ return tsa;
+ }
+
+ public Extensions getExtensions()
+ {
+ return extensions;
+ }
+
+ /**
+ * <pre>
+ *
+ * TSTInfo ::= SEQUENCE {
+ * version INTEGER { v1(1) },
+ * policy TSAPolicyId,
+ * messageImprint MessageImprint,
+ * -- MUST have the same value as the similar field in
+ * -- TimeStampReq
+ * serialNumber INTEGER,
+ * -- Time-Stamping users MUST be ready to accommodate integers
+ * -- up to 160 bits.
+ * genTime GeneralizedTime,
+ * accuracy Accuracy OPTIONAL,
+ * ordering BOOLEAN DEFAULT FALSE,
+ * nonce INTEGER OPTIONAL,
+ * -- MUST be present if the similar field was present
+ * -- in TimeStampReq. In that case it MUST have the same value.
+ * tsa [0] GeneralName OPTIONAL,
+ * extensions [1] IMPLICIT Extensions OPTIONAL }
+ *
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector seq = new ASN1EncodableVector();
+ seq.add(version);
+
+ seq.add(tsaPolicyId);
+ seq.add(messageImprint);
+ seq.add(serialNumber);
+ seq.add(genTime);
+
+ if (accuracy != null)
+ {
+ seq.add(accuracy);
+ }
+
+ if (ordering != null && ordering.isTrue())
+ {
+ seq.add(ordering);
+ }
+
+ if (nonce != null)
+ {
+ seq.add(nonce);
+ }
+
+ if (tsa != null)
+ {
+ seq.add(new DERTaggedObject(true, 0, tsa));
+ }
+
+ if (extensions != null)
+ {
+ seq.add(new DERTaggedObject(false, 1, extensions));
+ }
+
+ return new DERSequence(seq);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/tsp/TimeStampReq.java b/core/src/main/java/org/spongycastle/asn1/tsp/TimeStampReq.java
new file mode 100644
index 00000000..f88ed2b7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/tsp/TimeStampReq.java
@@ -0,0 +1,179 @@
+package org.spongycastle.asn1.tsp;
+
+import org.spongycastle.asn1.ASN1Boolean;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.Extensions;
+
+public class TimeStampReq
+ extends ASN1Object
+{
+ ASN1Integer version;
+
+ MessageImprint messageImprint;
+
+ ASN1ObjectIdentifier tsaPolicy;
+
+ ASN1Integer nonce;
+
+ ASN1Boolean certReq;
+
+ Extensions extensions;
+
+ public static TimeStampReq getInstance(Object o)
+ {
+ if (o instanceof TimeStampReq)
+ {
+ return (TimeStampReq) o;
+ }
+ else if (o != null)
+ {
+ return new TimeStampReq(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ private TimeStampReq(ASN1Sequence seq)
+ {
+ int nbObjects = seq.size();
+
+ int seqStart = 0;
+
+ // version
+ version = ASN1Integer.getInstance(seq.getObjectAt(seqStart));
+
+ seqStart++;
+
+ // messageImprint
+ messageImprint = MessageImprint.getInstance(seq.getObjectAt(seqStart));
+
+ seqStart++;
+
+ for (int opt = seqStart; opt < nbObjects; opt++)
+ {
+ // tsaPolicy
+ if (seq.getObjectAt(opt) instanceof ASN1ObjectIdentifier)
+ {
+ tsaPolicy = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(opt));
+ }
+ // nonce
+ else if (seq.getObjectAt(opt) instanceof ASN1Integer)
+ {
+ nonce = ASN1Integer.getInstance(seq.getObjectAt(opt));
+ }
+ // certReq
+ else if (seq.getObjectAt(opt) instanceof ASN1Boolean)
+ {
+ certReq = ASN1Boolean.getInstance(seq.getObjectAt(opt));
+ }
+ // extensions
+ else if (seq.getObjectAt(opt) instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tagged = (ASN1TaggedObject)seq.getObjectAt(opt);
+ if (tagged.getTagNo() == 0)
+ {
+ extensions = Extensions.getInstance(tagged, false);
+ }
+ }
+ }
+ }
+
+ public TimeStampReq(
+ MessageImprint messageImprint,
+ ASN1ObjectIdentifier tsaPolicy,
+ ASN1Integer nonce,
+ ASN1Boolean certReq,
+ Extensions extensions)
+ {
+ // default
+ version = new ASN1Integer(1);
+
+ this.messageImprint = messageImprint;
+ this.tsaPolicy = tsaPolicy;
+ this.nonce = nonce;
+ this.certReq = certReq;
+ this.extensions = extensions;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public MessageImprint getMessageImprint()
+ {
+ return messageImprint;
+ }
+
+ public ASN1ObjectIdentifier getReqPolicy()
+ {
+ return tsaPolicy;
+ }
+
+ public ASN1Integer getNonce()
+ {
+ return nonce;
+ }
+
+ public ASN1Boolean getCertReq()
+ {
+ return certReq;
+ }
+
+ public Extensions getExtensions()
+ {
+ return extensions;
+ }
+
+ /**
+ * <pre>
+ * TimeStampReq ::= SEQUENCE {
+ * version INTEGER { v1(1) },
+ * messageImprint MessageImprint,
+ * --a hash algorithm OID and the hash value of the data to be
+ * --time-stamped
+ * reqPolicy TSAPolicyId OPTIONAL,
+ * nonce INTEGER OPTIONAL,
+ * certReq BOOLEAN DEFAULT FALSE,
+ * extensions [0] IMPLICIT Extensions OPTIONAL
+ * }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(messageImprint);
+
+ if (tsaPolicy != null)
+ {
+ v.add(tsaPolicy);
+ }
+
+ if (nonce != null)
+ {
+ v.add(nonce);
+ }
+
+ if (certReq != null && certReq.isTrue())
+ {
+ v.add(certReq);
+ }
+
+ if (extensions != null)
+ {
+ v.add(new DERTaggedObject(false, 0, extensions));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/tsp/TimeStampResp.java b/core/src/main/java/org/spongycastle/asn1/tsp/TimeStampResp.java
new file mode 100644
index 00000000..eb73e068
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/tsp/TimeStampResp.java
@@ -0,0 +1,84 @@
+package org.spongycastle.asn1.tsp;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.cmp.PKIStatusInfo;
+import org.spongycastle.asn1.cms.ContentInfo;
+
+
+public class TimeStampResp
+ extends ASN1Object
+{
+ PKIStatusInfo pkiStatusInfo;
+
+ ContentInfo timeStampToken;
+
+ public static TimeStampResp getInstance(Object o)
+ {
+ if (o instanceof TimeStampResp)
+ {
+ return (TimeStampResp) o;
+ }
+ else if (o != null)
+ {
+ return new TimeStampResp(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ private TimeStampResp(ASN1Sequence seq)
+ {
+
+ Enumeration e = seq.getObjects();
+
+ // status
+ pkiStatusInfo = PKIStatusInfo.getInstance(e.nextElement());
+
+ if (e.hasMoreElements())
+ {
+ timeStampToken = ContentInfo.getInstance(e.nextElement());
+ }
+ }
+
+ public TimeStampResp(PKIStatusInfo pkiStatusInfo, ContentInfo timeStampToken)
+ {
+ this.pkiStatusInfo = pkiStatusInfo;
+ this.timeStampToken = timeStampToken;
+ }
+
+ public PKIStatusInfo getStatus()
+ {
+ return pkiStatusInfo;
+ }
+
+ public ContentInfo getTimeStampToken()
+ {
+ return timeStampToken;
+ }
+
+ /**
+ * <pre>
+ * TimeStampResp ::= SEQUENCE {
+ * status PKIStatusInfo,
+ * timeStampToken TimeStampToken OPTIONAL }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(pkiStatusInfo);
+ if (timeStampToken != null)
+ {
+ v.add(timeStampToken);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145BinaryField.java b/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145BinaryField.java
new file mode 100644
index 00000000..4cd53870
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145BinaryField.java
@@ -0,0 +1,119 @@
+package org.spongycastle.asn1.ua;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class DSTU4145BinaryField
+ extends ASN1Object
+{
+
+ private int m, k, j, l;
+
+ private DSTU4145BinaryField(ASN1Sequence seq)
+ {
+ m = ASN1Integer.getInstance(seq.getObjectAt(0)).getPositiveValue().intValue();
+
+ if (seq.getObjectAt(1) instanceof ASN1Integer)
+ {
+ k = ((ASN1Integer)seq.getObjectAt(1)).getPositiveValue().intValue();
+ }
+ else if (seq.getObjectAt(1) instanceof ASN1Sequence)
+ {
+ ASN1Sequence coefs = ASN1Sequence.getInstance(seq.getObjectAt(1));
+
+ k = ASN1Integer.getInstance(coefs.getObjectAt(0)).getPositiveValue().intValue();
+ j = ASN1Integer.getInstance(coefs.getObjectAt(1)).getPositiveValue().intValue();
+ l = ASN1Integer.getInstance(coefs.getObjectAt(2)).getPositiveValue().intValue();
+ }
+ else
+ {
+ throw new IllegalArgumentException("object parse error");
+ }
+ }
+
+ public static DSTU4145BinaryField getInstance(Object obj)
+ {
+ if (obj instanceof DSTU4145BinaryField)
+ {
+ return (DSTU4145BinaryField)obj;
+ }
+
+ if (obj != null)
+ {
+ return new DSTU4145BinaryField(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public DSTU4145BinaryField(int m, int k1, int k2, int k3)
+ {
+ this.m = m;
+ this.k = k1;
+ this.j = k2;
+ this.l = k3;
+ }
+
+ public int getM()
+ {
+ return m;
+ }
+
+ public int getK1()
+ {
+ return k;
+ }
+
+ public int getK2()
+ {
+ return j;
+ }
+
+ public int getK3()
+ {
+ return l;
+ }
+
+ public DSTU4145BinaryField(int m, int k)
+ {
+ this(m, k, 0, 0);
+ }
+
+ /**
+ * BinaryField ::= SEQUENCE {
+ * M INTEGER,
+ * CHOICE {Trinomial, Pentanomial}
+ * Trinomial::= INTEGER
+ * Pentanomial::= SEQUENCE {
+ * k INTEGER,
+ * j INTEGER,
+ * l INTEGER}
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(m));
+ if (j == 0) //Trinomial
+ {
+ v.add(new ASN1Integer(k));
+ }
+ else
+ {
+ ASN1EncodableVector coefs = new ASN1EncodableVector();
+ coefs.add(new ASN1Integer(k));
+ coefs.add(new ASN1Integer(j));
+ coefs.add(new ASN1Integer(l));
+
+ v.add(new DERSequence(coefs));
+ }
+
+ return new DERSequence(v);
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145ECBinary.java b/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145ECBinary.java
new file mode 100644
index 00000000..bd2d9add
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145ECBinary.java
@@ -0,0 +1,154 @@
+package org.spongycastle.asn1.ua;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.math.ec.ECAlgorithms;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.field.PolynomialExtensionField;
+import org.spongycastle.util.Arrays;
+
+public class DSTU4145ECBinary
+ extends ASN1Object
+{
+ BigInteger version = BigInteger.valueOf(0);
+
+ DSTU4145BinaryField f;
+ ASN1Integer a;
+ ASN1OctetString b;
+ ASN1Integer n;
+ ASN1OctetString bp;
+
+ public DSTU4145ECBinary(ECDomainParameters params)
+ {
+ ECCurve curve = params.getCurve();
+ if (!ECAlgorithms.isF2mCurve(curve))
+ {
+ throw new IllegalArgumentException("only binary domain is possible");
+ }
+
+ // We always use big-endian in parameter encoding
+
+ PolynomialExtensionField field = (PolynomialExtensionField)curve.getField();
+ int[] exponents = field.getMinimalPolynomial().getExponentsPresent();
+ if (exponents.length == 3)
+ {
+ f = new DSTU4145BinaryField(exponents[2], exponents[1]);
+ }
+ else if (exponents.length == 5)
+ {
+ f = new DSTU4145BinaryField(exponents[4], exponents[1], exponents[2], exponents[3]);
+ }
+
+ a = new ASN1Integer(curve.getA().toBigInteger());
+ b = new DEROctetString(curve.getB().getEncoded());
+ n = new ASN1Integer(params.getN());
+ bp = new DEROctetString(DSTU4145PointEncoder.encodePoint(params.getG()));
+ }
+
+ private DSTU4145ECBinary(ASN1Sequence seq)
+ {
+ int index = 0;
+
+ if (seq.getObjectAt(index) instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject taggedVersion = (ASN1TaggedObject)seq.getObjectAt(index);
+ if (taggedVersion.isExplicit() && 0 == taggedVersion.getTagNo())
+ {
+ version = ASN1Integer.getInstance(taggedVersion.getLoadedObject()).getValue();
+ index++;
+ }
+ else
+ {
+ throw new IllegalArgumentException("object parse error");
+ }
+ }
+ f = DSTU4145BinaryField.getInstance(seq.getObjectAt(index));
+ index++;
+ a = ASN1Integer.getInstance(seq.getObjectAt(index));
+ index++;
+ b = ASN1OctetString.getInstance(seq.getObjectAt(index));
+ index++;
+ n = ASN1Integer.getInstance(seq.getObjectAt(index));
+ index++;
+ bp = ASN1OctetString.getInstance(seq.getObjectAt(index));
+ }
+
+ public static DSTU4145ECBinary getInstance(Object obj)
+ {
+ if (obj instanceof DSTU4145ECBinary)
+ {
+ return (DSTU4145ECBinary)obj;
+ }
+
+ if (obj != null)
+ {
+ return new DSTU4145ECBinary(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public DSTU4145BinaryField getField()
+ {
+ return f;
+ }
+
+ public BigInteger getA()
+ {
+ return a.getValue();
+ }
+
+ public byte[] getB()
+ {
+ return Arrays.clone(b.getOctets());
+ }
+
+ public BigInteger getN()
+ {
+ return n.getValue();
+ }
+
+ public byte[] getG()
+ {
+ return Arrays.clone(bp.getOctets());
+ }
+
+ /**
+ * ECBinary ::= SEQUENCE {
+ * version [0] EXPLICIT INTEGER DEFAULT 0,
+ * f BinaryField,
+ * a INTEGER (0..1),
+ * b OCTET STRING,
+ * n INTEGER,
+ * bp OCTET STRING}
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (0 != version.compareTo(BigInteger.valueOf(0)))
+ {
+ v.add(new DERTaggedObject(true, 0, new ASN1Integer(version)));
+ }
+ v.add(f);
+ v.add(a);
+ v.add(b);
+ v.add(n);
+ v.add(bp);
+
+ return new DERSequence(v);
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145NamedCurves.java b/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145NamedCurves.java
new file mode 100644
index 00000000..252c4404
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145NamedCurves.java
@@ -0,0 +1,106 @@
+package org.spongycastle.asn1.ua;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECPoint;
+
+public class DSTU4145NamedCurves
+{
+ private static final BigInteger ZERO = BigInteger.valueOf(0);
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ public static final ECDomainParameters[] params = new ECDomainParameters[10];
+ static final ASN1ObjectIdentifier[] oids = new ASN1ObjectIdentifier[10];
+
+ //All named curves have the following oid format: 1.2.804.2.1.1.1.1.3.1.1.2.X
+ //where X is the curve number 0-9
+ static final String oidBase = UAObjectIdentifiers.dstu4145le.getId() + ".2.";
+
+ static
+ {
+ BigInteger[] n_s = new BigInteger[10];
+ n_s[0] = new BigInteger("400000000000000000002BEC12BE2262D39BCF14D", 16);
+ n_s[1] = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFB12EBCC7D7F29FF7701F", 16);
+ n_s[2] = new BigInteger("800000000000000000000189B4E67606E3825BB2831", 16);
+ n_s[3] = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFFB981960435FE5AB64236EF", 16);
+ n_s[4] = new BigInteger("40000000000000000000000069A779CAC1DABC6788F7474F", 16);
+ n_s[5] = new BigInteger("1000000000000000000000000000013E974E72F8A6922031D2603CFE0D7", 16);
+ n_s[6] = new BigInteger("800000000000000000000000000000006759213AF182E987D3E17714907D470D", 16);
+ n_s[7] = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC079C2F3825DA70D390FBBA588D4604022B7B7", 16);
+ n_s[8] = new BigInteger("40000000000000000000000000000000000000000000009C300B75A3FA824F22428FD28CE8812245EF44049B2D49", 16);
+ n_s[9] = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBA3175458009A8C0A724F02F81AA8A1FCBAF80D90C7A95110504CF", 16);
+
+ BigInteger[] h_s = new BigInteger[10];
+ h_s[0] = BigInteger.valueOf(2);
+ h_s[1] = BigInteger.valueOf(2);
+ h_s[2] = BigInteger.valueOf(4);
+ h_s[3] = BigInteger.valueOf(2);
+ h_s[4] = BigInteger.valueOf(2);
+ h_s[5] = BigInteger.valueOf(2);
+ h_s[6] = BigInteger.valueOf(4);
+ h_s[7] = BigInteger.valueOf(2);
+ h_s[8] = BigInteger.valueOf(2);
+ h_s[9] = BigInteger.valueOf(2);
+
+ ECCurve.F2m[] curves = new ECCurve.F2m[10];
+ curves[0] = new ECCurve.F2m(163, 3, 6, 7, ONE, new BigInteger("5FF6108462A2DC8210AB403925E638A19C1455D21", 16), n_s[0], h_s[0]);
+ curves[1] = new ECCurve.F2m(167, 6, ONE, new BigInteger("6EE3CEEB230811759F20518A0930F1A4315A827DAC", 16), n_s[1], h_s[1]);
+ curves[2] = new ECCurve.F2m(173, 1, 2, 10, ZERO, new BigInteger("108576C80499DB2FC16EDDF6853BBB278F6B6FB437D9", 16), n_s[2], h_s[2]);
+ curves[3] = new ECCurve.F2m(179, 1, 2, 4, ONE, new BigInteger("4A6E0856526436F2F88DD07A341E32D04184572BEB710", 16), n_s[3], h_s[3]);
+ curves[4] = new ECCurve.F2m(191, 9, ONE, new BigInteger("7BC86E2102902EC4D5890E8B6B4981ff27E0482750FEFC03", 16), n_s[4], h_s[4]);
+ curves[5] = new ECCurve.F2m(233, 1, 4, 9, ONE, new BigInteger("06973B15095675534C7CF7E64A21BD54EF5DD3B8A0326AA936ECE454D2C", 16), n_s[5], h_s[5]);
+ curves[6] = new ECCurve.F2m(257, 12, ZERO, new BigInteger("1CEF494720115657E18F938D7A7942394FF9425C1458C57861F9EEA6ADBE3BE10", 16), n_s[6], h_s[6]);
+ curves[7] = new ECCurve.F2m(307, 2, 4, 8, ONE, new BigInteger("393C7F7D53666B5054B5E6C6D3DE94F4296C0C599E2E2E241050DF18B6090BDC90186904968BB", 16), n_s[7], h_s[7]);
+ curves[8] = new ECCurve.F2m(367, 21, ONE, new BigInteger("43FC8AD242B0B7A6F3D1627AD5654447556B47BF6AA4A64B0C2AFE42CADAB8F93D92394C79A79755437B56995136", 16), n_s[8], h_s[8]);
+ curves[9] = new ECCurve.F2m(431, 1, 3, 5, ONE, new BigInteger("03CE10490F6A708FC26DFE8C3D27C4F94E690134D5BFF988D8D28AAEAEDE975936C66BAC536B18AE2DC312CA493117DAA469C640CAF3", 16), n_s[9], h_s[9]);
+
+ ECPoint[] points = new ECPoint[10];
+ 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));
+
+ for (int i = 0; i < params.length; i++)
+ {
+ params[i] = new ECDomainParameters(curves[i], points[i], n_s[i], h_s[i]);
+ }
+
+ for (int i = 0; i < oids.length; i++)
+ {
+ oids[i] = new ASN1ObjectIdentifier(oidBase + i);
+ }
+ }
+
+ /**
+ * All named curves have the following oid format: 1.2.804.2.1.1.1.1.3.1.1.2.X
+ * where X is the curve number 0-9
+ */
+ public static ASN1ObjectIdentifier[] getOIDs()
+ {
+ return oids;
+ }
+
+ /**
+ * All named curves have the following oid format: 1.2.804.2.1.1.1.1.3.1.1.2.X
+ * where X is the curve number 0-9
+ */
+ public static ECDomainParameters getByOID(ASN1ObjectIdentifier oid)
+ {
+ String oidStr = oid.getId();
+ if (oidStr.startsWith(oidBase))
+ {
+ int index = Integer.parseInt(oidStr.substring(oidStr.length() - 1));
+ return params[index];
+ }
+ return null;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145Params.java b/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145Params.java
new file mode 100644
index 00000000..d6c60f8b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145Params.java
@@ -0,0 +1,121 @@
+package org.spongycastle.asn1.ua;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+
+public class DSTU4145Params
+ extends ASN1Object
+{
+ private static final byte DEFAULT_DKE[] = {
+ (byte)0xa9, (byte)0xd6, (byte)0xeb, 0x45, (byte)0xf1, 0x3c, 0x70, (byte)0x82,
+ (byte)0x80, (byte)0xc4, (byte)0x96, 0x7b, 0x23, 0x1f, 0x5e, (byte)0xad,
+ (byte)0xf6, 0x58, (byte)0xeb, (byte)0xa4, (byte)0xc0, 0x37, 0x29, 0x1d,
+ 0x38, (byte)0xd9, 0x6b, (byte)0xf0, 0x25, (byte)0xca, 0x4e, 0x17,
+ (byte)0xf8, (byte)0xe9, 0x72, 0x0d, (byte)0xc6, 0x15, (byte)0xb4, 0x3a,
+ 0x28, (byte)0x97, 0x5f, 0x0b, (byte)0xc1, (byte)0xde, (byte)0xa3, 0x64,
+ 0x38, (byte)0xb5, 0x64, (byte)0xea, 0x2c, 0x17, (byte)0x9f, (byte)0xd0,
+ 0x12, 0x3e, 0x6d, (byte)0xb8, (byte)0xfa, (byte)0xc5, 0x79, 0x04};
+
+
+ private ASN1ObjectIdentifier namedCurve;
+ private DSTU4145ECBinary ecbinary;
+ private byte[] dke = DEFAULT_DKE;
+
+ public DSTU4145Params(ASN1ObjectIdentifier namedCurve)
+ {
+ this.namedCurve = namedCurve;
+ }
+
+ public DSTU4145Params(DSTU4145ECBinary ecbinary)
+ {
+ this.ecbinary = ecbinary;
+ }
+
+ public boolean isNamedCurve()
+ {
+ return namedCurve != null;
+ }
+
+ public DSTU4145ECBinary getECBinary()
+ {
+ return ecbinary;
+ }
+
+ public byte[] getDKE()
+ {
+ return dke;
+ }
+
+ public static byte[] getDefaultDKE()
+ {
+ return DEFAULT_DKE;
+ }
+
+ public ASN1ObjectIdentifier getNamedCurve()
+ {
+ return namedCurve;
+ }
+
+ public static DSTU4145Params getInstance(Object obj)
+ {
+ if (obj instanceof DSTU4145Params)
+ {
+ return (DSTU4145Params)obj;
+ }
+
+ if (obj != null)
+ {
+ ASN1Sequence seq = ASN1Sequence.getInstance(obj);
+ DSTU4145Params params;
+
+ if (seq.getObjectAt(0) instanceof ASN1ObjectIdentifier)
+ {
+ params = new DSTU4145Params(ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0)));
+ }
+ else
+ {
+ params = new DSTU4145Params(DSTU4145ECBinary.getInstance(seq.getObjectAt(0)));
+ }
+
+ if (seq.size() == 2)
+ {
+ params.dke = ASN1OctetString.getInstance(seq.getObjectAt(1)).getOctets();
+ if (params.dke.length != DSTU4145Params.DEFAULT_DKE.length)
+ {
+ throw new IllegalArgumentException("object parse error");
+ }
+ }
+
+ return params;
+ }
+
+ throw new IllegalArgumentException("object parse error");
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (namedCurve != null)
+ {
+ v.add(namedCurve);
+ }
+ else
+ {
+ v.add(ecbinary);
+ }
+
+ if (!org.spongycastle.util.Arrays.areEqual(dke, DEFAULT_DKE))
+ {
+ v.add(new DEROctetString(dke));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145PointEncoder.java b/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145PointEncoder.java
new file mode 100644
index 00000000..d43a58ae
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145PointEncoder.java
@@ -0,0 +1,154 @@
+package org.spongycastle.asn1.ua;
+
+import java.math.BigInteger;
+import java.util.Random;
+
+import org.spongycastle.math.ec.ECConstants;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+
+/**
+ * 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 ECFieldElement trace(ECFieldElement fe)
+ {
+ ECFieldElement t = fe;
+ for (int i = 1; i < fe.getFieldSize(); ++i)
+ {
+ t = t.square().add(fe);
+ }
+ return t;
+ }
+
+ /**
+ * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
+ * D.1.6) The other solution is <code>z + 1</code>.
+ *
+ * @param beta The value to solve the quadratic equation for.
+ * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+ * <code>null</code> if no solution exists.
+ */
+ private static ECFieldElement solveQuadraticEquation(ECCurve curve, ECFieldElement beta)
+ {
+ if (beta.isZero())
+ {
+ return beta;
+ }
+
+ ECFieldElement zeroElement = curve.fromBigInteger(ECConstants.ZERO);
+
+ ECFieldElement z = null;
+ ECFieldElement gamma = null;
+
+ Random rand = new Random();
+ int m = beta.getFieldSize();
+ do
+ {
+ ECFieldElement t = curve.fromBigInteger(new BigInteger(m, rand));
+ z = zeroElement;
+ ECFieldElement w = beta;
+ for (int i = 1; i <= m - 1; i++)
+ {
+ ECFieldElement w2 = w.square();
+ z = z.square().add(w2.multiply(t));
+ w = w2.add(beta);
+ }
+ if (!w.isZero())
+ {
+ return null;
+ }
+ gamma = z.square().add(z);
+ }
+ while (gamma.isZero());
+
+ return z;
+ }
+
+ public static byte[] encodePoint(ECPoint Q)
+ {
+ /*if (!Q.isCompressed())
+ Q=new ECPoint.F2m(Q.getCurve(),Q.getX(),Q.getY(),true);
+
+ byte[] bytes=Q.getEncoded();
+
+ if (bytes[0]==0x02)
+ bytes[bytes.length-1]&=0xFE;
+ else if (bytes[0]==0x02)
+ bytes[bytes.length-1]|=0x01;
+
+ return Arrays.copyOfRange(bytes, 1, bytes.length);*/
+
+ Q = Q.normalize();
+
+ ECFieldElement x = Q.getAffineXCoord();
+
+ byte[] bytes = x.getEncoded();
+
+ if (!x.isZero())
+ {
+ ECFieldElement z = Q.getAffineYCoord().divide(x);
+ if (trace(z).isOne())
+ {
+ bytes[bytes.length - 1] |= 0x01;
+ }
+ else
+ {
+ bytes[bytes.length - 1] &= 0xFE;
+ }
+ }
+
+ return bytes;
+ }
+
+ public static ECPoint decodePoint(ECCurve curve, byte[] bytes)
+ {
+ /*byte[] bp_enc=new byte[bytes.length+1];
+ if (0==(bytes[bytes.length-1]&0x1))
+ bp_enc[0]=0x02;
+ else
+ bp_enc[0]=0x03;
+ System.arraycopy(bytes, 0, bp_enc, 1, bytes.length);
+ if (!trace(curve.fromBigInteger(new BigInteger(1, bytes))).equals(curve.getA().toBigInteger()))
+ bp_enc[bp_enc.length-1]^=0x01;
+
+ return curve.decodePoint(bp_enc);*/
+
+ ECFieldElement k = curve.fromBigInteger(BigInteger.valueOf(bytes[bytes.length - 1] & 0x1));
+
+ ECFieldElement xp = curve.fromBigInteger(new BigInteger(1, bytes));
+ if (!trace(xp).equals(curve.getA()))
+ {
+ xp = xp.addOne();
+ }
+
+ ECFieldElement yp = null;
+ if (xp.isZero())
+ {
+ yp = curve.getB().sqrt();
+ }
+ else
+ {
+ ECFieldElement beta = xp.square().invert().multiply(curve.getB()).add(curve.getA()).add(xp);
+ ECFieldElement z = solveQuadraticEquation(curve, beta);
+ if (z != null)
+ {
+ if (!trace(z).equals(k))
+ {
+ z = z.addOne();
+ }
+ yp = xp.multiply(z);
+ }
+ }
+
+ if (yp == null)
+ {
+ throw new IllegalArgumentException("Invalid point compression");
+ }
+
+ return curve.createPoint(xp.toBigInteger(), yp.toBigInteger());
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145PublicKey.java b/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145PublicKey.java
new file mode 100644
index 00000000..d543df03
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145PublicKey.java
@@ -0,0 +1,46 @@
+package org.spongycastle.asn1.ua;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.math.ec.ECPoint;
+
+public class DSTU4145PublicKey
+ extends ASN1Object
+{
+
+ private ASN1OctetString pubKey;
+
+ public DSTU4145PublicKey(ECPoint pubKey)
+ {
+ // We always use big-endian in parameter encoding
+ this.pubKey = new DEROctetString(DSTU4145PointEncoder.encodePoint(pubKey));
+ }
+
+ private DSTU4145PublicKey(ASN1OctetString ocStr)
+ {
+ pubKey = ocStr;
+ }
+
+ public static DSTU4145PublicKey getInstance(Object obj)
+ {
+ if (obj instanceof DSTU4145PublicKey)
+ {
+ return (DSTU4145PublicKey)obj;
+ }
+
+ if (obj != null)
+ {
+ return new DSTU4145PublicKey(ASN1OctetString.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return pubKey;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/ua/UAObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/ua/UAObjectIdentifiers.java
new file mode 100644
index 00000000..8794143f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/ua/UAObjectIdentifiers.java
@@ -0,0 +1,23 @@
+package org.spongycastle.asn1.ua;
+
+import org.spongycastle.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
+{
+ /** Base OID: 1.2.804.2.1.1.1 */
+ static final ASN1ObjectIdentifier UaOid = new ASN1ObjectIdentifier("1.2.804.2.1.1.1");
+
+ /** 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/core/src/main/java/org/spongycastle/asn1/util/ASN1Dump.java b/core/src/main/java/org/spongycastle/asn1/util/ASN1Dump.java
new file mode 100644
index 00000000..6baad3c8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/util/ASN1Dump.java
@@ -0,0 +1,403 @@
+package org.spongycastle.asn1.util;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Boolean;
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Enumerated;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.ASN1UTCTime;
+import org.spongycastle.asn1.BERApplicationSpecific;
+import org.spongycastle.asn1.BEROctetString;
+import org.spongycastle.asn1.BERSequence;
+import org.spongycastle.asn1.BERSet;
+import org.spongycastle.asn1.BERTaggedObject;
+import org.spongycastle.asn1.BERTags;
+import org.spongycastle.asn1.DERApplicationSpecific;
+import org.spongycastle.asn1.DERBMPString;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERExternal;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.DERNull;
+import org.spongycastle.asn1.DERPrintableString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERT61String;
+import org.spongycastle.asn1.DERUTF8String;
+import org.spongycastle.asn1.DERVisibleString;
+import org.spongycastle.util.encoders.Hex;
+
+public class ASN1Dump
+{
+ private static final String TAB = " ";
+ private static final int SAMPLE_SIZE = 32;
+
+ /**
+ * dump a DER object as a formatted string with indentation
+ *
+ * @param obj the ASN1Primitive to be dumped out.
+ */
+ static void _dumpAsString(
+ String indent,
+ boolean verbose,
+ ASN1Primitive obj,
+ StringBuffer buf)
+ {
+ String nl = System.getProperty("line.separator");
+ if (obj instanceof ASN1Sequence)
+ {
+ Enumeration e = ((ASN1Sequence)obj).getObjects();
+ String tab = indent + TAB;
+
+ buf.append(indent);
+ if (obj instanceof BERSequence)
+ {
+ buf.append("BER Sequence");
+ }
+ else if (obj instanceof DERSequence)
+ {
+ buf.append("DER Sequence");
+ }
+ else
+ {
+ buf.append("Sequence");
+ }
+
+ buf.append(nl);
+
+ while (e.hasMoreElements())
+ {
+ Object o = e.nextElement();
+
+ if (o == null || o.equals(DERNull.INSTANCE))
+ {
+ buf.append(tab);
+ buf.append("NULL");
+ buf.append(nl);
+ }
+ else if (o instanceof ASN1Primitive)
+ {
+ _dumpAsString(tab, verbose, (ASN1Primitive)o, buf);
+ }
+ else
+ {
+ _dumpAsString(tab, verbose, ((ASN1Encodable)o).toASN1Primitive(), buf);
+ }
+ }
+ }
+ else if (obj instanceof ASN1TaggedObject)
+ {
+ String tab = indent + TAB;
+
+ buf.append(indent);
+ if (obj instanceof BERTaggedObject)
+ {
+ buf.append("BER Tagged [");
+ }
+ else
+ {
+ buf.append("Tagged [");
+ }
+
+ ASN1TaggedObject o = (ASN1TaggedObject)obj;
+
+ buf.append(Integer.toString(o.getTagNo()));
+ buf.append(']');
+
+ if (!o.isExplicit())
+ {
+ buf.append(" IMPLICIT ");
+ }
+
+ buf.append(nl);
+
+ if (o.isEmpty())
+ {
+ buf.append(tab);
+ buf.append("EMPTY");
+ buf.append(nl);
+ }
+ else
+ {
+ _dumpAsString(tab, verbose, o.getObject(), buf);
+ }
+ }
+ else if (obj instanceof ASN1Set)
+ {
+ Enumeration e = ((ASN1Set)obj).getObjects();
+ String tab = indent + TAB;
+
+ buf.append(indent);
+
+ if (obj instanceof BERSet)
+ {
+ buf.append("BER Set");
+ }
+ else
+ {
+ buf.append("DER Set");
+ }
+
+ buf.append(nl);
+
+ while (e.hasMoreElements())
+ {
+ Object o = e.nextElement();
+
+ if (o == null)
+ {
+ buf.append(tab);
+ buf.append("NULL");
+ buf.append(nl);
+ }
+ else if (o instanceof ASN1Primitive)
+ {
+ _dumpAsString(tab, verbose, (ASN1Primitive)o, buf);
+ }
+ else
+ {
+ _dumpAsString(tab, verbose, ((ASN1Encodable)o).toASN1Primitive(), buf);
+ }
+ }
+ }
+ else if (obj instanceof ASN1OctetString)
+ {
+ ASN1OctetString oct = (ASN1OctetString)obj;
+
+ if (obj instanceof BEROctetString)
+ {
+ buf.append(indent + "BER Constructed Octet String" + "[" + oct.getOctets().length + "] ");
+ }
+ else
+ {
+ buf.append(indent + "DER Octet String" + "[" + oct.getOctets().length + "] ");
+ }
+ if (verbose)
+ {
+ buf.append(dumpBinaryDataAsString(indent, oct.getOctets()));
+ }
+ else
+ {
+ buf.append(nl);
+ }
+ }
+ else if (obj instanceof ASN1ObjectIdentifier)
+ {
+ buf.append(indent + "ObjectIdentifier(" + ((ASN1ObjectIdentifier)obj).getId() + ")" + nl);
+ }
+ else if (obj instanceof ASN1Boolean)
+ {
+ buf.append(indent + "Boolean(" + ((ASN1Boolean)obj).isTrue() + ")" + nl);
+ }
+ else if (obj instanceof ASN1Integer)
+ {
+ buf.append(indent + "Integer(" + ((ASN1Integer)obj).getValue() + ")" + nl);
+ }
+ else if (obj instanceof DERBitString)
+ {
+ DERBitString bt = (DERBitString)obj;
+ buf.append(indent + "DER Bit String" + "[" + bt.getBytes().length + ", " + bt.getPadBits() + "] ");
+ if (verbose)
+ {
+ buf.append(dumpBinaryDataAsString(indent, bt.getBytes()));
+ }
+ else
+ {
+ buf.append(nl);
+ }
+ }
+ else if (obj instanceof DERIA5String)
+ {
+ buf.append(indent + "IA5String(" + ((DERIA5String)obj).getString() + ") " + nl);
+ }
+ else if (obj instanceof DERUTF8String)
+ {
+ buf.append(indent + "UTF8String(" + ((DERUTF8String)obj).getString() + ") " + nl);
+ }
+ else if (obj instanceof DERPrintableString)
+ {
+ buf.append(indent + "PrintableString(" + ((DERPrintableString)obj).getString() + ") " + nl);
+ }
+ else if (obj instanceof DERVisibleString)
+ {
+ buf.append(indent + "VisibleString(" + ((DERVisibleString)obj).getString() + ") " + nl);
+ }
+ else if (obj instanceof DERBMPString)
+ {
+ buf.append(indent + "BMPString(" + ((DERBMPString)obj).getString() + ") " + nl);
+ }
+ else if (obj instanceof DERT61String)
+ {
+ buf.append(indent + "T61String(" + ((DERT61String)obj).getString() + ") " + nl);
+ }
+ else if (obj instanceof ASN1UTCTime)
+ {
+ buf.append(indent + "UTCTime(" + ((ASN1UTCTime)obj).getTime() + ") " + nl);
+ }
+ else if (obj instanceof ASN1GeneralizedTime)
+ {
+ buf.append(indent + "GeneralizedTime(" + ((ASN1GeneralizedTime)obj).getTime() + ") " + nl);
+ }
+ else if (obj instanceof BERApplicationSpecific)
+ {
+ buf.append(outputApplicationSpecific("BER", indent, verbose, obj, nl));
+ }
+ else if (obj instanceof DERApplicationSpecific)
+ {
+ buf.append(outputApplicationSpecific("DER", indent, verbose, obj, nl));
+ }
+ else if (obj instanceof ASN1Enumerated)
+ {
+ ASN1Enumerated en = (ASN1Enumerated) obj;
+ buf.append(indent + "DER Enumerated(" + en.getValue() + ")" + nl);
+ }
+ else if (obj instanceof DERExternal)
+ {
+ DERExternal ext = (DERExternal) obj;
+ buf.append(indent + "External " + nl);
+ String tab = indent + TAB;
+ if (ext.getDirectReference() != null)
+ {
+ buf.append(tab + "Direct Reference: " + ext.getDirectReference().getId() + nl);
+ }
+ if (ext.getIndirectReference() != null)
+ {
+ buf.append(tab + "Indirect Reference: " + ext.getIndirectReference().toString() + nl);
+ }
+ if (ext.getDataValueDescriptor() != null)
+ {
+ _dumpAsString(tab, verbose, ext.getDataValueDescriptor(), buf);
+ }
+ buf.append(tab + "Encoding: " + ext.getEncoding() + nl);
+ _dumpAsString(tab, verbose, ext.getExternalContent(), buf);
+ }
+ else
+ {
+ buf.append(indent + obj.toString() + nl);
+ }
+ }
+
+ private static String outputApplicationSpecific(String type, String indent, boolean verbose, ASN1Primitive obj, String nl)
+ {
+ DERApplicationSpecific app = (DERApplicationSpecific)obj;
+ StringBuffer buf = new StringBuffer();
+
+ if (app.isConstructed())
+ {
+ try
+ {
+ ASN1Sequence s = ASN1Sequence.getInstance(app.getObject(BERTags.SEQUENCE));
+ buf.append(indent + type + " ApplicationSpecific[" + app.getApplicationTag() + "]" + nl);
+ for (Enumeration e = s.getObjects(); e.hasMoreElements();)
+ {
+ _dumpAsString(indent + TAB, verbose, (ASN1Primitive)e.nextElement(), buf);
+ }
+ }
+ catch (IOException e)
+ {
+ buf.append(e);
+ }
+ return buf.toString();
+ }
+
+ return indent + type + " ApplicationSpecific[" + app.getApplicationTag() + "] (" + new String(Hex.encode(app.getContents())) + ")" + nl;
+ }
+
+ /**
+ * dump out a DER object as a formatted string, in non-verbose mode.
+ *
+ * @param obj the ASN1Primitive to be dumped out.
+ * @return the resulting string.
+ */
+ public static String dumpAsString(
+ Object obj)
+ {
+ return dumpAsString(obj, false);
+ }
+
+ /**
+ * Dump out the object as a string.
+ *
+ * @param obj the object to be dumped
+ * @param verbose if true, dump out the contents of octet and bit strings.
+ * @return the resulting string.
+ */
+ public static String dumpAsString(
+ Object obj,
+ boolean verbose)
+ {
+ StringBuffer buf = new StringBuffer();
+
+ if (obj instanceof ASN1Primitive)
+ {
+ _dumpAsString("", verbose, (ASN1Primitive)obj, buf);
+ }
+ else if (obj instanceof ASN1Encodable)
+ {
+ _dumpAsString("", verbose, ((ASN1Encodable)obj).toASN1Primitive(), buf);
+ }
+ else
+ {
+ return "unknown object type " + obj.toString();
+ }
+
+ return buf.toString();
+ }
+
+ private static String dumpBinaryDataAsString(String indent, byte[] bytes)
+ {
+ String nl = System.getProperty("line.separator");
+ StringBuffer buf = new StringBuffer();
+
+ indent += TAB;
+
+ buf.append(nl);
+ for (int i = 0; i < bytes.length; i += SAMPLE_SIZE)
+ {
+ if (bytes.length - i > SAMPLE_SIZE)
+ {
+ buf.append(indent);
+ buf.append(new String(Hex.encode(bytes, i, SAMPLE_SIZE)));
+ buf.append(TAB);
+ buf.append(calculateAscString(bytes, i, SAMPLE_SIZE));
+ buf.append(nl);
+ }
+ else
+ {
+ buf.append(indent);
+ buf.append(new String(Hex.encode(bytes, i, bytes.length - i)));
+ for (int j = bytes.length - i; j != SAMPLE_SIZE; j++)
+ {
+ buf.append(" ");
+ }
+ buf.append(TAB);
+ buf.append(calculateAscString(bytes, i, bytes.length - i));
+ buf.append(nl);
+ }
+ }
+
+ return buf.toString();
+ }
+
+ private static String calculateAscString(byte[] bytes, int off, int len)
+ {
+ StringBuffer buf = new StringBuffer();
+
+ for (int i = off; i != off + len; i++)
+ {
+ if (bytes[i] >= ' ' && bytes[i] <= '~')
+ {
+ buf.append((char)bytes[i]);
+ }
+ }
+
+ return buf.toString();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/util/DERDump.java b/core/src/main/java/org/spongycastle/asn1/util/DERDump.java
new file mode 100644
index 00000000..c434abc2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/util/DERDump.java
@@ -0,0 +1,41 @@
+package org.spongycastle.asn1.util;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Primitive;
+
+/**
+ * @deprecated use ASN1Dump.
+ */
+public class DERDump
+ extends ASN1Dump
+{
+ /**
+ * dump out a DER object as a formatted string
+ *
+ * @param obj the ASN1Primitive to be dumped out.
+ */
+ public static String dumpAsString(
+ ASN1Primitive obj)
+ {
+ StringBuffer buf = new StringBuffer();
+
+ _dumpAsString("", false, obj, buf);
+
+ return buf.toString();
+ }
+
+ /**
+ * dump out a DER object as a formatted string
+ *
+ * @param obj the ASN1Primitive to be dumped out.
+ */
+ public static String dumpAsString(
+ ASN1Encodable obj)
+ {
+ StringBuffer buf = new StringBuffer();
+
+ _dumpAsString("", false, obj.toASN1Primitive(), buf);
+
+ return buf.toString();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/util/Dump.java b/core/src/main/java/org/spongycastle/asn1/util/Dump.java
new file mode 100644
index 00000000..6293e7b3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/util/Dump.java
@@ -0,0 +1,22 @@
+package org.spongycastle.asn1.util;
+
+import java.io.FileInputStream;
+
+import org.spongycastle.asn1.ASN1InputStream;
+
+public class Dump
+{
+ public static void main(
+ String args[])
+ throws Exception
+ {
+ FileInputStream fIn = new FileInputStream(args[0]);
+ ASN1InputStream bIn = new ASN1InputStream(fIn);
+ Object obj = null;
+
+ while ((obj = bIn.readObject()) != null)
+ {
+ System.out.println(ASN1Dump.dumpAsString(obj));
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x500/AttributeTypeAndValue.java b/core/src/main/java/org/spongycastle/asn1/x500/AttributeTypeAndValue.java
new file mode 100644
index 00000000..57fa4c25
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x500/AttributeTypeAndValue.java
@@ -0,0 +1,72 @@
+package org.spongycastle.asn1.x500;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class AttributeTypeAndValue
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier type;
+ private ASN1Encodable value;
+
+ private AttributeTypeAndValue(ASN1Sequence seq)
+ {
+ type = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ value = (ASN1Encodable)seq.getObjectAt(1);
+ }
+
+ public static AttributeTypeAndValue getInstance(Object o)
+ {
+ if (o instanceof AttributeTypeAndValue)
+ {
+ return (AttributeTypeAndValue)o;
+ }
+ else if (o != null)
+ {
+ return new AttributeTypeAndValue(ASN1Sequence.getInstance(o));
+ }
+
+ throw new IllegalArgumentException("null value in getInstance()");
+ }
+
+ public AttributeTypeAndValue(
+ ASN1ObjectIdentifier type,
+ ASN1Encodable value)
+ {
+ this.type = type;
+ this.value = value;
+ }
+
+ public ASN1ObjectIdentifier getType()
+ {
+ return type;
+ }
+
+ public ASN1Encodable getValue()
+ {
+ return value;
+ }
+
+ /**
+ * <pre>
+ * AttributeTypeAndValue ::= SEQUENCE {
+ * type OBJECT IDENTIFIER,
+ * value ANY DEFINED BY type }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(type);
+ v.add(value);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x500/DirectoryString.java b/core/src/main/java/org/spongycastle/asn1/x500/DirectoryString.java
new file mode 100644
index 00000000..8e61383b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x500/DirectoryString.java
@@ -0,0 +1,125 @@
+package org.spongycastle.asn1.x500;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1String;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBMPString;
+import org.spongycastle.asn1.DERPrintableString;
+import org.spongycastle.asn1.DERT61String;
+import org.spongycastle.asn1.DERUTF8String;
+import org.spongycastle.asn1.DERUniversalString;
+
+public class DirectoryString
+ extends ASN1Object
+ implements ASN1Choice, ASN1String
+{
+ private ASN1String string;
+
+ public static DirectoryString getInstance(Object o)
+ {
+ if (o == null || o instanceof DirectoryString)
+ {
+ return (DirectoryString)o;
+ }
+
+ if (o instanceof DERT61String)
+ {
+ return new DirectoryString((DERT61String)o);
+ }
+
+ if (o instanceof DERPrintableString)
+ {
+ return new DirectoryString((DERPrintableString)o);
+ }
+
+ if (o instanceof DERUniversalString)
+ {
+ return new DirectoryString((DERUniversalString)o);
+ }
+
+ if (o instanceof DERUTF8String)
+ {
+ return new DirectoryString((DERUTF8String)o);
+ }
+
+ if (o instanceof DERBMPString)
+ {
+ return new DirectoryString((DERBMPString)o);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + o.getClass().getName());
+ }
+
+ public static DirectoryString getInstance(ASN1TaggedObject o, boolean explicit)
+ {
+ if (!explicit)
+ {
+ throw new IllegalArgumentException("choice item must be explicitly tagged");
+ }
+
+ return getInstance(o.getObject());
+ }
+
+ private DirectoryString(
+ DERT61String string)
+ {
+ this.string = string;
+ }
+
+ private DirectoryString(
+ DERPrintableString string)
+ {
+ this.string = string;
+ }
+
+ private DirectoryString(
+ DERUniversalString string)
+ {
+ this.string = string;
+ }
+
+ private DirectoryString(
+ DERUTF8String string)
+ {
+ this.string = string;
+ }
+
+ private DirectoryString(
+ DERBMPString string)
+ {
+ this.string = string;
+ }
+
+ public DirectoryString(String string)
+ {
+ this.string = new DERUTF8String(string);
+ }
+
+ public String getString()
+ {
+ return string.getString();
+ }
+
+ public String toString()
+ {
+ return string.getString();
+ }
+
+ /**
+ * <pre>
+ * DirectoryString ::= CHOICE {
+ * teletexString TeletexString (SIZE (1..MAX)),
+ * printableString PrintableString (SIZE (1..MAX)),
+ * universalString UniversalString (SIZE (1..MAX)),
+ * utf8String UTF8String (SIZE (1..MAX)),
+ * bmpString BMPString (SIZE (1..MAX)) }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return ((ASN1Encodable)string).toASN1Primitive();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x500/RDN.java b/core/src/main/java/org/spongycastle/asn1/x500/RDN.java
new file mode 100644
index 00000000..5e70cfb3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x500/RDN.java
@@ -0,0 +1,119 @@
+package org.spongycastle.asn1.x500;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERSet;
+
+public class RDN
+ extends ASN1Object
+{
+ private ASN1Set values;
+
+ private RDN(ASN1Set values)
+ {
+ this.values = values;
+ }
+
+ public static RDN getInstance(Object obj)
+ {
+ if (obj instanceof RDN)
+ {
+ return (RDN)obj;
+ }
+ else if (obj != null)
+ {
+ return new RDN(ASN1Set.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Create a single valued RDN.
+ *
+ * @param oid RDN type.
+ * @param value RDN value.
+ */
+ public RDN(ASN1ObjectIdentifier oid, ASN1Encodable value)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(oid);
+ v.add(value);
+
+ this.values = new DERSet(new DERSequence(v));
+ }
+
+ public RDN(AttributeTypeAndValue attrTAndV)
+ {
+ this.values = new DERSet(attrTAndV);
+ }
+
+ /**
+ * Create a multi-valued RDN.
+ *
+ * @param aAndVs attribute type/value pairs making up the RDN
+ */
+ public RDN(AttributeTypeAndValue[] aAndVs)
+ {
+ this.values = new DERSet(aAndVs);
+ }
+
+ public boolean isMultiValued()
+ {
+ return this.values.size() > 1;
+ }
+
+ /**
+ * Return the number of AttributeTypeAndValue objects in this RDN,
+ *
+ * @return size of RDN, greater than 1 if multi-valued.
+ */
+ public int size()
+ {
+ return this.values.size();
+ }
+
+ public AttributeTypeAndValue getFirst()
+ {
+ if (this.values.size() == 0)
+ {
+ return null;
+ }
+
+ return AttributeTypeAndValue.getInstance(this.values.getObjectAt(0));
+ }
+
+ public AttributeTypeAndValue[] getTypesAndValues()
+ {
+ AttributeTypeAndValue[] tmp = new AttributeTypeAndValue[values.size()];
+
+ for (int i = 0; i != tmp.length; i++)
+ {
+ tmp[i] = AttributeTypeAndValue.getInstance(values.getObjectAt(i));
+ }
+
+ return tmp;
+ }
+
+ /**
+ * <pre>
+ * RelativeDistinguishedName ::=
+ * SET OF AttributeTypeAndValue
+
+ * AttributeTypeAndValue ::= SEQUENCE {
+ * type AttributeType,
+ * value AttributeValue }
+ * </pre>
+ * @return this object as an ASN1Primitive type
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return values;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x500/X500Name.java b/core/src/main/java/org/spongycastle/asn1/x500/X500Name.java
new file mode 100644
index 00000000..a5e01b31
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x500/X500Name.java
@@ -0,0 +1,326 @@
+package org.spongycastle.asn1.x500;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x500.style.BCStyle;
+
+/**
+ * <pre>
+ * Name ::= CHOICE {
+ * RDNSequence }
+ *
+ * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+ *
+ * RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
+ *
+ * AttributeTypeAndValue ::= SEQUENCE {
+ * type OBJECT IDENTIFIER,
+ * value ANY }
+ * </pre>
+ */
+public class X500Name
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private static X500NameStyle defaultStyle = BCStyle.INSTANCE;
+
+ private boolean isHashCodeCalculated;
+ private int hashCodeValue;
+
+ private X500NameStyle style;
+ private RDN[] rdns;
+
+ public X500Name(X500NameStyle style, X500Name name)
+ {
+ this.rdns = name.rdns;
+ this.style = style;
+ }
+
+ /**
+ * Return a X500Name based on the passed in tagged object.
+ *
+ * @param obj tag object holding name.
+ * @param explicit true if explicitly tagged false otherwise.
+ * @return the X500Name
+ */
+ public static X500Name getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ // must be true as choice item
+ return getInstance(ASN1Sequence.getInstance(obj, true));
+ }
+
+ public static X500Name getInstance(
+ Object obj)
+ {
+ if (obj instanceof X500Name)
+ {
+ return (X500Name)obj;
+ }
+ else if (obj != null)
+ {
+ return new X500Name(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static X500Name getInstance(
+ X500NameStyle style,
+ Object obj)
+ {
+ if (obj instanceof X500Name)
+ {
+ return getInstance(style, ((X500Name)obj).toASN1Primitive());
+ }
+ else if (obj != null)
+ {
+ return new X500Name(style, ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Constructor from ASN1Sequence
+ *
+ * the principal will be a list of constructed sets, each containing an (OID, String) pair.
+ */
+ private X500Name(
+ ASN1Sequence seq)
+ {
+ this(defaultStyle, seq);
+ }
+
+ private X500Name(
+ X500NameStyle style,
+ ASN1Sequence seq)
+ {
+ this.style = style;
+ this.rdns = new RDN[seq.size()];
+
+ int index = 0;
+
+ for (Enumeration e = seq.getObjects(); e.hasMoreElements();)
+ {
+ rdns[index++] = RDN.getInstance(e.nextElement());
+ }
+ }
+
+ public X500Name(
+ RDN[] rDNs)
+ {
+ this(defaultStyle, rDNs);
+ }
+
+ public X500Name(
+ X500NameStyle style,
+ RDN[] rDNs)
+ {
+ this.rdns = rDNs;
+ this.style = style;
+ }
+
+ public X500Name(
+ String dirName)
+ {
+ this(defaultStyle, dirName);
+ }
+
+ public X500Name(
+ X500NameStyle style,
+ String dirName)
+ {
+ this(style.fromString(dirName));
+
+ this.style = style;
+ }
+
+ /**
+ * return an array of RDNs in structure order.
+ *
+ * @return an array of RDN objects.
+ */
+ public RDN[] getRDNs()
+ {
+ RDN[] tmp = new RDN[this.rdns.length];
+
+ System.arraycopy(rdns, 0, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+
+ /**
+ * return an array of OIDs contained in the attribute type of each RDN in structure order.
+ *
+ * @return an array, possibly zero length, of ASN1ObjectIdentifiers objects.
+ */
+ public ASN1ObjectIdentifier[] getAttributeTypes()
+ {
+ int count = 0;
+
+ for (int i = 0; i != rdns.length; i++)
+ {
+ RDN rdn = rdns[i];
+
+ count += rdn.size();
+ }
+
+ ASN1ObjectIdentifier[] res = new ASN1ObjectIdentifier[count];
+
+ count = 0;
+
+ for (int i = 0; i != rdns.length; i++)
+ {
+ RDN rdn = rdns[i];
+
+ if (rdn.isMultiValued())
+ {
+ AttributeTypeAndValue[] attr = rdn.getTypesAndValues();
+ for (int j = 0; j != attr.length; j++)
+ {
+ res[count++] = attr[j].getType();
+ }
+ }
+ else if (rdn.size() != 0)
+ {
+ res[count++] = rdn.getFirst().getType();
+ }
+ }
+
+ return res;
+ }
+
+ /**
+ * return an array of RDNs containing the attribute type given by OID in structure order.
+ *
+ * @param attributeType the type OID we are looking for.
+ * @return an array, possibly zero length, of RDN objects.
+ */
+ public RDN[] getRDNs(ASN1ObjectIdentifier attributeType)
+ {
+ RDN[] res = new RDN[rdns.length];
+ int count = 0;
+
+ for (int i = 0; i != rdns.length; i++)
+ {
+ RDN rdn = rdns[i];
+
+ if (rdn.isMultiValued())
+ {
+ AttributeTypeAndValue[] attr = rdn.getTypesAndValues();
+ for (int j = 0; j != attr.length; j++)
+ {
+ if (attr[j].getType().equals(attributeType))
+ {
+ res[count++] = rdn;
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (rdn.getFirst().getType().equals(attributeType))
+ {
+ res[count++] = rdn;
+ }
+ }
+ }
+
+ RDN[] tmp = new RDN[count];
+
+ System.arraycopy(res, 0, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERSequence(rdns);
+ }
+
+ public int hashCode()
+ {
+ if (isHashCodeCalculated)
+ {
+ return hashCodeValue;
+ }
+
+ isHashCodeCalculated = true;
+
+ hashCodeValue = style.calculateHashCode(this);
+
+ return hashCodeValue;
+ }
+
+ /**
+ * test for equality - note: case is ignored.
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj == this)
+ {
+ return true;
+ }
+
+ if (!(obj instanceof X500Name || obj instanceof ASN1Sequence))
+ {
+ return false;
+ }
+
+ ASN1Primitive derO = ((ASN1Encodable)obj).toASN1Primitive();
+
+ if (this.toASN1Primitive().equals(derO))
+ {
+ return true;
+ }
+
+ try
+ {
+ return style.areEqual(this, new X500Name(ASN1Sequence.getInstance(((ASN1Encodable)obj).toASN1Primitive())));
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+ }
+
+ public String toString()
+ {
+ return style.toString(this);
+ }
+
+ /**
+ * Set the default style for X500Name construction.
+ *
+ * @param style an X500NameStyle
+ */
+ public static void setDefaultStyle(X500NameStyle style)
+ {
+ if (style == null)
+ {
+ throw new NullPointerException("cannot set style to null");
+ }
+
+ defaultStyle = style;
+ }
+
+ /**
+ * Return the current default style.
+ *
+ * @return default style for X500Name construction.
+ */
+ public static X500NameStyle getDefaultStyle()
+ {
+ return defaultStyle;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x500/X500NameBuilder.java b/core/src/main/java/org/spongycastle/asn1/x500/X500NameBuilder.java
new file mode 100644
index 00000000..6640eff9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x500/X500NameBuilder.java
@@ -0,0 +1,87 @@
+package org.spongycastle.asn1.x500;
+
+import java.util.Vector;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.x500.style.BCStyle;
+
+public class X500NameBuilder
+{
+ private X500NameStyle template;
+ private Vector rdns = new Vector();
+
+ public X500NameBuilder()
+ {
+ this(BCStyle.INSTANCE);
+ }
+
+ public X500NameBuilder(X500NameStyle template)
+ {
+ this.template = template;
+ }
+
+ public X500NameBuilder addRDN(ASN1ObjectIdentifier oid, String value)
+ {
+ this.addRDN(oid, template.stringToValue(oid, value));
+
+ return this;
+ }
+
+ public X500NameBuilder addRDN(ASN1ObjectIdentifier oid, ASN1Encodable value)
+ {
+ rdns.addElement(new RDN(oid, value));
+
+ return this;
+ }
+
+ public X500NameBuilder addRDN(AttributeTypeAndValue attrTAndV)
+ {
+ rdns.addElement(new RDN(attrTAndV));
+
+ return this;
+ }
+
+ public X500NameBuilder addMultiValuedRDN(ASN1ObjectIdentifier[] oids, String[] values)
+ {
+ ASN1Encodable[] vals = new ASN1Encodable[values.length];
+
+ for (int i = 0; i != vals.length; i++)
+ {
+ vals[i] = template.stringToValue(oids[i], values[i]);
+ }
+
+ return addMultiValuedRDN(oids, vals);
+ }
+
+ public X500NameBuilder addMultiValuedRDN(ASN1ObjectIdentifier[] oids, ASN1Encodable[] values)
+ {
+ AttributeTypeAndValue[] avs = new AttributeTypeAndValue[oids.length];
+
+ for (int i = 0; i != oids.length; i++)
+ {
+ avs[i] = new AttributeTypeAndValue(oids[i], values[i]);
+ }
+
+ return addMultiValuedRDN(avs);
+ }
+
+ public X500NameBuilder addMultiValuedRDN(AttributeTypeAndValue[] attrTAndVs)
+ {
+ rdns.addElement(new RDN(attrTAndVs));
+
+ return this;
+ }
+
+ public X500Name build()
+ {
+ RDN[] vals = new RDN[rdns.size()];
+
+ for (int i = 0; i != vals.length; i++)
+ {
+ vals[i] = (RDN)rdns.elementAt(i);
+ }
+
+ return new X500Name(template, vals);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x500/X500NameStyle.java b/core/src/main/java/org/spongycastle/asn1/x500/X500NameStyle.java
new file mode 100644
index 00000000..8c716170
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x500/X500NameStyle.java
@@ -0,0 +1,79 @@
+package org.spongycastle.asn1.x500;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+
+/**
+ * It turns out that the number of standard ways the fields in a DN should be
+ * encoded into their ASN.1 counterparts is rapidly approaching the
+ * number of machines on the internet. By default the X500Name class
+ * will produce UTF8Strings in line with the current recommendations (RFC 3280).
+ * <p>
+ */
+public interface X500NameStyle
+{
+ /**
+ * Convert the passed in String value into the appropriate ASN.1
+ * encoded object.
+ *
+ * @param oid the OID associated with the value in the DN.
+ * @param value the value of the particular DN component.
+ * @return the ASN.1 equivalent for the value.
+ */
+ ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value);
+
+ /**
+ * Return the OID associated with the passed in name.
+ *
+ * @param attrName the string to match.
+ * @return an OID
+ */
+ ASN1ObjectIdentifier attrNameToOID(String attrName);
+
+ /**
+ * Return an array of RDN generated from the passed in String.
+ * @param dirName the String representation.
+ * @return an array of corresponding RDNs.
+ */
+ RDN[] fromString(String dirName);
+
+ /**
+ * Return true if the two names are equal.
+ *
+ * @param name1 first name for comparison.
+ * @param name2 second name for comparison.
+ * @return true if name1 = name 2, false otherwise.
+ */
+ boolean areEqual(X500Name name1, X500Name name2);
+
+ /**
+ * Calculate a hashCode for the passed in name.
+ *
+ * @param name the name the hashCode is required for.
+ * @return the calculated hashCode.
+ */
+ int calculateHashCode(X500Name name);
+
+ /**
+ * Convert the passed in X500Name to a String.
+ * @param name the name to convert.
+ * @return a String representation.
+ */
+ String toString(X500Name name);
+
+ /**
+ * Return the display name for toString() associated with the OID.
+ *
+ * @param oid the OID of interest.
+ * @return the name displayed in toString(), null if no mapping provided.
+ */
+ String oidToDisplayName(ASN1ObjectIdentifier oid);
+
+ /**
+ * Return the acceptable names in a String DN that map to OID.
+ *
+ * @param oid the OID of interest.
+ * @return an array of String aliases for the OID, zero length if there are none.
+ */
+ String[] oidToAttrNames(ASN1ObjectIdentifier oid);
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x500/style/AbstractX500NameStyle.java b/core/src/main/java/org/spongycastle/asn1/x500/style/AbstractX500NameStyle.java
new file mode 100644
index 00000000..dfab0377
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x500/style/AbstractX500NameStyle.java
@@ -0,0 +1,192 @@
+package org.spongycastle.asn1.x500.style;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.DERUTF8String;
+import org.spongycastle.asn1.x500.AttributeTypeAndValue;
+import org.spongycastle.asn1.x500.RDN;
+import org.spongycastle.asn1.x500.X500Name;
+import org.spongycastle.asn1.x500.X500NameStyle;
+
+/**
+ * This class provides some default behavior and common implementation for a
+ * X500NameStyle. It should be easily extendable to support implementing the
+ * desired X500NameStyle.
+ */
+public abstract class AbstractX500NameStyle
+ implements X500NameStyle
+{
+
+ /**
+ * Tool function to shallow copy a Hashtable.
+ *
+ * @param paramsMap table to copy
+ * @return the copy of the table
+ */
+ public static Hashtable copyHashTable(Hashtable paramsMap)
+ {
+ Hashtable newTable = new Hashtable();
+
+ Enumeration keys = paramsMap.keys();
+ while (keys.hasMoreElements())
+ {
+ Object key = keys.nextElement();
+ newTable.put(key, paramsMap.get(key));
+ }
+
+ return newTable;
+ }
+
+ private int calcHashCode(ASN1Encodable enc)
+ {
+ String value = IETFUtils.valueToString(enc);
+ value = IETFUtils.canonicalize(value);
+ return value.hashCode();
+ }
+
+ public int calculateHashCode(X500Name name)
+ {
+ int hashCodeValue = 0;
+ RDN[] rdns = name.getRDNs();
+
+ // this needs to be order independent, like equals
+ for (int i = 0; i != rdns.length; i++)
+ {
+ if (rdns[i].isMultiValued())
+ {
+ AttributeTypeAndValue[] atv = rdns[i].getTypesAndValues();
+
+ for (int j = 0; j != atv.length; j++)
+ {
+ hashCodeValue ^= atv[j].getType().hashCode();
+ hashCodeValue ^= calcHashCode(atv[j].getValue());
+ }
+ }
+ else
+ {
+ hashCodeValue ^= rdns[i].getFirst().getType().hashCode();
+ hashCodeValue ^= calcHashCode(rdns[i].getFirst().getValue());
+ }
+ }
+
+ return hashCodeValue;
+ }
+
+
+ /**
+ * For all string values starting with '#' is assumed, that these are
+ * already valid ASN.1 objects encoded in hex.
+ * <p>
+ * All other string values are send to
+ * {@link AbstractX500NameStyle#encodeStringValue(ASN1ObjectIdentifier, String)}.
+ * </p>
+ * Subclasses should overwrite
+ * {@link AbstractX500NameStyle#encodeStringValue(ASN1ObjectIdentifier, String)}
+ * to change the encoding of specific types.
+ *
+ * @param oid the DN name of the value.
+ * @param value the String representation of the value.
+ */
+ public ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value)
+ {
+ if (value.length() != 0 && value.charAt(0) == '#')
+ {
+ try
+ {
+ return IETFUtils.valueFromHexString(value, 1);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("can't recode value for oid " + oid.getId());
+ }
+ }
+
+ if (value.length() != 0 && value.charAt(0) == '\\')
+ {
+ value = value.substring(1);
+ }
+
+ return encodeStringValue(oid, value);
+ }
+
+ /**
+ * Encoded every value into a UTF8String.
+ * <p>
+ * Subclasses should overwrite
+ * this method to change the encoding of specific types.
+ * </p>
+ *
+ * @param oid the DN oid of the value
+ * @param value the String representation of the value
+ * @return a the value encoded into a ASN.1 object. Never returns <code>null</code>.
+ */
+ protected ASN1Encodable encodeStringValue(ASN1ObjectIdentifier oid, String value)
+ {
+ return new DERUTF8String(value);
+ }
+
+ public boolean areEqual(X500Name name1, X500Name name2)
+ {
+ RDN[] rdns1 = name1.getRDNs();
+ RDN[] rdns2 = name2.getRDNs();
+
+ if (rdns1.length != rdns2.length)
+ {
+ return false;
+ }
+
+ boolean reverse = false;
+
+ if (rdns1[0].getFirst() != null && rdns2[0].getFirst() != null)
+ {
+ reverse = !rdns1[0].getFirst().getType().equals(rdns2[0].getFirst().getType()); // guess forward
+ }
+
+ for (int i = 0; i != rdns1.length; i++)
+ {
+ if (!foundMatch(reverse, rdns1[i], rdns2))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private boolean foundMatch(boolean reverse, RDN rdn, RDN[] possRDNs)
+ {
+ if (reverse)
+ {
+ for (int i = possRDNs.length - 1; i >= 0; i--)
+ {
+ if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
+ {
+ possRDNs[i] = null;
+ return true;
+ }
+ }
+ }
+ else
+ {
+ for (int i = 0; i != possRDNs.length; i++)
+ {
+ if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
+ {
+ possRDNs[i] = null;
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ protected boolean rdnAreEqual(RDN rdn1, RDN rdn2)
+ {
+ return IETFUtils.rDNAreEqual(rdn1, rdn2);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x500/style/BCStrictStyle.java b/core/src/main/java/org/spongycastle/asn1/x500/style/BCStrictStyle.java
new file mode 100644
index 00000000..23609e72
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x500/style/BCStrictStyle.java
@@ -0,0 +1,36 @@
+package org.spongycastle.asn1.x500.style;
+
+import org.spongycastle.asn1.x500.RDN;
+import org.spongycastle.asn1.x500.X500Name;
+import org.spongycastle.asn1.x500.X500NameStyle;
+
+/**
+ * Variation of BCStyle that insists on strict ordering for equality
+ * and hashCode comparisons
+ */
+public class BCStrictStyle
+ extends BCStyle
+{
+ public static final X500NameStyle INSTANCE = new BCStrictStyle();
+
+ public boolean areEqual(X500Name name1, X500Name name2)
+ {
+ RDN[] rdns1 = name1.getRDNs();
+ RDN[] rdns2 = name2.getRDNs();
+
+ if (rdns1.length != rdns2.length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i != rdns1.length; i++)
+ {
+ if (!rdnAreEqual(rdns1[i], rdns2[i]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x500/style/BCStyle.java b/core/src/main/java/org/spongycastle/asn1/x500/style/BCStyle.java
new file mode 100644
index 00000000..cb92a0bd
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x500/style/BCStyle.java
@@ -0,0 +1,349 @@
+package org.spongycastle.asn1.x500.style;
+
+import java.util.Hashtable;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.DERPrintableString;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.x500.RDN;
+import org.spongycastle.asn1.x500.X500Name;
+import org.spongycastle.asn1.x500.X500NameStyle;
+import org.spongycastle.asn1.x509.X509ObjectIdentifiers;
+
+public class BCStyle
+ extends AbstractX500NameStyle
+{
+ /**
+ * country code - StringType(SIZE(2))
+ */
+ public static final ASN1ObjectIdentifier C = new ASN1ObjectIdentifier("2.5.4.6");
+
+ /**
+ * organization - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier O = new ASN1ObjectIdentifier("2.5.4.10");
+
+ /**
+ * organizational unit name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier OU = new ASN1ObjectIdentifier("2.5.4.11");
+
+ /**
+ * Title
+ */
+ public static final ASN1ObjectIdentifier T = new ASN1ObjectIdentifier("2.5.4.12");
+
+ /**
+ * common name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier CN = new ASN1ObjectIdentifier("2.5.4.3");
+
+ /**
+ * device serial number name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier SN = new ASN1ObjectIdentifier("2.5.4.5");
+
+ /**
+ * street - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier STREET = new ASN1ObjectIdentifier("2.5.4.9");
+
+ /**
+ * device serial number name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier SERIALNUMBER = SN;
+
+ /**
+ * locality name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier L = new ASN1ObjectIdentifier("2.5.4.7");
+
+ /**
+ * state, or province name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier ST = new ASN1ObjectIdentifier("2.5.4.8");
+
+ /**
+ * Naming attributes of type X520name
+ */
+ public static final ASN1ObjectIdentifier SURNAME = new ASN1ObjectIdentifier("2.5.4.4");
+ public static final ASN1ObjectIdentifier GIVENNAME = new ASN1ObjectIdentifier("2.5.4.42");
+ public static final ASN1ObjectIdentifier INITIALS = new ASN1ObjectIdentifier("2.5.4.43");
+ public static final ASN1ObjectIdentifier GENERATION = new ASN1ObjectIdentifier("2.5.4.44");
+ public static final ASN1ObjectIdentifier UNIQUE_IDENTIFIER = new ASN1ObjectIdentifier("2.5.4.45");
+
+ /**
+ * businessCategory - DirectoryString(SIZE(1..128)
+ */
+ public static final ASN1ObjectIdentifier BUSINESS_CATEGORY = new ASN1ObjectIdentifier(
+ "2.5.4.15");
+
+ /**
+ * postalCode - DirectoryString(SIZE(1..40)
+ */
+ public static final ASN1ObjectIdentifier POSTAL_CODE = new ASN1ObjectIdentifier(
+ "2.5.4.17");
+
+ /**
+ * dnQualifier - DirectoryString(SIZE(1..64)
+ */
+ public static final ASN1ObjectIdentifier DN_QUALIFIER = new ASN1ObjectIdentifier(
+ "2.5.4.46");
+
+ /**
+ * RFC 3039 Pseudonym - DirectoryString(SIZE(1..64)
+ */
+ public static final ASN1ObjectIdentifier PSEUDONYM = new ASN1ObjectIdentifier(
+ "2.5.4.65");
+
+
+ /**
+ * RFC 3039 DateOfBirth - GeneralizedTime - YYYYMMDD000000Z
+ */
+ public static final ASN1ObjectIdentifier DATE_OF_BIRTH = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.1");
+
+ /**
+ * RFC 3039 PlaceOfBirth - DirectoryString(SIZE(1..128)
+ */
+ public static final ASN1ObjectIdentifier PLACE_OF_BIRTH = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.2");
+
+ /**
+ * RFC 3039 Gender - PrintableString (SIZE(1)) -- "M", "F", "m" or "f"
+ */
+ public static final ASN1ObjectIdentifier GENDER = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.3");
+
+ /**
+ * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
+ * codes only
+ */
+ public static final ASN1ObjectIdentifier COUNTRY_OF_CITIZENSHIP = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.4");
+
+ /**
+ * RFC 3039 CountryOfResidence - PrintableString (SIZE (2)) -- ISO 3166
+ * codes only
+ */
+ public static final ASN1ObjectIdentifier COUNTRY_OF_RESIDENCE = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.5");
+
+
+ /**
+ * ISIS-MTT NameAtBirth - DirectoryString(SIZE(1..64)
+ */
+ public static final ASN1ObjectIdentifier NAME_AT_BIRTH = new ASN1ObjectIdentifier("1.3.36.8.3.14");
+
+ /**
+ * RFC 3039 PostalAddress - SEQUENCE SIZE (1..6) OF
+ * DirectoryString(SIZE(1..30))
+ */
+ public static final ASN1ObjectIdentifier POSTAL_ADDRESS = new ASN1ObjectIdentifier("2.5.4.16");
+
+ /**
+ * RFC 2256 dmdName
+ */
+ public static final ASN1ObjectIdentifier DMD_NAME = new ASN1ObjectIdentifier("2.5.4.54");
+
+ /**
+ * id-at-telephoneNumber
+ */
+ public static final ASN1ObjectIdentifier TELEPHONE_NUMBER = X509ObjectIdentifiers.id_at_telephoneNumber;
+
+ /**
+ * id-at-name
+ */
+ public static final ASN1ObjectIdentifier NAME = X509ObjectIdentifiers.id_at_name;
+
+ /**
+ * Email address (RSA PKCS#9 extension) - IA5String.
+ * <p>Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.
+ */
+ public static final ASN1ObjectIdentifier EmailAddress = PKCSObjectIdentifiers.pkcs_9_at_emailAddress;
+
+ /**
+ * more from PKCS#9
+ */
+ public static final ASN1ObjectIdentifier UnstructuredName = PKCSObjectIdentifiers.pkcs_9_at_unstructuredName;
+ public static final ASN1ObjectIdentifier UnstructuredAddress = PKCSObjectIdentifiers.pkcs_9_at_unstructuredAddress;
+
+ /**
+ * email address in Verisign certificates
+ */
+ public static final ASN1ObjectIdentifier E = EmailAddress;
+
+ /*
+ * others...
+ */
+ public static final ASN1ObjectIdentifier DC = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.25");
+
+ /**
+ * LDAP User id.
+ */
+ public static final ASN1ObjectIdentifier UID = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.1");
+
+ /**
+ * default look up table translating OID values into their common symbols following
+ * the convention in RFC 2253 with a few extras
+ */
+ private static final Hashtable DefaultSymbols = new Hashtable();
+
+ /**
+ * look up table translating common symbols into their OIDS.
+ */
+ private static final Hashtable DefaultLookUp = new Hashtable();
+
+ static
+ {
+ DefaultSymbols.put(C, "C");
+ DefaultSymbols.put(O, "O");
+ DefaultSymbols.put(T, "T");
+ DefaultSymbols.put(OU, "OU");
+ DefaultSymbols.put(CN, "CN");
+ DefaultSymbols.put(L, "L");
+ DefaultSymbols.put(ST, "ST");
+ DefaultSymbols.put(SN, "SERIALNUMBER");
+ DefaultSymbols.put(EmailAddress, "E");
+ DefaultSymbols.put(DC, "DC");
+ DefaultSymbols.put(UID, "UID");
+ DefaultSymbols.put(STREET, "STREET");
+ DefaultSymbols.put(SURNAME, "SURNAME");
+ DefaultSymbols.put(GIVENNAME, "GIVENNAME");
+ DefaultSymbols.put(INITIALS, "INITIALS");
+ DefaultSymbols.put(GENERATION, "GENERATION");
+ DefaultSymbols.put(UnstructuredAddress, "unstructuredAddress");
+ DefaultSymbols.put(UnstructuredName, "unstructuredName");
+ DefaultSymbols.put(UNIQUE_IDENTIFIER, "UniqueIdentifier");
+ DefaultSymbols.put(DN_QUALIFIER, "DN");
+ DefaultSymbols.put(PSEUDONYM, "Pseudonym");
+ DefaultSymbols.put(POSTAL_ADDRESS, "PostalAddress");
+ DefaultSymbols.put(NAME_AT_BIRTH, "NameAtBirth");
+ DefaultSymbols.put(COUNTRY_OF_CITIZENSHIP, "CountryOfCitizenship");
+ DefaultSymbols.put(COUNTRY_OF_RESIDENCE, "CountryOfResidence");
+ DefaultSymbols.put(GENDER, "Gender");
+ DefaultSymbols.put(PLACE_OF_BIRTH, "PlaceOfBirth");
+ DefaultSymbols.put(DATE_OF_BIRTH, "DateOfBirth");
+ DefaultSymbols.put(POSTAL_CODE, "PostalCode");
+ DefaultSymbols.put(BUSINESS_CATEGORY, "BusinessCategory");
+ DefaultSymbols.put(TELEPHONE_NUMBER, "TelephoneNumber");
+ DefaultSymbols.put(NAME, "Name");
+
+ DefaultLookUp.put("c", C);
+ DefaultLookUp.put("o", O);
+ DefaultLookUp.put("t", T);
+ DefaultLookUp.put("ou", OU);
+ DefaultLookUp.put("cn", CN);
+ DefaultLookUp.put("l", L);
+ DefaultLookUp.put("st", ST);
+ DefaultLookUp.put("sn", SN);
+ DefaultLookUp.put("serialnumber", SN);
+ DefaultLookUp.put("street", STREET);
+ DefaultLookUp.put("emailaddress", E);
+ DefaultLookUp.put("dc", DC);
+ DefaultLookUp.put("e", E);
+ DefaultLookUp.put("uid", UID);
+ DefaultLookUp.put("surname", SURNAME);
+ DefaultLookUp.put("givenname", GIVENNAME);
+ DefaultLookUp.put("initials", INITIALS);
+ DefaultLookUp.put("generation", GENERATION);
+ DefaultLookUp.put("unstructuredaddress", UnstructuredAddress);
+ DefaultLookUp.put("unstructuredname", UnstructuredName);
+ DefaultLookUp.put("uniqueidentifier", UNIQUE_IDENTIFIER);
+ DefaultLookUp.put("dn", DN_QUALIFIER);
+ DefaultLookUp.put("pseudonym", PSEUDONYM);
+ DefaultLookUp.put("postaladdress", POSTAL_ADDRESS);
+ DefaultLookUp.put("nameofbirth", NAME_AT_BIRTH);
+ DefaultLookUp.put("countryofcitizenship", COUNTRY_OF_CITIZENSHIP);
+ DefaultLookUp.put("countryofresidence", COUNTRY_OF_RESIDENCE);
+ DefaultLookUp.put("gender", GENDER);
+ DefaultLookUp.put("placeofbirth", PLACE_OF_BIRTH);
+ DefaultLookUp.put("dateofbirth", DATE_OF_BIRTH);
+ DefaultLookUp.put("postalcode", POSTAL_CODE);
+ DefaultLookUp.put("businesscategory", BUSINESS_CATEGORY);
+ DefaultLookUp.put("telephonenumber", TELEPHONE_NUMBER);
+ 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);
+ }
+
+ protected ASN1Encodable encodeStringValue(ASN1ObjectIdentifier oid,
+ String value) {
+ if (oid.equals(EmailAddress) || oid.equals(DC))
+ {
+ return new DERIA5String(value);
+ }
+ else if (oid.equals(DATE_OF_BIRTH)) // accept time string as well as # (for compatibility)
+ {
+ return new ASN1GeneralizedTime(value);
+ }
+ else if (oid.equals(C) || oid.equals(SN) || oid.equals(DN_QUALIFIER)
+ || oid.equals(TELEPHONE_NUMBER))
+ {
+ return new DERPrintableString(value);
+ }
+
+ return super.encodeStringValue(oid, value);
+ }
+
+ public String oidToDisplayName(ASN1ObjectIdentifier oid)
+ {
+ return (String)DefaultSymbols.get(oid);
+ }
+
+ public String[] oidToAttrNames(ASN1ObjectIdentifier oid)
+ {
+ return IETFUtils.findAttrNamesForOID(oid, defaultLookUp);
+ }
+
+ public ASN1ObjectIdentifier attrNameToOID(String attrName)
+ {
+ return IETFUtils.decodeAttrName(attrName, defaultLookUp);
+ }
+
+ public RDN[] fromString(String dirName)
+ {
+ return IETFUtils.rDNsFromString(dirName, this);
+ }
+
+ public String toString(X500Name name)
+ {
+ StringBuffer buf = new StringBuffer();
+ boolean first = true;
+
+ RDN[] rdns = name.getRDNs();
+
+ for (int i = 0; i < rdns.length; i++)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ buf.append(',');
+ }
+
+ IETFUtils.appendRDN(buf, rdns[i], defaultSymbols);
+ }
+
+ return buf.toString();
+ }
+
+
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x500/style/IETFUtils.java b/core/src/main/java/org/spongycastle/asn1/x500/style/IETFUtils.java
new file mode 100644
index 00000000..14961e4c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x500/style/IETFUtils.java
@@ -0,0 +1,572 @@
+package org.spongycastle.asn1.x500.style;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Encoding;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1String;
+import org.spongycastle.asn1.DERUniversalString;
+import org.spongycastle.asn1.x500.AttributeTypeAndValue;
+import org.spongycastle.asn1.x500.RDN;
+import org.spongycastle.asn1.x500.X500NameBuilder;
+import org.spongycastle.asn1.x500.X500NameStyle;
+import org.spongycastle.util.Strings;
+import org.spongycastle.util.encoders.Hex;
+
+public class IETFUtils
+{
+ private static String unescape(String elt)
+ {
+ if (elt.length() == 0 || (elt.indexOf('\\') < 0 && elt.indexOf('"') < 0))
+ {
+ return elt.trim();
+ }
+
+ char[] elts = elt.toCharArray();
+ boolean escaped = false;
+ boolean quoted = false;
+ StringBuffer buf = new StringBuffer(elt.length());
+ int start = 0;
+
+ // if it's an escaped hash string and not an actual encoding in string form
+ // we need to leave it escaped.
+ if (elts[0] == '\\')
+ {
+ if (elts[1] == '#')
+ {
+ start = 2;
+ buf.append("\\#");
+ }
+ }
+
+ boolean nonWhiteSpaceEncountered = false;
+ int lastEscaped = 0;
+ char hex1 = 0;
+
+ for (int i = start; i != elts.length; i++)
+ {
+ char c = elts[i];
+
+ if (c != ' ')
+ {
+ nonWhiteSpaceEncountered = true;
+ }
+
+ if (c == '"')
+ {
+ if (!escaped)
+ {
+ quoted = !quoted;
+ }
+ else
+ {
+ buf.append(c);
+ }
+ escaped = false;
+ }
+ else if (c == '\\' && !(escaped || quoted))
+ {
+ escaped = true;
+ lastEscaped = buf.length();
+ }
+ else
+ {
+ if (c == ' ' && !escaped && !nonWhiteSpaceEncountered)
+ {
+ continue;
+ }
+ if (escaped && isHexDigit(c))
+ {
+ if (hex1 != 0)
+ {
+ buf.append((char)(convertHex(hex1) * 16 + convertHex(c)));
+ escaped = false;
+ hex1 = 0;
+ continue;
+ }
+ hex1 = c;
+ continue;
+ }
+ buf.append(c);
+ escaped = false;
+ }
+ }
+
+ if (buf.length() > 0)
+ {
+ while (buf.charAt(buf.length() - 1) == ' ' && lastEscaped != (buf.length() - 1))
+ {
+ buf.setLength(buf.length() - 1);
+ }
+ }
+
+ return buf.toString();
+ }
+
+ private static boolean isHexDigit(char c)
+ {
+ return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F');
+ }
+
+ private static int convertHex(char c)
+ {
+ if ('0' <= c && c <= '9')
+ {
+ return c - '0';
+ }
+ if ('a' <= c && c <= 'f')
+ {
+ return c - 'a' + 10;
+ }
+ return c - 'A' + 10;
+ }
+
+ public static RDN[] rDNsFromString(String name, X500NameStyle x500Style)
+ {
+ X500NameTokenizer nTok = new X500NameTokenizer(name);
+ X500NameBuilder builder = new X500NameBuilder(x500Style);
+
+ while (nTok.hasMoreTokens())
+ {
+ String token = nTok.nextToken();
+
+ if (token.indexOf('+') > 0)
+ {
+ X500NameTokenizer pTok = new X500NameTokenizer(token, '+');
+ X500NameTokenizer vTok = new X500NameTokenizer(pTok.nextToken(), '=');
+
+ String attr = vTok.nextToken();
+
+ if (!vTok.hasMoreTokens())
+ {
+ throw new IllegalArgumentException("badly formatted directory string");
+ }
+
+ String value = vTok.nextToken();
+ ASN1ObjectIdentifier oid = x500Style.attrNameToOID(attr.trim());
+
+ if (pTok.hasMoreTokens())
+ {
+ Vector oids = new Vector();
+ Vector values = new Vector();
+
+ oids.addElement(oid);
+ values.addElement(unescape(value));
+
+ while (pTok.hasMoreTokens())
+ {
+ vTok = new X500NameTokenizer(pTok.nextToken(), '=');
+
+ attr = vTok.nextToken();
+
+ if (!vTok.hasMoreTokens())
+ {
+ throw new IllegalArgumentException("badly formatted directory string");
+ }
+
+ value = vTok.nextToken();
+ oid = x500Style.attrNameToOID(attr.trim());
+
+
+ oids.addElement(oid);
+ values.addElement(unescape(value));
+ }
+
+ builder.addMultiValuedRDN(toOIDArray(oids), toValueArray(values));
+ }
+ else
+ {
+ builder.addRDN(oid, unescape(value));
+ }
+ }
+ else
+ {
+ X500NameTokenizer vTok = new X500NameTokenizer(token, '=');
+
+ String attr = vTok.nextToken();
+
+ if (!vTok.hasMoreTokens())
+ {
+ throw new IllegalArgumentException("badly formatted directory string");
+ }
+
+ String value = vTok.nextToken();
+ ASN1ObjectIdentifier oid = x500Style.attrNameToOID(attr.trim());
+
+ builder.addRDN(oid, unescape(value));
+ }
+ }
+
+ return builder.build().getRDNs();
+ }
+
+ private static String[] toValueArray(Vector values)
+ {
+ String[] tmp = new String[values.size()];
+
+ for (int i = 0; i != tmp.length; i++)
+ {
+ tmp[i] = (String)values.elementAt(i);
+ }
+
+ return tmp;
+ }
+
+ private static ASN1ObjectIdentifier[] toOIDArray(Vector oids)
+ {
+ ASN1ObjectIdentifier[] tmp = new ASN1ObjectIdentifier[oids.size()];
+
+ for (int i = 0; i != tmp.length; i++)
+ {
+ tmp[i] = (ASN1ObjectIdentifier)oids.elementAt(i);
+ }
+
+ return tmp;
+ }
+
+ public static String[] findAttrNamesForOID(
+ ASN1ObjectIdentifier oid,
+ Hashtable lookup)
+ {
+ int count = 0;
+ for (Enumeration en = lookup.elements(); en.hasMoreElements();)
+ {
+ if (oid.equals(en.nextElement()))
+ {
+ count++;
+ }
+ }
+
+ String[] aliases = new String[count];
+ count = 0;
+
+ for (Enumeration en = lookup.keys(); en.hasMoreElements();)
+ {
+ String key = (String)en.nextElement();
+ if (oid.equals(lookup.get(key)))
+ {
+ aliases[count++] = key;
+ }
+ }
+
+ return aliases;
+ }
+
+ public static ASN1ObjectIdentifier decodeAttrName(
+ String name,
+ Hashtable lookUp)
+ {
+ if (Strings.toUpperCase(name).startsWith("OID."))
+ {
+ return new ASN1ObjectIdentifier(name.substring(4));
+ }
+ else if (name.charAt(0) >= '0' && name.charAt(0) <= '9')
+ {
+ return new ASN1ObjectIdentifier(name);
+ }
+
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)lookUp.get(Strings.toLowerCase(name));
+ if (oid == null)
+ {
+ throw new IllegalArgumentException("Unknown object id - " + name + " - passed to distinguished name");
+ }
+
+ return oid;
+ }
+
+ public static ASN1Encodable valueFromHexString(
+ String str,
+ int off)
+ throws IOException
+ {
+ byte[] data = new byte[(str.length() - off) / 2];
+ for (int index = 0; index != data.length; index++)
+ {
+ char left = str.charAt((index * 2) + off);
+ char right = str.charAt((index * 2) + off + 1);
+
+ data[index] = (byte)((convertHex(left) << 4) | convertHex(right));
+ }
+
+ return ASN1Primitive.fromByteArray(data);
+ }
+
+ public static void appendRDN(
+ StringBuffer buf,
+ RDN rdn,
+ Hashtable oidSymbols)
+ {
+ if (rdn.isMultiValued())
+ {
+ AttributeTypeAndValue[] atv = rdn.getTypesAndValues();
+ boolean firstAtv = true;
+
+ for (int j = 0; j != atv.length; j++)
+ {
+ if (firstAtv)
+ {
+ firstAtv = false;
+ }
+ else
+ {
+ buf.append('+');
+ }
+
+ IETFUtils.appendTypeAndValue(buf, atv[j], oidSymbols);
+ }
+ }
+ else
+ {
+ IETFUtils.appendTypeAndValue(buf, rdn.getFirst(), oidSymbols);
+ }
+ }
+
+ public static void appendTypeAndValue(
+ StringBuffer buf,
+ AttributeTypeAndValue typeAndValue,
+ Hashtable oidSymbols)
+ {
+ String sym = (String)oidSymbols.get(typeAndValue.getType());
+
+ if (sym != null)
+ {
+ buf.append(sym);
+ }
+ else
+ {
+ buf.append(typeAndValue.getType().getId());
+ }
+
+ buf.append('=');
+
+ buf.append(valueToString(typeAndValue.getValue()));
+ }
+
+ public static String valueToString(ASN1Encodable value)
+ {
+ StringBuffer vBuf = new StringBuffer();
+
+ if (value instanceof ASN1String && !(value instanceof DERUniversalString))
+ {
+ String v = ((ASN1String)value).getString();
+ if (v.length() > 0 && v.charAt(0) == '#')
+ {
+ vBuf.append("\\" + v);
+ }
+ else
+ {
+ vBuf.append(v);
+ }
+ }
+ else
+ {
+ try
+ {
+ vBuf.append("#" + bytesToString(Hex.encode(value.toASN1Primitive().getEncoded(ASN1Encoding.DER))));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("Other value has no encoded form");
+ }
+ }
+
+ int end = vBuf.length();
+ int index = 0;
+
+ if (vBuf.length() >= 2 && vBuf.charAt(0) == '\\' && vBuf.charAt(1) == '#')
+ {
+ index += 2;
+ }
+
+ while (index != end)
+ {
+ if ((vBuf.charAt(index) == ',')
+ || (vBuf.charAt(index) == '"')
+ || (vBuf.charAt(index) == '\\')
+ || (vBuf.charAt(index) == '+')
+ || (vBuf.charAt(index) == '=')
+ || (vBuf.charAt(index) == '<')
+ || (vBuf.charAt(index) == '>')
+ || (vBuf.charAt(index) == ';'))
+ {
+ vBuf.insert(index, "\\");
+ index++;
+ end++;
+ }
+
+ index++;
+ }
+
+ int start = 0;
+ if (vBuf.length() > 0)
+ {
+ while (vBuf.length() > start && vBuf.charAt(start) == ' ')
+ {
+ vBuf.insert(start, "\\");
+ start += 2;
+ }
+ }
+
+ int endBuf = vBuf.length() - 1;
+
+ while (endBuf >= 0 && vBuf.charAt(endBuf) == ' ')
+ {
+ vBuf.insert(endBuf, '\\');
+ endBuf--;
+ }
+
+ return vBuf.toString();
+ }
+
+ private static String bytesToString(
+ byte[] data)
+ {
+ char[] cs = new char[data.length];
+
+ for (int i = 0; i != cs.length; i++)
+ {
+ cs[i] = (char)(data[i] & 0xff);
+ }
+
+ return new String(cs);
+ }
+
+ public static String canonicalize(String s)
+ {
+ String value = Strings.toLowerCase(s.trim());
+
+ if (value.length() > 0 && value.charAt(0) == '#')
+ {
+ ASN1Primitive obj = decodeObject(value);
+
+ if (obj instanceof ASN1String)
+ {
+ value = Strings.toLowerCase(((ASN1String)obj).getString().trim());
+ }
+ }
+
+ value = stripInternalSpaces(value);
+
+ return value;
+ }
+
+ private static ASN1Primitive decodeObject(String oValue)
+ {
+ try
+ {
+ return ASN1Primitive.fromByteArray(Hex.decode(oValue.substring(1)));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("unknown encoding in name: " + e);
+ }
+ }
+
+ public static String stripInternalSpaces(
+ String str)
+ {
+ StringBuffer res = new StringBuffer();
+
+ if (str.length() != 0)
+ {
+ char c1 = str.charAt(0);
+
+ res.append(c1);
+
+ for (int k = 1; k < str.length(); k++)
+ {
+ char c2 = str.charAt(k);
+ if (!(c1 == ' ' && c2 == ' '))
+ {
+ res.append(c2);
+ }
+ c1 = c2;
+ }
+ }
+
+ return res.toString();
+ }
+
+ public static boolean rDNAreEqual(RDN rdn1, RDN rdn2)
+ {
+ if (rdn1.isMultiValued())
+ {
+ if (rdn2.isMultiValued())
+ {
+ AttributeTypeAndValue[] atvs1 = rdn1.getTypesAndValues();
+ AttributeTypeAndValue[] atvs2 = rdn2.getTypesAndValues();
+
+ if (atvs1.length != atvs2.length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i != atvs1.length; i++)
+ {
+ if (!atvAreEqual(atvs1[i], atvs2[i]))
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (!rdn2.isMultiValued())
+ {
+ return atvAreEqual(rdn1.getFirst(), rdn2.getFirst());
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static boolean atvAreEqual(AttributeTypeAndValue atv1, AttributeTypeAndValue atv2)
+ {
+ if (atv1 == atv2)
+ {
+ return true;
+ }
+
+ if (atv1 == null)
+ {
+ return false;
+ }
+
+ if (atv2 == null)
+ {
+ return false;
+ }
+
+ ASN1ObjectIdentifier o1 = atv1.getType();
+ ASN1ObjectIdentifier o2 = atv2.getType();
+
+ if (!o1.equals(o2))
+ {
+ return false;
+ }
+
+ String v1 = IETFUtils.canonicalize(IETFUtils.valueToString(atv1.getValue()));
+ String v2 = IETFUtils.canonicalize(IETFUtils.valueToString(atv2.getValue()));
+
+ if (!v1.equals(v2))
+ {
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x500/style/RFC4519Style.java b/core/src/main/java/org/spongycastle/asn1/x500/style/RFC4519Style.java
new file mode 100644
index 00000000..83825e6c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x500/style/RFC4519Style.java
@@ -0,0 +1,248 @@
+package org.spongycastle.asn1.x500.style;
+
+import java.util.Hashtable;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.DERPrintableString;
+import org.spongycastle.asn1.x500.RDN;
+import org.spongycastle.asn1.x500.X500Name;
+import org.spongycastle.asn1.x500.X500NameStyle;
+
+public class RFC4519Style
+ extends AbstractX500NameStyle
+{
+ public static final ASN1ObjectIdentifier businessCategory = new ASN1ObjectIdentifier("2.5.4.15");
+ public static final ASN1ObjectIdentifier c = new ASN1ObjectIdentifier("2.5.4.6");
+ public static final ASN1ObjectIdentifier cn = new ASN1ObjectIdentifier("2.5.4.3");
+ public static final ASN1ObjectIdentifier dc = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.25");
+ public static final ASN1ObjectIdentifier description = new ASN1ObjectIdentifier("2.5.4.13");
+ public static final ASN1ObjectIdentifier destinationIndicator = new ASN1ObjectIdentifier("2.5.4.27");
+ public static final ASN1ObjectIdentifier distinguishedName = new ASN1ObjectIdentifier("2.5.4.49");
+ public static final ASN1ObjectIdentifier dnQualifier = new ASN1ObjectIdentifier("2.5.4.46");
+ public static final ASN1ObjectIdentifier enhancedSearchGuide = new ASN1ObjectIdentifier("2.5.4.47");
+ public static final ASN1ObjectIdentifier facsimileTelephoneNumber = new ASN1ObjectIdentifier("2.5.4.23");
+ public static final ASN1ObjectIdentifier generationQualifier = new ASN1ObjectIdentifier("2.5.4.44");
+ public static final ASN1ObjectIdentifier givenName = new ASN1ObjectIdentifier("2.5.4.42");
+ public static final ASN1ObjectIdentifier houseIdentifier = new ASN1ObjectIdentifier("2.5.4.51");
+ public static final ASN1ObjectIdentifier initials = new ASN1ObjectIdentifier("2.5.4.43");
+ public static final ASN1ObjectIdentifier internationalISDNNumber = new ASN1ObjectIdentifier("2.5.4.25");
+ public static final ASN1ObjectIdentifier l = new ASN1ObjectIdentifier("2.5.4.7");
+ public static final ASN1ObjectIdentifier member = new ASN1ObjectIdentifier("2.5.4.31");
+ public static final ASN1ObjectIdentifier name = new ASN1ObjectIdentifier("2.5.4.41");
+ public static final ASN1ObjectIdentifier o = new ASN1ObjectIdentifier("2.5.4.10");
+ public static final ASN1ObjectIdentifier ou = new ASN1ObjectIdentifier("2.5.4.11");
+ public static final ASN1ObjectIdentifier owner = new ASN1ObjectIdentifier("2.5.4.32");
+ public static final ASN1ObjectIdentifier physicalDeliveryOfficeName = new ASN1ObjectIdentifier("2.5.4.19");
+ public static final ASN1ObjectIdentifier postalAddress = new ASN1ObjectIdentifier("2.5.4.16");
+ public static final ASN1ObjectIdentifier postalCode = new ASN1ObjectIdentifier("2.5.4.17");
+ public static final ASN1ObjectIdentifier postOfficeBox = new ASN1ObjectIdentifier("2.5.4.18");
+ public static final ASN1ObjectIdentifier preferredDeliveryMethod = new ASN1ObjectIdentifier("2.5.4.28");
+ public static final ASN1ObjectIdentifier registeredAddress = new ASN1ObjectIdentifier("2.5.4.26");
+ public static final ASN1ObjectIdentifier roleOccupant = new ASN1ObjectIdentifier("2.5.4.33");
+ public static final ASN1ObjectIdentifier searchGuide = new ASN1ObjectIdentifier("2.5.4.14");
+ public static final ASN1ObjectIdentifier seeAlso = new ASN1ObjectIdentifier("2.5.4.34");
+ public static final ASN1ObjectIdentifier serialNumber = new ASN1ObjectIdentifier("2.5.4.5");
+ public static final ASN1ObjectIdentifier sn = new ASN1ObjectIdentifier("2.5.4.4");
+ public static final ASN1ObjectIdentifier st = new ASN1ObjectIdentifier("2.5.4.8");
+ public static final ASN1ObjectIdentifier street = new ASN1ObjectIdentifier("2.5.4.9");
+ public static final ASN1ObjectIdentifier telephoneNumber = new ASN1ObjectIdentifier("2.5.4.20");
+ public static final ASN1ObjectIdentifier teletexTerminalIdentifier = new ASN1ObjectIdentifier("2.5.4.22");
+ public static final ASN1ObjectIdentifier telexNumber = new ASN1ObjectIdentifier("2.5.4.21");
+ public static final ASN1ObjectIdentifier title = new ASN1ObjectIdentifier("2.5.4.12");
+ public static final ASN1ObjectIdentifier uid = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.1");
+ public static final ASN1ObjectIdentifier uniqueMember = new ASN1ObjectIdentifier("2.5.4.50");
+ public static final ASN1ObjectIdentifier userPassword = new ASN1ObjectIdentifier("2.5.4.35");
+ public static final ASN1ObjectIdentifier x121Address = new ASN1ObjectIdentifier("2.5.4.24");
+ public static final ASN1ObjectIdentifier x500UniqueIdentifier = new ASN1ObjectIdentifier("2.5.4.45");
+
+ /**
+ * default look up table translating OID values into their common symbols following
+ * the convention in RFC 2253 with a few extras
+ */
+ private static final Hashtable DefaultSymbols = new Hashtable();
+
+ /**
+ * look up table translating common symbols into their OIDS.
+ */
+ private static final Hashtable DefaultLookUp = new Hashtable();
+
+ static
+ {
+ DefaultSymbols.put(businessCategory, "businessCategory");
+ DefaultSymbols.put(c, "c");
+ DefaultSymbols.put(cn, "cn");
+ DefaultSymbols.put(dc, "dc");
+ DefaultSymbols.put(description, "description");
+ DefaultSymbols.put(destinationIndicator, "destinationIndicator");
+ DefaultSymbols.put(distinguishedName, "distinguishedName");
+ DefaultSymbols.put(dnQualifier, "dnQualifier");
+ DefaultSymbols.put(enhancedSearchGuide, "enhancedSearchGuide");
+ DefaultSymbols.put(facsimileTelephoneNumber, "facsimileTelephoneNumber");
+ DefaultSymbols.put(generationQualifier, "generationQualifier");
+ DefaultSymbols.put(givenName, "givenName");
+ DefaultSymbols.put(houseIdentifier, "houseIdentifier");
+ DefaultSymbols.put(initials, "initials");
+ DefaultSymbols.put(internationalISDNNumber, "internationalISDNNumber");
+ DefaultSymbols.put(l, "l");
+ DefaultSymbols.put(member, "member");
+ DefaultSymbols.put(name, "name");
+ DefaultSymbols.put(o, "o");
+ DefaultSymbols.put(ou, "ou");
+ DefaultSymbols.put(owner, "owner");
+ DefaultSymbols.put(physicalDeliveryOfficeName, "physicalDeliveryOfficeName");
+ DefaultSymbols.put(postalAddress, "postalAddress");
+ DefaultSymbols.put(postalCode, "postalCode");
+ DefaultSymbols.put(postOfficeBox, "postOfficeBox");
+ DefaultSymbols.put(preferredDeliveryMethod, "preferredDeliveryMethod");
+ DefaultSymbols.put(registeredAddress, "registeredAddress");
+ DefaultSymbols.put(roleOccupant, "roleOccupant");
+ DefaultSymbols.put(searchGuide, "searchGuide");
+ DefaultSymbols.put(seeAlso, "seeAlso");
+ DefaultSymbols.put(serialNumber, "serialNumber");
+ DefaultSymbols.put(sn, "sn");
+ DefaultSymbols.put(st, "st");
+ DefaultSymbols.put(street, "street");
+ DefaultSymbols.put(telephoneNumber, "telephoneNumber");
+ DefaultSymbols.put(teletexTerminalIdentifier, "teletexTerminalIdentifier");
+ DefaultSymbols.put(telexNumber, "telexNumber");
+ DefaultSymbols.put(title, "title");
+ DefaultSymbols.put(uid, "uid");
+ DefaultSymbols.put(uniqueMember, "uniqueMember");
+ DefaultSymbols.put(userPassword, "userPassword");
+ DefaultSymbols.put(x121Address, "x121Address");
+ DefaultSymbols.put(x500UniqueIdentifier, "x500UniqueIdentifier");
+
+ DefaultLookUp.put("businesscategory", businessCategory);
+ DefaultLookUp.put("c", c);
+ DefaultLookUp.put("cn", cn);
+ DefaultLookUp.put("dc", dc);
+ DefaultLookUp.put("description", description);
+ DefaultLookUp.put("destinationindicator", destinationIndicator);
+ DefaultLookUp.put("distinguishedname", distinguishedName);
+ DefaultLookUp.put("dnqualifier", dnQualifier);
+ DefaultLookUp.put("enhancedsearchguide", enhancedSearchGuide);
+ DefaultLookUp.put("facsimiletelephonenumber", facsimileTelephoneNumber);
+ DefaultLookUp.put("generationqualifier", generationQualifier);
+ DefaultLookUp.put("givenname", givenName);
+ DefaultLookUp.put("houseidentifier", houseIdentifier);
+ DefaultLookUp.put("initials", initials);
+ DefaultLookUp.put("internationalisdnnumber", internationalISDNNumber);
+ DefaultLookUp.put("l", l);
+ DefaultLookUp.put("member", member);
+ DefaultLookUp.put("name", name);
+ DefaultLookUp.put("o", o);
+ DefaultLookUp.put("ou", ou);
+ DefaultLookUp.put("owner", owner);
+ DefaultLookUp.put("physicaldeliveryofficename", physicalDeliveryOfficeName);
+ DefaultLookUp.put("postaladdress", postalAddress);
+ DefaultLookUp.put("postalcode", postalCode);
+ DefaultLookUp.put("postofficebox", postOfficeBox);
+ DefaultLookUp.put("preferreddeliverymethod", preferredDeliveryMethod);
+ DefaultLookUp.put("registeredaddress", registeredAddress);
+ DefaultLookUp.put("roleoccupant", roleOccupant);
+ DefaultLookUp.put("searchguide", searchGuide);
+ DefaultLookUp.put("seealso", seeAlso);
+ DefaultLookUp.put("serialnumber", serialNumber);
+ DefaultLookUp.put("sn", sn);
+ DefaultLookUp.put("st", st);
+ DefaultLookUp.put("street", street);
+ DefaultLookUp.put("telephonenumber", telephoneNumber);
+ DefaultLookUp.put("teletexterminalidentifier", teletexTerminalIdentifier);
+ DefaultLookUp.put("telexnumber", telexNumber);
+ DefaultLookUp.put("title", title);
+ DefaultLookUp.put("uid", uid);
+ DefaultLookUp.put("uniquemember", uniqueMember);
+ DefaultLookUp.put("userpassword", userPassword);
+ DefaultLookUp.put("x121address", x121Address);
+ DefaultLookUp.put("x500uniqueidentifier", x500UniqueIdentifier);
+
+ // 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);
+ }
+
+ protected ASN1Encodable encodeStringValue(ASN1ObjectIdentifier oid,
+ String value) {
+ if (oid.equals(dc))
+ {
+ return new DERIA5String(value);
+ }
+ else if (oid.equals(c) || oid.equals(serialNumber) || oid.equals(dnQualifier)
+ || oid.equals(telephoneNumber))
+ {
+ return new DERPrintableString(value);
+ }
+
+ return super.encodeStringValue(oid, value);
+ }
+
+ public String oidToDisplayName(ASN1ObjectIdentifier oid)
+ {
+ return (String)DefaultSymbols.get(oid);
+ }
+
+ public String[] oidToAttrNames(ASN1ObjectIdentifier oid)
+ {
+ return IETFUtils.findAttrNamesForOID(oid, defaultLookUp);
+ }
+
+ public ASN1ObjectIdentifier attrNameToOID(String attrName)
+ {
+ return IETFUtils.decodeAttrName(attrName, defaultLookUp);
+ }
+
+ // parse backwards
+ public RDN[] fromString(String dirName)
+ {
+ RDN[] tmp = IETFUtils.rDNsFromString(dirName, this);
+ RDN[] res = new RDN[tmp.length];
+
+ for (int i = 0; i != tmp.length; i++)
+ {
+ res[res.length - i - 1] = tmp[i];
+ }
+
+ return res;
+ }
+
+ // convert in reverse
+ public String toString(X500Name name)
+ {
+ StringBuffer buf = new StringBuffer();
+ boolean first = true;
+
+ RDN[] rdns = name.getRDNs();
+
+ for (int i = rdns.length - 1; i >= 0; i--)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ buf.append(',');
+ }
+
+ IETFUtils.appendRDN(buf, rdns[i], defaultSymbols);
+ }
+
+ return buf.toString();
+ }
+
+
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x500/style/X500NameTokenizer.java b/core/src/main/java/org/spongycastle/asn1/x500/style/X500NameTokenizer.java
new file mode 100644
index 00000000..65ce9865
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x500/style/X500NameTokenizer.java
@@ -0,0 +1,90 @@
+package org.spongycastle.asn1.x500.style;
+
+/**
+ * class for breaking up an X500 Name into it's component tokens, ala
+ * java.util.StringTokenizer. We need this class as some of the
+ * lightweight Java environment don't support classes like
+ * StringTokenizer.
+ */
+public class X500NameTokenizer
+{
+ private String value;
+ private int index;
+ private char separator;
+ private StringBuffer buf = new StringBuffer();
+
+ public X500NameTokenizer(
+ String oid)
+ {
+ this(oid, ',');
+ }
+
+ public X500NameTokenizer(
+ String oid,
+ char separator)
+ {
+ this.value = oid;
+ this.index = -1;
+ this.separator = separator;
+ }
+
+ public boolean hasMoreTokens()
+ {
+ return (index != value.length());
+ }
+
+ public String nextToken()
+ {
+ if (index == value.length())
+ {
+ return null;
+ }
+
+ int end = index + 1;
+ boolean quoted = false;
+ boolean escaped = false;
+
+ buf.setLength(0);
+
+ while (end != value.length())
+ {
+ char c = value.charAt(end);
+
+ if (c == '"')
+ {
+ if (!escaped)
+ {
+ quoted = !quoted;
+ }
+ buf.append(c);
+ escaped = false;
+ }
+ else
+ {
+ if (escaped || quoted)
+ {
+ buf.append(c);
+ escaped = false;
+ }
+ else if (c == '\\')
+ {
+ buf.append(c);
+ escaped = true;
+ }
+ else if (c == separator)
+ {
+ break;
+ }
+ else
+ {
+ buf.append(c);
+ }
+ }
+ end++;
+ }
+
+ index = end;
+
+ return buf.toString();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/AccessDescription.java b/core/src/main/java/org/spongycastle/asn1/x509/AccessDescription.java
new file mode 100644
index 00000000..29a57949
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/AccessDescription.java
@@ -0,0 +1,98 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * The AccessDescription object.
+ * <pre>
+ * AccessDescription ::= SEQUENCE {
+ * accessMethod OBJECT IDENTIFIER,
+ * accessLocation GeneralName }
+ * </pre>
+ */
+public class AccessDescription
+ extends ASN1Object
+{
+ public final static ASN1ObjectIdentifier id_ad_caIssuers = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.48.2");
+
+ public final static ASN1ObjectIdentifier id_ad_ocsp = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.48.1");
+
+ ASN1ObjectIdentifier accessMethod = null;
+ GeneralName accessLocation = null;
+
+ public static AccessDescription getInstance(
+ Object obj)
+ {
+ if (obj instanceof AccessDescription)
+ {
+ return (AccessDescription)obj;
+ }
+ else if (obj != null)
+ {
+ return new AccessDescription(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private AccessDescription(
+ ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("wrong number of elements in sequence");
+ }
+
+ accessMethod = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+ accessLocation = GeneralName.getInstance(seq.getObjectAt(1));
+ }
+
+ /**
+ * create an AccessDescription with the oid and location provided.
+ */
+ public AccessDescription(
+ ASN1ObjectIdentifier oid,
+ GeneralName location)
+ {
+ accessMethod = oid;
+ accessLocation = location;
+ }
+
+ /**
+ *
+ * @return the access method.
+ */
+ public ASN1ObjectIdentifier getAccessMethod()
+ {
+ return accessMethod;
+ }
+
+ /**
+ *
+ * @return the access location
+ */
+ public GeneralName getAccessLocation()
+ {
+ return accessLocation;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector accessDescription = new ASN1EncodableVector();
+
+ accessDescription.add(accessMethod);
+ accessDescription.add(accessLocation);
+
+ return new DERSequence(accessDescription);
+ }
+
+ public String toString()
+ {
+ return ("AccessDescription: Oid(" + this.accessMethod.getId() + ")");
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/AlgorithmIdentifier.java b/core/src/main/java/org/spongycastle/asn1/x509/AlgorithmIdentifier.java
new file mode 100644
index 00000000..f5797250
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/AlgorithmIdentifier.java
@@ -0,0 +1,148 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERNull;
+import org.spongycastle.asn1.DERSequence;
+
+public class AlgorithmIdentifier
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier objectId;
+ private ASN1Encodable parameters;
+ private boolean parametersDefined = false;
+
+ public static AlgorithmIdentifier getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static AlgorithmIdentifier getInstance(
+ Object obj)
+ {
+ if (obj== null || obj instanceof AlgorithmIdentifier)
+ {
+ return (AlgorithmIdentifier)obj;
+ }
+
+ // TODO: delete
+ if (obj instanceof ASN1ObjectIdentifier)
+ {
+ return new AlgorithmIdentifier((ASN1ObjectIdentifier)obj);
+ }
+
+ // TODO: delete
+ if (obj instanceof String)
+ {
+ return new AlgorithmIdentifier((String)obj);
+ }
+
+ return new AlgorithmIdentifier(ASN1Sequence.getInstance(obj));
+ }
+
+ public AlgorithmIdentifier(
+ ASN1ObjectIdentifier objectId)
+ {
+ this.objectId = objectId;
+ }
+
+ /**
+ * @deprecated use ASN1ObjectIdentifier
+ * @param objectId
+ */
+ public AlgorithmIdentifier(
+ String objectId)
+ {
+ this.objectId = new ASN1ObjectIdentifier(objectId);
+ }
+
+ public AlgorithmIdentifier(
+ ASN1ObjectIdentifier objectId,
+ ASN1Encodable parameters)
+ {
+ parametersDefined = true;
+ this.objectId = objectId;
+ this.parameters = parameters;
+ }
+
+ /**
+ * @deprecated use AlgorithmIdentifier.getInstance()
+ * @param seq
+ */
+ public AlgorithmIdentifier(
+ ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ objectId = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() == 2)
+ {
+ parametersDefined = true;
+ parameters = seq.getObjectAt(1);
+ }
+ else
+ {
+ parameters = null;
+ }
+ }
+
+ public ASN1ObjectIdentifier getAlgorithm()
+ {
+ return new ASN1ObjectIdentifier(objectId.getId());
+ }
+
+ /**
+ * @deprecated use getAlgorithm
+ * @return
+ */
+ public ASN1ObjectIdentifier getObjectId()
+ {
+ return objectId;
+ }
+
+ public ASN1Encodable getParameters()
+ {
+ return parameters;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(objectId);
+
+ if (parametersDefined)
+ {
+ if (parameters != null)
+ {
+ v.add(parameters);
+ }
+ else
+ {
+ v.add(DERNull.INSTANCE);
+ }
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/AttCertIssuer.java b/core/src/main/java/org/spongycastle/asn1/x509/AttCertIssuer.java
new file mode 100644
index 00000000..cb027fd1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/AttCertIssuer.java
@@ -0,0 +1,91 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERTaggedObject;
+
+public class AttCertIssuer
+ extends ASN1Object
+ implements ASN1Choice
+{
+ ASN1Encodable obj;
+ ASN1Primitive choiceObj;
+
+ public static AttCertIssuer getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof AttCertIssuer)
+ {
+ return (AttCertIssuer)obj;
+ }
+ else if (obj instanceof V2Form)
+ {
+ return new AttCertIssuer(V2Form.getInstance(obj));
+ }
+ else if (obj instanceof GeneralNames)
+ {
+ return new AttCertIssuer((GeneralNames)obj);
+ }
+ else if (obj instanceof ASN1TaggedObject)
+ {
+ return new AttCertIssuer(V2Form.getInstance((ASN1TaggedObject)obj, false));
+ }
+ else if (obj instanceof ASN1Sequence)
+ {
+ return new AttCertIssuer(GeneralNames.getInstance(obj));
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
+ }
+
+ public static AttCertIssuer getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject()); // must be explicitly tagged
+ }
+
+ /**
+ * Don't use this one if you are trying to be RFC 3281 compliant.
+ * Use it for v1 attribute certificates only.
+ *
+ * @param names our GeneralNames structure
+ */
+ public AttCertIssuer(
+ GeneralNames names)
+ {
+ obj = names;
+ choiceObj = obj.toASN1Primitive();
+ }
+
+ public AttCertIssuer(
+ V2Form v2Form)
+ {
+ obj = v2Form;
+ choiceObj = new DERTaggedObject(false, 0, obj);
+ }
+
+ public ASN1Encodable getIssuer()
+ {
+ return obj;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * AttCertIssuer ::= CHOICE {
+ * v1Form GeneralNames, -- MUST NOT be used in this
+ * -- profile
+ * v2Form [0] V2Form -- v2 only
+ * }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return choiceObj;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/AttCertValidityPeriod.java b/core/src/main/java/org/spongycastle/asn1/x509/AttCertValidityPeriod.java
new file mode 100644
index 00000000..eec4d634
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/AttCertValidityPeriod.java
@@ -0,0 +1,84 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class AttCertValidityPeriod
+ extends ASN1Object
+{
+ ASN1GeneralizedTime notBeforeTime;
+ ASN1GeneralizedTime notAfterTime;
+
+ public static AttCertValidityPeriod getInstance(
+ Object obj)
+ {
+ if (obj instanceof AttCertValidityPeriod)
+ {
+ return (AttCertValidityPeriod)obj;
+ }
+ else if (obj != null)
+ {
+ return new AttCertValidityPeriod(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private AttCertValidityPeriod(
+ ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ notBeforeTime = ASN1GeneralizedTime.getInstance(seq.getObjectAt(0));
+ notAfterTime = ASN1GeneralizedTime.getInstance(seq.getObjectAt(1));
+ }
+
+ /**
+ * @param notBeforeTime
+ * @param notAfterTime
+ */
+ public AttCertValidityPeriod(
+ ASN1GeneralizedTime notBeforeTime,
+ ASN1GeneralizedTime notAfterTime)
+ {
+ this.notBeforeTime = notBeforeTime;
+ this.notAfterTime = notAfterTime;
+ }
+
+ public ASN1GeneralizedTime getNotBeforeTime()
+ {
+ return notBeforeTime;
+ }
+
+ public ASN1GeneralizedTime getNotAfterTime()
+ {
+ return notAfterTime;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * AttCertValidityPeriod ::= SEQUENCE {
+ * notBeforeTime GeneralizedTime,
+ * notAfterTime GeneralizedTime
+ * }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(notBeforeTime);
+ v.add(notAfterTime);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/Attribute.java b/core/src/main/java/org/spongycastle/asn1/x509/Attribute.java
new file mode 100644
index 00000000..5a501e1f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/Attribute.java
@@ -0,0 +1,93 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.DERSequence;
+
+public class Attribute
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier attrType;
+ private ASN1Set attrValues;
+
+ /**
+ * return an Attribute object from the given object.
+ *
+ * @param o the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static Attribute getInstance(
+ Object o)
+ {
+ if (o instanceof Attribute)
+ {
+ return (Attribute)o;
+ }
+
+ if (o != null)
+ {
+ return new Attribute(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ private Attribute(
+ ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ attrType = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+ attrValues = ASN1Set.getInstance(seq.getObjectAt(1));
+ }
+
+ public Attribute(
+ ASN1ObjectIdentifier attrType,
+ ASN1Set attrValues)
+ {
+ this.attrType = attrType;
+ this.attrValues = attrValues;
+ }
+
+ public ASN1ObjectIdentifier getAttrType()
+ {
+ return new ASN1ObjectIdentifier(attrType.getId());
+ }
+
+ public ASN1Encodable[] getAttributeValues()
+ {
+ return attrValues.toArray();
+ }
+
+ public ASN1Set getAttrValues()
+ {
+ return attrValues;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * Attribute ::= SEQUENCE {
+ * attrType OBJECT IDENTIFIER,
+ * attrValues SET OF AttributeValue
+ * }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(attrType);
+ v.add(attrValues);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/AttributeCertificate.java b/core/src/main/java/org/spongycastle/asn1/x509/AttributeCertificate.java
new file mode 100644
index 00000000..7af85919
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/AttributeCertificate.java
@@ -0,0 +1,97 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+
+public class AttributeCertificate
+ extends ASN1Object
+{
+ AttributeCertificateInfo acinfo;
+ AlgorithmIdentifier signatureAlgorithm;
+ DERBitString signatureValue;
+
+ /**
+ * @param obj
+ * @return an AttributeCertificate object
+ */
+ public static AttributeCertificate getInstance(Object obj)
+ {
+ if (obj instanceof AttributeCertificate)
+ {
+ return (AttributeCertificate)obj;
+ }
+ else if (obj != null)
+ {
+ return new AttributeCertificate(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public AttributeCertificate(
+ AttributeCertificateInfo acinfo,
+ AlgorithmIdentifier signatureAlgorithm,
+ DERBitString signatureValue)
+ {
+ this.acinfo = acinfo;
+ this.signatureAlgorithm = signatureAlgorithm;
+ this.signatureValue = signatureValue;
+ }
+
+ /**
+ * @deprecated use getInstance() method.
+ */
+ public AttributeCertificate(
+ ASN1Sequence seq)
+ {
+ if (seq.size() != 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ this.acinfo = AttributeCertificateInfo.getInstance(seq.getObjectAt(0));
+ this.signatureAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
+ this.signatureValue = DERBitString.getInstance(seq.getObjectAt(2));
+ }
+
+ public AttributeCertificateInfo getAcinfo()
+ {
+ return acinfo;
+ }
+
+ public AlgorithmIdentifier getSignatureAlgorithm()
+ {
+ return signatureAlgorithm;
+ }
+
+ public DERBitString getSignatureValue()
+ {
+ return signatureValue;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * AttributeCertificate ::= SEQUENCE {
+ * acinfo AttributeCertificateInfo,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signatureValue BIT STRING
+ * }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(acinfo);
+ v.add(signatureAlgorithm);
+ v.add(signatureValue);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/AttributeCertificateInfo.java b/core/src/main/java/org/spongycastle/asn1/x509/AttributeCertificateInfo.java
new file mode 100644
index 00000000..33e3e86f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/AttributeCertificateInfo.java
@@ -0,0 +1,180 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+
+public class AttributeCertificateInfo
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private Holder holder;
+ private AttCertIssuer issuer;
+ private AlgorithmIdentifier signature;
+ private ASN1Integer serialNumber;
+ private AttCertValidityPeriod attrCertValidityPeriod;
+ private ASN1Sequence attributes;
+ private DERBitString issuerUniqueID;
+ private Extensions extensions;
+
+ public static AttributeCertificateInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static AttributeCertificateInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof AttributeCertificateInfo)
+ {
+ return (AttributeCertificateInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new AttributeCertificateInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private AttributeCertificateInfo(
+ ASN1Sequence seq)
+ {
+ if (seq.size() < 6 || seq.size() > 9)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ 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 = start + 6; i < seq.size(); i++)
+ {
+ ASN1Encodable obj = seq.getObjectAt(i);
+
+ if (obj instanceof DERBitString)
+ {
+ this.issuerUniqueID = DERBitString.getInstance(seq.getObjectAt(i));
+ }
+ else if (obj instanceof ASN1Sequence || obj instanceof Extensions)
+ {
+ this.extensions = Extensions.getInstance(seq.getObjectAt(i));
+ }
+ }
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public Holder getHolder()
+ {
+ return holder;
+ }
+
+ public AttCertIssuer getIssuer()
+ {
+ return issuer;
+ }
+
+ public AlgorithmIdentifier getSignature()
+ {
+ return signature;
+ }
+
+ public ASN1Integer getSerialNumber()
+ {
+ return serialNumber;
+ }
+
+ public AttCertValidityPeriod getAttrCertValidityPeriod()
+ {
+ return attrCertValidityPeriod;
+ }
+
+ public ASN1Sequence getAttributes()
+ {
+ return attributes;
+ }
+
+ public DERBitString getIssuerUniqueID()
+ {
+ return issuerUniqueID;
+ }
+
+ public Extensions getExtensions()
+ {
+ return extensions;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * AttributeCertificateInfo ::= SEQUENCE {
+ * version AttCertVersion -- version is v2,
+ * holder Holder,
+ * issuer AttCertIssuer,
+ * signature AlgorithmIdentifier,
+ * serialNumber CertificateSerialNumber,
+ * attrCertValidityPeriod AttCertValidityPeriod,
+ * attributes SEQUENCE OF Attribute,
+ * issuerUniqueID UniqueIdentifier OPTIONAL,
+ * extensions Extensions OPTIONAL
+ * }
+ *
+ * AttCertVersion ::= INTEGER { v2(1) }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (version.getValue().intValue() != 0)
+ {
+ v.add(version);
+ }
+ v.add(holder);
+ v.add(issuer);
+ v.add(signature);
+ v.add(serialNumber);
+ v.add(attrCertValidityPeriod);
+ v.add(attributes);
+
+ if (issuerUniqueID != null)
+ {
+ v.add(issuerUniqueID);
+ }
+
+ if (extensions != null)
+ {
+ v.add(extensions);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/AuthorityInformationAccess.java b/core/src/main/java/org/spongycastle/asn1/x509/AuthorityInformationAccess.java
new file mode 100644
index 00000000..2324f747
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/AuthorityInformationAccess.java
@@ -0,0 +1,104 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * The AuthorityInformationAccess object.
+ * <pre>
+ * id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 }
+ *
+ * AuthorityInfoAccessSyntax ::=
+ * SEQUENCE SIZE (1..MAX) OF AccessDescription
+ * AccessDescription ::= SEQUENCE {
+ * accessMethod OBJECT IDENTIFIER,
+ * accessLocation GeneralName }
+ *
+ * id-ad OBJECT IDENTIFIER ::= { id-pkix 48 }
+ * id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 }
+ * id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 }
+ * </pre>
+ */
+public class AuthorityInformationAccess
+ extends ASN1Object
+{
+ private AccessDescription[] descriptions;
+
+ public static AuthorityInformationAccess getInstance(
+ Object obj)
+ {
+ if (obj instanceof AuthorityInformationAccess)
+ {
+ return (AuthorityInformationAccess)obj;
+ }
+
+ if (obj != null)
+ {
+ return new AuthorityInformationAccess(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private AuthorityInformationAccess(
+ ASN1Sequence seq)
+ {
+ if (seq.size() < 1)
+ {
+ throw new IllegalArgumentException("sequence may not be empty");
+ }
+
+ descriptions = new AccessDescription[seq.size()];
+
+ for (int i = 0; i != seq.size(); i++)
+ {
+ descriptions[i] = AccessDescription.getInstance(seq.getObjectAt(i));
+ }
+ }
+
+ public AuthorityInformationAccess(
+ AccessDescription description)
+ {
+ this.descriptions = new AccessDescription[]{ description };
+ }
+
+ /**
+ * create an AuthorityInformationAccess with the oid and location provided.
+ */
+ public AuthorityInformationAccess(
+ ASN1ObjectIdentifier oid,
+ GeneralName location)
+ {
+ this(new AccessDescription(oid, location));
+ }
+
+ /**
+ *
+ * @return the access descriptions contained in this object.
+ */
+ public AccessDescription[] getAccessDescriptions()
+ {
+ return descriptions;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+
+ for (int i = 0; i != descriptions.length; i++)
+ {
+ vec.add(descriptions[i]);
+ }
+
+ return new DERSequence(vec);
+ }
+
+ public String toString()
+ {
+ return ("AuthorityInformationAccess: Oid(" + this.descriptions[0].getAccessMethod().getId() + ")");
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/AuthorityKeyIdentifier.java b/core/src/main/java/org/spongycastle/asn1/x509/AuthorityKeyIdentifier.java
new file mode 100644
index 00000000..5178e3b8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/AuthorityKeyIdentifier.java
@@ -0,0 +1,229 @@
+package org.spongycastle.asn1.x509;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA1Digest;
+
+/**
+ * The AuthorityKeyIdentifier object.
+ * <pre>
+ * id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 }
+ *
+ * AuthorityKeyIdentifier ::= SEQUENCE {
+ * keyIdentifier [0] IMPLICIT KeyIdentifier OPTIONAL,
+ * authorityCertIssuer [1] IMPLICIT GeneralNames OPTIONAL,
+ * authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL }
+ *
+ * KeyIdentifier ::= OCTET STRING
+ * </pre>
+ *
+ */
+public class AuthorityKeyIdentifier
+ extends ASN1Object
+{
+ ASN1OctetString keyidentifier=null;
+ GeneralNames certissuer=null;
+ ASN1Integer certserno=null;
+
+ public static AuthorityKeyIdentifier getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static AuthorityKeyIdentifier getInstance(
+ Object obj)
+ {
+ if (obj instanceof AuthorityKeyIdentifier)
+ {
+ return (AuthorityKeyIdentifier)obj;
+ }
+ if (obj != null)
+ {
+ return new AuthorityKeyIdentifier(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static AuthorityKeyIdentifier fromExtensions(Extensions extensions)
+ {
+ return AuthorityKeyIdentifier.getInstance(extensions.getExtensionParsedValue(Extension.authorityKeyIdentifier));
+ }
+
+ protected AuthorityKeyIdentifier(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ ASN1TaggedObject o = DERTaggedObject.getInstance(e.nextElement());
+
+ switch (o.getTagNo())
+ {
+ case 0:
+ this.keyidentifier = ASN1OctetString.getInstance(o, false);
+ break;
+ case 1:
+ this.certissuer = GeneralNames.getInstance(o, false);
+ break;
+ case 2:
+ this.certserno = ASN1Integer.getInstance(o, false);
+ break;
+ default:
+ throw new IllegalArgumentException("illegal tag");
+ }
+ }
+ }
+
+ /**
+ *
+ * Calulates the keyidentifier using a SHA1 hash over the BIT STRING
+ * from SubjectPublicKeyInfo as defined in RFC2459.
+ *
+ * Example of making a AuthorityKeyIdentifier:
+ * <pre>
+ * SubjectPublicKeyInfo apki = new SubjectPublicKeyInfo((ASN1Sequence)new ASN1InputStream(
+ * publicKey.getEncoded()).readObject());
+ * AuthorityKeyIdentifier aki = new AuthorityKeyIdentifier(apki);
+ * </pre>
+ * @deprecated create the extension using org.spongycastle.cert.X509ExtensionUtils
+ **/
+ public AuthorityKeyIdentifier(
+ SubjectPublicKeyInfo spki)
+ {
+ Digest digest = new SHA1Digest();
+ byte[] resBuf = new byte[digest.getDigestSize()];
+
+ byte[] bytes = spki.getPublicKeyData().getBytes();
+ digest.update(bytes, 0, bytes.length);
+ digest.doFinal(resBuf, 0);
+ this.keyidentifier = new DEROctetString(resBuf);
+ }
+
+ /**
+ * create an AuthorityKeyIdentifier with the GeneralNames tag and
+ * the serial number provided as well.
+ * @deprecated create the extension using org.spongycastle.cert.X509ExtensionUtils
+ */
+ public AuthorityKeyIdentifier(
+ SubjectPublicKeyInfo spki,
+ GeneralNames name,
+ BigInteger serialNumber)
+ {
+ Digest digest = new SHA1Digest();
+ byte[] resBuf = new byte[digest.getDigestSize()];
+
+ byte[] bytes = spki.getPublicKeyData().getBytes();
+ digest.update(bytes, 0, bytes.length);
+ digest.doFinal(resBuf, 0);
+
+ this.keyidentifier = new DEROctetString(resBuf);
+ this.certissuer = GeneralNames.getInstance(name.toASN1Primitive());
+ this.certserno = new ASN1Integer(serialNumber);
+ }
+
+ /**
+ * create an AuthorityKeyIdentifier with the GeneralNames tag and
+ * the serial number provided.
+ */
+ public AuthorityKeyIdentifier(
+ GeneralNames name,
+ BigInteger serialNumber)
+ {
+ this((byte[])null, name, serialNumber);
+ }
+
+ /**
+ * create an AuthorityKeyIdentifier with a precomputed key identifier
+ */
+ public AuthorityKeyIdentifier(
+ byte[] keyIdentifier)
+ {
+ this(keyIdentifier, null, null);
+ }
+
+ /**
+ * create an AuthorityKeyIdentifier with a precomputed key identifier
+ * and the GeneralNames tag and the serial number provided as well.
+ */
+ public AuthorityKeyIdentifier(
+ byte[] keyIdentifier,
+ GeneralNames name,
+ BigInteger serialNumber)
+ {
+ this.keyidentifier = (keyIdentifier != null) ? new DEROctetString(keyIdentifier) : null;
+ this.certissuer = name;
+ this.certserno = (serialNumber != null) ? new ASN1Integer(serialNumber) : null;
+ }
+
+ public byte[] getKeyIdentifier()
+ {
+ if (keyidentifier != null)
+ {
+ return keyidentifier.getOctets();
+ }
+
+ return null;
+ }
+
+ public GeneralNames getAuthorityCertIssuer()
+ {
+ return certissuer;
+ }
+
+ public BigInteger getAuthorityCertSerialNumber()
+ {
+ if (certserno != null)
+ {
+ return certserno.getValue();
+ }
+
+ return null;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (keyidentifier != null)
+ {
+ v.add(new DERTaggedObject(false, 0, keyidentifier));
+ }
+
+ if (certissuer != null)
+ {
+ v.add(new DERTaggedObject(false, 1, certissuer));
+ }
+
+ if (certserno != null)
+ {
+ v.add(new DERTaggedObject(false, 2, certserno));
+ }
+
+
+ return new DERSequence(v);
+ }
+
+ public String toString()
+ {
+ return ("AuthorityKeyIdentifier: KeyID(" + this.keyidentifier.getOctets() + ")");
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/BasicConstraints.java b/core/src/main/java/org/spongycastle/asn1/x509/BasicConstraints.java
new file mode 100644
index 00000000..32f81cc9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/BasicConstraints.java
@@ -0,0 +1,163 @@
+package org.spongycastle.asn1.x509;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1Boolean;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+
+public class BasicConstraints
+ extends ASN1Object
+{
+ ASN1Boolean cA = ASN1Boolean.getInstance(false);
+ ASN1Integer pathLenConstraint = null;
+
+ public static BasicConstraints getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static BasicConstraints getInstance(
+ Object obj)
+ {
+ if (obj instanceof BasicConstraints)
+ {
+ return (BasicConstraints)obj;
+ }
+ if (obj instanceof X509Extension)
+ {
+ return getInstance(X509Extension.convertValueToObject((X509Extension)obj));
+ }
+ if (obj != null)
+ {
+ return new BasicConstraints(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static BasicConstraints fromExtensions(Extensions extensions)
+ {
+ return BasicConstraints.getInstance(extensions.getExtensionParsedValue(Extension.basicConstraints));
+ }
+
+ private BasicConstraints(
+ ASN1Sequence seq)
+ {
+ if (seq.size() == 0)
+ {
+ this.cA = null;
+ this.pathLenConstraint = null;
+ }
+ else
+ {
+ if (seq.getObjectAt(0) instanceof ASN1Boolean)
+ {
+ this.cA = ASN1Boolean.getInstance(seq.getObjectAt(0));
+ }
+ else
+ {
+ this.cA = null;
+ this.pathLenConstraint = ASN1Integer.getInstance(seq.getObjectAt(0));
+ }
+ if (seq.size() > 1)
+ {
+ if (this.cA != null)
+ {
+ this.pathLenConstraint = ASN1Integer.getInstance(seq.getObjectAt(1));
+ }
+ else
+ {
+ throw new IllegalArgumentException("wrong sequence in constructor");
+ }
+ }
+ }
+ }
+
+ public BasicConstraints(
+ boolean cA)
+ {
+ if (cA)
+ {
+ this.cA = ASN1Boolean.getInstance(true);
+ }
+ else
+ {
+ this.cA = null;
+ }
+ this.pathLenConstraint = null;
+ }
+
+ /**
+ * create a cA=true object for the given path length constraint.
+ *
+ * @param pathLenConstraint
+ */
+ public BasicConstraints(
+ int pathLenConstraint)
+ {
+ this.cA = ASN1Boolean.getInstance(true);
+ this.pathLenConstraint = new ASN1Integer(pathLenConstraint);
+ }
+
+ public boolean isCA()
+ {
+ return (cA != null) && cA.isTrue();
+ }
+
+ public BigInteger getPathLenConstraint()
+ {
+ if (pathLenConstraint != null)
+ {
+ return pathLenConstraint.getValue();
+ }
+
+ return null;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * BasicConstraints := SEQUENCE {
+ * cA BOOLEAN DEFAULT FALSE,
+ * pathLenConstraint INTEGER (0..MAX) OPTIONAL
+ * }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (cA != null)
+ {
+ v.add(cA);
+ }
+
+ if (pathLenConstraint != null) // yes some people actually do this when cA is false...
+ {
+ v.add(pathLenConstraint);
+ }
+
+ return new DERSequence(v);
+ }
+
+ public String toString()
+ {
+ if (pathLenConstraint == null)
+ {
+ if (cA == null)
+ {
+ return "BasicConstraints: isCa(false)";
+ }
+ return "BasicConstraints: isCa(" + this.isCA() + ")";
+ }
+ return "BasicConstraints: isCa(" + this.isCA() + "), pathLenConstraint = " + pathLenConstraint.getValue();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/CRLDistPoint.java b/core/src/main/java/org/spongycastle/asn1/x509/CRLDistPoint.java
new file mode 100644
index 00000000..739e98b5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/CRLDistPoint.java
@@ -0,0 +1,100 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+
+public class CRLDistPoint
+ extends ASN1Object
+{
+ ASN1Sequence seq = null;
+
+ public static CRLDistPoint getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static CRLDistPoint getInstance(
+ Object obj)
+ {
+ if (obj instanceof CRLDistPoint)
+ {
+ return (CRLDistPoint)obj;
+ }
+ else if (obj != null)
+ {
+ return new CRLDistPoint(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private CRLDistPoint(
+ ASN1Sequence seq)
+ {
+ this.seq = seq;
+ }
+
+ public CRLDistPoint(
+ DistributionPoint[] points)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ for (int i = 0; i != points.length; i++)
+ {
+ v.add(points[i]);
+ }
+
+ seq = new DERSequence(v);
+ }
+
+ /**
+ * Return the distribution points making up the sequence.
+ *
+ * @return DistributionPoint[]
+ */
+ public DistributionPoint[] getDistributionPoints()
+ {
+ DistributionPoint[] dp = new DistributionPoint[seq.size()];
+
+ for (int i = 0; i != seq.size(); i++)
+ {
+ dp[i] = DistributionPoint.getInstance(seq.getObjectAt(i));
+ }
+
+ return dp;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * CRLDistPoint ::= SEQUENCE SIZE {1..MAX} OF DistributionPoint
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return seq;
+ }
+
+ public String toString()
+ {
+ StringBuffer buf = new StringBuffer();
+ String sep = System.getProperty("line.separator");
+
+ buf.append("CRLDistPoint:");
+ buf.append(sep);
+ DistributionPoint dp[] = getDistributionPoints();
+ for (int i = 0; i != dp.length; i++)
+ {
+ buf.append(" ");
+ buf.append(dp[i]);
+ buf.append(sep);
+ }
+ return buf.toString();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/CRLNumber.java b/core/src/main/java/org/spongycastle/asn1/x509/CRLNumber.java
new file mode 100644
index 00000000..7699fde5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/CRLNumber.java
@@ -0,0 +1,54 @@
+package org.spongycastle.asn1.x509;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+
+/**
+ * The CRLNumber object.
+ * <pre>
+ * CRLNumber::= INTEGER(0..MAX)
+ * </pre>
+ */
+public class CRLNumber
+ extends ASN1Object
+{
+ private BigInteger number;
+
+ public CRLNumber(
+ BigInteger number)
+ {
+ this.number = number;
+ }
+
+ public BigInteger getCRLNumber()
+ {
+ return number;
+ }
+
+ public String toString()
+ {
+ return "CRLNumber: " + getCRLNumber();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new ASN1Integer(number);
+ }
+
+ public static CRLNumber getInstance(Object o)
+ {
+ if (o instanceof CRLNumber)
+ {
+ return (CRLNumber)o;
+ }
+ else if (o != null)
+ {
+ return new CRLNumber(ASN1Integer.getInstance(o).getValue());
+ }
+
+ return null;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/CRLReason.java b/core/src/main/java/org/spongycastle/asn1/x509/CRLReason.java
new file mode 100644
index 00000000..c1071699
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/CRLReason.java
@@ -0,0 +1,151 @@
+package org.spongycastle.asn1.x509;
+
+import java.math.BigInteger;
+import java.util.Hashtable;
+
+import org.spongycastle.asn1.ASN1Enumerated;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.util.Integers;
+
+/**
+ * The CRLReason enumeration.
+ * <pre>
+ * CRLReason ::= ENUMERATED {
+ * unspecified (0),
+ * keyCompromise (1),
+ * cACompromise (2),
+ * affiliationChanged (3),
+ * superseded (4),
+ * cessationOfOperation (5),
+ * certificateHold (6),
+ * removeFromCRL (8),
+ * privilegeWithdrawn (9),
+ * aACompromise (10)
+ * }
+ * </pre>
+ */
+public class CRLReason
+ extends ASN1Object
+{
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int UNSPECIFIED = 0;
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int KEY_COMPROMISE = 1;
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int CA_COMPROMISE = 2;
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int AFFILIATION_CHANGED = 3;
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int SUPERSEDED = 4;
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int CESSATION_OF_OPERATION = 5;
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int CERTIFICATE_HOLD = 6;
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int REMOVE_FROM_CRL = 8;
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int PRIVILEGE_WITHDRAWN = 9;
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int AA_COMPROMISE = 10;
+
+ public static final int unspecified = 0;
+ public static final int keyCompromise = 1;
+ public static final int cACompromise = 2;
+ public static final int affiliationChanged = 3;
+ public static final int superseded = 4;
+ public static final int cessationOfOperation = 5;
+ public static final int certificateHold = 6;
+ // 7 -> unknown
+ public static final int removeFromCRL = 8;
+ public static final int privilegeWithdrawn = 9;
+ public static final int aACompromise = 10;
+
+ private static final String[] reasonString =
+ {
+ "unspecified", "keyCompromise", "cACompromise", "affiliationChanged",
+ "superseded", "cessationOfOperation", "certificateHold", "unknown",
+ "removeFromCRL", "privilegeWithdrawn", "aACompromise"
+ };
+
+ private static final Hashtable table = new Hashtable();
+
+ private ASN1Enumerated value;
+
+ public static CRLReason getInstance(Object o)
+ {
+ if (o instanceof CRLReason)
+ {
+ return (CRLReason)o;
+ }
+ else if (o != null)
+ {
+ return lookup(ASN1Enumerated.getInstance(o).getValue().intValue());
+ }
+
+ return null;
+ }
+
+ private CRLReason(
+ int reason)
+ {
+ value = new ASN1Enumerated(reason);
+ }
+
+ public String toString()
+ {
+ String str;
+ int reason = getValue().intValue();
+ if (reason < 0 || reason > 10)
+ {
+ str = "invalid";
+ }
+ else
+ {
+ str = reasonString[reason];
+ }
+ return "CRLReason: " + str;
+ }
+
+ public BigInteger getValue()
+ {
+ return value.getValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return value;
+ }
+
+ public static CRLReason lookup(int value)
+ {
+ Integer idx = Integers.valueOf(value);
+
+ if (!table.containsKey(idx))
+ {
+ table.put(idx, new CRLReason(value));
+ }
+
+ return (CRLReason)table.get(idx);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/CertPolicyId.java b/core/src/main/java/org/spongycastle/asn1/x509/CertPolicyId.java
new file mode 100644
index 00000000..142b83e7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/CertPolicyId.java
@@ -0,0 +1,57 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+
+
+/**
+ * CertPolicyId, used in the CertificatePolicies and PolicyMappings
+ * X509V3 Extensions.
+ *
+ * <pre>
+ * CertPolicyId ::= OBJECT IDENTIFIER
+ * </pre>
+ */
+/**
+ * CertPolicyId, used in the CertificatePolicies and PolicyMappings
+ * X509V3 Extensions.
+ *
+ * <pre>
+ * CertPolicyId ::= OBJECT IDENTIFIER
+ * </pre>
+ */
+public class CertPolicyId
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier id;
+
+ private CertPolicyId(ASN1ObjectIdentifier id)
+ {
+ this.id = id;
+ }
+
+ public static CertPolicyId getInstance(Object o)
+ {
+ if (o instanceof CertPolicyId)
+ {
+ return (CertPolicyId)o;
+ }
+ else if (o != null)
+ {
+ return new CertPolicyId(ASN1ObjectIdentifier.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public String getId()
+ {
+ return id.getId();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return id;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/Certificate.java b/core/src/main/java/org/spongycastle/asn1/x509/Certificate.java
new file mode 100644
index 00000000..8d1b69f2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/Certificate.java
@@ -0,0 +1,131 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.x500.X500Name;
+
+/**
+ * an X509Certificate structure.
+ * <pre>
+ * Certificate ::= SEQUENCE {
+ * tbsCertificate TBSCertificate,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING
+ * }
+ * </pre>
+ */
+public class Certificate
+ extends ASN1Object
+{
+ ASN1Sequence seq;
+ TBSCertificate tbsCert;
+ AlgorithmIdentifier sigAlgId;
+ DERBitString sig;
+
+ public static Certificate getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static Certificate getInstance(
+ Object obj)
+ {
+ if (obj instanceof Certificate)
+ {
+ return (Certificate)obj;
+ }
+ else if (obj != null)
+ {
+ return new Certificate(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private Certificate(
+ ASN1Sequence seq)
+ {
+ this.seq = seq;
+
+ //
+ // correct x509 certficate
+ //
+ if (seq.size() == 3)
+ {
+ tbsCert = TBSCertificate.getInstance(seq.getObjectAt(0));
+ sigAlgId = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
+
+ sig = DERBitString.getInstance(seq.getObjectAt(2));
+ }
+ else
+ {
+ throw new IllegalArgumentException("sequence wrong size for a certificate");
+ }
+ }
+
+ public TBSCertificate getTBSCertificate()
+ {
+ return tbsCert;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return tbsCert.getVersion();
+ }
+
+ public int getVersionNumber()
+ {
+ return tbsCert.getVersionNumber();
+ }
+
+ public ASN1Integer getSerialNumber()
+ {
+ return tbsCert.getSerialNumber();
+ }
+
+ public X500Name getIssuer()
+ {
+ return tbsCert.getIssuer();
+ }
+
+ public Time getStartDate()
+ {
+ return tbsCert.getStartDate();
+ }
+
+ public Time getEndDate()
+ {
+ return tbsCert.getEndDate();
+ }
+
+ public X500Name getSubject()
+ {
+ return tbsCert.getSubject();
+ }
+
+ public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
+ {
+ return tbsCert.getSubjectPublicKeyInfo();
+ }
+
+ public AlgorithmIdentifier getSignatureAlgorithm()
+ {
+ return sigAlgId;
+ }
+
+ public DERBitString getSignature()
+ {
+ return sig;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return seq;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/CertificateList.java b/core/src/main/java/org/spongycastle/asn1/x509/CertificateList.java
new file mode 100644
index 00000000..5d068198
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/CertificateList.java
@@ -0,0 +1,144 @@
+
+package org.spongycastle.asn1.x509;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x500.X500Name;
+
+/**
+ * PKIX RFC-2459
+ *
+ * The X.509 v2 CRL syntax is as follows. For signature calculation,
+ * the data that is to be signed is ASN.1 DER encoded.
+ *
+ * <pre>
+ * CertificateList ::= SEQUENCE {
+ * tbsCertList TBSCertList,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signatureValue BIT STRING }
+ * </pre>
+ */
+public class CertificateList
+ extends ASN1Object
+{
+ TBSCertList tbsCertList;
+ AlgorithmIdentifier sigAlgId;
+ DERBitString sig;
+ boolean isHashCodeSet = false;
+ int hashCodeValue;
+
+ public static CertificateList getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static CertificateList getInstance(
+ Object obj)
+ {
+ if (obj instanceof CertificateList)
+ {
+ return (CertificateList)obj;
+ }
+ else if (obj != null)
+ {
+ return new CertificateList(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * @deprecated use getInstance() method.
+ * @param seq
+ */
+ public CertificateList(
+ ASN1Sequence seq)
+ {
+ if (seq.size() == 3)
+ {
+ tbsCertList = TBSCertList.getInstance(seq.getObjectAt(0));
+ sigAlgId = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
+ sig = DERBitString.getInstance(seq.getObjectAt(2));
+ }
+ else
+ {
+ throw new IllegalArgumentException("sequence wrong size for CertificateList");
+ }
+ }
+
+ public TBSCertList getTBSCertList()
+ {
+ return tbsCertList;
+ }
+
+ public TBSCertList.CRLEntry[] getRevokedCertificates()
+ {
+ return tbsCertList.getRevokedCertificates();
+ }
+
+ public Enumeration getRevokedCertificateEnumeration()
+ {
+ return tbsCertList.getRevokedCertificateEnumeration();
+ }
+
+ public AlgorithmIdentifier getSignatureAlgorithm()
+ {
+ return sigAlgId;
+ }
+
+ public DERBitString getSignature()
+ {
+ return sig;
+ }
+
+ public int getVersionNumber()
+ {
+ return tbsCertList.getVersionNumber();
+ }
+
+ public X500Name getIssuer()
+ {
+ return tbsCertList.getIssuer();
+ }
+
+ public Time getThisUpdate()
+ {
+ return tbsCertList.getThisUpdate();
+ }
+
+ public Time getNextUpdate()
+ {
+ return tbsCertList.getNextUpdate();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(tbsCertList);
+ v.add(sigAlgId);
+ v.add(sig);
+
+ return new DERSequence(v);
+ }
+
+ public int hashCode()
+ {
+ if (!isHashCodeSet)
+ {
+ hashCodeValue = super.hashCode();
+ isHashCodeSet = true;
+ }
+
+ return hashCodeValue;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/CertificatePair.java b/core/src/main/java/org/spongycastle/asn1/x509/CertificatePair.java
new file mode 100644
index 00000000..976473fd
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/CertificatePair.java
@@ -0,0 +1,168 @@
+package org.spongycastle.asn1.x509;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+/**
+ * This class helps to support crossCerfificatePairs in a LDAP directory
+ * according RFC 2587
+ *
+ * <pre>
+ * crossCertificatePairATTRIBUTE::={
+ * WITH SYNTAX CertificatePair
+ * EQUALITY MATCHING RULE certificatePairExactMatch
+ * ID joint-iso-ccitt(2) ds(5) attributeType(4) crossCertificatePair(40)}
+ * </pre>
+ *
+ * <blockquote> The forward elements of the crossCertificatePair attribute of a
+ * CA's directory entry shall be used to store all, except self-issued
+ * certificates issued to this CA. Optionally, the reverse elements of the
+ * crossCertificatePair attribute, of a CA's directory entry may contain a
+ * subset of certificates issued by this CA to other CAs. When both the forward
+ * and the reverse elements are present in a single attribute value, issuer name
+ * in one certificate shall match the subject name in the other and vice versa,
+ * and the subject public key in one certificate shall be capable of verifying
+ * the digital signature on the other certificate and vice versa.
+ *
+ * When a reverse element is present, the forward element value and the reverse
+ * element value need not be stored in the same attribute value; in other words,
+ * they can be stored in either a single attribute value or two attribute
+ * values. </blockquote>
+ *
+ * <pre>
+ * CertificatePair ::= SEQUENCE {
+ * forward [0] Certificate OPTIONAL,
+ * reverse [1] Certificate OPTIONAL,
+ * -- at least one of the pair shall be present -- }
+ * </pre>
+ */
+public class CertificatePair
+ extends ASN1Object
+{
+ private Certificate forward;
+
+ private Certificate reverse;
+
+ public static CertificatePair getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof CertificatePair)
+ {
+ return (CertificatePair)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new CertificatePair((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ * <p/>
+ * The sequence is of type CertificatePair:
+ * <p/>
+ * <pre>
+ * CertificatePair ::= SEQUENCE {
+ * forward [0] Certificate OPTIONAL,
+ * reverse [1] Certificate OPTIONAL,
+ * -- at least one of the pair shall be present -- }
+ * </pre>
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private CertificatePair(ASN1Sequence seq)
+ {
+ if (seq.size() != 1 && seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ ASN1TaggedObject o = ASN1TaggedObject.getInstance(e.nextElement());
+ if (o.getTagNo() == 0)
+ {
+ forward = Certificate.getInstance(o, true);
+ }
+ else if (o.getTagNo() == 1)
+ {
+ reverse = Certificate.getInstance(o, true);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad tag number: "
+ + o.getTagNo());
+ }
+ }
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param forward Certificates issued to this CA.
+ * @param reverse Certificates issued by this CA to other CAs.
+ */
+ public CertificatePair(Certificate forward, Certificate reverse)
+ {
+ this.forward = forward;
+ this.reverse = reverse;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <p>
+ * Returns:
+ * <pre>
+ * CertificatePair ::= SEQUENCE {
+ * forward [0] Certificate OPTIONAL,
+ * reverse [1] Certificate OPTIONAL,
+ * -- at least one of the pair shall be present -- }
+ * </pre>
+ *
+ * @return a ASN1Primitive
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+
+ if (forward != null)
+ {
+ vec.add(new DERTaggedObject(0, forward));
+ }
+ if (reverse != null)
+ {
+ vec.add(new DERTaggedObject(1, reverse));
+ }
+
+ return new DERSequence(vec);
+ }
+
+ /**
+ * @return Returns the forward.
+ */
+ public Certificate getForward()
+ {
+ return forward;
+ }
+
+ /**
+ * @return Returns the reverse.
+ */
+ public Certificate getReverse()
+ {
+ return reverse;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/CertificatePolicies.java b/core/src/main/java/org/spongycastle/asn1/x509/CertificatePolicies.java
new file mode 100644
index 00000000..d8710ae7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/CertificatePolicies.java
@@ -0,0 +1,124 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+
+public class CertificatePolicies
+ extends ASN1Object
+{
+ private final PolicyInformation[] policyInformation;
+
+ public static CertificatePolicies getInstance(
+ Object obj)
+ {
+ if (obj instanceof CertificatePolicies)
+ {
+ return (CertificatePolicies)obj;
+ }
+
+ if (obj != null)
+ {
+ return new CertificatePolicies(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static CertificatePolicies getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * 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.
+ */
+ public CertificatePolicies(
+ PolicyInformation name)
+ {
+ this.policyInformation = new PolicyInformation[] { name };
+ }
+
+ public CertificatePolicies(
+ PolicyInformation[] policyInformation)
+ {
+ this.policyInformation = policyInformation;
+ }
+
+ private CertificatePolicies(
+ ASN1Sequence seq)
+ {
+ this.policyInformation = new PolicyInformation[seq.size()];
+
+ for (int i = 0; i != seq.size(); i++)
+ {
+ policyInformation[i] = PolicyInformation.getInstance(seq.getObjectAt(i));
+ }
+ }
+
+ public PolicyInformation[] getPolicyInformation()
+ {
+ PolicyInformation[] tmp = new PolicyInformation[policyInformation.length];
+
+ System.arraycopy(policyInformation, 0, tmp, 0, policyInformation.length);
+
+ 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>
+ * CertificatePolicies ::= SEQUENCE SIZE {1..MAX} OF PolicyInformation
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERSequence(policyInformation);
+ }
+
+ public String toString()
+ {
+ String p = null;
+ for (int i = 0; i < policyInformation.length; i++)
+ {
+ if (p != null)
+ {
+ p += ", ";
+ }
+ p += policyInformation[i];
+ }
+
+ return "CertificatePolicies: " + p;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/DSAParameter.java b/core/src/main/java/org/spongycastle/asn1/x509/DSAParameter.java
new file mode 100644
index 00000000..1b6b2405
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/DSAParameter.java
@@ -0,0 +1,92 @@
+package org.spongycastle.asn1.x509;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+
+public class DSAParameter
+ extends ASN1Object
+{
+ ASN1Integer p, q, g;
+
+ public static DSAParameter getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static DSAParameter getInstance(
+ Object obj)
+ {
+ if (obj instanceof DSAParameter)
+ {
+ return (DSAParameter)obj;
+ }
+
+ if(obj != null)
+ {
+ return new DSAParameter(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public DSAParameter(
+ BigInteger p,
+ BigInteger q,
+ BigInteger g)
+ {
+ this.p = new ASN1Integer(p);
+ this.q = new ASN1Integer(q);
+ this.g = new ASN1Integer(g);
+ }
+
+ private DSAParameter(
+ ASN1Sequence seq)
+ {
+ if (seq.size() != 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ Enumeration e = seq.getObjects();
+
+ p = ASN1Integer.getInstance(e.nextElement());
+ q = ASN1Integer.getInstance(e.nextElement());
+ g = ASN1Integer.getInstance(e.nextElement());
+ }
+
+ public BigInteger getP()
+ {
+ return p.getPositiveValue();
+ }
+
+ public BigInteger getQ()
+ {
+ return q.getPositiveValue();
+ }
+
+ public BigInteger getG()
+ {
+ return g.getPositiveValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(p);
+ v.add(q);
+ v.add(g);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/DigestInfo.java b/core/src/main/java/org/spongycastle/asn1/x509/DigestInfo.java
new file mode 100644
index 00000000..b5f5cf61
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/DigestInfo.java
@@ -0,0 +1,86 @@
+package org.spongycastle.asn1.x509;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * The DigestInfo object.
+ * <pre>
+ * DigestInfo::=SEQUENCE{
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING }
+ * </pre>
+ */
+public class DigestInfo
+ extends ASN1Object
+{
+ private byte[] digest;
+ private AlgorithmIdentifier algId;
+
+ public static DigestInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static DigestInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof DigestInfo)
+ {
+ return (DigestInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new DigestInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public DigestInfo(
+ AlgorithmIdentifier algId,
+ byte[] digest)
+ {
+ this.digest = digest;
+ this.algId = algId;
+ }
+
+ public DigestInfo(
+ ASN1Sequence obj)
+ {
+ Enumeration e = obj.getObjects();
+
+ algId = AlgorithmIdentifier.getInstance(e.nextElement());
+ digest = ASN1OctetString.getInstance(e.nextElement()).getOctets();
+ }
+
+ public AlgorithmIdentifier getAlgorithmId()
+ {
+ return algId;
+ }
+
+ public byte[] getDigest()
+ {
+ return digest;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(algId);
+ v.add(new DEROctetString(digest));
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/DisplayText.java b/core/src/main/java/org/spongycastle/asn1/x509/DisplayText.java
new file mode 100644
index 00000000..ad273cf8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/DisplayText.java
@@ -0,0 +1,165 @@
+
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1String;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBMPString;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.DERUTF8String;
+import org.spongycastle.asn1.DERVisibleString;
+
+/**
+ * <code>DisplayText</code> class, used in
+ * <code>CertificatePolicies</code> X509 V3 extensions (in policy qualifiers).
+ *
+ * <p>It stores a string in a chosen encoding.
+ * <pre>
+ * DisplayText ::= CHOICE {
+ * ia5String IA5String (SIZE (1..200)),
+ * visibleString VisibleString (SIZE (1..200)),
+ * bmpString BMPString (SIZE (1..200)),
+ * utf8String UTF8String (SIZE (1..200)) }
+ * </pre>
+ * @see PolicyQualifierInfo
+ * @see PolicyInformation
+ */
+public class DisplayText
+ extends ASN1Object
+ implements ASN1Choice
+{
+ /**
+ * Constant corresponding to ia5String encoding.
+ *
+ */
+ public static final int CONTENT_TYPE_IA5STRING = 0;
+ /**
+ * Constant corresponding to bmpString encoding.
+ *
+ */
+ public static final int CONTENT_TYPE_BMPSTRING = 1;
+ /**
+ * Constant corresponding to utf8String encoding.
+ *
+ */
+ public static final int CONTENT_TYPE_UTF8STRING = 2;
+ /**
+ * Constant corresponding to visibleString encoding.
+ *
+ */
+ public static final int CONTENT_TYPE_VISIBLESTRING = 3;
+
+ /**
+ * Describe constant <code>DISPLAY_TEXT_MAXIMUM_SIZE</code> here.
+ *
+ */
+ public static final int DISPLAY_TEXT_MAXIMUM_SIZE = 200;
+
+ int contentType;
+ ASN1String contents;
+
+ /**
+ * Creates a new <code>DisplayText</code> instance.
+ *
+ * @param type the desired encoding type for the text.
+ * @param text the text to store. Strings longer than 200
+ * characters are truncated.
+ */
+ public DisplayText(int type, String text)
+ {
+ if (text.length() > DISPLAY_TEXT_MAXIMUM_SIZE)
+ {
+ // RFC3280 limits these strings to 200 chars
+ // truncate the string
+ text = text.substring (0, DISPLAY_TEXT_MAXIMUM_SIZE);
+ }
+
+ contentType = type;
+ switch (type)
+ {
+ case CONTENT_TYPE_IA5STRING:
+ contents = new DERIA5String(text);
+ break;
+ case CONTENT_TYPE_UTF8STRING:
+ contents = new DERUTF8String(text);
+ break;
+ case CONTENT_TYPE_VISIBLESTRING:
+ contents = new DERVisibleString(text);
+ break;
+ case CONTENT_TYPE_BMPSTRING:
+ contents = new DERBMPString(text);
+ break;
+ default:
+ contents = new DERUTF8String(text);
+ break;
+ }
+ }
+
+ /**
+ * Creates a new <code>DisplayText</code> instance.
+ *
+ * @param text the text to encapsulate. Strings longer than 200
+ * characters are truncated.
+ */
+ public DisplayText(String text)
+ {
+ // by default use UTF8String
+ if (text.length() > DISPLAY_TEXT_MAXIMUM_SIZE)
+ {
+ text = text.substring(0, DISPLAY_TEXT_MAXIMUM_SIZE);
+ }
+
+ contentType = CONTENT_TYPE_UTF8STRING;
+ contents = new DERUTF8String(text);
+ }
+
+ /**
+ * Creates a new <code>DisplayText</code> instance.
+ * <p>Useful when reading back a <code>DisplayText</code> class
+ * from it's ASN1Encodable/DEREncodable form.
+ *
+ * @param de a <code>DEREncodable</code> instance.
+ */
+ private DisplayText(ASN1String de)
+ {
+ contents = de;
+ }
+
+ public static DisplayText getInstance(Object obj)
+ {
+ if (obj instanceof ASN1String)
+ {
+ return new DisplayText((ASN1String)obj);
+ }
+ else if (obj == null || obj instanceof DisplayText)
+ {
+ return (DisplayText)obj;
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ public static DisplayText getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject()); // must be explicitly tagged
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return (ASN1Primitive)contents;
+ }
+
+ /**
+ * Returns the stored <code>String</code> object.
+ *
+ * @return the stored text as a <code>String</code>.
+ */
+ public String getString()
+ {
+ return contents.getString();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/DistributionPoint.java b/core/src/main/java/org/spongycastle/asn1/x509/DistributionPoint.java
new file mode 100644
index 00000000..d854e854
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/DistributionPoint.java
@@ -0,0 +1,158 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+/**
+ * The DistributionPoint object.
+ * <pre>
+ * DistributionPoint ::= SEQUENCE {
+ * distributionPoint [0] DistributionPointName OPTIONAL,
+ * reasons [1] ReasonFlags OPTIONAL,
+ * cRLIssuer [2] GeneralNames OPTIONAL
+ * }
+ * </pre>
+ */
+public class DistributionPoint
+ extends ASN1Object
+{
+ DistributionPointName distributionPoint;
+ ReasonFlags reasons;
+ GeneralNames cRLIssuer;
+
+ public static DistributionPoint getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static DistributionPoint getInstance(
+ Object obj)
+ {
+ if(obj == null || obj instanceof DistributionPoint)
+ {
+ return (DistributionPoint)obj;
+ }
+
+ if(obj instanceof ASN1Sequence)
+ {
+ return new DistributionPoint((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid DistributionPoint: " + obj.getClass().getName());
+ }
+
+ public DistributionPoint(
+ ASN1Sequence seq)
+ {
+ for (int i = 0; i != seq.size(); i++)
+ {
+ ASN1TaggedObject t = ASN1TaggedObject.getInstance(seq.getObjectAt(i));
+ switch (t.getTagNo())
+ {
+ case 0:
+ distributionPoint = DistributionPointName.getInstance(t, true);
+ break;
+ case 1:
+ reasons = new ReasonFlags(DERBitString.getInstance(t, false));
+ break;
+ case 2:
+ cRLIssuer = GeneralNames.getInstance(t, false);
+ }
+ }
+ }
+
+ public DistributionPoint(
+ DistributionPointName distributionPoint,
+ ReasonFlags reasons,
+ GeneralNames cRLIssuer)
+ {
+ this.distributionPoint = distributionPoint;
+ this.reasons = reasons;
+ this.cRLIssuer = cRLIssuer;
+ }
+
+ public DistributionPointName getDistributionPoint()
+ {
+ return distributionPoint;
+ }
+
+ public ReasonFlags getReasons()
+ {
+ return reasons;
+ }
+
+ public GeneralNames getCRLIssuer()
+ {
+ return cRLIssuer;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (distributionPoint != null)
+ {
+ //
+ // as this is a CHOICE it must be explicitly tagged
+ //
+ v.add(new DERTaggedObject(0, distributionPoint));
+ }
+
+ if (reasons != null)
+ {
+ v.add(new DERTaggedObject(false, 1, reasons));
+ }
+
+ if (cRLIssuer != null)
+ {
+ v.add(new DERTaggedObject(false, 2, cRLIssuer));
+ }
+
+ return new DERSequence(v);
+ }
+
+ public String toString()
+ {
+ String sep = System.getProperty("line.separator");
+ StringBuffer buf = new StringBuffer();
+ buf.append("DistributionPoint: [");
+ buf.append(sep);
+ if (distributionPoint != null)
+ {
+ appendObject(buf, sep, "distributionPoint", distributionPoint.toString());
+ }
+ if (reasons != null)
+ {
+ appendObject(buf, sep, "reasons", reasons.toString());
+ }
+ if (cRLIssuer != null)
+ {
+ appendObject(buf, sep, "cRLIssuer", cRLIssuer.toString());
+ }
+ buf.append("]");
+ buf.append(sep);
+ return buf.toString();
+ }
+
+ private void appendObject(StringBuffer buf, String sep, String name, String value)
+ {
+ String indent = " ";
+
+ buf.append(indent);
+ buf.append(name);
+ buf.append(":");
+ buf.append(sep);
+ buf.append(indent);
+ buf.append(indent);
+ buf.append(value);
+ buf.append(sep);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/DistributionPointName.java b/core/src/main/java/org/spongycastle/asn1/x509/DistributionPointName.java
new file mode 100644
index 00000000..f0033fb8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/DistributionPointName.java
@@ -0,0 +1,138 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERTaggedObject;
+
+/**
+ * The DistributionPointName object.
+ * <pre>
+ * DistributionPointName ::= CHOICE {
+ * fullName [0] GeneralNames,
+ * nameRelativeToCRLIssuer [1] RDN
+ * }
+ * </pre>
+ */
+public class DistributionPointName
+ extends ASN1Object
+ implements ASN1Choice
+{
+ ASN1Encodable name;
+ int type;
+
+ public static final int FULL_NAME = 0;
+ public static final int NAME_RELATIVE_TO_CRL_ISSUER = 1;
+
+ public static DistributionPointName getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1TaggedObject.getInstance(obj, true));
+ }
+
+ public static DistributionPointName getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DistributionPointName)
+ {
+ return (DistributionPointName)obj;
+ }
+ else if (obj instanceof ASN1TaggedObject)
+ {
+ return new DistributionPointName((ASN1TaggedObject)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
+ }
+
+ public DistributionPointName(
+ int type,
+ ASN1Encodable name)
+ {
+ this.type = type;
+ this.name = name;
+ }
+
+ public DistributionPointName(
+ GeneralNames name)
+ {
+ this(FULL_NAME, name);
+ }
+
+ /**
+ * Return the tag number applying to the underlying choice.
+ *
+ * @return the tag number for this point name.
+ */
+ public int getType()
+ {
+ return this.type;
+ }
+
+ /**
+ * Return the tagged object inside the distribution point name.
+ *
+ * @return the underlying choice item.
+ */
+ public ASN1Encodable getName()
+ {
+ return (ASN1Encodable)name;
+ }
+
+ public DistributionPointName(
+ ASN1TaggedObject obj)
+ {
+ this.type = obj.getTagNo();
+
+ if (type == 0)
+ {
+ this.name = GeneralNames.getInstance(obj, false);
+ }
+ else
+ {
+ this.name = ASN1Set.getInstance(obj, false);
+ }
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERTaggedObject(false, type, name);
+ }
+
+ public String toString()
+ {
+ String sep = System.getProperty("line.separator");
+ StringBuffer buf = new StringBuffer();
+ buf.append("DistributionPointName: [");
+ buf.append(sep);
+ if (type == FULL_NAME)
+ {
+ appendObject(buf, sep, "fullName", name.toString());
+ }
+ else
+ {
+ appendObject(buf, sep, "nameRelativeToCRLIssuer", name.toString());
+ }
+ buf.append("]");
+ buf.append(sep);
+ return buf.toString();
+ }
+
+ private void appendObject(StringBuffer buf, String sep, String name, String value)
+ {
+ String indent = " ";
+
+ buf.append(indent);
+ buf.append(name);
+ buf.append(":");
+ buf.append(sep);
+ buf.append(indent);
+ buf.append(indent);
+ buf.append(value);
+ buf.append(sep);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/ExtendedKeyUsage.java b/core/src/main/java/org/spongycastle/asn1/x509/ExtendedKeyUsage.java
new file mode 100644
index 00000000..c430210f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/ExtendedKeyUsage.java
@@ -0,0 +1,192 @@
+package org.spongycastle.asn1.x509;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * The extendedKeyUsage object.
+ * <pre>
+ * extendedKeyUsage ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
+ * </pre>
+ */
+public class ExtendedKeyUsage
+ extends ASN1Object
+{
+ 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)
+ {
+ 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)
+ {
+ if (obj instanceof ExtendedKeyUsage)
+ {
+ return (ExtendedKeyUsage)obj;
+ }
+ else if (obj != null)
+ {
+ return new ExtendedKeyUsage(ASN1Sequence.getInstance(obj));
+ }
+
+ 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)
+ {
+ this.seq = new DERSequence(usage);
+
+ this.usageTable.put(usage, usage);
+ }
+
+ private ExtendedKeyUsage(
+ ASN1Sequence seq)
+ {
+ this.seq = seq;
+
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ ASN1Encodable o = (ASN1Encodable)e.nextElement();
+ if (!(o.toASN1Primitive() instanceof ASN1ObjectIdentifier))
+ {
+ throw new IllegalArgumentException("Only ASN1ObjectIdentifiers allowed in ExtendedKeyUsage.");
+ }
+ this.usageTable.put(o, o);
+ }
+ }
+
+ /**
+ * Base constructor, from multiple KeyPurposeIds.
+ *
+ * @param usages an array of KeyPurposeIds.
+ */
+ public ExtendedKeyUsage(
+ KeyPurposeId[] usages)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ for (int i = 0; i != usages.length; i++)
+ {
+ v.add(usages[i]);
+ this.usageTable.put(usages[i], usages[i]);
+ }
+
+ this.seq = new DERSequence(v);
+ }
+
+ /**
+ * @deprecated use KeyPurposeId[] constructor.
+ */
+ public ExtendedKeyUsage(
+ Vector usages)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ Enumeration e = usages.elements();
+
+ while (e.hasMoreElements())
+ {
+ KeyPurposeId o = KeyPurposeId.getInstance(e.nextElement());
+
+ v.add(o);
+ this.usageTable.put(o, o);
+ }
+
+ 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)
+ {
+ return (usageTable.get(keyPurposeId) != null);
+ }
+
+ /**
+ * Returns all extended key usages.
+ *
+ * @return An array with all key purposes.
+ */
+ public KeyPurposeId[] getUsages()
+ {
+ KeyPurposeId[] temp = new KeyPurposeId[seq.size()];
+
+ int i = 0;
+ for (Enumeration it = seq.getObjects(); it.hasMoreElements();)
+ {
+ temp[i++] = KeyPurposeId.getInstance(it.nextElement());
+ }
+ 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/core/src/main/java/org/spongycastle/asn1/x509/Extension.java b/core/src/main/java/org/spongycastle/asn1/x509/Extension.java
new file mode 100644
index 00000000..b34f191e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/Extension.java
@@ -0,0 +1,321 @@
+package org.spongycastle.asn1.x509;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Boolean;
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * an object for the elements in the X.509 V3 extension block.
+ */
+public class Extension
+ extends ASN1Object
+{
+ /**
+ * Subject Directory Attributes
+ */
+ public static final ASN1ObjectIdentifier subjectDirectoryAttributes = new ASN1ObjectIdentifier("2.5.29.9");
+
+ /**
+ * Subject Key Identifier
+ */
+ public static final ASN1ObjectIdentifier subjectKeyIdentifier = new ASN1ObjectIdentifier("2.5.29.14");
+
+ /**
+ * Key Usage
+ */
+ public static final ASN1ObjectIdentifier keyUsage = new ASN1ObjectIdentifier("2.5.29.15");
+
+ /**
+ * Private Key Usage Period
+ */
+ public static final ASN1ObjectIdentifier privateKeyUsagePeriod = new ASN1ObjectIdentifier("2.5.29.16");
+
+ /**
+ * Subject Alternative Name
+ */
+ public static final ASN1ObjectIdentifier subjectAlternativeName = new ASN1ObjectIdentifier("2.5.29.17");
+
+ /**
+ * Issuer Alternative Name
+ */
+ public static final ASN1ObjectIdentifier issuerAlternativeName = new ASN1ObjectIdentifier("2.5.29.18");
+
+ /**
+ * Basic Constraints
+ */
+ public static final ASN1ObjectIdentifier basicConstraints = new ASN1ObjectIdentifier("2.5.29.19");
+
+ /**
+ * CRL Number
+ */
+ public static final ASN1ObjectIdentifier cRLNumber = new ASN1ObjectIdentifier("2.5.29.20");
+
+ /**
+ * Reason code
+ */
+ public static final ASN1ObjectIdentifier reasonCode = new ASN1ObjectIdentifier("2.5.29.21");
+
+ /**
+ * Hold Instruction Code
+ */
+ public static final ASN1ObjectIdentifier instructionCode = new ASN1ObjectIdentifier("2.5.29.23");
+
+ /**
+ * Invalidity Date
+ */
+ public static final ASN1ObjectIdentifier invalidityDate = new ASN1ObjectIdentifier("2.5.29.24");
+
+ /**
+ * Delta CRL indicator
+ */
+ public static final ASN1ObjectIdentifier deltaCRLIndicator = new ASN1ObjectIdentifier("2.5.29.27");
+
+ /**
+ * Issuing Distribution Point
+ */
+ public static final ASN1ObjectIdentifier issuingDistributionPoint = new ASN1ObjectIdentifier("2.5.29.28");
+
+ /**
+ * Certificate Issuer
+ */
+ public static final ASN1ObjectIdentifier certificateIssuer = new ASN1ObjectIdentifier("2.5.29.29");
+
+ /**
+ * Name Constraints
+ */
+ public static final ASN1ObjectIdentifier nameConstraints = new ASN1ObjectIdentifier("2.5.29.30");
+
+ /**
+ * CRL Distribution Points
+ */
+ public static final ASN1ObjectIdentifier cRLDistributionPoints = new ASN1ObjectIdentifier("2.5.29.31");
+
+ /**
+ * Certificate Policies
+ */
+ public static final ASN1ObjectIdentifier certificatePolicies = new ASN1ObjectIdentifier("2.5.29.32");
+
+ /**
+ * Policy Mappings
+ */
+ public static final ASN1ObjectIdentifier policyMappings = new ASN1ObjectIdentifier("2.5.29.33");
+
+ /**
+ * Authority Key Identifier
+ */
+ public static final ASN1ObjectIdentifier authorityKeyIdentifier = new ASN1ObjectIdentifier("2.5.29.35");
+
+ /**
+ * Policy Constraints
+ */
+ public static final ASN1ObjectIdentifier policyConstraints = new ASN1ObjectIdentifier("2.5.29.36");
+
+ /**
+ * Extended Key Usage
+ */
+ public static final ASN1ObjectIdentifier extendedKeyUsage = new ASN1ObjectIdentifier("2.5.29.37");
+
+ /**
+ * Freshest CRL
+ */
+ public static final ASN1ObjectIdentifier freshestCRL = new ASN1ObjectIdentifier("2.5.29.46");
+
+ /**
+ * Inhibit Any Policy
+ */
+ public static final ASN1ObjectIdentifier inhibitAnyPolicy = new ASN1ObjectIdentifier("2.5.29.54");
+
+ /**
+ * Authority Info Access
+ */
+ public static final ASN1ObjectIdentifier authorityInfoAccess = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.1");
+
+ /**
+ * Subject Info Access
+ */
+ public static final ASN1ObjectIdentifier subjectInfoAccess = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.11");
+
+ /**
+ * Logo Type
+ */
+ public static final ASN1ObjectIdentifier logoType = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.12");
+
+ /**
+ * BiometricInfo
+ */
+ public static final ASN1ObjectIdentifier biometricInfo = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.2");
+
+ /**
+ * QCStatements
+ */
+ public static final ASN1ObjectIdentifier qCStatements = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.3");
+
+ /**
+ * Audit identity extension in attribute certificates.
+ */
+ public static final ASN1ObjectIdentifier auditIdentity = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.4");
+
+ /**
+ * NoRevAvail extension in attribute certificates.
+ */
+ public static final ASN1ObjectIdentifier noRevAvail = new ASN1ObjectIdentifier("2.5.29.56");
+
+ /**
+ * TargetInformation extension in attribute certificates.
+ */
+ public static final ASN1ObjectIdentifier targetInformation = new ASN1ObjectIdentifier("2.5.29.55");
+
+ private ASN1ObjectIdentifier extnId;
+ private boolean critical;
+ private ASN1OctetString value;
+
+ public Extension(
+ ASN1ObjectIdentifier extnId,
+ ASN1Boolean critical,
+ ASN1OctetString value)
+ {
+ this(extnId, critical.isTrue(), value);
+ }
+
+ public Extension(
+ ASN1ObjectIdentifier extnId,
+ boolean critical,
+ byte[] value)
+ {
+ this(extnId, critical, new DEROctetString(value));
+ }
+
+ public Extension(
+ ASN1ObjectIdentifier extnId,
+ boolean critical,
+ ASN1OctetString value)
+ {
+ this.extnId = extnId;
+ this.critical = critical;
+ this.value = value;
+ }
+
+ private Extension(ASN1Sequence seq)
+ {
+ if (seq.size() == 2)
+ {
+ this.extnId = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+ this.critical = false;
+ this.value = ASN1OctetString.getInstance(seq.getObjectAt(1));
+ }
+ else if (seq.size() == 3)
+ {
+ this.extnId = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+ this.critical = ASN1Boolean.getInstance(seq.getObjectAt(1)).isTrue();
+ this.value = ASN1OctetString.getInstance(seq.getObjectAt(2));
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+ }
+
+ public static Extension getInstance(Object obj)
+ {
+ if (obj instanceof Extension)
+ {
+ return (Extension)obj;
+ }
+ else if (obj != null)
+ {
+ return new Extension(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1ObjectIdentifier getExtnId()
+ {
+ return extnId;
+ }
+
+ public boolean isCritical()
+ {
+ return critical;
+ }
+
+ public ASN1OctetString getExtnValue()
+ {
+ return value;
+ }
+
+ public ASN1Encodable getParsedValue()
+ {
+ return convertValueToObject(this);
+ }
+
+ public int hashCode()
+ {
+ if (this.isCritical())
+ {
+ return this.getExtnValue().hashCode() ^ this.getExtnId().hashCode();
+ }
+
+ return ~(this.getExtnValue().hashCode() ^ this.getExtnId().hashCode());
+ }
+
+ public boolean equals(
+ Object o)
+ {
+ if (!(o instanceof Extension))
+ {
+ return false;
+ }
+
+ Extension other = (Extension)o;
+
+ return other.getExtnId().equals(this.getExtnId())
+ && other.getExtnValue().equals(this.getExtnValue())
+ && (other.isCritical() == this.isCritical());
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(extnId);
+
+ if (critical)
+ {
+ v.add(ASN1Boolean.getInstance(true));
+ }
+
+ v.add(value);
+
+ return new DERSequence(v);
+ }
+
+ /**
+ * Convert the value of the passed in extension to an object
+ * @param ext the extension to parse
+ * @return the object the value string contains
+ * @exception IllegalArgumentException if conversion is not possible
+ */
+ private static ASN1Primitive convertValueToObject(
+ Extension ext)
+ throws IllegalArgumentException
+ {
+ try
+ {
+ return ASN1Primitive.fromByteArray(ext.getExtnValue().getOctets());
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("can't convert extension: " + e);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/Extensions.java b/core/src/main/java/org/spongycastle/asn1/x509/Extensions.java
new file mode 100644
index 00000000..9678240a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/Extensions.java
@@ -0,0 +1,221 @@
+package org.spongycastle.asn1.x509;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+
+public class Extensions
+ extends ASN1Object
+{
+ private Hashtable extensions = new Hashtable();
+ private Vector ordering = new Vector();
+
+ public static Extensions getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static Extensions getInstance(
+ Object obj)
+ {
+ if (obj instanceof Extensions)
+ {
+ return (Extensions)obj;
+ }
+ else if (obj != null)
+ {
+ return new Extensions(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ * <p/>
+ * the extensions are a list of constructed sequences, either with (OID, OctetString) or (OID, Boolean, OctetString)
+ */
+ private Extensions(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ Extension ext = Extension.getInstance(e.nextElement());
+
+ extensions.put(ext.getExtnId(), ext);
+ ordering.addElement(ext.getExtnId());
+ }
+ }
+
+ /**
+ * Base Constructor
+ *
+ * @param extension a single extension.
+ */
+ public Extensions(
+ Extension extension)
+ {
+ this.ordering.addElement(extension.getExtnId());
+ this.extensions.put(extension.getExtnId(), extension);
+ }
+
+ /**
+ * Base Constructor
+ *
+ * @param extensions an array of extensions.
+ */
+ public Extensions(
+ Extension[] extensions)
+ {
+ for (int i = 0; i != extensions.length; i++)
+ {
+ Extension ext = extensions[i];
+
+ this.ordering.addElement(ext.getExtnId());
+ this.extensions.put(ext.getExtnId(), ext);
+ }
+ }
+
+ /**
+ * return an Enumeration of the extension field's object ids.
+ */
+ public Enumeration oids()
+ {
+ return ordering.elements();
+ }
+
+ /**
+ * return the extension represented by the object identifier
+ * passed in.
+ *
+ * @return the extension if it's present, null otherwise.
+ */
+ public Extension getExtension(
+ ASN1ObjectIdentifier oid)
+ {
+ return (Extension)extensions.get(oid);
+ }
+
+ /**
+ * return the parsed value of the extension represented by the object identifier
+ * passed in.
+ *
+ * @return the parsed value of the extension if it's present, null otherwise.
+ */
+ public ASN1Encodable getExtensionParsedValue(ASN1ObjectIdentifier oid)
+ {
+ Extension ext = this.getExtension(oid);
+
+ if (ext != null)
+ {
+ return ext.getParsedValue();
+ }
+
+ return null;
+ }
+
+ /**
+ * <pre>
+ * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+ *
+ * Extension ::= SEQUENCE {
+ * extnId EXTENSION.&amp;id ({ExtensionSet}),
+ * critical BOOLEAN DEFAULT FALSE,
+ * extnValue OCTET STRING }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+ Enumeration e = ordering.elements();
+
+ while (e.hasMoreElements())
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
+ Extension ext = (Extension)extensions.get(oid);
+
+ vec.add(ext);
+ }
+
+ return new DERSequence(vec);
+ }
+
+ public boolean equivalent(
+ Extensions other)
+ {
+ if (extensions.size() != other.extensions.size())
+ {
+ return false;
+ }
+
+ Enumeration e1 = extensions.keys();
+
+ while (e1.hasMoreElements())
+ {
+ Object key = e1.nextElement();
+
+ if (!extensions.get(key).equals(other.extensions.get(key)))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public ASN1ObjectIdentifier[] getExtensionOIDs()
+ {
+ return toOidArray(ordering);
+ }
+
+ public ASN1ObjectIdentifier[] getNonCriticalExtensionOIDs()
+ {
+ return getExtensionOIDs(false);
+ }
+
+ public ASN1ObjectIdentifier[] getCriticalExtensionOIDs()
+ {
+ return getExtensionOIDs(true);
+ }
+
+ private ASN1ObjectIdentifier[] getExtensionOIDs(boolean isCritical)
+ {
+ Vector oidVec = new Vector();
+
+ for (int i = 0; i != ordering.size(); i++)
+ {
+ Object oid = ordering.elementAt(i);
+
+ if (((Extension)extensions.get(oid)).isCritical() == isCritical)
+ {
+ oidVec.addElement(oid);
+ }
+ }
+
+ return toOidArray(oidVec);
+ }
+
+ private ASN1ObjectIdentifier[] toOidArray(Vector oidVec)
+ {
+ ASN1ObjectIdentifier[] oids = new ASN1ObjectIdentifier[oidVec.size()];
+
+ for (int i = 0; i != oids.length; i++)
+ {
+ oids[i] = (ASN1ObjectIdentifier)oidVec.elementAt(i);
+ }
+ return oids;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/ExtensionsGenerator.java b/core/src/main/java/org/spongycastle/asn1/x509/ExtensionsGenerator.java
new file mode 100644
index 00000000..1f2f571d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/ExtensionsGenerator.java
@@ -0,0 +1,94 @@
+package org.spongycastle.asn1.x509;
+
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Encoding;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.DEROctetString;
+
+/**
+ * Generator for X.509 extensions
+ */
+public class ExtensionsGenerator
+{
+ private Hashtable extensions = new Hashtable();
+ private Vector extOrdering = new Vector();
+
+ /**
+ * Reset the generator
+ */
+ public void reset()
+ {
+ extensions = new Hashtable();
+ extOrdering = new Vector();
+ }
+
+ /**
+ * Add an extension with the given oid and the passed in value to be included
+ * in the OCTET STRING associated with the extension.
+ *
+ * @param oid OID for the extension.
+ * @param critical true if critical, false otherwise.
+ * @param value the ASN.1 object to be included in the extension.
+ */
+ public void addExtension(
+ ASN1ObjectIdentifier oid,
+ boolean critical,
+ ASN1Encodable value)
+ throws IOException
+ {
+ this.addExtension(oid, critical, value.toASN1Primitive().getEncoded(ASN1Encoding.DER));
+ }
+
+ /**
+ * Add an extension with the given oid and the passed in byte array to be wrapped in the
+ * OCTET STRING associated with the extension.
+ *
+ * @param oid OID for the extension.
+ * @param critical true if critical, false otherwise.
+ * @param value the byte array to be wrapped.
+ */
+ public void addExtension(
+ ASN1ObjectIdentifier oid,
+ boolean critical,
+ byte[] value)
+ {
+ if (extensions.containsKey(oid))
+ {
+ throw new IllegalArgumentException("extension " + oid + " already added");
+ }
+
+ extOrdering.addElement(oid);
+ extensions.put(oid, new Extension(oid, critical, new DEROctetString(value)));
+ }
+
+ /**
+ * Return true if there are no extension present in this generator.
+ *
+ * @return true if empty, false otherwise
+ */
+ public boolean isEmpty()
+ {
+ return extOrdering.isEmpty();
+ }
+
+ /**
+ * Generate an Extensions object based on the current state of the generator.
+ *
+ * @return an X09Extensions object.
+ */
+ public Extensions generate()
+ {
+ Extension[] exts = new Extension[extOrdering.size()];
+
+ for (int i = 0; i != extOrdering.size(); i++)
+ {
+ exts[i] = (Extension)extensions.get(extOrdering.elementAt(i));
+ }
+
+ return new Extensions(exts);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/GeneralName.java b/core/src/main/java/org/spongycastle/asn1/x509/GeneralName.java
new file mode 100644
index 00000000..86ad11e5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/GeneralName.java
@@ -0,0 +1,439 @@
+package org.spongycastle.asn1.x509;
+
+import java.io.IOException;
+import java.util.StringTokenizer;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x500.X500Name;
+import org.spongycastle.util.IPAddress;
+
+/**
+ * The GeneralName object.
+ * <pre>
+ * GeneralName ::= CHOICE {
+ * otherName [0] OtherName,
+ * rfc822Name [1] IA5String,
+ * dNSName [2] IA5String,
+ * x400Address [3] ORAddress,
+ * directoryName [4] Name,
+ * ediPartyName [5] EDIPartyName,
+ * uniformResourceIdentifier [6] IA5String,
+ * iPAddress [7] OCTET STRING,
+ * registeredID [8] OBJECT IDENTIFIER}
+ *
+ * OtherName ::= SEQUENCE {
+ * type-id OBJECT IDENTIFIER,
+ * value [0] EXPLICIT ANY DEFINED BY type-id }
+ *
+ * EDIPartyName ::= SEQUENCE {
+ * nameAssigner [0] DirectoryString OPTIONAL,
+ * partyName [1] DirectoryString }
+ *
+ * Name ::= CHOICE { RDNSequence }
+ * </pre>
+ */
+public class GeneralName
+ extends ASN1Object
+ implements ASN1Choice
+{
+ public static final int otherName = 0;
+ public static final int rfc822Name = 1;
+ public static final int dNSName = 2;
+ public static final int x400Address = 3;
+ public static final int directoryName = 4;
+ public static final int ediPartyName = 5;
+ public static final int uniformResourceIdentifier = 6;
+ public static final int iPAddress = 7;
+ public static final int registeredID = 8;
+
+ private ASN1Encodable obj;
+ private int tag;
+
+ /**
+ * @deprecated use X500Name constructor.
+ * @param dirName
+ */
+ public GeneralName(
+ X509Name dirName)
+ {
+ this.obj = X500Name.getInstance(dirName);
+ this.tag = 4;
+ }
+
+ public GeneralName(
+ X500Name dirName)
+ {
+ this.obj = dirName;
+ this.tag = 4;
+ }
+
+ /**
+ * When the subjectAltName extension contains an Internet mail address,
+ * the address MUST be included as an rfc822Name. The format of an
+ * rfc822Name is an "addr-spec" as defined in RFC 822 [RFC 822].
+ *
+ * When the subjectAltName extension contains a domain name service
+ * label, the domain name MUST be stored in the dNSName (an IA5String).
+ * The name MUST be in the "preferred name syntax," as specified by RFC
+ * 1034 [RFC 1034].
+ *
+ * When the subjectAltName extension contains a URI, the name MUST be
+ * stored in the uniformResourceIdentifier (an IA5String). The name MUST
+ * be a non-relative URL, and MUST follow the URL syntax and encoding
+ * rules specified in [RFC 1738]. The name must include both a scheme
+ * (e.g., "http" or "ftp") and a scheme-specific-part. The scheme-
+ * specific-part must include a fully qualified domain name or IP
+ * address as the host.
+ *
+ * When the subjectAltName extension contains a iPAddress, the address
+ * MUST be stored in the octet string in "network byte order," as
+ * specified in RFC 791 [RFC 791]. The least significant bit (LSB) of
+ * each octet is the LSB of the corresponding byte in the network
+ * address. For IP Version 4, as specified in RFC 791, the octet string
+ * MUST contain exactly four octets. For IP Version 6, as specified in
+ * RFC 1883, the octet string MUST contain exactly sixteen octets [RFC
+ * 1883].
+ */
+ public GeneralName(
+ int tag,
+ ASN1Encodable name)
+ {
+ this.obj = name;
+ this.tag = tag;
+ }
+
+ /**
+ * Create a GeneralName for the given tag from the passed in String.
+ * <p>
+ * This constructor can handle:
+ * <ul>
+ * <li>rfc822Name
+ * <li>iPAddress
+ * <li>directoryName
+ * <li>dNSName
+ * <li>uniformResourceIdentifier
+ * <li>registeredID
+ * </ul>
+ * For x400Address, otherName and ediPartyName there is no common string
+ * format defined.
+ * <p>
+ * Note: A directory name can be encoded in different ways into a byte
+ * representation. Be aware of this if the byte representation is used for
+ * comparing results.
+ *
+ * @param tag tag number
+ * @param name string representation of name
+ * @throws IllegalArgumentException if the string encoding is not correct or * not supported.
+ */
+ public GeneralName(
+ int tag,
+ String name)
+ {
+ this.tag = tag;
+
+ if (tag == rfc822Name || tag == dNSName || tag == uniformResourceIdentifier)
+ {
+ this.obj = new DERIA5String(name);
+ }
+ else if (tag == registeredID)
+ {
+ this.obj = new ASN1ObjectIdentifier(name);
+ }
+ else if (tag == directoryName)
+ {
+ this.obj = new X500Name(name);
+ }
+ else if (tag == iPAddress)
+ {
+ byte[] enc = toGeneralNameEncoding(name);
+ if (enc != null)
+ {
+ this.obj = new DEROctetString(enc);
+ }
+ else
+ {
+ throw new IllegalArgumentException("IP Address is invalid");
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("can't process String for tag: " + tag);
+ }
+ }
+
+ public static GeneralName getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof GeneralName)
+ {
+ return (GeneralName)obj;
+ }
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tagObj = (ASN1TaggedObject)obj;
+ int tag = tagObj.getTagNo();
+
+ switch (tag)
+ {
+ case otherName:
+ return new GeneralName(tag, ASN1Sequence.getInstance(tagObj, false));
+ case rfc822Name:
+ return new GeneralName(tag, DERIA5String.getInstance(tagObj, false));
+ case dNSName:
+ return new GeneralName(tag, DERIA5String.getInstance(tagObj, false));
+ case x400Address:
+ throw new IllegalArgumentException("unknown tag: " + tag);
+ case directoryName:
+ return new GeneralName(tag, X500Name.getInstance(tagObj, true));
+ case ediPartyName:
+ return new GeneralName(tag, ASN1Sequence.getInstance(tagObj, false));
+ case uniformResourceIdentifier:
+ return new GeneralName(tag, DERIA5String.getInstance(tagObj, false));
+ case iPAddress:
+ return new GeneralName(tag, ASN1OctetString.getInstance(tagObj, false));
+ case registeredID:
+ return new GeneralName(tag, ASN1ObjectIdentifier.getInstance(tagObj, false));
+ }
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return getInstance(ASN1Primitive.fromByteArray((byte[])obj));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("unable to parse encoded general name");
+ }
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
+ }
+
+ public static GeneralName getInstance(
+ ASN1TaggedObject tagObj,
+ boolean explicit)
+ {
+ return GeneralName.getInstance(ASN1TaggedObject.getInstance(tagObj, true));
+ }
+
+ public int getTagNo()
+ {
+ return tag;
+ }
+
+ public ASN1Encodable getName()
+ {
+ return obj;
+ }
+
+ public String toString()
+ {
+ StringBuffer buf = new StringBuffer();
+
+ buf.append(tag);
+ buf.append(": ");
+ switch (tag)
+ {
+ case rfc822Name:
+ case dNSName:
+ case uniformResourceIdentifier:
+ buf.append(DERIA5String.getInstance(obj).getString());
+ break;
+ case directoryName:
+ buf.append(X500Name.getInstance(obj).toString());
+ break;
+ default:
+ buf.append(obj.toString());
+ }
+ return buf.toString();
+ }
+
+ private byte[] toGeneralNameEncoding(String ip)
+ {
+ if (IPAddress.isValidIPv6WithNetmask(ip) || IPAddress.isValidIPv6(ip))
+ {
+ int slashIndex = ip.indexOf('/');
+
+ if (slashIndex < 0)
+ {
+ byte[] addr = new byte[16];
+ int[] parsedIp = parseIPv6(ip);
+ copyInts(parsedIp, addr, 0);
+
+ return addr;
+ }
+ else
+ {
+ byte[] addr = new byte[32];
+ int[] parsedIp = parseIPv6(ip.substring(0, slashIndex));
+ copyInts(parsedIp, addr, 0);
+ String mask = ip.substring(slashIndex + 1);
+ if (mask.indexOf(':') > 0)
+ {
+ parsedIp = parseIPv6(mask);
+ }
+ else
+ {
+ parsedIp = parseMask(mask);
+ }
+ copyInts(parsedIp, addr, 16);
+
+ return addr;
+ }
+ }
+ else if (IPAddress.isValidIPv4WithNetmask(ip) || IPAddress.isValidIPv4(ip))
+ {
+ int slashIndex = ip.indexOf('/');
+
+ if (slashIndex < 0)
+ {
+ byte[] addr = new byte[4];
+
+ parseIPv4(ip, addr, 0);
+
+ return addr;
+ }
+ else
+ {
+ byte[] addr = new byte[8];
+
+ parseIPv4(ip.substring(0, slashIndex), addr, 0);
+
+ String mask = ip.substring(slashIndex + 1);
+ if (mask.indexOf('.') > 0)
+ {
+ parseIPv4(mask, addr, 4);
+ }
+ else
+ {
+ parseIPv4Mask(mask, addr, 4);
+ }
+
+ return addr;
+ }
+ }
+
+ return null;
+ }
+
+ private void parseIPv4Mask(String mask, byte[] addr, int offset)
+ {
+ int maskVal = Integer.parseInt(mask);
+
+ for (int i = 0; i != maskVal; i++)
+ {
+ addr[(i / 8) + offset] |= 1 << (7 - (i % 8));
+ }
+ }
+
+ private void parseIPv4(String ip, byte[] addr, int offset)
+ {
+ StringTokenizer sTok = new StringTokenizer(ip, "./");
+ int index = 0;
+
+ while (sTok.hasMoreTokens())
+ {
+ addr[offset + index++] = (byte)Integer.parseInt(sTok.nextToken());
+ }
+ }
+
+ private int[] parseMask(String mask)
+ {
+ int[] res = new int[8];
+ int maskVal = Integer.parseInt(mask);
+
+ for (int i = 0; i != maskVal; i++)
+ {
+ res[i / 16] |= 1 << (15 - (i % 16));
+ }
+ return res;
+ }
+
+ private void copyInts(int[] parsedIp, byte[] addr, int offSet)
+ {
+ for (int i = 0; i != parsedIp.length; i++)
+ {
+ addr[(i * 2) + offSet] = (byte)(parsedIp[i] >> 8);
+ addr[(i * 2 + 1) + offSet] = (byte)parsedIp[i];
+ }
+ }
+
+ private int[] parseIPv6(String ip)
+ {
+ StringTokenizer sTok = new StringTokenizer(ip, ":", true);
+ int index = 0;
+ int[] val = new int[8];
+
+ if (ip.charAt(0) == ':' && ip.charAt(1) == ':')
+ {
+ sTok.nextToken(); // skip the first one
+ }
+
+ int doubleColon = -1;
+
+ while (sTok.hasMoreTokens())
+ {
+ String e = sTok.nextToken();
+
+ if (e.equals(":"))
+ {
+ doubleColon = index;
+ val[index++] = 0;
+ }
+ else
+ {
+ if (e.indexOf('.') < 0)
+ {
+ val[index++] = Integer.parseInt(e, 16);
+ if (sTok.hasMoreTokens())
+ {
+ sTok.nextToken();
+ }
+ }
+ else
+ {
+ StringTokenizer eTok = new StringTokenizer(e, ".");
+
+ val[index++] = (Integer.parseInt(eTok.nextToken()) << 8) | Integer.parseInt(eTok.nextToken());
+ val[index++] = (Integer.parseInt(eTok.nextToken()) << 8) | Integer.parseInt(eTok.nextToken());
+ }
+ }
+ }
+
+ if (index != val.length)
+ {
+ System.arraycopy(val, doubleColon, val, val.length - (index - doubleColon), index - doubleColon);
+ for (int i = doubleColon; i != val.length - (index - doubleColon); i++)
+ {
+ val[i] = 0;
+ }
+ }
+
+ return val;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (tag == directoryName) // directoryName is explicitly tagged as it is a CHOICE
+ {
+ return new DERTaggedObject(true, tag, obj);
+ }
+ else
+ {
+ return new DERTaggedObject(false, tag, obj);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/GeneralNames.java b/core/src/main/java/org/spongycastle/asn1/x509/GeneralNames.java
new file mode 100644
index 00000000..bf8c21fa
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/GeneralNames.java
@@ -0,0 +1,108 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+
+public class GeneralNames
+ extends ASN1Object
+{
+ private final GeneralName[] names;
+
+ public static GeneralNames getInstance(
+ Object obj)
+ {
+ if (obj instanceof GeneralNames)
+ {
+ return (GeneralNames)obj;
+ }
+
+ if (obj != null)
+ {
+ return new GeneralNames(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static GeneralNames getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static GeneralNames fromExtensions(Extensions extensions, ASN1ObjectIdentifier extOID)
+ {
+ return GeneralNames.getInstance(extensions.getExtensionParsedValue(extOID));
+ }
+
+ /**
+ * Construct a GeneralNames object containing one GeneralName.
+ *
+ * @param name the name to be contained.
+ */
+ public GeneralNames(
+ GeneralName name)
+ {
+ this.names = new GeneralName[] { name };
+ }
+
+
+ public GeneralNames(
+ GeneralName[] names)
+ {
+ this.names = names;
+ }
+
+ private GeneralNames(
+ ASN1Sequence seq)
+ {
+ this.names = new GeneralName[seq.size()];
+
+ for (int i = 0; i != seq.size(); i++)
+ {
+ names[i] = GeneralName.getInstance(seq.getObjectAt(i));
+ }
+ }
+
+ public GeneralName[] getNames()
+ {
+ GeneralName[] tmp = new GeneralName[names.length];
+
+ System.arraycopy(names, 0, tmp, 0, names.length);
+
+ return tmp;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * GeneralNames ::= SEQUENCE SIZE {1..MAX} OF GeneralName
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERSequence(names);
+ }
+
+ public String toString()
+ {
+ StringBuffer buf = new StringBuffer();
+ String sep = System.getProperty("line.separator");
+
+ buf.append("GeneralNames:");
+ buf.append(sep);
+
+ for (int i = 0; i != names.length; i++)
+ {
+ buf.append(" ");
+ buf.append(names[i]);
+ buf.append(sep);
+ }
+ return buf.toString();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/GeneralNamesBuilder.java b/core/src/main/java/org/spongycastle/asn1/x509/GeneralNamesBuilder.java
new file mode 100644
index 00000000..2d4b94a8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/GeneralNamesBuilder.java
@@ -0,0 +1,39 @@
+package org.spongycastle.asn1.x509;
+
+import java.util.Vector;
+
+public class GeneralNamesBuilder
+{
+ private Vector names = new Vector();
+
+ public GeneralNamesBuilder addNames(GeneralNames names)
+ {
+ GeneralName[] n = names.getNames();
+
+ for (int i = 0; i != n.length; i++)
+ {
+ this.names.addElement(n[i]);
+ }
+
+ return this;
+ }
+
+ public GeneralNamesBuilder addName(GeneralName name)
+ {
+ names.addElement(name);
+
+ return this;
+ }
+
+ public GeneralNames build()
+ {
+ GeneralName[] tmp = new GeneralName[names.size()];
+
+ for (int i = 0; i != tmp.length; i++)
+ {
+ tmp[i] = (GeneralName)names.elementAt(i);
+ }
+
+ return new GeneralNames(tmp);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/GeneralSubtree.java b/core/src/main/java/org/spongycastle/asn1/x509/GeneralSubtree.java
new file mode 100644
index 00000000..82084e55
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/GeneralSubtree.java
@@ -0,0 +1,218 @@
+package org.spongycastle.asn1.x509;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+/**
+ * Class for containing a restriction object subtrees in NameConstraints. See
+ * RFC 3280.
+ *
+ * <pre>
+ *
+ * GeneralSubtree ::= SEQUENCE
+ * {
+ * base GeneralName,
+ * minimum [0] BaseDistance DEFAULT 0,
+ * maximum [1] BaseDistance OPTIONAL
+ * }
+ * </pre>
+ *
+ * @see org.spongycastle.asn1.x509.NameConstraints
+ *
+ */
+public class GeneralSubtree
+ extends ASN1Object
+{
+ private static final BigInteger ZERO = BigInteger.valueOf(0);
+
+ private GeneralName base;
+
+ private ASN1Integer minimum;
+
+ private ASN1Integer maximum;
+
+ private GeneralSubtree(
+ ASN1Sequence seq)
+ {
+ base = GeneralName.getInstance(seq.getObjectAt(0));
+
+ switch (seq.size())
+ {
+ case 1:
+ break;
+ case 2:
+ ASN1TaggedObject o = ASN1TaggedObject.getInstance(seq.getObjectAt(1));
+ switch (o.getTagNo())
+ {
+ case 0:
+ minimum = ASN1Integer.getInstance(o, false);
+ break;
+ case 1:
+ maximum = ASN1Integer.getInstance(o, false);
+ break;
+ default:
+ throw new IllegalArgumentException("Bad tag number: "
+ + o.getTagNo());
+ }
+ break;
+ case 3:
+ {
+ {
+ ASN1TaggedObject oMin = ASN1TaggedObject.getInstance(seq.getObjectAt(1));
+ if (oMin.getTagNo() != 0)
+ {
+ throw new IllegalArgumentException("Bad tag number for 'minimum': " + oMin.getTagNo());
+ }
+ minimum = ASN1Integer.getInstance(oMin, false);
+ }
+
+ {
+ ASN1TaggedObject oMax = ASN1TaggedObject.getInstance(seq.getObjectAt(2));
+ if (oMax.getTagNo() != 1)
+ {
+ throw new IllegalArgumentException("Bad tag number for 'maximum': " + oMax.getTagNo());
+ }
+ maximum = ASN1Integer.getInstance(oMax, false);
+ }
+
+ break;
+ }
+ default:
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * According RFC 3280, the minimum and maximum fields are not used with any
+ * name forms, thus minimum MUST be zero, and maximum MUST be absent.
+ * <p>
+ * If minimum is <code>null</code>, zero is assumed, if
+ * maximum is <code>null</code>, maximum is absent.
+ *
+ * @param base
+ * A restriction.
+ * @param minimum
+ * Minimum
+ *
+ * @param maximum
+ * Maximum
+ */
+ public GeneralSubtree(
+ GeneralName base,
+ BigInteger minimum,
+ BigInteger maximum)
+ {
+ this.base = base;
+ if (maximum != null)
+ {
+ this.maximum = new ASN1Integer(maximum);
+ }
+ if (minimum == null)
+ {
+ this.minimum = null;
+ }
+ else
+ {
+ this.minimum = new ASN1Integer(minimum);
+ }
+ }
+
+ public GeneralSubtree(GeneralName base)
+ {
+ this(base, null, null);
+ }
+
+ public static GeneralSubtree getInstance(
+ ASN1TaggedObject o,
+ boolean explicit)
+ {
+ return new GeneralSubtree(ASN1Sequence.getInstance(o, explicit));
+ }
+
+ public static GeneralSubtree getInstance(
+ Object obj)
+ {
+ if (obj == null)
+ {
+ return null;
+ }
+
+ if (obj instanceof GeneralSubtree)
+ {
+ return (GeneralSubtree) obj;
+ }
+
+ return new GeneralSubtree(ASN1Sequence.getInstance(obj));
+ }
+
+ public GeneralName getBase()
+ {
+ return base;
+ }
+
+ public BigInteger getMinimum()
+ {
+ if (minimum == null)
+ {
+ return ZERO;
+ }
+
+ return minimum.getValue();
+ }
+
+ public BigInteger getMaximum()
+ {
+ if (maximum == null)
+ {
+ return null;
+ }
+
+ return maximum.getValue();
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ * <pre>
+ * GeneralSubtree ::= SEQUENCE
+ * {
+ * base GeneralName,
+ * minimum [0] BaseDistance DEFAULT 0,
+ * maximum [1] BaseDistance OPTIONAL
+ * }
+ * </pre>
+ *
+ * @return a ASN1Primitive
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(base);
+
+ if (minimum != null && !minimum.getValue().equals(ZERO))
+ {
+ v.add(new DERTaggedObject(false, 0, minimum));
+ }
+
+ if (maximum != null)
+ {
+ v.add(new DERTaggedObject(false, 1, maximum));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/Holder.java b/core/src/main/java/org/spongycastle/asn1/x509/Holder.java
new file mode 100644
index 00000000..e3d89cbd
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/Holder.java
@@ -0,0 +1,245 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+/**
+ * The Holder object.
+ * <p>
+ * For an v2 attribute certificate this is:
+ *
+ * <pre>
+ * Holder ::= SEQUENCE {
+ * baseCertificateID [0] IssuerSerial OPTIONAL,
+ * -- the issuer and serial number of
+ * -- the holder's Public Key Certificate
+ * entityName [1] GeneralNames OPTIONAL,
+ * -- the name of the claimant or role
+ * objectDigestInfo [2] ObjectDigestInfo OPTIONAL
+ * -- used to directly authenticate the holder,
+ * -- for example, an executable
+ * }
+ * </pre>
+ *
+ * <p>
+ * For an v1 attribute certificate this is:
+ *
+ * <pre>
+ * subject CHOICE {
+ * baseCertificateID [0] EXPLICIT IssuerSerial,
+ * -- associated with a Public Key Certificate
+ * subjectName [1] EXPLICIT GeneralNames },
+ * -- associated with a name
+ * </pre>
+ */
+public class Holder
+ extends ASN1Object
+{
+ public static final int V1_CERTIFICATE_HOLDER = 0;
+ public static final int V2_CERTIFICATE_HOLDER = 1;
+
+ IssuerSerial baseCertificateID;
+
+ GeneralNames entityName;
+
+ ObjectDigestInfo objectDigestInfo;
+
+ private int version = V2_CERTIFICATE_HOLDER;
+
+ public static Holder getInstance(Object obj)
+ {
+ if (obj instanceof Holder)
+ {
+ return (Holder)obj;
+ }
+ else if (obj instanceof ASN1TaggedObject)
+ {
+ return new Holder(ASN1TaggedObject.getInstance(obj));
+ }
+ else if (obj != null)
+ {
+ return new Holder(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Constructor for a holder for an V1 attribute certificate.
+ *
+ * @param tagObj The ASN.1 tagged holder object.
+ */
+ private Holder(ASN1TaggedObject tagObj)
+ {
+ switch (tagObj.getTagNo())
+ {
+ case 0:
+ baseCertificateID = IssuerSerial.getInstance(tagObj, true);
+ break;
+ case 1:
+ entityName = GeneralNames.getInstance(tagObj, true);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag in Holder");
+ }
+ version = 0;
+ }
+
+ /**
+ * Constructor for a holder for an V2 attribute certificate.
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private Holder(ASN1Sequence seq)
+ {
+ if (seq.size() > 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ for (int i = 0; i != seq.size(); i++)
+ {
+ ASN1TaggedObject tObj = ASN1TaggedObject.getInstance(seq
+ .getObjectAt(i));
+
+ switch (tObj.getTagNo())
+ {
+ case 0:
+ baseCertificateID = IssuerSerial.getInstance(tObj, false);
+ break;
+ case 1:
+ entityName = GeneralNames.getInstance(tObj, false);
+ break;
+ case 2:
+ objectDigestInfo = ObjectDigestInfo.getInstance(tObj, false);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag in Holder");
+ }
+ }
+ version = 1;
+ }
+
+ public Holder(IssuerSerial baseCertificateID)
+ {
+ this(baseCertificateID, V2_CERTIFICATE_HOLDER);
+ }
+
+ /**
+ * Constructs a holder from a IssuerSerial for a V1 or V2 certificate.
+ * .
+ * @param baseCertificateID The IssuerSerial.
+ * @param version The version of the attribute certificate.
+ */
+ public Holder(IssuerSerial baseCertificateID, int version)
+ {
+ this.baseCertificateID = baseCertificateID;
+ this.version = version;
+ }
+
+ /**
+ * Returns 1 for V2 attribute certificates or 0 for V1 attribute
+ * certificates.
+ * @return The version of the attribute certificate.
+ */
+ public int getVersion()
+ {
+ return version;
+ }
+
+ /**
+ * Constructs a holder with an entityName for V2 attribute certificates.
+ *
+ * @param entityName The entity or subject name.
+ */
+ public Holder(GeneralNames entityName)
+ {
+ this(entityName, V2_CERTIFICATE_HOLDER);
+ }
+
+ /**
+ * Constructs a holder with an entityName for V2 attribute certificates or
+ * with a subjectName for V1 attribute certificates.
+ *
+ * @param entityName The entity or subject name.
+ * @param version The version of the attribute certificate.
+ */
+ public Holder(GeneralNames entityName, int version)
+ {
+ this.entityName = entityName;
+ this.version = version;
+ }
+
+ /**
+ * Constructs a holder from an object digest info.
+ *
+ * @param objectDigestInfo The object digest info object.
+ */
+ public Holder(ObjectDigestInfo objectDigestInfo)
+ {
+ this.objectDigestInfo = objectDigestInfo;
+ }
+
+ public IssuerSerial getBaseCertificateID()
+ {
+ return baseCertificateID;
+ }
+
+ /**
+ * Returns the entityName for an V2 attribute certificate or the subjectName
+ * for an V1 attribute certificate.
+ *
+ * @return The entityname or subjectname.
+ */
+ public GeneralNames getEntityName()
+ {
+ return entityName;
+ }
+
+ public ObjectDigestInfo getObjectDigestInfo()
+ {
+ return objectDigestInfo;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (version == 1)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (baseCertificateID != null)
+ {
+ v.add(new DERTaggedObject(false, 0, baseCertificateID));
+ }
+
+ if (entityName != null)
+ {
+ v.add(new DERTaggedObject(false, 1, entityName));
+ }
+
+ if (objectDigestInfo != null)
+ {
+ v.add(new DERTaggedObject(false, 2, objectDigestInfo));
+ }
+
+ return new DERSequence(v);
+ }
+ else
+ {
+ if (entityName != null)
+ {
+ return new DERTaggedObject(true, 1, entityName);
+ }
+ else
+ {
+ return new DERTaggedObject(true, 0, baseCertificateID);
+ }
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/IetfAttrSyntax.java b/core/src/main/java/org/spongycastle/asn1/x509/IetfAttrSyntax.java
new file mode 100644
index 00000000..c8eca193
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/IetfAttrSyntax.java
@@ -0,0 +1,189 @@
+package org.spongycastle.asn1.x509;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.DERUTF8String;
+
+/**
+ * Implementation of <code>IetfAttrSyntax</code> as specified by RFC3281.
+ */
+public class IetfAttrSyntax
+ extends ASN1Object
+{
+ public static final int VALUE_OCTETS = 1;
+ public static final int VALUE_OID = 2;
+ public static final int VALUE_UTF8 = 3;
+ GeneralNames policyAuthority = null;
+ Vector values = new Vector();
+ int valueChoice = -1;
+
+ public static IetfAttrSyntax getInstance(Object obj)
+ {
+ if (obj instanceof IetfAttrSyntax)
+ {
+ return (IetfAttrSyntax)obj;
+ }
+ if (obj != null)
+ {
+ return new IetfAttrSyntax(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ *
+ */
+ private IetfAttrSyntax(ASN1Sequence seq)
+ {
+ int i = 0;
+
+ if (seq.getObjectAt(0) instanceof ASN1TaggedObject)
+ {
+ policyAuthority = GeneralNames.getInstance(((ASN1TaggedObject)seq.getObjectAt(0)), false);
+ i++;
+ }
+ else if (seq.size() == 2)
+ { // VOMS fix
+ policyAuthority = GeneralNames.getInstance(seq.getObjectAt(0));
+ i++;
+ }
+
+ if (!(seq.getObjectAt(i) instanceof ASN1Sequence))
+ {
+ throw new IllegalArgumentException("Non-IetfAttrSyntax encoding");
+ }
+
+ seq = (ASN1Sequence)seq.getObjectAt(i);
+
+ for (Enumeration e = seq.getObjects(); e.hasMoreElements();)
+ {
+ ASN1Primitive obj = (ASN1Primitive)e.nextElement();
+ int type;
+
+ if (obj instanceof ASN1ObjectIdentifier)
+ {
+ type = VALUE_OID;
+ }
+ else if (obj instanceof DERUTF8String)
+ {
+ type = VALUE_UTF8;
+ }
+ else if (obj instanceof DEROctetString)
+ {
+ type = VALUE_OCTETS;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad value type encoding IetfAttrSyntax");
+ }
+
+ if (valueChoice < 0)
+ {
+ valueChoice = type;
+ }
+
+ if (type != valueChoice)
+ {
+ throw new IllegalArgumentException("Mix of value types in IetfAttrSyntax");
+ }
+
+ values.addElement(obj);
+ }
+ }
+
+ public GeneralNames getPolicyAuthority()
+ {
+ return policyAuthority;
+ }
+
+ public int getValueType()
+ {
+ return valueChoice;
+ }
+
+ public Object[] getValues()
+ {
+ if (this.getValueType() == VALUE_OCTETS)
+ {
+ ASN1OctetString[] tmp = new ASN1OctetString[values.size()];
+
+ for (int i = 0; i != tmp.length; i++)
+ {
+ tmp[i] = (ASN1OctetString)values.elementAt(i);
+ }
+
+ return tmp;
+ }
+ else if (this.getValueType() == VALUE_OID)
+ {
+ ASN1ObjectIdentifier[] tmp = new ASN1ObjectIdentifier[values.size()];
+
+ for (int i = 0; i != tmp.length; i++)
+ {
+ tmp[i] = (ASN1ObjectIdentifier)values.elementAt(i);
+ }
+
+ return tmp;
+ }
+ else
+ {
+ DERUTF8String[] tmp = new DERUTF8String[values.size()];
+
+ for (int i = 0; i != tmp.length; i++)
+ {
+ tmp[i] = (DERUTF8String)values.elementAt(i);
+ }
+
+ return tmp;
+ }
+ }
+
+ /**
+ *
+ * <pre>
+ *
+ * IetfAttrSyntax ::= SEQUENCE {
+ * policyAuthority [0] GeneralNames OPTIONAL,
+ * values SEQUENCE OF CHOICE {
+ * octets OCTET STRING,
+ * oid OBJECT IDENTIFIER,
+ * string UTF8String
+ * }
+ * }
+ *
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (policyAuthority != null)
+ {
+ v.add(new DERTaggedObject(0, policyAuthority));
+ }
+
+ ASN1EncodableVector v2 = new ASN1EncodableVector();
+
+ for (Enumeration i = values.elements(); i.hasMoreElements();)
+ {
+ v2.add((ASN1Encodable)i.nextElement());
+ }
+
+ v.add(new DERSequence(v2));
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/IssuerSerial.java b/core/src/main/java/org/spongycastle/asn1/x509/IssuerSerial.java
new file mode 100644
index 00000000..0ef8674a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/IssuerSerial.java
@@ -0,0 +1,123 @@
+package org.spongycastle.asn1.x509;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x500.X500Name;
+
+public class IssuerSerial
+ extends ASN1Object
+{
+ GeneralNames issuer;
+ ASN1Integer serial;
+ DERBitString issuerUID;
+
+ public static IssuerSerial getInstance(
+ Object obj)
+ {
+ if (obj instanceof IssuerSerial)
+ {
+ return (IssuerSerial)obj;
+ }
+
+ if (obj != null)
+ {
+ return new IssuerSerial(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static IssuerSerial getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ private IssuerSerial(
+ ASN1Sequence seq)
+ {
+ if (seq.size() != 2 && seq.size() != 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ issuer = GeneralNames.getInstance(seq.getObjectAt(0));
+ serial = ASN1Integer.getInstance(seq.getObjectAt(1));
+
+ if (seq.size() == 3)
+ {
+ issuerUID = DERBitString.getInstance(seq.getObjectAt(2));
+ }
+ }
+
+ public IssuerSerial(
+ X500Name issuer,
+ BigInteger serial)
+ {
+ this(new GeneralNames(new GeneralName(issuer)), new ASN1Integer(serial));
+ }
+
+ public IssuerSerial(
+ GeneralNames issuer,
+ BigInteger serial)
+ {
+ this(issuer, new ASN1Integer(serial));
+ }
+
+ public IssuerSerial(
+ GeneralNames issuer,
+ ASN1Integer serial)
+ {
+ this.issuer = issuer;
+ this.serial = serial;
+ }
+
+ public GeneralNames getIssuer()
+ {
+ return issuer;
+ }
+
+ public ASN1Integer getSerial()
+ {
+ return serial;
+ }
+
+ public DERBitString getIssuerUID()
+ {
+ return issuerUID;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * IssuerSerial ::= SEQUENCE {
+ * issuer GeneralNames,
+ * serial CertificateSerialNumber,
+ * issuerUID UniqueIdentifier OPTIONAL
+ * }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(issuer);
+ v.add(serial);
+
+ if (issuerUID != null)
+ {
+ v.add(issuerUID);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/IssuingDistributionPoint.java b/core/src/main/java/org/spongycastle/asn1/x509/IssuingDistributionPoint.java
new file mode 100644
index 00000000..dd0358fe
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/IssuingDistributionPoint.java
@@ -0,0 +1,274 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1Boolean;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+/**
+ * <pre>
+ * IssuingDistributionPoint ::= SEQUENCE {
+ * distributionPoint [0] DistributionPointName OPTIONAL,
+ * onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE,
+ * onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE,
+ * onlySomeReasons [3] ReasonFlags OPTIONAL,
+ * indirectCRL [4] BOOLEAN DEFAULT FALSE,
+ * onlyContainsAttributeCerts [5] BOOLEAN DEFAULT FALSE }
+ * </pre>
+ */
+public class IssuingDistributionPoint
+ extends ASN1Object
+{
+ private DistributionPointName distributionPoint;
+
+ private boolean onlyContainsUserCerts;
+
+ private boolean onlyContainsCACerts;
+
+ private ReasonFlags onlySomeReasons;
+
+ private boolean indirectCRL;
+
+ private boolean onlyContainsAttributeCerts;
+
+ private ASN1Sequence seq;
+
+ public static IssuingDistributionPoint getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static IssuingDistributionPoint getInstance(
+ Object obj)
+ {
+ if (obj instanceof IssuingDistributionPoint)
+ {
+ return (IssuingDistributionPoint)obj;
+ }
+ else if (obj != null)
+ {
+ return new IssuingDistributionPoint(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Constructor from given details.
+ *
+ * @param distributionPoint
+ * May contain an URI as pointer to most current CRL.
+ * @param onlyContainsUserCerts Covers revocation information for end certificates.
+ * @param onlyContainsCACerts Covers revocation information for CA certificates.
+ *
+ * @param onlySomeReasons
+ * Which revocation reasons does this point cover.
+ * @param indirectCRL
+ * If <code>true</code> then the CRL contains revocation
+ * information about certificates ssued by other CAs.
+ * @param onlyContainsAttributeCerts Covers revocation information for attribute certificates.
+ */
+ public IssuingDistributionPoint(
+ DistributionPointName distributionPoint,
+ boolean onlyContainsUserCerts,
+ boolean onlyContainsCACerts,
+ ReasonFlags onlySomeReasons,
+ boolean indirectCRL,
+ boolean onlyContainsAttributeCerts)
+ {
+ this.distributionPoint = distributionPoint;
+ this.indirectCRL = indirectCRL;
+ this.onlyContainsAttributeCerts = onlyContainsAttributeCerts;
+ this.onlyContainsCACerts = onlyContainsCACerts;
+ this.onlyContainsUserCerts = onlyContainsUserCerts;
+ this.onlySomeReasons = onlySomeReasons;
+
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+ if (distributionPoint != null)
+ { // CHOICE item so explicitly tagged
+ vec.add(new DERTaggedObject(true, 0, distributionPoint));
+ }
+ if (onlyContainsUserCerts)
+ {
+ vec.add(new DERTaggedObject(false, 1, ASN1Boolean.getInstance(true)));
+ }
+ if (onlyContainsCACerts)
+ {
+ vec.add(new DERTaggedObject(false, 2, ASN1Boolean.getInstance(true)));
+ }
+ if (onlySomeReasons != null)
+ {
+ vec.add(new DERTaggedObject(false, 3, onlySomeReasons));
+ }
+ if (indirectCRL)
+ {
+ vec.add(new DERTaggedObject(false, 4, ASN1Boolean.getInstance(true)));
+ }
+ if (onlyContainsAttributeCerts)
+ {
+ vec.add(new DERTaggedObject(false, 5, ASN1Boolean.getInstance(true)));
+ }
+
+ seq = new DERSequence(vec);
+ }
+
+ /**
+ * Shorthand Constructor from given details.
+ *
+ * @param distributionPoint
+ * May contain an URI as pointer to most current CRL.
+ * @param indirectCRL
+ * If <code>true</code> then the CRL contains revocation
+ * information about certificates ssued by other CAs.
+ * @param onlyContainsAttributeCerts Covers revocation information for attribute certificates.
+ */
+ public IssuingDistributionPoint(
+ DistributionPointName distributionPoint,
+ boolean indirectCRL,
+ boolean onlyContainsAttributeCerts)
+ {
+ this(distributionPoint, false, false, null, indirectCRL, onlyContainsAttributeCerts);
+ }
+
+ /**
+ * Constructor from ASN1Sequence
+ */
+ private IssuingDistributionPoint(
+ ASN1Sequence seq)
+ {
+ this.seq = seq;
+
+ for (int i = 0; i != seq.size(); i++)
+ {
+ ASN1TaggedObject o = ASN1TaggedObject.getInstance(seq.getObjectAt(i));
+
+ switch (o.getTagNo())
+ {
+ case 0:
+ // CHOICE so explicit
+ distributionPoint = DistributionPointName.getInstance(o, true);
+ break;
+ case 1:
+ onlyContainsUserCerts = ASN1Boolean.getInstance(o, false).isTrue();
+ break;
+ case 2:
+ onlyContainsCACerts = ASN1Boolean.getInstance(o, false).isTrue();
+ break;
+ case 3:
+ onlySomeReasons = new ReasonFlags(ReasonFlags.getInstance(o, false));
+ break;
+ case 4:
+ indirectCRL = ASN1Boolean.getInstance(o, false).isTrue();
+ break;
+ case 5:
+ onlyContainsAttributeCerts = ASN1Boolean.getInstance(o, false).isTrue();
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "unknown tag in IssuingDistributionPoint");
+ }
+ }
+ }
+
+ public boolean onlyContainsUserCerts()
+ {
+ return onlyContainsUserCerts;
+ }
+
+ public boolean onlyContainsCACerts()
+ {
+ return onlyContainsCACerts;
+ }
+
+ public boolean isIndirectCRL()
+ {
+ return indirectCRL;
+ }
+
+ public boolean onlyContainsAttributeCerts()
+ {
+ return onlyContainsAttributeCerts;
+ }
+
+ /**
+ * @return Returns the distributionPoint.
+ */
+ public DistributionPointName getDistributionPoint()
+ {
+ return distributionPoint;
+ }
+
+ /**
+ * @return Returns the onlySomeReasons.
+ */
+ public ReasonFlags getOnlySomeReasons()
+ {
+ return onlySomeReasons;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return seq;
+ }
+
+ public String toString()
+ {
+ String sep = System.getProperty("line.separator");
+ StringBuffer buf = new StringBuffer();
+
+ buf.append("IssuingDistributionPoint: [");
+ buf.append(sep);
+ if (distributionPoint != null)
+ {
+ appendObject(buf, sep, "distributionPoint", distributionPoint.toString());
+ }
+ if (onlyContainsUserCerts)
+ {
+ appendObject(buf, sep, "onlyContainsUserCerts", booleanToString(onlyContainsUserCerts));
+ }
+ if (onlyContainsCACerts)
+ {
+ appendObject(buf, sep, "onlyContainsCACerts", booleanToString(onlyContainsCACerts));
+ }
+ if (onlySomeReasons != null)
+ {
+ appendObject(buf, sep, "onlySomeReasons", onlySomeReasons.toString());
+ }
+ if (onlyContainsAttributeCerts)
+ {
+ appendObject(buf, sep, "onlyContainsAttributeCerts", booleanToString(onlyContainsAttributeCerts));
+ }
+ if (indirectCRL)
+ {
+ appendObject(buf, sep, "indirectCRL", booleanToString(indirectCRL));
+ }
+ buf.append("]");
+ buf.append(sep);
+ return buf.toString();
+ }
+
+ private void appendObject(StringBuffer buf, String sep, String name, String value)
+ {
+ String indent = " ";
+
+ buf.append(indent);
+ buf.append(name);
+ buf.append(":");
+ buf.append(sep);
+ buf.append(indent);
+ buf.append(indent);
+ buf.append(value);
+ buf.append(sep);
+ }
+
+ private String booleanToString(boolean value)
+ {
+ return value ? "true" : "false";
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/KeyPurposeId.java b/core/src/main/java/org/spongycastle/asn1/x509/KeyPurposeId.java
new file mode 100644
index 00000000..9308a48a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/KeyPurposeId.java
@@ -0,0 +1,157 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+
+/**
+ * The KeyPurposeId object.
+ * <pre>
+ * KeyPurposeId ::= OBJECT IDENTIFIER
+ *
+ * id-kp ::= OBJECT IDENTIFIER { iso(1) identified-organization(3)
+ * dod(6) internet(1) security(5) mechanisms(5) pkix(7) 3}
+ *
+ * </pre>
+ * To create a new KeyPurposeId where none of the below suit, use
+ * <pre>
+ * ASN1ObjectIdentifier newKeyPurposeIdOID = new ASN1ObjectIdentifier("1.3.6.1...");
+ *
+ * KeyPurposeId newKeyPurposeId = KeyPurposeId.getInstance(newKeyPurposeIdOID);
+ * </pre>
+ */
+public class KeyPurposeId
+ extends ASN1Object
+{
+ private static final ASN1ObjectIdentifier id_kp = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.3");
+
+ /**
+ * { 2 5 29 37 0 }
+ */
+ public static final KeyPurposeId anyExtendedKeyUsage = new KeyPurposeId(Extension.extendedKeyUsage.branch("0"));
+
+ /**
+ * { id-kp 1 }
+ */
+ public static final KeyPurposeId id_kp_serverAuth = new KeyPurposeId(id_kp.branch("1"));
+ /**
+ * { id-kp 2 }
+ */
+ public static final KeyPurposeId id_kp_clientAuth = new KeyPurposeId(id_kp.branch("2"));
+ /**
+ * { id-kp 3 }
+ */
+ public static final KeyPurposeId id_kp_codeSigning = new KeyPurposeId(id_kp.branch("3"));
+ /**
+ * { id-kp 4 }
+ */
+ public static final KeyPurposeId id_kp_emailProtection = new KeyPurposeId(id_kp.branch("4"));
+ /**
+ * Usage deprecated by RFC4945 - was { id-kp 5 }
+ */
+ public static final KeyPurposeId id_kp_ipsecEndSystem = new KeyPurposeId(id_kp.branch("5"));
+ /**
+ * Usage deprecated by RFC4945 - was { id-kp 6 }
+ */
+ public static final KeyPurposeId id_kp_ipsecTunnel = new KeyPurposeId(id_kp.branch("6"));
+ /**
+ * Usage deprecated by RFC4945 - was { idkp 7 }
+ */
+ public static final KeyPurposeId id_kp_ipsecUser = new KeyPurposeId(id_kp.branch("7"));
+ /**
+ * { id-kp 8 }
+ */
+ public static final KeyPurposeId id_kp_timeStamping = new KeyPurposeId(id_kp.branch("8"));
+ /**
+ * { id-kp 9 }
+ */
+ public static final KeyPurposeId id_kp_OCSPSigning = new KeyPurposeId(id_kp.branch("9"));
+ /**
+ * { id-kp 10 }
+ */
+ public static final KeyPurposeId id_kp_dvcs = new KeyPurposeId(id_kp.branch("10"));
+ /**
+ * { id-kp 11 }
+ */
+ public static final KeyPurposeId id_kp_sbgpCertAAServerAuth = new KeyPurposeId(id_kp.branch("11"));
+ /**
+ * { id-kp 12 }
+ */
+ public static final KeyPurposeId id_kp_scvp_responder = new KeyPurposeId(id_kp.branch("12"));
+ /**
+ * { id-kp 13 }
+ */
+ public static final KeyPurposeId id_kp_eapOverPPP = new KeyPurposeId(id_kp.branch("13"));
+ /**
+ * { id-kp 14 }
+ */
+ public static final KeyPurposeId id_kp_eapOverLAN = new KeyPurposeId(id_kp.branch("14"));
+ /**
+ * { id-kp 15 }
+ */
+ public static final KeyPurposeId id_kp_scvpServer = new KeyPurposeId(id_kp.branch("15"));
+ /**
+ * { id-kp 16 }
+ */
+ public static final KeyPurposeId id_kp_scvpClient = new KeyPurposeId(id_kp.branch("16"));
+ /**
+ * { id-kp 17 }
+ */
+ public static final KeyPurposeId id_kp_ipsecIKE = new KeyPurposeId(id_kp.branch("17"));
+ /**
+ * { id-kp 18 }
+ */
+ public static final KeyPurposeId id_kp_capwapAC = new KeyPurposeId(id_kp.branch("18"));
+ /**
+ * { id-kp 19 }
+ */
+ public static final KeyPurposeId id_kp_capwapWTP = new KeyPurposeId(id_kp.branch("19"));
+
+ //
+ // microsoft key purpose ids
+ //
+ /**
+ * { 1 3 6 1 4 1 311 20 2 2 }
+ */
+ public static final KeyPurposeId id_kp_smartcardlogon = new KeyPurposeId(new ASN1ObjectIdentifier("1.3.6.1.4.1.311.20.2.2"));
+
+ private ASN1ObjectIdentifier id;
+
+ private KeyPurposeId(ASN1ObjectIdentifier id)
+ {
+ this.id = id;
+ }
+
+ /**
+ * @deprecated use getInstance and an OID or one of the constants above.
+ * @param id string representation of an OID.
+ */
+ public KeyPurposeId(String id)
+ {
+ this(new ASN1ObjectIdentifier(id));
+ }
+
+ public static KeyPurposeId getInstance(Object o)
+ {
+ if (o instanceof KeyPurposeId)
+ {
+ return (KeyPurposeId)o;
+ }
+ else if (o != null)
+ {
+ return new KeyPurposeId(ASN1ObjectIdentifier.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return id;
+ }
+
+ public String getId()
+ {
+ return id.getId();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/KeyUsage.java b/core/src/main/java/org/spongycastle/asn1/x509/KeyUsage.java
new file mode 100644
index 00000000..afff0554
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/KeyUsage.java
@@ -0,0 +1,113 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DERBitString;
+
+/**
+ * The KeyUsage object.
+ * <pre>
+ * id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 }
+ *
+ * KeyUsage ::= BIT STRING {
+ * digitalSignature (0),
+ * nonRepudiation (1),
+ * keyEncipherment (2),
+ * dataEncipherment (3),
+ * keyAgreement (4),
+ * keyCertSign (5),
+ * cRLSign (6),
+ * encipherOnly (7),
+ * decipherOnly (8) }
+ * </pre>
+ */
+public class KeyUsage
+ extends ASN1Object
+{
+ public static final int digitalSignature = (1 << 7);
+ public static final int nonRepudiation = (1 << 6);
+ public static final int keyEncipherment = (1 << 5);
+ public static final int dataEncipherment = (1 << 4);
+ public static final int keyAgreement = (1 << 3);
+ public static final int keyCertSign = (1 << 2);
+ public static final int cRLSign = (1 << 1);
+ public static final int encipherOnly = (1 << 0);
+ public static final int decipherOnly = (1 << 15);
+
+ private DERBitString bitString;
+
+ public static KeyUsage getInstance(Object obj) // needs to be DERBitString for other VMs
+ {
+ if (obj instanceof KeyUsage)
+ {
+ return (KeyUsage)obj;
+ }
+ else if (obj != null)
+ {
+ return new KeyUsage(DERBitString.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static KeyUsage fromExtensions(Extensions extensions)
+ {
+ return KeyUsage.getInstance(extensions.getExtensionParsedValue(Extension.keyUsage));
+ }
+
+ /**
+ * Basic constructor.
+ *
+ * @param usage - the bitwise OR of the Key Usage flags giving the
+ * allowed uses for the key.
+ * e.g. (KeyUsage.keyEncipherment | KeyUsage.dataEncipherment)
+ */
+ public KeyUsage(
+ int usage)
+ {
+ this.bitString = new DERBitString(usage);
+ }
+
+ private KeyUsage(
+ DERBitString bitString)
+ {
+ 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();
+ }
+
+ public int getPadBits()
+ {
+ return bitString.getPadBits();
+ }
+
+ public String toString()
+ {
+ byte[] data = bitString.getBytes();
+
+ if (data.length == 1)
+ {
+ return "KeyUsage: 0x" + Integer.toHexString(data[0] & 0xff);
+ }
+ return "KeyUsage: 0x" + Integer.toHexString((data[1] & 0xff) << 8 | (data[0] & 0xff));
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return bitString;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/NameConstraints.java b/core/src/main/java/org/spongycastle/asn1/x509/NameConstraints.java
new file mode 100644
index 00000000..17611bb4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/NameConstraints.java
@@ -0,0 +1,118 @@
+package org.spongycastle.asn1.x509;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+public class NameConstraints
+ extends ASN1Object
+{
+ private GeneralSubtree[] permitted, excluded;
+
+ public static NameConstraints getInstance(Object obj)
+ {
+ if (obj instanceof NameConstraints)
+ {
+ return (NameConstraints)obj;
+ }
+ if (obj != null)
+ {
+ return new NameConstraints(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private NameConstraints(ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+ while (e.hasMoreElements())
+ {
+ ASN1TaggedObject o = ASN1TaggedObject.getInstance(e.nextElement());
+ switch (o.getTagNo())
+ {
+ case 0:
+ permitted = createArray(ASN1Sequence.getInstance(o, false));
+ break;
+ case 1:
+ excluded = createArray(ASN1Sequence.getInstance(o, false));
+ break;
+ }
+ }
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * <p>
+ * permitted and excluded are arrays of GeneralSubtree objects.
+ *
+ * @param permitted
+ * Permitted subtrees
+ * @param excluded
+ * Excludes subtrees
+ */
+ public NameConstraints(
+ GeneralSubtree[] permitted,
+ GeneralSubtree[] excluded)
+ {
+ if (permitted != null)
+ {
+ this.permitted = permitted;
+ }
+
+ if (excluded != null)
+ {
+ this.excluded = excluded;
+ }
+ }
+
+ private GeneralSubtree[] createArray(ASN1Sequence subtree)
+ {
+ GeneralSubtree[] ar = new GeneralSubtree[subtree.size()];
+
+ for (int i = 0; i != ar.length; i++)
+ {
+ ar[i] = GeneralSubtree.getInstance(subtree.getObjectAt(i));
+ }
+
+ return ar;
+ }
+
+ public GeneralSubtree[] getPermittedSubtrees()
+ {
+ return permitted;
+ }
+
+ public GeneralSubtree[] getExcludedSubtrees()
+ {
+ return excluded;
+ }
+
+ /*
+ * NameConstraints ::= SEQUENCE { permittedSubtrees [0] GeneralSubtrees
+ * OPTIONAL, excludedSubtrees [1] GeneralSubtrees OPTIONAL }
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (permitted != null)
+ {
+ v.add(new DERTaggedObject(false, 0, new DERSequence(permitted)));
+ }
+
+ if (excluded != null)
+ {
+ v.add(new DERTaggedObject(false, 1, new DERSequence(excluded)));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/NoticeReference.java b/core/src/main/java/org/spongycastle/asn1/x509/NoticeReference.java
new file mode 100644
index 00000000..5c9a7883
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/NoticeReference.java
@@ -0,0 +1,170 @@
+package org.spongycastle.asn1.x509;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * <code>NoticeReference</code> class, used in
+ * <code>CertificatePolicies</code> X509 V3 extensions
+ * (in policy qualifiers).
+ *
+ * <pre>
+ * NoticeReference ::= SEQUENCE {
+ * organization DisplayText,
+ * noticeNumbers SEQUENCE OF INTEGER }
+ *
+ * </pre>
+ *
+ * @see PolicyQualifierInfo
+ * @see PolicyInformation
+ */
+public class NoticeReference
+ extends ASN1Object
+{
+ private DisplayText organization;
+ private ASN1Sequence noticeNumbers;
+
+ private static ASN1EncodableVector convertVector(Vector numbers)
+ {
+ ASN1EncodableVector av = new ASN1EncodableVector();
+
+ Enumeration it = numbers.elements();
+
+ while (it.hasMoreElements())
+ {
+ Object o = it.nextElement();
+ ASN1Integer di;
+
+ if (o instanceof BigInteger)
+ {
+ di = new ASN1Integer((BigInteger)o);
+ }
+ else if (o instanceof Integer)
+ {
+ di = new ASN1Integer(((Integer)o).intValue());
+ }
+ else
+ {
+ throw new IllegalArgumentException();
+ }
+
+ av.add(di);
+ }
+ return av;
+ }
+
+ /**
+ * Creates a new <code>NoticeReference</code> instance.
+ *
+ * @param organization a <code>String</code> value
+ * @param numbers a <code>Vector</code> value
+ */
+ public NoticeReference(
+ String organization,
+ Vector numbers)
+ {
+ this(organization, convertVector(numbers));
+ }
+
+ /**
+ * Creates a new <code>NoticeReference</code> instance.
+ *
+ * @param organization a <code>String</code> value
+ * @param noticeNumbers an <code>ASN1EncodableVector</code> value
+ */
+ public NoticeReference(
+ String organization,
+ ASN1EncodableVector noticeNumbers)
+ {
+ this(new DisplayText(organization), noticeNumbers);
+ }
+
+ /**
+ * Creates a new <code>NoticeReference</code> instance.
+ *
+ * @param organization displayText
+ * @param noticeNumbers an <code>ASN1EncodableVector</code> value
+ */
+ public NoticeReference(
+ DisplayText organization,
+ ASN1EncodableVector noticeNumbers)
+ {
+ this.organization = organization;
+ this.noticeNumbers = new DERSequence(noticeNumbers);
+ }
+
+ /**
+ * Creates a new <code>NoticeReference</code> instance.
+ * <p>Useful for reconstructing a <code>NoticeReference</code>
+ * instance from its encodable/encoded form.
+ *
+ * @param as an <code>ASN1Sequence</code> value obtained from either
+ * calling @{link toASN1Primitive()} for a <code>NoticeReference</code>
+ * instance or from parsing it from a DER-encoded stream.
+ */
+ private NoticeReference(
+ ASN1Sequence as)
+ {
+ if (as.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + as.size());
+ }
+
+ organization = DisplayText.getInstance(as.getObjectAt(0));
+ noticeNumbers = ASN1Sequence.getInstance(as.getObjectAt(1));
+ }
+
+ public static NoticeReference getInstance(
+ Object as)
+ {
+ if (as instanceof NoticeReference)
+ {
+ return (NoticeReference)as;
+ }
+ else if (as != null)
+ {
+ return new NoticeReference(ASN1Sequence.getInstance(as));
+ }
+
+ return null;
+ }
+
+ public DisplayText getOrganization()
+ {
+ return organization;
+ }
+
+ public ASN1Integer[] getNoticeNumbers()
+ {
+ ASN1Integer[] tmp = new ASN1Integer[noticeNumbers.size()];
+
+ for (int i = 0; i != noticeNumbers.size(); i++)
+ {
+ tmp[i] = ASN1Integer.getInstance(noticeNumbers.getObjectAt(i));
+ }
+
+ return tmp;
+ }
+
+ /**
+ * Describe <code>toASN1Object</code> method here.
+ *
+ * @return a <code>ASN1Primitive</code> value
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector av = new ASN1EncodableVector();
+ av.add (organization);
+ av.add (noticeNumbers);
+ return new DERSequence (av);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/ObjectDigestInfo.java b/core/src/main/java/org/spongycastle/asn1/x509/ObjectDigestInfo.java
new file mode 100644
index 00000000..1d714cdf
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/ObjectDigestInfo.java
@@ -0,0 +1,190 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Enumerated;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * ObjectDigestInfo ASN.1 structure used in v2 attribute certificates.
+ *
+ * <pre>
+ *
+ * ObjectDigestInfo ::= SEQUENCE {
+ * digestedObjectType ENUMERATED {
+ * publicKey (0),
+ * publicKeyCert (1),
+ * otherObjectTypes (2) },
+ * -- otherObjectTypes MUST NOT
+ * -- be used in this profile
+ * otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
+ * digestAlgorithm AlgorithmIdentifier,
+ * objectDigest BIT STRING
+ * }
+ *
+ * </pre>
+ *
+ */
+public class ObjectDigestInfo
+ extends ASN1Object
+{
+ /**
+ * The public key is hashed.
+ */
+ public final static int publicKey = 0;
+
+ /**
+ * The public key certificate is hashed.
+ */
+ public final static int publicKeyCert = 1;
+
+ /**
+ * An other object is hashed.
+ */
+ public final static int otherObjectDigest = 2;
+
+ ASN1Enumerated digestedObjectType;
+
+ ASN1ObjectIdentifier otherObjectTypeID;
+
+ AlgorithmIdentifier digestAlgorithm;
+
+ DERBitString objectDigest;
+
+ public static ObjectDigestInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof ObjectDigestInfo)
+ {
+ return (ObjectDigestInfo)obj;
+ }
+
+ if (obj != null)
+ {
+ return new ObjectDigestInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static ObjectDigestInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * Constructor from given details.
+ * <p>
+ * If <code>digestedObjectType</code> is not {@link #publicKeyCert} or
+ * {@link #publicKey} <code>otherObjectTypeID</code> must be given,
+ * otherwise it is ignored.
+ *
+ * @param digestedObjectType The digest object type.
+ * @param otherObjectTypeID The object type ID for
+ * <code>otherObjectDigest</code>.
+ * @param digestAlgorithm The algorithm identifier for the hash.
+ * @param objectDigest The hash value.
+ */
+ public ObjectDigestInfo(
+ int digestedObjectType,
+ ASN1ObjectIdentifier otherObjectTypeID,
+ AlgorithmIdentifier digestAlgorithm,
+ byte[] objectDigest)
+ {
+ this.digestedObjectType = new ASN1Enumerated(digestedObjectType);
+ if (digestedObjectType == otherObjectDigest)
+ {
+ this.otherObjectTypeID = otherObjectTypeID;
+ }
+
+ this.digestAlgorithm = digestAlgorithm;
+ this.objectDigest = new DERBitString(objectDigest);
+ }
+
+ private ObjectDigestInfo(
+ ASN1Sequence seq)
+ {
+ if (seq.size() > 4 || seq.size() < 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ digestedObjectType = ASN1Enumerated.getInstance(seq.getObjectAt(0));
+
+ int offset = 0;
+
+ if (seq.size() == 4)
+ {
+ otherObjectTypeID = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(1));
+ offset++;
+ }
+
+ digestAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1 + offset));
+
+ objectDigest = DERBitString.getInstance(seq.getObjectAt(2 + offset));
+ }
+
+ public ASN1Enumerated getDigestedObjectType()
+ {
+ return digestedObjectType;
+ }
+
+ public ASN1ObjectIdentifier getOtherObjectTypeID()
+ {
+ return otherObjectTypeID;
+ }
+
+ public AlgorithmIdentifier getDigestAlgorithm()
+ {
+ return digestAlgorithm;
+ }
+
+ public DERBitString getObjectDigest()
+ {
+ return objectDigest;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * <pre>
+ *
+ * ObjectDigestInfo ::= SEQUENCE {
+ * digestedObjectType ENUMERATED {
+ * publicKey (0),
+ * publicKeyCert (1),
+ * otherObjectTypes (2) },
+ * -- otherObjectTypes MUST NOT
+ * -- be used in this profile
+ * otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
+ * digestAlgorithm AlgorithmIdentifier,
+ * objectDigest BIT STRING
+ * }
+ *
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(digestedObjectType);
+
+ if (otherObjectTypeID != null)
+ {
+ v.add(otherObjectTypeID);
+ }
+
+ v.add(digestAlgorithm);
+ v.add(objectDigest);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/PolicyConstraints.java b/core/src/main/java/org/spongycastle/asn1/x509/PolicyConstraints.java
new file mode 100644
index 00000000..540fd0b2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/PolicyConstraints.java
@@ -0,0 +1,106 @@
+package org.spongycastle.asn1.x509;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.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/core/src/main/java/org/spongycastle/asn1/x509/PolicyInformation.java b/core/src/main/java/org/spongycastle/asn1/x509/PolicyInformation.java
new file mode 100644
index 00000000..0b5ee0c8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/PolicyInformation.java
@@ -0,0 +1,87 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+public class PolicyInformation
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier policyIdentifier;
+ private ASN1Sequence policyQualifiers;
+
+ private PolicyInformation(
+ ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ policyIdentifier = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() > 1)
+ {
+ policyQualifiers = ASN1Sequence.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ public PolicyInformation(
+ ASN1ObjectIdentifier policyIdentifier)
+ {
+ this.policyIdentifier = policyIdentifier;
+ }
+
+ public PolicyInformation(
+ ASN1ObjectIdentifier policyIdentifier,
+ ASN1Sequence policyQualifiers)
+ {
+ this.policyIdentifier = policyIdentifier;
+ this.policyQualifiers = policyQualifiers;
+ }
+
+ public static PolicyInformation getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof PolicyInformation)
+ {
+ return (PolicyInformation)obj;
+ }
+
+ return new PolicyInformation(ASN1Sequence.getInstance(obj));
+ }
+
+ public ASN1ObjectIdentifier getPolicyIdentifier()
+ {
+ return policyIdentifier;
+ }
+
+ public ASN1Sequence getPolicyQualifiers()
+ {
+ return policyQualifiers;
+ }
+
+ /*
+ * PolicyInformation ::= SEQUENCE {
+ * policyIdentifier CertPolicyId,
+ * policyQualifiers SEQUENCE SIZE (1..MAX) OF
+ * PolicyQualifierInfo OPTIONAL }
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(policyIdentifier);
+
+ if (policyQualifiers != null)
+ {
+ v.add(policyQualifiers);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/PolicyMappings.java b/core/src/main/java/org/spongycastle/asn1/x509/PolicyMappings.java
new file mode 100644
index 00000000..4b01b0d6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/PolicyMappings.java
@@ -0,0 +1,107 @@
+package org.spongycastle.asn1.x509;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * PolicyMappings V3 extension, described in RFC3280.
+ * <pre>
+ * PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
+ * issuerDomainPolicy CertPolicyId,
+ * subjectDomainPolicy CertPolicyId }
+ * </pre>
+ *
+ * @see <a href="http://www.faqs.org/rfc/rfc3280.txt">RFC 3280, section 4.2.1.6</a>
+ */
+public class PolicyMappings
+ extends ASN1Object
+{
+ ASN1Sequence seq = null;
+
+ public static PolicyMappings getInstance(Object obj)
+ {
+ if (obj instanceof PolicyMappings)
+ {
+ return (PolicyMappings)obj;
+ }
+ if (obj != null)
+ {
+ return new PolicyMappings(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Creates a new <code>PolicyMappings</code> instance.
+ *
+ * @param seq an <code>ASN1Sequence</code> constructed as specified
+ * in RFC 3280
+ */
+ private PolicyMappings(ASN1Sequence seq)
+ {
+ this.seq = seq;
+ }
+
+ /**
+ * Creates a new <code>PolicyMappings</code> instance.
+ *
+ * @param mappings a <code>HashMap</code> value that maps
+ * <code>String</code> oids
+ * to other <code>String</code> oids.
+ * @deprecated use CertPolicyId constructors.
+ */
+ public PolicyMappings(Hashtable mappings)
+ {
+ ASN1EncodableVector dev = new ASN1EncodableVector();
+ Enumeration it = mappings.keys();
+
+ while (it.hasMoreElements())
+ {
+ String idp = (String)it.nextElement();
+ String sdp = (String)mappings.get(idp);
+ ASN1EncodableVector dv = new ASN1EncodableVector();
+ dv.add(new ASN1ObjectIdentifier(idp));
+ dv.add(new ASN1ObjectIdentifier(sdp));
+ dev.add(new DERSequence(dv));
+ }
+
+ seq = new DERSequence(dev);
+ }
+
+ public PolicyMappings(CertPolicyId issuerDomainPolicy, CertPolicyId subjectDomainPolicy)
+ {
+ ASN1EncodableVector dv = new ASN1EncodableVector();
+ dv.add(issuerDomainPolicy);
+ dv.add(subjectDomainPolicy);
+
+ seq = new DERSequence(new DERSequence(dv));
+ }
+
+ public PolicyMappings(CertPolicyId[] issuerDomainPolicy, CertPolicyId[] subjectDomainPolicy)
+ {
+ ASN1EncodableVector dev = new ASN1EncodableVector();
+
+ for (int i = 0; i != issuerDomainPolicy.length; i++)
+ {
+ ASN1EncodableVector dv = new ASN1EncodableVector();
+ dv.add(issuerDomainPolicy[i]);
+ dv.add(subjectDomainPolicy[i]);
+ dev.add(new DERSequence(dv));
+ }
+
+ seq = new DERSequence(dev);
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return seq;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/PolicyQualifierId.java b/core/src/main/java/org/spongycastle/asn1/x509/PolicyQualifierId.java
new file mode 100644
index 00000000..011e52cd
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/PolicyQualifierId.java
@@ -0,0 +1,31 @@
+
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+
+/**
+ * PolicyQualifierId, used in the CertificatePolicies
+ * X509V3 extension.
+ *
+ * <pre>
+ * id-qt OBJECT IDENTIFIER ::= { id-pkix 2 }
+ * id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 }
+ * id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 }
+ * PolicyQualifierId ::=
+ * OBJECT IDENTIFIER (id-qt-cps | id-qt-unotice)
+ * </pre>
+ */
+public class PolicyQualifierId extends ASN1ObjectIdentifier
+{
+ private static final String id_qt = "1.3.6.1.5.5.7.2";
+
+ private PolicyQualifierId(String id)
+ {
+ super(id);
+ }
+
+ public static final PolicyQualifierId id_qt_cps =
+ new PolicyQualifierId(id_qt + ".1");
+ public static final PolicyQualifierId id_qt_unotice =
+ new PolicyQualifierId(id_qt + ".2");
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/PolicyQualifierInfo.java b/core/src/main/java/org/spongycastle/asn1/x509/PolicyQualifierInfo.java
new file mode 100644
index 00000000..d7c5a343
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/PolicyQualifierInfo.java
@@ -0,0 +1,115 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * Policy qualifiers, used in the X509V3 CertificatePolicies
+ * extension.
+ *
+ * <pre>
+ * PolicyQualifierInfo ::= SEQUENCE {
+ * policyQualifierId PolicyQualifierId,
+ * qualifier ANY DEFINED BY policyQualifierId }
+ * </pre>
+ */
+public class PolicyQualifierInfo
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier policyQualifierId;
+ private ASN1Encodable qualifier;
+
+ /**
+ * Creates a new <code>PolicyQualifierInfo</code> instance.
+ *
+ * @param policyQualifierId a <code>PolicyQualifierId</code> value
+ * @param qualifier the qualifier, defined by the above field.
+ */
+ public PolicyQualifierInfo(
+ ASN1ObjectIdentifier policyQualifierId,
+ ASN1Encodable qualifier)
+ {
+ this.policyQualifierId = policyQualifierId;
+ this.qualifier = qualifier;
+ }
+
+ /**
+ * Creates a new <code>PolicyQualifierInfo</code> containing a
+ * cPSuri qualifier.
+ *
+ * @param cps the CPS (certification practice statement) uri as a
+ * <code>String</code>.
+ */
+ public PolicyQualifierInfo(
+ String cps)
+ {
+ policyQualifierId = PolicyQualifierId.id_qt_cps;
+ qualifier = new DERIA5String (cps);
+ }
+
+ /**
+ * Creates a new <code>PolicyQualifierInfo</code> instance.
+ *
+ * @param as <code>PolicyQualifierInfo</code> X509 structure
+ * encoded as an ASN1Sequence.
+ * @deprecated use PolicyQualifierInfo.getInstance()
+ */
+ public PolicyQualifierInfo(
+ ASN1Sequence as)
+ {
+ if (as.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + as.size());
+ }
+
+ policyQualifierId = ASN1ObjectIdentifier.getInstance(as.getObjectAt(0));
+ qualifier = as.getObjectAt(1);
+ }
+
+ public static PolicyQualifierInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof PolicyQualifierInfo)
+ {
+ return (PolicyQualifierInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new PolicyQualifierInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+
+ public ASN1ObjectIdentifier getPolicyQualifierId()
+ {
+ return policyQualifierId;
+ }
+
+ public ASN1Encodable getQualifier()
+ {
+ return qualifier;
+ }
+
+ /**
+ * Returns a DER-encodable representation of this instance.
+ *
+ * @return a <code>ASN1Primitive</code> value
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector dev = new ASN1EncodableVector();
+ dev.add(policyQualifierId);
+ dev.add(qualifier);
+
+ return new DERSequence(dev);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/PrivateKeyUsagePeriod.java b/core/src/main/java/org/spongycastle/asn1/x509/PrivateKeyUsagePeriod.java
new file mode 100644
index 00000000..12834c85
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/PrivateKeyUsagePeriod.java
@@ -0,0 +1,84 @@
+package org.spongycastle.asn1.x509;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+/**
+ * <pre>
+ * PrivateKeyUsagePeriod ::= SEQUENCE {
+ * notBefore [0] GeneralizedTime OPTIONAL,
+ * notAfter [1] GeneralizedTime OPTIONAL }
+ * </pre>
+ */
+public class PrivateKeyUsagePeriod
+ extends ASN1Object
+{
+ public static PrivateKeyUsagePeriod getInstance(Object obj)
+ {
+ if (obj instanceof PrivateKeyUsagePeriod)
+ {
+ return (PrivateKeyUsagePeriod)obj;
+ }
+
+ if (obj != null)
+ {
+ return new PrivateKeyUsagePeriod(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private ASN1GeneralizedTime _notBefore, _notAfter;
+
+ private PrivateKeyUsagePeriod(ASN1Sequence seq)
+ {
+ Enumeration en = seq.getObjects();
+ while (en.hasMoreElements())
+ {
+ ASN1TaggedObject tObj = (ASN1TaggedObject)en.nextElement();
+
+ if (tObj.getTagNo() == 0)
+ {
+ _notBefore = ASN1GeneralizedTime.getInstance(tObj, false);
+ }
+ else if (tObj.getTagNo() == 1)
+ {
+ _notAfter = ASN1GeneralizedTime.getInstance(tObj, false);
+ }
+ }
+ }
+
+ public ASN1GeneralizedTime getNotBefore()
+ {
+ return _notBefore;
+ }
+
+ public ASN1GeneralizedTime getNotAfter()
+ {
+ return _notAfter;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (_notBefore != null)
+ {
+ v.add(new DERTaggedObject(false, 0, _notBefore));
+ }
+ if (_notAfter != null)
+ {
+ v.add(new DERTaggedObject(false, 1, _notAfter));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/RSAPublicKeyStructure.java b/core/src/main/java/org/spongycastle/asn1/x509/RSAPublicKeyStructure.java
new file mode 100644
index 00000000..17451164
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/RSAPublicKeyStructure.java
@@ -0,0 +1,98 @@
+package org.spongycastle.asn1.x509;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * @deprecated use org.spongycastle.asn1.pkcs.RSAPublicKey
+ */
+public class RSAPublicKeyStructure
+ extends ASN1Object
+{
+ private BigInteger modulus;
+ private BigInteger publicExponent;
+
+ public static RSAPublicKeyStructure getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static RSAPublicKeyStructure getInstance(
+ Object obj)
+ {
+ if(obj == null || obj instanceof RSAPublicKeyStructure)
+ {
+ return (RSAPublicKeyStructure)obj;
+ }
+
+ if(obj instanceof ASN1Sequence)
+ {
+ return new RSAPublicKeyStructure((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid RSAPublicKeyStructure: " + obj.getClass().getName());
+ }
+
+ public RSAPublicKeyStructure(
+ BigInteger modulus,
+ BigInteger publicExponent)
+ {
+ this.modulus = modulus;
+ this.publicExponent = publicExponent;
+ }
+
+ public RSAPublicKeyStructure(
+ ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ Enumeration e = seq.getObjects();
+
+ modulus = ASN1Integer.getInstance(e.nextElement()).getPositiveValue();
+ publicExponent = ASN1Integer.getInstance(e.nextElement()).getPositiveValue();
+ }
+
+ public BigInteger getModulus()
+ {
+ return modulus;
+ }
+
+ public BigInteger getPublicExponent()
+ {
+ return publicExponent;
+ }
+
+ /**
+ * This outputs the key in PKCS1v2 format.
+ * <pre>
+ * RSAPublicKey ::= SEQUENCE {
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER, -- e
+ * }
+ * </pre>
+ * <p>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(getModulus()));
+ v.add(new ASN1Integer(getPublicExponent()));
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/ReasonFlags.java b/core/src/main/java/org/spongycastle/asn1/x509/ReasonFlags.java
new file mode 100644
index 00000000..3df0821b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/ReasonFlags.java
@@ -0,0 +1,85 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.DERBitString;
+
+/**
+ * The ReasonFlags object.
+ * <pre>
+ * ReasonFlags ::= BIT STRING {
+ * unused (0),
+ * keyCompromise (1),
+ * cACompromise (2),
+ * affiliationChanged (3),
+ * superseded (4),
+ * cessationOfOperation (5),
+ * certificateHold (6),
+ * privilegeWithdrawn (7),
+ * aACompromise (8) }
+ * </pre>
+ */
+public class ReasonFlags
+ extends DERBitString
+{
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int UNUSED = (1 << 7);
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int KEY_COMPROMISE = (1 << 6);
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int CA_COMPROMISE = (1 << 5);
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int AFFILIATION_CHANGED = (1 << 4);
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int SUPERSEDED = (1 << 3);
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int CESSATION_OF_OPERATION = (1 << 2);
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int CERTIFICATE_HOLD = (1 << 1);
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int PRIVILEGE_WITHDRAWN = (1 << 0);
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int AA_COMPROMISE = (1 << 15);
+
+ public static final int unused = (1 << 7);
+ public static final int keyCompromise = (1 << 6);
+ public static final int cACompromise = (1 << 5);
+ public static final int affiliationChanged = (1 << 4);
+ public static final int superseded = (1 << 3);
+ public static final int cessationOfOperation = (1 << 2);
+ public static final int certificateHold = (1 << 1);
+ public static final int privilegeWithdrawn = (1 << 0);
+ public static final int aACompromise = (1 << 15);
+
+ /**
+ * @param reasons - the bitwise OR of the Key Reason flags giving the
+ * allowed uses for the key.
+ */
+ public ReasonFlags(
+ int reasons)
+ {
+ super(getBytes(reasons), getPadBits(reasons));
+ }
+
+ public ReasonFlags(
+ DERBitString reasons)
+ {
+ super(reasons.getBytes(), reasons.getPadBits());
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/RoleSyntax.java b/core/src/main/java/org/spongycastle/asn1/x509/RoleSyntax.java
new file mode 100644
index 00000000..0a0b3d2b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/RoleSyntax.java
@@ -0,0 +1,237 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1String;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+/**
+ * Implementation of the RoleSyntax object as specified by the RFC3281.
+ *
+ * <pre>
+ * RoleSyntax ::= SEQUENCE {
+ * roleAuthority [0] GeneralNames OPTIONAL,
+ * roleName [1] GeneralName
+ * }
+ * </pre>
+ */
+public class RoleSyntax
+ extends ASN1Object
+{
+ private GeneralNames roleAuthority;
+ private GeneralName roleName;
+
+ /**
+ * RoleSyntax factory method.
+ * @param obj the object used to construct an instance of <code>
+ * RoleSyntax</code>. It must be an instance of <code>RoleSyntax
+ * </code> or <code>ASN1Sequence</code>.
+ * @return the instance of <code>RoleSyntax</code> built from the
+ * supplied object.
+ * @throws java.lang.IllegalArgumentException if the object passed
+ * to the factory is not an instance of <code>RoleSyntax</code> or
+ * <code>ASN1Sequence</code>.
+ */
+ public static RoleSyntax getInstance(
+ Object obj)
+ {
+
+ if (obj instanceof RoleSyntax)
+ {
+ return (RoleSyntax)obj;
+ }
+ else if (obj != null)
+ {
+ return new RoleSyntax(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Constructor.
+ * @param roleAuthority the role authority of this RoleSyntax.
+ * @param roleName the role name of this RoleSyntax.
+ */
+ public RoleSyntax(
+ GeneralNames roleAuthority,
+ GeneralName roleName)
+ {
+ if(roleName == null ||
+ roleName.getTagNo() != GeneralName.uniformResourceIdentifier ||
+ ((ASN1String)roleName.getName()).getString().equals(""))
+ {
+ throw new IllegalArgumentException("the role name MUST be non empty and MUST " +
+ "use the URI option of GeneralName");
+ }
+ this.roleAuthority = roleAuthority;
+ this.roleName = roleName;
+ }
+
+ /**
+ * Constructor. Invoking this constructor is the same as invoking
+ * <code>new RoleSyntax(null, roleName)</code>.
+ * @param roleName the role name of this RoleSyntax.
+ */
+ public RoleSyntax(
+ GeneralName roleName)
+ {
+ this(null, roleName);
+ }
+
+ /**
+ * Utility constructor. Takes a <code>String</code> argument representing
+ * the role name, builds a <code>GeneralName</code> to hold the role name
+ * and calls the constructor that takes a <code>GeneralName</code>.
+ * @param roleName
+ */
+ public RoleSyntax(
+ String roleName)
+ {
+ this(new GeneralName(GeneralName.uniformResourceIdentifier,
+ (roleName == null)? "": roleName));
+ }
+
+ /**
+ * Constructor that builds an instance of <code>RoleSyntax</code> by
+ * extracting the encoded elements from the <code>ASN1Sequence</code>
+ * object supplied.
+ * @param seq an instance of <code>ASN1Sequence</code> that holds
+ * the encoded elements used to build this <code>RoleSyntax</code>.
+ */
+ private RoleSyntax(
+ ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ for (int i = 0; i != seq.size(); i++)
+ {
+ ASN1TaggedObject taggedObject = ASN1TaggedObject.getInstance(seq.getObjectAt(i));
+ switch (taggedObject.getTagNo())
+ {
+ case 0:
+ roleAuthority = GeneralNames.getInstance(taggedObject, false);
+ break;
+ case 1:
+ roleName = GeneralName.getInstance(taggedObject, true);
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown tag in RoleSyntax");
+ }
+ }
+ }
+
+ /**
+ * Gets the role authority of this RoleSyntax.
+ * @return an instance of <code>GeneralNames</code> holding the
+ * role authority of this RoleSyntax.
+ */
+ public GeneralNames getRoleAuthority()
+ {
+ return this.roleAuthority;
+ }
+
+ /**
+ * Gets the role name of this RoleSyntax.
+ * @return an instance of <code>GeneralName</code> holding the
+ * role name of this RoleSyntax.
+ */
+ public GeneralName getRoleName()
+ {
+ return this.roleName;
+ }
+
+ /**
+ * Gets the role name as a <code>java.lang.String</code> object.
+ * @return the role name of this RoleSyntax represented as a
+ * <code>java.lang.String</code> object.
+ */
+ public String getRoleNameAsString()
+ {
+ ASN1String str = (ASN1String)this.roleName.getName();
+
+ return str.getString();
+ }
+
+ /**
+ * Gets the role authority as a <code>String[]</code> object.
+ * @return the role authority of this RoleSyntax represented as a
+ * <code>String[]</code> array.
+ */
+ public String[] getRoleAuthorityAsString()
+ {
+ if(roleAuthority == null)
+ {
+ return new String[0];
+ }
+
+ GeneralName[] names = roleAuthority.getNames();
+ String[] namesString = new String[names.length];
+ for(int i = 0; i < names.length; i++)
+ {
+ ASN1Encodable value = names[i].getName();
+ if(value instanceof ASN1String)
+ {
+ namesString[i] = ((ASN1String)value).getString();
+ }
+ else
+ {
+ namesString[i] = value.toString();
+ }
+ }
+ return namesString;
+ }
+
+ /**
+ * Implementation of the method <code>toASN1Object</code> as
+ * required by the superclass <code>ASN1Encodable</code>.
+ *
+ * <pre>
+ * RoleSyntax ::= SEQUENCE {
+ * roleAuthority [0] GeneralNames OPTIONAL,
+ * roleName [1] GeneralName
+ * }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ if(this.roleAuthority != null)
+ {
+ v.add(new DERTaggedObject(false, 0, roleAuthority));
+ }
+ v.add(new DERTaggedObject(true, 1, roleName));
+
+ return new DERSequence(v);
+ }
+
+ public String toString()
+ {
+ StringBuffer buff = new StringBuffer("Name: " + this.getRoleNameAsString() +
+ " - Auth: ");
+ if(this.roleAuthority == null || roleAuthority.getNames().length == 0)
+ {
+ buff.append("N/A");
+ }
+ else
+ {
+ String[] names = this.getRoleAuthorityAsString();
+ buff.append('[').append(names[0]);
+ for(int i = 1; i < names.length; i++)
+ {
+ buff.append(", ").append(names[i]);
+ }
+ buff.append(']');
+ }
+ return buff.toString();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/SubjectDirectoryAttributes.java b/core/src/main/java/org/spongycastle/asn1/x509/SubjectDirectoryAttributes.java
new file mode 100644
index 00000000..13d4d284
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/SubjectDirectoryAttributes.java
@@ -0,0 +1,144 @@
+package org.spongycastle.asn1.x509;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * This extension may contain further X.500 attributes of the subject. See also
+ * RFC 3039.
+ *
+ * <pre>
+ * SubjectDirectoryAttributes ::= Attributes
+ * Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+ * Attribute ::= SEQUENCE
+ * {
+ * type AttributeType
+ * values SET OF AttributeValue
+ * }
+ *
+ * AttributeType ::= OBJECT IDENTIFIER
+ * AttributeValue ::= ANY DEFINED BY AttributeType
+ * </pre>
+ *
+ * @see org.spongycastle.asn1.x500.style.BCStyle for AttributeType ObjectIdentifiers.
+ */
+public class SubjectDirectoryAttributes
+ extends ASN1Object
+{
+ private Vector attributes = new Vector();
+
+ public static SubjectDirectoryAttributes getInstance(
+ Object obj)
+ {
+ if (obj instanceof SubjectDirectoryAttributes)
+ {
+ return (SubjectDirectoryAttributes)obj;
+ }
+
+ if (obj != null)
+ {
+ return new SubjectDirectoryAttributes(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ *
+ * The sequence is of type SubjectDirectoryAttributes:
+ *
+ * <pre>
+ * SubjectDirectoryAttributes ::= Attributes
+ * Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+ * Attribute ::= SEQUENCE
+ * {
+ * type AttributeType
+ * values SET OF AttributeValue
+ * }
+ *
+ * AttributeType ::= OBJECT IDENTIFIER
+ * AttributeValue ::= ANY DEFINED BY AttributeType
+ * </pre>
+ *
+ * @param seq
+ * The ASN.1 sequence.
+ */
+ private SubjectDirectoryAttributes(ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ ASN1Sequence s = ASN1Sequence.getInstance(e.nextElement());
+ attributes.addElement(Attribute.getInstance(s));
+ }
+ }
+
+ /**
+ * Constructor from a vector of attributes.
+ *
+ * The vector consists of attributes of type {@link Attribute Attribute}
+ *
+ * @param attributes
+ * The attributes.
+ *
+ */
+ public SubjectDirectoryAttributes(Vector attributes)
+ {
+ Enumeration e = attributes.elements();
+
+ while (e.hasMoreElements())
+ {
+ this.attributes.addElement(e.nextElement());
+ }
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ * <pre>
+ * SubjectDirectoryAttributes ::= Attributes
+ * Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+ * Attribute ::= SEQUENCE
+ * {
+ * type AttributeType
+ * values SET OF AttributeValue
+ * }
+ *
+ * AttributeType ::= OBJECT IDENTIFIER
+ * AttributeValue ::= ANY DEFINED BY AttributeType
+ * </pre>
+ *
+ * @return a ASN1Primitive
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+ Enumeration e = attributes.elements();
+
+ while (e.hasMoreElements())
+ {
+
+ vec.add((Attribute)e.nextElement());
+ }
+
+ return new DERSequence(vec);
+ }
+
+ /**
+ * @return Returns the attributes.
+ */
+ public Vector getAttributes()
+ {
+ return attributes;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/SubjectKeyIdentifier.java b/core/src/main/java/org/spongycastle/asn1/x509/SubjectKeyIdentifier.java
new file mode 100644
index 00000000..2a0272b8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/SubjectKeyIdentifier.java
@@ -0,0 +1,68 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DEROctetString;
+
+/**
+ * The SubjectKeyIdentifier object.
+ * <pre>
+ * SubjectKeyIdentifier::= OCTET STRING
+ * </pre>
+ */
+public class SubjectKeyIdentifier
+ extends ASN1Object
+{
+ private byte[] keyidentifier;
+
+ public static SubjectKeyIdentifier getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1OctetString.getInstance(obj, explicit));
+ }
+
+ public static SubjectKeyIdentifier getInstance(
+ Object obj)
+ {
+ if (obj instanceof SubjectKeyIdentifier)
+ {
+ return (SubjectKeyIdentifier)obj;
+ }
+ else if (obj != null)
+ {
+ return new SubjectKeyIdentifier(ASN1OctetString.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static SubjectKeyIdentifier fromExtensions(Extensions extensions)
+ {
+ return SubjectKeyIdentifier.getInstance(extensions.getExtensionParsedValue(Extension.subjectKeyIdentifier));
+ }
+
+ public SubjectKeyIdentifier(
+ byte[] keyid)
+ {
+ this.keyidentifier = keyid;
+ }
+
+ protected SubjectKeyIdentifier(
+ ASN1OctetString keyid)
+ {
+ this.keyidentifier = keyid.getOctets();
+ }
+
+ public byte[] getKeyIdentifier()
+ {
+ return keyidentifier;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DEROctetString(keyidentifier);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/SubjectPublicKeyInfo.java b/core/src/main/java/org/spongycastle/asn1/x509/SubjectPublicKeyInfo.java
new file mode 100644
index 00000000..68a4c85e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/SubjectPublicKeyInfo.java
@@ -0,0 +1,156 @@
+package org.spongycastle.asn1.x509;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * The object that contains the public key stored in a certficate.
+ * <p>
+ * The getEncoded() method in the public keys in the JCE produces a DER
+ * encoded one of these.
+ */
+public class SubjectPublicKeyInfo
+ extends ASN1Object
+{
+ private AlgorithmIdentifier algId;
+ private DERBitString keyData;
+
+ public static SubjectPublicKeyInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static SubjectPublicKeyInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof SubjectPublicKeyInfo)
+ {
+ return (SubjectPublicKeyInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new SubjectPublicKeyInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public SubjectPublicKeyInfo(
+ AlgorithmIdentifier algId,
+ ASN1Encodable publicKey)
+ throws IOException
+ {
+ this.keyData = new DERBitString(publicKey);
+ this.algId = algId;
+ }
+
+ public SubjectPublicKeyInfo(
+ AlgorithmIdentifier algId,
+ byte[] publicKey)
+ {
+ this.keyData = new DERBitString(publicKey);
+ this.algId = algId;
+ }
+
+ public SubjectPublicKeyInfo(
+ ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ Enumeration e = seq.getObjects();
+
+ this.algId = AlgorithmIdentifier.getInstance(e.nextElement());
+ this.keyData = DERBitString.getInstance(e.nextElement());
+ }
+
+ public AlgorithmIdentifier getAlgorithm()
+ {
+ return algId;
+ }
+
+ /**
+ * @deprecated use getAlgorithm()
+ * @return alg ID.
+ */
+ public AlgorithmIdentifier getAlgorithmId()
+ {
+ return algId;
+ }
+
+ /**
+ * for when the public key is an encoded object - if the bitstring
+ * can't be decoded this routine throws an IOException.
+ *
+ * @exception IOException - if the bit string doesn't represent a DER
+ * encoded object.
+ * @return the public key as an ASN.1 primitive.
+ */
+ public ASN1Primitive parsePublicKey()
+ throws IOException
+ {
+ ASN1InputStream aIn = new ASN1InputStream(keyData.getBytes());
+
+ return aIn.readObject();
+ }
+
+ /**
+ * for when the public key is an encoded object - if the bitstring
+ * can't be decoded this routine throws an IOException.
+ *
+ * @exception IOException - if the bit string doesn't represent a DER
+ * encoded object.
+ * @deprecated use parsePublicKey
+ * @return the public key as an ASN.1 primitive.
+ */
+ public ASN1Primitive getPublicKey()
+ throws IOException
+ {
+ ASN1InputStream aIn = new ASN1InputStream(keyData.getBytes());
+
+ return aIn.readObject();
+ }
+
+ /**
+ * for when the public key is raw bits.
+ *
+ * @return the public key as the raw bit string...
+ */
+ public DERBitString getPublicKeyData()
+ {
+ return keyData;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * SubjectPublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * publicKey BIT STRING }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(algId);
+ v.add(keyData);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/TBSCertList.java b/core/src/main/java/org/spongycastle/asn1/x509/TBSCertList.java
new file mode 100644
index 00000000..76b46483
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/TBSCertList.java
@@ -0,0 +1,309 @@
+package org.spongycastle.asn1.x509;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.ASN1UTCTime;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x500.X500Name;
+
+/**
+ * PKIX RFC-2459 - TBSCertList object.
+ * <pre>
+ * TBSCertList ::= SEQUENCE {
+ * version Version OPTIONAL,
+ * -- if present, shall be v2
+ * signature AlgorithmIdentifier,
+ * issuer Name,
+ * thisUpdate Time,
+ * nextUpdate Time OPTIONAL,
+ * revokedCertificates SEQUENCE OF SEQUENCE {
+ * userCertificate CertificateSerialNumber,
+ * revocationDate Time,
+ * crlEntryExtensions Extensions OPTIONAL
+ * -- if present, shall be v2
+ * } OPTIONAL,
+ * crlExtensions [0] EXPLICIT Extensions OPTIONAL
+ * -- if present, shall be v2
+ * }
+ * </pre>
+ */
+public class TBSCertList
+ extends ASN1Object
+{
+ public static class CRLEntry
+ extends ASN1Object
+ {
+ ASN1Sequence seq;
+
+ Extensions crlEntryExtensions;
+
+ private CRLEntry(
+ ASN1Sequence seq)
+ {
+ if (seq.size() < 2 || seq.size() > 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ this.seq = seq;
+ }
+
+ public static CRLEntry getInstance(Object o)
+ {
+ if (o instanceof CRLEntry)
+ {
+ return ((CRLEntry)o);
+ }
+ else if (o != null)
+ {
+ return new CRLEntry(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer getUserCertificate()
+ {
+ return ASN1Integer.getInstance(seq.getObjectAt(0));
+ }
+
+ public Time getRevocationDate()
+ {
+ return Time.getInstance(seq.getObjectAt(1));
+ }
+
+ public Extensions getExtensions()
+ {
+ if (crlEntryExtensions == null && seq.size() == 3)
+ {
+ crlEntryExtensions = Extensions.getInstance(seq.getObjectAt(2));
+ }
+
+ return crlEntryExtensions;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return seq;
+ }
+
+ public boolean hasExtensions()
+ {
+ return seq.size() == 3;
+ }
+ }
+
+ private class RevokedCertificatesEnumeration
+ implements Enumeration
+ {
+ private final Enumeration en;
+
+ RevokedCertificatesEnumeration(Enumeration en)
+ {
+ this.en = en;
+ }
+
+ public boolean hasMoreElements()
+ {
+ return en.hasMoreElements();
+ }
+
+ public Object nextElement()
+ {
+ return CRLEntry.getInstance(en.nextElement());
+ }
+ }
+
+ private class EmptyEnumeration
+ implements Enumeration
+ {
+ public boolean hasMoreElements()
+ {
+ return false;
+ }
+
+ public Object nextElement()
+ {
+ return null; // TODO: check exception handling
+ }
+ }
+
+ ASN1Integer version;
+ AlgorithmIdentifier signature;
+ X500Name issuer;
+ Time thisUpdate;
+ Time nextUpdate;
+ ASN1Sequence revokedCertificates;
+ Extensions crlExtensions;
+
+ public static TBSCertList getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static TBSCertList getInstance(
+ Object obj)
+ {
+ if (obj instanceof TBSCertList)
+ {
+ return (TBSCertList)obj;
+ }
+ else if (obj != null)
+ {
+ return new TBSCertList(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public TBSCertList(
+ ASN1Sequence seq)
+ {
+ if (seq.size() < 3 || seq.size() > 7)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ int seqPos = 0;
+
+ if (seq.getObjectAt(seqPos) instanceof ASN1Integer)
+ {
+ version = ASN1Integer.getInstance(seq.getObjectAt(seqPos++));
+ }
+ else
+ {
+ version = null; // version is optional
+ }
+
+ signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(seqPos++));
+ issuer = X500Name.getInstance(seq.getObjectAt(seqPos++));
+ thisUpdate = Time.getInstance(seq.getObjectAt(seqPos++));
+
+ if (seqPos < seq.size()
+ && (seq.getObjectAt(seqPos) instanceof ASN1UTCTime
+ || seq.getObjectAt(seqPos) instanceof ASN1GeneralizedTime
+ || seq.getObjectAt(seqPos) instanceof Time))
+ {
+ nextUpdate = Time.getInstance(seq.getObjectAt(seqPos++));
+ }
+
+ if (seqPos < seq.size()
+ && !(seq.getObjectAt(seqPos) instanceof DERTaggedObject))
+ {
+ revokedCertificates = ASN1Sequence.getInstance(seq.getObjectAt(seqPos++));
+ }
+
+ if (seqPos < seq.size()
+ && seq.getObjectAt(seqPos) instanceof DERTaggedObject)
+ {
+ crlExtensions = Extensions.getInstance(ASN1Sequence.getInstance((ASN1TaggedObject)seq.getObjectAt(seqPos), true));
+ }
+ }
+
+ public int getVersionNumber()
+ {
+ if (version == null)
+ {
+ return 1;
+ }
+ return version.getValue().intValue() + 1;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public AlgorithmIdentifier getSignature()
+ {
+ return signature;
+ }
+
+ public X500Name getIssuer()
+ {
+ return issuer;
+ }
+
+ public Time getThisUpdate()
+ {
+ return thisUpdate;
+ }
+
+ public Time getNextUpdate()
+ {
+ return nextUpdate;
+ }
+
+ public CRLEntry[] getRevokedCertificates()
+ {
+ if (revokedCertificates == null)
+ {
+ return new CRLEntry[0];
+ }
+
+ CRLEntry[] entries = new CRLEntry[revokedCertificates.size()];
+
+ for (int i = 0; i < entries.length; i++)
+ {
+ entries[i] = CRLEntry.getInstance(revokedCertificates.getObjectAt(i));
+ }
+
+ return entries;
+ }
+
+ public Enumeration getRevokedCertificateEnumeration()
+ {
+ if (revokedCertificates == null)
+ {
+ return new EmptyEnumeration();
+ }
+
+ return new RevokedCertificatesEnumeration(revokedCertificates.getObjects());
+ }
+
+ public Extensions getExtensions()
+ {
+ return crlExtensions;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (version != null)
+ {
+ v.add(version);
+ }
+ v.add(signature);
+ v.add(issuer);
+
+ v.add(thisUpdate);
+ if (nextUpdate != null)
+ {
+ v.add(nextUpdate);
+ }
+
+ // Add CRLEntries if they exist
+ if (revokedCertificates != null)
+ {
+ v.add(revokedCertificates);
+ }
+
+ if (crlExtensions != null)
+ {
+ v.add(new DERTaggedObject(0, crlExtensions));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/TBSCertificate.java b/core/src/main/java/org/spongycastle/asn1/x509/TBSCertificate.java
new file mode 100644
index 00000000..b2ab6f1e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/TBSCertificate.java
@@ -0,0 +1,192 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x500.X500Name;
+
+/**
+ * The TBSCertificate object.
+ * <pre>
+ * TBSCertificate ::= SEQUENCE {
+ * version [ 0 ] Version DEFAULT v1(0),
+ * serialNumber CertificateSerialNumber,
+ * signature AlgorithmIdentifier,
+ * issuer Name,
+ * validity Validity,
+ * subject Name,
+ * subjectPublicKeyInfo SubjectPublicKeyInfo,
+ * issuerUniqueID [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
+ * subjectUniqueID [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
+ * extensions [ 3 ] Extensions OPTIONAL
+ * }
+ * </pre>
+ * <p>
+ * Note: issuerUniqueID and subjectUniqueID are both deprecated by the IETF. This class
+ * will parse them, but you really shouldn't be creating new ones.
+ */
+public class TBSCertificate
+ extends ASN1Object
+{
+ ASN1Sequence seq;
+
+ ASN1Integer version;
+ ASN1Integer serialNumber;
+ AlgorithmIdentifier signature;
+ X500Name issuer;
+ Time startDate, endDate;
+ X500Name subject;
+ SubjectPublicKeyInfo subjectPublicKeyInfo;
+ DERBitString issuerUniqueId;
+ DERBitString subjectUniqueId;
+ Extensions extensions;
+
+ public static TBSCertificate getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static TBSCertificate getInstance(
+ Object obj)
+ {
+ if (obj instanceof TBSCertificate)
+ {
+ return (TBSCertificate)obj;
+ }
+ else if (obj != null)
+ {
+ return new TBSCertificate(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private TBSCertificate(
+ ASN1Sequence seq)
+ {
+ int seqStart = 0;
+
+ this.seq = seq;
+
+ //
+ // some certficates don't include a version number - we assume v1
+ //
+ if (seq.getObjectAt(0) instanceof DERTaggedObject)
+ {
+ version = ASN1Integer.getInstance((ASN1TaggedObject)seq.getObjectAt(0), true);
+ }
+ else
+ {
+ seqStart = -1; // field 0 is missing!
+ version = new ASN1Integer(0);
+ }
+
+ serialNumber = ASN1Integer.getInstance(seq.getObjectAt(seqStart + 1));
+
+ signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(seqStart + 2));
+ issuer = X500Name.getInstance(seq.getObjectAt(seqStart + 3));
+
+ //
+ // before and after dates
+ //
+ ASN1Sequence dates = (ASN1Sequence)seq.getObjectAt(seqStart + 4);
+
+ startDate = Time.getInstance(dates.getObjectAt(0));
+ endDate = Time.getInstance(dates.getObjectAt(1));
+
+ subject = X500Name.getInstance(seq.getObjectAt(seqStart + 5));
+
+ //
+ // public key info.
+ //
+ subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(seqStart + 6));
+
+ for (int extras = seq.size() - (seqStart + 6) - 1; extras > 0; extras--)
+ {
+ DERTaggedObject extra = (DERTaggedObject)seq.getObjectAt(seqStart + 6 + extras);
+
+ switch (extra.getTagNo())
+ {
+ case 1:
+ issuerUniqueId = DERBitString.getInstance(extra, false);
+ break;
+ case 2:
+ subjectUniqueId = DERBitString.getInstance(extra, false);
+ break;
+ case 3:
+ extensions = Extensions.getInstance(ASN1Sequence.getInstance(extra, true));
+ }
+ }
+ }
+
+ public int getVersionNumber()
+ {
+ return version.getValue().intValue() + 1;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public ASN1Integer getSerialNumber()
+ {
+ return serialNumber;
+ }
+
+ public AlgorithmIdentifier getSignature()
+ {
+ return signature;
+ }
+
+ public X500Name getIssuer()
+ {
+ return issuer;
+ }
+
+ public Time getStartDate()
+ {
+ return startDate;
+ }
+
+ public Time getEndDate()
+ {
+ return endDate;
+ }
+
+ public X500Name getSubject()
+ {
+ return subject;
+ }
+
+ public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
+ {
+ return subjectPublicKeyInfo;
+ }
+
+ public DERBitString getIssuerUniqueId()
+ {
+ return issuerUniqueId;
+ }
+
+ public DERBitString getSubjectUniqueId()
+ {
+ return subjectUniqueId;
+ }
+
+ public Extensions getExtensions()
+ {
+ return extensions;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return seq;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/TBSCertificateStructure.java b/core/src/main/java/org/spongycastle/asn1/x509/TBSCertificateStructure.java
new file mode 100644
index 00000000..d138b47e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/TBSCertificateStructure.java
@@ -0,0 +1,194 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.x500.X500Name;
+
+/**
+ * The TBSCertificate object.
+ * <pre>
+ * TBSCertificate ::= SEQUENCE {
+ * version [ 0 ] Version DEFAULT v1(0),
+ * serialNumber CertificateSerialNumber,
+ * signature AlgorithmIdentifier,
+ * issuer Name,
+ * validity Validity,
+ * subject Name,
+ * subjectPublicKeyInfo SubjectPublicKeyInfo,
+ * issuerUniqueID [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
+ * subjectUniqueID [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
+ * extensions [ 3 ] Extensions OPTIONAL
+ * }
+ * </pre>
+ * <p>
+ * Note: issuerUniqueID and subjectUniqueID are both deprecated by the IETF. This class
+ * will parse them, but you really shouldn't be creating new ones.
+ */
+public class TBSCertificateStructure
+ extends ASN1Object
+ implements X509ObjectIdentifiers, PKCSObjectIdentifiers
+{
+ ASN1Sequence seq;
+
+ ASN1Integer version;
+ ASN1Integer serialNumber;
+ AlgorithmIdentifier signature;
+ X500Name issuer;
+ Time startDate, endDate;
+ X500Name subject;
+ SubjectPublicKeyInfo subjectPublicKeyInfo;
+ DERBitString issuerUniqueId;
+ DERBitString subjectUniqueId;
+ X509Extensions extensions;
+
+ public static TBSCertificateStructure getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static TBSCertificateStructure getInstance(
+ Object obj)
+ {
+ if (obj instanceof TBSCertificateStructure)
+ {
+ return (TBSCertificateStructure)obj;
+ }
+ else if (obj != null)
+ {
+ return new TBSCertificateStructure(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public TBSCertificateStructure(
+ ASN1Sequence seq)
+ {
+ int seqStart = 0;
+
+ this.seq = seq;
+
+ //
+ // some certficates don't include a version number - we assume v1
+ //
+ if (seq.getObjectAt(0) instanceof DERTaggedObject)
+ {
+ version = ASN1Integer.getInstance((ASN1TaggedObject)seq.getObjectAt(0), true);
+ }
+ else
+ {
+ seqStart = -1; // field 0 is missing!
+ version = new ASN1Integer(0);
+ }
+
+ serialNumber = ASN1Integer.getInstance(seq.getObjectAt(seqStart + 1));
+
+ signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(seqStart + 2));
+ issuer = X500Name.getInstance(seq.getObjectAt(seqStart + 3));
+
+ //
+ // before and after dates
+ //
+ ASN1Sequence dates = (ASN1Sequence)seq.getObjectAt(seqStart + 4);
+
+ startDate = Time.getInstance(dates.getObjectAt(0));
+ endDate = Time.getInstance(dates.getObjectAt(1));
+
+ subject = X500Name.getInstance(seq.getObjectAt(seqStart + 5));
+
+ //
+ // public key info.
+ //
+ subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(seqStart + 6));
+
+ for (int extras = seq.size() - (seqStart + 6) - 1; extras > 0; extras--)
+ {
+ DERTaggedObject extra = (DERTaggedObject)seq.getObjectAt(seqStart + 6 + extras);
+
+ switch (extra.getTagNo())
+ {
+ case 1:
+ issuerUniqueId = DERBitString.getInstance(extra, false);
+ break;
+ case 2:
+ subjectUniqueId = DERBitString.getInstance(extra, false);
+ break;
+ case 3:
+ extensions = X509Extensions.getInstance(extra);
+ }
+ }
+ }
+
+ public int getVersion()
+ {
+ return version.getValue().intValue() + 1;
+ }
+
+ public ASN1Integer getVersionNumber()
+ {
+ return version;
+ }
+
+ public ASN1Integer getSerialNumber()
+ {
+ return serialNumber;
+ }
+
+ public AlgorithmIdentifier getSignature()
+ {
+ return signature;
+ }
+
+ public X500Name getIssuer()
+ {
+ return issuer;
+ }
+
+ public Time getStartDate()
+ {
+ return startDate;
+ }
+
+ public Time getEndDate()
+ {
+ return endDate;
+ }
+
+ public X500Name getSubject()
+ {
+ return subject;
+ }
+
+ public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
+ {
+ return subjectPublicKeyInfo;
+ }
+
+ public DERBitString getIssuerUniqueId()
+ {
+ return issuerUniqueId;
+ }
+
+ public DERBitString getSubjectUniqueId()
+ {
+ return subjectUniqueId;
+ }
+
+ public X509Extensions getExtensions()
+ {
+ return extensions;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return seq;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/Target.java b/core/src/main/java/org/spongycastle/asn1/x509/Target.java
new file mode 100644
index 00000000..c153c260
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/Target.java
@@ -0,0 +1,138 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERTaggedObject;
+
+/**
+ * Target structure used in target information extension for attribute
+ * certificates from RFC 3281.
+ *
+ * <pre>
+ * Target ::= CHOICE {
+ * targetName [0] GeneralName,
+ * targetGroup [1] GeneralName,
+ * targetCert [2] TargetCert
+ * }
+ * </pre>
+ *
+ * <p>
+ * The targetCert field is currently not supported and must not be used
+ * according to RFC 3281.
+ */
+public class Target
+ extends ASN1Object
+ implements ASN1Choice
+{
+ public static final int targetName = 0;
+ public static final int targetGroup = 1;
+
+ private GeneralName targName;
+ private GeneralName targGroup;
+
+ /**
+ * Creates an instance of a Target from the given object.
+ * <p>
+ * <code>obj</code> can be a Target or a {@link ASN1TaggedObject}
+ *
+ * @param obj The object.
+ * @return A Target instance.
+ * @throws IllegalArgumentException if the given object cannot be
+ * interpreted as Target.
+ */
+ public static Target getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof Target)
+ {
+ return (Target) obj;
+ }
+ else if (obj instanceof ASN1TaggedObject)
+ {
+ return new Target((ASN1TaggedObject)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: "
+ + obj.getClass());
+ }
+
+ /**
+ * Constructor from ASN1TaggedObject.
+ *
+ * @param tagObj The tagged object.
+ * @throws IllegalArgumentException if the encoding is wrong.
+ */
+ private Target(ASN1TaggedObject tagObj)
+ {
+ switch (tagObj.getTagNo())
+ {
+ case targetName: // GeneralName is already a choice so explicit
+ targName = GeneralName.getInstance(tagObj, true);
+ break;
+ case targetGroup:
+ targGroup = GeneralName.getInstance(tagObj, true);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag: " + tagObj.getTagNo());
+ }
+ }
+
+ /**
+ * Constructor from given details.
+ * <p>
+ * Exactly one of the parameters must be not <code>null</code>.
+ *
+ * @param type the choice type to apply to the name.
+ * @param name the general name.
+ * @throws IllegalArgumentException if type is invalid.
+ */
+ public Target(int type, GeneralName name)
+ {
+ this(new DERTaggedObject(type, name));
+ }
+
+ /**
+ * @return Returns the targetGroup.
+ */
+ public GeneralName getTargetGroup()
+ {
+ return targGroup;
+ }
+
+ /**
+ * @return Returns the targetName.
+ */
+ public GeneralName getTargetName()
+ {
+ return targName;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ * <pre>
+ * Target ::= CHOICE {
+ * targetName [0] GeneralName,
+ * targetGroup [1] GeneralName,
+ * targetCert [2] TargetCert
+ * }
+ * </pre>
+ *
+ * @return a ASN1Primitive
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ // GeneralName is a choice already so most be explicitly tagged
+ if (targName != null)
+ {
+ return new DERTaggedObject(true, 0, targName);
+ }
+ else
+ {
+ return new DERTaggedObject(true, 1, targGroup);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/TargetInformation.java b/core/src/main/java/org/spongycastle/asn1/x509/TargetInformation.java
new file mode 100644
index 00000000..0b8c49a5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/TargetInformation.java
@@ -0,0 +1,120 @@
+package org.spongycastle.asn1.x509;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * Target information extension for attributes certificates according to RFC
+ * 3281.
+ *
+ * <pre>
+ * SEQUENCE OF Targets
+ * </pre>
+ *
+ */
+public class TargetInformation
+ extends ASN1Object
+{
+ private ASN1Sequence targets;
+
+ /**
+ * Creates an instance of a TargetInformation from the given object.
+ * <p>
+ * <code>obj</code> can be a TargetInformation or a {@link ASN1Sequence}
+ *
+ * @param obj The object.
+ * @return A TargetInformation instance.
+ * @throws IllegalArgumentException if the given object cannot be
+ * interpreted as TargetInformation.
+ */
+ public static TargetInformation getInstance(Object obj)
+ {
+ if (obj instanceof TargetInformation)
+ {
+ return (TargetInformation)obj;
+ }
+ else if (obj != null)
+ {
+ return new TargetInformation(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Constructor from a ASN1Sequence.
+ *
+ * @param seq The ASN1Sequence.
+ * @throws IllegalArgumentException if the sequence does not contain
+ * correctly encoded Targets elements.
+ */
+ private TargetInformation(ASN1Sequence seq)
+ {
+ targets = seq;
+ }
+
+ /**
+ * Returns the targets in this target information extension.
+ *
+ * @return Returns the targets.
+ */
+ public Targets[] getTargetsObjects()
+ {
+ Targets[] copy = new Targets[targets.size()];
+ int count = 0;
+ for (Enumeration e = targets.getObjects(); e.hasMoreElements();)
+ {
+ copy[count++] = Targets.getInstance(e.nextElement());
+ }
+ return copy;
+ }
+
+ /**
+ * Constructs a target information from a single targets element.
+ * According to RFC 3281 only one targets element must be produced.
+ *
+ * @param targets A Targets instance.
+ */
+ public TargetInformation(Targets targets)
+ {
+ this.targets = new DERSequence(targets);
+ }
+
+ /**
+ * According to RFC 3281 only one targets element must be produced. If
+ * multiple targets are given they must be merged in
+ * into one targets element.
+ *
+ * @param targets An array with {@link Targets}.
+ */
+ public TargetInformation(Target[] targets)
+ {
+ this(new Targets(targets));
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ * <pre>
+ * SEQUENCE OF Targets
+ * </pre>
+ *
+ * <p>
+ * According to RFC 3281 only one targets element must be produced. If
+ * multiple targets are given in the constructor they are merged into one
+ * targets element. If this was produced from a
+ * {@link org.spongycastle.asn1.ASN1Sequence} the encoding is kept.
+ *
+ * @return a ASN1Primitive
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return targets;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/Targets.java b/core/src/main/java/org/spongycastle/asn1/x509/Targets.java
new file mode 100644
index 00000000..a67b6984
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/Targets.java
@@ -0,0 +1,121 @@
+package org.spongycastle.asn1.x509;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * Targets structure used in target information extension for attribute
+ * certificates from RFC 3281.
+ *
+ * <pre>
+ * Targets ::= SEQUENCE OF Target
+ *
+ * Target ::= CHOICE {
+ * targetName [0] GeneralName,
+ * targetGroup [1] GeneralName,
+ * targetCert [2] TargetCert
+ * }
+ *
+ * TargetCert ::= SEQUENCE {
+ * targetCertificate IssuerSerial,
+ * targetName GeneralName OPTIONAL,
+ * certDigestInfo ObjectDigestInfo OPTIONAL
+ * }
+ * </pre>
+ *
+ * @see org.spongycastle.asn1.x509.Target
+ * @see org.spongycastle.asn1.x509.TargetInformation
+ */
+public class Targets
+ extends ASN1Object
+{
+ private ASN1Sequence targets;
+
+ /**
+ * Creates an instance of a Targets from the given object.
+ * <p>
+ * <code>obj</code> can be a Targets or a {@link ASN1Sequence}
+ *
+ * @param obj The object.
+ * @return A Targets instance.
+ * @throws IllegalArgumentException if the given object cannot be
+ * interpreted as Target.
+ */
+ public static Targets getInstance(Object obj)
+ {
+ if (obj instanceof Targets)
+ {
+ return (Targets)obj;
+ }
+ else if (obj != null)
+ {
+ return new Targets(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ *
+ * @param targets The ASN.1 SEQUENCE.
+ * @throws IllegalArgumentException if the contents of the sequence are
+ * invalid.
+ */
+ private Targets(ASN1Sequence targets)
+ {
+ this.targets = targets;
+ }
+
+ /**
+ * Constructor from given targets.
+ * <p>
+ * The vector is copied.
+ *
+ * @param targets A <code>Vector</code> of {@link Target}s.
+ * @see Target
+ * @throws IllegalArgumentException if the vector contains not only Targets.
+ */
+ public Targets(Target[] targets)
+ {
+ this.targets = new DERSequence(targets);
+ }
+
+ /**
+ * Returns the targets in a <code>Vector</code>.
+ * <p>
+ * The vector is cloned before it is returned.
+ *
+ * @return Returns the targets.
+ */
+ public Target[] getTargets()
+ {
+ Target[] targs = new Target[targets.size()];
+ int count = 0;
+ for (Enumeration e = targets.getObjects(); e.hasMoreElements();)
+ {
+ targs[count++] = Target.getInstance(e.nextElement());
+ }
+ return targs;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ * <pre>
+ * Targets ::= SEQUENCE OF Target
+ * </pre>
+ *
+ * @return a ASN1Primitive
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return targets;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/Time.java b/core/src/main/java/org/spongycastle/asn1/x509/Time.java
new file mode 100644
index 00000000..0cda6abf
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/Time.java
@@ -0,0 +1,169 @@
+package org.spongycastle.asn1.x509;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.SimpleTimeZone;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.ASN1UTCTime;
+import org.spongycastle.asn1.DERGeneralizedTime;
+import org.spongycastle.asn1.DERUTCTime;
+
+public class Time
+ extends ASN1Object
+ implements ASN1Choice
+{
+ ASN1Primitive time;
+
+ public static Time getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject()); // must be explicitly tagged
+ }
+
+ public Time(
+ ASN1Primitive time)
+ {
+ if (!(time instanceof ASN1UTCTime)
+ && !(time instanceof ASN1GeneralizedTime))
+ {
+ throw new IllegalArgumentException("unknown object passed to Time");
+ }
+
+ this.time = time;
+ }
+
+ /**
+ * Creates a time object from a given date - if the date is between 1950
+ * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
+ * is used.
+ *
+ * @param time a date object representing the time of interest.
+ */
+ public Time(
+ Date time)
+ {
+ SimpleTimeZone tz = new SimpleTimeZone(0, "Z");
+ SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss");
+
+ dateF.setTimeZone(tz);
+
+ String d = dateF.format(time) + "Z";
+ int year = Integer.parseInt(d.substring(0, 4));
+
+ if (year < 1950 || year > 2049)
+ {
+ this.time = new DERGeneralizedTime(d);
+ }
+ else
+ {
+ this.time = new DERUTCTime(d.substring(2));
+ }
+ }
+
+ /**
+ * Creates a time object from a given date and locale - if the date is between 1950
+ * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
+ * is used. You may need to use this constructor if the default locale
+ * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible with other ASN.1 implementations.
+ *
+ * @param time a date object representing the time of interest.
+ * @param locale an appropriate Locale for producing an ASN.1 GeneralizedTime value.
+ */
+ public Time(
+ Date time,
+ Locale locale)
+ {
+ SimpleTimeZone tz = new SimpleTimeZone(0, "Z");
+ SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss", locale);
+
+ dateF.setTimeZone(tz);
+
+ String d = dateF.format(time) + "Z";
+ int year = Integer.parseInt(d.substring(0, 4));
+
+ if (year < 1950 || year > 2049)
+ {
+ this.time = new DERGeneralizedTime(d);
+ }
+ else
+ {
+ this.time = new DERUTCTime(d.substring(2));
+ }
+ }
+
+ public static Time getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof Time)
+ {
+ return (Time)obj;
+ }
+ else if (obj instanceof ASN1UTCTime)
+ {
+ return new Time((ASN1UTCTime)obj);
+ }
+ else if (obj instanceof ASN1GeneralizedTime)
+ {
+ return new Time((ASN1GeneralizedTime)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
+ }
+
+ public String getTime()
+ {
+ if (time instanceof ASN1UTCTime)
+ {
+ return ((ASN1UTCTime)time).getAdjustedTime();
+ }
+ else
+ {
+ return ((ASN1GeneralizedTime)time).getTime();
+ }
+ }
+
+ public Date getDate()
+ {
+ try
+ {
+ if (time instanceof ASN1UTCTime)
+ {
+ return ((ASN1UTCTime)time).getAdjustedDate();
+ }
+ else
+ {
+ return ((ASN1GeneralizedTime)time).getDate();
+ }
+ }
+ catch (ParseException e)
+ { // this should never happen
+ throw new IllegalStateException("invalid date string: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * Time ::= CHOICE {
+ * utcTime UTCTime,
+ * generalTime GeneralizedTime }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return time;
+ }
+
+ public String toString()
+ {
+ return getTime();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/UserNotice.java b/core/src/main/java/org/spongycastle/asn1/x509/UserNotice.java
new file mode 100644
index 00000000..22c512c7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/UserNotice.java
@@ -0,0 +1,132 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * <code>UserNotice</code> class, used in
+ * <code>CertificatePolicies</code> X509 extensions (in policy
+ * qualifiers).
+ * <pre>
+ * UserNotice ::= SEQUENCE {
+ * noticeRef NoticeReference OPTIONAL,
+ * explicitText DisplayText OPTIONAL}
+ *
+ * </pre>
+ *
+ * @see PolicyQualifierId
+ * @see PolicyInformation
+ */
+public class UserNotice
+ extends ASN1Object
+{
+ private NoticeReference noticeRef;
+ private DisplayText explicitText;
+
+ /**
+ * Creates a new <code>UserNotice</code> instance.
+ *
+ * @param noticeRef a <code>NoticeReference</code> value
+ * @param explicitText a <code>DisplayText</code> value
+ */
+ public UserNotice(
+ NoticeReference noticeRef,
+ DisplayText explicitText)
+ {
+ this.noticeRef = noticeRef;
+ this.explicitText = explicitText;
+ }
+
+ /**
+ * Creates a new <code>UserNotice</code> instance.
+ *
+ * @param noticeRef a <code>NoticeReference</code> value
+ * @param str the explicitText field as a String.
+ */
+ public UserNotice(
+ NoticeReference noticeRef,
+ String str)
+ {
+ this(noticeRef, new DisplayText(str));
+ }
+
+ /**
+ * Creates a new <code>UserNotice</code> instance.
+ * <p>Useful from reconstructing a <code>UserNotice</code> instance
+ * from its encodable/encoded form.
+ *
+ * @param as an <code>ASN1Sequence</code> value obtained from either
+ * calling @{link toASN1Primitive()} for a <code>UserNotice</code>
+ * instance or from parsing it from a DER-encoded stream.
+ */
+ private UserNotice(
+ ASN1Sequence as)
+ {
+ if (as.size() == 2)
+ {
+ noticeRef = NoticeReference.getInstance(as.getObjectAt(0));
+ explicitText = DisplayText.getInstance(as.getObjectAt(1));
+ }
+ else if (as.size() == 1)
+ {
+ if (as.getObjectAt(0).toASN1Primitive() instanceof ASN1Sequence)
+ {
+ noticeRef = NoticeReference.getInstance(as.getObjectAt(0));
+ }
+ else
+ {
+ explicitText = DisplayText.getInstance(as.getObjectAt(0));
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + as.size());
+ }
+ }
+
+ public static UserNotice getInstance(
+ Object obj)
+ {
+ if (obj instanceof UserNotice)
+ {
+ return (UserNotice)obj;
+ }
+
+ if (obj != null)
+ {
+ return new UserNotice(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public NoticeReference getNoticeRef()
+ {
+ return noticeRef;
+ }
+
+ public DisplayText getExplicitText()
+ {
+ return explicitText;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector av = new ASN1EncodableVector();
+
+ if (noticeRef != null)
+ {
+ av.add(noticeRef);
+ }
+
+ if (explicitText != null)
+ {
+ av.add(explicitText);
+ }
+
+ return new DERSequence(av);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/V1TBSCertificateGenerator.java b/core/src/main/java/org/spongycastle/asn1/x509/V1TBSCertificateGenerator.java
new file mode 100644
index 00000000..415cabc1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/V1TBSCertificateGenerator.java
@@ -0,0 +1,144 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1UTCTime;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x500.X500Name;
+
+/**
+ * Generator for Version 1 TBSCertificateStructures.
+ * <pre>
+ * TBSCertificate ::= SEQUENCE {
+ * version [ 0 ] Version DEFAULT v1(0),
+ * serialNumber CertificateSerialNumber,
+ * signature AlgorithmIdentifier,
+ * issuer Name,
+ * validity Validity,
+ * subject Name,
+ * subjectPublicKeyInfo SubjectPublicKeyInfo,
+ * }
+ * </pre>
+ *
+ */
+public class V1TBSCertificateGenerator
+{
+ DERTaggedObject version = new DERTaggedObject(true, 0, new ASN1Integer(0));
+
+ ASN1Integer serialNumber;
+ AlgorithmIdentifier signature;
+ X500Name issuer;
+ Time startDate, endDate;
+ X500Name subject;
+ SubjectPublicKeyInfo subjectPublicKeyInfo;
+
+ public V1TBSCertificateGenerator()
+ {
+ }
+
+ public void setSerialNumber(
+ ASN1Integer serialNumber)
+ {
+ this.serialNumber = serialNumber;
+ }
+
+ public void setSignature(
+ AlgorithmIdentifier signature)
+ {
+ this.signature = signature;
+ }
+
+ /**
+ * @deprecated use X500Name method
+ */
+ public void setIssuer(
+ X509Name issuer)
+ {
+ this.issuer = X500Name.getInstance(issuer.toASN1Primitive());
+ }
+
+ public void setIssuer(
+ X500Name issuer)
+ {
+ this.issuer = issuer;
+ }
+
+ public void setStartDate(
+ Time startDate)
+ {
+ this.startDate = startDate;
+ }
+
+ public void setStartDate(
+ ASN1UTCTime startDate)
+ {
+ this.startDate = new Time(startDate);
+ }
+
+ public void setEndDate(
+ Time endDate)
+ {
+ this.endDate = endDate;
+ }
+
+ public void setEndDate(
+ ASN1UTCTime endDate)
+ {
+ this.endDate = new Time(endDate);
+ }
+
+ /**
+ * @deprecated use X500Name method
+ */
+ public void setSubject(
+ X509Name subject)
+ {
+ this.subject = X500Name.getInstance(subject.toASN1Primitive());
+ }
+
+ public void setSubject(
+ X500Name subject)
+ {
+ this.subject = subject;
+ }
+
+ public void setSubjectPublicKeyInfo(
+ SubjectPublicKeyInfo pubKeyInfo)
+ {
+ this.subjectPublicKeyInfo = pubKeyInfo;
+ }
+
+ public TBSCertificate generateTBSCertificate()
+ {
+ if ((serialNumber == null) || (signature == null)
+ || (issuer == null) || (startDate == null) || (endDate == null)
+ || (subject == null) || (subjectPublicKeyInfo == null))
+ {
+ throw new IllegalStateException("not all mandatory fields set in V1 TBScertificate generator");
+ }
+
+ ASN1EncodableVector seq = new ASN1EncodableVector();
+
+ // seq.add(version); - not required as default value.
+ seq.add(serialNumber);
+ seq.add(signature);
+ seq.add(issuer);
+
+ //
+ // before and after dates
+ //
+ ASN1EncodableVector validity = new ASN1EncodableVector();
+
+ validity.add(startDate);
+ validity.add(endDate);
+
+ seq.add(new DERSequence(validity));
+
+ seq.add(subject);
+
+ seq.add(subjectPublicKeyInfo);
+
+ return TBSCertificate.getInstance(new DERSequence(seq));
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/V2AttributeCertificateInfoGenerator.java b/core/src/main/java/org/spongycastle/asn1/x509/V2AttributeCertificateInfoGenerator.java
new file mode 100644
index 00000000..934e1c88
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/V2AttributeCertificateInfoGenerator.java
@@ -0,0 +1,158 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERSet;
+
+/**
+ * Generator for Version 2 AttributeCertificateInfo
+ * <pre>
+ * AttributeCertificateInfo ::= SEQUENCE {
+ * version AttCertVersion -- version is v2,
+ * holder Holder,
+ * issuer AttCertIssuer,
+ * signature AlgorithmIdentifier,
+ * serialNumber CertificateSerialNumber,
+ * attrCertValidityPeriod AttCertValidityPeriod,
+ * attributes SEQUENCE OF Attribute,
+ * issuerUniqueID UniqueIdentifier OPTIONAL,
+ * extensions Extensions OPTIONAL
+ * }
+ * </pre>
+ *
+ */
+public class V2AttributeCertificateInfoGenerator
+{
+ private ASN1Integer version;
+ private Holder holder;
+ private AttCertIssuer issuer;
+ private AlgorithmIdentifier signature;
+ private ASN1Integer serialNumber;
+ private ASN1EncodableVector attributes;
+ private DERBitString issuerUniqueID;
+ private Extensions extensions;
+
+ // Note: validity period start/end dates stored directly
+ //private AttCertValidityPeriod attrCertValidityPeriod;
+ private ASN1GeneralizedTime startDate, endDate;
+
+ public V2AttributeCertificateInfoGenerator()
+ {
+ this.version = new ASN1Integer(1);
+ attributes = new ASN1EncodableVector();
+ }
+
+ public void setHolder(Holder holder)
+ {
+ this.holder = holder;
+ }
+
+ public void addAttribute(String oid, ASN1Encodable value)
+ {
+ attributes.add(new Attribute(new ASN1ObjectIdentifier(oid), new DERSet(value)));
+ }
+
+ /**
+ * @param attribute
+ */
+ public void addAttribute(Attribute attribute)
+ {
+ attributes.add(attribute);
+ }
+
+ public void setSerialNumber(
+ ASN1Integer serialNumber)
+ {
+ this.serialNumber = serialNumber;
+ }
+
+ public void setSignature(
+ AlgorithmIdentifier signature)
+ {
+ this.signature = signature;
+ }
+
+ public void setIssuer(
+ AttCertIssuer issuer)
+ {
+ this.issuer = issuer;
+ }
+
+ public void setStartDate(
+ ASN1GeneralizedTime startDate)
+ {
+ this.startDate = startDate;
+ }
+
+ public void setEndDate(
+ ASN1GeneralizedTime endDate)
+ {
+ this.endDate = endDate;
+ }
+
+ public void setIssuerUniqueID(
+ DERBitString issuerUniqueID)
+ {
+ this.issuerUniqueID = issuerUniqueID;
+ }
+
+ /**
+ * @deprecated use method taking Extensions
+ * @param extensions
+ */
+ public void setExtensions(
+ X509Extensions extensions)
+ {
+ this.extensions = Extensions.getInstance(extensions.toASN1Primitive());
+ }
+
+ public void setExtensions(
+ Extensions extensions)
+ {
+ this.extensions = extensions;
+ }
+
+ public AttributeCertificateInfo generateAttributeCertificateInfo()
+ {
+ if ((serialNumber == null) || (signature == null)
+ || (issuer == null) || (startDate == null) || (endDate == null)
+ || (holder == null) || (attributes == null))
+ {
+ throw new IllegalStateException("not all mandatory fields set in V2 AttributeCertificateInfo generator");
+ }
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(holder);
+ v.add(issuer);
+ v.add(signature);
+ v.add(serialNumber);
+
+ //
+ // before and after dates => AttCertValidityPeriod
+ //
+ AttCertValidityPeriod validity = new AttCertValidityPeriod(startDate, endDate);
+ v.add(validity);
+
+ // Attributes
+ v.add(new DERSequence(attributes));
+
+ if (issuerUniqueID != null)
+ {
+ v.add(issuerUniqueID);
+ }
+
+ if (extensions != null)
+ {
+ v.add(extensions);
+ }
+
+ return AttributeCertificateInfo.getInstance(new DERSequence(v));
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/V2Form.java b/core/src/main/java/org/spongycastle/asn1/x509/V2Form.java
new file mode 100644
index 00000000..a94c4a54
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/V2Form.java
@@ -0,0 +1,157 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+public class V2Form
+ extends ASN1Object
+{
+ GeneralNames issuerName;
+ IssuerSerial baseCertificateID;
+ ObjectDigestInfo objectDigestInfo;
+
+ public static V2Form getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static V2Form getInstance(
+ Object obj)
+ {
+ if (obj instanceof V2Form)
+ {
+ return (V2Form)obj;
+ }
+ else if (obj != null)
+ {
+ return new V2Form(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public V2Form(
+ GeneralNames issuerName)
+ {
+ this(issuerName, null, null);
+ }
+
+ public V2Form(
+ GeneralNames issuerName,
+ IssuerSerial baseCertificateID)
+ {
+ this(issuerName, baseCertificateID, null);
+ }
+
+ public V2Form(
+ GeneralNames issuerName,
+ ObjectDigestInfo objectDigestInfo)
+ {
+ this(issuerName, null, objectDigestInfo);
+ }
+
+ public V2Form(
+ GeneralNames issuerName,
+ IssuerSerial baseCertificateID,
+ ObjectDigestInfo objectDigestInfo)
+ {
+ this.issuerName = issuerName;
+ this.baseCertificateID = baseCertificateID;
+ this.objectDigestInfo = objectDigestInfo;
+ }
+
+ /**
+ * @deprecated use getInstance().
+ */
+ public V2Form(
+ ASN1Sequence seq)
+ {
+ if (seq.size() > 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ int index = 0;
+
+ if (!(seq.getObjectAt(0) instanceof ASN1TaggedObject))
+ {
+ index++;
+ this.issuerName = GeneralNames.getInstance(seq.getObjectAt(0));
+ }
+
+ for (int i = index; i != seq.size(); i++)
+ {
+ ASN1TaggedObject o = ASN1TaggedObject.getInstance(seq.getObjectAt(i));
+ if (o.getTagNo() == 0)
+ {
+ baseCertificateID = IssuerSerial.getInstance(o, false);
+ }
+ else if (o.getTagNo() == 1)
+ {
+ objectDigestInfo = ObjectDigestInfo.getInstance(o, false);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad tag number: "
+ + o.getTagNo());
+ }
+ }
+ }
+
+ public GeneralNames getIssuerName()
+ {
+ return issuerName;
+ }
+
+ public IssuerSerial getBaseCertificateID()
+ {
+ return baseCertificateID;
+ }
+
+ public ObjectDigestInfo getObjectDigestInfo()
+ {
+ return objectDigestInfo;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * V2Form ::= SEQUENCE {
+ * issuerName GeneralNames OPTIONAL,
+ * baseCertificateID [0] IssuerSerial OPTIONAL,
+ * objectDigestInfo [1] ObjectDigestInfo OPTIONAL
+ * -- issuerName MUST be present in this profile
+ * -- baseCertificateID and objectDigestInfo MUST NOT
+ * -- be present in this profile
+ * }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (issuerName != null)
+ {
+ v.add(issuerName);
+ }
+
+ if (baseCertificateID != null)
+ {
+ v.add(new DERTaggedObject(false, 0, baseCertificateID));
+ }
+
+ if (objectDigestInfo != null)
+ {
+ v.add(new DERTaggedObject(false, 1, objectDigestInfo));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/V2TBSCertListGenerator.java b/core/src/main/java/org/spongycastle/asn1/x509/V2TBSCertListGenerator.java
new file mode 100644
index 00000000..8419470a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/V2TBSCertListGenerator.java
@@ -0,0 +1,281 @@
+package org.spongycastle.asn1.x509;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1UTCTime;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x500.X500Name;
+
+/**
+ * Generator for Version 2 TBSCertList structures.
+ * <pre>
+ * TBSCertList ::= SEQUENCE {
+ * version Version OPTIONAL,
+ * -- if present, shall be v2
+ * signature AlgorithmIdentifier,
+ * issuer Name,
+ * thisUpdate Time,
+ * nextUpdate Time OPTIONAL,
+ * revokedCertificates SEQUENCE OF SEQUENCE {
+ * userCertificate CertificateSerialNumber,
+ * revocationDate Time,
+ * crlEntryExtensions Extensions OPTIONAL
+ * -- if present, shall be v2
+ * } OPTIONAL,
+ * crlExtensions [0] EXPLICIT Extensions OPTIONAL
+ * -- if present, shall be v2
+ * }
+ * </pre>
+ *
+ * <b>Note: This class may be subject to change</b>
+ */
+public class V2TBSCertListGenerator
+{
+ private ASN1Integer version = new ASN1Integer(1);
+ private AlgorithmIdentifier signature;
+ private X500Name issuer;
+ private Time thisUpdate, nextUpdate=null;
+ private Extensions extensions = null;
+ private ASN1EncodableVector crlentries = new ASN1EncodableVector();
+
+ private final static ASN1Sequence[] reasons;
+
+ static
+ {
+ reasons = new ASN1Sequence[11];
+
+ reasons[0] = createReasonExtension(CRLReason.unspecified);
+ reasons[1] = createReasonExtension(CRLReason.keyCompromise);
+ reasons[2] = createReasonExtension(CRLReason.cACompromise);
+ reasons[3] = createReasonExtension(CRLReason.affiliationChanged);
+ reasons[4] = createReasonExtension(CRLReason.superseded);
+ reasons[5] = createReasonExtension(CRLReason.cessationOfOperation);
+ reasons[6] = createReasonExtension(CRLReason.certificateHold);
+ reasons[7] = createReasonExtension(7); // 7 -> unknown
+ reasons[8] = createReasonExtension(CRLReason.removeFromCRL);
+ reasons[9] = createReasonExtension(CRLReason.privilegeWithdrawn);
+ reasons[10] = createReasonExtension(CRLReason.aACompromise);
+ }
+
+ public V2TBSCertListGenerator()
+ {
+ }
+
+
+ public void setSignature(
+ AlgorithmIdentifier signature)
+ {
+ this.signature = signature;
+ }
+
+ /**
+ * @deprecated use X500Name method
+ */
+ public void setIssuer(
+ X509Name issuer)
+ {
+ this.issuer = X500Name.getInstance(issuer.toASN1Primitive());
+ }
+
+ public void setIssuer(X500Name issuer)
+ {
+ this.issuer = issuer;
+ }
+
+ public void setThisUpdate(
+ ASN1UTCTime thisUpdate)
+ {
+ this.thisUpdate = new Time(thisUpdate);
+ }
+
+ public void setNextUpdate(
+ ASN1UTCTime nextUpdate)
+ {
+ this.nextUpdate = new Time(nextUpdate);
+ }
+
+ public void setThisUpdate(
+ Time thisUpdate)
+ {
+ this.thisUpdate = thisUpdate;
+ }
+
+ public void setNextUpdate(
+ Time nextUpdate)
+ {
+ this.nextUpdate = nextUpdate;
+ }
+
+ public void addCRLEntry(
+ ASN1Sequence crlEntry)
+ {
+ crlentries.add(crlEntry);
+ }
+
+ public void addCRLEntry(ASN1Integer userCertificate, ASN1UTCTime revocationDate, int reason)
+ {
+ addCRLEntry(userCertificate, new Time(revocationDate), reason);
+ }
+
+ public void addCRLEntry(ASN1Integer userCertificate, Time revocationDate, int reason)
+ {
+ addCRLEntry(userCertificate, revocationDate, reason, null);
+ }
+
+ public void addCRLEntry(ASN1Integer userCertificate, Time revocationDate, int reason, ASN1GeneralizedTime invalidityDate)
+ {
+ if (reason != 0)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (reason < reasons.length)
+ {
+ if (reason < 0)
+ {
+ throw new IllegalArgumentException("invalid reason value: " + reason);
+ }
+ v.add(reasons[reason]);
+ }
+ else
+ {
+ v.add(createReasonExtension(reason));
+ }
+
+ if (invalidityDate != null)
+ {
+ v.add(createInvalidityDateExtension(invalidityDate));
+ }
+
+ internalAddCRLEntry(userCertificate, revocationDate, new DERSequence(v));
+ }
+ else if (invalidityDate != null)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(createInvalidityDateExtension(invalidityDate));
+
+ internalAddCRLEntry(userCertificate, revocationDate, new DERSequence(v));
+ }
+ else
+ {
+ addCRLEntry(userCertificate, revocationDate, null);
+ }
+ }
+
+ private void internalAddCRLEntry(ASN1Integer userCertificate, Time revocationDate, ASN1Sequence extensions)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(userCertificate);
+ v.add(revocationDate);
+
+ if (extensions != null)
+ {
+ v.add(extensions);
+ }
+
+ addCRLEntry(new DERSequence(v));
+ }
+
+ public void addCRLEntry(ASN1Integer userCertificate, Time revocationDate, Extensions extensions)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(userCertificate);
+ v.add(revocationDate);
+
+ if (extensions != null)
+ {
+ v.add(extensions);
+ }
+
+ addCRLEntry(new DERSequence(v));
+ }
+
+ public void setExtensions(
+ X509Extensions extensions)
+ {
+ setExtensions(Extensions.getInstance(extensions));
+ }
+
+ public void setExtensions(
+ Extensions extensions)
+ {
+ this.extensions = extensions;
+ }
+
+ public TBSCertList generateTBSCertList()
+ {
+ if ((signature == null) || (issuer == null) || (thisUpdate == null))
+ {
+ throw new IllegalStateException("Not all mandatory fields set in V2 TBSCertList generator.");
+ }
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(signature);
+ v.add(issuer);
+
+ v.add(thisUpdate);
+ if (nextUpdate != null)
+ {
+ v.add(nextUpdate);
+ }
+
+ // Add CRLEntries if they exist
+ if (crlentries.size() != 0)
+ {
+ v.add(new DERSequence(crlentries));
+ }
+
+ if (extensions != null)
+ {
+ v.add(new DERTaggedObject(0, extensions));
+ }
+
+ return new TBSCertList(new DERSequence(v));
+ }
+
+ private static ASN1Sequence createReasonExtension(int reasonCode)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ CRLReason crlReason = CRLReason.lookup(reasonCode);
+
+ try
+ {
+ v.add(Extension.reasonCode);
+ v.add(new DEROctetString(crlReason.getEncoded()));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("error encoding reason: " + e);
+ }
+
+ return new DERSequence(v);
+ }
+
+ private static ASN1Sequence createInvalidityDateExtension(ASN1GeneralizedTime invalidityDate)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ try
+ {
+ v.add(Extension.invalidityDate);
+ v.add(new DEROctetString(invalidityDate.getEncoded()));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("error encoding reason: " + e);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/V3TBSCertificateGenerator.java b/core/src/main/java/org/spongycastle/asn1/x509/V3TBSCertificateGenerator.java
new file mode 100644
index 00000000..26328cc5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/V3TBSCertificateGenerator.java
@@ -0,0 +1,212 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1UTCTime;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x500.X500Name;
+
+/**
+ * Generator for Version 3 TBSCertificateStructures.
+ * <pre>
+ * TBSCertificate ::= SEQUENCE {
+ * version [ 0 ] Version DEFAULT v1(0),
+ * serialNumber CertificateSerialNumber,
+ * signature AlgorithmIdentifier,
+ * issuer Name,
+ * validity Validity,
+ * subject Name,
+ * subjectPublicKeyInfo SubjectPublicKeyInfo,
+ * issuerUniqueID [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
+ * subjectUniqueID [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
+ * extensions [ 3 ] Extensions OPTIONAL
+ * }
+ * </pre>
+ *
+ */
+public class V3TBSCertificateGenerator
+{
+ DERTaggedObject version = new DERTaggedObject(true, 0, new ASN1Integer(2));
+
+ ASN1Integer serialNumber;
+ AlgorithmIdentifier signature;
+ X500Name issuer;
+ Time startDate, endDate;
+ X500Name subject;
+ SubjectPublicKeyInfo subjectPublicKeyInfo;
+ Extensions extensions;
+
+ private boolean altNamePresentAndCritical;
+ private DERBitString issuerUniqueID;
+ private DERBitString subjectUniqueID;
+
+ public V3TBSCertificateGenerator()
+ {
+ }
+
+ public void setSerialNumber(
+ ASN1Integer serialNumber)
+ {
+ this.serialNumber = serialNumber;
+ }
+
+ public void setSignature(
+ AlgorithmIdentifier signature)
+ {
+ this.signature = signature;
+ }
+
+ /**
+ * @deprecated use X500Name method
+ */
+ public void setIssuer(
+ X509Name issuer)
+ {
+ this.issuer = X500Name.getInstance(issuer);
+ }
+
+ public void setIssuer(
+ X500Name issuer)
+ {
+ this.issuer = issuer;
+ }
+
+ public void setStartDate(
+ ASN1UTCTime startDate)
+ {
+ this.startDate = new Time(startDate);
+ }
+
+ public void setStartDate(
+ Time startDate)
+ {
+ this.startDate = startDate;
+ }
+
+ public void setEndDate(
+ ASN1UTCTime endDate)
+ {
+ this.endDate = new Time(endDate);
+ }
+
+ public void setEndDate(
+ Time endDate)
+ {
+ this.endDate = endDate;
+ }
+
+ /**
+ * @deprecated use X500Name method
+ */
+ public void setSubject(
+ X509Name subject)
+ {
+ this.subject = X500Name.getInstance(subject.toASN1Primitive());
+ }
+
+ public void setSubject(
+ X500Name subject)
+ {
+ this.subject = subject;
+ }
+
+ public void setIssuerUniqueID(
+ DERBitString uniqueID)
+ {
+ this.issuerUniqueID = uniqueID;
+ }
+
+ public void setSubjectUniqueID(
+ DERBitString uniqueID)
+ {
+ this.subjectUniqueID = uniqueID;
+ }
+
+ public void setSubjectPublicKeyInfo(
+ SubjectPublicKeyInfo pubKeyInfo)
+ {
+ this.subjectPublicKeyInfo = pubKeyInfo;
+ }
+
+ /**
+ * @deprecated use method taking Extensions
+ * @param extensions
+ */
+ public void setExtensions(
+ X509Extensions extensions)
+ {
+ setExtensions(Extensions.getInstance(extensions));
+ }
+
+ public void setExtensions(
+ Extensions extensions)
+ {
+ this.extensions = extensions;
+ if (extensions != null)
+ {
+ Extension altName = extensions.getExtension(Extension.subjectAlternativeName);
+
+ if (altName != null && altName.isCritical())
+ {
+ altNamePresentAndCritical = true;
+ }
+ }
+ }
+
+ public TBSCertificate generateTBSCertificate()
+ {
+ if ((serialNumber == null) || (signature == null)
+ || (issuer == null) || (startDate == null) || (endDate == null)
+ || (subject == null && !altNamePresentAndCritical) || (subjectPublicKeyInfo == null))
+ {
+ throw new IllegalStateException("not all mandatory fields set in V3 TBScertificate generator");
+ }
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(serialNumber);
+ v.add(signature);
+ v.add(issuer);
+
+ //
+ // before and after dates
+ //
+ ASN1EncodableVector validity = new ASN1EncodableVector();
+
+ validity.add(startDate);
+ validity.add(endDate);
+
+ v.add(new DERSequence(validity));
+
+ if (subject != null)
+ {
+ v.add(subject);
+ }
+ else
+ {
+ v.add(new DERSequence());
+ }
+
+ v.add(subjectPublicKeyInfo);
+
+ if (issuerUniqueID != null)
+ {
+ v.add(new DERTaggedObject(false, 1, issuerUniqueID));
+ }
+
+ if (subjectUniqueID != null)
+ {
+ v.add(new DERTaggedObject(false, 2, subjectUniqueID));
+ }
+
+ if (extensions != null)
+ {
+ v.add(new DERTaggedObject(true, 3, extensions));
+ }
+
+ return TBSCertificate.getInstance(new DERSequence(v));
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/X509AttributeIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/x509/X509AttributeIdentifiers.java
new file mode 100644
index 00000000..28669a71
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/X509AttributeIdentifiers.java
@@ -0,0 +1,29 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+
+public interface X509AttributeIdentifiers
+{
+ /**
+ * @deprecated use id_at_role
+ */
+ static final ASN1ObjectIdentifier RoleSyntax = new ASN1ObjectIdentifier("2.5.4.72");
+
+ static final ASN1ObjectIdentifier id_pe_ac_auditIdentity = X509ObjectIdentifiers.id_pe.branch("4");
+ static final ASN1ObjectIdentifier id_pe_aaControls = X509ObjectIdentifiers.id_pe.branch("6");
+ static final ASN1ObjectIdentifier id_pe_ac_proxying = X509ObjectIdentifiers.id_pe.branch("10");
+
+ static final ASN1ObjectIdentifier id_ce_targetInformation= X509ObjectIdentifiers.id_ce.branch("55");
+
+ static final ASN1ObjectIdentifier id_aca = X509ObjectIdentifiers.id_pkix.branch("10");
+
+ static final ASN1ObjectIdentifier id_aca_authenticationInfo = id_aca.branch("1");
+ static final ASN1ObjectIdentifier id_aca_accessIdentity = id_aca.branch("2");
+ static final ASN1ObjectIdentifier id_aca_chargingIdentity = id_aca.branch("3");
+ static final ASN1ObjectIdentifier id_aca_group = id_aca.branch("4");
+ // { id-aca 5 } is reserved
+ static final ASN1ObjectIdentifier id_aca_encAttrs = id_aca.branch("6");
+
+ static final ASN1ObjectIdentifier id_at_role = new ASN1ObjectIdentifier("2.5.4.72");
+ static final ASN1ObjectIdentifier id_at_clearance = new ASN1ObjectIdentifier("2.5.1.5.55");
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/X509CertificateStructure.java b/core/src/main/java/org/spongycastle/asn1/x509/X509CertificateStructure.java
new file mode 100644
index 00000000..b7511792
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/X509CertificateStructure.java
@@ -0,0 +1,129 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.x500.X500Name;
+
+/**
+ * an X509Certificate structure.
+ * <pre>
+ * Certificate ::= SEQUENCE {
+ * tbsCertificate TBSCertificate,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING
+ * }
+ * </pre>
+ * @deprecated use org.spongycastle.asn1.x509.Certificate
+ */
+public class X509CertificateStructure
+ extends ASN1Object
+ implements X509ObjectIdentifiers, PKCSObjectIdentifiers
+{
+ ASN1Sequence seq;
+ TBSCertificateStructure tbsCert;
+ AlgorithmIdentifier sigAlgId;
+ DERBitString sig;
+
+ public static X509CertificateStructure getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static X509CertificateStructure getInstance(
+ Object obj)
+ {
+ if (obj instanceof X509CertificateStructure)
+ {
+ return (X509CertificateStructure)obj;
+ }
+ else if (obj != null)
+ {
+ return new X509CertificateStructure(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public X509CertificateStructure(
+ ASN1Sequence seq)
+ {
+ this.seq = seq;
+
+ //
+ // correct x509 certficate
+ //
+ if (seq.size() == 3)
+ {
+ tbsCert = TBSCertificateStructure.getInstance(seq.getObjectAt(0));
+ sigAlgId = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
+
+ sig = DERBitString.getInstance(seq.getObjectAt(2));
+ }
+ else
+ {
+ throw new IllegalArgumentException("sequence wrong size for a certificate");
+ }
+ }
+
+ public TBSCertificateStructure getTBSCertificate()
+ {
+ return tbsCert;
+ }
+
+ public int getVersion()
+ {
+ return tbsCert.getVersion();
+ }
+
+ public ASN1Integer getSerialNumber()
+ {
+ return tbsCert.getSerialNumber();
+ }
+
+ public X500Name getIssuer()
+ {
+ return tbsCert.getIssuer();
+ }
+
+ public Time getStartDate()
+ {
+ return tbsCert.getStartDate();
+ }
+
+ public Time getEndDate()
+ {
+ return tbsCert.getEndDate();
+ }
+
+ public X500Name getSubject()
+ {
+ return tbsCert.getSubject();
+ }
+
+ public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
+ {
+ return tbsCert.getSubjectPublicKeyInfo();
+ }
+
+ public AlgorithmIdentifier getSignatureAlgorithm()
+ {
+ return sigAlgId;
+ }
+
+ public DERBitString getSignature()
+ {
+ return sig;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return seq;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/X509DefaultEntryConverter.java b/core/src/main/java/org/spongycastle/asn1/x509/X509DefaultEntryConverter.java
new file mode 100644
index 00000000..38685b41
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/X509DefaultEntryConverter.java
@@ -0,0 +1,65 @@
+package org.spongycastle.asn1.x509;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DERGeneralizedTime;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.DERPrintableString;
+import org.spongycastle.asn1.DERUTF8String;
+
+/**
+ * The default converter for X509 DN entries when going from their
+ * string value to ASN.1 strings.
+ */
+public class X509DefaultEntryConverter
+ extends X509NameEntryConverter
+{
+ /**
+ * Apply default coversion for the given value depending on the oid
+ * and the character range of the value.
+ *
+ * @param oid the object identifier for the DN entry
+ * @param value the value associated with it
+ * @return the ASN.1 equivalent for the string value.
+ */
+ public ASN1Primitive getConvertedValue(
+ ASN1ObjectIdentifier oid,
+ String value)
+ {
+ if (value.length() != 0 && value.charAt(0) == '#')
+ {
+ try
+ {
+ return convertHexEncoded(value, 1);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("can't recode value for oid " + oid.getId());
+ }
+ }
+ else
+ {
+ if (value.length() != 0 && value.charAt(0) == '\\')
+ {
+ value = value.substring(1);
+ }
+ if (oid.equals(X509Name.EmailAddress) || oid.equals(X509Name.DC))
+ {
+ return new DERIA5String(value);
+ }
+ else if (oid.equals(X509Name.DATE_OF_BIRTH)) // accept time string as well as # (for compatibility)
+ {
+ return new DERGeneralizedTime(value);
+ }
+ else if (oid.equals(X509Name.C) || oid.equals(X509Name.SN) || oid.equals(X509Name.DN_QUALIFIER)
+ || oid.equals(X509Name.TELEPHONE_NUMBER))
+ {
+ return new DERPrintableString(value);
+ }
+ }
+
+ return new DERUTF8String(value);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/X509Extension.java b/core/src/main/java/org/spongycastle/asn1/x509/X509Extension.java
new file mode 100644
index 00000000..6537d80f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/X509Extension.java
@@ -0,0 +1,249 @@
+package org.spongycastle.asn1.x509;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Boolean;
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+
+/**
+ * an object for the elements in the X.509 V3 extension block.
+ * @deprecated use Extension
+ */
+public class X509Extension
+{
+ /**
+ * Subject Directory Attributes
+ */
+ public static final ASN1ObjectIdentifier subjectDirectoryAttributes = new ASN1ObjectIdentifier("2.5.29.9");
+
+ /**
+ * Subject Key Identifier
+ */
+ public static final ASN1ObjectIdentifier subjectKeyIdentifier = new ASN1ObjectIdentifier("2.5.29.14");
+
+ /**
+ * Key Usage
+ */
+ public static final ASN1ObjectIdentifier keyUsage = new ASN1ObjectIdentifier("2.5.29.15");
+
+ /**
+ * Private Key Usage Period
+ */
+ public static final ASN1ObjectIdentifier privateKeyUsagePeriod = new ASN1ObjectIdentifier("2.5.29.16");
+
+ /**
+ * Subject Alternative Name
+ */
+ public static final ASN1ObjectIdentifier subjectAlternativeName = new ASN1ObjectIdentifier("2.5.29.17");
+
+ /**
+ * Issuer Alternative Name
+ */
+ public static final ASN1ObjectIdentifier issuerAlternativeName = new ASN1ObjectIdentifier("2.5.29.18");
+
+ /**
+ * Basic Constraints
+ */
+ public static final ASN1ObjectIdentifier basicConstraints = new ASN1ObjectIdentifier("2.5.29.19");
+
+ /**
+ * CRL Number
+ */
+ public static final ASN1ObjectIdentifier cRLNumber = new ASN1ObjectIdentifier("2.5.29.20");
+
+ /**
+ * Reason code
+ */
+ public static final ASN1ObjectIdentifier reasonCode = new ASN1ObjectIdentifier("2.5.29.21");
+
+ /**
+ * Hold Instruction Code
+ */
+ public static final ASN1ObjectIdentifier instructionCode = new ASN1ObjectIdentifier("2.5.29.23");
+
+ /**
+ * Invalidity Date
+ */
+ public static final ASN1ObjectIdentifier invalidityDate = new ASN1ObjectIdentifier("2.5.29.24");
+
+ /**
+ * Delta CRL indicator
+ */
+ public static final ASN1ObjectIdentifier deltaCRLIndicator = new ASN1ObjectIdentifier("2.5.29.27");
+
+ /**
+ * Issuing Distribution Point
+ */
+ public static final ASN1ObjectIdentifier issuingDistributionPoint = new ASN1ObjectIdentifier("2.5.29.28");
+
+ /**
+ * Certificate Issuer
+ */
+ public static final ASN1ObjectIdentifier certificateIssuer = new ASN1ObjectIdentifier("2.5.29.29");
+
+ /**
+ * Name Constraints
+ */
+ public static final ASN1ObjectIdentifier nameConstraints = new ASN1ObjectIdentifier("2.5.29.30");
+
+ /**
+ * CRL Distribution Points
+ */
+ public static final ASN1ObjectIdentifier cRLDistributionPoints = new ASN1ObjectIdentifier("2.5.29.31");
+
+ /**
+ * Certificate Policies
+ */
+ public static final ASN1ObjectIdentifier certificatePolicies = new ASN1ObjectIdentifier("2.5.29.32");
+
+ /**
+ * Policy Mappings
+ */
+ public static final ASN1ObjectIdentifier policyMappings = new ASN1ObjectIdentifier("2.5.29.33");
+
+ /**
+ * Authority Key Identifier
+ */
+ public static final ASN1ObjectIdentifier authorityKeyIdentifier = new ASN1ObjectIdentifier("2.5.29.35");
+
+ /**
+ * Policy Constraints
+ */
+ public static final ASN1ObjectIdentifier policyConstraints = new ASN1ObjectIdentifier("2.5.29.36");
+
+ /**
+ * Extended Key Usage
+ */
+ public static final ASN1ObjectIdentifier extendedKeyUsage = new ASN1ObjectIdentifier("2.5.29.37");
+
+ /**
+ * Freshest CRL
+ */
+ public static final ASN1ObjectIdentifier freshestCRL = new ASN1ObjectIdentifier("2.5.29.46");
+
+ /**
+ * Inhibit Any Policy
+ */
+ public static final ASN1ObjectIdentifier inhibitAnyPolicy = new ASN1ObjectIdentifier("2.5.29.54");
+
+ /**
+ * Authority Info Access
+ */
+ public static final ASN1ObjectIdentifier authorityInfoAccess = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.1");
+
+ /**
+ * Subject Info Access
+ */
+ public static final ASN1ObjectIdentifier subjectInfoAccess = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.11");
+
+ /**
+ * Logo Type
+ */
+ public static final ASN1ObjectIdentifier logoType = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.12");
+
+ /**
+ * BiometricInfo
+ */
+ public static final ASN1ObjectIdentifier biometricInfo = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.2");
+
+ /**
+ * QCStatements
+ */
+ public static final ASN1ObjectIdentifier qCStatements = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.3");
+
+ /**
+ * Audit identity extension in attribute certificates.
+ */
+ public static final ASN1ObjectIdentifier auditIdentity = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.4");
+
+ /**
+ * NoRevAvail extension in attribute certificates.
+ */
+ public static final ASN1ObjectIdentifier noRevAvail = new ASN1ObjectIdentifier("2.5.29.56");
+
+ /**
+ * TargetInformation extension in attribute certificates.
+ */
+ public static final ASN1ObjectIdentifier targetInformation = new ASN1ObjectIdentifier("2.5.29.55");
+
+ boolean critical;
+ ASN1OctetString value;
+
+ public X509Extension(
+ ASN1Boolean critical,
+ ASN1OctetString value)
+ {
+ this.critical = critical.isTrue();
+ this.value = value;
+ }
+
+ public X509Extension(
+ boolean critical,
+ ASN1OctetString value)
+ {
+ this.critical = critical;
+ this.value = value;
+ }
+
+ public boolean isCritical()
+ {
+ return critical;
+ }
+
+ public ASN1OctetString getValue()
+ {
+ return value;
+ }
+
+ public ASN1Encodable getParsedValue()
+ {
+ return convertValueToObject(this);
+ }
+
+ public int hashCode()
+ {
+ if (this.isCritical())
+ {
+ return this.getValue().hashCode();
+ }
+
+ return ~this.getValue().hashCode();
+ }
+
+ public boolean equals(
+ Object o)
+ {
+ if (!(o instanceof X509Extension))
+ {
+ return false;
+ }
+
+ X509Extension other = (X509Extension)o;
+
+ return other.getValue().equals(this.getValue())
+ && (other.isCritical() == this.isCritical());
+ }
+
+ /**
+ * Convert the value of the passed in extension to an object
+ * @param ext the extension to parse
+ * @return the object the value string contains
+ * @exception IllegalArgumentException if conversion is not possible
+ */
+ public static ASN1Primitive convertValueToObject(
+ X509Extension ext)
+ throws IllegalArgumentException
+ {
+ try
+ {
+ return ASN1Primitive.fromByteArray(ext.getValue().getOctets());
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("can't convert extension: " + e);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/X509Extensions.java b/core/src/main/java/org/spongycastle/asn1/x509/X509Extensions.java
new file mode 100644
index 00000000..fb2cf923
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/X509Extensions.java
@@ -0,0 +1,477 @@
+package org.spongycastle.asn1.x509;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.spongycastle.asn1.ASN1Boolean;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * @deprecated use Extensions
+ */
+public class X509Extensions
+ extends ASN1Object
+{
+ /**
+ * Subject Directory Attributes
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier SubjectDirectoryAttributes = new ASN1ObjectIdentifier("2.5.29.9");
+
+ /**
+ * Subject Key Identifier
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier SubjectKeyIdentifier = new ASN1ObjectIdentifier("2.5.29.14");
+
+ /**
+ * Key Usage
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier KeyUsage = new ASN1ObjectIdentifier("2.5.29.15");
+
+ /**
+ * Private Key Usage Period
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier PrivateKeyUsagePeriod = new ASN1ObjectIdentifier("2.5.29.16");
+
+ /**
+ * Subject Alternative Name
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier SubjectAlternativeName = new ASN1ObjectIdentifier("2.5.29.17");
+
+ /**
+ * Issuer Alternative Name
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier IssuerAlternativeName = new ASN1ObjectIdentifier("2.5.29.18");
+
+ /**
+ * Basic Constraints
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier BasicConstraints = new ASN1ObjectIdentifier("2.5.29.19");
+
+ /**
+ * CRL Number
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier CRLNumber = new ASN1ObjectIdentifier("2.5.29.20");
+
+ /**
+ * Reason code
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier ReasonCode = new ASN1ObjectIdentifier("2.5.29.21");
+
+ /**
+ * Hold Instruction Code
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier InstructionCode = new ASN1ObjectIdentifier("2.5.29.23");
+
+ /**
+ * Invalidity Date
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier InvalidityDate = new ASN1ObjectIdentifier("2.5.29.24");
+
+ /**
+ * Delta CRL indicator
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier DeltaCRLIndicator = new ASN1ObjectIdentifier("2.5.29.27");
+
+ /**
+ * Issuing Distribution Point
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier IssuingDistributionPoint = new ASN1ObjectIdentifier("2.5.29.28");
+
+ /**
+ * Certificate Issuer
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier CertificateIssuer = new ASN1ObjectIdentifier("2.5.29.29");
+
+ /**
+ * Name Constraints
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier NameConstraints = new ASN1ObjectIdentifier("2.5.29.30");
+
+ /**
+ * CRL Distribution Points
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier CRLDistributionPoints = new ASN1ObjectIdentifier("2.5.29.31");
+
+ /**
+ * Certificate Policies
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier CertificatePolicies = new ASN1ObjectIdentifier("2.5.29.32");
+
+ /**
+ * Policy Mappings
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier PolicyMappings = new ASN1ObjectIdentifier("2.5.29.33");
+
+ /**
+ * Authority Key Identifier
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier AuthorityKeyIdentifier = new ASN1ObjectIdentifier("2.5.29.35");
+
+ /**
+ * Policy Constraints
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier PolicyConstraints = new ASN1ObjectIdentifier("2.5.29.36");
+
+ /**
+ * Extended Key Usage
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier ExtendedKeyUsage = new ASN1ObjectIdentifier("2.5.29.37");
+
+ /**
+ * Freshest CRL
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier FreshestCRL = new ASN1ObjectIdentifier("2.5.29.46");
+
+ /**
+ * Inhibit Any Policy
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier InhibitAnyPolicy = new ASN1ObjectIdentifier("2.5.29.54");
+
+ /**
+ * Authority Info Access
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier AuthorityInfoAccess = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.1");
+
+ /**
+ * Subject Info Access
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier SubjectInfoAccess = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.11");
+
+ /**
+ * Logo Type
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier LogoType = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.12");
+
+ /**
+ * BiometricInfo
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier BiometricInfo = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.2");
+
+ /**
+ * QCStatements
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier QCStatements = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.3");
+
+ /**
+ * Audit identity extension in attribute certificates.
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier AuditIdentity = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.4");
+
+ /**
+ * NoRevAvail extension in attribute certificates.
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier NoRevAvail = new ASN1ObjectIdentifier("2.5.29.56");
+
+ /**
+ * TargetInformation extension in attribute certificates.
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier TargetInformation = new ASN1ObjectIdentifier("2.5.29.55");
+
+ private Hashtable extensions = new Hashtable();
+ private Vector ordering = new Vector();
+
+ public static X509Extensions getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static X509Extensions getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof X509Extensions)
+ {
+ return (X509Extensions)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new X509Extensions((ASN1Sequence)obj);
+ }
+
+ if (obj instanceof Extensions)
+ {
+ return new X509Extensions((ASN1Sequence)((Extensions)obj).toASN1Primitive());
+ }
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ return getInstance(((ASN1TaggedObject)obj).getObject());
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ *
+ * the extensions are a list of constructed sequences, either with (OID, OctetString) or (OID, Boolean, OctetString)
+ */
+ public X509Extensions(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ ASN1Sequence s = ASN1Sequence.getInstance(e.nextElement());
+
+ if (s.size() == 3)
+ {
+ extensions.put(s.getObjectAt(0), new X509Extension(ASN1Boolean.getInstance(s.getObjectAt(1)), ASN1OctetString.getInstance(s.getObjectAt(2))));
+ }
+ else if (s.size() == 2)
+ {
+ extensions.put(s.getObjectAt(0), new X509Extension(false, ASN1OctetString.getInstance(s.getObjectAt(1))));
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + s.size());
+ }
+
+ ordering.addElement(s.getObjectAt(0));
+ }
+ }
+
+ /**
+ * constructor from a table of extensions.
+ * <p>
+ * it's is assumed the table contains OID/String pairs.
+ */
+ public X509Extensions(
+ Hashtable extensions)
+ {
+ this(null, extensions);
+ }
+
+ /**
+ * Constructor from a table of extensions with ordering.
+ * <p>
+ * It's is assumed the table contains OID/String pairs.
+ * @deprecated use Extensions
+ */
+ public X509Extensions(
+ Vector ordering,
+ Hashtable extensions)
+ {
+ Enumeration e;
+
+ if (ordering == null)
+ {
+ e = extensions.keys();
+ }
+ else
+ {
+ e = ordering.elements();
+ }
+
+ while (e.hasMoreElements())
+ {
+ this.ordering.addElement(ASN1ObjectIdentifier.getInstance(e.nextElement()));
+ }
+
+ e = this.ordering.elements();
+
+ while (e.hasMoreElements())
+ {
+ ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(e.nextElement());
+ X509Extension ext = (X509Extension)extensions.get(oid);
+
+ this.extensions.put(oid, ext);
+ }
+ }
+
+ /**
+ * Constructor from two vectors
+ *
+ * @param objectIDs a vector of the object identifiers.
+ * @param values a vector of the extension values.
+ * @deprecated use Extensions
+ */
+ public X509Extensions(
+ Vector objectIDs,
+ Vector values)
+ {
+ Enumeration e = objectIDs.elements();
+
+ while (e.hasMoreElements())
+ {
+ this.ordering.addElement(e.nextElement());
+ }
+
+ int count = 0;
+
+ e = this.ordering.elements();
+
+ while (e.hasMoreElements())
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
+ X509Extension ext = (X509Extension)values.elementAt(count);
+
+ this.extensions.put(oid, ext);
+ count++;
+ }
+ }
+
+ /**
+ * return an Enumeration of the extension field's object ids.
+ */
+ public Enumeration oids()
+ {
+ return ordering.elements();
+ }
+
+ /**
+ * return the extension represented by the object identifier
+ * passed in.
+ *
+ * @return the extension if it's present, null otherwise.
+ */
+ public X509Extension getExtension(
+ ASN1ObjectIdentifier oid)
+ {
+ return (X509Extension)extensions.get(oid);
+ }
+
+ /**
+ * <pre>
+ * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+ *
+ * Extension ::= SEQUENCE {
+ * extnId EXTENSION.&amp;id ({ExtensionSet}),
+ * critical BOOLEAN DEFAULT FALSE,
+ * extnValue OCTET STRING }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+ Enumeration e = ordering.elements();
+
+ while (e.hasMoreElements())
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
+ X509Extension ext = (X509Extension)extensions.get(oid);
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(oid);
+
+ if (ext.isCritical())
+ {
+ v.add(ASN1Boolean.TRUE);
+ }
+
+ v.add(ext.getValue());
+
+ vec.add(new DERSequence(v));
+ }
+
+ return new DERSequence(vec);
+ }
+
+ public boolean equivalent(
+ X509Extensions other)
+ {
+ if (extensions.size() != other.extensions.size())
+ {
+ return false;
+ }
+
+ Enumeration e1 = extensions.keys();
+
+ while (e1.hasMoreElements())
+ {
+ Object key = e1.nextElement();
+
+ if (!extensions.get(key).equals(other.extensions.get(key)))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public ASN1ObjectIdentifier[] getExtensionOIDs()
+ {
+ return toOidArray(ordering);
+ }
+
+ public ASN1ObjectIdentifier[] getNonCriticalExtensionOIDs()
+ {
+ return getExtensionOIDs(false);
+ }
+
+ public ASN1ObjectIdentifier[] getCriticalExtensionOIDs()
+ {
+ return getExtensionOIDs(true);
+ }
+
+ private ASN1ObjectIdentifier[] getExtensionOIDs(boolean isCritical)
+ {
+ Vector oidVec = new Vector();
+
+ for (int i = 0; i != ordering.size(); i++)
+ {
+ Object oid = ordering.elementAt(i);
+
+ if (((X509Extension)extensions.get(oid)).isCritical() == isCritical)
+ {
+ oidVec.addElement(oid);
+ }
+ }
+
+ return toOidArray(oidVec);
+ }
+
+ private ASN1ObjectIdentifier[] toOidArray(Vector oidVec)
+ {
+ ASN1ObjectIdentifier[] oids = new ASN1ObjectIdentifier[oidVec.size()];
+
+ for (int i = 0; i != oids.length; i++)
+ {
+ oids[i] = (ASN1ObjectIdentifier)oidVec.elementAt(i);
+ }
+ return oids;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/X509ExtensionsGenerator.java b/core/src/main/java/org/spongycastle/asn1/x509/X509ExtensionsGenerator.java
new file mode 100644
index 00000000..af8fc9bb
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/X509ExtensionsGenerator.java
@@ -0,0 +1,94 @@
+package org.spongycastle.asn1.x509;
+
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Encoding;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.DEROctetString;
+
+/**
+ * Generator for X.509 extensions
+ * @deprecated use org.spongycastle.asn1.x509.ExtensionsGenerator
+ */
+public class X509ExtensionsGenerator
+{
+ private Hashtable extensions = new Hashtable();
+ private Vector extOrdering = new Vector();
+
+ /**
+ * Reset the generator
+ */
+ public void reset()
+ {
+ extensions = new Hashtable();
+ extOrdering = new Vector();
+ }
+
+ /**
+ * Add an extension with the given oid and the passed in value to be included
+ * in the OCTET STRING associated with the extension.
+ *
+ * @param oid OID for the extension.
+ * @param critical true if critical, false otherwise.
+ * @param value the ASN.1 object to be included in the extension.
+ */
+ public void addExtension(
+ ASN1ObjectIdentifier oid,
+ boolean critical,
+ ASN1Encodable value)
+ {
+ try
+ {
+ this.addExtension(oid, critical, value.toASN1Primitive().getEncoded(ASN1Encoding.DER));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("error encoding value: " + e);
+ }
+ }
+
+ /**
+ * Add an extension with the given oid and the passed in byte array to be wrapped in the
+ * OCTET STRING associated with the extension.
+ *
+ * @param oid OID for the extension.
+ * @param critical true if critical, false otherwise.
+ * @param value the byte array to be wrapped.
+ */
+ public void addExtension(
+ ASN1ObjectIdentifier oid,
+ boolean critical,
+ byte[] value)
+ {
+ if (extensions.containsKey(oid))
+ {
+ throw new IllegalArgumentException("extension " + oid + " already added");
+ }
+
+ extOrdering.addElement(oid);
+ extensions.put(oid, new X509Extension(critical, new DEROctetString(value)));
+ }
+
+ /**
+ * Return true if there are no extension present in this generator.
+ *
+ * @return true if empty, false otherwise
+ */
+ public boolean isEmpty()
+ {
+ return extOrdering.isEmpty();
+ }
+
+ /**
+ * Generate an X509Extensions object based on the current state of the generator.
+ *
+ * @return an X09Extensions object.
+ */
+ public X509Extensions generate()
+ {
+ return new X509Extensions(extOrdering, extensions);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/X509Name.java b/core/src/main/java/org/spongycastle/asn1/x509/X509Name.java
new file mode 100644
index 00000000..7d2fedf8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/X509Name.java
@@ -0,0 +1,1379 @@
+package org.spongycastle.asn1.x509;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Encoding;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.ASN1String;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERSet;
+import org.spongycastle.asn1.DERUniversalString;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.x500.X500Name;
+import org.spongycastle.util.Strings;
+import org.spongycastle.util.encoders.Hex;
+
+/**
+ * <pre>
+ * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+ *
+ * RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
+ *
+ * AttributeTypeAndValue ::= SEQUENCE {
+ * type OBJECT IDENTIFIER,
+ * value ANY }
+ * </pre>
+ * @deprecated use org.spongycastle.asn1.x500.X500Name.
+ */
+public class X509Name
+ extends ASN1Object
+{
+ /**
+ * country code - StringType(SIZE(2))
+ * @deprecated use a X500NameStyle
+ */
+ public static final ASN1ObjectIdentifier C = new ASN1ObjectIdentifier("2.5.4.6");
+
+ /**
+ * organization - StringType(SIZE(1..64))
+ * @deprecated use a X500NameStyle
+ */
+ public static final ASN1ObjectIdentifier O = new ASN1ObjectIdentifier("2.5.4.10");
+
+ /**
+ * organizational unit name - StringType(SIZE(1..64))
+ * @deprecated use a X500NameStyle
+ */
+ public static final ASN1ObjectIdentifier OU = new ASN1ObjectIdentifier("2.5.4.11");
+
+ /**
+ * Title
+ * @deprecated use a X500NameStyle
+ */
+ public static final ASN1ObjectIdentifier T = new ASN1ObjectIdentifier("2.5.4.12");
+
+ /**
+ * common name - StringType(SIZE(1..64))
+ * @deprecated use a X500NameStyle
+ */
+ public static final ASN1ObjectIdentifier CN = new ASN1ObjectIdentifier("2.5.4.3");
+
+ /**
+ * device serial number name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier SN = new ASN1ObjectIdentifier("2.5.4.5");
+
+ /**
+ * street - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier STREET = new ASN1ObjectIdentifier("2.5.4.9");
+
+ /**
+ * device serial number name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier SERIALNUMBER = SN;
+
+ /**
+ * locality name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier L = new ASN1ObjectIdentifier("2.5.4.7");
+
+ /**
+ * state, or province name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier ST = new ASN1ObjectIdentifier("2.5.4.8");
+
+ /**
+ * Naming attributes of type X520name
+ */
+ public static final ASN1ObjectIdentifier SURNAME = new ASN1ObjectIdentifier("2.5.4.4");
+ public static final ASN1ObjectIdentifier GIVENNAME = new ASN1ObjectIdentifier("2.5.4.42");
+ public static final ASN1ObjectIdentifier INITIALS = new ASN1ObjectIdentifier("2.5.4.43");
+ public static final ASN1ObjectIdentifier GENERATION = new ASN1ObjectIdentifier("2.5.4.44");
+ public static final ASN1ObjectIdentifier UNIQUE_IDENTIFIER = new ASN1ObjectIdentifier("2.5.4.45");
+
+ /**
+ * businessCategory - DirectoryString(SIZE(1..128)
+ */
+ public static final ASN1ObjectIdentifier BUSINESS_CATEGORY = new ASN1ObjectIdentifier(
+ "2.5.4.15");
+
+ /**
+ * postalCode - DirectoryString(SIZE(1..40)
+ */
+ public static final ASN1ObjectIdentifier POSTAL_CODE = new ASN1ObjectIdentifier(
+ "2.5.4.17");
+
+ /**
+ * dnQualifier - DirectoryString(SIZE(1..64)
+ */
+ public static final ASN1ObjectIdentifier DN_QUALIFIER = new ASN1ObjectIdentifier(
+ "2.5.4.46");
+
+ /**
+ * RFC 3039 Pseudonym - DirectoryString(SIZE(1..64)
+ */
+ public static final ASN1ObjectIdentifier PSEUDONYM = new ASN1ObjectIdentifier(
+ "2.5.4.65");
+
+
+ /**
+ * RFC 3039 DateOfBirth - GeneralizedTime - YYYYMMDD000000Z
+ */
+ public static final ASN1ObjectIdentifier DATE_OF_BIRTH = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.1");
+
+ /**
+ * RFC 3039 PlaceOfBirth - DirectoryString(SIZE(1..128)
+ */
+ public static final ASN1ObjectIdentifier PLACE_OF_BIRTH = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.2");
+
+ /**
+ * RFC 3039 Gender - PrintableString (SIZE(1)) -- "M", "F", "m" or "f"
+ */
+ public static final ASN1ObjectIdentifier GENDER = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.3");
+
+ /**
+ * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
+ * codes only
+ */
+ public static final ASN1ObjectIdentifier COUNTRY_OF_CITIZENSHIP = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.4");
+
+ /**
+ * RFC 3039 CountryOfResidence - PrintableString (SIZE (2)) -- ISO 3166
+ * codes only
+ */
+ public static final ASN1ObjectIdentifier COUNTRY_OF_RESIDENCE = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.5");
+
+
+ /**
+ * ISIS-MTT NameAtBirth - DirectoryString(SIZE(1..64)
+ */
+ public static final ASN1ObjectIdentifier NAME_AT_BIRTH = new ASN1ObjectIdentifier("1.3.36.8.3.14");
+
+ /**
+ * RFC 3039 PostalAddress - SEQUENCE SIZE (1..6) OF
+ * DirectoryString(SIZE(1..30))
+ */
+ public static final ASN1ObjectIdentifier POSTAL_ADDRESS = new ASN1ObjectIdentifier("2.5.4.16");
+
+ /**
+ * RFC 2256 dmdName
+ */
+ public static final ASN1ObjectIdentifier DMD_NAME = new ASN1ObjectIdentifier("2.5.4.54");
+
+ /**
+ * id-at-telephoneNumber
+ */
+ public static final ASN1ObjectIdentifier TELEPHONE_NUMBER = X509ObjectIdentifiers.id_at_telephoneNumber;
+
+ /**
+ * id-at-name
+ */
+ public static final ASN1ObjectIdentifier NAME = X509ObjectIdentifiers.id_at_name;
+
+ /**
+ * Email address (RSA PKCS#9 extension) - IA5String.
+ * <p>Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.
+ * @deprecated use a X500NameStyle
+ */
+ public static final ASN1ObjectIdentifier EmailAddress = PKCSObjectIdentifiers.pkcs_9_at_emailAddress;
+
+ /**
+ * more from PKCS#9
+ */
+ public static final ASN1ObjectIdentifier UnstructuredName = PKCSObjectIdentifiers.pkcs_9_at_unstructuredName;
+ public static final ASN1ObjectIdentifier UnstructuredAddress = PKCSObjectIdentifiers.pkcs_9_at_unstructuredAddress;
+
+ /**
+ * email address in Verisign certificates
+ */
+ public static final ASN1ObjectIdentifier E = EmailAddress;
+
+ /*
+ * others...
+ */
+ public static final ASN1ObjectIdentifier DC = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.25");
+
+ /**
+ * LDAP User id.
+ */
+ public static final ASN1ObjectIdentifier UID = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.1");
+
+ /**
+ * determines whether or not strings should be processed and printed
+ * from back to front.
+ */
+ public static boolean DefaultReverse = false;
+
+ /**
+ * default look up table translating OID values into their common symbols following
+ * the convention in RFC 2253 with a few extras
+ */
+ public static final Hashtable DefaultSymbols = new Hashtable();
+
+ /**
+ * look up table translating OID values into their common symbols following the convention in RFC 2253
+ *
+ */
+ public static final Hashtable RFC2253Symbols = new Hashtable();
+
+ /**
+ * look up table translating OID values into their common symbols following the convention in RFC 1779
+ *
+ */
+ public static final Hashtable RFC1779Symbols = new Hashtable();
+
+ /**
+ * look up table translating common symbols into their OIDS.
+ */
+ public static final Hashtable DefaultLookUp = new Hashtable();
+
+ /**
+ * look up table translating OID values into their common symbols
+ * @deprecated use DefaultSymbols
+ */
+ public static final Hashtable OIDLookUp = DefaultSymbols;
+
+ /**
+ * look up table translating string values into their OIDS -
+ * @deprecated use DefaultLookUp
+ */
+ public static final Hashtable SymbolLookUp = DefaultLookUp;
+
+ private static final Boolean TRUE = new Boolean(true); // for J2ME compatibility
+ private static final Boolean FALSE = new Boolean(false);
+
+ static
+ {
+ DefaultSymbols.put(C, "C");
+ DefaultSymbols.put(O, "O");
+ DefaultSymbols.put(T, "T");
+ DefaultSymbols.put(OU, "OU");
+ DefaultSymbols.put(CN, "CN");
+ DefaultSymbols.put(L, "L");
+ DefaultSymbols.put(ST, "ST");
+ DefaultSymbols.put(SN, "SERIALNUMBER");
+ DefaultSymbols.put(EmailAddress, "E");
+ DefaultSymbols.put(DC, "DC");
+ DefaultSymbols.put(UID, "UID");
+ DefaultSymbols.put(STREET, "STREET");
+ DefaultSymbols.put(SURNAME, "SURNAME");
+ DefaultSymbols.put(GIVENNAME, "GIVENNAME");
+ DefaultSymbols.put(INITIALS, "INITIALS");
+ DefaultSymbols.put(GENERATION, "GENERATION");
+ DefaultSymbols.put(UnstructuredAddress, "unstructuredAddress");
+ DefaultSymbols.put(UnstructuredName, "unstructuredName");
+ DefaultSymbols.put(UNIQUE_IDENTIFIER, "UniqueIdentifier");
+ DefaultSymbols.put(DN_QUALIFIER, "DN");
+ DefaultSymbols.put(PSEUDONYM, "Pseudonym");
+ DefaultSymbols.put(POSTAL_ADDRESS, "PostalAddress");
+ DefaultSymbols.put(NAME_AT_BIRTH, "NameAtBirth");
+ DefaultSymbols.put(COUNTRY_OF_CITIZENSHIP, "CountryOfCitizenship");
+ DefaultSymbols.put(COUNTRY_OF_RESIDENCE, "CountryOfResidence");
+ DefaultSymbols.put(GENDER, "Gender");
+ DefaultSymbols.put(PLACE_OF_BIRTH, "PlaceOfBirth");
+ DefaultSymbols.put(DATE_OF_BIRTH, "DateOfBirth");
+ DefaultSymbols.put(POSTAL_CODE, "PostalCode");
+ DefaultSymbols.put(BUSINESS_CATEGORY, "BusinessCategory");
+ DefaultSymbols.put(TELEPHONE_NUMBER, "TelephoneNumber");
+ DefaultSymbols.put(NAME, "Name");
+
+ RFC2253Symbols.put(C, "C");
+ RFC2253Symbols.put(O, "O");
+ RFC2253Symbols.put(OU, "OU");
+ RFC2253Symbols.put(CN, "CN");
+ RFC2253Symbols.put(L, "L");
+ RFC2253Symbols.put(ST, "ST");
+ RFC2253Symbols.put(STREET, "STREET");
+ RFC2253Symbols.put(DC, "DC");
+ RFC2253Symbols.put(UID, "UID");
+
+ RFC1779Symbols.put(C, "C");
+ RFC1779Symbols.put(O, "O");
+ RFC1779Symbols.put(OU, "OU");
+ RFC1779Symbols.put(CN, "CN");
+ RFC1779Symbols.put(L, "L");
+ RFC1779Symbols.put(ST, "ST");
+ RFC1779Symbols.put(STREET, "STREET");
+
+ DefaultLookUp.put("c", C);
+ DefaultLookUp.put("o", O);
+ DefaultLookUp.put("t", T);
+ DefaultLookUp.put("ou", OU);
+ DefaultLookUp.put("cn", CN);
+ DefaultLookUp.put("l", L);
+ DefaultLookUp.put("st", ST);
+ DefaultLookUp.put("sn", SN);
+ DefaultLookUp.put("serialnumber", SN);
+ DefaultLookUp.put("street", STREET);
+ DefaultLookUp.put("emailaddress", E);
+ DefaultLookUp.put("dc", DC);
+ DefaultLookUp.put("e", E);
+ DefaultLookUp.put("uid", UID);
+ DefaultLookUp.put("surname", SURNAME);
+ DefaultLookUp.put("givenname", GIVENNAME);
+ DefaultLookUp.put("initials", INITIALS);
+ DefaultLookUp.put("generation", GENERATION);
+ DefaultLookUp.put("unstructuredaddress", UnstructuredAddress);
+ DefaultLookUp.put("unstructuredname", UnstructuredName);
+ DefaultLookUp.put("uniqueidentifier", UNIQUE_IDENTIFIER);
+ DefaultLookUp.put("dn", DN_QUALIFIER);
+ DefaultLookUp.put("pseudonym", PSEUDONYM);
+ DefaultLookUp.put("postaladdress", POSTAL_ADDRESS);
+ DefaultLookUp.put("nameofbirth", NAME_AT_BIRTH);
+ DefaultLookUp.put("countryofcitizenship", COUNTRY_OF_CITIZENSHIP);
+ DefaultLookUp.put("countryofresidence", COUNTRY_OF_RESIDENCE);
+ DefaultLookUp.put("gender", GENDER);
+ DefaultLookUp.put("placeofbirth", PLACE_OF_BIRTH);
+ DefaultLookUp.put("dateofbirth", DATE_OF_BIRTH);
+ DefaultLookUp.put("postalcode", POSTAL_CODE);
+ DefaultLookUp.put("businesscategory", BUSINESS_CATEGORY);
+ DefaultLookUp.put("telephonenumber", TELEPHONE_NUMBER);
+ DefaultLookUp.put("name", NAME);
+ }
+
+ private X509NameEntryConverter converter = null;
+ private Vector ordering = new Vector();
+ private Vector values = new Vector();
+ private Vector added = new Vector();
+
+ private ASN1Sequence seq;
+
+ private boolean isHashCodeCalculated;
+ private int hashCodeValue;
+
+ /**
+ * Return a X509Name based on the passed in tagged object.
+ *
+ * @param obj tag object holding name.
+ * @param explicit true if explicitly tagged false otherwise.
+ * @return the X509Name
+ */
+ public static X509Name getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static X509Name getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof X509Name)
+ {
+ return (X509Name)obj;
+ }
+ else if (obj instanceof X500Name)
+ {
+ return new X509Name(ASN1Sequence.getInstance(((X500Name)obj).toASN1Primitive()));
+ }
+ else if (obj != null)
+ {
+ return new X509Name(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ protected X509Name()
+ {
+ // constructure use by new X500 Name class
+ }
+ /**
+ * Constructor from ASN1Sequence
+ *
+ * the principal will be a list of constructed sets, each containing an (OID, String) pair.
+ * @deprecated use X500Name.getInstance()
+ */
+ public X509Name(
+ ASN1Sequence seq)
+ {
+ this.seq = seq;
+
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ ASN1Set set = ASN1Set.getInstance(((ASN1Encodable)e.nextElement()).toASN1Primitive());
+
+ for (int i = 0; i < set.size(); i++)
+ {
+ ASN1Sequence s = ASN1Sequence.getInstance(set.getObjectAt(i).toASN1Primitive());
+
+ if (s.size() != 2)
+ {
+ throw new IllegalArgumentException("badly sized pair");
+ }
+
+ ordering.addElement(ASN1ObjectIdentifier.getInstance(s.getObjectAt(0)));
+
+ ASN1Encodable value = s.getObjectAt(1);
+ if (value instanceof ASN1String && !(value instanceof DERUniversalString))
+ {
+ String v = ((ASN1String)value).getString();
+ if (v.length() > 0 && v.charAt(0) == '#')
+ {
+ values.addElement("\\" + v);
+ }
+ else
+ {
+ values.addElement(v);
+ }
+ }
+ else
+ {
+ try
+ {
+ values.addElement("#" + bytesToString(Hex.encode(value.toASN1Primitive().getEncoded(ASN1Encoding.DER))));
+ }
+ catch (IOException e1)
+ {
+ throw new IllegalArgumentException("cannot encode value");
+ }
+ }
+ added.addElement((i != 0) ? TRUE : FALSE); // to allow earlier JDK compatibility
+ }
+ }
+ }
+
+ /**
+ * constructor from a table of attributes.
+ * <p>
+ * it's is assumed the table contains OID/String pairs, and the contents
+ * of the table are copied into an internal table as part of the
+ * construction process.
+ * <p>
+ * <b>Note:</b> if the name you are trying to generate should be
+ * following a specific ordering, you should use the constructor
+ * with the ordering specified below.
+ * @deprecated use an ordered constructor! The hashtable ordering is rarely correct
+ */
+ public X509Name(
+ Hashtable attributes)
+ {
+ this(null, attributes);
+ }
+
+ /**
+ * Constructor from a table of attributes with ordering.
+ * <p>
+ * it's is assumed the table contains OID/String pairs, and the contents
+ * of the table are copied into an internal table as part of the
+ * construction process. The ordering vector should contain the OIDs
+ * in the order they are meant to be encoded or printed in toString.
+ */
+ public X509Name(
+ Vector ordering,
+ Hashtable attributes)
+ {
+ this(ordering, attributes, new X509DefaultEntryConverter());
+ }
+
+ /**
+ * Constructor from a table of attributes with ordering.
+ * <p>
+ * it's is assumed the table contains OID/String pairs, and the contents
+ * of the table are copied into an internal table as part of the
+ * construction process. The ordering vector should contain the OIDs
+ * in the order they are meant to be encoded or printed in toString.
+ * <p>
+ * The passed in converter will be used to convert the strings into their
+ * ASN.1 counterparts.
+ * @deprecated use X500Name, X500NameBuilder
+ */
+ public X509Name(
+ Vector ordering,
+ Hashtable attributes,
+ X509NameEntryConverter converter)
+ {
+ this.converter = converter;
+
+ if (ordering != null)
+ {
+ for (int i = 0; i != ordering.size(); i++)
+ {
+ this.ordering.addElement(ordering.elementAt(i));
+ this.added.addElement(FALSE);
+ }
+ }
+ else
+ {
+ Enumeration e = attributes.keys();
+
+ while (e.hasMoreElements())
+ {
+ this.ordering.addElement(e.nextElement());
+ this.added.addElement(FALSE);
+ }
+ }
+
+ for (int i = 0; i != this.ordering.size(); i++)
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)this.ordering.elementAt(i);
+
+ if (attributes.get(oid) == null)
+ {
+ throw new IllegalArgumentException("No attribute for object id - " + oid.getId() + " - passed to distinguished name");
+ }
+
+ this.values.addElement(attributes.get(oid)); // copy the hash table
+ }
+ }
+
+ /**
+ * Takes two vectors one of the oids and the other of the values.
+ * @deprecated use X500Name, X500NameBuilder
+ */
+ public X509Name(
+ Vector oids,
+ Vector values)
+ {
+ this(oids, values, new X509DefaultEntryConverter());
+ }
+
+ /**
+ * Takes two vectors one of the oids and the other of the values.
+ * <p>
+ * The passed in converter will be used to convert the strings into their
+ * ASN.1 counterparts.
+ * @deprecated use X500Name, X500NameBuilder
+ */
+ public X509Name(
+ Vector oids,
+ Vector values,
+ X509NameEntryConverter converter)
+ {
+ this.converter = converter;
+
+ if (oids.size() != values.size())
+ {
+ throw new IllegalArgumentException("oids vector must be same length as values.");
+ }
+
+ for (int i = 0; i < oids.size(); i++)
+ {
+ this.ordering.addElement(oids.elementAt(i));
+ this.values.addElement(values.elementAt(i));
+ this.added.addElement(FALSE);
+ }
+ }
+
+// private Boolean isEncoded(String s)
+// {
+// if (s.charAt(0) == '#')
+// {
+// return TRUE;
+// }
+//
+// return FALSE;
+// }
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes.
+ * @deprecated use X500Name, X500NameBuilder
+ */
+ public X509Name(
+ String dirName)
+ {
+ this(DefaultReverse, DefaultLookUp, dirName);
+ }
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes with each
+ * string value being converted to its associated ASN.1 type using the passed
+ * in converter.
+ * @deprecated use X500Name, X500NameBuilder
+ */
+ public X509Name(
+ String dirName,
+ X509NameEntryConverter converter)
+ {
+ this(DefaultReverse, DefaultLookUp, dirName, converter);
+ }
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes. If reverse
+ * is true, create the encoded version of the sequence starting from the
+ * last element in the string.
+ * @deprecated use X500Name, X500NameBuilder
+ */
+ public X509Name(
+ boolean reverse,
+ String dirName)
+ {
+ this(reverse, DefaultLookUp, dirName);
+ }
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes with each
+ * string value being converted to its associated ASN.1 type using the passed
+ * in converter. If reverse is true the ASN.1 sequence representing the DN will
+ * be built by starting at the end of the string, rather than the start.
+ * @deprecated use X500Name, X500NameBuilder
+ */
+ public X509Name(
+ boolean reverse,
+ String dirName,
+ X509NameEntryConverter converter)
+ {
+ this(reverse, DefaultLookUp, dirName, converter);
+ }
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes. lookUp
+ * should provide a table of lookups, indexed by lowercase only strings and
+ * yielding a ASN1ObjectIdentifier, other than that OID. and numeric oids
+ * will be processed automatically.
+ * <br>
+ * If reverse is true, create the encoded version of the sequence
+ * starting from the last element in the string.
+ * @param reverse true if we should start scanning from the end (RFC 2553).
+ * @param lookUp table of names and their oids.
+ * @param dirName the X.500 string to be parsed.
+ * @deprecated use X500Name, X500NameBuilder
+ */
+ public X509Name(
+ boolean reverse,
+ Hashtable lookUp,
+ String dirName)
+ {
+ this(reverse, lookUp, dirName, new X509DefaultEntryConverter());
+ }
+
+ private ASN1ObjectIdentifier decodeOID(
+ String name,
+ Hashtable lookUp)
+ {
+ name = name.trim();
+ if (Strings.toUpperCase(name).startsWith("OID."))
+ {
+ return new ASN1ObjectIdentifier(name.substring(4));
+ }
+ else if (name.charAt(0) >= '0' && name.charAt(0) <= '9')
+ {
+ return new ASN1ObjectIdentifier(name);
+ }
+
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)lookUp.get(Strings.toLowerCase(name));
+ if (oid == null)
+ {
+ throw new IllegalArgumentException("Unknown object id - " + name + " - passed to distinguished name");
+ }
+
+ return oid;
+ }
+
+ private String unescape(String elt)
+ {
+ if (elt.length() == 0 || (elt.indexOf('\\') < 0 && elt.indexOf('"') < 0))
+ {
+ return elt.trim();
+ }
+
+ char[] elts = elt.toCharArray();
+ boolean escaped = false;
+ boolean quoted = false;
+ StringBuffer buf = new StringBuffer(elt.length());
+ int start = 0;
+
+ // if it's an escaped hash string and not an actual encoding in string form
+ // we need to leave it escaped.
+ if (elts[0] == '\\')
+ {
+ if (elts[1] == '#')
+ {
+ start = 2;
+ buf.append("\\#");
+ }
+ }
+
+ boolean nonWhiteSpaceEncountered = false;
+ int lastEscaped = 0;
+
+ for (int i = start; i != elts.length; i++)
+ {
+ char c = elts[i];
+
+ if (c != ' ')
+ {
+ nonWhiteSpaceEncountered = true;
+ }
+
+ if (c == '"')
+ {
+ if (!escaped)
+ {
+ quoted = !quoted;
+ }
+ else
+ {
+ buf.append(c);
+ }
+ escaped = false;
+ }
+ else if (c == '\\' && !(escaped || quoted))
+ {
+ escaped = true;
+ lastEscaped = buf.length();
+ }
+ else
+ {
+ if (c == ' ' && !escaped && !nonWhiteSpaceEncountered)
+ {
+ continue;
+ }
+ buf.append(c);
+ escaped = false;
+ }
+ }
+
+ if (buf.length() > 0)
+ {
+ while (buf.charAt(buf.length() - 1) == ' ' && lastEscaped != (buf.length() - 1))
+ {
+ buf.setLength(buf.length() - 1);
+ }
+ }
+
+ return buf.toString();
+ }
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes. lookUp
+ * should provide a table of lookups, indexed by lowercase only strings and
+ * yielding a ASN1ObjectIdentifier, other than that OID. and numeric oids
+ * will be processed automatically. The passed in converter is used to convert the
+ * string values to the right of each equals sign to their ASN.1 counterparts.
+ * <br>
+ * @param reverse true if we should start scanning from the end, false otherwise.
+ * @param lookUp table of names and oids.
+ * @param dirName the string dirName
+ * @param converter the converter to convert string values into their ASN.1 equivalents
+ */
+ public X509Name(
+ boolean reverse,
+ Hashtable lookUp,
+ String dirName,
+ X509NameEntryConverter converter)
+ {
+ this.converter = converter;
+ X509NameTokenizer nTok = new X509NameTokenizer(dirName);
+
+ while (nTok.hasMoreTokens())
+ {
+ String token = nTok.nextToken();
+
+ if (token.indexOf('+') > 0)
+ {
+ X509NameTokenizer pTok = new X509NameTokenizer(token, '+');
+
+ addEntry(lookUp, pTok.nextToken(), FALSE);
+
+ while (pTok.hasMoreTokens())
+ {
+ addEntry(lookUp, pTok.nextToken(), TRUE);
+ }
+ }
+ else
+ {
+ addEntry(lookUp, token, FALSE);
+ }
+ }
+
+ if (reverse)
+ {
+ Vector o = new Vector();
+ Vector v = new Vector();
+ Vector a = new Vector();
+
+ int count = 1;
+
+ for (int i = 0; i < this.ordering.size(); i++)
+ {
+ if (((Boolean)this.added.elementAt(i)).booleanValue())
+ {
+ o.insertElementAt(this.ordering.elementAt(i), count);
+ v.insertElementAt(this.values.elementAt(i), count);
+ a.insertElementAt(this.added.elementAt(i), count);
+ count++;
+ }
+ else
+ {
+ o.insertElementAt(this.ordering.elementAt(i), 0);
+ v.insertElementAt(this.values.elementAt(i), 0);
+ a.insertElementAt(this.added.elementAt(i), 0);
+ count = 1;
+ }
+ }
+
+ this.ordering = o;
+ this.values = v;
+ this.added = a;
+ }
+ }
+
+ private void addEntry(Hashtable lookUp, String token, Boolean isAdded)
+ {
+ X509NameTokenizer vTok;
+ String name;
+ String value;ASN1ObjectIdentifier oid;
+ vTok = new X509NameTokenizer(token, '=');
+
+ name = vTok.nextToken();
+
+ if (!vTok.hasMoreTokens())
+ {
+ throw new IllegalArgumentException("badly formatted directory string");
+ }
+
+ value = vTok.nextToken();
+
+ oid = decodeOID(name, lookUp);
+
+ this.ordering.addElement(oid);
+ this.values.addElement(unescape(value));
+ this.added.addElement(isAdded);
+ }
+
+ /**
+ * return a vector of the oids in the name, in the order they were found.
+ */
+ public Vector getOIDs()
+ {
+ Vector v = new Vector();
+
+ for (int i = 0; i != ordering.size(); i++)
+ {
+ v.addElement(ordering.elementAt(i));
+ }
+
+ return v;
+ }
+
+ /**
+ * return a vector of the values found in the name, in the order they
+ * were found.
+ */
+ public Vector getValues()
+ {
+ Vector v = new Vector();
+
+ for (int i = 0; i != values.size(); i++)
+ {
+ v.addElement(values.elementAt(i));
+ }
+
+ return v;
+ }
+
+ /**
+ * return a vector of the values found in the name, in the order they
+ * were found, with the DN label corresponding to passed in oid.
+ */
+ public Vector getValues(
+ ASN1ObjectIdentifier oid)
+ {
+ Vector v = new Vector();
+
+ for (int i = 0; i != values.size(); i++)
+ {
+ if (ordering.elementAt(i).equals(oid))
+ {
+ String val = (String)values.elementAt(i);
+
+ if (val.length() > 2 && val.charAt(0) == '\\' && val.charAt(1) == '#')
+ {
+ v.addElement(val.substring(1));
+ }
+ else
+ {
+ v.addElement(val);
+ }
+ }
+ }
+
+ return v;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (seq == null)
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+ ASN1EncodableVector sVec = new ASN1EncodableVector();
+ ASN1ObjectIdentifier lstOid = null;
+
+ for (int i = 0; i != ordering.size(); i++)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)ordering.elementAt(i);
+
+ v.add(oid);
+
+ String str = (String)values.elementAt(i);
+
+ v.add(converter.getConvertedValue(oid, str));
+
+ if (lstOid == null
+ || ((Boolean)this.added.elementAt(i)).booleanValue())
+ {
+ sVec.add(new DERSequence(v));
+ }
+ else
+ {
+ vec.add(new DERSet(sVec));
+ sVec = new ASN1EncodableVector();
+
+ sVec.add(new DERSequence(v));
+ }
+
+ lstOid = oid;
+ }
+
+ vec.add(new DERSet(sVec));
+
+ seq = new DERSequence(vec);
+ }
+
+ return seq;
+ }
+
+ /**
+ * @param inOrder if true the order of both X509 names must be the same,
+ * as well as the values associated with each element.
+ */
+ public boolean equals(Object obj, boolean inOrder)
+ {
+ if (!inOrder)
+ {
+ return this.equals(obj);
+ }
+
+ if (obj == this)
+ {
+ return true;
+ }
+
+ if (!(obj instanceof X509Name || obj instanceof ASN1Sequence))
+ {
+ return false;
+ }
+
+ ASN1Primitive derO = ((ASN1Encodable)obj).toASN1Primitive();
+
+ if (this.toASN1Primitive().equals(derO))
+ {
+ return true;
+ }
+
+ X509Name other;
+
+ try
+ {
+ other = X509Name.getInstance(obj);
+ }
+ catch (IllegalArgumentException e)
+ {
+ return false;
+ }
+
+ int orderingSize = ordering.size();
+
+ if (orderingSize != other.ordering.size())
+ {
+ return false;
+ }
+
+ for (int i = 0; i < orderingSize; i++)
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)ordering.elementAt(i);
+ ASN1ObjectIdentifier oOid = (ASN1ObjectIdentifier)other.ordering.elementAt(i);
+
+ if (oid.equals(oOid))
+ {
+ String value = (String)values.elementAt(i);
+ String oValue = (String)other.values.elementAt(i);
+
+ if (!equivalentStrings(value, oValue))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public int hashCode()
+ {
+ if (isHashCodeCalculated)
+ {
+ return hashCodeValue;
+ }
+
+ isHashCodeCalculated = true;
+
+ // this needs to be order independent, like equals
+ for (int i = 0; i != ordering.size(); i += 1)
+ {
+ String value = (String)values.elementAt(i);
+
+ value = canonicalize(value);
+ value = stripInternalSpaces(value);
+
+ hashCodeValue ^= ordering.elementAt(i).hashCode();
+ hashCodeValue ^= value.hashCode();
+ }
+
+ return hashCodeValue;
+ }
+
+ /**
+ * test for equality - note: case is ignored.
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj == this)
+ {
+ return true;
+ }
+
+ if (!(obj instanceof X509Name || obj instanceof ASN1Sequence))
+ {
+ return false;
+ }
+
+ ASN1Primitive derO = ((ASN1Encodable)obj).toASN1Primitive();
+
+ if (this.toASN1Primitive().equals(derO))
+ {
+ return true;
+ }
+
+ X509Name other;
+
+ try
+ {
+ other = X509Name.getInstance(obj);
+ }
+ catch (IllegalArgumentException e)
+ {
+ return false;
+ }
+
+ int orderingSize = ordering.size();
+
+ if (orderingSize != other.ordering.size())
+ {
+ return false;
+ }
+
+ boolean[] indexes = new boolean[orderingSize];
+ int start, end, delta;
+
+ if (ordering.elementAt(0).equals(other.ordering.elementAt(0))) // guess forward
+ {
+ start = 0;
+ end = orderingSize;
+ delta = 1;
+ }
+ else // guess reversed - most common problem
+ {
+ start = orderingSize - 1;
+ end = -1;
+ delta = -1;
+ }
+
+ for (int i = start; i != end; i += delta)
+ {
+ boolean found = false;
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)ordering.elementAt(i);
+ String value = (String)values.elementAt(i);
+
+ for (int j = 0; j < orderingSize; j++)
+ {
+ if (indexes[j])
+ {
+ continue;
+ }
+
+ ASN1ObjectIdentifier oOid = (ASN1ObjectIdentifier)other.ordering.elementAt(j);
+
+ if (oid.equals(oOid))
+ {
+ String oValue = (String)other.values.elementAt(j);
+
+ if (equivalentStrings(value, oValue))
+ {
+ indexes[j] = true;
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private boolean equivalentStrings(String s1, String s2)
+ {
+ String value = canonicalize(s1);
+ String oValue = canonicalize(s2);
+
+ if (!value.equals(oValue))
+ {
+ value = stripInternalSpaces(value);
+ oValue = stripInternalSpaces(oValue);
+
+ if (!value.equals(oValue))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private String canonicalize(String s)
+ {
+ String value = Strings.toLowerCase(s.trim());
+
+ if (value.length() > 0 && value.charAt(0) == '#')
+ {
+ ASN1Primitive obj = decodeObject(value);
+
+ if (obj instanceof ASN1String)
+ {
+ value = Strings.toLowerCase(((ASN1String)obj).getString().trim());
+ }
+ }
+
+ return value;
+ }
+
+ private ASN1Primitive decodeObject(String oValue)
+ {
+ try
+ {
+ return ASN1Primitive.fromByteArray(Hex.decode(oValue.substring(1)));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("unknown encoding in name: " + e);
+ }
+ }
+
+ private String stripInternalSpaces(
+ String str)
+ {
+ StringBuffer res = new StringBuffer();
+
+ if (str.length() != 0)
+ {
+ char c1 = str.charAt(0);
+
+ res.append(c1);
+
+ for (int k = 1; k < str.length(); k++)
+ {
+ char c2 = str.charAt(k);
+ if (!(c1 == ' ' && c2 == ' '))
+ {
+ res.append(c2);
+ }
+ c1 = c2;
+ }
+ }
+
+ return res.toString();
+ }
+
+ private void appendValue(
+ StringBuffer buf,
+ Hashtable oidSymbols,
+ ASN1ObjectIdentifier oid,
+ String value)
+ {
+ String sym = (String)oidSymbols.get(oid);
+
+ if (sym != null)
+ {
+ buf.append(sym);
+ }
+ else
+ {
+ buf.append(oid.getId());
+ }
+
+ buf.append('=');
+
+ int start = buf.length();
+ buf.append(value);
+ int end = buf.length();
+
+ if (value.length() >= 2 && value.charAt(0) == '\\' && value.charAt(1) == '#')
+ {
+ start += 2;
+ }
+
+ while (start < end && buf.charAt(start) == ' ')
+ {
+ buf.insert(start, "\\");
+ start += 2;
+ ++end;
+ }
+
+ while (--end > start && buf.charAt(end) == ' ')
+ {
+ buf.insert(end, '\\');
+ }
+
+ while (start <= end)
+ {
+ switch (buf.charAt(start))
+ {
+ case ',':
+ case '"':
+ case '\\':
+ case '+':
+ case '=':
+ case '<':
+ case '>':
+ case ';':
+ buf.insert(start, "\\");
+ start += 2;
+ ++end;
+ break;
+ default:
+ ++start;
+ break;
+ }
+ }
+ }
+
+ /**
+ * convert the structure to a string - if reverse is true the
+ * oids and values are listed out starting with the last element
+ * in the sequence (ala RFC 2253), otherwise the string will begin
+ * with the first element of the structure. If no string definition
+ * for the oid is found in oidSymbols the string value of the oid is
+ * added. Two standard symbol tables are provided DefaultSymbols, and
+ * RFC2253Symbols as part of this class.
+ *
+ * @param reverse if true start at the end of the sequence and work back.
+ * @param oidSymbols look up table strings for oids.
+ */
+ public String toString(
+ boolean reverse,
+ Hashtable oidSymbols)
+ {
+ StringBuffer buf = new StringBuffer();
+ Vector components = new Vector();
+ boolean first = true;
+
+ StringBuffer ava = null;
+
+ for (int i = 0; i < ordering.size(); i++)
+ {
+ if (((Boolean)added.elementAt(i)).booleanValue())
+ {
+ ava.append('+');
+ appendValue(ava, oidSymbols,
+ (ASN1ObjectIdentifier)ordering.elementAt(i),
+ (String)values.elementAt(i));
+ }
+ else
+ {
+ ava = new StringBuffer();
+ appendValue(ava, oidSymbols,
+ (ASN1ObjectIdentifier)ordering.elementAt(i),
+ (String)values.elementAt(i));
+ components.addElement(ava);
+ }
+ }
+
+ if (reverse)
+ {
+ for (int i = components.size() - 1; i >= 0; i--)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ buf.append(',');
+ }
+
+ buf.append(components.elementAt(i).toString());
+ }
+ }
+ else
+ {
+ for (int i = 0; i < components.size(); i++)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ buf.append(',');
+ }
+
+ buf.append(components.elementAt(i).toString());
+ }
+ }
+
+ return buf.toString();
+ }
+
+ private String bytesToString(
+ byte[] data)
+ {
+ char[] cs = new char[data.length];
+
+ for (int i = 0; i != cs.length; i++)
+ {
+ cs[i] = (char)(data[i] & 0xff);
+ }
+
+ return new String(cs);
+ }
+
+ public String toString()
+ {
+ return toString(DefaultReverse, DefaultSymbols);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/X509NameEntryConverter.java b/core/src/main/java/org/spongycastle/asn1/x509/X509NameEntryConverter.java
new file mode 100644
index 00000000..bcbcc28e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/X509NameEntryConverter.java
@@ -0,0 +1,114 @@
+package org.spongycastle.asn1.x509;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DERPrintableString;
+import org.spongycastle.util.Strings;
+
+/**
+ * It turns out that the number of standard ways the fields in a DN should be
+ * encoded into their ASN.1 counterparts is rapidly approaching the
+ * number of machines on the internet. By default the X509Name class
+ * will produce UTF8Strings in line with the current recommendations (RFC 3280).
+ * <p>
+ * An example of an encoder look like below:
+ * <pre>
+ * public class X509DirEntryConverter
+ * extends X509NameEntryConverter
+ * {
+ * public ASN1Primitive getConvertedValue(
+ * ASN1ObjectIdentifier oid,
+ * String value)
+ * {
+ * if (str.length() != 0 &amp;&amp; str.charAt(0) == '#')
+ * {
+ * return convertHexEncoded(str, 1);
+ * }
+ * if (oid.equals(EmailAddress))
+ * {
+ * return new DERIA5String(str);
+ * }
+ * else if (canBePrintable(str))
+ * {
+ * return new DERPrintableString(str);
+ * }
+ * else if (canBeUTF8(str))
+ * {
+ * return new DERUTF8String(str);
+ * }
+ * else
+ * {
+ * return new DERBMPString(str);
+ * }
+ * }
+ * }
+ * </pre>
+ */
+public abstract class X509NameEntryConverter
+{
+ /**
+ * Convert an inline encoded hex string rendition of an ASN.1
+ * object back into its corresponding ASN.1 object.
+ *
+ * @param str the hex encoded object
+ * @param off the index at which the encoding starts
+ * @return the decoded object
+ */
+ protected ASN1Primitive convertHexEncoded(
+ String str,
+ int off)
+ throws IOException
+ {
+ str = Strings.toLowerCase(str);
+ byte[] data = new byte[(str.length() - off) / 2];
+ for (int index = 0; index != data.length; index++)
+ {
+ char left = str.charAt((index * 2) + off);
+ char right = str.charAt((index * 2) + off + 1);
+
+ if (left < 'a')
+ {
+ data[index] = (byte)((left - '0') << 4);
+ }
+ else
+ {
+ data[index] = (byte)((left - 'a' + 10) << 4);
+ }
+ if (right < 'a')
+ {
+ data[index] |= (byte)(right - '0');
+ }
+ else
+ {
+ data[index] |= (byte)(right - 'a' + 10);
+ }
+ }
+
+ ASN1InputStream aIn = new ASN1InputStream(data);
+
+ return aIn.readObject();
+ }
+
+ /**
+ * return true if the passed in String can be represented without
+ * loss as a PrintableString, false otherwise.
+ */
+ protected boolean canBePrintable(
+ String str)
+ {
+ return DERPrintableString.isPrintableString(str);
+ }
+
+ /**
+ * Convert the passed in String value into the appropriate ASN.1
+ * encoded object.
+ *
+ * @param oid the oid associated with the value in the DN.
+ * @param value the value of the particular DN component.
+ * @return the ASN.1 equivalent for the value.
+ */
+ public abstract ASN1Primitive getConvertedValue(ASN1ObjectIdentifier oid, String value);
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/X509NameTokenizer.java b/core/src/main/java/org/spongycastle/asn1/x509/X509NameTokenizer.java
new file mode 100644
index 00000000..864f0e81
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/X509NameTokenizer.java
@@ -0,0 +1,91 @@
+package org.spongycastle.asn1.x509;
+
+/**
+ * class for breaking up an X500 Name into it's component tokens, ala
+ * java.util.StringTokenizer. We need this class as some of the
+ * lightweight Java environment don't support classes like
+ * StringTokenizer.
+ * @deprecated use X500NameTokenizer
+ */
+public class X509NameTokenizer
+{
+ private String value;
+ private int index;
+ private char separator;
+ private StringBuffer buf = new StringBuffer();
+
+ public X509NameTokenizer(
+ String oid)
+ {
+ this(oid, ',');
+ }
+
+ public X509NameTokenizer(
+ String oid,
+ char separator)
+ {
+ this.value = oid;
+ this.index = -1;
+ this.separator = separator;
+ }
+
+ public boolean hasMoreTokens()
+ {
+ return (index != value.length());
+ }
+
+ public String nextToken()
+ {
+ if (index == value.length())
+ {
+ return null;
+ }
+
+ int end = index + 1;
+ boolean quoted = false;
+ boolean escaped = false;
+
+ buf.setLength(0);
+
+ while (end != value.length())
+ {
+ char c = value.charAt(end);
+
+ if (c == '"')
+ {
+ if (!escaped)
+ {
+ quoted = !quoted;
+ }
+ buf.append(c);
+ escaped = false;
+ }
+ else
+ {
+ if (escaped || quoted)
+ {
+ buf.append(c);
+ escaped = false;
+ }
+ else if (c == '\\')
+ {
+ buf.append(c);
+ escaped = true;
+ }
+ else if (c == separator)
+ {
+ break;
+ }
+ else
+ {
+ buf.append(c);
+ }
+ }
+ end++;
+ }
+
+ index = end;
+
+ return buf.toString();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/X509ObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/x509/X509ObjectIdentifiers.java
new file mode 100644
index 00000000..a760411b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/X509ObjectIdentifiers.java
@@ -0,0 +1,81 @@
+package org.spongycastle.asn1.x509;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+
+public interface X509ObjectIdentifiers
+{
+
+ /** 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");
+ /** 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 }
+ * <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)}
+ * <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) }
+ * <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 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; 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
+ * <p>
+ * OID: 2.5.29
+ */
+ static final ASN1ObjectIdentifier id_ce = new ASN1ObjectIdentifier("2.5.29");
+
+ /** 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 uri in AuthorityInformationAccess extension */
+ static final ASN1ObjectIdentifier ocspAccessMethod = id_ad_ocsp;
+ /** OID for crl uri in AuthorityInformationAccess extension */
+ static final ASN1ObjectIdentifier crlAccessMethod = id_ad_caIssuers;
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/qualified/BiometricData.java b/core/src/main/java/org/spongycastle/asn1/x509/qualified/BiometricData.java
new file mode 100644
index 00000000..6175572c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/qualified/BiometricData.java
@@ -0,0 +1,122 @@
+package org.spongycastle.asn1.x509.qualified;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * The BiometricData object.
+ * <pre>
+ * BiometricData ::= SEQUENCE {
+ * typeOfBiometricData TypeOfBiometricData,
+ * hashAlgorithm AlgorithmIdentifier,
+ * biometricDataHash OCTET STRING,
+ * sourceDataUri IA5String OPTIONAL }
+ * </pre>
+ */
+public class BiometricData
+ extends ASN1Object
+{
+ private TypeOfBiometricData typeOfBiometricData;
+ private AlgorithmIdentifier hashAlgorithm;
+ private ASN1OctetString biometricDataHash;
+ private DERIA5String sourceDataUri;
+
+ public static BiometricData getInstance(
+ Object obj)
+ {
+ if (obj instanceof BiometricData)
+ {
+ return (BiometricData)obj;
+ }
+
+ if (obj != null)
+ {
+ return new BiometricData(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private BiometricData(ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ // typeOfBiometricData
+ typeOfBiometricData = TypeOfBiometricData.getInstance(e.nextElement());
+ // hashAlgorithm
+ hashAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement());
+ // biometricDataHash
+ biometricDataHash = ASN1OctetString.getInstance(e.nextElement());
+ // sourceDataUri
+ if (e.hasMoreElements())
+ {
+ sourceDataUri = DERIA5String.getInstance(e.nextElement());
+ }
+ }
+
+ public BiometricData(
+ TypeOfBiometricData typeOfBiometricData,
+ AlgorithmIdentifier hashAlgorithm,
+ ASN1OctetString biometricDataHash,
+ DERIA5String sourceDataUri)
+ {
+ this.typeOfBiometricData = typeOfBiometricData;
+ this.hashAlgorithm = hashAlgorithm;
+ this.biometricDataHash = biometricDataHash;
+ this.sourceDataUri = sourceDataUri;
+ }
+
+ public BiometricData(
+ TypeOfBiometricData typeOfBiometricData,
+ AlgorithmIdentifier hashAlgorithm,
+ ASN1OctetString biometricDataHash)
+ {
+ this.typeOfBiometricData = typeOfBiometricData;
+ this.hashAlgorithm = hashAlgorithm;
+ this.biometricDataHash = biometricDataHash;
+ this.sourceDataUri = null;
+ }
+
+ public TypeOfBiometricData getTypeOfBiometricData()
+ {
+ return typeOfBiometricData;
+ }
+
+ public AlgorithmIdentifier getHashAlgorithm()
+ {
+ return hashAlgorithm;
+ }
+
+ public ASN1OctetString getBiometricDataHash()
+ {
+ return biometricDataHash;
+ }
+
+ public DERIA5String getSourceDataUri()
+ {
+ return sourceDataUri;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector seq = new ASN1EncodableVector();
+ seq.add(typeOfBiometricData);
+ seq.add(hashAlgorithm);
+ seq.add(biometricDataHash);
+
+ if (sourceDataUri != null)
+ {
+ seq.add(sourceDataUri);
+ }
+
+ return new DERSequence(seq);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/qualified/ETSIQCObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/x509/qualified/ETSIQCObjectIdentifiers.java
new file mode 100644
index 00000000..50145669
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/qualified/ETSIQCObjectIdentifiers.java
@@ -0,0 +1,11 @@
+package org.spongycastle.asn1.x509.qualified;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+
+public interface ETSIQCObjectIdentifiers
+{
+ 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/core/src/main/java/org/spongycastle/asn1/x509/qualified/Iso4217CurrencyCode.java b/core/src/main/java/org/spongycastle/asn1/x509/qualified/Iso4217CurrencyCode.java
new file mode 100644
index 00000000..3e791b47
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/qualified/Iso4217CurrencyCode.java
@@ -0,0 +1,93 @@
+package org.spongycastle.asn1.x509.qualified;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DERPrintableString;
+
+/**
+ * The Iso4217CurrencyCode object.
+ * <pre>
+ * Iso4217CurrencyCode ::= CHOICE {
+ * alphabetic PrintableString (SIZE 3), --Recommended
+ * numeric INTEGER (1..999) }
+ * -- Alphabetic or numeric currency code as defined in ISO 4217
+ * -- It is recommended that the Alphabetic form is used
+ * </pre>
+ */
+public class Iso4217CurrencyCode
+ extends ASN1Object
+ implements ASN1Choice
+{
+ final int ALPHABETIC_MAXSIZE = 3;
+ final int NUMERIC_MINSIZE = 1;
+ final int NUMERIC_MAXSIZE = 999;
+
+ ASN1Encodable obj;
+ int numeric;
+
+ public static Iso4217CurrencyCode getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof Iso4217CurrencyCode)
+ {
+ return (Iso4217CurrencyCode)obj;
+ }
+
+ if (obj instanceof ASN1Integer)
+ {
+ ASN1Integer numericobj = ASN1Integer.getInstance(obj);
+ int numeric = numericobj.getValue().intValue();
+ return new Iso4217CurrencyCode(numeric);
+ }
+ else
+ if (obj instanceof DERPrintableString)
+ {
+ DERPrintableString alphabetic = DERPrintableString.getInstance(obj);
+ return new Iso4217CurrencyCode(alphabetic.getString());
+ }
+ throw new IllegalArgumentException("unknown object in getInstance");
+ }
+
+ public Iso4217CurrencyCode(
+ int numeric)
+ {
+ if (numeric > NUMERIC_MAXSIZE || numeric < NUMERIC_MINSIZE)
+ {
+ throw new IllegalArgumentException("wrong size in numeric code : not in (" +NUMERIC_MINSIZE +".."+ NUMERIC_MAXSIZE +")");
+ }
+ obj = new ASN1Integer(numeric);
+ }
+
+ public Iso4217CurrencyCode(
+ String alphabetic)
+ {
+ if (alphabetic.length() > ALPHABETIC_MAXSIZE)
+ {
+ throw new IllegalArgumentException("wrong size in alphabetic code : max size is " + ALPHABETIC_MAXSIZE);
+ }
+ obj = new DERPrintableString(alphabetic);
+ }
+
+ public boolean isAlphabetic()
+ {
+ return obj instanceof DERPrintableString;
+ }
+
+ public String getAlphabetic()
+ {
+ return ((DERPrintableString)obj).getString();
+ }
+
+ public int getNumeric()
+ {
+ return ((ASN1Integer)obj).getValue().intValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return obj.toASN1Primitive();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/qualified/MonetaryValue.java b/core/src/main/java/org/spongycastle/asn1/x509/qualified/MonetaryValue.java
new file mode 100644
index 00000000..edf1897a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/qualified/MonetaryValue.java
@@ -0,0 +1,92 @@
+package org.spongycastle.asn1.x509.qualified;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * The MonetaryValue object.
+ * <pre>
+ * MonetaryValue ::= SEQUENCE {
+ * currency Iso4217CurrencyCode,
+ * amount INTEGER,
+ * exponent INTEGER }
+ * -- value = amount * 10^exponent
+ * </pre>
+ */
+public class MonetaryValue
+ extends ASN1Object
+{
+ private Iso4217CurrencyCode currency;
+ private ASN1Integer amount;
+ private ASN1Integer exponent;
+
+ public static MonetaryValue getInstance(
+ Object obj)
+ {
+ if (obj instanceof MonetaryValue)
+ {
+ return (MonetaryValue)obj;
+ }
+
+ if (obj != null)
+ {
+ return new MonetaryValue(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private MonetaryValue(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+ // currency
+ currency = Iso4217CurrencyCode.getInstance(e.nextElement());
+ // hashAlgorithm
+ amount = ASN1Integer.getInstance(e.nextElement());
+ // exponent
+ exponent = ASN1Integer.getInstance(e.nextElement());
+ }
+
+ public MonetaryValue(
+ Iso4217CurrencyCode currency,
+ int amount,
+ int exponent)
+ {
+ this.currency = currency;
+ this.amount = new ASN1Integer(amount);
+ this.exponent = new ASN1Integer(exponent);
+ }
+
+ public Iso4217CurrencyCode getCurrency()
+ {
+ return currency;
+ }
+
+ public BigInteger getAmount()
+ {
+ return amount.getValue();
+ }
+
+ public BigInteger getExponent()
+ {
+ return exponent.getValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector seq = new ASN1EncodableVector();
+ seq.add(currency);
+ seq.add(amount);
+ seq.add(exponent);
+
+ return new DERSequence(seq);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/qualified/QCStatement.java b/core/src/main/java/org/spongycastle/asn1/x509/qualified/QCStatement.java
new file mode 100644
index 00000000..f66f5113
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/qualified/QCStatement.java
@@ -0,0 +1,95 @@
+package org.spongycastle.asn1.x509.qualified;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * The QCStatement object.
+ * <pre>
+ * QCStatement ::= SEQUENCE {
+ * statementId OBJECT IDENTIFIER,
+ * statementInfo ANY DEFINED BY statementId OPTIONAL}
+ * </pre>
+ */
+
+public class QCStatement
+ extends ASN1Object
+ implements ETSIQCObjectIdentifiers, RFC3739QCObjectIdentifiers
+{
+ ASN1ObjectIdentifier qcStatementId;
+ ASN1Encodable qcStatementInfo;
+
+ public static QCStatement getInstance(
+ Object obj)
+ {
+ if (obj instanceof QCStatement)
+ {
+ return (QCStatement)obj;
+ }
+ if (obj != null)
+ {
+ return new QCStatement(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private QCStatement(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ // qcStatementId
+ qcStatementId = ASN1ObjectIdentifier.getInstance(e.nextElement());
+ // qcstatementInfo
+ if (e.hasMoreElements())
+ {
+ qcStatementInfo = (ASN1Encodable) e.nextElement();
+ }
+ }
+
+ public QCStatement(
+ ASN1ObjectIdentifier qcStatementId)
+ {
+ this.qcStatementId = qcStatementId;
+ this.qcStatementInfo = null;
+ }
+
+ public QCStatement(
+ ASN1ObjectIdentifier qcStatementId,
+ ASN1Encodable qcStatementInfo)
+ {
+ this.qcStatementId = qcStatementId;
+ this.qcStatementInfo = qcStatementInfo;
+ }
+
+ public ASN1ObjectIdentifier getStatementId()
+ {
+ return qcStatementId;
+ }
+
+ public ASN1Encodable getStatementInfo()
+ {
+ return qcStatementInfo;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector seq = new ASN1EncodableVector();
+ seq.add(qcStatementId);
+
+ if (qcStatementInfo != null)
+ {
+ seq.add(qcStatementInfo);
+ }
+
+ return new DERSequence(seq);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/qualified/RFC3739QCObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/x509/qualified/RFC3739QCObjectIdentifiers.java
new file mode 100644
index 00000000..d3663b0e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/qualified/RFC3739QCObjectIdentifiers.java
@@ -0,0 +1,11 @@
+package org.spongycastle.asn1.x509.qualified;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+
+public interface RFC3739QCObjectIdentifiers
+{
+ /** 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/core/src/main/java/org/spongycastle/asn1/x509/qualified/SemanticsInformation.java b/core/src/main/java/org/spongycastle/asn1/x509/qualified/SemanticsInformation.java
new file mode 100644
index 00000000..2a52a7d9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/qualified/SemanticsInformation.java
@@ -0,0 +1,131 @@
+package org.spongycastle.asn1.x509.qualified;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.GeneralName;
+
+/**
+ * The SemanticsInformation object.
+ * <pre>
+ * SemanticsInformation ::= SEQUENCE {
+ * semanticsIdentifier OBJECT IDENTIFIER OPTIONAL,
+ * nameRegistrationAuthorities NameRegistrationAuthorities
+ * OPTIONAL }
+ * (WITH COMPONENTS {..., semanticsIdentifier PRESENT}|
+ * WITH COMPONENTS {..., nameRegistrationAuthorities PRESENT})
+ *
+ * NameRegistrationAuthorities ::= SEQUENCE SIZE (1..MAX) OF
+ * GeneralName
+ * </pre>
+ */
+public class SemanticsInformation
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier semanticsIdentifier;
+ private GeneralName[] nameRegistrationAuthorities;
+
+ public static SemanticsInformation getInstance(Object obj)
+ {
+ if (obj instanceof SemanticsInformation)
+ {
+ return (SemanticsInformation)obj;
+ }
+
+ if (obj != null)
+ {
+ return new SemanticsInformation(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private SemanticsInformation(ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+ if (seq.size() < 1)
+ {
+ throw new IllegalArgumentException("no objects in SemanticsInformation");
+ }
+
+ Object object = e.nextElement();
+ if (object instanceof ASN1ObjectIdentifier)
+ {
+ semanticsIdentifier = ASN1ObjectIdentifier.getInstance(object);
+ if (e.hasMoreElements())
+ {
+ object = e.nextElement();
+ }
+ else
+ {
+ object = null;
+ }
+ }
+
+ if (object != null)
+ {
+ ASN1Sequence generalNameSeq = ASN1Sequence.getInstance(object);
+ nameRegistrationAuthorities = new GeneralName[generalNameSeq.size()];
+ for (int i= 0; i < generalNameSeq.size(); i++)
+ {
+ nameRegistrationAuthorities[i] = GeneralName.getInstance(generalNameSeq.getObjectAt(i));
+ }
+ }
+ }
+
+ public SemanticsInformation(
+ ASN1ObjectIdentifier semanticsIdentifier,
+ GeneralName[] generalNames)
+ {
+ this.semanticsIdentifier = semanticsIdentifier;
+ this.nameRegistrationAuthorities = generalNames;
+ }
+
+ public SemanticsInformation(ASN1ObjectIdentifier semanticsIdentifier)
+ {
+ this.semanticsIdentifier = semanticsIdentifier;
+ this.nameRegistrationAuthorities = null;
+ }
+
+ public SemanticsInformation(GeneralName[] generalNames)
+ {
+ this.semanticsIdentifier = null;
+ this.nameRegistrationAuthorities = generalNames;
+ }
+
+ public ASN1ObjectIdentifier getSemanticsIdentifier()
+ {
+ return semanticsIdentifier;
+ }
+
+ public GeneralName[] getNameRegistrationAuthorities()
+ {
+ return nameRegistrationAuthorities;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector seq = new ASN1EncodableVector();
+
+ if (this.semanticsIdentifier != null)
+ {
+ seq.add(semanticsIdentifier);
+ }
+ if (this.nameRegistrationAuthorities != null)
+ {
+ ASN1EncodableVector seqname = new ASN1EncodableVector();
+ for (int i = 0; i < nameRegistrationAuthorities.length; i++)
+ {
+ seqname.add(nameRegistrationAuthorities[i]);
+ }
+ seq.add(new DERSequence(seqname));
+ }
+
+ return new DERSequence(seq);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/qualified/TypeOfBiometricData.java b/core/src/main/java/org/spongycastle/asn1/x509/qualified/TypeOfBiometricData.java
new file mode 100644
index 00000000..e7285d26
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/qualified/TypeOfBiometricData.java
@@ -0,0 +1,90 @@
+package org.spongycastle.asn1.x509.qualified;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+
+/**
+ * The TypeOfBiometricData object.
+ * <pre>
+ * TypeOfBiometricData ::= CHOICE {
+ * predefinedBiometricType PredefinedBiometricType,
+ * biometricDataOid OBJECT IDENTIFIER }
+ *
+ * PredefinedBiometricType ::= INTEGER {
+ * picture(0),handwritten-signature(1)}
+ * (picture|handwritten-signature)
+ * </pre>
+ */
+public class TypeOfBiometricData
+ extends ASN1Object
+ implements ASN1Choice
+{
+ public static final int PICTURE = 0;
+ public static final int HANDWRITTEN_SIGNATURE = 1;
+
+ ASN1Encodable obj;
+
+ public static TypeOfBiometricData getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof TypeOfBiometricData)
+ {
+ return (TypeOfBiometricData)obj;
+ }
+
+ if (obj instanceof ASN1Integer)
+ {
+ ASN1Integer predefinedBiometricTypeObj = ASN1Integer.getInstance(obj);
+ int predefinedBiometricType = predefinedBiometricTypeObj.getValue().intValue();
+
+ return new TypeOfBiometricData(predefinedBiometricType);
+ }
+ else if (obj instanceof ASN1ObjectIdentifier)
+ {
+ ASN1ObjectIdentifier BiometricDataID = ASN1ObjectIdentifier.getInstance(obj);
+ return new TypeOfBiometricData(BiometricDataID);
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance");
+ }
+
+ public TypeOfBiometricData(int predefinedBiometricType)
+ {
+ if (predefinedBiometricType == PICTURE || predefinedBiometricType == HANDWRITTEN_SIGNATURE)
+ {
+ obj = new ASN1Integer(predefinedBiometricType);
+ }
+ else
+ {
+ throw new IllegalArgumentException("unknow PredefinedBiometricType : " + predefinedBiometricType);
+ }
+ }
+
+ public TypeOfBiometricData(ASN1ObjectIdentifier BiometricDataID)
+ {
+ obj = BiometricDataID;
+ }
+
+ public boolean isPredefined()
+ {
+ return obj instanceof ASN1Integer;
+ }
+
+ public int getPredefinedBiometricType()
+ {
+ return ((ASN1Integer)obj).getValue().intValue();
+ }
+
+ public ASN1ObjectIdentifier getBiometricDataOid()
+ {
+ return (ASN1ObjectIdentifier)obj;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return obj.toASN1Primitive();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/sigi/NameOrPseudonym.java b/core/src/main/java/org/spongycastle/asn1/x509/sigi/NameOrPseudonym.java
new file mode 100644
index 00000000..72433a0e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/sigi/NameOrPseudonym.java
@@ -0,0 +1,189 @@
+package org.spongycastle.asn1.x509.sigi;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1String;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x500.DirectoryString;
+
+/**
+ * Structure for a name or pseudonym.
+ *
+ * <pre>
+ * NameOrPseudonym ::= CHOICE {
+ * surAndGivenName SEQUENCE {
+ * surName DirectoryString,
+ * givenName SEQUENCE OF DirectoryString
+ * },
+ * pseudonym DirectoryString
+ * }
+ * </pre>
+ *
+ * @see org.spongycastle.asn1.x509.sigi.PersonalData
+ *
+ */
+public class NameOrPseudonym
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private DirectoryString pseudonym;
+
+ private DirectoryString surname;
+
+ private ASN1Sequence givenName;
+
+ public static NameOrPseudonym getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof NameOrPseudonym)
+ {
+ return (NameOrPseudonym)obj;
+ }
+
+ if (obj instanceof ASN1String)
+ {
+ return new NameOrPseudonym(DirectoryString.getInstance(obj));
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new NameOrPseudonym((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ /**
+ * Constructor from DirectoryString.
+ * <p>
+ * The sequence is of type NameOrPseudonym:
+ * <pre>
+ * NameOrPseudonym ::= CHOICE {
+ * surAndGivenName SEQUENCE {
+ * surName DirectoryString,
+ * givenName SEQUENCE OF DirectoryString
+ * },
+ * pseudonym DirectoryString
+ * }
+ * </pre>
+ * @param pseudonym pseudonym value to use.
+ */
+ public NameOrPseudonym(DirectoryString pseudonym)
+ {
+ this.pseudonym = pseudonym;
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ * <p/>
+ * The sequence is of type NameOrPseudonym:
+ * <p/>
+ * <pre>
+ * NameOrPseudonym ::= CHOICE {
+ * surAndGivenName SEQUENCE {
+ * surName DirectoryString,
+ * givenName SEQUENCE OF DirectoryString
+ * },
+ * pseudonym DirectoryString
+ * }
+ * </pre>
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private NameOrPseudonym(ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ if (!(seq.getObjectAt(0) instanceof ASN1String))
+ {
+ throw new IllegalArgumentException("Bad object encountered: "
+ + seq.getObjectAt(0).getClass());
+ }
+
+ surname = DirectoryString.getInstance(seq.getObjectAt(0));
+ givenName = ASN1Sequence.getInstance(seq.getObjectAt(1));
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param pseudonym The pseudonym.
+ */
+ public NameOrPseudonym(String pseudonym)
+ {
+ this(new DirectoryString(pseudonym));
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param surname The surname.
+ * @param givenName A sequence of directory strings making up the givenName
+ */
+ public NameOrPseudonym(DirectoryString surname, ASN1Sequence givenName)
+ {
+ this.surname = surname;
+ this.givenName = givenName;
+ }
+
+ public DirectoryString getPseudonym()
+ {
+ return pseudonym;
+ }
+
+ public DirectoryString getSurname()
+ {
+ return surname;
+ }
+
+ public DirectoryString[] getGivenName()
+ {
+ DirectoryString[] items = new DirectoryString[givenName.size()];
+ int count = 0;
+ for (Enumeration e = givenName.getObjects(); e.hasMoreElements();)
+ {
+ items[count++] = DirectoryString.getInstance(e.nextElement());
+ }
+ return items;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <p>
+ * Returns:
+ * <pre>
+ * NameOrPseudonym ::= CHOICE {
+ * surAndGivenName SEQUENCE {
+ * surName DirectoryString,
+ * givenName SEQUENCE OF DirectoryString
+ * },
+ * pseudonym DirectoryString
+ * }
+ * </pre>
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (pseudonym != null)
+ {
+ return pseudonym.toASN1Primitive();
+ }
+ else
+ {
+ ASN1EncodableVector vec1 = new ASN1EncodableVector();
+ vec1.add(surname);
+ vec1.add(givenName);
+ return new DERSequence(vec1);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/sigi/PersonalData.java b/core/src/main/java/org/spongycastle/asn1/x509/sigi/PersonalData.java
new file mode 100644
index 00000000..dec8ded6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/sigi/PersonalData.java
@@ -0,0 +1,213 @@
+package org.spongycastle.asn1.x509.sigi;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERPrintableString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x500.DirectoryString;
+
+/**
+ * Contains personal data for the otherName field in the subjectAltNames
+ * extension.
+ *
+ * <pre>
+ * PersonalData ::= SEQUENCE {
+ * nameOrPseudonym NameOrPseudonym,
+ * nameDistinguisher [0] INTEGER OPTIONAL,
+ * dateOfBirth [1] GeneralizedTime OPTIONAL,
+ * placeOfBirth [2] DirectoryString OPTIONAL,
+ * gender [3] PrintableString OPTIONAL,
+ * postalAddress [4] DirectoryString OPTIONAL
+ * }
+ * </pre>
+ *
+ * @see org.spongycastle.asn1.x509.sigi.NameOrPseudonym
+ * @see org.spongycastle.asn1.x509.sigi.SigIObjectIdentifiers
+ */
+public class PersonalData
+ extends ASN1Object
+{
+ private NameOrPseudonym nameOrPseudonym;
+ private BigInteger nameDistinguisher;
+ private ASN1GeneralizedTime dateOfBirth;
+ private DirectoryString placeOfBirth;
+ private String gender;
+ private DirectoryString postalAddress;
+
+ public static PersonalData getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof PersonalData)
+ {
+ return (PersonalData)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new PersonalData((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ * <p/>
+ * The sequence is of type NameOrPseudonym:
+ * <p/>
+ * <pre>
+ * PersonalData ::= SEQUENCE {
+ * nameOrPseudonym NameOrPseudonym,
+ * nameDistinguisher [0] INTEGER OPTIONAL,
+ * dateOfBirth [1] GeneralizedTime OPTIONAL,
+ * placeOfBirth [2] DirectoryString OPTIONAL,
+ * gender [3] PrintableString OPTIONAL,
+ * postalAddress [4] DirectoryString OPTIONAL
+ * }
+ * </pre>
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private PersonalData(ASN1Sequence seq)
+ {
+ if (seq.size() < 1)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ Enumeration e = seq.getObjects();
+
+ nameOrPseudonym = NameOrPseudonym.getInstance(e.nextElement());
+
+ while (e.hasMoreElements())
+ {
+ ASN1TaggedObject o = ASN1TaggedObject.getInstance(e.nextElement());
+ int tag = o.getTagNo();
+ switch (tag)
+ {
+ case 0:
+ nameDistinguisher = ASN1Integer.getInstance(o, false).getValue();
+ break;
+ case 1:
+ dateOfBirth = ASN1GeneralizedTime.getInstance(o, false);
+ break;
+ case 2:
+ placeOfBirth = DirectoryString.getInstance(o, true);
+ break;
+ case 3:
+ gender = DERPrintableString.getInstance(o, false).getString();
+ break;
+ case 4:
+ postalAddress = DirectoryString.getInstance(o, true);
+ break;
+ default:
+ throw new IllegalArgumentException("Bad tag number: " + o.getTagNo());
+ }
+ }
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param nameOrPseudonym Name or pseudonym.
+ * @param nameDistinguisher Name distinguisher.
+ * @param dateOfBirth Date of birth.
+ * @param placeOfBirth Place of birth.
+ * @param gender Gender.
+ * @param postalAddress Postal Address.
+ */
+ public PersonalData(NameOrPseudonym nameOrPseudonym,
+ BigInteger nameDistinguisher, ASN1GeneralizedTime dateOfBirth,
+ DirectoryString placeOfBirth, String gender, DirectoryString postalAddress)
+ {
+ this.nameOrPseudonym = nameOrPseudonym;
+ this.dateOfBirth = dateOfBirth;
+ this.gender = gender;
+ this.nameDistinguisher = nameDistinguisher;
+ this.postalAddress = postalAddress;
+ this.placeOfBirth = placeOfBirth;
+ }
+
+ public NameOrPseudonym getNameOrPseudonym()
+ {
+ return nameOrPseudonym;
+ }
+
+ public BigInteger getNameDistinguisher()
+ {
+ return nameDistinguisher;
+ }
+
+ public ASN1GeneralizedTime getDateOfBirth()
+ {
+ return dateOfBirth;
+ }
+
+ public DirectoryString getPlaceOfBirth()
+ {
+ return placeOfBirth;
+ }
+
+ public String getGender()
+ {
+ return gender;
+ }
+
+ public DirectoryString getPostalAddress()
+ {
+ return postalAddress;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <p>
+ * Returns:
+ * <pre>
+ * PersonalData ::= SEQUENCE {
+ * nameOrPseudonym NameOrPseudonym,
+ * nameDistinguisher [0] INTEGER OPTIONAL,
+ * dateOfBirth [1] GeneralizedTime OPTIONAL,
+ * placeOfBirth [2] DirectoryString OPTIONAL,
+ * gender [3] PrintableString OPTIONAL,
+ * postalAddress [4] DirectoryString OPTIONAL
+ * }
+ * </pre>
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+ vec.add(nameOrPseudonym);
+ if (nameDistinguisher != null)
+ {
+ vec.add(new DERTaggedObject(false, 0, new ASN1Integer(nameDistinguisher)));
+ }
+ if (dateOfBirth != null)
+ {
+ vec.add(new DERTaggedObject(false, 1, dateOfBirth));
+ }
+ if (placeOfBirth != null)
+ {
+ vec.add(new DERTaggedObject(true, 2, placeOfBirth));
+ }
+ if (gender != null)
+ {
+ vec.add(new DERTaggedObject(false, 3, new DERPrintableString(gender, true)));
+ }
+ if (postalAddress != null)
+ {
+ vec.add(new DERTaggedObject(true, 4, postalAddress));
+ }
+ return new DERSequence(vec);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x509/sigi/SigIObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/x509/sigi/SigIObjectIdentifiers.java
new file mode 100644
index 00000000..5d9b25b3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x509/sigi/SigIObjectIdentifiers.java
@@ -0,0 +1,60 @@
+package org.spongycastle.asn1.x509.sigi;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+
+/**
+ * Object Identifiers of SigI specifciation (German Signature Law
+ * Interoperability specification).
+ */
+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("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("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("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("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("1.3.36.8.4.1");
+
+ /**
+ * 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("1.3.36.8.1.1");
+
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x9/DHDomainParameters.java b/core/src/main/java/org/spongycastle/asn1/x9/DHDomainParameters.java
new file mode 100644
index 00000000..38575d89
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x9/DHDomainParameters.java
@@ -0,0 +1,163 @@
+package org.spongycastle.asn1.x9;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERSequence;
+
+public class DHDomainParameters
+ extends ASN1Object
+{
+ private ASN1Integer p, g, q, j;
+ private DHValidationParms validationParms;
+
+ public static DHDomainParameters getInstance(ASN1TaggedObject obj, boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static DHDomainParameters getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof DHDomainParameters)
+ {
+ return (DHDomainParameters)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new DHDomainParameters((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid DHDomainParameters: "
+ + obj.getClass().getName());
+ }
+
+ public DHDomainParameters(BigInteger p, BigInteger g, BigInteger q, BigInteger j,
+ DHValidationParms validationParms)
+ {
+ if (p == null)
+ {
+ throw new IllegalArgumentException("'p' cannot be null");
+ }
+ if (g == null)
+ {
+ throw new IllegalArgumentException("'g' cannot be null");
+ }
+ if (q == null)
+ {
+ throw new IllegalArgumentException("'q' cannot be null");
+ }
+
+ this.p = new ASN1Integer(p);
+ this.g = new ASN1Integer(g);
+ this.q = new ASN1Integer(q);
+ this.j = new ASN1Integer(j);
+ this.validationParms = validationParms;
+ }
+
+ public DHDomainParameters(ASN1Integer p, ASN1Integer g, ASN1Integer q, ASN1Integer j,
+ DHValidationParms validationParms)
+ {
+ if (p == null)
+ {
+ throw new IllegalArgumentException("'p' cannot be null");
+ }
+ if (g == null)
+ {
+ throw new IllegalArgumentException("'g' cannot be null");
+ }
+ if (q == null)
+ {
+ throw new IllegalArgumentException("'q' cannot be null");
+ }
+
+ this.p = p;
+ this.g = g;
+ this.q = q;
+ this.j = j;
+ this.validationParms = validationParms;
+ }
+
+ private DHDomainParameters(ASN1Sequence seq)
+ {
+ if (seq.size() < 3 || seq.size() > 5)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ Enumeration e = seq.getObjects();
+ this.p = ASN1Integer.getInstance(e.nextElement());
+ this.g = ASN1Integer.getInstance(e.nextElement());
+ this.q = ASN1Integer.getInstance(e.nextElement());
+
+ ASN1Encodable next = getNext(e);
+
+ if (next != null && next instanceof ASN1Integer)
+ {
+ this.j = ASN1Integer.getInstance(next);
+ next = getNext(e);
+ }
+
+ if (next != null)
+ {
+ this.validationParms = DHValidationParms.getInstance(next.toASN1Primitive());
+ }
+ }
+
+ private static ASN1Encodable getNext(Enumeration e)
+ {
+ return e.hasMoreElements() ? (ASN1Encodable)e.nextElement() : null;
+ }
+
+ public ASN1Integer getP()
+ {
+ return this.p;
+ }
+
+ public ASN1Integer getG()
+ {
+ return this.g;
+ }
+
+ public ASN1Integer getQ()
+ {
+ return this.q;
+ }
+
+ public ASN1Integer getJ()
+ {
+ return this.j;
+ }
+
+ public DHValidationParms getValidationParms()
+ {
+ return this.validationParms;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(this.p);
+ v.add(this.g);
+ v.add(this.q);
+
+ if (this.j != null)
+ {
+ v.add(this.j);
+ }
+
+ if (this.validationParms != null)
+ {
+ v.add(this.validationParms);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x9/DHPublicKey.java b/core/src/main/java/org/spongycastle/asn1/x9/DHPublicKey.java
new file mode 100644
index 00000000..b84a42b4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x9/DHPublicKey.java
@@ -0,0 +1,52 @@
+package org.spongycastle.asn1.x9;
+
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+
+public class DHPublicKey
+ extends ASN1Object
+{
+ private ASN1Integer y;
+
+ public static DHPublicKey getInstance(ASN1TaggedObject obj, boolean explicit)
+ {
+ return getInstance(ASN1Integer.getInstance(obj, explicit));
+ }
+
+ public static DHPublicKey getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof DHPublicKey)
+ {
+ return (DHPublicKey)obj;
+ }
+
+ if (obj instanceof ASN1Integer)
+ {
+ return new DHPublicKey((ASN1Integer)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid DHPublicKey: " + obj.getClass().getName());
+ }
+
+ public DHPublicKey(ASN1Integer y)
+ {
+ if (y == null)
+ {
+ throw new IllegalArgumentException("'y' cannot be null");
+ }
+
+ this.y = y;
+ }
+
+ public ASN1Integer getY()
+ {
+ return this.y;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return this.y;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x9/DHValidationParms.java b/core/src/main/java/org/spongycastle/asn1/x9/DHValidationParms.java
new file mode 100644
index 00000000..f70991c0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x9/DHValidationParms.java
@@ -0,0 +1,79 @@
+package org.spongycastle.asn1.x9;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+
+public class DHValidationParms extends ASN1Object
+{
+ private DERBitString seed;
+ private ASN1Integer pgenCounter;
+
+ public static DHValidationParms getInstance(ASN1TaggedObject obj, boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static DHValidationParms getInstance(Object obj)
+ {
+ if (obj instanceof DHValidationParms)
+ {
+ return (DHValidationParms)obj;
+ }
+ else if (obj != null)
+ {
+ return new DHValidationParms(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public DHValidationParms(DERBitString seed, ASN1Integer pgenCounter)
+ {
+ if (seed == null)
+ {
+ throw new IllegalArgumentException("'seed' cannot be null");
+ }
+ if (pgenCounter == null)
+ {
+ throw new IllegalArgumentException("'pgenCounter' cannot be null");
+ }
+
+ this.seed = seed;
+ this.pgenCounter = pgenCounter;
+ }
+
+ private DHValidationParms(ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ this.seed = DERBitString.getInstance(seq.getObjectAt(0));
+ this.pgenCounter = ASN1Integer.getInstance(seq.getObjectAt(1));
+ }
+
+ public DERBitString getSeed()
+ {
+ return this.seed;
+ }
+
+ public ASN1Integer getPgenCounter()
+ {
+ return this.pgenCounter;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(this.seed);
+ v.add(this.pgenCounter);
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x9/ECNamedCurveTable.java b/core/src/main/java/org/spongycastle/asn1/x9/ECNamedCurveTable.java
new file mode 100644
index 00000000..c5b471ae
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x9/ECNamedCurveTable.java
@@ -0,0 +1,128 @@
+package org.spongycastle.asn1.x9;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.nist.NISTNamedCurves;
+import org.spongycastle.asn1.sec.SECNamedCurves;
+import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves;
+
+/**
+ * A general class that reads all X9.62 style EC curve tables.
+ */
+public class ECNamedCurveTable
+{
+ /**
+ * return a X9ECParameters object representing the passed in named
+ * curve. The routine returns null if the curve is not present.
+ *
+ * @param name the name of the curve requested
+ * @return an X9ECParameters object or null if the curve is not available.
+ */
+ public static X9ECParameters getByName(
+ String name)
+ {
+ X9ECParameters ecP = X962NamedCurves.getByName(name);
+
+ if (ecP == null)
+ {
+ ecP = SECNamedCurves.getByName(name);
+ }
+
+ if (ecP == null)
+ {
+ ecP = TeleTrusTNamedCurves.getByName(name);
+ }
+
+ if (ecP == null)
+ {
+ ecP = NISTNamedCurves.getByName(name);
+ }
+
+ return ecP;
+ }
+
+ /**
+ * return the object identifier signified by the passed in name. Null
+ * if there is no object identifier associated with name.
+ *
+ * @return the object identifier associated with name, if present.
+ */
+ public static ASN1ObjectIdentifier getOID(
+ String name)
+ {
+ ASN1ObjectIdentifier oid = X962NamedCurves.getOID(name);
+
+ if (oid == null)
+ {
+ oid = SECNamedCurves.getOID(name);
+ }
+
+ if (oid == null)
+ {
+ oid = TeleTrusTNamedCurves.getOID(name);
+ }
+
+ if (oid == null)
+ {
+ oid = NISTNamedCurves.getOID(name);
+ }
+
+ return oid;
+ }
+
+ /**
+ * return a X9ECParameters object representing the passed in named
+ * curve.
+ *
+ * @param oid the object id of the curve requested
+ * @return an X9ECParameters object or null if the curve is not available.
+ */
+ public static X9ECParameters getByOID(
+ ASN1ObjectIdentifier oid)
+ {
+ X9ECParameters ecP = X962NamedCurves.getByOID(oid);
+
+ if (ecP == null)
+ {
+ ecP = SECNamedCurves.getByOID(oid);
+ }
+
+ if (ecP == null)
+ {
+ ecP = TeleTrusTNamedCurves.getByOID(oid);
+ }
+
+ // NOTE: All the NIST curves are currently from SEC, so no point in redundant OID lookup
+
+ return ecP;
+ }
+
+ /**
+ * return an enumeration of the names of the available curves.
+ *
+ * @return an enumeration of the names of the available curves.
+ */
+ 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());
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x9/KeySpecificInfo.java b/core/src/main/java/org/spongycastle/asn1/x9/KeySpecificInfo.java
new file mode 100644
index 00000000..3a7f9517
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x9/KeySpecificInfo.java
@@ -0,0 +1,68 @@
+package org.spongycastle.asn1.x9;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * ASN.1 def for Diffie-Hellman key exchange KeySpecificInfo structure. See
+ * RFC 2631, or X9.42, for further details.
+ */
+public class KeySpecificInfo
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier algorithm;
+ private ASN1OctetString counter;
+
+ public KeySpecificInfo(
+ ASN1ObjectIdentifier algorithm,
+ ASN1OctetString counter)
+ {
+ this.algorithm = algorithm;
+ this.counter = counter;
+ }
+
+ public KeySpecificInfo(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ algorithm = (ASN1ObjectIdentifier)e.nextElement();
+ counter = (ASN1OctetString)e.nextElement();
+ }
+
+ public ASN1ObjectIdentifier getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ public ASN1OctetString getCounter()
+ {
+ return counter;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * KeySpecificInfo ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * counter OCTET STRING SIZE (4..4)
+ * }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(algorithm);
+ v.add(counter);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x9/OtherInfo.java b/core/src/main/java/org/spongycastle/asn1/x9/OtherInfo.java
new file mode 100644
index 00000000..3506c868
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x9/OtherInfo.java
@@ -0,0 +1,96 @@
+package org.spongycastle.asn1.x9;
+
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+
+/**
+ * ANS.1 def for Diffie-Hellman key exchange OtherInfo structure. See
+ * RFC 2631, or X9.42, for further details.
+ */
+public class OtherInfo
+ extends ASN1Object
+{
+ private KeySpecificInfo keyInfo;
+ private ASN1OctetString partyAInfo;
+ private ASN1OctetString suppPubInfo;
+
+ public OtherInfo(
+ KeySpecificInfo keyInfo,
+ ASN1OctetString partyAInfo,
+ ASN1OctetString suppPubInfo)
+ {
+ this.keyInfo = keyInfo;
+ this.partyAInfo = partyAInfo;
+ this.suppPubInfo = suppPubInfo;
+ }
+
+ public OtherInfo(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ keyInfo = new KeySpecificInfo((ASN1Sequence)e.nextElement());
+
+ while (e.hasMoreElements())
+ {
+ DERTaggedObject o = (DERTaggedObject)e.nextElement();
+
+ if (o.getTagNo() == 0)
+ {
+ partyAInfo = (ASN1OctetString)o.getObject();
+ }
+ else if (o.getTagNo() == 2)
+ {
+ suppPubInfo = (ASN1OctetString)o.getObject();
+ }
+ }
+ }
+
+ public KeySpecificInfo getKeyInfo()
+ {
+ return keyInfo;
+ }
+
+ public ASN1OctetString getPartyAInfo()
+ {
+ return partyAInfo;
+ }
+
+ public ASN1OctetString getSuppPubInfo()
+ {
+ return suppPubInfo;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * OtherInfo ::= SEQUENCE {
+ * keyInfo KeySpecificInfo,
+ * partyAInfo [0] OCTET STRING OPTIONAL,
+ * suppPubInfo [2] OCTET STRING
+ * }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(keyInfo);
+
+ if (partyAInfo != null)
+ {
+ v.add(new DERTaggedObject(0, partyAInfo));
+ }
+
+ v.add(new DERTaggedObject(2, suppPubInfo));
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x9/X962NamedCurves.java b/core/src/main/java/org/spongycastle/asn1/x9/X962NamedCurves.java
new file mode 100644
index 00000000..61a6fc4b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x9/X962NamedCurves.java
@@ -0,0 +1,642 @@
+package org.spongycastle.asn1.x9;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.util.Strings;
+import org.spongycastle.util.encoders.Hex;
+
+
+/**
+ * table of the current named curves defined in X.962 EC-DSA.
+ */
+public class X962NamedCurves
+{
+ static X9ECParametersHolder prime192v1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger n = new BigInteger("ffffffffffffffffffffffff99def836146bc9b1b4d22831", 16);
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve cFp192v1 = new ECCurve.Fp(
+ new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
+ new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
+ new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16),
+ n, h);
+
+ return new X9ECParameters(
+ cFp192v1,
+ cFp192v1.decodePoint(
+ Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")),
+ n, h,
+ Hex.decode("3045AE6FC8422f64ED579528D38120EAE12196D5"));
+ }
+ };
+
+ static X9ECParametersHolder prime192v2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger n = new BigInteger("fffffffffffffffffffffffe5fb1a724dc80418648d8dd31", 16);
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve cFp192v2 = new ECCurve.Fp(
+ new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
+ new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
+ new BigInteger("cc22d6dfb95c6b25e49c0d6364a4e5980c393aa21668d953", 16),
+ n, h);
+
+ return new X9ECParameters(
+ cFp192v2,
+ cFp192v2.decodePoint(
+ Hex.decode("03eea2bae7e1497842f2de7769cfe9c989c072ad696f48034a")),
+ n, h,
+ Hex.decode("31a92ee2029fd10d901b113e990710f0d21ac6b6"));
+ }
+ };
+
+ static X9ECParametersHolder prime192v3 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger n = new BigInteger("ffffffffffffffffffffffff7a62d031c83f4294f640ec13", 16);
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve cFp192v3 = new ECCurve.Fp(
+ new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
+ new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
+ new BigInteger("22123dc2395a05caa7423daeccc94760a7d462256bd56916", 16),
+ n, h);
+
+ return new X9ECParameters(
+ cFp192v3,
+ cFp192v3.decodePoint(
+ Hex.decode("027d29778100c65a1da1783716588dce2b8b4aee8e228f1896")),
+ n, h,
+ Hex.decode("c469684435deb378c4b65ca9591e2a5763059a2e"));
+ }
+ };
+
+ static X9ECParametersHolder prime239v1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger n = new BigInteger("7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b", 16);
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve cFp239v1 = new ECCurve.Fp(
+ new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
+ new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
+ new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16),
+ n, h);
+
+ return new X9ECParameters(
+ cFp239v1,
+ cFp239v1.decodePoint(
+ Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")),
+ n, h,
+ Hex.decode("e43bb460f0b80cc0c0b075798e948060f8321b7d"));
+ }
+ };
+
+ static X9ECParametersHolder prime239v2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger n = new BigInteger("7fffffffffffffffffffffff800000cfa7e8594377d414c03821bc582063", 16);
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve cFp239v2 = new ECCurve.Fp(
+ new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
+ new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
+ new BigInteger("617fab6832576cbbfed50d99f0249c3fee58b94ba0038c7ae84c8c832f2c", 16),
+ n, h);
+
+ return new X9ECParameters(
+ cFp239v2,
+ cFp239v2.decodePoint(
+ Hex.decode("0238af09d98727705120c921bb5e9e26296a3cdcf2f35757a0eafd87b830e7")),
+ n, h,
+ Hex.decode("e8b4011604095303ca3b8099982be09fcb9ae616"));
+ }
+ };
+
+ static X9ECParametersHolder prime239v3 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger n = new BigInteger("7fffffffffffffffffffffff7fffff975deb41b3a6057c3c432146526551", 16);
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve cFp239v3 = new ECCurve.Fp(
+ new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
+ new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
+ new BigInteger("255705fa2a306654b1f4cb03d6a750a30c250102d4988717d9ba15ab6d3e", 16),
+ n, h);
+
+ return new X9ECParameters(
+ cFp239v3,
+ cFp239v3.decodePoint(
+ Hex.decode("036768ae8e18bb92cfcf005c949aa2c6d94853d0e660bbf854b1c9505fe95a")),
+ n, h,
+ Hex.decode("7d7374168ffe3471b60a857686a19475d3bfa2ff"));
+ }
+ };
+
+ static X9ECParametersHolder prime256v1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger n = new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16);
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve cFp256v1 = new ECCurve.Fp(
+ new BigInteger("115792089210356248762697446949407573530086143415290314195533631308867097853951"),
+ new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16),
+ new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16),
+ n, h);
+
+ return new X9ECParameters(
+ cFp256v1,
+ cFp256v1.decodePoint(
+ Hex.decode("036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296")),
+ n, h,
+ Hex.decode("c49d360886e704936a6678e1139d26b7819f7e90"));
+ }
+ };
+
+ /*
+ * F2m Curves
+ */
+ static X9ECParametersHolder c2pnb163v1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m163v1n = new BigInteger("0400000000000000000001E60FC8821CC74DAEAFC1", 16);
+ BigInteger c2m163v1h = BigInteger.valueOf(2);
+
+ ECCurve c2m163v1 = new ECCurve.F2m(
+ 163,
+ 1, 2, 8,
+ new BigInteger("072546B5435234A422E0789675F432C89435DE5242", 16),
+ new BigInteger("00C9517D06D5240D3CFF38C74B20B6CD4D6F9DD4D9", 16),
+ c2m163v1n, c2m163v1h);
+
+ return new X9ECParameters(
+ c2m163v1,
+ c2m163v1.decodePoint(
+ Hex.decode("0307AF69989546103D79329FCC3D74880F33BBE803CB")),
+ c2m163v1n, c2m163v1h,
+ Hex.decode("D2C0FB15760860DEF1EEF4D696E6768756151754"));
+ }
+ };
+
+ static X9ECParametersHolder c2pnb163v2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m163v2n = new BigInteger("03FFFFFFFFFFFFFFFFFFFDF64DE1151ADBB78F10A7", 16);
+ BigInteger c2m163v2h = BigInteger.valueOf(2);
+
+ ECCurve c2m163v2 = new ECCurve.F2m(
+ 163,
+ 1, 2, 8,
+ new BigInteger("0108B39E77C4B108BED981ED0E890E117C511CF072", 16),
+ new BigInteger("0667ACEB38AF4E488C407433FFAE4F1C811638DF20", 16),
+ c2m163v2n, c2m163v2h);
+
+ return new X9ECParameters(
+ c2m163v2,
+ c2m163v2.decodePoint(
+ Hex.decode("030024266E4EB5106D0A964D92C4860E2671DB9B6CC5")),
+ c2m163v2n, c2m163v2h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2pnb163v3 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m163v3n = new BigInteger("03FFFFFFFFFFFFFFFFFFFE1AEE140F110AFF961309", 16);
+ BigInteger c2m163v3h = BigInteger.valueOf(2);
+
+ ECCurve c2m163v3 = new ECCurve.F2m(
+ 163,
+ 1, 2, 8,
+ new BigInteger("07A526C63D3E25A256A007699F5447E32AE456B50E", 16),
+ new BigInteger("03F7061798EB99E238FD6F1BF95B48FEEB4854252B", 16),
+ c2m163v3n, c2m163v3h);
+
+ return new X9ECParameters(
+ c2m163v3,
+ c2m163v3.decodePoint(
+ Hex.decode("0202F9F87B7C574D0BDECF8A22E6524775F98CDEBDCB")),
+ c2m163v3n, c2m163v3h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2pnb176w1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m176w1n = new BigInteger("010092537397ECA4F6145799D62B0A19CE06FE26AD", 16);
+ BigInteger c2m176w1h = BigInteger.valueOf(0xFF6E);
+
+ ECCurve c2m176w1 = new ECCurve.F2m(
+ 176,
+ 1, 2, 43,
+ new BigInteger("00E4E6DB2995065C407D9D39B8D0967B96704BA8E9C90B", 16),
+ new BigInteger("005DDA470ABE6414DE8EC133AE28E9BBD7FCEC0AE0FFF2", 16),
+ c2m176w1n, c2m176w1h);
+
+ return new X9ECParameters(
+ c2m176w1,
+ c2m176w1.decodePoint(
+ Hex.decode("038D16C2866798B600F9F08BB4A8E860F3298CE04A5798")),
+ c2m176w1n, c2m176w1h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2tnb191v1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m191v1n = new BigInteger("40000000000000000000000004A20E90C39067C893BBB9A5", 16);
+ BigInteger c2m191v1h = BigInteger.valueOf(2);
+
+ ECCurve c2m191v1 = new ECCurve.F2m(
+ 191,
+ 9,
+ new BigInteger("2866537B676752636A68F56554E12640276B649EF7526267", 16),
+ new BigInteger("2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC", 16),
+ c2m191v1n, c2m191v1h);
+
+ return new X9ECParameters(
+ c2m191v1,
+ c2m191v1.decodePoint(
+ Hex.decode("0236B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D")),
+ c2m191v1n, c2m191v1h,
+ Hex.decode("4E13CA542744D696E67687561517552F279A8C84"));
+ }
+ };
+
+ static X9ECParametersHolder c2tnb191v2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m191v2n = new BigInteger("20000000000000000000000050508CB89F652824E06B8173", 16);
+ BigInteger c2m191v2h = BigInteger.valueOf(4);
+
+ ECCurve c2m191v2 = new ECCurve.F2m(
+ 191,
+ 9,
+ new BigInteger("401028774D7777C7B7666D1366EA432071274F89FF01E718", 16),
+ new BigInteger("0620048D28BCBD03B6249C99182B7C8CD19700C362C46A01", 16),
+ c2m191v2n, c2m191v2h);
+
+ return new X9ECParameters(
+ c2m191v2,
+ c2m191v2.decodePoint(
+ Hex.decode("023809B2B7CC1B28CC5A87926AAD83FD28789E81E2C9E3BF10")),
+ c2m191v2n, c2m191v2h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2tnb191v3 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m191v3n = new BigInteger("155555555555555555555555610C0B196812BFB6288A3EA3", 16);
+ BigInteger c2m191v3h = BigInteger.valueOf(6);
+
+ ECCurve c2m191v3 = new ECCurve.F2m(
+ 191,
+ 9,
+ new BigInteger("6C01074756099122221056911C77D77E77A777E7E7E77FCB", 16),
+ new BigInteger("71FE1AF926CF847989EFEF8DB459F66394D90F32AD3F15E8", 16),
+ c2m191v3n, c2m191v3h);
+
+ return new X9ECParameters(
+ c2m191v3,
+ c2m191v3.decodePoint(
+ Hex.decode("03375D4CE24FDE434489DE8746E71786015009E66E38A926DD")),
+ c2m191v3n, c2m191v3h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2pnb208w1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m208w1n = new BigInteger("0101BAF95C9723C57B6C21DA2EFF2D5ED588BDD5717E212F9D", 16);
+ BigInteger c2m208w1h = BigInteger.valueOf(0xFE48);
+
+ ECCurve c2m208w1 = new ECCurve.F2m(
+ 208,
+ 1, 2, 83,
+ new BigInteger("0", 16),
+ new BigInteger("00C8619ED45A62E6212E1160349E2BFA844439FAFC2A3FD1638F9E", 16),
+ c2m208w1n, c2m208w1h);
+
+ return new X9ECParameters(
+ c2m208w1,
+ c2m208w1.decodePoint(
+ Hex.decode("0289FDFBE4ABE193DF9559ECF07AC0CE78554E2784EB8C1ED1A57A")),
+ c2m208w1n, c2m208w1h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2tnb239v1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m239v1n = new BigInteger("2000000000000000000000000000000F4D42FFE1492A4993F1CAD666E447", 16);
+ BigInteger c2m239v1h = BigInteger.valueOf(4);
+
+ ECCurve c2m239v1 = new ECCurve.F2m(
+ 239,
+ 36,
+ new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16),
+ new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16),
+ c2m239v1n, c2m239v1h);
+
+ return new X9ECParameters(
+ c2m239v1,
+ c2m239v1.decodePoint(
+ Hex.decode("0257927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D")),
+ c2m239v1n, c2m239v1h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2tnb239v2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m239v2n = new BigInteger("1555555555555555555555555555553C6F2885259C31E3FCDF154624522D", 16);
+ BigInteger c2m239v2h = BigInteger.valueOf(6);
+
+ ECCurve c2m239v2 = new ECCurve.F2m(
+ 239,
+ 36,
+ new BigInteger("4230017757A767FAE42398569B746325D45313AF0766266479B75654E65F", 16),
+ new BigInteger("5037EA654196CFF0CD82B2C14A2FCF2E3FF8775285B545722F03EACDB74B", 16),
+ c2m239v2n, c2m239v2h);
+
+ return new X9ECParameters(
+ c2m239v2,
+ c2m239v2.decodePoint(
+ Hex.decode("0228F9D04E900069C8DC47A08534FE76D2B900B7D7EF31F5709F200C4CA205")),
+ c2m239v2n, c2m239v2h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2tnb239v3 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m239v3n = new BigInteger("0CCCCCCCCCCCCCCCCCCCCCCCCCCCCCAC4912D2D9DF903EF9888B8A0E4CFF", 16);
+ BigInteger c2m239v3h = BigInteger.valueOf(10);
+
+ ECCurve c2m239v3 = new ECCurve.F2m(
+ 239,
+ 36,
+ new BigInteger("01238774666A67766D6676F778E676B66999176666E687666D8766C66A9F", 16),
+ new BigInteger("6A941977BA9F6A435199ACFC51067ED587F519C5ECB541B8E44111DE1D40", 16),
+ c2m239v3n, c2m239v3h);
+
+ return new X9ECParameters(
+ c2m239v3,
+ c2m239v3.decodePoint(
+ Hex.decode("0370F6E9D04D289C4E89913CE3530BFDE903977D42B146D539BF1BDE4E9C92")),
+ c2m239v3n, c2m239v3h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2pnb272w1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m272w1n = new BigInteger("0100FAF51354E0E39E4892DF6E319C72C8161603FA45AA7B998A167B8F1E629521", 16);
+ BigInteger c2m272w1h = BigInteger.valueOf(0xFF06);
+
+ ECCurve c2m272w1 = new ECCurve.F2m(
+ 272,
+ 1, 3, 56,
+ new BigInteger("0091A091F03B5FBA4AB2CCF49C4EDD220FB028712D42BE752B2C40094DBACDB586FB20", 16),
+ new BigInteger("7167EFC92BB2E3CE7C8AAAFF34E12A9C557003D7C73A6FAF003F99F6CC8482E540F7", 16),
+ c2m272w1n, c2m272w1h);
+
+ return new X9ECParameters(
+ c2m272w1,
+ c2m272w1.decodePoint(
+ Hex.decode("026108BABB2CEEBCF787058A056CBE0CFE622D7723A289E08A07AE13EF0D10D171DD8D")),
+ c2m272w1n, c2m272w1h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2pnb304w1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m304w1n = new BigInteger("0101D556572AABAC800101D556572AABAC8001022D5C91DD173F8FB561DA6899164443051D", 16);
+ BigInteger c2m304w1h = BigInteger.valueOf(0xFE2E);
+
+ ECCurve c2m304w1 = new ECCurve.F2m(
+ 304,
+ 1, 2, 11,
+ new BigInteger("00FD0D693149A118F651E6DCE6802085377E5F882D1B510B44160074C1288078365A0396C8E681", 16),
+ new BigInteger("00BDDB97E555A50A908E43B01C798EA5DAA6788F1EA2794EFCF57166B8C14039601E55827340BE", 16),
+ c2m304w1n, c2m304w1h);
+
+ return new X9ECParameters(
+ c2m304w1,
+ c2m304w1.decodePoint(
+ Hex.decode("02197B07845E9BE2D96ADB0F5F3C7F2CFFBD7A3EB8B6FEC35C7FD67F26DDF6285A644F740A2614")),
+ c2m304w1n, c2m304w1h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2tnb359v1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m359v1n = new BigInteger("01AF286BCA1AF286BCA1AF286BCA1AF286BCA1AF286BC9FB8F6B85C556892C20A7EB964FE7719E74F490758D3B", 16);
+ BigInteger c2m359v1h = BigInteger.valueOf(0x4C);
+
+ ECCurve c2m359v1 = new ECCurve.F2m(
+ 359,
+ 68,
+ new BigInteger("5667676A654B20754F356EA92017D946567C46675556F19556A04616B567D223A5E05656FB549016A96656A557", 16),
+ new BigInteger("2472E2D0197C49363F1FE7F5B6DB075D52B6947D135D8CA445805D39BC345626089687742B6329E70680231988", 16),
+ c2m359v1n, c2m359v1h);
+
+ return new X9ECParameters(
+ c2m359v1,
+ c2m359v1.decodePoint(
+ Hex.decode("033C258EF3047767E7EDE0F1FDAA79DAEE3841366A132E163ACED4ED2401DF9C6BDCDE98E8E707C07A2239B1B097")),
+ c2m359v1n, c2m359v1h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2pnb368w1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m368w1n = new BigInteger("010090512DA9AF72B08349D98A5DD4C7B0532ECA51CE03E2D10F3B7AC579BD87E909AE40A6F131E9CFCE5BD967", 16);
+ BigInteger c2m368w1h = BigInteger.valueOf(0xFF70);
+
+ ECCurve c2m368w1 = new ECCurve.F2m(
+ 368,
+ 1, 2, 85,
+ new BigInteger("00E0D2EE25095206F5E2A4F9ED229F1F256E79A0E2B455970D8D0D865BD94778C576D62F0AB7519CCD2A1A906AE30D", 16),
+ new BigInteger("00FC1217D4320A90452C760A58EDCD30C8DD069B3C34453837A34ED50CB54917E1C2112D84D164F444F8F74786046A", 16),
+ c2m368w1n, c2m368w1h);
+
+ return new X9ECParameters(
+ c2m368w1,
+ c2m368w1.decodePoint(
+ Hex.decode("021085E2755381DCCCE3C1557AFA10C2F0C0C2825646C5B34A394CBCFA8BC16B22E7E789E927BE216F02E1FB136A5F")),
+ c2m368w1n, c2m368w1h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2tnb431r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m431r1n = new BigInteger("0340340340340340340340340340340340340340340340340340340323C313FAB50589703B5EC68D3587FEC60D161CC149C1AD4A91", 16);
+ BigInteger c2m431r1h = BigInteger.valueOf(0x2760);
+
+ ECCurve c2m431r1 = new ECCurve.F2m(
+ 431,
+ 120,
+ new BigInteger("1A827EF00DD6FC0E234CAF046C6A5D8A85395B236CC4AD2CF32A0CADBDC9DDF620B0EB9906D0957F6C6FEACD615468DF104DE296CD8F", 16),
+ new BigInteger("10D9B4A3D9047D8B154359ABFB1B7F5485B04CEB868237DDC9DEDA982A679A5A919B626D4E50A8DD731B107A9962381FB5D807BF2618", 16),
+ c2m431r1n, c2m431r1h);
+
+ return new X9ECParameters(
+ c2m431r1,
+ c2m431r1.decodePoint(
+ Hex.decode("02120FC05D3C67A99DE161D2F4092622FECA701BE4F50F4758714E8A87BBF2A658EF8C21E7C5EFE965361F6C2999C0C247B0DBD70CE6B7")),
+ c2m431r1n, c2m431r1h,
+ null);
+ }
+ };
+
+ static final Hashtable objIds = new Hashtable();
+ static final Hashtable curves = new Hashtable();
+ static final Hashtable names = new Hashtable();
+
+ static void defineCurve(String name, ASN1ObjectIdentifier oid, X9ECParametersHolder holder)
+ {
+ objIds.put(name, oid);
+ names.put(oid, name);
+ curves.put(oid, holder);
+ }
+
+ static
+ {
+ defineCurve("prime192v1", X9ObjectIdentifiers.prime192v1, prime192v1);
+ defineCurve("prime192v2", X9ObjectIdentifiers.prime192v2, prime192v2);
+ defineCurve("prime192v3", X9ObjectIdentifiers.prime192v3, prime192v3);
+ defineCurve("prime239v1", X9ObjectIdentifiers.prime239v1, prime239v1);
+ defineCurve("prime239v2", X9ObjectIdentifiers.prime239v2, prime239v2);
+ defineCurve("prime239v3", X9ObjectIdentifiers.prime239v3, prime239v3);
+ defineCurve("prime256v1", X9ObjectIdentifiers.prime256v1, prime256v1);
+ defineCurve("c2pnb163v1", X9ObjectIdentifiers.c2pnb163v1, c2pnb163v1);
+ defineCurve("c2pnb163v2", X9ObjectIdentifiers.c2pnb163v2, c2pnb163v2);
+ defineCurve("c2pnb163v3", X9ObjectIdentifiers.c2pnb163v3, c2pnb163v3);
+ defineCurve("c2pnb176w1", X9ObjectIdentifiers.c2pnb176w1, c2pnb176w1);
+ defineCurve("c2tnb191v1", X9ObjectIdentifiers.c2tnb191v1, c2tnb191v1);
+ defineCurve("c2tnb191v2", X9ObjectIdentifiers.c2tnb191v2, c2tnb191v2);
+ defineCurve("c2tnb191v3", X9ObjectIdentifiers.c2tnb191v3, c2tnb191v3);
+ defineCurve("c2pnb208w1", X9ObjectIdentifiers.c2pnb208w1, c2pnb208w1);
+ defineCurve("c2tnb239v1", X9ObjectIdentifiers.c2tnb239v1, c2tnb239v1);
+ defineCurve("c2tnb239v2", X9ObjectIdentifiers.c2tnb239v2, c2tnb239v2);
+ defineCurve("c2tnb239v3", X9ObjectIdentifiers.c2tnb239v3, c2tnb239v3);
+ defineCurve("c2pnb272w1", X9ObjectIdentifiers.c2pnb272w1, c2pnb272w1);
+ defineCurve("c2pnb304w1", X9ObjectIdentifiers.c2pnb304w1, c2pnb304w1);
+ defineCurve("c2tnb359v1", X9ObjectIdentifiers.c2tnb359v1, c2tnb359v1);
+ defineCurve("c2pnb368w1", X9ObjectIdentifiers.c2pnb368w1, c2pnb368w1);
+ defineCurve("c2tnb431r1", X9ObjectIdentifiers.c2tnb431r1, c2tnb431r1);
+ }
+
+ public static X9ECParameters getByName(
+ String name)
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)objIds.get(Strings.toLowerCase(name));
+
+ if (oid != null)
+ {
+ return getByOID(oid);
+ }
+
+ return null;
+ }
+
+ /**
+ * return the X9ECParameters object for the named curve represented by
+ * the passed in object identifier. Null if the curve isn't present.
+ *
+ * @param oid an object identifier representing a named curve, if present.
+ */
+ public static X9ECParameters getByOID(
+ ASN1ObjectIdentifier oid)
+ {
+ X9ECParametersHolder holder = (X9ECParametersHolder)curves.get(oid);
+
+ if (holder != null)
+ {
+ return holder.getParameters();
+ }
+
+ return null;
+ }
+
+ /**
+ * return the object identifier signified by the passed in name. Null
+ * if there is no object identifier associated with name.
+ *
+ * @return the object identifier associated with name, if present.
+ */
+ public static ASN1ObjectIdentifier getOID(
+ String name)
+ {
+ return (ASN1ObjectIdentifier)objIds.get(Strings.toLowerCase(name));
+ }
+
+ /**
+ * return the named curve name represented by the given object identifier.
+ */
+ public static String getName(
+ ASN1ObjectIdentifier oid)
+ {
+ return (String)names.get(oid);
+ }
+
+ /**
+ * returns an enumeration containing the name strings for curves
+ * contained in this structure.
+ */
+ public static Enumeration getNames()
+ {
+ return objIds.keys();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x9/X962Parameters.java b/core/src/main/java/org/spongycastle/asn1/x9/X962Parameters.java
new file mode 100644
index 00000000..7c95793f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x9/X962Parameters.java
@@ -0,0 +1,86 @@
+package org.spongycastle.asn1.x9;
+
+import org.spongycastle.asn1.ASN1Choice;
+import org.spongycastle.asn1.ASN1Null;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+
+public class X962Parameters
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private ASN1Primitive params = null;
+
+ public static X962Parameters getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof X962Parameters)
+ {
+ return (X962Parameters)obj;
+ }
+
+ if (obj instanceof ASN1Primitive)
+ {
+ return new X962Parameters((ASN1Primitive)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance()");
+ }
+
+ public static X962Parameters getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject()); // must be explicitly tagged
+ }
+
+ public X962Parameters(
+ X9ECParameters ecParameters)
+ {
+ this.params = ecParameters.toASN1Primitive();
+ }
+
+ public X962Parameters(
+ ASN1ObjectIdentifier namedCurve)
+ {
+ this.params = namedCurve;
+ }
+
+ public X962Parameters(
+ ASN1Primitive obj)
+ {
+ this.params = obj;
+ }
+
+ public boolean isNamedCurve()
+ {
+ return (params instanceof ASN1ObjectIdentifier);
+ }
+
+ public boolean isImplicitlyCA()
+ {
+ return (params instanceof ASN1Null);
+ }
+
+ public ASN1Primitive getParameters()
+ {
+ return params;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * Parameters ::= CHOICE {
+ * ecParameters ECParameters,
+ * namedCurve CURVES.&amp;id({CurveNames}),
+ * implicitlyCA NULL
+ * }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return (ASN1Primitive)params;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x9/X9Curve.java b/core/src/main/java/org/spongycastle/asn1/x9/X9Curve.java
new file mode 100644
index 00000000..f2d2976c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x9/X9Curve.java
@@ -0,0 +1,163 @@
+package org.spongycastle.asn1.x9;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.math.ec.ECAlgorithms;
+import org.spongycastle.math.ec.ECCurve;
+
+/**
+ * ASN.1 def for Elliptic-Curve Curve structure. See
+ * X9.62, for further details.
+ */
+public class X9Curve
+ extends ASN1Object
+ implements X9ObjectIdentifiers
+{
+ private ECCurve curve;
+ private byte[] seed;
+ private ASN1ObjectIdentifier fieldIdentifier = null;
+
+ public X9Curve(
+ ECCurve curve)
+ {
+ this.curve = curve;
+ this.seed = null;
+ setFieldIdentifier();
+ }
+
+ public X9Curve(
+ ECCurve curve,
+ byte[] seed)
+ {
+ this.curve = curve;
+ this.seed = seed;
+ setFieldIdentifier();
+ }
+
+ public X9Curve(
+ X9FieldID fieldID,
+ ASN1Sequence seq)
+ {
+ // TODO Is it possible to get the order(n) and cofactor(h) too?
+
+ fieldIdentifier = fieldID.getIdentifier();
+ if (fieldIdentifier.equals(prime_field))
+ {
+ BigInteger p = ((ASN1Integer)fieldID.getParameters()).getValue();
+ X9FieldElement x9A = new X9FieldElement(p, (ASN1OctetString)seq.getObjectAt(0));
+ X9FieldElement x9B = new X9FieldElement(p, (ASN1OctetString)seq.getObjectAt(1));
+ curve = new ECCurve.Fp(p, x9A.getValue().toBigInteger(), x9B.getValue().toBigInteger());
+ }
+ else if (fieldIdentifier.equals(characteristic_two_field))
+ {
+ // Characteristic two field
+ ASN1Sequence parameters = ASN1Sequence.getInstance(fieldID.getParameters());
+ int m = ((ASN1Integer)parameters.getObjectAt(0)).getValue().
+ intValue();
+ ASN1ObjectIdentifier representation
+ = (ASN1ObjectIdentifier)parameters.getObjectAt(1);
+
+ int k1 = 0;
+ int k2 = 0;
+ int k3 = 0;
+
+ if (representation.equals(tpBasis))
+ {
+ // Trinomial basis representation
+ k1 = ASN1Integer.getInstance(parameters.getObjectAt(2)).getValue().intValue();
+ }
+ else if (representation.equals(ppBasis))
+ {
+ // Pentanomial basis representation
+ ASN1Sequence pentanomial = ASN1Sequence.getInstance(parameters.getObjectAt(2));
+ k1 = ASN1Integer.getInstance(pentanomial.getObjectAt(0)).getValue().intValue();
+ k2 = ASN1Integer.getInstance(pentanomial.getObjectAt(1)).getValue().intValue();
+ k3 = ASN1Integer.getInstance(pentanomial.getObjectAt(2)).getValue().intValue();
+ }
+ else
+ {
+ throw new IllegalArgumentException("This type of EC basis is not implemented");
+ }
+ X9FieldElement x9A = new X9FieldElement(m, k1, k2, k3, (ASN1OctetString)seq.getObjectAt(0));
+ X9FieldElement x9B = new X9FieldElement(m, k1, k2, k3, (ASN1OctetString)seq.getObjectAt(1));
+ curve = new ECCurve.F2m(m, k1, k2, k3, x9A.getValue().toBigInteger(), x9B.getValue().toBigInteger());
+ }
+ else
+ {
+ throw new IllegalArgumentException("This type of ECCurve is not implemented");
+ }
+
+ if (seq.size() == 3)
+ {
+ seed = ((DERBitString)seq.getObjectAt(2)).getBytes();
+ }
+ }
+
+ private void setFieldIdentifier()
+ {
+ if (ECAlgorithms.isFpCurve(curve))
+ {
+ fieldIdentifier = prime_field;
+ }
+ else if (ECAlgorithms.isF2mCurve(curve))
+ {
+ fieldIdentifier = characteristic_two_field;
+ }
+ else
+ {
+ throw new IllegalArgumentException("This type of ECCurve is not implemented");
+ }
+ }
+
+ public ECCurve getCurve()
+ {
+ return curve;
+ }
+
+ public byte[] getSeed()
+ {
+ return seed;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * Curve ::= SEQUENCE {
+ * a FieldElement,
+ * b FieldElement,
+ * seed BIT STRING OPTIONAL
+ * }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (fieldIdentifier.equals(prime_field))
+ {
+ v.add(new X9FieldElement(curve.getA()).toASN1Primitive());
+ v.add(new X9FieldElement(curve.getB()).toASN1Primitive());
+ }
+ else if (fieldIdentifier.equals(characteristic_two_field))
+ {
+ v.add(new X9FieldElement(curve.getA()).toASN1Primitive());
+ v.add(new X9FieldElement(curve.getB()).toASN1Primitive());
+ }
+
+ if (seed != null)
+ {
+ v.add(new DERBitString(seed));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x9/X9ECParameters.java b/core/src/main/java/org/spongycastle/asn1/x9/X9ECParameters.java
new file mode 100644
index 00000000..e0a926f2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x9/X9ECParameters.java
@@ -0,0 +1,200 @@
+package org.spongycastle.asn1.x9;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.math.ec.ECAlgorithms;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.field.PolynomialExtensionField;
+
+/**
+ * ASN.1 def for Elliptic-Curve ECParameters structure. See
+ * X9.62, for further details.
+ */
+public class X9ECParameters
+ extends ASN1Object
+ implements X9ObjectIdentifiers
+{
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ private X9FieldID fieldID;
+ private ECCurve curve;
+ private ECPoint g;
+ private BigInteger n;
+ private BigInteger h;
+ private byte[] seed;
+
+ private X9ECParameters(
+ ASN1Sequence seq)
+ {
+ if (!(seq.getObjectAt(0) instanceof ASN1Integer)
+ || !((ASN1Integer)seq.getObjectAt(0)).getValue().equals(ONE))
+ {
+ throw new IllegalArgumentException("bad version in X9ECParameters");
+ }
+
+ X9Curve x9c = new X9Curve(
+ X9FieldID.getInstance(seq.getObjectAt(1)),
+ ASN1Sequence.getInstance(seq.getObjectAt(2)));
+
+ this.curve = x9c.getCurve();
+ 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();
+
+ if (seq.size() == 6)
+ {
+ this.h = ((ASN1Integer)seq.getObjectAt(5)).getValue();
+ }
+ }
+
+ public static X9ECParameters getInstance(Object obj)
+ {
+ if (obj instanceof X9ECParameters)
+ {
+ return (X9ECParameters)obj;
+ }
+
+ if (obj != null)
+ {
+ return new X9ECParameters(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public X9ECParameters(
+ ECCurve curve,
+ ECPoint g,
+ BigInteger n)
+ {
+ this(curve, g, n, ONE, null);
+ }
+
+ public X9ECParameters(
+ ECCurve curve,
+ ECPoint g,
+ BigInteger n,
+ BigInteger h)
+ {
+ this(curve, g, n, h, null);
+ }
+
+ public X9ECParameters(
+ ECCurve curve,
+ ECPoint g,
+ BigInteger n,
+ BigInteger h,
+ byte[] seed)
+ {
+ this.curve = curve;
+ this.g = g.normalize();
+ this.n = n;
+ this.h = h;
+ this.seed = seed;
+
+ if (ECAlgorithms.isFpCurve(curve))
+ {
+ this.fieldID = new X9FieldID(curve.getField().getCharacteristic());
+ }
+ else if (ECAlgorithms.isF2mCurve(curve))
+ {
+ PolynomialExtensionField field = (PolynomialExtensionField)curve.getField();
+ int[] exponents = field.getMinimalPolynomial().getExponentsPresent();
+ if (exponents.length == 3)
+ {
+ this.fieldID = new X9FieldID(exponents[2], exponents[1]);
+ }
+ else if (exponents.length == 5)
+ {
+ this.fieldID = new X9FieldID(exponents[4], exponents[1], exponents[2], exponents[3]);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Only trinomial and pentomial curves are supported");
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("'curve' is of an unsupported type");
+ }
+ }
+
+ public ECCurve getCurve()
+ {
+ return curve;
+ }
+
+ public ECPoint getG()
+ {
+ return g;
+ }
+
+ public BigInteger getN()
+ {
+ return n;
+ }
+
+ public BigInteger getH()
+ {
+ if (h == null)
+ {
+ return ONE; // TODO - this should be calculated, it will cause issues with custom curves.
+ }
+
+ return h;
+ }
+
+ public byte[] getSeed()
+ {
+ return seed;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * ECParameters ::= SEQUENCE {
+ * version INTEGER { ecpVer1(1) } (ecpVer1),
+ * fieldID FieldID {{FieldTypes}},
+ * curve X9Curve,
+ * base X9ECPoint,
+ * order INTEGER,
+ * cofactor INTEGER OPTIONAL
+ * }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(1));
+ v.add(fieldID);
+ v.add(new X9Curve(curve, seed));
+ v.add(new X9ECPoint(g));
+ v.add(new ASN1Integer(n));
+
+ if (h != null)
+ {
+ v.add(new ASN1Integer(h));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x9/X9ECParametersHolder.java b/core/src/main/java/org/spongycastle/asn1/x9/X9ECParametersHolder.java
new file mode 100644
index 00000000..50e4f1e1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x9/X9ECParametersHolder.java
@@ -0,0 +1,18 @@
+package org.spongycastle.asn1.x9;
+
+public abstract class X9ECParametersHolder
+{
+ private X9ECParameters params;
+
+ public X9ECParameters getParameters()
+ {
+ if (params == null)
+ {
+ params = createParameters();
+ }
+
+ return params;
+ }
+
+ protected abstract X9ECParameters createParameters();
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x9/X9ECPoint.java b/core/src/main/java/org/spongycastle/asn1/x9/X9ECPoint.java
new file mode 100644
index 00000000..d984bcd4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x9/X9ECPoint.java
@@ -0,0 +1,48 @@
+package org.spongycastle.asn1.x9;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECPoint;
+
+/**
+ * class for describing an ECPoint as a DER object.
+ */
+public class X9ECPoint
+ extends ASN1Object
+{
+ ECPoint p;
+
+ public X9ECPoint(
+ ECPoint p)
+ {
+ this.p = p.normalize();
+ }
+
+ public X9ECPoint(
+ ECCurve c,
+ ASN1OctetString s)
+ {
+ this.p = c.decodePoint(s.getOctets());
+ }
+
+ public ECPoint getPoint()
+ {
+ return p;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * ECPoint ::= OCTET STRING
+ * </pre>
+ * <p>
+ * Octet string produced using ECPoint.getEncoded().
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DEROctetString(p.getEncoded());
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x9/X9FieldElement.java b/core/src/main/java/org/spongycastle/asn1/x9/X9FieldElement.java
new file mode 100644
index 00000000..dd5b4dff
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x9/X9FieldElement.java
@@ -0,0 +1,64 @@
+package org.spongycastle.asn1.x9;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.math.ec.ECFieldElement;
+
+/**
+ * class for processing an FieldElement as a DER object.
+ */
+public class X9FieldElement
+ extends ASN1Object
+{
+ protected ECFieldElement f;
+
+ private static X9IntegerConverter converter = new X9IntegerConverter();
+
+ public X9FieldElement(ECFieldElement f)
+ {
+ this.f = f;
+ }
+
+ public X9FieldElement(BigInteger p, ASN1OctetString s)
+ {
+ this(new ECFieldElement.Fp(p, new BigInteger(1, s.getOctets())));
+ }
+
+ public X9FieldElement(int m, int k1, int k2, int k3, ASN1OctetString s)
+ {
+ this(new ECFieldElement.F2m(m, k1, k2, k3, new BigInteger(1, s.getOctets())));
+ }
+
+ public ECFieldElement getValue()
+ {
+ return f;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * FieldElement ::= OCTET STRING
+ * </pre>
+ * <p>
+ * <ol>
+ * <li> if <i>q</i> is an odd prime then the field element is
+ * processed as an Integer and converted to an octet string
+ * according to x 9.62 4.3.1.</li>
+ * <li> if <i>q</i> is 2<sup>m</sup> then the bit string
+ * contained in the field element is converted into an octet
+ * string with the same ordering padded at the front if necessary.
+ * </li>
+ * </ol>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ int byteCount = converter.getByteLength(f);
+ byte[] paddedBigInteger = converter.integerToBytes(f.toBigInteger(), byteCount);
+
+ return new DEROctetString(paddedBigInteger);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x9/X9FieldID.java b/core/src/main/java/org/spongycastle/asn1/x9/X9FieldID.java
new file mode 100644
index 00000000..831fc0b3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x9/X9FieldID.java
@@ -0,0 +1,148 @@
+package org.spongycastle.asn1.x9;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+
+/**
+ * ASN.1 def for Elliptic-Curve Field ID structure. See
+ * X9.62, for further details.
+ */
+public class X9FieldID
+ extends ASN1Object
+ implements X9ObjectIdentifiers
+{
+ private ASN1ObjectIdentifier id;
+ private ASN1Primitive parameters;
+
+ /**
+ * Constructor for elliptic curves over prime fields
+ * <code>F<sub>2</sub></code>.
+ * @param primeP The prime <code>p</code> defining the prime field.
+ */
+ public X9FieldID(BigInteger primeP)
+ {
+ this.id = prime_field;
+ this.parameters = new ASN1Integer(primeP);
+ }
+
+ /**
+ * Constructor for elliptic curves over binary fields
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param m The exponent <code>m</code> of
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
+ * x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.
+ */
+ public X9FieldID(int m, int k1)
+ {
+ this(m, k1, 0, 0);
+ }
+
+ /**
+ * Constructor for elliptic curves over binary fields
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param m The exponent <code>m</code> of
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.
+ * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.
+ * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>..
+ */
+ public X9FieldID(int m, int k1, int k2, int k3)
+ {
+ this.id = characteristic_two_field;
+ ASN1EncodableVector fieldIdParams = new ASN1EncodableVector();
+ fieldIdParams.add(new ASN1Integer(m));
+
+ if (k2 == 0)
+ {
+ if (k3 != 0)
+ {
+ throw new IllegalArgumentException("inconsistent k values");
+ }
+
+ fieldIdParams.add(tpBasis);
+ fieldIdParams.add(new ASN1Integer(k1));
+ }
+ else
+ {
+ if (k2 <= k1 || k3 <= k2)
+ {
+ throw new IllegalArgumentException("inconsistent k values");
+ }
+
+ fieldIdParams.add(ppBasis);
+ ASN1EncodableVector pentanomialParams = new ASN1EncodableVector();
+ pentanomialParams.add(new ASN1Integer(k1));
+ pentanomialParams.add(new ASN1Integer(k2));
+ pentanomialParams.add(new ASN1Integer(k3));
+ fieldIdParams.add(new DERSequence(pentanomialParams));
+ }
+
+ this.parameters = new DERSequence(fieldIdParams);
+ }
+
+ private X9FieldID(
+ ASN1Sequence seq)
+ {
+ 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()
+ {
+ return id;
+ }
+
+ public ASN1Primitive getParameters()
+ {
+ return parameters;
+ }
+
+ /**
+ * Produce a DER encoding of the following structure.
+ * <pre>
+ * FieldID ::= SEQUENCE {
+ * fieldType FIELD-ID.&amp;id({IOSet}),
+ * parameters FIELD-ID.&amp;Type({IOSet}{&#64;fieldType})
+ * }
+ * </pre>
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(this.id);
+ v.add(this.parameters);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x9/X9IntegerConverter.java b/core/src/main/java/org/spongycastle/asn1/x9/X9IntegerConverter.java
new file mode 100644
index 00000000..66dcc59b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x9/X9IntegerConverter.java
@@ -0,0 +1,47 @@
+package org.spongycastle.asn1.x9;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+
+public class X9IntegerConverter
+{
+ public int getByteLength(
+ ECCurve c)
+ {
+ return (c.getFieldSize() + 7) / 8;
+ }
+
+ public int getByteLength(
+ ECFieldElement fe)
+ {
+ return (fe.getFieldSize() + 7) / 8;
+ }
+
+ public byte[] integerToBytes(
+ BigInteger s,
+ int qLength)
+ {
+ byte[] bytes = s.toByteArray();
+
+ if (qLength < bytes.length)
+ {
+ byte[] tmp = new byte[qLength];
+
+ System.arraycopy(bytes, bytes.length - tmp.length, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+ else if (qLength > bytes.length)
+ {
+ byte[] tmp = new byte[qLength];
+
+ System.arraycopy(bytes, 0, tmp, tmp.length - bytes.length, bytes.length);
+
+ return tmp;
+ }
+
+ return bytes;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/asn1/x9/X9ObjectIdentifiers.java b/core/src/main/java/org/spongycastle/asn1/x9/X9ObjectIdentifiers.java
new file mode 100644
index 00000000..1b67cb71
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/asn1/x9/X9ObjectIdentifiers.java
@@ -0,0 +1,207 @@
+package org.spongycastle.asn1.x9;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+
+/**
+ *
+ * X9.62
+ * <pre>
+ * ansi-X9-62 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+ * us(840) ansi-x962(10045) }
+ * </pre>
+ */
+public interface X9ObjectIdentifiers
+{
+ /** 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");
+
+ /** 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 base
+ * <p>
+ * OID: 1.2.840.10045.1
+ */
+ static final ASN1ObjectIdentifier ellipticCurve = ansi_X9_62.branch("3");
+
+ /**
+ * 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 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
+ * <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");
+
+ /**
+ * <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
+ */
+ static final ASN1ObjectIdentifier id_dsa_with_sha1 = new ASN1ObjectIdentifier("1.2.840.10040.4.3");
+
+ /**
+ * X9.63 - Signature Specification
+ * <p>
+ * Base OID: 1.3.133.16.840.63.0
+ */
+ static final ASN1ObjectIdentifier x9_63_scheme = new ASN1ObjectIdentifier("1.3.133.16.840.63.0");
+ /** 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
+ */
+
+ static final ASN1ObjectIdentifier ansi_X9_42 = new ASN1ObjectIdentifier("1.2.840.10046");
+
+ /**
+ * 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/core/src/main/java/org/spongycastle/crypto/AsymmetricBlockCipher.java b/core/src/main/java/org/spongycastle/crypto/AsymmetricBlockCipher.java
new file mode 100644
index 00000000..a026a69a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/AsymmetricBlockCipher.java
@@ -0,0 +1,45 @@
+package org.spongycastle.crypto;
+
+
+/**
+ * base interface that a public/private key block cipher needs
+ * to conform to.
+ */
+public interface AsymmetricBlockCipher
+{
+ /**
+ * initialise the cipher.
+ *
+ * @param forEncryption if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param param the key and other data required by the cipher.
+ */
+ public void init(boolean forEncryption, CipherParameters param);
+
+ /**
+ * returns the largest size an input block can be.
+ *
+ * @return maximum size for an input block.
+ */
+ public int getInputBlockSize();
+
+ /**
+ * returns the maximum size of the block produced by this cipher.
+ *
+ * @return maximum size of the output block produced by the cipher.
+ */
+ public int getOutputBlockSize();
+
+ /**
+ * process the block of len bytes stored in in from offset inOff.
+ *
+ * @param in the input data
+ * @param inOff offset into the in array where the data starts
+ * @param len the length of the block to be processed.
+ * @return the resulting byte array of the encryption/decryption process.
+ * @exception InvalidCipherTextException data decrypts improperly.
+ * @exception DataLengthException the input data is too large for the cipher.
+ */
+ public byte[] processBlock(byte[] in, int inOff, int len)
+ throws InvalidCipherTextException;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/AsymmetricCipherKeyPair.java b/core/src/main/java/org/spongycastle/crypto/AsymmetricCipherKeyPair.java
new file mode 100644
index 00000000..cc8fa1a5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/AsymmetricCipherKeyPair.java
@@ -0,0 +1,61 @@
+package org.spongycastle.crypto;
+
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+
+/**
+ * a holding class for public/private parameter pairs.
+ */
+public class AsymmetricCipherKeyPair
+{
+ private AsymmetricKeyParameter publicParam;
+ private AsymmetricKeyParameter privateParam;
+
+ /**
+ * basic constructor.
+ *
+ * @param publicParam a public key parameters object.
+ * @param privateParam the corresponding private key parameters.
+ */
+ public AsymmetricCipherKeyPair(
+ AsymmetricKeyParameter publicParam,
+ AsymmetricKeyParameter privateParam)
+ {
+ this.publicParam = publicParam;
+ this.privateParam = privateParam;
+ }
+
+ /**
+ * basic constructor.
+ *
+ * @param publicParam a public key parameters object.
+ * @param privateParam the corresponding private key parameters.
+ * @deprecated use AsymmetricKeyParameter
+ */
+ public AsymmetricCipherKeyPair(
+ CipherParameters publicParam,
+ CipherParameters privateParam)
+ {
+ this.publicParam = (AsymmetricKeyParameter)publicParam;
+ this.privateParam = (AsymmetricKeyParameter)privateParam;
+ }
+
+ /**
+ * return the public key parameters.
+ *
+ * @return the public key parameters.
+ */
+ public AsymmetricKeyParameter getPublic()
+ {
+ return publicParam;
+ }
+
+ /**
+ * return the private key parameters.
+ *
+ * @return the private key parameters.
+ */
+ public AsymmetricKeyParameter getPrivate()
+ {
+ return privateParam;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/AsymmetricCipherKeyPairGenerator.java b/core/src/main/java/org/spongycastle/crypto/AsymmetricCipherKeyPairGenerator.java
new file mode 100644
index 00000000..7dad90fd
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/AsymmetricCipherKeyPairGenerator.java
@@ -0,0 +1,22 @@
+package org.spongycastle.crypto;
+
+/**
+ * interface that a public/private key pair generator should conform to.
+ */
+public interface AsymmetricCipherKeyPairGenerator
+{
+ /**
+ * intialise the key pair generator.
+ *
+ * @param param the parameters the key pair is to be initialised with.
+ */
+ public void init(KeyGenerationParameters param);
+
+ /**
+ * return an AsymmetricCipherKeyPair containing the generated keys.
+ *
+ * @return an AsymmetricCipherKeyPair containing the generated keys.
+ */
+ public AsymmetricCipherKeyPair generateKeyPair();
+}
+
diff --git a/core/src/main/java/org/spongycastle/crypto/BasicAgreement.java b/core/src/main/java/org/spongycastle/crypto/BasicAgreement.java
new file mode 100644
index 00000000..e6e003c6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/BasicAgreement.java
@@ -0,0 +1,26 @@
+package org.spongycastle.crypto;
+
+import java.math.BigInteger;
+
+/**
+ * The basic interface that basic Diffie-Hellman implementations
+ * conforms to.
+ */
+public interface BasicAgreement
+{
+ /**
+ * initialise the agreement engine.
+ */
+ void init(CipherParameters param);
+
+ /**
+ * return the field size for the agreement algorithm in bytes.
+ */
+ int getFieldSize();
+
+ /**
+ * given a public key from a given party calculate the next
+ * message in the agreement sequence.
+ */
+ BigInteger calculateAgreement(CipherParameters pubKey);
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/BlockCipher.java b/core/src/main/java/org/spongycastle/crypto/BlockCipher.java
new file mode 100644
index 00000000..a7d0573a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/BlockCipher.java
@@ -0,0 +1,56 @@
+package org.spongycastle.crypto;
+
+
+/**
+ * Block cipher engines are expected to conform to this interface.
+ */
+public interface BlockCipher
+{
+ /**
+ * Initialise the cipher.
+ *
+ * @param forEncryption if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException;
+
+ /**
+ * Return the name of the algorithm the cipher implements.
+ *
+ * @return the name of the algorithm the cipher implements.
+ */
+ public String getAlgorithmName();
+
+ /**
+ * Return the block size for this cipher (in bytes).
+ *
+ * @return the block size for this cipher in bytes.
+ */
+ public int getBlockSize();
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException;
+
+ /**
+ * Reset the cipher. After resetting the cipher is in the same state
+ * as it was after the last init (if there was one).
+ */
+ public void reset();
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/BufferedAsymmetricBlockCipher.java b/core/src/main/java/org/spongycastle/crypto/BufferedAsymmetricBlockCipher.java
new file mode 100644
index 00000000..9cefae14
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/BufferedAsymmetricBlockCipher.java
@@ -0,0 +1,171 @@
+package org.spongycastle.crypto;
+
+/**
+ * a buffer wrapper for an asymmetric block cipher, allowing input
+ * to be accumulated in a piecemeal fashion until final processing.
+ */
+public class BufferedAsymmetricBlockCipher
+{
+ protected byte[] buf;
+ protected int bufOff;
+
+ private final AsymmetricBlockCipher cipher;
+
+ /**
+ * base constructor.
+ *
+ * @param cipher the cipher this buffering object wraps.
+ */
+ public BufferedAsymmetricBlockCipher(
+ AsymmetricBlockCipher cipher)
+ {
+ this.cipher = cipher;
+ }
+
+ /**
+ * return the underlying cipher for the buffer.
+ *
+ * @return the underlying cipher for the buffer.
+ */
+ public AsymmetricBlockCipher getUnderlyingCipher()
+ {
+ return cipher;
+ }
+
+ /**
+ * return the amount of data sitting in the buffer.
+ *
+ * @return the amount of data sitting in the buffer.
+ */
+ public int getBufferPosition()
+ {
+ return bufOff;
+ }
+
+ /**
+ * initialise the buffer and the underlying cipher.
+ *
+ * @param forEncryption if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ reset();
+
+ cipher.init(forEncryption, params);
+
+ //
+ // we allow for an extra byte where people are using their own padding
+ // mechanisms on a raw cipher.
+ //
+ buf = new byte[cipher.getInputBlockSize() + (forEncryption ? 1 : 0)];
+ bufOff = 0;
+ }
+
+ /**
+ * returns the largest size an input block can be.
+ *
+ * @return maximum size for an input block.
+ */
+ public int getInputBlockSize()
+ {
+ return cipher.getInputBlockSize();
+ }
+
+ /**
+ * returns the maximum size of the block produced by this cipher.
+ *
+ * @return maximum size of the output block produced by the cipher.
+ */
+ public int getOutputBlockSize()
+ {
+ return cipher.getOutputBlockSize();
+ }
+
+ /**
+ * add another byte for processing.
+ *
+ * @param in the input byte.
+ */
+ public void processByte(
+ byte in)
+ {
+ if (bufOff >= buf.length)
+ {
+ throw new DataLengthException("attempt to process message too long for cipher");
+ }
+
+ buf[bufOff++] = in;
+ }
+
+ /**
+ * add len bytes to the buffer for processing.
+ *
+ * @param in the input data
+ * @param inOff offset into the in array where the data starts
+ * @param len the length of the block to be processed.
+ */
+ public void processBytes(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ if (len == 0)
+ {
+ return;
+ }
+
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ if (bufOff + len > buf.length)
+ {
+ throw new DataLengthException("attempt to process message too long for cipher");
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+ bufOff += len;
+ }
+
+ /**
+ * process the contents of the buffer using the underlying
+ * cipher.
+ *
+ * @return the result of the encryption/decryption process on the
+ * buffer.
+ * @exception InvalidCipherTextException if we are given a garbage block.
+ */
+ public byte[] doFinal()
+ throws InvalidCipherTextException
+ {
+ byte[] out = cipher.processBlock(buf, 0, bufOff);
+
+ reset();
+
+ return out;
+ }
+
+ /**
+ * Reset the buffer and the underlying cipher.
+ */
+ public void reset()
+ {
+ /*
+ * clean the buffer.
+ */
+ if (buf != null)
+ {
+ for (int i = 0; i < buf.length; i++)
+ {
+ buf[i] = 0;
+ }
+ }
+
+ bufOff = 0;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/BufferedBlockCipher.java b/core/src/main/java/org/spongycastle/crypto/BufferedBlockCipher.java
new file mode 100644
index 00000000..28e5a5b9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/BufferedBlockCipher.java
@@ -0,0 +1,313 @@
+package org.spongycastle.crypto;
+
+
+/**
+ * A wrapper class that allows block ciphers to be used to process data in
+ * a piecemeal fashion. The BufferedBlockCipher outputs a block only when the
+ * buffer is full and more data is being added, or on a doFinal.
+ * <p>
+ * Note: in the case where the underlying cipher is either a CFB cipher or an
+ * OFB one the last block may not be a multiple of the block size.
+ */
+public class BufferedBlockCipher
+{
+ protected byte[] buf;
+ protected int bufOff;
+
+ protected boolean forEncryption;
+ protected BlockCipher cipher;
+
+ protected boolean partialBlockOkay;
+ protected boolean pgpCFB;
+
+ /**
+ * constructor for subclasses
+ */
+ protected BufferedBlockCipher()
+ {
+ }
+
+ /**
+ * Create a buffered block cipher without padding.
+ *
+ * @param cipher the underlying block cipher this buffering object wraps.
+ */
+ public BufferedBlockCipher(
+ BlockCipher cipher)
+ {
+ this.cipher = cipher;
+
+ buf = new byte[cipher.getBlockSize()];
+ bufOff = 0;
+
+ //
+ // check if we can handle partial blocks on doFinal.
+ //
+ String name = cipher.getAlgorithmName();
+ int idx = name.indexOf('/') + 1;
+
+ pgpCFB = (idx > 0 && name.startsWith("PGP", idx));
+
+ if (pgpCFB || cipher instanceof StreamCipher)
+ {
+ partialBlockOkay = true;
+ }
+ else
+ {
+ partialBlockOkay = (idx > 0 && (name.startsWith("OpenPGP", idx)));
+ }
+ }
+
+ /**
+ * return the cipher this object wraps.
+ *
+ * @return the cipher this object wraps.
+ */
+ public BlockCipher getUnderlyingCipher()
+ {
+ return cipher;
+ }
+
+ /**
+ * initialise the cipher.
+ *
+ * @param forEncryption if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ this.forEncryption = forEncryption;
+
+ reset();
+
+ cipher.init(forEncryption, params);
+ }
+
+ /**
+ * return the blocksize for the underlying cipher.
+ *
+ * @return the blocksize for the underlying cipher.
+ */
+ public int getBlockSize()
+ {
+ return cipher.getBlockSize();
+ }
+
+ /**
+ * 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;
+
+ if (pgpCFB)
+ {
+ leftOver = total % buf.length - (cipher.getBlockSize() + 2);
+ }
+ else
+ {
+ leftOver = total % buf.length;
+ }
+
+ return total - leftOver;
+ }
+
+ /**
+ * return the size of the output buffer required for an update plus a
+ * doFinal with an input of 'length' bytes.
+ *
+ * @param length the length of the input.
+ * @return the space required to accommodate a call to update and doFinal
+ * with 'length' bytes of input.
+ */
+ public int getOutputSize(
+ int length)
+ {
+ // Note: Can assume partialBlockOkay is true for purposes of this calculation
+ return length + bufOff;
+ }
+
+ /**
+ * process a single byte, producing an output block if neccessary.
+ *
+ * @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 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;
+
+ buf[bufOff++] = in;
+
+ if (bufOff == buf.length)
+ {
+ resultLen = cipher.processBlock(buf, 0, out, outOff);
+ bufOff = 0;
+ }
+
+ 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 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 OutputLengthException("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);
+
+ bufOff = 0;
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > buf.length)
+ {
+ resultLen += cipher.processBlock(in, inOff, out, outOff + resultLen);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+
+ if (bufOff == buf.length)
+ {
+ resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen);
+ bufOff = 0;
+ }
+
+ 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 DataLengthException if there is insufficient space in out for
+ * the output, or the input is not block size aligned and should be.
+ * @exception IllegalStateException if the underlying cipher is not
+ * initialised.
+ * @exception InvalidCipherTextException if padding is expected and not found.
+ * @exception DataLengthException if the input is not block size
+ * aligned.
+ */
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException, InvalidCipherTextException
+ {
+ try
+ {
+ int resultLen = 0;
+
+ if (outOff + bufOff > out.length)
+ {
+ throw new OutputLengthException("output buffer too short for doFinal()");
+ }
+
+ if (bufOff != 0)
+ {
+ if (!partialBlockOkay)
+ {
+ throw new DataLengthException("data not block size aligned");
+ }
+
+ cipher.processBlock(buf, 0, buf, 0);
+ resultLen = bufOff;
+ bufOff = 0;
+ System.arraycopy(buf, 0, out, outOff, resultLen);
+ }
+
+ return resultLen;
+ }
+ finally
+ {
+ reset();
+ }
+ }
+
+ /**
+ * Reset the buffer and cipher. After resetting the object is in the same
+ * state as it was after the last init (if there was one).
+ */
+ public void reset()
+ {
+ //
+ // clean the buffer.
+ //
+ for (int i = 0; i < buf.length; i++)
+ {
+ buf[i] = 0;
+ }
+
+ bufOff = 0;
+
+ //
+ // reset the underlying cipher.
+ //
+ cipher.reset();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/CipherKeyGenerator.java b/core/src/main/java/org/spongycastle/crypto/CipherKeyGenerator.java
new file mode 100644
index 00000000..5377e739
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/CipherKeyGenerator.java
@@ -0,0 +1,38 @@
+package org.spongycastle.crypto;
+
+import java.security.SecureRandom;
+
+/**
+ * The base class for symmetric, or secret, cipher key generators.
+ */
+public class CipherKeyGenerator
+{
+ protected SecureRandom random;
+ protected int strength;
+
+ /**
+ * initialise the key generator.
+ *
+ * @param param the parameters to be used for key generation
+ */
+ public void init(
+ KeyGenerationParameters param)
+ {
+ this.random = param.getRandom();
+ this.strength = (param.getStrength() + 7) / 8;
+ }
+
+ /**
+ * generate a secret key.
+ *
+ * @return a byte array containing the key value.
+ */
+ public byte[] generateKey()
+ {
+ byte[] key = new byte[strength];
+
+ random.nextBytes(key);
+
+ return key;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/CipherParameters.java b/core/src/main/java/org/spongycastle/crypto/CipherParameters.java
new file mode 100644
index 00000000..5a9576bf
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/CipherParameters.java
@@ -0,0 +1,8 @@
+package org.spongycastle.crypto;
+
+/**
+ * all parameter classes implement this.
+ */
+public interface CipherParameters
+{
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/Commitment.java b/core/src/main/java/org/spongycastle/crypto/Commitment.java
new file mode 100644
index 00000000..9f5bcdf9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/Commitment.java
@@ -0,0 +1,42 @@
+package org.spongycastle.crypto;
+
+/**
+ * General holding class for a commitment.
+ */
+public class Commitment
+{
+ private final byte[] secret;
+ private final byte[] commitment;
+
+ /**
+ * Base constructor.
+ *
+ * @param secret an encoding of the secret required to reveal the commitment.
+ * @param commitment an encoding of the sealed commitment.
+ */
+ public Commitment(byte[] secret, byte[] commitment)
+ {
+ this.secret = secret;
+ this.commitment = commitment;
+ }
+
+ /**
+ * The secret required to reveal the commitment.
+ *
+ * @return an encoding of the secret associated with the commitment.
+ */
+ public byte[] getSecret()
+ {
+ return secret;
+ }
+
+ /**
+ * The sealed commitment.
+ *
+ * @return an encoding of the sealed commitment.
+ */
+ public byte[] getCommitment()
+ {
+ return commitment;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/Committer.java b/core/src/main/java/org/spongycastle/crypto/Committer.java
new file mode 100644
index 00000000..77748664
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/Committer.java
@@ -0,0 +1,24 @@
+package org.spongycastle.crypto;
+
+/**
+ * General interface fdr classes that produce and validate commitments.
+ */
+public interface Committer
+{
+ /**
+ * Generate a commitment for the passed in message.
+ *
+ * @param message the message to be committed to,
+ * @return a Commitment
+ */
+ Commitment commit(byte[] message);
+
+ /**
+ * Return true if the passed in commitment represents a commitment to the passed in maessage.
+ *
+ * @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.
+ */
+ boolean isRevealed(Commitment commitment, byte[] message);
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/CryptoException.java b/core/src/main/java/org/spongycastle/crypto/CryptoException.java
new file mode 100644
index 00000000..a33adf95
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/CryptoException.java
@@ -0,0 +1,48 @@
+package org.spongycastle.crypto;
+
+/**
+ * the foundation class for the hard exceptions thrown by the crypto packages.
+ */
+public class CryptoException
+ extends Exception
+{
+ private Throwable cause;
+
+ /**
+ * base constructor.
+ */
+ public CryptoException()
+ {
+ }
+
+ /**
+ * create a CryptoException with the given message.
+ *
+ * @param message the message to be carried with the exception.
+ */
+ public CryptoException(
+ String message)
+ {
+ super(message);
+ }
+
+ /**
+ * Create a CryptoException with the given message and underlying cause.
+ *
+ * @param message message describing exception.
+ * @param cause the throwable that was the underlying cause.
+ */
+ public CryptoException(
+ String message,
+ Throwable cause)
+ {
+ super(message);
+
+ this.cause = cause;
+ }
+
+ public Throwable getCause()
+ {
+ return cause;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/DSA.java b/core/src/main/java/org/spongycastle/crypto/DSA.java
new file mode 100644
index 00000000..7243ddd9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/DSA.java
@@ -0,0 +1,36 @@
+package org.spongycastle.crypto;
+
+import java.math.BigInteger;
+
+/**
+ * interface for classes implementing algorithms modeled similar to the Digital Signature Alorithm.
+ */
+public interface DSA
+{
+ /**
+ * initialise the signer for signature generation or signature
+ * verification.
+ *
+ * @param forSigning true if we are generating a signature, false
+ * otherwise.
+ * @param param key parameters for signature generation.
+ */
+ public void init(boolean forSigning, CipherParameters param);
+
+ /**
+ * sign the passed in message (usually the output of a hash function).
+ *
+ * @param message the message to be signed.
+ * @return two big integers representing the r and s values respectively.
+ */
+ public BigInteger[] generateSignature(byte[] message);
+
+ /**
+ * verify the message message against the signature values r and s.
+ *
+ * @param message the message that was supposed to have been signed.
+ * @param r the r signature value.
+ * @param s the s signature value.
+ */
+ public boolean verifySignature(byte[] message, BigInteger r, BigInteger s);
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/DataLengthException.java b/core/src/main/java/org/spongycastle/crypto/DataLengthException.java
new file mode 100644
index 00000000..c89e8bf1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/DataLengthException.java
@@ -0,0 +1,29 @@
+package org.spongycastle.crypto;
+
+/**
+ * this exception is thrown if a buffer that is meant to have output
+ * copied into it turns out to be too short, or if we've been given
+ * insufficient input. In general this exception will get thrown rather
+ * than an ArrayOutOfBounds exception.
+ */
+public class DataLengthException
+ extends RuntimeCryptoException
+{
+ /**
+ * base constructor.
+ */
+ public DataLengthException()
+ {
+ }
+
+ /**
+ * create a DataLengthException with the given message.
+ *
+ * @param message the message to be carried with the exception.
+ */
+ public DataLengthException(
+ String message)
+ {
+ super(message);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/DerivationFunction.java b/core/src/main/java/org/spongycastle/crypto/DerivationFunction.java
new file mode 100644
index 00000000..b8e913fd
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/DerivationFunction.java
@@ -0,0 +1,12 @@
+package org.spongycastle.crypto;
+
+/**
+ * base interface for general purpose byte derivation functions.
+ */
+public interface DerivationFunction
+{
+ public void init(DerivationParameters param);
+
+ public int generateBytes(byte[] out, int outOff, int len)
+ throws DataLengthException, IllegalArgumentException;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/DerivationParameters.java b/core/src/main/java/org/spongycastle/crypto/DerivationParameters.java
new file mode 100644
index 00000000..19b23ec6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/DerivationParameters.java
@@ -0,0 +1,8 @@
+package org.spongycastle.crypto;
+
+/**
+ * Parameters for key/byte stream derivation classes
+ */
+public interface DerivationParameters
+{
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/Digest.java b/core/src/main/java/org/spongycastle/crypto/Digest.java
new file mode 100644
index 00000000..33103b26
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/Digest.java
@@ -0,0 +1,51 @@
+package org.spongycastle.crypto;
+
+/**
+ * interface that a message digest conforms to.
+ */
+public interface Digest
+{
+ /**
+ * return the algorithm name
+ *
+ * @return the algorithm name
+ */
+ public String getAlgorithmName();
+
+ /**
+ * return the size, in bytes, of the digest produced by this message digest.
+ *
+ * @return the size, in bytes, of the digest produced by this message digest.
+ */
+ public int getDigestSize();
+
+ /**
+ * update the message digest with a single byte.
+ *
+ * @param in the input byte to be entered.
+ */
+ public void update(byte in);
+
+ /**
+ * update the message digest with a block of bytes.
+ *
+ * @param in the byte array containing the data.
+ * @param inOff the offset into the byte array where the data starts.
+ * @param len the length of the data.
+ */
+ public void update(byte[] in, int inOff, int len);
+
+ /**
+ * close the digest, producing the final digest value. The doFinal
+ * call leaves the digest reset.
+ *
+ * @param out the array the digest is to be copied into.
+ * @param outOff the offset into the out array the digest is to start at.
+ */
+ public int doFinal(byte[] out, int outOff);
+
+ /**
+ * reset the digest back to it's initial state.
+ */
+ public void reset();
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/DigestDerivationFunction.java b/core/src/main/java/org/spongycastle/crypto/DigestDerivationFunction.java
new file mode 100644
index 00000000..7ed0fe15
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/DigestDerivationFunction.java
@@ -0,0 +1,13 @@
+package org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/EphemeralKeyPair.java b/core/src/main/java/org/spongycastle/crypto/EphemeralKeyPair.java
new file mode 100644
index 00000000..042850c3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/EphemeralKeyPair.java
@@ -0,0 +1,23 @@
+package org.spongycastle.crypto;
+
+public class EphemeralKeyPair
+{
+ private AsymmetricCipherKeyPair keyPair;
+ private KeyEncoder publicKeyEncoder;
+
+ public EphemeralKeyPair(AsymmetricCipherKeyPair keyPair, KeyEncoder publicKeyEncoder)
+ {
+ this.keyPair = keyPair;
+ this.publicKeyEncoder = publicKeyEncoder;
+ }
+
+ public AsymmetricCipherKeyPair getKeyPair()
+ {
+ return keyPair;
+ }
+
+ public byte[] getEncodedPublicKey()
+ {
+ return publicKeyEncoder.getEncoded(keyPair.getPublic());
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/ExtendedDigest.java b/core/src/main/java/org/spongycastle/crypto/ExtendedDigest.java
new file mode 100644
index 00000000..7cc339f2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/ExtendedDigest.java
@@ -0,0 +1,13 @@
+package org.spongycastle.crypto;
+
+public interface ExtendedDigest
+ extends Digest
+{
+ /**
+ * Return the size in bytes of the internal buffer the digest applies it's compression
+ * function to.
+ *
+ * @return byte length of the digests internal buffer.
+ */
+ public int getByteLength();
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/InvalidCipherTextException.java b/core/src/main/java/org/spongycastle/crypto/InvalidCipherTextException.java
new file mode 100644
index 00000000..802683fc
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/InvalidCipherTextException.java
@@ -0,0 +1,40 @@
+package org.spongycastle.crypto;
+
+/**
+ * this exception is thrown whenever we find something we don't expect in a
+ * message.
+ */
+public class InvalidCipherTextException
+ extends CryptoException
+{
+ /**
+ * base constructor.
+ */
+ public InvalidCipherTextException()
+ {
+ }
+
+ /**
+ * create a InvalidCipherTextException with the given message.
+ *
+ * @param message the message to be carried with the exception.
+ */
+ public InvalidCipherTextException(
+ String message)
+ {
+ super(message);
+ }
+
+ /**
+ * create a InvalidCipherTextException with the given message.
+ *
+ * @param message the message to be carried with the exception.
+ * @param cause the root cause of the exception.
+ */
+ public InvalidCipherTextException(
+ String message,
+ Throwable cause)
+ {
+ super(message, cause);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/KeyEncapsulation.java b/core/src/main/java/org/spongycastle/crypto/KeyEncapsulation.java
new file mode 100755
index 00000000..1a53e790
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/KeyEncapsulation.java
@@ -0,0 +1,22 @@
+package org.spongycastle.crypto;
+
+/**
+ * The basic interface for key encapsulation mechanisms.
+ */
+public interface KeyEncapsulation
+{
+ /**
+ * Initialise the key encapsulation mechanism.
+ */
+ public void init(CipherParameters param);
+
+ /**
+ * Encapsulate a randomly generated session key.
+ */
+ public CipherParameters encrypt(byte[] out, int outOff, int keyLen);
+
+ /**
+ * Decapsulate an encapsulated session key.
+ */
+ public CipherParameters decrypt(byte[] in, int inOff, int inLen, int keyLen);
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/KeyEncoder.java b/core/src/main/java/org/spongycastle/crypto/KeyEncoder.java
new file mode 100644
index 00000000..b3cc1798
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/KeyEncoder.java
@@ -0,0 +1,8 @@
+package org.spongycastle.crypto;
+
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+
+public interface KeyEncoder
+{
+ byte[] getEncoded(AsymmetricKeyParameter keyParameter);
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/KeyGenerationParameters.java b/core/src/main/java/org/spongycastle/crypto/KeyGenerationParameters.java
new file mode 100644
index 00000000..853f9c13
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/KeyGenerationParameters.java
@@ -0,0 +1,48 @@
+package org.spongycastle.crypto;
+
+import java.security.SecureRandom;
+
+/**
+ * The base class for parameters to key generators.
+ */
+public class KeyGenerationParameters
+{
+ private SecureRandom random;
+ private int strength;
+
+ /**
+ * initialise the generator with a source of randomness
+ * and a strength (in bits).
+ *
+ * @param random the random byte source.
+ * @param strength the size, in bits, of the keys we want to produce.
+ */
+ public KeyGenerationParameters(
+ SecureRandom random,
+ int strength)
+ {
+ this.random = random;
+ this.strength = strength;
+ }
+
+ /**
+ * return the random source associated with this
+ * generator.
+ *
+ * @return the generators random source.
+ */
+ public SecureRandom getRandom()
+ {
+ return random;
+ }
+
+ /**
+ * return the bit strength for keys produced by this generator,
+ *
+ * @return the strength of the keys this generator produces (in bits).
+ */
+ public int getStrength()
+ {
+ return strength;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/KeyParser.java b/core/src/main/java/org/spongycastle/crypto/KeyParser.java
new file mode 100644
index 00000000..7992ff86
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/KeyParser.java
@@ -0,0 +1,12 @@
+package org.spongycastle.crypto;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+
+public interface KeyParser
+{
+ AsymmetricKeyParameter readKey(InputStream stream)
+ throws IOException;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/Mac.java b/core/src/main/java/org/spongycastle/crypto/Mac.java
new file mode 100644
index 00000000..8be61143
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/Mac.java
@@ -0,0 +1,71 @@
+package org.spongycastle.crypto;
+
+
+/**
+ * The base interface for implementations of message authentication codes (MACs).
+ */
+public interface Mac
+{
+ /**
+ * Initialise the MAC.
+ *
+ * @param params the key and other data required by the MAC.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(CipherParameters params)
+ throws IllegalArgumentException;
+
+ /**
+ * Return the name of the algorithm the MAC implements.
+ *
+ * @return the name of the algorithm the MAC implements.
+ */
+ public String getAlgorithmName();
+
+ /**
+ * Return the block size for this MAC (in bytes).
+ *
+ * @return the block size for this MAC in bytes.
+ */
+ public int getMacSize();
+
+ /**
+ * add a single byte to the mac for processing.
+ *
+ * @param in the byte to be processed.
+ * @exception IllegalStateException if the MAC is not initialised.
+ */
+ public void update(byte in)
+ throws IllegalStateException;
+
+ /**
+ * @param in the array containing the input.
+ * @param inOff the index in the array the data begins at.
+ * @param len the length of the input starting at inOff.
+ * @exception IllegalStateException if the MAC is not initialised.
+ * @exception DataLengthException if there isn't enough data in in.
+ */
+ public void update(byte[] in, int inOff, int len)
+ throws DataLengthException, IllegalStateException;
+
+ /**
+ * Compute the final stage of the MAC writing the output to the out
+ * parameter.
+ * <p>
+ * doFinal leaves the MAC in the same state it was after the last init.
+ *
+ * @param out the array the MAC is to be output to.
+ * @param outOff the offset into the out buffer the output is to start at.
+ * @exception DataLengthException if there isn't enough space in out.
+ * @exception IllegalStateException if the MAC is not initialised.
+ */
+ public int doFinal(byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException;
+
+ /**
+ * Reset the MAC. At the end of resetting the MAC should be in the
+ * in the same state it was after the last init (if there was one).
+ */
+ public void reset();
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/MacDerivationFunction.java b/core/src/main/java/org/spongycastle/crypto/MacDerivationFunction.java
new file mode 100644
index 00000000..0478e9a6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/MacDerivationFunction.java
@@ -0,0 +1,13 @@
+package org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/MaxBytesExceededException.java b/core/src/main/java/org/spongycastle/crypto/MaxBytesExceededException.java
new file mode 100644
index 00000000..b49f2661
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/MaxBytesExceededException.java
@@ -0,0 +1,27 @@
+package org.spongycastle.crypto;
+
+/**
+ * this exception is thrown whenever a cipher requires a change of key, iv
+ * or similar after x amount of bytes enciphered
+ */
+public class MaxBytesExceededException
+ extends RuntimeCryptoException
+{
+ /**
+ * base constructor.
+ */
+ public MaxBytesExceededException()
+ {
+ }
+
+ /**
+ * create an with the given message.
+ *
+ * @param message the message to be carried with the exception.
+ */
+ public MaxBytesExceededException(
+ String message)
+ {
+ super(message);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/OutputLengthException.java b/core/src/main/java/org/spongycastle/crypto/OutputLengthException.java
new file mode 100644
index 00000000..e1f23f31
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/OutputLengthException.java
@@ -0,0 +1,10 @@
+package org.spongycastle.crypto;
+
+public class OutputLengthException
+ extends DataLengthException
+{
+ public OutputLengthException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/PBEParametersGenerator.java b/core/src/main/java/org/spongycastle/crypto/PBEParametersGenerator.java
new file mode 100644
index 00000000..6788d14e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/PBEParametersGenerator.java
@@ -0,0 +1,171 @@
+package org.spongycastle.crypto;
+
+import org.spongycastle.util.Strings;
+
+/**
+ * super class for all Password Based Encryption (PBE) parameter generator classes.
+ */
+public abstract class PBEParametersGenerator
+{
+ protected byte[] password;
+ protected byte[] salt;
+ protected int iterationCount;
+
+ /**
+ * base constructor.
+ */
+ protected PBEParametersGenerator()
+ {
+ }
+
+ /**
+ * initialise the PBE generator.
+ *
+ * @param password the password converted into bytes (see below).
+ * @param salt the salt to be mixed with the password.
+ * @param iterationCount the number of iterations the "mixing" function
+ * is to be applied for.
+ */
+ public void init(
+ byte[] password,
+ byte[] salt,
+ int iterationCount)
+ {
+ this.password = password;
+ this.salt = salt;
+ this.iterationCount = iterationCount;
+ }
+
+ /**
+ * return the password byte array.
+ *
+ * @return the password byte array.
+ */
+ public byte[] getPassword()
+ {
+ return password;
+ }
+
+ /**
+ * return the salt byte array.
+ *
+ * @return the salt byte array.
+ */
+ public byte[] getSalt()
+ {
+ return salt;
+ }
+
+ /**
+ * return the iteration count.
+ *
+ * @return the iteration count.
+ */
+ public int getIterationCount()
+ {
+ return iterationCount;
+ }
+
+ /**
+ * generate derived parameters for a key of length keySize.
+ *
+ * @param keySize the length, in bits, of the key required.
+ * @return a parameters object representing a key.
+ */
+ public abstract CipherParameters generateDerivedParameters(int keySize);
+
+ /**
+ * generate derived parameters for a key of length keySize, and
+ * an initialisation vector (IV) of length ivSize.
+ *
+ * @param keySize the length, in bits, of the key required.
+ * @param ivSize the length, in bits, of the iv required.
+ * @return a parameters object representing a key and an IV.
+ */
+ public abstract CipherParameters generateDerivedParameters(int keySize, int ivSize);
+
+ /**
+ * generate derived parameters for a key of length keySize, specifically
+ * for use with a MAC.
+ *
+ * @param keySize the length, in bits, of the key required.
+ * @return a parameters object representing a key.
+ */
+ public abstract CipherParameters generateDerivedMacParameters(int keySize);
+
+ /**
+ * converts a password to a byte array according to the scheme in
+ * PKCS5 (ascii, no padding)
+ *
+ * @param password a character array representing the password.
+ * @return a byte array representing the password.
+ */
+ public static byte[] PKCS5PasswordToBytes(
+ char[] password)
+ {
+ if (password != null)
+ {
+ byte[] bytes = new byte[password.length];
+
+ for (int i = 0; i != bytes.length; i++)
+ {
+ bytes[i] = (byte)password[i];
+ }
+
+ return bytes;
+ }
+ else
+ {
+ return new byte[0];
+ }
+ }
+
+ /**
+ * converts a password to a byte array according to the scheme in
+ * PKCS5 (UTF-8, no padding)
+ *
+ * @param password a character array representing the password.
+ * @return a byte array representing the password.
+ */
+ public static byte[] PKCS5PasswordToUTF8Bytes(
+ char[] password)
+ {
+ if (password != null)
+ {
+ return Strings.toUTF8ByteArray(password);
+ }
+ else
+ {
+ return new byte[0];
+ }
+ }
+
+ /**
+ * converts a password to a byte array according to the scheme in
+ * PKCS12 (unicode, big endian, 2 zero pad bytes at the end).
+ *
+ * @param password a character array representing the password.
+ * @return a byte array representing the password.
+ */
+ public static byte[] PKCS12PasswordToBytes(
+ char[] password)
+ {
+ if (password != null && password.length > 0)
+ {
+ // +1 for extra 2 pad bytes.
+ byte[] bytes = new byte[(password.length + 1) * 2];
+
+ for (int i = 0; i != password.length; i ++)
+ {
+ bytes[i * 2] = (byte)(password[i] >>> 8);
+ bytes[i * 2 + 1] = (byte)password[i];
+ }
+
+ return bytes;
+ }
+ else
+ {
+ return new byte[0];
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/RuntimeCryptoException.java b/core/src/main/java/org/spongycastle/crypto/RuntimeCryptoException.java
new file mode 100644
index 00000000..4eeb18f4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/RuntimeCryptoException.java
@@ -0,0 +1,26 @@
+package org.spongycastle.crypto;
+
+/**
+ * the foundation class for the exceptions thrown by the crypto packages.
+ */
+public class RuntimeCryptoException
+ extends RuntimeException
+{
+ /**
+ * base constructor.
+ */
+ public RuntimeCryptoException()
+ {
+ }
+
+ /**
+ * create a RuntimeCryptoException with the given message.
+ *
+ * @param message the message to be carried with the exception.
+ */
+ public RuntimeCryptoException(
+ String message)
+ {
+ super(message);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/Signer.java b/core/src/main/java/org/spongycastle/crypto/Signer.java
new file mode 100644
index 00000000..503e1200
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/Signer.java
@@ -0,0 +1,43 @@
+package org.spongycastle.crypto;
+
+/**
+ * Generic signer interface for hash based and message recovery signers.
+ */
+public interface Signer
+{
+ /**
+ * Initialise the signer for signing or verification.
+ *
+ * @param forSigning true if for signing, false otherwise
+ * @param param necessary parameters.
+ */
+ public void init(boolean forSigning, CipherParameters param);
+
+ /**
+ * update the internal digest with the byte b
+ */
+ public void update(byte b);
+
+ /**
+ * update the internal digest with the byte array in
+ */
+ public void update(byte[] in, int off, int len);
+
+ /**
+ * generate a signature for the message we've been loaded with using
+ * the key we were initialised with.
+ */
+ public byte[] generateSignature()
+ throws CryptoException, DataLengthException;
+
+ /**
+ * return true if the internal state represents the signature described
+ * in the passed in array.
+ */
+ public boolean verifySignature(byte[] signature);
+
+ /**
+ * reset the internal state
+ */
+ public void reset();
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/SignerWithRecovery.java b/core/src/main/java/org/spongycastle/crypto/SignerWithRecovery.java
new file mode 100644
index 00000000..e7a39a66
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/SignerWithRecovery.java
@@ -0,0 +1,34 @@
+package org.spongycastle.crypto;
+
+/**
+ * Signer with message recovery.
+ */
+public interface SignerWithRecovery
+ extends Signer
+{
+ /**
+ * Returns true if the signer has recovered the full message as
+ * part of signature verification.
+ *
+ * @return true if full message recovered.
+ */
+ public boolean hasFullMessage();
+
+ /**
+ * Returns a reference to what message was recovered (if any).
+ *
+ * @return full/partial message, null if nothing.
+ */
+ public byte[] getRecoveredMessage();
+
+ /**
+ * Perform an update with the recovered message before adding any other data. This must
+ * be the first update method called, and calling it will result in the signer assuming
+ * that further calls to update will include message content past what is recoverable.
+ *
+ * @param signature the signature that we are in the process of verifying.
+ * @throws IllegalStateException
+ */
+ public void updateWithRecoveredMessage(byte[] signature)
+ throws InvalidCipherTextException;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/SkippingCipher.java b/core/src/main/java/org/spongycastle/crypto/SkippingCipher.java
new file mode 100644
index 00000000..653182cd
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/SkippingCipher.java
@@ -0,0 +1,31 @@
+package org.spongycastle.crypto;
+
+/**
+ * Ciphers producing a key stream which can be reset to particular points in the stream implement this.
+ */
+public interface SkippingCipher
+{
+ /**
+ * Skip numberOfBytes forwards, or backwards.
+ *
+ * @param numberOfBytes the number of bytes to skip (positive forward, negative backwards).
+ * @return the number of bytes actually skipped.
+ * @throws java.lang.IllegalArgumentException if numberOfBytes is an invalid value.
+ */
+ long skip(long numberOfBytes);
+
+ /**
+ * Reset the cipher and then skip forward to a given position.
+ *
+ * @param position the number of bytes in to set the cipher state to.
+ * @return the byte position moved to.
+ */
+ long seekTo(long position);
+
+ /**
+ * Return the current "position" of the cipher
+ *
+ * @return the current byte position.
+ */
+ long getPosition();
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/SkippingStreamCipher.java b/core/src/main/java/org/spongycastle/crypto/SkippingStreamCipher.java
new file mode 100644
index 00000000..1e704bad
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/SkippingStreamCipher.java
@@ -0,0 +1,9 @@
+package org.spongycastle.crypto;
+
+/**
+ * General interface for a stream cipher that supports skipping.
+ */
+public interface SkippingStreamCipher
+ extends StreamCipher, SkippingCipher
+{
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/StreamBlockCipher.java b/core/src/main/java/org/spongycastle/crypto/StreamBlockCipher.java
new file mode 100644
index 00000000..58410183
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/StreamBlockCipher.java
@@ -0,0 +1,58 @@
+package org.spongycastle.crypto;
+
+/**
+ * A parent class for block cipher modes that do not require block aligned data to be processed, but can function in
+ * a streaming mode.
+ */
+public abstract class StreamBlockCipher
+ implements BlockCipher, StreamCipher
+{
+ private final BlockCipher cipher;
+
+ protected StreamBlockCipher(BlockCipher cipher)
+ {
+ this.cipher = cipher;
+ }
+
+ /**
+ * return the underlying block cipher that we are wrapping.
+ *
+ * @return the underlying block cipher that we are wrapping.
+ */
+ public BlockCipher getUnderlyingCipher()
+ {
+ return cipher;
+ }
+
+ public final byte returnByte(byte in)
+ {
+ return calculateByte(in);
+ }
+
+ public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
+ throws DataLengthException
+ {
+ if (outOff + len > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (inOff + len > in.length)
+ {
+ throw new DataLengthException("input buffer too small");
+ }
+
+ int inStart = inOff;
+ int inEnd = inOff + len;
+ int outStart = outOff;
+
+ while (inStart < inEnd)
+ {
+ out[outStart++] = calculateByte(in[inStart++]);
+ }
+
+ return len;
+ }
+
+ protected abstract byte calculateByte(byte b);
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/crypto/StreamCipher.java b/core/src/main/java/org/spongycastle/crypto/StreamCipher.java
new file mode 100644
index 00000000..ba3107e3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/StreamCipher.java
@@ -0,0 +1,54 @@
+package org.spongycastle.crypto;
+
+/**
+ * the interface stream ciphers conform to.
+ */
+public interface StreamCipher
+{
+ /**
+ * Initialise the cipher.
+ *
+ * @param forEncryption if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException;
+
+ /**
+ * Return the name of the algorithm the cipher implements.
+ *
+ * @return the name of the algorithm the cipher implements.
+ */
+ public String getAlgorithmName();
+
+ /**
+ * encrypt/decrypt a single byte returning the result.
+ *
+ * @param in the byte to be processed.
+ * @return the result of processing the input byte.
+ */
+ public byte returnByte(byte in);
+
+ /**
+ * process a block of bytes from in putting the result into out.
+ *
+ * @param in the input byte array.
+ * @param inOff the offset into the in array where the data to be processed starts.
+ * @param len the number of bytes to be processed.
+ * @param out the output buffer the processed bytes go into.
+ * @param outOff the offset into the output byte array the processed data starts at.
+ * @return the number of bytes produced - should always be len.
+ * @exception DataLengthException if the output buffer is too small.
+ */
+ public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
+ throws DataLengthException;
+
+ /**
+ * reset the cipher. This leaves it in the same state
+ * it was at after the last init (if there was one).
+ */
+ public void reset();
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/Wrapper.java b/core/src/main/java/org/spongycastle/crypto/Wrapper.java
new file mode 100644
index 00000000..f517c127
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/Wrapper.java
@@ -0,0 +1,18 @@
+package org.spongycastle.crypto;
+
+public interface Wrapper
+{
+ public void init(boolean forWrapping, CipherParameters param);
+
+ /**
+ * Return the name of the algorithm the wrapper implements.
+ *
+ * @return the name of the algorithm the wrapper implements.
+ */
+ public String getAlgorithmName();
+
+ public byte[] wrap(byte[] in, int inOff, int inLen);
+
+ public byte[] unwrap(byte[] in, int inOff, int inLen)
+ throws InvalidCipherTextException;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/agreement/DHAgreement.java b/core/src/main/java/org/spongycastle/crypto/agreement/DHAgreement.java
new file mode 100644
index 00000000..9dd5d040
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/agreement/DHAgreement.java
@@ -0,0 +1,94 @@
+package org.spongycastle.crypto.agreement;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.generators.DHKeyPairGenerator;
+import org.spongycastle.crypto.params.DHKeyGenerationParameters;
+import org.spongycastle.crypto.params.DHParameters;
+import org.spongycastle.crypto.params.DHPublicKeyParameters;
+import org.spongycastle.crypto.params.DHPrivateKeyParameters;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+
+/**
+ * a Diffie-Hellman key exchange engine.
+ * <p>
+ * note: This uses MTI/A0 key agreement in order to make the key agreement
+ * secure against passive attacks. If you're doing Diffie-Hellman and both
+ * parties have long term public keys you should look at using this. For
+ * further information have a look at RFC 2631.
+ * <p>
+ * It's possible to extend this to more than two parties as well, for the moment
+ * that is left as an exercise for the reader.
+ */
+public class DHAgreement
+{
+ private DHPrivateKeyParameters key;
+ private DHParameters dhParams;
+ private BigInteger privateValue;
+ private SecureRandom random;
+
+ public void init(
+ CipherParameters param)
+ {
+ AsymmetricKeyParameter kParam;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.random = rParam.getRandom();
+ kParam = (AsymmetricKeyParameter)rParam.getParameters();
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ kParam = (AsymmetricKeyParameter)param;
+ }
+
+
+ if (!(kParam instanceof DHPrivateKeyParameters))
+ {
+ throw new IllegalArgumentException("DHEngine expects DHPrivateKeyParameters");
+ }
+
+ this.key = (DHPrivateKeyParameters)kParam;
+ this.dhParams = key.getParameters();
+ }
+
+ /**
+ * calculate our initial message.
+ */
+ public BigInteger calculateMessage()
+ {
+ DHKeyPairGenerator dhGen = new DHKeyPairGenerator();
+ dhGen.init(new DHKeyGenerationParameters(random, dhParams));
+ AsymmetricCipherKeyPair dhPair = dhGen.generateKeyPair();
+
+ this.privateValue = ((DHPrivateKeyParameters)dhPair.getPrivate()).getX();
+
+ return ((DHPublicKeyParameters)dhPair.getPublic()).getY();
+ }
+
+ /**
+ * given a message from a given party and the corresponding public key,
+ * calculate the next message in the agreement sequence. In this case
+ * this will represent the shared secret.
+ */
+ public BigInteger calculateAgreement(
+ DHPublicKeyParameters pub,
+ BigInteger message)
+ {
+ if (!pub.getParameters().equals(dhParams))
+ {
+ throw new IllegalArgumentException("Diffie-Hellman public key has wrong parameters.");
+ }
+
+ BigInteger p = dhParams.getP();
+
+ return message.modPow(key.getX(), p).multiply(pub.getY().modPow(privateValue, p)).mod(p);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/agreement/DHBasicAgreement.java b/core/src/main/java/org/spongycastle/crypto/agreement/DHBasicAgreement.java
new file mode 100644
index 00000000..6359ecdb
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/agreement/DHBasicAgreement.java
@@ -0,0 +1,71 @@
+package org.spongycastle.crypto.agreement;
+
+import java.math.BigInteger;
+
+import org.spongycastle.crypto.BasicAgreement;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.DHParameters;
+import org.spongycastle.crypto.params.DHPrivateKeyParameters;
+import org.spongycastle.crypto.params.DHPublicKeyParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+
+/**
+ * a Diffie-Hellman key agreement class.
+ * <p>
+ * note: This is only the basic algorithm, it doesn't take advantage of
+ * long term public keys if they are available. See the DHAgreement class
+ * for a "better" implementation.
+ */
+public class DHBasicAgreement
+ implements BasicAgreement
+{
+ private DHPrivateKeyParameters key;
+ private DHParameters dhParams;
+
+ public void init(
+ CipherParameters param)
+ {
+ AsymmetricKeyParameter kParam;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+ kParam = (AsymmetricKeyParameter)rParam.getParameters();
+ }
+ else
+ {
+ kParam = (AsymmetricKeyParameter)param;
+ }
+
+ if (!(kParam instanceof DHPrivateKeyParameters))
+ {
+ throw new IllegalArgumentException("DHEngine expects DHPrivateKeyParameters");
+ }
+
+ this.key = (DHPrivateKeyParameters)kParam;
+ this.dhParams = key.getParameters();
+ }
+
+ public int getFieldSize()
+ {
+ return (key.getParameters().getP().bitLength() + 7) / 8;
+ }
+
+ /**
+ * given a short term public key from a given party calculate the next
+ * message in the agreement sequence.
+ */
+ public BigInteger calculateAgreement(
+ CipherParameters pubKey)
+ {
+ DHPublicKeyParameters pub = (DHPublicKeyParameters)pubKey;
+
+ if (!pub.getParameters().equals(dhParams))
+ {
+ throw new IllegalArgumentException("Diffie-Hellman public key has wrong parameters.");
+ }
+
+ return pub.getY().modPow(key.getX(), dhParams.getP());
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/agreement/DHStandardGroups.java b/core/src/main/java/org/spongycastle/crypto/agreement/DHStandardGroups.java
new file mode 100644
index 00000000..e506d509
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/agreement/DHStandardGroups.java
@@ -0,0 +1,206 @@
+package org.spongycastle.crypto.agreement;
+
+import java.math.BigInteger;
+
+import org.spongycastle.crypto.params.DHParameters;
+import org.spongycastle.util.encoders.Hex;
+
+/**
+ * Standard Diffie-Hellman groups from various IETF specifications.
+ */
+public class DHStandardGroups
+{
+
+ private static DHParameters fromPG(String hexP, String hexG)
+ {
+ BigInteger p = new BigInteger(1, Hex.decode(hexP));
+ BigInteger g = new BigInteger(1, Hex.decode(hexG));
+ return new DHParameters(p, g);
+ }
+
+ private static DHParameters fromPGQ(String hexP, String hexG, String hexQ)
+ {
+ BigInteger p = new BigInteger(1, Hex.decode(hexP));
+ BigInteger g = new BigInteger(1, Hex.decode(hexG));
+ BigInteger q = new BigInteger(1, Hex.decode(hexQ));
+ return new DHParameters(p, g, q);
+ }
+
+ /*
+ * RFC 2409
+ */
+ private static final String rfc2409_768_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+ + "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF";
+ private static final String rfc2409_768_g = "02";
+ public static final DHParameters rfc2409_768 = fromPG(rfc2409_768_p, rfc2409_768_g);
+
+ private static final String rfc2409_1024_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381"
+ + "FFFFFFFFFFFFFFFF";
+ private static final String rfc2409_1024_g = "02";
+ public static final DHParameters rfc2409_1024 = fromPG(rfc2409_1024_p, rfc2409_1024_g);
+
+ /*
+ * RFC 3526
+ */
+ private static final String rfc3526_1536_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+ + "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF";
+ private static final String rfc3526_1536_g = "02";
+ public static final DHParameters rfc3526_1536 = fromPG(rfc3526_1536_p, rfc3526_1536_g);
+
+ private static final String rfc3526_2048_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
+ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AACAA68FFFFFFFFFFFFFFFF";
+ private static final String rfc3526_2048_g = "02";
+ public static final DHParameters rfc3526_2048 = fromPG(rfc3526_2048_p, rfc3526_2048_g);
+
+ private static final String rfc3526_3072_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
+ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
+ + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
+ + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
+ + "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF";
+ private static final String rfc3526_3072_g = "02";
+ public static final DHParameters rfc3526_3072 = fromPG(rfc3526_3072_p, rfc3526_3072_g);
+
+ private static final String rfc3526_4096_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
+ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
+ + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
+ + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
+ + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
+ + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
+ + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199"
+ + "FFFFFFFFFFFFFFFF";
+ private static final String rfc3526_4096_g = "02";
+ public static final DHParameters rfc3526_4096 = fromPG(rfc3526_4096_p, rfc3526_4096_g);
+
+ private static final String rfc3526_6144_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
+ + "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
+ + "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
+ + "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
+ + "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8"
+ + "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C"
+ + "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718"
+ + "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D"
+ + "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D"
+ + "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226"
+ + "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
+ + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC"
+ + "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26"
+ + "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB"
+ + "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2"
+ + "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127"
+ + "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
+ + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406"
+ + "AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918"
+ + "DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B33205151"
+ + "2BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03"
+ + "F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97F"
+ + "BEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
+ + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58B"
+ + "B7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632"
+ + "387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E" + "6DCC4024FFFFFFFFFFFFFFFF";
+ private static final String rfc3526_6144_g = "02";
+ public static final DHParameters rfc3526_6144 = fromPG(rfc3526_6144_p, rfc3526_6144_g);
+
+ private static final String rfc3526_8192_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
+ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
+ + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
+ + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
+ + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
+ + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
+ + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
+ + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" + "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831"
+ + "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" + "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF"
+ + "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" + "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3"
+ + "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328"
+ + "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" + "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE"
+ + "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4" + "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300"
+ + "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568" + "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9"
+ + "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B" + "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A"
+ + "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36" + "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1"
+ + "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92" + "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47"
+ + "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" + "60C980DD98EDD3DFFFFFFFFFFFFFFFFF";
+ private static final String rfc3526_8192_g = "02";
+ public static final DHParameters rfc3526_8192 = fromPG(rfc3526_8192_p, rfc3526_8192_g);
+
+ /*
+ * RFC 4306
+ */
+ public static final DHParameters rfc4306_768 = rfc2409_768;
+ public static final DHParameters rfc4306_1024 = rfc2409_1024;
+
+ /*
+ * RFC 5114
+ */
+ private static final String rfc5114_1024_160_p = "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C6"
+ + "9A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C0" + "13ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD70"
+ + "98488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0" + "A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708"
+ + "DF1FB2BC2E4A4371";
+ private static final String rfc5114_1024_160_g = "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507F"
+ + "D6406CFF14266D31266FEA1E5C41564B777E690F5504F213" + "160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1"
+ + "909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28A" + "D662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24"
+ + "855E6EEB22B3B2E5";
+ private static final String rfc5114_1024_160_q = "F518AA8781A8DF278ABA4E7D64B7CB9D49462353";
+ public static final DHParameters rfc5114_1024_160 = fromPGQ(rfc5114_1024_160_p, rfc5114_1024_160_g,
+ rfc5114_1024_160_q);
+
+ private static final String rfc5114_2048_224_p = "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1"
+ + "B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15" + "EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC212"
+ + "9037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207" + "C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708"
+ + "B3BF8A317091883681286130BC8985DB1602E714415D9330" + "278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486D"
+ + "CDF93ACC44328387315D75E198C641A480CD86A1B9E587E8" + "BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763"
+ + "C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71" + "CF9DE5384E71B81C0AC4DFFE0C10E64F";
+ private static final String rfc5114_2048_224_g = "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF"
+ + "74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFA" + "AB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7"
+ + "C17669101999024AF4D027275AC1348BB8A762D0521BC98A" + "E247150422EA1ED409939D54DA7460CDB5F6C6B250717CBE"
+ + "F180EB34118E98D119529A45D6F834566E3025E316A330EF" + "BB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB"
+ + "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381" + "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269"
+ + "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179" + "81BC087F2A7065B384B890D3191F2BFA";
+ private static final String rfc5114_2048_224_q = "801C0D34C58D93FE997177101F80535A4738CEBCBF389A99B36371EB";
+ public static final DHParameters rfc5114_2048_224 = fromPGQ(rfc5114_2048_224_p, rfc5114_2048_224_g,
+ rfc5114_2048_224_q);
+
+ private static final String rfc5114_2048_256_p = "87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F2"
+ + "5D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA30" + "16C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD"
+ + "5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B" + "6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C"
+ + "4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0E" + "F13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D9"
+ + "67E144E5140564251CCACB83E6B486F6B3CA3F7971506026" + "C0B857F689962856DED4010ABD0BE621C3A3960A54E710C3"
+ + "75F26375D7014103A4B54330C198AF126116D2276E11715F" + "693877FAD7EF09CADB094AE91E1A1597";
+ private static final String rfc5114_2048_256_g = "3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF2054"
+ + "07F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555" + "BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18"
+ + "A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B" + "777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC83"
+ + "1D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55" + "A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14"
+ + "C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915" + "B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6"
+ + "184B523D1DB246C32F63078490F00EF8D647D148D4795451" + "5E2327CFEF98C582664B4C0F6CC41659";
+ private static final String rfc5114_2048_256_q = "8CF83642A709A097B447997640129DA299B1A47D1EB3750B"
+ + "A308B0FE64F5FBD3";
+ public static final DHParameters rfc5114_2048_256 = fromPGQ(rfc5114_2048_256_p, rfc5114_2048_256_g,
+ rfc5114_2048_256_q);
+
+ /*
+ * RFC 5996
+ */
+ public static final DHParameters rfc5996_768 = rfc4306_768;
+ public static final DHParameters rfc5996_1024 = rfc4306_1024;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/agreement/ECDHBasicAgreement.java b/core/src/main/java/org/spongycastle/crypto/agreement/ECDHBasicAgreement.java
new file mode 100644
index 00000000..53559760
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/agreement/ECDHBasicAgreement.java
@@ -0,0 +1,54 @@
+package org.spongycastle.crypto.agreement;
+
+import java.math.BigInteger;
+
+import org.spongycastle.crypto.BasicAgreement;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.math.ec.ECPoint;
+
+/**
+ * P1363 7.2.1 ECSVDP-DH
+ *
+ * ECSVDP-DH is Elliptic Curve Secret Value Derivation Primitive,
+ * Diffie-Hellman version. It is based on the work of [DH76], [Mil86],
+ * and [Kob87]. This primitive derives a shared secret value from one
+ * party's private key and another party's public key, where both have
+ * the same set of EC domain parameters. If two parties correctly
+ * execute this primitive, they will produce the same output. This
+ * primitive can be invoked by a scheme to derive a shared secret key;
+ * specifically, it may be used with the schemes ECKAS-DH1 and
+ * DL/ECKAS-DH2. It assumes that the input keys are valid (see also
+ * Section 7.2.2).
+ */
+public class ECDHBasicAgreement
+ implements BasicAgreement
+{
+ private ECPrivateKeyParameters key;
+
+ public void init(
+ CipherParameters key)
+ {
+ this.key = (ECPrivateKeyParameters)key;
+ }
+
+ public int getFieldSize()
+ {
+ return (key.getParameters().getCurve().getFieldSize() + 7) / 8;
+ }
+
+ public BigInteger calculateAgreement(
+ CipherParameters pubKey)
+ {
+ ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey;
+ ECPoint P = pub.getQ().multiply(key.getD()).normalize();
+
+ if (P.isInfinity())
+ {
+ throw new IllegalStateException("Infinity is not a valid agreement value for ECDH");
+ }
+
+ return P.getAffineXCoord().toBigInteger();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/agreement/ECDHCBasicAgreement.java b/core/src/main/java/org/spongycastle/crypto/agreement/ECDHCBasicAgreement.java
new file mode 100644
index 00000000..49677805
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/agreement/ECDHCBasicAgreement.java
@@ -0,0 +1,64 @@
+package org.spongycastle.crypto.agreement;
+
+import java.math.BigInteger;
+
+import org.spongycastle.crypto.BasicAgreement;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.math.ec.ECPoint;
+
+/**
+ * P1363 7.2.2 ECSVDP-DHC
+ *
+ * ECSVDP-DHC is Elliptic Curve Secret Value Derivation Primitive,
+ * Diffie-Hellman version with cofactor multiplication. It is based on
+ * the work of [DH76], [Mil86], [Kob87], [LMQ98] and [Kal98a]. This
+ * primitive derives a shared secret value from one party's private key
+ * and another party's public key, where both have the same set of EC
+ * domain parameters. If two parties correctly execute this primitive,
+ * they will produce the same output. This primitive can be invoked by a
+ * scheme to derive a shared secret key; specifically, it may be used
+ * with the schemes ECKAS-DH1 and DL/ECKAS-DH2. It does not assume the
+ * validity of the input public key (see also Section 7.2.1).
+ * <p>
+ * Note: As stated P1363 compatibility mode with ECDH can be preset, and
+ * in this case the implementation doesn't have a ECDH compatibility mode
+ * (if you want that just use ECDHBasicAgreement and note they both implement
+ * BasicAgreement!).
+ */
+public class ECDHCBasicAgreement
+ implements BasicAgreement
+{
+ ECPrivateKeyParameters key;
+
+ public void init(
+ CipherParameters key)
+ {
+ this.key = (ECPrivateKeyParameters)key;
+ }
+
+ public int getFieldSize()
+ {
+ return (key.getParameters().getCurve().getFieldSize() + 7) / 8;
+ }
+
+ public BigInteger calculateAgreement(
+ CipherParameters pubKey)
+ {
+ ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey;
+ ECDomainParameters params = pub.getParameters();
+
+ BigInteger hd = params.getH().multiply(key.getD()).mod(params.getN());
+
+ 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/core/src/main/java/org/spongycastle/crypto/agreement/ECMQVBasicAgreement.java b/core/src/main/java/org/spongycastle/crypto/agreement/ECMQVBasicAgreement.java
new file mode 100644
index 00000000..9faa5006
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/agreement/ECMQVBasicAgreement.java
@@ -0,0 +1,91 @@
+package org.spongycastle.crypto.agreement;
+
+import java.math.BigInteger;
+
+import org.spongycastle.crypto.BasicAgreement;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.crypto.params.MQVPrivateParameters;
+import org.spongycastle.crypto.params.MQVPublicParameters;
+import org.spongycastle.math.ec.ECAlgorithms;
+import org.spongycastle.math.ec.ECConstants;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECPoint;
+
+public class ECMQVBasicAgreement
+ implements BasicAgreement
+{
+ MQVPrivateParameters privParams;
+
+ public void init(
+ CipherParameters key)
+ {
+ this.privParams = (MQVPrivateParameters)key;
+ }
+
+ public int getFieldSize()
+ {
+ return (privParams.getStaticPrivateKey().getParameters().getCurve().getFieldSize() + 7) / 8;
+ }
+
+ public BigInteger calculateAgreement(CipherParameters pubKey)
+ {
+ MQVPublicParameters pubParams = (MQVPublicParameters)pubKey;
+
+ ECPrivateKeyParameters staticPrivateKey = privParams.getStaticPrivateKey();
+
+ ECPoint agreement = calculateMqvAgreement(staticPrivateKey.getParameters(), staticPrivateKey,
+ privParams.getEphemeralPrivateKey(), privParams.getEphemeralPublicKey(),
+ pubParams.getStaticPublicKey(), pubParams.getEphemeralPublicKey()).normalize();
+
+ 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
+ private ECPoint calculateMqvAgreement(
+ ECDomainParameters parameters,
+ ECPrivateKeyParameters d1U,
+ ECPrivateKeyParameters d2U,
+ ECPublicKeyParameters Q2U,
+ ECPublicKeyParameters Q1V,
+ ECPublicKeyParameters Q2V)
+ {
+ BigInteger n = parameters.getN();
+ int e = (n.bitLength() + 1) / 2;
+ BigInteger powE = ECConstants.ONE.shiftLeft(e);
+
+ ECCurve curve = parameters.getCurve();
+
+ 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).add(d2U.getD()).mod(n);
+
+ BigInteger xPrime = q2v.getAffineXCoord().toBigInteger();
+ BigInteger xPrimeBar = xPrime.mod(powE);
+ BigInteger Q2VBar = xPrimeBar.setBit(e);
+
+ BigInteger hs = parameters.getH().multiply(s).mod(n);
+
+ return ECAlgorithms.sumOfTwoMultiplies(
+ q1v, Q2VBar.multiply(hs).mod(n), q2v, hs);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEParticipant.java b/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEParticipant.java
new file mode 100644
index 00000000..e7f1853e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEParticipant.java
@@ -0,0 +1,546 @@
+package org.spongycastle.crypto.agreement.jpake;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.util.Arrays;
+
+/**
+ * A participant in a Password Authenticated Key Exchange by Juggling (J-PAKE) exchange.
+ * <p>
+ * The J-PAKE exchange is defined by Feng Hao and Peter Ryan in the paper
+ * <a href="http://grouper.ieee.org/groups/1363/Research/contributions/hao-ryan-2008.pdf">
+ * "Password Authenticated Key Exchange by Juggling, 2008."</a>
+ * <p>
+ * The J-PAKE protocol is symmetric.
+ * There is no notion of a <i>client</i> or <i>server</i>, but rather just two <i>participants</i>.
+ * An instance of {@link JPAKEParticipant} represents one participant, and
+ * is the primary interface for executing the exchange.
+ * <p>
+ * To execute an exchange, construct a {@link JPAKEParticipant} on each end,
+ * and call the following 7 methods
+ * (once and only once, in the given order, for each participant, sending messages between them as described):
+ * <ol>
+ * <li>{@link #createRound1PayloadToSend()} - and send the payload to the other participant</li>
+ * <li>{@link #validateRound1PayloadReceived(JPAKERound1Payload)} - use the payload received from the other participant</li>
+ * <li>{@link #createRound2PayloadToSend()} - and send the payload to the other participant</li>
+ * <li>{@link #validateRound2PayloadReceived(JPAKERound2Payload)} - use the payload received from the other participant</li>
+ * <li>{@link #calculateKeyingMaterial()}</li>
+ * <li>{@link #createRound3PayloadToSend(BigInteger)} - and send the payload to the other participant</li>
+ * <li>{@link #validateRound3PayloadReceived(JPAKERound3Payload, BigInteger)} - use the payload received from the other participant</li>
+ * </ol>
+ * <p>
+ * Each side should derive a session key from the keying material returned by {@link #calculateKeyingMaterial()}.
+ * The caller is responsible for deriving the session key using a secure key derivation function (KDF).
+ * <p>
+ * Round 3 is an optional key confirmation process.
+ * If you do not execute round 3, then there is no assurance that both participants are using the same key.
+ * (i.e. if the participants used different passwords, then their session keys will differ.)
+ * <p>
+ * If the round 3 validation succeeds, then the keys are guaranteed to be the same on both sides.
+ * <p>
+ * The symmetric design can easily support the asymmetric cases when one party initiates the communication.
+ * e.g. Sometimes the round1 payload and round2 payload may be sent in one pass.
+ * Also, in some cases, the key confirmation payload can be sent together with the round2 payload.
+ * These are the trivial techniques to optimize the communication.
+ * <p>
+ * The key confirmation process is implemented as specified in
+ * <a href="http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf">NIST SP 800-56A Revision 1</a>,
+ * Section 8.2 Unilateral Key Confirmation for Key Agreement Schemes.
+ * <p>
+ * This class is stateful and NOT threadsafe.
+ * Each instance should only be used for ONE complete J-PAKE exchange
+ * (i.e. a new {@link JPAKEParticipant} should be constructed for each new J-PAKE exchange).
+ * <p>
+ * See {@link JPAKEExample} for example usage.
+ */
+public class JPAKEParticipant
+{
+ /*
+ * Possible internal states. Used for state checking.
+ */
+
+ public static final int STATE_INITIALIZED = 0;
+ public static final int STATE_ROUND_1_CREATED = 10;
+ public static final int STATE_ROUND_1_VALIDATED = 20;
+ public static final int STATE_ROUND_2_CREATED = 30;
+ public static final int STATE_ROUND_2_VALIDATED = 40;
+ public static final int STATE_KEY_CALCULATED = 50;
+ public static final int STATE_ROUND_3_CREATED = 60;
+ public static final int STATE_ROUND_3_VALIDATED = 70;
+
+ /**
+ * Unique identifier of this participant.
+ * The two participants in the exchange must NOT share the same id.
+ */
+ private final String participantId;
+
+ /**
+ * Shared secret. This only contains the secret between construction
+ * and the call to {@link #calculateKeyingMaterial()}.
+ * <p/>
+ * i.e. When {@link #calculateKeyingMaterial()} is called, this buffer overwritten with 0's,
+ * and the field is set to null.
+ */
+ private char[] password;
+
+ /**
+ * Digest to use during calculations.
+ */
+ private final Digest digest;
+
+ /**
+ * Source of secure random data.
+ */
+ private final SecureRandom random;
+
+ private final BigInteger p;
+ private final BigInteger q;
+ private final BigInteger g;
+
+ /**
+ * The participantId of the other participant in this exchange.
+ */
+ private String partnerParticipantId;
+
+ /**
+ * Alice's x1 or Bob's x3.
+ */
+ private BigInteger x1;
+ /**
+ * Alice's x2 or Bob's x4.
+ */
+ private BigInteger x2;
+ /**
+ * Alice's g^x1 or Bob's g^x3.
+ */
+ private BigInteger gx1;
+ /**
+ * Alice's g^x2 or Bob's g^x4.
+ */
+ private BigInteger gx2;
+ /**
+ * Alice's g^x3 or Bob's g^x1.
+ */
+ private BigInteger gx3;
+ /**
+ * Alice's g^x4 or Bob's g^x2.
+ */
+ private BigInteger gx4;
+ /**
+ * Alice's B or Bob's A.
+ */
+ private BigInteger b;
+
+ /**
+ * The current state.
+ * See the <tt>STATE_*</tt> constants for possible values.
+ */
+ private int state;
+
+ /**
+ * Convenience constructor for a new {@link JPAKEParticipant} that uses
+ * the {@link JPAKEPrimeOrderGroups#NIST_3072} prime order group,
+ * a SHA-256 digest, and a default {@link SecureRandom} implementation.
+ * <p>
+ * After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}.
+ *
+ * @param participantId unique identifier of this participant.
+ * The two participants in the exchange must NOT share the same id.
+ * @param password shared secret.
+ * A defensive copy of this array is made (and cleared once {@link #calculateKeyingMaterial()} is called).
+ * Caller should clear the input password as soon as possible.
+ * @throws NullPointerException if any argument is null
+ * @throws IllegalArgumentException if password is empty
+ */
+ public JPAKEParticipant(
+ String participantId,
+ char[] password)
+ {
+ this(
+ participantId,
+ password,
+ JPAKEPrimeOrderGroups.NIST_3072);
+ }
+
+
+ /**
+ * Convenience constructor for a new {@link JPAKEParticipant} that uses
+ * a SHA-256 digest and a default {@link SecureRandom} implementation.
+ * <p>
+ * After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}.
+ *
+ * @param participantId unique identifier of this participant.
+ * The two participants in the exchange must NOT share the same id.
+ * @param password shared secret.
+ * A defensive copy of this array is made (and cleared once {@link #calculateKeyingMaterial()} is called).
+ * Caller should clear the input password as soon as possible.
+ * @param group prime order group.
+ * See {@link JPAKEPrimeOrderGroups} for standard groups
+ * @throws NullPointerException if any argument is null
+ * @throws IllegalArgumentException if password is empty
+ */
+ public JPAKEParticipant(
+ String participantId,
+ char[] password,
+ JPAKEPrimeOrderGroup group)
+ {
+ this(
+ participantId,
+ password,
+ group,
+ new SHA256Digest(),
+ new SecureRandom());
+ }
+
+
+ /**
+ * Construct a new {@link JPAKEParticipant}.
+ * <p>
+ * After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}.
+ *
+ * @param participantId unique identifier of this participant.
+ * The two participants in the exchange must NOT share the same id.
+ * @param password shared secret.
+ * A defensive copy of this array is made (and cleared once {@link #calculateKeyingMaterial()} is called).
+ * Caller should clear the input password as soon as possible.
+ * @param group prime order group.
+ * See {@link JPAKEPrimeOrderGroups} for standard groups
+ * @param digest digest to use during zero knowledge proofs and key confirmation (SHA-256 or stronger preferred)
+ * @param random source of secure random data for x1 and x2, and for the zero knowledge proofs
+ * @throws NullPointerException if any argument is null
+ * @throws IllegalArgumentException if password is empty
+ */
+ public JPAKEParticipant(
+ String participantId,
+ char[] password,
+ JPAKEPrimeOrderGroup group,
+ Digest digest,
+ SecureRandom random)
+ {
+ JPAKEUtil.validateNotNull(participantId, "participantId");
+ JPAKEUtil.validateNotNull(password, "password");
+ JPAKEUtil.validateNotNull(group, "p");
+ JPAKEUtil.validateNotNull(digest, "digest");
+ JPAKEUtil.validateNotNull(random, "random");
+ if (password.length == 0)
+ {
+ throw new IllegalArgumentException("Password must not be empty.");
+ }
+
+ this.participantId = participantId;
+
+ /*
+ * Create a defensive copy so as to fully encapsulate the password.
+ *
+ * This array will contain the password for the lifetime of this
+ * participant BEFORE {@link #calculateKeyingMaterial()} is called.
+ *
+ * i.e. When {@link #calculateKeyingMaterial()} is called, the array will be cleared
+ * in order to remove the password from memory.
+ *
+ * The caller is responsible for clearing the original password array
+ * given as input to this constructor.
+ */
+ this.password = Arrays.copyOf(password, password.length);
+
+ this.p = group.getP();
+ this.q = group.getQ();
+ this.g = group.getG();
+
+ this.digest = digest;
+ this.random = random;
+
+ this.state = STATE_INITIALIZED;
+ }
+
+ /**
+ * Gets the current state of this participant.
+ * See the <tt>STATE_*</tt> constants for possible values.
+ */
+ public int getState()
+ {
+ return this.state;
+ }
+
+ /**
+ * Creates and returns the payload to send to the other participant during round 1.
+ * <p>
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_1_CREATED}.
+ */
+ public JPAKERound1Payload createRound1PayloadToSend()
+ {
+ if (this.state >= STATE_ROUND_1_CREATED)
+ {
+ throw new IllegalStateException("Round1 payload already created for " + participantId);
+ }
+
+ this.x1 = JPAKEUtil.generateX1(q, random);
+ this.x2 = JPAKEUtil.generateX2(q, random);
+
+ this.gx1 = JPAKEUtil.calculateGx(p, g, x1);
+ this.gx2 = JPAKEUtil.calculateGx(p, g, x2);
+ BigInteger[] knowledgeProofForX1 = JPAKEUtil.calculateZeroKnowledgeProof(p, q, g, gx1, x1, participantId, digest, random);
+ BigInteger[] knowledgeProofForX2 = JPAKEUtil.calculateZeroKnowledgeProof(p, q, g, gx2, x2, participantId, digest, random);
+
+ this.state = STATE_ROUND_1_CREATED;
+
+ return new JPAKERound1Payload(participantId, gx1, gx2, knowledgeProofForX1, knowledgeProofForX2);
+ }
+
+ /**
+ * Validates the payload received from the other participant during round 1.
+ * <p>
+ * Must be called prior to {@link #createRound2PayloadToSend()}.
+ * <p>
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_1_VALIDATED}.
+ *
+ * @throws CryptoException if validation fails.
+ * @throws IllegalStateException if called multiple times.
+ */
+ public void validateRound1PayloadReceived(JPAKERound1Payload round1PayloadReceived)
+ throws CryptoException
+ {
+ if (this.state >= STATE_ROUND_1_VALIDATED)
+ {
+ throw new IllegalStateException("Validation already attempted for round1 payload for" + participantId);
+ }
+ this.partnerParticipantId = round1PayloadReceived.getParticipantId();
+ this.gx3 = round1PayloadReceived.getGx1();
+ this.gx4 = round1PayloadReceived.getGx2();
+
+ BigInteger[] knowledgeProofForX3 = round1PayloadReceived.getKnowledgeProofForX1();
+ BigInteger[] knowledgeProofForX4 = round1PayloadReceived.getKnowledgeProofForX2();
+
+ JPAKEUtil.validateParticipantIdsDiffer(participantId, round1PayloadReceived.getParticipantId());
+ JPAKEUtil.validateGx4(gx4);
+ JPAKEUtil.validateZeroKnowledgeProof(p, q, g, gx3, knowledgeProofForX3, round1PayloadReceived.getParticipantId(), digest);
+ JPAKEUtil.validateZeroKnowledgeProof(p, q, g, gx4, knowledgeProofForX4, round1PayloadReceived.getParticipantId(), digest);
+
+ this.state = STATE_ROUND_1_VALIDATED;
+ }
+
+ /**
+ * Creates and returns the payload to send to the other participant during round 2.
+ * <p>
+ * {@link #validateRound1PayloadReceived(JPAKERound1Payload)} must be called prior to this method.
+ * <p>
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_2_CREATED}.
+ *
+ * @throws IllegalStateException if called prior to {@link #validateRound1PayloadReceived(JPAKERound1Payload)}, or multiple times
+ */
+ public JPAKERound2Payload createRound2PayloadToSend()
+ {
+ if (this.state >= STATE_ROUND_2_CREATED)
+ {
+ throw new IllegalStateException("Round2 payload already created for " + this.participantId);
+ }
+ if (this.state < STATE_ROUND_1_VALIDATED)
+ {
+ throw new IllegalStateException("Round1 payload must be validated prior to creating Round2 payload for " + this.participantId);
+ }
+ BigInteger gA = JPAKEUtil.calculateGA(p, gx1, gx3, gx4);
+ BigInteger s = JPAKEUtil.calculateS(password);
+ BigInteger x2s = JPAKEUtil.calculateX2s(q, x2, s);
+ BigInteger A = JPAKEUtil.calculateA(p, q, gA, x2s);
+ BigInteger[] knowledgeProofForX2s = JPAKEUtil.calculateZeroKnowledgeProof(p, q, gA, A, x2s, participantId, digest, random);
+
+ this.state = STATE_ROUND_2_CREATED;
+
+ return new JPAKERound2Payload(participantId, A, knowledgeProofForX2s);
+ }
+
+ /**
+ * Validates the payload received from the other participant during round 2.
+ * <p>
+ * Note that this DOES NOT detect a non-common password.
+ * The only indication of a non-common password is through derivation
+ * of different keys (which can be detected explicitly by executing round 3 and round 4)
+ * <p>
+ * Must be called prior to {@link #calculateKeyingMaterial()}.
+ * <p>
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_2_VALIDATED}.
+ *
+ * @throws CryptoException if validation fails.
+ * @throws IllegalStateException if called prior to {@link #validateRound1PayloadReceived(JPAKERound1Payload)}, or multiple times
+ */
+ public void validateRound2PayloadReceived(JPAKERound2Payload round2PayloadReceived)
+ throws CryptoException
+ {
+ if (this.state >= STATE_ROUND_2_VALIDATED)
+ {
+ throw new IllegalStateException("Validation already attempted for round2 payload for" + participantId);
+ }
+ if (this.state < STATE_ROUND_1_VALIDATED)
+ {
+ throw new IllegalStateException("Round1 payload must be validated prior to validating Round2 payload for " + this.participantId);
+ }
+ BigInteger gB = JPAKEUtil.calculateGA(p, gx3, gx1, gx2);
+ this.b = round2PayloadReceived.getA();
+ BigInteger[] knowledgeProofForX4s = round2PayloadReceived.getKnowledgeProofForX2s();
+
+ JPAKEUtil.validateParticipantIdsDiffer(participantId, round2PayloadReceived.getParticipantId());
+ JPAKEUtil.validateParticipantIdsEqual(this.partnerParticipantId, round2PayloadReceived.getParticipantId());
+ JPAKEUtil.validateGa(gB);
+ JPAKEUtil.validateZeroKnowledgeProof(p, q, gB, b, knowledgeProofForX4s, round2PayloadReceived.getParticipantId(), digest);
+
+ this.state = STATE_ROUND_2_VALIDATED;
+ }
+
+ /**
+ * Calculates and returns the key material.
+ * A session key must be derived from this key material using a secure key derivation function (KDF).
+ * The KDF used to derive the key is handled externally (i.e. not by {@link JPAKEParticipant}).
+ * <p>
+ * The keying material will be identical for each participant if and only if
+ * each participant's password is the same. i.e. If the participants do not
+ * share the same password, then each participant will derive a different key.
+ * Therefore, if you immediately start using a key derived from
+ * the keying material, then you must handle detection of incorrect keys.
+ * If you want to handle this detection explicitly, you can optionally perform
+ * rounds 3 and 4. See {@link JPAKEParticipant} for details on how to execute
+ * rounds 3 and 4.
+ * <p>
+ * The keying material will be in the range <tt>[0, p-1]</tt>.
+ * <p>
+ * {@link #validateRound2PayloadReceived(JPAKERound2Payload)} must be called prior to this method.
+ * <p>
+ * As a side effect, the internal {@link #password} array is cleared, since it is no longer needed.
+ * <p>
+ * After execution, the {@link #getState() state} will be {@link #STATE_KEY_CALCULATED}.
+ *
+ * @throws IllegalStateException if called prior to {@link #validateRound2PayloadReceived(JPAKERound2Payload)},
+ * or if called multiple times.
+ */
+ public BigInteger calculateKeyingMaterial()
+ {
+ if (this.state >= STATE_KEY_CALCULATED)
+ {
+ throw new IllegalStateException("Key already calculated for " + participantId);
+ }
+ if (this.state < STATE_ROUND_2_VALIDATED)
+ {
+ throw new IllegalStateException("Round2 payload must be validated prior to creating key for " + participantId);
+ }
+ BigInteger s = JPAKEUtil.calculateS(password);
+
+ /*
+ * Clear the password array from memory, since we don't need it anymore.
+ *
+ * Also set the field to null as a flag to indicate that the key has already been calculated.
+ */
+ Arrays.fill(password, (char)0);
+ this.password = null;
+
+ BigInteger keyingMaterial = JPAKEUtil.calculateKeyingMaterial(p, q, gx4, x2, s, b);
+
+ /*
+ * Clear the ephemeral private key fields as well.
+ * Note that we're relying on the garbage collector to do its job to clean these up.
+ * The old objects will hang around in memory until the garbage collector destroys them.
+ *
+ * If the ephemeral private keys x1 and x2 are leaked,
+ * the attacker might be able to brute-force the password.
+ */
+ this.x1 = null;
+ this.x2 = null;
+ this.b = null;
+
+ /*
+ * Do not clear gx* yet, since those are needed by round 3.
+ */
+
+ this.state = STATE_KEY_CALCULATED;
+
+ return keyingMaterial;
+ }
+
+
+ /**
+ * Creates and returns the payload to send to the other participant during round 3.
+ * <p>
+ * See {@link JPAKEParticipant} for more details on round 3.
+ * <p>
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_3_CREATED}.
+ *
+ * @param keyingMaterial The keying material as returned from {@link #calculateKeyingMaterial()}.
+ * @throws IllegalStateException if called prior to {@link #calculateKeyingMaterial()}, or multiple times
+ */
+ public JPAKERound3Payload createRound3PayloadToSend(BigInteger keyingMaterial)
+ {
+ if (this.state >= STATE_ROUND_3_CREATED)
+ {
+ throw new IllegalStateException("Round3 payload already created for " + this.participantId);
+ }
+ if (this.state < STATE_KEY_CALCULATED)
+ {
+ throw new IllegalStateException("Keying material must be calculated prior to creating Round3 payload for " + this.participantId);
+ }
+
+ BigInteger macTag = JPAKEUtil.calculateMacTag(
+ this.participantId,
+ this.partnerParticipantId,
+ this.gx1,
+ this.gx2,
+ this.gx3,
+ this.gx4,
+ keyingMaterial,
+ this.digest);
+
+ this.state = STATE_ROUND_3_CREATED;
+
+ return new JPAKERound3Payload(participantId, macTag);
+ }
+
+ /**
+ * Validates the payload received from the other participant during round 3.
+ * <p>
+ * See {@link JPAKEParticipant} for more details on round 3.
+ * <p>
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_3_VALIDATED}.
+ *
+ * @param keyingMaterial The keying material as returned from {@link #calculateKeyingMaterial()}.
+ * @throws CryptoException if validation fails.
+ * @throws IllegalStateException if called prior to {@link #calculateKeyingMaterial()}, or multiple times
+ */
+ public void validateRound3PayloadReceived(JPAKERound3Payload round3PayloadReceived, BigInteger keyingMaterial)
+ throws CryptoException
+ {
+ if (this.state >= STATE_ROUND_3_VALIDATED)
+ {
+ throw new IllegalStateException("Validation already attempted for round3 payload for" + participantId);
+ }
+ if (this.state < STATE_KEY_CALCULATED)
+ {
+ throw new IllegalStateException("Keying material must be calculated validated prior to validating Round3 payload for " + this.participantId);
+ }
+ JPAKEUtil.validateParticipantIdsDiffer(participantId, round3PayloadReceived.getParticipantId());
+ JPAKEUtil.validateParticipantIdsEqual(this.partnerParticipantId, round3PayloadReceived.getParticipantId());
+
+ JPAKEUtil.validateMacTag(
+ this.participantId,
+ this.partnerParticipantId,
+ this.gx1,
+ this.gx2,
+ this.gx3,
+ this.gx4,
+ keyingMaterial,
+ this.digest,
+ round3PayloadReceived.getMacTag());
+
+
+ /*
+ * Clear the rest of the fields.
+ */
+ this.gx1 = null;
+ this.gx2 = null;
+ this.gx3 = null;
+ this.gx4 = null;
+
+ this.state = STATE_ROUND_3_VALIDATED;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java b/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java
new file mode 100644
index 00000000..3571e81b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java
@@ -0,0 +1,115 @@
+package org.spongycastle.crypto.agreement.jpake;
+
+import java.math.BigInteger;
+
+/**
+ * A pre-computed prime order group for use during a J-PAKE exchange.
+ * <p>
+ * Typically a Schnorr group is used. In general, J-PAKE can use any prime order group
+ * that is suitable for public key cryptography, including elliptic curve cryptography.
+ * <p>
+ * See {@link JPAKEPrimeOrderGroups} for convenient standard groups.
+ * <p>
+ * NIST <a href="http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/DSA2_All.pdf">publishes</a>
+ * many groups that can be used for the desired level of security.
+ */
+public class JPAKEPrimeOrderGroup
+{
+ private final BigInteger p;
+ private final BigInteger q;
+ private final BigInteger g;
+
+ /**
+ * Constructs a new {@link JPAKEPrimeOrderGroup}.
+ * <p>
+ * In general, you should use one of the pre-approved groups from
+ * {@link JPAKEPrimeOrderGroups}, rather than manually constructing one.
+ * <p>
+ * The following basic checks are performed:
+ * <ul>
+ * <li>p-1 must be evenly divisible by q</li>
+ * <li>g must be in [2, p-1]</li>
+ * <li>g^q mod p must equal 1</li>
+ * <li>p must be prime (within reasonably certainty)</li>
+ * <li>q must be prime (within reasonably certainty)</li>
+ * </ul>
+ * <p>
+ * The prime checks are performed using {@link BigInteger#isProbablePrime(int)},
+ * and are therefore subject to the same probability guarantees.
+ * <p>
+ * These checks prevent trivial mistakes.
+ * However, due to the small uncertainties if p and q are not prime,
+ * advanced attacks are not prevented.
+ * Use it at your own risk.
+ *
+ * @throws NullPointerException if any argument is null
+ * @throws IllegalArgumentException if any of the above validations fail
+ */
+ public JPAKEPrimeOrderGroup(BigInteger p, BigInteger q, BigInteger g)
+ {
+ /*
+ * Don't skip the checks on user-specified groups.
+ */
+ this(p, q, g, false);
+ }
+
+ /**
+ * Internal package-private constructor used by the pre-approved
+ * groups in {@link JPAKEPrimeOrderGroups}.
+ * These pre-approved groups can avoid the expensive checks.
+ */
+ JPAKEPrimeOrderGroup(BigInteger p, BigInteger q, BigInteger g, boolean skipChecks)
+ {
+ JPAKEUtil.validateNotNull(p, "p");
+ JPAKEUtil.validateNotNull(q, "q");
+ JPAKEUtil.validateNotNull(g, "g");
+
+ if (!skipChecks)
+ {
+ if (!p.subtract(JPAKEUtil.ONE).mod(q).equals(JPAKEUtil.ZERO))
+ {
+ throw new IllegalArgumentException("p-1 must be evenly divisible by q");
+ }
+ if (g.compareTo(BigInteger.valueOf(2)) == -1 || g.compareTo(p.subtract(JPAKEUtil.ONE)) == 1)
+ {
+ throw new IllegalArgumentException("g must be in [2, p-1]");
+ }
+ if (!g.modPow(q, p).equals(JPAKEUtil.ONE))
+ {
+ throw new IllegalArgumentException("g^q mod p must equal 1");
+ }
+ /*
+ * Note that these checks do not guarantee that p and q are prime.
+ * We just have reasonable certainty that they are prime.
+ */
+ if (!p.isProbablePrime(20))
+ {
+ throw new IllegalArgumentException("p must be prime");
+ }
+ if (!q.isProbablePrime(20))
+ {
+ throw new IllegalArgumentException("q must be prime");
+ }
+ }
+
+ this.p = p;
+ this.q = q;
+ this.g = g;
+ }
+
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public BigInteger getG()
+ {
+ return g;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroups.java b/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroups.java
new file mode 100644
index 00000000..17f576a0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroups.java
@@ -0,0 +1,111 @@
+package org.spongycastle.crypto.agreement.jpake;
+
+import java.math.BigInteger;
+
+/**
+ * Standard pre-computed prime order groups for use by J-PAKE.
+ * (J-PAKE can use pre-computed prime order groups, same as DSA and Diffie-Hellman.)
+ * <p>
+ * This class contains some convenient constants for use as input for
+ * constructing {@link JPAKEParticipant}s.
+ * <p>
+ * The prime order groups below are taken from Sun's JDK JavaDoc (docs/guide/security/CryptoSpec.html#AppB),
+ * and from the prime order groups
+ * <a href="http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/DSA2_All.pdf">published by NIST</a>.
+ */
+public class JPAKEPrimeOrderGroups
+{
+ /**
+ * From Sun's JDK JavaDoc (docs/guide/security/CryptoSpec.html#AppB)
+ * 1024-bit p, 160-bit q and 1024-bit g for 80-bit security.
+ */
+ public static final JPAKEPrimeOrderGroup SUN_JCE_1024 = new JPAKEPrimeOrderGroup(
+ // p
+ new BigInteger(
+ "fd7f53811d75122952df4a9c2eece4e7f611b7523cef4400c31e3f80b6512669" +
+ "455d402251fb593d8d58fabfc5f5ba30f6cb9b556cd7813b801d346ff26660b7" +
+ "6b9950a5a49f9fe8047b1022c24fbba9d7feb7c61bf83b57e7c6a8a6150f04fb" +
+ "83f6d3c51ec3023554135a169132f675f3ae2b61d72aeff22203199dd14801c7", 16),
+ // q
+ new BigInteger(
+ "9760508f15230bccb292b982a2eb840bf0581cf5", 16),
+ // g
+ new BigInteger(
+ "f7e1a085d69b3ddecbbcab5c36b857b97994afbbfa3aea82f9574c0b3d078267" +
+ "5159578ebad4594fe67107108180b449167123e84c281613b7cf09328cc8a6e1" +
+ "3c167a8b547c8d28e0a3ae1e2bb3a675916ea37f0bfa213562f1fb627a01243b" +
+ "cca4f1bea8519089a883dfe15ae59f06928b665e807b552564014c3bfecf492a", 16),
+ true
+ );
+
+ /**
+ * From NIST.
+ * 2048-bit p, 224-bit q and 2048-bit g for 112-bit security.
+ */
+ public static final JPAKEPrimeOrderGroup NIST_2048 = new JPAKEPrimeOrderGroup(
+ // p
+ new BigInteger(
+ "C196BA05AC29E1F9C3C72D56DFFC6154A033F1477AC88EC37F09BE6C5BB95F51" +
+ "C296DD20D1A28A067CCC4D4316A4BD1DCA55ED1066D438C35AEBAABF57E7DAE4" +
+ "28782A95ECA1C143DB701FD48533A3C18F0FE23557EA7AE619ECACC7E0B51652" +
+ "A8776D02A425567DED36EABD90CA33A1E8D988F0BBB92D02D1D20290113BB562" +
+ "CE1FC856EEB7CDD92D33EEA6F410859B179E7E789A8F75F645FAE2E136D252BF" +
+ "FAFF89528945C1ABE705A38DBC2D364AADE99BE0D0AAD82E5320121496DC65B3" +
+ "930E38047294FF877831A16D5228418DE8AB275D7D75651CEFED65F78AFC3EA7" +
+ "FE4D79B35F62A0402A1117599ADAC7B269A59F353CF450E6982D3B1702D9CA83", 16),
+ // q
+ new BigInteger(
+ "90EAF4D1AF0708B1B612FF35E0A2997EB9E9D263C9CE659528945C0D", 16),
+ // g
+ new BigInteger(
+ "A59A749A11242C58C894E9E5A91804E8FA0AC64B56288F8D47D51B1EDC4D6544" +
+ "4FECA0111D78F35FC9FDD4CB1F1B79A3BA9CBEE83A3F811012503C8117F98E50" +
+ "48B089E387AF6949BF8784EBD9EF45876F2E6A5A495BE64B6E770409494B7FEE" +
+ "1DBB1E4B2BC2A53D4F893D418B7159592E4FFFDF6969E91D770DAEBD0B5CB14C" +
+ "00AD68EC7DC1E5745EA55C706C4A1C5C88964E34D09DEB753AD418C1AD0F4FDF" +
+ "D049A955E5D78491C0B7A2F1575A008CCD727AB376DB6E695515B05BD412F5B8" +
+ "C2F4C77EE10DA48ABD53F5DD498927EE7B692BBBCDA2FB23A516C5B4533D7398" +
+ "0B2A3B60E384ED200AE21B40D273651AD6060C13D97FD69AA13C5611A51B9085", 16),
+ true
+ );
+
+ /**
+ * From NIST.
+ * 3072-bit p, 256-bit q and 3072-bit g for 128-bit security.
+ */
+ public static final JPAKEPrimeOrderGroup NIST_3072 = new JPAKEPrimeOrderGroup(
+ // p
+ new BigInteger(
+ "90066455B5CFC38F9CAA4A48B4281F292C260FEEF01FD61037E56258A7795A1C" +
+ "7AD46076982CE6BB956936C6AB4DCFE05E6784586940CA544B9B2140E1EB523F" +
+ "009D20A7E7880E4E5BFA690F1B9004A27811CD9904AF70420EEFD6EA11EF7DA1" +
+ "29F58835FF56B89FAA637BC9AC2EFAAB903402229F491D8D3485261CD068699B" +
+ "6BA58A1DDBBEF6DB51E8FE34E8A78E542D7BA351C21EA8D8F1D29F5D5D159394" +
+ "87E27F4416B0CA632C59EFD1B1EB66511A5A0FBF615B766C5862D0BD8A3FE7A0" +
+ "E0DA0FB2FE1FCB19E8F9996A8EA0FCCDE538175238FC8B0EE6F29AF7F642773E" +
+ "BE8CD5402415A01451A840476B2FCEB0E388D30D4B376C37FE401C2A2C2F941D" +
+ "AD179C540C1C8CE030D460C4D983BE9AB0B20F69144C1AE13F9383EA1C08504F" +
+ "B0BF321503EFE43488310DD8DC77EC5B8349B8BFE97C2C560EA878DE87C11E3D" +
+ "597F1FEA742D73EEC7F37BE43949EF1A0D15C3F3E3FC0A8335617055AC91328E" +
+ "C22B50FC15B941D3D1624CD88BC25F3E941FDDC6200689581BFEC416B4B2CB73", 16),
+ // q
+ new BigInteger(
+ "CFA0478A54717B08CE64805B76E5B14249A77A4838469DF7F7DC987EFCCFB11D", 16),
+ // g
+ new BigInteger(
+ "5E5CBA992E0A680D885EB903AEA78E4A45A469103D448EDE3B7ACCC54D521E37" +
+ "F84A4BDD5B06B0970CC2D2BBB715F7B82846F9A0C393914C792E6A923E2117AB" +
+ "805276A975AADB5261D91673EA9AAFFEECBFA6183DFCB5D3B7332AA19275AFA1" +
+ "F8EC0B60FB6F66CC23AE4870791D5982AAD1AA9485FD8F4A60126FEB2CF05DB8" +
+ "A7F0F09B3397F3937F2E90B9E5B9C9B6EFEF642BC48351C46FB171B9BFA9EF17" +
+ "A961CE96C7E7A7CC3D3D03DFAD1078BA21DA425198F07D2481622BCE45969D9C" +
+ "4D6063D72AB7A0F08B2F49A7CC6AF335E08C4720E31476B67299E231F8BD90B3" +
+ "9AC3AE3BE0C6B6CACEF8289A2E2873D58E51E029CAFBD55E6841489AB66B5B4B" +
+ "9BA6E2F784660896AFF387D92844CCB8B69475496DE19DA2E58259B090489AC8" +
+ "E62363CDF82CFD8EF2A427ABCD65750B506F56DDE3B988567A88126B914D7828" +
+ "E2B63A6D7ED0747EC59E0E0A23CE7D8A74C1D2C2A7AFB6A29799620F00E11C33" +
+ "787F7DED3B30E1A22D09F1FBDA1ABBBFBF25CAE05A13F812E34563F99410E73B", 16),
+ true
+ );
+
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound1Payload.java b/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound1Payload.java
new file mode 100644
index 00000000..0f6d3838
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound1Payload.java
@@ -0,0 +1,96 @@
+package org.spongycastle.crypto.agreement.jpake;
+
+import java.math.BigInteger;
+
+import org.spongycastle.util.Arrays;
+
+/**
+ * The payload sent/received during the first round of a J-PAKE exchange.
+ * <p>
+ * Each {@link JPAKEParticipant} creates and sends an instance
+ * of this payload to the other {@link JPAKEParticipant}.
+ * The payload to send should be created via
+ * {@link JPAKEParticipant#createRound1PayloadToSend()}.
+ * <p>
+ * Each {@link JPAKEParticipant} must also validate the payload
+ * received from the other {@link JPAKEParticipant}.
+ * The received payload should be validated via
+ * {@link JPAKEParticipant#validateRound1PayloadReceived(JPAKERound1Payload)}.
+ */
+public class JPAKERound1Payload
+{
+ /**
+ * The id of the {@link JPAKEParticipant} who created/sent this payload.
+ */
+ private final String participantId;
+
+ /**
+ * The value of g^x1
+ */
+ private final BigInteger gx1;
+
+ /**
+ * The value of g^x2
+ */
+ private final BigInteger gx2;
+
+ /**
+ * The zero knowledge proof for x1.
+ * <p/>
+ * This is a two element array, containing {g^v, r} for x1.
+ */
+ private final BigInteger[] knowledgeProofForX1;
+
+ /**
+ * The zero knowledge proof for x2.
+ * <p/>
+ * This is a two element array, containing {g^v, r} for x2.
+ */
+ private final BigInteger[] knowledgeProofForX2;
+
+ public JPAKERound1Payload(
+ String participantId,
+ BigInteger gx1,
+ BigInteger gx2,
+ BigInteger[] knowledgeProofForX1,
+ BigInteger[] knowledgeProofForX2)
+ {
+ JPAKEUtil.validateNotNull(participantId, "participantId");
+ JPAKEUtil.validateNotNull(gx1, "gx1");
+ JPAKEUtil.validateNotNull(gx2, "gx2");
+ JPAKEUtil.validateNotNull(knowledgeProofForX1, "knowledgeProofForX1");
+ JPAKEUtil.validateNotNull(knowledgeProofForX2, "knowledgeProofForX2");
+
+ this.participantId = participantId;
+ this.gx1 = gx1;
+ this.gx2 = gx2;
+ this.knowledgeProofForX1 = Arrays.copyOf(knowledgeProofForX1, knowledgeProofForX1.length);
+ this.knowledgeProofForX2 = Arrays.copyOf(knowledgeProofForX2, knowledgeProofForX2.length);
+ }
+
+ public String getParticipantId()
+ {
+ return participantId;
+ }
+
+ public BigInteger getGx1()
+ {
+ return gx1;
+ }
+
+ public BigInteger getGx2()
+ {
+ return gx2;
+ }
+
+ public BigInteger[] getKnowledgeProofForX1()
+ {
+ return Arrays.copyOf(knowledgeProofForX1, knowledgeProofForX1.length);
+ }
+
+ public BigInteger[] getKnowledgeProofForX2()
+ {
+ return Arrays.copyOf(knowledgeProofForX2, knowledgeProofForX2.length);
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound2Payload.java b/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound2Payload.java
new file mode 100644
index 00000000..3df5c7b9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound2Payload.java
@@ -0,0 +1,68 @@
+package org.spongycastle.crypto.agreement.jpake;
+
+import java.math.BigInteger;
+
+import org.spongycastle.util.Arrays;
+
+/**
+ * The payload sent/received during the second round of a J-PAKE exchange.
+ * <p>
+ * Each {@link JPAKEParticipant} creates and sends an instance
+ * of this payload to the other {@link JPAKEParticipant}.
+ * The payload to send should be created via
+ * {@link JPAKEParticipant#createRound2PayloadToSend()}
+ * <p>
+ * Each {@link JPAKEParticipant} must also validate the payload
+ * received from the other {@link JPAKEParticipant}.
+ * The received payload should be validated via
+ * {@link JPAKEParticipant#validateRound2PayloadReceived(JPAKERound2Payload)}
+ */
+public class JPAKERound2Payload
+{
+ /**
+ * The id of the {@link JPAKEParticipant} who created/sent this payload.
+ */
+ private final String participantId;
+
+ /**
+ * The value of A, as computed during round 2.
+ */
+ private final BigInteger a;
+
+ /**
+ * The zero knowledge proof for x2 * s.
+ * <p/>
+ * This is a two element array, containing {g^v, r} for x2 * s.
+ */
+ private final BigInteger[] knowledgeProofForX2s;
+
+ public JPAKERound2Payload(
+ String participantId,
+ BigInteger a,
+ BigInteger[] knowledgeProofForX2s)
+ {
+ JPAKEUtil.validateNotNull(participantId, "participantId");
+ JPAKEUtil.validateNotNull(a, "a");
+ JPAKEUtil.validateNotNull(knowledgeProofForX2s, "knowledgeProofForX2s");
+
+ this.participantId = participantId;
+ this.a = a;
+ this.knowledgeProofForX2s = Arrays.copyOf(knowledgeProofForX2s, knowledgeProofForX2s.length);
+ }
+
+ public String getParticipantId()
+ {
+ return participantId;
+ }
+
+ public BigInteger getA()
+ {
+ return a;
+ }
+
+ public BigInteger[] getKnowledgeProofForX2s()
+ {
+ return Arrays.copyOf(knowledgeProofForX2s, knowledgeProofForX2s.length);
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound3Payload.java b/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound3Payload.java
new file mode 100644
index 00000000..bb4f6e14
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound3Payload.java
@@ -0,0 +1,49 @@
+package org.spongycastle.crypto.agreement.jpake;
+
+import java.math.BigInteger;
+
+/**
+ * The payload sent/received during the optional third round of a J-PAKE exchange,
+ * which is for explicit key confirmation.
+ * <p>
+ * Each {@link JPAKEParticipant} creates and sends an instance
+ * of this payload to the other {@link JPAKEParticipant}.
+ * The payload to send should be created via
+ * {@link JPAKEParticipant#createRound3PayloadToSend(BigInteger)}
+ * <p>
+ * Each {@link JPAKEParticipant} must also validate the payload
+ * received from the other {@link JPAKEParticipant}.
+ * The received payload should be validated via
+ * {@link JPAKEParticipant#validateRound3PayloadReceived(JPAKERound3Payload, BigInteger)}
+ */
+public class JPAKERound3Payload
+{
+ /**
+ * The id of the {@link JPAKEParticipant} who created/sent this payload.
+ */
+ private final String participantId;
+
+ /**
+ * The value of MacTag, as computed by round 3.
+ *
+ * @see JPAKEUtil#calculateMacTag(String, String, BigInteger, BigInteger, BigInteger, BigInteger, BigInteger, org.spongycastle.crypto.Digest)
+ */
+ private final BigInteger macTag;
+
+ public JPAKERound3Payload(String participantId, BigInteger magTag)
+ {
+ this.participantId = participantId;
+ this.macTag = magTag;
+ }
+
+ public String getParticipantId()
+ {
+ return participantId;
+ }
+
+ public BigInteger getMacTag()
+ {
+ return macTag;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEUtil.java b/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEUtil.java
new file mode 100644
index 00000000..39931f4a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEUtil.java
@@ -0,0 +1,495 @@
+package org.spongycastle.crypto.agreement.jpake;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.macs.HMac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.BigIntegers;
+import org.spongycastle.util.Strings;
+
+/**
+ * Primitives needed for a J-PAKE exchange.
+ * <p>
+ * The recommended way to perform a J-PAKE exchange is by using
+ * two {@link JPAKEParticipant}s. Internally, those participants
+ * call these primitive operations in {@link JPAKEUtil}.
+ * <p>
+ * The primitives, however, can be used without a {@link JPAKEParticipant}
+ * if needed.
+ */
+public class JPAKEUtil
+{
+ static final BigInteger ZERO = BigInteger.valueOf(0);
+ static final BigInteger ONE = BigInteger.valueOf(1);
+
+ /**
+ * Return a value that can be used as x1 or x3 during round 1.
+ * <p>
+ * The returned value is a random value in the range <tt>[0, q-1]</tt>.
+ */
+ public static BigInteger generateX1(
+ BigInteger q,
+ SecureRandom random)
+ {
+ BigInteger min = ZERO;
+ BigInteger max = q.subtract(ONE);
+ return BigIntegers.createRandomInRange(min, max, random);
+ }
+
+ /**
+ * Return a value that can be used as x2 or x4 during round 1.
+ * <p>
+ * The returned value is a random value in the range <tt>[1, q-1]</tt>.
+ */
+ public static BigInteger generateX2(
+ BigInteger q,
+ SecureRandom random)
+ {
+ BigInteger min = ONE;
+ BigInteger max = q.subtract(ONE);
+ return BigIntegers.createRandomInRange(min, max, random);
+ }
+
+ /**
+ * Converts the given password to a {@link BigInteger}
+ * for use in arithmetic calculations.
+ */
+ public static BigInteger calculateS(char[] password)
+ {
+ return new BigInteger(Strings.toUTF8ByteArray(password));
+ }
+
+ /**
+ * Calculate g^x mod p as done in round 1.
+ */
+ public static BigInteger calculateGx(
+ BigInteger p,
+ BigInteger g,
+ BigInteger x)
+ {
+ return g.modPow(x, p);
+ }
+
+
+ /**
+ * Calculate ga as done in round 2.
+ */
+ public static BigInteger calculateGA(
+ BigInteger p,
+ BigInteger gx1,
+ BigInteger gx3,
+ BigInteger gx4)
+ {
+ // ga = g^(x1+x3+x4) = g^x1 * g^x3 * g^x4
+ return gx1.multiply(gx3).multiply(gx4).mod(p);
+ }
+
+
+ /**
+ * Calculate x2 * s as done in round 2.
+ */
+ public static BigInteger calculateX2s(
+ BigInteger q,
+ BigInteger x2,
+ BigInteger s)
+ {
+ return x2.multiply(s).mod(q);
+ }
+
+
+ /**
+ * Calculate A as done in round 2.
+ */
+ public static BigInteger calculateA(
+ BigInteger p,
+ BigInteger q,
+ BigInteger gA,
+ BigInteger x2s)
+ {
+ // A = ga^(x*s)
+ return gA.modPow(x2s, p);
+ }
+
+ /**
+ * Calculate a zero knowledge proof of x using Schnorr's signature.
+ * The returned array has two elements {g^v, r = v-x*h} for x.
+ */
+ public static BigInteger[] calculateZeroKnowledgeProof(
+ BigInteger p,
+ BigInteger q,
+ BigInteger g,
+ BigInteger gx,
+ BigInteger x,
+ String participantId,
+ Digest digest,
+ SecureRandom random)
+ {
+ BigInteger[] zeroKnowledgeProof = new BigInteger[2];
+
+ /* Generate a random v, and compute g^v */
+ BigInteger vMin = ZERO;
+ BigInteger vMax = q.subtract(ONE);
+ BigInteger v = BigIntegers.createRandomInRange(vMin, vMax, random);
+
+ BigInteger gv = g.modPow(v, p);
+ BigInteger h = calculateHashForZeroKnowledgeProof(g, gv, gx, participantId, digest); // h
+
+ zeroKnowledgeProof[0] = gv;
+ zeroKnowledgeProof[1] = v.subtract(x.multiply(h)).mod(q); // r = v-x*h
+
+ return zeroKnowledgeProof;
+ }
+
+ private static BigInteger calculateHashForZeroKnowledgeProof(
+ BigInteger g,
+ BigInteger gr,
+ BigInteger gx,
+ String participantId,
+ Digest digest)
+ {
+ digest.reset();
+
+ updateDigestIncludingSize(digest, g);
+
+ updateDigestIncludingSize(digest, gr);
+
+ updateDigestIncludingSize(digest, gx);
+
+ updateDigestIncludingSize(digest, participantId);
+
+ byte[] output = new byte[digest.getDigestSize()];
+ digest.doFinal(output, 0);
+
+ return new BigInteger(output);
+ }
+
+ /**
+ * Validates that g^x4 is not 1.
+ *
+ * @throws CryptoException if g^x4 is 1
+ */
+ public static void validateGx4(BigInteger gx4)
+ throws CryptoException
+ {
+ if (gx4.equals(ONE))
+ {
+ throw new CryptoException("g^x validation failed. g^x should not be 1.");
+ }
+ }
+
+ /**
+ * Validates that ga is not 1.
+ * <p>
+ * As described by Feng Hao...
+ * <p>
+ * <blockquote>
+ * Alice could simply check ga != 1 to ensure it is a generator.
+ * In fact, as we will explain in Section 3, (x1 + x3 + x4 ) is random over Zq even in the face of active attacks.
+ * Hence, the probability for ga = 1 is extremely small - on the order of 2^160 for 160-bit q.
+ * </blockquote>
+ *
+ * @throws CryptoException if ga is 1
+ */
+ public static void validateGa(BigInteger ga)
+ throws CryptoException
+ {
+ if (ga.equals(ONE))
+ {
+ throw new CryptoException("ga is equal to 1. It should not be. The chances of this happening are on the order of 2^160 for a 160-bit q. Try again.");
+ }
+ }
+
+ /**
+ * Validates the zero knowledge proof (generated by
+ * {@link #calculateZeroKnowledgeProof(BigInteger, BigInteger, BigInteger, BigInteger, BigInteger, String, Digest, SecureRandom)})
+ * is correct.
+ *
+ * @throws CryptoException if the zero knowledge proof is not correct
+ */
+ public static void validateZeroKnowledgeProof(
+ BigInteger p,
+ BigInteger q,
+ BigInteger g,
+ BigInteger gx,
+ BigInteger[] zeroKnowledgeProof,
+ String participantId,
+ Digest digest)
+ throws CryptoException
+ {
+
+ /* sig={g^v,r} */
+ BigInteger gv = zeroKnowledgeProof[0];
+ BigInteger r = zeroKnowledgeProof[1];
+
+ BigInteger h = calculateHashForZeroKnowledgeProof(g, gv, gx, participantId, digest);
+ if (!(gx.compareTo(ZERO) == 1 && // g^x > 0
+ gx.compareTo(p) == -1 && // g^x < p
+ gx.modPow(q, p).compareTo(ONE) == 0 && // g^x^q mod q = 1
+ /*
+ * Below, I took an straightforward way to compute g^r * g^x^h,
+ * which needs 2 exp. Using a simultaneous computation technique
+ * would only need 1 exp.
+ */
+ g.modPow(r, p).multiply(gx.modPow(h, p)).mod(p).compareTo(gv) == 0)) // g^v=g^r * g^x^h
+ {
+ throw new CryptoException("Zero-knowledge proof validation failed");
+ }
+ }
+
+ /**
+ * Calculates the keying material, which can be done after round 2 has completed.
+ * A session key must be derived from this key material using a secure key derivation function (KDF).
+ * The KDF used to derive the key is handled externally (i.e. not by {@link JPAKEParticipant}).
+ * <pre>
+ * KeyingMaterial = (B/g^{x2*x4*s})^x2
+ * </pre>
+ */
+ public static BigInteger calculateKeyingMaterial(
+ BigInteger p,
+ BigInteger q,
+ BigInteger gx4,
+ BigInteger x2,
+ BigInteger s,
+ BigInteger B)
+ {
+ return gx4.modPow(x2.multiply(s).negate().mod(q), p).multiply(B).modPow(x2, p);
+ }
+
+ /**
+ * Validates that the given participant ids are not equal.
+ * (For the J-PAKE exchange, each participant must use a unique id.)
+ *
+ * @throws CryptoException if the participantId strings are equal.
+ */
+ public static void validateParticipantIdsDiffer(String participantId1, String participantId2)
+ throws CryptoException
+ {
+ if (participantId1.equals(participantId2))
+ {
+ throw new CryptoException(
+ "Both participants are using the same participantId ("
+ + participantId1
+ + "). This is not allowed. "
+ + "Each participant must use a unique participantId.");
+ }
+ }
+
+ /**
+ * Validates that the given participant ids are equal.
+ * This is used to ensure that the payloads received from
+ * each round all come from the same participant.
+ *
+ * @throws CryptoException if the participantId strings are equal.
+ */
+ public static void validateParticipantIdsEqual(String expectedParticipantId, String actualParticipantId)
+ throws CryptoException
+ {
+ if (!expectedParticipantId.equals(actualParticipantId))
+ {
+ throw new CryptoException(
+ "Received payload from incorrect partner ("
+ + actualParticipantId
+ + "). Expected to receive payload from "
+ + expectedParticipantId
+ + ".");
+ }
+ }
+
+ /**
+ * Validates that the given object is not null.
+ *
+ * @param object object in question
+ * @param description name of the object (to be used in exception message)
+ * @throws NullPointerException if the object is null.
+ */
+ public static void validateNotNull(Object object, String description)
+ {
+ if (object == null)
+ {
+ throw new NullPointerException(description + " must not be null");
+ }
+ }
+
+ /**
+ * Calculates the MacTag (to be used for key confirmation), as defined by
+ * <a href="http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf">NIST SP 800-56A Revision 1</a>,
+ * Section 8.2 Unilateral Key Confirmation for Key Agreement Schemes.
+ * <pre>
+ * MacTag = HMAC(MacKey, MacLen, MacData)
+ *
+ * MacKey = H(K || "JPAKE_KC")
+ *
+ * MacData = "KC_1_U" || participantId || partnerParticipantId || gx1 || gx2 || gx3 || gx4
+ *
+ * Note that both participants use "KC_1_U" because the sender of the round 3 message
+ * is always the initiator for key confirmation.
+ *
+ * HMAC = {@link HMac} used with the given {@link Digest}
+ * H = The given {@link Digest}
+ * MacLen = length of MacTag
+ * </pre>
+ */
+ public static BigInteger calculateMacTag(
+ String participantId,
+ String partnerParticipantId,
+ BigInteger gx1,
+ BigInteger gx2,
+ BigInteger gx3,
+ BigInteger gx4,
+ BigInteger keyingMaterial,
+ Digest digest)
+ {
+ byte[] macKey = calculateMacKey(
+ keyingMaterial,
+ digest);
+
+ HMac mac = new HMac(digest);
+ byte[] macOutput = new byte[mac.getMacSize()];
+ mac.init(new KeyParameter(macKey));
+
+ /*
+ * MacData = "KC_1_U" || participantId_Alice || participantId_Bob || gx1 || gx2 || gx3 || gx4.
+ */
+ updateMac(mac, "KC_1_U");
+ updateMac(mac, participantId);
+ updateMac(mac, partnerParticipantId);
+ updateMac(mac, gx1);
+ updateMac(mac, gx2);
+ updateMac(mac, gx3);
+ updateMac(mac, gx4);
+
+ mac.doFinal(macOutput, 0);
+
+ Arrays.fill(macKey, (byte)0);
+
+ return new BigInteger(macOutput);
+
+ }
+
+ /**
+ * Calculates the MacKey (i.e. the key to use when calculating the MagTag for key confirmation).
+ * <pre>
+ * MacKey = H(K || "JPAKE_KC")
+ * </pre>
+ */
+ private static byte[] calculateMacKey(BigInteger keyingMaterial, Digest digest)
+ {
+ digest.reset();
+
+ updateDigest(digest, keyingMaterial);
+ /*
+ * This constant is used to ensure that the macKey is NOT the same as the derived key.
+ */
+ updateDigest(digest, "JPAKE_KC");
+
+ byte[] output = new byte[digest.getDigestSize()];
+ digest.doFinal(output, 0);
+
+ return output;
+ }
+
+ /**
+ * Validates the MacTag received from the partner participant.
+ *
+ * @param partnerMacTag the MacTag received from the partner.
+ * @throws CryptoException if the participantId strings are equal.
+ */
+ public static void validateMacTag(
+ String participantId,
+ String partnerParticipantId,
+ BigInteger gx1,
+ BigInteger gx2,
+ BigInteger gx3,
+ BigInteger gx4,
+ BigInteger keyingMaterial,
+ Digest digest,
+ BigInteger partnerMacTag)
+ throws CryptoException
+ {
+ /*
+ * Calculate the expected MacTag using the parameters as the partner
+ * would have used when the partner called calculateMacTag.
+ *
+ * i.e. basically all the parameters are reversed.
+ * participantId <-> partnerParticipantId
+ * x1 <-> x3
+ * x2 <-> x4
+ */
+ BigInteger expectedMacTag = calculateMacTag(
+ partnerParticipantId,
+ participantId,
+ gx3,
+ gx4,
+ gx1,
+ gx2,
+ keyingMaterial,
+ digest);
+
+ if (!expectedMacTag.equals(partnerMacTag))
+ {
+ throw new CryptoException(
+ "Partner MacTag validation failed. "
+ + "Therefore, the password, MAC, or digest algorithm of each participant does not match.");
+ }
+ }
+
+ private static void updateDigest(Digest digest, BigInteger bigInteger)
+ {
+ byte[] byteArray = BigIntegers.asUnsignedByteArray(bigInteger);
+ digest.update(byteArray, 0, byteArray.length);
+ Arrays.fill(byteArray, (byte)0);
+ }
+
+ private static void updateDigestIncludingSize(Digest digest, BigInteger bigInteger)
+ {
+ byte[] byteArray = BigIntegers.asUnsignedByteArray(bigInteger);
+ digest.update(intToByteArray(byteArray.length), 0, 4);
+ digest.update(byteArray, 0, byteArray.length);
+ Arrays.fill(byteArray, (byte)0);
+ }
+
+ private static void updateDigest(Digest digest, String string)
+ {
+ byte[] byteArray = Strings.toUTF8ByteArray(string);
+ digest.update(byteArray, 0, byteArray.length);
+ Arrays.fill(byteArray, (byte)0);
+ }
+
+ private static void updateDigestIncludingSize(Digest digest, String string)
+ {
+ byte[] byteArray = Strings.toUTF8ByteArray(string);
+ digest.update(intToByteArray(byteArray.length), 0, 4);
+ digest.update(byteArray, 0, byteArray.length);
+ Arrays.fill(byteArray, (byte)0);
+ }
+
+ private static void updateMac(Mac mac, BigInteger bigInteger)
+ {
+ byte[] byteArray = BigIntegers.asUnsignedByteArray(bigInteger);
+ mac.update(byteArray, 0, byteArray.length);
+ Arrays.fill(byteArray, (byte)0);
+ }
+
+ private static void updateMac(Mac mac, String string)
+ {
+ byte[] byteArray = Strings.toUTF8ByteArray(string);
+ mac.update(byteArray, 0, byteArray.length);
+ Arrays.fill(byteArray, (byte)0);
+ }
+
+ private static byte[] intToByteArray(int value)
+ {
+ return new byte[]{
+ (byte)(value >>> 24),
+ (byte)(value >>> 16),
+ (byte)(value >>> 8),
+ (byte)value
+ };
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/agreement/kdf/DHKDFParameters.java b/core/src/main/java/org/spongycastle/crypto/agreement/kdf/DHKDFParameters.java
new file mode 100644
index 00000000..5f3f4c52
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/agreement/kdf/DHKDFParameters.java
@@ -0,0 +1,53 @@
+package org.spongycastle.crypto.agreement.kdf;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.crypto.DerivationParameters;
+
+public class DHKDFParameters
+ implements DerivationParameters
+{
+ private ASN1ObjectIdentifier algorithm;
+ private int keySize;
+ private byte[] z;
+ private byte[] extraInfo;
+
+ public DHKDFParameters(
+ ASN1ObjectIdentifier algorithm,
+ int keySize,
+ byte[] z)
+ {
+ this(algorithm, keySize, z, null);
+ }
+
+ public DHKDFParameters(
+ ASN1ObjectIdentifier algorithm,
+ int keySize,
+ byte[] z,
+ byte[] extraInfo)
+ {
+ this.algorithm = algorithm;
+ this.keySize = keySize;
+ this.z = z;
+ this.extraInfo = extraInfo;
+ }
+
+ public ASN1ObjectIdentifier getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ public int getKeySize()
+ {
+ return keySize;
+ }
+
+ public byte[] getZ()
+ {
+ return z;
+ }
+
+ public byte[] getExtraInfo()
+ {
+ return extraInfo;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/agreement/kdf/DHKEKGenerator.java b/core/src/main/java/org/spongycastle/crypto/agreement/kdf/DHKEKGenerator.java
new file mode 100644
index 00000000..70cf630d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/agreement/kdf/DHKEKGenerator.java
@@ -0,0 +1,131 @@
+package org.spongycastle.crypto.agreement.kdf;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Encoding;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.DerivationFunction;
+import org.spongycastle.crypto.DerivationParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.util.Pack;
+
+/**
+ * RFC 2631 Diffie-hellman KEK derivation function.
+ */
+public class DHKEKGenerator
+ implements DerivationFunction
+{
+ private final Digest digest;
+
+ private ASN1ObjectIdentifier algorithm;
+ private int keySize;
+ private byte[] z;
+ private byte[] partyAInfo;
+
+ public DHKEKGenerator(
+ Digest digest)
+ {
+ this.digest = digest;
+ }
+
+ public void init(DerivationParameters param)
+ {
+ DHKDFParameters params = (DHKDFParameters)param;
+
+ this.algorithm = params.getAlgorithm();
+ this.keySize = params.getKeySize();
+ this.z = params.getZ();
+ this.partyAInfo = params.getExtraInfo();
+ }
+
+ public Digest getDigest()
+ {
+ return digest;
+ }
+
+ public int generateBytes(byte[] out, int outOff, int len)
+ throws DataLengthException, IllegalArgumentException
+ {
+ if ((out.length - len) < outOff)
+ {
+ throw new DataLengthException("output buffer too small");
+ }
+
+ long oBytes = len;
+ int outLen = digest.getDigestSize();
+
+ //
+ // this is at odds with the standard implementation, the
+ // maximum value should be hBits * (2^32 - 1) where hBits
+ // is the digest output size in bits. We can't have an
+ // array with a long index at the moment...
+ //
+ if (oBytes > ((2L << 32) - 1))
+ {
+ throw new IllegalArgumentException("Output length too large");
+ }
+
+ int cThreshold = (int)((oBytes + outLen - 1) / outLen);
+
+ byte[] dig = new byte[digest.getDigestSize()];
+
+ int counter = 1;
+
+ for (int i = 0; i < cThreshold; i++)
+ {
+ digest.update(z, 0, z.length);
+
+ // OtherInfo
+ ASN1EncodableVector v1 = new ASN1EncodableVector();
+ // KeySpecificInfo
+ ASN1EncodableVector v2 = new ASN1EncodableVector();
+
+ v2.add(algorithm);
+ v2.add(new DEROctetString(Pack.intToBigEndian(counter)));
+
+ v1.add(new DERSequence(v2));
+
+ if (partyAInfo != null)
+ {
+ v1.add(new DERTaggedObject(true, 0, new DEROctetString(partyAInfo)));
+ }
+
+ v1.add(new DERTaggedObject(true, 2, new DEROctetString(Pack.intToBigEndian(keySize))));
+
+ try
+ {
+ byte[] other = new DERSequence(v1).getEncoded(ASN1Encoding.DER);
+
+ digest.update(other, 0, other.length);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("unable to encode parameter info: " + e.getMessage());
+ }
+
+ digest.doFinal(dig, 0);
+
+ if (len > outLen)
+ {
+ System.arraycopy(dig, 0, out, outOff, outLen);
+ outOff += outLen;
+ len -= outLen;
+ }
+ else
+ {
+ System.arraycopy(dig, 0, out, outOff, len);
+ }
+
+ counter++;
+ }
+
+ digest.reset();
+
+ return (int)oBytes;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/agreement/kdf/ECDHKEKGenerator.java b/core/src/main/java/org/spongycastle/crypto/agreement/kdf/ECDHKEKGenerator.java
new file mode 100644
index 00000000..65c564e8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/agreement/kdf/ECDHKEKGenerator.java
@@ -0,0 +1,74 @@
+package org.spongycastle.crypto.agreement.kdf;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Encoding;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.DERNull;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.DerivationParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.DigestDerivationFunction;
+import org.spongycastle.crypto.generators.KDF2BytesGenerator;
+import org.spongycastle.crypto.params.KDFParameters;
+import org.spongycastle.util.Pack;
+
+/**
+ * X9.63 based key derivation function for ECDH CMS.
+ */
+public class ECDHKEKGenerator
+ implements DigestDerivationFunction
+{
+ private DigestDerivationFunction kdf;
+
+ private ASN1ObjectIdentifier algorithm;
+ private int keySize;
+ private byte[] z;
+
+ public ECDHKEKGenerator(
+ Digest digest)
+ {
+ this.kdf = new KDF2BytesGenerator(digest);
+ }
+
+ public void init(DerivationParameters param)
+ {
+ DHKDFParameters params = (DHKDFParameters)param;
+
+ this.algorithm = params.getAlgorithm();
+ this.keySize = params.getKeySize();
+ this.z = params.getZ();
+ }
+
+ public Digest getDigest()
+ {
+ return kdf.getDigest();
+ }
+
+ public int generateBytes(byte[] out, int outOff, int len)
+ throws DataLengthException, IllegalArgumentException
+ {
+ // TODO Create an ASN.1 class for this (RFC3278)
+ // ECC-CMS-SharedInfo
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new AlgorithmIdentifier(algorithm, DERNull.INSTANCE));
+ v.add(new DERTaggedObject(true, 2, new DEROctetString(Pack.intToBigEndian(keySize))));
+
+ try
+ {
+ kdf.init(new KDFParameters(z, new DERSequence(v).getEncoded(ASN1Encoding.DER)));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("unable to initialise kdf: " + e.getMessage());
+ }
+
+ return kdf.generateBytes(out, outOff, len);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Client.java b/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Client.java
new file mode 100644
index 00000000..c6ee4dbe
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Client.java
@@ -0,0 +1,150 @@
+package org.spongycastle.crypto.agreement.srp;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.Digest;
+
+/**
+ * Implements the client side SRP-6a protocol. Note that this class is stateful, and therefore NOT threadsafe.
+ * This implementation of SRP is based on the optimized message sequence put forth by Thomas Wu in the paper
+ * "SRP-6: Improvements and Refinements to the Secure Remote Password Protocol, 2002"
+ */
+public class SRP6Client
+{
+ protected BigInteger N;
+ protected BigInteger g;
+
+ protected BigInteger a;
+ protected BigInteger A;
+
+ protected BigInteger B;
+
+ protected BigInteger x;
+ protected BigInteger u;
+ protected BigInteger S;
+
+ protected BigInteger M1;
+ protected BigInteger M2;
+ protected BigInteger Key;
+
+ protected Digest digest;
+ protected SecureRandom random;
+
+ public SRP6Client()
+ {
+ }
+
+ /**
+ * Initialises the client to begin new authentication attempt
+ * @param N The safe prime associated with the client's verifier
+ * @param g The group parameter associated with the client's verifier
+ * @param digest The digest algorithm associated with the client's verifier
+ * @param random For key generation
+ */
+ public void init(BigInteger N, BigInteger g, Digest digest, SecureRandom random)
+ {
+ this.N = N;
+ this.g = g;
+ this.digest = digest;
+ this.random = random;
+ }
+
+ /**
+ * Generates client's credentials given the client's salt, identity and password
+ * @param salt The salt used in the client's verifier.
+ * @param identity The user's identity (eg. username)
+ * @param password The user's password
+ * @return Client's public value to send to server
+ */
+ public BigInteger generateClientCredentials(byte[] salt, byte[] identity, byte[] password)
+ {
+ this.x = SRP6Util.calculateX(digest, N, salt, identity, password);
+ this.a = selectPrivateValue();
+ this.A = g.modPow(a, N);
+
+ return A;
+ }
+
+ /**
+ * Generates the secret S given the server's credentials
+ * @param serverB The server's credentials
+ * @return Client's verification message for the server
+ * @throws CryptoException If server's credentials are invalid
+ */
+ public BigInteger calculateSecret(BigInteger serverB) throws CryptoException
+ {
+ this.B = SRP6Util.validatePublicValue(N, serverB);
+ this.u = SRP6Util.calculateU(digest, N, A, B);
+ this.S = calculateS();
+
+ return S;
+ }
+
+ protected BigInteger selectPrivateValue()
+ {
+ return SRP6Util.generatePrivateValue(digest, N, g, random);
+ }
+
+ private BigInteger calculateS()
+ {
+ BigInteger k = SRP6Util.calculateK(digest, N, g);
+ BigInteger exp = u.multiply(x).add(a);
+ BigInteger tmp = g.modPow(x, N).multiply(k).mod(N);
+ return B.subtract(tmp).mod(N).modPow(exp, N);
+ }
+
+ /**
+ * Computes the client evidence message M1 using the previously received values.
+ * To be called after calculating the secret S.
+ * @return M1: the client side generated evidence message
+ * @throws CryptoException
+ */
+ public BigInteger calculateClientEvidenceMessage() throws CryptoException{
+ // verify pre-requirements
+ if ((this.A==null)||(this.B==null)||(this.S==null)){
+ throw new CryptoException("Impossible to compute M1: " +
+ "some data are missing from the previous operations (A,B,S)");
+ }
+ // compute the client evidence message 'M1'
+ this.M1 = SRP6Util.calculateM1(digest, N, A, B, S);
+ return M1;
+ }
+
+ /** Authenticates the server evidence message M2 received and saves it only if correct.
+ * @param M2: the server side generated evidence message
+ * @return A boolean indicating if the server message M2 was the expected one.
+ * @throws CryptoException
+ */
+ public boolean verifyServerEvidenceMessage(BigInteger serverM2) throws CryptoException{
+ //verify pre-requirements
+ if ((this.A==null)||(this.M1==null)||(this.S==null)){
+ throw new CryptoException("Impossible to compute and verify M2: " +
+ "some data are missing from the previous operations (A,M1,S)");
+ }
+ // Compute the own server evidence message 'M2'
+ BigInteger computedM2 = SRP6Util.calculateM2(digest, N, A, M1, S);
+ if (computedM2.equals(serverM2)){
+ this.M2 = serverM2;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Computes the final session key as a result of the SRP successful mutual authentication
+ * To be called after verifying the server evidence message M2.
+ * @return Key: the mutually authenticated symmetric session key
+ * @throws CryptoException
+ */
+ public BigInteger calculateSessionKey() throws CryptoException{
+ //verify pre-requirements (here we enforce a previous calculation of M1 and M2)
+ if ((this.S==null)||(this.M1==null)||(this.M2==null)){
+ throw new CryptoException("Impossible to compute Key: " +
+ "some data are missing from the previous operations (S,M1,M2)");
+ }
+ this.Key = SRP6Util.calculateKey(digest, N, S);
+ return Key;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Server.java b/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Server.java
new file mode 100644
index 00000000..efbdd0ab
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Server.java
@@ -0,0 +1,148 @@
+package org.spongycastle.crypto.agreement.srp;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.Digest;
+
+/**
+ * Implements the server side SRP-6a protocol. Note that this class is stateful, and therefore NOT threadsafe.
+ * This implementation of SRP is based on the optimized message sequence put forth by Thomas Wu in the paper
+ * "SRP-6: Improvements and Refinements to the Secure Remote Password Protocol, 2002"
+ */
+public class SRP6Server
+{
+ protected BigInteger N;
+ protected BigInteger g;
+ protected BigInteger v;
+
+ protected SecureRandom random;
+ protected Digest digest;
+
+ protected BigInteger A;
+
+ protected BigInteger b;
+ protected BigInteger B;
+
+ protected BigInteger u;
+ protected BigInteger S;
+ protected BigInteger M1;
+ protected BigInteger M2;
+ protected BigInteger Key;
+
+ public SRP6Server()
+ {
+ }
+
+ /**
+ * Initialises the server to accept a new client authentication attempt
+ * @param N The safe prime associated with the client's verifier
+ * @param g The group parameter associated with the client's verifier
+ * @param v The client's verifier
+ * @param digest The digest algorithm associated with the client's verifier
+ * @param random For key generation
+ */
+ public void init(BigInteger N, BigInteger g, BigInteger v, Digest digest, SecureRandom random)
+ {
+ this.N = N;
+ this.g = g;
+ this.v = v;
+
+ this.random = random;
+ this.digest = digest;
+ }
+
+ /**
+ * Generates the server's credentials that are to be sent to the client.
+ * @return The server's public value to the client
+ */
+ public BigInteger generateServerCredentials()
+ {
+ BigInteger k = SRP6Util.calculateK(digest, N, g);
+ this.b = selectPrivateValue();
+ this.B = k.multiply(v).mod(N).add(g.modPow(b, N)).mod(N);
+
+ return B;
+ }
+
+ /**
+ * Processes the client's credentials. If valid the shared secret is generated and returned.
+ * @param clientA The client's credentials
+ * @return A shared secret BigInteger
+ * @throws CryptoException If client's credentials are invalid
+ */
+ public BigInteger calculateSecret(BigInteger clientA) throws CryptoException
+ {
+ this.A = SRP6Util.validatePublicValue(N, clientA);
+ this.u = SRP6Util.calculateU(digest, N, A, B);
+ this.S = calculateS();
+
+ return S;
+ }
+
+ protected BigInteger selectPrivateValue()
+ {
+ return SRP6Util.generatePrivateValue(digest, N, g, random);
+ }
+
+ private BigInteger calculateS()
+ {
+ return v.modPow(u, N).multiply(A).mod(N).modPow(b, N);
+ }
+
+ /**
+ * Authenticates the received client evidence message M1 and saves it only if correct.
+ * To be called after calculating the secret S.
+ * @param M1: the client side generated evidence message
+ * @return A boolean indicating if the client message M1 was the expected one.
+ * @throws CryptoException
+ */
+ public boolean verifyClientEvidenceMessage(BigInteger clientM1) throws CryptoException{
+ //verify pre-requirements
+ if ((this.A==null)||(this.B==null)||(this.S==null)){
+ throw new CryptoException("Impossible to compute and verify M1: " +
+ "some data are missing from the previous operations (A,B,S)");
+ }
+ // Compute the own client evidence message 'M1'
+ BigInteger computedM1 = SRP6Util.calculateM1(digest, N, A, B, S);
+ if (computedM1.equals(clientM1)){
+ this.M1 = clientM1;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Computes the server evidence message M2 using the previously verified values.
+ * To be called after successfully verifying the client evidence message M1.
+ * @return M2: the server side generated evidence message
+ * @throws CryptoException
+ */
+ public BigInteger calculateServerEvidenceMessage() throws CryptoException{
+ //verify pre-requirements
+ if ((this.A==null)||(this.M1==null)||(this.S==null)){
+ throw new CryptoException("Impossible to compute M2: " +
+ "some data are missing from the previous operations (A,M1,S)");
+ }
+ // Compute the server evidence message 'M2'
+ this.M2 = SRP6Util.calculateM2(digest, N, A, M1, S);
+ return M2;
+ }
+
+ /**
+ * Computes the final session key as a result of the SRP successful mutual authentication
+ * To be called after calculating the server evidence message M2.
+ * @return Key: the mutual authenticated symmetric session key
+ * @throws CryptoException
+ */
+ public BigInteger calculateSessionKey() throws CryptoException{
+ //verify pre-requirements
+ if ((this.S==null)||(this.M1==null)||(this.M2==null)){
+ throw new CryptoException("Impossible to compute Key: " +
+ "some data are missing from the previous operations (S,M1,M2)");
+ }
+ this.Key = SRP6Util.calculateKey(digest, N, S);
+ return Key;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Util.java b/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Util.java
new file mode 100644
index 00000000..25d5b9a7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Util.java
@@ -0,0 +1,154 @@
+package org.spongycastle.crypto.agreement.srp;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.util.BigIntegers;
+
+public class SRP6Util
+{
+ private static BigInteger ZERO = BigInteger.valueOf(0);
+ private static BigInteger ONE = BigInteger.valueOf(1);
+
+ public static BigInteger calculateK(Digest digest, BigInteger N, BigInteger g)
+ {
+ return hashPaddedPair(digest, N, N, g);
+ }
+
+ public static BigInteger calculateU(Digest digest, BigInteger N, BigInteger A, BigInteger B)
+ {
+ return hashPaddedPair(digest, N, A, B);
+ }
+
+ public static BigInteger calculateX(Digest digest, BigInteger N, byte[] salt, byte[] identity, byte[] password)
+ {
+ byte[] output = new byte[digest.getDigestSize()];
+
+ digest.update(identity, 0, identity.length);
+ digest.update((byte)':');
+ digest.update(password, 0, password.length);
+ digest.doFinal(output, 0);
+
+ digest.update(salt, 0, salt.length);
+ digest.update(output, 0, output.length);
+ digest.doFinal(output, 0);
+
+ return new BigInteger(1, output);
+ }
+
+ public static BigInteger generatePrivateValue(Digest digest, BigInteger N, BigInteger g, SecureRandom random)
+ {
+ int minBits = Math.min(256, N.bitLength() / 2);
+ BigInteger min = ONE.shiftLeft(minBits - 1);
+ BigInteger max = N.subtract(ONE);
+
+ return BigIntegers.createRandomInRange(min, max, random);
+ }
+
+ public static BigInteger validatePublicValue(BigInteger N, BigInteger val)
+ throws CryptoException
+ {
+ val = val.mod(N);
+
+ // Check that val % N != 0
+ if (val.equals(ZERO))
+ {
+ throw new CryptoException("Invalid public value: 0");
+ }
+
+ return val;
+ }
+ /**
+ * Computes the client evidence message (M1) according to the standard routine:
+ * M1 = H( A | B | S )
+ * @param digest The Digest used as the hashing function H
+ * @param N Modulus used to get the pad length
+ * @param A The public client value
+ * @param B The public server value
+ * @param S The secret calculated by both sides
+ * @return M1 The calculated client evidence message
+ */
+ public static BigInteger calculateM1(Digest digest, BigInteger N, BigInteger A, BigInteger B, BigInteger S) {
+ BigInteger M1 = hashPaddedTriplet(digest,N,A,B,S);
+ return M1;
+ }
+
+ /**
+ * Computes the server evidence message (M2) according to the standard routine:
+ * M2 = H( A | M1 | S )
+ * @param digest The Digest used as the hashing function H
+ * @param N Modulus used to get the pad length
+ * @param A The public client value
+ * @param M1 The client evidence message
+ * @param S The secret calculated by both sides
+ * @return M2 The calculated server evidence message
+ */
+ public static BigInteger calculateM2(Digest digest, BigInteger N, BigInteger A, BigInteger M1, BigInteger S){
+ BigInteger M2 = hashPaddedTriplet(digest,N,A,M1,S);
+ return M2;
+ }
+
+ /**
+ * Computes the final Key according to the standard routine: Key = H(S)
+ * @param digest The Digest used as the hashing function H
+ * @param N Modulus used to get the pad length
+ * @param S The secret calculated by both sides
+ * @return
+ */
+ public static BigInteger calculateKey(Digest digest, BigInteger N, BigInteger S) {
+ int padLength = (N.bitLength() + 7) / 8;
+ byte[] _S = getPadded(S,padLength);
+ digest.update(_S, 0, _S.length);
+
+ byte[] output = new byte[digest.getDigestSize()];
+ digest.doFinal(output, 0);
+ return new BigInteger(1, output);
+ }
+
+ private static BigInteger hashPaddedTriplet(Digest digest, BigInteger N, BigInteger n1, BigInteger n2, BigInteger n3){
+ int padLength = (N.bitLength() + 7) / 8;
+
+ byte[] n1_bytes = getPadded(n1, padLength);
+ byte[] n2_bytes = getPadded(n2, padLength);
+ byte[] n3_bytes = getPadded(n3, padLength);
+
+ digest.update(n1_bytes, 0, n1_bytes.length);
+ digest.update(n2_bytes, 0, n2_bytes.length);
+ digest.update(n3_bytes, 0, n3_bytes.length);
+
+ byte[] output = new byte[digest.getDigestSize()];
+ digest.doFinal(output, 0);
+
+ return new BigInteger(1, output);
+ }
+
+ private static BigInteger hashPaddedPair(Digest digest, BigInteger N, BigInteger n1, BigInteger n2)
+ {
+ int padLength = (N.bitLength() + 7) / 8;
+
+ byte[] n1_bytes = getPadded(n1, padLength);
+ byte[] n2_bytes = getPadded(n2, padLength);
+
+ digest.update(n1_bytes, 0, n1_bytes.length);
+ digest.update(n2_bytes, 0, n2_bytes.length);
+
+ byte[] output = new byte[digest.getDigestSize()];
+ digest.doFinal(output, 0);
+
+ return new BigInteger(1, output);
+ }
+
+ private static byte[] getPadded(BigInteger n, int length)
+ {
+ byte[] bs = BigIntegers.asUnsignedByteArray(n);
+ if (bs.length < length)
+ {
+ byte[] tmp = new byte[length];
+ System.arraycopy(bs, 0, tmp, length - bs.length, bs.length);
+ bs = tmp;
+ }
+ return bs;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6VerifierGenerator.java b/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6VerifierGenerator.java
new file mode 100644
index 00000000..0324af18
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6VerifierGenerator.java
@@ -0,0 +1,47 @@
+package org.spongycastle.crypto.agreement.srp;
+
+import java.math.BigInteger;
+
+import org.spongycastle.crypto.Digest;
+
+/**
+ * Generates new SRP verifier for user
+ */
+public class SRP6VerifierGenerator
+{
+ protected BigInteger N;
+ protected BigInteger g;
+ protected Digest digest;
+
+ public SRP6VerifierGenerator()
+ {
+ }
+
+ /**
+ * Initialises generator to create new verifiers
+ * @param N The safe prime to use (see DHParametersGenerator)
+ * @param g The group parameter to use (see DHParametersGenerator)
+ * @param digest The digest to use. The same digest type will need to be used later for the actual authentication
+ * attempt. Also note that the final session key size is dependent on the chosen digest.
+ */
+ public void init(BigInteger N, BigInteger g, Digest digest)
+ {
+ this.N = N;
+ this.g = g;
+ this.digest = digest;
+ }
+
+ /**
+ * Creates a new SRP verifier
+ * @param salt The salt to use, generally should be large and random
+ * @param identity The user's identifying information (eg. username)
+ * @param password The user's password
+ * @return A new verifier for use in future SRP authentication
+ */
+ public BigInteger generateVerifier(byte[] salt, byte[] identity, byte[] password)
+ {
+ BigInteger x = SRP6Util.calculateX(digest, N, salt, identity, password);
+
+ return g.modPow(x, N);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/commitments/GeneralHashCommitter.java b/core/src/main/java/org/spongycastle/crypto/commitments/GeneralHashCommitter.java
new file mode 100644
index 00000000..e37c534e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/commitments/GeneralHashCommitter.java
@@ -0,0 +1,93 @@
+package org.spongycastle.crypto.commitments;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.Commitment;
+import org.spongycastle.crypto.Committer;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.ExtendedDigest;
+import org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/commitments/HashCommitter.java b/core/src/main/java/org/spongycastle/crypto/commitments/HashCommitter.java
new file mode 100644
index 00000000..4320d86d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/commitments/HashCommitter.java
@@ -0,0 +1,89 @@
+package org.spongycastle.crypto.commitments;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.Commitment;
+import org.spongycastle.crypto.Committer;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.ExtendedDigest;
+import org.spongycastle.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
+{
+ 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 HashCommitter(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.doFinal(commitment, 0);
+
+ return commitment;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/digests/EncodableDigest.java b/core/src/main/java/org/spongycastle/crypto/digests/EncodableDigest.java
new file mode 100644
index 00000000..643df2f8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/EncodableDigest.java
@@ -0,0 +1,17 @@
+package org.spongycastle.crypto.digests;
+
+/**
+ * Encodable digests allow you to download an encoded copy of their internal state. This is useful for the situation where
+ * you need to generate a signature on an external device and it allows for "sign with last round", so a copy of the
+ * internal state of the digest, plus the last few blocks of the message are all that needs to be sent, rather than the
+ * entire message.
+ */
+public interface EncodableDigest
+{
+ /**
+ * Return an encoded byte array for the digest's internal state
+ *
+ * @return an encoding of the digests internal state.
+ */
+ byte[] getEncodedState();
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/digests/GOST3411Digest.java b/core/src/main/java/org/spongycastle/crypto/digests/GOST3411Digest.java
new file mode 100644
index 00000000..e5473cf0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/GOST3411Digest.java
@@ -0,0 +1,362 @@
+package org.spongycastle.crypto.digests;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.ExtendedDigest;
+import org.spongycastle.crypto.engines.GOST28147Engine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithSBox;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Memoable;
+import org.spongycastle.util.Pack;
+
+/**
+ * implementation of GOST R 34.11-94
+ */
+public class GOST3411Digest
+ implements ExtendedDigest, Memoable
+{
+ private static final int DIGEST_LENGTH = 32;
+
+ private byte[] H = new byte[32], L = new byte[32],
+ M = new byte[32], Sum = new byte[32];
+ private byte[][] C = new byte[4][32];
+
+ private byte[] xBuf = new byte[32];
+ private int xBufOff;
+ private long byteCount;
+
+ private BlockCipher cipher = new GOST28147Engine();
+ private byte[] sBox;
+
+ /**
+ * Standard constructor
+ */
+ public GOST3411Digest()
+ {
+ sBox = GOST28147Engine.getSBox("D-A");
+ cipher.init(true, new ParametersWithSBox(null, sBox));
+
+ reset();
+ }
+
+ /**
+ * Constructor to allow use of a particular sbox with GOST28147
+ * @see GOST28147Engine#getSBox(String)
+ */
+ public GOST3411Digest(byte[] sBoxParam)
+ {
+ sBox = Arrays.clone(sBoxParam);
+ cipher.init(true, new ParametersWithSBox(null, sBox));
+
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public GOST3411Digest(GOST3411Digest t)
+ {
+ reset(t);
+ }
+
+ public String getAlgorithmName()
+ {
+ return "GOST3411";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ public void update(byte in)
+ {
+ xBuf[xBufOff++] = in;
+ if (xBufOff == xBuf.length)
+ {
+ sumByteArray(xBuf); // calc sum M
+ processBlock(xBuf, 0);
+ xBufOff = 0;
+ }
+ byteCount++;
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ {
+ while ((xBufOff != 0) && (len > 0))
+ {
+ update(in[inOff]);
+ inOff++;
+ len--;
+ }
+
+ while (len > xBuf.length)
+ {
+ System.arraycopy(in, inOff, xBuf, 0, xBuf.length);
+
+ sumByteArray(xBuf); // calc sum M
+ processBlock(xBuf, 0);
+ inOff += xBuf.length;
+ len -= xBuf.length;
+ byteCount += xBuf.length;
+ }
+
+ // load in the remainder.
+ while (len > 0)
+ {
+ update(in[inOff]);
+ inOff++;
+ len--;
+ }
+ }
+
+ // (i + 1 + 4(k - 1)) = 8i + k i = 0-3, k = 1-8
+ private byte[] K = new byte[32];
+
+ private byte[] P(byte[] in)
+ {
+ for(int k = 0; k < 8; k++)
+ {
+ K[4*k] = in[k];
+ K[1 + 4*k] = in[ 8 + k];
+ K[2 + 4*k] = in[16 + k];
+ K[3 + 4*k] = in[24 + k];
+ }
+
+ return K;
+ }
+
+ //A (x) = (x0 ^ x1) || x3 || x2 || x1
+ byte[] a = new byte[8];
+ private byte[] A(byte[] in)
+ {
+ for(int j=0; j<8; j++)
+ {
+ a[j]=(byte)(in[j] ^ in[j+8]);
+ }
+
+ System.arraycopy(in, 8, in, 0, 24);
+ System.arraycopy(a, 0, in, 24, 8);
+
+ return in;
+ }
+
+ //Encrypt function, ECB mode
+ private void E(byte[] key, byte[] s, int sOff, byte[] in, int inOff)
+ {
+ cipher.init(true, new KeyParameter(key));
+
+ cipher.processBlock(in, inOff, s, sOff);
+ }
+
+ // (in:) n16||..||n1 ==> (out:) n1^n2^n3^n4^n13^n16||n16||..||n2
+ short[] wS = new short[16], w_S = new short[16];
+
+ private void fw(byte[] in)
+ {
+ cpyBytesToShort(in, wS);
+ w_S[15] = (short)(wS[0] ^ wS[1] ^ wS[2] ^ wS[3] ^ wS[12] ^ wS[15]);
+ System.arraycopy(wS, 1, w_S, 0, 15);
+ cpyShortToBytes(w_S, in);
+ }
+
+ // block processing
+ byte[] S = new byte[32];
+ byte[] U = new byte[32], V = new byte[32], W = new byte[32];
+
+ protected void processBlock(byte[] in, int inOff)
+ {
+ System.arraycopy(in, inOff, M, 0, 32);
+
+ //key step 1
+
+ // H = h3 || h2 || h1 || h0
+ // S = s3 || s2 || s1 || s0
+ System.arraycopy(H, 0, U, 0, 32);
+ System.arraycopy(M, 0, V, 0, 32);
+ for (int j=0; j<32; j++)
+ {
+ W[j] = (byte)(U[j]^V[j]);
+ }
+ // Encrypt gost28147-ECB
+ E(P(W), S, 0, H, 0); // s0 = EK0 [h0]
+
+ //keys step 2,3,4
+ for (int i=1; i<4; i++)
+ {
+ byte[] tmpA = A(U);
+ for (int j=0; j<32; j++)
+ {
+ U[j] = (byte)(tmpA[j] ^ C[i][j]);
+ }
+ V = A(A(V));
+ for (int j=0; j<32; j++)
+ {
+ W[j] = (byte)(U[j]^V[j]);
+ }
+ // Encrypt gost28147-ECB
+ E(P(W), S, i * 8, H, i * 8); // si = EKi [hi]
+ }
+
+ // x(M, H) = y61(H^y(M^y12(S)))
+ for(int n = 0; n < 12; n++)
+ {
+ fw(S);
+ }
+ for(int n = 0; n < 32; n++)
+ {
+ S[n] = (byte)(S[n] ^ M[n]);
+ }
+
+ fw(S);
+
+ for(int n = 0; n < 32; n++)
+ {
+ S[n] = (byte)(H[n] ^ S[n]);
+ }
+ for(int n = 0; n < 61; n++)
+ {
+ fw(S);
+ }
+ System.arraycopy(S, 0, H, 0, H.length);
+ }
+
+ private void finish()
+ {
+ Pack.longToLittleEndian(byteCount * 8, L, 0); // get length into L (byteCount * 8 = bitCount)
+
+ while (xBufOff != 0)
+ {
+ update((byte)0);
+ }
+
+ processBlock(L, 0);
+ processBlock(Sum, 0);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ System.arraycopy(H, 0, out, outOff, H.length);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables to the IV values.
+ */
+ private static final byte[] C2 = {
+ 0x00,(byte)0xFF,0x00,(byte)0xFF,0x00,(byte)0xFF,0x00,(byte)0xFF,
+ (byte)0xFF,0x00,(byte)0xFF,0x00,(byte)0xFF,0x00,(byte)0xFF,0x00,
+ 0x00,(byte)0xFF,(byte)0xFF,0x00,(byte)0xFF,0x00,0x00,(byte)0xFF,
+ (byte)0xFF,0x00,0x00,0x00,(byte)0xFF,(byte)0xFF,0x00,(byte)0xFF};
+
+ public void reset()
+ {
+ byteCount = 0;
+ xBufOff = 0;
+
+ for(int i=0; i<H.length; i++)
+ {
+ H[i] = 0; // start vector H
+ }
+ for(int i=0; i<L.length; i++)
+ {
+ L[i] = 0;
+ }
+ for(int i=0; i<M.length; i++)
+ {
+ M[i] = 0;
+ }
+ for(int i=0; i<C[1].length; i++)
+ {
+ C[1][i] = 0; // real index C = +1 because index array with 0.
+ }
+ for(int i=0; i<C[3].length; i++)
+ {
+ C[3][i] = 0;
+ }
+ for(int i=0; i<Sum.length; i++)
+ {
+ Sum[i] = 0;
+ }
+ for(int i = 0; i < xBuf.length; i++)
+ {
+ xBuf[i] = 0;
+ }
+
+ System.arraycopy(C2, 0, C[2], 0, C2.length);
+ }
+
+ // 256 bitsblock modul -> (Sum + a mod (2^256))
+ private void sumByteArray(byte[] in)
+ {
+ int carry = 0;
+
+ for (int i = 0; i != Sum.length; i++)
+ {
+ int sum = (Sum[i] & 0xff) + (in[i] & 0xff) + carry;
+
+ Sum[i] = (byte)sum;
+
+ carry = sum >>> 8;
+ }
+ }
+
+ private void cpyBytesToShort(byte[] S, short[] wS)
+ {
+ for(int i=0; i<S.length/2; i++)
+ {
+ wS[i] = (short)(((S[i*2+1]<<8)&0xFF00)|(S[i*2]&0xFF));
+ }
+ }
+
+ private void cpyShortToBytes(short[] wS, byte[] S)
+ {
+ for(int i=0; i<S.length/2; i++)
+ {
+ S[i*2 + 1] = (byte)(wS[i] >> 8);
+ S[i*2] = (byte)wS[i];
+ }
+ }
+
+ public int getByteLength()
+ {
+ return 32;
+ }
+
+ public Memoable copy()
+ {
+ return new GOST3411Digest(this);
+ }
+
+ public void reset(Memoable other)
+ {
+ GOST3411Digest t = (GOST3411Digest)other;
+
+ this.sBox = t.sBox;
+ cipher.init(true, new ParametersWithSBox(null, sBox));
+
+ reset();
+
+ System.arraycopy(t.H, 0, this.H, 0, t.H.length);
+ System.arraycopy(t.L, 0, this.L, 0, t.L.length);
+ System.arraycopy(t.M, 0, this.M, 0, t.M.length);
+ System.arraycopy(t.Sum, 0, this.Sum, 0, t.Sum.length);
+ System.arraycopy(t.C[1], 0, this.C[1], 0, t.C[1].length);
+ System.arraycopy(t.C[2], 0, this.C[2], 0, t.C[2].length);
+ System.arraycopy(t.C[3], 0, this.C[3], 0, t.C[3].length);
+ System.arraycopy(t.xBuf, 0, this.xBuf, 0, t.xBuf.length);
+
+ this.xBufOff = t.xBufOff;
+ this.byteCount = t.byteCount;
+ }
+}
+
+
diff --git a/core/src/main/java/org/spongycastle/crypto/digests/GeneralDigest.java b/core/src/main/java/org/spongycastle/crypto/digests/GeneralDigest.java
new file mode 100644
index 00000000..e83bc991
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/GeneralDigest.java
@@ -0,0 +1,155 @@
+package org.spongycastle.crypto.digests;
+
+import org.spongycastle.crypto.ExtendedDigest;
+import org.spongycastle.util.Memoable;
+import org.spongycastle.util.Pack;
+
+/**
+ * base implementation of MD4 family style digest as outlined in
+ * "Handbook of Applied Cryptography", pages 344 - 347.
+ */
+public abstract class GeneralDigest
+ implements ExtendedDigest, Memoable
+{
+ private static final int BYTE_LENGTH = 64;
+
+ private final byte[] xBuf = new byte[4];
+ private int xBufOff;
+
+ private long byteCount;
+
+ /**
+ * Standard constructor
+ */
+ protected GeneralDigest()
+ {
+ xBufOff = 0;
+ }
+
+ /**
+ * Copy constructor. We are using copy constructors in place
+ * of the Object.clone() interface as this interface is not
+ * supported by J2ME.
+ */
+ protected GeneralDigest(GeneralDigest t)
+ {
+ copyIn(t);
+ }
+
+ protected GeneralDigest(byte[] encodedState)
+ {
+ System.arraycopy(encodedState, 0, xBuf, 0, xBuf.length);
+ xBufOff = Pack.bigEndianToInt(encodedState, 4);
+ byteCount = Pack.bigEndianToLong(encodedState, 8);
+ }
+
+ protected void copyIn(GeneralDigest t)
+ {
+ System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length);
+
+ xBufOff = t.xBufOff;
+ byteCount = t.byteCount;
+ }
+
+ public void update(
+ byte in)
+ {
+ xBuf[xBufOff++] = in;
+
+ if (xBufOff == xBuf.length)
+ {
+ processWord(xBuf, 0);
+ xBufOff = 0;
+ }
+
+ byteCount++;
+ }
+
+ public void update(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ //
+ // fill the current word
+ //
+ while ((xBufOff != 0) && (len > 0))
+ {
+ update(in[inOff]);
+
+ inOff++;
+ len--;
+ }
+
+ //
+ // process whole words.
+ //
+ while (len > xBuf.length)
+ {
+ processWord(in, inOff);
+
+ inOff += xBuf.length;
+ len -= xBuf.length;
+ byteCount += xBuf.length;
+ }
+
+ //
+ // load in the remainder.
+ //
+ while (len > 0)
+ {
+ update(in[inOff]);
+
+ inOff++;
+ len--;
+ }
+ }
+
+ public void finish()
+ {
+ long bitLength = (byteCount << 3);
+
+ //
+ // add the pad bytes.
+ //
+ update((byte)128);
+
+ while (xBufOff != 0)
+ {
+ update((byte)0);
+ }
+
+ processLength(bitLength);
+
+ processBlock();
+ }
+
+ public void reset()
+ {
+ byteCount = 0;
+
+ xBufOff = 0;
+ for (int i = 0; i < xBuf.length; i++)
+ {
+ xBuf[i] = 0;
+ }
+ }
+
+ protected void populateState(byte[] state)
+ {
+ System.arraycopy(xBuf, 0, state, 0, xBufOff);
+ Pack.intToBigEndian(xBufOff, state, 4);
+ Pack.longToBigEndian(byteCount, state, 8);
+ }
+
+ public int getByteLength()
+ {
+ return BYTE_LENGTH;
+ }
+
+ protected abstract void processWord(byte[] in, int inOff);
+
+ protected abstract void processLength(long bitLength);
+
+ protected abstract void processBlock();
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/digests/LongDigest.java b/core/src/main/java/org/spongycastle/crypto/digests/LongDigest.java
new file mode 100644
index 00000000..50a9b664
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/LongDigest.java
@@ -0,0 +1,409 @@
+package org.spongycastle.crypto.digests;
+
+import org.spongycastle.crypto.ExtendedDigest;
+import org.spongycastle.util.Memoable;
+import org.spongycastle.util.Pack;
+
+/**
+ * Base class for SHA-384 and SHA-512.
+ */
+public abstract class LongDigest
+ implements ExtendedDigest, Memoable, EncodableDigest
+{
+ private static final int BYTE_LENGTH = 128;
+
+ private byte[] xBuf = new byte[8];
+ private int xBufOff;
+
+ private long byteCount1;
+ private long byteCount2;
+
+ protected long H1, H2, H3, H4, H5, H6, H7, H8;
+
+ private long[] W = new long[80];
+ private int wOff;
+
+ /**
+ * Constructor for variable length word
+ */
+ protected LongDigest()
+ {
+ xBufOff = 0;
+
+ reset();
+ }
+
+ /**
+ * Copy constructor. We are using copy constructors in place
+ * of the Object.clone() interface as this interface is not
+ * supported by J2ME.
+ */
+ protected LongDigest(LongDigest t)
+ {
+ copyIn(t);
+ }
+
+ protected void copyIn(LongDigest t)
+ {
+ System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length);
+
+ xBufOff = t.xBufOff;
+ byteCount1 = t.byteCount1;
+ byteCount2 = t.byteCount2;
+
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+ H4 = t.H4;
+ H5 = t.H5;
+ H6 = t.H6;
+ H7 = t.H7;
+ H8 = t.H8;
+
+ System.arraycopy(t.W, 0, W, 0, t.W.length);
+ wOff = t.wOff;
+ }
+
+ protected void populateState(byte[] state)
+ {
+ System.arraycopy(xBuf, 0, state, 0, xBufOff);
+ Pack.intToBigEndian(xBufOff, state, 8);
+ Pack.longToBigEndian(byteCount1, state, 12);
+ Pack.longToBigEndian(byteCount2, state, 20);
+ Pack.longToBigEndian(H1, state, 28);
+ Pack.longToBigEndian(H2, state, 36);
+ Pack.longToBigEndian(H3, state, 44);
+ Pack.longToBigEndian(H4, state, 52);
+ Pack.longToBigEndian(H5, state, 60);
+ Pack.longToBigEndian(H6, state, 68);
+ Pack.longToBigEndian(H7, state, 76);
+ Pack.longToBigEndian(H8, state, 84);
+
+ Pack.intToBigEndian(wOff, state, 92);
+ for (int i = 0; i < wOff; i++)
+ {
+ Pack.longToBigEndian(W[i], state, 96 + (i * 8));
+ }
+ }
+
+ protected void restoreState(byte[] encodedState)
+ {
+ xBufOff = Pack.bigEndianToInt(encodedState, 8);
+ System.arraycopy(encodedState, 0, xBuf, 0, xBufOff);
+ byteCount1 = Pack.bigEndianToLong(encodedState, 12);
+ byteCount2 = Pack.bigEndianToLong(encodedState, 20);
+
+ H1 = Pack.bigEndianToLong(encodedState, 28);
+ H2 = Pack.bigEndianToLong(encodedState, 36);
+ H3 = Pack.bigEndianToLong(encodedState, 44);
+ H4 = Pack.bigEndianToLong(encodedState, 52);
+ H5 = Pack.bigEndianToLong(encodedState, 60);
+ H6 = Pack.bigEndianToLong(encodedState, 68);
+ H7 = Pack.bigEndianToLong(encodedState, 76);
+ H8 = Pack.bigEndianToLong(encodedState, 84);
+
+ wOff = Pack.bigEndianToInt(encodedState, 92);
+ for (int i = 0; i < wOff; i++)
+ {
+ W[i] = Pack.bigEndianToLong(encodedState, 96 + (i * 8));
+ }
+ }
+
+ protected int getEncodedStateSize()
+ {
+ return 96 + (wOff * 8);
+ }
+
+ public void update(
+ byte in)
+ {
+ xBuf[xBufOff++] = in;
+
+ if (xBufOff == xBuf.length)
+ {
+ processWord(xBuf, 0);
+ xBufOff = 0;
+ }
+
+ byteCount1++;
+ }
+
+ public void update(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ //
+ // fill the current word
+ //
+ while ((xBufOff != 0) && (len > 0))
+ {
+ update(in[inOff]);
+
+ inOff++;
+ len--;
+ }
+
+ //
+ // process whole words.
+ //
+ while (len > xBuf.length)
+ {
+ processWord(in, inOff);
+
+ inOff += xBuf.length;
+ len -= xBuf.length;
+ byteCount1 += xBuf.length;
+ }
+
+ //
+ // load in the remainder.
+ //
+ while (len > 0)
+ {
+ update(in[inOff]);
+
+ inOff++;
+ len--;
+ }
+ }
+
+ public void finish()
+ {
+ adjustByteCounts();
+
+ long lowBitLength = byteCount1 << 3;
+ long hiBitLength = byteCount2;
+
+ //
+ // add the pad bytes.
+ //
+ update((byte)128);
+
+ while (xBufOff != 0)
+ {
+ update((byte)0);
+ }
+
+ processLength(lowBitLength, hiBitLength);
+
+ processBlock();
+ }
+
+ public void reset()
+ {
+ byteCount1 = 0;
+ byteCount2 = 0;
+
+ xBufOff = 0;
+ for (int i = 0; i < xBuf.length; i++)
+ {
+ xBuf[i] = 0;
+ }
+
+ wOff = 0;
+ for (int i = 0; i != W.length; i++)
+ {
+ W[i] = 0;
+ }
+ }
+
+ public int getByteLength()
+ {
+ return BYTE_LENGTH;
+ }
+
+ protected void processWord(
+ byte[] in,
+ int inOff)
+ {
+ W[wOff] = Pack.bigEndianToLong(in, inOff);
+
+ if (++wOff == 16)
+ {
+ processBlock();
+ }
+ }
+
+ /**
+ * adjust the byte counts so that byteCount2 represents the
+ * upper long (less 3 bits) word of the byte count.
+ */
+ private void adjustByteCounts()
+ {
+ if (byteCount1 > 0x1fffffffffffffffL)
+ {
+ byteCount2 += (byteCount1 >>> 61);
+ byteCount1 &= 0x1fffffffffffffffL;
+ }
+ }
+
+ protected void processLength(
+ long lowW,
+ long hiW)
+ {
+ if (wOff > 14)
+ {
+ processBlock();
+ }
+
+ W[14] = hiW;
+ W[15] = lowW;
+ }
+
+ protected void processBlock()
+ {
+ adjustByteCounts();
+
+ //
+ // expand 16 word block into 80 word blocks.
+ //
+ for (int t = 16; t <= 79; t++)
+ {
+ W[t] = Sigma1(W[t - 2]) + W[t - 7] + Sigma0(W[t - 15]) + W[t - 16];
+ }
+
+ //
+ // set up working variables.
+ //
+ long a = H1;
+ long b = H2;
+ long c = H3;
+ long d = H4;
+ long e = H5;
+ long f = H6;
+ long g = H7;
+ long h = H8;
+
+ int t = 0;
+ for(int i = 0; i < 10; i ++)
+ {
+ // t = 8 * i
+ h += Sum1(e) + Ch(e, f, g) + K[t] + W[t++];
+ d += h;
+ h += Sum0(a) + Maj(a, b, c);
+
+ // t = 8 * i + 1
+ g += Sum1(d) + Ch(d, e, f) + K[t] + W[t++];
+ c += g;
+ g += Sum0(h) + Maj(h, a, b);
+
+ // t = 8 * i + 2
+ f += Sum1(c) + Ch(c, d, e) + K[t] + W[t++];
+ b += f;
+ f += Sum0(g) + Maj(g, h, a);
+
+ // t = 8 * i + 3
+ e += Sum1(b) + Ch(b, c, d) + K[t] + W[t++];
+ a += e;
+ e += Sum0(f) + Maj(f, g, h);
+
+ // t = 8 * i + 4
+ d += Sum1(a) + Ch(a, b, c) + K[t] + W[t++];
+ h += d;
+ d += Sum0(e) + Maj(e, f, g);
+
+ // t = 8 * i + 5
+ c += Sum1(h) + Ch(h, a, b) + K[t] + W[t++];
+ g += c;
+ c += Sum0(d) + Maj(d, e, f);
+
+ // t = 8 * i + 6
+ b += Sum1(g) + Ch(g, h, a) + K[t] + W[t++];
+ f += b;
+ b += Sum0(c) + Maj(c, d, e);
+
+ // t = 8 * i + 7
+ a += Sum1(f) + Ch(f, g, h) + K[t] + W[t++];
+ e += a;
+ a += Sum0(b) + Maj(b, c, d);
+ }
+
+ H1 += a;
+ H2 += b;
+ H3 += c;
+ H4 += d;
+ H5 += e;
+ H6 += f;
+ H7 += g;
+ H8 += h;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ wOff = 0;
+ for (int i = 0; i < 16; i++)
+ {
+ W[i] = 0;
+ }
+ }
+
+ /* SHA-384 and SHA-512 functions (as for SHA-256 but for longs) */
+ private long Ch(
+ long x,
+ long y,
+ long z)
+ {
+ return ((x & y) ^ ((~x) & z));
+ }
+
+ private long Maj(
+ long x,
+ long y,
+ long z)
+ {
+ return ((x & y) ^ (x & z) ^ (y & z));
+ }
+
+ private long Sum0(
+ long x)
+ {
+ return ((x << 36)|(x >>> 28)) ^ ((x << 30)|(x >>> 34)) ^ ((x << 25)|(x >>> 39));
+ }
+
+ private long Sum1(
+ long x)
+ {
+ return ((x << 50)|(x >>> 14)) ^ ((x << 46)|(x >>> 18)) ^ ((x << 23)|(x >>> 41));
+ }
+
+ private long Sigma0(
+ long x)
+ {
+ return ((x << 63)|(x >>> 1)) ^ ((x << 56)|(x >>> 8)) ^ (x >>> 7);
+ }
+
+ private long Sigma1(
+ long x)
+ {
+ return ((x << 45)|(x >>> 19)) ^ ((x << 3)|(x >>> 61)) ^ (x >>> 6);
+ }
+
+ /* SHA-384 and SHA-512 Constants
+ * (represent the first 64 bits of the fractional parts of the
+ * cube roots of the first sixty-four prime numbers)
+ */
+ static final long K[] = {
+0x428a2f98d728ae22L, 0x7137449123ef65cdL, 0xb5c0fbcfec4d3b2fL, 0xe9b5dba58189dbbcL,
+0x3956c25bf348b538L, 0x59f111f1b605d019L, 0x923f82a4af194f9bL, 0xab1c5ed5da6d8118L,
+0xd807aa98a3030242L, 0x12835b0145706fbeL, 0x243185be4ee4b28cL, 0x550c7dc3d5ffb4e2L,
+0x72be5d74f27b896fL, 0x80deb1fe3b1696b1L, 0x9bdc06a725c71235L, 0xc19bf174cf692694L,
+0xe49b69c19ef14ad2L, 0xefbe4786384f25e3L, 0x0fc19dc68b8cd5b5L, 0x240ca1cc77ac9c65L,
+0x2de92c6f592b0275L, 0x4a7484aa6ea6e483L, 0x5cb0a9dcbd41fbd4L, 0x76f988da831153b5L,
+0x983e5152ee66dfabL, 0xa831c66d2db43210L, 0xb00327c898fb213fL, 0xbf597fc7beef0ee4L,
+0xc6e00bf33da88fc2L, 0xd5a79147930aa725L, 0x06ca6351e003826fL, 0x142929670a0e6e70L,
+0x27b70a8546d22ffcL, 0x2e1b21385c26c926L, 0x4d2c6dfc5ac42aedL, 0x53380d139d95b3dfL,
+0x650a73548baf63deL, 0x766a0abb3c77b2a8L, 0x81c2c92e47edaee6L, 0x92722c851482353bL,
+0xa2bfe8a14cf10364L, 0xa81a664bbc423001L, 0xc24b8b70d0f89791L, 0xc76c51a30654be30L,
+0xd192e819d6ef5218L, 0xd69906245565a910L, 0xf40e35855771202aL, 0x106aa07032bbd1b8L,
+0x19a4c116b8d2d0c8L, 0x1e376c085141ab53L, 0x2748774cdf8eeb99L, 0x34b0bcb5e19b48a8L,
+0x391c0cb3c5c95a63L, 0x4ed8aa4ae3418acbL, 0x5b9cca4f7763e373L, 0x682e6ff3d6b2b8a3L,
+0x748f82ee5defb2fcL, 0x78a5636f43172f60L, 0x84c87814a1f0ab72L, 0x8cc702081a6439ecL,
+0x90befffa23631e28L, 0xa4506cebde82bde9L, 0xbef9a3f7b2c67915L, 0xc67178f2e372532bL,
+0xca273eceea26619cL, 0xd186b8c721c0c207L, 0xeada7dd6cde0eb1eL, 0xf57d4f7fee6ed178L,
+0x06f067aa72176fbaL, 0x0a637dc5a2c898a6L, 0x113f9804bef90daeL, 0x1b710b35131c471bL,
+0x28db77f523047d84L, 0x32caab7b40c72493L, 0x3c9ebe0a15c9bebcL, 0x431d67c49c100d4cL,
+0x4cc5d4becb3e42b6L, 0x597f299cfc657e2aL, 0x5fcb6fab3ad6faecL, 0x6c44198c4a475817L
+ };
+
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/digests/MD2Digest.java b/core/src/main/java/org/spongycastle/crypto/digests/MD2Digest.java
new file mode 100644
index 00000000..b7fe6449
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/MD2Digest.java
@@ -0,0 +1,258 @@
+package org.spongycastle.crypto.digests;
+
+import org.spongycastle.crypto.*;
+import org.spongycastle.util.Memoable;
+
+/**
+ * implementation of MD2
+ * as outlined in RFC1319 by B.Kaliski from RSA Laboratories April 1992
+ */
+public class MD2Digest
+ implements ExtendedDigest, Memoable
+{
+ private static final int DIGEST_LENGTH = 16;
+
+ /* X buffer */
+ private byte[] X = new byte[48];
+ private int xOff;
+ /* M buffer */
+ private byte[] M = new byte[16];
+ private int mOff;
+ /* check sum */
+ private byte[] C = new byte[16];
+ private int COff;
+
+ public MD2Digest()
+ {
+ reset();
+ }
+
+ public MD2Digest(MD2Digest t)
+ {
+ copyIn(t);
+ }
+
+ private void copyIn(MD2Digest t)
+ {
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ System.arraycopy(t.M, 0, M, 0, t.M.length);
+ mOff = t.mOff;
+ System.arraycopy(t.C, 0, C, 0, t.C.length);
+ COff = t.COff;
+ }
+
+ /**
+ * return the algorithm name
+ *
+ * @return the algorithm name
+ */
+ public String getAlgorithmName()
+ {
+ return "MD2";
+ }
+ /**
+ * return the size, in bytes, of the digest produced by this message digest.
+ *
+ * @return the size, in bytes, of the digest produced by this message digest.
+ */
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+ /**
+ * close the digest, producing the final digest value. The doFinal
+ * call leaves the digest reset.
+ *
+ * @param out the array the digest is to be copied into.
+ * @param outOff the offset into the out array the digest is to start at.
+ */
+ public int doFinal(byte[] out, int outOff)
+ {
+ // add padding
+ byte paddingByte = (byte)(M.length-mOff);
+ for (int i=mOff;i<M.length;i++)
+ {
+ M[i] = paddingByte;
+ }
+ //do final check sum
+ processCheckSum(M);
+ // do final block process
+ processBlock(M);
+
+ processBlock(C);
+
+ System.arraycopy(X,xOff,out,outOff,16);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+ /**
+ * reset the digest back to it's initial state.
+ */
+ public void reset()
+ {
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ mOff = 0;
+ for (int i = 0; i != M.length; i++)
+ {
+ M[i] = 0;
+ }
+ COff = 0;
+ for (int i = 0; i != C.length; i++)
+ {
+ C[i] = 0;
+ }
+ }
+ /**
+ * update the message digest with a single byte.
+ *
+ * @param in the input byte to be entered.
+ */
+ public void update(byte in)
+ {
+ M[mOff++] = in;
+
+ if (mOff == 16)
+ {
+ processCheckSum(M);
+ processBlock(M);
+ mOff = 0;
+ }
+ }
+
+ /**
+ * update the message digest with a block of bytes.
+ *
+ * @param in the byte array containing the data.
+ * @param inOff the offset into the byte array where the data starts.
+ * @param len the length of the data.
+ */
+ public void update(byte[] in, int inOff, int len)
+ {
+ //
+ // fill the current word
+ //
+ while ((mOff != 0) && (len > 0))
+ {
+ update(in[inOff]);
+ inOff++;
+ len--;
+ }
+
+ //
+ // process whole words.
+ //
+ while (len > 16)
+ {
+ System.arraycopy(in,inOff,M,0,16);
+ processCheckSum(M);
+ processBlock(M);
+ len -= 16;
+ inOff += 16;
+ }
+
+ //
+ // load in the remainder.
+ //
+ while (len > 0)
+ {
+ update(in[inOff]);
+ inOff++;
+ len--;
+ }
+ }
+ protected void processCheckSum(byte[] m)
+ {
+ int L = C[15];
+ for (int i=0;i<16;i++)
+ {
+ C[i] ^= S[(m[i] ^ L) & 0xff];
+ L = C[i];
+ }
+ }
+ protected void processBlock(byte[] m)
+ {
+ for (int i=0;i<16;i++)
+ {
+ X[i+16] = m[i];
+ X[i+32] = (byte)(m[i] ^ X[i]);
+ }
+ // encrypt block
+ int t = 0;
+
+ for (int j=0;j<18;j++)
+ {
+ for (int k=0;k<48;k++)
+ {
+ t = X[k] ^= S[t];
+ t = t & 0xff;
+ }
+ t = (t + j)%256;
+ }
+ }
+ // 256-byte random permutation constructed from the digits of PI
+ private static final byte[] S = {
+ (byte)41,(byte)46,(byte)67,(byte)201,(byte)162,(byte)216,(byte)124,
+ (byte)1,(byte)61,(byte)54,(byte)84,(byte)161,(byte)236,(byte)240,
+ (byte)6,(byte)19,(byte)98,(byte)167,(byte)5,(byte)243,(byte)192,
+ (byte)199,(byte)115,(byte)140,(byte)152,(byte)147,(byte)43,(byte)217,
+ (byte)188,(byte)76,(byte)130,(byte)202,(byte)30,(byte)155,(byte)87,
+ (byte)60,(byte)253,(byte)212,(byte)224,(byte)22,(byte)103,(byte)66,
+ (byte)111,(byte)24,(byte)138,(byte)23,(byte)229,(byte)18,(byte)190,
+ (byte)78,(byte)196,(byte)214,(byte)218,(byte)158,(byte)222,(byte)73,
+ (byte)160,(byte)251,(byte)245,(byte)142,(byte)187,(byte)47,(byte)238,
+ (byte)122,(byte)169,(byte)104,(byte)121,(byte)145,(byte)21,(byte)178,
+ (byte)7,(byte)63,(byte)148,(byte)194,(byte)16,(byte)137,(byte)11,
+ (byte)34,(byte)95,(byte)33,(byte)128,(byte)127,(byte)93,(byte)154,
+ (byte)90,(byte)144,(byte)50,(byte)39,(byte)53,(byte)62,(byte)204,
+ (byte)231,(byte)191,(byte)247,(byte)151,(byte)3,(byte)255,(byte)25,
+ (byte)48,(byte)179,(byte)72,(byte)165,(byte)181,(byte)209,(byte)215,
+ (byte)94,(byte)146,(byte)42,(byte)172,(byte)86,(byte)170,(byte)198,
+ (byte)79,(byte)184,(byte)56,(byte)210,(byte)150,(byte)164,(byte)125,
+ (byte)182,(byte)118,(byte)252,(byte)107,(byte)226,(byte)156,(byte)116,
+ (byte)4,(byte)241,(byte)69,(byte)157,(byte)112,(byte)89,(byte)100,
+ (byte)113,(byte)135,(byte)32,(byte)134,(byte)91,(byte)207,(byte)101,
+ (byte)230,(byte)45,(byte)168,(byte)2,(byte)27,(byte)96,(byte)37,
+ (byte)173,(byte)174,(byte)176,(byte)185,(byte)246,(byte)28,(byte)70,
+ (byte)97,(byte)105,(byte)52,(byte)64,(byte)126,(byte)15,(byte)85,
+ (byte)71,(byte)163,(byte)35,(byte)221,(byte)81,(byte)175,(byte)58,
+ (byte)195,(byte)92,(byte)249,(byte)206,(byte)186,(byte)197,(byte)234,
+ (byte)38,(byte)44,(byte)83,(byte)13,(byte)110,(byte)133,(byte)40,
+ (byte)132, 9,(byte)211,(byte)223,(byte)205,(byte)244,(byte)65,
+ (byte)129,(byte)77,(byte)82,(byte)106,(byte)220,(byte)55,(byte)200,
+ (byte)108,(byte)193,(byte)171,(byte)250,(byte)36,(byte)225,(byte)123,
+ (byte)8,(byte)12,(byte)189,(byte)177,(byte)74,(byte)120,(byte)136,
+ (byte)149,(byte)139,(byte)227,(byte)99,(byte)232,(byte)109,(byte)233,
+ (byte)203,(byte)213,(byte)254,(byte)59,(byte)0,(byte)29,(byte)57,
+ (byte)242,(byte)239,(byte)183,(byte)14,(byte)102,(byte)88,(byte)208,
+ (byte)228,(byte)166,(byte)119,(byte)114,(byte)248,(byte)235,(byte)117,
+ (byte)75,(byte)10,(byte)49,(byte)68,(byte)80,(byte)180,(byte)143,
+ (byte)237,(byte)31,(byte)26,(byte)219,(byte)153,(byte)141,(byte)51,
+ (byte)159,(byte)17,(byte)131,(byte)20
+ };
+
+ public int getByteLength()
+ {
+ return 16;
+ }
+
+ public Memoable copy()
+ {
+ return new MD2Digest(this);
+ }
+
+ public void reset(Memoable other)
+ {
+ MD2Digest d = (MD2Digest)other;
+
+ copyIn(d);
+ }
+}
+
+
diff --git a/core/src/main/java/org/spongycastle/crypto/digests/MD4Digest.java b/core/src/main/java/org/spongycastle/crypto/digests/MD4Digest.java
new file mode 100644
index 00000000..9faf0025
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/MD4Digest.java
@@ -0,0 +1,291 @@
+package org.spongycastle.crypto.digests;
+
+
+import org.spongycastle.util.Memoable;
+
+/**
+ * implementation of MD4 as RFC 1320 by R. Rivest, MIT Laboratory for
+ * Computer Science and RSA Data Security, Inc.
+ * <p>
+ * <b>NOTE</b>: This algorithm is only included for backwards compatability
+ * with legacy applications, it's not secure, don't use it for anything new!
+ */
+public class MD4Digest
+ extends GeneralDigest
+{
+ private static final int DIGEST_LENGTH = 16;
+
+ private int H1, H2, H3, H4; // IV's
+
+ private int[] X = new int[16];
+ private int xOff;
+
+ /**
+ * Standard constructor
+ */
+ public MD4Digest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public MD4Digest(MD4Digest t)
+ {
+ super(t);
+
+ copyIn(t);
+ }
+
+ private void copyIn(MD4Digest t)
+ {
+ super.copyIn(t);
+
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+ H4 = t.H4;
+
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "MD4";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ protected void processWord(
+ byte[] in,
+ int inOff)
+ {
+ X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
+ | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
+
+ if (xOff == 16)
+ {
+ processBlock();
+ }
+ }
+
+ protected void processLength(
+ long bitLength)
+ {
+ if (xOff > 14)
+ {
+ processBlock();
+ }
+
+ X[14] = (int)(bitLength & 0xffffffff);
+ X[15] = (int)(bitLength >>> 32);
+ }
+
+ private void unpackWord(
+ int word,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff] = (byte)word;
+ out[outOff + 1] = (byte)(word >>> 8);
+ out[outOff + 2] = (byte)(word >>> 16);
+ out[outOff + 3] = (byte)(word >>> 24);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ unpackWord(H1, out, outOff);
+ unpackWord(H2, out, outOff + 4);
+ unpackWord(H3, out, outOff + 8);
+ unpackWord(H4, out, outOff + 12);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables to the IV values.
+ */
+ public void reset()
+ {
+ super.reset();
+
+ H1 = 0x67452301;
+ H2 = 0xefcdab89;
+ H3 = 0x98badcfe;
+ H4 = 0x10325476;
+
+ xOff = 0;
+
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ //
+ // round 1 left rotates
+ //
+ private static final int S11 = 3;
+ private static final int S12 = 7;
+ private static final int S13 = 11;
+ private static final int S14 = 19;
+
+ //
+ // round 2 left rotates
+ //
+ private static final int S21 = 3;
+ private static final int S22 = 5;
+ private static final int S23 = 9;
+ private static final int S24 = 13;
+
+ //
+ // round 3 left rotates
+ //
+ private static final int S31 = 3;
+ private static final int S32 = 9;
+ private static final int S33 = 11;
+ private static final int S34 = 15;
+
+ /*
+ * rotate int x left n bits.
+ */
+ private int rotateLeft(
+ int x,
+ int n)
+ {
+ return (x << n) | (x >>> (32 - n));
+ }
+
+ /*
+ * F, G, H and I are the basic MD4 functions.
+ */
+ private int F(
+ int u,
+ int v,
+ int w)
+ {
+ return (u & v) | (~u & w);
+ }
+
+ private int G(
+ int u,
+ int v,
+ int w)
+ {
+ return (u & v) | (u & w) | (v & w);
+ }
+
+ private int H(
+ int u,
+ int v,
+ int w)
+ {
+ return u ^ v ^ w;
+ }
+
+ protected void processBlock()
+ {
+ int a = H1;
+ int b = H2;
+ int c = H3;
+ int d = H4;
+
+ //
+ // Round 1 - F cycle, 16 times.
+ //
+ a = rotateLeft(a + F(b, c, d) + X[ 0], S11);
+ d = rotateLeft(d + F(a, b, c) + X[ 1], S12);
+ c = rotateLeft(c + F(d, a, b) + X[ 2], S13);
+ b = rotateLeft(b + F(c, d, a) + X[ 3], S14);
+ a = rotateLeft(a + F(b, c, d) + X[ 4], S11);
+ d = rotateLeft(d + F(a, b, c) + X[ 5], S12);
+ c = rotateLeft(c + F(d, a, b) + X[ 6], S13);
+ b = rotateLeft(b + F(c, d, a) + X[ 7], S14);
+ a = rotateLeft(a + F(b, c, d) + X[ 8], S11);
+ d = rotateLeft(d + F(a, b, c) + X[ 9], S12);
+ c = rotateLeft(c + F(d, a, b) + X[10], S13);
+ b = rotateLeft(b + F(c, d, a) + X[11], S14);
+ a = rotateLeft(a + F(b, c, d) + X[12], S11);
+ d = rotateLeft(d + F(a, b, c) + X[13], S12);
+ c = rotateLeft(c + F(d, a, b) + X[14], S13);
+ b = rotateLeft(b + F(c, d, a) + X[15], S14);
+
+ //
+ // Round 2 - G cycle, 16 times.
+ //
+ a = rotateLeft(a + G(b, c, d) + X[ 0] + 0x5a827999, S21);
+ d = rotateLeft(d + G(a, b, c) + X[ 4] + 0x5a827999, S22);
+ c = rotateLeft(c + G(d, a, b) + X[ 8] + 0x5a827999, S23);
+ b = rotateLeft(b + G(c, d, a) + X[12] + 0x5a827999, S24);
+ a = rotateLeft(a + G(b, c, d) + X[ 1] + 0x5a827999, S21);
+ d = rotateLeft(d + G(a, b, c) + X[ 5] + 0x5a827999, S22);
+ c = rotateLeft(c + G(d, a, b) + X[ 9] + 0x5a827999, S23);
+ b = rotateLeft(b + G(c, d, a) + X[13] + 0x5a827999, S24);
+ a = rotateLeft(a + G(b, c, d) + X[ 2] + 0x5a827999, S21);
+ d = rotateLeft(d + G(a, b, c) + X[ 6] + 0x5a827999, S22);
+ c = rotateLeft(c + G(d, a, b) + X[10] + 0x5a827999, S23);
+ b = rotateLeft(b + G(c, d, a) + X[14] + 0x5a827999, S24);
+ a = rotateLeft(a + G(b, c, d) + X[ 3] + 0x5a827999, S21);
+ d = rotateLeft(d + G(a, b, c) + X[ 7] + 0x5a827999, S22);
+ c = rotateLeft(c + G(d, a, b) + X[11] + 0x5a827999, S23);
+ b = rotateLeft(b + G(c, d, a) + X[15] + 0x5a827999, S24);
+
+ //
+ // Round 3 - H cycle, 16 times.
+ //
+ a = rotateLeft(a + H(b, c, d) + X[ 0] + 0x6ed9eba1, S31);
+ d = rotateLeft(d + H(a, b, c) + X[ 8] + 0x6ed9eba1, S32);
+ c = rotateLeft(c + H(d, a, b) + X[ 4] + 0x6ed9eba1, S33);
+ b = rotateLeft(b + H(c, d, a) + X[12] + 0x6ed9eba1, S34);
+ a = rotateLeft(a + H(b, c, d) + X[ 2] + 0x6ed9eba1, S31);
+ d = rotateLeft(d + H(a, b, c) + X[10] + 0x6ed9eba1, S32);
+ c = rotateLeft(c + H(d, a, b) + X[ 6] + 0x6ed9eba1, S33);
+ b = rotateLeft(b + H(c, d, a) + X[14] + 0x6ed9eba1, S34);
+ a = rotateLeft(a + H(b, c, d) + X[ 1] + 0x6ed9eba1, S31);
+ d = rotateLeft(d + H(a, b, c) + X[ 9] + 0x6ed9eba1, S32);
+ c = rotateLeft(c + H(d, a, b) + X[ 5] + 0x6ed9eba1, S33);
+ b = rotateLeft(b + H(c, d, a) + X[13] + 0x6ed9eba1, S34);
+ a = rotateLeft(a + H(b, c, d) + X[ 3] + 0x6ed9eba1, S31);
+ d = rotateLeft(d + H(a, b, c) + X[11] + 0x6ed9eba1, S32);
+ c = rotateLeft(c + H(d, a, b) + X[ 7] + 0x6ed9eba1, S33);
+ b = rotateLeft(b + H(c, d, a) + X[15] + 0x6ed9eba1, S34);
+
+ H1 += a;
+ H2 += b;
+ H3 += c;
+ H4 += d;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ public Memoable copy()
+ {
+ return new MD4Digest(this);
+ }
+
+ public void reset(Memoable other)
+ {
+ MD4Digest d = (MD4Digest)other;
+
+ copyIn(d);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/digests/MD5Digest.java b/core/src/main/java/org/spongycastle/crypto/digests/MD5Digest.java
new file mode 100644
index 00000000..61c83494
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/MD5Digest.java
@@ -0,0 +1,323 @@
+package org.spongycastle.crypto.digests;
+
+
+import org.spongycastle.util.Memoable;
+
+/**
+ * implementation of MD5 as outlined in "Handbook of Applied Cryptography", pages 346 - 347.
+ */
+public class MD5Digest
+ extends GeneralDigest
+{
+ private static final int DIGEST_LENGTH = 16;
+
+ private int H1, H2, H3, H4; // IV's
+
+ private int[] X = new int[16];
+ private int xOff;
+
+ /**
+ * Standard constructor
+ */
+ public MD5Digest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public MD5Digest(MD5Digest t)
+ {
+ super(t);
+
+ copyIn(t);
+ }
+
+ private void copyIn(MD5Digest t)
+ {
+ super.copyIn(t);
+
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+ H4 = t.H4;
+
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "MD5";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ protected void processWord(
+ byte[] in,
+ int inOff)
+ {
+ X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
+ | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
+
+ if (xOff == 16)
+ {
+ processBlock();
+ }
+ }
+
+ protected void processLength(
+ long bitLength)
+ {
+ if (xOff > 14)
+ {
+ processBlock();
+ }
+
+ X[14] = (int)(bitLength & 0xffffffff);
+ X[15] = (int)(bitLength >>> 32);
+ }
+
+ private void unpackWord(
+ int word,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff] = (byte)word;
+ out[outOff + 1] = (byte)(word >>> 8);
+ out[outOff + 2] = (byte)(word >>> 16);
+ out[outOff + 3] = (byte)(word >>> 24);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ unpackWord(H1, out, outOff);
+ unpackWord(H2, out, outOff + 4);
+ unpackWord(H3, out, outOff + 8);
+ unpackWord(H4, out, outOff + 12);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables to the IV values.
+ */
+ public void reset()
+ {
+ super.reset();
+
+ H1 = 0x67452301;
+ H2 = 0xefcdab89;
+ H3 = 0x98badcfe;
+ H4 = 0x10325476;
+
+ xOff = 0;
+
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ //
+ // round 1 left rotates
+ //
+ private static final int S11 = 7;
+ private static final int S12 = 12;
+ private static final int S13 = 17;
+ private static final int S14 = 22;
+
+ //
+ // round 2 left rotates
+ //
+ private static final int S21 = 5;
+ private static final int S22 = 9;
+ private static final int S23 = 14;
+ private static final int S24 = 20;
+
+ //
+ // round 3 left rotates
+ //
+ private static final int S31 = 4;
+ private static final int S32 = 11;
+ private static final int S33 = 16;
+ private static final int S34 = 23;
+
+ //
+ // round 4 left rotates
+ //
+ private static final int S41 = 6;
+ private static final int S42 = 10;
+ private static final int S43 = 15;
+ private static final int S44 = 21;
+
+ /*
+ * rotate int x left n bits.
+ */
+ private int rotateLeft(
+ int x,
+ int n)
+ {
+ return (x << n) | (x >>> (32 - n));
+ }
+
+ /*
+ * F, G, H and I are the basic MD5 functions.
+ */
+ private int F(
+ int u,
+ int v,
+ int w)
+ {
+ return (u & v) | (~u & w);
+ }
+
+ private int G(
+ int u,
+ int v,
+ int w)
+ {
+ return (u & w) | (v & ~w);
+ }
+
+ private int H(
+ int u,
+ int v,
+ int w)
+ {
+ return u ^ v ^ w;
+ }
+
+ private int K(
+ int u,
+ int v,
+ int w)
+ {
+ return v ^ (u | ~w);
+ }
+
+ protected void processBlock()
+ {
+ int a = H1;
+ int b = H2;
+ int c = H3;
+ int d = H4;
+
+ //
+ // Round 1 - F cycle, 16 times.
+ //
+ a = rotateLeft(a + F(b, c, d) + X[ 0] + 0xd76aa478, S11) + b;
+ d = rotateLeft(d + F(a, b, c) + X[ 1] + 0xe8c7b756, S12) + a;
+ c = rotateLeft(c + F(d, a, b) + X[ 2] + 0x242070db, S13) + d;
+ b = rotateLeft(b + F(c, d, a) + X[ 3] + 0xc1bdceee, S14) + c;
+ a = rotateLeft(a + F(b, c, d) + X[ 4] + 0xf57c0faf, S11) + b;
+ d = rotateLeft(d + F(a, b, c) + X[ 5] + 0x4787c62a, S12) + a;
+ c = rotateLeft(c + F(d, a, b) + X[ 6] + 0xa8304613, S13) + d;
+ b = rotateLeft(b + F(c, d, a) + X[ 7] + 0xfd469501, S14) + c;
+ a = rotateLeft(a + F(b, c, d) + X[ 8] + 0x698098d8, S11) + b;
+ d = rotateLeft(d + F(a, b, c) + X[ 9] + 0x8b44f7af, S12) + a;
+ c = rotateLeft(c + F(d, a, b) + X[10] + 0xffff5bb1, S13) + d;
+ b = rotateLeft(b + F(c, d, a) + X[11] + 0x895cd7be, S14) + c;
+ a = rotateLeft(a + F(b, c, d) + X[12] + 0x6b901122, S11) + b;
+ d = rotateLeft(d + F(a, b, c) + X[13] + 0xfd987193, S12) + a;
+ c = rotateLeft(c + F(d, a, b) + X[14] + 0xa679438e, S13) + d;
+ b = rotateLeft(b + F(c, d, a) + X[15] + 0x49b40821, S14) + c;
+
+ //
+ // Round 2 - G cycle, 16 times.
+ //
+ a = rotateLeft(a + G(b, c, d) + X[ 1] + 0xf61e2562, S21) + b;
+ d = rotateLeft(d + G(a, b, c) + X[ 6] + 0xc040b340, S22) + a;
+ c = rotateLeft(c + G(d, a, b) + X[11] + 0x265e5a51, S23) + d;
+ b = rotateLeft(b + G(c, d, a) + X[ 0] + 0xe9b6c7aa, S24) + c;
+ a = rotateLeft(a + G(b, c, d) + X[ 5] + 0xd62f105d, S21) + b;
+ d = rotateLeft(d + G(a, b, c) + X[10] + 0x02441453, S22) + a;
+ c = rotateLeft(c + G(d, a, b) + X[15] + 0xd8a1e681, S23) + d;
+ b = rotateLeft(b + G(c, d, a) + X[ 4] + 0xe7d3fbc8, S24) + c;
+ a = rotateLeft(a + G(b, c, d) + X[ 9] + 0x21e1cde6, S21) + b;
+ d = rotateLeft(d + G(a, b, c) + X[14] + 0xc33707d6, S22) + a;
+ c = rotateLeft(c + G(d, a, b) + X[ 3] + 0xf4d50d87, S23) + d;
+ b = rotateLeft(b + G(c, d, a) + X[ 8] + 0x455a14ed, S24) + c;
+ a = rotateLeft(a + G(b, c, d) + X[13] + 0xa9e3e905, S21) + b;
+ d = rotateLeft(d + G(a, b, c) + X[ 2] + 0xfcefa3f8, S22) + a;
+ c = rotateLeft(c + G(d, a, b) + X[ 7] + 0x676f02d9, S23) + d;
+ b = rotateLeft(b + G(c, d, a) + X[12] + 0x8d2a4c8a, S24) + c;
+
+ //
+ // Round 3 - H cycle, 16 times.
+ //
+ a = rotateLeft(a + H(b, c, d) + X[ 5] + 0xfffa3942, S31) + b;
+ d = rotateLeft(d + H(a, b, c) + X[ 8] + 0x8771f681, S32) + a;
+ c = rotateLeft(c + H(d, a, b) + X[11] + 0x6d9d6122, S33) + d;
+ b = rotateLeft(b + H(c, d, a) + X[14] + 0xfde5380c, S34) + c;
+ a = rotateLeft(a + H(b, c, d) + X[ 1] + 0xa4beea44, S31) + b;
+ d = rotateLeft(d + H(a, b, c) + X[ 4] + 0x4bdecfa9, S32) + a;
+ c = rotateLeft(c + H(d, a, b) + X[ 7] + 0xf6bb4b60, S33) + d;
+ b = rotateLeft(b + H(c, d, a) + X[10] + 0xbebfbc70, S34) + c;
+ a = rotateLeft(a + H(b, c, d) + X[13] + 0x289b7ec6, S31) + b;
+ d = rotateLeft(d + H(a, b, c) + X[ 0] + 0xeaa127fa, S32) + a;
+ c = rotateLeft(c + H(d, a, b) + X[ 3] + 0xd4ef3085, S33) + d;
+ b = rotateLeft(b + H(c, d, a) + X[ 6] + 0x04881d05, S34) + c;
+ a = rotateLeft(a + H(b, c, d) + X[ 9] + 0xd9d4d039, S31) + b;
+ d = rotateLeft(d + H(a, b, c) + X[12] + 0xe6db99e5, S32) + a;
+ c = rotateLeft(c + H(d, a, b) + X[15] + 0x1fa27cf8, S33) + d;
+ b = rotateLeft(b + H(c, d, a) + X[ 2] + 0xc4ac5665, S34) + c;
+
+ //
+ // Round 4 - K cycle, 16 times.
+ //
+ a = rotateLeft(a + K(b, c, d) + X[ 0] + 0xf4292244, S41) + b;
+ d = rotateLeft(d + K(a, b, c) + X[ 7] + 0x432aff97, S42) + a;
+ c = rotateLeft(c + K(d, a, b) + X[14] + 0xab9423a7, S43) + d;
+ b = rotateLeft(b + K(c, d, a) + X[ 5] + 0xfc93a039, S44) + c;
+ a = rotateLeft(a + K(b, c, d) + X[12] + 0x655b59c3, S41) + b;
+ d = rotateLeft(d + K(a, b, c) + X[ 3] + 0x8f0ccc92, S42) + a;
+ c = rotateLeft(c + K(d, a, b) + X[10] + 0xffeff47d, S43) + d;
+ b = rotateLeft(b + K(c, d, a) + X[ 1] + 0x85845dd1, S44) + c;
+ a = rotateLeft(a + K(b, c, d) + X[ 8] + 0x6fa87e4f, S41) + b;
+ d = rotateLeft(d + K(a, b, c) + X[15] + 0xfe2ce6e0, S42) + a;
+ c = rotateLeft(c + K(d, a, b) + X[ 6] + 0xa3014314, S43) + d;
+ b = rotateLeft(b + K(c, d, a) + X[13] + 0x4e0811a1, S44) + c;
+ a = rotateLeft(a + K(b, c, d) + X[ 4] + 0xf7537e82, S41) + b;
+ d = rotateLeft(d + K(a, b, c) + X[11] + 0xbd3af235, S42) + a;
+ c = rotateLeft(c + K(d, a, b) + X[ 2] + 0x2ad7d2bb, S43) + d;
+ b = rotateLeft(b + K(c, d, a) + X[ 9] + 0xeb86d391, S44) + c;
+
+ H1 += a;
+ H2 += b;
+ H3 += c;
+ H4 += d;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ public Memoable copy()
+ {
+ return new MD5Digest(this);
+ }
+
+ public void reset(Memoable other)
+ {
+ MD5Digest d = (MD5Digest)other;
+
+ copyIn(d);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/digests/NonMemoableDigest.java b/core/src/main/java/org/spongycastle/crypto/digests/NonMemoableDigest.java
new file mode 100644
index 00000000..7ce89469
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/NonMemoableDigest.java
@@ -0,0 +1,64 @@
+package org.spongycastle.crypto.digests;
+
+import org.spongycastle.crypto.ExtendedDigest;
+
+/**
+ * Wrapper removes exposure to the Memoable interface on an ExtendedDigest implementation.
+ */
+public class NonMemoableDigest
+ implements ExtendedDigest
+{
+ private ExtendedDigest baseDigest;
+
+ /**
+ * Base constructor.
+ *
+ * @param baseDigest underlying digest to use.
+ * @exception IllegalArgumentException if baseDigest is null
+ */
+ public NonMemoableDigest(
+ ExtendedDigest baseDigest)
+ {
+ if (baseDigest == null)
+ {
+ throw new IllegalArgumentException("baseDigest must not be null");
+ }
+
+ this.baseDigest = baseDigest;
+ }
+
+ public String getAlgorithmName()
+ {
+ return baseDigest.getAlgorithmName();
+ }
+
+ public int getDigestSize()
+ {
+ return baseDigest.getDigestSize();
+ }
+
+ public void update(byte in)
+ {
+ baseDigest.update(in);
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ {
+ baseDigest.update(in, inOff, len);
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ {
+ return baseDigest.doFinal(out, outOff);
+ }
+
+ public void reset()
+ {
+ baseDigest.reset();
+ }
+
+ public int getByteLength()
+ {
+ return baseDigest.getByteLength();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/digests/NullDigest.java b/core/src/main/java/org/spongycastle/crypto/digests/NullDigest.java
new file mode 100644
index 00000000..6b3c8106
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/NullDigest.java
@@ -0,0 +1,48 @@
+package org.spongycastle.crypto.digests;
+
+import java.io.ByteArrayOutputStream;
+
+import org.spongycastle.crypto.Digest;
+
+
+public class NullDigest
+ implements Digest
+{
+ private ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ public String getAlgorithmName()
+ {
+ return "NULL";
+ }
+
+ public int getDigestSize()
+ {
+ return bOut.size();
+ }
+
+ public void update(byte in)
+ {
+ bOut.write(in);
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ {
+ bOut.write(in, inOff, len);
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ {
+ byte[] res = bOut.toByteArray();
+
+ System.arraycopy(res, 0, out, outOff, res.length);
+
+ reset();
+
+ return res.length;
+ }
+
+ public void reset()
+ {
+ bOut.reset();
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/crypto/digests/RIPEMD128Digest.java b/core/src/main/java/org/spongycastle/crypto/digests/RIPEMD128Digest.java
new file mode 100644
index 00000000..26a8b702
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/RIPEMD128Digest.java
@@ -0,0 +1,482 @@
+package org.spongycastle.crypto.digests;
+
+
+import org.spongycastle.util.Memoable;
+
+/**
+ * implementation of RIPEMD128
+ */
+public class RIPEMD128Digest
+ extends GeneralDigest
+{
+ private static final int DIGEST_LENGTH = 16;
+
+ private int H0, H1, H2, H3; // IV's
+
+ private int[] X = new int[16];
+ private int xOff;
+
+ /**
+ * Standard constructor
+ */
+ public RIPEMD128Digest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public RIPEMD128Digest(RIPEMD128Digest t)
+ {
+ super(t);
+
+ copyIn(t);
+ }
+
+ private void copyIn(RIPEMD128Digest t)
+ {
+ super.copyIn(t);
+
+ H0 = t.H0;
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "RIPEMD128";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ protected void processWord(
+ byte[] in,
+ int inOff)
+ {
+ X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
+ | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
+
+ if (xOff == 16)
+ {
+ processBlock();
+ }
+ }
+
+ protected void processLength(
+ long bitLength)
+ {
+ if (xOff > 14)
+ {
+ processBlock();
+ }
+
+ X[14] = (int)(bitLength & 0xffffffff);
+ X[15] = (int)(bitLength >>> 32);
+ }
+
+ private void unpackWord(
+ int word,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff] = (byte)word;
+ out[outOff + 1] = (byte)(word >>> 8);
+ out[outOff + 2] = (byte)(word >>> 16);
+ out[outOff + 3] = (byte)(word >>> 24);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ unpackWord(H0, out, outOff);
+ unpackWord(H1, out, outOff + 4);
+ unpackWord(H2, out, outOff + 8);
+ unpackWord(H3, out, outOff + 12);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables to the IV values.
+ */
+ public void reset()
+ {
+ super.reset();
+
+ H0 = 0x67452301;
+ H1 = 0xefcdab89;
+ H2 = 0x98badcfe;
+ H3 = 0x10325476;
+
+ xOff = 0;
+
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ /*
+ * rotate int x left n bits.
+ */
+ private int RL(
+ int x,
+ int n)
+ {
+ return (x << n) | (x >>> (32 - n));
+ }
+
+ /*
+ * f1,f2,f3,f4 are the basic RIPEMD128 functions.
+ */
+
+ /*
+ * F
+ */
+ private int f1(
+ int x,
+ int y,
+ int z)
+ {
+ return x ^ y ^ z;
+ }
+
+ /*
+ * G
+ */
+ private int f2(
+ int x,
+ int y,
+ int z)
+ {
+ return (x & y) | (~x & z);
+ }
+
+ /*
+ * H
+ */
+ private int f3(
+ int x,
+ int y,
+ int z)
+ {
+ return (x | ~y) ^ z;
+ }
+
+ /*
+ * I
+ */
+ private int f4(
+ int x,
+ int y,
+ int z)
+ {
+ return (x & z) | (y & ~z);
+ }
+
+ private int F1(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f1(b, c, d) + x, s);
+ }
+
+ private int F2(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f2(b, c, d) + x + 0x5a827999, s);
+ }
+
+ private int F3(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f3(b, c, d) + x + 0x6ed9eba1, s);
+ }
+
+ private int F4(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f4(b, c, d) + x + 0x8f1bbcdc, s);
+ }
+
+ private int FF1(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f1(b, c, d) + x, s);
+ }
+
+ private int FF2(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f2(b, c, d) + x + 0x6d703ef3, s);
+ }
+
+ private int FF3(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f3(b, c, d) + x + 0x5c4dd124, s);
+ }
+
+ private int FF4(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f4(b, c, d) + x + 0x50a28be6, s);
+ }
+
+ protected void processBlock()
+ {
+ int a, aa;
+ int b, bb;
+ int c, cc;
+ int d, dd;
+
+ a = aa = H0;
+ b = bb = H1;
+ c = cc = H2;
+ d = dd = H3;
+
+ //
+ // Round 1
+ //
+ a = F1(a, b, c, d, X[ 0], 11);
+ d = F1(d, a, b, c, X[ 1], 14);
+ c = F1(c, d, a, b, X[ 2], 15);
+ b = F1(b, c, d, a, X[ 3], 12);
+ a = F1(a, b, c, d, X[ 4], 5);
+ d = F1(d, a, b, c, X[ 5], 8);
+ c = F1(c, d, a, b, X[ 6], 7);
+ b = F1(b, c, d, a, X[ 7], 9);
+ a = F1(a, b, c, d, X[ 8], 11);
+ d = F1(d, a, b, c, X[ 9], 13);
+ c = F1(c, d, a, b, X[10], 14);
+ b = F1(b, c, d, a, X[11], 15);
+ a = F1(a, b, c, d, X[12], 6);
+ d = F1(d, a, b, c, X[13], 7);
+ c = F1(c, d, a, b, X[14], 9);
+ b = F1(b, c, d, a, X[15], 8);
+
+ //
+ // Round 2
+ //
+ a = F2(a, b, c, d, X[ 7], 7);
+ d = F2(d, a, b, c, X[ 4], 6);
+ c = F2(c, d, a, b, X[13], 8);
+ b = F2(b, c, d, a, X[ 1], 13);
+ a = F2(a, b, c, d, X[10], 11);
+ d = F2(d, a, b, c, X[ 6], 9);
+ c = F2(c, d, a, b, X[15], 7);
+ b = F2(b, c, d, a, X[ 3], 15);
+ a = F2(a, b, c, d, X[12], 7);
+ d = F2(d, a, b, c, X[ 0], 12);
+ c = F2(c, d, a, b, X[ 9], 15);
+ b = F2(b, c, d, a, X[ 5], 9);
+ a = F2(a, b, c, d, X[ 2], 11);
+ d = F2(d, a, b, c, X[14], 7);
+ c = F2(c, d, a, b, X[11], 13);
+ b = F2(b, c, d, a, X[ 8], 12);
+
+ //
+ // Round 3
+ //
+ a = F3(a, b, c, d, X[ 3], 11);
+ d = F3(d, a, b, c, X[10], 13);
+ c = F3(c, d, a, b, X[14], 6);
+ b = F3(b, c, d, a, X[ 4], 7);
+ a = F3(a, b, c, d, X[ 9], 14);
+ d = F3(d, a, b, c, X[15], 9);
+ c = F3(c, d, a, b, X[ 8], 13);
+ b = F3(b, c, d, a, X[ 1], 15);
+ a = F3(a, b, c, d, X[ 2], 14);
+ d = F3(d, a, b, c, X[ 7], 8);
+ c = F3(c, d, a, b, X[ 0], 13);
+ b = F3(b, c, d, a, X[ 6], 6);
+ a = F3(a, b, c, d, X[13], 5);
+ d = F3(d, a, b, c, X[11], 12);
+ c = F3(c, d, a, b, X[ 5], 7);
+ b = F3(b, c, d, a, X[12], 5);
+
+ //
+ // Round 4
+ //
+ a = F4(a, b, c, d, X[ 1], 11);
+ d = F4(d, a, b, c, X[ 9], 12);
+ c = F4(c, d, a, b, X[11], 14);
+ b = F4(b, c, d, a, X[10], 15);
+ a = F4(a, b, c, d, X[ 0], 14);
+ d = F4(d, a, b, c, X[ 8], 15);
+ c = F4(c, d, a, b, X[12], 9);
+ b = F4(b, c, d, a, X[ 4], 8);
+ a = F4(a, b, c, d, X[13], 9);
+ d = F4(d, a, b, c, X[ 3], 14);
+ c = F4(c, d, a, b, X[ 7], 5);
+ b = F4(b, c, d, a, X[15], 6);
+ a = F4(a, b, c, d, X[14], 8);
+ d = F4(d, a, b, c, X[ 5], 6);
+ c = F4(c, d, a, b, X[ 6], 5);
+ b = F4(b, c, d, a, X[ 2], 12);
+
+ //
+ // Parallel round 1
+ //
+ aa = FF4(aa, bb, cc, dd, X[ 5], 8);
+ dd = FF4(dd, aa, bb, cc, X[14], 9);
+ cc = FF4(cc, dd, aa, bb, X[ 7], 9);
+ bb = FF4(bb, cc, dd, aa, X[ 0], 11);
+ aa = FF4(aa, bb, cc, dd, X[ 9], 13);
+ dd = FF4(dd, aa, bb, cc, X[ 2], 15);
+ cc = FF4(cc, dd, aa, bb, X[11], 15);
+ bb = FF4(bb, cc, dd, aa, X[ 4], 5);
+ aa = FF4(aa, bb, cc, dd, X[13], 7);
+ dd = FF4(dd, aa, bb, cc, X[ 6], 7);
+ cc = FF4(cc, dd, aa, bb, X[15], 8);
+ bb = FF4(bb, cc, dd, aa, X[ 8], 11);
+ aa = FF4(aa, bb, cc, dd, X[ 1], 14);
+ dd = FF4(dd, aa, bb, cc, X[10], 14);
+ cc = FF4(cc, dd, aa, bb, X[ 3], 12);
+ bb = FF4(bb, cc, dd, aa, X[12], 6);
+
+ //
+ // Parallel round 2
+ //
+ aa = FF3(aa, bb, cc, dd, X[ 6], 9);
+ dd = FF3(dd, aa, bb, cc, X[11], 13);
+ cc = FF3(cc, dd, aa, bb, X[ 3], 15);
+ bb = FF3(bb, cc, dd, aa, X[ 7], 7);
+ aa = FF3(aa, bb, cc, dd, X[ 0], 12);
+ dd = FF3(dd, aa, bb, cc, X[13], 8);
+ cc = FF3(cc, dd, aa, bb, X[ 5], 9);
+ bb = FF3(bb, cc, dd, aa, X[10], 11);
+ aa = FF3(aa, bb, cc, dd, X[14], 7);
+ dd = FF3(dd, aa, bb, cc, X[15], 7);
+ cc = FF3(cc, dd, aa, bb, X[ 8], 12);
+ bb = FF3(bb, cc, dd, aa, X[12], 7);
+ aa = FF3(aa, bb, cc, dd, X[ 4], 6);
+ dd = FF3(dd, aa, bb, cc, X[ 9], 15);
+ cc = FF3(cc, dd, aa, bb, X[ 1], 13);
+ bb = FF3(bb, cc, dd, aa, X[ 2], 11);
+
+ //
+ // Parallel round 3
+ //
+ aa = FF2(aa, bb, cc, dd, X[15], 9);
+ dd = FF2(dd, aa, bb, cc, X[ 5], 7);
+ cc = FF2(cc, dd, aa, bb, X[ 1], 15);
+ bb = FF2(bb, cc, dd, aa, X[ 3], 11);
+ aa = FF2(aa, bb, cc, dd, X[ 7], 8);
+ dd = FF2(dd, aa, bb, cc, X[14], 6);
+ cc = FF2(cc, dd, aa, bb, X[ 6], 6);
+ bb = FF2(bb, cc, dd, aa, X[ 9], 14);
+ aa = FF2(aa, bb, cc, dd, X[11], 12);
+ dd = FF2(dd, aa, bb, cc, X[ 8], 13);
+ cc = FF2(cc, dd, aa, bb, X[12], 5);
+ bb = FF2(bb, cc, dd, aa, X[ 2], 14);
+ aa = FF2(aa, bb, cc, dd, X[10], 13);
+ dd = FF2(dd, aa, bb, cc, X[ 0], 13);
+ cc = FF2(cc, dd, aa, bb, X[ 4], 7);
+ bb = FF2(bb, cc, dd, aa, X[13], 5);
+
+ //
+ // Parallel round 4
+ //
+ aa = FF1(aa, bb, cc, dd, X[ 8], 15);
+ dd = FF1(dd, aa, bb, cc, X[ 6], 5);
+ cc = FF1(cc, dd, aa, bb, X[ 4], 8);
+ bb = FF1(bb, cc, dd, aa, X[ 1], 11);
+ aa = FF1(aa, bb, cc, dd, X[ 3], 14);
+ dd = FF1(dd, aa, bb, cc, X[11], 14);
+ cc = FF1(cc, dd, aa, bb, X[15], 6);
+ bb = FF1(bb, cc, dd, aa, X[ 0], 14);
+ aa = FF1(aa, bb, cc, dd, X[ 5], 6);
+ dd = FF1(dd, aa, bb, cc, X[12], 9);
+ cc = FF1(cc, dd, aa, bb, X[ 2], 12);
+ bb = FF1(bb, cc, dd, aa, X[13], 9);
+ aa = FF1(aa, bb, cc, dd, X[ 9], 12);
+ dd = FF1(dd, aa, bb, cc, X[ 7], 5);
+ cc = FF1(cc, dd, aa, bb, X[10], 15);
+ bb = FF1(bb, cc, dd, aa, X[14], 8);
+
+ dd += c + H1; // final result for H0
+
+ //
+ // combine the results
+ //
+ H1 = H2 + d + aa;
+ H2 = H3 + a + bb;
+ H3 = H0 + b + cc;
+ H0 = dd;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ public Memoable copy()
+ {
+ return new RIPEMD128Digest(this);
+ }
+
+ public void reset(Memoable other)
+ {
+ RIPEMD128Digest d = (RIPEMD128Digest)other;
+
+ copyIn(d);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/digests/RIPEMD160Digest.java b/core/src/main/java/org/spongycastle/crypto/digests/RIPEMD160Digest.java
new file mode 100644
index 00000000..c59ba7f7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/RIPEMD160Digest.java
@@ -0,0 +1,443 @@
+package org.spongycastle.crypto.digests;
+
+
+import org.spongycastle.util.Memoable;
+
+/**
+ * implementation of RIPEMD see,
+ * http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html
+ */
+public class RIPEMD160Digest
+ extends GeneralDigest
+{
+ private static final int DIGEST_LENGTH = 20;
+
+ private int H0, H1, H2, H3, H4; // IV's
+
+ private int[] X = new int[16];
+ private int xOff;
+
+ /**
+ * Standard constructor
+ */
+ public RIPEMD160Digest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public RIPEMD160Digest(RIPEMD160Digest t)
+ {
+ super(t);
+
+ copyIn(t);
+ }
+
+ private void copyIn(RIPEMD160Digest t)
+ {
+ super.copyIn(t);
+
+ H0 = t.H0;
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+ H4 = t.H4;
+
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "RIPEMD160";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ protected void processWord(
+ byte[] in,
+ int inOff)
+ {
+ X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
+ | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
+
+ if (xOff == 16)
+ {
+ processBlock();
+ }
+ }
+
+ protected void processLength(
+ long bitLength)
+ {
+ if (xOff > 14)
+ {
+ processBlock();
+ }
+
+ X[14] = (int)(bitLength & 0xffffffff);
+ X[15] = (int)(bitLength >>> 32);
+ }
+
+ private void unpackWord(
+ int word,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff] = (byte)word;
+ out[outOff + 1] = (byte)(word >>> 8);
+ out[outOff + 2] = (byte)(word >>> 16);
+ out[outOff + 3] = (byte)(word >>> 24);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ unpackWord(H0, out, outOff);
+ unpackWord(H1, out, outOff + 4);
+ unpackWord(H2, out, outOff + 8);
+ unpackWord(H3, out, outOff + 12);
+ unpackWord(H4, out, outOff + 16);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables to the IV values.
+ */
+ public void reset()
+ {
+ super.reset();
+
+ H0 = 0x67452301;
+ H1 = 0xefcdab89;
+ H2 = 0x98badcfe;
+ H3 = 0x10325476;
+ H4 = 0xc3d2e1f0;
+
+ xOff = 0;
+
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ /*
+ * rotate int x left n bits.
+ */
+ private int RL(
+ int x,
+ int n)
+ {
+ return (x << n) | (x >>> (32 - n));
+ }
+
+ /*
+ * f1,f2,f3,f4,f5 are the basic RIPEMD160 functions.
+ */
+
+ /*
+ * rounds 0-15
+ */
+ private int f1(
+ int x,
+ int y,
+ int z)
+ {
+ return x ^ y ^ z;
+ }
+
+ /*
+ * rounds 16-31
+ */
+ private int f2(
+ int x,
+ int y,
+ int z)
+ {
+ return (x & y) | (~x & z);
+ }
+
+ /*
+ * rounds 32-47
+ */
+ private int f3(
+ int x,
+ int y,
+ int z)
+ {
+ return (x | ~y) ^ z;
+ }
+
+ /*
+ * rounds 48-63
+ */
+ private int f4(
+ int x,
+ int y,
+ int z)
+ {
+ return (x & z) | (y & ~z);
+ }
+
+ /*
+ * rounds 64-79
+ */
+ private int f5(
+ int x,
+ int y,
+ int z)
+ {
+ return x ^ (y | ~z);
+ }
+
+ protected void processBlock()
+ {
+ int a, aa;
+ int b, bb;
+ int c, cc;
+ int d, dd;
+ int e, ee;
+
+ a = aa = H0;
+ b = bb = H1;
+ c = cc = H2;
+ d = dd = H3;
+ e = ee = H4;
+
+ //
+ // Rounds 1 - 16
+ //
+ // left
+ a = RL(a + f1(b,c,d) + X[ 0], 11) + e; c = RL(c, 10);
+ e = RL(e + f1(a,b,c) + X[ 1], 14) + d; b = RL(b, 10);
+ d = RL(d + f1(e,a,b) + X[ 2], 15) + c; a = RL(a, 10);
+ c = RL(c + f1(d,e,a) + X[ 3], 12) + b; e = RL(e, 10);
+ b = RL(b + f1(c,d,e) + X[ 4], 5) + a; d = RL(d, 10);
+ a = RL(a + f1(b,c,d) + X[ 5], 8) + e; c = RL(c, 10);
+ e = RL(e + f1(a,b,c) + X[ 6], 7) + d; b = RL(b, 10);
+ d = RL(d + f1(e,a,b) + X[ 7], 9) + c; a = RL(a, 10);
+ c = RL(c + f1(d,e,a) + X[ 8], 11) + b; e = RL(e, 10);
+ b = RL(b + f1(c,d,e) + X[ 9], 13) + a; d = RL(d, 10);
+ a = RL(a + f1(b,c,d) + X[10], 14) + e; c = RL(c, 10);
+ e = RL(e + f1(a,b,c) + X[11], 15) + d; b = RL(b, 10);
+ d = RL(d + f1(e,a,b) + X[12], 6) + c; a = RL(a, 10);
+ c = RL(c + f1(d,e,a) + X[13], 7) + b; e = RL(e, 10);
+ b = RL(b + f1(c,d,e) + X[14], 9) + a; d = RL(d, 10);
+ a = RL(a + f1(b,c,d) + X[15], 8) + e; c = RL(c, 10);
+
+ // right
+ aa = RL(aa + f5(bb,cc,dd) + X[ 5] + 0x50a28be6, 8) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f5(aa,bb,cc) + X[14] + 0x50a28be6, 9) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f5(ee,aa,bb) + X[ 7] + 0x50a28be6, 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f5(dd,ee,aa) + X[ 0] + 0x50a28be6, 11) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f5(cc,dd,ee) + X[ 9] + 0x50a28be6, 13) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f5(bb,cc,dd) + X[ 2] + 0x50a28be6, 15) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f5(aa,bb,cc) + X[11] + 0x50a28be6, 15) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f5(ee,aa,bb) + X[ 4] + 0x50a28be6, 5) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f5(dd,ee,aa) + X[13] + 0x50a28be6, 7) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f5(cc,dd,ee) + X[ 6] + 0x50a28be6, 7) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f5(bb,cc,dd) + X[15] + 0x50a28be6, 8) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f5(aa,bb,cc) + X[ 8] + 0x50a28be6, 11) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f5(ee,aa,bb) + X[ 1] + 0x50a28be6, 14) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f5(dd,ee,aa) + X[10] + 0x50a28be6, 14) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f5(cc,dd,ee) + X[ 3] + 0x50a28be6, 12) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f5(bb,cc,dd) + X[12] + 0x50a28be6, 6) + ee; cc = RL(cc, 10);
+
+ //
+ // Rounds 16-31
+ //
+ // left
+ e = RL(e + f2(a,b,c) + X[ 7] + 0x5a827999, 7) + d; b = RL(b, 10);
+ d = RL(d + f2(e,a,b) + X[ 4] + 0x5a827999, 6) + c; a = RL(a, 10);
+ c = RL(c + f2(d,e,a) + X[13] + 0x5a827999, 8) + b; e = RL(e, 10);
+ b = RL(b + f2(c,d,e) + X[ 1] + 0x5a827999, 13) + a; d = RL(d, 10);
+ a = RL(a + f2(b,c,d) + X[10] + 0x5a827999, 11) + e; c = RL(c, 10);
+ e = RL(e + f2(a,b,c) + X[ 6] + 0x5a827999, 9) + d; b = RL(b, 10);
+ d = RL(d + f2(e,a,b) + X[15] + 0x5a827999, 7) + c; a = RL(a, 10);
+ c = RL(c + f2(d,e,a) + X[ 3] + 0x5a827999, 15) + b; e = RL(e, 10);
+ b = RL(b + f2(c,d,e) + X[12] + 0x5a827999, 7) + a; d = RL(d, 10);
+ a = RL(a + f2(b,c,d) + X[ 0] + 0x5a827999, 12) + e; c = RL(c, 10);
+ e = RL(e + f2(a,b,c) + X[ 9] + 0x5a827999, 15) + d; b = RL(b, 10);
+ d = RL(d + f2(e,a,b) + X[ 5] + 0x5a827999, 9) + c; a = RL(a, 10);
+ c = RL(c + f2(d,e,a) + X[ 2] + 0x5a827999, 11) + b; e = RL(e, 10);
+ b = RL(b + f2(c,d,e) + X[14] + 0x5a827999, 7) + a; d = RL(d, 10);
+ a = RL(a + f2(b,c,d) + X[11] + 0x5a827999, 13) + e; c = RL(c, 10);
+ e = RL(e + f2(a,b,c) + X[ 8] + 0x5a827999, 12) + d; b = RL(b, 10);
+
+ // right
+ ee = RL(ee + f4(aa,bb,cc) + X[ 6] + 0x5c4dd124, 9) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f4(ee,aa,bb) + X[11] + 0x5c4dd124, 13) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f4(dd,ee,aa) + X[ 3] + 0x5c4dd124, 15) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f4(cc,dd,ee) + X[ 7] + 0x5c4dd124, 7) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f4(bb,cc,dd) + X[ 0] + 0x5c4dd124, 12) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f4(aa,bb,cc) + X[13] + 0x5c4dd124, 8) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f4(ee,aa,bb) + X[ 5] + 0x5c4dd124, 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f4(dd,ee,aa) + X[10] + 0x5c4dd124, 11) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f4(cc,dd,ee) + X[14] + 0x5c4dd124, 7) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f4(bb,cc,dd) + X[15] + 0x5c4dd124, 7) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f4(aa,bb,cc) + X[ 8] + 0x5c4dd124, 12) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f4(ee,aa,bb) + X[12] + 0x5c4dd124, 7) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f4(dd,ee,aa) + X[ 4] + 0x5c4dd124, 6) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f4(cc,dd,ee) + X[ 9] + 0x5c4dd124, 15) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f4(bb,cc,dd) + X[ 1] + 0x5c4dd124, 13) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f4(aa,bb,cc) + X[ 2] + 0x5c4dd124, 11) + dd; bb = RL(bb, 10);
+
+ //
+ // Rounds 32-47
+ //
+ // left
+ d = RL(d + f3(e,a,b) + X[ 3] + 0x6ed9eba1, 11) + c; a = RL(a, 10);
+ c = RL(c + f3(d,e,a) + X[10] + 0x6ed9eba1, 13) + b; e = RL(e, 10);
+ b = RL(b + f3(c,d,e) + X[14] + 0x6ed9eba1, 6) + a; d = RL(d, 10);
+ a = RL(a + f3(b,c,d) + X[ 4] + 0x6ed9eba1, 7) + e; c = RL(c, 10);
+ e = RL(e + f3(a,b,c) + X[ 9] + 0x6ed9eba1, 14) + d; b = RL(b, 10);
+ d = RL(d + f3(e,a,b) + X[15] + 0x6ed9eba1, 9) + c; a = RL(a, 10);
+ c = RL(c + f3(d,e,a) + X[ 8] + 0x6ed9eba1, 13) + b; e = RL(e, 10);
+ b = RL(b + f3(c,d,e) + X[ 1] + 0x6ed9eba1, 15) + a; d = RL(d, 10);
+ a = RL(a + f3(b,c,d) + X[ 2] + 0x6ed9eba1, 14) + e; c = RL(c, 10);
+ e = RL(e + f3(a,b,c) + X[ 7] + 0x6ed9eba1, 8) + d; b = RL(b, 10);
+ d = RL(d + f3(e,a,b) + X[ 0] + 0x6ed9eba1, 13) + c; a = RL(a, 10);
+ c = RL(c + f3(d,e,a) + X[ 6] + 0x6ed9eba1, 6) + b; e = RL(e, 10);
+ b = RL(b + f3(c,d,e) + X[13] + 0x6ed9eba1, 5) + a; d = RL(d, 10);
+ a = RL(a + f3(b,c,d) + X[11] + 0x6ed9eba1, 12) + e; c = RL(c, 10);
+ e = RL(e + f3(a,b,c) + X[ 5] + 0x6ed9eba1, 7) + d; b = RL(b, 10);
+ d = RL(d + f3(e,a,b) + X[12] + 0x6ed9eba1, 5) + c; a = RL(a, 10);
+
+ // right
+ dd = RL(dd + f3(ee,aa,bb) + X[15] + 0x6d703ef3, 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f3(dd,ee,aa) + X[ 5] + 0x6d703ef3, 7) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f3(cc,dd,ee) + X[ 1] + 0x6d703ef3, 15) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f3(bb,cc,dd) + X[ 3] + 0x6d703ef3, 11) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f3(aa,bb,cc) + X[ 7] + 0x6d703ef3, 8) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f3(ee,aa,bb) + X[14] + 0x6d703ef3, 6) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f3(dd,ee,aa) + X[ 6] + 0x6d703ef3, 6) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f3(cc,dd,ee) + X[ 9] + 0x6d703ef3, 14) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f3(bb,cc,dd) + X[11] + 0x6d703ef3, 12) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f3(aa,bb,cc) + X[ 8] + 0x6d703ef3, 13) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f3(ee,aa,bb) + X[12] + 0x6d703ef3, 5) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f3(dd,ee,aa) + X[ 2] + 0x6d703ef3, 14) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f3(cc,dd,ee) + X[10] + 0x6d703ef3, 13) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f3(bb,cc,dd) + X[ 0] + 0x6d703ef3, 13) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f3(aa,bb,cc) + X[ 4] + 0x6d703ef3, 7) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f3(ee,aa,bb) + X[13] + 0x6d703ef3, 5) + cc; aa = RL(aa, 10);
+
+ //
+ // Rounds 48-63
+ //
+ // left
+ c = RL(c + f4(d,e,a) + X[ 1] + 0x8f1bbcdc, 11) + b; e = RL(e, 10);
+ b = RL(b + f4(c,d,e) + X[ 9] + 0x8f1bbcdc, 12) + a; d = RL(d, 10);
+ a = RL(a + f4(b,c,d) + X[11] + 0x8f1bbcdc, 14) + e; c = RL(c, 10);
+ e = RL(e + f4(a,b,c) + X[10] + 0x8f1bbcdc, 15) + d; b = RL(b, 10);
+ d = RL(d + f4(e,a,b) + X[ 0] + 0x8f1bbcdc, 14) + c; a = RL(a, 10);
+ c = RL(c + f4(d,e,a) + X[ 8] + 0x8f1bbcdc, 15) + b; e = RL(e, 10);
+ b = RL(b + f4(c,d,e) + X[12] + 0x8f1bbcdc, 9) + a; d = RL(d, 10);
+ a = RL(a + f4(b,c,d) + X[ 4] + 0x8f1bbcdc, 8) + e; c = RL(c, 10);
+ e = RL(e + f4(a,b,c) + X[13] + 0x8f1bbcdc, 9) + d; b = RL(b, 10);
+ d = RL(d + f4(e,a,b) + X[ 3] + 0x8f1bbcdc, 14) + c; a = RL(a, 10);
+ c = RL(c + f4(d,e,a) + X[ 7] + 0x8f1bbcdc, 5) + b; e = RL(e, 10);
+ b = RL(b + f4(c,d,e) + X[15] + 0x8f1bbcdc, 6) + a; d = RL(d, 10);
+ a = RL(a + f4(b,c,d) + X[14] + 0x8f1bbcdc, 8) + e; c = RL(c, 10);
+ e = RL(e + f4(a,b,c) + X[ 5] + 0x8f1bbcdc, 6) + d; b = RL(b, 10);
+ d = RL(d + f4(e,a,b) + X[ 6] + 0x8f1bbcdc, 5) + c; a = RL(a, 10);
+ c = RL(c + f4(d,e,a) + X[ 2] + 0x8f1bbcdc, 12) + b; e = RL(e, 10);
+
+ // right
+ cc = RL(cc + f2(dd,ee,aa) + X[ 8] + 0x7a6d76e9, 15) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f2(cc,dd,ee) + X[ 6] + 0x7a6d76e9, 5) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f2(bb,cc,dd) + X[ 4] + 0x7a6d76e9, 8) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f2(aa,bb,cc) + X[ 1] + 0x7a6d76e9, 11) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f2(ee,aa,bb) + X[ 3] + 0x7a6d76e9, 14) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f2(dd,ee,aa) + X[11] + 0x7a6d76e9, 14) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f2(cc,dd,ee) + X[15] + 0x7a6d76e9, 6) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f2(bb,cc,dd) + X[ 0] + 0x7a6d76e9, 14) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f2(aa,bb,cc) + X[ 5] + 0x7a6d76e9, 6) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f2(ee,aa,bb) + X[12] + 0x7a6d76e9, 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f2(dd,ee,aa) + X[ 2] + 0x7a6d76e9, 12) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f2(cc,dd,ee) + X[13] + 0x7a6d76e9, 9) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f2(bb,cc,dd) + X[ 9] + 0x7a6d76e9, 12) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f2(aa,bb,cc) + X[ 7] + 0x7a6d76e9, 5) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f2(ee,aa,bb) + X[10] + 0x7a6d76e9, 15) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f2(dd,ee,aa) + X[14] + 0x7a6d76e9, 8) + bb; ee = RL(ee, 10);
+
+ //
+ // Rounds 64-79
+ //
+ // left
+ b = RL(b + f5(c,d,e) + X[ 4] + 0xa953fd4e, 9) + a; d = RL(d, 10);
+ a = RL(a + f5(b,c,d) + X[ 0] + 0xa953fd4e, 15) + e; c = RL(c, 10);
+ e = RL(e + f5(a,b,c) + X[ 5] + 0xa953fd4e, 5) + d; b = RL(b, 10);
+ d = RL(d + f5(e,a,b) + X[ 9] + 0xa953fd4e, 11) + c; a = RL(a, 10);
+ c = RL(c + f5(d,e,a) + X[ 7] + 0xa953fd4e, 6) + b; e = RL(e, 10);
+ b = RL(b + f5(c,d,e) + X[12] + 0xa953fd4e, 8) + a; d = RL(d, 10);
+ a = RL(a + f5(b,c,d) + X[ 2] + 0xa953fd4e, 13) + e; c = RL(c, 10);
+ e = RL(e + f5(a,b,c) + X[10] + 0xa953fd4e, 12) + d; b = RL(b, 10);
+ d = RL(d + f5(e,a,b) + X[14] + 0xa953fd4e, 5) + c; a = RL(a, 10);
+ c = RL(c + f5(d,e,a) + X[ 1] + 0xa953fd4e, 12) + b; e = RL(e, 10);
+ b = RL(b + f5(c,d,e) + X[ 3] + 0xa953fd4e, 13) + a; d = RL(d, 10);
+ a = RL(a + f5(b,c,d) + X[ 8] + 0xa953fd4e, 14) + e; c = RL(c, 10);
+ e = RL(e + f5(a,b,c) + X[11] + 0xa953fd4e, 11) + d; b = RL(b, 10);
+ d = RL(d + f5(e,a,b) + X[ 6] + 0xa953fd4e, 8) + c; a = RL(a, 10);
+ c = RL(c + f5(d,e,a) + X[15] + 0xa953fd4e, 5) + b; e = RL(e, 10);
+ b = RL(b + f5(c,d,e) + X[13] + 0xa953fd4e, 6) + a; d = RL(d, 10);
+
+ // right
+ bb = RL(bb + f1(cc,dd,ee) + X[12], 8) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f1(bb,cc,dd) + X[15], 5) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f1(aa,bb,cc) + X[10], 12) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f1(ee,aa,bb) + X[ 4], 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f1(dd,ee,aa) + X[ 1], 12) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f1(cc,dd,ee) + X[ 5], 5) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f1(bb,cc,dd) + X[ 8], 14) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f1(aa,bb,cc) + X[ 7], 6) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f1(ee,aa,bb) + X[ 6], 8) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f1(dd,ee,aa) + X[ 2], 13) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f1(cc,dd,ee) + X[13], 6) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f1(bb,cc,dd) + X[14], 5) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f1(aa,bb,cc) + X[ 0], 15) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f1(ee,aa,bb) + X[ 3], 13) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f1(dd,ee,aa) + X[ 9], 11) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f1(cc,dd,ee) + X[11], 11) + aa; dd = RL(dd, 10);
+
+ dd += c + H1;
+ H1 = H2 + d + ee;
+ H2 = H3 + e + aa;
+ H3 = H4 + a + bb;
+ H4 = H0 + b + cc;
+ H0 = dd;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ public Memoable copy()
+ {
+ return new RIPEMD160Digest(this);
+ }
+
+ public void reset(Memoable other)
+ {
+ RIPEMD160Digest d = (RIPEMD160Digest)other;
+
+ copyIn(d);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/digests/RIPEMD256Digest.java b/core/src/main/java/org/spongycastle/crypto/digests/RIPEMD256Digest.java
new file mode 100644
index 00000000..45d2bca8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/RIPEMD256Digest.java
@@ -0,0 +1,497 @@
+package org.spongycastle.crypto.digests;
+
+
+import org.spongycastle.util.Memoable;
+
+/**
+ * implementation of RIPEMD256.
+ * <p>
+ * <b>note:</b> this algorithm offers the same level of security as RIPEMD128.
+ */
+public class RIPEMD256Digest
+ extends GeneralDigest
+{
+ private static final int DIGEST_LENGTH = 32;
+
+ private int H0, H1, H2, H3, H4, H5, H6, H7; // IV's
+
+ private int[] X = new int[16];
+ private int xOff;
+
+ /**
+ * Standard constructor
+ */
+ public RIPEMD256Digest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public RIPEMD256Digest(RIPEMD256Digest t)
+ {
+ super(t);
+
+ copyIn(t);
+ }
+
+ private void copyIn(RIPEMD256Digest t)
+ {
+ super.copyIn(t);
+
+ H0 = t.H0;
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+ H4 = t.H4;
+ H5 = t.H5;
+ H6 = t.H6;
+ H7 = t.H7;
+
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "RIPEMD256";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ protected void processWord(
+ byte[] in,
+ int inOff)
+ {
+ X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
+ | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
+
+ if (xOff == 16)
+ {
+ processBlock();
+ }
+ }
+
+ protected void processLength(
+ long bitLength)
+ {
+ if (xOff > 14)
+ {
+ processBlock();
+ }
+
+ X[14] = (int)(bitLength & 0xffffffff);
+ X[15] = (int)(bitLength >>> 32);
+ }
+
+ private void unpackWord(
+ int word,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff] = (byte)word;
+ out[outOff + 1] = (byte)(word >>> 8);
+ out[outOff + 2] = (byte)(word >>> 16);
+ out[outOff + 3] = (byte)(word >>> 24);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ unpackWord(H0, out, outOff);
+ unpackWord(H1, out, outOff + 4);
+ unpackWord(H2, out, outOff + 8);
+ unpackWord(H3, out, outOff + 12);
+ unpackWord(H4, out, outOff + 16);
+ unpackWord(H5, out, outOff + 20);
+ unpackWord(H6, out, outOff + 24);
+ unpackWord(H7, out, outOff + 28);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables to the IV values.
+ */
+ public void reset()
+ {
+ super.reset();
+
+ H0 = 0x67452301;
+ H1 = 0xefcdab89;
+ H2 = 0x98badcfe;
+ H3 = 0x10325476;
+ H4 = 0x76543210;
+ H5 = 0xFEDCBA98;
+ H6 = 0x89ABCDEF;
+ H7 = 0x01234567;
+
+ xOff = 0;
+
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ /*
+ * rotate int x left n bits.
+ */
+ private int RL(
+ int x,
+ int n)
+ {
+ return (x << n) | (x >>> (32 - n));
+ }
+
+ /*
+ * f1,f2,f3,f4 are the basic RIPEMD128 functions.
+ */
+
+ /*
+ * F
+ */
+ private int f1(
+ int x,
+ int y,
+ int z)
+ {
+ return x ^ y ^ z;
+ }
+
+ /*
+ * G
+ */
+ private int f2(
+ int x,
+ int y,
+ int z)
+ {
+ return (x & y) | (~x & z);
+ }
+
+ /*
+ * H
+ */
+ private int f3(
+ int x,
+ int y,
+ int z)
+ {
+ return (x | ~y) ^ z;
+ }
+
+ /*
+ * I
+ */
+ private int f4(
+ int x,
+ int y,
+ int z)
+ {
+ return (x & z) | (y & ~z);
+ }
+
+ private int F1(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f1(b, c, d) + x, s);
+ }
+
+ private int F2(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f2(b, c, d) + x + 0x5a827999, s);
+ }
+
+ private int F3(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f3(b, c, d) + x + 0x6ed9eba1, s);
+ }
+
+ private int F4(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f4(b, c, d) + x + 0x8f1bbcdc, s);
+ }
+
+ private int FF1(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f1(b, c, d) + x, s);
+ }
+
+ private int FF2(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f2(b, c, d) + x + 0x6d703ef3, s);
+ }
+
+ private int FF3(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f3(b, c, d) + x + 0x5c4dd124, s);
+ }
+
+ private int FF4(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f4(b, c, d) + x + 0x50a28be6, s);
+ }
+
+ protected void processBlock()
+ {
+ int a, aa;
+ int b, bb;
+ int c, cc;
+ int d, dd;
+ int t;
+
+ a = H0;
+ b = H1;
+ c = H2;
+ d = H3;
+ aa = H4;
+ bb = H5;
+ cc = H6;
+ dd = H7;
+
+ //
+ // Round 1
+ //
+
+ a = F1(a, b, c, d, X[ 0], 11);
+ d = F1(d, a, b, c, X[ 1], 14);
+ c = F1(c, d, a, b, X[ 2], 15);
+ b = F1(b, c, d, a, X[ 3], 12);
+ a = F1(a, b, c, d, X[ 4], 5);
+ d = F1(d, a, b, c, X[ 5], 8);
+ c = F1(c, d, a, b, X[ 6], 7);
+ b = F1(b, c, d, a, X[ 7], 9);
+ a = F1(a, b, c, d, X[ 8], 11);
+ d = F1(d, a, b, c, X[ 9], 13);
+ c = F1(c, d, a, b, X[10], 14);
+ b = F1(b, c, d, a, X[11], 15);
+ a = F1(a, b, c, d, X[12], 6);
+ d = F1(d, a, b, c, X[13], 7);
+ c = F1(c, d, a, b, X[14], 9);
+ b = F1(b, c, d, a, X[15], 8);
+
+ aa = FF4(aa, bb, cc, dd, X[ 5], 8);
+ dd = FF4(dd, aa, bb, cc, X[14], 9);
+ cc = FF4(cc, dd, aa, bb, X[ 7], 9);
+ bb = FF4(bb, cc, dd, aa, X[ 0], 11);
+ aa = FF4(aa, bb, cc, dd, X[ 9], 13);
+ dd = FF4(dd, aa, bb, cc, X[ 2], 15);
+ cc = FF4(cc, dd, aa, bb, X[11], 15);
+ bb = FF4(bb, cc, dd, aa, X[ 4], 5);
+ aa = FF4(aa, bb, cc, dd, X[13], 7);
+ dd = FF4(dd, aa, bb, cc, X[ 6], 7);
+ cc = FF4(cc, dd, aa, bb, X[15], 8);
+ bb = FF4(bb, cc, dd, aa, X[ 8], 11);
+ aa = FF4(aa, bb, cc, dd, X[ 1], 14);
+ dd = FF4(dd, aa, bb, cc, X[10], 14);
+ cc = FF4(cc, dd, aa, bb, X[ 3], 12);
+ bb = FF4(bb, cc, dd, aa, X[12], 6);
+
+ t = a; a = aa; aa = t;
+
+ //
+ // Round 2
+ //
+ a = F2(a, b, c, d, X[ 7], 7);
+ d = F2(d, a, b, c, X[ 4], 6);
+ c = F2(c, d, a, b, X[13], 8);
+ b = F2(b, c, d, a, X[ 1], 13);
+ a = F2(a, b, c, d, X[10], 11);
+ d = F2(d, a, b, c, X[ 6], 9);
+ c = F2(c, d, a, b, X[15], 7);
+ b = F2(b, c, d, a, X[ 3], 15);
+ a = F2(a, b, c, d, X[12], 7);
+ d = F2(d, a, b, c, X[ 0], 12);
+ c = F2(c, d, a, b, X[ 9], 15);
+ b = F2(b, c, d, a, X[ 5], 9);
+ a = F2(a, b, c, d, X[ 2], 11);
+ d = F2(d, a, b, c, X[14], 7);
+ c = F2(c, d, a, b, X[11], 13);
+ b = F2(b, c, d, a, X[ 8], 12);
+
+ aa = FF3(aa, bb, cc, dd, X[ 6], 9);
+ dd = FF3(dd, aa, bb, cc, X[ 11], 13);
+ cc = FF3(cc, dd, aa, bb, X[3], 15);
+ bb = FF3(bb, cc, dd, aa, X[ 7], 7);
+ aa = FF3(aa, bb, cc, dd, X[0], 12);
+ dd = FF3(dd, aa, bb, cc, X[13], 8);
+ cc = FF3(cc, dd, aa, bb, X[5], 9);
+ bb = FF3(bb, cc, dd, aa, X[10], 11);
+ aa = FF3(aa, bb, cc, dd, X[14], 7);
+ dd = FF3(dd, aa, bb, cc, X[15], 7);
+ cc = FF3(cc, dd, aa, bb, X[ 8], 12);
+ bb = FF3(bb, cc, dd, aa, X[12], 7);
+ aa = FF3(aa, bb, cc, dd, X[ 4], 6);
+ dd = FF3(dd, aa, bb, cc, X[ 9], 15);
+ cc = FF3(cc, dd, aa, bb, X[ 1], 13);
+ bb = FF3(bb, cc, dd, aa, X[ 2], 11);
+
+ t = b; b = bb; bb = t;
+
+ //
+ // Round 3
+ //
+ a = F3(a, b, c, d, X[ 3], 11);
+ d = F3(d, a, b, c, X[10], 13);
+ c = F3(c, d, a, b, X[14], 6);
+ b = F3(b, c, d, a, X[ 4], 7);
+ a = F3(a, b, c, d, X[ 9], 14);
+ d = F3(d, a, b, c, X[15], 9);
+ c = F3(c, d, a, b, X[ 8], 13);
+ b = F3(b, c, d, a, X[ 1], 15);
+ a = F3(a, b, c, d, X[ 2], 14);
+ d = F3(d, a, b, c, X[ 7], 8);
+ c = F3(c, d, a, b, X[ 0], 13);
+ b = F3(b, c, d, a, X[ 6], 6);
+ a = F3(a, b, c, d, X[13], 5);
+ d = F3(d, a, b, c, X[11], 12);
+ c = F3(c, d, a, b, X[ 5], 7);
+ b = F3(b, c, d, a, X[12], 5);
+
+ aa = FF2(aa, bb, cc, dd, X[ 15], 9);
+ dd = FF2(dd, aa, bb, cc, X[5], 7);
+ cc = FF2(cc, dd, aa, bb, X[1], 15);
+ bb = FF2(bb, cc, dd, aa, X[ 3], 11);
+ aa = FF2(aa, bb, cc, dd, X[ 7], 8);
+ dd = FF2(dd, aa, bb, cc, X[14], 6);
+ cc = FF2(cc, dd, aa, bb, X[ 6], 6);
+ bb = FF2(bb, cc, dd, aa, X[ 9], 14);
+ aa = FF2(aa, bb, cc, dd, X[11], 12);
+ dd = FF2(dd, aa, bb, cc, X[ 8], 13);
+ cc = FF2(cc, dd, aa, bb, X[12], 5);
+ bb = FF2(bb, cc, dd, aa, X[ 2], 14);
+ aa = FF2(aa, bb, cc, dd, X[10], 13);
+ dd = FF2(dd, aa, bb, cc, X[ 0], 13);
+ cc = FF2(cc, dd, aa, bb, X[ 4], 7);
+ bb = FF2(bb, cc, dd, aa, X[13], 5);
+
+ t = c; c = cc; cc = t;
+
+ //
+ // Round 4
+ //
+ a = F4(a, b, c, d, X[ 1], 11);
+ d = F4(d, a, b, c, X[ 9], 12);
+ c = F4(c, d, a, b, X[11], 14);
+ b = F4(b, c, d, a, X[10], 15);
+ a = F4(a, b, c, d, X[ 0], 14);
+ d = F4(d, a, b, c, X[ 8], 15);
+ c = F4(c, d, a, b, X[12], 9);
+ b = F4(b, c, d, a, X[ 4], 8);
+ a = F4(a, b, c, d, X[13], 9);
+ d = F4(d, a, b, c, X[ 3], 14);
+ c = F4(c, d, a, b, X[ 7], 5);
+ b = F4(b, c, d, a, X[15], 6);
+ a = F4(a, b, c, d, X[14], 8);
+ d = F4(d, a, b, c, X[ 5], 6);
+ c = F4(c, d, a, b, X[ 6], 5);
+ b = F4(b, c, d, a, X[ 2], 12);
+
+ aa = FF1(aa, bb, cc, dd, X[ 8], 15);
+ dd = FF1(dd, aa, bb, cc, X[ 6], 5);
+ cc = FF1(cc, dd, aa, bb, X[ 4], 8);
+ bb = FF1(bb, cc, dd, aa, X[ 1], 11);
+ aa = FF1(aa, bb, cc, dd, X[ 3], 14);
+ dd = FF1(dd, aa, bb, cc, X[11], 14);
+ cc = FF1(cc, dd, aa, bb, X[15], 6);
+ bb = FF1(bb, cc, dd, aa, X[ 0], 14);
+ aa = FF1(aa, bb, cc, dd, X[ 5], 6);
+ dd = FF1(dd, aa, bb, cc, X[12], 9);
+ cc = FF1(cc, dd, aa, bb, X[ 2], 12);
+ bb = FF1(bb, cc, dd, aa, X[13], 9);
+ aa = FF1(aa, bb, cc, dd, X[ 9], 12);
+ dd = FF1(dd, aa, bb, cc, X[ 7], 5);
+ cc = FF1(cc, dd, aa, bb, X[10], 15);
+ bb = FF1(bb, cc, dd, aa, X[14], 8);
+
+ t = d; d = dd; dd = t;
+
+ H0 += a;
+ H1 += b;
+ H2 += c;
+ H3 += d;
+ H4 += aa;
+ H5 += bb;
+ H6 += cc;
+ H7 += dd;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ public Memoable copy()
+ {
+ return new RIPEMD256Digest(this);
+ }
+
+ public void reset(Memoable other)
+ {
+ RIPEMD256Digest d = (RIPEMD256Digest)other;
+
+ copyIn(d);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/digests/RIPEMD320Digest.java b/core/src/main/java/org/spongycastle/crypto/digests/RIPEMD320Digest.java
new file mode 100644
index 00000000..e3d7286c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/RIPEMD320Digest.java
@@ -0,0 +1,481 @@
+package org.spongycastle.crypto.digests;
+
+
+import org.spongycastle.util.Memoable;
+
+/**
+ * implementation of RIPEMD 320.
+ * <p>
+ * <b>Note:</b> this implementation offers the same level of security
+ * as RIPEMD 160.
+ */
+public class RIPEMD320Digest
+ extends GeneralDigest
+{
+ private static final int DIGEST_LENGTH = 40;
+
+ private int H0, H1, H2, H3, H4, H5, H6, H7, H8, H9; // IV's
+
+ private int[] X = new int[16];
+ private int xOff;
+
+ /**
+ * Standard constructor
+ */
+ public RIPEMD320Digest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public RIPEMD320Digest(RIPEMD320Digest t)
+ {
+ super(t);
+
+ doCopy(t);
+ }
+
+ private void doCopy(RIPEMD320Digest t)
+ {
+ super.copyIn(t);
+ H0 = t.H0;
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+ H4 = t.H4;
+ H5 = t.H5;
+ H6 = t.H6;
+ H7 = t.H7;
+ H8 = t.H8;
+ H9 = t.H9;
+
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "RIPEMD320";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ protected void processWord(
+ byte[] in,
+ int inOff)
+ {
+ X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
+ | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
+
+ if (xOff == 16)
+ {
+ processBlock();
+ }
+ }
+
+ protected void processLength(
+ long bitLength)
+ {
+ if (xOff > 14)
+ {
+ processBlock();
+ }
+
+ X[14] = (int)(bitLength & 0xffffffff);
+ X[15] = (int)(bitLength >>> 32);
+ }
+
+ private void unpackWord(
+ int word,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff] = (byte)word;
+ out[outOff + 1] = (byte)(word >>> 8);
+ out[outOff + 2] = (byte)(word >>> 16);
+ out[outOff + 3] = (byte)(word >>> 24);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ unpackWord(H0, out, outOff);
+ unpackWord(H1, out, outOff + 4);
+ unpackWord(H2, out, outOff + 8);
+ unpackWord(H3, out, outOff + 12);
+ unpackWord(H4, out, outOff + 16);
+ unpackWord(H5, out, outOff + 20);
+ unpackWord(H6, out, outOff + 24);
+ unpackWord(H7, out, outOff + 28);
+ unpackWord(H8, out, outOff + 32);
+ unpackWord(H9, out, outOff + 36);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables to the IV values.
+ */
+ public void reset()
+ {
+ super.reset();
+
+ H0 = 0x67452301;
+ H1 = 0xefcdab89;
+ H2 = 0x98badcfe;
+ H3 = 0x10325476;
+ H4 = 0xc3d2e1f0;
+ H5 = 0x76543210;
+ H6 = 0xFEDCBA98;
+ H7 = 0x89ABCDEF;
+ H8 = 0x01234567;
+ H9 = 0x3C2D1E0F;
+
+ xOff = 0;
+
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ /*
+ * rotate int x left n bits.
+ */
+ private int RL(
+ int x,
+ int n)
+ {
+ return (x << n) | (x >>> (32 - n));
+ }
+
+ /*
+ * f1,f2,f3,f4,f5 are the basic RIPEMD160 functions.
+ */
+
+ /*
+ * rounds 0-15
+ */
+ private int f1(
+ int x,
+ int y,
+ int z)
+ {
+ return x ^ y ^ z;
+ }
+
+ /*
+ * rounds 16-31
+ */
+ private int f2(
+ int x,
+ int y,
+ int z)
+ {
+ return (x & y) | (~x & z);
+ }
+
+ /*
+ * rounds 32-47
+ */
+ private int f3(
+ int x,
+ int y,
+ int z)
+ {
+ return (x | ~y) ^ z;
+ }
+
+ /*
+ * rounds 48-63
+ */
+ private int f4(
+ int x,
+ int y,
+ int z)
+ {
+ return (x & z) | (y & ~z);
+ }
+
+ /*
+ * rounds 64-79
+ */
+ private int f5(
+ int x,
+ int y,
+ int z)
+ {
+ return x ^ (y | ~z);
+ }
+
+ protected void processBlock()
+ {
+ int a, aa;
+ int b, bb;
+ int c, cc;
+ int d, dd;
+ int e, ee;
+ int t;
+
+ a = H0;
+ b = H1;
+ c = H2;
+ d = H3;
+ e = H4;
+ aa = H5;
+ bb = H6;
+ cc = H7;
+ dd = H8;
+ ee = H9;
+
+ //
+ // Rounds 1 - 16
+ //
+ // left
+ a = RL(a + f1(b,c,d) + X[ 0], 11) + e; c = RL(c, 10);
+ e = RL(e + f1(a,b,c) + X[ 1], 14) + d; b = RL(b, 10);
+ d = RL(d + f1(e,a,b) + X[ 2], 15) + c; a = RL(a, 10);
+ c = RL(c + f1(d,e,a) + X[ 3], 12) + b; e = RL(e, 10);
+ b = RL(b + f1(c,d,e) + X[ 4], 5) + a; d = RL(d, 10);
+ a = RL(a + f1(b,c,d) + X[ 5], 8) + e; c = RL(c, 10);
+ e = RL(e + f1(a,b,c) + X[ 6], 7) + d; b = RL(b, 10);
+ d = RL(d + f1(e,a,b) + X[ 7], 9) + c; a = RL(a, 10);
+ c = RL(c + f1(d,e,a) + X[ 8], 11) + b; e = RL(e, 10);
+ b = RL(b + f1(c,d,e) + X[ 9], 13) + a; d = RL(d, 10);
+ a = RL(a + f1(b,c,d) + X[10], 14) + e; c = RL(c, 10);
+ e = RL(e + f1(a,b,c) + X[11], 15) + d; b = RL(b, 10);
+ d = RL(d + f1(e,a,b) + X[12], 6) + c; a = RL(a, 10);
+ c = RL(c + f1(d,e,a) + X[13], 7) + b; e = RL(e, 10);
+ b = RL(b + f1(c,d,e) + X[14], 9) + a; d = RL(d, 10);
+ a = RL(a + f1(b,c,d) + X[15], 8) + e; c = RL(c, 10);
+
+ // right
+ aa = RL(aa + f5(bb,cc,dd) + X[ 5] + 0x50a28be6, 8) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f5(aa,bb,cc) + X[14] + 0x50a28be6, 9) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f5(ee,aa,bb) + X[ 7] + 0x50a28be6, 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f5(dd,ee,aa) + X[ 0] + 0x50a28be6, 11) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f5(cc,dd,ee) + X[ 9] + 0x50a28be6, 13) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f5(bb,cc,dd) + X[ 2] + 0x50a28be6, 15) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f5(aa,bb,cc) + X[11] + 0x50a28be6, 15) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f5(ee,aa,bb) + X[ 4] + 0x50a28be6, 5) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f5(dd,ee,aa) + X[13] + 0x50a28be6, 7) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f5(cc,dd,ee) + X[ 6] + 0x50a28be6, 7) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f5(bb,cc,dd) + X[15] + 0x50a28be6, 8) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f5(aa,bb,cc) + X[ 8] + 0x50a28be6, 11) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f5(ee,aa,bb) + X[ 1] + 0x50a28be6, 14) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f5(dd,ee,aa) + X[10] + 0x50a28be6, 14) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f5(cc,dd,ee) + X[ 3] + 0x50a28be6, 12) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f5(bb,cc,dd) + X[12] + 0x50a28be6, 6) + ee; cc = RL(cc, 10);
+
+ t = a; a = aa; aa = t;
+
+ //
+ // Rounds 16-31
+ //
+ // left
+ e = RL(e + f2(a,b,c) + X[ 7] + 0x5a827999, 7) + d; b = RL(b, 10);
+ d = RL(d + f2(e,a,b) + X[ 4] + 0x5a827999, 6) + c; a = RL(a, 10);
+ c = RL(c + f2(d,e,a) + X[13] + 0x5a827999, 8) + b; e = RL(e, 10);
+ b = RL(b + f2(c,d,e) + X[ 1] + 0x5a827999, 13) + a; d = RL(d, 10);
+ a = RL(a + f2(b,c,d) + X[10] + 0x5a827999, 11) + e; c = RL(c, 10);
+ e = RL(e + f2(a,b,c) + X[ 6] + 0x5a827999, 9) + d; b = RL(b, 10);
+ d = RL(d + f2(e,a,b) + X[15] + 0x5a827999, 7) + c; a = RL(a, 10);
+ c = RL(c + f2(d,e,a) + X[ 3] + 0x5a827999, 15) + b; e = RL(e, 10);
+ b = RL(b + f2(c,d,e) + X[12] + 0x5a827999, 7) + a; d = RL(d, 10);
+ a = RL(a + f2(b,c,d) + X[ 0] + 0x5a827999, 12) + e; c = RL(c, 10);
+ e = RL(e + f2(a,b,c) + X[ 9] + 0x5a827999, 15) + d; b = RL(b, 10);
+ d = RL(d + f2(e,a,b) + X[ 5] + 0x5a827999, 9) + c; a = RL(a, 10);
+ c = RL(c + f2(d,e,a) + X[ 2] + 0x5a827999, 11) + b; e = RL(e, 10);
+ b = RL(b + f2(c,d,e) + X[14] + 0x5a827999, 7) + a; d = RL(d, 10);
+ a = RL(a + f2(b,c,d) + X[11] + 0x5a827999, 13) + e; c = RL(c, 10);
+ e = RL(e + f2(a,b,c) + X[ 8] + 0x5a827999, 12) + d; b = RL(b, 10);
+
+ // right
+ ee = RL(ee + f4(aa,bb,cc) + X[ 6] + 0x5c4dd124, 9) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f4(ee,aa,bb) + X[11] + 0x5c4dd124, 13) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f4(dd,ee,aa) + X[ 3] + 0x5c4dd124, 15) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f4(cc,dd,ee) + X[ 7] + 0x5c4dd124, 7) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f4(bb,cc,dd) + X[ 0] + 0x5c4dd124, 12) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f4(aa,bb,cc) + X[13] + 0x5c4dd124, 8) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f4(ee,aa,bb) + X[ 5] + 0x5c4dd124, 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f4(dd,ee,aa) + X[10] + 0x5c4dd124, 11) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f4(cc,dd,ee) + X[14] + 0x5c4dd124, 7) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f4(bb,cc,dd) + X[15] + 0x5c4dd124, 7) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f4(aa,bb,cc) + X[ 8] + 0x5c4dd124, 12) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f4(ee,aa,bb) + X[12] + 0x5c4dd124, 7) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f4(dd,ee,aa) + X[ 4] + 0x5c4dd124, 6) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f4(cc,dd,ee) + X[ 9] + 0x5c4dd124, 15) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f4(bb,cc,dd) + X[ 1] + 0x5c4dd124, 13) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f4(aa,bb,cc) + X[ 2] + 0x5c4dd124, 11) + dd; bb = RL(bb, 10);
+
+ t = b; b = bb; bb = t;
+
+ //
+ // Rounds 32-47
+ //
+ // left
+ d = RL(d + f3(e,a,b) + X[ 3] + 0x6ed9eba1, 11) + c; a = RL(a, 10);
+ c = RL(c + f3(d,e,a) + X[10] + 0x6ed9eba1, 13) + b; e = RL(e, 10);
+ b = RL(b + f3(c,d,e) + X[14] + 0x6ed9eba1, 6) + a; d = RL(d, 10);
+ a = RL(a + f3(b,c,d) + X[ 4] + 0x6ed9eba1, 7) + e; c = RL(c, 10);
+ e = RL(e + f3(a,b,c) + X[ 9] + 0x6ed9eba1, 14) + d; b = RL(b, 10);
+ d = RL(d + f3(e,a,b) + X[15] + 0x6ed9eba1, 9) + c; a = RL(a, 10);
+ c = RL(c + f3(d,e,a) + X[ 8] + 0x6ed9eba1, 13) + b; e = RL(e, 10);
+ b = RL(b + f3(c,d,e) + X[ 1] + 0x6ed9eba1, 15) + a; d = RL(d, 10);
+ a = RL(a + f3(b,c,d) + X[ 2] + 0x6ed9eba1, 14) + e; c = RL(c, 10);
+ e = RL(e + f3(a,b,c) + X[ 7] + 0x6ed9eba1, 8) + d; b = RL(b, 10);
+ d = RL(d + f3(e,a,b) + X[ 0] + 0x6ed9eba1, 13) + c; a = RL(a, 10);
+ c = RL(c + f3(d,e,a) + X[ 6] + 0x6ed9eba1, 6) + b; e = RL(e, 10);
+ b = RL(b + f3(c,d,e) + X[13] + 0x6ed9eba1, 5) + a; d = RL(d, 10);
+ a = RL(a + f3(b,c,d) + X[11] + 0x6ed9eba1, 12) + e; c = RL(c, 10);
+ e = RL(e + f3(a,b,c) + X[ 5] + 0x6ed9eba1, 7) + d; b = RL(b, 10);
+ d = RL(d + f3(e,a,b) + X[12] + 0x6ed9eba1, 5) + c; a = RL(a, 10);
+
+ // right
+ dd = RL(dd + f3(ee,aa,bb) + X[15] + 0x6d703ef3, 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f3(dd,ee,aa) + X[ 5] + 0x6d703ef3, 7) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f3(cc,dd,ee) + X[ 1] + 0x6d703ef3, 15) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f3(bb,cc,dd) + X[ 3] + 0x6d703ef3, 11) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f3(aa,bb,cc) + X[ 7] + 0x6d703ef3, 8) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f3(ee,aa,bb) + X[14] + 0x6d703ef3, 6) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f3(dd,ee,aa) + X[ 6] + 0x6d703ef3, 6) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f3(cc,dd,ee) + X[ 9] + 0x6d703ef3, 14) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f3(bb,cc,dd) + X[11] + 0x6d703ef3, 12) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f3(aa,bb,cc) + X[ 8] + 0x6d703ef3, 13) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f3(ee,aa,bb) + X[12] + 0x6d703ef3, 5) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f3(dd,ee,aa) + X[ 2] + 0x6d703ef3, 14) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f3(cc,dd,ee) + X[10] + 0x6d703ef3, 13) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f3(bb,cc,dd) + X[ 0] + 0x6d703ef3, 13) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f3(aa,bb,cc) + X[ 4] + 0x6d703ef3, 7) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f3(ee,aa,bb) + X[13] + 0x6d703ef3, 5) + cc; aa = RL(aa, 10);
+
+ t = c; c = cc; cc = t;
+
+ //
+ // Rounds 48-63
+ //
+ // left
+ c = RL(c + f4(d,e,a) + X[ 1] + 0x8f1bbcdc, 11) + b; e = RL(e, 10);
+ b = RL(b + f4(c,d,e) + X[ 9] + 0x8f1bbcdc, 12) + a; d = RL(d, 10);
+ a = RL(a + f4(b,c,d) + X[11] + 0x8f1bbcdc, 14) + e; c = RL(c, 10);
+ e = RL(e + f4(a,b,c) + X[10] + 0x8f1bbcdc, 15) + d; b = RL(b, 10);
+ d = RL(d + f4(e,a,b) + X[ 0] + 0x8f1bbcdc, 14) + c; a = RL(a, 10);
+ c = RL(c + f4(d,e,a) + X[ 8] + 0x8f1bbcdc, 15) + b; e = RL(e, 10);
+ b = RL(b + f4(c,d,e) + X[12] + 0x8f1bbcdc, 9) + a; d = RL(d, 10);
+ a = RL(a + f4(b,c,d) + X[ 4] + 0x8f1bbcdc, 8) + e; c = RL(c, 10);
+ e = RL(e + f4(a,b,c) + X[13] + 0x8f1bbcdc, 9) + d; b = RL(b, 10);
+ d = RL(d + f4(e,a,b) + X[ 3] + 0x8f1bbcdc, 14) + c; a = RL(a, 10);
+ c = RL(c + f4(d,e,a) + X[ 7] + 0x8f1bbcdc, 5) + b; e = RL(e, 10);
+ b = RL(b + f4(c,d,e) + X[15] + 0x8f1bbcdc, 6) + a; d = RL(d, 10);
+ a = RL(a + f4(b,c,d) + X[14] + 0x8f1bbcdc, 8) + e; c = RL(c, 10);
+ e = RL(e + f4(a,b,c) + X[ 5] + 0x8f1bbcdc, 6) + d; b = RL(b, 10);
+ d = RL(d + f4(e,a,b) + X[ 6] + 0x8f1bbcdc, 5) + c; a = RL(a, 10);
+ c = RL(c + f4(d,e,a) + X[ 2] + 0x8f1bbcdc, 12) + b; e = RL(e, 10);
+
+ // right
+ cc = RL(cc + f2(dd,ee,aa) + X[ 8] + 0x7a6d76e9, 15) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f2(cc,dd,ee) + X[ 6] + 0x7a6d76e9, 5) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f2(bb,cc,dd) + X[ 4] + 0x7a6d76e9, 8) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f2(aa,bb,cc) + X[ 1] + 0x7a6d76e9, 11) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f2(ee,aa,bb) + X[ 3] + 0x7a6d76e9, 14) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f2(dd,ee,aa) + X[11] + 0x7a6d76e9, 14) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f2(cc,dd,ee) + X[15] + 0x7a6d76e9, 6) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f2(bb,cc,dd) + X[ 0] + 0x7a6d76e9, 14) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f2(aa,bb,cc) + X[ 5] + 0x7a6d76e9, 6) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f2(ee,aa,bb) + X[12] + 0x7a6d76e9, 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f2(dd,ee,aa) + X[ 2] + 0x7a6d76e9, 12) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f2(cc,dd,ee) + X[13] + 0x7a6d76e9, 9) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f2(bb,cc,dd) + X[ 9] + 0x7a6d76e9, 12) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f2(aa,bb,cc) + X[ 7] + 0x7a6d76e9, 5) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f2(ee,aa,bb) + X[10] + 0x7a6d76e9, 15) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f2(dd,ee,aa) + X[14] + 0x7a6d76e9, 8) + bb; ee = RL(ee, 10);
+
+ t = d; d = dd; dd = t;
+
+ //
+ // Rounds 64-79
+ //
+ // left
+ b = RL(b + f5(c,d,e) + X[ 4] + 0xa953fd4e, 9) + a; d = RL(d, 10);
+ a = RL(a + f5(b,c,d) + X[ 0] + 0xa953fd4e, 15) + e; c = RL(c, 10);
+ e = RL(e + f5(a,b,c) + X[ 5] + 0xa953fd4e, 5) + d; b = RL(b, 10);
+ d = RL(d + f5(e,a,b) + X[ 9] + 0xa953fd4e, 11) + c; a = RL(a, 10);
+ c = RL(c + f5(d,e,a) + X[ 7] + 0xa953fd4e, 6) + b; e = RL(e, 10);
+ b = RL(b + f5(c,d,e) + X[12] + 0xa953fd4e, 8) + a; d = RL(d, 10);
+ a = RL(a + f5(b,c,d) + X[ 2] + 0xa953fd4e, 13) + e; c = RL(c, 10);
+ e = RL(e + f5(a,b,c) + X[10] + 0xa953fd4e, 12) + d; b = RL(b, 10);
+ d = RL(d + f5(e,a,b) + X[14] + 0xa953fd4e, 5) + c; a = RL(a, 10);
+ c = RL(c + f5(d,e,a) + X[ 1] + 0xa953fd4e, 12) + b; e = RL(e, 10);
+ b = RL(b + f5(c,d,e) + X[ 3] + 0xa953fd4e, 13) + a; d = RL(d, 10);
+ a = RL(a + f5(b,c,d) + X[ 8] + 0xa953fd4e, 14) + e; c = RL(c, 10);
+ e = RL(e + f5(a,b,c) + X[11] + 0xa953fd4e, 11) + d; b = RL(b, 10);
+ d = RL(d + f5(e,a,b) + X[ 6] + 0xa953fd4e, 8) + c; a = RL(a, 10);
+ c = RL(c + f5(d,e,a) + X[15] + 0xa953fd4e, 5) + b; e = RL(e, 10);
+ b = RL(b + f5(c,d,e) + X[13] + 0xa953fd4e, 6) + a; d = RL(d, 10);
+
+ // right
+ bb = RL(bb + f1(cc,dd,ee) + X[12], 8) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f1(bb,cc,dd) + X[15], 5) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f1(aa,bb,cc) + X[10], 12) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f1(ee,aa,bb) + X[ 4], 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f1(dd,ee,aa) + X[ 1], 12) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f1(cc,dd,ee) + X[ 5], 5) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f1(bb,cc,dd) + X[ 8], 14) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f1(aa,bb,cc) + X[ 7], 6) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f1(ee,aa,bb) + X[ 6], 8) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f1(dd,ee,aa) + X[ 2], 13) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f1(cc,dd,ee) + X[13], 6) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f1(bb,cc,dd) + X[14], 5) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f1(aa,bb,cc) + X[ 0], 15) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f1(ee,aa,bb) + X[ 3], 13) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f1(dd,ee,aa) + X[ 9], 11) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f1(cc,dd,ee) + X[11], 11) + aa; dd = RL(dd, 10);
+
+ //
+ // do (e, ee) swap as part of assignment.
+ //
+
+ H0 += a;
+ H1 += b;
+ H2 += c;
+ H3 += d;
+ H4 += ee;
+ H5 += aa;
+ H6 += bb;
+ H7 += cc;
+ H8 += dd;
+ H9 += e;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ public Memoable copy()
+ {
+ return new RIPEMD320Digest(this);
+ }
+
+ public void reset(Memoable other)
+ {
+ RIPEMD320Digest d = (RIPEMD320Digest)other;
+
+ doCopy(d);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/digests/SHA1Digest.java b/core/src/main/java/org/spongycastle/crypto/digests/SHA1Digest.java
new file mode 100644
index 00000000..57df0c1e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/SHA1Digest.java
@@ -0,0 +1,348 @@
+package org.spongycastle.crypto.digests;
+
+import org.spongycastle.util.Memoable;
+import org.spongycastle.util.Pack;
+
+/**
+ * implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", pages 346 - 349.
+ *
+ * It is interesting to ponder why the, apart from the extra IV, the other difference here from MD5
+ * is the "endianness" of the word processing!
+ */
+public class SHA1Digest
+ extends GeneralDigest
+ implements EncodableDigest
+{
+ private static final int DIGEST_LENGTH = 20;
+
+ private int H1, H2, H3, H4, H5;
+
+ private int[] X = new int[80];
+ private int xOff;
+
+ /**
+ * Standard constructor
+ */
+ public SHA1Digest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public SHA1Digest(SHA1Digest t)
+ {
+ super(t);
+
+ copyIn(t);
+ }
+
+ public SHA1Digest(byte[] encodedState)
+ {
+ super(encodedState);
+
+ H1 = Pack.bigEndianToInt(encodedState, 16);
+ H2 = Pack.bigEndianToInt(encodedState, 20);
+ H3 = Pack.bigEndianToInt(encodedState, 24);
+ H4 = Pack.bigEndianToInt(encodedState, 28);
+ H5 = Pack.bigEndianToInt(encodedState, 32);
+
+ xOff = Pack.bigEndianToInt(encodedState, 36);
+ for (int i = 0; i != xOff; i++)
+ {
+ X[i] = Pack.bigEndianToInt(encodedState, 40 + (i * 4));
+ }
+ }
+
+ private void copyIn(SHA1Digest t)
+ {
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+ H4 = t.H4;
+ H5 = t.H5;
+
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "SHA-1";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ protected void processWord(
+ byte[] in,
+ int inOff)
+ {
+ // Note: Inlined for performance
+// X[xOff] = Pack.bigEndianToInt(in, inOff);
+ int n = in[ inOff] << 24;
+ n |= (in[++inOff] & 0xff) << 16;
+ n |= (in[++inOff] & 0xff) << 8;
+ n |= (in[++inOff] & 0xff);
+ X[xOff] = n;
+
+ if (++xOff == 16)
+ {
+ processBlock();
+ }
+ }
+
+ protected void processLength(
+ long bitLength)
+ {
+ if (xOff > 14)
+ {
+ processBlock();
+ }
+
+ X[14] = (int)(bitLength >>> 32);
+ X[15] = (int)(bitLength & 0xffffffff);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ Pack.intToBigEndian(H1, out, outOff);
+ Pack.intToBigEndian(H2, out, outOff + 4);
+ Pack.intToBigEndian(H3, out, outOff + 8);
+ Pack.intToBigEndian(H4, out, outOff + 12);
+ Pack.intToBigEndian(H5, out, outOff + 16);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables
+ */
+ public void reset()
+ {
+ super.reset();
+
+ H1 = 0x67452301;
+ H2 = 0xefcdab89;
+ H3 = 0x98badcfe;
+ H4 = 0x10325476;
+ H5 = 0xc3d2e1f0;
+
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ //
+ // Additive constants
+ //
+ private static final int Y1 = 0x5a827999;
+ private static final int Y2 = 0x6ed9eba1;
+ private static final int Y3 = 0x8f1bbcdc;
+ private static final int Y4 = 0xca62c1d6;
+
+ private int f(
+ int u,
+ int v,
+ int w)
+ {
+ return ((u & v) | ((~u) & w));
+ }
+
+ private int h(
+ int u,
+ int v,
+ int w)
+ {
+ return (u ^ v ^ w);
+ }
+
+ private int g(
+ int u,
+ int v,
+ int w)
+ {
+ return ((u & v) | (u & w) | (v & w));
+ }
+
+ protected void processBlock()
+ {
+ //
+ // expand 16 word block into 80 word block.
+ //
+ for (int i = 16; i < 80; i++)
+ {
+ int t = X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16];
+ X[i] = t << 1 | t >>> 31;
+ }
+
+ //
+ // set up working variables.
+ //
+ int A = H1;
+ int B = H2;
+ int C = H3;
+ int D = H4;
+ int E = H5;
+
+ //
+ // round 1
+ //
+ int idx = 0;
+
+ for (int j = 0; j < 4; j++)
+ {
+ // E = rotateLeft(A, 5) + f(B, C, D) + E + X[idx++] + Y1
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | A >>> 27) + f(B, C, D) + X[idx++] + Y1;
+ B = B << 30 | B >>> 2;
+
+ D += (E << 5 | E >>> 27) + f(A, B, C) + X[idx++] + Y1;
+ A = A << 30 | A >>> 2;
+
+ C += (D << 5 | D >>> 27) + f(E, A, B) + X[idx++] + Y1;
+ E = E << 30 | E >>> 2;
+
+ B += (C << 5 | C >>> 27) + f(D, E, A) + X[idx++] + Y1;
+ D = D << 30 | D >>> 2;
+
+ A += (B << 5 | B >>> 27) + f(C, D, E) + X[idx++] + Y1;
+ C = C << 30 | C >>> 2;
+ }
+
+ //
+ // round 2
+ //
+ for (int j = 0; j < 4; j++)
+ {
+ // E = rotateLeft(A, 5) + h(B, C, D) + E + X[idx++] + Y2
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | A >>> 27) + h(B, C, D) + X[idx++] + Y2;
+ B = B << 30 | B >>> 2;
+
+ D += (E << 5 | E >>> 27) + h(A, B, C) + X[idx++] + Y2;
+ A = A << 30 | A >>> 2;
+
+ C += (D << 5 | D >>> 27) + h(E, A, B) + X[idx++] + Y2;
+ E = E << 30 | E >>> 2;
+
+ B += (C << 5 | C >>> 27) + h(D, E, A) + X[idx++] + Y2;
+ D = D << 30 | D >>> 2;
+
+ A += (B << 5 | B >>> 27) + h(C, D, E) + X[idx++] + Y2;
+ C = C << 30 | C >>> 2;
+ }
+
+ //
+ // round 3
+ //
+ for (int j = 0; j < 4; j++)
+ {
+ // E = rotateLeft(A, 5) + g(B, C, D) + E + X[idx++] + Y3
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | A >>> 27) + g(B, C, D) + X[idx++] + Y3;
+ B = B << 30 | B >>> 2;
+
+ D += (E << 5 | E >>> 27) + g(A, B, C) + X[idx++] + Y3;
+ A = A << 30 | A >>> 2;
+
+ C += (D << 5 | D >>> 27) + g(E, A, B) + X[idx++] + Y3;
+ E = E << 30 | E >>> 2;
+
+ B += (C << 5 | C >>> 27) + g(D, E, A) + X[idx++] + Y3;
+ D = D << 30 | D >>> 2;
+
+ A += (B << 5 | B >>> 27) + g(C, D, E) + X[idx++] + Y3;
+ C = C << 30 | C >>> 2;
+ }
+
+ //
+ // round 4
+ //
+ for (int j = 0; j <= 3; j++)
+ {
+ // E = rotateLeft(A, 5) + h(B, C, D) + E + X[idx++] + Y4
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | A >>> 27) + h(B, C, D) + X[idx++] + Y4;
+ B = B << 30 | B >>> 2;
+
+ D += (E << 5 | E >>> 27) + h(A, B, C) + X[idx++] + Y4;
+ A = A << 30 | A >>> 2;
+
+ C += (D << 5 | D >>> 27) + h(E, A, B) + X[idx++] + Y4;
+ E = E << 30 | E >>> 2;
+
+ B += (C << 5 | C >>> 27) + h(D, E, A) + X[idx++] + Y4;
+ D = D << 30 | D >>> 2;
+
+ A += (B << 5 | B >>> 27) + h(C, D, E) + X[idx++] + Y4;
+ C = C << 30 | C >>> 2;
+ }
+
+
+ H1 += A;
+ H2 += B;
+ H3 += C;
+ H4 += D;
+ H5 += E;
+
+ //
+ // reset start of the buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i < 16; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ public Memoable copy()
+ {
+ return new SHA1Digest(this);
+ }
+
+ public void reset(Memoable other)
+ {
+ SHA1Digest d = (SHA1Digest)other;
+
+ super.copyIn(d);
+ copyIn(d);
+ }
+
+ public byte[] getEncodedState()
+ {
+ byte[] state = new byte[40 + xOff * 4];
+
+ super.populateState(state);
+
+ Pack.intToBigEndian(H1, state, 16);
+ Pack.intToBigEndian(H2, state, 20);
+ Pack.intToBigEndian(H3, state, 24);
+ Pack.intToBigEndian(H4, state, 28);
+ Pack.intToBigEndian(H5, state, 32);
+ Pack.intToBigEndian(xOff, state, 36);
+
+ for (int i = 0; i != xOff; i++)
+ {
+ Pack.intToBigEndian(X[i], state, 40 + (i * 4));
+ }
+
+ return state;
+ }
+}
+
+
+
+
diff --git a/core/src/main/java/org/spongycastle/crypto/digests/SHA224Digest.java b/core/src/main/java/org/spongycastle/crypto/digests/SHA224Digest.java
new file mode 100644
index 00000000..e542e996
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/SHA224Digest.java
@@ -0,0 +1,356 @@
+package org.spongycastle.crypto.digests;
+
+
+import org.spongycastle.util.Memoable;
+import org.spongycastle.util.Pack;
+
+
+/**
+ * SHA-224 as described in RFC 3874
+ * <pre>
+ * block word digest
+ * SHA-1 512 32 160
+ * SHA-224 512 32 224
+ * SHA-256 512 32 256
+ * SHA-384 1024 64 384
+ * SHA-512 1024 64 512
+ * </pre>
+ */
+public class SHA224Digest
+ extends GeneralDigest
+ implements EncodableDigest
+{
+ private static final int DIGEST_LENGTH = 28;
+
+ private int H1, H2, H3, H4, H5, H6, H7, H8;
+
+ private int[] X = new int[64];
+ private int xOff;
+
+ /**
+ * Standard constructor
+ */
+ public SHA224Digest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public SHA224Digest(SHA224Digest t)
+ {
+ super(t);
+
+ doCopy(t);
+ }
+
+ private void doCopy(SHA224Digest t)
+ {
+ super.copyIn(t);
+
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+ H4 = t.H4;
+ H5 = t.H5;
+ H6 = t.H6;
+ H7 = t.H7;
+ H8 = t.H8;
+
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ }
+
+ public SHA224Digest(byte[] encodedState)
+ {
+ super(encodedState);
+
+ H1 = Pack.bigEndianToInt(encodedState, 16);
+ H2 = Pack.bigEndianToInt(encodedState, 20);
+ H3 = Pack.bigEndianToInt(encodedState, 24);
+ H4 = Pack.bigEndianToInt(encodedState, 28);
+ H5 = Pack.bigEndianToInt(encodedState, 32);
+ H6 = Pack.bigEndianToInt(encodedState, 36);
+ H7 = Pack.bigEndianToInt(encodedState, 40);
+ H8 = Pack.bigEndianToInt(encodedState, 44);
+
+ xOff = Pack.bigEndianToInt(encodedState, 48);
+ for (int i = 0; i != xOff; i++)
+ {
+ X[i] = Pack.bigEndianToInt(encodedState, 52 + (i * 4));
+ }
+ }
+
+ public String getAlgorithmName()
+ {
+ return "SHA-224";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ protected void processWord(
+ byte[] in,
+ int inOff)
+ {
+ // Note: Inlined for performance
+// X[xOff] = Pack.bigEndianToInt(in, inOff);
+ int n = in[ inOff] << 24;
+ n |= (in[++inOff] & 0xff) << 16;
+ n |= (in[++inOff] & 0xff) << 8;
+ n |= (in[++inOff] & 0xff);
+ X[xOff] = n;
+
+ if (++xOff == 16)
+ {
+ processBlock();
+ }
+ }
+
+ protected void processLength(
+ long bitLength)
+ {
+ if (xOff > 14)
+ {
+ processBlock();
+ }
+
+ X[14] = (int)(bitLength >>> 32);
+ X[15] = (int)(bitLength & 0xffffffff);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ Pack.intToBigEndian(H1, out, outOff);
+ Pack.intToBigEndian(H2, out, outOff + 4);
+ Pack.intToBigEndian(H3, out, outOff + 8);
+ Pack.intToBigEndian(H4, out, outOff + 12);
+ Pack.intToBigEndian(H5, out, outOff + 16);
+ Pack.intToBigEndian(H6, out, outOff + 20);
+ Pack.intToBigEndian(H7, out, outOff + 24);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables
+ */
+ public void reset()
+ {
+ super.reset();
+
+ /* SHA-224 initial hash value
+ */
+
+ H1 = 0xc1059ed8;
+ H2 = 0x367cd507;
+ H3 = 0x3070dd17;
+ H4 = 0xf70e5939;
+ H5 = 0xffc00b31;
+ H6 = 0x68581511;
+ H7 = 0x64f98fa7;
+ H8 = 0xbefa4fa4;
+
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ protected void processBlock()
+ {
+ //
+ // expand 16 word block into 64 word blocks.
+ //
+ for (int t = 16; t <= 63; t++)
+ {
+ X[t] = Theta1(X[t - 2]) + X[t - 7] + Theta0(X[t - 15]) + X[t - 16];
+ }
+
+ //
+ // set up working variables.
+ //
+ int a = H1;
+ int b = H2;
+ int c = H3;
+ int d = H4;
+ int e = H5;
+ int f = H6;
+ int g = H7;
+ int h = H8;
+
+
+ int t = 0;
+ for(int i = 0; i < 8; i ++)
+ {
+ // t = 8 * i
+ h += Sum1(e) + Ch(e, f, g) + K[t] + X[t];
+ d += h;
+ h += Sum0(a) + Maj(a, b, c);
+ ++t;
+
+ // t = 8 * i + 1
+ g += Sum1(d) + Ch(d, e, f) + K[t] + X[t];
+ c += g;
+ g += Sum0(h) + Maj(h, a, b);
+ ++t;
+
+ // t = 8 * i + 2
+ f += Sum1(c) + Ch(c, d, e) + K[t] + X[t];
+ b += f;
+ f += Sum0(g) + Maj(g, h, a);
+ ++t;
+
+ // t = 8 * i + 3
+ e += Sum1(b) + Ch(b, c, d) + K[t] + X[t];
+ a += e;
+ e += Sum0(f) + Maj(f, g, h);
+ ++t;
+
+ // t = 8 * i + 4
+ d += Sum1(a) + Ch(a, b, c) + K[t] + X[t];
+ h += d;
+ d += Sum0(e) + Maj(e, f, g);
+ ++t;
+
+ // t = 8 * i + 5
+ c += Sum1(h) + Ch(h, a, b) + K[t] + X[t];
+ g += c;
+ c += Sum0(d) + Maj(d, e, f);
+ ++t;
+
+ // t = 8 * i + 6
+ b += Sum1(g) + Ch(g, h, a) + K[t] + X[t];
+ f += b;
+ b += Sum0(c) + Maj(c, d, e);
+ ++t;
+
+ // t = 8 * i + 7
+ a += Sum1(f) + Ch(f, g, h) + K[t] + X[t];
+ e += a;
+ a += Sum0(b) + Maj(b, c, d);
+ ++t;
+ }
+
+ H1 += a;
+ H2 += b;
+ H3 += c;
+ H4 += d;
+ H5 += e;
+ H6 += f;
+ H7 += g;
+ H8 += h;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i < 16; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ /* SHA-224 functions */
+ private int Ch(
+ int x,
+ int y,
+ int z)
+ {
+ return ((x & y) ^ ((~x) & z));
+ }
+
+ private int Maj(
+ int x,
+ int y,
+ int z)
+ {
+ return ((x & y) ^ (x & z) ^ (y & z));
+ }
+
+ private int Sum0(
+ int x)
+ {
+ return ((x >>> 2) | (x << 30)) ^ ((x >>> 13) | (x << 19)) ^ ((x >>> 22) | (x << 10));
+ }
+
+ private int Sum1(
+ int x)
+ {
+ return ((x >>> 6) | (x << 26)) ^ ((x >>> 11) | (x << 21)) ^ ((x >>> 25) | (x << 7));
+ }
+
+ private int Theta0(
+ int x)
+ {
+ return ((x >>> 7) | (x << 25)) ^ ((x >>> 18) | (x << 14)) ^ (x >>> 3);
+ }
+
+ private int Theta1(
+ int x)
+ {
+ return ((x >>> 17) | (x << 15)) ^ ((x >>> 19) | (x << 13)) ^ (x >>> 10);
+ }
+
+ /* SHA-224 Constants
+ * (represent the first 32 bits of the fractional parts of the
+ * cube roots of the first sixty-four prime numbers)
+ */
+ static final int K[] = {
+ 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
+ };
+
+ public Memoable copy()
+ {
+ return new SHA224Digest(this);
+ }
+
+ public void reset(Memoable other)
+ {
+ SHA224Digest d = (SHA224Digest)other;
+
+ doCopy(d);
+ }
+
+ public byte[] getEncodedState()
+ {
+ byte[] state = new byte[52 + xOff * 4];
+
+ super.populateState(state);
+
+ Pack.intToBigEndian(H1, state, 16);
+ Pack.intToBigEndian(H2, state, 20);
+ Pack.intToBigEndian(H3, state, 24);
+ Pack.intToBigEndian(H4, state, 28);
+ Pack.intToBigEndian(H5, state, 32);
+ Pack.intToBigEndian(H6, state, 36);
+ Pack.intToBigEndian(H7, state, 40);
+ Pack.intToBigEndian(H8, state, 44);
+ Pack.intToBigEndian(xOff, state, 48);
+
+ for (int i = 0; i != xOff; i++)
+ {
+ Pack.intToBigEndian(X[i], state, 52 + (i * 4));
+ }
+
+ return state;
+ }
+}
+
diff --git a/core/src/main/java/org/spongycastle/crypto/digests/SHA256Digest.java b/core/src/main/java/org/spongycastle/crypto/digests/SHA256Digest.java
new file mode 100644
index 00000000..9fe18347
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/SHA256Digest.java
@@ -0,0 +1,360 @@
+package org.spongycastle.crypto.digests;
+
+
+import org.spongycastle.util.Memoable;
+import org.spongycastle.util.Pack;
+
+
+/**
+ * FIPS 180-2 implementation of SHA-256.
+ *
+ * <pre>
+ * block word digest
+ * SHA-1 512 32 160
+ * SHA-256 512 32 256
+ * SHA-384 1024 64 384
+ * SHA-512 1024 64 512
+ * </pre>
+ */
+public class SHA256Digest
+ extends GeneralDigest
+ implements EncodableDigest
+{
+ private static final int DIGEST_LENGTH = 32;
+
+ private int H1, H2, H3, H4, H5, H6, H7, H8;
+
+ private int[] X = new int[64];
+ private int xOff;
+
+ /**
+ * Standard constructor
+ */
+ public SHA256Digest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public SHA256Digest(SHA256Digest t)
+ {
+ super(t);
+
+ copyIn(t);
+ }
+
+ private void copyIn(SHA256Digest t)
+ {
+ super.copyIn(t);
+
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+ H4 = t.H4;
+ H5 = t.H5;
+ H6 = t.H6;
+ H7 = t.H7;
+ H8 = t.H8;
+
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ }
+
+ public SHA256Digest(byte[] encodedState)
+ {
+ super(encodedState);
+
+ H1 = Pack.bigEndianToInt(encodedState, 16);
+ H2 = Pack.bigEndianToInt(encodedState, 20);
+ H3 = Pack.bigEndianToInt(encodedState, 24);
+ H4 = Pack.bigEndianToInt(encodedState, 28);
+ H5 = Pack.bigEndianToInt(encodedState, 32);
+ H6 = Pack.bigEndianToInt(encodedState, 36);
+ H7 = Pack.bigEndianToInt(encodedState, 40);
+ H8 = Pack.bigEndianToInt(encodedState, 44);
+
+ xOff = Pack.bigEndianToInt(encodedState, 48);
+ for (int i = 0; i != xOff; i++)
+ {
+ X[i] = Pack.bigEndianToInt(encodedState, 52 + (i * 4));
+ }
+ }
+
+
+ public String getAlgorithmName()
+ {
+ return "SHA-256";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ protected void processWord(
+ byte[] in,
+ int inOff)
+ {
+ // Note: Inlined for performance
+// X[xOff] = Pack.bigEndianToInt(in, inOff);
+ int n = in[inOff] << 24;
+ n |= (in[++inOff] & 0xff) << 16;
+ n |= (in[++inOff] & 0xff) << 8;
+ n |= (in[++inOff] & 0xff);
+ X[xOff] = n;
+
+ if (++xOff == 16)
+ {
+ processBlock();
+ }
+ }
+
+ protected void processLength(
+ long bitLength)
+ {
+ if (xOff > 14)
+ {
+ processBlock();
+ }
+
+ X[14] = (int)(bitLength >>> 32);
+ X[15] = (int)(bitLength & 0xffffffff);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ Pack.intToBigEndian(H1, out, outOff);
+ Pack.intToBigEndian(H2, out, outOff + 4);
+ Pack.intToBigEndian(H3, out, outOff + 8);
+ Pack.intToBigEndian(H4, out, outOff + 12);
+ Pack.intToBigEndian(H5, out, outOff + 16);
+ Pack.intToBigEndian(H6, out, outOff + 20);
+ Pack.intToBigEndian(H7, out, outOff + 24);
+ Pack.intToBigEndian(H8, out, outOff + 28);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables
+ */
+ public void reset()
+ {
+ super.reset();
+
+ /* SHA-256 initial hash value
+ * The first 32 bits of the fractional parts of the square roots
+ * of the first eight prime numbers
+ */
+
+ H1 = 0x6a09e667;
+ H2 = 0xbb67ae85;
+ H3 = 0x3c6ef372;
+ H4 = 0xa54ff53a;
+ H5 = 0x510e527f;
+ H6 = 0x9b05688c;
+ H7 = 0x1f83d9ab;
+ H8 = 0x5be0cd19;
+
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ protected void processBlock()
+ {
+ //
+ // expand 16 word block into 64 word blocks.
+ //
+ for (int t = 16; t <= 63; t++)
+ {
+ X[t] = Theta1(X[t - 2]) + X[t - 7] + Theta0(X[t - 15]) + X[t - 16];
+ }
+
+ //
+ // set up working variables.
+ //
+ int a = H1;
+ int b = H2;
+ int c = H3;
+ int d = H4;
+ int e = H5;
+ int f = H6;
+ int g = H7;
+ int h = H8;
+
+ int t = 0;
+ for(int i = 0; i < 8; i ++)
+ {
+ // t = 8 * i
+ h += Sum1(e) + Ch(e, f, g) + K[t] + X[t];
+ d += h;
+ h += Sum0(a) + Maj(a, b, c);
+ ++t;
+
+ // t = 8 * i + 1
+ g += Sum1(d) + Ch(d, e, f) + K[t] + X[t];
+ c += g;
+ g += Sum0(h) + Maj(h, a, b);
+ ++t;
+
+ // t = 8 * i + 2
+ f += Sum1(c) + Ch(c, d, e) + K[t] + X[t];
+ b += f;
+ f += Sum0(g) + Maj(g, h, a);
+ ++t;
+
+ // t = 8 * i + 3
+ e += Sum1(b) + Ch(b, c, d) + K[t] + X[t];
+ a += e;
+ e += Sum0(f) + Maj(f, g, h);
+ ++t;
+
+ // t = 8 * i + 4
+ d += Sum1(a) + Ch(a, b, c) + K[t] + X[t];
+ h += d;
+ d += Sum0(e) + Maj(e, f, g);
+ ++t;
+
+ // t = 8 * i + 5
+ c += Sum1(h) + Ch(h, a, b) + K[t] + X[t];
+ g += c;
+ c += Sum0(d) + Maj(d, e, f);
+ ++t;
+
+ // t = 8 * i + 6
+ b += Sum1(g) + Ch(g, h, a) + K[t] + X[t];
+ f += b;
+ b += Sum0(c) + Maj(c, d, e);
+ ++t;
+
+ // t = 8 * i + 7
+ a += Sum1(f) + Ch(f, g, h) + K[t] + X[t];
+ e += a;
+ a += Sum0(b) + Maj(b, c, d);
+ ++t;
+ }
+
+ H1 += a;
+ H2 += b;
+ H3 += c;
+ H4 += d;
+ H5 += e;
+ H6 += f;
+ H7 += g;
+ H8 += h;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i < 16; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ /* SHA-256 functions */
+ private int Ch(
+ int x,
+ int y,
+ int z)
+ {
+ return (x & y) ^ ((~x) & z);
+ }
+
+ private int Maj(
+ int x,
+ int y,
+ int z)
+ {
+ return (x & y) ^ (x & z) ^ (y & z);
+ }
+
+ private int Sum0(
+ int x)
+ {
+ return ((x >>> 2) | (x << 30)) ^ ((x >>> 13) | (x << 19)) ^ ((x >>> 22) | (x << 10));
+ }
+
+ private int Sum1(
+ int x)
+ {
+ return ((x >>> 6) | (x << 26)) ^ ((x >>> 11) | (x << 21)) ^ ((x >>> 25) | (x << 7));
+ }
+
+ private int Theta0(
+ int x)
+ {
+ return ((x >>> 7) | (x << 25)) ^ ((x >>> 18) | (x << 14)) ^ (x >>> 3);
+ }
+
+ private int Theta1(
+ int x)
+ {
+ return ((x >>> 17) | (x << 15)) ^ ((x >>> 19) | (x << 13)) ^ (x >>> 10);
+ }
+
+ /* SHA-256 Constants
+ * (represent the first 32 bits of the fractional parts of the
+ * cube roots of the first sixty-four prime numbers)
+ */
+ static final int K[] = {
+ 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
+ };
+
+ public Memoable copy()
+ {
+ return new SHA256Digest(this);
+ }
+
+ public void reset(Memoable other)
+ {
+ SHA256Digest d = (SHA256Digest)other;
+
+ copyIn(d);
+ }
+
+ public byte[] getEncodedState()
+ {
+ byte[] state = new byte[52 + xOff * 4];
+
+ super.populateState(state);
+
+ Pack.intToBigEndian(H1, state, 16);
+ Pack.intToBigEndian(H2, state, 20);
+ Pack.intToBigEndian(H3, state, 24);
+ Pack.intToBigEndian(H4, state, 28);
+ Pack.intToBigEndian(H5, state, 32);
+ Pack.intToBigEndian(H6, state, 36);
+ Pack.intToBigEndian(H7, state, 40);
+ Pack.intToBigEndian(H8, state, 44);
+ Pack.intToBigEndian(xOff, state, 48);
+
+ for (int i = 0; i != xOff; i++)
+ {
+ Pack.intToBigEndian(X[i], state, 52 + (i * 4));
+ }
+
+ return state;
+ }
+}
+
diff --git a/core/src/main/java/org/spongycastle/crypto/digests/SHA384Digest.java b/core/src/main/java/org/spongycastle/crypto/digests/SHA384Digest.java
new file mode 100644
index 00000000..1bf7c6ad
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/SHA384Digest.java
@@ -0,0 +1,111 @@
+package org.spongycastle.crypto.digests;
+
+import org.spongycastle.util.Memoable;
+import org.spongycastle.util.Pack;
+
+
+/**
+ * FIPS 180-2 implementation of SHA-384.
+ *
+ * <pre>
+ * block word digest
+ * SHA-1 512 32 160
+ * SHA-256 512 32 256
+ * SHA-384 1024 64 384
+ * SHA-512 1024 64 512
+ * </pre>
+ */
+public class SHA384Digest
+ extends LongDigest
+{
+ private static final int DIGEST_LENGTH = 48;
+
+ /**
+ * Standard constructor
+ */
+ public SHA384Digest()
+ {
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public SHA384Digest(SHA384Digest t)
+ {
+ super(t);
+ }
+
+ public SHA384Digest(byte[] encodedState)
+ {
+ restoreState(encodedState);
+ }
+
+ public String getAlgorithmName()
+ {
+ return "SHA-384";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ Pack.longToBigEndian(H1, out, outOff);
+ Pack.longToBigEndian(H2, out, outOff + 8);
+ Pack.longToBigEndian(H3, out, outOff + 16);
+ Pack.longToBigEndian(H4, out, outOff + 24);
+ Pack.longToBigEndian(H5, out, outOff + 32);
+ Pack.longToBigEndian(H6, out, outOff + 40);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables
+ */
+ public void reset()
+ {
+ super.reset();
+
+ /* SHA-384 initial hash value
+ * The first 64 bits of the fractional parts of the square roots
+ * of the 9th through 16th prime numbers
+ */
+ H1 = 0xcbbb9d5dc1059ed8l;
+ H2 = 0x629a292a367cd507l;
+ H3 = 0x9159015a3070dd17l;
+ H4 = 0x152fecd8f70e5939l;
+ H5 = 0x67332667ffc00b31l;
+ H6 = 0x8eb44a8768581511l;
+ H7 = 0xdb0c2e0d64f98fa7l;
+ H8 = 0x47b5481dbefa4fa4l;
+ }
+
+ public Memoable copy()
+ {
+ return new SHA384Digest(this);
+ }
+
+ public void reset(Memoable other)
+ {
+ SHA384Digest d = (SHA384Digest)other;
+
+ super.copyIn(d);
+ }
+
+ public byte[] getEncodedState()
+ {
+ byte[] encoded = new byte[getEncodedStateSize()];
+ super.populateState(encoded);
+ return encoded;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/digests/SHA3Digest.java b/core/src/main/java/org/spongycastle/crypto/digests/SHA3Digest.java
new file mode 100644
index 00000000..936e29b9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/SHA3Digest.java
@@ -0,0 +1,547 @@
+package org.spongycastle.crypto.digests;
+
+import org.spongycastle.crypto.ExtendedDigest;
+import org.spongycastle.util.Arrays;
+
+/**
+ * implementation of SHA-3 based on following KeccakNISTInterface.c from http://keccak.noekeon.org/
+ * <p>
+ * Following the naming conventions used in the C source code to enable easy review of the implementation.
+ */
+public class SHA3Digest
+ implements ExtendedDigest
+{
+ private static long[] KeccakRoundConstants = keccakInitializeRoundConstants();
+
+ private static int[] KeccakRhoOffsets = keccakInitializeRhoOffsets();
+
+ private static long[] keccakInitializeRoundConstants()
+ {
+ long[] keccakRoundConstants = new long[24];
+ byte[] LFSRstate = new byte[1];
+
+ LFSRstate[0] = 0x01;
+ int i, j, bitPosition;
+
+ for (i = 0; i < 24; i++)
+ {
+ keccakRoundConstants[i] = 0;
+ for (j = 0; j < 7; j++)
+ {
+ bitPosition = (1 << j) - 1;
+ if (LFSR86540(LFSRstate))
+ {
+ keccakRoundConstants[i] ^= 1L << bitPosition;
+ }
+ }
+ }
+
+ return keccakRoundConstants;
+ }
+
+ private static boolean LFSR86540(byte[] LFSR)
+ {
+ boolean result = (((LFSR[0]) & 0x01) != 0);
+ if (((LFSR[0]) & 0x80) != 0)
+ {
+ LFSR[0] = (byte)(((LFSR[0]) << 1) ^ 0x71);
+ }
+ else
+ {
+ LFSR[0] <<= 1;
+ }
+
+ return result;
+ }
+
+ private static int[] keccakInitializeRhoOffsets()
+ {
+ int[] keccakRhoOffsets = new int[25];
+ int x, y, t, newX, newY;
+
+ keccakRhoOffsets[(((0) % 5) + 5 * ((0) % 5))] = 0;
+ x = 1;
+ y = 0;
+ for (t = 0; t < 24; t++)
+ {
+ keccakRhoOffsets[(((x) % 5) + 5 * ((y) % 5))] = ((t + 1) * (t + 2) / 2) % 64;
+ newX = (0 * x + 1 * y) % 5;
+ newY = (2 * x + 3 * y) % 5;
+ x = newX;
+ y = newY;
+ }
+
+ return keccakRhoOffsets;
+ }
+
+ private byte[] state = new byte[(1600 / 8)];
+ private byte[] dataQueue = new byte[(1536 / 8)];
+ private int rate;
+ private int bitsInQueue;
+ private int fixedOutputLength;
+ private boolean squeezing;
+ private int bitsAvailableForSqueezing;
+ private byte[] chunk;
+ private byte[] oneByte;
+
+ private void clearDataQueueSection(int off, int len)
+ {
+ for (int i = off; i != off + len; i++)
+ {
+ dataQueue[i] = 0;
+ }
+ }
+
+ public SHA3Digest()
+ {
+ init(0);
+ }
+
+ public SHA3Digest(int bitLength)
+ {
+ init(bitLength);
+ }
+
+ public SHA3Digest(SHA3Digest source) {
+ System.arraycopy(source.state, 0, this.state, 0, source.state.length);
+ System.arraycopy(source.dataQueue, 0, this.dataQueue, 0, source.dataQueue.length);
+ this.rate = source.rate;
+ this.bitsInQueue = source.bitsInQueue;
+ this.fixedOutputLength = source.fixedOutputLength;
+ this.squeezing = source.squeezing;
+ this.bitsAvailableForSqueezing = source.bitsAvailableForSqueezing;
+ this.chunk = Arrays.clone(source.chunk);
+ this.oneByte = Arrays.clone(source.oneByte);
+ }
+
+ public String getAlgorithmName()
+ {
+ return "SHA3-" + fixedOutputLength;
+ }
+
+ public int getDigestSize()
+ {
+ return fixedOutputLength / 8;
+ }
+
+ public void update(byte in)
+ {
+ oneByte[0] = in;
+
+ doUpdate(oneByte, 0, 8L);
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ {
+ doUpdate(in, inOff, len * 8L);
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ {
+ squeeze(out, outOff, fixedOutputLength);
+
+ reset();
+
+ return getDigestSize();
+ }
+
+ public void reset()
+ {
+ init(fixedOutputLength);
+ }
+
+ /**
+ * Return the size of block that the compression function is applied to in bytes.
+ *
+ * @return internal byte length of a block.
+ */
+ public int getByteLength()
+ {
+ return rate / 8;
+ }
+
+ private void init(int bitLength)
+ {
+ switch (bitLength)
+ {
+ case 0:
+ case 288:
+ initSponge(1024, 576);
+ break;
+ case 224:
+ initSponge(1152, 448);
+ break;
+ case 256:
+ initSponge(1088, 512);
+ break;
+ case 384:
+ initSponge(832, 768);
+ break;
+ case 512:
+ initSponge(576, 1024);
+ break;
+ default:
+ throw new IllegalArgumentException("bitLength must be one of 224, 256, 384, or 512.");
+ }
+ }
+
+ private void doUpdate(byte[] data, int off, long databitlen)
+ {
+ if ((databitlen % 8) == 0)
+ {
+ absorb(data, off, databitlen);
+ }
+ else
+ {
+ absorb(data, off, databitlen - (databitlen % 8));
+
+ byte[] lastByte = new byte[1];
+
+ lastByte[0] = (byte)(data[off + (int)(databitlen / 8)] >> (8 - (databitlen % 8)));
+ absorb(lastByte, off, databitlen % 8);
+ }
+ }
+
+ private void initSponge(int rate, int capacity)
+ {
+ if (rate + capacity != 1600)
+ {
+ throw new IllegalStateException("rate + capacity != 1600");
+ }
+ if ((rate <= 0) || (rate >= 1600) || ((rate % 64) != 0))
+ {
+ throw new IllegalStateException("invalid rate value");
+ }
+
+ this.rate = rate;
+ // this is never read, need to check to see why we want to save it
+ // this.capacity = capacity;
+ this.fixedOutputLength = 0;
+ Arrays.fill(this.state, (byte)0);
+ Arrays.fill(this.dataQueue, (byte)0);
+ this.bitsInQueue = 0;
+ this.squeezing = false;
+ this.bitsAvailableForSqueezing = 0;
+ this.fixedOutputLength = capacity / 2;
+ this.chunk = new byte[rate / 8];
+ this.oneByte = new byte[1];
+ }
+
+ private void absorbQueue()
+ {
+ KeccakAbsorb(state, dataQueue, rate / 8);
+
+ bitsInQueue = 0;
+ }
+
+ private void absorb(byte[] data, int off, long databitlen)
+ {
+ long i, j, wholeBlocks;
+
+ if ((bitsInQueue % 8) != 0)
+ {
+ throw new IllegalStateException("attempt to absorb with odd length queue.");
+ }
+ if (squeezing)
+ {
+ throw new IllegalStateException("attempt to absorb while squeezing.");
+ }
+
+ i = 0;
+ while (i < databitlen)
+ {
+ if ((bitsInQueue == 0) && (databitlen >= rate) && (i <= (databitlen - rate)))
+ {
+ wholeBlocks = (databitlen - i) / rate;
+
+ for (j = 0; j < wholeBlocks; j++)
+ {
+ System.arraycopy(data, (int)(off + (i / 8) + (j * chunk.length)), chunk, 0, chunk.length);
+
+// displayIntermediateValues.displayBytes(1, "Block to be absorbed", curData, rate / 8);
+
+ KeccakAbsorb(state, chunk, chunk.length);
+ }
+
+ i += wholeBlocks * rate;
+ }
+ else
+ {
+ int partialBlock = (int)(databitlen - i);
+ if (partialBlock + bitsInQueue > rate)
+ {
+ partialBlock = rate - bitsInQueue;
+ }
+ int partialByte = partialBlock % 8;
+ partialBlock -= partialByte;
+ System.arraycopy(data, off + (int)(i / 8), dataQueue, bitsInQueue / 8, partialBlock / 8);
+
+ bitsInQueue += partialBlock;
+ i += partialBlock;
+ if (bitsInQueue == rate)
+ {
+ absorbQueue();
+ }
+ if (partialByte > 0)
+ {
+ int mask = (1 << partialByte) - 1;
+ dataQueue[bitsInQueue / 8] = (byte)(data[off + ((int)(i / 8))] & mask);
+ bitsInQueue += partialByte;
+ i += partialByte;
+ }
+ }
+ }
+ }
+
+ private void padAndSwitchToSqueezingPhase()
+ {
+ if (bitsInQueue + 1 == rate)
+ {
+ dataQueue[bitsInQueue / 8] |= 1 << (bitsInQueue % 8);
+ absorbQueue();
+ clearDataQueueSection(0, rate / 8);
+ }
+ else
+ {
+ clearDataQueueSection((bitsInQueue + 7) / 8, rate / 8 - (bitsInQueue + 7) / 8);
+ dataQueue[bitsInQueue / 8] |= 1 << (bitsInQueue % 8);
+ }
+ dataQueue[(rate - 1) / 8] |= 1 << ((rate - 1) % 8);
+ absorbQueue();
+
+
+// displayIntermediateValues.displayText(1, "--- Switching to squeezing phase ---");
+
+
+ if (rate == 1024)
+ {
+ KeccakExtract1024bits(state, dataQueue);
+ bitsAvailableForSqueezing = 1024;
+ }
+ else
+
+ {
+ KeccakExtract(state, dataQueue, rate / 64);
+ bitsAvailableForSqueezing = rate;
+ }
+
+// displayIntermediateValues.displayBytes(1, "Block available for squeezing", dataQueue, bitsAvailableForSqueezing / 8);
+
+ squeezing = true;
+ }
+
+ private void squeeze(byte[] output, int offset, long outputLength)
+ {
+ long i;
+ int partialBlock;
+
+ if (!squeezing)
+ {
+ padAndSwitchToSqueezingPhase();
+ }
+ if ((outputLength % 8) != 0)
+ {
+ throw new IllegalStateException("outputLength not a multiple of 8");
+ }
+
+ i = 0;
+ while (i < outputLength)
+ {
+ if (bitsAvailableForSqueezing == 0)
+ {
+ keccakPermutation(state);
+
+ if (rate == 1024)
+ {
+ KeccakExtract1024bits(state, dataQueue);
+ bitsAvailableForSqueezing = 1024;
+ }
+ else
+
+ {
+ KeccakExtract(state, dataQueue, rate / 64);
+ bitsAvailableForSqueezing = rate;
+ }
+
+// displayIntermediateValues.displayBytes(1, "Block available for squeezing", dataQueue, bitsAvailableForSqueezing / 8);
+
+ }
+ partialBlock = bitsAvailableForSqueezing;
+ if ((long)partialBlock > outputLength - i)
+ {
+ partialBlock = (int)(outputLength - i);
+ }
+
+ System.arraycopy(dataQueue, (rate - bitsAvailableForSqueezing) / 8, output, offset + (int)(i / 8), partialBlock / 8);
+ bitsAvailableForSqueezing -= partialBlock;
+ i += partialBlock;
+ }
+ }
+
+ private void fromBytesToWords(long[] stateAsWords, byte[] state)
+ {
+ for (int i = 0; i < (1600 / 64); i++)
+ {
+ stateAsWords[i] = 0;
+ int index = i * (64 / 8);
+ for (int j = 0; j < (64 / 8); j++)
+ {
+ stateAsWords[i] |= ((long)state[index + j] & 0xff) << ((8 * j));
+ }
+ }
+ }
+
+ private void fromWordsToBytes(byte[] state, long[] stateAsWords)
+ {
+ for (int i = 0; i < (1600 / 64); i++)
+ {
+ int index = i * (64 / 8);
+ for (int j = 0; j < (64 / 8); j++)
+ {
+ state[index + j] = (byte)((stateAsWords[i] >>> ((8 * j))) & 0xFF);
+ }
+ }
+ }
+
+ private void keccakPermutation(byte[] state)
+ {
+ long[] longState = new long[state.length / 8];
+
+ fromBytesToWords(longState, state);
+
+// displayIntermediateValues.displayStateAsBytes(1, "Input of permutation", longState);
+
+ keccakPermutationOnWords(longState);
+
+// displayIntermediateValues.displayStateAsBytes(1, "State after permutation", longState);
+
+ fromWordsToBytes(state, longState);
+ }
+
+ private void keccakPermutationAfterXor(byte[] state, byte[] data, int dataLengthInBytes)
+ {
+ int i;
+
+ for (i = 0; i < dataLengthInBytes; i++)
+ {
+ state[i] ^= data[i];
+ }
+
+ keccakPermutation(state);
+ }
+
+ private void keccakPermutationOnWords(long[] state)
+ {
+ int i;
+
+// displayIntermediateValues.displayStateAs64bitWords(3, "Same, with lanes as 64-bit words", state);
+
+ for (i = 0; i < 24; i++)
+ {
+// displayIntermediateValues.displayRoundNumber(3, i);
+
+ theta(state);
+// displayIntermediateValues.displayStateAs64bitWords(3, "After theta", state);
+
+ rho(state);
+// displayIntermediateValues.displayStateAs64bitWords(3, "After rho", state);
+
+ pi(state);
+// displayIntermediateValues.displayStateAs64bitWords(3, "After pi", state);
+
+ chi(state);
+// displayIntermediateValues.displayStateAs64bitWords(3, "After chi", state);
+
+ iota(state, i);
+// displayIntermediateValues.displayStateAs64bitWords(3, "After iota", state);
+ }
+ }
+
+ long[] C = new long[5];
+
+ private void theta(long[] A)
+ {
+ for (int x = 0; x < 5; x++)
+ {
+ C[x] = 0;
+ for (int y = 0; y < 5; y++)
+ {
+ C[x] ^= A[x + 5 * y];
+ }
+ }
+ for (int x = 0; x < 5; x++)
+ {
+ long dX = ((((C[(x + 1) % 5]) << 1) ^ ((C[(x + 1) % 5]) >>> (64 - 1)))) ^ C[(x + 4) % 5];
+ for (int y = 0; y < 5; y++)
+ {
+ A[x + 5 * y] ^= dX;
+ }
+ }
+ }
+
+ private void rho(long[] A)
+ {
+ for (int x = 0; x < 5; x++)
+ {
+ for (int y = 0; y < 5; y++)
+ {
+ int index = x + 5 * y;
+ A[index] = ((KeccakRhoOffsets[index] != 0) ? (((A[index]) << KeccakRhoOffsets[index]) ^ ((A[index]) >>> (64 - KeccakRhoOffsets[index]))) : A[index]);
+ }
+ }
+ }
+
+ long[] tempA = new long[25];
+
+ private void pi(long[] A)
+ {
+ System.arraycopy(A, 0, tempA, 0, tempA.length);
+
+ for (int x = 0; x < 5; x++)
+ {
+ for (int y = 0; y < 5; y++)
+ {
+ A[y + 5 * ((2 * x + 3 * y) % 5)] = tempA[x + 5 * y];
+ }
+ }
+ }
+
+ long[] chiC = new long[5];
+
+ private void chi(long[] A)
+ {
+ for (int y = 0; y < 5; y++)
+ {
+ for (int x = 0; x < 5; x++)
+ {
+ chiC[x] = A[x + 5 * y] ^ ((~A[(((x + 1) % 5) + 5 * y)]) & A[(((x + 2) % 5) + 5 * y)]);
+ }
+ for (int x = 0; x < 5; x++)
+ {
+ A[x + 5 * y] = chiC[x];
+ }
+ }
+ }
+
+ private void iota(long[] A, int indexRound)
+ {
+ A[(((0) % 5) + 5 * ((0) % 5))] ^= KeccakRoundConstants[indexRound];
+ }
+
+ private void KeccakAbsorb(byte[] byteState, byte[] data, int dataInBytes)
+ {
+ keccakPermutationAfterXor(byteState, data, dataInBytes);
+ }
+
+
+ private void KeccakExtract1024bits(byte[] byteState, byte[] data)
+ {
+ System.arraycopy(byteState, 0, data, 0, 128);
+ }
+
+
+ private void KeccakExtract(byte[] byteState, byte[] data, int laneCount)
+ {
+ System.arraycopy(byteState, 0, data, 0, laneCount * 8);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/digests/SHA512Digest.java b/core/src/main/java/org/spongycastle/crypto/digests/SHA512Digest.java
new file mode 100644
index 00000000..f97b1230
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/SHA512Digest.java
@@ -0,0 +1,114 @@
+package org.spongycastle.crypto.digests;
+
+import org.spongycastle.util.Memoable;
+import org.spongycastle.util.Pack;
+
+
+/**
+ * FIPS 180-2 implementation of SHA-512.
+ *
+ * <pre>
+ * block word digest
+ * SHA-1 512 32 160
+ * SHA-256 512 32 256
+ * SHA-384 1024 64 384
+ * SHA-512 1024 64 512
+ * </pre>
+ */
+public class SHA512Digest
+ extends LongDigest
+{
+ private static final int DIGEST_LENGTH = 64;
+
+ /**
+ * Standard constructor
+ */
+ public SHA512Digest()
+ {
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public SHA512Digest(SHA512Digest t)
+ {
+ super(t);
+ }
+
+ public SHA512Digest(byte[] encodedState)
+ {
+ restoreState(encodedState);
+ }
+
+ public String getAlgorithmName()
+ {
+ return "SHA-512";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ Pack.longToBigEndian(H1, out, outOff);
+ Pack.longToBigEndian(H2, out, outOff + 8);
+ Pack.longToBigEndian(H3, out, outOff + 16);
+ Pack.longToBigEndian(H4, out, outOff + 24);
+ Pack.longToBigEndian(H5, out, outOff + 32);
+ Pack.longToBigEndian(H6, out, outOff + 40);
+ Pack.longToBigEndian(H7, out, outOff + 48);
+ Pack.longToBigEndian(H8, out, outOff + 56);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables
+ */
+ public void reset()
+ {
+ super.reset();
+
+ /* SHA-512 initial hash value
+ * The first 64 bits of the fractional parts of the square roots
+ * of the first eight prime numbers
+ */
+ H1 = 0x6a09e667f3bcc908L;
+ H2 = 0xbb67ae8584caa73bL;
+ H3 = 0x3c6ef372fe94f82bL;
+ H4 = 0xa54ff53a5f1d36f1L;
+ H5 = 0x510e527fade682d1L;
+ H6 = 0x9b05688c2b3e6c1fL;
+ H7 = 0x1f83d9abfb41bd6bL;
+ H8 = 0x5be0cd19137e2179L;
+ }
+
+ public Memoable copy()
+ {
+ return new SHA512Digest(this);
+ }
+
+ public void reset(Memoable other)
+ {
+ SHA512Digest d = (SHA512Digest)other;
+
+ copyIn(d);
+ }
+
+ public byte[] getEncodedState()
+ {
+ byte[] encoded = new byte[getEncodedStateSize()];
+ super.populateState(encoded);
+ return encoded;
+ }
+}
+
diff --git a/core/src/main/java/org/spongycastle/crypto/digests/SHA512tDigest.java b/core/src/main/java/org/spongycastle/crypto/digests/SHA512tDigest.java
new file mode 100644
index 00000000..fc05781f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/SHA512tDigest.java
@@ -0,0 +1,227 @@
+package org.spongycastle.crypto.digests;
+
+import org.spongycastle.util.Memoable;
+import org.spongycastle.util.MemoableResetException;
+import org.spongycastle.util.Pack;
+
+/**
+ * FIPS 180-4 implementation of SHA-512/t
+ */
+public class SHA512tDigest
+ extends LongDigest
+{
+ private int digestLength; // non-final due to old flow analyser.
+
+ private long H1t, H2t, H3t, H4t, H5t, H6t, H7t, H8t;
+
+ /**
+ * Standard constructor
+ */
+ public SHA512tDigest(int bitLength)
+ {
+ if (bitLength >= 512)
+ {
+ throw new IllegalArgumentException("bitLength cannot be >= 512");
+ }
+
+ if (bitLength % 8 != 0)
+ {
+ throw new IllegalArgumentException("bitLength needs to be a multiple of 8");
+ }
+
+ if (bitLength == 384)
+ {
+ throw new IllegalArgumentException("bitLength cannot be 384 use SHA384 instead");
+ }
+
+ this.digestLength = bitLength / 8;
+
+ tIvGenerate(digestLength * 8);
+
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public SHA512tDigest(SHA512tDigest t)
+ {
+ super(t);
+
+ this.digestLength = t.digestLength;
+
+ reset(t);
+ }
+
+ public SHA512tDigest(byte[] encodedState)
+ {
+ this(readDigestLength(encodedState));
+ restoreState(encodedState);
+ }
+
+ private static int readDigestLength(byte[] encodedState)
+ {
+ return Pack.bigEndianToInt(encodedState, encodedState.length - 4);
+ }
+
+ public String getAlgorithmName()
+ {
+ return "SHA-512/" + Integer.toString(digestLength * 8);
+ }
+
+ public int getDigestSize()
+ {
+ return digestLength;
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ longToBigEndian(H1, out, outOff, digestLength);
+ longToBigEndian(H2, out, outOff + 8, digestLength - 8);
+ longToBigEndian(H3, out, outOff + 16, digestLength - 16);
+ longToBigEndian(H4, out, outOff + 24, digestLength - 24);
+ longToBigEndian(H5, out, outOff + 32, digestLength - 32);
+ longToBigEndian(H6, out, outOff + 40, digestLength - 40);
+ longToBigEndian(H7, out, outOff + 48, digestLength - 48);
+ longToBigEndian(H8, out, outOff + 56, digestLength - 56);
+
+ reset();
+
+ return digestLength;
+ }
+
+ /**
+ * reset the chaining variables
+ */
+ public void reset()
+ {
+ super.reset();
+
+ /*
+ * initial hash values use the iv generation algorithm for t.
+ */
+ H1 = H1t;
+ H2 = H2t;
+ H3 = H3t;
+ H4 = H4t;
+ H5 = H5t;
+ H6 = H6t;
+ H7 = H7t;
+ H8 = H8t;
+ }
+
+ private void tIvGenerate(int bitLength)
+ {
+ H1 = 0x6a09e667f3bcc908L ^ 0xa5a5a5a5a5a5a5a5L;
+ H2 = 0xbb67ae8584caa73bL ^ 0xa5a5a5a5a5a5a5a5L;
+ H3 = 0x3c6ef372fe94f82bL ^ 0xa5a5a5a5a5a5a5a5L;
+ H4 = 0xa54ff53a5f1d36f1L ^ 0xa5a5a5a5a5a5a5a5L;
+ H5 = 0x510e527fade682d1L ^ 0xa5a5a5a5a5a5a5a5L;
+ H6 = 0x9b05688c2b3e6c1fL ^ 0xa5a5a5a5a5a5a5a5L;
+ H7 = 0x1f83d9abfb41bd6bL ^ 0xa5a5a5a5a5a5a5a5L;
+ H8 = 0x5be0cd19137e2179L ^ 0xa5a5a5a5a5a5a5a5L;
+
+ update((byte)0x53);
+ update((byte)0x48);
+ update((byte)0x41);
+ update((byte)0x2D);
+ update((byte)0x35);
+ update((byte)0x31);
+ update((byte)0x32);
+ update((byte)0x2F);
+
+ if (bitLength > 100)
+ {
+ update((byte)(bitLength / 100 + 0x30));
+ bitLength = bitLength % 100;
+ update((byte)(bitLength / 10 + 0x30));
+ bitLength = bitLength % 10;
+ update((byte)(bitLength + 0x30));
+ }
+ else if (bitLength > 10)
+ {
+ update((byte)(bitLength / 10 + 0x30));
+ bitLength = bitLength % 10;
+ update((byte)(bitLength + 0x30));
+ }
+ else
+ {
+ update((byte)(bitLength + 0x30));
+ }
+
+ finish();
+
+ H1t = H1;
+ H2t = H2;
+ H3t = H3;
+ H4t = H4;
+ H5t = H5;
+ H6t = H6;
+ H7t = H7;
+ H8t = H8;
+ }
+
+ private static void longToBigEndian(long n, byte[] bs, int off, int max)
+ {
+ if (max > 0)
+ {
+ intToBigEndian((int)(n >>> 32), bs, off, max);
+
+ if (max > 4)
+ {
+ intToBigEndian((int)(n & 0xffffffffL), bs, off + 4, max - 4);
+ }
+ }
+ }
+
+ private static void intToBigEndian(int n, byte[] bs, int off, int max)
+ {
+ int num = Math.min(4, max);
+ while (--num >= 0)
+ {
+ int shift = 8 * (3 - num);
+ bs[off + num] = (byte)(n >>> shift);
+ }
+ }
+
+ public Memoable copy()
+ {
+ return new SHA512tDigest(this);
+ }
+
+ public void reset(Memoable other)
+ {
+ SHA512tDigest t = (SHA512tDigest)other;
+
+ if (this.digestLength != t.digestLength)
+ {
+ throw new MemoableResetException("digestLength inappropriate in other");
+ }
+
+ super.copyIn(t);
+
+ this.H1t = t.H1t;
+ this.H2t = t.H2t;
+ this.H3t = t.H3t;
+ this.H4t = t.H4t;
+ this.H5t = t.H5t;
+ this.H6t = t.H6t;
+ this.H7t = t.H7t;
+ this.H8t = t.H8t;
+ }
+
+ public byte[] getEncodedState()
+ {
+ final int baseSize = getEncodedStateSize();
+ byte[] encoded = new byte[baseSize + 4];
+ populateState(encoded);
+ Pack.intToBigEndian(digestLength * 8, encoded, baseSize);
+ return encoded;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/digests/SM3Digest.java b/core/src/main/java/org/spongycastle/crypto/digests/SM3Digest.java
new file mode 100644
index 00000000..ed74ba8e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/SM3Digest.java
@@ -0,0 +1,333 @@
+package org.spongycastle.crypto.digests;
+
+import org.spongycastle.util.Memoable;
+import org.spongycastle.util.Pack;
+
+/**
+ * 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/core/src/main/java/org/spongycastle/crypto/digests/ShortenedDigest.java b/core/src/main/java/org/spongycastle/crypto/digests/ShortenedDigest.java
new file mode 100644
index 00000000..274959f5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/ShortenedDigest.java
@@ -0,0 +1,80 @@
+package org.spongycastle.crypto.digests;
+
+import org.spongycastle.crypto.ExtendedDigest;
+
+/**
+ * Wrapper class that reduces the output length of a particular digest to
+ * only the first n bytes of the digest function.
+ */
+public class ShortenedDigest
+ implements ExtendedDigest
+{
+ private ExtendedDigest baseDigest;
+ private int length;
+
+ /**
+ * Base constructor.
+ *
+ * @param baseDigest underlying digest to use.
+ * @param length length in bytes of the output of doFinal.
+ * @exception IllegalArgumentException if baseDigest is null, or length is greater than baseDigest.getDigestSize().
+ */
+ public ShortenedDigest(
+ ExtendedDigest baseDigest,
+ int length)
+ {
+ if (baseDigest == null)
+ {
+ throw new IllegalArgumentException("baseDigest must not be null");
+ }
+
+ if (length > baseDigest.getDigestSize())
+ {
+ throw new IllegalArgumentException("baseDigest output not large enough to support length");
+ }
+
+ this.baseDigest = baseDigest;
+ this.length = length;
+ }
+
+ public String getAlgorithmName()
+ {
+ return baseDigest.getAlgorithmName() + "(" + length * 8 + ")";
+ }
+
+ public int getDigestSize()
+ {
+ return length;
+ }
+
+ public void update(byte in)
+ {
+ baseDigest.update(in);
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ {
+ baseDigest.update(in, inOff, len);
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ {
+ byte[] tmp = new byte[baseDigest.getDigestSize()];
+
+ baseDigest.doFinal(tmp, 0);
+
+ System.arraycopy(tmp, 0, out, outOff, length);
+
+ return length;
+ }
+
+ public void reset()
+ {
+ baseDigest.reset();
+ }
+
+ public int getByteLength()
+ {
+ return baseDigest.getByteLength();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/digests/SkeinDigest.java b/core/src/main/java/org/spongycastle/crypto/digests/SkeinDigest.java
new file mode 100644
index 00000000..d476170f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/SkeinDigest.java
@@ -0,0 +1,115 @@
+package org.spongycastle.crypto.digests;
+
+import org.spongycastle.crypto.ExtendedDigest;
+import org.spongycastle.crypto.engines.ThreefishEngine;
+import org.spongycastle.crypto.params.SkeinParameters;
+import org.spongycastle.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.
+ *
+ * @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/core/src/main/java/org/spongycastle/crypto/digests/SkeinEngine.java b/core/src/main/java/org/spongycastle/crypto/digests/SkeinEngine.java
new file mode 100644
index 00000000..12d06d8a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/SkeinEngine.java
@@ -0,0 +1,817 @@
+package org.spongycastle.crypto.digests;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.engines.ThreefishEngine;
+import org.spongycastle.crypto.macs.SkeinMac;
+import org.spongycastle.crypto.params.SkeinParameters;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/digests/TigerDigest.java b/core/src/main/java/org/spongycastle/crypto/digests/TigerDigest.java
new file mode 100644
index 00000000..b9d0b83a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/TigerDigest.java
@@ -0,0 +1,879 @@
+package org.spongycastle.crypto.digests;
+
+import org.spongycastle.crypto.ExtendedDigest;
+import org.spongycastle.util.Memoable;
+
+/**
+ * implementation of Tiger based on:
+ * <a href="http://www.cs.technion.ac.il/~biham/Reports/Tiger">
+ * http://www.cs.technion.ac.il/~biham/Reports/Tiger</a>
+ */
+public class TigerDigest
+ implements ExtendedDigest, Memoable
+{
+ private static final int BYTE_LENGTH = 64;
+
+ /*
+ * S-Boxes.
+ */
+ private static final long[] t1 = {
+ 0x02AAB17CF7E90C5EL /* 0 */, 0xAC424B03E243A8ECL /* 1 */,
+ 0x72CD5BE30DD5FCD3L /* 2 */, 0x6D019B93F6F97F3AL /* 3 */,
+ 0xCD9978FFD21F9193L /* 4 */, 0x7573A1C9708029E2L /* 5 */,
+ 0xB164326B922A83C3L /* 6 */, 0x46883EEE04915870L /* 7 */,
+ 0xEAACE3057103ECE6L /* 8 */, 0xC54169B808A3535CL /* 9 */,
+ 0x4CE754918DDEC47CL /* 10 */, 0x0AA2F4DFDC0DF40CL /* 11 */,
+ 0x10B76F18A74DBEFAL /* 12 */, 0xC6CCB6235AD1AB6AL /* 13 */,
+ 0x13726121572FE2FFL /* 14 */, 0x1A488C6F199D921EL /* 15 */,
+ 0x4BC9F9F4DA0007CAL /* 16 */, 0x26F5E6F6E85241C7L /* 17 */,
+ 0x859079DBEA5947B6L /* 18 */, 0x4F1885C5C99E8C92L /* 19 */,
+ 0xD78E761EA96F864BL /* 20 */, 0x8E36428C52B5C17DL /* 21 */,
+ 0x69CF6827373063C1L /* 22 */, 0xB607C93D9BB4C56EL /* 23 */,
+ 0x7D820E760E76B5EAL /* 24 */, 0x645C9CC6F07FDC42L /* 25 */,
+ 0xBF38A078243342E0L /* 26 */, 0x5F6B343C9D2E7D04L /* 27 */,
+ 0xF2C28AEB600B0EC6L /* 28 */, 0x6C0ED85F7254BCACL /* 29 */,
+ 0x71592281A4DB4FE5L /* 30 */, 0x1967FA69CE0FED9FL /* 31 */,
+ 0xFD5293F8B96545DBL /* 32 */, 0xC879E9D7F2A7600BL /* 33 */,
+ 0x860248920193194EL /* 34 */, 0xA4F9533B2D9CC0B3L /* 35 */,
+ 0x9053836C15957613L /* 36 */, 0xDB6DCF8AFC357BF1L /* 37 */,
+ 0x18BEEA7A7A370F57L /* 38 */, 0x037117CA50B99066L /* 39 */,
+ 0x6AB30A9774424A35L /* 40 */, 0xF4E92F02E325249BL /* 41 */,
+ 0x7739DB07061CCAE1L /* 42 */, 0xD8F3B49CECA42A05L /* 43 */,
+ 0xBD56BE3F51382F73L /* 44 */, 0x45FAED5843B0BB28L /* 45 */,
+ 0x1C813D5C11BF1F83L /* 46 */, 0x8AF0E4B6D75FA169L /* 47 */,
+ 0x33EE18A487AD9999L /* 48 */, 0x3C26E8EAB1C94410L /* 49 */,
+ 0xB510102BC0A822F9L /* 50 */, 0x141EEF310CE6123BL /* 51 */,
+ 0xFC65B90059DDB154L /* 52 */, 0xE0158640C5E0E607L /* 53 */,
+ 0x884E079826C3A3CFL /* 54 */, 0x930D0D9523C535FDL /* 55 */,
+ 0x35638D754E9A2B00L /* 56 */, 0x4085FCCF40469DD5L /* 57 */,
+ 0xC4B17AD28BE23A4CL /* 58 */, 0xCAB2F0FC6A3E6A2EL /* 59 */,
+ 0x2860971A6B943FCDL /* 60 */, 0x3DDE6EE212E30446L /* 61 */,
+ 0x6222F32AE01765AEL /* 62 */, 0x5D550BB5478308FEL /* 63 */,
+ 0xA9EFA98DA0EDA22AL /* 64 */, 0xC351A71686C40DA7L /* 65 */,
+ 0x1105586D9C867C84L /* 66 */, 0xDCFFEE85FDA22853L /* 67 */,
+ 0xCCFBD0262C5EEF76L /* 68 */, 0xBAF294CB8990D201L /* 69 */,
+ 0xE69464F52AFAD975L /* 70 */, 0x94B013AFDF133E14L /* 71 */,
+ 0x06A7D1A32823C958L /* 72 */, 0x6F95FE5130F61119L /* 73 */,
+ 0xD92AB34E462C06C0L /* 74 */, 0xED7BDE33887C71D2L /* 75 */,
+ 0x79746D6E6518393EL /* 76 */, 0x5BA419385D713329L /* 77 */,
+ 0x7C1BA6B948A97564L /* 78 */, 0x31987C197BFDAC67L /* 79 */,
+ 0xDE6C23C44B053D02L /* 80 */, 0x581C49FED002D64DL /* 81 */,
+ 0xDD474D6338261571L /* 82 */, 0xAA4546C3E473D062L /* 83 */,
+ 0x928FCE349455F860L /* 84 */, 0x48161BBACAAB94D9L /* 85 */,
+ 0x63912430770E6F68L /* 86 */, 0x6EC8A5E602C6641CL /* 87 */,
+ 0x87282515337DDD2BL /* 88 */, 0x2CDA6B42034B701BL /* 89 */,
+ 0xB03D37C181CB096DL /* 90 */, 0xE108438266C71C6FL /* 91 */,
+ 0x2B3180C7EB51B255L /* 92 */, 0xDF92B82F96C08BBCL /* 93 */,
+ 0x5C68C8C0A632F3BAL /* 94 */, 0x5504CC861C3D0556L /* 95 */,
+ 0xABBFA4E55FB26B8FL /* 96 */, 0x41848B0AB3BACEB4L /* 97 */,
+ 0xB334A273AA445D32L /* 98 */, 0xBCA696F0A85AD881L /* 99 */,
+ 0x24F6EC65B528D56CL /* 100 */, 0x0CE1512E90F4524AL /* 101 */,
+ 0x4E9DD79D5506D35AL /* 102 */, 0x258905FAC6CE9779L /* 103 */,
+ 0x2019295B3E109B33L /* 104 */, 0xF8A9478B73A054CCL /* 105 */,
+ 0x2924F2F934417EB0L /* 106 */, 0x3993357D536D1BC4L /* 107 */,
+ 0x38A81AC21DB6FF8BL /* 108 */, 0x47C4FBF17D6016BFL /* 109 */,
+ 0x1E0FAADD7667E3F5L /* 110 */, 0x7ABCFF62938BEB96L /* 111 */,
+ 0xA78DAD948FC179C9L /* 112 */, 0x8F1F98B72911E50DL /* 113 */,
+ 0x61E48EAE27121A91L /* 114 */, 0x4D62F7AD31859808L /* 115 */,
+ 0xECEBA345EF5CEAEBL /* 116 */, 0xF5CEB25EBC9684CEL /* 117 */,
+ 0xF633E20CB7F76221L /* 118 */, 0xA32CDF06AB8293E4L /* 119 */,
+ 0x985A202CA5EE2CA4L /* 120 */, 0xCF0B8447CC8A8FB1L /* 121 */,
+ 0x9F765244979859A3L /* 122 */, 0xA8D516B1A1240017L /* 123 */,
+ 0x0BD7BA3EBB5DC726L /* 124 */, 0xE54BCA55B86ADB39L /* 125 */,
+ 0x1D7A3AFD6C478063L /* 126 */, 0x519EC608E7669EDDL /* 127 */,
+ 0x0E5715A2D149AA23L /* 128 */, 0x177D4571848FF194L /* 129 */,
+ 0xEEB55F3241014C22L /* 130 */, 0x0F5E5CA13A6E2EC2L /* 131 */,
+ 0x8029927B75F5C361L /* 132 */, 0xAD139FABC3D6E436L /* 133 */,
+ 0x0D5DF1A94CCF402FL /* 134 */, 0x3E8BD948BEA5DFC8L /* 135 */,
+ 0xA5A0D357BD3FF77EL /* 136 */, 0xA2D12E251F74F645L /* 137 */,
+ 0x66FD9E525E81A082L /* 138 */, 0x2E0C90CE7F687A49L /* 139 */,
+ 0xC2E8BCBEBA973BC5L /* 140 */, 0x000001BCE509745FL /* 141 */,
+ 0x423777BBE6DAB3D6L /* 142 */, 0xD1661C7EAEF06EB5L /* 143 */,
+ 0xA1781F354DAACFD8L /* 144 */, 0x2D11284A2B16AFFCL /* 145 */,
+ 0xF1FC4F67FA891D1FL /* 146 */, 0x73ECC25DCB920ADAL /* 147 */,
+ 0xAE610C22C2A12651L /* 148 */, 0x96E0A810D356B78AL /* 149 */,
+ 0x5A9A381F2FE7870FL /* 150 */, 0xD5AD62EDE94E5530L /* 151 */,
+ 0xD225E5E8368D1427L /* 152 */, 0x65977B70C7AF4631L /* 153 */,
+ 0x99F889B2DE39D74FL /* 154 */, 0x233F30BF54E1D143L /* 155 */,
+ 0x9A9675D3D9A63C97L /* 156 */, 0x5470554FF334F9A8L /* 157 */,
+ 0x166ACB744A4F5688L /* 158 */, 0x70C74CAAB2E4AEADL /* 159 */,
+ 0xF0D091646F294D12L /* 160 */, 0x57B82A89684031D1L /* 161 */,
+ 0xEFD95A5A61BE0B6BL /* 162 */, 0x2FBD12E969F2F29AL /* 163 */,
+ 0x9BD37013FEFF9FE8L /* 164 */, 0x3F9B0404D6085A06L /* 165 */,
+ 0x4940C1F3166CFE15L /* 166 */, 0x09542C4DCDF3DEFBL /* 167 */,
+ 0xB4C5218385CD5CE3L /* 168 */, 0xC935B7DC4462A641L /* 169 */,
+ 0x3417F8A68ED3B63FL /* 170 */, 0xB80959295B215B40L /* 171 */,
+ 0xF99CDAEF3B8C8572L /* 172 */, 0x018C0614F8FCB95DL /* 173 */,
+ 0x1B14ACCD1A3ACDF3L /* 174 */, 0x84D471F200BB732DL /* 175 */,
+ 0xC1A3110E95E8DA16L /* 176 */, 0x430A7220BF1A82B8L /* 177 */,
+ 0xB77E090D39DF210EL /* 178 */, 0x5EF4BD9F3CD05E9DL /* 179 */,
+ 0x9D4FF6DA7E57A444L /* 180 */, 0xDA1D60E183D4A5F8L /* 181 */,
+ 0xB287C38417998E47L /* 182 */, 0xFE3EDC121BB31886L /* 183 */,
+ 0xC7FE3CCC980CCBEFL /* 184 */, 0xE46FB590189BFD03L /* 185 */,
+ 0x3732FD469A4C57DCL /* 186 */, 0x7EF700A07CF1AD65L /* 187 */,
+ 0x59C64468A31D8859L /* 188 */, 0x762FB0B4D45B61F6L /* 189 */,
+ 0x155BAED099047718L /* 190 */, 0x68755E4C3D50BAA6L /* 191 */,
+ 0xE9214E7F22D8B4DFL /* 192 */, 0x2ADDBF532EAC95F4L /* 193 */,
+ 0x32AE3909B4BD0109L /* 194 */, 0x834DF537B08E3450L /* 195 */,
+ 0xFA209DA84220728DL /* 196 */, 0x9E691D9B9EFE23F7L /* 197 */,
+ 0x0446D288C4AE8D7FL /* 198 */, 0x7B4CC524E169785BL /* 199 */,
+ 0x21D87F0135CA1385L /* 200 */, 0xCEBB400F137B8AA5L /* 201 */,
+ 0x272E2B66580796BEL /* 202 */, 0x3612264125C2B0DEL /* 203 */,
+ 0x057702BDAD1EFBB2L /* 204 */, 0xD4BABB8EACF84BE9L /* 205 */,
+ 0x91583139641BC67BL /* 206 */, 0x8BDC2DE08036E024L /* 207 */,
+ 0x603C8156F49F68EDL /* 208 */, 0xF7D236F7DBEF5111L /* 209 */,
+ 0x9727C4598AD21E80L /* 210 */, 0xA08A0896670A5FD7L /* 211 */,
+ 0xCB4A8F4309EBA9CBL /* 212 */, 0x81AF564B0F7036A1L /* 213 */,
+ 0xC0B99AA778199ABDL /* 214 */, 0x959F1EC83FC8E952L /* 215 */,
+ 0x8C505077794A81B9L /* 216 */, 0x3ACAAF8F056338F0L /* 217 */,
+ 0x07B43F50627A6778L /* 218 */, 0x4A44AB49F5ECCC77L /* 219 */,
+ 0x3BC3D6E4B679EE98L /* 220 */, 0x9CC0D4D1CF14108CL /* 221 */,
+ 0x4406C00B206BC8A0L /* 222 */, 0x82A18854C8D72D89L /* 223 */,
+ 0x67E366B35C3C432CL /* 224 */, 0xB923DD61102B37F2L /* 225 */,
+ 0x56AB2779D884271DL /* 226 */, 0xBE83E1B0FF1525AFL /* 227 */,
+ 0xFB7C65D4217E49A9L /* 228 */, 0x6BDBE0E76D48E7D4L /* 229 */,
+ 0x08DF828745D9179EL /* 230 */, 0x22EA6A9ADD53BD34L /* 231 */,
+ 0xE36E141C5622200AL /* 232 */, 0x7F805D1B8CB750EEL /* 233 */,
+ 0xAFE5C7A59F58E837L /* 234 */, 0xE27F996A4FB1C23CL /* 235 */,
+ 0xD3867DFB0775F0D0L /* 236 */, 0xD0E673DE6E88891AL /* 237 */,
+ 0x123AEB9EAFB86C25L /* 238 */, 0x30F1D5D5C145B895L /* 239 */,
+ 0xBB434A2DEE7269E7L /* 240 */, 0x78CB67ECF931FA38L /* 241 */,
+ 0xF33B0372323BBF9CL /* 242 */, 0x52D66336FB279C74L /* 243 */,
+ 0x505F33AC0AFB4EAAL /* 244 */, 0xE8A5CD99A2CCE187L /* 245 */,
+ 0x534974801E2D30BBL /* 246 */, 0x8D2D5711D5876D90L /* 247 */,
+ 0x1F1A412891BC038EL /* 248 */, 0xD6E2E71D82E56648L /* 249 */,
+ 0x74036C3A497732B7L /* 250 */, 0x89B67ED96361F5ABL /* 251 */,
+ 0xFFED95D8F1EA02A2L /* 252 */, 0xE72B3BD61464D43DL /* 253 */,
+ 0xA6300F170BDC4820L /* 254 */, 0xEBC18760ED78A77AL /* 255 */,
+ };
+
+ private static final long[] t2 = {
+ 0xE6A6BE5A05A12138L /* 256 */, 0xB5A122A5B4F87C98L /* 257 */,
+ 0x563C6089140B6990L /* 258 */, 0x4C46CB2E391F5DD5L /* 259 */,
+ 0xD932ADDBC9B79434L /* 260 */, 0x08EA70E42015AFF5L /* 261 */,
+ 0xD765A6673E478CF1L /* 262 */, 0xC4FB757EAB278D99L /* 263 */,
+ 0xDF11C6862D6E0692L /* 264 */, 0xDDEB84F10D7F3B16L /* 265 */,
+ 0x6F2EF604A665EA04L /* 266 */, 0x4A8E0F0FF0E0DFB3L /* 267 */,
+ 0xA5EDEEF83DBCBA51L /* 268 */, 0xFC4F0A2A0EA4371EL /* 269 */,
+ 0xE83E1DA85CB38429L /* 270 */, 0xDC8FF882BA1B1CE2L /* 271 */,
+ 0xCD45505E8353E80DL /* 272 */, 0x18D19A00D4DB0717L /* 273 */,
+ 0x34A0CFEDA5F38101L /* 274 */, 0x0BE77E518887CAF2L /* 275 */,
+ 0x1E341438B3C45136L /* 276 */, 0xE05797F49089CCF9L /* 277 */,
+ 0xFFD23F9DF2591D14L /* 278 */, 0x543DDA228595C5CDL /* 279 */,
+ 0x661F81FD99052A33L /* 280 */, 0x8736E641DB0F7B76L /* 281 */,
+ 0x15227725418E5307L /* 282 */, 0xE25F7F46162EB2FAL /* 283 */,
+ 0x48A8B2126C13D9FEL /* 284 */, 0xAFDC541792E76EEAL /* 285 */,
+ 0x03D912BFC6D1898FL /* 286 */, 0x31B1AAFA1B83F51BL /* 287 */,
+ 0xF1AC2796E42AB7D9L /* 288 */, 0x40A3A7D7FCD2EBACL /* 289 */,
+ 0x1056136D0AFBBCC5L /* 290 */, 0x7889E1DD9A6D0C85L /* 291 */,
+ 0xD33525782A7974AAL /* 292 */, 0xA7E25D09078AC09BL /* 293 */,
+ 0xBD4138B3EAC6EDD0L /* 294 */, 0x920ABFBE71EB9E70L /* 295 */,
+ 0xA2A5D0F54FC2625CL /* 296 */, 0xC054E36B0B1290A3L /* 297 */,
+ 0xF6DD59FF62FE932BL /* 298 */, 0x3537354511A8AC7DL /* 299 */,
+ 0xCA845E9172FADCD4L /* 300 */, 0x84F82B60329D20DCL /* 301 */,
+ 0x79C62CE1CD672F18L /* 302 */, 0x8B09A2ADD124642CL /* 303 */,
+ 0xD0C1E96A19D9E726L /* 304 */, 0x5A786A9B4BA9500CL /* 305 */,
+ 0x0E020336634C43F3L /* 306 */, 0xC17B474AEB66D822L /* 307 */,
+ 0x6A731AE3EC9BAAC2L /* 308 */, 0x8226667AE0840258L /* 309 */,
+ 0x67D4567691CAECA5L /* 310 */, 0x1D94155C4875ADB5L /* 311 */,
+ 0x6D00FD985B813FDFL /* 312 */, 0x51286EFCB774CD06L /* 313 */,
+ 0x5E8834471FA744AFL /* 314 */, 0xF72CA0AEE761AE2EL /* 315 */,
+ 0xBE40E4CDAEE8E09AL /* 316 */, 0xE9970BBB5118F665L /* 317 */,
+ 0x726E4BEB33DF1964L /* 318 */, 0x703B000729199762L /* 319 */,
+ 0x4631D816F5EF30A7L /* 320 */, 0xB880B5B51504A6BEL /* 321 */,
+ 0x641793C37ED84B6CL /* 322 */, 0x7B21ED77F6E97D96L /* 323 */,
+ 0x776306312EF96B73L /* 324 */, 0xAE528948E86FF3F4L /* 325 */,
+ 0x53DBD7F286A3F8F8L /* 326 */, 0x16CADCE74CFC1063L /* 327 */,
+ 0x005C19BDFA52C6DDL /* 328 */, 0x68868F5D64D46AD3L /* 329 */,
+ 0x3A9D512CCF1E186AL /* 330 */, 0x367E62C2385660AEL /* 331 */,
+ 0xE359E7EA77DCB1D7L /* 332 */, 0x526C0773749ABE6EL /* 333 */,
+ 0x735AE5F9D09F734BL /* 334 */, 0x493FC7CC8A558BA8L /* 335 */,
+ 0xB0B9C1533041AB45L /* 336 */, 0x321958BA470A59BDL /* 337 */,
+ 0x852DB00B5F46C393L /* 338 */, 0x91209B2BD336B0E5L /* 339 */,
+ 0x6E604F7D659EF19FL /* 340 */, 0xB99A8AE2782CCB24L /* 341 */,
+ 0xCCF52AB6C814C4C7L /* 342 */, 0x4727D9AFBE11727BL /* 343 */,
+ 0x7E950D0C0121B34DL /* 344 */, 0x756F435670AD471FL /* 345 */,
+ 0xF5ADD442615A6849L /* 346 */, 0x4E87E09980B9957AL /* 347 */,
+ 0x2ACFA1DF50AEE355L /* 348 */, 0xD898263AFD2FD556L /* 349 */,
+ 0xC8F4924DD80C8FD6L /* 350 */, 0xCF99CA3D754A173AL /* 351 */,
+ 0xFE477BACAF91BF3CL /* 352 */, 0xED5371F6D690C12DL /* 353 */,
+ 0x831A5C285E687094L /* 354 */, 0xC5D3C90A3708A0A4L /* 355 */,
+ 0x0F7F903717D06580L /* 356 */, 0x19F9BB13B8FDF27FL /* 357 */,
+ 0xB1BD6F1B4D502843L /* 358 */, 0x1C761BA38FFF4012L /* 359 */,
+ 0x0D1530C4E2E21F3BL /* 360 */, 0x8943CE69A7372C8AL /* 361 */,
+ 0xE5184E11FEB5CE66L /* 362 */, 0x618BDB80BD736621L /* 363 */,
+ 0x7D29BAD68B574D0BL /* 364 */, 0x81BB613E25E6FE5BL /* 365 */,
+ 0x071C9C10BC07913FL /* 366 */, 0xC7BEEB7909AC2D97L /* 367 */,
+ 0xC3E58D353BC5D757L /* 368 */, 0xEB017892F38F61E8L /* 369 */,
+ 0xD4EFFB9C9B1CC21AL /* 370 */, 0x99727D26F494F7ABL /* 371 */,
+ 0xA3E063A2956B3E03L /* 372 */, 0x9D4A8B9A4AA09C30L /* 373 */,
+ 0x3F6AB7D500090FB4L /* 374 */, 0x9CC0F2A057268AC0L /* 375 */,
+ 0x3DEE9D2DEDBF42D1L /* 376 */, 0x330F49C87960A972L /* 377 */,
+ 0xC6B2720287421B41L /* 378 */, 0x0AC59EC07C00369CL /* 379 */,
+ 0xEF4EAC49CB353425L /* 380 */, 0xF450244EEF0129D8L /* 381 */,
+ 0x8ACC46E5CAF4DEB6L /* 382 */, 0x2FFEAB63989263F7L /* 383 */,
+ 0x8F7CB9FE5D7A4578L /* 384 */, 0x5BD8F7644E634635L /* 385 */,
+ 0x427A7315BF2DC900L /* 386 */, 0x17D0C4AA2125261CL /* 387 */,
+ 0x3992486C93518E50L /* 388 */, 0xB4CBFEE0A2D7D4C3L /* 389 */,
+ 0x7C75D6202C5DDD8DL /* 390 */, 0xDBC295D8E35B6C61L /* 391 */,
+ 0x60B369D302032B19L /* 392 */, 0xCE42685FDCE44132L /* 393 */,
+ 0x06F3DDB9DDF65610L /* 394 */, 0x8EA4D21DB5E148F0L /* 395 */,
+ 0x20B0FCE62FCD496FL /* 396 */, 0x2C1B912358B0EE31L /* 397 */,
+ 0xB28317B818F5A308L /* 398 */, 0xA89C1E189CA6D2CFL /* 399 */,
+ 0x0C6B18576AAADBC8L /* 400 */, 0xB65DEAA91299FAE3L /* 401 */,
+ 0xFB2B794B7F1027E7L /* 402 */, 0x04E4317F443B5BEBL /* 403 */,
+ 0x4B852D325939D0A6L /* 404 */, 0xD5AE6BEEFB207FFCL /* 405 */,
+ 0x309682B281C7D374L /* 406 */, 0xBAE309A194C3B475L /* 407 */,
+ 0x8CC3F97B13B49F05L /* 408 */, 0x98A9422FF8293967L /* 409 */,
+ 0x244B16B01076FF7CL /* 410 */, 0xF8BF571C663D67EEL /* 411 */,
+ 0x1F0D6758EEE30DA1L /* 412 */, 0xC9B611D97ADEB9B7L /* 413 */,
+ 0xB7AFD5887B6C57A2L /* 414 */, 0x6290AE846B984FE1L /* 415 */,
+ 0x94DF4CDEACC1A5FDL /* 416 */, 0x058A5BD1C5483AFFL /* 417 */,
+ 0x63166CC142BA3C37L /* 418 */, 0x8DB8526EB2F76F40L /* 419 */,
+ 0xE10880036F0D6D4EL /* 420 */, 0x9E0523C9971D311DL /* 421 */,
+ 0x45EC2824CC7CD691L /* 422 */, 0x575B8359E62382C9L /* 423 */,
+ 0xFA9E400DC4889995L /* 424 */, 0xD1823ECB45721568L /* 425 */,
+ 0xDAFD983B8206082FL /* 426 */, 0xAA7D29082386A8CBL /* 427 */,
+ 0x269FCD4403B87588L /* 428 */, 0x1B91F5F728BDD1E0L /* 429 */,
+ 0xE4669F39040201F6L /* 430 */, 0x7A1D7C218CF04ADEL /* 431 */,
+ 0x65623C29D79CE5CEL /* 432 */, 0x2368449096C00BB1L /* 433 */,
+ 0xAB9BF1879DA503BAL /* 434 */, 0xBC23ECB1A458058EL /* 435 */,
+ 0x9A58DF01BB401ECCL /* 436 */, 0xA070E868A85F143DL /* 437 */,
+ 0x4FF188307DF2239EL /* 438 */, 0x14D565B41A641183L /* 439 */,
+ 0xEE13337452701602L /* 440 */, 0x950E3DCF3F285E09L /* 441 */,
+ 0x59930254B9C80953L /* 442 */, 0x3BF299408930DA6DL /* 443 */,
+ 0xA955943F53691387L /* 444 */, 0xA15EDECAA9CB8784L /* 445 */,
+ 0x29142127352BE9A0L /* 446 */, 0x76F0371FFF4E7AFBL /* 447 */,
+ 0x0239F450274F2228L /* 448 */, 0xBB073AF01D5E868BL /* 449 */,
+ 0xBFC80571C10E96C1L /* 450 */, 0xD267088568222E23L /* 451 */,
+ 0x9671A3D48E80B5B0L /* 452 */, 0x55B5D38AE193BB81L /* 453 */,
+ 0x693AE2D0A18B04B8L /* 454 */, 0x5C48B4ECADD5335FL /* 455 */,
+ 0xFD743B194916A1CAL /* 456 */, 0x2577018134BE98C4L /* 457 */,
+ 0xE77987E83C54A4ADL /* 458 */, 0x28E11014DA33E1B9L /* 459 */,
+ 0x270CC59E226AA213L /* 460 */, 0x71495F756D1A5F60L /* 461 */,
+ 0x9BE853FB60AFEF77L /* 462 */, 0xADC786A7F7443DBFL /* 463 */,
+ 0x0904456173B29A82L /* 464 */, 0x58BC7A66C232BD5EL /* 465 */,
+ 0xF306558C673AC8B2L /* 466 */, 0x41F639C6B6C9772AL /* 467 */,
+ 0x216DEFE99FDA35DAL /* 468 */, 0x11640CC71C7BE615L /* 469 */,
+ 0x93C43694565C5527L /* 470 */, 0xEA038E6246777839L /* 471 */,
+ 0xF9ABF3CE5A3E2469L /* 472 */, 0x741E768D0FD312D2L /* 473 */,
+ 0x0144B883CED652C6L /* 474 */, 0xC20B5A5BA33F8552L /* 475 */,
+ 0x1AE69633C3435A9DL /* 476 */, 0x97A28CA4088CFDECL /* 477 */,
+ 0x8824A43C1E96F420L /* 478 */, 0x37612FA66EEEA746L /* 479 */,
+ 0x6B4CB165F9CF0E5AL /* 480 */, 0x43AA1C06A0ABFB4AL /* 481 */,
+ 0x7F4DC26FF162796BL /* 482 */, 0x6CBACC8E54ED9B0FL /* 483 */,
+ 0xA6B7FFEFD2BB253EL /* 484 */, 0x2E25BC95B0A29D4FL /* 485 */,
+ 0x86D6A58BDEF1388CL /* 486 */, 0xDED74AC576B6F054L /* 487 */,
+ 0x8030BDBC2B45805DL /* 488 */, 0x3C81AF70E94D9289L /* 489 */,
+ 0x3EFF6DDA9E3100DBL /* 490 */, 0xB38DC39FDFCC8847L /* 491 */,
+ 0x123885528D17B87EL /* 492 */, 0xF2DA0ED240B1B642L /* 493 */,
+ 0x44CEFADCD54BF9A9L /* 494 */, 0x1312200E433C7EE6L /* 495 */,
+ 0x9FFCC84F3A78C748L /* 496 */, 0xF0CD1F72248576BBL /* 497 */,
+ 0xEC6974053638CFE4L /* 498 */, 0x2BA7B67C0CEC4E4CL /* 499 */,
+ 0xAC2F4DF3E5CE32EDL /* 500 */, 0xCB33D14326EA4C11L /* 501 */,
+ 0xA4E9044CC77E58BCL /* 502 */, 0x5F513293D934FCEFL /* 503 */,
+ 0x5DC9645506E55444L /* 504 */, 0x50DE418F317DE40AL /* 505 */,
+ 0x388CB31A69DDE259L /* 506 */, 0x2DB4A83455820A86L /* 507 */,
+ 0x9010A91E84711AE9L /* 508 */, 0x4DF7F0B7B1498371L /* 509 */,
+ 0xD62A2EABC0977179L /* 510 */, 0x22FAC097AA8D5C0EL /* 511 */,
+ };
+
+ private static final long[] t3 = {
+ 0xF49FCC2FF1DAF39BL /* 512 */, 0x487FD5C66FF29281L /* 513 */,
+ 0xE8A30667FCDCA83FL /* 514 */, 0x2C9B4BE3D2FCCE63L /* 515 */,
+ 0xDA3FF74B93FBBBC2L /* 516 */, 0x2FA165D2FE70BA66L /* 517 */,
+ 0xA103E279970E93D4L /* 518 */, 0xBECDEC77B0E45E71L /* 519 */,
+ 0xCFB41E723985E497L /* 520 */, 0xB70AAA025EF75017L /* 521 */,
+ 0xD42309F03840B8E0L /* 522 */, 0x8EFC1AD035898579L /* 523 */,
+ 0x96C6920BE2B2ABC5L /* 524 */, 0x66AF4163375A9172L /* 525 */,
+ 0x2174ABDCCA7127FBL /* 526 */, 0xB33CCEA64A72FF41L /* 527 */,
+ 0xF04A4933083066A5L /* 528 */, 0x8D970ACDD7289AF5L /* 529 */,
+ 0x8F96E8E031C8C25EL /* 530 */, 0xF3FEC02276875D47L /* 531 */,
+ 0xEC7BF310056190DDL /* 532 */, 0xF5ADB0AEBB0F1491L /* 533 */,
+ 0x9B50F8850FD58892L /* 534 */, 0x4975488358B74DE8L /* 535 */,
+ 0xA3354FF691531C61L /* 536 */, 0x0702BBE481D2C6EEL /* 537 */,
+ 0x89FB24057DEDED98L /* 538 */, 0xAC3075138596E902L /* 539 */,
+ 0x1D2D3580172772EDL /* 540 */, 0xEB738FC28E6BC30DL /* 541 */,
+ 0x5854EF8F63044326L /* 542 */, 0x9E5C52325ADD3BBEL /* 543 */,
+ 0x90AA53CF325C4623L /* 544 */, 0xC1D24D51349DD067L /* 545 */,
+ 0x2051CFEEA69EA624L /* 546 */, 0x13220F0A862E7E4FL /* 547 */,
+ 0xCE39399404E04864L /* 548 */, 0xD9C42CA47086FCB7L /* 549 */,
+ 0x685AD2238A03E7CCL /* 550 */, 0x066484B2AB2FF1DBL /* 551 */,
+ 0xFE9D5D70EFBF79ECL /* 552 */, 0x5B13B9DD9C481854L /* 553 */,
+ 0x15F0D475ED1509ADL /* 554 */, 0x0BEBCD060EC79851L /* 555 */,
+ 0xD58C6791183AB7F8L /* 556 */, 0xD1187C5052F3EEE4L /* 557 */,
+ 0xC95D1192E54E82FFL /* 558 */, 0x86EEA14CB9AC6CA2L /* 559 */,
+ 0x3485BEB153677D5DL /* 560 */, 0xDD191D781F8C492AL /* 561 */,
+ 0xF60866BAA784EBF9L /* 562 */, 0x518F643BA2D08C74L /* 563 */,
+ 0x8852E956E1087C22L /* 564 */, 0xA768CB8DC410AE8DL /* 565 */,
+ 0x38047726BFEC8E1AL /* 566 */, 0xA67738B4CD3B45AAL /* 567 */,
+ 0xAD16691CEC0DDE19L /* 568 */, 0xC6D4319380462E07L /* 569 */,
+ 0xC5A5876D0BA61938L /* 570 */, 0x16B9FA1FA58FD840L /* 571 */,
+ 0x188AB1173CA74F18L /* 572 */, 0xABDA2F98C99C021FL /* 573 */,
+ 0x3E0580AB134AE816L /* 574 */, 0x5F3B05B773645ABBL /* 575 */,
+ 0x2501A2BE5575F2F6L /* 576 */, 0x1B2F74004E7E8BA9L /* 577 */,
+ 0x1CD7580371E8D953L /* 578 */, 0x7F6ED89562764E30L /* 579 */,
+ 0xB15926FF596F003DL /* 580 */, 0x9F65293DA8C5D6B9L /* 581 */,
+ 0x6ECEF04DD690F84CL /* 582 */, 0x4782275FFF33AF88L /* 583 */,
+ 0xE41433083F820801L /* 584 */, 0xFD0DFE409A1AF9B5L /* 585 */,
+ 0x4325A3342CDB396BL /* 586 */, 0x8AE77E62B301B252L /* 587 */,
+ 0xC36F9E9F6655615AL /* 588 */, 0x85455A2D92D32C09L /* 589 */,
+ 0xF2C7DEA949477485L /* 590 */, 0x63CFB4C133A39EBAL /* 591 */,
+ 0x83B040CC6EBC5462L /* 592 */, 0x3B9454C8FDB326B0L /* 593 */,
+ 0x56F56A9E87FFD78CL /* 594 */, 0x2DC2940D99F42BC6L /* 595 */,
+ 0x98F7DF096B096E2DL /* 596 */, 0x19A6E01E3AD852BFL /* 597 */,
+ 0x42A99CCBDBD4B40BL /* 598 */, 0xA59998AF45E9C559L /* 599 */,
+ 0x366295E807D93186L /* 600 */, 0x6B48181BFAA1F773L /* 601 */,
+ 0x1FEC57E2157A0A1DL /* 602 */, 0x4667446AF6201AD5L /* 603 */,
+ 0xE615EBCACFB0F075L /* 604 */, 0xB8F31F4F68290778L /* 605 */,
+ 0x22713ED6CE22D11EL /* 606 */, 0x3057C1A72EC3C93BL /* 607 */,
+ 0xCB46ACC37C3F1F2FL /* 608 */, 0xDBB893FD02AAF50EL /* 609 */,
+ 0x331FD92E600B9FCFL /* 610 */, 0xA498F96148EA3AD6L /* 611 */,
+ 0xA8D8426E8B6A83EAL /* 612 */, 0xA089B274B7735CDCL /* 613 */,
+ 0x87F6B3731E524A11L /* 614 */, 0x118808E5CBC96749L /* 615 */,
+ 0x9906E4C7B19BD394L /* 616 */, 0xAFED7F7E9B24A20CL /* 617 */,
+ 0x6509EADEEB3644A7L /* 618 */, 0x6C1EF1D3E8EF0EDEL /* 619 */,
+ 0xB9C97D43E9798FB4L /* 620 */, 0xA2F2D784740C28A3L /* 621 */,
+ 0x7B8496476197566FL /* 622 */, 0x7A5BE3E6B65F069DL /* 623 */,
+ 0xF96330ED78BE6F10L /* 624 */, 0xEEE60DE77A076A15L /* 625 */,
+ 0x2B4BEE4AA08B9BD0L /* 626 */, 0x6A56A63EC7B8894EL /* 627 */,
+ 0x02121359BA34FEF4L /* 628 */, 0x4CBF99F8283703FCL /* 629 */,
+ 0x398071350CAF30C8L /* 630 */, 0xD0A77A89F017687AL /* 631 */,
+ 0xF1C1A9EB9E423569L /* 632 */, 0x8C7976282DEE8199L /* 633 */,
+ 0x5D1737A5DD1F7ABDL /* 634 */, 0x4F53433C09A9FA80L /* 635 */,
+ 0xFA8B0C53DF7CA1D9L /* 636 */, 0x3FD9DCBC886CCB77L /* 637 */,
+ 0xC040917CA91B4720L /* 638 */, 0x7DD00142F9D1DCDFL /* 639 */,
+ 0x8476FC1D4F387B58L /* 640 */, 0x23F8E7C5F3316503L /* 641 */,
+ 0x032A2244E7E37339L /* 642 */, 0x5C87A5D750F5A74BL /* 643 */,
+ 0x082B4CC43698992EL /* 644 */, 0xDF917BECB858F63CL /* 645 */,
+ 0x3270B8FC5BF86DDAL /* 646 */, 0x10AE72BB29B5DD76L /* 647 */,
+ 0x576AC94E7700362BL /* 648 */, 0x1AD112DAC61EFB8FL /* 649 */,
+ 0x691BC30EC5FAA427L /* 650 */, 0xFF246311CC327143L /* 651 */,
+ 0x3142368E30E53206L /* 652 */, 0x71380E31E02CA396L /* 653 */,
+ 0x958D5C960AAD76F1L /* 654 */, 0xF8D6F430C16DA536L /* 655 */,
+ 0xC8FFD13F1BE7E1D2L /* 656 */, 0x7578AE66004DDBE1L /* 657 */,
+ 0x05833F01067BE646L /* 658 */, 0xBB34B5AD3BFE586DL /* 659 */,
+ 0x095F34C9A12B97F0L /* 660 */, 0x247AB64525D60CA8L /* 661 */,
+ 0xDCDBC6F3017477D1L /* 662 */, 0x4A2E14D4DECAD24DL /* 663 */,
+ 0xBDB5E6D9BE0A1EEBL /* 664 */, 0x2A7E70F7794301ABL /* 665 */,
+ 0xDEF42D8A270540FDL /* 666 */, 0x01078EC0A34C22C1L /* 667 */,
+ 0xE5DE511AF4C16387L /* 668 */, 0x7EBB3A52BD9A330AL /* 669 */,
+ 0x77697857AA7D6435L /* 670 */, 0x004E831603AE4C32L /* 671 */,
+ 0xE7A21020AD78E312L /* 672 */, 0x9D41A70C6AB420F2L /* 673 */,
+ 0x28E06C18EA1141E6L /* 674 */, 0xD2B28CBD984F6B28L /* 675 */,
+ 0x26B75F6C446E9D83L /* 676 */, 0xBA47568C4D418D7FL /* 677 */,
+ 0xD80BADBFE6183D8EL /* 678 */, 0x0E206D7F5F166044L /* 679 */,
+ 0xE258A43911CBCA3EL /* 680 */, 0x723A1746B21DC0BCL /* 681 */,
+ 0xC7CAA854F5D7CDD3L /* 682 */, 0x7CAC32883D261D9CL /* 683 */,
+ 0x7690C26423BA942CL /* 684 */, 0x17E55524478042B8L /* 685 */,
+ 0xE0BE477656A2389FL /* 686 */, 0x4D289B5E67AB2DA0L /* 687 */,
+ 0x44862B9C8FBBFD31L /* 688 */, 0xB47CC8049D141365L /* 689 */,
+ 0x822C1B362B91C793L /* 690 */, 0x4EB14655FB13DFD8L /* 691 */,
+ 0x1ECBBA0714E2A97BL /* 692 */, 0x6143459D5CDE5F14L /* 693 */,
+ 0x53A8FBF1D5F0AC89L /* 694 */, 0x97EA04D81C5E5B00L /* 695 */,
+ 0x622181A8D4FDB3F3L /* 696 */, 0xE9BCD341572A1208L /* 697 */,
+ 0x1411258643CCE58AL /* 698 */, 0x9144C5FEA4C6E0A4L /* 699 */,
+ 0x0D33D06565CF620FL /* 700 */, 0x54A48D489F219CA1L /* 701 */,
+ 0xC43E5EAC6D63C821L /* 702 */, 0xA9728B3A72770DAFL /* 703 */,
+ 0xD7934E7B20DF87EFL /* 704 */, 0xE35503B61A3E86E5L /* 705 */,
+ 0xCAE321FBC819D504L /* 706 */, 0x129A50B3AC60BFA6L /* 707 */,
+ 0xCD5E68EA7E9FB6C3L /* 708 */, 0xB01C90199483B1C7L /* 709 */,
+ 0x3DE93CD5C295376CL /* 710 */, 0xAED52EDF2AB9AD13L /* 711 */,
+ 0x2E60F512C0A07884L /* 712 */, 0xBC3D86A3E36210C9L /* 713 */,
+ 0x35269D9B163951CEL /* 714 */, 0x0C7D6E2AD0CDB5FAL /* 715 */,
+ 0x59E86297D87F5733L /* 716 */, 0x298EF221898DB0E7L /* 717 */,
+ 0x55000029D1A5AA7EL /* 718 */, 0x8BC08AE1B5061B45L /* 719 */,
+ 0xC2C31C2B6C92703AL /* 720 */, 0x94CC596BAF25EF42L /* 721 */,
+ 0x0A1D73DB22540456L /* 722 */, 0x04B6A0F9D9C4179AL /* 723 */,
+ 0xEFFDAFA2AE3D3C60L /* 724 */, 0xF7C8075BB49496C4L /* 725 */,
+ 0x9CC5C7141D1CD4E3L /* 726 */, 0x78BD1638218E5534L /* 727 */,
+ 0xB2F11568F850246AL /* 728 */, 0xEDFABCFA9502BC29L /* 729 */,
+ 0x796CE5F2DA23051BL /* 730 */, 0xAAE128B0DC93537CL /* 731 */,
+ 0x3A493DA0EE4B29AEL /* 732 */, 0xB5DF6B2C416895D7L /* 733 */,
+ 0xFCABBD25122D7F37L /* 734 */, 0x70810B58105DC4B1L /* 735 */,
+ 0xE10FDD37F7882A90L /* 736 */, 0x524DCAB5518A3F5CL /* 737 */,
+ 0x3C9E85878451255BL /* 738 */, 0x4029828119BD34E2L /* 739 */,
+ 0x74A05B6F5D3CECCBL /* 740 */, 0xB610021542E13ECAL /* 741 */,
+ 0x0FF979D12F59E2ACL /* 742 */, 0x6037DA27E4F9CC50L /* 743 */,
+ 0x5E92975A0DF1847DL /* 744 */, 0xD66DE190D3E623FEL /* 745 */,
+ 0x5032D6B87B568048L /* 746 */, 0x9A36B7CE8235216EL /* 747 */,
+ 0x80272A7A24F64B4AL /* 748 */, 0x93EFED8B8C6916F7L /* 749 */,
+ 0x37DDBFF44CCE1555L /* 750 */, 0x4B95DB5D4B99BD25L /* 751 */,
+ 0x92D3FDA169812FC0L /* 752 */, 0xFB1A4A9A90660BB6L /* 753 */,
+ 0x730C196946A4B9B2L /* 754 */, 0x81E289AA7F49DA68L /* 755 */,
+ 0x64669A0F83B1A05FL /* 756 */, 0x27B3FF7D9644F48BL /* 757 */,
+ 0xCC6B615C8DB675B3L /* 758 */, 0x674F20B9BCEBBE95L /* 759 */,
+ 0x6F31238275655982L /* 760 */, 0x5AE488713E45CF05L /* 761 */,
+ 0xBF619F9954C21157L /* 762 */, 0xEABAC46040A8EAE9L /* 763 */,
+ 0x454C6FE9F2C0C1CDL /* 764 */, 0x419CF6496412691CL /* 765 */,
+ 0xD3DC3BEF265B0F70L /* 766 */, 0x6D0E60F5C3578A9EL /* 767 */,
+ };
+
+ private static final long[] t4 = {
+ 0x5B0E608526323C55L /* 768 */, 0x1A46C1A9FA1B59F5L /* 769 */,
+ 0xA9E245A17C4C8FFAL /* 770 */, 0x65CA5159DB2955D7L /* 771 */,
+ 0x05DB0A76CE35AFC2L /* 772 */, 0x81EAC77EA9113D45L /* 773 */,
+ 0x528EF88AB6AC0A0DL /* 774 */, 0xA09EA253597BE3FFL /* 775 */,
+ 0x430DDFB3AC48CD56L /* 776 */, 0xC4B3A67AF45CE46FL /* 777 */,
+ 0x4ECECFD8FBE2D05EL /* 778 */, 0x3EF56F10B39935F0L /* 779 */,
+ 0x0B22D6829CD619C6L /* 780 */, 0x17FD460A74DF2069L /* 781 */,
+ 0x6CF8CC8E8510ED40L /* 782 */, 0xD6C824BF3A6ECAA7L /* 783 */,
+ 0x61243D581A817049L /* 784 */, 0x048BACB6BBC163A2L /* 785 */,
+ 0xD9A38AC27D44CC32L /* 786 */, 0x7FDDFF5BAAF410ABL /* 787 */,
+ 0xAD6D495AA804824BL /* 788 */, 0xE1A6A74F2D8C9F94L /* 789 */,
+ 0xD4F7851235DEE8E3L /* 790 */, 0xFD4B7F886540D893L /* 791 */,
+ 0x247C20042AA4BFDAL /* 792 */, 0x096EA1C517D1327CL /* 793 */,
+ 0xD56966B4361A6685L /* 794 */, 0x277DA5C31221057DL /* 795 */,
+ 0x94D59893A43ACFF7L /* 796 */, 0x64F0C51CCDC02281L /* 797 */,
+ 0x3D33BCC4FF6189DBL /* 798 */, 0xE005CB184CE66AF1L /* 799 */,
+ 0xFF5CCD1D1DB99BEAL /* 800 */, 0xB0B854A7FE42980FL /* 801 */,
+ 0x7BD46A6A718D4B9FL /* 802 */, 0xD10FA8CC22A5FD8CL /* 803 */,
+ 0xD31484952BE4BD31L /* 804 */, 0xC7FA975FCB243847L /* 805 */,
+ 0x4886ED1E5846C407L /* 806 */, 0x28CDDB791EB70B04L /* 807 */,
+ 0xC2B00BE2F573417FL /* 808 */, 0x5C9590452180F877L /* 809 */,
+ 0x7A6BDDFFF370EB00L /* 810 */, 0xCE509E38D6D9D6A4L /* 811 */,
+ 0xEBEB0F00647FA702L /* 812 */, 0x1DCC06CF76606F06L /* 813 */,
+ 0xE4D9F28BA286FF0AL /* 814 */, 0xD85A305DC918C262L /* 815 */,
+ 0x475B1D8732225F54L /* 816 */, 0x2D4FB51668CCB5FEL /* 817 */,
+ 0xA679B9D9D72BBA20L /* 818 */, 0x53841C0D912D43A5L /* 819 */,
+ 0x3B7EAA48BF12A4E8L /* 820 */, 0x781E0E47F22F1DDFL /* 821 */,
+ 0xEFF20CE60AB50973L /* 822 */, 0x20D261D19DFFB742L /* 823 */,
+ 0x16A12B03062A2E39L /* 824 */, 0x1960EB2239650495L /* 825 */,
+ 0x251C16FED50EB8B8L /* 826 */, 0x9AC0C330F826016EL /* 827 */,
+ 0xED152665953E7671L /* 828 */, 0x02D63194A6369570L /* 829 */,
+ 0x5074F08394B1C987L /* 830 */, 0x70BA598C90B25CE1L /* 831 */,
+ 0x794A15810B9742F6L /* 832 */, 0x0D5925E9FCAF8C6CL /* 833 */,
+ 0x3067716CD868744EL /* 834 */, 0x910AB077E8D7731BL /* 835 */,
+ 0x6A61BBDB5AC42F61L /* 836 */, 0x93513EFBF0851567L /* 837 */,
+ 0xF494724B9E83E9D5L /* 838 */, 0xE887E1985C09648DL /* 839 */,
+ 0x34B1D3C675370CFDL /* 840 */, 0xDC35E433BC0D255DL /* 841 */,
+ 0xD0AAB84234131BE0L /* 842 */, 0x08042A50B48B7EAFL /* 843 */,
+ 0x9997C4EE44A3AB35L /* 844 */, 0x829A7B49201799D0L /* 845 */,
+ 0x263B8307B7C54441L /* 846 */, 0x752F95F4FD6A6CA6L /* 847 */,
+ 0x927217402C08C6E5L /* 848 */, 0x2A8AB754A795D9EEL /* 849 */,
+ 0xA442F7552F72943DL /* 850 */, 0x2C31334E19781208L /* 851 */,
+ 0x4FA98D7CEAEE6291L /* 852 */, 0x55C3862F665DB309L /* 853 */,
+ 0xBD0610175D53B1F3L /* 854 */, 0x46FE6CB840413F27L /* 855 */,
+ 0x3FE03792DF0CFA59L /* 856 */, 0xCFE700372EB85E8FL /* 857 */,
+ 0xA7BE29E7ADBCE118L /* 858 */, 0xE544EE5CDE8431DDL /* 859 */,
+ 0x8A781B1B41F1873EL /* 860 */, 0xA5C94C78A0D2F0E7L /* 861 */,
+ 0x39412E2877B60728L /* 862 */, 0xA1265EF3AFC9A62CL /* 863 */,
+ 0xBCC2770C6A2506C5L /* 864 */, 0x3AB66DD5DCE1CE12L /* 865 */,
+ 0xE65499D04A675B37L /* 866 */, 0x7D8F523481BFD216L /* 867 */,
+ 0x0F6F64FCEC15F389L /* 868 */, 0x74EFBE618B5B13C8L /* 869 */,
+ 0xACDC82B714273E1DL /* 870 */, 0xDD40BFE003199D17L /* 871 */,
+ 0x37E99257E7E061F8L /* 872 */, 0xFA52626904775AAAL /* 873 */,
+ 0x8BBBF63A463D56F9L /* 874 */, 0xF0013F1543A26E64L /* 875 */,
+ 0xA8307E9F879EC898L /* 876 */, 0xCC4C27A4150177CCL /* 877 */,
+ 0x1B432F2CCA1D3348L /* 878 */, 0xDE1D1F8F9F6FA013L /* 879 */,
+ 0x606602A047A7DDD6L /* 880 */, 0xD237AB64CC1CB2C7L /* 881 */,
+ 0x9B938E7225FCD1D3L /* 882 */, 0xEC4E03708E0FF476L /* 883 */,
+ 0xFEB2FBDA3D03C12DL /* 884 */, 0xAE0BCED2EE43889AL /* 885 */,
+ 0x22CB8923EBFB4F43L /* 886 */, 0x69360D013CF7396DL /* 887 */,
+ 0x855E3602D2D4E022L /* 888 */, 0x073805BAD01F784CL /* 889 */,
+ 0x33E17A133852F546L /* 890 */, 0xDF4874058AC7B638L /* 891 */,
+ 0xBA92B29C678AA14AL /* 892 */, 0x0CE89FC76CFAADCDL /* 893 */,
+ 0x5F9D4E0908339E34L /* 894 */, 0xF1AFE9291F5923B9L /* 895 */,
+ 0x6E3480F60F4A265FL /* 896 */, 0xEEBF3A2AB29B841CL /* 897 */,
+ 0xE21938A88F91B4ADL /* 898 */, 0x57DFEFF845C6D3C3L /* 899 */,
+ 0x2F006B0BF62CAAF2L /* 900 */, 0x62F479EF6F75EE78L /* 901 */,
+ 0x11A55AD41C8916A9L /* 902 */, 0xF229D29084FED453L /* 903 */,
+ 0x42F1C27B16B000E6L /* 904 */, 0x2B1F76749823C074L /* 905 */,
+ 0x4B76ECA3C2745360L /* 906 */, 0x8C98F463B91691BDL /* 907 */,
+ 0x14BCC93CF1ADE66AL /* 908 */, 0x8885213E6D458397L /* 909 */,
+ 0x8E177DF0274D4711L /* 910 */, 0xB49B73B5503F2951L /* 911 */,
+ 0x10168168C3F96B6BL /* 912 */, 0x0E3D963B63CAB0AEL /* 913 */,
+ 0x8DFC4B5655A1DB14L /* 914 */, 0xF789F1356E14DE5CL /* 915 */,
+ 0x683E68AF4E51DAC1L /* 916 */, 0xC9A84F9D8D4B0FD9L /* 917 */,
+ 0x3691E03F52A0F9D1L /* 918 */, 0x5ED86E46E1878E80L /* 919 */,
+ 0x3C711A0E99D07150L /* 920 */, 0x5A0865B20C4E9310L /* 921 */,
+ 0x56FBFC1FE4F0682EL /* 922 */, 0xEA8D5DE3105EDF9BL /* 923 */,
+ 0x71ABFDB12379187AL /* 924 */, 0x2EB99DE1BEE77B9CL /* 925 */,
+ 0x21ECC0EA33CF4523L /* 926 */, 0x59A4D7521805C7A1L /* 927 */,
+ 0x3896F5EB56AE7C72L /* 928 */, 0xAA638F3DB18F75DCL /* 929 */,
+ 0x9F39358DABE9808EL /* 930 */, 0xB7DEFA91C00B72ACL /* 931 */,
+ 0x6B5541FD62492D92L /* 932 */, 0x6DC6DEE8F92E4D5BL /* 933 */,
+ 0x353F57ABC4BEEA7EL /* 934 */, 0x735769D6DA5690CEL /* 935 */,
+ 0x0A234AA642391484L /* 936 */, 0xF6F9508028F80D9DL /* 937 */,
+ 0xB8E319A27AB3F215L /* 938 */, 0x31AD9C1151341A4DL /* 939 */,
+ 0x773C22A57BEF5805L /* 940 */, 0x45C7561A07968633L /* 941 */,
+ 0xF913DA9E249DBE36L /* 942 */, 0xDA652D9B78A64C68L /* 943 */,
+ 0x4C27A97F3BC334EFL /* 944 */, 0x76621220E66B17F4L /* 945 */,
+ 0x967743899ACD7D0BL /* 946 */, 0xF3EE5BCAE0ED6782L /* 947 */,
+ 0x409F753600C879FCL /* 948 */, 0x06D09A39B5926DB6L /* 949 */,
+ 0x6F83AEB0317AC588L /* 950 */, 0x01E6CA4A86381F21L /* 951 */,
+ 0x66FF3462D19F3025L /* 952 */, 0x72207C24DDFD3BFBL /* 953 */,
+ 0x4AF6B6D3E2ECE2EBL /* 954 */, 0x9C994DBEC7EA08DEL /* 955 */,
+ 0x49ACE597B09A8BC4L /* 956 */, 0xB38C4766CF0797BAL /* 957 */,
+ 0x131B9373C57C2A75L /* 958 */, 0xB1822CCE61931E58L /* 959 */,
+ 0x9D7555B909BA1C0CL /* 960 */, 0x127FAFDD937D11D2L /* 961 */,
+ 0x29DA3BADC66D92E4L /* 962 */, 0xA2C1D57154C2ECBCL /* 963 */,
+ 0x58C5134D82F6FE24L /* 964 */, 0x1C3AE3515B62274FL /* 965 */,
+ 0xE907C82E01CB8126L /* 966 */, 0xF8ED091913E37FCBL /* 967 */,
+ 0x3249D8F9C80046C9L /* 968 */, 0x80CF9BEDE388FB63L /* 969 */,
+ 0x1881539A116CF19EL /* 970 */, 0x5103F3F76BD52457L /* 971 */,
+ 0x15B7E6F5AE47F7A8L /* 972 */, 0xDBD7C6DED47E9CCFL /* 973 */,
+ 0x44E55C410228BB1AL /* 974 */, 0xB647D4255EDB4E99L /* 975 */,
+ 0x5D11882BB8AAFC30L /* 976 */, 0xF5098BBB29D3212AL /* 977 */,
+ 0x8FB5EA14E90296B3L /* 978 */, 0x677B942157DD025AL /* 979 */,
+ 0xFB58E7C0A390ACB5L /* 980 */, 0x89D3674C83BD4A01L /* 981 */,
+ 0x9E2DA4DF4BF3B93BL /* 982 */, 0xFCC41E328CAB4829L /* 983 */,
+ 0x03F38C96BA582C52L /* 984 */, 0xCAD1BDBD7FD85DB2L /* 985 */,
+ 0xBBB442C16082AE83L /* 986 */, 0xB95FE86BA5DA9AB0L /* 987 */,
+ 0xB22E04673771A93FL /* 988 */, 0x845358C9493152D8L /* 989 */,
+ 0xBE2A488697B4541EL /* 990 */, 0x95A2DC2DD38E6966L /* 991 */,
+ 0xC02C11AC923C852BL /* 992 */, 0x2388B1990DF2A87BL /* 993 */,
+ 0x7C8008FA1B4F37BEL /* 994 */, 0x1F70D0C84D54E503L /* 995 */,
+ 0x5490ADEC7ECE57D4L /* 996 */, 0x002B3C27D9063A3AL /* 997 */,
+ 0x7EAEA3848030A2BFL /* 998 */, 0xC602326DED2003C0L /* 999 */,
+ 0x83A7287D69A94086L /* 1000 */, 0xC57A5FCB30F57A8AL /* 1001 */,
+ 0xB56844E479EBE779L /* 1002 */, 0xA373B40F05DCBCE9L /* 1003 */,
+ 0xD71A786E88570EE2L /* 1004 */, 0x879CBACDBDE8F6A0L /* 1005 */,
+ 0x976AD1BCC164A32FL /* 1006 */, 0xAB21E25E9666D78BL /* 1007 */,
+ 0x901063AAE5E5C33CL /* 1008 */, 0x9818B34448698D90L /* 1009 */,
+ 0xE36487AE3E1E8ABBL /* 1010 */, 0xAFBDF931893BDCB4L /* 1011 */,
+ 0x6345A0DC5FBBD519L /* 1012 */, 0x8628FE269B9465CAL /* 1013 */,
+ 0x1E5D01603F9C51ECL /* 1014 */, 0x4DE44006A15049B7L /* 1015 */,
+ 0xBF6C70E5F776CBB1L /* 1016 */, 0x411218F2EF552BEDL /* 1017 */,
+ 0xCB0C0708705A36A3L /* 1018 */, 0xE74D14754F986044L /* 1019 */,
+ 0xCD56D9430EA8280EL /* 1020 */, 0xC12591D7535F5065L /* 1021 */,
+ 0xC83223F1720AEF96L /* 1022 */, 0xC3A0396F7363A51FL /* 1023 */
+ };
+
+ private static final int DIGEST_LENGTH = 24;
+
+ //
+ // registers
+ //
+ private long a, b, c;
+ private long byteCount;
+
+ //
+ // buffers
+ //
+ private byte[] buf = new byte[8];
+ private int bOff = 0;
+
+ private long[] x = new long[8];
+ private int xOff = 0;
+
+ /**
+ * Standard constructor
+ */
+ public TigerDigest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public TigerDigest(TigerDigest t)
+ {
+ this.reset(t);
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Tiger";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ private void processWord(
+ byte[] b,
+ int off)
+ {
+ x[xOff++] = ((long)(b[off + 7] & 0xff) << 56)
+ | ((long)(b[off + 6] & 0xff) << 48)
+ | ((long)(b[off + 5] & 0xff) << 40)
+ | ((long)(b[off + 4] & 0xff) << 32)
+ | ((long)(b[off + 3] & 0xff) << 24)
+ | ((long)(b[off + 2] & 0xff) << 16)
+ | ((long)(b[off + 1] & 0xff) << 8)
+ | ((b[off + 0] & 0xff));
+
+ if (xOff == x.length)
+ {
+ processBlock();
+ }
+
+ bOff = 0;
+ }
+
+ public void update(
+ byte in)
+ {
+ buf[bOff++] = in;
+
+ if (bOff == buf.length)
+ {
+ processWord(buf, 0);
+ }
+
+ byteCount++;
+ }
+
+ public void update(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ //
+ // fill the current word
+ //
+ while ((bOff != 0) && (len > 0))
+ {
+ update(in[inOff]);
+
+ inOff++;
+ len--;
+ }
+
+ //
+ // process whole words.
+ //
+ while (len > 8)
+ {
+ processWord(in, inOff);
+
+ inOff += 8;
+ len -= 8;
+ byteCount += 8;
+ }
+
+ //
+ // load in the remainder.
+ //
+ while (len > 0)
+ {
+ update(in[inOff]);
+
+ inOff++;
+ len--;
+ }
+ }
+
+ private void roundABC(
+ long x,
+ long mul)
+ {
+ c ^= x ;
+ a -= t1[(int)c & 0xff] ^ t2[(int)(c >> 16) & 0xff]
+ ^ t3[(int)(c >> 32) & 0xff] ^ t4[(int)(c >> 48) & 0xff];
+ b += t4[(int)(c >> 8) & 0xff] ^ t3[(int)(c >> 24) & 0xff]
+ ^ t2[(int)(c >> 40) & 0xff] ^ t1[(int)(c >> 56) & 0xff];
+ b *= mul;
+ }
+
+ private void roundBCA(
+ long x,
+ long mul)
+ {
+ a ^= x ;
+ b -= t1[(int)a & 0xff] ^ t2[(int)(a >> 16) & 0xff]
+ ^ t3[(int)(a >> 32) & 0xff] ^ t4[(int)(a >> 48) & 0xff];
+ c += t4[(int)(a >> 8) & 0xff] ^ t3[(int)(a >> 24) & 0xff]
+ ^ t2[(int)(a >> 40) & 0xff] ^ t1[(int)(a >> 56) & 0xff];
+ c *= mul;
+ }
+
+ private void roundCAB(
+ long x,
+ long mul)
+ {
+ b ^= x ;
+ c -= t1[(int)b & 0xff] ^ t2[(int)(b >> 16) & 0xff]
+ ^ t3[(int)(b >> 32) & 0xff] ^ t4[(int)(b >> 48) & 0xff];
+ a += t4[(int)(b >> 8) & 0xff] ^ t3[(int)(b >> 24) & 0xff]
+ ^ t2[(int)(b >> 40) & 0xff] ^ t1[(int)(b >> 56) & 0xff];
+ a *= mul;
+ }
+
+ private void keySchedule()
+ {
+ x[0] -= x[7] ^ 0xA5A5A5A5A5A5A5A5L;
+ x[1] ^= x[0];
+ x[2] += x[1];
+ x[3] -= x[2] ^ ((~x[1]) << 19);
+ x[4] ^= x[3];
+ x[5] += x[4];
+ x[6] -= x[5] ^ ((~x[4]) >>> 23);
+ x[7] ^= x[6];
+ x[0] += x[7];
+ x[1] -= x[0] ^ ((~x[7]) << 19);
+ x[2] ^= x[1];
+ x[3] += x[2];
+ x[4] -= x[3] ^ ((~x[2]) >>> 23);
+ x[5] ^= x[4];
+ x[6] += x[5];
+ x[7] -= x[6] ^ 0x0123456789ABCDEFL;
+ }
+
+ private void processBlock()
+ {
+ //
+ // save abc
+ //
+ long aa = a;
+ long bb = b;
+ long cc = c;
+
+ //
+ // rounds and schedule
+ //
+ roundABC(x[0], 5);
+ roundBCA(x[1], 5);
+ roundCAB(x[2], 5);
+ roundABC(x[3], 5);
+ roundBCA(x[4], 5);
+ roundCAB(x[5], 5);
+ roundABC(x[6], 5);
+ roundBCA(x[7], 5);
+
+ keySchedule();
+
+ roundCAB(x[0], 7);
+ roundABC(x[1], 7);
+ roundBCA(x[2], 7);
+ roundCAB(x[3], 7);
+ roundABC(x[4], 7);
+ roundBCA(x[5], 7);
+ roundCAB(x[6], 7);
+ roundABC(x[7], 7);
+
+ keySchedule();
+
+ roundBCA(x[0], 9);
+ roundCAB(x[1], 9);
+ roundABC(x[2], 9);
+ roundBCA(x[3], 9);
+ roundCAB(x[4], 9);
+ roundABC(x[5], 9);
+ roundBCA(x[6], 9);
+ roundCAB(x[7], 9);
+
+ //
+ // feed forward
+ //
+ a ^= aa;
+ b -= bb;
+ c += cc;
+
+ //
+ // clear the x buffer
+ //
+ xOff = 0;
+ for (int i = 0; i != x.length; i++)
+ {
+ x[i] = 0;
+ }
+ }
+
+ public void unpackWord(
+ long r,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff + 7] = (byte)(r >> 56);
+ out[outOff + 6] = (byte)(r >> 48);
+ out[outOff + 5] = (byte)(r >> 40);
+ out[outOff + 4] = (byte)(r >> 32);
+ out[outOff + 3] = (byte)(r >> 24);
+ out[outOff + 2] = (byte)(r >> 16);
+ out[outOff + 1] = (byte)(r >> 8);
+ out[outOff] = (byte)r;
+ }
+
+ private void processLength(
+ long bitLength)
+ {
+ x[7] = bitLength;
+ }
+
+ private void finish()
+ {
+ long bitLength = (byteCount << 3);
+
+ update((byte)0x01);
+
+ while (bOff != 0)
+ {
+ update((byte)0);
+ }
+
+ processLength(bitLength);
+
+ processBlock();
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ unpackWord(a, out, outOff);
+ unpackWord(b, out, outOff + 8);
+ unpackWord(c, out, outOff + 16);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables
+ */
+ public void reset()
+ {
+ a = 0x0123456789ABCDEFL;
+ b = 0xFEDCBA9876543210L;
+ c = 0xF096A5B4C3B2E187L;
+
+ xOff = 0;
+ for (int i = 0; i != x.length; i++)
+ {
+ x[i] = 0;
+ }
+
+ bOff = 0;
+ for (int i = 0; i != buf.length; i++)
+ {
+ buf[i] = 0;
+ }
+
+ byteCount = 0;
+ }
+
+ public int getByteLength()
+ {
+ return BYTE_LENGTH;
+ }
+
+ public Memoable copy()
+ {
+ return new TigerDigest(this);
+ }
+
+ public void reset(Memoable other)
+ {
+ TigerDigest t = (TigerDigest)other;
+
+ a = t.a;
+ b = t.b;
+ c = t.c;
+
+ System.arraycopy(t.x, 0, x, 0, t.x.length);
+ xOff = t.xOff;
+
+ System.arraycopy(t.buf, 0, buf, 0, t.buf.length);
+ bOff = t.bOff;
+
+ byteCount = t.byteCount;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/digests/WhirlpoolDigest.java b/core/src/main/java/org/spongycastle/crypto/digests/WhirlpoolDigest.java
new file mode 100644
index 00000000..8385f736
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/digests/WhirlpoolDigest.java
@@ -0,0 +1,409 @@
+package org.spongycastle.crypto.digests;
+
+import org.spongycastle.crypto.ExtendedDigest;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Memoable;
+
+
+/**
+ * Implementation of WhirlpoolDigest, based on Java source published by Barreto
+ * and Rijmen.
+ *
+ */
+public final class WhirlpoolDigest
+ implements ExtendedDigest, Memoable
+{
+ private static final int BYTE_LENGTH = 64;
+
+ private static final int DIGEST_LENGTH_BYTES = 512 / 8;
+ private static final int ROUNDS = 10;
+ private static final int REDUCTION_POLYNOMIAL = 0x011d; // 2^8 + 2^4 + 2^3 + 2 + 1;
+
+ private static final int[] SBOX = {
+ 0x18, 0x23, 0xc6, 0xe8, 0x87, 0xb8, 0x01, 0x4f, 0x36, 0xa6, 0xd2, 0xf5, 0x79, 0x6f, 0x91, 0x52,
+ 0x60, 0xbc, 0x9b, 0x8e, 0xa3, 0x0c, 0x7b, 0x35, 0x1d, 0xe0, 0xd7, 0xc2, 0x2e, 0x4b, 0xfe, 0x57,
+ 0x15, 0x77, 0x37, 0xe5, 0x9f, 0xf0, 0x4a, 0xda, 0x58, 0xc9, 0x29, 0x0a, 0xb1, 0xa0, 0x6b, 0x85,
+ 0xbd, 0x5d, 0x10, 0xf4, 0xcb, 0x3e, 0x05, 0x67, 0xe4, 0x27, 0x41, 0x8b, 0xa7, 0x7d, 0x95, 0xd8,
+ 0xfb, 0xee, 0x7c, 0x66, 0xdd, 0x17, 0x47, 0x9e, 0xca, 0x2d, 0xbf, 0x07, 0xad, 0x5a, 0x83, 0x33,
+ 0x63, 0x02, 0xaa, 0x71, 0xc8, 0x19, 0x49, 0xd9, 0xf2, 0xe3, 0x5b, 0x88, 0x9a, 0x26, 0x32, 0xb0,
+ 0xe9, 0x0f, 0xd5, 0x80, 0xbe, 0xcd, 0x34, 0x48, 0xff, 0x7a, 0x90, 0x5f, 0x20, 0x68, 0x1a, 0xae,
+ 0xb4, 0x54, 0x93, 0x22, 0x64, 0xf1, 0x73, 0x12, 0x40, 0x08, 0xc3, 0xec, 0xdb, 0xa1, 0x8d, 0x3d,
+ 0x97, 0x00, 0xcf, 0x2b, 0x76, 0x82, 0xd6, 0x1b, 0xb5, 0xaf, 0x6a, 0x50, 0x45, 0xf3, 0x30, 0xef,
+ 0x3f, 0x55, 0xa2, 0xea, 0x65, 0xba, 0x2f, 0xc0, 0xde, 0x1c, 0xfd, 0x4d, 0x92, 0x75, 0x06, 0x8a,
+ 0xb2, 0xe6, 0x0e, 0x1f, 0x62, 0xd4, 0xa8, 0x96, 0xf9, 0xc5, 0x25, 0x59, 0x84, 0x72, 0x39, 0x4c,
+ 0x5e, 0x78, 0x38, 0x8c, 0xd1, 0xa5, 0xe2, 0x61, 0xb3, 0x21, 0x9c, 0x1e, 0x43, 0xc7, 0xfc, 0x04,
+ 0x51, 0x99, 0x6d, 0x0d, 0xfa, 0xdf, 0x7e, 0x24, 0x3b, 0xab, 0xce, 0x11, 0x8f, 0x4e, 0xb7, 0xeb,
+ 0x3c, 0x81, 0x94, 0xf7, 0xb9, 0x13, 0x2c, 0xd3, 0xe7, 0x6e, 0xc4, 0x03, 0x56, 0x44, 0x7f, 0xa9,
+ 0x2a, 0xbb, 0xc1, 0x53, 0xdc, 0x0b, 0x9d, 0x6c, 0x31, 0x74, 0xf6, 0x46, 0xac, 0x89, 0x14, 0xe1,
+ 0x16, 0x3a, 0x69, 0x09, 0x70, 0xb6, 0xd0, 0xed, 0xcc, 0x42, 0x98, 0xa4, 0x28, 0x5c, 0xf8, 0x86
+ };
+
+ private static final long[] C0 = new long[256];
+ private static final long[] C1 = new long[256];
+ private static final long[] C2 = new long[256];
+ private static final long[] C3 = new long[256];
+ private static final long[] C4 = new long[256];
+ private static final long[] C5 = new long[256];
+ private static final long[] C6 = new long[256];
+ private static final long[] C7 = new long[256];
+
+ private final long[] _rc = new long[ROUNDS + 1];
+
+ public WhirlpoolDigest()
+ {
+ for (int i = 0; i < 256; i++)
+ {
+ int v1 = SBOX[i];
+ int v2 = maskWithReductionPolynomial(v1 << 1);
+ int v4 = maskWithReductionPolynomial(v2 << 1);
+ int v5 = v4 ^ v1;
+ int v8 = maskWithReductionPolynomial(v4 << 1);
+ int v9 = v8 ^ v1;
+
+ C0[i] = packIntoLong(v1, v1, v4, v1, v8, v5, v2, v9);
+ C1[i] = packIntoLong(v9, v1, v1, v4, v1, v8, v5, v2);
+ C2[i] = packIntoLong(v2, v9, v1, v1, v4, v1, v8, v5);
+ C3[i] = packIntoLong(v5, v2, v9, v1, v1, v4, v1, v8);
+ C4[i] = packIntoLong(v8, v5, v2, v9, v1, v1, v4, v1);
+ C5[i] = packIntoLong(v1, v8, v5, v2, v9, v1, v1, v4);
+ C6[i] = packIntoLong(v4, v1, v8, v5, v2, v9, v1, v1);
+ C7[i] = packIntoLong(v1, v4, v1, v8, v5, v2, v9, v1);
+
+ }
+
+ _rc[0] = 0L;
+ for (int r = 1; r <= ROUNDS; r++)
+ {
+ int i = 8 * (r - 1);
+ _rc[r] = (C0[i ] & 0xff00000000000000L) ^
+ (C1[i + 1] & 0x00ff000000000000L) ^
+ (C2[i + 2] & 0x0000ff0000000000L) ^
+ (C3[i + 3] & 0x000000ff00000000L) ^
+ (C4[i + 4] & 0x00000000ff000000L) ^
+ (C5[i + 5] & 0x0000000000ff0000L) ^
+ (C6[i + 6] & 0x000000000000ff00L) ^
+ (C7[i + 7] & 0x00000000000000ffL);
+ }
+
+ }
+
+ private long packIntoLong(int b7, int b6, int b5, int b4, int b3, int b2, int b1, int b0)
+ {
+ return
+ ((long)b7 << 56) ^
+ ((long)b6 << 48) ^
+ ((long)b5 << 40) ^
+ ((long)b4 << 32) ^
+ ((long)b3 << 24) ^
+ ((long)b2 << 16) ^
+ ((long)b1 << 8) ^
+ b0;
+ }
+
+ /*
+ * int's are used to prevent sign extension. The values that are really being used are
+ * actually just 0..255
+ */
+ private int maskWithReductionPolynomial(int input)
+ {
+ int rv = input;
+ if (rv >= 0x100L) // high bit set
+ {
+ rv ^= REDUCTION_POLYNOMIAL; // reduced by the polynomial
+ }
+ return rv;
+ }
+
+ // --------------------------------------------------------------------------------------//
+
+ // -- buffer information --
+ private static final int BITCOUNT_ARRAY_SIZE = 32;
+ private byte[] _buffer = new byte[64];
+ private int _bufferPos = 0;
+ private short[] _bitCount = new short[BITCOUNT_ARRAY_SIZE];
+
+ // -- internal hash state --
+ private long[] _hash = new long[8];
+ private long[] _K = new long[8]; // the round key
+ private long[] _L = new long[8];
+ private long[] _block = new long[8]; // mu (buffer)
+ private long[] _state = new long[8]; // the current "cipher" state
+
+
+
+ /**
+ * Copy constructor. This will copy the state of the provided message
+ * digest.
+ */
+ public WhirlpoolDigest(WhirlpoolDigest originalDigest)
+ {
+ reset(originalDigest);
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Whirlpool";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH_BYTES;
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ {
+ // sets out[outOff] .. out[outOff+DIGEST_LENGTH_BYTES]
+ finish();
+
+ for (int i = 0; i < 8; i++)
+ {
+ convertLongToByteArray(_hash[i], out, outOff + (i * 8));
+ }
+
+ reset();
+ return getDigestSize();
+ }
+
+ /**
+ * reset the chaining variables
+ */
+ public void reset()
+ {
+ // set variables to null, blank, whatever
+ _bufferPos = 0;
+ Arrays.fill(_bitCount, (short)0);
+ Arrays.fill(_buffer, (byte)0);
+ Arrays.fill(_hash, 0);
+ Arrays.fill(_K, 0);
+ Arrays.fill(_L, 0);
+ Arrays.fill(_block, 0);
+ Arrays.fill(_state, 0);
+ }
+
+ // this takes a buffer of information and fills the block
+ private void processFilledBuffer(byte[] in, int inOff)
+ {
+ // copies into the block...
+ for (int i = 0; i < _state.length; i++)
+ {
+ _block[i] = bytesToLongFromBuffer(_buffer, i * 8);
+ }
+ processBlock();
+ _bufferPos = 0;
+ Arrays.fill(_buffer, (byte)0);
+ }
+
+ private long bytesToLongFromBuffer(byte[] buffer, int startPos)
+ {
+ long rv = (((buffer[startPos + 0] & 0xffL) << 56) |
+ ((buffer[startPos + 1] & 0xffL) << 48) |
+ ((buffer[startPos + 2] & 0xffL) << 40) |
+ ((buffer[startPos + 3] & 0xffL) << 32) |
+ ((buffer[startPos + 4] & 0xffL) << 24) |
+ ((buffer[startPos + 5] & 0xffL) << 16) |
+ ((buffer[startPos + 6] & 0xffL) << 8) |
+ ((buffer[startPos + 7]) & 0xffL));
+
+ return rv;
+ }
+
+ private void convertLongToByteArray(long inputLong, byte[] outputArray, int offSet)
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ outputArray[offSet + i] = (byte)((inputLong >> (56 - (i * 8))) & 0xff);
+ }
+ }
+
+ protected void processBlock()
+ {
+ // buffer contents have been transferred to the _block[] array via
+ // processFilledBuffer
+
+ // compute and apply K^0
+ for (int i = 0; i < 8; i++)
+ {
+ _state[i] = _block[i] ^ (_K[i] = _hash[i]);
+ }
+
+ // iterate over the rounds
+ for (int round = 1; round <= ROUNDS; round++)
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ _L[i] = 0;
+ _L[i] ^= C0[(int)(_K[(i - 0) & 7] >>> 56) & 0xff];
+ _L[i] ^= C1[(int)(_K[(i - 1) & 7] >>> 48) & 0xff];
+ _L[i] ^= C2[(int)(_K[(i - 2) & 7] >>> 40) & 0xff];
+ _L[i] ^= C3[(int)(_K[(i - 3) & 7] >>> 32) & 0xff];
+ _L[i] ^= C4[(int)(_K[(i - 4) & 7] >>> 24) & 0xff];
+ _L[i] ^= C5[(int)(_K[(i - 5) & 7] >>> 16) & 0xff];
+ _L[i] ^= C6[(int)(_K[(i - 6) & 7] >>> 8) & 0xff];
+ _L[i] ^= C7[(int)(_K[(i - 7) & 7]) & 0xff];
+ }
+
+ System.arraycopy(_L, 0, _K, 0, _K.length);
+
+ _K[0] ^= _rc[round];
+
+ // apply the round transformation
+ for (int i = 0; i < 8; i++)
+ {
+ _L[i] = _K[i];
+
+ _L[i] ^= C0[(int)(_state[(i - 0) & 7] >>> 56) & 0xff];
+ _L[i] ^= C1[(int)(_state[(i - 1) & 7] >>> 48) & 0xff];
+ _L[i] ^= C2[(int)(_state[(i - 2) & 7] >>> 40) & 0xff];
+ _L[i] ^= C3[(int)(_state[(i - 3) & 7] >>> 32) & 0xff];
+ _L[i] ^= C4[(int)(_state[(i - 4) & 7] >>> 24) & 0xff];
+ _L[i] ^= C5[(int)(_state[(i - 5) & 7] >>> 16) & 0xff];
+ _L[i] ^= C6[(int)(_state[(i - 6) & 7] >>> 8) & 0xff];
+ _L[i] ^= C7[(int)(_state[(i - 7) & 7]) & 0xff];
+ }
+
+ // save the current state
+ System.arraycopy(_L, 0, _state, 0, _state.length);
+ }
+
+ // apply Miuaguchi-Preneel compression
+ for (int i = 0; i < 8; i++)
+ {
+ _hash[i] ^= _state[i] ^ _block[i];
+ }
+
+ }
+
+ public void update(byte in)
+ {
+ _buffer[_bufferPos] = in;
+
+ //System.out.println("adding to buffer = "+_buffer[_bufferPos]);
+
+ ++_bufferPos;
+
+ if (_bufferPos == _buffer.length)
+ {
+ processFilledBuffer(_buffer, 0);
+ }
+
+ increment();
+ }
+
+ /*
+ * increment() can be implemented in this way using 2 arrays or
+ * by having some temporary variables that are used to set the
+ * value provided by EIGHT[i] and carry within the loop.
+ *
+ * not having done any timing, this seems likely to be faster
+ * at the slight expense of 32*(sizeof short) bytes
+ */
+ private static final short[] EIGHT = new short[BITCOUNT_ARRAY_SIZE];
+ static
+ {
+ EIGHT[BITCOUNT_ARRAY_SIZE - 1] = 8;
+ }
+
+ private void increment()
+ {
+ int carry = 0;
+ for (int i = _bitCount.length - 1; i >= 0; i--)
+ {
+ int sum = (_bitCount[i] & 0xff) + EIGHT[i] + carry;
+
+ carry = sum >>> 8;
+ _bitCount[i] = (short)(sum & 0xff);
+ }
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ {
+ while (len > 0)
+ {
+ update(in[inOff]);
+ ++inOff;
+ --len;
+ }
+
+ }
+
+ private void finish()
+ {
+ /*
+ * this makes a copy of the current bit length. at the expense of an
+ * object creation of 32 bytes rather than providing a _stopCounting
+ * boolean which was the alternative I could think of.
+ */
+ byte[] bitLength = copyBitLength();
+
+ _buffer[_bufferPos++] |= 0x80;
+
+ if (_bufferPos == _buffer.length)
+ {
+ processFilledBuffer(_buffer, 0);
+ }
+
+ /*
+ * Final block contains
+ * [ ... data .... ][0][0][0][ length ]
+ *
+ * if [ length ] cannot fit. Need to create a new block.
+ */
+ if (_bufferPos > 32)
+ {
+ while (_bufferPos != 0)
+ {
+ update((byte)0);
+ }
+ }
+
+ while (_bufferPos <= 32)
+ {
+ update((byte)0);
+ }
+
+ // copy the length information to the final 32 bytes of the
+ // 64 byte block....
+ System.arraycopy(bitLength, 0, _buffer, 32, bitLength.length);
+
+ processFilledBuffer(_buffer, 0);
+ }
+
+ private byte[] copyBitLength()
+ {
+ byte[] rv = new byte[BITCOUNT_ARRAY_SIZE];
+ for (int i = 0; i < rv.length; i++)
+ {
+ rv[i] = (byte)(_bitCount[i] & 0xff);
+ }
+ return rv;
+ }
+
+ public int getByteLength()
+ {
+ return BYTE_LENGTH;
+ }
+
+ public Memoable copy()
+ {
+ return new WhirlpoolDigest(this);
+ }
+
+ public void reset(Memoable other)
+ {
+ WhirlpoolDigest originalDigest = (WhirlpoolDigest)other;
+
+ System.arraycopy(originalDigest._rc, 0, _rc, 0, _rc.length);
+
+ System.arraycopy(originalDigest._buffer, 0, _buffer, 0, _buffer.length);
+
+ this._bufferPos = originalDigest._bufferPos;
+ System.arraycopy(originalDigest._bitCount, 0, _bitCount, 0, _bitCount.length);
+
+ // -- internal hash state --
+ System.arraycopy(originalDigest._hash, 0, _hash, 0, _hash.length);
+ System.arraycopy(originalDigest._K, 0, _K, 0, _K.length);
+ System.arraycopy(originalDigest._L, 0, _L, 0, _L.length);
+ System.arraycopy(originalDigest._block, 0, _block, 0, _block.length);
+ System.arraycopy(originalDigest._state, 0, _state, 0, _state.length);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/ec/CustomNamedCurves.java b/core/src/main/java/org/spongycastle/crypto/ec/CustomNamedCurves.java
new file mode 100644
index 00000000..f2735a8c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/ec/CustomNamedCurves.java
@@ -0,0 +1,320 @@
+package org.spongycastle.crypto.ec;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.sec.SECObjectIdentifiers;
+import org.spongycastle.asn1.x9.X9ECParameters;
+import org.spongycastle.asn1.x9.X9ECParametersHolder;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.ec.custom.djb.Curve25519;
+import org.spongycastle.math.ec.custom.sec.SecP192K1Curve;
+import org.spongycastle.math.ec.custom.sec.SecP192R1Curve;
+import org.spongycastle.math.ec.custom.sec.SecP224K1Curve;
+import org.spongycastle.math.ec.custom.sec.SecP224R1Curve;
+import org.spongycastle.math.ec.custom.sec.SecP256K1Curve;
+import org.spongycastle.math.ec.custom.sec.SecP256R1Curve;
+import org.spongycastle.math.ec.custom.sec.SecP384R1Curve;
+import org.spongycastle.math.ec.custom.sec.SecP521R1Curve;
+import org.spongycastle.math.ec.endo.GLVTypeBEndomorphism;
+import org.spongycastle.math.ec.endo.GLVTypeBParameters;
+import org.spongycastle.util.Strings;
+import org.spongycastle.util.encoders.Hex;
+
+public class CustomNamedCurves
+{
+ private static ECCurve configureCurve(ECCurve curve)
+ {
+ return curve;
+ }
+
+ private static ECCurve configureCurveGLV(ECCurve c, GLVTypeBParameters p)
+ {
+ return c.configure().setEndomorphism(new GLVTypeBEndomorphism(c, p)).create();
+ }
+
+ /*
+ * curve25519
+ */
+ static X9ECParametersHolder curve25519 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ byte[] S = null;
+ ECCurve curve = configureCurve(new Curve25519());
+
+ /*
+ * NOTE: Curve25519 was specified in Montgomery form. Rewriting in Weierstrass form
+ * involves substitution of variables, so the base-point x coordinate is 9 + (486662 / 3).
+ *
+ * The Curve25519 paper doesn't say which of the two possible y values the base
+ * point has. The choice here is guided by language in the Ed25519 paper.
+ *
+ * (The other possible y value is 5F51E65E475F794B1FE122D388B72EB36DC2B28192839E4DD6163A5D81312C14)
+ */
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD245A"
+ + "20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9"));
+
+ return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ }
+ };
+
+ /*
+ * secp192k1
+ */
+ static X9ECParametersHolder secp192k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ byte[] S = null;
+ GLVTypeBParameters glv = new GLVTypeBParameters(
+ new BigInteger("bb85691939b869c1d087f601554b96b80cb4f55b35f433c2", 16),
+ new BigInteger("3d84f26c12238d7b4f3d516613c1759033b1a5800175d0b1", 16),
+ new BigInteger[]{
+ new BigInteger("71169be7330b3038edb025f1", 16),
+ new BigInteger("-b3fb3400dec5c4adceb8655c", 16) },
+ new BigInteger[]{
+ new BigInteger("12511cfe811d0f4e6bc688b4d", 16),
+ new BigInteger("71169be7330b3038edb025f1", 16) },
+ new BigInteger("71169be7330b3038edb025f1d0f9", 16),
+ new BigInteger("b3fb3400dec5c4adceb8655d4c94", 16),
+ 208);
+ ECCurve curve = configureCurveGLV(new SecP192K1Curve(), glv);
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"
+ + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D"));
+ return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ }
+ };
+
+ /*
+ * secp192r1
+ */
+ static X9ECParametersHolder secp192r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ byte[] S = Hex.decode("3045AE6FC8422F64ED579528D38120EAE12196D5");
+ ECCurve curve = configureCurve(new SecP192R1Curve());
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"
+ + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811"));
+ return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ }
+ };
+
+ /*
+ * secp224k1
+ */
+ static X9ECParametersHolder secp224k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ byte[] S = null;
+ GLVTypeBParameters glv = new GLVTypeBParameters(
+ new BigInteger("fe0e87005b4e83761908c5131d552a850b3f58b749c37cf5b84d6768", 16),
+ new BigInteger("60dcd2104c4cbc0be6eeefc2bdd610739ec34e317f9b33046c9e4788", 16),
+ new BigInteger[]{
+ new BigInteger("6b8cf07d4ca75c88957d9d670591", 16),
+ new BigInteger("-b8adf1378a6eb73409fa6c9c637d", 16) },
+ new BigInteger[]{
+ new BigInteger("1243ae1b4d71613bc9f780a03690e", 16),
+ new BigInteger("6b8cf07d4ca75c88957d9d670591", 16) },
+ new BigInteger("6b8cf07d4ca75c88957d9d67059037a4", 16),
+ new BigInteger("b8adf1378a6eb73409fa6c9c637ba7f5", 16),
+ 240);
+ ECCurve curve = configureCurveGLV(new SecP224K1Curve(), glv);
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"
+ + "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5"));
+ return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ }
+ };
+
+ /*
+ * secp224r1
+ */
+ static X9ECParametersHolder secp224r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ byte[] S = Hex.decode("BD71344799D5C7FCDC45B59FA3B9AB8F6A948BC5");
+ ECCurve curve = configureCurve(new SecP224R1Curve());
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"
+ + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"));
+ return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ }
+ };
+
+ /*
+ * secp256k1
+ */
+ static X9ECParametersHolder secp256k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ byte[] S = null;
+ GLVTypeBParameters glv = new GLVTypeBParameters(
+ new BigInteger("7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee", 16),
+ new BigInteger("5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72", 16),
+ new BigInteger[]{
+ new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16),
+ new BigInteger("-e4437ed6010e88286f547fa90abfe4c3", 16) },
+ new BigInteger[]{
+ new BigInteger("114ca50f7a8e2f3f657c1108d9d44cfd8", 16),
+ new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16) },
+ new BigInteger("3086d221a7d46bcde86c90e49284eb153dab", 16),
+ new BigInteger("e4437ed6010e88286f547fa90abfe4c42212", 16),
+ 272);
+ ECCurve curve = configureCurveGLV(new SecP256K1Curve(), glv);
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
+ + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"));
+ return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ }
+ };
+
+ /*
+ * secp256r1
+ */
+ static X9ECParametersHolder secp256r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ byte[] S = Hex.decode("C49D360886E704936A6678E1139D26B7819F7E90");
+ ECCurve curve = configureCurve(new SecP256R1Curve());
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"
+ + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"));
+ return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ }
+ };
+
+ /*
+ * secp384r1
+ */
+ static X9ECParametersHolder secp384r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ byte[] S = Hex.decode("A335926AA319A27A1D00896A6773A4827ACDAC73");
+ ECCurve curve = configureCurve(new SecP384R1Curve());
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"
+ + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F"));
+ return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ }
+ };
+
+ /*
+ * secp521r1
+ */
+ static X9ECParametersHolder secp521r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ byte[] S = Hex.decode("D09E8800291CB85396CC6717393284AAA0DA64BA");
+ ECCurve curve = configureCurve(new SecP521R1Curve());
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"
+ + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"));
+ return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ }
+ };
+
+ static final Hashtable nameToCurve = new Hashtable();
+ static final Hashtable nameToOID = new Hashtable();
+ static final Hashtable oidToCurve = new Hashtable();
+ static final Hashtable oidToName = new Hashtable();
+
+ static void defineCurve(String name, X9ECParametersHolder holder)
+ {
+ nameToCurve.put(name, holder);
+ }
+
+ static void defineCurveWithOID(String name, ASN1ObjectIdentifier oid, X9ECParametersHolder holder)
+ {
+ nameToCurve.put(name, holder);
+ nameToOID.put(name, oid);
+ oidToName.put(oid, name);
+ oidToCurve.put(oid, holder);
+ }
+
+ static void defineCurveAlias(String alias, ASN1ObjectIdentifier oid)
+ {
+ alias = Strings.toLowerCase(alias);
+ nameToOID.put(alias, oid);
+ nameToCurve.put(alias, oidToCurve.get(oid));
+ }
+
+ static
+ {
+ defineCurve("curve25519", curve25519);
+
+ defineCurveWithOID("secp192k1", SECObjectIdentifiers.secp192k1, secp192k1);
+ defineCurveWithOID("secp192r1", SECObjectIdentifiers.secp192r1, secp192r1);
+ defineCurveWithOID("secp224k1", SECObjectIdentifiers.secp224k1, secp224k1);
+ defineCurveWithOID("secp224r1", SECObjectIdentifiers.secp224r1, secp224r1);
+ defineCurveWithOID("secp256k1", SECObjectIdentifiers.secp256k1, secp256k1);
+ defineCurveWithOID("secp256r1", SECObjectIdentifiers.secp256r1, secp256r1);
+ defineCurveWithOID("secp384r1", SECObjectIdentifiers.secp384r1, secp384r1);
+ defineCurveWithOID("secp521r1", SECObjectIdentifiers.secp521r1, secp521r1);
+
+ defineCurveAlias("P-192", SECObjectIdentifiers.secp192r1);
+ defineCurveAlias("P-224", SECObjectIdentifiers.secp224r1);
+ defineCurveAlias("P-256", SECObjectIdentifiers.secp256r1);
+ defineCurveAlias("P-384", SECObjectIdentifiers.secp384r1);
+ defineCurveAlias("P-521", SECObjectIdentifiers.secp521r1);
+ }
+
+ public static X9ECParameters getByName(String name)
+ {
+ X9ECParametersHolder holder = (X9ECParametersHolder)nameToCurve.get(Strings.toLowerCase(name));
+ return holder == null ? null : holder.getParameters();
+ }
+
+ /**
+ * return the X9ECParameters object for the named curve represented by the passed in object
+ * identifier. Null if the curve isn't present.
+ *
+ * @param oid
+ * an object identifier representing a named curve, if present.
+ */
+ public static X9ECParameters getByOID(ASN1ObjectIdentifier oid)
+ {
+ X9ECParametersHolder holder = (X9ECParametersHolder)oidToCurve.get(oid);
+ return holder == null ? null : holder.getParameters();
+ }
+
+ /**
+ * return the object identifier signified by the passed in name. Null if there is no object
+ * identifier associated with name.
+ *
+ * @return the object identifier associated with name, if present.
+ */
+ public static ASN1ObjectIdentifier getOID(String name)
+ {
+ return (ASN1ObjectIdentifier)nameToOID.get(Strings.toLowerCase(name));
+ }
+
+ /**
+ * return the named curve name represented by the given object identifier.
+ */
+ public static String getName(ASN1ObjectIdentifier oid)
+ {
+ return (String)oidToName.get(oid);
+ }
+
+ /**
+ * returns an enumeration containing the name strings for curves contained in this structure.
+ */
+ public static Enumeration getNames()
+ {
+ return nameToCurve.keys();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/ec/ECDecryptor.java b/core/src/main/java/org/spongycastle/crypto/ec/ECDecryptor.java
new file mode 100644
index 00000000..23bf6f80
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/ec/ECDecryptor.java
@@ -0,0 +1,11 @@
+package org.spongycastle.crypto.ec;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.math.ec.ECPoint;
+
+public interface ECDecryptor
+{
+ void init(CipherParameters params);
+
+ ECPoint decrypt(ECPair cipherText);
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/ec/ECElGamalDecryptor.java b/core/src/main/java/org/spongycastle/crypto/ec/ECElGamalDecryptor.java
new file mode 100644
index 00000000..5359d98f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/ec/ECElGamalDecryptor.java
@@ -0,0 +1,48 @@
+package org.spongycastle.crypto.ec;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.math.ec.ECPoint;
+
+/**
+ * this does your basic decryption ElGamal style using EC
+ */
+public class ECElGamalDecryptor
+ implements ECDecryptor
+{
+ private ECPrivateKeyParameters key;
+
+ /**
+ * initialise the decryptor.
+ *
+ * @param param the necessary EC key parameters.
+ */
+ public void init(
+ CipherParameters param)
+ {
+ if (!(param instanceof ECPrivateKeyParameters))
+ {
+ throw new IllegalArgumentException("ECPrivateKeyParameters are required for decryption.");
+ }
+
+ this.key = (ECPrivateKeyParameters)param;
+ }
+
+ /**
+ * Decrypt an EC pair producing the original EC point.
+ *
+ * @param pair the EC point pair to process.
+ * @return the result of the Elgamal process.
+ */
+ public ECPoint decrypt(ECPair pair)
+ {
+ if (key == null)
+ {
+ throw new IllegalStateException("ECElGamalDecryptor not initialised");
+ }
+
+ ECPoint tmp = pair.getX().multiply(key.getD());
+
+ return pair.getY().subtract(tmp).normalize();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/ec/ECElGamalEncryptor.java b/core/src/main/java/org/spongycastle/crypto/ec/ECElGamalEncryptor.java
new file mode 100644
index 00000000..505fd502
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/ec/ECElGamalEncryptor.java
@@ -0,0 +1,86 @@
+package org.spongycastle.crypto.ec;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.math.ec.ECMultiplier;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.ec.FixedPointCombMultiplier;
+
+/**
+ * this does your basic ElGamal encryption algorithm using EC
+ */
+public class ECElGamalEncryptor
+ implements ECEncryptor
+{
+ private ECPublicKeyParameters key;
+ private SecureRandom random;
+
+ /**
+ * initialise the encryptor.
+ *
+ * @param param the necessary EC key parameters.
+ */
+ public void init(
+ CipherParameters param)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom p = (ParametersWithRandom)param;
+
+ if (!(p.getParameters() instanceof ECPublicKeyParameters))
+ {
+ throw new IllegalArgumentException("ECPublicKeyParameters are required for encryption.");
+ }
+ this.key = (ECPublicKeyParameters)p.getParameters();
+ this.random = p.getRandom();
+ }
+ else
+ {
+ if (!(param instanceof ECPublicKeyParameters))
+ {
+ throw new IllegalArgumentException("ECPublicKeyParameters are required for encryption.");
+ }
+
+ this.key = (ECPublicKeyParameters)param;
+ this.random = new SecureRandom();
+ }
+ }
+
+ /**
+ * Process a single EC point using the basic ElGamal algorithm.
+ *
+ * @param point the EC point to process.
+ * @return the result of the Elgamal process.
+ */
+ public ECPair encrypt(ECPoint point)
+ {
+ if (key == null)
+ {
+ throw new IllegalStateException("ECElGamalEncryptor not initialised");
+ }
+
+ ECDomainParameters ec = key.getParameters();
+ BigInteger k = ECUtil.generateK(ec.getN(), random);
+
+ ECMultiplier basePointMultiplier = createBasePointMultiplier();
+
+ ECPoint[] gamma_phi = new ECPoint[]{
+ basePointMultiplier.multiply(ec.getG(), k),
+ key.getQ().multiply(k).add(point)
+ };
+
+ ec.getCurve().normalizeAll(gamma_phi);
+
+ return new ECPair(gamma_phi[0], gamma_phi[1]);
+ }
+
+ protected ECMultiplier createBasePointMultiplier()
+ {
+ return new FixedPointCombMultiplier();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/ec/ECEncryptor.java b/core/src/main/java/org/spongycastle/crypto/ec/ECEncryptor.java
new file mode 100644
index 00000000..ee63720b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/ec/ECEncryptor.java
@@ -0,0 +1,11 @@
+package org.spongycastle.crypto.ec;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.math.ec.ECPoint;
+
+public interface ECEncryptor
+{
+ void init(CipherParameters params);
+
+ ECPair encrypt(ECPoint point);
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/ec/ECFixedTransform.java b/core/src/main/java/org/spongycastle/crypto/ec/ECFixedTransform.java
new file mode 100644
index 00000000..9bd5162b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/ec/ECFixedTransform.java
@@ -0,0 +1,88 @@
+package org.spongycastle.crypto.ec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.math.ec.ECMultiplier;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.ec.FixedPointCombMultiplier;
+
+/**
+ * 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 text 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");
+ }
+
+ ECDomainParameters ec = key.getParameters();
+ BigInteger n = ec.getN();
+
+ ECMultiplier basePointMultiplier = createBasePointMultiplier();
+ BigInteger k = this.k.mod(n);
+
+ ECPoint[] gamma_phi = new ECPoint[]{
+ basePointMultiplier.multiply(ec.getG(), k).add(cipherText.getX()),
+ key.getQ().multiply(k).add(cipherText.getY())
+ };
+
+ ec.getCurve().normalizeAll(gamma_phi);
+
+ return new ECPair(gamma_phi[0], gamma_phi[1]);
+ }
+
+ /**
+ * Return the last transform value used by the transform
+ *
+ * @return a BigInteger representing k value.
+ */
+ public BigInteger getTransformValue()
+ {
+ return k;
+ }
+
+ protected ECMultiplier createBasePointMultiplier()
+ {
+ return new FixedPointCombMultiplier();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/ec/ECNewPublicKeyTransform.java b/core/src/main/java/org/spongycastle/crypto/ec/ECNewPublicKeyTransform.java
new file mode 100644
index 00000000..a1d67fa9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/ec/ECNewPublicKeyTransform.java
@@ -0,0 +1,88 @@
+package org.spongycastle.crypto.ec;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.math.ec.ECMultiplier;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.ec.FixedPointCombMultiplier;
+
+/**
+ * this does your basic Elgamal encryption algorithm using EC
+ */
+public class ECNewPublicKeyTransform
+ implements ECPairTransform
+{
+ private ECPublicKeyParameters key;
+ private SecureRandom random;
+
+ /**
+ * initialise the EC Elgamal engine.
+ *
+ * @param param the necessary EC key parameters.
+ */
+ public void init(
+ CipherParameters param)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom p = (ParametersWithRandom)param;
+
+ if (!(p.getParameters() instanceof ECPublicKeyParameters))
+ {
+ throw new IllegalArgumentException("ECPublicKeyParameters are required for new public key transform.");
+ }
+ this.key = (ECPublicKeyParameters)p.getParameters();
+ this.random = p.getRandom();
+ }
+ else
+ {
+ if (!(param instanceof ECPublicKeyParameters))
+ {
+ throw new IllegalArgumentException("ECPublicKeyParameters are required for new public key transform.");
+ }
+
+ this.key = (ECPublicKeyParameters)param;
+ this.random = new SecureRandom();
+ }
+ }
+
+ /**
+ * Transform an existing cipher text pair using the ElGamal algorithm. Note: the input cipherText will
+ * need to be preserved in order to complete the transformation to the new public key.
+ *
+ * @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("ECNewPublicKeyTransform not initialised");
+ }
+
+ ECDomainParameters ec = key.getParameters();
+ BigInteger n = ec.getN();
+
+ ECMultiplier basePointMultiplier = createBasePointMultiplier();
+ BigInteger k = ECUtil.generateK(n, random);
+
+ ECPoint[] gamma_phi = new ECPoint[]{
+ basePointMultiplier.multiply(ec.getG(), k),
+ key.getQ().multiply(k).add(cipherText.getY())
+ };
+
+ ec.getCurve().normalizeAll(gamma_phi);
+
+ return new ECPair(gamma_phi[0], gamma_phi[1]);
+ }
+
+ protected ECMultiplier createBasePointMultiplier()
+ {
+ return new FixedPointCombMultiplier();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/ec/ECNewRandomnessTransform.java b/core/src/main/java/org/spongycastle/crypto/ec/ECNewRandomnessTransform.java
new file mode 100644
index 00000000..0f689d4d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/ec/ECNewRandomnessTransform.java
@@ -0,0 +1,105 @@
+package org.spongycastle.crypto.ec;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.math.ec.ECMultiplier;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.ec.FixedPointCombMultiplier;
+
+/**
+ * this transforms the original randomness used for an ElGamal encryption.
+ */
+public class ECNewRandomnessTransform
+ implements ECPairFactorTransform
+{
+ private ECPublicKeyParameters key;
+ private SecureRandom random;
+
+ private BigInteger lastK;
+
+ /**
+ * initialise the underlying EC ElGamal engine.
+ *
+ * @param param the necessary EC key parameters.
+ */
+ public void init(
+ CipherParameters param)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom p = (ParametersWithRandom)param;
+
+ if (!(p.getParameters() instanceof ECPublicKeyParameters))
+ {
+ throw new IllegalArgumentException("ECPublicKeyParameters are required for new randomness transform.");
+ }
+
+ this.key = (ECPublicKeyParameters)p.getParameters();
+ this.random = p.getRandom();
+ }
+ else
+ {
+ if (!(param instanceof ECPublicKeyParameters))
+ {
+ throw new IllegalArgumentException("ECPublicKeyParameters are required for new randomness transform.");
+ }
+
+ this.key = (ECPublicKeyParameters)param;
+ this.random = new SecureRandom();
+ }
+ }
+
+ /**
+ * 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("ECNewRandomnessTransform not initialised");
+ }
+
+
+ ECDomainParameters ec = key.getParameters();
+ BigInteger n = ec.getN();
+
+ ECMultiplier basePointMultiplier = createBasePointMultiplier();
+ BigInteger k = ECUtil.generateK(n, random);
+
+ ECPoint[] gamma_phi = new ECPoint[]{
+ basePointMultiplier.multiply(ec.getG(), k).add(cipherText.getX()),
+ key.getQ().multiply(k).add(cipherText.getY())
+ };
+
+ ec.getCurve().normalizeAll(gamma_phi);
+
+ lastK = k;
+
+ return new ECPair(gamma_phi[0], gamma_phi[1]);
+ }
+
+ /**
+ * Return the last random value generated for a transform
+ *
+ * @return a BigInteger representing the last random value.
+ */
+ public BigInteger getTransformValue()
+ {
+ return lastK;
+ }
+
+ protected ECMultiplier createBasePointMultiplier()
+ {
+ return new FixedPointCombMultiplier();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/ec/ECPair.java b/core/src/main/java/org/spongycastle/crypto/ec/ECPair.java
new file mode 100644
index 00000000..1b8d247d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/ec/ECPair.java
@@ -0,0 +1,40 @@
+package org.spongycastle.crypto.ec;
+
+import org.spongycastle.math.ec.ECPoint;
+
+public class ECPair
+{
+ private final ECPoint x;
+ private final ECPoint y;
+
+ public ECPair(ECPoint x, ECPoint y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ public ECPoint getX()
+ {
+ return x;
+ }
+
+ public ECPoint getY()
+ {
+ return y;
+ }
+
+ public boolean equals(ECPair other)
+ {
+ return other.getX().equals(getX()) && other.getY().equals(getY());
+ }
+
+ public boolean equals(Object other)
+ {
+ return other instanceof ECPair ? equals((ECPair)other) : false;
+ }
+
+ public int hashCode()
+ {
+ return x.hashCode() + 37 * y.hashCode();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/ec/ECPairFactorTransform.java b/core/src/main/java/org/spongycastle/crypto/ec/ECPairFactorTransform.java
new file mode 100644
index 00000000..db1c8ce5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/ec/ECPairFactorTransform.java
@@ -0,0 +1,14 @@
+package org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/ec/ECPairTransform.java b/core/src/main/java/org/spongycastle/crypto/ec/ECPairTransform.java
new file mode 100644
index 00000000..209937cd
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/ec/ECPairTransform.java
@@ -0,0 +1,10 @@
+package org.spongycastle.crypto.ec;
+
+import org.spongycastle.crypto.CipherParameters;
+
+public interface ECPairTransform
+{
+ void init(CipherParameters params);
+
+ ECPair transform(ECPair cipherText);
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/ec/ECUtil.java b/core/src/main/java/org/spongycastle/crypto/ec/ECUtil.java
new file mode 100644
index 00000000..cbfaaaa6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/ec/ECUtil.java
@@ -0,0 +1,21 @@
+package org.spongycastle.crypto.ec;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.math.ec.ECConstants;
+
+class ECUtil
+{
+ static BigInteger generateK(BigInteger n, SecureRandom random)
+ {
+ int nBitLength = n.bitLength();
+ BigInteger k;
+ do
+ {
+ k = new BigInteger(nBitLength, random);
+ }
+ while (k.equals(ECConstants.ZERO) || (k.compareTo(n) >= 0));
+ return k;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/encodings/ISO9796d1Encoding.java b/core/src/main/java/org/spongycastle/crypto/encodings/ISO9796d1Encoding.java
new file mode 100644
index 00000000..0fdc0593
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/encodings/ISO9796d1Encoding.java
@@ -0,0 +1,287 @@
+package org.spongycastle.crypto.encodings;
+
+import java.math.BigInteger;
+
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+
+/**
+ * ISO 9796-1 padding. Note in the light of recent results you should
+ * only use this with RSA (rather than the "simpler" Rabin keys) and you
+ * should never use it with anything other than a hash (ie. even if the
+ * message is small don't sign the message, sign it's hash) or some "random"
+ * value. See your favorite search engine for details.
+ */
+public class ISO9796d1Encoding
+ implements AsymmetricBlockCipher
+{
+ private static final BigInteger SIXTEEN = BigInteger.valueOf(16L);
+ private static final BigInteger SIX = BigInteger.valueOf(6L);
+
+ private static byte[] shadows = { 0xe, 0x3, 0x5, 0x8, 0x9, 0x4, 0x2, 0xf,
+ 0x0, 0xd, 0xb, 0x6, 0x7, 0xa, 0xc, 0x1 };
+ private static byte[] inverse = { 0x8, 0xf, 0x6, 0x1, 0x5, 0x2, 0xb, 0xc,
+ 0x3, 0x4, 0xd, 0xa, 0xe, 0x9, 0x0, 0x7 };
+
+ private AsymmetricBlockCipher engine;
+ private boolean forEncryption;
+ private int bitSize;
+ private int padBits = 0;
+ private BigInteger modulus;
+
+ public ISO9796d1Encoding(
+ AsymmetricBlockCipher cipher)
+ {
+ this.engine = cipher;
+ }
+
+ public AsymmetricBlockCipher getUnderlyingCipher()
+ {
+ return engine;
+ }
+
+ public void init(
+ boolean forEncryption,
+ CipherParameters param)
+ {
+ RSAKeyParameters kParam = null;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ kParam = (RSAKeyParameters)rParam.getParameters();
+ }
+ else
+ {
+ kParam = (RSAKeyParameters)param;
+ }
+
+ engine.init(forEncryption, param);
+
+ modulus = kParam.getModulus();
+ bitSize = modulus.bitLength();
+
+ this.forEncryption = forEncryption;
+ }
+
+ /**
+ * return the input block size. The largest message we can process
+ * is (key_size_in_bits + 3)/16, which in our world comes to
+ * key_size_in_bytes / 2.
+ */
+ public int getInputBlockSize()
+ {
+ int baseBlockSize = engine.getInputBlockSize();
+
+ if (forEncryption)
+ {
+ return (baseBlockSize + 1) / 2;
+ }
+ else
+ {
+ return baseBlockSize;
+ }
+ }
+
+ /**
+ * return the maximum possible size for the output.
+ */
+ public int getOutputBlockSize()
+ {
+ int baseBlockSize = engine.getOutputBlockSize();
+
+ if (forEncryption)
+ {
+ return baseBlockSize;
+ }
+ else
+ {
+ return (baseBlockSize + 1) / 2;
+ }
+ }
+
+ /**
+ * set the number of bits in the next message to be treated as
+ * pad bits.
+ */
+ public void setPadBits(
+ int padBits)
+ {
+ if (padBits > 7)
+ {
+ throw new IllegalArgumentException("padBits > 7");
+ }
+
+ this.padBits = padBits;
+ }
+
+ /**
+ * retrieve the number of pad bits in the last decoded message.
+ */
+ public int getPadBits()
+ {
+ return padBits;
+ }
+
+ public byte[] processBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ if (forEncryption)
+ {
+ return encodeBlock(in, inOff, inLen);
+ }
+ else
+ {
+ return decodeBlock(in, inOff, inLen);
+ }
+ }
+
+ private byte[] encodeBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ byte[] block = new byte[(bitSize + 7) / 8];
+ int r = padBits + 1;
+ int z = inLen;
+ int t = (bitSize + 13) / 16;
+
+ for (int i = 0; i < t; i += z)
+ {
+ if (i > t - z)
+ {
+ System.arraycopy(in, inOff + inLen - (t - i),
+ block, block.length - t, t - i);
+ }
+ else
+ {
+ System.arraycopy(in, inOff, block, block.length - (i + z), z);
+ }
+ }
+
+ for (int i = block.length - 2 * t; i != block.length; i += 2)
+ {
+ byte val = block[block.length - t + i / 2];
+
+ block[i] = (byte)((shadows[(val & 0xff) >>> 4] << 4)
+ | shadows[val & 0x0f]);
+ block[i + 1] = val;
+ }
+
+ block[block.length - 2 * z] ^= r;
+ block[block.length - 1] = (byte)((block[block.length - 1] << 4) | 0x06);
+
+ int maxBit = (8 - (bitSize - 1) % 8);
+ int offSet = 0;
+
+ if (maxBit != 8)
+ {
+ block[0] &= 0xff >>> maxBit;
+ block[0] |= 0x80 >>> maxBit;
+ }
+ else
+ {
+ block[0] = 0x00;
+ block[1] |= 0x80;
+ offSet = 1;
+ }
+
+ return engine.processBlock(block, offSet, block.length - offSet);
+ }
+
+ /**
+ * @exception InvalidCipherTextException if the decrypted block is not a valid ISO 9796 bit string
+ */
+ private byte[] decodeBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ byte[] block = engine.processBlock(in, inOff, inLen);
+ int r = 1;
+ int t = (bitSize + 13) / 16;
+
+ BigInteger iS = new BigInteger(1, block);
+ BigInteger iR;
+ if (iS.mod(SIXTEEN).equals(SIX))
+ {
+ iR = iS;
+ }
+ else if ((modulus.subtract(iS)).mod(SIXTEEN).equals(SIX))
+ {
+ iR = modulus.subtract(iS);
+ }
+ else
+ {
+ throw new InvalidCipherTextException("resulting integer iS or (modulus - iS) is not congruent to 6 mod 16");
+ }
+
+ block = convertOutputDecryptOnly(iR);
+
+ if ((block[block.length - 1] & 0x0f) != 0x6 )
+ {
+ throw new InvalidCipherTextException("invalid forcing byte in block");
+ }
+
+ block[block.length - 1] = (byte)(((block[block.length - 1] & 0xff) >>> 4) | ((inverse[(block[block.length - 2] & 0xff) >> 4]) << 4));
+ block[0] = (byte)((shadows[(block[1] & 0xff) >>> 4] << 4)
+ | shadows[block[1] & 0x0f]);
+
+ boolean boundaryFound = false;
+ int boundary = 0;
+
+ for (int i = block.length - 1; i >= block.length - 2 * t; i -= 2)
+ {
+ int val = ((shadows[(block[i] & 0xff) >>> 4] << 4)
+ | shadows[block[i] & 0x0f]);
+
+ if (((block[i - 1] ^ val) & 0xff) != 0)
+ {
+ if (!boundaryFound)
+ {
+ boundaryFound = true;
+ r = (block[i - 1] ^ val) & 0xff;
+ boundary = i - 1;
+ }
+ else
+ {
+ throw new InvalidCipherTextException("invalid tsums in block");
+ }
+ }
+ }
+
+ block[boundary] = 0;
+
+ byte[] nblock = new byte[(block.length - boundary) / 2];
+
+ for (int i = 0; i < nblock.length; i++)
+ {
+ nblock[i] = block[2 * i + boundary + 1];
+ }
+
+ padBits = r - 1;
+
+ return nblock;
+ }
+
+ private static byte[] convertOutputDecryptOnly(BigInteger result)
+ {
+ byte[] output = result.toByteArray();
+ if (output[0] == 0) // have ended up with an extra zero byte, copy down.
+ {
+ byte[] tmp = new byte[output.length - 1];
+ System.arraycopy(output, 1, tmp, 0, tmp.length);
+ return tmp;
+ }
+ return output;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/encodings/OAEPEncoding.java b/core/src/main/java/org/spongycastle/crypto/encodings/OAEPEncoding.java
new file mode 100644
index 00000000..11796fce
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/encodings/OAEPEncoding.java
@@ -0,0 +1,357 @@
+package org.spongycastle.crypto.encodings;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+
+/**
+ * Optimal Asymmetric Encryption Padding (OAEP) - see PKCS 1 V 2.
+ */
+public class OAEPEncoding
+ implements AsymmetricBlockCipher
+{
+ private byte[] defHash;
+ private Digest mgf1Hash;
+
+ private AsymmetricBlockCipher engine;
+ private SecureRandom random;
+ private boolean forEncryption;
+
+ public OAEPEncoding(
+ AsymmetricBlockCipher cipher)
+ {
+ this(cipher, new SHA1Digest(), null);
+ }
+
+ public OAEPEncoding(
+ AsymmetricBlockCipher cipher,
+ Digest hash)
+ {
+ this(cipher, hash, null);
+ }
+
+ public OAEPEncoding(
+ AsymmetricBlockCipher cipher,
+ Digest hash,
+ byte[] encodingParams)
+ {
+ this(cipher, hash, hash, encodingParams);
+ }
+
+ public OAEPEncoding(
+ AsymmetricBlockCipher cipher,
+ Digest hash,
+ Digest mgf1Hash,
+ byte[] encodingParams)
+ {
+ this.engine = cipher;
+ this.mgf1Hash = mgf1Hash;
+ this.defHash = new byte[hash.getDigestSize()];
+
+ hash.reset();
+
+ if (encodingParams != null)
+ {
+ hash.update(encodingParams, 0, encodingParams.length);
+ }
+
+ hash.doFinal(defHash, 0);
+ }
+
+ public AsymmetricBlockCipher getUnderlyingCipher()
+ {
+ return engine;
+ }
+
+ public void init(
+ boolean forEncryption,
+ CipherParameters param)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.random = rParam.getRandom();
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ }
+
+ engine.init(forEncryption, param);
+
+ this.forEncryption = forEncryption;
+ }
+
+ public int getInputBlockSize()
+ {
+ int baseBlockSize = engine.getInputBlockSize();
+
+ if (forEncryption)
+ {
+ return baseBlockSize - 1 - 2 * defHash.length;
+ }
+ else
+ {
+ return baseBlockSize;
+ }
+ }
+
+ public int getOutputBlockSize()
+ {
+ int baseBlockSize = engine.getOutputBlockSize();
+
+ if (forEncryption)
+ {
+ return baseBlockSize;
+ }
+ else
+ {
+ return baseBlockSize - 1 - 2 * defHash.length;
+ }
+ }
+
+ public byte[] processBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ if (forEncryption)
+ {
+ return encodeBlock(in, inOff, inLen);
+ }
+ else
+ {
+ return decodeBlock(in, inOff, inLen);
+ }
+ }
+
+ public byte[] encodeBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ byte[] block = new byte[getInputBlockSize() + 1 + 2 * defHash.length];
+
+ //
+ // copy in the message
+ //
+ System.arraycopy(in, inOff, block, block.length - inLen, inLen);
+
+ //
+ // add sentinel
+ //
+ block[block.length - inLen - 1] = 0x01;
+
+ //
+ // as the block is already zeroed - there's no need to add PS (the >= 0 pad of 0)
+ //
+
+ //
+ // add the hash of the encoding params.
+ //
+ System.arraycopy(defHash, 0, block, defHash.length, defHash.length);
+
+ //
+ // generate the seed.
+ //
+ byte[] seed = new byte[defHash.length];
+
+ random.nextBytes(seed);
+
+ //
+ // mask the message block.
+ //
+ byte[] mask = maskGeneratorFunction1(seed, 0, seed.length, block.length - defHash.length);
+
+ for (int i = defHash.length; i != block.length; i++)
+ {
+ block[i] ^= mask[i - defHash.length];
+ }
+
+ //
+ // add in the seed
+ //
+ System.arraycopy(seed, 0, block, 0, defHash.length);
+
+ //
+ // mask the seed.
+ //
+ mask = maskGeneratorFunction1(
+ block, defHash.length, block.length - defHash.length, defHash.length);
+
+ for (int i = 0; i != defHash.length; i++)
+ {
+ block[i] ^= mask[i];
+ }
+
+ return engine.processBlock(block, 0, block.length);
+ }
+
+ /**
+ * @exception InvalidCipherTextException if the decrypted block turns out to
+ * be badly formatted.
+ */
+ public byte[] decodeBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ byte[] data = engine.processBlock(in, inOff, inLen);
+ byte[] block;
+
+ //
+ // as we may have zeros in our leading bytes for the block we produced
+ // on encryption, we need to make sure our decrypted block comes back
+ // the same size.
+ //
+ if (data.length < engine.getOutputBlockSize())
+ {
+ block = new byte[engine.getOutputBlockSize()];
+
+ System.arraycopy(data, 0, block, block.length - data.length, data.length);
+ }
+ else
+ {
+ block = data;
+ }
+
+ if (block.length < (2 * defHash.length) + 1)
+ {
+ throw new InvalidCipherTextException("data too short");
+ }
+
+ //
+ // unmask the seed.
+ //
+ byte[] mask = maskGeneratorFunction1(
+ block, defHash.length, block.length - defHash.length, defHash.length);
+
+ for (int i = 0; i != defHash.length; i++)
+ {
+ block[i] ^= mask[i];
+ }
+
+ //
+ // unmask the message block.
+ //
+ mask = maskGeneratorFunction1(block, 0, defHash.length, block.length - defHash.length);
+
+ for (int i = defHash.length; i != block.length; i++)
+ {
+ block[i] ^= mask[i - defHash.length];
+ }
+
+ //
+ // check the hash of the encoding params.
+ // long check to try to avoid this been a source of a timing attack.
+ //
+ boolean defHashWrong = false;
+
+ for (int i = 0; i != defHash.length; i++)
+ {
+ if (defHash[i] != block[defHash.length + i])
+ {
+ defHashWrong = true;
+ }
+ }
+
+ if (defHashWrong)
+ {
+ throw new InvalidCipherTextException("data hash wrong");
+ }
+
+ //
+ // find the data block
+ //
+ int start;
+
+ for (start = 2 * defHash.length; start != block.length; start++)
+ {
+ if (block[start] != 0)
+ {
+ break;
+ }
+ }
+
+ if (start >= (block.length - 1) || block[start] != 1)
+ {
+ throw new InvalidCipherTextException("data start wrong " + start);
+ }
+
+ start++;
+
+ //
+ // extract the data block
+ //
+ byte[] output = new byte[block.length - start];
+
+ System.arraycopy(block, start, output, 0, output.length);
+
+ return output;
+ }
+
+ /**
+ * int to octet string.
+ */
+ private void ItoOSP(
+ int i,
+ byte[] sp)
+ {
+ sp[0] = (byte)(i >>> 24);
+ sp[1] = (byte)(i >>> 16);
+ sp[2] = (byte)(i >>> 8);
+ sp[3] = (byte)(i >>> 0);
+ }
+
+ /**
+ * mask generator function, as described in PKCS1v2.
+ */
+ private byte[] maskGeneratorFunction1(
+ byte[] Z,
+ int zOff,
+ int zLen,
+ int length)
+ {
+ byte[] mask = new byte[length];
+ byte[] hashBuf = new byte[mgf1Hash.getDigestSize()];
+ byte[] C = new byte[4];
+ int counter = 0;
+
+ mgf1Hash.reset();
+
+ while (counter < (length / hashBuf.length))
+ {
+ ItoOSP(counter, C);
+
+ mgf1Hash.update(Z, zOff, zLen);
+ mgf1Hash.update(C, 0, C.length);
+ mgf1Hash.doFinal(hashBuf, 0);
+
+ System.arraycopy(hashBuf, 0, mask, counter * hashBuf.length, hashBuf.length);
+
+ counter++;
+ }
+
+ if ((counter * hashBuf.length) < length)
+ {
+ ItoOSP(counter, C);
+
+ mgf1Hash.update(Z, zOff, zLen);
+ mgf1Hash.update(C, 0, C.length);
+ mgf1Hash.doFinal(hashBuf, 0);
+
+ System.arraycopy(hashBuf, 0, mask, counter * hashBuf.length, mask.length - (counter * hashBuf.length));
+ }
+
+ return mask;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/encodings/PKCS1Encoding.java b/core/src/main/java/org/spongycastle/crypto/encodings/PKCS1Encoding.java
new file mode 100644
index 00000000..89524494
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/encodings/PKCS1Encoding.java
@@ -0,0 +1,418 @@
+package org.spongycastle.crypto.encodings;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+
+/**
+ * this does your basic PKCS 1 v1.5 padding - whether or not you should be using this
+ * depends on your application - see PKCS1 Version 2 for details.
+ */
+public class PKCS1Encoding
+ implements AsymmetricBlockCipher
+{
+ /**
+ * some providers fail to include the leading zero in PKCS1 encoded blocks. If you need to
+ * work with one of these set the system property org.spongycastle.pkcs1.strict to false.
+ * <p>
+ * The system property is checked during construction of the encoding object, it is set to
+ * true by default.
+ * </p>
+ */
+ public static final String STRICT_LENGTH_ENABLED_PROPERTY = "org.spongycastle.pkcs1.strict";
+
+ private static final int HEADER_LENGTH = 10;
+
+ private SecureRandom random;
+ private AsymmetricBlockCipher engine;
+ private boolean forEncryption;
+ private boolean forPrivateKey;
+ private boolean useStrictLength;
+ private int pLen = -1;
+ private byte[] fallback = null;
+
+ /**
+ * Basic constructor.
+ * @param cipher
+ */
+ public PKCS1Encoding(
+ AsymmetricBlockCipher cipher)
+ {
+ this.engine = cipher;
+ this.useStrictLength = useStrict();
+ }
+
+ /**
+ * Constructor for decryption with a fixed plaintext length.
+ *
+ * @param cipher The cipher to use for cryptographic operation.
+ * @param pLen Length of the expected plaintext.
+ */
+ public PKCS1Encoding(
+ AsymmetricBlockCipher cipher,
+ int pLen)
+ {
+ this.engine = cipher;
+ this.useStrictLength = useStrict();
+ this.pLen = pLen;
+ }
+
+ /**
+ * Constructor for decryption with a fixed plaintext length and a fallback
+ * value that is returned, if the padding is incorrect.
+ *
+ * @param cipher
+ * The cipher to use for cryptographic operation.
+ * @param fallback
+ * The fallback value, we don't to a arraycopy here.
+ */
+ public PKCS1Encoding(
+ AsymmetricBlockCipher cipher,
+ byte[] fallback)
+ {
+ this.engine = cipher;
+ this.useStrictLength = useStrict();
+ this.fallback = fallback;
+ this.pLen = fallback.length;
+ }
+
+
+
+ //
+ // for J2ME compatibility
+ //
+ private boolean useStrict()
+ {
+ // required if security manager has been installed.
+ String strict = (String)AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ return System.getProperty(STRICT_LENGTH_ENABLED_PROPERTY);
+ }
+ });
+
+ return strict == null || strict.equals("true");
+ }
+
+ public AsymmetricBlockCipher getUnderlyingCipher()
+ {
+ return engine;
+ }
+
+ public void init(
+ boolean forEncryption,
+ CipherParameters param)
+ {
+ AsymmetricKeyParameter kParam;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.random = rParam.getRandom();
+ kParam = (AsymmetricKeyParameter)rParam.getParameters();
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ kParam = (AsymmetricKeyParameter)param;
+ }
+
+ engine.init(forEncryption, param);
+
+ this.forPrivateKey = kParam.isPrivate();
+ this.forEncryption = forEncryption;
+ }
+
+ public int getInputBlockSize()
+ {
+ int baseBlockSize = engine.getInputBlockSize();
+
+ if (forEncryption)
+ {
+ return baseBlockSize - HEADER_LENGTH;
+ }
+ else
+ {
+ return baseBlockSize;
+ }
+ }
+
+ public int getOutputBlockSize()
+ {
+ int baseBlockSize = engine.getOutputBlockSize();
+
+ if (forEncryption)
+ {
+ return baseBlockSize;
+ }
+ else
+ {
+ return baseBlockSize - HEADER_LENGTH;
+ }
+ }
+
+ public byte[] processBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ if (forEncryption)
+ {
+ return encodeBlock(in, inOff, inLen);
+ }
+ else
+ {
+ return decodeBlock(in, inOff, inLen);
+ }
+ }
+
+ private byte[] encodeBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ if (inLen > getInputBlockSize())
+ {
+ throw new IllegalArgumentException("input data too large");
+ }
+
+ byte[] block = new byte[engine.getInputBlockSize()];
+
+ if (forPrivateKey)
+ {
+ block[0] = 0x01; // type code 1
+
+ for (int i = 1; i != block.length - inLen - 1; i++)
+ {
+ block[i] = (byte)0xFF;
+ }
+ }
+ else
+ {
+ random.nextBytes(block); // random fill
+
+ block[0] = 0x02; // type code 2
+
+ //
+ // a zero byte marks the end of the padding, so all
+ // the pad bytes must be non-zero.
+ //
+ for (int i = 1; i != block.length - inLen - 1; i++)
+ {
+ while (block[i] == 0)
+ {
+ block[i] = (byte)random.nextInt();
+ }
+ }
+ }
+
+ block[block.length - inLen - 1] = 0x00; // mark the end of the padding
+ System.arraycopy(in, inOff, block, block.length - inLen, inLen);
+
+ return engine.processBlock(block, 0, block.length);
+ }
+
+ /**
+ * Checks if the argument is a correctly PKCS#1.5 encoded Plaintext
+ * for encryption.
+ *
+ * @param encoded The Plaintext.
+ * @param pLen Expected length of the plaintext.
+ * @return Either 0, if the encoding is correct, or -1, if it is incorrect.
+ */
+ private static int checkPkcs1Encoding(byte[] encoded, int pLen) {
+ int correct = 0;
+ /*
+ * Check if the first two bytes are 0 2
+ */
+ correct |= (encoded[0] ^ 2);
+
+ /*
+ * Now the padding check, check for no 0 byte in the padding
+ */
+ int plen = encoded.length - (
+ pLen /* Lenght of the PMS */
+ + 1 /* Final 0-byte before PMS */
+ );
+
+ for (int i = 1; i < plen; i++) {
+ int tmp = encoded[i];
+ tmp |= tmp >> 1;
+ tmp |= tmp >> 2;
+ tmp |= tmp >> 4;
+ correct |= (tmp & 1) - 1;
+ }
+
+ /*
+ * Make sure the padding ends with a 0 byte.
+ */
+ correct |= encoded[encoded.length - (pLen +1)];
+
+ /*
+ * Return 0 or 1, depending on the result.
+ */
+ correct |= correct >> 1;
+ correct |= correct >> 2;
+ correct |= correct >> 4;
+ return ~((correct & 1) - 1);
+ }
+
+
+ /**
+ * Decode PKCS#1.5 encoding, and return a random value if the padding is not correct.
+ *
+ * @param in The encrypted block.
+ * @param inOff Offset in the encrypted block.
+ * @param inLen Length of the encrypted block.
+ * //@param pLen Length of the desired output.
+ * @return The plaintext without padding, or a random value if the padding was incorrect.
+ *
+ * @throws InvalidCipherTextException
+ */
+ private byte[] decodeBlockOrRandom(byte[] in, int inOff, int inLen)
+ throws InvalidCipherTextException
+ {
+ if (!forPrivateKey)
+ {
+ throw new InvalidCipherTextException("sorry, this method is only for decryption, not for signing");
+ }
+
+ byte[] block = engine.processBlock(in, inOff, inLen);
+ byte[] random = null;
+ if (this.fallback == null)
+ {
+ random = new byte[this.pLen];
+ this.random.nextBytes(random);
+ }
+ else
+ {
+ random = fallback;
+ }
+
+ /*
+ * TODO: This is a potential dangerous side channel. However, you can
+ * fix this by changing the RSA engine in a way, that it will always
+ * return blocks of the same length and prepend them with 0 bytes if
+ * needed.
+ */
+ if (block.length < getOutputBlockSize())
+ {
+ throw new InvalidCipherTextException("block truncated");
+ }
+
+ /*
+ * TODO: Potential side channel. Fix it by making the engine always
+ * return blocks of the correct length.
+ */
+ if (useStrictLength && block.length != engine.getOutputBlockSize())
+ {
+ throw new InvalidCipherTextException("block incorrect size");
+ }
+
+ /*
+ * Check the padding.
+ */
+ int correct = PKCS1Encoding.checkPkcs1Encoding(block, this.pLen);
+
+ /*
+ * Now, to a constant time constant memory copy of the decrypted value
+ * or the random value, depending on the validity of the padding.
+ */
+ byte[] result = new byte[this.pLen];
+ for (int i = 0; i < this.pLen; i++)
+ {
+ result[i] = (byte)((block[i + (block.length - pLen)] & (~correct)) | (random[i] & correct));
+ }
+
+ return result;
+ }
+
+ /**
+ * @exception InvalidCipherTextException if the decrypted block is not in PKCS1 format.
+ */
+ private byte[] decodeBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ /*
+ * If the length of the expected plaintext is known, we use a constant-time decryption.
+ * If the decryption fails, we return a random value.
+ */
+ if (this.pLen != -1) {
+ return this.decodeBlockOrRandom(in, inOff, inLen);
+ }
+
+ byte[] block = engine.processBlock(in, inOff, inLen);
+
+ if (block.length < getOutputBlockSize())
+ {
+ throw new InvalidCipherTextException("block truncated");
+ }
+
+ byte type = block[0];
+
+ if (forPrivateKey)
+ {
+ if (type != 2)
+ {
+ throw new InvalidCipherTextException("unknown block type");
+ }
+ }
+ else
+ {
+ if (type != 1)
+ {
+ throw new InvalidCipherTextException("unknown block type");
+ }
+ }
+
+ if (useStrictLength && block.length != engine.getOutputBlockSize())
+ {
+ throw new InvalidCipherTextException("block incorrect size");
+ }
+
+ //
+ // find and extract the message block.
+ //
+ int start;
+
+ for (start = 1; start != block.length; start++)
+ {
+ byte pad = block[start];
+
+ if (pad == 0)
+ {
+ break;
+ }
+ if (type == 1 && pad != (byte)0xff)
+ {
+ throw new InvalidCipherTextException("block padding incorrect");
+ }
+ }
+
+ start++; // data should start at the next byte
+
+ if (start > block.length || start < HEADER_LENGTH)
+ {
+ throw new InvalidCipherTextException("no data in block");
+ }
+
+ byte[] result = new byte[block.length - start];
+
+ System.arraycopy(block, start, result, 0, result.length);
+
+ return result;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/AESEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/AESEngine.java
new file mode 100644
index 00000000..bc7e9176
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/AESEngine.java
@@ -0,0 +1,537 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+
+/**
+ * an implementation of the AES (Rijndael), from FIPS-197.
+ * <p>
+ * For further details see: <a href="http://csrc.nist.gov/encryption/aes/">http://csrc.nist.gov/encryption/aes/</a>.
+ *
+ * This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at
+ * <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
+ *
+ * There are three levels of tradeoff of speed vs memory
+ * Because java has no preprocessor, they are written as three separate classes from which to choose
+ *
+ * The fastest uses 8Kbytes of static tables to precompute round calculations, 4 256 word tables for encryption
+ * and 4 for decryption.
+ *
+ * The middle performance version uses only one 256 word table for each, for a total of 2Kbytes,
+ * adding 12 rotate operations per round to compute the values contained in the other tables from
+ * the contents of the first.
+ *
+ * The slowest version uses no static tables at all and computes the values in each round.
+ * <p>
+ * This file contains the middle performance version with 2Kbytes of static tables for round precomputation.
+ *
+ */
+public class AESEngine
+ implements BlockCipher
+{
+ // The S box
+ private static final byte[] S = {
+ (byte)99, (byte)124, (byte)119, (byte)123, (byte)242, (byte)107, (byte)111, (byte)197,
+ (byte)48, (byte)1, (byte)103, (byte)43, (byte)254, (byte)215, (byte)171, (byte)118,
+ (byte)202, (byte)130, (byte)201, (byte)125, (byte)250, (byte)89, (byte)71, (byte)240,
+ (byte)173, (byte)212, (byte)162, (byte)175, (byte)156, (byte)164, (byte)114, (byte)192,
+ (byte)183, (byte)253, (byte)147, (byte)38, (byte)54, (byte)63, (byte)247, (byte)204,
+ (byte)52, (byte)165, (byte)229, (byte)241, (byte)113, (byte)216, (byte)49, (byte)21,
+ (byte)4, (byte)199, (byte)35, (byte)195, (byte)24, (byte)150, (byte)5, (byte)154,
+ (byte)7, (byte)18, (byte)128, (byte)226, (byte)235, (byte)39, (byte)178, (byte)117,
+ (byte)9, (byte)131, (byte)44, (byte)26, (byte)27, (byte)110, (byte)90, (byte)160,
+ (byte)82, (byte)59, (byte)214, (byte)179, (byte)41, (byte)227, (byte)47, (byte)132,
+ (byte)83, (byte)209, (byte)0, (byte)237, (byte)32, (byte)252, (byte)177, (byte)91,
+ (byte)106, (byte)203, (byte)190, (byte)57, (byte)74, (byte)76, (byte)88, (byte)207,
+ (byte)208, (byte)239, (byte)170, (byte)251, (byte)67, (byte)77, (byte)51, (byte)133,
+ (byte)69, (byte)249, (byte)2, (byte)127, (byte)80, (byte)60, (byte)159, (byte)168,
+ (byte)81, (byte)163, (byte)64, (byte)143, (byte)146, (byte)157, (byte)56, (byte)245,
+ (byte)188, (byte)182, (byte)218, (byte)33, (byte)16, (byte)255, (byte)243, (byte)210,
+ (byte)205, (byte)12, (byte)19, (byte)236, (byte)95, (byte)151, (byte)68, (byte)23,
+ (byte)196, (byte)167, (byte)126, (byte)61, (byte)100, (byte)93, (byte)25, (byte)115,
+ (byte)96, (byte)129, (byte)79, (byte)220, (byte)34, (byte)42, (byte)144, (byte)136,
+ (byte)70, (byte)238, (byte)184, (byte)20, (byte)222, (byte)94, (byte)11, (byte)219,
+ (byte)224, (byte)50, (byte)58, (byte)10, (byte)73, (byte)6, (byte)36, (byte)92,
+ (byte)194, (byte)211, (byte)172, (byte)98, (byte)145, (byte)149, (byte)228, (byte)121,
+ (byte)231, (byte)200, (byte)55, (byte)109, (byte)141, (byte)213, (byte)78, (byte)169,
+ (byte)108, (byte)86, (byte)244, (byte)234, (byte)101, (byte)122, (byte)174, (byte)8,
+ (byte)186, (byte)120, (byte)37, (byte)46, (byte)28, (byte)166, (byte)180, (byte)198,
+ (byte)232, (byte)221, (byte)116, (byte)31, (byte)75, (byte)189, (byte)139, (byte)138,
+ (byte)112, (byte)62, (byte)181, (byte)102, (byte)72, (byte)3, (byte)246, (byte)14,
+ (byte)97, (byte)53, (byte)87, (byte)185, (byte)134, (byte)193, (byte)29, (byte)158,
+ (byte)225, (byte)248, (byte)152, (byte)17, (byte)105, (byte)217, (byte)142, (byte)148,
+ (byte)155, (byte)30, (byte)135, (byte)233, (byte)206, (byte)85, (byte)40, (byte)223,
+ (byte)140, (byte)161, (byte)137, (byte)13, (byte)191, (byte)230, (byte)66, (byte)104,
+ (byte)65, (byte)153, (byte)45, (byte)15, (byte)176, (byte)84, (byte)187, (byte)22,
+ };
+
+ // The inverse S-box
+ private static final byte[] Si = {
+ (byte)82, (byte)9, (byte)106, (byte)213, (byte)48, (byte)54, (byte)165, (byte)56,
+ (byte)191, (byte)64, (byte)163, (byte)158, (byte)129, (byte)243, (byte)215, (byte)251,
+ (byte)124, (byte)227, (byte)57, (byte)130, (byte)155, (byte)47, (byte)255, (byte)135,
+ (byte)52, (byte)142, (byte)67, (byte)68, (byte)196, (byte)222, (byte)233, (byte)203,
+ (byte)84, (byte)123, (byte)148, (byte)50, (byte)166, (byte)194, (byte)35, (byte)61,
+ (byte)238, (byte)76, (byte)149, (byte)11, (byte)66, (byte)250, (byte)195, (byte)78,
+ (byte)8, (byte)46, (byte)161, (byte)102, (byte)40, (byte)217, (byte)36, (byte)178,
+ (byte)118, (byte)91, (byte)162, (byte)73, (byte)109, (byte)139, (byte)209, (byte)37,
+ (byte)114, (byte)248, (byte)246, (byte)100, (byte)134, (byte)104, (byte)152, (byte)22,
+ (byte)212, (byte)164, (byte)92, (byte)204, (byte)93, (byte)101, (byte)182, (byte)146,
+ (byte)108, (byte)112, (byte)72, (byte)80, (byte)253, (byte)237, (byte)185, (byte)218,
+ (byte)94, (byte)21, (byte)70, (byte)87, (byte)167, (byte)141, (byte)157, (byte)132,
+ (byte)144, (byte)216, (byte)171, (byte)0, (byte)140, (byte)188, (byte)211, (byte)10,
+ (byte)247, (byte)228, (byte)88, (byte)5, (byte)184, (byte)179, (byte)69, (byte)6,
+ (byte)208, (byte)44, (byte)30, (byte)143, (byte)202, (byte)63, (byte)15, (byte)2,
+ (byte)193, (byte)175, (byte)189, (byte)3, (byte)1, (byte)19, (byte)138, (byte)107,
+ (byte)58, (byte)145, (byte)17, (byte)65, (byte)79, (byte)103, (byte)220, (byte)234,
+ (byte)151, (byte)242, (byte)207, (byte)206, (byte)240, (byte)180, (byte)230, (byte)115,
+ (byte)150, (byte)172, (byte)116, (byte)34, (byte)231, (byte)173, (byte)53, (byte)133,
+ (byte)226, (byte)249, (byte)55, (byte)232, (byte)28, (byte)117, (byte)223, (byte)110,
+ (byte)71, (byte)241, (byte)26, (byte)113, (byte)29, (byte)41, (byte)197, (byte)137,
+ (byte)111, (byte)183, (byte)98, (byte)14, (byte)170, (byte)24, (byte)190, (byte)27,
+ (byte)252, (byte)86, (byte)62, (byte)75, (byte)198, (byte)210, (byte)121, (byte)32,
+ (byte)154, (byte)219, (byte)192, (byte)254, (byte)120, (byte)205, (byte)90, (byte)244,
+ (byte)31, (byte)221, (byte)168, (byte)51, (byte)136, (byte)7, (byte)199, (byte)49,
+ (byte)177, (byte)18, (byte)16, (byte)89, (byte)39, (byte)128, (byte)236, (byte)95,
+ (byte)96, (byte)81, (byte)127, (byte)169, (byte)25, (byte)181, (byte)74, (byte)13,
+ (byte)45, (byte)229, (byte)122, (byte)159, (byte)147, (byte)201, (byte)156, (byte)239,
+ (byte)160, (byte)224, (byte)59, (byte)77, (byte)174, (byte)42, (byte)245, (byte)176,
+ (byte)200, (byte)235, (byte)187, (byte)60, (byte)131, (byte)83, (byte)153, (byte)97,
+ (byte)23, (byte)43, (byte)4, (byte)126, (byte)186, (byte)119, (byte)214, (byte)38,
+ (byte)225, (byte)105, (byte)20, (byte)99, (byte)85, (byte)33, (byte)12, (byte)125,
+ };
+
+ // vector used in calculating key schedule (powers of x in GF(256))
+ private static final int[] rcon = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
+ 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 };
+
+ // precomputation tables of calculations for rounds
+ private static final int[] T0 =
+ {
+ 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff,
+ 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102,
+ 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d,
+ 0x9a7676ec, 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa,
+ 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, 0xecadad41,
+ 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453,
+ 0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d,
+ 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83,
+ 0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9, 0x937171e2,
+ 0x73d8d8ab, 0x53313162, 0x3f15152a, 0x0c040408, 0x52c7c795,
+ 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0x0f05050a,
+ 0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
+ 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912,
+ 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc,
+ 0xee5a5ab4, 0xfba0a05b, 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7,
+ 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413,
+ 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, 0x60202040,
+ 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d,
+ 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0,
+ 0x4acfcf85, 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed,
+ 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, 0xcf45458a,
+ 0x10f9f9e9, 0x06020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78,
+ 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d, 0xc0404080,
+ 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
+ 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020,
+ 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18,
+ 0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488,
+ 0x3917172e, 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a,
+ 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, 0xa06060c0,
+ 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54,
+ 0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b,
+ 0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad,
+ 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992,
+ 0x0a06060c, 0x6c242448, 0xe45c5cb8, 0x5dc2c29f, 0x6ed3d3bd,
+ 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3,
+ 0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
+ 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8,
+ 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4,
+ 0xe9aeae47, 0x18080810, 0xd5baba6f, 0x887878f0, 0x6f25254a,
+ 0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697,
+ 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96,
+ 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c,
+ 0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x05030306, 0x01f6f6f7,
+ 0x120e0e1c, 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969,
+ 0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9,
+ 0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9,
+ 0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c, 0x92878715,
+ 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
+ 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65,
+ 0x31e6e6d7, 0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929,
+ 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d,
+ 0x3a16162c};
+
+private static final int[] Tinv0 =
+ {
+ 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b,
+ 0xf1459d1f, 0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad,
+ 0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526,
+ 0x8fa362b5, 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d,
+ 0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, 0xe75f8f03,
+ 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458,
+ 0x2969e049, 0x44c8c98e, 0x6a89c275, 0x78798ef4, 0x6b3e5899,
+ 0xdd71b927, 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d,
+ 0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362, 0xe07764b1,
+ 0x84ae6bbb, 0x1ca081fe, 0x942b08f9, 0x58684870, 0x19fd458f,
+ 0x876cde94, 0xb7f87b52, 0x23d373ab, 0xe2024b72, 0x578f1fe3,
+ 0x2aab5566, 0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3,
+ 0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a,
+ 0x92b479a7, 0xf0f207f3, 0xa1e2694e, 0xcdf4da65, 0xd5be0506,
+ 0x1f6234d1, 0x8afea6c4, 0x9d532e34, 0xa055f3a2, 0x32e18a05,
+ 0x75ebf6a4, 0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd,
+ 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, 0xb58d5491,
+ 0x055dc471, 0x6fd40604, 0xff155060, 0x24fb9819, 0x97e9bdd6,
+ 0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7,
+ 0xdbeec879, 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000,
+ 0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, 0xfbff0efd,
+ 0x5638850f, 0x1ed5ae3d, 0x27392d36, 0x64d90f0a, 0x21a65c68,
+ 0xd1545b9b, 0x3a2e3624, 0xb1670a0c, 0x0fe75793, 0xd296eeb4,
+ 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c,
+ 0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 0x0b0d090e,
+ 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, 0x8519f157, 0x4c0775af,
+ 0xbbdd99ee, 0xfd607fa3, 0x9f2601f7, 0xbcf5725c, 0xc53b6644,
+ 0x347efb5b, 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8,
+ 0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684, 0x7d244a85,
+ 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc,
+ 0xec52860d, 0xd0e3c177, 0x6c16b32b, 0x99b970a9, 0xfa489411,
+ 0x2264e947, 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322,
+ 0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, 0xcf81f5a6,
+ 0x28de7aa5, 0x268eb7da, 0xa4bfad3f, 0xe49d3a2c, 0x0d927850,
+ 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890, 0x5ef7392e,
+ 0xf5afc382, 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf,
+ 0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 0x097826cd,
+ 0xf418596e, 0x01b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa,
+ 0x08cfbc21, 0xe6e815ef, 0xd99be7ba, 0xce366f4a, 0xd4099fea,
+ 0xd67cb029, 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235,
+ 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, 0x4a9804f1,
+ 0xf7daec41, 0x0e50cd7f, 0x2ff69117, 0x8dd64d76, 0x4db0ef43,
+ 0x544daacc, 0xdf0496e4, 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1,
+ 0x7f516546, 0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb,
+ 0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d, 0x8c61d79a,
+ 0x7a0ca137, 0x8e14f859, 0x893c13eb, 0xee27a9ce, 0x35c961b7,
+ 0xede51ce1, 0x3cb1477a, 0x59dfd29c, 0x3f73f255, 0x79ce1418,
+ 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478,
+ 0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16,
+ 0x0c25e2bc, 0x8b493c28, 0x41950dff, 0x7101a839, 0xdeb30c08,
+ 0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48,
+ 0x4257b8d0};
+
+ private static int shift(int r, int shift)
+ {
+ return (r >>> shift) | (r << -shift);
+ }
+
+ /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */
+
+ private static final int m1 = 0x80808080;
+ private static final int m2 = 0x7f7f7f7f;
+ private static final int m3 = 0x0000001b;
+
+ private static int FFmulX(int x)
+ {
+ return (((x & m2) << 1) ^ (((x & m1) >>> 7) * m3));
+ }
+
+ /*
+ The following defines provide alternative definitions of FFmulX that might
+ give improved performance if a fast 32-bit multiply is not available.
+
+ private int FFmulX(int x) { int u = x & m1; u |= (u >> 1); return ((x & m2) << 1) ^ ((u >>> 3) | (u >>> 6)); }
+ private static final int m4 = 0x1b1b1b1b;
+ private int FFmulX(int x) { int u = x & m1; return ((x & m2) << 1) ^ ((u - (u >>> 7)) & m4); }
+
+ */
+
+ private static int inv_mcol(int x)
+ {
+ int f2 = FFmulX(x);
+ int f4 = FFmulX(f2);
+ int f8 = FFmulX(f4);
+ int f9 = x ^ f8;
+
+ return f2 ^ f4 ^ f8 ^ shift(f2 ^ f9, 8) ^ shift(f4 ^ f9, 16) ^ shift(f9, 24);
+ }
+
+ private static int subWord(int x)
+ {
+ return (S[x&255]&255 | ((S[(x>>8)&255]&255)<<8) | ((S[(x>>16)&255]&255)<<16) | S[(x>>24)&255]<<24);
+ }
+
+ /**
+ * Calculate the necessary round keys
+ * The number of calculations depends on key size and block size
+ * AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
+ * This code is written assuming those are the only possible values
+ */
+ private int[][] generateWorkingKey(
+ byte[] key,
+ boolean forEncryption)
+ {
+ int KC = key.length / 4; // key length in words
+ int t;
+
+ if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.length))
+ {
+ throw new IllegalArgumentException("Key length not 128/192/256 bits.");
+ }
+
+ ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes
+ int[][] W = new int[ROUNDS+1][4]; // 4 words in a block
+
+ //
+ // copy the key into the round key array
+ //
+
+ t = 0;
+ int i = 0;
+ while (i < key.length)
+ {
+ W[t >> 2][t & 3] = (key[i]&0xff) | ((key[i+1]&0xff) << 8) | ((key[i+2]&0xff) << 16) | (key[i+3] << 24);
+ i+=4;
+ t++;
+ }
+
+ //
+ // while not enough round key material calculated
+ // calculate new values
+ //
+ int k = (ROUNDS + 1) << 2;
+ for (i = KC; (i < k); i++)
+ {
+ int temp = W[(i-1)>>2][(i-1)&3];
+ if ((i % KC) == 0)
+ {
+ temp = subWord(shift(temp, 8)) ^ rcon[(i / KC)-1];
+ }
+ else if ((KC > 6) && ((i % KC) == 4))
+ {
+ temp = subWord(temp);
+ }
+
+ W[i>>2][i&3] = W[(i - KC)>>2][(i-KC)&3] ^ temp;
+ }
+
+ if (!forEncryption)
+ {
+ for (int j = 1; j < ROUNDS; j++)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ W[j][i] = inv_mcol(W[j][i]);
+ }
+ }
+ }
+
+ return W;
+ }
+
+ private int ROUNDS;
+ private int[][] WorkingKey = null;
+ private int C0, C1, C2, C3;
+ private boolean forEncryption;
+
+ private static final int BLOCK_SIZE = 16;
+
+ /**
+ * default constructor - 128 bit block size.
+ */
+ public AESEngine()
+ {
+ }
+
+ /**
+ * initialise an AES cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (params instanceof KeyParameter)
+ {
+ WorkingKey = generateWorkingKey(((KeyParameter)params).getKey(), forEncryption);
+ this.forEncryption = forEncryption;
+ return;
+ }
+
+ throw new IllegalArgumentException("invalid parameter passed to AES init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "AES";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (WorkingKey == null)
+ {
+ throw new IllegalStateException("AES engine not initialised");
+ }
+
+ if ((inOff + (32 / 2)) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + (32 / 2)) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ if (forEncryption)
+ {
+ unpackBlock(in, inOff);
+ encryptBlock(WorkingKey);
+ packBlock(out, outOff);
+ }
+ else
+ {
+ unpackBlock(in, inOff);
+ decryptBlock(WorkingKey);
+ packBlock(out, outOff);
+ }
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+
+ private void unpackBlock(
+ byte[] bytes,
+ int off)
+ {
+ int index = off;
+
+ C0 = (bytes[index++] & 0xff);
+ C0 |= (bytes[index++] & 0xff) << 8;
+ C0 |= (bytes[index++] & 0xff) << 16;
+ C0 |= bytes[index++] << 24;
+
+ C1 = (bytes[index++] & 0xff);
+ C1 |= (bytes[index++] & 0xff) << 8;
+ C1 |= (bytes[index++] & 0xff) << 16;
+ C1 |= bytes[index++] << 24;
+
+ C2 = (bytes[index++] & 0xff);
+ C2 |= (bytes[index++] & 0xff) << 8;
+ C2 |= (bytes[index++] & 0xff) << 16;
+ C2 |= bytes[index++] << 24;
+
+ C3 = (bytes[index++] & 0xff);
+ C3 |= (bytes[index++] & 0xff) << 8;
+ C3 |= (bytes[index++] & 0xff) << 16;
+ C3 |= bytes[index++] << 24;
+ }
+
+ private void packBlock(
+ byte[] bytes,
+ int off)
+ {
+ int index = off;
+
+ bytes[index++] = (byte)C0;
+ bytes[index++] = (byte)(C0 >> 8);
+ bytes[index++] = (byte)(C0 >> 16);
+ bytes[index++] = (byte)(C0 >> 24);
+
+ bytes[index++] = (byte)C1;
+ bytes[index++] = (byte)(C1 >> 8);
+ bytes[index++] = (byte)(C1 >> 16);
+ bytes[index++] = (byte)(C1 >> 24);
+
+ bytes[index++] = (byte)C2;
+ bytes[index++] = (byte)(C2 >> 8);
+ bytes[index++] = (byte)(C2 >> 16);
+ bytes[index++] = (byte)(C2 >> 24);
+
+ bytes[index++] = (byte)C3;
+ bytes[index++] = (byte)(C3 >> 8);
+ bytes[index++] = (byte)(C3 >> 16);
+ bytes[index++] = (byte)(C3 >> 24);
+ }
+
+
+ private void encryptBlock(int[][] KW)
+ {
+ int t0 = this.C0 ^ KW[0][0];
+ int t1 = this.C1 ^ KW[0][1];
+ int t2 = this.C2 ^ KW[0][2];
+
+ int r = 1, r0, r1, r2, r3 = this.C3 ^ KW[0][3];
+ while (r < ROUNDS - 1)
+ {
+ r0 = T0[t0&255] ^ shift(T0[(t1>>8)&255], 24) ^ shift(T0[(t2>>16)&255], 16) ^ shift(T0[(r3>>24)&255], 8) ^ KW[r][0];
+ r1 = T0[t1&255] ^ shift(T0[(t2>>8)&255], 24) ^ shift(T0[(r3>>16)&255], 16) ^ shift(T0[(t0>>24)&255], 8) ^ KW[r][1];
+ r2 = T0[t2&255] ^ shift(T0[(r3>>8)&255], 24) ^ shift(T0[(t0>>16)&255], 16) ^ shift(T0[(t1>>24)&255], 8) ^ KW[r][2];
+ r3 = T0[r3&255] ^ shift(T0[(t0>>8)&255], 24) ^ shift(T0[(t1>>16)&255], 16) ^ shift(T0[(t2>>24)&255], 8) ^ KW[r++][3];
+ t0 = T0[r0&255] ^ shift(T0[(r1>>8)&255], 24) ^ shift(T0[(r2>>16)&255], 16) ^ shift(T0[(r3>>24)&255], 8) ^ KW[r][0];
+ t1 = T0[r1&255] ^ shift(T0[(r2>>8)&255], 24) ^ shift(T0[(r3>>16)&255], 16) ^ shift(T0[(r0>>24)&255], 8) ^ KW[r][1];
+ t2 = T0[r2&255] ^ shift(T0[(r3>>8)&255], 24) ^ shift(T0[(r0>>16)&255], 16) ^ shift(T0[(r1>>24)&255], 8) ^ KW[r][2];
+ r3 = T0[r3&255] ^ shift(T0[(r0>>8)&255], 24) ^ shift(T0[(r1>>16)&255], 16) ^ shift(T0[(r2>>24)&255], 8) ^ KW[r++][3];
+ }
+
+ r0 = T0[t0&255] ^ shift(T0[(t1>>8)&255], 24) ^ shift(T0[(t2>>16)&255], 16) ^ shift(T0[(r3>>24)&255], 8) ^ KW[r][0];
+ r1 = T0[t1&255] ^ shift(T0[(t2>>8)&255], 24) ^ shift(T0[(r3>>16)&255], 16) ^ shift(T0[(t0>>24)&255], 8) ^ KW[r][1];
+ r2 = T0[t2&255] ^ shift(T0[(r3>>8)&255], 24) ^ shift(T0[(t0>>16)&255], 16) ^ shift(T0[(t1>>24)&255], 8) ^ KW[r][2];
+ r3 = T0[r3&255] ^ shift(T0[(t0>>8)&255], 24) ^ shift(T0[(t1>>16)&255], 16) ^ shift(T0[(t2>>24)&255], 8) ^ KW[r++][3];
+
+ // the final round's table is a simple function of S so we don't use a whole other four tables for it
+
+ this.C0 = (S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((S[(r2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24) ^ KW[r][0];
+ this.C1 = (S[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(r0>>24)&255]<<24) ^ KW[r][1];
+ this.C2 = (S[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24) ^ KW[r][2];
+ this.C3 = (S[r3&255]&255) ^ ((S[(r0>>8)&255]&255)<<8) ^ ((S[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24) ^ KW[r][3];
+ }
+
+ private void decryptBlock(int[][] KW)
+ {
+ int t0 = this.C0 ^ KW[ROUNDS][0];
+ int t1 = this.C1 ^ KW[ROUNDS][1];
+ int t2 = this.C2 ^ KW[ROUNDS][2];
+
+ int r = ROUNDS - 1, r0, r1, r2, r3 = this.C3 ^ KW[ROUNDS][3];
+ while (r > 1)
+ {
+ r0 = Tinv0[t0&255] ^ shift(Tinv0[(r3>>8)&255], 24) ^ shift(Tinv0[(t2>>16)&255], 16) ^ shift(Tinv0[(t1>>24)&255], 8) ^ KW[r][0];
+ r1 = Tinv0[t1&255] ^ shift(Tinv0[(t0>>8)&255], 24) ^ shift(Tinv0[(r3>>16)&255], 16) ^ shift(Tinv0[(t2>>24)&255], 8) ^ KW[r][1];
+ r2 = Tinv0[t2&255] ^ shift(Tinv0[(t1>>8)&255], 24) ^ shift(Tinv0[(t0>>16)&255], 16) ^ shift(Tinv0[(r3>>24)&255], 8) ^ KW[r][2];
+ r3 = Tinv0[r3&255] ^ shift(Tinv0[(t2>>8)&255], 24) ^ shift(Tinv0[(t1>>16)&255], 16) ^ shift(Tinv0[(t0>>24)&255], 8) ^ KW[r--][3];
+ t0 = Tinv0[r0&255] ^ shift(Tinv0[(r3>>8)&255], 24) ^ shift(Tinv0[(r2>>16)&255], 16) ^ shift(Tinv0[(r1>>24)&255], 8) ^ KW[r][0];
+ t1 = Tinv0[r1&255] ^ shift(Tinv0[(r0>>8)&255], 24) ^ shift(Tinv0[(r3>>16)&255], 16) ^ shift(Tinv0[(r2>>24)&255], 8) ^ KW[r][1];
+ t2 = Tinv0[r2&255] ^ shift(Tinv0[(r1>>8)&255], 24) ^ shift(Tinv0[(r0>>16)&255], 16) ^ shift(Tinv0[(r3>>24)&255], 8) ^ KW[r][2];
+ r3 = Tinv0[r3&255] ^ shift(Tinv0[(r2>>8)&255], 24) ^ shift(Tinv0[(r1>>16)&255], 16) ^ shift(Tinv0[(r0>>24)&255], 8) ^ KW[r--][3];
+ }
+
+ r0 = Tinv0[t0&255] ^ shift(Tinv0[(r3>>8)&255], 24) ^ shift(Tinv0[(t2>>16)&255], 16) ^ shift(Tinv0[(t1>>24)&255], 8) ^ KW[r][0];
+ r1 = Tinv0[t1&255] ^ shift(Tinv0[(t0>>8)&255], 24) ^ shift(Tinv0[(r3>>16)&255], 16) ^ shift(Tinv0[(t2>>24)&255], 8) ^ KW[r][1];
+ r2 = Tinv0[t2&255] ^ shift(Tinv0[(t1>>8)&255], 24) ^ shift(Tinv0[(t0>>16)&255], 16) ^ shift(Tinv0[(r3>>24)&255], 8) ^ KW[r][2];
+ r3 = Tinv0[r3&255] ^ shift(Tinv0[(t2>>8)&255], 24) ^ shift(Tinv0[(t1>>16)&255], 16) ^ shift(Tinv0[(t0>>24)&255], 8) ^ KW[r][3];
+
+ // the final round's table is a simple function of Si so we don't use a whole other four tables for it
+
+ this.C0 = (Si[r0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24) ^ KW[0][0];
+ this.C1 = (Si[r1&255]&255) ^ ((Si[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(r2>>24)&255]<<24) ^ KW[0][1];
+ this.C2 = (Si[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24) ^ KW[0][2];
+ this.C3 = (Si[r3&255]&255) ^ ((Si[(r2>>8)&255]&255)<<8) ^ ((Si[(r1>>16)&255]&255)<<16) ^ (Si[(r0>>24)&255]<<24) ^ KW[0][3];
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/AESFastEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/AESFastEngine.java
new file mode 100644
index 00000000..4eb705ba
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/AESFastEngine.java
@@ -0,0 +1,928 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Pack;
+
+/**
+ * an implementation of the AES (Rijndael), from FIPS-197.
+ * <p>
+ * For further details see: <a href="http://csrc.nist.gov/encryption/aes/">http://csrc.nist.gov/encryption/aes/</a>.
+ *
+ * This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at
+ * <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
+ *
+ * There are three levels of tradeoff of speed vs memory
+ * Because java has no preprocessor, they are written as three separate classes from which to choose
+ *
+ * The fastest uses 8Kbytes of static tables to precompute round calculations, 4 256 word tables for encryption
+ * and 4 for decryption.
+ *
+ * The middle performance version uses only one 256 word table for each, for a total of 2Kbytes,
+ * adding 12 rotate operations per round to compute the values contained in the other tables from
+ * the contents of the first
+ *
+ * The slowest version uses no static tables at all and computes the values in each round
+ * <p>
+ * This file contains the fast version with 8Kbytes of static tables for round precomputation
+ *
+ */
+public class AESFastEngine
+ implements BlockCipher
+{
+ // The S box
+ private static final byte[] S = {
+ (byte)99, (byte)124, (byte)119, (byte)123, (byte)242, (byte)107, (byte)111, (byte)197,
+ (byte)48, (byte)1, (byte)103, (byte)43, (byte)254, (byte)215, (byte)171, (byte)118,
+ (byte)202, (byte)130, (byte)201, (byte)125, (byte)250, (byte)89, (byte)71, (byte)240,
+ (byte)173, (byte)212, (byte)162, (byte)175, (byte)156, (byte)164, (byte)114, (byte)192,
+ (byte)183, (byte)253, (byte)147, (byte)38, (byte)54, (byte)63, (byte)247, (byte)204,
+ (byte)52, (byte)165, (byte)229, (byte)241, (byte)113, (byte)216, (byte)49, (byte)21,
+ (byte)4, (byte)199, (byte)35, (byte)195, (byte)24, (byte)150, (byte)5, (byte)154,
+ (byte)7, (byte)18, (byte)128, (byte)226, (byte)235, (byte)39, (byte)178, (byte)117,
+ (byte)9, (byte)131, (byte)44, (byte)26, (byte)27, (byte)110, (byte)90, (byte)160,
+ (byte)82, (byte)59, (byte)214, (byte)179, (byte)41, (byte)227, (byte)47, (byte)132,
+ (byte)83, (byte)209, (byte)0, (byte)237, (byte)32, (byte)252, (byte)177, (byte)91,
+ (byte)106, (byte)203, (byte)190, (byte)57, (byte)74, (byte)76, (byte)88, (byte)207,
+ (byte)208, (byte)239, (byte)170, (byte)251, (byte)67, (byte)77, (byte)51, (byte)133,
+ (byte)69, (byte)249, (byte)2, (byte)127, (byte)80, (byte)60, (byte)159, (byte)168,
+ (byte)81, (byte)163, (byte)64, (byte)143, (byte)146, (byte)157, (byte)56, (byte)245,
+ (byte)188, (byte)182, (byte)218, (byte)33, (byte)16, (byte)255, (byte)243, (byte)210,
+ (byte)205, (byte)12, (byte)19, (byte)236, (byte)95, (byte)151, (byte)68, (byte)23,
+ (byte)196, (byte)167, (byte)126, (byte)61, (byte)100, (byte)93, (byte)25, (byte)115,
+ (byte)96, (byte)129, (byte)79, (byte)220, (byte)34, (byte)42, (byte)144, (byte)136,
+ (byte)70, (byte)238, (byte)184, (byte)20, (byte)222, (byte)94, (byte)11, (byte)219,
+ (byte)224, (byte)50, (byte)58, (byte)10, (byte)73, (byte)6, (byte)36, (byte)92,
+ (byte)194, (byte)211, (byte)172, (byte)98, (byte)145, (byte)149, (byte)228, (byte)121,
+ (byte)231, (byte)200, (byte)55, (byte)109, (byte)141, (byte)213, (byte)78, (byte)169,
+ (byte)108, (byte)86, (byte)244, (byte)234, (byte)101, (byte)122, (byte)174, (byte)8,
+ (byte)186, (byte)120, (byte)37, (byte)46, (byte)28, (byte)166, (byte)180, (byte)198,
+ (byte)232, (byte)221, (byte)116, (byte)31, (byte)75, (byte)189, (byte)139, (byte)138,
+ (byte)112, (byte)62, (byte)181, (byte)102, (byte)72, (byte)3, (byte)246, (byte)14,
+ (byte)97, (byte)53, (byte)87, (byte)185, (byte)134, (byte)193, (byte)29, (byte)158,
+ (byte)225, (byte)248, (byte)152, (byte)17, (byte)105, (byte)217, (byte)142, (byte)148,
+ (byte)155, (byte)30, (byte)135, (byte)233, (byte)206, (byte)85, (byte)40, (byte)223,
+ (byte)140, (byte)161, (byte)137, (byte)13, (byte)191, (byte)230, (byte)66, (byte)104,
+ (byte)65, (byte)153, (byte)45, (byte)15, (byte)176, (byte)84, (byte)187, (byte)22,
+ };
+
+ // The inverse S-box
+ private static final byte[] Si = {
+ (byte)82, (byte)9, (byte)106, (byte)213, (byte)48, (byte)54, (byte)165, (byte)56,
+ (byte)191, (byte)64, (byte)163, (byte)158, (byte)129, (byte)243, (byte)215, (byte)251,
+ (byte)124, (byte)227, (byte)57, (byte)130, (byte)155, (byte)47, (byte)255, (byte)135,
+ (byte)52, (byte)142, (byte)67, (byte)68, (byte)196, (byte)222, (byte)233, (byte)203,
+ (byte)84, (byte)123, (byte)148, (byte)50, (byte)166, (byte)194, (byte)35, (byte)61,
+ (byte)238, (byte)76, (byte)149, (byte)11, (byte)66, (byte)250, (byte)195, (byte)78,
+ (byte)8, (byte)46, (byte)161, (byte)102, (byte)40, (byte)217, (byte)36, (byte)178,
+ (byte)118, (byte)91, (byte)162, (byte)73, (byte)109, (byte)139, (byte)209, (byte)37,
+ (byte)114, (byte)248, (byte)246, (byte)100, (byte)134, (byte)104, (byte)152, (byte)22,
+ (byte)212, (byte)164, (byte)92, (byte)204, (byte)93, (byte)101, (byte)182, (byte)146,
+ (byte)108, (byte)112, (byte)72, (byte)80, (byte)253, (byte)237, (byte)185, (byte)218,
+ (byte)94, (byte)21, (byte)70, (byte)87, (byte)167, (byte)141, (byte)157, (byte)132,
+ (byte)144, (byte)216, (byte)171, (byte)0, (byte)140, (byte)188, (byte)211, (byte)10,
+ (byte)247, (byte)228, (byte)88, (byte)5, (byte)184, (byte)179, (byte)69, (byte)6,
+ (byte)208, (byte)44, (byte)30, (byte)143, (byte)202, (byte)63, (byte)15, (byte)2,
+ (byte)193, (byte)175, (byte)189, (byte)3, (byte)1, (byte)19, (byte)138, (byte)107,
+ (byte)58, (byte)145, (byte)17, (byte)65, (byte)79, (byte)103, (byte)220, (byte)234,
+ (byte)151, (byte)242, (byte)207, (byte)206, (byte)240, (byte)180, (byte)230, (byte)115,
+ (byte)150, (byte)172, (byte)116, (byte)34, (byte)231, (byte)173, (byte)53, (byte)133,
+ (byte)226, (byte)249, (byte)55, (byte)232, (byte)28, (byte)117, (byte)223, (byte)110,
+ (byte)71, (byte)241, (byte)26, (byte)113, (byte)29, (byte)41, (byte)197, (byte)137,
+ (byte)111, (byte)183, (byte)98, (byte)14, (byte)170, (byte)24, (byte)190, (byte)27,
+ (byte)252, (byte)86, (byte)62, (byte)75, (byte)198, (byte)210, (byte)121, (byte)32,
+ (byte)154, (byte)219, (byte)192, (byte)254, (byte)120, (byte)205, (byte)90, (byte)244,
+ (byte)31, (byte)221, (byte)168, (byte)51, (byte)136, (byte)7, (byte)199, (byte)49,
+ (byte)177, (byte)18, (byte)16, (byte)89, (byte)39, (byte)128, (byte)236, (byte)95,
+ (byte)96, (byte)81, (byte)127, (byte)169, (byte)25, (byte)181, (byte)74, (byte)13,
+ (byte)45, (byte)229, (byte)122, (byte)159, (byte)147, (byte)201, (byte)156, (byte)239,
+ (byte)160, (byte)224, (byte)59, (byte)77, (byte)174, (byte)42, (byte)245, (byte)176,
+ (byte)200, (byte)235, (byte)187, (byte)60, (byte)131, (byte)83, (byte)153, (byte)97,
+ (byte)23, (byte)43, (byte)4, (byte)126, (byte)186, (byte)119, (byte)214, (byte)38,
+ (byte)225, (byte)105, (byte)20, (byte)99, (byte)85, (byte)33, (byte)12, (byte)125,
+ };
+
+ // vector used in calculating key schedule (powers of x in GF(256))
+ private static final int[] rcon = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
+ 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 };
+
+ // precomputation tables of calculations for rounds
+ private static final int[] T =
+ {
+ // T0
+ 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff,
+ 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102,
+ 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d,
+ 0x9a7676ec, 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa,
+ 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, 0xecadad41,
+ 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453,
+ 0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d,
+ 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83,
+ 0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9, 0x937171e2,
+ 0x73d8d8ab, 0x53313162, 0x3f15152a, 0x0c040408, 0x52c7c795,
+ 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0x0f05050a,
+ 0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
+ 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912,
+ 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc,
+ 0xee5a5ab4, 0xfba0a05b, 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7,
+ 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413,
+ 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, 0x60202040,
+ 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d,
+ 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0,
+ 0x4acfcf85, 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed,
+ 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, 0xcf45458a,
+ 0x10f9f9e9, 0x06020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78,
+ 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d, 0xc0404080,
+ 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
+ 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020,
+ 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18,
+ 0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488,
+ 0x3917172e, 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a,
+ 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, 0xa06060c0,
+ 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54,
+ 0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b,
+ 0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad,
+ 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992,
+ 0x0a06060c, 0x6c242448, 0xe45c5cb8, 0x5dc2c29f, 0x6ed3d3bd,
+ 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3,
+ 0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
+ 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8,
+ 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4,
+ 0xe9aeae47, 0x18080810, 0xd5baba6f, 0x887878f0, 0x6f25254a,
+ 0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697,
+ 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96,
+ 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c,
+ 0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x05030306, 0x01f6f6f7,
+ 0x120e0e1c, 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969,
+ 0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9,
+ 0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9,
+ 0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c, 0x92878715,
+ 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
+ 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65,
+ 0x31e6e6d7, 0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929,
+ 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d,
+ 0x3a16162c,
+
+ // T1
+ 0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, 0xf2f2ff0d,
+ 0x6b6bd6bd, 0x6f6fdeb1, 0xc5c59154, 0x30306050, 0x01010203,
+ 0x6767cea9, 0x2b2b567d, 0xfefee719, 0xd7d7b562, 0xabab4de6,
+ 0x7676ec9a, 0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87,
+ 0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b, 0xadad41ec,
+ 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea, 0x9c9c23bf, 0xa4a453f7,
+ 0x7272e496, 0xc0c09b5b, 0xb7b775c2, 0xfdfde11c, 0x93933dae,
+ 0x26264c6a, 0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f,
+ 0x3434685c, 0xa5a551f4, 0xe5e5d134, 0xf1f1f908, 0x7171e293,
+ 0xd8d8ab73, 0x31316253, 0x15152a3f, 0x0404080c, 0xc7c79552,
+ 0x23234665, 0xc3c39d5e, 0x18183028, 0x969637a1, 0x05050a0f,
+ 0x9a9a2fb5, 0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d,
+ 0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f, 0x0909121b,
+ 0x83831d9e, 0x2c2c5874, 0x1a1a342e, 0x1b1b362d, 0x6e6edcb2,
+ 0x5a5ab4ee, 0xa0a05bfb, 0x5252a4f6, 0x3b3b764d, 0xd6d6b761,
+ 0xb3b37dce, 0x2929527b, 0xe3e3dd3e, 0x2f2f5e71, 0x84841397,
+ 0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c, 0x20204060,
+ 0xfcfce31f, 0xb1b179c8, 0x5b5bb6ed, 0x6a6ad4be, 0xcbcb8d46,
+ 0xbebe67d9, 0x3939724b, 0x4a4a94de, 0x4c4c98d4, 0x5858b0e8,
+ 0xcfcf854a, 0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16,
+ 0x434386c5, 0x4d4d9ad7, 0x33336655, 0x85851194, 0x45458acf,
+ 0xf9f9e910, 0x02020406, 0x7f7ffe81, 0x5050a0f0, 0x3c3c7844,
+ 0x9f9f25ba, 0xa8a84be3, 0x5151a2f3, 0xa3a35dfe, 0x404080c0,
+ 0x8f8f058a, 0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104,
+ 0xbcbc63df, 0xb6b677c1, 0xdadaaf75, 0x21214263, 0x10102030,
+ 0xffffe51a, 0xf3f3fd0e, 0xd2d2bf6d, 0xcdcd814c, 0x0c0c1814,
+ 0x13132635, 0xececc32f, 0x5f5fbee1, 0x979735a2, 0x444488cc,
+ 0x17172e39, 0xc4c49357, 0xa7a755f2, 0x7e7efc82, 0x3d3d7a47,
+ 0x6464c8ac, 0x5d5dbae7, 0x1919322b, 0x7373e695, 0x6060c0a0,
+ 0x81811998, 0x4f4f9ed1, 0xdcdca37f, 0x22224466, 0x2a2a547e,
+ 0x90903bab, 0x88880b83, 0x46468cca, 0xeeeec729, 0xb8b86bd3,
+ 0x1414283c, 0xdedea779, 0x5e5ebce2, 0x0b0b161d, 0xdbdbad76,
+ 0xe0e0db3b, 0x32326456, 0x3a3a744e, 0x0a0a141e, 0x494992db,
+ 0x06060c0a, 0x2424486c, 0x5c5cb8e4, 0xc2c29f5d, 0xd3d3bd6e,
+ 0xacac43ef, 0x6262c4a6, 0x919139a8, 0x959531a4, 0xe4e4d337,
+ 0x7979f28b, 0xe7e7d532, 0xc8c88b43, 0x37376e59, 0x6d6ddab7,
+ 0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0, 0x6c6cd8b4,
+ 0x5656acfa, 0xf4f4f307, 0xeaeacf25, 0x6565caaf, 0x7a7af48e,
+ 0xaeae47e9, 0x08081018, 0xbaba6fd5, 0x7878f088, 0x25254a6f,
+ 0x2e2e5c72, 0x1c1c3824, 0xa6a657f1, 0xb4b473c7, 0xc6c69751,
+ 0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21, 0x4b4b96dd,
+ 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85, 0x7070e090, 0x3e3e7c42,
+ 0xb5b571c4, 0x6666ccaa, 0x484890d8, 0x03030605, 0xf6f6f701,
+ 0x0e0e1c12, 0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0,
+ 0x86861791, 0xc1c19958, 0x1d1d3a27, 0x9e9e27b9, 0xe1e1d938,
+ 0xf8f8eb13, 0x98982bb3, 0x11112233, 0x6969d2bb, 0xd9d9a970,
+ 0x8e8e0789, 0x949433a7, 0x9b9b2db6, 0x1e1e3c22, 0x87871592,
+ 0xe9e9c920, 0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a,
+ 0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17, 0xbfbf65da,
+ 0xe6e6d731, 0x424284c6, 0x6868d0b8, 0x414182c3, 0x999929b0,
+ 0x2d2d5a77, 0x0f0f1e11, 0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6,
+ 0x16162c3a,
+
+ // T2
+ 0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, 0xf2ff0df2,
+ 0x6bd6bd6b, 0x6fdeb16f, 0xc59154c5, 0x30605030, 0x01020301,
+ 0x67cea967, 0x2b567d2b, 0xfee719fe, 0xd7b562d7, 0xab4de6ab,
+ 0x76ec9a76, 0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d,
+ 0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0, 0xad41ecad,
+ 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf, 0x9c23bf9c, 0xa453f7a4,
+ 0x72e49672, 0xc09b5bc0, 0xb775c2b7, 0xfde11cfd, 0x933dae93,
+ 0x264c6a26, 0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc,
+ 0x34685c34, 0xa551f4a5, 0xe5d134e5, 0xf1f908f1, 0x71e29371,
+ 0xd8ab73d8, 0x31625331, 0x152a3f15, 0x04080c04, 0xc79552c7,
+ 0x23466523, 0xc39d5ec3, 0x18302818, 0x9637a196, 0x050a0f05,
+ 0x9a2fb59a, 0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2,
+ 0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75, 0x09121b09,
+ 0x831d9e83, 0x2c58742c, 0x1a342e1a, 0x1b362d1b, 0x6edcb26e,
+ 0x5ab4ee5a, 0xa05bfba0, 0x52a4f652, 0x3b764d3b, 0xd6b761d6,
+ 0xb37dceb3, 0x29527b29, 0xe3dd3ee3, 0x2f5e712f, 0x84139784,
+ 0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced, 0x20406020,
+ 0xfce31ffc, 0xb179c8b1, 0x5bb6ed5b, 0x6ad4be6a, 0xcb8d46cb,
+ 0xbe67d9be, 0x39724b39, 0x4a94de4a, 0x4c98d44c, 0x58b0e858,
+ 0xcf854acf, 0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb,
+ 0x4386c543, 0x4d9ad74d, 0x33665533, 0x85119485, 0x458acf45,
+ 0xf9e910f9, 0x02040602, 0x7ffe817f, 0x50a0f050, 0x3c78443c,
+ 0x9f25ba9f, 0xa84be3a8, 0x51a2f351, 0xa35dfea3, 0x4080c040,
+ 0x8f058a8f, 0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5,
+ 0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, 0x21426321, 0x10203010,
+ 0xffe51aff, 0xf3fd0ef3, 0xd2bf6dd2, 0xcd814ccd, 0x0c18140c,
+ 0x13263513, 0xecc32fec, 0x5fbee15f, 0x9735a297, 0x4488cc44,
+ 0x172e3917, 0xc49357c4, 0xa755f2a7, 0x7efc827e, 0x3d7a473d,
+ 0x64c8ac64, 0x5dbae75d, 0x19322b19, 0x73e69573, 0x60c0a060,
+ 0x81199881, 0x4f9ed14f, 0xdca37fdc, 0x22446622, 0x2a547e2a,
+ 0x903bab90, 0x880b8388, 0x468cca46, 0xeec729ee, 0xb86bd3b8,
+ 0x14283c14, 0xdea779de, 0x5ebce25e, 0x0b161d0b, 0xdbad76db,
+ 0xe0db3be0, 0x32645632, 0x3a744e3a, 0x0a141e0a, 0x4992db49,
+ 0x060c0a06, 0x24486c24, 0x5cb8e45c, 0xc29f5dc2, 0xd3bd6ed3,
+ 0xac43efac, 0x62c4a662, 0x9139a891, 0x9531a495, 0xe4d337e4,
+ 0x79f28b79, 0xe7d532e7, 0xc88b43c8, 0x376e5937, 0x6ddab76d,
+ 0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9, 0x6cd8b46c,
+ 0x56acfa56, 0xf4f307f4, 0xeacf25ea, 0x65caaf65, 0x7af48e7a,
+ 0xae47e9ae, 0x08101808, 0xba6fd5ba, 0x78f08878, 0x254a6f25,
+ 0x2e5c722e, 0x1c38241c, 0xa657f1a6, 0xb473c7b4, 0xc69751c6,
+ 0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f, 0x4b96dd4b,
+ 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a, 0x70e09070, 0x3e7c423e,
+ 0xb571c4b5, 0x66ccaa66, 0x4890d848, 0x03060503, 0xf6f701f6,
+ 0x0e1c120e, 0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9,
+ 0x86179186, 0xc19958c1, 0x1d3a271d, 0x9e27b99e, 0xe1d938e1,
+ 0xf8eb13f8, 0x982bb398, 0x11223311, 0x69d2bb69, 0xd9a970d9,
+ 0x8e07898e, 0x9433a794, 0x9b2db69b, 0x1e3c221e, 0x87159287,
+ 0xe9c920e9, 0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf,
+ 0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d, 0xbf65dabf,
+ 0xe6d731e6, 0x4284c642, 0x68d0b868, 0x4182c341, 0x9929b099,
+ 0x2d5a772d, 0x0f1e110f, 0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb,
+ 0x162c3a16,
+
+ // T3
+ 0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, 0xff0df2f2,
+ 0xd6bd6b6b, 0xdeb16f6f, 0x9154c5c5, 0x60503030, 0x02030101,
+ 0xcea96767, 0x567d2b2b, 0xe719fefe, 0xb562d7d7, 0x4de6abab,
+ 0xec9a7676, 0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d,
+ 0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0, 0x41ecadad,
+ 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf, 0x23bf9c9c, 0x53f7a4a4,
+ 0xe4967272, 0x9b5bc0c0, 0x75c2b7b7, 0xe11cfdfd, 0x3dae9393,
+ 0x4c6a2626, 0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc,
+ 0x685c3434, 0x51f4a5a5, 0xd134e5e5, 0xf908f1f1, 0xe2937171,
+ 0xab73d8d8, 0x62533131, 0x2a3f1515, 0x080c0404, 0x9552c7c7,
+ 0x46652323, 0x9d5ec3c3, 0x30281818, 0x37a19696, 0x0a0f0505,
+ 0x2fb59a9a, 0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2,
+ 0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575, 0x121b0909,
+ 0x1d9e8383, 0x58742c2c, 0x342e1a1a, 0x362d1b1b, 0xdcb26e6e,
+ 0xb4ee5a5a, 0x5bfba0a0, 0xa4f65252, 0x764d3b3b, 0xb761d6d6,
+ 0x7dceb3b3, 0x527b2929, 0xdd3ee3e3, 0x5e712f2f, 0x13978484,
+ 0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded, 0x40602020,
+ 0xe31ffcfc, 0x79c8b1b1, 0xb6ed5b5b, 0xd4be6a6a, 0x8d46cbcb,
+ 0x67d9bebe, 0x724b3939, 0x94de4a4a, 0x98d44c4c, 0xb0e85858,
+ 0x854acfcf, 0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb,
+ 0x86c54343, 0x9ad74d4d, 0x66553333, 0x11948585, 0x8acf4545,
+ 0xe910f9f9, 0x04060202, 0xfe817f7f, 0xa0f05050, 0x78443c3c,
+ 0x25ba9f9f, 0x4be3a8a8, 0xa2f35151, 0x5dfea3a3, 0x80c04040,
+ 0x058a8f8f, 0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5,
+ 0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, 0x42632121, 0x20301010,
+ 0xe51affff, 0xfd0ef3f3, 0xbf6dd2d2, 0x814ccdcd, 0x18140c0c,
+ 0x26351313, 0xc32fecec, 0xbee15f5f, 0x35a29797, 0x88cc4444,
+ 0x2e391717, 0x9357c4c4, 0x55f2a7a7, 0xfc827e7e, 0x7a473d3d,
+ 0xc8ac6464, 0xbae75d5d, 0x322b1919, 0xe6957373, 0xc0a06060,
+ 0x19988181, 0x9ed14f4f, 0xa37fdcdc, 0x44662222, 0x547e2a2a,
+ 0x3bab9090, 0x0b838888, 0x8cca4646, 0xc729eeee, 0x6bd3b8b8,
+ 0x283c1414, 0xa779dede, 0xbce25e5e, 0x161d0b0b, 0xad76dbdb,
+ 0xdb3be0e0, 0x64563232, 0x744e3a3a, 0x141e0a0a, 0x92db4949,
+ 0x0c0a0606, 0x486c2424, 0xb8e45c5c, 0x9f5dc2c2, 0xbd6ed3d3,
+ 0x43efacac, 0xc4a66262, 0x39a89191, 0x31a49595, 0xd337e4e4,
+ 0xf28b7979, 0xd532e7e7, 0x8b43c8c8, 0x6e593737, 0xdab76d6d,
+ 0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9, 0xd8b46c6c,
+ 0xacfa5656, 0xf307f4f4, 0xcf25eaea, 0xcaaf6565, 0xf48e7a7a,
+ 0x47e9aeae, 0x10180808, 0x6fd5baba, 0xf0887878, 0x4a6f2525,
+ 0x5c722e2e, 0x38241c1c, 0x57f1a6a6, 0x73c7b4b4, 0x9751c6c6,
+ 0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f, 0x96dd4b4b,
+ 0x61dcbdbd, 0x0d868b8b, 0x0f858a8a, 0xe0907070, 0x7c423e3e,
+ 0x71c4b5b5, 0xccaa6666, 0x90d84848, 0x06050303, 0xf701f6f6,
+ 0x1c120e0e, 0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9,
+ 0x17918686, 0x9958c1c1, 0x3a271d1d, 0x27b99e9e, 0xd938e1e1,
+ 0xeb13f8f8, 0x2bb39898, 0x22331111, 0xd2bb6969, 0xa970d9d9,
+ 0x07898e8e, 0x33a79494, 0x2db69b9b, 0x3c221e1e, 0x15928787,
+ 0xc920e9e9, 0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf,
+ 0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d, 0x65dabfbf,
+ 0xd731e6e6, 0x84c64242, 0xd0b86868, 0x82c34141, 0x29b09999,
+ 0x5a772d2d, 0x1e110f0f, 0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb,
+ 0x2c3a1616};
+
+ private static final int[] Tinv =
+ {
+ // Tinv0
+ 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b,
+ 0xf1459d1f, 0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad,
+ 0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526,
+ 0x8fa362b5, 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d,
+ 0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, 0xe75f8f03,
+ 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458,
+ 0x2969e049, 0x44c8c98e, 0x6a89c275, 0x78798ef4, 0x6b3e5899,
+ 0xdd71b927, 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d,
+ 0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362, 0xe07764b1,
+ 0x84ae6bbb, 0x1ca081fe, 0x942b08f9, 0x58684870, 0x19fd458f,
+ 0x876cde94, 0xb7f87b52, 0x23d373ab, 0xe2024b72, 0x578f1fe3,
+ 0x2aab5566, 0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3,
+ 0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a,
+ 0x92b479a7, 0xf0f207f3, 0xa1e2694e, 0xcdf4da65, 0xd5be0506,
+ 0x1f6234d1, 0x8afea6c4, 0x9d532e34, 0xa055f3a2, 0x32e18a05,
+ 0x75ebf6a4, 0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd,
+ 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, 0xb58d5491,
+ 0x055dc471, 0x6fd40604, 0xff155060, 0x24fb9819, 0x97e9bdd6,
+ 0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7,
+ 0xdbeec879, 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000,
+ 0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, 0xfbff0efd,
+ 0x5638850f, 0x1ed5ae3d, 0x27392d36, 0x64d90f0a, 0x21a65c68,
+ 0xd1545b9b, 0x3a2e3624, 0xb1670a0c, 0x0fe75793, 0xd296eeb4,
+ 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c,
+ 0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 0x0b0d090e,
+ 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, 0x8519f157, 0x4c0775af,
+ 0xbbdd99ee, 0xfd607fa3, 0x9f2601f7, 0xbcf5725c, 0xc53b6644,
+ 0x347efb5b, 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8,
+ 0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684, 0x7d244a85,
+ 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc,
+ 0xec52860d, 0xd0e3c177, 0x6c16b32b, 0x99b970a9, 0xfa489411,
+ 0x2264e947, 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322,
+ 0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, 0xcf81f5a6,
+ 0x28de7aa5, 0x268eb7da, 0xa4bfad3f, 0xe49d3a2c, 0x0d927850,
+ 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890, 0x5ef7392e,
+ 0xf5afc382, 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf,
+ 0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 0x097826cd,
+ 0xf418596e, 0x01b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa,
+ 0x08cfbc21, 0xe6e815ef, 0xd99be7ba, 0xce366f4a, 0xd4099fea,
+ 0xd67cb029, 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235,
+ 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, 0x4a9804f1,
+ 0xf7daec41, 0x0e50cd7f, 0x2ff69117, 0x8dd64d76, 0x4db0ef43,
+ 0x544daacc, 0xdf0496e4, 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1,
+ 0x7f516546, 0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb,
+ 0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d, 0x8c61d79a,
+ 0x7a0ca137, 0x8e14f859, 0x893c13eb, 0xee27a9ce, 0x35c961b7,
+ 0xede51ce1, 0x3cb1477a, 0x59dfd29c, 0x3f73f255, 0x79ce1418,
+ 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478,
+ 0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16,
+ 0x0c25e2bc, 0x8b493c28, 0x41950dff, 0x7101a839, 0xdeb30c08,
+ 0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48,
+ 0x4257b8d0,
+
+ // Tinv1
+ 0xa7f45150, 0x65417e53, 0xa4171ac3, 0x5e273a96, 0x6bab3bcb,
+ 0x459d1ff1, 0x58faacab, 0x03e34b93, 0xfa302055, 0x6d76adf6,
+ 0x76cc8891, 0x4c02f525, 0xd7e54ffc, 0xcb2ac5d7, 0x44352680,
+ 0xa362b58f, 0x5ab1de49, 0x1bba2567, 0x0eea4598, 0xc0fe5de1,
+ 0x752fc302, 0xf04c8112, 0x97468da3, 0xf9d36bc6, 0x5f8f03e7,
+ 0x9c921595, 0x7a6dbfeb, 0x595295da, 0x83bed42d, 0x217458d3,
+ 0x69e04929, 0xc8c98e44, 0x89c2756a, 0x798ef478, 0x3e58996b,
+ 0x71b927dd, 0x4fe1beb6, 0xad88f017, 0xac20c966, 0x3ace7db4,
+ 0x4adf6318, 0x311ae582, 0x33519760, 0x7f536245, 0x7764b1e0,
+ 0xae6bbb84, 0xa081fe1c, 0x2b08f994, 0x68487058, 0xfd458f19,
+ 0x6cde9487, 0xf87b52b7, 0xd373ab23, 0x024b72e2, 0x8f1fe357,
+ 0xab55662a, 0x28ebb207, 0xc2b52f03, 0x7bc5869a, 0x0837d3a5,
+ 0x872830f2, 0xa5bf23b2, 0x6a0302ba, 0x8216ed5c, 0x1ccf8a2b,
+ 0xb479a792, 0xf207f3f0, 0xe2694ea1, 0xf4da65cd, 0xbe0506d5,
+ 0x6234d11f, 0xfea6c48a, 0x532e349d, 0x55f3a2a0, 0xe18a0532,
+ 0xebf6a475, 0xec830b39, 0xef6040aa, 0x9f715e06, 0x106ebd51,
+ 0x8a213ef9, 0x06dd963d, 0x053eddae, 0xbde64d46, 0x8d5491b5,
+ 0x5dc47105, 0xd406046f, 0x155060ff, 0xfb981924, 0xe9bdd697,
+ 0x434089cc, 0x9ed96777, 0x42e8b0bd, 0x8b890788, 0x5b19e738,
+ 0xeec879db, 0x0a7ca147, 0x0f427ce9, 0x1e84f8c9, 0x00000000,
+ 0x86800983, 0xed2b3248, 0x70111eac, 0x725a6c4e, 0xff0efdfb,
+ 0x38850f56, 0xd5ae3d1e, 0x392d3627, 0xd90f0a64, 0xa65c6821,
+ 0x545b9bd1, 0x2e36243a, 0x670a0cb1, 0xe757930f, 0x96eeb4d2,
+ 0x919b1b9e, 0xc5c0804f, 0x20dc61a2, 0x4b775a69, 0x1a121c16,
+ 0xba93e20a, 0x2aa0c0e5, 0xe0223c43, 0x171b121d, 0x0d090e0b,
+ 0xc78bf2ad, 0xa8b62db9, 0xa91e14c8, 0x19f15785, 0x0775af4c,
+ 0xdd99eebb, 0x607fa3fd, 0x2601f79f, 0xf5725cbc, 0x3b6644c5,
+ 0x7efb5b34, 0x29438b76, 0xc623cbdc, 0xfcedb668, 0xf1e4b863,
+ 0xdc31d7ca, 0x85634210, 0x22971340, 0x11c68420, 0x244a857d,
+ 0x3dbbd2f8, 0x32f9ae11, 0xa129c76d, 0x2f9e1d4b, 0x30b2dcf3,
+ 0x52860dec, 0xe3c177d0, 0x16b32b6c, 0xb970a999, 0x489411fa,
+ 0x64e94722, 0x8cfca8c4, 0x3ff0a01a, 0x2c7d56d8, 0x903322ef,
+ 0x4e4987c7, 0xd138d9c1, 0xa2ca8cfe, 0x0bd49836, 0x81f5a6cf,
+ 0xde7aa528, 0x8eb7da26, 0xbfad3fa4, 0x9d3a2ce4, 0x9278500d,
+ 0xcc5f6a9b, 0x467e5462, 0x138df6c2, 0xb8d890e8, 0xf7392e5e,
+ 0xafc382f5, 0x805d9fbe, 0x93d0697c, 0x2dd56fa9, 0x1225cfb3,
+ 0x99acc83b, 0x7d1810a7, 0x639ce86e, 0xbb3bdb7b, 0x7826cd09,
+ 0x18596ef4, 0xb79aec01, 0x9a4f83a8, 0x6e95e665, 0xe6ffaa7e,
+ 0xcfbc2108, 0xe815efe6, 0x9be7bad9, 0x366f4ace, 0x099fead4,
+ 0x7cb029d6, 0xb2a431af, 0x233f2a31, 0x94a5c630, 0x66a235c0,
+ 0xbc4e7437, 0xca82fca6, 0xd090e0b0, 0xd8a73315, 0x9804f14a,
+ 0xdaec41f7, 0x50cd7f0e, 0xf691172f, 0xd64d768d, 0xb0ef434d,
+ 0x4daacc54, 0x0496e4df, 0xb5d19ee3, 0x886a4c1b, 0x1f2cc1b8,
+ 0x5165467f, 0xea5e9d04, 0x358c015d, 0x7487fa73, 0x410bfb2e,
+ 0x1d67b35a, 0xd2db9252, 0x5610e933, 0x47d66d13, 0x61d79a8c,
+ 0x0ca1377a, 0x14f8598e, 0x3c13eb89, 0x27a9ceee, 0xc961b735,
+ 0xe51ce1ed, 0xb1477a3c, 0xdfd29c59, 0x73f2553f, 0xce141879,
+ 0x37c773bf, 0xcdf753ea, 0xaafd5f5b, 0x6f3ddf14, 0xdb447886,
+ 0xf3afca81, 0xc468b93e, 0x3424382c, 0x40a3c25f, 0xc31d1672,
+ 0x25e2bc0c, 0x493c288b, 0x950dff41, 0x01a83971, 0xb30c08de,
+ 0xe4b4d89c, 0xc1566490, 0x84cb7b61, 0xb632d570, 0x5c6c4874,
+ 0x57b8d042,
+
+ // Tinv2
+ 0xf45150a7, 0x417e5365, 0x171ac3a4, 0x273a965e, 0xab3bcb6b,
+ 0x9d1ff145, 0xfaacab58, 0xe34b9303, 0x302055fa, 0x76adf66d,
+ 0xcc889176, 0x02f5254c, 0xe54ffcd7, 0x2ac5d7cb, 0x35268044,
+ 0x62b58fa3, 0xb1de495a, 0xba25671b, 0xea45980e, 0xfe5de1c0,
+ 0x2fc30275, 0x4c8112f0, 0x468da397, 0xd36bc6f9, 0x8f03e75f,
+ 0x9215959c, 0x6dbfeb7a, 0x5295da59, 0xbed42d83, 0x7458d321,
+ 0xe0492969, 0xc98e44c8, 0xc2756a89, 0x8ef47879, 0x58996b3e,
+ 0xb927dd71, 0xe1beb64f, 0x88f017ad, 0x20c966ac, 0xce7db43a,
+ 0xdf63184a, 0x1ae58231, 0x51976033, 0x5362457f, 0x64b1e077,
+ 0x6bbb84ae, 0x81fe1ca0, 0x08f9942b, 0x48705868, 0x458f19fd,
+ 0xde94876c, 0x7b52b7f8, 0x73ab23d3, 0x4b72e202, 0x1fe3578f,
+ 0x55662aab, 0xebb20728, 0xb52f03c2, 0xc5869a7b, 0x37d3a508,
+ 0x2830f287, 0xbf23b2a5, 0x0302ba6a, 0x16ed5c82, 0xcf8a2b1c,
+ 0x79a792b4, 0x07f3f0f2, 0x694ea1e2, 0xda65cdf4, 0x0506d5be,
+ 0x34d11f62, 0xa6c48afe, 0x2e349d53, 0xf3a2a055, 0x8a0532e1,
+ 0xf6a475eb, 0x830b39ec, 0x6040aaef, 0x715e069f, 0x6ebd5110,
+ 0x213ef98a, 0xdd963d06, 0x3eddae05, 0xe64d46bd, 0x5491b58d,
+ 0xc471055d, 0x06046fd4, 0x5060ff15, 0x981924fb, 0xbdd697e9,
+ 0x4089cc43, 0xd967779e, 0xe8b0bd42, 0x8907888b, 0x19e7385b,
+ 0xc879dbee, 0x7ca1470a, 0x427ce90f, 0x84f8c91e, 0x00000000,
+ 0x80098386, 0x2b3248ed, 0x111eac70, 0x5a6c4e72, 0x0efdfbff,
+ 0x850f5638, 0xae3d1ed5, 0x2d362739, 0x0f0a64d9, 0x5c6821a6,
+ 0x5b9bd154, 0x36243a2e, 0x0a0cb167, 0x57930fe7, 0xeeb4d296,
+ 0x9b1b9e91, 0xc0804fc5, 0xdc61a220, 0x775a694b, 0x121c161a,
+ 0x93e20aba, 0xa0c0e52a, 0x223c43e0, 0x1b121d17, 0x090e0b0d,
+ 0x8bf2adc7, 0xb62db9a8, 0x1e14c8a9, 0xf1578519, 0x75af4c07,
+ 0x99eebbdd, 0x7fa3fd60, 0x01f79f26, 0x725cbcf5, 0x6644c53b,
+ 0xfb5b347e, 0x438b7629, 0x23cbdcc6, 0xedb668fc, 0xe4b863f1,
+ 0x31d7cadc, 0x63421085, 0x97134022, 0xc6842011, 0x4a857d24,
+ 0xbbd2f83d, 0xf9ae1132, 0x29c76da1, 0x9e1d4b2f, 0xb2dcf330,
+ 0x860dec52, 0xc177d0e3, 0xb32b6c16, 0x70a999b9, 0x9411fa48,
+ 0xe9472264, 0xfca8c48c, 0xf0a01a3f, 0x7d56d82c, 0x3322ef90,
+ 0x4987c74e, 0x38d9c1d1, 0xca8cfea2, 0xd498360b, 0xf5a6cf81,
+ 0x7aa528de, 0xb7da268e, 0xad3fa4bf, 0x3a2ce49d, 0x78500d92,
+ 0x5f6a9bcc, 0x7e546246, 0x8df6c213, 0xd890e8b8, 0x392e5ef7,
+ 0xc382f5af, 0x5d9fbe80, 0xd0697c93, 0xd56fa92d, 0x25cfb312,
+ 0xacc83b99, 0x1810a77d, 0x9ce86e63, 0x3bdb7bbb, 0x26cd0978,
+ 0x596ef418, 0x9aec01b7, 0x4f83a89a, 0x95e6656e, 0xffaa7ee6,
+ 0xbc2108cf, 0x15efe6e8, 0xe7bad99b, 0x6f4ace36, 0x9fead409,
+ 0xb029d67c, 0xa431afb2, 0x3f2a3123, 0xa5c63094, 0xa235c066,
+ 0x4e7437bc, 0x82fca6ca, 0x90e0b0d0, 0xa73315d8, 0x04f14a98,
+ 0xec41f7da, 0xcd7f0e50, 0x91172ff6, 0x4d768dd6, 0xef434db0,
+ 0xaacc544d, 0x96e4df04, 0xd19ee3b5, 0x6a4c1b88, 0x2cc1b81f,
+ 0x65467f51, 0x5e9d04ea, 0x8c015d35, 0x87fa7374, 0x0bfb2e41,
+ 0x67b35a1d, 0xdb9252d2, 0x10e93356, 0xd66d1347, 0xd79a8c61,
+ 0xa1377a0c, 0xf8598e14, 0x13eb893c, 0xa9ceee27, 0x61b735c9,
+ 0x1ce1ede5, 0x477a3cb1, 0xd29c59df, 0xf2553f73, 0x141879ce,
+ 0xc773bf37, 0xf753eacd, 0xfd5f5baa, 0x3ddf146f, 0x447886db,
+ 0xafca81f3, 0x68b93ec4, 0x24382c34, 0xa3c25f40, 0x1d1672c3,
+ 0xe2bc0c25, 0x3c288b49, 0x0dff4195, 0xa8397101, 0x0c08deb3,
+ 0xb4d89ce4, 0x566490c1, 0xcb7b6184, 0x32d570b6, 0x6c48745c,
+ 0xb8d04257,
+
+ // Tinv3
+ 0x5150a7f4, 0x7e536541, 0x1ac3a417, 0x3a965e27, 0x3bcb6bab,
+ 0x1ff1459d, 0xacab58fa, 0x4b9303e3, 0x2055fa30, 0xadf66d76,
+ 0x889176cc, 0xf5254c02, 0x4ffcd7e5, 0xc5d7cb2a, 0x26804435,
+ 0xb58fa362, 0xde495ab1, 0x25671bba, 0x45980eea, 0x5de1c0fe,
+ 0xc302752f, 0x8112f04c, 0x8da39746, 0x6bc6f9d3, 0x03e75f8f,
+ 0x15959c92, 0xbfeb7a6d, 0x95da5952, 0xd42d83be, 0x58d32174,
+ 0x492969e0, 0x8e44c8c9, 0x756a89c2, 0xf478798e, 0x996b3e58,
+ 0x27dd71b9, 0xbeb64fe1, 0xf017ad88, 0xc966ac20, 0x7db43ace,
+ 0x63184adf, 0xe582311a, 0x97603351, 0x62457f53, 0xb1e07764,
+ 0xbb84ae6b, 0xfe1ca081, 0xf9942b08, 0x70586848, 0x8f19fd45,
+ 0x94876cde, 0x52b7f87b, 0xab23d373, 0x72e2024b, 0xe3578f1f,
+ 0x662aab55, 0xb20728eb, 0x2f03c2b5, 0x869a7bc5, 0xd3a50837,
+ 0x30f28728, 0x23b2a5bf, 0x02ba6a03, 0xed5c8216, 0x8a2b1ccf,
+ 0xa792b479, 0xf3f0f207, 0x4ea1e269, 0x65cdf4da, 0x06d5be05,
+ 0xd11f6234, 0xc48afea6, 0x349d532e, 0xa2a055f3, 0x0532e18a,
+ 0xa475ebf6, 0x0b39ec83, 0x40aaef60, 0x5e069f71, 0xbd51106e,
+ 0x3ef98a21, 0x963d06dd, 0xddae053e, 0x4d46bde6, 0x91b58d54,
+ 0x71055dc4, 0x046fd406, 0x60ff1550, 0x1924fb98, 0xd697e9bd,
+ 0x89cc4340, 0x67779ed9, 0xb0bd42e8, 0x07888b89, 0xe7385b19,
+ 0x79dbeec8, 0xa1470a7c, 0x7ce90f42, 0xf8c91e84, 0x00000000,
+ 0x09838680, 0x3248ed2b, 0x1eac7011, 0x6c4e725a, 0xfdfbff0e,
+ 0x0f563885, 0x3d1ed5ae, 0x3627392d, 0x0a64d90f, 0x6821a65c,
+ 0x9bd1545b, 0x243a2e36, 0x0cb1670a, 0x930fe757, 0xb4d296ee,
+ 0x1b9e919b, 0x804fc5c0, 0x61a220dc, 0x5a694b77, 0x1c161a12,
+ 0xe20aba93, 0xc0e52aa0, 0x3c43e022, 0x121d171b, 0x0e0b0d09,
+ 0xf2adc78b, 0x2db9a8b6, 0x14c8a91e, 0x578519f1, 0xaf4c0775,
+ 0xeebbdd99, 0xa3fd607f, 0xf79f2601, 0x5cbcf572, 0x44c53b66,
+ 0x5b347efb, 0x8b762943, 0xcbdcc623, 0xb668fced, 0xb863f1e4,
+ 0xd7cadc31, 0x42108563, 0x13402297, 0x842011c6, 0x857d244a,
+ 0xd2f83dbb, 0xae1132f9, 0xc76da129, 0x1d4b2f9e, 0xdcf330b2,
+ 0x0dec5286, 0x77d0e3c1, 0x2b6c16b3, 0xa999b970, 0x11fa4894,
+ 0x472264e9, 0xa8c48cfc, 0xa01a3ff0, 0x56d82c7d, 0x22ef9033,
+ 0x87c74e49, 0xd9c1d138, 0x8cfea2ca, 0x98360bd4, 0xa6cf81f5,
+ 0xa528de7a, 0xda268eb7, 0x3fa4bfad, 0x2ce49d3a, 0x500d9278,
+ 0x6a9bcc5f, 0x5462467e, 0xf6c2138d, 0x90e8b8d8, 0x2e5ef739,
+ 0x82f5afc3, 0x9fbe805d, 0x697c93d0, 0x6fa92dd5, 0xcfb31225,
+ 0xc83b99ac, 0x10a77d18, 0xe86e639c, 0xdb7bbb3b, 0xcd097826,
+ 0x6ef41859, 0xec01b79a, 0x83a89a4f, 0xe6656e95, 0xaa7ee6ff,
+ 0x2108cfbc, 0xefe6e815, 0xbad99be7, 0x4ace366f, 0xead4099f,
+ 0x29d67cb0, 0x31afb2a4, 0x2a31233f, 0xc63094a5, 0x35c066a2,
+ 0x7437bc4e, 0xfca6ca82, 0xe0b0d090, 0x3315d8a7, 0xf14a9804,
+ 0x41f7daec, 0x7f0e50cd, 0x172ff691, 0x768dd64d, 0x434db0ef,
+ 0xcc544daa, 0xe4df0496, 0x9ee3b5d1, 0x4c1b886a, 0xc1b81f2c,
+ 0x467f5165, 0x9d04ea5e, 0x015d358c, 0xfa737487, 0xfb2e410b,
+ 0xb35a1d67, 0x9252d2db, 0xe9335610, 0x6d1347d6, 0x9a8c61d7,
+ 0x377a0ca1, 0x598e14f8, 0xeb893c13, 0xceee27a9, 0xb735c961,
+ 0xe1ede51c, 0x7a3cb147, 0x9c59dfd2, 0x553f73f2, 0x1879ce14,
+ 0x73bf37c7, 0x53eacdf7, 0x5f5baafd, 0xdf146f3d, 0x7886db44,
+ 0xca81f3af, 0xb93ec468, 0x382c3424, 0xc25f40a3, 0x1672c31d,
+ 0xbc0c25e2, 0x288b493c, 0xff41950d, 0x397101a8, 0x08deb30c,
+ 0xd89ce4b4, 0x6490c156, 0x7b6184cb, 0xd570b632, 0x48745c6c,
+ 0xd04257b8};
+
+ private static int shift(int r, int shift)
+ {
+ return (r >>> shift) | (r << -shift);
+ }
+
+ /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */
+
+ private static final int m1 = 0x80808080;
+ private static final int m2 = 0x7f7f7f7f;
+ private static final int m3 = 0x0000001b;
+
+ private static int FFmulX(int x)
+ {
+ return (((x & m2) << 1) ^ (((x & m1) >>> 7) * m3));
+ }
+
+ /*
+ The following defines provide alternative definitions of FFmulX that might
+ give improved performance if a fast 32-bit multiply is not available.
+
+ private int FFmulX(int x) { int u = x & m1; u |= (u >> 1); return ((x & m2) << 1) ^ ((u >>> 3) | (u >>> 6)); }
+ private static final int m4 = 0x1b1b1b1b;
+ private int FFmulX(int x) { int u = x & m1; return ((x & m2) << 1) ^ ((u - (u >>> 7)) & m4); }
+
+ */
+
+ private static int inv_mcol(int x)
+ {
+ int f2 = FFmulX(x);
+ int f4 = FFmulX(f2);
+ int f8 = FFmulX(f4);
+ int f9 = x ^ f8;
+
+ return f2 ^ f4 ^ f8 ^ shift(f2 ^ f9, 8) ^ shift(f4 ^ f9, 16) ^ shift(f9, 24);
+ }
+
+ private static int subWord(int x)
+ {
+ int i0 = x, i1 = x >>> 8, i2 = x >>> 16, i3 = x >>> 24;
+ i0 = S[i0 & 255] & 255; i1 = S[i1 & 255] & 255; i2 = S[i2 & 255] & 255; i3 = S[i3 & 255] & 255;
+ return i0 | i1 << 8 | i2 << 16 | i3 << 24;
+ }
+
+ /**
+ * Calculate the necessary round keys
+ * The number of calculations depends on key size and block size
+ * AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
+ * This code is written assuming those are the only possible values
+ */
+ private int[][] generateWorkingKey(
+ byte[] key,
+ boolean forEncryption)
+ {
+ int KC = key.length / 4; // key length in words
+ int t;
+
+ if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.length))
+ {
+ throw new IllegalArgumentException("Key length not 128/192/256 bits.");
+ }
+
+ ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes
+ int[][] W = new int[ROUNDS+1][4]; // 4 words in a block
+
+ //
+ // copy the key into the round key array
+ //
+
+ t = 0;
+ int i = 0;
+ while (i < key.length)
+ {
+ W[t >> 2][t & 3] = (key[i]&0xff) | ((key[i+1]&0xff) << 8) | ((key[i+2]&0xff) << 16) | (key[i+3] << 24);
+ i+=4;
+ t++;
+ }
+
+ //
+ // while not enough round key material calculated
+ // calculate new values
+ //
+ int k = (ROUNDS + 1) << 2;
+ for (i = KC; (i < k); i++)
+ {
+ int temp = W[(i - 1) >> 2][(i - 1) & 3];
+ if ((i % KC) == 0)
+ {
+ temp = subWord(shift(temp, 8)) ^ rcon[(i / KC) - 1];
+ }
+ else if ((KC > 6) && ((i % KC) == 4))
+ {
+ temp = subWord(temp);
+ }
+
+ W[i >> 2][i & 3] = W[(i - KC) >> 2][(i - KC) & 3] ^ temp;
+ }
+
+ if (!forEncryption)
+ {
+ for (int j = 1; j < ROUNDS; j++)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ W[j][i] = inv_mcol(W[j][i]);
+ }
+ }
+ }
+
+ return W;
+ }
+
+ private int ROUNDS;
+ private int[][] WorkingKey = null;
+ private int C0, C1, C2, C3;
+ private boolean forEncryption;
+
+ private static final int BLOCK_SIZE = 16;
+
+ /**
+ * default constructor - 128 bit block size.
+ */
+ public AESFastEngine()
+ {
+ }
+
+ /**
+ * initialise an AES cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (params instanceof KeyParameter)
+ {
+ WorkingKey = generateWorkingKey(((KeyParameter)params).getKey(), forEncryption);
+ this.forEncryption = forEncryption;
+ return;
+ }
+
+ throw new IllegalArgumentException("invalid parameter passed to AES init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "AES";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (WorkingKey == null)
+ {
+ throw new IllegalStateException("AES engine not initialised");
+ }
+
+ if ((inOff + (32 / 2)) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + (32 / 2)) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ unpackBlock(in, inOff);
+
+ if (forEncryption)
+ {
+ encryptBlock(WorkingKey);
+ }
+ else
+ {
+ decryptBlock(WorkingKey);
+ }
+
+ packBlock(out, outOff);
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+
+ private void unpackBlock(byte[] bytes, int off)
+ {
+ this.C0 = Pack.littleEndianToInt(bytes, off);
+ this.C1 = Pack.littleEndianToInt(bytes, off + 4);
+ this.C2 = Pack.littleEndianToInt(bytes, off + 8);
+ this.C3 = Pack.littleEndianToInt(bytes, off + 12);
+ }
+
+ private void packBlock(byte[] bytes, int off)
+ {
+ Pack.intToLittleEndian(this.C0, bytes, off);
+ Pack.intToLittleEndian(this.C1, bytes, off + 4);
+ Pack.intToLittleEndian(this.C2, bytes, off + 8);
+ Pack.intToLittleEndian(this.C3, bytes, off + 12);
+ }
+
+ private void encryptBlock(int[][] KW)
+ {
+ int t0 = this.C0 ^ KW[0][0];
+ int t1 = this.C1 ^ KW[0][1];
+ int t2 = this.C2 ^ KW[0][2];
+
+ /*
+ * Fast engine has precomputed rotr(T0, 8/16/24) tables T1/T2/T3.
+ *
+ * Placing all precomputes in one array requires offsets additions for 8/16/24 rotations but
+ * avoids additional array range checks on 3 more arrays (which on HotSpot are more
+ * expensive than the offset additions).
+ */
+ int r = 1, r0, r1, r2, r3 = this.C3 ^ KW[0][3];
+ int i0, i1, i2, i3;
+
+ while (r < ROUNDS - 1)
+ {
+ i0 = t0; i1 = t1 >>> 8; i2 = t2 >>> 16; i3 = r3 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r0 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][0];
+
+ i0 = t1; i1 = t2 >>> 8; i2 = r3 >>> 16; i3 = t0 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r1 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][1];
+
+ i0 = t2; i1 = r3 >>> 8; i2 = t0 >>> 16; i3 = t1 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r2 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][2];
+
+ i0 = r3; i1 = t0 >>> 8; i2 = t1 >>> 16; i3 = t2 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r3 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r++][3];
+
+ i0 = r0; i1 = r1 >>> 8; i2 = r2 >>> 16; i3 = r3 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ t0 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][0];
+
+ i0 = r1; i1 = r2 >>> 8; i2 = r3 >>> 16; i3 = r0 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ t1 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][1];
+
+ i0 = r2; i1 = r3 >>> 8; i2 = r0 >>> 16; i3 = r1 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ t2 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][2];
+
+ i0 = r3; i1 = r0 >>> 8; i2 = r1 >>> 16; i3 = r2 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r3 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r++][3];
+ }
+
+ i0 = t0; i1 = t1 >>> 8; i2 = t2 >>> 16; i3 = r3 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r0 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][0];
+
+ i0 = t1; i1 = t2 >>> 8; i2 = r3 >>> 16; i3 = t0 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r1 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][1];
+
+ i0 = t2; i1 = r3 >>> 8; i2 = t0 >>> 16; i3 = t1 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r2 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][2];
+
+ i0 = r3; i1 = t0 >>> 8; i2 = t1 >>> 16; i3 = t2 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r3 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r++][3];
+
+ // the final round's table is a simple function of S so we don't use a whole other four tables for it
+
+ i0 = r0; i1 = r1 >>> 8; i2 = r2 >>> 16; i3 = r3 >>> 24;
+ i0 = S[i0 & 255] & 255; i1 = S[i1 & 255] & 255; i2 = S[i2 & 255] & 255; i3 = S[i3 & 255] & 255;
+ this.C0 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[r][0];
+
+ i0 = r1; i1 = r2 >>> 8; i2 = r3 >>> 16; i3 = r0 >>> 24;
+ i0 = S[i0 & 255] & 255; i1 = S[i1 & 255] & 255; i2 = S[i2 & 255] & 255; i3 = S[i3 & 255] & 255;
+ this.C1 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[r][1];
+
+ i0 = r2; i1 = r3 >>> 8; i2 = r0 >>> 16; i3 = r1 >>> 24;
+ i0 = S[i0 & 255] & 255; i1 = S[i1 & 255] & 255; i2 = S[i2 & 255] & 255; i3 = S[i3 & 255] & 255;
+ this.C2 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[r][2];
+
+ i0 = r3; i1 = r0 >>> 8; i2 = r1 >>> 16; i3 = r2 >>> 24;
+ i0 = S[i0 & 255] & 255; i1 = S[i1 & 255] & 255; i2 = S[i2 & 255] & 255; i3 = S[i3 & 255] & 255;
+ this.C3 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[r][3];
+ }
+
+ private void decryptBlock(int[][] KW)
+ {
+ int t0 = this.C0 ^ KW[ROUNDS][0];
+ int t1 = this.C1 ^ KW[ROUNDS][1];
+ int t2 = this.C2 ^ KW[ROUNDS][2];
+
+ int r = ROUNDS - 1, r0, r1, r2, r3 = this.C3 ^ KW[ROUNDS][3];
+ int i0, i1, i2, i3;
+
+ while (r > 1)
+ {
+ i0 = t0; i1 = r3 >>> 8; i2 = t2 >>> 16; i3 = t1 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r0 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][0];
+
+ i0 = t1; i1 = t0 >>> 8; i2 = r3 >>> 16; i3 = t2 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r1 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][1];
+
+ i0 = t2; i1 = t1 >>> 8; i2 = t0 >>> 16; i3 = r3 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r2 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][2];
+
+ i0 = r3; i1 = t2 >>> 8; i2 = t1 >>> 16; i3 = t0 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r3 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r--][3];
+
+ i0 = r0; i1 = r3 >>> 8; i2 = r2 >>> 16; i3 = r1 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ t0 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][0];
+
+ i0 = r1; i1 = r0 >>> 8; i2 = r3 >>> 16; i3 = r2 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ t1 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][1];
+
+ i0 = r2; i1 = r1 >>> 8; i2 = r0 >>> 16; i3 = r3 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ t2 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][2];
+
+ i0 = r3; i1 = r2 >>> 8; i2 = r1 >>> 16; i3 = r0 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r3 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r--][3];
+ }
+
+ i0 = t0; i1 = r3 >>> 8; i2 = t2 >>> 16; i3 = t1 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r0 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[1][0];
+
+ i0 = t1; i1 = t0 >>> 8; i2 = r3 >>> 16; i3 = t2 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r1 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[1][1];
+
+ i0 = t2; i1 = t1 >>> 8; i2 = t0 >>> 16; i3 = r3 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r2 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[1][2];
+
+ i0 = r3; i1 = t2 >>> 8; i2 = t1 >>> 16; i3 = t0 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r3 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[1][3];
+
+ // the final round's table is a simple function of Si so we don't use a whole other four tables for it
+
+ i0 = r0; i1 = r3 >>> 8; i2 = r2 >>> 16; i3 = r1 >>> 24;
+ i0 = Si[i0 & 255] & 255; i1 = Si[i1 & 255] & 255; i2 = Si[i2 & 255] & 255; i3 = Si[i3 & 255] & 255;
+ this.C0 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[0][0];
+
+ i0 = r1; i1 = r0 >>> 8; i2 = r3 >>> 16; i3 = r2 >>> 24;
+ i0 = Si[i0 & 255] & 255; i1 = Si[i1 & 255] & 255; i2 = Si[i2 & 255] & 255; i3 = Si[i3 & 255] & 255;
+ this.C1 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[0][1];
+
+ i0 = r2; i1 = r1 >>> 8; i2 = r0 >>> 16; i3 = r3 >>> 24;
+ i0 = Si[i0 & 255] & 255; i1 = Si[i1 & 255] & 255; i2 = Si[i2 & 255] & 255; i3 = Si[i3 & 255] & 255;
+ this.C2 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[0][2];
+
+ i0 = r3; i1 = r2 >>> 8; i2 = r1 >>> 16; i3 = r0 >>> 24;
+ i0 = Si[i0 & 255] & 255; i1 = Si[i1 & 255] & 255; i2 = Si[i2 & 255] & 255; i3 = Si[i3 & 255] & 255;
+ this.C3 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[0][3];
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/AESLightEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/AESLightEngine.java
new file mode 100644
index 00000000..07b8e513
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/AESLightEngine.java
@@ -0,0 +1,434 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+
+/**
+ * an implementation of the AES (Rijndael), from FIPS-197.
+ * <p>
+ * For further details see: <a href="http://csrc.nist.gov/encryption/aes/">http://csrc.nist.gov/encryption/aes/</a>.
+ *
+ * This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at
+ * <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
+ *
+ * There are three levels of tradeoff of speed vs memory
+ * Because java has no preprocessor, they are written as three separate classes from which to choose
+ *
+ * The fastest uses 8Kbytes of static tables to precompute round calculations, 4 256 word tables for encryption
+ * and 4 for decryption.
+ *
+ * The middle performance version uses only one 256 word table for each, for a total of 2Kbytes,
+ * adding 12 rotate operations per round to compute the values contained in the other tables from
+ * the contents of the first
+ *
+ * The slowest version uses no static tables at all and computes the values
+ * in each round.
+ * <p>
+ * This file contains the slowest performance version with no static tables
+ * for round precomputation, but it has the smallest foot print.
+ *
+ */
+public class AESLightEngine
+ implements BlockCipher
+{
+ // The S box
+ private static final byte[] S = {
+ (byte)99, (byte)124, (byte)119, (byte)123, (byte)242, (byte)107, (byte)111, (byte)197,
+ (byte)48, (byte)1, (byte)103, (byte)43, (byte)254, (byte)215, (byte)171, (byte)118,
+ (byte)202, (byte)130, (byte)201, (byte)125, (byte)250, (byte)89, (byte)71, (byte)240,
+ (byte)173, (byte)212, (byte)162, (byte)175, (byte)156, (byte)164, (byte)114, (byte)192,
+ (byte)183, (byte)253, (byte)147, (byte)38, (byte)54, (byte)63, (byte)247, (byte)204,
+ (byte)52, (byte)165, (byte)229, (byte)241, (byte)113, (byte)216, (byte)49, (byte)21,
+ (byte)4, (byte)199, (byte)35, (byte)195, (byte)24, (byte)150, (byte)5, (byte)154,
+ (byte)7, (byte)18, (byte)128, (byte)226, (byte)235, (byte)39, (byte)178, (byte)117,
+ (byte)9, (byte)131, (byte)44, (byte)26, (byte)27, (byte)110, (byte)90, (byte)160,
+ (byte)82, (byte)59, (byte)214, (byte)179, (byte)41, (byte)227, (byte)47, (byte)132,
+ (byte)83, (byte)209, (byte)0, (byte)237, (byte)32, (byte)252, (byte)177, (byte)91,
+ (byte)106, (byte)203, (byte)190, (byte)57, (byte)74, (byte)76, (byte)88, (byte)207,
+ (byte)208, (byte)239, (byte)170, (byte)251, (byte)67, (byte)77, (byte)51, (byte)133,
+ (byte)69, (byte)249, (byte)2, (byte)127, (byte)80, (byte)60, (byte)159, (byte)168,
+ (byte)81, (byte)163, (byte)64, (byte)143, (byte)146, (byte)157, (byte)56, (byte)245,
+ (byte)188, (byte)182, (byte)218, (byte)33, (byte)16, (byte)255, (byte)243, (byte)210,
+ (byte)205, (byte)12, (byte)19, (byte)236, (byte)95, (byte)151, (byte)68, (byte)23,
+ (byte)196, (byte)167, (byte)126, (byte)61, (byte)100, (byte)93, (byte)25, (byte)115,
+ (byte)96, (byte)129, (byte)79, (byte)220, (byte)34, (byte)42, (byte)144, (byte)136,
+ (byte)70, (byte)238, (byte)184, (byte)20, (byte)222, (byte)94, (byte)11, (byte)219,
+ (byte)224, (byte)50, (byte)58, (byte)10, (byte)73, (byte)6, (byte)36, (byte)92,
+ (byte)194, (byte)211, (byte)172, (byte)98, (byte)145, (byte)149, (byte)228, (byte)121,
+ (byte)231, (byte)200, (byte)55, (byte)109, (byte)141, (byte)213, (byte)78, (byte)169,
+ (byte)108, (byte)86, (byte)244, (byte)234, (byte)101, (byte)122, (byte)174, (byte)8,
+ (byte)186, (byte)120, (byte)37, (byte)46, (byte)28, (byte)166, (byte)180, (byte)198,
+ (byte)232, (byte)221, (byte)116, (byte)31, (byte)75, (byte)189, (byte)139, (byte)138,
+ (byte)112, (byte)62, (byte)181, (byte)102, (byte)72, (byte)3, (byte)246, (byte)14,
+ (byte)97, (byte)53, (byte)87, (byte)185, (byte)134, (byte)193, (byte)29, (byte)158,
+ (byte)225, (byte)248, (byte)152, (byte)17, (byte)105, (byte)217, (byte)142, (byte)148,
+ (byte)155, (byte)30, (byte)135, (byte)233, (byte)206, (byte)85, (byte)40, (byte)223,
+ (byte)140, (byte)161, (byte)137, (byte)13, (byte)191, (byte)230, (byte)66, (byte)104,
+ (byte)65, (byte)153, (byte)45, (byte)15, (byte)176, (byte)84, (byte)187, (byte)22,
+ };
+
+ // The inverse S-box
+ private static final byte[] Si = {
+ (byte)82, (byte)9, (byte)106, (byte)213, (byte)48, (byte)54, (byte)165, (byte)56,
+ (byte)191, (byte)64, (byte)163, (byte)158, (byte)129, (byte)243, (byte)215, (byte)251,
+ (byte)124, (byte)227, (byte)57, (byte)130, (byte)155, (byte)47, (byte)255, (byte)135,
+ (byte)52, (byte)142, (byte)67, (byte)68, (byte)196, (byte)222, (byte)233, (byte)203,
+ (byte)84, (byte)123, (byte)148, (byte)50, (byte)166, (byte)194, (byte)35, (byte)61,
+ (byte)238, (byte)76, (byte)149, (byte)11, (byte)66, (byte)250, (byte)195, (byte)78,
+ (byte)8, (byte)46, (byte)161, (byte)102, (byte)40, (byte)217, (byte)36, (byte)178,
+ (byte)118, (byte)91, (byte)162, (byte)73, (byte)109, (byte)139, (byte)209, (byte)37,
+ (byte)114, (byte)248, (byte)246, (byte)100, (byte)134, (byte)104, (byte)152, (byte)22,
+ (byte)212, (byte)164, (byte)92, (byte)204, (byte)93, (byte)101, (byte)182, (byte)146,
+ (byte)108, (byte)112, (byte)72, (byte)80, (byte)253, (byte)237, (byte)185, (byte)218,
+ (byte)94, (byte)21, (byte)70, (byte)87, (byte)167, (byte)141, (byte)157, (byte)132,
+ (byte)144, (byte)216, (byte)171, (byte)0, (byte)140, (byte)188, (byte)211, (byte)10,
+ (byte)247, (byte)228, (byte)88, (byte)5, (byte)184, (byte)179, (byte)69, (byte)6,
+ (byte)208, (byte)44, (byte)30, (byte)143, (byte)202, (byte)63, (byte)15, (byte)2,
+ (byte)193, (byte)175, (byte)189, (byte)3, (byte)1, (byte)19, (byte)138, (byte)107,
+ (byte)58, (byte)145, (byte)17, (byte)65, (byte)79, (byte)103, (byte)220, (byte)234,
+ (byte)151, (byte)242, (byte)207, (byte)206, (byte)240, (byte)180, (byte)230, (byte)115,
+ (byte)150, (byte)172, (byte)116, (byte)34, (byte)231, (byte)173, (byte)53, (byte)133,
+ (byte)226, (byte)249, (byte)55, (byte)232, (byte)28, (byte)117, (byte)223, (byte)110,
+ (byte)71, (byte)241, (byte)26, (byte)113, (byte)29, (byte)41, (byte)197, (byte)137,
+ (byte)111, (byte)183, (byte)98, (byte)14, (byte)170, (byte)24, (byte)190, (byte)27,
+ (byte)252, (byte)86, (byte)62, (byte)75, (byte)198, (byte)210, (byte)121, (byte)32,
+ (byte)154, (byte)219, (byte)192, (byte)254, (byte)120, (byte)205, (byte)90, (byte)244,
+ (byte)31, (byte)221, (byte)168, (byte)51, (byte)136, (byte)7, (byte)199, (byte)49,
+ (byte)177, (byte)18, (byte)16, (byte)89, (byte)39, (byte)128, (byte)236, (byte)95,
+ (byte)96, (byte)81, (byte)127, (byte)169, (byte)25, (byte)181, (byte)74, (byte)13,
+ (byte)45, (byte)229, (byte)122, (byte)159, (byte)147, (byte)201, (byte)156, (byte)239,
+ (byte)160, (byte)224, (byte)59, (byte)77, (byte)174, (byte)42, (byte)245, (byte)176,
+ (byte)200, (byte)235, (byte)187, (byte)60, (byte)131, (byte)83, (byte)153, (byte)97,
+ (byte)23, (byte)43, (byte)4, (byte)126, (byte)186, (byte)119, (byte)214, (byte)38,
+ (byte)225, (byte)105, (byte)20, (byte)99, (byte)85, (byte)33, (byte)12, (byte)125,
+ };
+
+ // vector used in calculating key schedule (powers of x in GF(256))
+ private static final int[] rcon = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
+ 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 };
+
+ private static int shift(int r, int shift)
+ {
+ return (r >>> shift) | (r << -shift);
+ }
+
+ /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */
+
+ private static final int m1 = 0x80808080;
+ private static final int m2 = 0x7f7f7f7f;
+ private static final int m3 = 0x0000001b;
+
+ private static int FFmulX(int x)
+ {
+ return (((x & m2) << 1) ^ (((x & m1) >>> 7) * m3));
+ }
+
+ /*
+ The following defines provide alternative definitions of FFmulX that might
+ give improved performance if a fast 32-bit multiply is not available.
+
+ private int FFmulX(int x) { int u = x & m1; u |= (u >> 1); return ((x & m2) << 1) ^ ((u >>> 3) | (u >>> 6)); }
+ private static final int m4 = 0x1b1b1b1b;
+ private int FFmulX(int x) { int u = x & m1; return ((x & m2) << 1) ^ ((u - (u >>> 7)) & m4); }
+
+ */
+
+ private static int mcol(int x)
+ {
+ int f2 = FFmulX(x);
+ return f2 ^ shift(x ^ f2, 8) ^ shift(x, 16) ^ shift(x, 24);
+ }
+
+ private static int inv_mcol(int x)
+ {
+ int f2 = FFmulX(x);
+ int f4 = FFmulX(f2);
+ int f8 = FFmulX(f4);
+ int f9 = x ^ f8;
+
+ return f2 ^ f4 ^ f8 ^ shift(f2 ^ f9, 8) ^ shift(f4 ^ f9, 16) ^ shift(f9, 24);
+ }
+
+
+ private static int subWord(int x)
+ {
+ return (S[x&255]&255 | ((S[(x>>8)&255]&255)<<8) | ((S[(x>>16)&255]&255)<<16) | S[(x>>24)&255]<<24);
+ }
+
+ /**
+ * Calculate the necessary round keys
+ * The number of calculations depends on key size and block size
+ * AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
+ * This code is written assuming those are the only possible values
+ */
+ private int[][] generateWorkingKey(
+ byte[] key,
+ boolean forEncryption)
+ {
+ int KC = key.length / 4; // key length in words
+ int t;
+
+ if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.length))
+ {
+ throw new IllegalArgumentException("Key length not 128/192/256 bits.");
+ }
+
+ ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes
+ int[][] W = new int[ROUNDS+1][4]; // 4 words in a block
+
+ //
+ // copy the key into the round key array
+ //
+
+ t = 0;
+ int i = 0;
+ while (i < key.length)
+ {
+ W[t >> 2][t & 3] = (key[i]&0xff) | ((key[i+1]&0xff) << 8) | ((key[i+2]&0xff) << 16) | (key[i+3] << 24);
+ i+=4;
+ t++;
+ }
+
+ //
+ // while not enough round key material calculated
+ // calculate new values
+ //
+ int k = (ROUNDS + 1) << 2;
+ for (i = KC; (i < k); i++)
+ {
+ int temp = W[(i-1)>>2][(i-1)&3];
+ if ((i % KC) == 0)
+ {
+ temp = subWord(shift(temp, 8)) ^ rcon[(i / KC)-1];
+ }
+ else if ((KC > 6) && ((i % KC) == 4))
+ {
+ temp = subWord(temp);
+ }
+
+ W[i>>2][i&3] = W[(i - KC)>>2][(i-KC)&3] ^ temp;
+ }
+
+ if (!forEncryption)
+ {
+ for (int j = 1; j < ROUNDS; j++)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ W[j][i] = inv_mcol(W[j][i]);
+ }
+ }
+ }
+
+ return W;
+ }
+
+ private int ROUNDS;
+ private int[][] WorkingKey = null;
+ private int C0, C1, C2, C3;
+ private boolean forEncryption;
+
+ private static final int BLOCK_SIZE = 16;
+
+ /**
+ * default constructor - 128 bit block size.
+ */
+ public AESLightEngine()
+ {
+ }
+
+ /**
+ * initialise an AES cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (params instanceof KeyParameter)
+ {
+ WorkingKey = generateWorkingKey(((KeyParameter)params).getKey(), forEncryption);
+ this.forEncryption = forEncryption;
+ return;
+ }
+
+ throw new IllegalArgumentException("invalid parameter passed to AES init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "AES";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (WorkingKey == null)
+ {
+ throw new IllegalStateException("AES engine not initialised");
+ }
+
+ if ((inOff + (32 / 2)) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + (32 / 2)) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ if (forEncryption)
+ {
+ unpackBlock(in, inOff);
+ encryptBlock(WorkingKey);
+ packBlock(out, outOff);
+ }
+ else
+ {
+ unpackBlock(in, inOff);
+ decryptBlock(WorkingKey);
+ packBlock(out, outOff);
+ }
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+
+ private void unpackBlock(
+ byte[] bytes,
+ int off)
+ {
+ int index = off;
+
+ C0 = (bytes[index++] & 0xff);
+ C0 |= (bytes[index++] & 0xff) << 8;
+ C0 |= (bytes[index++] & 0xff) << 16;
+ C0 |= bytes[index++] << 24;
+
+ C1 = (bytes[index++] & 0xff);
+ C1 |= (bytes[index++] & 0xff) << 8;
+ C1 |= (bytes[index++] & 0xff) << 16;
+ C1 |= bytes[index++] << 24;
+
+ C2 = (bytes[index++] & 0xff);
+ C2 |= (bytes[index++] & 0xff) << 8;
+ C2 |= (bytes[index++] & 0xff) << 16;
+ C2 |= bytes[index++] << 24;
+
+ C3 = (bytes[index++] & 0xff);
+ C3 |= (bytes[index++] & 0xff) << 8;
+ C3 |= (bytes[index++] & 0xff) << 16;
+ C3 |= bytes[index++] << 24;
+ }
+
+ private void packBlock(
+ byte[] bytes,
+ int off)
+ {
+ int index = off;
+
+ bytes[index++] = (byte)C0;
+ bytes[index++] = (byte)(C0 >> 8);
+ bytes[index++] = (byte)(C0 >> 16);
+ bytes[index++] = (byte)(C0 >> 24);
+
+ bytes[index++] = (byte)C1;
+ bytes[index++] = (byte)(C1 >> 8);
+ bytes[index++] = (byte)(C1 >> 16);
+ bytes[index++] = (byte)(C1 >> 24);
+
+ bytes[index++] = (byte)C2;
+ bytes[index++] = (byte)(C2 >> 8);
+ bytes[index++] = (byte)(C2 >> 16);
+ bytes[index++] = (byte)(C2 >> 24);
+
+ bytes[index++] = (byte)C3;
+ bytes[index++] = (byte)(C3 >> 8);
+ bytes[index++] = (byte)(C3 >> 16);
+ bytes[index++] = (byte)(C3 >> 24);
+ }
+
+ private void encryptBlock(int[][] KW)
+ {
+ int t0 = this.C0 ^ KW[0][0];
+ int t1 = this.C1 ^ KW[0][1];
+ int t2 = this.C2 ^ KW[0][2];
+
+ int r = 1, r0, r1, r2, r3 = this.C3 ^ KW[0][3];
+ while (r < ROUNDS - 1)
+ {
+ r0 = mcol((S[t0&255]&255) ^ ((S[(t1>>8)&255]&255)<<8) ^ ((S[(t2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24)) ^ KW[r][0];
+ r1 = mcol((S[t1&255]&255) ^ ((S[(t2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(t0>>24)&255]<<24)) ^ KW[r][1];
+ r2 = mcol((S[t2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(t0>>16)&255]&255)<<16) ^ (S[(t1>>24)&255]<<24)) ^ KW[r][2];
+ r3 = mcol((S[r3&255]&255) ^ ((S[(t0>>8)&255]&255)<<8) ^ ((S[(t1>>16)&255]&255)<<16) ^ (S[(t2>>24)&255]<<24)) ^ KW[r++][3];
+ t0 = mcol((S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((S[(r2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24)) ^ KW[r][0];
+ t1 = mcol((S[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(r0>>24)&255]<<24)) ^ KW[r][1];
+ t2 = mcol((S[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24)) ^ KW[r][2];
+ r3 = mcol((S[r3&255]&255) ^ ((S[(r0>>8)&255]&255)<<8) ^ ((S[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24)) ^ KW[r++][3];
+ }
+
+ r0 = mcol((S[t0&255]&255) ^ ((S[(t1>>8)&255]&255)<<8) ^ ((S[(t2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24)) ^ KW[r][0];
+ r1 = mcol((S[t1&255]&255) ^ ((S[(t2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(t0>>24)&255]<<24)) ^ KW[r][1];
+ r2 = mcol((S[t2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(t0>>16)&255]&255)<<16) ^ (S[(t1>>24)&255]<<24)) ^ KW[r][2];
+ r3 = mcol((S[r3&255]&255) ^ ((S[(t0>>8)&255]&255)<<8) ^ ((S[(t1>>16)&255]&255)<<16) ^ (S[(t2>>24)&255]<<24)) ^ KW[r++][3];
+
+ // the final round is a simple function of S
+
+ this.C0 = (S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((S[(r2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24) ^ KW[r][0];
+ this.C1 = (S[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(r0>>24)&255]<<24) ^ KW[r][1];
+ this.C2 = (S[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24) ^ KW[r][2];
+ this.C3 = (S[r3&255]&255) ^ ((S[(r0>>8)&255]&255)<<8) ^ ((S[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24) ^ KW[r][3];
+ }
+
+ private void decryptBlock(int[][] KW)
+ {
+ int t0 = this.C0 ^ KW[ROUNDS][0];
+ int t1 = this.C1 ^ KW[ROUNDS][1];
+ int t2 = this.C2 ^ KW[ROUNDS][2];
+
+ int r = ROUNDS - 1, r0, r1, r2, r3 = this.C3 ^ KW[ROUNDS][3];
+ while (r > 1)
+ {
+ r0 = inv_mcol((Si[t0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(t2>>16)&255]&255)<<16) ^ (Si[(t1>>24)&255]<<24)) ^ KW[r][0];
+ r1 = inv_mcol((Si[t1&255]&255) ^ ((Si[(t0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(t2>>24)&255]<<24)) ^ KW[r][1];
+ r2 = inv_mcol((Si[t2&255]&255) ^ ((Si[(t1>>8)&255]&255)<<8) ^ ((Si[(t0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24)) ^ KW[r][2];
+ r3 = inv_mcol((Si[r3&255]&255) ^ ((Si[(t2>>8)&255]&255)<<8) ^ ((Si[(t1>>16)&255]&255)<<16) ^ (Si[(t0>>24)&255]<<24)) ^ KW[r--][3];
+ t0 = inv_mcol((Si[r0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24)) ^ KW[r][0];
+ t1 = inv_mcol((Si[r1&255]&255) ^ ((Si[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(r2>>24)&255]<<24)) ^ KW[r][1];
+ t2 = inv_mcol((Si[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24)) ^ KW[r][2];
+ r3 = inv_mcol((Si[r3&255]&255) ^ ((Si[(r2>>8)&255]&255)<<8) ^ ((Si[(r1>>16)&255]&255)<<16) ^ (Si[(r0>>24)&255]<<24)) ^ KW[r--][3];
+ }
+
+ r0 = inv_mcol((Si[t0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(t2>>16)&255]&255)<<16) ^ (Si[(t1>>24)&255]<<24)) ^ KW[r][0];
+ r1 = inv_mcol((Si[t1&255]&255) ^ ((Si[(t0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(t2>>24)&255]<<24)) ^ KW[r][1];
+ r2 = inv_mcol((Si[t2&255]&255) ^ ((Si[(t1>>8)&255]&255)<<8) ^ ((Si[(t0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24)) ^ KW[r][2];
+ r3 = inv_mcol((Si[r3&255]&255) ^ ((Si[(t2>>8)&255]&255)<<8) ^ ((Si[(t1>>16)&255]&255)<<16) ^ (Si[(t0>>24)&255]<<24)) ^ KW[r][3];
+
+ // the final round's table is a simple function of Si
+
+ this.C0 = (Si[r0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24) ^ KW[0][0];
+ this.C1 = (Si[r1&255]&255) ^ ((Si[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(r2>>24)&255]<<24) ^ KW[0][1];
+ this.C2 = (Si[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24) ^ KW[0][2];
+ this.C3 = (Si[r3&255]&255) ^ ((Si[(r2>>8)&255]&255)<<8) ^ ((Si[(r1>>16)&255]&255)<<16) ^ (Si[(r0>>24)&255]<<24) ^ KW[0][3];
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/AESWrapEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/AESWrapEngine.java
new file mode 100644
index 00000000..d2977948
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/AESWrapEngine.java
@@ -0,0 +1,16 @@
+package org.spongycastle.crypto.engines;
+
+/**
+ * an implementation of the AES Key Wrapper from the NIST Key Wrap
+ * Specification.
+ * <p>
+ * For further details see: <a href="http://csrc.nist.gov/encryption/kms/key-wrap.pdf">http://csrc.nist.gov/encryption/kms/key-wrap.pdf</a>.
+ */
+public class AESWrapEngine
+ extends RFC3394WrapEngine
+{
+ public AESWrapEngine()
+ {
+ super(new AESEngine());
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/AESWrapPadEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/AESWrapPadEngine.java
new file mode 100644
index 00000000..03170ec6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/AESWrapPadEngine.java
@@ -0,0 +1,10 @@
+package org.spongycastle.crypto.engines;
+
+public class AESWrapPadEngine
+ extends RFC5649WrapEngine
+{
+ public AESWrapPadEngine()
+ {
+ super(new AESEngine());
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/BlowfishEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/BlowfishEngine.java
new file mode 100644
index 00000000..e2f04779
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/BlowfishEngine.java
@@ -0,0 +1,577 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+
+/**
+ * A class that provides Blowfish key encryption operations,
+ * such as encoding data and generating keys.
+ * All the algorithms herein are from Applied Cryptography
+ * and implement a simplified cryptography interface.
+ */
+public final class BlowfishEngine
+implements BlockCipher
+{
+ private final static int[]
+ KP = {
+ 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344,
+ 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89,
+ 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C,
+ 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917,
+ 0x9216D5D9, 0x8979FB1B
+ },
+
+ KS0 = {
+ 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7,
+ 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99,
+ 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16,
+ 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E,
+ 0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE,
+ 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013,
+ 0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF,
+ 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E,
+ 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60,
+ 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440,
+ 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE,
+ 0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A,
+ 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E,
+ 0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677,
+ 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193,
+ 0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032,
+ 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88,
+ 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239,
+ 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E,
+ 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0,
+ 0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3,
+ 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98,
+ 0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88,
+ 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE,
+ 0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6,
+ 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D,
+ 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B,
+ 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7,
+ 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA,
+ 0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463,
+ 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F,
+ 0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09,
+ 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3,
+ 0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB,
+ 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279,
+ 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8,
+ 0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB,
+ 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82,
+ 0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB,
+ 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573,
+ 0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0,
+ 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B,
+ 0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790,
+ 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8,
+ 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4,
+ 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0,
+ 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7,
+ 0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C,
+ 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD,
+ 0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1,
+ 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299,
+ 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9,
+ 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477,
+ 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF,
+ 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49,
+ 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF,
+ 0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA,
+ 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5,
+ 0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41,
+ 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915,
+ 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400,
+ 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915,
+ 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664,
+ 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A
+ },
+
+ KS1 = {
+ 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623,
+ 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266,
+ 0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1,
+ 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E,
+ 0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6,
+ 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1,
+ 0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E,
+ 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1,
+ 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737,
+ 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8,
+ 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF,
+ 0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD,
+ 0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701,
+ 0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7,
+ 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41,
+ 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331,
+ 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF,
+ 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF,
+ 0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E,
+ 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87,
+ 0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C,
+ 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2,
+ 0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16,
+ 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD,
+ 0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B,
+ 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509,
+ 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E,
+ 0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3,
+ 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F,
+ 0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A,
+ 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4,
+ 0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960,
+ 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66,
+ 0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28,
+ 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802,
+ 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84,
+ 0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510,
+ 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF,
+ 0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14,
+ 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E,
+ 0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50,
+ 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7,
+ 0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8,
+ 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281,
+ 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99,
+ 0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696,
+ 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128,
+ 0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73,
+ 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0,
+ 0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0,
+ 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105,
+ 0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250,
+ 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3,
+ 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285,
+ 0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00,
+ 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061,
+ 0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB,
+ 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E,
+ 0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735,
+ 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC,
+ 0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9,
+ 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340,
+ 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20,
+ 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7
+ },
+
+ KS2 = {
+ 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934,
+ 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068,
+ 0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF,
+ 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840,
+ 0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45,
+ 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504,
+ 0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A,
+ 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB,
+ 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE,
+ 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6,
+ 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42,
+ 0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B,
+ 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2,
+ 0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB,
+ 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527,
+ 0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B,
+ 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33,
+ 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C,
+ 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3,
+ 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC,
+ 0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17,
+ 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564,
+ 0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B,
+ 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115,
+ 0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922,
+ 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728,
+ 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0,
+ 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E,
+ 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37,
+ 0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D,
+ 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804,
+ 0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B,
+ 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3,
+ 0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB,
+ 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D,
+ 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C,
+ 0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350,
+ 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9,
+ 0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A,
+ 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE,
+ 0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D,
+ 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC,
+ 0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F,
+ 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61,
+ 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2,
+ 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9,
+ 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2,
+ 0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C,
+ 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E,
+ 0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633,
+ 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10,
+ 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169,
+ 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52,
+ 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027,
+ 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5,
+ 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62,
+ 0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634,
+ 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76,
+ 0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24,
+ 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC,
+ 0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4,
+ 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C,
+ 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837,
+ 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0
+ },
+
+ KS3 = {
+ 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B,
+ 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE,
+ 0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B,
+ 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4,
+ 0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8,
+ 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6,
+ 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304,
+ 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22,
+ 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4,
+ 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6,
+ 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9,
+ 0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59,
+ 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593,
+ 0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51,
+ 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28,
+ 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C,
+ 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B,
+ 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28,
+ 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C,
+ 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD,
+ 0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A,
+ 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319,
+ 0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB,
+ 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F,
+ 0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991,
+ 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32,
+ 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680,
+ 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166,
+ 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE,
+ 0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB,
+ 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5,
+ 0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47,
+ 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370,
+ 0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D,
+ 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84,
+ 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048,
+ 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8,
+ 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD,
+ 0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9,
+ 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7,
+ 0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38,
+ 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F,
+ 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C,
+ 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525,
+ 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1,
+ 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442,
+ 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964,
+ 0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E,
+ 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8,
+ 0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D,
+ 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F,
+ 0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299,
+ 0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02,
+ 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC,
+ 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614,
+ 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A,
+ 0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6,
+ 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B,
+ 0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0,
+ 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060,
+ 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E,
+ 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9,
+ 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F,
+ 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6
+ };
+
+ //====================================
+ // Useful constants
+ //====================================
+
+ private static final int ROUNDS = 16;
+ private static final int BLOCK_SIZE = 8; // bytes = 64 bits
+ private static final int SBOX_SK = 256;
+ private static final int P_SZ = ROUNDS+2;
+
+ private final int[] S0, S1, S2, S3; // the s-boxes
+ private final int[] P; // the p-array
+
+ private boolean encrypting = false;
+
+ private byte[] workingKey = null;
+
+ public BlowfishEngine()
+ {
+ S0 = new int[SBOX_SK];
+ S1 = new int[SBOX_SK];
+ S2 = new int[SBOX_SK];
+ S3 = new int[SBOX_SK];
+ P = new int[P_SZ];
+ }
+
+ /**
+ * initialise a Blowfish cipher.
+ *
+ * @param encrypting whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ {
+ if (params instanceof KeyParameter)
+ {
+ this.encrypting = encrypting;
+ this.workingKey = ((KeyParameter)params).getKey();
+ setKey(this.workingKey);
+
+ return;
+ }
+
+ throw new IllegalArgumentException("invalid parameter passed to Blowfish init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Blowfish";
+ }
+
+ public final int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (workingKey == null)
+ {
+ throw new IllegalStateException("Blowfish not initialised");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ if (encrypting)
+ {
+ encryptBlock(in, inOff, out, outOff);
+ }
+ else
+ {
+ decryptBlock(in, inOff, out, outOff);
+ }
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ //==================================
+ // Private Implementation
+ //==================================
+
+ private int F(int x)
+ {
+ return (((S0[(x >>> 24)] + S1[(x >>> 16) & 0xff])
+ ^ S2[(x >>> 8) & 0xff]) + S3[x & 0xff]);
+ }
+
+ /**
+ * apply the encryption cycle to each value pair in the table.
+ */
+ private void processTable(
+ int xl,
+ int xr,
+ int[] table)
+ {
+ int size = table.length;
+
+ for (int s = 0; s < size; s += 2)
+ {
+ xl ^= P[0];
+
+ for (int i = 1; i < ROUNDS; i += 2)
+ {
+ xr ^= F(xl) ^ P[i];
+ xl ^= F(xr) ^ P[i + 1];
+ }
+
+ xr ^= P[ROUNDS + 1];
+
+ table[s] = xr;
+ table[s + 1] = xl;
+
+ xr = xl; // end of cycle swap
+ xl = table[s];
+ }
+ }
+
+ private void setKey(byte[] key)
+ {
+ /*
+ * - comments are from _Applied Crypto_, Schneier, p338
+ * please be careful comparing the two, AC numbers the
+ * arrays from 1, the enclosed code from 0.
+ *
+ * (1)
+ * Initialise the S-boxes and the P-array, with a fixed string
+ * This string contains the hexadecimal digits of pi (3.141...)
+ */
+ System.arraycopy(KS0, 0, S0, 0, SBOX_SK);
+ System.arraycopy(KS1, 0, S1, 0, SBOX_SK);
+ System.arraycopy(KS2, 0, S2, 0, SBOX_SK);
+ System.arraycopy(KS3, 0, S3, 0, SBOX_SK);
+
+ System.arraycopy(KP, 0, P, 0, P_SZ);
+
+ /*
+ * (2)
+ * Now, XOR P[0] with the first 32 bits of the key, XOR P[1] with the
+ * second 32-bits of the key, and so on for all bits of the key
+ * (up to P[17]). Repeatedly cycle through the key bits until the
+ * entire P-array has been XOR-ed with the key bits
+ */
+ int keyLength = key.length;
+ int keyIndex = 0;
+
+ for (int i=0; i < P_SZ; i++)
+ {
+ // get the 32 bits of the key, in 4 * 8 bit chunks
+ int data = 0x0000000;
+ for (int j=0; j < 4; j++)
+ {
+ // create a 32 bit block
+ data = (data << 8) | (key[keyIndex++] & 0xff);
+
+ // wrap when we get to the end of the key
+ if (keyIndex >= keyLength)
+ {
+ keyIndex = 0;
+ }
+ }
+ // XOR the newly created 32 bit chunk onto the P-array
+ P[i] ^= data;
+ }
+
+ /*
+ * (3)
+ * Encrypt the all-zero string with the Blowfish algorithm, using
+ * the subkeys described in (1) and (2)
+ *
+ * (4)
+ * Replace P1 and P2 with the output of step (3)
+ *
+ * (5)
+ * Encrypt the output of step(3) using the Blowfish algorithm,
+ * with the modified subkeys.
+ *
+ * (6)
+ * Replace P3 and P4 with the output of step (5)
+ *
+ * (7)
+ * Continue the process, replacing all elements of the P-array
+ * and then all four S-boxes in order, with the output of the
+ * continuously changing Blowfish algorithm
+ */
+
+ processTable(0, 0, P);
+ processTable(P[P_SZ - 2], P[P_SZ - 1], S0);
+ processTable(S0[SBOX_SK - 2], S0[SBOX_SK - 1], S1);
+ processTable(S1[SBOX_SK - 2], S1[SBOX_SK - 1], S2);
+ processTable(S2[SBOX_SK - 2], S2[SBOX_SK - 1], S3);
+ }
+
+ /**
+ * Encrypt the given input starting at the given offset and place
+ * the result in the provided buffer starting at the given offset.
+ * The input will be an exact multiple of our blocksize.
+ */
+ private void encryptBlock(
+ byte[] src,
+ int srcIndex,
+ byte[] dst,
+ int dstIndex)
+ {
+ int xl = BytesTo32bits(src, srcIndex);
+ int xr = BytesTo32bits(src, srcIndex+4);
+
+ xl ^= P[0];
+
+ for (int i = 1; i < ROUNDS; i += 2)
+ {
+ xr ^= F(xl) ^ P[i];
+ xl ^= F(xr) ^ P[i + 1];
+ }
+
+ xr ^= P[ROUNDS + 1];
+
+ Bits32ToBytes(xr, dst, dstIndex);
+ Bits32ToBytes(xl, dst, dstIndex + 4);
+ }
+
+ /**
+ * Decrypt the given input starting at the given offset and place
+ * the result in the provided buffer starting at the given offset.
+ * The input will be an exact multiple of our blocksize.
+ */
+ private void decryptBlock(
+ byte[] src,
+ int srcIndex,
+ byte[] dst,
+ int dstIndex)
+ {
+ int xl = BytesTo32bits(src, srcIndex);
+ int xr = BytesTo32bits(src, srcIndex + 4);
+
+ xl ^= P[ROUNDS + 1];
+
+ for (int i = ROUNDS; i > 0 ; i -= 2)
+ {
+ xr ^= F(xl) ^ P[i];
+ xl ^= F(xr) ^ P[i - 1];
+ }
+
+ xr ^= P[0];
+
+ Bits32ToBytes(xr, dst, dstIndex);
+ Bits32ToBytes(xl, dst, dstIndex+4);
+ }
+
+ private int BytesTo32bits(byte[] b, int i)
+ {
+ return ((b[i] & 0xff) << 24) |
+ ((b[i+1] & 0xff) << 16) |
+ ((b[i+2] & 0xff) << 8) |
+ ((b[i+3] & 0xff));
+ }
+
+ private void Bits32ToBytes(int in, byte[] b, int offset)
+ {
+ b[offset + 3] = (byte)in;
+ b[offset + 2] = (byte)(in >> 8);
+ b[offset + 1] = (byte)(in >> 16);
+ b[offset] = (byte)(in >> 24);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/CAST5Engine.java b/core/src/main/java/org/spongycastle/crypto/engines/CAST5Engine.java
new file mode 100644
index 00000000..7b51fa48
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/CAST5Engine.java
@@ -0,0 +1,831 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+
+/**
+ * A class that provides CAST key encryption operations,
+ * such as encoding data and generating keys.
+ *
+ * All the algorithms herein are from the Internet RFC's
+ *
+ * RFC2144 - CAST5 (64bit block, 40-128bit key)
+ * RFC2612 - CAST6 (128bit block, 128-256bit key)
+ *
+ * and implement a simplified cryptography interface.
+ */
+public class CAST5Engine
+ implements BlockCipher
+{
+ protected final static int M32 = 0xffffffff;
+
+ protected final static int[]
+ S1 = {
+0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
+0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
+0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
+0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
+0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
+0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
+0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
+0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
+0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
+0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
+0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
+0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
+0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
+0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
+0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
+0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
+0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
+0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
+0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
+0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
+0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
+0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
+0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
+0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
+0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
+0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
+0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
+0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
+0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
+0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
+0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
+0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf
+ },
+ S2 = {
+0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
+0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
+0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
+0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
+0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
+0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
+0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
+0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
+0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
+0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
+0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
+0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
+0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
+0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
+0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
+0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
+0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
+0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
+0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
+0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
+0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
+0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
+0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
+0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
+0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
+0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
+0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
+0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
+0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
+0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
+0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
+0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1
+ },
+ S3 = {
+0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
+0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
+0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
+0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
+0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
+0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
+0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
+0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
+0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
+0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
+0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
+0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
+0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
+0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
+0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
+0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
+0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
+0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
+0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
+0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
+0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
+0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
+0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
+0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
+0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
+0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
+0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
+0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
+0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
+0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
+0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
+0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783
+ },
+ S4 = {
+0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
+0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
+0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
+0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
+0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
+0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
+0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
+0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
+0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
+0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
+0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
+0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
+0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
+0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
+0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
+0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
+0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
+0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
+0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
+0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
+0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
+0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
+0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
+0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
+0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
+0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
+0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
+0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
+0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
+0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
+0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
+0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2
+ },
+ S5 = {
+0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
+0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
+0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
+0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
+0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
+0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
+0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
+0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
+0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
+0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
+0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
+0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
+0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
+0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
+0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
+0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
+0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
+0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
+0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
+0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
+0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
+0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
+0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
+0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
+0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
+0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
+0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
+0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
+0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
+0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
+0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
+0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4
+ },
+ S6 = {
+0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
+0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
+0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
+0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
+0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
+0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
+0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
+0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
+0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
+0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
+0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
+0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
+0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
+0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
+0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
+0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
+0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
+0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
+0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
+0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
+0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
+0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
+0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
+0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
+0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
+0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
+0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
+0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
+0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
+0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
+0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
+0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f
+ },
+ S7 = {
+0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
+0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
+0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
+0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
+0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
+0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
+0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
+0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
+0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
+0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
+0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
+0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
+0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
+0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
+0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
+0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
+0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
+0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
+0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
+0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
+0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
+0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
+0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
+0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
+0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
+0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
+0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
+0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
+0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
+0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
+0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
+0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3
+ },
+ S8 = {
+0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
+0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
+0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
+0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
+0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
+0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
+0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
+0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
+0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
+0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
+0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
+0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
+0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
+0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
+0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
+0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
+0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
+0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
+0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
+0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
+0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
+0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
+0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
+0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
+0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
+0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
+0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
+0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
+0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
+0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
+0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
+0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e
+ };
+
+ //====================================
+ // Useful constants
+ //====================================
+
+ protected static final int MAX_ROUNDS = 16;
+ protected static final int RED_ROUNDS = 12;
+
+ protected static final int BLOCK_SIZE = 8; // bytes = 64 bits
+
+ protected int _Kr[] = new int[17]; // the rotating round key
+ protected int _Km[] = new int[17]; // the masking round key
+
+ private boolean _encrypting = false;
+
+ private byte[] _workingKey = null;
+ private int _rounds = MAX_ROUNDS;
+
+ public CAST5Engine()
+ {
+ }
+
+ /**
+ * initialise a CAST cipher.
+ *
+ * @param encrypting whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ {
+ if (params instanceof KeyParameter)
+ {
+ _encrypting = encrypting;
+ _workingKey = ((KeyParameter)params).getKey();
+
+ setKey(_workingKey);
+
+ return;
+ }
+
+ throw new IllegalArgumentException("Invalid parameter passed to "+getAlgorithmName()+" init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "CAST5";
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (_workingKey == null)
+ {
+ throw new IllegalStateException(getAlgorithmName()+" not initialised");
+ }
+
+ int blockSize = getBlockSize();
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("Input buffer too short");
+ }
+
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new OutputLengthException("Output buffer too short");
+ }
+
+ if (_encrypting)
+ {
+ return encryptBlock(in, inOff, out, outOff);
+ }
+ else
+ {
+ return decryptBlock(in, inOff, out, outOff);
+ }
+ }
+
+ public void reset()
+ {
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ //==================================
+ // Private Implementation
+ //==================================
+
+ /*
+ * Creates the subkeys using the same nomenclature
+ * as described in RFC2144.
+ *
+ * See section 2.4
+ */
+ protected void setKey(byte[] key)
+ {
+ /*
+ * Determine the key size here, if required
+ *
+ * if keysize <= 80bits, use 12 rounds instead of 16
+ * if keysize < 128bits, pad with 0
+ *
+ * Typical key sizes => 40, 64, 80, 128
+ */
+
+ if (key.length < 11)
+ {
+ _rounds = RED_ROUNDS;
+ }
+
+ int z[] = new int[16];
+ int x[] = new int[16];
+
+ int z03, z47, z8B, zCF;
+ int x03, x47, x8B, xCF;
+
+ /* copy the key into x */
+ for (int i=0; i< key.length; i++)
+ {
+ x[i] = key[i] & 0xff;
+ }
+
+ /*
+ * This will look different because the selection of
+ * bytes from the input key I've already chosen the
+ * correct int.
+ */
+ x03 = IntsTo32bits(x, 0x0);
+ x47 = IntsTo32bits(x, 0x4);
+ x8B = IntsTo32bits(x, 0x8);
+ xCF = IntsTo32bits(x, 0xC);
+
+ z03 = x03 ^S5[x[0xD]] ^S6[x[0xF]] ^S7[x[0xC]] ^S8[x[0xE]] ^S7[x[0x8]];
+
+ Bits32ToInts(z03, z, 0x0);
+ z47 = x8B ^S5[z[0x0]] ^S6[z[0x2]] ^S7[z[0x1]] ^S8[z[0x3]] ^S8[x[0xA]];
+ Bits32ToInts(z47, z, 0x4);
+ z8B = xCF ^S5[z[0x7]] ^S6[z[0x6]] ^S7[z[0x5]] ^S8[z[0x4]] ^S5[x[0x9]];
+ Bits32ToInts(z8B, z, 0x8);
+ zCF = x47 ^S5[z[0xA]] ^S6[z[0x9]] ^S7[z[0xB]] ^S8[z[0x8]] ^S6[x[0xB]];
+ Bits32ToInts(zCF, z, 0xC);
+ _Km[ 1]= S5[z[0x8]] ^ S6[z[0x9]] ^ S7[z[0x7]] ^ S8[z[0x6]] ^ S5[z[0x2]];
+ _Km[ 2]= S5[z[0xA]] ^ S6[z[0xB]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S6[z[0x6]];
+ _Km[ 3]= S5[z[0xC]] ^ S6[z[0xD]] ^ S7[z[0x3]] ^ S8[z[0x2]] ^ S7[z[0x9]];
+ _Km[ 4]= S5[z[0xE]] ^ S6[z[0xF]] ^ S7[z[0x1]] ^ S8[z[0x0]] ^ S8[z[0xC]];
+
+ z03 = IntsTo32bits(z, 0x0);
+ z47 = IntsTo32bits(z, 0x4);
+ z8B = IntsTo32bits(z, 0x8);
+ zCF = IntsTo32bits(z, 0xC);
+ x03 = z8B ^S5[z[0x5]] ^S6[z[0x7]] ^S7[z[0x4]] ^S8[z[0x6]] ^S7[z[0x0]];
+ Bits32ToInts(x03, x, 0x0);
+ x47 = z03 ^S5[x[0x0]] ^S6[x[0x2]] ^S7[x[0x1]] ^S8[x[0x3]] ^S8[z[0x2]];
+ Bits32ToInts(x47, x, 0x4);
+ x8B = z47 ^S5[x[0x7]] ^S6[x[0x6]] ^S7[x[0x5]] ^S8[x[0x4]] ^S5[z[0x1]];
+ Bits32ToInts(x8B, x, 0x8);
+ xCF = zCF ^S5[x[0xA]] ^S6[x[0x9]] ^S7[x[0xB]] ^S8[x[0x8]] ^S6[z[0x3]];
+ Bits32ToInts(xCF, x, 0xC);
+ _Km[ 5]= S5[x[0x3]] ^ S6[x[0x2]] ^ S7[x[0xC]] ^ S8[x[0xD]] ^ S5[x[0x8]];
+ _Km[ 6]= S5[x[0x1]] ^ S6[x[0x0]] ^ S7[x[0xE]] ^ S8[x[0xF]] ^ S6[x[0xD]];
+ _Km[ 7]= S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x8]] ^ S8[x[0x9]] ^ S7[x[0x3]];
+ _Km[ 8]= S5[x[0x5]] ^ S6[x[0x4]] ^ S7[x[0xA]] ^ S8[x[0xB]] ^ S8[x[0x7]];
+
+ x03 = IntsTo32bits(x, 0x0);
+ x47 = IntsTo32bits(x, 0x4);
+ x8B = IntsTo32bits(x, 0x8);
+ xCF = IntsTo32bits(x, 0xC);
+ z03 = x03 ^S5[x[0xD]] ^S6[x[0xF]] ^S7[x[0xC]] ^S8[x[0xE]] ^S7[x[0x8]];
+ Bits32ToInts(z03, z, 0x0);
+ z47 = x8B ^S5[z[0x0]] ^S6[z[0x2]] ^S7[z[0x1]] ^S8[z[0x3]] ^S8[x[0xA]];
+ Bits32ToInts(z47, z, 0x4);
+ z8B = xCF ^S5[z[0x7]] ^S6[z[0x6]] ^S7[z[0x5]] ^S8[z[0x4]] ^S5[x[0x9]];
+ Bits32ToInts(z8B, z, 0x8);
+ zCF = x47 ^S5[z[0xA]] ^S6[z[0x9]] ^S7[z[0xB]] ^S8[z[0x8]] ^S6[x[0xB]];
+ Bits32ToInts(zCF, z, 0xC);
+ _Km[ 9]= S5[z[0x3]] ^ S6[z[0x2]] ^ S7[z[0xC]] ^ S8[z[0xD]] ^ S5[z[0x9]];
+ _Km[10]= S5[z[0x1]] ^ S6[z[0x0]] ^ S7[z[0xE]] ^ S8[z[0xF]] ^ S6[z[0xc]];
+ _Km[11]= S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x8]] ^ S8[z[0x9]] ^ S7[z[0x2]];
+ _Km[12]= S5[z[0x5]] ^ S6[z[0x4]] ^ S7[z[0xA]] ^ S8[z[0xB]] ^ S8[z[0x6]];
+
+ z03 = IntsTo32bits(z, 0x0);
+ z47 = IntsTo32bits(z, 0x4);
+ z8B = IntsTo32bits(z, 0x8);
+ zCF = IntsTo32bits(z, 0xC);
+ x03 = z8B ^S5[z[0x5]] ^S6[z[0x7]] ^S7[z[0x4]] ^S8[z[0x6]] ^S7[z[0x0]];
+ Bits32ToInts(x03, x, 0x0);
+ x47 = z03 ^S5[x[0x0]] ^S6[x[0x2]] ^S7[x[0x1]] ^S8[x[0x3]] ^S8[z[0x2]];
+ Bits32ToInts(x47, x, 0x4);
+ x8B = z47 ^S5[x[0x7]] ^S6[x[0x6]] ^S7[x[0x5]] ^S8[x[0x4]] ^S5[z[0x1]];
+ Bits32ToInts(x8B, x, 0x8);
+ xCF = zCF ^S5[x[0xA]] ^S6[x[0x9]] ^S7[x[0xB]] ^S8[x[0x8]] ^S6[z[0x3]];
+ Bits32ToInts(xCF, x, 0xC);
+ _Km[13]= S5[x[0x8]] ^ S6[x[0x9]] ^ S7[x[0x7]] ^ S8[x[0x6]] ^ S5[x[0x3]];
+ _Km[14]= S5[x[0xA]] ^ S6[x[0xB]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S6[x[0x7]];
+ _Km[15]= S5[x[0xC]] ^ S6[x[0xD]] ^ S7[x[0x3]] ^ S8[x[0x2]] ^ S7[x[0x8]];
+ _Km[16]= S5[x[0xE]] ^ S6[x[0xF]] ^ S7[x[0x1]] ^ S8[x[0x0]] ^ S8[x[0xD]];
+
+ x03 = IntsTo32bits(x, 0x0);
+ x47 = IntsTo32bits(x, 0x4);
+ x8B = IntsTo32bits(x, 0x8);
+ xCF = IntsTo32bits(x, 0xC);
+ z03 = x03 ^S5[x[0xD]] ^S6[x[0xF]] ^S7[x[0xC]] ^S8[x[0xE]] ^S7[x[0x8]];
+ Bits32ToInts(z03, z, 0x0);
+ z47 = x8B ^S5[z[0x0]] ^S6[z[0x2]] ^S7[z[0x1]] ^S8[z[0x3]] ^S8[x[0xA]];
+ Bits32ToInts(z47, z, 0x4);
+ z8B = xCF ^S5[z[0x7]] ^S6[z[0x6]] ^S7[z[0x5]] ^S8[z[0x4]] ^S5[x[0x9]];
+ Bits32ToInts(z8B, z, 0x8);
+ zCF = x47 ^S5[z[0xA]] ^S6[z[0x9]] ^S7[z[0xB]] ^S8[z[0x8]] ^S6[x[0xB]];
+ Bits32ToInts(zCF, z, 0xC);
+ _Kr[ 1]=(S5[z[0x8]]^S6[z[0x9]]^S7[z[0x7]]^S8[z[0x6]] ^ S5[z[0x2]])&0x1f;
+ _Kr[ 2]=(S5[z[0xA]]^S6[z[0xB]]^S7[z[0x5]]^S8[z[0x4]] ^ S6[z[0x6]])&0x1f;
+ _Kr[ 3]=(S5[z[0xC]]^S6[z[0xD]]^S7[z[0x3]]^S8[z[0x2]] ^ S7[z[0x9]])&0x1f;
+ _Kr[ 4]=(S5[z[0xE]]^S6[z[0xF]]^S7[z[0x1]]^S8[z[0x0]] ^ S8[z[0xC]])&0x1f;
+
+ z03 = IntsTo32bits(z, 0x0);
+ z47 = IntsTo32bits(z, 0x4);
+ z8B = IntsTo32bits(z, 0x8);
+ zCF = IntsTo32bits(z, 0xC);
+ x03 = z8B ^S5[z[0x5]] ^S6[z[0x7]] ^S7[z[0x4]] ^S8[z[0x6]] ^S7[z[0x0]];
+ Bits32ToInts(x03, x, 0x0);
+ x47 = z03 ^S5[x[0x0]] ^S6[x[0x2]] ^S7[x[0x1]] ^S8[x[0x3]] ^S8[z[0x2]];
+ Bits32ToInts(x47, x, 0x4);
+ x8B = z47 ^S5[x[0x7]] ^S6[x[0x6]] ^S7[x[0x5]] ^S8[x[0x4]] ^S5[z[0x1]];
+ Bits32ToInts(x8B, x, 0x8);
+ xCF = zCF ^S5[x[0xA]] ^S6[x[0x9]] ^S7[x[0xB]] ^S8[x[0x8]] ^S6[z[0x3]];
+ Bits32ToInts(xCF, x, 0xC);
+ _Kr[ 5]=(S5[x[0x3]]^S6[x[0x2]]^S7[x[0xC]]^S8[x[0xD]]^S5[x[0x8]])&0x1f;
+ _Kr[ 6]=(S5[x[0x1]]^S6[x[0x0]]^S7[x[0xE]]^S8[x[0xF]]^S6[x[0xD]])&0x1f;
+ _Kr[ 7]=(S5[x[0x7]]^S6[x[0x6]]^S7[x[0x8]]^S8[x[0x9]]^S7[x[0x3]])&0x1f;
+ _Kr[ 8]=(S5[x[0x5]]^S6[x[0x4]]^S7[x[0xA]]^S8[x[0xB]]^S8[x[0x7]])&0x1f;
+
+ x03 = IntsTo32bits(x, 0x0);
+ x47 = IntsTo32bits(x, 0x4);
+ x8B = IntsTo32bits(x, 0x8);
+ xCF = IntsTo32bits(x, 0xC);
+ z03 = x03 ^S5[x[0xD]] ^S6[x[0xF]] ^S7[x[0xC]] ^S8[x[0xE]] ^S7[x[0x8]];
+ Bits32ToInts(z03, z, 0x0);
+ z47 = x8B ^S5[z[0x0]] ^S6[z[0x2]] ^S7[z[0x1]] ^S8[z[0x3]] ^S8[x[0xA]];
+ Bits32ToInts(z47, z, 0x4);
+ z8B = xCF ^S5[z[0x7]] ^S6[z[0x6]] ^S7[z[0x5]] ^S8[z[0x4]] ^S5[x[0x9]];
+ Bits32ToInts(z8B, z, 0x8);
+ zCF = x47 ^S5[z[0xA]] ^S6[z[0x9]] ^S7[z[0xB]] ^S8[z[0x8]] ^S6[x[0xB]];
+ Bits32ToInts(zCF, z, 0xC);
+ _Kr[ 9]=(S5[z[0x3]]^S6[z[0x2]]^S7[z[0xC]]^S8[z[0xD]]^S5[z[0x9]])&0x1f;
+ _Kr[10]=(S5[z[0x1]]^S6[z[0x0]]^S7[z[0xE]]^S8[z[0xF]]^S6[z[0xc]])&0x1f;
+ _Kr[11]=(S5[z[0x7]]^S6[z[0x6]]^S7[z[0x8]]^S8[z[0x9]]^S7[z[0x2]])&0x1f;
+ _Kr[12]=(S5[z[0x5]]^S6[z[0x4]]^S7[z[0xA]]^S8[z[0xB]]^S8[z[0x6]])&0x1f;
+
+ z03 = IntsTo32bits(z, 0x0);
+ z47 = IntsTo32bits(z, 0x4);
+ z8B = IntsTo32bits(z, 0x8);
+ zCF = IntsTo32bits(z, 0xC);
+ x03 = z8B ^S5[z[0x5]] ^S6[z[0x7]] ^S7[z[0x4]] ^S8[z[0x6]] ^S7[z[0x0]];
+ Bits32ToInts(x03, x, 0x0);
+ x47 = z03 ^S5[x[0x0]] ^S6[x[0x2]] ^S7[x[0x1]] ^S8[x[0x3]] ^S8[z[0x2]];
+ Bits32ToInts(x47, x, 0x4);
+ x8B = z47 ^S5[x[0x7]] ^S6[x[0x6]] ^S7[x[0x5]] ^S8[x[0x4]] ^S5[z[0x1]];
+ Bits32ToInts(x8B, x, 0x8);
+ xCF = zCF ^S5[x[0xA]] ^S6[x[0x9]] ^S7[x[0xB]] ^S8[x[0x8]] ^S6[z[0x3]];
+ Bits32ToInts(xCF, x, 0xC);
+ _Kr[13]=(S5[x[0x8]]^S6[x[0x9]]^S7[x[0x7]]^S8[x[0x6]]^S5[x[0x3]])&0x1f;
+ _Kr[14]=(S5[x[0xA]]^S6[x[0xB]]^S7[x[0x5]]^S8[x[0x4]]^S6[x[0x7]])&0x1f;
+ _Kr[15]=(S5[x[0xC]]^S6[x[0xD]]^S7[x[0x3]]^S8[x[0x2]]^S7[x[0x8]])&0x1f;
+ _Kr[16]=(S5[x[0xE]]^S6[x[0xF]]^S7[x[0x1]]^S8[x[0x0]]^S8[x[0xD]])&0x1f;
+ }
+
+ /**
+ * Encrypt the given input starting at the given offset and place
+ * the result in the provided buffer starting at the given offset.
+ *
+ * @param src The plaintext buffer
+ * @param srcIndex An offset into src
+ * @param dst The ciphertext buffer
+ * @param dstIndex An offset into dst
+ */
+ protected int encryptBlock(
+ byte[] src,
+ int srcIndex,
+ byte[] dst,
+ int dstIndex)
+ {
+
+ int result[] = new int[2];
+
+ // process the input block
+ // batch the units up into a 32 bit chunk and go for it
+ // the array is in bytes, the increment is 8x8 bits = 64
+
+ int L0 = BytesTo32bits(src, srcIndex);
+ int R0 = BytesTo32bits(src, srcIndex + 4);
+
+ CAST_Encipher(L0, R0, result);
+
+ // now stuff them into the destination block
+ Bits32ToBytes(result[0], dst, dstIndex);
+ Bits32ToBytes(result[1], dst, dstIndex + 4);
+
+ return BLOCK_SIZE;
+ }
+
+ /**
+ * Decrypt the given input starting at the given offset and place
+ * the result in the provided buffer starting at the given offset.
+ *
+ * @param src The plaintext buffer
+ * @param srcIndex An offset into src
+ * @param dst The ciphertext buffer
+ * @param dstIndex An offset into dst
+ */
+ protected int decryptBlock(
+ byte[] src,
+ int srcIndex,
+ byte[] dst,
+ int dstIndex)
+ {
+ int result[] = new int[2];
+
+ // process the input block
+ // batch the units up into a 32 bit chunk and go for it
+ // the array is in bytes, the increment is 8x8 bits = 64
+ int L16 = BytesTo32bits(src, srcIndex);
+ int R16 = BytesTo32bits(src, srcIndex+4);
+
+ CAST_Decipher(L16, R16, result);
+
+ // now stuff them into the destination block
+ Bits32ToBytes(result[0], dst, dstIndex);
+ Bits32ToBytes(result[1], dst, dstIndex+4);
+
+ return BLOCK_SIZE;
+ }
+
+ /**
+ * The first of the three processing functions for the
+ * encryption and decryption.
+ *
+ * @param D the input to be processed
+ * @param Kmi the mask to be used from Km[n]
+ * @param Kri the rotation value to be used
+ *
+ */
+ protected final int F1(int D, int Kmi, int Kri)
+ {
+ int I = Kmi + D;
+ I = I << Kri | I >>> (32-Kri);
+ return ((S1[(I>>>24)&0xff]^S2[(I>>>16)&0xff])-S3[(I>>> 8)&0xff])+
+ S4[I & 0xff];
+ }
+
+ /**
+ * The second of the three processing functions for the
+ * encryption and decryption.
+ *
+ * @param D the input to be processed
+ * @param Kmi the mask to be used from Km[n]
+ * @param Kri the rotation value to be used
+ *
+ */
+ protected final int F2(int D, int Kmi, int Kri)
+ {
+ int I = Kmi ^ D;
+ I = I << Kri | I >>> (32-Kri);
+ return ((S1[(I>>>24)&0xff]-S2[(I>>>16)&0xff])+S3[(I>>> 8)&0xff])^
+ S4[I & 0xff];
+ }
+
+ /**
+ * The third of the three processing functions for the
+ * encryption and decryption.
+ *
+ * @param D the input to be processed
+ * @param Kmi the mask to be used from Km[n]
+ * @param Kri the rotation value to be used
+ *
+ */
+ protected final int F3(int D, int Kmi, int Kri)
+ {
+ int I = Kmi - D;
+ I = I << Kri | I >>> (32-Kri);
+ return ((S1[(I>>>24)&0xff]+S2[(I>>>16)&0xff])^S3[(I>>> 8)&0xff])-
+ S4[I & 0xff];
+ }
+
+ /**
+ * Does the 16 rounds to encrypt the block.
+ *
+ * @param L0 the LH-32bits of the plaintext block
+ * @param R0 the RH-32bits of the plaintext block
+ */
+ protected final void CAST_Encipher(int L0, int R0, int result[])
+ {
+ int Lp = L0; // the previous value, equiv to L[i-1]
+ int Rp = R0; // equivalent to R[i-1]
+
+ /*
+ * numbering consistent with paper to make
+ * checking and validating easier
+ */
+ int Li = L0, Ri = R0;
+
+ for (int i = 1; i<=_rounds ; i++)
+ {
+ Lp = Li;
+ Rp = Ri;
+
+ Li = Rp;
+ switch (i)
+ {
+ case 1:
+ case 4:
+ case 7:
+ case 10:
+ case 13:
+ case 16:
+ Ri = Lp ^ F1(Rp, _Km[i], _Kr[i]);
+ break;
+ case 2:
+ case 5:
+ case 8:
+ case 11:
+ case 14:
+ Ri = Lp ^ F2(Rp, _Km[i], _Kr[i]);
+ break;
+ case 3:
+ case 6:
+ case 9:
+ case 12:
+ case 15:
+ Ri = Lp ^ F3(Rp, _Km[i], _Kr[i]);
+ break;
+ }
+ }
+
+ result[0] = Ri;
+ result[1] = Li;
+
+ return;
+ }
+
+ protected final void CAST_Decipher(int L16, int R16, int result[])
+ {
+ int Lp = L16; // the previous value, equiv to L[i-1]
+ int Rp = R16; // equivalent to R[i-1]
+
+ /*
+ * numbering consistent with paper to make
+ * checking and validating easier
+ */
+ int Li = L16, Ri = R16;
+
+ for (int i = _rounds; i > 0; i--)
+ {
+ Lp = Li;
+ Rp = Ri;
+
+ Li = Rp;
+ switch (i)
+ {
+ case 1:
+ case 4:
+ case 7:
+ case 10:
+ case 13:
+ case 16:
+ Ri = Lp ^ F1(Rp, _Km[i], _Kr[i]);
+ break;
+ case 2:
+ case 5:
+ case 8:
+ case 11:
+ case 14:
+ Ri = Lp ^ F2(Rp, _Km[i], _Kr[i]);
+ break;
+ case 3:
+ case 6:
+ case 9:
+ case 12:
+ case 15:
+ Ri = Lp ^ F3(Rp, _Km[i], _Kr[i]);
+ break;
+ }
+ }
+
+ result[0] = Ri;
+ result[1] = Li;
+
+ return;
+ }
+
+ protected final void Bits32ToInts(int in, int[] b, int offset)
+ {
+ b[offset + 3] = (in & 0xff);
+ b[offset + 2] = ((in >>> 8) & 0xff);
+ b[offset + 1] = ((in >>> 16) & 0xff);
+ b[offset] = ((in >>> 24) & 0xff);
+ }
+
+ protected final int IntsTo32bits(int[] b, int i)
+ {
+ int rv = 0;
+
+ rv = ((b[i] & 0xff) << 24) |
+ ((b[i+1] & 0xff) << 16) |
+ ((b[i+2] & 0xff) << 8) |
+ ((b[i+3] & 0xff));
+
+ return rv;
+ }
+
+ protected final void Bits32ToBytes(int in, byte[] b, int offset)
+ {
+ b[offset + 3] = (byte)in;
+ b[offset + 2] = (byte)(in >>> 8);
+ b[offset + 1] = (byte)(in >>> 16);
+ b[offset] = (byte)(in >>> 24);
+ }
+
+ protected final int BytesTo32bits(byte[] b, int i)
+ {
+ return ((b[i] & 0xff) << 24) |
+ ((b[i+1] & 0xff) << 16) |
+ ((b[i+2] & 0xff) << 8) |
+ ((b[i+3] & 0xff));
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/CAST6Engine.java b/core/src/main/java/org/spongycastle/crypto/engines/CAST6Engine.java
new file mode 100644
index 00000000..7a990756
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/CAST6Engine.java
@@ -0,0 +1,296 @@
+package org.spongycastle.crypto.engines;
+
+
+/**
+ * A class that provides CAST6 key encryption operations,
+ * such as encoding data and generating keys.
+ *
+ * All the algorithms herein are from the Internet RFC
+ *
+ * RFC2612 - CAST6 (128bit block, 128-256bit key)
+ *
+ * and implement a simplified cryptography interface.
+ */
+public final class CAST6Engine extends CAST5Engine
+{
+ //====================================
+ // Useful constants
+ //====================================
+
+ protected static final int ROUNDS = 12;
+
+ protected static final int BLOCK_SIZE = 16; // bytes = 128 bits
+
+ /*
+ * Put the round and mask keys into an array.
+ * Kr0[i] => _Kr[i*4 + 0]
+ */
+ protected int _Kr[] = new int[ROUNDS*4]; // the rotating round key(s)
+ protected int _Km[] = new int[ROUNDS*4]; // the masking round key(s)
+
+ /*
+ * Key setup
+ */
+ protected int _Tr[] = new int[24 * 8];
+ protected int _Tm[] = new int[24 * 8];
+
+ private int[] _workingKey = new int[8];
+
+ public CAST6Engine()
+ {
+ }
+
+ public String getAlgorithmName()
+ {
+ return "CAST6";
+ }
+
+ public void reset()
+ {
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ //==================================
+ // Private Implementation
+ //==================================
+
+ /*
+ * Creates the subkeys using the same nomenclature
+ * as described in RFC2612.
+ *
+ * See section 2.4
+ */
+ protected void setKey(byte[] key)
+ {
+ int Cm = 0x5a827999;
+ int Mm = 0x6ed9eba1;
+ int Cr = 19;
+ int Mr = 17;
+
+ /*
+ * Determine the key size here, if required
+ *
+ * if keysize < 256 bytes, pad with 0
+ *
+ * Typical key sizes => 128, 160, 192, 224, 256
+ */
+ for (int i=0; i< 24; i++)
+ {
+ for (int j=0; j< 8; j++)
+ {
+ _Tm[i*8 + j] = Cm;
+ Cm = (Cm + Mm); // mod 2^32;
+
+ _Tr[i*8 + j] = Cr;
+ Cr = (Cr + Mr) & 0x1f; // mod 32
+ }
+ }
+
+ byte[] tmpKey = new byte[64];
+ int length = key.length;
+ System.arraycopy(key, 0, tmpKey, 0, length);
+
+ // now create ABCDEFGH
+ for (int i=0; i< 8; i++)
+ {
+ _workingKey[i] = BytesTo32bits(tmpKey, i*4);
+ }
+
+ // Generate the key schedule
+ for (int i=0; i< 12; i++)
+ {
+ // KAPPA <- W2i(KAPPA)
+ int i2 = i*2 *8;
+ _workingKey[6] ^= F1(_workingKey[7], _Tm[i2 ], _Tr[i2 ]);
+ _workingKey[5] ^= F2(_workingKey[6], _Tm[i2+1], _Tr[i2+1]);
+ _workingKey[4] ^= F3(_workingKey[5], _Tm[i2+2], _Tr[i2+2]);
+ _workingKey[3] ^= F1(_workingKey[4], _Tm[i2+3], _Tr[i2+3]);
+ _workingKey[2] ^= F2(_workingKey[3], _Tm[i2+4], _Tr[i2+4]);
+ _workingKey[1] ^= F3(_workingKey[2], _Tm[i2+5], _Tr[i2+5]);
+ _workingKey[0] ^= F1(_workingKey[1], _Tm[i2+6], _Tr[i2+6]);
+ _workingKey[7] ^= F2(_workingKey[0], _Tm[i2+7], _Tr[i2+7]);
+
+ // KAPPA <- W2i+1(KAPPA)
+ i2 = (i*2 + 1)*8;
+ _workingKey[6] ^= F1(_workingKey[7], _Tm[i2 ], _Tr[i2 ]);
+ _workingKey[5] ^= F2(_workingKey[6], _Tm[i2+1], _Tr[i2+1]);
+ _workingKey[4] ^= F3(_workingKey[5], _Tm[i2+2], _Tr[i2+2]);
+ _workingKey[3] ^= F1(_workingKey[4], _Tm[i2+3], _Tr[i2+3]);
+ _workingKey[2] ^= F2(_workingKey[3], _Tm[i2+4], _Tr[i2+4]);
+ _workingKey[1] ^= F3(_workingKey[2], _Tm[i2+5], _Tr[i2+5]);
+ _workingKey[0] ^= F1(_workingKey[1], _Tm[i2+6], _Tr[i2+6]);
+ _workingKey[7] ^= F2(_workingKey[0], _Tm[i2+7], _Tr[i2+7]);
+
+ // Kr_(i) <- KAPPA
+ _Kr[i*4 ] = _workingKey[0] & 0x1f;
+ _Kr[i*4 + 1] = _workingKey[2] & 0x1f;
+ _Kr[i*4 + 2] = _workingKey[4] & 0x1f;
+ _Kr[i*4 + 3] = _workingKey[6] & 0x1f;
+
+
+ // Km_(i) <- KAPPA
+ _Km[i*4 ] = _workingKey[7];
+ _Km[i*4 + 1] = _workingKey[5];
+ _Km[i*4 + 2] = _workingKey[3];
+ _Km[i*4 + 3] = _workingKey[1];
+ }
+
+ }
+
+ /**
+ * Encrypt the given input starting at the given offset and place
+ * the result in the provided buffer starting at the given offset.
+ *
+ * @param src The plaintext buffer
+ * @param srcIndex An offset into src
+ * @param dst The ciphertext buffer
+ * @param dstIndex An offset into dst
+ */
+ protected int encryptBlock(
+ byte[] src,
+ int srcIndex,
+ byte[] dst,
+ int dstIndex)
+ {
+
+ int result[] = new int[4];
+
+ // process the input block
+ // batch the units up into 4x32 bit chunks and go for it
+
+ int A = BytesTo32bits(src, srcIndex);
+ int B = BytesTo32bits(src, srcIndex + 4);
+ int C = BytesTo32bits(src, srcIndex + 8);
+ int D = BytesTo32bits(src, srcIndex + 12);
+
+ CAST_Encipher(A, B, C, D, result);
+
+ // now stuff them into the destination block
+ Bits32ToBytes(result[0], dst, dstIndex);
+ Bits32ToBytes(result[1], dst, dstIndex + 4);
+ Bits32ToBytes(result[2], dst, dstIndex + 8);
+ Bits32ToBytes(result[3], dst, dstIndex + 12);
+
+ return BLOCK_SIZE;
+ }
+
+ /**
+ * Decrypt the given input starting at the given offset and place
+ * the result in the provided buffer starting at the given offset.
+ *
+ * @param src The plaintext buffer
+ * @param srcIndex An offset into src
+ * @param dst The ciphertext buffer
+ * @param dstIndex An offset into dst
+ */
+ protected int decryptBlock(
+ byte[] src,
+ int srcIndex,
+ byte[] dst,
+ int dstIndex)
+ {
+ int result[] = new int[4];
+
+ // process the input block
+ // batch the units up into 4x32 bit chunks and go for it
+ int A = BytesTo32bits(src, srcIndex);
+ int B = BytesTo32bits(src, srcIndex + 4);
+ int C = BytesTo32bits(src, srcIndex + 8);
+ int D = BytesTo32bits(src, srcIndex + 12);
+
+ CAST_Decipher(A, B, C, D, result);
+
+ // now stuff them into the destination block
+ Bits32ToBytes(result[0], dst, dstIndex);
+ Bits32ToBytes(result[1], dst, dstIndex + 4);
+ Bits32ToBytes(result[2], dst, dstIndex + 8);
+ Bits32ToBytes(result[3], dst, dstIndex + 12);
+
+ return BLOCK_SIZE;
+ }
+
+ /**
+ * Does the 12 quad rounds rounds to encrypt the block.
+ *
+ * @param A the 00-31 bits of the plaintext block
+ * @param B the 32-63 bits of the plaintext block
+ * @param C the 64-95 bits of the plaintext block
+ * @param D the 96-127 bits of the plaintext block
+ * @param result the resulting ciphertext
+ */
+ protected final void CAST_Encipher(int A, int B, int C, int D,int result[])
+ {
+ int x;
+ for (int i=0; i< 6; i++)
+ {
+ x = i*4;
+ // BETA <- Qi(BETA)
+ C ^= F1(D, _Km[x], _Kr[x]);
+ B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
+ A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
+ D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
+
+ }
+
+ for (int i=6; i<12; i++)
+ {
+ x = i*4;
+ // BETA <- QBARi(BETA)
+ D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
+ A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
+ B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
+ C ^= F1(D, _Km[x], _Kr[x]);
+
+ }
+
+ result[0] = A;
+ result[1] = B;
+ result[2] = C;
+ result[3] = D;
+ }
+
+ /**
+ * Does the 12 quad rounds rounds to decrypt the block.
+ *
+ * @param A the 00-31 bits of the ciphertext block
+ * @param B the 32-63 bits of the ciphertext block
+ * @param C the 64-95 bits of the ciphertext block
+ * @param D the 96-127 bits of the ciphertext block
+ * @param result the resulting plaintext
+ */
+ protected final void CAST_Decipher(int A, int B, int C, int D,int result[])
+ {
+ int x;
+ for (int i=0; i< 6; i++)
+ {
+ x = (11-i)*4;
+ // BETA <- Qi(BETA)
+ C ^= F1(D, _Km[x], _Kr[x]);
+ B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
+ A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
+ D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
+
+ }
+
+ for (int i=6; i<12; i++)
+ {
+ x = (11-i)*4;
+ // BETA <- QBARi(BETA)
+ D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
+ A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
+ B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
+ C ^= F1(D, _Km[x], _Kr[x]);
+
+ }
+
+ result[0] = A;
+ result[1] = B;
+ result[2] = C;
+ result[3] = D;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/CamelliaEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/CamelliaEngine.java
new file mode 100644
index 00000000..b82af072
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/CamelliaEngine.java
@@ -0,0 +1,684 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+
+/**
+ * Camellia - based on RFC 3713.
+ */
+public class CamelliaEngine
+ implements BlockCipher
+{
+ private boolean initialised = false;
+ private boolean _keyIs128;
+
+ private static final int BLOCK_SIZE = 16;
+ private static final int MASK8 = 0xff;
+
+ private int[] subkey = new int[24 * 4];
+ private int[] kw = new int[4 * 2]; // for whitening
+ private int[] ke = new int[6 * 2]; // for FL and FL^(-1)
+ private int[] state = new int[4]; // for encryption and decryption
+
+ private static final int SIGMA[] = {
+ 0xa09e667f, 0x3bcc908b,
+ 0xb67ae858, 0x4caa73b2,
+ 0xc6ef372f, 0xe94f82be,
+ 0x54ff53a5, 0xf1d36f1c,
+ 0x10e527fa, 0xde682d1d,
+ 0xb05688c2, 0xb3e6c1fd
+ };
+
+ /*
+ *
+ * S-box data
+ *
+ */
+ private static final int SBOX1_1110[] = {
+ 0x70707000, 0x82828200, 0x2c2c2c00, 0xececec00, 0xb3b3b300, 0x27272700,
+ 0xc0c0c000, 0xe5e5e500, 0xe4e4e400, 0x85858500, 0x57575700, 0x35353500,
+ 0xeaeaea00, 0x0c0c0c00, 0xaeaeae00, 0x41414100, 0x23232300, 0xefefef00,
+ 0x6b6b6b00, 0x93939300, 0x45454500, 0x19191900, 0xa5a5a500, 0x21212100,
+ 0xededed00, 0x0e0e0e00, 0x4f4f4f00, 0x4e4e4e00, 0x1d1d1d00, 0x65656500,
+ 0x92929200, 0xbdbdbd00, 0x86868600, 0xb8b8b800, 0xafafaf00, 0x8f8f8f00,
+ 0x7c7c7c00, 0xebebeb00, 0x1f1f1f00, 0xcecece00, 0x3e3e3e00, 0x30303000,
+ 0xdcdcdc00, 0x5f5f5f00, 0x5e5e5e00, 0xc5c5c500, 0x0b0b0b00, 0x1a1a1a00,
+ 0xa6a6a600, 0xe1e1e100, 0x39393900, 0xcacaca00, 0xd5d5d500, 0x47474700,
+ 0x5d5d5d00, 0x3d3d3d00, 0xd9d9d900, 0x01010100, 0x5a5a5a00, 0xd6d6d600,
+ 0x51515100, 0x56565600, 0x6c6c6c00, 0x4d4d4d00, 0x8b8b8b00, 0x0d0d0d00,
+ 0x9a9a9a00, 0x66666600, 0xfbfbfb00, 0xcccccc00, 0xb0b0b000, 0x2d2d2d00,
+ 0x74747400, 0x12121200, 0x2b2b2b00, 0x20202000, 0xf0f0f000, 0xb1b1b100,
+ 0x84848400, 0x99999900, 0xdfdfdf00, 0x4c4c4c00, 0xcbcbcb00, 0xc2c2c200,
+ 0x34343400, 0x7e7e7e00, 0x76767600, 0x05050500, 0x6d6d6d00, 0xb7b7b700,
+ 0xa9a9a900, 0x31313100, 0xd1d1d100, 0x17171700, 0x04040400, 0xd7d7d700,
+ 0x14141400, 0x58585800, 0x3a3a3a00, 0x61616100, 0xdedede00, 0x1b1b1b00,
+ 0x11111100, 0x1c1c1c00, 0x32323200, 0x0f0f0f00, 0x9c9c9c00, 0x16161600,
+ 0x53535300, 0x18181800, 0xf2f2f200, 0x22222200, 0xfefefe00, 0x44444400,
+ 0xcfcfcf00, 0xb2b2b200, 0xc3c3c300, 0xb5b5b500, 0x7a7a7a00, 0x91919100,
+ 0x24242400, 0x08080800, 0xe8e8e800, 0xa8a8a800, 0x60606000, 0xfcfcfc00,
+ 0x69696900, 0x50505000, 0xaaaaaa00, 0xd0d0d000, 0xa0a0a000, 0x7d7d7d00,
+ 0xa1a1a100, 0x89898900, 0x62626200, 0x97979700, 0x54545400, 0x5b5b5b00,
+ 0x1e1e1e00, 0x95959500, 0xe0e0e000, 0xffffff00, 0x64646400, 0xd2d2d200,
+ 0x10101000, 0xc4c4c400, 0x00000000, 0x48484800, 0xa3a3a300, 0xf7f7f700,
+ 0x75757500, 0xdbdbdb00, 0x8a8a8a00, 0x03030300, 0xe6e6e600, 0xdadada00,
+ 0x09090900, 0x3f3f3f00, 0xdddddd00, 0x94949400, 0x87878700, 0x5c5c5c00,
+ 0x83838300, 0x02020200, 0xcdcdcd00, 0x4a4a4a00, 0x90909000, 0x33333300,
+ 0x73737300, 0x67676700, 0xf6f6f600, 0xf3f3f300, 0x9d9d9d00, 0x7f7f7f00,
+ 0xbfbfbf00, 0xe2e2e200, 0x52525200, 0x9b9b9b00, 0xd8d8d800, 0x26262600,
+ 0xc8c8c800, 0x37373700, 0xc6c6c600, 0x3b3b3b00, 0x81818100, 0x96969600,
+ 0x6f6f6f00, 0x4b4b4b00, 0x13131300, 0xbebebe00, 0x63636300, 0x2e2e2e00,
+ 0xe9e9e900, 0x79797900, 0xa7a7a700, 0x8c8c8c00, 0x9f9f9f00, 0x6e6e6e00,
+ 0xbcbcbc00, 0x8e8e8e00, 0x29292900, 0xf5f5f500, 0xf9f9f900, 0xb6b6b600,
+ 0x2f2f2f00, 0xfdfdfd00, 0xb4b4b400, 0x59595900, 0x78787800, 0x98989800,
+ 0x06060600, 0x6a6a6a00, 0xe7e7e700, 0x46464600, 0x71717100, 0xbababa00,
+ 0xd4d4d400, 0x25252500, 0xababab00, 0x42424200, 0x88888800, 0xa2a2a200,
+ 0x8d8d8d00, 0xfafafa00, 0x72727200, 0x07070700, 0xb9b9b900, 0x55555500,
+ 0xf8f8f800, 0xeeeeee00, 0xacacac00, 0x0a0a0a00, 0x36363600, 0x49494900,
+ 0x2a2a2a00, 0x68686800, 0x3c3c3c00, 0x38383800, 0xf1f1f100, 0xa4a4a400,
+ 0x40404000, 0x28282800, 0xd3d3d300, 0x7b7b7b00, 0xbbbbbb00, 0xc9c9c900,
+ 0x43434300, 0xc1c1c100, 0x15151500, 0xe3e3e300, 0xadadad00, 0xf4f4f400,
+ 0x77777700, 0xc7c7c700, 0x80808000, 0x9e9e9e00
+ };
+
+ private static final int SBOX4_4404[] = {
+ 0x70700070, 0x2c2c002c, 0xb3b300b3, 0xc0c000c0, 0xe4e400e4, 0x57570057,
+ 0xeaea00ea, 0xaeae00ae, 0x23230023, 0x6b6b006b, 0x45450045, 0xa5a500a5,
+ 0xeded00ed, 0x4f4f004f, 0x1d1d001d, 0x92920092, 0x86860086, 0xafaf00af,
+ 0x7c7c007c, 0x1f1f001f, 0x3e3e003e, 0xdcdc00dc, 0x5e5e005e, 0x0b0b000b,
+ 0xa6a600a6, 0x39390039, 0xd5d500d5, 0x5d5d005d, 0xd9d900d9, 0x5a5a005a,
+ 0x51510051, 0x6c6c006c, 0x8b8b008b, 0x9a9a009a, 0xfbfb00fb, 0xb0b000b0,
+ 0x74740074, 0x2b2b002b, 0xf0f000f0, 0x84840084, 0xdfdf00df, 0xcbcb00cb,
+ 0x34340034, 0x76760076, 0x6d6d006d, 0xa9a900a9, 0xd1d100d1, 0x04040004,
+ 0x14140014, 0x3a3a003a, 0xdede00de, 0x11110011, 0x32320032, 0x9c9c009c,
+ 0x53530053, 0xf2f200f2, 0xfefe00fe, 0xcfcf00cf, 0xc3c300c3, 0x7a7a007a,
+ 0x24240024, 0xe8e800e8, 0x60600060, 0x69690069, 0xaaaa00aa, 0xa0a000a0,
+ 0xa1a100a1, 0x62620062, 0x54540054, 0x1e1e001e, 0xe0e000e0, 0x64640064,
+ 0x10100010, 0x00000000, 0xa3a300a3, 0x75750075, 0x8a8a008a, 0xe6e600e6,
+ 0x09090009, 0xdddd00dd, 0x87870087, 0x83830083, 0xcdcd00cd, 0x90900090,
+ 0x73730073, 0xf6f600f6, 0x9d9d009d, 0xbfbf00bf, 0x52520052, 0xd8d800d8,
+ 0xc8c800c8, 0xc6c600c6, 0x81810081, 0x6f6f006f, 0x13130013, 0x63630063,
+ 0xe9e900e9, 0xa7a700a7, 0x9f9f009f, 0xbcbc00bc, 0x29290029, 0xf9f900f9,
+ 0x2f2f002f, 0xb4b400b4, 0x78780078, 0x06060006, 0xe7e700e7, 0x71710071,
+ 0xd4d400d4, 0xabab00ab, 0x88880088, 0x8d8d008d, 0x72720072, 0xb9b900b9,
+ 0xf8f800f8, 0xacac00ac, 0x36360036, 0x2a2a002a, 0x3c3c003c, 0xf1f100f1,
+ 0x40400040, 0xd3d300d3, 0xbbbb00bb, 0x43430043, 0x15150015, 0xadad00ad,
+ 0x77770077, 0x80800080, 0x82820082, 0xecec00ec, 0x27270027, 0xe5e500e5,
+ 0x85850085, 0x35350035, 0x0c0c000c, 0x41410041, 0xefef00ef, 0x93930093,
+ 0x19190019, 0x21210021, 0x0e0e000e, 0x4e4e004e, 0x65650065, 0xbdbd00bd,
+ 0xb8b800b8, 0x8f8f008f, 0xebeb00eb, 0xcece00ce, 0x30300030, 0x5f5f005f,
+ 0xc5c500c5, 0x1a1a001a, 0xe1e100e1, 0xcaca00ca, 0x47470047, 0x3d3d003d,
+ 0x01010001, 0xd6d600d6, 0x56560056, 0x4d4d004d, 0x0d0d000d, 0x66660066,
+ 0xcccc00cc, 0x2d2d002d, 0x12120012, 0x20200020, 0xb1b100b1, 0x99990099,
+ 0x4c4c004c, 0xc2c200c2, 0x7e7e007e, 0x05050005, 0xb7b700b7, 0x31310031,
+ 0x17170017, 0xd7d700d7, 0x58580058, 0x61610061, 0x1b1b001b, 0x1c1c001c,
+ 0x0f0f000f, 0x16160016, 0x18180018, 0x22220022, 0x44440044, 0xb2b200b2,
+ 0xb5b500b5, 0x91910091, 0x08080008, 0xa8a800a8, 0xfcfc00fc, 0x50500050,
+ 0xd0d000d0, 0x7d7d007d, 0x89890089, 0x97970097, 0x5b5b005b, 0x95950095,
+ 0xffff00ff, 0xd2d200d2, 0xc4c400c4, 0x48480048, 0xf7f700f7, 0xdbdb00db,
+ 0x03030003, 0xdada00da, 0x3f3f003f, 0x94940094, 0x5c5c005c, 0x02020002,
+ 0x4a4a004a, 0x33330033, 0x67670067, 0xf3f300f3, 0x7f7f007f, 0xe2e200e2,
+ 0x9b9b009b, 0x26260026, 0x37370037, 0x3b3b003b, 0x96960096, 0x4b4b004b,
+ 0xbebe00be, 0x2e2e002e, 0x79790079, 0x8c8c008c, 0x6e6e006e, 0x8e8e008e,
+ 0xf5f500f5, 0xb6b600b6, 0xfdfd00fd, 0x59590059, 0x98980098, 0x6a6a006a,
+ 0x46460046, 0xbaba00ba, 0x25250025, 0x42420042, 0xa2a200a2, 0xfafa00fa,
+ 0x07070007, 0x55550055, 0xeeee00ee, 0x0a0a000a, 0x49490049, 0x68680068,
+ 0x38380038, 0xa4a400a4, 0x28280028, 0x7b7b007b, 0xc9c900c9, 0xc1c100c1,
+ 0xe3e300e3, 0xf4f400f4, 0xc7c700c7, 0x9e9e009e
+ };
+
+ private static final int SBOX2_0222[] = {
+ 0x00e0e0e0, 0x00050505, 0x00585858, 0x00d9d9d9, 0x00676767, 0x004e4e4e,
+ 0x00818181, 0x00cbcbcb, 0x00c9c9c9, 0x000b0b0b, 0x00aeaeae, 0x006a6a6a,
+ 0x00d5d5d5, 0x00181818, 0x005d5d5d, 0x00828282, 0x00464646, 0x00dfdfdf,
+ 0x00d6d6d6, 0x00272727, 0x008a8a8a, 0x00323232, 0x004b4b4b, 0x00424242,
+ 0x00dbdbdb, 0x001c1c1c, 0x009e9e9e, 0x009c9c9c, 0x003a3a3a, 0x00cacaca,
+ 0x00252525, 0x007b7b7b, 0x000d0d0d, 0x00717171, 0x005f5f5f, 0x001f1f1f,
+ 0x00f8f8f8, 0x00d7d7d7, 0x003e3e3e, 0x009d9d9d, 0x007c7c7c, 0x00606060,
+ 0x00b9b9b9, 0x00bebebe, 0x00bcbcbc, 0x008b8b8b, 0x00161616, 0x00343434,
+ 0x004d4d4d, 0x00c3c3c3, 0x00727272, 0x00959595, 0x00ababab, 0x008e8e8e,
+ 0x00bababa, 0x007a7a7a, 0x00b3b3b3, 0x00020202, 0x00b4b4b4, 0x00adadad,
+ 0x00a2a2a2, 0x00acacac, 0x00d8d8d8, 0x009a9a9a, 0x00171717, 0x001a1a1a,
+ 0x00353535, 0x00cccccc, 0x00f7f7f7, 0x00999999, 0x00616161, 0x005a5a5a,
+ 0x00e8e8e8, 0x00242424, 0x00565656, 0x00404040, 0x00e1e1e1, 0x00636363,
+ 0x00090909, 0x00333333, 0x00bfbfbf, 0x00989898, 0x00979797, 0x00858585,
+ 0x00686868, 0x00fcfcfc, 0x00ececec, 0x000a0a0a, 0x00dadada, 0x006f6f6f,
+ 0x00535353, 0x00626262, 0x00a3a3a3, 0x002e2e2e, 0x00080808, 0x00afafaf,
+ 0x00282828, 0x00b0b0b0, 0x00747474, 0x00c2c2c2, 0x00bdbdbd, 0x00363636,
+ 0x00222222, 0x00383838, 0x00646464, 0x001e1e1e, 0x00393939, 0x002c2c2c,
+ 0x00a6a6a6, 0x00303030, 0x00e5e5e5, 0x00444444, 0x00fdfdfd, 0x00888888,
+ 0x009f9f9f, 0x00656565, 0x00878787, 0x006b6b6b, 0x00f4f4f4, 0x00232323,
+ 0x00484848, 0x00101010, 0x00d1d1d1, 0x00515151, 0x00c0c0c0, 0x00f9f9f9,
+ 0x00d2d2d2, 0x00a0a0a0, 0x00555555, 0x00a1a1a1, 0x00414141, 0x00fafafa,
+ 0x00434343, 0x00131313, 0x00c4c4c4, 0x002f2f2f, 0x00a8a8a8, 0x00b6b6b6,
+ 0x003c3c3c, 0x002b2b2b, 0x00c1c1c1, 0x00ffffff, 0x00c8c8c8, 0x00a5a5a5,
+ 0x00202020, 0x00898989, 0x00000000, 0x00909090, 0x00474747, 0x00efefef,
+ 0x00eaeaea, 0x00b7b7b7, 0x00151515, 0x00060606, 0x00cdcdcd, 0x00b5b5b5,
+ 0x00121212, 0x007e7e7e, 0x00bbbbbb, 0x00292929, 0x000f0f0f, 0x00b8b8b8,
+ 0x00070707, 0x00040404, 0x009b9b9b, 0x00949494, 0x00212121, 0x00666666,
+ 0x00e6e6e6, 0x00cecece, 0x00ededed, 0x00e7e7e7, 0x003b3b3b, 0x00fefefe,
+ 0x007f7f7f, 0x00c5c5c5, 0x00a4a4a4, 0x00373737, 0x00b1b1b1, 0x004c4c4c,
+ 0x00919191, 0x006e6e6e, 0x008d8d8d, 0x00767676, 0x00030303, 0x002d2d2d,
+ 0x00dedede, 0x00969696, 0x00262626, 0x007d7d7d, 0x00c6c6c6, 0x005c5c5c,
+ 0x00d3d3d3, 0x00f2f2f2, 0x004f4f4f, 0x00191919, 0x003f3f3f, 0x00dcdcdc,
+ 0x00797979, 0x001d1d1d, 0x00525252, 0x00ebebeb, 0x00f3f3f3, 0x006d6d6d,
+ 0x005e5e5e, 0x00fbfbfb, 0x00696969, 0x00b2b2b2, 0x00f0f0f0, 0x00313131,
+ 0x000c0c0c, 0x00d4d4d4, 0x00cfcfcf, 0x008c8c8c, 0x00e2e2e2, 0x00757575,
+ 0x00a9a9a9, 0x004a4a4a, 0x00575757, 0x00848484, 0x00111111, 0x00454545,
+ 0x001b1b1b, 0x00f5f5f5, 0x00e4e4e4, 0x000e0e0e, 0x00737373, 0x00aaaaaa,
+ 0x00f1f1f1, 0x00dddddd, 0x00595959, 0x00141414, 0x006c6c6c, 0x00929292,
+ 0x00545454, 0x00d0d0d0, 0x00787878, 0x00707070, 0x00e3e3e3, 0x00494949,
+ 0x00808080, 0x00505050, 0x00a7a7a7, 0x00f6f6f6, 0x00777777, 0x00939393,
+ 0x00868686, 0x00838383, 0x002a2a2a, 0x00c7c7c7, 0x005b5b5b, 0x00e9e9e9,
+ 0x00eeeeee, 0x008f8f8f, 0x00010101, 0x003d3d3d
+ };
+
+ private static final int SBOX3_3033[] = {
+ 0x38003838, 0x41004141, 0x16001616, 0x76007676, 0xd900d9d9, 0x93009393,
+ 0x60006060, 0xf200f2f2, 0x72007272, 0xc200c2c2, 0xab00abab, 0x9a009a9a,
+ 0x75007575, 0x06000606, 0x57005757, 0xa000a0a0, 0x91009191, 0xf700f7f7,
+ 0xb500b5b5, 0xc900c9c9, 0xa200a2a2, 0x8c008c8c, 0xd200d2d2, 0x90009090,
+ 0xf600f6f6, 0x07000707, 0xa700a7a7, 0x27002727, 0x8e008e8e, 0xb200b2b2,
+ 0x49004949, 0xde00dede, 0x43004343, 0x5c005c5c, 0xd700d7d7, 0xc700c7c7,
+ 0x3e003e3e, 0xf500f5f5, 0x8f008f8f, 0x67006767, 0x1f001f1f, 0x18001818,
+ 0x6e006e6e, 0xaf00afaf, 0x2f002f2f, 0xe200e2e2, 0x85008585, 0x0d000d0d,
+ 0x53005353, 0xf000f0f0, 0x9c009c9c, 0x65006565, 0xea00eaea, 0xa300a3a3,
+ 0xae00aeae, 0x9e009e9e, 0xec00ecec, 0x80008080, 0x2d002d2d, 0x6b006b6b,
+ 0xa800a8a8, 0x2b002b2b, 0x36003636, 0xa600a6a6, 0xc500c5c5, 0x86008686,
+ 0x4d004d4d, 0x33003333, 0xfd00fdfd, 0x66006666, 0x58005858, 0x96009696,
+ 0x3a003a3a, 0x09000909, 0x95009595, 0x10001010, 0x78007878, 0xd800d8d8,
+ 0x42004242, 0xcc00cccc, 0xef00efef, 0x26002626, 0xe500e5e5, 0x61006161,
+ 0x1a001a1a, 0x3f003f3f, 0x3b003b3b, 0x82008282, 0xb600b6b6, 0xdb00dbdb,
+ 0xd400d4d4, 0x98009898, 0xe800e8e8, 0x8b008b8b, 0x02000202, 0xeb00ebeb,
+ 0x0a000a0a, 0x2c002c2c, 0x1d001d1d, 0xb000b0b0, 0x6f006f6f, 0x8d008d8d,
+ 0x88008888, 0x0e000e0e, 0x19001919, 0x87008787, 0x4e004e4e, 0x0b000b0b,
+ 0xa900a9a9, 0x0c000c0c, 0x79007979, 0x11001111, 0x7f007f7f, 0x22002222,
+ 0xe700e7e7, 0x59005959, 0xe100e1e1, 0xda00dada, 0x3d003d3d, 0xc800c8c8,
+ 0x12001212, 0x04000404, 0x74007474, 0x54005454, 0x30003030, 0x7e007e7e,
+ 0xb400b4b4, 0x28002828, 0x55005555, 0x68006868, 0x50005050, 0xbe00bebe,
+ 0xd000d0d0, 0xc400c4c4, 0x31003131, 0xcb00cbcb, 0x2a002a2a, 0xad00adad,
+ 0x0f000f0f, 0xca00caca, 0x70007070, 0xff00ffff, 0x32003232, 0x69006969,
+ 0x08000808, 0x62006262, 0x00000000, 0x24002424, 0xd100d1d1, 0xfb00fbfb,
+ 0xba00baba, 0xed00eded, 0x45004545, 0x81008181, 0x73007373, 0x6d006d6d,
+ 0x84008484, 0x9f009f9f, 0xee00eeee, 0x4a004a4a, 0xc300c3c3, 0x2e002e2e,
+ 0xc100c1c1, 0x01000101, 0xe600e6e6, 0x25002525, 0x48004848, 0x99009999,
+ 0xb900b9b9, 0xb300b3b3, 0x7b007b7b, 0xf900f9f9, 0xce00cece, 0xbf00bfbf,
+ 0xdf00dfdf, 0x71007171, 0x29002929, 0xcd00cdcd, 0x6c006c6c, 0x13001313,
+ 0x64006464, 0x9b009b9b, 0x63006363, 0x9d009d9d, 0xc000c0c0, 0x4b004b4b,
+ 0xb700b7b7, 0xa500a5a5, 0x89008989, 0x5f005f5f, 0xb100b1b1, 0x17001717,
+ 0xf400f4f4, 0xbc00bcbc, 0xd300d3d3, 0x46004646, 0xcf00cfcf, 0x37003737,
+ 0x5e005e5e, 0x47004747, 0x94009494, 0xfa00fafa, 0xfc00fcfc, 0x5b005b5b,
+ 0x97009797, 0xfe00fefe, 0x5a005a5a, 0xac00acac, 0x3c003c3c, 0x4c004c4c,
+ 0x03000303, 0x35003535, 0xf300f3f3, 0x23002323, 0xb800b8b8, 0x5d005d5d,
+ 0x6a006a6a, 0x92009292, 0xd500d5d5, 0x21002121, 0x44004444, 0x51005151,
+ 0xc600c6c6, 0x7d007d7d, 0x39003939, 0x83008383, 0xdc00dcdc, 0xaa00aaaa,
+ 0x7c007c7c, 0x77007777, 0x56005656, 0x05000505, 0x1b001b1b, 0xa400a4a4,
+ 0x15001515, 0x34003434, 0x1e001e1e, 0x1c001c1c, 0xf800f8f8, 0x52005252,
+ 0x20002020, 0x14001414, 0xe900e9e9, 0xbd00bdbd, 0xdd00dddd, 0xe400e4e4,
+ 0xa100a1a1, 0xe000e0e0, 0x8a008a8a, 0xf100f1f1, 0xd600d6d6, 0x7a007a7a,
+ 0xbb00bbbb, 0xe300e3e3, 0x40004040, 0x4f004f4f
+ };
+
+ private static int rightRotate(int x, int s)
+ {
+ return (((x) >>> (s)) + ((x) << (32 - s)));
+ }
+
+ private static int leftRotate(int x, int s)
+ {
+ return ((x) << (s)) + ((x) >>> (32 - s));
+ }
+
+ private static void roldq(int rot, int[] ki, int ioff,
+ int[] ko, int ooff)
+ {
+ ko[0 + ooff] = (ki[0 + ioff] << rot) | (ki[1 + ioff] >>> (32 - rot));
+ ko[1 + ooff] = (ki[1 + ioff] << rot) | (ki[2 + ioff] >>> (32 - rot));
+ ko[2 + ooff] = (ki[2 + ioff] << rot) | (ki[3 + ioff] >>> (32 - rot));
+ ko[3 + ooff] = (ki[3 + ioff] << rot) | (ki[0 + ioff] >>> (32 - rot));
+ ki[0 + ioff] = ko[0 + ooff];
+ ki[1 + ioff] = ko[1 + ooff];
+ ki[2 + ioff] = ko[2 + ooff];
+ ki[3 + ioff] = ko[3 + ooff];
+ }
+
+ private static void decroldq(int rot, int[] ki, int ioff,
+ int[] ko, int ooff)
+ {
+ ko[2 + ooff] = (ki[0 + ioff] << rot) | (ki[1 + ioff] >>> (32 - rot));
+ ko[3 + ooff] = (ki[1 + ioff] << rot) | (ki[2 + ioff] >>> (32 - rot));
+ ko[0 + ooff] = (ki[2 + ioff] << rot) | (ki[3 + ioff] >>> (32 - rot));
+ ko[1 + ooff] = (ki[3 + ioff] << rot) | (ki[0 + ioff] >>> (32 - rot));
+ ki[0 + ioff] = ko[2 + ooff];
+ ki[1 + ioff] = ko[3 + ooff];
+ ki[2 + ioff] = ko[0 + ooff];
+ ki[3 + ioff] = ko[1 + ooff];
+ }
+
+ private static void roldqo32(int rot, int[] ki, int ioff,
+ int[] ko, int ooff)
+ {
+ ko[0 + ooff] = (ki[1 + ioff] << (rot - 32)) | (ki[2 + ioff] >>> (64 - rot));
+ ko[1 + ooff] = (ki[2 + ioff] << (rot - 32)) | (ki[3 + ioff] >>> (64 - rot));
+ ko[2 + ooff] = (ki[3 + ioff] << (rot - 32)) | (ki[0 + ioff] >>> (64 - rot));
+ ko[3 + ooff] = (ki[0 + ioff] << (rot - 32)) | (ki[1 + ioff] >>> (64 - rot));
+ ki[0 + ioff] = ko[0 + ooff];
+ ki[1 + ioff] = ko[1 + ooff];
+ ki[2 + ioff] = ko[2 + ooff];
+ ki[3 + ioff] = ko[3 + ooff];
+ }
+
+ private static void decroldqo32(int rot, int[] ki, int ioff,
+ int[] ko, int ooff)
+ {
+ ko[2 + ooff] = (ki[1 + ioff] << (rot - 32)) | (ki[2 + ioff] >>> (64 - rot));
+ ko[3 + ooff] = (ki[2 + ioff] << (rot - 32)) | (ki[3 + ioff] >>> (64 - rot));
+ ko[0 + ooff] = (ki[3 + ioff] << (rot - 32)) | (ki[0 + ioff] >>> (64 - rot));
+ ko[1 + ooff] = (ki[0 + ioff] << (rot - 32)) | (ki[1 + ioff] >>> (64 - rot));
+ ki[0 + ioff] = ko[2 + ooff];
+ ki[1 + ioff] = ko[3 + ooff];
+ ki[2 + ioff] = ko[0 + ooff];
+ ki[3 + ioff] = ko[1 + ooff];
+ }
+
+ private int bytes2int(byte[] src, int offset)
+ {
+ int word = 0;
+
+ for (int i = 0; i < 4; i++)
+ {
+ word = (word << 8) + (src[i + offset] & MASK8);
+ }
+ return word;
+ }
+
+ private void int2bytes(int word, byte[] dst, int offset)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ dst[(3 - i) + offset] = (byte)word;
+ word >>>= 8;
+ }
+ }
+
+ private void camelliaF2(int[] s, int[] skey, int keyoff)
+ {
+ int t1, t2, u, v;
+
+ t1 = s[0] ^ skey[0 + keyoff];
+ u = SBOX4_4404[t1 & MASK8];
+ u ^= SBOX3_3033[(t1 >>> 8) & MASK8];
+ u ^= SBOX2_0222[(t1 >>> 16) & MASK8];
+ u ^= SBOX1_1110[(t1 >>> 24) & MASK8];
+ t2 = s[1] ^ skey[1 + keyoff];
+ v = SBOX1_1110[t2 & MASK8];
+ v ^= SBOX4_4404[(t2 >>> 8) & MASK8];
+ v ^= SBOX3_3033[(t2 >>> 16) & MASK8];
+ v ^= SBOX2_0222[(t2 >>> 24) & MASK8];
+
+ s[2] ^= u ^ v;
+ s[3] ^= u ^ v ^ rightRotate(u, 8);
+
+ t1 = s[2] ^ skey[2 + keyoff];
+ u = SBOX4_4404[t1 & MASK8];
+ u ^= SBOX3_3033[(t1 >>> 8) & MASK8];
+ u ^= SBOX2_0222[(t1 >>> 16) & MASK8];
+ u ^= SBOX1_1110[(t1 >>> 24) & MASK8];
+ t2 = s[3] ^ skey[3 + keyoff];
+ v = SBOX1_1110[t2 & MASK8];
+ v ^= SBOX4_4404[(t2 >>> 8) & MASK8];
+ v ^= SBOX3_3033[(t2 >>> 16) & MASK8];
+ v ^= SBOX2_0222[(t2 >>> 24) & MASK8];
+
+ s[0] ^= u ^ v;
+ s[1] ^= u ^ v ^ rightRotate(u, 8);
+ }
+
+ private void camelliaFLs(int[] s, int[] fkey, int keyoff)
+ {
+
+ s[1] ^= leftRotate(s[0] & fkey[0 + keyoff], 1);
+ s[0] ^= fkey[1 + keyoff] | s[1];
+
+ s[2] ^= fkey[3 + keyoff] | s[3];
+ s[3] ^= leftRotate(fkey[2 + keyoff] & s[2], 1);
+ }
+
+ private void setKey(boolean forEncryption, byte[] key)
+ {
+ int[] k = new int[8];
+ int[] ka = new int[4];
+ int[] kb = new int[4];
+ int[] t = new int[4];
+
+ switch (key.length)
+ {
+ case 16:
+ _keyIs128 = true;
+ k[0] = bytes2int(key, 0);
+ k[1] = bytes2int(key, 4);
+ k[2] = bytes2int(key, 8);
+ k[3] = bytes2int(key, 12);
+ k[4] = k[5] = k[6] = k[7] = 0;
+ break;
+ case 24:
+ k[0] = bytes2int(key, 0);
+ k[1] = bytes2int(key, 4);
+ k[2] = bytes2int(key, 8);
+ k[3] = bytes2int(key, 12);
+ k[4] = bytes2int(key, 16);
+ k[5] = bytes2int(key, 20);
+ k[6] = ~k[4];
+ k[7] = ~k[5];
+ _keyIs128 = false;
+ break;
+ case 32:
+ k[0] = bytes2int(key, 0);
+ k[1] = bytes2int(key, 4);
+ k[2] = bytes2int(key, 8);
+ k[3] = bytes2int(key, 12);
+ k[4] = bytes2int(key, 16);
+ k[5] = bytes2int(key, 20);
+ k[6] = bytes2int(key, 24);
+ k[7] = bytes2int(key, 28);
+ _keyIs128 = false;
+ break;
+ default:
+ throw new
+ IllegalArgumentException("key sizes are only 16/24/32 bytes.");
+ }
+
+ for (int i = 0; i < 4; i++)
+ {
+ ka[i] = k[i] ^ k[i + 4];
+ }
+ /* compute KA */
+ camelliaF2(ka, SIGMA, 0);
+ for (int i = 0; i < 4; i++)
+ {
+ ka[i] ^= k[i];
+ }
+ camelliaF2(ka, SIGMA, 4);
+
+ if (_keyIs128)
+ {
+ if (forEncryption)
+ {
+ /* KL dependant keys */
+ kw[0] = k[0];
+ kw[1] = k[1];
+ kw[2] = k[2];
+ kw[3] = k[3];
+ roldq(15, k, 0, subkey, 4);
+ roldq(30, k, 0, subkey, 12);
+ roldq(15, k, 0, t, 0);
+ subkey[18] = t[2];
+ subkey[19] = t[3];
+ roldq(17, k, 0, ke, 4);
+ roldq(17, k, 0, subkey, 24);
+ roldq(17, k, 0, subkey, 32);
+ /* KA dependant keys */
+ subkey[0] = ka[0];
+ subkey[1] = ka[1];
+ subkey[2] = ka[2];
+ subkey[3] = ka[3];
+ roldq(15, ka, 0, subkey, 8);
+ roldq(15, ka, 0, ke, 0);
+ roldq(15, ka, 0, t, 0);
+ subkey[16] = t[0];
+ subkey[17] = t[1];
+ roldq(15, ka, 0, subkey, 20);
+ roldqo32(34, ka, 0, subkey, 28);
+ roldq(17, ka, 0, kw, 4);
+
+ }
+ else
+ { // decryption
+ /* KL dependant keys */
+ kw[4] = k[0];
+ kw[5] = k[1];
+ kw[6] = k[2];
+ kw[7] = k[3];
+ decroldq(15, k, 0, subkey, 28);
+ decroldq(30, k, 0, subkey, 20);
+ decroldq(15, k, 0, t, 0);
+ subkey[16] = t[0];
+ subkey[17] = t[1];
+ decroldq(17, k, 0, ke, 0);
+ decroldq(17, k, 0, subkey, 8);
+ decroldq(17, k, 0, subkey, 0);
+ /* KA dependant keys */
+ subkey[34] = ka[0];
+ subkey[35] = ka[1];
+ subkey[32] = ka[2];
+ subkey[33] = ka[3];
+ decroldq(15, ka, 0, subkey, 24);
+ decroldq(15, ka, 0, ke, 4);
+ decroldq(15, ka, 0, t, 0);
+ subkey[18] = t[2];
+ subkey[19] = t[3];
+ decroldq(15, ka, 0, subkey, 12);
+ decroldqo32(34, ka, 0, subkey, 4);
+ roldq(17, ka, 0, kw, 0);
+ }
+ }
+ else
+ { // 192bit or 256bit
+ /* compute KB */
+ for (int i = 0; i < 4; i++)
+ {
+ kb[i] = ka[i] ^ k[i + 4];
+ }
+ camelliaF2(kb, SIGMA, 8);
+
+ if (forEncryption)
+ {
+ /* KL dependant keys */
+ kw[0] = k[0];
+ kw[1] = k[1];
+ kw[2] = k[2];
+ kw[3] = k[3];
+ roldqo32(45, k, 0, subkey, 16);
+ roldq(15, k, 0, ke, 4);
+ roldq(17, k, 0, subkey, 32);
+ roldqo32(34, k, 0, subkey, 44);
+ /* KR dependant keys */
+ roldq(15, k, 4, subkey, 4);
+ roldq(15, k, 4, ke, 0);
+ roldq(30, k, 4, subkey, 24);
+ roldqo32(34, k, 4, subkey, 36);
+ /* KA dependant keys */
+ roldq(15, ka, 0, subkey, 8);
+ roldq(30, ka, 0, subkey, 20);
+ /* 32bit rotation */
+ ke[8] = ka[1];
+ ke[9] = ka[2];
+ ke[10] = ka[3];
+ ke[11] = ka[0];
+ roldqo32(49, ka, 0, subkey, 40);
+
+ /* KB dependant keys */
+ subkey[0] = kb[0];
+ subkey[1] = kb[1];
+ subkey[2] = kb[2];
+ subkey[3] = kb[3];
+ roldq(30, kb, 0, subkey, 12);
+ roldq(30, kb, 0, subkey, 28);
+ roldqo32(51, kb, 0, kw, 4);
+
+ }
+ else
+ { // decryption
+ /* KL dependant keys */
+ kw[4] = k[0];
+ kw[5] = k[1];
+ kw[6] = k[2];
+ kw[7] = k[3];
+ decroldqo32(45, k, 0, subkey, 28);
+ decroldq(15, k, 0, ke, 4);
+ decroldq(17, k, 0, subkey, 12);
+ decroldqo32(34, k, 0, subkey, 0);
+ /* KR dependant keys */
+ decroldq(15, k, 4, subkey, 40);
+ decroldq(15, k, 4, ke, 8);
+ decroldq(30, k, 4, subkey, 20);
+ decroldqo32(34, k, 4, subkey, 8);
+ /* KA dependant keys */
+ decroldq(15, ka, 0, subkey, 36);
+ decroldq(30, ka, 0, subkey, 24);
+ /* 32bit rotation */
+ ke[2] = ka[1];
+ ke[3] = ka[2];
+ ke[0] = ka[3];
+ ke[1] = ka[0];
+ decroldqo32(49, ka, 0, subkey, 4);
+
+ /* KB dependant keys */
+ subkey[46] = kb[0];
+ subkey[47] = kb[1];
+ subkey[44] = kb[2];
+ subkey[45] = kb[3];
+ decroldq(30, kb, 0, subkey, 32);
+ decroldq(30, kb, 0, subkey, 16);
+ roldqo32(51, kb, 0, kw, 0);
+ }
+ }
+ }
+
+ private int processBlock128(byte[] in, int inOff,
+ byte[] out, int outOff)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ state[i] = bytes2int(in, inOff + (i * 4));
+ state[i] ^= kw[i];
+ }
+
+ camelliaF2(state, subkey, 0);
+ camelliaF2(state, subkey, 4);
+ camelliaF2(state, subkey, 8);
+ camelliaFLs(state, ke, 0);
+ camelliaF2(state, subkey, 12);
+ camelliaF2(state, subkey, 16);
+ camelliaF2(state, subkey, 20);
+ camelliaFLs(state, ke, 4);
+ camelliaF2(state, subkey, 24);
+ camelliaF2(state, subkey, 28);
+ camelliaF2(state, subkey, 32);
+
+ state[2] ^= kw[4];
+ state[3] ^= kw[5];
+ state[0] ^= kw[6];
+ state[1] ^= kw[7];
+
+ int2bytes(state[2], out, outOff);
+ int2bytes(state[3], out, outOff + 4);
+ int2bytes(state[0], out, outOff + 8);
+ int2bytes(state[1], out, outOff + 12);
+
+ return BLOCK_SIZE;
+ }
+
+ private int processBlock192or256(byte[] in, int inOff,
+ byte[] out, int outOff)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ state[i] = bytes2int(in, inOff + (i * 4));
+ state[i] ^= kw[i];
+ }
+
+ camelliaF2(state, subkey, 0);
+ camelliaF2(state, subkey, 4);
+ camelliaF2(state, subkey, 8);
+ camelliaFLs(state, ke, 0);
+ camelliaF2(state, subkey, 12);
+ camelliaF2(state, subkey, 16);
+ camelliaF2(state, subkey, 20);
+ camelliaFLs(state, ke, 4);
+ camelliaF2(state, subkey, 24);
+ camelliaF2(state, subkey, 28);
+ camelliaF2(state, subkey, 32);
+ camelliaFLs(state, ke, 8);
+ camelliaF2(state, subkey, 36);
+ camelliaF2(state, subkey, 40);
+ camelliaF2(state, subkey, 44);
+
+ state[2] ^= kw[4];
+ state[3] ^= kw[5];
+ state[0] ^= kw[6];
+ state[1] ^= kw[7];
+
+ int2bytes(state[2], out, outOff);
+ int2bytes(state[3], out, outOff + 4);
+ int2bytes(state[0], out, outOff + 8);
+ int2bytes(state[1], out, outOff + 12);
+ return BLOCK_SIZE;
+ }
+
+ public CamelliaEngine()
+ {
+ }
+
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ if (!(params instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("only simple KeyParameter expected.");
+ }
+
+ setKey(forEncryption, ((KeyParameter)params).getKey());
+ initialised = true;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Camellia";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException("Camellia engine not initialised");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ if (_keyIs128)
+ {
+ return processBlock128(in, inOff, out, outOff);
+ }
+ else
+ {
+ return processBlock192or256(in, inOff, out, outOff);
+ }
+ }
+
+ public void reset()
+ {
+ // nothing
+
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/CamelliaLightEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/CamelliaLightEngine.java
new file mode 100644
index 00000000..bc8dea4a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/CamelliaLightEngine.java
@@ -0,0 +1,592 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+
+/**
+ * Camellia - based on RFC 3713, smaller implementation, about half the size of CamelliaEngine.
+ */
+
+public class CamelliaLightEngine
+ implements BlockCipher
+{
+ private static final int BLOCK_SIZE = 16;
+ private static final int MASK8 = 0xff;
+ private boolean initialized;
+ private boolean _keyis128;
+
+ private int[] subkey = new int[24 * 4];
+ private int[] kw = new int[4 * 2]; // for whitening
+ private int[] ke = new int[6 * 2]; // for FL and FL^(-1)
+ private int[] state = new int[4]; // for encryption and decryption
+
+ private static final int SIGMA[] = {
+ 0xa09e667f, 0x3bcc908b,
+ 0xb67ae858, 0x4caa73b2,
+ 0xc6ef372f, 0xe94f82be,
+ 0x54ff53a5, 0xf1d36f1c,
+ 0x10e527fa, 0xde682d1d,
+ 0xb05688c2, 0xb3e6c1fd
+ };
+
+ /*
+ *
+ * S-box data
+ *
+ */
+ private static final byte SBOX1[] = {
+ (byte)112, (byte)130, (byte)44, (byte)236,
+ (byte)179, (byte)39, (byte)192, (byte)229,
+ (byte)228, (byte)133, (byte)87, (byte)53,
+ (byte)234, (byte)12, (byte)174, (byte)65,
+ (byte)35, (byte)239, (byte)107, (byte)147,
+ (byte)69, (byte)25, (byte)165, (byte)33,
+ (byte)237, (byte)14, (byte)79, (byte)78,
+ (byte)29, (byte)101, (byte)146, (byte)189,
+ (byte)134, (byte)184, (byte)175, (byte)143,
+ (byte)124, (byte)235, (byte)31, (byte)206,
+ (byte)62, (byte)48, (byte)220, (byte)95,
+ (byte)94, (byte)197, (byte)11, (byte)26,
+ (byte)166, (byte)225, (byte)57, (byte)202,
+ (byte)213, (byte)71, (byte)93, (byte)61,
+ (byte)217, (byte)1, (byte)90, (byte)214,
+ (byte)81, (byte)86, (byte)108, (byte)77,
+ (byte)139, (byte)13, (byte)154, (byte)102,
+ (byte)251, (byte)204, (byte)176, (byte)45,
+ (byte)116, (byte)18, (byte)43, (byte)32,
+ (byte)240, (byte)177, (byte)132, (byte)153,
+ (byte)223, (byte)76, (byte)203, (byte)194,
+ (byte)52, (byte)126, (byte)118, (byte)5,
+ (byte)109, (byte)183, (byte)169, (byte)49,
+ (byte)209, (byte)23, (byte)4, (byte)215,
+ (byte)20, (byte)88, (byte)58, (byte)97,
+ (byte)222, (byte)27, (byte)17, (byte)28,
+ (byte)50, (byte)15, (byte)156, (byte)22,
+ (byte)83, (byte)24, (byte)242, (byte)34,
+ (byte)254, (byte)68, (byte)207, (byte)178,
+ (byte)195, (byte)181, (byte)122, (byte)145,
+ (byte)36, (byte)8, (byte)232, (byte)168,
+ (byte)96, (byte)252, (byte)105, (byte)80,
+ (byte)170, (byte)208, (byte)160, (byte)125,
+ (byte)161, (byte)137, (byte)98, (byte)151,
+ (byte)84, (byte)91, (byte)30, (byte)149,
+ (byte)224, (byte)255, (byte)100, (byte)210,
+ (byte)16, (byte)196, (byte)0, (byte)72,
+ (byte)163, (byte)247, (byte)117, (byte)219,
+ (byte)138, (byte)3, (byte)230, (byte)218,
+ (byte)9, (byte)63, (byte)221, (byte)148,
+ (byte)135, (byte)92, (byte)131, (byte)2,
+ (byte)205, (byte)74, (byte)144, (byte)51,
+ (byte)115, (byte)103, (byte)246, (byte)243,
+ (byte)157, (byte)127, (byte)191, (byte)226,
+ (byte)82, (byte)155, (byte)216, (byte)38,
+ (byte)200, (byte)55, (byte)198, (byte)59,
+ (byte)129, (byte)150, (byte)111, (byte)75,
+ (byte)19, (byte)190, (byte)99, (byte)46,
+ (byte)233, (byte)121, (byte)167, (byte)140,
+ (byte)159, (byte)110, (byte)188, (byte)142,
+ (byte)41, (byte)245, (byte)249, (byte)182,
+ (byte)47, (byte)253, (byte)180, (byte)89,
+ (byte)120, (byte)152, (byte)6, (byte)106,
+ (byte)231, (byte)70, (byte)113, (byte)186,
+ (byte)212, (byte)37, (byte)171, (byte)66,
+ (byte)136, (byte)162, (byte)141, (byte)250,
+ (byte)114, (byte)7, (byte)185, (byte)85,
+ (byte)248, (byte)238, (byte)172, (byte)10,
+ (byte)54, (byte)73, (byte)42, (byte)104,
+ (byte)60, (byte)56, (byte)241, (byte)164,
+ (byte)64, (byte)40, (byte)211, (byte)123,
+ (byte)187, (byte)201, (byte)67, (byte)193,
+ (byte)21, (byte)227, (byte)173, (byte)244,
+ (byte)119, (byte)199, (byte)128, (byte)158
+ };
+
+ private static int rightRotate(int x, int s)
+ {
+ return (((x) >>> (s)) + ((x) << (32 - s)));
+ }
+
+ private static int leftRotate(int x, int s)
+ {
+ return ((x) << (s)) + ((x) >>> (32 - s));
+ }
+
+ private static void roldq(int rot, int[] ki, int ioff,
+ int[] ko, int ooff)
+ {
+ ko[0 + ooff] = (ki[0 + ioff] << rot) | (ki[1 + ioff] >>> (32 - rot));
+ ko[1 + ooff] = (ki[1 + ioff] << rot) | (ki[2 + ioff] >>> (32 - rot));
+ ko[2 + ooff] = (ki[2 + ioff] << rot) | (ki[3 + ioff] >>> (32 - rot));
+ ko[3 + ooff] = (ki[3 + ioff] << rot) | (ki[0 + ioff] >>> (32 - rot));
+ ki[0 + ioff] = ko[0 + ooff];
+ ki[1 + ioff] = ko[1 + ooff];
+ ki[2 + ioff] = ko[2 + ooff];
+ ki[3 + ioff] = ko[3 + ooff];
+ }
+
+ private static void decroldq(int rot, int[] ki, int ioff,
+ int[] ko, int ooff)
+ {
+ ko[2 + ooff] = (ki[0 + ioff] << rot) | (ki[1 + ioff] >>> (32 - rot));
+ ko[3 + ooff] = (ki[1 + ioff] << rot) | (ki[2 + ioff] >>> (32 - rot));
+ ko[0 + ooff] = (ki[2 + ioff] << rot) | (ki[3 + ioff] >>> (32 - rot));
+ ko[1 + ooff] = (ki[3 + ioff] << rot) | (ki[0 + ioff] >>> (32 - rot));
+ ki[0 + ioff] = ko[2 + ooff];
+ ki[1 + ioff] = ko[3 + ooff];
+ ki[2 + ioff] = ko[0 + ooff];
+ ki[3 + ioff] = ko[1 + ooff];
+ }
+
+ private static void roldqo32(int rot, int[] ki, int ioff,
+ int[] ko, int ooff)
+ {
+ ko[0 + ooff] = (ki[1 + ioff] << (rot - 32)) | (ki[2 + ioff] >>> (64 - rot));
+ ko[1 + ooff] = (ki[2 + ioff] << (rot - 32)) | (ki[3 + ioff] >>> (64 - rot));
+ ko[2 + ooff] = (ki[3 + ioff] << (rot - 32)) | (ki[0 + ioff] >>> (64 - rot));
+ ko[3 + ooff] = (ki[0 + ioff] << (rot - 32)) | (ki[1 + ioff] >>> (64 - rot));
+ ki[0 + ioff] = ko[0 + ooff];
+ ki[1 + ioff] = ko[1 + ooff];
+ ki[2 + ioff] = ko[2 + ooff];
+ ki[3 + ioff] = ko[3 + ooff];
+ }
+
+ private static void decroldqo32(int rot, int[] ki, int ioff,
+ int[] ko, int ooff)
+ {
+ ko[2 + ooff] = (ki[1 + ioff] << (rot - 32)) | (ki[2 + ioff] >>> (64 - rot));
+ ko[3 + ooff] = (ki[2 + ioff] << (rot - 32)) | (ki[3 + ioff] >>> (64 - rot));
+ ko[0 + ooff] = (ki[3 + ioff] << (rot - 32)) | (ki[0 + ioff] >>> (64 - rot));
+ ko[1 + ooff] = (ki[0 + ioff] << (rot - 32)) | (ki[1 + ioff] >>> (64 - rot));
+ ki[0 + ioff] = ko[2 + ooff];
+ ki[1 + ioff] = ko[3 + ooff];
+ ki[2 + ioff] = ko[0 + ooff];
+ ki[3 + ioff] = ko[1 + ooff];
+ }
+
+ private int bytes2int(byte[] src, int offset)
+ {
+ int word = 0;
+
+ for (int i = 0; i < 4; i++)
+ {
+ word = (word << 8) + (src[i + offset] & MASK8);
+ }
+ return word;
+ }
+
+ private void int2bytes(int word, byte[] dst, int offset)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ dst[(3 - i) + offset] = (byte)word;
+ word >>>= 8;
+ }
+ }
+
+ private byte lRot8(byte v, int rot)
+ {
+ return (byte)((v << rot) | ((v & 0xff) >>> (8 - rot)));
+ }
+
+ private int sbox2(int x)
+ {
+ return (lRot8(SBOX1[x], 1) & MASK8);
+ }
+
+ private int sbox3(int x)
+ {
+ return (lRot8(SBOX1[x], 7) & MASK8);
+ }
+
+ private int sbox4(int x)
+ {
+ return (SBOX1[((int)lRot8((byte)x, 1) & MASK8)] & MASK8);
+ }
+
+ private void camelliaF2(int[] s, int[] skey, int keyoff)
+ {
+ int t1, t2, u, v;
+
+ t1 = s[0] ^ skey[0 + keyoff];
+ u = sbox4((t1 & MASK8));
+ u |= (sbox3(((t1 >>> 8) & MASK8)) << 8);
+ u |= (sbox2(((t1 >>> 16) & MASK8)) << 16);
+ u |= ((int)(SBOX1[((t1 >>> 24) & MASK8)] & MASK8) << 24);
+
+ t2 = s[1] ^ skey[1 + keyoff];
+ v = (int)SBOX1[(t2 & MASK8)] & MASK8;
+ v |= (sbox4(((t2 >>> 8) & MASK8)) << 8);
+ v |= (sbox3(((t2 >>> 16) & MASK8)) << 16);
+ v |= (sbox2(((t2 >>> 24) & MASK8)) << 24);
+
+ v = leftRotate(v, 8);
+ u ^= v;
+ v = leftRotate(v, 8) ^ u;
+ u = rightRotate(u, 8) ^ v;
+ s[2] ^= leftRotate(v, 16) ^ u;
+ s[3] ^= leftRotate(u, 8);
+
+ t1 = s[2] ^ skey[2 + keyoff];
+ u = sbox4((t1 & MASK8));
+ u |= sbox3(((t1 >>> 8) & MASK8)) << 8;
+ u |= sbox2(((t1 >>> 16) & MASK8)) << 16;
+ u |= ((int)SBOX1[((t1 >>> 24) & MASK8)] & MASK8) << 24;
+
+ t2 = s[3] ^ skey[3 + keyoff];
+ v = ((int)SBOX1[(t2 & MASK8)] & MASK8);
+ v |= sbox4(((t2 >>> 8) & MASK8)) << 8;
+ v |= sbox3(((t2 >>> 16) & MASK8)) << 16;
+ v |= sbox2(((t2 >>> 24) & MASK8)) << 24;
+
+ v = leftRotate(v, 8);
+ u ^= v;
+ v = leftRotate(v, 8) ^ u;
+ u = rightRotate(u, 8) ^ v;
+ s[0] ^= leftRotate(v, 16) ^ u;
+ s[1] ^= leftRotate(u, 8);
+ }
+
+ private void camelliaFLs(int[] s, int[] fkey, int keyoff)
+ {
+
+ s[1] ^= leftRotate(s[0] & fkey[0 + keyoff], 1);
+ s[0] ^= fkey[1 + keyoff] | s[1];
+
+ s[2] ^= fkey[3 + keyoff] | s[3];
+ s[3] ^= leftRotate(fkey[2 + keyoff] & s[2], 1);
+ }
+
+ private void setKey(boolean forEncryption, byte[] key)
+ {
+ int[] k = new int[8];
+ int[] ka = new int[4];
+ int[] kb = new int[4];
+ int[] t = new int[4];
+
+ switch (key.length)
+ {
+ case 16:
+ _keyis128 = true;
+ k[0] = bytes2int(key, 0);
+ k[1] = bytes2int(key, 4);
+ k[2] = bytes2int(key, 8);
+ k[3] = bytes2int(key, 12);
+ k[4] = k[5] = k[6] = k[7] = 0;
+ break;
+ case 24:
+ k[0] = bytes2int(key, 0);
+ k[1] = bytes2int(key, 4);
+ k[2] = bytes2int(key, 8);
+ k[3] = bytes2int(key, 12);
+ k[4] = bytes2int(key, 16);
+ k[5] = bytes2int(key, 20);
+ k[6] = ~k[4];
+ k[7] = ~k[5];
+ _keyis128 = false;
+ break;
+ case 32:
+ k[0] = bytes2int(key, 0);
+ k[1] = bytes2int(key, 4);
+ k[2] = bytes2int(key, 8);
+ k[3] = bytes2int(key, 12);
+ k[4] = bytes2int(key, 16);
+ k[5] = bytes2int(key, 20);
+ k[6] = bytes2int(key, 24);
+ k[7] = bytes2int(key, 28);
+ _keyis128 = false;
+ break;
+ default:
+ throw new
+ IllegalArgumentException("key sizes are only 16/24/32 bytes.");
+ }
+
+ for (int i = 0; i < 4; i++)
+ {
+ ka[i] = k[i] ^ k[i + 4];
+ }
+ /* compute KA */
+ camelliaF2(ka, SIGMA, 0);
+ for (int i = 0; i < 4; i++)
+ {
+ ka[i] ^= k[i];
+ }
+ camelliaF2(ka, SIGMA, 4);
+
+ if (_keyis128)
+ {
+ if (forEncryption)
+ {
+ /* KL dependant keys */
+ kw[0] = k[0];
+ kw[1] = k[1];
+ kw[2] = k[2];
+ kw[3] = k[3];
+ roldq(15, k, 0, subkey, 4);
+ roldq(30, k, 0, subkey, 12);
+ roldq(15, k, 0, t, 0);
+ subkey[18] = t[2];
+ subkey[19] = t[3];
+ roldq(17, k, 0, ke, 4);
+ roldq(17, k, 0, subkey, 24);
+ roldq(17, k, 0, subkey, 32);
+ /* KA dependant keys */
+ subkey[0] = ka[0];
+ subkey[1] = ka[1];
+ subkey[2] = ka[2];
+ subkey[3] = ka[3];
+ roldq(15, ka, 0, subkey, 8);
+ roldq(15, ka, 0, ke, 0);
+ roldq(15, ka, 0, t, 0);
+ subkey[16] = t[0];
+ subkey[17] = t[1];
+ roldq(15, ka, 0, subkey, 20);
+ roldqo32(34, ka, 0, subkey, 28);
+ roldq(17, ka, 0, kw, 4);
+
+ }
+ else
+ { // decryption
+ /* KL dependant keys */
+ kw[4] = k[0];
+ kw[5] = k[1];
+ kw[6] = k[2];
+ kw[7] = k[3];
+ decroldq(15, k, 0, subkey, 28);
+ decroldq(30, k, 0, subkey, 20);
+ decroldq(15, k, 0, t, 0);
+ subkey[16] = t[0];
+ subkey[17] = t[1];
+ decroldq(17, k, 0, ke, 0);
+ decroldq(17, k, 0, subkey, 8);
+ decroldq(17, k, 0, subkey, 0);
+ /* KA dependant keys */
+ subkey[34] = ka[0];
+ subkey[35] = ka[1];
+ subkey[32] = ka[2];
+ subkey[33] = ka[3];
+ decroldq(15, ka, 0, subkey, 24);
+ decroldq(15, ka, 0, ke, 4);
+ decroldq(15, ka, 0, t, 0);
+ subkey[18] = t[2];
+ subkey[19] = t[3];
+ decroldq(15, ka, 0, subkey, 12);
+ decroldqo32(34, ka, 0, subkey, 4);
+ roldq(17, ka, 0, kw, 0);
+ }
+ }
+ else
+ { // 192bit or 256bit
+ /* compute KB */
+ for (int i = 0; i < 4; i++)
+ {
+ kb[i] = ka[i] ^ k[i + 4];
+ }
+ camelliaF2(kb, SIGMA, 8);
+
+ if (forEncryption)
+ {
+ /* KL dependant keys */
+ kw[0] = k[0];
+ kw[1] = k[1];
+ kw[2] = k[2];
+ kw[3] = k[3];
+ roldqo32(45, k, 0, subkey, 16);
+ roldq(15, k, 0, ke, 4);
+ roldq(17, k, 0, subkey, 32);
+ roldqo32(34, k, 0, subkey, 44);
+ /* KR dependant keys */
+ roldq(15, k, 4, subkey, 4);
+ roldq(15, k, 4, ke, 0);
+ roldq(30, k, 4, subkey, 24);
+ roldqo32(34, k, 4, subkey, 36);
+ /* KA dependant keys */
+ roldq(15, ka, 0, subkey, 8);
+ roldq(30, ka, 0, subkey, 20);
+ /* 32bit rotation */
+ ke[8] = ka[1];
+ ke[9] = ka[2];
+ ke[10] = ka[3];
+ ke[11] = ka[0];
+ roldqo32(49, ka, 0, subkey, 40);
+
+ /* KB dependant keys */
+ subkey[0] = kb[0];
+ subkey[1] = kb[1];
+ subkey[2] = kb[2];
+ subkey[3] = kb[3];
+ roldq(30, kb, 0, subkey, 12);
+ roldq(30, kb, 0, subkey, 28);
+ roldqo32(51, kb, 0, kw, 4);
+
+ }
+ else
+ { // decryption
+ /* KL dependant keys */
+ kw[4] = k[0];
+ kw[5] = k[1];
+ kw[6] = k[2];
+ kw[7] = k[3];
+ decroldqo32(45, k, 0, subkey, 28);
+ decroldq(15, k, 0, ke, 4);
+ decroldq(17, k, 0, subkey, 12);
+ decroldqo32(34, k, 0, subkey, 0);
+ /* KR dependant keys */
+ decroldq(15, k, 4, subkey, 40);
+ decroldq(15, k, 4, ke, 8);
+ decroldq(30, k, 4, subkey, 20);
+ decroldqo32(34, k, 4, subkey, 8);
+ /* KA dependant keys */
+ decroldq(15, ka, 0, subkey, 36);
+ decroldq(30, ka, 0, subkey, 24);
+ /* 32bit rotation */
+ ke[2] = ka[1];
+ ke[3] = ka[2];
+ ke[0] = ka[3];
+ ke[1] = ka[0];
+ decroldqo32(49, ka, 0, subkey, 4);
+
+ /* KB dependant keys */
+ subkey[46] = kb[0];
+ subkey[47] = kb[1];
+ subkey[44] = kb[2];
+ subkey[45] = kb[3];
+ decroldq(30, kb, 0, subkey, 32);
+ decroldq(30, kb, 0, subkey, 16);
+ roldqo32(51, kb, 0, kw, 0);
+ }
+ }
+ }
+
+ private int processBlock128(byte[] in, int inOff,
+ byte[] out, int outOff)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ state[i] = bytes2int(in, inOff + (i * 4));
+ state[i] ^= kw[i];
+ }
+
+ camelliaF2(state, subkey, 0);
+ camelliaF2(state, subkey, 4);
+ camelliaF2(state, subkey, 8);
+ camelliaFLs(state, ke, 0);
+ camelliaF2(state, subkey, 12);
+ camelliaF2(state, subkey, 16);
+ camelliaF2(state, subkey, 20);
+ camelliaFLs(state, ke, 4);
+ camelliaF2(state, subkey, 24);
+ camelliaF2(state, subkey, 28);
+ camelliaF2(state, subkey, 32);
+
+ state[2] ^= kw[4];
+ state[3] ^= kw[5];
+ state[0] ^= kw[6];
+ state[1] ^= kw[7];
+
+ int2bytes(state[2], out, outOff);
+ int2bytes(state[3], out, outOff + 4);
+ int2bytes(state[0], out, outOff + 8);
+ int2bytes(state[1], out, outOff + 12);
+
+ return BLOCK_SIZE;
+ }
+
+ private int processBlock192or256(byte[] in, int inOff,
+ byte[] out, int outOff)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ state[i] = bytes2int(in, inOff + (i * 4));
+ state[i] ^= kw[i];
+ }
+
+ camelliaF2(state, subkey, 0);
+ camelliaF2(state, subkey, 4);
+ camelliaF2(state, subkey, 8);
+ camelliaFLs(state, ke, 0);
+ camelliaF2(state, subkey, 12);
+ camelliaF2(state, subkey, 16);
+ camelliaF2(state, subkey, 20);
+ camelliaFLs(state, ke, 4);
+ camelliaF2(state, subkey, 24);
+ camelliaF2(state, subkey, 28);
+ camelliaF2(state, subkey, 32);
+ camelliaFLs(state, ke, 8);
+ camelliaF2(state, subkey, 36);
+ camelliaF2(state, subkey, 40);
+ camelliaF2(state, subkey, 44);
+
+ state[2] ^= kw[4];
+ state[3] ^= kw[5];
+ state[0] ^= kw[6];
+ state[1] ^= kw[7];
+
+ int2bytes(state[2], out, outOff);
+ int2bytes(state[3], out, outOff + 4);
+ int2bytes(state[0], out, outOff + 8);
+ int2bytes(state[1], out, outOff + 12);
+ return BLOCK_SIZE;
+ }
+
+ public CamelliaLightEngine()
+ {
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Camellia";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public void init(boolean forEncryption, CipherParameters params)
+ {
+ if (!(params instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("only simple KeyParameter expected.");
+ }
+
+ setKey(forEncryption, ((KeyParameter)params).getKey());
+ initialized = true;
+ }
+
+ public int processBlock(byte[] in, int inOff,
+ byte[] out, int outOff)
+ throws IllegalStateException
+ {
+
+ if (!initialized)
+ {
+ throw new IllegalStateException("Camellia is not initialized");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ if (_keyis128)
+ {
+ return processBlock128(in, inOff, out, outOff);
+ }
+ else
+ {
+ return processBlock192or256(in, inOff, out, outOff);
+ }
+ }
+
+ public void reset()
+ {
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/CamelliaWrapEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/CamelliaWrapEngine.java
new file mode 100644
index 00000000..04526eb1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/CamelliaWrapEngine.java
@@ -0,0 +1,15 @@
+package org.spongycastle.crypto.engines;
+
+/**
+ * An implementation of the Camellia key wrapper based on RFC 3657/RFC 3394.
+ * <p>
+ * For further details see: <a href="http://www.ietf.org/rfc/rfc3657.txt">http://www.ietf.org/rfc/rfc3657.txt</a>.
+ */
+public class CamelliaWrapEngine
+ extends RFC3394WrapEngine
+{
+ public CamelliaWrapEngine()
+ {
+ super(new CamelliaEngine());
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/ChaChaEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/ChaChaEngine.java
new file mode 100644
index 00000000..bcceed9c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/ChaChaEngine.java
@@ -0,0 +1,204 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.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 retreatCounter()
+ {
+ if (engineState[12] == 0 && engineState[13] == 0)
+ {
+ throw new IllegalStateException("attempt to reduce counter past zero.");
+ }
+
+ if (--engineState[12] == -1)
+ {
+ --engineState[13];
+ }
+ }
+
+ protected long getCounter()
+ {
+ return ((long)engineState[13] << 32) | (engineState[12] & 0xffffffffL);
+ }
+
+ protected void resetCounter()
+ {
+ engineState[12] = engineState[13] = 0;
+ }
+
+ protected void setKey(byte[] keyBytes, byte[] ivBytes)
+ {
+ if (keyBytes != null)
+ {
+ if ((keyBytes.length != 16) && (keyBytes.length != 32))
+ {
+ throw new IllegalArgumentException(getAlgorithmName() + " requires 128 bit or 256 bit key");
+ }
+
+ // 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);
+
+ byte[] constants;
+ int offset;
+ if (keyBytes.length == 32)
+ {
+ constants = sigma;
+ offset = 16;
+ }
+ else
+ {
+ constants = tau;
+ offset = 0;
+ }
+
+ 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);
+ }
+
+ // 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
+ */
+ 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/core/src/main/java/org/spongycastle/crypto/engines/CramerShoupCiphertext.java b/core/src/main/java/org/spongycastle/crypto/engines/CramerShoupCiphertext.java
new file mode 100644
index 00000000..c5d61aac
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/CramerShoupCiphertext.java
@@ -0,0 +1,179 @@
+package org.spongycastle.crypto.engines;
+
+import java.math.BigInteger;
+
+/**
+ * Class, holding Cramer Shoup ciphertexts (u1, u2, e, v)
+ */
+public class CramerShoupCiphertext
+{
+
+ BigInteger u1, u2, e, v;
+
+ public CramerShoupCiphertext()
+ {
+
+ }
+
+ public CramerShoupCiphertext(BigInteger u1, BigInteger u2, BigInteger e, BigInteger v)
+ {
+ this.u1 = u1;
+ this.u2 = u2;
+ this.e = e;
+ this.v = v;
+ }
+
+ public CramerShoupCiphertext(byte[] c)
+ {
+ int off = 0, s;
+ byte[] size = new byte[4];
+ byte[] tmp;
+
+ System.arraycopy(c, off, size, 0, 4);
+ s = byteArrayToInt(size);
+ tmp = new byte[s];
+ off += 4;
+ System.arraycopy(c, off, tmp, 0, s);
+ off += s;
+ u1 = new BigInteger(tmp);
+
+ System.arraycopy(c, off, size, 0, 4);
+ s = byteArrayToInt(size);
+ tmp = new byte[s];
+ off += 4;
+ System.arraycopy(c, off, tmp, 0, s);
+ off += s;
+ u2 = new BigInteger(tmp);
+
+ System.arraycopy(c, off, size, 0, 4);
+ s = byteArrayToInt(size);
+ tmp = new byte[s];
+ off += 4;
+ System.arraycopy(c, off, tmp, 0, s);
+ off += s;
+ e = new BigInteger(tmp);
+
+ System.arraycopy(c, off, size, 0, 4);
+ s = byteArrayToInt(size);
+ tmp = new byte[s];
+ off += 4;
+ System.arraycopy(c, off, tmp, 0, s);
+ off += s;
+ v = new BigInteger(tmp);
+ }
+
+ public BigInteger getU1()
+ {
+ return u1;
+ }
+
+ public void setU1(BigInteger u1)
+ {
+ this.u1 = u1;
+ }
+
+ public BigInteger getU2()
+ {
+ return u2;
+ }
+
+ public void setU2(BigInteger u2)
+ {
+ this.u2 = u2;
+ }
+
+ public BigInteger getE()
+ {
+ return e;
+ }
+
+ public void setE(BigInteger e)
+ {
+ this.e = e;
+ }
+
+ public BigInteger getV()
+ {
+ return v;
+ }
+
+ public void setV(BigInteger v)
+ {
+ this.v = v;
+ }
+
+ public String toString()
+ {
+ StringBuffer result = new StringBuffer();
+
+ result.append("u1: " + u1.toString());
+ result.append("\nu2: " + u2.toString());
+ result.append("\ne: " + e.toString());
+ result.append("\nv: " + v.toString());
+
+ return result.toString();
+ }
+
+ /**
+ * convert the cipher-text in a byte array,
+ * prepending them with 4 Bytes for their length
+ *
+ * @return
+ */
+ public byte[] toByteArray()
+ {
+
+ byte[] u1Bytes = u1.toByteArray();
+ int u1Length = u1Bytes.length;
+ byte[] u2Bytes = u2.toByteArray();
+ int u2Length = u2Bytes.length;
+ byte[] eBytes = e.toByteArray();
+ int eLength = eBytes.length;
+ byte[] vBytes = v.toByteArray();
+ int vLength = vBytes.length;
+
+ int off = 0;
+ byte[] result = new byte[u1Length + u2Length + eLength + vLength + 4 * 4];
+ System.arraycopy(intToByteArray(u1Length), 0, result, 0, 4);
+ off += 4;
+ System.arraycopy(u1Bytes, 0, result, off, u1Length);
+ off += u1Length;
+ System.arraycopy(intToByteArray(u2Length), 0, result, off, 4);
+ off += 4;
+ System.arraycopy(u2Bytes, 0, result, off, u2Length);
+ off += u2Length;
+ System.arraycopy(intToByteArray(eLength), 0, result, off, 4);
+ off += 4;
+ System.arraycopy(eBytes, 0, result, off, eLength);
+ off += eLength;
+ System.arraycopy(intToByteArray(vLength), 0, result, off, 4);
+ off += 4;
+ System.arraycopy(vBytes, 0, result, off, vLength);
+
+ return result;
+ }
+
+ private byte[] intToByteArray(int in)
+ {
+ byte[] bytes = new byte[4];
+ for (int i = 0; i < 4; i++)
+ {
+ bytes[3 - i] = (byte)(in >>> (i * 8));
+ }
+ return bytes;
+ }
+
+ private int byteArrayToInt(byte[] in)
+ {
+ if (in.length != 4)
+ {
+ return -1;
+ }
+ int r = 0;
+ for (int i = 3; i >= 0; i--)
+ {
+ r += (int)in[i] << ((3 - i) * 8);
+ }
+ return r;
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/CramerShoupCoreEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/CramerShoupCoreEngine.java
new file mode 100644
index 00000000..894b13d8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/CramerShoupCoreEngine.java
@@ -0,0 +1,313 @@
+package org.spongycastle.crypto.engines;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.params.CramerShoupKeyParameters;
+import org.spongycastle.crypto.params.CramerShoupPrivateKeyParameters;
+import org.spongycastle.crypto.params.CramerShoupPublicKeyParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.util.BigIntegers;
+
+/**
+ * Essentially the Cramer-Shoup encryption / decryption algorithms according to
+ * "A practical public key cryptosystem provably secure against adaptive chosen ciphertext attack." (Crypto 1998)
+ */
+public class CramerShoupCoreEngine
+{
+
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ private CramerShoupKeyParameters key;
+ private SecureRandom random;
+ private boolean forEncryption;
+ private String label = null;
+
+ /**
+ * initialise the CramerShoup engine.
+ *
+ * @param forEncryption whether this engine should encrypt or decrypt
+ * @param param the necessary CramerShoup key parameters.
+ * @param label the label for labelled CS as {@link String}
+ */
+ public void init(boolean forEncryption, CipherParameters param, String label)
+ {
+ init(forEncryption, param);
+
+ this.label = label;
+ }
+
+ /**
+ * initialise the CramerShoup engine.
+ *
+ * @param forEncryption whether this engine should encrypt or decrypt
+ * @param param the necessary CramerShoup key parameters.
+ */
+ public void init(boolean forEncryption, CipherParameters param)
+ {
+ SecureRandom providedRandom = null;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ key = (CramerShoupKeyParameters)rParam.getParameters();
+ providedRandom = rParam.getRandom();
+ }
+ else
+ {
+ key = (CramerShoupKeyParameters)param;
+ }
+
+ this.random = initSecureRandom(forEncryption, providedRandom);
+ this.forEncryption = forEncryption;
+ }
+
+ /**
+ * Return the maximum size for an input block to this engine. For Cramer
+ * Shoup this is always one byte less than the key size on encryption, and
+ * the same length as the key size on decryption.
+ *
+ * @return maximum size for an input block.
+ * <p/>
+ * TODO: correct?
+ */
+ public int getInputBlockSize()
+ {
+ int bitSize = key.getParameters().getP().bitLength();
+
+ if (forEncryption)
+ {
+ return (bitSize + 7) / 8 - 1;
+ }
+ else
+ {
+ return (bitSize + 7) / 8;
+ }
+ }
+
+ /**
+ * Return the maximum size for an output block to this engine. For Cramer
+ * Shoup this is always one byte less than the key size on decryption, and
+ * the same length as the key size on encryption.
+ *
+ * @return maximum size for an output block.
+ * <p/>
+ * TODO: correct?
+ */
+ public int getOutputBlockSize()
+ {
+ int bitSize = key.getParameters().getP().bitLength();
+
+ if (forEncryption)
+ {
+ return (bitSize + 7) / 8;
+ }
+ else
+ {
+ return (bitSize + 7) / 8 - 1;
+ }
+ }
+
+ public BigInteger convertInput(byte[] in, int inOff, int inLen)
+ {
+ if (inLen > (getInputBlockSize() + 1))
+ {
+ throw new DataLengthException("input too large for Cramer Shoup cipher.");
+ }
+ else if (inLen == (getInputBlockSize() + 1) && forEncryption)
+ {
+ throw new DataLengthException("input too large for Cramer Shoup cipher.");
+ }
+
+ byte[] block;
+
+ if (inOff != 0 || inLen != in.length)
+ {
+ block = new byte[inLen];
+
+ System.arraycopy(in, inOff, block, 0, inLen);
+ }
+ else
+ {
+ block = in;
+ }
+
+ BigInteger res = new BigInteger(1, block);
+ if (res.compareTo(key.getParameters().getP()) >= 0)
+ {
+ throw new DataLengthException("input too large for Cramer Shoup cipher.");
+ }
+
+ return res;
+ }
+
+ public byte[] convertOutput(BigInteger result)
+ {
+ byte[] output = result.toByteArray();
+
+ if (!forEncryption)
+ {
+ if (output[0] == 0 && output.length > getOutputBlockSize())
+ { // have ended up with an extra zero byte, copy down.
+ byte[] tmp = new byte[output.length - 1];
+
+ System.arraycopy(output, 1, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+
+ if (output.length < getOutputBlockSize())
+ {// have ended up with less bytes than normal, lengthen
+ byte[] tmp = new byte[getOutputBlockSize()];
+
+ System.arraycopy(output, 0, tmp, tmp.length - output.length, output.length);
+
+ return tmp;
+ }
+ }
+ else
+ {
+ if (output[0] == 0)
+ { // have ended up with an extra zero byte, copy down.
+ byte[] tmp = new byte[output.length - 1];
+
+ System.arraycopy(output, 1, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+ }
+
+ return output;
+ }
+
+ public CramerShoupCiphertext encryptBlock(BigInteger input)
+ {
+
+ CramerShoupCiphertext result = null;
+
+ if (!key.isPrivate() && this.forEncryption && key instanceof CramerShoupPublicKeyParameters)
+ {
+ CramerShoupPublicKeyParameters pk = (CramerShoupPublicKeyParameters)key;
+ BigInteger p = pk.getParameters().getP();
+ BigInteger g1 = pk.getParameters().getG1();
+ BigInteger g2 = pk.getParameters().getG2();
+
+ BigInteger h = pk.getH();
+
+ if (!isValidMessage(input, p))
+ {
+ return result;
+ }
+
+ BigInteger r = generateRandomElement(p, random);
+
+ BigInteger u1, u2, v, e, a;
+
+ u1 = g1.modPow(r, p);
+ u2 = g2.modPow(r, p);
+ e = h.modPow(r, p).multiply(input).mod(p);
+
+ Digest digest = pk.getParameters().getH();
+ byte[] u1Bytes = u1.toByteArray();
+ digest.update(u1Bytes, 0, u1Bytes.length);
+ byte[] u2Bytes = u2.toByteArray();
+ digest.update(u2Bytes, 0, u2Bytes.length);
+ byte[] eBytes = e.toByteArray();
+ digest.update(eBytes, 0, eBytes.length);
+ if (this.label != null)
+ {
+ byte[] lBytes = this.label.getBytes();
+ digest.update(lBytes, 0, lBytes.length);
+ }
+ byte[] out = new byte[digest.getDigestSize()];
+ digest.doFinal(out, 0);
+ a = new BigInteger(1, out);
+
+ v = pk.getC().modPow(r, p).multiply(pk.getD().modPow(r.multiply(a), p)).mod(p);
+
+ result = new CramerShoupCiphertext(u1, u2, e, v);
+ }
+ return result;
+ }
+
+ public BigInteger decryptBlock(CramerShoupCiphertext input)
+ throws CramerShoupCiphertextException
+ {
+
+ BigInteger result = null;
+
+ if (key.isPrivate() && !this.forEncryption && key instanceof CramerShoupPrivateKeyParameters)
+ {
+ CramerShoupPrivateKeyParameters sk = (CramerShoupPrivateKeyParameters)key;
+
+ BigInteger p = sk.getParameters().getP();
+
+ Digest digest = sk.getParameters().getH();
+ byte[] u1Bytes = input.getU1().toByteArray();
+ digest.update(u1Bytes, 0, u1Bytes.length);
+ byte[] u2Bytes = input.getU2().toByteArray();
+ digest.update(u2Bytes, 0, u2Bytes.length);
+ byte[] eBytes = input.getE().toByteArray();
+ digest.update(eBytes, 0, eBytes.length);
+ if (this.label != null)
+ {
+ byte[] lBytes = this.label.getBytes();
+ digest.update(lBytes, 0, lBytes.length);
+ }
+ byte[] out = new byte[digest.getDigestSize()];
+ digest.doFinal(out, 0);
+
+ BigInteger a = new BigInteger(1, out);
+ BigInteger v = input.u1.modPow(sk.getX1().add(sk.getY1().multiply(a)), p).
+ multiply(input.u2.modPow(sk.getX2().add(sk.getY2().multiply(a)), p)).mod(p);
+
+ // check correctness of ciphertext
+ if (input.v.equals(v))
+ {
+ result = input.e.multiply(input.u1.modPow(sk.getZ(), p).modInverse(p)).mod(p);
+ }
+ else
+ {
+ throw new CramerShoupCiphertextException("Sorry, that ciphertext is not correct");
+ }
+ }
+ return result;
+ }
+
+ private BigInteger generateRandomElement(BigInteger p, SecureRandom random)
+ {
+ return BigIntegers.createRandomInRange(ONE, p.subtract(ONE), random);
+ }
+
+ /**
+ * just checking whether the message m is actually less than the group order p
+ */
+ private boolean isValidMessage(BigInteger m, BigInteger p)
+ {
+ return m.compareTo(p) < 0;
+ }
+
+ protected SecureRandom initSecureRandom(boolean needed, SecureRandom provided)
+ {
+ return !needed ? null : (provided != null) ? provided : new SecureRandom();
+ }
+
+ /**
+ * CS exception for wrong cipher-texts
+ */
+ public static class CramerShoupCiphertextException
+ extends Exception
+ {
+ private static final long serialVersionUID = -6360977166495345076L;
+
+ public CramerShoupCiphertextException(String msg)
+ {
+ super(msg);
+ }
+
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/DESEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/DESEngine.java
new file mode 100644
index 00000000..8f43249a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/DESEngine.java
@@ -0,0 +1,495 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+
+/**
+ * a class that provides a basic DES engine.
+ */
+public class DESEngine
+ implements BlockCipher
+{
+ protected static final int BLOCK_SIZE = 8;
+
+ private int[] workingKey = null;
+
+ /**
+ * standard constructor.
+ */
+ public DESEngine()
+ {
+ }
+
+ /**
+ * initialise a DES cipher.
+ *
+ * @param encrypting whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ {
+ if (params instanceof KeyParameter)
+ {
+ if (((KeyParameter)params).getKey().length > 8)
+ {
+ throw new IllegalArgumentException("DES key too long - should be 8 bytes");
+ }
+
+ workingKey = generateWorkingKey(encrypting,
+ ((KeyParameter)params).getKey());
+
+ return;
+ }
+
+ throw new IllegalArgumentException("invalid parameter passed to DES init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "DES";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (workingKey == null)
+ {
+ throw new IllegalStateException("DES engine not initialised");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ desFunc(workingKey, in, inOff, out, outOff);
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+
+ /**
+ * what follows is mainly taken from "Applied Cryptography", by
+ * Bruce Schneier, however it also bears great resemblance to Richard
+ * Outerbridge's D3DES...
+ */
+
+// private static final short[] Df_Key =
+// {
+// 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
+// 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,
+// 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67
+// };
+
+ private static final short[] bytebit =
+ {
+ 0200, 0100, 040, 020, 010, 04, 02, 01
+ };
+
+ private static final int[] bigbyte =
+ {
+ 0x800000, 0x400000, 0x200000, 0x100000,
+ 0x80000, 0x40000, 0x20000, 0x10000,
+ 0x8000, 0x4000, 0x2000, 0x1000,
+ 0x800, 0x400, 0x200, 0x100,
+ 0x80, 0x40, 0x20, 0x10,
+ 0x8, 0x4, 0x2, 0x1
+ };
+
+ /*
+ * Use the key schedule specified in the Standard (ANSI X3.92-1981).
+ */
+
+ private static final byte[] pc1 =
+ {
+ 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
+ 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
+ 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
+ 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3
+ };
+
+ private static final byte[] totrot =
+ {
+ 1, 2, 4, 6, 8, 10, 12, 14,
+ 15, 17, 19, 21, 23, 25, 27, 28
+ };
+
+ private static final byte[] pc2 =
+ {
+ 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
+ 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
+ 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
+ 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
+ };
+
+ private static final int[] SP1 = {
+ 0x01010400, 0x00000000, 0x00010000, 0x01010404,
+ 0x01010004, 0x00010404, 0x00000004, 0x00010000,
+ 0x00000400, 0x01010400, 0x01010404, 0x00000400,
+ 0x01000404, 0x01010004, 0x01000000, 0x00000004,
+ 0x00000404, 0x01000400, 0x01000400, 0x00010400,
+ 0x00010400, 0x01010000, 0x01010000, 0x01000404,
+ 0x00010004, 0x01000004, 0x01000004, 0x00010004,
+ 0x00000000, 0x00000404, 0x00010404, 0x01000000,
+ 0x00010000, 0x01010404, 0x00000004, 0x01010000,
+ 0x01010400, 0x01000000, 0x01000000, 0x00000400,
+ 0x01010004, 0x00010000, 0x00010400, 0x01000004,
+ 0x00000400, 0x00000004, 0x01000404, 0x00010404,
+ 0x01010404, 0x00010004, 0x01010000, 0x01000404,
+ 0x01000004, 0x00000404, 0x00010404, 0x01010400,
+ 0x00000404, 0x01000400, 0x01000400, 0x00000000,
+ 0x00010004, 0x00010400, 0x00000000, 0x01010004
+ };
+
+ private static final int[] SP2 = {
+ 0x80108020, 0x80008000, 0x00008000, 0x00108020,
+ 0x00100000, 0x00000020, 0x80100020, 0x80008020,
+ 0x80000020, 0x80108020, 0x80108000, 0x80000000,
+ 0x80008000, 0x00100000, 0x00000020, 0x80100020,
+ 0x00108000, 0x00100020, 0x80008020, 0x00000000,
+ 0x80000000, 0x00008000, 0x00108020, 0x80100000,
+ 0x00100020, 0x80000020, 0x00000000, 0x00108000,
+ 0x00008020, 0x80108000, 0x80100000, 0x00008020,
+ 0x00000000, 0x00108020, 0x80100020, 0x00100000,
+ 0x80008020, 0x80100000, 0x80108000, 0x00008000,
+ 0x80100000, 0x80008000, 0x00000020, 0x80108020,
+ 0x00108020, 0x00000020, 0x00008000, 0x80000000,
+ 0x00008020, 0x80108000, 0x00100000, 0x80000020,
+ 0x00100020, 0x80008020, 0x80000020, 0x00100020,
+ 0x00108000, 0x00000000, 0x80008000, 0x00008020,
+ 0x80000000, 0x80100020, 0x80108020, 0x00108000
+ };
+
+ private static final int[] SP3 = {
+ 0x00000208, 0x08020200, 0x00000000, 0x08020008,
+ 0x08000200, 0x00000000, 0x00020208, 0x08000200,
+ 0x00020008, 0x08000008, 0x08000008, 0x00020000,
+ 0x08020208, 0x00020008, 0x08020000, 0x00000208,
+ 0x08000000, 0x00000008, 0x08020200, 0x00000200,
+ 0x00020200, 0x08020000, 0x08020008, 0x00020208,
+ 0x08000208, 0x00020200, 0x00020000, 0x08000208,
+ 0x00000008, 0x08020208, 0x00000200, 0x08000000,
+ 0x08020200, 0x08000000, 0x00020008, 0x00000208,
+ 0x00020000, 0x08020200, 0x08000200, 0x00000000,
+ 0x00000200, 0x00020008, 0x08020208, 0x08000200,
+ 0x08000008, 0x00000200, 0x00000000, 0x08020008,
+ 0x08000208, 0x00020000, 0x08000000, 0x08020208,
+ 0x00000008, 0x00020208, 0x00020200, 0x08000008,
+ 0x08020000, 0x08000208, 0x00000208, 0x08020000,
+ 0x00020208, 0x00000008, 0x08020008, 0x00020200
+ };
+
+ private static final int[] SP4 = {
+ 0x00802001, 0x00002081, 0x00002081, 0x00000080,
+ 0x00802080, 0x00800081, 0x00800001, 0x00002001,
+ 0x00000000, 0x00802000, 0x00802000, 0x00802081,
+ 0x00000081, 0x00000000, 0x00800080, 0x00800001,
+ 0x00000001, 0x00002000, 0x00800000, 0x00802001,
+ 0x00000080, 0x00800000, 0x00002001, 0x00002080,
+ 0x00800081, 0x00000001, 0x00002080, 0x00800080,
+ 0x00002000, 0x00802080, 0x00802081, 0x00000081,
+ 0x00800080, 0x00800001, 0x00802000, 0x00802081,
+ 0x00000081, 0x00000000, 0x00000000, 0x00802000,
+ 0x00002080, 0x00800080, 0x00800081, 0x00000001,
+ 0x00802001, 0x00002081, 0x00002081, 0x00000080,
+ 0x00802081, 0x00000081, 0x00000001, 0x00002000,
+ 0x00800001, 0x00002001, 0x00802080, 0x00800081,
+ 0x00002001, 0x00002080, 0x00800000, 0x00802001,
+ 0x00000080, 0x00800000, 0x00002000, 0x00802080
+ };
+
+ private static final int[] SP5 = {
+ 0x00000100, 0x02080100, 0x02080000, 0x42000100,
+ 0x00080000, 0x00000100, 0x40000000, 0x02080000,
+ 0x40080100, 0x00080000, 0x02000100, 0x40080100,
+ 0x42000100, 0x42080000, 0x00080100, 0x40000000,
+ 0x02000000, 0x40080000, 0x40080000, 0x00000000,
+ 0x40000100, 0x42080100, 0x42080100, 0x02000100,
+ 0x42080000, 0x40000100, 0x00000000, 0x42000000,
+ 0x02080100, 0x02000000, 0x42000000, 0x00080100,
+ 0x00080000, 0x42000100, 0x00000100, 0x02000000,
+ 0x40000000, 0x02080000, 0x42000100, 0x40080100,
+ 0x02000100, 0x40000000, 0x42080000, 0x02080100,
+ 0x40080100, 0x00000100, 0x02000000, 0x42080000,
+ 0x42080100, 0x00080100, 0x42000000, 0x42080100,
+ 0x02080000, 0x00000000, 0x40080000, 0x42000000,
+ 0x00080100, 0x02000100, 0x40000100, 0x00080000,
+ 0x00000000, 0x40080000, 0x02080100, 0x40000100
+ };
+
+ private static final int[] SP6 = {
+ 0x20000010, 0x20400000, 0x00004000, 0x20404010,
+ 0x20400000, 0x00000010, 0x20404010, 0x00400000,
+ 0x20004000, 0x00404010, 0x00400000, 0x20000010,
+ 0x00400010, 0x20004000, 0x20000000, 0x00004010,
+ 0x00000000, 0x00400010, 0x20004010, 0x00004000,
+ 0x00404000, 0x20004010, 0x00000010, 0x20400010,
+ 0x20400010, 0x00000000, 0x00404010, 0x20404000,
+ 0x00004010, 0x00404000, 0x20404000, 0x20000000,
+ 0x20004000, 0x00000010, 0x20400010, 0x00404000,
+ 0x20404010, 0x00400000, 0x00004010, 0x20000010,
+ 0x00400000, 0x20004000, 0x20000000, 0x00004010,
+ 0x20000010, 0x20404010, 0x00404000, 0x20400000,
+ 0x00404010, 0x20404000, 0x00000000, 0x20400010,
+ 0x00000010, 0x00004000, 0x20400000, 0x00404010,
+ 0x00004000, 0x00400010, 0x20004010, 0x00000000,
+ 0x20404000, 0x20000000, 0x00400010, 0x20004010
+ };
+
+ private static final int[] SP7 = {
+ 0x00200000, 0x04200002, 0x04000802, 0x00000000,
+ 0x00000800, 0x04000802, 0x00200802, 0x04200800,
+ 0x04200802, 0x00200000, 0x00000000, 0x04000002,
+ 0x00000002, 0x04000000, 0x04200002, 0x00000802,
+ 0x04000800, 0x00200802, 0x00200002, 0x04000800,
+ 0x04000002, 0x04200000, 0x04200800, 0x00200002,
+ 0x04200000, 0x00000800, 0x00000802, 0x04200802,
+ 0x00200800, 0x00000002, 0x04000000, 0x00200800,
+ 0x04000000, 0x00200800, 0x00200000, 0x04000802,
+ 0x04000802, 0x04200002, 0x04200002, 0x00000002,
+ 0x00200002, 0x04000000, 0x04000800, 0x00200000,
+ 0x04200800, 0x00000802, 0x00200802, 0x04200800,
+ 0x00000802, 0x04000002, 0x04200802, 0x04200000,
+ 0x00200800, 0x00000000, 0x00000002, 0x04200802,
+ 0x00000000, 0x00200802, 0x04200000, 0x00000800,
+ 0x04000002, 0x04000800, 0x00000800, 0x00200002
+ };
+
+ private static final int[] SP8 = {
+ 0x10001040, 0x00001000, 0x00040000, 0x10041040,
+ 0x10000000, 0x10001040, 0x00000040, 0x10000000,
+ 0x00040040, 0x10040000, 0x10041040, 0x00041000,
+ 0x10041000, 0x00041040, 0x00001000, 0x00000040,
+ 0x10040000, 0x10000040, 0x10001000, 0x00001040,
+ 0x00041000, 0x00040040, 0x10040040, 0x10041000,
+ 0x00001040, 0x00000000, 0x00000000, 0x10040040,
+ 0x10000040, 0x10001000, 0x00041040, 0x00040000,
+ 0x00041040, 0x00040000, 0x10041000, 0x00001000,
+ 0x00000040, 0x10040040, 0x00001000, 0x00041040,
+ 0x10001000, 0x00000040, 0x10000040, 0x10040000,
+ 0x10040040, 0x10000000, 0x00040000, 0x10001040,
+ 0x00000000, 0x10041040, 0x00040040, 0x10000040,
+ 0x10040000, 0x10001000, 0x10001040, 0x00000000,
+ 0x10041040, 0x00041000, 0x00041000, 0x00001040,
+ 0x00001040, 0x00040040, 0x10000000, 0x10041000
+ };
+
+ /**
+ * generate an integer based working key based on our secret key
+ * and what we processing we are planning to do.
+ *
+ * Acknowledgements for this routine go to James Gillogly &amp; Phil Karn.
+ * (whoever, and wherever they are!).
+ */
+ protected int[] generateWorkingKey(
+ boolean encrypting,
+ byte[] key)
+ {
+ int[] newKey = new int[32];
+ boolean[] pc1m = new boolean[56],
+ pcr = new boolean[56];
+
+ for (int j = 0; j < 56; j++)
+ {
+ int l = pc1[j];
+
+ pc1m[j] = ((key[l >>> 3] & bytebit[l & 07]) != 0);
+ }
+
+ for (int i = 0; i < 16; i++)
+ {
+ int l, m, n;
+
+ if (encrypting)
+ {
+ m = i << 1;
+ }
+ else
+ {
+ m = (15 - i) << 1;
+ }
+
+ n = m + 1;
+ newKey[m] = newKey[n] = 0;
+
+ for (int j = 0; j < 28; j++)
+ {
+ l = j + totrot[i];
+ if (l < 28)
+ {
+ pcr[j] = pc1m[l];
+ }
+ else
+ {
+ pcr[j] = pc1m[l - 28];
+ }
+ }
+
+ for (int j = 28; j < 56; j++)
+ {
+ l = j + totrot[i];
+ if (l < 56)
+ {
+ pcr[j] = pc1m[l];
+ }
+ else
+ {
+ pcr[j] = pc1m[l - 28];
+ }
+ }
+
+ for (int j = 0; j < 24; j++)
+ {
+ if (pcr[pc2[j]])
+ {
+ newKey[m] |= bigbyte[j];
+ }
+
+ if (pcr[pc2[j + 24]])
+ {
+ newKey[n] |= bigbyte[j];
+ }
+ }
+ }
+
+ //
+ // store the processed key
+ //
+ for (int i = 0; i != 32; i += 2)
+ {
+ int i1, i2;
+
+ i1 = newKey[i];
+ i2 = newKey[i + 1];
+
+ newKey[i] = ((i1 & 0x00fc0000) << 6) | ((i1 & 0x00000fc0) << 10)
+ | ((i2 & 0x00fc0000) >>> 10) | ((i2 & 0x00000fc0) >>> 6);
+
+ newKey[i + 1] = ((i1 & 0x0003f000) << 12) | ((i1 & 0x0000003f) << 16)
+ | ((i2 & 0x0003f000) >>> 4) | (i2 & 0x0000003f);
+ }
+
+ return newKey;
+ }
+
+ /**
+ * the DES engine.
+ */
+ protected void desFunc(
+ int[] wKey,
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ int work, right, left;
+
+ left = (in[inOff + 0] & 0xff) << 24;
+ left |= (in[inOff + 1] & 0xff) << 16;
+ left |= (in[inOff + 2] & 0xff) << 8;
+ left |= (in[inOff + 3] & 0xff);
+
+ right = (in[inOff + 4] & 0xff) << 24;
+ right |= (in[inOff + 5] & 0xff) << 16;
+ right |= (in[inOff + 6] & 0xff) << 8;
+ right |= (in[inOff + 7] & 0xff);
+
+ work = ((left >>> 4) ^ right) & 0x0f0f0f0f;
+ right ^= work;
+ left ^= (work << 4);
+ work = ((left >>> 16) ^ right) & 0x0000ffff;
+ right ^= work;
+ left ^= (work << 16);
+ work = ((right >>> 2) ^ left) & 0x33333333;
+ left ^= work;
+ right ^= (work << 2);
+ work = ((right >>> 8) ^ left) & 0x00ff00ff;
+ left ^= work;
+ right ^= (work << 8);
+ right = ((right << 1) | ((right >>> 31) & 1)) & 0xffffffff;
+ work = (left ^ right) & 0xaaaaaaaa;
+ left ^= work;
+ right ^= work;
+ left = ((left << 1) | ((left >>> 31) & 1)) & 0xffffffff;
+
+ for (int round = 0; round < 8; round++)
+ {
+ int fval;
+
+ work = (right << 28) | (right >>> 4);
+ work ^= wKey[round * 4 + 0];
+ fval = SP7[ work & 0x3f];
+ fval |= SP5[(work >>> 8) & 0x3f];
+ fval |= SP3[(work >>> 16) & 0x3f];
+ fval |= SP1[(work >>> 24) & 0x3f];
+ work = right ^ wKey[round * 4 + 1];
+ fval |= SP8[ work & 0x3f];
+ fval |= SP6[(work >>> 8) & 0x3f];
+ fval |= SP4[(work >>> 16) & 0x3f];
+ fval |= SP2[(work >>> 24) & 0x3f];
+ left ^= fval;
+ work = (left << 28) | (left >>> 4);
+ work ^= wKey[round * 4 + 2];
+ fval = SP7[ work & 0x3f];
+ fval |= SP5[(work >>> 8) & 0x3f];
+ fval |= SP3[(work >>> 16) & 0x3f];
+ fval |= SP1[(work >>> 24) & 0x3f];
+ work = left ^ wKey[round * 4 + 3];
+ fval |= SP8[ work & 0x3f];
+ fval |= SP6[(work >>> 8) & 0x3f];
+ fval |= SP4[(work >>> 16) & 0x3f];
+ fval |= SP2[(work >>> 24) & 0x3f];
+ right ^= fval;
+ }
+
+ right = (right << 31) | (right >>> 1);
+ work = (left ^ right) & 0xaaaaaaaa;
+ left ^= work;
+ right ^= work;
+ left = (left << 31) | (left >>> 1);
+ work = ((left >>> 8) ^ right) & 0x00ff00ff;
+ right ^= work;
+ left ^= (work << 8);
+ work = ((left >>> 2) ^ right) & 0x33333333;
+ right ^= work;
+ left ^= (work << 2);
+ work = ((right >>> 16) ^ left) & 0x0000ffff;
+ left ^= work;
+ right ^= (work << 16);
+ work = ((right >>> 4) ^ left) & 0x0f0f0f0f;
+ left ^= work;
+ right ^= (work << 4);
+
+ out[outOff + 0] = (byte)((right >>> 24) & 0xff);
+ out[outOff + 1] = (byte)((right >>> 16) & 0xff);
+ out[outOff + 2] = (byte)((right >>> 8) & 0xff);
+ out[outOff + 3] = (byte)(right & 0xff);
+ out[outOff + 4] = (byte)((left >>> 24) & 0xff);
+ out[outOff + 5] = (byte)((left >>> 16) & 0xff);
+ out[outOff + 6] = (byte)((left >>> 8) & 0xff);
+ out[outOff + 7] = (byte)(left & 0xff);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/DESedeEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/DESedeEngine.java
new file mode 100644
index 00000000..e0c0fb85
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/DESedeEngine.java
@@ -0,0 +1,127 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+
+/**
+ * a class that provides a basic DESede (or Triple DES) engine.
+ */
+public class DESedeEngine
+ extends DESEngine
+{
+ protected static final int BLOCK_SIZE = 8;
+
+ private int[] workingKey1 = null;
+ private int[] workingKey2 = null;
+ private int[] workingKey3 = null;
+
+ private boolean forEncryption;
+
+ /**
+ * standard constructor.
+ */
+ public DESedeEngine()
+ {
+ }
+
+ /**
+ * initialise a DESede cipher.
+ *
+ * @param encrypting whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ {
+ if (!(params instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("invalid parameter passed to DESede init - " + params.getClass().getName());
+ }
+
+ byte[] keyMaster = ((KeyParameter)params).getKey();
+
+ if (keyMaster.length != 24 && keyMaster.length != 16)
+ {
+ throw new IllegalArgumentException("key size must be 16 or 24 bytes.");
+ }
+
+ this.forEncryption = encrypting;
+
+ byte[] key1 = new byte[8];
+ System.arraycopy(keyMaster, 0, key1, 0, key1.length);
+ workingKey1 = generateWorkingKey(encrypting, key1);
+
+ byte[] key2 = new byte[8];
+ System.arraycopy(keyMaster, 8, key2, 0, key2.length);
+ workingKey2 = generateWorkingKey(!encrypting, key2);
+
+ if (keyMaster.length == 24)
+ {
+ byte[] key3 = new byte[8];
+ System.arraycopy(keyMaster, 16, key3, 0, key3.length);
+ workingKey3 = generateWorkingKey(encrypting, key3);
+ }
+ else // 16 byte key
+ {
+ workingKey3 = workingKey1;
+ }
+ }
+
+ public String getAlgorithmName()
+ {
+ return "DESede";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (workingKey1 == null)
+ {
+ throw new IllegalStateException("DESede engine not initialised");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ byte[] temp = new byte[BLOCK_SIZE];
+
+ if (forEncryption)
+ {
+ desFunc(workingKey1, in, inOff, temp, 0);
+ desFunc(workingKey2, temp, 0, temp, 0);
+ desFunc(workingKey3, temp, 0, out, outOff);
+ }
+ else
+ {
+ desFunc(workingKey3, in, inOff, temp, 0);
+ desFunc(workingKey2, temp, 0, temp, 0);
+ desFunc(workingKey1, temp, 0, out, outOff);
+ }
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/DESedeWrapEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/DESedeWrapEngine.java
new file mode 100644
index 00000000..756fe705
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/DESedeWrapEngine.java
@@ -0,0 +1,350 @@
+package org.spongycastle.crypto.engines;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.Wrapper;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.modes.CBCBlockCipher;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.util.Arrays;
+
+/**
+ * Wrap keys according to
+ * <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-smime-key-wrap-01.txt">
+ * draft-ietf-smime-key-wrap-01.txt</A>.
+ * <p>
+ * Note:
+ * <ul>
+ * <li>this is based on a draft, and as such is subject to change - don't use this class for anything requiring long term storage.
+ * <li>if you are using this to wrap triple-des keys you need to set the
+ * parity bits on the key and, if it's a two-key triple-des key, pad it
+ * yourself.
+ * </ul>
+ */
+public class DESedeWrapEngine
+ implements Wrapper
+{
+ /** Field engine */
+ private CBCBlockCipher engine;
+
+ /** Field param */
+ private KeyParameter param;
+
+ /** Field paramPlusIV */
+ private ParametersWithIV paramPlusIV;
+
+ /** Field iv */
+ private byte[] iv;
+
+ /** Field forWrapping */
+ private boolean forWrapping;
+
+ /** Field IV2 */
+ private static final byte[] IV2 = { (byte) 0x4a, (byte) 0xdd, (byte) 0xa2,
+ (byte) 0x2c, (byte) 0x79, (byte) 0xe8,
+ (byte) 0x21, (byte) 0x05 };
+
+ //
+ // checksum digest
+ //
+ Digest sha1 = new SHA1Digest();
+ byte[] digest = new byte[20];
+
+ /**
+ * Method init
+ *
+ * @param forWrapping true if for wrapping, false otherwise.
+ * @param param necessary parameters, may include KeyParameter, ParametersWithRandom, and ParametersWithIV
+ */
+ public void init(boolean forWrapping, CipherParameters param)
+ {
+
+ this.forWrapping = forWrapping;
+ this.engine = new CBCBlockCipher(new DESedeEngine());
+
+ SecureRandom sr;
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom pr = (ParametersWithRandom) param;
+ param = pr.getParameters();
+ sr = pr.getRandom();
+ }
+ else
+ {
+ sr = new SecureRandom();
+ }
+
+ if (param instanceof KeyParameter)
+ {
+ this.param = (KeyParameter)param;
+
+ if (this.forWrapping)
+ {
+
+ // Hm, we have no IV but we want to wrap ?!?
+ // well, then we have to create our own IV.
+ this.iv = new byte[8];
+ sr.nextBytes(iv);
+
+ this.paramPlusIV = new ParametersWithIV(this.param, this.iv);
+ }
+ }
+ else if (param instanceof ParametersWithIV)
+ {
+ this.paramPlusIV = (ParametersWithIV)param;
+ this.iv = this.paramPlusIV.getIV();
+ this.param = (KeyParameter)this.paramPlusIV.getParameters();
+
+ if (this.forWrapping)
+ {
+ if ((this.iv == null) || (this.iv.length != 8))
+ {
+ throw new IllegalArgumentException("IV is not 8 octets");
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException(
+ "You should not supply an IV for unwrapping");
+ }
+ }
+ }
+
+ /**
+ * Method getAlgorithmName
+ *
+ * @return the algorithm name "DESede".
+ */
+ public String getAlgorithmName()
+ {
+ return "DESede";
+ }
+
+ /**
+ * Method wrap
+ *
+ * @param in byte array containing the encoded key.
+ * @param inOff off set into in that the data starts at.
+ * @param inLen length of the data.
+ * @return the wrapped bytes.
+ */
+ public byte[] wrap(byte[] in, int inOff, int inLen)
+ {
+ if (!forWrapping)
+ {
+ throw new IllegalStateException("Not initialized for wrapping");
+ }
+
+ byte keyToBeWrapped[] = new byte[inLen];
+
+ System.arraycopy(in, inOff, keyToBeWrapped, 0, inLen);
+
+ // Compute the CMS Key Checksum, (section 5.6.1), call this CKS.
+ byte[] CKS = calculateCMSKeyChecksum(keyToBeWrapped);
+
+ // Let WKCKS = WK || CKS where || is concatenation.
+ byte[] WKCKS = new byte[keyToBeWrapped.length + CKS.length];
+
+ System.arraycopy(keyToBeWrapped, 0, WKCKS, 0, keyToBeWrapped.length);
+ System.arraycopy(CKS, 0, WKCKS, keyToBeWrapped.length, CKS.length);
+
+ // Encrypt WKCKS in CBC mode using KEK as the key and IV as the
+ // initialization vector. Call the results TEMP1.
+
+ int blockSize = engine.getBlockSize();
+
+ if (WKCKS.length % blockSize != 0)
+ {
+ throw new IllegalStateException("Not multiple of block length");
+ }
+
+ engine.init(true, paramPlusIV);
+
+ byte TEMP1[] = new byte[WKCKS.length];
+
+ for (int currentBytePos = 0; currentBytePos != WKCKS.length; currentBytePos += blockSize)
+ {
+ engine.processBlock(WKCKS, currentBytePos, TEMP1, currentBytePos);
+ }
+
+ // Let TEMP2 = IV || TEMP1.
+ byte[] TEMP2 = new byte[this.iv.length + TEMP1.length];
+
+ System.arraycopy(this.iv, 0, TEMP2, 0, this.iv.length);
+ System.arraycopy(TEMP1, 0, TEMP2, this.iv.length, TEMP1.length);
+
+ // Reverse the order of the octets in TEMP2 and call the result TEMP3.
+ byte[] TEMP3 = reverse(TEMP2);
+
+ // Encrypt TEMP3 in CBC mode using the KEK and an initialization vector
+ // of 0x 4a dd a2 2c 79 e8 21 05. The resulting cipher text is the desired
+ // result. It is 40 octets long if a 168 bit key is being wrapped.
+ ParametersWithIV param2 = new ParametersWithIV(this.param, IV2);
+
+ this.engine.init(true, param2);
+
+ for (int currentBytePos = 0; currentBytePos != TEMP3.length; currentBytePos += blockSize)
+ {
+ engine.processBlock(TEMP3, currentBytePos, TEMP3, currentBytePos);
+ }
+
+ return TEMP3;
+ }
+
+ /**
+ * Method unwrap
+ *
+ * @param in byte array containing the wrapped key.
+ * @param inOff off set into in that the data starts at.
+ * @param inLen length of the data.
+ * @return the unwrapped bytes.
+ * @throws InvalidCipherTextException
+ */
+ public byte[] unwrap(byte[] in, int inOff, int inLen)
+ throws InvalidCipherTextException
+ {
+ if (forWrapping)
+ {
+ throw new IllegalStateException("Not set for unwrapping");
+ }
+
+ if (in == null)
+ {
+ throw new InvalidCipherTextException("Null pointer as ciphertext");
+ }
+
+ final int blockSize = engine.getBlockSize();
+ if (inLen % blockSize != 0)
+ {
+ throw new InvalidCipherTextException("Ciphertext not multiple of " + blockSize);
+ }
+
+ /*
+ // Check if the length of the cipher text is reasonable given the key
+ // type. It must be 40 bytes for a 168 bit key and either 32, 40, or
+ // 48 bytes for a 128, 192, or 256 bit key. If the length is not supported
+ // or inconsistent with the algorithm for which the key is intended,
+ // return error.
+ //
+ // we do not accept 168 bit keys. it has to be 192 bit.
+ int lengthA = (estimatedKeyLengthInBit / 8) + 16;
+ int lengthB = estimatedKeyLengthInBit % 8;
+
+ if ((lengthA != keyToBeUnwrapped.length) || (lengthB != 0)) {
+ throw new XMLSecurityException("empty");
+ }
+ */
+
+ // Decrypt the cipher text with TRIPLedeS in CBC mode using the KEK
+ // and an initialization vector (IV) of 0x4adda22c79e82105. Call the output TEMP3.
+ ParametersWithIV param2 = new ParametersWithIV(this.param, IV2);
+
+ this.engine.init(false, param2);
+
+ byte TEMP3[] = new byte[inLen];
+
+ for (int currentBytePos = 0; currentBytePos != inLen; currentBytePos += blockSize)
+ {
+ engine.processBlock(in, inOff + currentBytePos, TEMP3, currentBytePos);
+ }
+
+ // Reverse the order of the octets in TEMP3 and call the result TEMP2.
+ byte[] TEMP2 = reverse(TEMP3);
+
+ // Decompose TEMP2 into IV, the first 8 octets, and TEMP1, the remaining octets.
+ this.iv = new byte[8];
+
+ byte[] TEMP1 = new byte[TEMP2.length - 8];
+
+ System.arraycopy(TEMP2, 0, this.iv, 0, 8);
+ System.arraycopy(TEMP2, 8, TEMP1, 0, TEMP2.length - 8);
+
+ // Decrypt TEMP1 using TRIPLedeS in CBC mode using the KEK and the IV
+ // found in the previous step. Call the result WKCKS.
+ this.paramPlusIV = new ParametersWithIV(this.param, this.iv);
+
+ this.engine.init(false, this.paramPlusIV);
+
+ byte[] WKCKS = new byte[TEMP1.length];
+
+ for (int currentBytePos = 0; currentBytePos != WKCKS.length; currentBytePos += blockSize)
+ {
+ engine.processBlock(TEMP1, currentBytePos, WKCKS, currentBytePos);
+ }
+
+ // Decompose WKCKS. CKS is the last 8 octets and WK, the wrapped key, are
+ // those octets before the CKS.
+ byte[] result = new byte[WKCKS.length - 8];
+ byte[] CKStoBeVerified = new byte[8];
+
+ System.arraycopy(WKCKS, 0, result, 0, WKCKS.length - 8);
+ System.arraycopy(WKCKS, WKCKS.length - 8, CKStoBeVerified, 0, 8);
+
+ // Calculate a CMS Key Checksum, (section 5.6.1), over the WK and compare
+ // with the CKS extracted in the above step. If they are not equal, return error.
+ if (!checkCMSKeyChecksum(result, CKStoBeVerified))
+ {
+ throw new InvalidCipherTextException(
+ "Checksum inside ciphertext is corrupted");
+ }
+
+ // WK is the wrapped key, now extracted for use in data decryption.
+ return result;
+ }
+
+ /**
+ * Some key wrap algorithms make use of the Key Checksum defined
+ * in CMS [CMS-Algorithms]. This is used to provide an integrity
+ * check value for the key being wrapped. The algorithm is
+ *
+ * - Compute the 20 octet SHA-1 hash on the key being wrapped.
+ * - Use the first 8 octets of this hash as the checksum value.
+ *
+ * For details see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum.
+ *
+ * @param key the key to check,
+ * @return the CMS checksum.
+ * @throws RuntimeException
+ */
+ private byte[] calculateCMSKeyChecksum(
+ byte[] key)
+ {
+ byte[] result = new byte[8];
+
+ sha1.update(key, 0, key.length);
+ sha1.doFinal(digest, 0);
+
+ System.arraycopy(digest, 0, result, 0, 8);
+
+ return result;
+ }
+
+ /**
+ * For details see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
+ *
+ * @param key key to be validated.
+ * @param checksum the checksum.
+ * @return true if okay, false otherwise.
+ */
+ private boolean checkCMSKeyChecksum(
+ byte[] key,
+ byte[] checksum)
+ {
+ return Arrays.constantTimeAreEqual(calculateCMSKeyChecksum(key), checksum);
+ }
+
+ private static byte[] reverse(byte[] bs)
+ {
+ byte[] result = new byte[bs.length];
+ for (int i = 0; i < bs.length; i++)
+ {
+ result[i] = bs[bs.length - (i + 1)];
+ }
+ return result;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/ElGamalEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/ElGamalEngine.java
new file mode 100644
index 00000000..cf4799b0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/ElGamalEngine.java
@@ -0,0 +1,217 @@
+package org.spongycastle.crypto.engines;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.params.ElGamalKeyParameters;
+import org.spongycastle.crypto.params.ElGamalPrivateKeyParameters;
+import org.spongycastle.crypto.params.ElGamalPublicKeyParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.util.BigIntegers;
+
+/**
+ * this does your basic ElGamal algorithm.
+ */
+public class ElGamalEngine
+ implements AsymmetricBlockCipher
+{
+ private ElGamalKeyParameters key;
+ private SecureRandom random;
+ private boolean forEncryption;
+ private int bitSize;
+
+ private static final BigInteger ZERO = BigInteger.valueOf(0);
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+ private static final BigInteger TWO = BigInteger.valueOf(2);
+
+ /**
+ * initialise the ElGamal engine.
+ *
+ * @param forEncryption true if we are encrypting, false otherwise.
+ * @param param the necessary ElGamal key parameters.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters param)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom p = (ParametersWithRandom)param;
+
+ this.key = (ElGamalKeyParameters)p.getParameters();
+ this.random = p.getRandom();
+ }
+ else
+ {
+ this.key = (ElGamalKeyParameters)param;
+ this.random = new SecureRandom();
+ }
+
+ this.forEncryption = forEncryption;
+
+ BigInteger p = key.getParameters().getP();
+
+ bitSize = p.bitLength();
+
+ if (forEncryption)
+ {
+ if (!(key instanceof ElGamalPublicKeyParameters))
+ {
+ throw new IllegalArgumentException("ElGamalPublicKeyParameters are required for encryption.");
+ }
+ }
+ else
+ {
+ if (!(key instanceof ElGamalPrivateKeyParameters))
+ {
+ throw new IllegalArgumentException("ElGamalPrivateKeyParameters are required for decryption.");
+ }
+ }
+ }
+
+ /**
+ * Return the maximum size for an input block to this engine.
+ * For ElGamal this is always one byte less than the size of P on
+ * encryption, and twice the length as the size of P on decryption.
+ *
+ * @return maximum size for an input block.
+ */
+ public int getInputBlockSize()
+ {
+ if (forEncryption)
+ {
+ return (bitSize - 1) / 8;
+ }
+
+ return 2 * ((bitSize + 7) / 8);
+ }
+
+ /**
+ * Return the maximum size for an output block to this engine.
+ * For ElGamal this is always one byte less than the size of P on
+ * decryption, and twice the length as the size of P on encryption.
+ *
+ * @return maximum size for an output block.
+ */
+ public int getOutputBlockSize()
+ {
+ if (forEncryption)
+ {
+ return 2 * ((bitSize + 7) / 8);
+ }
+
+ return (bitSize - 1) / 8;
+ }
+
+ /**
+ * Process a single block using the basic ElGamal algorithm.
+ *
+ * @param in the input array.
+ * @param inOff the offset into the input buffer where the data starts.
+ * @param inLen the length of the data to be processed.
+ * @return the result of the ElGamal process.
+ * @exception DataLengthException the input block is too large.
+ */
+ public byte[] processBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ {
+ if (key == null)
+ {
+ throw new IllegalStateException("ElGamal engine not initialised");
+ }
+
+ int maxLength = forEncryption
+ ? (bitSize - 1 + 7) / 8
+ : getInputBlockSize();
+
+ if (inLen > maxLength)
+ {
+ throw new DataLengthException("input too large for ElGamal cipher.\n");
+ }
+
+ BigInteger p = key.getParameters().getP();
+
+ if (key instanceof ElGamalPrivateKeyParameters) // decryption
+ {
+ byte[] in1 = new byte[inLen / 2];
+ byte[] in2 = new byte[inLen / 2];
+
+ System.arraycopy(in, inOff, in1, 0, in1.length);
+ System.arraycopy(in, inOff + in1.length, in2, 0, in2.length);
+
+ BigInteger gamma = new BigInteger(1, in1);
+ BigInteger phi = new BigInteger(1, in2);
+
+ ElGamalPrivateKeyParameters priv = (ElGamalPrivateKeyParameters)key;
+ // a shortcut, which generally relies on p being prime amongst other things.
+ // if a problem with this shows up, check the p and g values!
+ BigInteger m = gamma.modPow(p.subtract(ONE).subtract(priv.getX()), p).multiply(phi).mod(p);
+
+ return BigIntegers.asUnsignedByteArray(m);
+ }
+ else // encryption
+ {
+ byte[] block;
+ if (inOff != 0 || inLen != in.length)
+ {
+ block = new byte[inLen];
+
+ System.arraycopy(in, inOff, block, 0, inLen);
+ }
+ else
+ {
+ block = in;
+ }
+
+ BigInteger input = new BigInteger(1, block);
+
+ if (input.compareTo(p) >= 0)
+ {
+ throw new DataLengthException("input too large for ElGamal cipher.\n");
+ }
+
+ ElGamalPublicKeyParameters pub = (ElGamalPublicKeyParameters)key;
+
+ int pBitLength = p.bitLength();
+ BigInteger k = new BigInteger(pBitLength, random);
+
+ while (k.equals(ZERO) || (k.compareTo(p.subtract(TWO)) > 0))
+ {
+ k = new BigInteger(pBitLength, random);
+ }
+
+ BigInteger g = key.getParameters().getG();
+ BigInteger gamma = g.modPow(k, p);
+ BigInteger phi = input.multiply(pub.getY().modPow(k, p)).mod(p);
+
+ byte[] out1 = gamma.toByteArray();
+ byte[] out2 = phi.toByteArray();
+ byte[] output = new byte[this.getOutputBlockSize()];
+
+ if (out1.length > output.length / 2)
+ {
+ System.arraycopy(out1, 1, output, output.length / 2 - (out1.length - 1), out1.length - 1);
+ }
+ else
+ {
+ System.arraycopy(out1, 0, output, output.length / 2 - out1.length, out1.length);
+ }
+
+ if (out2.length > output.length / 2)
+ {
+ System.arraycopy(out2, 1, output, output.length - (out2.length - 1), out2.length - 1);
+ }
+ else
+ {
+ System.arraycopy(out2, 0, output, output.length - out2.length, out2.length);
+ }
+
+ return output;
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/GOST28147Engine.java b/core/src/main/java/org/spongycastle/crypto/engines/GOST28147Engine.java
new file mode 100644
index 00000000..f6ecbc36
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/GOST28147Engine.java
@@ -0,0 +1,372 @@
+package org.spongycastle.crypto.engines;
+
+import java.util.Hashtable;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithSBox;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Strings;
+
+/**
+ * implementation of GOST 28147-89
+ */
+public class GOST28147Engine
+ implements BlockCipher
+{
+ protected static final int BLOCK_SIZE = 8;
+ private int[] workingKey = null;
+ private boolean forEncryption;
+
+ private byte[] S = Sbox_Default;
+
+ // these are the S-boxes given in Applied Cryptography 2nd Ed., p. 333
+ // This is default S-box!
+ private static byte Sbox_Default[] = {
+ 0x4,0xA,0x9,0x2,0xD,0x8,0x0,0xE,0x6,0xB,0x1,0xC,0x7,0xF,0x5,0x3,
+ 0xE,0xB,0x4,0xC,0x6,0xD,0xF,0xA,0x2,0x3,0x8,0x1,0x0,0x7,0x5,0x9,
+ 0x5,0x8,0x1,0xD,0xA,0x3,0x4,0x2,0xE,0xF,0xC,0x7,0x6,0x0,0x9,0xB,
+ 0x7,0xD,0xA,0x1,0x0,0x8,0x9,0xF,0xE,0x4,0x6,0xC,0xB,0x2,0x5,0x3,
+ 0x6,0xC,0x7,0x1,0x5,0xF,0xD,0x8,0x4,0xA,0x9,0xE,0x0,0x3,0xB,0x2,
+ 0x4,0xB,0xA,0x0,0x7,0x2,0x1,0xD,0x3,0x6,0x8,0x5,0x9,0xC,0xF,0xE,
+ 0xD,0xB,0x4,0x1,0x3,0xF,0x5,0x9,0x0,0xA,0xE,0x7,0x6,0x8,0x2,0xC,
+ 0x1,0xF,0xD,0x0,0x5,0x7,0xA,0x4,0x9,0x2,0x3,0xE,0x6,0xB,0x8,0xC
+ };
+
+ /*
+ * class content S-box parameters for encrypting
+ * getting from, see: http://tools.ietf.org/id/draft-popov-cryptopro-cpalgs-01.txt
+ * http://tools.ietf.org/id/draft-popov-cryptopro-cpalgs-02.txt
+ */
+ private static byte[] ESbox_Test = {
+ 0x4,0x2,0xF,0x5,0x9,0x1,0x0,0x8,0xE,0x3,0xB,0xC,0xD,0x7,0xA,0x6,
+ 0xC,0x9,0xF,0xE,0x8,0x1,0x3,0xA,0x2,0x7,0x4,0xD,0x6,0x0,0xB,0x5,
+ 0xD,0x8,0xE,0xC,0x7,0x3,0x9,0xA,0x1,0x5,0x2,0x4,0x6,0xF,0x0,0xB,
+ 0xE,0x9,0xB,0x2,0x5,0xF,0x7,0x1,0x0,0xD,0xC,0x6,0xA,0x4,0x3,0x8,
+ 0x3,0xE,0x5,0x9,0x6,0x8,0x0,0xD,0xA,0xB,0x7,0xC,0x2,0x1,0xF,0x4,
+ 0x8,0xF,0x6,0xB,0x1,0x9,0xC,0x5,0xD,0x3,0x7,0xA,0x0,0xE,0x2,0x4,
+ 0x9,0xB,0xC,0x0,0x3,0x6,0x7,0x5,0x4,0x8,0xE,0xF,0x1,0xA,0x2,0xD,
+ 0xC,0x6,0x5,0x2,0xB,0x0,0x9,0xD,0x3,0xE,0x7,0xA,0xF,0x4,0x1,0x8
+ };
+
+ private static byte[] ESbox_A = {
+ 0x9,0x6,0x3,0x2,0x8,0xB,0x1,0x7,0xA,0x4,0xE,0xF,0xC,0x0,0xD,0x5,
+ 0x3,0x7,0xE,0x9,0x8,0xA,0xF,0x0,0x5,0x2,0x6,0xC,0xB,0x4,0xD,0x1,
+ 0xE,0x4,0x6,0x2,0xB,0x3,0xD,0x8,0xC,0xF,0x5,0xA,0x0,0x7,0x1,0x9,
+ 0xE,0x7,0xA,0xC,0xD,0x1,0x3,0x9,0x0,0x2,0xB,0x4,0xF,0x8,0x5,0x6,
+ 0xB,0x5,0x1,0x9,0x8,0xD,0xF,0x0,0xE,0x4,0x2,0x3,0xC,0x7,0xA,0x6,
+ 0x3,0xA,0xD,0xC,0x1,0x2,0x0,0xB,0x7,0x5,0x9,0x4,0x8,0xF,0xE,0x6,
+ 0x1,0xD,0x2,0x9,0x7,0xA,0x6,0x0,0x8,0xC,0x4,0x5,0xF,0x3,0xB,0xE,
+ 0xB,0xA,0xF,0x5,0x0,0xC,0xE,0x8,0x6,0x2,0x3,0x9,0x1,0x7,0xD,0x4
+ };
+
+ private static byte[] ESbox_B = {
+ 0x8,0x4,0xB,0x1,0x3,0x5,0x0,0x9,0x2,0xE,0xA,0xC,0xD,0x6,0x7,0xF,
+ 0x0,0x1,0x2,0xA,0x4,0xD,0x5,0xC,0x9,0x7,0x3,0xF,0xB,0x8,0x6,0xE,
+ 0xE,0xC,0x0,0xA,0x9,0x2,0xD,0xB,0x7,0x5,0x8,0xF,0x3,0x6,0x1,0x4,
+ 0x7,0x5,0x0,0xD,0xB,0x6,0x1,0x2,0x3,0xA,0xC,0xF,0x4,0xE,0x9,0x8,
+ 0x2,0x7,0xC,0xF,0x9,0x5,0xA,0xB,0x1,0x4,0x0,0xD,0x6,0x8,0xE,0x3,
+ 0x8,0x3,0x2,0x6,0x4,0xD,0xE,0xB,0xC,0x1,0x7,0xF,0xA,0x0,0x9,0x5,
+ 0x5,0x2,0xA,0xB,0x9,0x1,0xC,0x3,0x7,0x4,0xD,0x0,0x6,0xF,0x8,0xE,
+ 0x0,0x4,0xB,0xE,0x8,0x3,0x7,0x1,0xA,0x2,0x9,0x6,0xF,0xD,0x5,0xC
+ };
+
+ private static byte[] ESbox_C = {
+ 0x1,0xB,0xC,0x2,0x9,0xD,0x0,0xF,0x4,0x5,0x8,0xE,0xA,0x7,0x6,0x3,
+ 0x0,0x1,0x7,0xD,0xB,0x4,0x5,0x2,0x8,0xE,0xF,0xC,0x9,0xA,0x6,0x3,
+ 0x8,0x2,0x5,0x0,0x4,0x9,0xF,0xA,0x3,0x7,0xC,0xD,0x6,0xE,0x1,0xB,
+ 0x3,0x6,0x0,0x1,0x5,0xD,0xA,0x8,0xB,0x2,0x9,0x7,0xE,0xF,0xC,0x4,
+ 0x8,0xD,0xB,0x0,0x4,0x5,0x1,0x2,0x9,0x3,0xC,0xE,0x6,0xF,0xA,0x7,
+ 0xC,0x9,0xB,0x1,0x8,0xE,0x2,0x4,0x7,0x3,0x6,0x5,0xA,0x0,0xF,0xD,
+ 0xA,0x9,0x6,0x8,0xD,0xE,0x2,0x0,0xF,0x3,0x5,0xB,0x4,0x1,0xC,0x7,
+ 0x7,0x4,0x0,0x5,0xA,0x2,0xF,0xE,0xC,0x6,0x1,0xB,0xD,0x9,0x3,0x8
+ };
+
+ private static byte[] ESbox_D = {
+ 0xF,0xC,0x2,0xA,0x6,0x4,0x5,0x0,0x7,0x9,0xE,0xD,0x1,0xB,0x8,0x3,
+ 0xB,0x6,0x3,0x4,0xC,0xF,0xE,0x2,0x7,0xD,0x8,0x0,0x5,0xA,0x9,0x1,
+ 0x1,0xC,0xB,0x0,0xF,0xE,0x6,0x5,0xA,0xD,0x4,0x8,0x9,0x3,0x7,0x2,
+ 0x1,0x5,0xE,0xC,0xA,0x7,0x0,0xD,0x6,0x2,0xB,0x4,0x9,0x3,0xF,0x8,
+ 0x0,0xC,0x8,0x9,0xD,0x2,0xA,0xB,0x7,0x3,0x6,0x5,0x4,0xE,0xF,0x1,
+ 0x8,0x0,0xF,0x3,0x2,0x5,0xE,0xB,0x1,0xA,0x4,0x7,0xC,0x9,0xD,0x6,
+ 0x3,0x0,0x6,0xF,0x1,0xE,0x9,0x2,0xD,0x8,0xC,0x4,0xB,0xA,0x5,0x7,
+ 0x1,0xA,0x6,0x8,0xF,0xB,0x0,0x4,0xC,0x3,0x5,0x9,0x7,0xD,0x2,0xE
+ };
+
+ //S-box for digest
+ private static byte DSbox_Test[] = {
+ 0x4,0xA,0x9,0x2,0xD,0x8,0x0,0xE,0x6,0xB,0x1,0xC,0x7,0xF,0x5,0x3,
+ 0xE,0xB,0x4,0xC,0x6,0xD,0xF,0xA,0x2,0x3,0x8,0x1,0x0,0x7,0x5,0x9,
+ 0x5,0x8,0x1,0xD,0xA,0x3,0x4,0x2,0xE,0xF,0xC,0x7,0x6,0x0,0x9,0xB,
+ 0x7,0xD,0xA,0x1,0x0,0x8,0x9,0xF,0xE,0x4,0x6,0xC,0xB,0x2,0x5,0x3,
+ 0x6,0xC,0x7,0x1,0x5,0xF,0xD,0x8,0x4,0xA,0x9,0xE,0x0,0x3,0xB,0x2,
+ 0x4,0xB,0xA,0x0,0x7,0x2,0x1,0xD,0x3,0x6,0x8,0x5,0x9,0xC,0xF,0xE,
+ 0xD,0xB,0x4,0x1,0x3,0xF,0x5,0x9,0x0,0xA,0xE,0x7,0x6,0x8,0x2,0xC,
+ 0x1,0xF,0xD,0x0,0x5,0x7,0xA,0x4,0x9,0x2,0x3,0xE,0x6,0xB,0x8,0xC
+ };
+
+ private static byte DSbox_A[] = {
+ 0xA,0x4,0x5,0x6,0x8,0x1,0x3,0x7,0xD,0xC,0xE,0x0,0x9,0x2,0xB,0xF,
+ 0x5,0xF,0x4,0x0,0x2,0xD,0xB,0x9,0x1,0x7,0x6,0x3,0xC,0xE,0xA,0x8,
+ 0x7,0xF,0xC,0xE,0x9,0x4,0x1,0x0,0x3,0xB,0x5,0x2,0x6,0xA,0x8,0xD,
+ 0x4,0xA,0x7,0xC,0x0,0xF,0x2,0x8,0xE,0x1,0x6,0x5,0xD,0xB,0x9,0x3,
+ 0x7,0x6,0x4,0xB,0x9,0xC,0x2,0xA,0x1,0x8,0x0,0xE,0xF,0xD,0x3,0x5,
+ 0x7,0x6,0x2,0x4,0xD,0x9,0xF,0x0,0xA,0x1,0x5,0xB,0x8,0xE,0xC,0x3,
+ 0xD,0xE,0x4,0x1,0x7,0x0,0x5,0xA,0x3,0xC,0x8,0xF,0x6,0x2,0x9,0xB,
+ 0x1,0x3,0xA,0x9,0x5,0xB,0x4,0xF,0x8,0x6,0x7,0xE,0xD,0x0,0x2,0xC
+ };
+
+ //
+ // pre-defined sbox table
+ //
+ private static Hashtable sBoxes = new Hashtable();
+
+ static
+ {
+ addSBox("Default", Sbox_Default);
+ addSBox("E-TEST", ESbox_Test);
+ addSBox("E-A", ESbox_A);
+ addSBox("E-B", ESbox_B);
+ addSBox("E-C", ESbox_C);
+ addSBox("E-D", ESbox_D);
+ addSBox("D-TEST", DSbox_Test);
+ addSBox("D-A", DSbox_A);
+ }
+
+ private static void addSBox(String sBoxName, byte[] sBox)
+ {
+ sBoxes.put(Strings.toUpperCase(sBoxName), sBox);
+ }
+
+ /**
+ * standard constructor.
+ */
+ public GOST28147Engine()
+ {
+ }
+
+ /**
+ * initialise an GOST28147 cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (params instanceof ParametersWithSBox)
+ {
+ ParametersWithSBox param = (ParametersWithSBox)params;
+
+ //
+ // Set the S-Box
+ //
+ byte[] sBox = param.getSBox();
+ if (sBox.length != Sbox_Default.length)
+ {
+ throw new IllegalArgumentException("invalid S-box passed to GOST28147 init");
+ }
+ this.S = Arrays.clone(sBox);
+
+ //
+ // set key if there is one
+ //
+ if (param.getParameters() != null)
+ {
+ workingKey = generateWorkingKey(forEncryption,
+ ((KeyParameter)param.getParameters()).getKey());
+ }
+ }
+ else if (params instanceof KeyParameter)
+ {
+ workingKey = generateWorkingKey(forEncryption,
+ ((KeyParameter)params).getKey());
+ }
+ else if (params != null)
+ {
+ throw new IllegalArgumentException("invalid parameter passed to GOST28147 init - " + params.getClass().getName());
+ }
+ }
+
+ public String getAlgorithmName()
+ {
+ return "GOST28147";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (workingKey == null)
+ {
+ throw new IllegalStateException("GOST28147 engine not initialised");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ GOST28147Func(workingKey, in, inOff, out, outOff);
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+
+ private int[] generateWorkingKey(
+ boolean forEncryption,
+ byte[] userKey)
+ {
+ this.forEncryption = forEncryption;
+
+ if (userKey.length != 32)
+ {
+ throw new IllegalArgumentException("Key length invalid. Key needs to be 32 byte - 256 bit!!!");
+ }
+
+ int key[] = new int[8];
+ for(int i=0; i!=8; i++)
+ {
+ key[i] = bytesToint(userKey,i*4);
+ }
+
+ return key;
+ }
+
+ private int GOST28147_mainStep(int n1, int key)
+ {
+ int cm = (key + n1); // CM1
+
+ // S-box replacing
+
+ int om = S[ 0 + ((cm >> (0 * 4)) & 0xF)] << (0 * 4);
+ om += S[ 16 + ((cm >> (1 * 4)) & 0xF)] << (1 * 4);
+ om += S[ 32 + ((cm >> (2 * 4)) & 0xF)] << (2 * 4);
+ om += S[ 48 + ((cm >> (3 * 4)) & 0xF)] << (3 * 4);
+ om += S[ 64 + ((cm >> (4 * 4)) & 0xF)] << (4 * 4);
+ om += S[ 80 + ((cm >> (5 * 4)) & 0xF)] << (5 * 4);
+ om += S[ 96 + ((cm >> (6 * 4)) & 0xF)] << (6 * 4);
+ om += S[112 + ((cm >> (7 * 4)) & 0xF)] << (7 * 4);
+
+ return om << 11 | om >>> (32-11); // 11-leftshift
+ }
+
+ private void GOST28147Func(
+ int[] workingKey,
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ int N1, N2, tmp; //tmp -> for saving N1
+ N1 = bytesToint(in, inOff);
+ N2 = bytesToint(in, inOff + 4);
+
+ if (this.forEncryption)
+ {
+ for(int k = 0; k < 3; k++) // 1-24 steps
+ {
+ for(int j = 0; j < 8; j++)
+ {
+ tmp = N1;
+ N1 = N2 ^ GOST28147_mainStep(N1, workingKey[j]); // CM2
+ N2 = tmp;
+ }
+ }
+ for(int j = 7; j > 0; j--) // 25-31 steps
+ {
+ tmp = N1;
+ N1 = N2 ^ GOST28147_mainStep(N1, workingKey[j]); // CM2
+ N2 = tmp;
+ }
+ }
+ else //decrypt
+ {
+ for(int j = 0; j < 8; j++) // 1-8 steps
+ {
+ tmp = N1;
+ N1 = N2 ^ GOST28147_mainStep(N1, workingKey[j]); // CM2
+ N2 = tmp;
+ }
+ for(int k = 0; k < 3; k++) //9-31 steps
+ {
+ for(int j = 7; j >= 0; j--)
+ {
+ if ((k == 2) && (j==0))
+ {
+ break; // break 32 step
+ }
+ tmp = N1;
+ N1 = N2 ^ GOST28147_mainStep(N1, workingKey[j]); // CM2
+ N2 = tmp;
+ }
+ }
+ }
+
+ N2 = N2 ^ GOST28147_mainStep(N1, workingKey[0]); // 32 step (N1=N1)
+
+ intTobytes(N1, out, outOff);
+ intTobytes(N2, out, outOff + 4);
+ }
+
+ //array of bytes to type int
+ private int bytesToint(
+ byte[] in,
+ int inOff)
+ {
+ return ((in[inOff + 3] << 24) & 0xff000000) + ((in[inOff + 2] << 16) & 0xff0000) +
+ ((in[inOff + 1] << 8) & 0xff00) + (in[inOff] & 0xff);
+ }
+
+ //int to array of bytes
+ private void intTobytes(
+ int num,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff + 3] = (byte)(num >>> 24);
+ out[outOff + 2] = (byte)(num >>> 16);
+ out[outOff + 1] = (byte)(num >>> 8);
+ out[outOff] = (byte)num;
+ }
+
+ /**
+ * Return the S-Box associated with SBoxName
+ * @param sBoxName name of the S-Box
+ * @return byte array representing the S-Box
+ */
+ public static byte[] getSBox(
+ String sBoxName)
+ {
+ byte[] sBox = (byte[])sBoxes.get(Strings.toUpperCase(sBoxName));
+
+ if (sBox == null)
+ {
+ throw new IllegalArgumentException("Unknown S-Box - possible types: "
+ + "\"Default\", \"E-Test\", \"E-A\", \"E-B\", \"E-C\", \"E-D\", \"D-Test\", \"D-A\".");
+ }
+
+ return Arrays.clone(sBox);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/Grain128Engine.java b/core/src/main/java/org/spongycastle/crypto/engines/Grain128Engine.java
new file mode 100644
index 00000000..eedd26c7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/Grain128Engine.java
@@ -0,0 +1,304 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.StreamCipher;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+
+/**
+ * Implementation of Martin Hell's, Thomas Johansson's and Willi Meier's stream
+ * cipher, Grain-128.
+ */
+public class Grain128Engine
+ implements StreamCipher
+{
+
+ /**
+ * Constants
+ */
+ private static final int STATE_SIZE = 4;
+
+ /**
+ * Variables to hold the state of the engine during encryption and
+ * decryption
+ */
+ private byte[] workingKey;
+ private byte[] workingIV;
+ private byte[] out;
+ private int[] lfsr;
+ private int[] nfsr;
+ private int output;
+ private int index = 4;
+
+ private boolean initialised = false;
+
+ public String getAlgorithmName()
+ {
+ return "Grain-128";
+ }
+
+ /**
+ * Initialize a Grain-128 cipher.
+ *
+ * @param forEncryption Whether or not we are for encryption.
+ * @param params The parameters required to set up the cipher.
+ * @throws IllegalArgumentException If the params argument is inappropriate.
+ */
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ /**
+ * Grain encryption and decryption is completely symmetrical, so the
+ * 'forEncryption' is irrelevant.
+ */
+ if (!(params instanceof ParametersWithIV))
+ {
+ throw new IllegalArgumentException(
+ "Grain-128 Init parameters must include an IV");
+ }
+
+ ParametersWithIV ivParams = (ParametersWithIV)params;
+
+ byte[] iv = ivParams.getIV();
+
+ if (iv == null || iv.length != 12)
+ {
+ throw new IllegalArgumentException(
+ "Grain-128 requires exactly 12 bytes of IV");
+ }
+
+ if (!(ivParams.getParameters() instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException(
+ "Grain-128 Init parameters must include a key");
+ }
+
+ KeyParameter key = (KeyParameter)ivParams.getParameters();
+
+ /**
+ * Initialize variables.
+ */
+ workingIV = new byte[key.getKey().length];
+ workingKey = new byte[key.getKey().length];
+ lfsr = new int[STATE_SIZE];
+ nfsr = new int[STATE_SIZE];
+ out = new byte[4];
+
+ System.arraycopy(iv, 0, workingIV, 0, iv.length);
+ System.arraycopy(key.getKey(), 0, workingKey, 0, key.getKey().length);
+
+ reset();
+ }
+
+ /**
+ * 256 clocks initialization phase.
+ */
+ private void initGrain()
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ output = getOutput();
+ nfsr = shift(nfsr, getOutputNFSR() ^ lfsr[0] ^ output);
+ lfsr = shift(lfsr, getOutputLFSR() ^ output);
+ }
+ initialised = true;
+ }
+
+ /**
+ * Get output from non-linear function g(x).
+ *
+ * @return Output from NFSR.
+ */
+ private int getOutputNFSR()
+ {
+ int b0 = nfsr[0];
+ int b3 = nfsr[0] >>> 3 | nfsr[1] << 29;
+ int b11 = nfsr[0] >>> 11 | nfsr[1] << 21;
+ int b13 = nfsr[0] >>> 13 | nfsr[1] << 19;
+ int b17 = nfsr[0] >>> 17 | nfsr[1] << 15;
+ int b18 = nfsr[0] >>> 18 | nfsr[1] << 14;
+ int b26 = nfsr[0] >>> 26 | nfsr[1] << 6;
+ int b27 = nfsr[0] >>> 27 | nfsr[1] << 5;
+ int b40 = nfsr[1] >>> 8 | nfsr[2] << 24;
+ int b48 = nfsr[1] >>> 16 | nfsr[2] << 16;
+ int b56 = nfsr[1] >>> 24 | nfsr[2] << 8;
+ int b59 = nfsr[1] >>> 27 | nfsr[2] << 5;
+ int b61 = nfsr[1] >>> 29 | nfsr[2] << 3;
+ int b65 = nfsr[2] >>> 1 | nfsr[3] << 31;
+ int b67 = nfsr[2] >>> 3 | nfsr[3] << 29;
+ int b68 = nfsr[2] >>> 4 | nfsr[3] << 28;
+ int b84 = nfsr[2] >>> 20 | nfsr[3] << 12;
+ int b91 = nfsr[2] >>> 27 | nfsr[3] << 5;
+ int b96 = nfsr[3];
+
+ return b0 ^ b26 ^ b56 ^ b91 ^ b96 ^ b3 & b67 ^ b11 & b13 ^ b17 & b18
+ ^ b27 & b59 ^ b40 & b48 ^ b61 & b65 ^ b68 & b84;
+ }
+
+ /**
+ * Get output from linear function f(x).
+ *
+ * @return Output from LFSR.
+ */
+ private int getOutputLFSR()
+ {
+ int s0 = lfsr[0];
+ int s7 = lfsr[0] >>> 7 | lfsr[1] << 25;
+ int s38 = lfsr[1] >>> 6 | lfsr[2] << 26;
+ int s70 = lfsr[2] >>> 6 | lfsr[3] << 26;
+ int s81 = lfsr[2] >>> 17 | lfsr[3] << 15;
+ int s96 = lfsr[3];
+
+ return s0 ^ s7 ^ s38 ^ s70 ^ s81 ^ s96;
+ }
+
+ /**
+ * Get output from output function h(x).
+ *
+ * @return Output from h(x).
+ */
+ private int getOutput()
+ {
+ int b2 = nfsr[0] >>> 2 | nfsr[1] << 30;
+ int b12 = nfsr[0] >>> 12 | nfsr[1] << 20;
+ int b15 = nfsr[0] >>> 15 | nfsr[1] << 17;
+ int b36 = nfsr[1] >>> 4 | nfsr[2] << 28;
+ int b45 = nfsr[1] >>> 13 | nfsr[2] << 19;
+ int b64 = nfsr[2];
+ int b73 = nfsr[2] >>> 9 | nfsr[3] << 23;
+ int b89 = nfsr[2] >>> 25 | nfsr[3] << 7;
+ int b95 = nfsr[2] >>> 31 | nfsr[3] << 1;
+ int s8 = lfsr[0] >>> 8 | lfsr[1] << 24;
+ int s13 = lfsr[0] >>> 13 | lfsr[1] << 19;
+ int s20 = lfsr[0] >>> 20 | lfsr[1] << 12;
+ int s42 = lfsr[1] >>> 10 | lfsr[2] << 22;
+ int s60 = lfsr[1] >>> 28 | lfsr[2] << 4;
+ int s79 = lfsr[2] >>> 15 | lfsr[3] << 17;
+ int s93 = lfsr[2] >>> 29 | lfsr[3] << 3;
+ int s95 = lfsr[2] >>> 31 | lfsr[3] << 1;
+
+ return b12 & s8 ^ s13 & s20 ^ b95 & s42 ^ s60 & s79 ^ b12 & b95 & s95 ^ s93
+ ^ b2 ^ b15 ^ b36 ^ b45 ^ b64 ^ b73 ^ b89;
+ }
+
+ /**
+ * Shift array 32 bits and add val to index.length - 1.
+ *
+ * @param array The array to shift.
+ * @param val The value to shift in.
+ * @return The shifted array with val added to index.length - 1.
+ */
+ private int[] shift(int[] array, int val)
+ {
+ array[0] = array[1];
+ array[1] = array[2];
+ array[2] = array[3];
+ array[3] = val;
+
+ return array;
+ }
+
+ /**
+ * Set keys, reset cipher.
+ *
+ * @param keyBytes The key.
+ * @param ivBytes The IV.
+ */
+ private void setKey(byte[] keyBytes, byte[] ivBytes)
+ {
+ ivBytes[12] = (byte)0xFF;
+ ivBytes[13] = (byte)0xFF;
+ ivBytes[14] = (byte)0xFF;
+ ivBytes[15] = (byte)0xFF;
+ workingKey = keyBytes;
+ workingIV = ivBytes;
+
+ /**
+ * Load NFSR and LFSR
+ */
+ int j = 0;
+ for (int i = 0; i < nfsr.length; i++)
+ {
+ nfsr[i] = ((workingKey[j + 3]) << 24) | ((workingKey[j + 2]) << 16)
+ & 0x00FF0000 | ((workingKey[j + 1]) << 8) & 0x0000FF00
+ | ((workingKey[j]) & 0x000000FF);
+
+ lfsr[i] = ((workingIV[j + 3]) << 24) | ((workingIV[j + 2]) << 16)
+ & 0x00FF0000 | ((workingIV[j + 1]) << 8) & 0x0000FF00
+ | ((workingIV[j]) & 0x000000FF);
+ j += 4;
+ }
+ }
+
+ public int processBytes(byte[] in, int inOff, int len, byte[] out,
+ int outOff)
+ throws DataLengthException
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName()
+ + " not initialised");
+ }
+
+ if ((inOff + len) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + len) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ for (int i = 0; i < len; i++)
+ {
+ out[outOff + i] = (byte)(in[inOff + i] ^ getKeyStream());
+ }
+
+ return len;
+ }
+
+ public void reset()
+ {
+ index = 4;
+ setKey(workingKey, workingIV);
+ initGrain();
+ }
+
+ /**
+ * Run Grain one round(i.e. 32 bits).
+ */
+ private void oneRound()
+ {
+ output = getOutput();
+ out[0] = (byte)output;
+ out[1] = (byte)(output >> 8);
+ out[2] = (byte)(output >> 16);
+ out[3] = (byte)(output >> 24);
+
+ nfsr = shift(nfsr, getOutputNFSR() ^ lfsr[0]);
+ lfsr = shift(lfsr, getOutputLFSR());
+ }
+
+ public byte returnByte(byte in)
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName()
+ + " not initialised");
+ }
+ return (byte)(in ^ getKeyStream());
+ }
+
+ private byte getKeyStream()
+ {
+ if (index > 3)
+ {
+ oneRound();
+ index = 0;
+ }
+ return out[index++];
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/Grainv1Engine.java b/core/src/main/java/org/spongycastle/crypto/engines/Grainv1Engine.java
new file mode 100644
index 00000000..69f78772
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/Grainv1Engine.java
@@ -0,0 +1,290 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.StreamCipher;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+
+/**
+ * Implementation of Martin Hell's, Thomas Johansson's and Willi Meier's stream
+ * cipher, Grain v1.
+ */
+public class Grainv1Engine
+ implements StreamCipher
+{
+
+ /**
+ * Constants
+ */
+ private static final int STATE_SIZE = 5;
+
+ /**
+ * Variables to hold the state of the engine during encryption and
+ * decryption
+ */
+ private byte[] workingKey;
+ private byte[] workingIV;
+ private byte[] out;
+ private int[] lfsr;
+ private int[] nfsr;
+ private int output;
+ private int index = 2;
+
+ private boolean initialised = false;
+
+ public String getAlgorithmName()
+ {
+ return "Grain v1";
+ }
+
+ /**
+ * Initialize a Grain v1 cipher.
+ *
+ * @param forEncryption Whether or not we are for encryption.
+ * @param params The parameters required to set up the cipher.
+ * @throws IllegalArgumentException If the params argument is inappropriate.
+ */
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ /**
+ * Grain encryption and decryption is completely symmetrical, so the
+ * 'forEncryption' is irrelevant.
+ */
+ if (!(params instanceof ParametersWithIV))
+ {
+ throw new IllegalArgumentException(
+ "Grain v1 Init parameters must include an IV");
+ }
+
+ ParametersWithIV ivParams = (ParametersWithIV)params;
+
+ byte[] iv = ivParams.getIV();
+
+ if (iv == null || iv.length != 8)
+ {
+ throw new IllegalArgumentException(
+ "Grain v1 requires exactly 8 bytes of IV");
+ }
+
+ if (!(ivParams.getParameters() instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException(
+ "Grain v1 Init parameters must include a key");
+ }
+
+ KeyParameter key = (KeyParameter)ivParams.getParameters();
+
+ /**
+ * Initialize variables.
+ */
+ workingIV = new byte[key.getKey().length];
+ workingKey = new byte[key.getKey().length];
+ lfsr = new int[STATE_SIZE];
+ nfsr = new int[STATE_SIZE];
+ out = new byte[2];
+
+ System.arraycopy(iv, 0, workingIV, 0, iv.length);
+ System.arraycopy(key.getKey(), 0, workingKey, 0, key.getKey().length);
+
+ reset();
+ }
+
+ /**
+ * 160 clocks initialization phase.
+ */
+ private void initGrain()
+ {
+ for (int i = 0; i < 10; i++)
+ {
+ output = getOutput();
+ nfsr = shift(nfsr, getOutputNFSR() ^ lfsr[0] ^ output);
+ lfsr = shift(lfsr, getOutputLFSR() ^ output);
+ }
+ initialised = true;
+ }
+
+ /**
+ * Get output from non-linear function g(x).
+ *
+ * @return Output from NFSR.
+ */
+ private int getOutputNFSR()
+ {
+ int b0 = nfsr[0];
+ int b9 = nfsr[0] >>> 9 | nfsr[1] << 7;
+ int b14 = nfsr[0] >>> 14 | nfsr[1] << 2;
+ int b15 = nfsr[0] >>> 15 | nfsr[1] << 1;
+ int b21 = nfsr[1] >>> 5 | nfsr[2] << 11;
+ int b28 = nfsr[1] >>> 12 | nfsr[2] << 4;
+ int b33 = nfsr[2] >>> 1 | nfsr[3] << 15;
+ int b37 = nfsr[2] >>> 5 | nfsr[3] << 11;
+ int b45 = nfsr[2] >>> 13 | nfsr[3] << 3;
+ int b52 = nfsr[3] >>> 4 | nfsr[4] << 12;
+ int b60 = nfsr[3] >>> 12 | nfsr[4] << 4;
+ int b62 = nfsr[3] >>> 14 | nfsr[4] << 2;
+ int b63 = nfsr[3] >>> 15 | nfsr[4] << 1;
+
+ return (b62 ^ b60 ^ b52 ^ b45 ^ b37 ^ b33 ^ b28 ^ b21 ^ b14
+ ^ b9 ^ b0 ^ b63 & b60 ^ b37 & b33 ^ b15 & b9 ^ b60 & b52 & b45
+ ^ b33 & b28 & b21 ^ b63 & b45 & b28 & b9 ^ b60 & b52 & b37
+ & b33 ^ b63 & b60 & b21 & b15 ^ b63 & b60 & b52 & b45 & b37
+ ^ b33 & b28 & b21 & b15 & b9 ^ b52 & b45 & b37 & b33 & b28
+ & b21) & 0x0000FFFF;
+ }
+
+ /**
+ * Get output from linear function f(x).
+ *
+ * @return Output from LFSR.
+ */
+ private int getOutputLFSR()
+ {
+ int s0 = lfsr[0];
+ int s13 = lfsr[0] >>> 13 | lfsr[1] << 3;
+ int s23 = lfsr[1] >>> 7 | lfsr[2] << 9;
+ int s38 = lfsr[2] >>> 6 | lfsr[3] << 10;
+ int s51 = lfsr[3] >>> 3 | lfsr[4] << 13;
+ int s62 = lfsr[3] >>> 14 | lfsr[4] << 2;
+
+ return (s0 ^ s13 ^ s23 ^ s38 ^ s51 ^ s62) & 0x0000FFFF;
+ }
+
+ /**
+ * Get output from output function h(x).
+ *
+ * @return Output from h(x).
+ */
+ private int getOutput()
+ {
+ int b1 = nfsr[0] >>> 1 | nfsr[1] << 15;
+ int b2 = nfsr[0] >>> 2 | nfsr[1] << 14;
+ int b4 = nfsr[0] >>> 4 | nfsr[1] << 12;
+ int b10 = nfsr[0] >>> 10 | nfsr[1] << 6;
+ int b31 = nfsr[1] >>> 15 | nfsr[2] << 1;
+ int b43 = nfsr[2] >>> 11 | nfsr[3] << 5;
+ int b56 = nfsr[3] >>> 8 | nfsr[4] << 8;
+ int b63 = nfsr[3] >>> 15 | nfsr[4] << 1;
+ int s3 = lfsr[0] >>> 3 | lfsr[1] << 13;
+ int s25 = lfsr[1] >>> 9 | lfsr[2] << 7;
+ int s46 = lfsr[2] >>> 14 | lfsr[3] << 2;
+ int s64 = lfsr[4];
+
+ return (s25 ^ b63 ^ s3 & s64 ^ s46 & s64 ^ s64 & b63 ^ s3
+ & s25 & s46 ^ s3 & s46 & s64 ^ s3 & s46 & b63 ^ s25 & s46 & b63 ^ s46
+ & s64 & b63 ^ b1 ^ b2 ^ b4 ^ b10 ^ b31 ^ b43 ^ b56) & 0x0000FFFF;
+ }
+
+ /**
+ * Shift array 16 bits and add val to index.length - 1.
+ *
+ * @param array The array to shift.
+ * @param val The value to shift in.
+ * @return The shifted array with val added to index.length - 1.
+ */
+ private int[] shift(int[] array, int val)
+ {
+ array[0] = array[1];
+ array[1] = array[2];
+ array[2] = array[3];
+ array[3] = array[4];
+ array[4] = val;
+
+ return array;
+ }
+
+ /**
+ * Set keys, reset cipher.
+ *
+ * @param keyBytes The key.
+ * @param ivBytes The IV.
+ */
+ private void setKey(byte[] keyBytes, byte[] ivBytes)
+ {
+ ivBytes[8] = (byte)0xFF;
+ ivBytes[9] = (byte)0xFF;
+ workingKey = keyBytes;
+ workingIV = ivBytes;
+
+ /**
+ * Load NFSR and LFSR
+ */
+ int j = 0;
+ for (int i = 0; i < nfsr.length; i++)
+ {
+ nfsr[i] = (workingKey[j + 1] << 8 | workingKey[j] & 0xFF) & 0x0000FFFF;
+ lfsr[i] = (workingIV[j + 1] << 8 | workingIV[j] & 0xFF) & 0x0000FFFF;
+ j += 2;
+ }
+ }
+
+ public int processBytes(byte[] in, int inOff, int len, byte[] out,
+ int outOff)
+ throws DataLengthException
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName()
+ + " not initialised");
+ }
+
+ if ((inOff + len) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + len) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ for (int i = 0; i < len; i++)
+ {
+ out[outOff + i] = (byte)(in[inOff + i] ^ getKeyStream());
+ }
+
+ return len;
+ }
+
+ public void reset()
+ {
+ index = 2;
+ setKey(workingKey, workingIV);
+ initGrain();
+ }
+
+ /**
+ * Run Grain one round(i.e. 16 bits).
+ */
+ private void oneRound()
+ {
+ output = getOutput();
+ out[0] = (byte)output;
+ out[1] = (byte)(output >> 8);
+
+ nfsr = shift(nfsr, getOutputNFSR() ^ lfsr[0]);
+ lfsr = shift(lfsr, getOutputLFSR());
+ }
+
+ public byte returnByte(byte in)
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName()
+ + " not initialised");
+ }
+ return (byte)(in ^ getKeyStream());
+ }
+
+ private byte getKeyStream()
+ {
+ if (index > 1)
+ {
+ oneRound();
+ index = 0;
+ }
+ return out[index++];
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/HC128Engine.java b/core/src/main/java/org/spongycastle/crypto/engines/HC128Engine.java
new file mode 100644
index 00000000..93882825
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/HC128Engine.java
@@ -0,0 +1,259 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.StreamCipher;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+
+/**
+ * HC-128 is a software-efficient stream cipher created by Hongjun Wu. It
+ * generates keystream from a 128-bit secret key and a 128-bit initialization
+ * vector.
+ * <p>
+ * http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc128_p3.pdf
+ * </p><p>
+ * It is a third phase candidate in the eStream contest, and is patent-free.
+ * No attacks are known as of today (April 2007). See
+ *
+ * http://www.ecrypt.eu.org/stream/hcp3.html
+ * </p>
+ */
+public class HC128Engine
+ implements StreamCipher
+{
+ private int[] p = new int[512];
+ private int[] q = new int[512];
+ private int cnt = 0;
+
+ private static int f1(int x)
+ {
+ return rotateRight(x, 7) ^ rotateRight(x, 18)
+ ^ (x >>> 3);
+ }
+
+ private static int f2(int x)
+ {
+ return rotateRight(x, 17) ^ rotateRight(x, 19)
+ ^ (x >>> 10);
+ }
+
+ private int g1(int x, int y, int z)
+ {
+ return (rotateRight(x, 10) ^ rotateRight(z, 23))
+ + rotateRight(y, 8);
+ }
+
+ private int g2(int x, int y, int z)
+ {
+ return (rotateLeft(x, 10) ^ rotateLeft(z, 23)) + rotateLeft(y, 8);
+ }
+
+ private static int rotateLeft(
+ int x,
+ int bits)
+ {
+ return (x << bits) | (x >>> -bits);
+ }
+
+ private static int rotateRight(
+ int x,
+ int bits)
+ {
+ return (x >>> bits) | (x << -bits);
+ }
+
+ private int h1(int x)
+ {
+ return q[x & 0xFF] + q[((x >> 16) & 0xFF) + 256];
+ }
+
+ private int h2(int x)
+ {
+ return p[x & 0xFF] + p[((x >> 16) & 0xFF) + 256];
+ }
+
+ private static int mod1024(int x)
+ {
+ return x & 0x3FF;
+ }
+
+ private static int mod512(int x)
+ {
+ return x & 0x1FF;
+ }
+
+ private static int dim(int x, int y)
+ {
+ return mod512(x - y);
+ }
+
+ private int step()
+ {
+ int j = mod512(cnt);
+ int ret;
+ if (cnt < 512)
+ {
+ p[j] += g1(p[dim(j, 3)], p[dim(j, 10)], p[dim(j, 511)]);
+ ret = h1(p[dim(j, 12)]) ^ p[j];
+ }
+ else
+ {
+ q[j] += g2(q[dim(j, 3)], q[dim(j, 10)], q[dim(j, 511)]);
+ ret = h2(q[dim(j, 12)]) ^ q[j];
+ }
+ cnt = mod1024(cnt + 1);
+ return ret;
+ }
+
+ private byte[] key, iv;
+ private boolean initialised;
+
+ private void init()
+ {
+ if (key.length != 16)
+ {
+ throw new java.lang.IllegalArgumentException(
+ "The key must be 128 bits long");
+ }
+
+ idx = 0;
+ cnt = 0;
+
+ int[] w = new int[1280];
+
+ for (int i = 0; i < 16; i++)
+ {
+ w[i >> 2] |= (key[i] & 0xff) << (8 * (i & 0x3));
+ }
+ System.arraycopy(w, 0, w, 4, 4);
+
+ for (int i = 0; i < iv.length && i < 16; i++)
+ {
+ w[(i >> 2) + 8] |= (iv[i] & 0xff) << (8 * (i & 0x3));
+ }
+ System.arraycopy(w, 8, w, 12, 4);
+
+ for (int i = 16; i < 1280; i++)
+ {
+ w[i] = f2(w[i - 2]) + w[i - 7] + f1(w[i - 15]) + w[i - 16] + i;
+ }
+
+ System.arraycopy(w, 256, p, 0, 512);
+ System.arraycopy(w, 768, q, 0, 512);
+
+ for (int i = 0; i < 512; i++)
+ {
+ p[i] = step();
+ }
+ for (int i = 0; i < 512; i++)
+ {
+ q[i] = step();
+ }
+
+ cnt = 0;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "HC-128";
+ }
+
+ /**
+ * Initialise a HC-128 cipher.
+ *
+ * @param forEncryption whether or not we are for encryption. Irrelevant, as
+ * encryption and decryption are the same.
+ * @param params the parameters required to set up the cipher.
+ * @throws IllegalArgumentException if the params argument is
+ * inappropriate (ie. the key is not 128 bit long).
+ */
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ CipherParameters keyParam = params;
+
+ if (params instanceof ParametersWithIV)
+ {
+ iv = ((ParametersWithIV)params).getIV();
+ keyParam = ((ParametersWithIV)params).getParameters();
+ }
+ else
+ {
+ iv = new byte[0];
+ }
+
+ if (keyParam instanceof KeyParameter)
+ {
+ key = ((KeyParameter)keyParam).getKey();
+ init();
+ }
+ else
+ {
+ throw new IllegalArgumentException(
+ "Invalid parameter passed to HC128 init - "
+ + params.getClass().getName());
+ }
+
+ initialised = true;
+ }
+
+ private byte[] buf = new byte[4];
+ private int idx = 0;
+
+ private byte getByte()
+ {
+ if (idx == 0)
+ {
+ int step = step();
+ buf[0] = (byte)(step & 0xFF);
+ step >>= 8;
+ buf[1] = (byte)(step & 0xFF);
+ step >>= 8;
+ buf[2] = (byte)(step & 0xFF);
+ step >>= 8;
+ buf[3] = (byte)(step & 0xFF);
+ }
+ byte ret = buf[idx];
+ idx = idx + 1 & 0x3;
+ return ret;
+ }
+
+ public int processBytes(byte[] in, int inOff, int len, byte[] out,
+ int outOff) throws DataLengthException
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName()
+ + " not initialised");
+ }
+
+ if ((inOff + len) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + len) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ for (int i = 0; i < len; i++)
+ {
+ out[outOff + i] = (byte)(in[inOff + i] ^ getByte());
+ }
+
+ return len;
+ }
+
+ public void reset()
+ {
+ init();
+ }
+
+ public byte returnByte(byte in)
+ {
+ return (byte)(in ^ getByte());
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/HC256Engine.java b/core/src/main/java/org/spongycastle/crypto/engines/HC256Engine.java
new file mode 100644
index 00000000..4e42672b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/HC256Engine.java
@@ -0,0 +1,246 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.StreamCipher;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+
+/**
+ * HC-256 is a software-efficient stream cipher created by Hongjun Wu. It
+ * generates keystream from a 256-bit secret key and a 256-bit initialization
+ * vector.
+ * <p>
+ * http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc256_p3.pdf
+ * </p><p>
+ * Its brother, HC-128, is a third phase candidate in the eStream contest.
+ * The algorithm is patent-free. No attacks are known as of today (April 2007).
+ * See
+ *
+ * http://www.ecrypt.eu.org/stream/hcp3.html
+ * </p>
+ */
+public class HC256Engine
+ implements StreamCipher
+{
+ private int[] p = new int[1024];
+ private int[] q = new int[1024];
+ private int cnt = 0;
+
+ private int step()
+ {
+ int j = cnt & 0x3FF;
+ int ret;
+ if (cnt < 1024)
+ {
+ int x = p[(j - 3 & 0x3FF)];
+ int y = p[(j - 1023 & 0x3FF)];
+ p[j] += p[(j - 10 & 0x3FF)]
+ + (rotateRight(x, 10) ^ rotateRight(y, 23))
+ + q[((x ^ y) & 0x3FF)];
+
+ x = p[(j - 12 & 0x3FF)];
+ ret = (q[x & 0xFF] + q[((x >> 8) & 0xFF) + 256]
+ + q[((x >> 16) & 0xFF) + 512] + q[((x >> 24) & 0xFF) + 768])
+ ^ p[j];
+ }
+ else
+ {
+ int x = q[(j - 3 & 0x3FF)];
+ int y = q[(j - 1023 & 0x3FF)];
+ q[j] += q[(j - 10 & 0x3FF)]
+ + (rotateRight(x, 10) ^ rotateRight(y, 23))
+ + p[((x ^ y) & 0x3FF)];
+
+ x = q[(j - 12 & 0x3FF)];
+ ret = (p[x & 0xFF] + p[((x >> 8) & 0xFF) + 256]
+ + p[((x >> 16) & 0xFF) + 512] + p[((x >> 24) & 0xFF) + 768])
+ ^ q[j];
+ }
+ cnt = cnt + 1 & 0x7FF;
+ return ret;
+ }
+
+ private byte[] key, iv;
+ private boolean initialised;
+
+ private void init()
+ {
+ if (key.length != 32 && key.length != 16)
+ {
+ throw new IllegalArgumentException(
+ "The key must be 128/256 bits long");
+ }
+
+ if (iv.length < 16)
+ {
+ throw new IllegalArgumentException(
+ "The IV must be at least 128 bits long");
+ }
+
+ if (key.length != 32)
+ {
+ byte[] k = new byte[32];
+
+ System.arraycopy(key, 0, k, 0, key.length);
+ System.arraycopy(key, 0, k, 16, key.length);
+
+ key = k;
+ }
+
+ if (iv.length < 32)
+ {
+ byte[] newIV = new byte[32];
+
+ System.arraycopy(iv, 0, newIV, 0, iv.length);
+ System.arraycopy(iv, 0, newIV, iv.length, newIV.length - iv.length);
+
+ iv = newIV;
+ }
+
+ idx = 0;
+ cnt = 0;
+
+ int[] w = new int[2560];
+
+ for (int i = 0; i < 32; i++)
+ {
+ w[i >> 2] |= (key[i] & 0xff) << (8 * (i & 0x3));
+ }
+
+ for (int i = 0; i < 32; i++)
+ {
+ w[(i >> 2) + 8] |= (iv[i] & 0xff) << (8 * (i & 0x3));
+ }
+
+ for (int i = 16; i < 2560; i++)
+ {
+ int x = w[i - 2];
+ int y = w[i - 15];
+ w[i] = (rotateRight(x, 17) ^ rotateRight(x, 19) ^ (x >>> 10))
+ + w[i - 7]
+ + (rotateRight(y, 7) ^ rotateRight(y, 18) ^ (y >>> 3))
+ + w[i - 16] + i;
+ }
+
+ System.arraycopy(w, 512, p, 0, 1024);
+ System.arraycopy(w, 1536, q, 0, 1024);
+
+ for (int i = 0; i < 4096; i++)
+ {
+ step();
+ }
+
+ cnt = 0;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "HC-256";
+ }
+
+ /**
+ * Initialise a HC-256 cipher.
+ *
+ * @param forEncryption whether or not we are for encryption. Irrelevant, as
+ * encryption and decryption are the same.
+ * @param params the parameters required to set up the cipher.
+ * @throws IllegalArgumentException if the params argument is
+ * inappropriate (ie. the key is not 256 bit long).
+ */
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ CipherParameters keyParam = params;
+
+ if (params instanceof ParametersWithIV)
+ {
+ iv = ((ParametersWithIV)params).getIV();
+ keyParam = ((ParametersWithIV)params).getParameters();
+ }
+ else
+ {
+ iv = new byte[0];
+ }
+
+ if (keyParam instanceof KeyParameter)
+ {
+ key = ((KeyParameter)keyParam).getKey();
+ init();
+ }
+ else
+ {
+ throw new IllegalArgumentException(
+ "Invalid parameter passed to HC256 init - "
+ + params.getClass().getName());
+ }
+
+ initialised = true;
+ }
+
+ private byte[] buf = new byte[4];
+ private int idx = 0;
+
+ private byte getByte()
+ {
+ if (idx == 0)
+ {
+ int step = step();
+ buf[0] = (byte)(step & 0xFF);
+ step >>= 8;
+ buf[1] = (byte)(step & 0xFF);
+ step >>= 8;
+ buf[2] = (byte)(step & 0xFF);
+ step >>= 8;
+ buf[3] = (byte)(step & 0xFF);
+ }
+ byte ret = buf[idx];
+ idx = idx + 1 & 0x3;
+ return ret;
+ }
+
+ public int processBytes(byte[] in, int inOff, int len, byte[] out,
+ int outOff) throws DataLengthException
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName()
+ + " not initialised");
+ }
+
+ if ((inOff + len) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + len) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ for (int i = 0; i < len; i++)
+ {
+ out[outOff + i] = (byte)(in[inOff + i] ^ getByte());
+ }
+
+ return len;
+ }
+
+ public void reset()
+ {
+ init();
+ }
+
+ public byte returnByte(byte in)
+ {
+ return (byte)(in ^ getByte());
+ }
+
+ private static int rotateRight(
+ int x,
+ int bits)
+ {
+ return (x >>> bits) | (x << -bits);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/IDEAEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/IDEAEngine.java
new file mode 100644
index 00000000..68cef879
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/IDEAEngine.java
@@ -0,0 +1,357 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+
+/**
+ * A class that provides a basic International Data Encryption Algorithm (IDEA) engine.
+ * <p>
+ * This implementation is based on the "HOWTO: INTERNATIONAL DATA ENCRYPTION ALGORITHM"
+ * implementation summary by Fauzan Mirza (F.U.Mirza@sheffield.ac.uk). (barring 1 typo at the
+ * end of the mulinv function!).
+ * <p>
+ * It can be found at ftp://ftp.funet.fi/pub/crypt/cryptography/symmetric/idea/
+ * <p>
+ * Note: This algorithm was patented in the USA, Japan and Europe. These patents expired in 2011/2012.
+ */
+public class IDEAEngine
+ implements BlockCipher
+{
+ protected static final int BLOCK_SIZE = 8;
+
+ private int[] workingKey = null;
+
+ /**
+ * standard constructor.
+ */
+ public IDEAEngine()
+ {
+ }
+
+ /**
+ * initialise an IDEA cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (params instanceof KeyParameter)
+ {
+ workingKey = generateWorkingKey(forEncryption,
+ ((KeyParameter)params).getKey());
+ return;
+ }
+
+ throw new IllegalArgumentException("invalid parameter passed to IDEA init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "IDEA";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (workingKey == null)
+ {
+ throw new IllegalStateException("IDEA engine not initialised");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ ideaFunc(workingKey, in, inOff, out, outOff);
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+
+ private static final int MASK = 0xffff;
+ private static final int BASE = 0x10001;
+
+ private int bytesToWord(
+ byte[] in,
+ int inOff)
+ {
+ return ((in[inOff] << 8) & 0xff00) + (in[inOff + 1] & 0xff);
+ }
+
+ private void wordToBytes(
+ int word,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff] = (byte)(word >>> 8);
+ out[outOff + 1] = (byte)word;
+ }
+
+ /**
+ * return x = x * y where the multiplication is done modulo
+ * 65537 (0x10001) (as defined in the IDEA specification) and
+ * a zero input is taken to be 65536 (0x10000).
+ *
+ * @param x the x value
+ * @param y the y value
+ * @return x = x * y
+ */
+ private int mul(
+ int x,
+ int y)
+ {
+ if (x == 0)
+ {
+ x = (BASE - y);
+ }
+ else if (y == 0)
+ {
+ x = (BASE - x);
+ }
+ else
+ {
+ int p = x * y;
+
+ y = p & MASK;
+ x = p >>> 16;
+ x = y - x + ((y < x) ? 1 : 0);
+ }
+
+ return x & MASK;
+ }
+
+ private void ideaFunc(
+ int[] workingKey,
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ int x0, x1, x2, x3, t0, t1;
+ int keyOff = 0;
+
+ x0 = bytesToWord(in, inOff);
+ x1 = bytesToWord(in, inOff + 2);
+ x2 = bytesToWord(in, inOff + 4);
+ x3 = bytesToWord(in, inOff + 6);
+
+ for (int round = 0; round < 8; round++)
+ {
+ x0 = mul(x0, workingKey[keyOff++]);
+ x1 += workingKey[keyOff++];
+ x1 &= MASK;
+ x2 += workingKey[keyOff++];
+ x2 &= MASK;
+ x3 = mul(x3, workingKey[keyOff++]);
+
+ t0 = x1;
+ t1 = x2;
+ x2 ^= x0;
+ x1 ^= x3;
+
+ x2 = mul(x2, workingKey[keyOff++]);
+ x1 += x2;
+ x1 &= MASK;
+
+ x1 = mul(x1, workingKey[keyOff++]);
+ x2 += x1;
+ x2 &= MASK;
+
+ x0 ^= x1;
+ x3 ^= x2;
+ x1 ^= t1;
+ x2 ^= t0;
+ }
+
+ wordToBytes(mul(x0, workingKey[keyOff++]), out, outOff);
+ wordToBytes(x2 + workingKey[keyOff++], out, outOff + 2); /* NB: Order */
+ wordToBytes(x1 + workingKey[keyOff++], out, outOff + 4);
+ wordToBytes(mul(x3, workingKey[keyOff]), out, outOff + 6);
+ }
+
+ /**
+ * The following function is used to expand the user key to the encryption
+ * subkey. The first 16 bytes are the user key, and the rest of the subkey
+ * is calculated by rotating the previous 16 bytes by 25 bits to the left,
+ * and so on until the subkey is completed.
+ */
+ private int[] expandKey(
+ byte[] uKey)
+ {
+ int[] key = new int[52];
+
+ if (uKey.length < 16)
+ {
+ byte[] tmp = new byte[16];
+
+ System.arraycopy(uKey, 0, tmp, tmp.length - uKey.length, uKey.length);
+
+ uKey = tmp;
+ }
+
+ for (int i = 0; i < 8; i++)
+ {
+ key[i] = bytesToWord(uKey, i * 2);
+ }
+
+ for (int i = 8; i < 52; i++)
+ {
+ if ((i & 7) < 6)
+ {
+ key[i] = ((key[i - 7] & 127) << 9 | key[i - 6] >> 7) & MASK;
+ }
+ else if ((i & 7) == 6)
+ {
+ key[i] = ((key[i - 7] & 127) << 9 | key[i - 14] >> 7) & MASK;
+ }
+ else
+ {
+ key[i] = ((key[i - 15] & 127) << 9 | key[i - 14] >> 7) & MASK;
+ }
+ }
+
+ return key;
+ }
+
+ /**
+ * This function computes multiplicative inverse using Euclid's Greatest
+ * Common Divisor algorithm. Zero and one are self inverse.
+ * <p>
+ * i.e. x * mulInv(x) == 1 (modulo BASE)
+ */
+ private int mulInv(
+ int x)
+ {
+ int t0, t1, q, y;
+
+ if (x < 2)
+ {
+ return x;
+ }
+
+ t0 = 1;
+ t1 = BASE / x;
+ y = BASE % x;
+
+ while (y != 1)
+ {
+ q = x / y;
+ x = x % y;
+ t0 = (t0 + (t1 * q)) & MASK;
+ if (x == 1)
+ {
+ return t0;
+ }
+ q = y / x;
+ y = y % x;
+ t1 = (t1 + (t0 * q)) & MASK;
+ }
+
+ return (1 - t1) & MASK;
+ }
+
+ /**
+ * Return the additive inverse of x.
+ * <p>
+ * i.e. x + addInv(x) == 0
+ */
+ int addInv(
+ int x)
+ {
+ return (0 - x) & MASK;
+ }
+
+ /**
+ * The function to invert the encryption subkey to the decryption subkey.
+ * It also involves the multiplicative inverse and the additive inverse functions.
+ */
+ private int[] invertKey(
+ int[] inKey)
+ {
+ int t1, t2, t3, t4;
+ int p = 52; /* We work backwards */
+ int[] key = new int[52];
+ int inOff = 0;
+
+ t1 = mulInv(inKey[inOff++]);
+ t2 = addInv(inKey[inOff++]);
+ t3 = addInv(inKey[inOff++]);
+ t4 = mulInv(inKey[inOff++]);
+ key[--p] = t4;
+ key[--p] = t3;
+ key[--p] = t2;
+ key[--p] = t1;
+
+ for (int round = 1; round < 8; round++)
+ {
+ t1 = inKey[inOff++];
+ t2 = inKey[inOff++];
+ key[--p] = t2;
+ key[--p] = t1;
+
+ t1 = mulInv(inKey[inOff++]);
+ t2 = addInv(inKey[inOff++]);
+ t3 = addInv(inKey[inOff++]);
+ t4 = mulInv(inKey[inOff++]);
+ key[--p] = t4;
+ key[--p] = t2; /* NB: Order */
+ key[--p] = t3;
+ key[--p] = t1;
+ }
+
+ t1 = inKey[inOff++];
+ t2 = inKey[inOff++];
+ key[--p] = t2;
+ key[--p] = t1;
+
+ t1 = mulInv(inKey[inOff++]);
+ t2 = addInv(inKey[inOff++]);
+ t3 = addInv(inKey[inOff++]);
+ t4 = mulInv(inKey[inOff]);
+ key[--p] = t4;
+ key[--p] = t3;
+ key[--p] = t2;
+ key[--p] = t1;
+
+ return key;
+ }
+
+ private int[] generateWorkingKey(
+ boolean forEncryption,
+ byte[] userKey)
+ {
+ if (forEncryption)
+ {
+ return expandKey(userKey);
+ }
+ else
+ {
+ return invertKey(expandKey(userKey));
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/IESEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/IESEngine.java
new file mode 100755
index 00000000..1aebdf4d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/IESEngine.java
@@ -0,0 +1,438 @@
+package org.spongycastle.crypto.engines;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+
+import org.spongycastle.crypto.BasicAgreement;
+import org.spongycastle.crypto.BufferedBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DerivationFunction;
+import org.spongycastle.crypto.EphemeralKeyPair;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.KeyParser;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.generators.EphemeralKeyPairGenerator;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.IESParameters;
+import org.spongycastle.crypto.params.IESWithCipherParameters;
+import org.spongycastle.crypto.params.KDFParameters;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.BigIntegers;
+import org.spongycastle.util.Pack;
+
+/**
+ * Support class for constructing integrated encryption ciphers
+ * for doing basic message exchanges on top of key agreement ciphers.
+ * Follows the description given in IEEE Std 1363a.
+ */
+public class IESEngine
+{
+ BasicAgreement agree;
+ DerivationFunction kdf;
+ Mac mac;
+ BufferedBlockCipher cipher;
+ byte[] macBuf;
+
+ boolean forEncryption;
+ CipherParameters privParam, pubParam;
+ IESParameters param;
+
+ byte[] V;
+ private EphemeralKeyPairGenerator keyPairGenerator;
+ private KeyParser keyParser;
+ private byte[] IV;
+
+ /**
+ * set up for use with stream mode, where the key derivation function
+ * is used to provide a stream of bytes to xor with the message.
+ *
+ * @param agree the key agreement used as the basis for the encryption
+ * @param kdf the key derivation function used for byte generation
+ * @param mac the message authentication code generator for the message
+ */
+ public IESEngine(
+ BasicAgreement agree,
+ DerivationFunction kdf,
+ Mac mac)
+ {
+ this.agree = agree;
+ this.kdf = kdf;
+ this.mac = mac;
+ this.macBuf = new byte[mac.getMacSize()];
+ this.cipher = null;
+ }
+
+
+ /**
+ * set up for use in conjunction with a block cipher to handle the
+ * message.
+ *
+ * @param agree the key agreement used as the basis for the encryption
+ * @param kdf the key derivation function used for byte generation
+ * @param mac the message authentication code generator for the message
+ * @param cipher the cipher to used for encrypting the message
+ */
+ public IESEngine(
+ BasicAgreement agree,
+ DerivationFunction kdf,
+ Mac mac,
+ BufferedBlockCipher cipher)
+ {
+ this.agree = agree;
+ this.kdf = kdf;
+ this.mac = mac;
+ this.macBuf = new byte[mac.getMacSize()];
+ this.cipher = cipher;
+ }
+
+ /**
+ * Initialise the encryptor.
+ *
+ * @param forEncryption whether or not this is encryption/decryption.
+ * @param privParam our private key parameters
+ * @param pubParam the recipient's/sender's public key parameters
+ * @param params encoding and derivation parameters, may be wrapped to include an IV for an underlying block cipher.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters privParam,
+ CipherParameters pubParam,
+ CipherParameters params)
+ {
+ this.forEncryption = forEncryption;
+ this.privParam = privParam;
+ this.pubParam = pubParam;
+ this.V = new byte[0];
+
+ extractParams(params);
+ }
+
+
+ /**
+ * Initialise the encryptor.
+ *
+ * @param publicKey the recipient's/sender's public key parameters
+ * @param params encoding and derivation parameters, may be wrapped to include an IV for an underlying block cipher.
+ * @param ephemeralKeyPairGenerator the ephemeral key pair generator to use.
+ */
+ public void init(AsymmetricKeyParameter publicKey, CipherParameters params, EphemeralKeyPairGenerator ephemeralKeyPairGenerator)
+ {
+ this.forEncryption = true;
+ this.pubParam = publicKey;
+ this.keyPairGenerator = ephemeralKeyPairGenerator;
+
+ extractParams(params);
+ }
+
+ /**
+ * Initialise the encryptor.
+ *
+ * @param privateKey the recipient's private key.
+ * @param params encoding and derivation parameters, may be wrapped to include an IV for an underlying block cipher.
+ * @param publicKeyParser the parser for reading the ephemeral public key.
+ */
+ public void init(AsymmetricKeyParameter privateKey, CipherParameters params, KeyParser publicKeyParser)
+ {
+ this.forEncryption = false;
+ this.privParam = privateKey;
+ this.keyParser = publicKeyParser;
+
+ extractParams(params);
+ }
+
+ private void extractParams(CipherParameters params)
+ {
+ if (params instanceof ParametersWithIV)
+ {
+ this.IV = ((ParametersWithIV)params).getIV();
+ this.param = (IESParameters)((ParametersWithIV)params).getParameters();
+ }
+ else
+ {
+ this.IV = null;
+ this.param = (IESParameters)params;
+ }
+ }
+
+ public BufferedBlockCipher getCipher()
+ {
+ return cipher;
+ }
+
+ public Mac getMac()
+ {
+ return mac;
+ }
+
+ private byte[] encryptBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ byte[] C = null, K = null, K1 = null, K2 = null;
+ int len;
+
+ if (cipher == null)
+ {
+ // Streaming mode.
+ K1 = new byte[inLen];
+ K2 = new byte[param.getMacKeySize() / 8];
+ K = new byte[K1.length + K2.length];
+
+ kdf.generateBytes(K, 0, K.length);
+
+ if (V.length != 0)
+ {
+ System.arraycopy(K, 0, K2, 0, K2.length);
+ System.arraycopy(K, K2.length, K1, 0, K1.length);
+ }
+ else
+ {
+ System.arraycopy(K, 0, K1, 0, K1.length);
+ System.arraycopy(K, inLen, K2, 0, K2.length);
+ }
+
+ C = new byte[inLen];
+
+ for (int i = 0; i != inLen; i++)
+ {
+ C[i] = (byte)(in[inOff + i] ^ K1[i]);
+ }
+ len = inLen;
+ }
+ else
+ {
+ // Block cipher mode.
+ K1 = new byte[((IESWithCipherParameters)param).getCipherKeySize() / 8];
+ K2 = new byte[param.getMacKeySize() / 8];
+ K = new byte[K1.length + K2.length];
+
+ kdf.generateBytes(K, 0, K.length);
+ System.arraycopy(K, 0, K1, 0, K1.length);
+ System.arraycopy(K, K1.length, K2, 0, K2.length);
+
+ // If iv provided use it to initialise the cipher
+ if (IV != null)
+ {
+ cipher.init(true, new ParametersWithIV(new KeyParameter(K1), IV));
+ }
+ else
+ {
+ cipher.init(true, new KeyParameter(K1));
+ }
+
+ C = new byte[cipher.getOutputSize(inLen)];
+ len = cipher.processBytes(in, inOff, inLen, C, 0);
+ len += cipher.doFinal(C, len);
+ }
+
+
+ // Convert the length of the encoding vector into a byte array.
+ byte[] P2 = param.getEncodingV();
+ byte[] L2 = new byte[4];
+ if (V.length != 0 && P2 != null)
+ {
+ Pack.intToBigEndian(P2.length * 8, L2, 0);
+ }
+
+
+ // Apply the MAC.
+ byte[] T = new byte[mac.getMacSize()];
+
+ mac.init(new KeyParameter(K2));
+ mac.update(C, 0, C.length);
+ if (P2 != null)
+ {
+ mac.update(P2, 0, P2.length);
+ }
+ if (V.length != 0)
+ {
+ mac.update(L2, 0, L2.length);
+ }
+ mac.doFinal(T, 0);
+
+
+ // Output the triple (V,C,T).
+ byte[] Output = new byte[V.length + len + T.length];
+ System.arraycopy(V, 0, Output, 0, V.length);
+ System.arraycopy(C, 0, Output, V.length, len);
+ System.arraycopy(T, 0, Output, V.length + len, T.length);
+ return Output;
+ }
+
+ private byte[] decryptBlock(
+ byte[] in_enc,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ byte[] M = null, K = null, K1 = null, K2 = null;
+ int len;
+
+ // Ensure that the length of the input is greater than the MAC in bytes
+ if (inLen <= (param.getMacKeySize() / 8))
+ {
+ throw new InvalidCipherTextException("Length of input must be greater than the MAC");
+ }
+
+ if (cipher == null)
+ {
+ // Streaming mode.
+ K1 = new byte[inLen - V.length - mac.getMacSize()];
+ K2 = new byte[param.getMacKeySize() / 8];
+ K = new byte[K1.length + K2.length];
+
+ kdf.generateBytes(K, 0, K.length);
+
+ if (V.length != 0)
+ {
+ System.arraycopy(K, 0, K2, 0, K2.length);
+ System.arraycopy(K, K2.length, K1, 0, K1.length);
+ }
+ else
+ {
+ System.arraycopy(K, 0, K1, 0, K1.length);
+ System.arraycopy(K, K1.length, K2, 0, K2.length);
+ }
+
+ M = new byte[K1.length];
+
+ for (int i = 0; i != K1.length; i++)
+ {
+ M[i] = (byte)(in_enc[inOff + V.length + i] ^ K1[i]);
+ }
+
+ len = K1.length;
+ }
+ else
+ {
+ // Block cipher mode.
+ K1 = new byte[((IESWithCipherParameters)param).getCipherKeySize() / 8];
+ K2 = new byte[param.getMacKeySize() / 8];
+ K = new byte[K1.length + K2.length];
+
+ kdf.generateBytes(K, 0, K.length);
+ System.arraycopy(K, 0, K1, 0, K1.length);
+ System.arraycopy(K, K1.length, K2, 0, K2.length);
+
+ // If IV provide use it to initialize the cipher
+ if (IV != null)
+ {
+ cipher.init(false, new ParametersWithIV(new KeyParameter(K1), IV));
+ }
+ else
+ {
+ cipher.init(false, new KeyParameter(K1));
+ }
+
+ M = new byte[cipher.getOutputSize(inLen - V.length - mac.getMacSize())];
+ len = cipher.processBytes(in_enc, inOff + V.length, inLen - V.length - mac.getMacSize(), M, 0);
+ len += cipher.doFinal(M, len);
+ }
+
+
+ // Convert the length of the encoding vector into a byte array.
+ byte[] P2 = param.getEncodingV();
+ byte[] L2 = new byte[4];
+ if (V.length != 0 && P2 != null)
+ {
+ Pack.intToBigEndian(P2.length * 8, L2, 0);
+ }
+
+
+ // Verify the MAC.
+ int end = inOff + inLen;
+ byte[] T1 = Arrays.copyOfRange(in_enc, end - mac.getMacSize(), end);
+
+ byte[] T2 = new byte[T1.length];
+ mac.init(new KeyParameter(K2));
+ mac.update(in_enc, inOff + V.length, inLen - V.length - T2.length);
+
+ if (P2 != null)
+ {
+ mac.update(P2, 0, P2.length);
+ }
+ if (V.length != 0)
+ {
+ mac.update(L2, 0, L2.length);
+ }
+ mac.doFinal(T2, 0);
+
+ if (!Arrays.constantTimeAreEqual(T1, T2))
+ {
+ throw new InvalidCipherTextException("Invalid MAC.");
+ }
+
+
+ // Output the message.
+ return Arrays.copyOfRange(M, 0, len);
+ }
+
+
+ public byte[] processBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ if (forEncryption)
+ {
+ if (keyPairGenerator != null)
+ {
+ EphemeralKeyPair ephKeyPair = keyPairGenerator.generate();
+
+ this.privParam = ephKeyPair.getKeyPair().getPrivate();
+ this.V = ephKeyPair.getEncodedPublicKey();
+ }
+ }
+ else
+ {
+ if (keyParser != null)
+ {
+ ByteArrayInputStream bIn = new ByteArrayInputStream(in, inOff, inLen);
+
+ try
+ {
+ this.pubParam = keyParser.readKey(bIn);
+ }
+ catch (IOException e)
+ {
+ throw new InvalidCipherTextException("unable to recover ephemeral public key: " + e.getMessage(), e);
+ }
+
+ int encLength = (inLen - bIn.available());
+ this.V = Arrays.copyOfRange(in, inOff, inOff + encLength);
+ }
+ }
+
+ // Compute the common value and convert to byte array.
+ agree.init(privParam);
+ BigInteger z = agree.calculateAgreement(pubParam);
+ byte[] Z = BigIntegers.asUnsignedByteArray(agree.getFieldSize(), z);
+
+ // Create input to KDF.
+ byte[] VZ;
+ if (V.length != 0)
+ {
+ VZ = new byte[V.length + Z.length];
+ System.arraycopy(V, 0, VZ, 0, V.length);
+ System.arraycopy(Z, 0, VZ, V.length, Z.length);
+ }
+ else
+ {
+ VZ = Z;
+ }
+
+ // Initialise the KDF.
+ KDFParameters kdfParam = new KDFParameters(VZ, param.getDerivationV());
+ kdf.init(kdfParam);
+
+ return forEncryption
+ ? encryptBlock(in, inOff, inLen)
+ : decryptBlock(in, inOff, inLen);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/ISAACEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/ISAACEngine.java
new file mode 100644
index 00000000..36e762da
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/ISAACEngine.java
@@ -0,0 +1,221 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.StreamCipher;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Pack;
+
+/**
+ * Implementation of Bob Jenkin's ISAAC (Indirection Shift Accumulate Add and Count).
+ * see: http://www.burtleburtle.net/bob/rand/isaacafa.html
+*/
+public class ISAACEngine
+ implements StreamCipher
+{
+ // Constants
+ private final int sizeL = 8,
+ stateArraySize = sizeL<<5; // 256
+
+ // Cipher's internal state
+ private int[] engineState = null, // mm
+ results = null; // randrsl
+ private int a = 0, b = 0, c = 0;
+
+ // Engine state
+ private int index = 0;
+ private byte[] keyStream = new byte[stateArraySize<<2], // results expanded into bytes
+ workingKey = null;
+ private boolean initialised = false;
+
+ /**
+ * initialise an ISAAC cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (!(params instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("invalid parameter passed to ISAAC init - " + params.getClass().getName());
+ }
+ /*
+ * ISAAC encryption and decryption is completely
+ * symmetrical, so the 'forEncryption' is
+ * irrelevant.
+ */
+ KeyParameter p = (KeyParameter)params;
+ setKey(p.getKey());
+
+ return;
+ }
+
+ public byte returnByte(byte in)
+ {
+ if (index == 0)
+ {
+ isaac();
+ keyStream = Pack.intToBigEndian(results);
+ }
+ byte out = (byte)(keyStream[index]^in);
+ index = (index + 1) & 1023;
+
+ return out;
+ }
+
+ public int processBytes(
+ byte[] in,
+ int inOff,
+ int len,
+ byte[] out,
+ int outOff)
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName()+" not initialised");
+ }
+
+ if ((inOff + len) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + len) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ for (int i = 0; i < len; i++)
+ {
+ if (index == 0)
+ {
+ isaac();
+ keyStream = Pack.intToBigEndian(results);
+ }
+ out[i+outOff] = (byte)(keyStream[index]^in[i+inOff]);
+ index = (index + 1) & 1023;
+ }
+
+ return len;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "ISAAC";
+ }
+
+ public void reset()
+ {
+ setKey(workingKey);
+ }
+
+ // Private implementation
+ private void setKey(byte[] keyBytes)
+ {
+ workingKey = keyBytes;
+
+ if (engineState == null)
+ {
+ engineState = new int[stateArraySize];
+ }
+
+ if (results == null)
+ {
+ results = new int[stateArraySize];
+ }
+
+ int i, j, k;
+
+ // Reset state
+ for (i = 0; i < stateArraySize; i++)
+ {
+ engineState[i] = results[i] = 0;
+ }
+ a = b = c = 0;
+
+ // Reset index counter for output
+ index = 0;
+
+ // Convert the key bytes to ints and put them into results[] for initialization
+ byte[] t = new byte[keyBytes.length + (keyBytes.length & 3)];
+ System.arraycopy(keyBytes, 0, t, 0, keyBytes.length);
+ for (i = 0; i < t.length; i+=4)
+ {
+ results[i >>> 2] = Pack.littleEndianToInt(t, i);
+ }
+
+ // It has begun?
+ int[] abcdefgh = new int[sizeL];
+
+ for (i = 0; i < sizeL; i++)
+ {
+ abcdefgh[i] = 0x9e3779b9; // Phi (golden ratio)
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ mix(abcdefgh);
+ }
+
+ for (i = 0; i < 2; i++)
+ {
+ for (j = 0; j < stateArraySize; j+=sizeL)
+ {
+ for (k = 0; k < sizeL; k++)
+ {
+ abcdefgh[k] += (i<1) ? results[j+k] : engineState[j+k];
+ }
+
+ mix(abcdefgh);
+
+ for (k = 0; k < sizeL; k++)
+ {
+ engineState[j+k] = abcdefgh[k];
+ }
+ }
+ }
+
+ isaac();
+
+ initialised = true;
+ }
+
+ private void isaac()
+ {
+ int i, x, y;
+
+ b += ++c;
+ for (i = 0; i < stateArraySize; i++)
+ {
+ x = engineState[i];
+ switch (i & 3)
+ {
+ case 0: a ^= (a << 13); break;
+ case 1: a ^= (a >>> 6); break;
+ case 2: a ^= (a << 2); break;
+ case 3: a ^= (a >>> 16); break;
+ }
+ a += engineState[(i+128) & 0xFF];
+ engineState[i] = y = engineState[(x >>> 2) & 0xFF] + a + b;
+ results[i] = b = engineState[(y >>> 10) & 0xFF] + x;
+ }
+ }
+
+ private void mix(int[] x)
+ {
+ x[0]^=x[1]<< 11; x[3]+=x[0]; x[1]+=x[2];
+ x[1]^=x[2]>>> 2; x[4]+=x[1]; x[2]+=x[3];
+ x[2]^=x[3]<< 8; x[5]+=x[2]; x[3]+=x[4];
+ x[3]^=x[4]>>>16; x[6]+=x[3]; x[4]+=x[5];
+ x[4]^=x[5]<< 10; x[7]+=x[4]; x[5]+=x[6];
+ x[5]^=x[6]>>> 4; x[0]+=x[5]; x[6]+=x[7];
+ x[6]^=x[7]<< 8; x[1]+=x[6]; x[7]+=x[0];
+ x[7]^=x[0]>>> 9; x[2]+=x[7]; x[0]+=x[1];
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/NaccacheSternEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/NaccacheSternEngine.java
new file mode 100644
index 00000000..a25b12f1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/NaccacheSternEngine.java
@@ -0,0 +1,437 @@
+package org.spongycastle.crypto.engines;
+
+import java.math.BigInteger;
+import java.util.Vector;
+import org.spongycastle.util.Arrays;
+
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.params.NaccacheSternKeyParameters;
+import org.spongycastle.crypto.params.NaccacheSternPrivateKeyParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+
+/**
+ * NaccacheStern Engine. For details on this cipher, please see
+ * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+ */
+public class NaccacheSternEngine
+ implements AsymmetricBlockCipher
+{
+ private boolean forEncryption;
+
+ private NaccacheSternKeyParameters key;
+
+ private Vector[] lookup = null;
+
+ private boolean debug = false;
+
+ private static BigInteger ZERO = BigInteger.valueOf(0);
+ private static BigInteger ONE = BigInteger.valueOf(1);
+
+ /**
+ * Initializes this algorithm. Must be called before all other Functions.
+ *
+ * @see org.spongycastle.crypto.AsymmetricBlockCipher#init(boolean,
+ * org.spongycastle.crypto.CipherParameters)
+ */
+ public void init(boolean forEncryption, CipherParameters param)
+ {
+ this.forEncryption = forEncryption;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ param = ((ParametersWithRandom) param).getParameters();
+ }
+
+ key = (NaccacheSternKeyParameters)param;
+
+ // construct lookup table for faster decryption if necessary
+ if (!this.forEncryption)
+ {
+ if (debug)
+ {
+ System.out.println("Constructing lookup Array");
+ }
+ NaccacheSternPrivateKeyParameters priv = (NaccacheSternPrivateKeyParameters)key;
+ Vector primes = priv.getSmallPrimes();
+ lookup = new Vector[primes.size()];
+ for (int i = 0; i < primes.size(); i++)
+ {
+ BigInteger actualPrime = (BigInteger)primes.elementAt(i);
+ int actualPrimeValue = actualPrime.intValue();
+
+ lookup[i] = new Vector();
+ lookup[i].addElement(ONE);
+
+ if (debug)
+ {
+ System.out.println("Constructing lookup ArrayList for " + actualPrimeValue);
+ }
+
+ BigInteger accJ = ZERO;
+
+ for (int j = 1; j < actualPrimeValue; j++)
+ {
+ accJ = accJ.add(priv.getPhi_n());
+ BigInteger comp = accJ.divide(actualPrime);
+ lookup[i].addElement(priv.getG().modPow(comp, priv.getModulus()));
+ }
+ }
+ }
+ }
+
+ public void setDebug(boolean debug)
+ {
+ this.debug = debug;
+ }
+
+ /**
+ * Returns the input block size of this algorithm.
+ *
+ * @see org.spongycastle.crypto.AsymmetricBlockCipher#getInputBlockSize()
+ */
+ public int getInputBlockSize()
+ {
+ if (forEncryption)
+ {
+ // We can only encrypt values up to lowerSigmaBound
+ return (key.getLowerSigmaBound() + 7) / 8 - 1;
+ }
+ else
+ {
+ // We pad to modulus-size bytes for easier decryption.
+ return key.getModulus().toByteArray().length;
+ }
+ }
+
+ /**
+ * Returns the output block size of this algorithm.
+ *
+ * @see org.spongycastle.crypto.AsymmetricBlockCipher#getOutputBlockSize()
+ */
+ public int getOutputBlockSize()
+ {
+ if (forEncryption)
+ {
+ // encrypted Data is always padded up to modulus size
+ return key.getModulus().toByteArray().length;
+ }
+ else
+ {
+ // decrypted Data has upper limit lowerSigmaBound
+ return (key.getLowerSigmaBound() + 7) / 8 - 1;
+ }
+ }
+
+ /**
+ * Process a single Block using the Naccache-Stern algorithm.
+ *
+ * @see org.spongycastle.crypto.AsymmetricBlockCipher#processBlock(byte[],
+ * int, int)
+ */
+ public byte[] processBlock(byte[] in, int inOff, int len) throws InvalidCipherTextException
+ {
+ if (key == null)
+ {
+ throw new IllegalStateException("NaccacheStern engine not initialised");
+ }
+ if (len > (getInputBlockSize() + 1))
+ {
+ throw new DataLengthException("input too large for Naccache-Stern cipher.\n");
+ }
+
+ if (!forEncryption)
+ {
+ // At decryption make sure that we receive padded data blocks
+ if (len < getInputBlockSize())
+ {
+ throw new InvalidCipherTextException("BlockLength does not match modulus for Naccache-Stern cipher.\n");
+ }
+ }
+
+ byte[] block;
+
+ if (inOff != 0 || len != in.length)
+ {
+ block = new byte[len];
+ System.arraycopy(in, inOff, block, 0, len);
+ }
+ else
+ {
+ block = in;
+ }
+
+ // transform input into BigInteger
+ BigInteger input = new BigInteger(1, block);
+ if (debug)
+ {
+ System.out.println("input as BigInteger: " + input);
+ }
+ byte[] output;
+ if (forEncryption)
+ {
+ output = encrypt(input);
+ }
+ else
+ {
+ Vector plain = new Vector();
+ NaccacheSternPrivateKeyParameters priv = (NaccacheSternPrivateKeyParameters)key;
+ Vector primes = priv.getSmallPrimes();
+ // Get Chinese Remainders of CipherText
+ for (int i = 0; i < primes.size(); i++)
+ {
+ BigInteger exp = input.modPow(priv.getPhi_n().divide((BigInteger)primes.elementAt(i)), priv.getModulus());
+ Vector al = lookup[i];
+ if (lookup[i].size() != ((BigInteger)primes.elementAt(i)).intValue())
+ {
+ if (debug)
+ {
+ System.out.println("Prime is " + primes.elementAt(i) + ", lookup table has size " + al.size());
+ }
+ throw new InvalidCipherTextException("Error in lookup Array for "
+ + ((BigInteger)primes.elementAt(i)).intValue()
+ + ": Size mismatch. Expected ArrayList with length "
+ + ((BigInteger)primes.elementAt(i)).intValue() + " but found ArrayList of length "
+ + lookup[i].size());
+ }
+ int lookedup = al.indexOf(exp);
+
+ if (lookedup == -1)
+ {
+ if (debug)
+ {
+ System.out.println("Actual prime is " + primes.elementAt(i));
+ System.out.println("Decrypted value is " + exp);
+
+ System.out.println("LookupList for " + primes.elementAt(i) + " with size " + lookup[i].size()
+ + " is: ");
+ for (int j = 0; j < lookup[i].size(); j++)
+ {
+ System.out.println(lookup[i].elementAt(j));
+ }
+ }
+ throw new InvalidCipherTextException("Lookup failed");
+ }
+ plain.addElement(BigInteger.valueOf(lookedup));
+ }
+ BigInteger test = chineseRemainder(plain, primes);
+
+ // Should not be used as an oracle, so reencrypt output to see
+ // if it corresponds to input
+
+ // this breaks probabilisic encryption, so disable it. Anyway, we do
+ // use the first n primes for key generation, so it is pretty easy
+ // to guess them. But as stated in the paper, this is not a security
+ // breach. So we can just work with the correct sigma.
+
+ // if (debug) {
+ // System.out.println("Decryption is " + test);
+ // }
+ // if ((key.getG().modPow(test, key.getModulus())).equals(input)) {
+ // output = test.toByteArray();
+ // } else {
+ // if(debug){
+ // System.out.println("Engine seems to be used as an oracle,
+ // returning null");
+ // }
+ // output = null;
+ // }
+
+ output = test.toByteArray();
+
+ }
+
+ return output;
+ }
+
+ /**
+ * Encrypts a BigInteger aka Plaintext with the public key.
+ *
+ * @param plain
+ * The BigInteger to encrypt
+ * @return The byte[] representation of the encrypted BigInteger (i.e.
+ * crypted.toByteArray())
+ */
+ public byte[] encrypt(BigInteger plain)
+ {
+ // Always return modulus size values 0-padded at the beginning
+ // 0-padding at the beginning is correctly parsed by BigInteger :)
+ byte[] output = key.getModulus().toByteArray();
+ Arrays.fill(output, (byte)0);
+ byte[] tmp = key.getG().modPow(plain, key.getModulus()).toByteArray();
+ System
+ .arraycopy(tmp, 0, output, output.length - tmp.length,
+ tmp.length);
+ if (debug)
+ {
+ System.out
+ .println("Encrypted value is: " + new BigInteger(output));
+ }
+ return output;
+ }
+
+ /**
+ * Adds the contents of two encrypted blocks mod sigma
+ *
+ * @param block1
+ * the first encrypted block
+ * @param block2
+ * the second encrypted block
+ * @return encrypt((block1 + block2) mod sigma)
+ * @throws InvalidCipherTextException
+ */
+ public byte[] addCryptedBlocks(byte[] block1, byte[] block2)
+ throws InvalidCipherTextException
+ {
+ // check for correct blocksize
+ if (forEncryption)
+ {
+ if ((block1.length > getOutputBlockSize())
+ || (block2.length > getOutputBlockSize()))
+ {
+ throw new InvalidCipherTextException(
+ "BlockLength too large for simple addition.\n");
+ }
+ }
+ else
+ {
+ if ((block1.length > getInputBlockSize())
+ || (block2.length > getInputBlockSize()))
+ {
+ throw new InvalidCipherTextException(
+ "BlockLength too large for simple addition.\n");
+ }
+ }
+
+ // calculate resulting block
+ BigInteger m1Crypt = new BigInteger(1, block1);
+ BigInteger m2Crypt = new BigInteger(1, block2);
+ BigInteger m1m2Crypt = m1Crypt.multiply(m2Crypt);
+ m1m2Crypt = m1m2Crypt.mod(key.getModulus());
+ if (debug)
+ {
+ System.out.println("c(m1) as BigInteger:....... " + m1Crypt);
+ System.out.println("c(m2) as BigInteger:....... " + m2Crypt);
+ System.out.println("c(m1)*c(m2)%n = c(m1+m2)%n: " + m1m2Crypt);
+ }
+
+ byte[] output = key.getModulus().toByteArray();
+ Arrays.fill(output, (byte)0);
+ System.arraycopy(m1m2Crypt.toByteArray(), 0, output, output.length
+ - m1m2Crypt.toByteArray().length,
+ m1m2Crypt.toByteArray().length);
+
+ return output;
+ }
+
+ /**
+ * Convenience Method for data exchange with the cipher.
+ *
+ * Determines blocksize and splits data to blocksize.
+ *
+ * @param data the data to be processed
+ * @return the data after it went through the NaccacheSternEngine.
+ * @throws InvalidCipherTextException
+ */
+ public byte[] processData(byte[] data) throws InvalidCipherTextException
+ {
+ if (debug)
+ {
+ System.out.println();
+ }
+ if (data.length > getInputBlockSize())
+ {
+ int inBlocksize = getInputBlockSize();
+ int outBlocksize = getOutputBlockSize();
+ if (debug)
+ {
+ System.out.println("Input blocksize is: " + inBlocksize + " bytes");
+ System.out.println("Output blocksize is: " + outBlocksize + " bytes");
+ System.out.println("Data has length:.... " + data.length + " bytes");
+ }
+ int datapos = 0;
+ int retpos = 0;
+ byte[] retval = new byte[(data.length / inBlocksize + 1) * outBlocksize];
+ while (datapos < data.length)
+ {
+ byte[] tmp;
+ if (datapos + inBlocksize < data.length)
+ {
+ tmp = processBlock(data, datapos, inBlocksize);
+ datapos += inBlocksize;
+ }
+ else
+ {
+ tmp = processBlock(data, datapos, data.length - datapos);
+ datapos += data.length - datapos;
+ }
+ if (debug)
+ {
+ System.out.println("new datapos is " + datapos);
+ }
+ if (tmp != null)
+ {
+ System.arraycopy(tmp, 0, retval, retpos, tmp.length);
+
+ retpos += tmp.length;
+ }
+ else
+ {
+ if (debug)
+ {
+ System.out.println("cipher returned null");
+ }
+ throw new InvalidCipherTextException("cipher returned null");
+ }
+ }
+ byte[] ret = new byte[retpos];
+ System.arraycopy(retval, 0, ret, 0, retpos);
+ if (debug)
+ {
+ System.out.println("returning " + ret.length + " bytes");
+ }
+ return ret;
+ }
+ else
+ {
+ if (debug)
+ {
+ System.out.println("data size is less then input block size, processing directly");
+ }
+ return processBlock(data, 0, data.length);
+ }
+ }
+
+ /**
+ * Computes the integer x that is expressed through the given primes and the
+ * congruences with the chinese remainder theorem (CRT).
+ *
+ * @param congruences
+ * the congruences c_i
+ * @param primes
+ * the primes p_i
+ * @return an integer x for that x % p_i == c_i
+ */
+ private static BigInteger chineseRemainder(Vector congruences, Vector primes)
+ {
+ BigInteger retval = ZERO;
+ BigInteger all = ONE;
+ for (int i = 0; i < primes.size(); i++)
+ {
+ all = all.multiply((BigInteger)primes.elementAt(i));
+ }
+ for (int i = 0; i < primes.size(); i++)
+ {
+ BigInteger a = (BigInteger)primes.elementAt(i);
+ BigInteger b = all.divide(a);
+ BigInteger b_ = b.modInverse(a);
+ BigInteger tmp = b.multiply(b_);
+ tmp = tmp.multiply((BigInteger)congruences.elementAt(i));
+ retval = retval.add(tmp);
+ }
+
+ return retval.mod(all);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/NoekeonEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/NoekeonEngine.java
new file mode 100644
index 00000000..3abaeede
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/NoekeonEngine.java
@@ -0,0 +1,263 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+
+/**
+ * A Noekeon engine, using direct-key mode.
+ */
+
+public class NoekeonEngine
+ implements BlockCipher
+{
+ private static final int genericSize = 16; // Block and key size, as well as the amount of rounds.
+
+ private static final int[] nullVector =
+ {
+ 0x00, 0x00, 0x00, 0x00 // Used in decryption
+ },
+
+ roundConstants =
+ {
+ 0x80, 0x1b, 0x36, 0x6c,
+ 0xd8, 0xab, 0x4d, 0x9a,
+ 0x2f, 0x5e, 0xbc, 0x63,
+ 0xc6, 0x97, 0x35, 0x6a,
+ 0xd4
+ };
+
+ private int[] state = new int[4], // a
+ subKeys = new int[4], // k
+ decryptKeys = new int[4];
+
+ private boolean _initialised,
+ _forEncryption;
+
+ /**
+ * Create an instance of the Noekeon encryption algorithm
+ * and set some defaults
+ */
+ public NoekeonEngine()
+ {
+ _initialised = false;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Noekeon";
+ }
+
+ public int getBlockSize()
+ {
+ return genericSize;
+ }
+
+ /**
+ * initialise
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (!(params instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("invalid parameter passed to Noekeon init - " + params.getClass().getName());
+ }
+
+ _forEncryption = forEncryption;
+ _initialised = true;
+
+ KeyParameter p = (KeyParameter)params;
+
+ setKey(p.getKey());
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (!_initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName()+" not initialised");
+ }
+
+ if ((inOff + genericSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + genericSize) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ return (_forEncryption) ? encryptBlock(in, inOff, out, outOff)
+ : decryptBlock(in, inOff, out, outOff);
+ }
+
+ public void reset()
+ {
+ }
+
+ /**
+ * Re-key the cipher.
+ * <p>
+ * @param key the key to be used
+ */
+ private void setKey(
+ byte[] key)
+ {
+ subKeys[0] = bytesToIntBig(key, 0);
+ subKeys[1] = bytesToIntBig(key, 4);
+ subKeys[2] = bytesToIntBig(key, 8);
+ subKeys[3] = bytesToIntBig(key, 12);
+ }
+
+ private int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ state[0] = bytesToIntBig(in, inOff);
+ state[1] = bytesToIntBig(in, inOff+4);
+ state[2] = bytesToIntBig(in, inOff+8);
+ state[3] = bytesToIntBig(in, inOff+12);
+
+ int i;
+ for (i = 0; i < genericSize; i++)
+ {
+ state[0] ^= roundConstants[i];
+ theta(state, subKeys);
+ pi1(state);
+ gamma(state);
+ pi2(state);
+ }
+
+ state[0] ^= roundConstants[i];
+ theta(state, subKeys);
+
+ intToBytesBig(state[0], out, outOff);
+ intToBytesBig(state[1], out, outOff+4);
+ intToBytesBig(state[2], out, outOff+8);
+ intToBytesBig(state[3], out, outOff+12);
+
+ return genericSize;
+ }
+
+ private int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ state[0] = bytesToIntBig(in, inOff);
+ state[1] = bytesToIntBig(in, inOff+4);
+ state[2] = bytesToIntBig(in, inOff+8);
+ state[3] = bytesToIntBig(in, inOff+12);
+
+ System.arraycopy(subKeys, 0, decryptKeys, 0, subKeys.length);
+ theta(decryptKeys, nullVector);
+
+ int i;
+ for (i = genericSize; i > 0; i--)
+ {
+ theta(state, decryptKeys);
+ state[0] ^= roundConstants[i];
+ pi1(state);
+ gamma(state);
+ pi2(state);
+ }
+
+ theta(state, decryptKeys);
+ state[0] ^= roundConstants[i];
+
+ intToBytesBig(state[0], out, outOff);
+ intToBytesBig(state[1], out, outOff+4);
+ intToBytesBig(state[2], out, outOff+8);
+ intToBytesBig(state[3], out, outOff+12);
+
+ return genericSize;
+ }
+
+ private void gamma(int[] a)
+ {
+ a[1] ^= ~a[3] & ~a[2];
+ a[0] ^= a[2] & a[1];
+
+ int tmp = a[3];
+ a[3] = a[0];
+ a[0] = tmp;
+ a[2] ^= a[0]^a[1]^a[3];
+
+ a[1] ^= ~a[3] & ~a[2];
+ a[0] ^= a[2] & a[1];
+ }
+
+ private void theta(int[] a, int[] k)
+ {
+ int tmp;
+
+ tmp = a[0]^a[2];
+ tmp ^= rotl(tmp,8)^rotl(tmp,24);
+ a[1] ^= tmp;
+ a[3] ^= tmp;
+
+ for (int i = 0; i < 4; i++)
+ {
+ a[i] ^= k[i];
+ }
+
+ tmp = a[1]^a[3];
+ tmp ^= rotl(tmp,8)^rotl(tmp,24);
+ a[0] ^= tmp;
+ a[2] ^= tmp;
+ }
+
+ private void pi1(int[] a)
+ {
+ a[1] = rotl(a[1], 1);
+ a[2] = rotl(a[2], 5);
+ a[3] = rotl(a[3], 2);
+ }
+
+ private void pi2(int[] a)
+ {
+ a[1] = rotl(a[1], 31);
+ a[2] = rotl(a[2], 27);
+ a[3] = rotl(a[3], 30);
+ }
+
+ // Helpers
+
+ private int bytesToIntBig(byte[] in, int off)
+ {
+ return ((in[off++]) << 24) |
+ ((in[off++] & 0xff) << 16) |
+ ((in[off++] & 0xff) << 8) |
+ (in[off ] & 0xff);
+ }
+
+ private void intToBytesBig(int x, byte[] out, int off)
+ {
+ out[off++] = (byte)(x >>> 24);
+ out[off++] = (byte)(x >>> 16);
+ out[off++] = (byte)(x >>> 8);
+ out[off ] = (byte)x;
+ }
+
+ private int rotl(int x, int y)
+ {
+ return (x << y) | (x >>> (32-y));
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/NullEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/NullEngine.java
new file mode 100644
index 00000000..f8d28413
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/NullEngine.java
@@ -0,0 +1,96 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+
+/**
+ * The no-op engine that just copies bytes through, irrespective of whether encrypting and decrypting.
+ * Provided for the sake of completeness.
+ */
+public class NullEngine implements BlockCipher
+{
+ private boolean initialised;
+ protected static final int DEFAULT_BLOCK_SIZE = 1;
+ private final int blockSize;
+
+ /**
+ * Constructs a null engine with a block size of 1 byte.
+ */
+ public NullEngine()
+ {
+ 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)
+ * @see org.spongycastle.crypto.BlockCipher#init(boolean, org.spongycastle.crypto.CipherParameters)
+ */
+ public void init(boolean forEncryption, CipherParameters params) throws IllegalArgumentException
+ {
+ // we don't mind any parameters that may come in
+ this.initialised = true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.spongycastle.crypto.BlockCipher#getAlgorithmName()
+ */
+ public String getAlgorithmName()
+ {
+ return "Null";
+ }
+
+ /* (non-Javadoc)
+ * @see org.spongycastle.crypto.BlockCipher#getBlockSize()
+ */
+ public int getBlockSize()
+ {
+ return blockSize;
+ }
+
+ /* (non-Javadoc)
+ * @see org.spongycastle.crypto.BlockCipher#processBlock(byte[], int, byte[], int)
+ */
+ public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException("Null engine not initialised");
+ }
+ 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];
+ }
+
+ return blockSize;
+ }
+
+ /* (non-Javadoc)
+ * @see org.spongycastle.crypto.BlockCipher#reset()
+ */
+ public void reset()
+ {
+ // nothing needs to be done
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/RC2Engine.java b/core/src/main/java/org/spongycastle/crypto/engines/RC2Engine.java
new file mode 100644
index 00000000..24bdab6a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/RC2Engine.java
@@ -0,0 +1,317 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.RC2Parameters;
+
+/**
+ * an implementation of RC2 as described in RFC 2268
+ * "A Description of the RC2(r) Encryption Algorithm" R. Rivest.
+ */
+public class RC2Engine
+ implements BlockCipher
+{
+ //
+ // the values we use for key expansion (based on the digits of PI)
+ //
+ private static byte[] piTable =
+ {
+ (byte)0xd9, (byte)0x78, (byte)0xf9, (byte)0xc4, (byte)0x19, (byte)0xdd, (byte)0xb5, (byte)0xed,
+ (byte)0x28, (byte)0xe9, (byte)0xfd, (byte)0x79, (byte)0x4a, (byte)0xa0, (byte)0xd8, (byte)0x9d,
+ (byte)0xc6, (byte)0x7e, (byte)0x37, (byte)0x83, (byte)0x2b, (byte)0x76, (byte)0x53, (byte)0x8e,
+ (byte)0x62, (byte)0x4c, (byte)0x64, (byte)0x88, (byte)0x44, (byte)0x8b, (byte)0xfb, (byte)0xa2,
+ (byte)0x17, (byte)0x9a, (byte)0x59, (byte)0xf5, (byte)0x87, (byte)0xb3, (byte)0x4f, (byte)0x13,
+ (byte)0x61, (byte)0x45, (byte)0x6d, (byte)0x8d, (byte)0x9, (byte)0x81, (byte)0x7d, (byte)0x32,
+ (byte)0xbd, (byte)0x8f, (byte)0x40, (byte)0xeb, (byte)0x86, (byte)0xb7, (byte)0x7b, (byte)0xb,
+ (byte)0xf0, (byte)0x95, (byte)0x21, (byte)0x22, (byte)0x5c, (byte)0x6b, (byte)0x4e, (byte)0x82,
+ (byte)0x54, (byte)0xd6, (byte)0x65, (byte)0x93, (byte)0xce, (byte)0x60, (byte)0xb2, (byte)0x1c,
+ (byte)0x73, (byte)0x56, (byte)0xc0, (byte)0x14, (byte)0xa7, (byte)0x8c, (byte)0xf1, (byte)0xdc,
+ (byte)0x12, (byte)0x75, (byte)0xca, (byte)0x1f, (byte)0x3b, (byte)0xbe, (byte)0xe4, (byte)0xd1,
+ (byte)0x42, (byte)0x3d, (byte)0xd4, (byte)0x30, (byte)0xa3, (byte)0x3c, (byte)0xb6, (byte)0x26,
+ (byte)0x6f, (byte)0xbf, (byte)0xe, (byte)0xda, (byte)0x46, (byte)0x69, (byte)0x7, (byte)0x57,
+ (byte)0x27, (byte)0xf2, (byte)0x1d, (byte)0x9b, (byte)0xbc, (byte)0x94, (byte)0x43, (byte)0x3,
+ (byte)0xf8, (byte)0x11, (byte)0xc7, (byte)0xf6, (byte)0x90, (byte)0xef, (byte)0x3e, (byte)0xe7,
+ (byte)0x6, (byte)0xc3, (byte)0xd5, (byte)0x2f, (byte)0xc8, (byte)0x66, (byte)0x1e, (byte)0xd7,
+ (byte)0x8, (byte)0xe8, (byte)0xea, (byte)0xde, (byte)0x80, (byte)0x52, (byte)0xee, (byte)0xf7,
+ (byte)0x84, (byte)0xaa, (byte)0x72, (byte)0xac, (byte)0x35, (byte)0x4d, (byte)0x6a, (byte)0x2a,
+ (byte)0x96, (byte)0x1a, (byte)0xd2, (byte)0x71, (byte)0x5a, (byte)0x15, (byte)0x49, (byte)0x74,
+ (byte)0x4b, (byte)0x9f, (byte)0xd0, (byte)0x5e, (byte)0x4, (byte)0x18, (byte)0xa4, (byte)0xec,
+ (byte)0xc2, (byte)0xe0, (byte)0x41, (byte)0x6e, (byte)0xf, (byte)0x51, (byte)0xcb, (byte)0xcc,
+ (byte)0x24, (byte)0x91, (byte)0xaf, (byte)0x50, (byte)0xa1, (byte)0xf4, (byte)0x70, (byte)0x39,
+ (byte)0x99, (byte)0x7c, (byte)0x3a, (byte)0x85, (byte)0x23, (byte)0xb8, (byte)0xb4, (byte)0x7a,
+ (byte)0xfc, (byte)0x2, (byte)0x36, (byte)0x5b, (byte)0x25, (byte)0x55, (byte)0x97, (byte)0x31,
+ (byte)0x2d, (byte)0x5d, (byte)0xfa, (byte)0x98, (byte)0xe3, (byte)0x8a, (byte)0x92, (byte)0xae,
+ (byte)0x5, (byte)0xdf, (byte)0x29, (byte)0x10, (byte)0x67, (byte)0x6c, (byte)0xba, (byte)0xc9,
+ (byte)0xd3, (byte)0x0, (byte)0xe6, (byte)0xcf, (byte)0xe1, (byte)0x9e, (byte)0xa8, (byte)0x2c,
+ (byte)0x63, (byte)0x16, (byte)0x1, (byte)0x3f, (byte)0x58, (byte)0xe2, (byte)0x89, (byte)0xa9,
+ (byte)0xd, (byte)0x38, (byte)0x34, (byte)0x1b, (byte)0xab, (byte)0x33, (byte)0xff, (byte)0xb0,
+ (byte)0xbb, (byte)0x48, (byte)0xc, (byte)0x5f, (byte)0xb9, (byte)0xb1, (byte)0xcd, (byte)0x2e,
+ (byte)0xc5, (byte)0xf3, (byte)0xdb, (byte)0x47, (byte)0xe5, (byte)0xa5, (byte)0x9c, (byte)0x77,
+ (byte)0xa, (byte)0xa6, (byte)0x20, (byte)0x68, (byte)0xfe, (byte)0x7f, (byte)0xc1, (byte)0xad
+ };
+
+ private static final int BLOCK_SIZE = 8;
+
+ private int[] workingKey;
+ private boolean encrypting;
+
+ private int[] generateWorkingKey(
+ byte[] key,
+ int bits)
+ {
+ int x;
+ int[] xKey = new int[128];
+
+ for (int i = 0; i != key.length; i++)
+ {
+ xKey[i] = key[i] & 0xff;
+ }
+
+ // Phase 1: Expand input key to 128 bytes
+ int len = key.length;
+
+ if (len < 128)
+ {
+ int index = 0;
+
+ x = xKey[len - 1];
+
+ do
+ {
+ x = piTable[(x + xKey[index++]) & 255] & 0xff;
+ xKey[len++] = x;
+ }
+ while (len < 128);
+ }
+
+ // Phase 2 - reduce effective key size to "bits"
+ len = (bits + 7) >> 3;
+ x = piTable[xKey[128 - len] & (255 >> (7 & -bits))] & 0xff;
+ xKey[128 - len] = x;
+
+ for (int i = 128 - len - 1; i >= 0; i--)
+ {
+ x = piTable[x ^ xKey[i + len]] & 0xff;
+ xKey[i] = x;
+ }
+
+ // Phase 3 - copy to newKey in little-endian order
+ int[] newKey = new int[64];
+
+ for (int i = 0; i != newKey.length; i++)
+ {
+ newKey[i] = (xKey[2 * i] + (xKey[2 * i + 1] << 8));
+ }
+
+ return newKey;
+ }
+
+ /**
+ * initialise a RC2 cipher.
+ *
+ * @param encrypting whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ {
+ this.encrypting = encrypting;
+
+ if (params instanceof RC2Parameters)
+ {
+ RC2Parameters param = (RC2Parameters)params;
+
+ workingKey = generateWorkingKey(param.getKey(),
+ param.getEffectiveKeyBits());
+ }
+ else if (params instanceof KeyParameter)
+ {
+ byte[] key = ((KeyParameter)params).getKey();
+
+ workingKey = generateWorkingKey(key, key.length * 8);
+ }
+ else
+ {
+ throw new IllegalArgumentException("invalid parameter passed to RC2 init - " + params.getClass().getName());
+ }
+
+ }
+
+ public void reset()
+ {
+ }
+
+ public String getAlgorithmName()
+ {
+ return "RC2";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public final int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (workingKey == null)
+ {
+ throw new IllegalStateException("RC2 engine not initialised");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ if (encrypting)
+ {
+ encryptBlock(in, inOff, out, outOff);
+ }
+ else
+ {
+ decryptBlock(in, inOff, out, outOff);
+ }
+
+ return BLOCK_SIZE;
+ }
+
+ /**
+ * return the result rotating the 16 bit number in x left by y
+ */
+ private int rotateWordLeft(
+ int x,
+ int y)
+ {
+ x &= 0xffff;
+ return (x << y) | (x >> (16 - y));
+ }
+
+ private void encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ int x76, x54, x32, x10;
+
+ x76 = ((in[inOff + 7] & 0xff) << 8) + (in[inOff + 6] & 0xff);
+ x54 = ((in[inOff + 5] & 0xff) << 8) + (in[inOff + 4] & 0xff);
+ x32 = ((in[inOff + 3] & 0xff) << 8) + (in[inOff + 2] & 0xff);
+ x10 = ((in[inOff + 1] & 0xff) << 8) + (in[inOff + 0] & 0xff);
+
+ for (int i = 0; i <= 16; i += 4)
+ {
+ x10 = rotateWordLeft(x10 + (x32 & ~x76) + (x54 & x76) + workingKey[i ], 1);
+ x32 = rotateWordLeft(x32 + (x54 & ~x10) + (x76 & x10) + workingKey[i+1], 2);
+ x54 = rotateWordLeft(x54 + (x76 & ~x32) + (x10 & x32) + workingKey[i+2], 3);
+ x76 = rotateWordLeft(x76 + (x10 & ~x54) + (x32 & x54) + workingKey[i+3], 5);
+ }
+
+ x10 += workingKey[x76 & 63];
+ x32 += workingKey[x10 & 63];
+ x54 += workingKey[x32 & 63];
+ x76 += workingKey[x54 & 63];
+
+ for (int i = 20; i <= 40; i += 4)
+ {
+ x10 = rotateWordLeft(x10 + (x32 & ~x76) + (x54 & x76) + workingKey[i ], 1);
+ x32 = rotateWordLeft(x32 + (x54 & ~x10) + (x76 & x10) + workingKey[i+1], 2);
+ x54 = rotateWordLeft(x54 + (x76 & ~x32) + (x10 & x32) + workingKey[i+2], 3);
+ x76 = rotateWordLeft(x76 + (x10 & ~x54) + (x32 & x54) + workingKey[i+3], 5);
+ }
+
+ x10 += workingKey[x76 & 63];
+ x32 += workingKey[x10 & 63];
+ x54 += workingKey[x32 & 63];
+ x76 += workingKey[x54 & 63];
+
+ for (int i = 44; i < 64; i += 4)
+ {
+ x10 = rotateWordLeft(x10 + (x32 & ~x76) + (x54 & x76) + workingKey[i ], 1);
+ x32 = rotateWordLeft(x32 + (x54 & ~x10) + (x76 & x10) + workingKey[i+1], 2);
+ x54 = rotateWordLeft(x54 + (x76 & ~x32) + (x10 & x32) + workingKey[i+2], 3);
+ x76 = rotateWordLeft(x76 + (x10 & ~x54) + (x32 & x54) + workingKey[i+3], 5);
+ }
+
+ out[outOff + 0] = (byte)x10;
+ out[outOff + 1] = (byte)(x10 >> 8);
+ out[outOff + 2] = (byte)x32;
+ out[outOff + 3] = (byte)(x32 >> 8);
+ out[outOff + 4] = (byte)x54;
+ out[outOff + 5] = (byte)(x54 >> 8);
+ out[outOff + 6] = (byte)x76;
+ out[outOff + 7] = (byte)(x76 >> 8);
+ }
+
+ private void decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ int x76, x54, x32, x10;
+
+ x76 = ((in[inOff + 7] & 0xff) << 8) + (in[inOff + 6] & 0xff);
+ x54 = ((in[inOff + 5] & 0xff) << 8) + (in[inOff + 4] & 0xff);
+ x32 = ((in[inOff + 3] & 0xff) << 8) + (in[inOff + 2] & 0xff);
+ x10 = ((in[inOff + 1] & 0xff) << 8) + (in[inOff + 0] & 0xff);
+
+ for (int i = 60; i >= 44; i -= 4)
+ {
+ x76 = rotateWordLeft(x76, 11) - ((x10 & ~x54) + (x32 & x54) + workingKey[i+3]);
+ x54 = rotateWordLeft(x54, 13) - ((x76 & ~x32) + (x10 & x32) + workingKey[i+2]);
+ x32 = rotateWordLeft(x32, 14) - ((x54 & ~x10) + (x76 & x10) + workingKey[i+1]);
+ x10 = rotateWordLeft(x10, 15) - ((x32 & ~x76) + (x54 & x76) + workingKey[i ]);
+ }
+
+ x76 -= workingKey[x54 & 63];
+ x54 -= workingKey[x32 & 63];
+ x32 -= workingKey[x10 & 63];
+ x10 -= workingKey[x76 & 63];
+
+ for (int i = 40; i >= 20; i -= 4)
+ {
+ x76 = rotateWordLeft(x76, 11) - ((x10 & ~x54) + (x32 & x54) + workingKey[i+3]);
+ x54 = rotateWordLeft(x54, 13) - ((x76 & ~x32) + (x10 & x32) + workingKey[i+2]);
+ x32 = rotateWordLeft(x32, 14) - ((x54 & ~x10) + (x76 & x10) + workingKey[i+1]);
+ x10 = rotateWordLeft(x10, 15) - ((x32 & ~x76) + (x54 & x76) + workingKey[i ]);
+ }
+
+ x76 -= workingKey[x54 & 63];
+ x54 -= workingKey[x32 & 63];
+ x32 -= workingKey[x10 & 63];
+ x10 -= workingKey[x76 & 63];
+
+ for (int i = 16; i >= 0; i -= 4)
+ {
+ x76 = rotateWordLeft(x76, 11) - ((x10 & ~x54) + (x32 & x54) + workingKey[i+3]);
+ x54 = rotateWordLeft(x54, 13) - ((x76 & ~x32) + (x10 & x32) + workingKey[i+2]);
+ x32 = rotateWordLeft(x32, 14) - ((x54 & ~x10) + (x76 & x10) + workingKey[i+1]);
+ x10 = rotateWordLeft(x10, 15) - ((x32 & ~x76) + (x54 & x76) + workingKey[i ]);
+ }
+
+ out[outOff + 0] = (byte)x10;
+ out[outOff + 1] = (byte)(x10 >> 8);
+ out[outOff + 2] = (byte)x32;
+ out[outOff + 3] = (byte)(x32 >> 8);
+ out[outOff + 4] = (byte)x54;
+ out[outOff + 5] = (byte)(x54 >> 8);
+ out[outOff + 6] = (byte)x76;
+ out[outOff + 7] = (byte)(x76 >> 8);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/RC2WrapEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/RC2WrapEngine.java
new file mode 100644
index 00000000..4203954e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/RC2WrapEngine.java
@@ -0,0 +1,385 @@
+package org.spongycastle.crypto.engines;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.Wrapper;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.modes.CBCBlockCipher;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.util.Arrays;
+
+/**
+ * Wrap keys according to RFC 3217 - RC2 mechanism
+ */
+public class RC2WrapEngine
+ implements Wrapper
+{
+ /** Field engine */
+ private CBCBlockCipher engine;
+
+ /** Field param */
+ private CipherParameters param;
+
+ /** Field paramPlusIV */
+ private ParametersWithIV paramPlusIV;
+
+ /** Field iv */
+ private byte[] iv;
+
+ /** Field forWrapping */
+ private boolean forWrapping;
+
+ private SecureRandom sr;
+
+ /** Field IV2 */
+ private static final byte[] IV2 = { (byte) 0x4a, (byte) 0xdd, (byte) 0xa2,
+ (byte) 0x2c, (byte) 0x79, (byte) 0xe8,
+ (byte) 0x21, (byte) 0x05 };
+
+ //
+ // checksum digest
+ //
+ Digest sha1 = new SHA1Digest();
+ byte[] digest = new byte[20];
+
+ /**
+ * Method init
+ *
+ * @param forWrapping
+ * @param param
+ */
+ public void init(boolean forWrapping, CipherParameters param)
+ {
+ this.forWrapping = forWrapping;
+ this.engine = new CBCBlockCipher(new RC2Engine());
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom pWithR = (ParametersWithRandom)param;
+ sr = pWithR.getRandom();
+ param = pWithR.getParameters();
+ }
+ else
+ {
+ sr = new SecureRandom();
+ }
+
+ if (param instanceof ParametersWithIV)
+ {
+ this.paramPlusIV = (ParametersWithIV)param;
+ this.iv = this.paramPlusIV.getIV();
+ this.param = this.paramPlusIV.getParameters();
+
+ if (this.forWrapping)
+ {
+ if ((this.iv == null) || (this.iv.length != 8))
+ {
+ throw new IllegalArgumentException("IV is not 8 octets");
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException(
+ "You should not supply an IV for unwrapping");
+ }
+ }
+ else
+ {
+ this.param = param;
+
+ if (this.forWrapping)
+ {
+
+ // Hm, we have no IV but we want to wrap ?!?
+ // well, then we have to create our own IV.
+ this.iv = new byte[8];
+
+ sr.nextBytes(iv);
+
+ this.paramPlusIV = new ParametersWithIV(this.param, this.iv);
+ }
+ }
+
+ }
+
+ /**
+ * Method getAlgorithmName
+ *
+ * @return the algorithm name "RC2".
+ */
+ public String getAlgorithmName()
+ {
+ return "RC2";
+ }
+
+ /**
+ * Method wrap
+ *
+ * @param in
+ * @param inOff
+ * @param inLen
+ * @return the wrapped bytes.
+ */
+ public byte[] wrap(byte[] in, int inOff, int inLen)
+ {
+
+ if (!forWrapping)
+ {
+ throw new IllegalStateException("Not initialized for wrapping");
+ }
+
+ int length = inLen + 1;
+ if ((length % 8) != 0)
+ {
+ length += 8 - (length % 8);
+ }
+
+ byte keyToBeWrapped[] = new byte[length];
+
+ keyToBeWrapped[0] = (byte)inLen;
+ System.arraycopy(in, inOff, keyToBeWrapped, 1, inLen);
+
+ byte[] pad = new byte[keyToBeWrapped.length - inLen - 1];
+
+ if (pad.length > 0)
+ {
+ sr.nextBytes(pad);
+ System.arraycopy(pad, 0, keyToBeWrapped, inLen + 1, pad.length);
+ }
+
+ // Compute the CMS Key Checksum, (section 5.6.1), call this CKS.
+ byte[] CKS = calculateCMSKeyChecksum(keyToBeWrapped);
+
+ // Let WKCKS = WK || CKS where || is concatenation.
+ byte[] WKCKS = new byte[keyToBeWrapped.length + CKS.length];
+
+ System.arraycopy(keyToBeWrapped, 0, WKCKS, 0, keyToBeWrapped.length);
+ System.arraycopy(CKS, 0, WKCKS, keyToBeWrapped.length, CKS.length);
+
+ // Encrypt WKCKS in CBC mode using KEK as the key and IV as the
+ // initialization vector. Call the results TEMP1.
+ byte TEMP1[] = new byte[WKCKS.length];
+
+ System.arraycopy(WKCKS, 0, TEMP1, 0, WKCKS.length);
+
+ int noOfBlocks = WKCKS.length / engine.getBlockSize();
+ int extraBytes = WKCKS.length % engine.getBlockSize();
+
+ if (extraBytes != 0)
+ {
+ throw new IllegalStateException("Not multiple of block length");
+ }
+
+ engine.init(true, paramPlusIV);
+
+ for (int i = 0; i < noOfBlocks; i++)
+ {
+ int currentBytePos = i * engine.getBlockSize();
+
+ engine.processBlock(TEMP1, currentBytePos, TEMP1, currentBytePos);
+ }
+
+ // Left TEMP2 = IV || TEMP1.
+ byte[] TEMP2 = new byte[this.iv.length + TEMP1.length];
+
+ System.arraycopy(this.iv, 0, TEMP2, 0, this.iv.length);
+ System.arraycopy(TEMP1, 0, TEMP2, this.iv.length, TEMP1.length);
+
+ // Reverse the order of the octets in TEMP2 and call the result TEMP3.
+ byte[] TEMP3 = new byte[TEMP2.length];
+
+ for (int i = 0; i < TEMP2.length; i++)
+ {
+ TEMP3[i] = TEMP2[TEMP2.length - (i + 1)];
+ }
+
+ // Encrypt TEMP3 in CBC mode using the KEK and an initialization vector
+ // of 0x 4a dd a2 2c 79 e8 21 05. The resulting cipher text is the
+ // desired
+ // result. It is 40 octets long if a 168 bit key is being wrapped.
+ ParametersWithIV param2 = new ParametersWithIV(this.param, IV2);
+
+ this.engine.init(true, param2);
+
+ for (int i = 0; i < noOfBlocks + 1; i++)
+ {
+ int currentBytePos = i * engine.getBlockSize();
+
+ engine.processBlock(TEMP3, currentBytePos, TEMP3, currentBytePos);
+ }
+
+ return TEMP3;
+ }
+
+ /**
+ * Method unwrap
+ *
+ * @param in
+ * @param inOff
+ * @param inLen
+ * @return the unwrapped bytes.
+ * @throws InvalidCipherTextException
+ */
+ public byte[] unwrap(byte[] in, int inOff, int inLen)
+ throws InvalidCipherTextException
+ {
+
+ if (forWrapping)
+ {
+ throw new IllegalStateException("Not set for unwrapping");
+ }
+
+ if (in == null)
+ {
+ throw new InvalidCipherTextException("Null pointer as ciphertext");
+ }
+
+ if (inLen % engine.getBlockSize() != 0)
+ {
+ throw new InvalidCipherTextException("Ciphertext not multiple of "
+ + engine.getBlockSize());
+ }
+
+ /*
+ * // Check if the length of the cipher text is reasonable given the key //
+ * type. It must be 40 bytes for a 168 bit key and either 32, 40, or //
+ * 48 bytes for a 128, 192, or 256 bit key. If the length is not
+ * supported // or inconsistent with the algorithm for which the key is
+ * intended, // return error. // // we do not accept 168 bit keys. it
+ * has to be 192 bit. int lengthA = (estimatedKeyLengthInBit / 8) + 16;
+ * int lengthB = estimatedKeyLengthInBit % 8;
+ *
+ * if ((lengthA != keyToBeUnwrapped.length) || (lengthB != 0)) { throw
+ * new XMLSecurityException("empty"); }
+ */
+
+ // Decrypt the cipher text with TRIPLedeS in CBC mode using the KEK
+ // and an initialization vector (IV) of 0x4adda22c79e82105. Call the
+ // output TEMP3.
+ ParametersWithIV param2 = new ParametersWithIV(this.param, IV2);
+
+ this.engine.init(false, param2);
+
+ byte TEMP3[] = new byte[inLen];
+
+ System.arraycopy(in, inOff, TEMP3, 0, inLen);
+
+ for (int i = 0; i < (TEMP3.length / engine.getBlockSize()); i++)
+ {
+ int currentBytePos = i * engine.getBlockSize();
+
+ engine.processBlock(TEMP3, currentBytePos, TEMP3, currentBytePos);
+ }
+
+ // Reverse the order of the octets in TEMP3 and call the result TEMP2.
+ byte[] TEMP2 = new byte[TEMP3.length];
+
+ for (int i = 0; i < TEMP3.length; i++)
+ {
+ TEMP2[i] = TEMP3[TEMP3.length - (i + 1)];
+ }
+
+ // Decompose TEMP2 into IV, the first 8 octets, and TEMP1, the remaining
+ // octets.
+ this.iv = new byte[8];
+
+ byte[] TEMP1 = new byte[TEMP2.length - 8];
+
+ System.arraycopy(TEMP2, 0, this.iv, 0, 8);
+ System.arraycopy(TEMP2, 8, TEMP1, 0, TEMP2.length - 8);
+
+ // Decrypt TEMP1 using TRIPLedeS in CBC mode using the KEK and the IV
+ // found in the previous step. Call the result WKCKS.
+ this.paramPlusIV = new ParametersWithIV(this.param, this.iv);
+
+ this.engine.init(false, this.paramPlusIV);
+
+ byte[] LCEKPADICV = new byte[TEMP1.length];
+
+ System.arraycopy(TEMP1, 0, LCEKPADICV, 0, TEMP1.length);
+
+ for (int i = 0; i < (LCEKPADICV.length / engine.getBlockSize()); i++)
+ {
+ int currentBytePos = i * engine.getBlockSize();
+
+ engine.processBlock(LCEKPADICV, currentBytePos, LCEKPADICV,
+ currentBytePos);
+ }
+
+ // Decompose LCEKPADICV. CKS is the last 8 octets and WK, the wrapped
+ // key, are
+ // those octets before the CKS.
+ byte[] result = new byte[LCEKPADICV.length - 8];
+ byte[] CKStoBeVerified = new byte[8];
+
+ System.arraycopy(LCEKPADICV, 0, result, 0, LCEKPADICV.length - 8);
+ System.arraycopy(LCEKPADICV, LCEKPADICV.length - 8, CKStoBeVerified, 0,
+ 8);
+
+ // Calculate a CMS Key Checksum, (section 5.6.1), over the WK and
+ // compare
+ // with the CKS extracted in the above step. If they are not equal,
+ // return error.
+ if (!checkCMSKeyChecksum(result, CKStoBeVerified))
+ {
+ throw new InvalidCipherTextException(
+ "Checksum inside ciphertext is corrupted");
+ }
+
+ if ((result.length - ((result[0] & 0xff) + 1)) > 7)
+ {
+ throw new InvalidCipherTextException("too many pad bytes ("
+ + (result.length - ((result[0] & 0xff) + 1)) + ")");
+ }
+
+ // CEK is the wrapped key, now extracted for use in data decryption.
+ byte[] CEK = new byte[result[0]];
+ System.arraycopy(result, 1, CEK, 0, CEK.length);
+ return CEK;
+ }
+
+ /**
+ * Some key wrap algorithms make use of the Key Checksum defined
+ * in CMS [CMS-Algorithms]. This is used to provide an integrity
+ * check value for the key being wrapped. The algorithm is
+ *
+ * - Compute the 20 octet SHA-1 hash on the key being wrapped.
+ * - Use the first 8 octets of this hash as the checksum value.
+ *
+ * For details see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
+ * @param key
+ * @return
+ * @throws RuntimeException
+ *
+ */
+ private byte[] calculateCMSKeyChecksum(
+ byte[] key)
+ {
+ byte[] result = new byte[8];
+
+ sha1.update(key, 0, key.length);
+ sha1.doFinal(digest, 0);
+
+ System.arraycopy(digest, 0, result, 0, 8);
+
+ return result;
+ }
+
+ /**
+ * For details see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
+ *
+ * @param key
+ * @param checksum
+ * @return
+ */
+ private boolean checkCMSKeyChecksum(
+ byte[] key,
+ byte[] checksum)
+ {
+ return Arrays.constantTimeAreEqual(calculateCMSKeyChecksum(key), checksum);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/RC4Engine.java b/core/src/main/java/org/spongycastle/crypto/engines/RC4Engine.java
new file mode 100644
index 00000000..e7ff73a9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/RC4Engine.java
@@ -0,0 +1,146 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.StreamCipher;
+import org.spongycastle.crypto.params.KeyParameter;
+
+public class RC4Engine implements StreamCipher
+{
+ private final static int STATE_LENGTH = 256;
+
+ /*
+ * variables to hold the state of the RC4 engine
+ * during encryption and decryption
+ */
+
+ private byte[] engineState = null;
+ private int x = 0;
+ private int y = 0;
+ private byte[] workingKey = null;
+
+ /**
+ * initialise a RC4 cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params
+ )
+ {
+ if (params instanceof KeyParameter)
+ {
+ /*
+ * RC4 encryption and decryption is completely
+ * symmetrical, so the 'forEncryption' is
+ * irrelevant.
+ */
+ workingKey = ((KeyParameter)params).getKey();
+ setKey(workingKey);
+
+ return;
+ }
+
+ throw new IllegalArgumentException("invalid parameter passed to RC4 init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "RC4";
+ }
+
+ public byte returnByte(byte in)
+ {
+ x = (x + 1) & 0xff;
+ y = (engineState[x] + y) & 0xff;
+
+ // swap
+ byte tmp = engineState[x];
+ engineState[x] = engineState[y];
+ engineState[y] = tmp;
+
+ // xor
+ return (byte)(in ^ engineState[(engineState[x] + engineState[y]) & 0xff]);
+ }
+
+ public int processBytes(
+ byte[] in,
+ int inOff,
+ int len,
+ byte[] out,
+ int outOff)
+ {
+ if ((inOff + len) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + len) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ for (int i = 0; i < len ; i++)
+ {
+ x = (x + 1) & 0xff;
+ y = (engineState[x] + y) & 0xff;
+
+ // swap
+ byte tmp = engineState[x];
+ engineState[x] = engineState[y];
+ engineState[y] = tmp;
+
+ // xor
+ out[i+outOff] = (byte)(in[i + inOff]
+ ^ engineState[(engineState[x] + engineState[y]) & 0xff]);
+ }
+
+ return len;
+ }
+
+ public void reset()
+ {
+ setKey(workingKey);
+ }
+
+ // Private implementation
+
+ private void setKey(byte[] keyBytes)
+ {
+ workingKey = keyBytes;
+
+ // System.out.println("the key length is ; "+ workingKey.length);
+
+ x = 0;
+ y = 0;
+
+ if (engineState == null)
+ {
+ engineState = new byte[STATE_LENGTH];
+ }
+
+ // reset the state of the engine
+ for (int i=0; i < STATE_LENGTH; i++)
+ {
+ engineState[i] = (byte)i;
+ }
+
+ int i1 = 0;
+ int i2 = 0;
+
+ for (int i=0; i < STATE_LENGTH; i++)
+ {
+ i2 = ((keyBytes[i1] & 0xff) + engineState[i] + i2) & 0xff;
+ // do the byte-swap inline
+ byte tmp = engineState[i];
+ engineState[i] = engineState[i2];
+ engineState[i2] = tmp;
+ i1 = (i1+1) % keyBytes.length;
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/RC532Engine.java b/core/src/main/java/org/spongycastle/crypto/engines/RC532Engine.java
new file mode 100644
index 00000000..24619716
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/RC532Engine.java
@@ -0,0 +1,287 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.RC5Parameters;
+
+/**
+ * The specification for RC5 came from the <code>RC5 Encryption Algorithm</code>
+ * publication in RSA CryptoBytes, Spring of 1995.
+ * <em>http://www.rsasecurity.com/rsalabs/cryptobytes</em>.
+ * <p>
+ * This implementation has a word size of 32 bits.
+ * <p>
+ * Implementation courtesy of Tito Pena.
+ */
+public class RC532Engine
+ implements BlockCipher
+{
+ /*
+ * the number of rounds to perform
+ */
+ private int _noRounds;
+
+ /*
+ * the expanded key array of size 2*(rounds + 1)
+ */
+ private int _S[];
+
+ /*
+ * our "magic constants" for 32 32
+ *
+ * Pw = Odd((e-2) * 2^wordsize)
+ * Qw = Odd((o-2) * 2^wordsize)
+ *
+ * where e is the base of natural logarithms (2.718281828...)
+ * and o is the golden ratio (1.61803398...)
+ */
+ private static final int P32 = 0xb7e15163;
+ private static final int Q32 = 0x9e3779b9;
+
+ private boolean forEncryption;
+
+ /**
+ * Create an instance of the RC5 encryption algorithm
+ * and set some defaults
+ */
+ public RC532Engine()
+ {
+ _noRounds = 12; // the default
+ _S = null;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "RC5-32";
+ }
+
+ public int getBlockSize()
+ {
+ return 2 * 4;
+ }
+
+ /**
+ * initialise a RC5-32 cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (params instanceof RC5Parameters)
+ {
+ RC5Parameters p = (RC5Parameters)params;
+
+ _noRounds = p.getRounds();
+
+ setKey(p.getKey());
+ }
+ else if (params instanceof KeyParameter)
+ {
+ KeyParameter p = (KeyParameter)params;
+
+ setKey(p.getKey());
+ }
+ else
+ {
+ throw new IllegalArgumentException("invalid parameter passed to RC532 init - " + params.getClass().getName());
+ }
+
+ this.forEncryption = forEncryption;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ return (forEncryption) ? encryptBlock(in, inOff, out, outOff)
+ : decryptBlock(in, inOff, out, outOff);
+ }
+
+ public void reset()
+ {
+ }
+
+ /**
+ * Re-key the cipher.
+ * <p>
+ * @param key the key to be used
+ */
+ private void setKey(
+ byte[] key)
+ {
+ //
+ // KEY EXPANSION:
+ //
+ // There are 3 phases to the key expansion.
+ //
+ // Phase 1:
+ // Copy the secret key K[0...b-1] into an array L[0..c-1] of
+ // c = ceil(b/u), where u = 32/8 in little-endian order.
+ // In other words, we fill up L using u consecutive key bytes
+ // of K. Any unfilled byte positions in L are zeroed. In the
+ // case that b = c = 0, set c = 1 and L[0] = 0.
+ //
+ int[] L = new int[(key.length + (4 - 1)) / 4];
+
+ for (int i = 0; i != key.length; i++)
+ {
+ L[i / 4] += (key[i] & 0xff) << (8 * (i % 4));
+ }
+
+ //
+ // Phase 2:
+ // Initialize S to a particular fixed pseudo-random bit pattern
+ // using an arithmetic progression modulo 2^wordsize determined
+ // by the magic numbers, Pw & Qw.
+ //
+ _S = new int[2*(_noRounds + 1)];
+
+ _S[0] = P32;
+ for (int i=1; i < _S.length; i++)
+ {
+ _S[i] = (_S[i-1] + Q32);
+ }
+
+ //
+ // Phase 3:
+ // Mix in the user's secret key in 3 passes over the arrays S & L.
+ // The max of the arrays sizes is used as the loop control
+ //
+ int iter;
+
+ if (L.length > _S.length)
+ {
+ iter = 3 * L.length;
+ }
+ else
+ {
+ iter = 3 * _S.length;
+ }
+
+ int A = 0, B = 0;
+ int i = 0, j = 0;
+
+ for (int k = 0; k < iter; k++)
+ {
+ A = _S[i] = rotateLeft(_S[i] + A + B, 3);
+ B = L[j] = rotateLeft(L[j] + A + B, A+B);
+ i = (i+1) % _S.length;
+ j = (j+1) % L.length;
+ }
+ }
+
+ /**
+ * Encrypt the given block starting at the given offset and place
+ * the result in the provided buffer starting at the given offset.
+ * <p>
+ * @param in in byte buffer containing data to encrypt
+ * @param inOff offset into src buffer
+ * @param out out buffer where encrypted data is written
+ * @param outOff offset into out buffer
+ */
+ private int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ int A = bytesToWord(in, inOff) + _S[0];
+ int B = bytesToWord(in, inOff + 4) + _S[1];
+
+ for (int i = 1; i <= _noRounds; i++)
+ {
+ A = rotateLeft(A ^ B, B) + _S[2*i];
+ B = rotateLeft(B ^ A, A) + _S[2*i+1];
+ }
+
+ wordToBytes(A, out, outOff);
+ wordToBytes(B, out, outOff + 4);
+
+ return 2 * 4;
+ }
+
+ private int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ int A = bytesToWord(in, inOff);
+ int B = bytesToWord(in, inOff + 4);
+
+ for (int i = _noRounds; i >= 1; i--)
+ {
+ B = rotateRight(B - _S[2*i+1], A) ^ A;
+ A = rotateRight(A - _S[2*i], B) ^ B;
+ }
+
+ wordToBytes(A - _S[0], out, outOff);
+ wordToBytes(B - _S[1], out, outOff + 4);
+
+ return 2 * 4;
+ }
+
+
+ //////////////////////////////////////////////////////////////
+ //
+ // PRIVATE Helper Methods
+ //
+ //////////////////////////////////////////////////////////////
+
+ /**
+ * Perform a left "spin" of the word. The rotation of the given
+ * word <em>x</em> is rotated left by <em>y</em> bits.
+ * Only the <em>lg(32)</em> low-order bits of <em>y</em>
+ * are used to determine the rotation amount. Here it is
+ * assumed that the wordsize used is a power of 2.
+ * <p>
+ * @param x word to rotate
+ * @param y number of bits to rotate % 32
+ */
+ private int rotateLeft(int x, int y)
+ {
+ return ((x << (y & (32-1))) | (x >>> (32 - (y & (32-1)))));
+ }
+
+ /**
+ * Perform a right "spin" of the word. The rotation of the given
+ * word <em>x</em> is rotated left by <em>y</em> bits.
+ * Only the <em>lg(32)</em> low-order bits of <em>y</em>
+ * are used to determine the rotation amount. Here it is
+ * assumed that the wordsize used is a power of 2.
+ * <p>
+ * @param x word to rotate
+ * @param y number of bits to rotate % 32
+ */
+ private int rotateRight(int x, int y)
+ {
+ return ((x >>> (y & (32-1))) | (x << (32 - (y & (32-1)))));
+ }
+
+ private int bytesToWord(
+ byte[] src,
+ int srcOff)
+ {
+ return (src[srcOff] & 0xff) | ((src[srcOff + 1] & 0xff) << 8)
+ | ((src[srcOff + 2] & 0xff) << 16) | ((src[srcOff + 3] & 0xff) << 24);
+ }
+
+ private void wordToBytes(
+ int word,
+ byte[] dst,
+ int dstOff)
+ {
+ dst[dstOff] = (byte)word;
+ dst[dstOff + 1] = (byte)(word >> 8);
+ dst[dstOff + 2] = (byte)(word >> 16);
+ dst[dstOff + 3] = (byte)(word >> 24);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/RC564Engine.java b/core/src/main/java/org/spongycastle/crypto/engines/RC564Engine.java
new file mode 100644
index 00000000..06fcbf7c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/RC564Engine.java
@@ -0,0 +1,288 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.params.RC5Parameters;
+
+/**
+ * The specification for RC5 came from the <code>RC5 Encryption Algorithm</code>
+ * publication in RSA CryptoBytes, Spring of 1995.
+ * <em>http://www.rsasecurity.com/rsalabs/cryptobytes</em>.
+ * <p>
+ * This implementation is set to work with a 64 bit word size.
+ * <p>
+ * Implementation courtesy of Tito Pena.
+ */
+public class RC564Engine
+ implements BlockCipher
+{
+ private static final int wordSize = 64;
+ private static final int bytesPerWord = wordSize / 8;
+
+ /*
+ * the number of rounds to perform
+ */
+ private int _noRounds;
+
+ /*
+ * the expanded key array of size 2*(rounds + 1)
+ */
+ private long _S[];
+
+ /*
+ * our "magic constants" for wordSize 62
+ *
+ * Pw = Odd((e-2) * 2^wordsize)
+ * Qw = Odd((o-2) * 2^wordsize)
+ *
+ * where e is the base of natural logarithms (2.718281828...)
+ * and o is the golden ratio (1.61803398...)
+ */
+ private static final long P64 = 0xb7e151628aed2a6bL;
+ private static final long Q64 = 0x9e3779b97f4a7c15L;
+
+ private boolean forEncryption;
+
+ /**
+ * Create an instance of the RC5 encryption algorithm
+ * and set some defaults
+ */
+ public RC564Engine()
+ {
+ _noRounds = 12;
+ _S = null;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "RC5-64";
+ }
+
+ public int getBlockSize()
+ {
+ return 2 * bytesPerWord;
+ }
+
+ /**
+ * initialise a RC5-64 cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (!(params instanceof RC5Parameters))
+ {
+ throw new IllegalArgumentException("invalid parameter passed to RC564 init - " + params.getClass().getName());
+ }
+
+ RC5Parameters p = (RC5Parameters)params;
+
+ this.forEncryption = forEncryption;
+
+ _noRounds = p.getRounds();
+
+ setKey(p.getKey());
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ return (forEncryption) ? encryptBlock(in, inOff, out, outOff)
+ : decryptBlock(in, inOff, out, outOff);
+ }
+
+ public void reset()
+ {
+ }
+
+ /**
+ * Re-key the cipher.
+ * <p>
+ * @param key the key to be used
+ */
+ private void setKey(
+ byte[] key)
+ {
+ //
+ // KEY EXPANSION:
+ //
+ // There are 3 phases to the key expansion.
+ //
+ // Phase 1:
+ // Copy the secret key K[0...b-1] into an array L[0..c-1] of
+ // c = ceil(b/u), where u = wordSize/8 in little-endian order.
+ // In other words, we fill up L using u consecutive key bytes
+ // of K. Any unfilled byte positions in L are zeroed. In the
+ // case that b = c = 0, set c = 1 and L[0] = 0.
+ //
+ long[] L = new long[(key.length + (bytesPerWord - 1)) / bytesPerWord];
+
+ for (int i = 0; i != key.length; i++)
+ {
+ L[i / bytesPerWord] += (long)(key[i] & 0xff) << (8 * (i % bytesPerWord));
+ }
+
+ //
+ // Phase 2:
+ // Initialize S to a particular fixed pseudo-random bit pattern
+ // using an arithmetic progression modulo 2^wordsize determined
+ // by the magic numbers, Pw & Qw.
+ //
+ _S = new long[2*(_noRounds + 1)];
+
+ _S[0] = P64;
+ for (int i=1; i < _S.length; i++)
+ {
+ _S[i] = (_S[i-1] + Q64);
+ }
+
+ //
+ // Phase 3:
+ // Mix in the user's secret key in 3 passes over the arrays S & L.
+ // The max of the arrays sizes is used as the loop control
+ //
+ int iter;
+
+ if (L.length > _S.length)
+ {
+ iter = 3 * L.length;
+ }
+ else
+ {
+ iter = 3 * _S.length;
+ }
+
+ long A = 0, B = 0;
+ int i = 0, j = 0;
+
+ for (int k = 0; k < iter; k++)
+ {
+ A = _S[i] = rotateLeft(_S[i] + A + B, 3);
+ B = L[j] = rotateLeft(L[j] + A + B, A+B);
+ i = (i+1) % _S.length;
+ j = (j+1) % L.length;
+ }
+ }
+
+ /**
+ * Encrypt the given block starting at the given offset and place
+ * the result in the provided buffer starting at the given offset.
+ * <p>
+ * @param in in byte buffer containing data to encrypt
+ * @param inOff offset into src buffer
+ * @param out out buffer where encrypted data is written
+ * @param outOff offset into out buffer
+ */
+ private int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ long A = bytesToWord(in, inOff) + _S[0];
+ long B = bytesToWord(in, inOff + bytesPerWord) + _S[1];
+
+ for (int i = 1; i <= _noRounds; i++)
+ {
+ A = rotateLeft(A ^ B, B) + _S[2*i];
+ B = rotateLeft(B ^ A, A) + _S[2*i+1];
+ }
+
+ wordToBytes(A, out, outOff);
+ wordToBytes(B, out, outOff + bytesPerWord);
+
+ return 2 * bytesPerWord;
+ }
+
+ private int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ long A = bytesToWord(in, inOff);
+ long B = bytesToWord(in, inOff + bytesPerWord);
+
+ for (int i = _noRounds; i >= 1; i--)
+ {
+ B = rotateRight(B - _S[2*i+1], A) ^ A;
+ A = rotateRight(A - _S[2*i], B) ^ B;
+ }
+
+ wordToBytes(A - _S[0], out, outOff);
+ wordToBytes(B - _S[1], out, outOff + bytesPerWord);
+
+ return 2 * bytesPerWord;
+ }
+
+
+ //////////////////////////////////////////////////////////////
+ //
+ // PRIVATE Helper Methods
+ //
+ //////////////////////////////////////////////////////////////
+
+ /**
+ * Perform a left "spin" of the word. The rotation of the given
+ * word <em>x</em> is rotated left by <em>y</em> bits.
+ * Only the <em>lg(wordSize)</em> low-order bits of <em>y</em>
+ * are used to determine the rotation amount. Here it is
+ * assumed that the wordsize used is a power of 2.
+ * <p>
+ * @param x word to rotate
+ * @param y number of bits to rotate % wordSize
+ */
+ private long rotateLeft(long x, long y)
+ {
+ return ((x << (y & (wordSize-1))) | (x >>> (wordSize - (y & (wordSize-1)))));
+ }
+
+ /**
+ * Perform a right "spin" of the word. The rotation of the given
+ * word <em>x</em> is rotated left by <em>y</em> bits.
+ * Only the <em>lg(wordSize)</em> low-order bits of <em>y</em>
+ * are used to determine the rotation amount. Here it is
+ * assumed that the wordsize used is a power of 2.
+ * <p>
+ * @param x word to rotate
+ * @param y number of bits to rotate % wordSize
+ */
+ private long rotateRight(long x, long y)
+ {
+ return ((x >>> (y & (wordSize-1))) | (x << (wordSize - (y & (wordSize-1)))));
+ }
+
+ private long bytesToWord(
+ byte[] src,
+ int srcOff)
+ {
+ long word = 0;
+
+ for (int i = bytesPerWord - 1; i >= 0; i--)
+ {
+ word = (word << 8) + (src[i + srcOff] & 0xff);
+ }
+
+ return word;
+ }
+
+ private void wordToBytes(
+ long word,
+ byte[] dst,
+ int dstOff)
+ {
+ for (int i = 0; i < bytesPerWord; i++)
+ {
+ dst[i + dstOff] = (byte)word;
+ word >>>= 8;
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/RC6Engine.java b/core/src/main/java/org/spongycastle/crypto/engines/RC6Engine.java
new file mode 100644
index 00000000..e91e654e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/RC6Engine.java
@@ -0,0 +1,363 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+
+/**
+ * An RC6 engine.
+ */
+public class RC6Engine
+ implements BlockCipher
+{
+ private static final int wordSize = 32;
+ private static final int bytesPerWord = wordSize / 8;
+
+ /*
+ * the number of rounds to perform
+ */
+ private static final int _noRounds = 20;
+
+ /*
+ * the expanded key array of size 2*(rounds + 1)
+ */
+ private int _S[];
+
+ /*
+ * our "magic constants" for wordSize 32
+ *
+ * Pw = Odd((e-2) * 2^wordsize)
+ * Qw = Odd((o-2) * 2^wordsize)
+ *
+ * where e is the base of natural logarithms (2.718281828...)
+ * and o is the golden ratio (1.61803398...)
+ */
+ private static final int P32 = 0xb7e15163;
+ private static final int Q32 = 0x9e3779b9;
+
+ private static final int LGW = 5; // log2(32)
+
+ private boolean forEncryption;
+
+ /**
+ * Create an instance of the RC6 encryption algorithm
+ * and set some defaults
+ */
+ public RC6Engine()
+ {
+ _S = null;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "RC6";
+ }
+
+ public int getBlockSize()
+ {
+ return 4 * bytesPerWord;
+ }
+
+ /**
+ * initialise a RC5-32 cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (!(params instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("invalid parameter passed to RC6 init - " + params.getClass().getName());
+ }
+
+ KeyParameter p = (KeyParameter)params;
+ this.forEncryption = forEncryption;
+ setKey(p.getKey());
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ int blockSize = getBlockSize();
+ if (_S == null)
+ {
+ throw new IllegalStateException("RC6 engine not initialised");
+ }
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ return (forEncryption)
+ ? encryptBlock(in, inOff, out, outOff)
+ : decryptBlock(in, inOff, out, outOff);
+ }
+
+ public void reset()
+ {
+ }
+
+ /**
+ * Re-key the cipher.
+ * <p>
+ * @param key the key to be used
+ */
+ private void setKey(
+ byte[] key)
+ {
+
+ //
+ // KEY EXPANSION:
+ //
+ // There are 3 phases to the key expansion.
+ //
+ // Phase 1:
+ // Copy the secret key K[0...b-1] into an array L[0..c-1] of
+ // c = ceil(b/u), where u = wordSize/8 in little-endian order.
+ // In other words, we fill up L using u consecutive key bytes
+ // of K. Any unfilled byte positions in L are zeroed. In the
+ // case that b = c = 0, set c = 1 and L[0] = 0.
+ //
+ // compute number of dwords
+ int c = (key.length + (bytesPerWord - 1)) / bytesPerWord;
+ if (c == 0)
+ {
+ c = 1;
+ }
+ int[] L = new int[(key.length + bytesPerWord - 1) / bytesPerWord];
+
+ // load all key bytes into array of key dwords
+ for (int i = key.length - 1; i >= 0; i--)
+ {
+ L[i / bytesPerWord] = (L[i / bytesPerWord] << 8) + (key[i] & 0xff);
+ }
+
+ //
+ // Phase 2:
+ // Key schedule is placed in a array of 2+2*ROUNDS+2 = 44 dwords.
+ // Initialize S to a particular fixed pseudo-random bit pattern
+ // using an arithmetic progression modulo 2^wordsize determined
+ // by the magic numbers, Pw & Qw.
+ //
+ _S = new int[2+2*_noRounds+2];
+
+ _S[0] = P32;
+ for (int i=1; i < _S.length; i++)
+ {
+ _S[i] = (_S[i-1] + Q32);
+ }
+
+ //
+ // Phase 3:
+ // Mix in the user's secret key in 3 passes over the arrays S & L.
+ // The max of the arrays sizes is used as the loop control
+ //
+ int iter;
+
+ if (L.length > _S.length)
+ {
+ iter = 3 * L.length;
+ }
+ else
+ {
+ iter = 3 * _S.length;
+ }
+
+ int A = 0;
+ int B = 0;
+ int i = 0, j = 0;
+
+ for (int k = 0; k < iter; k++)
+ {
+ A = _S[i] = rotateLeft(_S[i] + A + B, 3);
+ B = L[j] = rotateLeft(L[j] + A + B, A+B);
+ i = (i+1) % _S.length;
+ j = (j+1) % L.length;
+ }
+ }
+
+ private int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ // load A,B,C and D registers from in.
+ int A = bytesToWord(in, inOff);
+ int B = bytesToWord(in, inOff + bytesPerWord);
+ int C = bytesToWord(in, inOff + bytesPerWord*2);
+ int D = bytesToWord(in, inOff + bytesPerWord*3);
+
+ // Do pseudo-round #0: pre-whitening of B and D
+ B += _S[0];
+ D += _S[1];
+
+ // perform round #1,#2 ... #ROUNDS of encryption
+ for (int i = 1; i <= _noRounds; i++)
+ {
+ int t = 0,u = 0;
+
+ t = B*(2*B+1);
+ t = rotateLeft(t,5);
+
+ u = D*(2*D+1);
+ u = rotateLeft(u,5);
+
+ A ^= t;
+ A = rotateLeft(A,u);
+ A += _S[2*i];
+
+ C ^= u;
+ C = rotateLeft(C,t);
+ C += _S[2*i+1];
+
+ int temp = A;
+ A = B;
+ B = C;
+ C = D;
+ D = temp;
+ }
+ // do pseudo-round #(ROUNDS+1) : post-whitening of A and C
+ A += _S[2*_noRounds+2];
+ C += _S[2*_noRounds+3];
+
+ // store A, B, C and D registers to out
+ wordToBytes(A, out, outOff);
+ wordToBytes(B, out, outOff + bytesPerWord);
+ wordToBytes(C, out, outOff + bytesPerWord*2);
+ wordToBytes(D, out, outOff + bytesPerWord*3);
+
+ return 4 * bytesPerWord;
+ }
+
+ private int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ // load A,B,C and D registers from out.
+ int A = bytesToWord(in, inOff);
+ int B = bytesToWord(in, inOff + bytesPerWord);
+ int C = bytesToWord(in, inOff + bytesPerWord*2);
+ int D = bytesToWord(in, inOff + bytesPerWord*3);
+
+ // Undo pseudo-round #(ROUNDS+1) : post whitening of A and C
+ C -= _S[2*_noRounds+3];
+ A -= _S[2*_noRounds+2];
+
+ // Undo round #ROUNDS, .., #2,#1 of encryption
+ for (int i = _noRounds; i >= 1; i--)
+ {
+ int t=0,u = 0;
+
+ int temp = D;
+ D = C;
+ C = B;
+ B = A;
+ A = temp;
+
+ t = B*(2*B+1);
+ t = rotateLeft(t, LGW);
+
+ u = D*(2*D+1);
+ u = rotateLeft(u, LGW);
+
+ C -= _S[2*i+1];
+ C = rotateRight(C,t);
+ C ^= u;
+
+ A -= _S[2*i];
+ A = rotateRight(A,u);
+ A ^= t;
+
+ }
+ // Undo pseudo-round #0: pre-whitening of B and D
+ D -= _S[1];
+ B -= _S[0];
+
+ wordToBytes(A, out, outOff);
+ wordToBytes(B, out, outOff + bytesPerWord);
+ wordToBytes(C, out, outOff + bytesPerWord*2);
+ wordToBytes(D, out, outOff + bytesPerWord*3);
+
+ return 4 * bytesPerWord;
+ }
+
+
+ //////////////////////////////////////////////////////////////
+ //
+ // PRIVATE Helper Methods
+ //
+ //////////////////////////////////////////////////////////////
+
+ /**
+ * Perform a left "spin" of the word. The rotation of the given
+ * word <em>x</em> is rotated left by <em>y</em> bits.
+ * Only the <em>lg(wordSize)</em> low-order bits of <em>y</em>
+ * are used to determine the rotation amount. Here it is
+ * assumed that the wordsize used is 32.
+ * <p>
+ * @param x word to rotate
+ * @param y number of bits to rotate % wordSize
+ */
+ private int rotateLeft(int x, int y)
+ {
+ return (x << y) | (x >>> -y);
+ }
+
+ /**
+ * Perform a right "spin" of the word. The rotation of the given
+ * word <em>x</em> is rotated left by <em>y</em> bits.
+ * Only the <em>lg(wordSize)</em> low-order bits of <em>y</em>
+ * are used to determine the rotation amount. Here it is
+ * assumed that the wordsize used is a power of 2.
+ * <p>
+ * @param x word to rotate
+ * @param y number of bits to rotate % wordSize
+ */
+ private int rotateRight(int x, int y)
+ {
+ return (x >>> y) | (x << -y);
+ }
+
+ private int bytesToWord(
+ byte[] src,
+ int srcOff)
+ {
+ int word = 0;
+
+ for (int i = bytesPerWord - 1; i >= 0; i--)
+ {
+ word = (word << 8) + (src[i + srcOff] & 0xff);
+ }
+
+ return word;
+ }
+
+ private void wordToBytes(
+ int word,
+ byte[] dst,
+ int dstOff)
+ {
+ for (int i = 0; i < bytesPerWord; i++)
+ {
+ dst[i + dstOff] = (byte)word;
+ word >>>= 8;
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/RFC3211WrapEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/RFC3211WrapEngine.java
new file mode 100644
index 00000000..f55a717a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/RFC3211WrapEngine.java
@@ -0,0 +1,175 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.Wrapper;
+import org.spongycastle.crypto.modes.CBCBlockCipher;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+
+import java.security.SecureRandom;
+
+/**
+ * an implementation of the RFC 3211 Key Wrap
+ * Specification.
+ */
+public class RFC3211WrapEngine
+ implements Wrapper
+{
+ private CBCBlockCipher engine;
+ private ParametersWithIV param;
+ private boolean forWrapping;
+ private SecureRandom rand;
+
+ public RFC3211WrapEngine(BlockCipher engine)
+ {
+ this.engine = new CBCBlockCipher(engine);
+ }
+
+ public void init(
+ boolean forWrapping,
+ CipherParameters param)
+ {
+ this.forWrapping = forWrapping;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom p = (ParametersWithRandom)param;
+
+ rand = p.getRandom();
+ this.param = (ParametersWithIV)p.getParameters();
+ }
+ else
+ {
+ if (forWrapping)
+ {
+ rand = new SecureRandom();
+ }
+
+ this.param = (ParametersWithIV)param;
+ }
+ }
+
+ public String getAlgorithmName()
+ {
+ return engine.getUnderlyingCipher().getAlgorithmName() + "/RFC3211Wrap";
+ }
+
+ public byte[] wrap(
+ byte[] in,
+ int inOff,
+ int inLen)
+ {
+ if (!forWrapping)
+ {
+ throw new IllegalStateException("not set for wrapping");
+ }
+
+ engine.init(true, param);
+
+ int blockSize = engine.getBlockSize();
+ byte[] cekBlock;
+
+ if (inLen + 4 < blockSize * 2)
+ {
+ cekBlock = new byte[blockSize * 2];
+ }
+ else
+ {
+ cekBlock = new byte[(inLen + 4) % blockSize == 0 ? inLen + 4 : ((inLen + 4) / blockSize + 1) * blockSize];
+ }
+
+ cekBlock[0] = (byte)inLen;
+ cekBlock[1] = (byte)~in[inOff];
+ cekBlock[2] = (byte)~in[inOff + 1];
+ cekBlock[3] = (byte)~in[inOff + 2];
+
+ System.arraycopy(in, inOff, cekBlock, 4, inLen);
+
+ for (int i = inLen + 4; i < cekBlock.length; i++)
+ {
+ cekBlock[i] = (byte)rand.nextInt();
+ }
+
+ for (int i = 0; i < cekBlock.length; i += blockSize)
+ {
+ engine.processBlock(cekBlock, i, cekBlock, i);
+ }
+
+ for (int i = 0; i < cekBlock.length; i += blockSize)
+ {
+ engine.processBlock(cekBlock, i, cekBlock, i);
+ }
+
+ return cekBlock;
+ }
+
+ public byte[] unwrap(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ if (forWrapping)
+ {
+ throw new IllegalStateException("not set for unwrapping");
+ }
+
+ int blockSize = engine.getBlockSize();
+
+ if (inLen < 2 * blockSize)
+ {
+ throw new InvalidCipherTextException("input too short");
+ }
+
+ byte[] cekBlock = new byte[inLen];
+ byte[] iv = new byte[blockSize];
+
+ System.arraycopy(in, inOff, cekBlock, 0, inLen);
+ System.arraycopy(in, inOff, iv, 0, iv.length);
+
+ engine.init(false, new ParametersWithIV(param.getParameters(), iv));
+
+ for (int i = blockSize; i < cekBlock.length; i += blockSize)
+ {
+ engine.processBlock(cekBlock, i, cekBlock, i);
+ }
+
+ System.arraycopy(cekBlock, cekBlock.length - iv.length, iv, 0, iv.length);
+
+ engine.init(false, new ParametersWithIV(param.getParameters(), iv));
+
+ engine.processBlock(cekBlock, 0, cekBlock, 0);
+
+ engine.init(false, param);
+
+ for (int i = 0; i < cekBlock.length; i += blockSize)
+ {
+ engine.processBlock(cekBlock, i, cekBlock, i);
+ }
+
+ if ((cekBlock[0] & 0xff) > cekBlock.length - 4)
+ {
+ throw new InvalidCipherTextException("wrapped key corrupted");
+ }
+
+ byte[] key = new byte[cekBlock[0] & 0xff];
+
+ System.arraycopy(cekBlock, 4, key, 0, cekBlock[0]);
+
+ // Note: Using constant time comparison
+ int nonEqual = 0;
+ for (int i = 0; i != 3; i++)
+ {
+ byte check = (byte)~cekBlock[1 + i];
+ nonEqual |= (check ^ key[i]);
+ }
+ if (nonEqual != 0)
+ {
+ throw new InvalidCipherTextException("wrapped key fails checksum");
+ }
+
+ return key;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/RFC3394WrapEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/RFC3394WrapEngine.java
new file mode 100644
index 00000000..67ee43a7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/RFC3394WrapEngine.java
@@ -0,0 +1,177 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.Wrapper;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.util.Arrays;
+
+/**
+ * an implementation of the AES Key Wrapper from the NIST Key Wrap
+ * Specification as described in RFC 3394.
+ * <p>
+ * For further details see: <a href="http://www.ietf.org/rfc/rfc3394.txt">http://www.ietf.org/rfc/rfc3394.txt</a>
+ * and <a href="http://csrc.nist.gov/encryption/kms/key-wrap.pdf">http://csrc.nist.gov/encryption/kms/key-wrap.pdf</a>.
+ */
+public class RFC3394WrapEngine
+ implements Wrapper
+{
+ private BlockCipher engine;
+ private KeyParameter param;
+ private boolean forWrapping;
+
+ private byte[] iv = {
+ (byte)0xa6, (byte)0xa6, (byte)0xa6, (byte)0xa6,
+ (byte)0xa6, (byte)0xa6, (byte)0xa6, (byte)0xa6 };
+
+ public RFC3394WrapEngine(BlockCipher engine)
+ {
+ this.engine = engine;
+ }
+
+ public void init(
+ boolean forWrapping,
+ CipherParameters param)
+ {
+ this.forWrapping = forWrapping;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ param = ((ParametersWithRandom) param).getParameters();
+ }
+
+ if (param instanceof KeyParameter)
+ {
+ this.param = (KeyParameter)param;
+ }
+ else if (param instanceof ParametersWithIV)
+ {
+ this.iv = ((ParametersWithIV)param).getIV();
+ this.param = (KeyParameter)((ParametersWithIV) param).getParameters();
+ if (this.iv.length != 8)
+ {
+ throw new IllegalArgumentException("IV not equal to 8");
+ }
+ }
+ }
+
+ public String getAlgorithmName()
+ {
+ return engine.getAlgorithmName();
+ }
+
+ public byte[] wrap(
+ byte[] in,
+ int inOff,
+ int inLen)
+ {
+ if (!forWrapping)
+ {
+ throw new IllegalStateException("not set for wrapping");
+ }
+
+ int n = inLen / 8;
+
+ if ((n * 8) != inLen)
+ {
+ throw new DataLengthException("wrap data must be a multiple of 8 bytes");
+ }
+
+ byte[] block = new byte[inLen + iv.length];
+ byte[] buf = new byte[8 + iv.length];
+
+ System.arraycopy(iv, 0, block, 0, iv.length);
+ System.arraycopy(in, inOff, block, iv.length, inLen);
+
+ engine.init(true, param);
+
+ for (int j = 0; j != 6; j++)
+ {
+ for (int i = 1; i <= n; i++)
+ {
+ System.arraycopy(block, 0, buf, 0, iv.length);
+ System.arraycopy(block, 8 * i, buf, iv.length, 8);
+ engine.processBlock(buf, 0, buf, 0);
+
+ int t = n * j + i;
+ for (int k = 1; t != 0; k++)
+ {
+ byte v = (byte)t;
+
+ buf[iv.length - k] ^= v;
+
+ t >>>= 8;
+ }
+
+ System.arraycopy(buf, 0, block, 0, 8);
+ System.arraycopy(buf, 8, block, 8 * i, 8);
+ }
+ }
+
+ return block;
+ }
+
+ public byte[] unwrap(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ if (forWrapping)
+ {
+ throw new IllegalStateException("not set for unwrapping");
+ }
+
+ int n = inLen / 8;
+
+ if ((n * 8) != inLen)
+ {
+ throw new InvalidCipherTextException("unwrap data must be a multiple of 8 bytes");
+ }
+
+ byte[] block = new byte[inLen - iv.length];
+ byte[] a = new byte[iv.length];
+ byte[] buf = new byte[8 + 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);
+
+ n = n - 1;
+
+ for (int j = 5; j >= 0; j--)
+ {
+ for (int i = n; i >= 1; i--)
+ {
+ System.arraycopy(a, 0, buf, 0, iv.length);
+ System.arraycopy(block, 8 * (i - 1), buf, iv.length, 8);
+
+ int t = n * j + i;
+ for (int k = 1; t != 0; k++)
+ {
+ byte v = (byte)t;
+
+ buf[iv.length - k] ^= v;
+
+ t >>>= 8;
+ }
+
+ engine.processBlock(buf, 0, buf, 0);
+ System.arraycopy(buf, 0, a, 0, 8);
+ System.arraycopy(buf, 8, block, 8 * (i - 1), 8);
+ }
+ }
+
+ if (!Arrays.constantTimeAreEqual(a, iv))
+ {
+ throw new InvalidCipherTextException("checksum failed");
+ }
+
+ return block;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/RFC5649WrapEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/RFC5649WrapEngine.java
new file mode 100644
index 00000000..59cd7732
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/RFC5649WrapEngine.java
@@ -0,0 +1,294 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.Wrapper;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Pack;
+
+/**
+ * An implementation of the AES Key Wrap with Padding specification
+ * as described in RFC 5649.
+ * <p>
+ * For details on the specification see:
+ * <a href="https://tools.ietf.org/html/rfc5649">https://tools.ietf.org/html/rfc5649</a>
+ * </p>
+ */
+public class RFC5649WrapEngine
+ implements Wrapper
+{
+ private BlockCipher engine;
+ private KeyParameter param;
+ private boolean forWrapping;
+
+ // The AIV as defined in the RFC
+ private byte[] highOrderIV = {(byte)0xa6, (byte)0x59, (byte)0x59, (byte)0xa6};
+ private byte[] preIV = highOrderIV;
+
+ private byte[] extractedAIV = null;
+
+ public RFC5649WrapEngine(BlockCipher engine)
+ {
+ this.engine = engine;
+ }
+
+ public void init(boolean forWrapping, CipherParameters param)
+ {
+ this.forWrapping = forWrapping;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ param = ((ParametersWithRandom)param).getParameters();
+ }
+
+ if (param instanceof KeyParameter)
+ {
+ this.param = (KeyParameter)param;
+ }
+ else if (param instanceof ParametersWithIV)
+ {
+ this.preIV = ((ParametersWithIV)param).getIV();
+ this.param = (KeyParameter)((ParametersWithIV)param).getParameters();
+ if (this.preIV.length != 4)
+ {
+ throw new IllegalArgumentException("IV length not equal to 4");
+ }
+ }
+ }
+
+ public String getAlgorithmName()
+ {
+ return engine.getAlgorithmName();
+ }
+
+ /**
+ * Pads the plaintext (i.e., the key to be wrapped)
+ * as per section 4.1 of RFC 5649.
+ *
+ * @param plaintext The key being wrapped.
+ * @return The padded key.
+ */
+ private byte[] padPlaintext(byte[] plaintext)
+ {
+ int plaintextLength = plaintext.length;
+ int numOfZerosToAppend = (8 - (plaintextLength % 8)) % 8;
+ byte[] paddedPlaintext = new byte[plaintextLength + numOfZerosToAppend];
+ System.arraycopy(plaintext, 0, paddedPlaintext, 0, plaintextLength);
+ if (numOfZerosToAppend != 0)
+ {
+ // plaintext (i.e., key to be wrapped) does not have
+ // a multiple of 8 octet blocks so it must be padded
+ byte[] zeros = new byte[numOfZerosToAppend];
+ System.arraycopy(zeros, 0, paddedPlaintext, plaintextLength, numOfZerosToAppend);
+ }
+ return paddedPlaintext;
+ }
+
+ public byte[] wrap(byte[] in, int inOff, int inLen)
+ {
+ if (!forWrapping)
+ {
+ throw new IllegalStateException("not set for wrapping");
+ }
+ byte[] iv = new byte[8];
+
+ // MLI = size of key to be wrapped
+ byte[] mli = Pack.intToBigEndian(inLen);
+ // copy in the fixed portion of the AIV
+ System.arraycopy(preIV, 0, iv, 0, preIV.length);
+ // copy in the MLI after the AIV
+ System.arraycopy(mli, 0, iv, preIV.length, mli.length);
+
+ // get the relevant plaintext to be wrapped
+ byte[] relevantPlaintext = new byte[inLen];
+ System.arraycopy(in, inOff, relevantPlaintext, 0, inLen);
+ byte[] paddedPlaintext = padPlaintext(relevantPlaintext);
+
+ if (paddedPlaintext.length == 8)
+ {
+ // if the padded plaintext contains exactly 8 octets,
+ // then prepend iv and encrypt using AES in ECB mode.
+
+ // prepend the IV to the plaintext
+ byte[] paddedPlainTextWithIV = new byte[paddedPlaintext.length + iv.length];
+ System.arraycopy(iv, 0, paddedPlainTextWithIV, 0, iv.length);
+ System.arraycopy(paddedPlaintext, 0, paddedPlainTextWithIV, iv.length, paddedPlaintext.length);
+
+ engine.init(true, param);
+ for (int i = 0; i < paddedPlainTextWithIV.length; i += engine.getBlockSize())
+ {
+ engine.processBlock(paddedPlainTextWithIV, i, paddedPlainTextWithIV, i);
+ }
+
+ return paddedPlainTextWithIV;
+ }
+ else
+ {
+ // otherwise, apply the RFC 3394 wrap to
+ // the padded plaintext with the new IV
+ Wrapper wrapper = new RFC3394WrapEngine(engine);
+ ParametersWithIV paramsWithIV = new ParametersWithIV(param, iv);
+ wrapper.init(true, paramsWithIV);
+ return wrapper.wrap(paddedPlaintext, inOff, paddedPlaintext.length);
+ }
+
+ }
+
+ public byte[] unwrap(byte[] in, int inOff, int inLen)
+ throws InvalidCipherTextException
+ {
+ if (forWrapping)
+ {
+ throw new IllegalStateException("not set for unwrapping");
+ }
+
+ int n = inLen / 8;
+
+ if ((n * 8) != inLen)
+ {
+ throw new InvalidCipherTextException("unwrap data must be a multiple of 8 bytes");
+ }
+
+ if (n == 1)
+ {
+ throw new InvalidCipherTextException("unwrap data must be at least 16 bytes");
+ }
+
+ byte[] relevantCiphertext = new byte[inLen];
+ System.arraycopy(in, inOff, relevantCiphertext, 0, inLen);
+ byte[] decrypted = new byte[inLen];
+ byte[] paddedPlaintext;
+
+ if (n == 2)
+ {
+ // When there are exactly two 64-bit blocks of ciphertext,
+ // they are decrypted as a single block using AES in ECB.
+ engine.init(false, param);
+ for (int i = 0; i < relevantCiphertext.length; i += engine.getBlockSize())
+ {
+ engine.processBlock(relevantCiphertext, i, decrypted, i);
+ }
+
+ // extract the AIV
+ extractedAIV = new byte[8];
+ System.arraycopy(decrypted, 0, extractedAIV, 0, extractedAIV.length);
+ paddedPlaintext = new byte[decrypted.length - extractedAIV.length];
+ System.arraycopy(decrypted, extractedAIV.length, paddedPlaintext, 0, paddedPlaintext.length);
+ }
+ else
+ {
+ // Otherwise, unwrap as per RFC 3394 but don't check IV the same way
+ decrypted = rfc3394UnwrapNoIvCheck(in, inOff, inLen);
+ paddedPlaintext = decrypted;
+ }
+
+ // Decompose the extracted AIV to the fixed portion and the MLI
+ byte[] extractedHighOrderAIV = new byte[4];
+ byte[] mliBytes = new byte[4];
+ System.arraycopy(extractedAIV, 0, extractedHighOrderAIV, 0, extractedHighOrderAIV.length);
+ System.arraycopy(extractedAIV, extractedHighOrderAIV.length, mliBytes, 0, mliBytes.length);
+ int mli = Pack.bigEndianToInt(mliBytes, 0);
+
+ // Even if a check fails we still continue and check everything
+ // else in order to avoid certain timing based side-channel attacks.
+ boolean isValid = true;
+
+ // Check the fixed portion of the AIV
+ if (!Arrays.constantTimeAreEqual(extractedHighOrderAIV, preIV))
+ {
+ isValid = false;
+ }
+
+ // Check the MLI against the actual length
+ int upperBound = paddedPlaintext.length;
+ int lowerBound = upperBound - 8;
+ if (mli <= lowerBound)
+ {
+ isValid = false;
+ }
+ if (mli > upperBound)
+ {
+ isValid = false;
+ }
+
+ // Check the number of padded zeros
+ int expectedZeros = upperBound - mli;
+ byte[] zeros = new byte[expectedZeros];
+ byte[] pad = new byte[expectedZeros];
+ System.arraycopy(paddedPlaintext, paddedPlaintext.length - expectedZeros, pad, 0, expectedZeros);
+ if (!Arrays.constantTimeAreEqual(pad, zeros))
+ {
+ isValid = false;
+ }
+
+ // Extract the plaintext from the padded plaintext
+ byte[] plaintext = new byte[mli];
+ System.arraycopy(paddedPlaintext, 0, plaintext, 0, plaintext.length);
+
+ if (!isValid)
+ {
+ throw new InvalidCipherTextException("checksum failed");
+ }
+
+ return plaintext;
+ }
+
+ /**
+ * Performs steps 1 and 2 of the unwrap process defined in RFC 3394.
+ * This code is duplicated from RFC3394WrapEngine because that class
+ * will throw an error during unwrap because the IV won't match up.
+ *
+ * @param in
+ * @param inOff
+ * @param inLen
+ * @return Unwrapped data.
+ */
+ private byte[] rfc3394UnwrapNoIvCheck(byte[] in, int inOff, int inLen)
+ {
+ byte[] iv = new byte[8];
+ byte[] block = new byte[inLen - iv.length];
+ byte[] a = new byte[iv.length];
+ byte[] buf = new byte[8 + 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);
+
+ int n = inLen / 8;
+ n = n - 1;
+
+ for (int j = 5; j >= 0; j--)
+ {
+ for (int i = n; i >= 1; i--)
+ {
+ System.arraycopy(a, 0, buf, 0, iv.length);
+ System.arraycopy(block, 8 * (i - 1), buf, iv.length, 8);
+
+ int t = n * j + i;
+ for (int k = 1; t != 0; k++)
+ {
+ byte v = (byte)t;
+
+ buf[iv.length - k] ^= v;
+
+ t >>>= 8;
+ }
+
+ engine.processBlock(buf, 0, buf, 0);
+ System.arraycopy(buf, 0, a, 0, 8);
+ System.arraycopy(buf, 8, block, 8 * (i - 1), 8);
+ }
+ }
+
+ // set the extracted AIV
+ extractedAIV = a;
+
+ return block;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/RSABlindedEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/RSABlindedEngine.java
new file mode 100644
index 00000000..d254f1c6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/RSABlindedEngine.java
@@ -0,0 +1,126 @@
+package org.spongycastle.crypto.engines;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+import org.spongycastle.crypto.params.RSAPrivateCrtKeyParameters;
+import org.spongycastle.util.BigIntegers;
+
+/**
+ * this does your basic RSA algorithm with blinding
+ */
+public class RSABlindedEngine
+ implements AsymmetricBlockCipher
+{
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ private RSACoreEngine core = new RSACoreEngine();
+ private RSAKeyParameters key;
+ private SecureRandom random;
+
+ /**
+ * initialise the RSA engine.
+ *
+ * @param forEncryption true if we are encrypting, false otherwise.
+ * @param param the necessary RSA key parameters.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters param)
+ {
+ core.init(forEncryption, param);
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ key = (RSAKeyParameters)rParam.getParameters();
+ random = rParam.getRandom();
+ }
+ else
+ {
+ key = (RSAKeyParameters)param;
+ random = new SecureRandom();
+ }
+ }
+
+ /**
+ * Return the maximum size for an input block to this engine.
+ * For RSA this is always one byte less than the key size on
+ * encryption, and the same length as the key size on decryption.
+ *
+ * @return maximum size for an input block.
+ */
+ public int getInputBlockSize()
+ {
+ return core.getInputBlockSize();
+ }
+
+ /**
+ * Return the maximum size for an output block to this engine.
+ * For RSA this is always one byte less than the key size on
+ * decryption, and the same length as the key size on encryption.
+ *
+ * @return maximum size for an output block.
+ */
+ public int getOutputBlockSize()
+ {
+ return core.getOutputBlockSize();
+ }
+
+ /**
+ * Process a single block using the basic RSA algorithm.
+ *
+ * @param in the input array.
+ * @param inOff the offset into the input buffer where the data starts.
+ * @param inLen the length of the data to be processed.
+ * @return the result of the RSA process.
+ * @exception DataLengthException the input block is too large.
+ */
+ public byte[] processBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ {
+ if (key == null)
+ {
+ throw new IllegalStateException("RSA engine not initialised");
+ }
+
+ BigInteger input = core.convertInput(in, inOff, inLen);
+
+ BigInteger result;
+ if (key instanceof RSAPrivateCrtKeyParameters)
+ {
+ RSAPrivateCrtKeyParameters k = (RSAPrivateCrtKeyParameters)key;
+
+ BigInteger e = k.getPublicExponent();
+ if (e != null) // can't do blinding without a public exponent
+ {
+ BigInteger m = k.getModulus();
+ BigInteger r = BigIntegers.createRandomInRange(ONE, m.subtract(ONE), random);
+
+ BigInteger blindedInput = r.modPow(e, m).multiply(input).mod(m);
+ BigInteger blindedResult = core.processBlock(blindedInput);
+
+ BigInteger rInv = r.modInverse(m);
+ result = blindedResult.multiply(rInv).mod(m);
+ }
+ else
+ {
+ result = core.processBlock(input);
+ }
+ }
+ else
+ {
+ result = core.processBlock(input);
+ }
+
+ return core.convertOutput(result);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/RSABlindingEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/RSABlindingEngine.java
new file mode 100644
index 00000000..1888916e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/RSABlindingEngine.java
@@ -0,0 +1,137 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.params.RSABlindingParameters;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+
+import java.math.BigInteger;
+
+/**
+ * This does your basic RSA Chaum's blinding and unblinding as outlined in
+ * "Handbook of Applied Cryptography", page 475. You need to use this if you are
+ * trying to get another party to generate signatures without them being aware
+ * of the message they are signing.
+ */
+public class RSABlindingEngine
+ implements AsymmetricBlockCipher
+{
+ private RSACoreEngine core = new RSACoreEngine();
+
+ private RSAKeyParameters key;
+ private BigInteger blindingFactor;
+
+ private boolean forEncryption;
+
+ /**
+ * Initialise the blinding engine.
+ *
+ * @param forEncryption true if we are encrypting (blinding), false otherwise.
+ * @param param the necessary RSA key parameters.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters param)
+ {
+ RSABlindingParameters p;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ p = (RSABlindingParameters)rParam.getParameters();
+ }
+ else
+ {
+ p = (RSABlindingParameters)param;
+ }
+
+ core.init(forEncryption, p.getPublicKey());
+
+ this.forEncryption = forEncryption;
+ this.key = p.getPublicKey();
+ this.blindingFactor = p.getBlindingFactor();
+ }
+
+ /**
+ * Return the maximum size for an input block to this engine.
+ * For RSA this is always one byte less than the key size on
+ * encryption, and the same length as the key size on decryption.
+ *
+ * @return maximum size for an input block.
+ */
+ public int getInputBlockSize()
+ {
+ return core.getInputBlockSize();
+ }
+
+ /**
+ * Return the maximum size for an output block to this engine.
+ * For RSA this is always one byte less than the key size on
+ * decryption, and the same length as the key size on encryption.
+ *
+ * @return maximum size for an output block.
+ */
+ public int getOutputBlockSize()
+ {
+ return core.getOutputBlockSize();
+ }
+
+ /**
+ * Process a single block using the RSA blinding algorithm.
+ *
+ * @param in the input array.
+ * @param inOff the offset into the input buffer where the data starts.
+ * @param inLen the length of the data to be processed.
+ * @return the result of the RSA process.
+ * @throws DataLengthException the input block is too large.
+ */
+ public byte[] processBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ {
+ BigInteger msg = core.convertInput(in, inOff, inLen);
+
+ if (forEncryption)
+ {
+ msg = blindMessage(msg);
+ }
+ else
+ {
+ msg = unblindMessage(msg);
+ }
+
+ return core.convertOutput(msg);
+ }
+
+ /*
+ * Blind message with the blind factor.
+ */
+ private BigInteger blindMessage(
+ BigInteger msg)
+ {
+ BigInteger blindMsg = blindingFactor;
+ blindMsg = msg.multiply(blindMsg.modPow(key.getExponent(), key.getModulus()));
+ blindMsg = blindMsg.mod(key.getModulus());
+
+ return blindMsg;
+ }
+
+ /*
+ * Unblind the message blinded with the blind factor.
+ */
+ private BigInteger unblindMessage(
+ BigInteger blindedMsg)
+ {
+ BigInteger m = key.getModulus();
+ BigInteger msg = blindedMsg;
+ BigInteger blindFactorInverse = blindingFactor.modInverse(m);
+ msg = msg.multiply(blindFactorInverse);
+ msg = msg.mod(m);
+
+ return msg;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/RSACoreEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/RSACoreEngine.java
new file mode 100644
index 00000000..4a98bbda
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/RSACoreEngine.java
@@ -0,0 +1,203 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+import org.spongycastle.crypto.params.RSAPrivateCrtKeyParameters;
+
+import java.math.BigInteger;
+
+/**
+ * this does your basic RSA algorithm.
+ */
+class RSACoreEngine
+{
+ private RSAKeyParameters key;
+ private boolean forEncryption;
+
+ /**
+ * initialise the RSA engine.
+ *
+ * @param forEncryption true if we are encrypting, false otherwise.
+ * @param param the necessary RSA key parameters.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters param)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ key = (RSAKeyParameters)rParam.getParameters();
+ }
+ else
+ {
+ key = (RSAKeyParameters)param;
+ }
+
+ this.forEncryption = forEncryption;
+ }
+
+ /**
+ * Return the maximum size for an input block to this engine.
+ * For RSA this is always one byte less than the key size on
+ * encryption, and the same length as the key size on decryption.
+ *
+ * @return maximum size for an input block.
+ */
+ public int getInputBlockSize()
+ {
+ int bitSize = key.getModulus().bitLength();
+
+ if (forEncryption)
+ {
+ return (bitSize + 7) / 8 - 1;
+ }
+ else
+ {
+ return (bitSize + 7) / 8;
+ }
+ }
+
+ /**
+ * Return the maximum size for an output block to this engine.
+ * For RSA this is always one byte less than the key size on
+ * decryption, and the same length as the key size on encryption.
+ *
+ * @return maximum size for an output block.
+ */
+ public int getOutputBlockSize()
+ {
+ int bitSize = key.getModulus().bitLength();
+
+ if (forEncryption)
+ {
+ return (bitSize + 7) / 8;
+ }
+ else
+ {
+ return (bitSize + 7) / 8 - 1;
+ }
+ }
+
+ public BigInteger convertInput(
+ byte[] in,
+ int inOff,
+ int inLen)
+ {
+ if (inLen > (getInputBlockSize() + 1))
+ {
+ throw new DataLengthException("input too large for RSA cipher.");
+ }
+ else if (inLen == (getInputBlockSize() + 1) && !forEncryption)
+ {
+ throw new DataLengthException("input too large for RSA cipher.");
+ }
+
+ byte[] block;
+
+ if (inOff != 0 || inLen != in.length)
+ {
+ block = new byte[inLen];
+
+ System.arraycopy(in, inOff, block, 0, inLen);
+ }
+ else
+ {
+ block = in;
+ }
+
+ BigInteger res = new BigInteger(1, block);
+ if (res.compareTo(key.getModulus()) >= 0)
+ {
+ throw new DataLengthException("input too large for RSA cipher.");
+ }
+
+ return res;
+ }
+
+ public byte[] convertOutput(
+ BigInteger result)
+ {
+ byte[] output = result.toByteArray();
+
+ if (forEncryption)
+ {
+ if (output[0] == 0 && output.length > getOutputBlockSize()) // have ended up with an extra zero byte, copy down.
+ {
+ byte[] tmp = new byte[output.length - 1];
+
+ System.arraycopy(output, 1, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+
+ if (output.length < getOutputBlockSize()) // have ended up with less bytes than normal, lengthen
+ {
+ byte[] tmp = new byte[getOutputBlockSize()];
+
+ System.arraycopy(output, 0, tmp, tmp.length - output.length, output.length);
+
+ return tmp;
+ }
+ }
+ else
+ {
+ if (output[0] == 0) // have ended up with an extra zero byte, copy down.
+ {
+ byte[] tmp = new byte[output.length - 1];
+
+ System.arraycopy(output, 1, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+ }
+
+ return output;
+ }
+
+ public BigInteger processBlock(BigInteger input)
+ {
+ if (key instanceof RSAPrivateCrtKeyParameters)
+ {
+ //
+ // we have the extra factors, use the Chinese Remainder Theorem - the author
+ // wishes to express his thanks to Dirk Bonekaemper at rtsffm.com for
+ // advice regarding the expression of this.
+ //
+ RSAPrivateCrtKeyParameters crtKey = (RSAPrivateCrtKeyParameters)key;
+
+ BigInteger p = crtKey.getP();
+ BigInteger q = crtKey.getQ();
+ BigInteger dP = crtKey.getDP();
+ BigInteger dQ = crtKey.getDQ();
+ BigInteger qInv = crtKey.getQInv();
+
+ BigInteger mP, mQ, h, m;
+
+ // mP = ((input mod p) ^ dP)) mod p
+ mP = (input.remainder(p)).modPow(dP, p);
+
+ // mQ = ((input mod q) ^ dQ)) mod q
+ mQ = (input.remainder(q)).modPow(dQ, q);
+
+ // h = qInv * (mP - mQ) mod p
+ h = mP.subtract(mQ);
+ h = h.multiply(qInv);
+ h = h.mod(p); // mod (in Java) returns the positive residual
+
+ // m = h * q + mQ
+ m = h.multiply(q);
+ m = m.add(mQ);
+
+ return m;
+ }
+ else
+ {
+ return input.modPow(
+ key.getExponent(), key.getModulus());
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/RSAEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/RSAEngine.java
new file mode 100644
index 00000000..5ffe2ace
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/RSAEngine.java
@@ -0,0 +1,78 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+
+/**
+ * this does your basic RSA algorithm.
+ */
+public class RSAEngine
+ implements AsymmetricBlockCipher
+{
+ private RSACoreEngine core;
+
+ /**
+ * initialise the RSA engine.
+ *
+ * @param forEncryption true if we are encrypting, false otherwise.
+ * @param param the necessary RSA key parameters.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters param)
+ {
+ if (core == null)
+ {
+ core = new RSACoreEngine();
+ }
+
+ core.init(forEncryption, param);
+ }
+
+ /**
+ * Return the maximum size for an input block to this engine.
+ * For RSA this is always one byte less than the key size on
+ * encryption, and the same length as the key size on decryption.
+ *
+ * @return maximum size for an input block.
+ */
+ public int getInputBlockSize()
+ {
+ return core.getInputBlockSize();
+ }
+
+ /**
+ * Return the maximum size for an output block to this engine.
+ * For RSA this is always one byte less than the key size on
+ * decryption, and the same length as the key size on encryption.
+ *
+ * @return maximum size for an output block.
+ */
+ public int getOutputBlockSize()
+ {
+ return core.getOutputBlockSize();
+ }
+
+ /**
+ * Process a single block using the basic RSA algorithm.
+ *
+ * @param in the input array.
+ * @param inOff the offset into the input buffer where the data starts.
+ * @param inLen the length of the data to be processed.
+ * @return the result of the RSA process.
+ * @exception DataLengthException the input block is too large.
+ */
+ public byte[] processBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ {
+ if (core == null)
+ {
+ throw new IllegalStateException("RSA engine not initialised");
+ }
+
+ return core.convertOutput(core.processBlock(core.convertInput(in, inOff, inLen)));
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/RijndaelEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/RijndaelEngine.java
new file mode 100644
index 00000000..b38c7114
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/RijndaelEngine.java
@@ -0,0 +1,725 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+
+/**
+ * an implementation of Rijndael, based on the documentation and reference implementation
+ * by Paulo Barreto, Vincent Rijmen, for v2.0 August '99.
+ * <p>
+ * Note: this implementation is based on information prior to final NIST publication.
+ */
+public class RijndaelEngine
+ implements BlockCipher
+{
+ private static final int MAXROUNDS = 14;
+
+ private static final int MAXKC = (256/4);
+
+ private static final byte[] logtable = {
+ (byte)0, (byte)0, (byte)25, (byte)1, (byte)50, (byte)2, (byte)26, (byte)198,
+ (byte)75, (byte)199, (byte)27, (byte)104, (byte)51, (byte)238, (byte)223, (byte)3,
+ (byte)100, (byte)4, (byte)224, (byte)14, (byte)52, (byte)141, (byte)129, (byte)239,
+ (byte)76, (byte)113, (byte)8, (byte)200, (byte)248, (byte)105, (byte)28, (byte)193,
+ (byte)125, (byte)194, (byte)29, (byte)181, (byte)249, (byte)185, (byte)39, (byte)106,
+ (byte)77, (byte)228, (byte)166, (byte)114, (byte)154, (byte)201, (byte)9, (byte)120,
+ (byte)101, (byte)47, (byte)138, (byte)5, (byte)33, (byte)15, (byte)225, (byte)36,
+ (byte)18, (byte)240, (byte)130, (byte)69, (byte)53, (byte)147, (byte)218, (byte)142,
+ (byte)150, (byte)143, (byte)219, (byte)189, (byte)54, (byte)208, (byte)206, (byte)148,
+ (byte)19, (byte)92, (byte)210, (byte)241, (byte)64, (byte)70, (byte)131, (byte)56,
+ (byte)102, (byte)221, (byte)253, (byte)48, (byte)191, (byte)6, (byte)139, (byte)98,
+ (byte)179, (byte)37, (byte)226, (byte)152, (byte)34, (byte)136, (byte)145, (byte)16,
+ (byte)126, (byte)110, (byte)72, (byte)195, (byte)163, (byte)182, (byte)30, (byte)66,
+ (byte)58, (byte)107, (byte)40, (byte)84, (byte)250, (byte)133, (byte)61, (byte)186,
+ (byte)43, (byte)121, (byte)10, (byte)21, (byte)155, (byte)159, (byte)94, (byte)202,
+ (byte)78, (byte)212, (byte)172, (byte)229, (byte)243, (byte)115, (byte)167, (byte)87,
+ (byte)175, (byte)88, (byte)168, (byte)80, (byte)244, (byte)234, (byte)214, (byte)116,
+ (byte)79, (byte)174, (byte)233, (byte)213, (byte)231, (byte)230, (byte)173, (byte)232,
+ (byte)44, (byte)215, (byte)117, (byte)122, (byte)235, (byte)22, (byte)11, (byte)245,
+ (byte)89, (byte)203, (byte)95, (byte)176, (byte)156, (byte)169, (byte)81, (byte)160,
+ (byte)127, (byte)12, (byte)246, (byte)111, (byte)23, (byte)196, (byte)73, (byte)236,
+ (byte)216, (byte)67, (byte)31, (byte)45, (byte)164, (byte)118, (byte)123, (byte)183,
+ (byte)204, (byte)187, (byte)62, (byte)90, (byte)251, (byte)96, (byte)177, (byte)134,
+ (byte)59, (byte)82, (byte)161, (byte)108, (byte)170, (byte)85, (byte)41, (byte)157,
+ (byte)151, (byte)178, (byte)135, (byte)144, (byte)97, (byte)190, (byte)220, (byte)252,
+ (byte)188, (byte)149, (byte)207, (byte)205, (byte)55, (byte)63, (byte)91, (byte)209,
+ (byte)83, (byte)57, (byte)132, (byte)60, (byte)65, (byte)162, (byte)109, (byte)71,
+ (byte)20, (byte)42, (byte)158, (byte)93, (byte)86, (byte)242, (byte)211, (byte)171,
+ (byte)68, (byte)17, (byte)146, (byte)217, (byte)35, (byte)32, (byte)46, (byte)137,
+ (byte)180, (byte)124, (byte)184, (byte)38, (byte)119, (byte)153, (byte)227, (byte)165,
+ (byte)103, (byte)74, (byte)237, (byte)222, (byte)197, (byte)49, (byte)254, (byte)24,
+ (byte)13, (byte)99, (byte)140, (byte)128, (byte)192, (byte)247, (byte)112, (byte)7
+ };
+
+ private static final byte[] aLogtable = {
+ (byte)0, (byte)3, (byte)5, (byte)15, (byte)17, (byte)51, (byte)85, (byte)255, (byte)26, (byte)46, (byte)114, (byte)150, (byte)161, (byte)248, (byte)19, (byte)53,
+ (byte)95, (byte)225, (byte)56, (byte)72, (byte)216, (byte)115, (byte)149, (byte)164, (byte)247, (byte)2, (byte)6, (byte)10, (byte)30, (byte)34, (byte)102, (byte)170,
+ (byte)229, (byte)52, (byte)92, (byte)228, (byte)55, (byte)89, (byte)235, (byte)38, (byte)106, (byte)190, (byte)217, (byte)112, (byte)144, (byte)171, (byte)230, (byte)49,
+ (byte)83, (byte)245, (byte)4, (byte)12, (byte)20, (byte)60, (byte)68, (byte)204, (byte)79, (byte)209, (byte)104, (byte)184, (byte)211, (byte)110, (byte)178, (byte)205,
+ (byte)76, (byte)212, (byte)103, (byte)169, (byte)224, (byte)59, (byte)77, (byte)215, (byte)98, (byte)166, (byte)241, (byte)8, (byte)24, (byte)40, (byte)120, (byte)136,
+ (byte)131, (byte)158, (byte)185, (byte)208, (byte)107, (byte)189, (byte)220, (byte)127, (byte)129, (byte)152, (byte)179, (byte)206, (byte)73, (byte)219, (byte)118, (byte)154,
+ (byte)181, (byte)196, (byte)87, (byte)249, (byte)16, (byte)48, (byte)80, (byte)240, (byte)11, (byte)29, (byte)39, (byte)105, (byte)187, (byte)214, (byte)97, (byte)163,
+ (byte)254, (byte)25, (byte)43, (byte)125, (byte)135, (byte)146, (byte)173, (byte)236, (byte)47, (byte)113, (byte)147, (byte)174, (byte)233, (byte)32, (byte)96, (byte)160,
+ (byte)251, (byte)22, (byte)58, (byte)78, (byte)210, (byte)109, (byte)183, (byte)194, (byte)93, (byte)231, (byte)50, (byte)86, (byte)250, (byte)21, (byte)63, (byte)65,
+ (byte)195, (byte)94, (byte)226, (byte)61, (byte)71, (byte)201, (byte)64, (byte)192, (byte)91, (byte)237, (byte)44, (byte)116, (byte)156, (byte)191, (byte)218, (byte)117,
+ (byte)159, (byte)186, (byte)213, (byte)100, (byte)172, (byte)239, (byte)42, (byte)126, (byte)130, (byte)157, (byte)188, (byte)223, (byte)122, (byte)142, (byte)137, (byte)128,
+ (byte)155, (byte)182, (byte)193, (byte)88, (byte)232, (byte)35, (byte)101, (byte)175, (byte)234, (byte)37, (byte)111, (byte)177, (byte)200, (byte)67, (byte)197, (byte)84,
+ (byte)252, (byte)31, (byte)33, (byte)99, (byte)165, (byte)244, (byte)7, (byte)9, (byte)27, (byte)45, (byte)119, (byte)153, (byte)176, (byte)203, (byte)70, (byte)202,
+ (byte)69, (byte)207, (byte)74, (byte)222, (byte)121, (byte)139, (byte)134, (byte)145, (byte)168, (byte)227, (byte)62, (byte)66, (byte)198, (byte)81, (byte)243, (byte)14,
+ (byte)18, (byte)54, (byte)90, (byte)238, (byte)41, (byte)123, (byte)141, (byte)140, (byte)143, (byte)138, (byte)133, (byte)148, (byte)167, (byte)242, (byte)13, (byte)23,
+ (byte)57, (byte)75, (byte)221, (byte)124, (byte)132, (byte)151, (byte)162, (byte)253, (byte)28, (byte)36, (byte)108, (byte)180, (byte)199, (byte)82, (byte)246, (byte)1,
+ (byte)3, (byte)5, (byte)15, (byte)17, (byte)51, (byte)85, (byte)255, (byte)26, (byte)46, (byte)114, (byte)150, (byte)161, (byte)248, (byte)19, (byte)53,
+ (byte)95, (byte)225, (byte)56, (byte)72, (byte)216, (byte)115, (byte)149, (byte)164, (byte)247, (byte)2, (byte)6, (byte)10, (byte)30, (byte)34, (byte)102, (byte)170,
+ (byte)229, (byte)52, (byte)92, (byte)228, (byte)55, (byte)89, (byte)235, (byte)38, (byte)106, (byte)190, (byte)217, (byte)112, (byte)144, (byte)171, (byte)230, (byte)49,
+ (byte)83, (byte)245, (byte)4, (byte)12, (byte)20, (byte)60, (byte)68, (byte)204, (byte)79, (byte)209, (byte)104, (byte)184, (byte)211, (byte)110, (byte)178, (byte)205,
+ (byte)76, (byte)212, (byte)103, (byte)169, (byte)224, (byte)59, (byte)77, (byte)215, (byte)98, (byte)166, (byte)241, (byte)8, (byte)24, (byte)40, (byte)120, (byte)136,
+ (byte)131, (byte)158, (byte)185, (byte)208, (byte)107, (byte)189, (byte)220, (byte)127, (byte)129, (byte)152, (byte)179, (byte)206, (byte)73, (byte)219, (byte)118, (byte)154,
+ (byte)181, (byte)196, (byte)87, (byte)249, (byte)16, (byte)48, (byte)80, (byte)240, (byte)11, (byte)29, (byte)39, (byte)105, (byte)187, (byte)214, (byte)97, (byte)163,
+ (byte)254, (byte)25, (byte)43, (byte)125, (byte)135, (byte)146, (byte)173, (byte)236, (byte)47, (byte)113, (byte)147, (byte)174, (byte)233, (byte)32, (byte)96, (byte)160,
+ (byte)251, (byte)22, (byte)58, (byte)78, (byte)210, (byte)109, (byte)183, (byte)194, (byte)93, (byte)231, (byte)50, (byte)86, (byte)250, (byte)21, (byte)63, (byte)65,
+ (byte)195, (byte)94, (byte)226, (byte)61, (byte)71, (byte)201, (byte)64, (byte)192, (byte)91, (byte)237, (byte)44, (byte)116, (byte)156, (byte)191, (byte)218, (byte)117,
+ (byte)159, (byte)186, (byte)213, (byte)100, (byte)172, (byte)239, (byte)42, (byte)126, (byte)130, (byte)157, (byte)188, (byte)223, (byte)122, (byte)142, (byte)137, (byte)128,
+ (byte)155, (byte)182, (byte)193, (byte)88, (byte)232, (byte)35, (byte)101, (byte)175, (byte)234, (byte)37, (byte)111, (byte)177, (byte)200, (byte)67, (byte)197, (byte)84,
+ (byte)252, (byte)31, (byte)33, (byte)99, (byte)165, (byte)244, (byte)7, (byte)9, (byte)27, (byte)45, (byte)119, (byte)153, (byte)176, (byte)203, (byte)70, (byte)202,
+ (byte)69, (byte)207, (byte)74, (byte)222, (byte)121, (byte)139, (byte)134, (byte)145, (byte)168, (byte)227, (byte)62, (byte)66, (byte)198, (byte)81, (byte)243, (byte)14,
+ (byte)18, (byte)54, (byte)90, (byte)238, (byte)41, (byte)123, (byte)141, (byte)140, (byte)143, (byte)138, (byte)133, (byte)148, (byte)167, (byte)242, (byte)13, (byte)23,
+ (byte)57, (byte)75, (byte)221, (byte)124, (byte)132, (byte)151, (byte)162, (byte)253, (byte)28, (byte)36, (byte)108, (byte)180, (byte)199, (byte)82, (byte)246, (byte)1,
+ };
+
+ private static final byte[] S = {
+ (byte)99, (byte)124, (byte)119, (byte)123, (byte)242, (byte)107, (byte)111, (byte)197, (byte)48, (byte)1, (byte)103, (byte)43, (byte)254, (byte)215, (byte)171, (byte)118,
+ (byte)202, (byte)130, (byte)201, (byte)125, (byte)250, (byte)89, (byte)71, (byte)240, (byte)173, (byte)212, (byte)162, (byte)175, (byte)156, (byte)164, (byte)114, (byte)192,
+ (byte)183, (byte)253, (byte)147, (byte)38, (byte)54, (byte)63, (byte)247, (byte)204, (byte)52, (byte)165, (byte)229, (byte)241, (byte)113, (byte)216, (byte)49, (byte)21,
+ (byte)4, (byte)199, (byte)35, (byte)195, (byte)24, (byte)150, (byte)5, (byte)154, (byte)7, (byte)18, (byte)128, (byte)226, (byte)235, (byte)39, (byte)178, (byte)117,
+ (byte)9, (byte)131, (byte)44, (byte)26, (byte)27, (byte)110, (byte)90, (byte)160, (byte)82, (byte)59, (byte)214, (byte)179, (byte)41, (byte)227, (byte)47, (byte)132,
+ (byte)83, (byte)209, (byte)0, (byte)237, (byte)32, (byte)252, (byte)177, (byte)91, (byte)106, (byte)203, (byte)190, (byte)57, (byte)74, (byte)76, (byte)88, (byte)207,
+ (byte)208, (byte)239, (byte)170, (byte)251, (byte)67, (byte)77, (byte)51, (byte)133, (byte)69, (byte)249, (byte)2, (byte)127, (byte)80, (byte)60, (byte)159, (byte)168,
+ (byte)81, (byte)163, (byte)64, (byte)143, (byte)146, (byte)157, (byte)56, (byte)245, (byte)188, (byte)182, (byte)218, (byte)33, (byte)16, (byte)255, (byte)243, (byte)210,
+ (byte)205, (byte)12, (byte)19, (byte)236, (byte)95, (byte)151, (byte)68, (byte)23, (byte)196, (byte)167, (byte)126, (byte)61, (byte)100, (byte)93, (byte)25, (byte)115,
+ (byte)96, (byte)129, (byte)79, (byte)220, (byte)34, (byte)42, (byte)144, (byte)136, (byte)70, (byte)238, (byte)184, (byte)20, (byte)222, (byte)94, (byte)11, (byte)219,
+ (byte)224, (byte)50, (byte)58, (byte)10, (byte)73, (byte)6, (byte)36, (byte)92, (byte)194, (byte)211, (byte)172, (byte)98, (byte)145, (byte)149, (byte)228, (byte)121,
+ (byte)231, (byte)200, (byte)55, (byte)109, (byte)141, (byte)213, (byte)78, (byte)169, (byte)108, (byte)86, (byte)244, (byte)234, (byte)101, (byte)122, (byte)174, (byte)8,
+ (byte)186, (byte)120, (byte)37, (byte)46, (byte)28, (byte)166, (byte)180, (byte)198, (byte)232, (byte)221, (byte)116, (byte)31, (byte)75, (byte)189, (byte)139, (byte)138,
+ (byte)112, (byte)62, (byte)181, (byte)102, (byte)72, (byte)3, (byte)246, (byte)14, (byte)97, (byte)53, (byte)87, (byte)185, (byte)134, (byte)193, (byte)29, (byte)158,
+ (byte)225, (byte)248, (byte)152, (byte)17, (byte)105, (byte)217, (byte)142, (byte)148, (byte)155, (byte)30, (byte)135, (byte)233, (byte)206, (byte)85, (byte)40, (byte)223,
+ (byte)140, (byte)161, (byte)137, (byte)13, (byte)191, (byte)230, (byte)66, (byte)104, (byte)65, (byte)153, (byte)45, (byte)15, (byte)176, (byte)84, (byte)187, (byte)22,
+ };
+
+ private static final byte[] Si = {
+ (byte)82, (byte)9, (byte)106, (byte)213, (byte)48, (byte)54, (byte)165, (byte)56, (byte)191, (byte)64, (byte)163, (byte)158, (byte)129, (byte)243, (byte)215, (byte)251,
+ (byte)124, (byte)227, (byte)57, (byte)130, (byte)155, (byte)47, (byte)255, (byte)135, (byte)52, (byte)142, (byte)67, (byte)68, (byte)196, (byte)222, (byte)233, (byte)203,
+ (byte)84, (byte)123, (byte)148, (byte)50, (byte)166, (byte)194, (byte)35, (byte)61, (byte)238, (byte)76, (byte)149, (byte)11, (byte)66, (byte)250, (byte)195, (byte)78,
+ (byte)8, (byte)46, (byte)161, (byte)102, (byte)40, (byte)217, (byte)36, (byte)178, (byte)118, (byte)91, (byte)162, (byte)73, (byte)109, (byte)139, (byte)209, (byte)37,
+ (byte)114, (byte)248, (byte)246, (byte)100, (byte)134, (byte)104, (byte)152, (byte)22, (byte)212, (byte)164, (byte)92, (byte)204, (byte)93, (byte)101, (byte)182, (byte)146,
+ (byte)108, (byte)112, (byte)72, (byte)80, (byte)253, (byte)237, (byte)185, (byte)218, (byte)94, (byte)21, (byte)70, (byte)87, (byte)167, (byte)141, (byte)157, (byte)132,
+ (byte)144, (byte)216, (byte)171, (byte)0, (byte)140, (byte)188, (byte)211, (byte)10, (byte)247, (byte)228, (byte)88, (byte)5, (byte)184, (byte)179, (byte)69, (byte)6,
+ (byte)208, (byte)44, (byte)30, (byte)143, (byte)202, (byte)63, (byte)15, (byte)2, (byte)193, (byte)175, (byte)189, (byte)3, (byte)1, (byte)19, (byte)138, (byte)107,
+ (byte)58, (byte)145, (byte)17, (byte)65, (byte)79, (byte)103, (byte)220, (byte)234, (byte)151, (byte)242, (byte)207, (byte)206, (byte)240, (byte)180, (byte)230, (byte)115,
+ (byte)150, (byte)172, (byte)116, (byte)34, (byte)231, (byte)173, (byte)53, (byte)133, (byte)226, (byte)249, (byte)55, (byte)232, (byte)28, (byte)117, (byte)223, (byte)110,
+ (byte)71, (byte)241, (byte)26, (byte)113, (byte)29, (byte)41, (byte)197, (byte)137, (byte)111, (byte)183, (byte)98, (byte)14, (byte)170, (byte)24, (byte)190, (byte)27,
+ (byte)252, (byte)86, (byte)62, (byte)75, (byte)198, (byte)210, (byte)121, (byte)32, (byte)154, (byte)219, (byte)192, (byte)254, (byte)120, (byte)205, (byte)90, (byte)244,
+ (byte)31, (byte)221, (byte)168, (byte)51, (byte)136, (byte)7, (byte)199, (byte)49, (byte)177, (byte)18, (byte)16, (byte)89, (byte)39, (byte)128, (byte)236, (byte)95,
+ (byte)96, (byte)81, (byte)127, (byte)169, (byte)25, (byte)181, (byte)74, (byte)13, (byte)45, (byte)229, (byte)122, (byte)159, (byte)147, (byte)201, (byte)156, (byte)239,
+ (byte)160, (byte)224, (byte)59, (byte)77, (byte)174, (byte)42, (byte)245, (byte)176, (byte)200, (byte)235, (byte)187, (byte)60, (byte)131, (byte)83, (byte)153, (byte)97,
+ (byte)23, (byte)43, (byte)4, (byte)126, (byte)186, (byte)119, (byte)214, (byte)38, (byte)225, (byte)105, (byte)20, (byte)99, (byte)85, (byte)33, (byte)12, (byte)125,
+ };
+
+ private static final int[] rcon = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 };
+
+ static byte[][] shifts0 =
+ {
+ { 0, 8, 16, 24 },
+ { 0, 8, 16, 24 },
+ { 0, 8, 16, 24 },
+ { 0, 8, 16, 32 },
+ { 0, 8, 24, 32 }
+ };
+
+ static byte[][] shifts1 =
+ {
+ { 0, 24, 16, 8 },
+ { 0, 32, 24, 16 },
+ { 0, 40, 32, 24 },
+ { 0, 48, 40, 24 },
+ { 0, 56, 40, 32 }
+ };
+
+ /**
+ * multiply two elements of GF(2^m)
+ * needed for MixColumn and InvMixColumn
+ */
+ private byte mul0x2(
+ int b)
+ {
+ if (b != 0)
+ {
+ return aLogtable[25 + (logtable[b] & 0xff)];
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ private byte mul0x3(
+ int b)
+ {
+ if (b != 0)
+ {
+ return aLogtable[1 + (logtable[b] & 0xff)];
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ private byte mul0x9(
+ int b)
+ {
+ if (b >= 0)
+ {
+ return aLogtable[199 + b];
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ private byte mul0xb(
+ int b)
+ {
+ if (b >= 0)
+ {
+ return aLogtable[104 + b];
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ private byte mul0xd(
+ int b)
+ {
+ if (b >= 0)
+ {
+ return aLogtable[238 + b];
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ private byte mul0xe(
+ int b)
+ {
+ if (b >= 0)
+ {
+ return aLogtable[223 + b];
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ /**
+ * xor corresponding text input and round key input bytes
+ */
+ private void KeyAddition(
+ long[] rk)
+ {
+ A0 ^= rk[0];
+ A1 ^= rk[1];
+ A2 ^= rk[2];
+ A3 ^= rk[3];
+ }
+
+ private long shift(
+ long r,
+ int shift)
+ {
+ return (((r >>> shift) | (r << (BC - shift)))) & BC_MASK;
+ }
+
+ /**
+ * Row 0 remains unchanged
+ * The other three rows are shifted a variable amount
+ */
+ private void ShiftRow(
+ byte[] shiftsSC)
+ {
+ A1 = shift(A1, shiftsSC[1]);
+ A2 = shift(A2, shiftsSC[2]);
+ A3 = shift(A3, shiftsSC[3]);
+ }
+
+ private long applyS(
+ long r,
+ byte[] box)
+ {
+ long res = 0;
+
+ for (int j = 0; j < BC; j += 8)
+ {
+ res |= (long)(box[(int)((r >> j) & 0xff)] & 0xff) << j;
+ }
+
+ return res;
+ }
+
+ /**
+ * Replace every byte of the input by the byte at that place
+ * in the nonlinear S-box
+ */
+ private void Substitution(
+ byte[] box)
+ {
+ A0 = applyS(A0, box);
+ A1 = applyS(A1, box);
+ A2 = applyS(A2, box);
+ A3 = applyS(A3, box);
+ }
+
+ /**
+ * Mix the bytes of every column in a linear way
+ */
+ private void MixColumn()
+ {
+ long r0, r1, r2, r3;
+
+ r0 = r1 = r2 = r3 = 0;
+
+ for (int j = 0; j < BC; j += 8)
+ {
+ int a0 = (int)((A0 >> j) & 0xff);
+ int a1 = (int)((A1 >> j) & 0xff);
+ int a2 = (int)((A2 >> j) & 0xff);
+ int a3 = (int)((A3 >> j) & 0xff);
+
+ r0 |= (long)((mul0x2(a0) ^ mul0x3(a1) ^ a2 ^ a3) & 0xff) << j;
+
+ r1 |= (long)((mul0x2(a1) ^ mul0x3(a2) ^ a3 ^ a0) & 0xff) << j;
+
+ r2 |= (long)((mul0x2(a2) ^ mul0x3(a3) ^ a0 ^ a1) & 0xff) << j;
+
+ r3 |= (long)((mul0x2(a3) ^ mul0x3(a0) ^ a1 ^ a2) & 0xff) << j;
+ }
+
+ A0 = r0;
+ A1 = r1;
+ A2 = r2;
+ A3 = r3;
+ }
+
+ /**
+ * Mix the bytes of every column in a linear way
+ * This is the opposite operation of Mixcolumn
+ */
+ private void InvMixColumn()
+ {
+ long r0, r1, r2, r3;
+
+ r0 = r1 = r2 = r3 = 0;
+ for (int j = 0; j < BC; j += 8)
+ {
+ int a0 = (int)((A0 >> j) & 0xff);
+ int a1 = (int)((A1 >> j) & 0xff);
+ int a2 = (int)((A2 >> j) & 0xff);
+ int a3 = (int)((A3 >> j) & 0xff);
+
+ //
+ // pre-lookup the log table
+ //
+ a0 = (a0 != 0) ? (logtable[a0 & 0xff] & 0xff) : -1;
+ a1 = (a1 != 0) ? (logtable[a1 & 0xff] & 0xff) : -1;
+ a2 = (a2 != 0) ? (logtable[a2 & 0xff] & 0xff) : -1;
+ a3 = (a3 != 0) ? (logtable[a3 & 0xff] & 0xff) : -1;
+
+ r0 |= (long)((mul0xe(a0) ^ mul0xb(a1) ^ mul0xd(a2) ^ mul0x9(a3)) & 0xff) << j;
+
+ r1 |= (long)((mul0xe(a1) ^ mul0xb(a2) ^ mul0xd(a3) ^ mul0x9(a0)) & 0xff) << j;
+
+ r2 |= (long)((mul0xe(a2) ^ mul0xb(a3) ^ mul0xd(a0) ^ mul0x9(a1)) & 0xff) << j;
+
+ r3 |= (long)((mul0xe(a3) ^ mul0xb(a0) ^ mul0xd(a1) ^ mul0x9(a2)) & 0xff) << j;
+ }
+
+ A0 = r0;
+ A1 = r1;
+ A2 = r2;
+ A3 = r3;
+ }
+
+ /**
+ * Calculate the necessary round keys
+ * The number of calculations depends on keyBits and blockBits
+ */
+ private long[][] generateWorkingKey(
+ byte[] key)
+ {
+ int KC;
+ int t, rconpointer = 0;
+ int keyBits = key.length * 8;
+ byte[][] tk = new byte[4][MAXKC];
+ long[][] W = new long[MAXROUNDS+1][4];
+
+ switch (keyBits)
+ {
+ case 128:
+ KC = 4;
+ break;
+ case 160:
+ KC = 5;
+ break;
+ case 192:
+ KC = 6;
+ break;
+ case 224:
+ KC = 7;
+ break;
+ case 256:
+ KC = 8;
+ break;
+ default :
+ throw new IllegalArgumentException("Key length not 128/160/192/224/256 bits.");
+ }
+
+ if (keyBits >= blockBits)
+ {
+ ROUNDS = KC + 6;
+ }
+ else
+ {
+ ROUNDS = (BC / 8) + 6;
+ }
+
+ //
+ // copy the key into the processing area
+ //
+ int index = 0;
+
+ for (int i = 0; i < key.length; i++)
+ {
+ tk[i % 4][i / 4] = key[index++];
+ }
+
+ t = 0;
+
+ //
+ // copy values into round key array
+ //
+ for (int j = 0; (j < KC) && (t < (ROUNDS+1)*(BC / 8)); j++, t++)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ W[t / (BC / 8)][i] |= (long)(tk[i][j] & 0xff) << ((t * 8) % BC);
+ }
+ }
+
+ //
+ // while not enough round key material calculated
+ // calculate new values
+ //
+ while (t < (ROUNDS+1)*(BC/8))
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ tk[i][0] ^= S[tk[(i+1)%4][KC-1] & 0xff];
+ }
+ tk[0][0] ^= rcon[rconpointer++];
+
+ if (KC <= 6)
+ {
+ for (int j = 1; j < KC; j++)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ tk[i][j] ^= tk[i][j-1];
+ }
+ }
+ }
+ else
+ {
+ for (int j = 1; j < 4; j++)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ tk[i][j] ^= tk[i][j-1];
+ }
+ }
+ for (int i = 0; i < 4; i++)
+ {
+ tk[i][4] ^= S[tk[i][3] & 0xff];
+ }
+ for (int j = 5; j < KC; j++)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ tk[i][j] ^= tk[i][j-1];
+ }
+ }
+ }
+
+ //
+ // copy values into round key array
+ //
+ for (int j = 0; (j < KC) && (t < (ROUNDS+1)*(BC/8)); j++, t++)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ W[t / (BC/8)][i] |= (long)(tk[i][j] & 0xff) << ((t * 8) % (BC));
+ }
+ }
+ }
+
+ return W;
+ }
+
+ private int BC;
+ private long BC_MASK;
+ private int ROUNDS;
+ private int blockBits;
+ private long[][] workingKey;
+ private long A0, A1, A2, A3;
+ private boolean forEncryption;
+ private byte[] shifts0SC;
+ private byte[] shifts1SC;
+
+ /**
+ * default constructor - 128 bit block size.
+ */
+ public RijndaelEngine()
+ {
+ this(128);
+ }
+
+ /**
+ * basic constructor - set the cipher up for a given blocksize
+ *
+ * @param blockBits the blocksize in bits, must be 128, 192, or 256.
+ */
+ public RijndaelEngine(
+ int blockBits)
+ {
+ switch (blockBits)
+ {
+ case 128:
+ BC = 32;
+ BC_MASK = 0xffffffffL;
+ shifts0SC = shifts0[0];
+ shifts1SC = shifts1[0];
+ break;
+ case 160:
+ BC = 40;
+ BC_MASK = 0xffffffffffL;
+ shifts0SC = shifts0[1];
+ shifts1SC = shifts1[1];
+ break;
+ case 192:
+ BC = 48;
+ BC_MASK = 0xffffffffffffL;
+ shifts0SC = shifts0[2];
+ shifts1SC = shifts1[2];
+ break;
+ case 224:
+ BC = 56;
+ BC_MASK = 0xffffffffffffffL;
+ shifts0SC = shifts0[3];
+ shifts1SC = shifts1[3];
+ break;
+ case 256:
+ BC = 64;
+ BC_MASK = 0xffffffffffffffffL;
+ shifts0SC = shifts0[4];
+ shifts1SC = shifts1[4];
+ break;
+ default:
+ throw new IllegalArgumentException("unknown blocksize to Rijndael");
+ }
+
+ this.blockBits = blockBits;
+ }
+
+ /**
+ * initialise a Rijndael cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (params instanceof KeyParameter)
+ {
+ workingKey = generateWorkingKey(((KeyParameter)params).getKey());
+ this.forEncryption = forEncryption;
+ return;
+ }
+
+ throw new IllegalArgumentException("invalid parameter passed to Rijndael init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Rijndael";
+ }
+
+ public int getBlockSize()
+ {
+ return BC / 2;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (workingKey == null)
+ {
+ throw new IllegalStateException("Rijndael engine not initialised");
+ }
+
+ if ((inOff + (BC / 2)) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + (BC / 2)) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ if (forEncryption)
+ {
+ unpackBlock(in, inOff);
+ encryptBlock(workingKey);
+ packBlock(out, outOff);
+ }
+ else
+ {
+ unpackBlock(in, inOff);
+ decryptBlock(workingKey);
+ packBlock(out, outOff);
+ }
+
+ return BC / 2;
+ }
+
+ public void reset()
+ {
+ }
+
+ private void unpackBlock(
+ byte[] bytes,
+ int off)
+ {
+ int index = off;
+
+ A0 = (bytes[index++] & 0xff);
+ A1 = (bytes[index++] & 0xff);
+ A2 = (bytes[index++] & 0xff);
+ A3 = (bytes[index++] & 0xff);
+
+ for (int j = 8; j != BC; j += 8)
+ {
+ A0 |= (long)(bytes[index++] & 0xff) << j;
+ A1 |= (long)(bytes[index++] & 0xff) << j;
+ A2 |= (long)(bytes[index++] & 0xff) << j;
+ A3 |= (long)(bytes[index++] & 0xff) << j;
+ }
+ }
+
+ private void packBlock(
+ byte[] bytes,
+ int off)
+ {
+ int index = off;
+
+ for (int j = 0; j != BC; j += 8)
+ {
+ bytes[index++] = (byte)(A0 >> j);
+ bytes[index++] = (byte)(A1 >> j);
+ bytes[index++] = (byte)(A2 >> j);
+ bytes[index++] = (byte)(A3 >> j);
+ }
+ }
+
+ private void encryptBlock(
+ long[][] rk)
+ {
+ int r;
+
+ //
+ // begin with a key addition
+ //
+ KeyAddition(rk[0]);
+
+ //
+ // ROUNDS-1 ordinary rounds
+ //
+ for (r = 1; r < ROUNDS; r++)
+ {
+ Substitution(S);
+ ShiftRow(shifts0SC);
+ MixColumn();
+ KeyAddition(rk[r]);
+ }
+
+ //
+ // Last round is special: there is no MixColumn
+ //
+ Substitution(S);
+ ShiftRow(shifts0SC);
+ KeyAddition(rk[ROUNDS]);
+ }
+
+ private void decryptBlock(
+ long[][] rk)
+ {
+ int r;
+
+ // To decrypt: apply the inverse operations of the encrypt routine,
+ // in opposite order
+ //
+ // (KeyAddition is an involution: it 's equal to its inverse)
+ // (the inverse of Substitution with table S is Substitution with the inverse table of S)
+ // (the inverse of Shiftrow is Shiftrow over a suitable distance)
+ //
+
+ // First the special round:
+ // without InvMixColumn
+ // with extra KeyAddition
+ //
+ KeyAddition(rk[ROUNDS]);
+ Substitution(Si);
+ ShiftRow(shifts1SC);
+
+ //
+ // ROUNDS-1 ordinary rounds
+ //
+ for (r = ROUNDS-1; r > 0; r--)
+ {
+ KeyAddition(rk[r]);
+ InvMixColumn();
+ Substitution(Si);
+ ShiftRow(shifts1SC);
+ }
+
+ //
+ // End with the extra key addition
+ //
+ KeyAddition(rk[0]);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/SEEDEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/SEEDEngine.java
new file mode 100644
index 00000000..1a376c91
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/SEEDEngine.java
@@ -0,0 +1,346 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+
+/**
+ * Implementation of the SEED algorithm as described in RFC 4009
+ */
+public class SEEDEngine
+ implements BlockCipher
+{
+ private final int BLOCK_SIZE = 16;
+
+ private static final int[] SS0 =
+ {
+ 0x2989a1a8, 0x05858184, 0x16c6d2d4, 0x13c3d3d0, 0x14445054, 0x1d0d111c, 0x2c8ca0ac, 0x25052124,
+ 0x1d4d515c, 0x03434340, 0x18081018, 0x1e0e121c, 0x11415150, 0x3cccf0fc, 0x0acac2c8, 0x23436360,
+ 0x28082028, 0x04444044, 0x20002020, 0x1d8d919c, 0x20c0e0e0, 0x22c2e2e0, 0x08c8c0c8, 0x17071314,
+ 0x2585a1a4, 0x0f8f838c, 0x03030300, 0x3b4b7378, 0x3b8bb3b8, 0x13031310, 0x12c2d2d0, 0x2ecee2ec,
+ 0x30407070, 0x0c8c808c, 0x3f0f333c, 0x2888a0a8, 0x32023230, 0x1dcdd1dc, 0x36c6f2f4, 0x34447074,
+ 0x2ccce0ec, 0x15859194, 0x0b0b0308, 0x17475354, 0x1c4c505c, 0x1b4b5358, 0x3d8db1bc, 0x01010100,
+ 0x24042024, 0x1c0c101c, 0x33437370, 0x18889098, 0x10001010, 0x0cccc0cc, 0x32c2f2f0, 0x19c9d1d8,
+ 0x2c0c202c, 0x27c7e3e4, 0x32427270, 0x03838380, 0x1b8b9398, 0x11c1d1d0, 0x06868284, 0x09c9c1c8,
+ 0x20406060, 0x10405050, 0x2383a3a0, 0x2bcbe3e8, 0x0d0d010c, 0x3686b2b4, 0x1e8e929c, 0x0f4f434c,
+ 0x3787b3b4, 0x1a4a5258, 0x06c6c2c4, 0x38487078, 0x2686a2a4, 0x12021210, 0x2f8fa3ac, 0x15c5d1d4,
+ 0x21416160, 0x03c3c3c0, 0x3484b0b4, 0x01414140, 0x12425250, 0x3d4d717c, 0x0d8d818c, 0x08080008,
+ 0x1f0f131c, 0x19899198, 0x00000000, 0x19091118, 0x04040004, 0x13435350, 0x37c7f3f4, 0x21c1e1e0,
+ 0x3dcdf1fc, 0x36467274, 0x2f0f232c, 0x27072324, 0x3080b0b0, 0x0b8b8388, 0x0e0e020c, 0x2b8ba3a8,
+ 0x2282a2a0, 0x2e4e626c, 0x13839390, 0x0d4d414c, 0x29496168, 0x3c4c707c, 0x09090108, 0x0a0a0208,
+ 0x3f8fb3bc, 0x2fcfe3ec, 0x33c3f3f0, 0x05c5c1c4, 0x07878384, 0x14041014, 0x3ecef2fc, 0x24446064,
+ 0x1eced2dc, 0x2e0e222c, 0x0b4b4348, 0x1a0a1218, 0x06060204, 0x21012120, 0x2b4b6368, 0x26466264,
+ 0x02020200, 0x35c5f1f4, 0x12829290, 0x0a8a8288, 0x0c0c000c, 0x3383b3b0, 0x3e4e727c, 0x10c0d0d0,
+ 0x3a4a7278, 0x07474344, 0x16869294, 0x25c5e1e4, 0x26062224, 0x00808080, 0x2d8da1ac, 0x1fcfd3dc,
+ 0x2181a1a0, 0x30003030, 0x37073334, 0x2e8ea2ac, 0x36063234, 0x15051114, 0x22022220, 0x38083038,
+ 0x34c4f0f4, 0x2787a3a4, 0x05454144, 0x0c4c404c, 0x01818180, 0x29c9e1e8, 0x04848084, 0x17879394,
+ 0x35053134, 0x0bcbc3c8, 0x0ecec2cc, 0x3c0c303c, 0x31417170, 0x11011110, 0x07c7c3c4, 0x09898188,
+ 0x35457174, 0x3bcbf3f8, 0x1acad2d8, 0x38c8f0f8, 0x14849094, 0x19495158, 0x02828280, 0x04c4c0c4,
+ 0x3fcff3fc, 0x09494148, 0x39093138, 0x27476364, 0x00c0c0c0, 0x0fcfc3cc, 0x17c7d3d4, 0x3888b0b8,
+ 0x0f0f030c, 0x0e8e828c, 0x02424240, 0x23032320, 0x11819190, 0x2c4c606c, 0x1bcbd3d8, 0x2484a0a4,
+ 0x34043034, 0x31c1f1f0, 0x08484048, 0x02c2c2c0, 0x2f4f636c, 0x3d0d313c, 0x2d0d212c, 0x00404040,
+ 0x3e8eb2bc, 0x3e0e323c, 0x3c8cb0bc, 0x01c1c1c0, 0x2a8aa2a8, 0x3a8ab2b8, 0x0e4e424c, 0x15455154,
+ 0x3b0b3338, 0x1cccd0dc, 0x28486068, 0x3f4f737c, 0x1c8c909c, 0x18c8d0d8, 0x0a4a4248, 0x16465254,
+ 0x37477374, 0x2080a0a0, 0x2dcde1ec, 0x06464244, 0x3585b1b4, 0x2b0b2328, 0x25456164, 0x3acaf2f8,
+ 0x23c3e3e0, 0x3989b1b8, 0x3181b1b0, 0x1f8f939c, 0x1e4e525c, 0x39c9f1f8, 0x26c6e2e4, 0x3282b2b0,
+ 0x31013130, 0x2acae2e8, 0x2d4d616c, 0x1f4f535c, 0x24c4e0e4, 0x30c0f0f0, 0x0dcdc1cc, 0x08888088,
+ 0x16061214, 0x3a0a3238, 0x18485058, 0x14c4d0d4, 0x22426260, 0x29092128, 0x07070304, 0x33033330,
+ 0x28c8e0e8, 0x1b0b1318, 0x05050104, 0x39497178, 0x10809090, 0x2a4a6268, 0x2a0a2228, 0x1a8a9298
+ };
+
+ private static final int[] SS1 =
+ {
+
+ 0x38380830, 0xe828c8e0, 0x2c2d0d21, 0xa42686a2, 0xcc0fcfc3, 0xdc1eced2, 0xb03383b3, 0xb83888b0,
+ 0xac2f8fa3, 0x60204060, 0x54154551, 0xc407c7c3, 0x44044440, 0x6c2f4f63, 0x682b4b63, 0x581b4b53,
+ 0xc003c3c3, 0x60224262, 0x30330333, 0xb43585b1, 0x28290921, 0xa02080a0, 0xe022c2e2, 0xa42787a3,
+ 0xd013c3d3, 0x90118191, 0x10110111, 0x04060602, 0x1c1c0c10, 0xbc3c8cb0, 0x34360632, 0x480b4b43,
+ 0xec2fcfe3, 0x88088880, 0x6c2c4c60, 0xa82888a0, 0x14170713, 0xc404c4c0, 0x14160612, 0xf434c4f0,
+ 0xc002c2c2, 0x44054541, 0xe021c1e1, 0xd416c6d2, 0x3c3f0f33, 0x3c3d0d31, 0x8c0e8e82, 0x98188890,
+ 0x28280820, 0x4c0e4e42, 0xf436c6f2, 0x3c3e0e32, 0xa42585a1, 0xf839c9f1, 0x0c0d0d01, 0xdc1fcfd3,
+ 0xd818c8d0, 0x282b0b23, 0x64264662, 0x783a4a72, 0x24270723, 0x2c2f0f23, 0xf031c1f1, 0x70324272,
+ 0x40024242, 0xd414c4d0, 0x40014141, 0xc000c0c0, 0x70334373, 0x64274763, 0xac2c8ca0, 0x880b8b83,
+ 0xf437c7f3, 0xac2d8da1, 0x80008080, 0x1c1f0f13, 0xc80acac2, 0x2c2c0c20, 0xa82a8aa2, 0x34340430,
+ 0xd012c2d2, 0x080b0b03, 0xec2ecee2, 0xe829c9e1, 0x5c1d4d51, 0x94148490, 0x18180810, 0xf838c8f0,
+ 0x54174753, 0xac2e8ea2, 0x08080800, 0xc405c5c1, 0x10130313, 0xcc0dcdc1, 0x84068682, 0xb83989b1,
+ 0xfc3fcff3, 0x7c3d4d71, 0xc001c1c1, 0x30310131, 0xf435c5f1, 0x880a8a82, 0x682a4a62, 0xb03181b1,
+ 0xd011c1d1, 0x20200020, 0xd417c7d3, 0x00020202, 0x20220222, 0x04040400, 0x68284860, 0x70314171,
+ 0x04070703, 0xd81bcbd3, 0x9c1d8d91, 0x98198991, 0x60214161, 0xbc3e8eb2, 0xe426c6e2, 0x58194951,
+ 0xdc1dcdd1, 0x50114151, 0x90108090, 0xdc1cccd0, 0x981a8a92, 0xa02383a3, 0xa82b8ba3, 0xd010c0d0,
+ 0x80018181, 0x0c0f0f03, 0x44074743, 0x181a0a12, 0xe023c3e3, 0xec2ccce0, 0x8c0d8d81, 0xbc3f8fb3,
+ 0x94168692, 0x783b4b73, 0x5c1c4c50, 0xa02282a2, 0xa02181a1, 0x60234363, 0x20230323, 0x4c0d4d41,
+ 0xc808c8c0, 0x9c1e8e92, 0x9c1c8c90, 0x383a0a32, 0x0c0c0c00, 0x2c2e0e22, 0xb83a8ab2, 0x6c2e4e62,
+ 0x9c1f8f93, 0x581a4a52, 0xf032c2f2, 0x90128292, 0xf033c3f3, 0x48094941, 0x78384870, 0xcc0cccc0,
+ 0x14150511, 0xf83bcbf3, 0x70304070, 0x74354571, 0x7c3f4f73, 0x34350531, 0x10100010, 0x00030303,
+ 0x64244460, 0x6c2d4d61, 0xc406c6c2, 0x74344470, 0xd415c5d1, 0xb43484b0, 0xe82acae2, 0x08090901,
+ 0x74364672, 0x18190911, 0xfc3ecef2, 0x40004040, 0x10120212, 0xe020c0e0, 0xbc3d8db1, 0x04050501,
+ 0xf83acaf2, 0x00010101, 0xf030c0f0, 0x282a0a22, 0x5c1e4e52, 0xa82989a1, 0x54164652, 0x40034343,
+ 0x84058581, 0x14140410, 0x88098981, 0x981b8b93, 0xb03080b0, 0xe425c5e1, 0x48084840, 0x78394971,
+ 0x94178793, 0xfc3cccf0, 0x1c1e0e12, 0x80028282, 0x20210121, 0x8c0c8c80, 0x181b0b13, 0x5c1f4f53,
+ 0x74374773, 0x54144450, 0xb03282b2, 0x1c1d0d11, 0x24250521, 0x4c0f4f43, 0x00000000, 0x44064642,
+ 0xec2dcde1, 0x58184850, 0x50124252, 0xe82bcbe3, 0x7c3e4e72, 0xd81acad2, 0xc809c9c1, 0xfc3dcdf1,
+ 0x30300030, 0x94158591, 0x64254561, 0x3c3c0c30, 0xb43686b2, 0xe424c4e0, 0xb83b8bb3, 0x7c3c4c70,
+ 0x0c0e0e02, 0x50104050, 0x38390931, 0x24260622, 0x30320232, 0x84048480, 0x68294961, 0x90138393,
+ 0x34370733, 0xe427c7e3, 0x24240420, 0xa42484a0, 0xc80bcbc3, 0x50134353, 0x080a0a02, 0x84078783,
+ 0xd819c9d1, 0x4c0c4c40, 0x80038383, 0x8c0f8f83, 0xcc0ecec2, 0x383b0b33, 0x480a4a42, 0xb43787b3
+ };
+
+ private static final int[] SS2 =
+ {
+
+ 0xa1a82989, 0x81840585, 0xd2d416c6, 0xd3d013c3, 0x50541444, 0x111c1d0d, 0xa0ac2c8c, 0x21242505,
+ 0x515c1d4d, 0x43400343, 0x10181808, 0x121c1e0e, 0x51501141, 0xf0fc3ccc, 0xc2c80aca, 0x63602343,
+ 0x20282808, 0x40440444, 0x20202000, 0x919c1d8d, 0xe0e020c0, 0xe2e022c2, 0xc0c808c8, 0x13141707,
+ 0xa1a42585, 0x838c0f8f, 0x03000303, 0x73783b4b, 0xb3b83b8b, 0x13101303, 0xd2d012c2, 0xe2ec2ece,
+ 0x70703040, 0x808c0c8c, 0x333c3f0f, 0xa0a82888, 0x32303202, 0xd1dc1dcd, 0xf2f436c6, 0x70743444,
+ 0xe0ec2ccc, 0x91941585, 0x03080b0b, 0x53541747, 0x505c1c4c, 0x53581b4b, 0xb1bc3d8d, 0x01000101,
+ 0x20242404, 0x101c1c0c, 0x73703343, 0x90981888, 0x10101000, 0xc0cc0ccc, 0xf2f032c2, 0xd1d819c9,
+ 0x202c2c0c, 0xe3e427c7, 0x72703242, 0x83800383, 0x93981b8b, 0xd1d011c1, 0x82840686, 0xc1c809c9,
+ 0x60602040, 0x50501040, 0xa3a02383, 0xe3e82bcb, 0x010c0d0d, 0xb2b43686, 0x929c1e8e, 0x434c0f4f,
+ 0xb3b43787, 0x52581a4a, 0xc2c406c6, 0x70783848, 0xa2a42686, 0x12101202, 0xa3ac2f8f, 0xd1d415c5,
+ 0x61602141, 0xc3c003c3, 0xb0b43484, 0x41400141, 0x52501242, 0x717c3d4d, 0x818c0d8d, 0x00080808,
+ 0x131c1f0f, 0x91981989, 0x00000000, 0x11181909, 0x00040404, 0x53501343, 0xf3f437c7, 0xe1e021c1,
+ 0xf1fc3dcd, 0x72743646, 0x232c2f0f, 0x23242707, 0xb0b03080, 0x83880b8b, 0x020c0e0e, 0xa3a82b8b,
+ 0xa2a02282, 0x626c2e4e, 0x93901383, 0x414c0d4d, 0x61682949, 0x707c3c4c, 0x01080909, 0x02080a0a,
+ 0xb3bc3f8f, 0xe3ec2fcf, 0xf3f033c3, 0xc1c405c5, 0x83840787, 0x10141404, 0xf2fc3ece, 0x60642444,
+ 0xd2dc1ece, 0x222c2e0e, 0x43480b4b, 0x12181a0a, 0x02040606, 0x21202101, 0x63682b4b, 0x62642646,
+ 0x02000202, 0xf1f435c5, 0x92901282, 0x82880a8a, 0x000c0c0c, 0xb3b03383, 0x727c3e4e, 0xd0d010c0,
+ 0x72783a4a, 0x43440747, 0x92941686, 0xe1e425c5, 0x22242606, 0x80800080, 0xa1ac2d8d, 0xd3dc1fcf,
+ 0xa1a02181, 0x30303000, 0x33343707, 0xa2ac2e8e, 0x32343606, 0x11141505, 0x22202202, 0x30383808,
+ 0xf0f434c4, 0xa3a42787, 0x41440545, 0x404c0c4c, 0x81800181, 0xe1e829c9, 0x80840484, 0x93941787,
+ 0x31343505, 0xc3c80bcb, 0xc2cc0ece, 0x303c3c0c, 0x71703141, 0x11101101, 0xc3c407c7, 0x81880989,
+ 0x71743545, 0xf3f83bcb, 0xd2d81aca, 0xf0f838c8, 0x90941484, 0x51581949, 0x82800282, 0xc0c404c4,
+ 0xf3fc3fcf, 0x41480949, 0x31383909, 0x63642747, 0xc0c000c0, 0xc3cc0fcf, 0xd3d417c7, 0xb0b83888,
+ 0x030c0f0f, 0x828c0e8e, 0x42400242, 0x23202303, 0x91901181, 0x606c2c4c, 0xd3d81bcb, 0xa0a42484,
+ 0x30343404, 0xf1f031c1, 0x40480848, 0xc2c002c2, 0x636c2f4f, 0x313c3d0d, 0x212c2d0d, 0x40400040,
+ 0xb2bc3e8e, 0x323c3e0e, 0xb0bc3c8c, 0xc1c001c1, 0xa2a82a8a, 0xb2b83a8a, 0x424c0e4e, 0x51541545,
+ 0x33383b0b, 0xd0dc1ccc, 0x60682848, 0x737c3f4f, 0x909c1c8c, 0xd0d818c8, 0x42480a4a, 0x52541646,
+ 0x73743747, 0xa0a02080, 0xe1ec2dcd, 0x42440646, 0xb1b43585, 0x23282b0b, 0x61642545, 0xf2f83aca,
+ 0xe3e023c3, 0xb1b83989, 0xb1b03181, 0x939c1f8f, 0x525c1e4e, 0xf1f839c9, 0xe2e426c6, 0xb2b03282,
+ 0x31303101, 0xe2e82aca, 0x616c2d4d, 0x535c1f4f, 0xe0e424c4, 0xf0f030c0, 0xc1cc0dcd, 0x80880888,
+ 0x12141606, 0x32383a0a, 0x50581848, 0xd0d414c4, 0x62602242, 0x21282909, 0x03040707, 0x33303303,
+ 0xe0e828c8, 0x13181b0b, 0x01040505, 0x71783949, 0x90901080, 0x62682a4a, 0x22282a0a, 0x92981a8a
+ };
+
+
+ private static final int[] SS3 =
+ {
+
+ 0x08303838, 0xc8e0e828, 0x0d212c2d, 0x86a2a426, 0xcfc3cc0f, 0xced2dc1e, 0x83b3b033, 0x88b0b838,
+ 0x8fa3ac2f, 0x40606020, 0x45515415, 0xc7c3c407, 0x44404404, 0x4f636c2f, 0x4b63682b, 0x4b53581b,
+ 0xc3c3c003, 0x42626022, 0x03333033, 0x85b1b435, 0x09212829, 0x80a0a020, 0xc2e2e022, 0x87a3a427,
+ 0xc3d3d013, 0x81919011, 0x01111011, 0x06020406, 0x0c101c1c, 0x8cb0bc3c, 0x06323436, 0x4b43480b,
+ 0xcfe3ec2f, 0x88808808, 0x4c606c2c, 0x88a0a828, 0x07131417, 0xc4c0c404, 0x06121416, 0xc4f0f434,
+ 0xc2c2c002, 0x45414405, 0xc1e1e021, 0xc6d2d416, 0x0f333c3f, 0x0d313c3d, 0x8e828c0e, 0x88909818,
+ 0x08202828, 0x4e424c0e, 0xc6f2f436, 0x0e323c3e, 0x85a1a425, 0xc9f1f839, 0x0d010c0d, 0xcfd3dc1f,
+ 0xc8d0d818, 0x0b23282b, 0x46626426, 0x4a72783a, 0x07232427, 0x0f232c2f, 0xc1f1f031, 0x42727032,
+ 0x42424002, 0xc4d0d414, 0x41414001, 0xc0c0c000, 0x43737033, 0x47636427, 0x8ca0ac2c, 0x8b83880b,
+ 0xc7f3f437, 0x8da1ac2d, 0x80808000, 0x0f131c1f, 0xcac2c80a, 0x0c202c2c, 0x8aa2a82a, 0x04303434,
+ 0xc2d2d012, 0x0b03080b, 0xcee2ec2e, 0xc9e1e829, 0x4d515c1d, 0x84909414, 0x08101818, 0xc8f0f838,
+ 0x47535417, 0x8ea2ac2e, 0x08000808, 0xc5c1c405, 0x03131013, 0xcdc1cc0d, 0x86828406, 0x89b1b839,
+ 0xcff3fc3f, 0x4d717c3d, 0xc1c1c001, 0x01313031, 0xc5f1f435, 0x8a82880a, 0x4a62682a, 0x81b1b031,
+ 0xc1d1d011, 0x00202020, 0xc7d3d417, 0x02020002, 0x02222022, 0x04000404, 0x48606828, 0x41717031,
+ 0x07030407, 0xcbd3d81b, 0x8d919c1d, 0x89919819, 0x41616021, 0x8eb2bc3e, 0xc6e2e426, 0x49515819,
+ 0xcdd1dc1d, 0x41515011, 0x80909010, 0xccd0dc1c, 0x8a92981a, 0x83a3a023, 0x8ba3a82b, 0xc0d0d010,
+ 0x81818001, 0x0f030c0f, 0x47434407, 0x0a12181a, 0xc3e3e023, 0xcce0ec2c, 0x8d818c0d, 0x8fb3bc3f,
+ 0x86929416, 0x4b73783b, 0x4c505c1c, 0x82a2a022, 0x81a1a021, 0x43636023, 0x03232023, 0x4d414c0d,
+ 0xc8c0c808, 0x8e929c1e, 0x8c909c1c, 0x0a32383a, 0x0c000c0c, 0x0e222c2e, 0x8ab2b83a, 0x4e626c2e,
+ 0x8f939c1f, 0x4a52581a, 0xc2f2f032, 0x82929012, 0xc3f3f033, 0x49414809, 0x48707838, 0xccc0cc0c,
+ 0x05111415, 0xcbf3f83b, 0x40707030, 0x45717435, 0x4f737c3f, 0x05313435, 0x00101010, 0x03030003,
+ 0x44606424, 0x4d616c2d, 0xc6c2c406, 0x44707434, 0xc5d1d415, 0x84b0b434, 0xcae2e82a, 0x09010809,
+ 0x46727436, 0x09111819, 0xcef2fc3e, 0x40404000, 0x02121012, 0xc0e0e020, 0x8db1bc3d, 0x05010405,
+ 0xcaf2f83a, 0x01010001, 0xc0f0f030, 0x0a22282a, 0x4e525c1e, 0x89a1a829, 0x46525416, 0x43434003,
+ 0x85818405, 0x04101414, 0x89818809, 0x8b93981b, 0x80b0b030, 0xc5e1e425, 0x48404808, 0x49717839,
+ 0x87939417, 0xccf0fc3c, 0x0e121c1e, 0x82828002, 0x01212021, 0x8c808c0c, 0x0b13181b, 0x4f535c1f,
+ 0x47737437, 0x44505414, 0x82b2b032, 0x0d111c1d, 0x05212425, 0x4f434c0f, 0x00000000, 0x46424406,
+ 0xcde1ec2d, 0x48505818, 0x42525012, 0xcbe3e82b, 0x4e727c3e, 0xcad2d81a, 0xc9c1c809, 0xcdf1fc3d,
+ 0x00303030, 0x85919415, 0x45616425, 0x0c303c3c, 0x86b2b436, 0xc4e0e424, 0x8bb3b83b, 0x4c707c3c,
+ 0x0e020c0e, 0x40505010, 0x09313839, 0x06222426, 0x02323032, 0x84808404, 0x49616829, 0x83939013,
+ 0x07333437, 0xc7e3e427, 0x04202424, 0x84a0a424, 0xcbc3c80b, 0x43535013, 0x0a02080a, 0x87838407,
+ 0xc9d1d819, 0x4c404c0c, 0x83838003, 0x8f838c0f, 0xcec2cc0e, 0x0b33383b, 0x4a42480a, 0x87b3b437
+ };
+
+
+ private static final int[] KC =
+ {
+ 0x9e3779b9, 0x3c6ef373, 0x78dde6e6, 0xf1bbcdcc,
+ 0xe3779b99, 0xc6ef3733, 0x8dde6e67, 0x1bbcdccf,
+ 0x3779b99e, 0x6ef3733c, 0xdde6e678, 0xbbcdccf1,
+ 0x779b99e3, 0xef3733c6, 0xde6e678d, 0xbcdccf1b
+ };
+
+ private int[] wKey;
+ private boolean forEncryption;
+
+ public void init(boolean forEncryption, CipherParameters params) throws IllegalArgumentException
+ {
+ this.forEncryption = forEncryption;
+ wKey = createWorkingKey(((KeyParameter)params).getKey());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "SEED";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public int processBlock(byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException
+ {
+ if (wKey == null)
+ {
+ throw new IllegalStateException("SEED engine not initialised");
+ }
+
+ if (inOff + BLOCK_SIZE > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if (outOff + BLOCK_SIZE > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ long l = bytesToLong(in, inOff + 0);
+ long r = bytesToLong(in, inOff + 8);
+
+ if (forEncryption)
+ {
+ for (int i = 0; i < 16; i++)
+ {
+ long nl = r;
+
+ r = l ^ F(wKey[2 * i], wKey[(2 * i) + 1], r);
+ l = nl;
+ }
+ }
+ else
+ {
+ for (int i = 15; i >= 0; i--)
+ {
+ long nl = r;
+
+ r = l ^ F(wKey[2 * i], wKey[(2 * i) + 1], r);
+ l = nl;
+ }
+ }
+
+ longToBytes(out, outOff + 0, r);
+ longToBytes(out, outOff + 8, l);
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+
+ private int[] createWorkingKey(byte[] inKey)
+ {
+ int[] key = new int[32];
+ long lower = bytesToLong(inKey, 0);
+ long upper = bytesToLong(inKey, 8);
+
+ int key0 = extractW0(lower);
+ int key1 = extractW1(lower);
+ int key2 = extractW0(upper);
+ int key3 = extractW1(upper);
+
+ for (int i = 0; i < 16; i++)
+ {
+ key[2 * i] = G(key0 + key2 - KC[i]);
+ key[2 * i + 1] = G(key1 - key3 + KC[i]);
+
+ if (i % 2 == 0)
+ {
+ lower = rotateRight8(lower);
+ key0 = extractW0(lower);
+ key1 = extractW1(lower);
+ }
+ else
+ {
+ upper = rotateLeft8(upper);
+ key2 = extractW0(upper);
+ key3 = extractW1(upper);
+ }
+ }
+
+ return key;
+ }
+
+ private int extractW1(long lVal)
+ {
+ return (int)lVal;
+ }
+
+ private int extractW0(long lVal)
+ {
+ return (int)(lVal >> 32);
+ }
+
+ private long rotateLeft8(long x)
+ {
+ return (x << 8) | (x >>> 56);
+ }
+
+ private long rotateRight8(long x)
+ {
+ return (x >>> 8) | (x << 56);
+ }
+
+ private long bytesToLong(
+ byte[] src,
+ int srcOff)
+ {
+ long word = 0;
+
+ for (int i = 0; i <= 7; i++)
+ {
+ word = (word << 8) + (src[i + srcOff] & 0xff);
+ }
+
+ return word;
+ }
+
+ private void longToBytes(
+ byte[] dest,
+ int destOff,
+ long value)
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ dest[i + destOff] = (byte)(value >> ((7 - i) * 8));
+ }
+ }
+
+ private int G(int x)
+ {
+ return SS0[x & 0xff] ^ SS1[(x >> 8) & 0xff] ^ SS2[(x >> 16) & 0xff] ^ SS3[(x >> 24) & 0xff];
+ }
+
+ private long F(int ki0, int ki1, long r)
+ {
+ int r0 = (int)(r >> 32);
+ int r1 = (int)r;
+ int rd1 = phaseCalc2(r0, ki0, r1, ki1);
+ int rd0 = rd1 + phaseCalc1(r0, ki0, r1, ki1);
+
+ return ((long)rd0 << 32) | (rd1 & 0xffffffffL);
+ }
+
+ private int phaseCalc1(int r0, int ki0, int r1, int ki1)
+ {
+ return G(G((r0 ^ ki0) ^ (r1 ^ ki1)) + (r0 ^ ki0));
+ }
+
+ private int phaseCalc2(int r0, int ki0, int r1, int ki1)
+ {
+ return G(phaseCalc1(r0, ki0, r1, ki1) + G((r0 ^ ki0) ^ (r1 ^ ki1)));
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/SEEDWrapEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/SEEDWrapEngine.java
new file mode 100644
index 00000000..2b5213c2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/SEEDWrapEngine.java
@@ -0,0 +1,15 @@
+package org.spongycastle.crypto.engines;
+
+/**
+ * An implementation of the SEED key wrapper based on RFC 4010/RFC 3394.
+ * <p>
+ * For further details see: <a href="http://www.ietf.org/rfc/rfc4010.txt">http://www.ietf.org/rfc/rfc4010.txt</a>.
+ */
+public class SEEDWrapEngine
+ extends RFC3394WrapEngine
+{
+ public SEEDWrapEngine()
+ {
+ super(new SEEDEngine());
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/Salsa20Engine.java b/core/src/main/java/org/spongycastle/crypto/engines/Salsa20Engine.java
new file mode 100644
index 00000000..ff9953aa
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/Salsa20Engine.java
@@ -0,0 +1,474 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.MaxBytesExceededException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.SkippingStreamCipher;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Pack;
+import org.spongycastle.util.Strings;
+
+/**
+ * Implementation of Daniel J. Bernstein's Salsa20 stream cipher, Snuffle 2005
+ */
+public class Salsa20Engine
+ implements SkippingStreamCipher
+{
+ public final static int DEFAULT_ROUNDS = 20;
+
+ /** Constants */
+ private final static int STATE_SIZE = 16; // 16, 32 bit ints = 64 bytes
+
+ 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;
+ 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;
+
+ /*
+ * internal counter
+ */
+ 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.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ /*
+ * Salsa20 encryption and decryption is completely
+ * symmetrical, so the 'forEncryption' is
+ * irrelevant. (Like 90% of stream ciphers)
+ */
+
+ if (!(params instanceof ParametersWithIV))
+ {
+ throw new IllegalArgumentException(getAlgorithmName() + " Init parameters must include an IV");
+ }
+
+ ParametersWithIV ivParams = (ParametersWithIV) params;
+
+ byte[] iv = ivParams.getIV();
+ if (iv == null || iv.length != getNonceSize())
+ {
+ throw new IllegalArgumentException(getAlgorithmName() + " requires exactly " + getNonceSize()
+ + " bytes of IV");
+ }
+
+ CipherParameters keyParam = ivParams.getParameters();
+ if (keyParam == null)
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName() + " KeyParameter can not be null for first initialisation");
+ }
+
+ setKey(null, iv);
+ }
+ else if (keyParam instanceof KeyParameter)
+ {
+ setKey(((KeyParameter)keyParam).getKey(), iv);
+ }
+ else
+ {
+ throw new IllegalArgumentException(getAlgorithmName() + " Init parameters must contain a KeyParameter (or null for re-init)");
+ }
+
+ reset();
+
+ initialised = true;
+ }
+
+ protected int getNonceSize()
+ {
+ return 8;
+ }
+
+ public String getAlgorithmName()
+ {
+ String name = "Salsa20";
+ if (rounds != DEFAULT_ROUNDS)
+ {
+ name += "/" + rounds;
+ }
+ return name;
+ }
+
+ public byte returnByte(byte in)
+ {
+ if (limitExceeded())
+ {
+ throw new MaxBytesExceededException("2^70 byte limit per IV; Change IV");
+ }
+
+ byte out = (byte)(keyStream[index]^in);
+ index = (index + 1) & 63;
+
+ if (index == 0)
+ {
+ advanceCounter();
+ generateKeyStream(keyStream);
+ }
+
+ return out;
+ }
+
+ protected void advanceCounter()
+ {
+ if (++engineState[8] == 0)
+ {
+ ++engineState[9];
+ }
+ }
+
+ protected void retreatCounter()
+ {
+ if (engineState[8] == 0 && engineState[9] == 0)
+ {
+ throw new IllegalStateException("attempt to reduce counter past zero.");
+ }
+
+ if (--engineState[8] == -1)
+ {
+ --engineState[9];
+ }
+ }
+
+ public int processBytes(
+ byte[] in,
+ int inOff,
+ int len,
+ byte[] out,
+ int outOff)
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName() + " not initialised");
+ }
+
+ if ((inOff + len) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + len) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ if (limitExceeded(len))
+ {
+ throw new MaxBytesExceededException("2^70 byte limit per IV would be exceeded; Change IV");
+ }
+
+ for (int i = 0; i < len; i++)
+ {
+ out[i + outOff] = (byte)(keyStream[index] ^ in[i + inOff]);
+ index = (index + 1) & 63;
+
+ if (index == 0)
+ {
+ advanceCounter();
+ generateKeyStream(keyStream);
+ }
+ }
+
+ return len;
+ }
+
+ public long skip(long numberOfBytes)
+ {
+ if (numberOfBytes >= 0)
+ {
+ for (long i = 0; i < numberOfBytes; i++)
+ {
+ index = (index + 1) & 63;
+
+ if (index == 0)
+ {
+ advanceCounter();
+ }
+ }
+ }
+ else
+ {
+ for (long i = 0; i > numberOfBytes; i--)
+ {
+ if (index == 0)
+ {
+ retreatCounter();
+ }
+
+ index = (index - 1) & 63;
+ }
+ }
+
+ generateKeyStream(keyStream);
+
+ return numberOfBytes;
+ }
+
+ public long seekTo(long position)
+ {
+ reset();
+
+ return skip(position);
+ }
+
+ public long getPosition()
+ {
+ return getCounter() * 64 + index;
+ }
+
+ public void reset()
+ {
+ index = 0;
+ resetLimitCounter();
+ resetCounter();
+
+ generateKeyStream(keyStream);
+ }
+
+ protected long getCounter()
+ {
+ return ((long)engineState[9] << 32) | (engineState[8] & 0xffffffffL);
+ }
+
+ protected void resetCounter()
+ {
+ engineState[8] = engineState[9] = 0;
+ }
+
+ protected void setKey(byte[] keyBytes, byte[] ivBytes)
+ {
+ if (keyBytes != null)
+ {
+ if ((keyBytes.length != 16) && (keyBytes.length != 32))
+ {
+ throw new IllegalArgumentException(getAlgorithmName() + " requires 128 bit or 256 bit key");
+ }
+
+ // Key
+ engineState[1] = Pack.littleEndianToInt(keyBytes, 0);
+ engineState[2] = Pack.littleEndianToInt(keyBytes, 4);
+ engineState[3] = Pack.littleEndianToInt(keyBytes, 8);
+ engineState[4] = Pack.littleEndianToInt(keyBytes, 12);
+
+ byte[] constants;
+ int offset;
+ if (keyBytes.length == 32)
+ {
+ constants = sigma;
+ offset = 16;
+ }
+ else
+ {
+ constants = tau;
+ offset = 0;
+ }
+
+ 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(ivBytes, 0);
+ engineState[7] = Pack.littleEndianToInt(ivBytes, 4);
+ }
+
+ protected void generateKeyStream(byte[] output)
+ {
+ salsaCore(rounds, engineState, x);
+ Pack.intToLittleEndian(x, output, 0);
+ }
+
+ /**
+ * Salsa20 function
+ *
+ * @param input input data
+ */
+ public static void salsaCore(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)
+ {
+ 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);
+ }
+
+ 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];
+ }
+
+ /**
+ * Rotate left
+ *
+ * @param x value to rotate
+ * @param y amount to rotate x
+ *
+ * @return rotated x
+ */
+ protected static int rotl(int x, int y)
+ {
+ return (x << y) | (x >>> -y);
+ }
+
+ private void resetLimitCounter()
+ {
+ cW0 = 0;
+ cW1 = 0;
+ cW2 = 0;
+ }
+
+ private boolean limitExceeded()
+ {
+ if (++cW0 == 0)
+ {
+ if (++cW1 == 0)
+ {
+ return (++cW2 & 0x20) != 0; // 2^(32 + 32 + 6)
+ }
+ }
+
+ return false;
+ }
+
+ /*
+ * this relies on the fact len will always be positive.
+ */
+ private boolean limitExceeded(int len)
+ {
+ cW0 += len;
+ if (cW0 < len && cW0 >= 0)
+ {
+ if (++cW1 == 0)
+ {
+ return (++cW2 & 0x20) != 0; // 2^(32 + 32 + 6)
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/SerpentEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/SerpentEngine.java
new file mode 100644
index 00000000..944f0ae5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/SerpentEngine.java
@@ -0,0 +1,783 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+
+/**
+ * Serpent is a 128-bit 32-round block cipher with variable key lengths,
+ * including 128, 192 and 256 bit keys conjectured to be at least as
+ * secure as three-key triple-DES.
+ * <p>
+ * Serpent was designed by Ross Anderson, Eli Biham and Lars Knudsen as a
+ * candidate algorithm for the NIST AES Quest.
+ * <p>
+ * For full details see the <a href="http://www.cl.cam.ac.uk/~rja14/serpent.html">The Serpent home page</a>
+ */
+public class SerpentEngine
+ implements BlockCipher
+{
+ private static final int BLOCK_SIZE = 16;
+
+ static final int ROUNDS = 32;
+ static final int PHI = 0x9E3779B9; // (sqrt(5) - 1) * 2**31
+
+ private boolean encrypting;
+ private int[] wKey;
+
+ private int X0, X1, X2, X3; // registers
+
+ /**
+ * initialise a Serpent cipher.
+ *
+ * @param encrypting whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ {
+ if (params instanceof KeyParameter)
+ {
+ this.encrypting = encrypting;
+ this.wKey = makeWorkingKey(((KeyParameter)params).getKey());
+ return;
+ }
+
+ throw new IllegalArgumentException("invalid parameter passed to Serpent init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Serpent";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public final int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (wKey == null)
+ {
+ throw new IllegalStateException("Serpent not initialised");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ if (encrypting)
+ {
+ encryptBlock(in, inOff, out, outOff);
+ }
+ else
+ {
+ decryptBlock(in, inOff, out, outOff);
+ }
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+
+ /**
+ * Expand a user-supplied key material into a session key.
+ *
+ * @param key The user-key bytes (multiples of 4) to use.
+ * @exception IllegalArgumentException
+ */
+ private int[] makeWorkingKey(
+ byte[] key)
+ throws IllegalArgumentException
+ {
+ //
+ // pad key to 256 bits
+ //
+ int[] kPad = new int[16];
+ int off = 0;
+ int length = 0;
+
+ for (off = key.length - 4; off > 0; off -= 4)
+ {
+ kPad[length++] = bytesToWord(key, off);
+ }
+
+ if (off == 0)
+ {
+ kPad[length++] = bytesToWord(key, 0);
+ if (length < 8)
+ {
+ kPad[length] = 1;
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("key must be a multiple of 4 bytes");
+ }
+
+ //
+ // expand the padded key up to 33 x 128 bits of key material
+ //
+ int amount = (ROUNDS + 1) * 4;
+ int[] w = new int[amount];
+
+ //
+ // compute w0 to w7 from w-8 to w-1
+ //
+ for (int i = 8; i < 16; i++)
+ {
+ kPad[i] = rotateLeft(kPad[i - 8] ^ kPad[i - 5] ^ kPad[i - 3] ^ kPad[i - 1] ^ PHI ^ (i - 8), 11);
+ }
+
+ System.arraycopy(kPad, 8, w, 0, 8);
+
+ //
+ // compute w8 to w136
+ //
+ for (int i = 8; i < amount; i++)
+ {
+ w[i] = rotateLeft(w[i - 8] ^ w[i - 5] ^ w[i - 3] ^ w[i - 1] ^ PHI ^ i, 11);
+ }
+
+ //
+ // create the working keys by processing w with the Sbox and IP
+ //
+ sb3(w[0], w[1], w[2], w[3]);
+ w[0] = X0; w[1] = X1; w[2] = X2; w[3] = X3;
+ sb2(w[4], w[5], w[6], w[7]);
+ w[4] = X0; w[5] = X1; w[6] = X2; w[7] = X3;
+ sb1(w[8], w[9], w[10], w[11]);
+ w[8] = X0; w[9] = X1; w[10] = X2; w[11] = X3;
+ sb0(w[12], w[13], w[14], w[15]);
+ w[12] = X0; w[13] = X1; w[14] = X2; w[15] = X3;
+ sb7(w[16], w[17], w[18], w[19]);
+ w[16] = X0; w[17] = X1; w[18] = X2; w[19] = X3;
+ sb6(w[20], w[21], w[22], w[23]);
+ w[20] = X0; w[21] = X1; w[22] = X2; w[23] = X3;
+ sb5(w[24], w[25], w[26], w[27]);
+ w[24] = X0; w[25] = X1; w[26] = X2; w[27] = X3;
+ sb4(w[28], w[29], w[30], w[31]);
+ w[28] = X0; w[29] = X1; w[30] = X2; w[31] = X3;
+ sb3(w[32], w[33], w[34], w[35]);
+ w[32] = X0; w[33] = X1; w[34] = X2; w[35] = X3;
+ sb2(w[36], w[37], w[38], w[39]);
+ w[36] = X0; w[37] = X1; w[38] = X2; w[39] = X3;
+ sb1(w[40], w[41], w[42], w[43]);
+ w[40] = X0; w[41] = X1; w[42] = X2; w[43] = X3;
+ sb0(w[44], w[45], w[46], w[47]);
+ w[44] = X0; w[45] = X1; w[46] = X2; w[47] = X3;
+ sb7(w[48], w[49], w[50], w[51]);
+ w[48] = X0; w[49] = X1; w[50] = X2; w[51] = X3;
+ sb6(w[52], w[53], w[54], w[55]);
+ w[52] = X0; w[53] = X1; w[54] = X2; w[55] = X3;
+ sb5(w[56], w[57], w[58], w[59]);
+ w[56] = X0; w[57] = X1; w[58] = X2; w[59] = X3;
+ sb4(w[60], w[61], w[62], w[63]);
+ w[60] = X0; w[61] = X1; w[62] = X2; w[63] = X3;
+ sb3(w[64], w[65], w[66], w[67]);
+ w[64] = X0; w[65] = X1; w[66] = X2; w[67] = X3;
+ sb2(w[68], w[69], w[70], w[71]);
+ w[68] = X0; w[69] = X1; w[70] = X2; w[71] = X3;
+ sb1(w[72], w[73], w[74], w[75]);
+ w[72] = X0; w[73] = X1; w[74] = X2; w[75] = X3;
+ sb0(w[76], w[77], w[78], w[79]);
+ w[76] = X0; w[77] = X1; w[78] = X2; w[79] = X3;
+ sb7(w[80], w[81], w[82], w[83]);
+ w[80] = X0; w[81] = X1; w[82] = X2; w[83] = X3;
+ sb6(w[84], w[85], w[86], w[87]);
+ w[84] = X0; w[85] = X1; w[86] = X2; w[87] = X3;
+ sb5(w[88], w[89], w[90], w[91]);
+ w[88] = X0; w[89] = X1; w[90] = X2; w[91] = X3;
+ sb4(w[92], w[93], w[94], w[95]);
+ w[92] = X0; w[93] = X1; w[94] = X2; w[95] = X3;
+ sb3(w[96], w[97], w[98], w[99]);
+ w[96] = X0; w[97] = X1; w[98] = X2; w[99] = X3;
+ sb2(w[100], w[101], w[102], w[103]);
+ w[100] = X0; w[101] = X1; w[102] = X2; w[103] = X3;
+ sb1(w[104], w[105], w[106], w[107]);
+ w[104] = X0; w[105] = X1; w[106] = X2; w[107] = X3;
+ sb0(w[108], w[109], w[110], w[111]);
+ w[108] = X0; w[109] = X1; w[110] = X2; w[111] = X3;
+ sb7(w[112], w[113], w[114], w[115]);
+ w[112] = X0; w[113] = X1; w[114] = X2; w[115] = X3;
+ sb6(w[116], w[117], w[118], w[119]);
+ w[116] = X0; w[117] = X1; w[118] = X2; w[119] = X3;
+ sb5(w[120], w[121], w[122], w[123]);
+ w[120] = X0; w[121] = X1; w[122] = X2; w[123] = X3;
+ sb4(w[124], w[125], w[126], w[127]);
+ w[124] = X0; w[125] = X1; w[126] = X2; w[127] = X3;
+ sb3(w[128], w[129], w[130], w[131]);
+ w[128] = X0; w[129] = X1; w[130] = X2; w[131] = X3;
+
+ return w;
+ }
+
+ private int rotateLeft(
+ int x,
+ int bits)
+ {
+ return (x << bits) | (x >>> -bits);
+ }
+
+ private int rotateRight(
+ int x,
+ int bits)
+ {
+ return (x >>> bits) | (x << -bits);
+ }
+
+ private int bytesToWord(
+ byte[] src,
+ int srcOff)
+ {
+ return (((src[srcOff] & 0xff) << 24) | ((src[srcOff + 1] & 0xff) << 16) |
+ ((src[srcOff + 2] & 0xff) << 8) | ((src[srcOff + 3] & 0xff)));
+ }
+
+ private void wordToBytes(
+ int word,
+ byte[] dst,
+ int dstOff)
+ {
+ dst[dstOff + 3] = (byte)(word);
+ dst[dstOff + 2] = (byte)(word >>> 8);
+ dst[dstOff + 1] = (byte)(word >>> 16);
+ dst[dstOff] = (byte)(word >>> 24);
+ }
+
+ /**
+ * Encrypt one block of plaintext.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ */
+ private void encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ X3 = bytesToWord(in, inOff);
+ X2 = bytesToWord(in, inOff + 4);
+ X1 = bytesToWord(in, inOff + 8);
+ X0 = bytesToWord(in, inOff + 12);
+
+ sb0(wKey[0] ^ X0, wKey[1] ^ X1, wKey[2] ^ X2, wKey[3] ^ X3); LT();
+ sb1(wKey[4] ^ X0, wKey[5] ^ X1, wKey[6] ^ X2, wKey[7] ^ X3); LT();
+ sb2(wKey[8] ^ X0, wKey[9] ^ X1, wKey[10] ^ X2, wKey[11] ^ X3); LT();
+ sb3(wKey[12] ^ X0, wKey[13] ^ X1, wKey[14] ^ X2, wKey[15] ^ X3); LT();
+ sb4(wKey[16] ^ X0, wKey[17] ^ X1, wKey[18] ^ X2, wKey[19] ^ X3); LT();
+ sb5(wKey[20] ^ X0, wKey[21] ^ X1, wKey[22] ^ X2, wKey[23] ^ X3); LT();
+ sb6(wKey[24] ^ X0, wKey[25] ^ X1, wKey[26] ^ X2, wKey[27] ^ X3); LT();
+ sb7(wKey[28] ^ X0, wKey[29] ^ X1, wKey[30] ^ X2, wKey[31] ^ X3); LT();
+ sb0(wKey[32] ^ X0, wKey[33] ^ X1, wKey[34] ^ X2, wKey[35] ^ X3); LT();
+ sb1(wKey[36] ^ X0, wKey[37] ^ X1, wKey[38] ^ X2, wKey[39] ^ X3); LT();
+ sb2(wKey[40] ^ X0, wKey[41] ^ X1, wKey[42] ^ X2, wKey[43] ^ X3); LT();
+ sb3(wKey[44] ^ X0, wKey[45] ^ X1, wKey[46] ^ X2, wKey[47] ^ X3); LT();
+ sb4(wKey[48] ^ X0, wKey[49] ^ X1, wKey[50] ^ X2, wKey[51] ^ X3); LT();
+ sb5(wKey[52] ^ X0, wKey[53] ^ X1, wKey[54] ^ X2, wKey[55] ^ X3); LT();
+ sb6(wKey[56] ^ X0, wKey[57] ^ X1, wKey[58] ^ X2, wKey[59] ^ X3); LT();
+ sb7(wKey[60] ^ X0, wKey[61] ^ X1, wKey[62] ^ X2, wKey[63] ^ X3); LT();
+ sb0(wKey[64] ^ X0, wKey[65] ^ X1, wKey[66] ^ X2, wKey[67] ^ X3); LT();
+ sb1(wKey[68] ^ X0, wKey[69] ^ X1, wKey[70] ^ X2, wKey[71] ^ X3); LT();
+ sb2(wKey[72] ^ X0, wKey[73] ^ X1, wKey[74] ^ X2, wKey[75] ^ X3); LT();
+ sb3(wKey[76] ^ X0, wKey[77] ^ X1, wKey[78] ^ X2, wKey[79] ^ X3); LT();
+ sb4(wKey[80] ^ X0, wKey[81] ^ X1, wKey[82] ^ X2, wKey[83] ^ X3); LT();
+ sb5(wKey[84] ^ X0, wKey[85] ^ X1, wKey[86] ^ X2, wKey[87] ^ X3); LT();
+ sb6(wKey[88] ^ X0, wKey[89] ^ X1, wKey[90] ^ X2, wKey[91] ^ X3); LT();
+ sb7(wKey[92] ^ X0, wKey[93] ^ X1, wKey[94] ^ X2, wKey[95] ^ X3); LT();
+ sb0(wKey[96] ^ X0, wKey[97] ^ X1, wKey[98] ^ X2, wKey[99] ^ X3); LT();
+ sb1(wKey[100] ^ X0, wKey[101] ^ X1, wKey[102] ^ X2, wKey[103] ^ X3); LT();
+ sb2(wKey[104] ^ X0, wKey[105] ^ X1, wKey[106] ^ X2, wKey[107] ^ X3); LT();
+ sb3(wKey[108] ^ X0, wKey[109] ^ X1, wKey[110] ^ X2, wKey[111] ^ X3); LT();
+ sb4(wKey[112] ^ X0, wKey[113] ^ X1, wKey[114] ^ X2, wKey[115] ^ X3); LT();
+ sb5(wKey[116] ^ X0, wKey[117] ^ X1, wKey[118] ^ X2, wKey[119] ^ X3); LT();
+ sb6(wKey[120] ^ X0, wKey[121] ^ X1, wKey[122] ^ X2, wKey[123] ^ X3); LT();
+ sb7(wKey[124] ^ X0, wKey[125] ^ X1, wKey[126] ^ X2, wKey[127] ^ X3);
+
+ wordToBytes(wKey[131] ^ X3, out, outOff);
+ wordToBytes(wKey[130] ^ X2, out, outOff + 4);
+ wordToBytes(wKey[129] ^ X1, out, outOff + 8);
+ wordToBytes(wKey[128] ^ X0, out, outOff + 12);
+ }
+
+ /**
+ * Decrypt one block of ciphertext.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ */
+ private void decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ X3 = wKey[131] ^ bytesToWord(in, inOff);
+ X2 = wKey[130] ^ bytesToWord(in, inOff + 4);
+ X1 = wKey[129] ^ bytesToWord(in, inOff + 8);
+ X0 = wKey[128] ^ bytesToWord(in, inOff + 12);
+
+ ib7(X0, X1, X2, X3);
+ X0 ^= wKey[124]; X1 ^= wKey[125]; X2 ^= wKey[126]; X3 ^= wKey[127];
+ inverseLT(); ib6(X0, X1, X2, X3);
+ X0 ^= wKey[120]; X1 ^= wKey[121]; X2 ^= wKey[122]; X3 ^= wKey[123];
+ inverseLT(); ib5(X0, X1, X2, X3);
+ X0 ^= wKey[116]; X1 ^= wKey[117]; X2 ^= wKey[118]; X3 ^= wKey[119];
+ inverseLT(); ib4(X0, X1, X2, X3);
+ X0 ^= wKey[112]; X1 ^= wKey[113]; X2 ^= wKey[114]; X3 ^= wKey[115];
+ inverseLT(); ib3(X0, X1, X2, X3);
+ X0 ^= wKey[108]; X1 ^= wKey[109]; X2 ^= wKey[110]; X3 ^= wKey[111];
+ inverseLT(); ib2(X0, X1, X2, X3);
+ X0 ^= wKey[104]; X1 ^= wKey[105]; X2 ^= wKey[106]; X3 ^= wKey[107];
+ inverseLT(); ib1(X0, X1, X2, X3);
+ X0 ^= wKey[100]; X1 ^= wKey[101]; X2 ^= wKey[102]; X3 ^= wKey[103];
+ inverseLT(); ib0(X0, X1, X2, X3);
+ X0 ^= wKey[96]; X1 ^= wKey[97]; X2 ^= wKey[98]; X3 ^= wKey[99];
+ inverseLT(); ib7(X0, X1, X2, X3);
+ X0 ^= wKey[92]; X1 ^= wKey[93]; X2 ^= wKey[94]; X3 ^= wKey[95];
+ inverseLT(); ib6(X0, X1, X2, X3);
+ X0 ^= wKey[88]; X1 ^= wKey[89]; X2 ^= wKey[90]; X3 ^= wKey[91];
+ inverseLT(); ib5(X0, X1, X2, X3);
+ X0 ^= wKey[84]; X1 ^= wKey[85]; X2 ^= wKey[86]; X3 ^= wKey[87];
+ inverseLT(); ib4(X0, X1, X2, X3);
+ X0 ^= wKey[80]; X1 ^= wKey[81]; X2 ^= wKey[82]; X3 ^= wKey[83];
+ inverseLT(); ib3(X0, X1, X2, X3);
+ X0 ^= wKey[76]; X1 ^= wKey[77]; X2 ^= wKey[78]; X3 ^= wKey[79];
+ inverseLT(); ib2(X0, X1, X2, X3);
+ X0 ^= wKey[72]; X1 ^= wKey[73]; X2 ^= wKey[74]; X3 ^= wKey[75];
+ inverseLT(); ib1(X0, X1, X2, X3);
+ X0 ^= wKey[68]; X1 ^= wKey[69]; X2 ^= wKey[70]; X3 ^= wKey[71];
+ inverseLT(); ib0(X0, X1, X2, X3);
+ X0 ^= wKey[64]; X1 ^= wKey[65]; X2 ^= wKey[66]; X3 ^= wKey[67];
+ inverseLT(); ib7(X0, X1, X2, X3);
+ X0 ^= wKey[60]; X1 ^= wKey[61]; X2 ^= wKey[62]; X3 ^= wKey[63];
+ inverseLT(); ib6(X0, X1, X2, X3);
+ X0 ^= wKey[56]; X1 ^= wKey[57]; X2 ^= wKey[58]; X3 ^= wKey[59];
+ inverseLT(); ib5(X0, X1, X2, X3);
+ X0 ^= wKey[52]; X1 ^= wKey[53]; X2 ^= wKey[54]; X3 ^= wKey[55];
+ inverseLT(); ib4(X0, X1, X2, X3);
+ X0 ^= wKey[48]; X1 ^= wKey[49]; X2 ^= wKey[50]; X3 ^= wKey[51];
+ inverseLT(); ib3(X0, X1, X2, X3);
+ X0 ^= wKey[44]; X1 ^= wKey[45]; X2 ^= wKey[46]; X3 ^= wKey[47];
+ inverseLT(); ib2(X0, X1, X2, X3);
+ X0 ^= wKey[40]; X1 ^= wKey[41]; X2 ^= wKey[42]; X3 ^= wKey[43];
+ inverseLT(); ib1(X0, X1, X2, X3);
+ X0 ^= wKey[36]; X1 ^= wKey[37]; X2 ^= wKey[38]; X3 ^= wKey[39];
+ inverseLT(); ib0(X0, X1, X2, X3);
+ X0 ^= wKey[32]; X1 ^= wKey[33]; X2 ^= wKey[34]; X3 ^= wKey[35];
+ inverseLT(); ib7(X0, X1, X2, X3);
+ X0 ^= wKey[28]; X1 ^= wKey[29]; X2 ^= wKey[30]; X3 ^= wKey[31];
+ inverseLT(); ib6(X0, X1, X2, X3);
+ X0 ^= wKey[24]; X1 ^= wKey[25]; X2 ^= wKey[26]; X3 ^= wKey[27];
+ inverseLT(); ib5(X0, X1, X2, X3);
+ X0 ^= wKey[20]; X1 ^= wKey[21]; X2 ^= wKey[22]; X3 ^= wKey[23];
+ inverseLT(); ib4(X0, X1, X2, X3);
+ X0 ^= wKey[16]; X1 ^= wKey[17]; X2 ^= wKey[18]; X3 ^= wKey[19];
+ inverseLT(); ib3(X0, X1, X2, X3);
+ X0 ^= wKey[12]; X1 ^= wKey[13]; X2 ^= wKey[14]; X3 ^= wKey[15];
+ inverseLT(); ib2(X0, X1, X2, X3);
+ X0 ^= wKey[8]; X1 ^= wKey[9]; X2 ^= wKey[10]; X3 ^= wKey[11];
+ inverseLT(); ib1(X0, X1, X2, X3);
+ X0 ^= wKey[4]; X1 ^= wKey[5]; X2 ^= wKey[6]; X3 ^= wKey[7];
+ inverseLT(); ib0(X0, X1, X2, X3);
+
+ wordToBytes(X3 ^ wKey[3], out, outOff);
+ wordToBytes(X2 ^ wKey[2], out, outOff + 4);
+ wordToBytes(X1 ^ wKey[1], out, outOff + 8);
+ wordToBytes(X0 ^ wKey[0], out, outOff + 12);
+ }
+
+ /**
+ * The sboxes below are based on the work of Brian Gladman and
+ * Sam Simpson, whose original notice appears below.
+ * <p>
+ * For further details see:
+ * http://fp.gladman.plus.com/cryptography_technology/serpent/
+ */
+
+ /* Partially optimised Serpent S Box boolean functions derived */
+ /* using a recursive descent analyser but without a full search */
+ /* of all subtrees. This set of S boxes is the result of work */
+ /* by Sam Simpson and Brian Gladman using the spare time on a */
+ /* cluster of high capacity servers to search for S boxes with */
+ /* this customised search engine. There are now an average of */
+ /* 15.375 terms per S box. */
+ /* */
+ /* Copyright: Dr B. R Gladman (gladman@seven77.demon.co.uk) */
+ /* and Sam Simpson (s.simpson@mia.co.uk) */
+ /* 17th December 1998 */
+ /* */
+ /* We hereby give permission for information in this file to be */
+ /* used freely subject only to acknowledgement of its origin. */
+
+ /**
+ * S0 - { 3, 8,15, 1,10, 6, 5,11,14,13, 4, 2, 7, 0, 9,12 } - 15 terms.
+ */
+ private void sb0(int a, int b, int c, int d)
+ {
+ int t1 = a ^ d;
+ int t3 = c ^ t1;
+ int t4 = b ^ t3;
+ X3 = (a & d) ^ t4;
+ int t7 = a ^ (b & t1);
+ X2 = t4 ^ (c | t7);
+ int t12 = X3 & (t3 ^ t7);
+ X1 = (~t3) ^ t12;
+ X0 = t12 ^ (~t7);
+ }
+
+ /**
+ * InvSO - {13, 3,11, 0,10, 6, 5,12, 1,14, 4, 7,15, 9, 8, 2 } - 15 terms.
+ */
+ private void ib0(int a, int b, int c, int d)
+ {
+ int t1 = ~a;
+ int t2 = a ^ b;
+ int t4 = d ^ (t1 | t2);
+ int t5 = c ^ t4;
+ X2 = t2 ^ t5;
+ int t8 = t1 ^ (d & t2);
+ X1 = t4 ^ (X2 & t8);
+ X3 = (a & t4) ^ (t5 | X1);
+ X0 = X3 ^ (t5 ^ t8);
+ }
+
+ /**
+ * S1 - {15,12, 2, 7, 9, 0, 5,10, 1,11,14, 8, 6,13, 3, 4 } - 14 terms.
+ */
+ private void sb1(int a, int b, int c, int d)
+ {
+ int t2 = b ^ (~a);
+ int t5 = c ^ (a | t2);
+ X2 = d ^ t5;
+ int t7 = b ^ (d | t2);
+ int t8 = t2 ^ X2;
+ X3 = t8 ^ (t5 & t7);
+ int t11 = t5 ^ t7;
+ X1 = X3 ^ t11;
+ X0 = t5 ^ (t8 & t11);
+ }
+
+ /**
+ * InvS1 - { 5, 8, 2,14,15, 6,12, 3,11, 4, 7, 9, 1,13,10, 0 } - 14 steps.
+ */
+ private void ib1(int a, int b, int c, int d)
+ {
+ int t1 = b ^ d;
+ int t3 = a ^ (b & t1);
+ int t4 = t1 ^ t3;
+ X3 = c ^ t4;
+ int t7 = b ^ (t1 & t3);
+ int t8 = X3 | t7;
+ X1 = t3 ^ t8;
+ int t10 = ~X1;
+ int t11 = X3 ^ t7;
+ X0 = t10 ^ t11;
+ X2 = t4 ^ (t10 | t11);
+ }
+
+ /**
+ * S2 - { 8, 6, 7, 9, 3,12,10,15,13, 1,14, 4, 0,11, 5, 2 } - 16 terms.
+ */
+ private void sb2(int a, int b, int c, int d)
+ {
+ int t1 = ~a;
+ int t2 = b ^ d;
+ int t3 = c & t1;
+ X0 = t2 ^ t3;
+ int t5 = c ^ t1;
+ int t6 = c ^ X0;
+ int t7 = b & t6;
+ X3 = t5 ^ t7;
+ X2 = a ^ ((d | t7) & (X0 | t5));
+ X1 = (t2 ^ X3) ^ (X2 ^ (d | t1));
+ }
+
+ /**
+ * InvS2 - {12, 9,15, 4,11,14, 1, 2, 0, 3, 6,13, 5, 8,10, 7 } - 16 steps.
+ */
+ private void ib2(int a, int b, int c, int d)
+ {
+ int t1 = b ^ d;
+ int t2 = ~t1;
+ int t3 = a ^ c;
+ int t4 = c ^ t1;
+ int t5 = b & t4;
+ X0 = t3 ^ t5;
+ int t7 = a | t2;
+ int t8 = d ^ t7;
+ int t9 = t3 | t8;
+ X3 = t1 ^ t9;
+ int t11 = ~t4;
+ int t12 = X0 | X3;
+ X1 = t11 ^ t12;
+ X2 = (d & t11) ^ (t3 ^ t12);
+ }
+
+ /**
+ * S3 - { 0,15,11, 8,12, 9, 6, 3,13, 1, 2, 4,10, 7, 5,14 } - 16 terms.
+ */
+ private void sb3(int a, int b, int c, int d)
+ {
+ int t1 = a ^ b;
+ int t2 = a & c;
+ int t3 = a | d;
+ int t4 = c ^ d;
+ int t5 = t1 & t3;
+ int t6 = t2 | t5;
+ X2 = t4 ^ t6;
+ int t8 = b ^ t3;
+ int t9 = t6 ^ t8;
+ int t10 = t4 & t9;
+ X0 = t1 ^ t10;
+ int t12 = X2 & X0;
+ X1 = t9 ^ t12;
+ X3 = (b | d) ^ (t4 ^ t12);
+ }
+
+ /**
+ * InvS3 - { 0, 9,10, 7,11,14, 6,13, 3, 5,12, 2, 4, 8,15, 1 } - 15 terms
+ */
+ private void ib3(int a, int b, int c, int d)
+ {
+ int t1 = a | b;
+ int t2 = b ^ c;
+ int t3 = b & t2;
+ int t4 = a ^ t3;
+ int t5 = c ^ t4;
+ int t6 = d | t4;
+ X0 = t2 ^ t6;
+ int t8 = t2 | t6;
+ int t9 = d ^ t8;
+ X2 = t5 ^ t9;
+ int t11 = t1 ^ t9;
+ int t12 = X0 & t11;
+ X3 = t4 ^ t12;
+ X1 = X3 ^ (X0 ^ t11);
+ }
+
+ /**
+ * S4 - { 1,15, 8, 3,12, 0,11, 6, 2, 5, 4,10, 9,14, 7,13 } - 15 terms.
+ */
+ private void sb4(int a, int b, int c, int d)
+ {
+ int t1 = a ^ d;
+ int t2 = d & t1;
+ int t3 = c ^ t2;
+ int t4 = b | t3;
+ X3 = t1 ^ t4;
+ int t6 = ~b;
+ int t7 = t1 | t6;
+ X0 = t3 ^ t7;
+ int t9 = a & X0;
+ int t10 = t1 ^ t6;
+ int t11 = t4 & t10;
+ X2 = t9 ^ t11;
+ X1 = (a ^ t3) ^ (t10 & X2);
+ }
+
+ /**
+ * InvS4 - { 5, 0, 8, 3,10, 9, 7,14, 2,12,11, 6, 4,15,13, 1 } - 15 terms.
+ */
+ private void ib4(int a, int b, int c, int d)
+ {
+ int t1 = c | d;
+ int t2 = a & t1;
+ int t3 = b ^ t2;
+ int t4 = a & t3;
+ int t5 = c ^ t4;
+ X1 = d ^ t5;
+ int t7 = ~a;
+ int t8 = t5 & X1;
+ X3 = t3 ^ t8;
+ int t10 = X1 | t7;
+ int t11 = d ^ t10;
+ X0 = X3 ^ t11;
+ X2 = (t3 & t11) ^ (X1 ^ t7);
+ }
+
+ /**
+ * S5 - {15, 5, 2,11, 4,10, 9,12, 0, 3,14, 8,13, 6, 7, 1 } - 16 terms.
+ */
+ private void sb5(int a, int b, int c, int d)
+ {
+ int t1 = ~a;
+ int t2 = a ^ b;
+ int t3 = a ^ d;
+ int t4 = c ^ t1;
+ int t5 = t2 | t3;
+ X0 = t4 ^ t5;
+ int t7 = d & X0;
+ int t8 = t2 ^ X0;
+ X1 = t7 ^ t8;
+ int t10 = t1 | X0;
+ int t11 = t2 | t7;
+ int t12 = t3 ^ t10;
+ X2 = t11 ^ t12;
+ X3 = (b ^ t7) ^ (X1 & t12);
+ }
+
+ /**
+ * InvS5 - { 8,15, 2, 9, 4, 1,13,14,11, 6, 5, 3, 7,12,10, 0 } - 16 terms.
+ */
+ private void ib5(int a, int b, int c, int d)
+ {
+ int t1 = ~c;
+ int t2 = b & t1;
+ int t3 = d ^ t2;
+ int t4 = a & t3;
+ int t5 = b ^ t1;
+ X3 = t4 ^ t5;
+ int t7 = b | X3;
+ int t8 = a & t7;
+ X1 = t3 ^ t8;
+ int t10 = a | d;
+ int t11 = t1 ^ t7;
+ X0 = t10 ^ t11;
+ X2 = (b & t10) ^ (t4 | (a ^ c));
+ }
+
+ /**
+ * S6 - { 7, 2,12, 5, 8, 4, 6,11,14, 9, 1,15,13, 3,10, 0 } - 15 terms.
+ */
+ private void sb6(int a, int b, int c, int d)
+ {
+ int t1 = ~a;
+ int t2 = a ^ d;
+ int t3 = b ^ t2;
+ int t4 = t1 | t2;
+ int t5 = c ^ t4;
+ X1 = b ^ t5;
+ int t7 = t2 | X1;
+ int t8 = d ^ t7;
+ int t9 = t5 & t8;
+ X2 = t3 ^ t9;
+ int t11 = t5 ^ t8;
+ X0 = X2 ^ t11;
+ X3 = (~t5) ^ (t3 & t11);
+ }
+
+ /**
+ * InvS6 - {15,10, 1,13, 5, 3, 6, 0, 4, 9,14, 7, 2,12, 8,11 } - 15 terms.
+ */
+ private void ib6(int a, int b, int c, int d)
+ {
+ int t1 = ~a;
+ int t2 = a ^ b;
+ int t3 = c ^ t2;
+ int t4 = c | t1;
+ int t5 = d ^ t4;
+ X1 = t3 ^ t5;
+ int t7 = t3 & t5;
+ int t8 = t2 ^ t7;
+ int t9 = b | t8;
+ X3 = t5 ^ t9;
+ int t11 = b | X3;
+ X0 = t8 ^ t11;
+ X2 = (d & t1) ^ (t3 ^ t11);
+ }
+
+ /**
+ * S7 - { 1,13,15, 0,14, 8, 2,11, 7, 4,12,10, 9, 3, 5, 6 } - 16 terms.
+ */
+ private void sb7(int a, int b, int c, int d)
+ {
+ int t1 = b ^ c;
+ int t2 = c & t1;
+ int t3 = d ^ t2;
+ int t4 = a ^ t3;
+ int t5 = d | t1;
+ int t6 = t4 & t5;
+ X1 = b ^ t6;
+ int t8 = t3 | X1;
+ int t9 = a & t4;
+ X3 = t1 ^ t9;
+ int t11 = t4 ^ t8;
+ int t12 = X3 & t11;
+ X2 = t3 ^ t12;
+ X0 = (~t11) ^ (X3 & X2);
+ }
+
+ /**
+ * InvS7 - { 3, 0, 6,13, 9,14,15, 8, 5,12,11, 7,10, 1, 4, 2 } - 17 terms.
+ */
+ private void ib7(int a, int b, int c, int d)
+ {
+ int t3 = c | (a & b);
+ int t4 = d & (a | b);
+ X3 = t3 ^ t4;
+ int t6 = ~d;
+ int t7 = b ^ t4;
+ int t9 = t7 | (X3 ^ t6);
+ X1 = a ^ t9;
+ X0 = (c ^ t7) ^ (d | X1);
+ X2 = (t3 ^ X1) ^ (X0 ^ (a & X3));
+ }
+
+ /**
+ * Apply the linear transformation to the register set.
+ */
+ private void LT()
+ {
+ int x0 = rotateLeft(X0, 13);
+ int x2 = rotateLeft(X2, 3);
+ int x1 = X1 ^ x0 ^ x2 ;
+ int x3 = X3 ^ x2 ^ x0 << 3;
+
+ X1 = rotateLeft(x1, 1);
+ X3 = rotateLeft(x3, 7);
+ X0 = rotateLeft(x0 ^ X1 ^ X3, 5);
+ X2 = rotateLeft(x2 ^ X3 ^ (X1 << 7), 22);
+ }
+
+ /**
+ * Apply the inverse of the linear transformation to the register set.
+ */
+ private void inverseLT()
+ {
+ int x2 = rotateRight(X2, 22) ^ X3 ^ (X1 << 7);
+ int x0 = rotateRight(X0, 5) ^ X1 ^ X3;
+ int x3 = rotateRight(X3, 7);
+ int x1 = rotateRight(X1, 1);
+ X3 = x3 ^ x2 ^ x0 << 3;
+ X1 = x1 ^ x0 ^ x2;
+ X2 = rotateRight(x2, 3);
+ X0 = rotateRight(x0, 13);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/Shacal2Engine.java b/core/src/main/java/org/spongycastle/crypto/engines/Shacal2Engine.java
new file mode 100644
index 00000000..8b461f86
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/Shacal2Engine.java
@@ -0,0 +1,201 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/engines/SkipjackEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/SkipjackEngine.java
new file mode 100644
index 00000000..4f7a5f6b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/SkipjackEngine.java
@@ -0,0 +1,260 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+
+/**
+ * a class that provides a basic SKIPJACK engine.
+ */
+public class SkipjackEngine
+ implements BlockCipher
+{
+ static final int BLOCK_SIZE = 8;
+
+ static short ftable[] =
+ {
+ 0xa3, 0xd7, 0x09, 0x83, 0xf8, 0x48, 0xf6, 0xf4, 0xb3, 0x21, 0x15, 0x78, 0x99, 0xb1, 0xaf, 0xf9,
+ 0xe7, 0x2d, 0x4d, 0x8a, 0xce, 0x4c, 0xca, 0x2e, 0x52, 0x95, 0xd9, 0x1e, 0x4e, 0x38, 0x44, 0x28,
+ 0x0a, 0xdf, 0x02, 0xa0, 0x17, 0xf1, 0x60, 0x68, 0x12, 0xb7, 0x7a, 0xc3, 0xe9, 0xfa, 0x3d, 0x53,
+ 0x96, 0x84, 0x6b, 0xba, 0xf2, 0x63, 0x9a, 0x19, 0x7c, 0xae, 0xe5, 0xf5, 0xf7, 0x16, 0x6a, 0xa2,
+ 0x39, 0xb6, 0x7b, 0x0f, 0xc1, 0x93, 0x81, 0x1b, 0xee, 0xb4, 0x1a, 0xea, 0xd0, 0x91, 0x2f, 0xb8,
+ 0x55, 0xb9, 0xda, 0x85, 0x3f, 0x41, 0xbf, 0xe0, 0x5a, 0x58, 0x80, 0x5f, 0x66, 0x0b, 0xd8, 0x90,
+ 0x35, 0xd5, 0xc0, 0xa7, 0x33, 0x06, 0x65, 0x69, 0x45, 0x00, 0x94, 0x56, 0x6d, 0x98, 0x9b, 0x76,
+ 0x97, 0xfc, 0xb2, 0xc2, 0xb0, 0xfe, 0xdb, 0x20, 0xe1, 0xeb, 0xd6, 0xe4, 0xdd, 0x47, 0x4a, 0x1d,
+ 0x42, 0xed, 0x9e, 0x6e, 0x49, 0x3c, 0xcd, 0x43, 0x27, 0xd2, 0x07, 0xd4, 0xde, 0xc7, 0x67, 0x18,
+ 0x89, 0xcb, 0x30, 0x1f, 0x8d, 0xc6, 0x8f, 0xaa, 0xc8, 0x74, 0xdc, 0xc9, 0x5d, 0x5c, 0x31, 0xa4,
+ 0x70, 0x88, 0x61, 0x2c, 0x9f, 0x0d, 0x2b, 0x87, 0x50, 0x82, 0x54, 0x64, 0x26, 0x7d, 0x03, 0x40,
+ 0x34, 0x4b, 0x1c, 0x73, 0xd1, 0xc4, 0xfd, 0x3b, 0xcc, 0xfb, 0x7f, 0xab, 0xe6, 0x3e, 0x5b, 0xa5,
+ 0xad, 0x04, 0x23, 0x9c, 0x14, 0x51, 0x22, 0xf0, 0x29, 0x79, 0x71, 0x7e, 0xff, 0x8c, 0x0e, 0xe2,
+ 0x0c, 0xef, 0xbc, 0x72, 0x75, 0x6f, 0x37, 0xa1, 0xec, 0xd3, 0x8e, 0x62, 0x8b, 0x86, 0x10, 0xe8,
+ 0x08, 0x77, 0x11, 0xbe, 0x92, 0x4f, 0x24, 0xc5, 0x32, 0x36, 0x9d, 0xcf, 0xf3, 0xa6, 0xbb, 0xac,
+ 0x5e, 0x6c, 0xa9, 0x13, 0x57, 0x25, 0xb5, 0xe3, 0xbd, 0xa8, 0x3a, 0x01, 0x05, 0x59, 0x2a, 0x46
+ };
+
+ private int[] key0, key1, key2, key3;
+ private boolean encrypting;
+
+ /**
+ * initialise a SKIPJACK cipher.
+ *
+ * @param encrypting whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ {
+ if (!(params instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("invalid parameter passed to SKIPJACK init - " + params.getClass().getName());
+ }
+
+ byte[] keyBytes = ((KeyParameter)params).getKey();
+
+ this.encrypting = encrypting;
+ this.key0 = new int[32];
+ this.key1 = new int[32];
+ this.key2 = new int[32];
+ this.key3 = new int[32];
+
+ //
+ // expand the key to 128 bytes in 4 parts (saving us a modulo, multiply
+ // and an addition).
+ //
+ for (int i = 0; i < 32; i ++)
+ {
+ key0[i] = keyBytes[(i * 4) % 10] & 0xff;
+ key1[i] = keyBytes[(i * 4 + 1) % 10] & 0xff;
+ key2[i] = keyBytes[(i * 4 + 2) % 10] & 0xff;
+ key3[i] = keyBytes[(i * 4 + 3) % 10] & 0xff;
+ }
+ }
+
+ public String getAlgorithmName()
+ {
+ return "SKIPJACK";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (key1 == null)
+ {
+ throw new IllegalStateException("SKIPJACK engine not initialised");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ if (encrypting)
+ {
+ encryptBlock(in, inOff, out, outOff);
+ }
+ else
+ {
+ decryptBlock(in, inOff, out, outOff);
+ }
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+
+ /**
+ * The G permutation
+ */
+ private int g(
+ int k,
+ int w)
+ {
+ int g1, g2, g3, g4, g5, g6;
+
+ g1 = (w >> 8) & 0xff;
+ g2 = w & 0xff;
+
+ g3 = ftable[g2 ^ key0[k]] ^ g1;
+ g4 = ftable[g3 ^ key1[k]] ^ g2;
+ g5 = ftable[g4 ^ key2[k]] ^ g3;
+ g6 = ftable[g5 ^ key3[k]] ^ g4;
+
+ return ((g5 << 8) + g6);
+ }
+
+ public int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ int w1 = (in[inOff + 0] << 8) + (in[inOff + 1] & 0xff);
+ int w2 = (in[inOff + 2] << 8) + (in[inOff + 3] & 0xff);
+ int w3 = (in[inOff + 4] << 8) + (in[inOff + 5] & 0xff);
+ int w4 = (in[inOff + 6] << 8) + (in[inOff + 7] & 0xff);
+
+ int k = 0;
+
+ for (int t = 0; t < 2; t++)
+ {
+ for(int i = 0; i < 8; i++)
+ {
+ int tmp = w4;
+ w4 = w3;
+ w3 = w2;
+ w2 = g(k, w1);
+ w1 = w2 ^ tmp ^ (k + 1);
+ k++;
+ }
+
+ for(int i = 0; i < 8; i++)
+ {
+ int tmp = w4;
+ w4 = w3;
+ w3 = w1 ^ w2 ^ (k + 1);
+ w2 = g(k, w1);
+ w1 = tmp;
+ k++;
+ }
+ }
+
+ out[outOff + 0] = (byte)((w1 >> 8));
+ out[outOff + 1] = (byte)(w1);
+ out[outOff + 2] = (byte)((w2 >> 8));
+ out[outOff + 3] = (byte)(w2);
+ out[outOff + 4] = (byte)((w3 >> 8));
+ out[outOff + 5] = (byte)(w3);
+ out[outOff + 6] = (byte)((w4 >> 8));
+ out[outOff + 7] = (byte)(w4);
+
+ return BLOCK_SIZE;
+ }
+
+ /**
+ * the inverse of the G permutation.
+ */
+ private int h(
+ int k,
+ int w)
+ {
+ int h1, h2, h3, h4, h5, h6;
+
+ h1 = w & 0xff;
+ h2 = (w >> 8) & 0xff;
+
+ h3 = ftable[h2 ^ key3[k]] ^ h1;
+ h4 = ftable[h3 ^ key2[k]] ^ h2;
+ h5 = ftable[h4 ^ key1[k]] ^ h3;
+ h6 = ftable[h5 ^ key0[k]] ^ h4;
+
+ return ((h6 << 8) + h5);
+ }
+
+ public int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ int w2 = (in[inOff + 0] << 8) + (in[inOff + 1] & 0xff);
+ int w1 = (in[inOff + 2] << 8) + (in[inOff + 3] & 0xff);
+ int w4 = (in[inOff + 4] << 8) + (in[inOff + 5] & 0xff);
+ int w3 = (in[inOff + 6] << 8) + (in[inOff + 7] & 0xff);
+
+ int k = 31;
+
+ for (int t = 0; t < 2; t++)
+ {
+ for(int i = 0; i < 8; i++)
+ {
+ int tmp = w4;
+ w4 = w3;
+ w3 = w2;
+ w2 = h(k, w1);
+ w1 = w2 ^ tmp ^ (k + 1);
+ k--;
+ }
+
+ for(int i = 0; i < 8; i++)
+ {
+ int tmp = w4;
+ w4 = w3;
+ w3 = w1 ^ w2 ^ (k + 1);
+ w2 = h(k, w1);
+ w1 = tmp;
+ k--;
+ }
+ }
+
+ out[outOff + 0] = (byte)((w2 >> 8));
+ out[outOff + 1] = (byte)(w2);
+ out[outOff + 2] = (byte)((w1 >> 8));
+ out[outOff + 3] = (byte)(w1);
+ out[outOff + 4] = (byte)((w4 >> 8));
+ out[outOff + 5] = (byte)(w4);
+ out[outOff + 6] = (byte)((w3 >> 8));
+ out[outOff + 7] = (byte)(w3);
+
+ return BLOCK_SIZE;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/TEAEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/TEAEngine.java
new file mode 100644
index 00000000..a027edc9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/TEAEngine.java
@@ -0,0 +1,184 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+
+/**
+ * An TEA engine.
+ */
+public class TEAEngine
+ implements BlockCipher
+{
+ private static final int rounds = 32,
+ block_size = 8,
+// key_size = 16,
+ delta = 0x9E3779B9,
+ d_sum = 0xC6EF3720; // sum on decrypt
+ /*
+ * the expanded key array of 4 subkeys
+ */
+ private int _a, _b, _c, _d;
+ private boolean _initialised;
+ private boolean _forEncryption;
+
+ /**
+ * Create an instance of the TEA encryption algorithm
+ * and set some defaults
+ */
+ public TEAEngine()
+ {
+ _initialised = false;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "TEA";
+ }
+
+ public int getBlockSize()
+ {
+ return block_size;
+ }
+
+ /**
+ * initialise
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (!(params instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("invalid parameter passed to TEA init - " + params.getClass().getName());
+ }
+
+ _forEncryption = forEncryption;
+ _initialised = true;
+
+ KeyParameter p = (KeyParameter)params;
+
+ setKey(p.getKey());
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (!_initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName()+" not initialised");
+ }
+
+ if ((inOff + block_size) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + block_size) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ return (_forEncryption) ? encryptBlock(in, inOff, out, outOff)
+ : decryptBlock(in, inOff, out, outOff);
+ }
+
+ public void reset()
+ {
+ }
+
+ /**
+ * Re-key the cipher.
+ * <p>
+ * @param key the key to be used
+ */
+ 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);
+ _d = bytesToInt(key, 12);
+ }
+
+ private int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ // Pack bytes into integers
+ int v0 = bytesToInt(in, inOff);
+ int v1 = bytesToInt(in, inOff + 4);
+
+ int sum = 0;
+
+ for (int i = 0; i != rounds; i++)
+ {
+ sum += delta;
+ v0 += ((v1 << 4) + _a) ^ (v1 + sum) ^ ((v1 >>> 5) + _b);
+ v1 += ((v0 << 4) + _c) ^ (v0 + sum) ^ ((v0 >>> 5) + _d);
+ }
+
+ unpackInt(v0, out, outOff);
+ unpackInt(v1, out, outOff + 4);
+
+ return block_size;
+ }
+
+ private int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ // Pack bytes into integers
+ int v0 = bytesToInt(in, inOff);
+ int v1 = bytesToInt(in, inOff + 4);
+
+ int sum = d_sum;
+
+ for (int i = 0; i != rounds; i++)
+ {
+ v1 -= ((v0 << 4) + _c) ^ (v0 + sum) ^ ((v0 >>> 5) + _d);
+ v0 -= ((v1 << 4) + _a) ^ (v1 + sum) ^ ((v1 >>> 5) + _b);
+ sum -= delta;
+ }
+
+ unpackInt(v0, out, outOff);
+ unpackInt(v1, out, outOff + 4);
+
+ return block_size;
+ }
+
+ private int bytesToInt(byte[] in, int inOff)
+ {
+ return ((in[inOff++]) << 24) |
+ ((in[inOff++] & 255) << 16) |
+ ((in[inOff++] & 255) << 8) |
+ ((in[inOff] & 255));
+ }
+
+ private void unpackInt(int v, byte[] out, int outOff)
+ {
+ out[outOff++] = (byte)(v >>> 24);
+ out[outOff++] = (byte)(v >>> 16);
+ out[outOff++] = (byte)(v >>> 8);
+ out[outOff ] = (byte)v;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/ThreefishEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/ThreefishEngine.java
new file mode 100644
index 00000000..40e08b9b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/ThreefishEngine.java
@@ -0,0 +1,1494 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/engines/TwofishEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/TwofishEngine.java
new file mode 100644
index 00000000..c5b84385
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/TwofishEngine.java
@@ -0,0 +1,680 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+
+/**
+ * A class that provides Twofish encryption operations.
+ *
+ * This Java implementation is based on the Java reference
+ * implementation provided by Bruce Schneier and developed
+ * by Raif S. Naffah.
+ */
+public final class TwofishEngine
+ implements BlockCipher
+{
+ private static final byte[][] P = {
+ { // p0
+ (byte) 0xA9, (byte) 0x67, (byte) 0xB3, (byte) 0xE8,
+ (byte) 0x04, (byte) 0xFD, (byte) 0xA3, (byte) 0x76,
+ (byte) 0x9A, (byte) 0x92, (byte) 0x80, (byte) 0x78,
+ (byte) 0xE4, (byte) 0xDD, (byte) 0xD1, (byte) 0x38,
+ (byte) 0x0D, (byte) 0xC6, (byte) 0x35, (byte) 0x98,
+ (byte) 0x18, (byte) 0xF7, (byte) 0xEC, (byte) 0x6C,
+ (byte) 0x43, (byte) 0x75, (byte) 0x37, (byte) 0x26,
+ (byte) 0xFA, (byte) 0x13, (byte) 0x94, (byte) 0x48,
+ (byte) 0xF2, (byte) 0xD0, (byte) 0x8B, (byte) 0x30,
+ (byte) 0x84, (byte) 0x54, (byte) 0xDF, (byte) 0x23,
+ (byte) 0x19, (byte) 0x5B, (byte) 0x3D, (byte) 0x59,
+ (byte) 0xF3, (byte) 0xAE, (byte) 0xA2, (byte) 0x82,
+ (byte) 0x63, (byte) 0x01, (byte) 0x83, (byte) 0x2E,
+ (byte) 0xD9, (byte) 0x51, (byte) 0x9B, (byte) 0x7C,
+ (byte) 0xA6, (byte) 0xEB, (byte) 0xA5, (byte) 0xBE,
+ (byte) 0x16, (byte) 0x0C, (byte) 0xE3, (byte) 0x61,
+ (byte) 0xC0, (byte) 0x8C, (byte) 0x3A, (byte) 0xF5,
+ (byte) 0x73, (byte) 0x2C, (byte) 0x25, (byte) 0x0B,
+ (byte) 0xBB, (byte) 0x4E, (byte) 0x89, (byte) 0x6B,
+ (byte) 0x53, (byte) 0x6A, (byte) 0xB4, (byte) 0xF1,
+ (byte) 0xE1, (byte) 0xE6, (byte) 0xBD, (byte) 0x45,
+ (byte) 0xE2, (byte) 0xF4, (byte) 0xB6, (byte) 0x66,
+ (byte) 0xCC, (byte) 0x95, (byte) 0x03, (byte) 0x56,
+ (byte) 0xD4, (byte) 0x1C, (byte) 0x1E, (byte) 0xD7,
+ (byte) 0xFB, (byte) 0xC3, (byte) 0x8E, (byte) 0xB5,
+ (byte) 0xE9, (byte) 0xCF, (byte) 0xBF, (byte) 0xBA,
+ (byte) 0xEA, (byte) 0x77, (byte) 0x39, (byte) 0xAF,
+ (byte) 0x33, (byte) 0xC9, (byte) 0x62, (byte) 0x71,
+ (byte) 0x81, (byte) 0x79, (byte) 0x09, (byte) 0xAD,
+ (byte) 0x24, (byte) 0xCD, (byte) 0xF9, (byte) 0xD8,
+ (byte) 0xE5, (byte) 0xC5, (byte) 0xB9, (byte) 0x4D,
+ (byte) 0x44, (byte) 0x08, (byte) 0x86, (byte) 0xE7,
+ (byte) 0xA1, (byte) 0x1D, (byte) 0xAA, (byte) 0xED,
+ (byte) 0x06, (byte) 0x70, (byte) 0xB2, (byte) 0xD2,
+ (byte) 0x41, (byte) 0x7B, (byte) 0xA0, (byte) 0x11,
+ (byte) 0x31, (byte) 0xC2, (byte) 0x27, (byte) 0x90,
+ (byte) 0x20, (byte) 0xF6, (byte) 0x60, (byte) 0xFF,
+ (byte) 0x96, (byte) 0x5C, (byte) 0xB1, (byte) 0xAB,
+ (byte) 0x9E, (byte) 0x9C, (byte) 0x52, (byte) 0x1B,
+ (byte) 0x5F, (byte) 0x93, (byte) 0x0A, (byte) 0xEF,
+ (byte) 0x91, (byte) 0x85, (byte) 0x49, (byte) 0xEE,
+ (byte) 0x2D, (byte) 0x4F, (byte) 0x8F, (byte) 0x3B,
+ (byte) 0x47, (byte) 0x87, (byte) 0x6D, (byte) 0x46,
+ (byte) 0xD6, (byte) 0x3E, (byte) 0x69, (byte) 0x64,
+ (byte) 0x2A, (byte) 0xCE, (byte) 0xCB, (byte) 0x2F,
+ (byte) 0xFC, (byte) 0x97, (byte) 0x05, (byte) 0x7A,
+ (byte) 0xAC, (byte) 0x7F, (byte) 0xD5, (byte) 0x1A,
+ (byte) 0x4B, (byte) 0x0E, (byte) 0xA7, (byte) 0x5A,
+ (byte) 0x28, (byte) 0x14, (byte) 0x3F, (byte) 0x29,
+ (byte) 0x88, (byte) 0x3C, (byte) 0x4C, (byte) 0x02,
+ (byte) 0xB8, (byte) 0xDA, (byte) 0xB0, (byte) 0x17,
+ (byte) 0x55, (byte) 0x1F, (byte) 0x8A, (byte) 0x7D,
+ (byte) 0x57, (byte) 0xC7, (byte) 0x8D, (byte) 0x74,
+ (byte) 0xB7, (byte) 0xC4, (byte) 0x9F, (byte) 0x72,
+ (byte) 0x7E, (byte) 0x15, (byte) 0x22, (byte) 0x12,
+ (byte) 0x58, (byte) 0x07, (byte) 0x99, (byte) 0x34,
+ (byte) 0x6E, (byte) 0x50, (byte) 0xDE, (byte) 0x68,
+ (byte) 0x65, (byte) 0xBC, (byte) 0xDB, (byte) 0xF8,
+ (byte) 0xC8, (byte) 0xA8, (byte) 0x2B, (byte) 0x40,
+ (byte) 0xDC, (byte) 0xFE, (byte) 0x32, (byte) 0xA4,
+ (byte) 0xCA, (byte) 0x10, (byte) 0x21, (byte) 0xF0,
+ (byte) 0xD3, (byte) 0x5D, (byte) 0x0F, (byte) 0x00,
+ (byte) 0x6F, (byte) 0x9D, (byte) 0x36, (byte) 0x42,
+ (byte) 0x4A, (byte) 0x5E, (byte) 0xC1, (byte) 0xE0 },
+ { // p1
+ (byte) 0x75, (byte) 0xF3, (byte) 0xC6, (byte) 0xF4,
+ (byte) 0xDB, (byte) 0x7B, (byte) 0xFB, (byte) 0xC8,
+ (byte) 0x4A, (byte) 0xD3, (byte) 0xE6, (byte) 0x6B,
+ (byte) 0x45, (byte) 0x7D, (byte) 0xE8, (byte) 0x4B,
+ (byte) 0xD6, (byte) 0x32, (byte) 0xD8, (byte) 0xFD,
+ (byte) 0x37, (byte) 0x71, (byte) 0xF1, (byte) 0xE1,
+ (byte) 0x30, (byte) 0x0F, (byte) 0xF8, (byte) 0x1B,
+ (byte) 0x87, (byte) 0xFA, (byte) 0x06, (byte) 0x3F,
+ (byte) 0x5E, (byte) 0xBA, (byte) 0xAE, (byte) 0x5B,
+ (byte) 0x8A, (byte) 0x00, (byte) 0xBC, (byte) 0x9D,
+ (byte) 0x6D, (byte) 0xC1, (byte) 0xB1, (byte) 0x0E,
+ (byte) 0x80, (byte) 0x5D, (byte) 0xD2, (byte) 0xD5,
+ (byte) 0xA0, (byte) 0x84, (byte) 0x07, (byte) 0x14,
+ (byte) 0xB5, (byte) 0x90, (byte) 0x2C, (byte) 0xA3,
+ (byte) 0xB2, (byte) 0x73, (byte) 0x4C, (byte) 0x54,
+ (byte) 0x92, (byte) 0x74, (byte) 0x36, (byte) 0x51,
+ (byte) 0x38, (byte) 0xB0, (byte) 0xBD, (byte) 0x5A,
+ (byte) 0xFC, (byte) 0x60, (byte) 0x62, (byte) 0x96,
+ (byte) 0x6C, (byte) 0x42, (byte) 0xF7, (byte) 0x10,
+ (byte) 0x7C, (byte) 0x28, (byte) 0x27, (byte) 0x8C,
+ (byte) 0x13, (byte) 0x95, (byte) 0x9C, (byte) 0xC7,
+ (byte) 0x24, (byte) 0x46, (byte) 0x3B, (byte) 0x70,
+ (byte) 0xCA, (byte) 0xE3, (byte) 0x85, (byte) 0xCB,
+ (byte) 0x11, (byte) 0xD0, (byte) 0x93, (byte) 0xB8,
+ (byte) 0xA6, (byte) 0x83, (byte) 0x20, (byte) 0xFF,
+ (byte) 0x9F, (byte) 0x77, (byte) 0xC3, (byte) 0xCC,
+ (byte) 0x03, (byte) 0x6F, (byte) 0x08, (byte) 0xBF,
+ (byte) 0x40, (byte) 0xE7, (byte) 0x2B, (byte) 0xE2,
+ (byte) 0x79, (byte) 0x0C, (byte) 0xAA, (byte) 0x82,
+ (byte) 0x41, (byte) 0x3A, (byte) 0xEA, (byte) 0xB9,
+ (byte) 0xE4, (byte) 0x9A, (byte) 0xA4, (byte) 0x97,
+ (byte) 0x7E, (byte) 0xDA, (byte) 0x7A, (byte) 0x17,
+ (byte) 0x66, (byte) 0x94, (byte) 0xA1, (byte) 0x1D,
+ (byte) 0x3D, (byte) 0xF0, (byte) 0xDE, (byte) 0xB3,
+ (byte) 0x0B, (byte) 0x72, (byte) 0xA7, (byte) 0x1C,
+ (byte) 0xEF, (byte) 0xD1, (byte) 0x53, (byte) 0x3E,
+ (byte) 0x8F, (byte) 0x33, (byte) 0x26, (byte) 0x5F,
+ (byte) 0xEC, (byte) 0x76, (byte) 0x2A, (byte) 0x49,
+ (byte) 0x81, (byte) 0x88, (byte) 0xEE, (byte) 0x21,
+ (byte) 0xC4, (byte) 0x1A, (byte) 0xEB, (byte) 0xD9,
+ (byte) 0xC5, (byte) 0x39, (byte) 0x99, (byte) 0xCD,
+ (byte) 0xAD, (byte) 0x31, (byte) 0x8B, (byte) 0x01,
+ (byte) 0x18, (byte) 0x23, (byte) 0xDD, (byte) 0x1F,
+ (byte) 0x4E, (byte) 0x2D, (byte) 0xF9, (byte) 0x48,
+ (byte) 0x4F, (byte) 0xF2, (byte) 0x65, (byte) 0x8E,
+ (byte) 0x78, (byte) 0x5C, (byte) 0x58, (byte) 0x19,
+ (byte) 0x8D, (byte) 0xE5, (byte) 0x98, (byte) 0x57,
+ (byte) 0x67, (byte) 0x7F, (byte) 0x05, (byte) 0x64,
+ (byte) 0xAF, (byte) 0x63, (byte) 0xB6, (byte) 0xFE,
+ (byte) 0xF5, (byte) 0xB7, (byte) 0x3C, (byte) 0xA5,
+ (byte) 0xCE, (byte) 0xE9, (byte) 0x68, (byte) 0x44,
+ (byte) 0xE0, (byte) 0x4D, (byte) 0x43, (byte) 0x69,
+ (byte) 0x29, (byte) 0x2E, (byte) 0xAC, (byte) 0x15,
+ (byte) 0x59, (byte) 0xA8, (byte) 0x0A, (byte) 0x9E,
+ (byte) 0x6E, (byte) 0x47, (byte) 0xDF, (byte) 0x34,
+ (byte) 0x35, (byte) 0x6A, (byte) 0xCF, (byte) 0xDC,
+ (byte) 0x22, (byte) 0xC9, (byte) 0xC0, (byte) 0x9B,
+ (byte) 0x89, (byte) 0xD4, (byte) 0xED, (byte) 0xAB,
+ (byte) 0x12, (byte) 0xA2, (byte) 0x0D, (byte) 0x52,
+ (byte) 0xBB, (byte) 0x02, (byte) 0x2F, (byte) 0xA9,
+ (byte) 0xD7, (byte) 0x61, (byte) 0x1E, (byte) 0xB4,
+ (byte) 0x50, (byte) 0x04, (byte) 0xF6, (byte) 0xC2,
+ (byte) 0x16, (byte) 0x25, (byte) 0x86, (byte) 0x56,
+ (byte) 0x55, (byte) 0x09, (byte) 0xBE, (byte) 0x91 }
+ };
+
+ /**
+ * Define the fixed p0/p1 permutations used in keyed S-box lookup.
+ * By changing the following constant definitions, the S-boxes will
+ * automatically get changed in the Twofish engine.
+ */
+ private static final int P_00 = 1;
+ private static final int P_01 = 0;
+ private static final int P_02 = 0;
+ private static final int P_03 = P_01 ^ 1;
+ private static final int P_04 = 1;
+
+ private static final int P_10 = 0;
+ private static final int P_11 = 0;
+ private static final int P_12 = 1;
+ private static final int P_13 = P_11 ^ 1;
+ private static final int P_14 = 0;
+
+ private static final int P_20 = 1;
+ private static final int P_21 = 1;
+ private static final int P_22 = 0;
+ private static final int P_23 = P_21 ^ 1;
+ private static final int P_24 = 0;
+
+ private static final int P_30 = 0;
+ private static final int P_31 = 1;
+ private static final int P_32 = 1;
+ private static final int P_33 = P_31 ^ 1;
+ private static final int P_34 = 1;
+
+ /* Primitive polynomial for GF(256) */
+ private static final int GF256_FDBK = 0x169;
+ private static final int GF256_FDBK_2 = GF256_FDBK / 2;
+ private static final int GF256_FDBK_4 = GF256_FDBK / 4;
+
+ private static final int RS_GF_FDBK = 0x14D; // field generator
+
+ //====================================
+ // Useful constants
+ //====================================
+
+ private static final int ROUNDS = 16;
+ private static final int MAX_ROUNDS = 16; // bytes = 128 bits
+ private static final int BLOCK_SIZE = 16; // bytes = 128 bits
+ private static final int MAX_KEY_BITS = 256;
+
+ private static final int INPUT_WHITEN=0;
+ private static final int OUTPUT_WHITEN=INPUT_WHITEN+BLOCK_SIZE/4; // 4
+ private static final int ROUND_SUBKEYS=OUTPUT_WHITEN+BLOCK_SIZE/4;// 8
+
+ private static final int TOTAL_SUBKEYS=ROUND_SUBKEYS+2*MAX_ROUNDS;// 40
+
+ private static final int SK_STEP = 0x02020202;
+ private static final int SK_BUMP = 0x01010101;
+ private static final int SK_ROTL = 9;
+
+ private boolean encrypting = false;
+
+ private int[] gMDS0 = new int[MAX_KEY_BITS];
+ private int[] gMDS1 = new int[MAX_KEY_BITS];
+ private int[] gMDS2 = new int[MAX_KEY_BITS];
+ private int[] gMDS3 = new int[MAX_KEY_BITS];
+
+ /**
+ * gSubKeys[] and gSBox[] are eventually used in the
+ * encryption and decryption methods.
+ */
+ private int[] gSubKeys;
+ private int[] gSBox;
+
+ private int k64Cnt = 0;
+
+ private byte[] workingKey = null;
+
+ public TwofishEngine()
+ {
+ // calculate the MDS matrix
+ int[] m1 = new int[2];
+ int[] mX = new int[2];
+ int[] mY = new int[2];
+ int j;
+
+ for (int i=0; i< MAX_KEY_BITS ; i++)
+ {
+ j = P[0][i] & 0xff;
+ m1[0] = j;
+ mX[0] = Mx_X(j) & 0xff;
+ mY[0] = Mx_Y(j) & 0xff;
+
+ j = P[1][i] & 0xff;
+ m1[1] = j;
+ mX[1] = Mx_X(j) & 0xff;
+ mY[1] = Mx_Y(j) & 0xff;
+
+ gMDS0[i] = m1[P_00] | mX[P_00] << 8 |
+ mY[P_00] << 16 | mY[P_00] << 24;
+
+ gMDS1[i] = mY[P_10] | mY[P_10] << 8 |
+ mX[P_10] << 16 | m1[P_10] << 24;
+
+ gMDS2[i] = mX[P_20] | mY[P_20] << 8 |
+ m1[P_20] << 16 | mY[P_20] << 24;
+
+ gMDS3[i] = mX[P_30] | m1[P_30] << 8 |
+ mY[P_30] << 16 | mX[P_30] << 24;
+ }
+ }
+
+ /**
+ * initialise a Twofish cipher.
+ *
+ * @param encrypting whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ {
+ if (params instanceof KeyParameter)
+ {
+ this.encrypting = encrypting;
+ this.workingKey = ((KeyParameter)params).getKey();
+ this.k64Cnt = (this.workingKey.length / 8); // pre-padded ?
+ setKey(this.workingKey);
+
+ return;
+ }
+
+ throw new IllegalArgumentException("invalid parameter passed to Twofish init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Twofish";
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (workingKey == null)
+ {
+ throw new IllegalStateException("Twofish not initialised");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ if (encrypting)
+ {
+ encryptBlock(in, inOff, out, outOff);
+ }
+ else
+ {
+ decryptBlock(in, inOff, out, outOff);
+ }
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ if (this.workingKey != null)
+ {
+ setKey(this.workingKey);
+ }
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ //==================================
+ // Private Implementation
+ //==================================
+
+ private void setKey(byte[] key)
+ {
+ int[] k32e = new int[MAX_KEY_BITS/64]; // 4
+ int[] k32o = new int[MAX_KEY_BITS/64]; // 4
+
+ int[] sBoxKeys = new int[MAX_KEY_BITS/64]; // 4
+ gSubKeys = new int[TOTAL_SUBKEYS];
+
+ if (k64Cnt < 1)
+ {
+ throw new IllegalArgumentException("Key size less than 64 bits");
+ }
+
+ if (k64Cnt > 4)
+ {
+ throw new IllegalArgumentException("Key size larger than 256 bits");
+ }
+
+ /*
+ * k64Cnt is the number of 8 byte blocks (64 chunks)
+ * that are in the input key. The input key is a
+ * maximum of 32 bytes (256 bits), so the range
+ * for k64Cnt is 1..4
+ */
+ for (int i=0; i<k64Cnt ; i++)
+ {
+ int p = i* 8;
+
+ k32e[i] = BytesTo32Bits(key, p);
+ k32o[i] = BytesTo32Bits(key, p+4);
+
+ sBoxKeys[k64Cnt-1-i] = RS_MDS_Encode(k32e[i], k32o[i]);
+ }
+
+ int q,A,B;
+ for (int i=0; i < TOTAL_SUBKEYS / 2 ; i++)
+ {
+ q = i*SK_STEP;
+ A = F32(q, k32e);
+ B = F32(q+SK_BUMP, k32o);
+ B = B << 8 | B >>> 24;
+ A += B;
+ gSubKeys[i*2] = A;
+ A += B;
+ gSubKeys[i*2 + 1] = A << SK_ROTL | A >>> (32-SK_ROTL);
+ }
+
+ /*
+ * fully expand the table for speed
+ */
+ int k0 = sBoxKeys[0];
+ int k1 = sBoxKeys[1];
+ int k2 = sBoxKeys[2];
+ int k3 = sBoxKeys[3];
+ int b0, b1, b2, b3;
+ gSBox = new int[4*MAX_KEY_BITS];
+ for (int i=0; i<MAX_KEY_BITS; i++)
+ {
+ b0 = b1 = b2 = b3 = i;
+ switch (k64Cnt & 3)
+ {
+ case 1:
+ gSBox[i*2] = gMDS0[(P[P_01][b0] & 0xff) ^ b0(k0)];
+ gSBox[i*2+1] = gMDS1[(P[P_11][b1] & 0xff) ^ b1(k0)];
+ gSBox[i*2+0x200] = gMDS2[(P[P_21][b2] & 0xff) ^ b2(k0)];
+ gSBox[i*2+0x201] = gMDS3[(P[P_31][b3] & 0xff) ^ b3(k0)];
+ break;
+ case 0: // 256 bits of key
+ b0 = (P[P_04][b0] & 0xff) ^ b0(k3);
+ b1 = (P[P_14][b1] & 0xff) ^ b1(k3);
+ b2 = (P[P_24][b2] & 0xff) ^ b2(k3);
+ b3 = (P[P_34][b3] & 0xff) ^ b3(k3);
+ // fall through, having pre-processed b[0]..b[3] with k32[3]
+ case 3: // 192 bits of key
+ b0 = (P[P_03][b0] & 0xff) ^ b0(k2);
+ b1 = (P[P_13][b1] & 0xff) ^ b1(k2);
+ b2 = (P[P_23][b2] & 0xff) ^ b2(k2);
+ b3 = (P[P_33][b3] & 0xff) ^ b3(k2);
+ // fall through, having pre-processed b[0]..b[3] with k32[2]
+ case 2: // 128 bits of key
+ gSBox[i*2] = gMDS0[(P[P_01]
+ [(P[P_02][b0] & 0xff) ^ b0(k1)] & 0xff) ^ b0(k0)];
+ gSBox[i*2+1] = gMDS1[(P[P_11]
+ [(P[P_12][b1] & 0xff) ^ b1(k1)] & 0xff) ^ b1(k0)];
+ gSBox[i*2+0x200] = gMDS2[(P[P_21]
+ [(P[P_22][b2] & 0xff) ^ b2(k1)] & 0xff) ^ b2(k0)];
+ gSBox[i*2+0x201] = gMDS3[(P[P_31]
+ [(P[P_32][b3] & 0xff) ^ b3(k1)] & 0xff) ^ b3(k0)];
+ break;
+ }
+ }
+
+ /*
+ * the function exits having setup the gSBox with the
+ * input key material.
+ */
+ }
+
+ /**
+ * Encrypt the given input starting at the given offset and place
+ * the result in the provided buffer starting at the given offset.
+ * The input will be an exact multiple of our blocksize.
+ *
+ * encryptBlock uses the pre-calculated gSBox[] and subKey[]
+ * arrays.
+ */
+ private void encryptBlock(
+ byte[] src,
+ int srcIndex,
+ byte[] dst,
+ int dstIndex)
+ {
+ int x0 = BytesTo32Bits(src, srcIndex) ^ gSubKeys[INPUT_WHITEN];
+ int x1 = BytesTo32Bits(src, srcIndex + 4) ^ gSubKeys[INPUT_WHITEN + 1];
+ int x2 = BytesTo32Bits(src, srcIndex + 8) ^ gSubKeys[INPUT_WHITEN + 2];
+ int x3 = BytesTo32Bits(src, srcIndex + 12) ^ gSubKeys[INPUT_WHITEN + 3];
+
+ int k = ROUND_SUBKEYS;
+ int t0, t1;
+ for (int r = 0; r < ROUNDS; r +=2)
+ {
+ t0 = Fe32_0(x0);
+ t1 = Fe32_3(x1);
+ x2 ^= t0 + t1 + gSubKeys[k++];
+ x2 = x2 >>>1 | x2 << 31;
+ x3 = (x3 << 1 | x3 >>> 31) ^ (t0 + 2*t1 + gSubKeys[k++]);
+
+ t0 = Fe32_0(x2);
+ t1 = Fe32_3(x3);
+ x0 ^= t0 + t1 + gSubKeys[k++];
+ x0 = x0 >>>1 | x0 << 31;
+ x1 = (x1 << 1 | x1 >>> 31) ^ (t0 + 2*t1 + gSubKeys[k++]);
+ }
+
+ Bits32ToBytes(x2 ^ gSubKeys[OUTPUT_WHITEN], dst, dstIndex);
+ Bits32ToBytes(x3 ^ gSubKeys[OUTPUT_WHITEN + 1], dst, dstIndex + 4);
+ Bits32ToBytes(x0 ^ gSubKeys[OUTPUT_WHITEN + 2], dst, dstIndex + 8);
+ Bits32ToBytes(x1 ^ gSubKeys[OUTPUT_WHITEN + 3], dst, dstIndex + 12);
+ }
+
+ /**
+ * Decrypt the given input starting at the given offset and place
+ * the result in the provided buffer starting at the given offset.
+ * The input will be an exact multiple of our blocksize.
+ */
+ private void decryptBlock(
+ byte[] src,
+ int srcIndex,
+ byte[] dst,
+ int dstIndex)
+ {
+ int x2 = BytesTo32Bits(src, srcIndex) ^ gSubKeys[OUTPUT_WHITEN];
+ int x3 = BytesTo32Bits(src, srcIndex+4) ^ gSubKeys[OUTPUT_WHITEN + 1];
+ int x0 = BytesTo32Bits(src, srcIndex+8) ^ gSubKeys[OUTPUT_WHITEN + 2];
+ int x1 = BytesTo32Bits(src, srcIndex+12) ^ gSubKeys[OUTPUT_WHITEN + 3];
+
+ int k = ROUND_SUBKEYS + 2 * ROUNDS -1 ;
+ int t0, t1;
+ for (int r = 0; r< ROUNDS ; r +=2)
+ {
+ t0 = Fe32_0(x2);
+ t1 = Fe32_3(x3);
+ x1 ^= t0 + 2*t1 + gSubKeys[k--];
+ x0 = (x0 << 1 | x0 >>> 31) ^ (t0 + t1 + gSubKeys[k--]);
+ x1 = x1 >>>1 | x1 << 31;
+
+ t0 = Fe32_0(x0);
+ t1 = Fe32_3(x1);
+ x3 ^= t0 + 2*t1 + gSubKeys[k--];
+ x2 = (x2 << 1 | x2 >>> 31) ^ (t0 + t1 + gSubKeys[k--]);
+ x3 = x3 >>>1 | x3 << 31;
+ }
+
+ Bits32ToBytes(x0 ^ gSubKeys[INPUT_WHITEN], dst, dstIndex);
+ Bits32ToBytes(x1 ^ gSubKeys[INPUT_WHITEN + 1], dst, dstIndex + 4);
+ Bits32ToBytes(x2 ^ gSubKeys[INPUT_WHITEN + 2], dst, dstIndex + 8);
+ Bits32ToBytes(x3 ^ gSubKeys[INPUT_WHITEN + 3], dst, dstIndex + 12);
+ }
+
+ /*
+ * TODO: This can be optimised and made cleaner by combining
+ * the functionality in this function and applying it appropriately
+ * to the creation of the subkeys during key setup.
+ */
+ private int F32(int x, int[] k32)
+ {
+ int b0 = b0(x);
+ int b1 = b1(x);
+ int b2 = b2(x);
+ int b3 = b3(x);
+ int k0 = k32[0];
+ int k1 = k32[1];
+ int k2 = k32[2];
+ int k3 = k32[3];
+
+ int result = 0;
+ switch (k64Cnt & 3)
+ {
+ case 1:
+ result = gMDS0[(P[P_01][b0] & 0xff) ^ b0(k0)] ^
+ gMDS1[(P[P_11][b1] & 0xff) ^ b1(k0)] ^
+ gMDS2[(P[P_21][b2] & 0xff) ^ b2(k0)] ^
+ gMDS3[(P[P_31][b3] & 0xff) ^ b3(k0)];
+ break;
+ case 0: /* 256 bits of key */
+ b0 = (P[P_04][b0] & 0xff) ^ b0(k3);
+ b1 = (P[P_14][b1] & 0xff) ^ b1(k3);
+ b2 = (P[P_24][b2] & 0xff) ^ b2(k3);
+ b3 = (P[P_34][b3] & 0xff) ^ b3(k3);
+ case 3:
+ b0 = (P[P_03][b0] & 0xff) ^ b0(k2);
+ b1 = (P[P_13][b1] & 0xff) ^ b1(k2);
+ b2 = (P[P_23][b2] & 0xff) ^ b2(k2);
+ b3 = (P[P_33][b3] & 0xff) ^ b3(k2);
+ case 2:
+ result =
+ gMDS0[(P[P_01][(P[P_02][b0]&0xff)^b0(k1)]&0xff)^b0(k0)] ^
+ gMDS1[(P[P_11][(P[P_12][b1]&0xff)^b1(k1)]&0xff)^b1(k0)] ^
+ gMDS2[(P[P_21][(P[P_22][b2]&0xff)^b2(k1)]&0xff)^b2(k0)] ^
+ gMDS3[(P[P_31][(P[P_32][b3]&0xff)^b3(k1)]&0xff)^b3(k0)];
+ break;
+ }
+ return result;
+ }
+
+ /**
+ * Use (12, 8) Reed-Solomon code over GF(256) to produce
+ * a key S-box 32-bit entity from 2 key material 32-bit
+ * entities.
+ *
+ * @param k0 first 32-bit entity
+ * @param k1 second 32-bit entity
+ * @return Remainder polynomial generated using RS code
+ */
+ private int RS_MDS_Encode(int k0, int k1)
+ {
+ int r = k1;
+ for (int i = 0 ; i < 4 ; i++) // shift 1 byte at a time
+ {
+ r = RS_rem(r);
+ }
+ r ^= k0;
+ for (int i=0 ; i < 4 ; i++)
+ {
+ r = RS_rem(r);
+ }
+
+ return r;
+ }
+
+ /**
+ * Reed-Solomon code parameters: (12,8) reversible code:<p>
+ * <pre>
+ * g(x) = x^4 + (a+1/a)x^3 + ax^2 + (a+1/a)x + 1
+ * </pre>
+ * where a = primitive root of field generator 0x14D
+ */
+ private int RS_rem(int x)
+ {
+ int b = (x >>> 24) & 0xff;
+ int g2 = ((b << 1) ^
+ ((b & 0x80) != 0 ? RS_GF_FDBK : 0)) & 0xff;
+ int g3 = ((b >>> 1) ^
+ ((b & 0x01) != 0 ? (RS_GF_FDBK >>> 1) : 0)) ^ g2 ;
+ return ((x << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b);
+ }
+
+ private int LFSR1(int x)
+ {
+ return (x >> 1) ^
+ (((x & 0x01) != 0) ? GF256_FDBK_2 : 0);
+ }
+
+ private int LFSR2(int x)
+ {
+ return (x >> 2) ^
+ (((x & 0x02) != 0) ? GF256_FDBK_2 : 0) ^
+ (((x & 0x01) != 0) ? GF256_FDBK_4 : 0);
+ }
+
+ private int Mx_X(int x)
+ {
+ return x ^ LFSR2(x);
+ } // 5B
+
+ private int Mx_Y(int x)
+ {
+ return x ^ LFSR1(x) ^ LFSR2(x);
+ } // EF
+
+ private int b0(int x)
+ {
+ return x & 0xff;
+ }
+
+ private int b1(int x)
+ {
+ return (x >>> 8) & 0xff;
+ }
+
+ private int b2(int x)
+ {
+ return (x >>> 16) & 0xff;
+ }
+
+ private int b3(int x)
+ {
+ return (x >>> 24) & 0xff;
+ }
+
+ private int Fe32_0(int x)
+ {
+ return gSBox[ 0x000 + 2*(x & 0xff) ] ^
+ gSBox[ 0x001 + 2*((x >>> 8) & 0xff) ] ^
+ gSBox[ 0x200 + 2*((x >>> 16) & 0xff) ] ^
+ gSBox[ 0x201 + 2*((x >>> 24) & 0xff) ];
+ }
+
+ private int Fe32_3(int x)
+ {
+ return gSBox[ 0x000 + 2*((x >>> 24) & 0xff) ] ^
+ gSBox[ 0x001 + 2*(x & 0xff) ] ^
+ gSBox[ 0x200 + 2*((x >>> 8) & 0xff) ] ^
+ gSBox[ 0x201 + 2*((x >>> 16) & 0xff) ];
+ }
+
+ private int BytesTo32Bits(byte[] b, int p)
+ {
+ return ((b[p] & 0xff)) |
+ ((b[p+1] & 0xff) << 8) |
+ ((b[p+2] & 0xff) << 16) |
+ ((b[p+3] & 0xff) << 24);
+ }
+
+ private void Bits32ToBytes(int in, byte[] b, int offset)
+ {
+ b[offset] = (byte)in;
+ b[offset + 1] = (byte)(in >> 8);
+ b[offset + 2] = (byte)(in >> 16);
+ b[offset + 3] = (byte)(in >> 24);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/VMPCEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/VMPCEngine.java
new file mode 100644
index 00000000..f1a4a564
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/VMPCEngine.java
@@ -0,0 +1,142 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.StreamCipher;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+
+public class VMPCEngine implements StreamCipher
+{
+ /*
+ * variables to hold the state of the VMPC engine during encryption and
+ * decryption
+ */
+ protected byte n = 0;
+ protected byte[] P = null;
+ protected byte s = 0;
+
+ protected byte[] workingIV;
+ protected byte[] workingKey;
+
+ public String getAlgorithmName()
+ {
+ return "VMPC";
+ }
+
+ /**
+ * initialise a VMPC cipher.
+ *
+ * @param forEncryption
+ * whether or not we are for encryption.
+ * @param params
+ * the parameters required to set up the cipher.
+ * @exception IllegalArgumentException
+ * if the params argument is inappropriate.
+ */
+ public void init(boolean forEncryption, CipherParameters params)
+ {
+ if (!(params instanceof ParametersWithIV))
+ {
+ throw new IllegalArgumentException(
+ "VMPC init parameters must include an IV");
+ }
+
+ ParametersWithIV ivParams = (ParametersWithIV) params;
+
+ if (!(ivParams.getParameters() instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException(
+ "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)
+ {
+ throw new IllegalArgumentException("VMPC requires 1 to 768 bytes of IV");
+ }
+
+ this.workingKey = key.getKey();
+
+ initKey(this.workingKey, this.workingIV);
+ }
+
+ protected void initKey(byte[] keyBytes, byte[] ivBytes)
+ {
+ s = 0;
+ P = new byte[256];
+ for (int i = 0; i < 256; i++)
+ {
+ P[i] = (byte) i;
+ }
+
+ for (int m = 0; m < 768; m++)
+ {
+ s = P[(s + P[m & 0xff] + keyBytes[m % keyBytes.length]) & 0xff];
+ byte temp = P[m & 0xff];
+ P[m & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ }
+ for (int m = 0; m < 768; m++)
+ {
+ s = P[(s + P[m & 0xff] + ivBytes[m % ivBytes.length]) & 0xff];
+ byte temp = P[m & 0xff];
+ P[m & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ }
+ n = 0;
+ }
+
+ public int processBytes(byte[] in, int inOff, int len, byte[] out,
+ int outOff)
+ {
+ if ((inOff + len) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + len) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ for (int i = 0; i < len; i++)
+ {
+ s = P[(s + P[n & 0xff]) & 0xff];
+ byte z = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff];
+ // encryption
+ byte temp = P[n & 0xff];
+ P[n & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ n = (byte) ((n + 1) & 0xff);
+
+ // xor
+ out[i + outOff] = (byte) (in[i + inOff] ^ z);
+ }
+
+ return len;
+ }
+
+ public void reset()
+ {
+ initKey(this.workingKey, this.workingIV);
+ }
+
+ public byte returnByte(byte in)
+ {
+ s = P[(s + P[n & 0xff]) & 0xff];
+ byte z = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff];
+ // encryption
+ byte temp = P[n & 0xff];
+ P[n & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ n = (byte) ((n + 1) & 0xff);
+
+ // xor
+ return (byte) (in ^ z);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/VMPCKSA3Engine.java b/core/src/main/java/org/spongycastle/crypto/engines/VMPCKSA3Engine.java
new file mode 100644
index 00000000..2e03fdbb
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/VMPCKSA3Engine.java
@@ -0,0 +1,45 @@
+package org.spongycastle.crypto.engines;
+
+public class VMPCKSA3Engine extends VMPCEngine
+{
+ public String getAlgorithmName()
+ {
+ return "VMPC-KSA3";
+ }
+
+ protected void initKey(byte[] keyBytes, byte[] ivBytes)
+ {
+ s = 0;
+ P = new byte[256];
+ for (int i = 0; i < 256; i++)
+ {
+ P[i] = (byte) i;
+ }
+
+ for (int m = 0; m < 768; m++)
+ {
+ s = P[(s + P[m & 0xff] + keyBytes[m % keyBytes.length]) & 0xff];
+ byte temp = P[m & 0xff];
+ P[m & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ }
+
+ for (int m = 0; m < 768; m++)
+ {
+ s = P[(s + P[m & 0xff] + ivBytes[m % ivBytes.length]) & 0xff];
+ byte temp = P[m & 0xff];
+ P[m & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ }
+
+ for (int m = 0; m < 768; m++)
+ {
+ s = P[(s + P[m & 0xff] + keyBytes[m % keyBytes.length]) & 0xff];
+ byte temp = P[m & 0xff];
+ P[m & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ }
+
+ n = 0;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/XSalsa20Engine.java b/core/src/main/java/org/spongycastle/crypto/engines/XSalsa20Engine.java
new file mode 100644
index 00000000..f70022b9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/XSalsa20Engine.java
@@ -0,0 +1,65 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.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 == null)
+ {
+ throw new IllegalArgumentException(getAlgorithmName() + " doesn't support re-init with null key");
+ }
+
+ 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);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/XTEAEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/XTEAEngine.java
new file mode 100644
index 00000000..5dcb4ea1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/XTEAEngine.java
@@ -0,0 +1,188 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+
+/**
+ * An XTEA engine.
+ */
+public class XTEAEngine
+ implements BlockCipher
+{
+ private static final int rounds = 32,
+ block_size = 8,
+// key_size = 16,
+ delta = 0x9E3779B9;
+
+ /*
+ * the expanded key array of 4 subkeys
+ */
+ private int[] _S = new int[4],
+ _sum0 = new int[32],
+ _sum1 = new int[32];
+ private boolean _initialised,
+ _forEncryption;
+
+ /**
+ * Create an instance of the TEA encryption algorithm
+ * and set some defaults
+ */
+ public XTEAEngine()
+ {
+ _initialised = false;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "XTEA";
+ }
+
+ public int getBlockSize()
+ {
+ return block_size;
+ }
+
+ /**
+ * initialise
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (!(params instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("invalid parameter passed to TEA init - " + params.getClass().getName());
+ }
+
+ _forEncryption = forEncryption;
+ _initialised = true;
+
+ KeyParameter p = (KeyParameter)params;
+
+ setKey(p.getKey());
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (!_initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName()+" not initialised");
+ }
+
+ if ((inOff + block_size) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + block_size) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ return (_forEncryption) ? encryptBlock(in, inOff, out, outOff)
+ : decryptBlock(in, inOff, out, outOff);
+ }
+
+ public void reset()
+ {
+ }
+
+ /**
+ * Re-key the cipher.
+ * <p>
+ * @param key the key to be used
+ */
+ 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)
+ {
+ _S[i] = bytesToInt(key, j);
+ }
+
+ for (i = j = 0; i < rounds; i++)
+ {
+ _sum0[i] = (j + _S[j & 3]);
+ j += delta;
+ _sum1[i] = (j + _S[j >>> 11 & 3]);
+ }
+ }
+
+ private int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ // Pack bytes into integers
+ int v0 = bytesToInt(in, inOff);
+ int v1 = bytesToInt(in, inOff + 4);
+
+ for (int i = 0; i < rounds; i++)
+ {
+ v0 += ((v1 << 4 ^ v1 >>> 5) + v1) ^ _sum0[i];
+ v1 += ((v0 << 4 ^ v0 >>> 5) + v0) ^ _sum1[i];
+ }
+
+ unpackInt(v0, out, outOff);
+ unpackInt(v1, out, outOff + 4);
+
+ return block_size;
+ }
+
+ private int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ // Pack bytes into integers
+ int v0 = bytesToInt(in, inOff);
+ int v1 = bytesToInt(in, inOff + 4);
+
+ for (int i = rounds-1; i >= 0; i--)
+ {
+ v1 -= ((v0 << 4 ^ v0 >>> 5) + v0) ^ _sum1[i];
+ v0 -= ((v1 << 4 ^ v1 >>> 5) + v1) ^ _sum0[i];
+ }
+
+ unpackInt(v0, out, outOff);
+ unpackInt(v1, out, outOff + 4);
+
+ return block_size;
+ }
+
+ private int bytesToInt(byte[] in, int inOff)
+ {
+ return ((in[inOff++]) << 24) |
+ ((in[inOff++] & 255) << 16) |
+ ((in[inOff++] & 255) << 8) |
+ ((in[inOff] & 255));
+ }
+
+ private void unpackInt(int v, byte[] out, int outOff)
+ {
+ out[outOff++] = (byte)(v >>> 24);
+ out[outOff++] = (byte)(v >>> 16);
+ out[outOff++] = (byte)(v >>> 8);
+ out[outOff ] = (byte)v;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/examples/DESExample.java b/core/src/main/java/org/spongycastle/crypto/examples/DESExample.java
new file mode 100644
index 00000000..f05ffbdf
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/examples/DESExample.java
@@ -0,0 +1,421 @@
+package org.spongycastle.crypto.examples;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.crypto.engines.DESedeEngine;
+import org.spongycastle.crypto.generators.DESedeKeyGenerator;
+import org.spongycastle.crypto.modes.CBCBlockCipher;
+import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
+import org.spongycastle.crypto.params.DESedeParameters;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.encoders.Hex;
+
+/**
+ * DESExample is a simple DES based encryptor/decryptor.
+ * <p>
+ * The program is command line driven, with the input
+ * and output files specified on the command line.
+ * <pre>
+ * java org.spongycastle.crypto.examples.DESExample infile outfile [keyfile]
+ * </pre>
+ * A new key is generated for each encryption, if key is not specified,
+ * then the example will assume encryption is required, and as output
+ * create deskey.dat in the current directory. This key is a hex
+ * encoded byte-stream that is used for the decryption. The output
+ * file is Hex encoded, 60 characters wide text file.
+ * <p>
+ * When encrypting;
+ * <ul>
+ * <li>the infile is expected to be a byte stream (text or binary)
+ * <li>there is no keyfile specified on the input line
+ * </ul>
+ * <p>
+ * When decrypting;
+ * <ul>
+ * <li>the infile is expected to be the 60 character wide base64
+ * encoded file
+ * <li>the keyfile is expected to be a base64 encoded file
+ * </ul>
+ * <p>
+ * This example shows how to use the light-weight API, DES and
+ * the filesystem for message encryption and decryption.
+ *
+ */
+public class DESExample extends Object
+{
+ // Encrypting or decrypting ?
+ private boolean encrypt = true;
+
+ // To hold the initialised DESede cipher
+ private PaddedBufferedBlockCipher cipher = null;
+
+ // The input stream of bytes to be processed for encryption
+ private BufferedInputStream in = null;
+
+ // The output stream of bytes to be procssed
+ private BufferedOutputStream out = null;
+
+ // The key
+ private byte[] key = null;
+
+ /*
+ * start the application
+ */
+ public static void main(String[] args)
+ {
+ boolean encrypt = true;
+ String infile = null;
+ String outfile = null;
+ String keyfile = null;
+
+ if (args.length < 2)
+ {
+ DESExample de = new DESExample();
+ System.err.println("Usage: java "+de.getClass().getName()+
+ " infile outfile [keyfile]");
+ System.exit(1);
+ }
+
+ keyfile = "deskey.dat";
+ infile = args[0];
+ outfile = args[1];
+
+ if (args.length > 2)
+ {
+ encrypt = false;
+ keyfile = args[2];
+ }
+
+ DESExample de = new DESExample(infile, outfile, keyfile, encrypt);
+ de.process();
+ }
+
+ // Default constructor, used for the usage message
+ public DESExample()
+ {
+ }
+
+ /*
+ * Constructor, that takes the arguments appropriate for
+ * processing the command line directives.
+ */
+ public DESExample(
+ String infile,
+ String outfile,
+ String keyfile,
+ boolean encrypt)
+ {
+ /*
+ * First, determine that infile & keyfile exist as appropriate.
+ *
+ * This will also create the BufferedInputStream as required
+ * for reading the input file. All input files are treated
+ * as if they are binary, even if they contain text, it's the
+ * bytes that are encrypted.
+ */
+ this.encrypt = encrypt;
+ try
+ {
+ in = new BufferedInputStream(new FileInputStream(infile));
+ }
+ catch (FileNotFoundException fnf)
+ {
+ System.err.println("Input file not found ["+infile+"]");
+ System.exit(1);
+ }
+
+ try
+ {
+ out = new BufferedOutputStream(new FileOutputStream(outfile));
+ }
+ catch (IOException fnf)
+ {
+ System.err.println("Output file not created ["+outfile+"]");
+ System.exit(1);
+ }
+
+ if (encrypt)
+ {
+ try
+ {
+ /*
+ * The process of creating a new key requires a
+ * number of steps.
+ *
+ * First, create the parameters for the key generator
+ * which are a secure random number generator, and
+ * the length of the key (in bits).
+ */
+ SecureRandom sr = null;
+ try
+ {
+ sr = new SecureRandom();
+ /*
+ * This following call to setSeed() makes the
+ * initialisation of the SecureRandom object
+ * _very_ fast, but not secure AT ALL.
+ *
+ * Remove the line, recreate the class file and
+ * then run DESExample again to see the difference.
+ *
+ * The initialisation of a SecureRandom object
+ * can take 5 or more seconds depending on the
+ * CPU that the program is running on. That can
+ * be annoying during unit testing.
+ * -- jon
+ */
+ sr.setSeed("www.bouncycastle.org".getBytes());
+ }
+ catch (Exception nsa)
+ {
+ System.err.println("Hmmm, no SHA1PRNG, you need the "+
+ "Sun implementation");
+ System.exit(1);
+ }
+ KeyGenerationParameters kgp = new KeyGenerationParameters(
+ sr,
+ DESedeParameters.DES_EDE_KEY_LENGTH*8);
+
+ /*
+ * Second, initialise the key generator with the parameters
+ */
+ DESedeKeyGenerator kg = new DESedeKeyGenerator();
+ kg.init(kgp);
+
+ /*
+ * Third, and finally, generate the key
+ */
+ key = kg.generateKey();
+
+ /*
+ * We can now output the key to the file, but first
+ * hex encode the key so that we can have a look
+ * at it with a text editor if we so desire
+ */
+ BufferedOutputStream keystream =
+ new BufferedOutputStream(new FileOutputStream(keyfile));
+ byte[] keyhex = Hex.encode(key);
+ keystream.write(keyhex, 0, keyhex.length);
+ keystream.flush();
+ keystream.close();
+ }
+ catch (IOException createKey)
+ {
+ System.err.println("Could not decryption create key file "+
+ "["+keyfile+"]");
+ System.exit(1);
+ }
+ }
+ else
+ {
+ try
+ {
+ // read the key, and decode from hex encoding
+ BufferedInputStream keystream =
+ new BufferedInputStream(new FileInputStream(keyfile));
+ int len = keystream.available();
+ byte[] keyhex = new byte[len];
+ keystream.read(keyhex, 0, len);
+ key = Hex.decode(keyhex);
+ }
+ catch (IOException ioe)
+ {
+ System.err.println("Decryption key file not found, "+
+ "or not valid ["+keyfile+"]");
+ System.exit(1);
+ }
+ }
+ }
+
+ private void process()
+ {
+ /*
+ * Setup the DESede cipher engine, create a PaddedBufferedBlockCipher
+ * in CBC mode.
+ */
+ cipher = new PaddedBufferedBlockCipher(
+ new CBCBlockCipher(new DESedeEngine()));
+
+ /*
+ * The input and output streams are currently set up
+ * appropriately, and the key bytes are ready to be
+ * used.
+ *
+ */
+
+ if (encrypt)
+ {
+ performEncrypt(key);
+ }
+ else
+ {
+ performDecrypt(key);
+ }
+
+ // after processing clean up the files
+ try
+ {
+ in.close();
+ out.flush();
+ out.close();
+ }
+ catch (IOException closing)
+ {
+
+ }
+ }
+
+ /*
+ * This method performs all the encryption and writes
+ * the cipher text to the buffered output stream created
+ * previously.
+ */
+ private void performEncrypt(byte[] key)
+ {
+ // initialise the cipher with the key bytes, for encryption
+ cipher.init(true, new KeyParameter(key));
+
+ /*
+ * Create some temporary byte arrays for use in
+ * encryption, make them a reasonable size so that
+ * we don't spend forever reading small chunks from
+ * a file.
+ *
+ * There is no particular reason for using getBlockSize()
+ * to determine the size of the input chunk. It just
+ * was a convenient number for the example.
+ */
+ // int inBlockSize = cipher.getBlockSize() * 5;
+ int inBlockSize = 47;
+ int outBlockSize = cipher.getOutputSize(inBlockSize);
+
+ byte[] inblock = new byte[inBlockSize];
+ byte[] outblock = new byte[outBlockSize];
+
+ /*
+ * now, read the file, and output the chunks
+ */
+ try
+ {
+ int inL;
+ int outL;
+ byte[] rv = null;
+ while ((inL=in.read(inblock, 0, inBlockSize)) > 0)
+ {
+ outL = cipher.processBytes(inblock, 0, inL, outblock, 0);
+ /*
+ * Before we write anything out, we need to make sure
+ * that we've got something to write out.
+ */
+ if (outL > 0)
+ {
+ rv = Hex.encode(outblock, 0, outL);
+ out.write(rv, 0, rv.length);
+ out.write('\n');
+ }
+ }
+
+ try
+ {
+ /*
+ * Now, process the bytes that are still buffered
+ * within the cipher.
+ */
+ outL = cipher.doFinal(outblock, 0);
+ if (outL > 0)
+ {
+ rv = Hex.encode(outblock, 0, outL);
+ out.write(rv, 0, rv.length);
+ out.write('\n');
+ }
+ }
+ catch (CryptoException ce)
+ {
+
+ }
+ }
+ catch (IOException ioeread)
+ {
+ ioeread.printStackTrace();
+ }
+ }
+
+ /*
+ * This method performs all the decryption and writes
+ * the plain text to the buffered output stream created
+ * previously.
+ */
+ private void performDecrypt(byte[] key)
+ {
+ // initialise the cipher for decryption
+ cipher.init(false, new KeyParameter(key));
+
+ /*
+ * As the decryption is from our preformatted file,
+ * and we know that it's a hex encoded format, then
+ * we wrap the InputStream with a BufferedReader
+ * so that we can read it easily.
+ */
+ BufferedReader br = new BufferedReader(new InputStreamReader(in));
+
+ /*
+ * now, read the file, and output the chunks
+ */
+ try
+ {
+ int outL;
+ byte[] inblock = null;
+ byte[] outblock = null;
+ String rv = null;
+ while ((rv = br.readLine()) != null)
+ {
+ inblock = Hex.decode(rv);
+ outblock = new byte[cipher.getOutputSize(inblock.length)];
+
+ outL = cipher.processBytes(inblock, 0, inblock.length,
+ outblock, 0);
+ /*
+ * Before we write anything out, we need to make sure
+ * that we've got something to write out.
+ */
+ if (outL > 0)
+ {
+ out.write(outblock, 0, outL);
+ }
+ }
+
+ try
+ {
+ /*
+ * Now, process the bytes that are still buffered
+ * within the cipher.
+ */
+ outL = cipher.doFinal(outblock, 0);
+ if (outL > 0)
+ {
+ out.write(outblock, 0, outL);
+ }
+ }
+ catch (CryptoException ce)
+ {
+
+ }
+ }
+ catch (IOException ioeread)
+ {
+ ioeread.printStackTrace();
+ }
+ }
+
+}
+
diff --git a/core/src/main/java/org/spongycastle/crypto/examples/JPAKEExample.java b/core/src/main/java/org/spongycastle/crypto/examples/JPAKEExample.java
new file mode 100644
index 00000000..53654f51
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/examples/JPAKEExample.java
@@ -0,0 +1,214 @@
+package org.spongycastle.crypto.examples;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroup;
+import org.spongycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroups;
+import org.spongycastle.crypto.agreement.jpake.JPAKEParticipant;
+import org.spongycastle.crypto.agreement.jpake.JPAKERound1Payload;
+import org.spongycastle.crypto.agreement.jpake.JPAKERound2Payload;
+import org.spongycastle.crypto.agreement.jpake.JPAKERound3Payload;
+import org.spongycastle.crypto.digests.SHA256Digest;
+
+/**
+ * An example of a J-PAKE exchange.
+ * <p>
+ *
+ * In this example, both Alice and Bob are on the same computer (in the same JVM, in fact).
+ * In reality, Alice and Bob would be in different locations,
+ * and would be sending their generated payloads to each other.
+ */
+public class JPAKEExample
+{
+
+ public static void main(String args[]) throws CryptoException
+ {
+ /*
+ * Initialization
+ *
+ * Pick an appropriate prime order group to use throughout the exchange.
+ * Note that both participants must use the same group.
+ */
+ JPAKEPrimeOrderGroup group = JPAKEPrimeOrderGroups.NIST_3072;
+
+ BigInteger p = group.getP();
+ BigInteger q = group.getQ();
+ BigInteger g = group.getG();
+
+ String alicePassword = "password";
+ String bobPassword = "password";
+
+ System.out.println("********* Initialization **********");
+ System.out.println("Public parameters for the cyclic group:");
+ System.out.println("p (" + p.bitLength() + " bits): " + p.toString(16));
+ System.out.println("q (" + q.bitLength() + " bits): " + q.toString(16));
+ System.out.println("g (" + p.bitLength() + " bits): " + g.toString(16));
+ System.out.println("p mod q = " + p.mod(q).toString(16));
+ System.out.println("g^{q} mod p = " + g.modPow(q, p).toString(16));
+ System.out.println("");
+
+ System.out.println("(Secret passwords used by Alice and Bob: " +
+ "\"" + alicePassword + "\" and \"" + bobPassword + "\")\n");
+
+ /*
+ * Both participants must use the same hashing algorithm.
+ */
+ Digest digest = new SHA256Digest();
+ SecureRandom random = new SecureRandom();
+
+ JPAKEParticipant alice = new JPAKEParticipant("alice", alicePassword.toCharArray(), group, digest, random);
+ JPAKEParticipant bob = new JPAKEParticipant("bob", bobPassword.toCharArray(), group, digest, random);
+
+ /*
+ * Round 1
+ *
+ * Alice and Bob each generate a round 1 payload, and send it to each other.
+ */
+
+ JPAKERound1Payload aliceRound1Payload = alice.createRound1PayloadToSend();
+ JPAKERound1Payload bobRound1Payload = bob.createRound1PayloadToSend();
+
+ System.out.println("************ Round 1 **************");
+ System.out.println("Alice sends to Bob: ");
+ System.out.println("g^{x1}=" + aliceRound1Payload.getGx1().toString(16));
+ System.out.println("g^{x2}=" + aliceRound1Payload.getGx2().toString(16));
+ System.out.println("KP{x1}={" + aliceRound1Payload.getKnowledgeProofForX1()[0].toString(16) + "};{" + aliceRound1Payload.getKnowledgeProofForX1()[1].toString(16) + "}");
+ System.out.println("KP{x2}={" + aliceRound1Payload.getKnowledgeProofForX2()[0].toString(16) + "};{" + aliceRound1Payload.getKnowledgeProofForX2()[1].toString(16) + "}");
+ System.out.println("");
+
+ System.out.println("Bob sends to Alice: ");
+ System.out.println("g^{x3}=" + bobRound1Payload.getGx1().toString(16));
+ System.out.println("g^{x4}=" + bobRound1Payload.getGx2().toString(16));
+ System.out.println("KP{x3}={" + bobRound1Payload.getKnowledgeProofForX1()[0].toString(16) + "};{" + bobRound1Payload.getKnowledgeProofForX1()[1].toString(16) + "}");
+ System.out.println("KP{x4}={" + bobRound1Payload.getKnowledgeProofForX2()[0].toString(16) + "};{" + bobRound1Payload.getKnowledgeProofForX2()[1].toString(16) + "}");
+ System.out.println("");
+
+ /*
+ * Each participant must then validate the received payload for round 1
+ */
+
+ alice.validateRound1PayloadReceived(bobRound1Payload);
+ System.out.println("Alice checks g^{x4}!=1: OK");
+ System.out.println("Alice checks KP{x3}: OK");
+ System.out.println("Alice checks KP{x4}: OK");
+ System.out.println("");
+
+ bob.validateRound1PayloadReceived(aliceRound1Payload);
+ System.out.println("Bob checks g^{x2}!=1: OK");
+ System.out.println("Bob checks KP{x1},: OK");
+ System.out.println("Bob checks KP{x2},: OK");
+ System.out.println("");
+
+ /*
+ * Round 2
+ *
+ * Alice and Bob each generate a round 2 payload, and send it to each other.
+ */
+
+ JPAKERound2Payload aliceRound2Payload = alice.createRound2PayloadToSend();
+ JPAKERound2Payload bobRound2Payload = bob.createRound2PayloadToSend();
+
+ System.out.println("************ Round 2 **************");
+ System.out.println("Alice sends to Bob: ");
+ System.out.println("A=" + aliceRound2Payload.getA().toString(16));
+ System.out.println("KP{x2*s}={" + aliceRound2Payload.getKnowledgeProofForX2s()[0].toString(16) + "},{" + aliceRound2Payload.getKnowledgeProofForX2s()[1].toString(16) + "}");
+ System.out.println("");
+
+ System.out.println("Bob sends to Alice");
+ System.out.println("B=" + bobRound2Payload.getA().toString(16));
+ System.out.println("KP{x4*s}={" + bobRound2Payload.getKnowledgeProofForX2s()[0].toString(16) + "},{" + bobRound2Payload.getKnowledgeProofForX2s()[1].toString(16) + "}");
+ System.out.println("");
+
+ /*
+ * Each participant must then validate the received payload for round 2
+ */
+
+ alice.validateRound2PayloadReceived(bobRound2Payload);
+ System.out.println("Alice checks KP{x4*s}: OK\n");
+
+ bob.validateRound2PayloadReceived(aliceRound2Payload);
+ System.out.println("Bob checks KP{x2*s}: OK\n");
+
+ /*
+ * After round 2, each participant computes the keying material.
+ */
+
+ BigInteger aliceKeyingMaterial = alice.calculateKeyingMaterial();
+ BigInteger bobKeyingMaterial = bob.calculateKeyingMaterial();
+
+ System.out.println("********* After round 2 ***********");
+ System.out.println("Alice computes key material \t K=" + aliceKeyingMaterial.toString(16));
+ System.out.println("Bob computes key material \t K=" + bobKeyingMaterial.toString(16));
+ System.out.println();
+
+
+ /*
+ * You must derive a session key from the keying material applicable
+ * to whatever encryption algorithm you want to use.
+ */
+
+ BigInteger aliceKey = deriveSessionKey(aliceKeyingMaterial);
+ BigInteger bobKey = deriveSessionKey(bobKeyingMaterial);
+
+ /*
+ * At this point, you can stop and use the session keys if you want.
+ * This is implicit key confirmation.
+ *
+ * If you want to explicitly confirm that the key material matches,
+ * you can continue on and perform round 3.
+ */
+
+ /*
+ * Round 3
+ *
+ * Alice and Bob each generate a round 3 payload, and send it to each other.
+ */
+
+ JPAKERound3Payload aliceRound3Payload = alice.createRound3PayloadToSend(aliceKeyingMaterial);
+ JPAKERound3Payload bobRound3Payload = bob.createRound3PayloadToSend(bobKeyingMaterial);
+
+ System.out.println("************ Round 3 **************");
+ System.out.println("Alice sends to Bob: ");
+ System.out.println("MacTag=" + aliceRound3Payload.getMacTag().toString(16));
+ System.out.println("");
+ System.out.println("Bob sends to Alice: ");
+ System.out.println("MacTag=" + bobRound3Payload.getMacTag().toString(16));
+ System.out.println("");
+
+ /*
+ * Each participant must then validate the received payload for round 3
+ */
+
+ alice.validateRound3PayloadReceived(bobRound3Payload, aliceKeyingMaterial);
+ System.out.println("Alice checks MacTag: OK\n");
+
+ bob.validateRound3PayloadReceived(aliceRound3Payload, bobKeyingMaterial);
+ System.out.println("Bob checks MacTag: OK\n");
+
+ System.out.println();
+ System.out.println("MacTags validated, therefore the keying material matches.");
+ }
+
+ private static BigInteger deriveSessionKey(BigInteger keyingMaterial)
+ {
+ /*
+ * You should use a secure key derivation function (KDF) to derive the session key.
+ *
+ * For the purposes of this example, I'm just going to use a hash of the keying material.
+ */
+ SHA256Digest digest = new SHA256Digest();
+
+ byte[] keyByteArray = keyingMaterial.toByteArray();
+
+ byte[] output = new byte[digest.getDigestSize()];
+
+ digest.update(keyByteArray, 0, keyByteArray.length);
+
+ digest.doFinal(output, 0);
+
+ return new BigInteger(output);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/BaseKDFBytesGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/BaseKDFBytesGenerator.java
new file mode 100644
index 00000000..0d1577cd
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/BaseKDFBytesGenerator.java
@@ -0,0 +1,143 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.DerivationParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.DigestDerivationFunction;
+import org.spongycastle.crypto.params.ISO18033KDFParameters;
+import org.spongycastle.crypto.params.KDFParameters;
+import org.spongycastle.util.Pack;
+
+/**
+ * Basic KDF generator for derived keys and ivs as defined by IEEE P1363a/ISO
+ * 18033 <br>
+ * This implementation is based on ISO 18033/P1363a.
+ */
+public class BaseKDFBytesGenerator
+ implements DigestDerivationFunction
+{
+ private int counterStart;
+ private Digest digest;
+ private byte[] shared;
+ private byte[] iv;
+
+ /**
+ * Construct a KDF Parameters generator.
+ * <p>
+ *
+ * @param counterStart
+ * value of counter.
+ * @param digest
+ * the digest to be used as the source of derived keys.
+ */
+ protected BaseKDFBytesGenerator(int counterStart, Digest digest)
+ {
+ this.counterStart = counterStart;
+ this.digest = digest;
+ }
+
+ public void init(DerivationParameters param)
+ {
+ if (param instanceof KDFParameters)
+ {
+ KDFParameters p = (KDFParameters)param;
+
+ shared = p.getSharedSecret();
+ iv = p.getIV();
+ }
+ else if (param instanceof ISO18033KDFParameters)
+ {
+ ISO18033KDFParameters p = (ISO18033KDFParameters)param;
+
+ shared = p.getSeed();
+ iv = null;
+ }
+ else
+ {
+ throw new IllegalArgumentException("KDF parameters required for KDF2Generator");
+ }
+ }
+
+ /**
+ * return the underlying digest.
+ */
+ public Digest getDigest()
+ {
+ return digest;
+ }
+
+ /**
+ * fill len bytes of the output buffer with bytes generated from the
+ * derivation function.
+ *
+ * @throws IllegalArgumentException
+ * if the size of the request will cause an overflow.
+ * @throws DataLengthException
+ * if the out buffer is too small.
+ */
+ public int generateBytes(byte[] out, int outOff, int len) throws DataLengthException,
+ IllegalArgumentException
+ {
+ if ((out.length - len) < outOff)
+ {
+ throw new DataLengthException("output buffer too small");
+ }
+
+ long oBytes = len;
+ int outLen = digest.getDigestSize();
+
+ //
+ // this is at odds with the standard implementation, the
+ // maximum value should be hBits * (2^32 - 1) where hBits
+ // is the digest output size in bits. We can't have an
+ // array with a long index at the moment...
+ //
+ if (oBytes > ((2L << 32) - 1))
+ {
+ throw new IllegalArgumentException("Output length too large");
+ }
+
+ int cThreshold = (int)((oBytes + outLen - 1) / outLen);
+
+ byte[] dig = new byte[digest.getDigestSize()];
+
+ byte[] C = new byte[4];
+ Pack.intToBigEndian(counterStart, C, 0);
+
+ int counterBase = counterStart & ~0xFF;
+
+ for (int i = 0; i < cThreshold; i++)
+ {
+ digest.update(shared, 0, shared.length);
+ digest.update(C, 0, C.length);
+
+ if (iv != null)
+ {
+ digest.update(iv, 0, iv.length);
+ }
+
+ digest.doFinal(dig, 0);
+
+ if (len > outLen)
+ {
+ System.arraycopy(dig, 0, out, outOff, outLen);
+ outOff += outLen;
+ len -= outLen;
+ }
+ else
+ {
+ System.arraycopy(dig, 0, out, outOff, len);
+ }
+
+ if (++C[3] == 0)
+ {
+ counterBase += 0x100;
+ Pack.intToBigEndian(counterBase, C, 0);
+ }
+ }
+
+ digest.reset();
+
+ return (int)oBytes;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/CramerShoupKeyPairGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/CramerShoupKeyPairGenerator.java
new file mode 100644
index 00000000..e5186b9a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/CramerShoupKeyPairGenerator.java
@@ -0,0 +1,63 @@
+package org.spongycastle.crypto.generators;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.crypto.params.CramerShoupKeyGenerationParameters;
+import org.spongycastle.crypto.params.CramerShoupParameters;
+import org.spongycastle.crypto.params.CramerShoupPrivateKeyParameters;
+import org.spongycastle.crypto.params.CramerShoupPublicKeyParameters;
+import org.spongycastle.util.BigIntegers;
+
+/**
+ * a Cramer Shoup key pair generator
+ *
+ */
+public class CramerShoupKeyPairGenerator implements AsymmetricCipherKeyPairGenerator {
+
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ private CramerShoupKeyGenerationParameters param;
+
+ public void init(KeyGenerationParameters param) {
+ this.param = (CramerShoupKeyGenerationParameters) param;
+ }
+
+ public AsymmetricCipherKeyPair generateKeyPair() {
+ CramerShoupParameters csParams = param.getParameters();
+
+ CramerShoupPrivateKeyParameters sk = generatePrivateKey(param.getRandom(), csParams);
+ CramerShoupPublicKeyParameters pk = calculatePublicKey(csParams, sk);
+ sk.setPk(pk);
+
+ return new AsymmetricCipherKeyPair(pk, sk);
+ }
+
+ private BigInteger generateRandomElement(BigInteger p, SecureRandom random) {
+ return BigIntegers.createRandomInRange(ONE, p.subtract(ONE), random);
+ }
+
+ private CramerShoupPrivateKeyParameters generatePrivateKey(SecureRandom random, CramerShoupParameters csParams){
+ BigInteger p = csParams.getP();
+ CramerShoupPrivateKeyParameters key = new CramerShoupPrivateKeyParameters(csParams,
+ generateRandomElement(p, random), generateRandomElement(p, random),
+ generateRandomElement(p, random), generateRandomElement(p, random),
+ generateRandomElement(p, random));
+ return key;
+ }
+
+ private CramerShoupPublicKeyParameters calculatePublicKey(CramerShoupParameters csParams, CramerShoupPrivateKeyParameters sk) {
+ BigInteger g1 = csParams.getG1();
+ BigInteger g2 = csParams.getG2();
+ BigInteger p = csParams.getP();
+
+ BigInteger c = g1.modPow(sk.getX1(), p).multiply(g2.modPow(sk.getX2(), p));
+ BigInteger d = g1.modPow(sk.getY1(), p).multiply(g2.modPow(sk.getY2(), p));
+ BigInteger h = g1.modPow(sk.getZ(), p);
+
+ return new CramerShoupPublicKeyParameters(csParams, c, d, h);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/CramerShoupParametersGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/CramerShoupParametersGenerator.java
new file mode 100644
index 00000000..b7b32a3b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/CramerShoupParametersGenerator.java
@@ -0,0 +1,123 @@
+package org.spongycastle.crypto.generators;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.params.CramerShoupParameters;
+import org.spongycastle.crypto.params.DHParameters;
+import org.spongycastle.util.BigIntegers;
+
+public class CramerShoupParametersGenerator
+{
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ private int size;
+ private int certainty;
+ private SecureRandom random;
+
+ /**
+ * Initialise the parameters generator.
+ *
+ * @param size bit length for the prime p
+ * @param certainty a measure of the uncertainty that the caller is willing to tolerate:
+ * the probability that the generated modulus is prime exceeds (1 - 1/2^certainty).
+ * The execution time of this method is proportional to the value of this parameter.
+ * @param random a source of randomness
+ */
+ public void init(int size, int certainty, SecureRandom random)
+ {
+ this.size = size;
+ this.certainty = certainty;
+ this.random = random;
+ }
+
+ /**
+ * which generates the p and g values from the given parameters, returning
+ * the CramerShoupParameters object.
+ * <p/>
+ * Note: can take a while...
+ */
+ public CramerShoupParameters generateParameters()
+ {
+ //
+ // find a safe prime p where p = 2*q + 1, where p and q are prime.
+ //
+ BigInteger[] safePrimes = ParametersHelper.generateSafePrimes(size, certainty, random);
+
+// BigInteger p = safePrimes[0];
+ BigInteger q = safePrimes[1];
+ BigInteger g1 = ParametersHelper.selectGenerator(q, random);
+ BigInteger g2 = ParametersHelper.selectGenerator(q, random);
+ while (g1.equals(g2))
+ {
+ g2 = ParametersHelper.selectGenerator(q, random);
+ }
+
+ return new CramerShoupParameters(q, g1, g2, new SHA256Digest());
+ }
+
+ public CramerShoupParameters generateParameters(DHParameters dhParams)
+ {
+ BigInteger p = dhParams.getP();
+ BigInteger g1 = dhParams.getG();
+
+ // now we just need a second generator
+ BigInteger g2 = ParametersHelper.selectGenerator(p, random);
+ while (g1.equals(g2))
+ {
+ g2 = ParametersHelper.selectGenerator(p, random);
+ }
+
+ return new CramerShoupParameters(p, g1, g2, new SHA256Digest());
+ }
+
+ private static class ParametersHelper
+ {
+
+ private static final BigInteger TWO = BigInteger.valueOf(2);
+
+ /*
+ * Finds a pair of prime BigInteger's {p, q: p = 2q + 1}
+ *
+ * (see: Handbook of Applied Cryptography 4.86)
+ */
+ static BigInteger[] generateSafePrimes(int size, int certainty, SecureRandom random)
+ {
+ BigInteger p, q;
+ int qLength = size - 1;
+
+ for (; ; )
+ {
+ q = new BigInteger(qLength, 2, random);
+ p = q.shiftLeft(1).add(ONE);
+ if (p.isProbablePrime(certainty) && (certainty <= 2 || q.isProbablePrime(certainty)))
+ {
+ break;
+ }
+ }
+
+ return new BigInteger[]{p, q};
+ }
+
+ static BigInteger selectGenerator(BigInteger p, SecureRandom random)
+ {
+ BigInteger pMinusTwo = p.subtract(TWO);
+ BigInteger g;
+
+ /*
+ * RFC 2631 2.2.1.2 (and see: Handbook of Applied Cryptography 4.81)
+ */
+ do
+ {
+ BigInteger h = BigIntegers.createRandomInRange(TWO, pMinusTwo, random);
+
+ g = h.modPow(TWO, p);
+ }
+ while (g.equals(ONE));
+
+ return g;
+ }
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/DESKeyGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/DESKeyGenerator.java
new file mode 100644
index 00000000..ef6894f5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/DESKeyGenerator.java
@@ -0,0 +1,48 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.CipherKeyGenerator;
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.crypto.params.DESParameters;
+
+public class DESKeyGenerator
+ extends CipherKeyGenerator
+{
+ /**
+ * initialise the key generator - if strength is set to zero
+ * the key generated will be 64 bits in size, otherwise
+ * strength can be 64 or 56 bits (if you don't count the parity bits).
+ *
+ * @param param the parameters to be used for key generation
+ */
+ public void init(
+ KeyGenerationParameters param)
+ {
+ super.init(param);
+
+ if (strength == 0 || strength == (56 / 8))
+ {
+ strength = DESParameters.DES_KEY_LENGTH;
+ }
+ else if (strength != DESParameters.DES_KEY_LENGTH)
+ {
+ throw new IllegalArgumentException("DES key must be "
+ + (DESParameters.DES_KEY_LENGTH * 8)
+ + " bits long.");
+ }
+ }
+
+ public byte[] generateKey()
+ {
+ byte[] newKey = new byte[DESParameters.DES_KEY_LENGTH];
+
+ do
+ {
+ random.nextBytes(newKey);
+
+ DESParameters.setOddParity(newKey);
+ }
+ while (DESParameters.isWeakKey(newKey, 0));
+
+ return newKey;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/DESedeKeyGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/DESedeKeyGenerator.java
new file mode 100644
index 00000000..c22cc172
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/DESedeKeyGenerator.java
@@ -0,0 +1,56 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.crypto.params.DESedeParameters;
+
+public class DESedeKeyGenerator
+ extends DESKeyGenerator
+{
+ /**
+ * initialise the key generator - if strength is set to zero
+ * the key generated will be 192 bits in size, otherwise
+ * strength can be 128 or 192 (or 112 or 168 if you don't count
+ * parity bits), depending on whether you wish to do 2-key or 3-key
+ * triple DES.
+ *
+ * @param param the parameters to be used for key generation
+ */
+ public void init(
+ KeyGenerationParameters param)
+ {
+ this.random = param.getRandom();
+ this.strength = (param.getStrength() + 7) / 8;
+
+ if (strength == 0 || strength == (168 / 8))
+ {
+ strength = DESedeParameters.DES_EDE_KEY_LENGTH;
+ }
+ else if (strength == (112 / 8))
+ {
+ strength = 2 * DESedeParameters.DES_KEY_LENGTH;
+ }
+ else if (strength != DESedeParameters.DES_EDE_KEY_LENGTH
+ && strength != (2 * DESedeParameters.DES_KEY_LENGTH))
+ {
+ throw new IllegalArgumentException("DESede key must be "
+ + (DESedeParameters.DES_EDE_KEY_LENGTH * 8) + " or "
+ + (2 * 8 * DESedeParameters.DES_KEY_LENGTH)
+ + " bits long.");
+ }
+ }
+
+ public byte[] generateKey()
+ {
+ byte[] newKey = new byte[strength];
+
+ do
+ {
+ random.nextBytes(newKey);
+
+ DESedeParameters.setOddParity(newKey);
+ }
+ while (DESedeParameters.isWeakKey(newKey, 0, newKey.length));
+
+ return newKey;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/DHBasicKeyPairGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/DHBasicKeyPairGenerator.java
new file mode 100644
index 00000000..be5e34f8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/DHBasicKeyPairGenerator.java
@@ -0,0 +1,42 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.crypto.params.DHKeyGenerationParameters;
+import org.spongycastle.crypto.params.DHParameters;
+import org.spongycastle.crypto.params.DHPrivateKeyParameters;
+import org.spongycastle.crypto.params.DHPublicKeyParameters;
+
+import java.math.BigInteger;
+
+/**
+ * a basic Diffie-Hellman key pair generator.
+ *
+ * This generates keys consistent for use with the basic algorithm for
+ * Diffie-Hellman.
+ */
+public class DHBasicKeyPairGenerator
+ implements AsymmetricCipherKeyPairGenerator
+{
+ private DHKeyGenerationParameters param;
+
+ public void init(
+ KeyGenerationParameters param)
+ {
+ this.param = (DHKeyGenerationParameters)param;
+ }
+
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+ DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.INSTANCE;
+ DHParameters dhp = param.getParameters();
+
+ BigInteger x = helper.calculatePrivate(dhp, param.getRandom());
+ BigInteger y = helper.calculatePublic(dhp, x);
+
+ return new AsymmetricCipherKeyPair(
+ new DHPublicKeyParameters(y, dhp),
+ new DHPrivateKeyParameters(x, dhp));
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/DHKeyGeneratorHelper.java b/core/src/main/java/org/spongycastle/crypto/generators/DHKeyGeneratorHelper.java
new file mode 100644
index 00000000..6982d222
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/DHKeyGeneratorHelper.java
@@ -0,0 +1,67 @@
+package org.spongycastle.crypto.generators;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.params.DHParameters;
+import org.spongycastle.math.ec.WNafUtil;
+import org.spongycastle.util.BigIntegers;
+
+class DHKeyGeneratorHelper
+{
+ static final DHKeyGeneratorHelper INSTANCE = new DHKeyGeneratorHelper();
+
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+ private static final BigInteger TWO = BigInteger.valueOf(2);
+
+ private DHKeyGeneratorHelper()
+ {
+ }
+
+ BigInteger calculatePrivate(DHParameters dhParams, SecureRandom random)
+ {
+ int limit = dhParams.getL();
+
+ if (limit != 0)
+ {
+ int minWeight = limit >>> 2;
+ for (;;)
+ {
+ BigInteger x = new BigInteger(limit, random).setBit(limit - 1);
+ if (WNafUtil.getNafWeight(x) >= minWeight)
+ {
+ return x;
+ }
+ }
+ }
+
+ BigInteger min = TWO;
+ int m = dhParams.getM();
+ if (m != 0)
+ {
+ min = ONE.shiftLeft(m - 1);
+ }
+
+ BigInteger q = dhParams.getQ();
+ if (q == null)
+ {
+ q = dhParams.getP();
+ }
+ BigInteger max = q.subtract(TWO);
+
+ int minWeight = max.bitLength() >>> 2;
+ for (;;)
+ {
+ BigInteger x = BigIntegers.createRandomInRange(min, max, random);
+ if (WNafUtil.getNafWeight(x) >= minWeight)
+ {
+ return x;
+ }
+ }
+ }
+
+ BigInteger calculatePublic(DHParameters dhParams, BigInteger x)
+ {
+ return dhParams.getG().modPow(x, dhParams.getP());
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/DHKeyPairGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/DHKeyPairGenerator.java
new file mode 100644
index 00000000..f87b416f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/DHKeyPairGenerator.java
@@ -0,0 +1,42 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.crypto.params.DHKeyGenerationParameters;
+import org.spongycastle.crypto.params.DHParameters;
+import org.spongycastle.crypto.params.DHPrivateKeyParameters;
+import org.spongycastle.crypto.params.DHPublicKeyParameters;
+
+import java.math.BigInteger;
+
+/**
+ * a Diffie-Hellman key pair generator.
+ *
+ * This generates keys consistent for use in the MTI/A0 key agreement protocol
+ * as described in "Handbook of Applied Cryptography", Pages 516-519.
+ */
+public class DHKeyPairGenerator
+ implements AsymmetricCipherKeyPairGenerator
+{
+ private DHKeyGenerationParameters param;
+
+ public void init(
+ KeyGenerationParameters param)
+ {
+ this.param = (DHKeyGenerationParameters)param;
+ }
+
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+ DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.INSTANCE;
+ DHParameters dhp = param.getParameters();
+
+ BigInteger x = helper.calculatePrivate(dhp, param.getRandom());
+ BigInteger y = helper.calculatePublic(dhp, x);
+
+ return new AsymmetricCipherKeyPair(
+ new DHPublicKeyParameters(y, dhp),
+ new DHPrivateKeyParameters(x, dhp));
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/DHParametersGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/DHParametersGenerator.java
new file mode 100644
index 00000000..894c3804
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/DHParametersGenerator.java
@@ -0,0 +1,52 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.params.DHParameters;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+public class DHParametersGenerator
+{
+ private int size;
+ private int certainty;
+ private SecureRandom random;
+
+ private static final BigInteger TWO = BigInteger.valueOf(2);
+
+ /**
+ * Initialise the parameters generator.
+ *
+ * @param size bit length for the prime p
+ * @param certainty level of certainty for the prime number tests
+ * @param random a source of randomness
+ */
+ public void init(
+ int size,
+ int certainty,
+ SecureRandom random)
+ {
+ this.size = size;
+ this.certainty = certainty;
+ this.random = random;
+ }
+
+ /**
+ * which generates the p and g values from the given parameters,
+ * returning the DHParameters object.
+ * <p>
+ * Note: can take a while...
+ */
+ public DHParameters generateParameters()
+ {
+ //
+ // find a safe prime p where p = 2*q + 1, where p and q are prime.
+ //
+ BigInteger[] safePrimes = DHParametersHelper.generateSafePrimes(size, certainty, random);
+
+ BigInteger p = safePrimes[0];
+ BigInteger q = safePrimes[1];
+ BigInteger g = DHParametersHelper.selectGenerator(p, q, random);
+
+ return new DHParameters(p, g, q, TWO, null);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/DHParametersHelper.java b/core/src/main/java/org/spongycastle/crypto/generators/DHParametersHelper.java
new file mode 100644
index 00000000..24813191
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/DHParametersHelper.java
@@ -0,0 +1,93 @@
+package org.spongycastle.crypto.generators;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.math.ec.WNafUtil;
+import org.spongycastle.util.BigIntegers;
+
+class DHParametersHelper
+{
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+ private static final BigInteger TWO = BigInteger.valueOf(2);
+
+ /*
+ * Finds a pair of prime BigInteger's {p, q: p = 2q + 1}
+ *
+ * (see: Handbook of Applied Cryptography 4.86)
+ */
+ static BigInteger[] generateSafePrimes(int size, int certainty, SecureRandom random)
+ {
+ BigInteger p, q;
+ int qLength = size - 1;
+ int minWeight = size >>> 2;
+
+ for (;;)
+ {
+ q = new BigInteger(qLength, 2, random);
+
+ // p <- 2q + 1
+ p = q.shiftLeft(1).add(ONE);
+
+ if (!p.isProbablePrime(certainty))
+ {
+ continue;
+ }
+
+ if (certainty > 2 && !q.isProbablePrime(certainty - 2))
+ {
+ continue;
+ }
+
+ /*
+ * Require a minimum weight of the NAF representation, since low-weight primes may be
+ * weak against a version of the number-field-sieve for the discrete-logarithm-problem.
+ *
+ * See "The number field sieve for integers of low weight", Oliver Schirokauer.
+ */
+ if (WNafUtil.getNafWeight(p) < minWeight)
+ {
+ continue;
+ }
+
+ break;
+ }
+
+ return new BigInteger[] { p, q };
+ }
+
+ /*
+ * Select a high order element of the multiplicative group Zp*
+ *
+ * p and q must be s.t. p = 2*q + 1, where p and q are prime (see generateSafePrimes)
+ */
+ static BigInteger selectGenerator(BigInteger p, BigInteger q, SecureRandom random)
+ {
+ BigInteger pMinusTwo = p.subtract(TWO);
+ BigInteger g;
+
+ /*
+ * (see: Handbook of Applied Cryptography 4.80)
+ */
+// do
+// {
+// g = BigIntegers.createRandomInRange(TWO, pMinusTwo, random);
+// }
+// while (g.modPow(TWO, p).equals(ONE) || g.modPow(q, p).equals(ONE));
+
+
+ /*
+ * RFC 2631 2.2.1.2 (and see: Handbook of Applied Cryptography 4.81)
+ */
+ do
+ {
+ BigInteger h = BigIntegers.createRandomInRange(TWO, pMinusTwo, random);
+
+ g = h.modPow(TWO, p);
+ }
+ while (g.equals(ONE));
+
+
+ return g;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/DSAKeyPairGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/DSAKeyPairGenerator.java
new file mode 100644
index 00000000..01c3b26a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/DSAKeyPairGenerator.java
@@ -0,0 +1,69 @@
+package org.spongycastle.crypto.generators;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.crypto.params.DSAKeyGenerationParameters;
+import org.spongycastle.crypto.params.DSAParameters;
+import org.spongycastle.crypto.params.DSAPrivateKeyParameters;
+import org.spongycastle.crypto.params.DSAPublicKeyParameters;
+import org.spongycastle.math.ec.WNafUtil;
+import org.spongycastle.util.BigIntegers;
+
+/**
+ * a DSA key pair generator.
+ *
+ * This generates DSA keys in line with the method described
+ * in <i>FIPS 186-3 B.1 FFC Key Pair Generation</i>.
+ */
+public class DSAKeyPairGenerator
+ implements AsymmetricCipherKeyPairGenerator
+{
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ private DSAKeyGenerationParameters param;
+
+ public void init(
+ KeyGenerationParameters param)
+ {
+ this.param = (DSAKeyGenerationParameters)param;
+ }
+
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+ DSAParameters dsaParams = param.getParameters();
+
+ BigInteger x = generatePrivateKey(dsaParams.getQ(), param.getRandom());
+ BigInteger y = calculatePublicKey(dsaParams.getP(), dsaParams.getG(), x);
+
+ return new AsymmetricCipherKeyPair(
+ new DSAPublicKeyParameters(y, dsaParams),
+ new DSAPrivateKeyParameters(x, dsaParams));
+ }
+
+ private static BigInteger generatePrivateKey(BigInteger q, SecureRandom random)
+ {
+ // B.1.2 Key Pair Generation by Testing Candidates
+ int minWeight = q.bitLength() >>> 2;
+ for (;;)
+ {
+ // TODO Prefer this method? (change test cases that used fixed random)
+ // B.1.1 Key Pair Generation Using Extra Random Bits
+// BigInteger x = new BigInteger(q.bitLength() + 64, random).mod(q.subtract(ONE)).add(ONE);
+
+ BigInteger x = BigIntegers.createRandomInRange(ONE, q.subtract(ONE), random);
+ if (WNafUtil.getNafWeight(x) >= minWeight)
+ {
+ return x;
+ }
+ }
+ }
+
+ private static BigInteger calculatePublicKey(BigInteger p, BigInteger g, BigInteger x)
+ {
+ return g.modPow(x, p);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/DSAParametersGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/DSAParametersGenerator.java
new file mode 100644
index 00000000..b00130fc
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/DSAParametersGenerator.java
@@ -0,0 +1,387 @@
+package org.spongycastle.crypto.generators;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.params.DSAParameterGenerationParameters;
+import org.spongycastle.crypto.params.DSAParameters;
+import org.spongycastle.crypto.params.DSAValidationParameters;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.BigIntegers;
+import org.spongycastle.util.encoders.Hex;
+
+/**
+ * Generate suitable parameters for DSA, in line with FIPS 186-2, or FIPS 186-3.
+ */
+public class DSAParametersGenerator
+{
+ private Digest digest;
+ private int L, N;
+ private int certainty;
+ private SecureRandom random;
+
+ private static final BigInteger ZERO = BigInteger.valueOf(0);
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+ private static final BigInteger TWO = BigInteger.valueOf(2);
+
+ private boolean use186_3;
+ private int usageIndex;
+
+ public DSAParametersGenerator()
+ {
+ this(new SHA1Digest());
+ }
+
+ public DSAParametersGenerator(Digest digest)
+ {
+ this.digest = digest;
+ }
+
+ /**
+ * initialise the key generator.
+ *
+ * @param size size of the key (range 2^512 -&gt; 2^1024 - 64 bit increments)
+ * @param certainty measure of robustness of prime (for FIPS 186-2 compliance this should be at least 80).
+ * @param random random byte source.
+ */
+ public void init(
+ int size,
+ int certainty,
+ SecureRandom random)
+ {
+ this.use186_3 = false;
+ this.L = size;
+ this.N = getDefaultN(size);
+ this.certainty = certainty;
+ this.random = random;
+ }
+
+ /**
+ * Initialise the key generator for DSA 2.
+ * <p>
+ * Use this init method if you need to generate parameters for DSA 2 keys.
+ * </p>
+ *
+ * @param params DSA 2 key generation parameters.
+ */
+ public void init(
+ DSAParameterGenerationParameters params)
+ {
+ // TODO Should we enforce the minimum 'certainty' values as per C.3 Table C.1?
+ this.use186_3 = true;
+ this.L = params.getL();
+ this.N = params.getN();
+ this.certainty = params.getCertainty();
+ this.random = params.getRandom();
+ this.usageIndex = params.getUsageIndex();
+
+ if ((L < 1024 || L > 3072) || L % 1024 != 0)
+ {
+ throw new IllegalArgumentException("L values must be between 1024 and 3072 and a multiple of 1024");
+ }
+ else if (L == 1024 && N != 160)
+ {
+ throw new IllegalArgumentException("N must be 160 for L = 1024");
+ }
+ else if (L == 2048 && (N != 224 && N != 256))
+ {
+ throw new IllegalArgumentException("N must be 224 or 256 for L = 2048");
+ }
+ else if (L == 3072 && N != 256)
+ {
+ throw new IllegalArgumentException("N must be 256 for L = 3072");
+ }
+
+ if (digest.getDigestSize() * 8 < N)
+ {
+ throw new IllegalStateException("Digest output size too small for value of N");
+ }
+ }
+
+ /**
+ * which generates the p and g values from the given parameters,
+ * returning the DSAParameters object.
+ * <p>
+ * Note: can take a while...
+ */
+ public DSAParameters generateParameters()
+ {
+ return (use186_3)
+ ? generateParameters_FIPS186_3()
+ : generateParameters_FIPS186_2();
+ }
+
+ private DSAParameters generateParameters_FIPS186_2()
+ {
+ byte[] seed = new byte[20];
+ byte[] part1 = new byte[20];
+ byte[] part2 = new byte[20];
+ byte[] u = new byte[20];
+ int n = (L - 1) / 160;
+ byte[] w = new byte[L / 8];
+
+ if (!(digest instanceof SHA1Digest))
+ {
+ throw new IllegalStateException("can only use SHA-1 for generating FIPS 186-2 parameters");
+ }
+
+ for (;;)
+ {
+ random.nextBytes(seed);
+
+ hash(digest, seed, part1);
+ System.arraycopy(seed, 0, part2, 0, seed.length);
+ inc(part2);
+ hash(digest, part2, part2);
+
+ for (int i = 0; i != u.length; i++)
+ {
+ u[i] = (byte)(part1[i] ^ part2[i]);
+ }
+
+ u[0] |= (byte)0x80;
+ u[19] |= (byte)0x01;
+
+ BigInteger q = new BigInteger(1, u);
+
+ if (!q.isProbablePrime(certainty))
+ {
+ continue;
+ }
+
+ byte[] offset = Arrays.clone(seed);
+ inc(offset);
+
+ for (int counter = 0; counter < 4096; ++counter)
+ {
+ for (int k = 0; k < n; k++)
+ {
+ inc(offset);
+ hash(digest, offset, part1);
+ System.arraycopy(part1, 0, w, w.length - (k + 1) * part1.length, part1.length);
+ }
+
+ inc(offset);
+ hash(digest, offset, part1);
+ System.arraycopy(part1, part1.length - ((w.length - (n) * part1.length)), w, 0, w.length - n * part1.length);
+
+ w[0] |= (byte)0x80;
+
+ BigInteger x = new BigInteger(1, w);
+
+ BigInteger c = x.mod(q.shiftLeft(1));
+
+ BigInteger p = x.subtract(c.subtract(ONE));
+
+ if (p.bitLength() != L)
+ {
+ continue;
+ }
+
+ if (p.isProbablePrime(certainty))
+ {
+ BigInteger g = calculateGenerator_FIPS186_2(p, q, random);
+
+ return new DSAParameters(p, q, g, new DSAValidationParameters(seed, counter));
+ }
+ }
+ }
+ }
+
+ private static BigInteger calculateGenerator_FIPS186_2(BigInteger p, BigInteger q, SecureRandom r)
+ {
+ BigInteger e = p.subtract(ONE).divide(q);
+ BigInteger pSub2 = p.subtract(TWO);
+
+ for (;;)
+ {
+ BigInteger h = BigIntegers.createRandomInRange(TWO, pSub2, r);
+ BigInteger g = h.modPow(e, p);
+ if (g.bitLength() > 1)
+ {
+ return g;
+ }
+ }
+ }
+
+ /**
+ * generate suitable parameters for DSA, in line with
+ * <i>FIPS 186-3 A.1 Generation of the FFC Primes p and q</i>.
+ */
+ private DSAParameters generateParameters_FIPS186_3()
+ {
+// A.1.1.2 Generation of the Probable Primes p and q Using an Approved Hash Function
+ // FIXME This should be configurable (digest size in bits must be >= N)
+ Digest d = digest;
+ int outlen = d.getDigestSize() * 8;
+
+// 1. Check that the (L, N) pair is in the list of acceptable (L, N pairs) (see Section 4.2). If
+// the pair is not in the list, then return INVALID.
+ // Note: checked at initialisation
+
+// 2. If (seedlen < N), then return INVALID.
+ // FIXME This should be configurable (must be >= N)
+ int seedlen = N;
+ byte[] seed = new byte[seedlen / 8];
+
+// 3. n = ceiling(L / outlen) - 1.
+ int n = (L - 1) / outlen;
+
+// 4. b = L - 1 - (n * outlen).
+ int b = (L - 1) % outlen;
+
+ byte[] output = new byte[d.getDigestSize()];
+ for (;;)
+ {
+// 5. Get an arbitrary sequence of seedlen bits as the domain_parameter_seed.
+ random.nextBytes(seed);
+
+// 6. U = Hash (domain_parameter_seed) mod 2^(N–1).
+ hash(d, seed, output);
+
+ BigInteger U = new BigInteger(1, output).mod(ONE.shiftLeft(N - 1));
+
+// 7. q = 2^(N–1) + U + 1 – ( U mod 2).
+ BigInteger q = ONE.shiftLeft(N - 1).add(U).add(ONE).subtract(U.mod(TWO));
+
+// 8. Test whether or not q is prime as specified in Appendix C.3.
+ // TODO Review C.3 for primality checking
+ if (!q.isProbablePrime(certainty))
+ {
+// 9. If q is not a prime, then go to step 5.
+ continue;
+ }
+
+// 10. offset = 1.
+ // Note: 'offset' value managed incrementally
+ byte[] offset = Arrays.clone(seed);
+
+// 11. For counter = 0 to (4L – 1) do
+ int counterLimit = 4 * L;
+ for (int counter = 0; counter < counterLimit; ++counter)
+ {
+// 11.1 For j = 0 to n do
+// Vj = Hash ((domain_parameter_seed + offset + j) mod 2^seedlen).
+// 11.2 W = V0 + (V1 ∗ 2^outlen) + ... + (V^(n–1) ∗ 2^((n–1) ∗ outlen)) + ((Vn mod 2^b) ∗ 2^(n ∗ outlen)).
+ // TODO Assemble w as a byte array
+ BigInteger W = ZERO;
+ for (int j = 0, exp = 0; j <= n; ++j, exp += outlen)
+ {
+ inc(offset);
+ hash(d, offset, output);
+
+ BigInteger Vj = new BigInteger(1, output);
+ if (j == n)
+ {
+ Vj = Vj.mod(ONE.shiftLeft(b));
+ }
+
+ W = W.add(Vj.shiftLeft(exp));
+ }
+
+// 11.3 X = W + 2^(L–1). Comment: 0 ≤ W < 2L–1; hence, 2L–1 ≤ X < 2L.
+ BigInteger X = W.add(ONE.shiftLeft(L - 1));
+
+// 11.4 c = X mod 2q.
+ BigInteger c = X.mod(q.shiftLeft(1));
+
+// 11.5 p = X - (c - 1). Comment: p ≡ 1 (mod 2q).
+ BigInteger p = X.subtract(c.subtract(ONE));
+
+// 11.6 If (p < 2^(L - 1)), then go to step 11.9
+ if (p.bitLength() != L)
+ {
+ continue;
+ }
+
+// 11.7 Test whether or not p is prime as specified in Appendix C.3.
+ // TODO Review C.3 for primality checking
+ if (p.isProbablePrime(certainty))
+ {
+// 11.8 If p is determined to be prime, then return VALID and the values of p, q and
+// (optionally) the values of domain_parameter_seed and counter.
+ if (usageIndex >= 0)
+ {
+ BigInteger g = calculateGenerator_FIPS186_3_Verifiable(d, p, q, seed, usageIndex);
+ if (g != null)
+ {
+ return new DSAParameters(p, q, g, new DSAValidationParameters(seed, counter, usageIndex));
+ }
+ }
+
+ BigInteger g = calculateGenerator_FIPS186_3_Unverifiable(p, q, random);
+
+ return new DSAParameters(p, q, g, new DSAValidationParameters(seed, counter));
+ }
+
+// 11.9 offset = offset + n + 1. Comment: Increment offset; then, as part of
+// the loop in step 11, increment counter; if
+// counter < 4L, repeat steps 11.1 through 11.8.
+ // Note: 'offset' value already incremented in inner loop
+ }
+// 12. Go to step 5.
+ }
+ }
+
+ private static BigInteger calculateGenerator_FIPS186_3_Unverifiable(BigInteger p, BigInteger q,
+ SecureRandom r)
+ {
+ return calculateGenerator_FIPS186_2(p, q, r);
+ }
+
+ private static BigInteger calculateGenerator_FIPS186_3_Verifiable(Digest d, BigInteger p, BigInteger q,
+ byte[] seed, int index)
+ {
+// A.2.3 Verifiable Canonical Generation of the Generator g
+ BigInteger e = p.subtract(ONE).divide(q);
+ byte[] ggen = Hex.decode("6767656E");
+
+ // 7. U = domain_parameter_seed || "ggen" || index || count.
+ byte[] U = new byte[seed.length + ggen.length + 1 + 2];
+ System.arraycopy(seed, 0, U, 0, seed.length);
+ System.arraycopy(ggen, 0, U, seed.length, ggen.length);
+ U[U.length - 3] = (byte)index;
+
+ byte[] w = new byte[d.getDigestSize()];
+ for (int count = 1; count < (1 << 16); ++count)
+ {
+ inc(U);
+ hash(d, U, w);
+ BigInteger W = new BigInteger(1, w);
+ BigInteger g = W.modPow(e, p);
+ if (g.compareTo(TWO) >= 0)
+ {
+ return g;
+ }
+ }
+
+ return null;
+ }
+
+ private static void hash(Digest d, byte[] input, byte[] output)
+ {
+ d.update(input, 0, input.length);
+ d.doFinal(output, 0);
+ }
+
+ private static int getDefaultN(int L)
+ {
+ return L > 1024 ? 256 : 160;
+ }
+
+ private static void inc(byte[] buf)
+ {
+ for (int i = buf.length - 1; i >= 0; --i)
+ {
+ byte b = (byte)((buf[i] + 1) & 0xff);
+ buf[i] = b;
+
+ if (b != 0)
+ {
+ break;
+ }
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/DSTU4145KeyPairGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/DSTU4145KeyPairGenerator.java
new file mode 100644
index 00000000..47740485
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/DSTU4145KeyPairGenerator.java
@@ -0,0 +1,21 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+
+public class DSTU4145KeyPairGenerator
+ extends ECKeyPairGenerator
+{
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+ AsymmetricCipherKeyPair pair = super.generateKeyPair();
+
+ ECPublicKeyParameters pub = (ECPublicKeyParameters)pair.getPublic();
+ ECPrivateKeyParameters priv = (ECPrivateKeyParameters)pair.getPrivate();
+
+ pub = new ECPublicKeyParameters(pub.getQ().negate(), pub.getParameters());
+
+ return new AsymmetricCipherKeyPair(pub, priv);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/ECKeyPairGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/ECKeyPairGenerator.java
new file mode 100644
index 00000000..62b12b9a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/ECKeyPairGenerator.java
@@ -0,0 +1,84 @@
+package org.spongycastle.crypto.generators;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECKeyGenerationParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.math.ec.ECConstants;
+import org.spongycastle.math.ec.ECMultiplier;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.ec.FixedPointCombMultiplier;
+import org.spongycastle.math.ec.WNafUtil;
+
+public class ECKeyPairGenerator
+ implements AsymmetricCipherKeyPairGenerator, ECConstants
+{
+ ECDomainParameters params;
+ SecureRandom random;
+
+ public void init(
+ KeyGenerationParameters param)
+ {
+ ECKeyGenerationParameters ecP = (ECKeyGenerationParameters)param;
+
+ this.random = ecP.getRandom();
+ this.params = ecP.getDomainParameters();
+
+ if (this.random == null)
+ {
+ this.random = new SecureRandom();
+ }
+ }
+
+ /**
+ * Given the domain parameters this routine generates an EC key
+ * pair in accordance with X9.62 section 5.2.1 pages 26, 27.
+ */
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+ BigInteger n = params.getN();
+ int nBitLength = n.bitLength();
+ int minWeight = nBitLength >>> 2;
+
+ BigInteger d;
+ for (;;)
+ {
+ d = new BigInteger(nBitLength, random);
+
+ if (d.compareTo(TWO) < 0 || (d.compareTo(n) >= 0))
+ {
+ continue;
+ }
+
+ /*
+ * Require a minimum weight of the NAF representation, since low-weight primes may be
+ * weak against a version of the number-field-sieve for the discrete-logarithm-problem.
+ *
+ * See "The number field sieve for integers of low weight", Oliver Schirokauer.
+ */
+ if (WNafUtil.getNafWeight(d) < minWeight)
+ {
+ continue;
+ }
+
+ break;
+ }
+
+ ECPoint Q = createBasePointMultiplier().multiply(params.getG(), d);
+
+ return new AsymmetricCipherKeyPair(
+ new ECPublicKeyParameters(Q, params),
+ new ECPrivateKeyParameters(d, params));
+ }
+
+ protected ECMultiplier createBasePointMultiplier()
+ {
+ return new FixedPointCombMultiplier();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/ElGamalKeyPairGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/ElGamalKeyPairGenerator.java
new file mode 100644
index 00000000..cb0a9fcf
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/ElGamalKeyPairGenerator.java
@@ -0,0 +1,44 @@
+package org.spongycastle.crypto.generators;
+
+import java.math.BigInteger;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.crypto.params.DHParameters;
+import org.spongycastle.crypto.params.ElGamalKeyGenerationParameters;
+import org.spongycastle.crypto.params.ElGamalParameters;
+import org.spongycastle.crypto.params.ElGamalPrivateKeyParameters;
+import org.spongycastle.crypto.params.ElGamalPublicKeyParameters;
+
+/**
+ * a ElGamal key pair generator.
+ * <p>
+ * This generates keys consistent for use with ElGamal as described in
+ * page 164 of "Handbook of Applied Cryptography".
+ */
+public class ElGamalKeyPairGenerator
+ implements AsymmetricCipherKeyPairGenerator
+{
+ private ElGamalKeyGenerationParameters param;
+
+ public void init(
+ KeyGenerationParameters param)
+ {
+ this.param = (ElGamalKeyGenerationParameters)param;
+ }
+
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+ DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.INSTANCE;
+ ElGamalParameters egp = param.getParameters();
+ DHParameters dhp = new DHParameters(egp.getP(), egp.getG(), null, egp.getL());
+
+ BigInteger x = helper.calculatePrivate(dhp, param.getRandom());
+ BigInteger y = helper.calculatePublic(dhp, x);
+
+ return new AsymmetricCipherKeyPair(
+ new ElGamalPublicKeyParameters(y, egp),
+ new ElGamalPrivateKeyParameters(x, egp));
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/ElGamalParametersGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/ElGamalParametersGenerator.java
new file mode 100644
index 00000000..863a8f4a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/ElGamalParametersGenerator.java
@@ -0,0 +1,43 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.params.ElGamalParameters;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+public class ElGamalParametersGenerator
+{
+ private int size;
+ private int certainty;
+ private SecureRandom random;
+
+ public void init(
+ int size,
+ int certainty,
+ SecureRandom random)
+ {
+ this.size = size;
+ this.certainty = certainty;
+ this.random = random;
+ }
+
+ /**
+ * which generates the p and g values from the given parameters,
+ * returning the ElGamalParameters object.
+ * <p>
+ * Note: can take a while...
+ */
+ public ElGamalParameters generateParameters()
+ {
+ //
+ // find a safe prime p where p = 2*q + 1, where p and q are prime.
+ //
+ BigInteger[] safePrimes = DHParametersHelper.generateSafePrimes(size, certainty, random);
+
+ BigInteger p = safePrimes[0];
+ BigInteger q = safePrimes[1];
+ BigInteger g = DHParametersHelper.selectGenerator(p, q, random);
+
+ return new ElGamalParameters(p, g);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/EphemeralKeyPairGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/EphemeralKeyPairGenerator.java
new file mode 100644
index 00000000..d3048b3b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/EphemeralKeyPairGenerator.java
@@ -0,0 +1,26 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import org.spongycastle.crypto.EphemeralKeyPair;
+import org.spongycastle.crypto.KeyEncoder;
+
+public class EphemeralKeyPairGenerator
+{
+ private AsymmetricCipherKeyPairGenerator gen;
+ private KeyEncoder keyEncoder;
+
+ public EphemeralKeyPairGenerator(AsymmetricCipherKeyPairGenerator gen, KeyEncoder keyEncoder)
+ {
+ this.gen = gen;
+ this.keyEncoder = keyEncoder;
+ }
+
+ public EphemeralKeyPair generate()
+ {
+ AsymmetricCipherKeyPair eph = gen.generateKeyPair();
+
+ // Encode the ephemeral public key
+ return new EphemeralKeyPair(eph, keyEncoder);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/GOST3410KeyPairGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/GOST3410KeyPairGenerator.java
new file mode 100644
index 00000000..2929828b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/GOST3410KeyPairGenerator.java
@@ -0,0 +1,74 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.crypto.params.GOST3410KeyGenerationParameters;
+import org.spongycastle.crypto.params.GOST3410Parameters;
+import org.spongycastle.crypto.params.GOST3410PrivateKeyParameters;
+import org.spongycastle.crypto.params.GOST3410PublicKeyParameters;
+import org.spongycastle.math.ec.WNafUtil;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * a GOST3410 key pair generator.
+ * This generates GOST3410 keys in line with the method described
+ * in GOST R 34.10-94.
+ */
+public class GOST3410KeyPairGenerator
+ implements AsymmetricCipherKeyPairGenerator
+ {
+ private GOST3410KeyGenerationParameters param;
+
+ public void init(
+ KeyGenerationParameters param)
+ {
+ this.param = (GOST3410KeyGenerationParameters)param;
+ }
+
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+ BigInteger p, q, a, x, y;
+ GOST3410Parameters GOST3410Params = param.getParameters();
+ SecureRandom random = param.getRandom();
+
+ q = GOST3410Params.getQ();
+ p = GOST3410Params.getP();
+ a = GOST3410Params.getA();
+
+ int minWeight = 64;
+ for (;;)
+ {
+ x = new BigInteger(256, random);
+
+ if (x.signum() < 1 || x.compareTo(q) >= 0)
+ {
+ continue;
+ }
+
+ /*
+ * Require a minimum weight of the NAF representation, since low-weight primes may be
+ * weak against a version of the number-field-sieve for the discrete-logarithm-problem.
+ *
+ * See "The number field sieve for integers of low weight", Oliver Schirokauer.
+ */
+ if (WNafUtil.getNafWeight(x) < minWeight)
+ {
+ continue;
+ }
+
+ break;
+ }
+
+ //
+ // calculate the public key.
+ //
+ y = a.modPow(x, p);
+
+ return new AsymmetricCipherKeyPair(
+ new GOST3410PublicKeyParameters(y, GOST3410Params),
+ new GOST3410PrivateKeyParameters(x, GOST3410Params));
+ }
+ }
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/GOST3410ParametersGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/GOST3410ParametersGenerator.java
new file mode 100644
index 00000000..c4e57127
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/GOST3410ParametersGenerator.java
@@ -0,0 +1,541 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.params.GOST3410Parameters;
+import org.spongycastle.crypto.params.GOST3410ValidationParameters;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * generate suitable parameters for GOST3410.
+ */
+public class GOST3410ParametersGenerator
+{
+ private int size;
+ private int typeproc;
+ private SecureRandom init_random;
+
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+ private static final BigInteger TWO = BigInteger.valueOf(2);
+
+ /**
+ * initialise the key generator.
+ *
+ * @param size size of the key
+ * @param typeproc type procedure A,B = 1; A',B' - else
+ * @param random random byte source.
+ */
+ public void init(
+ int size,
+ int typeproc,
+ SecureRandom random)
+ {
+ this.size = size;
+ this.typeproc = typeproc;
+ this.init_random = random;
+ }
+
+ //Procedure A
+ private int procedure_A(int x0, int c, BigInteger[] pq, int size)
+ {
+ //Verify and perform condition: 0<x<2^16; 0<c<2^16; c - odd.
+ while(x0<0 || x0>65536)
+ {
+ x0 = init_random.nextInt()/32768;
+ }
+
+ while((c<0 || c>65536) || (c/2==0))
+ {
+ c = init_random.nextInt()/32768 + 1;
+ }
+
+ BigInteger C = new BigInteger(Integer.toString(c));
+ BigInteger constA16 = new BigInteger("19381");
+
+ //step1
+ BigInteger[] y = new BigInteger[1]; // begin length = 1
+ y[0] = new BigInteger(Integer.toString(x0));
+
+ //step 2
+ int[] t = new int[1]; // t - orders; begin length = 1
+ t[0] = size;
+ int s = 0;
+ for (int i=0; t[i]>=17; i++)
+ {
+ // extension array t
+ int tmp_t[] = new int[t.length + 1]; ///////////////
+ System.arraycopy(t,0,tmp_t,0,t.length); // extension
+ t = new int[tmp_t.length]; // array t
+ System.arraycopy(tmp_t, 0, t, 0, tmp_t.length); ///////////////
+
+ t[i+1] = t[i]/2;
+ s = i+1;
+ }
+
+ //step3
+ BigInteger p[] = new BigInteger[s+1];
+ p[s] = new BigInteger("8003",16); //set min prime number length 16 bit
+
+ int m = s-1; //step4
+
+ for (int i=0; i<s; i++)
+ {
+ int rm = t[m]/16; //step5
+
+ step6: for(;;)
+ {
+ //step 6
+ BigInteger tmp_y[] = new BigInteger[y.length]; ////////////////
+ System.arraycopy(y,0,tmp_y,0,y.length); // extension
+ y = new BigInteger[rm+1]; // array y
+ System.arraycopy(tmp_y,0,y,0,tmp_y.length); ////////////////
+
+ for (int j=0; j<rm; j++)
+ {
+ y[j+1] = (y[j].multiply(constA16).add(C)).mod(TWO.pow(16));
+ }
+
+ //step 7
+ BigInteger Ym = new BigInteger("0");
+ for (int j=0; j<rm; j++)
+ {
+ Ym = Ym.add(y[j].multiply(TWO.pow(16*j)));
+ }
+
+ y[0] = y[rm]; //step 8
+
+ //step 9
+ BigInteger N = TWO.pow(t[m]-1).divide(p[m+1]).
+ add((TWO.pow(t[m]-1).multiply(Ym)).
+ divide(p[m+1].multiply(TWO.pow(16*rm))));
+
+ if (N.mod(TWO).compareTo(ONE)==0)
+ {
+ N = N.add(ONE);
+ }
+
+ int k = 0; //step 10
+
+ step11: for(;;)
+ {
+ //step 11
+ p[m] = p[m+1].multiply(N.add(BigInteger.valueOf(k))).add(ONE);
+
+ if (p[m].compareTo(TWO.pow(t[m]))==1)
+ {
+ continue step6; //step 12
+ }
+
+ //step13
+ if ((TWO.modPow(p[m+1].multiply(N.add(BigInteger.valueOf(k))),p[m]).compareTo(ONE)==0) &&
+ (TWO.modPow(N.add(BigInteger.valueOf(k)),p[m]).compareTo(ONE)!=0))
+ {
+ m -= 1;
+ break;
+ }
+ else
+ {
+ k += 2;
+ continue step11;
+ }
+ }
+
+ if (m>=0)
+ {
+ break; //step 14
+ }
+ else
+ {
+ pq[0] = p[0];
+ pq[1] = p[1];
+ return y[0].intValue(); //return for procedure B step 2
+ }
+ }
+ }
+ return y[0].intValue();
+ }
+
+ //Procedure A'
+ private long procedure_Aa(long x0, long c, BigInteger[] pq, int size)
+ {
+ //Verify and perform condition: 0<x<2^32; 0<c<2^32; c - odd.
+ while(x0<0 || x0>4294967296L)
+ {
+ x0 = init_random.nextInt()*2;
+ }
+
+ while((c<0 || c>4294967296L) || (c/2==0))
+ {
+ c = init_random.nextInt()*2+1;
+ }
+
+ BigInteger C = new BigInteger(Long.toString(c));
+ BigInteger constA32 = new BigInteger("97781173");
+
+ //step1
+ BigInteger[] y = new BigInteger[1]; // begin length = 1
+ y[0] = new BigInteger(Long.toString(x0));
+
+ //step 2
+ int[] t = new int[1]; // t - orders; begin length = 1
+ t[0] = size;
+ int s = 0;
+ for (int i=0; t[i]>=33; i++)
+ {
+ // extension array t
+ int tmp_t[] = new int[t.length + 1]; ///////////////
+ System.arraycopy(t,0,tmp_t,0,t.length); // extension
+ t = new int[tmp_t.length]; // array t
+ System.arraycopy(tmp_t, 0, t, 0, tmp_t.length); ///////////////
+
+ t[i+1] = t[i]/2;
+ s = i+1;
+ }
+
+ //step3
+ BigInteger p[] = new BigInteger[s+1];
+ p[s] = new BigInteger("8000000B",16); //set min prime number length 32 bit
+
+ int m = s-1; //step4
+
+ for (int i=0; i<s; i++)
+ {
+ int rm = t[m]/32; //step5
+
+ step6: for(;;)
+ {
+ //step 6
+ BigInteger tmp_y[] = new BigInteger[y.length]; ////////////////
+ System.arraycopy(y,0,tmp_y,0,y.length); // extension
+ y = new BigInteger[rm+1]; // array y
+ System.arraycopy(tmp_y,0,y,0,tmp_y.length); ////////////////
+
+ for (int j=0; j<rm; j++)
+ {
+ y[j+1] = (y[j].multiply(constA32).add(C)).mod(TWO.pow(32));
+ }
+
+ //step 7
+ BigInteger Ym = new BigInteger("0");
+ for (int j=0; j<rm; j++)
+ {
+ Ym = Ym.add(y[j].multiply(TWO.pow(32*j)));
+ }
+
+ y[0] = y[rm]; //step 8
+
+ //step 9
+ BigInteger N = TWO.pow(t[m]-1).divide(p[m+1]).
+ add((TWO.pow(t[m]-1).multiply(Ym)).
+ divide(p[m+1].multiply(TWO.pow(32*rm))));
+
+ if (N.mod(TWO).compareTo(ONE)==0)
+ {
+ N = N.add(ONE);
+ }
+
+ int k = 0; //step 10
+
+ step11: for(;;)
+ {
+ //step 11
+ p[m] = p[m+1].multiply(N.add(BigInteger.valueOf(k))).add(ONE);
+
+ if (p[m].compareTo(TWO.pow(t[m]))==1)
+ {
+ continue step6; //step 12
+ }
+
+ //step13
+ if ((TWO.modPow(p[m+1].multiply(N.add(BigInteger.valueOf(k))),p[m]).compareTo(ONE)==0) &&
+ (TWO.modPow(N.add(BigInteger.valueOf(k)),p[m]).compareTo(ONE)!=0))
+ {
+ m -= 1;
+ break;
+ }
+ else
+ {
+ k += 2;
+ continue step11;
+ }
+ }
+
+ if (m>=0)
+ {
+ break; //step 14
+ }
+ else
+ {
+ pq[0] = p[0];
+ pq[1] = p[1];
+ return y[0].longValue(); //return for procedure B' step 2
+ }
+ }
+ }
+ return y[0].longValue();
+ }
+
+ //Procedure B
+ private void procedure_B(int x0, int c, BigInteger[] pq)
+ {
+ //Verify and perform condition: 0<x<2^16; 0<c<2^16; c - odd.
+ while(x0<0 || x0>65536)
+ {
+ x0 = init_random.nextInt()/32768;
+ }
+
+ while((c<0 || c>65536) || (c/2==0))
+ {
+ c = init_random.nextInt()/32768 + 1;
+ }
+
+ BigInteger [] qp = new BigInteger[2];
+ BigInteger q = null, Q = null, p = null;
+ BigInteger C = new BigInteger(Integer.toString(c));
+ BigInteger constA16 = new BigInteger("19381");
+
+ //step1
+ x0 = procedure_A(x0, c, qp, 256);
+ q = qp[0];
+
+ //step2
+ x0 = procedure_A(x0, c, qp, 512);
+ Q = qp[0];
+
+ BigInteger[] y = new BigInteger[65];
+ y[0] = new BigInteger(Integer.toString(x0));
+
+ int tp = 1024;
+
+ step3: for(;;)
+ {
+ //step 3
+ for (int j=0; j<64; j++)
+ {
+ y[j+1] = (y[j].multiply(constA16).add(C)).mod(TWO.pow(16));
+ }
+
+ //step 4
+ BigInteger Y = new BigInteger("0");
+
+ for (int j=0; j<64; j++)
+ {
+ Y = Y.add(y[j].multiply(TWO.pow(16*j)));
+ }
+
+ y[0] = y[64]; //step 5
+
+ //step 6
+ BigInteger N = TWO.pow(tp-1).divide(q.multiply(Q)).
+ add((TWO.pow(tp-1).multiply(Y)).
+ divide(q.multiply(Q).multiply(TWO.pow(1024))));
+
+ if (N.mod(TWO).compareTo(ONE)==0)
+ {
+ N = N.add(ONE);
+ }
+
+ int k = 0; //step 7
+
+ step8: for(;;)
+ {
+ //step 11
+ p = q.multiply(Q).multiply(N.add(BigInteger.valueOf(k))).add(ONE);
+
+ if (p.compareTo(TWO.pow(tp))==1)
+ {
+ continue step3; //step 9
+ }
+
+ //step10
+ if ((TWO.modPow(q.multiply(Q).multiply(N.add(BigInteger.valueOf(k))),p).compareTo(ONE)==0) &&
+ (TWO.modPow(q.multiply(N.add(BigInteger.valueOf(k))),p).compareTo(ONE)!=0))
+ {
+ pq[0] = p;
+ pq[1] = q;
+ return;
+ }
+ else
+ {
+ k += 2;
+ continue step8;
+ }
+ }
+ }
+ }
+
+ //Procedure B'
+ private void procedure_Bb(long x0, long c, BigInteger[] pq)
+ {
+ //Verify and perform condition: 0<x<2^32; 0<c<2^32; c - odd.
+ while(x0<0 || x0>4294967296L)
+ {
+ x0 = init_random.nextInt()*2;
+ }
+
+ while((c<0 || c>4294967296L) || (c/2==0))
+ {
+ c = init_random.nextInt()*2+1;
+ }
+
+ BigInteger [] qp = new BigInteger[2];
+ BigInteger q = null, Q = null, p = null;
+ BigInteger C = new BigInteger(Long.toString(c));
+ BigInteger constA32 = new BigInteger("97781173");
+
+ //step1
+ x0 = procedure_Aa(x0, c, qp, 256);
+ q = qp[0];
+
+ //step2
+ x0 = procedure_Aa(x0, c, qp, 512);
+ Q = qp[0];
+
+ BigInteger[] y = new BigInteger[33];
+ y[0] = new BigInteger(Long.toString(x0));
+
+ int tp = 1024;
+
+ step3: for(;;)
+ {
+ //step 3
+ for (int j=0; j<32; j++)
+ {
+ y[j+1] = (y[j].multiply(constA32).add(C)).mod(TWO.pow(32));
+ }
+
+ //step 4
+ BigInteger Y = new BigInteger("0");
+ for (int j=0; j<32; j++)
+ {
+ Y = Y.add(y[j].multiply(TWO.pow(32*j)));
+ }
+
+ y[0] = y[32]; //step 5
+
+ //step 6
+ BigInteger N = TWO.pow(tp-1).divide(q.multiply(Q)).
+ add((TWO.pow(tp-1).multiply(Y)).
+ divide(q.multiply(Q).multiply(TWO.pow(1024))));
+
+ if (N.mod(TWO).compareTo(ONE)==0)
+ {
+ N = N.add(ONE);
+ }
+
+ int k = 0; //step 7
+
+ step8: for(;;)
+ {
+ //step 11
+ p = q.multiply(Q).multiply(N.add(BigInteger.valueOf(k))).add(ONE);
+
+ if (p.compareTo(TWO.pow(tp))==1)
+ {
+ continue step3; //step 9
+ }
+
+ //step10
+ if ((TWO.modPow(q.multiply(Q).multiply(N.add(BigInteger.valueOf(k))),p).compareTo(ONE)==0) &&
+ (TWO.modPow(q.multiply(N.add(BigInteger.valueOf(k))),p).compareTo(ONE)!=0))
+ {
+ pq[0] = p;
+ pq[1] = q;
+ return;
+ }
+ else
+ {
+ k += 2;
+ continue step8;
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Procedure C
+ * procedure generates the a value from the given p,q,
+ * returning the a value.
+ */
+ private BigInteger procedure_C(BigInteger p, BigInteger q)
+ {
+ BigInteger pSub1 = p.subtract(ONE);
+ BigInteger pSub1DivQ = pSub1.divide(q);
+ int length = p.bitLength();
+
+ for(;;)
+ {
+ BigInteger d = new BigInteger(length, init_random);
+
+ // 1 < d < p-1
+ if (d.compareTo(ONE) > 0 && d.compareTo(pSub1) < 0)
+ {
+ BigInteger a = d.modPow(pSub1DivQ, p);
+
+ if (a.compareTo(ONE) != 0)
+ {
+ return a;
+ }
+ }
+ }
+ }
+
+ /**
+ * which generates the p , q and a values from the given parameters,
+ * returning the GOST3410Parameters object.
+ */
+ public GOST3410Parameters generateParameters()
+ {
+ BigInteger [] pq = new BigInteger[2];
+ BigInteger q = null, p = null, a = null;
+
+ int x0, c;
+ long x0L, cL;
+
+ if (typeproc==1)
+ {
+ x0 = init_random.nextInt();
+ c = init_random.nextInt();
+
+ switch(size)
+ {
+ case 512:
+ procedure_A(x0, c, pq, 512);
+ break;
+ case 1024:
+ procedure_B(x0, c, pq);
+ break;
+ default:
+ throw new IllegalArgumentException("Ooops! key size 512 or 1024 bit.");
+ }
+ p = pq[0]; q = pq[1];
+ a = procedure_C(p, q);
+ //System.out.println("p:"+p.toString(16)+"\n"+"q:"+q.toString(16)+"\n"+"a:"+a.toString(16));
+ //System.out.println("p:"+p+"\n"+"q:"+q+"\n"+"a:"+a);
+ return new GOST3410Parameters(p, q, a, new GOST3410ValidationParameters(x0, c));
+ }
+ else
+ {
+ x0L = init_random.nextLong();
+ cL = init_random.nextLong();
+
+ switch(size)
+ {
+ case 512:
+ procedure_Aa(x0L, cL, pq, 512);
+ break;
+ case 1024:
+ procedure_Bb(x0L, cL, pq);
+ break;
+ default:
+ throw new IllegalStateException("Ooops! key size 512 or 1024 bit.");
+ }
+ p = pq[0]; q = pq[1];
+ a = procedure_C(p, q);
+ //System.out.println("p:"+p.toString(16)+"\n"+"q:"+q.toString(16)+"\n"+"a:"+a.toString(16));
+ //System.out.println("p:"+p+"\n"+"q:"+q+"\n"+"a:"+a);
+ return new GOST3410Parameters(p, q, a, new GOST3410ValidationParameters(x0L, cL));
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/HKDFBytesGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/HKDFBytesGenerator.java
new file mode 100644
index 00000000..fbeeca61
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/HKDFBytesGenerator.java
@@ -0,0 +1,161 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.DerivationFunction;
+import org.spongycastle.crypto.DerivationParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.macs.HMac;
+import org.spongycastle.crypto.params.HKDFParameters;
+import org.spongycastle.crypto.params.KeyParameter;
+
+/**
+ * HMAC-based Extract-and-Expand Key Derivation Function (HKDF) implemented
+ * according to IETF RFC 5869, May 2010 as specified by H. Krawczyk, IBM
+ * Research &amp; P. Eronen, Nokia. It uses a HMac internally to compute de OKM
+ * (output keying material) and is likely to have better security properties
+ * than KDF's based on just a hash function.
+ */
+public class HKDFBytesGenerator
+ implements DerivationFunction
+{
+
+ private HMac hMacHash;
+ private int hashLen;
+
+ private byte[] info;
+ private byte[] currentT;
+
+ private int generatedBytes;
+
+ /**
+ * Creates a HKDFBytesGenerator based on the given hash function.
+ *
+ * @param hash the digest to be used as the source of generatedBytes bytes
+ */
+ public HKDFBytesGenerator(Digest hash)
+ {
+ this.hMacHash = new HMac(hash);
+ this.hashLen = hash.getDigestSize();
+ }
+
+ public void init(DerivationParameters param)
+ {
+ if (!(param instanceof HKDFParameters))
+ {
+ throw new IllegalArgumentException(
+ "HKDF parameters required for HKDFBytesGenerator");
+ }
+
+ HKDFParameters params = (HKDFParameters)param;
+ if (params.skipExtract())
+ {
+ // use IKM directly as PRK
+ hMacHash.init(new KeyParameter(params.getIKM()));
+ }
+ else
+ {
+ hMacHash.init(extract(params.getSalt(), params.getIKM()));
+ }
+
+ info = params.getInfo();
+
+ generatedBytes = 0;
+ currentT = new byte[hashLen];
+ }
+
+ /**
+ * Performs the extract part of the key derivation function.
+ *
+ * @param salt the salt to use
+ * @param ikm the input keying material
+ * @return the PRK as KeyParameter
+ */
+ private KeyParameter extract(byte[] salt, byte[] ikm)
+ {
+ hMacHash.init(new KeyParameter(ikm));
+ if (salt == null)
+ {
+ // TODO check if hashLen is indeed same as HMAC size
+ hMacHash.init(new KeyParameter(new byte[hashLen]));
+ }
+ else
+ {
+ hMacHash.init(new KeyParameter(salt));
+ }
+
+ hMacHash.update(ikm, 0, ikm.length);
+
+ byte[] prk = new byte[hashLen];
+ hMacHash.doFinal(prk, 0);
+ return new KeyParameter(prk);
+ }
+
+ /**
+ * Performs the expand part of the key derivation function, using currentT
+ * as input and output buffer.
+ *
+ * @throws DataLengthException if the total number of bytes generated is larger than the one
+ * specified by RFC 5869 (255 * HashLen)
+ */
+ private void expandNext()
+ throws DataLengthException
+ {
+ int n = generatedBytes / hashLen + 1;
+ if (n >= 256)
+ {
+ throw new DataLengthException(
+ "HKDF cannot generate more than 255 blocks of HashLen size");
+ }
+ // special case for T(0): T(0) is empty, so no update
+ if (generatedBytes != 0)
+ {
+ hMacHash.update(currentT, 0, hashLen);
+ }
+ hMacHash.update(info, 0, info.length);
+ hMacHash.update((byte)n);
+ hMacHash.doFinal(currentT, 0);
+ }
+
+ public Digest getDigest()
+ {
+ return hMacHash.getUnderlyingDigest();
+ }
+
+ public int generateBytes(byte[] out, int outOff, int len)
+ throws DataLengthException, IllegalArgumentException
+ {
+
+ if (generatedBytes + len > 255 * hashLen)
+ {
+ throw new DataLengthException(
+ "HKDF may only be used for 255 * HashLen bytes of output");
+ }
+
+ if (generatedBytes % hashLen == 0)
+ {
+ expandNext();
+ }
+
+ // copy what is left in the currentT (1..hash
+ int toGenerate = len;
+ int posInT = generatedBytes % hashLen;
+ int leftInT = hashLen - generatedBytes % hashLen;
+ int toCopy = Math.min(leftInT, toGenerate);
+ System.arraycopy(currentT, posInT, out, outOff, toCopy);
+ generatedBytes += toCopy;
+ toGenerate -= toCopy;
+ outOff += toCopy;
+
+ while (toGenerate > 0)
+ {
+ expandNext();
+ toCopy = Math.min(hashLen, toGenerate);
+ System.arraycopy(currentT, 0, out, outOff, toCopy);
+ generatedBytes += toCopy;
+ toGenerate -= toCopy;
+ outOff += toCopy;
+ }
+
+ return len;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/KDF1BytesGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/KDF1BytesGenerator.java
new file mode 100644
index 00000000..2d176a32
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/KDF1BytesGenerator.java
@@ -0,0 +1,23 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.Digest;
+
+/**
+ * KDF1 generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033
+ * <br>
+ * This implementation is based on ISO 18033/IEEE P1363a.
+ */
+public class KDF1BytesGenerator
+ extends BaseKDFBytesGenerator
+{
+ /**
+ * Construct a KDF1 byte generator.
+ * <p>
+ * @param digest the digest to be used as the source of derived keys.
+ */
+ public KDF1BytesGenerator(
+ Digest digest)
+ {
+ super(0, digest);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/KDF2BytesGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/KDF2BytesGenerator.java
new file mode 100644
index 00000000..bcdfc096
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/KDF2BytesGenerator.java
@@ -0,0 +1,24 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.Digest;
+
+/**
+ * KDF2 generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033
+ * <br>
+ * This implementation is based on IEEE P1363/ISO 18033.
+ */
+public class KDF2BytesGenerator
+ extends BaseKDFBytesGenerator
+{
+ /**
+ * Construct a KDF2 bytes generator. Generates key material
+ * according to IEEE P1363 or ISO 18033 depending on the initialisation.
+ * <p>
+ * @param digest the digest to be used as the source of derived keys.
+ */
+ public KDF2BytesGenerator(
+ Digest digest)
+ {
+ super(1, digest);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/KDFCounterBytesGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/KDFCounterBytesGenerator.java
new file mode 100644
index 00000000..fd540354
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/KDFCounterBytesGenerator.java
@@ -0,0 +1,180 @@
+package org.spongycastle.crypto.generators;
+
+import java.math.BigInteger;
+
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.DerivationParameters;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.MacDerivationFunction;
+import org.spongycastle.crypto.params.KDFCounterParameters;
+import org.spongycastle.crypto.params.KeyParameter;
+
+/**
+ * This KDF has been defined by the publicly available NIST SP 800-108 specification.
+ * NIST SP800-108 allows for alternative orderings of the input fields, meaning that the input can be formated in multiple ways.
+ * There are 3 supported formats: - Below [i]_2 is a counter of r-bits length concatenated to the fixedInputData.
+ * <ul>
+ * <li>1: K(i) := PRF( KI, [i]_2 || Label || 0x00 || Context || [L]_2 ) with the counter at the very beginning of the fixedInputData (The default implementation has this format)</li>
+ * <li>2: K(i) := PRF( KI, Label || 0x00 || Context || [L]_2 || [i]_2 ) with the counter at the very end of the fixedInputData</li>
+ * <li>3a: K(i) := PRF( KI, Label || 0x00 || [i]_2 || Context || [L]_2 ) OR:</li>
+ * <li>3b: K(i) := PRF( KI, Label || 0x00 || [i]_2 || [L]_2 || Context ) OR:</li>
+ * <li>3c: K(i) := PRF( KI, Label || [i]_2 || 0x00 || Context || [L]_2 ) etc... with the counter somewhere in the 'middle' of the fixedInputData.</li>
+ * </ul>
+ * </p>
+ * <p>
+ * This function must be called with the following KDFCounterParameters():
+ * - KI <br/>
+ * - The part of the fixedInputData that comes BEFORE the counter OR null <br/>
+ * - the part of the fixedInputData that comes AFTER the counter OR null <br/>
+ * - the length of the counter in bits (not bytes)
+ * </p>
+ * Resulting function calls assuming an 8 bit counter.
+ * <ul>
+ * <li>1. KDFCounterParameters(ki, null, "Label || 0x00 || Context || [L]_2]", 8);</li>
+ * <li>2. KDFCounterParameters(ki, "Label || 0x00 || Context || [L]_2]", null, 8);</li>
+ * <li>3a. KDFCounterParameters(ki, "Label || 0x00", "Context || [L]_2]", 8);</li>
+ * <li>3b. KDFCounterParameters(ki, "Label || 0x00", "[L]_2] || Context", 8);</li>
+ * <li>3c. KDFCounterParameters(ki, "Label", "0x00 || Context || [L]_2]", 8);</li>
+ * </ul>
+ */
+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[] fixedInputDataCtrPrefix;
+ private byte[] fixedInputData_afterCtr;
+ 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.fixedInputDataCtrPrefix = kdfParams.getFixedInputDataCounterPrefix();
+ this.fixedInputData_afterCtr = kdfParams.getFixedInputDataCounterSuffix();
+
+ 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(fixedInputDataCtrPrefix, 0, fixedInputDataCtrPrefix.length);
+ prf.update(ios, 0, ios.length);
+ prf.update(fixedInputData_afterCtr, 0, fixedInputData_afterCtr.length);
+ prf.doFinal(k, 0);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/KDFDoublePipelineIterationBytesGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/KDFDoublePipelineIterationBytesGenerator.java
new file mode 100644
index 00000000..1716dc08
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/KDFDoublePipelineIterationBytesGenerator.java
@@ -0,0 +1,181 @@
+package org.spongycastle.crypto.generators;
+
+import java.math.BigInteger;
+
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.DerivationParameters;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.MacDerivationFunction;
+import org.spongycastle.crypto.params.KDFDoublePipelineIterationParameters;
+import org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/generators/KDFFeedbackBytesGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/KDFFeedbackBytesGenerator.java
new file mode 100644
index 00000000..6410ec91
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/KDFFeedbackBytesGenerator.java
@@ -0,0 +1,175 @@
+package org.spongycastle.crypto.generators;
+
+import java.math.BigInteger;
+
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.DerivationParameters;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.MacDerivationFunction;
+import org.spongycastle.crypto.params.KDFFeedbackParameters;
+import org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/generators/MGF1BytesGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/MGF1BytesGenerator.java
new file mode 100644
index 00000000..03cb7ba5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/MGF1BytesGenerator.java
@@ -0,0 +1,114 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.DerivationFunction;
+import org.spongycastle.crypto.DerivationParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.params.MGFParameters;
+
+/**
+ * Generator for MGF1 as defined in PKCS 1v2
+ */
+public class MGF1BytesGenerator
+ implements DerivationFunction
+{
+ private Digest digest;
+ private byte[] seed;
+ private int hLen;
+
+ /**
+ * @param digest the digest to be used as the source of generated bytes
+ */
+ public MGF1BytesGenerator(
+ Digest digest)
+ {
+ this.digest = digest;
+ this.hLen = digest.getDigestSize();
+ }
+
+ public void init(
+ DerivationParameters param)
+ {
+ if (!(param instanceof MGFParameters))
+ {
+ throw new IllegalArgumentException("MGF parameters required for MGF1Generator");
+ }
+
+ MGFParameters p = (MGFParameters)param;
+
+ seed = p.getSeed();
+ }
+
+ /**
+ * return the underlying digest.
+ */
+ public Digest getDigest()
+ {
+ return digest;
+ }
+
+ /**
+ * int to octet string.
+ */
+ private void ItoOSP(
+ int i,
+ byte[] sp)
+ {
+ sp[0] = (byte)(i >>> 24);
+ sp[1] = (byte)(i >>> 16);
+ sp[2] = (byte)(i >>> 8);
+ sp[3] = (byte)(i >>> 0);
+ }
+
+ /**
+ * fill len bytes of the output buffer with bytes generated from
+ * the derivation function.
+ *
+ * @throws DataLengthException if the out buffer is too small.
+ */
+ public int generateBytes(
+ byte[] out,
+ int outOff,
+ int len)
+ throws DataLengthException, IllegalArgumentException
+ {
+ if ((out.length - len) < outOff)
+ {
+ throw new DataLengthException("output buffer too small");
+ }
+
+ byte[] hashBuf = new byte[hLen];
+ byte[] C = new byte[4];
+ int counter = 0;
+
+ digest.reset();
+
+ if (len > hLen)
+ {
+ do
+ {
+ ItoOSP(counter, C);
+
+ digest.update(seed, 0, seed.length);
+ digest.update(C, 0, C.length);
+ digest.doFinal(hashBuf, 0);
+
+ System.arraycopy(hashBuf, 0, out, outOff + counter * hLen, hLen);
+ }
+ while (++counter < (len / hLen));
+ }
+
+ if ((counter * hLen) < len)
+ {
+ ItoOSP(counter, C);
+
+ digest.update(seed, 0, seed.length);
+ digest.update(C, 0, C.length);
+ digest.doFinal(hashBuf, 0);
+
+ System.arraycopy(hashBuf, 0, out, outOff + counter * hLen, len - (counter * hLen));
+ }
+
+ return len;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/NaccacheSternKeyPairGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/NaccacheSternKeyPairGenerator.java
new file mode 100644
index 00000000..5aa60026
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/NaccacheSternKeyPairGenerator.java
@@ -0,0 +1,365 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.crypto.params.NaccacheSternKeyGenerationParameters;
+import org.spongycastle.crypto.params.NaccacheSternKeyParameters;
+import org.spongycastle.crypto.params.NaccacheSternPrivateKeyParameters;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.Vector;
+
+/**
+ * Key generation parameters for NaccacheStern cipher. For details on this cipher, please see
+ *
+ * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+ */
+public class NaccacheSternKeyPairGenerator
+ implements AsymmetricCipherKeyPairGenerator
+{
+
+ private static int[] smallPrimes =
+ {
+ 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67,
+ 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149,
+ 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
+ 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331,
+ 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431,
+ 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523,
+ 541, 547, 557
+ };
+
+ private NaccacheSternKeyGenerationParameters param;
+
+ private static final BigInteger ONE = BigInteger.valueOf(1); // JDK 1.1 compatibility
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.spongycastle.crypto.AsymmetricCipherKeyPairGenerator#init(org.spongycastle.crypto.KeyGenerationParameters)
+ */
+ public void init(KeyGenerationParameters param)
+ {
+ this.param = (NaccacheSternKeyGenerationParameters)param;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.spongycastle.crypto.AsymmetricCipherKeyPairGenerator#generateKeyPair()
+ */
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+ int strength = param.getStrength();
+ SecureRandom rand = param.getRandom();
+ int certainty = param.getCertainty();
+ boolean debug = param.isDebug();
+
+ if (debug)
+ {
+ System.out.println("Fetching first " + param.getCntSmallPrimes() + " primes.");
+ }
+
+ Vector smallPrimes = findFirstPrimes(param.getCntSmallPrimes());
+ smallPrimes = permuteList(smallPrimes, rand);
+
+ BigInteger u = ONE;
+ BigInteger v = ONE;
+
+ for (int i = 0; i < smallPrimes.size() / 2; i++)
+ {
+ u = u.multiply((BigInteger)smallPrimes.elementAt(i));
+ }
+ for (int i = smallPrimes.size() / 2; i < smallPrimes.size(); i++)
+ {
+ v = v.multiply((BigInteger)smallPrimes.elementAt(i));
+ }
+
+ BigInteger sigma = u.multiply(v);
+
+ // n = (2 a u p_ + 1 ) ( 2 b v q_ + 1)
+ // -> |n| = strength
+ // |2| = 1 in bits
+ // -> |a| * |b| = |n| - |u| - |v| - |p_| - |q_| - |2| -|2|
+ // remainingStrength = strength - sigma.bitLength() - p_.bitLength() -
+ // q_.bitLength() - 1 -1
+ int remainingStrength = strength - sigma.bitLength() - 48;
+ BigInteger a = generatePrime(remainingStrength / 2 + 1, certainty, rand);
+ BigInteger b = generatePrime(remainingStrength / 2 + 1, certainty, rand);
+
+ BigInteger p_;
+ BigInteger q_;
+ BigInteger p;
+ BigInteger q;
+ long tries = 0;
+ if (debug)
+ {
+ System.out.println("generating p and q");
+ }
+
+ BigInteger _2au = a.multiply(u).shiftLeft(1);
+ BigInteger _2bv = b.multiply(v).shiftLeft(1);
+
+ for (;;)
+ {
+ tries++;
+
+ p_ = generatePrime(24, certainty, rand);
+
+ p = p_.multiply(_2au).add(ONE);
+
+ if (!p.isProbablePrime(certainty))
+ {
+ continue;
+ }
+
+ for (;;)
+ {
+ q_ = generatePrime(24, certainty, rand);
+
+ if (p_.equals(q_))
+ {
+ continue;
+ }
+
+ q = q_.multiply(_2bv).add(ONE);
+
+ if (q.isProbablePrime(certainty))
+ {
+ break;
+ }
+ }
+
+ if (!sigma.gcd(p_.multiply(q_)).equals(ONE))
+ {
+ // System.out.println("sigma.gcd(p_.mult(q_)) != 1!\n p_: " + p_
+ // +"\n q_: "+ q_ );
+ continue;
+ }
+
+ if (p.multiply(q).bitLength() < strength)
+ {
+ if (debug)
+ {
+ System.out.println("key size too small. Should be " + strength + " but is actually "
+ + p.multiply(q).bitLength());
+ }
+ continue;
+ }
+ break;
+ }
+
+ if (debug)
+ {
+ System.out.println("needed " + tries + " tries to generate p and q.");
+ }
+
+ BigInteger n = p.multiply(q);
+ BigInteger phi_n = p.subtract(ONE).multiply(q.subtract(ONE));
+ BigInteger g;
+ tries = 0;
+ if (debug)
+ {
+ System.out.println("generating g");
+ }
+ for (;;)
+ {
+
+ Vector gParts = new Vector();
+ for (int ind = 0; ind != smallPrimes.size(); ind++)
+ {
+ BigInteger i = (BigInteger)smallPrimes.elementAt(ind);
+ BigInteger e = phi_n.divide(i);
+
+ for (;;)
+ {
+ tries++;
+ g = new BigInteger(strength, certainty, rand);
+ if (g.modPow(e, n).equals(ONE))
+ {
+ continue;
+ }
+ gParts.addElement(g);
+ break;
+ }
+ }
+ g = ONE;
+ for (int i = 0; i < smallPrimes.size(); i++)
+ {
+ g = g.multiply(((BigInteger)gParts.elementAt(i)).modPow(sigma.divide((BigInteger)smallPrimes.elementAt(i)), n)).mod(n);
+ }
+
+ // make sure that g is not divisible by p_i or q_i
+ boolean divisible = false;
+ for (int i = 0; i < smallPrimes.size(); i++)
+ {
+ if (g.modPow(phi_n.divide((BigInteger)smallPrimes.elementAt(i)), n).equals(ONE))
+ {
+ if (debug)
+ {
+ System.out.println("g has order phi(n)/" + smallPrimes.elementAt(i) + "\n g: " + g);
+ }
+ divisible = true;
+ break;
+ }
+ }
+
+ if (divisible)
+ {
+ continue;
+ }
+
+ // make sure that g has order > phi_n/4
+
+ if (g.modPow(phi_n.divide(BigInteger.valueOf(4)), n).equals(ONE))
+ {
+ if (debug)
+ {
+ System.out.println("g has order phi(n)/4\n g:" + g);
+ }
+ continue;
+ }
+
+ if (g.modPow(phi_n.divide(p_), n).equals(ONE))
+ {
+ if (debug)
+ {
+ System.out.println("g has order phi(n)/p'\n g: " + g);
+ }
+ continue;
+ }
+ if (g.modPow(phi_n.divide(q_), n).equals(ONE))
+ {
+ if (debug)
+ {
+ System.out.println("g has order phi(n)/q'\n g: " + g);
+ }
+ continue;
+ }
+ if (g.modPow(phi_n.divide(a), n).equals(ONE))
+ {
+ if (debug)
+ {
+ System.out.println("g has order phi(n)/a\n g: " + g);
+ }
+ continue;
+ }
+ if (g.modPow(phi_n.divide(b), n).equals(ONE))
+ {
+ if (debug)
+ {
+ System.out.println("g has order phi(n)/b\n g: " + g);
+ }
+ continue;
+ }
+ break;
+ }
+ if (debug)
+ {
+ System.out.println("needed " + tries + " tries to generate g");
+ System.out.println();
+ System.out.println("found new NaccacheStern cipher variables:");
+ System.out.println("smallPrimes: " + smallPrimes);
+ System.out.println("sigma:...... " + sigma + " (" + sigma.bitLength() + " bits)");
+ System.out.println("a:.......... " + a);
+ System.out.println("b:.......... " + b);
+ System.out.println("p':......... " + p_);
+ System.out.println("q':......... " + q_);
+ System.out.println("p:.......... " + p);
+ System.out.println("q:.......... " + q);
+ System.out.println("n:.......... " + n);
+ System.out.println("phi(n):..... " + phi_n);
+ System.out.println("g:.......... " + g);
+ System.out.println();
+ }
+
+ return new AsymmetricCipherKeyPair(new NaccacheSternKeyParameters(false, g, n, sigma.bitLength()),
+ new NaccacheSternPrivateKeyParameters(g, n, sigma.bitLength(), smallPrimes, phi_n));
+ }
+
+ private static BigInteger generatePrime(
+ int bitLength,
+ int certainty,
+ SecureRandom rand)
+ {
+ BigInteger p_ = new BigInteger(bitLength, certainty, rand);
+ while (p_.bitLength() != bitLength)
+ {
+ p_ = new BigInteger(bitLength, certainty, rand);
+ }
+ return p_;
+ }
+
+ /**
+ * Generates a permuted ArrayList from the original one. The original List
+ * is not modified
+ *
+ * @param arr
+ * the ArrayList to be permuted
+ * @param rand
+ * the source of Randomness for permutation
+ * @return a new ArrayList with the permuted elements.
+ */
+ private static Vector permuteList(
+ Vector arr,
+ SecureRandom rand)
+ {
+ Vector retval = new Vector();
+ Vector tmp = new Vector();
+ for (int i = 0; i < arr.size(); i++)
+ {
+ tmp.addElement(arr.elementAt(i));
+ }
+ retval.addElement(tmp.elementAt(0));
+ tmp.removeElementAt(0);
+ while (tmp.size() != 0)
+ {
+ retval.insertElementAt(tmp.elementAt(0), getInt(rand, retval.size() + 1));
+ tmp.removeElementAt(0);
+ }
+ return retval;
+ }
+
+ private static int getInt(
+ SecureRandom rand,
+ int n)
+ {
+ if ((n & -n) == n)
+ {
+ return (int)((n * (long)(rand.nextInt() & 0x7fffffff)) >> 31);
+ }
+
+ int bits, val;
+ do
+ {
+ bits = rand.nextInt() & 0x7fffffff;
+ val = bits % n;
+ }
+ while (bits - val + (n-1) < 0);
+
+ return val;
+ }
+
+ /**
+ * Finds the first 'count' primes starting with 3
+ *
+ * @param count
+ * the number of primes to find
+ * @return a vector containing the found primes as Integer
+ */
+ private static Vector findFirstPrimes(
+ int count)
+ {
+ Vector primes = new Vector(count);
+
+ for (int i = 0; i != count; i++)
+ {
+ primes.addElement(BigInteger.valueOf(smallPrimes[i]));
+ }
+
+ return primes;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/OpenSSLPBEParametersGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/OpenSSLPBEParametersGenerator.java
new file mode 100644
index 00000000..70e35927
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/OpenSSLPBEParametersGenerator.java
@@ -0,0 +1,131 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.PBEParametersGenerator;
+import org.spongycastle.crypto.digests.MD5Digest;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+
+/**
+ * Generator for PBE derived keys and ivs as usd by OpenSSL.
+ * <p>
+ * The scheme is a simple extension of PKCS 5 V2.0 Scheme 1 using MD5 with an
+ * iteration count of 1.
+ * <p>
+ */
+public class OpenSSLPBEParametersGenerator
+ extends PBEParametersGenerator
+{
+ private Digest digest = new MD5Digest();
+
+ /**
+ * Construct a OpenSSL Parameters generator.
+ */
+ public OpenSSLPBEParametersGenerator()
+ {
+ }
+
+ /**
+ * Initialise - note the iteration count for this algorithm is fixed at 1.
+ *
+ * @param password password to use.
+ * @param salt salt to use.
+ */
+ public void init(
+ byte[] password,
+ byte[] salt)
+ {
+ super.init(password, salt, 1);
+ }
+
+ /**
+ * the derived key function, the ith hash of the password and the salt.
+ */
+ private byte[] generateDerivedKey(
+ int bytesNeeded)
+ {
+ byte[] buf = new byte[digest.getDigestSize()];
+ byte[] key = new byte[bytesNeeded];
+ int offset = 0;
+
+ for (;;)
+ {
+ digest.update(password, 0, password.length);
+ digest.update(salt, 0, salt.length);
+
+ digest.doFinal(buf, 0);
+
+ int len = (bytesNeeded > buf.length) ? buf.length : bytesNeeded;
+ System.arraycopy(buf, 0, key, offset, len);
+ offset += len;
+
+ // check if we need any more
+ bytesNeeded -= len;
+ if (bytesNeeded == 0)
+ {
+ break;
+ }
+
+ // do another round
+ digest.reset();
+ digest.update(buf, 0, buf.length);
+ }
+
+ return key;
+ }
+
+ /**
+ * Generate a key parameter derived from the password, salt, and iteration
+ * count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ * @exception IllegalArgumentException if the key length larger than the base hash size.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize)
+ {
+ keySize = keySize / 8;
+
+ byte[] dKey = generateDerivedKey(keySize);
+
+ return new KeyParameter(dKey, 0, keySize);
+ }
+
+ /**
+ * Generate a key with initialisation vector parameter derived from
+ * the password, salt, and iteration count we are currently initialised
+ * with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @param ivSize the size of the iv we want (in bits)
+ * @return a ParametersWithIV object.
+ * @exception IllegalArgumentException if keySize + ivSize is larger than the base hash size.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize,
+ int ivSize)
+ {
+ keySize = keySize / 8;
+ ivSize = ivSize / 8;
+
+ byte[] dKey = generateDerivedKey(keySize + ivSize);
+
+ return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
+ }
+
+ /**
+ * Generate a key parameter for use with a MAC derived from the password,
+ * salt, and iteration count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ * @exception IllegalArgumentException if the key length larger than the base hash size.
+ */
+ public CipherParameters generateDerivedMacParameters(
+ int keySize)
+ {
+ return generateDerivedParameters(keySize);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/PKCS12ParametersGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/PKCS12ParametersGenerator.java
new file mode 100644
index 00000000..ee40465e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/PKCS12ParametersGenerator.java
@@ -0,0 +1,220 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.ExtendedDigest;
+import org.spongycastle.crypto.PBEParametersGenerator;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+
+/**
+ * Generator for PBE derived keys and ivs as defined by PKCS 12 V1.0.
+ * <p>
+ * The document this implementation is based on can be found at
+ * <a href=http://www.rsasecurity.com/rsalabs/pkcs/pkcs-12/index.html>
+ * RSA's PKCS12 Page</a>
+ */
+public class PKCS12ParametersGenerator
+ extends PBEParametersGenerator
+{
+ public static final int KEY_MATERIAL = 1;
+ public static final int IV_MATERIAL = 2;
+ public static final int MAC_MATERIAL = 3;
+
+ private Digest digest;
+
+ private int u;
+ private int v;
+
+ /**
+ * Construct a PKCS 12 Parameters generator. This constructor will
+ * accept any digest which also implements ExtendedDigest.
+ *
+ * @param digest the digest to be used as the source of derived keys.
+ * @exception IllegalArgumentException if an unknown digest is passed in.
+ */
+ public PKCS12ParametersGenerator(
+ Digest digest)
+ {
+ this.digest = digest;
+ if (digest instanceof ExtendedDigest)
+ {
+ u = digest.getDigestSize();
+ v = ((ExtendedDigest)digest).getByteLength();
+ }
+ else
+ {
+ throw new IllegalArgumentException("Digest " + digest.getAlgorithmName() + " unsupported");
+ }
+ }
+
+ /**
+ * add a + b + 1, returning the result in a. The a value is treated
+ * as a BigInteger of length (b.length * 8) bits. The result is
+ * modulo 2^b.length in case of overflow.
+ */
+ private void adjust(
+ byte[] a,
+ int aOff,
+ byte[] b)
+ {
+ int x = (b[b.length - 1] & 0xff) + (a[aOff + b.length - 1] & 0xff) + 1;
+
+ a[aOff + b.length - 1] = (byte)x;
+ x >>>= 8;
+
+ for (int i = b.length - 2; i >= 0; i--)
+ {
+ x += (b[i] & 0xff) + (a[aOff + i] & 0xff);
+ a[aOff + i] = (byte)x;
+ x >>>= 8;
+ }
+ }
+
+ /**
+ * generation of a derived key ala PKCS12 V1.0.
+ */
+ private byte[] generateDerivedKey(
+ int idByte,
+ int n)
+ {
+ byte[] D = new byte[v];
+ byte[] dKey = new byte[n];
+
+ for (int i = 0; i != D.length; i++)
+ {
+ D[i] = (byte)idByte;
+ }
+
+ byte[] S;
+
+ if ((salt != null) && (salt.length != 0))
+ {
+ S = new byte[v * ((salt.length + v - 1) / v)];
+
+ for (int i = 0; i != S.length; i++)
+ {
+ S[i] = salt[i % salt.length];
+ }
+ }
+ else
+ {
+ S = new byte[0];
+ }
+
+ byte[] P;
+
+ if ((password != null) && (password.length != 0))
+ {
+ P = new byte[v * ((password.length + v - 1) / v)];
+
+ for (int i = 0; i != P.length; i++)
+ {
+ P[i] = password[i % password.length];
+ }
+ }
+ else
+ {
+ P = new byte[0];
+ }
+
+ byte[] I = new byte[S.length + P.length];
+
+ System.arraycopy(S, 0, I, 0, S.length);
+ System.arraycopy(P, 0, I, S.length, P.length);
+
+ byte[] B = new byte[v];
+ int c = (n + u - 1) / u;
+ byte[] A = new byte[u];
+
+ for (int i = 1; i <= c; i++)
+ {
+ digest.update(D, 0, D.length);
+ digest.update(I, 0, I.length);
+ digest.doFinal(A, 0);
+ for (int j = 1; j < iterationCount; j++)
+ {
+ digest.update(A, 0, A.length);
+ digest.doFinal(A, 0);
+ }
+
+ for (int j = 0; j != B.length; j++)
+ {
+ B[j] = A[j % A.length];
+ }
+
+ for (int j = 0; j != I.length / v; j++)
+ {
+ adjust(I, j * v, B);
+ }
+
+ if (i == c)
+ {
+ System.arraycopy(A, 0, dKey, (i - 1) * u, dKey.length - ((i - 1) * u));
+ }
+ else
+ {
+ System.arraycopy(A, 0, dKey, (i - 1) * u, A.length);
+ }
+ }
+
+ return dKey;
+ }
+
+ /**
+ * Generate a key parameter derived from the password, salt, and iteration
+ * count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize)
+ {
+ keySize = keySize / 8;
+
+ byte[] dKey = generateDerivedKey(KEY_MATERIAL, keySize);
+
+ return new KeyParameter(dKey, 0, keySize);
+ }
+
+ /**
+ * Generate a key with initialisation vector parameter derived from
+ * the password, salt, and iteration count we are currently initialised
+ * with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @param ivSize the size of the iv we want (in bits)
+ * @return a ParametersWithIV object.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize,
+ int ivSize)
+ {
+ keySize = keySize / 8;
+ ivSize = ivSize / 8;
+
+ byte[] dKey = generateDerivedKey(KEY_MATERIAL, keySize);
+
+ byte[] iv = generateDerivedKey(IV_MATERIAL, ivSize);
+
+ return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), iv, 0, ivSize);
+ }
+
+ /**
+ * Generate a key parameter for use with a MAC derived from the password,
+ * salt, and iteration count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ */
+ public CipherParameters generateDerivedMacParameters(
+ int keySize)
+ {
+ keySize = keySize / 8;
+
+ byte[] dKey = generateDerivedKey(MAC_MATERIAL, keySize);
+
+ return new KeyParameter(dKey, 0, keySize);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/PKCS5S1ParametersGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/PKCS5S1ParametersGenerator.java
new file mode 100644
index 00000000..3a6415f2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/PKCS5S1ParametersGenerator.java
@@ -0,0 +1,119 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.PBEParametersGenerator;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+
+/**
+ * Generator for PBE derived keys and ivs as defined by PKCS 5 V2.0 Scheme 1.
+ * Note this generator is limited to the size of the hash produced by the
+ * digest used to drive it.
+ * <p>
+ * The document this implementation is based on can be found at
+ * <a href=http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html>
+ * RSA's PKCS5 Page</a>
+ */
+public class PKCS5S1ParametersGenerator
+ extends PBEParametersGenerator
+{
+ private Digest digest;
+
+ /**
+ * Construct a PKCS 5 Scheme 1 Parameters generator.
+ *
+ * @param digest the digest to be used as the source of derived keys.
+ */
+ public PKCS5S1ParametersGenerator(
+ Digest digest)
+ {
+ this.digest = digest;
+ }
+
+ /**
+ * the derived key function, the ith hash of the password and the salt.
+ */
+ private byte[] generateDerivedKey()
+ {
+ byte[] digestBytes = new byte[digest.getDigestSize()];
+
+ digest.update(password, 0, password.length);
+ digest.update(salt, 0, salt.length);
+
+ digest.doFinal(digestBytes, 0);
+ for (int i = 1; i < iterationCount; i++)
+ {
+ digest.update(digestBytes, 0, digestBytes.length);
+ digest.doFinal(digestBytes, 0);
+ }
+
+ return digestBytes;
+ }
+
+ /**
+ * Generate a key parameter derived from the password, salt, and iteration
+ * count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ * @exception IllegalArgumentException if the key length larger than the base hash size.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize)
+ {
+ keySize = keySize / 8;
+
+ if (keySize > digest.getDigestSize())
+ {
+ throw new IllegalArgumentException(
+ "Can't generate a derived key " + keySize + " bytes long.");
+ }
+
+ byte[] dKey = generateDerivedKey();
+
+ return new KeyParameter(dKey, 0, keySize);
+ }
+
+ /**
+ * Generate a key with initialisation vector parameter derived from
+ * the password, salt, and iteration count we are currently initialised
+ * with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @param ivSize the size of the iv we want (in bits)
+ * @return a ParametersWithIV object.
+ * @exception IllegalArgumentException if keySize + ivSize is larger than the base hash size.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize,
+ int ivSize)
+ {
+ keySize = keySize / 8;
+ ivSize = ivSize / 8;
+
+ if ((keySize + ivSize) > digest.getDigestSize())
+ {
+ throw new IllegalArgumentException(
+ "Can't generate a derived key " + (keySize + ivSize) + " bytes long.");
+ }
+
+ byte[] dKey = generateDerivedKey();
+
+ return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
+ }
+
+ /**
+ * Generate a key parameter for use with a MAC derived from the password,
+ * salt, and iteration count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ * @exception IllegalArgumentException if the key length larger than the base hash size.
+ */
+ public CipherParameters generateDerivedMacParameters(
+ int keySize)
+ {
+ return generateDerivedParameters(keySize);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/PKCS5S2ParametersGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/PKCS5S2ParametersGenerator.java
new file mode 100644
index 00000000..59b5a187
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/PKCS5S2ParametersGenerator.java
@@ -0,0 +1,153 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.PBEParametersGenerator;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.macs.HMac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+
+/**
+ * Generator for PBE derived keys and ivs as defined by PKCS 5 V2.0 Scheme 2.
+ * This generator uses a SHA-1 HMac as the calculation function.
+ * <p>
+ * The document this implementation is based on can be found at
+ * <a href=http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html>
+ * RSA's PKCS5 Page</a>
+ */
+public class PKCS5S2ParametersGenerator
+ extends PBEParametersGenerator
+{
+ private Mac hMac;
+ private byte[] state;
+
+ /**
+ * construct a PKCS5 Scheme 2 Parameters generator.
+ */
+ public PKCS5S2ParametersGenerator()
+ {
+ this(new SHA1Digest());
+ }
+
+ public PKCS5S2ParametersGenerator(Digest digest)
+ {
+ hMac = new HMac(digest);
+ state = new byte[hMac.getMacSize()];
+ }
+
+ private void F(
+ byte[] S,
+ int c,
+ byte[] iBuf,
+ byte[] out,
+ int outOff)
+ {
+ if (c == 0)
+ {
+ throw new IllegalArgumentException("iteration count must be at least 1.");
+ }
+
+ if (S != null)
+ {
+ hMac.update(S, 0, S.length);
+ }
+
+ hMac.update(iBuf, 0, iBuf.length);
+ 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);
+ hMac.doFinal(state, 0);
+
+ for (int j = 0; j != state.length; j++)
+ {
+ out[outOff + j] ^= state[j];
+ }
+ }
+ }
+
+ private byte[] generateDerivedKey(
+ int dkLen)
+ {
+ int hLen = hMac.getMacSize();
+ int l = (dkLen + hLen - 1) / hLen;
+ byte[] iBuf = new byte[4];
+ byte[] outBytes = new byte[l * hLen];
+ int outPos = 0;
+
+ CipherParameters param = new KeyParameter(password);
+
+ hMac.init(param);
+
+ for (int i = 1; i <= l; i++)
+ {
+ // Increment the value in 'iBuf'
+ int pos = 3;
+ while (++iBuf[pos] == 0)
+ {
+ --pos;
+ }
+
+ F(salt, iterationCount, iBuf, outBytes, outPos);
+ outPos += hLen;
+ }
+
+ return outBytes;
+ }
+
+ /**
+ * Generate a key parameter derived from the password, salt, and iteration
+ * count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize)
+ {
+ keySize = keySize / 8;
+
+ byte[] dKey = generateDerivedKey(keySize);
+
+ return new KeyParameter(dKey, 0, keySize);
+ }
+
+ /**
+ * Generate a key with initialisation vector parameter derived from
+ * the password, salt, and iteration count we are currently initialised
+ * with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @param ivSize the size of the iv we want (in bits)
+ * @return a ParametersWithIV object.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize,
+ int ivSize)
+ {
+ keySize = keySize / 8;
+ ivSize = ivSize / 8;
+
+ byte[] dKey = generateDerivedKey(keySize + ivSize);
+
+ return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
+ }
+
+ /**
+ * Generate a key parameter for use with a MAC derived from the password,
+ * salt, and iteration count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ */
+ public CipherParameters generateDerivedMacParameters(
+ int keySize)
+ {
+ return generateDerivedParameters(keySize);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/Poly1305KeyGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/Poly1305KeyGenerator.java
new file mode 100644
index 00000000..4c5c148a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/Poly1305KeyGenerator.java
@@ -0,0 +1,117 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.CipherKeyGenerator;
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.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 key 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/core/src/main/java/org/spongycastle/crypto/generators/RSABlindingFactorGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/RSABlindingFactorGenerator.java
new file mode 100644
index 00000000..50b7db5e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/RSABlindingFactorGenerator.java
@@ -0,0 +1,77 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+import org.spongycastle.crypto.params.RSAPrivateCrtKeyParameters;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * Generate a random factor suitable for use with RSA blind signatures
+ * as outlined in Chaum's blinding and unblinding as outlined in
+ * "Handbook of Applied Cryptography", page 475.
+ */
+public class RSABlindingFactorGenerator
+{
+ private static BigInteger ZERO = BigInteger.valueOf(0);
+ private static BigInteger ONE = BigInteger.valueOf(1);
+
+ private RSAKeyParameters key;
+ private SecureRandom random;
+
+ /**
+ * Initialise the factor generator
+ *
+ * @param param the necessary RSA key parameters.
+ */
+ public void init(
+ CipherParameters param)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ key = (RSAKeyParameters)rParam.getParameters();
+ random = rParam.getRandom();
+ }
+ else
+ {
+ key = (RSAKeyParameters)param;
+ random = new SecureRandom();
+ }
+
+ if (key instanceof RSAPrivateCrtKeyParameters)
+ {
+ throw new IllegalArgumentException("generator requires RSA public key");
+ }
+ }
+
+ /**
+ * Generate a suitable blind factor for the public key the generator was initialised with.
+ *
+ * @return a random blind factor
+ */
+ public BigInteger generateBlindingFactor()
+ {
+ if (key == null)
+ {
+ throw new IllegalStateException("generator not initialised");
+ }
+
+ BigInteger m = key.getModulus();
+ int length = m.bitLength() - 1; // must be less than m.bitLength()
+ BigInteger factor;
+ BigInteger gcd;
+
+ do
+ {
+ factor = new BigInteger(length, random);
+ gcd = factor.gcd(m);
+ }
+ while (factor.equals(ZERO) || factor.equals(ONE) || !gcd.equals(ONE));
+
+ return factor;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/RSAKeyPairGenerator.java b/core/src/main/java/org/spongycastle/crypto/generators/RSAKeyPairGenerator.java
new file mode 100644
index 00000000..354eccd2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/RSAKeyPairGenerator.java
@@ -0,0 +1,153 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.crypto.params.RSAKeyGenerationParameters;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+import org.spongycastle.crypto.params.RSAPrivateCrtKeyParameters;
+import org.spongycastle.math.ec.WNafUtil;
+
+import java.math.BigInteger;
+
+/**
+ * an RSA key pair generator.
+ */
+public class RSAKeyPairGenerator
+ implements AsymmetricCipherKeyPairGenerator
+{
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ private RSAKeyGenerationParameters param;
+
+ public void init(KeyGenerationParameters param)
+ {
+ this.param = (RSAKeyGenerationParameters)param;
+ }
+
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+ BigInteger p, q, n, d, e, pSub1, qSub1, phi;
+
+ //
+ // p and q values should have a length of half the strength in bits
+ //
+ int strength = param.getStrength();
+ int qBitlength = strength >>> 1;
+ int pBitlength = strength - qBitlength;
+ int mindiffbits = strength / 3;
+ int minWeight = strength >>> 2;
+
+ e = param.getPublicExponent();
+
+ // TODO Consider generating safe primes for p, q (see DHParametersHelper.generateSafePrimes)
+ // (then p-1 and q-1 will not consist of only small factors - see "Pollard's algorithm")
+
+ p = chooseRandomPrime(pBitlength, e);
+
+ //
+ // generate a modulus of the required length
+ //
+ for (;;)
+ {
+ q = chooseRandomPrime(qBitlength, e);
+
+ // p and q should not be too close together (or equal!)
+ BigInteger diff = q.subtract(p).abs();
+ if (diff.bitLength() < mindiffbits)
+ {
+ continue;
+ }
+
+ //
+ // calculate the modulus
+ //
+ n = p.multiply(q);
+
+ if (n.bitLength() != strength)
+ {
+ //
+ // if we get here our primes aren't big enough, make the largest
+ // of the two p and try again
+ //
+ p = p.max(q);
+ continue;
+ }
+
+ /*
+ * Require a minimum weight of the NAF representation, since low-weight composites may
+ * be weak against a version of the number-field-sieve for factoring.
+ *
+ * See "The number field sieve for integers of low weight", Oliver Schirokauer.
+ */
+ if (WNafUtil.getNafWeight(n) < minWeight)
+ {
+ p = chooseRandomPrime(pBitlength, e);
+ continue;
+ }
+
+ break;
+ }
+
+ if (p.compareTo(q) < 0)
+ {
+ phi = p;
+ p = q;
+ q = phi;
+ }
+
+ pSub1 = p.subtract(ONE);
+ qSub1 = q.subtract(ONE);
+ phi = pSub1.multiply(qSub1);
+
+ //
+ // calculate the private exponent
+ //
+ d = e.modInverse(phi);
+
+ //
+ // calculate the CRT factors
+ //
+ BigInteger dP, dQ, qInv;
+
+ dP = d.remainder(pSub1);
+ dQ = d.remainder(qSub1);
+ qInv = q.modInverse(p);
+
+ return new AsymmetricCipherKeyPair(
+ new RSAKeyParameters(false, n, e),
+ new RSAPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv));
+ }
+
+ /**
+ * Choose a random prime value for use with RSA
+ *
+ * @param bitlength the bit-length of the returned prime
+ * @param e the RSA public exponent
+ * @return a prime p, with (p-1) relatively prime to e
+ */
+ protected BigInteger chooseRandomPrime(int bitlength, BigInteger e)
+ {
+ for (;;)
+ {
+ BigInteger p = new BigInteger(bitlength, 1, param.getRandom());
+
+ if (p.mod(e).equals(ONE))
+ {
+ continue;
+ }
+
+ if (!p.isProbablePrime(param.getCertainty()))
+ {
+ continue;
+ }
+
+ if (!e.gcd(p.subtract(ONE)).equals(ONE))
+ {
+ continue;
+ }
+
+ return p;
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/generators/SCrypt.java b/core/src/main/java/org/spongycastle/crypto/generators/SCrypt.java
new file mode 100644
index 00000000..58d59baf
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/generators/SCrypt.java
@@ -0,0 +1,198 @@
+package org.spongycastle.crypto.generators;
+
+import org.spongycastle.crypto.PBEParametersGenerator;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.engines.Salsa20Engine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Pack;
+
+/**
+ * Implementation of the scrypt a password-based key derivation function.
+ * <p>
+ * Scrypt was created by Colin Percival and is specified in <a
+ * href="http://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01">draft-josefsson-scrypt-kd</a>
+ *
+ */
+public class SCrypt
+{
+ /**
+ * Generate a key using the scrypt key derivation function.
+ *
+ * @param P the bytes of the pass phrase.
+ * @param S the salt to use for this invocation.
+ * @param N CPU/Memory cost parameter. Must be larger than 1, a power of 2 and less than
+ * <code>2^(128 * r / 8)</code>.
+ * @param r the block size, must be >= 1.
+ * @param p Parallelization parameter. Must be a positive integer less than or equal to
+ * <code>Integer.MAX_VALUE / (128 * r * 8)</code>.
+ *
+ * @param dkLen the length of the key to generate.
+ * @return the generated key.
+ */
+ public static byte[] generate(byte[] P, byte[] S, int N, int r, int p, int dkLen)
+ {
+ if (P== null)
+ {
+ throw new IllegalArgumentException("Passphrase P must be provided.");
+ }
+ if (S == null)
+ {
+ throw new IllegalArgumentException("Salt S must be provided.");
+ }
+ if (N <= 1)
+ {
+ throw new IllegalArgumentException("Cost parameter N must be > 1.");
+ }
+ // Only value of r that cost (as an int) could be exceeded for is 1
+ if (r == 1 && N > 65536)
+ {
+ throw new IllegalArgumentException("Cost parameter N must be > 1 and < 65536.");
+ }
+ if (r < 1)
+ {
+ throw new IllegalArgumentException("Block size r must be >= 1.");
+ }
+ int maxParallel = Integer.MAX_VALUE / (128 * r * 8);
+ if (p < 1 || p > maxParallel)
+ {
+ throw new IllegalArgumentException("Parallelisation parameter p must be >= 1 and <= " + maxParallel
+ + " (based on block size r of " + r + ")");
+ }
+ if (dkLen < 1)
+ {
+ throw new IllegalArgumentException("Generated key length dkLen must be >= 1.");
+ }
+ return MFcrypt(P, S, N, r, p, dkLen);
+ }
+
+ private static byte[] MFcrypt(byte[] P, byte[] S, int N, int r, int p, int dkLen)
+ {
+ int MFLenBytes = r * 128;
+ byte[] bytes = SingleIterationPBKDF2(P, S, p * MFLenBytes);
+
+ int[] B = null;
+
+ try
+ {
+ int BLen = bytes.length >>> 2;
+ B = new int[BLen];
+
+ Pack.littleEndianToInt(bytes, 0, B);
+
+ int MFLenWords = MFLenBytes >>> 2;
+ for (int BOff = 0; BOff < BLen; BOff += MFLenWords)
+ {
+ // TODO These can be done in parallel threads
+ SMix(B, BOff, N, r);
+ }
+
+ Pack.intToLittleEndian(B, bytes, 0);
+
+ return SingleIterationPBKDF2(P, bytes, dkLen);
+ }
+ finally
+ {
+ Clear(bytes);
+ Clear(B);
+ }
+ }
+
+ private static byte[] SingleIterationPBKDF2(byte[] P, byte[] S, int dkLen)
+ {
+ PBEParametersGenerator pGen = new PKCS5S2ParametersGenerator(new SHA256Digest());
+ pGen.init(P, S, 1);
+ KeyParameter key = (KeyParameter) pGen.generateDerivedMacParameters(dkLen * 8);
+ return key.getKey();
+ }
+
+ private static void SMix(int[] B, int BOff, int N, int r)
+ {
+ int BCount = r * 32;
+
+ int[] blockX1 = new int[16];
+ int[] blockX2 = new int[16];
+ int[] blockY = new int[BCount];
+
+ int[] X = new int[BCount];
+ int[][] V = new int[N][];
+
+ try
+ {
+ System.arraycopy(B, BOff, X, 0, BCount);
+
+ for (int i = 0; i < N; ++i)
+ {
+ V[i] = Arrays.clone(X);
+ BlockMix(X, blockX1, blockX2, blockY, r);
+ }
+
+ int mask = N - 1;
+ for (int i = 0; i < N; ++i)
+ {
+ int j = X[BCount - 16] & mask;
+ Xor(X, V[j], 0, X);
+ BlockMix(X, blockX1, blockX2, blockY, r);
+ }
+
+ System.arraycopy(X, 0, B, BOff, BCount);
+ }
+ finally
+ {
+ ClearAll(V);
+ ClearAll(new int[][]{ X, blockX1, blockX2, blockY });
+ }
+ }
+
+ private static void BlockMix(int[] B, int[] X1, int[] X2, int[] Y, int r)
+ {
+ System.arraycopy(B, B.length - 16, X1, 0, 16);
+
+ int BOff = 0, YOff = 0, halfLen = B.length >>> 1;
+
+ for (int i = 2 * r; i > 0; --i)
+ {
+ Xor(X1, B, BOff, X2);
+
+ Salsa20Engine.salsaCore(8, X2, X1);
+ System.arraycopy(X1, 0, Y, YOff, 16);
+
+ YOff = halfLen + BOff - YOff;
+ BOff += 16;
+ }
+
+ System.arraycopy(Y, 0, B, 0, Y.length);
+ }
+
+ private static void Xor(int[] a, int[] b, int bOff, int[] output)
+ {
+ for (int i = output.length - 1; i >= 0; --i)
+ {
+ output[i] = a[i] ^ b[bOff + i];
+ }
+ }
+
+ private static void Clear(byte[] array)
+ {
+ if (array != null)
+ {
+ Arrays.fill(array, (byte)0);
+ }
+ }
+
+ private static void Clear(int[] array)
+ {
+ if (array != null)
+ {
+ Arrays.fill(array, 0);
+ }
+ }
+
+ private static void ClearAll(int[][] arrays)
+ {
+ for (int i = 0; i < arrays.length; ++i)
+ {
+ Clear(arrays[i]);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/io/CipherIOException.java b/core/src/main/java/org/spongycastle/crypto/io/CipherIOException.java
new file mode 100644
index 00000000..c621c6b1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/io/CipherIOException.java
@@ -0,0 +1,26 @@
+package org.spongycastle.crypto.io;
+
+import java.io.IOException;
+
+/**
+ * {@link IOException} wrapper around an exception indicating a problem with the use of a cipher.
+ */
+public class CipherIOException
+ extends IOException
+{
+ private static final long serialVersionUID = 1L;
+
+ private final Throwable cause;
+
+ public CipherIOException(String message, Throwable cause)
+ {
+ super(message);
+
+ this.cause = cause;
+ }
+
+ public Throwable getCause()
+ {
+ return cause;
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/crypto/io/CipherInputStream.java b/core/src/main/java/org/spongycastle/crypto/io/CipherInputStream.java
new file mode 100644
index 00000000..625e6659
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/io/CipherInputStream.java
@@ -0,0 +1,477 @@
+package org.spongycastle.crypto.io;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.spongycastle.crypto.BufferedBlockCipher;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.SkippingCipher;
+import org.spongycastle.crypto.StreamCipher;
+import org.spongycastle.crypto.modes.AEADBlockCipher;
+import org.spongycastle.util.Arrays;
+
+/**
+ * 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.
+ */
+public class CipherInputStream
+ extends FilterInputStream
+{
+ private static final int INPUT_BUF_SIZE = 2048;
+
+ private SkippingCipher skippingCipher;
+ private byte[] inBuf;
+
+ private BufferedBlockCipher bufferedBlockCipher;
+ private StreamCipher streamCipher;
+ private AEADBlockCipher aeadBlockCipher;
+
+ private byte[] buf;
+ private byte[] markBuf;
+
+
+ private int bufOff;
+ private int maxBuf;
+ private boolean finalized;
+ private long markPosition;
+ private int markBufOff;
+
+ /**
+ * Constructs a CipherInputStream from an InputStream and a
+ * BufferedBlockCipher.
+ */
+ public CipherInputStream(
+ InputStream is,
+ BufferedBlockCipher cipher)
+ {
+ this(is, cipher, INPUT_BUF_SIZE);
+ }
+
+ /**
+ * Constructs a CipherInputStream from an InputStream and a StreamCipher.
+ */
+ public CipherInputStream(
+ InputStream is,
+ StreamCipher cipher)
+ {
+ this(is, cipher, INPUT_BUF_SIZE);
+ }
+
+ /**
+ * Constructs a CipherInputStream from an InputStream and an AEADBlockCipher.
+ */
+ public CipherInputStream(
+ InputStream is,
+ AEADBlockCipher cipher)
+ {
+ this(is, cipher, INPUT_BUF_SIZE);
+ }
+
+ /**
+ * Constructs a CipherInputStream from an InputStream, a
+ * BufferedBlockCipher, and a specified internal buffer size.
+ */
+ public CipherInputStream(
+ InputStream is,
+ BufferedBlockCipher cipher,
+ int bufSize)
+ {
+ super(is);
+
+ this.bufferedBlockCipher = cipher;
+ this.inBuf = new byte[bufSize];
+ this.skippingCipher = (cipher instanceof SkippingCipher) ? (SkippingCipher)cipher : null;
+ }
+
+ /**
+ * Constructs a CipherInputStream from an InputStream, a StreamCipher, and a specified internal buffer size.
+ */
+ public CipherInputStream(
+ InputStream is,
+ StreamCipher cipher,
+ int bufSize)
+ {
+ super(is);
+
+ this.streamCipher = cipher;
+ this.inBuf = new byte[bufSize];
+ this.skippingCipher = (cipher instanceof SkippingCipher) ? (SkippingCipher)cipher : null;
+ }
+
+ /**
+ * Constructs a CipherInputStream from an InputStream, an AEADBlockCipher, and a specified internal buffer size.
+ */
+ public CipherInputStream(
+ InputStream is,
+ AEADBlockCipher cipher,
+ int bufSize)
+ {
+ super(is);
+
+ this.aeadBlockCipher = cipher;
+ this.inBuf = new byte[bufSize];
+ this.skippingCipher = (cipher instanceof SkippingCipher) ? (SkippingCipher)cipher : null;
+ }
+
+ /**
+ * 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(inBuf);
+ if (read == -1)
+ {
+ finaliseCipher();
+ if (maxBuf == 0)
+ {
+ return -1;
+ }
+ return maxBuf;
+ }
+
+ try
+ {
+ ensureCapacity(read, false);
+ if (bufferedBlockCipher != null)
+ {
+ maxBuf = bufferedBlockCipher.processBytes(inBuf, 0, read, buf, 0);
+ }
+ else if (aeadBlockCipher != null)
+ {
+ maxBuf = aeadBlockCipher.processBytes(inBuf, 0, read, buf, 0);
+ }
+ else
+ {
+ streamCipher.processBytes(inBuf, 0, read, buf, 0);
+ maxBuf = read;
+ }
+ }
+ catch (Exception e)
+ {
+ throw new CipherIOException("Error processing stream ", e);
+ }
+ }
+ return maxBuf;
+ }
+
+ private void finaliseCipher()
+ throws IOException
+ {
+ try
+ {
+ finalized = true;
+ ensureCapacity(0, true);
+ if (bufferedBlockCipher != null)
+ {
+ maxBuf = bufferedBlockCipher.doFinal(buf, 0);
+ }
+ else if (aeadBlockCipher != null)
+ {
+ maxBuf = aeadBlockCipher.doFinal(buf, 0);
+ }
+ else
+ {
+ maxBuf = 0; // a stream cipher
+ }
+ }
+ 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.
+ * </p>
+ * @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>b.length</code> bytes in the provided array.
+ * <p>
+ * If the underlying stream is exhausted by this call, the cipher will be finalised.
+ * </p>
+ * @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
+ {
+ 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.
+ * </p>
+ * @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;
+ }
+
+ if (skippingCipher != null)
+ {
+ int avail = available();
+ if (n <= avail)
+ {
+ bufOff += n;
+
+ return n;
+ }
+
+ bufOff = maxBuf;
+
+ long skip = in.skip(n - avail);
+
+ long cSkip = skippingCipher.skip(skip);
+
+ if (skip != cSkip)
+ {
+ throw new IOException("Unable to skip cipher " + skip + " bytes.");
+ }
+
+ return skip + avail;
+ }
+ else
+ {
+ int skip = (int)Math.min(n, available());
+ bufOff += skip;
+
+ return skip;
+ }
+ }
+
+ public int available()
+ throws IOException
+ {
+ return maxBuf - bufOff;
+ }
+
+ /**
+ * Ensure the cipher text buffer has space sufficient to accept an upcoming output.
+ *
+ * @param updateSize the size of the pending update.
+ * @param finalOutput <code>true</code> iff this the cipher is to be finalised.
+ */
+ private void ensureCapacity(int updateSize, boolean finalOutput)
+ {
+ int bufLen = updateSize;
+ if (finalOutput)
+ {
+ if (bufferedBlockCipher != null)
+ {
+ bufLen = bufferedBlockCipher.getOutputSize(updateSize);
+ }
+ else if (aeadBlockCipher != null)
+ {
+ bufLen = aeadBlockCipher.getOutputSize(updateSize);
+ }
+ }
+ else
+ {
+ if (bufferedBlockCipher != null)
+ {
+ bufLen = bufferedBlockCipher.getUpdateOutputSize(updateSize);
+ }
+ else if (aeadBlockCipher != null)
+ {
+ bufLen = aeadBlockCipher.getUpdateOutputSize(updateSize);
+ }
+ }
+
+ if ((buf == null) || (buf.length < bufLen))
+ {
+ buf = new byte[bufLen];
+ }
+ }
+
+ /**
+ * 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();
+ }
+ 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;
+ markBufOff = 0;
+ markPosition = 0;
+ if (markBuf != null)
+ {
+ Arrays.fill(markBuf, (byte)0);
+ markBuf = null;
+ }
+ if (buf != null)
+ {
+ Arrays.fill(buf, (byte)0);
+ buf = null;
+ }
+ Arrays.fill(inBuf, (byte)0);
+ }
+
+ /**
+ * Mark the current position.
+ * <p>
+ * This method only works if markSupported() returns true - which means the underlying stream supports marking, and the cipher passed
+ * in to this stream's constructor is a SkippingCipher (so capable of being reset to an arbitrary point easily).
+ * </p>
+ * @param readlimit the maximum read ahead required before a reset() may be called.
+ */
+ public void mark(int readlimit)
+ {
+ in.mark(readlimit);
+ if (skippingCipher != null)
+ {
+ markPosition = skippingCipher.getPosition();
+ }
+
+ if (buf != null)
+ {
+ markBuf = new byte[buf.length];
+ System.arraycopy(buf, 0, markBuf, 0, buf.length);
+ }
+
+ markBufOff = bufOff;
+ }
+
+ /**
+ * Reset to the last marked position, if supported.
+ *
+ * @throws IOException if marking not supported by the cipher used, or the underlying stream.
+ */
+ public void reset()
+ throws IOException
+ {
+ if (skippingCipher == null)
+ {
+ throw new IOException("cipher must implement SkippingCipher to be used with reset()");
+ }
+
+ in.reset();
+
+ skippingCipher.seekTo(markPosition);
+
+ if (markBuf != null)
+ {
+ buf = markBuf;
+ }
+
+ bufOff = markBufOff;
+ }
+
+ /**
+ * Return true if mark(readlimit) is supported. This will be true if the underlying stream supports marking and the
+ * cipher used is a SkippingCipher,
+ *
+ * @return true if mark(readlimit) supported, false otherwise.
+ */
+ public boolean markSupported()
+ {
+ if (skippingCipher != null)
+ {
+ return in.markSupported();
+ }
+
+ return false;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/io/CipherOutputStream.java b/core/src/main/java/org/spongycastle/crypto/io/CipherOutputStream.java
new file mode 100644
index 00000000..e45962f3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/io/CipherOutputStream.java
@@ -0,0 +1,276 @@
+package org.spongycastle.crypto.io;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.spongycastle.crypto.BufferedBlockCipher;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.StreamCipher;
+import org.spongycastle.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 final byte[] oneByte = new byte[1];
+ private byte[] buf;
+
+ /**
+ * Constructs a CipherOutputStream from an OutputStream and a
+ * BufferedBlockCipher.
+ */
+ public CipherOutputStream(
+ OutputStream os,
+ BufferedBlockCipher cipher)
+ {
+ super(os);
+ this.bufferedBlockCipher = cipher;
+ }
+
+ /**
+ * Constructs a CipherOutputStream from an OutputStream and a
+ * BufferedBlockCipher.
+ */
+ public CipherOutputStream(
+ OutputStream os,
+ StreamCipher cipher)
+ {
+ super(os);
+ this.streamCipher = cipher;
+ }
+
+ /**
+ * 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>.
+ * @throws java.io.IOException if an I/O error occurs.
+ */
+ public void write(
+ int b)
+ throws IOException
+ {
+ oneByte[0] = (byte)b;
+
+ if (streamCipher != null)
+ {
+ out.write(streamCipher.returnByte((byte)b));
+ }
+ else
+ {
+ write(oneByte, 0, 1);
+ }
+ }
+
+ /**
+ * Writes <code>b.length</code> bytes from the specified byte array
+ * to this output stream.
+ * <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.
+ * @throws java.io.IOException if an I/O error occurs.
+ * @see #write(byte[], int, int)
+ */
+ public void write(
+ byte[] b)
+ throws IOException
+ {
+ write(b, 0, b.length);
+ }
+
+ /**
+ * 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
+ {
+ ensureCapacity(len, false);
+
+ if (bufferedBlockCipher != null)
+ {
+ int outLen = bufferedBlockCipher.processBytes(b, off, len, buf, 0);
+
+ if (outLen != 0)
+ {
+ out.write(buf, 0, outLen);
+ }
+ }
+ else if (aeadBlockCipher != null)
+ {
+ 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);
+ }
+ }
+
+ /**
+ * Ensure the ciphertext buffer has space sufficient to accept an upcoming output.
+ *
+ * @param updateSize the size of the pending update.
+ * @param finalOutput <code>true</code> iff this the cipher is to be finalised.
+ */
+ private void ensureCapacity(int updateSize, boolean finalOutput)
+ {
+ int bufLen = updateSize;
+ if (finalOutput)
+ {
+ if (bufferedBlockCipher != null)
+ {
+ bufLen = bufferedBlockCipher.getOutputSize(updateSize);
+ }
+ else if (aeadBlockCipher != null)
+ {
+ bufLen = aeadBlockCipher.getOutputSize(updateSize);
+ }
+ }
+ else
+ {
+ if (bufferedBlockCipher != null)
+ {
+ bufLen = bufferedBlockCipher.getUpdateOutputSize(updateSize);
+ }
+ else if (aeadBlockCipher != null)
+ {
+ bufLen = aeadBlockCipher.getUpdateOutputSize(updateSize);
+ }
+ }
+
+ 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>
+ * 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
+ {
+ ensureCapacity(0, true);
+ IOException error = null;
+ try
+ {
+ if (bufferedBlockCipher != null)
+ {
+ int outLen = bufferedBlockCipher.doFinal(buf, 0);
+
+ if (outLen != 0)
+ {
+ 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)
+ {
+ error = new CipherIOException("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/core/src/main/java/org/spongycastle/crypto/io/DigestInputStream.java b/core/src/main/java/org/spongycastle/crypto/io/DigestInputStream.java
new file mode 100644
index 00000000..23a71964
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/io/DigestInputStream.java
@@ -0,0 +1,52 @@
+package org.spongycastle.crypto.io;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.spongycastle.crypto.Digest;
+
+public class DigestInputStream
+ extends FilterInputStream
+{
+ protected Digest digest;
+
+ public DigestInputStream(
+ InputStream stream,
+ Digest digest)
+ {
+ super(stream);
+ this.digest = digest;
+ }
+
+ public int read()
+ throws IOException
+ {
+ int b = in.read();
+
+ if (b >= 0)
+ {
+ digest.update((byte)b);
+ }
+ return b;
+ }
+
+ public int read(
+ byte[] b,
+ int off,
+ int len)
+ throws IOException
+ {
+ int n = in.read(b, off, len);
+ if (n > 0)
+ {
+ digest.update(b, off, n);
+ }
+ return n;
+ }
+
+ public Digest getDigest()
+ {
+ return digest;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/io/DigestOutputStream.java b/core/src/main/java/org/spongycastle/crypto/io/DigestOutputStream.java
new file mode 100644
index 00000000..d280b514
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/io/DigestOutputStream.java
@@ -0,0 +1,42 @@
+package org.spongycastle.crypto.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.spongycastle.crypto.Digest;
+
+public class DigestOutputStream
+ extends OutputStream
+{
+ protected Digest digest;
+
+ public DigestOutputStream(
+ Digest Digest)
+ {
+ this.digest = Digest;
+ }
+
+ public void write(int b)
+ throws IOException
+ {
+ digest.update((byte)b);
+ }
+
+ public void write(
+ byte[] b,
+ int off,
+ int len)
+ throws IOException
+ {
+ digest.update(b, off, len);
+ }
+
+ public byte[] getDigest()
+ {
+ byte[] res = new byte[digest.getDigestSize()];
+
+ digest.doFinal(res, 0);
+
+ return res;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/io/InvalidCipherTextIOException.java b/core/src/main/java/org/spongycastle/crypto/io/InvalidCipherTextIOException.java
new file mode 100644
index 00000000..fd488a97
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/io/InvalidCipherTextIOException.java
@@ -0,0 +1,19 @@
+package org.spongycastle.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 CipherIOException
+{
+ private static final long serialVersionUID = 1L;
+
+ public InvalidCipherTextIOException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/crypto/io/MacInputStream.java b/core/src/main/java/org/spongycastle/crypto/io/MacInputStream.java
new file mode 100644
index 00000000..35e0e9c2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/io/MacInputStream.java
@@ -0,0 +1,52 @@
+package org.spongycastle.crypto.io;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.spongycastle.crypto.Mac;
+
+public class MacInputStream
+ extends FilterInputStream
+{
+ protected Mac mac;
+
+ public MacInputStream(
+ InputStream stream,
+ Mac mac)
+ {
+ super(stream);
+ this.mac = mac;
+ }
+
+ public int read()
+ throws IOException
+ {
+ int b = in.read();
+
+ if (b >= 0)
+ {
+ mac.update((byte)b);
+ }
+ return b;
+ }
+
+ public int read(
+ byte[] b,
+ int off,
+ int len)
+ throws IOException
+ {
+ int n = in.read(b, off, len);
+ if (n >= 0)
+ {
+ mac.update(b, off, n);
+ }
+ return n;
+ }
+
+ public Mac getMac()
+ {
+ return mac;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/io/MacOutputStream.java b/core/src/main/java/org/spongycastle/crypto/io/MacOutputStream.java
new file mode 100644
index 00000000..340b994e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/io/MacOutputStream.java
@@ -0,0 +1,42 @@
+package org.spongycastle.crypto.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.spongycastle.crypto.Mac;
+
+public class MacOutputStream
+ extends OutputStream
+{
+ protected Mac mac;
+
+ public MacOutputStream(
+ Mac mac)
+ {
+ this.mac = mac;
+ }
+
+ public void write(int b)
+ throws IOException
+ {
+ mac.update((byte)b);
+ }
+
+ public void write(
+ byte[] b,
+ int off,
+ int len)
+ throws IOException
+ {
+ mac.update(b, off, len);
+ }
+
+ public byte[] getMac()
+ {
+ byte[] res = new byte[mac.getMacSize()];
+
+ mac.doFinal(res, 0);
+
+ return res;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/io/SignerInputStream.java b/core/src/main/java/org/spongycastle/crypto/io/SignerInputStream.java
new file mode 100644
index 00000000..f7f6935f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/io/SignerInputStream.java
@@ -0,0 +1,52 @@
+package org.spongycastle.crypto.io;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.spongycastle.crypto.Signer;
+
+public class SignerInputStream
+ extends FilterInputStream
+{
+ protected Signer signer;
+
+ public SignerInputStream(
+ InputStream stream,
+ Signer signer)
+ {
+ super(stream);
+ this.signer = signer;
+ }
+
+ public int read()
+ throws IOException
+ {
+ int b = in.read();
+
+ if (b >= 0)
+ {
+ signer.update((byte)b);
+ }
+ return b;
+ }
+
+ public int read(
+ byte[] b,
+ int off,
+ int len)
+ throws IOException
+ {
+ int n = in.read(b, off, len);
+ if (n > 0)
+ {
+ signer.update(b, off, n);
+ }
+ return n;
+ }
+
+ public Signer getSigner()
+ {
+ return signer;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/io/SignerOutputStream.java b/core/src/main/java/org/spongycastle/crypto/io/SignerOutputStream.java
new file mode 100644
index 00000000..6e6c55b1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/io/SignerOutputStream.java
@@ -0,0 +1,38 @@
+package org.spongycastle.crypto.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.spongycastle.crypto.Signer;
+
+public class SignerOutputStream
+ extends OutputStream
+{
+ protected Signer signer;
+
+ public SignerOutputStream(
+ Signer Signer)
+ {
+ this.signer = Signer;
+ }
+
+ public void write(int b)
+ throws IOException
+ {
+ signer.update((byte)b);
+ }
+
+ public void write(
+ byte[] b,
+ int off,
+ int len)
+ throws IOException
+ {
+ signer.update(b, off, len);
+ }
+
+ public Signer getSigner()
+ {
+ return signer;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/kems/ECIESKeyEncapsulation.java b/core/src/main/java/org/spongycastle/crypto/kems/ECIESKeyEncapsulation.java
new file mode 100755
index 00000000..500ac3ed
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/kems/ECIESKeyEncapsulation.java
@@ -0,0 +1,244 @@
+package org.spongycastle.crypto.kems;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DerivationFunction;
+import org.spongycastle.crypto.KeyEncapsulation;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECKeyParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.crypto.params.KDFParameters;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECMultiplier;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.ec.FixedPointCombMultiplier;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.BigIntegers;
+
+/**
+ * The ECIES Key Encapsulation Mechanism (ECIES-KEM) from ISO 18033-2.
+ */
+public class ECIESKeyEncapsulation
+ implements KeyEncapsulation
+{
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ private DerivationFunction kdf;
+ private SecureRandom rnd;
+ private ECKeyParameters key;
+ private boolean CofactorMode;
+ private boolean OldCofactorMode;
+ private boolean SingleHashMode;
+
+ /**
+ * Set up the ECIES-KEM.
+ *
+ * @param kdf the key derivation function to be used.
+ * @param rnd the random source for the session key.
+ */
+ public ECIESKeyEncapsulation(
+ DerivationFunction kdf,
+ SecureRandom rnd)
+ {
+ this.kdf = kdf;
+ this.rnd = rnd;
+ this.CofactorMode = false;
+ this.OldCofactorMode = false;
+ this.SingleHashMode = false;
+ }
+
+ /**
+ * Set up the ECIES-KEM.
+ *
+ * @param kdf the key derivation function to be used.
+ * @param rnd the random source for the session key.
+ * @param cofactorMode true to use the new cofactor ECDH.
+ * @param oldCofactorMode true to use the old cofactor ECDH.
+ * @param singleHashMode true to use single hash mode.
+ */
+ public ECIESKeyEncapsulation(
+ DerivationFunction kdf,
+ SecureRandom rnd,
+ boolean cofactorMode,
+ boolean oldCofactorMode,
+ boolean singleHashMode)
+ {
+ this.kdf = kdf;
+ this.rnd = rnd;
+
+ // If both cofactorMode and oldCofactorMode are set to true
+ // then the implementation will use the new cofactor ECDH
+ this.CofactorMode = cofactorMode;
+ this.OldCofactorMode = oldCofactorMode;
+ this.SingleHashMode = singleHashMode;
+ }
+
+ /**
+ * Initialise the ECIES-KEM.
+ *
+ * @param key the recipient's public (for encryption) or private (for decryption) key.
+ */
+ public void init(CipherParameters key)
+ throws IllegalArgumentException
+ {
+ if (!(key instanceof ECKeyParameters))
+ {
+ throw new IllegalArgumentException("EC key required");
+ }
+ else
+ {
+ this.key = (ECKeyParameters)key;
+ }
+ }
+
+ /**
+ * Generate and encapsulate a random session key.
+ *
+ * @param out the output buffer for the encapsulated key.
+ * @param outOff the offset for the output buffer.
+ * @param keyLen the length of the session key.
+ * @return the random session key.
+ */
+ public CipherParameters encrypt(byte[] out, int outOff, int keyLen)
+ throws IllegalArgumentException
+ {
+ if (!(key instanceof ECPublicKeyParameters))
+ {
+ throw new IllegalArgumentException("Public key required for encryption");
+ }
+
+ 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);
+
+ // Compute the static-ephemeral key agreement
+ BigInteger rPrime = CofactorMode ? r.multiply(h).mod(n) : r;
+
+ ECMultiplier basePointMultiplier = createBasePointMultiplier();
+
+ ECPoint[] ghTilde = new ECPoint[]{
+ basePointMultiplier.multiply(ecParams.getG(), 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);
+
+ // Encode the shared secret value
+ byte[] PEH = hTilde.getAffineXCoord().getEncoded();
+
+ // Initialise the KDF
+ byte[] kdfInput = SingleHashMode ? Arrays.concatenate(C, PEH) : PEH;
+ kdf.init(new KDFParameters(kdfInput, null));
+
+ // Generate the secret key
+ byte[] K = new byte[keyLen];
+ kdf.generateBytes(K, 0, K.length);
+
+ // Return the ciphertext
+ return new KeyParameter(K);
+ }
+
+ /**
+ * Generate and encapsulate a random session key.
+ *
+ * @param out the output buffer for the encapsulated key.
+ * @param keyLen the length of the session key.
+ * @return the random session key.
+ */
+ public CipherParameters encrypt(byte[] out, int keyLen)
+ {
+ return encrypt(out, 0, keyLen);
+ }
+
+ /**
+ * Decrypt an encapsulated session key.
+ *
+ * @param in the input buffer for the encapsulated key.
+ * @param inOff the offset for the input buffer.
+ * @param inLen the length of the encapsulated key.
+ * @param keyLen the length of the session key.
+ * @return the session key.
+ */
+ public CipherParameters decrypt(byte[] in, int inOff, int inLen, int keyLen)
+ throws IllegalArgumentException
+ {
+ if (!(key instanceof ECPrivateKeyParameters))
+ {
+ throw new IllegalArgumentException("Private key required for encryption");
+ }
+
+ 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);
+
+ // NOTE: Decoded points are already normalized (i.e in affine form)
+ ECPoint gTilde = curve.decodePoint(C);
+
+ // Compute the static-ephemeral key agreement
+ ECPoint gHat = gTilde;
+ if ((CofactorMode) || (OldCofactorMode))
+ {
+ gHat = gHat.multiply(h);
+ }
+
+ BigInteger xHat = ecPrivKey.getD();
+ if (CofactorMode)
+ {
+ xHat = xHat.multiply(h.modInverse(n)).mod(n);
+ }
+
+ ECPoint hTilde = gHat.multiply(xHat).normalize();
+
+ // Encode the shared secret value
+ byte[] PEH = hTilde.getAffineXCoord().getEncoded();
+
+ // Initialise the KDF
+ byte[] kdfInput = SingleHashMode ? Arrays.concatenate(C, PEH) : PEH;
+ kdf.init(new KDFParameters(kdfInput, null));
+
+ // Generate the secret key
+ byte[] K = new byte[keyLen];
+ kdf.generateBytes(K, 0, K.length);
+
+ return new KeyParameter(K);
+ }
+
+ /**
+ * Decrypt an encapsulated session key.
+ *
+ * @param in the input buffer for the encapsulated key.
+ * @param keyLen the length of the session key.
+ * @return the session key.
+ */
+ public CipherParameters decrypt(byte[] in, int keyLen)
+ {
+ return decrypt(in, 0, in.length, keyLen);
+ }
+
+ protected ECMultiplier createBasePointMultiplier()
+ {
+ return new FixedPointCombMultiplier();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/kems/RSAKeyEncapsulation.java b/core/src/main/java/org/spongycastle/crypto/kems/RSAKeyEncapsulation.java
new file mode 100755
index 00000000..7c3dba57
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/kems/RSAKeyEncapsulation.java
@@ -0,0 +1,155 @@
+package org.spongycastle.crypto.kems;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DerivationFunction;
+import org.spongycastle.crypto.KeyEncapsulation;
+import org.spongycastle.crypto.params.KDFParameters;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+import org.spongycastle.util.BigIntegers;
+
+/**
+ * The RSA Key Encapsulation Mechanism (RSA-KEM) from ISO 18033-2.
+ */
+public class RSAKeyEncapsulation
+ implements KeyEncapsulation
+{
+ private static final BigInteger ZERO = BigInteger.valueOf(0);
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ private DerivationFunction kdf;
+ private SecureRandom rnd;
+ private RSAKeyParameters key;
+
+ /**
+ * Set up the RSA-KEM.
+ *
+ * @param kdf the key derivation function to be used.
+ * @param rnd the random source for the session key.
+ */
+ public RSAKeyEncapsulation(
+ DerivationFunction kdf,
+ SecureRandom rnd)
+ {
+ this.kdf = kdf;
+ this.rnd = rnd;
+ }
+
+ /**
+ * Initialise the RSA-KEM.
+ *
+ * @param key the recipient's public (for encryption) or private (for decryption) key.
+ */
+ public void init(CipherParameters key)
+ throws IllegalArgumentException
+ {
+ if (!(key instanceof RSAKeyParameters))
+ {
+ throw new IllegalArgumentException("RSA key required");
+ }
+
+ this.key = (RSAKeyParameters)key;
+ }
+
+ /**
+ * Generate and encapsulate a random session key.
+ *
+ * @param out the output buffer for the encapsulated key.
+ * @param outOff the offset for the output buffer.
+ * @param keyLen the length of the random session key.
+ * @return the random session key.
+ */
+ public CipherParameters encrypt(byte[] out, int outOff, int keyLen)
+ throws IllegalArgumentException
+ {
+ if (key.isPrivate())
+ {
+ throw new IllegalArgumentException("Public key required for encryption");
+ }
+
+ BigInteger n = key.getModulus();
+ BigInteger e = key.getExponent();
+
+ // Generate the ephemeral random and encode it
+ BigInteger r = BigIntegers.createRandomInRange(ZERO, n.subtract(ONE), rnd);
+
+ // Encrypt the random and encode it
+ BigInteger c = r.modPow(e, n);
+ byte[] C = BigIntegers.asUnsignedByteArray((n.bitLength() + 7) / 8, c);
+ System.arraycopy(C, 0, out, outOff, C.length);
+
+ return generateKey(n, r, keyLen);
+ }
+
+ /**
+ * Generate and encapsulate a random session key.
+ *
+ * @param out the output buffer for the encapsulated key.
+ * @param keyLen the length of the random session key.
+ * @return the random session key.
+ */
+ public CipherParameters encrypt(byte[] out, int keyLen)
+ {
+ return encrypt(out, 0, keyLen);
+ }
+
+ /**
+ * Decrypt an encapsulated session key.
+ *
+ * @param in the input buffer for the encapsulated key.
+ * @param inOff the offset for the input buffer.
+ * @param inLen the length of the encapsulated key.
+ * @param keyLen the length of the session key.
+ * @return the session key.
+ */
+ public CipherParameters decrypt(byte[] in, int inOff, int inLen, int keyLen)
+ throws IllegalArgumentException
+ {
+ if (!key.isPrivate())
+ {
+ throw new IllegalArgumentException("Private key required for decryption");
+ }
+
+ BigInteger n = key.getModulus();
+ BigInteger d = key.getExponent();
+
+ // Decode the input
+ byte[] C = new byte[inLen];
+ System.arraycopy(in, inOff, C, 0, C.length);
+ BigInteger c = new BigInteger(1, C);
+
+ // Decrypt the ephemeral random and encode it
+ BigInteger r = c.modPow(d, n);
+
+ return generateKey(n, r, keyLen);
+ }
+
+ /**
+ * Decrypt an encapsulated session key.
+ *
+ * @param in the input buffer for the encapsulated key.
+ * @param keyLen the length of the session key.
+ * @return the session key.
+ */
+ public CipherParameters decrypt(byte[] in, int keyLen)
+ {
+ return decrypt(in, 0, in.length, keyLen);
+ }
+
+ protected KeyParameter generateKey(BigInteger n, BigInteger r, int keyLen)
+ {
+ byte[] R = BigIntegers.asUnsignedByteArray((n.bitLength() + 7) / 8, r);
+
+ // Initialise the KDF
+ kdf.init(new KDFParameters(R, null));
+
+ // Generate the secret key
+ byte[] K = new byte[keyLen];
+ kdf.generateBytes(K, 0, K.length);
+
+ return new KeyParameter(K);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/macs/BlockCipherMac.java b/core/src/main/java/org/spongycastle/crypto/macs/BlockCipherMac.java
new file mode 100644
index 00000000..2446812c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/macs/BlockCipherMac.java
@@ -0,0 +1,174 @@
+package org.spongycastle.crypto.macs;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.modes.CBCBlockCipher;
+
+public class BlockCipherMac
+ implements Mac
+{
+ private byte[] mac;
+
+ private byte[] buf;
+ private int bufOff;
+ private BlockCipher cipher;
+
+ private int macSize;
+
+ /**
+ * create a standard MAC based on a block cipher. This will produce an
+ * authentication code half the length of the block size of the cipher.
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @deprecated use CBCBlockCipherMac
+ */
+ public BlockCipherMac(
+ BlockCipher cipher)
+ {
+ this(cipher, (cipher.getBlockSize() * 8) / 2);
+ }
+
+ /**
+ * create a standard MAC based on a block cipher with the size of the
+ * MAC been given in bits.
+ * <p>
+ * Note: the size of the MAC must be at least 16 bits (FIPS Publication 113),
+ * and in general should be less than the size of the block cipher as it reduces
+ * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+ * @deprecated use CBCBlockCipherMac
+ */
+ public BlockCipherMac(
+ BlockCipher cipher,
+ int macSizeInBits)
+ {
+ if ((macSizeInBits % 8) != 0)
+ {
+ throw new IllegalArgumentException("MAC size must be multiple of 8");
+ }
+
+ this.cipher = new CBCBlockCipher(cipher);
+ this.macSize = macSizeInBits / 8;
+
+ mac = new byte[cipher.getBlockSize()];
+
+ buf = new byte[cipher.getBlockSize()];
+ bufOff = 0;
+ }
+
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName();
+ }
+
+ public void init(
+ CipherParameters params)
+ {
+ reset();
+
+ cipher.init(true, params);
+ }
+
+ public int getMacSize()
+ {
+ return macSize;
+ }
+
+ public void update(
+ byte in)
+ {
+ if (bufOff == buf.length)
+ {
+ cipher.processBlock(buf, 0, mac, 0);
+ bufOff = 0;
+ }
+
+ buf[bufOff++] = in;
+ }
+
+ public void update(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ int blockSize = cipher.getBlockSize();
+ int resultLen = 0;
+ int gapLen = blockSize - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ resultLen += cipher.processBlock(buf, 0, mac, 0);
+
+ bufOff = 0;
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > blockSize)
+ {
+ resultLen += cipher.processBlock(in, inOff, mac, 0);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ int blockSize = cipher.getBlockSize();
+
+ //
+ // pad with zeroes
+ //
+ while (bufOff < blockSize)
+ {
+ buf[bufOff] = 0;
+ bufOff++;
+ }
+
+ cipher.processBlock(buf, 0, mac, 0);
+
+ System.arraycopy(mac, 0, out, outOff, macSize);
+
+ reset();
+
+ return macSize;
+ }
+
+ /**
+ * Reset the mac generator.
+ */
+ public void reset()
+ {
+ /*
+ * clean the buffer.
+ */
+ for (int i = 0; i < buf.length; i++)
+ {
+ buf[i] = 0;
+ }
+
+ bufOff = 0;
+
+ /*
+ * reset the underlying cipher.
+ */
+ cipher.reset();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/macs/CBCBlockCipherMac.java b/core/src/main/java/org/spongycastle/crypto/macs/CBCBlockCipherMac.java
new file mode 100644
index 00000000..fd8a4f14
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/macs/CBCBlockCipherMac.java
@@ -0,0 +1,229 @@
+package org.spongycastle.crypto.macs;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.modes.CBCBlockCipher;
+import org.spongycastle.crypto.paddings.BlockCipherPadding;
+
+/**
+ * standard CBC Block Cipher MAC - if no padding is specified the default of
+ * pad of zeroes is used.
+ */
+public class CBCBlockCipherMac
+ implements Mac
+{
+ private byte[] mac;
+
+ private byte[] buf;
+ private int bufOff;
+ private BlockCipher cipher;
+ private BlockCipherPadding padding;
+
+ private int macSize;
+
+ /**
+ * create a standard MAC based on a CBC block cipher. This will produce an
+ * authentication code half the length of the block size of the cipher.
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ */
+ public CBCBlockCipherMac(
+ BlockCipher cipher)
+ {
+ this(cipher, (cipher.getBlockSize() * 8) / 2, null);
+ }
+
+ /**
+ * create a standard MAC based on a CBC block cipher. This will produce an
+ * authentication code half the length of the block size of the cipher.
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @param padding the padding to be used to complete the last block.
+ */
+ public CBCBlockCipherMac(
+ BlockCipher cipher,
+ BlockCipherPadding padding)
+ {
+ this(cipher, (cipher.getBlockSize() * 8) / 2, padding);
+ }
+
+ /**
+ * create a standard MAC based on a block cipher with the size of the
+ * MAC been given in bits. This class uses CBC mode as the basis for the
+ * MAC generation.
+ * <p>
+ * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+ * or 16 bits if being used as a data authenticator (FIPS Publication 113),
+ * and in general should be less than the size of the block cipher as it reduces
+ * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+ */
+ public CBCBlockCipherMac(
+ BlockCipher cipher,
+ int macSizeInBits)
+ {
+ this(cipher, macSizeInBits, null);
+ }
+
+ /**
+ * create a standard MAC based on a block cipher with the size of the
+ * MAC been given in bits. This class uses CBC mode as the basis for the
+ * MAC generation.
+ * <p>
+ * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+ * or 16 bits if being used as a data authenticator (FIPS Publication 113),
+ * and in general should be less than the size of the block cipher as it reduces
+ * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+ * @param padding the padding to be used to complete the last block.
+ */
+ public CBCBlockCipherMac(
+ BlockCipher cipher,
+ int macSizeInBits,
+ BlockCipherPadding padding)
+ {
+ if ((macSizeInBits % 8) != 0)
+ {
+ throw new IllegalArgumentException("MAC size must be multiple of 8");
+ }
+
+ this.cipher = new CBCBlockCipher(cipher);
+ this.padding = padding;
+ this.macSize = macSizeInBits / 8;
+
+ mac = new byte[cipher.getBlockSize()];
+
+ buf = new byte[cipher.getBlockSize()];
+ bufOff = 0;
+ }
+
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName();
+ }
+
+ public void init(
+ CipherParameters params)
+ {
+ reset();
+
+ cipher.init(true, params);
+ }
+
+ public int getMacSize()
+ {
+ return macSize;
+ }
+
+ public void update(
+ byte in)
+ {
+ if (bufOff == buf.length)
+ {
+ cipher.processBlock(buf, 0, mac, 0);
+ bufOff = 0;
+ }
+
+ buf[bufOff++] = in;
+ }
+
+ public void update(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ int blockSize = cipher.getBlockSize();
+ int gapLen = blockSize - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ cipher.processBlock(buf, 0, mac, 0);
+
+ bufOff = 0;
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > blockSize)
+ {
+ cipher.processBlock(in, inOff, mac, 0);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ int blockSize = cipher.getBlockSize();
+
+ if (padding == null)
+ {
+ //
+ // pad with zeroes
+ //
+ while (bufOff < blockSize)
+ {
+ buf[bufOff] = 0;
+ bufOff++;
+ }
+ }
+ else
+ {
+ if (bufOff == blockSize)
+ {
+ cipher.processBlock(buf, 0, mac, 0);
+ bufOff = 0;
+ }
+
+ padding.addPadding(buf, bufOff);
+ }
+
+ cipher.processBlock(buf, 0, mac, 0);
+
+ System.arraycopy(mac, 0, out, outOff, macSize);
+
+ reset();
+
+ return macSize;
+ }
+
+ /**
+ * Reset the mac generator.
+ */
+ public void reset()
+ {
+ /*
+ * clean the buffer.
+ */
+ for (int i = 0; i < buf.length; i++)
+ {
+ buf[i] = 0;
+ }
+
+ bufOff = 0;
+
+ /*
+ * reset the underlying cipher.
+ */
+ cipher.reset();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/macs/CFBBlockCipherMac.java b/core/src/main/java/org/spongycastle/crypto/macs/CFBBlockCipherMac.java
new file mode 100644
index 00000000..920b1fa6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/macs/CFBBlockCipherMac.java
@@ -0,0 +1,388 @@
+package org.spongycastle.crypto.macs;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.paddings.BlockCipherPadding;
+import org.spongycastle.crypto.params.ParametersWithIV;
+
+/**
+ * implements a Cipher-FeedBack (CFB) mode on top of a simple cipher.
+ */
+class MacCFBBlockCipher
+{
+ private byte[] IV;
+ private byte[] cfbV;
+ private byte[] cfbOutV;
+
+ private int blockSize;
+ private BlockCipher cipher = null;
+
+ /**
+ * Basic constructor.
+ *
+ * @param cipher the block cipher to be used as the basis of the
+ * feedback mode.
+ * @param blockSize the block size in bits (note: a multiple of 8)
+ */
+ public MacCFBBlockCipher(
+ BlockCipher cipher,
+ int bitBlockSize)
+ {
+ this.cipher = cipher;
+ this.blockSize = bitBlockSize / 8;
+
+ this.IV = new byte[cipher.getBlockSize()];
+ this.cfbV = new byte[cipher.getBlockSize()];
+ this.cfbOutV = new byte[cipher.getBlockSize()];
+ }
+
+ /**
+ * Initialise the cipher and, possibly, the initialisation vector (IV).
+ * If an IV isn't passed as part of the parameter, the IV will be all zeros.
+ * An IV which is too short is handled in FIPS compliant fashion.
+ *
+ * @param param the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV ivParam = (ParametersWithIV)params;
+ byte[] iv = ivParam.getIV();
+
+ if (iv.length < IV.length)
+ {
+ System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
+ }
+ else
+ {
+ System.arraycopy(iv, 0, IV, 0, IV.length);
+ }
+
+ reset();
+
+ cipher.init(true, ivParam.getParameters());
+ }
+ else
+ {
+ reset();
+
+ cipher.init(true, params);
+ }
+ }
+
+ /**
+ * return the algorithm name and mode.
+ *
+ * @return the name of the underlying algorithm followed by "/CFB"
+ * and the block size in bits.
+ */
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName() + "/CFB" + (blockSize * 8);
+ }
+
+ /**
+ * return the block size we are operating at.
+ *
+ * @return the block size we are operating at (in bytes).
+ */
+ public int getBlockSize()
+ {
+ return blockSize;
+ }
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ cipher.processBlock(cfbV, 0, cfbOutV, 0);
+
+ //
+ // XOR the cfbV with the plaintext producing the cipher text
+ //
+ for (int i = 0; i < blockSize; i++)
+ {
+ out[outOff + i] = (byte)(cfbOutV[i] ^ in[inOff + i]);
+ }
+
+ //
+ // change over the input block.
+ //
+ System.arraycopy(cfbV, blockSize, cfbV, 0, cfbV.length - blockSize);
+ System.arraycopy(out, outOff, cfbV, cfbV.length - blockSize, blockSize);
+
+ return blockSize;
+ }
+
+ /**
+ * reset the chaining vector back to the IV and reset the underlying
+ * cipher.
+ */
+ public void reset()
+ {
+ System.arraycopy(IV, 0, cfbV, 0, IV.length);
+
+ cipher.reset();
+ }
+
+ void getMacBlock(
+ byte[] mac)
+ {
+ cipher.processBlock(cfbV, 0, mac, 0);
+ }
+}
+
+public class CFBBlockCipherMac
+ implements Mac
+{
+ private byte[] mac;
+
+ private byte[] buf;
+ private int bufOff;
+ private MacCFBBlockCipher cipher;
+ private BlockCipherPadding padding = null;
+
+
+ private int macSize;
+
+ /**
+ * create a standard MAC based on a CFB block cipher. This will produce an
+ * authentication code half the length of the block size of the cipher, with
+ * the CFB mode set to 8 bits.
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ */
+ public CFBBlockCipherMac(
+ BlockCipher cipher)
+ {
+ this(cipher, 8, (cipher.getBlockSize() * 8) / 2, null);
+ }
+
+ /**
+ * create a standard MAC based on a CFB block cipher. This will produce an
+ * authentication code half the length of the block size of the cipher, with
+ * the CFB mode set to 8 bits.
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @param padding the padding to be used.
+ */
+ public CFBBlockCipherMac(
+ BlockCipher cipher,
+ BlockCipherPadding padding)
+ {
+ this(cipher, 8, (cipher.getBlockSize() * 8) / 2, padding);
+ }
+
+ /**
+ * create a standard MAC based on a block cipher with the size of the
+ * MAC been given in bits. This class uses CFB mode as the basis for the
+ * MAC generation.
+ * <p>
+ * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+ * or 16 bits if being used as a data authenticator (FIPS Publication 113),
+ * and in general should be less than the size of the block cipher as it reduces
+ * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @param cfbBitSize the size of an output block produced by the CFB mode.
+ * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+ */
+ public CFBBlockCipherMac(
+ BlockCipher cipher,
+ int cfbBitSize,
+ int macSizeInBits)
+ {
+ this(cipher, cfbBitSize, macSizeInBits, null);
+ }
+
+ /**
+ * create a standard MAC based on a block cipher with the size of the
+ * MAC been given in bits. This class uses CFB mode as the basis for the
+ * MAC generation.
+ * <p>
+ * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+ * or 16 bits if being used as a data authenticator (FIPS Publication 113),
+ * and in general should be less than the size of the block cipher as it reduces
+ * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @param cfbBitSize the size of an output block produced by the CFB mode.
+ * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+ * @param padding a padding to be used.
+ */
+ public CFBBlockCipherMac(
+ BlockCipher cipher,
+ int cfbBitSize,
+ int macSizeInBits,
+ BlockCipherPadding padding)
+ {
+ if ((macSizeInBits % 8) != 0)
+ {
+ throw new IllegalArgumentException("MAC size must be multiple of 8");
+ }
+
+ mac = new byte[cipher.getBlockSize()];
+
+ this.cipher = new MacCFBBlockCipher(cipher, cfbBitSize);
+ this.padding = padding;
+ this.macSize = macSizeInBits / 8;
+
+ buf = new byte[this.cipher.getBlockSize()];
+ bufOff = 0;
+ }
+
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName();
+ }
+
+ public void init(
+ CipherParameters params)
+ {
+ reset();
+
+ cipher.init(params);
+ }
+
+ public int getMacSize()
+ {
+ return macSize;
+ }
+
+ public void update(
+ byte in)
+ {
+ if (bufOff == buf.length)
+ {
+ cipher.processBlock(buf, 0, mac, 0);
+ bufOff = 0;
+ }
+
+ buf[bufOff++] = in;
+ }
+
+ public void update(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ int blockSize = cipher.getBlockSize();
+ int resultLen = 0;
+ int gapLen = blockSize - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ resultLen += cipher.processBlock(buf, 0, mac, 0);
+
+ bufOff = 0;
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > blockSize)
+ {
+ resultLen += cipher.processBlock(in, inOff, mac, 0);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ int blockSize = cipher.getBlockSize();
+
+ //
+ // pad with zeroes
+ //
+ if (this.padding == null)
+ {
+ while (bufOff < blockSize)
+ {
+ buf[bufOff] = 0;
+ bufOff++;
+ }
+ }
+ else
+ {
+ padding.addPadding(buf, bufOff);
+ }
+
+ cipher.processBlock(buf, 0, mac, 0);
+
+ cipher.getMacBlock(mac);
+
+ System.arraycopy(mac, 0, out, outOff, macSize);
+
+ reset();
+
+ return macSize;
+ }
+
+ /**
+ * Reset the mac generator.
+ */
+ public void reset()
+ {
+ /*
+ * clean the buffer.
+ */
+ for (int i = 0; i < buf.length; i++)
+ {
+ buf[i] = 0;
+ }
+
+ bufOff = 0;
+
+ /*
+ * reset the underlying cipher.
+ */
+ cipher.reset();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/macs/CMac.java b/core/src/main/java/org/spongycastle/crypto/macs/CMac.java
new file mode 100644
index 00000000..5bf47382
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/macs/CMac.java
@@ -0,0 +1,261 @@
+package org.spongycastle.crypto.macs;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.modes.CBCBlockCipher;
+import org.spongycastle.crypto.paddings.ISO7816d4Padding;
+import org.spongycastle.crypto.params.KeyParameter;
+
+/**
+ * CMAC - as specified at www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/omac.html
+ * <p>
+ * CMAC is analogous to OMAC1 - see also en.wikipedia.org/wiki/CMAC
+ * </p><p>
+ * CMAC is a NIST recomendation - see
+ * csrc.nist.gov/CryptoToolkit/modes/800-38_Series_Publications/SP800-38B.pdf
+ * </p><p>
+ * CMAC/OMAC1 is a blockcipher-based message authentication code designed and
+ * analyzed by Tetsu Iwata and Kaoru Kurosawa.
+ * </p><p>
+ * CMAC/OMAC1 is a simple variant of the CBC MAC (Cipher Block Chaining Message
+ * Authentication Code). OMAC stands for One-Key CBC MAC.
+ * </p><p>
+ * It supports 128- or 64-bits block ciphers, with any key size, and returns
+ * a MAC with dimension less or equal to the block size of the underlying
+ * cipher.
+ * </p>
+ */
+public class CMac implements Mac
+{
+ private static final byte CONSTANT_128 = (byte)0x87;
+ private static final byte CONSTANT_64 = (byte)0x1b;
+
+ private byte[] ZEROES;
+
+ private byte[] mac;
+
+ private byte[] buf;
+ private int bufOff;
+ private BlockCipher cipher;
+
+ private int macSize;
+
+ private byte[] L, Lu, Lu2;
+
+ /**
+ * create a standard MAC based on a CBC block cipher (64 or 128 bit block).
+ * This will produce an authentication code the length of the block size
+ * of the cipher.
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ */
+ public CMac(BlockCipher cipher)
+ {
+ this(cipher, cipher.getBlockSize() * 8);
+ }
+
+ /**
+ * create a standard MAC based on a block cipher with the size of the
+ * MAC been given in bits.
+ * <p>
+ * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+ * or 16 bits if being used as a data authenticator (FIPS Publication 113),
+ * and in general should be less than the size of the block cipher as it reduces
+ * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8 and &lt;= 128.
+ */
+ public CMac(BlockCipher cipher, int macSizeInBits)
+ {
+ if ((macSizeInBits % 8) != 0)
+ {
+ throw new IllegalArgumentException("MAC size must be multiple of 8");
+ }
+
+ if (macSizeInBits > (cipher.getBlockSize() * 8))
+ {
+ throw new IllegalArgumentException(
+ "MAC size must be less or equal to "
+ + (cipher.getBlockSize() * 8));
+ }
+
+ if (cipher.getBlockSize() != 8 && cipher.getBlockSize() != 16)
+ {
+ throw new IllegalArgumentException(
+ "Block size must be either 64 or 128 bits");
+ }
+
+ this.cipher = new CBCBlockCipher(cipher);
+ this.macSize = macSizeInBits / 8;
+
+ mac = new byte[cipher.getBlockSize()];
+
+ buf = new byte[cipher.getBlockSize()];
+
+ ZEROES = new byte[cipher.getBlockSize()];
+
+ bufOff = 0;
+ }
+
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName();
+ }
+
+ private static int shiftLeft(byte[] block, byte[] output)
+ {
+ int i = block.length;
+ int bit = 0;
+ while (--i >= 0)
+ {
+ 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)
+ {
+ validate(params);
+
+ cipher.init(true, params);
+
+ //initializes the L, Lu, Lu2 numbers
+ L = new byte[ZEROES.length];
+ cipher.processBlock(ZEROES, 0, L, 0);
+ Lu = doubleLu(L);
+ Lu2 = doubleLu(Lu);
+
+ reset();
+ }
+
+ void validate(CipherParameters params)
+ {
+ if (params != null)
+ {
+ if (!(params instanceof KeyParameter))
+ {
+ // CMAC mode does not permit IV to underlying CBC mode
+ throw new IllegalArgumentException("CMac mode only permits key to be set.");
+ }
+ }
+ }
+
+ public int getMacSize()
+ {
+ return macSize;
+ }
+
+ public void update(byte in)
+ {
+ if (bufOff == buf.length)
+ {
+ cipher.processBlock(buf, 0, mac, 0);
+ bufOff = 0;
+ }
+
+ buf[bufOff++] = in;
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException(
+ "Can't have a negative input length!");
+ }
+
+ int blockSize = cipher.getBlockSize();
+ int gapLen = blockSize - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ cipher.processBlock(buf, 0, mac, 0);
+
+ bufOff = 0;
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > blockSize)
+ {
+ cipher.processBlock(in, inOff, mac, 0);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ {
+ int blockSize = cipher.getBlockSize();
+
+ byte[] lu;
+ if (bufOff == blockSize)
+ {
+ lu = Lu;
+ }
+ else
+ {
+ new ISO7816d4Padding().addPadding(buf, bufOff);
+ lu = Lu2;
+ }
+
+ for (int i = 0; i < mac.length; i++)
+ {
+ buf[i] ^= lu[i];
+ }
+
+ cipher.processBlock(buf, 0, mac, 0);
+
+ System.arraycopy(mac, 0, out, outOff, macSize);
+
+ reset();
+
+ return macSize;
+ }
+
+ /**
+ * Reset the mac generator.
+ */
+ public void reset()
+ {
+ /*
+ * clean the buffer.
+ */
+ for (int i = 0; i < buf.length; i++)
+ {
+ buf[i] = 0;
+ }
+
+ bufOff = 0;
+
+ /*
+ * reset the underlying cipher.
+ */
+ cipher.reset();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/macs/CMacWithIV.java b/core/src/main/java/org/spongycastle/crypto/macs/CMacWithIV.java
new file mode 100644
index 00000000..f4894a6e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/macs/CMacWithIV.java
@@ -0,0 +1,27 @@
+package org.spongycastle.crypto.macs;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+
+/**
+ * A non-NIST variant which allows passing of an IV to the underlying CBC cipher.
+ * <p>Note: there isn't really a good reason to use an IV here, use the regular CMac where possible.</p>
+ */
+public class CMacWithIV
+ extends CMac
+{
+ public CMacWithIV(BlockCipher cipher)
+ {
+ super(cipher);
+ }
+
+ public CMacWithIV(BlockCipher cipher, int macSizeInBits)
+ {
+ super(cipher, macSizeInBits);
+ }
+
+ void validate(CipherParameters params)
+ {
+ // accept all
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/macs/GMac.java b/core/src/main/java/org/spongycastle/crypto/macs/GMac.java
new file mode 100644
index 00000000..fc2e29f5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/macs/GMac.java
@@ -0,0 +1,115 @@
+package org.spongycastle.crypto.macs;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.modes.GCMBlockCipher;
+import org.spongycastle.crypto.params.AEADParameters;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+
+/**
+ * The GMAC specialisation of Galois/Counter mode (GCM) detailed in NIST Special Publication
+ * 800-38D.
+ * <p>
+ * GMac is an invocation of the GCM mode where no data is encrypted (i.e. all input data to the Mac
+ * is processed as additional authenticated data with the underlying GCM block cipher).
+ */
+public class GMac implements Mac
+{
+ private final GCMBlockCipher cipher;
+ private final int macSizeBits;
+
+ /**
+ * Creates a GMAC based on the operation of a block cipher in GCM mode.
+ * <p>
+ * This will produce an authentication code the length of the block size of the cipher.
+ *
+ * @param cipher
+ * the cipher to be used in GCM mode to generate the MAC.
+ */
+ public GMac(final GCMBlockCipher cipher)
+ {
+ // use of this confused flow analyser in some earlier JDKs
+ this.cipher = cipher;
+ this.macSizeBits = 128;
+ }
+
+ /**
+ * Creates a GMAC based on the operation of a 128 bit block cipher in GCM mode.
+ *
+ * @param macSizeBits
+ * the mac size to generate, in bits. Must be a multiple of 8 and &gt;= 32 and &lt;= 128.
+ * Sizes less than 96 are not recommended, but are supported for specialized applications.
+ * @param cipher
+ * the cipher to be used in GCM mode to generate the MAC.
+ */
+ public GMac(final GCMBlockCipher cipher, final int macSizeBits)
+ {
+ this.cipher = cipher;
+ this.macSizeBits = macSizeBits;
+ }
+
+ /**
+ * Initialises the GMAC - requires a {@link ParametersWithIV} providing a {@link KeyParameter}
+ * and a nonce.
+ */
+ public void init(final CipherParameters params) throws IllegalArgumentException
+ {
+ if (params instanceof ParametersWithIV)
+ {
+ final ParametersWithIV param = (ParametersWithIV)params;
+
+ final byte[] iv = param.getIV();
+ final KeyParameter keyParam = (KeyParameter)param.getParameters();
+
+ // GCM is always operated in encrypt mode to calculate MAC
+ cipher.init(true, new AEADParameters(keyParam, macSizeBits, iv));
+ }
+ else
+ {
+ throw new IllegalArgumentException("GMAC requires ParametersWithIV");
+ }
+ }
+
+ public String getAlgorithmName()
+ {
+ return cipher.getUnderlyingCipher().getAlgorithmName() + "-GMAC";
+ }
+
+ public int getMacSize()
+ {
+ return macSizeBits / 8;
+ }
+
+ public void update(byte in) throws IllegalStateException
+ {
+ cipher.processAADByte(in);
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ throws DataLengthException, IllegalStateException
+ {
+ cipher.processAADBytes(in, inOff, len);
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ try
+ {
+ return cipher.doFinal(out, outOff);
+ }
+ catch (InvalidCipherTextException e)
+ {
+ // Impossible in encrypt mode
+ throw new IllegalStateException(e.toString());
+ }
+ }
+
+ public void reset()
+ {
+ cipher.reset();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/macs/GOST28147Mac.java b/core/src/main/java/org/spongycastle/crypto/macs/GOST28147Mac.java
new file mode 100644
index 00000000..4a245760
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/macs/GOST28147Mac.java
@@ -0,0 +1,298 @@
+package org.spongycastle.crypto.macs;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithSBox;
+
+/**
+ * implementation of GOST 28147-89 MAC
+ */
+public class GOST28147Mac
+ implements Mac
+{
+ private int blockSize = 8;
+ private int macSize = 4;
+ private int bufOff;
+ private byte[] buf;
+ private byte[] mac;
+ private boolean firstStep = true;
+ private int[] workingKey = null;
+
+ //
+ // This is default S-box - E_A.
+ private byte S[] = {
+ 0x9,0x6,0x3,0x2,0x8,0xB,0x1,0x7,0xA,0x4,0xE,0xF,0xC,0x0,0xD,0x5,
+ 0x3,0x7,0xE,0x9,0x8,0xA,0xF,0x0,0x5,0x2,0x6,0xC,0xB,0x4,0xD,0x1,
+ 0xE,0x4,0x6,0x2,0xB,0x3,0xD,0x8,0xC,0xF,0x5,0xA,0x0,0x7,0x1,0x9,
+ 0xE,0x7,0xA,0xC,0xD,0x1,0x3,0x9,0x0,0x2,0xB,0x4,0xF,0x8,0x5,0x6,
+ 0xB,0x5,0x1,0x9,0x8,0xD,0xF,0x0,0xE,0x4,0x2,0x3,0xC,0x7,0xA,0x6,
+ 0x3,0xA,0xD,0xC,0x1,0x2,0x0,0xB,0x7,0x5,0x9,0x4,0x8,0xF,0xE,0x6,
+ 0x1,0xD,0x2,0x9,0x7,0xA,0x6,0x0,0x8,0xC,0x4,0x5,0xF,0x3,0xB,0xE,
+ 0xB,0xA,0xF,0x5,0x0,0xC,0xE,0x8,0x6,0x2,0x3,0x9,0x1,0x7,0xD,0x4
+ };
+
+ public GOST28147Mac()
+ {
+ mac = new byte[blockSize];
+
+ buf = new byte[blockSize];
+ bufOff = 0;
+ }
+
+ private int[] generateWorkingKey(
+ byte[] userKey)
+ {
+ if (userKey.length != 32)
+ {
+ throw new IllegalArgumentException("Key length invalid. Key needs to be 32 byte - 256 bit!!!");
+ }
+
+ int key[] = new int[8];
+ for(int i=0; i!=8; i++)
+ {
+ key[i] = bytesToint(userKey,i*4);
+ }
+
+ return key;
+ }
+
+ public void init(
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ reset();
+ buf = new byte[blockSize];
+ if (params instanceof ParametersWithSBox)
+ {
+ ParametersWithSBox param = (ParametersWithSBox)params;
+
+ //
+ // Set the S-Box
+ //
+ System.arraycopy(param.getSBox(), 0, this.S, 0, param.getSBox().length);
+
+ //
+ // set key if there is one
+ //
+ if (param.getParameters() != null)
+ {
+ workingKey = generateWorkingKey(((KeyParameter)param.getParameters()).getKey());
+ }
+ }
+ else if (params instanceof KeyParameter)
+ {
+ workingKey = generateWorkingKey(((KeyParameter)params).getKey());
+ }
+ else
+ {
+ throw new IllegalArgumentException("invalid parameter passed to GOST28147 init - " + params.getClass().getName());
+ }
+ }
+
+ public String getAlgorithmName()
+ {
+ return "GOST28147Mac";
+ }
+
+ public int getMacSize()
+ {
+ return macSize;
+ }
+
+ private int gost28147_mainStep(int n1, int key)
+ {
+ int cm = (key + n1); // CM1
+
+ // S-box replacing
+
+ int om = S[ 0 + ((cm >> (0 * 4)) & 0xF)] << (0 * 4);
+ om += S[ 16 + ((cm >> (1 * 4)) & 0xF)] << (1 * 4);
+ om += S[ 32 + ((cm >> (2 * 4)) & 0xF)] << (2 * 4);
+ om += S[ 48 + ((cm >> (3 * 4)) & 0xF)] << (3 * 4);
+ om += S[ 64 + ((cm >> (4 * 4)) & 0xF)] << (4 * 4);
+ om += S[ 80 + ((cm >> (5 * 4)) & 0xF)] << (5 * 4);
+ om += S[ 96 + ((cm >> (6 * 4)) & 0xF)] << (6 * 4);
+ om += S[112 + ((cm >> (7 * 4)) & 0xF)] << (7 * 4);
+
+ return om << 11 | om >>> (32-11); // 11-leftshift
+ }
+
+ private void gost28147MacFunc(
+ int[] workingKey,
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ int N1, N2, tmp; //tmp -> for saving N1
+ N1 = bytesToint(in, inOff);
+ N2 = bytesToint(in, inOff + 4);
+
+ for(int k = 0; k < 2; k++) // 1-16 steps
+ {
+ for(int j = 0; j < 8; j++)
+ {
+ tmp = N1;
+ N1 = N2 ^ gost28147_mainStep(N1, workingKey[j]); // CM2
+ N2 = tmp;
+ }
+ }
+
+ intTobytes(N1, out, outOff);
+ intTobytes(N2, out, outOff + 4);
+ }
+
+ //array of bytes to type int
+ private int bytesToint(
+ byte[] in,
+ int inOff)
+ {
+ return ((in[inOff + 3] << 24) & 0xff000000) + ((in[inOff + 2] << 16) & 0xff0000) +
+ ((in[inOff + 1] << 8) & 0xff00) + (in[inOff] & 0xff);
+ }
+
+ //int to array of bytes
+ private void intTobytes(
+ int num,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff + 3] = (byte)(num >>> 24);
+ out[outOff + 2] = (byte)(num >>> 16);
+ out[outOff + 1] = (byte)(num >>> 8);
+ out[outOff] = (byte)num;
+ }
+
+ private byte[] CM5func(byte[] buf, int bufOff, byte[] mac)
+ {
+ byte[] sum = new byte[buf.length - bufOff];
+
+ System.arraycopy(buf, bufOff, sum, 0, mac.length);
+
+ for (int i = 0; i != mac.length; i++)
+ {
+ sum[i] = (byte)(sum[i] ^ mac[i]);
+ }
+
+ return sum;
+ }
+
+ public void update(byte in)
+ throws IllegalStateException
+ {
+ if (bufOff == buf.length)
+ {
+ byte[] sumbuf = new byte[buf.length];
+ System.arraycopy(buf, 0, sumbuf, 0, mac.length);
+
+ if (firstStep)
+ {
+ firstStep = false;
+ }
+ else
+ {
+ sumbuf = CM5func(buf, 0, mac);
+ }
+
+ gost28147MacFunc(workingKey, sumbuf, 0, mac, 0);
+ bufOff = 0;
+ }
+
+ buf[bufOff++] = in;
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ throws DataLengthException, IllegalStateException
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ int gapLen = blockSize - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ byte[] sumbuf = new byte[buf.length];
+ System.arraycopy(buf, 0, sumbuf, 0, mac.length);
+
+ if (firstStep)
+ {
+ firstStep = false;
+ }
+ else
+ {
+ sumbuf = CM5func(buf, 0, mac);
+ }
+
+ gost28147MacFunc(workingKey, sumbuf, 0, mac, 0);
+
+ bufOff = 0;
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > blockSize)
+ {
+ sumbuf = CM5func(in, inOff, mac);
+ gost28147MacFunc(workingKey, sumbuf, 0, mac, 0);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ //padding with zero
+ while (bufOff < blockSize)
+ {
+ buf[bufOff] = 0;
+ bufOff++;
+ }
+
+ byte[] sumbuf = new byte[buf.length];
+ System.arraycopy(buf, 0, sumbuf, 0, mac.length);
+
+ if (firstStep)
+ {
+ firstStep = false;
+ }
+ else
+ {
+ sumbuf = CM5func(buf, 0, mac);
+ }
+
+ gost28147MacFunc(workingKey, sumbuf, 0, mac, 0);
+
+ System.arraycopy(mac, (mac.length/2)-macSize, out, outOff, macSize);
+
+ reset();
+
+ return macSize;
+ }
+
+ public void reset()
+ {
+ /*
+ * clean the buffer.
+ */
+ for (int i = 0; i < buf.length; i++)
+ {
+ buf[i] = 0;
+ }
+
+ bufOff = 0;
+
+ firstStep = true;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/macs/HMac.java b/core/src/main/java/org/spongycastle/crypto/macs/HMac.java
new file mode 100644
index 00000000..e7c0fe56
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/macs/HMac.java
@@ -0,0 +1,231 @@
+package org.spongycastle.crypto.macs;
+
+import java.util.Hashtable;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.ExtendedDigest;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Integers;
+import org.spongycastle.util.Memoable;
+
+/**
+ * HMAC implementation based on RFC2104
+ *
+ * H(K XOR opad, H(K XOR ipad, text))
+ */
+public class HMac
+ implements Mac
+{
+ private final static byte IPAD = (byte)0x36;
+ private final static byte OPAD = (byte)0x5C;
+
+ private Digest digest;
+ private int digestSize;
+ private int blockLength;
+ private Memoable ipadState;
+ private Memoable opadState;
+
+ private byte[] inputPad;
+ private byte[] outputBuf;
+
+ private static Hashtable blockLengths;
+
+ static
+ {
+ blockLengths = new Hashtable();
+
+ blockLengths.put("GOST3411", Integers.valueOf(32));
+
+ blockLengths.put("MD2", Integers.valueOf(16));
+ blockLengths.put("MD4", Integers.valueOf(64));
+ blockLengths.put("MD5", Integers.valueOf(64));
+
+ blockLengths.put("RIPEMD128", Integers.valueOf(64));
+ blockLengths.put("RIPEMD160", Integers.valueOf(64));
+
+ blockLengths.put("SHA-1", Integers.valueOf(64));
+ blockLengths.put("SHA-224", Integers.valueOf(64));
+ blockLengths.put("SHA-256", Integers.valueOf(64));
+ blockLengths.put("SHA-384", Integers.valueOf(128));
+ blockLengths.put("SHA-512", Integers.valueOf(128));
+
+ blockLengths.put("Tiger", Integers.valueOf(64));
+ blockLengths.put("Whirlpool", Integers.valueOf(64));
+ }
+
+ private static int getByteLength(
+ Digest digest)
+ {
+ if (digest instanceof ExtendedDigest)
+ {
+ return ((ExtendedDigest)digest).getByteLength();
+ }
+
+ Integer b = (Integer)blockLengths.get(digest.getAlgorithmName());
+
+ if (b == null)
+ {
+ throw new IllegalArgumentException("unknown digest passed: " + digest.getAlgorithmName());
+ }
+
+ return b.intValue();
+ }
+
+ /**
+ * Base constructor for one of the standard digest algorithms that the
+ * byteLength of the algorithm is know for.
+ *
+ * @param digest the digest.
+ */
+ public HMac(
+ Digest digest)
+ {
+ this(digest, getByteLength(digest));
+ }
+
+ private HMac(
+ Digest digest,
+ int byteLength)
+ {
+ this.digest = digest;
+ this.digestSize = digest.getDigestSize();
+ this.blockLength = byteLength;
+ this.inputPad = new byte[blockLength];
+ this.outputBuf = new byte[blockLength + digestSize];
+ }
+
+ public String getAlgorithmName()
+ {
+ return digest.getAlgorithmName() + "/HMAC";
+ }
+
+ public Digest getUnderlyingDigest()
+ {
+ return digest;
+ }
+
+ public void init(
+ CipherParameters params)
+ {
+ digest.reset();
+
+ byte[] key = ((KeyParameter)params).getKey();
+ int keyLength = key.length;
+
+ if (keyLength > blockLength)
+ {
+ digest.update(key, 0, keyLength);
+ digest.doFinal(inputPad, 0);
+
+ keyLength = digestSize;
+ }
+ else
+ {
+ System.arraycopy(key, 0, inputPad, 0, keyLength);
+ }
+
+ for (int i = keyLength; i < inputPad.length; i++)
+ {
+ inputPad[i] = 0;
+ }
+
+ System.arraycopy(inputPad, 0, outputBuf, 0, blockLength);
+
+ xorPad(inputPad, blockLength, IPAD);
+ xorPad(outputBuf, blockLength, OPAD);
+
+ if (digest instanceof Memoable)
+ {
+ opadState = ((Memoable)digest).copy();
+
+ ((Digest)opadState).update(outputBuf, 0, blockLength);
+ }
+
+ digest.update(inputPad, 0, inputPad.length);
+
+ if (digest instanceof Memoable)
+ {
+ ipadState = ((Memoable)digest).copy();
+ }
+ }
+
+ public int getMacSize()
+ {
+ return digestSize;
+ }
+
+ public void update(
+ byte in)
+ {
+ digest.update(in);
+ }
+
+ public void update(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ digest.update(in, inOff, len);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ digest.doFinal(outputBuf, blockLength);
+
+ if (opadState != null)
+ {
+ ((Memoable)digest).reset(opadState);
+ digest.update(outputBuf, blockLength, digest.getDigestSize());
+ }
+ else
+ {
+ digest.update(outputBuf, 0, outputBuf.length);
+ }
+
+ int len = digest.doFinal(out, outOff);
+
+ for (int i = blockLength; i < outputBuf.length; i++)
+ {
+ outputBuf[i] = 0;
+ }
+
+ if (ipadState != null)
+ {
+ ((Memoable)digest).reset(ipadState);
+ }
+ else
+ {
+ digest.update(inputPad, 0, inputPad.length);
+ }
+
+ return len;
+ }
+
+ /**
+ * Reset the mac generator.
+ */
+ public void reset()
+ {
+ /*
+ * reset the underlying digest.
+ */
+ digest.reset();
+
+ /*
+ * reinitialize the digest.
+ */
+ digest.update(inputPad, 0, inputPad.length);
+ }
+
+ private static void xorPad(byte[] pad, int len, byte n)
+ {
+ for (int i = 0; i < len; ++i)
+ {
+ pad[i] ^= n;
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/macs/ISO9797Alg3Mac.java b/core/src/main/java/org/spongycastle/crypto/macs/ISO9797Alg3Mac.java
new file mode 100644
index 00000000..276c7e44
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/macs/ISO9797Alg3Mac.java
@@ -0,0 +1,305 @@
+package org.spongycastle.crypto.macs;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.engines.DESEngine;
+import org.spongycastle.crypto.modes.CBCBlockCipher;
+import org.spongycastle.crypto.paddings.BlockCipherPadding;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+
+/**
+ * DES based CBC Block Cipher MAC according to ISO9797, algorithm 3 (ANSI X9.19 Retail MAC)
+ *
+ * This could as well be derived from CBCBlockCipherMac, but then the property mac in the base
+ * class must be changed to protected
+ */
+
+public class ISO9797Alg3Mac
+ implements Mac
+{
+ private byte[] mac;
+
+ private byte[] buf;
+ private int bufOff;
+ private BlockCipher cipher;
+ private BlockCipherPadding padding;
+
+ private int macSize;
+ private KeyParameter lastKey2;
+ private KeyParameter lastKey3;
+
+ /**
+ * create a Retail-MAC based on a CBC block cipher. This will produce an
+ * authentication code of the length of the block size of the cipher.
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation. This must
+ * be DESEngine.
+ */
+ public ISO9797Alg3Mac(
+ BlockCipher cipher)
+ {
+ this(cipher, cipher.getBlockSize() * 8, null);
+ }
+
+ /**
+ * create a Retail-MAC based on a CBC block cipher. This will produce an
+ * authentication code of the length of the block size of the cipher.
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @param padding the padding to be used to complete the last block.
+ */
+ public ISO9797Alg3Mac(
+ BlockCipher cipher,
+ BlockCipherPadding padding)
+ {
+ this(cipher, cipher.getBlockSize() * 8, padding);
+ }
+
+ /**
+ * create a Retail-MAC based on a block cipher with the size of the
+ * MAC been given in bits. This class uses single DES CBC mode as the basis for the
+ * MAC generation.
+ * <p>
+ * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+ * or 16 bits if being used as a data authenticator (FIPS Publication 113),
+ * and in general should be less than the size of the block cipher as it reduces
+ * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+ */
+ public ISO9797Alg3Mac(
+ BlockCipher cipher,
+ int macSizeInBits)
+ {
+ this(cipher, macSizeInBits, null);
+ }
+
+ /**
+ * create a standard MAC based on a block cipher with the size of the
+ * MAC been given in bits. This class uses single DES CBC mode as the basis for the
+ * MAC generation. The final block is decrypted and then encrypted using the
+ * middle and right part of the key.
+ * <p>
+ * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+ * or 16 bits if being used as a data authenticator (FIPS Publication 113),
+ * and in general should be less than the size of the block cipher as it reduces
+ * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+ * @param padding the padding to be used to complete the last block.
+ */
+ public ISO9797Alg3Mac(
+ BlockCipher cipher,
+ int macSizeInBits,
+ BlockCipherPadding padding)
+ {
+ if ((macSizeInBits % 8) != 0)
+ {
+ throw new IllegalArgumentException("MAC size must be multiple of 8");
+ }
+
+ if (!(cipher instanceof DESEngine))
+ {
+ throw new IllegalArgumentException("cipher must be instance of DESEngine");
+ }
+
+ this.cipher = new CBCBlockCipher(cipher);
+ this.padding = padding;
+ this.macSize = macSizeInBits / 8;
+
+ mac = new byte[cipher.getBlockSize()];
+
+ buf = new byte[cipher.getBlockSize()];
+ bufOff = 0;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "ISO9797Alg3";
+ }
+
+ public void init(CipherParameters params)
+ {
+ reset();
+
+ if (!(params instanceof KeyParameter || params instanceof ParametersWithIV))
+ {
+ throw new IllegalArgumentException(
+ "params must be an instance of KeyParameter or ParametersWithIV");
+ }
+
+ // KeyParameter must contain a double or triple length DES key,
+ // however the underlying cipher is a single DES. The middle and
+ // right key are used only in the final step.
+
+ KeyParameter kp;
+
+ if (params instanceof KeyParameter)
+ {
+ kp = (KeyParameter)params;
+ }
+ else
+ {
+ kp = (KeyParameter)((ParametersWithIV)params).getParameters();
+ }
+
+ KeyParameter key1;
+ byte[] keyvalue = kp.getKey();
+
+ if (keyvalue.length == 16)
+ { // Double length DES key
+ key1 = new KeyParameter(keyvalue, 0, 8);
+ this.lastKey2 = new KeyParameter(keyvalue, 8, 8);
+ this.lastKey3 = key1;
+ }
+ else if (keyvalue.length == 24)
+ { // Triple length DES key
+ key1 = new KeyParameter(keyvalue, 0, 8);
+ this.lastKey2 = new KeyParameter(keyvalue, 8, 8);
+ this.lastKey3 = new KeyParameter(keyvalue, 16, 8);
+ }
+ else
+ {
+ throw new IllegalArgumentException(
+ "Key must be either 112 or 168 bit long");
+ }
+
+ if (params instanceof ParametersWithIV)
+ {
+ cipher.init(true, new ParametersWithIV(key1, ((ParametersWithIV)params).getIV()));
+ }
+ else
+ {
+ cipher.init(true, key1);
+ }
+ }
+
+ public int getMacSize()
+ {
+ return macSize;
+ }
+
+ public void update(
+ byte in)
+ {
+ if (bufOff == buf.length)
+ {
+ cipher.processBlock(buf, 0, mac, 0);
+ bufOff = 0;
+ }
+
+ buf[bufOff++] = in;
+ }
+
+
+ public void update(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ int blockSize = cipher.getBlockSize();
+ int resultLen = 0;
+ int gapLen = blockSize - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ resultLen += cipher.processBlock(buf, 0, mac, 0);
+
+ bufOff = 0;
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > blockSize)
+ {
+ resultLen += cipher.processBlock(in, inOff, mac, 0);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ int blockSize = cipher.getBlockSize();
+
+ if (padding == null)
+ {
+ //
+ // pad with zeroes
+ //
+ while (bufOff < blockSize)
+ {
+ buf[bufOff] = 0;
+ bufOff++;
+ }
+ }
+ else
+ {
+ if (bufOff == blockSize)
+ {
+ cipher.processBlock(buf, 0, mac, 0);
+ bufOff = 0;
+ }
+
+ padding.addPadding(buf, bufOff);
+ }
+
+ cipher.processBlock(buf, 0, mac, 0);
+
+ // Added to code from base class
+ DESEngine deseng = new DESEngine();
+
+ deseng.init(false, this.lastKey2);
+ deseng.processBlock(mac, 0, mac, 0);
+
+ deseng.init(true, this.lastKey3);
+ deseng.processBlock(mac, 0, mac, 0);
+ // ****
+
+ System.arraycopy(mac, 0, out, outOff, macSize);
+
+ reset();
+
+ return macSize;
+ }
+
+
+ /**
+ * Reset the mac generator.
+ */
+ public void reset()
+ {
+ /*
+ * clean the buffer.
+ */
+ for (int i = 0; i < buf.length; i++)
+ {
+ buf[i] = 0;
+ }
+
+ bufOff = 0;
+
+ /*
+ * reset the underlying cipher.
+ */
+ cipher.reset();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/macs/OldHMac.java b/core/src/main/java/org/spongycastle/crypto/macs/OldHMac.java
new file mode 100644
index 00000000..ff680838
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/macs/OldHMac.java
@@ -0,0 +1,138 @@
+package org.spongycastle.crypto.macs;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.params.KeyParameter;
+
+/**
+ * HMAC implementation based on RFC2104
+ *
+ * H(K XOR opad, H(K XOR ipad, text))
+ */
+public class OldHMac
+implements Mac
+{
+ private final static int BLOCK_LENGTH = 64;
+
+ private final static byte IPAD = (byte)0x36;
+ private final static byte OPAD = (byte)0x5C;
+
+ private Digest digest;
+ private int digestSize;
+ private byte[] inputPad = new byte[BLOCK_LENGTH];
+ private byte[] outputPad = new byte[BLOCK_LENGTH];
+
+ /**
+ * @deprecated uses incorrect pad for SHA-512 and SHA-384 use HMac.
+ */
+ public OldHMac(
+ Digest digest)
+ {
+ this.digest = digest;
+ digestSize = digest.getDigestSize();
+ }
+
+ public String getAlgorithmName()
+ {
+ return digest.getAlgorithmName() + "/HMAC";
+ }
+
+ public Digest getUnderlyingDigest()
+ {
+ return digest;
+ }
+
+ public void init(
+ CipherParameters params)
+ {
+ digest.reset();
+
+ byte[] key = ((KeyParameter)params).getKey();
+
+ if (key.length > BLOCK_LENGTH)
+ {
+ digest.update(key, 0, key.length);
+ digest.doFinal(inputPad, 0);
+ for (int i = digestSize; i < inputPad.length; i++)
+ {
+ inputPad[i] = 0;
+ }
+ }
+ else
+ {
+ System.arraycopy(key, 0, inputPad, 0, key.length);
+ for (int i = key.length; i < inputPad.length; i++)
+ {
+ inputPad[i] = 0;
+ }
+ }
+
+ outputPad = new byte[inputPad.length];
+ System.arraycopy(inputPad, 0, outputPad, 0, inputPad.length);
+
+ for (int i = 0; i < inputPad.length; i++)
+ {
+ inputPad[i] ^= IPAD;
+ }
+
+ for (int i = 0; i < outputPad.length; i++)
+ {
+ outputPad[i] ^= OPAD;
+ }
+
+ digest.update(inputPad, 0, inputPad.length);
+ }
+
+ public int getMacSize()
+ {
+ return digestSize;
+ }
+
+ public void update(
+ byte in)
+ {
+ digest.update(in);
+ }
+
+ public void update(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ digest.update(in, inOff, len);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ byte[] tmp = new byte[digestSize];
+ digest.doFinal(tmp, 0);
+
+ digest.update(outputPad, 0, outputPad.length);
+ digest.update(tmp, 0, tmp.length);
+
+ int len = digest.doFinal(out, outOff);
+
+ reset();
+
+ return len;
+ }
+
+ /**
+ * Reset the mac generator.
+ */
+ public void reset()
+ {
+ /*
+ * reset the underlying digest.
+ */
+ digest.reset();
+
+ /*
+ * reinitialize the digest.
+ */
+ digest.update(inputPad, 0, inputPad.length);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/macs/Poly1305.java b/core/src/main/java/org/spongycastle/crypto/macs/Poly1305.java
new file mode 100644
index 00000000..a33acbb1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/macs/Poly1305.java
@@ -0,0 +1,306 @@
+package org.spongycastle.crypto.macs;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.generators.Poly1305KeyGenerator;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.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, where the key passed to init() will be used directly.
+ */
+ public Poly1305()
+ {
+ this.cipher = null;
+ }
+
+ /**
+ * 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 params if used with a block cipher, then 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}, otherwise just the
+ * {@link KeyParameter}.
+ */
+ public void init(CipherParameters params)
+ throws IllegalArgumentException
+ {
+ byte[] nonce = null;
+
+ if (cipher != null)
+ {
+ if (!(params instanceof ParametersWithIV))
+ {
+ throw new IllegalArgumentException("Poly1305 requires an IV when used with a block cipher.");
+ }
+
+ ParametersWithIV ivParams = (ParametersWithIV)params;
+ nonce = ivParams.getIV();
+ params = ivParams.getParameters();
+ }
+
+ if (!(params instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("Poly1305 requires a key.");
+ }
+
+ KeyParameter keyParams = (KeyParameter)params;
+
+ setKey(keyParams.getKey(), nonce);
+
+ reset();
+ }
+
+ private void setKey(final byte[] key, final byte[] nonce)
+ {
+ if (cipher != null && (nonce == null || 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;
+
+ final byte[] kBytes;
+ if (cipher == null)
+ {
+ kBytes = key;
+ }
+ else
+ {
+ // Compute encrypted nonce
+ kBytes = new byte[BLOCK_SIZE];
+ cipher.init(true, new KeyParameter(key, 0, BLOCK_SIZE));
+ cipher.processBlock(nonce, 0, kBytes, 0);
+ }
+
+ k0 = Pack.littleEndianToInt(kBytes, 0);
+ k1 = Pack.littleEndianToInt(kBytes, 4);
+ k2 = Pack.littleEndianToInt(kBytes, 8);
+ k3 = Pack.littleEndianToInt(kBytes, 12);
+ }
+
+ public String getAlgorithmName()
+ {
+ return cipher == null ? "Poly1305" : "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/core/src/main/java/org/spongycastle/crypto/macs/SipHash.java b/core/src/main/java/org/spongycastle/crypto/macs/SipHash.java
new file mode 100644
index 00000000..3489d4c1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/macs/SipHash.java
@@ -0,0 +1,216 @@
+package org.spongycastle.crypto.macs;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Pack;
+
+/**
+ * Implementation of SipHash as specified in "SipHash: a fast short-input PRF", by Jean-Philippe
+ * Aumasson and Daniel J. Bernstein (https://131002.net/siphash/siphash.pdf).
+ * <p>
+ * "SipHash is a family of PRFs SipHash-c-d where the integer parameters c and d are the number of
+ * compression rounds and the number of finalization rounds. A compression round is identical to a
+ * finalization round and this round function is called SipRound. Given a 128-bit key k and a
+ * (possibly empty) byte string m, SipHash-c-d returns a 64-bit value..."
+ */
+public class SipHash
+ implements Mac
+{
+ protected final int c, d;
+
+ protected long k0, k1;
+ protected long v0, v1, v2, v3;
+
+ protected long m = 0;
+ protected int wordPos = 0;
+ protected int wordCount = 0;
+
+ /**
+ * SipHash-2-4
+ */
+ public SipHash()
+ {
+ // use of 'this' confuses the flow analyser on earlier JDKs.
+ this.c = 2;
+ this.d = 4;
+ }
+
+ /**
+ * SipHash-c-d
+ *
+ * @param c the number of compression rounds
+ * @param d the number of finalization rounds
+ */
+ public SipHash(int c, int d)
+ {
+ this.c = c;
+ this.d = d;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "SipHash-" + c + "-" + d;
+ }
+
+ public int getMacSize()
+ {
+ return 8;
+ }
+
+ public void init(CipherParameters params)
+ throws IllegalArgumentException
+ {
+ if (!(params instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("'params' must be an instance of KeyParameter");
+ }
+ KeyParameter keyParameter = (KeyParameter)params;
+ byte[] key = keyParameter.getKey();
+ if (key.length != 16)
+ {
+ throw new IllegalArgumentException("'params' must be a 128-bit key");
+ }
+
+ this.k0 = Pack.littleEndianToLong(key, 0);
+ this.k1 = Pack.littleEndianToLong(key, 8);
+
+ reset();
+ }
+
+ public void update(byte input)
+ throws IllegalStateException
+ {
+ m >>>= 8;
+ m |= (input & 0xffL) << 56;
+
+ if (++wordPos == 8)
+ {
+ processMessageWord();
+ wordPos = 0;
+ }
+ }
+
+ public void update(byte[] input, int offset, int length)
+ throws DataLengthException,
+ IllegalStateException
+ {
+ int i = 0, fullWords = length & ~7;
+ if (wordPos == 0)
+ {
+ for (; i < fullWords; i += 8)
+ {
+ m = Pack.littleEndianToLong(input, offset + i);
+ processMessageWord();
+ }
+ for (; i < length; ++i)
+ {
+ m >>>= 8;
+ m |= (input[offset + i] & 0xffL) << 56;
+ }
+ wordPos = length - fullWords;
+ }
+ else
+ {
+ int bits = wordPos << 3;
+ for (; i < fullWords; i += 8)
+ {
+ long n = Pack.littleEndianToLong(input, offset + i);
+ m = (n << bits) | (m >>> -bits);
+ processMessageWord();
+ m = n;
+ }
+ for (; i < length; ++i)
+ {
+ m >>>= 8;
+ m |= (input[offset + i] & 0xffL) << 56;
+
+ if (++wordPos == 8)
+ {
+ processMessageWord();
+ wordPos = 0;
+ }
+ }
+ }
+ }
+
+ public long doFinal()
+ throws DataLengthException, IllegalStateException
+ {
+ // NOTE: 2 distinct shifts to avoid "64-bit shift" when wordPos == 0
+ m >>>= ((7 - wordPos) << 3);
+ m >>>= 8;
+ m |= (((wordCount << 3) + wordPos) & 0xffL) << 56;
+
+ processMessageWord();
+
+ v2 ^= 0xffL;
+
+ applySipRounds(d);
+
+ long result = v0 ^ v1 ^ v2 ^ v3;
+
+ reset();
+
+ return result;
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ long result = doFinal();
+ Pack.longToLittleEndian(result, out, outOff);
+ return 8;
+ }
+
+ public void reset()
+ {
+ v0 = k0 ^ 0x736f6d6570736575L;
+ v1 = k1 ^ 0x646f72616e646f6dL;
+ v2 = k0 ^ 0x6c7967656e657261L;
+ v3 = k1 ^ 0x7465646279746573L;
+
+ m = 0;
+ wordPos = 0;
+ wordCount = 0;
+ }
+
+ protected void processMessageWord()
+ {
+ ++wordCount;
+ v3 ^= m;
+ applySipRounds(c);
+ v0 ^= m;
+ }
+
+ protected void applySipRounds(int n)
+ {
+ long r0 = v0, r1 = v1, r2 = v2, r3 = v3;
+
+ for (int r = 0; r < n; ++r)
+ {
+ r0 += r1;
+ r2 += r3;
+ r1 = rotateLeft(r1, 13);
+ r3 = rotateLeft(r3, 16);
+ r1 ^= r0;
+ r3 ^= r2;
+ r0 = rotateLeft(r0, 32);
+ r2 += r1;
+ r0 += r3;
+ r1 = rotateLeft(r1, 17);
+ r3 = rotateLeft(r3, 21);
+ r1 ^= r2;
+ r3 ^= r0;
+ r2 = rotateLeft(r2, 32);
+ }
+
+ v0 = r0; v1 = r1; v2 = r2; v3 = r3;
+ }
+
+ protected static long rotateLeft(long x, int n)
+ {
+ return (x << n) | (x >>> -n);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/macs/SkeinMac.java b/core/src/main/java/org/spongycastle/crypto/macs/SkeinMac.java
new file mode 100644
index 00000000..b7a72f86
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/macs/SkeinMac.java
@@ -0,0 +1,118 @@
+package org.spongycastle.crypto.macs;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.digests.SkeinEngine;
+import org.spongycastle.crypto.engines.ThreefishEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.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.
+ *
+ * @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/core/src/main/java/org/spongycastle/crypto/macs/VMPCMac.java b/core/src/main/java/org/spongycastle/crypto/macs/VMPCMac.java
new file mode 100644
index 00000000..56a38ba9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/macs/VMPCMac.java
@@ -0,0 +1,186 @@
+package org.spongycastle.crypto.macs;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+
+public class VMPCMac implements Mac
+{
+ private byte g;
+
+ private byte n = 0;
+ private byte[] P = null;
+ private byte s = 0;
+
+ private byte[] T;
+ private byte[] workingIV;
+
+ private byte[] workingKey;
+
+ private byte x1, x2, x3, x4;
+
+ public int doFinal(byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ // Execute the Post-Processing Phase
+ for (int r = 1; r < 25; r++)
+ {
+ s = P[(s + P[n & 0xff]) & 0xff];
+
+ x4 = P[(x4 + x3 + r) & 0xff];
+ x3 = P[(x3 + x2 + r) & 0xff];
+ x2 = P[(x2 + x1 + r) & 0xff];
+ x1 = P[(x1 + s + r) & 0xff];
+ T[g & 0x1f] = (byte) (T[g & 0x1f] ^ x1);
+ T[(g + 1) & 0x1f] = (byte) (T[(g + 1) & 0x1f] ^ x2);
+ T[(g + 2) & 0x1f] = (byte) (T[(g + 2) & 0x1f] ^ x3);
+ T[(g + 3) & 0x1f] = (byte) (T[(g + 3) & 0x1f] ^ x4);
+ g = (byte) ((g + 4) & 0x1f);
+
+ byte temp = P[n & 0xff];
+ P[n & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ n = (byte) ((n + 1) & 0xff);
+ }
+
+ // Input T to the IV-phase of the VMPC KSA
+ for (int m = 0; m < 768; m++)
+ {
+ s = P[(s + P[m & 0xff] + T[m & 0x1f]) & 0xff];
+ byte temp = P[m & 0xff];
+ P[m & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ }
+
+ // Store 20 new outputs of the VMPC Stream Cipher in table M
+ byte[] M = new byte[20];
+ for (int i = 0; i < 20; i++)
+ {
+ s = P[(s + P[i & 0xff]) & 0xff];
+ M[i] = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff];
+
+ byte temp = P[i & 0xff];
+ P[i & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ }
+
+ System.arraycopy(M, 0, out, outOff, M.length);
+ reset();
+
+ return M.length;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "VMPC-MAC";
+ }
+
+ public int getMacSize()
+ {
+ return 20;
+ }
+
+ public void init(CipherParameters params) throws IllegalArgumentException
+ {
+ if (!(params instanceof ParametersWithIV))
+ {
+ throw new IllegalArgumentException(
+ "VMPC-MAC Init parameters must include an IV");
+ }
+
+ ParametersWithIV ivParams = (ParametersWithIV) params;
+ KeyParameter key = (KeyParameter) ivParams.getParameters();
+
+ if (!(ivParams.getParameters() instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException(
+ "VMPC-MAC Init parameters must include a key");
+ }
+
+ this.workingIV = ivParams.getIV();
+
+ if (workingIV == null || workingIV.length < 1 || workingIV.length > 768)
+ {
+ throw new IllegalArgumentException(
+ "VMPC-MAC requires 1 to 768 bytes of IV");
+ }
+
+ this.workingKey = key.getKey();
+
+ reset();
+
+ }
+
+ private void initKey(byte[] keyBytes, byte[] ivBytes)
+ {
+ s = 0;
+ P = new byte[256];
+ for (int i = 0; i < 256; i++)
+ {
+ P[i] = (byte) i;
+ }
+ for (int m = 0; m < 768; m++)
+ {
+ s = P[(s + P[m & 0xff] + keyBytes[m % keyBytes.length]) & 0xff];
+ byte temp = P[m & 0xff];
+ P[m & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ }
+ for (int m = 0; m < 768; m++)
+ {
+ s = P[(s + P[m & 0xff] + ivBytes[m % ivBytes.length]) & 0xff];
+ byte temp = P[m & 0xff];
+ P[m & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ }
+ n = 0;
+ }
+
+ public void reset()
+ {
+ initKey(this.workingKey, this.workingIV);
+ g = x1 = x2 = x3 = x4 = n = 0;
+ T = new byte[32];
+ for (int i = 0; i < 32; i++)
+ {
+ T[i] = 0;
+ }
+ }
+
+ public void update(byte in) throws IllegalStateException
+ {
+ s = P[(s + P[n & 0xff]) & 0xff];
+ byte c = (byte) (in ^ P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff]);
+
+ x4 = P[(x4 + x3) & 0xff];
+ x3 = P[(x3 + x2) & 0xff];
+ x2 = P[(x2 + x1) & 0xff];
+ x1 = P[(x1 + s + c) & 0xff];
+ T[g & 0x1f] = (byte) (T[g & 0x1f] ^ x1);
+ T[(g + 1) & 0x1f] = (byte) (T[(g + 1) & 0x1f] ^ x2);
+ T[(g + 2) & 0x1f] = (byte) (T[(g + 2) & 0x1f] ^ x3);
+ T[(g + 3) & 0x1f] = (byte) (T[(g + 3) & 0x1f] ^ x4);
+ g = (byte) ((g + 4) & 0x1f);
+
+ byte temp = P[n & 0xff];
+ P[n & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ n = (byte) ((n + 1) & 0xff);
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + len) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ for (int i = 0; i < len; i++)
+ {
+ update(in[i]);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/modes/AEADBlockCipher.java b/core/src/main/java/org/spongycastle/crypto/modes/AEADBlockCipher.java
new file mode 100644
index 00000000..ef48098e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/AEADBlockCipher.java
@@ -0,0 +1,146 @@
+package org.spongycastle.crypto.modes;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A block cipher mode that includes authenticated encryption with a streaming mode and optional associated data.
+ * <p>
+ * Implementations of this interface may operate in a packet mode (where all input data is buffered and
+ * processed dugin the call to {@link #doFinal(byte[], int)}), or in a streaming mode (where output data is
+ * incrementally produced with each call to {@link #processByte(byte, byte[], int)} or
+ * {@link #processBytes(byte[], int, int, byte[], int)}.
+ * </p>
+ * This is important to consider during decryption: in a streaming mode, unauthenticated plaintext data
+ * may be output prior to the call to {@link #doFinal(byte[], int)} that results in an authentication
+ * failure. The higher level protocol utilising this cipher must ensure the plaintext data is handled
+ * appropriately until the end of data is reached and the entire ciphertext is authenticated.
+ * @see org.spongycastle.crypto.params.AEADParameters
+ */
+public interface AEADBlockCipher
+{
+ /**
+ * initialise the underlying cipher. Parameter can either be an AEADParameters or a ParametersWithIV object.
+ *
+ * @param forEncryption true if we are setting up for encryption, false otherwise.
+ * @param params the necessary parameters for the underlying cipher to be initialised.
+ * @exception IllegalArgumentException if the params argument is inappropriate.
+ */
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException;
+
+ /**
+ * Return the name of the algorithm.
+ *
+ * @return the algorithm name.
+ */
+ public String getAlgorithmName();
+
+ /**
+ * return the cipher this object wraps.
+ *
+ * @return the cipher this object wraps.
+ */
+ public BlockCipher getUnderlyingCipher();
+
+ /**
+ * Add a single byte to the associated data check.
+ * <br>If the implementation supports it, this will be an online operation and will not retain the associated data.
+ *
+ * @param in the byte to be processed.
+ */
+ public void processAADByte(byte in);
+
+ /**
+ * Add a sequence of bytes to the associated data check.
+ * <br>If the implementation supports it, this will be an online operation and will not retain the associated data.
+ *
+ * @param in the input byte array.
+ * @param inOff the offset into the in array where the data to be processed starts.
+ * @param len the number of bytes to be processed.
+ */
+ public void processAADBytes(byte[] in, int inOff, int len);
+
+ /**
+ * encrypt/decrypt a single byte.
+ *
+ * @param in the byte to be processed.
+ * @param out the output buffer the processed byte goes into.
+ * @param outOff the offset into the output byte array the processed data starts at.
+ * @return the number of bytes written to out.
+ * @exception DataLengthException if the output buffer is too small.
+ */
+ public int processByte(byte in, byte[] out, int outOff)
+ throws DataLengthException;
+
+ /**
+ * process a block of bytes from in putting the result into out.
+ *
+ * @param in the input byte array.
+ * @param inOff the offset into the in array where the data to be processed starts.
+ * @param len the number of bytes to be processed.
+ * @param out the output buffer the processed bytes go into.
+ * @param outOff the offset into the output byte array the processed data starts at.
+ * @return the number of bytes written to out.
+ * @exception DataLengthException if the output buffer is too small.
+ */
+ public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
+ throws DataLengthException;
+
+ /**
+ * Finish the operation either appending or verifying the MAC at the end of the data.
+ *
+ * @param out space for any resulting output data.
+ * @param outOff offset into out to start copying the data at.
+ * @return number of bytes written into out.
+ * @throws IllegalStateException if the cipher is in an inappropriate state.
+ * @throws org.spongycastle.crypto.InvalidCipherTextException if the MAC fails to match.
+ */
+ public int doFinal(byte[] out, int outOff)
+ throws IllegalStateException, InvalidCipherTextException;
+
+ /**
+ * Return the value of the MAC associated with the last stream processed.
+ *
+ * @return MAC for plaintext data.
+ */
+ public byte[] getMac();
+
+ /**
+ * return the size of the output buffer required for a processBytes
+ * an input of len bytes.
+ * <p>
+ * The returned size may be dependent on the initialisation of this cipher
+ * and may not be accurate once subsequent input data is processed - this method
+ * should be invoked immediately prior to input data being processed.
+ * </p>
+ *
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to processBytes
+ * with len bytes of input.
+ */
+ public int getUpdateOutputSize(int len);
+
+ /**
+ * return the size of the output buffer required for a processBytes plus a
+ * doFinal with an input of len bytes.
+ * <p>
+ * The returned size may be dependent on the initialisation of this cipher
+ * and may not be accurate once subsequent input data is processed - this method
+ * should be invoked immediately prior to a call to final processing of input data
+ * and a call to {@link #doFinal(byte[], int)}.
+ * </p>
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to processBytes and doFinal
+ * with len bytes of input.
+ */
+ public int getOutputSize(int len);
+
+ /**
+ * Reset the cipher. After resetting the cipher is in the same state
+ * as it was after the last init (if there was one).
+ */
+ public void reset();
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/modes/CBCBlockCipher.java b/core/src/main/java/org/spongycastle/crypto/modes/CBCBlockCipher.java
new file mode 100644
index 00000000..381eab8a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/CBCBlockCipher.java
@@ -0,0 +1,253 @@
+package org.spongycastle.crypto.modes;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Arrays;
+
+/**
+ * implements Cipher-Block-Chaining (CBC) mode on top of a simple cipher.
+ */
+public class CBCBlockCipher
+ implements BlockCipher
+{
+ private byte[] IV;
+ private byte[] cbcV;
+ private byte[] cbcNextV;
+
+ private int blockSize;
+ private BlockCipher cipher = null;
+ private boolean encrypting;
+
+ /**
+ * Basic constructor.
+ *
+ * @param cipher the block cipher to be used as the basis of chaining.
+ */
+ public CBCBlockCipher(
+ BlockCipher cipher)
+ {
+ this.cipher = cipher;
+ this.blockSize = cipher.getBlockSize();
+
+ this.IV = new byte[blockSize];
+ this.cbcV = new byte[blockSize];
+ this.cbcNextV = new byte[blockSize];
+ }
+
+ /**
+ * return the underlying block cipher that we are wrapping.
+ *
+ * @return the underlying block cipher that we are wrapping.
+ */
+ public BlockCipher getUnderlyingCipher()
+ {
+ return cipher;
+ }
+
+ /**
+ * Initialise the cipher and, possibly, the initialisation vector (IV).
+ * If an IV isn't passed as part of the parameter, the IV will be all zeros.
+ *
+ * @param encrypting if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ boolean oldEncrypting = this.encrypting;
+
+ this.encrypting = encrypting;
+
+ if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV ivParam = (ParametersWithIV)params;
+ byte[] iv = ivParam.getIV();
+
+ if (iv.length != blockSize)
+ {
+ throw new IllegalArgumentException("initialisation vector must be the same length as block size");
+ }
+
+ System.arraycopy(iv, 0, IV, 0, iv.length);
+
+ reset();
+
+ // if null it's an IV changed only.
+ if (ivParam.getParameters() != null)
+ {
+ cipher.init(encrypting, ivParam.getParameters());
+ }
+ else if (oldEncrypting != encrypting)
+ {
+ throw new IllegalArgumentException("cannot change encrypting state without providing key.");
+ }
+ }
+ else
+ {
+ reset();
+
+ // if it's null, key is to be reused.
+ if (params != null)
+ {
+ cipher.init(encrypting, params);
+ }
+ else if (oldEncrypting != encrypting)
+ {
+ throw new IllegalArgumentException("cannot change encrypting state without providing key.");
+ }
+ }
+ }
+
+ /**
+ * return the algorithm name and mode.
+ *
+ * @return the name of the underlying algorithm followed by "/CBC".
+ */
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName() + "/CBC";
+ }
+
+ /**
+ * return the block size of the underlying cipher.
+ *
+ * @return the block size of the underlying cipher.
+ */
+ public int getBlockSize()
+ {
+ return cipher.getBlockSize();
+ }
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ return (encrypting) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff);
+ }
+
+ /**
+ * reset the chaining vector back to the IV and reset the underlying
+ * cipher.
+ */
+ public void reset()
+ {
+ System.arraycopy(IV, 0, cbcV, 0, IV.length);
+ Arrays.fill(cbcNextV, (byte)0);
+
+ cipher.reset();
+ }
+
+ /**
+ * Do the appropriate chaining step for CBC mode encryption.
+ *
+ * @param in the array containing the data to be encrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the encrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ private int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ /*
+ * XOR the cbcV and the input,
+ * then encrypt the cbcV
+ */
+ for (int i = 0; i < blockSize; i++)
+ {
+ cbcV[i] ^= in[inOff + i];
+ }
+
+ int length = cipher.processBlock(cbcV, 0, out, outOff);
+
+ /*
+ * copy ciphertext to cbcV
+ */
+ System.arraycopy(out, outOff, cbcV, 0, cbcV.length);
+
+ return length;
+ }
+
+ /**
+ * Do the appropriate chaining step for CBC mode decryption.
+ *
+ * @param in the array containing the data to be decrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the decrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ private int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ System.arraycopy(in, inOff, cbcNextV, 0, blockSize);
+
+ int length = cipher.processBlock(in, inOff, out, outOff);
+
+ /*
+ * XOR the cbcV and the output
+ */
+ for (int i = 0; i < blockSize; i++)
+ {
+ out[outOff + i] ^= cbcV[i];
+ }
+
+ /*
+ * swap the back up buffer into next position
+ */
+ byte[] tmp;
+
+ tmp = cbcV;
+ cbcV = cbcNextV;
+ cbcNextV = tmp;
+
+ return length;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/modes/CCMBlockCipher.java b/core/src/main/java/org/spongycastle/crypto/modes/CCMBlockCipher.java
new file mode 100644
index 00000000..0b713f63
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/CCMBlockCipher.java
@@ -0,0 +1,457 @@
+package org.spongycastle.crypto.modes;
+
+import java.io.ByteArrayOutputStream;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.macs.CBCBlockCipherMac;
+import org.spongycastle.crypto.params.AEADParameters;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Arrays;
+
+/**
+ * Implements the Counter with Cipher Block Chaining mode (CCM) detailed in
+ * NIST Special Publication 800-38C.
+ * <p>
+ * <b>Note</b>: this mode is a packet mode - it needs all the data up front.
+ */
+public class CCMBlockCipher
+ implements AEADBlockCipher
+{
+ private BlockCipher cipher;
+ private int blockSize;
+ private boolean forEncryption;
+ private byte[] nonce;
+ private byte[] initialAssociatedText;
+ private int macSize;
+ private CipherParameters keyParam;
+ private byte[] macBlock;
+ private ExposedByteArrayOutputStream associatedText = new ExposedByteArrayOutputStream();
+ private ExposedByteArrayOutputStream data = new ExposedByteArrayOutputStream();
+
+ /**
+ * Basic constructor.
+ *
+ * @param c the block cipher to be used.
+ */
+ public CCMBlockCipher(BlockCipher c)
+ {
+ this.cipher = c;
+ this.blockSize = c.getBlockSize();
+ this.macBlock = new byte[blockSize];
+
+ if (blockSize != 16)
+ {
+ throw new IllegalArgumentException("cipher required with a block size of 16.");
+ }
+ }
+
+ /**
+ * return the underlying block cipher that we are wrapping.
+ *
+ * @return the underlying block cipher that we are wrapping.
+ */
+ public BlockCipher getUnderlyingCipher()
+ {
+ return cipher;
+ }
+
+
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ this.forEncryption = forEncryption;
+
+ CipherParameters cipherParameters;
+ if (params instanceof AEADParameters)
+ {
+ AEADParameters param = (AEADParameters)params;
+
+ nonce = param.getNonce();
+ initialAssociatedText = param.getAssociatedText();
+ macSize = param.getMacSize() / 8;
+ cipherParameters = param.getKey();
+ }
+ else if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV param = (ParametersWithIV)params;
+
+ nonce = param.getIV();
+ initialAssociatedText = null;
+ macSize = macBlock.length / 2;
+ 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()
+ {
+ return cipher.getAlgorithmName() + "/CCM";
+ }
+
+ public void processAADByte(byte in)
+ {
+ associatedText.write(in);
+ }
+
+ public void processAADBytes(byte[] in, int inOff, int len)
+ {
+ // TODO: Process AAD online
+ associatedText.write(in, inOff, len);
+ }
+
+ public int processByte(byte in, byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ data.write(in);
+
+ return 0;
+ }
+
+ public int processBytes(byte[] in, int inOff, int inLen, byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if (in.length < (inOff + inLen))
+ {
+ throw new DataLengthException("Input buffer too short");
+ }
+ data.write(in, inOff, inLen);
+
+ return 0;
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ throws IllegalStateException, InvalidCipherTextException
+ {
+ int len = processPacket(data.getBuffer(), 0, data.size(), out, outOff);
+
+ reset();
+
+ return len;
+ }
+
+ public void reset()
+ {
+ cipher.reset();
+ associatedText.reset();
+ data.reset();
+ }
+
+ /**
+ * Returns a byte array containing the mac calculated as part of the
+ * last encrypt or decrypt operation.
+ *
+ * @return the last mac calculated.
+ */
+ public byte[] getMac()
+ {
+ byte[] mac = new byte[macSize];
+
+ System.arraycopy(macBlock, 0, mac, 0, mac.length);
+
+ return mac;
+ }
+
+ public int getUpdateOutputSize(int len)
+ {
+ return 0;
+ }
+
+ public int getOutputSize(int len)
+ {
+ int totalData = len + data.size();
+
+ if (forEncryption)
+ {
+ return totalData + macSize;
+ }
+
+ 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)
+ {
+ throw new IllegalStateException("CCM cipher unitialized.");
+ }
+
+ int n = nonce.length;
+ int q = 15 - n;
+ if (q < 4)
+ {
+ int limitLen = 1 << (8 * q);
+ if (inLen >= limitLen)
+ {
+ throw new IllegalStateException("CCM packet too large for choice of q.");
+ }
+ }
+
+ byte[] iv = new byte[blockSize];
+ iv[0] = (byte)((q - 1) & 0x7);
+ System.arraycopy(nonce, 0, iv, 1, nonce.length);
+
+ BlockCipher ctrCipher = new SICBlockCipher(cipher);
+ ctrCipher.init(forEncryption, new ParametersWithIV(keyParam, iv));
+
+ int outputLen;
+ int inIndex = inOff;
+ int outIndex = outOff;
+
+ if (forEncryption)
+ {
+ outputLen = inLen + macSize;
+ if (output.length < (outputLen + outOff))
+ {
+ throw new OutputLengthException("Output buffer too short.");
+ }
+
+ calculateMac(in, inOff, inLen, macBlock);
+
+ ctrCipher.processBlock(macBlock, 0, macBlock, 0); // S0
+
+ while (inIndex < (inOff + inLen - blockSize)) // S1...
+ {
+ ctrCipher.processBlock(in, inIndex, output, outIndex);
+ outIndex += blockSize;
+ inIndex += blockSize;
+ }
+
+ byte[] block = new byte[blockSize];
+
+ System.arraycopy(in, inIndex, block, 0, inLen + inOff - inIndex);
+
+ ctrCipher.processBlock(block, 0, block, 0);
+
+ System.arraycopy(block, 0, output, outIndex, inLen + inOff - inIndex);
+
+ System.arraycopy(macBlock, 0, output, outOff + inLen, macSize);
+ }
+ else
+ {
+ if (inLen < macSize)
+ {
+ throw new InvalidCipherTextException("data too short");
+ }
+ outputLen = inLen - macSize;
+ if (output.length < (outputLen + outOff))
+ {
+ throw new OutputLengthException("Output buffer too short.");
+ }
+
+ System.arraycopy(in, inOff + outputLen, macBlock, 0, macSize);
+
+ ctrCipher.processBlock(macBlock, 0, macBlock, 0);
+
+ for (int i = macSize; i != macBlock.length; i++)
+ {
+ macBlock[i] = 0;
+ }
+
+ while (inIndex < (inOff + outputLen - blockSize))
+ {
+ ctrCipher.processBlock(in, inIndex, output, outIndex);
+ outIndex += blockSize;
+ inIndex += blockSize;
+ }
+
+ byte[] block = new byte[blockSize];
+
+ System.arraycopy(in, inIndex, block, 0, outputLen - (inIndex - inOff));
+
+ ctrCipher.processBlock(block, 0, block, 0);
+
+ System.arraycopy(block, 0, output, outIndex, outputLen - (inIndex - inOff));
+
+ byte[] calculatedMacBlock = new byte[blockSize];
+
+ calculateMac(output, outOff, outputLen, calculatedMacBlock);
+
+ if (!Arrays.constantTimeAreEqual(macBlock, calculatedMacBlock))
+ {
+ throw new InvalidCipherTextException("mac check in CCM failed");
+ }
+ }
+
+ return outputLen;
+ }
+
+ private int calculateMac(byte[] data, int dataOff, int dataLen, byte[] macBlock)
+ {
+ Mac cMac = new CBCBlockCipherMac(cipher, macSize * 8);
+
+ cMac.init(keyParam);
+
+ //
+ // build b0
+ //
+ byte[] b0 = new byte[16];
+
+ if (hasAssociatedText())
+ {
+ b0[0] |= 0x40;
+ }
+
+ b0[0] |= (((cMac.getMacSize() - 2) / 2) & 0x7) << 3;
+
+ b0[0] |= ((15 - nonce.length) - 1) & 0x7;
+
+ System.arraycopy(nonce, 0, b0, 1, nonce.length);
+
+ int q = dataLen;
+ int count = 1;
+ while (q > 0)
+ {
+ b0[b0.length - count] = (byte)(q & 0xff);
+ q >>>= 8;
+ count++;
+ }
+
+ cMac.update(b0, 0, b0.length);
+
+ //
+ // process associated text
+ //
+ if (hasAssociatedText())
+ {
+ int extra;
+
+ int textLength = getAssociatedTextLength();
+ if (textLength < ((1 << 16) - (1 << 8)))
+ {
+ cMac.update((byte)(textLength >> 8));
+ cMac.update((byte)textLength);
+
+ extra = 2;
+ }
+ else // can't go any higher than 2^32
+ {
+ cMac.update((byte)0xff);
+ cMac.update((byte)0xfe);
+ cMac.update((byte)(textLength >> 24));
+ cMac.update((byte)(textLength >> 16));
+ cMac.update((byte)(textLength >> 8));
+ cMac.update((byte)textLength);
+
+ extra = 6;
+ }
+
+ if (initialAssociatedText != null)
+ {
+ cMac.update(initialAssociatedText, 0, initialAssociatedText.length);
+ }
+ if (associatedText.size() > 0)
+ {
+ cMac.update(associatedText.getBuffer(), 0, associatedText.size());
+ }
+
+ extra = (extra + textLength) % 16;
+ if (extra != 0)
+ {
+ for (int i = extra; i != 16; i++)
+ {
+ cMac.update((byte)0x00);
+ }
+ }
+ }
+
+ //
+ // add the text
+ //
+ cMac.update(data, dataOff, dataLen);
+
+ return cMac.doFinal(macBlock, 0);
+ }
+
+ private int getAssociatedTextLength()
+ {
+ return associatedText.size() + ((initialAssociatedText == null) ? 0 : initialAssociatedText.length);
+ }
+
+ private boolean hasAssociatedText()
+ {
+ return getAssociatedTextLength() > 0;
+ }
+
+ private class ExposedByteArrayOutputStream
+ extends ByteArrayOutputStream
+ {
+ public ExposedByteArrayOutputStream()
+ {
+ }
+
+ public byte[] getBuffer()
+ {
+ return this.buf;
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/modes/CFBBlockCipher.java b/core/src/main/java/org/spongycastle/crypto/modes/CFBBlockCipher.java
new file mode 100644
index 00000000..52bf2cc9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/CFBBlockCipher.java
@@ -0,0 +1,269 @@
+package org.spongycastle.crypto.modes;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.StreamBlockCipher;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Arrays;
+
+/**
+ * implements a Cipher-FeedBack (CFB) mode on top of a simple cipher.
+ */
+public class CFBBlockCipher
+ extends StreamBlockCipher
+{
+ private byte[] IV;
+ private byte[] cfbV;
+ private byte[] cfbOutV;
+ private byte[] inBuf;
+
+ private int blockSize;
+ private BlockCipher cipher = null;
+ private boolean encrypting;
+ private int byteCount;
+
+ /**
+ * Basic constructor.
+ *
+ * @param cipher the block cipher to be used as the basis of the
+ * feedback mode.
+ * @param bitBlockSize the block size in bits (note: a multiple of 8)
+ */
+ public CFBBlockCipher(
+ BlockCipher cipher,
+ int bitBlockSize)
+ {
+ super(cipher);
+
+ this.cipher = cipher;
+ this.blockSize = bitBlockSize / 8;
+
+ this.IV = new byte[cipher.getBlockSize()];
+ this.cfbV = new byte[cipher.getBlockSize()];
+ this.cfbOutV = new byte[cipher.getBlockSize()];
+ this.inBuf = new byte[blockSize];
+ }
+
+ /**
+ * Initialise the cipher and, possibly, the initialisation vector (IV).
+ * If an IV isn't passed as part of the parameter, the IV will be all zeros.
+ * An IV which is too short is handled in FIPS compliant fashion.
+ *
+ * @param encrypting if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ this.encrypting = encrypting;
+
+ if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV ivParam = (ParametersWithIV)params;
+ byte[] iv = ivParam.getIV();
+
+ if (iv.length < IV.length)
+ {
+ // prepend the supplied IV with zeros (per FIPS PUB 81)
+ System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
+ for (int i = 0; i < IV.length - iv.length; i++)
+ {
+ IV[i] = 0;
+ }
+ }
+ else
+ {
+ System.arraycopy(iv, 0, IV, 0, IV.length);
+ }
+
+ reset();
+
+ // if null it's an IV changed only.
+ if (ivParam.getParameters() != null)
+ {
+ cipher.init(true, ivParam.getParameters());
+ }
+ }
+ else
+ {
+ reset();
+
+ // if it's null, key is to be reused.
+ if (params != null)
+ {
+ cipher.init(true, params);
+ }
+ }
+ }
+
+ /**
+ * return the algorithm name and mode.
+ *
+ * @return the name of the underlying algorithm followed by "/CFB"
+ * and the block size in bits.
+ */
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName() + "/CFB" + (blockSize * 8);
+ }
+
+ protected byte calculateByte(byte in)
+ throws DataLengthException, IllegalStateException
+ {
+ return (encrypting) ? encryptByte(in) : decryptByte(in);
+ }
+
+ private byte encryptByte(byte in)
+ {
+ if (byteCount == 0)
+ {
+ cipher.processBlock(cfbV, 0, cfbOutV, 0);
+ }
+
+ byte rv = (byte)(cfbOutV[byteCount] ^ in);
+ inBuf[byteCount++] = rv;
+
+ if (byteCount == blockSize)
+ {
+ byteCount = 0;
+
+ System.arraycopy(cfbV, blockSize, cfbV, 0, cfbV.length - blockSize);
+ System.arraycopy(inBuf, 0, cfbV, cfbV.length - blockSize, blockSize);
+ }
+
+ return rv;
+ }
+
+ private byte decryptByte(byte in)
+ {
+ if (byteCount == 0)
+ {
+ cipher.processBlock(cfbV, 0, cfbOutV, 0);
+ }
+
+ inBuf[byteCount] = in;
+ byte rv = (byte)(cfbOutV[byteCount++] ^ in);
+
+ if (byteCount == blockSize)
+ {
+ byteCount = 0;
+
+ System.arraycopy(cfbV, blockSize, cfbV, 0, cfbV.length - blockSize);
+ System.arraycopy(inBuf, 0, cfbV, cfbV.length - blockSize, blockSize);
+ }
+
+ return rv;
+ }
+
+ /**
+ * return the block size we are operating at.
+ *
+ * @return the block size we are operating at (in bytes).
+ */
+ public int getBlockSize()
+ {
+ return blockSize;
+ }
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ processBytes(in, inOff, blockSize, out, outOff);
+
+ return blockSize;
+ }
+
+ /**
+ * Do the appropriate processing for CFB mode encryption.
+ *
+ * @param in the array containing the data to be encrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the encrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ processBytes(in, inOff, blockSize, out, outOff);
+
+ return blockSize;
+ }
+
+ /**
+ * Do the appropriate processing for CFB mode decryption.
+ *
+ * @param in the array containing the data to be decrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the encrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ processBytes(in, inOff, blockSize, out, outOff);
+
+ return blockSize;
+ }
+
+ /**
+ * 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.
+ */
+ public void reset()
+ {
+ System.arraycopy(IV, 0, cfbV, 0, IV.length);
+ Arrays.fill(inBuf, (byte)0);
+ byteCount = 0;
+
+ cipher.reset();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/modes/CTSBlockCipher.java b/core/src/main/java/org/spongycastle/crypto/modes/CTSBlockCipher.java
new file mode 100644
index 00000000..d56fd10b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/CTSBlockCipher.java
@@ -0,0 +1,287 @@
+package org.spongycastle.crypto.modes;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.BufferedBlockCipher;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.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.
+ */
+public class CTSBlockCipher
+ 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 CTSBlockCipher(
+ BlockCipher cipher)
+ {
+ 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");
+ }
+
+ 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 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 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 DataLengthException if there is insufficient space in out for
+ * the output.
+ * @exception IllegalStateException if the underlying cipher is not
+ * initialised.
+ * @exception 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)
+ {
+ if (bufOff < blockSize)
+ {
+ throw new DataLengthException("need at least one block of input for CTS");
+ }
+
+ cipher.processBlock(buf, 0, block, 0);
+
+ if (bufOff > blockSize)
+ {
+ 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
+ {
+ System.arraycopy(block, 0, out, outOff, blockSize);
+ }
+ }
+ else
+ {
+ if (bufOff < blockSize)
+ {
+ throw new DataLengthException("need at least one block of input for CTS");
+ }
+
+ byte[] lastBlock = new byte[blockSize];
+
+ if (bufOff > 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);
+ }
+ else
+ {
+ cipher.processBlock(buf, 0, block, 0);
+
+ System.arraycopy(block, 0, out, outOff, blockSize);
+ }
+ }
+
+ int offset = bufOff;
+
+ reset();
+
+ return offset;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/modes/EAXBlockCipher.java b/core/src/main/java/org/spongycastle/crypto/modes/EAXBlockCipher.java
new file mode 100644
index 00000000..f997689b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/EAXBlockCipher.java
@@ -0,0 +1,387 @@
+package org.spongycastle.crypto.modes;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.macs.CMac;
+import org.spongycastle.crypto.params.AEADParameters;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Arrays;
+
+/**
+ * A Two-Pass Authenticated-Encryption Scheme Optimized for Simplicity and
+ * Efficiency - by M. Bellare, P. Rogaway, D. Wagner.
+ *
+ * http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf
+ *
+ * EAX is an AEAD scheme based on CTR and OMAC1/CMAC, that uses a single block
+ * cipher to encrypt and authenticate data. It's on-line (the length of a
+ * message isn't needed to begin processing it), has good performances, it's
+ * simple and provably secure (provided the underlying block cipher is secure).
+ *
+ * Of course, this implementations is NOT thread-safe.
+ */
+public class EAXBlockCipher
+ implements AEADBlockCipher
+{
+ private static final byte nTAG = 0x0;
+
+ private static final byte hTAG = 0x1;
+
+ private static final byte cTAG = 0x2;
+
+ private SICBlockCipher cipher;
+
+ private boolean forEncryption;
+
+ private int blockSize;
+
+ private Mac mac;
+
+ private byte[] nonceMac;
+ private byte[] associatedTextMac;
+ private byte[] macBlock;
+
+ private int macSize;
+ private byte[] bufBlock;
+ private int bufOff;
+
+ private boolean cipherInitialized;
+ private byte[] initialAssociatedText;
+
+ /**
+ * Constructor that accepts an instance of a block cipher engine.
+ *
+ * @param cipher the engine to use
+ */
+ public EAXBlockCipher(BlockCipher cipher)
+ {
+ blockSize = cipher.getBlockSize();
+ mac = new CMac(cipher);
+ macBlock = new byte[blockSize];
+ associatedTextMac = new byte[mac.getMacSize()];
+ nonceMac = new byte[mac.getMacSize()];
+ this.cipher = new SICBlockCipher(cipher);
+ }
+
+ public String getAlgorithmName()
+ {
+ return cipher.getUnderlyingCipher().getAlgorithmName() + "/EAX";
+ }
+
+ public BlockCipher getUnderlyingCipher()
+ {
+ return cipher.getUnderlyingCipher();
+ }
+
+ public int getBlockSize()
+ {
+ return cipher.getBlockSize();
+ }
+
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ this.forEncryption = forEncryption;
+
+ byte[] nonce;
+ CipherParameters keyParam;
+
+ if (params instanceof AEADParameters)
+ {
+ AEADParameters param = (AEADParameters)params;
+
+ nonce = param.getNonce();
+ initialAssociatedText = param.getAssociatedText();
+ macSize = param.getMacSize() / 8;
+ keyParam = param.getKey();
+ }
+ else if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV param = (ParametersWithIV)params;
+
+ nonce = param.getIV();
+ initialAssociatedText = null;
+ macSize = mac.getMacSize() / 2;
+ keyParam = param.getParameters();
+ }
+ else
+ {
+ throw new IllegalArgumentException("invalid parameters passed to EAX");
+ }
+
+ bufBlock = new byte[forEncryption ? blockSize : (blockSize + macSize)];
+
+ byte[] tag = new byte[blockSize];
+
+ // Key reuse implemented in CBC mode of underlying CMac
+ mac.init(keyParam);
+
+ tag[blockSize - 1] = nTAG;
+ mac.update(tag, 0, blockSize);
+ mac.update(nonce, 0, nonce.length);
+ mac.doFinal(nonceMac, 0);
+
+ // Same BlockCipher underlies this and the mac, so reuse last key on cipher
+ cipher.init(true, new ParametersWithIV(null, nonceMac));
+
+ reset();
+ }
+
+ private void initCipher()
+ {
+ if (cipherInitialized)
+ {
+ return;
+ }
+
+ cipherInitialized = true;
+
+ mac.doFinal(associatedTextMac, 0);
+
+ byte[] tag = new byte[blockSize];
+ tag[blockSize - 1] = cTAG;
+ mac.update(tag, 0, blockSize);
+ }
+
+ private void calculateMac()
+ {
+ byte[] outC = new byte[blockSize];
+ mac.doFinal(outC, 0);
+
+ for (int i = 0; i < macBlock.length; i++)
+ {
+ macBlock[i] = (byte)(nonceMac[i] ^ associatedTextMac[i] ^ outC[i]);
+ }
+ }
+
+ public void reset()
+ {
+ reset(true);
+ }
+
+ private void reset(
+ boolean clearMac)
+ {
+ cipher.reset(); // TODO Redundant since the mac will reset it?
+ mac.reset();
+
+ bufOff = 0;
+ Arrays.fill(bufBlock, (byte)0);
+
+ if (clearMac)
+ {
+ Arrays.fill(macBlock, (byte)0);
+ }
+
+ byte[] tag = new byte[blockSize];
+ tag[blockSize - 1] = hTAG;
+ mac.update(tag, 0, blockSize);
+
+ cipherInitialized = false;
+
+ if (initialAssociatedText != null)
+ {
+ processAADBytes(initialAssociatedText, 0, initialAssociatedText.length);
+ }
+ }
+
+ public void processAADByte(byte in)
+ {
+ if (cipherInitialized)
+ {
+ throw new IllegalStateException("AAD data cannot be added after encryption/decription processing has begun.");
+ }
+ mac.update(in);
+ }
+
+ public void processAADBytes(byte[] in, int inOff, int len)
+ {
+ if (cipherInitialized)
+ {
+ throw new IllegalStateException("AAD data cannot be added after encryption/decryption processing has begun.");
+ }
+ mac.update(in, inOff, len);
+ }
+
+ public int processByte(byte in, byte[] out, int outOff)
+ throws DataLengthException
+ {
+ initCipher();
+
+ return process(in, out, outOff);
+ }
+
+ public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
+ throws DataLengthException
+ {
+ initCipher();
+
+ if (in.length < (inOff + len))
+ {
+ throw new DataLengthException("Input buffer too short");
+ }
+
+ int resultLen = 0;
+
+ for (int i = 0; i != len; i++)
+ {
+ resultLen += process(in[inOff + i], out, outOff + resultLen);
+ }
+
+ return resultLen;
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ throws IllegalStateException, InvalidCipherTextException
+ {
+ initCipher();
+
+ int extra = bufOff;
+ byte[] tmp = new byte[bufBlock.length];
+
+ bufOff = 0;
+
+ if (forEncryption)
+ {
+ if (out.length < (outOff + extra + macSize))
+ {
+ throw new OutputLengthException("Output buffer too short");
+ }
+ cipher.processBlock(bufBlock, 0, tmp, 0);
+
+ System.arraycopy(tmp, 0, out, outOff, extra);
+
+ mac.update(tmp, 0, extra);
+
+ calculateMac();
+
+ System.arraycopy(macBlock, 0, out, outOff + extra, macSize);
+
+ reset(false);
+
+ return extra + macSize;
+ }
+ else
+ {
+ if (out.length < (outOff + extra - macSize))
+ {
+ throw new OutputLengthException("Output buffer too short");
+ }
+ if (extra < macSize)
+ {
+ throw new InvalidCipherTextException("data too short");
+ }
+ if (extra > macSize)
+ {
+ mac.update(bufBlock, 0, extra - macSize);
+
+ cipher.processBlock(bufBlock, 0, tmp, 0);
+
+ System.arraycopy(tmp, 0, out, outOff, extra - macSize);
+ }
+
+ calculateMac();
+
+ if (!verifyMac(bufBlock, extra - macSize))
+ {
+ throw new InvalidCipherTextException("mac check in EAX failed");
+ }
+
+ reset(false);
+
+ return extra - macSize;
+ }
+ }
+
+ public byte[] getMac()
+ {
+ byte[] mac = new byte[macSize];
+
+ System.arraycopy(macBlock, 0, mac, 0, macSize);
+
+ return mac;
+ }
+
+ public int getUpdateOutputSize(int len)
+ {
+ int totalData = len + bufOff;
+ if (!forEncryption)
+ {
+ if (totalData < macSize)
+ {
+ return 0;
+ }
+ totalData -= macSize;
+ }
+ return totalData - totalData % blockSize;
+ }
+
+ public int getOutputSize(int len)
+ {
+ int totalData = len + bufOff;
+
+ if (forEncryption)
+ {
+ return totalData + macSize;
+ }
+
+ return totalData < macSize ? 0 : totalData - macSize;
+ }
+
+ private int process(byte b, byte[] out, int outOff)
+ {
+ bufBlock[bufOff++] = b;
+
+ if (bufOff == bufBlock.length)
+ {
+ if (out.length < (outOff + blockSize))
+ {
+ throw new OutputLengthException("Output buffer is too short");
+ }
+ // TODO Could move the processByte(s) calls to here
+// initCipher();
+
+ int size;
+
+ if (forEncryption)
+ {
+ size = cipher.processBlock(bufBlock, 0, out, outOff);
+
+ mac.update(out, outOff, blockSize);
+ }
+ else
+ {
+ mac.update(bufBlock, 0, blockSize);
+
+ size = cipher.processBlock(bufBlock, 0, out, outOff);
+ }
+
+ bufOff = 0;
+ if (!forEncryption)
+ {
+ System.arraycopy(bufBlock, blockSize, bufBlock, 0, macSize);
+ bufOff = macSize;
+ }
+
+ return size;
+ }
+
+ return 0;
+ }
+
+ private boolean verifyMac(byte[] mac, int off)
+ {
+ int nonEqual = 0;
+
+ for (int i = 0; i < macSize; i++)
+ {
+ nonEqual |= (macBlock[i] ^ mac[off + i]);
+ }
+
+ return nonEqual == 0;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/modes/GCFBBlockCipher.java b/core/src/main/java/org/spongycastle/crypto/modes/GCFBBlockCipher.java
new file mode 100644
index 00000000..545b6208
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/GCFBBlockCipher.java
@@ -0,0 +1,120 @@
+package org.spongycastle.crypto.modes;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.StreamBlockCipher;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.params.ParametersWithSBox;
+
+/**
+ * An implementation of the GOST CFB mode with CryptoPro key meshing as described in RFC 4357.
+ */
+public class GCFBBlockCipher
+ extends StreamBlockCipher
+{
+ 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)
+ {
+ super(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()
+ {
+ String name = cfbEngine.getAlgorithmName();
+ return name.substring(0, name.indexOf('/') - 1) + "/G" + name.substring(name.indexOf('/') + 1);
+ }
+
+ public int getBlockSize()
+ {
+ return cfbEngine.getBlockSize();
+ }
+
+ public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ this.processBytes(in, inOff, cfbEngine.getBlockSize(), out, outOff);
+
+ return cfbEngine.getBlockSize();
+ }
+
+ protected byte calculateByte(byte b)
+ {
+ 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);
+
+ base.init(true, key);
+
+ byte[] iv = cfbEngine.getCurrentIV();
+
+ base.processBlock(iv, 0, iv, 0);
+
+ cfbEngine.init(forEncryption, new ParametersWithIV(key, iv));
+ }
+
+ counter++;
+
+ return cfbEngine.calculateByte(b);
+ }
+
+ public void reset()
+ {
+ counter = 0;
+ cfbEngine.reset();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/modes/GCMBlockCipher.java b/core/src/main/java/org/spongycastle/crypto/modes/GCMBlockCipher.java
new file mode 100644
index 00000000..d45c586d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/GCMBlockCipher.java
@@ -0,0 +1,596 @@
+package org.spongycastle.crypto.modes;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.modes.gcm.GCMExponentiator;
+import org.spongycastle.crypto.modes.gcm.GCMMultiplier;
+import org.spongycastle.crypto.modes.gcm.Tables1kGCMExponentiator;
+import org.spongycastle.crypto.modes.gcm.Tables8kGCMMultiplier;
+import org.spongycastle.crypto.params.AEADParameters;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Pack;
+
+/**
+ * Implements the Galois/Counter mode (GCM) detailed in
+ * NIST Special Publication 800-38D.
+ */
+public class GCMBlockCipher
+ implements AEADBlockCipher
+{
+ private static final int BLOCK_SIZE = 16;
+
+ // not final due to a compiler bug
+ private BlockCipher cipher;
+ private GCMMultiplier multiplier;
+ private GCMExponentiator exp;
+
+ // These fields are set by init and not modified by processing
+ private boolean forEncryption;
+ private int macSize;
+ private byte[] nonce;
+ private byte[] initialAssociatedText;
+ private byte[] H;
+ private byte[] J0;
+
+ // These fields are modified during processing
+ private byte[] bufBlock;
+ private byte[] macBlock;
+ private byte[] S, S_at, S_atPre;
+ private byte[] counter;
+ private int bufOff;
+ private long totalLength;
+ private byte[] atBlock;
+ private int atBlockPos;
+ private long atLength;
+ private long atLengthPre;
+
+ public GCMBlockCipher(BlockCipher c)
+ {
+ this(c, null);
+ }
+
+ public GCMBlockCipher(BlockCipher c, GCMMultiplier m)
+ {
+ if (c.getBlockSize() != BLOCK_SIZE)
+ {
+ throw new IllegalArgumentException(
+ "cipher required with a block size of " + BLOCK_SIZE + ".");
+ }
+
+ if (m == null)
+ {
+ // TODO Consider a static property specifying default multiplier
+ m = new Tables8kGCMMultiplier();
+ }
+
+ this.cipher = c;
+ this.multiplier = m;
+ }
+
+ public BlockCipher getUnderlyingCipher()
+ {
+ return cipher;
+ }
+
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName() + "/GCM";
+ }
+
+ /**
+ * NOTE: MAC sizes from 32 bits to 128 bits (must be a multiple of 8) are supported. The default is 128 bits.
+ * Sizes less than 96 are not recommended, but are supported for specialized applications.
+ */
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ this.forEncryption = forEncryption;
+ this.macBlock = null;
+
+ KeyParameter keyParam;
+
+ if (params instanceof AEADParameters)
+ {
+ AEADParameters param = (AEADParameters)params;
+
+ nonce = param.getNonce();
+ initialAssociatedText = param.getAssociatedText();
+
+ int macSizeBits = param.getMacSize();
+ if (macSizeBits < 32 || macSizeBits > 128 || macSizeBits % 8 != 0)
+ {
+ throw new IllegalArgumentException("Invalid value for MAC size: " + macSizeBits);
+ }
+
+ macSize = macSizeBits / 8;
+ keyParam = param.getKey();
+ }
+ else if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV param = (ParametersWithIV)params;
+
+ nonce = param.getIV();
+ initialAssociatedText = null;
+ macSize = 16;
+ keyParam = (KeyParameter)param.getParameters();
+ }
+ else
+ {
+ throw new IllegalArgumentException("invalid parameters passed to GCM");
+ }
+
+ int bufLength = forEncryption ? BLOCK_SIZE : (BLOCK_SIZE + macSize);
+ this.bufBlock = new byte[bufLength];
+
+ if (nonce == null || nonce.length < 1)
+ {
+ throw new IllegalArgumentException("IV must be at least 1 byte");
+ }
+
+ // TODO Restrict macSize to 16 if nonce length not 12?
+
+ // Cipher always used in forward mode
+ // if keyParam is null we're reusing the last key.
+ if (keyParam != null)
+ {
+ cipher.init(true, keyParam);
+
+ this.H = new byte[BLOCK_SIZE];
+ cipher.processBlock(H, 0, H, 0);
+
+ // GCMMultiplier tables don't change unless the key changes (and are expensive to init)
+ multiplier.init(H);
+ exp = null;
+ }
+ else if (this.H == null)
+ {
+ throw new IllegalArgumentException("Key must be specified in initial init");
+ }
+
+ this.J0 = new byte[BLOCK_SIZE];
+
+ if (nonce.length == 12)
+ {
+ System.arraycopy(nonce, 0, J0, 0, nonce.length);
+ this.J0[BLOCK_SIZE - 1] = 0x01;
+ }
+ else
+ {
+ gHASH(J0, nonce, nonce.length);
+ byte[] X = new byte[BLOCK_SIZE];
+ Pack.longToBigEndian((long)nonce.length * 8, X, 8);
+ gHASHBlock(J0, X);
+ }
+
+ this.S = new byte[BLOCK_SIZE];
+ this.S_at = new byte[BLOCK_SIZE];
+ this.S_atPre = new byte[BLOCK_SIZE];
+ this.atBlock = new byte[BLOCK_SIZE];
+ this.atBlockPos = 0;
+ this.atLength = 0;
+ this.atLengthPre = 0;
+ this.counter = Arrays.clone(J0);
+ this.bufOff = 0;
+ this.totalLength = 0;
+
+ if (initialAssociatedText != null)
+ {
+ processAADBytes(initialAssociatedText, 0, initialAssociatedText.length);
+ }
+ }
+
+ public byte[] getMac()
+ {
+ return Arrays.clone(macBlock);
+ }
+
+ public int getOutputSize(int len)
+ {
+ int totalData = len + bufOff;
+
+ if (forEncryption)
+ {
+ return totalData + macSize;
+ }
+
+ return totalData < macSize ? 0 : totalData - macSize;
+ }
+
+ public int getUpdateOutputSize(int len)
+ {
+ int totalData = len + bufOff;
+ if (!forEncryption)
+ {
+ if (totalData < macSize)
+ {
+ return 0;
+ }
+ totalData -= macSize;
+ }
+ return totalData - totalData % BLOCK_SIZE;
+ }
+
+ public void processAADByte(byte in)
+ {
+ atBlock[atBlockPos] = in;
+ if (++atBlockPos == BLOCK_SIZE)
+ {
+ // Hash each block as it fills
+ gHASHBlock(S_at, atBlock);
+ atBlockPos = 0;
+ atLength += BLOCK_SIZE;
+ }
+ }
+
+ public void processAADBytes(byte[] in, int inOff, int len)
+ {
+ for (int i = 0; i < len; ++i)
+ {
+ atBlock[atBlockPos] = in[inOff + i];
+ if (++atBlockPos == BLOCK_SIZE)
+ {
+ // Hash each block as it fills
+ gHASHBlock(S_at, atBlock);
+ atBlockPos = 0;
+ atLength += BLOCK_SIZE;
+ }
+ }
+ }
+
+ private void initCipher()
+ {
+ if (atLength > 0)
+ {
+ System.arraycopy(S_at, 0, S_atPre, 0, BLOCK_SIZE);
+ atLengthPre = atLength;
+ }
+
+ // Finish hash for partial AAD block
+ if (atBlockPos > 0)
+ {
+ gHASHPartial(S_atPre, atBlock, 0, atBlockPos);
+ atLengthPre += atBlockPos;
+ }
+
+ if (atLengthPre > 0)
+ {
+ System.arraycopy(S_atPre, 0, S, 0, BLOCK_SIZE);
+ }
+ }
+
+ public int processByte(byte in, byte[] out, int outOff)
+ throws DataLengthException
+ {
+ bufBlock[bufOff] = in;
+ if (++bufOff == bufBlock.length)
+ {
+ outputBlock(out, outOff);
+ return BLOCK_SIZE;
+ }
+ return 0;
+ }
+
+ public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
+ throws DataLengthException
+ {
+ if (in.length < (inOff + len))
+ {
+ throw new DataLengthException("Input buffer too short");
+ }
+ int resultLen = 0;
+
+ for (int i = 0; i < len; ++i)
+ {
+ bufBlock[bufOff] = in[inOff + i];
+ if (++bufOff == bufBlock.length)
+ {
+ outputBlock(out, outOff + resultLen);
+ resultLen += BLOCK_SIZE;
+ }
+ }
+
+ return resultLen;
+ }
+
+ private void outputBlock(byte[] output, int offset)
+ {
+ if (output.length < (offset + BLOCK_SIZE))
+ {
+ throw new OutputLengthException("Output buffer too short");
+ }
+ if (totalLength == 0)
+ {
+ initCipher();
+ }
+ gCTRBlock(bufBlock, output, offset);
+ if (forEncryption)
+ {
+ bufOff = 0;
+ }
+ else
+ {
+ System.arraycopy(bufBlock, BLOCK_SIZE, bufBlock, 0, macSize);
+ bufOff = macSize;
+ }
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ throws IllegalStateException, InvalidCipherTextException
+ {
+ if (totalLength == 0)
+ {
+ initCipher();
+ }
+
+ int extra = bufOff;
+ if (!forEncryption)
+ {
+ if (extra < macSize)
+ {
+ throw new InvalidCipherTextException("data too short");
+ }
+ extra -= macSize;
+ }
+
+ if (extra > 0)
+ {
+ if (out.length < (outOff + extra))
+ {
+ throw new OutputLengthException("Output buffer too short");
+ }
+ gCTRPartial(bufBlock, 0, extra, out, outOff);
+ }
+
+ atLength += atBlockPos;
+
+ if (atLength > atLengthPre)
+ {
+ /*
+ * Some AAD was sent after the cipher started. We determine the difference b/w the hash value
+ * we actually used when the cipher started (S_atPre) and the final hash value calculated (S_at).
+ * Then we carry this difference forward by multiplying by H^c, where c is the number of (full or
+ * partial) cipher-text blocks produced, and adjust the current hash.
+ */
+
+ // Finish hash for partial AAD block
+ if (atBlockPos > 0)
+ {
+ gHASHPartial(S_at, atBlock, 0, atBlockPos);
+ }
+
+ // Find the difference between the AAD hashes
+ if (atLengthPre > 0)
+ {
+ xor(S_at, S_atPre);
+ }
+
+ // Number of cipher-text blocks produced
+ long c = ((totalLength * 8) + 127) >>> 7;
+
+ // Calculate the adjustment factor
+ byte[] H_c = new byte[16];
+ if (exp == null)
+ {
+ exp = new Tables1kGCMExponentiator();
+ exp.init(H);
+ }
+ exp.exponentiateX(c, H_c);
+
+ // Carry the difference forward
+ multiply(S_at, H_c);
+
+ // Adjust the current hash
+ xor(S, S_at);
+ }
+
+ // Final gHASH
+ byte[] X = new byte[BLOCK_SIZE];
+ Pack.longToBigEndian(atLength * 8, X, 0);
+ Pack.longToBigEndian(totalLength * 8, X, 8);
+
+ gHASHBlock(S, X);
+
+ // T = MSBt(GCTRk(J0,S))
+ byte[] tag = new byte[BLOCK_SIZE];
+ cipher.processBlock(J0, 0, tag, 0);
+ xor(tag, S);
+
+ int resultLen = extra;
+
+ // We place into macBlock our calculated value for T
+ this.macBlock = new byte[macSize];
+ System.arraycopy(tag, 0, macBlock, 0, macSize);
+
+ if (forEncryption)
+ {
+ if (out.length < (outOff + extra + macSize))
+ {
+ throw new OutputLengthException("Output buffer too short");
+ }
+ // Append T to the message
+ System.arraycopy(macBlock, 0, out, outOff + bufOff, macSize);
+ resultLen += macSize;
+ }
+ else
+ {
+ // Retrieve the T value from the message and compare to calculated one
+ byte[] msgMac = new byte[macSize];
+ System.arraycopy(bufBlock, extra, msgMac, 0, macSize);
+ if (!Arrays.constantTimeAreEqual(this.macBlock, msgMac))
+ {
+ throw new InvalidCipherTextException("mac check in GCM failed");
+ }
+ }
+
+ reset(false);
+
+ return resultLen;
+ }
+
+ public void reset()
+ {
+ reset(true);
+ }
+
+ private void reset(
+ boolean clearMac)
+ {
+ cipher.reset();
+
+ S = new byte[BLOCK_SIZE];
+ S_at = new byte[BLOCK_SIZE];
+ S_atPre = new byte[BLOCK_SIZE];
+ atBlock = new byte[BLOCK_SIZE];
+ atBlockPos = 0;
+ atLength = 0;
+ atLengthPre = 0;
+ counter = Arrays.clone(J0);
+ bufOff = 0;
+ totalLength = 0;
+
+ if (bufBlock != null)
+ {
+ Arrays.fill(bufBlock, (byte)0);
+ }
+
+ if (clearMac)
+ {
+ macBlock = null;
+ }
+
+ if (initialAssociatedText != null)
+ {
+ processAADBytes(initialAssociatedText, 0, initialAssociatedText.length);
+ }
+ }
+
+ private void gCTRBlock(byte[] block, byte[] out, int outOff)
+ {
+ byte[] tmp = getNextCounterBlock();
+
+ xor(tmp, block);
+ System.arraycopy(tmp, 0, out, outOff, BLOCK_SIZE);
+
+ gHASHBlock(S, forEncryption ? tmp : block);
+
+ totalLength += BLOCK_SIZE;
+ }
+
+ private void gCTRPartial(byte[] buf, int off, int len, byte[] out, int outOff)
+ {
+ byte[] tmp = getNextCounterBlock();
+
+ xor(tmp, buf, off, len);
+ System.arraycopy(tmp, 0, out, outOff, len);
+
+ gHASHPartial(S, forEncryption ? tmp : buf, 0, len);
+
+ totalLength += len;
+ }
+
+ private void gHASH(byte[] Y, byte[] b, int len)
+ {
+ for (int pos = 0; pos < len; pos += BLOCK_SIZE)
+ {
+ int num = Math.min(len - pos, BLOCK_SIZE);
+ gHASHPartial(Y, b, pos, num);
+ }
+ }
+
+ private void gHASHBlock(byte[] Y, byte[] b)
+ {
+ xor(Y, b);
+ multiplier.multiplyH(Y);
+ }
+
+ private void gHASHPartial(byte[] Y, byte[] b, int off, int len)
+ {
+ xor(Y, b, off, len);
+ multiplier.multiplyH(Y);
+ }
+
+ private byte[] getNextCounterBlock()
+ {
+ for (int i = 15; i >= 12; --i)
+ {
+ byte b = (byte)((counter[i] + 1) & 0xff);
+ counter[i] = b;
+
+ if (b != 0)
+ {
+ break;
+ }
+ }
+
+ byte[] tmp = new byte[BLOCK_SIZE];
+ // TODO Sure would be nice if ciphers could operate on int[]
+ cipher.processBlock(counter, 0, tmp, 0);
+ return tmp;
+ }
+
+ private static void multiply(byte[] block, byte[] val)
+ {
+ byte[] tmp = Arrays.clone(block);
+ byte[] c = new byte[16];
+
+ for (int i = 0; i < 16; ++i)
+ {
+ byte bits = val[i];
+ for (int j = 7; j >= 0; --j)
+ {
+ if ((bits & (1 << j)) != 0)
+ {
+ xor(c, tmp);
+ }
+
+ boolean lsb = (tmp[15] & 1) != 0;
+ shiftRight(tmp);
+ if (lsb)
+ {
+ // R = new byte[]{ 0xe1, ... };
+// xor(v, R);
+ tmp[0] ^= (byte)0xe1;
+ }
+ }
+ }
+
+ System.arraycopy(c, 0, block, 0, 16);
+ }
+
+ private static void shiftRight(byte[] block)
+ {
+ int i = 0;
+ int bit = 0;
+ for (;;)
+ {
+ int b = block[i] & 0xff;
+ block[i] = (byte) ((b >>> 1) | bit);
+ if (++i == 16)
+ {
+ break;
+ }
+ bit = (b & 1) << 7;
+ }
+ }
+
+ private static void xor(byte[] block, byte[] val)
+ {
+ for (int i = 15; i >= 0; --i)
+ {
+ block[i] ^= val[i];
+ }
+ }
+
+ private static void xor(byte[] block, byte[] val, int off, int len)
+ {
+ while (len-- > 0)
+ {
+ block[len] ^= val[off + len];
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/modes/GOFBBlockCipher.java b/core/src/main/java/org/spongycastle/crypto/modes/GOFBBlockCipher.java
new file mode 100644
index 00000000..c982e230
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/GOFBBlockCipher.java
@@ -0,0 +1,228 @@
+package org.spongycastle.crypto.modes;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.StreamBlockCipher;
+import org.spongycastle.crypto.params.ParametersWithIV;
+
+/**
+ * implements the GOST 28147 OFB counter mode (GCTR).
+ */
+public class GOFBBlockCipher
+ extends StreamBlockCipher
+{
+ private byte[] IV;
+ private byte[] ofbV;
+ private byte[] ofbOutV;
+ private int byteCount;
+
+ private final int blockSize;
+ private final BlockCipher cipher;
+
+ boolean firstStep = true;
+ int N3;
+ int N4;
+ static final int C1 = 16843012; //00000001000000010000000100000100
+ static final int C2 = 16843009; //00000001000000010000000100000001
+
+
+ /**
+ * Basic constructor.
+ *
+ * @param cipher the block cipher to be used as the basis of the
+ * counter mode (must have a 64 bit block size).
+ */
+ public GOFBBlockCipher(
+ BlockCipher cipher)
+ {
+ super(cipher);
+
+ this.cipher = cipher;
+ this.blockSize = cipher.getBlockSize();
+
+ if (blockSize != 8)
+ {
+ throw new IllegalArgumentException("GCTR only for 64 bit block ciphers");
+ }
+
+ this.IV = new byte[cipher.getBlockSize()];
+ this.ofbV = new byte[cipher.getBlockSize()];
+ this.ofbOutV = new byte[cipher.getBlockSize()];
+ }
+
+ /**
+ * Initialise the cipher and, possibly, the initialisation vector (IV).
+ * If an IV isn't passed as part of the parameter, the IV will be all zeros.
+ * An IV which is too short is handled in FIPS compliant fashion.
+ *
+ * @param encrypting if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting, //ignored by this CTR mode
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ firstStep = true;
+ N3 = 0;
+ N4 = 0;
+
+ if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV ivParam = (ParametersWithIV)params;
+ byte[] iv = ivParam.getIV();
+
+ if (iv.length < IV.length)
+ {
+ // prepend the supplied IV with zeros (per FIPS PUB 81)
+ System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
+ for (int i = 0; i < IV.length - iv.length; i++)
+ {
+ IV[i] = 0;
+ }
+ }
+ else
+ {
+ System.arraycopy(iv, 0, IV, 0, IV.length);
+ }
+
+ reset();
+
+ // if params is null we reuse the current working key.
+ if (ivParam.getParameters() != null)
+ {
+ cipher.init(true, ivParam.getParameters());
+ }
+ }
+ else
+ {
+ reset();
+
+ // if params is null we reuse the current working key.
+ if (params != null)
+ {
+ cipher.init(true, params);
+ }
+ }
+ }
+
+ /**
+ * return the algorithm name and mode.
+ *
+ * @return the name of the underlying algorithm followed by "/GCTR"
+ * and the block size in bits
+ */
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName() + "/GCTR";
+ }
+
+ /**
+ * return the block size we are operating at (in bytes).
+ *
+ * @return the block size we are operating at (in bytes).
+ */
+ public int getBlockSize()
+ {
+ return blockSize;
+ }
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ processBytes(in, inOff, blockSize, out, outOff);
+
+ return blockSize;
+ }
+
+ /**
+ * reset the feedback vector back to the IV and reset the underlying
+ * cipher.
+ */
+ public void reset()
+ {
+ firstStep = true;
+ N3 = 0;
+ N4 = 0;
+ System.arraycopy(IV, 0, ofbV, 0, IV.length);
+ byteCount = 0;
+ cipher.reset();
+ }
+
+ //array of bytes to type int
+ private int bytesToint(
+ byte[] in,
+ int inOff)
+ {
+ return ((in[inOff + 3] << 24) & 0xff000000) + ((in[inOff + 2] << 16) & 0xff0000) +
+ ((in[inOff + 1] << 8) & 0xff00) + (in[inOff] & 0xff);
+ }
+
+ //int to array of bytes
+ private void intTobytes(
+ int num,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff + 3] = (byte)(num >>> 24);
+ out[outOff + 2] = (byte)(num >>> 16);
+ out[outOff + 1] = (byte)(num >>> 8);
+ out[outOff] = (byte)num;
+ }
+
+ protected byte calculateByte(byte b)
+ {
+ if (byteCount == 0)
+ {
+ if (firstStep)
+ {
+ firstStep = false;
+ cipher.processBlock(ofbV, 0, ofbOutV, 0);
+ N3 = bytesToint(ofbOutV, 0);
+ N4 = bytesToint(ofbOutV, 4);
+ }
+ N3 += C2;
+ N4 += C1;
+ intTobytes(N3, ofbV, 0);
+ intTobytes(N4, ofbV, 4);
+
+ cipher.processBlock(ofbV, 0, ofbOutV, 0);
+ }
+
+ byte rv = (byte)(ofbOutV[byteCount++] ^ b);
+
+ if (byteCount == blockSize)
+ {
+ byteCount = 0;
+
+ //
+ // change over the input block.
+ //
+ System.arraycopy(ofbV, blockSize, ofbV, 0, ofbV.length - blockSize);
+ System.arraycopy(ofbOutV, 0, ofbV, ofbV.length - blockSize, blockSize);
+ }
+
+ return rv;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/modes/OCBBlockCipher.java b/core/src/main/java/org/spongycastle/crypto/modes/OCBBlockCipher.java
new file mode 100644
index 00000000..eb348eab
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/OCBBlockCipher.java
@@ -0,0 +1,598 @@
+package org.spongycastle.crypto.modes;
+
+import java.util.Vector;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.AEADParameters;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Arrays;
+
+/**
+ * An implementation of <a href="http://tools.ietf.org/html/rfc7253">RFC 7253 on The OCB
+ * Authenticated-Encryption Algorithm</a>, licensed per:
+ * <p>
+ * <blockquote> <a href="http://www.cs.ucdavis.edu/~rogaway/ocb/license1.pdf">License for
+ * Open-Source Software Implementations of OCB</a> (Jan 9, 2013) &mdash; &ldquo;License 1&rdquo; <br>
+ * Under this license, you are authorized to make, use, and distribute open-source software
+ * implementations of OCB. This license terminates for you if you sue someone over their open-source
+ * software implementation of OCB claiming that you have a patent covering their implementation.
+ * <p>
+ * This is a non-binding summary of a legal document (the link above). The parameters of the license
+ * are specified in the license document and that document is controlling. </blockquote>
+ */
+public class OCBBlockCipher
+ implements AEADBlockCipher
+{
+ private static final int BLOCK_SIZE = 16;
+
+ private BlockCipher hashCipher;
+ private BlockCipher mainCipher;
+
+ /*
+ * CONFIGURATION
+ */
+ private boolean forEncryption;
+ private int macSize;
+ private byte[] initialAssociatedText;
+
+ /*
+ * KEY-DEPENDENT
+ */
+ // NOTE: elements are lazily calculated
+ private Vector L;
+ private byte[] L_Asterisk, L_Dollar;
+
+ /*
+ * NONCE-DEPENDENT
+ */
+ private byte[] KtopInput = null;
+ private byte[] Stretch = new byte[24];
+ private byte[] OffsetMAIN_0 = new byte[16];
+
+ /*
+ * PER-ENCRYPTION/DECRYPTION
+ */
+ private byte[] hashBlock, mainBlock;
+ private int hashBlockPos, mainBlockPos;
+ private long hashBlockCount, mainBlockCount;
+ private byte[] OffsetHASH;
+ private byte[] Sum;
+ private byte[] OffsetMAIN = new byte[16];
+ private byte[] Checksum;
+
+ // NOTE: The MAC value is preserved after doFinal
+ private byte[] macBlock;
+
+ public OCBBlockCipher(BlockCipher hashCipher, BlockCipher mainCipher)
+ {
+ if (hashCipher == null)
+ {
+ throw new IllegalArgumentException("'hashCipher' cannot be null");
+ }
+ if (hashCipher.getBlockSize() != BLOCK_SIZE)
+ {
+ throw new IllegalArgumentException("'hashCipher' must have a block size of "
+ + BLOCK_SIZE);
+ }
+ if (mainCipher == null)
+ {
+ throw new IllegalArgumentException("'mainCipher' cannot be null");
+ }
+ if (mainCipher.getBlockSize() != BLOCK_SIZE)
+ {
+ throw new IllegalArgumentException("'mainCipher' must have a block size of "
+ + BLOCK_SIZE);
+ }
+
+ if (!hashCipher.getAlgorithmName().equals(mainCipher.getAlgorithmName()))
+ {
+ throw new IllegalArgumentException(
+ "'hashCipher' and 'mainCipher' must be the same algorithm");
+ }
+
+ this.hashCipher = hashCipher;
+ this.mainCipher = mainCipher;
+ }
+
+ public BlockCipher getUnderlyingCipher()
+ {
+ return mainCipher;
+ }
+
+ public String getAlgorithmName()
+ {
+ return mainCipher.getAlgorithmName() + "/OCB";
+ }
+
+ public void init(boolean forEncryption, CipherParameters parameters)
+ throws IllegalArgumentException
+ {
+ boolean oldForEncryption = this.forEncryption;
+ this.forEncryption = forEncryption;
+ this.macBlock = null;
+
+ KeyParameter keyParameter;
+
+ byte[] N;
+ if (parameters instanceof AEADParameters)
+ {
+ AEADParameters aeadParameters = (AEADParameters)parameters;
+
+ N = aeadParameters.getNonce();
+ initialAssociatedText = aeadParameters.getAssociatedText();
+
+ int macSizeBits = aeadParameters.getMacSize();
+ if (macSizeBits < 64 || macSizeBits > 128 || macSizeBits % 8 != 0)
+ {
+ throw new IllegalArgumentException("Invalid value for MAC size: " + macSizeBits);
+ }
+
+ macSize = macSizeBits / 8;
+ keyParameter = aeadParameters.getKey();
+ }
+ else if (parameters instanceof ParametersWithIV)
+ {
+ ParametersWithIV parametersWithIV = (ParametersWithIV)parameters;
+
+ N = parametersWithIV.getIV();
+ initialAssociatedText = null;
+ macSize = 16;
+ keyParameter = (KeyParameter)parametersWithIV.getParameters();
+ }
+ else
+ {
+ throw new IllegalArgumentException("invalid parameters passed to OCB");
+ }
+
+ this.hashBlock = new byte[16];
+ this.mainBlock = new byte[forEncryption ? BLOCK_SIZE : (BLOCK_SIZE + macSize)];
+
+ if (N == null)
+ {
+ N = new byte[0];
+ }
+
+ if (N.length > 15)
+ {
+ throw new IllegalArgumentException("IV must be no more than 15 bytes");
+ }
+
+ /*
+ * KEY-DEPENDENT INITIALISATION
+ */
+
+ if (keyParameter != null)
+ {
+ // hashCipher always used in forward mode
+ hashCipher.init(true, keyParameter);
+ mainCipher.init(forEncryption, keyParameter);
+ KtopInput = null;
+ }
+ else if (oldForEncryption != forEncryption)
+ {
+ throw new IllegalArgumentException("cannot change encrypting state without providing key.");
+ }
+
+ this.L_Asterisk = new byte[16];
+ hashCipher.processBlock(L_Asterisk, 0, L_Asterisk, 0);
+
+ this.L_Dollar = OCB_double(L_Asterisk);
+
+ this.L = new Vector();
+ this.L.addElement(OCB_double(L_Dollar));
+
+ /*
+ * NONCE-DEPENDENT AND PER-ENCRYPTION/DECRYPTION INITIALISATION
+ */
+
+ int bottom = processNonce(N);
+
+ int bits = bottom % 8, bytes = bottom / 8;
+ if (bits == 0)
+ {
+ System.arraycopy(Stretch, bytes, OffsetMAIN_0, 0, 16);
+ }
+ else
+ {
+ for (int i = 0; i < 16; ++i)
+ {
+ int b1 = Stretch[bytes] & 0xff;
+ int b2 = Stretch[++bytes] & 0xff;
+ this.OffsetMAIN_0[i] = (byte)((b1 << bits) | (b2 >>> (8 - bits)));
+ }
+ }
+
+ this.hashBlockPos = 0;
+ this.mainBlockPos = 0;
+
+ this.hashBlockCount = 0;
+ this.mainBlockCount = 0;
+
+ this.OffsetHASH = new byte[16];
+ this.Sum = new byte[16];
+ System.arraycopy(this.OffsetMAIN_0, 0, this.OffsetMAIN, 0, 16);
+ this.Checksum = new byte[16];
+
+ if (initialAssociatedText != null)
+ {
+ processAADBytes(initialAssociatedText, 0, initialAssociatedText.length);
+ }
+ }
+
+ protected int processNonce(byte[] N)
+ {
+ byte[] nonce = new byte[16];
+ System.arraycopy(N, 0, nonce, nonce.length - N.length, N.length);
+ nonce[0] = (byte)(macSize << 4);
+ nonce[15 - N.length] |= 1;
+
+ int bottom = nonce[15] & 0x3F;
+ nonce[15] &= 0xC0;
+
+ /*
+ * When used with incrementing nonces, the cipher is only applied once every 64 inits.
+ */
+ if (KtopInput == null || !Arrays.areEqual(nonce, KtopInput))
+ {
+ byte[] Ktop = new byte[16];
+ KtopInput = nonce;
+ hashCipher.processBlock(KtopInput, 0, Ktop, 0);
+ System.arraycopy(Ktop, 0, Stretch, 0, 16);
+ for (int i = 0; i < 8; ++i)
+ {
+ Stretch[16 + i] = (byte)(Ktop[i] ^ Ktop[i + 1]);
+ }
+ }
+
+ return bottom;
+ }
+
+ public byte[] getMac()
+ {
+ return Arrays.clone(macBlock);
+ }
+
+ public int getOutputSize(int len)
+ {
+ int totalData = len + mainBlockPos;
+ if (forEncryption)
+ {
+ return totalData + macSize;
+ }
+ return totalData < macSize ? 0 : totalData - macSize;
+ }
+
+ public int getUpdateOutputSize(int len)
+ {
+ int totalData = len + mainBlockPos;
+ if (!forEncryption)
+ {
+ if (totalData < macSize)
+ {
+ return 0;
+ }
+ totalData -= macSize;
+ }
+ return totalData - totalData % BLOCK_SIZE;
+ }
+
+ public void processAADByte(byte input)
+ {
+ hashBlock[hashBlockPos] = input;
+ if (++hashBlockPos == hashBlock.length)
+ {
+ processHashBlock();
+ }
+ }
+
+ public void processAADBytes(byte[] input, int off, int len)
+ {
+ for (int i = 0; i < len; ++i)
+ {
+ hashBlock[hashBlockPos] = input[off + i];
+ if (++hashBlockPos == hashBlock.length)
+ {
+ processHashBlock();
+ }
+ }
+ }
+
+ public int processByte(byte input, byte[] output, int outOff)
+ throws DataLengthException
+ {
+ mainBlock[mainBlockPos] = input;
+ if (++mainBlockPos == mainBlock.length)
+ {
+ processMainBlock(output, outOff);
+ return BLOCK_SIZE;
+ }
+ return 0;
+ }
+
+ public int processBytes(byte[] input, int inOff, int len, byte[] output, int outOff)
+ throws DataLengthException
+ {
+ if (input.length < (inOff + len))
+ {
+ throw new DataLengthException("Input buffer too short");
+ }
+ int resultLen = 0;
+
+ for (int i = 0; i < len; ++i)
+ {
+ mainBlock[mainBlockPos] = input[inOff + i];
+ if (++mainBlockPos == mainBlock.length)
+ {
+ processMainBlock(output, outOff + resultLen);
+ resultLen += BLOCK_SIZE;
+ }
+ }
+
+ return resultLen;
+ }
+
+ public int doFinal(byte[] output, int outOff)
+ throws IllegalStateException,
+ InvalidCipherTextException
+ {
+ /*
+ * For decryption, get the tag from the end of the message
+ */
+ byte[] tag = null;
+ if (!forEncryption)
+ {
+ if (mainBlockPos < macSize)
+ {
+ throw new InvalidCipherTextException("data too short");
+ }
+ mainBlockPos -= macSize;
+ tag = new byte[macSize];
+ System.arraycopy(mainBlock, mainBlockPos, tag, 0, macSize);
+ }
+
+ /*
+ * HASH: Process any final partial block; compute final hash value
+ */
+ if (hashBlockPos > 0)
+ {
+ OCB_extend(hashBlock, hashBlockPos);
+ updateHASH(L_Asterisk);
+ }
+
+ /*
+ * OCB-ENCRYPT/OCB-DECRYPT: Process any final partial block
+ */
+ if (mainBlockPos > 0)
+ {
+ if (forEncryption)
+ {
+ OCB_extend(mainBlock, mainBlockPos);
+ xor(Checksum, mainBlock);
+ }
+
+ xor(OffsetMAIN, L_Asterisk);
+
+ byte[] Pad = new byte[16];
+ hashCipher.processBlock(OffsetMAIN, 0, Pad, 0);
+
+ xor(mainBlock, Pad);
+
+ if (output.length < (outOff + mainBlockPos))
+ {
+ throw new OutputLengthException("Output buffer too short");
+ }
+ System.arraycopy(mainBlock, 0, output, outOff, mainBlockPos);
+
+ if (!forEncryption)
+ {
+ OCB_extend(mainBlock, mainBlockPos);
+ xor(Checksum, mainBlock);
+ }
+ }
+
+ /*
+ * OCB-ENCRYPT/OCB-DECRYPT: Compute raw tag
+ */
+ xor(Checksum, OffsetMAIN);
+ xor(Checksum, L_Dollar);
+ hashCipher.processBlock(Checksum, 0, Checksum, 0);
+ xor(Checksum, Sum);
+
+ this.macBlock = new byte[macSize];
+ System.arraycopy(Checksum, 0, macBlock, 0, macSize);
+
+ /*
+ * Validate or append tag and reset this cipher for the next run
+ */
+ int resultLen = mainBlockPos;
+
+ if (forEncryption)
+ {
+ if (output.length < (outOff + resultLen + macSize))
+ {
+ throw new OutputLengthException("Output buffer too short");
+ }
+ // Append tag to the message
+ System.arraycopy(macBlock, 0, output, outOff + resultLen, macSize);
+ resultLen += macSize;
+ }
+ else
+ {
+ // Compare the tag from the message with the calculated one
+ if (!Arrays.constantTimeAreEqual(macBlock, tag))
+ {
+ throw new InvalidCipherTextException("mac check in OCB failed");
+ }
+ }
+
+ reset(false);
+
+ return resultLen;
+ }
+
+ public void reset()
+ {
+ reset(true);
+ }
+
+ protected void clear(byte[] bs)
+ {
+ if (bs != null)
+ {
+ Arrays.fill(bs, (byte)0);
+ }
+ }
+
+ protected byte[] getLSub(int n)
+ {
+ while (n >= L.size())
+ {
+ L.addElement(OCB_double((byte[])L.lastElement()));
+ }
+ return (byte[])L.elementAt(n);
+ }
+
+ protected void processHashBlock()
+ {
+ /*
+ * HASH: Process any whole blocks
+ */
+ updateHASH(getLSub(OCB_ntz(++hashBlockCount)));
+ hashBlockPos = 0;
+ }
+
+ protected void processMainBlock(byte[] output, int outOff)
+ {
+ if (output.length < (outOff + BLOCK_SIZE))
+ {
+ throw new OutputLengthException("Output buffer too short");
+ }
+
+ /*
+ * OCB-ENCRYPT/OCB-DECRYPT: Process any whole blocks
+ */
+
+ if (forEncryption)
+ {
+ xor(Checksum, mainBlock);
+ mainBlockPos = 0;
+ }
+
+ xor(OffsetMAIN, getLSub(OCB_ntz(++mainBlockCount)));
+
+ xor(mainBlock, OffsetMAIN);
+ mainCipher.processBlock(mainBlock, 0, mainBlock, 0);
+ xor(mainBlock, OffsetMAIN);
+
+ System.arraycopy(mainBlock, 0, output, outOff, 16);
+
+ if (!forEncryption)
+ {
+ xor(Checksum, mainBlock);
+ System.arraycopy(mainBlock, BLOCK_SIZE, mainBlock, 0, macSize);
+ mainBlockPos = macSize;
+ }
+ }
+
+ protected void reset(boolean clearMac)
+ {
+ hashCipher.reset();
+ mainCipher.reset();
+
+ clear(hashBlock);
+ clear(mainBlock);
+
+ hashBlockPos = 0;
+ mainBlockPos = 0;
+
+ hashBlockCount = 0;
+ mainBlockCount = 0;
+
+ clear(OffsetHASH);
+ clear(Sum);
+ System.arraycopy(OffsetMAIN_0, 0, OffsetMAIN, 0, 16);
+ clear(Checksum);
+
+ if (clearMac)
+ {
+ macBlock = null;
+ }
+
+ if (initialAssociatedText != null)
+ {
+ processAADBytes(initialAssociatedText, 0, initialAssociatedText.length);
+ }
+ }
+
+ protected void updateHASH(byte[] LSub)
+ {
+ xor(OffsetHASH, LSub);
+ xor(hashBlock, OffsetHASH);
+ hashCipher.processBlock(hashBlock, 0, hashBlock, 0);
+ xor(Sum, hashBlock);
+ }
+
+ protected static byte[] OCB_double(byte[] block)
+ {
+ byte[] result = new byte[16];
+ int carry = shiftLeft(block, result);
+
+ /*
+ * NOTE: This construction is an attempt at a constant-time implementation.
+ */
+ result[15] ^= (0x87 >>> ((1 - carry) << 3));
+
+ return result;
+ }
+
+ protected static void OCB_extend(byte[] block, int pos)
+ {
+ block[pos] = (byte)0x80;
+ while (++pos < 16)
+ {
+ block[pos] = 0;
+ }
+ }
+
+ protected static int OCB_ntz(long x)
+ {
+ if (x == 0)
+ {
+ return 64;
+ }
+
+ int n = 0;
+ while ((x & 1L) == 0L)
+ {
+ ++n;
+ x >>>= 1;
+ }
+ return n;
+ }
+
+ protected static int shiftLeft(byte[] block, byte[] output)
+ {
+ int i = 16;
+ int bit = 0;
+ while (--i >= 0)
+ {
+ int b = block[i] & 0xff;
+ output[i] = (byte)((b << 1) | bit);
+ bit = (b >>> 7) & 1;
+ }
+ return bit;
+ }
+
+ protected static void xor(byte[] block, byte[] val)
+ {
+ for (int i = 15; i >= 0; --i)
+ {
+ block[i] ^= val[i];
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/modes/OFBBlockCipher.java b/core/src/main/java/org/spongycastle/crypto/modes/OFBBlockCipher.java
new file mode 100644
index 00000000..629d2c1e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/OFBBlockCipher.java
@@ -0,0 +1,178 @@
+package org.spongycastle.crypto.modes;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.StreamBlockCipher;
+import org.spongycastle.crypto.params.ParametersWithIV;
+
+/**
+ * implements a Output-FeedBack (OFB) mode on top of a simple cipher.
+ */
+public class OFBBlockCipher
+ extends StreamBlockCipher
+{
+ private int byteCount;
+ private byte[] IV;
+ private byte[] ofbV;
+ private byte[] ofbOutV;
+
+ private final int blockSize;
+ private final BlockCipher cipher;
+
+ /**
+ * Basic constructor.
+ *
+ * @param cipher the block cipher to be used as the basis of the
+ * feedback mode.
+ * @param blockSize the block size in bits (note: a multiple of 8)
+ */
+ public OFBBlockCipher(
+ BlockCipher cipher,
+ int blockSize)
+ {
+ super(cipher);
+
+ this.cipher = cipher;
+ this.blockSize = blockSize / 8;
+
+ this.IV = new byte[cipher.getBlockSize()];
+ this.ofbV = new byte[cipher.getBlockSize()];
+ this.ofbOutV = new byte[cipher.getBlockSize()];
+ }
+
+ /**
+ * Initialise the cipher and, possibly, the initialisation vector (IV).
+ * If an IV isn't passed as part of the parameter, the IV will be all zeros.
+ * An IV which is too short is handled in FIPS compliant fashion.
+ *
+ * @param encrypting if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting, //ignored by this OFB mode
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV ivParam = (ParametersWithIV)params;
+ byte[] iv = ivParam.getIV();
+
+ if (iv.length < IV.length)
+ {
+ // prepend the supplied IV with zeros (per FIPS PUB 81)
+ System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
+ for (int i = 0; i < IV.length - iv.length; i++)
+ {
+ IV[i] = 0;
+ }
+ }
+ else
+ {
+ System.arraycopy(iv, 0, IV, 0, IV.length);
+ }
+
+ reset();
+
+ // if null it's an IV changed only.
+ if (ivParam.getParameters() != null)
+ {
+ cipher.init(true, ivParam.getParameters());
+ }
+ }
+ else
+ {
+ reset();
+
+ // if it's null, key is to be reused.
+ if (params != null)
+ {
+ cipher.init(true, params);
+ }
+ }
+ }
+
+ /**
+ * return the algorithm name and mode.
+ *
+ * @return the name of the underlying algorithm followed by "/OFB"
+ * and the block size in bits
+ */
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName() + "/OFB" + (blockSize * 8);
+ }
+
+
+ /**
+ * return the block size we are operating at (in bytes).
+ *
+ * @return the block size we are operating at (in bytes).
+ */
+ public int getBlockSize()
+ {
+ return blockSize;
+ }
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ processBytes(in, inOff, blockSize, out, outOff);
+
+ return blockSize;
+ }
+
+ /**
+ * reset the feedback vector back to the IV and reset the underlying
+ * cipher.
+ */
+ public void reset()
+ {
+ System.arraycopy(IV, 0, ofbV, 0, IV.length);
+ byteCount = 0;
+
+ cipher.reset();
+ }
+
+ protected byte calculateByte(byte in)
+ throws DataLengthException, IllegalStateException
+ {
+ if (byteCount == 0)
+ {
+ cipher.processBlock(ofbV, 0, ofbOutV, 0);
+ }
+
+ byte rv = (byte)(ofbOutV[byteCount++] ^ in);
+
+ if (byteCount == blockSize)
+ {
+ byteCount = 0;
+
+ System.arraycopy(ofbV, blockSize, ofbV, 0, ofbV.length - blockSize);
+ System.arraycopy(ofbOutV, 0, ofbV, ofbV.length - blockSize, blockSize);
+ }
+
+ return rv;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/modes/OldCTSBlockCipher.java b/core/src/main/java/org/spongycastle/crypto/modes/OldCTSBlockCipher.java
new file mode 100644
index 00000000..30402b55
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/OldCTSBlockCipher.java
@@ -0,0 +1,269 @@
+package org.spongycastle.crypto.modes;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.BufferedBlockCipher;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.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.spongycastle.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.spongycastle.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.spongycastle.crypto.DataLengthException if there is insufficient space in out for
+ * the output.
+ * @exception IllegalStateException if the underlying cipher is not
+ * initialised.
+ * @exception org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/modes/OpenPGPCFBBlockCipher.java b/core/src/main/java/org/spongycastle/crypto/modes/OpenPGPCFBBlockCipher.java
new file mode 100644
index 00000000..0be996be
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/OpenPGPCFBBlockCipher.java
@@ -0,0 +1,312 @@
+package org.spongycastle.crypto.modes;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+
+/**
+ * Implements OpenPGP's rather strange version of Cipher-FeedBack (CFB) mode
+ * on top of a simple cipher. This class assumes the IV has been prepended
+ * to the data stream already, and just accomodates the reset after
+ * (blockSize + 2) bytes have been read.
+ * <p>
+ * For further info see <a href="http://www.ietf.org/rfc/rfc2440.html">RFC 2440</a>.
+ */
+public class OpenPGPCFBBlockCipher
+ implements BlockCipher
+{
+ private byte[] IV;
+ private byte[] FR;
+ private byte[] FRE;
+
+ private BlockCipher cipher;
+
+ private int count;
+ private int blockSize;
+ private boolean forEncryption;
+
+ /**
+ * Basic constructor.
+ *
+ * @param cipher the block cipher to be used as the basis of the
+ * feedback mode.
+ */
+ public OpenPGPCFBBlockCipher(
+ BlockCipher cipher)
+ {
+ this.cipher = cipher;
+
+ this.blockSize = cipher.getBlockSize();
+ this.IV = new byte[blockSize];
+ this.FR = new byte[blockSize];
+ this.FRE = new byte[blockSize];
+ }
+
+ /**
+ * return the underlying block cipher that we are wrapping.
+ *
+ * @return the underlying block cipher that we are wrapping.
+ */
+ public BlockCipher getUnderlyingCipher()
+ {
+ return cipher;
+ }
+
+ /**
+ * return the algorithm name and mode.
+ *
+ * @return the name of the underlying algorithm followed by "/PGPCFB"
+ * and the block size in bits.
+ */
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName() + "/OpenPGPCFB";
+ }
+
+ /**
+ * return the block size we are operating at.
+ *
+ * @return the block size we are operating at (in bytes).
+ */
+ public int getBlockSize()
+ {
+ return cipher.getBlockSize();
+ }
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ return (forEncryption) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff);
+ }
+
+ /**
+ * reset the chaining vector back to the IV and reset the underlying
+ * cipher.
+ */
+ public void reset()
+ {
+ count = 0;
+
+ System.arraycopy(IV, 0, FR, 0, FR.length);
+
+ cipher.reset();
+ }
+
+ /**
+ * Initialise the cipher and, possibly, the initialisation vector (IV).
+ * If an IV isn't passed as part of the parameter, the IV will be all zeros.
+ * An IV which is too short is handled in FIPS compliant fashion.
+ *
+ * @param forEncryption if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ this.forEncryption = forEncryption;
+
+ reset();
+
+ cipher.init(true, params);
+ }
+
+ /**
+ * Encrypt one byte of data according to CFB mode.
+ * @param data the byte to encrypt
+ * @param blockOff offset in the current block
+ * @return the encrypted byte
+ */
+ private byte encryptByte(byte data, int blockOff)
+ {
+ return (byte)(FRE[blockOff] ^ data);
+ }
+
+ /**
+ * Do the appropriate processing for CFB IV mode encryption.
+ *
+ * @param in the array containing the data to be encrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the encrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ private int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (count > blockSize)
+ {
+ FR[blockSize - 2] = out[outOff] = encryptByte(in[inOff], blockSize - 2);
+ FR[blockSize - 1] = out[outOff + 1] = encryptByte(in[inOff + 1], blockSize - 1);
+
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ for (int n = 2; n < blockSize; n++)
+ {
+ FR[n - 2] = out[outOff + n] = encryptByte(in[inOff + n], n - 2);
+ }
+ }
+ else if (count == 0)
+ {
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ for (int n = 0; n < blockSize; n++)
+ {
+ FR[n] = out[outOff + n] = encryptByte(in[inOff + n], n);
+ }
+
+ count += blockSize;
+ }
+ else if (count == blockSize)
+ {
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ out[outOff] = encryptByte(in[inOff], 0);
+ out[outOff + 1] = encryptByte(in[inOff + 1], 1);
+
+ //
+ // do reset
+ //
+ System.arraycopy(FR, 2, FR, 0, blockSize - 2);
+ System.arraycopy(out, outOff, FR, blockSize - 2, 2);
+
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ for (int n = 2; n < blockSize; n++)
+ {
+ FR[n - 2] = out[outOff + n] = encryptByte(in[inOff + n], n - 2);
+ }
+
+ count += blockSize;
+ }
+
+ return blockSize;
+ }
+
+ /**
+ * Do the appropriate processing for CFB IV mode decryption.
+ *
+ * @param in the array containing the data to be decrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the encrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ private int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (count > blockSize)
+ {
+ byte inVal = in[inOff];
+ FR[blockSize - 2] = inVal;
+ out[outOff] = encryptByte(inVal, blockSize - 2);
+
+ inVal = in[inOff + 1];
+ FR[blockSize - 1] = inVal;
+ out[outOff + 1] = encryptByte(inVal, blockSize - 1);
+
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ for (int n = 2; n < blockSize; n++)
+ {
+ inVal = in[inOff + n];
+ FR[n - 2] = inVal;
+ out[outOff + n] = encryptByte(inVal, n - 2);
+ }
+ }
+ else if (count == 0)
+ {
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ for (int n = 0; n < blockSize; n++)
+ {
+ FR[n] = in[inOff + n];
+ out[n] = encryptByte(in[inOff + n], n);
+ }
+
+ count += blockSize;
+ }
+ else if (count == blockSize)
+ {
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ byte inVal1 = in[inOff];
+ byte inVal2 = in[inOff + 1];
+ out[outOff ] = encryptByte(inVal1, 0);
+ out[outOff + 1] = encryptByte(inVal2, 1);
+
+ System.arraycopy(FR, 2, FR, 0, blockSize - 2);
+
+ FR[blockSize - 2] = inVal1;
+ FR[blockSize - 1] = inVal2;
+
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ for (int n = 2; n < blockSize; n++)
+ {
+ byte inVal = in[inOff + n];
+ FR[n - 2] = inVal;
+ out[outOff + n] = encryptByte(inVal, n - 2);
+ }
+
+ count += blockSize;
+ }
+
+ return blockSize;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/modes/PGPCFBBlockCipher.java b/core/src/main/java/org/spongycastle/crypto/modes/PGPCFBBlockCipher.java
new file mode 100644
index 00000000..370ce40d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/PGPCFBBlockCipher.java
@@ -0,0 +1,455 @@
+package org.spongycastle.crypto.modes;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.params.ParametersWithIV;
+
+/**
+ * Implements OpenPGP's rather strange version of Cipher-FeedBack (CFB) mode on top of a simple cipher. For further info see <a href="http://www.ietf.org/rfc/rfc2440.html">RFC 2440</a>.
+ */
+public class PGPCFBBlockCipher
+ implements BlockCipher
+{
+ private byte[] IV;
+ private byte[] FR;
+ private byte[] FRE;
+ private byte[] tmp;
+
+ private BlockCipher cipher;
+
+ private int count;
+ private int blockSize;
+ private boolean forEncryption;
+
+ private boolean inlineIv; // if false we don't need to prepend an IV
+
+ /**
+ * Basic constructor.
+ *
+ * @param cipher the block cipher to be used as the basis of the
+ * feedback mode.
+ * @param inlineIv if true this is for PGP CFB with a prepended iv.
+ */
+ public PGPCFBBlockCipher(
+ BlockCipher cipher,
+ boolean inlineIv)
+ {
+ this.cipher = cipher;
+ this.inlineIv = inlineIv;
+
+ this.blockSize = cipher.getBlockSize();
+ this.IV = new byte[blockSize];
+ this.FR = new byte[blockSize];
+ this.FRE = new byte[blockSize];
+ this.tmp = new byte[blockSize];
+ }
+
+ /**
+ * return the underlying block cipher that we are wrapping.
+ *
+ * @return the underlying block cipher that we are wrapping.
+ */
+ public BlockCipher getUnderlyingCipher()
+ {
+ return cipher;
+ }
+
+ /**
+ * return the algorithm name and mode.
+ *
+ * @return the name of the underlying algorithm followed by "/PGPCFB"
+ * and the block size in bits.
+ */
+ public String getAlgorithmName()
+ {
+ if (inlineIv)
+ {
+ return cipher.getAlgorithmName() + "/PGPCFBwithIV";
+ }
+ else
+ {
+ return cipher.getAlgorithmName() + "/PGPCFB";
+ }
+ }
+
+ /**
+ * return the block size we are operating at.
+ *
+ * @return the block size we are operating at (in bytes).
+ */
+ public int getBlockSize()
+ {
+ return cipher.getBlockSize();
+ }
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if (inlineIv)
+ {
+ return (forEncryption) ? encryptBlockWithIV(in, inOff, out, outOff) : decryptBlockWithIV(in, inOff, out, outOff);
+ }
+ else
+ {
+ return (forEncryption) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff);
+ }
+ }
+
+ /**
+ * reset the chaining vector back to the IV and reset the underlying
+ * cipher.
+ */
+ public void reset()
+ {
+ count = 0;
+
+ for (int i = 0; i != FR.length; i++)
+ {
+ if (inlineIv)
+ {
+ FR[i] = 0;
+ }
+ else
+ {
+ FR[i] = IV[i]; // if simple mode, key is IV (even if this is zero)
+ }
+ }
+
+ cipher.reset();
+ }
+
+ /**
+ * Initialise the cipher and, possibly, the initialisation vector (IV).
+ * If an IV isn't passed as part of the parameter, the IV will be all zeros.
+ * An IV which is too short is handled in FIPS compliant fashion.
+ *
+ * @param forEncryption if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ this.forEncryption = forEncryption;
+
+ if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV ivParam = (ParametersWithIV)params;
+ byte[] iv = ivParam.getIV();
+
+ if (iv.length < IV.length)
+ {
+ // prepend the supplied IV with zeros (per FIPS PUB 81)
+ System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
+ for (int i = 0; i < IV.length - iv.length; i++)
+ {
+ IV[i] = 0;
+ }
+ }
+ else
+ {
+ System.arraycopy(iv, 0, IV, 0, IV.length);
+ }
+
+ reset();
+
+ cipher.init(true, ivParam.getParameters());
+ }
+ else
+ {
+ reset();
+
+ cipher.init(true, params);
+ }
+ }
+
+ /**
+ * Encrypt one byte of data according to CFB mode.
+ * @param data the byte to encrypt
+ * @param blockOff where am i in the current block, determines when to resync the block
+ * @returns the encrypted byte
+ */
+ private byte encryptByte(byte data, int blockOff)
+ {
+ return (byte)(FRE[blockOff] ^ data);
+ }
+
+ /**
+ * Do the appropriate processing for CFB IV mode encryption.
+ *
+ * @param in the array containing the data to be encrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the encrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ private int encryptBlockWithIV(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input 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++)
+ {
+ out[outOff + n] = encryptByte(IV[n], n);
+ }
+
+ System.arraycopy(out, outOff, FR, 0, blockSize);
+
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ out[outOff + blockSize] = encryptByte(IV[blockSize - 2], 0);
+ out[outOff + blockSize + 1] = encryptByte(IV[blockSize - 1], 1);
+
+ System.arraycopy(out, outOff + 2, FR, 0, blockSize);
+
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ for (int n = 0; n < blockSize; n++)
+ {
+ out[outOff + blockSize + 2 + n] = encryptByte(in[inOff + n], n);
+ }
+
+ System.arraycopy(out, outOff + blockSize + 2, FR, 0, blockSize);
+
+ count += 2 * blockSize + 2;
+
+ return 2 * blockSize + 2;
+ }
+ 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++)
+ {
+ out[outOff + n] = encryptByte(in[inOff + n], n);
+ }
+
+ System.arraycopy(out, outOff, FR, 0, blockSize);
+ }
+
+ return blockSize;
+ }
+
+ /**
+ * Do the appropriate processing for CFB IV mode decryption.
+ *
+ * @param in the array containing the data to be decrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the encrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ private int decryptBlockWithIV(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (count == 0)
+ {
+ for (int n = 0; n < blockSize; n++)
+ {
+ FR[n] = in[inOff + n];
+ }
+
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ count += blockSize;
+
+ return 0;
+ }
+ else if (count == blockSize)
+ {
+ // copy in buffer so that this mode works if in and out are the same
+ System.arraycopy(in, inOff, tmp, 0, blockSize);
+
+ System.arraycopy(FR, 2, FR, 0, blockSize - 2);
+
+ FR[blockSize - 2] = tmp[0];
+ FR[blockSize - 1] = tmp[1];
+
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ for (int n = 0; n < blockSize - 2; n++)
+ {
+ out[outOff + n] = encryptByte(tmp[n + 2], n);
+ }
+
+ System.arraycopy(tmp, 2, FR, 0, blockSize - 2);
+
+ count += 2;
+
+ return blockSize - 2;
+ }
+ else if (count >= blockSize + 2)
+ {
+ // copy in buffer so that this mode works if in and out are the same
+ System.arraycopy(in, inOff, tmp, 0, blockSize);
+
+ out[outOff + 0] = encryptByte(tmp[0], blockSize - 2);
+ out[outOff + 1] = encryptByte(tmp[1], blockSize - 1);
+
+ System.arraycopy(tmp, 0, FR, blockSize - 2, 2);
+
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ for (int n = 0; n < blockSize - 2; n++)
+ {
+ out[outOff + n + 2] = encryptByte(tmp[n + 2], n);
+ }
+
+ System.arraycopy(tmp, 2, FR, 0, blockSize - 2);
+
+ }
+
+ return blockSize;
+ }
+
+ /**
+ * Do the appropriate processing for CFB mode encryption.
+ *
+ * @param in the array containing the data to be encrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the encrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ private int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ cipher.processBlock(FR, 0, FRE, 0);
+ for (int n = 0; n < blockSize; n++)
+ {
+ out[outOff + n] = encryptByte(in[inOff + n], n);
+ }
+
+ for (int n = 0; n < blockSize; n++)
+ {
+ FR[n] = out[outOff + n];
+ }
+
+ return blockSize;
+
+ }
+
+ /**
+ * Do the appropriate processing for CFB mode decryption.
+ *
+ * @param in the array containing the data to be decrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the encrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ private int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ cipher.processBlock(FR, 0, FRE, 0);
+ for (int n = 0; n < blockSize; n++)
+ {
+ out[outOff + n] = encryptByte(in[inOff + n], n);
+ }
+
+ for (int n = 0; n < blockSize; n++)
+ {
+ FR[n] = in[inOff + n];
+ }
+
+ return blockSize;
+
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/modes/PaddedBlockCipher.java b/core/src/main/java/org/spongycastle/crypto/modes/PaddedBlockCipher.java
new file mode 100644
index 00000000..23d6de74
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/PaddedBlockCipher.java
@@ -0,0 +1,253 @@
+package org.spongycastle.crypto.modes;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.BufferedBlockCipher;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A wrapper class that allows block ciphers to be used to process data in
+ * a piecemeal fashion with PKCS5/PKCS7 padding. The PaddedBlockCipher
+ * outputs a block only when the buffer is full and more data is being added,
+ * or on a doFinal (unless the current block in the buffer is a pad block).
+ * The padding mechanism used is the one outlined in PKCS5/PKCS7.
+ *
+ * @deprecated use org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher instead.
+ */
+public class PaddedBlockCipher
+ extends BufferedBlockCipher
+{
+ /**
+ * Create a buffered block cipher with, or without, padding.
+ *
+ * @param cipher the underlying block cipher this buffering object wraps.
+ */
+ public PaddedBlockCipher(
+ BlockCipher cipher)
+ {
+ this.cipher = cipher;
+
+ buf = new byte[cipher.getBlockSize()];
+ bufOff = 0;
+ }
+
+ /**
+ * 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)
+ {
+ int total = len + bufOff;
+ int leftOver = total % buf.length;
+
+ if (leftOver == 0)
+ {
+ if (forEncryption)
+ {
+ return total + buf.length;
+ }
+
+ return total;
+ }
+
+ return total - leftOver + buf.length;
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * process a single byte, producing an output block if neccessary.
+ *
+ * @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.
+ * @exception 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);
+ bufOff = 0;
+ }
+
+ 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.
+ * @exception 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);
+
+ bufOff = 0;
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > buf.length)
+ {
+ resultLen += cipher.processBlock(in, inOff, out, outOff + resultLen);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+
+ return resultLen;
+ }
+
+ /**
+ * Process the last block in the buffer. If the buffer is currently
+ * full and padding needs to be added a call to doFinal will produce
+ * 2 * getBlockSize() bytes.
+ *
+ * @param out the array the block currently being held is copied into.
+ * @param outOff the offset at which the copying starts.
+ * @exception DataLengthException if there is insufficient space in out for
+ * the output or we are decrypting and the input is not block size aligned.
+ * @exception IllegalStateException if the underlying cipher is not
+ * initialised.
+ * @exception InvalidCipherTextException if padding is expected and not found.
+ */
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException, InvalidCipherTextException
+ {
+ int blockSize = cipher.getBlockSize();
+ int resultLen = 0;
+
+ if (forEncryption)
+ {
+ if (bufOff == blockSize)
+ {
+ if ((outOff + 2 * blockSize) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ resultLen = cipher.processBlock(buf, 0, out, outOff);
+ bufOff = 0;
+ }
+
+ //
+ // add PKCS7 padding
+ //
+ byte code = (byte)(blockSize - bufOff);
+
+ while (bufOff < blockSize)
+ {
+ buf[bufOff] = code;
+ bufOff++;
+ }
+
+ resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen);
+ }
+ else
+ {
+ if (bufOff == blockSize)
+ {
+ resultLen = cipher.processBlock(buf, 0, buf, 0);
+ bufOff = 0;
+ }
+ else
+ {
+ throw new DataLengthException("last block incomplete in decryption");
+ }
+
+ //
+ // remove PKCS7 padding
+ //
+ int count = buf[blockSize - 1] & 0xff;
+
+ if ((count < 0) || (count > blockSize))
+ {
+ throw new InvalidCipherTextException("pad block corrupted");
+ }
+
+ resultLen -= count;
+
+ System.arraycopy(buf, 0, out, outOff, resultLen);
+ }
+
+ reset();
+
+ return resultLen;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/modes/SICBlockCipher.java b/core/src/main/java/org/spongycastle/crypto/modes/SICBlockCipher.java
new file mode 100644
index 00000000..8f6f9843
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/SICBlockCipher.java
@@ -0,0 +1,225 @@
+package org.spongycastle.crypto.modes;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.SkippingStreamCipher;
+import org.spongycastle.crypto.StreamBlockCipher;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Pack;
+
+/**
+ * Implements the Segmented Integer Counter (SIC) mode on top of a simple
+ * block cipher. This mode is also known as CTR mode.
+ */
+public class SICBlockCipher
+ extends StreamBlockCipher
+ implements SkippingStreamCipher
+{
+ private final BlockCipher cipher;
+ private final int blockSize;
+
+ private byte[] IV;
+ private byte[] counter;
+ private byte[] counterOut;
+ private int byteCount;
+
+ /**
+ * Basic constructor.
+ *
+ * @param c the block cipher to be used.
+ */
+ public SICBlockCipher(BlockCipher c)
+ {
+ super(c);
+
+ this.cipher = c;
+ this.blockSize = cipher.getBlockSize();
+ this.IV = new byte[blockSize];
+ this.counter = new byte[blockSize];
+ this.counterOut = new byte[blockSize];
+ this.byteCount = 0;
+ }
+
+ public void init(
+ boolean forEncryption, //ignored by this CTR mode
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV ivParam = (ParametersWithIV)params;
+ byte[] iv = ivParam.getIV();
+ System.arraycopy(iv, 0, IV, 0, IV.length);
+
+ // if null it's an IV changed only.
+ if (ivParam.getParameters() != null)
+ {
+ cipher.init(true, ivParam.getParameters());
+ }
+
+ reset();
+ }
+ else
+ {
+ throw new IllegalArgumentException("SIC mode requires ParametersWithIV");
+ }
+ }
+
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName() + "/SIC";
+ }
+
+ public int getBlockSize()
+ {
+ return cipher.getBlockSize();
+ }
+
+ public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ processBytes(in, inOff, blockSize, out, outOff);
+
+ return blockSize;
+ }
+
+ protected byte calculateByte(byte in)
+ throws DataLengthException, IllegalStateException
+ {
+ if (byteCount == 0)
+ {
+ cipher.processBlock(counter, 0, counterOut, 0);
+
+ return (byte)(counterOut[byteCount++] ^ in);
+ }
+
+ byte rv = (byte)(counterOut[byteCount++] ^ in);
+
+ if (byteCount == counter.length)
+ {
+ byteCount = 0;
+
+ incrementCounter();
+ }
+
+ return rv;
+ }
+
+ private void incrementCounter()
+ {
+ // increment counter by 1.
+ for (int i = counter.length - 1; i >= 0 && ++counter[i] == 0; i--)
+ {
+ ; // do nothing - pre-increment and test for 0 in counter does the job.
+ }
+ }
+
+ private void decrementCounter()
+ {
+ if (counter[0] == 0)
+ {
+ boolean nonZero = false;
+
+ for (int i = counter.length - 1; i > 0; i--)
+ {
+ if (counter[i] != 0)
+ {
+ nonZero = true;
+ }
+ }
+
+ if (!nonZero)
+ {
+ throw new IllegalStateException("attempt to reduce counter past zero.");
+ }
+ }
+
+ // decrement counter by 1.
+ for (int i = counter.length - 1; i >= 0 && --counter[i] == -1; i--)
+ {
+ ;
+ }
+ }
+
+ private void adjustCounter(long n)
+ {
+ if (n >= 0)
+ {
+ long numBlocks = (n + byteCount) / blockSize;
+
+ for (long i = 0; i != numBlocks; i++)
+ {
+ incrementCounter();
+ }
+
+ byteCount = (int)((n + byteCount) - (blockSize * numBlocks));
+ }
+ else
+ {
+ long numBlocks = (-n - byteCount) / blockSize;
+
+ for (long i = 0; i != numBlocks; i++)
+ {
+ decrementCounter();
+ }
+
+ int gap = (int)(byteCount + n + (blockSize * numBlocks));
+
+ if (gap >= 0)
+ {
+ byteCount = 0;
+ }
+ else
+ {
+ decrementCounter();
+ byteCount = blockSize + gap;
+ }
+ }
+ }
+
+ public void reset()
+ {
+ System.arraycopy(IV, 0, counter, 0, counter.length);
+ cipher.reset();
+ this.byteCount = 0;
+ }
+
+ public long skip(long numberOfBytes)
+ {
+ adjustCounter(numberOfBytes);
+
+ cipher.processBlock(counter, 0, counterOut, 0);
+
+ return numberOfBytes;
+ }
+
+ public long seekTo(long position)
+ {
+ reset();
+
+ return skip(position);
+ }
+
+ public long getPosition()
+ {
+ byte[] res = new byte[IV.length];
+
+ System.arraycopy(counter, 0, res, 0, res.length);
+
+ for (int i = res.length - 1; i >= 1; i--)
+ {
+ int v = (res[i] - IV[i]);
+
+ if (v < 0)
+ {
+ res[i - 1]--;
+ v += 256;
+ }
+
+ res[i] = (byte)v;
+ }
+
+ return Pack.bigEndianToLong(res, res.length - 8) * blockSize + byteCount;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/modes/gcm/BasicGCMExponentiator.java b/core/src/main/java/org/spongycastle/crypto/modes/gcm/BasicGCMExponentiator.java
new file mode 100644
index 00000000..b84fe6f0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/gcm/BasicGCMExponentiator.java
@@ -0,0 +1,36 @@
+package org.spongycastle.crypto.modes.gcm;
+
+import org.spongycastle.util.Arrays;
+
+public class BasicGCMExponentiator implements GCMExponentiator
+{
+ private int[] x;
+
+ public void init(byte[] x)
+ {
+ this.x = GCMUtil.asInts(x);
+ }
+
+ public void exponentiateX(long pow, byte[] output)
+ {
+ // Initial value is little-endian 1
+ int[] y = GCMUtil.oneAsInts();
+
+ if (pow > 0)
+ {
+ int[] powX = Arrays.clone(x);
+ do
+ {
+ if ((pow & 1L) != 0)
+ {
+ GCMUtil.multiply(y, powX);
+ }
+ GCMUtil.multiply(powX, powX);
+ pow >>>= 1;
+ }
+ while (pow > 0);
+ }
+
+ GCMUtil.asBytes(y, output);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/modes/gcm/BasicGCMMultiplier.java b/core/src/main/java/org/spongycastle/crypto/modes/gcm/BasicGCMMultiplier.java
new file mode 100644
index 00000000..33866a9a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/gcm/BasicGCMMultiplier.java
@@ -0,0 +1,18 @@
+package org.spongycastle.crypto.modes.gcm;
+
+import org.spongycastle.util.Arrays;
+
+public class BasicGCMMultiplier implements GCMMultiplier
+{
+ private byte[] H;
+
+ public void init(byte[] H)
+ {
+ this.H = Arrays.clone(H);
+ }
+
+ public void multiplyH(byte[] x)
+ {
+ GCMUtil.multiply(x, H);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/modes/gcm/GCMExponentiator.java b/core/src/main/java/org/spongycastle/crypto/modes/gcm/GCMExponentiator.java
new file mode 100644
index 00000000..1ed19fbd
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/gcm/GCMExponentiator.java
@@ -0,0 +1,7 @@
+package org.spongycastle.crypto.modes.gcm;
+
+public interface GCMExponentiator
+{
+ void init(byte[] x);
+ void exponentiateX(long pow, byte[] output);
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/modes/gcm/GCMMultiplier.java b/core/src/main/java/org/spongycastle/crypto/modes/gcm/GCMMultiplier.java
new file mode 100644
index 00000000..74afee2f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/gcm/GCMMultiplier.java
@@ -0,0 +1,7 @@
+package org.spongycastle.crypto.modes.gcm;
+
+public interface GCMMultiplier
+{
+ void init(byte[] H);
+ void multiplyH(byte[] x);
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/modes/gcm/GCMUtil.java b/core/src/main/java/org/spongycastle/crypto/modes/gcm/GCMUtil.java
new file mode 100644
index 00000000..77be4b87
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/gcm/GCMUtil.java
@@ -0,0 +1,457 @@
+package org.spongycastle.crypto.modes.gcm;
+
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Pack;
+
+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];
+ tmp[0] = (byte)0x80;
+ return tmp;
+ }
+
+ static int[] oneAsInts()
+ {
+ int[] tmp = new int[4];
+ tmp[0] = 1 << 31;
+ return tmp;
+ }
+
+ static long[] oneAsLongs()
+ {
+ long[] tmp = new long[2];
+ tmp[0] = 1L << 63;
+ return tmp;
+ }
+
+ 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)
+ {
+ Pack.bigEndianToInt(x, 0, z);
+ }
+
+ static long[] asLongs(byte[] x)
+ {
+ long[] z = new long[2];
+ Pack.bigEndianToLong(x, 0, z);
+ return z;
+ }
+
+ static void asLongs(byte[] x, long[] z)
+ {
+ Pack.bigEndianToLong(x, 0, z);
+ }
+
+ static void multiply(byte[] x, byte[] y)
+ {
+ byte[] r0 = Arrays.clone(x);
+ byte[] r1 = new byte[16];
+
+ for (int i = 0; i < 16; ++i)
+ {
+ byte bits = y[i];
+ for (int j = 7; j >= 0; --j)
+ {
+ if ((bits & (1 << j)) != 0)
+ {
+ xor(r1, r0);
+ }
+
+ if (shiftRight(r0) != 0)
+ {
+ r0[0] ^= E1B;
+ }
+ }
+ }
+
+ 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)
+ {
+ if (shiftRight(x) != 0)
+ {
+ x[0] ^= E1;
+ }
+ }
+
+ static void multiplyP(int[] x, int[] y)
+ {
+ if (shiftRight(x, y) != 0)
+ {
+ y[0] ^= E1;
+ }
+ }
+
+ // P is the value with only bit i=1 set
+ static void multiplyP8(int[] x)
+ {
+// for (int i = 8; i != 0; --i)
+// {
+// multiplyP(x);
+// }
+
+ int c = shiftRightN(x, 8);
+ x[0] ^= LOOKUP[c >>> 24];
+ }
+
+ static void multiplyP8(int[] x, int[] y)
+ {
+ int c = shiftRightN(x, 8, y);
+ y[0] ^= LOOKUP[c >>> 24];
+ }
+
+ static byte shiftRight(byte[] x)
+ {
+// 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 = 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 byte shiftRight(byte[] x, byte[] z)
+ {
+// 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 = 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 int shiftRight(int[] x)
+ {
+// int c = 0;
+// for (int i = 0; i < 4; ++i)
+// {
+// int b = x[i];
+// x[i] = (b >>> 1) | c;
+// c = b << 31;
+// }
+// return c;
+
+ int b = x[0];
+ x[0] = b >>> 1;
+ int c = b << 31;
+ b = x[1];
+ x[1] = (b >>> 1) | c;
+ c = b << 31;
+ b = x[2];
+ x[2] = (b >>> 1) | c;
+ c = b << 31;
+ b = x[3];
+ x[3] = (b >>> 1) | c;
+ return b << 31;
+ }
+
+ static int shiftRight(int[] x, int[] z)
+ {
+// int c = 0;
+// for (int i = 0; i < 4; ++i)
+// {
+// int b = x[i];
+// z[i] = (b >>> 1) | c;
+// c = b << 31;
+// }
+// return c;
+
+ int b = x[0];
+ z[0] = b >>> 1;
+ int c = b << 31;
+ b = x[1];
+ z[1] = (b >>> 1) | c;
+ c = b << 31;
+ b = x[2];
+ z[2] = (b >>> 1) | c;
+ c = b << 31;
+ b = x[3];
+ z[3] = (b >>> 1) | c;
+ return b << 31;
+ }
+
+ static long shiftRight(long[] x)
+ {
+ long b = x[0];
+ x[0] = b >>> 1;
+ long c = b << 63;
+ b = x[1];
+ x[1] = (b >>> 1) | c;
+ return b << 63;
+ }
+
+ static long shiftRight(long[] x, long[] z)
+ {
+ long b = x[0];
+ z[0] = b >>> 1;
+ long c = b << 63;
+ b = x[1];
+ z[1] = (b >>> 1) | c;
+ return b << 63;
+ }
+
+ static int shiftRightN(int[] x, int n)
+ {
+// int c = 0, nInv = 32 - n;
+// for (int i = 0; i < 4; ++i)
+// {
+// int b = x[i];
+// x[i] = (b >>> n) | c;
+// c = b << nInv;
+// }
+// return c;
+
+ int b = x[0], nInv = 32 - n;
+ x[0] = b >>> n;
+ int c = b << nInv;
+ b = x[1];
+ x[1] = (b >>> n) | c;
+ c = b << nInv;
+ b = x[2];
+ x[2] = (b >>> n) | c;
+ c = b << nInv;
+ b = x[3];
+ x[3] = (b >>> n) | c;
+ return b << nInv;
+ }
+
+ static int shiftRightN(int[] x, int n, int[] z)
+ {
+// int c = 0, nInv = 32 - n;
+// for (int i = 0; i < 4; ++i)
+// {
+// int b = x[i];
+// z[i] = (b >>> n) | c;
+// c = b << nInv;
+// }
+// return c;
+
+ int b = x[0], nInv = 32 - n;
+ z[0] = b >>> n;
+ int c = b << nInv;
+ b = x[1];
+ z[1] = (b >>> n) | c;
+ c = b << nInv;
+ b = x[2];
+ z[2] = (b >>> n) | c;
+ c = b << nInv;
+ b = x[3];
+ z[3] = (b >>> n) | c;
+ return b << nInv;
+ }
+
+ static void xor(byte[] x, byte[] y)
+ {
+ int i = 0;
+ do
+ {
+ 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[] x, byte[] y, int yOff, int yLen)
+ {
+ while (yLen-- > 0)
+ {
+ x[yLen] ^= y[yOff + yLen];
+ }
+ }
+
+ static void xor(byte[] x, byte[] y, byte[] z)
+ {
+ int i = 0;
+ do
+ {
+ 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(int[] x, int[] y)
+ {
+ x[0] ^= y[0];
+ x[1] ^= y[1];
+ x[2] ^= y[2];
+ x[3] ^= y[3];
+ }
+
+ static void xor(int[] x, int[] y, int[] z)
+ {
+ 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(long[] x, long[] y)
+ {
+ 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/core/src/main/java/org/spongycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java b/core/src/main/java/org/spongycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java
new file mode 100644
index 00000000..f7818898
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java
@@ -0,0 +1,58 @@
+package org.spongycastle.crypto.modes.gcm;
+
+import java.util.Vector;
+
+import org.spongycastle.util.Arrays;
+
+public class Tables1kGCMExponentiator implements GCMExponentiator
+{
+ // A lookup table of the power-of-two powers of 'x'
+ // - lookupPowX2[i] = x^(2^i)
+ private Vector lookupPowX2;
+
+ public void init(byte[] x)
+ {
+ int[] y = GCMUtil.asInts(x);
+ if (lookupPowX2 != null && Arrays.areEqual(y, (int[])lookupPowX2.elementAt(0)))
+ {
+ return;
+ }
+
+ lookupPowX2 = new Vector(8);
+ lookupPowX2.addElement(y);
+ }
+
+ public void exponentiateX(long pow, byte[] output)
+ {
+ int[] y = GCMUtil.oneAsInts();
+ int bit = 0;
+ while (pow > 0)
+ {
+ if ((pow & 1L) != 0)
+ {
+ ensureAvailable(bit);
+ GCMUtil.multiply(y, (int[])lookupPowX2.elementAt(bit));
+ }
+ ++bit;
+ pow >>>= 1;
+ }
+
+ GCMUtil.asBytes(y, output);
+ }
+
+ private void ensureAvailable(int bit)
+ {
+ int count = lookupPowX2.size();
+ if (count <= bit)
+ {
+ int[] tmp = (int[])lookupPowX2.elementAt(count - 1);
+ do
+ {
+ tmp = Arrays.clone(tmp);
+ GCMUtil.multiply(tmp, tmp);
+ lookupPowX2.addElement(tmp);
+ }
+ while (++count <= bit);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/modes/gcm/Tables64kGCMMultiplier.java b/core/src/main/java/org/spongycastle/crypto/modes/gcm/Tables64kGCMMultiplier.java
new file mode 100644
index 00000000..352ffc58
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/gcm/Tables64kGCMMultiplier.java
@@ -0,0 +1,73 @@
+package org.spongycastle.crypto.modes.gcm;
+
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Pack;
+
+public class Tables64kGCMMultiplier implements GCMMultiplier
+{
+ private byte[] H;
+ private int[][][] M;
+
+ public void init(byte[] H)
+ {
+ if (M == null)
+ {
+ M = new int[16][256][4];
+ }
+ else if (Arrays.areEqual(this.H, H))
+ {
+ return;
+ }
+
+ this.H = Arrays.clone(H);
+
+ // M[0][0] is ZEROES;
+ GCMUtil.asInts(H, M[0][128]);
+
+ for (int j = 64; j >= 1; j >>= 1)
+ {
+ GCMUtil.multiplyP(M[0][j + j], M[0][j]);
+ }
+
+ int i = 0;
+ for (;;)
+ {
+ for (int j = 2; j < 256; j += j)
+ {
+ for (int k = 1; k < j; ++k)
+ {
+ GCMUtil.xor(M[i][j], M[i][k], M[i][j + k]);
+ }
+ }
+
+ if (++i == 16)
+ {
+ return;
+ }
+
+ // M[i][0] is ZEROES;
+ for (int j = 128; j > 0; j >>= 1)
+ {
+ GCMUtil.multiplyP8(M[i - 1][j], M[i][j]);
+ }
+ }
+ }
+
+ public void multiplyH(byte[] x)
+ {
+// assert x.Length == 16;
+
+ int[] z = new int[4];
+ for (int i = 15; i >= 0; --i)
+ {
+// GCMUtil.xor(z, M[i][x[i] & 0xff]);
+ int[] m = M[i][x[i] & 0xff];
+ z[0] ^= m[0];
+ z[1] ^= m[1];
+ z[2] ^= m[2];
+ z[3] ^= m[3];
+ }
+
+ Pack.intToBigEndian(z, x, 0);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java b/core/src/main/java/org/spongycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java
new file mode 100644
index 00000000..65e0389a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java
@@ -0,0 +1,90 @@
+package org.spongycastle.crypto.modes.gcm;
+
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Pack;
+
+public class Tables8kGCMMultiplier implements GCMMultiplier
+{
+ private byte[] H;
+ private int[][][] M;
+
+ public void init(byte[] H)
+ {
+ if (M == null)
+ {
+ M = new int[32][16][4];
+ }
+ else if (Arrays.areEqual(this.H, H))
+ {
+ return;
+ }
+
+ this.H = Arrays.clone(H);
+
+ // M[0][0] is ZEROES;
+ // M[1][0] is ZEROES;
+ GCMUtil.asInts(H, M[1][8]);
+
+ for (int j = 4; j >= 1; j >>= 1)
+ {
+ GCMUtil.multiplyP(M[1][j + j], M[1][j]);
+ }
+
+ GCMUtil.multiplyP(M[1][1], M[0][8]);
+
+ for (int j = 4; j >= 1; j >>= 1)
+ {
+ GCMUtil.multiplyP(M[0][j + j], M[0][j]);
+ }
+
+ int i = 0;
+ for (;;)
+ {
+ for (int j = 2; j < 16; j += j)
+ {
+ for (int k = 1; k < j; ++k)
+ {
+ GCMUtil.xor(M[i][j], M[i][k], M[i][j + k]);
+ }
+ }
+
+ if (++i == 32)
+ {
+ return;
+ }
+
+ if (i > 1)
+ {
+ // M[i][0] is ZEROES;
+ for(int j = 8; j > 0; j >>= 1)
+ {
+ GCMUtil.multiplyP8(M[i - 2][j], M[i][j]);
+ }
+ }
+ }
+ }
+
+ public void multiplyH(byte[] x)
+ {
+// assert x.Length == 16;
+
+ int[] z = new int[4];
+ for (int i = 15; i >= 0; --i)
+ {
+// GCMUtil.xor(z, M[i + i][x[i] & 0x0f]);
+ int[] m = M[i + i][x[i] & 0x0f];
+ z[0] ^= m[0];
+ z[1] ^= m[1];
+ z[2] ^= m[2];
+ z[3] ^= m[3];
+// GCMUtil.xor(z, M[i + i + 1][(x[i] & 0xf0) >>> 4]);
+ m = M[i + i + 1][(x[i] & 0xf0) >>> 4];
+ z[0] ^= m[0];
+ z[1] ^= m[1];
+ z[2] ^= m[2];
+ z[3] ^= m[3];
+ }
+
+ Pack.intToBigEndian(z, x, 0);
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/crypto/paddings/BlockCipherPadding.java b/core/src/main/java/org/spongycastle/crypto/paddings/BlockCipherPadding.java
new file mode 100644
index 00000000..f68915d1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/paddings/BlockCipherPadding.java
@@ -0,0 +1,48 @@
+package org.spongycastle.crypto.paddings;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.InvalidCipherTextException;
+
+/**
+ * Block cipher padders are expected to conform to this interface
+ */
+public interface BlockCipherPadding
+{
+ /**
+ * Initialise the padder.
+ *
+ * @param random the source of randomness for the padding, if required.
+ */
+ public void init(SecureRandom random)
+ throws IllegalArgumentException;
+
+ /**
+ * Return the name of the algorithm the cipher implements.
+ *
+ * @return the name of the algorithm the cipher implements.
+ */
+ public String getPaddingName();
+
+ /**
+ * add the pad bytes to the passed in block, returning the
+ * number of bytes added.
+ * <p>
+ * Note: this assumes that the last block of plain text is always
+ * passed to it inside in. i.e. if inOff is zero, indicating the
+ * entire block is to be overwritten with padding the value of in
+ * should be the same as the last block of plain text. The reason
+ * for this is that some modes such as "trailing bit compliment"
+ * base the padding on the last byte of plain text.
+ * </p>
+ */
+ public int addPadding(byte[] in, int inOff);
+
+ /**
+ * return the number of pad bytes present in the block.
+ * @exception InvalidCipherTextException if the padding is badly formed
+ * or invalid.
+ */
+ public int padCount(byte[] in)
+ throws InvalidCipherTextException;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/paddings/ISO10126d2Padding.java b/core/src/main/java/org/spongycastle/crypto/paddings/ISO10126d2Padding.java
new file mode 100644
index 00000000..16e32f27
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/paddings/ISO10126d2Padding.java
@@ -0,0 +1,79 @@
+package org.spongycastle.crypto.paddings;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A padder that adds ISO10126-2 padding to a block.
+ */
+public class ISO10126d2Padding
+ implements BlockCipherPadding
+{
+ SecureRandom random;
+
+ /**
+ * Initialise the padder.
+ *
+ * @param random a SecureRandom if available.
+ */
+ public void init(SecureRandom random)
+ throws IllegalArgumentException
+ {
+ if (random != null)
+ {
+ this.random = random;
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ }
+ }
+
+ /**
+ * Return the name of the algorithm the padder implements.
+ *
+ * @return the name of the algorithm the padder implements.
+ */
+ public String getPaddingName()
+ {
+ return "ISO10126-2";
+ }
+
+ /**
+ * add the pad bytes to the passed in block, returning the
+ * number of bytes added.
+ */
+ public int addPadding(
+ byte[] in,
+ int inOff)
+ {
+ byte code = (byte)(in.length - inOff);
+
+ while (inOff < (in.length - 1))
+ {
+ in[inOff] = (byte)random.nextInt();
+ inOff++;
+ }
+
+ in[inOff] = code;
+
+ return code;
+ }
+
+ /**
+ * return the number of pad bytes present in the block.
+ */
+ public int padCount(byte[] in)
+ throws InvalidCipherTextException
+ {
+ int count = in[in.length - 1] & 0xff;
+
+ if (count > in.length)
+ {
+ throw new InvalidCipherTextException("pad block corrupted");
+ }
+
+ return count;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/paddings/ISO7816d4Padding.java b/core/src/main/java/org/spongycastle/crypto/paddings/ISO7816d4Padding.java
new file mode 100644
index 00000000..d187e445
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/paddings/ISO7816d4Padding.java
@@ -0,0 +1,77 @@
+package org.spongycastle.crypto.paddings;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A padder that adds the padding according to the scheme referenced in
+ * ISO 7814-4 - scheme 2 from ISO 9797-1. The first byte is 0x80, rest is 0x00
+ */
+public class ISO7816d4Padding
+ implements BlockCipherPadding
+{
+ /**
+ * Initialise the padder.
+ *
+ * @param random - a SecureRandom if available.
+ */
+ public void init(SecureRandom random)
+ throws IllegalArgumentException
+ {
+ // nothing to do.
+ }
+
+ /**
+ * Return the name of the algorithm the padder implements.
+ *
+ * @return the name of the algorithm the padder implements.
+ */
+ public String getPaddingName()
+ {
+ return "ISO7816-4";
+ }
+
+ /**
+ * add the pad bytes to the passed in block, returning the
+ * number of bytes added.
+ */
+ public int addPadding(
+ byte[] in,
+ int inOff)
+ {
+ int added = (in.length - inOff);
+
+ in [inOff]= (byte) 0x80;
+ inOff ++;
+
+ while (inOff < in.length)
+ {
+ in[inOff] = (byte) 0;
+ inOff++;
+ }
+
+ return added;
+ }
+
+ /**
+ * return the number of pad bytes present in the block.
+ */
+ public int padCount(byte[] in)
+ throws InvalidCipherTextException
+ {
+ int count = in.length - 1;
+
+ while (count > 0 && in[count] == 0)
+ {
+ count--;
+ }
+
+ if (in[count] != (byte)0x80)
+ {
+ throw new InvalidCipherTextException("pad block corrupted");
+ }
+
+ return in.length - count;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/paddings/PKCS7Padding.java b/core/src/main/java/org/spongycastle/crypto/paddings/PKCS7Padding.java
new file mode 100644
index 00000000..88973649
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/paddings/PKCS7Padding.java
@@ -0,0 +1,76 @@
+package org.spongycastle.crypto.paddings;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A padder that adds PKCS7/PKCS5 padding to a block.
+ */
+public class PKCS7Padding
+ implements BlockCipherPadding
+{
+ /**
+ * Initialise the padder.
+ *
+ * @param random - a SecureRandom if available.
+ */
+ public void init(SecureRandom random)
+ throws IllegalArgumentException
+ {
+ // nothing to do.
+ }
+
+ /**
+ * Return the name of the algorithm the padder implements.
+ *
+ * @return the name of the algorithm the padder implements.
+ */
+ public String getPaddingName()
+ {
+ return "PKCS7";
+ }
+
+ /**
+ * add the pad bytes to the passed in block, returning the
+ * number of bytes added.
+ */
+ public int addPadding(
+ byte[] in,
+ int inOff)
+ {
+ byte code = (byte)(in.length - inOff);
+
+ while (inOff < in.length)
+ {
+ in[inOff] = code;
+ inOff++;
+ }
+
+ return code;
+ }
+
+ /**
+ * return the number of pad bytes present in the block.
+ */
+ public int padCount(byte[] in)
+ throws InvalidCipherTextException
+ {
+ int count = in[in.length - 1] & 0xff;
+
+ if (count > in.length || count == 0)
+ {
+ throw new InvalidCipherTextException("pad block corrupted");
+ }
+
+ for (int i = 1; i <= count; i++)
+ {
+ if (in[in.length - i] != count)
+ {
+ throw new InvalidCipherTextException("pad block corrupted");
+ }
+ }
+
+ return count;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/paddings/PaddedBufferedBlockCipher.java b/core/src/main/java/org/spongycastle/crypto/paddings/PaddedBufferedBlockCipher.java
new file mode 100644
index 00000000..c479a062
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/paddings/PaddedBufferedBlockCipher.java
@@ -0,0 +1,299 @@
+package org.spongycastle.crypto.paddings;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.BufferedBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+
+/**
+ * A wrapper class that allows block ciphers to be used to process data in
+ * a piecemeal fashion with padding. The PaddedBufferedBlockCipher
+ * outputs a block only when the buffer is full and more data is being added,
+ * or on a doFinal (unless the current block in the buffer is a pad block).
+ * The default padding mechanism used is the one outlined in PKCS5/PKCS7.
+ */
+public class PaddedBufferedBlockCipher
+ extends BufferedBlockCipher
+{
+ BlockCipherPadding padding;
+
+ /**
+ * Create a buffered block cipher with the desired padding.
+ *
+ * @param cipher the underlying block cipher this buffering object wraps.
+ * @param padding the padding type.
+ */
+ public PaddedBufferedBlockCipher(
+ BlockCipher cipher,
+ BlockCipherPadding padding)
+ {
+ this.cipher = cipher;
+ this.padding = padding;
+
+ buf = new byte[cipher.getBlockSize()];
+ bufOff = 0;
+ }
+
+ /**
+ * Create a buffered block cipher PKCS7 padding
+ *
+ * @param cipher the underlying block cipher this buffering object wraps.
+ */
+ public PaddedBufferedBlockCipher(
+ BlockCipher cipher)
+ {
+ this(cipher, new PKCS7Padding());
+ }
+
+ /**
+ * initialise the cipher.
+ *
+ * @param forEncryption if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ this.forEncryption = forEncryption;
+
+ reset();
+
+ if (params instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom p = (ParametersWithRandom)params;
+
+ padding.init(p.getRandom());
+
+ cipher.init(forEncryption, p.getParameters());
+ }
+ else
+ {
+ padding.init(null);
+
+ cipher.init(forEncryption, params);
+ }
+ }
+
+ /**
+ * return the minimum 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)
+ {
+ int total = len + bufOff;
+ int leftOver = total % buf.length;
+
+ if (leftOver == 0)
+ {
+ if (forEncryption)
+ {
+ return total + buf.length;
+ }
+
+ return total;
+ }
+
+ return total - leftOver + buf.length;
+ }
+
+ /**
+ * 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 Math.max(0, total - buf.length);
+ }
+
+ return total - leftOver;
+ }
+
+ /**
+ * process a single byte, producing an output block if neccessary.
+ *
+ * @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 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);
+ bufOff = 0;
+ }
+
+ 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 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 OutputLengthException("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);
+
+ bufOff = 0;
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > buf.length)
+ {
+ resultLen += cipher.processBlock(in, inOff, out, outOff + resultLen);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+
+ return resultLen;
+ }
+
+ /**
+ * Process the last block in the buffer. If the buffer is currently
+ * full and padding needs to be added a call to doFinal will produce
+ * 2 * getBlockSize() bytes.
+ *
+ * @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 DataLengthException if there is insufficient space in out for
+ * the output or we are decrypting and the input is not block size aligned.
+ * @exception IllegalStateException if the underlying cipher is not
+ * initialised.
+ * @exception InvalidCipherTextException if padding is expected and not found.
+ */
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException, InvalidCipherTextException
+ {
+ int blockSize = cipher.getBlockSize();
+ int resultLen = 0;
+
+ if (forEncryption)
+ {
+ if (bufOff == blockSize)
+ {
+ if ((outOff + 2 * blockSize) > out.length)
+ {
+ reset();
+
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ resultLen = cipher.processBlock(buf, 0, out, outOff);
+ bufOff = 0;
+ }
+
+ padding.addPadding(buf, bufOff);
+
+ resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen);
+
+ reset();
+ }
+ else
+ {
+ if (bufOff == blockSize)
+ {
+ resultLen = cipher.processBlock(buf, 0, buf, 0);
+ bufOff = 0;
+ }
+ else
+ {
+ reset();
+
+ throw new DataLengthException("last block incomplete in decryption");
+ }
+
+ try
+ {
+ resultLen -= padding.padCount(buf);
+
+ System.arraycopy(buf, 0, out, outOff, resultLen);
+ }
+ finally
+ {
+ reset();
+ }
+ }
+
+ return resultLen;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/paddings/TBCPadding.java b/core/src/main/java/org/spongycastle/crypto/paddings/TBCPadding.java
new file mode 100644
index 00000000..4b8190df
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/paddings/TBCPadding.java
@@ -0,0 +1,89 @@
+package org.spongycastle.crypto.paddings;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A padder that adds Trailing-Bit-Compliment padding to a block.
+ * <p>
+ * This padding pads the block out with the compliment of the last bit
+ * of the plain text.
+ * </p>
+ */
+public class TBCPadding
+ implements BlockCipherPadding
+{
+ /**
+ * Initialise the padder.
+ *
+ * @param random - a SecureRandom if available.
+ */
+ public void init(SecureRandom random)
+ throws IllegalArgumentException
+ {
+ // nothing to do.
+ }
+
+ /**
+ * Return the name of the algorithm the padder implements.
+ *
+ * @return the name of the algorithm the padder implements.
+ */
+ public String getPaddingName()
+ {
+ return "TBC";
+ }
+
+ /**
+ * add the pad bytes to the passed in block, returning the
+ * number of bytes added.
+ * <p>
+ * Note: this assumes that the last block of plain text is always
+ * passed to it inside in. i.e. if inOff is zero, indicating the
+ * entire block is to be overwritten with padding the value of in
+ * should be the same as the last block of plain text.
+ * </p>
+ */
+ public int addPadding(
+ byte[] in,
+ int inOff)
+ {
+ int count = in.length - inOff;
+ byte code;
+
+ if (inOff > 0)
+ {
+ code = (byte)((in[inOff - 1] & 0x01) == 0 ? 0xff : 0x00);
+ }
+ else
+ {
+ code = (byte)((in[in.length - 1] & 0x01) == 0 ? 0xff : 0x00);
+ }
+
+ while (inOff < in.length)
+ {
+ in[inOff] = code;
+ inOff++;
+ }
+
+ return count;
+ }
+
+ /**
+ * return the number of pad bytes present in the block.
+ */
+ public int padCount(byte[] in)
+ throws InvalidCipherTextException
+ {
+ byte code = in[in.length - 1];
+
+ int index = in.length - 1;
+ while (index > 0 && in[index - 1] == code)
+ {
+ index--;
+ }
+
+ return in.length - index;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/paddings/X923Padding.java b/core/src/main/java/org/spongycastle/crypto/paddings/X923Padding.java
new file mode 100644
index 00000000..e5b8992f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/paddings/X923Padding.java
@@ -0,0 +1,80 @@
+package org.spongycastle.crypto.paddings;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A padder that adds X9.23 padding to a block - if a SecureRandom is
+ * passed in random padding is assumed, otherwise padding with zeros is used.
+ */
+public class X923Padding
+ implements BlockCipherPadding
+{
+ SecureRandom random = null;
+
+ /**
+ * Initialise the padder.
+ *
+ * @param random a SecureRandom if one is available.
+ */
+ public void init(SecureRandom random)
+ throws IllegalArgumentException
+ {
+ this.random = random;
+ }
+
+ /**
+ * Return the name of the algorithm the padder implements.
+ *
+ * @return the name of the algorithm the padder implements.
+ */
+ public String getPaddingName()
+ {
+ return "X9.23";
+ }
+
+ /**
+ * add the pad bytes to the passed in block, returning the
+ * number of bytes added.
+ */
+ public int addPadding(
+ byte[] in,
+ int inOff)
+ {
+ byte code = (byte)(in.length - inOff);
+
+ while (inOff < in.length - 1)
+ {
+ if (random == null)
+ {
+ in[inOff] = 0;
+ }
+ else
+ {
+ in[inOff] = (byte)random.nextInt();
+ }
+ inOff++;
+ }
+
+ in[inOff] = code;
+
+ return code;
+ }
+
+ /**
+ * return the number of pad bytes present in the block.
+ */
+ public int padCount(byte[] in)
+ throws InvalidCipherTextException
+ {
+ int count = in[in.length - 1] & 0xff;
+
+ if (count > in.length)
+ {
+ throw new InvalidCipherTextException("pad block corrupted");
+ }
+
+ return count;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/paddings/ZeroBytePadding.java b/core/src/main/java/org/spongycastle/crypto/paddings/ZeroBytePadding.java
new file mode 100644
index 00000000..53c80599
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/paddings/ZeroBytePadding.java
@@ -0,0 +1,73 @@
+package org.spongycastle.crypto.paddings;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A padder that adds NULL byte padding to a block.
+ */
+public class ZeroBytePadding
+ implements BlockCipherPadding
+{
+ /**
+ * Initialise the padder.
+ *
+ * @param random - a SecureRandom if available.
+ */
+ public void init(SecureRandom random)
+ throws IllegalArgumentException
+ {
+ // nothing to do.
+ }
+
+ /**
+ * Return the name of the algorithm the padder implements.
+ *
+ * @return the name of the algorithm the padder implements.
+ */
+ public String getPaddingName()
+ {
+ return "ZeroByte";
+ }
+
+ /**
+ * add the pad bytes to the passed in block, returning the
+ * number of bytes added.
+ */
+ public int addPadding(
+ byte[] in,
+ int inOff)
+ {
+ int added = (in.length - inOff);
+
+ while (inOff < in.length)
+ {
+ in[inOff] = (byte) 0;
+ inOff++;
+ }
+
+ return added;
+ }
+
+ /**
+ * return the number of pad bytes present in the block.
+ */
+ public int padCount(byte[] in)
+ throws InvalidCipherTextException
+ {
+ int count = in.length;
+
+ while (count > 0)
+ {
+ if (in[count - 1] != 0)
+ {
+ break;
+ }
+
+ count--;
+ }
+
+ return in.length - count;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/AEADParameters.java b/core/src/main/java/org/spongycastle/crypto/params/AEADParameters.java
new file mode 100644
index 00000000..b3ee4fca
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/AEADParameters.java
@@ -0,0 +1,60 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.CipherParameters;
+
+public class AEADParameters
+ implements CipherParameters
+{
+ private byte[] associatedText;
+ private byte[] nonce;
+ private KeyParameter key;
+ private int macSize;
+
+ /**
+ * Base constructor.
+ *
+ * @param key key to be used by underlying cipher
+ * @param macSize macSize in bits
+ * @param nonce nonce to be used
+ */
+ public AEADParameters(KeyParameter key, int macSize, byte[] nonce)
+ {
+ this(key, macSize, nonce, null);
+ }
+
+ /**
+ * Base constructor.
+ *
+ * @param key key to be used by underlying cipher
+ * @param macSize macSize in bits
+ * @param nonce nonce to be used
+ * @param associatedText initial associated text, if any
+ */
+ public AEADParameters(KeyParameter key, int macSize, byte[] nonce, byte[] associatedText)
+ {
+ this.key = key;
+ this.nonce = nonce;
+ this.macSize = macSize;
+ this.associatedText = associatedText;
+ }
+
+ public KeyParameter getKey()
+ {
+ return key;
+ }
+
+ public int getMacSize()
+ {
+ return macSize;
+ }
+
+ public byte[] getAssociatedText()
+ {
+ return associatedText;
+ }
+
+ public byte[] getNonce()
+ {
+ return nonce;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/AsymmetricKeyParameter.java b/core/src/main/java/org/spongycastle/crypto/params/AsymmetricKeyParameter.java
new file mode 100644
index 00000000..9ac1c48b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/AsymmetricKeyParameter.java
@@ -0,0 +1,20 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.CipherParameters;
+
+public class AsymmetricKeyParameter
+ implements CipherParameters
+{
+ boolean privateKey;
+
+ public AsymmetricKeyParameter(
+ boolean privateKey)
+ {
+ this.privateKey = privateKey;
+ }
+
+ public boolean isPrivate()
+ {
+ return privateKey;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/CCMParameters.java b/core/src/main/java/org/spongycastle/crypto/params/CCMParameters.java
new file mode 100644
index 00000000..a1198645
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/CCMParameters.java
@@ -0,0 +1,21 @@
+package org.spongycastle.crypto.params;
+
+/**
+ * @deprecated use AEADParameters
+ */
+public class CCMParameters
+ extends AEADParameters
+{
+ /**
+ * Base constructor.
+ *
+ * @param key key to be used by underlying cipher
+ * @param macSize macSize in bits
+ * @param nonce nonce to be used
+ * @param associatedText associated text, if any
+ */
+ public CCMParameters(KeyParameter key, int macSize, byte[] nonce, byte[] associatedText)
+ {
+ super(key, macSize, nonce, associatedText);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/CramerShoupKeyGenerationParameters.java b/core/src/main/java/org/spongycastle/crypto/params/CramerShoupKeyGenerationParameters.java
new file mode 100644
index 00000000..38976d2c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/CramerShoupKeyGenerationParameters.java
@@ -0,0 +1,24 @@
+package org.spongycastle.crypto.params;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.KeyGenerationParameters;
+
+public class CramerShoupKeyGenerationParameters extends KeyGenerationParameters {
+
+ private CramerShoupParameters params;
+
+ public CramerShoupKeyGenerationParameters(SecureRandom random, CramerShoupParameters params) {
+ super(random, getStrength(params));
+
+ this.params = params;
+ }
+
+ public CramerShoupParameters getParameters() {
+ return params;
+ }
+
+ static int getStrength(CramerShoupParameters params) {
+ return params.getP().bitLength();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/CramerShoupKeyParameters.java b/core/src/main/java/org/spongycastle/crypto/params/CramerShoupKeyParameters.java
new file mode 100644
index 00000000..5bacd588
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/CramerShoupKeyParameters.java
@@ -0,0 +1,40 @@
+package org.spongycastle.crypto.params;
+
+public class CramerShoupKeyParameters extends AsymmetricKeyParameter {
+
+ private CramerShoupParameters params;
+
+ protected CramerShoupKeyParameters(boolean isPrivate, CramerShoupParameters params) {
+ super(isPrivate);
+
+ this.params = params;
+ }
+
+ public CramerShoupParameters getParameters() {
+ return params;
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof CramerShoupKeyParameters)) {
+ return false;
+ }
+
+ CramerShoupKeyParameters csKey = (CramerShoupKeyParameters) obj;
+
+ if (params == null) {
+ return csKey.getParameters() == null;
+ } else {
+ return params.equals(csKey.getParameters());
+ }
+ }
+
+ public int hashCode() {
+ int code = isPrivate() ? 0 : 1;
+
+ if (params != null) {
+ code ^= params.hashCode();
+ }
+
+ return code;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/CramerShoupParameters.java b/core/src/main/java/org/spongycastle/crypto/params/CramerShoupParameters.java
new file mode 100644
index 00000000..d1504bab
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/CramerShoupParameters.java
@@ -0,0 +1,53 @@
+package org.spongycastle.crypto.params;
+
+import java.math.BigInteger;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+
+public class CramerShoupParameters implements CipherParameters {
+
+ private BigInteger p; // prime order of G
+ private BigInteger g1, g2; // generate G
+
+ private Digest H; // hash function
+
+ public CramerShoupParameters(BigInteger p, BigInteger g1, BigInteger g2, Digest H) {
+ this.p = p;
+ this.g1 = g1;
+ this.g2 = g2;
+ this.H = H;
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof DSAParameters)) {
+ return false;
+ }
+
+ CramerShoupParameters pm = (CramerShoupParameters) obj;
+
+ return (pm.getP().equals(p) && pm.getG1().equals(g1) && pm.getG2().equals(g2));
+ }
+
+ public int hashCode() {
+ return getP().hashCode() ^ getG1().hashCode() ^ getG2().hashCode();
+ }
+
+ public BigInteger getG1() {
+ return g1;
+ }
+
+ public BigInteger getG2() {
+ return g2;
+ }
+
+ public BigInteger getP() {
+ return p;
+ }
+
+ public Digest getH() {
+ H.reset();
+ return H;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/CramerShoupPrivateKeyParameters.java b/core/src/main/java/org/spongycastle/crypto/params/CramerShoupPrivateKeyParameters.java
new file mode 100644
index 00000000..6aae8be2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/CramerShoupPrivateKeyParameters.java
@@ -0,0 +1,61 @@
+package org.spongycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class CramerShoupPrivateKeyParameters extends CramerShoupKeyParameters {
+
+ private BigInteger x1, x2, y1, y2, z; // Z_p
+ private CramerShoupPublicKeyParameters pk; // public key
+
+ public CramerShoupPrivateKeyParameters(CramerShoupParameters params, BigInteger x1, BigInteger x2, BigInteger y1, BigInteger y2, BigInteger z) {
+ super(true, params);
+
+ this.x1 = x1;
+ this.x2 = x2;
+ this.y1 = y1;
+ this.y2 = y2;
+ this.z = z;
+ }
+
+ public BigInteger getX1() {
+ return x1;
+ }
+
+ public BigInteger getX2() {
+ return x2;
+ }
+
+ public BigInteger getY1() {
+ return y1;
+ }
+
+ public BigInteger getY2() {
+ return y2;
+ }
+
+ public BigInteger getZ() {
+ return z;
+ }
+
+ public void setPk(CramerShoupPublicKeyParameters pk) {
+ this.pk = pk;
+ }
+
+ public CramerShoupPublicKeyParameters getPk() {
+ return pk;
+ }
+
+ public int hashCode() {
+ return x1.hashCode() ^ x2.hashCode() ^ y1.hashCode() ^ y2.hashCode() ^ z.hashCode() ^ super.hashCode();
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof CramerShoupPrivateKeyParameters)) {
+ return false;
+ }
+
+ CramerShoupPrivateKeyParameters other = (CramerShoupPrivateKeyParameters) obj;
+
+ return other.getX1().equals(this.x1) && other.getX2().equals(this.x2) && other.getY1().equals(this.y1) && other.getY2().equals(this.y2) && other.getZ().equals(this.z) && super.equals(obj);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/CramerShoupPublicKeyParameters.java b/core/src/main/java/org/spongycastle/crypto/params/CramerShoupPublicKeyParameters.java
new file mode 100644
index 00000000..20752bf6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/CramerShoupPublicKeyParameters.java
@@ -0,0 +1,42 @@
+package org.spongycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class CramerShoupPublicKeyParameters extends CramerShoupKeyParameters {
+
+ private BigInteger c, d, h; // public key group elements
+
+ public CramerShoupPublicKeyParameters(CramerShoupParameters params, BigInteger c, BigInteger d, BigInteger h) {
+ super(false, params);
+
+ this.c = c;
+ this.d = d;
+ this.h = h;
+ }
+
+ public BigInteger getC() {
+ return c;
+ }
+
+ public BigInteger getD() {
+ return d;
+ }
+
+ public BigInteger getH() {
+ return h;
+ }
+
+ public int hashCode() {
+ return c.hashCode() ^ d.hashCode() ^ h.hashCode() ^ super.hashCode();
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof CramerShoupPublicKeyParameters)) {
+ return false;
+ }
+
+ CramerShoupPublicKeyParameters other = (CramerShoupPublicKeyParameters) obj;
+
+ return other.getC().equals(c) && other.getD().equals(d) && other.getH().equals(h) && super.equals(obj);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/DESParameters.java b/core/src/main/java/org/spongycastle/crypto/params/DESParameters.java
new file mode 100644
index 00000000..6c9c3985
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/DESParameters.java
@@ -0,0 +1,107 @@
+package org.spongycastle.crypto.params;
+
+public class DESParameters
+ extends KeyParameter
+{
+ public DESParameters(
+ byte[] key)
+ {
+ super(key);
+
+ if (isWeakKey(key, 0))
+ {
+ throw new IllegalArgumentException("attempt to create weak DES key");
+ }
+ }
+
+ /*
+ * DES Key length in bytes.
+ */
+ static public final int DES_KEY_LENGTH = 8;
+
+ /*
+ * Table of weak and semi-weak keys taken from Schneier pp281
+ */
+ static private final int N_DES_WEAK_KEYS = 16;
+
+ static private byte[] DES_weak_keys =
+ {
+ /* weak keys */
+ (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01, (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01,
+ (byte)0x1f,(byte)0x1f,(byte)0x1f,(byte)0x1f, (byte)0x0e,(byte)0x0e,(byte)0x0e,(byte)0x0e,
+ (byte)0xe0,(byte)0xe0,(byte)0xe0,(byte)0xe0, (byte)0xf1,(byte)0xf1,(byte)0xf1,(byte)0xf1,
+ (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe, (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe,
+
+ /* semi-weak keys */
+ (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe, (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe,
+ (byte)0x1f,(byte)0xe0,(byte)0x1f,(byte)0xe0, (byte)0x0e,(byte)0xf1,(byte)0x0e,(byte)0xf1,
+ (byte)0x01,(byte)0xe0,(byte)0x01,(byte)0xe0, (byte)0x01,(byte)0xf1,(byte)0x01,(byte)0xf1,
+ (byte)0x1f,(byte)0xfe,(byte)0x1f,(byte)0xfe, (byte)0x0e,(byte)0xfe,(byte)0x0e,(byte)0xfe,
+ (byte)0x01,(byte)0x1f,(byte)0x01,(byte)0x1f, (byte)0x01,(byte)0x0e,(byte)0x01,(byte)0x0e,
+ (byte)0xe0,(byte)0xfe,(byte)0xe0,(byte)0xfe, (byte)0xf1,(byte)0xfe,(byte)0xf1,(byte)0xfe,
+ (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01, (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01,
+ (byte)0xe0,(byte)0x1f,(byte)0xe0,(byte)0x1f, (byte)0xf1,(byte)0x0e,(byte)0xf1,(byte)0x0e,
+ (byte)0xe0,(byte)0x01,(byte)0xe0,(byte)0x01, (byte)0xf1,(byte)0x01,(byte)0xf1,(byte)0x01,
+ (byte)0xfe,(byte)0x1f,(byte)0xfe,(byte)0x1f, (byte)0xfe,(byte)0x0e,(byte)0xfe,(byte)0x0e,
+ (byte)0x1f,(byte)0x01,(byte)0x1f,(byte)0x01, (byte)0x0e,(byte)0x01,(byte)0x0e,(byte)0x01,
+ (byte)0xfe,(byte)0xe0,(byte)0xfe,(byte)0xe0, (byte)0xfe,(byte)0xf1,(byte)0xfe,(byte)0xf1
+ };
+
+ /**
+ * DES has 16 weak keys. This method will check
+ * if the given DES key material is weak or semi-weak.
+ * Key material that is too short is regarded as weak.
+ * <p>
+ * See <a href="http://www.counterpane.com/applied.html">"Applied
+ * Cryptography"</a> by Bruce Schneier for more information.
+ *
+ * @return true if the given DES key material is weak or semi-weak,
+ * false otherwise.
+ */
+ public static boolean isWeakKey(
+ byte[] key,
+ int offset)
+ {
+ if (key.length - offset < DES_KEY_LENGTH)
+ {
+ throw new IllegalArgumentException("key material too short.");
+ }
+
+ nextkey: for (int i = 0; i < N_DES_WEAK_KEYS; i++)
+ {
+ for (int j = 0; j < DES_KEY_LENGTH; j++)
+ {
+ if (key[j + offset] != DES_weak_keys[i * DES_KEY_LENGTH + j])
+ {
+ continue nextkey;
+ }
+ }
+
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * DES Keys use the LSB as the odd parity bit. This can
+ * be used to check for corrupt keys.
+ *
+ * @param bytes the byte array to set the parity on.
+ */
+ public static void setOddParity(
+ byte[] bytes)
+ {
+ for (int i = 0; i < bytes.length; i++)
+ {
+ int b = bytes[i];
+ bytes[i] = (byte)((b & 0xfe) |
+ ((((b >> 1) ^
+ (b >> 2) ^
+ (b >> 3) ^
+ (b >> 4) ^
+ (b >> 5) ^
+ (b >> 6) ^
+ (b >> 7)) ^ 0x01) & 0x01));
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/DESedeParameters.java b/core/src/main/java/org/spongycastle/crypto/params/DESedeParameters.java
new file mode 100644
index 00000000..498371ad
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/DESedeParameters.java
@@ -0,0 +1,57 @@
+package org.spongycastle.crypto.params;
+
+public class DESedeParameters
+ extends DESParameters
+{
+ /*
+ * DES-EDE Key length in bytes.
+ */
+ static public final int DES_EDE_KEY_LENGTH = 24;
+
+ public DESedeParameters(
+ byte[] key)
+ {
+ super(key);
+
+ if (isWeakKey(key, 0, key.length))
+ {
+ throw new IllegalArgumentException("attempt to create weak DESede key");
+ }
+ }
+
+ /**
+ * return true if the passed in key is a DES-EDE weak key.
+ *
+ * @param key bytes making up the key
+ * @param offset offset into the byte array the key starts at
+ * @param length number of bytes making up the key
+ */
+ public static boolean isWeakKey(
+ byte[] key,
+ int offset,
+ int length)
+ {
+ for (int i = offset; i < length; i += DES_KEY_LENGTH)
+ {
+ if (DESParameters.isWeakKey(key, i))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * return true if the passed in key is a DES-EDE weak key.
+ *
+ * @param key bytes making up the key
+ * @param offset offset into the byte array the key starts at
+ */
+ public static boolean isWeakKey(
+ byte[] key,
+ int offset)
+ {
+ return isWeakKey(key, offset, key.length - offset);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/DHKeyGenerationParameters.java b/core/src/main/java/org/spongycastle/crypto/params/DHKeyGenerationParameters.java
new file mode 100644
index 00000000..246a195e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/DHKeyGenerationParameters.java
@@ -0,0 +1,30 @@
+package org.spongycastle.crypto.params;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.KeyGenerationParameters;
+
+public class DHKeyGenerationParameters
+ extends KeyGenerationParameters
+{
+ private DHParameters params;
+
+ public DHKeyGenerationParameters(
+ SecureRandom random,
+ DHParameters params)
+ {
+ super(random, getStrength(params));
+
+ this.params = params;
+ }
+
+ public DHParameters getParameters()
+ {
+ return params;
+ }
+
+ static int getStrength(DHParameters params)
+ {
+ return params.getL() != 0 ? params.getL() : params.getP().bitLength();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/DHKeyParameters.java b/core/src/main/java/org/spongycastle/crypto/params/DHKeyParameters.java
new file mode 100644
index 00000000..f2ac392e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/DHKeyParameters.java
@@ -0,0 +1,54 @@
+package org.spongycastle.crypto.params;
+
+
+public class DHKeyParameters
+ extends AsymmetricKeyParameter
+{
+ private DHParameters params;
+
+ protected DHKeyParameters(
+ boolean isPrivate,
+ DHParameters params)
+ {
+ super(isPrivate);
+
+ this.params = params;
+ }
+
+ public DHParameters getParameters()
+ {
+ return params;
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof DHKeyParameters))
+ {
+ return false;
+ }
+
+ DHKeyParameters dhKey = (DHKeyParameters)obj;
+
+ if (params == null)
+ {
+ return dhKey.getParameters() == null;
+ }
+ else
+ {
+ return params.equals(dhKey.getParameters());
+ }
+ }
+
+ public int hashCode()
+ {
+ int code = isPrivate() ? 0 : 1;
+
+ if (params != null)
+ {
+ code ^= params.hashCode();
+ }
+
+ return code;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/DHParameters.java b/core/src/main/java/org/spongycastle/crypto/params/DHParameters.java
new file mode 100644
index 00000000..d4f03ff3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/DHParameters.java
@@ -0,0 +1,189 @@
+package org.spongycastle.crypto.params;
+
+import java.math.BigInteger;
+
+import org.spongycastle.crypto.CipherParameters;
+
+public class DHParameters
+ implements CipherParameters
+{
+ private static final int DEFAULT_MINIMUM_LENGTH = 160;
+
+ // not final due to compiler bug in "simpler" JDKs
+ private BigInteger g;
+ private BigInteger p;
+ private BigInteger q;
+ private BigInteger j;
+ private int m;
+ private int l;
+ private DHValidationParameters validation;
+
+ private static int getDefaultMParam(
+ int lParam)
+ {
+ if (lParam == 0)
+ {
+ return DEFAULT_MINIMUM_LENGTH;
+ }
+
+ return lParam < DEFAULT_MINIMUM_LENGTH ? lParam : DEFAULT_MINIMUM_LENGTH;
+ }
+
+ public DHParameters(
+ BigInteger p,
+ BigInteger g)
+ {
+ this(p, g, null, 0);
+ }
+
+ public DHParameters(
+ BigInteger p,
+ BigInteger g,
+ BigInteger q)
+ {
+ this(p, g, q, 0);
+ }
+
+ public DHParameters(
+ BigInteger p,
+ BigInteger g,
+ BigInteger q,
+ int l)
+ {
+ this(p, g, q, getDefaultMParam(l), l, null, null);
+ }
+
+ public DHParameters(
+ BigInteger p,
+ BigInteger g,
+ BigInteger q,
+ int m,
+ int l)
+ {
+ this(p, g, q, m, l, null, null);
+ }
+
+ public DHParameters(
+ BigInteger p,
+ BigInteger g,
+ BigInteger q,
+ BigInteger j,
+ DHValidationParameters validation)
+ {
+ this(p, g, q, DEFAULT_MINIMUM_LENGTH, 0, j, validation);
+ }
+
+ public DHParameters(
+ BigInteger p,
+ BigInteger g,
+ BigInteger q,
+ int m,
+ int l,
+ BigInteger j,
+ DHValidationParameters validation)
+ {
+ if (l != 0)
+ {
+ BigInteger bigL = BigInteger.valueOf(2L ^ (l - 1));
+ if (bigL.compareTo(p) == 1)
+ {
+ throw new IllegalArgumentException("when l value specified, it must satisfy 2^(l-1) <= p");
+ }
+ if (l < m)
+ {
+ throw new IllegalArgumentException("when l value specified, it may not be less than m value");
+ }
+ }
+
+ this.g = g;
+ this.p = p;
+ this.q = q;
+ this.m = m;
+ this.l = l;
+ this.j = j;
+ this.validation = validation;
+ }
+
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ public BigInteger getG()
+ {
+ return g;
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ /**
+ * Return the subgroup factor J.
+ *
+ * @return subgroup factor
+ */
+ public BigInteger getJ()
+ {
+ return j;
+ }
+
+ /**
+ * Return the minimum length of the private value.
+ *
+ * @return the minimum length of the private value in bits.
+ */
+ public int getM()
+ {
+ return m;
+ }
+
+ /**
+ * Return the private value length in bits - if set, zero otherwise
+ *
+ * @return the private value length in bits, zero otherwise.
+ */
+ public int getL()
+ {
+ return l;
+ }
+
+ public DHValidationParameters getValidationParameters()
+ {
+ return validation;
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof DHParameters))
+ {
+ return false;
+ }
+
+ DHParameters pm = (DHParameters)obj;
+
+ if (this.getQ() != null)
+ {
+ if (!this.getQ().equals(pm.getQ()))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (pm.getQ() != null)
+ {
+ return false;
+ }
+ }
+
+ return pm.getP().equals(p) && pm.getG().equals(g);
+ }
+
+ public int hashCode()
+ {
+ return getP().hashCode() ^ getG().hashCode() ^ (getQ() != null ? getQ().hashCode() : 0);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/DHPrivateKeyParameters.java b/core/src/main/java/org/spongycastle/crypto/params/DHPrivateKeyParameters.java
new file mode 100644
index 00000000..6f192b36
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/DHPrivateKeyParameters.java
@@ -0,0 +1,41 @@
+package org.spongycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class DHPrivateKeyParameters
+ extends DHKeyParameters
+{
+ private BigInteger x;
+
+ public DHPrivateKeyParameters(
+ BigInteger x,
+ DHParameters params)
+ {
+ super(true, params);
+
+ this.x = x;
+ }
+
+ public BigInteger getX()
+ {
+ return x;
+ }
+
+ public int hashCode()
+ {
+ return x.hashCode() ^ super.hashCode();
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof DHPrivateKeyParameters))
+ {
+ return false;
+ }
+
+ DHPrivateKeyParameters other = (DHPrivateKeyParameters)obj;
+
+ return other.getX().equals(this.x) && super.equals(obj);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/DHPublicKeyParameters.java b/core/src/main/java/org/spongycastle/crypto/params/DHPublicKeyParameters.java
new file mode 100644
index 00000000..3fbdd58e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/DHPublicKeyParameters.java
@@ -0,0 +1,41 @@
+package org.spongycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class DHPublicKeyParameters
+ extends DHKeyParameters
+{
+ private BigInteger y;
+
+ public DHPublicKeyParameters(
+ BigInteger y,
+ DHParameters params)
+ {
+ super(false, params);
+
+ this.y = y;
+ }
+
+ public BigInteger getY()
+ {
+ return y;
+ }
+
+ public int hashCode()
+ {
+ return y.hashCode() ^ super.hashCode();
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof DHPublicKeyParameters))
+ {
+ return false;
+ }
+
+ DHPublicKeyParameters other = (DHPublicKeyParameters)obj;
+
+ return other.getY().equals(y) && super.equals(obj);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/DHValidationParameters.java b/core/src/main/java/org/spongycastle/crypto/params/DHValidationParameters.java
new file mode 100644
index 00000000..cf385d0c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/DHValidationParameters.java
@@ -0,0 +1,50 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.util.Arrays;
+
+public class DHValidationParameters
+{
+ private byte[] seed;
+ private int counter;
+
+ public DHValidationParameters(
+ byte[] seed,
+ int counter)
+ {
+ this.seed = seed;
+ this.counter = counter;
+ }
+
+ public int getCounter()
+ {
+ return counter;
+ }
+
+ public byte[] getSeed()
+ {
+ return seed;
+ }
+
+ public boolean equals(
+ Object o)
+ {
+ if (!(o instanceof DHValidationParameters))
+ {
+ return false;
+ }
+
+ DHValidationParameters other = (DHValidationParameters)o;
+
+ if (other.counter != this.counter)
+ {
+ return false;
+ }
+
+ return Arrays.areEqual(this.seed, other.seed);
+ }
+
+ public int hashCode()
+ {
+ return counter ^ Arrays.hashCode(seed);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/DSAKeyGenerationParameters.java b/core/src/main/java/org/spongycastle/crypto/params/DSAKeyGenerationParameters.java
new file mode 100644
index 00000000..eaa8f80d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/DSAKeyGenerationParameters.java
@@ -0,0 +1,25 @@
+package org.spongycastle.crypto.params;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.KeyGenerationParameters;
+
+public class DSAKeyGenerationParameters
+ extends KeyGenerationParameters
+{
+ private DSAParameters params;
+
+ public DSAKeyGenerationParameters(
+ SecureRandom random,
+ DSAParameters params)
+ {
+ super(random, params.getP().bitLength() - 1);
+
+ this.params = params;
+ }
+
+ public DSAParameters getParameters()
+ {
+ return params;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/DSAKeyParameters.java b/core/src/main/java/org/spongycastle/crypto/params/DSAKeyParameters.java
new file mode 100644
index 00000000..8417a4e9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/DSAKeyParameters.java
@@ -0,0 +1,21 @@
+package org.spongycastle.crypto.params;
+
+public class DSAKeyParameters
+ extends AsymmetricKeyParameter
+{
+ private DSAParameters params;
+
+ public DSAKeyParameters(
+ boolean isPrivate,
+ DSAParameters params)
+ {
+ super(isPrivate);
+
+ this.params = params;
+ }
+
+ public DSAParameters getParameters()
+ {
+ return params;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/DSAParameterGenerationParameters.java b/core/src/main/java/org/spongycastle/crypto/params/DSAParameterGenerationParameters.java
new file mode 100644
index 00000000..8822209c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/DSAParameterGenerationParameters.java
@@ -0,0 +1,80 @@
+package org.spongycastle.crypto.params;
+
+import java.security.SecureRandom;
+
+public class DSAParameterGenerationParameters
+{
+ public static final int DIGITAL_SIGNATURE_USAGE = 1;
+ public static final int KEY_ESTABLISHMENT_USAGE = 2;
+
+ private final int l;
+ private final int n;
+ private final int usageIndex;
+ private final int certainty;
+ private final SecureRandom random;
+
+ /**
+ * Construct without a usage index, this will do a random construction of G.
+ *
+ * @param L desired length of prime P in bits (the effective key size).
+ * @param N desired length of prime Q in bits.
+ * @param certainty certainty level for prime number generation.
+ * @param random the source of randomness to use.
+ */
+ public DSAParameterGenerationParameters(
+ int L,
+ int N,
+ int certainty,
+ SecureRandom random)
+ {
+ this(L, N, certainty, random, -1);
+ }
+
+ /**
+ * Construct for a specific usage index - this has the effect of using verifiable canonical generation of G.
+ *
+ * @param L desired length of prime P in bits (the effective key size).
+ * @param N desired length of prime Q in bits.
+ * @param certainty certainty level for prime number generation.
+ * @param random the source of randomness to use.
+ * @param usageIndex a valid usage index.
+ */
+ public DSAParameterGenerationParameters(
+ int L,
+ int N,
+ int certainty,
+ SecureRandom random,
+ int usageIndex)
+ {
+ this.l = L;
+ this.n = N;
+ this.certainty = certainty;
+ this.usageIndex = usageIndex;
+ this.random = random;
+ }
+
+ public int getL()
+ {
+ return l;
+ }
+
+ public int getN()
+ {
+ return n;
+ }
+
+ public int getCertainty()
+ {
+ return certainty;
+ }
+
+ public SecureRandom getRandom()
+ {
+ return random;
+ }
+
+ public int getUsageIndex()
+ {
+ return usageIndex;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/DSAParameters.java b/core/src/main/java/org/spongycastle/crypto/params/DSAParameters.java
new file mode 100644
index 00000000..b1baf067
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/DSAParameters.java
@@ -0,0 +1,74 @@
+package org.spongycastle.crypto.params;
+
+import java.math.BigInteger;
+
+import org.spongycastle.crypto.CipherParameters;
+
+public class DSAParameters
+ implements CipherParameters
+{
+ private BigInteger g;
+ private BigInteger q;
+ private BigInteger p;
+ private DSAValidationParameters validation;
+
+ public DSAParameters(
+ BigInteger p,
+ BigInteger q,
+ BigInteger g)
+ {
+ this.g = g;
+ this.p = p;
+ this.q = q;
+ }
+
+ public DSAParameters(
+ BigInteger p,
+ BigInteger q,
+ BigInteger g,
+ DSAValidationParameters params)
+ {
+ this.g = g;
+ this.p = p;
+ this.q = q;
+ this.validation = params;
+ }
+
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public BigInteger getG()
+ {
+ return g;
+ }
+
+ public DSAValidationParameters getValidationParameters()
+ {
+ return validation;
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof DSAParameters))
+ {
+ return false;
+ }
+
+ DSAParameters pm = (DSAParameters)obj;
+
+ return (pm.getP().equals(p) && pm.getQ().equals(q) && pm.getG().equals(g));
+ }
+
+ public int hashCode()
+ {
+ return getP().hashCode() ^ getQ().hashCode() ^ getG().hashCode();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/DSAPrivateKeyParameters.java b/core/src/main/java/org/spongycastle/crypto/params/DSAPrivateKeyParameters.java
new file mode 100644
index 00000000..bd1d9681
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/DSAPrivateKeyParameters.java
@@ -0,0 +1,23 @@
+package org.spongycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class DSAPrivateKeyParameters
+ extends DSAKeyParameters
+{
+ private BigInteger x;
+
+ public DSAPrivateKeyParameters(
+ BigInteger x,
+ DSAParameters params)
+ {
+ super(true, params);
+
+ this.x = x;
+ }
+
+ public BigInteger getX()
+ {
+ return x;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/DSAPublicKeyParameters.java b/core/src/main/java/org/spongycastle/crypto/params/DSAPublicKeyParameters.java
new file mode 100644
index 00000000..cd244b9d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/DSAPublicKeyParameters.java
@@ -0,0 +1,23 @@
+package org.spongycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class DSAPublicKeyParameters
+ extends DSAKeyParameters
+{
+ private BigInteger y;
+
+ public DSAPublicKeyParameters(
+ BigInteger y,
+ DSAParameters params)
+ {
+ super(false, params);
+
+ this.y = y;
+ }
+
+ public BigInteger getY()
+ {
+ return y;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/DSAValidationParameters.java b/core/src/main/java/org/spongycastle/crypto/params/DSAValidationParameters.java
new file mode 100644
index 00000000..ca7c6cf6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/DSAValidationParameters.java
@@ -0,0 +1,65 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.util.Arrays;
+
+public class DSAValidationParameters
+{
+ private int usageIndex;
+ private byte[] seed;
+ private int counter;
+
+ public DSAValidationParameters(
+ byte[] seed,
+ int counter)
+ {
+ this(seed, counter, -1);
+ }
+
+ public DSAValidationParameters(
+ byte[] seed,
+ int counter,
+ int usageIndex)
+ {
+ this.seed = seed;
+ this.counter = counter;
+ this.usageIndex = usageIndex;
+ }
+
+ public int getCounter()
+ {
+ return counter;
+ }
+
+ public byte[] getSeed()
+ {
+ return seed;
+ }
+
+ public int getUsageIndex()
+ {
+ return usageIndex;
+ }
+
+ public int hashCode()
+ {
+ return counter ^ Arrays.hashCode(seed);
+ }
+
+ public boolean equals(
+ Object o)
+ {
+ if (!(o instanceof DSAValidationParameters))
+ {
+ return false;
+ }
+
+ DSAValidationParameters other = (DSAValidationParameters)o;
+
+ if (other.counter != this.counter)
+ {
+ return false;
+ }
+
+ return Arrays.areEqual(this.seed, other.seed);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/ECDomainParameters.java b/core/src/main/java/org/spongycastle/crypto/params/ECDomainParameters.java
new file mode 100644
index 00000000..57daaee3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/ECDomainParameters.java
@@ -0,0 +1,74 @@
+package org.spongycastle.crypto.params;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.ec.ECConstants;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.util.Arrays;
+
+public class ECDomainParameters
+ implements ECConstants
+{
+ private ECCurve curve;
+ private byte[] seed;
+ private ECPoint G;
+ private BigInteger n;
+ private BigInteger h;
+
+ public ECDomainParameters(
+ ECCurve curve,
+ ECPoint G,
+ BigInteger n)
+ {
+ this(curve, G, n, ONE, null);
+ }
+
+ public ECDomainParameters(
+ ECCurve curve,
+ ECPoint G,
+ BigInteger n,
+ BigInteger h)
+ {
+ this(curve, G, n, h, null);
+ }
+
+ public ECDomainParameters(
+ ECCurve curve,
+ ECPoint G,
+ BigInteger n,
+ BigInteger h,
+ byte[] seed)
+ {
+ this.curve = curve;
+ this.G = G.normalize();
+ this.n = n;
+ this.h = h;
+ this.seed = seed;
+ }
+
+ public ECCurve getCurve()
+ {
+ return curve;
+ }
+
+ public ECPoint getG()
+ {
+ return G;
+ }
+
+ public BigInteger getN()
+ {
+ return n;
+ }
+
+ public BigInteger getH()
+ {
+ return h;
+ }
+
+ public byte[] getSeed()
+ {
+ return Arrays.clone(seed);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/ECKeyGenerationParameters.java b/core/src/main/java/org/spongycastle/crypto/params/ECKeyGenerationParameters.java
new file mode 100644
index 00000000..4675c65a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/ECKeyGenerationParameters.java
@@ -0,0 +1,25 @@
+package org.spongycastle.crypto.params;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.KeyGenerationParameters;
+
+public class ECKeyGenerationParameters
+ extends KeyGenerationParameters
+{
+ private ECDomainParameters domainParams;
+
+ public ECKeyGenerationParameters(
+ ECDomainParameters domainParams,
+ SecureRandom random)
+ {
+ super(random, domainParams.getN().bitLength());
+
+ this.domainParams = domainParams;
+ }
+
+ public ECDomainParameters getDomainParameters()
+ {
+ return domainParams;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/ECKeyParameters.java b/core/src/main/java/org/spongycastle/crypto/params/ECKeyParameters.java
new file mode 100644
index 00000000..480a969f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/ECKeyParameters.java
@@ -0,0 +1,21 @@
+package org.spongycastle.crypto.params;
+
+public class ECKeyParameters
+ extends AsymmetricKeyParameter
+{
+ ECDomainParameters params;
+
+ protected ECKeyParameters(
+ boolean isPrivate,
+ ECDomainParameters params)
+ {
+ super(isPrivate);
+
+ this.params = params;
+ }
+
+ public ECDomainParameters getParameters()
+ {
+ return params;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/ECNamedDomainParameters.java b/core/src/main/java/org/spongycastle/crypto/params/ECNamedDomainParameters.java
new file mode 100644
index 00000000..b6bb23c1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/ECNamedDomainParameters.java
@@ -0,0 +1,35 @@
+package org.spongycastle.crypto.params;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECPoint;
+
+public class ECNamedDomainParameters
+ extends ECDomainParameters
+{
+ private ASN1ObjectIdentifier name;
+
+ public ECNamedDomainParameters(ASN1ObjectIdentifier name, ECCurve curve, ECPoint G, BigInteger n)
+ {
+ this(name, curve, G, n, null, null);
+ }
+
+ public ECNamedDomainParameters(ASN1ObjectIdentifier name, ECCurve curve, ECPoint G, BigInteger n, BigInteger h)
+ {
+ this(name, curve, G, n, h, null);
+ }
+
+ public ECNamedDomainParameters(ASN1ObjectIdentifier name, ECCurve curve, ECPoint G, BigInteger n, BigInteger h, byte[] seed)
+ {
+ super(curve, G, n, h, seed);
+
+ this.name = name;
+ }
+
+ public ASN1ObjectIdentifier getName()
+ {
+ return name;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/ECPrivateKeyParameters.java b/core/src/main/java/org/spongycastle/crypto/params/ECPrivateKeyParameters.java
new file mode 100644
index 00000000..484ca232
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/ECPrivateKeyParameters.java
@@ -0,0 +1,22 @@
+package org.spongycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class ECPrivateKeyParameters
+ extends ECKeyParameters
+{
+ BigInteger d;
+
+ public ECPrivateKeyParameters(
+ BigInteger d,
+ ECDomainParameters params)
+ {
+ super(true, params);
+ this.d = d;
+ }
+
+ public BigInteger getD()
+ {
+ return d;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/ECPublicKeyParameters.java b/core/src/main/java/org/spongycastle/crypto/params/ECPublicKeyParameters.java
new file mode 100644
index 00000000..deab005c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/ECPublicKeyParameters.java
@@ -0,0 +1,22 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.math.ec.ECPoint;
+
+public class ECPublicKeyParameters
+ extends ECKeyParameters
+{
+ ECPoint Q;
+
+ public ECPublicKeyParameters(
+ ECPoint Q,
+ ECDomainParameters params)
+ {
+ super(false, params);
+ this.Q = Q.normalize();
+ }
+
+ public ECPoint getQ()
+ {
+ return Q;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/ElGamalKeyGenerationParameters.java b/core/src/main/java/org/spongycastle/crypto/params/ElGamalKeyGenerationParameters.java
new file mode 100644
index 00000000..c1741ec1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/ElGamalKeyGenerationParameters.java
@@ -0,0 +1,30 @@
+package org.spongycastle.crypto.params;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.KeyGenerationParameters;
+
+public class ElGamalKeyGenerationParameters
+ extends KeyGenerationParameters
+{
+ private ElGamalParameters params;
+
+ public ElGamalKeyGenerationParameters(
+ SecureRandom random,
+ ElGamalParameters params)
+ {
+ super(random, getStrength(params));
+
+ this.params = params;
+ }
+
+ public ElGamalParameters getParameters()
+ {
+ return params;
+ }
+
+ static int getStrength(ElGamalParameters params)
+ {
+ return params.getL() != 0 ? params.getL() : params.getP().bitLength();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/ElGamalKeyParameters.java b/core/src/main/java/org/spongycastle/crypto/params/ElGamalKeyParameters.java
new file mode 100644
index 00000000..83c00de6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/ElGamalKeyParameters.java
@@ -0,0 +1,47 @@
+package org.spongycastle.crypto.params;
+
+
+public class ElGamalKeyParameters
+ extends AsymmetricKeyParameter
+{
+ private ElGamalParameters params;
+
+ protected ElGamalKeyParameters(
+ boolean isPrivate,
+ ElGamalParameters params)
+ {
+ super(isPrivate);
+
+ this.params = params;
+ }
+
+ public ElGamalParameters getParameters()
+ {
+ return params;
+ }
+
+ public int hashCode()
+ {
+ return (params != null) ? params.hashCode() : 0;
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof ElGamalKeyParameters))
+ {
+ return false;
+ }
+
+ ElGamalKeyParameters dhKey = (ElGamalKeyParameters)obj;
+
+ if (params == null)
+ {
+ return dhKey.getParameters() == null;
+ }
+ else
+ {
+ return params.equals(dhKey.getParameters());
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/ElGamalParameters.java b/core/src/main/java/org/spongycastle/crypto/params/ElGamalParameters.java
new file mode 100644
index 00000000..60c484b1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/ElGamalParameters.java
@@ -0,0 +1,69 @@
+package org.spongycastle.crypto.params;
+
+import java.math.BigInteger;
+
+import org.spongycastle.crypto.CipherParameters;
+
+public class ElGamalParameters
+ implements CipherParameters
+{
+ private BigInteger g;
+ private BigInteger p;
+ private int l;
+
+ public ElGamalParameters(
+ BigInteger p,
+ BigInteger g)
+ {
+ this(p, g, 0);
+ }
+
+ public ElGamalParameters(
+ BigInteger p,
+ BigInteger g,
+ int l)
+ {
+ this.g = g;
+ this.p = p;
+ this.l = l;
+ }
+
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ /**
+ * return the generator - g
+ */
+ public BigInteger getG()
+ {
+ return g;
+ }
+
+ /**
+ * return private value limit - l
+ */
+ public int getL()
+ {
+ return l;
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof ElGamalParameters))
+ {
+ return false;
+ }
+
+ ElGamalParameters pm = (ElGamalParameters)obj;
+
+ return pm.getP().equals(p) && pm.getG().equals(g) && pm.getL() == l;
+ }
+
+ public int hashCode()
+ {
+ return (getP().hashCode() ^ getG().hashCode()) + l;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/ElGamalPrivateKeyParameters.java b/core/src/main/java/org/spongycastle/crypto/params/ElGamalPrivateKeyParameters.java
new file mode 100644
index 00000000..51095891
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/ElGamalPrivateKeyParameters.java
@@ -0,0 +1,46 @@
+package org.spongycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class ElGamalPrivateKeyParameters
+ extends ElGamalKeyParameters
+{
+ private BigInteger x;
+
+ public ElGamalPrivateKeyParameters(
+ BigInteger x,
+ ElGamalParameters params)
+ {
+ super(true, params);
+
+ this.x = x;
+ }
+
+ public BigInteger getX()
+ {
+ return x;
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof ElGamalPrivateKeyParameters))
+ {
+ return false;
+ }
+
+ ElGamalPrivateKeyParameters pKey = (ElGamalPrivateKeyParameters)obj;
+
+ if (!pKey.getX().equals(x))
+ {
+ return false;
+ }
+
+ return super.equals(obj);
+ }
+
+ public int hashCode()
+ {
+ return getX().hashCode();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/ElGamalPublicKeyParameters.java b/core/src/main/java/org/spongycastle/crypto/params/ElGamalPublicKeyParameters.java
new file mode 100644
index 00000000..ae21f8e8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/ElGamalPublicKeyParameters.java
@@ -0,0 +1,41 @@
+package org.spongycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class ElGamalPublicKeyParameters
+ extends ElGamalKeyParameters
+{
+ private BigInteger y;
+
+ public ElGamalPublicKeyParameters(
+ BigInteger y,
+ ElGamalParameters params)
+ {
+ super(false, params);
+
+ this.y = y;
+ }
+
+ public BigInteger getY()
+ {
+ return y;
+ }
+
+ public int hashCode()
+ {
+ return y.hashCode() ^ super.hashCode();
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof ElGamalPublicKeyParameters))
+ {
+ return false;
+ }
+
+ ElGamalPublicKeyParameters other = (ElGamalPublicKeyParameters)obj;
+
+ return other.getY().equals(y) && super.equals(obj);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/GOST3410KeyGenerationParameters.java b/core/src/main/java/org/spongycastle/crypto/params/GOST3410KeyGenerationParameters.java
new file mode 100644
index 00000000..2a32389f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/GOST3410KeyGenerationParameters.java
@@ -0,0 +1,25 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.KeyGenerationParameters;
+
+import java.security.SecureRandom;
+
+public class GOST3410KeyGenerationParameters
+ extends KeyGenerationParameters
+{
+ private GOST3410Parameters params;
+
+ public GOST3410KeyGenerationParameters(
+ SecureRandom random,
+ GOST3410Parameters params)
+ {
+ super(random, params.getP().bitLength() - 1);
+
+ this.params = params;
+ }
+
+ public GOST3410Parameters getParameters()
+ {
+ return params;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/GOST3410KeyParameters.java b/core/src/main/java/org/spongycastle/crypto/params/GOST3410KeyParameters.java
new file mode 100644
index 00000000..b9a6ee7e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/GOST3410KeyParameters.java
@@ -0,0 +1,21 @@
+package org.spongycastle.crypto.params;
+
+public class GOST3410KeyParameters
+ extends AsymmetricKeyParameter
+{
+ private GOST3410Parameters params;
+
+ public GOST3410KeyParameters(
+ boolean isPrivate,
+ GOST3410Parameters params)
+ {
+ super(isPrivate);
+
+ this.params = params;
+ }
+
+ public GOST3410Parameters getParameters()
+ {
+ return params;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/GOST3410Parameters.java b/core/src/main/java/org/spongycastle/crypto/params/GOST3410Parameters.java
new file mode 100644
index 00000000..ad29ed65
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/GOST3410Parameters.java
@@ -0,0 +1,74 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.CipherParameters;
+
+import java.math.BigInteger;
+
+public class GOST3410Parameters
+ implements CipherParameters
+{
+ private BigInteger p;
+ private BigInteger q;
+ private BigInteger a;
+ private GOST3410ValidationParameters validation;
+
+ public GOST3410Parameters(
+ BigInteger p,
+ BigInteger q,
+ BigInteger a)
+ {
+ this.p = p;
+ this.q = q;
+ this.a = a;
+ }
+
+ public GOST3410Parameters(
+ BigInteger p,
+ BigInteger q,
+ BigInteger a,
+ GOST3410ValidationParameters params)
+ {
+ this.a = a;
+ this.p = p;
+ this.q = q;
+ this.validation = params;
+ }
+
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public BigInteger getA()
+ {
+ return a;
+ }
+
+ public GOST3410ValidationParameters getValidationParameters()
+ {
+ return validation;
+ }
+
+ public int hashCode()
+ {
+ return p.hashCode() ^ q.hashCode() ^ a.hashCode();
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof GOST3410Parameters))
+ {
+ return false;
+ }
+
+ GOST3410Parameters pm = (GOST3410Parameters)obj;
+
+ return (pm.getP().equals(p) && pm.getQ().equals(q) && pm.getA().equals(a));
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/GOST3410PrivateKeyParameters.java b/core/src/main/java/org/spongycastle/crypto/params/GOST3410PrivateKeyParameters.java
new file mode 100644
index 00000000..531870e2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/GOST3410PrivateKeyParameters.java
@@ -0,0 +1,23 @@
+package org.spongycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class GOST3410PrivateKeyParameters
+ extends GOST3410KeyParameters
+{
+ private BigInteger x;
+
+ public GOST3410PrivateKeyParameters(
+ BigInteger x,
+ GOST3410Parameters params)
+ {
+ super(true, params);
+
+ this.x = x;
+ }
+
+ public BigInteger getX()
+ {
+ return x;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/GOST3410PublicKeyParameters.java b/core/src/main/java/org/spongycastle/crypto/params/GOST3410PublicKeyParameters.java
new file mode 100644
index 00000000..b0b05899
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/GOST3410PublicKeyParameters.java
@@ -0,0 +1,23 @@
+package org.spongycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class GOST3410PublicKeyParameters
+ extends GOST3410KeyParameters
+{
+ private BigInteger y;
+
+ public GOST3410PublicKeyParameters(
+ BigInteger y,
+ GOST3410Parameters params)
+ {
+ super(false, params);
+
+ this.y = y;
+ }
+
+ public BigInteger getY()
+ {
+ return y;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/GOST3410ValidationParameters.java b/core/src/main/java/org/spongycastle/crypto/params/GOST3410ValidationParameters.java
new file mode 100644
index 00000000..46f893ca
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/GOST3410ValidationParameters.java
@@ -0,0 +1,84 @@
+package org.spongycastle.crypto.params;
+
+public class GOST3410ValidationParameters
+{
+ private int x0;
+ private int c;
+ private long x0L;
+ private long cL;
+
+
+ public GOST3410ValidationParameters(
+ int x0,
+ int c)
+ {
+ this.x0 = x0;
+ this.c = c;
+ }
+
+ public GOST3410ValidationParameters(
+ long x0L,
+ long cL)
+ {
+ this.x0L = x0L;
+ this.cL = cL;
+ }
+
+ public int getC()
+ {
+ return c;
+ }
+
+ public int getX0()
+ {
+ return x0;
+ }
+
+ public long getCL()
+ {
+ return cL;
+ }
+
+ public long getX0L()
+ {
+ return x0L;
+ }
+
+ public boolean equals(
+ Object o)
+ {
+ if (!(o instanceof GOST3410ValidationParameters))
+ {
+ return false;
+ }
+
+ GOST3410ValidationParameters other = (GOST3410ValidationParameters)o;
+
+ if (other.c != this.c)
+ {
+ return false;
+ }
+
+ if (other.x0 != this.x0)
+ {
+ return false;
+ }
+
+ if (other.cL != this.cL)
+ {
+ return false;
+ }
+
+ if (other.x0L != this.x0L)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ public int hashCode()
+ {
+ return x0 ^ c ^ (int) x0L ^ (int)(x0L >> 32) ^ (int) cL ^ (int)(cL >> 32);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/HKDFParameters.java b/core/src/main/java/org/spongycastle/crypto/params/HKDFParameters.java
new file mode 100644
index 00000000..94595a15
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/HKDFParameters.java
@@ -0,0 +1,123 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.DerivationParameters;
+import org.spongycastle.util.Arrays;
+
+/**
+ * Parameter class for the HKDFBytesGenerator class.
+ */
+public class HKDFParameters
+ implements DerivationParameters
+{
+ private final byte[] ikm;
+ private final boolean skipExpand;
+ private final byte[] salt;
+ private final byte[] info;
+
+ private HKDFParameters(final byte[] ikm, final boolean skip,
+ final byte[] salt, final byte[] info)
+ {
+ if (ikm == null)
+ {
+ throw new IllegalArgumentException(
+ "IKM (input keying material) should not be null");
+ }
+
+ this.ikm = Arrays.clone(ikm);
+
+ this.skipExpand = skip;
+
+ if (salt == null || salt.length == 0)
+ {
+ this.salt = null;
+ }
+ else
+ {
+ this.salt = Arrays.clone(salt);
+ }
+
+ if (info == null)
+ {
+ this.info = new byte[0];
+ }
+ else
+ {
+ this.info = Arrays.clone(info);
+ }
+ }
+
+ /**
+ * Generates parameters for HKDF, specifying both the optional salt and
+ * optional info. Step 1: Extract won't be skipped.
+ *
+ * @param ikm the input keying material or seed
+ * @param salt the salt to use, may be null for a salt for hashLen zeros
+ * @param info the info to use, may be null for an info field of zero bytes
+ */
+ public HKDFParameters(final byte[] ikm, final byte[] salt, final byte[] info)
+ {
+ this(ikm, false, salt, info);
+ }
+
+ /**
+ * Factory method that makes the HKDF skip the extract part of the key
+ * derivation function.
+ *
+ * @param ikm the input keying material or seed, directly used for step 2:
+ * Expand
+ * @param info the info to use, may be null for an info field of zero bytes
+ * @return HKDFParameters that makes the implementation skip step 1
+ */
+ public static HKDFParameters skipExtractParameters(final byte[] ikm,
+ final byte[] info)
+ {
+
+ return new HKDFParameters(ikm, true, null, info);
+ }
+
+ public static HKDFParameters defaultParameters(final byte[] ikm)
+ {
+ return new HKDFParameters(ikm, false, null, null);
+ }
+
+ /**
+ * Returns the input keying material or seed.
+ *
+ * @return the keying material
+ */
+ public byte[] getIKM()
+ {
+ return Arrays.clone(ikm);
+ }
+
+ /**
+ * Returns if step 1: extract has to be skipped or not
+ *
+ * @return true for skipping, false for no skipping of step 1
+ */
+ public boolean skipExtract()
+ {
+ return skipExpand;
+ }
+
+ /**
+ * Returns the salt, or null if the salt should be generated as a byte array
+ * of HashLen zeros.
+ *
+ * @return the salt, or null
+ */
+ public byte[] getSalt()
+ {
+ return Arrays.clone(salt);
+ }
+
+ /**
+ * Returns the info field, which may be empty (null is converted to empty).
+ *
+ * @return the info field, never null
+ */
+ public byte[] getInfo()
+ {
+ return Arrays.clone(info);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/IESParameters.java b/core/src/main/java/org/spongycastle/crypto/params/IESParameters.java
new file mode 100644
index 00000000..419d135d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/IESParameters.java
@@ -0,0 +1,44 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.CipherParameters;
+
+/**
+ * parameters for using an integrated cipher in stream mode.
+ */
+public class IESParameters
+ implements CipherParameters
+{
+ private byte[] derivation;
+ private byte[] encoding;
+ private int macKeySize;
+
+ /**
+ * @param derivation the derivation parameter for the KDF function.
+ * @param encoding the encoding parameter for the KDF function.
+ * @param macKeySize the size of the MAC key (in bits).
+ */
+ public IESParameters(
+ byte[] derivation,
+ byte[] encoding,
+ int macKeySize)
+ {
+ this.derivation = derivation;
+ this.encoding = encoding;
+ this.macKeySize = macKeySize;
+ }
+
+ public byte[] getDerivationV()
+ {
+ return derivation;
+ }
+
+ public byte[] getEncodingV()
+ {
+ return encoding;
+ }
+
+ public int getMacKeySize()
+ {
+ return macKeySize;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/IESWithCipherParameters.java b/core/src/main/java/org/spongycastle/crypto/params/IESWithCipherParameters.java
new file mode 100644
index 00000000..68bb2d62
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/IESWithCipherParameters.java
@@ -0,0 +1,30 @@
+package org.spongycastle.crypto.params;
+
+
+public class IESWithCipherParameters
+ extends IESParameters
+{
+ private int cipherKeySize;
+
+ /**
+ * @param derivation the derivation parameter for the KDF function.
+ * @param encoding the encoding parameter for the KDF function.
+ * @param macKeySize the size of the MAC key (in bits).
+ * @param cipherKeySize the size of the associated Cipher key (in bits).
+ */
+ public IESWithCipherParameters(
+ byte[] derivation,
+ byte[] encoding,
+ int macKeySize,
+ int cipherKeySize)
+ {
+ super(derivation, encoding, macKeySize);
+
+ this.cipherKeySize = cipherKeySize;
+ }
+
+ public int getCipherKeySize()
+ {
+ return cipherKeySize;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/ISO18033KDFParameters.java b/core/src/main/java/org/spongycastle/crypto/params/ISO18033KDFParameters.java
new file mode 100644
index 00000000..c6e1d999
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/ISO18033KDFParameters.java
@@ -0,0 +1,23 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.DerivationParameters;
+
+/**
+ * parameters for Key derivation functions for ISO-18033
+ */
+public class ISO18033KDFParameters
+ implements DerivationParameters
+{
+ byte[] seed;
+
+ public ISO18033KDFParameters(
+ byte[] seed)
+ {
+ this.seed = seed;
+ }
+
+ public byte[] getSeed()
+ {
+ return seed;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/KDFCounterParameters.java b/core/src/main/java/org/spongycastle/crypto/params/KDFCounterParameters.java
new file mode 100644
index 00000000..02ee9142
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/KDFCounterParameters.java
@@ -0,0 +1,120 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.DerivationParameters;
+import org.spongycastle.util.Arrays;
+
+/**
+ * This KDF has been defined by the publicly available NIST SP 800-108 specification.
+ * NIST SP800-108 allows for alternative orderings of the input fields, meaning that the input can be formated in multiple ways.
+ * There are 3 supported formats: - Below [i]_2 is a counter of r-bits length concatenated to the fixedInputData.
+ * <ul>
+ * <li>1: K(i) := PRF( KI, [i]_2 || Label || 0x00 || Context || [L]_2 ) with the counter at the very beginning of the fixedInputData (The default implementation has this format)</li>
+ * <li>2: K(i) := PRF( KI, Label || 0x00 || Context || [L]_2 || [i]_2 ) with the counter at the very end of the fixedInputData</li>
+ * <li>3a: K(i) := PRF( KI, Label || 0x00 || [i]_2 || Context || [L]_2 ) OR:</li>
+ * <li>3b: K(i) := PRF( KI, Label || 0x00 || [i]_2 || [L]_2 || Context ) OR:</li>
+ * <li>3c: K(i) := PRF( KI, Label || [i]_2 || 0x00 || Context || [L]_2 ) etc... with the counter somewhere in the 'middle' of the fixedInputData.</li>
+ * </ul>
+ * <p>
+ * This function must be called with the following KDFCounterParameters():
+ * - KI <br/>
+ * - The part of the fixedInputData that comes BEFORE the counter OR null <br/>
+ * - the part of the fixedInputData that comes AFTER the counter OR null <br/>
+ * - the length of the counter in bits (not bytes) <br/>
+ * </p>
+ * Resulting function calls assuming an 8 bit counter.
+ * <ul>
+ * <li>1. KDFCounterParameters(ki, null, "Label || 0x00 || Context || [L]_2]", 8); </li>
+ * <li>2. KDFCounterParameters(ki, "Label || 0x00 || Context || [L]_2]", null, 8); </li>
+ * <li>3a. KDFCounterParameters(ki, "Label || 0x00", "Context || [L]_2]", 8); </li>
+ * <li>3b. KDFCounterParameters(ki, "Label || 0x00", "[L]_2] || Context", 8);</li>
+ * <li>3c. KDFCounterParameters(ki, "Label", "0x00 || Context || [L]_2]", 8); </li>
+ * </ul>
+ */
+public final class KDFCounterParameters
+ implements DerivationParameters
+{
+
+ private byte[] ki;
+ private byte[] fixedInputDataCounterPrefix;
+ private byte[] fixedInputDataCounterSuffix;
+ private int r;
+
+ /**
+ * Base constructor - suffix fixed input data only.
+ *
+ * @param ki the KDF seed
+ * @param fixedInputDataCounterSuffix fixed input data to follow counter.
+ * @param r length of the counter in bits.
+ */
+ public KDFCounterParameters(byte[] ki, byte[] fixedInputDataCounterSuffix, int r)
+ {
+ this(ki, null, fixedInputDataCounterSuffix, r);
+ }
+
+ /**
+ * Base constructor - prefix and suffix fixed input data.
+ *
+ * @param ki the KDF seed
+ * @param fixedInputDataCounterPrefix fixed input data to precede counter
+ * @param fixedInputDataCounterSuffix fixed input data to follow counter.
+ * @param r length of the counter in bits.
+ */
+ public KDFCounterParameters(byte[] ki, byte[] fixedInputDataCounterPrefix, byte[] fixedInputDataCounterSuffix, int r)
+ {
+ if (ki == null)
+ {
+ throw new IllegalArgumentException("A KDF requires Ki (a seed) as input");
+ }
+ this.ki = Arrays.clone(ki);
+
+ if (fixedInputDataCounterPrefix == null)
+ {
+ this.fixedInputDataCounterPrefix = new byte[0];
+ }
+ else
+ {
+ this.fixedInputDataCounterPrefix = Arrays.clone(fixedInputDataCounterPrefix);
+ }
+
+ if (fixedInputDataCounterSuffix == null)
+ {
+ this.fixedInputDataCounterSuffix = new byte[0];
+ }
+ else
+ {
+ this.fixedInputDataCounterSuffix = Arrays.clone(fixedInputDataCounterSuffix);
+ }
+
+ 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()
+ {
+ //Retained for backwards compatibility
+ return Arrays.clone(fixedInputDataCounterSuffix);
+ }
+
+ public byte[] getFixedInputDataCounterPrefix()
+ {
+ return Arrays.clone(fixedInputDataCounterPrefix);
+ }
+
+ public byte[] getFixedInputDataCounterSuffix()
+ {
+ return Arrays.clone(fixedInputDataCounterSuffix);
+ }
+
+ public int getR()
+ {
+ return r;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/KDFDoublePipelineIterationParameters.java b/core/src/main/java/org/spongycastle/crypto/params/KDFDoublePipelineIterationParameters.java
new file mode 100644
index 00000000..30fe6138
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/KDFDoublePipelineIterationParameters.java
@@ -0,0 +1,80 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.DerivationParameters;
+import org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/params/KDFFeedbackParameters.java b/core/src/main/java/org/spongycastle/crypto/params/KDFFeedbackParameters.java
new file mode 100644
index 00000000..44d1e964
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/KDFFeedbackParameters.java
@@ -0,0 +1,96 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.DerivationParameters;
+import org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/params/KDFParameters.java b/core/src/main/java/org/spongycastle/crypto/params/KDFParameters.java
new file mode 100644
index 00000000..60010615
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/KDFParameters.java
@@ -0,0 +1,31 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.DerivationParameters;
+
+/**
+ * parameters for Key derivation functions for IEEE P1363a
+ */
+public class KDFParameters
+ implements DerivationParameters
+{
+ byte[] iv;
+ byte[] shared;
+
+ public KDFParameters(
+ byte[] shared,
+ byte[] iv)
+ {
+ this.shared = shared;
+ this.iv = iv;
+ }
+
+ public byte[] getSharedSecret()
+ {
+ return shared;
+ }
+
+ public byte[] getIV()
+ {
+ return iv;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/KeyParameter.java b/core/src/main/java/org/spongycastle/crypto/params/KeyParameter.java
new file mode 100644
index 00000000..079e136b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/KeyParameter.java
@@ -0,0 +1,30 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.CipherParameters;
+
+public class KeyParameter
+ implements CipherParameters
+{
+ private byte[] key;
+
+ public KeyParameter(
+ byte[] key)
+ {
+ this(key, 0, key.length);
+ }
+
+ public KeyParameter(
+ byte[] key,
+ int keyOff,
+ int keyLen)
+ {
+ this.key = new byte[keyLen];
+
+ System.arraycopy(key, keyOff, this.key, 0, keyLen);
+ }
+
+ public byte[] getKey()
+ {
+ return key;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/MGFParameters.java b/core/src/main/java/org/spongycastle/crypto/params/MGFParameters.java
new file mode 100644
index 00000000..082e37cd
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/MGFParameters.java
@@ -0,0 +1,32 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.DerivationParameters;
+
+/**
+ * parameters for mask derivation functions.
+ */
+public class MGFParameters
+ implements DerivationParameters
+{
+ byte[] seed;
+
+ public MGFParameters(
+ byte[] seed)
+ {
+ this(seed, 0, seed.length);
+ }
+
+ public MGFParameters(
+ byte[] seed,
+ int off,
+ int len)
+ {
+ this.seed = new byte[len];
+ System.arraycopy(seed, off, this.seed, 0, len);
+ }
+
+ public byte[] getSeed()
+ {
+ return seed;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/MQVPrivateParameters.java b/core/src/main/java/org/spongycastle/crypto/params/MQVPrivateParameters.java
new file mode 100644
index 00000000..ae917ab8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/MQVPrivateParameters.java
@@ -0,0 +1,43 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.CipherParameters;
+
+public class MQVPrivateParameters
+ implements CipherParameters
+{
+ private ECPrivateKeyParameters staticPrivateKey;
+ private ECPrivateKeyParameters ephemeralPrivateKey;
+ private ECPublicKeyParameters ephemeralPublicKey;
+
+ public MQVPrivateParameters(
+ ECPrivateKeyParameters staticPrivateKey,
+ ECPrivateKeyParameters ephemeralPrivateKey)
+ {
+ this(staticPrivateKey, ephemeralPrivateKey, null);
+ }
+
+ public MQVPrivateParameters(
+ ECPrivateKeyParameters staticPrivateKey,
+ ECPrivateKeyParameters ephemeralPrivateKey,
+ ECPublicKeyParameters ephemeralPublicKey)
+ {
+ this.staticPrivateKey = staticPrivateKey;
+ this.ephemeralPrivateKey = ephemeralPrivateKey;
+ this.ephemeralPublicKey = ephemeralPublicKey;
+ }
+
+ public ECPrivateKeyParameters getStaticPrivateKey()
+ {
+ return staticPrivateKey;
+ }
+
+ public ECPrivateKeyParameters getEphemeralPrivateKey()
+ {
+ return ephemeralPrivateKey;
+ }
+
+ public ECPublicKeyParameters getEphemeralPublicKey()
+ {
+ return ephemeralPublicKey;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/MQVPublicParameters.java b/core/src/main/java/org/spongycastle/crypto/params/MQVPublicParameters.java
new file mode 100644
index 00000000..9f6f67de
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/MQVPublicParameters.java
@@ -0,0 +1,28 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.CipherParameters;
+
+public class MQVPublicParameters
+ implements CipherParameters
+{
+ private ECPublicKeyParameters staticPublicKey;
+ private ECPublicKeyParameters ephemeralPublicKey;
+
+ public MQVPublicParameters(
+ ECPublicKeyParameters staticPublicKey,
+ ECPublicKeyParameters ephemeralPublicKey)
+ {
+ this.staticPublicKey = staticPublicKey;
+ this.ephemeralPublicKey = ephemeralPublicKey;
+ }
+
+ public ECPublicKeyParameters getStaticPublicKey()
+ {
+ return staticPublicKey;
+ }
+
+ public ECPublicKeyParameters getEphemeralPublicKey()
+ {
+ return ephemeralPublicKey;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/NaccacheSternKeyGenerationParameters.java b/core/src/main/java/org/spongycastle/crypto/params/NaccacheSternKeyGenerationParameters.java
new file mode 100644
index 00000000..c0b5998b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/NaccacheSternKeyGenerationParameters.java
@@ -0,0 +1,97 @@
+package org.spongycastle.crypto.params;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.KeyGenerationParameters;
+
+/**
+ * Parameters for NaccacheStern public private key generation. For details on
+ * this cipher, please see
+ *
+ * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+ */
+public class NaccacheSternKeyGenerationParameters extends KeyGenerationParameters
+{
+
+ // private BigInteger publicExponent;
+ private int certainty;
+
+ private int cntSmallPrimes;
+
+ private boolean debug = false;
+
+ /**
+ * Parameters for generating a NaccacheStern KeyPair.
+ *
+ * @param random
+ * The source of randomness
+ * @param strength
+ * The desired strength of the Key in Bits
+ * @param certainty
+ * the probability that the generated primes are not really prime
+ * as integer: 2^(-certainty) is then the probability
+ * @param cntSmallPrimes
+ * How many small key factors are desired
+ */
+ public NaccacheSternKeyGenerationParameters(SecureRandom random, int strength, int certainty, int cntSmallPrimes)
+ {
+ this(random, strength, certainty, cntSmallPrimes, false);
+ }
+
+ /**
+ * Parameters for a NaccacheStern KeyPair.
+ *
+ * @param random
+ * The source of randomness
+ * @param strength
+ * The desired strength of the Key in Bits
+ * @param certainty
+ * the probability that the generated primes are not really prime
+ * as integer: 2^(-certainty) is then the probability
+ * @param cntSmallPrimes
+ * How many small key factors are desired
+ * @param debug
+ * Turn debugging on or off (reveals secret information, use with
+ * caution)
+ */
+ public NaccacheSternKeyGenerationParameters(SecureRandom random,
+ int strength, int certainty, int cntSmallPrimes, boolean debug)
+ {
+ super(random, strength);
+
+ this.certainty = certainty;
+ if (cntSmallPrimes % 2 == 1)
+ {
+ throw new IllegalArgumentException("cntSmallPrimes must be a multiple of 2");
+ }
+ if (cntSmallPrimes < 30)
+ {
+ throw new IllegalArgumentException("cntSmallPrimes must be >= 30 for security reasons");
+ }
+ this.cntSmallPrimes = cntSmallPrimes;
+
+ this.debug = debug;
+ }
+
+ /**
+ * @return Returns the certainty.
+ */
+ public int getCertainty()
+ {
+ return certainty;
+ }
+
+ /**
+ * @return Returns the cntSmallPrimes.
+ */
+ public int getCntSmallPrimes()
+ {
+ return cntSmallPrimes;
+ }
+
+ public boolean isDebug()
+ {
+ return debug;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/NaccacheSternKeyParameters.java b/core/src/main/java/org/spongycastle/crypto/params/NaccacheSternKeyParameters.java
new file mode 100644
index 00000000..4b855b3f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/NaccacheSternKeyParameters.java
@@ -0,0 +1,53 @@
+package org.spongycastle.crypto.params;
+
+import java.math.BigInteger;
+
+/**
+ * Public key parameters for NaccacheStern cipher. For details on this cipher,
+ * please see
+ *
+ * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+ */
+public class NaccacheSternKeyParameters extends AsymmetricKeyParameter
+{
+
+ private BigInteger g, n;
+
+ int lowerSigmaBound;
+
+ /**
+ * @param privateKey
+ */
+ public NaccacheSternKeyParameters(boolean privateKey, BigInteger g, BigInteger n, int lowerSigmaBound)
+ {
+ super(privateKey);
+ this.g = g;
+ this.n = n;
+ this.lowerSigmaBound = lowerSigmaBound;
+ }
+
+ /**
+ * @return Returns the g.
+ */
+ public BigInteger getG()
+ {
+ return g;
+ }
+
+ /**
+ * @return Returns the lowerSigmaBound.
+ */
+ public int getLowerSigmaBound()
+ {
+ return lowerSigmaBound;
+ }
+
+ /**
+ * @return Returns the n.
+ */
+ public BigInteger getModulus()
+ {
+ return n;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/NaccacheSternPrivateKeyParameters.java b/core/src/main/java/org/spongycastle/crypto/params/NaccacheSternPrivateKeyParameters.java
new file mode 100644
index 00000000..7fa61c94
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/NaccacheSternPrivateKeyParameters.java
@@ -0,0 +1,50 @@
+package org.spongycastle.crypto.params;
+
+import java.math.BigInteger;
+import java.util.Vector;
+
+/**
+ * Private key parameters for NaccacheStern cipher. For details on this cipher,
+ * please see
+ *
+ * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+ */
+public class NaccacheSternPrivateKeyParameters extends NaccacheSternKeyParameters
+{
+ private BigInteger phi_n;
+ private Vector smallPrimes;
+
+ /**
+ * Constructs a NaccacheSternPrivateKey
+ *
+ * @param g
+ * the public enryption parameter g
+ * @param n
+ * the public modulus n = p*q
+ * @param lowerSigmaBound
+ * the public lower sigma bound up to which data can be encrypted
+ * @param smallPrimes
+ * the small primes, of which sigma is constructed in the right
+ * order
+ * @param phi_n
+ * the private modulus phi(n) = (p-1)(q-1)
+ */
+ public NaccacheSternPrivateKeyParameters(BigInteger g, BigInteger n,
+ int lowerSigmaBound, Vector smallPrimes,
+ BigInteger phi_n)
+ {
+ super(true, g, n, lowerSigmaBound);
+ this.smallPrimes = smallPrimes;
+ this.phi_n = phi_n;
+ }
+
+ public BigInteger getPhi_n()
+ {
+ return phi_n;
+ }
+
+ public Vector getSmallPrimes()
+ {
+ return smallPrimes;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/ParametersWithIV.java b/core/src/main/java/org/spongycastle/crypto/params/ParametersWithIV.java
new file mode 100644
index 00000000..7fb39b7e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/ParametersWithIV.java
@@ -0,0 +1,39 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.CipherParameters;
+
+public class ParametersWithIV
+ implements CipherParameters
+{
+ private byte[] iv;
+ private CipherParameters parameters;
+
+ public ParametersWithIV(
+ CipherParameters parameters,
+ byte[] iv)
+ {
+ this(parameters, iv, 0, iv.length);
+ }
+
+ public ParametersWithIV(
+ CipherParameters parameters,
+ byte[] iv,
+ int ivOff,
+ int ivLen)
+ {
+ this.iv = new byte[ivLen];
+ this.parameters = parameters;
+
+ System.arraycopy(iv, ivOff, this.iv, 0, ivLen);
+ }
+
+ public byte[] getIV()
+ {
+ return iv;
+ }
+
+ public CipherParameters getParameters()
+ {
+ return parameters;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/ParametersWithRandom.java b/core/src/main/java/org/spongycastle/crypto/params/ParametersWithRandom.java
new file mode 100644
index 00000000..ca445554
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/ParametersWithRandom.java
@@ -0,0 +1,36 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.CipherParameters;
+
+import java.security.SecureRandom;
+
+public class ParametersWithRandom
+ implements CipherParameters
+{
+ private SecureRandom random;
+ private CipherParameters parameters;
+
+ public ParametersWithRandom(
+ CipherParameters parameters,
+ SecureRandom random)
+ {
+ this.random = random;
+ this.parameters = parameters;
+ }
+
+ public ParametersWithRandom(
+ CipherParameters parameters)
+ {
+ this(parameters, new SecureRandom());
+ }
+
+ public SecureRandom getRandom()
+ {
+ return random;
+ }
+
+ public CipherParameters getParameters()
+ {
+ return parameters;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/ParametersWithSBox.java b/core/src/main/java/org/spongycastle/crypto/params/ParametersWithSBox.java
new file mode 100644
index 00000000..a1046476
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/ParametersWithSBox.java
@@ -0,0 +1,28 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.CipherParameters;
+
+public class ParametersWithSBox
+ implements CipherParameters
+{
+ private CipherParameters parameters;
+ private byte[] sBox;
+
+ public ParametersWithSBox(
+ CipherParameters parameters,
+ byte[] sBox)
+ {
+ this.parameters = parameters;
+ this.sBox = sBox;
+ }
+
+ public byte[] getSBox()
+ {
+ return sBox;
+ }
+
+ public CipherParameters getParameters()
+ {
+ return parameters;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/ParametersWithSalt.java b/core/src/main/java/org/spongycastle/crypto/params/ParametersWithSalt.java
new file mode 100644
index 00000000..e6566a36
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/ParametersWithSalt.java
@@ -0,0 +1,42 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.CipherParameters;
+
+/**
+ * Cipher parameters with a fixed salt value associated with them.
+ */
+public class ParametersWithSalt
+ implements CipherParameters
+{
+ private byte[] salt;
+ private CipherParameters parameters;
+
+ public ParametersWithSalt(
+ CipherParameters parameters,
+ byte[] salt)
+ {
+ this(parameters, salt, 0, salt.length);
+ }
+
+ public ParametersWithSalt(
+ CipherParameters parameters,
+ byte[] salt,
+ int saltOff,
+ int saltLen)
+ {
+ this.salt = new byte[saltLen];
+ this.parameters = parameters;
+
+ System.arraycopy(salt, saltOff, this.salt, 0, saltLen);
+ }
+
+ public byte[] getSalt()
+ {
+ return salt;
+ }
+
+ public CipherParameters getParameters()
+ {
+ return parameters;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/RC2Parameters.java b/core/src/main/java/org/spongycastle/crypto/params/RC2Parameters.java
new file mode 100644
index 00000000..ae396f60
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/RC2Parameters.java
@@ -0,0 +1,36 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.CipherParameters;
+
+public class RC2Parameters
+ implements CipherParameters
+{
+ private byte[] key;
+ private int bits;
+
+ public RC2Parameters(
+ byte[] key)
+ {
+ this(key, (key.length > 128) ? 1024 : (key.length * 8));
+ }
+
+ public RC2Parameters(
+ byte[] key,
+ int bits)
+ {
+ this.key = new byte[key.length];
+ this.bits = bits;
+
+ System.arraycopy(key, 0, this.key, 0, key.length);
+ }
+
+ public byte[] getKey()
+ {
+ return key;
+ }
+
+ public int getEffectiveKeyBits()
+ {
+ return bits;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/RC5Parameters.java b/core/src/main/java/org/spongycastle/crypto/params/RC5Parameters.java
new file mode 100644
index 00000000..402843e8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/RC5Parameters.java
@@ -0,0 +1,35 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.CipherParameters;
+
+public class RC5Parameters
+ implements CipherParameters
+{
+ private byte[] key;
+ private int rounds;
+
+ public RC5Parameters(
+ byte[] key,
+ int rounds)
+ {
+ if (key.length > 255)
+ {
+ throw new IllegalArgumentException("RC5 key length can be no greater than 255");
+ }
+
+ this.key = new byte[key.length];
+ this.rounds = rounds;
+
+ System.arraycopy(key, 0, this.key, 0, key.length);
+ }
+
+ public byte[] getKey()
+ {
+ return key;
+ }
+
+ public int getRounds()
+ {
+ return rounds;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/RSABlindingParameters.java b/core/src/main/java/org/spongycastle/crypto/params/RSABlindingParameters.java
new file mode 100644
index 00000000..fd45d205
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/RSABlindingParameters.java
@@ -0,0 +1,35 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.CipherParameters;
+
+import java.math.BigInteger;
+
+public class RSABlindingParameters
+ implements CipherParameters
+{
+ private RSAKeyParameters publicKey;
+ private BigInteger blindingFactor;
+
+ public RSABlindingParameters(
+ RSAKeyParameters publicKey,
+ BigInteger blindingFactor)
+ {
+ if (publicKey instanceof RSAPrivateCrtKeyParameters)
+ {
+ throw new IllegalArgumentException("RSA parameters should be for a public key");
+ }
+
+ this.publicKey = publicKey;
+ this.blindingFactor = blindingFactor;
+ }
+
+ public RSAKeyParameters getPublicKey()
+ {
+ return publicKey;
+ }
+
+ public BigInteger getBlindingFactor()
+ {
+ return blindingFactor;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/RSAKeyGenerationParameters.java b/core/src/main/java/org/spongycastle/crypto/params/RSAKeyGenerationParameters.java
new file mode 100644
index 00000000..6c047059
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/RSAKeyGenerationParameters.java
@@ -0,0 +1,48 @@
+package org.spongycastle.crypto.params;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.KeyGenerationParameters;
+
+public class RSAKeyGenerationParameters
+ extends KeyGenerationParameters
+{
+ private BigInteger publicExponent;
+ private int certainty;
+
+ public RSAKeyGenerationParameters(
+ BigInteger publicExponent,
+ SecureRandom random,
+ int strength,
+ int certainty)
+ {
+ super(random, strength);
+
+ if (strength < 12)
+ {
+ throw new IllegalArgumentException("key strength too small");
+ }
+
+ //
+ // public exponent cannot be even
+ //
+ if (!publicExponent.testBit(0))
+ {
+ throw new IllegalArgumentException("public exponent cannot be even");
+ }
+
+ this.publicExponent = publicExponent;
+ this.certainty = certainty;
+ }
+
+ public BigInteger getPublicExponent()
+ {
+ return publicExponent;
+ }
+
+ public int getCertainty()
+ {
+ return certainty;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/RSAKeyParameters.java b/core/src/main/java/org/spongycastle/crypto/params/RSAKeyParameters.java
new file mode 100644
index 00000000..d2eceeba
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/RSAKeyParameters.java
@@ -0,0 +1,31 @@
+package org.spongycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class RSAKeyParameters
+ extends AsymmetricKeyParameter
+{
+ private BigInteger modulus;
+ private BigInteger exponent;
+
+ public RSAKeyParameters(
+ boolean isPrivate,
+ BigInteger modulus,
+ BigInteger exponent)
+ {
+ super(isPrivate);
+
+ this.modulus = modulus;
+ this.exponent = exponent;
+ }
+
+ public BigInteger getModulus()
+ {
+ return modulus;
+ }
+
+ public BigInteger getExponent()
+ {
+ return exponent;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/RSAPrivateCrtKeyParameters.java b/core/src/main/java/org/spongycastle/crypto/params/RSAPrivateCrtKeyParameters.java
new file mode 100644
index 00000000..4dc79bdf
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/RSAPrivateCrtKeyParameters.java
@@ -0,0 +1,67 @@
+package org.spongycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class RSAPrivateCrtKeyParameters
+ extends RSAKeyParameters
+{
+ private BigInteger e;
+ private BigInteger p;
+ private BigInteger q;
+ private BigInteger dP;
+ private BigInteger dQ;
+ private BigInteger qInv;
+
+ /**
+ *
+ */
+ public RSAPrivateCrtKeyParameters(
+ BigInteger modulus,
+ BigInteger publicExponent,
+ BigInteger privateExponent,
+ BigInteger p,
+ BigInteger q,
+ BigInteger dP,
+ BigInteger dQ,
+ BigInteger qInv)
+ {
+ super(true, modulus, privateExponent);
+
+ this.e = publicExponent;
+ this.p = p;
+ this.q = q;
+ this.dP = dP;
+ this.dQ = dQ;
+ this.qInv = qInv;
+ }
+
+ public BigInteger getPublicExponent()
+ {
+ return e;
+ }
+
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public BigInteger getDP()
+ {
+ return dP;
+ }
+
+ public BigInteger getDQ()
+ {
+ return dQ;
+ }
+
+ public BigInteger getQInv()
+ {
+ return qInv;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/params/SkeinParameters.java b/core/src/main/java/org/spongycastle/crypto/params/SkeinParameters.java
new file mode 100644
index 00000000..0f4fc0ef
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/SkeinParameters.java
@@ -0,0 +1,329 @@
+package org.spongycastle.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 java.util.Locale;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.digests.SkeinDigest;
+import org.spongycastle.crypto.digests.SkeinEngine;
+import org.spongycastle.crypto.macs.SkeinMac;
+import org.spongycastle.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 &lt; {@value SkeinParameters#PARAM_TYPE_MESSAGE} are processed before
+ * the message content, parameters with type &gt; {@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 the current builder.
+ */
+ 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);
+ }
+ }
+
+ /**
+ * Implements the recommended personalisation format for Skein defined in Section 4.11 of
+ * the Skein 1.3 specification. You may need to use this method if the default locale
+ * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible implementations.
+ * <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 dateLocale locale to be used for date interpretation.
+ * @param emailAddress the email address of the creation of the personalised application.
+ * @param distinguisher an arbitrary personalisation string distinguishing the application.
+ * @return the current builder.
+ */
+ public Builder setPersonalisation(Date date, Locale dateLocale, String emailAddress, String distinguisher)
+ {
+ try
+ {
+ final ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ final OutputStreamWriter out = new OutputStreamWriter(bout, "UTF-8");
+ final DateFormat format = new SimpleDateFormat("YYYYMMDD", dateLocale);
+ 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/core/src/main/java/org/spongycastle/crypto/params/TweakableBlockCipherParameters.java b/core/src/main/java/org/spongycastle/crypto/params/TweakableBlockCipherParameters.java
new file mode 100644
index 00000000..2a12186e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/params/TweakableBlockCipherParameters.java
@@ -0,0 +1,40 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/parsers/DHIESPublicKeyParser.java b/core/src/main/java/org/spongycastle/crypto/parsers/DHIESPublicKeyParser.java
new file mode 100644
index 00000000..26ba1193
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/parsers/DHIESPublicKeyParser.java
@@ -0,0 +1,31 @@
+package org.spongycastle.crypto.parsers;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+
+import org.spongycastle.crypto.KeyParser;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.DHParameters;
+import org.spongycastle.crypto.params.DHPublicKeyParameters;
+
+public class DHIESPublicKeyParser
+ implements KeyParser
+{
+ private DHParameters dhParams;
+
+ public DHIESPublicKeyParser(DHParameters dhParams)
+ {
+ this.dhParams = dhParams;
+ }
+
+ public AsymmetricKeyParameter readKey(InputStream stream)
+ throws IOException
+ {
+ byte[] V = new byte[(dhParams.getP().bitLength() + 7) / 8];
+
+ stream.read(V, 0, V.length);
+
+ return new DHPublicKeyParameters(new BigInteger(1, V), dhParams);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/parsers/ECIESPublicKeyParser.java b/core/src/main/java/org/spongycastle/crypto/parsers/ECIESPublicKeyParser.java
new file mode 100644
index 00000000..aed4a625
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/parsers/ECIESPublicKeyParser.java
@@ -0,0 +1,53 @@
+package org.spongycastle.crypto.parsers;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.spongycastle.crypto.KeyParser;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+
+public class ECIESPublicKeyParser
+ implements KeyParser
+{
+ private ECDomainParameters ecParams;
+
+ public ECIESPublicKeyParser(ECDomainParameters ecParams)
+ {
+ this.ecParams = ecParams;
+ }
+
+ public AsymmetricKeyParameter readKey(InputStream stream)
+ throws IOException
+ {
+ byte[] V;
+ int first = stream.read();
+
+ // Decode the public ephemeral key
+ switch (first)
+ {
+ case 0x00: // infinity
+ throw new IOException("Sender's public key invalid.");
+
+ case 0x02: // compressed
+ case 0x03: // Byte length calculated as in ECPoint.getEncoded();
+ V = new byte[1 + (ecParams.getCurve().getFieldSize()+7)/8];
+ break;
+
+ case 0x04: // uncompressed or
+ case 0x06: // hybrid
+ case 0x07: // Byte length calculated as in ECPoint.getEncoded();
+ V = new byte[1 + 2*((ecParams.getCurve().getFieldSize()+7)/8)];
+ break;
+
+ default:
+ throw new IOException("Sender's public key has invalid point encoding 0x" + Integer.toString(first, 16));
+ }
+
+ V[0] = (byte)first;
+ stream.read(V, 1, V.length - 1);
+
+ return new ECPublicKeyParameters(ecParams.getCurve().decodePoint(V), ecParams);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/prng/BasicEntropySourceProvider.java b/core/src/main/java/org/spongycastle/crypto/prng/BasicEntropySourceProvider.java
new file mode 100644
index 00000000..176b5fb0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/prng/BasicEntropySourceProvider.java
@@ -0,0 +1,53 @@
+package org.spongycastle.crypto.prng;
+
+import java.security.SecureRandom;
+
+/**
+ * An EntropySourceProvider where entropy generation is based on a SecureRandom output using SecureRandom.generateSeed().
+ */
+public class BasicEntropySourceProvider
+ implements EntropySourceProvider
+{
+ private final SecureRandom _sr;
+ private final boolean _predictionResistant;
+
+ /**
+ * Create a entropy source provider based on the passed in SecureRandom.
+ *
+ * @param random the SecureRandom to base EntropySource construction on.
+ * @param isPredictionResistant boolean indicating if the SecureRandom is based on prediction resistant entropy or not (true if it is).
+ */
+ public BasicEntropySourceProvider(SecureRandom random, boolean isPredictionResistant)
+ {
+ _sr = random;
+ _predictionResistant = isPredictionResistant;
+ }
+
+ /**
+ * Return an entropy source that will create bitsRequired bits of entropy on
+ * each invocation of getEntropy().
+ *
+ * @param bitsRequired size (in bits) of entropy to be created by the provided source.
+ * @return an EntropySource that generates bitsRequired bits of entropy on each call to its getEntropy() method.
+ */
+ public EntropySource get(final int bitsRequired)
+ {
+ return new EntropySource()
+ {
+ public boolean isPredictionResistant()
+ {
+ return _predictionResistant;
+ }
+
+ public byte[] getEntropy()
+ {
+ return _sr.generateSeed((bitsRequired + 7) / 8);
+ }
+
+ public int entropySize()
+ {
+ return bitsRequired;
+ }
+ };
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/prng/DRBGProvider.java b/core/src/main/java/org/spongycastle/crypto/prng/DRBGProvider.java
new file mode 100644
index 00000000..f9067323
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/prng/DRBGProvider.java
@@ -0,0 +1,8 @@
+package org.spongycastle.crypto.prng;
+
+import org.spongycastle.crypto.prng.drbg.SP80090DRBG;
+
+interface DRBGProvider
+{
+ SP80090DRBG get(EntropySource entropySource);
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/prng/DigestRandomGenerator.java b/core/src/main/java/org/spongycastle/crypto/prng/DigestRandomGenerator.java
new file mode 100644
index 00000000..5505338a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/prng/DigestRandomGenerator.java
@@ -0,0 +1,123 @@
+package org.spongycastle.crypto.prng;
+
+import org.spongycastle.crypto.Digest;
+
+/**
+ * Random generation based on the digest with counter. Calling addSeedMaterial will
+ * always increase the entropy of the hash.
+ * <p>
+ * Internal access to the digest is synchronized so a single one of these can be shared.
+ * </p>
+ */
+public class DigestRandomGenerator
+ implements RandomGenerator
+{
+ private static long CYCLE_COUNT = 10;
+
+ private long stateCounter;
+ private long seedCounter;
+ private Digest digest;
+ private byte[] state;
+ private byte[] seed;
+
+ // public constructors
+ public DigestRandomGenerator(
+ Digest digest)
+ {
+ this.digest = digest;
+
+ this.seed = new byte[digest.getDigestSize()];
+ this.seedCounter = 1;
+
+ this.state = new byte[digest.getDigestSize()];
+ this.stateCounter = 1;
+ }
+
+ public void addSeedMaterial(byte[] inSeed)
+ {
+ synchronized (this)
+ {
+ digestUpdate(inSeed);
+ digestUpdate(seed);
+ digestDoFinal(seed);
+ }
+ }
+
+ public void addSeedMaterial(long rSeed)
+ {
+ synchronized (this)
+ {
+ digestAddCounter(rSeed);
+ digestUpdate(seed);
+
+ digestDoFinal(seed);
+ }
+ }
+
+ public void nextBytes(byte[] bytes)
+ {
+ nextBytes(bytes, 0, bytes.length);
+ }
+
+ public void nextBytes(byte[] bytes, int start, int len)
+ {
+ synchronized (this)
+ {
+ int stateOff = 0;
+
+ generateState();
+
+ int end = start + len;
+ for (int i = start; i != end; i++)
+ {
+ if (stateOff == state.length)
+ {
+ generateState();
+ stateOff = 0;
+ }
+ bytes[i] = state[stateOff++];
+ }
+ }
+ }
+
+ private void cycleSeed()
+ {
+ digestUpdate(seed);
+ digestAddCounter(seedCounter++);
+
+ digestDoFinal(seed);
+ }
+
+ private void generateState()
+ {
+ digestAddCounter(stateCounter++);
+ digestUpdate(state);
+ digestUpdate(seed);
+
+ digestDoFinal(state);
+
+ if ((stateCounter % CYCLE_COUNT) == 0)
+ {
+ cycleSeed();
+ }
+ }
+
+ private void digestAddCounter(long seed)
+ {
+ for (int i = 0; i != 8; i++)
+ {
+ digest.update((byte)seed);
+ seed >>>= 8;
+ }
+ }
+
+ private void digestUpdate(byte[] inSeed)
+ {
+ digest.update(inSeed, 0, inSeed.length);
+ }
+
+ private void digestDoFinal(byte[] result)
+ {
+ digest.doFinal(result, 0);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/prng/EntropySource.java b/core/src/main/java/org/spongycastle/crypto/prng/EntropySource.java
new file mode 100644
index 00000000..783f375c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/prng/EntropySource.java
@@ -0,0 +1,25 @@
+package org.spongycastle.crypto.prng;
+
+public interface EntropySource
+{
+ /**
+ * Return whether or not this entropy source is regarded as prediction resistant.
+ *
+ * @return true if it is, false otherwise.
+ */
+ boolean isPredictionResistant();
+
+ /**
+ * Return a byte array of entropy.
+ *
+ * @return entropy bytes.
+ */
+ byte[] getEntropy();
+
+ /**
+ * Return the number of bits of entropy this source can produce.
+ *
+ * @return size in bits of the return value of getEntropy.
+ */
+ int entropySize();
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/prng/EntropySourceProvider.java b/core/src/main/java/org/spongycastle/crypto/prng/EntropySourceProvider.java
new file mode 100644
index 00000000..1efabb48
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/prng/EntropySourceProvider.java
@@ -0,0 +1,6 @@
+package org.spongycastle.crypto.prng;
+
+public interface EntropySourceProvider
+{
+ EntropySource get(final int bitsRequired);
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/prng/FixedSecureRandom.java b/core/src/main/java/org/spongycastle/crypto/prng/FixedSecureRandom.java
new file mode 100644
index 00000000..cea20329
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/prng/FixedSecureRandom.java
@@ -0,0 +1,147 @@
+package org.spongycastle.crypto.prng;
+
+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
+{
+ private byte[] _data;
+
+ private int _index;
+ private int _intPad;
+
+ public FixedSecureRandom(byte[] value)
+ {
+ this(false, new byte[][] { value });
+ }
+
+ public FixedSecureRandom(
+ byte[][] values)
+ {
+ this(false, values);
+ }
+
+ /**
+ * Pad the data on integer boundaries. This is necessary for the classpath project's BigInteger
+ * implementation.
+ */
+ public FixedSecureRandom(
+ boolean intPad,
+ byte[] value)
+ {
+ this(intPad, new byte[][] { value });
+ }
+
+ /**
+ * Pad the data on integer boundaries. This is necessary for the classpath project's BigInteger
+ * implementation.
+ */
+ public FixedSecureRandom(
+ boolean intPad,
+ byte[][] values)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ for (int i = 0; i != values.length; i++)
+ {
+ try
+ {
+ bOut.write(values[i]);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("can't save value array.");
+ }
+ }
+
+ _data = bOut.toByteArray();
+
+ if (intPad)
+ {
+ _intPad = _data.length % 4;
+ }
+ }
+
+ public void nextBytes(byte[] bytes)
+ {
+ System.arraycopy(_data, _index, bytes, 0, bytes.length);
+
+ _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.
+ //
+ public int nextInt()
+ {
+ int val = 0;
+
+ val |= nextValue() << 24;
+ val |= nextValue() << 16;
+
+ if (_intPad == 2)
+ {
+ _intPad--;
+ }
+ else
+ {
+ val |= nextValue() << 8;
+ }
+
+ if (_intPad == 1)
+ {
+ _intPad--;
+ }
+ else
+ {
+ val |= nextValue();
+ }
+
+ return val;
+ }
+
+ //
+ // 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.
+ //
+ public long nextLong()
+ {
+ long val = 0;
+
+ val |= (long)nextValue() << 56;
+ val |= (long)nextValue() << 48;
+ val |= (long)nextValue() << 40;
+ val |= (long)nextValue() << 32;
+ val |= (long)nextValue() << 24;
+ val |= (long)nextValue() << 16;
+ val |= (long)nextValue() << 8;
+ val |= (long)nextValue();
+
+ return val;
+ }
+
+ public boolean isExhausted()
+ {
+ return _index == _data.length;
+ }
+
+ private int nextValue()
+ {
+ return _data[_index++] & 0xff;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/prng/RandomGenerator.java b/core/src/main/java/org/spongycastle/crypto/prng/RandomGenerator.java
new file mode 100644
index 00000000..aa9a3834
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/prng/RandomGenerator.java
@@ -0,0 +1,38 @@
+package org.spongycastle.crypto.prng;
+
+/**
+ * Generic interface for objects generating random bytes.
+ */
+public interface RandomGenerator
+{
+ /**
+ * Add more seed material to the generator.
+ *
+ * @param seed a byte array to be mixed into the generator's state.
+ */
+ void addSeedMaterial(byte[] seed);
+
+ /**
+ * Add more seed material to the generator.
+ *
+ * @param seed a long value to be mixed into the generator's state.
+ */
+ void addSeedMaterial(long seed);
+
+ /**
+ * Fill bytes with random values.
+ *
+ * @param bytes byte array to be filled.
+ */
+ void nextBytes(byte[] bytes);
+
+ /**
+ * Fill part of bytes with random values.
+ *
+ * @param bytes byte array to be filled.
+ * @param start index to start filling at.
+ * @param len length of segment to fill.
+ */
+ void nextBytes(byte[] bytes, int start, int len);
+
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/prng/ReversedWindowGenerator.java b/core/src/main/java/org/spongycastle/crypto/prng/ReversedWindowGenerator.java
new file mode 100644
index 00000000..0e12d41d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/prng/ReversedWindowGenerator.java
@@ -0,0 +1,111 @@
+package org.spongycastle.crypto.prng;
+
+/**
+ * Takes bytes generated by an underling RandomGenerator and reverses the order in
+ * each small window (of configurable size).
+ * <p>
+ * Access to internals is synchronized so a single one of these can be shared.
+ * </p>
+ */
+public class ReversedWindowGenerator
+ implements RandomGenerator
+{
+ private final RandomGenerator generator;
+
+ private byte[] window;
+ private int windowCount;
+
+ public ReversedWindowGenerator(
+ RandomGenerator generator,
+ int windowSize)
+ {
+ if (generator == null)
+ {
+ throw new IllegalArgumentException("generator cannot be null");
+ }
+ if (windowSize < 2)
+ {
+ throw new IllegalArgumentException("windowSize must be at least 2");
+ }
+
+ this.generator = generator;
+ this.window = new byte[windowSize];
+ }
+
+ /**
+ * Add more seed material to the generator.
+ *
+ * @param seed a byte array to be mixed into the generator's state.
+ */
+ public void addSeedMaterial(
+ byte[] seed)
+ {
+ synchronized (this)
+ {
+ windowCount = 0;
+ generator.addSeedMaterial(seed);
+ }
+ }
+
+ /**
+ * Add more seed material to the generator.
+ *
+ * @param seed a long value to be mixed into the generator's state.
+ */
+ public void addSeedMaterial(
+ long seed)
+ {
+ synchronized (this)
+ {
+ windowCount = 0;
+ generator.addSeedMaterial(seed);
+ }
+ }
+
+ /**
+ * Fill bytes with random values.
+ *
+ * @param bytes byte array to be filled.
+ */
+ public void nextBytes(
+ byte[] bytes)
+ {
+ doNextBytes(bytes, 0, bytes.length);
+ }
+
+ /**
+ * Fill part of bytes with random values.
+ *
+ * @param bytes byte array to be filled.
+ * @param start index to start filling at.
+ * @param len length of segment to fill.
+ */
+ public void nextBytes(
+ byte[] bytes,
+ int start,
+ int len)
+ {
+ doNextBytes(bytes, start, len);
+ }
+
+ private void doNextBytes(
+ byte[] bytes,
+ int start,
+ int len)
+ {
+ synchronized (this)
+ {
+ int done = 0;
+ while (done < len)
+ {
+ if (windowCount < 1)
+ {
+ generator.nextBytes(window, 0, window.length);
+ windowCount = window.length;
+ }
+
+ bytes[start + done++] = window[--windowCount];
+ }
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/prng/SP800SecureRandom.java b/core/src/main/java/org/spongycastle/crypto/prng/SP800SecureRandom.java
new file mode 100644
index 00000000..1a452f9e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/prng/SP800SecureRandom.java
@@ -0,0 +1,74 @@
+package org.spongycastle.crypto.prng;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.prng.drbg.SP80090DRBG;
+
+public class SP800SecureRandom
+ extends SecureRandom
+{
+ private final DRBGProvider drbgProvider;
+ private final boolean predictionResistant;
+ private final SecureRandom randomSource;
+ private final EntropySource entropySource;
+
+ private SP80090DRBG drbg;
+
+ SP800SecureRandom(SecureRandom randomSource, EntropySource entropySource, DRBGProvider drbgProvider, boolean predictionResistant)
+ {
+ this.randomSource = randomSource;
+ this.entropySource = entropySource;
+ this.drbgProvider = drbgProvider;
+ this.predictionResistant = predictionResistant;
+ }
+
+ public void setSeed(byte[] seed)
+ {
+ synchronized (this)
+ {
+ if (randomSource != null)
+ {
+ this.randomSource.setSeed(seed);
+ }
+ }
+ }
+
+ public void setSeed(long seed)
+ {
+ synchronized (this)
+ {
+ // this will happen when SecureRandom() is created
+ if (randomSource != null)
+ {
+ this.randomSource.setSeed(seed);
+ }
+ }
+ }
+
+ public void nextBytes(byte[] bytes)
+ {
+ synchronized (this)
+ {
+ if (drbg == null)
+ {
+ drbg = drbgProvider.get(entropySource);
+ }
+
+ // check if a reseed is required...
+ if (drbg.generate(bytes, null, predictionResistant) < 0)
+ {
+ drbg.reseed(entropySource.getEntropy());
+ drbg.generate(bytes, null, predictionResistant);
+ }
+ }
+ }
+
+ public byte[] generateSeed(int numBytes)
+ {
+ byte[] bytes = new byte[numBytes];
+
+ this.nextBytes(bytes);
+
+ return bytes;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/prng/SP800SecureRandomBuilder.java b/core/src/main/java/org/spongycastle/crypto/prng/SP800SecureRandomBuilder.java
new file mode 100644
index 00000000..6e9e3ccc
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/prng/SP800SecureRandomBuilder.java
@@ -0,0 +1,290 @@
+package org.spongycastle.crypto.prng;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.prng.drbg.CTRSP800DRBG;
+import org.spongycastle.crypto.prng.drbg.DualECPoints;
+import org.spongycastle.crypto.prng.drbg.DualECSP800DRBG;
+import org.spongycastle.crypto.prng.drbg.HMacSP800DRBG;
+import org.spongycastle.crypto.prng.drbg.HashSP800DRBG;
+import org.spongycastle.crypto.prng.drbg.SP80090DRBG;
+
+/**
+ * Builder class for making SecureRandom objects based on SP 800-90A Deterministic Random Bit Generators (DRBG).
+ */
+public class SP800SecureRandomBuilder
+{
+ private final SecureRandom random;
+ private final EntropySourceProvider entropySourceProvider;
+
+ private byte[] personalizationString;
+ private int securityStrength = 256;
+ private int entropyBitsRequired = 256;
+
+ /**
+ * Basic constructor, creates a builder using an EntropySourceProvider based on the default SecureRandom with
+ * predictionResistant set to false.
+ * <p>
+ * Any SecureRandom created from a builder constructed like this will make use of input passed to SecureRandom.setSeed() if
+ * the default SecureRandom does for its generateSeed() call.
+ * </p>
+ */
+ public SP800SecureRandomBuilder()
+ {
+ this(new SecureRandom(), false);
+ }
+
+ /**
+ * Construct a builder with an EntropySourceProvider based on the passed in SecureRandom and the passed in value
+ * for prediction resistance.
+ * <p>
+ * Any SecureRandom created from a builder constructed like this will make use of input passed to SecureRandom.setSeed() if
+ * the passed in SecureRandom does for its generateSeed() call.
+ * </p>
+ * @param entropySource
+ * @param predictionResistant
+ */
+ public SP800SecureRandomBuilder(SecureRandom entropySource, boolean predictionResistant)
+ {
+ this.random = entropySource;
+ this.entropySourceProvider = new BasicEntropySourceProvider(random, predictionResistant);
+ }
+
+ /**
+ * Create a builder which makes creates the SecureRandom objects from a specified entropy source provider.
+ * <p>
+ * <b>Note:</b> If this constructor is used any calls to setSeed() in the resulting SecureRandom will be ignored.
+ * </p>
+ * @param entropySourceProvider a provider of EntropySource objects.
+ */
+ public SP800SecureRandomBuilder(EntropySourceProvider entropySourceProvider)
+ {
+ this.random = null;
+ this.entropySourceProvider = entropySourceProvider;
+ }
+
+ /**
+ * Set the personalization string for DRBG SecureRandoms created by this builder
+ * @param personalizationString the personalisation string for the underlying DRBG.
+ * @return the current builder.
+ */
+ public SP800SecureRandomBuilder setPersonalizationString(byte[] personalizationString)
+ {
+ this.personalizationString = personalizationString;
+
+ return this;
+ }
+
+ /**
+ * Set the security strength required for DRBGs used in building SecureRandom objects.
+ *
+ * @param securityStrength the security strength (in bits)
+ * @return the current builder.
+ */
+ public SP800SecureRandomBuilder setSecurityStrength(int securityStrength)
+ {
+ this.securityStrength = securityStrength;
+
+ return this;
+ }
+
+ /**
+ * Set the amount of entropy bits required for seeding and reseeding DRBGs used in building SecureRandom objects.
+ *
+ * @param entropyBitsRequired the number of bits of entropy to be requested from the entropy source on each seed/reseed.
+ * @return the current builder.
+ */
+ public SP800SecureRandomBuilder setEntropyBitsRequired(int entropyBitsRequired)
+ {
+ this.entropyBitsRequired = entropyBitsRequired;
+
+ return this;
+ }
+
+ /**
+ * Build a SecureRandom based on a SP 800-90A Hash DRBG.
+ *
+ * @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 Hash DRBG.
+ */
+ public SP800SecureRandom buildHash(Digest digest, byte[] nonce, boolean predictionResistant)
+ {
+ return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new HashDRBGProvider(digest, nonce, personalizationString, securityStrength), predictionResistant);
+ }
+
+ /**
+ * Build a SecureRandom based on a SP 800-90A CTR DRBG.
+ *
+ * @param cipher the block cipher to base the DRBG on.
+ * @param keySizeInBits key size in bits to be used with the block cipher.
+ * @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 CTR DRBG.
+ */
+ public SP800SecureRandom buildCTR(BlockCipher cipher, int keySizeInBits, byte[] nonce, boolean predictionResistant)
+ {
+ return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new CTRDRBGProvider(cipher, keySizeInBits, nonce, personalizationString, securityStrength), predictionResistant);
+ }
+
+ /**
+ * Build a SecureRandom based on a SP 800-90A HMAC DRBG.
+ *
+ * @param hMac HMAC 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 HMAC DRBG.
+ */
+ public SP800SecureRandom buildHMAC(Mac hMac, byte[] nonce, boolean predictionResistant)
+ {
+ return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new HMacDRBGProvider(hMac, nonce, personalizationString, securityStrength), predictionResistant);
+ }
+
+ /**
+ * 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.
+ * @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(Digest digest, byte[] nonce, boolean predictionResistant)
+ {
+ 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
+ {
+ private final Digest digest;
+ private final byte[] nonce;
+ private final byte[] personalizationString;
+ private final int securityStrength;
+
+ public HashDRBGProvider(Digest digest, byte[] nonce, byte[] personalizationString, int securityStrength)
+ {
+ this.digest = digest;
+ this.nonce = nonce;
+ this.personalizationString = personalizationString;
+ this.securityStrength = securityStrength;
+ }
+
+ public SP80090DRBG get(EntropySource entropySource)
+ {
+ return new HashSP800DRBG(digest, securityStrength, entropySource, personalizationString, nonce);
+ }
+ }
+
+ private static class DualECDRBGProvider
+ implements DRBGProvider
+ {
+ private final Digest digest;
+ private final byte[] nonce;
+ private final byte[] personalizationString;
+ private final int securityStrength;
+
+ public DualECDRBGProvider(Digest digest, byte[] nonce, byte[] personalizationString, int securityStrength)
+ {
+ this.digest = digest;
+ this.nonce = nonce;
+ this.personalizationString = personalizationString;
+ this.securityStrength = securityStrength;
+ }
+
+ public SP80090DRBG get(EntropySource entropySource)
+ {
+ return new DualECSP800DRBG(digest, securityStrength, entropySource, personalizationString, nonce);
+ }
+ }
+
+ 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
+ {
+ private final Mac hMac;
+ private final byte[] nonce;
+ private final byte[] personalizationString;
+ private final int securityStrength;
+
+ public HMacDRBGProvider(Mac hMac, byte[] nonce, byte[] personalizationString, int securityStrength)
+ {
+ this.hMac = hMac;
+ this.nonce = nonce;
+ this.personalizationString = personalizationString;
+ this.securityStrength = securityStrength;
+ }
+
+ public SP80090DRBG get(EntropySource entropySource)
+ {
+ return new HMacSP800DRBG(hMac, securityStrength, entropySource, personalizationString, nonce);
+ }
+ }
+
+ private static class CTRDRBGProvider
+ implements DRBGProvider
+ {
+
+ private final BlockCipher blockCipher;
+ private final int keySizeInBits;
+ private final byte[] nonce;
+ private final byte[] personalizationString;
+ private final int securityStrength;
+
+ public CTRDRBGProvider(BlockCipher blockCipher, int keySizeInBits, byte[] nonce, byte[] personalizationString, int securityStrength)
+ {
+ this.blockCipher = blockCipher;
+ this.keySizeInBits = keySizeInBits;
+ this.nonce = nonce;
+ this.personalizationString = personalizationString;
+ this.securityStrength = securityStrength;
+ }
+
+ public SP80090DRBG get(EntropySource entropySource)
+ {
+ return new CTRSP800DRBG(blockCipher, keySizeInBits, securityStrength, entropySource, personalizationString, nonce);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/prng/ThreadedSeedGenerator.java b/core/src/main/java/org/spongycastle/crypto/prng/ThreadedSeedGenerator.java
new file mode 100644
index 00000000..fc103542
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/prng/ThreadedSeedGenerator.java
@@ -0,0 +1,95 @@
+package org.spongycastle.crypto.prng;
+
+/**
+ * A thread based seed generator - one source of randomness.
+ * <p>
+ * Based on an idea from Marcus Lippert.
+ * </p>
+ */
+public class ThreadedSeedGenerator
+{
+ private class SeedGenerator
+ implements Runnable
+ {
+ private volatile int counter = 0;
+ private volatile boolean stop = false;
+
+ public void run()
+ {
+ while (!this.stop)
+ {
+ this.counter++;
+ }
+
+ }
+
+ public byte[] generateSeed(
+ int numbytes,
+ boolean fast)
+ {
+ Thread t = new Thread(this);
+ byte[] result = new byte[numbytes];
+ this.counter = 0;
+ this.stop = false;
+ int last = 0;
+ int end;
+
+ t.start();
+ if(fast)
+ {
+ end = numbytes;
+ }
+ else
+ {
+ end = numbytes * 8;
+ }
+ for (int i = 0; i < end; i++)
+ {
+ while (this.counter == last)
+ {
+ try
+ {
+ Thread.sleep(1);
+ }
+ catch (InterruptedException e)
+ {
+ // ignore
+ }
+ }
+ last = this.counter;
+ if (fast)
+ {
+ result[i] = (byte) (last & 0xff);
+ }
+ else
+ {
+ int bytepos = i/8;
+ result[bytepos] = (byte) ((result[bytepos] << 1) | (last & 1));
+ }
+
+ }
+ stop = true;
+ return result;
+ }
+ }
+
+ /**
+ * Generate seed bytes. Set fast to false for best quality.
+ * <p>
+ * If fast is set to true, the code should be round about 8 times faster when
+ * generating a long sequence of random bytes. 20 bytes of random values using
+ * the fast mode take less than half a second on a Nokia e70. If fast is set to false,
+ * it takes round about 2500 ms.
+ * </p>
+ * @param numBytes the number of bytes to generate
+ * @param fast true if fast mode should be used
+ */
+ public byte[] generateSeed(
+ int numBytes,
+ boolean fast)
+ {
+ SeedGenerator gen = new SeedGenerator();
+
+ return gen.generateSeed(numBytes, fast);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/prng/VMPCRandomGenerator.java b/core/src/main/java/org/spongycastle/crypto/prng/VMPCRandomGenerator.java
new file mode 100644
index 00000000..bae1bc39
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/prng/VMPCRandomGenerator.java
@@ -0,0 +1,127 @@
+package org.spongycastle.crypto.prng;
+
+import org.spongycastle.util.Pack;
+
+public class VMPCRandomGenerator implements RandomGenerator
+{
+ private byte n = 0;
+
+ /**
+ * Permutation generated by code: <code>
+ * // First 1850 fractional digit of Pi number.
+ * byte[] key = new BigInteger("14159265358979323846...5068006422512520511").toByteArray();
+ * s = 0;
+ * P = new byte[256];
+ * for (int i = 0; i < 256; i++) {
+ * P[i] = (byte) i;
+ * }
+ * for (int m = 0; m < 768; m++) {
+ * s = P[(s + P[m & 0xff] + key[m % key.length]) & 0xff];
+ * byte temp = P[m & 0xff];
+ * P[m & 0xff] = P[s & 0xff];
+ * P[s & 0xff] = temp;
+ * } </code>
+ */
+ private byte[] P =
+ {
+ (byte) 0xbb, (byte) 0x2c, (byte) 0x62, (byte) 0x7f,
+ (byte) 0xb5, (byte) 0xaa, (byte) 0xd4, (byte) 0x0d, (byte) 0x81,
+ (byte) 0xfe, (byte) 0xb2, (byte) 0x82, (byte) 0xcb, (byte) 0xa0,
+ (byte) 0xa1, (byte) 0x08, (byte) 0x18, (byte) 0x71, (byte) 0x56,
+ (byte) 0xe8, (byte) 0x49, (byte) 0x02, (byte) 0x10, (byte) 0xc4,
+ (byte) 0xde, (byte) 0x35, (byte) 0xa5, (byte) 0xec, (byte) 0x80,
+ (byte) 0x12, (byte) 0xb8, (byte) 0x69, (byte) 0xda, (byte) 0x2f,
+ (byte) 0x75, (byte) 0xcc, (byte) 0xa2, (byte) 0x09, (byte) 0x36,
+ (byte) 0x03, (byte) 0x61, (byte) 0x2d, (byte) 0xfd, (byte) 0xe0,
+ (byte) 0xdd, (byte) 0x05, (byte) 0x43, (byte) 0x90, (byte) 0xad,
+ (byte) 0xc8, (byte) 0xe1, (byte) 0xaf, (byte) 0x57, (byte) 0x9b,
+ (byte) 0x4c, (byte) 0xd8, (byte) 0x51, (byte) 0xae, (byte) 0x50,
+ (byte) 0x85, (byte) 0x3c, (byte) 0x0a, (byte) 0xe4, (byte) 0xf3,
+ (byte) 0x9c, (byte) 0x26, (byte) 0x23, (byte) 0x53, (byte) 0xc9,
+ (byte) 0x83, (byte) 0x97, (byte) 0x46, (byte) 0xb1, (byte) 0x99,
+ (byte) 0x64, (byte) 0x31, (byte) 0x77, (byte) 0xd5, (byte) 0x1d,
+ (byte) 0xd6, (byte) 0x78, (byte) 0xbd, (byte) 0x5e, (byte) 0xb0,
+ (byte) 0x8a, (byte) 0x22, (byte) 0x38, (byte) 0xf8, (byte) 0x68,
+ (byte) 0x2b, (byte) 0x2a, (byte) 0xc5, (byte) 0xd3, (byte) 0xf7,
+ (byte) 0xbc, (byte) 0x6f, (byte) 0xdf, (byte) 0x04, (byte) 0xe5,
+ (byte) 0x95, (byte) 0x3e, (byte) 0x25, (byte) 0x86, (byte) 0xa6,
+ (byte) 0x0b, (byte) 0x8f, (byte) 0xf1, (byte) 0x24, (byte) 0x0e,
+ (byte) 0xd7, (byte) 0x40, (byte) 0xb3, (byte) 0xcf, (byte) 0x7e,
+ (byte) 0x06, (byte) 0x15, (byte) 0x9a, (byte) 0x4d, (byte) 0x1c,
+ (byte) 0xa3, (byte) 0xdb, (byte) 0x32, (byte) 0x92, (byte) 0x58,
+ (byte) 0x11, (byte) 0x27, (byte) 0xf4, (byte) 0x59, (byte) 0xd0,
+ (byte) 0x4e, (byte) 0x6a, (byte) 0x17, (byte) 0x5b, (byte) 0xac,
+ (byte) 0xff, (byte) 0x07, (byte) 0xc0, (byte) 0x65, (byte) 0x79,
+ (byte) 0xfc, (byte) 0xc7, (byte) 0xcd, (byte) 0x76, (byte) 0x42,
+ (byte) 0x5d, (byte) 0xe7, (byte) 0x3a, (byte) 0x34, (byte) 0x7a,
+ (byte) 0x30, (byte) 0x28, (byte) 0x0f, (byte) 0x73, (byte) 0x01,
+ (byte) 0xf9, (byte) 0xd1, (byte) 0xd2, (byte) 0x19, (byte) 0xe9,
+ (byte) 0x91, (byte) 0xb9, (byte) 0x5a, (byte) 0xed, (byte) 0x41,
+ (byte) 0x6d, (byte) 0xb4, (byte) 0xc3, (byte) 0x9e, (byte) 0xbf,
+ (byte) 0x63, (byte) 0xfa, (byte) 0x1f, (byte) 0x33, (byte) 0x60,
+ (byte) 0x47, (byte) 0x89, (byte) 0xf0, (byte) 0x96, (byte) 0x1a,
+ (byte) 0x5f, (byte) 0x93, (byte) 0x3d, (byte) 0x37, (byte) 0x4b,
+ (byte) 0xd9, (byte) 0xa8, (byte) 0xc1, (byte) 0x1b, (byte) 0xf6,
+ (byte) 0x39, (byte) 0x8b, (byte) 0xb7, (byte) 0x0c, (byte) 0x20,
+ (byte) 0xce, (byte) 0x88, (byte) 0x6e, (byte) 0xb6, (byte) 0x74,
+ (byte) 0x8e, (byte) 0x8d, (byte) 0x16, (byte) 0x29, (byte) 0xf2,
+ (byte) 0x87, (byte) 0xf5, (byte) 0xeb, (byte) 0x70, (byte) 0xe3,
+ (byte) 0xfb, (byte) 0x55, (byte) 0x9f, (byte) 0xc6, (byte) 0x44,
+ (byte) 0x4a, (byte) 0x45, (byte) 0x7d, (byte) 0xe2, (byte) 0x6b,
+ (byte) 0x5c, (byte) 0x6c, (byte) 0x66, (byte) 0xa9, (byte) 0x8c,
+ (byte) 0xee, (byte) 0x84, (byte) 0x13, (byte) 0xa7, (byte) 0x1e,
+ (byte) 0x9d, (byte) 0xdc, (byte) 0x67, (byte) 0x48, (byte) 0xba,
+ (byte) 0x2e, (byte) 0xe6, (byte) 0xa4, (byte) 0xab, (byte) 0x7c,
+ (byte) 0x94, (byte) 0x00, (byte) 0x21, (byte) 0xef, (byte) 0xea,
+ (byte) 0xbe, (byte) 0xca, (byte) 0x72, (byte) 0x4f, (byte) 0x52,
+ (byte) 0x98, (byte) 0x3f, (byte) 0xc2, (byte) 0x14, (byte) 0x7b,
+ (byte) 0x3b, (byte) 0x54 };
+
+ /**
+ * Value generated in the same way as {@link VMPCRandomGenerator#P};
+ */
+ private byte s = (byte) 0xbe;
+
+ public VMPCRandomGenerator()
+ {
+ }
+
+ public void addSeedMaterial(byte[] seed)
+ {
+ for (int m = 0; m < seed.length; m++)
+ {
+ s = P[(s + P[n & 0xff] + seed[m]) & 0xff];
+ byte temp = P[n & 0xff];
+ P[n & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ n = (byte) ((n + 1) & 0xff);
+ }
+ }
+
+ public void addSeedMaterial(long seed)
+ {
+ addSeedMaterial(Pack.longToBigEndian(seed));
+ }
+
+ public void nextBytes(byte[] bytes)
+ {
+ nextBytes(bytes, 0, bytes.length);
+ }
+
+ public void nextBytes(byte[] bytes, int start, int len)
+ {
+ synchronized (P)
+ {
+ int end = start + len;
+ for (int i = start; i != end; i++)
+ {
+ s = P[(s + P[n & 0xff]) & 0xff];
+ bytes[i] = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff];
+ byte temp = P[n & 0xff];
+ P[n & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ n = (byte) ((n + 1) & 0xff);
+ }
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/prng/drbg/CTRSP800DRBG.java b/core/src/main/java/org/spongycastle/crypto/prng/drbg/CTRSP800DRBG.java
new file mode 100644
index 00000000..26316685
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/prng/drbg/CTRSP800DRBG.java
@@ -0,0 +1,478 @@
+package org.spongycastle.crypto.prng.drbg;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.prng.EntropySource;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+
+/**
+ * A SP800-90A CTR DRBG.
+ */
+public class CTRSP800DRBG
+ implements SP80090DRBG
+{
+ private static final long TDEA_RESEED_MAX = 1L << (32 - 1);
+ private static final long AES_RESEED_MAX = 1L << (48 - 1);
+ private static final int TDEA_MAX_BITS_REQUEST = 1 << (13 - 1);
+ private static final int AES_MAX_BITS_REQUEST = 1 << (19 - 1);
+
+ private EntropySource _entropySource;
+ private BlockCipher _engine;
+ private int _keySizeInBits;
+ private int _seedLength;
+
+ // internal state
+ private byte[] _Key;
+ private byte[] _V;
+ private long _reseedCounter = 0;
+ private boolean _isTDEA = false;
+
+ /**
+ * Construct a SP800-90A CTR DRBG.
+ * <p>
+ * Minimum entropy requirement is the security strength requested.
+ * </p>
+ * @param engine underlying block cipher to use to support DRBG
+ * @param keySizeInBits size of the key to use with the block cipher.
+ * @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 CTRSP800DRBG(BlockCipher engine, int keySizeInBits, int securityStrength, EntropySource entropySource, byte[] personalizationString, byte[] nonce)
+ {
+ _entropySource = entropySource;
+ _engine = engine;
+
+ _keySizeInBits = keySizeInBits;
+ _seedLength = keySizeInBits + engine.getBlockSize() * 8;
+ _isTDEA = isTDEA(engine);
+
+ if (securityStrength > 256)
+ {
+ throw new IllegalArgumentException("Requested security strength is not supported by the derivation function");
+ }
+
+ if (getMaxSecurityStrength(engine, keySizeInBits) < securityStrength)
+ {
+ throw new IllegalArgumentException("Requested security strength is not supported by block cipher and key size");
+ }
+
+ if (entropySource.entropySize() < securityStrength)
+ {
+ throw new IllegalArgumentException("Not enough entropy for security strength required");
+ }
+
+ byte[] entropy = entropySource.getEntropy(); // Get_entropy_input
+
+ CTR_DRBG_Instantiate_algorithm(entropy, nonce, personalizationString);
+ }
+
+ private void CTR_DRBG_Instantiate_algorithm(byte[] entropy, byte[] nonce,
+ byte[] personalisationString)
+ {
+ byte[] seedMaterial = Arrays.concatenate(entropy, nonce, personalisationString);
+ byte[] seed = Block_Cipher_df(seedMaterial, _seedLength);
+
+ int outlen = _engine.getBlockSize();
+
+ _Key = new byte[(_keySizeInBits + 7) / 8];
+ _V = new byte[outlen];
+
+ // _Key & _V are modified by this call
+ CTR_DRBG_Update(seed, _Key, _V);
+
+ _reseedCounter = 1;
+ }
+
+ private void CTR_DRBG_Update(byte[] seed, byte[] key, byte[] v)
+ {
+ byte[] temp = new byte[seed.length];
+ byte[] outputBlock = new byte[_engine.getBlockSize()];
+
+ int i=0;
+ int outLen = _engine.getBlockSize();
+
+ _engine.init(true, new KeyParameter(expandKey(key)));
+ while (i*outLen < seed.length)
+ {
+ addOneTo(v);
+ _engine.processBlock(v, 0, outputBlock, 0);
+
+ int bytesToCopy = ((temp.length - i * outLen) > outLen)
+ ? outLen : (temp.length - i * outLen);
+
+ System.arraycopy(outputBlock, 0, temp, i * outLen, bytesToCopy);
+ ++i;
+ }
+
+ XOR(temp, seed, temp, 0);
+
+ System.arraycopy(temp, 0, key, 0, key.length);
+ System.arraycopy(temp, key.length, v, 0, v.length);
+ }
+
+ private void CTR_DRBG_Reseed_algorithm(EntropySource entropy, byte[] additionalInput)
+ {
+ byte[] seedMaterial = Arrays.concatenate(entropy.getEntropy(), additionalInput);
+
+ seedMaterial = Block_Cipher_df(seedMaterial, _seedLength);
+
+ CTR_DRBG_Update(seedMaterial, _Key, _V);
+
+ _reseedCounter = 1;
+ }
+
+ private void XOR(byte[] out, byte[] a, byte[] b, int bOff)
+ {
+ for (int i=0; i< out.length; i++)
+ {
+ out[i] = (byte)(a[i] ^ b[i+bOff]);
+ }
+ }
+
+ private void addOneTo(byte[] longer)
+ {
+ int carry = 1;
+ for (int i = 1; i <= longer.length; i++) // warning
+ {
+ int res = (longer[longer.length - i] & 0xff) + carry;
+ carry = (res > 0xff) ? 1 : 0;
+ longer[longer.length - i] = (byte)res;
+ }
+ }
+
+ // -- Internal state migration ---
+
+ private static final byte[] K_BITS = Hex.decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F");
+
+ // 1. If (number_of_bits_to_return > max_number_of_bits), then return an
+ // ERROR_FLAG.
+ // 2. L = len (input_string)/8.
+ // 3. N = number_of_bits_to_return/8.
+ // Comment: L is the bitstring represention of
+ // the integer resulting from len (input_string)/8.
+ // L shall be represented as a 32-bit integer.
+ //
+ // Comment : N is the bitstring represention of
+ // the integer resulting from
+ // number_of_bits_to_return/8. N shall be
+ // represented as a 32-bit integer.
+ //
+ // 4. S = L || N || input_string || 0x80.
+ // 5. While (len (S) mod outlen)
+ // Comment : Pad S with zeros, if necessary.
+ // 0, S = S || 0x00.
+ //
+ // Comment : Compute the starting value.
+ // 6. temp = the Null string.
+ // 7. i = 0.
+ // 8. K = Leftmost keylen bits of 0x00010203...1D1E1F.
+ // 9. While len (temp) < keylen + outlen, do
+ //
+ // IV = i || 0outlen - len (i).
+ //
+ // 9.1
+ //
+ // temp = temp || BCC (K, (IV || S)).
+ //
+ // 9.2
+ //
+ // i = i + 1.
+ //
+ // 9.3
+ //
+ // Comment : i shall be represented as a 32-bit
+ // integer, i.e., len (i) = 32.
+ //
+ // Comment: The 32-bit integer represenation of
+ // i is padded with zeros to outlen bits.
+ //
+ // Comment: Compute the requested number of
+ // bits.
+ //
+ // 10. K = Leftmost keylen bits of temp.
+ //
+ // 11. X = Next outlen bits of temp.
+ //
+ // 12. temp = the Null string.
+ //
+ // 13. While len (temp) < number_of_bits_to_return, do
+ //
+ // 13.1 X = Block_Encrypt (K, X).
+ //
+ // 13.2 temp = temp || X.
+ //
+ // 14. requested_bits = Leftmost number_of_bits_to_return of temp.
+ //
+ // 15. Return SUCCESS and requested_bits.
+ private byte[] Block_Cipher_df(byte[] inputString, int bitLength)
+ {
+ int outLen = _engine.getBlockSize();
+ int L = inputString.length; // already in bytes
+ int N = bitLength / 8;
+ // 4 S = L || N || inputstring || 0x80
+ int sLen = 4 + 4 + L + 1;
+ int blockLen = ((sLen + outLen - 1) / outLen) * outLen;
+ byte[] S = new byte[blockLen];
+ copyIntToByteArray(S, L, 0);
+ copyIntToByteArray(S, N, 4);
+ System.arraycopy(inputString, 0, S, 8, L);
+ S[8 + L] = (byte)0x80;
+ // S already padded with zeros
+
+ byte[] temp = new byte[_keySizeInBits / 8 + outLen];
+ byte[] bccOut = new byte[outLen];
+
+ byte[] IV = new byte[outLen];
+
+ int i = 0;
+ byte[] K = new byte[_keySizeInBits / 8];
+ System.arraycopy(K_BITS, 0, K, 0, K.length);
+
+ while (i*outLen*8 < _keySizeInBits + outLen *8)
+ {
+ copyIntToByteArray(IV, i, 0);
+ BCC(bccOut, K, IV, S);
+
+ int bytesToCopy = ((temp.length - i * outLen) > outLen)
+ ? outLen
+ : (temp.length - i * outLen);
+
+ System.arraycopy(bccOut, 0, temp, i * outLen, bytesToCopy);
+ ++i;
+ }
+
+ byte[] X = new byte[outLen];
+ System.arraycopy(temp, 0, K, 0, K.length);
+ System.arraycopy(temp, K.length, X, 0, X.length);
+
+ temp = new byte[bitLength / 2];
+
+ i = 0;
+ _engine.init(true, new KeyParameter(expandKey(K)));
+
+ while (i * outLen < temp.length)
+ {
+ _engine.processBlock(X, 0, X, 0);
+
+ int bytesToCopy = ((temp.length - i * outLen) > outLen)
+ ? outLen
+ : (temp.length - i * outLen);
+
+ System.arraycopy(X, 0, temp, i * outLen, bytesToCopy);
+ i++;
+ }
+
+ return temp;
+ }
+
+ /*
+ * 1. chaining_value = 0^outlen
+ * . Comment: Set the first chaining value to outlen zeros.
+ * 2. n = len (data)/outlen.
+ * 3. Starting with the leftmost bits of data, split the data into n blocks of outlen bits
+ * each, forming block(1) to block(n).
+ * 4. For i = 1 to n do
+ * 4.1 input_block = chaining_value ^ block(i) .
+ * 4.2 chaining_value = Block_Encrypt (Key, input_block).
+ * 5. output_block = chaining_value.
+ * 6. Return output_block.
+ */
+ private void BCC(byte[] bccOut, byte[] k, byte[] iV, byte[] data)
+ {
+ int outlen = _engine.getBlockSize();
+ byte[] chainingValue = new byte[outlen]; // initial values = 0
+ int n = data.length / outlen;
+
+ byte[] inputBlock = new byte[outlen];
+
+ _engine.init(true, new KeyParameter(expandKey(k)));
+
+ _engine.processBlock(iV, 0, chainingValue, 0);
+
+ for (int i = 0; i < n; i++)
+ {
+ XOR(inputBlock, chainingValue, data, i*outlen);
+ _engine.processBlock(inputBlock, 0, chainingValue, 0);
+ }
+
+ System.arraycopy(chainingValue, 0, bccOut, 0, bccOut.length);
+ }
+
+ private void copyIntToByteArray(byte[] buf, int value, int offSet)
+ {
+ buf[offSet + 0] = ((byte)(value >> 24));
+ buf[offSet + 1] = ((byte)(value >> 16));
+ buf[offSet + 2] = ((byte)(value >> 8));
+ buf[offSet + 3] = ((byte)(value));
+ }
+
+ /**
+ * Return the block size (in bits) of the DRBG.
+ *
+ * @return the number of bits produced on each internal round of the DRBG.
+ */
+ public int getBlockSize()
+ {
+ return _V.length * 8;
+ }
+
+ /**
+ * Populate a passed in array with random data.
+ *
+ * @param output output array for generated bits.
+ * @param additionalInput additional input to be added to the DRBG in this step.
+ * @param predictionResistant true if a reseed should be forced, false otherwise.
+ *
+ * @return number of bits generated, -1 if a reseed required.
+ */
+ public int generate(byte[] output, byte[] additionalInput, boolean predictionResistant)
+ {
+ if (_isTDEA)
+ {
+ if (_reseedCounter > TDEA_RESEED_MAX)
+ {
+ return -1;
+ }
+
+ if (Utils.isTooLarge(output, TDEA_MAX_BITS_REQUEST / 8))
+ {
+ throw new IllegalArgumentException("Number of bits per request limited to " + TDEA_MAX_BITS_REQUEST);
+ }
+ }
+ else
+ {
+ if (_reseedCounter > AES_RESEED_MAX)
+ {
+ return -1;
+ }
+
+ if (Utils.isTooLarge(output, AES_MAX_BITS_REQUEST / 8))
+ {
+ throw new IllegalArgumentException("Number of bits per request limited to " + AES_MAX_BITS_REQUEST);
+ }
+ }
+
+ if (predictionResistant)
+ {
+ CTR_DRBG_Reseed_algorithm(_entropySource, additionalInput);
+ additionalInput = null;
+ }
+
+ if (additionalInput != null)
+ {
+ additionalInput = Block_Cipher_df(additionalInput, _seedLength);
+ CTR_DRBG_Update(additionalInput, _Key, _V);
+ }
+ else
+ {
+ additionalInput = new byte[_seedLength];
+ }
+
+ byte[] out = new byte[_V.length];
+
+ _engine.init(true, new KeyParameter(expandKey(_Key)));
+
+ for (int i = 0; i < output.length / out.length; i++)
+ {
+ addOneTo(_V);
+
+ _engine.processBlock(_V, 0, out, 0);
+
+ int bytesToCopy = ((output.length - i * out.length) > out.length)
+ ? out.length
+ : (output.length - i * _V.length);
+
+ System.arraycopy(out, 0, output, i * out.length, bytesToCopy);
+ }
+
+ CTR_DRBG_Update(additionalInput, _Key, _V);
+
+ _reseedCounter++;
+
+ return output.length * 8;
+ }
+
+ /**
+ * Reseed the DRBG.
+ *
+ * @param additionalInput additional input to be added to the DRBG in this step.
+ */
+ public void reseed(byte[] additionalInput)
+ {
+ CTR_DRBG_Reseed_algorithm(_entropySource, additionalInput);
+ }
+
+ private boolean isTDEA(BlockCipher cipher)
+ {
+ return cipher.getAlgorithmName().equals("DESede") || cipher.getAlgorithmName().equals("TDEA");
+ }
+
+ private int getMaxSecurityStrength(BlockCipher cipher, int keySizeInBits)
+ {
+ if (isTDEA(cipher) && keySizeInBits == 168)
+ {
+ return 112;
+ }
+ if (cipher.getAlgorithmName().equals("AES"))
+ {
+ return keySizeInBits;
+ }
+
+ return -1;
+ }
+
+ byte[] expandKey(byte[] key)
+ {
+ if (_isTDEA)
+ {
+ // expand key to 192 bits.
+ byte[] tmp = new byte[24];
+
+ padKey(key, 0, tmp, 0);
+ padKey(key, 7, tmp, 8);
+ padKey(key, 14, tmp, 16);
+
+ return tmp;
+ }
+ else
+ {
+ return key;
+ }
+ }
+
+ /**
+ * Pad out a key for TDEA, setting odd parity for each byte.
+ *
+ * @param keyMaster
+ * @param keyOff
+ * @param tmp
+ * @param tmpOff
+ */
+ private void padKey(byte[] keyMaster, int keyOff, byte[] tmp, int tmpOff)
+ {
+ tmp[tmpOff + 0] = (byte)(keyMaster[keyOff + 0] & 0xfe);
+ tmp[tmpOff + 1] = (byte)((keyMaster[keyOff + 0] << 7) | ((keyMaster[keyOff + 1] & 0xfc) >>> 1));
+ tmp[tmpOff + 2] = (byte)((keyMaster[keyOff + 1] << 6) | ((keyMaster[keyOff + 2] & 0xf8) >>> 2));
+ tmp[tmpOff + 3] = (byte)((keyMaster[keyOff + 2] << 5) | ((keyMaster[keyOff + 3] & 0xf0) >>> 3));
+ tmp[tmpOff + 4] = (byte)((keyMaster[keyOff + 3] << 4) | ((keyMaster[keyOff + 4] & 0xe0) >>> 4));
+ tmp[tmpOff + 5] = (byte)((keyMaster[keyOff + 4] << 3) | ((keyMaster[keyOff + 5] & 0xc0) >>> 5));
+ tmp[tmpOff + 6] = (byte)((keyMaster[keyOff + 5] << 2) | ((keyMaster[keyOff + 6] & 0x80) >>> 6));
+ tmp[tmpOff + 7] = (byte)(keyMaster[keyOff + 6] << 1);
+
+ for (int i = tmpOff; i <= tmpOff + 7; i++)
+ {
+ int b = tmp[i];
+ tmp[i] = (byte)((b & 0xfe) |
+ ((((b >> 1) ^
+ (b >> 2) ^
+ (b >> 3) ^
+ (b >> 4) ^
+ (b >> 5) ^
+ (b >> 6) ^
+ (b >> 7)) ^ 0x01) & 0x01));
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/prng/drbg/DualECPoints.java b/core/src/main/java/org/spongycastle/crypto/prng/drbg/DualECPoints.java
new file mode 100644
index 00000000..251b319f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/prng/drbg/DualECPoints.java
@@ -0,0 +1,82 @@
+package org.spongycastle.crypto.prng.drbg;
+
+import org.spongycastle.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>
+ *
+ * @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/core/src/main/java/org/spongycastle/crypto/prng/drbg/DualECSP800DRBG.java b/core/src/main/java/org/spongycastle/crypto/prng/drbg/DualECSP800DRBG.java
new file mode 100644
index 00000000..239ffe57
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/prng/drbg/DualECSP800DRBG.java
@@ -0,0 +1,320 @@
+package org.spongycastle.crypto.prng.drbg;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.nist.NISTNamedCurves;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.prng.EntropySource;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECMultiplier;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.ec.FixedPointCombMultiplier;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.BigIntegers;
+
+/**
+ * A SP800-90A Dual EC DRBG.
+ */
+public class DualECSP800DRBG
+ implements SP80090DRBG
+{
+ /*
+ * Default P, Q values for each curve
+ */
+ private static final BigInteger p256_Px = new BigInteger("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16);
+ private static final BigInteger p256_Py = new BigInteger("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16);
+ private static final BigInteger p256_Qx = new BigInteger("c97445f45cdef9f0d3e05e1e585fc297235b82b5be8ff3efca67c59852018192", 16);
+ private static final BigInteger p256_Qy = new BigInteger("b28ef557ba31dfcbdd21ac46e2a91e3c304f44cb87058ada2cb815151e610046", 16);
+
+ private static final BigInteger p384_Px = new BigInteger("aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7", 16);
+ private static final BigInteger p384_Py = new BigInteger("3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f", 16);
+ private static final BigInteger p384_Qx = new BigInteger("8e722de3125bddb05580164bfe20b8b432216a62926c57502ceede31c47816edd1e89769124179d0b695106428815065", 16);
+ private static final BigInteger p384_Qy = new BigInteger("023b1660dd701d0839fd45eec36f9ee7b32e13b315dc02610aa1b636e346df671f790f84c5e09b05674dbb7e45c803dd", 16);
+
+ private static final BigInteger p521_Px = new BigInteger("c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", 16);
+ private static final BigInteger p521_Py = new BigInteger("11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", 16);
+ 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);
+ private static final int MAX_PERSONALIZATION_STRING = 1 << (13 -1);
+
+ private Digest _digest;
+ private long _reseedCounter;
+ private EntropySource _entropySource;
+ private int _securityStrength;
+ private int _seedlen;
+ private int _outlen;
+ private ECCurve.Fp _curve;
+ private ECPoint _P;
+ private ECPoint _Q;
+ private byte[] _s;
+ private int _sLength;
+ private ECMultiplier _fixedPointMultiplier = new FixedPointCombMultiplier();
+
+ /**
+ * Construct a SP800-90A Dual EC DRBG.
+ * <p>
+ * Minimum entropy requirement is the security strength requested.
+ * </p>
+ * @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(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;
+
+ if (Utils.isTooLarge(personalizationString, MAX_PERSONALIZATION_STRING / 8))
+ {
+ throw new IllegalArgumentException("Personalization string too large");
+ }
+
+ if (entropySource.entropySize() < securityStrength || entropySource.entropySize() > MAX_ENTROPY_LENGTH)
+ {
+ throw new IllegalArgumentException("EntropySource must provide between " + securityStrength + " and " + MAX_ENTROPY_LENGTH + " bits");
+ }
+
+ byte[] entropy = entropySource.getEntropy();
+ byte[] seedMaterial = Arrays.concatenate(entropy, nonce, personalizationString);
+
+ for (int i = 0; i != pointSet.length; i++)
+ {
+ if (securityStrength <= pointSet[i].getSecurityStrength())
+ {
+ 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;
+ }
+ }
+
+ if (_P == null)
+ {
+ throw new IllegalArgumentException("security strength cannot be greater than 256 bits");
+ }
+
+ _s = Utils.hash_df(_digest, seedMaterial, _seedlen);
+ _sLength = _s.length;
+
+ _reseedCounter = 0;
+ }
+
+ /**
+ * Return the block size (in bits) of the DRBG.
+ *
+ * @return the number of bits produced on each internal round of the DRBG.
+ */
+ public int getBlockSize()
+ {
+ return _outlen * 8;
+ }
+
+ /**
+ * Populate a passed in array with random data.
+ *
+ * @param output output array for generated bits.
+ * @param additionalInput additional input to be added to the DRBG in this step.
+ * @param predictionResistant true if a reseed should be forced, false otherwise.
+ *
+ * @return number of bits generated, -1 if a reseed required.
+ */
+ public int generate(byte[] output, byte[] additionalInput, boolean predictionResistant)
+ {
+ int numberOfBits = output.length*8;
+ int m = output.length / _outlen;
+
+ if (Utils.isTooLarge(additionalInput, MAX_ADDITIONAL_INPUT / 8))
+ {
+ throw new IllegalArgumentException("Additional input too large");
+ }
+
+ if (_reseedCounter + m > RESEED_MAX)
+ {
+ return -1;
+ }
+
+ if (predictionResistant)
+ {
+ reseed(additionalInput);
+ 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++)
+ {
+ s = getScalarMultipleXCoord(_P, s);
+
+ //System.err.println("S: " + new String(Hex.encode(_s)));
+
+ byte[] r = getScalarMultipleXCoord(_Q, s).toByteArray();
+
+ if (r.length > _outlen)
+ {
+ System.arraycopy(r, r.length - _outlen, output, outOffset, _outlen);
+ }
+ else
+ {
+ System.arraycopy(r, 0, output, outOffset + (_outlen - r.length), r.length);
+ }
+
+ //System.err.println("R: " + new String(Hex.encode(r)));
+ outOffset += _outlen;
+
+ _reseedCounter++;
+ }
+
+ if (outOffset < output.length)
+ {
+ s = getScalarMultipleXCoord(_P, s);
+
+ byte[] r = getScalarMultipleXCoord(_Q, s).toByteArray();
+
+ int required = output.length - outOffset;
+
+ 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, getScalarMultipleXCoord(_P, s));
+
+ return numberOfBits;
+ }
+
+ /**
+ * Reseed the DRBG.
+ *
+ * @param additionalInput additional input to be added to the DRBG in this step.
+ */
+ public void reseed(byte[] additionalInput)
+ {
+ if (Utils.isTooLarge(additionalInput, MAX_ADDITIONAL_INPUT / 8))
+ {
+ throw new IllegalArgumentException("Additional input string too large");
+ }
+
+ byte[] entropy = _entropySource.getEntropy();
+ byte[] seedMaterial = Arrays.concatenate(pad8(_s, _seedlen), entropy, additionalInput);
+
+ _s = Utils.hash_df(_digest, seedMaterial, _seedlen);
+
+ _reseedCounter = 0;
+ }
+
+ private byte[] xor(byte[] a, byte[] b)
+ {
+ if (b == null)
+ {
+ return a;
+ }
+
+ byte[] rv = new byte[a.length];
+
+ for (int i = 0; i != rv.length; i++)
+ {
+ rv[i] = (byte)(a[i] ^ b[i]);
+ }
+
+ return rv;
+ }
+
+ // Note: works in place
+ private byte[] pad8(byte[] s, int seedlen)
+ {
+ if (seedlen % 8 == 0)
+ {
+ return s;
+ }
+
+ int shift = 8 - (seedlen % 8);
+ int carry = 0;
+
+ for (int i = s.length - 1; i >= 0; i--)
+ {
+ int b = s[i] & 0xff;
+ s[i] = (byte)((b << shift) | (carry >> (8 - shift)));
+ carry = b;
+ }
+
+ return s;
+ }
+
+ private BigInteger getScalarMultipleXCoord(ECPoint p, BigInteger s)
+ {
+ return _fixedPointMultiplier.multiply(p, s).normalize().getAffineXCoord().toBigInteger();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/prng/drbg/HMacSP800DRBG.java b/core/src/main/java/org/spongycastle/crypto/prng/drbg/HMacSP800DRBG.java
new file mode 100644
index 00000000..6d2d4247
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/prng/drbg/HMacSP800DRBG.java
@@ -0,0 +1,181 @@
+package org.spongycastle.crypto.prng.drbg;
+
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.prng.EntropySource;
+import org.spongycastle.util.Arrays;
+
+/**
+ * A SP800-90A HMAC DRBG.
+ */
+public class HMacSP800DRBG
+ implements SP80090DRBG
+{
+ private final static long RESEED_MAX = 1L << (48 - 1);
+ private final static int MAX_BITS_REQUEST = 1 << (19 - 1);
+
+ private byte[] _K;
+ private byte[] _V;
+ private long _reseedCounter;
+ private EntropySource _entropySource;
+ private Mac _hMac;
+
+ /**
+ * Construct a SP800-90A Hash DRBG.
+ * <p>
+ * Minimum entropy requirement is the security strength requested.
+ * </p>
+ * @param hMac Hash MAC to base the DRBG on.
+ * @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 HMacSP800DRBG(Mac hMac, int securityStrength, EntropySource entropySource, byte[] personalizationString, byte[] nonce)
+ {
+ if (securityStrength > Utils.getMaxSecurityStrength(hMac))
+ {
+ throw new IllegalArgumentException("Requested security strength is not supported by the derivation function");
+ }
+
+ if (entropySource.entropySize() < securityStrength)
+ {
+ throw new IllegalArgumentException("Not enough entropy for security strength required");
+ }
+
+ _entropySource = entropySource;
+ _hMac = hMac;
+
+ byte[] entropy = entropySource.getEntropy();
+ byte[] seedMaterial = Arrays.concatenate(entropy, nonce, personalizationString);
+
+ _K = new byte[hMac.getMacSize()];
+ _V = new byte[_K.length];
+ Arrays.fill(_V, (byte)1);
+
+ hmac_DRBG_Update(seedMaterial);
+
+ _reseedCounter = 1;
+ }
+
+ private void hmac_DRBG_Update(byte[] seedMaterial)
+ {
+ hmac_DRBG_Update_Func(seedMaterial, (byte)0x00);
+ if (seedMaterial != null)
+ {
+ hmac_DRBG_Update_Func(seedMaterial, (byte)0x01);
+ }
+ }
+
+ private void hmac_DRBG_Update_Func(byte[] seedMaterial, byte vValue)
+ {
+ _hMac.init(new KeyParameter(_K));
+
+ _hMac.update(_V, 0, _V.length);
+ _hMac.update(vValue);
+
+ if (seedMaterial != null)
+ {
+ _hMac.update(seedMaterial, 0, seedMaterial.length);
+ }
+
+ _hMac.doFinal(_K, 0);
+
+ _hMac.init(new KeyParameter(_K));
+ _hMac.update(_V, 0, _V.length);
+
+ _hMac.doFinal(_V, 0);
+ }
+
+ /**
+ * Return the block size (in bits) of the DRBG.
+ *
+ * @return the number of bits produced on each round of the DRBG.
+ */
+ public int getBlockSize()
+ {
+ return _V.length * 8;
+ }
+
+ /**
+ * Populate a passed in array with random data.
+ *
+ * @param output output array for generated bits.
+ * @param additionalInput additional input to be added to the DRBG in this step.
+ * @param predictionResistant true if a reseed should be forced, false otherwise.
+ *
+ * @return number of bits generated, -1 if a reseed required.
+ */
+ public int generate(byte[] output, byte[] additionalInput, boolean predictionResistant)
+ {
+ int numberOfBits = output.length * 8;
+
+ if (numberOfBits > MAX_BITS_REQUEST)
+ {
+ throw new IllegalArgumentException("Number of bits per request limited to " + MAX_BITS_REQUEST);
+ }
+
+ if (_reseedCounter > RESEED_MAX)
+ {
+ return -1;
+ }
+
+ if (predictionResistant)
+ {
+ reseed(additionalInput);
+ additionalInput = null;
+ }
+
+ // 2.
+ if (additionalInput != null)
+ {
+ hmac_DRBG_Update(additionalInput);
+ }
+
+ // 3.
+ byte[] rv = new byte[output.length];
+
+ int m = output.length / _V.length;
+
+ _hMac.init(new KeyParameter(_K));
+
+ for (int i = 0; i < m; i++)
+ {
+ _hMac.update(_V, 0, _V.length);
+ _hMac.doFinal(_V, 0);
+
+ System.arraycopy(_V, 0, rv, i * _V.length, _V.length);
+ }
+
+ if (m * _V.length < rv.length)
+ {
+ _hMac.update(_V, 0, _V.length);
+ _hMac.doFinal(_V, 0);
+
+ System.arraycopy(_V, 0, rv, m * _V.length, rv.length - (m * _V.length));
+ }
+
+ hmac_DRBG_Update(additionalInput);
+
+ _reseedCounter++;
+
+ System.arraycopy(rv, 0, output, 0, output.length);
+
+ return numberOfBits;
+ }
+
+ /**
+ * Reseed the DRBG.
+ *
+ * @param additionalInput additional input to be added to the DRBG in this step.
+ */
+ public void reseed(byte[] additionalInput)
+ {
+ byte[] entropy = _entropySource.getEntropy();
+ byte[] seedMaterial = Arrays.concatenate(entropy, additionalInput);
+
+ hmac_DRBG_Update(seedMaterial);
+
+ _reseedCounter = 1;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/prng/drbg/HashSP800DRBG.java b/core/src/main/java/org/spongycastle/crypto/prng/drbg/HashSP800DRBG.java
new file mode 100644
index 00000000..13498046
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/prng/drbg/HashSP800DRBG.java
@@ -0,0 +1,284 @@
+package org.spongycastle.crypto.prng.drbg;
+
+import java.util.Hashtable;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.prng.EntropySource;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Integers;
+
+/**
+ * A SP800-90A Hash DRBG.
+ */
+public class HashSP800DRBG
+ implements SP80090DRBG
+{
+ private final static byte[] ONE = { 0x01 };
+
+ private final static long RESEED_MAX = 1L << (48 - 1);
+ private final static int MAX_BITS_REQUEST = 1 << (19 - 1);
+
+ private final static Hashtable seedlens = new Hashtable();
+
+ static
+ {
+ seedlens.put("SHA-1", Integers.valueOf(440));
+ seedlens.put("SHA-224", Integers.valueOf(440));
+ seedlens.put("SHA-256", Integers.valueOf(440));
+ seedlens.put("SHA-512/256", Integers.valueOf(440));
+ seedlens.put("SHA-512/224", Integers.valueOf(440));
+ seedlens.put("SHA-384", Integers.valueOf(888));
+ seedlens.put("SHA-512", Integers.valueOf(888));
+ }
+
+ private Digest _digest;
+ private byte[] _V;
+ private byte[] _C;
+ private long _reseedCounter;
+ private EntropySource _entropySource;
+ private int _securityStrength;
+ private int _seedLength;
+
+ /**
+ * Construct a SP800-90A Hash DRBG.
+ * <p>
+ * Minimum entropy requirement is the security strength requested.
+ * </p>
+ * @param digest source digest to use for 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 HashSP800DRBG(Digest digest, int securityStrength, EntropySource entropySource, byte[] personalizationString, byte[] nonce)
+ {
+ if (securityStrength > Utils.getMaxSecurityStrength(digest))
+ {
+ throw new IllegalArgumentException("Requested security strength is not supported by the derivation function");
+ }
+
+ if (entropySource.entropySize() < securityStrength)
+ {
+ throw new IllegalArgumentException("Not enough entropy for security strength required");
+ }
+
+ _digest = digest;
+ _entropySource = entropySource;
+ _securityStrength = securityStrength;
+ _seedLength = ((Integer)seedlens.get(digest.getAlgorithmName())).intValue();
+
+ // 1. seed_material = entropy_input || nonce || personalization_string.
+ // 2. seed = Hash_df (seed_material, seedlen).
+ // 3. V = seed.
+ // 4. C = Hash_df ((0x00 || V), seedlen). Comment: Preceed V with a byte
+ // of zeros.
+ // 5. reseed_counter = 1.
+ // 6. Return V, C, and reseed_counter as the initial_working_state
+
+ byte[] entropy = entropySource.getEntropy();
+ byte[] seedMaterial = Arrays.concatenate(entropy, nonce, personalizationString);
+ byte[] seed = Utils.hash_df(_digest, seedMaterial, _seedLength);
+
+ _V = seed;
+ byte[] subV = new byte[_V.length + 1];
+ System.arraycopy(_V, 0, subV, 1, _V.length);
+ _C = Utils.hash_df(_digest, subV, _seedLength);
+
+ _reseedCounter = 1;
+ }
+
+ /**
+ * Return the block size (in bits) of the DRBG.
+ *
+ * @return the number of bits produced on each internal round of the DRBG.
+ */
+ public int getBlockSize()
+ {
+ return _digest.getDigestSize() * 8;
+ }
+
+ /**
+ * Populate a passed in array with random data.
+ *
+ * @param output output array for generated bits.
+ * @param additionalInput additional input to be added to the DRBG in this step.
+ * @param predictionResistant true if a reseed should be forced, false otherwise.
+ *
+ * @return number of bits generated, -1 if a reseed required.
+ */
+ public int generate(byte[] output, byte[] additionalInput, boolean predictionResistant)
+ {
+ // 1. If reseed_counter > reseed_interval, then return an indication that a
+ // reseed is required.
+ // 2. If (additional_input != Null), then do
+ // 2.1 w = Hash (0x02 || V || additional_input).
+ // 2.2 V = (V + w) mod 2^seedlen
+ // .
+ // 3. (returned_bits) = Hashgen (requested_number_of_bits, V).
+ // 4. H = Hash (0x03 || V).
+ // 5. V = (V + H + C + reseed_counter) mod 2^seedlen
+ // .
+ // 6. reseed_counter = reseed_counter + 1.
+ // 7. Return SUCCESS, returned_bits, and the new values of V, C, and
+ // reseed_counter for the new_working_state.
+ int numberOfBits = output.length*8;
+
+ if (numberOfBits > MAX_BITS_REQUEST)
+ {
+ throw new IllegalArgumentException("Number of bits per request limited to " + MAX_BITS_REQUEST);
+ }
+
+ if (_reseedCounter > RESEED_MAX)
+ {
+ return -1;
+ }
+
+ if (predictionResistant)
+ {
+ reseed(additionalInput);
+ additionalInput = null;
+ }
+
+ // 2.
+ if (additionalInput != null)
+ {
+ byte[] newInput = new byte[1 + _V.length + additionalInput.length];
+ newInput[0] = 0x02;
+ System.arraycopy(_V, 0, newInput, 1, _V.length);
+ // TODO: inOff / inLength
+ System.arraycopy(additionalInput, 0, newInput, 1 + _V.length, additionalInput.length);
+ byte[] w = hash(newInput);
+
+ addTo(_V, w);
+ }
+
+ // 3.
+ byte[] rv = hashgen(_V, numberOfBits);
+
+ // 4.
+ byte[] subH = new byte[_V.length + 1];
+ System.arraycopy(_V, 0, subH, 1, _V.length);
+ subH[0] = 0x03;
+
+ byte[] H = hash(subH);
+
+ // 5.
+ addTo(_V, H);
+ addTo(_V, _C);
+ byte[] c = new byte[4];
+ c[0] = (byte)(_reseedCounter >> 24);
+ c[1] = (byte)(_reseedCounter >> 16);
+ c[2] = (byte)(_reseedCounter >> 8);
+ c[3] = (byte)_reseedCounter;
+
+ addTo(_V, c);
+
+ _reseedCounter++;
+
+ System.arraycopy(rv, 0, output, 0, output.length);
+
+ return numberOfBits;
+ }
+
+ // this will always add the shorter length byte array mathematically to the
+ // longer length byte array.
+ // be careful....
+ private void addTo(byte[] longer, byte[] shorter)
+ {
+ int carry = 0;
+ for (int i=1;i <= shorter.length; i++) // warning
+ {
+ int res = (longer[longer.length-i] & 0xff) + (shorter[shorter.length-i] & 0xff) + carry;
+ carry = (res > 0xff) ? 1 : 0;
+ longer[longer.length-i] = (byte)res;
+ }
+
+ for (int i=shorter.length+1;i <= longer.length; i++) // warning
+ {
+ int res = (longer[longer.length-i] & 0xff) + carry;
+ carry = (res > 0xff) ? 1 : 0;
+ longer[longer.length-i] = (byte)res;
+ }
+ }
+
+ /**
+ * Reseed the DRBG.
+ *
+ * @param additionalInput additional input to be added to the DRBG in this step.
+ */
+ public void reseed(byte[] additionalInput)
+ {
+ // 1. seed_material = 0x01 || V || entropy_input || additional_input.
+ //
+ // 2. seed = Hash_df (seed_material, seedlen).
+ //
+ // 3. V = seed.
+ //
+ // 4. C = Hash_df ((0x00 || V), seedlen).
+ //
+ // 5. reseed_counter = 1.
+ //
+ // 6. Return V, C, and reseed_counter for the new_working_state.
+ //
+ // Comment: Precede with a byte of all zeros.
+ byte[] entropy = _entropySource.getEntropy();
+ byte[] seedMaterial = Arrays.concatenate(ONE, _V, entropy, additionalInput);
+ byte[] seed = Utils.hash_df(_digest, seedMaterial, _seedLength);
+
+ _V = seed;
+ byte[] subV = new byte[_V.length + 1];
+ subV[0] = 0x00;
+ System.arraycopy(_V, 0, subV, 1, _V.length);
+ _C = Utils.hash_df(_digest, subV, _seedLength);
+
+ _reseedCounter = 1;
+ }
+
+ private byte[] hash(byte[] input)
+ {
+ byte[] hash = new byte[_digest.getDigestSize()];
+ doHash(input, hash);
+ return hash;
+ }
+
+ private void doHash(byte[] input, byte[] output)
+ {
+ _digest.update(input, 0, input.length);
+ _digest.doFinal(output, 0);
+ }
+
+ // 1. m = [requested_number_of_bits / outlen]
+ // 2. data = V.
+ // 3. W = the Null string.
+ // 4. For i = 1 to m
+ // 4.1 wi = Hash (data).
+ // 4.2 W = W || wi.
+ // 4.3 data = (data + 1) mod 2^seedlen
+ // .
+ // 5. returned_bits = Leftmost (requested_no_of_bits) bits of W.
+ private byte[] hashgen(byte[] input, int lengthInBits)
+ {
+ int digestSize = _digest.getDigestSize();
+ int m = (lengthInBits / 8) / digestSize;
+
+ byte[] data = new byte[input.length];
+ System.arraycopy(input, 0, data, 0, input.length);
+
+ byte[] W = new byte[lengthInBits / 8];
+
+ byte[] dig = new byte[_digest.getDigestSize()];
+ for (int i = 0; i <= m; i++)
+ {
+ doHash(data, dig);
+
+ int bytesToCopy = ((W.length - i * dig.length) > dig.length)
+ ? dig.length
+ : (W.length - i * dig.length);
+ System.arraycopy(dig, 0, W, i * dig.length, bytesToCopy);
+
+ addTo(data, ONE);
+ }
+
+ return W;
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/crypto/prng/drbg/SP80090DRBG.java b/core/src/main/java/org/spongycastle/crypto/prng/drbg/SP80090DRBG.java
new file mode 100644
index 00000000..a1ec3b26
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/prng/drbg/SP80090DRBG.java
@@ -0,0 +1,32 @@
+package org.spongycastle.crypto.prng.drbg;
+
+/**
+ * Interface to SP800-90A deterministic random bit generators.
+ */
+public interface SP80090DRBG
+{
+ /**
+ * Return the block size of the DRBG.
+ *
+ * @return the block size (in bits) produced by each round of the DRBG.
+ */
+ int getBlockSize();
+
+ /**
+ * Populate a passed in array with random data.
+ *
+ * @param output output array for generated bits.
+ * @param additionalInput additional input to be added to the DRBG in this step.
+ * @param predictionResistant true if a reseed should be forced, false otherwise.
+ *
+ * @return number of bits generated, -1 if a reseed required.
+ */
+ int generate(byte[] output, byte[] additionalInput, boolean predictionResistant);
+
+ /**
+ * Reseed the DRBG.
+ *
+ * @param additionalInput additional input to be added to the DRBG in this step.
+ */
+ void reseed(byte[] additionalInput);
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/prng/drbg/Utils.java b/core/src/main/java/org/spongycastle/crypto/prng/drbg/Utils.java
new file mode 100644
index 00000000..bf2626d0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/prng/drbg/Utils.java
@@ -0,0 +1,103 @@
+package org.spongycastle.crypto.prng.drbg;
+
+import java.util.Hashtable;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.util.Integers;
+
+class Utils
+{
+ static final Hashtable maxSecurityStrengths = new Hashtable();
+
+ static
+ {
+ maxSecurityStrengths.put("SHA-1", Integers.valueOf(128));
+
+ maxSecurityStrengths.put("SHA-224", Integers.valueOf(192));
+ maxSecurityStrengths.put("SHA-256", Integers.valueOf(256));
+ maxSecurityStrengths.put("SHA-384", Integers.valueOf(256));
+ maxSecurityStrengths.put("SHA-512", Integers.valueOf(256));
+
+ maxSecurityStrengths.put("SHA-512/224", Integers.valueOf(192));
+ maxSecurityStrengths.put("SHA-512/256", Integers.valueOf(256));
+ }
+
+ static int getMaxSecurityStrength(Digest d)
+ {
+ return ((Integer)maxSecurityStrengths.get(d.getAlgorithmName())).intValue();
+ }
+
+ static int getMaxSecurityStrength(Mac m)
+ {
+ String name = m.getAlgorithmName();
+
+ return ((Integer)maxSecurityStrengths.get(name.substring(0, name.indexOf("/")))).intValue();
+ }
+
+ /**
+ * Used by both Dual EC and Hash.
+ */
+ static byte[] hash_df(Digest digest, byte[] seedMaterial, int seedLength)
+ {
+ // 1. temp = the Null string.
+ // 2. .
+ // 3. counter = an 8-bit binary value representing the integer "1".
+ // 4. For i = 1 to len do
+ // Comment : In step 4.1, no_of_bits_to_return
+ // is used as a 32-bit string.
+ // 4.1 temp = temp || Hash (counter || no_of_bits_to_return ||
+ // input_string).
+ // 4.2 counter = counter + 1.
+ // 5. requested_bits = Leftmost (no_of_bits_to_return) of temp.
+ // 6. Return SUCCESS and requested_bits.
+ byte[] temp = new byte[(seedLength + 7) / 8];
+
+ int len = temp.length / digest.getDigestSize();
+ int counter = 1;
+
+ byte[] dig = new byte[digest.getDigestSize()];
+
+ for (int i = 0; i <= len; i++)
+ {
+ digest.update((byte)counter);
+
+ digest.update((byte)(seedLength >> 24));
+ digest.update((byte)(seedLength >> 16));
+ digest.update((byte)(seedLength >> 8));
+ digest.update((byte)seedLength);
+
+ digest.update(seedMaterial, 0, seedMaterial.length);
+
+ digest.doFinal(dig, 0);
+
+ int bytesToCopy = ((temp.length - i * dig.length) > dig.length)
+ ? dig.length
+ : (temp.length - i * dig.length);
+ System.arraycopy(dig, 0, temp, i * dig.length, bytesToCopy);
+
+ counter++;
+ }
+
+ // do a left shift to get rid of excess bits.
+ if (seedLength % 8 != 0)
+ {
+ int shift = 8 - (seedLength % 8);
+ int carry = 0;
+
+ for (int i = 0; i != temp.length; i++)
+ {
+ int b = temp[i] & 0xff;
+ temp[i] = (byte)((b >>> shift) | (carry << (8 - shift)));
+ carry = b;
+ }
+ }
+
+ return temp;
+ }
+
+ static boolean isTooLarge(byte[] bytes, int maxBytes)
+ {
+ return bytes != null && bytes.length > maxBytes;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/signers/DSADigestSigner.java b/core/src/main/java/org/spongycastle/crypto/signers/DSADigestSigner.java
new file mode 100644
index 00000000..243752e5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/signers/DSADigestSigner.java
@@ -0,0 +1,163 @@
+package org.spongycastle.crypto.signers;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Encoding;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DSA;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.Signer;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+
+public class DSADigestSigner
+ implements Signer
+{
+ private final Digest digest;
+ private final DSA dsaSigner;
+ private boolean forSigning;
+
+ public DSADigestSigner(
+ DSA signer,
+ Digest digest)
+ {
+ this.digest = digest;
+ this.dsaSigner = signer;
+ }
+
+ public void init(
+ boolean forSigning,
+ CipherParameters parameters)
+ {
+ this.forSigning = forSigning;
+
+ AsymmetricKeyParameter k;
+
+ if (parameters instanceof ParametersWithRandom)
+ {
+ k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).getParameters();
+ }
+ else
+ {
+ k = (AsymmetricKeyParameter)parameters;
+ }
+
+ if (forSigning && !k.isPrivate())
+ {
+ throw new IllegalArgumentException("Signing Requires Private Key.");
+ }
+
+ if (!forSigning && k.isPrivate())
+ {
+ throw new IllegalArgumentException("Verification Requires Public Key.");
+ }
+
+ reset();
+
+ dsaSigner.init(forSigning, parameters);
+ }
+
+ /**
+ * update the internal digest with the byte b
+ */
+ public void update(
+ byte input)
+ {
+ digest.update(input);
+ }
+
+ /**
+ * update the internal digest with the byte array in
+ */
+ public void update(
+ byte[] input,
+ int inOff,
+ int length)
+ {
+ digest.update(input, inOff, length);
+ }
+
+ /**
+ * Generate a signature for the message we've been loaded with using
+ * the key we were initialised with.
+ */
+ public byte[] generateSignature()
+ {
+ if (!forSigning)
+ {
+ throw new IllegalStateException("DSADigestSigner not initialised for signature generation.");
+ }
+
+ byte[] hash = new byte[digest.getDigestSize()];
+ digest.doFinal(hash, 0);
+
+ BigInteger[] sig = dsaSigner.generateSignature(hash);
+
+ try
+ {
+ return derEncode(sig[0], sig[1]);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("unable to encode signature");
+ }
+ }
+
+ public boolean verifySignature(
+ byte[] signature)
+ {
+ if (forSigning)
+ {
+ throw new IllegalStateException("DSADigestSigner not initialised for verification");
+ }
+
+ byte[] hash = new byte[digest.getDigestSize()];
+ digest.doFinal(hash, 0);
+
+ try
+ {
+ BigInteger[] sig = derDecode(signature);
+ return dsaSigner.verifySignature(hash, sig[0], sig[1]);
+ }
+ catch (IOException e)
+ {
+ return false;
+ }
+ }
+
+ public void reset()
+ {
+ digest.reset();
+ }
+
+ private byte[] derEncode(
+ BigInteger r,
+ BigInteger s)
+ throws IOException
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(new ASN1Integer(r));
+ v.add(new ASN1Integer(s));
+
+ return new DERSequence(v).getEncoded(ASN1Encoding.DER);
+ }
+
+ private BigInteger[] derDecode(
+ byte[] encoding)
+ throws IOException
+ {
+ ASN1Sequence s = (ASN1Sequence)ASN1Primitive.fromByteArray(encoding);
+
+ return new BigInteger[]
+ {
+ ((ASN1Integer)s.getObjectAt(0)).getValue(),
+ ((ASN1Integer)s.getObjectAt(1)).getValue()
+ };
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/signers/DSAKCalculator.java b/core/src/main/java/org/spongycastle/crypto/signers/DSAKCalculator.java
new file mode 100644
index 00000000..6c8e1dc8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/signers/DSAKCalculator.java
@@ -0,0 +1,41 @@
+package org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/signers/DSASigner.java b/core/src/main/java/org/spongycastle/crypto/signers/DSASigner.java
new file mode 100644
index 00000000..c4988d2b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/signers/DSASigner.java
@@ -0,0 +1,168 @@
+package org.spongycastle.crypto.signers;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DSA;
+import org.spongycastle.crypto.params.DSAKeyParameters;
+import org.spongycastle.crypto.params.DSAParameters;
+import org.spongycastle.crypto.params.DSAPrivateKeyParameters;
+import org.spongycastle.crypto.params.DSAPublicKeyParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+
+/**
+ * The Digital Signature Algorithm - as described in "Handbook of Applied
+ * Cryptography", pages 452 - 453.
+ */
+public class DSASigner
+ implements DSA
+{
+ private final DSAKCalculator kCalculator;
+
+ 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,
+ CipherParameters param)
+ {
+ SecureRandom providedRandom = null;
+
+ if (forSigning)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.key = (DSAPrivateKeyParameters)rParam.getParameters();
+ providedRandom = rParam.getRandom();
+ }
+ else
+ {
+ this.key = (DSAPrivateKeyParameters)param;
+ }
+ }
+ else
+ {
+ this.key = (DSAPublicKeyParameters)param;
+ }
+
+ this.random = initSecureRandom(forSigning && !kCalculator.isDeterministic(), providedRandom);
+ }
+
+ /**
+ * generate a signature for the given message using the key we were
+ * initialised with. For conventional DSA the message should be a SHA-1
+ * hash of the message of interest.
+ *
+ * @param message the message that will be verified later.
+ */
+ public BigInteger[] generateSignature(
+ byte[] message)
+ {
+ DSAParameters params = key.getParameters();
+ BigInteger m = calculateE(params.getQ(), message);
+
+ if (kCalculator.isDeterministic())
+ {
+ kCalculator.init(params.getQ(), ((DSAPrivateKeyParameters)key).getX(), message);
+ }
+ else
+ {
+ kCalculator.init(params.getQ(), random);
+ }
+
+ BigInteger k = kCalculator.nextK();
+
+ BigInteger r = params.getG().modPow(k, params.getP()).mod(params.getQ());
+
+ k = k.modInverse(params.getQ()).multiply(
+ m.add(((DSAPrivateKeyParameters)key).getX().multiply(r)));
+
+ BigInteger s = k.mod(params.getQ());
+
+ BigInteger[] res = new BigInteger[2];
+
+ res[0] = r;
+ res[1] = s;
+
+ return res;
+ }
+
+ /**
+ * return true if the value r and s represent a DSA signature for
+ * the passed in message for standard DSA the message should be a
+ * SHA-1 hash of the real message to be verified.
+ */
+ public boolean verifySignature(
+ byte[] message,
+ BigInteger r,
+ BigInteger s)
+ {
+ DSAParameters params = key.getParameters();
+ BigInteger m = calculateE(params.getQ(), message);
+ BigInteger zero = BigInteger.valueOf(0);
+
+ if (zero.compareTo(r) >= 0 || params.getQ().compareTo(r) <= 0)
+ {
+ return false;
+ }
+
+ if (zero.compareTo(s) >= 0 || params.getQ().compareTo(s) <= 0)
+ {
+ return false;
+ }
+
+ BigInteger w = s.modInverse(params.getQ());
+
+ BigInteger u1 = m.multiply(w).mod(params.getQ());
+ BigInteger u2 = r.multiply(w).mod(params.getQ());
+
+ u1 = params.getG().modPow(u1, params.getP());
+ u2 = ((DSAPublicKeyParameters)key).getY().modPow(u2, params.getP());
+
+ BigInteger v = u1.multiply(u2).mod(params.getP()).mod(params.getQ());
+
+ return v.equals(r);
+ }
+
+ private BigInteger calculateE(BigInteger n, byte[] message)
+ {
+ if (n.bitLength() >= message.length * 8)
+ {
+ return new BigInteger(1, message);
+ }
+ else
+ {
+ byte[] trunc = new byte[n.bitLength() / 8];
+
+ System.arraycopy(message, 0, trunc, 0, trunc.length);
+
+ return new BigInteger(1, trunc);
+ }
+ }
+
+ protected SecureRandom initSecureRandom(boolean needed, SecureRandom provided)
+ {
+ return !needed ? null : (provided != null) ? provided : new SecureRandom();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/signers/DSTU4145Signer.java b/core/src/main/java/org/spongycastle/crypto/signers/DSTU4145Signer.java
new file mode 100644
index 00000000..f938f5cf
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/signers/DSTU4145Signer.java
@@ -0,0 +1,170 @@
+package org.spongycastle.crypto.signers;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DSA;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECKeyParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.math.ec.ECAlgorithms;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECMultiplier;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.ec.FixedPointCombMultiplier;
+import org.spongycastle.util.Arrays;
+
+/**
+ * DSTU 4145-2002
+ * <p>
+ * National Ukrainian standard of digital signature based on elliptic curves (DSTU 4145-2002).
+ * </p>
+ */
+public class DSTU4145Signer
+ implements DSA
+{
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ private ECKeyParameters key;
+ private SecureRandom random;
+
+ public void init(boolean forSigning, CipherParameters param)
+ {
+ if (forSigning)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.random = rParam.getRandom();
+ param = rParam.getParameters();
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ }
+
+ this.key = (ECPrivateKeyParameters)param;
+ }
+ else
+ {
+ this.key = (ECPublicKeyParameters)param;
+ }
+
+ }
+
+ public BigInteger[] generateSignature(byte[] message)
+ {
+ ECDomainParameters ec = key.getParameters();
+
+ ECCurve curve = ec.getCurve();
+
+ ECFieldElement h = hash2FieldElement(curve, message);
+ if (h.isZero())
+ {
+ h = curve.fromBigInteger(ONE);
+ }
+
+ BigInteger n = ec.getN();
+ BigInteger e, r, s;
+ ECFieldElement Fe, y;
+
+ BigInteger d = ((ECPrivateKeyParameters)key).getD();
+
+ ECMultiplier basePointMultiplier = createBasePointMultiplier();
+
+ do
+ {
+ do
+ {
+ do
+ {
+ e = generateRandomInteger(n, random);
+ Fe = basePointMultiplier.multiply(ec.getG(), e).normalize().getAffineXCoord();
+ }
+ while (Fe.isZero());
+
+ y = h.multiply(Fe);
+ r = fieldElement2Integer(n, y);
+ }
+ while (r.signum() == 0);
+
+ s = r.multiply(d).add(e).mod(n);
+ }
+ while (s.signum() == 0);
+
+ return new BigInteger[]{r, s};
+ }
+
+ public boolean verifySignature(byte[] message, BigInteger r, BigInteger s)
+ {
+ if (r.signum() <= 0 || s.signum() <= 0)
+ {
+ return false;
+ }
+
+ ECDomainParameters parameters = key.getParameters();
+
+ BigInteger n = parameters.getN();
+ if (r.compareTo(n) >= 0 || s.compareTo(n) >= 0)
+ {
+ return false;
+ }
+
+ ECCurve curve = parameters.getCurve();
+
+ ECFieldElement h = hash2FieldElement(curve, message);
+ if (h.isZero())
+ {
+ h = curve.fromBigInteger(ONE);
+ }
+
+ ECPoint R = ECAlgorithms.sumOfTwoMultiplies(parameters.getG(), s, ((ECPublicKeyParameters)key).getQ(), r).normalize();
+
+ // components must be bogus.
+ if (R.isInfinity())
+ {
+ return false;
+ }
+
+ ECFieldElement y = h.multiply(R.getAffineXCoord());
+ return fieldElement2Integer(n, y).compareTo(r) == 0;
+ }
+
+ protected ECMultiplier createBasePointMultiplier()
+ {
+ return new FixedPointCombMultiplier();
+ }
+
+ /**
+ * Generates random integer such, than its bit length is less than that of n
+ */
+ private static BigInteger generateRandomInteger(BigInteger n, SecureRandom random)
+ {
+ return new BigInteger(n.bitLength() - 1, random);
+ }
+
+ private static ECFieldElement hash2FieldElement(ECCurve curve, byte[] hash)
+ {
+ byte[] data = Arrays.reverse(hash);
+ return curve.fromBigInteger(truncate(new BigInteger(1, data), curve.getFieldSize()));
+ }
+
+ private static BigInteger fieldElement2Integer(BigInteger n, ECFieldElement fe)
+ {
+ return truncate(fe.toBigInteger(), n.bitLength() - 1);
+ }
+
+ private static BigInteger truncate(BigInteger x, int bitLength)
+ {
+ if (x.bitLength() > bitLength)
+ {
+ x = x.mod(ONE.shiftLeft(bitLength));
+ }
+ return x;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/signers/ECDSASigner.java b/core/src/main/java/org/spongycastle/crypto/signers/ECDSASigner.java
new file mode 100644
index 00000000..b0cfdf6c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/signers/ECDSASigner.java
@@ -0,0 +1,197 @@
+package org.spongycastle.crypto.signers;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DSA;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECKeyParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.math.ec.ECAlgorithms;
+import org.spongycastle.math.ec.ECConstants;
+import org.spongycastle.math.ec.ECMultiplier;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.ec.FixedPointCombMultiplier;
+
+/**
+ * EC-DSA as described in X9.62
+ */
+public class ECDSASigner
+ implements ECConstants, DSA
+{
+ private final DSAKCalculator kCalculator;
+
+ 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,
+ CipherParameters param)
+ {
+ SecureRandom providedRandom = null;
+
+ if (forSigning)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.key = (ECPrivateKeyParameters)rParam.getParameters();
+ providedRandom = rParam.getRandom();
+ }
+ else
+ {
+ this.key = (ECPrivateKeyParameters)param;
+ }
+ }
+ else
+ {
+ this.key = (ECPublicKeyParameters)param;
+ }
+
+ this.random = initSecureRandom(forSigning && !kCalculator.isDeterministic(), providedRandom);
+ }
+
+ // 5.3 pg 28
+ /**
+ * generate a signature for the given message using the key we were
+ * initialised with. For conventional DSA the message should be a SHA-1
+ * hash of the message of interest.
+ *
+ * @param message the message that will be verified later.
+ */
+ public BigInteger[] generateSignature(
+ byte[] message)
+ {
+ ECDomainParameters ec = key.getParameters();
+ BigInteger n = ec.getN();
+ BigInteger e = calculateE(n, message);
+ BigInteger d = ((ECPrivateKeyParameters)key).getD();
+
+ if (kCalculator.isDeterministic())
+ {
+ kCalculator.init(n, d, message);
+ }
+ else
+ {
+ kCalculator.init(n, random);
+ }
+
+ BigInteger r, s;
+
+ ECMultiplier basePointMultiplier = createBasePointMultiplier();
+
+ // 5.3.2
+ do // generate s
+ {
+ BigInteger k;
+ do // generate r
+ {
+ k = kCalculator.nextK();
+
+ ECPoint p = basePointMultiplier.multiply(ec.getG(), k).normalize();
+
+ // 5.3.3
+ r = p.getAffineXCoord().toBigInteger().mod(n);
+ }
+ while (r.equals(ZERO));
+
+ s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n);
+ }
+ while (s.equals(ZERO));
+
+ return new BigInteger[]{ r, s };
+ }
+
+ // 5.4 pg 29
+ /**
+ * return true if the value r and s represent a DSA signature for
+ * the passed in message (for standard DSA the message should be
+ * a SHA-1 hash of the real message to be verified).
+ */
+ public boolean verifySignature(
+ byte[] message,
+ BigInteger r,
+ BigInteger s)
+ {
+ ECDomainParameters ec = key.getParameters();
+ BigInteger n = ec.getN();
+ BigInteger e = calculateE(n, message);
+
+ // r in the range [1,n-1]
+ if (r.compareTo(ONE) < 0 || r.compareTo(n) >= 0)
+ {
+ return false;
+ }
+
+ // s in the range [1,n-1]
+ if (s.compareTo(ONE) < 0 || s.compareTo(n) >= 0)
+ {
+ return false;
+ }
+
+ BigInteger c = s.modInverse(n);
+
+ BigInteger u1 = e.multiply(c).mod(n);
+ BigInteger u2 = r.multiply(c).mod(n);
+
+ ECPoint G = ec.getG();
+ ECPoint Q = ((ECPublicKeyParameters)key).getQ();
+
+ ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, u1, Q, u2).normalize();
+
+ // components must be bogus.
+ if (point.isInfinity())
+ {
+ return false;
+ }
+
+ BigInteger v = point.getAffineXCoord().toBigInteger().mod(n);
+
+ return v.equals(r);
+ }
+
+ protected BigInteger calculateE(BigInteger n, byte[] message)
+ {
+ int log2n = n.bitLength();
+ int messageBitLength = message.length * 8;
+
+ BigInteger e = new BigInteger(1, message);
+ if (log2n < messageBitLength)
+ {
+ e = e.shiftRight(messageBitLength - log2n);
+ }
+ return e;
+ }
+
+ protected ECMultiplier createBasePointMultiplier()
+ {
+ return new FixedPointCombMultiplier();
+ }
+
+ protected SecureRandom initSecureRandom(boolean needed, SecureRandom provided)
+ {
+ return !needed ? null : (provided != null) ? provided : new SecureRandom();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/signers/ECGOST3410Signer.java b/core/src/main/java/org/spongycastle/crypto/signers/ECGOST3410Signer.java
new file mode 100644
index 00000000..92cc56ab
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/signers/ECGOST3410Signer.java
@@ -0,0 +1,160 @@
+package org.spongycastle.crypto.signers;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DSA;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECKeyParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.math.ec.ECAlgorithms;
+import org.spongycastle.math.ec.ECConstants;
+import org.spongycastle.math.ec.ECMultiplier;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.ec.FixedPointCombMultiplier;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * GOST R 34.10-2001 Signature Algorithm
+ */
+public class ECGOST3410Signer
+ implements DSA
+{
+ ECKeyParameters key;
+
+ SecureRandom random;
+
+ public void init(
+ boolean forSigning,
+ CipherParameters param)
+ {
+ if (forSigning)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.random = rParam.getRandom();
+ this.key = (ECPrivateKeyParameters)rParam.getParameters();
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ this.key = (ECPrivateKeyParameters)param;
+ }
+ }
+ else
+ {
+ this.key = (ECPublicKeyParameters)param;
+ }
+ }
+
+ /**
+ * generate a signature for the given message using the key we were
+ * initialised with. For conventional GOST3410 the message should be a GOST3411
+ * hash of the message of interest.
+ *
+ * @param message the message that will be verified later.
+ */
+ public BigInteger[] generateSignature(
+ byte[] message)
+ {
+ byte[] mRev = new byte[message.length]; // conversion is little-endian
+ for (int i = 0; i != mRev.length; i++)
+ {
+ mRev[i] = message[mRev.length - 1 - i];
+ }
+
+ BigInteger e = new BigInteger(1, mRev);
+
+ ECDomainParameters ec = key.getParameters();
+ BigInteger n = ec.getN();
+ BigInteger d = ((ECPrivateKeyParameters)key).getD();
+
+ BigInteger r, s;
+
+ ECMultiplier basePointMultiplier = createBasePointMultiplier();
+
+ do // generate s
+ {
+ BigInteger k;
+ do // generate r
+ {
+ do
+ {
+ k = new BigInteger(n.bitLength(), random);
+ }
+ while (k.equals(ECConstants.ZERO));
+
+ ECPoint p = basePointMultiplier.multiply(ec.getG(), k).normalize();
+
+ r = p.getAffineXCoord().toBigInteger().mod(n);
+ }
+ while (r.equals(ECConstants.ZERO));
+
+ s = (k.multiply(e)).add(d.multiply(r)).mod(n);
+ }
+ while (s.equals(ECConstants.ZERO));
+
+ return new BigInteger[]{ r, s };
+ }
+
+ /**
+ * return true if the value r and s represent a GOST3410 signature for
+ * the passed in message (for standard GOST3410 the message should be
+ * a GOST3411 hash of the real message to be verified).
+ */
+ public boolean verifySignature(
+ byte[] message,
+ BigInteger r,
+ BigInteger s)
+ {
+ byte[] mRev = new byte[message.length]; // conversion is little-endian
+ for (int i = 0; i != mRev.length; i++)
+ {
+ mRev[i] = message[mRev.length - 1 - i];
+ }
+
+ BigInteger e = new BigInteger(1, mRev);
+ BigInteger n = key.getParameters().getN();
+
+ // r in the range [1,n-1]
+ if (r.compareTo(ECConstants.ONE) < 0 || r.compareTo(n) >= 0)
+ {
+ return false;
+ }
+
+ // s in the range [1,n-1]
+ if (s.compareTo(ECConstants.ONE) < 0 || s.compareTo(n) >= 0)
+ {
+ return false;
+ }
+
+ BigInteger v = e.modInverse(n);
+
+ BigInteger z1 = s.multiply(v).mod(n);
+ BigInteger z2 = (n.subtract(r)).multiply(v).mod(n);
+
+ ECPoint G = key.getParameters().getG(); // P
+ ECPoint Q = ((ECPublicKeyParameters)key).getQ();
+
+ ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, z1, Q, z2).normalize();
+
+ // components must be bogus.
+ if (point.isInfinity())
+ {
+ return false;
+ }
+
+ BigInteger R = point.getAffineXCoord().toBigInteger().mod(n);
+
+ return R.equals(r);
+ }
+
+ protected ECMultiplier createBasePointMultiplier()
+ {
+ return new FixedPointCombMultiplier();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/signers/ECNRSigner.java b/core/src/main/java/org/spongycastle/crypto/signers/ECNRSigner.java
new file mode 100644
index 00000000..2fa90fb2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/signers/ECNRSigner.java
@@ -0,0 +1,188 @@
+package org.spongycastle.crypto.signers;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DSA;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.generators.ECKeyPairGenerator;
+import org.spongycastle.crypto.params.ECKeyGenerationParameters;
+import org.spongycastle.crypto.params.ECKeyParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.math.ec.ECAlgorithms;
+import org.spongycastle.math.ec.ECConstants;
+import org.spongycastle.math.ec.ECPoint;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * EC-NR as described in IEEE 1363-2000
+ */
+public class ECNRSigner
+ implements DSA
+{
+ private boolean forSigning;
+ private ECKeyParameters key;
+ private SecureRandom random;
+
+ public void init(
+ boolean forSigning,
+ CipherParameters param)
+ {
+ this.forSigning = forSigning;
+
+ if (forSigning)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.random = rParam.getRandom();
+ this.key = (ECPrivateKeyParameters)rParam.getParameters();
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ this.key = (ECPrivateKeyParameters)param;
+ }
+ }
+ else
+ {
+ this.key = (ECPublicKeyParameters)param;
+ }
+ }
+
+ // Section 7.2.5 ECSP-NR, pg 34
+ /**
+ * generate a signature for the given message using the key we were
+ * initialised with. Generally, the order of the curve should be at
+ * least as long as the hash of the message of interest, and with
+ * ECNR it *must* be at least as long.
+ *
+ * @param digest the digest to be signed.
+ * @exception DataLengthException if the digest is longer than the key allows
+ */
+ public BigInteger[] generateSignature(
+ byte[] digest)
+ {
+ if (! this.forSigning)
+ {
+ throw new IllegalStateException("not initialised for signing");
+ }
+
+ BigInteger n = ((ECPrivateKeyParameters)this.key).getParameters().getN();
+ int nBitLength = n.bitLength();
+
+ BigInteger e = new BigInteger(1, digest);
+ int eBitLength = e.bitLength();
+
+ ECPrivateKeyParameters privKey = (ECPrivateKeyParameters)key;
+
+ if (eBitLength > nBitLength)
+ {
+ throw new DataLengthException("input too large for ECNR key.");
+ }
+
+ BigInteger r = null;
+ BigInteger s = null;
+
+ AsymmetricCipherKeyPair tempPair;
+ do // generate r
+ {
+ // generate another, but very temporary, key pair using
+ // the same EC parameters
+ ECKeyPairGenerator keyGen = new ECKeyPairGenerator();
+
+ keyGen.init(new ECKeyGenerationParameters(privKey.getParameters(), this.random));
+
+ tempPair = keyGen.generateKeyPair();
+
+ // BigInteger Vx = tempPair.getPublic().getW().getAffineX();
+ ECPublicKeyParameters V = (ECPublicKeyParameters)tempPair.getPublic(); // get temp's public key
+ BigInteger Vx = V.getQ().getAffineXCoord().toBigInteger(); // get the point's x coordinate
+
+ r = Vx.add(e).mod(n);
+ }
+ while (r.equals(ECConstants.ZERO));
+
+ // generate s
+ BigInteger x = privKey.getD(); // private key value
+ BigInteger u = ((ECPrivateKeyParameters)tempPair.getPrivate()).getD(); // temp's private key value
+ s = u.subtract(r.multiply(x)).mod(n);
+
+ BigInteger[] res = new BigInteger[2];
+ res[0] = r;
+ res[1] = s;
+
+ return res;
+ }
+
+ // Section 7.2.6 ECVP-NR, pg 35
+ /**
+ * return true if the value r and s represent a signature for the
+ * message passed in. Generally, the order of the curve should be at
+ * least as long as the hash of the message of interest, and with
+ * ECNR, it *must* be at least as long. But just in case the signer
+ * applied mod(n) to the longer digest, this implementation will
+ * apply mod(n) during verification.
+ *
+ * @param digest the digest to be verified.
+ * @param r the r value of the signature.
+ * @param s the s value of the signature.
+ * @exception DataLengthException if the digest is longer than the key allows
+ */
+ public boolean verifySignature(
+ byte[] digest,
+ BigInteger r,
+ BigInteger s)
+ {
+ if (this.forSigning)
+ {
+ throw new IllegalStateException("not initialised for verifying");
+ }
+
+ ECPublicKeyParameters pubKey = (ECPublicKeyParameters)key;
+ BigInteger n = pubKey.getParameters().getN();
+ int nBitLength = n.bitLength();
+
+ BigInteger e = new BigInteger(1, digest);
+ int eBitLength = e.bitLength();
+
+ if (eBitLength > nBitLength)
+ {
+ throw new DataLengthException("input too large for ECNR key.");
+ }
+
+ // r in the range [1,n-1]
+ if (r.compareTo(ECConstants.ONE) < 0 || r.compareTo(n) >= 0)
+ {
+ return false;
+ }
+
+ // s in the range [0,n-1] NB: ECNR spec says 0
+ if (s.compareTo(ECConstants.ZERO) < 0 || s.compareTo(n) >= 0)
+ {
+ return false;
+ }
+
+ // compute P = sG + rW
+
+ ECPoint G = pubKey.getParameters().getG();
+ ECPoint W = pubKey.getQ();
+ // calculate P using Bouncy math
+ ECPoint P = ECAlgorithms.sumOfTwoMultiplies(G, s, W, r).normalize();
+
+ // components must be bogus.
+ if (P.isInfinity())
+ {
+ return false;
+ }
+
+ BigInteger x = P.getAffineXCoord().toBigInteger();
+ BigInteger t = r.subtract(x).mod(n);
+
+ return t.equals(e);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/signers/GOST3410Signer.java b/core/src/main/java/org/spongycastle/crypto/signers/GOST3410Signer.java
new file mode 100644
index 00000000..81d5d7a6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/signers/GOST3410Signer.java
@@ -0,0 +1,131 @@
+package org.spongycastle.crypto.signers;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DSA;
+import org.spongycastle.crypto.params.GOST3410KeyParameters;
+import org.spongycastle.crypto.params.GOST3410Parameters;
+import org.spongycastle.crypto.params.GOST3410PrivateKeyParameters;
+import org.spongycastle.crypto.params.GOST3410PublicKeyParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+
+/**
+ * GOST R 34.10-94 Signature Algorithm
+ */
+public class GOST3410Signer
+ implements DSA
+{
+ GOST3410KeyParameters key;
+
+ SecureRandom random;
+
+ public void init(
+ boolean forSigning,
+ CipherParameters param)
+ {
+ if (forSigning)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.random = rParam.getRandom();
+ this.key = (GOST3410PrivateKeyParameters)rParam.getParameters();
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ this.key = (GOST3410PrivateKeyParameters)param;
+ }
+ }
+ else
+ {
+ this.key = (GOST3410PublicKeyParameters)param;
+ }
+ }
+
+ /**
+ * generate a signature for the given message using the key we were
+ * initialised with. For conventional GOST3410 the message should be a GOST3411
+ * hash of the message of interest.
+ *
+ * @param message the message that will be verified later.
+ */
+ public BigInteger[] generateSignature(
+ byte[] message)
+ {
+ byte[] mRev = new byte[message.length]; // conversion is little-endian
+ for (int i = 0; i != mRev.length; i++)
+ {
+ mRev[i] = message[mRev.length - 1 - i];
+ }
+
+ BigInteger m = new BigInteger(1, mRev);
+ GOST3410Parameters params = key.getParameters();
+ BigInteger k;
+
+ do
+ {
+ k = new BigInteger(params.getQ().bitLength(), random);
+ }
+ while (k.compareTo(params.getQ()) >= 0);
+
+ BigInteger r = params.getA().modPow(k, params.getP()).mod(params.getQ());
+
+ BigInteger s = k.multiply(m).
+ add(((GOST3410PrivateKeyParameters)key).getX().multiply(r)).
+ mod(params.getQ());
+
+ BigInteger[] res = new BigInteger[2];
+
+ res[0] = r;
+ res[1] = s;
+
+ return res;
+ }
+
+ /**
+ * return true if the value r and s represent a GOST3410 signature for
+ * the passed in message for standard GOST3410 the message should be a
+ * GOST3411 hash of the real message to be verified.
+ */
+ public boolean verifySignature(
+ byte[] message,
+ BigInteger r,
+ BigInteger s)
+ {
+ byte[] mRev = new byte[message.length]; // conversion is little-endian
+ for (int i = 0; i != mRev.length; i++)
+ {
+ mRev[i] = message[mRev.length - 1 - i];
+ }
+
+ BigInteger m = new BigInteger(1, mRev);
+ GOST3410Parameters params = key.getParameters();
+ BigInteger zero = BigInteger.valueOf(0);
+
+ if (zero.compareTo(r) >= 0 || params.getQ().compareTo(r) <= 0)
+ {
+ return false;
+ }
+
+ if (zero.compareTo(s) >= 0 || params.getQ().compareTo(s) <= 0)
+ {
+ return false;
+ }
+
+ BigInteger v = m.modPow(params.getQ().subtract(new BigInteger("2")),params.getQ());
+
+ BigInteger z1 = s.multiply(v).mod(params.getQ());
+ BigInteger z2 = (params.getQ().subtract(r)).multiply(v).mod(params.getQ());
+
+ z1 = params.getA().modPow(z1, params.getP());
+ z2 = ((GOST3410PublicKeyParameters)key).getY().modPow(z2, params.getP());
+
+ BigInteger u = z1.multiply(z2).mod(params.getP()).mod(params.getQ());
+
+ return u.equals(r);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/signers/GenericSigner.java b/core/src/main/java/org/spongycastle/crypto/signers/GenericSigner.java
new file mode 100644
index 00000000..0df5a875
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/signers/GenericSigner.java
@@ -0,0 +1,136 @@
+package org.spongycastle.crypto.signers;
+
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.Signer;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.util.Arrays;
+
+public class GenericSigner
+ implements Signer
+{
+ private final AsymmetricBlockCipher engine;
+ private final Digest digest;
+ private boolean forSigning;
+
+ public GenericSigner(
+ AsymmetricBlockCipher engine,
+ Digest digest)
+ {
+ this.engine = engine;
+ this.digest = digest;
+ }
+
+ /**
+ * initialise the signer for signing or verification.
+ *
+ * @param forSigning
+ * true if for signing, false otherwise
+ * @param parameters
+ * necessary parameters.
+ */
+ public void init(
+ boolean forSigning,
+ CipherParameters parameters)
+ {
+ this.forSigning = forSigning;
+ AsymmetricKeyParameter k;
+
+ if (parameters instanceof ParametersWithRandom)
+ {
+ k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).getParameters();
+ }
+ else
+ {
+ k = (AsymmetricKeyParameter)parameters;
+ }
+
+ if (forSigning && !k.isPrivate())
+ {
+ throw new IllegalArgumentException("signing requires private key");
+ }
+
+ if (!forSigning && k.isPrivate())
+ {
+ throw new IllegalArgumentException("verification requires public key");
+ }
+
+ reset();
+
+ engine.init(forSigning, parameters);
+ }
+
+ /**
+ * update the internal digest with the byte b
+ */
+ public void update(
+ byte input)
+ {
+ digest.update(input);
+ }
+
+ /**
+ * update the internal digest with the byte array in
+ */
+ public void update(
+ byte[] input,
+ int inOff,
+ int length)
+ {
+ digest.update(input, inOff, length);
+ }
+
+ /**
+ * Generate a signature for the message we've been loaded with using the key
+ * we were initialised with.
+ */
+ public byte[] generateSignature()
+ throws CryptoException, DataLengthException
+ {
+ if (!forSigning)
+ {
+ throw new IllegalStateException("GenericSigner not initialised for signature generation.");
+ }
+
+ byte[] hash = new byte[digest.getDigestSize()];
+ digest.doFinal(hash, 0);
+
+ return engine.processBlock(hash, 0, hash.length);
+ }
+
+ /**
+ * return true if the internal state represents the signature described in
+ * the passed in array.
+ */
+ public boolean verifySignature(
+ byte[] signature)
+ {
+ if (forSigning)
+ {
+ throw new IllegalStateException("GenericSigner not initialised for verification");
+ }
+
+ byte[] hash = new byte[digest.getDigestSize()];
+ digest.doFinal(hash, 0);
+
+ try
+ {
+ byte[] sig = engine.processBlock(signature, 0, signature.length);
+
+ return Arrays.constantTimeAreEqual(sig, hash);
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+ }
+
+ public void reset()
+ {
+ digest.reset();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/signers/HMacDSAKCalculator.java b/core/src/main/java/org/spongycastle/crypto/signers/HMacDSAKCalculator.java
new file mode 100644
index 00000000..e919673f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/signers/HMacDSAKCalculator.java
@@ -0,0 +1,152 @@
+package org.spongycastle.crypto.signers;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.macs.HMac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.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);
+
+ int len = Math.min(t.length - tOff, V.length);
+ System.arraycopy(V, 0, t, tOff, len);
+ tOff += len;
+ }
+
+ BigInteger k = bitsToInt(t);
+
+ if (k.compareTo(ZERO) > 0 && k.compareTo(n) < 0)
+ {
+ return k;
+ }
+
+ 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);
+ }
+ }
+
+ 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/core/src/main/java/org/spongycastle/crypto/signers/ISO9796d2PSSSigner.java b/core/src/main/java/org/spongycastle/crypto/signers/ISO9796d2PSSSigner.java
new file mode 100644
index 00000000..5ebb1e28
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/signers/ISO9796d2PSSSigner.java
@@ -0,0 +1,668 @@
+package org.spongycastle.crypto.signers;
+
+import java.security.SecureRandom;
+import java.util.Hashtable;
+
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.SignerWithRecovery;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.params.ParametersWithSalt;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Integers;
+
+/**
+ * ISO9796-2 - mechanism using a hash function with recovery (scheme 2 and 3).
+ * <p>
+ * Note: the usual length for the salt is the length of the hash
+ * function used in bytes.
+ */
+public class ISO9796d2PSSSigner
+ implements SignerWithRecovery
+{
+ static final public int TRAILER_IMPLICIT = 0xBC;
+ static final public int TRAILER_RIPEMD160 = 0x31CC;
+ static final public int TRAILER_RIPEMD128 = 0x32CC;
+ static final public int TRAILER_SHA1 = 0x33CC;
+ static final public int TRAILER_SHA256 = 0x34CC;
+ static final public int TRAILER_SHA512 = 0x35CC;
+ static final public int TRAILER_SHA384 = 0x36CC;
+ static final public int TRAILER_WHIRLPOOL = 0x37CC;
+
+ private static Hashtable trailerMap = new Hashtable();
+
+ static
+ {
+ trailerMap.put("RIPEMD128", Integers.valueOf(TRAILER_RIPEMD128));
+ trailerMap.put("RIPEMD160", Integers.valueOf(TRAILER_RIPEMD160));
+
+ trailerMap.put("SHA-1", Integers.valueOf(TRAILER_SHA1));
+ trailerMap.put("SHA-256", Integers.valueOf(TRAILER_SHA256));
+ trailerMap.put("SHA-384", Integers.valueOf(TRAILER_SHA384));
+ trailerMap.put("SHA-512", Integers.valueOf(TRAILER_SHA512));
+
+ trailerMap.put("Whirlpool", Integers.valueOf(TRAILER_WHIRLPOOL));
+ }
+
+ private Digest digest;
+ private AsymmetricBlockCipher cipher;
+
+ private SecureRandom random;
+ private byte[] standardSalt;
+
+ private int hLen;
+ private int trailer;
+ private int keyBits;
+ private byte[] block;
+ private byte[] mBuf;
+ private int messageLength;
+ private int saltLength;
+ private boolean fullMessage;
+ private byte[] recoveredMessage;
+
+ private byte[] preSig;
+ private byte[] preBlock;
+ private int preMStart;
+ private int preTLength;
+
+ /**
+ * Generate a signer for the with either implicit or explicit trailers
+ * for ISO9796-2, scheme 2 or 3.
+ *
+ * @param cipher base cipher to use for signature creation/verification
+ * @param digest digest to use.
+ * @param saltLength length of salt in bytes.
+ * @param implicit whether or not the trailer is implicit or gives the hash.
+ */
+ public ISO9796d2PSSSigner(
+ AsymmetricBlockCipher cipher,
+ Digest digest,
+ int saltLength,
+ boolean implicit)
+ {
+ this.cipher = cipher;
+ this.digest = digest;
+ this.hLen = digest.getDigestSize();
+ this.saltLength = saltLength;
+
+ if (implicit)
+ {
+ trailer = TRAILER_IMPLICIT;
+ }
+ else
+ {
+ Integer trailerObj = (Integer)trailerMap.get(digest.getAlgorithmName());
+
+ if (trailerObj != null)
+ {
+ trailer = trailerObj.intValue();
+ }
+ else
+ {
+ throw new IllegalArgumentException("no valid trailer for digest");
+ }
+ }
+ }
+
+ /**
+ * Constructor for a signer with an explicit digest trailer.
+ *
+ * @param cipher cipher to use.
+ * @param digest digest to sign with.
+ * @param saltLength length of salt in bytes.
+ */
+ public ISO9796d2PSSSigner(
+ AsymmetricBlockCipher cipher,
+ Digest digest,
+ int saltLength)
+ {
+ this(cipher, digest, saltLength, false);
+ }
+
+ /**
+ * Initialise the signer.
+ *
+ * @param forSigning true if for signing, false if for verification.
+ * @param param parameters for signature generation/verification. If the
+ * parameters are for generation they should be a ParametersWithRandom,
+ * a ParametersWithSalt, or just an RSAKeyParameters object. If RSAKeyParameters
+ * are passed in a SecureRandom will be created.
+ * @throws IllegalArgumentException if wrong parameter type or a fixed
+ * salt is passed in which is the wrong length.
+ */
+ public void init(
+ boolean forSigning,
+ CipherParameters param)
+ {
+ RSAKeyParameters kParam;
+ int lengthOfSalt = saltLength;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom p = (ParametersWithRandom)param;
+
+ kParam = (RSAKeyParameters)p.getParameters();
+ if (forSigning)
+ {
+ random = p.getRandom();
+ }
+ }
+ else if (param instanceof ParametersWithSalt)
+ {
+ ParametersWithSalt p = (ParametersWithSalt)param;
+
+ kParam = (RSAKeyParameters)p.getParameters();
+ standardSalt = p.getSalt();
+ lengthOfSalt = standardSalt.length;
+ if (standardSalt.length != saltLength)
+ {
+ throw new IllegalArgumentException("Fixed salt is of wrong length");
+ }
+ }
+ else
+ {
+ kParam = (RSAKeyParameters)param;
+ if (forSigning)
+ {
+ random = new SecureRandom();
+ }
+ }
+
+ cipher.init(forSigning, kParam);
+
+ keyBits = kParam.getModulus().bitLength();
+
+ block = new byte[(keyBits + 7) / 8];
+
+ if (trailer == TRAILER_IMPLICIT)
+ {
+ mBuf = new byte[block.length - digest.getDigestSize() - lengthOfSalt - 1 - 1];
+ }
+ else
+ {
+ mBuf = new byte[block.length - digest.getDigestSize() - lengthOfSalt - 1 - 2];
+ }
+
+ reset();
+ }
+
+ /**
+ * compare two byte arrays - constant time
+ */
+ private boolean isSameAs(
+ byte[] a,
+ byte[] b)
+ {
+ boolean isOkay = true;
+
+ if (messageLength != b.length)
+ {
+ isOkay = false;
+ }
+
+ for (int i = 0; i != b.length; i++)
+ {
+ if (a[i] != b[i])
+ {
+ isOkay = false;
+ }
+ }
+
+ return isOkay;
+ }
+
+ /**
+ * clear possible sensitive data
+ */
+ private void clearBlock(
+ byte[] block)
+ {
+ for (int i = 0; i != block.length; i++)
+ {
+ block[i] = 0;
+ }
+ }
+
+ public void updateWithRecoveredMessage(byte[] signature)
+ throws InvalidCipherTextException
+ {
+ byte[] block = cipher.processBlock(signature, 0, signature.length);
+
+ //
+ // adjust block size for leading zeroes if necessary
+ //
+ if (block.length < (keyBits + 7) / 8)
+ {
+ byte[] tmp = new byte[(keyBits + 7) / 8];
+
+ System.arraycopy(block, 0, tmp, tmp.length - block.length, block.length);
+ clearBlock(block);
+ block = tmp;
+ }
+
+ int tLength;
+
+ if (((block[block.length - 1] & 0xFF) ^ 0xBC) == 0)
+ {
+ tLength = 1;
+ }
+ else
+ {
+ int sigTrail = ((block[block.length - 2] & 0xFF) << 8) | (block[block.length - 1] & 0xFF);
+
+ Integer trailerObj = (Integer)trailerMap.get(digest.getAlgorithmName());
+
+ if (trailerObj != null)
+ {
+ if (sigTrail != trailerObj.intValue())
+ {
+ throw new IllegalStateException("signer initialised with wrong digest for trailer " + sigTrail);
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("unrecognised hash in signature");
+ }
+
+ tLength = 2;
+ }
+
+ //
+ // calculate H(m2)
+ //
+ byte[] m2Hash = new byte[hLen];
+ digest.doFinal(m2Hash, 0);
+
+ //
+ // remove the mask
+ //
+ byte[] dbMask = maskGeneratorFunction1(block, block.length - hLen - tLength, hLen, block.length - hLen - tLength);
+ for (int i = 0; i != dbMask.length; i++)
+ {
+ block[i] ^= dbMask[i];
+ }
+
+ block[0] &= 0x7f;
+
+ //
+ // find out how much padding we've got
+ //
+ int mStart = 0;
+ for (; mStart != block.length; mStart++)
+ {
+ if (block[mStart] == 0x01)
+ {
+ break;
+ }
+ }
+
+ mStart++;
+
+ if (mStart >= block.length)
+ {
+ clearBlock(block);
+ }
+
+ fullMessage = (mStart > 1);
+
+ recoveredMessage = new byte[dbMask.length - mStart - saltLength];
+
+ System.arraycopy(block, mStart, recoveredMessage, 0, recoveredMessage.length);
+ System.arraycopy(recoveredMessage, 0, mBuf, 0, recoveredMessage.length);
+
+ preSig = signature;
+ preBlock = block;
+ preMStart = mStart;
+ preTLength = tLength;
+ }
+
+ /**
+ * update the internal digest with the byte b
+ */
+ public void update(
+ byte b)
+ {
+ if (preSig == null && messageLength < mBuf.length)
+ {
+ mBuf[messageLength++] = b;
+ }
+ else
+ {
+ digest.update(b);
+ }
+ }
+
+ /**
+ * update the internal digest with the byte array in
+ */
+ public void update(
+ byte[] in,
+ int off,
+ int len)
+ {
+ if (preSig == null)
+ {
+ while (len > 0 && messageLength < mBuf.length)
+ {
+ this.update(in[off]);
+ off++;
+ len--;
+ }
+ }
+
+ if (len > 0)
+ {
+ digest.update(in, off, len);
+ }
+ }
+
+ /**
+ * reset the internal state
+ */
+ public void reset()
+ {
+ digest.reset();
+ messageLength = 0;
+ if (mBuf != null)
+ {
+ clearBlock(mBuf);
+ }
+ if (recoveredMessage != null)
+ {
+ clearBlock(recoveredMessage);
+ recoveredMessage = null;
+ }
+ fullMessage = false;
+ if (preSig != null)
+ {
+ preSig = null;
+ clearBlock(preBlock);
+ preBlock = null;
+ }
+ }
+
+ /**
+ * generate a signature for the loaded message using the key we were
+ * initialised with.
+ */
+ public byte[] generateSignature()
+ throws CryptoException
+ {
+ int digSize = digest.getDigestSize();
+
+ byte[] m2Hash = new byte[digSize];
+
+ digest.doFinal(m2Hash, 0);
+
+ byte[] C = new byte[8];
+ LtoOSP(messageLength * 8, C);
+
+ digest.update(C, 0, C.length);
+
+ digest.update(mBuf, 0, messageLength);
+
+ digest.update(m2Hash, 0, m2Hash.length);
+
+ byte[] salt;
+
+ if (standardSalt != null)
+ {
+ salt = standardSalt;
+ }
+ else
+ {
+ salt = new byte[saltLength];
+ random.nextBytes(salt);
+ }
+
+ digest.update(salt, 0, salt.length);
+
+ byte[] hash = new byte[digest.getDigestSize()];
+
+ digest.doFinal(hash, 0);
+
+ int tLength = 2;
+ if (trailer == TRAILER_IMPLICIT)
+ {
+ tLength = 1;
+ }
+
+ int off = block.length - messageLength - salt.length - hLen - tLength - 1;
+
+ block[off] = 0x01;
+
+ System.arraycopy(mBuf, 0, block, off + 1, messageLength);
+ System.arraycopy(salt, 0, block, off + 1 + messageLength, salt.length);
+
+ byte[] dbMask = maskGeneratorFunction1(hash, 0, hash.length, block.length - hLen - tLength);
+ for (int i = 0; i != dbMask.length; i++)
+ {
+ block[i] ^= dbMask[i];
+ }
+
+ System.arraycopy(hash, 0, block, block.length - hLen - tLength, hLen);
+
+ if (trailer == TRAILER_IMPLICIT)
+ {
+ block[block.length - 1] = (byte)TRAILER_IMPLICIT;
+ }
+ else
+ {
+ block[block.length - 2] = (byte)(trailer >>> 8);
+ block[block.length - 1] = (byte)trailer;
+ }
+
+ block[0] &= 0x7f;
+
+ byte[] b = cipher.processBlock(block, 0, block.length);
+
+ clearBlock(mBuf);
+ clearBlock(block);
+ messageLength = 0;
+
+ return b;
+ }
+
+ /**
+ * return true if the signature represents a ISO9796-2 signature
+ * for the passed in message.
+ */
+ public boolean verifySignature(
+ byte[] signature)
+ {
+ //
+ // calculate H(m2)
+ //
+ byte[] m2Hash = new byte[hLen];
+ digest.doFinal(m2Hash, 0);
+
+ byte[] block;
+ int tLength;
+ int mStart = 0;
+
+ if (preSig == null)
+ {
+ try
+ {
+ updateWithRecoveredMessage(signature);
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (!Arrays.areEqual(preSig, signature))
+ {
+ throw new IllegalStateException("updateWithRecoveredMessage called on different signature");
+ }
+ }
+
+ block = preBlock;
+ mStart = preMStart;
+ tLength = preTLength;
+
+ preSig = null;
+ preBlock = null;
+
+ //
+ // check the hashes
+ //
+ byte[] C = new byte[8];
+ LtoOSP(recoveredMessage.length * 8, C);
+
+ digest.update(C, 0, C.length);
+
+ if (recoveredMessage.length != 0)
+ {
+ digest.update(recoveredMessage, 0, recoveredMessage.length);
+ }
+
+ digest.update(m2Hash, 0, m2Hash.length);
+
+ // Update for the salt
+ digest.update(block, mStart + recoveredMessage.length, saltLength);
+
+ byte[] hash = new byte[digest.getDigestSize()];
+ digest.doFinal(hash, 0);
+
+ int off = block.length - tLength - hash.length;
+
+ boolean isOkay = true;
+
+ for (int i = 0; i != hash.length; i++)
+ {
+ if (hash[i] != block[off + i])
+ {
+ isOkay = false;
+ }
+ }
+
+ clearBlock(block);
+ clearBlock(hash);
+
+ if (!isOkay)
+ {
+ fullMessage = false;
+ clearBlock(recoveredMessage);
+ return false;
+ }
+
+ //
+ // if they've input a message check what we've recovered against
+ // what was input.
+ //
+ if (messageLength != 0)
+ {
+ if (!isSameAs(mBuf, recoveredMessage))
+ {
+ clearBlock(mBuf);
+ return false;
+ }
+ messageLength = 0;
+ }
+
+ clearBlock(mBuf);
+ return true;
+ }
+
+ /**
+ * Return true if the full message was recoveredMessage.
+ *
+ * @return true on full message recovery, false otherwise, or if not sure.
+ * @see org.spongycastle.crypto.SignerWithRecovery#hasFullMessage()
+ */
+ public boolean hasFullMessage()
+ {
+ return fullMessage;
+ }
+
+ /**
+ * Return a reference to the recoveredMessage message.
+ *
+ * @return the full/partial recoveredMessage message.
+ * @see org.spongycastle.crypto.SignerWithRecovery#getRecoveredMessage()
+ */
+ public byte[] getRecoveredMessage()
+ {
+ return recoveredMessage;
+ }
+
+ /**
+ * int to octet string.
+ */
+ private void ItoOSP(
+ int i,
+ byte[] sp)
+ {
+ sp[0] = (byte)(i >>> 24);
+ sp[1] = (byte)(i >>> 16);
+ sp[2] = (byte)(i >>> 8);
+ sp[3] = (byte)(i >>> 0);
+ }
+
+ /**
+ * long to octet string.
+ */
+ private void LtoOSP(
+ long l,
+ byte[] sp)
+ {
+ sp[0] = (byte)(l >>> 56);
+ sp[1] = (byte)(l >>> 48);
+ sp[2] = (byte)(l >>> 40);
+ sp[3] = (byte)(l >>> 32);
+ sp[4] = (byte)(l >>> 24);
+ sp[5] = (byte)(l >>> 16);
+ sp[6] = (byte)(l >>> 8);
+ sp[7] = (byte)(l >>> 0);
+ }
+
+ /**
+ * mask generator function, as described in PKCS1v2.
+ */
+ private byte[] maskGeneratorFunction1(
+ byte[] Z,
+ int zOff,
+ int zLen,
+ int length)
+ {
+ byte[] mask = new byte[length];
+ byte[] hashBuf = new byte[hLen];
+ byte[] C = new byte[4];
+ int counter = 0;
+
+ digest.reset();
+
+ while (counter < (length / hLen))
+ {
+ ItoOSP(counter, C);
+
+ digest.update(Z, zOff, zLen);
+ digest.update(C, 0, C.length);
+ digest.doFinal(hashBuf, 0);
+
+ System.arraycopy(hashBuf, 0, mask, counter * hLen, hLen);
+
+ counter++;
+ }
+
+ if ((counter * hLen) < length)
+ {
+ ItoOSP(counter, C);
+
+ digest.update(Z, zOff, zLen);
+ digest.update(C, 0, C.length);
+ digest.doFinal(hashBuf, 0);
+
+ System.arraycopy(hashBuf, 0, mask, counter * hLen, mask.length - (counter * hLen));
+ }
+
+ return mask;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/signers/ISO9796d2Signer.java b/core/src/main/java/org/spongycastle/crypto/signers/ISO9796d2Signer.java
new file mode 100644
index 00000000..7047d1ee
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/signers/ISO9796d2Signer.java
@@ -0,0 +1,618 @@
+package org.spongycastle.crypto.signers;
+
+import java.util.Hashtable;
+
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.SignerWithRecovery;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Integers;
+
+/**
+ * ISO9796-2 - mechanism using a hash function with recovery (scheme 1)
+ */
+public class ISO9796d2Signer
+ implements SignerWithRecovery
+{
+ static final public int TRAILER_IMPLICIT = 0xBC;
+ static final public int TRAILER_RIPEMD160 = 0x31CC;
+ static final public int TRAILER_RIPEMD128 = 0x32CC;
+ static final public int TRAILER_SHA1 = 0x33CC;
+ static final public int TRAILER_SHA256 = 0x34CC;
+ static final public int TRAILER_SHA512 = 0x35CC;
+ static final public int TRAILER_SHA384 = 0x36CC;
+ static final public int TRAILER_WHIRLPOOL = 0x37CC;
+
+ private static Hashtable trailerMap = new Hashtable();
+
+ static
+ {
+ trailerMap.put("RIPEMD128", Integers.valueOf(TRAILER_RIPEMD128));
+ trailerMap.put("RIPEMD160", Integers.valueOf(TRAILER_RIPEMD160));
+
+ trailerMap.put("SHA-1", Integers.valueOf(TRAILER_SHA1));
+ trailerMap.put("SHA-256", Integers.valueOf(TRAILER_SHA256));
+ trailerMap.put("SHA-384", Integers.valueOf(TRAILER_SHA384));
+ trailerMap.put("SHA-512", Integers.valueOf(TRAILER_SHA512));
+
+ trailerMap.put("Whirlpool", Integers.valueOf(TRAILER_WHIRLPOOL));
+ }
+
+ private Digest digest;
+ private AsymmetricBlockCipher cipher;
+
+ private int trailer;
+ private int keyBits;
+ private byte[] block;
+ private byte[] mBuf;
+ private int messageLength;
+ private boolean fullMessage;
+ private byte[] recoveredMessage;
+
+ private byte[] preSig;
+ private byte[] preBlock;
+
+ /**
+ * Generate a signer for the with either implicit or explicit trailers
+ * for ISO9796-2.
+ *
+ * @param cipher base cipher to use for signature creation/verification
+ * @param digest digest to use.
+ * @param implicit whether or not the trailer is implicit or gives the hash.
+ */
+ public ISO9796d2Signer(
+ AsymmetricBlockCipher cipher,
+ Digest digest,
+ boolean implicit)
+ {
+ this.cipher = cipher;
+ this.digest = digest;
+
+ if (implicit)
+ {
+ trailer = TRAILER_IMPLICIT;
+ }
+ else
+ {
+ Integer trailerObj = (Integer)trailerMap.get(digest.getAlgorithmName());
+
+ if (trailerObj != null)
+ {
+ trailer = trailerObj.intValue();
+ }
+ else
+ {
+ throw new IllegalArgumentException("no valid trailer for digest");
+ }
+ }
+ }
+
+ /**
+ * Constructor for a signer with an explicit digest trailer.
+ *
+ * @param cipher cipher to use.
+ * @param digest digest to sign with.
+ */
+ public ISO9796d2Signer(
+ AsymmetricBlockCipher cipher,
+ Digest digest)
+ {
+ this(cipher, digest, false);
+ }
+
+ public void init(
+ boolean forSigning,
+ CipherParameters param)
+ {
+ RSAKeyParameters kParam = (RSAKeyParameters)param;
+
+ cipher.init(forSigning, kParam);
+
+ keyBits = kParam.getModulus().bitLength();
+
+ block = new byte[(keyBits + 7) / 8];
+
+ if (trailer == TRAILER_IMPLICIT)
+ {
+ mBuf = new byte[block.length - digest.getDigestSize() - 2];
+ }
+ else
+ {
+ mBuf = new byte[block.length - digest.getDigestSize() - 3];
+ }
+
+ reset();
+ }
+
+ /**
+ * compare two byte arrays - constant time
+ */
+ private boolean isSameAs(
+ byte[] a,
+ byte[] b)
+ {
+ boolean isOkay = true;
+
+ if (messageLength > mBuf.length)
+ {
+ if (mBuf.length > b.length)
+ {
+ isOkay = false;
+ }
+
+ for (int i = 0; i != mBuf.length; i++)
+ {
+ if (a[i] != b[i])
+ {
+ isOkay = false;
+ }
+ }
+ }
+ else
+ {
+ if (messageLength != b.length)
+ {
+ isOkay = false;
+ }
+
+ for (int i = 0; i != b.length; i++)
+ {
+ if (a[i] != b[i])
+ {
+ isOkay = false;
+ }
+ }
+ }
+
+ return isOkay;
+ }
+
+ /**
+ * clear possible sensitive data
+ */
+ private void clearBlock(
+ byte[] block)
+ {
+ for (int i = 0; i != block.length; i++)
+ {
+ block[i] = 0;
+ }
+ }
+
+ public void updateWithRecoveredMessage(byte[] signature)
+ throws InvalidCipherTextException
+ {
+ byte[] block = cipher.processBlock(signature, 0, signature.length);
+
+ if (((block[0] & 0xC0) ^ 0x40) != 0)
+ {
+ throw new InvalidCipherTextException("malformed signature");
+ }
+
+ if (((block[block.length - 1] & 0xF) ^ 0xC) != 0)
+ {
+ throw new InvalidCipherTextException("malformed signature");
+ }
+
+ int delta = 0;
+
+ if (((block[block.length - 1] & 0xFF) ^ 0xBC) == 0)
+ {
+ delta = 1;
+ }
+ else
+ {
+ int sigTrail = ((block[block.length - 2] & 0xFF) << 8) | (block[block.length - 1] & 0xFF);
+ Integer trailerObj = (Integer)trailerMap.get(digest.getAlgorithmName());
+
+ if (trailerObj != null)
+ {
+ if (sigTrail != trailerObj.intValue())
+ {
+ throw new IllegalStateException("signer initialised with wrong digest for trailer " + sigTrail);
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("unrecognised hash in signature");
+ }
+
+ delta = 2;
+ }
+
+ //
+ // find out how much padding we've got
+ //
+ int mStart = 0;
+
+ for (mStart = 0; mStart != block.length; mStart++)
+ {
+ if (((block[mStart] & 0x0f) ^ 0x0a) == 0)
+ {
+ break;
+ }
+ }
+
+ mStart++;
+
+ int off = block.length - delta - digest.getDigestSize();
+
+ //
+ // there must be at least one byte of message string
+ //
+ if ((off - mStart) <= 0)
+ {
+ throw new InvalidCipherTextException("malformed block");
+ }
+
+ //
+ // if we contain the whole message as well, check the hash of that.
+ //
+ if ((block[0] & 0x20) == 0)
+ {
+ fullMessage = true;
+
+ recoveredMessage = new byte[off - mStart];
+ System.arraycopy(block, mStart, recoveredMessage, 0, recoveredMessage.length);
+ }
+ else
+ {
+ fullMessage = false;
+
+ recoveredMessage = new byte[off - mStart];
+ System.arraycopy(block, mStart, recoveredMessage, 0, recoveredMessage.length);
+ }
+
+ preSig = signature;
+ preBlock = block;
+
+ digest.update(recoveredMessage, 0, recoveredMessage.length);
+ messageLength = recoveredMessage.length;
+ System.arraycopy(recoveredMessage, 0, mBuf, 0, recoveredMessage.length);
+ }
+
+ /**
+ * update the internal digest with the byte b
+ */
+ public void update(
+ byte b)
+ {
+ digest.update(b);
+
+ if (messageLength < mBuf.length)
+ {
+ mBuf[messageLength] = b;
+ }
+
+ messageLength++;
+ }
+
+ /**
+ * update the internal digest with the byte array in
+ */
+ public void update(
+ byte[] in,
+ int off,
+ int len)
+ {
+ while (len > 0 && messageLength < mBuf.length)
+ {
+ this.update(in[off]);
+ off++;
+ len--;
+ }
+
+ digest.update(in, off, len);
+ messageLength += len;
+ }
+
+ /**
+ * reset the internal state
+ */
+ public void reset()
+ {
+ digest.reset();
+ messageLength = 0;
+ clearBlock(mBuf);
+
+ if (recoveredMessage != null)
+ {
+ clearBlock(recoveredMessage);
+ }
+
+ recoveredMessage = null;
+ fullMessage = false;
+
+ if (preSig != null)
+ {
+ preSig = null;
+ clearBlock(preBlock);
+ preBlock = null;
+ }
+ }
+
+ /**
+ * generate a signature for the loaded message using the key we were
+ * initialised with.
+ */
+ public byte[] generateSignature()
+ throws CryptoException
+ {
+ int digSize = digest.getDigestSize();
+
+ int t = 0;
+ int delta = 0;
+
+ if (trailer == TRAILER_IMPLICIT)
+ {
+ t = 8;
+ delta = block.length - digSize - 1;
+ digest.doFinal(block, delta);
+ block[block.length - 1] = (byte)TRAILER_IMPLICIT;
+ }
+ else
+ {
+ t = 16;
+ delta = block.length - digSize - 2;
+ digest.doFinal(block, delta);
+ block[block.length - 2] = (byte)(trailer >>> 8);
+ block[block.length - 1] = (byte)trailer;
+ }
+
+ byte header = 0;
+ int x = (digSize + messageLength) * 8 + t + 4 - keyBits;
+
+ if (x > 0)
+ {
+ int mR = messageLength - ((x + 7) / 8);
+ header = 0x60;
+
+ delta -= mR;
+
+ System.arraycopy(mBuf, 0, block, delta, mR);
+ }
+ else
+ {
+ header = 0x40;
+ delta -= messageLength;
+
+ System.arraycopy(mBuf, 0, block, delta, messageLength);
+ }
+
+ if ((delta - 1) > 0)
+ {
+ for (int i = delta - 1; i != 0; i--)
+ {
+ block[i] = (byte)0xbb;
+ }
+ block[delta - 1] ^= (byte)0x01;
+ block[0] = (byte)0x0b;
+ block[0] |= header;
+ }
+ else
+ {
+ block[0] = (byte)0x0a;
+ block[0] |= header;
+ }
+
+ byte[] b = cipher.processBlock(block, 0, block.length);
+
+ clearBlock(mBuf);
+ clearBlock(block);
+
+ return b;
+ }
+
+ /**
+ * return true if the signature represents a ISO9796-2 signature
+ * for the passed in message.
+ */
+ public boolean verifySignature(
+ byte[] signature)
+ {
+ byte[] block = null;
+
+ if (preSig == null)
+ {
+ try
+ {
+ block = cipher.processBlock(signature, 0, signature.length);
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (!Arrays.areEqual(preSig, signature))
+ {
+ throw new IllegalStateException("updateWithRecoveredMessage called on different signature");
+ }
+
+ block = preBlock;
+
+ preSig = null;
+ preBlock = null;
+ }
+
+ if (((block[0] & 0xC0) ^ 0x40) != 0)
+ {
+ return returnFalse(block);
+ }
+
+ if (((block[block.length - 1] & 0xF) ^ 0xC) != 0)
+ {
+ return returnFalse(block);
+ }
+
+ int delta = 0;
+
+ if (((block[block.length - 1] & 0xFF) ^ 0xBC) == 0)
+ {
+ delta = 1;
+ }
+ else
+ {
+ int sigTrail = ((block[block.length - 2] & 0xFF) << 8) | (block[block.length - 1] & 0xFF);
+ Integer trailerObj = (Integer)trailerMap.get(digest.getAlgorithmName());
+
+ if (trailerObj != null)
+ {
+ if (sigTrail != trailerObj.intValue())
+ {
+ throw new IllegalStateException("signer initialised with wrong digest for trailer " + sigTrail);
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("unrecognised hash in signature");
+ }
+
+ delta = 2;
+ }
+
+ //
+ // find out how much padding we've got
+ //
+ int mStart = 0;
+
+ for (mStart = 0; mStart != block.length; mStart++)
+ {
+ if (((block[mStart] & 0x0f) ^ 0x0a) == 0)
+ {
+ break;
+ }
+ }
+
+ mStart++;
+
+ //
+ // check the hashes
+ //
+ byte[] hash = new byte[digest.getDigestSize()];
+
+ int off = block.length - delta - hash.length;
+
+ //
+ // there must be at least one byte of message string
+ //
+ if ((off - mStart) <= 0)
+ {
+ return returnFalse(block);
+ }
+
+ //
+ // if we contain the whole message as well, check the hash of that.
+ //
+ if ((block[0] & 0x20) == 0)
+ {
+ fullMessage = true;
+
+ // check right number of bytes passed in.
+ if (messageLength > off - mStart)
+ {
+ return returnFalse(block);
+ }
+
+ digest.reset();
+ digest.update(block, mStart, off - mStart);
+ digest.doFinal(hash, 0);
+
+ boolean isOkay = true;
+
+ for (int i = 0; i != hash.length; i++)
+ {
+ block[off + i] ^= hash[i];
+ if (block[off + i] != 0)
+ {
+ isOkay = false;
+ }
+ }
+
+ if (!isOkay)
+ {
+ return returnFalse(block);
+ }
+
+ recoveredMessage = new byte[off - mStart];
+ System.arraycopy(block, mStart, recoveredMessage, 0, recoveredMessage.length);
+ }
+ else
+ {
+ fullMessage = false;
+
+ digest.doFinal(hash, 0);
+
+ boolean isOkay = true;
+
+ for (int i = 0; i != hash.length; i++)
+ {
+ block[off + i] ^= hash[i];
+ if (block[off + i] != 0)
+ {
+ isOkay = false;
+ }
+ }
+
+ if (!isOkay)
+ {
+ return returnFalse(block);
+ }
+
+ recoveredMessage = new byte[off - mStart];
+ System.arraycopy(block, mStart, recoveredMessage, 0, recoveredMessage.length);
+ }
+
+ //
+ // if they've input a message check what we've recovered against
+ // what was input.
+ //
+ if (messageLength != 0)
+ {
+ if (!isSameAs(mBuf, recoveredMessage))
+ {
+ return returnFalse(block);
+ }
+ }
+
+ clearBlock(mBuf);
+ clearBlock(block);
+
+ return true;
+ }
+
+ private boolean returnFalse(byte[] block)
+ {
+ clearBlock(mBuf);
+ clearBlock(block);
+
+ return false;
+ }
+
+ /**
+ * Return true if the full message was recoveredMessage.
+ *
+ * @return true on full message recovery, false otherwise.
+ * @see org.spongycastle.crypto.SignerWithRecovery#hasFullMessage()
+ */
+ public boolean hasFullMessage()
+ {
+ return fullMessage;
+ }
+
+ /**
+ * Return a reference to the recoveredMessage message.
+ *
+ * @return the full/partial recoveredMessage message.
+ * @see org.spongycastle.crypto.SignerWithRecovery#getRecoveredMessage()
+ */
+ public byte[] getRecoveredMessage()
+ {
+ return recoveredMessage;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/signers/PSSSigner.java b/core/src/main/java/org/spongycastle/crypto/signers/PSSSigner.java
new file mode 100644
index 00000000..3fb8bf50
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/signers/PSSSigner.java
@@ -0,0 +1,348 @@
+package org.spongycastle.crypto.signers;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.Signer;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.params.RSABlindingParameters;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+
+/**
+ * RSA-PSS as described in PKCS# 1 v 2.1.
+ * <p>
+ * Note: the usual value for the salt length is the number of
+ * bytes in the hash function.
+ */
+public class PSSSigner
+ implements Signer
+{
+ static final public byte TRAILER_IMPLICIT = (byte)0xBC;
+
+ private Digest contentDigest;
+ private Digest mgfDigest;
+ private AsymmetricBlockCipher cipher;
+ private SecureRandom random;
+
+ private int hLen;
+ private int mgfhLen;
+ private int sLen;
+ private int emBits;
+ private byte[] salt;
+ private byte[] mDash;
+ private byte[] block;
+ private byte trailer;
+
+ /**
+ * basic constructor
+ *
+ * @param cipher the asymmetric cipher to use.
+ * @param digest the digest to use.
+ * @param sLen the length of the salt to use (in bytes).
+ */
+ public PSSSigner(
+ AsymmetricBlockCipher cipher,
+ Digest digest,
+ int sLen)
+ {
+ this(cipher, digest, sLen, TRAILER_IMPLICIT);
+ }
+
+ public PSSSigner(
+ AsymmetricBlockCipher cipher,
+ Digest contentDigest,
+ Digest mgfDigest,
+ int sLen)
+ {
+ this(cipher, contentDigest, mgfDigest, sLen, TRAILER_IMPLICIT);
+ }
+
+ public PSSSigner(
+ AsymmetricBlockCipher cipher,
+ Digest digest,
+ int sLen,
+ byte trailer)
+ {
+ this(cipher, digest, digest, sLen, trailer);
+ }
+
+ public PSSSigner(
+ AsymmetricBlockCipher cipher,
+ Digest contentDigest,
+ Digest mgfDigest,
+ int sLen,
+ byte trailer)
+ {
+ this.cipher = cipher;
+ this.contentDigest = contentDigest;
+ this.mgfDigest = mgfDigest;
+ this.hLen = contentDigest.getDigestSize();
+ this.mgfhLen = mgfDigest.getDigestSize();
+ this.sLen = sLen;
+ this.salt = new byte[sLen];
+ this.mDash = new byte[8 + sLen + hLen];
+ this.trailer = trailer;
+ }
+
+ public void init(
+ boolean forSigning,
+ CipherParameters param)
+ {
+ CipherParameters params;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom p = (ParametersWithRandom)param;
+
+ params = p.getParameters();
+ random = p.getRandom();
+ }
+ else
+ {
+ params = param;
+ if (forSigning)
+ {
+ random = new SecureRandom();
+ }
+ }
+
+ cipher.init(forSigning, params);
+
+ RSAKeyParameters kParam;
+
+ if (params instanceof RSABlindingParameters)
+ {
+ kParam = ((RSABlindingParameters)params).getPublicKey();
+ }
+ else
+ {
+ kParam = (RSAKeyParameters)params;
+ }
+
+ emBits = kParam.getModulus().bitLength() - 1;
+
+ if (emBits < (8 * hLen + 8 * sLen + 9))
+ {
+ throw new IllegalArgumentException("key too small for specified hash and salt lengths");
+ }
+
+ block = new byte[(emBits + 7) / 8];
+
+ reset();
+ }
+
+ /**
+ * clear possible sensitive data
+ */
+ private void clearBlock(
+ byte[] block)
+ {
+ for (int i = 0; i != block.length; i++)
+ {
+ block[i] = 0;
+ }
+ }
+
+ /**
+ * update the internal digest with the byte b
+ */
+ public void update(
+ byte b)
+ {
+ contentDigest.update(b);
+ }
+
+ /**
+ * update the internal digest with the byte array in
+ */
+ public void update(
+ byte[] in,
+ int off,
+ int len)
+ {
+ contentDigest.update(in, off, len);
+ }
+
+ /**
+ * reset the internal state
+ */
+ public void reset()
+ {
+ contentDigest.reset();
+ }
+
+ /**
+ * generate a signature for the message we've been loaded with using
+ * the key we were initialised with.
+ */
+ public byte[] generateSignature()
+ throws CryptoException, DataLengthException
+ {
+ contentDigest.doFinal(mDash, mDash.length - hLen - sLen);
+
+ if (sLen != 0)
+ {
+ random.nextBytes(salt);
+
+ System.arraycopy(salt, 0, mDash, mDash.length - sLen, sLen);
+ }
+
+ byte[] h = new byte[hLen];
+
+ contentDigest.update(mDash, 0, mDash.length);
+
+ contentDigest.doFinal(h, 0);
+
+ block[block.length - sLen - 1 - hLen - 1] = 0x01;
+ System.arraycopy(salt, 0, block, block.length - sLen - hLen - 1, sLen);
+
+ byte[] dbMask = maskGeneratorFunction1(h, 0, h.length, block.length - hLen - 1);
+ for (int i = 0; i != dbMask.length; i++)
+ {
+ block[i] ^= dbMask[i];
+ }
+
+ block[0] &= (0xff >> ((block.length * 8) - emBits));
+
+ System.arraycopy(h, 0, block, block.length - hLen - 1, hLen);
+
+ block[block.length - 1] = trailer;
+
+ byte[] b = cipher.processBlock(block, 0, block.length);
+
+ clearBlock(block);
+
+ return b;
+ }
+
+ /**
+ * return true if the internal state represents the signature described
+ * in the passed in array.
+ */
+ public boolean verifySignature(
+ byte[] signature)
+ {
+ contentDigest.doFinal(mDash, mDash.length - hLen - sLen);
+
+ try
+ {
+ byte[] b = cipher.processBlock(signature, 0, signature.length);
+ System.arraycopy(b, 0, block, block.length - b.length, b.length);
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+
+ if (block[block.length - 1] != trailer)
+ {
+ clearBlock(block);
+ return false;
+ }
+
+ byte[] dbMask = maskGeneratorFunction1(block, block.length - hLen - 1, hLen, block.length - hLen - 1);
+
+ for (int i = 0; i != dbMask.length; i++)
+ {
+ block[i] ^= dbMask[i];
+ }
+
+ block[0] &= (0xff >> ((block.length * 8) - emBits));
+
+ for (int i = 0; i != block.length - hLen - sLen - 2; i++)
+ {
+ if (block[i] != 0)
+ {
+ clearBlock(block);
+ return false;
+ }
+ }
+
+ if (block[block.length - hLen - sLen - 2] != 0x01)
+ {
+ clearBlock(block);
+ return false;
+ }
+
+ System.arraycopy(block, block.length - sLen - hLen - 1, mDash, mDash.length - sLen, sLen);
+
+ contentDigest.update(mDash, 0, mDash.length);
+ contentDigest.doFinal(mDash, mDash.length - hLen);
+
+ for (int i = block.length - hLen - 1, j = mDash.length - hLen;
+ j != mDash.length; i++, j++)
+ {
+ if ((block[i] ^ mDash[j]) != 0)
+ {
+ clearBlock(mDash);
+ clearBlock(block);
+ return false;
+ }
+ }
+
+ clearBlock(mDash);
+ clearBlock(block);
+
+ return true;
+ }
+
+ /**
+ * int to octet string.
+ */
+ private void ItoOSP(
+ int i,
+ byte[] sp)
+ {
+ sp[0] = (byte)(i >>> 24);
+ sp[1] = (byte)(i >>> 16);
+ sp[2] = (byte)(i >>> 8);
+ sp[3] = (byte)(i >>> 0);
+ }
+
+ /**
+ * mask generator function, as described in PKCS1v2.
+ */
+ private byte[] maskGeneratorFunction1(
+ byte[] Z,
+ int zOff,
+ int zLen,
+ int length)
+ {
+ byte[] mask = new byte[length];
+ byte[] hashBuf = new byte[mgfhLen];
+ byte[] C = new byte[4];
+ int counter = 0;
+
+ mgfDigest.reset();
+
+ while (counter < (length / mgfhLen))
+ {
+ ItoOSP(counter, C);
+
+ mgfDigest.update(Z, zOff, zLen);
+ mgfDigest.update(C, 0, C.length);
+ mgfDigest.doFinal(hashBuf, 0);
+
+ System.arraycopy(hashBuf, 0, mask, counter * mgfhLen, mgfhLen);
+
+ counter++;
+ }
+
+ if ((counter * mgfhLen) < length)
+ {
+ ItoOSP(counter, C);
+
+ mgfDigest.update(Z, zOff, zLen);
+ mgfDigest.update(C, 0, C.length);
+ mgfDigest.doFinal(hashBuf, 0);
+
+ System.arraycopy(hashBuf, 0, mask, counter * mgfhLen, mask.length - (counter * mgfhLen));
+ }
+
+ return mask;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/signers/RSADigestSigner.java b/core/src/main/java/org/spongycastle/crypto/signers/RSADigestSigner.java
new file mode 100644
index 00000000..2fe248e4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/signers/RSADigestSigner.java
@@ -0,0 +1,240 @@
+package org.spongycastle.crypto.signers;
+
+import java.io.IOException;
+import java.util.Hashtable;
+
+import org.spongycastle.asn1.ASN1Encoding;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.DERNull;
+import org.spongycastle.asn1.nist.NISTObjectIdentifiers;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.DigestInfo;
+import org.spongycastle.asn1.x509.X509ObjectIdentifiers;
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.Signer;
+import org.spongycastle.crypto.encodings.PKCS1Encoding;
+import org.spongycastle.crypto.engines.RSABlindedEngine;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.util.Arrays;
+
+public class RSADigestSigner
+ implements Signer
+{
+ private final AsymmetricBlockCipher rsaEngine = new PKCS1Encoding(new RSABlindedEngine());
+ private final AlgorithmIdentifier algId;
+ private final Digest digest;
+ private boolean forSigning;
+
+ private static final Hashtable oidMap = new Hashtable();
+
+ /*
+ * Load OID table.
+ */
+ static
+ {
+ oidMap.put("RIPEMD128", TeleTrusTObjectIdentifiers.ripemd128);
+ oidMap.put("RIPEMD160", TeleTrusTObjectIdentifiers.ripemd160);
+ oidMap.put("RIPEMD256", TeleTrusTObjectIdentifiers.ripemd256);
+
+ oidMap.put("SHA-1", X509ObjectIdentifiers.id_SHA1);
+ oidMap.put("SHA-224", NISTObjectIdentifiers.id_sha224);
+ oidMap.put("SHA-256", NISTObjectIdentifiers.id_sha256);
+ oidMap.put("SHA-384", NISTObjectIdentifiers.id_sha384);
+ oidMap.put("SHA-512", NISTObjectIdentifiers.id_sha512);
+ oidMap.put("SHA-512/224", NISTObjectIdentifiers.id_sha512_224);
+ oidMap.put("SHA-512/256", NISTObjectIdentifiers.id_sha512_256);
+
+ oidMap.put("MD2", PKCSObjectIdentifiers.md2);
+ oidMap.put("MD4", PKCSObjectIdentifiers.md4);
+ oidMap.put("MD5", PKCSObjectIdentifiers.md5);
+ }
+
+ public RSADigestSigner(
+ Digest digest)
+ {
+ this(digest, (ASN1ObjectIdentifier)oidMap.get(digest.getAlgorithmName()));
+ }
+
+ public RSADigestSigner(
+ Digest digest,
+ ASN1ObjectIdentifier digestOid)
+ {
+ this.digest = digest;
+ this.algId = new AlgorithmIdentifier(digestOid, DERNull.INSTANCE);
+ }
+
+ /**
+ * @deprecated
+ */
+ public String getAlgorithmName()
+ {
+ return digest.getAlgorithmName() + "withRSA";
+ }
+
+ /**
+ * initialise the signer for signing or verification.
+ *
+ * @param forSigning
+ * true if for signing, false otherwise
+ * @param parameters
+ * necessary parameters.
+ */
+ public void init(
+ boolean forSigning,
+ CipherParameters parameters)
+ {
+ this.forSigning = forSigning;
+ AsymmetricKeyParameter k;
+
+ if (parameters instanceof ParametersWithRandom)
+ {
+ k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).getParameters();
+ }
+ else
+ {
+ k = (AsymmetricKeyParameter)parameters;
+ }
+
+ if (forSigning && !k.isPrivate())
+ {
+ throw new IllegalArgumentException("signing requires private key");
+ }
+
+ if (!forSigning && k.isPrivate())
+ {
+ throw new IllegalArgumentException("verification requires public key");
+ }
+
+ reset();
+
+ rsaEngine.init(forSigning, parameters);
+ }
+
+ /**
+ * update the internal digest with the byte b
+ */
+ public void update(
+ byte input)
+ {
+ digest.update(input);
+ }
+
+ /**
+ * update the internal digest with the byte array in
+ */
+ public void update(
+ byte[] input,
+ int inOff,
+ int length)
+ {
+ digest.update(input, inOff, length);
+ }
+
+ /**
+ * Generate a signature for the message we've been loaded with using the key
+ * we were initialised with.
+ */
+ public byte[] generateSignature()
+ throws CryptoException, DataLengthException
+ {
+ if (!forSigning)
+ {
+ throw new IllegalStateException("RSADigestSigner not initialised for signature generation.");
+ }
+
+ byte[] hash = new byte[digest.getDigestSize()];
+ digest.doFinal(hash, 0);
+
+ try
+ {
+ byte[] data = derEncode(hash);
+ return rsaEngine.processBlock(data, 0, data.length);
+ }
+ catch (IOException e)
+ {
+ throw new CryptoException("unable to encode signature: " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * return true if the internal state represents the signature described in
+ * the passed in array.
+ */
+ public boolean verifySignature(
+ byte[] signature)
+ {
+ if (forSigning)
+ {
+ throw new IllegalStateException("RSADigestSigner not initialised for verification");
+ }
+
+ byte[] hash = new byte[digest.getDigestSize()];
+
+ digest.doFinal(hash, 0);
+
+ byte[] sig;
+ byte[] expected;
+
+ try
+ {
+ sig = rsaEngine.processBlock(signature, 0, signature.length);
+ expected = derEncode(hash);
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+
+ if (sig.length == expected.length)
+ {
+ return Arrays.constantTimeAreEqual(sig, expected);
+ }
+ else if (sig.length == expected.length - 2) // NULL left out
+ {
+ int sigOffset = sig.length - hash.length - 2;
+ int expectedOffset = expected.length - hash.length - 2;
+
+ expected[1] -= 2; // adjust lengths
+ expected[3] -= 2;
+
+ int nonEqual = 0;
+
+ for (int i = 0; i < hash.length; i++)
+ {
+ nonEqual |= (sig[sigOffset + i] ^ expected[expectedOffset + i]);
+ }
+
+ for (int i = 0; i < sigOffset; i++)
+ {
+ nonEqual |= (sig[i] ^ expected[i]); // check header less NULL
+ }
+
+ return nonEqual == 0;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public void reset()
+ {
+ digest.reset();
+ }
+
+ private byte[] derEncode(
+ byte[] hash)
+ throws IOException
+ {
+ DigestInfo dInfo = new DigestInfo(algId, hash);
+
+ return dInfo.getEncoded(ASN1Encoding.DER);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/signers/RandomDSAKCalculator.java b/core/src/main/java/org/spongycastle/crypto/signers/RandomDSAKCalculator.java
new file mode 100644
index 00000000..fb8e3ae7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/signers/RandomDSAKCalculator.java
@@ -0,0 +1,43 @@
+package org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsAgreementCredentials.java b/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsAgreementCredentials.java
new file mode 100644
index 00000000..188dfafe
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsAgreementCredentials.java
@@ -0,0 +1,7 @@
+package org.spongycastle.crypto.tls;
+
+public abstract class AbstractTlsAgreementCredentials
+ extends AbstractTlsCredentials
+ implements TlsAgreementCredentials
+{
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsCipherFactory.java b/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsCipherFactory.java
new file mode 100644
index 00000000..755c7b7e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsCipherFactory.java
@@ -0,0 +1,13 @@
+package org.spongycastle.crypto.tls;
+
+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/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsClient.java b/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsClient.java
new file mode 100644
index 00000000..81c399ff
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsClient.java
@@ -0,0 +1,235 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.Vector;
+
+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;
+
+ public AbstractTlsClient()
+ {
+ this(new DefaultTlsCipherFactory());
+ }
+
+ public AbstractTlsClient(TlsCipherFactory cipherFactory)
+ {
+ this.cipherFactory = cipherFactory;
+ }
+
+ public void init(TlsClientContext context)
+ {
+ 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
+ * version number supported by the client, and the value of ClientHello.client_version. No
+ * single value will guarantee interoperability with all old servers, but this is a complex
+ * topic beyond the scope of this document."
+ */
+ public ProtocolVersion getClientHelloRecordLayerVersion()
+ {
+ // "{03,00}"
+ // return ProtocolVersion.SSLv3;
+
+ // "the lowest version number supported by the client"
+ // return getMinimumVersion();
+
+ // "the value of ClientHello.client_version"
+ return getClientVersion();
+ }
+
+ public ProtocolVersion getClientVersion()
+ {
+ return ProtocolVersion.TLSv12;
+ }
+
+ public Hashtable getClientExtensions()
+ throws IOException
+ {
+ Hashtable clientExtensions = null;
+
+ ProtocolVersion clientVersion = context.getClientVersion();
+
+ /*
+ * RFC 5246 7.4.1.4.1. Note: this extension is not meaningful for TLS versions prior to 1.2.
+ * Clients MUST NOT offer it if they are offering prior versions.
+ */
+ 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 };
+
+ // TODO Sort out ECDSA signatures and add them as the preferred option here
+ short[] signatureAlgorithms = new short[]{ SignatureAlgorithm.rsa };
+
+ this.supportedSignatureAlgorithms = new Vector();
+ for (int i = 0; i < hashAlgorithms.length; ++i)
+ {
+ for (int j = 0; j < signatureAlgorithms.length; ++j)
+ {
+ this.supportedSignatureAlgorithms.addElement(new SignatureAndHashAlgorithm(hashAlgorithms[i],
+ signatureAlgorithms[j]));
+ }
+ }
+
+ /*
+ * RFC 5264 7.4.3. Currently, DSA [DSS] may only be used with SHA-1.
+ */
+ this.supportedSignatureAlgorithms.addElement(new SignatureAndHashAlgorithm(HashAlgorithm.sha1,
+ SignatureAlgorithm.dsa));
+
+ 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;
+ }
+
+ public ProtocolVersion getMinimumVersion()
+ {
+ return ProtocolVersion.TLSv10;
+ }
+
+ public void notifyServerVersion(ProtocolVersion serverVersion)
+ throws IOException
+ {
+ if (!getMinimumVersion().isEqualOrEarlierVersionOf(serverVersion))
+ {
+ throw new TlsFatalAlert(AlertDescription.protocol_version);
+ }
+ }
+
+ public short[] getCompressionMethods()
+ {
+ return new short[]{CompressionMethod._null};
+ }
+
+ public void notifySessionID(byte[] sessionID)
+ {
+ // Currently ignored
+ }
+
+ public void notifySelectedCipherSuite(int selectedCipherSuite)
+ {
+ this.selectedCipherSuite = selectedCipherSuite;
+ }
+
+ public void notifySelectedCompressionMethod(short selectedCompressionMethod)
+ {
+ this.selectedCompressionMethod = selectedCompressionMethod;
+ }
+
+ public void processServerExtensions(Hashtable serverExtensions)
+ throws IOException
+ {
+ /*
+ * TlsProtocol implementation validates that any server extensions received correspond to
+ * client extensions sent. By default, we don't send any, and this method is not called.
+ */
+ if (serverExtensions != null)
+ {
+ /*
+ * RFC 5246 7.4.1.4.1. Servers MUST NOT send this extension.
+ */
+ if (serverExtensions.containsKey(TlsUtils.EXT_signature_algorithms))
+ {
+ 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);
+ }
+ }
+ }
+
+ public void processServerSupplementalData(Vector serverSupplementalData)
+ throws IOException
+ {
+ if (serverSupplementalData != null)
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ }
+
+ public Vector getClientSupplementalData()
+ throws IOException
+ {
+ return null;
+ }
+
+ public TlsCompression getCompression()
+ throws IOException
+ {
+ switch (selectedCompressionMethod)
+ {
+ case CompressionMethod._null:
+ return new TlsNullCompression();
+
+ default:
+ /*
+ * Note: internal error here; the TlsProtocol implementation verifies that the
+ * server-selected compression method was in the list of client-offered compression
+ * methods, so if we now can't produce an implementation, we shouldn't have offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public void notifyNewSessionTicket(NewSessionTicket newSessionTicket)
+ throws IOException
+ {
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsContext.java b/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsContext.java
new file mode 100644
index 00000000..a9504bef
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsContext.java
@@ -0,0 +1,133 @@
+package org.spongycastle.crypto.tls;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.prng.DigestRandomGenerator;
+import org.spongycastle.crypto.prng.RandomGenerator;
+import org.spongycastle.util.Times;
+
+abstract class AbstractTlsContext
+ implements TlsContext
+{
+ private static long counter = Times.nanoTime();
+
+ private synchronized static long nextCounterValue()
+ {
+ return ++counter;
+ }
+
+ private RandomGenerator nonceRandom;
+ 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)
+ {
+ secureRandom.setSeed(nextCounterValue());
+ secureRandom.setSeed(Times.nanoTime());
+
+ this.nonceRandom = new DigestRandomGenerator(TlsUtils.createHash(HashAlgorithm.sha256));
+ this.nonceRandom.addSeedMaterial(secureRandom.generateSeed(32));
+
+ this.secureRandom = secureRandom;
+ this.securityParameters = securityParameters;
+ }
+
+ public RandomGenerator getNonceRandomGenerator()
+ {
+ return nonceRandom;
+ }
+
+ public SecureRandom getSecureRandom()
+ {
+ return secureRandom;
+ }
+
+ public SecurityParameters getSecurityParameters()
+ {
+ return securityParameters;
+ }
+
+ public ProtocolVersion getClientVersion()
+ {
+ return clientVersion;
+ }
+
+ void setClientVersion(ProtocolVersion clientVersion)
+ {
+ this.clientVersion = clientVersion;
+ }
+
+ public ProtocolVersion getServerVersion()
+ {
+ return 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;
+ }
+
+ public void setUserObject(Object userObject)
+ {
+ this.userObject = userObject;
+ }
+
+ 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();
+
+ int seedLength = cr.length + sr.length;
+ if (context_value != null)
+ {
+ seedLength += (2 + context_value.length);
+ }
+
+ byte[] seed = new byte[seedLength];
+ int seedPos = 0;
+
+ System.arraycopy(cr, 0, seed, seedPos, cr.length);
+ seedPos += cr.length;
+ System.arraycopy(sr, 0, seed, seedPos, sr.length);
+ seedPos += sr.length;
+ if (context_value != null)
+ {
+ TlsUtils.writeUint16(context_value.length, seed, seedPos);
+ seedPos += 2;
+ System.arraycopy(context_value, 0, seed, seedPos, context_value.length);
+ seedPos += context_value.length;
+ }
+
+ if (seedPos != seedLength)
+ {
+ throw new IllegalStateException("error in calculation of seed for export");
+ }
+
+ return TlsUtils.PRF(this, sp.getMasterSecret(), asciiLabel, seed, length);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsCredentials.java b/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsCredentials.java
new file mode 100644
index 00000000..ab6cda7e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsCredentials.java
@@ -0,0 +1,6 @@
+package org.spongycastle.crypto.tls;
+
+public abstract class AbstractTlsCredentials
+ implements TlsCredentials
+{
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsEncryptionCredentials.java b/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsEncryptionCredentials.java
new file mode 100644
index 00000000..8eb0147e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsEncryptionCredentials.java
@@ -0,0 +1,7 @@
+package org.spongycastle.crypto.tls;
+
+public abstract class AbstractTlsEncryptionCredentials
+ extends AbstractTlsCredentials
+ implements TlsEncryptionCredentials
+{
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsKeyExchange.java b/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsKeyExchange.java
new file mode 100644
index 00000000..4920007d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsKeyExchange.java
@@ -0,0 +1,166 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Vector;
+
+public abstract class AbstractTlsKeyExchange
+ implements TlsKeyExchange
+{
+ protected int keyExchange;
+ protected Vector supportedSignatureAlgorithms;
+
+ protected TlsContext context;
+
+ protected AbstractTlsKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms)
+ {
+ this.keyExchange = keyExchange;
+ this.supportedSignatureAlgorithms = supportedSignatureAlgorithms;
+ }
+
+ public void init(TlsContext context)
+ {
+ this.context = context;
+
+ ProtocolVersion clientVersion = context.getClientVersion();
+
+ 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:
+ *
+ * - If the negotiated key exchange algorithm is one of (RSA, DHE_RSA, DH_RSA, RSA_PSK,
+ * ECDH_RSA, ECDHE_RSA), behave as if client had sent the value {sha1,rsa}.
+ *
+ * - If the negotiated key exchange algorithm is one of (DHE_DSS, DH_DSS), behave as if
+ * the client had sent the value {sha1,dsa}.
+ *
+ * - If the negotiated key exchange algorithm is one of (ECDH_ECDSA, ECDHE_ECDSA),
+ * behave as if the client had sent value {sha1,ecdsa}.
+ */
+ if (this.supportedSignatureAlgorithms == null)
+ {
+ switch (keyExchange)
+ {
+ case KeyExchangeAlgorithm.DH_DSS:
+ case KeyExchangeAlgorithm.DHE_DSS:
+ case KeyExchangeAlgorithm.SRP_DSS:
+ {
+ this.supportedSignatureAlgorithms = TlsUtils.getDefaultDSSSignatureAlgorithms();
+ break;
+ }
+
+ case KeyExchangeAlgorithm.ECDH_ECDSA:
+ case KeyExchangeAlgorithm.ECDHE_ECDSA:
+ {
+ this.supportedSignatureAlgorithms = TlsUtils.getDefaultECDSASignatureAlgorithms();
+ break;
+ }
+
+ case KeyExchangeAlgorithm.DH_RSA:
+ case KeyExchangeAlgorithm.DHE_RSA:
+ case KeyExchangeAlgorithm.ECDH_RSA:
+ case KeyExchangeAlgorithm.ECDHE_RSA:
+ case KeyExchangeAlgorithm.RSA:
+ case KeyExchangeAlgorithm.RSA_PSK:
+ case KeyExchangeAlgorithm.SRP_RSA:
+ {
+ this.supportedSignatureAlgorithms = TlsUtils.getDefaultRSASignatureAlgorithms();
+ break;
+ }
+
+ case KeyExchangeAlgorithm.DHE_PSK:
+ case KeyExchangeAlgorithm.ECDHE_PSK:
+ case KeyExchangeAlgorithm.PSK:
+ case KeyExchangeAlgorithm.SRP:
+ break;
+
+ default:
+ throw new IllegalStateException("unsupported key exchange algorithm");
+ }
+ }
+
+ }
+ else if (this.supportedSignatureAlgorithms != null)
+ {
+ throw new IllegalStateException("supported_signature_algorithms not allowed for " + clientVersion);
+ }
+ }
+
+ public void processServerCertificate(Certificate serverCertificate)
+ throws IOException
+ {
+ if (supportedSignatureAlgorithms == null)
+ {
+ /*
+ * TODO RFC 2264 7.4.2. Unless otherwise specified, the signing algorithm for the
+ * certificate must be the same as the algorithm for the certificate key.
+ */
+ }
+ else
+ {
+ /*
+ * TODO RFC 5264 7.4.2. If the client provided a "signature_algorithms" extension, then
+ * all certificates provided by the server MUST be signed by a hash/signature algorithm
+ * pair that appears in that extension.
+ */
+ }
+ }
+
+ public void processServerCredentials(TlsCredentials serverCredentials)
+ throws IOException
+ {
+ processServerCertificate(serverCredentials.getCertificate());
+ }
+
+ public boolean requiresServerKeyExchange()
+ {
+ return false;
+ }
+
+ public byte[] generateServerKeyExchange()
+ throws IOException
+ {
+ if (requiresServerKeyExchange())
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ return null;
+ }
+
+ public void skipServerKeyExchange()
+ throws IOException
+ {
+ if (requiresServerKeyExchange())
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ }
+
+ public void processServerKeyExchange(InputStream input)
+ throws IOException
+ {
+ if (!requiresServerKeyExchange())
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ }
+
+ public void skipClientCredentials()
+ throws IOException
+ {
+ }
+
+ public void processClientCertificate(Certificate clientCertificate)
+ throws IOException
+ {
+ }
+
+ public void processClientKeyExchange(InputStream input)
+ throws IOException
+ {
+ // Key exchange implementation MUST support client key exchange
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsPeer.java b/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsPeer.java
new file mode 100644
index 00000000..cf90455f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsPeer.java
@@ -0,0 +1,42 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+public abstract class AbstractTlsPeer
+ implements TlsPeer
+{
+ public boolean shouldUseGMTUnixTime()
+ {
+ /*
+ * draft-mathewson-no-gmtunixtime-00 2. For the reasons we discuss above, we recommend that
+ * TLS implementors MUST by default set the entire value the ClientHello.Random and
+ * ServerHello.Random fields, including gmt_unix_time, to a cryptographically random
+ * sequence.
+ */
+ return false;
+ }
+
+ 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)
+ {
+ }
+
+ public void notifyAlertReceived(short alertLevel, short alertDescription)
+ {
+ }
+
+ public void notifyHandshakeComplete() throws IOException
+ {
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsServer.java b/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsServer.java
new file mode 100644
index 00000000..f4ffdfdd
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsServer.java
@@ -0,0 +1,335 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.spongycastle.util.Arrays;
+
+public abstract class AbstractTlsServer
+ extends AbstractTlsPeer
+ implements TlsServer
+{
+ protected TlsCipherFactory cipherFactory;
+
+ protected TlsServerContext context;
+
+ protected ProtocolVersion clientVersion;
+ protected int[] offeredCipherSuites;
+ protected short[] offeredCompressionMethods;
+ protected Hashtable clientExtensions;
+
+ protected boolean encryptThenMACOffered;
+ protected short maxFragmentLengthOffered;
+ protected boolean truncatedHMacOffered;
+ protected Vector supportedSignatureAlgorithms;
+ protected boolean eccCipherSuitesOffered;
+ protected int[] namedCurves;
+ protected short[] clientECPointFormats, serverECPointFormats;
+
+ protected ProtocolVersion serverVersion;
+ protected int selectedCipherSuite;
+ protected short selectedCompressionMethod;
+ protected Hashtable serverExtensions;
+
+ public AbstractTlsServer()
+ {
+ this(new DefaultTlsCipherFactory());
+ }
+
+ public AbstractTlsServer(TlsCipherFactory cipherFactory)
+ {
+ this.cipherFactory = cipherFactory;
+ }
+
+ protected boolean allowEncryptThenMAC()
+ {
+ return true;
+ }
+
+ protected boolean allowTruncatedHMac()
+ {
+ return false;
+ }
+
+ protected Hashtable checkServerExtensions()
+ {
+ return this.serverExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(this.serverExtensions);
+ }
+
+ protected abstract int[] getCipherSuites();
+
+ protected short[] getCompressionMethods()
+ {
+ return new short[]{CompressionMethod._null};
+ }
+
+ protected ProtocolVersion getMaximumVersion()
+ {
+ return ProtocolVersion.TLSv11;
+ }
+
+ protected ProtocolVersion getMinimumVersion()
+ {
+ return ProtocolVersion.TLSv10;
+ }
+
+ 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)
+ {
+ /*
+ * RFC 4492 4. A client that proposes ECC cipher suites may choose not to include these
+ * extensions. In this case, the server is free to choose any one of the elliptic curves
+ * or point formats [...].
+ */
+ return TlsECCUtils.hasAnySupportedNamedCurves();
+ }
+
+ for (int i = 0; i < namedCurves.length; ++i)
+ {
+ int namedCurve = namedCurves[i];
+ if (NamedCurve.isValid(namedCurve)
+ && (!NamedCurve.refersToASpecificNamedCurve(namedCurve) || TlsECCUtils.isSupportedNamedCurve(namedCurve)))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public void init(TlsServerContext context)
+ {
+ this.context = context;
+ }
+
+ public void notifyClientVersion(ProtocolVersion clientVersion)
+ throws IOException
+ {
+ this.clientVersion = clientVersion;
+ }
+
+ public void notifyOfferedCipherSuites(int[] offeredCipherSuites)
+ throws IOException
+ {
+ this.offeredCipherSuites = offeredCipherSuites;
+ this.eccCipherSuitesOffered = TlsECCUtils.containsECCCipherSuites(this.offeredCipherSuites);
+ }
+
+ public void notifyOfferedCompressionMethods(short[] offeredCompressionMethods)
+ throws IOException
+ {
+ this.offeredCompressionMethods = offeredCompressionMethods;
+ }
+
+ public void processClientExtensions(Hashtable clientExtensions)
+ throws IOException
+ {
+ this.clientExtensions = clientExtensions;
+
+ if (clientExtensions != null)
+ {
+ this.encryptThenMACOffered = TlsExtensionsUtils.hasEncryptThenMACExtension(clientExtensions);
+ this.maxFragmentLengthOffered = TlsExtensionsUtils.getMaxFragmentLengthExtension(clientExtensions);
+ this.truncatedHMacOffered = TlsExtensionsUtils.hasTruncatedHMacExtension(clientExtensions);
+
+ this.supportedSignatureAlgorithms = TlsUtils.getSignatureAlgorithmsExtension(clientExtensions);
+ if (this.supportedSignatureAlgorithms != null)
+ {
+ /*
+ * RFC 5246 7.4.1.4.1. Note: this extension is not meaningful for TLS versions prior
+ * to 1.2. Clients MUST NOT offer it if they are offering prior versions.
+ */
+ if (!TlsUtils.isSignatureAlgorithmsExtensionAllowed(clientVersion))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+
+ this.namedCurves = TlsECCUtils.getSupportedEllipticCurvesExtension(clientExtensions);
+ this.clientECPointFormats = TlsECCUtils.getSupportedPointFormatsExtension(clientExtensions);
+ }
+
+ /*
+ * RFC 4429 4. The client MUST NOT include these extensions in the ClientHello message if it
+ * does not propose any ECC cipher suites.
+ */
+ if (!this.eccCipherSuitesOffered && (this.namedCurves != null || this.clientECPointFormats != null))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+
+ public ProtocolVersion getServerVersion()
+ throws IOException
+ {
+ if (getMinimumVersion().isEqualOrEarlierVersionOf(clientVersion))
+ {
+ ProtocolVersion maximumVersion = getMaximumVersion();
+ if (clientVersion.isEqualOrEarlierVersionOf(maximumVersion))
+ {
+ return serverVersion = clientVersion;
+ }
+ if (clientVersion.isLaterVersionOf(maximumVersion))
+ {
+ return serverVersion = maximumVersion;
+ }
+ }
+ throw new TlsFatalAlert(AlertDescription.protocol_version);
+ }
+
+ 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
+ * somewhat inelegant but is a compromise designed to minimize changes to the original
+ * cipher suite design.
+ */
+
+ /*
+ * RFC 4429 5.1. A server that receives a ClientHello containing one or both of these
+ * extensions MUST use the client's enumerated capabilities to guide its selection of an
+ * appropriate cipher suite. One of the proposed ECC cipher suites must be negotiated only
+ * if the server can successfully complete the handshake while using the curves and point
+ * formats supported by the client [...].
+ */
+ boolean eccCipherSuitesEnabled = supportsClientECCCapabilities(this.namedCurves, this.clientECPointFormats);
+
+ int[] cipherSuites = getCipherSuites();
+ for (int i = 0; i < cipherSuites.length; ++i)
+ {
+ int cipherSuite = cipherSuites[i];
+
+ if (Arrays.contains(this.offeredCipherSuites, cipherSuite)
+ && (eccCipherSuitesEnabled || !TlsECCUtils.isECCCipherSuite(cipherSuite))
+ && TlsUtils.isValidCipherSuiteForVersion(cipherSuite, serverVersion))
+ {
+ return this.selectedCipherSuite = cipherSuite;
+ }
+ }
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
+ }
+
+ public short getSelectedCompressionMethod()
+ throws IOException
+ {
+ short[] compressionMethods = getCompressionMethods();
+ for (int i = 0; i < compressionMethods.length; ++i)
+ {
+ if (Arrays.contains(offeredCompressionMethods, compressionMethods[i]))
+ {
+ return this.selectedCompressionMethod = compressionMethods[i];
+ }
+ }
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
+ }
+
+ // Hashtable is (Integer -> byte[])
+ public Hashtable getServerExtensions()
+ throws IOException
+ {
+ if (this.encryptThenMACOffered && allowEncryptThenMAC())
+ {
+ /*
+ * draft-ietf-tls-encrypt-then-mac-03 3. If a server receives an encrypt-then-MAC
+ * request extension from a client and then selects a stream or AEAD cipher suite, it
+ * MUST NOT send an encrypt-then-MAC response extension back to the client.
+ */
+ if (TlsUtils.isBlockCipherSuite(this.selectedCipherSuite))
+ {
+ TlsExtensionsUtils.addEncryptThenMACExtension(checkServerExtensions());
+ }
+ }
+
+ if (this.maxFragmentLengthOffered >= 0)
+ {
+ TlsExtensionsUtils.addMaxFragmentLengthExtension(checkServerExtensions(), this.maxFragmentLengthOffered);
+ }
+
+ if (this.truncatedHMacOffered && allowTruncatedHMac())
+ {
+ TlsExtensionsUtils.addTruncatedHMacExtension(checkServerExtensions());
+ }
+
+ if (this.clientECPointFormats != null && TlsECCUtils.isECCCipherSuite(this.selectedCipherSuite))
+ {
+ /*
+ * RFC 4492 5.2. A server that selects an ECC cipher suite in response to a ClientHello
+ * 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.uncompressed,
+ ECPointFormat.ansiX962_compressed_prime, ECPointFormat.ansiX962_compressed_char2, };
+
+ TlsECCUtils.addSupportedPointFormatsExtension(checkServerExtensions(), serverECPointFormats);
+ }
+
+ return serverExtensions;
+ }
+
+ public Vector getServerSupplementalData()
+ throws IOException
+ {
+ return null;
+ }
+
+ public CertificateStatus getCertificateStatus()
+ throws IOException
+ {
+ return null;
+ }
+
+ public CertificateRequest getCertificateRequest()
+ throws IOException
+ {
+ return null;
+ }
+
+ public void processClientSupplementalData(Vector clientSupplementalData)
+ throws IOException
+ {
+ if (clientSupplementalData != null)
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ }
+
+ public void notifyClientCertificate(Certificate clientCertificate)
+ throws IOException
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ public TlsCompression getCompression()
+ throws IOException
+ {
+ switch (selectedCompressionMethod)
+ {
+ case CompressionMethod._null:
+ return new TlsNullCompression();
+
+ default:
+ /*
+ * Note: internal error here; we selected the compression method, so if we now can't
+ * produce an implementation, we shouldn't have chosen it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public NewSessionTicket getNewSessionTicket()
+ throws IOException
+ {
+ /*
+ * RFC 5077 3.3. If the server determines that it does not want to include a ticket after it
+ * has included the SessionTicket extension in the ServerHello, then it sends a zero-length
+ * ticket in the NewSessionTicket handshake message.
+ */
+ return new NewSessionTicket(0L, TlsUtils.EMPTY_BYTES);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsSigner.java b/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsSigner.java
new file mode 100644
index 00000000..cc88f5a2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsSigner.java
@@ -0,0 +1,38 @@
+package org.spongycastle.crypto.tls;
+
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.Signer;
+import org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsSignerCredentials.java b/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsSignerCredentials.java
new file mode 100644
index 00000000..d10e6499
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsSignerCredentials.java
@@ -0,0 +1,11 @@
+package org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/tls/AlertDescription.java b/core/src/main/java/org/spongycastle/crypto/tls/AlertDescription.java
new file mode 100644
index 00000000..275cb16e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/AlertDescription.java
@@ -0,0 +1,216 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 5246 7.2.
+ */
+public class AlertDescription
+{
+ /**
+ * This message notifies the recipient that the sender will not send any more messages on this
+ * 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;
+
+ /**
+ * An inappropriate message was received. This alert is always fatal and should never be
+ * observed in communication between proper implementations.
+ */
+ public static final short unexpected_message = 10;
+
+ /**
+ * This alert is returned if a record is received with an incorrect MAC. This alert also MUST be
+ * returned if an alert is sent because a TLSCiphertext decrypted in an invalid way: either it
+ * wasn't an even multiple of the block length, or its padding values, when checked, weren't
+ * correct. This message is always fatal and should never be observed in communication between
+ * proper implementations (except when messages were corrupted in the network).
+ */
+ public static final short bad_record_mac = 20;
+
+ /**
+ * This alert was used in some earlier versions of TLS, and may have permitted certain attacks
+ * against the CBC mode [CBCATT]. It MUST NOT be sent by compliant implementations.
+ */
+ public static final short decryption_failed = 21;
+
+ /**
+ * A TLSCiphertext record was received that had a length more than 2^14+2048 bytes, or a record
+ * decrypted to a TLSCompressed record with more than 2^14+1024 bytes. This message is always
+ * fatal and should never be observed in communication between proper implementations (except
+ * when messages were corrupted in the network).
+ */
+ public static final short record_overflow = 22;
+
+ /**
+ * The decompression function received improper input (e.g., data that would expand to excessive
+ * length). This message is always fatal and should never be observed in communication between
+ * proper implementations.
+ */
+ public static final short decompression_failure = 30;
+
+ /**
+ * Reception of a handshake_failure alert message indicates that the sender was unable to
+ * negotiate an acceptable set of security parameters given the options available. This is a
+ * fatal error.
+ */
+ public static final short handshake_failure = 40;
+
+ /**
+ * This alert was used in SSLv3 but not any version of TLS. It MUST NOT be sent by compliant
+ * implementations.
+ */
+ public static final short no_certificate = 41;
+
+ /**
+ * A certificate was corrupt, contained signatures that did not verify correctly, etc.
+ */
+ public static final short bad_certificate = 42;
+
+ /**
+ * A certificate was of an unsupported type.
+ */
+ public static final short unsupported_certificate = 43;
+
+ /**
+ * A certificate was revoked by its signer.
+ */
+ public static final short certificate_revoked = 44;
+
+ /**
+ * A certificate has expired or is not currently valid.
+ */
+ public static final short certificate_expired = 45;
+
+ /**
+ * Some other (unspecified) issue arose in processing the certificate, rendering it
+ * unacceptable.
+ */
+ public static final short certificate_unknown = 46;
+
+ /**
+ * A field in the handshake was out of range or inconsistent with other fields. This message is
+ * always fatal.
+ */
+ public static final short illegal_parameter = 47;
+
+ /**
+ * A valid certificate chain or partial chain was received, but the certificate was not accepted
+ * because the CA certificate could not be located or couldn't be matched with a known, trusted
+ * CA. This message is always fatal.
+ */
+ public static final short unknown_ca = 48;
+
+ /**
+ * A valid certificate was received, but when access control was applied, the sender decided not
+ * to proceed with negotiation. This message is always fatal.
+ */
+ public static final short access_denied = 49;
+
+ /**
+ * A message could not be decoded because some field was out of the specified range or the
+ * length of the message was incorrect. This message is always fatal and should never be
+ * observed in communication between proper implementations (except when messages were corrupted
+ * in the network).
+ */
+ public static final short decode_error = 50;
+
+ /**
+ * A handshake cryptographic operation failed, including being unable to correctly verify a
+ * signature or validate a Finished message. This message is always fatal.
+ */
+ public static final short decrypt_error = 51;
+
+ /**
+ * This alert was used in some earlier versions of TLS. It MUST NOT be sent by compliant
+ * implementations.
+ */
+ public static final short export_restriction = 60;
+
+ /**
+ * The protocol version the client has attempted to negotiate is recognized but not supported.
+ * (For example, old protocol versions might be avoided for security reasons.) This message is
+ * always fatal.
+ */
+ public static final short protocol_version = 70;
+
+ /**
+ * Returned instead of handshake_failure when a negotiation has failed specifically because the
+ * server requires ciphers more secure than those supported by the client. This message is
+ * always fatal.
+ */
+ public static final short insufficient_security = 71;
+
+ /**
+ * An internal error unrelated to the peer or the correctness of the protocol (such as a memory
+ * allocation failure) makes it impossible to continue. This message is always fatal.
+ */
+ public static final short internal_error = 80;
+
+ /**
+ * This handshake is being canceled for some reason unrelated to a protocol failure. If the user
+ * cancels an operation after the handshake is complete, just closing the connection by sending
+ * a close_notify is more appropriate. This alert should be followed by a close_notify. This
+ * message is generally a warning.
+ */
+ public static final short user_canceled = 90;
+
+ /**
+ * Sent by the client in response to a hello request or by the server in response to a client
+ * hello after initial handshaking. Either of these would normally lead to renegotiation; when
+ * that is not appropriate, the recipient should respond with this alert. At that point, the
+ * original requester can decide whether to proceed with the connection. One case where this
+ * would be appropriate is where a server has spawned a process to satisfy a request; the
+ * process might receive security parameters (key length, authentication, etc.) at startup, and
+ * it might be difficult to communicate changes to these parameters after that point. This
+ * message is always a warning.
+ */
+ public static final short no_renegotiation = 100;
+
+ /**
+ * Sent by clients that receive an extended server hello containing an extension that they did
+ * not put in the corresponding client hello. This message is always fatal.
+ */
+ public static final short unsupported_extension = 110;
+
+ /*
+ * RFC 3546
+ */
+
+ /**
+ * This alert is sent by servers who are unable to retrieve a certificate chain from the URL
+ * supplied by the client (see Section 3.3). This message MAY be fatal - for example if client
+ * authentication is required by the server for the handshake to continue and the server is
+ * unable to retrieve the certificate chain, it may send a fatal alert.
+ */
+ public static final short certificate_unobtainable = 111;
+
+ /**
+ * This alert is sent by servers that receive a server_name extension request, but do not
+ * recognize the server name. This message MAY be fatal.
+ */
+ public static final short unrecognized_name = 112;
+
+ /**
+ * This alert is sent by clients that receive an invalid certificate status response (see
+ * Section 3.6). This message is always fatal.
+ */
+ public static final short bad_certificate_status_response = 113;
+
+ /**
+ * This alert is sent by servers when a certificate hash does not match a client provided
+ * certificate_hash. This message is always fatal.
+ */
+ public static final short bad_certificate_hash_value = 114;
+
+ /*
+ * RFC 4279
+ */
+
+ /**
+ * If the server does not recognize the PSK identity, it MAY respond with an
+ * "unknown_psk_identity" alert message.
+ */
+ public static final short unknown_psk_identity = 115;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/AlertLevel.java b/core/src/main/java/org/spongycastle/crypto/tls/AlertLevel.java
new file mode 100644
index 00000000..2ba4542f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/AlertLevel.java
@@ -0,0 +1,10 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 5246 7.2
+ */
+public class AlertLevel
+{
+ public static final short warning = 1;
+ public static final short fatal = 2;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/AlwaysValidVerifyer.java b/core/src/main/java/org/spongycastle/crypto/tls/AlwaysValidVerifyer.java
new file mode 100644
index 00000000..990a98f9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/AlwaysValidVerifyer.java
@@ -0,0 +1,23 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * A certificate verifyer, that will always return true.
+ * <pre>
+ * DO NOT USE THIS FILE UNLESS YOU KNOW EXACTLY WHAT YOU ARE DOING.
+ * </pre>
+ *
+ * @deprecated Perform certificate verification in TlsAuthentication implementation
+ */
+public class AlwaysValidVerifyer
+ implements CertificateVerifyer
+{
+ /**
+ * Return true.
+ *
+ * @see org.spongycastle.crypto.tls.CertificateVerifyer#isValid(org.spongycastle.asn1.x509.Certificate[])
+ */
+ public boolean isValid(org.spongycastle.asn1.x509.Certificate[] certs)
+ {
+ return true;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/BulkCipherAlgorithm.java b/core/src/main/java/org/spongycastle/crypto/tls/BulkCipherAlgorithm.java
new file mode 100644
index 00000000..e56cd713
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/BulkCipherAlgorithm.java
@@ -0,0 +1,23 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 2246
+ * <p>
+ * Note that the values here are implementation-specific and arbitrary. It is recommended not to
+ * depend on the particular values (e.g. serialization).
+ */
+public class BulkCipherAlgorithm
+{
+ public static final int _null = 0;
+ public static final int rc4 = 1;
+ public static final int rc2 = 2;
+ public static final int des = 3;
+ public static final int _3des = 4;
+ public static final int des40 = 5;
+
+ /*
+ * RFC 4346
+ */
+ public static final int aes = 6;
+ public static final int idea = 7;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/ByteQueue.java b/core/src/main/java/org/spongycastle/crypto/tls/ByteQueue.java
new file mode 100644
index 00000000..ce21ddaf
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/ByteQueue.java
@@ -0,0 +1,153 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * A queue for bytes. This file could be more optimized.
+ */
+public class ByteQueue
+{
+ /**
+ * @return The smallest number which can be written as 2^x which is bigger than i.
+ */
+ public static int nextTwoPow(int i)
+ {
+ /*
+ * This code is based of a lot of code I found on the Internet which mostly
+ * referenced a book called "Hacking delight".
+ */
+ i |= (i >> 1);
+ i |= (i >> 2);
+ i |= (i >> 4);
+ i |= (i >> 8);
+ i |= (i >> 16);
+ return i + 1;
+ }
+
+ /**
+ * The initial size for our buffer.
+ */
+ private static final int DEFAULT_CAPACITY = 1024;
+
+ /**
+ * The buffer where we store our data.
+ */
+ private byte[] databuf;
+
+ /**
+ * How many bytes at the beginning of the buffer are skipped.
+ */
+ private int skipped = 0;
+
+ /**
+ * How many bytes in the buffer are valid data.
+ */
+ private int available = 0;
+
+ public ByteQueue()
+ {
+ this(DEFAULT_CAPACITY);
+ }
+
+ public ByteQueue(int capacity)
+ {
+ databuf = new byte[capacity];
+ }
+
+ /**
+ * Read data from the buffer.
+ *
+ * @param buf The buffer where the read data will be copied to.
+ * @param offset 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 read(byte[] buf, int offset, int len, int skip)
+ {
+ if ((buf.length - offset) < len)
+ {
+ throw new IllegalArgumentException("Buffer size of " + buf.length
+ + " is too small for a read of " + len + " bytes");
+ }
+ if ((available - skip) < len)
+ {
+ throw new IllegalStateException("Not enough data to read");
+ }
+ System.arraycopy(databuf, skipped + skip, buf, offset, len);
+ }
+
+ /**
+ * Add some data to our buffer.
+ *
+ * @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[] buf, int off, int len)
+ {
+ if ((skipped + available + len) > databuf.length)
+ {
+ 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;
+ }
+
+ System.arraycopy(buf, off, databuf, skipped + available, len);
+ available += len;
+ }
+
+ /**
+ * Remove some bytes from our data from the beginning.
+ *
+ * @param i How many bytes to remove.
+ */
+ public void removeData(int i)
+ {
+ if (i > available)
+ {
+ throw new IllegalStateException("Cannot remove " + i + " bytes, only got " + available);
+ }
+
+ /*
+ * Skip the data.
+ */
+ available -= i;
+ skipped += i;
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * @return The number of bytes which are available in this buffer.
+ */
+ public int size()
+ {
+ return available;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/CertChainType.java b/core/src/main/java/org/spongycastle/crypto/tls/CertChainType.java
new file mode 100644
index 00000000..85749615
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/CertChainType.java
@@ -0,0 +1,15 @@
+package org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/tls/Certificate.java b/core/src/main/java/org/spongycastle/crypto/tls/Certificate.java
new file mode 100644
index 00000000..df2a2033
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/Certificate.java
@@ -0,0 +1,148 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Vector;
+
+import org.spongycastle.asn1.ASN1Encoding;
+import org.spongycastle.asn1.ASN1Primitive;
+
+/**
+ * Parsing and encoding of a <i>Certificate</i> struct from RFC 4346.
+ * <pre>
+ * opaque ASN.1Cert&lt;2^24-1&gt;;
+ *
+ * struct {
+ * ASN.1Cert certificate_list&lt;0..2^24-1&gt;;
+ * } Certificate;
+ * </pre>
+ *
+ * @see org.spongycastle.asn1.x509.Certificate
+ */
+public class Certificate
+{
+ public static final Certificate EMPTY_CHAIN = new Certificate(
+ new org.spongycastle.asn1.x509.Certificate[0]);
+
+ protected org.spongycastle.asn1.x509.Certificate[] certificateList;
+
+ public Certificate(org.spongycastle.asn1.x509.Certificate[] certificateList)
+ {
+ if (certificateList == null)
+ {
+ throw new IllegalArgumentException("'certificateList' cannot be null");
+ }
+
+ this.certificateList = certificateList;
+ }
+
+ /**
+ * @deprecated use {@link #getCertificateList()} instead
+ */
+ public org.spongycastle.asn1.x509.Certificate[] getCerts()
+ {
+ return getCertificateList();
+ }
+
+ /**
+ * @return an array of {@link org.spongycastle.asn1.x509.Certificate} representing a certificate
+ * chain.
+ */
+ public org.spongycastle.asn1.x509.Certificate[] getCertificateList()
+ {
+ return cloneCertificateList();
+ }
+
+ public org.spongycastle.asn1.x509.Certificate getCertificateAt(int index)
+ {
+ return certificateList[index];
+ }
+
+ public int getLength()
+ {
+ return certificateList.length;
+ }
+
+ /**
+ * @return <code>true</code> if this certificate chain contains no certificates, or
+ * <code>false</code> otherwise.
+ */
+ public boolean isEmpty()
+ {
+ return certificateList.length == 0;
+ }
+
+ /**
+ * Encode this {@link Certificate} to an {@link OutputStream}.
+ *
+ * @param output the {@link OutputStream} to encode to.
+ * @throws IOException
+ */
+ public void encode(OutputStream output)
+ throws IOException
+ {
+ Vector derEncodings = new Vector(this.certificateList.length);
+
+ int totalLength = 0;
+ for (int i = 0; i < this.certificateList.length; ++i)
+ {
+ 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 < derEncodings.size(); ++i)
+ {
+ byte[] derEncoding = (byte[])derEncodings.elementAt(i);
+ TlsUtils.writeOpaque24(derEncoding, output);
+ }
+ }
+
+ /**
+ * Parse a {@link Certificate} from an {@link InputStream}.
+ *
+ * @param input the {@link InputStream} to parse from.
+ * @return a {@link Certificate} object.
+ * @throws IOException
+ */
+ public static Certificate parse(InputStream input)
+ throws IOException
+ {
+ int totalLength = TlsUtils.readUint24(input);
+ if (totalLength == 0)
+ {
+ return EMPTY_CHAIN;
+ }
+
+ byte[] certListData = TlsUtils.readFully(totalLength, input);
+
+ ByteArrayInputStream buf = new ByteArrayInputStream(certListData);
+
+ Vector certificate_list = new Vector();
+ while (buf.available() > 0)
+ {
+ byte[] derEncoding = TlsUtils.readOpaque24(buf);
+ ASN1Primitive asn1Cert = TlsUtils.readDERObject(derEncoding);
+ certificate_list.addElement(org.spongycastle.asn1.x509.Certificate.getInstance(asn1Cert));
+ }
+
+ org.spongycastle.asn1.x509.Certificate[] certificateList = new org.spongycastle.asn1.x509.Certificate[certificate_list.size()];
+ for (int i = 0; i < certificate_list.size(); i++)
+ {
+ certificateList[i] = (org.spongycastle.asn1.x509.Certificate)certificate_list.elementAt(i);
+ }
+ return new Certificate(certificateList);
+ }
+
+ protected org.spongycastle.asn1.x509.Certificate[] cloneCertificateList()
+ {
+ org.spongycastle.asn1.x509.Certificate[] result = new org.spongycastle.asn1.x509.Certificate[certificateList.length];
+ System.arraycopy(certificateList, 0, result, 0, result.length);
+ return result;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/CertificateRequest.java b/core/src/main/java/org/spongycastle/crypto/tls/CertificateRequest.java
new file mode 100644
index 00000000..ae40206b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/CertificateRequest.java
@@ -0,0 +1,158 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Vector;
+
+import org.spongycastle.asn1.ASN1Encoding;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.x500.X500Name;
+
+/**
+ * Parsing and encoding of a <i>CertificateRequest</i> struct from RFC 4346.
+ * <pre>
+ * struct {
+ * ClientCertificateType certificate_types&lt;1..2^8-1&gt;;
+ * DistinguishedName certificate_authorities&lt;3..2^16-1&gt;;
+ * } CertificateRequest;
+ * </pre>
+ *
+ * @see ClientCertificateType
+ * @see X500Name
+ */
+public class CertificateRequest
+{
+ protected short[] certificateTypes;
+ protected Vector supportedSignatureAlgorithms;
+ protected Vector certificateAuthorities;
+
+ /**
+ * @param certificateTypes see {@link ClientCertificateType} for valid constants.
+ * @param certificateAuthorities a {@link Vector} of {@link X500Name}.
+ */
+ public CertificateRequest(short[] certificateTypes, Vector supportedSignatureAlgorithms, Vector certificateAuthorities)
+ {
+ this.certificateTypes = certificateTypes;
+ this.supportedSignatureAlgorithms = supportedSignatureAlgorithms;
+ this.certificateAuthorities = certificateAuthorities;
+ }
+
+ /**
+ * @return an array of certificate types
+ * @see ClientCertificateType
+ */
+ public short[] getCertificateTypes()
+ {
+ return certificateTypes;
+ }
+
+ /**
+ * @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()
+ {
+ return certificateAuthorities;
+ }
+
+ /**
+ * Encode this {@link CertificateRequest} to an {@link OutputStream}.
+ *
+ * @param output the {@link OutputStream} to encode to.
+ * @throws IOException
+ */
+ public void encode(OutputStream output)
+ throws IOException
+ {
+ if (certificateTypes == null || certificateTypes.length == 0)
+ {
+ TlsUtils.writeUint8(0, output);
+ }
+ else
+ {
+ 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())
+ {
+ TlsUtils.writeUint16(0, output);
+ }
+ else
+ {
+ Vector derEncodings = new Vector(certificateAuthorities.size());
+
+ int totalLength = 0;
+ for (int i = 0; i < certificateAuthorities.size(); ++i)
+ {
+ X500Name certificateAuthority = (X500Name)certificateAuthorities.elementAt(i);
+ byte[] derEncoding = certificateAuthority.getEncoded(ASN1Encoding.DER);
+ derEncodings.addElement(derEncoding);
+ totalLength += derEncoding.length + 2;
+ }
+
+ TlsUtils.checkUint16(totalLength);
+ TlsUtils.writeUint16(totalLength, output);
+
+ for (int i = 0; i < derEncodings.size(); ++i)
+ {
+ byte[] derEncoding = (byte[])derEncodings.elementAt(i);
+ TlsUtils.writeOpaque16(derEncoding, output);
+ }
+ }
+ }
+
+ /**
+ * Parse a {@link CertificateRequest} from an {@link InputStream}.
+ *
+ * @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(TlsContext context, InputStream input)
+ throws IOException
+ {
+ int numTypes = TlsUtils.readUint8(input);
+ short[] certificateTypes = new short[numTypes];
+ for (int i = 0; i < numTypes; ++i)
+ {
+ certificateTypes[i] = TlsUtils.readUint8(input);
+ }
+
+ Vector supportedSignatureAlgorithms = null;
+ if (TlsUtils.isTLSv12(context))
+ {
+ // TODO Check whether SignatureAlgorithm.anonymous is allowed here
+ supportedSignatureAlgorithms = TlsUtils.parseSupportedSignatureAlgorithms(false, input);
+ }
+
+ Vector certificateAuthorities = new Vector();
+ byte[] certAuthData = TlsUtils.readOpaque16(input);
+ ByteArrayInputStream bis = new ByteArrayInputStream(certAuthData);
+ while (bis.available() > 0)
+ {
+ byte[] derEncoding = TlsUtils.readOpaque16(bis);
+ ASN1Primitive asn1 = TlsUtils.readDERObject(derEncoding);
+ certificateAuthorities.addElement(X500Name.getInstance(asn1));
+ }
+
+ return new CertificateRequest(certificateTypes, supportedSignatureAlgorithms, certificateAuthorities);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/CertificateStatus.java b/core/src/main/java/org/spongycastle/crypto/tls/CertificateStatus.java
new file mode 100644
index 00000000..14b0a0d9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/CertificateStatus.java
@@ -0,0 +1,105 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.spongycastle.asn1.ASN1Encoding;
+import org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/tls/CertificateStatusRequest.java b/core/src/main/java/org/spongycastle/crypto/tls/CertificateStatusRequest.java
new file mode 100644
index 00000000..16318057
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/CertificateStatusRequest.java
@@ -0,0 +1,98 @@
+package org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/tls/CertificateStatusType.java b/core/src/main/java/org/spongycastle/crypto/tls/CertificateStatusType.java
new file mode 100644
index 00000000..75090262
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/CertificateStatusType.java
@@ -0,0 +1,9 @@
+package org.spongycastle.crypto.tls;
+
+public class CertificateStatusType
+{
+ /*
+ * RFC 3546 3.6
+ */
+ public static final short ocsp = 1;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/CertificateURL.java b/core/src/main/java/org/spongycastle/crypto/tls/CertificateURL.java
new file mode 100644
index 00000000..f6b7df53
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/CertificateURL.java
@@ -0,0 +1,133 @@
+package org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/tls/CertificateVerifyer.java b/core/src/main/java/org/spongycastle/crypto/tls/CertificateVerifyer.java
new file mode 100644
index 00000000..65c764a4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/CertificateVerifyer.java
@@ -0,0 +1,16 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * This should be implemented by any class which can find out, if a given certificate
+ * chain is being accepted by an client.
+ *
+ * @deprecated Perform certificate verification in TlsAuthentication implementation
+ */
+public interface CertificateVerifyer
+{
+ /**
+ * @param certs The certs, which are part of the chain.
+ * @return True, if the chain is accepted, false otherwise.
+ */
+ public boolean isValid(org.spongycastle.asn1.x509.Certificate[] certs);
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/Chacha20Poly1305.java b/core/src/main/java/org/spongycastle/crypto/tls/Chacha20Poly1305.java
new file mode 100644
index 00000000..aa2c8960
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/Chacha20Poly1305.java
@@ -0,0 +1,156 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.engines.ChaChaEngine;
+import org.spongycastle.crypto.generators.Poly1305KeyGenerator;
+import org.spongycastle.crypto.macs.Poly1305;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Pack;
+
+public class Chacha20Poly1305 implements TlsCipher
+{
+ protected TlsContext context;
+
+ protected ChaChaEngine encryptCipher;
+ protected ChaChaEngine decryptCipher;
+
+ public Chacha20Poly1305(TlsContext context) throws IOException
+ {
+ if (!TlsUtils.isTLSv12(context))
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ this.context = context;
+
+ byte[] key_block = TlsUtils.calculateKeyBlock(context, 64);
+
+ KeyParameter client_write_key = new KeyParameter(key_block, 0, 32);
+ KeyParameter server_write_key = new KeyParameter(key_block, 32, 32);
+
+ this.encryptCipher = new ChaChaEngine(20);
+ this.decryptCipher = new ChaChaEngine(20);
+
+ KeyParameter encryptKey, decryptKey;
+ if (context.isServer())
+ {
+ encryptKey = server_write_key;
+ decryptKey = client_write_key;
+ }
+ else
+ {
+ encryptKey = client_write_key;
+ decryptKey = server_write_key;
+ }
+
+ byte[] dummyNonce = new byte[8];
+
+ this.encryptCipher.init(true, new ParametersWithIV(encryptKey, dummyNonce));
+ this.decryptCipher.init(false, new ParametersWithIV(decryptKey, dummyNonce));
+ }
+
+ public int getPlaintextLimit(int ciphertextLimit)
+ {
+ return ciphertextLimit - 16;
+ }
+
+ public byte[] encodePlaintext(long seqNo, short type, byte[] plaintext, int offset, int len) throws IOException
+ {
+ int ciphertextLength = len + 16;
+
+ KeyParameter macKey = initRecordMAC(encryptCipher, true, seqNo);
+
+ byte[] output = new byte[ciphertextLength];
+ encryptCipher.processBytes(plaintext, offset, len, output, 0);
+
+ byte[] additionalData = getAdditionalData(seqNo, type, len);
+ byte[] mac = calculateRecordMAC(macKey, additionalData, output, 0, len);
+ System.arraycopy(mac, 0, output, len, mac.length);
+
+ return output;
+ }
+
+ 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);
+ }
+
+ int plaintextLength = len - 16;
+
+ byte[] receivedMAC = Arrays.copyOfRange(ciphertext, offset + plaintextLength, offset + len);
+
+ KeyParameter macKey = initRecordMAC(decryptCipher, false, seqNo);
+
+ byte[] additionalData = getAdditionalData(seqNo, type, plaintextLength);
+ byte[] calculatedMAC = calculateRecordMAC(macKey, additionalData, ciphertext, offset, plaintextLength);
+
+ if (!Arrays.constantTimeAreEqual(calculatedMAC, receivedMAC))
+ {
+ throw new TlsFatalAlert(AlertDescription.bad_record_mac);
+ }
+
+ byte[] output = new byte[plaintextLength];
+ decryptCipher.processBytes(ciphertext, offset, plaintextLength, output, 0);
+
+ return output;
+ }
+
+ protected KeyParameter initRecordMAC(ChaChaEngine cipher, boolean forEncryption, long seqNo)
+ {
+ byte[] nonce = new byte[8];
+ TlsUtils.writeUint64(seqNo, nonce, 0);
+
+ cipher.init(forEncryption, new ParametersWithIV(null, nonce));
+
+ byte[] firstBlock = new byte[64];
+ cipher.processBytes(firstBlock, 0, firstBlock.length, firstBlock, 0);
+
+ // NOTE: The BC implementation puts 'r' after 'k'
+ System.arraycopy(firstBlock, 0, firstBlock, 32, 16);
+ KeyParameter macKey = new KeyParameter(firstBlock, 16, 32);
+ Poly1305KeyGenerator.clamp(macKey.getKey());
+ return macKey;
+ }
+
+ protected byte[] calculateRecordMAC(KeyParameter macKey, byte[] additionalData, byte[] buf, int off, int len)
+ {
+ Mac mac = new Poly1305();
+ mac.init(macKey);
+
+ updateRecordMAC(mac, additionalData, 0, additionalData.length);
+ updateRecordMAC(mac, buf, off, len);
+
+ byte[] output = new byte[mac.getMacSize()];
+ mac.doFinal(output, 0);
+ return output;
+ }
+
+ protected void updateRecordMAC(Mac mac, byte[] buf, int off, int len)
+ {
+ mac.update(buf, off, len);
+
+ byte[] longLen = Pack.longToLittleEndian(len & 0xFFFFFFFFL);
+ mac.update(longLen, 0, longLen.length);
+ }
+
+ protected byte[] getAdditionalData(long seqNo, short type, int len) throws IOException
+ {
+ /*
+ * additional_data = seq_num + TLSCompressed.type + TLSCompressed.version +
+ * TLSCompressed.length
+ */
+ byte[] additional_data = new byte[13];
+ TlsUtils.writeUint64(seqNo, additional_data, 0);
+ TlsUtils.writeUint8(type, additional_data, 8);
+ TlsUtils.writeVersion(context.getServerVersion(), additional_data, 9);
+ TlsUtils.writeUint16(len, additional_data, 11);
+
+ return additional_data;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/ChangeCipherSpec.java b/core/src/main/java/org/spongycastle/crypto/tls/ChangeCipherSpec.java
new file mode 100644
index 00000000..b3a23c39
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/ChangeCipherSpec.java
@@ -0,0 +1,6 @@
+package org.spongycastle.crypto.tls;
+
+public class ChangeCipherSpec
+{
+ public static final short change_cipher_spec = 1;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/CipherSuite.java b/core/src/main/java/org/spongycastle/crypto/tls/CipherSuite.java
new file mode 100644
index 00000000..420f0d29
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/CipherSuite.java
@@ -0,0 +1,351 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 2246 A.5
+ */
+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;
+ public static final int TLS_RSA_EXPORT_WITH_RC4_40_MD5 = 0x0003;
+ public static final int TLS_RSA_WITH_RC4_128_MD5 = 0x0004;
+ public static final int TLS_RSA_WITH_RC4_128_SHA = 0x0005;
+ public static final int TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 0x0006;
+ public static final int TLS_RSA_WITH_IDEA_CBC_SHA = 0x0007;
+ public static final int TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0008;
+ public static final int TLS_RSA_WITH_DES_CBC_SHA = 0x0009;
+ public static final int TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A;
+ public static final int TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x000B;
+ public static final int TLS_DH_DSS_WITH_DES_CBC_SHA = 0x000C;
+ public static final int TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x000D;
+ public static final int TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x000E;
+ public static final int TLS_DH_RSA_WITH_DES_CBC_SHA = 0x000F;
+ public static final int TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0010;
+ public static final int TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x0011;
+ public static final int TLS_DHE_DSS_WITH_DES_CBC_SHA = 0x0012;
+ public static final int TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013;
+ public static final int TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0014;
+ public static final int TLS_DHE_RSA_WITH_DES_CBC_SHA = 0x0015;
+ public static final int TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016;
+ public static final int TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = 0x0017;
+ public static final int TLS_DH_anon_WITH_RC4_128_MD5 = 0x0018;
+ public static final int TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 0x0019;
+ public static final int TLS_DH_anon_WITH_DES_CBC_SHA = 0x001A;
+ public static final int TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0x001B;
+
+ /*
+ * Note: The cipher suite values { 0x00, 0x1C } and { 0x00, 0x1D } are reserved to avoid
+ * collision with Fortezza-based cipher suites in SSL 3.
+ */
+
+ /*
+ * RFC 3268
+ */
+ public static final int TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F;
+ public static final int TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0x0030;
+ public static final int TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0x0031;
+ public static final int TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032;
+ public static final int TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033;
+ public static final int TLS_DH_anon_WITH_AES_128_CBC_SHA = 0x0034;
+ public static final int TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035;
+ public static final int TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0x0036;
+ public static final int TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0x0037;
+ public static final int TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038;
+ public static final int TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039;
+ public static final int TLS_DH_anon_WITH_AES_256_CBC_SHA = 0x003A;
+
+ /*
+ * RFC 5932
+ */
+ public static final int TLS_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0041;
+ public static final int TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA = 0x0042;
+ public static final int TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0043;
+ public static final int TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA = 0x0044;
+ public static final int TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0045;
+ public static final int TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA = 0x0046;
+
+ public static final int TLS_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0084;
+ public static final int TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0085;
+ public static final int TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0086;
+ public static final int TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0087;
+ public static final int TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0088;
+ public static final int TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA = 0x0089;
+
+ public static final int TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BA;
+ public static final int TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BB;
+ public static final int TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BC;
+ public static final int TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BD;
+ public static final int TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BE;
+ public static final int TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BF;
+
+ public static final int TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C0;
+ public static final int TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C1;
+ public static final int TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C2;
+ public static final int TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C3;
+ public static final int TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C4;
+ public static final int TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C5;
+
+ /*
+ * RFC 4162
+ */
+ public static final int TLS_RSA_WITH_SEED_CBC_SHA = 0x0096;
+ public static final int TLS_DH_DSS_WITH_SEED_CBC_SHA = 0x0097;
+ public static final int TLS_DH_RSA_WITH_SEED_CBC_SHA = 0x0098;
+ public static final int TLS_DHE_DSS_WITH_SEED_CBC_SHA = 0x0099;
+ public static final int TLS_DHE_RSA_WITH_SEED_CBC_SHA = 0x009A;
+ public static final int TLS_DH_anon_WITH_SEED_CBC_SHA = 0x009B;
+
+ /*
+ * RFC 4279
+ */
+ public static final int TLS_PSK_WITH_RC4_128_SHA = 0x008A;
+ public static final int TLS_PSK_WITH_3DES_EDE_CBC_SHA = 0x008B;
+ public static final int TLS_PSK_WITH_AES_128_CBC_SHA = 0x008C;
+ public static final int TLS_PSK_WITH_AES_256_CBC_SHA = 0x008D;
+ public static final int TLS_DHE_PSK_WITH_RC4_128_SHA = 0x008E;
+ public static final int TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA = 0x008F;
+ public static final int TLS_DHE_PSK_WITH_AES_128_CBC_SHA = 0x0090;
+ public static final int TLS_DHE_PSK_WITH_AES_256_CBC_SHA = 0x0091;
+ public static final int TLS_RSA_PSK_WITH_RC4_128_SHA = 0x0092;
+ public static final int TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA = 0x0093;
+ public static final int TLS_RSA_PSK_WITH_AES_128_CBC_SHA = 0x0094;
+ public static final int TLS_RSA_PSK_WITH_AES_256_CBC_SHA = 0x0095;
+
+ /*
+ * RFC 4492
+ */
+ public static final int TLS_ECDH_ECDSA_WITH_NULL_SHA = 0xC001;
+ public static final int TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 0xC002;
+ public static final int TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC003;
+ public static final int TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = 0xC004;
+ public static final int TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0xC005;
+ public static final int TLS_ECDHE_ECDSA_WITH_NULL_SHA = 0xC006;
+ public static final int TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 0xC007;
+ public static final int TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC008;
+ public static final int TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009;
+ public static final int TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A;
+ public static final int TLS_ECDH_RSA_WITH_NULL_SHA = 0xC00B;
+ public static final int TLS_ECDH_RSA_WITH_RC4_128_SHA = 0xC00C;
+ public static final int TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = 0xC00D;
+ public static final int TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = 0xC00E;
+ public static final int TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = 0xC00F;
+ public static final int TLS_ECDHE_RSA_WITH_NULL_SHA = 0xC010;
+ public static final int TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xC011;
+ public static final int TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xC012;
+ public static final int TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013;
+ public static final int TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014;
+ public static final int TLS_ECDH_anon_WITH_NULL_SHA = 0xC015;
+ public static final int TLS_ECDH_anon_WITH_RC4_128_SHA = 0xC016;
+ public static final int TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA = 0xC017;
+ public static final int TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 0xC018;
+ public static final int TLS_ECDH_anon_WITH_AES_256_CBC_SHA = 0xC019;
+
+ /*
+ * RFC 4785
+ */
+ public static final int TLS_PSK_WITH_NULL_SHA = 0x002C;
+ public static final int TLS_DHE_PSK_WITH_NULL_SHA = 0x002D;
+ public static final int TLS_RSA_PSK_WITH_NULL_SHA = 0x002E;
+
+ /*
+ * RFC 5054
+ */
+ public static final int TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA = 0xC01A;
+ public static final int TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA = 0xC01B;
+ public static final int TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA = 0xC01C;
+ public static final int TLS_SRP_SHA_WITH_AES_128_CBC_SHA = 0xC01D;
+ public static final int TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA = 0xC01E;
+ public static final int TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA = 0xC01F;
+ public static final int TLS_SRP_SHA_WITH_AES_256_CBC_SHA = 0xC020;
+ public static final int TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA = 0xC021;
+ public static final int TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA = 0xC022;
+
+ /*
+ * RFC 5246
+ */
+ public static final int TLS_RSA_WITH_NULL_SHA256 = 0x003B;
+ public static final int TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C;
+ public static final int TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D;
+ public static final int TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 0x003E;
+ public static final int TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 0x003F;
+ public static final int TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040;
+ public static final int TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067;
+ public static final int TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 0x0068;
+ public static final int TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 0x0069;
+ public static final int TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A;
+ public static final int TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B;
+ public static final int TLS_DH_anon_WITH_AES_128_CBC_SHA256 = 0x006C;
+ public static final int TLS_DH_anon_WITH_AES_256_CBC_SHA256 = 0x006D;
+
+ /*
+ * RFC 5288
+ */
+ public static final int TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C;
+ public static final int TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D;
+ public static final int TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E;
+ public static final int TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F;
+ public static final int TLS_DH_RSA_WITH_AES_128_GCM_SHA256 = 0x00A0;
+ public static final int TLS_DH_RSA_WITH_AES_256_GCM_SHA384 = 0x00A1;
+ public static final int TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = 0x00A2;
+ public static final int TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = 0x00A3;
+ public static final int TLS_DH_DSS_WITH_AES_128_GCM_SHA256 = 0x00A4;
+ public static final int TLS_DH_DSS_WITH_AES_256_GCM_SHA384 = 0x00A5;
+ public static final int TLS_DH_anon_WITH_AES_128_GCM_SHA256 = 0x00A6;
+ public static final int TLS_DH_anon_WITH_AES_256_GCM_SHA384 = 0x00A7;
+
+ /*
+ * RFC 5289
+ */
+ public static final int TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023;
+ public static final int TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024;
+ public static final int TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC025;
+ public static final int TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC026;
+ public static final int TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027;
+ public static final int TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028;
+ public static final int TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 = 0xC029;
+ public static final int TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 = 0xC02A;
+ public static final int TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B;
+ public static final int TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C;
+ public static final int TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02D;
+ public static final int TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02E;
+ public static final int TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F;
+ public static final int TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030;
+ public static final int TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 = 0xC031;
+ 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 6367
+ */
+ public static final int TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC072;
+ public static final int TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC073;
+ public static final int TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC074;
+ public static final int TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC075;
+ public static final int TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC076;
+ public static final int TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC077;
+ public static final int TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC078;
+ public static final int TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC079;
+
+ public static final int TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07A;
+ public static final int TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07B;
+ public static final int TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07C;
+ public static final int TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07D;
+ public static final int TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07E;
+ public static final int TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07F;
+ public static final int TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 = 0xC080;
+ public static final int TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 = 0xC081;
+ public static final int TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256 = 0xC082;
+ public static final int TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384 = 0xC083;
+ public static final int TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256 = 0xC084;
+ public static final int TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384 = 0xC085;
+ public static final int TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC086;
+ public static final int TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC087;
+ public static final int TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC088;
+ public static final int TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC089;
+ public static final int TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08A;
+ public static final int TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08B;
+ public static final int TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08C;
+ public static final int TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08D;
+
+ public static final int TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08E;
+ public static final int TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08F;
+ public static final int TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC090;
+ public static final int TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC091;
+ public static final int TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC092;
+ public static final int TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC093;
+ public static final int TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC094;
+ public static final int TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC095;
+ public static final int TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC096;
+ public static final int TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC097;
+ public static final int TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC098;
+ public static final int TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC099;
+ public static final int TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC09A;
+ public static final int TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC09B;
+
+ /*
+ * 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;
+
+ /*
+ * draft-agl-tls-chacha20poly1305-04
+ */
+ public static final int TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC13;
+ public static final int TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC14;
+ public static final int TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC15;
+
+ /*
+ * draft-josefsson-salsa20-tls-04
+ */
+ public static final int TLS_RSA_WITH_ESTREAM_SALSA20_SHA1 = 0xE410;
+ public static final int TLS_RSA_WITH_SALSA20_SHA1 = 0xE411;
+ public static final int TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1 = 0xE412;
+ public static final int TLS_ECDHE_RSA_WITH_SALSA20_SHA1 = 0xE413;
+ public static final int TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1 = 0xE414;
+ public static final int TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1 = 0xE415;
+ public static final int TLS_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xE416;
+ public static final int TLS_PSK_WITH_SALSA20_SHA1 = 0xE417;
+ public static final int TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xE418;
+ public static final int TLS_ECDHE_PSK_WITH_SALSA20_SHA1 = 0xE419;
+ public static final int TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xE41A;
+ public static final int TLS_RSA_PSK_WITH_SALSA20_SHA1 = 0xE41B;
+ public static final int TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xE41C;
+ public static final int TLS_DHE_PSK_WITH_SALSA20_SHA1 = 0xE41D;
+ public static final int TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1 = 0xE41E;
+ public static final int TLS_DHE_RSA_WITH_SALSA20_SHA1 = 0xE41F;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/CipherType.java b/core/src/main/java/org/spongycastle/crypto/tls/CipherType.java
new file mode 100644
index 00000000..253da6f6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/CipherType.java
@@ -0,0 +1,18 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 2246
+ * <p>
+ * Note that the values here are implementation-specific and arbitrary. It is recommended not to
+ * depend on the particular values (e.g. serialization).
+ */
+public class CipherType
+{
+ public static final int stream = 0;
+ public static final int block = 1;
+
+ /*
+ * RFC 5246
+ */
+ public static final int aead = 2;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/ClientAuthenticationType.java b/core/src/main/java/org/spongycastle/crypto/tls/ClientAuthenticationType.java
new file mode 100644
index 00000000..90eb48f2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/ClientAuthenticationType.java
@@ -0,0 +1,11 @@
+package org.spongycastle.crypto.tls;
+
+public class ClientAuthenticationType
+{
+ /*
+ * RFC 5077 4
+ */
+ public static final short anonymous = 0;
+ public static final short certificate_based = 1;
+ public static final short psk = 2;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/ClientCertificateType.java b/core/src/main/java/org/spongycastle/crypto/tls/ClientCertificateType.java
new file mode 100644
index 00000000..35752b07
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/ClientCertificateType.java
@@ -0,0 +1,22 @@
+package org.spongycastle.crypto.tls;
+
+public class ClientCertificateType
+{
+ /*
+ * RFC 4346 7.4.4
+ */
+ public static final short rsa_sign = 1;
+ public static final short dss_sign = 2;
+ public static final short rsa_fixed_dh = 3;
+ public static final short dss_fixed_dh = 4;
+ public static final short rsa_ephemeral_dh_RESERVED = 5;
+ public static final short dss_ephemeral_dh_RESERVED = 6;
+ public static final short fortezza_dms_RESERVED = 20;
+
+ /*
+ * RFC 4492 5.5
+ */
+ public static final short ecdsa_sign = 64;
+ public static final short rsa_fixed_ecdh = 65;
+ public static final short ecdsa_fixed_ecdh = 66;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/CombinedHash.java b/core/src/main/java/org/spongycastle/crypto/tls/CombinedHash.java
new file mode 100644
index 00000000..b32ad91e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/CombinedHash.java
@@ -0,0 +1,135 @@
+package org.spongycastle.crypto.tls;
+
+import org.spongycastle.crypto.Digest;
+
+/**
+ * A combined hash, which implements md5(m) || sha1(m).
+ */
+class CombinedHash
+ implements TlsHandshakeHash
+{
+ protected TlsContext context;
+ protected Digest md5;
+ protected Digest sha1;
+
+ CombinedHash()
+ {
+ this.md5 = TlsUtils.createHash(HashAlgorithm.md5);
+ this.sha1 = TlsUtils.createHash(HashAlgorithm.sha1);
+ }
+
+ CombinedHash(CombinedHash t)
+ {
+ this.context = t.context;
+ this.md5 = TlsUtils.cloneHash(HashAlgorithm.md5, t.md5);
+ this.sha1 = TlsUtils.cloneHash(HashAlgorithm.sha1, t.sha1);
+ }
+
+ public void init(TlsContext context)
+ {
+ this.context = context;
+ }
+
+ public TlsHandshakeHash notifyPRFDetermined()
+ {
+ return this;
+ }
+
+ 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.spongycastle.crypto.Digest#getAlgorithmName()
+ */
+ public String getAlgorithmName()
+ {
+ return md5.getAlgorithmName() + " and " + sha1.getAlgorithmName();
+ }
+
+ /**
+ * @see org.spongycastle.crypto.Digest#getDigestSize()
+ */
+ public int getDigestSize()
+ {
+ return md5.getDigestSize() + sha1.getDigestSize();
+ }
+
+ /**
+ * @see org.spongycastle.crypto.Digest#update(byte)
+ */
+ public void update(byte in)
+ {
+ md5.update(in);
+ sha1.update(in);
+ }
+
+ /**
+ * @see org.spongycastle.crypto.Digest#update(byte[], int, int)
+ */
+ public void update(byte[] in, int inOff, int len)
+ {
+ md5.update(in, inOff, len);
+ sha1.update(in, inOff, len);
+ }
+
+ /**
+ * @see org.spongycastle.crypto.Digest#doFinal(byte[], int)
+ */
+ public int doFinal(byte[] out, int outOff)
+ {
+ if (context != null && TlsUtils.isSSL(context))
+ {
+ ssl3Complete(md5, SSL3Mac.IPAD, SSL3Mac.OPAD, 48);
+ ssl3Complete(sha1, SSL3Mac.IPAD, SSL3Mac.OPAD, 40);
+ }
+
+ int i1 = md5.doFinal(out, outOff);
+ int i2 = sha1.doFinal(out, outOff + i1);
+ return i1 + i2;
+ }
+
+ /**
+ * @see org.spongycastle.crypto.Digest#reset()
+ */
+ public void reset()
+ {
+ md5.reset();
+ sha1.reset();
+ }
+
+ protected void ssl3Complete(Digest d, byte[] ipad, byte[] opad, int padLength)
+ {
+ byte[] master_secret = context.getSecurityParameters().masterSecret;
+
+ 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(master_secret, 0, master_secret.length);
+ d.update(opad, 0, padLength);
+ d.update(tmp, 0, tmp.length);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/CompressionMethod.java b/core/src/main/java/org/spongycastle/crypto/tls/CompressionMethod.java
new file mode 100644
index 00000000..2a19b7ff
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/CompressionMethod.java
@@ -0,0 +1,24 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 2246 6.1
+ */
+public class CompressionMethod
+{
+ public static final short _null = 0;
+
+ /**
+ * @deprecated use '_null' instead
+ */
+ public static final short NULL = _null;
+
+ /*
+ * RFC 3749 2
+ */
+ public static final short DEFLATE = 1;
+
+ /*
+ * Values from 224 decimal (0xE0) through 255 decimal (0xFF)
+ * inclusive are reserved for private use.
+ */
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/ConnectionEnd.java b/core/src/main/java/org/spongycastle/crypto/tls/ConnectionEnd.java
new file mode 100644
index 00000000..4964eff7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/ConnectionEnd.java
@@ -0,0 +1,13 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 2246
+ * <p>
+ * Note that the values here are implementation-specific and arbitrary. It is recommended not to
+ * depend on the particular values (e.g. serialization).
+ */
+public class ConnectionEnd
+{
+ public static final int server = 0;
+ public static final int client = 1;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/ContentType.java b/core/src/main/java/org/spongycastle/crypto/tls/ContentType.java
new file mode 100644
index 00000000..8704dd80
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/ContentType.java
@@ -0,0 +1,13 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 2246 6.2.1
+ */
+public class ContentType
+{
+ public static final short change_cipher_spec = 20;
+ 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/core/src/main/java/org/spongycastle/crypto/tls/DTLSClientProtocol.java b/core/src/main/java/org/spongycastle/crypto/tls/DTLSClientProtocol.java
new file mode 100644
index 00000000..f5a4f80c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/DTLSClientProtocol.java
@@ -0,0 +1,831 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.SecureRandom;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.spongycastle.util.Arrays;
+
+public class DTLSClientProtocol
+ extends DTLSProtocol
+{
+ public DTLSClientProtocol(SecureRandom secureRandom)
+ {
+ super(secureRandom);
+ }
+
+ public DTLSTransport connect(TlsClient client, DatagramTransport transport)
+ throws IOException
+ {
+ if (client == null)
+ {
+ throw new IllegalArgumentException("'client' cannot be null");
+ }
+ if (transport == null)
+ {
+ throw new IllegalArgumentException("'transport' cannot be null");
+ }
+
+ SecurityParameters securityParameters = new SecurityParameters();
+ securityParameters.entity = ConnectionEnd.client;
+
+ ClientHandshakeState state = new ClientHandshakeState();
+ state.client = client;
+ state.clientContext = new TlsClientContextImpl(secureRandom, securityParameters);
+
+ securityParameters.clientRandom = TlsProtocol.createRandomBlock(client.shouldUseGMTUnixTime(),
+ state.clientContext.getNonceRandomGenerator());
+
+ client.init(state.clientContext);
+
+ 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);
+ }
+ catch (TlsFatalAlert fatalAlert)
+ {
+ recordLayer.fail(fatalAlert.getAlertDescription());
+ throw fatalAlert;
+ }
+ catch (IOException e)
+ {
+ recordLayer.fail(AlertDescription.internal_error);
+ throw e;
+ }
+ catch (RuntimeException e)
+ {
+ recordLayer.fail(AlertDescription.internal_error);
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ protected DTLSTransport clientHandshake(ClientHandshakeState state, DTLSRecordLayer recordLayer)
+ throws IOException
+ {
+ SecurityParameters securityParameters = state.clientContext.getSecurityParameters();
+ DTLSReliableHandshake handshake = new DTLSReliableHandshake(state.clientContext, recordLayer);
+
+ byte[] clientHelloBody = generateClientHello(state, state.client);
+ handshake.sendMessage(HandshakeType.client_hello, clientHelloBody);
+
+ DTLSReliableHandshake.Message serverMessage = handshake.receiveMessage();
+
+ while (serverMessage.getType() == HandshakeType.hello_verify_request)
+ {
+ ProtocolVersion recordLayerVersion = recordLayer.resetDiscoveredPeerVersion();
+ ProtocolVersion client_version = state.clientContext.getClientVersion();
+
+ /*
+ * 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);
+ }
+
+ byte[] cookie = processHelloVerifyRequest(state, serverMessage.getBody());
+ byte[] patched = patchClientHelloWithCookie(clientHelloBody, cookie);
+
+ handshake.resetHandshakeMessagesDigest();
+ handshake.sendMessage(HandshakeType.client_hello, patched);
+
+ serverMessage = handshake.receiveMessage();
+ }
+
+ if (serverMessage.getType() == HandshakeType.server_hello)
+ {
+ reportServerVersion(state, recordLayer.getDiscoveredPeerVersion());
+
+ processServerHello(state, serverMessage.getBody());
+ }
+ else
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ 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
+ * a verify_data_length equal to 12. This includes all existing cipher suites.
+ */
+ securityParameters.verifyDataLength = 12;
+
+ 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());
+ serverMessage = handshake.receiveMessage();
+ }
+ else
+ {
+ state.client.processServerSupplementalData(null);
+ }
+
+ state.keyExchange = state.client.getKeyExchange();
+ state.keyExchange.init(state.clientContext);
+
+ Certificate serverCertificate = null;
+
+ if (serverMessage.getType() == HandshakeType.certificate)
+ {
+ serverCertificate = processServerCertificate(state, serverMessage.getBody());
+ serverMessage = handshake.receiveMessage();
+ }
+ else
+ {
+ // Okay, Certificate is optional
+ 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());
+ serverMessage = handshake.receiveMessage();
+ }
+ else
+ {
+ // Okay, ServerKeyExchange is optional
+ state.keyExchange.skipServerKeyExchange();
+ }
+
+ 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
+ {
+ // Okay, CertificateRequest is optional
+ }
+
+ if (serverMessage.getType() == HandshakeType.server_hello_done)
+ {
+ if (serverMessage.getBody().length != 0)
+ {
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+ }
+ else
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ handshake.getHandshakeHash().sealHashAlgorithms();
+
+ Vector clientSupplementalData = state.client.getClientSupplementalData();
+ if (clientSupplementalData != null)
+ {
+ byte[] supplementalDataBody = generateSupplementalData(clientSupplementalData);
+ handshake.sendMessage(HandshakeType.supplemental_data, supplementalDataBody);
+ }
+
+ if (state.certificateRequest != null)
+ {
+ state.clientCredentials = state.authentication.getClientCredentials(state.certificateRequest);
+
+ /*
+ * RFC 5246 If no suitable certificate is available, the client MUST send a certificate
+ * message containing no certificates.
+ *
+ * NOTE: In previous RFCs, this was SHOULD instead of MUST.
+ */
+ Certificate clientCertificate = null;
+ if (state.clientCredentials != null)
+ {
+ clientCertificate = state.clientCredentials.getCertificate();
+ }
+ if (clientCertificate == null)
+ {
+ clientCertificate = Certificate.EMPTY_CHAIN;
+ }
+
+ byte[] certificateBody = generateCertificate(clientCertificate);
+ handshake.sendMessage(HandshakeType.certificate, certificateBody);
+ }
+
+ if (state.clientCredentials != null)
+ {
+ state.keyExchange.processClientCredentials(state.clientCredentials);
+ }
+ else
+ {
+ state.keyExchange.skipClientCredentials();
+ }
+
+ byte[] clientKeyExchangeBody = generateClientKeyExchange(state);
+ 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 != null && state.clientCredentials instanceof TlsSignerCredentials)
+ {
+ TlsSignerCredentials signerCredentials = (TlsSignerCredentials)state.clientCredentials;
+
+ /*
+ * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2
+ */
+ 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);
+ }
+
+ // 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);
+
+ if (state.expectSessionTicket)
+ {
+ serverMessage = handshake.receiveMessage();
+ if (serverMessage.getType() == HandshakeType.session_ticket)
+ {
+ processNewSessionTicket(state, serverMessage.getBody());
+ }
+ else
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ }
+
+ // 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);
+
+ handshake.finish();
+
+ if (state.tlsSession != null)
+ {
+ state.sessionParameters = new SessionParameters.Builder()
+ .setCipherSuite(securityParameters.cipherSuite)
+ .setCompressionAlgorithm(securityParameters.compressionAlgorithm)
+ .setMasterSecret(securityParameters.masterSecret)
+ .setPeerCertificate(serverCertificate)
+ .build();
+
+ 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, DigitallySigned certificateVerify)
+ throws IOException
+ {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ certificateVerify.encode(buf);
+ return buf.toByteArray();
+ }
+
+ protected byte[] generateClientHello(ClientHandshakeState state, TlsClient client)
+ throws IOException
+ {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+
+ ProtocolVersion client_version = client.getClientVersion();
+ if (!client_version.isDTLS())
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ state.clientContext.setClientVersion(client_version);
+ TlsUtils.writeVersion(client_version, buf);
+
+ buf.write(state.clientContext.getSecurityParameters().getClientRandom());
+
+ // 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);
+
+ /*
+ * Cipher suites
+ */
+ state.offeredCipherSuites = client.getCipherSuites();
+
+ // Integer -> byte[]
+ state.clientExtensions = client.getClientExtensions();
+
+ // Cipher Suites (and SCSV)
+ {
+ /*
+ * RFC 5746 3.4. The client MUST include either an empty "renegotiation_info" extension,
+ * or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling cipher suite value in the
+ * ClientHello. Including both is NOT RECOMMENDED.
+ */
+ byte[] renegExtData = TlsUtils.getExtensionData(state.clientExtensions, TlsProtocol.EXT_RenegotiationInfo);
+ boolean noRenegExt = (null == renegExtData);
+
+ boolean noSCSV = !Arrays.contains(state.offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
+
+ if (noRenegExt && noSCSV)
+ {
+ // 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 };
+
+ TlsUtils.writeUint8ArrayWithUint8Length(state.offeredCompressionMethods, buf);
+
+ // Extensions
+ if (state.clientExtensions != null)
+ {
+ TlsProtocol.writeExtensions(buf, state.clientExtensions);
+ }
+
+ return buf.toByteArray();
+ }
+
+ 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)
+ {
+ /*
+ * RFC 2246 7.4.4. It is a fatal handshake_failure alert for an anonymous server to
+ * request client identification.
+ */
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
+ }
+
+ ByteArrayInputStream buf = new ByteArrayInputStream(body);
+
+ state.certificateRequest = CertificateRequest.parse(state.clientContext, buf);
+
+ TlsProtocol.assertEmpty(buf);
+
+ state.keyExchange.validateCertificateRequest(state.certificateRequest);
+ }
+
+ 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);
+
+ state.client.notifyNewSessionTicket(newSessionTicket);
+ }
+
+ protected Certificate processServerCertificate(ClientHandshakeState state, byte[] body)
+ throws IOException
+ {
+ ByteArrayInputStream buf = new ByteArrayInputStream(body);
+
+ Certificate serverCertificate = Certificate.parse(buf);
+
+ TlsProtocol.assertEmpty(buf);
+
+ 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);
+
+ ProtocolVersion server_version = TlsUtils.readVersion(buf);
+ reportServerVersion(state, server_version);
+
+ securityParameters.serverRandom = TlsUtils.readFully(32, buf);
+
+ state.selectedSessionID = TlsUtils.readOpaque8(buf);
+ if (state.selectedSessionID.length > 32)
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ state.client.notifySessionID(state.selectedSessionID);
+
+ state.selectedCipherSuite = TlsUtils.readUint16(buf);
+ if (!Arrays.contains(state.offeredCipherSuites, state.selectedCipherSuite)
+ || state.selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL
+ || state.selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV
+ || !TlsUtils.isValidCipherSuiteForVersion(state.selectedCipherSuite, server_version))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ validateSelectedCipherSuite(state.selectedCipherSuite, AlertDescription.illegal_parameter);
+
+ state.client.notifySelectedCipherSuite(state.selectedCipherSuite);
+
+ state.selectedCompressionMethod = TlsUtils.readUint8(buf);
+ if (!Arrays.contains(state.offeredCompressionMethods, state.selectedCompressionMethod))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ state.client.notifySelectedCompressionMethod(state.selectedCompressionMethod);
+
+ /*
+ * RFC3546 2.2 The extended server hello message format MAY be sent in place of the server
+ * hello message when the client has requested extended functionality via the extended
+ * client hello message specified in Section 2.1. ... Note that the extended server hello
+ * message is only sent in response to an extended client hello message. This prevents the
+ * 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 = TlsProtocol.readExtensions(buf);
+
+ /*
+ * RFC 3546 2.2 Note that the extended server hello message is only sent in response to an
+ * extended client hello message. However, see RFC 5746 exception below. We always include
+ * the SCSV, so an Extended Server Hello is always allowed.
+ */
+ if (serverExtensions != null)
+ {
+ Enumeration e = serverExtensions.keys();
+ while (e.hasMoreElements())
+ {
+ Integer extType = (Integer)e.nextElement();
+
+ /*
+ * RFC 5746 Note that sending a "renegotiation_info" extension in response to a
+ * ClientHello containing only the SCSV is an explicit exception to the prohibition
+ * in RFC 5246, Section 7.4.1.4, on the server sending unsolicited extensions and is
+ * only allowed because the client is signaling its willingness to receive the
+ * extension via the TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. TLS implementations
+ * MUST continue to comply with Section 7.4.1.4 for all other extensions.
+ */
+ if (!extType.equals(TlsProtocol.EXT_RenegotiationInfo)
+ && null == TlsUtils.getExtensionData(state.clientExtensions, extType))
+ {
+ /*
+ * RFC 3546 2.3 Note that for all extension types (including those defined in
+ * future), the extension type MUST NOT appear in the extended server hello
+ * unless the same extension type appeared in the corresponding client hello.
+ * Thus clients MUST abort the handshake if they receive an extension type in
+ * the extended server hello that they did not request in the associated
+ * (extended) client hello.
+ */
+ throw new TlsFatalAlert(AlertDescription.unsupported_extension);
+ }
+ }
+
+ /*
+ * 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 = (byte[])serverExtensions.get(TlsProtocol.EXT_RenegotiationInfo);
+ if (renegExtData != 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).
+ */
+ state.secure_renegotiation = true;
+
+ if (!Arrays.constantTimeAreEqual(renegExtData,
+ TlsProtocol.createRenegotiationInfo(TlsUtils.EMPTY_BYTES)))
+ {
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
+ }
+ }
+ }
+
+ /*
+ * draft-ietf-tls-encrypt-then-mac-03 3. If a server receives an encrypt-then-MAC
+ * request extension from a client and then selects a stream or AEAD cipher suite, it
+ * MUST NOT send an encrypt-then-MAC response extension back to the client.
+ */
+ boolean serverSentEncryptThenMAC = TlsExtensionsUtils.hasEncryptThenMACExtension(serverExtensions);
+ if (serverSentEncryptThenMAC && !TlsUtils.isBlockCipherSuite(state.selectedCipherSuite))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ securityParameters.encryptThenMAC = serverSentEncryptThenMAC;
+
+ 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);
+
+ if (state.clientExtensions != null)
+ {
+ state.client.processServerExtensions(serverExtensions);
+ }
+ }
+
+ protected void processServerKeyExchange(ClientHandshakeState state, byte[] body)
+ throws IOException
+ {
+ ByteArrayInputStream buf = new ByteArrayInputStream(body);
+
+ state.keyExchange.processServerKeyExchange(buf);
+
+ TlsProtocol.assertEmpty(buf);
+ }
+
+ protected void processServerSupplementalData(ClientHandshakeState state, byte[] body)
+ throws IOException
+ {
+ ByteArrayInputStream buf = new ByteArrayInputStream(body);
+ Vector serverSupplementalData = TlsProtocol.readSupplementalDataMessage(buf);
+ state.client.processServerSupplementalData(serverSupplementalData);
+ }
+
+ protected void reportServerVersion(ClientHandshakeState state, ProtocolVersion server_version)
+ throws IOException
+ {
+ 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);
+ }
+ }
+
+ protected static byte[] patchClientHelloWithCookie(byte[] clientHelloBody, byte[] cookie)
+ throws IOException
+ {
+ int sessionIDPos = 34;
+ int sessionIDLength = TlsUtils.readUint8(clientHelloBody, sessionIDPos);
+
+ int cookieLengthPos = sessionIDPos + 1 + sessionIDLength;
+ int cookiePos = cookieLengthPos + 1;
+
+ byte[] patched = new byte[clientHelloBody.length + cookie.length];
+ System.arraycopy(clientHelloBody, 0, patched, 0, 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);
+
+ return patched;
+ }
+
+ protected static class ClientHandshakeState
+ {
+ 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/core/src/main/java/org/spongycastle/crypto/tls/DTLSEpoch.java b/core/src/main/java/org/spongycastle/crypto/tls/DTLSEpoch.java
new file mode 100644
index 00000000..33dda1c7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/DTLSEpoch.java
@@ -0,0 +1,52 @@
+package org.spongycastle.crypto.tls;
+
+class DTLSEpoch
+{
+ private final DTLSReplayWindow replayWindow = new DTLSReplayWindow();
+
+ private final int epoch;
+ private final TlsCipher cipher;
+
+ private long sequence_number = 0;
+
+ DTLSEpoch(int epoch, TlsCipher cipher)
+ {
+ if (epoch < 0)
+ {
+ throw new IllegalArgumentException("'epoch' must be >= 0");
+ }
+ if (cipher == null)
+ {
+ throw new IllegalArgumentException("'cipher' cannot be null");
+ }
+
+ this.epoch = epoch;
+ this.cipher = cipher;
+ }
+
+ long allocateSequenceNumber()
+ {
+ // TODO Check for overflow
+ return sequence_number++;
+ }
+
+ TlsCipher getCipher()
+ {
+ return cipher;
+ }
+
+ int getEpoch()
+ {
+ return epoch;
+ }
+
+ DTLSReplayWindow getReplayWindow()
+ {
+ return replayWindow;
+ }
+
+ long getSequence_number()
+ {
+ return sequence_number;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/DTLSHandshakeRetransmit.java b/core/src/main/java/org/spongycastle/crypto/tls/DTLSHandshakeRetransmit.java
new file mode 100644
index 00000000..f0b0086c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/DTLSHandshakeRetransmit.java
@@ -0,0 +1,9 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+interface DTLSHandshakeRetransmit
+{
+ void receivedHandshakeRecord(int epoch, byte[] buf, int off, int len)
+ throws IOException;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/DTLSProtocol.java b/core/src/main/java/org/spongycastle/crypto/tls/DTLSProtocol.java
new file mode 100644
index 00000000..13d5db00
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/DTLSProtocol.java
@@ -0,0 +1,78 @@
+package org.spongycastle.crypto.tls;
+
+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.spongycastle.util.Arrays;
+
+public abstract class DTLSProtocol
+{
+ protected final SecureRandom secureRandom;
+
+ protected DTLSProtocol(SecureRandom secureRandom)
+ {
+ if (secureRandom == null)
+ {
+ throw new IllegalArgumentException("'secureRandom' cannot be null");
+ }
+
+ this.secureRandom = secureRandom;
+ }
+
+ 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);
+
+ TlsProtocol.assertEmpty(buf);
+
+ if (!Arrays.constantTimeAreEqual(expected_verify_data, verify_data))
+ {
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
+ }
+ }
+
+ 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();
+ }
+
+ protected static byte[] generateSupplementalData(Vector supplementalData)
+ throws IOException
+ {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ TlsProtocol.writeSupplementalData(buf, supplementalData);
+ return buf.toByteArray();
+ }
+
+ protected static void validateSelectedCipherSuite(int selectedCipherSuite, short alertDescription)
+ throws IOException
+ {
+ switch (TlsUtils.getEncryptionAlgorithm(selectedCipherSuite))
+ {
+ case EncryptionAlgorithm.RC4_40:
+ case EncryptionAlgorithm.RC4_128:
+ throw new TlsFatalAlert(alertDescription);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/DTLSReassembler.java b/core/src/main/java/org/spongycastle/crypto/tls/DTLSReassembler.java
new file mode 100644
index 00000000..810d6979
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/DTLSReassembler.java
@@ -0,0 +1,133 @@
+package org.spongycastle.crypto.tls;
+
+import java.util.Vector;
+
+class DTLSReassembler
+{
+ private final short msg_type;
+ private final byte[] body;
+
+ private Vector missing = new Vector();
+
+ DTLSReassembler(short msg_type, int length)
+ {
+ this.msg_type = msg_type;
+ this.body = new byte[length];
+ this.missing.addElement(new Range(0, length));
+ }
+
+ short getType()
+ {
+ return msg_type;
+ }
+
+ byte[] getBodyIfComplete()
+ {
+ return missing.isEmpty() ? body : null;
+ }
+
+ void contributeFragment(short msg_type, int length, byte[] buf, int off, int fragment_offset,
+ int fragment_length)
+ {
+ int fragment_end = fragment_offset + fragment_length;
+
+ if (this.msg_type != msg_type || this.body.length != length || fragment_end > length)
+ {
+ return;
+ }
+
+ if (fragment_length == 0)
+ {
+ // NOTE: Empty messages still require an empty fragment to complete it
+ if (fragment_offset == 0 && !missing.isEmpty())
+ {
+ Range firstRange = (Range)missing.firstElement();
+ if (firstRange.getEnd() == 0)
+ {
+ missing.removeElementAt(0);
+ }
+ }
+ return;
+ }
+
+ for (int i = 0; i < missing.size(); ++i)
+ {
+ Range range = (Range)missing.elementAt(i);
+ if (range.getStart() >= fragment_end)
+ {
+ break;
+ }
+ if (range.getEnd() > fragment_offset)
+ {
+
+ int copyStart = Math.max(range.getStart(), fragment_offset);
+ int copyEnd = Math.min(range.getEnd(), fragment_end);
+ int copyLength = copyEnd - copyStart;
+
+ System.arraycopy(buf, off + copyStart - fragment_offset, body, copyStart,
+ copyLength);
+
+ if (copyStart == range.getStart())
+ {
+ if (copyEnd == range.getEnd())
+ {
+ missing.removeElementAt(i--);
+ }
+ else
+ {
+ range.setStart(copyEnd);
+ }
+ }
+ else
+ {
+ if (copyEnd == range.getEnd())
+ {
+ range.setEnd(copyStart);
+ }
+ else
+ {
+ missing.insertElementAt(new Range(copyEnd, range.getEnd()), ++i);
+ range.setEnd(copyStart);
+ }
+ }
+ }
+ }
+ }
+
+ void reset()
+ {
+ this.missing.removeAllElements();
+ this.missing.addElement(new Range(0, body.length));
+ }
+
+ private static class Range
+ {
+ private int start, end;
+
+ Range(int start, int end)
+ {
+ this.start = start;
+ this.end = end;
+ }
+
+ public int getStart()
+ {
+ return start;
+ }
+
+ public void setStart(int start)
+ {
+ this.start = start;
+ }
+
+ public int getEnd()
+ {
+ return end;
+ }
+
+ public void setEnd(int end)
+ {
+ this.end = end;
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/DTLSRecordLayer.java b/core/src/main/java/org/spongycastle/crypto/tls/DTLSRecordLayer.java
new file mode 100644
index 00000000..1f798d5a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/DTLSRecordLayer.java
@@ -0,0 +1,516 @@
+package org.spongycastle.crypto.tls;
+
+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;
+ private static final long RETRANSMIT_TIMEOUT = TCP_MSL * 2;
+
+ private final DatagramTransport transport;
+ private final TlsContext context;
+ private final TlsPeer peer;
+
+ private final ByteQueue recordQueue = new ByteQueue();
+
+ private volatile boolean closed = false;
+ 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;
+
+ private DTLSHandshakeRetransmit retransmit = null;
+ private DTLSEpoch retransmitEpoch = null;
+ private long retransmitExpiry = 0;
+
+ DTLSRecordLayer(DatagramTransport transport, TlsContext context, TlsPeer peer, short contentType)
+ {
+ this.transport = transport;
+ this.context = context;
+ this.peer = peer;
+
+ this.inHandshake = true;
+
+ this.currentEpoch = new DTLSEpoch(0, new TlsNullCipher(context));
+ this.pendingEpoch = null;
+ this.readEpoch = currentEpoch;
+ this.writeEpoch = currentEpoch;
+
+ setPlaintextLimit(MAX_FRAGMENT_LENGTH);
+ }
+
+ void setPlaintextLimit(int plaintextLimit)
+ {
+ this.plaintextLimit = plaintextLimit;
+ }
+
+ ProtocolVersion getDiscoveredPeerVersion()
+ {
+ return discoveredPeerVersion;
+ }
+
+ ProtocolVersion resetDiscoveredPeerVersion()
+ {
+ ProtocolVersion result = discoveredPeerVersion;
+ discoveredPeerVersion = null;
+ return result;
+ }
+
+ void initPendingEpoch(TlsCipher pendingCipher)
+ {
+ if (pendingEpoch != null)
+ {
+ throw new IllegalStateException();
+ }
+
+ /*
+ * TODO "In order to ensure that any given sequence/epoch pair is unique, implementations
+ * MUST NOT allow the same epoch value to be reused within two times the TCP maximum segment
+ * lifetime."
+ */
+
+ // TODO Check for overflow
+ this.pendingEpoch = new DTLSEpoch(writeEpoch.getEpoch() + 1, pendingCipher);
+ }
+
+ void handshakeSuccessful(DTLSHandshakeRetransmit retransmit)
+ {
+ if (readEpoch == currentEpoch || writeEpoch == currentEpoch)
+ {
+ // TODO
+ throw new IllegalStateException();
+ }
+
+ if (retransmit != null)
+ {
+ this.retransmit = retransmit;
+ this.retransmitEpoch = currentEpoch;
+ this.retransmitExpiry = System.currentTimeMillis() + RETRANSMIT_TIMEOUT;
+ }
+
+ this.inHandshake = false;
+ this.currentEpoch = pendingEpoch;
+ this.pendingEpoch = null;
+ }
+
+ void resetWriteEpoch()
+ {
+ if (retransmitEpoch != null)
+ {
+ this.writeEpoch = retransmitEpoch;
+ }
+ else
+ {
+ this.writeEpoch = currentEpoch;
+ }
+ }
+
+ public int getReceiveLimit()
+ throws IOException
+ {
+ return Math.min(this.plaintextLimit,
+ readEpoch.getCipher().getPlaintextLimit(transport.getReceiveLimit() - RECORD_HEADER_LENGTH));
+ }
+
+ public int getSendLimit()
+ throws IOException
+ {
+ 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 (;;)
+ {
+ int receiveLimit = Math.min(len, getReceiveLimit()) + RECORD_HEADER_LENGTH;
+ if (record == null || record.length < receiveLimit)
+ {
+ record = new byte[receiveLimit];
+ }
+
+ try
+ {
+ if (retransmit != null && System.currentTimeMillis() > retransmitExpiry)
+ {
+ retransmit = null;
+ retransmitEpoch = null;
+ }
+
+ int received = receiveRecord(record, 0, receiveLimit, waitMillis);
+ if (received < 0)
+ {
+ return received;
+ }
+ if (received < RECORD_HEADER_LENGTH)
+ {
+ continue;
+ }
+ int length = TlsUtils.readUint16(record, 11);
+ if (received != (length + RECORD_HEADER_LENGTH))
+ {
+ continue;
+ }
+
+ short type = TlsUtils.readUint8(record, 0);
+
+ // TODO Support user-specified custom protocols?
+ switch (type)
+ {
+ case ContentType.alert:
+ case ContentType.application_data:
+ case ContentType.change_cipher_spec:
+ case ContentType.handshake:
+ case ContentType.heartbeat:
+ break;
+ default:
+ // TODO Exception?
+ continue;
+ }
+
+ int epoch = TlsUtils.readUint16(record, 3);
+
+ DTLSEpoch recordEpoch = null;
+ if (epoch == readEpoch.getEpoch())
+ {
+ recordEpoch = readEpoch;
+ }
+ else if (type == ContentType.handshake && retransmitEpoch != null
+ && epoch == retransmitEpoch.getEpoch())
+ {
+ recordEpoch = retransmitEpoch;
+ }
+
+ if (recordEpoch == null)
+ {
+ continue;
+ }
+
+ long seq = TlsUtils.readUint48(record, 5);
+ if (recordEpoch.getReplayWindow().shouldDiscard(seq))
+ {
+ continue;
+ }
+
+ ProtocolVersion version = TlsUtils.readVersion(record, 1);
+ if (discoveredPeerVersion != null && !discoveredPeerVersion.equals(version))
+ {
+ continue;
+ }
+
+ byte[] plaintext = recordEpoch.getCipher().decodeCiphertext(
+ getMacSequenceNumber(recordEpoch.getEpoch(), seq), type, record, RECORD_HEADER_LENGTH,
+ received - RECORD_HEADER_LENGTH);
+
+ recordEpoch.getReplayWindow().reportAuthenticated(seq);
+
+ if (plaintext.length > this.plaintextLimit)
+ {
+ continue;
+ }
+
+ if (discoveredPeerVersion == null)
+ {
+ discoveredPeerVersion = version;
+ }
+
+ switch (type)
+ {
+ case ContentType.alert:
+ {
+ if (plaintext.length == 2)
+ {
+ short alertLevel = plaintext[0];
+ short alertDescription = plaintext[1];
+
+ peer.notifyAlertReceived(alertLevel, alertDescription);
+
+ if (alertLevel == AlertLevel.fatal)
+ {
+ fail(alertDescription);
+ throw new TlsFatalAlert(alertDescription);
+ }
+
+ // TODO Can close_notify be a fatal alert?
+ if (alertDescription == AlertDescription.close_notify)
+ {
+ closeTransport();
+ }
+ }
+
+ continue;
+ }
+ case ContentType.application_data:
+ {
+ if (inHandshake)
+ {
+ // TODO Consider buffering application data for new epoch that arrives
+ // out-of-order with the Finished message
+ continue;
+ }
+ break;
+ }
+ case ContentType.change_cipher_spec:
+ {
+ // Implicitly receive change_cipher_spec and change to pending cipher state
+
+ for (int i = 0; i < plaintext.length; ++i)
+ {
+ short message = TlsUtils.readUint8(plaintext, i);
+ if (message != ChangeCipherSpec.change_cipher_spec)
+ {
+ continue;
+ }
+
+ if (pendingEpoch != null)
+ {
+ readEpoch = pendingEpoch;
+ }
+ }
+
+ continue;
+ }
+ case ContentType.handshake:
+ {
+ if (!inHandshake)
+ {
+ if (retransmit != null)
+ {
+ retransmit.receivedHandshakeRecord(epoch, plaintext, 0, plaintext.length);
+ }
+
+ // TODO Consider support for HelloRequest
+ continue;
+ }
+ break;
+ }
+ case ContentType.heartbeat:
+ {
+ // TODO[RFC 6520]
+ continue;
+ }
+ }
+
+ /*
+ * NOTE: If we receive any non-handshake data in the new epoch implies the peer has
+ * received our final flight.
+ */
+ if (!inHandshake && retransmit != null)
+ {
+ this.retransmit = null;
+ this.retransmitEpoch = null;
+ }
+
+ System.arraycopy(plaintext, 0, buf, off, plaintext.length);
+ return plaintext.length;
+ }
+ catch (IOException e)
+ {
+ // NOTE: Assume this is a timeout for the moment
+ throw e;
+ }
+ }
+ }
+
+ 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)
+ {
+ nextEpoch = pendingEpoch;
+ }
+ else if (this.writeEpoch == this.retransmitEpoch)
+ {
+ nextEpoch = currentEpoch;
+ }
+
+ if (nextEpoch == null)
+ {
+ // TODO
+ throw new IllegalStateException();
+ }
+
+ // 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 };
+ sendRecord(ContentType.change_cipher_spec, data, 0, data.length);
+
+ writeEpoch = nextEpoch;
+ }
+ }
+
+ sendRecord(contentType, buf, off, len);
+ }
+
+ public void close()
+ throws IOException
+ {
+ if (!closed)
+ {
+ if (inHandshake)
+ {
+ warn(AlertDescription.user_canceled, "User canceled handshake");
+ }
+ closeTransport();
+ }
+ }
+
+ void fail(short alertDescription)
+ {
+ if (!closed)
+ {
+ try
+ {
+ raiseAlert(AlertLevel.fatal, alertDescription, null, null);
+ }
+ catch (Exception e)
+ {
+ // Ignore
+ }
+
+ failed = true;
+
+ closeTransport();
+ }
+ }
+
+ void warn(short alertDescription, String message)
+ throws IOException
+ {
+ raiseAlert(AlertLevel.warning, alertDescription, message, null);
+ }
+
+ private void closeTransport()
+ {
+ if (!closed)
+ {
+ /*
+ * RFC 5246 7.2.1. Unless some other fatal alert has been transmitted, each party is
+ * required to send a close_notify alert before closing the write side of the
+ * connection. The other party MUST respond with a close_notify alert of its own and
+ * close down the connection immediately, discarding any pending writes.
+ */
+
+ try
+ {
+ if (!failed)
+ {
+ warn(AlertDescription.close_notify, null);
+ }
+ transport.close();
+ }
+ catch (Exception e)
+ {
+ // Ignore
+ }
+
+ closed = true;
+ }
+ }
+
+ private void raiseAlert(short alertLevel, short alertDescription, String message, Exception cause)
+ throws IOException
+ {
+ peer.notifyAlertRaised(alertLevel, alertDescription, message, cause);
+
+ byte[] error = new byte[2];
+ error[0] = (byte)alertLevel;
+ error[1] = (byte)alertDescription;
+
+ sendRecord(ContentType.alert, error, 0, 2);
+ }
+
+ private int receiveRecord(byte[] buf, int off, int len, int waitMillis)
+ throws IOException
+ {
+ if (recordQueue.size() > 0)
+ {
+ int length = 0;
+ if (recordQueue.size() >= RECORD_HEADER_LENGTH)
+ {
+ byte[] lengthBytes = new byte[2];
+ recordQueue.read(lengthBytes, 0, 2, 11);
+ length = TlsUtils.readUint16(lengthBytes, 0);
+ }
+
+ int received = Math.min(recordQueue.size(), RECORD_HEADER_LENGTH + length);
+ recordQueue.removeData(buf, off, received, 0);
+ return received;
+ }
+
+ int received = transport.receive(buf, off, len, waitMillis);
+ if (received >= RECORD_HEADER_LENGTH)
+ {
+ int fragmentLength = TlsUtils.readUint16(buf, off + 11);
+ int recordLength = RECORD_HEADER_LENGTH + fragmentLength;
+ if (received > recordLength)
+ {
+ recordQueue.addData(buf, off + recordLength, received - recordLength);
+ received = recordLength;
+ }
+ }
+
+ return received;
+ }
+
+ 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,
+ * or ChangeCipherSpec content types.
+ */
+ if (len < 1 && contentType != ContentType.application_data)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ int recordEpoch = writeEpoch.getEpoch();
+ long recordSequenceNumber = writeEpoch.allocateSequenceNumber();
+
+ byte[] ciphertext = writeEpoch.getCipher().encodePlaintext(
+ getMacSequenceNumber(recordEpoch, recordSequenceNumber), contentType, buf, off, len);
+
+ // TODO Check the ciphertext length?
+
+ byte[] record = new byte[ciphertext.length + RECORD_HEADER_LENGTH];
+ TlsUtils.writeUint8(contentType, record, 0);
+ ProtocolVersion version = discoveredPeerVersion != null ? discoveredPeerVersion : context.getClientVersion();
+ TlsUtils.writeVersion(version, record, 1);
+ TlsUtils.writeUint16(recordEpoch, record, 3);
+ TlsUtils.writeUint48(recordSequenceNumber, record, 5);
+ TlsUtils.writeUint16(ciphertext.length, record, 11);
+ System.arraycopy(ciphertext, 0, record, RECORD_HEADER_LENGTH, ciphertext.length);
+
+ transport.send(record, 0, record.length);
+ }
+
+ private static long getMacSequenceNumber(int epoch, long sequence_number)
+ {
+ return ((epoch & 0xFFFFFFFFL) << 48) | sequence_number;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/DTLSReliableHandshake.java b/core/src/main/java/org/spongycastle/crypto/tls/DTLSReliableHandshake.java
new file mode 100644
index 00000000..d89dabca
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/DTLSReliableHandshake.java
@@ -0,0 +1,453 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.spongycastle.util.Integers;
+
+class DTLSReliableHandshake
+{
+ private final static int MAX_RECEIVE_AHEAD = 10;
+
+ private final DTLSRecordLayer recordLayer;
+
+ private TlsHandshakeHash handshakeHash;
+
+ private Hashtable currentInboundFlight = new Hashtable();
+ private Hashtable previousInboundFlight = null;
+ private Vector outboundFlight = new Vector();
+ private boolean sending = true;
+
+ private int message_seq = 0, next_receive_seq = 0;
+
+ DTLSReliableHandshake(TlsContext context, DTLSRecordLayer transport)
+ {
+ this.recordLayer = transport;
+ this.handshakeHash = new DeferredHash();
+ this.handshakeHash.init(context);
+ }
+
+ void notifyHelloComplete()
+ {
+ this.handshakeHash = handshakeHash.notifyPRFDetermined();
+ }
+
+ TlsHandshakeHash getHandshakeHash()
+ {
+ return handshakeHash;
+ }
+
+ TlsHandshakeHash prepareToFinish()
+ {
+ TlsHandshakeHash result = handshakeHash;
+ this.handshakeHash = handshakeHash.stopTracking();
+ return result;
+ }
+
+ void sendMessage(short msg_type, byte[] body)
+ throws IOException
+ {
+ TlsUtils.checkUint24(body.length);
+
+ if (!sending)
+ {
+ checkInboundFlight();
+ sending = true;
+ outboundFlight.removeAllElements();
+ }
+
+ Message message = new Message(message_seq++, msg_type, body);
+
+ outboundFlight.addElement(message);
+
+ writeMessage(message);
+ updateHandshakeMessagesDigest(message);
+ }
+
+ 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;
+ prepareInboundFlight();
+ }
+
+ // Check if we already have the next message waiting
+ {
+ DTLSReassembler next = (DTLSReassembler)currentInboundFlight.get(Integers.valueOf(next_receive_seq));
+ if (next != null)
+ {
+ byte[] body = next.getBodyIfComplete();
+ if (body != null)
+ {
+ previousInboundFlight = null;
+ return updateHandshakeMessagesDigest(new Message(next_receive_seq++, next.getType(), body));
+ }
+ }
+ }
+
+ byte[] buf = null;
+
+ // TODO Check the conditions under which we should reset this
+ int readTimeoutMillis = 1000;
+
+ for (;;)
+ {
+ int receiveLimit = recordLayer.getReceiveLimit();
+ if (buf == null || buf.length < receiveLimit)
+ {
+ buf = new byte[receiveLimit];
+ }
+
+ // TODO Handle records containing multiple handshake messages
+
+ try
+ {
+ for (; ; )
+ {
+ int received = recordLayer.receive(buf, 0, receiveLimit, readTimeoutMillis);
+ if (received < 0)
+ {
+ break;
+ }
+ if (received < 12)
+ {
+ continue;
+ }
+ int fragment_length = TlsUtils.readUint24(buf, 9);
+ if (received != (fragment_length + 12))
+ {
+ continue;
+ }
+ int seq = TlsUtils.readUint16(buf, 4);
+ if (seq > (next_receive_seq + MAX_RECEIVE_AHEAD))
+ {
+ continue;
+ }
+ short msg_type = TlsUtils.readUint8(buf, 0);
+ int length = TlsUtils.readUint24(buf, 1);
+ int fragment_offset = TlsUtils.readUint24(buf, 6);
+ if (fragment_offset + fragment_length > length)
+ {
+ continue;
+ }
+
+ if (seq < next_receive_seq)
+ {
+ /*
+ * NOTE: If we receive the previous flight of incoming messages in full
+ * again, retransmit our last flight
+ */
+ if (previousInboundFlight != null)
+ {
+ DTLSReassembler reassembler = (DTLSReassembler)previousInboundFlight.get(Integers
+ .valueOf(seq));
+ if (reassembler != null)
+ {
+ reassembler.contributeFragment(msg_type, length, buf, 12, fragment_offset,
+ fragment_length);
+
+ if (checkAll(previousInboundFlight))
+ {
+ resendOutboundFlight();
+
+ /*
+ * TODO[DTLS] implementations SHOULD back off handshake packet
+ * size during the retransmit backoff.
+ */
+ readTimeoutMillis = Math.min(readTimeoutMillis * 2, 60000);
+
+ resetAll(previousInboundFlight);
+ }
+ }
+ }
+ }
+ else
+ {
+ DTLSReassembler reassembler = (DTLSReassembler)currentInboundFlight.get(Integers.valueOf(seq));
+ if (reassembler == null)
+ {
+ reassembler = new DTLSReassembler(msg_type, length);
+ currentInboundFlight.put(Integers.valueOf(seq), reassembler);
+ }
+
+ reassembler.contributeFragment(msg_type, length, buf, 12, fragment_offset, fragment_length);
+
+ if (seq == next_receive_seq)
+ {
+ byte[] body = reassembler.getBodyIfComplete();
+ if (body != null)
+ {
+ previousInboundFlight = null;
+ return updateHandshakeMessagesDigest(new Message(next_receive_seq++,
+ reassembler.getType(), body));
+ }
+ }
+ }
+ }
+ }
+ catch (IOException e)
+ {
+ // NOTE: Assume this is a timeout for the moment
+ }
+
+ resendOutboundFlight();
+
+ /*
+ * TODO[DTLS] implementations SHOULD back off handshake packet size during the
+ * retransmit backoff.
+ */
+ readTimeoutMillis = Math.min(readTimeoutMillis * 2, 60000);
+ }
+ }
+
+ void finish()
+ {
+ DTLSHandshakeRetransmit retransmit = null;
+ if (!sending)
+ {
+ checkInboundFlight();
+ }
+ else if (currentInboundFlight != null)
+ {
+ /*
+ * RFC 6347 4.2.4. In addition, for at least twice the default MSL defined for [TCP],
+ * when in the FINISHED state, the node that transmits the last flight (the server in an
+ * ordinary handshake or the client in a resumed handshake) MUST respond to a retransmit
+ * of the peer's last flight with a retransmit of the last flight.
+ */
+ retransmit = new DTLSHandshakeRetransmit()
+ {
+ public void receivedHandshakeRecord(int epoch, byte[] buf, int off, int len)
+ throws IOException
+ {
+ /*
+ * TODO Need to handle the case where the previous inbound flight contains
+ * messages from two epochs.
+ */
+ if (len < 12)
+ {
+ return;
+ }
+ int fragment_length = TlsUtils.readUint24(buf, off + 9);
+ if (len != (fragment_length + 12))
+ {
+ return;
+ }
+ int seq = TlsUtils.readUint16(buf, off + 4);
+ if (seq >= next_receive_seq)
+ {
+ return;
+ }
+
+ short msg_type = TlsUtils.readUint8(buf, off);
+
+ // TODO This is a hack that only works until we try to support renegotiation
+ int expectedEpoch = msg_type == HandshakeType.finished ? 1 : 0;
+ if (epoch != expectedEpoch)
+ {
+ return;
+ }
+
+ int length = TlsUtils.readUint24(buf, off + 1);
+ int fragment_offset = TlsUtils.readUint24(buf, off + 6);
+ if (fragment_offset + fragment_length > length)
+ {
+ return;
+ }
+
+ DTLSReassembler reassembler = (DTLSReassembler)currentInboundFlight.get(Integers.valueOf(seq));
+ if (reassembler != null)
+ {
+ reassembler.contributeFragment(msg_type, length, buf, off + 12, fragment_offset,
+ fragment_length);
+ if (checkAll(currentInboundFlight))
+ {
+ resendOutboundFlight();
+ resetAll(currentInboundFlight);
+ }
+ }
+ }
+ };
+ }
+
+ recordLayer.handshakeSuccessful(retransmit);
+ }
+
+ void resetHandshakeMessagesDigest()
+ {
+ handshakeHash.reset();
+ }
+
+ /**
+ * Check that there are no "extra" messages left in the current inbound flight
+ */
+ private void checkInboundFlight()
+ {
+ Enumeration e = currentInboundFlight.keys();
+ while (e.hasMoreElements())
+ {
+ Integer key = (Integer)e.nextElement();
+ if (key.intValue() >= next_receive_seq)
+ {
+ // TODO Should this be considered an error?
+ }
+ }
+ }
+
+ private void prepareInboundFlight()
+ {
+ resetAll(currentInboundFlight);
+ previousInboundFlight = currentInboundFlight;
+ currentInboundFlight = new Hashtable();
+ }
+
+ private void resendOutboundFlight()
+ throws IOException
+ {
+ recordLayer.resetWriteEpoch();
+ for (int i = 0; i < outboundFlight.size(); ++i)
+ {
+ writeMessage((Message)outboundFlight.elementAt(i));
+ }
+ }
+
+ private Message updateHandshakeMessagesDigest(Message message)
+ throws IOException
+ {
+ if (message.getType() != HandshakeType.hello_request)
+ {
+ byte[] body = message.getBody();
+ byte[] buf = new byte[12];
+ TlsUtils.writeUint8(message.getType(), buf, 0);
+ TlsUtils.writeUint24(body.length, buf, 1);
+ TlsUtils.writeUint16(message.getSeq(), buf, 4);
+ TlsUtils.writeUint24(0, buf, 6);
+ TlsUtils.writeUint24(body.length, buf, 9);
+ handshakeHash.update(buf, 0, buf.length);
+ handshakeHash.update(body, 0, body.length);
+ }
+ return message;
+ }
+
+ private void writeMessage(Message message)
+ throws IOException
+ {
+ int sendLimit = recordLayer.getSendLimit();
+ int fragmentLimit = sendLimit - 12;
+
+ // TODO Support a higher minimum fragment size?
+ if (fragmentLimit < 1)
+ {
+ // TODO Should we be throwing an exception here?
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ int length = message.getBody().length;
+
+ // NOTE: Must still send a fragment if body is empty
+ int fragment_offset = 0;
+ do
+ {
+ int fragment_length = Math.min(length - fragment_offset, fragmentLimit);
+ writeHandshakeFragment(message, fragment_offset, fragment_length);
+ fragment_offset += fragment_length;
+ }
+ while (fragment_offset < length);
+ }
+
+ private void writeHandshakeFragment(Message message, int fragment_offset, int fragment_length)
+ throws IOException
+ {
+ 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)
+ {
+ Enumeration e = inboundFlight.elements();
+ while (e.hasMoreElements())
+ {
+ if (((DTLSReassembler)e.nextElement()).getBodyIfComplete() == null)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static void resetAll(Hashtable inboundFlight)
+ {
+ Enumeration e = inboundFlight.elements();
+ while (e.hasMoreElements())
+ {
+ ((DTLSReassembler)e.nextElement()).reset();
+ }
+ }
+
+ static class Message
+ {
+ private final int message_seq;
+ private final short msg_type;
+ private final byte[] body;
+
+ private Message(int message_seq, short msg_type, byte[] body)
+ {
+ this.message_seq = message_seq;
+ this.msg_type = msg_type;
+ this.body = body;
+ }
+
+ public int getSeq()
+ {
+ return message_seq;
+ }
+
+ public short getType()
+ {
+ return msg_type;
+ }
+
+ public byte[] getBody()
+ {
+ 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/core/src/main/java/org/spongycastle/crypto/tls/DTLSReplayWindow.java b/core/src/main/java/org/spongycastle/crypto/tls/DTLSReplayWindow.java
new file mode 100644
index 00000000..d7db51c3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/DTLSReplayWindow.java
@@ -0,0 +1,90 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 4347 4.1.2.5 Anti-replay
+ * <p/>
+ * Support fast rejection of duplicate records by maintaining a sliding receive window
+ */
+class DTLSReplayWindow
+{
+ private static final long VALID_SEQ_MASK = 0x0000FFFFFFFFFFFFL;
+
+ private static final long WINDOW_SIZE = 64L;
+
+ private long latestConfirmedSeq = -1;
+ private long bitmap = 0;
+
+ /**
+ * Check whether a received record with the given sequence number should be rejected as a duplicate.
+ *
+ * @param seq the 48-bit DTLSPlainText.sequence_number field of a received record.
+ * @return true if the record should be discarded without further processing.
+ */
+ boolean shouldDiscard(long seq)
+ {
+ if ((seq & VALID_SEQ_MASK) != seq)
+ {
+ return true;
+ }
+
+ if (seq <= latestConfirmedSeq)
+ {
+ long diff = latestConfirmedSeq - seq;
+ if (diff >= WINDOW_SIZE)
+ {
+ return true;
+ }
+ if ((bitmap & (1L << diff)) != 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Report that a received record with the given sequence number passed authentication checks.
+ *
+ * @param seq the 48-bit DTLSPlainText.sequence_number field of an authenticated record.
+ */
+ void reportAuthenticated(long seq)
+ {
+ if ((seq & VALID_SEQ_MASK) != seq)
+ {
+ throw new IllegalArgumentException("'seq' out of range");
+ }
+
+ if (seq <= latestConfirmedSeq)
+ {
+ long diff = latestConfirmedSeq - seq;
+ if (diff < WINDOW_SIZE)
+ {
+ bitmap |= (1L << diff);
+ }
+ }
+ else
+ {
+ long diff = seq - latestConfirmedSeq;
+ if (diff >= WINDOW_SIZE)
+ {
+ bitmap = 1;
+ }
+ else
+ {
+ bitmap <<= (int)diff; // for earlier JDKs
+ bitmap |= 1;
+ }
+ latestConfirmedSeq = seq;
+ }
+ }
+
+ /**
+ * When a new epoch begins, sequence numbers begin again at 0
+ */
+ void reset()
+ {
+ latestConfirmedSeq = -1;
+ bitmap = 0;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/DTLSServerProtocol.java b/core/src/main/java/org/spongycastle/crypto/tls/DTLSServerProtocol.java
new file mode 100644
index 00000000..6adb61e5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/DTLSServerProtocol.java
@@ -0,0 +1,667 @@
+package org.spongycastle.crypto.tls;
+
+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.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.util.PublicKeyFactory;
+import org.spongycastle.util.Arrays;
+
+public class DTLSServerProtocol
+ extends DTLSProtocol
+{
+ protected boolean verifyRequests = true;
+
+ public DTLSServerProtocol(SecureRandom secureRandom)
+ {
+ super(secureRandom);
+ }
+
+ public boolean getVerifyRequests()
+ {
+ return verifyRequests;
+ }
+
+ public void setVerifyRequests(boolean verifyRequests)
+ {
+ this.verifyRequests = verifyRequests;
+ }
+
+ public DTLSTransport accept(TlsServer server, DatagramTransport transport)
+ throws IOException
+ {
+ if (server == null)
+ {
+ throw new IllegalArgumentException("'server' cannot be null");
+ }
+ if (transport == null)
+ {
+ throw new IllegalArgumentException("'transport' cannot be null");
+ }
+
+ SecurityParameters securityParameters = new SecurityParameters();
+ securityParameters.entity = ConnectionEnd.server;
+
+ ServerHandshakeState state = new ServerHandshakeState();
+ state.server = server;
+ state.serverContext = new TlsServerContextImpl(secureRandom, securityParameters);
+
+ securityParameters.serverRandom = TlsProtocol.createRandomBlock(server.shouldUseGMTUnixTime(),
+ state.serverContext.getNonceRandomGenerator());
+
+ server.init(state.serverContext);
+
+ DTLSRecordLayer recordLayer = new DTLSRecordLayer(transport, state.serverContext, server, ContentType.handshake);
+
+ // TODO Need to handle sending of HelloVerifyRequest without entering a full connection
+
+ try
+ {
+ return serverHandshake(state, recordLayer);
+ }
+ catch (TlsFatalAlert fatalAlert)
+ {
+ recordLayer.fail(fatalAlert.getAlertDescription());
+ throw fatalAlert;
+ }
+ catch (IOException e)
+ {
+ recordLayer.fail(AlertDescription.internal_error);
+ throw e;
+ }
+ catch (RuntimeException e)
+ {
+ recordLayer.fail(AlertDescription.internal_error);
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ protected DTLSTransport serverHandshake(ServerHandshakeState state, DTLSRecordLayer recordLayer)
+ throws IOException
+ {
+ SecurityParameters securityParameters = state.serverContext.getSecurityParameters();
+ DTLSReliableHandshake handshake = new DTLSReliableHandshake(state.serverContext, recordLayer);
+
+ DTLSReliableHandshake.Message clientMessage = handshake.receiveMessage();
+
+ {
+ // NOTE: After receiving a record from the client, we discover the record layer version
+ ProtocolVersion client_version = recordLayer.getDiscoveredPeerVersion();
+ // TODO Read RFCs for guidance on the expected record layer version number
+ state.serverContext.setClientVersion(client_version);
+ }
+
+ if (clientMessage.getType() == HandshakeType.client_hello)
+ {
+ processClientHello(state, clientMessage.getBody());
+ }
+ else
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ {
+ 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.sendMessage(HandshakeType.server_hello, serverHelloBody);
+ }
+
+ handshake.notifyHelloComplete();
+
+ Vector serverSupplementalData = state.server.getServerSupplementalData();
+ if (serverSupplementalData != null)
+ {
+ byte[] supplementalDataBody = generateSupplementalData(serverSupplementalData);
+ handshake.sendMessage(HandshakeType.supplemental_data, supplementalDataBody);
+ }
+
+ state.keyExchange = state.server.getKeyExchange();
+ state.keyExchange.init(state.serverContext);
+
+ state.serverCredentials = state.server.getCredentials();
+
+ Certificate serverCertificate = null;
+
+ if (state.serverCredentials == null)
+ {
+ state.keyExchange.skipServerCredentials();
+ }
+ else
+ {
+ state.keyExchange.processServerCredentials(state.serverCredentials);
+
+ 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)
+ {
+ handshake.sendMessage(HandshakeType.server_key_exchange, serverKeyExchange);
+ }
+
+ if (state.serverCredentials != null)
+ {
+ state.certificateRequest = state.server.getCertificateRequest();
+ if (state.certificateRequest != null)
+ {
+ state.keyExchange.validateCertificateRequest(state.certificateRequest);
+
+ 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)
+ {
+ processClientSupplementalData(state, clientMessage.getBody());
+ clientMessage = handshake.receiveMessage();
+ }
+ else
+ {
+ state.server.processClientSupplementalData(null);
+ }
+
+ if (state.certificateRequest == null)
+ {
+ state.keyExchange.skipClientCredentials();
+ }
+ else
+ {
+ if (clientMessage.getType() == HandshakeType.certificate)
+ {
+ processClientCertificate(state, clientMessage.getBody());
+ clientMessage = handshake.receiveMessage();
+ }
+ else
+ {
+ if (TlsUtils.isTLSv12(state.serverContext))
+ {
+ /*
+ * RFC 5246 If no suitable certificate is available, the client MUST send a
+ * certificate message containing no certificates.
+ *
+ * NOTE: In previous RFCs, this was SHOULD instead of MUST.
+ */
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ notifyClientCertificate(state, Certificate.EMPTY_CHAIN);
+ }
+ }
+
+ if (clientMessage.getType() == HandshakeType.client_key_exchange)
+ {
+ processClientKeyExchange(state, clientMessage.getBody());
+ }
+ else
+ {
+ 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
+ * parameters).
+ */
+ if (expectCertificateVerifyMessage(state))
+ {
+ byte[] certificateVerifyBody = handshake.receiveMessageBody(HandshakeType.certificate_verify);
+ processCertificateVerify(state, certificateVerifyBody, prepareFinishHash);
+ }
+
+ // NOTE: Calculated exclusive of the actual Finished message from the client
+ 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)
+ {
+ NewSessionTicket newSessionTicket = state.server.getNewSessionTicket();
+ byte[] newSessionTicketBody = generateNewSessionTicket(state, newSessionTicket);
+ handshake.sendMessage(HandshakeType.session_ticket, newSessionTicketBody);
+ }
+
+ // NOTE: Calculated exclusive of the Finished message itself
+ byte[] serverVerifyData = TlsUtils.calculateVerifyData(state.serverContext, ExporterLabel.server_finished,
+ TlsProtocol.getCurrentPRFHash(state.serverContext, handshake.getHandshakeHash(), null));
+ handshake.sendMessage(HandshakeType.finished, serverVerifyData);
+
+ handshake.finish();
+
+ state.server.notifyHandshakeComplete();
+
+ return new DTLSTransport(recordLayer);
+ }
+
+ protected byte[] generateCertificateRequest(ServerHandshakeState state, CertificateRequest certificateRequest)
+ throws IOException
+ {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ certificateRequest.encode(buf);
+ return buf.toByteArray();
+ }
+
+ 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();
+ }
+
+ protected byte[] generateServerHello(ServerHandshakeState state)
+ throws IOException
+ {
+ SecurityParameters securityParameters = state.serverContext.getSecurityParameters();
+
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+
+ ProtocolVersion server_version = state.server.getServerVersion();
+ if (!server_version.isEqualOrEarlierVersionOf(state.serverContext.getClientVersion()))
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ // TODO Read RFCs for guidance on the expected record layer version number
+ // recordStream.setReadVersion(server_version);
+ // recordStream.setWriteVersion(server_version);
+ // recordStream.setRestrictReadVersion(true);
+ state.serverContext.setServerVersion(server_version);
+
+ TlsUtils.writeVersion(state.serverContext.getServerVersion(), buf);
+
+ buf.write(securityParameters.getServerRandom());
+
+ /*
+ * 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);
+
+ state.selectedCipherSuite = state.server.getSelectedCipherSuite();
+ if (!Arrays.contains(state.offeredCipherSuites, state.selectedCipherSuite)
+ || state.selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL
+ || state.selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV
+ || !TlsUtils.isValidCipherSuiteForVersion(state.selectedCipherSuite, server_version))
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ validateSelectedCipherSuite(state.selectedCipherSuite, AlertDescription.internal_error);
+
+ state.selectedCompressionMethod = state.server.getSelectedCompressionMethod();
+ if (!Arrays.contains(state.offeredCompressionMethods, state.selectedCompressionMethod))
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ TlsUtils.writeUint16(state.selectedCipherSuite, buf);
+ TlsUtils.writeUint8(state.selectedCompressionMethod, buf);
+
+ state.serverExtensions = state.server.getServerExtensions();
+
+ /*
+ * RFC 5746 3.6. Server Behavior: Initial Handshake
+ */
+ if (state.secure_renegotiation)
+ {
+ byte[] renegExtData = TlsUtils.getExtensionData(state.serverExtensions, TlsProtocol.EXT_RenegotiationInfo);
+ boolean noRenegExt = (null == renegExtData);
+
+ if (noRenegExt)
+ {
+ /*
+ * Note that sending a "renegotiation_info" extension in response to a ClientHello
+ * containing only the SCSV is an explicit exception to the prohibition in RFC 5246,
+ * Section 7.4.1.4, on the server sending unsolicited extensions and is only allowed
+ * because the client is signaling its willingness to receive the extension via the
+ * TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV.
+ */
+
+ /*
+ * 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));
+ }
+ }
+
+ if (state.serverExtensions != null)
+ {
+ securityParameters.encryptThenMAC = TlsExtensionsUtils.hasEncryptThenMACExtension(state.serverExtensions);
+
+ 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);
+ }
+
+ return buf.toByteArray();
+ }
+
+ protected void notifyClientCertificate(ServerHandshakeState state, Certificate clientCertificate)
+ throws IOException
+ {
+ if (state.certificateRequest == null)
+ {
+ throw new IllegalStateException();
+ }
+
+ if (state.clientCertificate != null)
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ state.clientCertificate = clientCertificate;
+
+ if (clientCertificate.isEmpty())
+ {
+ state.keyExchange.skipClientCredentials();
+ }
+ else
+ {
+
+ /*
+ * TODO RFC 5246 7.4.6. If the certificate_authorities list in the certificate request
+ * message was non-empty, one of the certificates in the certificate chain SHOULD be
+ * issued by one of the listed CAs.
+ */
+
+ state.clientCertificateType = TlsUtils.getClientCertificateType(clientCertificate,
+ state.serverCredentials.getCertificate());
+
+ state.keyExchange.processClientCertificate(clientCertificate);
+ }
+
+ /*
+ * RFC 5246 7.4.6. If the client does not send any certificates, the server MAY at its
+ * discretion either continue the handshake without client authentication, or respond with a
+ * fatal handshake_failure alert. Also, if some aspect of the certificate chain was
+ * unacceptable (e.g., it was not signed by a known, trusted CA), the server MAY at its
+ * discretion either continue the handshake (considering the client unauthenticated) or send
+ * a fatal alert.
+ */
+ state.server.notifyClientCertificate(clientCertificate);
+ }
+
+ protected void processClientCertificate(ServerHandshakeState state, byte[] body)
+ throws IOException
+ {
+ ByteArrayInputStream buf = new ByteArrayInputStream(body);
+
+ Certificate clientCertificate = Certificate.parse(buf);
+
+ TlsProtocol.assertEmpty(buf);
+
+ notifyClientCertificate(state, clientCertificate);
+ }
+
+ protected void processCertificateVerify(ServerHandshakeState state, byte[] body, TlsHandshakeHash prepareFinishHash)
+ throws IOException
+ {
+ ByteArrayInputStream buf = new ByteArrayInputStream(body);
+
+ DigitallySigned clientCertificateVerify = DigitallySigned.parse(state.serverContext, buf);
+
+ TlsProtocol.assertEmpty(buf);
+
+ // Verify the CertificateVerify message contains a correct signature.
+ boolean verified = false;
+ try
+ {
+ byte[] certificateVerifyHash;
+ if (TlsUtils.isTLSv12(state.serverContext))
+ {
+ certificateVerifyHash = prepareFinishHash.getFinalHash(clientCertificateVerify.getAlgorithm().getHash());
+ }
+ else
+ {
+ certificateVerifyHash = TlsProtocol.getCurrentPRFHash(state.serverContext, prepareFinishHash, null);
+ }
+
+ org.spongycastle.asn1.x509.Certificate x509Cert = state.clientCertificate.getCertificateAt(0);
+ SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo();
+ AsymmetricKeyParameter publicKey = PublicKeyFactory.createKey(keyInfo);
+
+ TlsSigner tlsSigner = TlsUtils.createTlsSigner(state.clientCertificateType);
+ tlsSigner.init(state.serverContext);
+ verified = tlsSigner.verifyRawSignature(clientCertificateVerify.getAlgorithm(),
+ clientCertificateVerify.getSignature(), publicKey, certificateVerifyHash);
+ }
+ catch (Exception e)
+ {
+ }
+
+ if (!verified)
+ {
+ throw new TlsFatalAlert(AlertDescription.decrypt_error);
+ }
+ }
+
+ 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
+ ProtocolVersion client_version = TlsUtils.readVersion(buf);
+ if (!client_version.isDTLS())
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ /*
+ * Read the client random
+ */
+ byte[] client_random = TlsUtils.readFully(32, buf);
+
+ byte[] sessionID = TlsUtils.readOpaque8(buf);
+ if (sessionID.length > 32)
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ // TODO RFC 4347 has the cookie length restricted to 32, but not in RFC 6347
+ byte[] cookie = TlsUtils.readOpaque8(buf);
+
+ int cipher_suites_length = TlsUtils.readUint16(buf);
+ if (cipher_suites_length < 2 || (cipher_suites_length & 1) != 0)
+ {
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+
+ /*
+ * 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."
+ */
+ state.offeredCipherSuites = TlsUtils.readUint16Array(cipher_suites_length / 2, buf);
+
+ int compression_methods_length = TlsUtils.readUint8(buf);
+ if (compression_methods_length < 1)
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ state.offeredCompressionMethods = TlsUtils.readUint8Array(compression_methods_length, buf);
+
+ /*
+ * 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.
+ */
+ state.clientExtensions = TlsProtocol.readExtensions(buf);
+
+ state.serverContext.setClientVersion(client_version);
+
+ state.server.notifyClientVersion(client_version);
+
+ state.serverContext.getSecurityParameters().clientRandom = client_random;
+
+ state.server.notifyOfferedCipherSuites(state.offeredCipherSuites);
+ state.server.notifyOfferedCompressionMethods(state.offeredCompressionMethods);
+
+ /*
+ * RFC 5746 3.6. Server Behavior: Initial Handshake
+ */
+ {
+ /*
+ * RFC 5746 3.4. The client MUST include either an empty "renegotiation_info" extension,
+ * or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling cipher suite value in the
+ * ClientHello. Including both is NOT RECOMMENDED.
+ */
+
+ /*
+ * When a ClientHello is received, the server MUST check if it includes the
+ * TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. If it does, set the secure_renegotiation flag
+ * to TRUE.
+ */
+ if (Arrays.contains(state.offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV))
+ {
+ state.secure_renegotiation = true;
+ }
+
+ /*
+ * The server MUST check if the "renegotiation_info" extension is included in the
+ * ClientHello.
+ */
+ byte[] renegExtData = TlsUtils.getExtensionData(state.clientExtensions, TlsProtocol.EXT_RenegotiationInfo);
+ if (renegExtData != 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 (!Arrays.constantTimeAreEqual(renegExtData, TlsProtocol.createRenegotiationInfo(TlsUtils.EMPTY_BYTES)))
+ {
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
+ }
+ }
+ }
+
+ state.server.notifySecureRenegotiation(state.secure_renegotiation);
+
+ if (state.clientExtensions != null)
+ {
+ state.server.processClientExtensions(state.clientExtensions);
+ }
+ }
+
+ protected void processClientKeyExchange(ServerHandshakeState state, byte[] body)
+ throws IOException
+ {
+ ByteArrayInputStream buf = new ByteArrayInputStream(body);
+
+ state.keyExchange.processClientKeyExchange(buf);
+
+ TlsProtocol.assertEmpty(buf);
+ }
+
+ protected void processClientSupplementalData(ServerHandshakeState state, byte[] body)
+ throws IOException
+ {
+ ByteArrayInputStream buf = new ByteArrayInputStream(body);
+ Vector clientSupplementalData = TlsProtocol.readSupplementalDataMessage(buf);
+ state.server.processClientSupplementalData(clientSupplementalData);
+ }
+
+ protected boolean expectCertificateVerifyMessage(ServerHandshakeState state)
+ {
+ return state.clientCertificateType >= 0 && TlsUtils.hasSigningCapability(state.clientCertificateType);
+ }
+
+ protected static class ServerHandshakeState
+ {
+ TlsServer server = null;
+ TlsServerContextImpl serverContext = null;
+ int[] offeredCipherSuites;
+ short[] offeredCompressionMethods;
+ Hashtable clientExtensions;
+ 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;
+ TlsCredentials serverCredentials = null;
+ CertificateRequest certificateRequest = null;
+ short clientCertificateType = -1;
+ Certificate clientCertificate = null;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/DTLSTransport.java b/core/src/main/java/org/spongycastle/crypto/tls/DTLSTransport.java
new file mode 100644
index 00000000..ba6377b1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/DTLSTransport.java
@@ -0,0 +1,80 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+public class DTLSTransport
+ implements DatagramTransport
+{
+ private final DTLSRecordLayer recordLayer;
+
+ DTLSTransport(DTLSRecordLayer recordLayer)
+ {
+ this.recordLayer = recordLayer;
+ }
+
+ public int getReceiveLimit()
+ throws IOException
+ {
+ return recordLayer.getReceiveLimit();
+ }
+
+ public int getSendLimit()
+ throws IOException
+ {
+ return recordLayer.getSendLimit();
+ }
+
+ public int receive(byte[] buf, int off, int len, int waitMillis)
+ throws IOException
+ {
+ try
+ {
+ return recordLayer.receive(buf, off, len, waitMillis);
+ }
+ catch (TlsFatalAlert fatalAlert)
+ {
+ recordLayer.fail(fatalAlert.getAlertDescription());
+ throw fatalAlert;
+ }
+ catch (IOException e)
+ {
+ recordLayer.fail(AlertDescription.internal_error);
+ throw e;
+ }
+ catch (RuntimeException e)
+ {
+ recordLayer.fail(AlertDescription.internal_error);
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public void send(byte[] buf, int off, int len)
+ throws IOException
+ {
+ try
+ {
+ recordLayer.send(buf, off, len);
+ }
+ catch (TlsFatalAlert fatalAlert)
+ {
+ recordLayer.fail(fatalAlert.getAlertDescription());
+ throw fatalAlert;
+ }
+ catch (IOException e)
+ {
+ recordLayer.fail(AlertDescription.internal_error);
+ throw e;
+ }
+ catch (RuntimeException e)
+ {
+ recordLayer.fail(AlertDescription.internal_error);
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public void close()
+ throws IOException
+ {
+ recordLayer.close();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/DatagramTransport.java b/core/src/main/java/org/spongycastle/crypto/tls/DatagramTransport.java
new file mode 100644
index 00000000..9ceac9ef
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/DatagramTransport.java
@@ -0,0 +1,21 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+public interface DatagramTransport
+{
+ int getReceiveLimit()
+ throws IOException;
+
+ int getSendLimit()
+ throws IOException;
+
+ int receive(byte[] buf, int off, int len, int waitMillis)
+ throws IOException;
+
+ void send(byte[] buf, int off, int len)
+ throws IOException;
+
+ void close()
+ throws IOException;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsAgreementCredentials.java b/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsAgreementCredentials.java
new file mode 100644
index 00000000..be981d8a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsAgreementCredentials.java
@@ -0,0 +1,78 @@
+package org.spongycastle.crypto.tls;
+
+import java.math.BigInteger;
+
+import org.spongycastle.crypto.BasicAgreement;
+import org.spongycastle.crypto.agreement.DHBasicAgreement;
+import org.spongycastle.crypto.agreement.ECDHBasicAgreement;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.DHPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.util.BigIntegers;
+
+public class DefaultTlsAgreementCredentials
+ extends AbstractTlsAgreementCredentials
+{
+ protected Certificate certificate;
+ protected AsymmetricKeyParameter privateKey;
+
+ protected BasicAgreement basicAgreement;
+ protected boolean truncateAgreement;
+
+ public DefaultTlsAgreementCredentials(Certificate certificate, AsymmetricKeyParameter privateKey)
+ {
+ if (certificate == null)
+ {
+ throw new IllegalArgumentException("'certificate' cannot be null");
+ }
+ if (certificate.isEmpty())
+ {
+ throw new IllegalArgumentException("'certificate' cannot be empty");
+ }
+ if (privateKey == null)
+ {
+ throw new IllegalArgumentException("'privateKey' cannot be null");
+ }
+ if (!privateKey.isPrivate())
+ {
+ throw new IllegalArgumentException("'privateKey' must be private");
+ }
+
+ if (privateKey instanceof DHPrivateKeyParameters)
+ {
+ basicAgreement = new DHBasicAgreement();
+ truncateAgreement = true;
+ }
+ else if (privateKey instanceof ECPrivateKeyParameters)
+ {
+ basicAgreement = new ECDHBasicAgreement();
+ truncateAgreement = false;
+ }
+ else
+ {
+ throw new IllegalArgumentException("'privateKey' type not supported: "
+ + privateKey.getClass().getName());
+ }
+
+ this.certificate = certificate;
+ this.privateKey = privateKey;
+ }
+
+ public Certificate getCertificate()
+ {
+ return certificate;
+ }
+
+ public byte[] generateAgreement(AsymmetricKeyParameter peerPublicKey)
+ {
+ basicAgreement.init(privateKey);
+ BigInteger agreementValue = basicAgreement.calculateAgreement(peerPublicKey);
+
+ if (truncateAgreement)
+ {
+ return BigIntegers.asUnsignedByteArray(agreementValue);
+ }
+
+ return BigIntegers.asUnsignedByteArray(basicAgreement.getFieldSize(), agreementValue);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsCipherFactory.java b/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsCipherFactory.java
new file mode 100644
index 00000000..9c1c68a4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsCipherFactory.java
@@ -0,0 +1,237 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.StreamCipher;
+import org.spongycastle.crypto.digests.MD5Digest;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.digests.SHA384Digest;
+import org.spongycastle.crypto.digests.SHA512Digest;
+import org.spongycastle.crypto.engines.AESEngine;
+import org.spongycastle.crypto.engines.CamelliaEngine;
+import org.spongycastle.crypto.engines.DESedeEngine;
+import org.spongycastle.crypto.engines.RC4Engine;
+import org.spongycastle.crypto.engines.SEEDEngine;
+import org.spongycastle.crypto.engines.Salsa20Engine;
+import org.spongycastle.crypto.modes.AEADBlockCipher;
+import org.spongycastle.crypto.modes.CBCBlockCipher;
+import org.spongycastle.crypto.modes.CCMBlockCipher;
+import org.spongycastle.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.AEAD_CHACHA20_POLY1305:
+ // NOTE: Ignores macAlgorithm
+ return createChaCha20Poly1305(context);
+ 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);
+ case EncryptionAlgorithm.AES_256_CBC:
+ return createAESCipher(context, 32, macAlgorithm);
+ case EncryptionAlgorithm.AES_256_GCM:
+ // NOTE: Ignores macAlgorithm
+ return createCipher_AES_GCM(context, 32, 16);
+ case EncryptionAlgorithm.CAMELLIA_128_CBC:
+ return createCamelliaCipher(context, 16, macAlgorithm);
+ case EncryptionAlgorithm.CAMELLIA_128_GCM:
+ // NOTE: Ignores macAlgorithm
+ return createCipher_Camellia_GCM(context, 16, 16);
+ case EncryptionAlgorithm.CAMELLIA_256_CBC:
+ return createCamelliaCipher(context, 32, macAlgorithm);
+ case EncryptionAlgorithm.CAMELLIA_256_GCM:
+ // NOTE: Ignores macAlgorithm
+ return createCipher_Camellia_GCM(context, 32, 16);
+ 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:
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ protected TlsBlockCipher createAESCipher(TlsContext context, int cipherKeySize, int macAlgorithm)
+ throws IOException
+ {
+ return new TlsBlockCipher(context, createAESBlockCipher(), createAESBlockCipher(),
+ createHMACDigest(macAlgorithm), createHMACDigest(macAlgorithm), cipherKeySize);
+ }
+
+ protected TlsBlockCipher createCamelliaCipher(TlsContext context, int cipherKeySize, int macAlgorithm)
+ throws IOException
+ {
+ return new TlsBlockCipher(context, createCamelliaBlockCipher(),
+ createCamelliaBlockCipher(), createHMACDigest(macAlgorithm),
+ createHMACDigest(macAlgorithm), cipherKeySize);
+ }
+
+ protected TlsCipher createChaCha20Poly1305(TlsContext context) throws IOException
+ {
+ return new Chacha20Poly1305(context);
+ }
+
+ 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
+ {
+ return new TlsAEADCipher(context, createAEADBlockCipher_AES_GCM(),
+ createAEADBlockCipher_AES_GCM(), cipherKeySize, macSize);
+ }
+
+ protected TlsAEADCipher createCipher_Camellia_GCM(TlsContext context, int cipherKeySize, int macSize)
+ throws IOException
+ {
+ return new TlsAEADCipher(context, createAEADBlockCipher_Camellia_GCM(),
+ createAEADBlockCipher_Camellia_GCM(), cipherKeySize, macSize);
+ }
+
+ 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
+ {
+ return new TlsNullCipher(context, createHMACDigest(macAlgorithm),
+ createHMACDigest(macAlgorithm));
+ }
+
+ protected TlsStreamCipher createRC4Cipher(TlsContext context, int cipherKeySize, int macAlgorithm)
+ throws IOException
+ {
+ return new TlsStreamCipher(context, createRC4StreamCipher(), createRC4StreamCipher(),
+ createHMACDigest(macAlgorithm), createHMACDigest(macAlgorithm), cipherKeySize, false);
+ }
+
+ protected TlsStreamCipher createSalsa20Cipher(TlsContext context, int rounds, int cipherKeySize, int macAlgorithm)
+ throws IOException
+ {
+ return new TlsStreamCipher(context, createSalsa20StreamCipher(rounds), createSalsa20StreamCipher(rounds),
+ createHMACDigest(macAlgorithm), createHMACDigest(macAlgorithm), cipherKeySize, true);
+ }
+
+ protected TlsBlockCipher createSEEDCipher(TlsContext context, int macAlgorithm)
+ throws IOException
+ {
+ return new TlsBlockCipher(context, createSEEDBlockCipher(), createSEEDBlockCipher(),
+ createHMACDigest(macAlgorithm), createHMACDigest(macAlgorithm), 16);
+ }
+
+ protected BlockCipher createAESEngine()
+ {
+ return new AESEngine();
+ }
+
+ protected BlockCipher createCamelliaEngine()
+ {
+ return new CamelliaEngine();
+ }
+
+ protected BlockCipher createAESBlockCipher()
+ {
+ return new CBCBlockCipher(createAESEngine());
+ }
+
+ protected AEADBlockCipher createAEADBlockCipher_AES_CCM()
+ {
+ return new CCMBlockCipher(createAESEngine());
+ }
+
+ protected AEADBlockCipher createAEADBlockCipher_AES_GCM()
+ {
+ // TODO Consider allowing custom configuration of multiplier
+ return new GCMBlockCipher(createAESEngine());
+ }
+
+ protected AEADBlockCipher createAEADBlockCipher_Camellia_GCM()
+ {
+ // TODO Consider allowing custom configuration of multiplier
+ return new GCMBlockCipher(createCamelliaEngine());
+ }
+
+ protected BlockCipher createCamelliaBlockCipher()
+ {
+ return new CBCBlockCipher(createCamelliaEngine());
+ }
+
+ protected BlockCipher createDESedeBlockCipher()
+ {
+ 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
+ {
+ switch (macAlgorithm)
+ {
+ case MACAlgorithm._null:
+ return null;
+ case MACAlgorithm.hmac_md5:
+ return TlsUtils.createHash(HashAlgorithm.md5);
+ case MACAlgorithm.hmac_sha1:
+ return TlsUtils.createHash(HashAlgorithm.sha1);
+ case MACAlgorithm.hmac_sha256:
+ return TlsUtils.createHash(HashAlgorithm.sha256);
+ case MACAlgorithm.hmac_sha384:
+ return TlsUtils.createHash(HashAlgorithm.sha384);
+ case MACAlgorithm.hmac_sha512:
+ return TlsUtils.createHash(HashAlgorithm.sha512);
+ default:
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsClient.java b/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsClient.java
new file mode 100644
index 00000000..0c17b032
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsClient.java
@@ -0,0 +1,453 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+public abstract class DefaultTlsClient
+ extends AbstractTlsClient
+{
+ public DefaultTlsClient()
+ {
+ super();
+ }
+
+ public DefaultTlsClient(TlsCipherFactory cipherFactory)
+ {
+ super(cipherFactory);
+ }
+
+ public int[] getCipherSuites()
+ {
+ 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:
+ case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
+ case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA:
+ return createDHKeyExchange(KeyExchangeAlgorithm.DH_DSS);
+
+ case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
+ 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_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA:
+ return createDHKeyExchange(KeyExchangeAlgorithm.DH_RSA);
+
+ case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
+ 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_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA:
+ return createDHEKeyExchange(KeyExchangeAlgorithm.DHE_DSS);
+
+ 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_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
+ return createDHEKeyExchange(KeyExchangeAlgorithm.DHE_RSA);
+
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
+ return createECDHKeyExchange(KeyExchangeAlgorithm.ECDH_ECDSA);
+
+ case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
+ return createECDHKeyExchange(KeyExchangeAlgorithm.ECDH_RSA);
+
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+ 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_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
+ 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:
+ return createECDHEKeyExchange(KeyExchangeAlgorithm.ECDHE_ECDSA);
+
+ case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+ 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_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ 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:
+ 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_128_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ 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_SEED_CBC_SHA:
+ return createRSAKeyExchange();
+
+ default:
+ /*
+ * Note: internal error here; the TlsProtocol implementation verifies that the
+ * server-selected cipher suite was in the list of client-offered cipher suites, so if
+ * we now can't produce an implementation, we shouldn't have offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public TlsCipher getCipher()
+ throws IOException
+ {
+ switch (selectedCipherSuite)
+ {
+ case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm._3DES_EDE_CBC, MACAlgorithm.hmac_sha1);
+
+ case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AEAD_CHACHA20_POLY1305, MACAlgorithm._null);
+
+ case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_CBC, MACAlgorithm.hmac_sha1);
+
+ 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:
+ 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:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_GCM, MACAlgorithm._null);
+
+ case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_CBC, MACAlgorithm.hmac_sha1);
+
+ 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:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_CBC, MACAlgorithm.hmac_sha256);
+
+ 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:
+ 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:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_GCM, MACAlgorithm._null);
+
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_CBC, MACAlgorithm.hmac_sha1);
+
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_CBC, MACAlgorithm.hmac_sha256);
+
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_GCM, MACAlgorithm._null);
+
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_CBC, MACAlgorithm.hmac_sha1);
+
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_CBC, MACAlgorithm.hmac_sha256);
+
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_GCM, MACAlgorithm._null);
+
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_CBC, MACAlgorithm.hmac_sha384);
+
+ 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_RSA_WITH_NULL_MD5:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.NULL, MACAlgorithm.hmac_md5);
+
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
+ case CipherSuite.TLS_RSA_WITH_NULL_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.NULL, MACAlgorithm.hmac_sha1);
+
+ case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.NULL, MACAlgorithm.hmac_sha256);
+
+ case CipherSuite.TLS_RSA_WITH_RC4_128_MD5:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.RC4_128, MACAlgorithm.hmac_md5);
+
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
+ 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_DH_DSS_WITH_SEED_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.SEED_CBC, MACAlgorithm.hmac_sha1);
+
+ default:
+ /*
+ * Note: internal error here; the TlsProtocol implementation verifies that the
+ * server-selected cipher suite was in the list of client-offered cipher suites, so if
+ * we now can't produce an implementation, we shouldn't have offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ protected TlsKeyExchange createDHKeyExchange(int keyExchange)
+ {
+ return new TlsDHKeyExchange(keyExchange, supportedSignatureAlgorithms, null);
+ }
+
+ protected TlsKeyExchange createDHEKeyExchange(int keyExchange)
+ {
+ return new TlsDHEKeyExchange(keyExchange, supportedSignatureAlgorithms, null);
+ }
+
+ protected TlsKeyExchange createECDHKeyExchange(int keyExchange)
+ {
+ return new TlsECDHKeyExchange(keyExchange, supportedSignatureAlgorithms, namedCurves, clientECPointFormats,
+ serverECPointFormats);
+ }
+
+ protected TlsKeyExchange createECDHEKeyExchange(int keyExchange)
+ {
+ return new TlsECDHEKeyExchange(keyExchange, supportedSignatureAlgorithms, namedCurves, clientECPointFormats,
+ serverECPointFormats);
+ }
+
+ protected TlsKeyExchange createRSAKeyExchange()
+ {
+ return new TlsRSAKeyExchange(supportedSignatureAlgorithms);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsEncryptionCredentials.java b/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsEncryptionCredentials.java
new file mode 100644
index 00000000..53f9315e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsEncryptionCredentials.java
@@ -0,0 +1,62 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.encodings.PKCS1Encoding;
+import org.spongycastle.crypto.engines.RSABlindedEngine;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+
+public class DefaultTlsEncryptionCredentials extends AbstractTlsEncryptionCredentials
+{
+ protected TlsContext context;
+ protected Certificate certificate;
+ protected AsymmetricKeyParameter privateKey;
+
+ public DefaultTlsEncryptionCredentials(TlsContext context, Certificate certificate,
+ AsymmetricKeyParameter privateKey)
+ {
+ if (certificate == null)
+ {
+ throw new IllegalArgumentException("'certificate' cannot be null");
+ }
+ if (certificate.isEmpty())
+ {
+ throw new IllegalArgumentException("'certificate' cannot be empty");
+ }
+ if (privateKey == null)
+ {
+ throw new IllegalArgumentException("'privateKey' cannot be null");
+ }
+ if (!privateKey.isPrivate())
+ {
+ throw new IllegalArgumentException("'privateKey' must be private");
+ }
+
+ if (privateKey instanceof RSAKeyParameters)
+ {
+ }
+ else
+ {
+ throw new IllegalArgumentException("'privateKey' type not supported: "
+ + privateKey.getClass().getName());
+ }
+
+ this.context = context;
+ this.certificate = certificate;
+ this.privateKey = privateKey;
+ }
+
+ public Certificate getCertificate()
+ {
+ return certificate;
+ }
+
+ public byte[] decryptPreMasterSecret(byte[] encryptedPreMasterSecret)
+ throws IOException
+ {
+ return TlsRSAUtils.safeDecryptPreMasterSecret(context, (RSAKeyParameters)privateKey, encryptedPreMasterSecret);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsServer.java b/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsServer.java
new file mode 100644
index 00000000..3a2ac3b2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsServer.java
@@ -0,0 +1,550 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+import org.spongycastle.crypto.agreement.DHStandardGroups;
+import org.spongycastle.crypto.params.DHParameters;
+
+public abstract class DefaultTlsServer
+ extends AbstractTlsServer
+{
+ public DefaultTlsServer()
+ {
+ super();
+ }
+
+ public DefaultTlsServer(TlsCipherFactory cipherFactory)
+ {
+ super(cipherFactory);
+ }
+
+ protected TlsEncryptionCredentials getRSAEncryptionCredentials()
+ throws IOException
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ protected TlsSignerCredentials getRSASignerCredentials()
+ throws IOException
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ protected DHParameters getDHParameters()
+ {
+ return DHStandardGroups.rfc5114_1024_160;
+ }
+
+ protected int[] getCipherSuites()
+ {
+ return new int[]
+ {
+ CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
+ CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+ CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384,
+ CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256,
+ CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256,
+ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256,
+ CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,
+ };
+ }
+
+ 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_128_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ 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_SEED_CBC_SHA:
+ return getRSAEncryptionCredentials();
+
+ 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_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+ 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_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ 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:
+ return getRSASignerCredentials();
+
+ default:
+ /*
+ * Note: internal error here; selected a key exchange we don't implement!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public TlsKeyExchange getKeyExchange()
+ throws IOException
+ {
+ switch (selectedCipherSuite)
+ {
+ case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
+ case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA:
+ return createDHKeyExchange(KeyExchangeAlgorithm.DH_DSS);
+
+ case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
+ 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_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA:
+ return createDHKeyExchange(KeyExchangeAlgorithm.DH_RSA);
+
+ case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
+ 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_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA:
+ return createDHEKeyExchange(KeyExchangeAlgorithm.DHE_DSS);
+
+ 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_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
+ return createDHEKeyExchange(KeyExchangeAlgorithm.DHE_RSA);
+
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
+ return createECDHKeyExchange(KeyExchangeAlgorithm.ECDH_ECDSA);
+
+ case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
+ return createECDHKeyExchange(KeyExchangeAlgorithm.ECDH_RSA);
+
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+ 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_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
+ 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:
+ return createECDHEKeyExchange(KeyExchangeAlgorithm.ECDHE_ECDSA);
+
+ case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+ 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_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ 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:
+ 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_128_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ 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_SEED_CBC_SHA:
+ return createRSAKeyExchange();
+
+ default:
+ /*
+ * Note: internal error here; selected a key exchange we don't implement!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public TlsCipher getCipher()
+ throws IOException
+ {
+ switch (selectedCipherSuite)
+ {
+ case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm._3DES_EDE_CBC, MACAlgorithm.hmac_sha1);
+
+ case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AEAD_CHACHA20_POLY1305, MACAlgorithm._null);
+
+ case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_CBC, MACAlgorithm.hmac_sha1);
+
+ 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:
+ 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:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_GCM, MACAlgorithm._null);
+
+ case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_CBC, MACAlgorithm.hmac_sha1);
+
+ 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:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_CBC, MACAlgorithm.hmac_sha256);
+
+ 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:
+ 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:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_GCM, MACAlgorithm._null);
+
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_CBC, MACAlgorithm.hmac_sha1);
+
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_CBC, MACAlgorithm.hmac_sha256);
+
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_GCM, MACAlgorithm._null);
+
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_CBC, MACAlgorithm.hmac_sha1);
+
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_CBC, MACAlgorithm.hmac_sha256);
+
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_GCM, MACAlgorithm._null);
+
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_CBC, MACAlgorithm.hmac_sha384);
+
+ 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_RSA_WITH_NULL_MD5:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.NULL, MACAlgorithm.hmac_md5);
+
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
+ case CipherSuite.TLS_RSA_WITH_NULL_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.NULL, MACAlgorithm.hmac_sha1);
+
+ case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.NULL, MACAlgorithm.hmac_sha256);
+
+ case CipherSuite.TLS_RSA_WITH_RC4_128_MD5:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.RC4_128, MACAlgorithm.hmac_md5);
+
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
+ 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_DH_DSS_WITH_SEED_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.SEED_CBC, MACAlgorithm.hmac_sha1);
+
+ default:
+ /*
+ * Note: internal error here; selected a cipher suite we don't implement!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ protected TlsKeyExchange createDHKeyExchange(int keyExchange)
+ {
+ return new TlsDHKeyExchange(keyExchange, supportedSignatureAlgorithms, getDHParameters());
+ }
+
+ protected TlsKeyExchange createDHEKeyExchange(int keyExchange)
+ {
+ return new TlsDHEKeyExchange(keyExchange, supportedSignatureAlgorithms, getDHParameters());
+ }
+
+ protected TlsKeyExchange createECDHKeyExchange(int keyExchange)
+ {
+ return new TlsECDHKeyExchange(keyExchange, supportedSignatureAlgorithms, namedCurves, clientECPointFormats,
+ serverECPointFormats);
+ }
+
+ protected TlsKeyExchange createECDHEKeyExchange(int keyExchange)
+ {
+ return new TlsECDHEKeyExchange(keyExchange, supportedSignatureAlgorithms, namedCurves, clientECPointFormats,
+ serverECPointFormats);
+ }
+
+ protected TlsKeyExchange createRSAKeyExchange()
+ {
+ return new TlsRSAKeyExchange(supportedSignatureAlgorithms);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsSignerCredentials.java b/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsSignerCredentials.java
new file mode 100755
index 00000000..51ac6e88
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsSignerCredentials.java
@@ -0,0 +1,104 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.DSAPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+
+public class DefaultTlsSignerCredentials
+ 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");
+ }
+ if (certificate.isEmpty())
+ {
+ throw new IllegalArgumentException("'certificate' cannot be empty");
+ }
+ if (privateKey == null)
+ {
+ throw new IllegalArgumentException("'privateKey' cannot be null");
+ }
+ if (!privateKey.isPrivate())
+ {
+ 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)
+ {
+ this.signer = new TlsRSASigner();
+ }
+ else if (privateKey instanceof DSAPrivateKeyParameters)
+ {
+ this.signer = new TlsDSSSigner();
+ }
+ else if (privateKey instanceof ECPrivateKeyParameters)
+ {
+ this.signer = new TlsECDSASigner();
+ }
+ else
+ {
+ throw new IllegalArgumentException("'privateKey' type not supported: " + privateKey.getClass().getName());
+ }
+
+ this.signer.init(context);
+
+ this.context = context;
+ this.certificate = certificate;
+ this.privateKey = privateKey;
+ this.signatureAndHashAlgorithm = signatureAndHashAlgorithm;
+ }
+
+ public Certificate getCertificate()
+ {
+ return certificate;
+ }
+
+ public byte[] generateCertificateSignature(byte[] hash)
+ throws IOException
+ {
+ try
+ {
+ 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/core/src/main/java/org/spongycastle/crypto/tls/DeferredHash.java b/core/src/main/java/org/spongycastle/crypto/tls/DeferredHash.java
new file mode 100644
index 00000000..9ac7d346
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/DeferredHash.java
@@ -0,0 +1,207 @@
+package org.spongycastle.crypto.tls;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.util.Shorts;
+
+/**
+ * Buffers input until the hash algorithm is determined.
+ */
+class DeferredHash
+ implements TlsHandshakeHash
+{
+ protected static final int BUFFERING_HASH_LIMIT = 4;
+
+ protected TlsContext context;
+
+ private DigestInputBuffer buf;
+ private Hashtable hashes;
+ private Short prfHashAlgorithm;
+
+ DeferredHash()
+ {
+ this.buf = new DigestInputBuffer();
+ this.hashes = new Hashtable();
+ this.prfHashAlgorithm = null;
+ }
+
+ private DeferredHash(Short prfHashAlgorithm, Digest prfHash)
+ {
+ this.buf = null;
+ this.hashes = new Hashtable();
+ this.prfHashAlgorithm = prfHashAlgorithm;
+ hashes.put(prfHashAlgorithm, prfHash);
+ }
+
+ public void init(TlsContext context)
+ {
+ this.context = context;
+ }
+
+ 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();
+ }
+
+ this.prfHashAlgorithm = Shorts.valueOf(TlsUtils.getHashAlgorithmForPRFAlgorithm(prfAlgorithm));
+
+ checkTrackingHash(prfHashAlgorithm);
+
+ return this;
+ }
+
+ public void trackHashAlgorithm(short hashAlgorithm)
+ {
+ if (buf == null)
+ {
+ throw new IllegalStateException("Too late to track more hash algorithms");
+ }
+
+ checkTrackingHash(Shorts.valueOf(hashAlgorithm));
+ }
+
+ public void sealHashAlgorithms()
+ {
+ checkStopBuffering();
+ }
+
+ public TlsHandshakeHash stopTracking()
+ {
+ 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()
+ {
+ throw new IllegalStateException("Use fork() to get a definite Digest");
+ }
+
+ public int getDigestSize()
+ {
+ throw new IllegalStateException("Use fork() to get a definite Digest");
+ }
+
+ public void update(byte input)
+ {
+ if (buf != null)
+ {
+ buf.write(input);
+ return;
+ }
+
+ 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 (buf != null)
+ {
+ buf.write(input, inOff, len);
+ return;
+ }
+
+ Enumeration e = hashes.elements();
+ while (e.hasMoreElements())
+ {
+ Digest hash = (Digest)e.nextElement();
+ hash.update(input, inOff, len);
+ }
+ }
+
+ public int doFinal(byte[] output, int outOff)
+ {
+ throw new IllegalStateException("Use fork() to get a definite Digest");
+ }
+
+ public void reset()
+ {
+ if (buf != null)
+ {
+ buf.reset();
+ return;
+ }
+
+ Enumeration e = hashes.elements();
+ while (e.hasMoreElements())
+ {
+ Digest hash = (Digest)e.nextElement();
+ hash.reset();
+ }
+ }
+
+ 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 (!hashes.containsKey(hashAlgorithm))
+ {
+ Digest hash = TlsUtils.createHash(hashAlgorithm.shortValue());
+ hashes.put(hashAlgorithm, hash);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/DigestAlgorithm.java b/core/src/main/java/org/spongycastle/crypto/tls/DigestAlgorithm.java
new file mode 100644
index 00000000..a1459553
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/DigestAlgorithm.java
@@ -0,0 +1,23 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 2246
+ * <p>
+ * Note that the values here are implementation-specific and arbitrary. It is recommended not to
+ * depend on the particular values (e.g. serialization).
+ *
+ * @deprecated use MACAlgorithm constants instead
+ */
+public class DigestAlgorithm
+{
+ public static final int NULL = 0;
+ public static final int MD5 = 1;
+ public static final int SHA = 2;
+
+ /*
+ * RFC 5246
+ */
+ public static final int SHA256 = 3;
+ public static final int SHA384 = 4;
+ public static final int SHA512 = 5;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/DigestInputBuffer.java b/core/src/main/java/org/spongycastle/crypto/tls/DigestInputBuffer.java
new file mode 100644
index 00000000..a8f6594e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/DigestInputBuffer.java
@@ -0,0 +1,13 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.ByteArrayOutputStream;
+
+import org.spongycastle.crypto.Digest;
+
+class DigestInputBuffer extends ByteArrayOutputStream
+{
+ void updateDigest(Digest d)
+ {
+ d.update(this.buf, 0, count);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/DigitallySigned.java b/core/src/main/java/org/spongycastle/crypto/tls/DigitallySigned.java
new file mode 100644
index 00000000..8ab8a8d4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/DigitallySigned.java
@@ -0,0 +1,72 @@
+package org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/tls/ECBasisType.java b/core/src/main/java/org/spongycastle/crypto/tls/ECBasisType.java
new file mode 100644
index 00000000..3a8d6a57
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/ECBasisType.java
@@ -0,0 +1,15 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 4492 5.4. (Errata ID: 2389)
+ */
+public class ECBasisType
+{
+ public static final short ec_basis_trinomial = 1;
+ public static final short ec_basis_pentanomial = 2;
+
+ public static boolean isValid(short ecBasisType)
+ {
+ return ecBasisType >= ec_basis_trinomial && ecBasisType <= ec_basis_pentanomial;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/ECCurveType.java b/core/src/main/java/org/spongycastle/crypto/tls/ECCurveType.java
new file mode 100644
index 00000000..01266b08
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/ECCurveType.java
@@ -0,0 +1,28 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 4492 5.4
+ */
+public class ECCurveType
+{
+ /**
+ * Indicates the elliptic curve domain parameters are conveyed verbosely, and the
+ * underlying finite field is a prime field.
+ */
+ public static final short explicit_prime = 1;
+
+ /**
+ * Indicates the elliptic curve domain parameters are conveyed verbosely, and the
+ * underlying finite field is a characteristic-2 field.
+ */
+ public static final short explicit_char2 = 2;
+
+ /**
+ * Indicates that a named curve is used. This option SHOULD be used when applicable.
+ */
+ public static final short named_curve = 3;
+
+ /*
+ * Values 248 through 255 are reserved for private use.
+ */
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/ECPointFormat.java b/core/src/main/java/org/spongycastle/crypto/tls/ECPointFormat.java
new file mode 100644
index 00000000..794bc757
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/ECPointFormat.java
@@ -0,0 +1,15 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 4492 5.1.2
+ */
+public class ECPointFormat
+{
+ public static final short uncompressed = 0;
+ public static final short ansiX962_compressed_prime = 1;
+ public static final short ansiX962_compressed_char2 = 2;
+
+ /*
+ * reserved (248..255)
+ */
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/EncryptionAlgorithm.java b/core/src/main/java/org/spongycastle/crypto/tls/EncryptionAlgorithm.java
new file mode 100644
index 00000000..9fcc7299
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/EncryptionAlgorithm.java
@@ -0,0 +1,67 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 2246
+ * <p>
+ * Note that the values here are implementation-specific and arbitrary. It is recommended not to
+ * depend on the particular values (e.g. serialization).
+ */
+public class EncryptionAlgorithm
+{
+ public static final int NULL = 0;
+ public static final int RC4_40 = 1;
+ public static final int RC4_128 = 2;
+ public static final int RC2_CBC_40 = 3;
+ public static final int IDEA_CBC = 4;
+ public static final int DES40_CBC = 5;
+ public static final int DES_CBC = 6;
+ public static final int _3DES_EDE_CBC = 7;
+
+ /*
+ * RFC 3268
+ */
+ public static final int AES_128_CBC = 8;
+ 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 5932
+ */
+ public static final int CAMELLIA_128_CBC = 12;
+ public static final int CAMELLIA_256_CBC = 13;
+
+ /*
+ * RFC 4162
+ */
+ public static final int SEED_CBC = 14;
+
+ /*
+ * RFC 6655
+ */
+ 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;
+
+ /*
+ * RFC 6367
+ */
+ public static final int CAMELLIA_128_GCM = 19;
+ public static final int CAMELLIA_256_GCM = 20;
+
+ /*
+ * draft-josefsson-salsa20-tls-04
+ */
+ public static final int ESTREAM_SALSA20 = 100;
+ public static final int SALSA20 = 101;
+
+ /*
+ * draft-agl-tls-chacha20poly1305-04
+ */
+ public static final int AEAD_CHACHA20_POLY1305 = 102;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/ExporterLabel.java b/core/src/main/java/org/spongycastle/crypto/tls/ExporterLabel.java
new file mode 100644
index 00000000..419680a8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/ExporterLabel.java
@@ -0,0 +1,31 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 5705
+ */
+public class ExporterLabel
+{
+ /*
+ * RFC 5246
+ */
+ public static final String client_finished = "client finished";
+ public static final String server_finished = "server finished";
+ public static final String master_secret = "master secret";
+ public static final String key_expansion = "key expansion";
+
+ /*
+ * RFC 5216
+ */
+ public static final String client_EAP_encryption = "client EAP encryption";
+
+ /*
+ * RFC 5281
+ */
+ public static final String ttls_keying_material = "ttls keying material";
+ public static final String ttls_challenge = "ttls challenge";
+
+ /*
+ * RFC 5764
+ */
+ public static final String dtls_srtp = "EXTRACTOR-dtls_srtp";
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/ExtensionType.java b/core/src/main/java/org/spongycastle/crypto/tls/ExtensionType.java
new file mode 100644
index 00000000..9047d1db
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/ExtensionType.java
@@ -0,0 +1,60 @@
+package org.spongycastle.crypto.tls;
+
+public class ExtensionType
+{
+ /*
+ * RFC 2546 2.3.
+ */
+ public static final int server_name = 0;
+ public static final int max_fragment_length = 1;
+ public static final int client_certificate_url = 2;
+ public static final int trusted_ca_keys = 3;
+ public static final int truncated_hmac = 4;
+ public static final int status_request = 5;
+
+ /*
+ * RFC 4681
+ */
+ public static final int user_mapping = 6;
+
+ /*
+ * RFC 4492 5.1.
+ */
+ public static final int elliptic_curves = 10;
+ public static final int ec_point_formats = 11;
+
+ /*
+ * RFC 5054 2.8.1.
+ */
+ public static final int srp = 12;
+
+ /*
+ * RFC 5246 7.4.1.4.
+ */
+ public static final int signature_algorithms = 13;
+
+ /*
+ * RFC 5764 9.
+ */
+ public static final int use_srtp = 14;
+
+ /*
+ * RFC 6520 6.
+ */
+ public static final int heartbeat = 15;
+
+ /*
+ * RFC 5077 7.
+ */
+ public static final int session_ticket = 35;
+
+ /*
+ * draft-ietf-tls-encrypt-then-mac-03
+ */
+ public static final int encrypt_then_mac = 22;
+
+ /*
+ * RFC 5746 3.2.
+ */
+ public static final int renegotiation_info = 0xff01;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/HandshakeType.java b/core/src/main/java/org/spongycastle/crypto/tls/HandshakeType.java
new file mode 100644
index 00000000..f03135f1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/HandshakeType.java
@@ -0,0 +1,39 @@
+package org.spongycastle.crypto.tls;
+
+public class HandshakeType
+{
+ /*
+ * RFC 2246 7.4
+ */
+ public static final short hello_request = 0;
+ public static final short client_hello = 1;
+ public static final short server_hello = 2;
+ public static final short certificate = 11;
+ public static final short server_key_exchange = 12;
+ public static final short certificate_request = 13;
+ public static final short server_hello_done = 14;
+ public static final short certificate_verify = 15;
+ public static final short client_key_exchange = 16;
+ 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;
+
+ /*
+ * RFC 4680
+ */
+ public static final short supplemental_data = 23;
+
+ /*
+ * RFC 5077
+ */
+ public static final short session_ticket = 4;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/HashAlgorithm.java b/core/src/main/java/org/spongycastle/crypto/tls/HashAlgorithm.java
new file mode 100644
index 00000000..0e32be9c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/HashAlgorithm.java
@@ -0,0 +1,15 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 5246 7.4.1.4.1
+ */
+public class HashAlgorithm
+{
+ public static final short none = 0;
+ public static final short md5 = 1;
+ public static final short sha1 = 2;
+ public static final short sha224 = 3;
+ public static final short sha256 = 4;
+ public static final short sha384 = 5;
+ public static final short sha512 = 6;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/HeartbeatExtension.java b/core/src/main/java/org/spongycastle/crypto/tls/HeartbeatExtension.java
new file mode 100644
index 00000000..4c325014
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/HeartbeatExtension.java
@@ -0,0 +1,56 @@
+package org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/tls/HeartbeatMessage.java b/core/src/main/java/org/spongycastle/crypto/tls/HeartbeatMessage.java
new file mode 100644
index 00000000..e09005b0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/HeartbeatMessage.java
@@ -0,0 +1,111 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.spongycastle.util.Arrays;
+import org.spongycastle.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.getNonceRandomGenerator().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;
+
+ /*
+ * RFC 6520 4. The padding of a received HeartbeatMessage message MUST be ignored
+ */
+ 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/core/src/main/java/org/spongycastle/crypto/tls/HeartbeatMessageType.java b/core/src/main/java/org/spongycastle/crypto/tls/HeartbeatMessageType.java
new file mode 100644
index 00000000..2d21a1e8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/HeartbeatMessageType.java
@@ -0,0 +1,15 @@
+package org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/tls/HeartbeatMode.java b/core/src/main/java/org/spongycastle/crypto/tls/HeartbeatMode.java
new file mode 100644
index 00000000..1c9472b2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/HeartbeatMode.java
@@ -0,0 +1,15 @@
+package org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/tls/KeyExchangeAlgorithm.java b/core/src/main/java/org/spongycastle/crypto/tls/KeyExchangeAlgorithm.java
new file mode 100644
index 00000000..86834461
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/KeyExchangeAlgorithm.java
@@ -0,0 +1,52 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 2246
+ * <p>
+ * Note that the values here are implementation-specific and arbitrary. It is recommended not to
+ * depend on the particular values (e.g. serialization).
+ */
+public class KeyExchangeAlgorithm
+{
+ public static final int NULL = 0;
+ public static final int RSA = 1;
+ public static final int RSA_EXPORT = 2;
+ public static final int DHE_DSS = 3;
+ public static final int DHE_DSS_EXPORT = 4;
+ public static final int DHE_RSA = 5;
+ public static final int DHE_RSA_EXPORT = 6;
+ public static final int DH_DSS = 7;
+ public static final int DH_DSS_EXPORT = 8;
+ public static final int DH_RSA = 9;
+ public static final int DH_RSA_EXPORT = 10;
+ public static final int DH_anon = 11;
+ public static final int DH_anon_EXPORT = 12;
+
+ /*
+ * RFC 4279
+ */
+ public static final int PSK = 13;
+ public static final int DHE_PSK = 14;
+ public static final int RSA_PSK = 15;
+
+ /*
+ * RFC 4429
+ */
+ public static final int ECDH_ECDSA = 16;
+ public static final int ECDHE_ECDSA = 17;
+ public static final int ECDH_RSA = 18;
+ public static final int ECDHE_RSA = 19;
+ public static final int ECDH_anon = 20;
+
+ /*
+ * RFC 5054
+ */
+ 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/core/src/main/java/org/spongycastle/crypto/tls/LegacyTlsAuthentication.java b/core/src/main/java/org/spongycastle/crypto/tls/LegacyTlsAuthentication.java
new file mode 100644
index 00000000..5e8a67ee
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/LegacyTlsAuthentication.java
@@ -0,0 +1,28 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+/**
+ * A temporary class to wrap old CertificateVerifyer stuff for new TlsAuthentication
+ *
+ * @deprecated
+ */
+public class LegacyTlsAuthentication
+ extends ServerOnlyTlsAuthentication
+{
+ protected CertificateVerifyer verifyer;
+
+ public LegacyTlsAuthentication(CertificateVerifyer verifyer)
+ {
+ this.verifyer = verifyer;
+ }
+
+ public void notifyServerCertificate(Certificate serverCertificate)
+ throws IOException
+ {
+ if (!this.verifyer.isValid(serverCertificate.getCertificateList()))
+ {
+ throw new TlsFatalAlert(AlertDescription.user_canceled);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/LegacyTlsClient.java b/core/src/main/java/org/spongycastle/crypto/tls/LegacyTlsClient.java
new file mode 100644
index 00000000..32384ff9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/LegacyTlsClient.java
@@ -0,0 +1,33 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+/**
+ * A temporary class to use LegacyTlsAuthentication
+ *
+ * @deprecated
+ */
+public class LegacyTlsClient
+ extends DefaultTlsClient
+{
+ /**
+ * @deprecated
+ */
+ protected CertificateVerifyer verifyer;
+
+ /**
+ * @deprecated
+ */
+ public LegacyTlsClient(CertificateVerifyer verifyer)
+ {
+ super();
+
+ this.verifyer = verifyer;
+ }
+
+ public TlsAuthentication getAuthentication()
+ throws IOException
+ {
+ return new LegacyTlsAuthentication(verifyer);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/MACAlgorithm.java b/core/src/main/java/org/spongycastle/crypto/tls/MACAlgorithm.java
new file mode 100644
index 00000000..5b522b6c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/MACAlgorithm.java
@@ -0,0 +1,23 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 2246
+ * <p>
+ * Note that the values here are implementation-specific and arbitrary. It is recommended not to
+ * depend on the particular values (e.g. serialization).
+ */
+public class MACAlgorithm
+{
+ public static final int _null = 0;
+ public static final int md5 = 1;
+ public static final int sha = 2;
+
+ /*
+ * RFC 5246
+ */
+ public static final int hmac_md5 = md5;
+ public static final int hmac_sha1 = sha;
+ public static final int hmac_sha256 = 3;
+ public static final int hmac_sha384 = 4;
+ public static final int hmac_sha512 = 5;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/MaxFragmentLength.java b/core/src/main/java/org/spongycastle/crypto/tls/MaxFragmentLength.java
new file mode 100644
index 00000000..6d864114
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/MaxFragmentLength.java
@@ -0,0 +1,17 @@
+package org.spongycastle.crypto.tls;
+
+public class MaxFragmentLength
+{
+ /*
+ * RFC 3546 3.2.
+ */
+ public static final short pow2_9 = 1;
+ public static final short pow2_10 = 2;
+ public static final short pow2_11 = 3;
+ public static final short pow2_12 = 4;
+
+ public static boolean isValid(short maxFragmentLength)
+ {
+ return maxFragmentLength >= pow2_9 && maxFragmentLength <= pow2_12;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/NameType.java b/core/src/main/java/org/spongycastle/crypto/tls/NameType.java
new file mode 100644
index 00000000..86ca0ef0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/NameType.java
@@ -0,0 +1,9 @@
+package org.spongycastle.crypto.tls;
+
+public class NameType
+{
+ /*
+ * RFC 3546 3.1.
+ */
+ public static final short host_name = 0;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/NamedCurve.java b/core/src/main/java/org/spongycastle/crypto/tls/NamedCurve.java
new file mode 100644
index 00000000..8f733587
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/NamedCurve.java
@@ -0,0 +1,71 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 4492 5.1.1
+ * <p>
+ * The named curves defined here are those specified in SEC 2 [13]. Note that many of these curves
+ * are also recommended in ANSI X9.62 [7] and FIPS 186-2 [11]. Values 0xFE00 through 0xFEFF are
+ * reserved for private use. Values 0xFF01 and 0xFF02 indicate that the client supports arbitrary
+ * prime and characteristic-2 curves, respectively (the curve parameters must be encoded explicitly
+ * in ECParameters).
+ */
+public class NamedCurve
+{
+ public static final int sect163k1 = 1;
+ public static final int sect163r1 = 2;
+ public static final int sect163r2 = 3;
+ public static final int sect193r1 = 4;
+ public static final int sect193r2 = 5;
+ public static final int sect233k1 = 6;
+ public static final int sect233r1 = 7;
+ public static final int sect239k1 = 8;
+ public static final int sect283k1 = 9;
+ public static final int sect283r1 = 10;
+ public static final int sect409k1 = 11;
+ public static final int sect409r1 = 12;
+ public static final int sect571k1 = 13;
+ public static final int sect571r1 = 14;
+ public static final int secp160k1 = 15;
+ public static final int secp160r1 = 16;
+ public static final int secp160r2 = 17;
+ public static final int secp192k1 = 18;
+ public static final int secp192r1 = 19;
+ public static final int secp224k1 = 20;
+ public static final int secp224r1 = 21;
+ public static final int secp256k1 = 22;
+ 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)
+ */
+
+ public static final int arbitrary_explicit_prime_curves = 0xFF01;
+ public static final int arbitrary_explicit_char2_curves = 0xFF02;
+
+ public static boolean isValid(int namedCurve)
+ {
+ return (namedCurve >= sect163k1 && namedCurve <= brainpoolP512r1)
+ || (namedCurve >= arbitrary_explicit_prime_curves && namedCurve <= arbitrary_explicit_char2_curves);
+ }
+
+ public static boolean refersToASpecificNamedCurve(int namedCurve)
+ {
+ switch (namedCurve)
+ {
+ case arbitrary_explicit_prime_curves:
+ case arbitrary_explicit_char2_curves:
+ return false;
+ default:
+ return true;
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/NewSessionTicket.java b/core/src/main/java/org/spongycastle/crypto/tls/NewSessionTicket.java
new file mode 100644
index 00000000..d9d67c28
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/NewSessionTicket.java
@@ -0,0 +1,55 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class NewSessionTicket
+{
+ protected long ticketLifetimeHint;
+ protected byte[] ticket;
+
+ public NewSessionTicket(long ticketLifetimeHint, byte[] ticket)
+ {
+ this.ticketLifetimeHint = ticketLifetimeHint;
+ this.ticket = ticket;
+ }
+
+ public long getTicketLifetimeHint()
+ {
+ return ticketLifetimeHint;
+ }
+
+ public byte[] getTicket()
+ {
+ 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
+ {
+ TlsUtils.writeUint32(ticketLifetimeHint, output);
+ 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
+ {
+ long ticketLifetimeHint = TlsUtils.readUint32(input);
+ byte[] ticket = TlsUtils.readOpaque16(input);
+ return new NewSessionTicket(ticketLifetimeHint, ticket);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/OCSPStatusRequest.java b/core/src/main/java/org/spongycastle/crypto/tls/OCSPStatusRequest.java
new file mode 100644
index 00000000..25c45deb
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/OCSPStatusRequest.java
@@ -0,0 +1,131 @@
+package org.spongycastle.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.spongycastle.asn1.ASN1Encoding;
+import org.spongycastle.asn1.ocsp.ResponderID;
+import org.spongycastle.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 an {@link OCSPStatusRequest} from an {@link InputStream}.
+ *
+ * @param input
+ * the {@link InputStream} to parse from.
+ * @return an {@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/core/src/main/java/org/spongycastle/crypto/tls/PRFAlgorithm.java b/core/src/main/java/org/spongycastle/crypto/tls/PRFAlgorithm.java
new file mode 100644
index 00000000..63da881e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/PRFAlgorithm.java
@@ -0,0 +1,22 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 5246
+ * <p>
+ * Note that the values here are implementation-specific and arbitrary. It is recommended not to
+ * depend on the particular values (e.g. serialization).
+ */
+public class PRFAlgorithm
+{
+ /*
+ * Placeholder to refer to the legacy TLS algorithm
+ */
+ public static final int tls_prf_legacy = 0;
+
+ public static final int tls_prf_sha256 = 1;
+
+ /*
+ * Implied by RFC 5288
+ */
+ public static final int tls_prf_sha384 = 2;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/PSKTlsClient.java b/core/src/main/java/org/spongycastle/crypto/tls/PSKTlsClient.java
new file mode 100644
index 00000000..318535e1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/PSKTlsClient.java
@@ -0,0 +1,256 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+public abstract class PSKTlsClient
+ extends AbstractTlsClient
+{
+ protected TlsPSKIdentity pskIdentity;
+
+ public PSKTlsClient(TlsPSKIdentity pskIdentity)
+ {
+ super();
+ this.pskIdentity = pskIdentity;
+ }
+
+ public PSKTlsClient(TlsCipherFactory cipherFactory, TlsPSKIdentity pskIdentity)
+ {
+ super(cipherFactory);
+ this.pskIdentity = pskIdentity;
+ }
+
+ public int[] getCipherSuites()
+ {
+ 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
+ {
+ 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_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ 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_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_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ 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:
+ 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_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ 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:
+ 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_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ 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:
+ return createPSKKeyExchange(KeyExchangeAlgorithm.RSA_PSK);
+
+ default:
+ /*
+ * Note: internal error here; the TlsProtocol implementation verifies that the
+ * server-selected cipher suite was in the list of client-offered cipher suites, so if
+ * we now can't produce an implementation, we shouldn't have offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ 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:
+ 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:
+ 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:
+ 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_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_CBC, MACAlgorithm.hmac_sha256);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_GCM, MACAlgorithm._null);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_CBC, MACAlgorithm.hmac_sha384);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_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_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:
+ 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:
+ 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);
+
+ default:
+ /*
+ * Note: internal error here; the TlsProtocol implementation verifies that the
+ * server-selected cipher suite was in the list of client-offered cipher suites, so if
+ * we now can't produce an implementation, we shouldn't have offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ protected TlsKeyExchange createPSKKeyExchange(int keyExchange)
+ {
+ return new TlsPSKKeyExchange(keyExchange, supportedSignatureAlgorithms, pskIdentity, null, namedCurves,
+ clientECPointFormats, serverECPointFormats);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/ProtocolVersion.java b/core/src/main/java/org/spongycastle/crypto/tls/ProtocolVersion.java
new file mode 100644
index 00000000..2bd9a0a8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/ProtocolVersion.java
@@ -0,0 +1,158 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+import org.spongycastle.util.Strings;
+
+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");
+ public static final ProtocolVersion TLSv12 = new ProtocolVersion(0x0303, "TLS 1.2");
+ public static final ProtocolVersion DTLSv10 = new ProtocolVersion(0xFEFF, "DTLS 1.0");
+ public static final ProtocolVersion DTLSv12 = new ProtocolVersion(0xFEFD, "DTLS 1.2");
+
+ private int version;
+ private String name;
+
+ private ProtocolVersion(int v, String name)
+ {
+ this.version = v & 0xffff;
+ this.name = name;
+ }
+
+ public int getFullVersion()
+ {
+ return version;
+ }
+
+ public int getMajorVersion()
+ {
+ return version >> 8;
+ }
+
+ public int getMinorVersion()
+ {
+ return version & 0xff;
+ }
+
+ public boolean isDTLS()
+ {
+ return getMajorVersion() == 0xFE;
+ }
+
+ public boolean isSSL()
+ {
+ return this == SSLv3;
+ }
+
+ public boolean isTLS()
+ {
+ return getMajorVersion() == 0x03;
+ }
+
+ public ProtocolVersion getEquivalentTLSVersion()
+ {
+ if (!isDTLS())
+ {
+ return this;
+ }
+ if (this == DTLSv10)
+ {
+ return TLSv11;
+ }
+ return TLSv12;
+ }
+
+ public boolean isEqualOrEarlierVersionOf(ProtocolVersion version)
+ {
+ if (getMajorVersion() != version.getMajorVersion())
+ {
+ return false;
+ }
+ int diffMinorVersion = version.getMinorVersion() - getMinorVersion();
+ return isDTLS() ? diffMinorVersion <= 0 : diffMinorVersion >= 0;
+ }
+
+ public boolean isLaterVersionOf(ProtocolVersion version)
+ {
+ if (getMajorVersion() != version.getMajorVersion())
+ {
+ return false;
+ }
+ int diffMinorVersion = version.getMinorVersion() - getMinorVersion();
+ return isDTLS() ? diffMinorVersion > 0 : diffMinorVersion < 0;
+ }
+
+ public boolean equals(Object other)
+ {
+ return this == other || (other instanceof ProtocolVersion && equals((ProtocolVersion)other));
+ }
+
+ public boolean equals(ProtocolVersion other)
+ {
+ return other != null && this.version == other.version;
+ }
+
+ public int hashCode()
+ {
+ return version;
+ }
+
+ public static ProtocolVersion get(int major, int minor)
+ throws IOException
+ {
+ switch (major)
+ {
+ case 0x03:
+ {
+ switch (minor)
+ {
+ case 0x00:
+ return SSLv3;
+ case 0x01:
+ return TLSv10;
+ case 0x02:
+ return TLSv11;
+ case 0x03:
+ return TLSv12;
+ }
+ return getUnknownVersion(major, minor, "TLS");
+ }
+ case 0xFE:
+ {
+ switch (minor)
+ {
+ case 0xFF:
+ return DTLSv10;
+ case 0xFE:
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ case 0xFD:
+ return DTLSv12;
+ }
+ return getUnknownVersion(major, minor, "DTLS");
+ }
+ default:
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+ }
+
+ public String toString()
+ {
+ return name;
+ }
+
+ private static ProtocolVersion getUnknownVersion(int major, int minor, String prefix)
+ throws IOException
+ {
+ TlsUtils.checkUint8(major);
+ TlsUtils.checkUint8(minor);
+
+ int v = (major << 8) | minor;
+ String hex = Strings.toUpperCase(Integer.toHexString(0x10000 | v).substring(1));
+ return new ProtocolVersion(v, prefix + " 0x" + hex);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/RecordStream.java b/core/src/main/java/org/spongycastle/crypto/tls/RecordStream.java
new file mode 100644
index 00000000..3e1b3873
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/RecordStream.java
@@ -0,0 +1,365 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * An implementation of the TLS 1.0/1.1/1.2 record layer, allowing downgrade to SSLv3.
+ */
+class RecordStream
+{
+ private static int DEFAULT_PLAINTEXT_LIMIT = (1 << 14);
+
+ private TlsProtocol handler;
+ private InputStream input;
+ private OutputStream output;
+ private TlsCompression pendingCompression = null, readCompression = null, writeCompression = null;
+ private TlsCipher pendingCipher = null, readCipher = null, writeCipher = null;
+ private long readSeqNo = 0, writeSeqNo = 0;
+ private ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+
+ private TlsContext context = 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;
+ this.input = input;
+ this.output = output;
+ this.readCompression = new TlsNullCompression();
+ 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.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()
+ {
+ return readVersion;
+ }
+
+ void setReadVersion(ProtocolVersion readVersion)
+ {
+ this.readVersion = readVersion;
+ }
+
+ void setWriteVersion(ProtocolVersion writeVersion)
+ {
+ this.writeVersion = writeVersion;
+ }
+
+ /**
+ * RFC 5246 E.1. "Earlier versions of the TLS specification were not fully clear on what the
+ * record layer version number (TLSPlaintext.version) should contain when sending ClientHello
+ * (i.e., before it is known which version of the protocol will be employed). Thus, TLS servers
+ * compliant with this specification MUST accept any value {03,XX} as the record layer version
+ * number for ClientHello."
+ */
+ void setRestrictReadVersion(boolean enabled)
+ {
+ this.restrictReadVersion = enabled;
+ }
+
+ void setPendingConnectionState(TlsCompression tlsCompression, TlsCipher tlsCipher)
+ {
+ this.pendingCompression = tlsCompression;
+ this.pendingCipher = tlsCipher;
+ }
+
+ void sentWriteCipherSpec()
+ throws IOException
+ {
+ if (pendingCompression == null || pendingCipher == null)
+ {
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
+ }
+ this.writeCompression = this.pendingCompression;
+ this.writeCipher = this.pendingCipher;
+ this.writeSeqNo = 0;
+ }
+
+ void receivedReadCipherSpec()
+ throws IOException
+ {
+ if (pendingCompression == null || pendingCipher == null)
+ {
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
+ }
+ this.readCompression = this.pendingCompression;
+ this.readCipher = this.pendingCipher;
+ this.readSeqNo = 0;
+ }
+
+ void finaliseHandshake()
+ throws IOException
+ {
+ if (readCompression != pendingCompression || writeCompression != pendingCompression
+ || readCipher != pendingCipher || writeCipher != pendingCipher)
+ {
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
+ }
+ pendingCompression = null;
+ pendingCipher = null;
+ }
+
+ public boolean readRecord()
+ throws IOException
+ {
+ byte[] recordHeader = TlsUtils.readAllOrNothing(5, input);
+ if (recordHeader == null)
+ {
+ return false;
+ }
+
+ short type = TlsUtils.readUint8(recordHeader, 0);
+
+ /*
+ * RFC 5246 6. If a TLS implementation receives an unexpected record type, it MUST send an
+ * unexpected_message alert.
+ */
+ checkType(type, AlertDescription.unexpected_message);
+
+ if (!restrictReadVersion)
+ {
+ int version = TlsUtils.readVersionRaw(recordHeader, 1);
+ if ((version & 0xffffff00) != 0x0300)
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+ else
+ {
+ ProtocolVersion version = TlsUtils.readVersion(recordHeader, 1);
+ if (readVersion == null)
+ {
+ readVersion = version;
+ }
+ else if (!version.equals(readVersion))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+
+ 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, ciphertextLimit, AlertDescription.record_overflow);
+
+ byte[] buf = TlsUtils.readFully(len, input);
+ byte[] decoded = readCipher.decodeCiphertext(readSeqNo++, type, buf, 0, buf.length);
+
+ checkLength(decoded.length, compressedLimit, AlertDescription.record_overflow);
+
+ /*
+ * TODO RFC5264 6.2.2. Implementation note: Decompression functions are responsible for
+ * ensuring that messages cannot cause internal buffer overflows.
+ */
+ OutputStream cOut = readCompression.decompress(buffer);
+ if (cOut != buffer)
+ {
+ cOut.write(decoded, 0, decoded.length);
+ cOut.flush();
+ decoded = getBufferContents();
+ }
+
+ /*
+ * RFC 5264 6.2.2. If the decompression function encounters a TLSCompressed.fragment that
+ * would decompress to a length in excess of 2^14 bytes, it should report a fatal
+ * decompression failure error.
+ */
+ 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;
+ }
+
+ protected void writeRecord(short type, byte[] plaintext, int plaintextOffset, int plaintextLength)
+ throws IOException
+ {
+ // Never send anything until a valid ClientHello has been received
+ if (writeVersion == null)
+ {
+ return;
+ }
+
+ /*
+ * RFC 5264 6. Implementations MUST NOT send record types not defined in this document
+ * unless negotiated by some extension.
+ */
+ checkType(type, AlertDescription.internal_error);
+
+ /*
+ * RFC 5264 6.2.1 The length should not exceed 2^14.
+ */
+ checkLength(plaintextLength, plaintextLimit, AlertDescription.internal_error);
+
+ /*
+ * RFC 5264 6.2.1 Implementations MUST NOT send zero-length fragments of Handshake, Alert,
+ * or ChangeCipherSpec content types.
+ */
+ if (plaintextLength < 1 && type != ContentType.application_data)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ if (type == ContentType.handshake)
+ {
+ updateHandshakeData(plaintext, plaintextOffset, plaintextLength);
+ }
+
+ OutputStream cOut = writeCompression.compress(buffer);
+
+ byte[] ciphertext;
+ if (cOut == buffer)
+ {
+ ciphertext = writeCipher.encodePlaintext(writeSeqNo++, type, plaintext, plaintextOffset, plaintextLength);
+ }
+ else
+ {
+ cOut.write(plaintext, plaintextOffset, plaintextLength);
+ cOut.flush();
+ byte[] compressed = getBufferContents();
+
+ /*
+ * RFC5264 6.2.2. Compression must be lossless and may not increase the content length
+ * by more than 1024 bytes.
+ */
+ checkLength(compressed.length, plaintextLength + 1024, AlertDescription.internal_error);
+
+ ciphertext = writeCipher.encodePlaintext(writeSeqNo++, type, compressed, 0, compressed.length);
+ }
+
+ /*
+ * RFC 5264 6.2.3. The length may not exceed 2^14 + 2048.
+ */
+ checkLength(ciphertext.length, ciphertextLimit, AlertDescription.internal_error);
+
+ byte[] record = new byte[ciphertext.length + 5];
+ TlsUtils.writeUint8(type, record, 0);
+ TlsUtils.writeVersion(writeVersion, record, 1);
+ TlsUtils.writeUint16(ciphertext.length, record, 3);
+ System.arraycopy(ciphertext, 0, record, 5, ciphertext.length);
+ output.write(record);
+ output.flush();
+ }
+
+ void notifyHelloComplete()
+ {
+ this.handshakeHash = handshakeHash.notifyPRFDetermined();
+ }
+
+ TlsHandshakeHash getHandshakeHash()
+ {
+ return handshakeHash;
+ }
+
+ TlsHandshakeHash prepareToFinish()
+ {
+ TlsHandshakeHash result = handshakeHash;
+ this.handshakeHash = handshakeHash.stopTracking();
+ return result;
+ }
+
+ void updateHandshakeData(byte[] message, int offset, int len)
+ {
+ handshakeHash.update(message, offset, len);
+ }
+
+ protected void safeClose()
+ {
+ try
+ {
+ input.close();
+ }
+ catch (IOException e)
+ {
+ }
+
+ try
+ {
+ output.close();
+ }
+ catch (IOException e)
+ {
+ }
+ }
+
+ protected void flush()
+ throws IOException
+ {
+ output.flush();
+ }
+
+ private byte[] getBufferContents()
+ {
+ byte[] contents = buffer.toByteArray();
+ buffer.reset();
+ return contents;
+ }
+
+ private static void checkType(short type, short alertDescription)
+ throws IOException
+ {
+ switch (type)
+ {
+ case ContentType.application_data:
+ case ContentType.alert:
+ case ContentType.change_cipher_spec:
+ case ContentType.handshake:
+ case ContentType.heartbeat:
+ break;
+ default:
+ throw new TlsFatalAlert(alertDescription);
+ }
+ }
+
+ private static void checkLength(int length, int limit, short alertDescription)
+ throws IOException
+ {
+ if (length > limit)
+ {
+ throw new TlsFatalAlert(alertDescription);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/SRPTlsClient.java b/core/src/main/java/org/spongycastle/crypto/tls/SRPTlsClient.java
new file mode 100644
index 00000000..65aa6cee
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/SRPTlsClient.java
@@ -0,0 +1,121 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.util.Hashtable;
+
+import org.spongycastle.util.Arrays;
+
+public abstract class SRPTlsClient
+ extends AbstractTlsClient
+{
+ /**
+ * @deprecated use TlsSRPUtils.EXT_SRP instead
+ */
+ public static final Integer EXT_SRP = TlsSRPUtils.EXT_SRP;
+
+ protected byte[] identity;
+ protected byte[] password;
+
+ public SRPTlsClient(byte[] identity, byte[] password)
+ {
+ super();
+ this.identity = Arrays.clone(identity);
+ this.password = Arrays.clone(password);
+ }
+
+ public SRPTlsClient(TlsCipherFactory cipherFactory, byte[] identity, byte[] password)
+ {
+ super(cipherFactory);
+ this.identity = Arrays.clone(identity);
+ this.password = Arrays.clone(password);
+ }
+
+ public int[] getCipherSuites()
+ {
+ return new int[] { CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA };
+ }
+
+ public Hashtable getClientExtensions()
+ throws IOException
+ {
+ Hashtable clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(super.getClientExtensions());
+ TlsSRPUtils.addSRPExtension(clientExtensions, this.identity);
+ return clientExtensions;
+ }
+
+ public void processServerExtensions(Hashtable serverExtensions)
+ throws IOException
+ {
+ if (!TlsUtils.hasExpectedEmptyExtensionData(serverExtensions, TlsSRPUtils.EXT_SRP, AlertDescription.illegal_parameter))
+ {
+ // No explicit guidance in RFC 5054 here; we allow an optional empty extension from server
+ }
+ }
+
+ public TlsKeyExchange getKeyExchange()
+ throws IOException
+ {
+
+ switch (selectedCipherSuite)
+ {
+ case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
+ return createSRPKeyExchange(KeyExchangeAlgorithm.SRP);
+
+ case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
+ return createSRPKeyExchange(KeyExchangeAlgorithm.SRP_RSA);
+
+ case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
+ return createSRPKeyExchange(KeyExchangeAlgorithm.SRP_DSS);
+
+ default:
+ /*
+ * Note: internal error here; the TlsProtocol implementation verifies that the
+ * server-selected cipher suite was in the list of client-offered cipher suites, so if
+ * we now can't produce an implementation, we shouldn't have offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public TlsCipher getCipher()
+ throws IOException
+ {
+
+ switch (selectedCipherSuite)
+ {
+ case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm._3DES_EDE_CBC, MACAlgorithm.hmac_sha1);
+
+ case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_CBC, MACAlgorithm.hmac_sha1);
+
+ case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_CBC, MACAlgorithm.hmac_sha1);
+
+ default:
+ /*
+ * Note: internal error here; the TlsProtocol implementation verifies that the
+ * server-selected cipher suite was in the list of client-offered cipher suites, so if
+ * we now can't produce an implementation, we shouldn't have offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ protected TlsKeyExchange createSRPKeyExchange(int keyExchange)
+ {
+ return new TlsSRPKeyExchange(keyExchange, supportedSignatureAlgorithms, identity, password);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/SRTPProtectionProfile.java b/core/src/main/java/org/spongycastle/crypto/tls/SRTPProtectionProfile.java
new file mode 100644
index 00000000..6581b54a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/SRTPProtectionProfile.java
@@ -0,0 +1,12 @@
+package org.spongycastle.crypto.tls;
+
+public class SRTPProtectionProfile
+{
+ /*
+ * RFC 5764 4.1.2.
+ */
+ public static final int SRTP_AES128_CM_HMAC_SHA1_80 = 0x0001;
+ public static final int SRTP_AES128_CM_HMAC_SHA1_32 = 0x0002;
+ public static final int SRTP_NULL_HMAC_SHA1_80 = 0x0005;
+ public static final int SRTP_NULL_HMAC_SHA1_32 = 0x0006;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/SSL3Mac.java b/core/src/main/java/org/spongycastle/crypto/tls/SSL3Mac.java
new file mode 100644
index 00000000..6b3f2faf
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/SSL3Mac.java
@@ -0,0 +1,114 @@
+package org.spongycastle.crypto.tls;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Arrays;
+
+/**
+ * HMAC implementation based on original internet draft for HMAC (RFC 2104)
+ * <p>
+ * The difference is that padding is concatenated versus XORed with the key
+ * <p>
+ * H(K + opad, H(K + ipad, text))
+ */
+public class SSL3Mac
+ implements Mac
+{
+ private final static byte IPAD_BYTE = (byte)0x36;
+ private final static byte OPAD_BYTE = (byte)0x5C;
+
+ static final byte[] IPAD = genPad(IPAD_BYTE, 48);
+ static final byte[] OPAD = genPad(OPAD_BYTE, 48);
+
+ private Digest digest;
+
+ private byte[] secret;
+ private int padLength;
+
+ /**
+ * Base constructor for one of the standard digest algorithms that the byteLength of
+ * the algorithm is know for. Behaviour is undefined for digests other than MD5 or SHA1.
+ *
+ * @param digest the digest.
+ */
+ public SSL3Mac(Digest digest)
+ {
+ this.digest = digest;
+
+ if (digest.getDigestSize() == 20)
+ {
+ this.padLength = 40;
+ }
+ else
+ {
+ this.padLength = 48;
+ }
+ }
+
+ public String getAlgorithmName()
+ {
+ return digest.getAlgorithmName() + "/SSL3MAC";
+ }
+
+ public Digest getUnderlyingDigest()
+ {
+ return digest;
+ }
+
+ public void init(CipherParameters params)
+ {
+ secret = Arrays.clone(((KeyParameter)params).getKey());
+
+ reset();
+ }
+
+ public int getMacSize()
+ {
+ return digest.getDigestSize();
+ }
+
+ public void update(byte in)
+ {
+ digest.update(in);
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ {
+ digest.update(in, inOff, len);
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ {
+ byte[] tmp = new byte[digest.getDigestSize()];
+ digest.doFinal(tmp, 0);
+
+ digest.update(secret, 0, secret.length);
+ digest.update(OPAD, 0, padLength);
+ digest.update(tmp, 0, tmp.length);
+
+ int len = digest.doFinal(out, outOff);
+
+ reset();
+
+ return len;
+ }
+
+ /**
+ * Reset the mac generator.
+ */
+ public void reset()
+ {
+ digest.reset();
+ digest.update(secret, 0, secret.length);
+ digest.update(IPAD, 0, padLength);
+ }
+
+ private static byte[] genPad(byte b, int count)
+ {
+ byte[] padding = new byte[count];
+ Arrays.fill(padding, b);
+ return padding;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/SecurityParameters.java b/core/src/main/java/org/spongycastle/crypto/tls/SecurityParameters.java
new file mode 100644
index 00000000..36648311
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/SecurityParameters.java
@@ -0,0 +1,91 @@
+package org.spongycastle.crypto.tls;
+
+import org.spongycastle.util.Arrays;
+
+public class SecurityParameters
+{
+ int entity = -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;
+ boolean encryptThenMAC = 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}
+ */
+ public int getEntity()
+ {
+ return entity;
+ }
+
+ /**
+ * @return {@link CipherSuite}
+ */
+ public int getCipherSuite()
+ {
+ return cipherSuite;
+ }
+
+ /**
+ * @return {@link CompressionMethod}
+ */
+ public short getCompressionAlgorithm()
+ {
+ return compressionAlgorithm;
+ }
+
+ /**
+ * @return {@link PRFAlgorithm}
+ */
+ public int getPrfAlgorithm()
+ {
+ return prfAlgorithm;
+ }
+
+ public int getVerifyDataLength()
+ {
+ return verifyDataLength;
+ }
+
+ public byte[] getMasterSecret()
+ {
+ return masterSecret;
+ }
+
+ public byte[] getClientRandom()
+ {
+ return clientRandom;
+ }
+
+ public byte[] getServerRandom()
+ {
+ return serverRandom;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/ServerDHParams.java b/core/src/main/java/org/spongycastle/crypto/tls/ServerDHParams.java
new file mode 100644
index 00000000..fa22e629
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/ServerDHParams.java
@@ -0,0 +1,63 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+
+import org.spongycastle.crypto.params.DHParameters;
+import org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/tls/ServerName.java b/core/src/main/java/org/spongycastle/crypto/tls/ServerName.java
new file mode 100644
index 00000000..8e260291
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/ServerName.java
@@ -0,0 +1,112 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/tls/ServerNameList.java b/core/src/main/java/org/spongycastle/crypto/tls/ServerNameList.java
new file mode 100644
index 00000000..67c56e53
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/ServerNameList.java
@@ -0,0 +1,86 @@
+package org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/tls/ServerOnlyTlsAuthentication.java b/core/src/main/java/org/spongycastle/crypto/tls/ServerOnlyTlsAuthentication.java
new file mode 100644
index 00000000..325209ba
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/ServerOnlyTlsAuthentication.java
@@ -0,0 +1,10 @@
+package org.spongycastle.crypto.tls;
+
+public abstract class ServerOnlyTlsAuthentication
+ implements TlsAuthentication
+{
+ public final TlsCredentials getClientCredentials(CertificateRequest certificateRequest)
+ {
+ return null;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/SessionParameters.java b/core/src/main/java/org/spongycastle/crypto/tls/SessionParameters.java
new file mode 100644
index 00000000..cf8ec194
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/SessionParameters.java
@@ -0,0 +1,142 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Hashtable;
+
+import org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/tls/SignatureAlgorithm.java b/core/src/main/java/org/spongycastle/crypto/tls/SignatureAlgorithm.java
new file mode 100644
index 00000000..5da3b27b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/SignatureAlgorithm.java
@@ -0,0 +1,12 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 5246 7.4.1.4.1 (in RFC 2246, there were no specific values assigned)
+ */
+public class SignatureAlgorithm
+{
+ public static final short anonymous = 0;
+ public static final short rsa = 1;
+ public static final short dsa = 2;
+ public static final short ecdsa = 3;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/SignatureAndHashAlgorithm.java b/core/src/main/java/org/spongycastle/crypto/tls/SignatureAndHashAlgorithm.java
new file mode 100644
index 00000000..211c96c3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/SignatureAndHashAlgorithm.java
@@ -0,0 +1,96 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * RFC 5246 7.4.1.4.1
+ */
+public class SignatureAndHashAlgorithm
+{
+ protected short hash;
+ protected short signature;
+
+ /**
+ * @param hash {@link HashAlgorithm}
+ * @param signature {@link SignatureAlgorithm}
+ */
+ public SignatureAndHashAlgorithm(short hash, short signature)
+ {
+ if (!TlsUtils.isValidUint8(hash))
+ {
+ throw new IllegalArgumentException("'hash' should be a uint8");
+ }
+ if (!TlsUtils.isValidUint8(signature))
+ {
+ throw new IllegalArgumentException("'signature' should be a uint8");
+ }
+ if (signature == SignatureAlgorithm.anonymous)
+ {
+ throw new IllegalArgumentException("'signature' MUST NOT be \"anonymous\"");
+ }
+
+ this.hash = hash;
+ this.signature = signature;
+ }
+
+ /**
+ * @return {@link HashAlgorithm}
+ */
+ public short getHash()
+ {
+ return hash;
+ }
+
+ /**
+ * @return {@link SignatureAlgorithm}
+ */
+ public short getSignature()
+ {
+ return signature;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof SignatureAndHashAlgorithm))
+ {
+ return false;
+ }
+ SignatureAndHashAlgorithm other = (SignatureAndHashAlgorithm)obj;
+ return other.getHash() == getHash() && other.getSignature() == getSignature();
+ }
+
+ public int hashCode()
+ {
+ return (getHash() << 16) | getSignature();
+ }
+
+ /**
+ * Encode this {@link SignatureAndHashAlgorithm} to an {@link OutputStream}.
+ *
+ * @param output the {@link OutputStream} to encode to.
+ * @throws IOException
+ */
+ public void encode(OutputStream output)
+ throws IOException
+ {
+ TlsUtils.writeUint8(getHash(), output);
+ TlsUtils.writeUint8(getSignature(), output);
+ }
+
+ /**
+ * Parse a {@link SignatureAndHashAlgorithm} from an {@link InputStream}.
+ *
+ * @param input the {@link InputStream} to parse from.
+ * @return a {@link SignatureAndHashAlgorithm} object.
+ * @throws IOException
+ */
+ public static SignatureAndHashAlgorithm parse(InputStream input)
+ throws IOException
+ {
+ short hash = TlsUtils.readUint8(input);
+ short signature = TlsUtils.readUint8(input);
+ return new SignatureAndHashAlgorithm(hash, signature);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/SignerInputBuffer.java b/core/src/main/java/org/spongycastle/crypto/tls/SignerInputBuffer.java
new file mode 100644
index 00000000..39a68e6c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/SignerInputBuffer.java
@@ -0,0 +1,13 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.ByteArrayOutputStream;
+
+import org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/tls/SupplementalDataEntry.java b/core/src/main/java/org/spongycastle/crypto/tls/SupplementalDataEntry.java
new file mode 100644
index 00000000..2633623d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/SupplementalDataEntry.java
@@ -0,0 +1,23 @@
+package org.spongycastle.crypto.tls;
+
+public class SupplementalDataEntry
+{
+ protected int dataType;
+ protected byte[] data;
+
+ public SupplementalDataEntry(int dataType, byte[] data)
+ {
+ this.dataType = dataType;
+ this.data = data;
+ }
+
+ public int getDataType()
+ {
+ return dataType;
+ }
+
+ public byte[] getData()
+ {
+ return data;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/SupplementalDataType.java b/core/src/main/java/org/spongycastle/crypto/tls/SupplementalDataType.java
new file mode 100644
index 00000000..5cabe8c3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/SupplementalDataType.java
@@ -0,0 +1,12 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 4680
+ */
+public class SupplementalDataType
+{
+ /*
+ * RFC 4681
+ */
+ public static final int user_mapping_data = 0;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsAEADCipher.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsAEADCipher.java
new file mode 100644
index 00000000..0ddc2fe5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsAEADCipher.java
@@ -0,0 +1,193 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+import org.spongycastle.crypto.modes.AEADBlockCipher;
+import org.spongycastle.crypto.params.AEADParameters;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Arrays;
+
+public class TlsAEADCipher
+ implements TlsCipher
+{
+ protected TlsContext context;
+ protected int macSize;
+ protected int nonce_explicit_length;
+
+ protected AEADBlockCipher encryptCipher;
+ protected AEADBlockCipher decryptCipher;
+
+ protected byte[] encryptImplicitNonce, decryptImplicitNonce;
+
+ public TlsAEADCipher(TlsContext context, AEADBlockCipher clientWriteCipher, AEADBlockCipher serverWriteCipher,
+ int cipherKeySize, int macSize) throws IOException
+ {
+ if (!TlsUtils.isTLSv12(context))
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ this.context = context;
+ this.macSize = macSize;
+
+ // 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
+ int fixed_iv_length = 4;
+
+ int key_block_size = (2 * cipherKeySize) + (2 * fixed_iv_length);
+
+ byte[] key_block = TlsUtils.calculateKeyBlock(context, key_block_size);
+
+ int offset = 0;
+
+ KeyParameter client_write_key = new KeyParameter(key_block, offset, cipherKeySize);
+ offset += cipherKeySize;
+ KeyParameter server_write_key = new KeyParameter(key_block, offset, cipherKeySize);
+ offset += cipherKeySize;
+ byte[] client_write_IV = Arrays.copyOfRange(key_block, offset, offset + fixed_iv_length);
+ offset += fixed_iv_length;
+ byte[] server_write_IV = Arrays.copyOfRange(key_block, offset, offset + fixed_iv_length);
+ offset += fixed_iv_length;
+
+ if (offset != key_block_size)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ KeyParameter encryptKey, decryptKey;
+ if (context.isServer())
+ {
+ this.encryptCipher = serverWriteCipher;
+ this.decryptCipher = clientWriteCipher;
+ this.encryptImplicitNonce = server_write_IV;
+ this.decryptImplicitNonce = client_write_IV;
+ encryptKey = server_write_key;
+ decryptKey = client_write_key;
+ }
+ else
+ {
+ this.encryptCipher = clientWriteCipher;
+ this.decryptCipher = serverWriteCipher;
+ this.encryptImplicitNonce = client_write_IV;
+ this.decryptImplicitNonce = server_write_IV;
+ encryptKey = client_write_key;
+ decryptKey = server_write_key;
+ }
+
+ byte[] dummyNonce = new byte[fixed_iv_length + nonce_explicit_length];
+
+ this.encryptCipher.init(true, new AEADParameters(encryptKey, 8 * macSize, dummyNonce));
+ this.decryptCipher.init(false, new AEADParameters(decryptKey, 8 * macSize, dummyNonce));
+ }
+
+ public int getPlaintextLimit(int ciphertextLimit)
+ {
+ // TODO We ought to be able to ask the decryptCipher (independently of it's current state!)
+ return ciphertextLimit - macSize - nonce_explicit_length;
+ }
+
+ 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/6655 The nonce_explicit MAY be the 64-bit sequence number.
+ *
+ * (May need review for other AEAD ciphers).
+ */
+ TlsUtils.writeUint64(seqNo, nonce, encryptImplicitNonce.length);
+
+ int plaintextOffset = offset;
+ int plaintextLength = len;
+ int ciphertextLength = encryptCipher.getOutputSize(plaintextLength);
+
+ byte[] output = new byte[nonce_explicit_length + ciphertextLength];
+ System.arraycopy(nonce, encryptImplicitNonce.length, output, 0, nonce_explicit_length);
+ int outputPos = nonce_explicit_length;
+
+ byte[] additionalData = getAdditionalData(seqNo, type, plaintextLength);
+ AEADParameters parameters = new AEADParameters(null, 8 * macSize, nonce, additionalData);
+
+ try
+ {
+ encryptCipher.init(true, parameters);
+ outputPos += encryptCipher.processBytes(plaintext, plaintextOffset, plaintextLength, output, outputPos);
+ outputPos += encryptCipher.doFinal(output, outputPos);
+ }
+ catch (Exception e)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ if (outputPos != output.length)
+ {
+ // NOTE: Existing AEAD cipher implementations all give exact output lengths
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ return output;
+ }
+
+ 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);
+ }
+
+ byte[] nonce = new byte[this.decryptImplicitNonce.length + nonce_explicit_length];
+ System.arraycopy(decryptImplicitNonce, 0, nonce, 0, decryptImplicitNonce.length);
+ System.arraycopy(ciphertext, offset, nonce, decryptImplicitNonce.length, nonce_explicit_length);
+
+ int ciphertextOffset = offset + nonce_explicit_length;
+ int ciphertextLength = len - nonce_explicit_length;
+ int plaintextLength = decryptCipher.getOutputSize(ciphertextLength);
+
+ byte[] output = new byte[plaintextLength];
+ int outputPos = 0;
+
+ 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)
+ {
+ throw new TlsFatalAlert(AlertDescription.bad_record_mac);
+ }
+
+ if (outputPos != output.length)
+ {
+ // NOTE: Existing AEAD cipher implementations all give exact output lengths
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ return output;
+ }
+
+ protected byte[] getAdditionalData(long seqNo, short type, int len)
+ throws IOException
+ {
+ /*
+ * additional_data = seq_num + TLSCompressed.type + TLSCompressed.version +
+ * TLSCompressed.length
+ */
+
+ byte[] additional_data = new byte[13];
+ TlsUtils.writeUint64(seqNo, additional_data, 0);
+ TlsUtils.writeUint8(type, additional_data, 8);
+ TlsUtils.writeVersion(context.getServerVersion(), additional_data, 9);
+ TlsUtils.writeUint16(len, additional_data, 11);
+
+ return additional_data;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsAgreementCredentials.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsAgreementCredentials.java
new file mode 100644
index 00000000..8926d6fb
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsAgreementCredentials.java
@@ -0,0 +1,12 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+
+public interface TlsAgreementCredentials
+ extends TlsCredentials
+{
+ byte[] generateAgreement(AsymmetricKeyParameter peerPublicKey)
+ throws IOException;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsAuthentication.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsAuthentication.java
new file mode 100755
index 00000000..8783dd75
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsAuthentication.java
@@ -0,0 +1,26 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+public interface TlsAuthentication
+{
+ /**
+ * Called by the protocol handler to report the server certificate
+ * Note: this method is responsible for certificate verification and validation
+ *
+ * @param serverCertificate the server certificate received
+ * @throws IOException
+ */
+ void notifyServerCertificate(Certificate serverCertificate)
+ throws IOException;
+
+ /**
+ * Return client credentials in response to server's certificate request
+ *
+ * @param certificateRequest details of the certificate request
+ * @return a TlsCredentials object or null for no client authentication
+ * @throws IOException
+ */
+ TlsCredentials getClientCredentials(CertificateRequest certificateRequest)
+ throws IOException;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsBlockCipher.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsBlockCipher.java
new file mode 100644
index 00000000..4dd67595
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsBlockCipher.java
@@ -0,0 +1,386 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Arrays;
+
+/**
+ * A generic TLS 1.0-1.2 / SSLv3 block cipher. This can be used for AES or 3DES for example.
+ */
+public class TlsBlockCipher
+ implements TlsCipher
+{
+ protected TlsContext context;
+ protected byte[] randomData;
+ protected boolean useExplicitIV;
+ private boolean encryptThenMAC;
+
+ protected BlockCipher encryptCipher;
+ protected BlockCipher decryptCipher;
+
+ protected TlsMac writeMac;
+ protected TlsMac readMac;
+
+ public TlsMac getWriteMac()
+ {
+ return writeMac;
+ }
+
+ public TlsMac getReadMac()
+ {
+ return readMac;
+ }
+
+ public TlsBlockCipher(TlsContext context, BlockCipher clientWriteCipher, BlockCipher serverWriteCipher,
+ Digest clientWriteDigest, Digest serverWriteDigest, int cipherKeySize) throws IOException
+ {
+ this.context = context;
+
+ this.randomData = new byte[256];
+ context.getNonceRandomGenerator().nextBytes(randomData);
+
+ this.useExplicitIV = TlsUtils.isTLSv11(context);
+ this.encryptThenMAC = context.getSecurityParameters().encryptThenMAC;
+
+ int key_block_size = (2 * cipherKeySize) + clientWriteDigest.getDigestSize()
+ + serverWriteDigest.getDigestSize();
+
+ // From TLS 1.1 onwards, block ciphers don't need client_write_IV
+ if (!useExplicitIV)
+ {
+ key_block_size += clientWriteCipher.getBlockSize() + serverWriteCipher.getBlockSize();
+ }
+
+ byte[] key_block = TlsUtils.calculateKeyBlock(context, key_block_size);
+
+ int offset = 0;
+
+ TlsMac clientWriteMac = new TlsMac(context, clientWriteDigest, key_block, offset,
+ clientWriteDigest.getDigestSize());
+ offset += clientWriteDigest.getDigestSize();
+ TlsMac serverWriteMac = new TlsMac(context, serverWriteDigest, key_block, offset,
+ serverWriteDigest.getDigestSize());
+ offset += serverWriteDigest.getDigestSize();
+
+ KeyParameter client_write_key = new KeyParameter(key_block, offset, cipherKeySize);
+ offset += cipherKeySize;
+ KeyParameter server_write_key = new KeyParameter(key_block, offset, cipherKeySize);
+ offset += cipherKeySize;
+
+ byte[] client_write_IV, server_write_IV;
+ if (useExplicitIV)
+ {
+ client_write_IV = new byte[clientWriteCipher.getBlockSize()];
+ server_write_IV = new byte[serverWriteCipher.getBlockSize()];
+ }
+ else
+ {
+ client_write_IV = Arrays.copyOfRange(key_block, offset, offset + clientWriteCipher.getBlockSize());
+ offset += clientWriteCipher.getBlockSize();
+ server_write_IV = Arrays.copyOfRange(key_block, offset, offset + serverWriteCipher.getBlockSize());
+ offset += serverWriteCipher.getBlockSize();
+ }
+
+ if (offset != key_block_size)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ CipherParameters encryptParams, decryptParams;
+ if (context.isServer())
+ {
+ this.writeMac = serverWriteMac;
+ this.readMac = clientWriteMac;
+ this.encryptCipher = serverWriteCipher;
+ this.decryptCipher = clientWriteCipher;
+ encryptParams = new ParametersWithIV(server_write_key, server_write_IV);
+ decryptParams = new ParametersWithIV(client_write_key, client_write_IV);
+ }
+ else
+ {
+ this.writeMac = clientWriteMac;
+ this.readMac = serverWriteMac;
+ this.encryptCipher = clientWriteCipher;
+ this.decryptCipher = serverWriteCipher;
+ encryptParams = new ParametersWithIV(client_write_key, client_write_IV);
+ decryptParams = new ParametersWithIV(server_write_key, server_write_IV);
+ }
+
+ this.encryptCipher.init(true, encryptParams);
+ this.decryptCipher.init(false, decryptParams);
+ }
+
+ public int getPlaintextLimit(int ciphertextLimit)
+ {
+ int blockSize = encryptCipher.getBlockSize();
+ int macSize = writeMac.getSize();
+
+ int plaintextLimit = ciphertextLimit;
+
+ // An explicit IV consumes 1 block
+ if (useExplicitIV)
+ {
+ plaintextLimit -= blockSize;
+ }
+
+ // 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)
+ {
+ int blockSize = encryptCipher.getBlockSize();
+ int macSize = writeMac.getSize();
+
+ ProtocolVersion version = context.getServerVersion();
+
+ 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())
+ {
+ // Add a random number of extra blocks worth of padding
+ int maxExtraPadBlocks = (255 - padding_length) / blockSize;
+ int actualExtraPadBlocks = chooseExtraPadBlocks(context.getSecureRandom(), maxExtraPadBlocks);
+ padding_length += actualExtraPadBlocks * blockSize;
+ }
+
+ int totalSize = len + macSize + padding_length + 1;
+ if (useExplicitIV)
+ {
+ totalSize += blockSize;
+ }
+
+ byte[] outBuf = new byte[totalSize];
+ int outOff = 0;
+
+ if (useExplicitIV)
+ {
+ byte[] explicitIV = new byte[blockSize];
+ context.getNonceRandomGenerator().nextBytes(explicitIV);
+
+ encryptCipher.init(true, new ParametersWithIV(null, explicitIV));
+
+ System.arraycopy(explicitIV, 0, outBuf, outOff, blockSize);
+ outOff += blockSize;
+ }
+
+ int blocks_start = outOff;
+
+ System.arraycopy(plaintext, offset, outBuf, outOff, len);
+ outOff += len;
+
+ if (!encryptThenMAC)
+ {
+ byte[] mac = writeMac.calculateMac(seqNo, type, plaintext, offset, len);
+ System.arraycopy(mac, 0, outBuf, outOff, mac.length);
+ outOff += mac.length;
+ }
+
+ for (int i = 0; i <= padding_length; i++)
+ {
+ outBuf[outOff++] = (byte)padding_length;
+ }
+
+ for (int i = blocks_start; i < outOff; i += blockSize)
+ {
+ encryptCipher.processBlock(outBuf, i, outBuf, i);
+ }
+
+ 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)
+ throws IOException
+ {
+ int blockSize = decryptCipher.getBlockSize();
+ int macSize = readMac.getSize();
+
+ int minLen = blockSize;
+ if (encryptThenMAC)
+ {
+ minLen += macSize;
+ }
+ else
+ {
+ minLen = Math.max(minLen, macSize + 1);
+ }
+
+ if (useExplicitIV)
+ {
+ minLen += blockSize;
+ }
+
+ if (len < minLen)
+ {
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+
+ 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;
+ blocks_length -= 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, blocks_length, blockSize, encryptThenMAC ? 0 : macSize);
+
+ int dec_output_length = blocks_length - totalPad;
+
+ 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, receivedMac);
+
+ if (badMac || totalPad == 0)
+ {
+ throw new TlsFatalAlert(AlertDescription.bad_record_mac);
+ }
+ }
+
+ return Arrays.copyOfRange(ciphertext, offset, offset + dec_output_length);
+ }
+
+ protected int checkPaddingConstantTime(byte[] buf, int off, int len, int blockSize, int macSize)
+ {
+ int end = off + len;
+ byte lastByte = buf[end - 1];
+ int padlen = lastByte & 0xff;
+ int totalPad = padlen + 1;
+
+ int dummyIndex = 0;
+ byte padDiff = 0;
+
+ if ((TlsUtils.isSSL(context) && totalPad > blockSize) || (macSize + totalPad > len))
+ {
+ totalPad = 0;
+ }
+ else
+ {
+ int padPos = end - totalPad;
+ do
+ {
+ padDiff |= (buf[padPos++] ^ lastByte);
+ }
+ while (padPos < end);
+
+ dummyIndex = totalPad;
+
+ if (padDiff != 0)
+ {
+ totalPad = 0;
+ }
+ }
+
+ // Run some extra dummy checks so the number of checks is always constant
+ {
+ byte[] dummyPad = randomData;
+ while (dummyIndex < 256)
+ {
+ padDiff |= (dummyPad[dummyIndex++] ^ lastByte);
+ }
+ // Ensure the above loop is not eliminated
+ dummyPad[0] ^= padDiff;
+ }
+
+ return totalPad;
+ }
+
+ protected int chooseExtraPadBlocks(SecureRandom r, int max)
+ {
+ // return r.nextInt(max + 1);
+
+ int x = r.nextInt();
+ int n = lowestBitSet(x);
+ return Math.min(n, max);
+ }
+
+ protected int lowestBitSet(int x)
+ {
+ if (x == 0)
+ {
+ return 32;
+ }
+
+ int n = 0;
+ while ((x & 1) == 0)
+ {
+ ++n;
+ x >>= 1;
+ }
+ return n;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsCipher.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsCipher.java
new file mode 100644
index 00000000..6a8f6bc0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsCipher.java
@@ -0,0 +1,14 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+public interface TlsCipher
+{
+ int getPlaintextLimit(int ciphertextLimit);
+
+ byte[] encodePlaintext(long seqNo, short type, byte[] plaintext, int offset, int len)
+ throws IOException;
+
+ byte[] decodeCiphertext(long seqNo, short type, byte[] ciphertext, int offset, int len)
+ throws IOException;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsCipherFactory.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsCipherFactory.java
new file mode 100644
index 00000000..31b2bacf
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsCipherFactory.java
@@ -0,0 +1,12 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+public interface TlsCipherFactory
+{
+ /**
+ * See enumeration classes EncryptionAlgorithm, MACAlgorithm for appropriate argument values
+ */
+ TlsCipher createCipher(TlsContext context, int encryptionAlgorithm, int macAlgorithm)
+ throws IOException;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsClient.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsClient.java
new file mode 100644
index 00000000..bce22061
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsClient.java
@@ -0,0 +1,79 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.util.Hashtable;
+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();
+
+ int[] getCipherSuites();
+
+ short[] getCompressionMethods();
+
+ // Hashtable is (Integer -> byte[])
+ Hashtable getClientExtensions()
+ throws IOException;
+
+ void notifyServerVersion(ProtocolVersion selectedVersion)
+ throws IOException;
+
+ /**
+ * Notifies the client of the session_id sent in the ServerHello.
+ *
+ * @param sessionID
+ * @see TlsContext#getResumableSession()
+ */
+ void notifySessionID(byte[] sessionID);
+
+ void notifySelectedCipherSuite(int selectedCipherSuite);
+
+ void notifySelectedCompressionMethod(short selectedCompressionMethod);
+
+ // Hashtable is (Integer -> byte[])
+ void processServerExtensions(Hashtable serverExtensions)
+ throws IOException;
+
+ // Vector is (SupplementalDataEntry)
+ void processServerSupplementalData(Vector serverSupplementalData)
+ throws IOException;
+
+ TlsKeyExchange getKeyExchange()
+ throws IOException;
+
+ TlsAuthentication getAuthentication()
+ throws IOException;
+
+ // Vector is (SupplementalDataEntry)
+ Vector getClientSupplementalData()
+ throws IOException;
+
+ /**
+ * RFC 5077 3.3. NewSessionTicket Handshake Message
+ * <p>
+ * This method will be called (only) when a NewSessionTicket handshake message is received. The
+ * ticket is opaque to the client and clients MUST NOT examine the ticket under the assumption
+ * that it complies with e.g. <i>RFC 5077 4. Recommended Ticket Construction</i>.
+ *
+ * @param newSessionTicket The ticket.
+ * @throws IOException
+ */
+ void notifyNewSessionTicket(NewSessionTicket newSessionTicket)
+ throws IOException;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsClientContext.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsClientContext.java
new file mode 100644
index 00000000..245245b2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsClientContext.java
@@ -0,0 +1,6 @@
+package org.spongycastle.crypto.tls;
+
+public interface TlsClientContext
+ extends TlsContext
+{
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsClientContextImpl.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsClientContextImpl.java
new file mode 100644
index 00000000..ca392944
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsClientContextImpl.java
@@ -0,0 +1,18 @@
+package org.spongycastle.crypto.tls;
+
+import java.security.SecureRandom;
+
+class TlsClientContextImpl
+ extends AbstractTlsContext
+ implements TlsClientContext
+{
+ TlsClientContextImpl(SecureRandom secureRandom, SecurityParameters securityParameters)
+ {
+ super(secureRandom, securityParameters);
+ }
+
+ public boolean isServer()
+ {
+ return false;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsClientProtocol.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsClientProtocol.java
new file mode 100644
index 00000000..b50bd7d8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsClientProtocol.java
@@ -0,0 +1,917 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.SecureRandom;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.spongycastle.crypto.prng.ThreadedSeedGenerator;
+import org.spongycastle.util.Arrays;
+
+public class TlsClientProtocol
+ extends TlsProtocol
+{
+ protected TlsClient tlsClient = null;
+ protected TlsClientContextImpl tlsClientContext = null;
+
+ protected byte[] selectedSessionID = null;
+
+ protected TlsKeyExchange keyExchange = null;
+ protected TlsAuthentication authentication = null;
+
+ protected CertificateStatus certificateStatus = null;
+ protected CertificateRequest certificateRequest = null;
+
+ private static SecureRandom createSecureRandom()
+ {
+ /*
+ * We use our threaded seed generator to generate a good random seed. If the user has a
+ * better random seed, he should use the constructor with a SecureRandom.
+ */
+ ThreadedSeedGenerator tsg = new ThreadedSeedGenerator();
+ SecureRandom random = new SecureRandom();
+
+ /*
+ * Hopefully, 20 bytes in fast mode are good enough.
+ */
+ random.setSeed(tsg.generateSeed(20, true));
+
+ return random;
+ }
+
+ /**
+ * @deprecated use alternate constructor taking an explicit {@link SecureRandom}
+ */
+ public TlsClientProtocol(InputStream input, OutputStream output)
+ {
+ this(input, output, createSecureRandom());
+ }
+
+ public TlsClientProtocol(InputStream input, OutputStream output, SecureRandom secureRandom)
+ {
+ super(input, output, secureRandom);
+ }
+
+ /**
+ * Initiates a TLS handshake in the role of client
+ *
+ * @param tlsClient The {@link TlsClient} to use for the handshake.
+ * @throws IOException If handshake was not successful.
+ */
+ public void connect(TlsClient tlsClient) throws IOException
+ {
+ if (tlsClient == null)
+ {
+ throw new IllegalArgumentException("'tlsClient' cannot be null");
+ }
+ if (this.tlsClient != null)
+ {
+ throw new IllegalStateException("'connect' can only be called once");
+ }
+
+ this.tlsClient = tlsClient;
+
+ this.securityParameters = new SecurityParameters();
+ this.securityParameters.entity = ConnectionEnd.client;
+
+ this.tlsClientContext = new TlsClientContextImpl(secureRandom, securityParameters);
+
+ this.securityParameters.clientRandom = createRandomBlock(tlsClient.shouldUseGMTUnixTime(),
+ tlsClientContext.getNonceRandomGenerator());
+
+ 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();
+ }
+
+ protected void cleanupHandshake()
+ {
+ super.cleanupHandshake();
+
+ this.selectedSessionID = null;
+ this.keyExchange = null;
+ this.authentication = null;
+ this.certificateStatus = null;
+ this.certificateRequest = null;
+ }
+
+ protected AbstractTlsContext getContext()
+ {
+ return tlsClientContext;
+ }
+
+ protected TlsPeer getPeer()
+ {
+ return tlsClient;
+ }
+
+ protected void handleHandshakeMessage(short type, byte[] data)
+ throws IOException
+ {
+ ByteArrayInputStream buf = new ByteArrayInputStream(data);
+
+ if (this.resumedSession)
+ {
+ if (type != HandshakeType.finished || this.connection_state != CS_SERVER_HELLO)
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ processFinishedMessage(buf);
+ this.connection_state = CS_SERVER_FINISHED;
+
+ sendFinishedMessage();
+ this.connection_state = CS_CLIENT_FINISHED;
+ this.connection_state = CS_END;
+
+ return;
+ }
+
+ switch (type)
+ {
+ case HandshakeType.certificate:
+ {
+ switch (this.connection_state)
+ {
+ case CS_SERVER_HELLO:
+ {
+ handleSupplementalData(null);
+ // NB: Fall through to next case label
+ }
+ case CS_SERVER_SUPPLEMENTAL_DATA:
+ {
+ // Parse the Certificate message and send to cipher suite
+
+ this.peerCertificate = Certificate.parse(buf);
+
+ assertEmpty(buf);
+
+ // 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(this.peerCertificate);
+
+ break;
+ }
+ default:
+ 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_CLIENT_FINISHED:
+ {
+ if (this.expectSessionTicket)
+ {
+ /*
+ * RFC 5077 3.3. This message MUST be sent if the server included a
+ * SessionTicket extension in the ServerHello.
+ */
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ // NB: Fall through to next case label
+ }
+ case CS_SERVER_SESSION_TICKET:
+ {
+ processFinishedMessage(buf);
+ this.connection_state = CS_SERVER_FINISHED;
+ this.connection_state = CS_END;
+ break;
+ }
+ default:
+ 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;
+
+ 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.
+ */
+ this.securityParameters.verifyDataLength = 12;
+
+ 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:
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ break;
+ }
+ case HandshakeType.supplemental_data:
+ {
+ switch (this.connection_state)
+ {
+ case CS_SERVER_HELLO:
+ {
+ handleSupplementalData(readSupplementalDataMessage(buf));
+ break;
+ }
+ default:
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ break;
+ }
+ case HandshakeType.server_hello_done:
+ {
+ switch (this.connection_state)
+ {
+ case CS_SERVER_HELLO:
+ {
+ handleSupplementalData(null);
+ // NB: Fall through to next case label
+ }
+ case CS_SERVER_SUPPLEMENTAL_DATA:
+ {
+ // There was no server certificate message; check it's OK
+ this.keyExchange.skipServerCredentials();
+ this.authentication = null;
+
+ // 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)
+ {
+ sendSupplementalDataMessage(clientSupplementalData);
+ }
+ this.connection_state = CS_CLIENT_SUPPLEMENTAL_DATA;
+
+ TlsCredentials clientCreds = null;
+ if (certificateRequest == null)
+ {
+ this.keyExchange.skipClientCredentials();
+ }
+ else
+ {
+ clientCreds = this.authentication.getClientCredentials(certificateRequest);
+
+ if (clientCreds == null)
+ {
+ this.keyExchange.skipClientCredentials();
+
+ /*
+ * RFC 5246 If no suitable certificate is available, the client MUST send a
+ * certificate message containing no certificates.
+ *
+ * NOTE: In previous RFCs, this was SHOULD instead of MUST.
+ */
+ sendCertificateMessage(Certificate.EMPTY_CHAIN);
+ }
+ else
+ {
+ this.keyExchange.processClientCredentials(clientCreds);
+
+ sendCertificateMessage(clientCreds.getCertificate());
+ }
+ }
+
+ this.connection_state = CS_CLIENT_CERTIFICATE;
+
+ /*
+ * Send the client key exchange message, depending on the key exchange we are using
+ * in our CipherSuite.
+ */
+ sendClientKeyExchangeMessage();
+ this.connection_state = CS_CLIENT_KEY_EXCHANGE;
+
+ establishMasterSecret(getContext(), keyExchange);
+ recordStream.setPendingConnectionState(getPeer().getCompression(), getPeer().getCipher());
+
+ TlsHandshakeHash prepareFinishHash = recordStream.prepareToFinish();
+
+ if (clientCreds != null && clientCreds instanceof TlsSignerCredentials)
+ {
+ TlsSignerCredentials signerCredentials = (TlsSignerCredentials)clientCreds;
+
+ /*
+ * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2
+ */
+ 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();
+ sendFinishedMessage();
+ this.connection_state = CS_CLIENT_FINISHED;
+ break;
+ }
+ default:
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
+ }
+ break;
+ }
+ case HandshakeType.server_key_exchange:
+ {
+ switch (this.connection_state)
+ {
+ case CS_SERVER_HELLO:
+ {
+ handleSupplementalData(null);
+ // NB: Fall through to next case label
+ }
+ case CS_SERVER_SUPPLEMENTAL_DATA:
+ {
+ // There was no server certificate message; check it's OK
+ this.keyExchange.skipServerCredentials();
+ this.authentication = null;
+
+ // NB: Fall through to next case label
+ }
+ case CS_SERVER_CERTIFICATE:
+ case CS_CERTIFICATE_STATUS:
+ {
+ this.keyExchange.processServerKeyExchange(buf);
+
+ assertEmpty(buf);
+ break;
+ }
+ default:
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ this.connection_state = CS_SERVER_KEY_EXCHANGE;
+ break;
+ }
+ case HandshakeType.certificate_request:
+ {
+ 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)
+ {
+ /*
+ * RFC 2246 7.4.4. It is a fatal handshake_failure alert for an anonymous server
+ * to request client identification.
+ */
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
+ }
+
+ 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:
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ this.connection_state = CS_CERTIFICATE_REQUEST;
+ break;
+ }
+ case HandshakeType.session_ticket:
+ {
+ 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.
+ */
+ 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:
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ }
+ case HandshakeType.hello_request:
+ {
+ assertEmpty(buf);
+
+ /*
+ * RFC 2246 7.4.1.1 Hello request This message will be ignored by the client if the
+ * client is currently negotiating a session. This message may be ignored by the client
+ * 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_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.hello_verify_request:
+ default:
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ }
+
+ protected void handleSupplementalData(Vector serverSupplementalData)
+ throws IOException
+ {
+ this.tlsClient.processServerSupplementalData(serverSupplementalData);
+ this.connection_state = CS_SERVER_SUPPLEMENTAL_DATA;
+
+ this.keyExchange = tlsClient.getKeyExchange();
+ this.keyExchange.init(getContext());
+ }
+
+ protected void receiveNewSessionTicketMessage(ByteArrayInputStream buf)
+ throws IOException
+ {
+ NewSessionTicket newSessionTicket = NewSessionTicket.parse(buf);
+
+ TlsProtocol.assertEmpty(buf);
+
+ tlsClient.notifyNewSessionTicket(newSessionTicket);
+ }
+
+ protected void receiveServerHelloMessage(ByteArrayInputStream buf)
+ throws IOException
+ {
+ ProtocolVersion server_version = TlsUtils.readVersion(buf);
+ if (server_version.isDTLS())
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ // Check that this matches what the server is sending in the record layer
+ if (!server_version.equals(this.recordStream.getReadVersion()))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ ProtocolVersion client_version = getContext().getClientVersion();
+ if (!server_version.isEqualOrEarlierVersionOf(client_version))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ this.recordStream.setWriteVersion(server_version);
+ getContext().setServerVersion(server_version);
+ this.tlsClient.notifyServerVersion(server_version);
+
+ /*
+ * Read the server random
+ */
+ this.securityParameters.serverRandom = TlsUtils.readFully(32, buf);
+
+ this.selectedSessionID = TlsUtils.readOpaque8(buf);
+ if (this.selectedSessionID.length > 32)
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ 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, and is a valid selection for the negotiated version.
+ */
+ 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
+ || !TlsUtils.isValidCipherSuiteForVersion(selectedCipherSuite, server_version))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ 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 (!Arrays.contains(this.offeredCompressionMethods, selectedCompressionMethod))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ this.tlsClient.notifySelectedCompressionMethod(selectedCompressionMethod);
+
+ /*
+ * RFC3546 2.2 The extended server hello message format MAY be sent in place of the server
+ * hello message when the client has requested extended functionality via the extended
+ * client hello message specified in Section 2.1. ... Note that the extended server hello
+ * message is only sent in response to an extended client hello message. This prevents the
+ * possibility that the extended server hello message could "break" existing TLS 1.0
+ * clients.
+ */
+ this.serverExtensions = readExtensions(buf);
+
+ /*
+ * RFC 3546 2.2 Note that the extended server hello message is only sent in response to an
+ * extended client hello message.
+ *
+ * However, see RFC 5746 exception below. We always include the SCSV, so an Extended Server
+ * Hello is always allowed.
+ */
+ if (this.serverExtensions != null)
+ {
+ Enumeration e = this.serverExtensions.keys();
+ while (e.hasMoreElements())
+ {
+ Integer extType = (Integer)e.nextElement();
+
+ /*
+ * RFC 5746 3.6. Note that sending a "renegotiation_info" extension in response to a
+ * ClientHello containing only the SCSV is an explicit exception to the prohibition
+ * in RFC 5246, Section 7.4.1.4, on the server sending unsolicited extensions and is
+ * 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))
+ {
+ 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
+ */
+ {
+ /*
+ * 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)
+ {
+ /*
+ * 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;
+
+ 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);
+
+ 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();
+ }
+
+ this.securityParameters.cipherSuite = selectedCipherSuite;
+ this.securityParameters.compressionAlgorithm = selectedCompressionMethod;
+
+ if (sessionServerExtensions != null)
+ {
+ /*
+ * draft-ietf-tls-encrypt-then-mac-03 3. If a server receives an encrypt-then-MAC
+ * request extension from a client and then selects a stream or AEAD cipher suite, it
+ * MUST NOT send an encrypt-then-MAC response extension back to the client.
+ */
+ boolean serverSentEncryptThenMAC = TlsExtensionsUtils.hasEncryptThenMACExtension(sessionServerExtensions);
+ if (serverSentEncryptThenMAC && !TlsUtils.isBlockCipherSuite(selectedCipherSuite))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ this.securityParameters.encryptThenMAC = serverSentEncryptThenMAC;
+
+ 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)
+ {
+ this.tlsClient.processServerExtensions(sessionServerExtensions);
+ }
+ }
+
+ protected void sendCertificateVerifyMessage(DigitallySigned certificateVerify)
+ throws IOException
+ {
+ HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate_verify);
+
+ certificateVerify.encode(message);
+
+ message.writeToRecordStream();
+ }
+
+ protected void sendClientHelloMessage()
+ throws IOException
+ {
+ this.recordStream.setWriteVersion(this.tlsClient.getClientHelloRecordLayerVersion());
+
+ ProtocolVersion client_version = this.tlsClient.getClientVersion();
+ if (client_version.isDTLS())
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ getContext().setClientVersion(client_version);
+
+ /*
+ * 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();
+
+ 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)
+ {
+ /*
+ * RFC 5746 3.4. The client MUST include either an empty "renegotiation_info" extension,
+ * or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling cipher suite value in the
+ * ClientHello. Including both is NOT RECOMMENDED.
+ */
+ byte[] renegExtData = TlsUtils.getExtensionData(clientExtensions, EXT_RenegotiationInfo);
+ boolean noRenegExt = (null == renegExtData);
+
+ boolean noSCSV = !Arrays.contains(offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
+
+ if (noRenegExt && noSCSV)
+ {
+ // 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);
+ }
+
+ TlsUtils.writeUint16ArrayWithUint16Length(offeredCipherSuites, message);
+ }
+
+ TlsUtils.writeUint8ArrayWithUint8Length(offeredCompressionMethods, message);
+
+ if (clientExtensions != null)
+ {
+ writeExtensions(message, clientExtensions);
+ }
+
+ message.writeToRecordStream();
+ }
+
+ protected void sendClientKeyExchangeMessage()
+ throws IOException
+ {
+ HandshakeMessage message = new HandshakeMessage(HandshakeType.client_key_exchange);
+
+ this.keyExchange.generateClientKeyExchange(message);
+
+ message.writeToRecordStream();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsCompression.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsCompression.java
new file mode 100644
index 00000000..e6d475ce
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsCompression.java
@@ -0,0 +1,10 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.OutputStream;
+
+public interface TlsCompression
+{
+ OutputStream compress(OutputStream output);
+
+ OutputStream decompress(OutputStream output);
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsContext.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsContext.java
new file mode 100644
index 00000000..a47d1d6e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsContext.java
@@ -0,0 +1,45 @@
+package org.spongycastle.crypto.tls;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.prng.RandomGenerator;
+
+public interface TlsContext
+{
+ RandomGenerator getNonceRandomGenerator();
+
+ SecureRandom getSecureRandom();
+
+ SecurityParameters getSecurityParameters();
+
+ boolean isServer();
+
+ ProtocolVersion getClientVersion();
+
+ 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 TlsPeer#notifyHandshakeComplete()
+ */
+ TlsSession getResumableSession();
+
+ Object getUserObject();
+
+ void setUserObject(Object userObject);
+
+ /**
+ * Export keying material according to RFC 5705: "Keying Material Exporters for TLS".
+ *
+ * @param asciiLabel indicates which application will use the exported keys.
+ * @param context_value allows the application using the exporter to mix its own data with the TLS PRF for
+ * the exporter output.
+ * @param length the number of bytes to generate
+ * @return a pseudorandom bit string of 'length' bytes generated from the master_secret.
+ */
+ byte[] exportKeyingMaterial(String asciiLabel, byte[] context_value, int length);
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsCredentials.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsCredentials.java
new file mode 100644
index 00000000..26923394
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsCredentials.java
@@ -0,0 +1,6 @@
+package org.spongycastle.crypto.tls;
+
+public interface TlsCredentials
+{
+ Certificate getCertificate();
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsDHEKeyExchange.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsDHEKeyExchange.java
new file mode 100644
index 00000000..fa4bd98f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsDHEKeyExchange.java
@@ -0,0 +1,115 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Vector;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.Signer;
+import org.spongycastle.crypto.params.DHParameters;
+import org.spongycastle.util.io.TeeInputStream;
+
+public class TlsDHEKeyExchange
+ extends TlsDHKeyExchange
+{
+ protected TlsSignerCredentials serverCredentials = null;
+
+ public TlsDHEKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms, DHParameters dhParameters)
+ {
+ super(keyExchange, supportedSignatureAlgorithms, dhParameters);
+ }
+
+ public void processServerCredentials(TlsCredentials serverCredentials)
+ throws IOException
+ {
+ if (!(serverCredentials instanceof TlsSignerCredentials))
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ processServerCertificate(serverCredentials.getCertificate());
+
+ this.serverCredentials = (TlsSignerCredentials)serverCredentials;
+ }
+
+ public byte[] generateServerKeyExchange()
+ throws IOException
+ {
+ if (this.dhParameters == null)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ DigestInputBuffer buf = new DigestInputBuffer();
+
+ this.dhAgreeServerPrivateKey = TlsDHUtils.generateEphemeralServerKeyExchange(context.getSecureRandom(),
+ this.dhParameters, 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);
+ }
+
+ d = TlsUtils.createHash(signatureAndHashAlgorithm.getHash());
+ }
+ else
+ {
+ signatureAndHashAlgorithm = null;
+ d = new CombinedHash();
+ }
+
+ SecurityParameters securityParameters = context.getSecurityParameters();
+ d.update(securityParameters.clientRandom, 0, securityParameters.clientRandom.length);
+ d.update(securityParameters.serverRandom, 0, securityParameters.serverRandom.length);
+ buf.updateDigest(d);
+
+ byte[] hash = new byte[d.getDigestSize()];
+ d.doFinal(hash, 0);
+
+ byte[] signature = serverCredentials.generateCertificateSignature(hash);
+
+ DigitallySigned signed_params = new DigitallySigned(signatureAndHashAlgorithm, signature);
+ signed_params.encode(buf);
+
+ return buf.toByteArray();
+ }
+
+ public void processServerKeyExchange(InputStream input)
+ throws IOException
+ {
+ SecurityParameters securityParameters = context.getSecurityParameters();
+
+ SignerInputBuffer buf = new SignerInputBuffer();
+ InputStream teeIn = new TeeInputStream(input, buf);
+
+ ServerDHParams params = ServerDHParams.parse(teeIn);
+
+ DigitallySigned signed_params = DigitallySigned.parse(context, input);
+
+ 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 = TlsDHUtils.validateDHPublicKey(params.getPublicKey());
+ }
+
+ protected Signer initVerifyer(TlsSigner tlsSigner, SignatureAndHashAlgorithm algorithm, SecurityParameters securityParameters)
+ {
+ 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/core/src/main/java/org/spongycastle/crypto/tls/TlsDHKeyExchange.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsDHKeyExchange.java
new file mode 100644
index 00000000..b4948d9d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsDHKeyExchange.java
@@ -0,0 +1,208 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.util.Vector;
+
+import org.spongycastle.asn1.x509.KeyUsage;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.DHParameters;
+import org.spongycastle.crypto.params.DHPrivateKeyParameters;
+import org.spongycastle.crypto.params.DHPublicKeyParameters;
+import org.spongycastle.crypto.util.PublicKeyFactory;
+
+/**
+ * TLS 1.0/1.1 DH key exchange.
+ */
+public class TlsDHKeyExchange
+ extends AbstractTlsKeyExchange
+{
+ protected static final BigInteger ONE = BigInteger.valueOf(1);
+ protected static final BigInteger TWO = BigInteger.valueOf(2);
+
+ protected TlsSigner tlsSigner;
+ protected DHParameters dhParameters;
+
+ protected AsymmetricKeyParameter serverPublicKey;
+ protected DHPublicKeyParameters dhAgreeServerPublicKey;
+ 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)
+ {
+ case KeyExchangeAlgorithm.DH_RSA:
+ case KeyExchangeAlgorithm.DH_DSS:
+ this.tlsSigner = null;
+ break;
+ case KeyExchangeAlgorithm.DHE_RSA:
+ this.tlsSigner = new TlsRSASigner();
+ break;
+ case KeyExchangeAlgorithm.DHE_DSS:
+ this.tlsSigner = new TlsDSSSigner();
+ break;
+ default:
+ throw new IllegalArgumentException("unsupported key exchange algorithm");
+ }
+
+ this.dhParameters = dhParameters;
+ }
+
+ public void init(TlsContext context)
+ {
+ super.init(context);
+
+ if (this.tlsSigner != null)
+ {
+ this.tlsSigner.init(context);
+ }
+ }
+
+ public void skipServerCredentials()
+ throws IOException
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ public void processServerCertificate(Certificate serverCertificate)
+ throws IOException
+ {
+ if (serverCertificate.isEmpty())
+ {
+ throw new TlsFatalAlert(AlertDescription.bad_certificate);
+ }
+
+ org.spongycastle.asn1.x509.Certificate x509Cert = serverCertificate.getCertificateAt(0);
+
+ SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo();
+ try
+ {
+ this.serverPublicKey = PublicKeyFactory.createKey(keyInfo);
+ }
+ catch (RuntimeException e)
+ {
+ throw new TlsFatalAlert(AlertDescription.unsupported_certificate);
+ }
+
+ if (tlsSigner == null)
+ {
+ try
+ {
+ this.dhAgreeServerPublicKey = TlsDHUtils.validateDHPublicKey((DHPublicKeyParameters)this.serverPublicKey);
+ }
+ catch (ClassCastException e)
+ {
+ throw new TlsFatalAlert(AlertDescription.certificate_unknown);
+ }
+
+ TlsUtils.validateKeyUsage(x509Cert, KeyUsage.keyAgreement);
+ }
+ else
+ {
+ if (!tlsSigner.isValidPublicKey(this.serverPublicKey))
+ {
+ throw new TlsFatalAlert(AlertDescription.certificate_unknown);
+ }
+
+ TlsUtils.validateKeyUsage(x509Cert, KeyUsage.digitalSignature);
+ }
+
+ super.processServerCertificate(serverCertificate);
+ }
+
+ public boolean requiresServerKeyExchange()
+ {
+ switch (keyExchange)
+ {
+ case KeyExchangeAlgorithm.DHE_DSS:
+ case KeyExchangeAlgorithm.DHE_RSA:
+ case KeyExchangeAlgorithm.DH_anon:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public void validateCertificateRequest(CertificateRequest certificateRequest)
+ throws IOException
+ {
+ short[] types = certificateRequest.getCertificateTypes();
+ for (int i = 0; i < types.length; ++i)
+ {
+ switch (types[i])
+ {
+ case ClientCertificateType.rsa_sign:
+ case ClientCertificateType.dss_sign:
+ case ClientCertificateType.rsa_fixed_dh:
+ case ClientCertificateType.dss_fixed_dh:
+ case ClientCertificateType.ecdsa_sign:
+ break;
+ default:
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+ }
+
+ public void processClientCredentials(TlsCredentials clientCredentials)
+ throws IOException
+ {
+ if (clientCredentials instanceof TlsAgreementCredentials)
+ {
+ // TODO Validate client cert has matching parameters (see 'areCompatibleParameters')?
+
+ this.agreementCredentials = (TlsAgreementCredentials)clientCredentials;
+ }
+ else if (clientCredentials instanceof TlsSignerCredentials)
+ {
+ // OK
+ }
+ else
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public void generateClientKeyExchange(OutputStream output)
+ throws IOException
+ {
+ /*
+ * RFC 2246 7.4.7.2 If the client certificate already contains a suitable Diffie-Hellman
+ * key, then Yc is implicit and does not need to be sent again. In this case, the Client Key
+ * Exchange message will be sent, but will be empty.
+ */
+ if (agreementCredentials == null)
+ {
+ this.dhAgreeClientPrivateKey = TlsDHUtils.generateEphemeralClientKeyExchange(context.getSecureRandom(),
+ dhAgreeServerPublicKey.getParameters(), output);
+ }
+ }
+
+ public byte[] generatePremasterSecret()
+ throws IOException
+ {
+ if (agreementCredentials != null)
+ {
+ return agreementCredentials.generateAgreement(dhAgreeServerPublicKey);
+ }
+
+ if (dhAgreeServerPrivateKey != null)
+ {
+ return TlsDHUtils.calculateDHBasicAgreement(dhAgreeClientPublicKey, dhAgreeServerPrivateKey);
+ }
+
+ if (dhAgreeClientPrivateKey != null)
+ {
+ return TlsDHUtils.calculateDHBasicAgreement(dhAgreeServerPublicKey, dhAgreeClientPrivateKey);
+ }
+
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsDHUtils.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsDHUtils.java
new file mode 100644
index 00000000..9a7a2218
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsDHUtils.java
@@ -0,0 +1,105 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.agreement.DHBasicAgreement;
+import org.spongycastle.crypto.generators.DHBasicKeyPairGenerator;
+import org.spongycastle.crypto.params.DHKeyGenerationParameters;
+import org.spongycastle.crypto.params.DHParameters;
+import org.spongycastle.crypto.params.DHPrivateKeyParameters;
+import org.spongycastle.crypto.params.DHPublicKeyParameters;
+import org.spongycastle.util.BigIntegers;
+
+public class TlsDHUtils
+{
+ static final BigInteger ONE = BigInteger.valueOf(1);
+ static final BigInteger TWO = BigInteger.valueOf(2);
+
+ 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);
+
+ /*
+ * RFC 5246 8.1.2. Leading bytes of Z that contain all zero bits are stripped before it is
+ * used as the pre_master_secret.
+ */
+ return BigIntegers.asUnsignedByteArray(agreementValue);
+ }
+
+ 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
+ {
+ AsymmetricCipherKeyPair kp = generateDHKeyPair(random, dhParams);
+
+ DHPublicKeyParameters dh_public = (DHPublicKeyParameters) kp.getPublic();
+ writeDHParameter(dh_public.getY(), output);
+
+ return (DHPrivateKeyParameters) kp.getPrivate();
+ }
+
+ public static DHPrivateKeyParameters generateEphemeralServerKeyExchange(SecureRandom random, DHParameters dhParams,
+ OutputStream output) throws IOException
+ {
+ AsymmetricCipherKeyPair kp = TlsDHUtils.generateDHKeyPair(random, dhParams);
+
+ DHPublicKeyParameters dhPublicKey = (DHPublicKeyParameters)kp.getPublic();
+ ServerDHParams params = new ServerDHParams(dhPublicKey);
+ params.encode(output);
+
+ return (DHPrivateKeyParameters)kp.getPrivate();
+ }
+
+ public static DHPublicKeyParameters validateDHPublicKey(DHPublicKeyParameters key) throws IOException
+ {
+ BigInteger Y = key.getY();
+ DHParameters params = key.getParameters();
+ BigInteger p = params.getP();
+ BigInteger g = params.getG();
+
+ if (!p.isProbablePrime(2))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ if (g.compareTo(TWO) < 0 || g.compareTo(p.subtract(TWO)) > 0)
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ if (Y.compareTo(TWO) < 0 || Y.compareTo(p.subtract(ONE)) > 0)
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ // TODO See RFC 2631 for more discussion of Diffie-Hellman validation
+
+ return key;
+ }
+
+ 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
+ {
+ TlsUtils.writeOpaque16(BigIntegers.asUnsignedByteArray(x), output);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsDSASigner.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsDSASigner.java
new file mode 100644
index 00000000..ef4a8e47
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsDSASigner.java
@@ -0,0 +1,92 @@
+package org.spongycastle.crypto.tls;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.DSA;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.Signer;
+import org.spongycastle.crypto.digests.NullDigest;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.signers.DSADigestSigner;
+
+public abstract class TlsDSASigner
+ extends AbstractTlsSigner
+{
+ public byte[] generateRawSignature(SignatureAndHashAlgorithm algorithm,
+ AsymmetricKeyParameter privateKey, byte[] hash)
+ throws CryptoException
+ {
+ Signer signer = makeSigner(algorithm, true, true,
+ new ParametersWithRandom(privateKey, this.context.getSecureRandom()));
+ 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(SignatureAndHashAlgorithm algorithm, byte[] sigBytes,
+ AsymmetricKeyParameter publicKey, byte[] hash)
+ throws CryptoException
+ {
+ 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(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter privateKey)
+ {
+ return makeSigner(algorithm, false, true, privateKey);
+ }
+
+ public Signer createVerifyer(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter publicKey)
+ {
+ return makeSigner(algorithm, false, false, publicKey);
+ }
+
+ protected CipherParameters makeInitParameters(boolean forSigning, CipherParameters cp)
+ {
+ return cp;
+ }
+
+ protected Signer makeSigner(SignatureAndHashAlgorithm algorithm, boolean raw, boolean forSigning,
+ CipherParameters cp)
+ {
+ if ((algorithm != null) != TlsUtils.isTLSv12(context))
+ {
+ throw new IllegalStateException();
+ }
+
+ // TODO For TLS 1.2+, lift the SHA-1 restriction here
+ if (algorithm != null
+ && (algorithm.getHash() != HashAlgorithm.sha1 || algorithm.getSignature() != getSignatureAlgorithm()))
+ {
+ throw new IllegalStateException();
+ }
+
+ short hashAlgorithm = algorithm == null ? HashAlgorithm.sha1 : algorithm.getHash();
+ Digest d = raw ? new NullDigest() : TlsUtils.createHash(hashAlgorithm);
+
+ Signer s = new DSADigestSigner(createDSAImpl(hashAlgorithm), d);
+ s.init(forSigning, makeInitParameters(forSigning, cp));
+ return s;
+ }
+
+ protected abstract short getSignatureAlgorithm();
+
+ protected abstract DSA createDSAImpl(short hashAlgorithm);
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsDSSSigner.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsDSSSigner.java
new file mode 100644
index 00000000..bc26c036
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsDSSSigner.java
@@ -0,0 +1,26 @@
+package org.spongycastle.crypto.tls;
+
+import org.spongycastle.crypto.DSA;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.DSAPublicKeyParameters;
+import org.spongycastle.crypto.signers.DSASigner;
+import org.spongycastle.crypto.signers.HMacDSAKCalculator;
+
+public class TlsDSSSigner
+ extends TlsDSASigner
+{
+ public boolean isValidPublicKey(AsymmetricKeyParameter publicKey)
+ {
+ return publicKey instanceof DSAPublicKeyParameters;
+ }
+
+ protected DSA createDSAImpl(short hashAlgorithm)
+ {
+ return new DSASigner(new HMacDSAKCalculator(TlsUtils.createHash(hashAlgorithm)));
+ }
+
+ protected short getSignatureAlgorithm()
+ {
+ return SignatureAlgorithm.dsa;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsECCUtils.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsECCUtils.java
new file mode 100644
index 00000000..5f9adffb
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsECCUtils.java
@@ -0,0 +1,690 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.Hashtable;
+
+import org.spongycastle.asn1.x9.ECNamedCurveTable;
+import org.spongycastle.asn1.x9.X9ECParameters;
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.agreement.ECDHBasicAgreement;
+import org.spongycastle.crypto.ec.CustomNamedCurves;
+import org.spongycastle.crypto.generators.ECKeyPairGenerator;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECKeyGenerationParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.math.ec.ECAlgorithms;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.field.PolynomialExtensionField;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.BigIntegers;
+import org.spongycastle.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",
+ "sect193r2", "sect233k1", "sect233r1", "sect239k1", "sect283k1", "sect283r1", "sect409k1", "sect409r1",
+ "sect571k1", "sect571r1", "secp160k1", "secp160r1", "secp160r2", "secp192k1", "secp192r1", "secp224k1",
+ "secp224r1", "secp256k1", "secp256r1", "secp384r1", "secp521r1",
+ "brainpoolP256r1", "brainpoolP384r1", "brainpoolP512r1"};
+
+ 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
+ {
+ byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_elliptic_curves);
+ return extensionData == null ? null : readSupportedEllipticCurvesExtension(extensionData);
+ }
+
+ public static short[] getSupportedPointFormatsExtension(Hashtable extensions) throws IOException
+ {
+ byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_ec_point_formats);
+ return extensionData == null ? null : readSupportedPointFormatsExtension(extensionData);
+ }
+
+ public static byte[] createSupportedEllipticCurvesExtension(int[] namedCurves) throws IOException
+ {
+ if (namedCurves == null || namedCurves.length < 1)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ return TlsUtils.encodeUint16ArrayWithUint16Length(namedCurves);
+ }
+
+ public static byte[] createSupportedPointFormatsExtension(short[] ecPointFormats) throws IOException
+ {
+ if (ecPointFormats == null || !Arrays.contains(ecPointFormats, ECPointFormat.uncompressed))
+ {
+ /*
+ * RFC 4492 5.1. If the Supported Point Formats Extension is indeed sent, it MUST
+ * contain the value 0 (uncompressed) as one of the items in the list of point formats.
+ */
+
+ // NOTE: We add it at the end (lowest preference)
+ ecPointFormats = Arrays.append(ecPointFormats, ECPointFormat.uncompressed);
+ }
+
+ return TlsUtils.encodeUint8ArrayWithUint8Length(ecPointFormats);
+ }
+
+ public static int[] readSupportedEllipticCurvesExtension(byte[] extensionData) throws IOException
+ {
+ if (extensionData == null)
+ {
+ throw new IllegalArgumentException("'extensionData' cannot be null");
+ }
+
+ ByteArrayInputStream buf = new ByteArrayInputStream(extensionData);
+
+ int length = TlsUtils.readUint16(buf);
+ if (length < 2 || (length & 1) != 0)
+ {
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+
+ int[] namedCurves = TlsUtils.readUint16Array(length / 2, buf);
+
+ TlsProtocol.assertEmpty(buf);
+
+ return namedCurves;
+ }
+
+ public static short[] readSupportedPointFormatsExtension(byte[] extensionData) throws IOException
+ {
+ if (extensionData == null)
+ {
+ throw new IllegalArgumentException("'extensionData' cannot be null");
+ }
+
+ ByteArrayInputStream buf = new ByteArrayInputStream(extensionData);
+
+ short length = TlsUtils.readUint8(buf);
+ if (length < 1)
+ {
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+
+ short[] ecPointFormats = TlsUtils.readUint8Array(length, buf);
+
+ TlsProtocol.assertEmpty(buf);
+
+ if (!Arrays.contains(ecPointFormats, ECPointFormat.uncompressed))
+ {
+ /*
+ * RFC 4492 5.1. If the Supported Point Formats Extension is indeed sent, it MUST
+ * contain the value 0 (uncompressed) as one of the items in the list of point formats.
+ */
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ return ecPointFormats;
+ }
+
+ public static String getNameOfNamedCurve(int namedCurve)
+ {
+ return isSupportedNamedCurve(namedCurve) ? curveNames[namedCurve - 1] : null;
+ }
+
+ public static ECDomainParameters getParametersForNamedCurve(int namedCurve)
+ {
+ String curveName = getNameOfNamedCurve(namedCurve);
+ if (curveName == null)
+ {
+ return null;
+ }
+
+ // Parameters are lazily created the first time a particular curve is accessed
+
+ X9ECParameters ecP = CustomNamedCurves.getByName(curveName);
+ if (ecP == null)
+ {
+ ecP = ECNamedCurveTable.getByName(curveName);
+ if (ecP == null)
+ {
+ return null;
+ }
+ }
+
+ // It's a bit inefficient to do this conversion every time
+ return new ECDomainParameters(ecP.getCurve(), ecP.getG(), ecP.getN(), ecP.getH(), ecP.getSeed());
+ }
+
+ public static boolean hasAnySupportedNamedCurves()
+ {
+ return curveNames.length > 0;
+ }
+
+ public static boolean containsECCCipherSuites(int[] cipherSuites)
+ {
+ for (int i = 0; i < cipherSuites.length; ++i)
+ {
+ if (isECCCipherSuite(cipherSuites[i]))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static boolean isECCCipherSuite(int cipherSuite)
+ {
+ 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:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDH_anon_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDH_anon_WITH_RC4_128_SHA:
+ 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:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+ 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:
+
+ /*
+ * RFC 6367
+ */
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+
+ case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+
+ /*
+ * draft-agl-tls-chacha20poly1305-04
+ */
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+
+ /*
+ * draft-josefsson-salsa20-tls-04
+ */
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1:
+
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ public static boolean areOnSameCurve(ECDomainParameters a, ECDomainParameters b)
+ {
+ // TODO Move to ECDomainParameters.equals() or other utility method?
+ return a.getCurve().equals(b.getCurve()) && a.getG().equals(b.getG()) && a.getN().equals(b.getN())
+ && a.getH().equals(b.getH());
+ }
+
+ public static boolean isSupportedNamedCurve(int namedCurve)
+ {
+ return (namedCurve > 0 && namedCurve <= curveNames.length);
+ }
+
+ public static boolean isCompressionPreferred(short[] ecPointFormats, short compressionFormat)
+ {
+ if (ecPointFormats == null)
+ {
+ return false;
+ }
+ for (int i = 0; i < ecPointFormats.length; ++i)
+ {
+ short ecPointFormat = ecPointFormats[i];
+ if (ecPointFormat == ECPointFormat.uncompressed)
+ {
+ return false;
+ }
+ if (ecPointFormat == compressionFormat)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static byte[] serializeECFieldElement(int fieldSize, BigInteger x) throws IOException
+ {
+ return BigIntegers.asUnsignedByteArray((fieldSize + 7) / 8, x);
+ }
+
+ public static byte[] serializeECPoint(short[] ecPointFormats, ECPoint point) throws IOException
+ {
+ ECCurve curve = point.getCurve();
+
+ /*
+ * RFC 4492 5.7. ...an elliptic curve point in uncompressed or compressed format. Here, the
+ * format MUST conform to what the server has requested through a Supported Point Formats
+ * Extension if this extension was used, and MUST be uncompressed if this extension was not
+ * used.
+ */
+ boolean compressed = false;
+ if (ECAlgorithms.isFpCurve(curve))
+ {
+ compressed = isCompressionPreferred(ecPointFormats, ECPointFormat.ansiX962_compressed_prime);
+ }
+ else if (ECAlgorithms.isF2mCurve(curve))
+ {
+ compressed = isCompressionPreferred(ecPointFormats, ECPointFormat.ansiX962_compressed_char2);
+ }
+ return point.getEncoded(compressed);
+ }
+
+ 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
+ {
+ int requiredLength = (fieldSize + 7) / 8;
+ if (encoding.length != requiredLength)
+ {
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+ return new BigInteger(1, encoding);
+ }
+
+ public static ECPoint deserializeECPoint(short[] ecPointFormats, ECCurve curve, byte[] encoding) throws IOException
+ {
+ if (encoding == null || encoding.length < 1)
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ short actualFormat;
+ switch (encoding[0])
+ {
+ case 0x02: // compressed
+ case 0x03: // compressed
+ {
+ if (ECAlgorithms.isF2mCurve(curve))
+ {
+ actualFormat = ECPointFormat.ansiX962_compressed_char2;
+ }
+ else if (ECAlgorithms.isFpCurve(curve))
+ {
+ actualFormat = ECPointFormat.ansiX962_compressed_prime;
+ }
+ else
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ break;
+ }
+ case 0x04: // uncompressed
+ {
+ actualFormat = ECPointFormat.uncompressed;
+ break;
+ }
+ case 0x00: // infinity
+ case 0x06: // hybrid
+ case 0x07: // hybrid
+ default:
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ if (!Arrays.contains(ecPointFormats, actualFormat))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ return curve.decodePoint(encoding);
+ }
+
+ public static ECPublicKeyParameters deserializeECPublicKey(short[] ecPointFormats, ECDomainParameters curve_params,
+ byte[] encoding) throws IOException
+ {
+ try
+ {
+ ECPoint Y = deserializeECPoint(ecPointFormats, curve_params.getCurve(), encoding);
+ return new ECPublicKeyParameters(Y, curve_params);
+ }
+ catch (RuntimeException e)
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+
+ public static byte[] calculateECDHBasicAgreement(ECPublicKeyParameters publicKey, ECPrivateKeyParameters privateKey)
+ {
+ ECDHBasicAgreement basicAgreement = new ECDHBasicAgreement();
+ basicAgreement.init(privateKey);
+ BigInteger agreementValue = basicAgreement.calculateAgreement(publicKey);
+
+ /*
+ * RFC 4492 5.10. Note that this octet string (Z in IEEE 1363 terminology) as output by
+ * FE2OSP, the Field Element to Octet String Conversion Primitive, has constant length for
+ * any given field; leading zeros found in this octet string MUST NOT be truncated.
+ */
+ return BigIntegers.asUnsignedByteArray(basicAgreement.getFieldSize(), agreementValue);
+ }
+
+ public static AsymmetricCipherKeyPair generateECKeyPair(SecureRandom random, ECDomainParameters ecParams)
+ {
+ ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
+ keyPairGenerator.init(new ECKeyGenerationParameters(ecParams, random));
+ return keyPairGenerator.generateKeyPair();
+ }
+
+ public static ECPrivateKeyParameters generateEphemeralClientKeyExchange(SecureRandom random, short[] ecPointFormats,
+ ECDomainParameters ecParams, OutputStream output) throws IOException
+ {
+ AsymmetricCipherKeyPair kp = 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
+ {
+ BigInteger K = readECParameter(input);
+ if (K.bitLength() < 32)
+ {
+ int k = K.intValue();
+ if (k > 0 && k < fieldSize)
+ {
+ return k;
+ }
+ }
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ public static BigInteger readECFieldElement(int fieldSize, InputStream input) throws IOException
+ {
+ return deserializeECFieldElement(fieldSize, TlsUtils.readOpaque8(input));
+ }
+
+ public static BigInteger readECParameter(InputStream input) throws IOException
+ {
+ // TODO Are leading zeroes okay here?
+ return new BigInteger(1, TlsUtils.readOpaque8(input));
+ }
+
+ public static ECDomainParameters readECParameters(int[] namedCurves, short[] ecPointFormats, InputStream input)
+ throws IOException
+ {
+ try
+ {
+ short curveType = TlsUtils.readUint8(input);
+
+ switch (curveType)
+ {
+ 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);
+ byte[] baseEncoding = TlsUtils.readOpaque8(input);
+ BigInteger order = readECParameter(input);
+ BigInteger cofactor = readECParameter(input);
+ ECCurve curve = new ECCurve.Fp(prime_p, a, b, order, cofactor);
+ ECPoint base = deserializeECPoint(ecPointFormats, curve, baseEncoding);
+ return new ECDomainParameters(curve, base, order, cofactor);
+ }
+ case ECCurveType.explicit_char2:
+ {
+ checkNamedCurve(namedCurves, NamedCurve.arbitrary_explicit_char2_curves);
+
+ int m = TlsUtils.readUint16(input);
+ short basis = TlsUtils.readUint8(input);
+ if (!ECBasisType.isValid(basis))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ int k1 = readECExponent(m, input), k2 = -1, k3 = -1;
+ if (basis == ECBasisType.ec_basis_pentanomial)
+ {
+ k2 = readECExponent(m, input);
+ k3 = readECExponent(m, input);
+ }
+
+ BigInteger a = readECFieldElement(m, input);
+ BigInteger b = readECFieldElement(m, input);
+ byte[] baseEncoding = TlsUtils.readOpaque8(input);
+ BigInteger order = readECParameter(input);
+ BigInteger cofactor = readECParameter(input);
+
+ ECCurve curve = (basis == ECBasisType.ec_basis_pentanomial)
+ ? new ECCurve.F2m(m, k1, k2, k3, a, b, order, cofactor)
+ : new ECCurve.F2m(m, k1, a, b, order, cofactor);
+
+ ECPoint base = deserializeECPoint(ecPointFormats, curve, baseEncoding);
+
+ return new ECDomainParameters(curve, base, order, cofactor);
+ }
+ case ECCurveType.named_curve:
+ {
+ int namedCurve = TlsUtils.readUint16(input);
+ if (!NamedCurve.refersToASpecificNamedCurve(namedCurve))
+ {
+ /*
+ * RFC 4492 5.4. All those values of NamedCurve are allowed that refer to a
+ * specific curve. Values of NamedCurve that indicate support for a class of
+ * explicitly defined curves are not allowed here [...].
+ */
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ checkNamedCurve(namedCurves, namedCurve);
+
+ return getParametersForNamedCurve(namedCurve);
+ }
+ default:
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+ catch (RuntimeException e)
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+
+ 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(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
+ {
+ TlsUtils.writeOpaque8(BigIntegers.asUnsignedByteArray(x), output);
+ }
+
+ public static void writeExplicitECParameters(short[] ecPointFormats, ECDomainParameters ecParameters,
+ OutputStream output) throws IOException
+ {
+ ECCurve curve = ecParameters.getCurve();
+
+ if (ECAlgorithms.isFpCurve(curve))
+ {
+ TlsUtils.writeUint8(ECCurveType.explicit_prime, output);
+
+ writeECParameter(curve.getField().getCharacteristic(), output);
+ }
+ else if (ECAlgorithms.isF2mCurve(curve))
+ {
+ PolynomialExtensionField field = (PolynomialExtensionField)curve.getField();
+ int[] exponents = field.getMinimalPolynomial().getExponentsPresent();
+
+ TlsUtils.writeUint8(ECCurveType.explicit_char2, output);
+
+ int m = exponents[exponents.length - 1];
+ TlsUtils.checkUint16(m);
+ TlsUtils.writeUint16(m, output);
+
+ if (exponents.length == 3)
+ {
+ TlsUtils.writeUint8(ECBasisType.ec_basis_trinomial, output);
+ writeECExponent(exponents[1], output);
+ }
+ else if (exponents.length == 5)
+ {
+ TlsUtils.writeUint8(ECBasisType.ec_basis_pentanomial, output);
+ writeECExponent(exponents[1], output);
+ writeECExponent(exponents[2], output);
+ writeECExponent(exponents[3], output);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Only trinomial and pentomial curves are supported");
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("'ecParameters' not a known curve type");
+ }
+
+ 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 writeECPoint(short[] ecPointFormats, ECPoint point, OutputStream output) throws IOException
+ {
+ TlsUtils.writeOpaque8(serializeECPoint(ecPointFormats, point), output);
+ }
+
+ public static void writeNamedECParameters(int namedCurve, OutputStream output) throws IOException
+ {
+ if (!NamedCurve.refersToASpecificNamedCurve(namedCurve))
+ {
+ /*
+ * RFC 4492 5.4. All those values of NamedCurve are allowed that refer to a specific
+ * curve. Values of NamedCurve that indicate support for a class of explicitly defined
+ * curves are not allowed here [...].
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ TlsUtils.writeUint8(ECCurveType.named_curve, output);
+ TlsUtils.checkUint16(namedCurve);
+ TlsUtils.writeUint16(namedCurve, output);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsECDHEKeyExchange.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsECDHEKeyExchange.java
new file mode 100644
index 00000000..d159368d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsECDHEKeyExchange.java
@@ -0,0 +1,221 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Vector;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.Signer;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.io.TeeInputStream;
+
+/**
+ * ECDHE key exchange (see RFC 4492)
+ */
+public class TlsECDHEKeyExchange
+ extends TlsECDHKeyExchange
+{
+ protected TlsSignerCredentials serverCredentials = null;
+
+ public TlsECDHEKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms, int[] namedCurves,
+ short[] clientECPointFormats, short[] serverECPointFormats)
+ {
+ super(keyExchange, supportedSignatureAlgorithms, namedCurves, clientECPointFormats, serverECPointFormats);
+ }
+
+ public void processServerCredentials(TlsCredentials serverCredentials)
+ throws IOException
+ {
+ if (!(serverCredentials instanceof TlsSignerCredentials))
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ processServerCertificate(serverCredentials.getCertificate());
+
+ this.serverCredentials = (TlsSignerCredentials)serverCredentials;
+ }
+
+ 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
+ {
+ for (int i = 0; i < namedCurves.length; ++i)
+ {
+ int entry = namedCurves[i];
+ if (NamedCurve.isValid(entry) && TlsECCUtils.isSupportedNamedCurve(entry))
+ {
+ namedCurve = entry;
+ break;
+ }
+ }
+ }
+
+ ECDomainParameters curve_params = null;
+ if (namedCurve >= 0)
+ {
+ curve_params = TlsECCUtils.getParametersForNamedCurve(namedCurve);
+ }
+ else
+ {
+ /*
+ * If no named curves are suitable, check if the client supports explicit curves.
+ */
+ if (Arrays.contains(namedCurves, NamedCurve.arbitrary_explicit_prime_curves))
+ {
+ curve_params = TlsECCUtils.getParametersForNamedCurve(NamedCurve.secp256r1);
+ }
+ else if (Arrays.contains(namedCurves, NamedCurve.arbitrary_explicit_char2_curves))
+ {
+ curve_params = TlsECCUtils.getParametersForNamedCurve(NamedCurve.sect283r1);
+ }
+ }
+
+ if (curve_params == null)
+ {
+ /*
+ * NOTE: We shouldn't have negotiated ECDHE key exchange since we apparently can't find
+ * a suitable curve.
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ AsymmetricCipherKeyPair kp = TlsECCUtils.generateECKeyPair(context.getSecureRandom(), curve_params);
+ this.ecAgreePrivateKey = (ECPrivateKeyParameters)kp.getPrivate();
+
+ DigestInputBuffer buf = new DigestInputBuffer();
+
+ if (namedCurve < 0)
+ {
+ TlsECCUtils.writeExplicitECParameters(clientECPointFormats, curve_params, buf);
+ }
+ else
+ {
+ TlsECCUtils.writeNamedECParameters(namedCurve, 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);
+ }
+
+ d = TlsUtils.createHash(signatureAndHashAlgorithm.getHash());
+ }
+ else
+ {
+ signatureAndHashAlgorithm = null;
+ d = new CombinedHash();
+ }
+
+ SecurityParameters securityParameters = context.getSecurityParameters();
+ d.update(securityParameters.clientRandom, 0, securityParameters.clientRandom.length);
+ d.update(securityParameters.serverRandom, 0, securityParameters.serverRandom.length);
+ buf.updateDigest(d);
+
+ byte[] hash = new byte[d.getDigestSize()];
+ d.doFinal(hash, 0);
+
+ byte[] signature = serverCredentials.generateCertificateSignature(hash);
+
+ DigitallySigned signed_params = new DigitallySigned(signatureAndHashAlgorithm, signature);
+ signed_params.encode(buf);
+
+ return buf.toByteArray();
+ }
+
+ public void processServerKeyExchange(InputStream input)
+ throws IOException
+ {
+ SecurityParameters securityParameters = context.getSecurityParameters();
+
+ SignerInputBuffer buf = new SignerInputBuffer();
+ InputStream teeIn = new TeeInputStream(input, buf);
+
+ ECDomainParameters curve_params = TlsECCUtils.readECParameters(namedCurves, clientECPointFormats, teeIn);
+
+ byte[] point = TlsUtils.readOpaque8(teeIn);
+
+ DigitallySigned signed_params = DigitallySigned.parse(context, input);
+
+ Signer signer = initVerifyer(tlsSigner, signed_params.getAlgorithm(), securityParameters);
+ buf.updateSigner(signer);
+ if (!signer.verifySignature(signed_params.getSignature()))
+ {
+ throw new TlsFatalAlert(AlertDescription.decrypt_error);
+ }
+
+ this.ecAgreePublicKey = TlsECCUtils.validateECPublicKey(TlsECCUtils.deserializeECPublicKey(
+ clientECPointFormats, curve_params, point));
+ }
+
+ public void validateCertificateRequest(CertificateRequest certificateRequest)
+ throws IOException
+ {
+ /*
+ * RFC 4492 3. [...] The ECDSA_fixed_ECDH and RSA_fixed_ECDH mechanisms are usable with
+ * ECDH_ECDSA and ECDH_RSA. Their use with ECDHE_ECDSA and ECDHE_RSA is prohibited because
+ * the use of a long-term ECDH client key would jeopardize the forward secrecy property of
+ * these algorithms.
+ */
+ short[] types = certificateRequest.getCertificateTypes();
+ for (int i = 0; i < types.length; ++i)
+ {
+ switch (types[i])
+ {
+ case ClientCertificateType.rsa_sign:
+ case ClientCertificateType.dss_sign:
+ case ClientCertificateType.ecdsa_sign:
+ break;
+ default:
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+ }
+
+ public void processClientCredentials(TlsCredentials clientCredentials)
+ throws IOException
+ {
+ if (clientCredentials instanceof TlsSignerCredentials)
+ {
+ // OK
+ }
+ else
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ protected Signer initVerifyer(TlsSigner tlsSigner, SignatureAndHashAlgorithm algorithm, SecurityParameters securityParameters)
+ {
+ 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/core/src/main/java/org/spongycastle/crypto/tls/TlsECDHKeyExchange.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsECDHKeyExchange.java
new file mode 100644
index 00000000..87ecaedb
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsECDHKeyExchange.java
@@ -0,0 +1,219 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Vector;
+
+import org.spongycastle.asn1.x509.KeyUsage;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.crypto.util.PublicKeyFactory;
+
+/**
+ * ECDH key exchange (see RFC 4492)
+ */
+public class TlsECDHKeyExchange extends AbstractTlsKeyExchange
+{
+ protected TlsSigner tlsSigner;
+ protected int[] namedCurves;
+ protected short[] clientECPointFormats, serverECPointFormats;
+
+ protected AsymmetricKeyParameter serverPublicKey;
+ protected TlsAgreementCredentials agreementCredentials;
+
+ protected ECPrivateKeyParameters ecAgreePrivateKey;
+ protected ECPublicKeyParameters ecAgreePublicKey;
+
+ public TlsECDHKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms, int[] namedCurves,
+ short[] clientECPointFormats, short[] serverECPointFormats)
+ {
+ super(keyExchange, supportedSignatureAlgorithms);
+
+ switch (keyExchange)
+ {
+ case KeyExchangeAlgorithm.ECDHE_RSA:
+ this.tlsSigner = new TlsRSASigner();
+ break;
+ case KeyExchangeAlgorithm.ECDHE_ECDSA:
+ this.tlsSigner = new TlsECDSASigner();
+ break;
+ case KeyExchangeAlgorithm.ECDH_RSA:
+ case KeyExchangeAlgorithm.ECDH_ECDSA:
+ this.tlsSigner = null;
+ break;
+ default:
+ throw new IllegalArgumentException("unsupported key exchange algorithm");
+ }
+
+ this.keyExchange = keyExchange;
+ this.namedCurves = namedCurves;
+ this.clientECPointFormats = clientECPointFormats;
+ this.serverECPointFormats = serverECPointFormats;
+ }
+
+ public void init(TlsContext context)
+ {
+ super.init(context);
+
+ if (this.tlsSigner != null)
+ {
+ this.tlsSigner.init(context);
+ }
+ }
+
+ public void skipServerCredentials() throws IOException
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ public void processServerCertificate(Certificate serverCertificate) throws IOException
+ {
+ if (serverCertificate.isEmpty())
+ {
+ throw new TlsFatalAlert(AlertDescription.bad_certificate);
+ }
+
+ org.spongycastle.asn1.x509.Certificate x509Cert = serverCertificate.getCertificateAt(0);
+
+ SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo();
+ try
+ {
+ this.serverPublicKey = PublicKeyFactory.createKey(keyInfo);
+ }
+ catch (RuntimeException e)
+ {
+ throw new TlsFatalAlert(AlertDescription.unsupported_certificate);
+ }
+
+ if (tlsSigner == null)
+ {
+ try
+ {
+ this.ecAgreePublicKey = TlsECCUtils.validateECPublicKey((ECPublicKeyParameters) this.serverPublicKey);
+ }
+ catch (ClassCastException e)
+ {
+ throw new TlsFatalAlert(AlertDescription.certificate_unknown);
+ }
+
+ TlsUtils.validateKeyUsage(x509Cert, KeyUsage.keyAgreement);
+ }
+ else
+ {
+ if (!tlsSigner.isValidPublicKey(this.serverPublicKey))
+ {
+ throw new TlsFatalAlert(AlertDescription.certificate_unknown);
+ }
+
+ TlsUtils.validateKeyUsage(x509Cert, KeyUsage.digitalSignature);
+ }
+
+ super.processServerCertificate(serverCertificate);
+ }
+
+ public boolean requiresServerKeyExchange()
+ {
+ switch (keyExchange)
+ {
+ case KeyExchangeAlgorithm.ECDHE_ECDSA:
+ case KeyExchangeAlgorithm.ECDHE_RSA:
+ case KeyExchangeAlgorithm.ECDH_anon:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public void validateCertificateRequest(CertificateRequest certificateRequest) throws IOException
+ {
+ /*
+ * RFC 4492 3. [...] The ECDSA_fixed_ECDH and RSA_fixed_ECDH mechanisms are usable with
+ * ECDH_ECDSA and ECDH_RSA. Their use with ECDHE_ECDSA and ECDHE_RSA is prohibited because
+ * the use of a long-term ECDH client key would jeopardize the forward secrecy property of
+ * these algorithms.
+ */
+ short[] types = certificateRequest.getCertificateTypes();
+ for (int i = 0; i < types.length; ++i)
+ {
+ switch (types[i])
+ {
+ case ClientCertificateType.rsa_sign:
+ case ClientCertificateType.dss_sign:
+ case ClientCertificateType.ecdsa_sign:
+ case ClientCertificateType.rsa_fixed_ecdh:
+ case ClientCertificateType.ecdsa_fixed_ecdh:
+ break;
+ default:
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+ }
+
+ 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;
+ }
+ else if (clientCredentials instanceof TlsSignerCredentials)
+ {
+ // OK
+ }
+ else
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public void generateClientKeyExchange(OutputStream output) throws IOException
+ {
+ if (agreementCredentials == null)
+ {
+ this.ecAgreePrivateKey = TlsECCUtils.generateEphemeralClientKeyExchange(context.getSecureRandom(),
+ serverECPointFormats, ecAgreePublicKey.getParameters(), output);
+ }
+ }
+
+ 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
+ {
+ if (ecAgreePublicKey != null)
+ {
+ // For ecdsa_fixed_ecdh and rsa_fixed_ecdh, the key arrived in the client certificate
+ return;
+ }
+
+ byte[] point = TlsUtils.readOpaque8(input);
+
+ ECDomainParameters curve_params = this.ecAgreePrivateKey.getParameters();
+
+ this.ecAgreePublicKey = TlsECCUtils.validateECPublicKey(TlsECCUtils.deserializeECPublicKey(
+ serverECPointFormats, curve_params, point));
+ }
+
+ public byte[] generatePremasterSecret() throws IOException
+ {
+ if (agreementCredentials != null)
+ {
+ return agreementCredentials.generateAgreement(ecAgreePublicKey);
+ }
+
+ if (ecAgreePrivateKey != null)
+ {
+ return TlsECCUtils.calculateECDHBasicAgreement(ecAgreePublicKey, ecAgreePrivateKey);
+ }
+
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsECDSASigner.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsECDSASigner.java
new file mode 100644
index 00000000..308aabf0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsECDSASigner.java
@@ -0,0 +1,26 @@
+package org.spongycastle.crypto.tls;
+
+import org.spongycastle.crypto.DSA;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.crypto.signers.ECDSASigner;
+import org.spongycastle.crypto.signers.HMacDSAKCalculator;
+
+public class TlsECDSASigner
+ extends TlsDSASigner
+{
+ public boolean isValidPublicKey(AsymmetricKeyParameter publicKey)
+ {
+ return publicKey instanceof ECPublicKeyParameters;
+ }
+
+ protected DSA createDSAImpl(short hashAlgorithm)
+ {
+ return new ECDSASigner(new HMacDSAKCalculator(TlsUtils.createHash(hashAlgorithm)));
+ }
+
+ protected short getSignatureAlgorithm()
+ {
+ return SignatureAlgorithm.ecdsa;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsEncryptionCredentials.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsEncryptionCredentials.java
new file mode 100644
index 00000000..c4736382
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsEncryptionCredentials.java
@@ -0,0 +1,9 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+public interface TlsEncryptionCredentials extends TlsCredentials
+{
+ byte[] decryptPreMasterSecret(byte[] encryptedPreMasterSecret)
+ throws IOException;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsExtensionsUtils.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsExtensionsUtils.java
new file mode 100644
index 00000000..70393e0f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsExtensionsUtils.java
@@ -0,0 +1,267 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Hashtable;
+
+import org.spongycastle.util.Integers;
+
+public class TlsExtensionsUtils
+{
+ public static final Integer EXT_encrypt_then_mac = Integers.valueOf(ExtensionType.encrypt_then_mac);
+ 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 addEncryptThenMACExtension(Hashtable extensions)
+ {
+ extensions.put(EXT_encrypt_then_mac, createEncryptThenMACExtension());
+ }
+
+ 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 hasEncryptThenMACExtension(Hashtable extensions) throws IOException
+ {
+ byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_encrypt_then_mac);
+ return extensionData == null ? false : readEncryptThenMACExtension(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[] createEncryptThenMACExtension()
+ {
+ return createEmptyExtensionData();
+ }
+
+ 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();
+ }
+
+ private static boolean readEmptyExtensionData(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;
+ }
+
+ public static boolean readEncryptThenMACExtension(byte[] extensionData) throws IOException
+ {
+ return readEmptyExtensionData(extensionData);
+ }
+
+ 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;
+ }
+
+ public static boolean readTruncatedHMacExtension(byte[] extensionData) throws IOException
+ {
+ return readEmptyExtensionData(extensionData);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsFatalAlert.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsFatalAlert.java
new file mode 100644
index 00000000..7e633809
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsFatalAlert.java
@@ -0,0 +1,21 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+public class TlsFatalAlert
+ extends IOException
+{
+ private static final long serialVersionUID = 3584313123679111168L;
+
+ private short alertDescription;
+
+ public TlsFatalAlert(short alertDescription)
+ {
+ this.alertDescription = alertDescription;
+ }
+
+ public short getAlertDescription()
+ {
+ return alertDescription;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsHandshakeHash.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsHandshakeHash.java
new file mode 100644
index 00000000..4fc82ffd
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsHandshakeHash.java
@@ -0,0 +1,21 @@
+package org.spongycastle.crypto.tls;
+
+import org.spongycastle.crypto.Digest;
+
+public interface TlsHandshakeHash
+ extends Digest
+{
+ void init(TlsContext context);
+
+ TlsHandshakeHash notifyPRFDetermined();
+
+ void trackHashAlgorithm(short hashAlgorithm);
+
+ void sealHashAlgorithms();
+
+ TlsHandshakeHash stopTracking();
+
+ Digest forkPRFHash();
+
+ byte[] getFinalHash(short hashAlgorithm);
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsInputStream.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsInputStream.java
new file mode 100644
index 00000000..e2c3e281
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsInputStream.java
@@ -0,0 +1,47 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * An InputStream for an TLS 1.0 connection.
+ */
+class TlsInputStream
+ extends InputStream
+{
+ private byte[] buf = new byte[1];
+ private TlsProtocol handler = null;
+
+ TlsInputStream(TlsProtocol handler)
+ {
+ this.handler = handler;
+ }
+
+ public int available()
+ throws IOException
+ {
+ return this.handler.applicationDataAvailable();
+ }
+
+ public int read(byte[] buf, int offset, int len)
+ throws IOException
+ {
+ return this.handler.readApplicationData(buf, offset, len);
+ }
+
+ public int read()
+ throws IOException
+ {
+ if (this.read(buf) < 0)
+ {
+ return -1;
+ }
+ return buf[0] & 0xff;
+ }
+
+ public void close()
+ throws IOException
+ {
+ handler.close();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsKeyExchange.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsKeyExchange.java
new file mode 100644
index 00000000..82902170
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsKeyExchange.java
@@ -0,0 +1,54 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * A generic interface for key exchange implementations in TLS 1.0/1.1.
+ */
+public interface TlsKeyExchange
+{
+ void init(TlsContext context);
+
+ void skipServerCredentials()
+ throws IOException;
+
+ void processServerCredentials(TlsCredentials serverCredentials)
+ throws IOException;
+
+ void processServerCertificate(Certificate serverCertificate)
+ throws IOException;
+
+ boolean requiresServerKeyExchange();
+
+ byte[] generateServerKeyExchange()
+ throws IOException;
+
+ void skipServerKeyExchange()
+ throws IOException;
+
+ void processServerKeyExchange(InputStream input)
+ throws IOException;
+
+ void validateCertificateRequest(CertificateRequest certificateRequest)
+ throws IOException;
+
+ void skipClientCredentials()
+ throws IOException;
+
+ void processClientCredentials(TlsCredentials clientCredentials)
+ throws IOException;
+
+ void processClientCertificate(Certificate clientCertificate)
+ throws IOException;
+
+ void generateClientKeyExchange(OutputStream output)
+ throws IOException;
+
+ void processClientKeyExchange(InputStream input)
+ throws IOException;
+
+ byte[] generatePremasterSecret()
+ throws IOException;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsMac.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsMac.java
new file mode 100644
index 00000000..6390b699
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsMac.java
@@ -0,0 +1,172 @@
+package org.spongycastle.crypto.tls;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.digests.LongDigest;
+import org.spongycastle.crypto.macs.HMac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Arrays;
+
+/**
+ * A generic TLS MAC implementation, acting as an HMAC based on some underlying Digest.
+ */
+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 keyOff The number of bytes to skip, before the key starts in the buffer.
+ * @param keyLen The length of the key.
+ */
+ public TlsMac(TlsContext context, Digest digest, byte[] key, int keyOff, int keyLen)
+ {
+ this.context = context;
+
+ KeyParameter keyParameter = new KeyParameter(key, keyOff, keyLen);
+
+ this.secret = Arrays.clone(keyParameter.getKey());
+
+ // TODO This should check the actual algorithm, not rely on the engine type
+ if (digest instanceof LongDigest)
+ {
+ this.digestBlockSize = 128;
+ this.digestOverhead = 16;
+ }
+ else
+ {
+ this.digestBlockSize = 64;
+ this.digestOverhead = 8;
+ }
+
+ if (TlsUtils.isSSL(context))
+ {
+ this.mac = new SSL3Mac(digest);
+
+ // TODO This should check the actual algorithm, not assume based on the digest size
+ if (digest.getDigestSize() == 20)
+ {
+ /*
+ * NOTE: When SHA-1 is used with the SSL 3.0 MAC, the secret + input pad is not
+ * digest block-aligned.
+ */
+ this.digestOverhead = 4;
+ }
+ }
+ else
+ {
+ this.mac = new HMac(digest);
+
+ // NOTE: The input pad for HMAC is always a full digest block
+ }
+
+ this.mac.init(keyParameter);
+
+ this.macLength = mac.getMacSize();
+ if (context.getSecurityParameters().truncatedHMac)
+ {
+ this.macLength = Math.min(this.macLength, 10);
+ }
+ }
+
+ /**
+ * @return the MAC write secret
+ */
+ public byte[] getMACSecret()
+ {
+ return this.secret;
+ }
+
+ /**
+ * @return The output length of this MAC.
+ */
+ public int getSize()
+ {
+ return macLength;
+ }
+
+ /**
+ * Calculate the MAC for some given data.
+ *
+ * @param type The message type of the message.
+ * @param message A byte-buffer containing the message.
+ * @param offset The number of bytes to skip, before the message starts.
+ * @param length The length of the message.
+ * @return A new byte-buffer containing the MAC value.
+ */
+ public byte[] calculateMac(long seqNo, short type, byte[] message, int offset, int length)
+ {
+ ProtocolVersion serverVersion = context.getServerVersion();
+ boolean isSSL = serverVersion.isSSL();
+
+ byte[] macHeader = new byte[isSSL ? 11 : 13];
+ TlsUtils.writeUint64(seqNo, macHeader, 0);
+ TlsUtils.writeUint8(type, macHeader, 8);
+ if (!isSSL)
+ {
+ TlsUtils.writeVersion(serverVersion, macHeader, 9);
+ }
+ TlsUtils.writeUint16(length, macHeader, macHeader.length - 2);
+
+ mac.update(macHeader, 0, macHeader.length);
+ mac.update(message, offset, length);
+
+ byte[] result = new byte[mac.getMacSize()];
+ mac.doFinal(result, 0);
+ return truncate(result);
+ }
+
+ public byte[] calculateMacConstantTime(long seqNo, short type, byte[] message, int offset, int length,
+ int fullLength, byte[] dummyData)
+ {
+ /*
+ * Actual MAC only calculated on 'length' bytes...
+ */
+ byte[] result = calculateMac(seqNo, type, message, offset, length);
+
+ /*
+ * ...but ensure a constant number of complete digest blocks are processed (as many as would
+ * be needed for 'fullLength' bytes of input).
+ */
+ 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);
+
+ while (--extra >= 0)
+ {
+ mac.update(dummyData, 0, digestBlockSize);
+ }
+
+ // One more byte in case the implementation is "lazy" about processing blocks
+ mac.update(dummyData[0]);
+ mac.reset();
+
+ return result;
+ }
+
+ 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/core/src/main/java/org/spongycastle/crypto/tls/TlsNullCipher.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsNullCipher.java
new file mode 100644
index 00000000..6972cea6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsNullCipher.java
@@ -0,0 +1,123 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.util.Arrays;
+
+/**
+ * A NULL CipherSuite with optional MAC
+ */
+public class TlsNullCipher
+ implements TlsCipher
+{
+ protected TlsContext context;
+
+ protected TlsMac writeMac;
+ protected TlsMac readMac;
+
+ public TlsNullCipher(TlsContext context)
+ {
+ this.context = context;
+ this.writeMac = null;
+ this.readMac = null;
+ }
+
+ public TlsNullCipher(TlsContext context, Digest clientWriteDigest, Digest serverWriteDigest)
+ throws IOException
+ {
+ if ((clientWriteDigest == null) != (serverWriteDigest == null))
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ this.context = context;
+
+ TlsMac clientWriteMac = null, serverWriteMac = null;
+
+ if (clientWriteDigest != null)
+ {
+ int key_block_size = clientWriteDigest.getDigestSize()
+ + serverWriteDigest.getDigestSize();
+ byte[] key_block = TlsUtils.calculateKeyBlock(context, key_block_size);
+
+ int offset = 0;
+
+ clientWriteMac = new TlsMac(context, clientWriteDigest, key_block, offset,
+ clientWriteDigest.getDigestSize());
+ offset += clientWriteDigest.getDigestSize();
+
+ serverWriteMac = new TlsMac(context, serverWriteDigest, key_block, offset,
+ serverWriteDigest.getDigestSize());
+ offset += serverWriteDigest.getDigestSize();
+
+ if (offset != key_block_size)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ if (context.isServer())
+ {
+ writeMac = serverWriteMac;
+ readMac = clientWriteMac;
+ }
+ else
+ {
+ writeMac = clientWriteMac;
+ readMac = serverWriteMac;
+ }
+ }
+
+ public int getPlaintextLimit(int ciphertextLimit)
+ {
+ int result = ciphertextLimit;
+ if (writeMac != null)
+ {
+ result -= writeMac.getSize();
+ }
+ return result;
+ }
+
+ 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);
+ }
+
+ byte[] mac = writeMac.calculateMac(seqNo, type, plaintext, offset, len);
+ byte[] ciphertext = new byte[len + mac.length];
+ System.arraycopy(plaintext, offset, ciphertext, 0, len);
+ System.arraycopy(mac, 0, ciphertext, len, mac.length);
+ return ciphertext;
+ }
+
+ 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);
+ }
+
+ int macSize = readMac.getSize();
+ if (len < macSize)
+ {
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+
+ int macInputLen = len - macSize;
+
+ byte[] receivedMac = Arrays.copyOfRange(ciphertext, offset + macInputLen, offset + len);
+ byte[] computedMac = readMac.calculateMac(seqNo, type, ciphertext, offset, macInputLen);
+
+ if (!Arrays.constantTimeAreEqual(receivedMac, computedMac))
+ {
+ throw new TlsFatalAlert(AlertDescription.bad_record_mac);
+ }
+
+ return Arrays.copyOfRange(ciphertext, offset, offset + macInputLen);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsNullCompression.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsNullCompression.java
new file mode 100644
index 00000000..724d93b6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsNullCompression.java
@@ -0,0 +1,17 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.OutputStream;
+
+public class TlsNullCompression
+ implements TlsCompression
+{
+ public OutputStream compress(OutputStream output)
+ {
+ return output;
+ }
+
+ public OutputStream decompress(OutputStream output)
+ {
+ return output;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsOutputStream.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsOutputStream.java
new file mode 100644
index 00000000..d4b6de66
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsOutputStream.java
@@ -0,0 +1,44 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * An OutputStream for an TLS connection.
+ */
+class TlsOutputStream
+ extends OutputStream
+{
+ private byte[] buf = new byte[1];
+ private TlsProtocol handler;
+
+ TlsOutputStream(TlsProtocol handler)
+ {
+ this.handler = handler;
+ }
+
+ public void write(byte buf[], int offset, int len)
+ throws IOException
+ {
+ this.handler.writeData(buf, offset, len);
+ }
+
+ public void write(int arg0)
+ throws IOException
+ {
+ buf[0] = (byte)arg0;
+ this.write(buf, 0, 1);
+ }
+
+ public void close()
+ throws IOException
+ {
+ handler.close();
+ }
+
+ public void flush()
+ throws IOException
+ {
+ handler.flush();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsPSKIdentity.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsPSKIdentity.java
new file mode 100644
index 00000000..a271ddce
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsPSKIdentity.java
@@ -0,0 +1,12 @@
+package org.spongycastle.crypto.tls;
+
+public interface TlsPSKIdentity
+{
+ void skipIdentityHint();
+
+ void notifyIdentityHint(byte[] psk_identity_hint);
+
+ byte[] getPSKIdentity();
+
+ byte[] getPSK();
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsPSKKeyExchange.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsPSKKeyExchange.java
new file mode 100644
index 00000000..c3431bb4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsPSKKeyExchange.java
@@ -0,0 +1,285 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Vector;
+
+import org.spongycastle.asn1.x509.KeyUsage;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.DHParameters;
+import org.spongycastle.crypto.params.DHPrivateKeyParameters;
+import org.spongycastle.crypto.params.DHPublicKeyParameters;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+import org.spongycastle.crypto.util.PublicKeyFactory;
+
+/**
+ * TLS 1.0 PSK key exchange (RFC 4279).
+ */
+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 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,
+ 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:
+ 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()
+ throws IOException
+ {
+ if (keyExchange == KeyExchangeAlgorithm.RSA_PSK)
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ }
+
+ 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);
+ }
+ if (serverCertificate.isEmpty())
+ {
+ throw new TlsFatalAlert(AlertDescription.bad_certificate);
+ }
+
+ org.spongycastle.asn1.x509.Certificate x509Cert = serverCertificate.getCertificateAt(0);
+
+ SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo();
+ try
+ {
+ this.serverPublicKey = PublicKeyFactory.createKey(keyInfo);
+ }
+ catch (RuntimeException e)
+ {
+ throw new TlsFatalAlert(AlertDescription.unsupported_certificate);
+ }
+
+ // Sanity check the PublicKeyFactory
+ if (this.serverPublicKey.isPrivate())
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ this.rsaServerPublicKey = validateRSAPublicKey((RSAKeyParameters)this.serverPublicKey);
+
+ TlsUtils.validateKeyUsage(x509Cert, KeyUsage.keyEncipherment);
+
+ super.processServerCertificate(serverCertificate);
+ }
+
+ public boolean requiresServerKeyExchange()
+ {
+ 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)
+ {
+ ServerDHParams serverDHParams = ServerDHParams.parse(input);
+
+ this.dhAgreePublicKey = TlsDHUtils.validateDHPublicKey(serverDHParams.getPublicKey());
+ }
+ else if (this.keyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
+ {
+ // TODO[RFC 5489]
+ }
+ }
+
+ public void validateCertificateRequest(CertificateRequest certificateRequest)
+ throws IOException
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ public void processClientCredentials(TlsCredentials clientCredentials)
+ throws IOException
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ public void generateClientKeyExchange(OutputStream output)
+ throws IOException
+ {
+ if (psk_identity_hint == null)
+ {
+ pskIdentity.skipIdentityHint();
+ }
+ else
+ {
+ pskIdentity.notifyIdentityHint(psk_identity_hint);
+ }
+
+ byte[] psk_identity = pskIdentity.getPSKIdentity();
+
+ TlsUtils.writeOpaque16(psk_identity, output);
+
+ if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK)
+ {
+ 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.RSA_PSK)
+ {
+ this.premasterSecret = TlsRSAUtils.generateEncryptedPreMasterSecret(context, this.rsaServerPublicKey,
+ output);
+ }
+ }
+
+ public byte[] generatePremasterSecret()
+ throws IOException
+ {
+ byte[] psk = pskIdentity.getPSK();
+ byte[] other_secret = generateOtherSecret(psk.length);
+
+ ByteArrayOutputStream buf = new ByteArrayOutputStream(4 + other_secret.length + psk.length);
+ TlsUtils.writeOpaque16(other_secret, buf);
+ TlsUtils.writeOpaque16(psk, buf);
+ return buf.toByteArray();
+ }
+
+ protected byte[] generateOtherSecret(int pskLength) throws IOException
+ {
+ if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK)
+ {
+ 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)
+ {
+ return this.premasterSecret;
+ }
+
+ return new byte[pskLength];
+ }
+
+ protected RSAKeyParameters validateRSAPublicKey(RSAKeyParameters key)
+ throws IOException
+ {
+ // TODO What is the minimum bit length required?
+ // key.getModulus().bitLength();
+
+ if (!key.getExponent().isProbablePrime(2))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ return key;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsPeer.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsPeer.java
new file mode 100644
index 00000000..62ed0f71
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsPeer.java
@@ -0,0 +1,46 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+public interface TlsPeer
+{
+ /**
+ * draft-mathewson-no-gmtunixtime-00 2. "If existing users of a TLS implementation may rely on
+ * gmt_unix_time containing the current time, we recommend that implementors MAY provide the
+ * ability to set gmt_unix_time as an option only, off by default."
+ *
+ * @return <code>true</code> if the current time should be used in the gmt_unix_time field of
+ * Random, or <code>false</code> if gmt_unix_time should contain a cryptographically
+ * random value.
+ */
+ boolean shouldUseGMTUnixTime();
+
+ 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.
+ *
+ * @param alertLevel {@link AlertLevel}
+ * @param alertDescription {@link AlertDescription}
+ * @param message A human-readable message explaining what caused this alert. May be null.
+ * @param cause The exception that caused this alert to be raised. May be null.
+ */
+ void notifyAlertRaised(short alertLevel, short alertDescription, String message, Exception cause);
+
+ /**
+ * This method will be called when an alert is received from the remote peer.
+ *
+ * @param alertLevel {@link AlertLevel}
+ * @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/core/src/main/java/org/spongycastle/crypto/tls/TlsProtocol.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsProtocol.java
new file mode 100644
index 00000000..96aff625
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsProtocol.java
@@ -0,0 +1,1184 @@
+package org.spongycastle.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;
+import java.security.SecureRandom;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.prng.RandomGenerator;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Integers;
+
+/**
+ * An implementation of all high level protocols in TLS 1.0/1.1.
+ */
+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);
+
+ private static final String TLS_ERROR_MESSAGE = "Internal TLS error, this could be an attack";
+
+ /*
+ * Our Connection states
+ */
+ protected static final short CS_START = 0;
+ protected static final short CS_CLIENT_HELLO = 1;
+ 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_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_FINISHED = 15;
+ protected static final short CS_END = 16;
+
+ /*
+ * Queues for data from some protocols.
+ */
+ private ByteQueue applicationDataQueue = new ByteQueue();
+ private ByteQueue alertQueue = new ByteQueue(2);
+ private ByteQueue handshakeQueue = new ByteQueue();
+// private ByteQueue heartbeatQueue = new ByteQueue();
+
+ /*
+ * The Record Stream we use
+ */
+ protected RecordStream recordStream;
+ protected SecureRandom secureRandom;
+
+ private TlsInputStream tlsInputStream = null;
+ private TlsOutputStream tlsOutputStream = null;
+
+ private volatile boolean closed = false;
+ private volatile boolean failedWithError = false;
+ private volatile boolean appDataReady = false;
+ 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)
+ {
+ this.recordStream = new RecordStream(this, input, output);
+ this.secureRandom = secureRandom;
+ }
+
+ protected abstract AbstractTlsContext getContext();
+
+ protected abstract TlsPeer getPeer();
+
+ protected void handleChangeCipherSpecMessage() throws IOException
+ {
+ }
+
+ protected abstract void handleHandshakeMessage(short type, byte[] buf)
+ throws IOException;
+
+ 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?
+ }
+
+ safeReadRecord();
+ }
+
+ this.recordStream.finaliseHandshake();
+
+ this.splitApplicationDataRecords = !TlsUtils.isTLSv11(getContext());
+
+ /*
+ * 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);
+ }
+
+ 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();
+ }
+ }
+
+ protected void processRecord(short protocol, byte[] buf, int offset, int len)
+ throws IOException
+ {
+ /*
+ * Have a look at the protocol type, and add it to the correct queue.
+ */
+ switch (protocol)
+ {
+ case ContentType.alert:
+ {
+ alertQueue.addData(buf, offset, len);
+ processAlert();
+ break;
+ }
+ case ContentType.application_data:
+ {
+ if (!appDataReady)
+ {
+ 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:
+ {
+ if (!appDataReady)
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ // TODO[RFC 6520]
+// heartbeatQueue.addData(buf, offset, len);
+// processHeartbeat();
+ }
+ default:
+ /*
+ * Uh, we don't know this protocol.
+ *
+ * RFC2246 defines on page 13, that we should ignore this.
+ */
+ }
+ }
+
+ private void processHandshake()
+ throws IOException
+ {
+ boolean read;
+ do
+ {
+ read = false;
+ /*
+ * We need the first 4 bytes, they contain type and length of the message.
+ */
+ if (handshakeQueue.size() >= 4)
+ {
+ byte[] beginning = new byte[4];
+ handshakeQueue.read(beginning, 0, 4, 0);
+ ByteArrayInputStream bis = new ByteArrayInputStream(beginning);
+ short type = TlsUtils.readUint8(bis);
+ int len = TlsUtils.readUint24(bis);
+
+ /*
+ * Check if we have enough bytes in the buffer to read the full message.
+ */
+ if (handshakeQueue.size() >= (len + 4))
+ {
+ /*
+ * Read the message.
+ */
+ byte[] buf = handshakeQueue.removeData(len, 4);
+
+ /*
+ * RFC 2246 7.4.9. The value handshake_messages includes all handshake messages
+ * starting at client hello up to, but not including, this finished message.
+ * [..] Note: [Also,] Hello Request messages are omitted from handshake hashes.
+ */
+ switch (type)
+ {
+ case HandshakeType.hello_request:
+ break;
+ case HandshakeType.finished:
+ {
+ if (this.expected_verify_data == null)
+ {
+ this.expected_verify_data = createVerifyData(!getContext().isServer());
+ }
+
+ // NB: Fall through to next case label
+ }
+ default:
+ recordStream.updateHandshakeData(beginning, 0, 4);
+ recordStream.updateHandshakeData(buf, 0, len);
+ break;
+ }
+
+ /*
+ * Now, parse the message.
+ */
+ handleHandshakeMessage(type, buf);
+ read = true;
+ }
+ }
+ }
+ while (read);
+ }
+
+ private void processApplicationData()
+ {
+ /*
+ * There is nothing we need to do here.
+ *
+ * This function could be used for callbacks when application data arrives in the future.
+ */
+ }
+
+ private void processAlert()
+ throws IOException
+ {
+ while (alertQueue.size() >= 2)
+ {
+ /*
+ * An alert is always 2 bytes. Read the alert.
+ */
+ byte[] tmp = alertQueue.removeData(2, 0);
+ short level = tmp[0];
+ short description = tmp[1];
+
+ getPeer().notifyAlertReceived(level, description);
+
+ 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;
+
+ recordStream.safeClose();
+
+ throw new IOException(TLS_ERROR_MESSAGE);
+ }
+ else
+ {
+
+ /*
+ * RFC 5246 7.2.1. The other party MUST respond with a close_notify alert of its own
+ * and close down the connection immediately, discarding any pending writes.
+ */
+ // TODO Can close_notify be a fatal alert?
+ if (description == AlertDescription.close_notify)
+ {
+ handleClose(false);
+ }
+
+ /*
+ * If it is just a warning, we continue.
+ */
+ handleWarningMessage(description);
+ }
+ }
+ }
+
+ /**
+ * This method is called, when a change cipher spec message is received.
+ *
+ * @throws IOException If the message has an invalid content or the handshake is not in the correct
+ * state.
+ */
+ private void processChangeCipherSpec(byte[] buf, int off, int len)
+ throws IOException
+ {
+ for (int i = 0; i < len; ++i)
+ {
+ short message = TlsUtils.readUint8(buf, off + i);
+
+ if (message != ChangeCipherSpec.change_cipher_spec)
+ {
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+
+ if (this.receivedChangeCipherSpec
+ || alertQueue.size() > 0
+ || handshakeQueue.size() > 0)
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ recordStream.receivedReadCipherSpec();
+
+ this.receivedChangeCipherSpec = true;
+
+ handleChangeCipherSpecMessage();
+ }
+ }
+
+ protected int applicationDataAvailable()
+ throws IOException
+ {
+ return applicationDataQueue.size();
+ }
+
+ /**
+ * Read data from the network. The method will return immediately, if there is still some data
+ * left in the buffer, or block until some application data has been read from the network.
+ *
+ * @param buf The buffer where the data will be copied to.
+ * @param offset The position where the data will be placed in the buffer.
+ * @param len The maximum number of bytes to read.
+ * @return The number of bytes read.
+ * @throws IOException If something goes wrong during reading data.
+ */
+ protected int readApplicationData(byte[] buf, int offset, int len)
+ throws IOException
+ {
+ if (len < 1)
+ {
+ return 0;
+ }
+
+ while (applicationDataQueue.size() == 0)
+ {
+ /*
+ * We need to read some data.
+ */
+ if (this.closed)
+ {
+ if (this.failedWithError)
+ {
+ /*
+ * Something went terribly wrong, we should throw an IOException
+ */
+ throw new IOException(TLS_ERROR_MESSAGE);
+ }
+
+ /*
+ * Connection has been closed, there is no more data to read.
+ */
+ return -1;
+ }
+
+ safeReadRecord();
+ }
+
+ len = Math.min(len, applicationDataQueue.size());
+ applicationDataQueue.removeData(buf, offset, len, 0);
+ return len;
+ }
+
+ protected void safeReadRecord()
+ throws IOException
+ {
+ try
+ {
+ 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(), "Failed to read record", e);
+ }
+ throw e;
+ }
+ catch (IOException e)
+ {
+ if (!this.closed)
+ {
+ this.failWithError(AlertLevel.fatal, AlertDescription.internal_error, "Failed to read record", e);
+ }
+ throw e;
+ }
+ catch (RuntimeException e)
+ {
+ if (!this.closed)
+ {
+ this.failWithError(AlertLevel.fatal, AlertDescription.internal_error, "Failed to read record", e);
+ }
+ throw e;
+ }
+ }
+
+ protected void safeWriteRecord(short type, byte[] buf, int offset, int len)
+ throws IOException
+ {
+ try
+ {
+ recordStream.writeRecord(type, buf, offset, len);
+ }
+ catch (TlsFatalAlert e)
+ {
+ if (!this.closed)
+ {
+ this.failWithError(AlertLevel.fatal, e.getAlertDescription(), "Failed to write record", e);
+ }
+ throw e;
+ }
+ catch (IOException e)
+ {
+ if (!closed)
+ {
+ this.failWithError(AlertLevel.fatal, AlertDescription.internal_error, "Failed to write record", e);
+ }
+ throw e;
+ }
+ catch (RuntimeException e)
+ {
+ if (!closed)
+ {
+ this.failWithError(AlertLevel.fatal, AlertDescription.internal_error, "Failed to write record", e);
+ }
+ throw e;
+ }
+ }
+
+ /**
+ * Send some application data to the remote system.
+ * <p/>
+ * The method will handle fragmentation internally.
+ *
+ * @param buf The buffer with the data.
+ * @param offset The position in the buffer where the data is placed.
+ * @param len The length of the data.
+ * @throws IOException If something goes wrong during sending.
+ */
+ protected void writeData(byte[] buf, int offset, int len)
+ throws IOException
+ {
+ if (this.closed)
+ {
+ if (this.failedWithError)
+ {
+ throw new IOException(TLS_ERROR_MESSAGE);
+ }
+
+ throw new IOException("Sorry, connection has been closed, you cannot write more data");
+ }
+
+ while (len > 0)
+ {
+ /*
+ * 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.splitApplicationDataRecords)
+ {
+ /*
+ * Protect against known IV attack!
+ *
+ * DO NOT REMOVE THIS CODE, EXCEPT YOU KNOW EXACTLY WHAT YOU ARE DOING HERE.
+ */
+ safeWriteRecord(ContentType.application_data, buf, offset, 1);
+ ++offset;
+ --len;
+ }
+
+ 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;
+ }
+ }
+ }
+
+ 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;
+ }
+ }
+
+ /**
+ * @return An OutputStream which can be used to send data.
+ */
+ public OutputStream getOutputStream()
+ {
+ return this.tlsOutputStream;
+ }
+
+ /**
+ * @return An InputStream which can be used to read data.
+ */
+ public InputStream getInputStream()
+ {
+ return this.tlsInputStream;
+ }
+
+ /**
+ * 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, String message, Exception cause)
+ throws IOException
+ {
+ /*
+ * Check if the connection is still open.
+ */
+ if (!closed)
+ {
+ /*
+ * Prepare the message
+ */
+ this.closed = true;
+
+ if (alertLevel == 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.
+ */
+ // 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, message, cause);
+ recordStream.safeClose();
+ if (alertLevel != AlertLevel.fatal)
+ {
+ return;
+ }
+ }
+
+ throw new IOException(TLS_ERROR_MESSAGE);
+ }
+
+ protected void invalidateSession()
+ {
+ if (this.sessionParameters != null)
+ {
+ 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);
+
+ /*
+ * Compare both checksums.
+ */
+ if (!Arrays.constantTimeAreEqual(expected_verify_data, verify_data))
+ {
+ /*
+ * Wrong checksum in the finished message.
+ */
+ 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];
+ error[0] = (byte)alertLevel;
+ error[1] = (byte)alertDescription;
+
+ safeWriteRecord(ContentType.alert, error, 0, 2);
+ }
+
+ protected void raiseWarning(short alertDescription, String message)
+ throws IOException
+ {
+ raiseAlert(AlertLevel.warning, alertDescription, message, null);
+ }
+
+ protected void sendCertificateMessage(Certificate certificate)
+ throws IOException
+ {
+ if (certificate == null)
+ {
+ certificate = Certificate.EMPTY_CHAIN;
+ }
+
+ if (certificate.getLength() == 0)
+ {
+ TlsContext context = getContext();
+ if (!context.isServer())
+ {
+ ProtocolVersion serverVersion = getContext().getServerVersion();
+ if (serverVersion.isSSL())
+ {
+ String message = serverVersion.toString() + " client didn't provide credentials";
+ raiseWarning(AlertDescription.no_certificate, message);
+ return;
+ }
+ }
+ }
+
+ HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate);
+
+ certificate.encode(message);
+
+ message.writeToRecordStream();
+ }
+
+ protected void sendChangeCipherSpecMessage()
+ throws IOException
+ {
+ byte[] message = new byte[]{ 1 };
+ safeWriteRecord(ContentType.change_cipher_spec, message, 0, message.length);
+ recordStream.sentWriteCipherSpec();
+ }
+
+ protected void sendFinishedMessage()
+ throws IOException
+ {
+ byte[] verify_data = createVerifyData(getContext().isServer());
+
+ HandshakeMessage message = new HandshakeMessage(HandshakeType.finished, verify_data.length);
+
+ message.write(verify_data);
+
+ message.writeToRecordStream();
+ }
+
+ protected void sendSupplementalDataMessage(Vector supplementalData)
+ throws IOException
+ {
+ HandshakeMessage message = new HandshakeMessage(HandshakeType.supplemental_data);
+
+ writeSupplementalData(message, supplementalData);
+
+ message.writeToRecordStream();
+ }
+
+ protected byte[] createVerifyData(boolean isServer)
+ {
+ TlsContext context = getContext();
+
+ if (isServer)
+ {
+ return TlsUtils.calculateVerifyData(context, ExporterLabel.server_finished,
+ getCurrentPRFHash(getContext(), recordStream.getHandshakeHash(), TlsUtils.SSL_SERVER));
+ }
+
+ return TlsUtils.calculateVerifyData(context, ExporterLabel.client_finished,
+ getCurrentPRFHash(getContext(), recordStream.getHandshakeHash(), TlsUtils.SSL_CLIENT));
+ }
+
+ /**
+ * Closes this connection.
+ *
+ * @throws IOException If something goes wrong during closing.
+ */
+ public void close()
+ throws IOException
+ {
+ handleClose(true);
+ }
+
+ protected void handleClose(boolean user_canceled)
+ throws IOException
+ {
+ if (!closed)
+ {
+ if (user_canceled && !appDataReady)
+ {
+ raiseWarning(AlertDescription.user_canceled, "User canceled handshake");
+ }
+ this.failWithError(AlertLevel.warning, AlertDescription.close_notify, "Connection closed", null);
+ }
+ }
+
+ protected void flush()
+ throws IOException
+ {
+ recordStream.flush();
+ }
+
+ protected short processMaxFragmentLengthExtension(Hashtable clientExtensions, Hashtable serverExtensions, short alertDescription)
+ throws IOException
+ {
+ short maxFragmentLength = TlsExtensionsUtils.getMaxFragmentLengthExtension(serverExtensions);
+ if (maxFragmentLength >= 0 && !this.resumedSession)
+ {
+ if (maxFragmentLength != TlsExtensionsUtils.getMaxFragmentLengthExtension(clientExtensions))
+ {
+ throw new TlsFatalAlert(alertDescription);
+ }
+ }
+ return maxFragmentLength;
+ }
+
+ /**
+ * Make sure the InputStream 'buf' now empty. Fail otherwise.
+ *
+ * @param buf The InputStream to check.
+ * @throws IOException If 'buf' is not empty.
+ */
+ protected static void assertEmpty(ByteArrayInputStream buf)
+ throws IOException
+ {
+ if (buf.available() > 0)
+ {
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+ }
+
+ protected static byte[] createRandomBlock(boolean useGMTUnixTime, RandomGenerator randomGenerator)
+ {
+ byte[] result = new byte[32];
+ randomGenerator.nextBytes(result);
+
+ if (useGMTUnixTime)
+ {
+ TlsUtils.writeGMTUnixTime(result, 0);
+ }
+
+ return result;
+ }
+
+ protected static byte[] createRenegotiationInfo(byte[] renegotiated_connection)
+ throws IOException
+ {
+ return TlsUtils.encodeOpaque8(renegotiated_connection);
+ }
+
+ protected static void establishMasterSecret(TlsContext context, TlsKeyExchange keyExchange)
+ throws IOException
+ {
+ byte[] pre_master_secret = keyExchange.generatePremasterSecret();
+
+ try
+ {
+ context.getSecurityParameters().masterSecret = TlsUtils.calculateMasterSecret(context, pre_master_secret);
+ }
+ finally
+ {
+ // TODO Is there a way to ensure the data is really overwritten?
+ /*
+ * RFC 2246 8.1. The pre_master_secret should be deleted from memory once the
+ * master_secret has been computed.
+ */
+ if (pre_master_secret != null)
+ {
+ Arrays.fill(pre_master_secret, (byte)0);
+ }
+ }
+ }
+
+ /**
+ * '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;
+ }
+
+ byte[] extBytes = TlsUtils.readOpaque16(input);
+
+ assertEmpty(input);
+
+ ByteArrayInputStream buf = new ByteArrayInputStream(extBytes);
+
+ // Integer -> byte[]
+ Hashtable extensions = new Hashtable();
+
+ while (buf.available() > 0)
+ {
+ 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(extension_type, extension_data))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+
+ return extensions;
+ }
+
+ protected static Vector readSupplementalDataMessage(ByteArrayInputStream input)
+ throws IOException
+ {
+ byte[] supp_data = TlsUtils.readOpaque24(input);
+
+ assertEmpty(input);
+
+ ByteArrayInputStream buf = new ByteArrayInputStream(supp_data);
+
+ Vector supplementalData = new Vector();
+
+ while (buf.available() > 0)
+ {
+ int supp_data_type = TlsUtils.readUint16(buf);
+ byte[] data = TlsUtils.readOpaque16(buf);
+
+ supplementalData.addElement(new SupplementalDataEntry(supp_data_type, data));
+ }
+
+ return supplementalData;
+ }
+
+ protected static void writeExtensions(OutputStream output, Hashtable extensions)
+ throws IOException
+ {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+
+ Enumeration keys = extensions.keys();
+ while (keys.hasMoreElements())
+ {
+ Integer key = (Integer)keys.nextElement();
+ int extension_type = key.intValue();
+ byte[] extension_data = (byte[])extensions.get(key);
+
+ TlsUtils.checkUint16(extension_type);
+ TlsUtils.writeUint16(extension_type, buf);
+ TlsUtils.writeOpaque16(extension_data, buf);
+ }
+
+ byte[] extBytes = buf.toByteArray();
+
+ TlsUtils.writeOpaque16(extBytes, output);
+ }
+
+ 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);
+
+ int supp_data_type = entry.getDataType();
+ TlsUtils.checkUint16(supp_data_type);
+ TlsUtils.writeUint16(supp_data_type, buf);
+ TlsUtils.writeOpaque16(entry.getData(), buf);
+ }
+
+ byte[] supp_data = buf.toByteArray();
+
+ TlsUtils.writeOpaque24(supp_data, output);
+ }
+
+ protected static int getPRFAlgorithm(TlsContext context, int ciphersuite) throws IOException
+ {
+ boolean isTLSv12 = TlsUtils.isTLSv12(context);
+
+ switch (ciphersuite)
+ {
+ case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DH_DSS_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_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_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_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_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_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_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_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+ 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_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_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_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_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_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_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_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_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_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_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
+ {
+ if (isTLSv12)
+ {
+ return PRFAlgorithm.tls_prf_sha256;
+ }
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_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_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_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_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_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_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_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_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_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_CAMELLIA_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_CAMELLIA_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_CAMELLIA_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_CAMELLIA_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/core/src/main/java/org/spongycastle/crypto/tls/TlsProtocolHandler.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsProtocolHandler.java
new file mode 100644
index 00000000..49dceb23
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsProtocolHandler.java
@@ -0,0 +1,22 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.SecureRandom;
+
+/**
+ * @deprecated use TlsClientProtocol instead
+ */
+public class TlsProtocolHandler
+ extends TlsClientProtocol
+{
+ public TlsProtocolHandler(InputStream is, OutputStream os)
+ {
+ super(is, os);
+ }
+
+ public TlsProtocolHandler(InputStream is, OutputStream os, SecureRandom sr)
+ {
+ super(is, os, sr);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsRSAKeyExchange.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsRSAKeyExchange.java
new file mode 100644
index 00000000..10cace4b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsRSAKeyExchange.java
@@ -0,0 +1,191 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Vector;
+
+import org.spongycastle.asn1.x509.KeyUsage;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+import org.spongycastle.crypto.util.PublicKeyFactory;
+import org.spongycastle.util.io.Streams;
+
+/**
+ * TLS 1.0/1.1 and SSLv3 RSA key exchange.
+ */
+public class TlsRSAKeyExchange
+ extends AbstractTlsKeyExchange
+{
+ protected AsymmetricKeyParameter serverPublicKey = null;
+
+ protected RSAKeyParameters rsaServerPublicKey = null;
+
+ protected TlsEncryptionCredentials serverCredentials = null;
+
+ protected byte[] premasterSecret;
+
+ public TlsRSAKeyExchange(Vector supportedSignatureAlgorithms)
+ {
+ super(KeyExchangeAlgorithm.RSA, supportedSignatureAlgorithms);
+ }
+
+ public void skipServerCredentials()
+ throws IOException
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ 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 void processServerCertificate(Certificate serverCertificate)
+ throws IOException
+ {
+ if (serverCertificate.isEmpty())
+ {
+ throw new TlsFatalAlert(AlertDescription.bad_certificate);
+ }
+
+ org.spongycastle.asn1.x509.Certificate x509Cert = serverCertificate.getCertificateAt(0);
+
+ SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo();
+ try
+ {
+ this.serverPublicKey = PublicKeyFactory.createKey(keyInfo);
+ }
+ catch (RuntimeException e)
+ {
+ throw new TlsFatalAlert(AlertDescription.unsupported_certificate);
+ }
+
+ // Sanity check the PublicKeyFactory
+ if (this.serverPublicKey.isPrivate())
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ this.rsaServerPublicKey = validateRSAPublicKey((RSAKeyParameters)this.serverPublicKey);
+
+ TlsUtils.validateKeyUsage(x509Cert, KeyUsage.keyEncipherment);
+
+ super.processServerCertificate(serverCertificate);
+ }
+
+ public void validateCertificateRequest(CertificateRequest certificateRequest)
+ throws IOException
+ {
+ short[] types = certificateRequest.getCertificateTypes();
+ for (int i = 0; i < types.length; ++i)
+ {
+ switch (types[i])
+ {
+ case ClientCertificateType.rsa_sign:
+ case ClientCertificateType.dss_sign:
+ case ClientCertificateType.ecdsa_sign:
+ break;
+ default:
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+ }
+
+ public void processClientCredentials(TlsCredentials clientCredentials)
+ throws IOException
+ {
+ if (!(clientCredentials instanceof TlsSignerCredentials))
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public void generateClientKeyExchange(OutputStream output)
+ throws IOException
+ {
+ this.premasterSecret = TlsRSAUtils.generateEncryptedPreMasterSecret(context, rsaServerPublicKey, output);
+ }
+
+ public void processClientKeyExchange(InputStream input)
+ throws IOException
+ {
+ byte[] encryptedPreMasterSecret;
+ if (TlsUtils.isSSL(context))
+ {
+ // TODO Do any SSLv3 clients actually include the length?
+ encryptedPreMasterSecret = Streams.readAll(input);
+ }
+ else
+ {
+ encryptedPreMasterSecret = TlsUtils.readOpaque16(input);
+ }
+
+ this.premasterSecret = serverCredentials.decryptPreMasterSecret(encryptedPreMasterSecret);
+ }
+
+ public byte[] generatePremasterSecret()
+ throws IOException
+ {
+ if (this.premasterSecret == null)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ byte[] tmp = this.premasterSecret;
+ this.premasterSecret = null;
+ return tmp;
+ }
+
+ // Would be needed to process RSA_EXPORT server key exchange
+ // protected void processRSAServerKeyExchange(InputStream is, Signer signer) throws IOException
+ // {
+ // InputStream sigIn = is;
+ // if (signer != null)
+ // {
+ // sigIn = new SignerInputStream(is, signer);
+ // }
+ //
+ // byte[] modulusBytes = TlsUtils.readOpaque16(sigIn);
+ // byte[] exponentBytes = TlsUtils.readOpaque16(sigIn);
+ //
+ // if (signer != null)
+ // {
+ // byte[] sigByte = TlsUtils.readOpaque16(is);
+ //
+ // if (!signer.verifySignature(sigByte))
+ // {
+ // handler.failWithError(AlertLevel.fatal, AlertDescription.bad_certificate);
+ // }
+ // }
+ //
+ // BigInteger modulus = new BigInteger(1, modulusBytes);
+ // BigInteger exponent = new BigInteger(1, exponentBytes);
+ //
+ // this.rsaServerPublicKey = validateRSAPublicKey(new RSAKeyParameters(false, modulus,
+ // exponent));
+ // }
+
+ protected RSAKeyParameters validateRSAPublicKey(RSAKeyParameters key)
+ throws IOException
+ {
+ // TODO What is the minimum bit length required?
+ // key.getModulus().bitLength();
+
+ if (!key.getExponent().isProbablePrime(2))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ return key;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsRSASigner.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsRSASigner.java
new file mode 100644
index 00000000..9511b078
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsRSASigner.java
@@ -0,0 +1,112 @@
+package org.spongycastle.crypto.tls;
+
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.Signer;
+import org.spongycastle.crypto.digests.NullDigest;
+import org.spongycastle.crypto.encodings.PKCS1Encoding;
+import org.spongycastle.crypto.engines.RSABlindedEngine;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+import org.spongycastle.crypto.signers.GenericSigner;
+import org.spongycastle.crypto.signers.RSADigestSigner;
+
+public class TlsRSASigner
+ extends AbstractTlsSigner
+{
+ public byte[] generateRawSignature(SignatureAndHashAlgorithm algorithm,
+ AsymmetricKeyParameter privateKey, byte[] hash)
+ throws CryptoException
+ {
+ Signer signer = makeSigner(algorithm, true, true,
+ new ParametersWithRandom(privateKey, this.context.getSecureRandom()));
+ signer.update(hash, 0, hash.length);
+ return signer.generateSignature();
+ }
+
+ public boolean verifyRawSignature(SignatureAndHashAlgorithm algorithm, byte[] sigBytes,
+ AsymmetricKeyParameter publicKey, byte[] hash)
+ throws CryptoException
+ {
+ Signer signer = makeSigner(algorithm, true, false, publicKey);
+ signer.update(hash, 0, hash.length);
+ return signer.verifySignature(sigBytes);
+ }
+
+ public Signer createSigner(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter privateKey)
+ {
+ return makeSigner(algorithm, false, true, new ParametersWithRandom(privateKey, this.context.getSecureRandom()));
+ }
+
+ public Signer createVerifyer(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter publicKey)
+ {
+ return makeSigner(algorithm, false, false, publicKey);
+ }
+
+ public boolean isValidPublicKey(AsymmetricKeyParameter publicKey)
+ {
+ return publicKey instanceof RSAKeyParameters && !publicKey.isPrivate();
+ }
+
+ 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 (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, TlsUtils.getOIDForHashAlgorithm(algorithm.getHash()));
+ }
+ else
+ {
+ /*
+ * RFC 5246 4.7. Note that earlier versions of TLS used a different RSA signature scheme
+ * that did not include a DigestInfo encoding.
+ */
+ s = new GenericSigner(createRSAImpl(), d);
+ }
+ s.init(forSigning, cp);
+ return s;
+ }
+
+ protected AsymmetricBlockCipher createRSAImpl()
+ {
+ /*
+ * RFC 5264 7.4.7.1. Implementation note: It is now known that remote timing-based attacks
+ * on TLS are possible, at least when the client and server are on the same LAN.
+ * Accordingly, implementations that use static RSA keys MUST use RSA blinding or some other
+ * anti-timing technique, as described in [TIMING].
+ */
+ return new PKCS1Encoding(new RSABlindedEngine());
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsRSAUtils.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsRSAUtils.java
new file mode 100644
index 00000000..ecc058b5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsRSAUtils.java
@@ -0,0 +1,140 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.encodings.PKCS1Encoding;
+import org.spongycastle.crypto.engines.RSABlindedEngine;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+import org.spongycastle.util.Arrays;
+
+public class TlsRSAUtils
+{
+ public static byte[] generateEncryptedPreMasterSecret(TlsContext context, RSAKeyParameters rsaServerPublicKey,
+ OutputStream output) throws IOException
+ {
+ /*
+ * Choose a PremasterSecret and send it encrypted to the server
+ */
+ byte[] premasterSecret = new byte[48];
+ context.getSecureRandom().nextBytes(premasterSecret);
+ TlsUtils.writeVersion(context.getClientVersion(), premasterSecret, 0);
+
+ PKCS1Encoding encoding = new PKCS1Encoding(new RSABlindedEngine());
+ encoding.init(true, new ParametersWithRandom(rsaServerPublicKey, context.getSecureRandom()));
+
+ try
+ {
+ byte[] encryptedPreMasterSecret = encoding.processBlock(premasterSecret, 0, premasterSecret.length);
+
+ if (TlsUtils.isSSL(context))
+ {
+ // TODO Do any SSLv3 servers actually expect the length?
+ output.write(encryptedPreMasterSecret);
+ }
+ else
+ {
+ TlsUtils.writeOpaque16(encryptedPreMasterSecret, output);
+ }
+ }
+ catch (InvalidCipherTextException e)
+ {
+ /*
+ * This should never happen, only during decryption.
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ return premasterSecret;
+ }
+
+ /**
+ * @deprecated {@link TlsEncryptionCredentials#decryptPreMasterSecret(byte[])} is expected to decrypt safely
+ */
+ public static byte[] safeDecryptPreMasterSecret(TlsContext context, TlsEncryptionCredentials encryptionCredentials,
+ byte[] encryptedPreMasterSecret) throws IOException
+ {
+ return encryptionCredentials.decryptPreMasterSecret(encryptedPreMasterSecret);
+ }
+
+ public static byte[] safeDecryptPreMasterSecret(TlsContext context, RSAKeyParameters rsaServerPrivateKey,
+ byte[] encryptedPreMasterSecret)
+ {
+ /*
+ * RFC 5246 7.4.7.1.
+ */
+ ProtocolVersion clientVersion = context.getClientVersion();
+
+ // TODO Provide as configuration option?
+ boolean versionNumberCheckDisabled = false;
+
+ /*
+ * Generate 48 random bytes we can use as a Pre-Master-Secret, if the
+ * PKCS1 padding check should fail.
+ */
+ byte[] fallback = new byte[48];
+ context.getSecureRandom().nextBytes(fallback);
+
+ byte[] M = Arrays.clone(fallback);
+ try
+ {
+ PKCS1Encoding encoding = new PKCS1Encoding(new RSABlindedEngine(), fallback);
+ encoding.init(false,
+ new ParametersWithRandom(rsaServerPrivateKey, context.getSecureRandom()));
+
+ M = encoding.processBlock(encryptedPreMasterSecret, 0, encryptedPreMasterSecret.length);
+ }
+ catch (Exception e)
+ {
+ /*
+ * This should never happen since the decryption should never throw an exception
+ * and return a random value instead.
+ *
+ * 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 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.
+ *
+ * So there is nothing to do here.
+ */
+ }
+ else
+ {
+ /*
+ * OK, we need to compare the version number in the decrypted Pre-Master-Secret with the
+ * clientVersion received during the handshake. If they don't match, we replace the
+ * decrypted Pre-Master-Secret with a random one.
+ */
+ int correct = (clientVersion.getMajorVersion() ^ (M[0] & 0xff))
+ | (clientVersion.getMinorVersion() ^ (M[1] & 0xff));
+ correct |= correct >> 1;
+ correct |= correct >> 2;
+ correct |= correct >> 4;
+ int mask = ~((correct & 1) - 1);
+
+ /*
+ * mask will be all bits set to 0xff if the version number differed.
+ */
+ for (int i = 0; i < 48; i++)
+ {
+ M[i] = (byte)((M[i] & (~mask)) | (fallback[i] & mask));
+ }
+ }
+ return M;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsSRPKeyExchange.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsSRPKeyExchange.java
new file mode 100644
index 00000000..6e9072ed
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsSRPKeyExchange.java
@@ -0,0 +1,205 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.util.Vector;
+
+import org.spongycastle.asn1.x509.KeyUsage;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.Signer;
+import org.spongycastle.crypto.agreement.srp.SRP6Client;
+import org.spongycastle.crypto.agreement.srp.SRP6Util;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.util.PublicKeyFactory;
+import org.spongycastle.util.BigIntegers;
+import org.spongycastle.util.io.TeeInputStream;
+
+/**
+ * TLS 1.1 SRP key exchange (RFC 5054).
+ */
+public class TlsSRPKeyExchange extends AbstractTlsKeyExchange
+{
+ protected TlsSigner tlsSigner;
+ protected byte[] identity;
+ protected byte[] password;
+
+ protected AsymmetricKeyParameter serverPublicKey = null;
+
+ protected byte[] s = null;
+ protected BigInteger B = null;
+ protected SRP6Client srpClient = new SRP6Client();
+
+ public TlsSRPKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms, byte[] identity, byte[] password)
+ {
+ super(keyExchange, supportedSignatureAlgorithms);
+
+ switch (keyExchange)
+ {
+ case KeyExchangeAlgorithm.SRP:
+ this.tlsSigner = null;
+ break;
+ case KeyExchangeAlgorithm.SRP_RSA:
+ this.tlsSigner = new TlsRSASigner();
+ break;
+ case KeyExchangeAlgorithm.SRP_DSS:
+ this.tlsSigner = new TlsDSSSigner();
+ break;
+ default:
+ throw new IllegalArgumentException("unsupported key exchange algorithm");
+ }
+
+ this.keyExchange = keyExchange;
+ this.identity = identity;
+ this.password = password;
+ }
+
+ public void init(TlsContext context)
+ {
+ super.init(context);
+
+ if (this.tlsSigner != null) {
+ this.tlsSigner.init(context);
+ }
+ }
+
+ public void skipServerCredentials() throws IOException
+ {
+ if (tlsSigner != null)
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ }
+
+ public void processServerCertificate(Certificate serverCertificate) throws IOException
+ {
+ if (tlsSigner == null)
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ if (serverCertificate.isEmpty())
+ {
+ throw new TlsFatalAlert(AlertDescription.bad_certificate);
+ }
+
+ org.spongycastle.asn1.x509.Certificate x509Cert = serverCertificate.getCertificateAt(0);
+
+ SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo();
+ try
+ {
+ this.serverPublicKey = PublicKeyFactory.createKey(keyInfo);
+ }
+ catch (RuntimeException e)
+ {
+ throw new TlsFatalAlert(AlertDescription.unsupported_certificate);
+ }
+
+ if (!tlsSigner.isValidPublicKey(this.serverPublicKey))
+ {
+ throw new TlsFatalAlert(AlertDescription.certificate_unknown);
+ }
+
+ TlsUtils.validateKeyUsage(x509Cert, KeyUsage.digitalSignature);
+
+ super.processServerCertificate(serverCertificate);
+ }
+
+ public boolean requiresServerKeyExchange()
+ {
+ return true;
+ }
+
+ public void processServerKeyExchange(InputStream input) throws IOException
+ {
+ SecurityParameters securityParameters = context.getSecurityParameters();
+
+ SignerInputBuffer buf = null;
+ InputStream teeIn = input;
+
+ if (tlsSigner != null)
+ {
+ buf = new SignerInputBuffer();
+ teeIn = new TeeInputStream(input, buf);
+ }
+
+ byte[] NBytes = TlsUtils.readOpaque16(teeIn);
+ byte[] gBytes = TlsUtils.readOpaque16(teeIn);
+ byte[] sBytes = TlsUtils.readOpaque8(teeIn);
+ byte[] BBytes = TlsUtils.readOpaque16(teeIn);
+
+ if (buf != null)
+ {
+ DigitallySigned signed_params = DigitallySigned.parse(context, input);
+
+ Signer signer = initVerifyer(tlsSigner, signed_params.getAlgorithm(), securityParameters);
+ buf.updateSigner(signer);
+ if (!signer.verifySignature(signed_params.getSignature()))
+ {
+ throw new TlsFatalAlert(AlertDescription.decrypt_error);
+ }
+ }
+
+ BigInteger N = new BigInteger(1, NBytes);
+ BigInteger g = new BigInteger(1, gBytes);
+
+ // TODO Validate group parameters (see RFC 5054)
+// throw new TlsFatalAlert(AlertDescription.insufficient_security);
+
+ this.s = sBytes;
+
+ /*
+ * RFC 5054 2.5.3: The client MUST abort the handshake with an "illegal_parameter" alert if
+ * B % N = 0.
+ */
+ try
+ {
+ this.B = SRP6Util.validatePublicValue(N, new BigInteger(1, BBytes));
+ }
+ catch (CryptoException e)
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ this.srpClient.init(N, g, TlsUtils.createHash(HashAlgorithm.sha1), context.getSecureRandom());
+ }
+
+ public void validateCertificateRequest(CertificateRequest certificateRequest) throws IOException
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ public void processClientCredentials(TlsCredentials clientCredentials) throws IOException
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ public void generateClientKeyExchange(OutputStream output) throws IOException
+ {
+ BigInteger A = srpClient.generateClientCredentials(s, this.identity, this.password);
+ TlsUtils.writeOpaque16(BigIntegers.asUnsignedByteArray(A), output);
+ }
+
+ public byte[] generatePremasterSecret() throws IOException
+ {
+ try
+ {
+ // TODO Check if this needs to be a fixed size
+ return BigIntegers.asUnsignedByteArray(srpClient.calculateSecret(B));
+ }
+ catch (CryptoException e)
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+
+ protected Signer initVerifyer(TlsSigner tlsSigner, SignatureAndHashAlgorithm algorithm, SecurityParameters securityParameters)
+ {
+ 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/core/src/main/java/org/spongycastle/crypto/tls/TlsSRPUtils.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsSRPUtils.java
new file mode 100644
index 00000000..48ddefb7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsSRPUtils.java
@@ -0,0 +1,48 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Hashtable;
+
+import org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/tls/TlsSRTPUtils.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsSRTPUtils.java
new file mode 100644
index 00000000..edc48795
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsSRTPUtils.java
@@ -0,0 +1,74 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Hashtable;
+
+import org.spongycastle.util.Integers;
+
+/**
+ * RFC 5764 DTLS Extension to Establish Keys for SRTP.
+ */
+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
+ {
+ 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");
+ }
+
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+
+ // SRTPProtectionProfiles
+ TlsUtils.writeUint16ArrayWithUint16Length(useSRTPData.getProtectionProfiles(), buf);
+
+ // srtp_mki
+ TlsUtils.writeOpaque8(useSRTPData.getMki(), buf);
+
+ return buf.toByteArray();
+ }
+
+ public static UseSRTPData readUseSRTPExtension(byte[] extensionData)
+ throws IOException
+ {
+ if (extensionData == null)
+ {
+ throw new IllegalArgumentException("'extensionData' cannot be null");
+ }
+
+ ByteArrayInputStream buf = new ByteArrayInputStream(extensionData);
+
+ // SRTPProtectionProfiles
+ int length = TlsUtils.readUint16(buf);
+ if (length < 2 || (length & 1) != 0)
+ {
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+ int[] protectionProfiles = TlsUtils.readUint16Array(length / 2, buf);
+
+ // srtp_mki
+ byte[] mki = TlsUtils.readOpaque8(buf);
+
+ TlsProtocol.assertEmpty(buf);
+
+ return new UseSRTPData(protectionProfiles, mki);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsServer.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsServer.java
new file mode 100644
index 00000000..225963f3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsServer.java
@@ -0,0 +1,90 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.Vector;
+
+public interface TlsServer
+ extends TlsPeer
+{
+ void init(TlsServerContext context);
+
+ void notifyClientVersion(ProtocolVersion clientVersion) throws IOException;
+
+ void notifyOfferedCipherSuites(int[] offeredCipherSuites)
+ throws IOException;
+
+ void notifyOfferedCompressionMethods(short[] offeredCompressionMethods)
+ throws IOException;
+
+ // Hashtable is (Integer -> byte[])
+ void processClientExtensions(Hashtable clientExtensions)
+ throws IOException;
+
+ ProtocolVersion getServerVersion()
+ throws IOException;
+
+ int getSelectedCipherSuite()
+ throws IOException;
+
+ short getSelectedCompressionMethod()
+ throws IOException;
+
+ // Hashtable is (Integer -> byte[])
+ Hashtable getServerExtensions()
+ throws IOException;
+
+ // Vector is (SupplementalDataEntry)
+ Vector getServerSupplementalData()
+ throws IOException;
+
+ 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()
+ throws IOException;
+
+ // Vector is (SupplementalDataEntry)
+ void processClientSupplementalData(Vector clientSupplementalData)
+ throws IOException;
+
+ /**
+ * 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;
+
+ /**
+ * RFC 5077 3.3. NewSessionTicket Handshake Message.
+ * <p>
+ * This method will be called (only) if a NewSessionTicket extension was sent by the server. See
+ * <i>RFC 5077 4. Recommended Ticket Construction</i> for recommended format and protection.
+ *
+ * @return The ticket.
+ * @throws IOException
+ */
+ NewSessionTicket getNewSessionTicket()
+ throws IOException;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsServerContext.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsServerContext.java
new file mode 100644
index 00000000..48480f36
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsServerContext.java
@@ -0,0 +1,6 @@
+package org.spongycastle.crypto.tls;
+
+public interface TlsServerContext
+ extends TlsContext
+{
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsServerContextImpl.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsServerContextImpl.java
new file mode 100644
index 00000000..27063350
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsServerContextImpl.java
@@ -0,0 +1,18 @@
+package org.spongycastle.crypto.tls;
+
+import java.security.SecureRandom;
+
+class TlsServerContextImpl
+ extends AbstractTlsContext
+ implements TlsServerContext
+{
+ TlsServerContextImpl(SecureRandom secureRandom, SecurityParameters securityParameters)
+ {
+ super(secureRandom, securityParameters);
+ }
+
+ public boolean isServer()
+ {
+ return true;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsServerProtocol.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsServerProtocol.java
new file mode 100644
index 00000000..b4e3b04c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsServerProtocol.java
@@ -0,0 +1,778 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.SecureRandom;
+import java.util.Vector;
+
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.util.PublicKeyFactory;
+import org.spongycastle.util.Arrays;
+
+public class TlsServerProtocol
+ extends TlsProtocol
+{
+ protected TlsServer tlsServer = null;
+ protected TlsServerContextImpl tlsServerContext = null;
+
+ protected TlsKeyExchange keyExchange = null;
+ protected TlsCredentials serverCredentials = null;
+ protected CertificateRequest certificateRequest = null;
+
+ protected short clientCertificateType = -1;
+ protected TlsHandshakeHash prepareFinishHash = null;
+
+ public TlsServerProtocol(InputStream input, OutputStream output, SecureRandom secureRandom)
+ {
+ super(input, output, secureRandom);
+ }
+
+ /**
+ * Receives a TLS handshake in the role of server
+ *
+ * @param tlsServer
+ * @throws IOException If handshake was not successful.
+ */
+ 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");
+ }
+
+ this.tlsServer = tlsServer;
+
+ this.securityParameters = new SecurityParameters();
+ this.securityParameters.entity = ConnectionEnd.server;
+
+ this.tlsServerContext = new TlsServerContextImpl(secureRandom, securityParameters);
+
+ this.securityParameters.serverRandom = createRandomBlock(tlsServer.shouldUseGMTUnixTime(),
+ tlsServerContext.getNonceRandomGenerator());
+
+ this.tlsServer.init(tlsServerContext);
+ this.recordStream.init(tlsServerContext);
+
+ this.recordStream.setRestrictReadVersion(false);
+
+ completeHandshake();
+ }
+
+ protected void cleanupHandshake()
+ {
+ super.cleanupHandshake();
+
+ this.keyExchange = null;
+ this.serverCredentials = null;
+ this.certificateRequest = null;
+ this.prepareFinishHash = null;
+ }
+
+ protected AbstractTlsContext getContext()
+ {
+ return tlsServerContext;
+ }
+
+ protected TlsPeer getPeer()
+ {
+ return tlsServer;
+ }
+
+ protected void handleHandshakeMessage(short type, byte[] data)
+ throws IOException
+ {
+ ByteArrayInputStream buf = new ByteArrayInputStream(data);
+
+ switch (type)
+ {
+ case HandshakeType.client_hello:
+ {
+ switch (this.connection_state)
+ {
+ case CS_START:
+ {
+ receiveClientHelloMessage(buf);
+ this.connection_state = CS_CLIENT_HELLO;
+
+ sendServerHelloMessage();
+ this.connection_state = CS_SERVER_HELLO;
+
+ Vector serverSupplementalData = tlsServer.getServerSupplementalData();
+ if (serverSupplementalData != null)
+ {
+ sendSupplementalDataMessage(serverSupplementalData);
+ }
+ this.connection_state = CS_SERVER_SUPPLEMENTAL_DATA;
+
+ this.keyExchange = tlsServer.getKeyExchange();
+ this.keyExchange.init(getContext());
+
+ this.serverCredentials = tlsServer.getCredentials();
+
+ Certificate serverCertificate = null;
+
+ if (this.serverCredentials == null)
+ {
+ this.keyExchange.skipServerCredentials();
+ }
+ else
+ {
+ this.keyExchange.processServerCredentials(this.serverCredentials);
+
+ 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)
+ {
+ sendServerKeyExchangeMessage(serverKeyExchange);
+ }
+ this.connection_state = CS_SERVER_KEY_EXCHANGE;
+
+ if (this.serverCredentials != null)
+ {
+ this.certificateRequest = tlsServer.getCertificateRequest();
+ if (this.certificateRequest != null)
+ {
+ this.keyExchange.validateCertificateRequest(certificateRequest);
+
+ sendCertificateRequestMessage(certificateRequest);
+
+ TlsUtils.trackHashAlgorithms(this.recordStream.getHandshakeHash(),
+ this.certificateRequest.getSupportedSignatureAlgorithms());
+ }
+ }
+ this.connection_state = CS_CERTIFICATE_REQUEST;
+
+ sendServerHelloDoneMessage();
+ this.connection_state = CS_SERVER_HELLO_DONE;
+
+ this.recordStream.getHandshakeHash().sealHashAlgorithms();
+
+ break;
+ }
+ default:
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ break;
+ }
+ case HandshakeType.supplemental_data:
+ {
+ switch (this.connection_state)
+ {
+ case CS_SERVER_HELLO_DONE:
+ {
+ tlsServer.processClientSupplementalData(readSupplementalDataMessage(buf));
+ this.connection_state = CS_CLIENT_SUPPLEMENTAL_DATA;
+ break;
+ }
+ default:
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ break;
+ }
+ case HandshakeType.certificate:
+ {
+ switch (this.connection_state)
+ {
+ case CS_SERVER_HELLO_DONE:
+ {
+ tlsServer.processClientSupplementalData(null);
+ // NB: Fall through to next case label
+ }
+ case CS_CLIENT_SUPPLEMENTAL_DATA:
+ {
+ if (this.certificateRequest == null)
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ receiveCertificateMessage(buf);
+ this.connection_state = CS_CLIENT_CERTIFICATE;
+ break;
+ }
+ default:
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ break;
+ }
+ case HandshakeType.client_key_exchange:
+ {
+ switch (this.connection_state)
+ {
+ case CS_SERVER_HELLO_DONE:
+ {
+ tlsServer.processClientSupplementalData(null);
+ // NB: Fall through to next case label
+ }
+ case CS_CLIENT_SUPPLEMENTAL_DATA:
+ {
+ if (this.certificateRequest == null)
+ {
+ this.keyExchange.skipClientCredentials();
+ }
+ else
+ {
+ if (TlsUtils.isTLSv12(getContext()))
+ {
+ /*
+ * RFC 5246 If no suitable certificate is available, the client MUST send a
+ * certificate message containing no certificates.
+ *
+ * NOTE: In previous RFCs, this was SHOULD instead of MUST.
+ */
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ else if (TlsUtils.isSSL(getContext()))
+ {
+ if (this.peerCertificate == null)
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ }
+ else
+ {
+ notifyClientCertificate(Certificate.EMPTY_CHAIN);
+ }
+ }
+ // NB: Fall through to next case label
+ }
+ case CS_CLIENT_CERTIFICATE:
+ {
+ receiveClientKeyExchangeMessage(buf);
+ this.connection_state = CS_CLIENT_KEY_EXCHANGE;
+ break;
+ }
+ default:
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ break;
+ }
+ case HandshakeType.certificate_verify:
+ {
+ switch (this.connection_state)
+ {
+ case CS_CLIENT_KEY_EXCHANGE:
+ {
+ /*
+ * 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 parameters).
+ */
+ if (!expectCertificateVerifyMessage())
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ receiveCertificateVerifyMessage(buf);
+ this.connection_state = CS_CERTIFICATE_VERIFY;
+
+ break;
+ }
+ default:
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ break;
+ }
+ case HandshakeType.finished:
+ {
+ switch (this.connection_state)
+ {
+ 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 (this.expectSessionTicket)
+ {
+ sendNewSessionTicketMessage(tlsServer.getNewSessionTicket());
+ sendChangeCipherSpecMessage();
+ }
+ this.connection_state = CS_SERVER_SESSION_TICKET;
+
+ sendFinishedMessage();
+ this.connection_state = CS_SERVER_FINISHED;
+ this.connection_state = CS_END;
+ break;
+ }
+ default:
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ break;
+ }
+ case HandshakeType.hello_request:
+ case HandshakeType.hello_verify_request:
+ case HandshakeType.server_hello:
+ case HandshakeType.server_key_exchange:
+ case HandshakeType.certificate_request:
+ case HandshakeType.server_hello_done:
+ case HandshakeType.session_ticket:
+ default:
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ }
+
+ protected void handleWarningMessage(short description)
+ throws IOException
+ {
+ switch (description)
+ {
+ case AlertDescription.no_certificate:
+ {
+ /*
+ * 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 (TlsUtils.isSSL(getContext()) && certificateRequest != null)
+ {
+ notifyClientCertificate(Certificate.EMPTY_CHAIN);
+ }
+ break;
+ }
+ default:
+ {
+ super.handleWarningMessage(description);
+ }
+ }
+ }
+
+ protected void notifyClientCertificate(Certificate clientCertificate)
+ throws IOException
+ {
+ if (certificateRequest == null)
+ {
+ throw new IllegalStateException();
+ }
+
+ if (this.peerCertificate != null)
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ this.peerCertificate = clientCertificate;
+
+ if (clientCertificate.isEmpty())
+ {
+ this.keyExchange.skipClientCredentials();
+ }
+ else
+ {
+
+ /*
+ * TODO RFC 5246 7.4.6. If the certificate_authorities list in the certificate request
+ * message was non-empty, one of the certificates in the certificate chain SHOULD be
+ * issued by one of the listed CAs.
+ */
+
+ this.clientCertificateType = TlsUtils.getClientCertificateType(clientCertificate,
+ this.serverCredentials.getCertificate());
+
+ this.keyExchange.processClientCertificate(clientCertificate);
+ }
+
+ /*
+ * RFC 5246 7.4.6. If the client does not send any certificates, the server MAY at its
+ * discretion either continue the handshake without client authentication, or respond with a
+ * fatal handshake_failure alert. Also, if some aspect of the certificate chain was
+ * unacceptable (e.g., it was not signed by a known, trusted CA), the server MAY at its
+ * discretion either continue the handshake (considering the client unauthenticated) or send
+ * a fatal alert.
+ */
+ this.tlsServer.notifyClientCertificate(clientCertificate);
+ }
+
+ protected void receiveCertificateMessage(ByteArrayInputStream buf)
+ throws IOException
+ {
+ Certificate clientCertificate = Certificate.parse(buf);
+
+ assertEmpty(buf);
+
+ notifyClientCertificate(clientCertificate);
+ }
+
+ protected void receiveCertificateVerifyMessage(ByteArrayInputStream buf)
+ throws IOException
+ {
+ DigitallySigned clientCertificateVerify = DigitallySigned.parse(getContext(), buf);
+
+ assertEmpty(buf);
+
+ // Verify the CertificateVerify message contains a correct signature.
+ boolean verified = false;
+ try
+ {
+ byte[] certificateVerifyHash;
+ if (TlsUtils.isTLSv12(getContext()))
+ {
+ certificateVerifyHash = prepareFinishHash.getFinalHash(clientCertificateVerify.getAlgorithm().getHash());
+ }
+ else
+ {
+ certificateVerifyHash = TlsProtocol.getCurrentPRFHash(getContext(), prepareFinishHash, null);
+ }
+
+ org.spongycastle.asn1.x509.Certificate x509Cert = this.peerCertificate.getCertificateAt(0);
+ SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo();
+ AsymmetricKeyParameter publicKey = PublicKeyFactory.createKey(keyInfo);
+
+ TlsSigner tlsSigner = TlsUtils.createTlsSigner(this.clientCertificateType);
+ tlsSigner.init(getContext());
+ verified = tlsSigner.verifyRawSignature(clientCertificateVerify.getAlgorithm(),
+ clientCertificateVerify.getSignature(), publicKey, certificateVerifyHash);
+ }
+ catch (Exception e)
+ {
+ }
+
+ if (!verified)
+ {
+ throw new TlsFatalAlert(AlertDescription.decrypt_error);
+ }
+ }
+
+ protected void receiveClientHelloMessage(ByteArrayInputStream buf)
+ throws IOException
+ {
+ ProtocolVersion client_version = TlsUtils.readVersion(buf);
+ if (client_version.isDTLS())
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ 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)
+ {
+ 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)
+ {
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+ this.offeredCipherSuites = TlsUtils.readUint16Array(cipher_suites_length / 2, buf);
+
+ /*
+ * 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.
+ */
+ int compression_methods_length = TlsUtils.readUint8(buf);
+ if (compression_methods_length < 1)
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ this.offeredCompressionMethods = TlsUtils.readUint8Array(compression_methods_length, buf);
+
+ /*
+ * 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.
+ */
+ this.clientExtensions = readExtensions(buf);
+
+ getContext().setClientVersion(client_version);
+
+ tlsServer.notifyClientVersion(client_version);
+
+ securityParameters.clientRandom = client_random;
+
+ tlsServer.notifyOfferedCipherSuites(offeredCipherSuites);
+ tlsServer.notifyOfferedCompressionMethods(offeredCompressionMethods);
+
+ /*
+ * RFC 5746 3.6. Server Behavior: Initial Handshake
+ */
+ {
+ /*
+ * RFC 5746 3.4. The client MUST include either an empty "renegotiation_info" extension,
+ * or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling cipher suite value in the
+ * ClientHello. Including both is NOT RECOMMENDED.
+ */
+
+ /*
+ * When a ClientHello is received, the server MUST check if it includes the
+ * TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. If it does, set the secure_renegotiation flag
+ * to TRUE.
+ */
+ if (Arrays.contains(offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV))
+ {
+ this.secure_renegotiation = true;
+ }
+
+ /*
+ * The server MUST check if the "renegotiation_info" extension is included in the
+ * ClientHello.
+ */
+ byte[] renegExtData = TlsUtils.getExtensionData(clientExtensions, EXT_RenegotiationInfo);
+ if (renegExtData != 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)))
+ {
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
+ }
+ }
+ }
+
+ tlsServer.notifySecureRenegotiation(this.secure_renegotiation);
+
+ if (clientExtensions != null)
+ {
+ tlsServer.processClientExtensions(clientExtensions);
+ }
+ }
+
+ protected void receiveClientKeyExchangeMessage(ByteArrayInputStream buf)
+ throws IOException
+ {
+ this.keyExchange.processClientKeyExchange(buf);
+
+ assertEmpty(buf);
+
+ establishMasterSecret(getContext(), keyExchange);
+ recordStream.setPendingConnectionState(getPeer().getCompression(), getPeer().getCipher());
+
+ this.prepareFinishHash = recordStream.prepareToFinish();
+
+ if (!expectSessionTicket)
+ {
+ sendChangeCipherSpecMessage();
+ }
+ }
+
+ protected void sendCertificateRequestMessage(CertificateRequest certificateRequest)
+ throws IOException
+ {
+ HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate_request);
+
+ certificateRequest.encode(message);
+
+ message.writeToRecordStream();
+ }
+
+ protected void sendCertificateStatusMessage(CertificateStatus certificateStatus)
+ throws IOException
+ {
+ HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate_status);
+
+ certificateStatus.encode(message);
+
+ message.writeToRecordStream();
+ }
+
+ protected void sendNewSessionTicketMessage(NewSessionTicket newSessionTicket)
+ throws IOException
+ {
+ if (newSessionTicket == null)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ HandshakeMessage message = new HandshakeMessage(HandshakeType.session_ticket);
+
+ newSessionTicket.encode(message);
+
+ message.writeToRecordStream();
+ }
+
+ protected void sendServerHelloMessage()
+ throws IOException
+ {
+ HandshakeMessage message = new HandshakeMessage(HandshakeType.server_hello);
+
+ ProtocolVersion server_version = tlsServer.getServerVersion();
+ if (!server_version.isEqualOrEarlierVersionOf(getContext().getClientVersion()))
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ recordStream.setReadVersion(server_version);
+ recordStream.setWriteVersion(server_version);
+ recordStream.setRestrictReadVersion(true);
+ getContext().setServerVersion(server_version);
+
+ TlsUtils.writeVersion(server_version, message);
+
+ 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, message);
+
+ int selectedCipherSuite = tlsServer.getSelectedCipherSuite();
+ if (!Arrays.contains(this.offeredCipherSuites, selectedCipherSuite)
+ || selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL
+ || selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV
+ || !TlsUtils.isValidCipherSuiteForVersion(selectedCipherSuite, server_version))
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ securityParameters.cipherSuite = selectedCipherSuite;
+
+ short selectedCompressionMethod = tlsServer.getSelectedCompressionMethod();
+ if (!Arrays.contains(this.offeredCompressionMethods, selectedCompressionMethod))
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ securityParameters.compressionAlgorithm = selectedCompressionMethod;
+
+ TlsUtils.writeUint16(selectedCipherSuite, message);
+ TlsUtils.writeUint8(selectedCompressionMethod, message);
+
+ this.serverExtensions = tlsServer.getServerExtensions();
+
+ /*
+ * RFC 5746 3.6. Server Behavior: Initial Handshake
+ */
+ if (this.secure_renegotiation)
+ {
+ byte[] renegExtData = TlsUtils.getExtensionData(this.serverExtensions, EXT_RenegotiationInfo);
+ boolean noRenegExt = (null == renegExtData);
+
+ if (noRenegExt)
+ {
+ /*
+ * Note that sending a "renegotiation_info" extension in response to a ClientHello
+ * containing only the SCSV is an explicit exception to the prohibition in RFC 5246,
+ * Section 7.4.1.4, on the server sending unsolicited extensions and is only allowed
+ * because the client is signaling its willingness to receive the extension via the
+ * TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV.
+ */
+
+ /*
+ * 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.securityParameters.encryptThenMAC = TlsExtensionsUtils.hasEncryptThenMACExtension(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);
+ }
+
+ securityParameters.prfAlgorithm = getPRFAlgorithm(getContext(), 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;
+
+ 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);
+
+ writeHandshakeMessage(message, 0, message.length);
+ }
+
+ protected void sendServerKeyExchangeMessage(byte[] serverKeyExchange)
+ throws IOException
+ {
+ HandshakeMessage message = new HandshakeMessage(HandshakeType.server_key_exchange, serverKeyExchange.length);
+
+ message.write(serverKeyExchange);
+
+ message.writeToRecordStream();
+ }
+
+ protected boolean expectCertificateVerifyMessage()
+ {
+ return this.clientCertificateType >= 0 && TlsUtils.hasSigningCapability(this.clientCertificateType);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsSession.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsSession.java
new file mode 100644
index 00000000..6d30e442
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsSession.java
@@ -0,0 +1,12 @@
+package org.spongycastle.crypto.tls;
+
+public interface TlsSession
+{
+ SessionParameters exportSessionParameters();
+
+ byte[] getSessionID();
+
+ void invalidate();
+
+ boolean isResumable();
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsSessionImpl.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsSessionImpl.java
new file mode 100644
index 00000000..af11bf08
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsSessionImpl.java
@@ -0,0 +1,48 @@
+package org.spongycastle.crypto.tls;
+
+import org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/tls/TlsSigner.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsSigner.java
new file mode 100644
index 00000000..021155e3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsSigner.java
@@ -0,0 +1,34 @@
+package org.spongycastle.crypto.tls;
+
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.Signer;
+import org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/tls/TlsSignerCredentials.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsSignerCredentials.java
new file mode 100644
index 00000000..da1a91cd
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsSignerCredentials.java
@@ -0,0 +1,12 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+public interface TlsSignerCredentials
+ extends TlsCredentials
+{
+ byte[] generateCertificateSignature(byte[] hash)
+ throws IOException;
+
+ SignatureAndHashAlgorithm getSignatureAndHashAlgorithm();
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsStreamCipher.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsStreamCipher.java
new file mode 100644
index 00000000..6394b391
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsStreamCipher.java
@@ -0,0 +1,178 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.StreamCipher;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Arrays;
+
+public class TlsStreamCipher
+ implements TlsCipher
+{
+ protected TlsContext context;
+
+ protected StreamCipher encryptCipher;
+ protected StreamCipher decryptCipher;
+
+ protected TlsMac writeMac;
+ protected TlsMac readMac;
+
+ protected boolean usesNonce;
+
+ /**
+ * @deprecated Use version with additional 'usesNonce' argument
+ */
+ public TlsStreamCipher(TlsContext context, StreamCipher clientWriteCipher,
+ StreamCipher serverWriteCipher, Digest clientWriteDigest, Digest serverWriteDigest,
+ int cipherKeySize) throws IOException
+ {
+ this(context, clientWriteCipher, serverWriteCipher, clientWriteDigest, serverWriteDigest, cipherKeySize, false);
+ }
+
+ public TlsStreamCipher(TlsContext context, StreamCipher clientWriteCipher,
+ StreamCipher serverWriteCipher, Digest clientWriteDigest, Digest serverWriteDigest,
+ int cipherKeySize, boolean usesNonce) throws IOException
+ {
+ boolean isServer = context.isServer();
+
+ this.context = context;
+ this.usesNonce = usesNonce;
+
+ this.encryptCipher = clientWriteCipher;
+ this.decryptCipher = serverWriteCipher;
+
+ int key_block_size = (2 * cipherKeySize) + clientWriteDigest.getDigestSize()
+ + serverWriteDigest.getDigestSize();
+
+ byte[] key_block = TlsUtils.calculateKeyBlock(context, key_block_size);
+
+ int offset = 0;
+
+ // Init MACs
+ TlsMac clientWriteMac = new TlsMac(context, clientWriteDigest, key_block, offset,
+ clientWriteDigest.getDigestSize());
+ offset += clientWriteDigest.getDigestSize();
+ TlsMac serverWriteMac = new TlsMac(context, serverWriteDigest, key_block, offset,
+ serverWriteDigest.getDigestSize());
+ offset += serverWriteDigest.getDigestSize();
+
+ // Build keys
+ KeyParameter clientWriteKey = new KeyParameter(key_block, offset, cipherKeySize);
+ offset += cipherKeySize;
+ KeyParameter serverWriteKey = new KeyParameter(key_block, offset, cipherKeySize);
+ offset += cipherKeySize;
+
+ if (offset != key_block_size)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ CipherParameters encryptParams, decryptParams;
+ if (isServer)
+ {
+ this.writeMac = serverWriteMac;
+ this.readMac = clientWriteMac;
+ this.encryptCipher = serverWriteCipher;
+ this.decryptCipher = clientWriteCipher;
+ encryptParams = serverWriteKey;
+ decryptParams = clientWriteKey;
+ }
+ else
+ {
+ this.writeMac = clientWriteMac;
+ this.readMac = serverWriteMac;
+ this.encryptCipher = clientWriteCipher;
+ this.decryptCipher = serverWriteCipher;
+ encryptParams = clientWriteKey;
+ decryptParams = serverWriteKey;
+ }
+
+ if (usesNonce)
+ {
+ byte[] dummyNonce = new byte[8];
+ encryptParams = new ParametersWithIV(encryptParams, dummyNonce);
+ decryptParams = new ParametersWithIV(decryptParams, dummyNonce);
+ }
+
+ this.encryptCipher.init(true, encryptParams);
+ this.decryptCipher.init(false, decryptParams);
+ }
+
+ public int getPlaintextLimit(int ciphertextLimit)
+ {
+ return ciphertextLimit - writeMac.getSize();
+ }
+
+ public byte[] encodePlaintext(long seqNo, short type, byte[] plaintext, int offset, int len)
+ {
+ /*
+ * draft-josefsson-salsa20-tls-04 2.1 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.
+ */
+ if (usesNonce)
+ {
+ updateIV(encryptCipher, true, seqNo);
+ }
+
+ byte[] outBuf = new byte[len + writeMac.getSize()];
+
+ encryptCipher.processBytes(plaintext, offset, len, outBuf, 0);
+
+ byte[] mac = writeMac.calculateMac(seqNo, type, plaintext, offset, len);
+ encryptCipher.processBytes(mac, 0, mac.length, outBuf, len);
+
+ return outBuf;
+ }
+
+ public byte[] decodeCiphertext(long seqNo, short type, byte[] ciphertext, int offset, int len)
+ throws IOException
+ {
+ /*
+ * draft-josefsson-salsa20-tls-04 2.1 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.
+ */
+ if (usesNonce)
+ {
+ updateIV(decryptCipher, false, seqNo);
+ }
+
+ int macSize = readMac.getSize();
+ if (len < macSize)
+ {
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+
+ int plaintextLength = len - macSize;
+
+ 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);
+ }
+
+ 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);
+ }
+ }
+
+ private void updateIV(StreamCipher cipher, boolean forEncryption, long seqNo)
+ {
+ byte[] nonce = new byte[8];
+ TlsUtils.writeUint64(seqNo, nonce, 0);
+ cipher.init(forEncryption, new ParametersWithIV(null, nonce));
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/TlsUtils.java b/core/src/main/java/org/spongycastle/crypto/tls/TlsUtils.java
new file mode 100644
index 00000000..118af480
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/TlsUtils.java
@@ -0,0 +1,1780 @@
+package org.spongycastle.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;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.spongycastle.asn1.ASN1Encoding;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.nist.NISTObjectIdentifiers;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.x509.Extensions;
+import org.spongycastle.asn1.x509.KeyUsage;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.spongycastle.asn1.x509.X509ObjectIdentifiers;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.MD5Digest;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA224Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.digests.SHA384Digest;
+import org.spongycastle.crypto.digests.SHA512Digest;
+import org.spongycastle.crypto.macs.HMac;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.DSAPublicKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+import org.spongycastle.crypto.util.PublicKeyFactory;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Integers;
+import org.spongycastle.util.Strings;
+import org.spongycastle.util.io.Streams;
+
+/**
+ * Some helper functions for MicroTLS.
+ */
+public class TlsUtils
+{
+ public static final byte[] EMPTY_BYTES = new byte[0];
+
+ 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 checkUint8(long 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 checkUint16(long 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 checkUint24(long 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 isValidUint8(long i)
+ {
+ return (i & 0xFFL) == i;
+ }
+
+ public static boolean isValidUint16(int i)
+ {
+ return (i & 0xFFFF) == i;
+ }
+
+ public static boolean isValidUint16(long i)
+ {
+ return (i & 0xFFFFL) == i;
+ }
+
+ public static boolean isValidUint24(int i)
+ {
+ return (i & 0xFFFFFF) == i;
+ }
+
+ public static boolean isValidUint24(long i)
+ {
+ return (i & 0xFFFFFFL) == i;
+ }
+
+ public static boolean isValidUint32(long i)
+ {
+ return (i & 0xFFFFFFFFL) == i;
+ }
+
+ public static boolean isValidUint48(long i)
+ {
+ return (i & 0xFFFFFFFFFFFFL) == i;
+ }
+
+ public static boolean isValidUint64(long i)
+ {
+ 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
+ {
+ output.write(i >>> 8);
+ output.write(i);
+ }
+
+ public static void writeUint16(int i, byte[] buf, int offset)
+ {
+ buf[offset] = (byte)(i >>> 8);
+ buf[offset + 1] = (byte)i;
+ }
+
+ public static void writeUint24(int i, OutputStream output)
+ throws IOException
+ {
+ output.write((byte)(i >>> 16));
+ output.write((byte)(i >>> 8));
+ output.write((byte)i);
+ }
+
+ public static void writeUint24(int i, byte[] buf, int offset)
+ {
+ buf[offset] = (byte)(i >>> 16);
+ buf[offset + 1] = (byte)(i >>> 8);
+ buf[offset + 2] = (byte)i;
+ }
+
+ public static void writeUint32(long i, OutputStream output)
+ throws IOException
+ {
+ output.write((byte)(i >>> 24));
+ output.write((byte)(i >>> 16));
+ output.write((byte)(i >>> 8));
+ output.write((byte)i);
+ }
+
+ public static void writeUint32(long i, byte[] buf, int offset)
+ {
+ buf[offset] = (byte)(i >>> 24);
+ buf[offset + 1] = (byte)(i >>> 16);
+ buf[offset + 2] = (byte)(i >>> 8);
+ 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);
+ buf[offset + 1] = (byte)(i >>> 32);
+ buf[offset + 2] = (byte)(i >>> 24);
+ buf[offset + 3] = (byte)(i >>> 16);
+ buf[offset + 4] = (byte)(i >>> 8);
+ buf[offset + 5] = (byte)i;
+ }
+
+ public static void writeUint64(long i, OutputStream output)
+ throws IOException
+ {
+ 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)
+ {
+ buf[offset] = (byte)(i >>> 56);
+ buf[offset + 1] = (byte)(i >>> 48);
+ buf[offset + 2] = (byte)(i >>> 40);
+ buf[offset + 3] = (byte)(i >>> 32);
+ buf[offset + 4] = (byte)(i >>> 24);
+ buf[offset + 5] = (byte)(i >>> 16);
+ buf[offset + 6] = (byte)(i >>> 8);
+ buf[offset + 7] = (byte)i;
+ }
+
+ public static void writeOpaque8(byte[] buf, OutputStream output)
+ throws IOException
+ {
+ 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);
+ }
+
+ public static void writeOpaque24(byte[] buf, OutputStream output)
+ throws IOException
+ {
+ checkUint24(buf.length);
+ writeUint24(buf.length, output);
+ output.write(buf);
+ }
+
+ public static void writeUint8Array(short[] uints, OutputStream output)
+ throws IOException
+ {
+ for (int i = 0; i < uints.length; ++i)
+ {
+ writeUint8(uints[i], output);
+ }
+ }
+
+ 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
+ {
+ for (int i = 0; i < uints.length; ++i)
+ {
+ writeUint16(uints[i], output);
+ }
+ }
+
+ 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
+ {
+ int i = input.read();
+ if (i < 0)
+ {
+ throw new EOFException();
+ }
+ return (short)i;
+ }
+
+ public static short readUint8(byte[] buf, int offset)
+ {
+ return (short)buf[offset];
+ }
+
+ public static int readUint16(InputStream input)
+ throws IOException
+ {
+ int i1 = input.read();
+ int i2 = input.read();
+ if (i2 < 0)
+ {
+ throw new EOFException();
+ }
+ return i1 << 8 | i2;
+ }
+
+ public static int readUint16(byte[] buf, int offset)
+ {
+ int n = (buf[offset] & 0xff) << 8;
+ n |= (buf[++offset] & 0xff);
+ return n;
+ }
+
+ public static int readUint24(InputStream input)
+ throws IOException
+ {
+ int i1 = input.read();
+ int i2 = input.read();
+ int i3 = input.read();
+ if (i3 < 0)
+ {
+ throw new EOFException();
+ }
+ return (i1 << 16) | (i2 << 8) | i3;
+ }
+
+ public static int readUint24(byte[] buf, int offset)
+ {
+ int n = (buf[offset] & 0xff) << 16;
+ n |= (buf[++offset] & 0xff) << 8;
+ n |= (buf[++offset] & 0xff);
+ return n;
+ }
+
+ public static long readUint32(InputStream input)
+ throws IOException
+ {
+ int i1 = input.read();
+ int i2 = input.read();
+ int i3 = input.read();
+ int i4 = input.read();
+ if (i4 < 0)
+ {
+ throw new EOFException();
+ }
+ return ((i1 << 2) | (i2 << 16) | (i3 << 8) | i4) & 0xFFFFFFFFL;
+ }
+
+ public static long readUint32(byte[] buf, int offset)
+ {
+ int n = (buf[offset] & 0xff) << 24;
+ n |= (buf[++offset] & 0xff) << 16;
+ n |= (buf[++offset] & 0xff) << 8;
+ n |= (buf[++offset] & 0xff);
+ return n & 0xFFFFFFFFL;
+ }
+
+ public static long readUint48(InputStream input)
+ throws IOException
+ {
+ int hi = readUint24(input);
+ int lo = readUint24(input);
+ return ((long)(hi & 0xffffffffL) << 24) | (long)(lo & 0xffffffffL);
+ }
+
+ public static long readUint48(byte[] buf, int offset)
+ {
+ int hi = readUint24(buf, offset);
+ int lo = readUint24(buf, offset + 3);
+ 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
+ {
+ if (length < 1)
+ {
+ return EMPTY_BYTES;
+ }
+ byte[] buf = new byte[length];
+ if (length != Streams.readFully(input, buf))
+ {
+ throw new EOFException();
+ }
+ return buf;
+ }
+
+ public static void readFully(byte[] buf, InputStream input)
+ throws IOException
+ {
+ int length = buf.length;
+ if (length > 0 && length != Streams.readFully(input, buf))
+ {
+ throw new EOFException();
+ }
+ }
+
+ public static byte[] readOpaque8(InputStream input)
+ throws IOException
+ {
+ short length = readUint8(input);
+ return readFully(length, input);
+ }
+
+ public static byte[] readOpaque16(InputStream input)
+ throws IOException
+ {
+ int length = readUint16(input);
+ return readFully(length, input);
+ }
+
+ public static byte[] readOpaque24(InputStream input)
+ throws IOException
+ {
+ int length = readUint24(input);
+ return readFully(length, input);
+ }
+
+ public static short[] readUint8Array(int count, InputStream input)
+ throws IOException
+ {
+ short[] uints = new short[count];
+ for (int i = 0; i < count; ++i)
+ {
+ uints[i] = readUint8(input);
+ }
+ return uints;
+ }
+
+ public static int[] readUint16Array(int count, InputStream input)
+ throws IOException
+ {
+ int[] uints = new int[count];
+ for (int i = 0; i < count; ++i)
+ {
+ uints[i] = readUint16(input);
+ }
+ return uints;
+ }
+
+ public static ProtocolVersion readVersion(byte[] buf, int offset)
+ throws IOException
+ {
+ return ProtocolVersion.get(buf[offset] & 0xFF, buf[offset + 1] & 0xFF);
+ }
+
+ public static ProtocolVersion readVersion(InputStream input)
+ throws IOException
+ {
+ int i1 = input.read();
+ int i2 = input.read();
+ if (i2 < 0)
+ {
+ throw new EOFException();
+ }
+ 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
+ {
+ int i1 = input.read();
+ int i2 = input.read();
+ if (i2 < 0)
+ {
+ throw new EOFException();
+ }
+ 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);
+ buf[offset] = (byte)(t >>> 24);
+ buf[offset + 1] = (byte)(t >>> 16);
+ buf[offset + 2] = (byte)(t >>> 8);
+ buf[offset + 3] = (byte)t;
+ }
+
+ public static void writeVersion(ProtocolVersion version, OutputStream output)
+ throws IOException
+ {
+ output.write(version.getMajorVersion());
+ output.write(version.getMinorVersion());
+ }
+
+ public static void writeVersion(ProtocolVersion version, byte[] buf, int offset)
+ {
+ buf[offset] = (byte)version.getMajorVersion();
+ buf[offset + 1] = (byte)version.getMinorVersion();
+ }
+
+ public static Vector getDefaultDSSSignatureAlgorithms()
+ {
+ return vectorOfOne(new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.dsa));
+ }
+
+ public static Vector getDefaultECDSASignatureAlgorithms()
+ {
+ return vectorOfOne(new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.ecdsa));
+ }
+
+ public static Vector getDefaultRSASignatureAlgorithms()
+ {
+ 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());
+ }
+
+ /**
+ * Add a 'signature_algorithms' extension to existing extensions.
+ *
+ * @param extensions A {@link Hashtable} to add the extension to.
+ * @param supportedSignatureAlgorithms {@link Vector} containing at least 1 {@link SignatureAndHashAlgorithm}.
+ * @throws IOException
+ */
+ public static void addSignatureAlgorithmsExtension(Hashtable extensions, Vector supportedSignatureAlgorithms)
+ throws IOException
+ {
+ extensions.put(EXT_signature_algorithms, createSignatureAlgorithmsExtension(supportedSignatureAlgorithms));
+ }
+
+ /**
+ * Get a 'signature_algorithms' extension from extensions.
+ *
+ * @param extensions A {@link Hashtable} to get the extension from, if it is present.
+ * @return A {@link Vector} containing at least 1 {@link SignatureAndHashAlgorithm}, or null.
+ * @throws IOException
+ */
+ public static Vector getSignatureAlgorithmsExtension(Hashtable extensions)
+ throws IOException
+ {
+ byte[] extensionData = getExtensionData(extensions, EXT_signature_algorithms);
+ return extensionData == null ? null : readSignatureAlgorithmsExtension(extensionData);
+ }
+
+ /**
+ * Create a 'signature_algorithms' extension value.
+ *
+ * @param supportedSignatureAlgorithms A {@link Vector} containing at least 1 {@link SignatureAndHashAlgorithm}.
+ * @return A byte array suitable for use as an extension value.
+ * @throws IOException
+ */
+ public static byte[] createSignatureAlgorithmsExtension(Vector supportedSignatureAlgorithms)
+ throws IOException
+ {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+
+ // supported_signature_algorithms
+ encodeSupportedSignatureAlgorithms(supportedSignatureAlgorithms, false, buf);
+
+ return buf.toByteArray();
+ }
+
+ /**
+ * Read 'signature_algorithms' extension data.
+ *
+ * @param extensionData The extension data.
+ * @return A {@link Vector} containing at least 1 {@link SignatureAndHashAlgorithm}.
+ * @throws IOException
+ */
+ public static Vector readSignatureAlgorithmsExtension(byte[] extensionData)
+ throws IOException
+ {
+ if (extensionData == null)
+ {
+ throw new IllegalArgumentException("'extensionData' cannot be null");
+ }
+
+ ByteArrayInputStream buf = new ByteArrayInputStream(extensionData);
+
+ // 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(
+ "'supportedSignatureAlgorithms' must have length from 1 to (2^15 - 1)");
+ }
+
+ // 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(input);
+ if (length < 2 || (length & 1) != 0)
+ {
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+ int count = length / 2;
+ Vector supportedSignatureAlgorithms = new Vector(count);
+ for (int i = 0; i < count; ++i)
+ {
+ 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);
+ }
+ return supportedSignatureAlgorithms;
+ }
+
+ public static byte[] PRF(TlsContext context, byte[] secret, String asciiLabel, byte[] seed, int size)
+ {
+ ProtocolVersion version = context.getServerVersion();
+
+ if (version.isSSL())
+ {
+ throw new IllegalStateException("No PRF available for SSLv3 session");
+ }
+
+ byte[] label = Strings.toByteArray(asciiLabel);
+ byte[] labelSeed = concat(label, seed);
+
+ int prfAlgorithm = context.getSecurityParameters().getPrfAlgorithm();
+
+ if (prfAlgorithm == PRFAlgorithm.tls_prf_legacy)
+ {
+ return PRF_legacy(secret, label, labelSeed, size);
+ }
+
+ Digest prfDigest = createPRFHash(prfAlgorithm);
+ byte[] buf = new byte[size];
+ hmac_hash(prfDigest, secret, labelSeed, buf);
+ return buf;
+ }
+
+ public static byte[] PRF_legacy(byte[] secret, String asciiLabel, byte[] seed, int size)
+ {
+ byte[] label = Strings.toByteArray(asciiLabel);
+ byte[] labelSeed = concat(label, seed);
+
+ return PRF_legacy(secret, label, labelSeed, size);
+ }
+
+ static byte[] PRF_legacy(byte[] secret, byte[] label, byte[] labelSeed, int size)
+ {
+ int s_half = (secret.length + 1) / 2;
+ byte[] s1 = new byte[s_half];
+ byte[] s2 = new byte[s_half];
+ System.arraycopy(secret, 0, s1, 0, s_half);
+ System.arraycopy(secret, secret.length - s_half, s2, 0, s_half);
+
+ byte[] b1 = new byte[size];
+ byte[] b2 = new byte[size];
+ hmac_hash(createHash(HashAlgorithm.md5), s1, labelSeed, b1);
+ hmac_hash(createHash(HashAlgorithm.sha1), s2, labelSeed, b2);
+ for (int i = 0; i < size; i++)
+ {
+ b1[i] ^= b2[i];
+ }
+ return b1;
+ }
+
+ static byte[] concat(byte[] a, byte[] b)
+ {
+ byte[] c = new byte[a.length + b.length];
+ System.arraycopy(a, 0, c, 0, a.length);
+ System.arraycopy(b, 0, c, a.length, b.length);
+ return c;
+ }
+
+ static void hmac_hash(Digest digest, byte[] secret, byte[] seed, byte[] out)
+ {
+ HMac mac = new HMac(digest);
+ mac.init(new KeyParameter(secret));
+ byte[] a = seed;
+ int size = digest.getDigestSize();
+ int iterations = (out.length + size - 1) / size;
+ byte[] buf = new byte[mac.getMacSize()];
+ byte[] buf2 = new byte[mac.getMacSize()];
+ for (int i = 0; i < iterations; i++)
+ {
+ mac.update(a, 0, a.length);
+ mac.doFinal(buf, 0);
+ a = buf;
+ mac.update(a, 0, a.length);
+ mac.update(seed, 0, seed.length);
+ mac.doFinal(buf2, 0);
+ System.arraycopy(buf2, 0, out, (size * i), Math.min(size, out.length - (size * i)));
+ }
+ }
+
+ static void validateKeyUsage(org.spongycastle.asn1.x509.Certificate c, int keyUsageBits)
+ throws IOException
+ {
+ Extensions exts = c.getTBSCertificate().getExtensions();
+ if (exts != null)
+ {
+ KeyUsage ku = KeyUsage.fromExtensions(exts);
+ if (ku != null)
+ {
+ int bits = ku.getBytes()[0] & 0xff;
+ if ((bits & keyUsageBits) != keyUsageBits)
+ {
+ throw new TlsFatalAlert(AlertDescription.certificate_unknown);
+ }
+ }
+ }
+ }
+
+ static byte[] calculateKeyBlock(TlsContext context, int size)
+ {
+ SecurityParameters securityParameters = context.getSecurityParameters();
+ byte[] master_secret = securityParameters.getMasterSecret();
+ byte[] seed = concat(securityParameters.getServerRandom(),
+ securityParameters.getClientRandom());
+
+ if (isSSL(context))
+ {
+ return calculateKeyBlock_SSL(master_secret, seed, size);
+ }
+
+ return PRF(context, master_secret, ExporterLabel.key_expansion, seed, size);
+ }
+
+ static byte[] calculateKeyBlock_SSL(byte[] master_secret, byte[] random, int size)
+ {
+ Digest md5 = createHash(HashAlgorithm.md5);
+ Digest sha1 = createHash(HashAlgorithm.sha1);
+ int md5Size = md5.getDigestSize();
+ byte[] shatmp = new byte[sha1.getDigestSize()];
+ byte[] tmp = new byte[size + md5Size];
+
+ int i = 0, pos = 0;
+ while (pos < size)
+ {
+ byte[] ssl3Const = SSL3_CONST[i];
+
+ sha1.update(ssl3Const, 0, ssl3Const.length);
+ sha1.update(master_secret, 0, master_secret.length);
+ sha1.update(random, 0, random.length);
+ sha1.doFinal(shatmp, 0);
+
+ md5.update(master_secret, 0, master_secret.length);
+ md5.update(shatmp, 0, shatmp.length);
+ md5.doFinal(tmp, pos);
+
+ pos += md5Size;
+ ++i;
+ }
+
+ byte rval[] = new byte[size];
+ System.arraycopy(tmp, 0, rval, 0, size);
+ return rval;
+ }
+
+ static byte[] calculateMasterSecret(TlsContext context, byte[] pre_master_secret)
+ {
+ SecurityParameters securityParameters = context.getSecurityParameters();
+ byte[] seed = concat(securityParameters.getClientRandom(), securityParameters.getServerRandom());
+
+ if (isSSL(context))
+ {
+ return calculateMasterSecret_SSL(pre_master_secret, seed);
+ }
+
+ return PRF(context, pre_master_secret, ExporterLabel.master_secret, seed, 48);
+ }
+
+ static byte[] calculateMasterSecret_SSL(byte[] pre_master_secret, byte[] random)
+ {
+ Digest md5 = createHash(HashAlgorithm.md5);
+ Digest sha1 = createHash(HashAlgorithm.sha1);
+ int md5Size = md5.getDigestSize();
+ byte[] shatmp = new byte[sha1.getDigestSize()];
+
+ byte[] rval = new byte[md5Size * 3];
+ int pos = 0;
+
+ for (int i = 0; i < 3; ++i)
+ {
+ byte[] ssl3Const = SSL3_CONST[i];
+
+ sha1.update(ssl3Const, 0, ssl3Const.length);
+ sha1.update(pre_master_secret, 0, pre_master_secret.length);
+ sha1.update(random, 0, random.length);
+ sha1.doFinal(shatmp, 0);
+
+ md5.update(pre_master_secret, 0, pre_master_secret.length);
+ md5.update(shatmp, 0, shatmp.length);
+ md5.doFinal(rval, pos);
+
+ pos += md5Size;
+ }
+
+ return rval;
+ }
+
+ static byte[] calculateVerifyData(TlsContext context, String asciiLabel, byte[] handshakeHash)
+ {
+ if (isSSL(context))
+ {
+ return handshakeHash;
+ }
+
+ SecurityParameters securityParameters = context.getSecurityParameters();
+ byte[] master_secret = securityParameters.getMasterSecret();
+ int verify_data_length = securityParameters.getVerifyDataLength();
+
+ return PRF(context, master_secret, asciiLabel, handshakeHash, verify_data_length);
+ }
+
+ public static Digest createHash(short hashAlgorithm)
+ {
+ switch (hashAlgorithm)
+ {
+ case HashAlgorithm.md5:
+ return new MD5Digest();
+ case HashAlgorithm.sha1:
+ return new SHA1Digest();
+ case HashAlgorithm.sha224:
+ return new SHA224Digest();
+ case HashAlgorithm.sha256:
+ return new SHA256Digest();
+ case HashAlgorithm.sha384:
+ return new SHA384Digest();
+ case HashAlgorithm.sha512:
+ return new SHA512Digest();
+ default:
+ throw new IllegalArgumentException("unknown HashAlgorithm");
+ }
+ }
+
+ public static Digest cloneHash(short hashAlgorithm, Digest hash)
+ {
+ switch (hashAlgorithm)
+ {
+ case HashAlgorithm.md5:
+ return new MD5Digest((MD5Digest)hash);
+ case HashAlgorithm.sha1:
+ return new SHA1Digest((SHA1Digest)hash);
+ case HashAlgorithm.sha224:
+ return new SHA224Digest((SHA224Digest)hash);
+ case HashAlgorithm.sha256:
+ return new SHA256Digest((SHA256Digest)hash);
+ case HashAlgorithm.sha384:
+ return new SHA384Digest((SHA384Digest)hash);
+ case HashAlgorithm.sha512:
+ return new SHA512Digest((SHA512Digest)hash);
+ default:
+ throw new IllegalArgumentException("unknown HashAlgorithm");
+ }
+ }
+
+ public static Digest createPRFHash(int prfAlgorithm)
+ {
+ switch (prfAlgorithm)
+ {
+ case PRFAlgorithm.tls_prf_legacy:
+ return new CombinedHash();
+ default:
+ return createHash(getHashAlgorithmForPRFAlgorithm(prfAlgorithm));
+ }
+ }
+
+ public static Digest clonePRFHash(int prfAlgorithm, Digest hash)
+ {
+ switch (prfAlgorithm)
+ {
+ case PRFAlgorithm.tls_prf_legacy:
+ return new CombinedHash((CombinedHash)hash);
+ default:
+ return cloneHash(getHashAlgorithmForPRFAlgorithm(prfAlgorithm), hash);
+ }
+ }
+
+ public static short getHashAlgorithmForPRFAlgorithm(int prfAlgorithm)
+ {
+ switch (prfAlgorithm)
+ {
+ case PRFAlgorithm.tls_prf_legacy:
+ throw new IllegalArgumentException("legacy PRF not a valid algorithm");
+ case PRFAlgorithm.tls_prf_sha256:
+ return HashAlgorithm.sha256;
+ case PRFAlgorithm.tls_prf_sha384:
+ return HashAlgorithm.sha384;
+ default:
+ throw new IllegalArgumentException("unknown PRFAlgorithm");
+ }
+ }
+
+ public static ASN1ObjectIdentifier getOIDForHashAlgorithm(short hashAlgorithm)
+ {
+ switch (hashAlgorithm)
+ {
+ case HashAlgorithm.md5:
+ return PKCSObjectIdentifiers.md5;
+ case HashAlgorithm.sha1:
+ return X509ObjectIdentifiers.id_SHA1;
+ case HashAlgorithm.sha224:
+ return NISTObjectIdentifiers.id_sha224;
+ case HashAlgorithm.sha256:
+ return NISTObjectIdentifiers.id_sha256;
+ case HashAlgorithm.sha384:
+ return NISTObjectIdentifiers.id_sha384;
+ case HashAlgorithm.sha512:
+ return NISTObjectIdentifiers.id_sha512;
+ default:
+ throw new IllegalArgumentException("unknown HashAlgorithm");
+ }
+ }
+
+ static short getClientCertificateType(Certificate clientCertificate, Certificate serverCertificate)
+ throws IOException
+ {
+ if (clientCertificate.isEmpty())
+ {
+ return -1;
+ }
+
+ org.spongycastle.asn1.x509.Certificate x509Cert = clientCertificate.getCertificateAt(0);
+ SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo();
+ try
+ {
+ AsymmetricKeyParameter publicKey = PublicKeyFactory.createKey(keyInfo);
+ if (publicKey.isPrivate())
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ /*
+ * TODO RFC 5246 7.4.6. The certificates MUST be signed using an acceptable hash/
+ * signature algorithm pair, as described in Section 7.4.4. Note that this relaxes the
+ * constraints on certificate-signing algorithms found in prior versions of TLS.
+ */
+
+ /*
+ * RFC 5246 7.4.6. Client Certificate
+ */
+
+ /*
+ * RSA public key; the certificate MUST allow the key to be used for signing with the
+ * signature scheme and hash algorithm that will be employed in the certificate verify
+ * message.
+ */
+ if (publicKey instanceof RSAKeyParameters)
+ {
+ validateKeyUsage(x509Cert, KeyUsage.digitalSignature);
+ return ClientCertificateType.rsa_sign;
+ }
+
+ /*
+ * DSA public key; the certificate MUST allow the key to be used for signing with the
+ * hash algorithm that will be employed in the certificate verify message.
+ */
+ if (publicKey instanceof DSAPublicKeyParameters)
+ {
+ validateKeyUsage(x509Cert, KeyUsage.digitalSignature);
+ return ClientCertificateType.dss_sign;
+ }
+
+ /*
+ * ECDSA-capable public key; the certificate MUST allow the key to be used for signing
+ * with the hash algorithm that will be employed in the certificate verify message; the
+ * public key MUST use a curve and point format supported by the server.
+ */
+ if (publicKey instanceof ECPublicKeyParameters)
+ {
+ validateKeyUsage(x509Cert, KeyUsage.digitalSignature);
+ // TODO Check the curve and point format
+ return ClientCertificateType.ecdsa_sign;
+ }
+
+ // TODO Add support for ClientCertificateType.*_fixed_*
+
+ }
+ catch (Exception e)
+ {
+ }
+
+ 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)
+ {
+ case ClientCertificateType.dss_sign:
+ case ClientCertificateType.ecdsa_sign:
+ case ClientCertificateType.rsa_sign:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public static TlsSigner createTlsSigner(short clientCertificateType)
+ {
+ switch (clientCertificateType)
+ {
+ case ClientCertificateType.dss_sign:
+ return new TlsDSSSigner();
+ case ClientCertificateType.ecdsa_sign:
+ return new TlsECDSASigner();
+ case ClientCertificateType.rsa_sign:
+ return new TlsRSASigner();
+ default:
+ throw new IllegalArgumentException("'clientCertificateType' is not a type with signing capability");
+ }
+ }
+
+ static final byte[] SSL_CLIENT = {0x43, 0x4C, 0x4E, 0x54};
+ static final byte[] SSL_SERVER = {0x53, 0x52, 0x56, 0x52};
+
+ // SSL3 magic mix constants ("A", "BB", "CCC", ...)
+ static final byte[][] SSL3_CONST = genConst();
+
+ private static byte[][] genConst()
+ {
+ int n = 10;
+ byte[][] arr = new byte[n][];
+ for (int i = 0; i < n; i++)
+ {
+ byte[] b = new byte[i + 1];
+ Arrays.fill(b, (byte)('A' + i));
+ arr[i] = b;
+ }
+ return arr;
+ }
+
+ private static Vector vectorOfOne(Object obj)
+ {
+ Vector v = new Vector(1);
+ v.addElement(obj);
+ return v;
+ }
+
+ public static int getCipherType(int ciphersuite) throws IOException
+ {
+ switch (getEncryptionAlgorithm(ciphersuite))
+ {
+ case EncryptionAlgorithm.AES_128_GCM:
+ case EncryptionAlgorithm.AES_256_GCM:
+ case EncryptionAlgorithm.AES_128_CCM:
+ case EncryptionAlgorithm.AES_128_CCM_8:
+ case EncryptionAlgorithm.AES_256_CCM:
+ case EncryptionAlgorithm.AES_256_CCM_8:
+ case EncryptionAlgorithm.CAMELLIA_128_GCM:
+ case EncryptionAlgorithm.CAMELLIA_256_GCM:
+ case EncryptionAlgorithm.AEAD_CHACHA20_POLY1305:
+ return CipherType.aead;
+
+ case EncryptionAlgorithm.RC2_CBC_40:
+ case EncryptionAlgorithm.IDEA_CBC:
+ case EncryptionAlgorithm.DES40_CBC:
+ case EncryptionAlgorithm.DES_CBC:
+ case EncryptionAlgorithm._3DES_EDE_CBC:
+ case EncryptionAlgorithm.AES_128_CBC:
+ case EncryptionAlgorithm.AES_256_CBC:
+ case EncryptionAlgorithm.CAMELLIA_128_CBC:
+ case EncryptionAlgorithm.CAMELLIA_256_CBC:
+ case EncryptionAlgorithm.SEED_CBC:
+ return CipherType.block;
+
+ case EncryptionAlgorithm.RC4_40:
+ case EncryptionAlgorithm.RC4_128:
+ case EncryptionAlgorithm.ESTREAM_SALSA20:
+ case EncryptionAlgorithm.SALSA20:
+ return CipherType.stream;
+
+ default:
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public static int getEncryptionAlgorithm(int ciphersuite) throws IOException
+ {
+ switch (ciphersuite)
+ {
+ case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_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_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
+ return EncryptionAlgorithm._3DES_EDE_CBC;
+
+ case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+ return EncryptionAlgorithm.AEAD_CHACHA20_POLY1305;
+
+ case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_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_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
+ return EncryptionAlgorithm.AES_128_CBC;
+
+ 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_PSK_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_PSK_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
+ return EncryptionAlgorithm.AES_128_CBC;
+
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
+ case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
+ return EncryptionAlgorithm.AES_128_CCM;
+
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
+ case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
+ case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
+ return EncryptionAlgorithm.AES_128_CCM_8;
+
+ 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:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
+ return EncryptionAlgorithm.AES_128_GCM;
+
+ case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_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_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
+ return EncryptionAlgorithm.AES_256_CBC;
+
+ 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:
+ return EncryptionAlgorithm.AES_256_CBC;
+
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
+ 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_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_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 EncryptionAlgorithm.AES_256_CBC;
+
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
+ case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
+ return EncryptionAlgorithm.AES_256_CCM;
+
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
+ case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
+ case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
+ return EncryptionAlgorithm.AES_256_CCM_8;
+
+ 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_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_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 EncryptionAlgorithm.AES_256_GCM;
+
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
+ return EncryptionAlgorithm.CAMELLIA_128_CBC;
+
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ return EncryptionAlgorithm.CAMELLIA_128_CBC;
+
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ return EncryptionAlgorithm.CAMELLIA_128_GCM;
+
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ return EncryptionAlgorithm.CAMELLIA_256_CBC;
+
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ return EncryptionAlgorithm.CAMELLIA_256_CBC;
+
+ case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+ return EncryptionAlgorithm.CAMELLIA_256_CBC;
+
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ return EncryptionAlgorithm.CAMELLIA_256_GCM;
+
+ case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ return EncryptionAlgorithm.ESTREAM_SALSA20;
+
+ case CipherSuite.TLS_RSA_WITH_NULL_MD5:
+ return EncryptionAlgorithm.NULL;
+
+ case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
+ case CipherSuite.TLS_PSK_WITH_NULL_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA:
+ case CipherSuite.TLS_RSA_WITH_NULL_SHA:
+ return EncryptionAlgorithm.NULL;
+
+ 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:
+ case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
+ return EncryptionAlgorithm.NULL;
+
+ 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 EncryptionAlgorithm.NULL;
+
+ case CipherSuite.TLS_DH_anon_WITH_RC4_128_MD5:
+ case CipherSuite.TLS_RSA_WITH_RC4_128_MD5:
+ return EncryptionAlgorithm.RC4_128;
+
+ case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDH_anon_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_PSK_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_RSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA:
+ return EncryptionAlgorithm.RC4_128;
+
+ case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1:
+ return EncryptionAlgorithm.SALSA20;
+
+ 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:
+ case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA:
+ return EncryptionAlgorithm.SEED_CBC;
+
+ default:
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public static ProtocolVersion getMinimumVersion(int ciphersuite)
+ {
+ switch (ciphersuite)
+ {
+ case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DH_DSS_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_DSS_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+ 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_DH_RSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ 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_DSS_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+ 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_PSK_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+ 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_DHE_RSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+ 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_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+ 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_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_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_PSK_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+ 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_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_SHA256:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
+ return ProtocolVersion.TLSv12;
+
+ default:
+ return ProtocolVersion.SSLv3;
+ }
+ }
+
+ public static boolean isAEADCipherSuite(int ciphersuite) throws IOException
+ {
+ return CipherType.aead == getCipherType(ciphersuite);
+ }
+
+ public static boolean isBlockCipherSuite(int ciphersuite) throws IOException
+ {
+ return CipherType.block == getCipherType(ciphersuite);
+ }
+
+ public static boolean isStreamCipherSuite(int ciphersuite) throws IOException
+ {
+ return CipherType.stream == getCipherType(ciphersuite);
+ }
+
+ public static boolean isValidCipherSuiteForVersion(int cipherSuite, ProtocolVersion serverVersion)
+ {
+ return getMinimumVersion(cipherSuite).isEqualOrEarlierVersionOf(serverVersion.getEquivalentTLSVersion());
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/UDPTransport.java b/core/src/main/java/org/spongycastle/crypto/tls/UDPTransport.java
new file mode 100644
index 00000000..63aca852
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/UDPTransport.java
@@ -0,0 +1,75 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+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;
+
+ 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");
+ }
+
+ this.socket = socket;
+
+ // NOTE: As of JDK 1.6, can use NetworkInterface.getMTU
+
+ this.receiveLimit = mtu - MIN_IP_OVERHEAD - UDP_OVERHEAD;
+ this.sendLimit = mtu - MAX_IP_OVERHEAD - UDP_OVERHEAD;
+ }
+
+ public int getReceiveLimit()
+ {
+ return receiveLimit;
+ }
+
+ public int getSendLimit()
+ {
+ // TODO[DTLS] Implement Path-MTU discovery?
+ return sendLimit;
+ }
+
+ public int receive(byte[] buf, int off, int len, int waitMillis)
+ throws IOException
+ {
+ socket.setSoTimeout(waitMillis);
+ DatagramPacket packet = new DatagramPacket(buf, off, len);
+ socket.receive(packet);
+ return packet.getLength();
+ }
+
+ public void send(byte[] buf, int off, int len)
+ throws IOException
+ {
+ if (len > getSendLimit())
+ {
+ /*
+ * RFC 4347 4.1.1. "If the application attempts to send a record larger than the MTU,
+ * the DTLS implementation SHOULD generate an error, thus avoiding sending a packet
+ * which will be fragmented."
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ DatagramPacket packet = new DatagramPacket(buf, off, len);
+ socket.send(packet);
+ }
+
+ public void close()
+ throws IOException
+ {
+ socket.close();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/URLAndHash.java b/core/src/main/java/org/spongycastle/crypto/tls/URLAndHash.java
new file mode 100644
index 00000000..05407842
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/URLAndHash.java
@@ -0,0 +1,104 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.spongycastle.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/core/src/main/java/org/spongycastle/crypto/tls/UseSRTPData.java b/core/src/main/java/org/spongycastle/crypto/tls/UseSRTPData.java
new file mode 100644
index 00000000..8202dd1e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/UseSRTPData.java
@@ -0,0 +1,52 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 5764 4.1.1
+ */
+public class UseSRTPData
+{
+ private int[] protectionProfiles;
+ private byte[] mki;
+
+ /**
+ * @param protectionProfiles see {@link SRTPProtectionProfile} for valid constants.
+ * @param mki valid lengths from 0 to 255.
+ */
+ public UseSRTPData(int[] protectionProfiles, byte[] mki)
+ {
+ if (protectionProfiles == null || protectionProfiles.length < 1
+ || protectionProfiles.length >= (1 << 15))
+ {
+ throw new IllegalArgumentException(
+ "'protectionProfiles' must have length from 1 to (2^15 - 1)");
+ }
+
+ if (mki == null)
+ {
+ mki = TlsUtils.EMPTY_BYTES;
+ }
+ else if (mki.length > 255)
+ {
+ throw new IllegalArgumentException("'mki' cannot be longer than 255 bytes");
+ }
+
+ this.protectionProfiles = protectionProfiles;
+ this.mki = mki;
+ }
+
+ /**
+ * @return see {@link SRTPProtectionProfile} for valid constants.
+ */
+ public int[] getProtectionProfiles()
+ {
+ return protectionProfiles;
+ }
+
+ /**
+ * @return valid lengths from 0 to 255.
+ */
+ public byte[] getMki()
+ {
+ return mki;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/tls/UserMappingType.java b/core/src/main/java/org/spongycastle/crypto/tls/UserMappingType.java
new file mode 100644
index 00000000..f2fc21f2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/tls/UserMappingType.java
@@ -0,0 +1,12 @@
+package org.spongycastle.crypto.tls;
+
+/**
+ * RFC 4681
+ */
+public class UserMappingType
+{
+ /*
+ * RFC 4681
+ */
+ public static final short upn_domain_hint = 64;
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/util/Pack.java b/core/src/main/java/org/spongycastle/crypto/util/Pack.java
new file mode 100644
index 00000000..e7743e9a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/util/Pack.java
@@ -0,0 +1,204 @@
+package org.spongycastle.crypto.util;
+
+/**
+ * @deprecated use org.spongycastle.util.pack
+ */
+public abstract class Pack
+{
+ public static int bigEndianToInt(byte[] bs, int off)
+ {
+ int n = bs[ off] << 24;
+ n |= (bs[++off] & 0xff) << 16;
+ n |= (bs[++off] & 0xff) << 8;
+ n |= (bs[++off] & 0xff);
+ return n;
+ }
+
+ public static void bigEndianToInt(byte[] bs, int off, int[] ns)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ ns[i] = bigEndianToInt(bs, off);
+ off += 4;
+ }
+ }
+
+ public static byte[] intToBigEndian(int n)
+ {
+ byte[] bs = new byte[4];
+ intToBigEndian(n, bs, 0);
+ return bs;
+ }
+
+ public static void intToBigEndian(int n, byte[] bs, int off)
+ {
+ bs[ off] = (byte)(n >>> 24);
+ bs[++off] = (byte)(n >>> 16);
+ bs[++off] = (byte)(n >>> 8);
+ bs[++off] = (byte)(n );
+ }
+
+ public static byte[] intToBigEndian(int[] ns)
+ {
+ byte[] bs = new byte[4 * ns.length];
+ intToBigEndian(ns, bs, 0);
+ return bs;
+ }
+
+ public static void intToBigEndian(int[] ns, byte[] bs, int off)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ intToBigEndian(ns[i], bs, off);
+ off += 4;
+ }
+ }
+
+ public static long bigEndianToLong(byte[] bs, int off)
+ {
+ int hi = bigEndianToInt(bs, off);
+ int lo = bigEndianToInt(bs, off + 4);
+ return ((long)(hi & 0xffffffffL) << 32) | (long)(lo & 0xffffffffL);
+ }
+
+ public static void bigEndianToLong(byte[] bs, int off, long[] ns)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ ns[i] = bigEndianToLong(bs, off);
+ off += 8;
+ }
+ }
+
+ public static byte[] longToBigEndian(long n)
+ {
+ byte[] bs = new byte[8];
+ longToBigEndian(n, bs, 0);
+ return bs;
+ }
+
+ public static void longToBigEndian(long n, byte[] bs, int off)
+ {
+ intToBigEndian((int)(n >>> 32), bs, off);
+ intToBigEndian((int)(n & 0xffffffffL), bs, off + 4);
+ }
+
+ public static byte[] longToBigEndian(long[] ns)
+ {
+ byte[] bs = new byte[8 * ns.length];
+ longToBigEndian(ns, bs, 0);
+ return bs;
+ }
+
+ public static void longToBigEndian(long[] ns, byte[] bs, int off)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ longToBigEndian(ns[i], bs, off);
+ off += 8;
+ }
+ }
+
+ public static int littleEndianToInt(byte[] bs, int off)
+ {
+ int n = bs[ off] & 0xff;
+ n |= (bs[++off] & 0xff) << 8;
+ n |= (bs[++off] & 0xff) << 16;
+ n |= bs[++off] << 24;
+ return n;
+ }
+
+ public static void littleEndianToInt(byte[] bs, int off, int[] ns)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ ns[i] = littleEndianToInt(bs, off);
+ off += 4;
+ }
+ }
+
+ public static void littleEndianToInt(byte[] bs, int bOff, int[] ns, int nOff, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ ns[nOff + i] = littleEndianToInt(bs, bOff);
+ bOff += 4;
+ }
+ }
+
+ public static byte[] intToLittleEndian(int n)
+ {
+ byte[] bs = new byte[4];
+ intToLittleEndian(n, bs, 0);
+ return bs;
+ }
+
+ public static void intToLittleEndian(int n, byte[] bs, int off)
+ {
+ bs[ off] = (byte)(n );
+ bs[++off] = (byte)(n >>> 8);
+ bs[++off] = (byte)(n >>> 16);
+ bs[++off] = (byte)(n >>> 24);
+ }
+
+ public static byte[] intToLittleEndian(int[] ns)
+ {
+ byte[] bs = new byte[4 * ns.length];
+ intToLittleEndian(ns, bs, 0);
+ return bs;
+ }
+
+ public static void intToLittleEndian(int[] ns, byte[] bs, int off)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ intToLittleEndian(ns[i], bs, off);
+ off += 4;
+ }
+ }
+
+ public static long littleEndianToLong(byte[] bs, int off)
+ {
+ int lo = littleEndianToInt(bs, off);
+ int hi = littleEndianToInt(bs, off + 4);
+ return ((long)(hi & 0xffffffffL) << 32) | (long)(lo & 0xffffffffL);
+ }
+
+ public static void littleEndianToLong(byte[] bs, int off, long[] ns)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ ns[i] = littleEndianToLong(bs, off);
+ off += 8;
+ }
+ }
+
+ public static byte[] longToLittleEndian(long n)
+ {
+ byte[] bs = new byte[8];
+ longToLittleEndian(n, bs, 0);
+ return bs;
+ }
+
+ public static void longToLittleEndian(long n, byte[] bs, int off)
+ {
+ intToLittleEndian((int)(n & 0xffffffffL), bs, off);
+ intToLittleEndian((int)(n >>> 32), bs, off + 4);
+ }
+
+ public static byte[] longToLittleEndian(long[] ns)
+ {
+ byte[] bs = new byte[8 * ns.length];
+ longToLittleEndian(ns, bs, 0);
+ return bs;
+ }
+
+ public static void longToLittleEndian(long[] ns, byte[] bs, int off)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ longToLittleEndian(ns[i], bs, off);
+ off += 8;
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/util/PrivateKeyFactory.java b/core/src/main/java/org/spongycastle/crypto/util/PrivateKeyFactory.java
new file mode 100644
index 00000000..289b25f5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/util/PrivateKeyFactory.java
@@ -0,0 +1,159 @@
+package org.spongycastle.crypto.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.oiw.ElGamalParameter;
+import org.spongycastle.asn1.oiw.OIWObjectIdentifiers;
+import org.spongycastle.asn1.pkcs.DHParameter;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.pkcs.PrivateKeyInfo;
+import org.spongycastle.asn1.pkcs.RSAPrivateKey;
+import org.spongycastle.asn1.sec.ECPrivateKey;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.DSAParameter;
+import org.spongycastle.asn1.x9.ECNamedCurveTable;
+import org.spongycastle.asn1.x9.X962Parameters;
+import org.spongycastle.asn1.x9.X9ECParameters;
+import org.spongycastle.asn1.x9.X9ObjectIdentifiers;
+import org.spongycastle.crypto.ec.CustomNamedCurves;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.DHParameters;
+import org.spongycastle.crypto.params.DHPrivateKeyParameters;
+import org.spongycastle.crypto.params.DSAParameters;
+import org.spongycastle.crypto.params.DSAPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECNamedDomainParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ElGamalParameters;
+import org.spongycastle.crypto.params.ElGamalPrivateKeyParameters;
+import org.spongycastle.crypto.params.RSAPrivateCrtKeyParameters;
+
+/**
+ * Factory for creating private key objects from PKCS8 PrivateKeyInfo objects.
+ */
+public class PrivateKeyFactory
+{
+ /**
+ * Create a private key parameter from a PKCS8 PrivateKeyInfo encoding.
+ *
+ * @param privateKeyInfoData the PrivateKeyInfo encoding
+ * @return a suitable private key parameter
+ * @throws IOException on an error decoding the key
+ */
+ public static AsymmetricKeyParameter createKey(byte[] privateKeyInfoData) throws IOException
+ {
+ return createKey(PrivateKeyInfo.getInstance(ASN1Primitive.fromByteArray(privateKeyInfoData)));
+ }
+
+ /**
+ * Create a private key parameter from a PKCS8 PrivateKeyInfo encoding read from a
+ * stream.
+ *
+ * @param inStr the stream to read the PrivateKeyInfo encoding from
+ * @return a suitable private key parameter
+ * @throws IOException on an error decoding the key
+ */
+ public static AsymmetricKeyParameter createKey(InputStream inStr) throws IOException
+ {
+ return createKey(PrivateKeyInfo.getInstance(new ASN1InputStream(inStr).readObject()));
+ }
+
+ /**
+ * Create a private key parameter from the passed in PKCS8 PrivateKeyInfo object.
+ *
+ * @param keyInfo the PrivateKeyInfo object containing the key material
+ * @return a suitable private key parameter
+ * @throws IOException on an error decoding the key
+ */
+ public static AsymmetricKeyParameter createKey(PrivateKeyInfo keyInfo) throws IOException
+ {
+ AlgorithmIdentifier algId = keyInfo.getPrivateKeyAlgorithm();
+
+ if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.rsaEncryption))
+ {
+ RSAPrivateKey keyStructure = RSAPrivateKey.getInstance(keyInfo.parsePrivateKey());
+
+ return new RSAPrivateCrtKeyParameters(keyStructure.getModulus(),
+ keyStructure.getPublicExponent(), keyStructure.getPrivateExponent(),
+ keyStructure.getPrime1(), keyStructure.getPrime2(), keyStructure.getExponent1(),
+ keyStructure.getExponent2(), keyStructure.getCoefficient());
+ }
+ // TODO?
+// else if (algId.getObjectId().equals(X9ObjectIdentifiers.dhpublicnumber))
+ else if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.dhKeyAgreement))
+ {
+ DHParameter params = DHParameter.getInstance(algId.getParameters());
+ ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey();
+
+ BigInteger lVal = params.getL();
+ int l = lVal == null ? 0 : lVal.intValue();
+ DHParameters dhParams = new DHParameters(params.getP(), params.getG(), null, l);
+
+ return new DHPrivateKeyParameters(derX.getValue(), dhParams);
+ }
+ else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm))
+ {
+ ElGamalParameter params = ElGamalParameter.getInstance(algId.getParameters());
+ ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey();
+
+ return new ElGamalPrivateKeyParameters(derX.getValue(), new ElGamalParameters(
+ params.getP(), params.getG()));
+ }
+ else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_dsa))
+ {
+ ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey();
+ ASN1Encodable de = algId.getParameters();
+
+ DSAParameters parameters = null;
+ if (de != null)
+ {
+ DSAParameter params = DSAParameter.getInstance(de.toASN1Primitive());
+ parameters = new DSAParameters(params.getP(), params.getQ(), params.getG());
+ }
+
+ return new DSAPrivateKeyParameters(derX.getValue(), parameters);
+ }
+ else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_ecPublicKey))
+ {
+ X962Parameters params = new X962Parameters((ASN1Primitive)algId.getParameters());
+
+ X9ECParameters x9;
+ ECDomainParameters dParams;
+
+ if (params.isNamedCurve())
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters();
+
+ x9 = CustomNamedCurves.getByOID(oid);
+ if (x9 == null)
+ {
+ x9 = ECNamedCurveTable.getByOID(oid);
+ }
+ dParams = new ECNamedDomainParameters(
+ oid, x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
+ }
+ else
+ {
+ x9 = X9ECParameters.getInstance(params.getParameters());
+ dParams = new ECDomainParameters(
+ x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
+ }
+
+ ECPrivateKey ec = ECPrivateKey.getInstance(keyInfo.parsePrivateKey());
+ BigInteger d = ec.getKey();
+
+ return new ECPrivateKeyParameters(d, dParams);
+ }
+ else
+ {
+ throw new RuntimeException("algorithm identifier in key not recognised");
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/util/PrivateKeyInfoFactory.java b/core/src/main/java/org/spongycastle/crypto/util/PrivateKeyInfoFactory.java
new file mode 100644
index 00000000..3fa6d2f1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/util/PrivateKeyInfoFactory.java
@@ -0,0 +1,86 @@
+package org.spongycastle.crypto.util;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.DERNull;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.pkcs.PrivateKeyInfo;
+import org.spongycastle.asn1.pkcs.RSAPrivateKey;
+import org.spongycastle.asn1.sec.ECPrivateKey;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.DSAParameter;
+import org.spongycastle.asn1.x9.X962Parameters;
+import org.spongycastle.asn1.x9.X9ECParameters;
+import org.spongycastle.asn1.x9.X9ObjectIdentifiers;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.DSAParameters;
+import org.spongycastle.crypto.params.DSAPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECNamedDomainParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+import org.spongycastle.crypto.params.RSAPrivateCrtKeyParameters;
+
+/**
+ * Factory to create ASN.1 private key info objects from lightweight private keys.
+ */
+public class PrivateKeyInfoFactory
+{
+ /**
+ * Create a PrivateKeyInfo representation of a private key.
+ *
+ * @param privateKey the SubjectPublicKeyInfo encoding
+ * @return the appropriate key parameter
+ * @throws java.io.IOException on an error encoding the key
+ */
+ public static PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter privateKey) throws IOException
+ {
+ if (privateKey instanceof RSAKeyParameters)
+ {
+ RSAPrivateCrtKeyParameters priv = (RSAPrivateCrtKeyParameters)privateKey;
+
+ return new PrivateKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE), new RSAPrivateKey(priv.getModulus(), priv.getPublicExponent(), priv.getExponent(), priv.getP(), priv.getQ(), priv.getDP(), priv.getDQ(), priv.getQInv()));
+ }
+ else if (privateKey instanceof DSAPrivateKeyParameters)
+ {
+ DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)privateKey;
+ DSAParameters params = priv.getParameters();
+
+ 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;
+
+ if (domainParams == null)
+ {
+ params = new X962Parameters(DERNull.INSTANCE); // Implicitly CA
+ }
+ else if (domainParams instanceof ECNamedDomainParameters)
+ {
+ params = new X962Parameters(((ECNamedDomainParameters)domainParams).getName());
+ }
+ 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/core/src/main/java/org/spongycastle/crypto/util/PublicKeyFactory.java b/core/src/main/java/org/spongycastle/crypto/util/PublicKeyFactory.java
new file mode 100644
index 00000000..ec588f46
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/util/PublicKeyFactory.java
@@ -0,0 +1,195 @@
+package org.spongycastle.crypto.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.oiw.ElGamalParameter;
+import org.spongycastle.asn1.oiw.OIWObjectIdentifiers;
+import org.spongycastle.asn1.pkcs.DHParameter;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.pkcs.RSAPublicKey;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.DSAParameter;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.spongycastle.asn1.x509.X509ObjectIdentifiers;
+import org.spongycastle.asn1.x9.DHDomainParameters;
+import org.spongycastle.asn1.x9.DHPublicKey;
+import org.spongycastle.asn1.x9.DHValidationParms;
+import org.spongycastle.asn1.x9.ECNamedCurveTable;
+import org.spongycastle.asn1.x9.X962Parameters;
+import org.spongycastle.asn1.x9.X9ECParameters;
+import org.spongycastle.asn1.x9.X9ECPoint;
+import org.spongycastle.asn1.x9.X9ObjectIdentifiers;
+import org.spongycastle.crypto.ec.CustomNamedCurves;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.DHParameters;
+import org.spongycastle.crypto.params.DHPublicKeyParameters;
+import org.spongycastle.crypto.params.DHValidationParameters;
+import org.spongycastle.crypto.params.DSAParameters;
+import org.spongycastle.crypto.params.DSAPublicKeyParameters;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECNamedDomainParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.crypto.params.ElGamalParameters;
+import org.spongycastle.crypto.params.ElGamalPublicKeyParameters;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+
+/**
+ * Factory to create asymmetric public key parameters for asymmetric ciphers from range of
+ * ASN.1 encoded SubjectPublicKeyInfo objects.
+ */
+public class PublicKeyFactory
+{
+ /**
+ * Create a public key from a SubjectPublicKeyInfo encoding
+ *
+ * @param keyInfoData the SubjectPublicKeyInfo encoding
+ * @return the appropriate key parameter
+ * @throws IOException on an error decoding the key
+ */
+ public static AsymmetricKeyParameter createKey(byte[] keyInfoData) throws IOException
+ {
+ return createKey(SubjectPublicKeyInfo.getInstance(ASN1Primitive.fromByteArray(keyInfoData)));
+ }
+
+ /**
+ * Create a public key from a SubjectPublicKeyInfo encoding read from a stream
+ *
+ * @param inStr the stream to read the SubjectPublicKeyInfo encoding from
+ * @return the appropriate key parameter
+ * @throws IOException on an error decoding the key
+ */
+ public static AsymmetricKeyParameter createKey(InputStream inStr) throws IOException
+ {
+ return createKey(SubjectPublicKeyInfo.getInstance(new ASN1InputStream(inStr).readObject()));
+ }
+
+ /**
+ * Create a public key from the passed in SubjectPublicKeyInfo
+ *
+ * @param keyInfo the SubjectPublicKeyInfo containing the key data
+ * @return the appropriate key parameter
+ * @throws IOException on an error decoding the key
+ */
+ public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo) throws IOException
+ {
+ AlgorithmIdentifier algId = keyInfo.getAlgorithm();
+
+ if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.rsaEncryption)
+ || algId.getAlgorithm().equals(X509ObjectIdentifiers.id_ea_rsa))
+ {
+ RSAPublicKey pubKey = RSAPublicKey.getInstance(keyInfo.parsePublicKey());
+
+ return new RSAKeyParameters(false, pubKey.getModulus(), pubKey.getPublicExponent());
+ }
+ else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.dhpublicnumber))
+ {
+ DHPublicKey dhPublicKey = DHPublicKey.getInstance(keyInfo.parsePublicKey());
+
+ BigInteger y = dhPublicKey.getY().getValue();
+
+ DHDomainParameters dhParams = DHDomainParameters.getInstance(algId.getParameters());
+
+ BigInteger p = dhParams.getP().getValue();
+ BigInteger g = dhParams.getG().getValue();
+ BigInteger q = dhParams.getQ().getValue();
+
+ BigInteger j = null;
+ if (dhParams.getJ() != null)
+ {
+ j = dhParams.getJ().getValue();
+ }
+
+ DHValidationParameters validation = null;
+ DHValidationParms dhValidationParms = dhParams.getValidationParms();
+ if (dhValidationParms != null)
+ {
+ byte[] seed = dhValidationParms.getSeed().getBytes();
+ BigInteger pgenCounter = dhValidationParms.getPgenCounter().getValue();
+
+ // TODO Check pgenCounter size?
+
+ validation = new DHValidationParameters(seed, pgenCounter.intValue());
+ }
+
+ return new DHPublicKeyParameters(y, new DHParameters(p, g, q, j, validation));
+ }
+ else if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.dhKeyAgreement))
+ {
+ DHParameter params = DHParameter.getInstance(algId.getParameters());
+ ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey();
+
+ BigInteger lVal = params.getL();
+ int l = lVal == null ? 0 : lVal.intValue();
+ DHParameters dhParams = new DHParameters(params.getP(), params.getG(), null, l);
+
+ return new DHPublicKeyParameters(derY.getValue(), dhParams);
+ }
+ else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm))
+ {
+ ElGamalParameter params = ElGamalParameter.getInstance(algId.getParameters());
+ ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey();
+
+ return new ElGamalPublicKeyParameters(derY.getValue(), new ElGamalParameters(
+ params.getP(), params.getG()));
+ }
+ else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_dsa)
+ || algId.getAlgorithm().equals(OIWObjectIdentifiers.dsaWithSHA1))
+ {
+ ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey();
+ ASN1Encodable de = algId.getParameters();
+
+ DSAParameters parameters = null;
+ if (de != null)
+ {
+ DSAParameter params = DSAParameter.getInstance(de.toASN1Primitive());
+ parameters = new DSAParameters(params.getP(), params.getQ(), params.getG());
+ }
+
+ return new DSAPublicKeyParameters(derY.getValue(), parameters);
+ }
+ else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_ecPublicKey))
+ {
+ X962Parameters params = X962Parameters.getInstance(algId.getParameters());
+
+ X9ECParameters x9;
+ ECDomainParameters dParams;
+
+ if (params.isNamedCurve())
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters();
+
+ x9 = CustomNamedCurves.getByOID(oid);
+ if (x9 == null)
+ {
+ x9 = ECNamedCurveTable.getByOID(oid);
+ }
+ dParams = new ECNamedDomainParameters(
+ oid, x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
+ }
+ else
+ {
+ x9 = X9ECParameters.getInstance(params.getParameters());
+ dParams = new ECDomainParameters(
+ x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
+ }
+
+ ASN1OctetString key = new DEROctetString(keyInfo.getPublicKeyData().getBytes());
+ X9ECPoint derQ = new X9ECPoint(x9.getCurve(), key);
+
+ return new ECPublicKeyParameters(derQ.getPoint(), dParams);
+ }
+ else
+ {
+ throw new RuntimeException("algorithm identifier in key not recognised");
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/crypto/util/SubjectPublicKeyInfoFactory.java b/core/src/main/java/org/spongycastle/crypto/util/SubjectPublicKeyInfoFactory.java
new file mode 100644
index 00000000..749de7f3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/util/SubjectPublicKeyInfoFactory.java
@@ -0,0 +1,85 @@
+package org.spongycastle.crypto.util;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.DERNull;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.pkcs.RSAPublicKey;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.spongycastle.asn1.x9.X962Parameters;
+import org.spongycastle.asn1.x9.X9ECParameters;
+import org.spongycastle.asn1.x9.X9ECPoint;
+import org.spongycastle.asn1.x9.X9ObjectIdentifiers;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.DSAPublicKeyParameters;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECNamedDomainParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+
+/**
+ * Factory to create ASN.1 subject public key info objects from lightweight public keys.
+ */
+public class SubjectPublicKeyInfoFactory
+{
+ /**
+ * Create a SubjectPublicKeyInfo public key.
+ *
+ * @param publicKey the SubjectPublicKeyInfo encoding
+ * @return the appropriate key parameter
+ * @throws java.io.IOException on an error encoding the key
+ */
+ public static SubjectPublicKeyInfo createSubjectPublicKeyInfo(AsymmetricKeyParameter publicKey) throws IOException
+ {
+ if (publicKey instanceof RSAKeyParameters)
+ {
+ RSAKeyParameters pub = (RSAKeyParameters)publicKey;
+
+ return new SubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE), new RSAPublicKey(pub.getModulus(), pub.getExponent()));
+ }
+ else if (publicKey instanceof DSAPublicKeyParameters)
+ {
+ DSAPublicKeyParameters pub = (DSAPublicKeyParameters)publicKey;
+
+ return new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa), new ASN1Integer(pub.getY()));
+ }
+ else if (publicKey instanceof ECPublicKeyParameters)
+ {
+ ECPublicKeyParameters pub = (ECPublicKeyParameters)publicKey;
+ ECDomainParameters domainParams = pub.getParameters();
+ ASN1Encodable params;
+
+ if (domainParams == null)
+ {
+ params = new X962Parameters(DERNull.INSTANCE); // Implicitly CA
+ }
+ else if (domainParams instanceof ECNamedDomainParameters)
+ {
+ params = new X962Parameters(((ECNamedDomainParameters)domainParams).getName());
+ }
+ else
+ {
+ X9ECParameters ecP = new X9ECParameters(
+ domainParams.getCurve(),
+ domainParams.getG(),
+ domainParams.getN(),
+ domainParams.getH(),
+ domainParams.getSeed());
+
+ params = new X962Parameters(ecP);
+ }
+
+ ASN1OctetString p = (ASN1OctetString)new X9ECPoint(pub.getQ()).toASN1Primitive();
+
+ return new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), p.getOctets());
+ }
+ else
+ {
+ throw new IOException("key parameters not recognised.");
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/i18n/ErrorBundle.java b/core/src/main/java/org/spongycastle/i18n/ErrorBundle.java
new file mode 100644
index 00000000..fc703e01
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/i18n/ErrorBundle.java
@@ -0,0 +1,120 @@
+package org.spongycastle.i18n;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Locale;
+import java.util.TimeZone;
+
+public class ErrorBundle extends MessageBundle
+{
+
+ /**
+ * summary entry key
+ */
+ public static final String SUMMARY_ENTRY = "summary";
+
+ /**
+ * detail entry key
+ */
+ public static final String DETAIL_ENTRY = "details";
+
+ /**
+ * Constructs a new ErrorBundle using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ */
+ public ErrorBundle(String resource, String id) throws NullPointerException
+ {
+ super(resource, id);
+ }
+
+ /**
+ * Constructs a new ErrorBundle using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param encoding the encoding of the resource file
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ * @throws UnsupportedEncodingException if the encoding is not supported
+ */
+ public ErrorBundle(String resource, String id, String encoding) throws NullPointerException, UnsupportedEncodingException
+ {
+ super(resource, id, encoding);
+ }
+
+ /**
+ * Constructs a new ErrorBundle using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param arguments an array containing the arguments for the message
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ */
+ public ErrorBundle(String resource, String id, Object[] arguments) throws NullPointerException
+ {
+ super(resource, id, arguments);
+ }
+
+ /**
+ * Constructs a new ErrorBundle using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param encoding the encoding of the resource file
+ * @param arguments an array containing the arguments for the message
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ * @throws UnsupportedEncodingException if the encoding is not supported
+ */
+ public ErrorBundle(String resource, String id, String encoding, Object[] arguments) throws NullPointerException, UnsupportedEncodingException
+ {
+ super(resource, id, encoding, arguments);
+ }
+
+ /**
+ * Returns the summary message in the given locale and timezone.
+ * @param loc the {@link Locale}
+ * @param timezone the {@link TimeZone}
+ * @return the summary message.
+ * @throws MissingEntryException if the message is not available
+ */
+ public String getSummary(Locale loc, TimeZone timezone) throws MissingEntryException
+ {
+ return getEntry(SUMMARY_ENTRY,loc,timezone);
+ }
+
+ /**
+ * Returns the summary message in the given locale and the default timezone.
+ * @param loc the {@link Locale}
+ * @return the summary message.
+ * @throws MissingEntryException if the message is not available
+ */
+ public String getSummary(Locale loc) throws MissingEntryException
+ {
+ return getEntry(SUMMARY_ENTRY,loc,TimeZone.getDefault());
+ }
+
+ /**
+ * Returns the detail message in the given locale and timezone.
+ * @param loc the {@link Locale}
+ * @param timezone the {@link TimeZone}
+ * @return the detail message.
+ * @throws MissingEntryException if the message is not available
+ */
+ public String getDetail(Locale loc, TimeZone timezone) throws MissingEntryException
+ {
+ return getEntry(DETAIL_ENTRY,loc,timezone);
+ }
+
+ /**
+ * Returns the detail message in the given locale and the default timezone.
+ * @param loc the {@link Locale}
+ * @return the detail message.
+ * @throws MissingEntryException if the message is not available
+ */
+ public String getDetail(Locale loc) throws MissingEntryException
+ {
+ return getEntry(DETAIL_ENTRY,loc,TimeZone.getDefault());
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/i18n/LocaleString.java b/core/src/main/java/org/spongycastle/i18n/LocaleString.java
new file mode 100644
index 00000000..26a85b8a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/i18n/LocaleString.java
@@ -0,0 +1,30 @@
+package org.spongycastle.i18n;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Locale;
+
+public class LocaleString extends LocalizedMessage
+{
+
+ public LocaleString(String resource, String id)
+ {
+ super(resource, id);
+ }
+
+ public LocaleString(String resource, String id, String encoding) throws NullPointerException, UnsupportedEncodingException
+ {
+ 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)
+ {
+ return this.getEntry(null, locale, null);
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/i18n/LocalizedException.java b/core/src/main/java/org/spongycastle/i18n/LocalizedException.java
new file mode 100644
index 00000000..4b07c2cb
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/i18n/LocalizedException.java
@@ -0,0 +1,49 @@
+package org.spongycastle.i18n;
+
+import java.util.Locale;
+
+/**
+ * Base class for all Exceptions with localized messages.
+ */
+public class LocalizedException extends Exception
+{
+
+ protected ErrorBundle message;
+ private Throwable cause;
+
+ /**
+ * Constructs a new LocalizedException with the specified localized message.
+ * @param message the {@link ErrorBundle} that contains the message for the exception
+ */
+ public LocalizedException(ErrorBundle message)
+ {
+ super(message.getText(Locale.getDefault()));
+ this.message = message;
+ }
+
+ /**
+ * Constructs a new LocalizedException with the specified localized message and cause.
+ * @param message the {@link ErrorBundle} that contains the message for the exception
+ * @param throwable the cause
+ */
+ public LocalizedException(ErrorBundle message, Throwable throwable)
+ {
+ super(message.getText(Locale.getDefault()));
+ this.message = message;
+ this.cause = throwable;
+ }
+
+ /**
+ * Returns the localized error message of the exception.
+ * @return the localized error message as {@link ErrorBundle}
+ */
+ public ErrorBundle getErrorMessage()
+ {
+ return message;
+ }
+
+ public Throwable getCause()
+ {
+ return cause;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/i18n/LocalizedMessage.java b/core/src/main/java/org/spongycastle/i18n/LocalizedMessage.java
new file mode 100644
index 00000000..e4e40328
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/i18n/LocalizedMessage.java
@@ -0,0 +1,476 @@
+package org.spongycastle.i18n;
+
+import org.spongycastle.i18n.filter.Filter;
+import org.spongycastle.i18n.filter.TrustedInput;
+import org.spongycastle.i18n.filter.UntrustedInput;
+import org.spongycastle.i18n.filter.UntrustedUrlInput;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.text.DateFormat;
+import java.text.Format;
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.TimeZone;
+
+public class LocalizedMessage
+{
+
+ protected final String id;
+ protected final String resource;
+
+ // ISO-8859-1 is the default encoding
+ public static final String DEFAULT_ENCODING = "ISO-8859-1";
+ protected String encoding = DEFAULT_ENCODING;
+
+ protected FilteredArguments arguments;
+ protected FilteredArguments extraArgs = null;
+
+ protected Filter filter = null;
+
+ protected ClassLoader loader = null;
+
+ /**
+ * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ */
+ public LocalizedMessage(String resource,String id) throws NullPointerException
+ {
+ if (resource == null || id == null)
+ {
+ throw new NullPointerException();
+ }
+ this.id = id;
+ this.resource = resource;
+ arguments = new FilteredArguments();
+ }
+
+ /**
+ * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param encoding the encoding of the resource file
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ * @throws UnsupportedEncodingException if the encoding is not supported
+ */
+ public LocalizedMessage(String resource,String id, String encoding) throws NullPointerException, UnsupportedEncodingException
+ {
+ if (resource == null || id == null)
+ {
+ throw new NullPointerException();
+ }
+ this.id = id;
+ this.resource = resource;
+ arguments = new FilteredArguments();
+ if (!Charset.isSupported(encoding))
+ {
+ throw new UnsupportedEncodingException("The encoding \"" + encoding + "\" is not supported.");
+ }
+ this.encoding = encoding;
+ }
+
+ /**
+ * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param arguments an array containing the arguments for the message
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ */
+ public LocalizedMessage(String resource, String id, Object[] arguments) throws NullPointerException
+ {
+ if (resource == null || id == null || arguments == null)
+ {
+ throw new NullPointerException();
+ }
+ this.id = id;
+ this.resource = resource;
+ this.arguments = new FilteredArguments(arguments);
+ }
+
+ /**
+ * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param encoding the encoding of the resource file
+ * @param arguments an array containing the arguments for the message
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ * @throws UnsupportedEncodingException if the encoding is not supported
+ */
+ public LocalizedMessage(String resource, String id, String encoding, Object[] arguments) throws NullPointerException, UnsupportedEncodingException
+ {
+ if (resource == null || id == null || arguments == null)
+ {
+ throw new NullPointerException();
+ }
+ this.id = id;
+ this.resource = resource;
+ this.arguments = new FilteredArguments(arguments);
+ if (!Charset.isSupported(encoding))
+ {
+ throw new UnsupportedEncodingException("The encoding \"" + encoding + "\" is not supported.");
+ }
+ this.encoding = encoding;
+ }
+
+ /**
+ * Reads the entry <code>id + "." + key</code> from the resource file and returns a
+ * formated message for the given Locale and TimeZone.
+ * @param key second part of the entry id
+ * @param loc the used {@link Locale}
+ * @param timezone the used {@link TimeZone}
+ * @return a Strng containing the localized message
+ * @throws MissingEntryException if the resource file is not available or the entry does not exist.
+ */
+ public String getEntry(String key,Locale loc, TimeZone timezone) throws MissingEntryException
+ {
+ String entry = id;
+ if (key != null)
+ {
+ entry += "." + key;
+ }
+
+ try
+ {
+ ResourceBundle bundle;
+ if (loader == null)
+ {
+ bundle = ResourceBundle.getBundle(resource,loc);
+ }
+ else
+ {
+ bundle = ResourceBundle.getBundle(resource, loc, loader);
+ }
+ String result = bundle.getString(entry);
+ if (!encoding.equals(DEFAULT_ENCODING))
+ {
+ result = new String(result.getBytes(DEFAULT_ENCODING), encoding);
+ }
+ if (!arguments.isEmpty())
+ {
+ result = formatWithTimeZone(result,arguments.getFilteredArgs(loc),loc,timezone);
+ }
+ result = addExtraArgs(result, loc);
+ return result;
+ }
+ catch (MissingResourceException mre)
+ {
+ throw new MissingEntryException("Can't find entry " + entry + " in resource file " + resource + ".",
+ resource,
+ entry,
+ loc,
+ loader != null ? loader : this.getClassLoader());
+ }
+ catch (UnsupportedEncodingException use)
+ {
+ // should never occur - cause we already test this in the constructor
+ throw new RuntimeException(use);
+ }
+ }
+
+ protected String formatWithTimeZone(
+ String template,
+ Object[] arguments,
+ Locale locale,
+ TimeZone timezone)
+ {
+ MessageFormat mf = new MessageFormat(" ");
+ mf.setLocale(locale);
+ mf.applyPattern(template);
+ if (!timezone.equals(TimeZone.getDefault()))
+ {
+ Format[] formats = mf.getFormats();
+ for (int i = 0; i < formats.length; i++)
+ {
+ if (formats[i] instanceof DateFormat)
+ {
+ DateFormat temp = (DateFormat) formats[i];
+ temp.setTimeZone(timezone);
+ mf.setFormat(i,temp);
+ }
+ }
+ }
+ return mf.format(arguments);
+ }
+
+ protected String addExtraArgs(String msg, Locale locale)
+ {
+ if (extraArgs != null)
+ {
+ StringBuffer sb = new StringBuffer(msg);
+ Object[] filteredArgs = extraArgs.getFilteredArgs(locale);
+ for (int i = 0; i < filteredArgs.length; i++)
+ {
+ sb.append(filteredArgs[i]);
+ }
+ msg = sb.toString();
+ }
+ return msg;
+ }
+
+ /**
+ * Sets the {@link Filter} that is used to filter the arguments of this message
+ * @param filter the {@link Filter} to use. <code>null</code> to disable filtering.
+ */
+ public void setFilter(Filter filter)
+ {
+ arguments.setFilter(filter);
+ if (extraArgs != null)
+ {
+ extraArgs.setFilter(filter);
+ }
+ this.filter = filter;
+ }
+
+ /**
+ * Returns the current filter.
+ * @return the current filter
+ */
+ public Filter getFilter()
+ {
+ return filter;
+ }
+
+ /**
+ * Set the {@link ClassLoader} which loads the resource files. If it is set to <code>null</code>
+ * then the default {@link ClassLoader} is used.
+ * @param loader the {@link ClassLoader} which loads the resource files
+ */
+ public void setClassLoader(ClassLoader loader)
+ {
+ this.loader = loader;
+ }
+
+ /**
+ * Returns the {@link ClassLoader} which loads the resource files or <code>null</code>
+ * if the default ClassLoader is used.
+ * @return the {@link ClassLoader} which loads the resource files
+ */
+ public ClassLoader getClassLoader()
+ {
+ return loader;
+ }
+
+ /**
+ * Returns the id of the message in the resource bundle.
+ * @return the id of the message
+ */
+ public String getId()
+ {
+ return id;
+ }
+
+ /**
+ * Returns the name of the resource bundle for this message
+ * @return name of the resource file
+ */
+ public String getResource()
+ {
+ return resource;
+ }
+
+ /**
+ * Returns an <code>Object[]</code> containing the message arguments.
+ * @return the message arguments
+ */
+ public Object[] getArguments()
+ {
+ return arguments.getArguments();
+ }
+
+ /**
+ *
+ * @param extraArg
+ */
+ public void setExtraArgument(Object extraArg)
+ {
+ setExtraArguments(new Object[] {extraArg});
+ }
+
+ /**
+ *
+ * @param extraArgs
+ */
+ public void setExtraArguments(Object[] extraArgs)
+ {
+ if (extraArgs != null)
+ {
+ this.extraArgs = new FilteredArguments(extraArgs);
+ this.extraArgs.setFilter(filter);
+ }
+ else
+ {
+ this.extraArgs = null;
+ }
+ }
+
+ /**
+ *
+ * @return
+ */
+ public Object[] getExtraArgs()
+ {
+ return (extraArgs == null) ? null : extraArgs.getArguments();
+ }
+
+ protected class FilteredArguments
+ {
+ protected static final int NO_FILTER = 0;
+ protected static final int FILTER = 1;
+ protected static final int FILTER_URL = 2;
+
+ protected Filter filter = null;
+
+ protected boolean[] isLocaleSpecific;
+ protected int[] argFilterType;
+ protected Object[] arguments;
+ protected Object[] unpackedArgs;
+ protected Object[] filteredArgs;
+
+ FilteredArguments()
+ {
+ this(new Object[0]);
+ }
+
+ FilteredArguments(Object[] args)
+ {
+ this.arguments = args;
+ this.unpackedArgs = new Object[args.length];
+ this.filteredArgs = new Object[args.length];
+ this.isLocaleSpecific = new boolean[args.length];
+ this.argFilterType = new int[args.length];
+ for (int i = 0; i < args.length; i++)
+ {
+ if (args[i] instanceof TrustedInput)
+ {
+ this.unpackedArgs[i] = ((TrustedInput) args[i]).getInput();
+ argFilterType[i] = NO_FILTER;
+ }
+ else if (args[i] instanceof UntrustedInput)
+ {
+ this.unpackedArgs[i] = ((UntrustedInput) args[i]).getInput();
+ if (args[i] instanceof UntrustedUrlInput)
+ {
+ argFilterType[i] = FILTER_URL;
+ }
+ else
+ {
+ argFilterType[i] = FILTER;
+ }
+ }
+ else
+ {
+ this.unpackedArgs[i] = args[i];
+ argFilterType[i] = FILTER;
+ }
+
+ // locale specific
+ this.isLocaleSpecific[i] = (this.unpackedArgs[i] instanceof LocaleString);
+ }
+ }
+
+ public boolean isEmpty()
+ {
+ return unpackedArgs.length == 0;
+ }
+
+ public Object[] getArguments()
+ {
+ return arguments;
+ }
+
+ public Object[] getFilteredArgs(Locale locale)
+ {
+ Object[] result = new Object[unpackedArgs.length];
+ for (int i = 0; i < unpackedArgs.length; i++)
+ {
+ Object arg;
+ if (filteredArgs[i] != null)
+ {
+ arg = filteredArgs[i];
+ }
+ else
+ {
+ arg = unpackedArgs[i];
+ if (isLocaleSpecific[i])
+ {
+ // get locale
+ arg = ((LocaleString) arg).getLocaleString(locale);
+ arg = filter(argFilterType[i], arg);
+ }
+ else
+ {
+ arg = filter(argFilterType[i], arg);
+ filteredArgs[i] = arg;
+ }
+ }
+ result[i] = arg;
+ }
+ return result;
+ }
+
+ private Object filter(int type, Object obj)
+ {
+ if (filter != null)
+ {
+ Object o = (null == obj) ? "null" : obj;
+ switch (type)
+ {
+ case NO_FILTER:
+ return o;
+ case FILTER:
+ return filter.doFilter(o.toString());
+ case FILTER_URL:
+ return filter.doFilterUrl(o.toString());
+ default:
+ return null;
+ }
+ }
+ else
+ {
+ return obj;
+ }
+ }
+
+ public Filter getFilter()
+ {
+ return filter;
+ }
+
+ public void setFilter(Filter filter)
+ {
+ if (filter != this.filter)
+ {
+ for (int i = 0; i < unpackedArgs.length; i++)
+ {
+ filteredArgs[i] = null;
+ }
+ }
+ this.filter = filter;
+ }
+
+ }
+
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append("Resource: \"").append(resource);
+ sb.append("\" Id: \"").append(id).append("\"");
+ sb.append(" Arguments: ").append(arguments.getArguments().length).append(" normal");
+ if (extraArgs != null && extraArgs.getArguments().length > 0)
+ {
+ sb.append(", ").append(extraArgs.getArguments().length).append(" extra");
+ }
+ sb.append(" Encoding: ").append(encoding);
+ sb.append(" ClassLoader: ").append(loader);
+ return sb.toString();
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/i18n/MessageBundle.java b/core/src/main/java/org/spongycastle/i18n/MessageBundle.java
new file mode 100644
index 00000000..407e9cab
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/i18n/MessageBundle.java
@@ -0,0 +1,92 @@
+package org.spongycastle.i18n;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Locale;
+import java.util.TimeZone;
+
+public class MessageBundle extends TextBundle
+{
+
+ /**
+ * title entry key
+ */
+ public static final String TITLE_ENTRY = "title";
+
+ /**
+ * Constructs a new MessageBundle using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ */
+ public MessageBundle(String resource, String id) throws NullPointerException
+ {
+ super(resource, id);
+ }
+
+ /**
+ * Constructs a new MessageBundle using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param encoding the encoding of the resource file
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ * @throws UnsupportedEncodingException if the encoding is not supported
+ */
+ public MessageBundle(String resource, String id, String encoding) throws NullPointerException, UnsupportedEncodingException
+ {
+ super(resource, id, encoding);
+ }
+
+ /**
+ * Constructs a new MessageBundle using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param arguments an array containing the arguments for the message
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ */
+ public MessageBundle(String resource, String id, Object[] arguments) throws NullPointerException
+ {
+ super(resource, id, arguments);
+ }
+
+ /**
+ * Constructs a new MessageBundle using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param encoding the encoding of the resource file
+ * @param arguments an array containing the arguments for the message
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ * @throws UnsupportedEncodingException if the encoding is not supported
+ */
+ public MessageBundle(String resource, String id, String encoding, Object[] arguments) throws NullPointerException, UnsupportedEncodingException
+ {
+ super(resource, id, encoding, arguments);
+ }
+
+ /**
+ * Returns the title message in the given locale and timezone.
+ * @param loc the {@link Locale}
+ * @param timezone the {@link TimeZone}
+ * @return the title message.
+ * @throws MissingEntryException if the message is not available
+ */
+ public String getTitle(Locale loc,TimeZone timezone) throws MissingEntryException
+ {
+ return getEntry(TITLE_ENTRY,loc,timezone);
+ }
+
+ /**
+ * Returns the title message in the given locale and the default timezone.
+ * @param loc the {@link Locale}
+ * @return the title message.
+ * @throws MissingEntryException if the message is not available
+ */
+ public String getTitle(Locale loc) throws MissingEntryException
+ {
+ return getEntry(TITLE_ENTRY,loc,TimeZone.getDefault());
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/i18n/MissingEntryException.java b/core/src/main/java/org/spongycastle/i18n/MissingEntryException.java
new file mode 100644
index 00000000..5ee4df86
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/i18n/MissingEntryException.java
@@ -0,0 +1,73 @@
+package org.spongycastle.i18n;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Locale;
+
+public class MissingEntryException extends RuntimeException
+{
+
+ protected final String resource;
+ protected final String key;
+ protected final ClassLoader loader;
+ protected final Locale locale;
+
+ private String debugMsg;
+
+ public MissingEntryException(String message, String resource, String key, Locale locale, ClassLoader loader)
+ {
+ super(message);
+ this.resource = resource;
+ this.key = key;
+ this.locale = locale;
+ this.loader = loader;
+ }
+
+ public MissingEntryException(String message, Throwable cause, String resource, String key, Locale locale, ClassLoader loader)
+ {
+ super(message, cause);
+ this.resource = resource;
+ this.key = key;
+ this.locale = locale;
+ this.loader = loader;
+ }
+
+ public String getKey()
+ {
+ return key;
+ }
+
+ public String getResource()
+ {
+ return resource;
+ }
+
+ public ClassLoader getClassLoader()
+ {
+ return loader;
+ }
+
+ public Locale getLocale()
+ {
+ return locale;
+ }
+
+ public String getDebugMsg()
+ {
+ if (debugMsg == null)
+ {
+ debugMsg = "Can not find entry " + key + " in resource file " + resource + " for the locale " + locale + ".";
+ if (loader instanceof URLClassLoader)
+ {
+ URL[] urls = ((URLClassLoader) loader).getURLs();
+ debugMsg += " The following entries in the classpath were searched: ";
+ for (int i = 0; i != urls.length; i++)
+ {
+ debugMsg += urls[i] + " ";
+ }
+ }
+ }
+ return debugMsg;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/i18n/TextBundle.java b/core/src/main/java/org/spongycastle/i18n/TextBundle.java
new file mode 100644
index 00000000..6432c3b4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/i18n/TextBundle.java
@@ -0,0 +1,92 @@
+package org.spongycastle.i18n;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Locale;
+import java.util.TimeZone;
+
+public class TextBundle extends LocalizedMessage
+{
+
+ /**
+ * text entry key
+ */
+ public static final String TEXT_ENTRY = "text";
+
+ /**
+ * Constructs a new TextBundle using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ */
+ public TextBundle(String resource, String id) throws NullPointerException
+ {
+ super(resource, id);
+ }
+
+ /**
+ * Constructs a new TextBundle using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param encoding the encoding of the resource file
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ * @throws UnsupportedEncodingException if the encoding is not supported
+ */
+ public TextBundle(String resource, String id, String encoding) throws NullPointerException, UnsupportedEncodingException
+ {
+ super(resource, id, encoding);
+ }
+
+ /**
+ * Constructs a new TextBundle using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param arguments an array containing the arguments for the message
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ */
+ public TextBundle(String resource, String id, Object[] arguments) throws NullPointerException
+ {
+ super(resource, id, arguments);
+ }
+
+ /**
+ * Constructs a new TextBundle using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param encoding the encoding of the resource file
+ * @param arguments an array containing the arguments for the message
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ * @throws UnsupportedEncodingException if the encoding is not supported
+ */
+ public TextBundle(String resource, String id, String encoding, Object[] arguments) throws NullPointerException, UnsupportedEncodingException
+ {
+ super(resource, id, encoding, arguments);
+ }
+
+ /**
+ * Returns the text message in the given locale and timezone.
+ * @param loc the {@link Locale}
+ * @param timezone the {@link TimeZone}
+ * @return the text message.
+ * @throws MissingEntryException if the message is not available
+ */
+ public String getText(Locale loc, TimeZone timezone) throws MissingEntryException
+ {
+ return getEntry(TEXT_ENTRY,loc,timezone);
+ }
+
+ /**
+ * Returns the text message in the given locale and the defaut timezone.
+ * @param loc the {@link Locale}
+ * @return the text message.
+ * @throws MissingEntryException if the message is not available
+ */
+ public String getText(Locale loc) throws MissingEntryException
+ {
+ return getEntry(TEXT_ENTRY,loc,TimeZone.getDefault());
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/i18n/filter/Filter.java b/core/src/main/java/org/spongycastle/i18n/filter/Filter.java
new file mode 100644
index 00000000..7483241c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/i18n/filter/Filter.java
@@ -0,0 +1,21 @@
+
+package org.spongycastle.i18n.filter;
+
+public interface Filter
+{
+
+ /**
+ * Runs the filter on the input String and returns the filtered String
+ * @param input input String
+ * @return filtered String
+ */
+ public String doFilter(String input);
+
+ /**
+ * Runs the filter on the input url and returns the filtered String
+ * @param input input url String
+ * @return filtered String
+ */
+ public String doFilterUrl(String input);
+
+}
diff --git a/core/src/main/java/org/spongycastle/i18n/filter/HTMLFilter.java b/core/src/main/java/org/spongycastle/i18n/filter/HTMLFilter.java
new file mode 100644
index 00000000..a6af7fe7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/i18n/filter/HTMLFilter.java
@@ -0,0 +1,68 @@
+
+package org.spongycastle.i18n.filter;
+
+/**
+ * HTML Filter
+ */
+public class HTMLFilter implements Filter
+{
+
+ public String doFilter(String input)
+ {
+ StringBuffer buf = new StringBuffer(input);
+ int i = 0;
+ while (i < buf.length())
+ {
+ char ch = buf.charAt(i);
+ switch (ch)
+ {
+ case '<':
+ buf.replace(i,i+1,"&#60");
+ break;
+ case '>':
+ buf.replace(i,i+1,"&#62");
+ break;
+ case '(':
+ buf.replace(i,i+1,"&#40");
+ break;
+ case ')':
+ buf.replace(i,i+1,"&#41");
+ break;
+ case '#':
+ buf.replace(i,i+1,"&#35");
+ break;
+ case '&':
+ buf.replace(i,i+1,"&#38");
+ break;
+ case '\"':
+ buf.replace(i,i+1,"&#34");
+ break;
+ case '\'':
+ buf.replace(i,i+1,"&#39");
+ break;
+ case '%':
+ buf.replace(i,i+1,"&#37");
+ break;
+ case ';':
+ buf.replace(i,i+1,"&#59");
+ break;
+ case '+':
+ buf.replace(i,i+1,"&#43");
+ break;
+ case '-':
+ buf.replace(i,i+1,"&#45");
+ break;
+ default:
+ i -= 3;
+ }
+ i += 4;
+ }
+ return buf.toString();
+ }
+
+ public String doFilterUrl(String input)
+ {
+ return doFilter(input);
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/i18n/filter/SQLFilter.java b/core/src/main/java/org/spongycastle/i18n/filter/SQLFilter.java
new file mode 100644
index 00000000..73ec5efe
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/i18n/filter/SQLFilter.java
@@ -0,0 +1,69 @@
+
+package org.spongycastle.i18n.filter;
+
+/**
+ * Filter for strings to store in a SQL table.
+ *
+ * escapes ' " = - / \ ; \r \n
+ */
+public class SQLFilter implements Filter
+{
+
+ public String doFilter(String input)
+ {
+ StringBuffer buf = new StringBuffer(input);
+ int i = 0;
+ while (i < buf.length())
+ {
+ char ch = buf.charAt(i);
+ switch (ch)
+ {
+ case '\'':
+ buf.replace(i,i+1,"\\\'");
+ i += 1;
+ break;
+ case '\"':
+ buf.replace(i,i+1,"\\\"");
+ i += 1;
+ break;
+ case '=':
+ buf.replace(i,i+1,"\\=");
+ i += 1;
+ break;
+ case '-':
+ buf.replace(i,i+1,"\\-");
+ i += 1;
+ break;
+ case '/':
+ buf.replace(i,i+1,"\\/");
+ i += 1;
+ break;
+ case '\\':
+ buf.replace(i,i+1,"\\\\");
+ i += 1;
+ break;
+ case ';':
+ buf.replace(i,i+1,"\\;");
+ i += 1;
+ break;
+ case '\r':
+ buf.replace(i,i+1,"\\r");
+ i += 1;
+ break;
+ case '\n':
+ buf.replace(i,i+1,"\\n");
+ i += 1;
+ break;
+ default:
+ }
+ i++;
+ }
+ return buf.toString();
+ }
+
+ public String doFilterUrl(String input)
+ {
+ return doFilter(input);
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/i18n/filter/TrustedInput.java b/core/src/main/java/org/spongycastle/i18n/filter/TrustedInput.java
new file mode 100644
index 00000000..adbf0a3e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/i18n/filter/TrustedInput.java
@@ -0,0 +1,23 @@
+package org.spongycastle.i18n.filter;
+
+public class TrustedInput
+{
+
+ protected Object input;
+
+ public TrustedInput(Object input)
+ {
+ this.input = input;
+ }
+
+ public Object getInput()
+ {
+ return input;
+ }
+
+ public String toString()
+ {
+ return input.toString();
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/i18n/filter/UntrustedInput.java b/core/src/main/java/org/spongycastle/i18n/filter/UntrustedInput.java
new file mode 100644
index 00000000..79754a0b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/i18n/filter/UntrustedInput.java
@@ -0,0 +1,44 @@
+
+package org.spongycastle.i18n.filter;
+
+/**
+ * Wrapper class to mark untrusted input.
+ */
+public class UntrustedInput
+{
+
+ protected Object input;
+
+ /**
+ * Construct a new UntrustedInput instance.
+ * @param input the untrusted input Object
+ */
+ public UntrustedInput(Object input)
+ {
+ this.input = input;
+ }
+
+ /**
+ * Returns the untrusted input as Object.
+ * @return the <code>input</code> as Object
+ */
+ public Object getInput()
+ {
+ return input;
+ }
+
+ /**
+ * Returns the untrusted input convertet to a String.
+ * @return the <code>input</code> as String
+ */
+ public String getString()
+ {
+ return input.toString();
+ }
+
+ public String toString()
+ {
+ return input.toString();
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/i18n/filter/UntrustedUrlInput.java b/core/src/main/java/org/spongycastle/i18n/filter/UntrustedUrlInput.java
new file mode 100644
index 00000000..3a3cc39a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/i18n/filter/UntrustedUrlInput.java
@@ -0,0 +1,14 @@
+package org.spongycastle.i18n.filter;
+
+/**
+ *
+ * Wrapper class to mark an untrusted Url
+ */
+public class UntrustedUrlInput extends UntrustedInput
+{
+ public UntrustedUrlInput(Object url)
+ {
+ super(url);
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/AbstractECMultiplier.java b/core/src/main/java/org/spongycastle/math/ec/AbstractECMultiplier.java
new file mode 100644
index 00000000..e4dee6dd
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/AbstractECMultiplier.java
@@ -0,0 +1,26 @@
+package org.spongycastle.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());
+ ECPoint result = sign > 0 ? positive : positive.negate();
+
+ /*
+ * Although the various multipliers ought not to produce invalid output under normal
+ * circumstances, a final check here is advised to guard against fault attacks.
+ */
+ return ECAlgorithms.validatePoint(result);
+ }
+
+ protected abstract ECPoint multiplyPositive(ECPoint p, BigInteger k);
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/DoubleAddMultiplier.java b/core/src/main/java/org/spongycastle/math/ec/DoubleAddMultiplier.java
new file mode 100644
index 00000000..cc98a3a2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/DoubleAddMultiplier.java
@@ -0,0 +1,24 @@
+package org.spongycastle.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/core/src/main/java/org/spongycastle/math/ec/ECAlgorithms.java b/core/src/main/java/org/spongycastle/math/ec/ECAlgorithms.java
new file mode 100644
index 00000000..7d73cebe
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/ECAlgorithms.java
@@ -0,0 +1,469 @@
+package org.spongycastle.math.ec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.ec.endo.ECEndomorphism;
+import org.spongycastle.math.ec.endo.GLVEndomorphism;
+import org.spongycastle.math.field.FiniteField;
+import org.spongycastle.math.field.PolynomialExtensionField;
+
+public class ECAlgorithms
+{
+ public static boolean isF2mCurve(ECCurve c)
+ {
+ FiniteField field = c.getField();
+ return field.getDimension() > 1 && field.getCharacteristic().equals(ECConstants.TWO)
+ && field instanceof PolynomialExtensionField;
+ }
+
+ public static boolean isFpCurve(ECCurve c)
+ {
+ return c.getField().getDimension() == 1;
+ }
+
+ public static ECPoint sumOfMultiplies(ECPoint[] ps, BigInteger[] ks)
+ {
+ if (ps == null || ks == null || ps.length != ks.length || ps.length < 1)
+ {
+ throw new IllegalArgumentException("point and scalar arrays should be non-null, and of equal, non-zero, length");
+ }
+
+ int count = ps.length;
+ switch (count)
+ {
+ case 1:
+ return ps[0].multiply(ks[0]);
+ case 2:
+ return sumOfTwoMultiplies(ps[0], ks[0], ps[1], ks[1]);
+ default:
+ break;
+ }
+
+ ECPoint p = ps[0];
+ ECCurve c = p.getCurve();
+
+ ECPoint[] imported = new ECPoint[count];
+ imported[0] = p;
+ for (int i = 1; i < count; ++i)
+ {
+ imported[i] = importPoint(c, ps[i]);
+ }
+
+ ECEndomorphism endomorphism = c.getEndomorphism();
+ if (endomorphism instanceof GLVEndomorphism)
+ {
+ return validatePoint(implSumOfMultipliesGLV(imported, ks, (GLVEndomorphism)endomorphism));
+ }
+
+ return validatePoint(implSumOfMultiplies(imported, ks));
+ }
+
+ public static ECPoint sumOfTwoMultiplies(ECPoint P, BigInteger a,
+ ECPoint Q, BigInteger b)
+ {
+ ECCurve cp = P.getCurve();
+ Q = importPoint(cp, Q);
+
+ // Point multiplication for Koblitz curves (using WTNAF) beats Shamir's trick
+ if (cp instanceof ECCurve.F2m)
+ {
+ ECCurve.F2m f2mCurve = (ECCurve.F2m)cp;
+ if (f2mCurve.isKoblitz())
+ {
+ return validatePoint(P.multiply(a).add(Q.multiply(b)));
+ }
+ }
+
+ ECEndomorphism endomorphism = cp.getEndomorphism();
+ if (endomorphism instanceof GLVEndomorphism)
+ {
+ return validatePoint(
+ implSumOfMultipliesGLV(new ECPoint[]{ P, Q }, new BigInteger[]{ a, b }, (GLVEndomorphism)endomorphism));
+ }
+
+ return validatePoint(implShamirsTrickWNaf(P, a, Q, b));
+ }
+
+ /*
+ * "Shamir's Trick", originally due to E. G. Straus
+ * (Addition chains of vectors. American Mathematical Monthly,
+ * 71(7):806-808, Aug./Sept. 1964)
+ * <pre>
+ * Input: The points P, Q, scalar k = (km?, ... , k1, k0)
+ * and scalar l = (lm?, ... , l1, l0).
+ * Output: R = k * P + l * Q.
+ * 1: Z <- P + Q
+ * 2: R <- O
+ * 3: for i from m-1 down to 0 do
+ * 4: R <- R + R {point doubling}
+ * 5: if (ki = 1) and (li = 0) then R <- R + P end if
+ * 6: if (ki = 0) and (li = 1) then R <- R + Q end if
+ * 7: if (ki = 1) and (li = 1) then R <- R + Z end if
+ * 8: end for
+ * 9: return R
+ * </pre>
+ */
+ public static ECPoint shamirsTrick(ECPoint P, BigInteger k,
+ ECPoint Q, BigInteger l)
+ {
+ ECCurve cp = P.getCurve();
+ Q = importPoint(cp, Q);
+
+ return validatePoint(implShamirsTrickJsf(P, k, Q, l));
+ }
+
+ public static ECPoint importPoint(ECCurve c, ECPoint p)
+ {
+ ECCurve cp = p.getCurve();
+ if (!c.equals(cp))
+ {
+ throw new IllegalArgumentException("Point must be on the same curve");
+ }
+ return c.importPoint(p);
+ }
+
+ public static void montgomeryTrick(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;
+ }
+
+ /**
+ * Simple shift-and-add multiplication. Serves as reference implementation
+ * to verify (possibly faster) implementations, and for very small scalars.
+ *
+ * @param p
+ * The point to multiply.
+ * @param k
+ * The multiplier.
+ * @return The result of the point multiplication <code>kP</code>.
+ */
+ public static ECPoint referenceMultiply(ECPoint p, BigInteger k)
+ {
+ BigInteger x = k.abs();
+ ECPoint q = p.getCurve().getInfinity();
+ int t = x.bitLength();
+ if (t > 0)
+ {
+ if (x.testBit(0))
+ {
+ q = p;
+ }
+ for (int i = 1; i < t; i++)
+ {
+ p = p.twice();
+ if (x.testBit(i))
+ {
+ q = q.add(p);
+ }
+ }
+ }
+ return k.signum() < 0 ? q.negate() : q;
+ }
+
+ public static ECPoint validatePoint(ECPoint p)
+ {
+ if (!p.isValid())
+ {
+ throw new IllegalArgumentException("Invalid point");
+ }
+
+ return p;
+ }
+
+ static ECPoint implShamirsTrickJsf(ECPoint P, BigInteger k,
+ ECPoint Q, BigInteger l)
+ {
+ ECCurve curve = P.getCurve();
+ 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);
+
+ 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)
+ {
+ int jsfi = jsf[i];
+
+ // NOTE: The shifting ensures the sign is extended correctly
+ int kDigit = ((jsfi << 24) >> 28), lDigit = ((jsfi << 28) >> 28);
+
+ int index = 4 + (kDigit * 3) + lDigit;
+ R = R.twicePlus(table[index]);
+ }
+
+ return R;
+ }
+
+ static ECPoint implShamirsTrickWNaf(ECPoint P, BigInteger k,
+ ECPoint Q, BigInteger l)
+ {
+ boolean negK = k.signum() < 0, negL = l.signum() < 0;
+
+ k = k.abs();
+ l = l.abs();
+
+ int widthP = Math.max(2, Math.min(16, WNafUtil.getWindowSize(k.bitLength())));
+ int widthQ = Math.max(2, Math.min(16, WNafUtil.getWindowSize(l.bitLength())));
+
+ WNafPreCompInfo infoP = WNafUtil.precompute(P, widthP, true);
+ WNafPreCompInfo infoQ = WNafUtil.precompute(Q, widthQ, true);
+
+ ECPoint[] preCompP = negK ? infoP.getPreCompNeg() : infoP.getPreComp();
+ ECPoint[] preCompQ = negL ? infoQ.getPreCompNeg() : infoQ.getPreComp();
+ ECPoint[] preCompNegP = negK ? infoP.getPreComp() : infoP.getPreCompNeg();
+ ECPoint[] preCompNegQ = negL ? infoQ.getPreComp() : infoQ.getPreCompNeg();
+
+ byte[] wnafP = WNafUtil.generateWindowNaf(widthP, k);
+ byte[] wnafQ = WNafUtil.generateWindowNaf(widthQ, l);
+
+ return implShamirsTrickWNaf(preCompP, preCompNegP, wnafP, preCompQ, preCompNegQ, wnafQ);
+ }
+
+ static ECPoint implShamirsTrickWNaf(ECPoint P, BigInteger k, ECPointMap pointMapQ, BigInteger l)
+ {
+ boolean negK = k.signum() < 0, negL = l.signum() < 0;
+
+ k = k.abs();
+ l = l.abs();
+
+ int width = Math.max(2, Math.min(16, WNafUtil.getWindowSize(Math.max(k.bitLength(), l.bitLength()))));
+
+ ECPoint Q = WNafUtil.mapPointWithPrecomp(P, width, true, pointMapQ);
+ WNafPreCompInfo infoP = WNafUtil.getWNafPreCompInfo(P);
+ WNafPreCompInfo infoQ = WNafUtil.getWNafPreCompInfo(Q);
+
+ ECPoint[] preCompP = negK ? infoP.getPreCompNeg() : infoP.getPreComp();
+ ECPoint[] preCompQ = negL ? infoQ.getPreCompNeg() : infoQ.getPreComp();
+ ECPoint[] preCompNegP = negK ? infoP.getPreComp() : infoP.getPreCompNeg();
+ ECPoint[] preCompNegQ = negL ? infoQ.getPreComp() : infoQ.getPreCompNeg();
+
+ byte[] wnafP = WNafUtil.generateWindowNaf(width, k);
+ byte[] wnafQ = WNafUtil.generateWindowNaf(width, l);
+
+ return implShamirsTrickWNaf(preCompP, preCompNegP, wnafP, preCompQ, preCompNegQ, wnafQ);
+ }
+
+ private static ECPoint implShamirsTrickWNaf(ECPoint[] preCompP, ECPoint[] preCompNegP, byte[] wnafP,
+ ECPoint[] preCompQ, ECPoint[] preCompNegQ, byte[] wnafQ)
+ {
+ int len = Math.max(wnafP.length, wnafQ.length);
+
+ ECCurve curve = preCompP[0].getCurve();
+ ECPoint infinity = curve.getInfinity();
+
+ ECPoint R = infinity;
+ int zeroes = 0;
+
+ for (int i = len - 1; i >= 0; --i)
+ {
+ int wiP = i < wnafP.length ? wnafP[i] : 0;
+ int wiQ = i < wnafQ.length ? wnafQ[i] : 0;
+
+ if ((wiP | wiQ) == 0)
+ {
+ ++zeroes;
+ continue;
+ }
+
+ ECPoint r = infinity;
+ if (wiP != 0)
+ {
+ int nP = Math.abs(wiP);
+ ECPoint[] tableP = wiP < 0 ? preCompNegP : preCompP;
+ r = r.add(tableP[nP >>> 1]);
+ }
+ if (wiQ != 0)
+ {
+ int nQ = Math.abs(wiQ);
+ ECPoint[] tableQ = wiQ < 0 ? preCompNegQ : preCompQ;
+ r = r.add(tableQ[nQ >>> 1]);
+ }
+
+ if (zeroes > 0)
+ {
+ R = R.timesPow2(zeroes);
+ zeroes = 0;
+ }
+
+ R = R.twicePlus(r);
+ }
+
+ if (zeroes > 0)
+ {
+ R = R.timesPow2(zeroes);
+ }
+
+ return R;
+ }
+
+ static ECPoint implSumOfMultiplies(ECPoint[] ps, BigInteger[] ks)
+ {
+ int count = ps.length;
+ boolean[] negs = new boolean[count];
+ WNafPreCompInfo[] infos = new WNafPreCompInfo[count];
+ byte[][] wnafs = new byte[count][];
+
+ for (int i = 0; i < count; ++i)
+ {
+ BigInteger ki = ks[i]; negs[i] = ki.signum() < 0; ki = ki.abs();
+
+ int width = Math.max(2, Math.min(16, WNafUtil.getWindowSize(ki.bitLength())));
+ infos[i] = WNafUtil.precompute(ps[i], width, true);
+ wnafs[i] = WNafUtil.generateWindowNaf(width, ki);
+ }
+
+ return implSumOfMultiplies(negs, infos, wnafs);
+ }
+
+ static ECPoint implSumOfMultipliesGLV(ECPoint[] ps, BigInteger[] ks, GLVEndomorphism glvEndomorphism)
+ {
+ BigInteger n = ps[0].getCurve().getOrder();
+
+ int len = ps.length;
+
+ BigInteger[] abs = new BigInteger[len << 1];
+ for (int i = 0, j = 0; i < len; ++i)
+ {
+ BigInteger[] ab = glvEndomorphism.decomposeScalar(ks[i].mod(n));
+ abs[j++] = ab[0];
+ abs[j++] = ab[1];
+ }
+
+ ECPointMap pointMap = glvEndomorphism.getPointMap();
+ if (glvEndomorphism.hasEfficientPointMap())
+ {
+ return ECAlgorithms.implSumOfMultiplies(ps, pointMap, abs);
+ }
+
+ ECPoint[] pqs = new ECPoint[len << 1];
+ for (int i = 0, j = 0; i < len; ++i)
+ {
+ ECPoint p = ps[i], q = pointMap.map(p);
+ pqs[j++] = p;
+ pqs[j++] = q;
+ }
+
+ return ECAlgorithms.implSumOfMultiplies(pqs, abs);
+
+ }
+
+ static ECPoint implSumOfMultiplies(ECPoint[] ps, ECPointMap pointMap, BigInteger[] ks)
+ {
+ int halfCount = ps.length, fullCount = halfCount << 1;
+
+ boolean[] negs = new boolean[fullCount];
+ WNafPreCompInfo[] infos = new WNafPreCompInfo[fullCount];
+ byte[][] wnafs = new byte[fullCount][];
+
+ for (int i = 0; i < halfCount; ++i)
+ {
+ int j0 = i << 1, j1 = j0 + 1;
+
+ BigInteger kj0 = ks[j0]; negs[j0] = kj0.signum() < 0; kj0 = kj0.abs();
+ BigInteger kj1 = ks[j1]; negs[j1] = kj1.signum() < 0; kj1 = kj1.abs();
+
+ int width = Math.max(2, Math.min(16, WNafUtil.getWindowSize(Math.max(kj0.bitLength(), kj1.bitLength()))));
+
+ ECPoint P = ps[i], Q = WNafUtil.mapPointWithPrecomp(P, width, true, pointMap);
+ infos[j0] = WNafUtil.getWNafPreCompInfo(P);
+ infos[j1] = WNafUtil.getWNafPreCompInfo(Q);
+ wnafs[j0] = WNafUtil.generateWindowNaf(width, kj0);
+ wnafs[j1] = WNafUtil.generateWindowNaf(width, kj1);
+ }
+
+ return implSumOfMultiplies(negs, infos, wnafs);
+ }
+
+ private static ECPoint implSumOfMultiplies(boolean[] negs, WNafPreCompInfo[] infos, byte[][] wnafs)
+ {
+ int len = 0, count = wnafs.length;
+ for (int i = 0; i < count; ++i)
+ {
+ len = Math.max(len, wnafs[i].length);
+ }
+
+ ECCurve curve = infos[0].getPreComp()[0].getCurve();
+ ECPoint infinity = curve.getInfinity();
+
+ ECPoint R = infinity;
+ int zeroes = 0;
+
+ for (int i = len - 1; i >= 0; --i)
+ {
+ ECPoint r = infinity;
+
+ for (int j = 0; j < count; ++j)
+ {
+ byte[] wnaf = wnafs[j];
+ int wi = i < wnaf.length ? wnaf[i] : 0;
+ if (wi != 0)
+ {
+ int n = Math.abs(wi);
+ WNafPreCompInfo info = infos[j];
+ ECPoint[] table = (wi < 0 == negs[j]) ? info.getPreComp() : info.getPreCompNeg();
+ r = r.add(table[n >>> 1]);
+ }
+ }
+
+ if (r == infinity)
+ {
+ ++zeroes;
+ continue;
+ }
+
+ if (zeroes > 0)
+ {
+ R = R.timesPow2(zeroes);
+ zeroes = 0;
+ }
+
+ R = R.twicePlus(r);
+ }
+
+ if (zeroes > 0)
+ {
+ R = R.timesPow2(zeroes);
+ }
+
+ return R;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/ECConstants.java b/core/src/main/java/org/spongycastle/math/ec/ECConstants.java
new file mode 100644
index 00000000..c2b2a09a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/ECConstants.java
@@ -0,0 +1,12 @@
+package org.spongycastle.math.ec;
+
+import java.math.BigInteger;
+
+public interface ECConstants
+{
+ public static final BigInteger ZERO = BigInteger.valueOf(0);
+ public static final BigInteger ONE = BigInteger.valueOf(1);
+ public static final BigInteger TWO = BigInteger.valueOf(2);
+ public static final BigInteger THREE = BigInteger.valueOf(3);
+ public static final BigInteger FOUR = BigInteger.valueOf(4);
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/ECCurve.java b/core/src/main/java/org/spongycastle/math/ec/ECCurve.java
new file mode 100644
index 00000000..35c35473
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/ECCurve.java
@@ -0,0 +1,1113 @@
+package org.spongycastle.math.ec;
+
+import java.math.BigInteger;
+import java.util.Hashtable;
+import java.util.Random;
+
+import org.spongycastle.math.ec.endo.ECEndomorphism;
+import org.spongycastle.math.ec.endo.GLVEndomorphism;
+import org.spongycastle.math.field.FiniteField;
+import org.spongycastle.math.field.FiniteFields;
+import org.spongycastle.util.BigIntegers;
+import org.spongycastle.util.Integers;
+
+/**
+ * base class for an elliptic curve
+ */
+public abstract class ECCurve
+{
+ 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 ECEndomorphism endomorphism;
+ protected ECMultiplier multiplier;
+
+ Config(int coord, ECEndomorphism endomorphism, ECMultiplier multiplier)
+ {
+ this.coord = coord;
+ this.endomorphism = endomorphism;
+ this.multiplier = multiplier;
+ }
+
+ public Config setCoordinateSystem(int coord)
+ {
+ this.coord = coord;
+ return this;
+ }
+
+ public Config setEndomorphism(ECEndomorphism endomorphism)
+ {
+ this.endomorphism = endomorphism;
+ 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.endomorphism = endomorphism;
+ c.multiplier = multiplier;
+
+ return c;
+ }
+ }
+
+ protected FiniteField field;
+ protected ECFieldElement a, b;
+ protected BigInteger order, cofactor;
+
+ protected int coord = COORD_AFFINE;
+ protected ECEndomorphism endomorphism = null;
+ protected ECMultiplier multiplier = null;
+
+ protected ECCurve(FiniteField field)
+ {
+ this.field = field;
+ }
+
+ public abstract int getFieldSize();
+
+ public abstract ECFieldElement fromBigInteger(BigInteger x);
+
+ public Config configure()
+ {
+ return new Config(this.coord, this.endomorphism, this.multiplier);
+ }
+
+ public ECPoint validatePoint(BigInteger x, BigInteger y)
+ {
+ ECPoint p = createPoint(x, y);
+ if (!p.isValid())
+ {
+ throw new IllegalArgumentException("Invalid point coordinates");
+ }
+ return p;
+ }
+
+ /**
+ * @deprecated per-point compression property will be removed, use {@link #validatePoint(BigInteger, BigInteger)}
+ * and refer {@link ECPoint#getEncoded(boolean)}
+ */
+ public ECPoint validatePoint(BigInteger x, BigInteger y, boolean withCompression)
+ {
+ ECPoint p = createPoint(x, y, withCompression);
+ if (!p.isValid())
+ {
+ throw new IllegalArgumentException("Invalid point coordinates");
+ }
+ return p;
+ }
+
+ public ECPoint createPoint(BigInteger x, BigInteger y)
+ {
+ 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 abstract ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression);
+
+ protected ECMultiplier createDefaultMultiplier()
+ {
+ if (endomorphism instanceof GLVEndomorphism)
+ {
+ return new GLVMultiplier(this, (GLVEndomorphism)endomorphism);
+ }
+
+ return new WNafL2RMultiplier();
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ return coord == COORD_AFFINE;
+ }
+
+ public PreCompInfo getPreCompInfo(ECPoint point, String name)
+ {
+ checkPoint(point);
+ synchronized (point)
+ {
+ Hashtable table = point.preCompTable;
+ return table == null ? null : (PreCompInfo)table.get(name);
+ }
+ }
+
+ /**
+ * Adds <code>PreCompInfo</code> for a point on this curve, under a given name. Used by
+ * <code>ECMultiplier</code>s to save the precomputation for this <code>ECPoint</code> for use
+ * by subsequent multiplication.
+ *
+ * @param point
+ * The <code>ECPoint</code> to store precomputations for.
+ * @param name
+ * A <code>String</code> used to index precomputations of different types.
+ * @param preCompInfo
+ * The values precomputed by the <code>ECMultiplier</code>.
+ */
+ public void setPreCompInfo(ECPoint point, String name, PreCompInfo preCompInfo)
+ {
+ checkPoint(point);
+ synchronized (point)
+ {
+ Hashtable table = point.preCompTable;
+ if (null == table)
+ {
+ point.preCompTable = table = new Hashtable(4);
+ }
+ table.put(name, 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 validatePoint(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.montgomeryTrick(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();
+
+ public FiniteField getField()
+ {
+ return field;
+ }
+
+ public ECFieldElement getA()
+ {
+ return a;
+ }
+
+ public ECFieldElement getB()
+ {
+ return b;
+ }
+
+ public BigInteger getOrder()
+ {
+ return order;
+ }
+
+ public BigInteger getCofactor()
+ {
+ return cofactor;
+ }
+
+ public int getCoordinateSystem()
+ {
+ return coord;
+ }
+
+ protected abstract ECPoint decompressPoint(int yTilde, BigInteger X1);
+
+ public ECEndomorphism getEndomorphism()
+ {
+ return endomorphism;
+ }
+
+ /**
+ * Sets the default <code>ECMultiplier</code>, unless already set.
+ */
+ public synchronized 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).
+ * @return The decoded point.
+ */
+ public ECPoint decodePoint(byte[] encoded)
+ {
+ ECPoint p = null;
+ int expectedLength = (getFieldSize() + 7) / 8;
+
+ byte type = encoded[0];
+ switch (type)
+ {
+ case 0x00: // infinity
+ {
+ if (encoded.length != 1)
+ {
+ throw new IllegalArgumentException("Incorrect length for infinity encoding");
+ }
+
+ p = getInfinity();
+ break;
+ }
+ case 0x02: // compressed
+ case 0x03: // compressed
+ {
+ if (encoded.length != (expectedLength + 1))
+ {
+ throw new IllegalArgumentException("Incorrect length for compressed encoding");
+ }
+
+ int yTilde = type & 1;
+ BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength);
+
+ p = decompressPoint(yTilde, X);
+ if (!p.satisfiesCofactor())
+ {
+ throw new IllegalArgumentException("Invalid point");
+ }
+
+ break;
+ }
+ case 0x04: // uncompressed
+ {
+ if (encoded.length != (2 * expectedLength + 1))
+ {
+ throw new IllegalArgumentException("Incorrect length for uncompressed encoding");
+ }
+
+ BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength);
+ BigInteger Y = BigIntegers.fromUnsignedByteArray(encoded, 1 + expectedLength, expectedLength);
+
+ p = validatePoint(X, Y);
+ break;
+ }
+ case 0x06: // hybrid
+ case 0x07: // hybrid
+ {
+ if (encoded.length != (2 * expectedLength + 1))
+ {
+ throw new IllegalArgumentException("Incorrect length for hybrid encoding");
+ }
+
+ BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength);
+ BigInteger Y = BigIntegers.fromUnsignedByteArray(encoded, 1 + expectedLength, expectedLength);
+
+ if (Y.testBit(0) != (type == 0x07))
+ {
+ throw new IllegalArgumentException("Inconsistent Y coordinate in hybrid encoding");
+ }
+
+ p = validatePoint(X, Y);
+ break;
+ }
+ default:
+ throw new IllegalArgumentException("Invalid point encoding 0x" + Integer.toString(type, 16));
+ }
+
+ if (type != 0x00 && p.isInfinity())
+ {
+ throw new IllegalArgumentException("Invalid infinity encoding");
+ }
+
+ return p;
+ }
+
+ protected void checkPoint(ECPoint point)
+ {
+ 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");
+ }
+ }
+ }
+
+ public boolean equals(ECCurve other)
+ {
+ return this == other
+ || (null != other
+ && getField().equals(other.getField())
+ && getA().toBigInteger().equals(other.getA().toBigInteger())
+ && getB().toBigInteger().equals(other.getB().toBigInteger()));
+ }
+
+ public boolean equals(Object obj)
+ {
+ return this == obj || (obj instanceof ECCurve && equals((ECCurve)obj));
+ }
+
+ public int hashCode()
+ {
+ return getField().hashCode()
+ ^ Integers.rotateLeft(getA().toBigInteger().hashCode(), 8)
+ ^ Integers.rotateLeft(getB().toBigInteger().hashCode(), 16);
+ }
+
+ public static abstract class AbstractFp extends ECCurve
+ {
+ protected AbstractFp(BigInteger q)
+ {
+ super(FiniteFields.getPrimeField(q));
+ }
+
+ protected ECPoint decompressPoint(int yTilde, BigInteger X1)
+ {
+ ECFieldElement x = this.fromBigInteger(X1);
+ ECFieldElement rhs = x.square().add(a).multiply(x).add(b);
+ ECFieldElement y = rhs.sqrt();
+
+ /*
+ * If y is not a square, then we haven't got a point on the curve
+ */
+ if (y == null)
+ {
+ throw new IllegalArgumentException("Invalid point compression");
+ }
+
+ if (y.testBitZero() != (yTilde == 1))
+ {
+ // Use the other root
+ y = y.negate();
+ }
+
+ return this.createRawPoint(x, y, true);
+ }
+ }
+
+ /**
+ * Elliptic curve over Fp
+ */
+ public static class Fp extends AbstractFp
+ {
+ 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, a, b, null, null);
+ }
+
+ public Fp(BigInteger q, BigInteger a, BigInteger b, BigInteger order, BigInteger cofactor)
+ {
+ super(q);
+
+ this.q = q;
+ this.r = ECFieldElement.Fp.calculateResidue(q);
+ this.infinity = new ECPoint.Fp(this, null, null);
+
+ this.a = fromBigInteger(a);
+ this.b = fromBigInteger(b);
+ this.order = order;
+ this.cofactor = cofactor;
+ this.coord = FP_DEFAULT_COORDS;
+ }
+
+ protected Fp(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b)
+ {
+ this(q, r, a, b, null, null);
+ }
+
+ protected Fp(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b, BigInteger order, BigInteger cofactor)
+ {
+ super(q);
+
+ this.q = q;
+ this.r = r;
+ this.infinity = new ECPoint.Fp(this, null, null);
+
+ this.a = a;
+ this.b = b;
+ this.order = order;
+ this.cofactor = cofactor;
+ this.coord = FP_DEFAULT_COORDS;
+ }
+
+ protected ECCurve cloneCurve()
+ {
+ return new Fp(q, r, a, b, order, cofactor);
+ }
+
+ 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()
+ {
+ return q;
+ }
+
+ public int getFieldSize()
+ {
+ return q.bitLength();
+ }
+
+ public ECFieldElement fromBigInteger(BigInteger x)
+ {
+ return new ECFieldElement.Fp(this.q, this.r, x);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ return new ECPoint.Fp(this, x, y, withCompression);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ return new ECPoint.Fp(this, x, y, zs, withCompression);
+ }
+
+ public ECPoint importPoint(ECPoint p)
+ {
+ if (this != p.getCurve() && this.getCoordinateSystem() == COORD_JACOBIAN && !p.isInfinity())
+ {
+ 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);
+ }
+
+ public ECPoint getInfinity()
+ {
+ return infinity;
+ }
+ }
+
+ public static abstract class AbstractF2m extends ECCurve
+ {
+ private static FiniteField buildField(int m, int k1, int k2, int k3)
+ {
+ if (k1 == 0)
+ {
+ throw new IllegalArgumentException("k1 must be > 0");
+ }
+
+ if (k2 == 0)
+ {
+ if (k3 != 0)
+ {
+ throw new IllegalArgumentException("k3 must be 0 if k2 == 0");
+ }
+
+ return FiniteFields.getBinaryExtensionField(new int[]{ 0, k1, m });
+ }
+
+ if (k2 <= k1)
+ {
+ throw new IllegalArgumentException("k2 must be > k1");
+ }
+
+ if (k3 <= k2)
+ {
+ throw new IllegalArgumentException("k3 must be > k2");
+ }
+
+ return FiniteFields.getBinaryExtensionField(new int[]{ 0, k1, k2, k3, m });
+ }
+
+ protected AbstractF2m(int m, int k1, int k2, int k3)
+ {
+ super(buildField(m, k1, k2, k3));
+ }
+ }
+
+ /**
+ * Elliptic curves over F2m. The Weierstrass equation is given by
+ * <code>y<sup>2</sup> + xy = x<sup>3</sup> + ax<sup>2</sup> + b</code>.
+ */
+ public static class F2m extends AbstractF2m
+ {
+ private static final int F2M_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
+
+ /**
+ * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
+ */
+ private int m; // can't be final - JDK 1.1
+
+ /**
+ * TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
+ * x<sup>k</sup> + 1</code> represents the reduction polynomial
+ * <code>f(z)</code>.<br>
+ * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.<br>
+ */
+ private int k1; // can't be final - JDK 1.1
+
+ /**
+ * TPB: Always set to <code>0</code><br>
+ * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.<br>
+ */
+ private int k2; // can't be final - JDK 1.1
+
+ /**
+ * TPB: Always set to <code>0</code><br>
+ * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.<br>
+ */
+ private int k3; // can't be final - JDK 1.1
+
+ /**
+ * The point at infinity on this curve.
+ */
+ private ECPoint.F2m infinity; // can't be final - JDK 1.1
+
+ /**
+ * The parameter <code>&mu;</code> of the elliptic curve if this is
+ * a Koblitz curve.
+ */
+ private byte mu = 0;
+
+ /**
+ * The auxiliary values <code>s<sub>0</sub></code> and
+ * <code>s<sub>1</sub></code> used for partial modular reduction for
+ * Koblitz curves.
+ */
+ private BigInteger[] si = null;
+
+ /**
+ * Constructor for Trinomial Polynomial Basis (TPB).
+ * @param m The exponent <code>m</code> of
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
+ * x<sup>k</sup> + 1</code> represents the reduction
+ * polynomial <code>f(z)</code>.
+ * @param a The coefficient <code>a</code> in the Weierstrass equation
+ * for non-supersingular elliptic curves over
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param b The coefficient <code>b</code> in the Weierstrass equation
+ * for non-supersingular elliptic curves over
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ */
+ public F2m(
+ int m,
+ int k,
+ BigInteger a,
+ BigInteger b)
+ {
+ this(m, k, 0, 0, a, b, null, null);
+ }
+
+ /**
+ * Constructor for Trinomial Polynomial Basis (TPB).
+ * @param m The exponent <code>m</code> of
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
+ * x<sup>k</sup> + 1</code> represents the reduction
+ * polynomial <code>f(z)</code>.
+ * @param a The coefficient <code>a</code> in the Weierstrass equation
+ * for non-supersingular elliptic curves over
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param b The coefficient <code>b</code> in the Weierstrass equation
+ * for non-supersingular elliptic curves over
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param order The order of the main subgroup of the elliptic curve.
+ * @param cofactor The cofactor of the elliptic curve, i.e.
+ * <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>.
+ */
+ public F2m(
+ int m,
+ int k,
+ BigInteger a,
+ BigInteger b,
+ BigInteger order,
+ BigInteger cofactor)
+ {
+ this(m, k, 0, 0, a, b, order, cofactor);
+ }
+
+ /**
+ * Constructor for Pentanomial Polynomial Basis (PPB).
+ * @param m The exponent <code>m</code> of
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.
+ * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.
+ * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.
+ * @param a The coefficient <code>a</code> in the Weierstrass equation
+ * for non-supersingular elliptic curves over
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param b The coefficient <code>b</code> in the Weierstrass equation
+ * for non-supersingular elliptic curves over
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ */
+ public F2m(
+ int m,
+ int k1,
+ int k2,
+ int k3,
+ BigInteger a,
+ BigInteger b)
+ {
+ this(m, k1, k2, k3, a, b, null, null);
+ }
+
+ /**
+ * Constructor for Pentanomial Polynomial Basis (PPB).
+ * @param m The exponent <code>m</code> of
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.
+ * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.
+ * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.
+ * @param a The coefficient <code>a</code> in the Weierstrass equation
+ * for non-supersingular elliptic curves over
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param b The coefficient <code>b</code> in the Weierstrass equation
+ * for non-supersingular elliptic curves over
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param order The order of the main subgroup of the elliptic curve.
+ * @param cofactor The cofactor of the elliptic curve, i.e.
+ * <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>.
+ */
+ public F2m(
+ int m,
+ int k1,
+ int k2,
+ int k3,
+ BigInteger a,
+ BigInteger b,
+ BigInteger order,
+ BigInteger cofactor)
+ {
+ super(m, k1, k2, k3);
+
+ this.m = m;
+ this.k1 = k1;
+ this.k2 = k2;
+ this.k3 = k3;
+ this.order = order;
+ this.cofactor = cofactor;
+
+ 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 order, BigInteger cofactor)
+ {
+ super(m, k1, k2, k3);
+
+ this.m = m;
+ this.k1 = k1;
+ this.k2 = k2;
+ this.k3 = k3;
+ this.order = order;
+ this.cofactor = cofactor;
+
+ 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, order, cofactor);
+ }
+
+ 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()
+ {
+ return m;
+ }
+
+ public ECFieldElement fromBigInteger(BigInteger x)
+ {
+ return new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, x);
+ }
+
+ public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression)
+ {
+ ECFieldElement X = fromBigInteger(x), Y = fromBigInteger(y);
+
+ switch (this.getCoordinateSystem())
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ if (X.isZero())
+ {
+ if (!Y.square().equals(this.getB()))
+ {
+ throw new IllegalArgumentException();
+ }
+ }
+ else
+ {
+ // Y becomes Lambda (X + Y/X) here
+ Y = Y.divide(X).add(X);
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ return createRawPoint(X, Y, withCompression);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ return new ECPoint.F2m(this, x, y, withCompression);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ return new ECPoint.F2m(this, x, y, zs, withCompression);
+ }
+
+ public ECPoint getInfinity()
+ {
+ return infinity;
+ }
+
+ /**
+ * Returns true if this is a Koblitz curve (ABC curve).
+ * @return true if this is a Koblitz curve (ABC curve), false otherwise
+ */
+ public boolean isKoblitz()
+ {
+ return order != null && cofactor != null && b.isOne() && (a.isZero() || a.isOne());
+ }
+
+ /**
+ * Returns the parameter <code>&mu;</code> of the elliptic curve.
+ * @return <code>&mu;</code> of the elliptic curve.
+ * @throws IllegalArgumentException if the given ECCurve is not a
+ * Koblitz curve.
+ */
+ synchronized byte getMu()
+ {
+ if (mu == 0)
+ {
+ mu = Tnaf.getMu(this);
+ }
+ return mu;
+ }
+
+ /**
+ * @return the auxiliary values <code>s<sub>0</sub></code> and
+ * <code>s<sub>1</sub></code> used for partial modular reduction for
+ * Koblitz curves.
+ */
+ synchronized BigInteger[] getSi()
+ {
+ if (si == null)
+ {
+ si = Tnaf.getSi(this);
+ }
+ return si;
+ }
+
+ /**
+ * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
+ *
+ * @param yTilde
+ * ~yp, an indication bit for the decompression of yp.
+ * @param X1
+ * The field element xp.
+ * @return the decompressed point.
+ */
+ protected ECPoint decompressPoint(int yTilde, BigInteger X1)
+ {
+ ECFieldElement x = fromBigInteger(X1), y = null;
+ if (x.isZero())
+ {
+ y = b.sqrt();
+ }
+ else
+ {
+ ECFieldElement beta = x.square().invert().multiply(b).add(a).add(x);
+ ECFieldElement z = solveQuadraticEquation(beta);
+ if (z != null)
+ {
+ if (z.testBitZero() != (yTilde == 1))
+ {
+ z = z.addOne();
+ }
+
+ switch (this.getCoordinateSystem())
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ y = z.add(x);
+ break;
+ }
+ default:
+ {
+ y = z.multiply(x);
+ break;
+ }
+ }
+ }
+ }
+
+ if (y == null)
+ {
+ throw new IllegalArgumentException("Invalid point compression");
+ }
+
+ return this.createRawPoint(x, y, true);
+ }
+
+ /**
+ * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
+ * D.1.6) The other solution is <code>z + 1</code>.
+ *
+ * @param beta
+ * The value to solve the quadratic equation for.
+ * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+ * <code>null</code> if no solution exists.
+ */
+ private ECFieldElement solveQuadraticEquation(ECFieldElement beta)
+ {
+ if (beta.isZero())
+ {
+ return beta;
+ }
+
+ ECFieldElement zeroElement = fromBigInteger(ECConstants.ZERO);
+
+ ECFieldElement z = null;
+ ECFieldElement gamma = null;
+
+ Random rand = new Random();
+ do
+ {
+ ECFieldElement t = fromBigInteger(new BigInteger(m, rand));
+ z = zeroElement;
+ ECFieldElement w = beta;
+ for (int i = 1; i <= m - 1; i++)
+ {
+ ECFieldElement w2 = w.square();
+ z = z.square().add(w2.multiply(t));
+ w = w2.add(beta);
+ }
+ if (!w.isZero())
+ {
+ return null;
+ }
+ gamma = z.square().add(z);
+ }
+ while (gamma.isZero());
+
+ return z;
+ }
+
+ public int getM()
+ {
+ return m;
+ }
+
+ /**
+ * Return true if curve uses a Trinomial basis.
+ *
+ * @return true if curve Trinomial, false otherwise.
+ */
+ public boolean isTrinomial()
+ {
+ return k2 == 0 && k3 == 0;
+ }
+
+ public int getK1()
+ {
+ return k1;
+ }
+
+ public int getK2()
+ {
+ return k2;
+ }
+
+ public int getK3()
+ {
+ return k3;
+ }
+
+ /**
+ * @deprecated use {@link #getOrder()} instead
+ */
+ public BigInteger getN()
+ {
+ return order;
+ }
+
+ /**
+ * @deprecated use {@link #getCofactor()} instead
+ */
+ public BigInteger getH()
+ {
+ return cofactor;
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/ECFieldElement.java b/core/src/main/java/org/spongycastle/math/ec/ECFieldElement.java
new file mode 100644
index 00000000..f96b8e61
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/ECFieldElement.java
@@ -0,0 +1,868 @@
+package org.spongycastle.math.ec;
+
+import java.math.BigInteger;
+import java.util.Random;
+
+import org.spongycastle.math.raw.Mod;
+import org.spongycastle.math.raw.Nat;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.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);
+ public abstract ECFieldElement negate();
+ public abstract ECFieldElement square();
+ public abstract ECFieldElement invert();
+ public abstract ECFieldElement sqrt();
+
+ public int bitLength()
+ {
+ return toBigInteger().bitLength();
+ }
+
+ public boolean isOne()
+ {
+ return bitLength() == 1;
+ }
+
+ public boolean isZero()
+ {
+ return 0 == toBigInteger().signum();
+ }
+
+ public ECFieldElement multiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ return multiply(b).subtract(x.multiply(y));
+ }
+
+ public ECFieldElement multiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ return multiply(b).add(x.multiply(y));
+ }
+
+ public ECFieldElement squareMinusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ return square().subtract(x.multiply(y));
+ }
+
+ public ECFieldElement squarePlusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ return square().add(x.multiply(y));
+ }
+
+ public boolean testBitZero()
+ {
+ return toBigInteger().testBit(0);
+ }
+
+ public String toString()
+ {
+ return this.toBigInteger().toString(16);
+ }
+
+ public byte[] getEncoded()
+ {
+ return BigIntegers.asUnsignedByteArray((getFieldSize() + 7) / 8, toBigInteger());
+ }
+
+ public static class Fp extends ECFieldElement
+ {
+ BigInteger q, r, x;
+
+ static BigInteger calculateResidue(BigInteger p)
+ {
+ int bitLength = p.bitLength();
+ if (bitLength >= 96)
+ {
+ 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(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 invalid in Fp field element");
+ }
+
+ this.q = q;
+ this.r = r;
+ this.x = x;
+ }
+
+ public BigInteger toBigInteger()
+ {
+ return x;
+ }
+
+ /**
+ * return the field name for this field.
+ *
+ * @return the string "Fp".
+ */
+ public String getFieldName()
+ {
+ return "Fp";
+ }
+
+ public int getFieldSize()
+ {
+ return q.bitLength();
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public ECFieldElement add(ECFieldElement b)
+ {
+ return new Fp(q, 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, r, modSubtract(x, b.toBigInteger()));
+ }
+
+ public ECFieldElement multiply(ECFieldElement b)
+ {
+ return new Fp(q, r, modMult(x, b.toBigInteger()));
+ }
+
+ public ECFieldElement multiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ BigInteger ax = this.x, bx = b.toBigInteger(), xx = x.toBigInteger(), yx = y.toBigInteger();
+ BigInteger ab = ax.multiply(bx);
+ BigInteger xy = xx.multiply(yx);
+ return new Fp(q, r, modReduce(ab.subtract(xy)));
+ }
+
+ public ECFieldElement multiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ BigInteger ax = this.x, bx = b.toBigInteger(), xx = x.toBigInteger(), yx = y.toBigInteger();
+ BigInteger ab = ax.multiply(bx);
+ BigInteger xy = xx.multiply(yx);
+ return new Fp(q, r, modReduce(ab.add(xy)));
+ }
+
+ public ECFieldElement divide(ECFieldElement b)
+ {
+ return new Fp(q, r, modMult(x, modInverse(b.toBigInteger())));
+ }
+
+ public ECFieldElement negate()
+ {
+ return x.signum() == 0 ? this : new Fp(q, r, q.subtract(x));
+ }
+
+ public ECFieldElement square()
+ {
+ return new Fp(q, r, modMult(x, x));
+ }
+
+ public ECFieldElement squareMinusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ BigInteger ax = this.x, xx = x.toBigInteger(), yx = y.toBigInteger();
+ BigInteger aa = ax.multiply(ax);
+ BigInteger xy = xx.multiply(yx);
+ return new Fp(q, r, modReduce(aa.subtract(xy)));
+ }
+
+ public ECFieldElement squarePlusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ BigInteger ax = this.x, xx = x.toBigInteger(), yx = y.toBigInteger();
+ BigInteger aa = ax.multiply(ax);
+ BigInteger xy = xx.multiply(yx);
+ return new Fp(q, r, modReduce(aa.add(xy)));
+ }
+
+ public ECFieldElement invert()
+ {
+ // TODO Modular inversion can be faster for a (Generalized) Mersenne Prime.
+ return new Fp(q, r, modInverse(x));
+ }
+
+ // D.1.4 91
+ /**
+ * return a sqrt root - the routine verifies that the calculation
+ * returns the right value - if none exists it returns null.
+ */
+ public ECFieldElement sqrt()
+ {
+ if (this.isZero() || this.isOne()) // earlier JDK compatibility
+ {
+ return this;
+ }
+
+ if (!q.testBit(0))
+ {
+ throw new RuntimeException("not done yet");
+ }
+
+ // note: even though this class implements ECConstants don't be tempted to
+ // remove the explicit declaration, some J2ME environments don't cope.
+
+ if (q.testBit(1)) // q == 4m + 3
+ {
+ BigInteger e = q.shiftRight(2).add(ECConstants.ONE);
+ return checkSqrt(new Fp(q, r, x.modPow(e, q)));
+ }
+
+ if (q.testBit(2)) // q == 8m + 5
+ {
+ BigInteger t1 = x.modPow(q.shiftRight(3), q);
+ BigInteger t2 = modMult(t1, x);
+ BigInteger t3 = modMult(t2, t1);
+
+ if (t3.equals(ECConstants.ONE))
+ {
+ return checkSqrt(new Fp(q, r, t2));
+ }
+
+ // TODO This is constant and could be precomputed
+ BigInteger t4 = ECConstants.TWO.modPow(q.shiftRight(2), q);
+
+ BigInteger y = modMult(t2, t4);
+
+ return checkSqrt(new Fp(q, r, y));
+ }
+
+ // q == 8m + 1
+
+ BigInteger legendreExponent = q.shiftRight(1);
+ if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE)))
+ {
+ return null;
+ }
+
+ BigInteger X = this.x;
+ BigInteger fourX = modDouble(modDouble(X));
+
+ BigInteger k = legendreExponent.add(ECConstants.ONE), qMinusOne = q.subtract(ECConstants.ONE);
+
+ BigInteger U, V;
+ Random rand = new Random();
+ do
+ {
+ BigInteger P;
+ do
+ {
+ P = new BigInteger(q.bitLength(), rand);
+ }
+ while (P.compareTo(q) >= 0
+ || !modReduce(P.multiply(P).subtract(fourX)).modPow(legendreExponent, q).equals(qMinusOne));
+
+ BigInteger[] result = lucasSequence(P, X, k);
+ U = result[0];
+ V = result[1];
+
+ if (modMult(V, V).equals(fourX))
+ {
+ return new ECFieldElement.Fp(q, r, modHalfAbs(V));
+ }
+ }
+ while (U.equals(ECConstants.ONE) || U.equals(qMinusOne));
+
+ return null;
+ }
+
+ private ECFieldElement checkSqrt(ECFieldElement z)
+ {
+ return z.square().equals(this) ? z : null;
+ }
+
+ private BigInteger[] lucasSequence(
+ BigInteger P,
+ BigInteger Q,
+ BigInteger k)
+ {
+ // TODO Research and apply "common-multiplicand multiplication here"
+
+ int n = k.bitLength();
+ int s = k.getLowestSetBit();
+
+ // assert k.testBit(s);
+
+ BigInteger Uh = ECConstants.ONE;
+ BigInteger Vl = ECConstants.TWO;
+ BigInteger Vh = P;
+ BigInteger Ql = ECConstants.ONE;
+ BigInteger Qh = ECConstants.ONE;
+
+ for (int j = n - 1; j >= s + 1; --j)
+ {
+ Ql = modMult(Ql, Qh);
+
+ if (k.testBit(j))
+ {
+ 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 = 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 = 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 = 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 modHalf(BigInteger x)
+ {
+ if (x.testBit(0))
+ {
+ x = q.add(x);
+ }
+ return x.shiftRight(1);
+ }
+
+ protected BigInteger modHalfAbs(BigInteger x)
+ {
+ if (x.testBit(0))
+ {
+ x = q.subtract(x);
+ }
+ return x.shiftRight(1);
+ }
+
+ protected BigInteger modInverse(BigInteger x)
+ {
+ int bits = getFieldSize();
+ int len = (bits + 31) >> 5;
+ int[] p = Nat.fromBigInteger(bits, q);
+ int[] n = Nat.fromBigInteger(bits, x);
+ int[] z = Nat.create(len);
+ Mod.invert(p, n, z);
+ return Nat.toBigInteger(len, z);
+ }
+
+ protected BigInteger modMult(BigInteger x1, BigInteger x2)
+ {
+ return modReduce(x1.multiply(x2));
+ }
+
+ protected BigInteger modReduce(BigInteger x)
+ {
+ if (r != null)
+ {
+ boolean negative = x.signum() < 0;
+ if (negative)
+ {
+ x = x.abs();
+ }
+ int qLen = q.bitLength();
+ boolean rIsOne = r.equals(ECConstants.ONE);
+ while (x.bitLength() > (qLen + 1))
+ {
+ BigInteger u = x.shiftRight(qLen);
+ BigInteger v = x.subtract(u.shiftLeft(qLen));
+ if (!rIsOne)
+ {
+ u = u.multiply(r);
+ }
+ x = u.add(v);
+ }
+ while (x.compareTo(q) >= 0)
+ {
+ x = x.subtract(q);
+ }
+ if (negative && x.signum() != 0)
+ {
+ x = q.subtract(x);
+ }
+ }
+ else
+ {
+ x = x.mod(q);
+ }
+ return x;
+ }
+
+ protected BigInteger modSubtract(BigInteger x1, BigInteger x2)
+ {
+ BigInteger x3 = x1.subtract(x2);
+ if (x3.signum() < 0)
+ {
+ x3 = x3.add(q);
+ }
+ return x3;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other == this)
+ {
+ return true;
+ }
+
+ if (!(other instanceof ECFieldElement.Fp))
+ {
+ return false;
+ }
+
+ ECFieldElement.Fp o = (ECFieldElement.Fp)other;
+ return q.equals(o.q) && x.equals(o.x);
+ }
+
+ public int hashCode()
+ {
+ return q.hashCode() ^ x.hashCode();
+ }
+ }
+
+ /**
+ * Class representing the Elements of the finite field
+ * <code>F<sub>2<sup>m</sup></sub></code> in polynomial basis (PB)
+ * representation. Both trinomial (TPB) and pentanomial (PPB) polynomial
+ * basis representations are supported. Gaussian normal basis (GNB)
+ * representation is not supported.
+ */
+ public static class F2m extends ECFieldElement
+ {
+ /**
+ * Indicates gaussian normal basis representation (GNB). Number chosen
+ * according to X9.62. GNB is not implemented at present.
+ */
+ public static final int GNB = 1;
+
+ /**
+ * Indicates trinomial basis representation (TPB). Number chosen
+ * according to X9.62.
+ */
+ public static final int TPB = 2;
+
+ /**
+ * Indicates pentanomial basis representation (PPB). Number chosen
+ * according to X9.62.
+ */
+ public static final int PPB = 3;
+
+ /**
+ * TPB or PPB.
+ */
+ private int representation;
+
+ /**
+ * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
+ */
+ private int m;
+
+ private int[] ks;
+
+ /**
+ * The <code>LongArray</code> holding the bits.
+ */
+ private LongArray x;
+
+ /**
+ * Constructor for PPB.
+ * @param m The exponent <code>m</code> of
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.
+ * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.
+ * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.
+ * @param x The BigInteger representing the value of the field element.
+ * @deprecated Use ECCurve.fromBigInteger to construct field elements
+ */
+ public F2m(
+ int m,
+ int k1,
+ int k2,
+ int k3,
+ BigInteger x)
+ {
+ if ((k2 == 0) && (k3 == 0))
+ {
+ this.representation = TPB;
+ this.ks = new int[]{ k1 };
+ }
+ else
+ {
+ if (k2 >= k3)
+ {
+ throw new IllegalArgumentException(
+ "k2 must be smaller than k3");
+ }
+ if (k2 <= 0)
+ {
+ throw new IllegalArgumentException(
+ "k2 must be larger than 0");
+ }
+ this.representation = PPB;
+ this.ks = new int[]{ k1, k2, k3 };
+ }
+
+ this.m = m;
+ this.x = new LongArray(x);
+ }
+
+ /**
+ * Constructor for TPB.
+ * @param m The exponent <code>m</code> of
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
+ * x<sup>k</sup> + 1</code> represents the reduction
+ * polynomial <code>f(z)</code>.
+ * @param x The BigInteger representing the value of the field element.
+ * @deprecated Use ECCurve.fromBigInteger to construct field elements
+ */
+ public F2m(int m, int k, BigInteger x)
+ {
+ // Set k1 to k, and set k2 and k3 to 0
+ this(m, k, 0, 0, x);
+ }
+
+ private F2m(int m, int[] ks, LongArray x)
+ {
+ this.m = m;
+ this.representation = (ks.length == 1) ? TPB : PPB;
+ this.ks = ks;
+ this.x = x;
+ }
+
+ public int bitLength()
+ {
+ return x.degree();
+ }
+
+ public boolean isOne()
+ {
+ return x.isOne();
+ }
+
+ public boolean isZero()
+ {
+ return x.isZero();
+ }
+
+ public boolean testBitZero()
+ {
+ return x.testBitZero();
+ }
+
+ public BigInteger toBigInteger()
+ {
+ return x.toBigInteger();
+ }
+
+ public String getFieldName()
+ {
+ return "F2m";
+ }
+
+ public int getFieldSize()
+ {
+ return m;
+ }
+
+ /**
+ * Checks, if the ECFieldElements <code>a</code> and <code>b</code>
+ * are elements of the same field <code>F<sub>2<sup>m</sup></sub></code>
+ * (having the same representation).
+ * @param a field element.
+ * @param b field element to be compared.
+ * @throws IllegalArgumentException if <code>a</code> and <code>b</code>
+ * are not elements of the same field
+ * <code>F<sub>2<sup>m</sup></sub></code> (having the same
+ * representation).
+ */
+ public static void checkFieldElements(
+ ECFieldElement a,
+ ECFieldElement b)
+ {
+ if ((!(a instanceof F2m)) || (!(b instanceof F2m)))
+ {
+ throw new IllegalArgumentException("Field elements are not "
+ + "both instances of ECFieldElement.F2m");
+ }
+
+ ECFieldElement.F2m aF2m = (ECFieldElement.F2m)a;
+ ECFieldElement.F2m bF2m = (ECFieldElement.F2m)b;
+
+ if (aF2m.representation != bF2m.representation)
+ {
+ // Should never occur
+ throw new IllegalArgumentException("One of the F2m field elements has incorrect representation");
+ }
+
+ if ((aF2m.m != bF2m.m) || !Arrays.areEqual(aF2m.ks, bF2m.ks))
+ {
+ throw new IllegalArgumentException("Field elements are not elements of the same field F2m");
+ }
+ }
+
+ public ECFieldElement add(final ECFieldElement b)
+ {
+ // No check performed here for performance reasons. Instead the
+ // elements involved are checked in ECPoint.F2m
+ // checkFieldElements(this, b);
+ LongArray iarrClone = (LongArray)this.x.clone();
+ F2m bF2m = (F2m)b;
+ 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)
+ {
+ // Addition and subtraction are the same in F2m
+ return add(b);
+ }
+
+ public ECFieldElement multiply(final ECFieldElement b)
+ {
+ // 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);
+ return new F2m(m, ks, x.modMultiply(((F2m)b).x, m, ks));
+ }
+
+ public ECFieldElement multiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ return multiplyPlusProduct(b, x, y);
+ }
+
+ public ECFieldElement multiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ LongArray ax = this.x, bx = ((F2m)b).x, xx = ((F2m)x).x, yx = ((F2m)y).x;
+
+ LongArray ab = ax.multiply(bx, m, ks);
+ LongArray xy = xx.multiply(yx, m, ks);
+
+ if (ab == ax || ab == bx)
+ {
+ ab = (LongArray)ab.clone();
+ }
+
+ ab.addShiftedByWords(xy, 0);
+ ab.reduce(m, ks);
+
+ return new F2m(m, ks, ab);
+ }
+
+ public ECFieldElement divide(final ECFieldElement b)
+ {
+ // There may be more efficient implementations
+ ECFieldElement bInv = b.invert();
+ return multiply(bInv);
+ }
+
+ public ECFieldElement negate()
+ {
+ // -x == x holds for all x in F2m
+ return this;
+ }
+
+ public ECFieldElement square()
+ {
+ return new F2m(m, ks, x.modSquare(m, ks));
+ }
+
+ public ECFieldElement squareMinusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ return squarePlusProduct(x, y);
+ }
+
+ public ECFieldElement squarePlusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ LongArray ax = this.x, xx = ((F2m)x).x, yx = ((F2m)y).x;
+
+ LongArray aa = ax.square(m, ks);
+ LongArray xy = xx.multiply(yx, m, ks);
+
+ if (aa == ax)
+ {
+ aa = (LongArray)aa.clone();
+ }
+
+ aa.addShiftedByWords(xy, 0);
+ aa.reduce(m, ks);
+
+ return new F2m(m, ks, aa);
+ }
+
+ public ECFieldElement invert()
+ {
+ return new ECFieldElement.F2m(this.m, this.ks, this.x.modInverse(m, ks));
+ }
+
+ public ECFieldElement sqrt()
+ {
+ LongArray x1 = this.x;
+ if (x1.isOne() || x1.isZero())
+ {
+ return this;
+ }
+
+ LongArray x2 = x1.modSquareN(m - 1, m, ks);
+ return new ECFieldElement.F2m(m, ks, x2);
+ }
+
+ /**
+ * @return the representation of the field
+ * <code>F<sub>2<sup>m</sup></sub></code>, either of
+ * TPB (trinomial
+ * basis representation) or
+ * PPB (pentanomial
+ * basis representation).
+ */
+ public int getRepresentation()
+ {
+ return this.representation;
+ }
+
+ /**
+ * @return the degree <code>m</code> of the reduction polynomial
+ * <code>f(z)</code>.
+ */
+ public int getM()
+ {
+ return this.m;
+ }
+
+ /**
+ * @return TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
+ * x<sup>k</sup> + 1</code> represents the reduction polynomial
+ * <code>f(z)</code>.<br>
+ * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.<br>
+ */
+ public int getK1()
+ {
+ return this.ks[0];
+ }
+
+ /**
+ * @return TPB: Always returns <code>0</code><br>
+ * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.<br>
+ */
+ public int getK2()
+ {
+ return this.ks.length >= 2 ? this.ks[1] : 0;
+ }
+
+ /**
+ * @return TPB: Always set to <code>0</code><br>
+ * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.<br>
+ */
+ public int getK3()
+ {
+ return this.ks.length >= 3 ? this.ks[2] : 0;
+ }
+
+ public boolean equals(Object anObject)
+ {
+ if (anObject == this)
+ {
+ return true;
+ }
+
+ if (!(anObject instanceof ECFieldElement.F2m))
+ {
+ return false;
+ }
+
+ ECFieldElement.F2m b = (ECFieldElement.F2m)anObject;
+
+ return ((this.m == b.m)
+ && (this.representation == b.representation)
+ && Arrays.areEqual(this.ks, b.ks)
+ && (this.x.equals(b.x)));
+ }
+
+ public int hashCode()
+ {
+ return x.hashCode() ^ m ^ Arrays.hashCode(ks);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/ECMultiplier.java b/core/src/main/java/org/spongycastle/math/ec/ECMultiplier.java
new file mode 100644
index 00000000..17205e63
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/ECMultiplier.java
@@ -0,0 +1,19 @@
+package org.spongycastle.math.ec;
+
+import java.math.BigInteger;
+
+/**
+ * Interface for classes encapsulating a point multiplication algorithm
+ * for <code>ECPoint</code>s.
+ */
+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> is multiplied.
+ * @return <code>p</code> multiplied by <code>k</code>.
+ */
+ ECPoint multiply(ECPoint p, BigInteger k);
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/ECPoint.java b/core/src/main/java/org/spongycastle/math/ec/ECPoint.java
new file mode 100644
index 00000000..d5783ada
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/ECPoint.java
@@ -0,0 +1,2122 @@
+package org.spongycastle.math.ec;
+
+import java.math.BigInteger;
+import java.util.Hashtable;
+
+/**
+ * base class for points on elliptic curves.
+ */
+public abstract class ECPoint
+{
+ protected static ECFieldElement[] EMPTY_ZS = new ECFieldElement[0];
+
+ protected static ECFieldElement[] getInitialZCoords(ECCurve curve)
+ {
+ // Cope with null curve, most commonly used by implicitlyCa
+ int coord = null == curve ? ECCurve.COORD_AFFINE : curve.getCoordinateSystem();
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ return EMPTY_ZS;
+ default:
+ break;
+ }
+
+ ECFieldElement one = curve.fromBigInteger(ECConstants.ONE);
+
+ 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;
+
+ // Hashtable is (String -> PreCompInfo)
+ protected Hashtable preCompTable = 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;
+ }
+
+ protected boolean satisfiesCofactor()
+ {
+ BigInteger h = curve.getCofactor();
+ return h == null || h.equals(ECConstants.ONE) || !ECAlgorithms.referenceMultiply(this, h).isInfinity();
+ }
+
+ protected abstract boolean satisfiesCurveEquation();
+
+ public final ECPoint getDetachedPoint()
+ {
+ return normalize().detach();
+ }
+
+ public ECCurve getCurve()
+ {
+ return curve;
+ }
+
+ protected abstract ECPoint detach();
+
+ protected int getCurveCoordinateSystem()
+ {
+ // Cope with null curve, most commonly used by implicitlyCa
+ 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 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 final ECFieldElement getRawXCoord()
+ {
+ return x;
+ }
+
+ protected final ECFieldElement getRawYCoord()
+ {
+ return y;
+ }
+
+ protected final ECFieldElement[] getRawZCoords()
+ {
+ return zs;
+ }
+
+ 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].isOne();
+ }
+
+ /**
+ * 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.isOne())
+ {
+ 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 || (zs.length > 0 && zs[0].isZero());
+ }
+
+ public boolean isCompressed()
+ {
+ return this.withCompression;
+ }
+
+ public boolean isValid()
+ {
+ if (isInfinity())
+ {
+ return true;
+ }
+
+ // TODO Sanity-check the field elements
+
+ ECCurve curve = getCurve();
+ if (curve != null)
+ {
+ if (!satisfiesCurveEquation())
+ {
+ return false;
+ }
+
+ if (!satisfiesCofactor())
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public ECPoint scaleX(ECFieldElement scale)
+ {
+ return isInfinity()
+ ? this
+ : getCurve().createRawPoint(getRawXCoord().multiply(scale), getRawYCoord(), getRawZCoords(), this.withCompression);
+ }
+
+ public ECPoint scaleY(ECFieldElement scale)
+ {
+ return isInfinity()
+ ? this
+ : getCurve().createRawPoint(getRawXCoord(), getRawYCoord().multiply(scale), getRawZCoords(), this.withCompression);
+ }
+
+ public boolean equals(ECPoint other)
+ {
+ if (null == other)
+ {
+ 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)
+ {
+ if (other == this)
+ {
+ return true;
+ }
+
+ if (!(other instanceof ECPoint))
+ {
+ return false;
+ }
+
+ return equals((ECPoint)other);
+ }
+
+ public int hashCode()
+ {
+ ECCurve c = this.getCurve();
+ int hc = (null == c) ? 0 : ~c.hashCode();
+
+ if (!this.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 hc;
+ }
+
+ public String toString()
+ {
+ if (this.isInfinity())
+ {
+ return "INF";
+ }
+
+ 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();
+ }
+
+ public byte[] getEncoded()
+ {
+ return getEncoded(this.withCompression);
+ }
+
+ /**
+ * return the field element encoded with point compression. (S 4.3.6)
+ */
+ public byte[] getEncoded(boolean compressed)
+ {
+ if (this.isInfinity())
+ {
+ return new byte[1];
+ }
+
+ 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;
+ }
+
+ protected abstract boolean getCompressionYTilde();
+
+ public abstract ECPoint add(ECPoint b);
+
+ public abstract ECPoint negate();
+
+ public abstract ECPoint subtract(ECPoint b);
+
+ public ECPoint timesPow2(int e)
+ {
+ if (e < 0)
+ {
+ throw new IllegalArgumentException("'e' cannot be negative");
+ }
+
+ ECPoint p = this;
+ while (--e >= 0)
+ {
+ p = p.twice();
+ }
+ return p;
+ }
+
+ public abstract ECPoint twice();
+
+ public ECPoint twicePlus(ECPoint b)
+ {
+ return twice().add(b);
+ }
+
+ public ECPoint threeTimes()
+ {
+ return twicePlus(this);
+ }
+
+ /**
+ * Multiplies this <code>ECPoint</code> by the given number.
+ * @param k The multiplicator.
+ * @return <code>k * this</code>.
+ */
+ public ECPoint multiply(BigInteger k)
+ {
+ return this.getCurve().getMultiplier().multiply(this, k);
+ }
+
+ public static abstract class AbstractFp extends ECPoint
+ {
+ protected AbstractFp(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ super(curve, x, y);
+ }
+
+ protected AbstractFp(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs)
+ {
+ super(curve, x, y, zs);
+ }
+
+ protected boolean getCompressionYTilde()
+ {
+ return this.getAffineYCoord().testBitZero();
+ }
+
+ protected boolean satisfiesCurveEquation()
+ {
+ ECFieldElement X = this.x, Y = this.y, A = curve.getA(), B = curve.getB();
+ ECFieldElement lhs = Y.square();
+
+ switch (this.getCurveCoordinateSystem())
+ {
+ case ECCurve.COORD_AFFINE:
+ break;
+ case ECCurve.COORD_HOMOGENEOUS:
+ {
+ ECFieldElement Z = this.zs[0];
+ if (!Z.isOne())
+ {
+ ECFieldElement Z2 = Z.square(), Z3 = Z.multiply(Z2);
+ lhs = lhs.multiply(Z);
+ A = A.multiply(Z2);
+ B = B.multiply(Z3);
+ }
+ break;
+ }
+ case ECCurve.COORD_JACOBIAN:
+ case ECCurve.COORD_JACOBIAN_CHUDNOVSKY:
+ case ECCurve.COORD_JACOBIAN_MODIFIED:
+ {
+ ECFieldElement Z = this.zs[0];
+ if (!Z.isOne())
+ {
+ ECFieldElement Z2 = Z.square(), Z4 = Z2.square(), Z6 = Z2.multiply(Z4);
+ A = A.multiply(Z4);
+ B = B.multiply(Z6);
+ }
+ break;
+ }
+ default:
+ throw new IllegalStateException("unsupported coordinate system");
+ }
+
+ ECFieldElement rhs = X.square().add(A).multiply(X).add(B);
+ return lhs.equals(rhs);
+ }
+
+ public ECPoint subtract(ECPoint b)
+ {
+ if (b.isInfinity())
+ {
+ return this;
+ }
+
+ // Add -b
+ return this.add(b.negate());
+ }
+ }
+
+ /**
+ * Elliptic curve points over Fp
+ */
+ public static class Fp extends AbstractFp
+ {
+ /**
+ * Create a point which encodes without point compression.
+ *
+ * @param curve the curve to use
+ * @param x affine x co-ordinate
+ * @param y affine y co-ordinate
+ *
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ this(curve, x, y, false);
+ }
+
+ /**
+ * Create a point that encodes with or without point compression.
+ *
+ * @param curve the curve to use
+ * @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)
+ {
+ super(curve, x, y);
+
+ if ((x == null) != (y == null))
+ {
+ throw new IllegalArgumentException("Exactly one of the field elements is null");
+ }
+
+ this.withCompression = withCompression;
+ }
+
+ Fp(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ super(curve, x, y, zs);
+
+ this.withCompression = withCompression;
+ }
+
+ protected ECPoint detach()
+ {
+ return new ECPoint.Fp(null, this.getAffineXCoord(), this.getAffineYCoord());
+ }
+
+ public ECFieldElement getZCoord(int index)
+ {
+ if (index == 1 && ECCurve.COORD_JACOBIAN_MODIFIED == this.getCurveCoordinateSystem())
+ {
+ return getJacobianModifiedW();
+ }
+
+ return super.getZCoord(index);
+ }
+
+ // B.3 pg 62
+ public ECPoint add(ECPoint b)
+ {
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return this;
+ }
+ if (this == b)
+ {
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+ 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())
+ {
+ 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();
+ }
+
+ 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.isOne();
+ boolean Z2IsOne = Z2.isOne();
+
+ 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())
+ {
+ 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).multiplyMinusProduct(u, u2, vCubed);
+ 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.isOne();
+
+ 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.isOne();
+ 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();
+ }
+
+ ECFieldElement HSquared = H.square();
+ ECFieldElement G = HSquared.multiply(H);
+ ECFieldElement V = HSquared.multiply(U1);
+
+ X3 = R.square().add(G).subtract(two(V));
+ Y3 = V.subtract(X3).multiplyMinusProduct(R, G, S1);
+
+ 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);
+ }
+
+ 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:
+ {
+ ECFieldElement Z1 = this.zs[0];
+
+ boolean Z1IsOne = Z1.isOne();
+
+ // TODO Optimize for small negative a4 and -3
+ ECFieldElement w = curve.getA();
+ if (!w.isZero() && !Z1IsOne)
+ {
+ w = w.multiply(Z1.square());
+ }
+ w = w.add(three(X1.square()));
+
+ 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 _2s = two(s);
+ ECFieldElement X3 = h.multiply(_2s);
+ ECFieldElement _2t = two(t);
+ ECFieldElement Y3 = _4B.subtract(h).multiply(w).subtract(two(_2t.square()));
+ ECFieldElement _4sSquared = Z1IsOne ? two(_2t) : _2s.square();
+ ECFieldElement Z3 = two(_4sSquared).multiply(s);
+
+ return new ECPoint.Fp(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+
+ case ECCurve.COORD_JACOBIAN:
+ {
+ ECFieldElement Z1 = this.zs[0];
+
+ boolean Z1IsOne = Z1.isOne();
+
+ 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)))
+ {
+ ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.square();
+ 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 if (!a4.isZero())
+ {
+ ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.square();
+ 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));
+ S = four(X1.multiply(Y1Squared));
+ }
+
+ 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);
+ }
+
+ // 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");
+ }
+ }
+ }
+
+ public ECPoint twicePlus(ECPoint b)
+ {
+ if (this == b)
+ {
+ return threeTimes();
+ }
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return twice();
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return b;
+ }
+
+ ECCurve curve = this.getCurve();
+ int coord = curve.getCoordinateSystem();
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ {
+ ECFieldElement X1 = this.x;
+ ECFieldElement X2 = b.x, Y2 = b.y;
+
+ ECFieldElement dx = X2.subtract(X1), dy = Y2.subtract(Y1);
+
+ if (dx.isZero())
+ {
+ if (dy.isZero())
+ {
+ // this == b i.e. the result is 3P
+ return threeTimes();
+ }
+
+ // this == -b, i.e. the result is P
+ return this;
+ }
+
+ /*
+ * Optimized calculation of 2P + Q, as described in "Trading Inversions for
+ * Multiplications in Elliptic Curve Cryptography", by Ciet, Joye, Lauter, Montgomery.
+ */
+
+ ECFieldElement X = dx.square(), Y = dy.square();
+ ECFieldElement d = X.multiply(two(X1).add(X2)).subtract(Y);
+ if (d.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ 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, X4, Y4, this.withCompression);
+ }
+ case ECCurve.COORD_JACOBIAN_MODIFIED:
+ {
+ return twiceJacobianModified(false).add(b);
+ }
+ default:
+ {
+ return twice().add(b);
+ }
+ }
+ }
+
+ public ECPoint threeTimes()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+ int coord = curve.getCoordinateSystem();
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ {
+ ECFieldElement X1 = this.x;
+
+ 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);
+ }
+ }
+ }
+
+ public ECPoint timesPow2(int e)
+ {
+ if (e < 0)
+ {
+ throw new IllegalArgumentException("'e' cannot be negative");
+ }
+ if (e == 0 || this.isInfinity())
+ {
+ return this;
+ }
+ if (e == 1)
+ {
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ int coord = curve.getCoordinateSystem();
+
+ ECFieldElement W1 = curve.getA();
+ ECFieldElement X1 = this.x;
+ ECFieldElement Z1 = this.zs.length < 1 ? curve.fromBigInteger(ECConstants.ONE) : this.zs[0];
+
+ if (!Z1.isOne())
+ {
+ switch (coord)
+ {
+ case ECCurve.COORD_HOMOGENEOUS:
+ ECFieldElement Z1Sq = Z1.square();
+ X1 = X1.multiply(Z1);
+ Y1 = Y1.multiply(Z1Sq);
+ W1 = calculateJacobianModifiedW(Z1, Z1Sq);
+ break;
+ case ECCurve.COORD_JACOBIAN:
+ W1 = calculateJacobianModifiedW(Z1, null);
+ break;
+ case ECCurve.COORD_JACOBIAN_MODIFIED:
+ W1 = getJacobianModifiedW();
+ break;
+ }
+ }
+
+ for (int i = 0; i < e; ++i)
+ {
+ if (Y1.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ ECFieldElement X1Squared = X1.square();
+ ECFieldElement M = three(X1Squared);
+ ECFieldElement _2Y1 = two(Y1);
+ ECFieldElement _2Y1Squared = _2Y1.multiply(Y1);
+ ECFieldElement S = two(X1.multiply(_2Y1Squared));
+ ECFieldElement _4T = _2Y1Squared.square();
+ ECFieldElement _8T = two(_4T);
+
+ if (!W1.isZero())
+ {
+ M = M.add(W1);
+ W1 = two(_8T.multiply(W1));
+ }
+
+ X1 = M.square().subtract(two(S));
+ Y1 = M.multiply(S.subtract(X1)).subtract(_8T);
+ Z1 = Z1.isOne() ? _2Y1 : _2Y1.multiply(Z1);
+ }
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ ECFieldElement zInv = Z1.invert(), zInv2 = zInv.square(), zInv3 = zInv2.multiply(zInv);
+ return new Fp(curve, X1.multiply(zInv2), Y1.multiply(zInv3), this.withCompression);
+ case ECCurve.COORD_HOMOGENEOUS:
+ X1 = X1.multiply(Z1);
+ Z1 = Z1.multiply(Z1.square());
+ return new Fp(curve, X1, Y1, new ECFieldElement[]{ Z1 }, this.withCompression);
+ case ECCurve.COORD_JACOBIAN:
+ return new Fp(curve, X1, Y1, new ECFieldElement[]{ Z1 }, this.withCompression);
+ case ECCurve.COORD_JACOBIAN_MODIFIED:
+ return new Fp(curve, X1, Y1, new ECFieldElement[]{ Z1, W1 }, this.withCompression);
+ default:
+ throw new IllegalStateException("unsupported coordinate system");
+ }
+ }
+
+ protected ECFieldElement two(ECFieldElement x)
+ {
+ return x.add(x);
+ }
+
+ protected ECFieldElement three(ECFieldElement x)
+ {
+ return two(x).add(x);
+ }
+
+ protected ECFieldElement four(ECFieldElement x)
+ {
+ return two(two(x));
+ }
+
+ protected ECFieldElement eight(ECFieldElement x)
+ {
+ return four(two(x));
+ }
+
+ protected ECFieldElement doubleProductFromSquares(ECFieldElement a, ECFieldElement b,
+ ECFieldElement aSquared, ECFieldElement bSquared)
+ {
+ /*
+ * NOTE: If squaring in the field is faster than multiplication, then this is a quicker
+ * way to calculate 2.A.B, if A^2 and B^2 are already known.
+ */
+ return a.add(b).square().subtract(aSquared).subtract(bSquared);
+ }
+
+ public ECPoint negate()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ 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);
+ }
+
+ protected ECFieldElement calculateJacobianModifiedW(ECFieldElement Z, ECFieldElement ZSquared)
+ {
+ ECFieldElement a4 = this.getCurve().getA();
+ if (a4.isZero() || Z.isOne())
+ {
+ return a4;
+ }
+
+ if (ZSquared == null)
+ {
+ ZSquared = Z.square();
+ }
+
+ ECFieldElement W = ZSquared.square();
+ ECFieldElement a4Neg = a4.negate();
+ if (a4Neg.bitLength() < a4.bitLength())
+ {
+ 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 _2Y1 = two(Y1);
+ ECFieldElement _2Y1Squared = _2Y1.multiply(Y1);
+ ECFieldElement S = two(X1.multiply(_2Y1Squared));
+ ECFieldElement X3 = M.square().subtract(two(S));
+ ECFieldElement _4T = _2Y1Squared.square();
+ ECFieldElement _8T = two(_4T);
+ ECFieldElement Y3 = M.multiply(S.subtract(X3)).subtract(_8T);
+ ECFieldElement W3 = calculateW ? two(_8T.multiply(W1)) : null;
+ ECFieldElement Z3 = Z1.isOne() ? _2Y1 : _2Y1.multiply(Z1);
+
+ return new ECPoint.Fp(this.getCurve(), X3, Y3, new ECFieldElement[]{ Z3, W3 }, this.withCompression);
+ }
+ }
+
+ public static abstract class AbstractF2m extends ECPoint
+ {
+ protected AbstractF2m(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ super(curve, x, y);
+ }
+
+ protected AbstractF2m(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs)
+ {
+ super(curve, x, y, zs);
+ }
+
+ protected boolean satisfiesCurveEquation()
+ {
+ ECCurve curve = this.getCurve();
+ ECFieldElement X = this.x, A = curve.getA(), B = curve.getB();
+
+ int coord = curve.getCoordinateSystem();
+ if (coord == ECCurve.COORD_LAMBDA_PROJECTIVE)
+ {
+ ECFieldElement Z = this.zs[0];
+ boolean ZIsOne = Z.isOne();
+
+ if (X.isZero())
+ {
+ // NOTE: For x == 0, we expect the affine-y instead of the lambda-y
+ ECFieldElement Y = this.y;
+ ECFieldElement lhs = Y.square(), rhs = B;
+ if (!ZIsOne)
+ {
+ rhs = rhs.multiply(Z.square());
+ }
+ return lhs.equals(rhs);
+ }
+
+ ECFieldElement L = this.y, X2 = X.square();
+ ECFieldElement lhs, rhs;
+ if (ZIsOne)
+ {
+ lhs = L.square().add(L).add(A);
+ rhs = X2.square().add(B);
+ }
+ else
+ {
+ ECFieldElement Z2 = Z.square(), Z4 = Z2.square();
+ lhs = L.add(Z).multiplyPlusProduct(L, A, Z2);
+ // TODO If sqrt(b) is precomputed this can be simplified to a single square
+ rhs = X2.squarePlusProduct(B, Z4);
+ }
+ lhs = lhs.multiply(X2);
+ return lhs.equals(rhs);
+ }
+
+ ECFieldElement Y = this.y;
+ ECFieldElement lhs = Y.add(X).multiply(Y);
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ break;
+ case ECCurve.COORD_HOMOGENEOUS:
+ {
+ ECFieldElement Z = this.zs[0];
+ if (!Z.isOne())
+ {
+ ECFieldElement Z2 = Z.square(), Z3 = Z.multiply(Z2);
+ lhs = lhs.multiply(Z);
+ A = A.multiply(Z);
+ B = B.multiply(Z3);
+ }
+ break;
+ }
+ default:
+ throw new IllegalStateException("unsupported coordinate system");
+ }
+
+ ECFieldElement rhs = X.add(A).multiply(X.square()).add(B);
+ return lhs.equals(rhs);
+ }
+ }
+
+ /**
+ * Elliptic curve points over F2m
+ */
+ public static class F2m extends AbstractF2m
+ {
+ /**
+ * @param curve base curve
+ * @param x x point
+ * @param y y point
+ *
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ this(curve, x, y, false);
+ }
+
+ /**
+ * @param curve base curve
+ * @param x x point
+ * @param y y point
+ * @param withCompression true if encode with point compression.
+ *
+ * @deprecated per-point compression property will be removed, refer {@link #getEncoded(boolean)}
+ */
+ public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ super(curve, x, y);
+
+ if ((x == null) != (y == null))
+ {
+ throw new IllegalArgumentException("Exactly one of the field elements is null");
+ }
+
+ 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();
+ }
+
+ F2m(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ super(curve, x, y, zs);
+
+ this.withCompression = withCompression;
+
+// checkCurveEquation();
+ }
+
+ protected ECPoint detach()
+ {
+ return new ECPoint.F2m(null, this.getAffineXCoord(), this.getAffineYCoord()); // earlier JDK
+ }
+
+ public ECFieldElement getYCoord()
+ {
+ int coord = this.getCurveCoordinateSystem();
+
+ switch (coord)
+ {
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ ECFieldElement X = x, L = y;
+
+ if (this.isInfinity() || X.isZero())
+ {
+ return L;
+ }
+
+ // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
+ ECFieldElement Y = L.add(X).multiply(X);
+ if (ECCurve.COORD_LAMBDA_PROJECTIVE == coord)
+ {
+ ECFieldElement Z = zs[0];
+ if (!Z.isOne())
+ {
+ Y = Y.divide(Z);
+ }
+ }
+ return Y;
+ }
+ default:
+ {
+ return y;
+ }
+ }
+ }
+
+ public ECPoint scaleX(ECFieldElement scale)
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ int coord = this.getCurveCoordinateSystem();
+
+ switch (coord)
+ {
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ {
+ // Y is actually Lambda (X + Y/X) here
+ ECFieldElement X = this.getRawXCoord(), L = this.getRawYCoord(); // earlier JDK
+
+ ECFieldElement X2 = X.multiply(scale);
+ ECFieldElement L2 = L.add(X).divide(scale).add(X2);
+
+ return this.getCurve().createRawPoint(X, L2, this.getRawZCoords(), this.withCompression); // earlier JDK
+ }
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ // Y is actually Lambda (X + Y/X) here
+ ECFieldElement X = this.getRawXCoord(), L = this.getRawYCoord(), Z = this.getRawZCoords()[0]; // earlier JDK
+
+ // We scale the Z coordinate also, to avoid an inversion
+ ECFieldElement X2 = X.multiply(scale.square());
+ ECFieldElement L2 = L.add(X).add(X2);
+ ECFieldElement Z2 = Z.multiply(scale);
+
+ return this.getCurve().createRawPoint(X2, L2, new ECFieldElement[]{ Z2 }, this.withCompression); // earlier JDK
+ }
+ default:
+ {
+ return super.scaleX(scale);
+ }
+ }
+ }
+
+ public ECPoint scaleY(ECFieldElement scale)
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ int coord = this.getCurveCoordinateSystem();
+
+ switch (coord)
+ {
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ ECFieldElement X = this.getRawXCoord(), L = this.getRawYCoord(); // earlier JDK
+
+ // Y is actually Lambda (X + Y/X) here
+ ECFieldElement L2 = L.add(X).multiply(scale).add(X);
+
+ return this.getCurve().createRawPoint(X, L2, this.getRawZCoords(), this.withCompression); // earlier JDK
+ }
+ default:
+ {
+ return super.scaleY(scale);
+ }
+ }
+ }
+
+ protected boolean getCompressionYTilde()
+ {
+ ECFieldElement X = this.getRawXCoord();
+ if (X.isZero())
+ {
+ return false;
+ }
+
+ 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.testBitZero() != X.testBitZero();
+ }
+ default:
+ {
+ return Y.divide(X).testBitZero();
+ }
+ }
+ }
+
+ /**
+ * Check, if two <code>ECPoint</code>s can be added or subtracted.
+ * @param a The first <code>ECPoint</code> to check.
+ * @param b The second <code>ECPoint</code> to check.
+ * @throws IllegalArgumentException if <code>a</code> and <code>b</code>
+ * cannot be added.
+ */
+ private static void checkPoints(ECPoint a, ECPoint b)
+ {
+ // Check, if points are on the same curve
+ if (a.curve != b.curve)
+ {
+ throw new IllegalArgumentException("Only points on the same "
+ + "curve can be added or subtracted");
+ }
+
+// ECFieldElement.F2m.checkFieldElements(a.x, b.x);
+ }
+
+ /* (non-Javadoc)
+ * @see org.spongycastle.math.ec.ECPoint#add(org.spongycastle.math.ec.ECPoint)
+ */
+ public ECPoint add(ECPoint b)
+ {
+ checkPoints(this, b);
+ return addSimple((ECPoint.F2m)b);
+ }
+
+ /**
+ * Adds another <code>ECPoints.F2m</code> to <code>this</code> without
+ * checking if both points are on the same curve. Used by multiplication
+ * algorithms, because there all points are a multiple of the same point
+ * and hence the checks can be omitted.
+ * @param b The other <code>ECPoints.F2m</code> to add to
+ * <code>this</code>.
+ * @return <code>this + b</code>
+ */
+ public ECPoint.F2m addSimple(ECPoint.F2m b)
+ {
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return this;
+ }
+
+ 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;
+
+ ECFieldElement dx = X1.add(X2), dy = Y1.add(Y2);
+ if (dx.isZero())
+ {
+ if (dy.isZero())
+ {
+ return (ECPoint.F2m)twice();
+ }
+
+ return (ECPoint.F2m)curve.getInfinity();
+ }
+
+ ECFieldElement L = dy.divide(dx);
+
+ ECFieldElement X3 = L.square().add(L).add(dx).add(curve.getA());
+ ECFieldElement Y3 = L.multiply(X1.add(X3)).add(X3).add(Y1);
+
+ return new ECPoint.F2m(curve, X3, Y3, this.withCompression);
+ }
+ case ECCurve.COORD_HOMOGENEOUS:
+ {
+ ECFieldElement Y1 = this.y, Z1 = this.zs[0];
+ ECFieldElement Y2 = b.y, Z2 = b.zs[0];
+
+ boolean Z2IsOne = Z2.isOne();
+
+ ECFieldElement U1 = Z1.multiply(Y2);
+ ECFieldElement U2 = Z2IsOne ? Y1 : Y1.multiply(Z2);
+ ECFieldElement U = U1.add(U2);
+ ECFieldElement V1 = Z1.multiply(X2);
+ ECFieldElement V2 = Z2IsOne ? X1 : X1.multiply(Z2);
+ ECFieldElement V = V1.add(V2);
+
+ if (V.isZero())
+ {
+ if (U.isZero())
+ {
+ return (ECPoint.F2m)twice();
+ }
+
+ return (ECPoint.F2m)curve.getInfinity();
+ }
+
+ ECFieldElement VSq = V.square();
+ ECFieldElement VCu = VSq.multiply(V);
+ ECFieldElement W = Z2IsOne ? Z1 : Z1.multiply(Z2);
+ ECFieldElement uv = U.add(V);
+ ECFieldElement A = uv.multiplyPlusProduct(U, VSq, curve.getA()).multiply(W).add(VCu);
+
+ ECFieldElement X3 = V.multiply(A);
+ ECFieldElement VSqZ2 = Z2IsOne ? VSq : VSq.multiply(Z2);
+ ECFieldElement Y3 = U.multiplyPlusProduct(X1, V, Y1).multiplyPlusProduct(VSqZ2, uv, A);
+ ECFieldElement Z3 = VCu.multiply(W);
+
+ return new ECPoint.F2m(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ if (X1.isZero())
+ {
+ if (X2.isZero())
+ {
+ return (ECPoint.F2m)curve.getInfinity();
+ }
+
+ return b.addSimple(this);
+ }
+
+ ECFieldElement L1 = this.y, Z1 = this.zs[0];
+ ECFieldElement L2 = b.y, Z2 = b.zs[0];
+
+ boolean Z1IsOne = Z1.isOne();
+ ECFieldElement U2 = X2, S2 = L2;
+ if (!Z1IsOne)
+ {
+ U2 = U2.multiply(Z1);
+ S2 = S2.multiply(Z1);
+ }
+
+ boolean Z2IsOne = Z2.isOne();
+ ECFieldElement U1 = X1, S1 = L1;
+ if (!Z2IsOne)
+ {
+ U1 = U1.multiply(Z2);
+ S1 = S1.multiply(Z2);
+ }
+
+ ECFieldElement A = S1.add(S2);
+ ECFieldElement B = U1.add(U2);
+
+ 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
+ ECPoint p = this.normalize();
+ X1 = p.getXCoord();
+ ECFieldElement Y1 = p.getYCoord();
+
+ ECFieldElement Y2 = L2;
+ ECFieldElement L = Y1.add(Y2).divide(X1);
+
+ X3 = L.square().add(L).add(X1).add(curve.getA());
+ if (X3.isZero())
+ {
+ return new ECPoint.F2m(curve, X3, curve.getB().sqrt(), this.withCompression);
+ }
+
+ ECFieldElement Y3 = L.multiply(X1.add(X3)).add(X3).add(Y1);
+ L3 = Y3.divide(X3).add(X3);
+ Z3 = curve.fromBigInteger(ECConstants.ONE);
+ }
+ else
+ {
+ B = B.square();
+
+ ECFieldElement AU1 = A.multiply(U1);
+ ECFieldElement AU2 = A.multiply(U2);
+
+ X3 = AU1.multiply(AU2);
+ if (X3.isZero())
+ {
+ return new ECPoint.F2m(curve, X3, curve.getB().sqrt(), this.withCompression);
+ }
+
+ ECFieldElement ABZ2 = A.multiply(B);
+ if (!Z2IsOne)
+ {
+ ABZ2 = ABZ2.multiply(Z2);
+ }
+
+ L3 = AU2.add(B).squarePlusProduct(ABZ2, 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)
+ * @see org.spongycastle.math.ec.ECPoint#subtract(org.spongycastle.math.ec.ECPoint)
+ */
+ public ECPoint subtract(ECPoint b)
+ {
+ checkPoints(this, b);
+ return subtractSimple((ECPoint.F2m)b);
+ }
+
+ /**
+ * Subtracts another <code>ECPoints.F2m</code> from <code>this</code>
+ * without checking if both points are on the same curve. Used by
+ * multiplication algorithms, because there all points are a multiple
+ * of the same point and hence the checks can be omitted.
+ * @param b The other <code>ECPoints.F2m</code> to subtract from
+ * <code>this</code>.
+ * @return <code>this - b</code>
+ */
+ public ECPoint.F2m subtractSimple(ECPoint.F2m b)
+ {
+ if (b.isInfinity())
+ {
+ return this;
+ }
+
+ // Add -b
+ return addSimple((ECPoint.F2m)b.negate());
+ }
+
+ public ECPoint.F2m tau()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+ int coord = curve.getCoordinateSystem();
+
+ ECFieldElement X1 = this.x;
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ {
+ ECFieldElement Y1 = this.y;
+ return new ECPoint.F2m(curve, X1.square(), Y1.square(), this.withCompression);
+ }
+ case ECCurve.COORD_HOMOGENEOUS:
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ ECFieldElement Y1 = this.y, Z1 = this.zs[0];
+ return new ECPoint.F2m(curve, X1.square(), Y1.square(), new ECFieldElement[]{ Z1.square() }, this.withCompression);
+ }
+ default:
+ {
+ throw new IllegalStateException("unsupported coordinate system");
+ }
+ }
+ }
+
+ public ECPoint twice()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+
+ ECFieldElement X1 = this.x;
+ if (X1.isZero())
+ {
+ // A point with X == 0 is it's own additive inverse
+ return curve.getInfinity();
+ }
+
+ int coord = curve.getCoordinateSystem();
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ {
+ ECFieldElement Y1 = this.y;
+
+ ECFieldElement L1 = Y1.divide(X1).add(X1);
+
+ ECFieldElement X3 = L1.square().add(L1).add(curve.getA());
+ ECFieldElement Y3 = X1.squarePlusProduct(X3, L1.addOne());
+
+ return new ECPoint.F2m(curve, X3, Y3, this.withCompression);
+ }
+ case ECCurve.COORD_HOMOGENEOUS:
+ {
+ ECFieldElement Y1 = this.y, Z1 = this.zs[0];
+
+ boolean Z1IsOne = Z1.isOne();
+ 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 sv = S.add(V);
+ ECFieldElement h = sv.multiplyPlusProduct(S, vSquared, curve.getA());
+
+ ECFieldElement X3 = V.multiply(h);
+ ECFieldElement Y3 = X1Sq.square().multiplyPlusProduct(V, h, sv);
+ ECFieldElement Z3 = V.multiply(vSquared);
+
+ return new ECPoint.F2m(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ ECFieldElement L1 = this.y, Z1 = this.zs[0];
+
+ boolean Z1IsOne = Z1.isOne();
+ ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.multiply(Z1);
+ ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.square();
+ ECFieldElement a = curve.getA();
+ ECFieldElement aZ1Sq = Z1IsOne ? a : a.multiply(Z1Sq);
+ ECFieldElement T = L1.square().add(L1Z1).add(aZ1Sq);
+ if (T.isZero())
+ {
+ return new ECPoint.F2m(curve, T, curve.getB().sqrt(), withCompression);
+ }
+
+ ECFieldElement X3 = T.square();
+ ECFieldElement Z3 = Z1IsOne ? T : T.multiply(Z1Sq);
+
+ ECFieldElement b = curve.getB();
+ ECFieldElement L3;
+ if (b.bitLength() < (curve.getFieldSize() >> 1))
+ {
+ ECFieldElement t1 = L1.add(X1).square();
+ ECFieldElement t2;
+ if (b.isOne())
+ {
+ t2 = aZ1Sq.add(Z1Sq).square();
+ }
+ else
+ {
+ // TODO Can be calculated with one square if we pre-compute sqrt(b)
+ t2 = aZ1Sq.squarePlusProduct(b, Z1Sq.square());
+ }
+ L3 = t1.add(T).add(Z1Sq).multiply(t1).add(t2).add(X3);
+ if (a.isZero())
+ {
+ L3 = L3.add(Z3);
+ }
+ else if (!a.isOne())
+ {
+ L3 = L3.add(a.addOne().multiply(Z3));
+ }
+ }
+ else
+ {
+ ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.multiply(Z1);
+ L3 = X1Z1.squarePlusProduct(T, L1Z1).add(X3).add(Z3);
+ }
+
+ return new ECPoint.F2m(curve, X3, L3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+ default:
+ {
+ throw new IllegalStateException("unsupported coordinate system");
+ }
+ }
+ }
+
+ public ECPoint twicePlus(ECPoint b)
+ {
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ 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.isOne())
+ {
+ return twice().add(b);
+ }
+
+ 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).multiplyPlusProduct(T, X1Sq, Z1Sq);
+ ECFieldElement X2Z1Sq = X2.multiply(Z1Sq);
+ ECFieldElement B = X2Z1Sq.add(T).square();
+
+ if (B.isZero())
+ {
+ if (A.isZero())
+ {
+ return b.twice();
+ }
+
+ return curve.getInfinity();
+ }
+
+ if (A.isZero())
+ {
+ return new ECPoint.F2m(curve, A, curve.getB().sqrt(), withCompression);
+ }
+
+ ECFieldElement X3 = A.square().multiply(X2Z1Sq);
+ ECFieldElement Z3 = A.multiply(B).multiply(Z1Sq);
+ ECFieldElement L3 = A.add(B).square().multiplyPlusProduct(T, L2plus1, Z3);
+
+ return new ECPoint.F2m(curve, X3, L3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+ default:
+ {
+ return twice().add(b);
+ }
+ }
+ }
+
+ 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/core/src/main/java/org/spongycastle/math/ec/ECPointMap.java b/core/src/main/java/org/spongycastle/math/ec/ECPointMap.java
new file mode 100644
index 00000000..69503585
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/ECPointMap.java
@@ -0,0 +1,6 @@
+package org.spongycastle.math.ec;
+
+public interface ECPointMap
+{
+ ECPoint map(ECPoint p);
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/FixedPointCombMultiplier.java b/core/src/main/java/org/spongycastle/math/ec/FixedPointCombMultiplier.java
new file mode 100644
index 00000000..42ba2cc8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/FixedPointCombMultiplier.java
@@ -0,0 +1,57 @@
+package org.spongycastle.math.ec;
+
+import java.math.BigInteger;
+
+public class FixedPointCombMultiplier extends AbstractECMultiplier
+{
+ protected ECPoint multiplyPositive(ECPoint p, BigInteger k)
+ {
+ ECCurve c = p.getCurve();
+ int size = FixedPointUtil.getCombSize(c);
+
+ if (k.bitLength() > size)
+ {
+ /*
+ * TODO The comb works best when the scalars are less than the (possibly unknown) order.
+ * Still, if we want to handle larger scalars, we could allow customization of the comb
+ * size, or alternatively we could deal with the 'extra' bits either by running the comb
+ * multiple times as necessary, or by using an alternative multiplier as prelude.
+ */
+ throw new IllegalStateException("fixed-point comb doesn't support scalars larger than the curve order");
+ }
+
+ int minWidth = getWidthForCombSize(size);
+
+ FixedPointPreCompInfo info = FixedPointUtil.precompute(p, minWidth);
+ ECPoint[] lookupTable = info.getPreComp();
+ int width = info.getWidth();
+
+ int d = (size + width - 1) / width;
+
+ ECPoint R = c.getInfinity();
+
+ int top = d * width - 1;
+ for (int i = 0; i < d; ++i)
+ {
+ int index = 0;
+
+ for (int j = top - i; j >= 0; j -= d)
+ {
+ index <<= 1;
+ if (k.testBit(j))
+ {
+ index |= 1;
+ }
+ }
+
+ R = R.twicePlus(lookupTable[index]);
+ }
+
+ return R;
+ }
+
+ protected int getWidthForCombSize(int combSize)
+ {
+ return combSize > 257 ? 6 : 5;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/FixedPointPreCompInfo.java b/core/src/main/java/org/spongycastle/math/ec/FixedPointPreCompInfo.java
new file mode 100644
index 00000000..0a14f499
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/FixedPointPreCompInfo.java
@@ -0,0 +1,40 @@
+package org.spongycastle.math.ec;
+
+/**
+ * Class holding precomputation data for fixed-point multiplications.
+ */
+public class FixedPointPreCompInfo implements PreCompInfo
+{
+ /**
+ * Array holding the precomputed <code>ECPoint</code>s used for a fixed
+ * point multiplication.
+ */
+ protected ECPoint[] preComp = null;
+
+ /**
+ * The width used for the precomputation. If a larger width precomputation
+ * is already available this may be larger than was requested, so calling
+ * code should refer to the actual width.
+ */
+ protected int width = -1;
+
+ public ECPoint[] getPreComp()
+ {
+ return preComp;
+ }
+
+ public void setPreComp(ECPoint[] preComp)
+ {
+ this.preComp = preComp;
+ }
+
+ public int getWidth()
+ {
+ return width;
+ }
+
+ public void setWidth(int width)
+ {
+ this.width = width;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/FixedPointUtil.java b/core/src/main/java/org/spongycastle/math/ec/FixedPointUtil.java
new file mode 100644
index 00000000..aa96ebcb
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/FixedPointUtil.java
@@ -0,0 +1,71 @@
+package org.spongycastle.math.ec;
+
+import java.math.BigInteger;
+
+public class FixedPointUtil
+{
+ public static final String PRECOMP_NAME = "bc_fixed_point";
+
+ public static int getCombSize(ECCurve c)
+ {
+ BigInteger order = c.getOrder();
+ return order == null ? c.getFieldSize() + 1 : order.bitLength();
+ }
+
+ public static FixedPointPreCompInfo getFixedPointPreCompInfo(PreCompInfo preCompInfo)
+ {
+ if ((preCompInfo != null) && (preCompInfo instanceof FixedPointPreCompInfo))
+ {
+ return (FixedPointPreCompInfo)preCompInfo;
+ }
+
+ return new FixedPointPreCompInfo();
+ }
+
+ public static FixedPointPreCompInfo precompute(ECPoint p, int minWidth)
+ {
+ ECCurve c = p.getCurve();
+
+ int n = 1 << minWidth;
+ FixedPointPreCompInfo info = getFixedPointPreCompInfo(c.getPreCompInfo(p, PRECOMP_NAME));
+ ECPoint[] lookupTable = info.getPreComp();
+
+ if (lookupTable == null || lookupTable.length < n)
+ {
+ int bits = getCombSize(c);
+ int d = (bits + minWidth - 1) / minWidth;
+
+ ECPoint[] pow2Table = new ECPoint[minWidth];
+ pow2Table[0] = p;
+ for (int i = 1; i < minWidth; ++i)
+ {
+ pow2Table[i] = pow2Table[i - 1].timesPow2(d);
+ }
+
+ c.normalizeAll(pow2Table);
+
+ lookupTable = new ECPoint[n];
+ lookupTable[0] = c.getInfinity();
+
+ for (int bit = minWidth - 1; bit >= 0; --bit)
+ {
+ ECPoint pow2 = pow2Table[bit];
+
+ int step = 1 << bit;
+ for (int i = step; i < n; i += (step << 1))
+ {
+ lookupTable[i] = lookupTable[i - step].add(pow2);
+ }
+ }
+
+ c.normalizeAll(lookupTable);
+
+ info.setPreComp(lookupTable);
+ info.setWidth(minWidth);
+
+ c.setPreCompInfo(p, PRECOMP_NAME, info);
+ }
+
+ return info;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/GLVMultiplier.java b/core/src/main/java/org/spongycastle/math/ec/GLVMultiplier.java
new file mode 100644
index 00000000..fb2c3ee3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/GLVMultiplier.java
@@ -0,0 +1,42 @@
+package org.spongycastle.math.ec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.ec.endo.GLVEndomorphism;
+
+public class GLVMultiplier extends AbstractECMultiplier
+{
+ protected final ECCurve curve;
+ protected final GLVEndomorphism glvEndomorphism;
+
+ public GLVMultiplier(ECCurve curve, GLVEndomorphism glvEndomorphism)
+ {
+ if (curve == null || curve.getOrder() == null)
+ {
+ throw new IllegalArgumentException("Need curve with known group order");
+ }
+
+ this.curve = curve;
+ this.glvEndomorphism = glvEndomorphism;
+ }
+
+ protected ECPoint multiplyPositive(ECPoint p, BigInteger k)
+ {
+ if (!curve.equals(p.getCurve()))
+ {
+ throw new IllegalStateException();
+ }
+
+ BigInteger n = p.getCurve().getOrder();
+ BigInteger[] ab = glvEndomorphism.decomposeScalar(k.mod(n));
+ BigInteger a = ab[0], b = ab[1];
+
+ ECPointMap pointMap = glvEndomorphism.getPointMap();
+ if (glvEndomorphism.hasEfficientPointMap())
+ {
+ return ECAlgorithms.implShamirsTrickWNaf(p, a, pointMap, b);
+ }
+
+ return ECAlgorithms.implShamirsTrickWNaf(p, a, pointMap.map(p), b);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/LongArray.java b/core/src/main/java/org/spongycastle/math/ec/LongArray.java
new file mode 100644
index 00000000..6f718cd5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/LongArray.java
@@ -0,0 +1,2195 @@
+package org.spongycastle.math.ec;
+
+import org.spongycastle.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 isOne()
+ {
+ long[] a = m_ints;
+ if (a[0] != 1L)
+ {
+ return false;
+ }
+ for (int i = 1; i < a.length; ++i)
+ {
+ if (a[i] != 0L)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean isZero()
+ {
+ long[] a = m_ints;
+ 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) != 0L)
+ {
+ if ((a & 1L) != 0L)
+ {
+ long carry = addShiftedUp(c, cOff, b, 0, bLen, k);
+ if (carry != 0L)
+ {
+ 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 a0 = A.m_ints[0];
+ if (a0 == 1L)
+ {
+ return B;
+ }
+
+ /*
+ * Fast path for small A, with performance dependent only on the number of set bits
+ */
+ long[] c0 = new long[cLen];
+ multiplyWord(a0, B.m_ints, bLen, c0, 0);
+
+ /*
+ * Reduce the raw answer against the reduction coefficients
+ */
+ return reduceResult(c0, 0, cLen, m, ks);
+ }
+
+ /*
+ * 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 a0 = A.m_ints[0];
+ if (a0 == 1L)
+ {
+ return B;
+ }
+
+ /*
+ * Fast path for small A, with performance dependent only on the number of set bits
+ */
+ long[] c0 = new long[cLen];
+ multiplyWord(a0, B.m_ints, bLen, c0, 0);
+
+ /*
+ * Reduce the raw answer against the reduction coefficients
+ */
+ return reduceResult(c0, 0, cLen, m, ks);
+ }
+
+ /*
+ * Determine if B will get bigger during shifting
+ */
+ int bMax = (bDeg + 7 + 63) >>> 6;
+
+ /*
+ * Lookup table for the offset of each B in the tables
+ */
+ int[] ti = new int[16];
+
+ /*
+ * Precompute table of all 4-bit products of B
+ */
+ long[] T0 = new long[bMax << 4];
+ int tOff = bMax;
+ ti[1] = tOff;
+ System.arraycopy(B.m_ints, 0, T0, tOff, bLen);
+ for (int i = 2; i < 16; ++i)
+ {
+ ti[i] = (tOff += bMax);
+ if ((i & 1) == 0)
+ {
+ shiftUp(T0, tOff >>> 1, T0, tOff, bMax, 1);
+ }
+ else
+ {
+ add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax);
+ }
+ }
+
+ /*
+ * Second table with all 4-bit products of B shifted 4 bits
+ */
+ long[] T1 = new long[T0.length];
+ shiftUp(T0, 0, T1, 0, T0.length, 4);
+// shiftUp(T0, bMax, T1, bMax, tOff, 4);
+
+ long[] a = A.m_ints;
+ long[] c = new long[cLen << 3];
+
+ int MASK = 0xF;
+
+ /*
+ * Lopez-Dahab (Modified) algorithm
+ */
+
+ for (int aPos = 0; aPos < aLen; ++aPos)
+ {
+ long aVal = a[aPos];
+ int cOff = aPos;
+ for (;;)
+ {
+ int u = (int)aVal & MASK;
+ aVal >>>= 4;
+ int v = (int)aVal & MASK;
+ addBoth(c, cOff, T0, ti[u], T1, ti[v], bMax);
+ aVal >>>= 4;
+ if (aVal == 0L)
+ {
+ break;
+ }
+ cOff += cLen;
+ }
+ }
+
+ {
+ int cOff = c.length;
+ while ((cOff -= cLen) != 0)
+ {
+ addShiftedUp(c, cOff - cLen, c, cOff, cLen, 8);
+ }
+ }
+
+ /*
+ * Finally the raw answer is collected, reduce it against the reduction coefficients
+ */
+ return reduceResult(c, 0, cLen, m, ks);
+ }
+
+ 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 a0 = A.m_ints[0];
+ if (a0 == 1L)
+ {
+ return B;
+ }
+
+ /*
+ * Fast path for small A, with performance dependent only on the number of set bits
+ */
+ long[] c0 = new long[cLen];
+ multiplyWord(a0, B.m_ints, bLen, c0, 0);
+
+ /*
+ * Reduce the raw answer against the reduction coefficients
+ */
+ return reduceResult(c0, 0, cLen, m, ks);
+ }
+
+ // 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);
+ }
+
+ public LongArray modReduce(int m, int[] ks)
+ {
+ long[] buf = Arrays.clone(m_ints);
+ int rLen = reduceInPlace(buf, 0, buf.length, m, ks);
+ return new LongArray(buf, 0, rLen);
+ }
+
+ public LongArray multiply(LongArray other, int m, int[] ks)
+ {
+ /*
+ * Find out the degree of each argument and handle the zero cases
+ */
+ int aDeg = degree();
+ if (aDeg == 0)
+ {
+ return this;
+ }
+ int bDeg = other.degree();
+ if (bDeg == 0)
+ {
+ return other;
+ }
+
+ /*
+ * Swap if necessary so that A is the smaller argument
+ */
+ LongArray A = this, B = other;
+ if (aDeg > bDeg)
+ {
+ A = other; B = this;
+ int tmp = aDeg; aDeg = bDeg; bDeg = tmp;
+ }
+
+ /*
+ * Establish the word lengths of the arguments and result
+ */
+ int aLen = (aDeg + 63) >>> 6;
+ int bLen = (bDeg + 63) >>> 6;
+ int cLen = (aDeg + bDeg + 62) >>> 6;
+
+ if (aLen == 1)
+ {
+ long a0 = A.m_ints[0];
+ if (a0 == 1L)
+ {
+ return B;
+ }
+
+ /*
+ * Fast path for small A, with performance dependent only on the number of set bits
+ */
+ long[] c0 = new long[cLen];
+ multiplyWord(a0, B.m_ints, bLen, c0, 0);
+
+ /*
+ * Reduce the raw answer against the reduction coefficients
+ */
+// return reduceResult(c0, 0, cLen, m, ks);
+ return new LongArray(c0, 0, cLen);
+ }
+
+ /*
+ * Determine if B will get bigger during shifting
+ */
+ int bMax = (bDeg + 7 + 63) >>> 6;
+
+ /*
+ * Lookup table for the offset of each B in the tables
+ */
+ int[] ti = new int[16];
+
+ /*
+ * Precompute table of all 4-bit products of B
+ */
+ long[] T0 = new long[bMax << 4];
+ int tOff = bMax;
+ ti[1] = tOff;
+ System.arraycopy(B.m_ints, 0, T0, tOff, bLen);
+ for (int i = 2; i < 16; ++i)
+ {
+ ti[i] = (tOff += bMax);
+ if ((i & 1) == 0)
+ {
+ shiftUp(T0, tOff >>> 1, T0, tOff, bMax, 1);
+ }
+ else
+ {
+ add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax);
+ }
+ }
+
+ /*
+ * Second table with all 4-bit products of B shifted 4 bits
+ */
+ long[] T1 = new long[T0.length];
+ shiftUp(T0, 0, T1, 0, T0.length, 4);
+// shiftUp(T0, bMax, T1, bMax, tOff, 4);
+
+ long[] a = A.m_ints;
+ long[] c = new long[cLen << 3];
+
+ int MASK = 0xF;
+
+ /*
+ * Lopez-Dahab (Modified) algorithm
+ */
+
+ for (int aPos = 0; aPos < aLen; ++aPos)
+ {
+ long aVal = a[aPos];
+ int cOff = aPos;
+ for (;;)
+ {
+ int u = (int)aVal & MASK;
+ aVal >>>= 4;
+ int v = (int)aVal & MASK;
+ addBoth(c, cOff, T0, ti[u], T1, ti[v], bMax);
+ aVal >>>= 4;
+ if (aVal == 0L)
+ {
+ break;
+ }
+ cOff += cLen;
+ }
+ }
+
+ {
+ int cOff = c.length;
+ while ((cOff -= cLen) != 0)
+ {
+ addShiftedUp(c, cOff - cLen, c, cOff, cLen, 8);
+ }
+ }
+
+ /*
+ * Finally the raw answer is collected, reduce it against the reduction coefficients
+ */
+// return reduceResult(c, 0, cLen, m, ks);
+ return new LongArray(c, 0, cLen);
+ }
+
+ public void reduce(int m, int[] ks)
+ {
+ long[] buf = m_ints;
+ int rLen = reduceInPlace(buf, 0, buf.length, m, ks);
+ if (rLen < buf.length)
+ {
+ m_ints = new long[rLen];
+ System.arraycopy(buf, 0, m_ints, 0, rLen);
+ }
+ }
+
+ private static LongArray reduceResult(long[] buf, int off, int len, int m, int[] ks)
+ {
+ int rLen = reduceInPlace(buf, off, len, m, ks);
+ 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 n = bit - m;
+ int j = ks.length;
+ while (--j >= 0)
+ {
+ flipBit(buf, off, ks[j] + n);
+ }
+ flipBit(buf, off, n);
+ }
+
+ 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));
+ }
+
+ public LongArray modSquareN(int n, int m, int[] ks)
+ {
+ int len = getUsedLength();
+ if (len == 0)
+ {
+ return this;
+ }
+
+ int mLen = (m + 63) >>> 6;
+ long[] r = new long[mLen << 1];
+ System.arraycopy(m_ints, 0, r, 0, len);
+
+ while (--n >= 0)
+ {
+ squareInPlace(r, len, m, ks);
+ len = reduceInPlace(r, 0, r.length, m, ks);
+ }
+
+ return new LongArray(r, 0, len);
+ }
+
+ public LongArray square(int m, int[] ks)
+ {
+ int len = getUsedLength();
+ if (len == 0)
+ {
+ return this;
+ }
+
+ int _2len = len << 1;
+ long[] r = new long[_2len];
+
+ int pos = 0;
+ while (pos < _2len)
+ {
+ long mi = m_ints[pos >>> 1];
+ r[pos++] = interleave2_32to64((int)mi);
+ r[pos++] = interleave2_32to64((int)(mi >>> 32));
+ }
+
+ return new LongArray(r, 0, r.length);
+ }
+
+ private static void squareInPlace(long[] x, int xLen, int m, int[] ks)
+ {
+ int pos = xLen << 1;
+ while (--xLen >= 0)
+ {
+ long xVal = x[xLen];
+ x[--pos] = interleave2_32to64((int)(xVal >>> 32));
+ x[--pos] = interleave2_32to64((int)xVal);
+ }
+ }
+
+ private static void interleave(long[] x, int xOff, long[] z, int zOff, int count, int width)
+ {
+ 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 == 0)
+ {
+ throw new IllegalStateException();
+ }
+ 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/core/src/main/java/org/spongycastle/math/ec/MixedNafR2LMultiplier.java b/core/src/main/java/org/spongycastle/math/ec/MixedNafR2LMultiplier.java
new file mode 100644
index 00000000..e626103a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/MixedNafR2LMultiplier.java
@@ -0,0 +1,77 @@
+package org.spongycastle.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/core/src/main/java/org/spongycastle/math/ec/MontgomeryLadderMultiplier.java b/core/src/main/java/org/spongycastle/math/ec/MontgomeryLadderMultiplier.java
new file mode 100644
index 00000000..bc4f7a00
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/MontgomeryLadderMultiplier.java
@@ -0,0 +1,25 @@
+package org.spongycastle.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/core/src/main/java/org/spongycastle/math/ec/NafL2RMultiplier.java b/core/src/main/java/org/spongycastle/math/ec/NafL2RMultiplier.java
new file mode 100644
index 00000000..b2aac42c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/NafL2RMultiplier.java
@@ -0,0 +1,30 @@
+package org.spongycastle.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/core/src/main/java/org/spongycastle/math/ec/NafR2LMultiplier.java b/core/src/main/java/org/spongycastle/math/ec/NafR2LMultiplier.java
new file mode 100644
index 00000000..78aecb02
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/NafR2LMultiplier.java
@@ -0,0 +1,31 @@
+package org.spongycastle.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/core/src/main/java/org/spongycastle/math/ec/PreCompInfo.java b/core/src/main/java/org/spongycastle/math/ec/PreCompInfo.java
new file mode 100644
index 00000000..72af12c4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/PreCompInfo.java
@@ -0,0 +1,10 @@
+package org.spongycastle.math.ec;
+
+/**
+ * Interface for classes storing precomputation data for multiplication
+ * algorithms. Used as a Memento (see GOF patterns) by e.g.
+ * <code>WNafL2RMultiplier</code>.
+ */
+public interface PreCompInfo
+{
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/ReferenceMultiplier.java b/core/src/main/java/org/spongycastle/math/ec/ReferenceMultiplier.java
new file mode 100644
index 00000000..b4c53fdd
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/ReferenceMultiplier.java
@@ -0,0 +1,11 @@
+package org.spongycastle.math.ec;
+
+import java.math.BigInteger;
+
+public class ReferenceMultiplier extends AbstractECMultiplier
+{
+ protected ECPoint multiplyPositive(ECPoint p, BigInteger k)
+ {
+ return ECAlgorithms.referenceMultiply(p, k);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/ScaleXPointMap.java b/core/src/main/java/org/spongycastle/math/ec/ScaleXPointMap.java
new file mode 100644
index 00000000..6630c4f9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/ScaleXPointMap.java
@@ -0,0 +1,16 @@
+package org.spongycastle.math.ec;
+
+public class ScaleXPointMap implements ECPointMap
+{
+ protected final ECFieldElement scale;
+
+ public ScaleXPointMap(ECFieldElement scale)
+ {
+ this.scale = scale;
+ }
+
+ public ECPoint map(ECPoint p)
+ {
+ return p.scaleX(scale);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/ScaleYPointMap.java b/core/src/main/java/org/spongycastle/math/ec/ScaleYPointMap.java
new file mode 100644
index 00000000..7a215cb4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/ScaleYPointMap.java
@@ -0,0 +1,16 @@
+package org.spongycastle.math.ec;
+
+public class ScaleYPointMap implements ECPointMap
+{
+ protected final ECFieldElement scale;
+
+ public ScaleYPointMap(ECFieldElement scale)
+ {
+ this.scale = scale;
+ }
+
+ public ECPoint map(ECPoint p)
+ {
+ return p.scaleY(scale);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/SimpleBigDecimal.java b/core/src/main/java/org/spongycastle/math/ec/SimpleBigDecimal.java
new file mode 100644
index 00000000..c367830a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/SimpleBigDecimal.java
@@ -0,0 +1,247 @@
+package org.spongycastle.math.ec;
+
+import java.math.BigInteger;
+
+/**
+ * Class representing a simple version of a big decimal. A
+ * <code>SimpleBigDecimal</code> is basically a
+ * {@link java.math.BigInteger BigInteger} with a few digits on the right of
+ * the decimal point. The number of (binary) digits on the right of the decimal
+ * point is called the <code>scale</code> of the <code>SimpleBigDecimal</code>.
+ * Unlike in {@link java.math.BigDecimal BigDecimal}, the scale is not adjusted
+ * automatically, but must be set manually. All <code>SimpleBigDecimal</code>s
+ * taking part in the same arithmetic operation must have equal scale. The
+ * result of a multiplication of two <code>SimpleBigDecimal</code>s returns a
+ * <code>SimpleBigDecimal</code> with double scale.
+ */
+class SimpleBigDecimal
+ //extends Number // not in J2ME - add compatibility class?
+{
+ private static final long serialVersionUID = 1L;
+
+ private final BigInteger bigInt;
+ private final int scale;
+
+ /**
+ * Returns a <code>SimpleBigDecimal</code> representing the same numerical
+ * value as <code>value</code>.
+ * @param value The value of the <code>SimpleBigDecimal</code> to be
+ * created.
+ * @param scale The scale of the <code>SimpleBigDecimal</code> to be
+ * created.
+ * @return The such created <code>SimpleBigDecimal</code>.
+ */
+ public static SimpleBigDecimal getInstance(BigInteger value, int scale)
+ {
+ return new SimpleBigDecimal(value.shiftLeft(scale), scale);
+ }
+
+ /**
+ * Constructor for <code>SimpleBigDecimal</code>. The value of the
+ * constructed <code>SimpleBigDecimal</code> equals <code>bigInt /
+ * 2<sup>scale</sup></code>.
+ * @param bigInt The <code>bigInt</code> value parameter.
+ * @param scale The scale of the constructed <code>SimpleBigDecimal</code>.
+ */
+ public SimpleBigDecimal(BigInteger bigInt, int scale)
+ {
+ if (scale < 0)
+ {
+ throw new IllegalArgumentException("scale may not be negative");
+ }
+
+ this.bigInt = bigInt;
+ this.scale = scale;
+ }
+
+ private void checkScale(SimpleBigDecimal b)
+ {
+ if (scale != b.scale)
+ {
+ throw new IllegalArgumentException("Only SimpleBigDecimal of " +
+ "same scale allowed in arithmetic operations");
+ }
+ }
+
+ public SimpleBigDecimal adjustScale(int newScale)
+ {
+ if (newScale < 0)
+ {
+ throw new IllegalArgumentException("scale may not be negative");
+ }
+
+ if (newScale == scale)
+ {
+ return this;
+ }
+
+ return new SimpleBigDecimal(bigInt.shiftLeft(newScale - scale),
+ newScale);
+ }
+
+ public SimpleBigDecimal add(SimpleBigDecimal b)
+ {
+ checkScale(b);
+ return new SimpleBigDecimal(bigInt.add(b.bigInt), scale);
+ }
+
+ public SimpleBigDecimal add(BigInteger b)
+ {
+ return new SimpleBigDecimal(bigInt.add(b.shiftLeft(scale)), scale);
+ }
+
+ public SimpleBigDecimal negate()
+ {
+ return new SimpleBigDecimal(bigInt.negate(), scale);
+ }
+
+ public SimpleBigDecimal subtract(SimpleBigDecimal b)
+ {
+ return add(b.negate());
+ }
+
+ public SimpleBigDecimal subtract(BigInteger b)
+ {
+ return new SimpleBigDecimal(bigInt.subtract(b.shiftLeft(scale)),
+ scale);
+ }
+
+ public SimpleBigDecimal multiply(SimpleBigDecimal b)
+ {
+ checkScale(b);
+ return new SimpleBigDecimal(bigInt.multiply(b.bigInt), scale + scale);
+ }
+
+ public SimpleBigDecimal multiply(BigInteger b)
+ {
+ return new SimpleBigDecimal(bigInt.multiply(b), scale);
+ }
+
+ public SimpleBigDecimal divide(SimpleBigDecimal b)
+ {
+ checkScale(b);
+ BigInteger dividend = bigInt.shiftLeft(scale);
+ return new SimpleBigDecimal(dividend.divide(b.bigInt), scale);
+ }
+
+ public SimpleBigDecimal divide(BigInteger b)
+ {
+ return new SimpleBigDecimal(bigInt.divide(b), scale);
+ }
+
+ public SimpleBigDecimal shiftLeft(int n)
+ {
+ return new SimpleBigDecimal(bigInt.shiftLeft(n), scale);
+ }
+
+ public int compareTo(SimpleBigDecimal val)
+ {
+ checkScale(val);
+ return bigInt.compareTo(val.bigInt);
+ }
+
+ public int compareTo(BigInteger val)
+ {
+ return bigInt.compareTo(val.shiftLeft(scale));
+ }
+
+ public BigInteger floor()
+ {
+ return bigInt.shiftRight(scale);
+ }
+
+ public BigInteger round()
+ {
+ SimpleBigDecimal oneHalf = new SimpleBigDecimal(ECConstants.ONE, 1);
+ return add(oneHalf.adjustScale(scale)).floor();
+ }
+
+ public int intValue()
+ {
+ return floor().intValue();
+ }
+
+ public long longValue()
+ {
+ return floor().longValue();
+ }
+ /* NON-J2ME compliant.
+ public double doubleValue()
+ {
+ return Double.valueOf(toString()).doubleValue();
+ }
+
+ public float floatValue()
+ {
+ return Float.valueOf(toString()).floatValue();
+ }
+ */
+ public int getScale()
+ {
+ return scale;
+ }
+
+ public String toString()
+ {
+ if (scale == 0)
+ {
+ return bigInt.toString();
+ }
+
+ BigInteger floorBigInt = floor();
+
+ BigInteger fract = bigInt.subtract(floorBigInt.shiftLeft(scale));
+ if (bigInt.signum() == -1)
+ {
+ fract = ECConstants.ONE.shiftLeft(scale).subtract(fract);
+ }
+
+ if ((floorBigInt.signum() == -1) && (!(fract.equals(ECConstants.ZERO))))
+ {
+ floorBigInt = floorBigInt.add(ECConstants.ONE);
+ }
+ String leftOfPoint = floorBigInt.toString();
+
+ char[] fractCharArr = new char[scale];
+ String fractStr = fract.toString(2);
+ int fractLen = fractStr.length();
+ int zeroes = scale - fractLen;
+ for (int i = 0; i < zeroes; i++)
+ {
+ fractCharArr[i] = '0';
+ }
+ for (int j = 0; j < fractLen; j++)
+ {
+ fractCharArr[zeroes + j] = fractStr.charAt(j);
+ }
+ String rightOfPoint = new String(fractCharArr);
+
+ StringBuffer sb = new StringBuffer(leftOfPoint);
+ sb.append(".");
+ sb.append(rightOfPoint);
+
+ return sb.toString();
+ }
+
+ public boolean equals(Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+
+ if (!(o instanceof SimpleBigDecimal))
+ {
+ return false;
+ }
+
+ SimpleBigDecimal other = (SimpleBigDecimal)o;
+ return ((bigInt.equals(other.bigInt)) && (scale == other.scale));
+ }
+
+ public int hashCode()
+ {
+ return bigInt.hashCode() ^ scale;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/Tnaf.java b/core/src/main/java/org/spongycastle/math/ec/Tnaf.java
new file mode 100644
index 00000000..d5aba320
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/Tnaf.java
@@ -0,0 +1,823 @@
+package org.spongycastle.math.ec;
+
+import java.math.BigInteger;
+
+/**
+ * Class holding methods for point multiplication based on the window
+ * &tau;-adic nonadjacent form (WTNAF). The algorithms are based on the
+ * paper "Improved Algorithms for Arithmetic on Anomalous Binary Curves"
+ * by Jerome A. Solinas. The paper first appeared in the Proceedings of
+ * Crypto 1997.
+ */
+class Tnaf
+{
+ private static final BigInteger MINUS_ONE = ECConstants.ONE.negate();
+ private static final BigInteger MINUS_TWO = ECConstants.TWO.negate();
+ private static final BigInteger MINUS_THREE = ECConstants.THREE.negate();
+
+ /**
+ * The window width of WTNAF. The standard value of 4 is slightly less
+ * than optimal for running time, but keeps space requirements for
+ * precomputation low. For typical curves, a value of 5 or 6 results in
+ * a better running time. When changing this value, the
+ * <code>&alpha;<sub>u</sub></code>'s must be computed differently, see
+ * e.g. "Guide to Elliptic Curve Cryptography", Darrel Hankerson,
+ * Alfred Menezes, Scott Vanstone, Springer-Verlag New York Inc., 2004,
+ * p. 121-122
+ */
+ public static final byte WIDTH = 4;
+
+ /**
+ * 2<sup>4</sup>
+ */
+ public static final byte POW_2_WIDTH = 16;
+
+ /**
+ * The <code>&alpha;<sub>u</sub></code>'s for <code>a=0</code> as an array
+ * of <code>ZTauElement</code>s.
+ */
+ public static final ZTauElement[] alpha0 = {
+ null,
+ new ZTauElement(ECConstants.ONE, ECConstants.ZERO), null,
+ new ZTauElement(MINUS_THREE, MINUS_ONE), null,
+ new ZTauElement(MINUS_ONE, MINUS_ONE), null,
+ new ZTauElement(ECConstants.ONE, MINUS_ONE), null
+ };
+
+ /**
+ * The <code>&alpha;<sub>u</sub></code>'s for <code>a=0</code> as an array
+ * of TNAFs.
+ */
+ public static final byte[][] alpha0Tnaf = {
+ null, {1}, null, {-1, 0, 1}, null, {1, 0, 1}, null, {-1, 0, 0, 1}
+ };
+
+ /**
+ * The <code>&alpha;<sub>u</sub></code>'s for <code>a=1</code> as an array
+ * of <code>ZTauElement</code>s.
+ */
+ public static final ZTauElement[] alpha1 = {null,
+ new ZTauElement(ECConstants.ONE, ECConstants.ZERO), null,
+ new ZTauElement(MINUS_THREE, ECConstants.ONE), null,
+ new ZTauElement(MINUS_ONE, ECConstants.ONE), null,
+ new ZTauElement(ECConstants.ONE, ECConstants.ONE), null
+ };
+
+ /**
+ * The <code>&alpha;<sub>u</sub></code>'s for <code>a=1</code> as an array
+ * of TNAFs.
+ */
+ public static final byte[][] alpha1Tnaf = {
+ null, {1}, null, {-1, 0, 1}, null, {1, 0, 1}, null, {-1, 0, 0, -1}
+ };
+
+ /**
+ * Computes the norm of an element <code>&lambda;</code> of
+ * <code><b>Z</b>[&tau;]</code>.
+ * @param mu The parameter <code>&mu;</code> of the elliptic curve.
+ * @param lambda The element <code>&lambda;</code> of
+ * <code><b>Z</b>[&tau;]</code>.
+ * @return The norm of <code>&lambda;</code>.
+ */
+ public static BigInteger norm(final byte mu, ZTauElement lambda)
+ {
+ BigInteger norm;
+
+ // s1 = u^2
+ BigInteger s1 = lambda.u.multiply(lambda.u);
+
+ // s2 = u * v
+ BigInteger s2 = lambda.u.multiply(lambda.v);
+
+ // s3 = 2 * v^2
+ BigInteger s3 = lambda.v.multiply(lambda.v).shiftLeft(1);
+
+ if (mu == 1)
+ {
+ norm = s1.add(s2).add(s3);
+ }
+ else if (mu == -1)
+ {
+ norm = s1.subtract(s2).add(s3);
+ }
+ else
+ {
+ throw new IllegalArgumentException("mu must be 1 or -1");
+ }
+
+ return norm;
+ }
+
+ /**
+ * Computes the norm of an element <code>&lambda;</code> of
+ * <code><b>R</b>[&tau;]</code>, where <code>&lambda; = u + v&tau;</code>
+ * and <code>u</code> and <code>u</code> are real numbers (elements of
+ * <code><b>R</b></code>).
+ * @param mu The parameter <code>&mu;</code> of the elliptic curve.
+ * @param u The real part of the element <code>&lambda;</code> of
+ * <code><b>R</b>[&tau;]</code>.
+ * @param v The <code>&tau;</code>-adic part of the element
+ * <code>&lambda;</code> of <code><b>R</b>[&tau;]</code>.
+ * @return The norm of <code>&lambda;</code>.
+ */
+ public static SimpleBigDecimal norm(final byte mu, SimpleBigDecimal u,
+ SimpleBigDecimal v)
+ {
+ SimpleBigDecimal norm;
+
+ // s1 = u^2
+ SimpleBigDecimal s1 = u.multiply(u);
+
+ // s2 = u * v
+ SimpleBigDecimal s2 = u.multiply(v);
+
+ // s3 = 2 * v^2
+ SimpleBigDecimal s3 = v.multiply(v).shiftLeft(1);
+
+ if (mu == 1)
+ {
+ norm = s1.add(s2).add(s3);
+ }
+ else if (mu == -1)
+ {
+ norm = s1.subtract(s2).add(s3);
+ }
+ else
+ {
+ throw new IllegalArgumentException("mu must be 1 or -1");
+ }
+
+ return norm;
+ }
+
+ /**
+ * Rounds an element <code>&lambda;</code> of <code><b>R</b>[&tau;]</code>
+ * to an element of <code><b>Z</b>[&tau;]</code>, such that their difference
+ * has minimal norm. <code>&lambda;</code> is given as
+ * <code>&lambda; = &lambda;<sub>0</sub> + &lambda;<sub>1</sub>&tau;</code>.
+ * @param lambda0 The component <code>&lambda;<sub>0</sub></code>.
+ * @param lambda1 The component <code>&lambda;<sub>1</sub></code>.
+ * @param mu The parameter <code>&mu;</code> of the elliptic curve. Must
+ * equal 1 or -1.
+ * @return The rounded element of <code><b>Z</b>[&tau;]</code>.
+ * @throws IllegalArgumentException if <code>lambda0</code> and
+ * <code>lambda1</code> do not have same scale.
+ */
+ public static ZTauElement round(SimpleBigDecimal lambda0,
+ SimpleBigDecimal lambda1, byte mu)
+ {
+ int scale = lambda0.getScale();
+ if (lambda1.getScale() != scale)
+ {
+ throw new IllegalArgumentException("lambda0 and lambda1 do not " +
+ "have same scale");
+ }
+
+ if (!((mu == 1) || (mu == -1)))
+ {
+ throw new IllegalArgumentException("mu must be 1 or -1");
+ }
+
+ BigInteger f0 = lambda0.round();
+ BigInteger f1 = lambda1.round();
+
+ SimpleBigDecimal eta0 = lambda0.subtract(f0);
+ SimpleBigDecimal eta1 = lambda1.subtract(f1);
+
+ // eta = 2*eta0 + mu*eta1
+ SimpleBigDecimal eta = eta0.add(eta0);
+ if (mu == 1)
+ {
+ eta = eta.add(eta1);
+ }
+ else
+ {
+ // mu == -1
+ eta = eta.subtract(eta1);
+ }
+
+ // check1 = eta0 - 3*mu*eta1
+ // check2 = eta0 + 4*mu*eta1
+ SimpleBigDecimal threeEta1 = eta1.add(eta1).add(eta1);
+ SimpleBigDecimal fourEta1 = threeEta1.add(eta1);
+ SimpleBigDecimal check1;
+ SimpleBigDecimal check2;
+ if (mu == 1)
+ {
+ check1 = eta0.subtract(threeEta1);
+ check2 = eta0.add(fourEta1);
+ }
+ else
+ {
+ // mu == -1
+ check1 = eta0.add(threeEta1);
+ check2 = eta0.subtract(fourEta1);
+ }
+
+ byte h0 = 0;
+ byte h1 = 0;
+
+ // if eta >= 1
+ if (eta.compareTo(ECConstants.ONE) >= 0)
+ {
+ if (check1.compareTo(MINUS_ONE) < 0)
+ {
+ h1 = mu;
+ }
+ else
+ {
+ h0 = 1;
+ }
+ }
+ else
+ {
+ // eta < 1
+ if (check2.compareTo(ECConstants.TWO) >= 0)
+ {
+ h1 = mu;
+ }
+ }
+
+ // if eta < -1
+ if (eta.compareTo(MINUS_ONE) < 0)
+ {
+ if (check1.compareTo(ECConstants.ONE) >= 0)
+ {
+ h1 = (byte)-mu;
+ }
+ else
+ {
+ h0 = -1;
+ }
+ }
+ else
+ {
+ // eta >= -1
+ if (check2.compareTo(MINUS_TWO) < 0)
+ {
+ h1 = (byte)-mu;
+ }
+ }
+
+ BigInteger q0 = f0.add(BigInteger.valueOf(h0));
+ BigInteger q1 = f1.add(BigInteger.valueOf(h1));
+ return new ZTauElement(q0, q1);
+ }
+
+ /**
+ * Approximate division by <code>n</code>. For an integer
+ * <code>k</code>, the value <code>&lambda; = s k / n</code> is
+ * computed to <code>c</code> bits of accuracy.
+ * @param k The parameter <code>k</code>.
+ * @param s The curve parameter <code>s<sub>0</sub></code> or
+ * <code>s<sub>1</sub></code>.
+ * @param vm The Lucas Sequence element <code>V<sub>m</sub></code>.
+ * @param a The parameter <code>a</code> of the elliptic curve.
+ * @param m The bit length of the finite field
+ * <code><b>F</b><sub>m</sub></code>.
+ * @param c The number of bits of accuracy, i.e. the scale of the returned
+ * <code>SimpleBigDecimal</code>.
+ * @return The value <code>&lambda; = s k / n</code> computed to
+ * <code>c</code> bits of accuracy.
+ */
+ public static SimpleBigDecimal approximateDivisionByN(BigInteger k,
+ BigInteger s, BigInteger vm, byte a, int m, int c)
+ {
+ int _k = (m + 5)/2 + c;
+ BigInteger ns = k.shiftRight(m - _k - 2 + a);
+
+ BigInteger gs = s.multiply(ns);
+
+ BigInteger hs = gs.shiftRight(m);
+
+ BigInteger js = vm.multiply(hs);
+
+ BigInteger gsPlusJs = gs.add(js);
+ BigInteger ls = gsPlusJs.shiftRight(_k-c);
+ if (gsPlusJs.testBit(_k-c-1))
+ {
+ // round up
+ ls = ls.add(ECConstants.ONE);
+ }
+
+ return new SimpleBigDecimal(ls, c);
+ }
+
+ /**
+ * Computes the <code>&tau;</code>-adic NAF (non-adjacent form) of an
+ * element <code>&lambda;</code> of <code><b>Z</b>[&tau;]</code>.
+ * @param mu The parameter <code>&mu;</code> of the elliptic curve.
+ * @param lambda The element <code>&lambda;</code> of
+ * <code><b>Z</b>[&tau;]</code>.
+ * @return The <code>&tau;</code>-adic NAF of <code>&lambda;</code>.
+ */
+ public static byte[] tauAdicNaf(byte mu, ZTauElement lambda)
+ {
+ if (!((mu == 1) || (mu == -1)))
+ {
+ throw new IllegalArgumentException("mu must be 1 or -1");
+ }
+
+ BigInteger norm = norm(mu, lambda);
+
+ // Ceiling of log2 of the norm
+ int log2Norm = norm.bitLength();
+
+ // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52
+ int maxLength = log2Norm > 30 ? log2Norm + 4 : 34;
+
+ // The array holding the TNAF
+ byte[] u = new byte[maxLength];
+ int i = 0;
+
+ // The actual length of the TNAF
+ int length = 0;
+
+ BigInteger r0 = lambda.u;
+ BigInteger r1 = lambda.v;
+
+ while(!((r0.equals(ECConstants.ZERO)) && (r1.equals(ECConstants.ZERO))))
+ {
+ // If r0 is odd
+ if (r0.testBit(0))
+ {
+ u[i] = (byte) ECConstants.TWO.subtract((r0.subtract(r1.shiftLeft(1))).mod(ECConstants.FOUR)).intValue();
+
+ // r0 = r0 - u[i]
+ if (u[i] == 1)
+ {
+ r0 = r0.clearBit(0);
+ }
+ else
+ {
+ // u[i] == -1
+ r0 = r0.add(ECConstants.ONE);
+ }
+ length = i;
+ }
+ else
+ {
+ u[i] = 0;
+ }
+
+ BigInteger t = r0;
+ BigInteger s = r0.shiftRight(1);
+ if (mu == 1)
+ {
+ r0 = r1.add(s);
+ }
+ else
+ {
+ // mu == -1
+ r0 = r1.subtract(s);
+ }
+
+ r1 = t.shiftRight(1).negate();
+ i++;
+ }
+
+ length++;
+
+ // Reduce the TNAF array to its actual length
+ byte[] tnaf = new byte[length];
+ System.arraycopy(u, 0, tnaf, 0, length);
+ return tnaf;
+ }
+
+ /**
+ * Applies the operation <code>&tau;()</code> to an
+ * <code>ECPoint.F2m</code>.
+ * @param p The ECPoint.F2m to which <code>&tau;()</code> is applied.
+ * @return <code>&tau;(p)</code>
+ */
+ public static ECPoint.F2m tau(ECPoint.F2m p)
+ {
+ return p.tau();
+ }
+
+ /**
+ * Returns the parameter <code>&mu;</code> of the elliptic curve.
+ * @param curve The elliptic curve from which to obtain <code>&mu;</code>.
+ * The curve must be a Koblitz curve, i.e. <code>a</code> equals
+ * <code>0</code> or <code>1</code> and <code>b</code> equals
+ * <code>1</code>.
+ * @return <code>&mu;</code> of the elliptic curve.
+ * @throws IllegalArgumentException if the given ECCurve is not a Koblitz
+ * curve.
+ */
+ public static byte getMu(ECCurve.F2m curve)
+ {
+ if (!curve.isKoblitz())
+ {
+ throw new IllegalArgumentException("No Koblitz curve (ABC), TNAF multiplication not possible");
+ }
+
+ if (curve.getA().isZero())
+ {
+ return -1;
+ }
+
+ return 1;
+ }
+
+ /**
+ * Calculates the Lucas Sequence elements <code>U<sub>k-1</sub></code> and
+ * <code>U<sub>k</sub></code> or <code>V<sub>k-1</sub></code> and
+ * <code>V<sub>k</sub></code>.
+ * @param mu The parameter <code>&mu;</code> of the elliptic curve.
+ * @param k The index of the second element of the Lucas Sequence to be
+ * returned.
+ * @param doV If set to true, computes <code>V<sub>k-1</sub></code> and
+ * <code>V<sub>k</sub></code>, otherwise <code>U<sub>k-1</sub></code> and
+ * <code>U<sub>k</sub></code>.
+ * @return An array with 2 elements, containing <code>U<sub>k-1</sub></code>
+ * and <code>U<sub>k</sub></code> or <code>V<sub>k-1</sub></code>
+ * and <code>V<sub>k</sub></code>.
+ */
+ public static BigInteger[] getLucas(byte mu, int k, boolean doV)
+ {
+ if (!((mu == 1) || (mu == -1)))
+ {
+ throw new IllegalArgumentException("mu must be 1 or -1");
+ }
+
+ BigInteger u0;
+ BigInteger u1;
+ BigInteger u2;
+
+ if (doV)
+ {
+ u0 = ECConstants.TWO;
+ u1 = BigInteger.valueOf(mu);
+ }
+ else
+ {
+ u0 = ECConstants.ZERO;
+ u1 = ECConstants.ONE;
+ }
+
+ for (int i = 1; i < k; i++)
+ {
+ // u2 = mu*u1 - 2*u0;
+ BigInteger s = null;
+ if (mu == 1)
+ {
+ s = u1;
+ }
+ else
+ {
+ // mu == -1
+ s = u1.negate();
+ }
+
+ u2 = s.subtract(u0.shiftLeft(1));
+ u0 = u1;
+ u1 = u2;
+// System.out.println(i + ": " + u2);
+// System.out.println();
+ }
+
+ BigInteger[] retVal = {u0, u1};
+ return retVal;
+ }
+
+ /**
+ * Computes the auxiliary value <code>t<sub>w</sub></code>. If the width is
+ * 4, then for <code>mu = 1</code>, <code>t<sub>w</sub> = 6</code> and for
+ * <code>mu = -1</code>, <code>t<sub>w</sub> = 10</code>
+ * @param mu The parameter <code>&mu;</code> of the elliptic curve.
+ * @param w The window width of the WTNAF.
+ * @return the auxiliary value <code>t<sub>w</sub></code>
+ */
+ public static BigInteger getTw(byte mu, int w)
+ {
+ if (w == 4)
+ {
+ if (mu == 1)
+ {
+ return BigInteger.valueOf(6);
+ }
+ else
+ {
+ // mu == -1
+ return BigInteger.valueOf(10);
+ }
+ }
+ else
+ {
+ // For w <> 4, the values must be computed
+ BigInteger[] us = getLucas(mu, w, false);
+ BigInteger twoToW = ECConstants.ZERO.setBit(w);
+ BigInteger u1invert = us[1].modInverse(twoToW);
+ BigInteger tw;
+ tw = ECConstants.TWO.multiply(us[0]).multiply(u1invert).mod(twoToW);
+// System.out.println("mu = " + mu);
+// System.out.println("tw = " + tw);
+ return tw;
+ }
+ }
+
+ /**
+ * Computes the auxiliary values <code>s<sub>0</sub></code> and
+ * <code>s<sub>1</sub></code> used for partial modular reduction.
+ * @param curve The elliptic curve for which to compute
+ * <code>s<sub>0</sub></code> and <code>s<sub>1</sub></code>.
+ * @throws IllegalArgumentException if <code>curve</code> is not a
+ * Koblitz curve (Anomalous Binary Curve, ABC).
+ */
+ public static BigInteger[] getSi(ECCurve.F2m curve)
+ {
+ if (!curve.isKoblitz())
+ {
+ throw new IllegalArgumentException("si is defined for Koblitz curves only");
+ }
+
+ int m = curve.getM();
+ int a = curve.getA().toBigInteger().intValue();
+ byte mu = curve.getMu();
+ int shifts = getShiftsForCofactor(curve.getCofactor());
+ int index = m + 3 - a;
+ BigInteger[] ui = getLucas(mu, index, false);
+ if (mu == 1)
+ {
+ ui[0] = ui[0].negate();
+ ui[1] = ui[1].negate();
+ }
+
+ BigInteger dividend0 = ECConstants.ONE.add(ui[1]).shiftRight(shifts);
+ BigInteger dividend1 = ECConstants.ONE.add(ui[0]).shiftRight(shifts).negate();
+
+ return new BigInteger[] { dividend0, dividend1 };
+ }
+
+ protected static int getShiftsForCofactor(BigInteger h)
+ {
+ if (h != null)
+ {
+ if (h.equals(ECConstants.TWO))
+ {
+ return 1;
+ }
+ if (h.equals(ECConstants.FOUR))
+ {
+ return 2;
+ }
+ }
+
+ throw new IllegalArgumentException("h (Cofactor) must be 2 or 4");
+ }
+
+ /**
+ * Partial modular reduction modulo
+ * <code>(&tau;<sup>m</sup> - 1)/(&tau; - 1)</code>.
+ * @param k The integer to be reduced.
+ * @param m The bitlength of the underlying finite field.
+ * @param a The parameter <code>a</code> of the elliptic curve.
+ * @param s The auxiliary values <code>s<sub>0</sub></code> and
+ * <code>s<sub>1</sub></code>.
+ * @param mu The parameter &mu; of the elliptic curve.
+ * @param c The precision (number of bits of accuracy) of the partial
+ * modular reduction.
+ * @return <code>&rho; := k partmod (&tau;<sup>m</sup> - 1)/(&tau; - 1)</code>
+ */
+ public static ZTauElement partModReduction(BigInteger k, int m, byte a,
+ BigInteger[] s, byte mu, byte c)
+ {
+ // d0 = s[0] + mu*s[1]; mu is either 1 or -1
+ BigInteger d0;
+ if (mu == 1)
+ {
+ d0 = s[0].add(s[1]);
+ }
+ else
+ {
+ d0 = s[0].subtract(s[1]);
+ }
+
+ BigInteger[] v = getLucas(mu, m, true);
+ BigInteger vm = v[1];
+
+ SimpleBigDecimal lambda0 = approximateDivisionByN(
+ k, s[0], vm, a, m, c);
+
+ SimpleBigDecimal lambda1 = approximateDivisionByN(
+ k, s[1], vm, a, m, c);
+
+ ZTauElement q = round(lambda0, lambda1, mu);
+
+ // r0 = n - d0*q0 - 2*s1*q1
+ BigInteger r0 = k.subtract(d0.multiply(q.u)).subtract(
+ BigInteger.valueOf(2).multiply(s[1]).multiply(q.v));
+
+ // r1 = s1*q0 - s0*q1
+ BigInteger r1 = s[1].multiply(q.u).subtract(s[0].multiply(q.v));
+
+ return new ZTauElement(r0, r1);
+ }
+
+ /**
+ * Multiplies a {@link org.spongycastle.math.ec.ECPoint.F2m ECPoint.F2m}
+ * by a <code>BigInteger</code> using the reduced <code>&tau;</code>-adic
+ * NAF (RTNAF) method.
+ * @param p The ECPoint.F2m to multiply.
+ * @param k The <code>BigInteger</code> by which to multiply <code>p</code>.
+ * @return <code>k * p</code>
+ */
+ public static ECPoint.F2m multiplyRTnaf(ECPoint.F2m p, BigInteger k)
+ {
+ ECCurve.F2m curve = (ECCurve.F2m) p.getCurve();
+ int m = curve.getM();
+ byte a = (byte) curve.getA().toBigInteger().intValue();
+ byte mu = curve.getMu();
+ BigInteger[] s = curve.getSi();
+ ZTauElement rho = partModReduction(k, m, a, s, mu, (byte)10);
+
+ return multiplyTnaf(p, rho);
+ }
+
+ /**
+ * Multiplies a {@link org.spongycastle.math.ec.ECPoint.F2m ECPoint.F2m}
+ * by an element <code>&lambda;</code> of <code><b>Z</b>[&tau;]</code>
+ * using the <code>&tau;</code>-adic NAF (TNAF) method.
+ * @param p The ECPoint.F2m to multiply.
+ * @param lambda The element <code>&lambda;</code> of
+ * <code><b>Z</b>[&tau;]</code>.
+ * @return <code>&lambda; * p</code>
+ */
+ public static ECPoint.F2m multiplyTnaf(ECPoint.F2m p, ZTauElement lambda)
+ {
+ ECCurve.F2m curve = (ECCurve.F2m)p.getCurve();
+ byte mu = curve.getMu();
+ byte[] u = tauAdicNaf(mu, lambda);
+
+ ECPoint.F2m q = multiplyFromTnaf(p, u);
+
+ return q;
+ }
+
+ /**
+ * Multiplies a {@link org.spongycastle.math.ec.ECPoint.F2m ECPoint.F2m}
+ * by an element <code>&lambda;</code> of <code><b>Z</b>[&tau;]</code>
+ * using the <code>&tau;</code>-adic NAF (TNAF) method, given the TNAF
+ * of <code>&lambda;</code>.
+ * @param p The ECPoint.F2m to multiply.
+ * @param u The the TNAF of <code>&lambda;</code>..
+ * @return <code>&lambda; * p</code>
+ */
+ public static ECPoint.F2m multiplyFromTnaf(ECPoint.F2m p, byte[] u)
+ {
+ ECCurve.F2m curve = (ECCurve.F2m)p.getCurve();
+ ECPoint.F2m q = (ECPoint.F2m) curve.getInfinity();
+ for (int i = u.length - 1; i >= 0; i--)
+ {
+ q = tau(q);
+ if (u[i] == 1)
+ {
+ q = (ECPoint.F2m)q.addSimple(p);
+ }
+ else if (u[i] == -1)
+ {
+ q = (ECPoint.F2m)q.subtractSimple(p);
+ }
+ }
+ return q;
+ }
+
+ /**
+ * Computes the <code>[&tau;]</code>-adic window NAF of an element
+ * <code>&lambda;</code> of <code><b>Z</b>[&tau;]</code>.
+ * @param mu The parameter &mu; of the elliptic curve.
+ * @param lambda The element <code>&lambda;</code> of
+ * <code><b>Z</b>[&tau;]</code> of which to compute the
+ * <code>[&tau;]</code>-adic NAF.
+ * @param width The window width of the resulting WNAF.
+ * @param pow2w 2<sup>width</sup>.
+ * @param tw The auxiliary value <code>t<sub>w</sub></code>.
+ * @param alpha The <code>&alpha;<sub>u</sub></code>'s for the window width.
+ * @return The <code>[&tau;]</code>-adic window NAF of
+ * <code>&lambda;</code>.
+ */
+ public static byte[] tauAdicWNaf(byte mu, ZTauElement lambda,
+ byte width, BigInteger pow2w, BigInteger tw, ZTauElement[] alpha)
+ {
+ if (!((mu == 1) || (mu == -1)))
+ {
+ throw new IllegalArgumentException("mu must be 1 or -1");
+ }
+
+ BigInteger norm = norm(mu, lambda);
+
+ // Ceiling of log2 of the norm
+ int log2Norm = norm.bitLength();
+
+ // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52
+ int maxLength = log2Norm > 30 ? log2Norm + 4 + width : 34 + width;
+
+ // The array holding the TNAF
+ byte[] u = new byte[maxLength];
+
+ // 2^(width - 1)
+ BigInteger pow2wMin1 = pow2w.shiftRight(1);
+
+ // Split lambda into two BigIntegers to simplify calculations
+ BigInteger r0 = lambda.u;
+ BigInteger r1 = lambda.v;
+ int i = 0;
+
+ // while lambda <> (0, 0)
+ while (!((r0.equals(ECConstants.ZERO))&&(r1.equals(ECConstants.ZERO))))
+ {
+ // if r0 is odd
+ if (r0.testBit(0))
+ {
+ // uUnMod = r0 + r1*tw mod 2^width
+ BigInteger uUnMod
+ = r0.add(r1.multiply(tw)).mod(pow2w);
+
+ byte uLocal;
+ // if uUnMod >= 2^(width - 1)
+ if (uUnMod.compareTo(pow2wMin1) >= 0)
+ {
+ uLocal = (byte) uUnMod.subtract(pow2w).intValue();
+ }
+ else
+ {
+ uLocal = (byte) uUnMod.intValue();
+ }
+ // uLocal is now in [-2^(width-1), 2^(width-1)-1]
+
+ u[i] = uLocal;
+ boolean s = true;
+ if (uLocal < 0)
+ {
+ s = false;
+ uLocal = (byte)-uLocal;
+ }
+ // uLocal is now >= 0
+
+ if (s)
+ {
+ r0 = r0.subtract(alpha[uLocal].u);
+ r1 = r1.subtract(alpha[uLocal].v);
+ }
+ else
+ {
+ r0 = r0.add(alpha[uLocal].u);
+ r1 = r1.add(alpha[uLocal].v);
+ }
+ }
+ else
+ {
+ u[i] = 0;
+ }
+
+ BigInteger t = r0;
+
+ if (mu == 1)
+ {
+ r0 = r1.add(r0.shiftRight(1));
+ }
+ else
+ {
+ // mu == -1
+ r0 = r1.subtract(r0.shiftRight(1));
+ }
+ r1 = t.shiftRight(1).negate();
+ i++;
+ }
+ return u;
+ }
+
+ /**
+ * Does the precomputation for WTNAF multiplication.
+ * @param p The <code>ECPoint</code> for which to do the precomputation.
+ * @param a The parameter <code>a</code> of the elliptic curve.
+ * @return The precomputation array for <code>p</code>.
+ */
+ public static ECPoint.F2m[] getPreComp(ECPoint.F2m p, byte a)
+ {
+ ECPoint.F2m[] pu;
+ pu = new ECPoint.F2m[16];
+ pu[1] = p;
+ byte[][] alphaTnaf;
+ if (a == 0)
+ {
+ alphaTnaf = Tnaf.alpha0Tnaf;
+ }
+ else
+ {
+ // a == 1
+ alphaTnaf = Tnaf.alpha1Tnaf;
+ }
+
+ int precompLen = alphaTnaf.length;
+ for (int i = 3; i < precompLen; i = i + 2)
+ {
+ pu[i] = Tnaf.multiplyFromTnaf(p, alphaTnaf[i]);
+ }
+
+ p.getCurve().normalizeAll(pu);
+
+ return pu;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/WNafL2RMultiplier.java b/core/src/main/java/org/spongycastle/math/ec/WNafL2RMultiplier.java
new file mode 100644
index 00000000..b9af4da9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/WNafL2RMultiplier.java
@@ -0,0 +1,96 @@
+package org.spongycastle.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: We try to optimize 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;
+
+ // Optimization can only be used for values in the lower half of the table
+ if ((n << 2) < (1 << width))
+ {
+ int highest = LongArray.bitLengths[n];
+
+ // TODO Get addition/doubling cost ratio from curve and compare to 'scale' to see if worth substituting?
+ int scale = width - highest;
+ int lowBits = n ^ (1 << (highest - 1));
+
+ int i1 = ((1 << (width - 1)) - 1);
+ int i2 = (lowBits << scale) + 1;
+ 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/core/src/main/java/org/spongycastle/math/ec/WNafPreCompInfo.java b/core/src/main/java/org/spongycastle/math/ec/WNafPreCompInfo.java
new file mode 100644
index 00000000..2eaea940
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/WNafPreCompInfo.java
@@ -0,0 +1,56 @@
+package org.spongycastle.math.ec;
+
+/**
+ * Class holding precomputation data for the WNAF (Window Non-Adjacent Form)
+ * algorithm.
+ */
+public class WNafPreCompInfo implements PreCompInfo
+{
+ /**
+ * Array holding the precomputed <code>ECPoint</code>s used for a Window
+ * NAF multiplication.
+ */
+ protected ECPoint[] preComp = null;
+
+ /**
+ * Array holding the negations of the precomputed <code>ECPoint</code>s used
+ * for a Window NAF multiplication.
+ */
+ protected ECPoint[] preCompNeg = null;
+
+ /**
+ * Holds an <code>ECPoint</code> representing twice(this). Used for the
+ * Window NAF multiplication to create or extend the precomputed values.
+ */
+ protected ECPoint twice = null;
+
+ public ECPoint[] getPreComp()
+ {
+ return preComp;
+ }
+
+ public void setPreComp(ECPoint[] preComp)
+ {
+ this.preComp = preComp;
+ }
+
+ public ECPoint[] getPreCompNeg()
+ {
+ return preCompNeg;
+ }
+
+ public void setPreCompNeg(ECPoint[] preCompNeg)
+ {
+ this.preCompNeg = preCompNeg;
+ }
+
+ public ECPoint getTwice()
+ {
+ return twice;
+ }
+
+ public void setTwice(ECPoint twice)
+ {
+ this.twice = twice;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/WNafUtil.java b/core/src/main/java/org/spongycastle/math/ec/WNafUtil.java
new file mode 100644
index 00000000..4e0c5869
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/WNafUtil.java
@@ -0,0 +1,485 @@
+package org.spongycastle.math.ec;
+
+import java.math.BigInteger;
+
+public abstract class WNafUtil
+{
+ public static final String PRECOMP_NAME = "bc_wnaf";
+
+ private static final int[] DEFAULT_WINDOW_SIZE_CUTOFFS = new int[]{ 13, 41, 121, 337, 897, 2305 };
+
+ private static final byte[] EMPTY_BYTES = new byte[0];
+ private static final int[] EMPTY_INTS = new int[0];
+
+ public static int[] generateCompactNaf(BigInteger k)
+ {
+ if ((k.bitLength() >>> 16) != 0)
+ {
+ throw new IllegalArgumentException("'k' must have bitlength < 2^16");
+ }
+ if (k.signum() == 0)
+ {
+ return EMPTY_INTS;
+ }
+
+ BigInteger _3k = k.shiftLeft(1).add(k);
+
+ int bits = _3k.bitLength();
+ int[] naf = new int[bits >> 1];
+
+ BigInteger diff = _3k.xor(k);
+
+ int highBit = bits - 1, length = 0, zeroes = 0;
+ for (int i = 1; i < highBit; ++i)
+ {
+ if (!diff.testBit(i))
+ {
+ ++zeroes;
+ continue;
+ }
+
+ int digit = k.testBit(i) ? -1 : 1;
+ naf[length++] = (digit << 16) | zeroes;
+ zeroes = 1;
+ ++i;
+ }
+
+ naf[length++] = (1 << 16) | zeroes;
+
+ if (naf.length > length)
+ {
+ naf = trim(naf, length);
+ }
+
+ 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");
+ }
+ if (k.signum() == 0)
+ {
+ return EMPTY_INTS;
+ }
+
+ 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;
+
+ int offset = 0;
+ while ((d0 | d1) != 0 || k0.bitLength() > offset || k1.bitLength() > offset)
+ {
+ int n0 = ((k0.intValue() >>> offset) + d0) & 7, n1 = ((k1.intValue() >>> offset) + 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;
+ }
+ if ((d1 << 1) == 1 + u1)
+ {
+ d1 ^= 1;
+ }
+
+ if (++offset == 30)
+ {
+ offset = 0;
+ k0 = k0.shiftRight(30);
+ k1 = k1.shiftRight(30);
+ }
+
+ 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)
+ {
+ if (k.signum() == 0)
+ {
+ return EMPTY_BYTES;
+ }
+
+ BigInteger _3k = k.shiftLeft(1).add(k);
+
+ int digits = _3k.bitLength() - 1;
+ byte[] naf = new byte[digits];
+
+ BigInteger diff = _3k.xor(k);
+
+ for (int i = 1; i < digits; ++i)
+ {
+ if (diff.testBit(i))
+ {
+ naf[i - 1] = (byte)(k.testBit(i) ? -1 : 1);
+ ++i;
+ }
+ }
+
+ naf[digits - 1] = 1;
+
+ return naf;
+ }
+
+ /**
+ * 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]");
+ }
+ if (k.signum() == 0)
+ {
+ return EMPTY_BYTES;
+ }
+
+ 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 int getNafWeight(BigInteger k)
+ {
+ if (k.signum() == 0)
+ {
+ return 0;
+ }
+
+ BigInteger _3k = k.shiftLeft(1).add(k);
+ BigInteger diff = _3k.xor(k);
+
+ return diff.bitCount();
+ }
+
+ public static WNafPreCompInfo getWNafPreCompInfo(ECPoint p)
+ {
+ return getWNafPreCompInfo(p.getCurve().getPreCompInfo(p, PRECOMP_NAME));
+ }
+
+ public static WNafPreCompInfo getWNafPreCompInfo(PreCompInfo preCompInfo)
+ {
+ if ((preCompInfo != null) && (preCompInfo instanceof WNafPreCompInfo))
+ {
+ 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 ECPoint mapPointWithPrecomp(ECPoint p, int width, boolean includeNegated,
+ ECPointMap pointMap)
+ {
+ ECCurve c = p.getCurve();
+ WNafPreCompInfo wnafPreCompP = precompute(p, width, includeNegated);
+
+ ECPoint q = pointMap.map(p);
+ WNafPreCompInfo wnafPreCompQ = getWNafPreCompInfo(c.getPreCompInfo(q, PRECOMP_NAME));
+
+ ECPoint twiceP = wnafPreCompP.getTwice();
+ if (twiceP != null)
+ {
+ ECPoint twiceQ = pointMap.map(twiceP);
+ wnafPreCompQ.setTwice(twiceQ);
+ }
+
+ ECPoint[] preCompP = wnafPreCompP.getPreComp();
+ ECPoint[] preCompQ = new ECPoint[preCompP.length];
+ for (int i = 0; i < preCompP.length; ++i)
+ {
+ preCompQ[i] = pointMap.map(preCompP[i]);
+ }
+ wnafPreCompQ.setPreComp(preCompQ);
+
+ if (includeNegated)
+ {
+ ECPoint[] preCompNegQ = new ECPoint[preCompQ.length];
+ for (int i = 0; i < preCompNegQ.length; ++i)
+ {
+ preCompNegQ[i] = preCompQ[i].negate();
+ }
+ wnafPreCompQ.setPreCompNeg(preCompNegQ);
+ }
+
+ c.setPreCompInfo(q, PRECOMP_NAME, wnafPreCompQ);
+
+ return q;
+ }
+
+ public static WNafPreCompInfo precompute(ECPoint p, int width, boolean includeNegated)
+ {
+ ECCurve c = p.getCurve();
+ WNafPreCompInfo wnafPreCompInfo = getWNafPreCompInfo(c.getPreCompInfo(p, PRECOMP_NAME));
+
+ 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)
+ {
+ preComp = resizeTable(preComp, reqPreCompLen);
+ if (reqPreCompLen == 2)
+ {
+ preComp[1] = preComp[0].threeTimes();
+ }
+ else
+ {
+ ECPoint twiceP = wnafPreCompInfo.getTwice();
+ if (twiceP == null)
+ {
+ twiceP = preComp[0].twice();
+ wnafPreCompInfo.setTwice(twiceP);
+ }
+
+ for (int i = preCompLen; i < reqPreCompLen; i++)
+ {
+ /*
+ * Compute the new ECPoints for the precomputation array. The values 1, 3, 5, ...,
+ * 2^(width-1)-1 times p are computed
+ */
+ preComp[i] = twiceP.add(preComp[i - 1]);
+ }
+ }
+
+ /*
+ * 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, PRECOMP_NAME, 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/core/src/main/java/org/spongycastle/math/ec/WTauNafMultiplier.java b/core/src/main/java/org/spongycastle/math/ec/WTauNafMultiplier.java
new file mode 100644
index 00000000..068c252f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/WTauNafMultiplier.java
@@ -0,0 +1,114 @@
+package org.spongycastle.math.ec;
+
+import java.math.BigInteger;
+
+/**
+ * Class implementing the WTNAF (Window
+ * <code>&tau;</code>-adic Non-Adjacent Form) algorithm.
+ */
+public class WTauNafMultiplier extends AbstractECMultiplier
+{
+ // TODO Create WTauNafUtil class and move various functionality into it
+ static final String PRECOMP_NAME = "bc_wtnaf";
+
+ /**
+ * Multiplies a {@link org.spongycastle.math.ec.ECPoint.F2m ECPoint.F2m}
+ * by <code>k</code> using the reduced <code>&tau;</code>-adic NAF (RTNAF)
+ * method.
+ * @param p The ECPoint.F2m to multiply.
+ * @param k The integer by which to multiply <code>k</code>.
+ * @return <code>p</code> multiplied by <code>k</code>.
+ */
+ protected ECPoint multiplyPositive(ECPoint point, BigInteger k)
+ {
+ if (!(point instanceof ECPoint.F2m))
+ {
+ throw new IllegalArgumentException("Only ECPoint.F2m can be " +
+ "used in WTauNafMultiplier");
+ }
+
+ ECPoint.F2m p = (ECPoint.F2m)point;
+ ECCurve.F2m curve = (ECCurve.F2m)p.getCurve();
+ int m = curve.getM();
+ byte a = curve.getA().toBigInteger().byteValue();
+ byte mu = curve.getMu();
+ BigInteger[] s = curve.getSi();
+
+ ZTauElement rho = Tnaf.partModReduction(k, m, a, s, mu, (byte)10);
+
+ return multiplyWTnaf(p, rho, curve.getPreCompInfo(p, PRECOMP_NAME), a, mu);
+ }
+
+ /**
+ * Multiplies a {@link org.spongycastle.math.ec.ECPoint.F2m ECPoint.F2m}
+ * by an element <code>&lambda;</code> of <code><b>Z</b>[&tau;]</code> using
+ * the <code>&tau;</code>-adic NAF (TNAF) method.
+ * @param p The ECPoint.F2m to multiply.
+ * @param lambda The element <code>&lambda;</code> of
+ * <code><b>Z</b>[&tau;]</code> of which to compute the
+ * <code>[&tau;]</code>-adic NAF.
+ * @return <code>p</code> multiplied by <code>&lambda;</code>.
+ */
+ private ECPoint.F2m multiplyWTnaf(ECPoint.F2m p, ZTauElement lambda,
+ PreCompInfo preCompInfo, byte a, byte mu)
+ {
+ ZTauElement[] alpha = (a == 0) ? Tnaf.alpha0 : Tnaf.alpha1;
+
+ BigInteger tw = Tnaf.getTw(mu, Tnaf.WIDTH);
+
+ byte[]u = Tnaf.tauAdicWNaf(mu, lambda, Tnaf.WIDTH,
+ BigInteger.valueOf(Tnaf.POW_2_WIDTH), tw, alpha);
+
+ return multiplyFromWTnaf(p, u, preCompInfo);
+ }
+
+ /**
+ * Multiplies a {@link org.spongycastle.math.ec.ECPoint.F2m ECPoint.F2m}
+ * by an element <code>&lambda;</code> of <code><b>Z</b>[&tau;]</code>
+ * using the window <code>&tau;</code>-adic NAF (TNAF) method, given the
+ * WTNAF of <code>&lambda;</code>.
+ * @param p The ECPoint.F2m to multiply.
+ * @param u The the WTNAF of <code>&lambda;</code>..
+ * @return <code>&lambda; * p</code>
+ */
+ private static ECPoint.F2m multiplyFromWTnaf(ECPoint.F2m p, byte[] u, PreCompInfo preCompInfo)
+ {
+ ECCurve.F2m curve = (ECCurve.F2m)p.getCurve();
+ byte a = curve.getA().toBigInteger().byteValue();
+
+ ECPoint.F2m[] pu;
+ if ((preCompInfo == null) || !(preCompInfo instanceof WTauNafPreCompInfo))
+ {
+ pu = Tnaf.getPreComp(p, a);
+
+ WTauNafPreCompInfo pre = new WTauNafPreCompInfo();
+ pre.setPreComp(pu);
+ curve.setPreCompInfo(p, PRECOMP_NAME, pre);
+ }
+ else
+ {
+ pu = ((WTauNafPreCompInfo)preCompInfo).getPreComp();
+ }
+
+ // q = infinity
+ ECPoint.F2m q = (ECPoint.F2m) p.getCurve().getInfinity();
+ for (int i = u.length - 1; i >= 0; i--)
+ {
+ q = Tnaf.tau(q);
+ byte ui = u[i];
+ if (ui != 0)
+ {
+ if (ui > 0)
+ {
+ q = q.addSimple(pu[ui]);
+ }
+ else
+ {
+ q = q.subtractSimple(pu[-ui]);
+ }
+ }
+ }
+
+ return q;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/WTauNafPreCompInfo.java b/core/src/main/java/org/spongycastle/math/ec/WTauNafPreCompInfo.java
new file mode 100644
index 00000000..ed7d4ceb
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/WTauNafPreCompInfo.java
@@ -0,0 +1,26 @@
+package org.spongycastle.math.ec;
+
+/**
+ * Class holding precomputation data for the WTNAF (Window
+ * <code>&tau;</code>-adic Non-Adjacent Form) algorithm.
+ */
+public class WTauNafPreCompInfo implements PreCompInfo
+{
+ /**
+ * Array holding the precomputed <code>ECPoint.F2m</code>s used for the
+ * WTNAF multiplication in <code>
+ * {@link org.spongycastle.math.ec.multiplier.WTauNafMultiplier.multiply()
+ * WTauNafMultiplier.multiply()}</code>.
+ */
+ protected ECPoint.F2m[] preComp = null;
+
+ public ECPoint.F2m[] getPreComp()
+ {
+ return preComp;
+ }
+
+ public void setPreComp(ECPoint.F2m[] preComp)
+ {
+ this.preComp = preComp;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/ZSignedDigitL2RMultiplier.java b/core/src/main/java/org/spongycastle/math/ec/ZSignedDigitL2RMultiplier.java
new file mode 100644
index 00000000..543bb581
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/ZSignedDigitL2RMultiplier.java
@@ -0,0 +1,29 @@
+package org.spongycastle.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/core/src/main/java/org/spongycastle/math/ec/ZSignedDigitR2LMultiplier.java b/core/src/main/java/org/spongycastle/math/ec/ZSignedDigitR2LMultiplier.java
new file mode 100644
index 00000000..e9147ea7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/ZSignedDigitR2LMultiplier.java
@@ -0,0 +1,30 @@
+package org.spongycastle.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/core/src/main/java/org/spongycastle/math/ec/ZTauElement.java b/core/src/main/java/org/spongycastle/math/ec/ZTauElement.java
new file mode 100644
index 00000000..3fd5e21f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/ZTauElement.java
@@ -0,0 +1,37 @@
+package org.spongycastle.math.ec;
+
+import java.math.BigInteger;
+
+/**
+ * Class representing an element of <code><b>Z</b>[&tau;]</code>. Let
+ * <code>&lambda;</code> be an element of <code><b>Z</b>[&tau;]</code>. Then
+ * <code>&lambda;</code> is given as <code>&lambda; = u + v&tau;</code>. The
+ * components <code>u</code> and <code>v</code> may be used directly, there
+ * are no accessor methods.
+ * Immutable class.
+ */
+class ZTauElement
+{
+ /**
+ * The &quot;real&quot; part of <code>&lambda;</code>.
+ */
+ public final BigInteger u;
+
+ /**
+ * The &quot;<code>&tau;</code>-adic&quot; part of <code>&lambda;</code>.
+ */
+ public final BigInteger v;
+
+ /**
+ * Constructor for an element <code>&lambda;</code> of
+ * <code><b>Z</b>[&tau;]</code>.
+ * @param u The &quot;real&quot; part of <code>&lambda;</code>.
+ * @param v The &quot;<code>&tau;</code>-adic&quot; part of
+ * <code>&lambda;</code>.
+ */
+ public ZTauElement(BigInteger u, BigInteger v)
+ {
+ this.u = u;
+ this.v = v;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519.java b/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519.java
new file mode 100644
index 00000000..c7d77397
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519.java
@@ -0,0 +1,80 @@
+package org.spongycastle.math.ec.custom.djb;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.raw.Nat256;
+import org.spongycastle.util.encoders.Hex;
+
+public class Curve25519 extends ECCurve.AbstractFp
+{
+ public static final BigInteger q = Nat256.toBigInteger(Curve25519Field.P);
+
+ private static final int Curve25519_DEFAULT_COORDS = COORD_JACOBIAN_MODIFIED;
+
+ protected Curve25519Point infinity;
+
+ public Curve25519()
+ {
+ super(q);
+
+ this.infinity = new Curve25519Point(this, null, null);
+
+ this.a = fromBigInteger(new BigInteger(1,
+ Hex.decode("2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA984914A144")));
+ this.b = fromBigInteger(new BigInteger(1,
+ Hex.decode("7B425ED097B425ED097B425ED097B425ED097B425ED097B4260B5E9C7710C864")));
+ this.order = new BigInteger(1, Hex.decode("1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED"));
+ this.cofactor = BigInteger.valueOf(8);
+
+ this.coord = Curve25519_DEFAULT_COORDS;
+ }
+
+ protected ECCurve cloneCurve()
+ {
+ return new Curve25519();
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_JACOBIAN_MODIFIED:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public int getFieldSize()
+ {
+ return q.bitLength();
+ }
+
+ public ECFieldElement fromBigInteger(BigInteger x)
+ {
+ return new Curve25519FieldElement(x);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ return new Curve25519Point(this, x, y, withCompression);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ return new Curve25519Point(this, x, y, zs, withCompression);
+ }
+
+ public ECPoint getInfinity()
+ {
+ return infinity;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519Field.java b/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519Field.java
new file mode 100644
index 00000000..2fe484e1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519Field.java
@@ -0,0 +1,254 @@
+package org.spongycastle.math.ec.custom.djb;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.raw.Nat;
+import org.spongycastle.math.raw.Nat256;
+
+public class Curve25519Field
+{
+ private static final long M = 0xFFFFFFFFL;
+
+ // 2^255 - 2^4 - 2^1 - 1
+ static final int[] P = new int[]{ 0xFFFFFFED, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0x7FFFFFFF };
+ private static final int P7 = 0x7FFFFFFF;
+ private static final int[] PExt = new int[]{ 0x00000169, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFED, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0x3FFFFFFF };
+ private static final int PInv = 0x13;
+
+ public static void add(int[] x, int[] y, int[] z)
+ {
+ Nat256.add(x, y, z);
+ if (Nat256.gte(z, P))
+ {
+ subPFrom(z);
+ }
+ }
+
+ public static void addExt(int[] xx, int[] yy, int[] zz)
+ {
+ Nat.add(16, xx, yy, zz);
+ if (Nat.gte(16, zz, PExt))
+ {
+ subPExtFrom(zz);
+ }
+ }
+
+ public static void addOne(int[] x, int[] z)
+ {
+ Nat.inc(8, x, z);
+ if (Nat256.gte(z, P))
+ {
+ subPFrom(z);
+ }
+ }
+
+ public static int[] fromBigInteger(BigInteger x)
+ {
+ int[] z = Nat256.fromBigInteger(x);
+ while (Nat256.gte(z, P))
+ {
+ Nat256.subFrom(P, z);
+ }
+ return z;
+ }
+
+ public static void half(int[] x, int[] z)
+ {
+ if ((x[0] & 1) == 0)
+ {
+ Nat.shiftDownBit(8, x, 0, z);
+ }
+ else
+ {
+ Nat256.add(x, P, z);
+ Nat.shiftDownBit(8, z, 0);
+ }
+ }
+
+ public static void multiply(int[] x, int[] y, int[] z)
+ {
+ int[] tt = Nat256.createExt();
+ Nat256.mul(x, y, tt);
+ reduce(tt, z);
+ }
+
+ public static void multiplyAddToExt(int[] x, int[] y, int[] zz)
+ {
+ Nat256.mulAddTo(x, y, zz);
+ if (Nat.gte(16, zz, PExt))
+ {
+ subPExtFrom(zz);
+ }
+ }
+
+ public static void negate(int[] x, int[] z)
+ {
+ if (Nat256.isZero(x))
+ {
+ Nat256.zero(z);
+ }
+ else
+ {
+ Nat256.sub(P, x, z);
+ }
+ }
+
+ public static void reduce(int[] xx, int[] z)
+ {
+// assert xx[15] >>> 30 == 0;
+
+ int xx07 = xx[7];
+ Nat.shiftUpBit(8, xx, 8, xx07, z, 0);
+ int c = Nat256.mulByWordAddTo(PInv, xx, z) << 1;
+ int z7 = z[7];
+ c += (z7 >>> 31) - (xx07 >>> 31);
+ z7 &= P7;
+ z7 += Nat.addWordTo(7, c * PInv, z);
+ z[7] = z7;
+ if (Nat256.gte(z, P))
+ {
+ subPFrom(z);
+ }
+ }
+
+ public static void reduce27(int x, int[] z)
+ {
+// assert x >>> 26 == 0;
+
+ int z7 = z[7];
+ int c = (x << 1 | z7 >>> 31);
+ z7 &= P7;
+ z7 += Nat.addWordTo(7, c * PInv, z);
+ z[7] = z7;
+ if (Nat256.gte(z, P))
+ {
+ subPFrom(z);
+ }
+ }
+
+ public static void square(int[] x, int[] z)
+ {
+ int[] tt = Nat256.createExt();
+ Nat256.square(x, tt);
+ reduce(tt, z);
+ }
+
+ public static void squareN(int[] x, int n, int[] z)
+ {
+// assert n > 0;
+
+ int[] tt = Nat256.createExt();
+ Nat256.square(x, tt);
+ reduce(tt, z);
+
+ while (--n > 0)
+ {
+ Nat256.square(z, tt);
+ reduce(tt, z);
+ }
+ }
+
+ public static void subtract(int[] x, int[] y, int[] z)
+ {
+ int c = Nat256.sub(x, y, z);
+ if (c != 0)
+ {
+ addPTo(z);
+ }
+ }
+
+ public static void subtractExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.sub(16, xx, yy, zz);
+ if (c != 0)
+ {
+ addPExtTo(zz);
+ }
+ }
+
+ public static void twice(int[] x, int[] z)
+ {
+ Nat.shiftUpBit(8, x, 0, z);
+ if (Nat256.gte(z, P))
+ {
+ subPFrom(z);
+ }
+ }
+
+ private static int addPTo(int[] z)
+ {
+ long c = (z[0] & M) - PInv;
+ z[0] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c = Nat.decAt(7, z, 1);
+ }
+ c += (z[7] & M) + ((P7 + 1) & M);
+ z[7] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ private static int addPExtTo(int[] zz)
+ {
+ long c = (zz[0] & M) + (PExt[0] & M);
+ zz[0] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c = Nat.incAt(8, zz, 1);
+ }
+ c += (zz[8] & M) - PInv;
+ zz[8] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c = Nat.decAt(15, zz, 9);
+ }
+ c += (zz[15] & M) + ((PExt[15] + 1) & M);
+ zz[15] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ private static int subPFrom(int[] z)
+ {
+ long c = (z[0] & M) + PInv;
+ z[0] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c = Nat.incAt(7, z, 1);
+ }
+ c += (z[7] & M) - ((P7 + 1) & M);
+ z[7] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ private static int subPExtFrom(int[] zz)
+ {
+ long c = (zz[0] & M) - (PExt[0] & M);
+ zz[0] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c = Nat.decAt(8, zz, 1);
+ }
+ c += (zz[8] & M) + PInv;
+ zz[8] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c = Nat.incAt(15, zz, 9);
+ }
+ c += (zz[15] & M) - ((PExt[15] + 1) & M);
+ zz[15] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519FieldElement.java b/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519FieldElement.java
new file mode 100644
index 00000000..a5d5cb7b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519FieldElement.java
@@ -0,0 +1,234 @@
+package org.spongycastle.math.ec.custom.djb;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.raw.Mod;
+import org.spongycastle.math.raw.Nat256;
+import org.spongycastle.util.Arrays;
+
+public class Curve25519FieldElement extends ECFieldElement
+{
+ public static final BigInteger Q = Curve25519.q;
+
+ // Calculated as ECConstants.TWO.modPow(Q.shiftRight(2), Q)
+ private static final int[] PRECOMP_POW2 = new int[]{ 0x4a0ea0b0, 0xc4ee1b27, 0xad2fe478, 0x2f431806,
+ 0x3dfbd7a7, 0x2b4d0099, 0x4fc1df0b, 0x2b832480 };
+
+ protected int[] x;
+
+ public Curve25519FieldElement(BigInteger x)
+ {
+ if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
+ {
+ throw new IllegalArgumentException("x value invalid for Curve25519FieldElement");
+ }
+
+ this.x = Curve25519Field.fromBigInteger(x);
+ }
+
+ public Curve25519FieldElement()
+ {
+ this.x = Nat256.create();
+ }
+
+ protected Curve25519FieldElement(int[] x)
+ {
+ this.x = x;
+ }
+
+ public boolean isZero()
+ {
+ return Nat256.isZero(x);
+ }
+
+ public boolean isOne()
+ {
+ return Nat256.isOne(x);
+ }
+
+ public boolean testBitZero()
+ {
+ return Nat256.getBit(x, 0) == 1;
+ }
+
+ public BigInteger toBigInteger()
+ {
+ return Nat256.toBigInteger(x);
+ }
+
+ public String getFieldName()
+ {
+ return "Curve25519Field";
+ }
+
+ public int getFieldSize()
+ {
+ return Q.bitLength();
+ }
+
+ public ECFieldElement add(ECFieldElement b)
+ {
+ int[] z = Nat256.create();
+ Curve25519Field.add(x, ((Curve25519FieldElement)b).x, z);
+ return new Curve25519FieldElement(z);
+ }
+
+ public ECFieldElement addOne()
+ {
+ int[] z = Nat256.create();
+ Curve25519Field.addOne(x, z);
+ return new Curve25519FieldElement(z);
+ }
+
+ public ECFieldElement subtract(ECFieldElement b)
+ {
+ int[] z = Nat256.create();
+ Curve25519Field.subtract(x, ((Curve25519FieldElement)b).x, z);
+ return new Curve25519FieldElement(z);
+ }
+
+ public ECFieldElement multiply(ECFieldElement b)
+ {
+ int[] z = Nat256.create();
+ Curve25519Field.multiply(x, ((Curve25519FieldElement)b).x, z);
+ return new Curve25519FieldElement(z);
+ }
+
+ public ECFieldElement divide(ECFieldElement b)
+ {
+// return multiply(b.invert());
+ int[] z = Nat256.create();
+ Mod.invert(Curve25519Field.P, ((Curve25519FieldElement)b).x, z);
+ Curve25519Field.multiply(z, x, z);
+ return new Curve25519FieldElement(z);
+ }
+
+ public ECFieldElement negate()
+ {
+ int[] z = Nat256.create();
+ Curve25519Field.negate(x, z);
+ return new Curve25519FieldElement(z);
+ }
+
+ public ECFieldElement square()
+ {
+ int[] z = Nat256.create();
+ Curve25519Field.square(x, z);
+ return new Curve25519FieldElement(z);
+ }
+
+ public ECFieldElement invert()
+ {
+// return new Curve25519FieldElement(toBigInteger().modInverse(Q));
+ int[] z = Nat256.create();
+ Mod.invert(Curve25519Field.P, x, z);
+ return new Curve25519FieldElement(z);
+ }
+
+ /**
+ * return a sqrt root - the routine verifies that the calculation returns the right value - if
+ * none exists it returns null.
+ */
+ public ECFieldElement sqrt()
+ {
+ /*
+ * Q == 8m + 5, so we use Pocklington's method for this case.
+ *
+ * First, raise this element to the exponent 2^252 - 2^1 (i.e. m + 1)
+ *
+ * Breaking up the exponent's binary representation into "repunits", we get:
+ * { 251 1s } { 1 0s }
+ *
+ * Therefore we need an addition chain containing 251 (the lengths of the repunits)
+ * We use: 1, 2, 3, 4, 7, 11, 15, 30, 60, 120, 131, [251]
+ */
+
+ int[] x1 = this.x;
+ if (Nat256.isZero(x1) || Nat256.isOne(x1))
+ {
+ return this;
+ }
+
+ int[] x2 = Nat256.create();
+ Curve25519Field.square(x1, x2);
+ Curve25519Field.multiply(x2, x1, x2);
+ int[] x3 = x2;
+ Curve25519Field.square(x2, x3);
+ Curve25519Field.multiply(x3, x1, x3);
+ int[] x4 = Nat256.create();
+ Curve25519Field.square(x3, x4);
+ Curve25519Field.multiply(x4, x1, x4);
+ int[] x7 = Nat256.create();
+ Curve25519Field.squareN(x4, 3, x7);
+ Curve25519Field.multiply(x7, x3, x7);
+ int[] x11 = x3;
+ Curve25519Field.squareN(x7, 4, x11);
+ Curve25519Field.multiply(x11, x4, x11);
+ int[] x15 = x7;
+ Curve25519Field.squareN(x11, 4, x15);
+ Curve25519Field.multiply(x15, x4, x15);
+ int[] x30 = x4;
+ Curve25519Field.squareN(x15, 15, x30);
+ Curve25519Field.multiply(x30, x15, x30);
+ int[] x60 = x15;
+ Curve25519Field.squareN(x30, 30, x60);
+ Curve25519Field.multiply(x60, x30, x60);
+ int[] x120 = x30;
+ Curve25519Field.squareN(x60, 60, x120);
+ Curve25519Field.multiply(x120, x60, x120);
+ int[] x131 = x60;
+ Curve25519Field.squareN(x120, 11, x131);
+ Curve25519Field.multiply(x131, x11, x131);
+ int[] x251 = x11;
+ Curve25519Field.squareN(x131, 120, x251);
+ Curve25519Field.multiply(x251, x120, x251);
+
+ int[] t1 = x251;
+ Curve25519Field.square(t1, t1);
+
+ int[] t2 = x120;
+ Curve25519Field.square(t1, t2);
+
+ if (Nat256.eq(x1, t2))
+ {
+ return new Curve25519FieldElement(t1);
+ }
+
+ /*
+ * If the first guess is incorrect, we multiply by a precomputed power of 2 to get the second guess,
+ * which is ((4x)^(m + 1))/2 mod Q
+ */
+ Curve25519Field.multiply(t1, PRECOMP_POW2, t1);
+
+ Curve25519Field.square(t1, t2);
+
+ if (Nat256.eq(x1, t2))
+ {
+ return new Curve25519FieldElement(t1);
+ }
+
+ return null;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other == this)
+ {
+ return true;
+ }
+
+ if (!(other instanceof Curve25519FieldElement))
+ {
+ return false;
+ }
+
+ Curve25519FieldElement o = (Curve25519FieldElement)other;
+ return Nat256.eq(x, o.x);
+ }
+
+ public int hashCode()
+ {
+ return Q.hashCode() ^ Arrays.hashCode(x, 0, 8);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519Point.java b/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519Point.java
new file mode 100644
index 00000000..a8b98a93
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519Point.java
@@ -0,0 +1,348 @@
+package org.spongycastle.math.ec.custom.djb;
+
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.raw.Nat256;
+
+public class Curve25519Point extends ECPoint.AbstractFp
+{
+ /**
+ * Create a point which encodes with point compression.
+ *
+ * @param curve the curve to use
+ * @param x affine x co-ordinate
+ * @param y affine y co-ordinate
+ *
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public Curve25519Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ this(curve, x, y, false);
+ }
+
+ /**
+ * Create a point that encodes with or without point compresion.
+ *
+ * @param curve the curve to use
+ * @param x affine x co-ordinate
+ * @param y affine y co-ordinate
+ * @param withCompression if true encode with point compression
+ *
+ * @deprecated per-point compression property will be removed, refer {@link #getEncoded(boolean)}
+ */
+ public Curve25519Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ super(curve, x, y);
+
+ if ((x == null) != (y == null))
+ {
+ throw new IllegalArgumentException("Exactly one of the field elements is null");
+ }
+
+ this.withCompression = withCompression;
+ }
+
+ Curve25519Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ super(curve, x, y, zs);
+
+ this.withCompression = withCompression;
+ }
+
+ protected ECPoint detach()
+ {
+ return new Curve25519Point(null, getAffineXCoord(), getAffineYCoord());
+ }
+
+ public ECFieldElement getZCoord(int index)
+ {
+ if (index == 1)
+ {
+ return getJacobianModifiedW();
+ }
+
+ return super.getZCoord(index);
+ }
+
+ public ECPoint add(ECPoint b)
+ {
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return this;
+ }
+ if (this == b)
+ {
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+
+ Curve25519FieldElement X1 = (Curve25519FieldElement)this.x, Y1 = (Curve25519FieldElement)this.y,
+ Z1 = (Curve25519FieldElement)this.zs[0];
+ Curve25519FieldElement X2 = (Curve25519FieldElement)b.getXCoord(), Y2 = (Curve25519FieldElement)b.getYCoord(),
+ Z2 = (Curve25519FieldElement)b.getZCoord(0);
+
+ int c;
+ int[] tt1 = Nat256.createExt();
+ int[] t2 = Nat256.create();
+ int[] t3 = Nat256.create();
+ int[] t4 = Nat256.create();
+
+ boolean Z1IsOne = Z1.isOne();
+ int[] U2, S2;
+ if (Z1IsOne)
+ {
+ U2 = X2.x;
+ S2 = Y2.x;
+ }
+ else
+ {
+ S2 = t3;
+ Curve25519Field.square(Z1.x, S2);
+
+ U2 = t2;
+ Curve25519Field.multiply(S2, X2.x, U2);
+
+ Curve25519Field.multiply(S2, Z1.x, S2);
+ Curve25519Field.multiply(S2, Y2.x, S2);
+ }
+
+ boolean Z2IsOne = Z2.isOne();
+ int[] U1, S1;
+ if (Z2IsOne)
+ {
+ U1 = X1.x;
+ S1 = Y1.x;
+ }
+ else
+ {
+ S1 = t4;
+ Curve25519Field.square(Z2.x, S1);
+
+ U1 = tt1;
+ Curve25519Field.multiply(S1, X1.x, U1);
+
+ Curve25519Field.multiply(S1, Z2.x, S1);
+ Curve25519Field.multiply(S1, Y1.x, S1);
+ }
+
+ int[] H = Nat256.create();
+ Curve25519Field.subtract(U1, U2, H);
+
+ int[] R = t2;
+ Curve25519Field.subtract(S1, S2, R);
+
+ // Check if b == this or b == -this
+ if (Nat256.isZero(H))
+ {
+ if (Nat256.isZero(R))
+ {
+ // this == b, i.e. this must be doubled
+ return this.twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.getInfinity();
+ }
+
+ int[] HSquared = Nat256.create();
+ Curve25519Field.square(H, HSquared);
+
+ int[] G = Nat256.create();
+ Curve25519Field.multiply(HSquared, H, G);
+
+ int[] V = t3;
+ Curve25519Field.multiply(HSquared, U1, V);
+
+ Curve25519Field.negate(G, G);
+ Nat256.mul(S1, G, tt1);
+
+ c = Nat256.addBothTo(V, V, G);
+ Curve25519Field.reduce27(c, G);
+
+ Curve25519FieldElement X3 = new Curve25519FieldElement(t4);
+ Curve25519Field.square(R, X3.x);
+ Curve25519Field.subtract(X3.x, G, X3.x);
+
+ Curve25519FieldElement Y3 = new Curve25519FieldElement(G);
+ Curve25519Field.subtract(V, X3.x, Y3.x);
+ Curve25519Field.multiplyAddToExt(Y3.x, R, tt1);
+ Curve25519Field.reduce(tt1, Y3.x);
+
+ Curve25519FieldElement Z3 = new Curve25519FieldElement(H);
+ if (!Z1IsOne)
+ {
+ Curve25519Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+ if (!Z2IsOne)
+ {
+ Curve25519Field.multiply(Z3.x, Z2.x, Z3.x);
+ }
+
+ int[] Z3Squared = (Z1IsOne && Z2IsOne) ? HSquared : null;
+
+ // TODO If the result will only be used in a subsequent addition, we don't need W3
+ Curve25519FieldElement W3 = calculateJacobianModifiedW((Curve25519FieldElement)Z3, Z3Squared);
+
+ ECFieldElement[] zs = new ECFieldElement[]{ Z3, W3 };
+
+ return new Curve25519Point(curve, X3, Y3, zs, this.withCompression);
+ }
+
+ public ECPoint twice()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ return twiceJacobianModified(true);
+ }
+
+ public ECPoint twicePlus(ECPoint b)
+ {
+ if (this == b)
+ {
+ return threeTimes();
+ }
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return twice();
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return b;
+ }
+
+ return twiceJacobianModified(false).add(b);
+ }
+
+ public ECPoint threeTimes()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return this;
+ }
+
+ return twiceJacobianModified(false).add(this);
+ }
+
+ public ECPoint negate()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ return new Curve25519Point(this.getCurve(), this.x, this.y.negate(), this.zs, this.withCompression);
+ }
+
+ protected Curve25519FieldElement calculateJacobianModifiedW(Curve25519FieldElement Z, int[] ZSquared)
+ {
+ Curve25519FieldElement a4 = (Curve25519FieldElement)this.getCurve().getA();
+ if (Z.isOne())
+ {
+ return a4;
+ }
+
+ Curve25519FieldElement W = new Curve25519FieldElement();
+ if (ZSquared == null)
+ {
+ ZSquared = W.x;
+ Curve25519Field.square(Z.x, ZSquared);
+ }
+ Curve25519Field.square(ZSquared, W.x);
+ Curve25519Field.multiply(W.x, a4.x, W.x);
+ return W;
+ }
+
+ protected Curve25519FieldElement getJacobianModifiedW()
+ {
+ Curve25519FieldElement W = (Curve25519FieldElement)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((Curve25519FieldElement)this.zs[0], null);
+ }
+ return W;
+ }
+
+ protected Curve25519Point twiceJacobianModified(boolean calculateW)
+ {
+ Curve25519FieldElement X1 = (Curve25519FieldElement)this.x, Y1 = (Curve25519FieldElement)this.y,
+ Z1 = (Curve25519FieldElement)this.zs[0], W1 = getJacobianModifiedW();
+
+ int c;
+
+ int[] M = Nat256.create();
+ Curve25519Field.square(X1.x, M);
+ c = Nat256.addBothTo(M, M, M);
+ c += Nat256.addTo(W1.x, M);
+ Curve25519Field.reduce27(c, M);
+
+ int[] _2Y1 = Nat256.create();
+ Curve25519Field.twice(Y1.x, _2Y1);
+
+ int[] _2Y1Squared = Nat256.create();
+ Curve25519Field.multiply(_2Y1, Y1.x, _2Y1Squared);
+
+ int[] S = Nat256.create();
+ Curve25519Field.multiply(_2Y1Squared, X1.x, S);
+ Curve25519Field.twice(S, S);
+
+ int[] _8T = Nat256.create();
+ Curve25519Field.square(_2Y1Squared, _8T);
+ Curve25519Field.twice(_8T, _8T);
+
+ Curve25519FieldElement X3 = new Curve25519FieldElement(_2Y1Squared);
+ Curve25519Field.square(M, X3.x);
+ Curve25519Field.subtract(X3.x, S, X3.x);
+ Curve25519Field.subtract(X3.x, S, X3.x);
+
+ Curve25519FieldElement Y3 = new Curve25519FieldElement(S);
+ Curve25519Field.subtract(S, X3.x, Y3.x);
+ Curve25519Field.multiply(Y3.x, M, Y3.x);
+ Curve25519Field.subtract(Y3.x, _8T, Y3.x);
+
+ Curve25519FieldElement Z3 = new Curve25519FieldElement(_2Y1);
+ if (!Nat256.isOne(Z1.x))
+ {
+ Curve25519Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+
+ Curve25519FieldElement W3 = null;
+ if (calculateW)
+ {
+ W3 = new Curve25519FieldElement(_8T);
+ Curve25519Field.multiply(W3.x, W1.x, W3.x);
+ Curve25519Field.twice(W3.x, W3.x);
+ }
+
+ return new Curve25519Point(this.getCurve(), X3, Y3, new ECFieldElement[]{ Z3, W3 }, this.withCompression);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1Curve.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1Curve.java
new file mode 100644
index 00000000..3c5d9cb3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1Curve.java
@@ -0,0 +1,79 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.ec.ECConstants;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.util.encoders.Hex;
+
+public class SecP192K1Curve extends ECCurve.AbstractFp
+{
+ public static final BigInteger q = new BigInteger(1,
+ Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37"));
+
+ private static final int SecP192K1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+ protected SecP192K1Point infinity;
+
+ public SecP192K1Curve()
+ {
+ super(q);
+
+ this.infinity = new SecP192K1Point(this, null, null);
+
+ this.a = fromBigInteger(ECConstants.ZERO);
+ this.b = fromBigInteger(BigInteger.valueOf(3));
+ this.order = new BigInteger(1, Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D"));
+ this.cofactor = BigInteger.valueOf(1);
+
+ this.coord = SecP192K1_DEFAULT_COORDS;
+ }
+
+ protected ECCurve cloneCurve()
+ {
+ return new SecP192K1Curve();
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_JACOBIAN:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public int getFieldSize()
+ {
+ return q.bitLength();
+ }
+
+ public ECFieldElement fromBigInteger(BigInteger x)
+ {
+ return new SecP192K1FieldElement(x);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ return new SecP192K1Point(this, x, y, withCompression);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ return new SecP192K1Point(this, x, y, zs, withCompression);
+ }
+
+ public ECPoint getInfinity()
+ {
+ return infinity;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1Field.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1Field.java
new file mode 100644
index 00000000..b7e87f27
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1Field.java
@@ -0,0 +1,177 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.raw.Nat;
+import org.spongycastle.math.raw.Nat192;
+
+public class SecP192K1Field
+{
+ // 2^192 - 2^32 - 2^12 - 2^8 - 2^7 - 2^6 - 2^3 - 1
+ static final int[] P = new int[]{ 0xFFFFEE37, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ static final int[] PExt = new int[]{ 0x013C4FD1, 0x00002392, 0x00000001, 0x00000000, 0x00000000,
+ 0x00000000, 0xFFFFDC6E, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ private static final int[] PExtInv = new int[]{ 0xFEC3B02F, 0xFFFFDC6D, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0x00002391, 0x00000002 };
+ private static final int P5 = 0xFFFFFFFF;
+ private static final int PExt11 = 0xFFFFFFFF;
+ private static final int PInv33 = 0x11C9;
+
+ public static void add(int[] x, int[] y, int[] z)
+ {
+ int c = Nat192.add(x, y, z);
+ if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
+ {
+ Nat.add33To(6, PInv33, z);
+ }
+ }
+
+ public static void addExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.add(12, xx, yy, zz);
+ if (c != 0 || (zz[11] == PExt11 && Nat.gte(12, zz, PExt)))
+ {
+ if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.incAt(12, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void addOne(int[] x, int[] z)
+ {
+ int c = Nat.inc(6, x, z);
+ if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
+ {
+ Nat.add33To(6, PInv33, z);
+ }
+ }
+
+ public static int[] fromBigInteger(BigInteger x)
+ {
+ int[] z = Nat192.fromBigInteger(x);
+ if (z[5] == P5 && Nat192.gte(z, P))
+ {
+ Nat192.subFrom(P, z);
+ }
+ return z;
+ }
+
+ public static void half(int[] x, int[] z)
+ {
+ if ((x[0] & 1) == 0)
+ {
+ Nat.shiftDownBit(6, x, 0, z);
+ }
+ else
+ {
+ int c = Nat192.add(x, P, z);
+ Nat.shiftDownBit(6, z, c);
+ }
+ }
+
+ public static void multiply(int[] x, int[] y, int[] z)
+ {
+ int[] tt = Nat192.createExt();
+ Nat192.mul(x, y, tt);
+ reduce(tt, z);
+ }
+
+ public static void multiplyAddToExt(int[] x, int[] y, int[] zz)
+ {
+ int c = Nat192.mulAddTo(x, y, zz);
+ if (c != 0 || (zz[11] == PExt11 && Nat.gte(12, zz, PExt)))
+ {
+ if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.incAt(12, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void negate(int[] x, int[] z)
+ {
+ if (Nat192.isZero(x))
+ {
+ Nat192.zero(z);
+ }
+ else
+ {
+ Nat192.sub(P, x, z);
+ }
+ }
+
+ public static void reduce(int[] xx, int[] z)
+ {
+ long cc = Nat192.mul33Add(PInv33, xx, 6, xx, 0, z, 0);
+ int c = Nat192.mul33DWordAdd(PInv33, cc, z, 0);
+
+ // assert c == 0L || c == 1L;
+
+ if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
+ {
+ Nat.add33To(6, PInv33, z);
+ }
+ }
+
+ public static void reduce32(int x, int[] z)
+ {
+ if ((x != 0 && Nat192.mul33WordAdd(PInv33, x, z, 0) != 0)
+ || (z[5] == P5 && Nat192.gte(z, P)))
+ {
+ Nat.add33To(6, PInv33, z);
+ }
+ }
+
+ public static void square(int[] x, int[] z)
+ {
+ int[] tt = Nat192.createExt();
+ Nat192.square(x, tt);
+ reduce(tt, z);
+ }
+
+ public static void squareN(int[] x, int n, int[] z)
+ {
+// assert n > 0;
+
+ int[] tt = Nat192.createExt();
+ Nat192.square(x, tt);
+ reduce(tt, z);
+
+ while (--n > 0)
+ {
+ Nat192.square(z, tt);
+ reduce(tt, z);
+ }
+ }
+
+ public static void subtract(int[] x, int[] y, int[] z)
+ {
+ int c = Nat192.sub(x, y, z);
+ if (c != 0)
+ {
+ Nat.sub33From(6, PInv33, z);
+ }
+ }
+
+ public static void subtractExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.sub(12, xx, yy, zz);
+ if (c != 0)
+ {
+ if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.decAt(12, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void twice(int[] x, int[] z)
+ {
+ int c = Nat.shiftUpBit(6, x, 0, z);
+ if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
+ {
+ Nat.add33To(6, PInv33, z);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1FieldElement.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1FieldElement.java
new file mode 100644
index 00000000..449c560c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1FieldElement.java
@@ -0,0 +1,213 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.raw.Mod;
+import org.spongycastle.math.raw.Nat192;
+import org.spongycastle.util.Arrays;
+
+public class SecP192K1FieldElement extends ECFieldElement
+{
+ public static final BigInteger Q = SecP192K1Curve.q;
+
+ protected int[] x;
+
+ public SecP192K1FieldElement(BigInteger x)
+ {
+ if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
+ {
+ throw new IllegalArgumentException("x value invalid for SecP192K1FieldElement");
+ }
+
+ this.x = SecP192K1Field.fromBigInteger(x);
+ }
+
+ public SecP192K1FieldElement()
+ {
+ this.x = Nat192.create();
+ }
+
+ protected SecP192K1FieldElement(int[] x)
+ {
+ this.x = x;
+ }
+
+ public boolean isZero()
+ {
+ return Nat192.isZero(x);
+ }
+
+ public boolean isOne()
+ {
+ return Nat192.isOne(x);
+ }
+
+ public boolean testBitZero()
+ {
+ return Nat192.getBit(x, 0) == 1;
+ }
+
+ public BigInteger toBigInteger()
+ {
+ return Nat192.toBigInteger(x);
+ }
+
+ public String getFieldName()
+ {
+ return "SecP192K1Field";
+ }
+
+ public int getFieldSize()
+ {
+ return Q.bitLength();
+ }
+
+ public ECFieldElement add(ECFieldElement b)
+ {
+ int[] z = Nat192.create();
+ SecP192K1Field.add(x, ((SecP192K1FieldElement)b).x, z);
+ return new SecP192K1FieldElement(z);
+ }
+
+ public ECFieldElement addOne()
+ {
+ int[] z = Nat192.create();
+ SecP192K1Field.addOne(x, z);
+ return new SecP192K1FieldElement(z);
+ }
+
+ public ECFieldElement subtract(ECFieldElement b)
+ {
+ int[] z = Nat192.create();
+ SecP192K1Field.subtract(x, ((SecP192K1FieldElement)b).x, z);
+ return new SecP192K1FieldElement(z);
+ }
+
+ public ECFieldElement multiply(ECFieldElement b)
+ {
+ int[] z = Nat192.create();
+ SecP192K1Field.multiply(x, ((SecP192K1FieldElement)b).x, z);
+ return new SecP192K1FieldElement(z);
+ }
+
+ public ECFieldElement divide(ECFieldElement b)
+ {
+// return multiply(b.invert());
+ int[] z = Nat192.create();
+ Mod.invert(SecP192K1Field.P, ((SecP192K1FieldElement)b).x, z);
+ SecP192K1Field.multiply(z, x, z);
+ return new SecP192K1FieldElement(z);
+ }
+
+ public ECFieldElement negate()
+ {
+ int[] z = Nat192.create();
+ SecP192K1Field.negate(x, z);
+ return new SecP192K1FieldElement(z);
+ }
+
+ public ECFieldElement square()
+ {
+ int[] z = Nat192.create();
+ SecP192K1Field.square(x, z);
+ return new SecP192K1FieldElement(z);
+ }
+
+ public ECFieldElement invert()
+ {
+// return new SecP192K1FieldElement(toBigInteger().modInverse(Q));
+ int[] z = Nat192.create();
+ Mod.invert(SecP192K1Field.P, x, z);
+ return new SecP192K1FieldElement(z);
+ }
+
+ /**
+ * return a sqrt root - the routine verifies that the calculation returns the right value - if
+ * none exists it returns null.
+ */
+ public ECFieldElement sqrt()
+ {
+ /*
+ * Raise this element to the exponent 2^190 - 2^30 - 2^10 - 2^6 - 2^5 - 2^4 - 2^1
+ *
+ * Breaking up the exponent's binary representation into "repunits", we get:
+ * { 159 1s } { 1 0s } { 19 1s } { 1 0s } { 3 1s } { 3 0s} { 3 1s } { 1 0s }
+ *
+ * Therefore we need an addition chain containing 3, 19, 159 (the lengths of the repunits)
+ * We use: 1, 2, [3], 6, 8, 16, [19], 35, 70, 140, [159]
+ */
+
+ int[] x1 = this.x;
+ if (Nat192.isZero(x1) || Nat192.isOne(x1))
+ {
+ return this;
+ }
+
+ int[] x2 = Nat192.create();
+ SecP192K1Field.square(x1, x2);
+ SecP192K1Field.multiply(x2, x1, x2);
+ int[] x3 = Nat192.create();
+ SecP192K1Field.square(x2, x3);
+ SecP192K1Field.multiply(x3, x1, x3);
+ int[] x6 = Nat192.create();
+ SecP192K1Field.squareN(x3, 3, x6);
+ SecP192K1Field.multiply(x6, x3, x6);
+ int[] x8 = x6;
+ SecP192K1Field.squareN(x6, 2, x8);
+ SecP192K1Field.multiply(x8, x2, x8);
+ int[] x16 = x2;
+ SecP192K1Field.squareN(x8, 8, x16);
+ SecP192K1Field.multiply(x16, x8, x16);
+ int[] x19 = x8;
+ SecP192K1Field.squareN(x16, 3, x19);
+ SecP192K1Field.multiply(x19, x3, x19);
+ int[] x35 = Nat192.create();
+ SecP192K1Field.squareN(x19, 16, x35);
+ SecP192K1Field.multiply(x35, x16, x35);
+ int[] x70 = x16;
+ SecP192K1Field.squareN(x35, 35, x70);
+ SecP192K1Field.multiply(x70, x35, x70);
+ int[] x140 = x35;
+ SecP192K1Field.squareN(x70, 70, x140);
+ SecP192K1Field.multiply(x140, x70, x140);
+ int[] x159 = x70;
+ SecP192K1Field.squareN(x140, 19, x159);
+ SecP192K1Field.multiply(x159, x19, x159);
+
+ int[] t1 = x159;
+ SecP192K1Field.squareN(t1, 20, t1);
+ SecP192K1Field.multiply(t1, x19, t1);
+ SecP192K1Field.squareN(t1, 4, t1);
+ SecP192K1Field.multiply(t1, x3, t1);
+ SecP192K1Field.squareN(t1, 6, t1);
+ SecP192K1Field.multiply(t1, x3, t1);
+ SecP192K1Field.square(t1, t1);
+
+ int[] t2 = x3;
+ SecP192K1Field.square(t1, t2);
+
+ return Nat192.eq(x1, t2) ? new SecP192K1FieldElement(t1) : null;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other == this)
+ {
+ return true;
+ }
+
+ if (!(other instanceof SecP192K1FieldElement))
+ {
+ return false;
+ }
+
+ SecP192K1FieldElement o = (SecP192K1FieldElement)other;
+ return Nat192.eq(x, o.x);
+ }
+
+ public int hashCode()
+ {
+ return Q.hashCode() ^ Arrays.hashCode(x, 0, 6);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1Point.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1Point.java
new file mode 100644
index 00000000..d2fc0ad2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1Point.java
@@ -0,0 +1,298 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.raw.Nat;
+import org.spongycastle.math.raw.Nat192;
+
+public class SecP192K1Point extends ECPoint.AbstractFp
+{
+ /**
+ * Create a point which encodes with point compression.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ *
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecP192K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ this(curve, x, y, false);
+ }
+
+ /**
+ * Create a point that encodes with or without point compresion.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ * @param withCompression
+ * if true encode with point compression
+ *
+ * @deprecated per-point compression property will be removed, refer
+ * {@link #getEncoded(boolean)}
+ */
+ public SecP192K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ super(curve, x, y);
+
+ if ((x == null) != (y == null))
+ {
+ throw new IllegalArgumentException("Exactly one of the field elements is null");
+ }
+
+ this.withCompression = withCompression;
+ }
+
+ SecP192K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs,
+ boolean withCompression)
+ {
+ super(curve, x, y, zs);
+
+ this.withCompression = withCompression;
+ }
+
+ protected ECPoint detach()
+ {
+ return new SecP192K1Point(null, getAffineXCoord(), getAffineYCoord());
+ }
+
+ // B.3 pg 62
+ public ECPoint add(ECPoint b)
+ {
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return this;
+ }
+ if (this == b)
+ {
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP192K1FieldElement X1 = (SecP192K1FieldElement)this.x, Y1 = (SecP192K1FieldElement)this.y;
+ SecP192K1FieldElement X2 = (SecP192K1FieldElement)b.getXCoord(), Y2 = (SecP192K1FieldElement)b.getYCoord();
+
+ SecP192K1FieldElement Z1 = (SecP192K1FieldElement)this.zs[0];
+ SecP192K1FieldElement Z2 = (SecP192K1FieldElement)b.getZCoord(0);
+
+ int c;
+ int[] tt1 = Nat192.createExt();
+ int[] t2 = Nat192.create();
+ int[] t3 = Nat192.create();
+ int[] t4 = Nat192.create();
+
+ boolean Z1IsOne = Z1.isOne();
+ int[] U2, S2;
+ if (Z1IsOne)
+ {
+ U2 = X2.x;
+ S2 = Y2.x;
+ }
+ else
+ {
+ S2 = t3;
+ SecP192K1Field.square(Z1.x, S2);
+
+ U2 = t2;
+ SecP192K1Field.multiply(S2, X2.x, U2);
+
+ SecP192K1Field.multiply(S2, Z1.x, S2);
+ SecP192K1Field.multiply(S2, Y2.x, S2);
+ }
+
+ boolean Z2IsOne = Z2.isOne();
+ int[] U1, S1;
+ if (Z2IsOne)
+ {
+ U1 = X1.x;
+ S1 = Y1.x;
+ }
+ else
+ {
+ S1 = t4;
+ SecP192K1Field.square(Z2.x, S1);
+
+ U1 = tt1;
+ SecP192K1Field.multiply(S1, X1.x, U1);
+
+ SecP192K1Field.multiply(S1, Z2.x, S1);
+ SecP192K1Field.multiply(S1, Y1.x, S1);
+ }
+
+ int[] H = Nat192.create();
+ SecP192K1Field.subtract(U1, U2, H);
+
+ int[] R = t2;
+ SecP192K1Field.subtract(S1, S2, R);
+
+ // Check if b == this or b == -this
+ if (Nat192.isZero(H))
+ {
+ if (Nat192.isZero(R))
+ {
+ // this == b, i.e. this must be doubled
+ return this.twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.getInfinity();
+ }
+
+ int[] HSquared = t3;
+ SecP192K1Field.square(H, HSquared);
+
+ int[] G = Nat192.create();
+ SecP192K1Field.multiply(HSquared, H, G);
+
+ int[] V = t3;
+ SecP192K1Field.multiply(HSquared, U1, V);
+
+ SecP192K1Field.negate(G, G);
+ Nat192.mul(S1, G, tt1);
+
+ c = Nat192.addBothTo(V, V, G);
+ SecP192K1Field.reduce32(c, G);
+
+ SecP192K1FieldElement X3 = new SecP192K1FieldElement(t4);
+ SecP192K1Field.square(R, X3.x);
+ SecP192K1Field.subtract(X3.x, G, X3.x);
+
+ SecP192K1FieldElement Y3 = new SecP192K1FieldElement(G);
+ SecP192K1Field.subtract(V, X3.x, Y3.x);
+ SecP192K1Field.multiplyAddToExt(Y3.x, R, tt1);
+ SecP192K1Field.reduce(tt1, Y3.x);
+
+ SecP192K1FieldElement Z3 = new SecP192K1FieldElement(H);
+ if (!Z1IsOne)
+ {
+ SecP192K1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+ if (!Z2IsOne)
+ {
+ SecP192K1Field.multiply(Z3.x, Z2.x, Z3.x);
+ }
+
+ ECFieldElement[] zs = new ECFieldElement[] { Z3 };
+
+ return new SecP192K1Point(curve, X3, Y3, zs, this.withCompression);
+ }
+
+ // B.3 pg 62
+ public ECPoint twice()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP192K1FieldElement Y1 = (SecP192K1FieldElement)this.y;
+ if (Y1.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ SecP192K1FieldElement X1 = (SecP192K1FieldElement)this.x, Z1 = (SecP192K1FieldElement)this.zs[0];
+
+ int c;
+
+ int[] Y1Squared = Nat192.create();
+ SecP192K1Field.square(Y1.x, Y1Squared);
+
+ int[] T = Nat192.create();
+ SecP192K1Field.square(Y1Squared, T);
+
+ int[] M = Nat192.create();
+ SecP192K1Field.square(X1.x, M);
+ c = Nat192.addBothTo(M, M, M);
+ SecP192K1Field.reduce32(c, M);
+
+ int[] S = Y1Squared;
+ SecP192K1Field.multiply(Y1Squared, X1.x, S);
+ c = Nat.shiftUpBits(6, S, 2, 0);
+ SecP192K1Field.reduce32(c, S);
+
+ int[] t1 = Nat192.create();
+ c = Nat.shiftUpBits(6, T, 3, 0, t1);
+ SecP192K1Field.reduce32(c, t1);
+
+ SecP192K1FieldElement X3 = new SecP192K1FieldElement(T);
+ SecP192K1Field.square(M, X3.x);
+ SecP192K1Field.subtract(X3.x, S, X3.x);
+ SecP192K1Field.subtract(X3.x, S, X3.x);
+
+ SecP192K1FieldElement Y3 = new SecP192K1FieldElement(S);
+ SecP192K1Field.subtract(S, X3.x, Y3.x);
+ SecP192K1Field.multiply(Y3.x, M, Y3.x);
+ SecP192K1Field.subtract(Y3.x, t1, Y3.x);
+
+ SecP192K1FieldElement Z3 = new SecP192K1FieldElement(M);
+ SecP192K1Field.twice(Y1.x, Z3.x);
+ if (!Z1.isOne())
+ {
+ SecP192K1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+
+ return new SecP192K1Point(curve, X3, Y3, new ECFieldElement[] { Z3 }, this.withCompression);
+ }
+
+ public ECPoint twicePlus(ECPoint b)
+ {
+ if (this == b)
+ {
+ return threeTimes();
+ }
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return twice();
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return b;
+ }
+
+ return twice().add(b);
+ }
+
+ public ECPoint threeTimes()
+ {
+ if (this.isInfinity() || this.y.isZero())
+ {
+ return this;
+ }
+
+ // NOTE: Be careful about recursions between twicePlus and threeTimes
+ return twice().add(this);
+ }
+
+ public ECPoint negate()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ return new SecP192K1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1Curve.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1Curve.java
new file mode 100644
index 00000000..705069fc
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1Curve.java
@@ -0,0 +1,80 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.util.encoders.Hex;
+
+public class SecP192R1Curve extends ECCurve.AbstractFp
+{
+ public static final BigInteger q = new BigInteger(1,
+ Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF"));
+
+ private static final int SecP192R1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+ protected SecP192R1Point infinity;
+
+ public SecP192R1Curve()
+ {
+ super(q);
+
+ this.infinity = new SecP192R1Point(this, null, null);
+
+ this.a = fromBigInteger(new BigInteger(1,
+ Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC")));
+ this.b = fromBigInteger(new BigInteger(1,
+ Hex.decode("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1")));
+ this.order = new BigInteger(1, Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831"));
+ this.cofactor = BigInteger.valueOf(1);
+
+ this.coord = SecP192R1_DEFAULT_COORDS;
+ }
+
+ protected ECCurve cloneCurve()
+ {
+ return new SecP192R1Curve();
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_JACOBIAN:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public int getFieldSize()
+ {
+ return q.bitLength();
+ }
+
+ public ECFieldElement fromBigInteger(BigInteger x)
+ {
+ return new SecP192R1FieldElement(x);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ return new SecP192R1Point(this, x, y, withCompression);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ return new SecP192R1Point(this, x, y, zs, withCompression);
+ }
+
+ public ECPoint getInfinity()
+ {
+ return infinity;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1Field.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1Field.java
new file mode 100644
index 00000000..4188b8f8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1Field.java
@@ -0,0 +1,286 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.raw.Nat;
+import org.spongycastle.math.raw.Nat192;
+
+public class SecP192R1Field
+{
+ private static final long M = 0xFFFFFFFFL;
+
+ // 2^192 - 2^64 - 1
+ static final int[] P = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ static final int[] PExt = new int[]{ 0x00000001, 0x00000000, 0x00000002, 0x00000000, 0x00000001,
+ 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ private static final int[] PExtInv = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFE,
+ 0xFFFFFFFF, 0x00000001, 0x00000000, 0x00000002 };
+ private static final int P5 = 0xFFFFFFFF;
+ private static final int PExt11 = 0xFFFFFFFF;
+
+ public static void add(int[] x, int[] y, int[] z)
+ {
+ int c = Nat192.add(x, y, z);
+ if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static void addExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.add(12, xx, yy, zz);
+ if (c != 0 || (zz[11] == PExt11 && Nat.gte(12, zz, PExt)))
+ {
+ if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.incAt(12, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void addOne(int[] x, int[] z)
+ {
+ int c = Nat.inc(6, x, z);
+ if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static int[] fromBigInteger(BigInteger x)
+ {
+ int[] z = Nat192.fromBigInteger(x);
+ if (z[5] == P5 && Nat192.gte(z, P))
+ {
+ Nat192.subFrom(P, z);
+ }
+ return z;
+ }
+
+ public static void half(int[] x, int[] z)
+ {
+ if ((x[0] & 1) == 0)
+ {
+ Nat.shiftDownBit(6, x, 0, z);
+ }
+ else
+ {
+ int c = Nat192.add(x, P, z);
+ Nat.shiftDownBit(6, z, c);
+ }
+ }
+
+ public static void multiply(int[] x, int[] y, int[] z)
+ {
+ int[] tt = Nat192.createExt();
+ Nat192.mul(x, y, tt);
+ reduce(tt, z);
+ }
+
+ public static void multiplyAddToExt(int[] x, int[] y, int[] zz)
+ {
+ int c = Nat192.mulAddTo(x, y, zz);
+ if (c != 0 || (zz[11] == PExt11 && Nat.gte(12, zz, PExt)))
+ {
+ if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.incAt(12, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void negate(int[] x, int[] z)
+ {
+ if (Nat192.isZero(x))
+ {
+ Nat192.zero(z);
+ }
+ else
+ {
+ Nat192.sub(P, x, z);
+ }
+ }
+
+ public static void reduce(int[] xx, int[] z)
+ {
+ long xx06 = xx[6] & M, xx07 = xx[7] & M, xx08 = xx[8] & M;
+ long xx09 = xx[9] & M, xx10 = xx[10] & M, xx11 = xx[11] & M;
+
+ long t0 = xx06 + xx10;
+ long t1 = xx07 + xx11;
+
+ long cc = 0;
+ cc += (xx[0] & M) + t0;
+ int z0 = (int)cc;
+ cc >>= 32;
+ cc += (xx[1] & M) + t1;
+ z[1] = (int)cc;
+ cc >>= 32;
+
+ t0 += xx08;
+ t1 += xx09;
+
+ cc += (xx[2] & M) + t0;
+ long z2 = cc & M;
+ cc >>= 32;
+ cc += (xx[3] & M) + t1;
+ z[3] = (int)cc;
+ cc >>= 32;
+
+ t0 -= xx06;
+ t1 -= xx07;
+
+ cc += (xx[4] & M) + t0;
+ z[4] = (int)cc;
+ cc >>= 32;
+ cc += (xx[5] & M) + t1;
+ z[5] = (int)cc;
+ cc >>= 32;
+
+ z2 += cc;
+
+ cc += (z0 & M);
+ z[0] = (int)cc;
+ cc >>= 32;
+ if (cc != 0)
+ {
+ cc += (z[1] & M);
+ z[1] = (int)cc;
+ z2 += cc >> 32;
+ }
+ z[2] = (int)z2;
+ cc = z2 >> 32;
+
+// assert cc == 0 || cc == 1;
+
+ if ((cc != 0 && Nat.incAt(6, z, 3) != 0)
+ || (z[5] == P5 && Nat192.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static void reduce32(int x, int[] z)
+ {
+ long cc = 0;
+
+ if (x != 0)
+ {
+ long xx06 = x & M;
+
+ cc += (z[0] & M) + xx06;
+ z[0] = (int)cc;
+ cc >>= 32;
+ if (cc != 0)
+ {
+ cc += (z[1] & M);
+ z[1] = (int)cc;
+ cc >>= 32;
+ }
+ cc += (z[2] & M) + xx06;
+ z[2] = (int)cc;
+ cc >>= 32;
+
+// assert cc == 0 || cc == 1;
+ }
+
+ if ((cc != 0 && Nat.incAt(6, z, 3) != 0)
+ || (z[5] == P5 && Nat192.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static void square(int[] x, int[] z)
+ {
+ int[] tt = Nat192.createExt();
+ Nat192.square(x, tt);
+ reduce(tt, z);
+ }
+
+ public static void squareN(int[] x, int n, int[] z)
+ {
+// assert n > 0;
+
+ int[] tt = Nat192.createExt();
+ Nat192.square(x, tt);
+ reduce(tt, z);
+
+ while (--n > 0)
+ {
+ Nat192.square(z, tt);
+ reduce(tt, z);
+ }
+ }
+
+ public static void subtract(int[] x, int[] y, int[] z)
+ {
+ int c = Nat192.sub(x, y, z);
+ if (c != 0)
+ {
+ subPInvFrom(z);
+ }
+ }
+
+ public static void subtractExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.sub(12, xx, yy, zz);
+ if (c != 0)
+ {
+ if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.decAt(12, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void twice(int[] x, int[] z)
+ {
+ int c = Nat.shiftUpBit(6, x, 0, z);
+ if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ private static void addPInvTo(int[] z)
+ {
+ long c = (z[0] & M) + 1;
+ z[0] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (z[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ }
+ c += (z[2] & M) + 1;
+ z[2] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ Nat.incAt(6, z, 3);
+ }
+ }
+
+ private static void subPInvFrom(int[] z)
+ {
+ long c = (z[0] & M) - 1;
+ z[0] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (z[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ }
+ c += (z[2] & M) - 1;
+ z[2] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ Nat.decAt(6, z, 3);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1FieldElement.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1FieldElement.java
new file mode 100644
index 00000000..2ab5030c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1FieldElement.java
@@ -0,0 +1,190 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.raw.Mod;
+import org.spongycastle.math.raw.Nat192;
+import org.spongycastle.util.Arrays;
+
+public class SecP192R1FieldElement extends ECFieldElement
+{
+ public static final BigInteger Q = SecP192R1Curve.q;
+
+ protected int[] x;
+
+ public SecP192R1FieldElement(BigInteger x)
+ {
+ if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
+ {
+ throw new IllegalArgumentException("x value invalid for SecP192R1FieldElement");
+ }
+
+ this.x = SecP192R1Field.fromBigInteger(x);
+ }
+
+ public SecP192R1FieldElement()
+ {
+ this.x = Nat192.create();
+ }
+
+ protected SecP192R1FieldElement(int[] x)
+ {
+ this.x = x;
+ }
+
+ public boolean isZero()
+ {
+ return Nat192.isZero(x);
+ }
+
+ public boolean isOne()
+ {
+ return Nat192.isOne(x);
+ }
+
+ public boolean testBitZero()
+ {
+ return Nat192.getBit(x, 0) == 1;
+ }
+
+ public BigInteger toBigInteger()
+ {
+ return Nat192.toBigInteger(x);
+ }
+
+ public String getFieldName()
+ {
+ return "SecP192R1Field";
+ }
+
+ public int getFieldSize()
+ {
+ return Q.bitLength();
+ }
+
+ public ECFieldElement add(ECFieldElement b)
+ {
+ int[] z = Nat192.create();
+ SecP192R1Field.add(x, ((SecP192R1FieldElement)b).x, z);
+ return new SecP192R1FieldElement(z);
+ }
+
+ public ECFieldElement addOne()
+ {
+ int[] z = Nat192.create();
+ SecP192R1Field.addOne(x, z);
+ return new SecP192R1FieldElement(z);
+ }
+
+ public ECFieldElement subtract(ECFieldElement b)
+ {
+ int[] z = Nat192.create();
+ SecP192R1Field.subtract(x, ((SecP192R1FieldElement)b).x, z);
+ return new SecP192R1FieldElement(z);
+ }
+
+ public ECFieldElement multiply(ECFieldElement b)
+ {
+ int[] z = Nat192.create();
+ SecP192R1Field.multiply(x, ((SecP192R1FieldElement)b).x, z);
+ return new SecP192R1FieldElement(z);
+ }
+
+ public ECFieldElement divide(ECFieldElement b)
+ {
+// return multiply(b.invert());
+ int[] z = Nat192.create();
+ Mod.invert(SecP192R1Field.P, ((SecP192R1FieldElement)b).x, z);
+ SecP192R1Field.multiply(z, x, z);
+ return new SecP192R1FieldElement(z);
+ }
+
+ public ECFieldElement negate()
+ {
+ int[] z = Nat192.create();
+ SecP192R1Field.negate(x, z);
+ return new SecP192R1FieldElement(z);
+ }
+
+ public ECFieldElement square()
+ {
+ int[] z = Nat192.create();
+ SecP192R1Field.square(x, z);
+ return new SecP192R1FieldElement(z);
+ }
+
+ public ECFieldElement invert()
+ {
+// return new SecP192R1FieldElement(toBigInteger().modInverse(Q));
+ int[] z = Nat192.create();
+ Mod.invert(SecP192R1Field.P, x, z);
+ return new SecP192R1FieldElement(z);
+ }
+
+ // D.1.4 91
+ /**
+ * return a sqrt root - the routine verifies that the calculation returns the right value - if
+ * none exists it returns null.
+ */
+ public ECFieldElement sqrt()
+ {
+ // Raise this element to the exponent 2^190 - 2^62
+
+ int[] x1 = this.x;
+ if (Nat192.isZero(x1) || Nat192.isOne(x1))
+ {
+ return this;
+ }
+
+ int[] t1 = Nat192.create();
+ int[] t2 = Nat192.create();
+
+ SecP192R1Field.square(x1, t1);
+ SecP192R1Field.multiply(t1, x1, t1);
+
+ SecP192R1Field.squareN(t1, 2, t2);
+ SecP192R1Field.multiply(t2, t1, t2);
+
+ SecP192R1Field.squareN(t2, 4, t1);
+ SecP192R1Field.multiply(t1, t2, t1);
+
+ SecP192R1Field.squareN(t1, 8, t2);
+ SecP192R1Field.multiply(t2, t1, t2);
+
+ SecP192R1Field.squareN(t2, 16, t1);
+ SecP192R1Field.multiply(t1, t2, t1);
+
+ SecP192R1Field.squareN(t1, 32, t2);
+ SecP192R1Field.multiply(t2, t1, t2);
+
+ SecP192R1Field.squareN(t2, 64, t1);
+ SecP192R1Field.multiply(t1, t2, t1);
+
+ SecP192R1Field.squareN(t1, 62, t1);
+ SecP192R1Field.square(t1, t2);
+
+ return Nat192.eq(x1, t2) ? new SecP192R1FieldElement(t1) : null;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other == this)
+ {
+ return true;
+ }
+
+ if (!(other instanceof SecP192R1FieldElement))
+ {
+ return false;
+ }
+
+ SecP192R1FieldElement o = (SecP192R1FieldElement)other;
+ return Nat192.eq(x, o.x);
+ }
+
+ public int hashCode()
+ {
+ return Q.hashCode() ^ Arrays.hashCode(x, 0, 6);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1Point.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1Point.java
new file mode 100644
index 00000000..9d611267
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1Point.java
@@ -0,0 +1,310 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.raw.Nat;
+import org.spongycastle.math.raw.Nat192;
+
+public class SecP192R1Point extends ECPoint.AbstractFp
+{
+ /**
+ * Create a point which encodes with point compression.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ *
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecP192R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ this(curve, x, y, false);
+ }
+
+ /**
+ * Create a point that encodes with or without point compresion.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ * @param withCompression
+ * if true encode with point compression
+ *
+ * @deprecated per-point compression property will be removed, refer
+ * {@link #getEncoded(boolean)}
+ */
+ public SecP192R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ super(curve, x, y);
+
+ if ((x == null) != (y == null))
+ {
+ throw new IllegalArgumentException("Exactly one of the field elements is null");
+ }
+
+ this.withCompression = withCompression;
+ }
+
+ SecP192R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ super(curve, x, y, zs);
+
+ this.withCompression = withCompression;
+ }
+
+ protected ECPoint detach()
+ {
+ return new SecP192R1Point(null, getAffineXCoord(), getAffineYCoord());
+ }
+
+ // B.3 pg 62
+ public ECPoint add(ECPoint b)
+ {
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return this;
+ }
+ if (this == b)
+ {
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP192R1FieldElement X1 = (SecP192R1FieldElement)this.x, Y1 = (SecP192R1FieldElement)this.y;
+ SecP192R1FieldElement X2 = (SecP192R1FieldElement)b.getXCoord(), Y2 = (SecP192R1FieldElement)b.getYCoord();
+
+ SecP192R1FieldElement Z1 = (SecP192R1FieldElement)this.zs[0];
+ SecP192R1FieldElement Z2 = (SecP192R1FieldElement)b.getZCoord(0);
+
+ int c;
+ int[] tt1 = Nat192.createExt();
+ int[] t2 = Nat192.create();
+ int[] t3 = Nat192.create();
+ int[] t4 = Nat192.create();
+
+ boolean Z1IsOne = Z1.isOne();
+ int[] U2, S2;
+ if (Z1IsOne)
+ {
+ U2 = X2.x;
+ S2 = Y2.x;
+ }
+ else
+ {
+ S2 = t3;
+ SecP192R1Field.square(Z1.x, S2);
+
+ U2 = t2;
+ SecP192R1Field.multiply(S2, X2.x, U2);
+
+ SecP192R1Field.multiply(S2, Z1.x, S2);
+ SecP192R1Field.multiply(S2, Y2.x, S2);
+ }
+
+ boolean Z2IsOne = Z2.isOne();
+ int[] U1, S1;
+ if (Z2IsOne)
+ {
+ U1 = X1.x;
+ S1 = Y1.x;
+ }
+ else
+ {
+ S1 = t4;
+ SecP192R1Field.square(Z2.x, S1);
+
+ U1 = tt1;
+ SecP192R1Field.multiply(S1, X1.x, U1);
+
+ SecP192R1Field.multiply(S1, Z2.x, S1);
+ SecP192R1Field.multiply(S1, Y1.x, S1);
+ }
+
+ int[] H = Nat192.create();
+ SecP192R1Field.subtract(U1, U2, H);
+
+ int[] R = t2;
+ SecP192R1Field.subtract(S1, S2, R);
+
+ // Check if b == this or b == -this
+ if (Nat192.isZero(H))
+ {
+ if (Nat192.isZero(R))
+ {
+ // this == b, i.e. this must be doubled
+ return this.twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.getInfinity();
+ }
+
+ int[] HSquared = t3;
+ SecP192R1Field.square(H, HSquared);
+
+ int[] G = Nat192.create();
+ SecP192R1Field.multiply(HSquared, H, G);
+
+ int[] V = t3;
+ SecP192R1Field.multiply(HSquared, U1, V);
+
+ SecP192R1Field.negate(G, G);
+ Nat192.mul(S1, G, tt1);
+
+ c = Nat192.addBothTo(V, V, G);
+ SecP192R1Field.reduce32(c, G);
+
+ SecP192R1FieldElement X3 = new SecP192R1FieldElement(t4);
+ SecP192R1Field.square(R, X3.x);
+ SecP192R1Field.subtract(X3.x, G, X3.x);
+
+ SecP192R1FieldElement Y3 = new SecP192R1FieldElement(G);
+ SecP192R1Field.subtract(V, X3.x, Y3.x);
+ SecP192R1Field.multiplyAddToExt(Y3.x, R, tt1);
+ SecP192R1Field.reduce(tt1, Y3.x);
+
+ SecP192R1FieldElement Z3 = new SecP192R1FieldElement(H);
+ if (!Z1IsOne)
+ {
+ SecP192R1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+ if (!Z2IsOne)
+ {
+ SecP192R1Field.multiply(Z3.x, Z2.x, Z3.x);
+ }
+
+ ECFieldElement[] zs = new ECFieldElement[]{ Z3 };
+
+ return new SecP192R1Point(curve, X3, Y3, zs, this.withCompression);
+ }
+
+ // B.3 pg 62
+ public ECPoint twice()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP192R1FieldElement Y1 = (SecP192R1FieldElement)this.y;
+ if (Y1.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ SecP192R1FieldElement X1 = (SecP192R1FieldElement)this.x, Z1 = (SecP192R1FieldElement)this.zs[0];
+
+ int c;
+ int[] t1 = Nat192.create();
+ int[] t2 = Nat192.create();
+
+ int[] Y1Squared = Nat192.create();
+ SecP192R1Field.square(Y1.x, Y1Squared);
+
+ int[] T = Nat192.create();
+ SecP192R1Field.square(Y1Squared, T);
+
+ boolean Z1IsOne = Z1.isOne();
+
+ int[] Z1Squared = Z1.x;
+ if (!Z1IsOne)
+ {
+ Z1Squared = t2;
+ SecP192R1Field.square(Z1.x, Z1Squared);
+ }
+
+ SecP192R1Field.subtract(X1.x, Z1Squared, t1);
+
+ int[] M = t2;
+ SecP192R1Field.add(X1.x, Z1Squared, M);
+ SecP192R1Field.multiply(M, t1, M);
+ c = Nat192.addBothTo(M, M, M);
+ SecP192R1Field.reduce32(c, M);
+
+ int[] S = Y1Squared;
+ SecP192R1Field.multiply(Y1Squared, X1.x, S);
+ c = Nat.shiftUpBits(6, S, 2, 0);
+ SecP192R1Field.reduce32(c, S);
+
+ c = Nat.shiftUpBits(6, T, 3, 0, t1);
+ SecP192R1Field.reduce32(c, t1);
+
+ SecP192R1FieldElement X3 = new SecP192R1FieldElement(T);
+ SecP192R1Field.square(M, X3.x);
+ SecP192R1Field.subtract(X3.x, S, X3.x);
+ SecP192R1Field.subtract(X3.x, S, X3.x);
+
+ SecP192R1FieldElement Y3 = new SecP192R1FieldElement(S);
+ SecP192R1Field.subtract(S, X3.x, Y3.x);
+ SecP192R1Field.multiply(Y3.x, M, Y3.x);
+ SecP192R1Field.subtract(Y3.x, t1, Y3.x);
+
+ SecP192R1FieldElement Z3 = new SecP192R1FieldElement(M);
+ SecP192R1Field.twice(Y1.x, Z3.x);
+ if (!Z1IsOne)
+ {
+ SecP192R1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+
+ return new SecP192R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+
+ public ECPoint twicePlus(ECPoint b)
+ {
+ if (this == b)
+ {
+ return threeTimes();
+ }
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return twice();
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return b;
+ }
+
+ return twice().add(b);
+ }
+
+ public ECPoint threeTimes()
+ {
+ if (this.isInfinity() || this.y.isZero())
+ {
+ return this;
+ }
+
+ // NOTE: Be careful about recursions between twicePlus and threeTimes
+ return twice().add(this);
+ }
+
+ public ECPoint negate()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ return new SecP192R1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1Curve.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1Curve.java
new file mode 100644
index 00000000..9b26b6f8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1Curve.java
@@ -0,0 +1,78 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.ec.ECConstants;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.util.encoders.Hex;
+
+public class SecP224K1Curve extends ECCurve.AbstractFp
+{
+ public static final BigInteger q = new BigInteger(1,
+ Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D"));
+
+ private static final int SECP224K1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+ protected SecP224K1Point infinity;
+
+ public SecP224K1Curve()
+ {
+ super(q);
+
+ this.infinity = new SecP224K1Point(this, null, null);
+
+ this.a = fromBigInteger(ECConstants.ZERO);
+ this.b = fromBigInteger(BigInteger.valueOf(5));
+ this.order = new BigInteger(1, Hex.decode("010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7"));
+ this.cofactor = BigInteger.valueOf(1);
+ this.coord = SECP224K1_DEFAULT_COORDS;
+ }
+
+ protected ECCurve cloneCurve()
+ {
+ return new SecP224K1Curve();
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_JACOBIAN:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public int getFieldSize()
+ {
+ return q.bitLength();
+ }
+
+ public ECFieldElement fromBigInteger(BigInteger x)
+ {
+ return new SecP224K1FieldElement(x);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ return new SecP224K1Point(this, x, y, withCompression);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ return new SecP224K1Point(this, x, y, zs, withCompression);
+ }
+
+ public ECPoint getInfinity()
+ {
+ return infinity;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1Field.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1Field.java
new file mode 100644
index 00000000..0db90e56
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1Field.java
@@ -0,0 +1,178 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.raw.Nat;
+import org.spongycastle.math.raw.Nat224;
+
+public class SecP224K1Field
+{
+ // 2^224 - 2^32 - 2^12 - 2^11 - 2^9 - 2^7 - 2^4 - 2 - 1
+ static final int[] P = new int[]{ 0xFFFFE56D, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF };
+ static final int[] PExt = new int[]{ 0x02C23069, 0x00003526, 0x00000001, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xFFFFCADA, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ private static final int[] PExtInv = new int[]{ 0xFD3DCF97, 0xFFFFCAD9, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0x00003525, 0x00000002 };
+ private static final int P6 = 0xFFFFFFFF;
+ private static final int PExt13 = 0xFFFFFFFF;
+ private static final int PInv33 = 0x1A93;
+
+ public static void add(int[] x, int[] y, int[] z)
+ {
+ int c = Nat224.add(x, y, z);
+ if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
+ {
+ Nat.add33To(7, PInv33, z);
+ }
+ }
+
+ public static void addExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.add(14, xx, yy, zz);
+ if (c != 0 || (zz[13] == PExt13 && Nat.gte(14, zz, PExt)))
+ {
+ if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.incAt(14, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void addOne(int[] x, int[] z)
+ {
+ int c = Nat.inc(7, x, z);
+ if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
+ {
+ Nat.add33To(7, PInv33, z);
+ }
+ }
+
+ public static int[] fromBigInteger(BigInteger x)
+ {
+ int[] z = Nat224.fromBigInteger(x);
+ if (z[6] == P6 && Nat224.gte(z, P))
+ {
+ Nat.add33To(7, PInv33, z);
+ }
+ return z;
+ }
+
+ public static void half(int[] x, int[] z)
+ {
+ if ((x[0] & 1) == 0)
+ {
+ Nat.shiftDownBit(7, x, 0, z);
+ }
+ else
+ {
+ int c = Nat224.add(x, P, z);
+ Nat.shiftDownBit(7, z, c);
+ }
+ }
+
+ public static void multiply(int[] x, int[] y, int[] z)
+ {
+ int[] tt = Nat224.createExt();
+ Nat224.mul(x, y, tt);
+ reduce(tt, z);
+ }
+
+ public static void multiplyAddToExt(int[] x, int[] y, int[] zz)
+ {
+ int c = Nat224.mulAddTo(x, y, zz);
+ if (c != 0 || (zz[13] == PExt13 && Nat.gte(14, zz, PExt)))
+ {
+ if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.incAt(14, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void negate(int[] x, int[] z)
+ {
+ if (Nat224.isZero(x))
+ {
+ Nat224.zero(z);
+ }
+ else
+ {
+ Nat224.sub(P, x, z);
+ }
+ }
+
+ public static void reduce(int[] xx, int[] z)
+ {
+ long cc = Nat224.mul33Add(PInv33, xx, 7, xx, 0, z, 0);
+ int c = Nat224.mul33DWordAdd(PInv33, cc, z, 0);
+
+ // assert c == 0L || c == 1L;
+
+ if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
+ {
+ Nat.add33To(7, PInv33, z);
+ }
+ }
+
+ public static void reduce32(int x, int[] z)
+ {
+ if ((x != 0 && Nat224.mul33WordAdd(PInv33, x, z, 0) != 0)
+ || (z[6] == P6 && Nat224.gte(z, P)))
+ {
+ Nat.add33To(7, PInv33, z);
+ }
+ }
+
+ public static void square(int[] x, int[] z)
+ {
+ int[] tt = Nat224.createExt();
+ Nat224.square(x, tt);
+ reduce(tt, z);
+ }
+
+ public static void squareN(int[] x, int n, int[] z)
+ {
+// assert n > 0;
+
+ int[] tt = Nat224.createExt();
+ Nat224.square(x, tt);
+ reduce(tt, z);
+
+ while (--n > 0)
+ {
+ Nat224.square(z, tt);
+ reduce(tt, z);
+ }
+ }
+
+ public static void subtract(int[] x, int[] y, int[] z)
+ {
+ int c = Nat224.sub(x, y, z);
+ if (c != 0)
+ {
+ Nat.sub33From(7, PInv33, z);
+ }
+ }
+
+ public static void subtractExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.sub(14, xx, yy, zz);
+ if (c != 0)
+ {
+ if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.decAt(14, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void twice(int[] x, int[] z)
+ {
+ int c = Nat.shiftUpBit(7, x, 0, z);
+ if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
+ {
+ Nat.add33To(7, PInv33, z);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1FieldElement.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1FieldElement.java
new file mode 100644
index 00000000..655b9592
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1FieldElement.java
@@ -0,0 +1,243 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.raw.Mod;
+import org.spongycastle.math.raw.Nat224;
+import org.spongycastle.util.Arrays;
+
+public class SecP224K1FieldElement extends ECFieldElement
+{
+ public static final BigInteger Q = SecP224K1Curve.q;
+
+ // Calculated as ECConstants.TWO.modPow(Q.shiftRight(2), Q)
+ private static final int[] PRECOMP_POW2 = new int[]{ 0x33bfd202, 0xdcfad133, 0x2287624a, 0xc3811ba8,
+ 0xa85558fc, 0x1eaef5d7, 0x8edf154c };
+
+ protected int[] x;
+
+ public SecP224K1FieldElement(BigInteger x)
+ {
+ if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
+ {
+ throw new IllegalArgumentException("x value invalid for SecP224K1FieldElement");
+ }
+
+ this.x = SecP224K1Field.fromBigInteger(x);
+ }
+
+ public SecP224K1FieldElement()
+ {
+ this.x = Nat224.create();
+ }
+
+ protected SecP224K1FieldElement(int[] x)
+ {
+ this.x = x;
+ }
+
+ public boolean isZero()
+ {
+ return Nat224.isZero(x);
+ }
+
+ public boolean isOne()
+ {
+ return Nat224.isOne(x);
+ }
+
+ public boolean testBitZero()
+ {
+ return Nat224.getBit(x, 0) == 1;
+ }
+
+ public BigInteger toBigInteger()
+ {
+ return Nat224.toBigInteger(x);
+ }
+
+ public String getFieldName()
+ {
+ return "SecP224K1Field";
+ }
+
+ public int getFieldSize()
+ {
+ return Q.bitLength();
+ }
+
+ public ECFieldElement add(ECFieldElement b)
+ {
+ int[] z = Nat224.create();
+ SecP224K1Field.add(x, ((SecP224K1FieldElement)b).x, z);
+ return new SecP224K1FieldElement(z);
+ }
+
+ public ECFieldElement addOne()
+ {
+ int[] z = Nat224.create();
+ SecP224K1Field.addOne(x, z);
+ return new SecP224K1FieldElement(z);
+ }
+
+ public ECFieldElement subtract(ECFieldElement b)
+ {
+ int[] z = Nat224.create();
+ SecP224K1Field.subtract(x, ((SecP224K1FieldElement)b).x, z);
+ return new SecP224K1FieldElement(z);
+ }
+
+ public ECFieldElement multiply(ECFieldElement b)
+ {
+ int[] z = Nat224.create();
+ SecP224K1Field.multiply(x, ((SecP224K1FieldElement)b).x, z);
+ return new SecP224K1FieldElement(z);
+ }
+
+ public ECFieldElement divide(ECFieldElement b)
+ {
+// return multiply(b.invert());
+ int[] z = Nat224.create();
+ Mod.invert(SecP224K1Field.P, ((SecP224K1FieldElement)b).x, z);
+ SecP224K1Field.multiply(z, x, z);
+ return new SecP224K1FieldElement(z);
+ }
+
+ public ECFieldElement negate()
+ {
+ int[] z = Nat224.create();
+ SecP224K1Field.negate(x, z);
+ return new SecP224K1FieldElement(z);
+ }
+
+ public ECFieldElement square()
+ {
+ int[] z = Nat224.create();
+ SecP224K1Field.square(x, z);
+ return new SecP224K1FieldElement(z);
+ }
+
+ public ECFieldElement invert()
+ {
+// return new SecP224K1FieldElement(toBigInteger().modInverse(Q));
+ int[] z = Nat224.create();
+ Mod.invert(SecP224K1Field.P, x, z);
+ return new SecP224K1FieldElement(z);
+ }
+
+ // D.1.4 91
+ /**
+ * return a sqrt root - the routine verifies that the calculation returns the right value - if
+ * none exists it returns null.
+ */
+ public ECFieldElement sqrt()
+ {
+ /*
+ * Q == 8m + 5, so we use Pocklington's method for this case.
+ *
+ * First, raise this element to the exponent 2^221 - 2^29 - 2^9 - 2^8 - 2^6 - 2^4 - 2^1 (i.e. m + 1)
+ *
+ * Breaking up the exponent's binary representation into "repunits", we get:
+ * { 191 1s } { 1 0s } { 19 1s } { 2 0s } { 1 1s } { 1 0s} { 1 1s } { 1 0s} { 3 1s } { 1 0s}
+ *
+ * Therefore we need an addition chain containing 1, 3, 19, 191 (the lengths of the repunits)
+ * We use: [1], 2, [3], 4, 8, 11, [19], 23, 42, 84, 107, [191]
+ */
+
+ int[] x1 = this.x;
+ if (Nat224.isZero(x1) || Nat224.isOne(x1))
+ {
+ return this;
+ }
+
+ int[] x2 = Nat224.create();
+ SecP224K1Field.square(x1, x2);
+ SecP224K1Field.multiply(x2, x1, x2);
+ int[] x3 = x2;
+ SecP224K1Field.square(x2, x3);
+ SecP224K1Field.multiply(x3, x1, x3);
+ int[] x4 = Nat224.create();
+ SecP224K1Field.square(x3, x4);
+ SecP224K1Field.multiply(x4, x1, x4);
+ int[] x8 = Nat224.create();
+ SecP224K1Field.squareN(x4, 4, x8);
+ SecP224K1Field.multiply(x8, x4, x8);
+ int[] x11 = Nat224.create();
+ SecP224K1Field.squareN(x8, 3, x11);
+ SecP224K1Field.multiply(x11, x3, x11);
+ int[] x19 = x11;
+ SecP224K1Field.squareN(x11, 8, x19);
+ SecP224K1Field.multiply(x19, x8, x19);
+ int[] x23 = x8;
+ SecP224K1Field.squareN(x19, 4, x23);
+ SecP224K1Field.multiply(x23, x4, x23);
+ int[] x42 = x4;
+ SecP224K1Field.squareN(x23, 19, x42);
+ SecP224K1Field.multiply(x42, x19, x42);
+ int[] x84 = Nat224.create();
+ SecP224K1Field.squareN(x42, 42, x84);
+ SecP224K1Field.multiply(x84, x42, x84);
+ int[] x107 = x42;
+ SecP224K1Field.squareN(x84, 23, x107);
+ SecP224K1Field.multiply(x107, x23, x107);
+ int[] x191 = x23;
+ SecP224K1Field.squareN(x107, 84, x191);
+ SecP224K1Field.multiply(x191, x84, x191);
+
+ int[] t1 = x191;
+ SecP224K1Field.squareN(t1, 20, t1);
+ SecP224K1Field.multiply(t1, x19, t1);
+ SecP224K1Field.squareN(t1, 3, t1);
+ SecP224K1Field.multiply(t1, x1, t1);
+ SecP224K1Field.squareN(t1, 2, t1);
+ SecP224K1Field.multiply(t1, x1, t1);
+ SecP224K1Field.squareN(t1, 4, t1);
+ SecP224K1Field.multiply(t1, x3, t1);
+ SecP224K1Field.square(t1, t1);
+
+ int[] t2 = x84;
+ SecP224K1Field.square(t1, t2);
+
+ if (Nat224.eq(x1, t2))
+ {
+ return new SecP224K1FieldElement(t1);
+ }
+
+ /*
+ * If the first guess is incorrect, we multiply by a precomputed power of 2 to get the second guess,
+ * which is ((4x)^(m + 1))/2 mod Q
+ */
+ SecP224K1Field.multiply(t1, PRECOMP_POW2, t1);
+
+ SecP224K1Field.square(t1, t2);
+
+ if (Nat224.eq(x1, t2))
+ {
+ return new SecP224K1FieldElement(t1);
+ }
+
+ return null;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other == this)
+ {
+ return true;
+ }
+
+ if (!(other instanceof SecP224K1FieldElement))
+ {
+ return false;
+ }
+
+ SecP224K1FieldElement o = (SecP224K1FieldElement)other;
+ return Nat224.eq(x, o.x);
+ }
+
+ public int hashCode()
+ {
+ return Q.hashCode() ^ Arrays.hashCode(x, 0, 7);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1Point.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1Point.java
new file mode 100644
index 00000000..e33bc5fd
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1Point.java
@@ -0,0 +1,298 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.raw.Nat;
+import org.spongycastle.math.raw.Nat224;
+
+public class SecP224K1Point extends ECPoint.AbstractFp
+{
+ /**
+ * Create a point which encodes with point compression.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ *
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecP224K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ this(curve, x, y, false);
+ }
+
+ /**
+ * Create a point that encodes with or without point compresion.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ * @param withCompression
+ * if true encode with point compression
+ *
+ * @deprecated per-point compression property will be removed, refer
+ * {@link #getEncoded(boolean)}
+ */
+ public SecP224K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ super(curve, x, y);
+
+ if ((x == null) != (y == null))
+ {
+ throw new IllegalArgumentException("Exactly one of the field elements is null");
+ }
+
+ this.withCompression = withCompression;
+ }
+
+ SecP224K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs,
+ boolean withCompression)
+ {
+ super(curve, x, y, zs);
+
+ this.withCompression = withCompression;
+ }
+
+ protected ECPoint detach()
+ {
+ return new SecP224K1Point(null, getAffineXCoord(), getAffineYCoord());
+ }
+
+ // B.3 pg 62
+ public ECPoint add(ECPoint b)
+ {
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return this;
+ }
+ if (this == b)
+ {
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP224K1FieldElement X1 = (SecP224K1FieldElement)this.x, Y1 = (SecP224K1FieldElement)this.y;
+ SecP224K1FieldElement X2 = (SecP224K1FieldElement)b.getXCoord(), Y2 = (SecP224K1FieldElement)b.getYCoord();
+
+ SecP224K1FieldElement Z1 = (SecP224K1FieldElement)this.zs[0];
+ SecP224K1FieldElement Z2 = (SecP224K1FieldElement)b.getZCoord(0);
+
+ int c;
+ int[] tt1 = Nat224.createExt();
+ int[] t2 = Nat224.create();
+ int[] t3 = Nat224.create();
+ int[] t4 = Nat224.create();
+
+ boolean Z1IsOne = Z1.isOne();
+ int[] U2, S2;
+ if (Z1IsOne)
+ {
+ U2 = X2.x;
+ S2 = Y2.x;
+ }
+ else
+ {
+ S2 = t3;
+ SecP224K1Field.square(Z1.x, S2);
+
+ U2 = t2;
+ SecP224K1Field.multiply(S2, X2.x, U2);
+
+ SecP224K1Field.multiply(S2, Z1.x, S2);
+ SecP224K1Field.multiply(S2, Y2.x, S2);
+ }
+
+ boolean Z2IsOne = Z2.isOne();
+ int[] U1, S1;
+ if (Z2IsOne)
+ {
+ U1 = X1.x;
+ S1 = Y1.x;
+ }
+ else
+ {
+ S1 = t4;
+ SecP224K1Field.square(Z2.x, S1);
+
+ U1 = tt1;
+ SecP224K1Field.multiply(S1, X1.x, U1);
+
+ SecP224K1Field.multiply(S1, Z2.x, S1);
+ SecP224K1Field.multiply(S1, Y1.x, S1);
+ }
+
+ int[] H = Nat224.create();
+ SecP224K1Field.subtract(U1, U2, H);
+
+ int[] R = t2;
+ SecP224K1Field.subtract(S1, S2, R);
+
+ // Check if b == this or b == -this
+ if (Nat224.isZero(H))
+ {
+ if (Nat224.isZero(R))
+ {
+ // this == b, i.e. this must be doubled
+ return this.twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.getInfinity();
+ }
+
+ int[] HSquared = t3;
+ SecP224K1Field.square(H, HSquared);
+
+ int[] G = Nat224.create();
+ SecP224K1Field.multiply(HSquared, H, G);
+
+ int[] V = t3;
+ SecP224K1Field.multiply(HSquared, U1, V);
+
+ SecP224K1Field.negate(G, G);
+ Nat224.mul(S1, G, tt1);
+
+ c = Nat224.addBothTo(V, V, G);
+ SecP224K1Field.reduce32(c, G);
+
+ SecP224K1FieldElement X3 = new SecP224K1FieldElement(t4);
+ SecP224K1Field.square(R, X3.x);
+ SecP224K1Field.subtract(X3.x, G, X3.x);
+
+ SecP224K1FieldElement Y3 = new SecP224K1FieldElement(G);
+ SecP224K1Field.subtract(V, X3.x, Y3.x);
+ SecP224K1Field.multiplyAddToExt(Y3.x, R, tt1);
+ SecP224K1Field.reduce(tt1, Y3.x);
+
+ SecP224K1FieldElement Z3 = new SecP224K1FieldElement(H);
+ if (!Z1IsOne)
+ {
+ SecP224K1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+ if (!Z2IsOne)
+ {
+ SecP224K1Field.multiply(Z3.x, Z2.x, Z3.x);
+ }
+
+ ECFieldElement[] zs = new ECFieldElement[] { Z3 };
+
+ return new SecP224K1Point(curve, X3, Y3, zs, this.withCompression);
+ }
+
+ // B.3 pg 62
+ public ECPoint twice()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP224K1FieldElement Y1 = (SecP224K1FieldElement)this.y;
+ if (Y1.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ SecP224K1FieldElement X1 = (SecP224K1FieldElement)this.x, Z1 = (SecP224K1FieldElement)this.zs[0];
+
+ int c;
+
+ int[] Y1Squared = Nat224.create();
+ SecP224K1Field.square(Y1.x, Y1Squared);
+
+ int[] T = Nat224.create();
+ SecP224K1Field.square(Y1Squared, T);
+
+ int[] M = Nat224.create();
+ SecP224K1Field.square(X1.x, M);
+ c = Nat224.addBothTo(M, M, M);
+ SecP224K1Field.reduce32(c, M);
+
+ int[] S = Y1Squared;
+ SecP224K1Field.multiply(Y1Squared, X1.x, S);
+ c = Nat.shiftUpBits(7, S, 2, 0);
+ SecP224K1Field.reduce32(c, S);
+
+ int[] t1 = Nat224.create();
+ c = Nat.shiftUpBits(7, T, 3, 0, t1);
+ SecP224K1Field.reduce32(c, t1);
+
+ SecP224K1FieldElement X3 = new SecP224K1FieldElement(T);
+ SecP224K1Field.square(M, X3.x);
+ SecP224K1Field.subtract(X3.x, S, X3.x);
+ SecP224K1Field.subtract(X3.x, S, X3.x);
+
+ SecP224K1FieldElement Y3 = new SecP224K1FieldElement(S);
+ SecP224K1Field.subtract(S, X3.x, Y3.x);
+ SecP224K1Field.multiply(Y3.x, M, Y3.x);
+ SecP224K1Field.subtract(Y3.x, t1, Y3.x);
+
+ SecP224K1FieldElement Z3 = new SecP224K1FieldElement(M);
+ SecP224K1Field.twice(Y1.x, Z3.x);
+ if (!Z1.isOne())
+ {
+ SecP224K1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+
+ return new SecP224K1Point(curve, X3, Y3, new ECFieldElement[] { Z3 }, this.withCompression);
+ }
+
+ public ECPoint twicePlus(ECPoint b)
+ {
+ if (this == b)
+ {
+ return threeTimes();
+ }
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return twice();
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return b;
+ }
+
+ return twice().add(b);
+ }
+
+ public ECPoint threeTimes()
+ {
+ if (this.isInfinity() || this.y.isZero())
+ {
+ return this;
+ }
+
+ // NOTE: Be careful about recursions between twicePlus and threeTimes
+ return twice().add(this);
+ }
+
+ public ECPoint negate()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ return new SecP224K1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1Curve.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1Curve.java
new file mode 100644
index 00000000..e81cca7f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1Curve.java
@@ -0,0 +1,80 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.util.encoders.Hex;
+
+public class SecP224R1Curve extends ECCurve.AbstractFp
+{
+ public static final BigInteger q = new BigInteger(1,
+ Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001"));
+
+ private static final int SecP224R1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+ protected SecP224R1Point infinity;
+
+ public SecP224R1Curve()
+ {
+ super(q);
+
+ this.infinity = new SecP224R1Point(this, null, null);
+
+ this.a = fromBigInteger(new BigInteger(1,
+ Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE")));
+ this.b = fromBigInteger(new BigInteger(1,
+ Hex.decode("B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4")));
+ this.order = new BigInteger(1, Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D"));
+ this.cofactor = BigInteger.valueOf(1);
+
+ this.coord = SecP224R1_DEFAULT_COORDS;
+ }
+
+ protected ECCurve cloneCurve()
+ {
+ return new SecP224R1Curve();
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_JACOBIAN:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public int getFieldSize()
+ {
+ return q.bitLength();
+ }
+
+ public ECFieldElement fromBigInteger(BigInteger x)
+ {
+ return new SecP224R1FieldElement(x);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ return new SecP224R1Point(this, x, y, withCompression);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ return new SecP224R1Point(this, x, y, zs, withCompression);
+ }
+
+ public ECPoint getInfinity()
+ {
+ return infinity;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1Field.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1Field.java
new file mode 100644
index 00000000..1722e158
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1Field.java
@@ -0,0 +1,298 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.raw.Nat;
+import org.spongycastle.math.raw.Nat224;
+
+public class SecP224R1Field
+{
+ private static final long M = 0xFFFFFFFFL;
+
+ // 2^224 - 2^96 + 1
+ static final int[] P = new int[]{ 0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ static final int[] PExt = new int[]{ 0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ private static final int[] PExtInv = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001, 0x00000000,
+ 0x00000000, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001 };
+ private static final int P6 = 0xFFFFFFFF;
+ private static final int PExt13 = 0xFFFFFFFF;
+
+ public static void add(int[] x, int[] y, int[] z)
+ {
+ int c = Nat224.add(x, y, z);
+ if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static void addExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.add(14, xx, yy, zz);
+ if (c != 0 || (zz[13] == PExt13 && Nat.gte(14, zz, PExt)))
+ {
+ if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.incAt(14, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void addOne(int[] x, int[] z)
+ {
+ int c = Nat.inc(7, x, z);
+ if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static int[] fromBigInteger(BigInteger x)
+ {
+ int[] z = Nat224.fromBigInteger(x);
+ if (z[6] == P6 && Nat224.gte(z, P))
+ {
+ Nat224.subFrom(P, z);
+ }
+ return z;
+ }
+
+ public static void half(int[] x, int[] z)
+ {
+ if ((x[0] & 1) == 0)
+ {
+ Nat.shiftDownBit(7, x, 0, z);
+ }
+ else
+ {
+ int c = Nat224.add(x, P, z);
+ Nat.shiftDownBit(7, z, c);
+ }
+ }
+
+ public static void multiply(int[] x, int[] y, int[] z)
+ {
+ int[] tt = Nat224.createExt();
+ Nat224.mul(x, y, tt);
+ reduce(tt, z);
+ }
+
+ public static void multiplyAddToExt(int[] x, int[] y, int[] zz)
+ {
+ int c = Nat224.mulAddTo(x, y, zz);
+ if (c != 0 || (zz[13] == PExt13 && Nat.gte(14, zz, PExt)))
+ {
+ if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.incAt(14, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void negate(int[] x, int[] z)
+ {
+ if (Nat224.isZero(x))
+ {
+ Nat224.zero(z);
+ }
+ else
+ {
+ Nat224.sub(P, x, z);
+ }
+ }
+
+ public static void reduce(int[] xx, int[] z)
+ {
+ long xx10 = xx[10] & M, xx11 = xx[11] & M, xx12 = xx[12] & M, xx13 = xx[13] & M;
+
+ final long n = 1;
+
+ long t0 = (xx[7] & M) + xx11 - n;
+ long t1 = (xx[8] & M) + xx12;
+ long t2 = (xx[9] & M) + xx13;
+
+ long cc = 0;
+ cc += (xx[0] & M) - t0;
+ long z0 = cc & M;
+ cc >>= 32;
+ cc += (xx[1] & M) - t1;
+ z[1] = (int)cc;
+ cc >>= 32;
+ cc += (xx[2] & M) - t2;
+ z[2] = (int)cc;
+ cc >>= 32;
+ cc += (xx[3] & M) + t0 - xx10;
+ long z3 = cc & M;
+ cc >>= 32;
+ cc += (xx[4] & M) + t1 - xx11;
+ z[4] = (int)cc;
+ cc >>= 32;
+ cc += (xx[5] & M) + t2 - xx12;
+ z[5] = (int)cc;
+ cc >>= 32;
+ cc += (xx[6] & M) + xx10 - xx13;
+ z[6] = (int)cc;
+ cc >>= 32;
+ cc += n;
+
+// assert cc >= 0;
+
+ z3 += cc;
+
+ z0 -= cc;
+ z[0] = (int)z0;
+ cc = z0 >> 32;
+ if (cc != 0)
+ {
+ cc += (z[1] & M);
+ z[1] = (int)cc;
+ cc >>= 32;
+ cc += (z[2] & M);
+ z[2] = (int)cc;
+ z3 += cc >> 32;
+ }
+ z[3] = (int)z3;
+ cc = z3 >> 32;
+
+// assert cc == 0 || cc == 1;
+
+ if ((cc != 0 && Nat.incAt(7, z, 4) != 0)
+ || (z[6] == P6 && Nat224.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static void reduce32(int x, int[] z)
+ {
+ long cc = 0;
+
+ if (x != 0)
+ {
+ long xx07 = x & M;
+
+ cc += (z[0] & M) - xx07;
+ z[0] = (int)cc;
+ cc >>= 32;
+ if (cc != 0)
+ {
+ cc += (z[1] & M);
+ z[1] = (int)cc;
+ cc >>= 32;
+ cc += (z[2] & M);
+ z[2] = (int)cc;
+ cc >>= 32;
+ }
+ cc += (z[3] & M) + xx07;
+ z[3] = (int)cc;
+ cc >>= 32;
+
+// assert cc == 0 || cc == 1;
+ }
+
+ if ((cc != 0 && Nat.incAt(7, z, 4) != 0)
+ || (z[6] == P6 && Nat224.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static void square(int[] x, int[] z)
+ {
+ int[] tt = Nat224.createExt();
+ Nat224.square(x, tt);
+ reduce(tt, z);
+ }
+
+ public static void squareN(int[] x, int n, int[] z)
+ {
+// assert n > 0;
+
+ int[] tt = Nat224.createExt();
+ Nat224.square(x, tt);
+ reduce(tt, z);
+
+ while (--n > 0)
+ {
+ Nat224.square(z, tt);
+ reduce(tt, z);
+ }
+ }
+
+ public static void subtract(int[] x, int[] y, int[] z)
+ {
+ int c = Nat224.sub(x, y, z);
+ if (c != 0)
+ {
+ subPInvFrom(z);
+ }
+ }
+
+ public static void subtractExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.sub(14, xx, yy, zz);
+ if (c != 0)
+ {
+ if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.decAt(14, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void twice(int[] x, int[] z)
+ {
+ int c = Nat.shiftUpBit(7, x, 0, z);
+ if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ private static void addPInvTo(int[] z)
+ {
+ long c = (z[0] & M) - 1;
+ z[0] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (z[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (z[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ }
+ c += (z[3] & M) + 1;
+ z[3] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ Nat.incAt(7, z, 4);
+ }
+ }
+
+ private static void subPInvFrom(int[] z)
+ {
+ long c = (z[0] & M) + 1;
+ z[0] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (z[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (z[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ }
+ c += (z[3] & M) - 1;
+ z[3] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ Nat.decAt(7, z, 4);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1FieldElement.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1FieldElement.java
new file mode 100644
index 00000000..3a82fcab
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1FieldElement.java
@@ -0,0 +1,273 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.raw.Mod;
+import org.spongycastle.math.raw.Nat;
+import org.spongycastle.math.raw.Nat224;
+import org.spongycastle.util.Arrays;
+
+public class SecP224R1FieldElement extends ECFieldElement
+{
+ public static final BigInteger Q = SecP224R1Curve.q;
+
+ protected int[] x;
+
+ public SecP224R1FieldElement(BigInteger x)
+ {
+ if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
+ {
+ throw new IllegalArgumentException("x value invalid for SecP224R1FieldElement");
+ }
+
+ this.x = SecP224R1Field.fromBigInteger(x);
+ }
+
+ public SecP224R1FieldElement()
+ {
+ this.x = Nat224.create();
+ }
+
+ protected SecP224R1FieldElement(int[] x)
+ {
+ this.x = x;
+ }
+
+ public boolean isZero()
+ {
+ return Nat224.isZero(x);
+ }
+
+ public boolean isOne()
+ {
+ return Nat224.isOne(x);
+ }
+
+ public boolean testBitZero()
+ {
+ return Nat224.getBit(x, 0) == 1;
+ }
+
+ public BigInteger toBigInteger()
+ {
+ return Nat224.toBigInteger(x);
+ }
+
+ public String getFieldName()
+ {
+ return "SecP224R1Field";
+ }
+
+ public int getFieldSize()
+ {
+ return Q.bitLength();
+ }
+
+ public ECFieldElement add(ECFieldElement b)
+ {
+ int[] z = Nat224.create();
+ SecP224R1Field.add(x, ((SecP224R1FieldElement)b).x, z);
+ return new SecP224R1FieldElement(z);
+ }
+
+ public ECFieldElement addOne()
+ {
+ int[] z = Nat224.create();
+ SecP224R1Field.addOne(x, z);
+ return new SecP224R1FieldElement(z);
+ }
+
+ public ECFieldElement subtract(ECFieldElement b)
+ {
+ int[] z = Nat224.create();
+ SecP224R1Field.subtract(x, ((SecP224R1FieldElement)b).x, z);
+ return new SecP224R1FieldElement(z);
+ }
+
+ public ECFieldElement multiply(ECFieldElement b)
+ {
+ int[] z = Nat224.create();
+ SecP224R1Field.multiply(x, ((SecP224R1FieldElement)b).x, z);
+ return new SecP224R1FieldElement(z);
+ }
+
+ public ECFieldElement divide(ECFieldElement b)
+ {
+// return multiply(b.invert());
+ int[] z = Nat224.create();
+ Mod.invert(SecP224R1Field.P, ((SecP224R1FieldElement)b).x, z);
+ SecP224R1Field.multiply(z, x, z);
+ return new SecP224R1FieldElement(z);
+ }
+
+ public ECFieldElement negate()
+ {
+ int[] z = Nat224.create();
+ SecP224R1Field.negate(x, z);
+ return new SecP224R1FieldElement(z);
+ }
+
+ public ECFieldElement square()
+ {
+ int[] z = Nat224.create();
+ SecP224R1Field.square(x, z);
+ return new SecP224R1FieldElement(z);
+ }
+
+ public ECFieldElement invert()
+ {
+// return new SecP224R1FieldElement(toBigInteger().modInverse(Q));
+ int[] z = Nat224.create();
+ Mod.invert(SecP224R1Field.P, x, z);
+ return new SecP224R1FieldElement(z);
+ }
+
+ /**
+ * return a sqrt root - the routine verifies that the calculation returns the right value - if
+ * none exists it returns null.
+ */
+ public ECFieldElement sqrt()
+ {
+ int[] c = this.x;
+ if (Nat224.isZero(c) || Nat224.isOne(c))
+ {
+ return this;
+ }
+
+ int[] nc = Nat224.create();
+ SecP224R1Field.negate(c, nc);
+
+ int[] r = Mod.random(SecP224R1Field.P);
+ int[] t = Nat224.create();
+
+ if (!isSquare(c))
+ {
+ return null;
+ }
+
+ while (!trySqrt(nc, r, t))
+ {
+ SecP224R1Field.addOne(r, r);
+ }
+
+ SecP224R1Field.square(t, r);
+
+ return Nat224.eq(c, r) ? new SecP224R1FieldElement(t) : null;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other == this)
+ {
+ return true;
+ }
+
+ if (!(other instanceof SecP224R1FieldElement))
+ {
+ return false;
+ }
+
+ SecP224R1FieldElement o = (SecP224R1FieldElement)other;
+ return Nat224.eq(x, o.x);
+ }
+
+ public int hashCode()
+ {
+ return Q.hashCode() ^ Arrays.hashCode(x, 0, 7);
+ }
+
+ private static boolean isSquare(int[] x)
+ {
+ int[] t1 = Nat224.create();
+ int[] t2 = Nat224.create();
+ Nat224.copy(x, t1);
+
+ for (int i = 0; i < 7; ++i)
+ {
+ Nat224.copy(t1, t2);
+ SecP224R1Field.squareN(t1, 1 << i, t1);
+ SecP224R1Field.multiply(t1, t2, t1);
+ }
+
+ SecP224R1Field.squareN(t1, 95, t1);
+ return Nat224.isOne(t1);
+ }
+
+ private static void RM(int[] nc, int[] d0, int[] e0, int[] d1, int[] e1, int[] f1, int[] t)
+ {
+ SecP224R1Field.multiply(e1, e0, t);
+ SecP224R1Field.multiply(t, nc, t);
+ SecP224R1Field.multiply(d1, d0, f1);
+ SecP224R1Field.add(f1, t, f1);
+ SecP224R1Field.multiply(d1, e0, t);
+ Nat224.copy(f1, d1);
+ SecP224R1Field.multiply(e1, d0, e1);
+ SecP224R1Field.add(e1, t, e1);
+ SecP224R1Field.square(e1, f1);
+ SecP224R1Field.multiply(f1, nc, f1);
+ }
+
+ private static void RP(int[] nc, int[] d1, int[] e1, int[] f1, int[] t)
+ {
+ Nat224.copy(nc, f1);
+
+ int[] d0 = Nat224.create();
+ int[] e0 = Nat224.create();
+
+ for (int i = 0; i < 7; ++i)
+ {
+ Nat224.copy(d1, d0);
+ Nat224.copy(e1, e0);
+
+ int j = 1 << i;
+ while (--j >= 0)
+ {
+ RS(d1, e1, f1, t);
+ }
+
+ RM(nc, d0, e0, d1, e1, f1, t);
+ }
+ }
+
+ private static void RS(int[] d, int[] e, int[] f, int[] t)
+ {
+ SecP224R1Field.multiply(e, d, e);
+ SecP224R1Field.twice(e, e);
+ SecP224R1Field.square(d, t);
+ SecP224R1Field.add(f, t, d);
+ SecP224R1Field.multiply(f, t, f);
+ int c = Nat.shiftUpBits(7, f, 2, 0);
+ SecP224R1Field.reduce32(c, f);
+ }
+
+ private static boolean trySqrt(int[] nc, int[] r, int[] t)
+ {
+ int[] d1 = Nat224.create();
+ Nat224.copy(r, d1);
+ int[] e1 = Nat224.create();
+ e1[0] = 1;
+ int[] f1 = Nat224.create();
+ RP(nc, d1, e1, f1, t);
+
+ int[] d0 = Nat224.create();
+ int[] e0 = Nat224.create();
+
+ for (int k = 1; k < 96; ++k)
+ {
+ Nat224.copy(d1, d0);
+ Nat224.copy(e1, e0);
+
+ RS(d1, e1, f1, t);
+
+ if (Nat224.isZero(d1))
+ {
+ Mod.invert(SecP224R1Field.P, e0, t);
+ SecP224R1Field.multiply(t, d0, t);
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1Point.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1Point.java
new file mode 100644
index 00000000..d44f2f8f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1Point.java
@@ -0,0 +1,308 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.raw.Nat;
+import org.spongycastle.math.raw.Nat224;
+
+public class SecP224R1Point extends ECPoint.AbstractFp
+{
+ /**
+ * Create a point which encodes with point compression.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ *
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecP224R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ this(curve, x, y, false);
+ }
+
+ /**
+ * Create a point that encodes with or without point compresion.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ * @param withCompression
+ * if true encode with point compression
+ *
+ * @deprecated per-point compression property will be removed, refer
+ * {@link #getEncoded(boolean)}
+ */
+ public SecP224R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ super(curve, x, y);
+
+ if ((x == null) != (y == null))
+ {
+ throw new IllegalArgumentException("Exactly one of the field elements is null");
+ }
+
+ this.withCompression = withCompression;
+ }
+
+ SecP224R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ super(curve, x, y, zs);
+
+ this.withCompression = withCompression;
+ }
+
+ protected ECPoint detach()
+ {
+ return new SecP224R1Point(null, getAffineXCoord(), getAffineYCoord());
+ }
+
+ public ECPoint add(ECPoint b)
+ {
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return this;
+ }
+ if (this == b)
+ {
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP224R1FieldElement X1 = (SecP224R1FieldElement)this.x, Y1 = (SecP224R1FieldElement)this.y;
+ SecP224R1FieldElement X2 = (SecP224R1FieldElement)b.getXCoord(), Y2 = (SecP224R1FieldElement)b.getYCoord();
+
+ SecP224R1FieldElement Z1 = (SecP224R1FieldElement)this.zs[0];
+ SecP224R1FieldElement Z2 = (SecP224R1FieldElement)b.getZCoord(0);
+
+ int c;
+ int[] tt1 = Nat224.createExt();
+ int[] t2 = Nat224.create();
+ int[] t3 = Nat224.create();
+ int[] t4 = Nat224.create();
+
+ boolean Z1IsOne = Z1.isOne();
+ int[] U2, S2;
+ if (Z1IsOne)
+ {
+ U2 = X2.x;
+ S2 = Y2.x;
+ }
+ else
+ {
+ S2 = t3;
+ SecP224R1Field.square(Z1.x, S2);
+
+ U2 = t2;
+ SecP224R1Field.multiply(S2, X2.x, U2);
+
+ SecP224R1Field.multiply(S2, Z1.x, S2);
+ SecP224R1Field.multiply(S2, Y2.x, S2);
+ }
+
+ boolean Z2IsOne = Z2.isOne();
+ int[] U1, S1;
+ if (Z2IsOne)
+ {
+ U1 = X1.x;
+ S1 = Y1.x;
+ }
+ else
+ {
+ S1 = t4;
+ SecP224R1Field.square(Z2.x, S1);
+
+ U1 = tt1;
+ SecP224R1Field.multiply(S1, X1.x, U1);
+
+ SecP224R1Field.multiply(S1, Z2.x, S1);
+ SecP224R1Field.multiply(S1, Y1.x, S1);
+ }
+
+ int[] H = Nat224.create();
+ SecP224R1Field.subtract(U1, U2, H);
+
+ int[] R = t2;
+ SecP224R1Field.subtract(S1, S2, R);
+
+ // Check if b == this or b == -this
+ if (Nat224.isZero(H))
+ {
+ if (Nat224.isZero(R))
+ {
+ // this == b, i.e. this must be doubled
+ return this.twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.getInfinity();
+ }
+
+ int[] HSquared = t3;
+ SecP224R1Field.square(H, HSquared);
+
+ int[] G = Nat224.create();
+ SecP224R1Field.multiply(HSquared, H, G);
+
+ int[] V = t3;
+ SecP224R1Field.multiply(HSquared, U1, V);
+
+ SecP224R1Field.negate(G, G);
+ Nat224.mul(S1, G, tt1);
+
+ c = Nat224.addBothTo(V, V, G);
+ SecP224R1Field.reduce32(c, G);
+
+ SecP224R1FieldElement X3 = new SecP224R1FieldElement(t4);
+ SecP224R1Field.square(R, X3.x);
+ SecP224R1Field.subtract(X3.x, G, X3.x);
+
+ SecP224R1FieldElement Y3 = new SecP224R1FieldElement(G);
+ SecP224R1Field.subtract(V, X3.x, Y3.x);
+ SecP224R1Field.multiplyAddToExt(Y3.x, R, tt1);
+ SecP224R1Field.reduce(tt1, Y3.x);
+
+ SecP224R1FieldElement Z3 = new SecP224R1FieldElement(H);
+ if (!Z1IsOne)
+ {
+ SecP224R1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+ if (!Z2IsOne)
+ {
+ SecP224R1Field.multiply(Z3.x, Z2.x, Z3.x);
+ }
+
+ ECFieldElement[] zs = new ECFieldElement[]{ Z3 };
+
+ return new SecP224R1Point(curve, X3, Y3, zs, this.withCompression);
+ }
+
+ public ECPoint twice()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP224R1FieldElement Y1 = (SecP224R1FieldElement)this.y;
+ if (Y1.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ SecP224R1FieldElement X1 = (SecP224R1FieldElement)this.x, Z1 = (SecP224R1FieldElement)this.zs[0];
+
+ int c;
+ int[] t1 = Nat224.create();
+ int[] t2 = Nat224.create();
+
+ int[] Y1Squared = Nat224.create();
+ SecP224R1Field.square(Y1.x, Y1Squared);
+
+ int[] T = Nat224.create();
+ SecP224R1Field.square(Y1Squared, T);
+
+ boolean Z1IsOne = Z1.isOne();
+
+ int[] Z1Squared = Z1.x;
+ if (!Z1IsOne)
+ {
+ Z1Squared = t2;
+ SecP224R1Field.square(Z1.x, Z1Squared);
+ }
+
+ SecP224R1Field.subtract(X1.x, Z1Squared, t1);
+
+ int[] M = t2;
+ SecP224R1Field.add(X1.x, Z1Squared, M);
+ SecP224R1Field.multiply(M, t1, M);
+ c = Nat224.addBothTo(M, M, M);
+ SecP224R1Field.reduce32(c, M);
+
+ int[] S = Y1Squared;
+ SecP224R1Field.multiply(Y1Squared, X1.x, S);
+ c = Nat.shiftUpBits(7, S, 2, 0);
+ SecP224R1Field.reduce32(c, S);
+
+ c = Nat.shiftUpBits(7, T, 3, 0, t1);
+ SecP224R1Field.reduce32(c, t1);
+
+ SecP224R1FieldElement X3 = new SecP224R1FieldElement(T);
+ SecP224R1Field.square(M, X3.x);
+ SecP224R1Field.subtract(X3.x, S, X3.x);
+ SecP224R1Field.subtract(X3.x, S, X3.x);
+
+ SecP224R1FieldElement Y3 = new SecP224R1FieldElement(S);
+ SecP224R1Field.subtract(S, X3.x, Y3.x);
+ SecP224R1Field.multiply(Y3.x, M, Y3.x);
+ SecP224R1Field.subtract(Y3.x, t1, Y3.x);
+
+ SecP224R1FieldElement Z3 = new SecP224R1FieldElement(M);
+ SecP224R1Field.twice(Y1.x, Z3.x);
+ if (!Z1IsOne)
+ {
+ SecP224R1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+
+ return new SecP224R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+
+ public ECPoint twicePlus(ECPoint b)
+ {
+ if (this == b)
+ {
+ return threeTimes();
+ }
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return twice();
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return b;
+ }
+
+ return twice().add(b);
+ }
+
+ public ECPoint threeTimes()
+ {
+ if (this.isInfinity() || this.y.isZero())
+ {
+ return this;
+ }
+
+ // NOTE: Be careful about recursions between twicePlus and threeTimes
+ return twice().add(this);
+ }
+
+ public ECPoint negate()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ return new SecP224R1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1Curve.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1Curve.java
new file mode 100644
index 00000000..85d31cc1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1Curve.java
@@ -0,0 +1,78 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.ec.ECConstants;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.util.encoders.Hex;
+
+public class SecP256K1Curve extends ECCurve.AbstractFp
+{
+ public static final BigInteger q = new BigInteger(1,
+ Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F"));
+
+ private static final int SECP256K1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+ protected SecP256K1Point infinity;
+
+ public SecP256K1Curve()
+ {
+ super(q);
+
+ this.infinity = new SecP256K1Point(this, null, null);
+
+ this.a = fromBigInteger(ECConstants.ZERO);
+ this.b = fromBigInteger(BigInteger.valueOf(7));
+ this.order = new BigInteger(1, Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"));
+ this.cofactor = BigInteger.valueOf(1);
+ this.coord = SECP256K1_DEFAULT_COORDS;
+ }
+
+ protected ECCurve cloneCurve()
+ {
+ return new SecP256K1Curve();
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_JACOBIAN:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public int getFieldSize()
+ {
+ return q.bitLength();
+ }
+
+ public ECFieldElement fromBigInteger(BigInteger x)
+ {
+ return new SecP256K1FieldElement(x);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ return new SecP256K1Point(this, x, y, withCompression);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ return new SecP256K1Point(this, x, y, zs, withCompression);
+ }
+
+ public ECPoint getInfinity()
+ {
+ return infinity;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1Field.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1Field.java
new file mode 100644
index 00000000..3aae2f2f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1Field.java
@@ -0,0 +1,179 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.raw.Nat;
+import org.spongycastle.math.raw.Nat256;
+
+public class SecP256K1Field
+{
+ // 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
+ static final int[] P = new int[]{ 0xFFFFFC2F, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF };
+ static final int[] PExt = new int[]{ 0x000E90A1, 0x000007A2, 0x00000001, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xFFFFF85E, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF };
+ private static final int[] PExtInv = new int[]{ 0xFFF16F5F, 0xFFFFF85D, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000007A1, 0x00000002 };
+ private static final int P7 = 0xFFFFFFFF;
+ private static final int PExt15 = 0xFFFFFFFF;
+ private static final int PInv33 = 0x3D1;
+
+ public static void add(int[] x, int[] y, int[] z)
+ {
+ int c = Nat256.add(x, y, z);
+ if (c != 0 || (z[7] == P7 && Nat256.gte(z, P)))
+ {
+ Nat.add33To(8, PInv33, z);
+ }
+ }
+
+ public static void addExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.add(16, xx, yy, zz);
+ if (c != 0 || (zz[15] == PExt15 && Nat.gte(16, zz, PExt)))
+ {
+ if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.incAt(16, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void addOne(int[] x, int[] z)
+ {
+ int c = Nat.inc(8, x, z);
+ if (c != 0 || (z[7] == P7 && Nat256.gte(z, P)))
+ {
+ Nat.add33To(8, PInv33, z);
+ }
+ }
+
+ public static int[] fromBigInteger(BigInteger x)
+ {
+ int[] z = Nat256.fromBigInteger(x);
+ if (z[7] == P7 && Nat256.gte(z, P))
+ {
+ Nat256.subFrom(P, z);
+ }
+ return z;
+ }
+
+ public static void half(int[] x, int[] z)
+ {
+ if ((x[0] & 1) == 0)
+ {
+ Nat.shiftDownBit(8, x, 0, z);
+ }
+ else
+ {
+ int c = Nat256.add(x, P, z);
+ Nat.shiftDownBit(8, z, c);
+ }
+ }
+
+ public static void multiply(int[] x, int[] y, int[] z)
+ {
+ int[] tt = Nat256.createExt();
+ Nat256.mul(x, y, tt);
+ reduce(tt, z);
+ }
+
+ public static void multiplyAddToExt(int[] x, int[] y, int[] zz)
+ {
+ int c = Nat256.mulAddTo(x, y, zz);
+ if (c != 0 || (zz[15] == PExt15 && Nat.gte(16, zz, PExt)))
+ {
+ if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.incAt(16, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void negate(int[] x, int[] z)
+ {
+ if (Nat256.isZero(x))
+ {
+ Nat256.zero(z);
+ }
+ else
+ {
+ Nat256.sub(P, x, z);
+ }
+ }
+
+ public static void reduce(int[] xx, int[] z)
+ {
+ long cc = Nat256.mul33Add(PInv33, xx, 8, xx, 0, z, 0);
+ int c = Nat256.mul33DWordAdd(PInv33, cc, z, 0);
+
+ // assert c == 0L || c == 1L;
+
+ if (c != 0 || (z[7] == P7 && Nat256.gte(z, P)))
+ {
+ Nat.add33To(8, PInv33, z);
+ }
+ }
+
+ public static void reduce32(int x, int[] z)
+ {
+ if ((x != 0 && Nat256.mul33WordAdd(PInv33, x, z, 0) != 0)
+ || (z[7] == P7 && Nat256.gte(z, P)))
+ {
+ Nat.add33To(8, PInv33, z);
+ }
+ }
+
+ public static void square(int[] x, int[] z)
+ {
+ int[] tt = Nat256.createExt();
+ Nat256.square(x, tt);
+ reduce(tt, z);
+ }
+
+ public static void squareN(int[] x, int n, int[] z)
+ {
+// assert n > 0;
+
+ int[] tt = Nat256.createExt();
+ Nat256.square(x, tt);
+ reduce(tt, z);
+
+ while (--n > 0)
+ {
+ Nat256.square(z, tt);
+ reduce(tt, z);
+ }
+ }
+
+ public static void subtract(int[] x, int[] y, int[] z)
+ {
+ int c = Nat256.sub(x, y, z);
+ if (c != 0)
+ {
+ Nat.sub33From(8, PInv33, z);
+ }
+ }
+
+ public static void subtractExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.sub(16, xx, yy, zz);
+ if (c != 0)
+ {
+ if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.decAt(16, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void twice(int[] x, int[] z)
+ {
+ int c = Nat.shiftUpBit(8, x, 0, z);
+ if (c != 0 || (z[7] == P7 && Nat256.gte(z, P)))
+ {
+ Nat.add33To(8, PInv33, z);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1FieldElement.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1FieldElement.java
new file mode 100644
index 00000000..10d8a265
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1FieldElement.java
@@ -0,0 +1,215 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.raw.Mod;
+import org.spongycastle.math.raw.Nat256;
+import org.spongycastle.util.Arrays;
+
+public class SecP256K1FieldElement extends ECFieldElement
+{
+ public static final BigInteger Q = SecP256K1Curve.q;
+
+ protected int[] x;
+
+ public SecP256K1FieldElement(BigInteger x)
+ {
+ if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
+ {
+ throw new IllegalArgumentException("x value invalid for SecP256K1FieldElement");
+ }
+
+ this.x = SecP256K1Field.fromBigInteger(x);
+ }
+
+ public SecP256K1FieldElement()
+ {
+ this.x = Nat256.create();
+ }
+
+ protected SecP256K1FieldElement(int[] x)
+ {
+ this.x = x;
+ }
+
+ public boolean isZero()
+ {
+ return Nat256.isZero(x);
+ }
+
+ public boolean isOne()
+ {
+ return Nat256.isOne(x);
+ }
+
+ public boolean testBitZero()
+ {
+ return Nat256.getBit(x, 0) == 1;
+ }
+
+ public BigInteger toBigInteger()
+ {
+ return Nat256.toBigInteger(x);
+ }
+
+ public String getFieldName()
+ {
+ return "SecP256K1Field";
+ }
+
+ public int getFieldSize()
+ {
+ return Q.bitLength();
+ }
+
+ public ECFieldElement add(ECFieldElement b)
+ {
+ int[] z = Nat256.create();
+ SecP256K1Field.add(x, ((SecP256K1FieldElement)b).x, z);
+ return new SecP256K1FieldElement(z);
+ }
+
+ public ECFieldElement addOne()
+ {
+ int[] z = Nat256.create();
+ SecP256K1Field.addOne(x, z);
+ return new SecP256K1FieldElement(z);
+ }
+
+ public ECFieldElement subtract(ECFieldElement b)
+ {
+ int[] z = Nat256.create();
+ SecP256K1Field.subtract(x, ((SecP256K1FieldElement)b).x, z);
+ return new SecP256K1FieldElement(z);
+ }
+
+ public ECFieldElement multiply(ECFieldElement b)
+ {
+ int[] z = Nat256.create();
+ SecP256K1Field.multiply(x, ((SecP256K1FieldElement)b).x, z);
+ return new SecP256K1FieldElement(z);
+ }
+
+ public ECFieldElement divide(ECFieldElement b)
+ {
+// return multiply(b.invert());
+ int[] z = Nat256.create();
+ Mod.invert(SecP256K1Field.P, ((SecP256K1FieldElement)b).x, z);
+ SecP256K1Field.multiply(z, x, z);
+ return new SecP256K1FieldElement(z);
+ }
+
+ public ECFieldElement negate()
+ {
+ int[] z = Nat256.create();
+ SecP256K1Field.negate(x, z);
+ return new SecP256K1FieldElement(z);
+ }
+
+ public ECFieldElement square()
+ {
+ int[] z = Nat256.create();
+ SecP256K1Field.square(x, z);
+ return new SecP256K1FieldElement(z);
+ }
+
+ public ECFieldElement invert()
+ {
+// return new SecP256K1FieldElement(toBigInteger().modInverse(Q));
+ int[] z = Nat256.create();
+ Mod.invert(SecP256K1Field.P, x, z);
+ return new SecP256K1FieldElement(z);
+ }
+
+ // D.1.4 91
+ /**
+ * return a sqrt root - the routine verifies that the calculation returns the right value - if
+ * none exists it returns null.
+ */
+ public ECFieldElement sqrt()
+ {
+ /*
+ * Raise this element to the exponent 2^254 - 2^30 - 2^7 - 2^6 - 2^5 - 2^4 - 2^2
+ *
+ * Breaking up the exponent's binary representation into "repunits", we get:
+ * { 223 1s } { 1 0s } { 22 1s } { 4 0s } { 2 1s } { 2 0s}
+ *
+ * Therefore we need an addition chain containing 2, 22, 223 (the lengths of the repunits)
+ * We use: 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223]
+ */
+
+ int[] x1 = this.x;
+ if (Nat256.isZero(x1) || Nat256.isOne(x1))
+ {
+ return this;
+ }
+
+ int[] x2 = Nat256.create();
+ SecP256K1Field.square(x1, x2);
+ SecP256K1Field.multiply(x2, x1, x2);
+ int[] x3 = Nat256.create();
+ SecP256K1Field.square(x2, x3);
+ SecP256K1Field.multiply(x3, x1, x3);
+ int[] x6 = Nat256.create();
+ SecP256K1Field.squareN(x3, 3, x6);
+ SecP256K1Field.multiply(x6, x3, x6);
+ int[] x9 = x6;
+ SecP256K1Field.squareN(x6, 3, x9);
+ SecP256K1Field.multiply(x9, x3, x9);
+ int[] x11 = x9;
+ SecP256K1Field.squareN(x9, 2, x11);
+ SecP256K1Field.multiply(x11, x2, x11);
+ int[] x22 = Nat256.create();
+ SecP256K1Field.squareN(x11, 11, x22);
+ SecP256K1Field.multiply(x22, x11, x22);
+ int[] x44 = x11;
+ SecP256K1Field.squareN(x22, 22, x44);
+ SecP256K1Field.multiply(x44, x22, x44);
+ int[] x88 = Nat256.create();
+ SecP256K1Field.squareN(x44, 44, x88);
+ SecP256K1Field.multiply(x88, x44, x88);
+ int[] x176 = Nat256.create();
+ SecP256K1Field.squareN(x88, 88, x176);
+ SecP256K1Field.multiply(x176, x88, x176);
+ int[] x220 = x88;
+ SecP256K1Field.squareN(x176, 44, x220);
+ SecP256K1Field.multiply(x220, x44, x220);
+ int[] x223 = x44;
+ SecP256K1Field.squareN(x220, 3, x223);
+ SecP256K1Field.multiply(x223, x3, x223);
+
+ int[] t1 = x223;
+ SecP256K1Field.squareN(t1, 23, t1);
+ SecP256K1Field.multiply(t1, x22, t1);
+ SecP256K1Field.squareN(t1, 6, t1);
+ SecP256K1Field.multiply(t1, x2, t1);
+ SecP256K1Field.squareN(t1, 2, t1);
+
+ int[] t2 = x2;
+ SecP256K1Field.square(t1, t2);
+
+ return Nat256.eq(x1, t2) ? new SecP256K1FieldElement(t1) : null;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other == this)
+ {
+ return true;
+ }
+
+ if (!(other instanceof SecP256K1FieldElement))
+ {
+ return false;
+ }
+
+ SecP256K1FieldElement o = (SecP256K1FieldElement)other;
+ return Nat256.eq(x, o.x);
+ }
+
+ public int hashCode()
+ {
+ return Q.hashCode() ^ Arrays.hashCode(x, 0, 8);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1Point.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1Point.java
new file mode 100644
index 00000000..fa939431
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1Point.java
@@ -0,0 +1,298 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.raw.Nat;
+import org.spongycastle.math.raw.Nat256;
+
+public class SecP256K1Point extends ECPoint.AbstractFp
+{
+ /**
+ * Create a point which encodes with point compression.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ *
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecP256K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ this(curve, x, y, false);
+ }
+
+ /**
+ * Create a point that encodes with or without point compresion.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ * @param withCompression
+ * if true encode with point compression
+ *
+ * @deprecated per-point compression property will be removed, refer
+ * {@link #getEncoded(boolean)}
+ */
+ public SecP256K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ super(curve, x, y);
+
+ if ((x == null) != (y == null))
+ {
+ throw new IllegalArgumentException("Exactly one of the field elements is null");
+ }
+
+ this.withCompression = withCompression;
+ }
+
+ SecP256K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs,
+ boolean withCompression)
+ {
+ super(curve, x, y, zs);
+
+ this.withCompression = withCompression;
+ }
+
+ protected ECPoint detach()
+ {
+ return new SecP256K1Point(null, getAffineXCoord(), getAffineYCoord());
+ }
+
+ // B.3 pg 62
+ public ECPoint add(ECPoint b)
+ {
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return this;
+ }
+ if (this == b)
+ {
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP256K1FieldElement X1 = (SecP256K1FieldElement)this.x, Y1 = (SecP256K1FieldElement)this.y;
+ SecP256K1FieldElement X2 = (SecP256K1FieldElement)b.getXCoord(), Y2 = (SecP256K1FieldElement)b.getYCoord();
+
+ SecP256K1FieldElement Z1 = (SecP256K1FieldElement)this.zs[0];
+ SecP256K1FieldElement Z2 = (SecP256K1FieldElement)b.getZCoord(0);
+
+ int c;
+ int[] tt1 = Nat256.createExt();
+ int[] t2 = Nat256.create();
+ int[] t3 = Nat256.create();
+ int[] t4 = Nat256.create();
+
+ boolean Z1IsOne = Z1.isOne();
+ int[] U2, S2;
+ if (Z1IsOne)
+ {
+ U2 = X2.x;
+ S2 = Y2.x;
+ }
+ else
+ {
+ S2 = t3;
+ SecP256K1Field.square(Z1.x, S2);
+
+ U2 = t2;
+ SecP256K1Field.multiply(S2, X2.x, U2);
+
+ SecP256K1Field.multiply(S2, Z1.x, S2);
+ SecP256K1Field.multiply(S2, Y2.x, S2);
+ }
+
+ boolean Z2IsOne = Z2.isOne();
+ int[] U1, S1;
+ if (Z2IsOne)
+ {
+ U1 = X1.x;
+ S1 = Y1.x;
+ }
+ else
+ {
+ S1 = t4;
+ SecP256K1Field.square(Z2.x, S1);
+
+ U1 = tt1;
+ SecP256K1Field.multiply(S1, X1.x, U1);
+
+ SecP256K1Field.multiply(S1, Z2.x, S1);
+ SecP256K1Field.multiply(S1, Y1.x, S1);
+ }
+
+ int[] H = Nat256.create();
+ SecP256K1Field.subtract(U1, U2, H);
+
+ int[] R = t2;
+ SecP256K1Field.subtract(S1, S2, R);
+
+ // Check if b == this or b == -this
+ if (Nat256.isZero(H))
+ {
+ if (Nat256.isZero(R))
+ {
+ // this == b, i.e. this must be doubled
+ return this.twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.getInfinity();
+ }
+
+ int[] HSquared = t3;
+ SecP256K1Field.square(H, HSquared);
+
+ int[] G = Nat256.create();
+ SecP256K1Field.multiply(HSquared, H, G);
+
+ int[] V = t3;
+ SecP256K1Field.multiply(HSquared, U1, V);
+
+ SecP256K1Field.negate(G, G);
+ Nat256.mul(S1, G, tt1);
+
+ c = Nat256.addBothTo(V, V, G);
+ SecP256K1Field.reduce32(c, G);
+
+ SecP256K1FieldElement X3 = new SecP256K1FieldElement(t4);
+ SecP256K1Field.square(R, X3.x);
+ SecP256K1Field.subtract(X3.x, G, X3.x);
+
+ SecP256K1FieldElement Y3 = new SecP256K1FieldElement(G);
+ SecP256K1Field.subtract(V, X3.x, Y3.x);
+ SecP256K1Field.multiplyAddToExt(Y3.x, R, tt1);
+ SecP256K1Field.reduce(tt1, Y3.x);
+
+ SecP256K1FieldElement Z3 = new SecP256K1FieldElement(H);
+ if (!Z1IsOne)
+ {
+ SecP256K1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+ if (!Z2IsOne)
+ {
+ SecP256K1Field.multiply(Z3.x, Z2.x, Z3.x);
+ }
+
+ ECFieldElement[] zs = new ECFieldElement[] { Z3 };
+
+ return new SecP256K1Point(curve, X3, Y3, zs, this.withCompression);
+ }
+
+ // B.3 pg 62
+ public ECPoint twice()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP256K1FieldElement Y1 = (SecP256K1FieldElement)this.y;
+ if (Y1.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ SecP256K1FieldElement X1 = (SecP256K1FieldElement)this.x, Z1 = (SecP256K1FieldElement)this.zs[0];
+
+ int c;
+
+ int[] Y1Squared = Nat256.create();
+ SecP256K1Field.square(Y1.x, Y1Squared);
+
+ int[] T = Nat256.create();
+ SecP256K1Field.square(Y1Squared, T);
+
+ int[] M = Nat256.create();
+ SecP256K1Field.square(X1.x, M);
+ c = Nat256.addBothTo(M, M, M);
+ SecP256K1Field.reduce32(c, M);
+
+ int[] S = Y1Squared;
+ SecP256K1Field.multiply(Y1Squared, X1.x, S);
+ c = Nat.shiftUpBits(8, S, 2, 0);
+ SecP256K1Field.reduce32(c, S);
+
+ int[] t1 = Nat256.create();
+ c = Nat.shiftUpBits(8, T, 3, 0, t1);
+ SecP256K1Field.reduce32(c, t1);
+
+ SecP256K1FieldElement X3 = new SecP256K1FieldElement(T);
+ SecP256K1Field.square(M, X3.x);
+ SecP256K1Field.subtract(X3.x, S, X3.x);
+ SecP256K1Field.subtract(X3.x, S, X3.x);
+
+ SecP256K1FieldElement Y3 = new SecP256K1FieldElement(S);
+ SecP256K1Field.subtract(S, X3.x, Y3.x);
+ SecP256K1Field.multiply(Y3.x, M, Y3.x);
+ SecP256K1Field.subtract(Y3.x, t1, Y3.x);
+
+ SecP256K1FieldElement Z3 = new SecP256K1FieldElement(M);
+ SecP256K1Field.twice(Y1.x, Z3.x);
+ if (!Z1.isOne())
+ {
+ SecP256K1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+
+ return new SecP256K1Point(curve, X3, Y3, new ECFieldElement[] { Z3 }, this.withCompression);
+ }
+
+ public ECPoint twicePlus(ECPoint b)
+ {
+ if (this == b)
+ {
+ return threeTimes();
+ }
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return twice();
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return b;
+ }
+
+ return twice().add(b);
+ }
+
+ public ECPoint threeTimes()
+ {
+ if (this.isInfinity() || this.y.isZero())
+ {
+ return this;
+ }
+
+ // NOTE: Be careful about recursions between twicePlus and threeTimes
+ return twice().add(this);
+ }
+
+ public ECPoint negate()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ return new SecP256K1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1Curve.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1Curve.java
new file mode 100644
index 00000000..f856bb34
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1Curve.java
@@ -0,0 +1,80 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.util.encoders.Hex;
+
+public class SecP256R1Curve extends ECCurve.AbstractFp
+{
+ public static final BigInteger q = new BigInteger(1,
+ Hex.decode("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"));
+
+ private static final int SecP256R1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+ protected SecP256R1Point infinity;
+
+ public SecP256R1Curve()
+ {
+ super(q);
+
+ this.infinity = new SecP256R1Point(this, null, null);
+
+ this.a = fromBigInteger(new BigInteger(1,
+ Hex.decode("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC")));
+ this.b = fromBigInteger(new BigInteger(1,
+ Hex.decode("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B")));
+ this.order = new BigInteger(1, Hex.decode("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"));
+ this.cofactor = BigInteger.valueOf(1);
+
+ this.coord = SecP256R1_DEFAULT_COORDS;
+ }
+
+ protected ECCurve cloneCurve()
+ {
+ return new SecP256R1Curve();
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_JACOBIAN:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public int getFieldSize()
+ {
+ return q.bitLength();
+ }
+
+ public ECFieldElement fromBigInteger(BigInteger x)
+ {
+ return new SecP256R1FieldElement(x);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ return new SecP256R1Point(this, x, y, withCompression);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ return new SecP256R1Point(this, x, y, zs, withCompression);
+ }
+
+ public ECPoint getInfinity()
+ {
+ return infinity;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1Field.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1Field.java
new file mode 100644
index 00000000..78c15d17
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1Field.java
@@ -0,0 +1,312 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.raw.Nat;
+import org.spongycastle.math.raw.Nat256;
+
+public class SecP256R1Field
+{
+ private static final long M = 0xFFFFFFFFL;
+
+ // 2^256 - 2^224 + 2^192 + 2^96 - 1
+ static final int[] P = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000001, 0xFFFFFFFF };
+ static final int[] PExt = new int[]{ 0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFE, 0x00000001, 0xFFFFFFFE, 0x00000001, 0xFFFFFFFE, 0x00000001, 0x00000001, 0xFFFFFFFE,
+ 0x00000002, 0xFFFFFFFE };
+ private static final int P7 = 0xFFFFFFFF;
+ private static final int PExt15 = 0xFFFFFFFF;
+
+ public static void add(int[] x, int[] y, int[] z)
+ {
+ int c = Nat256.add(x, y, z);
+ if (c != 0 || (z[7] == P7 && Nat256.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static void addExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.add(16, xx, yy, zz);
+ if (c != 0 || ((zz[15] & PExt15) == PExt15 && Nat.gte(16, zz, PExt)))
+ {
+ Nat.subFrom(16, PExt, zz);
+ }
+ }
+
+ public static void addOne(int[] x, int[] z)
+ {
+ int c = Nat.inc(8, x, z);
+ if (c != 0 || (z[7] == P7 && Nat256.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static int[] fromBigInteger(BigInteger x)
+ {
+ int[] z = Nat256.fromBigInteger(x);
+ if (z[7] == P7 && Nat256.gte(z, P))
+ {
+ Nat256.subFrom(P, z);
+ }
+ return z;
+ }
+
+ public static void half(int[] x, int[] z)
+ {
+ if ((x[0] & 1) == 0)
+ {
+ Nat.shiftDownBit(8, x, 0, z);
+ }
+ else
+ {
+ int c = Nat256.add(x, P, z);
+ Nat.shiftDownBit(8, z, c);
+ }
+ }
+
+ public static void multiply(int[] x, int[] y, int[] z)
+ {
+ int[] tt = Nat256.createExt();
+ Nat256.mul(x, y, tt);
+ reduce(tt, z);
+ }
+
+ public static void multiplyAddToExt(int[] x, int[] y, int[] zz)
+ {
+ int c = Nat256.mulAddTo(x, y, zz);
+ if (c != 0 || ((zz[15] & PExt15) == PExt15 && Nat.gte(16, zz, PExt)))
+ {
+ Nat.subFrom(16, PExt, zz);
+ }
+ }
+
+ public static void negate(int[] x, int[] z)
+ {
+ if (Nat256.isZero(x))
+ {
+ Nat256.zero(z);
+ }
+ else
+ {
+ Nat256.sub(P, x, z);
+ }
+ }
+
+ public static void reduce(int[] xx, int[] z)
+ {
+ long xx08 = xx[8] & M, xx09 = xx[9] & M, xx10 = xx[10] & M, xx11 = xx[11] & M;
+ long xx12 = xx[12] & M, xx13 = xx[13] & M, xx14 = xx[14] & M, xx15 = xx[15] & M;
+
+ final long n = 6;
+
+ xx08 -= n;
+
+ long t0 = xx08 + xx09;
+ long t1 = xx09 + xx10;
+ long t2 = xx10 + xx11 - xx15;
+ long t3 = xx11 + xx12;
+ long t4 = xx12 + xx13;
+ long t5 = xx13 + xx14;
+ long t6 = xx14 + xx15;
+
+ long cc = 0;
+ cc += (xx[0] & M) + t0 - t3 - t5;
+ z[0] = (int)cc;
+ cc >>= 32;
+ cc += (xx[1] & M) + t1 - t4 - t6;
+ z[1] = (int)cc;
+ cc >>= 32;
+ cc += (xx[2] & M) + t2 - t5;
+ z[2] = (int)cc;
+ cc >>= 32;
+ cc += (xx[3] & M) + (t3 << 1) + xx13 - xx15 - t0;
+ z[3] = (int)cc;
+ cc >>= 32;
+ cc += (xx[4] & M) + (t4 << 1) + xx14 - t1;
+ z[4] = (int)cc;
+ cc >>= 32;
+ cc += (xx[5] & M) + (t5 << 1) - t2;
+ z[5] = (int)cc;
+ cc >>= 32;
+ cc += (xx[6] & M) + (t6 << 1) + t5 - t0;
+ z[6] = (int)cc;
+ cc >>= 32;
+ cc += (xx[7] & M) + (xx15 << 1) + xx08 - t2 - t4;
+ z[7] = (int)cc;
+ cc >>= 32;
+ cc += n;
+
+// assert cc >= 0;
+
+ reduce32((int)cc, z);
+ }
+
+ public static void reduce32(int x, int[] z)
+ {
+ long cc = 0;
+
+ if (x != 0)
+ {
+ long xx08 = x & M;
+
+ cc += (z[0] & M) + xx08;
+ z[0] = (int)cc;
+ cc >>= 32;
+ if (cc != 0)
+ {
+ cc += (z[1] & M);
+ z[1] = (int)cc;
+ cc >>= 32;
+ cc += (z[2] & M);
+ z[2] = (int)cc;
+ cc >>= 32;
+ }
+ cc += (z[3] & M) - xx08;
+ z[3] = (int)cc;
+ cc >>= 32;
+ if (cc != 0)
+ {
+ cc += (z[4] & M);
+ z[4] = (int)cc;
+ cc >>= 32;
+ cc += (z[5] & M);
+ z[5] = (int)cc;
+ cc >>= 32;
+ }
+ cc += (z[6] & M) - xx08;
+ z[6] = (int)cc;
+ cc >>= 32;
+ cc += (z[7] & M) + xx08;
+ z[7] = (int)cc;
+ cc >>= 32;
+
+// assert cc == 0 || cc == 1;
+ }
+
+ if (cc != 0 || (z[7] == P7 && Nat256.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static void square(int[] x, int[] z)
+ {
+ int[] tt = Nat256.createExt();
+ Nat256.square(x, tt);
+ reduce(tt, z);
+ }
+
+ public static void squareN(int[] x, int n, int[] z)
+ {
+// assert n > 0;
+
+ int[] tt = Nat256.createExt();
+ Nat256.square(x, tt);
+ reduce(tt, z);
+
+ while (--n > 0)
+ {
+ Nat256.square(z, tt);
+ reduce(tt, z);
+ }
+ }
+
+ public static void subtract(int[] x, int[] y, int[] z)
+ {
+ int c = Nat256.sub(x, y, z);
+ if (c != 0)
+ {
+ subPInvFrom(z);
+ }
+ }
+
+ public static void subtractExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.sub(16, xx, yy, zz);
+ if (c != 0)
+ {
+ Nat.addTo(16, PExt, zz);
+ }
+ }
+
+ public static void twice(int[] x, int[] z)
+ {
+ int c = Nat.shiftUpBit(8, x, 0, z);
+ if (c != 0 || (z[7] == P7 && Nat256.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ private static void addPInvTo(int[] z)
+ {
+ long c = (z[0] & M) + 1;
+ z[0] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (z[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (z[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ }
+ c += (z[3] & M) - 1;
+ z[3] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (z[4] & M);
+ z[4] = (int)c;
+ c >>= 32;
+ c += (z[5] & M);
+ z[5] = (int)c;
+ c >>= 32;
+ }
+ c += (z[6] & M) - 1;
+ z[6] = (int)c;
+ c >>= 32;
+ c += (z[7] & M) + 1;
+ z[7] = (int)c;
+// c >>= 32;
+ }
+
+ private static void subPInvFrom(int[] z)
+ {
+ long c = (z[0] & M) - 1;
+ z[0] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (z[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (z[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ }
+ c += (z[3] & M) + 1;
+ z[3] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (z[4] & M);
+ z[4] = (int)c;
+ c >>= 32;
+ c += (z[5] & M);
+ z[5] = (int)c;
+ c >>= 32;
+ }
+ c += (z[6] & M) + 1;
+ z[6] = (int)c;
+ c >>= 32;
+ c += (z[7] & M) - 1;
+ z[7] = (int)c;
+// c >>= 32;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1FieldElement.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1FieldElement.java
new file mode 100644
index 00000000..ddbab1a3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1FieldElement.java
@@ -0,0 +1,189 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.raw.Mod;
+import org.spongycastle.math.raw.Nat256;
+import org.spongycastle.util.Arrays;
+
+public class SecP256R1FieldElement extends ECFieldElement
+{
+ public static final BigInteger Q = SecP256R1Curve.q;
+
+ protected int[] x;
+
+ public SecP256R1FieldElement(BigInteger x)
+ {
+ if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
+ {
+ throw new IllegalArgumentException("x value invalid for SecP256R1FieldElement");
+ }
+
+ this.x = SecP256R1Field.fromBigInteger(x);
+ }
+
+ public SecP256R1FieldElement()
+ {
+ this.x = Nat256.create();
+ }
+
+ protected SecP256R1FieldElement(int[] x)
+ {
+ this.x = x;
+ }
+
+ public boolean isZero()
+ {
+ return Nat256.isZero(x);
+ }
+
+ public boolean isOne()
+ {
+ return Nat256.isOne(x);
+ }
+
+ public boolean testBitZero()
+ {
+ return Nat256.getBit(x, 0) == 1;
+ }
+
+ public BigInteger toBigInteger()
+ {
+ return Nat256.toBigInteger(x);
+ }
+
+ public String getFieldName()
+ {
+ return "SecP256R1Field";
+ }
+
+ public int getFieldSize()
+ {
+ return Q.bitLength();
+ }
+
+ public ECFieldElement add(ECFieldElement b)
+ {
+ int[] z = Nat256.create();
+ SecP256R1Field.add(x, ((SecP256R1FieldElement)b).x, z);
+ return new SecP256R1FieldElement(z);
+ }
+
+ public ECFieldElement addOne()
+ {
+ int[] z = Nat256.create();
+ SecP256R1Field.addOne(x, z);
+ return new SecP256R1FieldElement(z);
+ }
+
+ public ECFieldElement subtract(ECFieldElement b)
+ {
+ int[] z = Nat256.create();
+ SecP256R1Field.subtract(x, ((SecP256R1FieldElement)b).x, z);
+ return new SecP256R1FieldElement(z);
+ }
+
+ public ECFieldElement multiply(ECFieldElement b)
+ {
+ int[] z = Nat256.create();
+ SecP256R1Field.multiply(x, ((SecP256R1FieldElement)b).x, z);
+ return new SecP256R1FieldElement(z);
+ }
+
+ public ECFieldElement divide(ECFieldElement b)
+ {
+// return multiply(b.invert());
+ int[] z = Nat256.create();
+ Mod.invert(SecP256R1Field.P, ((SecP256R1FieldElement)b).x, z);
+ SecP256R1Field.multiply(z, x, z);
+ return new SecP256R1FieldElement(z);
+ }
+
+ public ECFieldElement negate()
+ {
+ int[] z = Nat256.create();
+ SecP256R1Field.negate(x, z);
+ return new SecP256R1FieldElement(z);
+ }
+
+ public ECFieldElement square()
+ {
+ int[] z = Nat256.create();
+ SecP256R1Field.square(x, z);
+ return new SecP256R1FieldElement(z);
+ }
+
+ public ECFieldElement invert()
+ {
+// return new SecP256R1FieldElement(toBigInteger().modInverse(Q));
+ int[] z = Nat256.create();
+ Mod.invert(SecP256R1Field.P, x, z);
+ return new SecP256R1FieldElement(z);
+ }
+
+ /**
+ * return a sqrt root - the routine verifies that the calculation returns the right value - if
+ * none exists it returns null.
+ */
+ public ECFieldElement sqrt()
+ {
+ // Raise this element to the exponent 2^254 - 2^222 + 2^190 + 2^94
+
+ int[] x1 = this.x;
+ if (Nat256.isZero(x1) || Nat256.isOne(x1))
+ {
+ return this;
+ }
+
+ int[] t1 = Nat256.create();
+ int[] t2 = Nat256.create();
+
+ SecP256R1Field.square(x1, t1);
+ SecP256R1Field.multiply(t1, x1, t1);
+
+ SecP256R1Field.squareN(t1, 2, t2);
+ SecP256R1Field.multiply(t2, t1, t2);
+
+ SecP256R1Field.squareN(t2, 4, t1);
+ SecP256R1Field.multiply(t1, t2, t1);
+
+ SecP256R1Field.squareN(t1, 8, t2);
+ SecP256R1Field.multiply(t2, t1, t2);
+
+ SecP256R1Field.squareN(t2, 16, t1);
+ SecP256R1Field.multiply(t1, t2, t1);
+
+ SecP256R1Field.squareN(t1, 32, t1);
+ SecP256R1Field.multiply(t1, x1, t1);
+
+ SecP256R1Field.squareN(t1, 96, t1);
+ SecP256R1Field.multiply(t1, x1, t1);
+
+ SecP256R1Field.squareN(t1, 94, t1);
+ SecP256R1Field.square(t1, t2);
+
+ return Nat256.eq(x1, t2) ? new SecP256R1FieldElement(t1) : null;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other == this)
+ {
+ return true;
+ }
+
+ if (!(other instanceof SecP256R1FieldElement))
+ {
+ return false;
+ }
+
+ SecP256R1FieldElement o = (SecP256R1FieldElement)other;
+ return Nat256.eq(x, o.x);
+ }
+
+ public int hashCode()
+ {
+ return Q.hashCode() ^ Arrays.hashCode(x, 0, 8);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1Point.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1Point.java
new file mode 100644
index 00000000..8daaf049
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1Point.java
@@ -0,0 +1,308 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.raw.Nat;
+import org.spongycastle.math.raw.Nat256;
+
+public class SecP256R1Point extends ECPoint.AbstractFp
+{
+ /**
+ * Create a point which encodes with point compression.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ *
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecP256R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ this(curve, x, y, false);
+ }
+
+ /**
+ * Create a point that encodes with or without point compresion.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ * @param withCompression
+ * if true encode with point compression
+ *
+ * @deprecated per-point compression property will be removed, refer
+ * {@link #getEncoded(boolean)}
+ */
+ public SecP256R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ super(curve, x, y);
+
+ if ((x == null) != (y == null))
+ {
+ throw new IllegalArgumentException("Exactly one of the field elements is null");
+ }
+
+ this.withCompression = withCompression;
+ }
+
+ SecP256R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ super(curve, x, y, zs);
+
+ this.withCompression = withCompression;
+ }
+
+ protected ECPoint detach()
+ {
+ return new SecP256R1Point(null, getAffineXCoord(), getAffineYCoord());
+ }
+
+ public ECPoint add(ECPoint b)
+ {
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return this;
+ }
+ if (this == b)
+ {
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP256R1FieldElement X1 = (SecP256R1FieldElement)this.x, Y1 = (SecP256R1FieldElement)this.y;
+ SecP256R1FieldElement X2 = (SecP256R1FieldElement)b.getXCoord(), Y2 = (SecP256R1FieldElement)b.getYCoord();
+
+ SecP256R1FieldElement Z1 = (SecP256R1FieldElement)this.zs[0];
+ SecP256R1FieldElement Z2 = (SecP256R1FieldElement)b.getZCoord(0);
+
+ int c;
+ int[] tt1 = Nat256.createExt();
+ int[] t2 = Nat256.create();
+ int[] t3 = Nat256.create();
+ int[] t4 = Nat256.create();
+
+ boolean Z1IsOne = Z1.isOne();
+ int[] U2, S2;
+ if (Z1IsOne)
+ {
+ U2 = X2.x;
+ S2 = Y2.x;
+ }
+ else
+ {
+ S2 = t3;
+ SecP256R1Field.square(Z1.x, S2);
+
+ U2 = t2;
+ SecP256R1Field.multiply(S2, X2.x, U2);
+
+ SecP256R1Field.multiply(S2, Z1.x, S2);
+ SecP256R1Field.multiply(S2, Y2.x, S2);
+ }
+
+ boolean Z2IsOne = Z2.isOne();
+ int[] U1, S1;
+ if (Z2IsOne)
+ {
+ U1 = X1.x;
+ S1 = Y1.x;
+ }
+ else
+ {
+ S1 = t4;
+ SecP256R1Field.square(Z2.x, S1);
+
+ U1 = tt1;
+ SecP256R1Field.multiply(S1, X1.x, U1);
+
+ SecP256R1Field.multiply(S1, Z2.x, S1);
+ SecP256R1Field.multiply(S1, Y1.x, S1);
+ }
+
+ int[] H = Nat256.create();
+ SecP256R1Field.subtract(U1, U2, H);
+
+ int[] R = t2;
+ SecP256R1Field.subtract(S1, S2, R);
+
+ // Check if b == this or b == -this
+ if (Nat256.isZero(H))
+ {
+ if (Nat256.isZero(R))
+ {
+ // this == b, i.e. this must be doubled
+ return this.twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.getInfinity();
+ }
+
+ int[] HSquared = t3;
+ SecP256R1Field.square(H, HSquared);
+
+ int[] G = Nat256.create();
+ SecP256R1Field.multiply(HSquared, H, G);
+
+ int[] V = t3;
+ SecP256R1Field.multiply(HSquared, U1, V);
+
+ SecP256R1Field.negate(G, G);
+ Nat256.mul(S1, G, tt1);
+
+ c = Nat256.addBothTo(V, V, G);
+ SecP256R1Field.reduce32(c, G);
+
+ SecP256R1FieldElement X3 = new SecP256R1FieldElement(t4);
+ SecP256R1Field.square(R, X3.x);
+ SecP256R1Field.subtract(X3.x, G, X3.x);
+
+ SecP256R1FieldElement Y3 = new SecP256R1FieldElement(G);
+ SecP256R1Field.subtract(V, X3.x, Y3.x);
+ SecP256R1Field.multiplyAddToExt(Y3.x, R, tt1);
+ SecP256R1Field.reduce(tt1, Y3.x);
+
+ SecP256R1FieldElement Z3 = new SecP256R1FieldElement(H);
+ if (!Z1IsOne)
+ {
+ SecP256R1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+ if (!Z2IsOne)
+ {
+ SecP256R1Field.multiply(Z3.x, Z2.x, Z3.x);
+ }
+
+ ECFieldElement[] zs = new ECFieldElement[]{ Z3 };
+
+ return new SecP256R1Point(curve, X3, Y3, zs, this.withCompression);
+ }
+
+ public ECPoint twice()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP256R1FieldElement Y1 = (SecP256R1FieldElement)this.y;
+ if (Y1.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ SecP256R1FieldElement X1 = (SecP256R1FieldElement)this.x, Z1 = (SecP256R1FieldElement)this.zs[0];
+
+ int c;
+ int[] t1 = Nat256.create();
+ int[] t2 = Nat256.create();
+
+ int[] Y1Squared = Nat256.create();
+ SecP256R1Field.square(Y1.x, Y1Squared);
+
+ int[] T = Nat256.create();
+ SecP256R1Field.square(Y1Squared, T);
+
+ boolean Z1IsOne = Z1.isOne();
+
+ int[] Z1Squared = Z1.x;
+ if (!Z1IsOne)
+ {
+ Z1Squared = t2;
+ SecP256R1Field.square(Z1.x, Z1Squared);
+ }
+
+ SecP256R1Field.subtract(X1.x, Z1Squared, t1);
+
+ int[] M = t2;
+ SecP256R1Field.add(X1.x, Z1Squared, M);
+ SecP256R1Field.multiply(M, t1, M);
+ c = Nat256.addBothTo(M, M, M);
+ SecP256R1Field.reduce32(c, M);
+
+ int[] S = Y1Squared;
+ SecP256R1Field.multiply(Y1Squared, X1.x, S);
+ c = Nat.shiftUpBits(8, S, 2, 0);
+ SecP256R1Field.reduce32(c, S);
+
+ c = Nat.shiftUpBits(8, T, 3, 0, t1);
+ SecP256R1Field.reduce32(c, t1);
+
+ SecP256R1FieldElement X3 = new SecP256R1FieldElement(T);
+ SecP256R1Field.square(M, X3.x);
+ SecP256R1Field.subtract(X3.x, S, X3.x);
+ SecP256R1Field.subtract(X3.x, S, X3.x);
+
+ SecP256R1FieldElement Y3 = new SecP256R1FieldElement(S);
+ SecP256R1Field.subtract(S, X3.x, Y3.x);
+ SecP256R1Field.multiply(Y3.x, M, Y3.x);
+ SecP256R1Field.subtract(Y3.x, t1, Y3.x);
+
+ SecP256R1FieldElement Z3 = new SecP256R1FieldElement(M);
+ SecP256R1Field.twice(Y1.x, Z3.x);
+ if (!Z1IsOne)
+ {
+ SecP256R1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+
+ return new SecP256R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+
+ public ECPoint twicePlus(ECPoint b)
+ {
+ if (this == b)
+ {
+ return threeTimes();
+ }
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return twice();
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return b;
+ }
+
+ return twice().add(b);
+ }
+
+ public ECPoint threeTimes()
+ {
+ if (this.isInfinity() || this.y.isZero())
+ {
+ return this;
+ }
+
+ // NOTE: Be careful about recursions between twicePlus and threeTimes
+ return twice().add(this);
+ }
+
+ public ECPoint negate()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ return new SecP256R1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1Curve.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1Curve.java
new file mode 100644
index 00000000..cb5bab24
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1Curve.java
@@ -0,0 +1,80 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.util.encoders.Hex;
+
+public class SecP384R1Curve extends ECCurve.AbstractFp
+{
+ public static final BigInteger q = new BigInteger(1,
+ Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF"));
+
+ private static final int SecP384R1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+ protected SecP384R1Point infinity;
+
+ public SecP384R1Curve()
+ {
+ super(q);
+
+ this.infinity = new SecP384R1Point(this, null, null);
+
+ this.a = fromBigInteger(new BigInteger(1,
+ Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC")));
+ this.b = fromBigInteger(new BigInteger(1,
+ Hex.decode("B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF")));
+ this.order = new BigInteger(1, Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973"));
+ this.cofactor = BigInteger.valueOf(1);
+
+ this.coord = SecP384R1_DEFAULT_COORDS;
+ }
+
+ protected ECCurve cloneCurve()
+ {
+ return new SecP384R1Curve();
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_JACOBIAN:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public int getFieldSize()
+ {
+ return q.bitLength();
+ }
+
+ public ECFieldElement fromBigInteger(BigInteger x)
+ {
+ return new SecP384R1FieldElement(x);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ return new SecP384R1Point(this, x, y, withCompression);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ return new SecP384R1Point(this, x, y, zs, withCompression);
+ }
+
+ public ECPoint getInfinity()
+ {
+ return infinity;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1Field.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1Field.java
new file mode 100644
index 00000000..d3b78762
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1Field.java
@@ -0,0 +1,295 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.raw.Nat;
+import org.spongycastle.math.raw.Nat384;
+
+public class SecP384R1Field
+{
+ private static final long M = 0xFFFFFFFFL;
+
+ // 2^384 - 2^128 - 2^96 + 2^32 - 1
+ static final int[] P = new int[]{ 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ static final int[] PExt = new int[]{ 0x00000001, 0xFFFFFFFE, 0x00000000, 0x00000002, 0x00000000, 0xFFFFFFFE,
+ 0x00000000, 0x00000002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFE, 0x00000001, 0x00000000,
+ 0xFFFFFFFE, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ private static final int[] PExtInv = new int[]{ 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0x00000001,
+ 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001, 0xFFFFFFFE, 0xFFFFFFFF,
+ 0x00000001, 0x00000002 };
+ private static final int P11 = 0xFFFFFFFF;
+ private static final int PExt23 = 0xFFFFFFFF;
+
+ public static void add(int[] x, int[] y, int[] z)
+ {
+ int c = Nat.add(12, x, y, z);
+ if (c != 0 || (z[11] == P11 && Nat.gte(12, z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static void addExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.add(24, xx, yy, zz);
+ if (c != 0 || (zz[23] == PExt23 && Nat.gte(24, zz, PExt)))
+ {
+ if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.incAt(24, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void addOne(int[] x, int[] z)
+ {
+ int c = Nat.inc(12, x, z);
+ if (c != 0 || (z[11] == P11 && Nat.gte(12, z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static int[] fromBigInteger(BigInteger x)
+ {
+ int[] z = Nat.fromBigInteger(384, x);
+ if (z[11] == P11 && Nat.gte(12, z, P))
+ {
+ Nat.subFrom(12, P, z);
+ }
+ return z;
+ }
+
+ public static void half(int[] x, int[] z)
+ {
+ if ((x[0] & 1) == 0)
+ {
+ Nat.shiftDownBit(12, x, 0, z);
+ }
+ else
+ {
+ int c = Nat.add(12, x, P, z);
+ Nat.shiftDownBit(12, z, c);
+ }
+ }
+
+ public static void multiply(int[] x, int[] y, int[] z)
+ {
+ int[] tt = Nat.create(24);
+ Nat384.mul(x, y, tt);
+ reduce(tt, z);
+ }
+
+ public static void negate(int[] x, int[] z)
+ {
+ if (Nat.isZero(12, x))
+ {
+ Nat.zero(12, z);
+ }
+ else
+ {
+ Nat.sub(12, P, x, z);
+ }
+ }
+
+ public static void reduce(int[] xx, int[] z)
+ {
+ long xx16 = xx[16] & M, xx17 = xx[17] & M, xx18 = xx[18] & M, xx19 = xx[19] & M;
+ long xx20 = xx[20] & M, xx21 = xx[21] & M, xx22 = xx[22] & M, xx23 = xx[23] & M;
+
+ final long n = 1;
+
+ long t0 = (xx[12] & M) + xx20 - n;
+ long t1 = (xx[13] & M) + xx22;
+ long t2 = (xx[14] & M) + xx22 + xx23;
+ long t3 = (xx[15] & M) + xx23;
+ long t4 = xx17 + xx21;
+ long t5 = xx21 - xx23;
+ long t6 = xx22 - xx23;
+
+ long cc = 0;
+ cc += (xx[0] & M) + t0 + t5;
+ z[0] = (int)cc;
+ cc >>= 32;
+ cc += (xx[1] & M) + xx23 - t0 + t1;
+ z[1] = (int)cc;
+ cc >>= 32;
+ cc += (xx[2] & M) - xx21 - t1 + t2;
+ z[2] = (int)cc;
+ cc >>= 32;
+ cc += (xx[3] & M) + t0 - t2 + t3 + t5;
+ z[3] = (int)cc;
+ cc >>= 32;
+ cc += (xx[4] & M) + xx16 + xx21 + t0 + t1 - t3 + t5;
+ z[4] = (int)cc;
+ cc >>= 32;
+ cc += (xx[5] & M) - xx16 + t1 + t2 + t4;
+ z[5] = (int)cc;
+ cc >>= 32;
+ cc += (xx[6] & M) + xx18 - xx17 + t2 + t3;
+ z[6] = (int)cc;
+ cc >>= 32;
+ cc += (xx[7] & M) + xx16 + xx19 - xx18 + t3;
+ z[7] = (int)cc;
+ cc >>= 32;
+ cc += (xx[8] & M) + xx16 + xx17 + xx20 - xx19;
+ z[8] = (int)cc;
+ cc >>= 32;
+ cc += (xx[9] & M) + xx18 - xx20 + t4;
+ z[9] = (int)cc;
+ cc >>= 32;
+ cc += (xx[10] & M) + xx18 + xx19 - t5 + t6;
+ z[10] = (int)cc;
+ cc >>= 32;
+ cc += (xx[11] & M) + xx19 + xx20 - t6;
+ z[11] = (int)cc;
+ cc >>= 32;
+ cc += n;
+
+// assert cc >= 0;
+
+ reduce32((int)cc, z);
+ }
+
+ public static void reduce32(int x, int[] z)
+ {
+ long cc = 0;
+
+ if (x != 0)
+ {
+ long xx12 = x & M;
+
+ cc += (z[0] & M) + xx12;
+ z[0] = (int)cc;
+ cc >>= 32;
+ cc += (z[1] & M) - xx12;
+ z[1] = (int)cc;
+ cc >>= 32;
+ if (cc != 0)
+ {
+ cc += (z[2] & M);
+ z[2] = (int)cc;
+ cc >>= 32;
+ }
+ cc += (z[3] & M) + xx12;
+ z[3] = (int)cc;
+ cc >>= 32;
+ cc += (z[4] & M) + xx12;
+ z[4] = (int)cc;
+ cc >>= 32;
+
+// assert cc == 0 || cc == 1;
+ }
+
+ if ((cc != 0 && Nat.incAt(12, z, 5) != 0)
+ || (z[11] == P11 && Nat.gte(12, z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static void square(int[] x, int[] z)
+ {
+ int[] tt = Nat.create(24);
+ Nat384.square(x, tt);
+ reduce(tt, z);
+ }
+
+ public static void squareN(int[] x, int n, int[] z)
+ {
+// assert n > 0;
+
+ int[] tt = Nat.create(24);
+ Nat384.square(x, tt);
+ reduce(tt, z);
+
+ while (--n > 0)
+ {
+ Nat384.square(z, tt);
+ reduce(tt, z);
+ }
+ }
+
+ public static void subtract(int[] x, int[] y, int[] z)
+ {
+ int c = Nat.sub(12, x, y, z);
+ if (c != 0)
+ {
+ subPInvFrom(z);
+ }
+ }
+
+ public static void subtractExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.sub(24, xx, yy, zz);
+ if (c != 0)
+ {
+ if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.decAt(24, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void twice(int[] x, int[] z)
+ {
+ int c = Nat.shiftUpBit(12, x, 0, z);
+ if (c != 0 || (z[11] == P11 && Nat.gte(12, z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ private static void addPInvTo(int[] z)
+ {
+ long c = (z[0] & M) + 1;
+ z[0] = (int)c;
+ c >>= 32;
+ c += (z[1] & M) - 1;
+ z[1] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (z[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ }
+ c += (z[3] & M) + 1;
+ z[3] = (int)c;
+ c >>= 32;
+ c += (z[4] & M) + 1;
+ z[4] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ Nat.incAt(12, z, 5);
+ }
+ }
+
+ private static void subPInvFrom(int[] z)
+ {
+ long c = (z[0] & M) - 1;
+ z[0] = (int)c;
+ c >>= 32;
+ c += (z[1] & M) + 1;
+ z[1] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (z[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ }
+ c += (z[3] & M) - 1;
+ z[3] = (int)c;
+ c >>= 32;
+ c += (z[4] & M) - 1;
+ z[4] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ Nat.decAt(12, z, 5);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1FieldElement.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1FieldElement.java
new file mode 100644
index 00000000..3203bda9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1FieldElement.java
@@ -0,0 +1,211 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.raw.Mod;
+import org.spongycastle.math.raw.Nat;
+import org.spongycastle.util.Arrays;
+
+public class SecP384R1FieldElement extends ECFieldElement
+{
+ public static final BigInteger Q = SecP384R1Curve.q;
+
+ protected int[] x;
+
+ public SecP384R1FieldElement(BigInteger x)
+ {
+ if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
+ {
+ throw new IllegalArgumentException("x value invalid for SecP384R1FieldElement");
+ }
+
+ this.x = SecP384R1Field.fromBigInteger(x);
+ }
+
+ public SecP384R1FieldElement()
+ {
+ this.x = Nat.create(12);
+ }
+
+ protected SecP384R1FieldElement(int[] x)
+ {
+ this.x = x;
+ }
+
+ public boolean isZero()
+ {
+ return Nat.isZero(12, x);
+ }
+
+ public boolean isOne()
+ {
+ return Nat.isOne(12, x);
+ }
+
+ public boolean testBitZero()
+ {
+ return Nat.getBit(x, 0) == 1;
+ }
+
+ public BigInteger toBigInteger()
+ {
+ return Nat.toBigInteger(12, x);
+ }
+
+ public String getFieldName()
+ {
+ return "SecP384R1Field";
+ }
+
+ public int getFieldSize()
+ {
+ return Q.bitLength();
+ }
+
+ public ECFieldElement add(ECFieldElement b)
+ {
+ int[] z = Nat.create(12);
+ SecP384R1Field.add(x, ((SecP384R1FieldElement)b).x, z);
+ return new SecP384R1FieldElement(z);
+ }
+
+ public ECFieldElement addOne()
+ {
+ int[] z = Nat.create(12);
+ SecP384R1Field.addOne(x, z);
+ return new SecP384R1FieldElement(z);
+ }
+
+ public ECFieldElement subtract(ECFieldElement b)
+ {
+ int[] z = Nat.create(12);
+ SecP384R1Field.subtract(x, ((SecP384R1FieldElement)b).x, z);
+ return new SecP384R1FieldElement(z);
+ }
+
+ public ECFieldElement multiply(ECFieldElement b)
+ {
+ int[] z = Nat.create(12);
+ SecP384R1Field.multiply(x, ((SecP384R1FieldElement)b).x, z);
+ return new SecP384R1FieldElement(z);
+ }
+
+ public ECFieldElement divide(ECFieldElement b)
+ {
+// return multiply(b.invert());
+ int[] z = Nat.create(12);
+ Mod.invert(SecP384R1Field.P, ((SecP384R1FieldElement)b).x, z);
+ SecP384R1Field.multiply(z, x, z);
+ return new SecP384R1FieldElement(z);
+ }
+
+ public ECFieldElement negate()
+ {
+ int[] z = Nat.create(12);
+ SecP384R1Field.negate(x, z);
+ return new SecP384R1FieldElement(z);
+ }
+
+ public ECFieldElement square()
+ {
+ int[] z = Nat.create(12);
+ SecP384R1Field.square(x, z);
+ return new SecP384R1FieldElement(z);
+ }
+
+ public ECFieldElement invert()
+ {
+// return new SecP384R1FieldElement(toBigInteger().modInverse(Q));
+ int[] z = Nat.create(12);
+ Mod.invert(SecP384R1Field.P, x, z);
+ return new SecP384R1FieldElement(z);
+ }
+
+ /**
+ * return a sqrt root - the routine verifies that the calculation returns the right value - if
+ * none exists it returns null.
+ */
+ public ECFieldElement sqrt()
+ {
+ // Raise this element to the exponent 2^382 - 2^126 - 2^94 + 2^30
+
+ int[] x1 = this.x;
+ if (Nat.isZero(12, x1) || Nat.isOne(12, x1))
+ {
+ return this;
+ }
+
+ int[] t1 = Nat.create(12);
+ int[] t2 = Nat.create(12);
+ int[] t3 = Nat.create(12);
+ int[] t4 = Nat.create(12);
+
+ SecP384R1Field.square(x1, t1);
+ SecP384R1Field.multiply(t1, x1, t1);
+
+ SecP384R1Field.squareN(t1, 2, t2);
+ SecP384R1Field.multiply(t2, t1, t2);
+
+ SecP384R1Field.square(t2, t2);
+ SecP384R1Field.multiply(t2, x1, t2);
+
+ SecP384R1Field.squareN(t2, 5, t3);
+ SecP384R1Field.multiply(t3, t2, t3);
+
+ SecP384R1Field.squareN(t3, 5, t4);
+ SecP384R1Field.multiply(t4, t2, t4);
+
+ SecP384R1Field.squareN(t4, 15, t2);
+ SecP384R1Field.multiply(t2, t4, t2);
+
+ SecP384R1Field.squareN(t2, 2, t3);
+ SecP384R1Field.multiply(t1, t3, t1);
+
+ SecP384R1Field.squareN(t3, 28, t3);
+ SecP384R1Field.multiply(t2, t3, t2);
+
+ SecP384R1Field.squareN(t2, 60, t3);
+ SecP384R1Field.multiply(t3, t2, t3);
+
+ int[] r = t2;
+
+ SecP384R1Field.squareN(t3, 120, r);
+ SecP384R1Field.multiply(r, t3, r);
+
+ SecP384R1Field.squareN(r, 15, r);
+ SecP384R1Field.multiply(r, t4, r);
+
+ SecP384R1Field.squareN(r, 33, r);
+ SecP384R1Field.multiply(r, t1, r);
+
+ SecP384R1Field.squareN(r, 64, r);
+ SecP384R1Field.multiply(r, x1, r);
+
+ SecP384R1Field.squareN(r, 30, t1);
+ SecP384R1Field.square(t1, t2);
+
+ return Nat.eq(12, x1, t2) ? new SecP384R1FieldElement(t1) : null;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other == this)
+ {
+ return true;
+ }
+
+ if (!(other instanceof SecP384R1FieldElement))
+ {
+ return false;
+ }
+
+ SecP384R1FieldElement o = (SecP384R1FieldElement)other;
+ return Nat.eq(12, x, o.x);
+ }
+
+ public int hashCode()
+ {
+ return Q.hashCode() ^ Arrays.hashCode(x, 0, 12);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1Point.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1Point.java
new file mode 100644
index 00000000..47e5c793
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1Point.java
@@ -0,0 +1,309 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.raw.Nat;
+import org.spongycastle.math.raw.Nat384;
+
+public class SecP384R1Point extends ECPoint.AbstractFp
+{
+ /**
+ * Create a point which encodes with point compression.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ *
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecP384R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ this(curve, x, y, false);
+ }
+
+ /**
+ * Create a point that encodes with or without point compresion.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ * @param withCompression
+ * if true encode with point compression
+ *
+ * @deprecated per-point compression property will be removed, refer
+ * {@link #getEncoded(boolean)}
+ */
+ public SecP384R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ super(curve, x, y);
+
+ if ((x == null) != (y == null))
+ {
+ throw new IllegalArgumentException("Exactly one of the field elements is null");
+ }
+
+ this.withCompression = withCompression;
+ }
+
+ SecP384R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ super(curve, x, y, zs);
+
+ this.withCompression = withCompression;
+ }
+
+ protected ECPoint detach()
+ {
+ return new SecP384R1Point(null, getAffineXCoord(), getAffineYCoord());
+ }
+
+ public ECPoint add(ECPoint b)
+ {
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return this;
+ }
+ if (this == b)
+ {
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP384R1FieldElement X1 = (SecP384R1FieldElement)this.x, Y1 = (SecP384R1FieldElement)this.y;
+ SecP384R1FieldElement X2 = (SecP384R1FieldElement)b.getXCoord(), Y2 = (SecP384R1FieldElement)b.getYCoord();
+
+ SecP384R1FieldElement Z1 = (SecP384R1FieldElement)this.zs[0];
+ SecP384R1FieldElement Z2 = (SecP384R1FieldElement)b.getZCoord(0);
+
+ int c;
+ int[] tt1 = Nat.create(24);
+ int[] tt2 = Nat.create(24);
+ int[] t3 = Nat.create(12);
+ int[] t4 = Nat.create(12);
+
+ boolean Z1IsOne = Z1.isOne();
+ int[] U2, S2;
+ if (Z1IsOne)
+ {
+ U2 = X2.x;
+ S2 = Y2.x;
+ }
+ else
+ {
+ S2 = t3;
+ SecP384R1Field.square(Z1.x, S2);
+
+ U2 = tt2;
+ SecP384R1Field.multiply(S2, X2.x, U2);
+
+ SecP384R1Field.multiply(S2, Z1.x, S2);
+ SecP384R1Field.multiply(S2, Y2.x, S2);
+ }
+
+ boolean Z2IsOne = Z2.isOne();
+ int[] U1, S1;
+ if (Z2IsOne)
+ {
+ U1 = X1.x;
+ S1 = Y1.x;
+ }
+ else
+ {
+ S1 = t4;
+ SecP384R1Field.square(Z2.x, S1);
+
+ U1 = tt1;
+ SecP384R1Field.multiply(S1, X1.x, U1);
+
+ SecP384R1Field.multiply(S1, Z2.x, S1);
+ SecP384R1Field.multiply(S1, Y1.x, S1);
+ }
+
+ int[] H = Nat.create(12);
+ SecP384R1Field.subtract(U1, U2, H);
+
+ int[] R = Nat.create(12);
+ SecP384R1Field.subtract(S1, S2, R);
+
+ // Check if b == this or b == -this
+ if (Nat.isZero(12, H))
+ {
+ if (Nat.isZero(12, R))
+ {
+ // this == b, i.e. this must be doubled
+ return this.twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.getInfinity();
+ }
+
+ int[] HSquared = t3;
+ SecP384R1Field.square(H, HSquared);
+
+ int[] G = Nat.create(12);
+ SecP384R1Field.multiply(HSquared, H, G);
+
+ int[] V = t3;
+ SecP384R1Field.multiply(HSquared, U1, V);
+
+ SecP384R1Field.negate(G, G);
+ Nat384.mul(S1, G, tt1);
+
+ c = Nat.addBothTo(12, V, V, G);
+ SecP384R1Field.reduce32(c, G);
+
+ SecP384R1FieldElement X3 = new SecP384R1FieldElement(t4);
+ SecP384R1Field.square(R, X3.x);
+ SecP384R1Field.subtract(X3.x, G, X3.x);
+
+ SecP384R1FieldElement Y3 = new SecP384R1FieldElement(G);
+ SecP384R1Field.subtract(V, X3.x, Y3.x);
+ Nat384.mul(Y3.x, R, tt2);
+ SecP384R1Field.addExt(tt1, tt2, tt1);
+ SecP384R1Field.reduce(tt1, Y3.x);
+
+ SecP384R1FieldElement Z3 = new SecP384R1FieldElement(H);
+ if (!Z1IsOne)
+ {
+ SecP384R1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+ if (!Z2IsOne)
+ {
+ SecP384R1Field.multiply(Z3.x, Z2.x, Z3.x);
+ }
+
+ ECFieldElement[] zs = new ECFieldElement[]{ Z3 };
+
+ return new SecP384R1Point(curve, X3, Y3, zs, this.withCompression);
+ }
+
+ public ECPoint twice()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP384R1FieldElement Y1 = (SecP384R1FieldElement)this.y;
+ if (Y1.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ SecP384R1FieldElement X1 = (SecP384R1FieldElement)this.x, Z1 = (SecP384R1FieldElement)this.zs[0];
+
+ int c;
+ int[] t1 = Nat.create(12);
+ int[] t2 = Nat.create(12);
+
+ int[] Y1Squared = Nat.create(12);
+ SecP384R1Field.square(Y1.x, Y1Squared);
+
+ int[] T = Nat.create(12);
+ SecP384R1Field.square(Y1Squared, T);
+
+ boolean Z1IsOne = Z1.isOne();
+
+ int[] Z1Squared = Z1.x;
+ if (!Z1IsOne)
+ {
+ Z1Squared = t2;
+ SecP384R1Field.square(Z1.x, Z1Squared);
+ }
+
+ SecP384R1Field.subtract(X1.x, Z1Squared, t1);
+
+ int[] M = t2;
+ SecP384R1Field.add(X1.x, Z1Squared, M);
+ SecP384R1Field.multiply(M, t1, M);
+ c = Nat.addBothTo(12, M, M, M);
+ SecP384R1Field.reduce32(c, M);
+
+ int[] S = Y1Squared;
+ SecP384R1Field.multiply(Y1Squared, X1.x, S);
+ c = Nat.shiftUpBits(12, S, 2, 0);
+ SecP384R1Field.reduce32(c, S);
+
+ c = Nat.shiftUpBits(12, T, 3, 0, t1);
+ SecP384R1Field.reduce32(c, t1);
+
+ SecP384R1FieldElement X3 = new SecP384R1FieldElement(T);
+ SecP384R1Field.square(M, X3.x);
+ SecP384R1Field.subtract(X3.x, S, X3.x);
+ SecP384R1Field.subtract(X3.x, S, X3.x);
+
+ SecP384R1FieldElement Y3 = new SecP384R1FieldElement(S);
+ SecP384R1Field.subtract(S, X3.x, Y3.x);
+ SecP384R1Field.multiply(Y3.x, M, Y3.x);
+ SecP384R1Field.subtract(Y3.x, t1, Y3.x);
+
+ SecP384R1FieldElement Z3 = new SecP384R1FieldElement(M);
+ SecP384R1Field.twice(Y1.x, Z3.x);
+ if (!Z1IsOne)
+ {
+ SecP384R1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+
+ return new SecP384R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+
+ public ECPoint twicePlus(ECPoint b)
+ {
+ if (this == b)
+ {
+ return threeTimes();
+ }
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return twice();
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return b;
+ }
+
+ return twice().add(b);
+ }
+
+ public ECPoint threeTimes()
+ {
+ if (this.isInfinity() || this.y.isZero())
+ {
+ return this;
+ }
+
+ // NOTE: Be careful about recursions between twicePlus and threeTimes
+ return twice().add(this);
+ }
+
+ public ECPoint negate()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ return new SecP384R1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1Curve.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1Curve.java
new file mode 100644
index 00000000..fb53cfbb
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1Curve.java
@@ -0,0 +1,80 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.util.encoders.Hex;
+
+public class SecP521R1Curve extends ECCurve.AbstractFp
+{
+ public static final BigInteger q = new BigInteger(1,
+ Hex.decode("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));
+
+ private static final int SecP521R1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+ protected SecP521R1Point infinity;
+
+ public SecP521R1Curve()
+ {
+ super(q);
+
+ this.infinity = new SecP521R1Point(this, null, null);
+
+ this.a = fromBigInteger(new BigInteger(1,
+ Hex.decode("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC")));
+ this.b = fromBigInteger(new BigInteger(1,
+ Hex.decode("0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00")));
+ this.order = new BigInteger(1, Hex.decode("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409"));
+ this.cofactor = BigInteger.valueOf(1);
+
+ this.coord = SecP521R1_DEFAULT_COORDS;
+ }
+
+ protected ECCurve cloneCurve()
+ {
+ return new SecP521R1Curve();
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_JACOBIAN:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public int getFieldSize()
+ {
+ return q.bitLength();
+ }
+
+ public ECFieldElement fromBigInteger(BigInteger x)
+ {
+ return new SecP521R1FieldElement(x);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ return new SecP521R1Point(this, x, y, withCompression);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ return new SecP521R1Point(this, x, y, zs, withCompression);
+ }
+
+ public ECPoint getInfinity()
+ {
+ return infinity;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1Field.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1Field.java
new file mode 100644
index 00000000..5328a510
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1Field.java
@@ -0,0 +1,156 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.raw.Nat;
+import org.spongycastle.math.raw.Nat512;
+
+public class SecP521R1Field
+{
+ // 2^521 - 1
+ static final int[] P = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x1FF };
+ private static final int P16 = 0x1FF;
+
+ public static void add(int[] x, int[] y, int[] z)
+ {
+ int c = Nat.add(16, x, y, z) + x[16] + y[16];
+ if (c > P16 || (c == P16 && Nat.eq(16, z, P)))
+ {
+ c += Nat.inc(16, z);
+ c &= P16;
+ }
+ z[16] = c;
+ }
+
+ public static void addOne(int[] x, int[] z)
+ {
+ int c = Nat.inc(16, x, z) + x[16];
+ if (c > P16 || (c == P16 && Nat.eq(16, z, P)))
+ {
+ c += Nat.inc(16, z);
+ c &= P16;
+ }
+ z[16] = c;
+ }
+
+ public static int[] fromBigInteger(BigInteger x)
+ {
+ int[] z = Nat.fromBigInteger(521, x);
+ if (Nat.eq(17, z, P))
+ {
+ Nat.zero(17, z);
+ }
+ return z;
+ }
+
+ public static void half(int[] x, int[] z)
+ {
+ int x16 = x[16];
+ int c = Nat.shiftDownBit(16, x, x16, z);
+ z[16] = (x16 >>> 1) | (c >>> 23);
+ }
+
+ public static void multiply(int[] x, int[] y, int[] z)
+ {
+ int[] tt = Nat.create(33);
+ implMultiply(x, y, tt);
+ reduce(tt, z);
+ }
+
+ public static void negate(int[] x, int[] z)
+ {
+ if (Nat.isZero(17, x))
+ {
+ Nat.zero(17, z);
+ }
+ else
+ {
+ Nat.sub(17, P, x, z);
+ }
+ }
+
+ public static void reduce(int[] xx, int[] z)
+ {
+// assert xx[32] >>> 18 == 0;
+
+ int xx32 = xx[32];
+ int c = Nat.shiftDownBits(16, xx, 16, 9, xx32, z, 0) >>> 23;
+ c += xx32 >>> 9;
+ c += Nat.addTo(16, xx, z);
+ if (c > P16 || (c == P16 && Nat.eq(16, z, P)))
+ {
+ c += Nat.inc(16, z);
+ c &= P16;
+ }
+ z[16] = c;
+ }
+
+ public static void reduce23(int[] z)
+ {
+ int z16 = z[16];
+ int c = Nat.addWordTo(16, z16 >>> 9, z) + (z16 & P16);
+ if (c > P16 || (c == P16 && Nat.eq(16, z, P)))
+ {
+ c += Nat.inc(16, z);
+ c &= P16;
+ }
+ z[16] = c;
+ }
+
+ public static void square(int[] x, int[] z)
+ {
+ int[] tt = Nat.create(33);
+ implSquare(x, tt);
+ reduce(tt, z);
+ }
+
+ public static void squareN(int[] x, int n, int[] z)
+ {
+// assert n > 0;
+
+ int[] tt = Nat.create(33);
+ implSquare(x, tt);
+ reduce(tt, z);
+
+ while (--n > 0)
+ {
+ implSquare(z, tt);
+ reduce(tt, z);
+ }
+ }
+
+ public static void subtract(int[] x, int[] y, int[] z)
+ {
+ int c = Nat.sub(16, x, y, z) + x[16] - y[16];
+ if (c < 0)
+ {
+ c += Nat.dec(16, z);
+ c &= P16;
+ }
+ z[16] = c;
+ }
+
+ public static void twice(int[] x, int[] z)
+ {
+ int x16 = x[16];
+ int c = Nat.shiftUpBit(16, x, x16 << 23, z) | (x16 << 1);
+ z[16] = c & P16;
+ }
+
+ protected static void implMultiply(int[] x, int[] y, int[] zz)
+ {
+ Nat512.mul(x, y, zz);
+
+ int x16 = x[16], y16 = y[16];
+ zz[32] = Nat.mul31BothAdd(16, x16, y, y16, x, zz, 16) + (x16 * y16);
+ }
+
+ protected static void implSquare(int[] x, int[] zz)
+ {
+ Nat512.square(x, zz);
+
+ int x16 = x[16];
+ zz[32] = Nat.mulWordAddTo(16, x16 << 1, x, 0, zz, 16) + (x16 * x16);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1FieldElement.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1FieldElement.java
new file mode 100644
index 00000000..b0b92b6e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1FieldElement.java
@@ -0,0 +1,169 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.raw.Mod;
+import org.spongycastle.math.raw.Nat;
+import org.spongycastle.util.Arrays;
+
+public class SecP521R1FieldElement extends ECFieldElement
+{
+ public static final BigInteger Q = SecP521R1Curve.q;
+
+ protected int[] x;
+
+ public SecP521R1FieldElement(BigInteger x)
+ {
+ if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
+ {
+ throw new IllegalArgumentException("x value invalid for SecP521R1FieldElement");
+ }
+
+ this.x = SecP521R1Field.fromBigInteger(x);
+ }
+
+ public SecP521R1FieldElement()
+ {
+ this.x = Nat.create(17);
+ }
+
+ protected SecP521R1FieldElement(int[] x)
+ {
+ this.x = x;
+ }
+
+ public boolean isZero()
+ {
+ return Nat.isZero(17, x);
+ }
+
+ public boolean isOne()
+ {
+ return Nat.isOne(17, x);
+ }
+
+ public boolean testBitZero()
+ {
+ return Nat.getBit(x, 0) == 1;
+ }
+
+ public BigInteger toBigInteger()
+ {
+ return Nat.toBigInteger(17, x);
+ }
+
+ public String getFieldName()
+ {
+ return "SecP521R1Field";
+ }
+
+ public int getFieldSize()
+ {
+ return Q.bitLength();
+ }
+
+ public ECFieldElement add(ECFieldElement b)
+ {
+ int[] z = Nat.create(17);
+ SecP521R1Field.add(x, ((SecP521R1FieldElement)b).x, z);
+ return new SecP521R1FieldElement(z);
+ }
+
+ public ECFieldElement addOne()
+ {
+ int[] z = Nat.create(17);
+ SecP521R1Field.addOne(x, z);
+ return new SecP521R1FieldElement(z);
+ }
+
+ public ECFieldElement subtract(ECFieldElement b)
+ {
+ int[] z = Nat.create(17);
+ SecP521R1Field.subtract(x, ((SecP521R1FieldElement)b).x, z);
+ return new SecP521R1FieldElement(z);
+ }
+
+ public ECFieldElement multiply(ECFieldElement b)
+ {
+ int[] z = Nat.create(17);
+ SecP521R1Field.multiply(x, ((SecP521R1FieldElement)b).x, z);
+ return new SecP521R1FieldElement(z);
+ }
+
+ public ECFieldElement divide(ECFieldElement b)
+ {
+// return multiply(b.invert());
+ int[] z = Nat.create(17);
+ Mod.invert(SecP521R1Field.P, ((SecP521R1FieldElement)b).x, z);
+ SecP521R1Field.multiply(z, x, z);
+ return new SecP521R1FieldElement(z);
+ }
+
+ public ECFieldElement negate()
+ {
+ int[] z = Nat.create(17);
+ SecP521R1Field.negate(x, z);
+ return new SecP521R1FieldElement(z);
+ }
+
+ public ECFieldElement square()
+ {
+ int[] z = Nat.create(17);
+ SecP521R1Field.square(x, z);
+ return new SecP521R1FieldElement(z);
+ }
+
+ public ECFieldElement invert()
+ {
+// return new SecP521R1FieldElement(toBigInteger().modInverse(Q));
+ int[] z = Nat.create(17);
+ Mod.invert(SecP521R1Field.P, x, z);
+ return new SecP521R1FieldElement(z);
+ }
+
+ // D.1.4 91
+ /**
+ * return a sqrt root - the routine verifies that the calculation returns the right value - if
+ * none exists it returns null.
+ */
+ public ECFieldElement sqrt()
+ {
+ // Raise this element to the exponent 2^519
+
+ int[] x1 = this.x;
+ if (Nat.isZero(17, x1) || Nat.isOne(17, x1))
+ {
+ return this;
+ }
+
+ int[] t1 = Nat.create(17);
+ int[] t2 = Nat.create(17);
+
+ SecP521R1Field.squareN(x1, 519, t1);
+ SecP521R1Field.square(t1, t2);
+
+ return Nat.eq(17, x1, t2) ? new SecP521R1FieldElement(t1) : null;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other == this)
+ {
+ return true;
+ }
+
+ if (!(other instanceof SecP521R1FieldElement))
+ {
+ return false;
+ }
+
+ SecP521R1FieldElement o = (SecP521R1FieldElement)other;
+ return Nat.eq(17, x, o.x);
+ }
+
+ public int hashCode()
+ {
+ return Q.hashCode() ^ Arrays.hashCode(x, 0, 17);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1Point.java b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1Point.java
new file mode 100644
index 00000000..c38132b5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1Point.java
@@ -0,0 +1,333 @@
+package org.spongycastle.math.ec.custom.sec;
+
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.math.raw.Nat;
+
+public class SecP521R1Point extends ECPoint.AbstractFp
+{
+ /**
+ * Create a point which encodes with point compression.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ *
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecP521R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ this(curve, x, y, false);
+ }
+
+ /**
+ * Create a point that encodes with or without point compresion.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ * @param withCompression
+ * if true encode with point compression
+ *
+ * @deprecated per-point compression property will be removed, refer
+ * {@link #getEncoded(boolean)}
+ */
+ public SecP521R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ super(curve, x, y);
+
+ if ((x == null) != (y == null))
+ {
+ throw new IllegalArgumentException("Exactly one of the field elements is null");
+ }
+
+ this.withCompression = withCompression;
+ }
+
+ SecP521R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ super(curve, x, y, zs);
+
+ this.withCompression = withCompression;
+ }
+
+ protected ECPoint detach()
+ {
+ return new SecP521R1Point(null, getAffineXCoord(), getAffineYCoord());
+ }
+
+ public ECPoint add(ECPoint b)
+ {
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return this;
+ }
+ if (this == b)
+ {
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP521R1FieldElement X1 = (SecP521R1FieldElement)this.x, Y1 = (SecP521R1FieldElement)this.y;
+ SecP521R1FieldElement X2 = (SecP521R1FieldElement)b.getXCoord(), Y2 = (SecP521R1FieldElement)b.getYCoord();
+
+ SecP521R1FieldElement Z1 = (SecP521R1FieldElement)this.zs[0];
+ SecP521R1FieldElement Z2 = (SecP521R1FieldElement)b.getZCoord(0);
+
+ int[] t1 = Nat.create(17);
+ int[] t2 = Nat.create(17);
+ int[] t3 = Nat.create(17);
+ int[] t4 = Nat.create(17);
+
+ boolean Z1IsOne = Z1.isOne();
+ int[] U2, S2;
+ if (Z1IsOne)
+ {
+ U2 = X2.x;
+ S2 = Y2.x;
+ }
+ else
+ {
+ S2 = t3;
+ SecP521R1Field.square(Z1.x, S2);
+
+ U2 = t2;
+ SecP521R1Field.multiply(S2, X2.x, U2);
+
+ SecP521R1Field.multiply(S2, Z1.x, S2);
+ SecP521R1Field.multiply(S2, Y2.x, S2);
+ }
+
+ boolean Z2IsOne = Z2.isOne();
+ int[] U1, S1;
+ if (Z2IsOne)
+ {
+ U1 = X1.x;
+ S1 = Y1.x;
+ }
+ else
+ {
+ S1 = t4;
+ SecP521R1Field.square(Z2.x, S1);
+
+ U1 = t1;
+ SecP521R1Field.multiply(S1, X1.x, U1);
+
+ SecP521R1Field.multiply(S1, Z2.x, S1);
+ SecP521R1Field.multiply(S1, Y1.x, S1);
+ }
+
+ int[] H = Nat.create(17);
+ SecP521R1Field.subtract(U1, U2, H);
+
+ int[] R = t2;
+ SecP521R1Field.subtract(S1, S2, R);
+
+ // Check if b == this or b == -this
+ if (Nat.isZero(17, H))
+ {
+ if (Nat.isZero(17, R))
+ {
+ // this == b, i.e. this must be doubled
+ return this.twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.getInfinity();
+ }
+
+ int[] HSquared = t3;
+ SecP521R1Field.square(H, HSquared);
+
+ int[] G = Nat.create(17);
+ SecP521R1Field.multiply(HSquared, H, G);
+
+ int[] V = t3;
+ SecP521R1Field.multiply(HSquared, U1, V);
+
+ SecP521R1Field.multiply(S1, G, t1);
+
+ SecP521R1FieldElement X3 = new SecP521R1FieldElement(t4);
+ SecP521R1Field.square(R, X3.x);
+ SecP521R1Field.add(X3.x, G, X3.x);
+ SecP521R1Field.subtract(X3.x, V, X3.x);
+ SecP521R1Field.subtract(X3.x, V, X3.x);
+
+ SecP521R1FieldElement Y3 = new SecP521R1FieldElement(G);
+ SecP521R1Field.subtract(V, X3.x, Y3.x);
+ SecP521R1Field.multiply(Y3.x, R, t2);
+ SecP521R1Field.subtract(t2, t1, Y3.x);
+
+ SecP521R1FieldElement Z3 = new SecP521R1FieldElement(H);
+ if (!Z1IsOne)
+ {
+ SecP521R1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+ if (!Z2IsOne)
+ {
+ SecP521R1Field.multiply(Z3.x, Z2.x, Z3.x);
+ }
+
+ ECFieldElement[] zs = new ECFieldElement[]{ Z3 };
+
+ return new SecP521R1Point(curve, X3, Y3, zs, this.withCompression);
+ }
+
+ public ECPoint twice()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP521R1FieldElement Y1 = (SecP521R1FieldElement)this.y;
+ if (Y1.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ SecP521R1FieldElement X1 = (SecP521R1FieldElement)this.x, Z1 = (SecP521R1FieldElement)this.zs[0];
+
+ int[] t1 = Nat.create(17);
+ int[] t2 = Nat.create(17);
+
+ int[] Y1Squared = Nat.create(17);
+ SecP521R1Field.square(Y1.x, Y1Squared);
+
+ int[] T = Nat.create(17);
+ SecP521R1Field.square(Y1Squared, T);
+
+ boolean Z1IsOne = Z1.isOne();
+
+ int[] Z1Squared = Z1.x;
+ if (!Z1IsOne)
+ {
+ Z1Squared = t2;
+ SecP521R1Field.square(Z1.x, Z1Squared);
+ }
+
+ SecP521R1Field.subtract(X1.x, Z1Squared, t1);
+
+ int[] M = t2;
+ SecP521R1Field.add(X1.x, Z1Squared, M);
+ SecP521R1Field.multiply(M, t1, M);
+ Nat.addBothTo(17, M, M, M);
+ SecP521R1Field.reduce23(M);
+
+ int[] S = Y1Squared;
+ SecP521R1Field.multiply(Y1Squared, X1.x, S);
+ Nat.shiftUpBits(17, S, 2, 0);
+ SecP521R1Field.reduce23(S);
+
+ Nat.shiftUpBits(17, T, 3, 0, t1);
+ SecP521R1Field.reduce23(t1);
+
+ SecP521R1FieldElement X3 = new SecP521R1FieldElement(T);
+ SecP521R1Field.square(M, X3.x);
+ SecP521R1Field.subtract(X3.x, S, X3.x);
+ SecP521R1Field.subtract(X3.x, S, X3.x);
+
+ SecP521R1FieldElement Y3 = new SecP521R1FieldElement(S);
+ SecP521R1Field.subtract(S, X3.x, Y3.x);
+ SecP521R1Field.multiply(Y3.x, M, Y3.x);
+ SecP521R1Field.subtract(Y3.x, t1, Y3.x);
+
+ SecP521R1FieldElement Z3 = new SecP521R1FieldElement(M);
+ SecP521R1Field.twice(Y1.x, Z3.x);
+ if (!Z1IsOne)
+ {
+ SecP521R1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+
+ return new SecP521R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+
+ public ECPoint twicePlus(ECPoint b)
+ {
+ if (this == b)
+ {
+ return threeTimes();
+ }
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return twice();
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return b;
+ }
+
+ return twice().add(b);
+ }
+
+ public ECPoint threeTimes()
+ {
+ if (this.isInfinity() || this.y.isZero())
+ {
+ return this;
+ }
+
+ // NOTE: Be careful about recursions between twicePlus and threeTimes
+ return twice().add(this);
+ }
+
+ protected ECFieldElement two(ECFieldElement x)
+ {
+ return x.add(x);
+ }
+
+ protected ECFieldElement three(ECFieldElement x)
+ {
+ return two(x).add(x);
+ }
+
+ protected ECFieldElement four(ECFieldElement x)
+ {
+ return two(two(x));
+ }
+
+ protected ECFieldElement eight(ECFieldElement x)
+ {
+ return four(two(x));
+ }
+
+ protected ECFieldElement doubleProductFromSquares(ECFieldElement a, ECFieldElement b,
+ ECFieldElement aSquared, ECFieldElement bSquared)
+ {
+ /*
+ * NOTE: If squaring in the field is faster than multiplication, then this is a quicker
+ * way to calculate 2.A.B, if A^2 and B^2 are already known.
+ */
+ return a.add(b).square().subtract(aSquared).subtract(bSquared);
+ }
+
+ public ECPoint negate()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ return new SecP521R1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/endo/ECEndomorphism.java b/core/src/main/java/org/spongycastle/math/ec/endo/ECEndomorphism.java
new file mode 100644
index 00000000..7396bf33
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/endo/ECEndomorphism.java
@@ -0,0 +1,10 @@
+package org.spongycastle.math.ec.endo;
+
+import org.spongycastle.math.ec.ECPointMap;
+
+public interface ECEndomorphism
+{
+ ECPointMap getPointMap();
+
+ boolean hasEfficientPointMap();
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/endo/GLVEndomorphism.java b/core/src/main/java/org/spongycastle/math/ec/endo/GLVEndomorphism.java
new file mode 100644
index 00000000..9c251a1e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/endo/GLVEndomorphism.java
@@ -0,0 +1,8 @@
+package org.spongycastle.math.ec.endo;
+
+import java.math.BigInteger;
+
+public interface GLVEndomorphism extends ECEndomorphism
+{
+ BigInteger[] decomposeScalar(BigInteger k);
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/endo/GLVTypeBEndomorphism.java b/core/src/main/java/org/spongycastle/math/ec/endo/GLVTypeBEndomorphism.java
new file mode 100644
index 00000000..884cbf53
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/endo/GLVTypeBEndomorphism.java
@@ -0,0 +1,58 @@
+package org.spongycastle.math.ec.endo;
+
+import java.math.BigInteger;
+
+import org.spongycastle.math.ec.ECConstants;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECPointMap;
+import org.spongycastle.math.ec.ScaleXPointMap;
+
+public class GLVTypeBEndomorphism implements GLVEndomorphism
+{
+ protected final ECCurve curve;
+ protected final GLVTypeBParameters parameters;
+ protected final ECPointMap pointMap;
+
+ public GLVTypeBEndomorphism(ECCurve curve, GLVTypeBParameters parameters)
+ {
+ this.curve = curve;
+ this.parameters = parameters;
+ this.pointMap = new ScaleXPointMap(curve.fromBigInteger(parameters.getBeta()));
+ }
+
+ public BigInteger[] decomposeScalar(BigInteger k)
+ {
+ int bits = parameters.getBits();
+ BigInteger b1 = calculateB(k, parameters.getG1(), bits);
+ BigInteger b2 = calculateB(k, parameters.getG2(), bits);
+
+ BigInteger[] v1 = parameters.getV1(), v2 = parameters.getV2();
+ BigInteger a = k.subtract((b1.multiply(v1[0])).add(b2.multiply(v2[0])));
+ BigInteger b = (b1.multiply(v1[1])).add(b2.multiply(v2[1])).negate();
+
+ return new BigInteger[]{ a, b };
+ }
+
+ public ECPointMap getPointMap()
+ {
+ return pointMap;
+ }
+
+ public boolean hasEfficientPointMap()
+ {
+ return true;
+ }
+
+ protected BigInteger calculateB(BigInteger k, BigInteger g, int t)
+ {
+ boolean negative = (g.signum() < 0);
+ BigInteger b = k.multiply(g.abs());
+ boolean extra = b.testBit(t - 1);
+ b = b.shiftRight(t);
+ if (extra)
+ {
+ b = b.add(ECConstants.ONE);
+ }
+ return negative ? b.negate() : b;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/endo/GLVTypeBParameters.java b/core/src/main/java/org/spongycastle/math/ec/endo/GLVTypeBParameters.java
new file mode 100644
index 00000000..92dbfd0e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/endo/GLVTypeBParameters.java
@@ -0,0 +1,59 @@
+package org.spongycastle.math.ec.endo;
+
+import java.math.BigInteger;
+
+public class GLVTypeBParameters
+{
+ protected final BigInteger beta;
+ protected final BigInteger lambda;
+ protected final BigInteger[] v1, v2;
+ protected final BigInteger g1, g2;
+ protected final int bits;
+
+ public GLVTypeBParameters(BigInteger beta, BigInteger lambda, BigInteger[] v1, BigInteger[] v2, BigInteger g1,
+ BigInteger g2, int bits)
+ {
+ this.beta = beta;
+ this.lambda = lambda;
+ this.v1 = v1;
+ this.v2 = v2;
+ this.g1 = g1;
+ this.g2 = g2;
+ this.bits = bits;
+ }
+
+ public BigInteger getBeta()
+ {
+ return beta;
+ }
+
+ public BigInteger getLambda()
+ {
+ return lambda;
+ }
+
+ public BigInteger[] getV1()
+ {
+ return v1;
+ }
+
+ public BigInteger[] getV2()
+ {
+ return v2;
+ }
+
+ public BigInteger getG1()
+ {
+ return g1;
+ }
+
+ public BigInteger getG2()
+ {
+ return g2;
+ }
+
+ public int getBits()
+ {
+ return bits;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/ec/tools/DiscoverEndomorphisms.java b/core/src/main/java/org/spongycastle/math/ec/tools/DiscoverEndomorphisms.java
new file mode 100644
index 00000000..32341d60
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/ec/tools/DiscoverEndomorphisms.java
@@ -0,0 +1,373 @@
+package org.spongycastle.math.ec.tools;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.asn1.x9.ECNamedCurveTable;
+import org.spongycastle.asn1.x9.X9ECParameters;
+import org.spongycastle.math.ec.ECAlgorithms;
+import org.spongycastle.math.ec.ECConstants;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.util.BigIntegers;
+
+public class DiscoverEndomorphisms
+{
+ private static final int radix = 16;
+
+ public static void main(String[] args)
+ {
+ if (args.length < 1)
+ {
+ System.err.println("Expected a list of curve names as arguments");
+ return;
+ }
+
+ for (int i = 0; i < args.length; ++i)
+ {
+ discoverEndomorphism(args[i]);
+ }
+ }
+
+ private static void discoverEndomorphism(String curveName)
+ {
+ X9ECParameters x9 = ECNamedCurveTable.getByName(curveName);
+ if (x9 == null)
+ {
+ System.err.println("Unknown curve: " + curveName);
+ return;
+ }
+
+ ECCurve c = x9.getCurve();
+ if (ECAlgorithms.isFpCurve(c))
+ {
+ BigInteger characteristic = c.getField().getCharacteristic();
+
+ if (c.getA().isZero() && characteristic.mod(ECConstants.THREE).equals(ECConstants.ONE))
+ {
+ System.out.println("Curve '" + curveName + "' has a 'GLV Type B' endomorphism with these parameters: ");
+ printGLVTypeBParameters(x9);
+ }
+ }
+ }
+
+ private static void printGLVTypeBParameters(X9ECParameters x9)
+ {
+ BigInteger n = x9.getN();
+ BigInteger[] v1 = null;
+ BigInteger[] v2 = null;
+
+ // x^2 + x + 1 = 0 mod n
+ BigInteger lambda = solveQuadraticEquation(n, ECConstants.ONE, ECConstants.ONE);
+
+ BigInteger[] rt = extEuclidGLV(n, lambda);
+ v1 = new BigInteger[]{ rt[2], rt[3].negate() };
+ v2 = chooseShortest(new BigInteger[]{ rt[0], rt[1].negate() }, new BigInteger[]{ rt[4], rt[5].negate() });
+
+ /*
+ * If elements of v2 are not bounded by sqrt(n), then if r1/t1 are relatively prime there
+ * _may_ yet be a GLV generator, so search for it. See
+ * "Integer Decomposition for Fast Scalar Multiplication on Elliptic Curves", D. Kim, S. Lim
+ * (SAC 2002)
+ */
+ if (!isVectorBoundedBySqrt(v2, n) && areRelativelyPrime(v1[0], v1[1]))
+ {
+ BigInteger r = v1[0], t = v1[1], s = r.add(t.multiply(lambda)).divide(n);
+
+ BigInteger[] vw = extEuclidBezout(new BigInteger[]{ s.abs(), t.abs() });
+ BigInteger v = vw[0], w = vw[1];
+
+ if (s.signum() < 0)
+ {
+ v = v.negate();
+ }
+ if (t.signum() > 0)
+ {
+ w = w.negate();
+ }
+
+ BigInteger check = s.multiply(v).subtract(t.multiply(w));
+ if (!check.equals(ECConstants.ONE))
+ {
+ throw new IllegalStateException();
+ }
+
+ BigInteger x = w.multiply(n).subtract(v.multiply(lambda));
+
+ BigInteger base1 = v.negate();
+ BigInteger base2 = x.negate();
+
+ /*
+ * We calculate the range(s) conservatively large to avoid messy rounding issues, so
+ * there may be spurious candidate generators, but we won't miss any.
+ */
+ BigInteger sqrtN = isqrt(n.subtract(ECConstants.ONE)).add(ECConstants.ONE);
+
+ BigInteger[] I1 = calculateRange(base1, sqrtN, t);
+ BigInteger[] I2 = calculateRange(base2, sqrtN, r);
+
+ BigInteger[] range = intersect(I1, I2);
+ if (range != null)
+ {
+ for (BigInteger alpha = range[0]; alpha.compareTo(range[1]) <= 0; alpha = alpha.add(ECConstants.ONE))
+ {
+ BigInteger[] candidate = new BigInteger[]{ x.add(alpha.multiply(r)), v.add(alpha.multiply(t)) };
+ if (isShorter(candidate, v2))
+ {
+ v2 = candidate;
+ }
+ }
+ }
+ }
+
+ /*
+ * 'Beta' is a field element of order 3. There are only two such values besides 1; determine which of them
+ * corresponds to our choice for 'Lambda'.
+ */
+ ECFieldElement beta;
+ {
+ ECPoint G = x9.getG().normalize();
+ ECPoint mapG = G.multiply(lambda).normalize();
+ if (!G.getYCoord().equals(mapG.getYCoord()))
+ {
+ throw new IllegalStateException("Derivation of GLV Type B parameters failed unexpectedly");
+ }
+
+ BigInteger q = x9.getCurve().getField().getCharacteristic();
+ BigInteger e = q.divide(ECConstants.THREE);
+
+ SecureRandom random = new SecureRandom();
+ BigInteger b;
+ do
+ {
+ BigInteger r = BigIntegers.createRandomInRange(ECConstants.TWO, q.subtract(ECConstants.TWO), random);
+ b = r.modPow(e, q);
+ }
+ while (b.equals(ECConstants.ONE));
+
+ beta = x9.getCurve().fromBigInteger(ECConstants.TWO.modPow(e, q));
+
+ if (!G.getXCoord().multiply(beta).equals(mapG.getXCoord()))
+ {
+ beta = beta.square();
+ if (!G.getXCoord().multiply(beta).equals(mapG.getXCoord()))
+ {
+ throw new IllegalStateException("Derivation of GLV Type B parameters failed unexpectedly");
+ }
+ }
+ }
+
+ /*
+ * These parameters are used to avoid division when decomposing the scalar in a GLV point multiplication
+ */
+ BigInteger d = (v1[0].multiply(v2[1])).subtract(v1[1].multiply(v2[0]));
+
+ int bits = n.bitLength() + 16 - (n.bitLength() & 7);
+ BigInteger g1 = roundQuotient(v2[1].shiftLeft(bits), d);
+ BigInteger g2 = roundQuotient(v1[1].shiftLeft(bits), d).negate();
+
+ printProperty("Beta", beta.toBigInteger().toString(radix));
+ printProperty("Lambda", lambda.toString(radix));
+ printProperty("v1", "{ " + v1[0].toString(radix) + ", " + v1[1].toString(radix) + " }");
+ printProperty("v2", "{ " + v2[0].toString(radix) + ", " + v2[1].toString(radix) + " }");
+ printProperty("(OPT) g1", g1.toString(radix));
+ printProperty("(OPT) g2", g2.toString(radix));
+ printProperty("(OPT) bits", Integer.toString(bits));
+ }
+
+ private static void printProperty(String name, Object value)
+ {
+ StringBuffer sb = new StringBuffer(" ");
+ sb.append(name);
+ while (sb.length() < 20)
+ {
+ sb.append(' ');
+ }
+ sb.append("= ");
+ sb.append(value.toString());
+ System.out.println(sb.toString());
+ }
+
+ private static boolean areRelativelyPrime(BigInteger a, BigInteger b)
+ {
+ return a.gcd(b).equals(ECConstants.ONE);
+ }
+
+ private static BigInteger[] calculateRange(BigInteger mid, BigInteger off, BigInteger div)
+ {
+ BigInteger i1 = mid.subtract(off).divide(div);
+ BigInteger i2 = mid.add(off).divide(div);
+ return order(i1, i2);
+ }
+
+ private static BigInteger[] extEuclidBezout(BigInteger[] ab)
+ {
+ boolean swap = ab[0].compareTo(ab[1]) < 0;
+ if (swap)
+ {
+ swap(ab);
+ }
+
+ BigInteger r0 = ab[0], r1 = ab[1];
+ BigInteger s0 = ECConstants.ONE, s1 = ECConstants.ZERO;
+ BigInteger t0 = ECConstants.ZERO, t1 = ECConstants.ONE;
+
+ while (r1.compareTo(ECConstants.ONE) > 0)
+ {
+ BigInteger[] qr = r0.divideAndRemainder(r1);
+ BigInteger q = qr[0], r2 = qr[1];
+
+ BigInteger s2 = s0.subtract(q.multiply(s1));
+ BigInteger t2 = t0.subtract(q.multiply(t1));
+
+ r0 = r1;
+ r1 = r2;
+ s0 = s1;
+ s1 = s2;
+ t0 = t1;
+ t1 = t2;
+ }
+
+ if (r1.signum() <= 0)
+ {
+ throw new IllegalStateException();
+ }
+
+ BigInteger[] st = new BigInteger[]{ s1, t1 };
+ if (swap)
+ {
+ swap(st);
+ }
+ return st;
+ }
+
+ private static BigInteger[] extEuclidGLV(BigInteger n, BigInteger lambda)
+ {
+ BigInteger r0 = n, r1 = lambda;
+ // BigInteger s0 = ECConstants.ONE, s1 = ECConstants.ZERO;
+ BigInteger t0 = ECConstants.ZERO, t1 = ECConstants.ONE;
+
+ for (;;)
+ {
+ BigInteger[] qr = r0.divideAndRemainder(r1);
+ BigInteger q = qr[0], r2 = qr[1];
+
+ // BigInteger s2 = s0.subtract(q.multiply(s1));
+ BigInteger t2 = t0.subtract(q.multiply(t1));
+
+ if (isLessThanSqrt(r1, n))
+ {
+ return new BigInteger[]{ r0, t0, r1, t1, r2, t2 };
+ }
+
+ r0 = r1;
+ r1 = r2;
+ // s0 = s1;
+ // s1 = s2;
+ t0 = t1;
+ t1 = t2;
+ }
+ }
+
+ private static BigInteger[] chooseShortest(BigInteger[] u, BigInteger[] v)
+ {
+ return isShorter(u, v) ? u : v;
+ }
+
+ private static BigInteger[] intersect(BigInteger[] ab, BigInteger[] cd)
+ {
+ BigInteger min = ab[0].max(cd[0]);
+ BigInteger max = ab[1].min(cd[1]);
+ if (min.compareTo(max) > 0)
+ {
+ return null;
+ }
+ return new BigInteger[]{ min, max };
+ }
+
+ private static boolean isLessThanSqrt(BigInteger a, BigInteger b)
+ {
+ a = a.abs();
+ b = b.abs();
+ int target = b.bitLength(), maxBits = a.bitLength() * 2, minBits = maxBits - 1;
+ return minBits <= target && (maxBits < target || a.multiply(a).compareTo(b) < 0);
+ }
+
+ private static boolean isShorter(BigInteger[] u, BigInteger[] v)
+ {
+ BigInteger u1 = u[0].abs(), u2 = u[1].abs(), v1 = v[0].abs(), v2 = v[1].abs();
+
+ // TODO Check whether "shorter" just means by rectangle norm:
+ // return u1.max(u2).compareTo(v1.max(v2)) < 0;
+
+ boolean c1 = u1.compareTo(v1) < 0, c2 = u2.compareTo(v2) < 0;
+ if (c1 == c2)
+ {
+ return c1;
+ }
+
+ BigInteger du = u1.multiply(u1).add(u2.multiply(u2));
+ BigInteger dv = v1.multiply(v1).add(v2.multiply(v2));
+
+ return du.compareTo(dv) < 0;
+ }
+
+ private static boolean isVectorBoundedBySqrt(BigInteger[] v, BigInteger n)
+ {
+ BigInteger max = v[0].abs().max(v[1].abs());
+ return isLessThanSqrt(max, n);
+ }
+
+ private static BigInteger[] order(BigInteger a, BigInteger b)
+ {
+ if (a.compareTo(b) <= 0)
+ {
+ return new BigInteger[]{ a, b };
+ }
+ return new BigInteger[]{ b, a };
+ }
+
+ private static BigInteger roundQuotient(BigInteger x, BigInteger y)
+ {
+ boolean negative = (x.signum() != y.signum());
+ x = x.abs();
+ y = y.abs();
+ BigInteger result = x.add(y.shiftRight(1)).divide(y);
+ return negative ? result.negate() : result;
+ }
+
+ private static BigInteger solveQuadraticEquation(BigInteger n, BigInteger r, BigInteger s)
+ {
+ BigInteger det = r.multiply(r).subtract(s.shiftLeft(2)).mod(n);
+
+ BigInteger root = new ECFieldElement.Fp(n, det).sqrt().toBigInteger();
+ if (!root.testBit(0))
+ {
+ root = n.subtract(root);
+ }
+
+ return root.shiftRight(1); // NOTE: implicit -1 of the low-bit
+ }
+
+ private static BigInteger isqrt(BigInteger x)
+ {
+ BigInteger g0 = x.shiftRight(x.bitLength() / 2);
+ for (;;)
+ {
+ BigInteger g1 = g0.add(x.divide(g0)).shiftRight(1);
+ if (g1.equals(g0))
+ {
+ return g1;
+ }
+ g0 = g1;
+ }
+ }
+
+ private static void swap(BigInteger[] ab)
+ {
+ BigInteger tmp = ab[0];
+ ab[0] = ab[1];
+ ab[1] = tmp;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/field/ExtensionField.java b/core/src/main/java/org/spongycastle/math/field/ExtensionField.java
new file mode 100644
index 00000000..d32fda58
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/field/ExtensionField.java
@@ -0,0 +1,8 @@
+package org.spongycastle.math.field;
+
+public interface ExtensionField extends FiniteField
+{
+ FiniteField getSubfield();
+
+ int getDegree();
+}
diff --git a/core/src/main/java/org/spongycastle/math/field/FiniteField.java b/core/src/main/java/org/spongycastle/math/field/FiniteField.java
new file mode 100644
index 00000000..25801c31
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/field/FiniteField.java
@@ -0,0 +1,10 @@
+package org.spongycastle.math.field;
+
+import java.math.BigInteger;
+
+public interface FiniteField
+{
+ BigInteger getCharacteristic();
+
+ int getDimension();
+}
diff --git a/core/src/main/java/org/spongycastle/math/field/FiniteFields.java b/core/src/main/java/org/spongycastle/math/field/FiniteFields.java
new file mode 100644
index 00000000..602d32e6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/field/FiniteFields.java
@@ -0,0 +1,53 @@
+package org.spongycastle.math.field;
+
+import java.math.BigInteger;
+
+public abstract class FiniteFields
+{
+ static final FiniteField GF_2 = new PrimeField(BigInteger.valueOf(2));
+ static final FiniteField GF_3 = new PrimeField(BigInteger.valueOf(3));
+
+ public static PolynomialExtensionField getBinaryExtensionField(int[] exponents)
+ {
+ if (exponents[0] != 0)
+ {
+ throw new IllegalArgumentException("Irreducible polynomials in GF(2) must have constant term");
+ }
+ for (int i = 1; i < exponents.length; ++i)
+ {
+ if (exponents[i] <= exponents[i - 1])
+ {
+ throw new IllegalArgumentException("Polynomial exponents must be montonically increasing");
+ }
+ }
+
+ return new GenericPolynomialExtensionField(GF_2, new GF2Polynomial(exponents));
+ }
+
+// public static PolynomialExtensionField getTernaryExtensionField(Term[] terms)
+// {
+// return new GenericPolynomialExtensionField(GF_3, new GF3Polynomial(terms));
+// }
+
+ public static FiniteField getPrimeField(BigInteger characteristic)
+ {
+ int bitLength = characteristic.bitLength();
+ if (characteristic.signum() <= 0 || bitLength < 2)
+ {
+ throw new IllegalArgumentException("'characteristic' must be >= 2");
+ }
+
+ if (bitLength < 3)
+ {
+ switch (characteristic.intValue())
+ {
+ case 2:
+ return GF_2;
+ case 3:
+ return GF_3;
+ }
+ }
+
+ return new PrimeField(characteristic);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/field/GF2Polynomial.java b/core/src/main/java/org/spongycastle/math/field/GF2Polynomial.java
new file mode 100644
index 00000000..a8e900c7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/field/GF2Polynomial.java
@@ -0,0 +1,42 @@
+package org.spongycastle.math.field;
+
+import org.spongycastle.util.Arrays;
+
+class GF2Polynomial implements Polynomial
+{
+ protected final int[] exponents;
+
+ GF2Polynomial(int[] exponents)
+ {
+ this.exponents = Arrays.clone(exponents);
+ }
+
+ public int getDegree()
+ {
+ return exponents[exponents.length - 1];
+ }
+
+ public int[] getExponentsPresent()
+ {
+ return Arrays.clone(exponents);
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (!(obj instanceof GF2Polynomial))
+ {
+ return false;
+ }
+ GF2Polynomial other = (GF2Polynomial)obj;
+ return Arrays.areEqual(exponents, other.exponents);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(exponents);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/field/GenericPolynomialExtensionField.java b/core/src/main/java/org/spongycastle/math/field/GenericPolynomialExtensionField.java
new file mode 100644
index 00000000..677cff96
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/field/GenericPolynomialExtensionField.java
@@ -0,0 +1,62 @@
+package org.spongycastle.math.field;
+
+import java.math.BigInteger;
+
+import org.spongycastle.util.Integers;
+
+class GenericPolynomialExtensionField implements PolynomialExtensionField
+{
+ protected final FiniteField subfield;
+ protected final Polynomial minimalPolynomial;
+
+ GenericPolynomialExtensionField(FiniteField subfield, Polynomial polynomial)
+ {
+ this.subfield = subfield;
+ this.minimalPolynomial = polynomial;
+ }
+
+ public BigInteger getCharacteristic()
+ {
+ return subfield.getCharacteristic();
+ }
+
+ public int getDimension()
+ {
+ return subfield.getDimension() * minimalPolynomial.getDegree();
+ }
+
+ public FiniteField getSubfield()
+ {
+ return subfield;
+ }
+
+ public int getDegree()
+ {
+ return minimalPolynomial.getDegree();
+ }
+
+ public Polynomial getMinimalPolynomial()
+ {
+ return minimalPolynomial;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (!(obj instanceof GenericPolynomialExtensionField))
+ {
+ return false;
+ }
+ GenericPolynomialExtensionField other = (GenericPolynomialExtensionField)obj;
+ return subfield.equals(other.subfield) && minimalPolynomial.equals(other.minimalPolynomial);
+ }
+
+ public int hashCode()
+ {
+ return subfield.hashCode()
+ ^ Integers.rotateLeft(minimalPolynomial.hashCode(), 16);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/field/Polynomial.java b/core/src/main/java/org/spongycastle/math/field/Polynomial.java
new file mode 100644
index 00000000..b0724cb5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/field/Polynomial.java
@@ -0,0 +1,12 @@
+package org.spongycastle.math.field;
+
+public interface Polynomial
+{
+ int getDegree();
+
+// BigInteger[] getCoefficients();
+
+ int[] getExponentsPresent();
+
+// Term[] getNonZeroTerms();
+}
diff --git a/core/src/main/java/org/spongycastle/math/field/PolynomialExtensionField.java b/core/src/main/java/org/spongycastle/math/field/PolynomialExtensionField.java
new file mode 100644
index 00000000..35eb98ea
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/field/PolynomialExtensionField.java
@@ -0,0 +1,6 @@
+package org.spongycastle.math.field;
+
+public interface PolynomialExtensionField extends ExtensionField
+{
+ Polynomial getMinimalPolynomial();
+}
diff --git a/core/src/main/java/org/spongycastle/math/field/PrimeField.java b/core/src/main/java/org/spongycastle/math/field/PrimeField.java
new file mode 100644
index 00000000..38c313a7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/field/PrimeField.java
@@ -0,0 +1,42 @@
+package org.spongycastle.math.field;
+
+import java.math.BigInteger;
+
+class PrimeField implements FiniteField
+{
+ protected final BigInteger characteristic;
+
+ PrimeField(BigInteger characteristic)
+ {
+ this.characteristic = characteristic;
+ }
+
+ public BigInteger getCharacteristic()
+ {
+ return characteristic;
+ }
+
+ public int getDimension()
+ {
+ return 1;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (!(obj instanceof PrimeField))
+ {
+ return false;
+ }
+ PrimeField other = (PrimeField)obj;
+ return characteristic.equals(other.characteristic);
+ }
+
+ public int hashCode()
+ {
+ return characteristic.hashCode();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/raw/Mod.java b/core/src/main/java/org/spongycastle/math/raw/Mod.java
new file mode 100644
index 00000000..6bb8d748
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/raw/Mod.java
@@ -0,0 +1,199 @@
+package org.spongycastle.math.raw;
+
+import java.util.Random;
+
+import org.spongycastle.util.Pack;
+
+public abstract class Mod
+{
+ public static int inverse32(int d)
+ {
+// int x = d + (((d + 1) & 4) << 1); // d.x == 1 mod 2**4
+ int x = d; // d.x == 1 mod 2**3
+ x *= 2 - d * x; // d.x == 1 mod 2**6
+ x *= 2 - d * x; // d.x == 1 mod 2**12
+ x *= 2 - d * x; // d.x == 1 mod 2**24
+ x *= 2 - d * x; // d.x == 1 mod 2**48
+// assert d * x == 1;
+ return x;
+ }
+
+ public static void invert(int[] p, int[] x, int[] z)
+ {
+ int len = p.length;
+ if (Nat.isZero(len, x))
+ {
+ throw new IllegalArgumentException("'x' cannot be 0");
+ }
+ if (Nat.isOne(len, x))
+ {
+ System.arraycopy(x, 0, z, 0, len);
+ return;
+ }
+
+ int[] u = Nat.copy(len, x);
+ int[] a = Nat.create(len);
+ a[0] = 1;
+ int ac = 0;
+
+ if ((u[0] & 1) == 0)
+ {
+ ac = inversionStep(p, u, len, a, ac);
+ }
+ if (Nat.isOne(len, u))
+ {
+ inversionResult(p, ac, a, z);
+ return;
+ }
+
+ int[] v = Nat.copy(len, p);
+ int[] b = Nat.create(len);
+ int bc = 0;
+
+ int uvLen = len;
+
+ for (;;)
+ {
+ while (u[uvLen - 1] == 0 && v[uvLen - 1] == 0)
+ {
+ --uvLen;
+ }
+
+ if (Nat.gte(uvLen, u, v))
+ {
+ Nat.subFrom(uvLen, v, u);
+// assert (u[0] & 1) == 0;
+ ac += Nat.subFrom(len, b, a) - bc;
+ ac = inversionStep(p, u, uvLen, a, ac);
+ if (Nat.isOne(uvLen, u))
+ {
+ inversionResult(p, ac, a, z);
+ return;
+ }
+ }
+ else
+ {
+ Nat.subFrom(uvLen, u, v);
+// assert (v[0] & 1) == 0;
+ bc += Nat.subFrom(len, a, b) - ac;
+ bc = inversionStep(p, v, uvLen, b, bc);
+ if (Nat.isOne(uvLen, v))
+ {
+ inversionResult(p, bc, b, z);
+ return;
+ }
+ }
+ }
+ }
+
+ public static int[] random(int[] p)
+ {
+ int len = p.length;
+ Random rand = new Random();
+ int[] s = Nat.create(len);
+
+ int m = p[len - 1];
+ m |= m >>> 1;
+ m |= m >>> 2;
+ m |= m >>> 4;
+ m |= m >>> 8;
+ m |= m >>> 16;
+
+ do
+ {
+ for (int i = 0; i != len; i++)
+ {
+ s[i] = rand.nextInt();
+ }
+ s[len - 1] &= m;
+ }
+ while (Nat.gte(len, s, p));
+
+ return s;
+ }
+
+ public static void add(int[] p, int[] x, int[] y, int[] z)
+ {
+ int len = p.length;
+ int c = Nat.add(len, x, y, z);
+ if (c != 0)
+ {
+ Nat.subFrom(len, p, z);
+ }
+ }
+
+ public static void subtract(int[] p, int[] x, int[] y, int[] z)
+ {
+ int len = p.length;
+ int c = Nat.sub(len, x, y, z);
+ if (c != 0)
+ {
+ Nat.addTo(len, p, z);
+ }
+ }
+
+ private static void inversionResult(int[] p, int ac, int[] a, int[] z)
+ {
+ if (ac < 0)
+ {
+ Nat.add(p.length, a, p, z);
+ }
+ else
+ {
+ System.arraycopy(a, 0, z, 0, p.length);
+ }
+ }
+
+ private static int inversionStep(int[] p, int[] u, int uLen, int[] x, int xc)
+ {
+ int len = p.length;
+ int count = 0;
+ while (u[0] == 0)
+ {
+ Nat.shiftDownWord(uLen, u, 0);
+ count += 32;
+ }
+
+ {
+ int zeroes = getTrailingZeroes(u[0]);
+ if (zeroes > 0)
+ {
+ Nat.shiftDownBits(uLen, u, zeroes, 0);
+ count += zeroes;
+ }
+ }
+
+ for (int i = 0; i < count; ++i)
+ {
+ if ((x[0] & 1) != 0)
+ {
+ if (xc < 0)
+ {
+ xc += Nat.addTo(len, p, x);
+ }
+ else
+ {
+ xc += Nat.subFrom(len, p, x);
+ }
+ }
+
+// assert xc == 0 || xc == 1;
+ Nat.shiftDownBit(len, x, xc);
+ }
+
+ return xc;
+ }
+
+ private static int getTrailingZeroes(int x)
+ {
+// assert x != 0;
+
+ int count = 0;
+ while ((x & 1) == 0)
+ {
+ x >>>= 1;
+ ++count;
+ }
+ return count;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/raw/Mont256.java b/core/src/main/java/org/spongycastle/math/raw/Mont256.java
new file mode 100644
index 00000000..b90dcc5a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/raw/Mont256.java
@@ -0,0 +1,152 @@
+package org.spongycastle.math.raw;
+
+public abstract class Mont256
+{
+ private static final long M = 0xFFFFFFFFL;
+
+ public static int inverse32(int x)
+ {
+ // assert (x & 1) == 1;
+ int z = x; // x.z == 1 mod 2**3
+ z *= 2 - x * z; // x.z == 1 mod 2**6
+ z *= 2 - x * z; // x.z == 1 mod 2**12
+ z *= 2 - x * z; // x.z == 1 mod 2**24
+ z *= 2 - x * z; // x.z == 1 mod 2**48
+ // assert x * z == 1;
+ return z;
+ }
+
+ public static void multAdd(int[] x, int[] y, int[] z, int[] m, int mInv32)
+ {
+ int z_8 = 0;
+ long y_0 = y[0] & M;
+
+ for (int i = 0; i < 8; ++i)
+ {
+ long z_0 = z[0] & M;
+ long x_i = x[i] & M;
+
+ long prod1 = x_i * y_0;
+ long carry = (prod1 & M) + z_0;
+
+ long t = ((int)carry * mInv32) & M;
+
+ long prod2 = t * (m[0] & M);
+ carry += (prod2 & M);
+ // assert (int)carry == 0;
+ carry = (carry >>> 32) + (prod1 >>> 32) + (prod2 >>> 32);
+
+ for (int j = 1; j < 8; ++j)
+ {
+ prod1 = x_i * (y[j] & M);
+ prod2 = t * (m[j] & M);
+
+ carry += (prod1 & M) + (prod2 & M) + (z[j] & M);
+ z[j - 1] = (int)carry;
+ carry = (carry >>> 32) + (prod1 >>> 32) + (prod2 >>> 32);
+ }
+
+ carry += (z_8 & M);
+ z[7] = (int)carry;
+ z_8 = (int)(carry >>> 32);
+ }
+
+ if (z_8 != 0 || Nat256.gte(z, m))
+ {
+ Nat256.sub(z, m, z);
+ }
+ }
+
+ public static void multAddXF(int[] x, int[] y, int[] z, int[] m)
+ {
+ // assert m[0] == M;
+
+ int z_8 = 0;
+ long y_0 = y[0] & M;
+
+ for (int i = 0; i < 8; ++i)
+ {
+ long x_i = x[i] & M;
+
+ long carry = x_i * y_0 + (z[0] & M);
+ long t = carry & M;
+ carry = (carry >>> 32) + t;
+
+ for (int j = 1; j < 8; ++j)
+ {
+ long prod1 = x_i * (y[j] & M);
+ long prod2 = t * (m[j] & M);
+
+ carry += (prod1 & M) + (prod2 & M) + (z[j] & M);
+ z[j - 1] = (int)carry;
+ carry = (carry >>> 32) + (prod1 >>> 32) + (prod2 >>> 32);
+ }
+
+ carry += (z_8 & M);
+ z[7] = (int)carry;
+ z_8 = (int)(carry >>> 32);
+ }
+
+ if (z_8 != 0 || Nat256.gte(z, m))
+ {
+ Nat256.sub(z, m, z);
+ }
+ }
+
+ public static void reduce(int[] z, int[] m, int mInv32)
+ {
+ for (int i = 0; i < 8; ++i)
+ {
+ int z_0 = z[0];
+
+ long t = (z_0 * mInv32) & M;
+
+ long carry = t * (m[0] & M) + (z_0 & M);
+ // assert (int)carry == 0;
+ carry >>>= 32;
+
+ for (int j = 1; j < 8; ++j)
+ {
+ carry += t * (m[j] & M) + (z[j] & M);
+ z[j - 1] = (int)carry;
+ carry >>>= 32;
+ }
+
+ z[7] = (int)carry;
+ // assert carry >>> 32 == 0;
+ }
+
+ if (Nat256.gte(z, m))
+ {
+ Nat256.sub(z, m, z);
+ }
+ }
+
+ public static void reduceXF(int[] z, int[] m)
+ {
+ // assert m[0] == M;
+
+ for (int i = 0; i < 8; ++i)
+ {
+ int z_0 = z[0];
+
+ long t = z_0 & M;
+ long carry = t;
+
+ for (int j = 1; j < 8; ++j)
+ {
+ carry += t * (m[j] & M) + (z[j] & M);
+ z[j - 1] = (int)carry;
+ carry >>>= 32;
+ }
+
+ z[7] = (int)carry;
+ // assert carry >>> 32 == 0;
+ }
+
+ if (Nat256.gte(z, m))
+ {
+ Nat256.sub(z, m, z);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/raw/Nat.java b/core/src/main/java/org/spongycastle/math/raw/Nat.java
new file mode 100644
index 00000000..14909673
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/raw/Nat.java
@@ -0,0 +1,1038 @@
+package org.spongycastle.math.raw;
+
+import java.math.BigInteger;
+
+import org.spongycastle.util.Pack;
+
+public abstract class Nat
+{
+ private static final long M = 0xFFFFFFFFL;
+
+ public static int add(int len, int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (x[i] & M) + (y[i] & M);
+ z[i] = (int)c;
+ c >>>= 32;
+ }
+ return (int)c;
+ }
+
+ public static int add33At(int len, int x, int[] z, int zPos)
+ {
+ // assert zPos <= (len - 2);
+ long c = (z[zPos + 0] & M) + (x & M);
+ z[zPos + 0] = (int)c;
+ c >>>= 32;
+ c += (z[zPos + 1] & M) + 1L;
+ z[zPos + 1] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, zPos + 2);
+ }
+
+ public static int add33At(int len, int x, int[] z, int zOff, int zPos)
+ {
+ // assert zPos <= (len - 2);
+ long c = (z[zOff + zPos] & M) + (x & M);
+ z[zOff + zPos] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + zPos + 1] & M) + 1L;
+ z[zOff + zPos + 1] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, zOff, zPos + 2);
+ }
+
+ public static int add33To(int len, int x, int[] z)
+ {
+ long c = (z[0] & M) + (x & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += (z[1] & M) + 1L;
+ z[1] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, 2);
+ }
+
+ public static int add33To(int len, int x, int[] z, int zOff)
+ {
+ long c = (z[zOff + 0] & M) + (x & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + 1] & M) + 1L;
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, zOff, 2);
+ }
+
+ public static int addBothTo(int len, int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (x[i] & M) + (y[i] & M) + (z[i] & M);
+ z[i] = (int)c;
+ c >>>= 32;
+ }
+ return (int)c;
+ }
+
+ public static int addBothTo(int len, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (x[xOff + i] & M) + (y[yOff + i] & M) + (z[zOff + i] & M);
+ z[zOff + i] = (int)c;
+ c >>>= 32;
+ }
+ return (int)c;
+ }
+
+ public static int addDWordAt(int len, long x, int[] z, int zPos)
+ {
+ // assert zPos <= (len - 2);
+ long c = (z[zPos + 0] & M) + (x & M);
+ z[zPos + 0] = (int)c;
+ c >>>= 32;
+ c += (z[zPos + 1] & M) + (x >>> 32);
+ z[zPos + 1] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, zPos + 2);
+ }
+
+ public static int addDWordAt(int len, long x, int[] z, int zOff, int zPos)
+ {
+ // assert zPos <= (len - 2);
+ long c = (z[zOff + zPos] & M) + (x & M);
+ z[zOff + zPos] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + zPos + 1] & M) + (x >>> 32);
+ z[zOff + zPos + 1] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, zOff, zPos + 2);
+ }
+
+ public static int addDWordTo(int len, long x, int[] z)
+ {
+ long c = (z[0] & M) + (x & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += (z[1] & M) + (x >>> 32);
+ z[1] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, 2);
+ }
+
+ public static int addDWordTo(int len, long x, int[] z, int zOff)
+ {
+ long c = (z[zOff + 0] & M) + (x & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + 1] & M) + (x >>> 32);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, zOff, 2);
+ }
+
+ public static int addTo(int len, int[] x, int[] z)
+ {
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (x[i] & M) + (z[i] & M);
+ z[i] = (int)c;
+ c >>>= 32;
+ }
+ return (int)c;
+ }
+
+ public static int addTo(int len, int[] x, int xOff, int[] z, int zOff)
+ {
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (x[xOff + i] & M) + (z[zOff + i] & M);
+ z[zOff + i] = (int)c;
+ c >>>= 32;
+ }
+ return (int)c;
+ }
+
+ public static int addWordAt(int len, int x, int[] z, int zPos)
+ {
+ // assert zPos <= (len - 1);
+ long c = (x & M) + (z[zPos] & M);
+ z[zPos] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, zPos + 1);
+ }
+
+ public static int addWordAt(int len, int x, int[] z, int zOff, int zPos)
+ {
+ // assert zPos <= (len - 1);
+ long c = (x & M) + (z[zOff + zPos] & M);
+ z[zOff + zPos] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, zOff, zPos + 1);
+ }
+
+ public static int addWordTo(int len, int x, int[] z)
+ {
+ long c = (x & M) + (z[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, 1);
+ }
+
+ public static int addWordTo(int len, int x, int[] z, int zOff)
+ {
+ long c = (x & M) + (z[zOff] & M);
+ z[zOff] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, zOff, 1);
+ }
+
+ public static int[] copy(int len, int[] x)
+ {
+ int[] z = new int[len];
+ System.arraycopy(x, 0, z, 0, len);
+ return z;
+ }
+
+ public static void copy(int len, int[] x, int[] z)
+ {
+ System.arraycopy(x, 0, z, 0, len);
+ }
+
+ public static int[] create(int len)
+ {
+ return new int[len];
+ }
+
+ public static int dec(int len, int[] z)
+ {
+ for (int i = 0; i < len; ++i)
+ {
+ if (--z[i] != -1)
+ {
+ return 0;
+ }
+ }
+ return -1;
+ }
+
+ public static int dec(int len, int[] x, int[] z)
+ {
+ int i = 0;
+ while (i < len)
+ {
+ int c = x[i] - 1;
+ z[i] = c;
+ ++i;
+ if (c != -1)
+ {
+ while (i < len)
+ {
+ z[i] = x[i];
+ ++i;
+ }
+ return 0;
+ }
+ }
+ return -1;
+ }
+
+ public static int decAt(int len, int[] z, int zPos)
+ {
+ // assert zPos <= len;
+ for (int i = zPos; i < len; ++i)
+ {
+ if (--z[i] != -1)
+ {
+ return 0;
+ }
+ }
+ return -1;
+ }
+
+ public static int decAt(int len, int[] z, int zOff, int zPos)
+ {
+ // assert zPos <= len;
+ for (int i = zPos; i < len; ++i)
+ {
+ if (--z[zOff + i] != -1)
+ {
+ return 0;
+ }
+ }
+ return -1;
+ }
+
+ public static boolean eq(int len, int[] x, int[] y)
+ {
+ for (int i = len - 1; i >= 0; --i)
+ {
+ if (x[i] != y[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static int[] fromBigInteger(int bits, BigInteger x)
+ {
+ if (x.signum() < 0 || x.bitLength() > bits)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ int len = (bits + 31) >> 5;
+ int[] z = create(len);
+ int i = 0;
+ while (x.signum() != 0)
+ {
+ z[i++] = x.intValue();
+ x = x.shiftRight(32);
+ }
+ return z;
+ }
+
+ public static int getBit(int[] x, int bit)
+ {
+ if (bit == 0)
+ {
+ return x[0] & 1;
+ }
+ int w = bit >> 5;
+ if (w < 0 || w >= x.length)
+ {
+ return 0;
+ }
+ int b = bit & 31;
+ return (x[w] >>> b) & 1;
+ }
+
+ public static boolean gte(int len, int[] x, int[] y)
+ {
+ for (int i = len - 1; i >= 0; --i)
+ {
+ int x_i = x[i] ^ Integer.MIN_VALUE;
+ int y_i = y[i] ^ Integer.MIN_VALUE;
+ if (x_i < y_i)
+ return false;
+ if (x_i > y_i)
+ return true;
+ }
+ return true;
+ }
+
+ public static int inc(int len, int[] z)
+ {
+ for (int i = 0; i < len; ++i)
+ {
+ if (++z[i] != 0)
+ {
+ return 0;
+ }
+ }
+ return 1;
+ }
+
+ public static int inc(int len, int[] x, int[] z)
+ {
+ int i = 0;
+ while (i < len)
+ {
+ int c = x[i] + 1;
+ z[i] = c;
+ ++i;
+ if (c != 0)
+ {
+ while (i < len)
+ {
+ z[i] = x[i];
+ ++i;
+ }
+ return 0;
+ }
+ }
+ return 1;
+ }
+
+ public static int incAt(int len, int[] z, int zPos)
+ {
+ // assert zPos <= len;
+ for (int i = zPos; i < len; ++i)
+ {
+ if (++z[i] != 0)
+ {
+ return 0;
+ }
+ }
+ return 1;
+ }
+
+ public static int incAt(int len, int[] z, int zOff, int zPos)
+ {
+ // assert zPos <= len;
+ for (int i = zPos; i < len; ++i)
+ {
+ if (++z[zOff + i] != 0)
+ {
+ return 0;
+ }
+ }
+ return 1;
+ }
+
+ public static boolean isOne(int len, int[] x)
+ {
+ if (x[0] != 1)
+ {
+ return false;
+ }
+ for (int i = 1; i < len; ++i)
+ {
+ if (x[i] != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static boolean isZero(int len, int[] x)
+ {
+ for (int i = 0; i < len; ++i)
+ {
+ if (x[i] != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static void mul(int len, int[] x, int[] y, int[] zz)
+ {
+ zz[len] = mulWord(len, x[0], y, zz);
+
+ for (int i = 1; i < len; ++i)
+ {
+ zz[i + len] = mulWordAddTo(len, x[i], y, 0, zz, i);
+ }
+ }
+
+ public static void mul(int len, int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
+ {
+ zz[zzOff + len] = mulWord(len, x[xOff], y, yOff, zz, zzOff);
+
+ for (int i = 1; i < len; ++i)
+ {
+ zz[zzOff + i + len] = mulWordAddTo(len, x[xOff + i], y, yOff, zz, zzOff + i);
+ }
+ }
+
+ public static int mulAddTo(int len, int[] x, int[] y, int[] zz)
+ {
+ long zc = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ long c = mulWordAddTo(len, x[i], y, 0, zz, i) & M;
+ c += zc + (zz[i + len] & M);
+ zz[i + len] = (int)c;
+ zc = c >>> 32;
+ }
+ return (int)zc;
+ }
+
+ public static int mulAddTo(int len, int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
+ {
+ long zc = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ long c = mulWordAddTo(len, x[xOff + i], y, yOff, zz, zzOff) & M;
+ c += zc + (zz[zzOff + len] & M);
+ zz[zzOff + len] = (int)c;
+ zc = c >>> 32;
+ ++zzOff;
+ }
+ return (int)zc;
+ }
+
+ public static int mul31BothAdd(int len, int a, int[] x, int b, int[] y, int[] z, int zOff)
+ {
+ long c = 0, aVal = a & M, bVal = b & M;
+ int i = 0;
+ do
+ {
+ c += aVal * (x[i] & M) + bVal * (y[i] & M) + (z[zOff + i] & M);
+ z[zOff + i] = (int)c;
+ c >>>= 32;
+ }
+ while (++i < len);
+ return (int)c;
+ }
+
+ public static int mulWord(int len, int x, int[] y, int[] z)
+ {
+ long c = 0, xVal = x & M;
+ int i = 0;
+ do
+ {
+ c += xVal * (y[i] & M);
+ z[i] = (int)c;
+ c >>>= 32;
+ }
+ while (++i < len);
+ return (int)c;
+ }
+
+ public static int mulWord(int len, int x, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0, xVal = x & M;
+ int i = 0;
+ do
+ {
+ c += xVal * (y[yOff + i] & M);
+ z[zOff + i] = (int)c;
+ c >>>= 32;
+ }
+ while (++i < len);
+ return (int)c;
+ }
+
+ public static int mulWordAddTo(int len, int x, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0, xVal = x & M;
+ int i = 0;
+ do
+ {
+ c += xVal * (y[yOff + i] & M) + (z[zOff + i] & M);
+ z[zOff + i] = (int)c;
+ c >>>= 32;
+ }
+ while (++i < len);
+ return (int)c;
+ }
+
+ public static int mulWordDwordAddAt(int len, int x, long y, int[] z, int zPos)
+ {
+ // assert zPos <= (len - 3);
+ long c = 0, xVal = x & M;
+ c += xVal * (y & M) + (z[zPos + 0] & M);
+ z[zPos + 0] = (int)c;
+ c >>>= 32;
+ c += xVal * (y >>> 32) + (z[zPos + 1] & M);
+ z[zPos + 1] = (int)c;
+ c >>>= 32;
+ c += (z[zPos + 2] & M);
+ z[zPos + 2] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, zPos + 3);
+ }
+
+ public static int shiftDownBit(int len, int[] z, int c)
+ {
+ int i = len;
+ while (--i >= 0)
+ {
+ int next = z[i];
+ z[i] = (next >>> 1) | (c << 31);
+ c = next;
+ }
+ return c << 31;
+ }
+
+ public static int shiftDownBit(int len, int[] z, int zOff, int c)
+ {
+ int i = len;
+ while (--i >= 0)
+ {
+ int next = z[zOff + i];
+ z[zOff + i] = (next >>> 1) | (c << 31);
+ c = next;
+ }
+ return c << 31;
+ }
+
+ public static int shiftDownBit(int len, int[] x, int c, int[] z)
+ {
+ int i = len;
+ while (--i >= 0)
+ {
+ int next = x[i];
+ z[i] = (next >>> 1) | (c << 31);
+ c = next;
+ }
+ return c << 31;
+ }
+
+ public static int shiftDownBit(int len, int[] x, int xOff, int c, int[] z, int zOff)
+ {
+ int i = len;
+ while (--i >= 0)
+ {
+ int next = x[xOff + i];
+ z[zOff + i] = (next >>> 1) | (c << 31);
+ c = next;
+ }
+ return c << 31;
+ }
+
+ public static int shiftDownBits(int len, int[] z, int bits, int c)
+ {
+// assert bits > 0 && bits < 32;
+ int i = len;
+ while (--i >= 0)
+ {
+ int next = z[i];
+ z[i] = (next >>> bits) | (c << -bits);
+ c = next;
+ }
+ return c << -bits;
+ }
+
+ public static int shiftDownBits(int len, int[] z, int zOff, int bits, int c)
+ {
+// assert bits > 0 && bits < 32;
+ int i = len;
+ while (--i >= 0)
+ {
+ int next = z[zOff + i];
+ z[zOff + i] = (next >>> bits) | (c << -bits);
+ c = next;
+ }
+ return c << -bits;
+ }
+
+ public static int shiftDownBits(int len, int[] x, int bits, int c, int[] z)
+ {
+// assert bits > 0 && bits < 32;
+ int i = len;
+ while (--i >= 0)
+ {
+ int next = x[i];
+ z[i] = (next >>> bits) | (c << -bits);
+ c = next;
+ }
+ return c << -bits;
+ }
+
+ public static int shiftDownBits(int len, int[] x, int xOff, int bits, int c, int[] z, int zOff)
+ {
+// assert bits > 0 && bits < 32;
+ int i = len;
+ while (--i >= 0)
+ {
+ int next = x[xOff + i];
+ z[zOff + i] = (next >>> bits) | (c << -bits);
+ c = next;
+ }
+ return c << -bits;
+ }
+
+ public static int shiftDownWord(int len, int[] z, int c)
+ {
+ int i = len;
+ while (--i >= 0)
+ {
+ int next = z[i];
+ z[i] = c;
+ c = next;
+ }
+ return c;
+ }
+
+ public static int shiftUpBit(int len, int[] z, int c)
+ {
+ for (int i = 0; i < len; ++i)
+ {
+ int next = z[i];
+ z[i] = (next << 1) | (c >>> 31);
+ c = next;
+ }
+ return c >>> 31;
+ }
+
+ public static int shiftUpBit(int len, int[] z, int zOff, int c)
+ {
+ for (int i = 0; i < len; ++i)
+ {
+ int next = z[zOff + i];
+ z[zOff + i] = (next << 1) | (c >>> 31);
+ c = next;
+ }
+ return c >>> 31;
+ }
+
+ public static int shiftUpBit(int len, int[] x, int c, int[] z)
+ {
+ for (int i = 0; i < len; ++i)
+ {
+ int next = x[i];
+ z[i] = (next << 1) | (c >>> 31);
+ c = next;
+ }
+ return c >>> 31;
+ }
+
+ public static int shiftUpBit(int len, int[] x, int xOff, int c, int[] z, int zOff)
+ {
+ for (int i = 0; i < len; ++i)
+ {
+ int next = x[xOff + i];
+ z[zOff + i] = (next << 1) | (c >>> 31);
+ c = next;
+ }
+ return c >>> 31;
+ }
+
+ public static int shiftUpBits(int len, int[] z, int bits, int c)
+ {
+// assert bits > 0 && bits < 32;
+ for (int i = 0; i < len; ++i)
+ {
+ int next = z[i];
+ z[i] = (next << bits) | (c >>> -bits);
+ c = next;
+ }
+ return c >>> -bits;
+ }
+
+ public static int shiftUpBits(int len, int[] z, int zOff, int bits, int c)
+ {
+// assert bits > 0 && bits < 32;
+ for (int i = 0; i < len; ++i)
+ {
+ int next = z[zOff + i];
+ z[zOff + i] = (next << bits) | (c >>> -bits);
+ c = next;
+ }
+ return c >>> -bits;
+ }
+
+ public static int shiftUpBits(int len, int[] x, int bits, int c, int[] z)
+ {
+// assert bits > 0 && bits < 32;
+ for (int i = 0; i < len; ++i)
+ {
+ int next = x[i];
+ z[i] = (next << bits) | (c >>> -bits);
+ c = next;
+ }
+ return c >>> -bits;
+ }
+
+ public static int shiftUpBits(int len, int[] x, int xOff, int bits, int c, int[] z, int zOff)
+ {
+// assert bits > 0 && bits < 32;
+ for (int i = 0; i < len; ++i)
+ {
+ int next = x[xOff + i];
+ z[zOff + i] = (next << bits) | (c >>> -bits);
+ c = next;
+ }
+ return c >>> -bits;
+ }
+
+ public static void square(int len, int[] x, int[] zz)
+ {
+ int extLen = len << 1;
+ int c = 0;
+ int j = len, k = extLen;
+ do
+ {
+ long xVal = (x[--j] & M);
+ long p = xVal * xVal;
+ zz[--k] = (c << 31) | (int)(p >>> 33);
+ zz[--k] = (int)(p >>> 1);
+ c = (int)p;
+ }
+ while (j > 0);
+
+ for (int i = 1; i < len; ++i)
+ {
+ c = squareWordAdd(x, i, zz);
+ addWordAt(extLen, c, zz, i << 1);
+ }
+
+ shiftUpBit(extLen, zz, x[0] << 31);
+ }
+
+ public static void square(int len, int[] x, int xOff, int[] zz, int zzOff)
+ {
+ int extLen = len << 1;
+ int c = 0;
+ int j = len, k = extLen;
+ do
+ {
+ long xVal = (x[xOff + --j] & M);
+ long p = xVal * xVal;
+ zz[zzOff + --k] = (c << 31) | (int)(p >>> 33);
+ zz[zzOff + --k] = (int)(p >>> 1);
+ c = (int)p;
+ }
+ while (j > 0);
+
+ for (int i = 1; i < len; ++i)
+ {
+ c = squareWordAdd(x, xOff, i, zz, zzOff);
+ addWordAt(extLen, c, zz, zzOff, i << 1);
+ }
+
+ shiftUpBit(extLen, zz, zzOff, x[xOff] << 31);
+ }
+
+ public static int squareWordAdd(int[] x, int xPos, int[] z)
+ {
+ long c = 0, xVal = x[xPos] & M;
+ int i = 0;
+ do
+ {
+ c += xVal * (x[i] & M) + (z[xPos + i] & M);
+ z[xPos + i] = (int)c;
+ c >>>= 32;
+ }
+ while (++i < xPos);
+ return (int)c;
+ }
+
+ public static int squareWordAdd(int[] x, int xOff, int xPos, int[] z, int zOff)
+ {
+ long c = 0, xVal = x[xOff + xPos] & M;
+ int i = 0;
+ do
+ {
+ c += xVal * (x[xOff + i] & M) + (z[xPos + zOff] & M);
+ z[xPos + zOff] = (int)c;
+ c >>>= 32;
+ ++zOff;
+ }
+ while (++i < xPos);
+ return (int)c;
+ }
+
+ public static int sub(int len, int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (x[i] & M) - (y[i] & M);
+ z[i] = (int)c;
+ c >>= 32;
+ }
+ return (int)c;
+ }
+
+ public static int sub(int len, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (x[xOff + i] & M) - (y[yOff + i] & M);
+ z[zOff + i] = (int)c;
+ c >>= 32;
+ }
+ return (int)c;
+ }
+
+ public static int sub33At(int len, int x, int[] z, int zPos)
+ {
+ // assert zPos <= (len - 2);
+ long c = (z[zPos + 0] & M) - (x & M);
+ z[zPos + 0] = (int)c;
+ c >>= 32;
+ c += (z[zPos + 1] & M) - 1;
+ z[zPos + 1] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, zPos + 2);
+ }
+
+ public static int sub33At(int len, int x, int[] z, int zOff, int zPos)
+ {
+ // assert zPos <= (len - 2);
+ long c = (z[zOff + zPos] & M) - (x & M);
+ z[zOff + zPos] = (int)c;
+ c >>= 32;
+ c += (z[zOff + zPos + 1] & M) - 1;
+ z[zOff + zPos + 1] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, zOff, zPos + 2);
+ }
+
+ public static int sub33From(int len, int x, int[] z)
+ {
+ long c = (z[0] & M) - (x & M);
+ z[0] = (int)c;
+ c >>= 32;
+ c += (z[1] & M) - 1;
+ z[1] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, 2);
+ }
+
+ public static int sub33From(int len, int x, int[] z, int zOff)
+ {
+ long c = (z[zOff + 0] & M) - (x & M);
+ z[zOff + 0] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 1] & M) - 1;
+ z[zOff + 1] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, zOff, 2);
+ }
+
+ public static int subBothFrom(int len, int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (z[i] & M) - (x[i] & M) - (y[i] & M);
+ z[i] = (int)c;
+ c >>= 32;
+ }
+ return (int)c;
+ }
+
+ public static int subBothFrom(int len, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (z[zOff + i] & M) - (x[xOff + i] & M) - (y[yOff + i] & M);
+ z[zOff + i] = (int)c;
+ c >>= 32;
+ }
+ return (int)c;
+ }
+
+ public static int subDWordAt(int len, long x, int[] z, int zPos)
+ {
+ // assert zPos <= (len - 2);
+ long c = (z[zPos + 0] & M) - (x & M);
+ z[zPos + 0] = (int)c;
+ c >>= 32;
+ c += (z[zPos + 1] & M) - (x >>> 32);
+ z[zPos + 1] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, zPos + 2);
+ }
+
+ public static int subDWordAt(int len, long x, int[] z, int zOff, int zPos)
+ {
+ // assert zPos <= (len - 2);
+ long c = (z[zOff + zPos] & M) - (x & M);
+ z[zOff + zPos] = (int)c;
+ c >>= 32;
+ c += (z[zOff + zPos + 1] & M) - (x >>> 32);
+ z[zOff + zPos + 1] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, zOff, zPos + 2);
+ }
+
+ public static int subDWordFrom(int len, long x, int[] z)
+ {
+ long c = (z[0] & M) - (x & M);
+ z[0] = (int)c;
+ c >>= 32;
+ c += (z[1] & M) - (x >>> 32);
+ z[1] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, 2);
+ }
+
+ public static int subDWordFrom(int len, long x, int[] z, int zOff)
+ {
+ long c = (z[zOff + 0] & M) - (x & M);
+ z[zOff + 0] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 1] & M) - (x >>> 32);
+ z[zOff + 1] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, zOff, 2);
+ }
+
+ public static int subFrom(int len, int[] x, int[] z)
+ {
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (z[i] & M) - (x[i] & M);
+ z[i] = (int)c;
+ c >>= 32;
+ }
+ return (int)c;
+ }
+
+ public static int subFrom(int len, int[] x, int xOff, int[] z, int zOff)
+ {
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (z[zOff + i] & M) - (x[xOff + i] & M);
+ z[zOff + i] = (int)c;
+ c >>= 32;
+ }
+ return (int)c;
+ }
+
+ public static int subWordAt(int len, int x, int[] z, int zPos)
+ {
+ // assert zPos <= (len - 1);
+ long c = (z[zPos] & M) - (x & M);
+ z[zPos] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, zPos + 1);
+ }
+
+ public static int subWordAt(int len, int x, int[] z, int zOff, int zPos)
+ {
+ // assert zPos <= (len - 1);
+ long c = (z[zOff + zPos] & M) - (x & M);
+ z[zOff + zPos] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, zOff, zPos + 1);
+ }
+
+ public static int subWordFrom(int len, int x, int[] z)
+ {
+ long c = (z[0] & M) - (x & M);
+ z[0] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, 1);
+ }
+
+ public static int subWordFrom(int len, int x, int[] z, int zOff)
+ {
+ long c = (z[zOff + 0] & M) - (x & M);
+ z[zOff + 0] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, zOff, 1);
+ }
+
+ public static BigInteger toBigInteger(int len, int[] x)
+ {
+ byte[] bs = new byte[len << 2];
+ for (int i = 0; i < len; ++i)
+ {
+ int x_i = x[i];
+ if (x_i != 0)
+ {
+ Pack.intToBigEndian(x_i, bs, (len - 1 - i) << 2);
+ }
+ }
+ return new BigInteger(1, bs);
+ }
+
+ public static void zero(int len, int[] z)
+ {
+ for (int i = 0; i < len; ++i)
+ {
+ z[i] = 0;
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/raw/Nat192.java b/core/src/main/java/org/spongycastle/math/raw/Nat192.java
new file mode 100644
index 00000000..0b71cfe8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/raw/Nat192.java
@@ -0,0 +1,968 @@
+package org.spongycastle.math.raw;
+
+import java.math.BigInteger;
+
+import org.spongycastle.util.Pack;
+
+public abstract class Nat192
+{
+ private static final long M = 0xFFFFFFFFL;
+
+ public static int add(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) + (y[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += (x[1] & M) + (y[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += (x[2] & M) + (y[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += (x[3] & M) + (y[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += (x[4] & M) + (y[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += (x[5] & M) + (y[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addBothTo(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) + (y[0] & M) + (z[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += (x[1] & M) + (y[1] & M) + (z[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += (x[2] & M) + (y[2] & M) + (z[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += (x[3] & M) + (y[3] & M) + (z[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += (x[4] & M) + (y[4] & M) + (z[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += (x[5] & M) + (y[5] & M) + (z[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addTo(int[] x, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) + (z[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += (x[1] & M) + (z[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += (x[2] & M) + (z[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += (x[3] & M) + (z[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += (x[4] & M) + (z[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += (x[5] & M) + (z[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addTo(int[] x, int xOff, int[] z, int zOff, int cIn)
+ {
+ long c = cIn & M;
+ c += (x[xOff + 0] & M) + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 1] & M) + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 2] & M) + (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 3] & M) + (z[zOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 4] & M) + (z[zOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 5] & M) + (z[zOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addToEachOther(int[] u, int uOff, int[] v, int vOff)
+ {
+ long c = 0;
+ c += (u[uOff + 0] & M) + (v[vOff + 0] & M);
+ u[uOff + 0] = (int)c;
+ v[vOff + 0] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 1] & M) + (v[vOff + 1] & M);
+ u[uOff + 1] = (int)c;
+ v[vOff + 1] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 2] & M) + (v[vOff + 2] & M);
+ u[uOff + 2] = (int)c;
+ v[vOff + 2] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 3] & M) + (v[vOff + 3] & M);
+ u[uOff + 3] = (int)c;
+ v[vOff + 3] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 4] & M) + (v[vOff + 4] & M);
+ u[uOff + 4] = (int)c;
+ v[vOff + 4] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 5] & M) + (v[vOff + 5] & M);
+ u[uOff + 5] = (int)c;
+ v[vOff + 5] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static void copy(int[] x, int[] z)
+ {
+ z[0] = x[0];
+ z[1] = x[1];
+ z[2] = x[2];
+ z[3] = x[3];
+ z[4] = x[4];
+ z[5] = x[5];
+ }
+
+ public static int[] create()
+ {
+ return new int[6];
+ }
+
+ public static int[] createExt()
+ {
+ return new int[12];
+ }
+
+ public static boolean diff(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ boolean pos = gte(x, xOff, y, yOff);
+ if (pos)
+ {
+ sub(x, xOff, y, yOff, z, zOff);
+ }
+ else
+ {
+ sub(y, yOff, x, xOff, z, zOff);
+ }
+ return pos;
+ }
+
+ public static boolean eq(int[] x, int[] y)
+ {
+ for (int i = 5; i >= 0; --i)
+ {
+ if (x[i] != y[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static int[] fromBigInteger(BigInteger x)
+ {
+ if (x.signum() < 0 || x.bitLength() > 192)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ int[] z = create();
+ int i = 0;
+ while (x.signum() != 0)
+ {
+ z[i++] = x.intValue();
+ x = x.shiftRight(32);
+ }
+ return z;
+ }
+
+ public static int getBit(int[] x, int bit)
+ {
+ if (bit == 0)
+ {
+ return x[0] & 1;
+ }
+ int w = bit >> 5;
+ if (w < 0 || w >= 6)
+ {
+ return 0;
+ }
+ int b = bit & 31;
+ return (x[w] >>> b) & 1;
+ }
+
+ public static boolean gte(int[] x, int[] y)
+ {
+ for (int i = 5; i >= 0; --i)
+ {
+ int x_i = x[i] ^ Integer.MIN_VALUE;
+ int y_i = y[i] ^ Integer.MIN_VALUE;
+ if (x_i < y_i)
+ return false;
+ if (x_i > y_i)
+ return true;
+ }
+ return true;
+ }
+
+ public static boolean gte(int[] x, int xOff, int[] y, int yOff)
+ {
+ for (int i = 5; i >= 0; --i)
+ {
+ int x_i = x[xOff + i] ^ Integer.MIN_VALUE;
+ int y_i = y[yOff + i] ^ Integer.MIN_VALUE;
+ if (x_i < y_i)
+ return false;
+ if (x_i > y_i)
+ return true;
+ }
+ return true;
+ }
+
+ public static boolean isOne(int[] x)
+ {
+ if (x[0] != 1)
+ {
+ return false;
+ }
+ for (int i = 1; i < 6; ++i)
+ {
+ if (x[i] != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static boolean isZero(int[] x)
+ {
+ for (int i = 0; i < 6; ++i)
+ {
+ if (x[i] != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static void mul(int[] x, int[] y, int[] zz)
+ {
+ long y_0 = y[0] & M;
+ long y_1 = y[1] & M;
+ long y_2 = y[2] & M;
+ long y_3 = y[3] & M;
+ long y_4 = y[4] & M;
+ long y_5 = y[5] & M;
+
+ {
+ long c = 0, x_0 = x[0] & M;
+ c += x_0 * y_0;
+ zz[0] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_1;
+ zz[1] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_2;
+ zz[2] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_3;
+ zz[3] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_4;
+ zz[4] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_5;
+ zz[5] = (int)c;
+ c >>>= 32;
+ zz[6] = (int)c;
+ }
+
+ for (int i = 1; i < 6; ++i)
+ {
+ long c = 0, x_i = x[i] & M;
+ c += x_i * y_0 + (zz[i + 0] & M);
+ zz[i + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[i + 1] & M);
+ zz[i + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[i + 2] & M);
+ zz[i + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[i + 3] & M);
+ zz[i + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[i + 4] & M);
+ zz[i + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[i + 5] & M);
+ zz[i + 5] = (int)c;
+ c >>>= 32;
+ zz[i + 6] = (int)c;
+ }
+ }
+
+ public static void mul(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
+ {
+ long y_0 = y[yOff + 0] & M;
+ long y_1 = y[yOff + 1] & M;
+ long y_2 = y[yOff + 2] & M;
+ long y_3 = y[yOff + 3] & M;
+ long y_4 = y[yOff + 4] & M;
+ long y_5 = y[yOff + 5] & M;
+
+ {
+ long c = 0, x_0 = x[xOff + 0] & M;
+ c += x_0 * y_0;
+ zz[zzOff + 0] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_1;
+ zz[zzOff + 1] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_2;
+ zz[zzOff + 2] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_3;
+ zz[zzOff + 3] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_4;
+ zz[zzOff + 4] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_5;
+ zz[zzOff + 5] = (int)c;
+ c >>>= 32;
+ zz[zzOff + 6] = (int)c;
+ }
+
+ for (int i = 1; i < 6; ++i)
+ {
+ ++zzOff;
+ long c = 0, x_i = x[xOff + i] & M;
+ c += x_i * y_0 + (zz[zzOff + 0] & M);
+ zz[zzOff + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[zzOff + 1] & M);
+ zz[zzOff + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[zzOff + 2] & M);
+ zz[zzOff + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[zzOff + 3] & M);
+ zz[zzOff + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[zzOff + 4] & M);
+ zz[zzOff + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[zzOff + 5] & M);
+ zz[zzOff + 5] = (int)c;
+ c >>>= 32;
+ zz[zzOff + 6] = (int)c;
+ }
+ }
+
+ public static int mulAddTo(int[] x, int[] y, int[] zz)
+ {
+ long y_0 = y[0] & M;
+ long y_1 = y[1] & M;
+ long y_2 = y[2] & M;
+ long y_3 = y[3] & M;
+ long y_4 = y[4] & M;
+ long y_5 = y[5] & M;
+
+ long zc = 0;
+ for (int i = 0; i < 6; ++i)
+ {
+ long c = 0, x_i = x[i] & M;
+ c += x_i * y_0 + (zz[i + 0] & M);
+ zz[i + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[i + 1] & M);
+ zz[i + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[i + 2] & M);
+ zz[i + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[i + 3] & M);
+ zz[i + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[i + 4] & M);
+ zz[i + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[i + 5] & M);
+ zz[i + 5] = (int)c;
+ c >>>= 32;
+ c += zc + (zz[i + 6] & M);
+ zz[i + 6] = (int)c;
+ zc = c >>> 32;
+ }
+ return (int)zc;
+ }
+
+ public static int mulAddTo(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
+ {
+ long y_0 = y[yOff + 0] & M;
+ long y_1 = y[yOff + 1] & M;
+ long y_2 = y[yOff + 2] & M;
+ long y_3 = y[yOff + 3] & M;
+ long y_4 = y[yOff + 4] & M;
+ long y_5 = y[yOff + 5] & M;
+
+ long zc = 0;
+ for (int i = 0; i < 6; ++i)
+ {
+ long c = 0, x_i = x[xOff + i] & M;
+ c += x_i * y_0 + (zz[zzOff + 0] & M);
+ zz[zzOff + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[zzOff + 1] & M);
+ zz[zzOff + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[zzOff + 2] & M);
+ zz[zzOff + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[zzOff + 3] & M);
+ zz[zzOff + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[zzOff + 4] & M);
+ zz[zzOff + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[zzOff + 5] & M);
+ zz[zzOff + 5] = (int)c;
+ c >>>= 32;
+ c += zc + (zz[zzOff + 6] & M);
+ zz[zzOff + 6] = (int)c;
+ zc = c >>> 32;
+ ++zzOff;
+ }
+ return (int)zc;
+ }
+
+ public static long mul33Add(int w, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ // assert w >>> 31 == 0;
+
+ long c = 0, wVal = w & M;
+ long x0 = x[xOff + 0] & M;
+ c += wVal * x0 + (y[yOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ long x1 = x[xOff + 1] & M;
+ c += wVal * x1 + x0 + (y[yOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ long x2 = x[xOff + 2] & M;
+ c += wVal * x2 + x1 + (y[yOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ long x3 = x[xOff + 3] & M;
+ c += wVal * x3 + x2 + (y[yOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ long x4 = x[xOff + 4] & M;
+ c += wVal * x4 + x3 + (y[yOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ long x5 = x[xOff + 5] & M;
+ c += wVal * x5 + x4 + (y[yOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ c += x5;
+ return c;
+ }
+
+ public static int mulWordAddExt(int x, int[] yy, int yyOff, int[] zz, int zzOff)
+ {
+ // assert yyOff <= 6;
+ // assert zzOff <= 6;
+ long c = 0, xVal = x & M;
+ c += xVal * (yy[yyOff + 0] & M) + (zz[zzOff + 0] & M);
+ zz[zzOff + 0] = (int)c;
+ c >>>= 32;
+ c += xVal * (yy[yyOff + 1] & M) + (zz[zzOff + 1] & M);
+ zz[zzOff + 1] = (int)c;
+ c >>>= 32;
+ c += xVal * (yy[yyOff + 2] & M) + (zz[zzOff + 2] & M);
+ zz[zzOff + 2] = (int)c;
+ c >>>= 32;
+ c += xVal * (yy[yyOff + 3] & M) + (zz[zzOff + 3] & M);
+ zz[zzOff + 3] = (int)c;
+ c >>>= 32;
+ c += xVal * (yy[yyOff + 4] & M) + (zz[zzOff + 4] & M);
+ zz[zzOff + 4] = (int)c;
+ c >>>= 32;
+ c += xVal * (yy[yyOff + 5] & M) + (zz[zzOff + 5] & M);
+ zz[zzOff + 5] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int mul33DWordAdd(int x, long y, int[] z, int zOff)
+ {
+ // assert x >>> 31 == 0;
+ // assert zOff <= 2;
+
+ long c = 0, xVal = x & M;
+ long y00 = y & M;
+ c += xVal * y00 + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ long y01 = y >>> 32;
+ c += xVal * y01 + y00 + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += y01 + (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : Nat.incAt(6, z, zOff, 4);
+ }
+
+ public static int mul33WordAdd(int x, int y, int[] z, int zOff)
+ {
+ // assert x >>> 31 == 0;
+ // assert zOff <= 3;
+
+ long c = 0, xVal = x & M, yVal = y & M;
+ c += yVal * xVal + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += yVal + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : Nat.incAt(6, z, zOff, 3);
+ }
+
+ public static int mulWordDwordAdd(int x, long y, int[] z, int zOff)
+ {
+ // assert zOff <= 3;
+ long c = 0, xVal = x & M;
+ c += xVal * (y & M) + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += xVal * (y >>> 32) + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : Nat.incAt(6, z, zOff, 3);
+ }
+
+ public static int mulWord(int x, int[] y, int[] z, int zOff)
+ {
+ long c = 0, xVal = x & M;
+ int i = 0;
+ do
+ {
+ c += xVal * (y[i] & M);
+ z[zOff + i] = (int)c;
+ c >>>= 32;
+ }
+ while (++i < 6);
+ return (int)c;
+ }
+
+ public static void square(int[] x, int[] zz)
+ {
+ long x_0 = x[0] & M;
+ long zz_1;
+
+ int c = 0, w;
+ {
+ int i = 5, j = 12;
+ do
+ {
+ long xVal = (x[i--] & M);
+ long p = xVal * xVal;
+ zz[--j] = (c << 31) | (int)(p >>> 33);
+ zz[--j] = (int)(p >>> 1);
+ c = (int)p;
+ }
+ while (i > 0);
+
+ {
+ long p = x_0 * x_0;
+ zz_1 = ((c << 31) & M) | (p >>> 33);
+ zz[0] = (int)p;
+ c = (int)(p >>> 32) & 1;
+ }
+ }
+
+ long x_1 = x[1] & M;
+ long zz_2 = zz[2] & M;
+
+ {
+ zz_1 += x_1 * x_0;
+ w = (int)zz_1;
+ zz[1] = (w << 1) | c;
+ c = w >>> 31;
+ zz_2 += zz_1 >>> 32;
+ }
+
+ long x_2 = x[2] & M;
+ long zz_3 = zz[3] & M;
+ long zz_4 = zz[4] & M;
+ {
+ zz_2 += x_2 * x_0;
+ w = (int)zz_2;
+ zz[2] = (w << 1) | c;
+ c = w >>> 31;
+ zz_3 += (zz_2 >>> 32) + x_2 * x_1;
+ zz_4 += zz_3 >>> 32;
+ zz_3 &= M;
+ }
+
+ long x_3 = x[3] & M;
+ long zz_5 = zz[5] & M;
+ long zz_6 = zz[6] & M;
+ {
+ zz_3 += x_3 * x_0;
+ w = (int)zz_3;
+ zz[3] = (w << 1) | c;
+ c = w >>> 31;
+ zz_4 += (zz_3 >>> 32) + x_3 * x_1;
+ zz_5 += (zz_4 >>> 32) + x_3 * x_2;
+ zz_4 &= M;
+ zz_6 += zz_5 >>> 32;
+ zz_5 &= M;
+ }
+
+ long x_4 = x[4] & M;
+ long zz_7 = zz[7] & M;
+ long zz_8 = zz[8] & M;
+ {
+ zz_4 += x_4 * x_0;
+ w = (int)zz_4;
+ zz[4] = (w << 1) | c;
+ c = w >>> 31;
+ zz_5 += (zz_4 >>> 32) + x_4 * x_1;
+ zz_6 += (zz_5 >>> 32) + x_4 * x_2;
+ zz_5 &= M;
+ zz_7 += (zz_6 >>> 32) + x_4 * x_3;
+ zz_6 &= M;
+ zz_8 += zz_7 >>> 32;
+ zz_7 &= M;
+ }
+
+ long x_5 = x[5] & M;
+ long zz_9 = zz[9] & M;
+ long zz_10 = zz[10] & M;
+ {
+ zz_5 += x_5 * x_0;
+ w = (int)zz_5;
+ zz[5] = (w << 1) | c;
+ c = w >>> 31;
+ zz_6 += (zz_5 >>> 32) + x_5 * x_1;
+ zz_7 += (zz_6 >>> 32) + x_5 * x_2;
+ zz_8 += (zz_7 >>> 32) + x_5 * x_3;
+ zz_9 += (zz_8 >>> 32) + x_5 * x_4;
+ zz_10 += zz_9 >>> 32;
+ }
+
+ w = (int)zz_6;
+ zz[6] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_7;
+ zz[7] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_8;
+ zz[8] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_9;
+ zz[9] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_10;
+ zz[10] = (w << 1) | c;
+ c = w >>> 31;
+ w = zz[11] + (int)(zz_10 >> 32);
+ zz[11] = (w << 1) | c;
+ }
+
+ public static void square(int[] x, int xOff, int[] zz, int zzOff)
+ {
+ long x_0 = x[xOff + 0] & M;
+ long zz_1;
+
+ int c = 0, w;
+ {
+ int i = 5, j = 12;
+ do
+ {
+ long xVal = (x[xOff + i--] & M);
+ long p = xVal * xVal;
+ zz[zzOff + --j] = (c << 31) | (int)(p >>> 33);
+ zz[zzOff + --j] = (int)(p >>> 1);
+ c = (int)p;
+ }
+ while (i > 0);
+
+ {
+ long p = x_0 * x_0;
+ zz_1 = ((c << 31) & M) | (p >>> 33);
+ zz[zzOff + 0] = (int)p;
+ c = (int)(p >>> 32) & 1;
+ }
+ }
+
+ long x_1 = x[xOff + 1] & M;
+ long zz_2 = zz[zzOff + 2] & M;
+
+ {
+ zz_1 += x_1 * x_0;
+ w = (int)zz_1;
+ zz[zzOff + 1] = (w << 1) | c;
+ c = w >>> 31;
+ zz_2 += zz_1 >>> 32;
+ }
+
+ long x_2 = x[xOff + 2] & M;
+ long zz_3 = zz[zzOff + 3] & M;
+ long zz_4 = zz[zzOff + 4] & M;
+ {
+ zz_2 += x_2 * x_0;
+ w = (int)zz_2;
+ zz[zzOff + 2] = (w << 1) | c;
+ c = w >>> 31;
+ zz_3 += (zz_2 >>> 32) + x_2 * x_1;
+ zz_4 += zz_3 >>> 32;
+ zz_3 &= M;
+ }
+
+ long x_3 = x[xOff + 3] & M;
+ long zz_5 = zz[zzOff + 5] & M;
+ long zz_6 = zz[zzOff + 6] & M;
+ {
+ zz_3 += x_3 * x_0;
+ w = (int)zz_3;
+ zz[zzOff + 3] = (w << 1) | c;
+ c = w >>> 31;
+ zz_4 += (zz_3 >>> 32) + x_3 * x_1;
+ zz_5 += (zz_4 >>> 32) + x_3 * x_2;
+ zz_4 &= M;
+ zz_6 += zz_5 >>> 32;
+ zz_5 &= M;
+ }
+
+ long x_4 = x[xOff + 4] & M;
+ long zz_7 = zz[zzOff + 7] & M;
+ long zz_8 = zz[zzOff + 8] & M;
+ {
+ zz_4 += x_4 * x_0;
+ w = (int)zz_4;
+ zz[zzOff + 4] = (w << 1) | c;
+ c = w >>> 31;
+ zz_5 += (zz_4 >>> 32) + x_4 * x_1;
+ zz_6 += (zz_5 >>> 32) + x_4 * x_2;
+ zz_5 &= M;
+ zz_7 += (zz_6 >>> 32) + x_4 * x_3;
+ zz_6 &= M;
+ zz_8 += zz_7 >>> 32;
+ zz_7 &= M;
+ }
+
+ long x_5 = x[xOff + 5] & M;
+ long zz_9 = zz[zzOff + 9] & M;
+ long zz_10 = zz[zzOff + 10] & M;
+ {
+ zz_5 += x_5 * x_0;
+ w = (int)zz_5;
+ zz[zzOff + 5] = (w << 1) | c;
+ c = w >>> 31;
+ zz_6 += (zz_5 >>> 32) + x_5 * x_1;
+ zz_7 += (zz_6 >>> 32) + x_5 * x_2;
+ zz_8 += (zz_7 >>> 32) + x_5 * x_3;
+ zz_9 += (zz_8 >>> 32) + x_5 * x_4;
+ zz_10 += zz_9 >>> 32;
+ }
+
+ w = (int)zz_6;
+ zz[zzOff + 6] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_7;
+ zz[zzOff + 7] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_8;
+ zz[zzOff + 8] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_9;
+ zz[zzOff + 9] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_10;
+ zz[zzOff + 10] = (w << 1) | c;
+ c = w >>> 31;
+ w = zz[zzOff + 11] + (int)(zz_10 >> 32);
+ zz[zzOff + 11] = (w << 1) | c;
+ }
+
+ public static int sub(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) - (y[0] & M);
+ z[0] = (int)c;
+ c >>= 32;
+ c += (x[1] & M) - (y[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (x[2] & M) - (y[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ c += (x[3] & M) - (y[3] & M);
+ z[3] = (int)c;
+ c >>= 32;
+ c += (x[4] & M) - (y[4] & M);
+ z[4] = (int)c;
+ c >>= 32;
+ c += (x[5] & M) - (y[5] & M);
+ z[5] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int sub(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0;
+ c += (x[xOff + 0] & M) - (y[yOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 1] & M) - (y[yOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 2] & M) - (y[yOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 3] & M) - (y[yOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 4] & M) - (y[yOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 5] & M) - (y[yOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int subBothFrom(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (z[0] & M) - (x[0] & M) - (y[0] & M);
+ z[0] = (int)c;
+ c >>= 32;
+ c += (z[1] & M) - (x[1] & M) - (y[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (z[2] & M) - (x[2] & M) - (y[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ c += (z[3] & M) - (x[3] & M) - (y[3] & M);
+ z[3] = (int)c;
+ c >>= 32;
+ c += (z[4] & M) - (x[4] & M) - (y[4] & M);
+ z[4] = (int)c;
+ c >>= 32;
+ c += (z[5] & M) - (x[5] & M) - (y[5] & M);
+ z[5] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int subFrom(int[] x, int[] z)
+ {
+ long c = 0;
+ c += (z[0] & M) - (x[0] & M);
+ z[0] = (int)c;
+ c >>= 32;
+ c += (z[1] & M) - (x[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (z[2] & M) - (x[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ c += (z[3] & M) - (x[3] & M);
+ z[3] = (int)c;
+ c >>= 32;
+ c += (z[4] & M) - (x[4] & M);
+ z[4] = (int)c;
+ c >>= 32;
+ c += (z[5] & M) - (x[5] & M);
+ z[5] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int subFrom(int[] x, int xOff, int[] z, int zOff)
+ {
+ long c = 0;
+ c += (z[zOff + 0] & M) - (x[xOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 1] & M) - (x[xOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 2] & M) - (x[xOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 3] & M) - (x[xOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 4] & M) - (x[xOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 5] & M) - (x[xOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static BigInteger toBigInteger(int[] x)
+ {
+ byte[] bs = new byte[24];
+ for (int i = 0; i < 6; ++i)
+ {
+ int x_i = x[i];
+ if (x_i != 0)
+ {
+ Pack.intToBigEndian(x_i, bs, (5 - i) << 2);
+ }
+ }
+ return new BigInteger(1, bs);
+ }
+
+ public static void zero(int[] z)
+ {
+ z[0] = 0;
+ z[1] = 0;
+ z[2] = 0;
+ z[3] = 0;
+ z[4] = 0;
+ z[5] = 0;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/raw/Nat224.java b/core/src/main/java/org/spongycastle/math/raw/Nat224.java
new file mode 100644
index 00000000..8f4e47b8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/raw/Nat224.java
@@ -0,0 +1,1182 @@
+package org.spongycastle.math.raw;
+
+import java.math.BigInteger;
+
+import org.spongycastle.util.Pack;
+
+public abstract class Nat224
+{
+ private static final long M = 0xFFFFFFFFL;
+
+ public static int add(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) + (y[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += (x[1] & M) + (y[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += (x[2] & M) + (y[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += (x[3] & M) + (y[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += (x[4] & M) + (y[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += (x[5] & M) + (y[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ c += (x[6] & M) + (y[6] & M);
+ z[6] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int add(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0;
+ c += (x[xOff + 0] & M) + (y[yOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 1] & M) + (y[yOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 2] & M) + (y[yOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 3] & M) + (y[yOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 4] & M) + (y[yOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 5] & M) + (y[yOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 6] & M) + (y[yOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addBothTo(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) + (y[0] & M) + (z[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += (x[1] & M) + (y[1] & M) + (z[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += (x[2] & M) + (y[2] & M) + (z[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += (x[3] & M) + (y[3] & M) + (z[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += (x[4] & M) + (y[4] & M) + (z[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += (x[5] & M) + (y[5] & M) + (z[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ c += (x[6] & M) + (y[6] & M) + (z[6] & M);
+ z[6] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addBothTo(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0;
+ c += (x[xOff + 0] & M) + (y[yOff + 0] & M) + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 1] & M) + (y[yOff + 1] & M) + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 2] & M) + (y[yOff + 2] & M) + (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 3] & M) + (y[yOff + 3] & M) + (z[zOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 4] & M) + (y[yOff + 4] & M) + (z[zOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 5] & M) + (y[yOff + 5] & M) + (z[zOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 6] & M) + (y[yOff + 6] & M) + (z[zOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addTo(int[] x, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) + (z[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += (x[1] & M) + (z[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += (x[2] & M) + (z[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += (x[3] & M) + (z[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += (x[4] & M) + (z[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += (x[5] & M) + (z[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ c += (x[6] & M) + (z[6] & M);
+ z[6] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addTo(int[] x, int xOff, int[] z, int zOff, int cIn)
+ {
+ long c = cIn & M;
+ c += (x[xOff + 0] & M) + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 1] & M) + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 2] & M) + (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 3] & M) + (z[zOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 4] & M) + (z[zOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 5] & M) + (z[zOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 6] & M) + (z[zOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addToEachOther(int[] u, int uOff, int[] v, int vOff)
+ {
+ long c = 0;
+ c += (u[uOff + 0] & M) + (v[vOff + 0] & M);
+ u[uOff + 0] = (int)c;
+ v[vOff + 0] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 1] & M) + (v[vOff + 1] & M);
+ u[uOff + 1] = (int)c;
+ v[vOff + 1] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 2] & M) + (v[vOff + 2] & M);
+ u[uOff + 2] = (int)c;
+ v[vOff + 2] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 3] & M) + (v[vOff + 3] & M);
+ u[uOff + 3] = (int)c;
+ v[vOff + 3] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 4] & M) + (v[vOff + 4] & M);
+ u[uOff + 4] = (int)c;
+ v[vOff + 4] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 5] & M) + (v[vOff + 5] & M);
+ u[uOff + 5] = (int)c;
+ v[vOff + 5] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 6] & M) + (v[vOff + 6] & M);
+ u[uOff + 6] = (int)c;
+ v[vOff + 6] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static void copy(int[] x, int[] z)
+ {
+ z[0] = x[0];
+ z[1] = x[1];
+ z[2] = x[2];
+ z[3] = x[3];
+ z[4] = x[4];
+ z[5] = x[5];
+ z[6] = x[6];
+ }
+
+ public static int[] create()
+ {
+ return new int[7];
+ }
+
+ public static int[] createExt()
+ {
+ return new int[14];
+ }
+
+ public static boolean diff(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ boolean pos = gte(x, xOff, y, yOff);
+ if (pos)
+ {
+ sub(x, xOff, y, yOff, z, zOff);
+ }
+ else
+ {
+ sub(y, yOff, x, xOff, z, zOff);
+ }
+ return pos;
+ }
+
+ public static boolean eq(int[] x, int[] y)
+ {
+ for (int i = 6; i >= 0; --i)
+ {
+ if (x[i] != y[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static int[] fromBigInteger(BigInteger x)
+ {
+ if (x.signum() < 0 || x.bitLength() > 224)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ int[] z = create();
+ int i = 0;
+ while (x.signum() != 0)
+ {
+ z[i++] = x.intValue();
+ x = x.shiftRight(32);
+ }
+ return z;
+ }
+
+ public static int getBit(int[] x, int bit)
+ {
+ if (bit == 0)
+ {
+ return x[0] & 1;
+ }
+ int w = bit >> 5;
+ if (w < 0 || w >= 7)
+ {
+ return 0;
+ }
+ int b = bit & 31;
+ return (x[w] >>> b) & 1;
+ }
+
+ public static boolean gte(int[] x, int[] y)
+ {
+ for (int i = 6; i >= 0; --i)
+ {
+ int x_i = x[i] ^ Integer.MIN_VALUE;
+ int y_i = y[i] ^ Integer.MIN_VALUE;
+ if (x_i < y_i)
+ return false;
+ if (x_i > y_i)
+ return true;
+ }
+ return true;
+ }
+
+ public static boolean gte(int[] x, int xOff, int[] y, int yOff)
+ {
+ for (int i = 6; i >= 0; --i)
+ {
+ int x_i = x[xOff + i] ^ Integer.MIN_VALUE;
+ int y_i = y[yOff + i] ^ Integer.MIN_VALUE;
+ if (x_i < y_i)
+ return false;
+ if (x_i > y_i)
+ return true;
+ }
+ return true;
+ }
+
+ public static boolean isOne(int[] x)
+ {
+ if (x[0] != 1)
+ {
+ return false;
+ }
+ for (int i = 1; i < 7; ++i)
+ {
+ if (x[i] != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static boolean isZero(int[] x)
+ {
+ for (int i = 0; i < 7; ++i)
+ {
+ if (x[i] != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static void mul(int[] x, int[] y, int[] zz)
+ {
+ long y_0 = y[0] & M;
+ long y_1 = y[1] & M;
+ long y_2 = y[2] & M;
+ long y_3 = y[3] & M;
+ long y_4 = y[4] & M;
+ long y_5 = y[5] & M;
+ long y_6 = y[6] & M;
+
+ {
+ long c = 0, x_0 = x[0] & M;
+ c += x_0 * y_0;
+ zz[0] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_1;
+ zz[1] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_2;
+ zz[2] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_3;
+ zz[3] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_4;
+ zz[4] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_5;
+ zz[5] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_6;
+ zz[6] = (int)c;
+ c >>>= 32;
+ zz[7] = (int)c;
+ }
+
+ for (int i = 1; i < 7; ++i)
+ {
+ long c = 0, x_i = x[i] & M;
+ c += x_i * y_0 + (zz[i + 0] & M);
+ zz[i + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[i + 1] & M);
+ zz[i + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[i + 2] & M);
+ zz[i + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[i + 3] & M);
+ zz[i + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[i + 4] & M);
+ zz[i + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[i + 5] & M);
+ zz[i + 5] = (int)c;
+ c >>>= 32;
+ c += x_i * y_6 + (zz[i + 6] & M);
+ zz[i + 6] = (int)c;
+ c >>>= 32;
+ zz[i + 7] = (int)c;
+ }
+ }
+
+ public static void mul(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
+ {
+ long y_0 = y[yOff + 0] & M;
+ long y_1 = y[yOff + 1] & M;
+ long y_2 = y[yOff + 2] & M;
+ long y_3 = y[yOff + 3] & M;
+ long y_4 = y[yOff + 4] & M;
+ long y_5 = y[yOff + 5] & M;
+ long y_6 = y[yOff + 6] & M;
+
+ {
+ long c = 0, x_0 = x[xOff + 0] & M;
+ c += x_0 * y_0;
+ zz[zzOff + 0] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_1;
+ zz[zzOff + 1] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_2;
+ zz[zzOff + 2] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_3;
+ zz[zzOff + 3] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_4;
+ zz[zzOff + 4] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_5;
+ zz[zzOff + 5] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_6;
+ zz[zzOff + 6] = (int)c;
+ c >>>= 32;
+ zz[zzOff + 7] = (int)c;
+ }
+
+ for (int i = 1; i < 7; ++i)
+ {
+ ++zzOff;
+ long c = 0, x_i = x[xOff + i] & M;
+ c += x_i * y_0 + (zz[zzOff + 0] & M);
+ zz[zzOff + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[zzOff + 1] & M);
+ zz[zzOff + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[zzOff + 2] & M);
+ zz[zzOff + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[zzOff + 3] & M);
+ zz[zzOff + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[zzOff + 4] & M);
+ zz[zzOff + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[zzOff + 5] & M);
+ zz[zzOff + 5] = (int)c;
+ c >>>= 32;
+ c += x_i * y_6 + (zz[zzOff + 6] & M);
+ zz[zzOff + 6] = (int)c;
+ c >>>= 32;
+ zz[zzOff + 7] = (int)c;
+ }
+ }
+
+ public static int mulAddTo(int[] x, int[] y, int[] zz)
+ {
+ long y_0 = y[0] & M;
+ long y_1 = y[1] & M;
+ long y_2 = y[2] & M;
+ long y_3 = y[3] & M;
+ long y_4 = y[4] & M;
+ long y_5 = y[5] & M;
+ long y_6 = y[6] & M;
+
+ long zc = 0;
+ for (int i = 0; i < 7; ++i)
+ {
+ long c = 0, x_i = x[i] & M;
+ c += x_i * y_0 + (zz[i + 0] & M);
+ zz[i + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[i + 1] & M);
+ zz[i + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[i + 2] & M);
+ zz[i + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[i + 3] & M);
+ zz[i + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[i + 4] & M);
+ zz[i + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[i + 5] & M);
+ zz[i + 5] = (int)c;
+ c >>>= 32;
+ c += x_i * y_6 + (zz[i + 6] & M);
+ zz[i + 6] = (int)c;
+ c >>>= 32;
+ c += zc + (zz[i + 7] & M);
+ zz[i + 7] = (int)c;
+ zc = c >>> 32;
+ }
+ return (int)zc;
+ }
+
+ public static int mulAddTo(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
+ {
+ long y_0 = y[yOff + 0] & M;
+ long y_1 = y[yOff + 1] & M;
+ long y_2 = y[yOff + 2] & M;
+ long y_3 = y[yOff + 3] & M;
+ long y_4 = y[yOff + 4] & M;
+ long y_5 = y[yOff + 5] & M;
+ long y_6 = y[yOff + 6] & M;
+
+ long zc = 0;
+ for (int i = 0; i < 7; ++i)
+ {
+ long c = 0, x_i = x[xOff + i] & M;
+ c += x_i * y_0 + (zz[zzOff + 0] & M);
+ zz[zzOff + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[zzOff + 1] & M);
+ zz[zzOff + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[zzOff + 2] & M);
+ zz[zzOff + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[zzOff + 3] & M);
+ zz[zzOff + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[zzOff + 4] & M);
+ zz[zzOff + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[zzOff + 5] & M);
+ zz[zzOff + 5] = (int)c;
+ c >>>= 32;
+ c += x_i * y_6 + (zz[zzOff + 6] & M);
+ zz[zzOff + 6] = (int)c;
+ c >>>= 32;
+ c += zc + (zz[zzOff + 7] & M);
+ zz[zzOff + 7] = (int)c;
+ zc = c >>> 32;
+ ++zzOff;
+ }
+ return (int)zc;
+ }
+
+ public static long mul33Add(int w, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ // assert w >>> 31 == 0;
+
+ long c = 0, wVal = w & M;
+ long x0 = x[xOff + 0] & M;
+ c += wVal * x0 + (y[yOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ long x1 = x[xOff + 1] & M;
+ c += wVal * x1 + x0 + (y[yOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ long x2 = x[xOff + 2] & M;
+ c += wVal * x2 + x1 + (y[yOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ long x3 = x[xOff + 3] & M;
+ c += wVal * x3 + x2 + (y[yOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ long x4 = x[xOff + 4] & M;
+ c += wVal * x4 + x3 + (y[yOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ long x5 = x[xOff + 5] & M;
+ c += wVal * x5 + x4 + (y[yOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ long x6 = x[xOff + 6] & M;
+ c += wVal * x6 + x5 + (y[yOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>>= 32;
+ c += x6;
+ return c;
+ }
+
+ public static int mulByWord(int x, int[] z)
+ {
+ long c = 0, xVal = x & M;
+ c += xVal * (z[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[6] & M);
+ z[6] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int mulByWordAddTo(int x, int[] y, int[] z)
+ {
+ long c = 0, xVal = x & M;
+ c += xVal * (z[0] & M) + (y[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[1] & M) + (y[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[2] & M) + (y[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[3] & M) + (y[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[4] & M) + (y[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[5] & M) + (y[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[6] & M) + (y[6] & M);
+ z[6] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int mulWordAddTo(int x, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0, xVal = x & M;
+ c += xVal * (y[yOff + 0] & M) + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 1] & M) + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 2] & M) + (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 3] & M) + (z[zOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 4] & M) + (z[zOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 5] & M) + (z[zOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 6] & M) + (z[zOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int mul33DWordAdd(int x, long y, int[] z, int zOff)
+ {
+ // assert x >>> 31 == 0;
+ // assert zOff <= 3;
+
+ long c = 0, xVal = x & M;
+ long y00 = y & M;
+ c += xVal * y00 + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ long y01 = y >>> 32;
+ c += xVal * y01 + y00 + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += y01 + (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : Nat.incAt(7, z, zOff, 4);
+ }
+
+ public static int mul33WordAdd(int x, int y, int[] z, int zOff)
+ {
+ // assert x >>> 31 == 0;
+ // assert zOff <= 4;
+
+ long c = 0, xVal = x & M, yVal = y & M;
+ c += yVal * xVal + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += yVal + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : Nat.incAt(7, z, zOff, 3);
+ }
+
+ public static int mulWordDwordAdd(int x, long y, int[] z, int zOff)
+ {
+ // assert zOff <= 4;
+ long c = 0, xVal = x & M;
+ c += xVal * (y & M) + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += xVal * (y >>> 32) + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : Nat.incAt(7, z, zOff, 3);
+ }
+
+ public static int mulWord(int x, int[] y, int[] z, int zOff)
+ {
+ long c = 0, xVal = x & M;
+ int i = 0;
+ do
+ {
+ c += xVal * (y[i] & M);
+ z[zOff + i] = (int)c;
+ c >>>= 32;
+ }
+ while (++i < 7);
+ return (int)c;
+ }
+
+ public static void square(int[] x, int[] zz)
+ {
+ long x_0 = x[0] & M;
+ long zz_1;
+
+ int c = 0, w;
+ {
+ int i = 6, j = 14;
+ do
+ {
+ long xVal = (x[i--] & M);
+ long p = xVal * xVal;
+ zz[--j] = (c << 31) | (int)(p >>> 33);
+ zz[--j] = (int)(p >>> 1);
+ c = (int)p;
+ }
+ while (i > 0);
+
+ {
+ long p = x_0 * x_0;
+ zz_1 = ((c << 31) & M) | (p >>> 33);
+ zz[0] = (int)p;
+ c = (int)(p >>> 32) & 1;
+ }
+ }
+
+ long x_1 = x[1] & M;
+ long zz_2 = zz[2] & M;
+
+ {
+ zz_1 += x_1 * x_0;
+ w = (int)zz_1;
+ zz[1] = (w << 1) | c;
+ c = w >>> 31;
+ zz_2 += zz_1 >>> 32;
+ }
+
+ long x_2 = x[2] & M;
+ long zz_3 = zz[3] & M;
+ long zz_4 = zz[4] & M;
+ {
+ zz_2 += x_2 * x_0;
+ w = (int)zz_2;
+ zz[2] = (w << 1) | c;
+ c = w >>> 31;
+ zz_3 += (zz_2 >>> 32) + x_2 * x_1;
+ zz_4 += zz_3 >>> 32;
+ zz_3 &= M;
+ }
+
+ long x_3 = x[3] & M;
+ long zz_5 = zz[5] & M;
+ long zz_6 = zz[6] & M;
+ {
+ zz_3 += x_3 * x_0;
+ w = (int)zz_3;
+ zz[3] = (w << 1) | c;
+ c = w >>> 31;
+ zz_4 += (zz_3 >>> 32) + x_3 * x_1;
+ zz_5 += (zz_4 >>> 32) + x_3 * x_2;
+ zz_4 &= M;
+ zz_6 += zz_5 >>> 32;
+ zz_5 &= M;
+ }
+
+ long x_4 = x[4] & M;
+ long zz_7 = zz[7] & M;
+ long zz_8 = zz[8] & M;
+ {
+ zz_4 += x_4 * x_0;
+ w = (int)zz_4;
+ zz[4] = (w << 1) | c;
+ c = w >>> 31;
+ zz_5 += (zz_4 >>> 32) + x_4 * x_1;
+ zz_6 += (zz_5 >>> 32) + x_4 * x_2;
+ zz_5 &= M;
+ zz_7 += (zz_6 >>> 32) + x_4 * x_3;
+ zz_6 &= M;
+ zz_8 += zz_7 >>> 32;
+ zz_7 &= M;
+ }
+
+ long x_5 = x[5] & M;
+ long zz_9 = zz[9] & M;
+ long zz_10 = zz[10] & M;
+ {
+ zz_5 += x_5 * x_0;
+ w = (int)zz_5;
+ zz[5] = (w << 1) | c;
+ c = w >>> 31;
+ zz_6 += (zz_5 >>> 32) + x_5 * x_1;
+ zz_7 += (zz_6 >>> 32) + x_5 * x_2;
+ zz_6 &= M;
+ zz_8 += (zz_7 >>> 32) + x_5 * x_3;
+ zz_7 &= M;
+ zz_9 += (zz_8 >>> 32) + x_5 * x_4;
+ zz_8 &= M;
+ zz_10 += zz_9 >>> 32;
+ zz_9 &= M;
+ }
+
+ long x_6 = x[6] & M;
+ long zz_11 = zz[11] & M;
+ long zz_12 = zz[12] & M;
+ {
+ zz_6 += x_6 * x_0;
+ w = (int)zz_6;
+ zz[6] = (w << 1) | c;
+ c = w >>> 31;
+ zz_7 += (zz_6 >>> 32) + x_6 * x_1;
+ zz_8 += (zz_7 >>> 32) + x_6 * x_2;
+ zz_9 += (zz_8 >>> 32) + x_6 * x_3;
+ zz_10 += (zz_9 >>> 32) + x_6 * x_4;
+ zz_11 += (zz_10 >>> 32) + x_6 * x_5;
+ zz_12 += zz_11 >>> 32;
+ }
+
+ w = (int)zz_7;
+ zz[7] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_8;
+ zz[8] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_9;
+ zz[9] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_10;
+ zz[10] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_11;
+ zz[11] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_12;
+ zz[12] = (w << 1) | c;
+ c = w >>> 31;
+ w = zz[13] + (int)(zz_12 >> 32);
+ zz[13] = (w << 1) | c;
+ }
+
+ public static void square(int[] x, int xOff, int[] zz, int zzOff)
+ {
+ long x_0 = x[xOff + 0] & M;
+ long zz_1;
+
+ int c = 0, w;
+ {
+ int i = 6, j = 14;
+ do
+ {
+ long xVal = (x[xOff + i--] & M);
+ long p = xVal * xVal;
+ zz[zzOff + --j] = (c << 31) | (int)(p >>> 33);
+ zz[zzOff + --j] = (int)(p >>> 1);
+ c = (int)p;
+ }
+ while (i > 0);
+
+ {
+ long p = x_0 * x_0;
+ zz_1 = ((c << 31) & M) | (p >>> 33);
+ zz[zzOff + 0] = (int)p;
+ c = (int)(p >>> 32) & 1;
+ }
+ }
+
+ long x_1 = x[xOff + 1] & M;
+ long zz_2 = zz[zzOff + 2] & M;
+
+ {
+ zz_1 += x_1 * x_0;
+ w = (int)zz_1;
+ zz[zzOff + 1] = (w << 1) | c;
+ c = w >>> 31;
+ zz_2 += zz_1 >>> 32;
+ }
+
+ long x_2 = x[xOff + 2] & M;
+ long zz_3 = zz[zzOff + 3] & M;
+ long zz_4 = zz[zzOff + 4] & M;
+ {
+ zz_2 += x_2 * x_0;
+ w = (int)zz_2;
+ zz[zzOff + 2] = (w << 1) | c;
+ c = w >>> 31;
+ zz_3 += (zz_2 >>> 32) + x_2 * x_1;
+ zz_4 += zz_3 >>> 32;
+ zz_3 &= M;
+ }
+
+ long x_3 = x[xOff + 3] & M;
+ long zz_5 = zz[zzOff + 5] & M;
+ long zz_6 = zz[zzOff + 6] & M;
+ {
+ zz_3 += x_3 * x_0;
+ w = (int)zz_3;
+ zz[zzOff + 3] = (w << 1) | c;
+ c = w >>> 31;
+ zz_4 += (zz_3 >>> 32) + x_3 * x_1;
+ zz_5 += (zz_4 >>> 32) + x_3 * x_2;
+ zz_4 &= M;
+ zz_6 += zz_5 >>> 32;
+ zz_5 &= M;
+ }
+
+ long x_4 = x[xOff + 4] & M;
+ long zz_7 = zz[zzOff + 7] & M;
+ long zz_8 = zz[zzOff + 8] & M;
+ {
+ zz_4 += x_4 * x_0;
+ w = (int)zz_4;
+ zz[zzOff + 4] = (w << 1) | c;
+ c = w >>> 31;
+ zz_5 += (zz_4 >>> 32) + x_4 * x_1;
+ zz_6 += (zz_5 >>> 32) + x_4 * x_2;
+ zz_5 &= M;
+ zz_7 += (zz_6 >>> 32) + x_4 * x_3;
+ zz_6 &= M;
+ zz_8 += zz_7 >>> 32;
+ zz_7 &= M;
+ }
+
+ long x_5 = x[xOff + 5] & M;
+ long zz_9 = zz[zzOff + 9] & M;
+ long zz_10 = zz[zzOff + 10] & M;
+ {
+ zz_5 += x_5 * x_0;
+ w = (int)zz_5;
+ zz[zzOff + 5] = (w << 1) | c;
+ c = w >>> 31;
+ zz_6 += (zz_5 >>> 32) + x_5 * x_1;
+ zz_7 += (zz_6 >>> 32) + x_5 * x_2;
+ zz_6 &= M;
+ zz_8 += (zz_7 >>> 32) + x_5 * x_3;
+ zz_7 &= M;
+ zz_9 += (zz_8 >>> 32) + x_5 * x_4;
+ zz_8 &= M;
+ zz_10 += zz_9 >>> 32;
+ zz_9 &= M;
+ }
+
+ long x_6 = x[xOff + 6] & M;
+ long zz_11 = zz[zzOff + 11] & M;
+ long zz_12 = zz[zzOff + 12] & M;
+ {
+ zz_6 += x_6 * x_0;
+ w = (int)zz_6;
+ zz[zzOff + 6] = (w << 1) | c;
+ c = w >>> 31;
+ zz_7 += (zz_6 >>> 32) + x_6 * x_1;
+ zz_8 += (zz_7 >>> 32) + x_6 * x_2;
+ zz_9 += (zz_8 >>> 32) + x_6 * x_3;
+ zz_10 += (zz_9 >>> 32) + x_6 * x_4;
+ zz_11 += (zz_10 >>> 32) + x_6 * x_5;
+ zz_12 += zz_11 >>> 32;
+ }
+
+ w = (int)zz_7;
+ zz[zzOff + 7] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_8;
+ zz[zzOff + 8] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_9;
+ zz[zzOff + 9] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_10;
+ zz[zzOff + 10] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_11;
+ zz[zzOff + 11] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_12;
+ zz[zzOff + 12] = (w << 1) | c;
+ c = w >>> 31;
+ w = zz[zzOff + 13] + (int)(zz_12 >> 32);
+ zz[zzOff + 13] = (w << 1) | c;
+ }
+
+ public static int sub(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) - (y[0] & M);
+ z[0] = (int)c;
+ c >>= 32;
+ c += (x[1] & M) - (y[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (x[2] & M) - (y[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ c += (x[3] & M) - (y[3] & M);
+ z[3] = (int)c;
+ c >>= 32;
+ c += (x[4] & M) - (y[4] & M);
+ z[4] = (int)c;
+ c >>= 32;
+ c += (x[5] & M) - (y[5] & M);
+ z[5] = (int)c;
+ c >>= 32;
+ c += (x[6] & M) - (y[6] & M);
+ z[6] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int sub(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0;
+ c += (x[xOff + 0] & M) - (y[yOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 1] & M) - (y[yOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 2] & M) - (y[yOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 3] & M) - (y[yOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 4] & M) - (y[yOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 5] & M) - (y[yOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 6] & M) - (y[yOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int subBothFrom(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (z[0] & M) - (x[0] & M) - (y[0] & M);
+ z[0] = (int)c;
+ c >>= 32;
+ c += (z[1] & M) - (x[1] & M) - (y[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (z[2] & M) - (x[2] & M) - (y[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ c += (z[3] & M) - (x[3] & M) - (y[3] & M);
+ z[3] = (int)c;
+ c >>= 32;
+ c += (z[4] & M) - (x[4] & M) - (y[4] & M);
+ z[4] = (int)c;
+ c >>= 32;
+ c += (z[5] & M) - (x[5] & M) - (y[5] & M);
+ z[5] = (int)c;
+ c >>= 32;
+ c += (z[6] & M) - (x[6] & M) - (y[6] & M);
+ z[6] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int subFrom(int[] x, int[] z)
+ {
+ long c = 0;
+ c += (z[0] & M) - (x[0] & M);
+ z[0] = (int)c;
+ c >>= 32;
+ c += (z[1] & M) - (x[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (z[2] & M) - (x[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ c += (z[3] & M) - (x[3] & M);
+ z[3] = (int)c;
+ c >>= 32;
+ c += (z[4] & M) - (x[4] & M);
+ z[4] = (int)c;
+ c >>= 32;
+ c += (z[5] & M) - (x[5] & M);
+ z[5] = (int)c;
+ c >>= 32;
+ c += (z[6] & M) - (x[6] & M);
+ z[6] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int subFrom(int[] x, int xOff, int[] z, int zOff)
+ {
+ long c = 0;
+ c += (z[zOff + 0] & M) - (x[xOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 1] & M) - (x[xOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 2] & M) - (x[xOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 3] & M) - (x[xOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 4] & M) - (x[xOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 5] & M) - (x[xOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 6] & M) - (x[xOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static BigInteger toBigInteger(int[] x)
+ {
+ byte[] bs = new byte[28];
+ for (int i = 0; i < 7; ++i)
+ {
+ int x_i = x[i];
+ if (x_i != 0)
+ {
+ Pack.intToBigEndian(x_i, bs, (6 - i) << 2);
+ }
+ }
+ return new BigInteger(1, bs);
+ }
+
+ public static void zero(int[] z)
+ {
+ z[0] = 0;
+ z[1] = 0;
+ z[2] = 0;
+ z[3] = 0;
+ z[4] = 0;
+ z[5] = 0;
+ z[6] = 0;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/raw/Nat256.java b/core/src/main/java/org/spongycastle/math/raw/Nat256.java
new file mode 100644
index 00000000..3cbf1ae7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/raw/Nat256.java
@@ -0,0 +1,1306 @@
+package org.spongycastle.math.raw;
+
+import java.math.BigInteger;
+
+import org.spongycastle.util.Pack;
+
+public abstract class Nat256
+{
+ private static final long M = 0xFFFFFFFFL;
+
+ public static int add(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) + (y[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += (x[1] & M) + (y[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += (x[2] & M) + (y[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += (x[3] & M) + (y[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += (x[4] & M) + (y[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += (x[5] & M) + (y[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ c += (x[6] & M) + (y[6] & M);
+ z[6] = (int)c;
+ c >>>= 32;
+ c += (x[7] & M) + (y[7] & M);
+ z[7] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int add(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0;
+ c += (x[xOff + 0] & M) + (y[yOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 1] & M) + (y[yOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 2] & M) + (y[yOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 3] & M) + (y[yOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 4] & M) + (y[yOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 5] & M) + (y[yOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 6] & M) + (y[yOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 7] & M) + (y[yOff + 7] & M);
+ z[zOff + 7] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addBothTo(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) + (y[0] & M) + (z[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += (x[1] & M) + (y[1] & M) + (z[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += (x[2] & M) + (y[2] & M) + (z[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += (x[3] & M) + (y[3] & M) + (z[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += (x[4] & M) + (y[4] & M) + (z[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += (x[5] & M) + (y[5] & M) + (z[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ c += (x[6] & M) + (y[6] & M) + (z[6] & M);
+ z[6] = (int)c;
+ c >>>= 32;
+ c += (x[7] & M) + (y[7] & M) + (z[7] & M);
+ z[7] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addBothTo(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0;
+ c += (x[xOff + 0] & M) + (y[yOff + 0] & M) + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 1] & M) + (y[yOff + 1] & M) + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 2] & M) + (y[yOff + 2] & M) + (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 3] & M) + (y[yOff + 3] & M) + (z[zOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 4] & M) + (y[yOff + 4] & M) + (z[zOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 5] & M) + (y[yOff + 5] & M) + (z[zOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 6] & M) + (y[yOff + 6] & M) + (z[zOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 7] & M) + (y[yOff + 7] & M) + (z[zOff + 7] & M);
+ z[zOff + 7] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addTo(int[] x, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) + (z[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += (x[1] & M) + (z[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += (x[2] & M) + (z[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += (x[3] & M) + (z[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += (x[4] & M) + (z[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += (x[5] & M) + (z[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ c += (x[6] & M) + (z[6] & M);
+ z[6] = (int)c;
+ c >>>= 32;
+ c += (x[7] & M) + (z[7] & M);
+ z[7] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addTo(int[] x, int xOff, int[] z, int zOff, int cIn)
+ {
+ long c = cIn & M;
+ c += (x[xOff + 0] & M) + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 1] & M) + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 2] & M) + (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 3] & M) + (z[zOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 4] & M) + (z[zOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 5] & M) + (z[zOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 6] & M) + (z[zOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 7] & M) + (z[zOff + 7] & M);
+ z[zOff + 7] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addToEachOther(int[] u, int uOff, int[] v, int vOff)
+ {
+ long c = 0;
+ c += (u[uOff + 0] & M) + (v[vOff + 0] & M);
+ u[uOff + 0] = (int)c;
+ v[vOff + 0] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 1] & M) + (v[vOff + 1] & M);
+ u[uOff + 1] = (int)c;
+ v[vOff + 1] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 2] & M) + (v[vOff + 2] & M);
+ u[uOff + 2] = (int)c;
+ v[vOff + 2] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 3] & M) + (v[vOff + 3] & M);
+ u[uOff + 3] = (int)c;
+ v[vOff + 3] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 4] & M) + (v[vOff + 4] & M);
+ u[uOff + 4] = (int)c;
+ v[vOff + 4] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 5] & M) + (v[vOff + 5] & M);
+ u[uOff + 5] = (int)c;
+ v[vOff + 5] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 6] & M) + (v[vOff + 6] & M);
+ u[uOff + 6] = (int)c;
+ v[vOff + 6] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 7] & M) + (v[vOff + 7] & M);
+ u[uOff + 7] = (int)c;
+ v[vOff + 7] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static void copy(int[] x, int[] z)
+ {
+ z[0] = x[0];
+ z[1] = x[1];
+ z[2] = x[2];
+ z[3] = x[3];
+ z[4] = x[4];
+ z[5] = x[5];
+ z[6] = x[6];
+ z[7] = x[7];
+ }
+
+ public static int[] create()
+ {
+ return new int[8];
+ }
+
+ public static int[] createExt()
+ {
+ return new int[16];
+ }
+
+ public static boolean diff(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ boolean pos = gte(x, xOff, y, yOff);
+ if (pos)
+ {
+ sub(x, xOff, y, yOff, z, zOff);
+ }
+ else
+ {
+ sub(y, yOff, x, xOff, z, zOff);
+ }
+ return pos;
+ }
+
+ public static boolean eq(int[] x, int[] y)
+ {
+ for (int i = 7; i >= 0; --i)
+ {
+ if (x[i] != y[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static int[] fromBigInteger(BigInteger x)
+ {
+ if (x.signum() < 0 || x.bitLength() > 256)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ int[] z = create();
+ int i = 0;
+ while (x.signum() != 0)
+ {
+ z[i++] = x.intValue();
+ x = x.shiftRight(32);
+ }
+ return z;
+ }
+
+ public static int getBit(int[] x, int bit)
+ {
+ if (bit == 0)
+ {
+ return x[0] & 1;
+ }
+ if ((bit & 255) != bit)
+ {
+ return 0;
+ }
+ int w = bit >>> 5;
+ int b = bit & 31;
+ return (x[w] >>> b) & 1;
+ }
+
+ public static boolean gte(int[] x, int[] y)
+ {
+ for (int i = 7; i >= 0; --i)
+ {
+ int x_i = x[i] ^ Integer.MIN_VALUE;
+ int y_i = y[i] ^ Integer.MIN_VALUE;
+ if (x_i < y_i)
+ return false;
+ if (x_i > y_i)
+ return true;
+ }
+ return true;
+ }
+
+ public static boolean gte(int[] x, int xOff, int[] y, int yOff)
+ {
+ for (int i = 7; i >= 0; --i)
+ {
+ int x_i = x[xOff + i] ^ Integer.MIN_VALUE;
+ int y_i = y[yOff + i] ^ Integer.MIN_VALUE;
+ if (x_i < y_i)
+ return false;
+ if (x_i > y_i)
+ return true;
+ }
+ return true;
+ }
+
+ public static boolean isOne(int[] x)
+ {
+ if (x[0] != 1)
+ {
+ return false;
+ }
+ for (int i = 1; i < 8; ++i)
+ {
+ if (x[i] != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static boolean isZero(int[] x)
+ {
+ for (int i = 0; i < 8; ++i)
+ {
+ if (x[i] != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static void mul(int[] x, int[] y, int[] zz)
+ {
+ long y_0 = y[0] & M;
+ long y_1 = y[1] & M;
+ long y_2 = y[2] & M;
+ long y_3 = y[3] & M;
+ long y_4 = y[4] & M;
+ long y_5 = y[5] & M;
+ long y_6 = y[6] & M;
+ long y_7 = y[7] & M;
+
+ {
+ long c = 0, x_0 = x[0] & M;
+ c += x_0 * y_0;
+ zz[0] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_1;
+ zz[1] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_2;
+ zz[2] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_3;
+ zz[3] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_4;
+ zz[4] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_5;
+ zz[5] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_6;
+ zz[6] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_7;
+ zz[7] = (int)c;
+ c >>>= 32;
+ zz[8] = (int)c;
+ }
+
+ for (int i = 1; i < 8; ++i)
+ {
+ long c = 0, x_i = x[i] & M;
+ c += x_i * y_0 + (zz[i + 0] & M);
+ zz[i + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[i + 1] & M);
+ zz[i + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[i + 2] & M);
+ zz[i + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[i + 3] & M);
+ zz[i + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[i + 4] & M);
+ zz[i + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[i + 5] & M);
+ zz[i + 5] = (int)c;
+ c >>>= 32;
+ c += x_i * y_6 + (zz[i + 6] & M);
+ zz[i + 6] = (int)c;
+ c >>>= 32;
+ c += x_i * y_7 + (zz[i + 7] & M);
+ zz[i + 7] = (int)c;
+ c >>>= 32;
+ zz[i + 8] = (int)c;
+ }
+ }
+
+ public static void mul(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
+ {
+ long y_0 = y[yOff + 0] & M;
+ long y_1 = y[yOff + 1] & M;
+ long y_2 = y[yOff + 2] & M;
+ long y_3 = y[yOff + 3] & M;
+ long y_4 = y[yOff + 4] & M;
+ long y_5 = y[yOff + 5] & M;
+ long y_6 = y[yOff + 6] & M;
+ long y_7 = y[yOff + 7] & M;
+
+ {
+ long c = 0, x_0 = x[xOff + 0] & M;
+ c += x_0 * y_0;
+ zz[zzOff + 0] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_1;
+ zz[zzOff + 1] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_2;
+ zz[zzOff + 2] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_3;
+ zz[zzOff + 3] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_4;
+ zz[zzOff + 4] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_5;
+ zz[zzOff + 5] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_6;
+ zz[zzOff + 6] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_7;
+ zz[zzOff + 7] = (int)c;
+ c >>>= 32;
+ zz[zzOff + 8] = (int)c;
+ }
+
+ for (int i = 1; i < 8; ++i)
+ {
+ ++zzOff;
+ long c = 0, x_i = x[xOff + i] & M;
+ c += x_i * y_0 + (zz[zzOff + 0] & M);
+ zz[zzOff + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[zzOff + 1] & M);
+ zz[zzOff + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[zzOff + 2] & M);
+ zz[zzOff + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[zzOff + 3] & M);
+ zz[zzOff + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[zzOff + 4] & M);
+ zz[zzOff + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[zzOff + 5] & M);
+ zz[zzOff + 5] = (int)c;
+ c >>>= 32;
+ c += x_i * y_6 + (zz[zzOff + 6] & M);
+ zz[zzOff + 6] = (int)c;
+ c >>>= 32;
+ c += x_i * y_7 + (zz[zzOff + 7] & M);
+ zz[zzOff + 7] = (int)c;
+ c >>>= 32;
+ zz[zzOff + 8] = (int)c;
+ }
+ }
+
+ public static int mulAddTo(int[] x, int[] y, int[] zz)
+ {
+ long y_0 = y[0] & M;
+ long y_1 = y[1] & M;
+ long y_2 = y[2] & M;
+ long y_3 = y[3] & M;
+ long y_4 = y[4] & M;
+ long y_5 = y[5] & M;
+ long y_6 = y[6] & M;
+ long y_7 = y[7] & M;
+
+ long zc = 0;
+ for (int i = 0; i < 8; ++i)
+ {
+ long c = 0, x_i = x[i] & M;
+ c += x_i * y_0 + (zz[i + 0] & M);
+ zz[i + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[i + 1] & M);
+ zz[i + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[i + 2] & M);
+ zz[i + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[i + 3] & M);
+ zz[i + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[i + 4] & M);
+ zz[i + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[i + 5] & M);
+ zz[i + 5] = (int)c;
+ c >>>= 32;
+ c += x_i * y_6 + (zz[i + 6] & M);
+ zz[i + 6] = (int)c;
+ c >>>= 32;
+ c += x_i * y_7 + (zz[i + 7] & M);
+ zz[i + 7] = (int)c;
+ c >>>= 32;
+ c += zc + (zz[i + 8] & M);
+ zz[i + 8] = (int)c;
+ zc = c >>> 32;
+ }
+ return (int)zc;
+ }
+
+ public static int mulAddTo(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
+ {
+ long y_0 = y[yOff + 0] & M;
+ long y_1 = y[yOff + 1] & M;
+ long y_2 = y[yOff + 2] & M;
+ long y_3 = y[yOff + 3] & M;
+ long y_4 = y[yOff + 4] & M;
+ long y_5 = y[yOff + 5] & M;
+ long y_6 = y[yOff + 6] & M;
+ long y_7 = y[yOff + 7] & M;
+
+ long zc = 0;
+ for (int i = 0; i < 8; ++i)
+ {
+ long c = 0, x_i = x[xOff + i] & M;
+ c += x_i * y_0 + (zz[zzOff + 0] & M);
+ zz[zzOff + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[zzOff + 1] & M);
+ zz[zzOff + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[zzOff + 2] & M);
+ zz[zzOff + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[zzOff + 3] & M);
+ zz[zzOff + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[zzOff + 4] & M);
+ zz[zzOff + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[zzOff + 5] & M);
+ zz[zzOff + 5] = (int)c;
+ c >>>= 32;
+ c += x_i * y_6 + (zz[zzOff + 6] & M);
+ zz[zzOff + 6] = (int)c;
+ c >>>= 32;
+ c += x_i * y_7 + (zz[zzOff + 7] & M);
+ zz[zzOff + 7] = (int)c;
+ c >>>= 32;
+ c += zc + (zz[zzOff + 8] & M);
+ zz[zzOff + 8] = (int)c;
+ zc = c >>> 32;
+ ++zzOff;
+ }
+ return (int)zc;
+ }
+
+ public static long mul33Add(int w, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ // assert w >>> 31 == 0;
+
+ long c = 0, wVal = w & M;
+ long x0 = x[xOff + 0] & M;
+ c += wVal * x0 + (y[yOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ long x1 = x[xOff + 1] & M;
+ c += wVal * x1 + x0 + (y[yOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ long x2 = x[xOff + 2] & M;
+ c += wVal * x2 + x1 + (y[yOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ long x3 = x[xOff + 3] & M;
+ c += wVal * x3 + x2 + (y[yOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ long x4 = x[xOff + 4] & M;
+ c += wVal * x4 + x3 + (y[yOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ long x5 = x[xOff + 5] & M;
+ c += wVal * x5 + x4 + (y[yOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ long x6 = x[xOff + 6] & M;
+ c += wVal * x6 + x5 + (y[yOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>>= 32;
+ long x7 = x[xOff + 7] & M;
+ c += wVal * x7 + x6 + (y[yOff + 7] & M);
+ z[zOff + 7] = (int)c;
+ c >>>= 32;
+ c += x7;
+ return c;
+ }
+
+ public static int mulByWord(int x, int[] z)
+ {
+ long c = 0, xVal = x & M;
+ c += xVal * (z[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[6] & M);
+ z[6] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[7] & M);
+ z[7] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int mulByWordAddTo(int x, int[] y, int[] z)
+ {
+ long c = 0, xVal = x & M;
+ c += xVal * (z[0] & M) + (y[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[1] & M) + (y[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[2] & M) + (y[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[3] & M) + (y[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[4] & M) + (y[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[5] & M) + (y[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[6] & M) + (y[6] & M);
+ z[6] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[7] & M) + (y[7] & M);
+ z[7] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int mulWordAddTo(int x, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0, xVal = x & M;
+ c += xVal * (y[yOff + 0] & M) + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 1] & M) + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 2] & M) + (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 3] & M) + (z[zOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 4] & M) + (z[zOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 5] & M) + (z[zOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 6] & M) + (z[zOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 7] & M) + (z[zOff + 7] & M);
+ z[zOff + 7] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int mul33DWordAdd(int x, long y, int[] z, int zOff)
+ {
+ // assert x >>> 31 == 0;
+ // assert zOff <= 4;
+
+ long c = 0, xVal = x & M;
+ long y00 = y & M;
+ c += xVal * y00 + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ long y01 = y >>> 32;
+ c += xVal * y01 + y00 + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += y01 + (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : Nat.incAt(8, z, zOff, 4);
+ }
+
+ public static int mul33WordAdd(int x, int y, int[] z, int zOff)
+ {
+ // assert x >>> 31 == 0;
+ // assert zOff <= 5;
+
+ long c = 0, xVal = x & M, yVal = y & M;
+ c += yVal * xVal + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += yVal + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : Nat.incAt(8, z, zOff, 3);
+ }
+
+ public static int mulWordDwordAdd(int x, long y, int[] z, int zOff)
+ {
+ // assert zOff <= 5;
+ long c = 0, xVal = x & M;
+ c += xVal * (y & M) + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += xVal * (y >>> 32) + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : Nat.incAt(8, z, zOff, 3);
+ }
+
+ public static int mulWord(int x, int[] y, int[] z, int zOff)
+ {
+ long c = 0, xVal = x & M;
+ int i = 0;
+ do
+ {
+ c += xVal * (y[i] & M);
+ z[zOff + i] = (int)c;
+ c >>>= 32;
+ }
+ while (++i < 8);
+ return (int)c;
+ }
+
+ public static void square(int[] x, int[] zz)
+ {
+ long x_0 = x[0] & M;
+ long zz_1;
+
+ int c = 0, w;
+ {
+ int i = 7, j = 16;
+ do
+ {
+ long xVal = (x[i--] & M);
+ long p = xVal * xVal;
+ zz[--j] = (c << 31) | (int)(p >>> 33);
+ zz[--j] = (int)(p >>> 1);
+ c = (int)p;
+ }
+ while (i > 0);
+
+ {
+ long p = x_0 * x_0;
+ zz_1 = ((c << 31) & M) | (p >>> 33);
+ zz[0] = (int)p;
+ c = (int)(p >>> 32) & 1;
+ }
+ }
+
+ long x_1 = x[1] & M;
+ long zz_2 = zz[2] & M;
+
+ {
+ zz_1 += x_1 * x_0;
+ w = (int)zz_1;
+ zz[1] = (w << 1) | c;
+ c = w >>> 31;
+ zz_2 += zz_1 >>> 32;
+ }
+
+ long x_2 = x[2] & M;
+ long zz_3 = zz[3] & M;
+ long zz_4 = zz[4] & M;
+ {
+ zz_2 += x_2 * x_0;
+ w = (int)zz_2;
+ zz[2] = (w << 1) | c;
+ c = w >>> 31;
+ zz_3 += (zz_2 >>> 32) + x_2 * x_1;
+ zz_4 += zz_3 >>> 32;
+ zz_3 &= M;
+ }
+
+ long x_3 = x[3] & M;
+ long zz_5 = zz[5] & M;
+ long zz_6 = zz[6] & M;
+ {
+ zz_3 += x_3 * x_0;
+ w = (int)zz_3;
+ zz[3] = (w << 1) | c;
+ c = w >>> 31;
+ zz_4 += (zz_3 >>> 32) + x_3 * x_1;
+ zz_5 += (zz_4 >>> 32) + x_3 * x_2;
+ zz_4 &= M;
+ zz_6 += zz_5 >>> 32;
+ zz_5 &= M;
+ }
+
+ long x_4 = x[4] & M;
+ long zz_7 = zz[7] & M;
+ long zz_8 = zz[8] & M;
+ {
+ zz_4 += x_4 * x_0;
+ w = (int)zz_4;
+ zz[4] = (w << 1) | c;
+ c = w >>> 31;
+ zz_5 += (zz_4 >>> 32) + x_4 * x_1;
+ zz_6 += (zz_5 >>> 32) + x_4 * x_2;
+ zz_5 &= M;
+ zz_7 += (zz_6 >>> 32) + x_4 * x_3;
+ zz_6 &= M;
+ zz_8 += zz_7 >>> 32;
+ zz_7 &= M;
+ }
+
+ long x_5 = x[5] & M;
+ long zz_9 = zz[9] & M;
+ long zz_10 = zz[10] & M;
+ {
+ zz_5 += x_5 * x_0;
+ w = (int)zz_5;
+ zz[5] = (w << 1) | c;
+ c = w >>> 31;
+ zz_6 += (zz_5 >>> 32) + x_5 * x_1;
+ zz_7 += (zz_6 >>> 32) + x_5 * x_2;
+ zz_6 &= M;
+ zz_8 += (zz_7 >>> 32) + x_5 * x_3;
+ zz_7 &= M;
+ zz_9 += (zz_8 >>> 32) + x_5 * x_4;
+ zz_8 &= M;
+ zz_10 += zz_9 >>> 32;
+ zz_9 &= M;
+ }
+
+ long x_6 = x[6] & M;
+ long zz_11 = zz[11] & M;
+ long zz_12 = zz[12] & M;
+ {
+ zz_6 += x_6 * x_0;
+ w = (int)zz_6;
+ zz[6] = (w << 1) | c;
+ c = w >>> 31;
+ zz_7 += (zz_6 >>> 32) + x_6 * x_1;
+ zz_8 += (zz_7 >>> 32) + x_6 * x_2;
+ zz_7 &= M;
+ zz_9 += (zz_8 >>> 32) + x_6 * x_3;
+ zz_8 &= M;
+ zz_10 += (zz_9 >>> 32) + x_6 * x_4;
+ zz_9 &= M;
+ zz_11 += (zz_10 >>> 32) + x_6 * x_5;
+ zz_10 &= M;
+ zz_12 += zz_11 >>> 32;
+ zz_11 &= M;
+ }
+
+ long x_7 = x[7] & M;
+ long zz_13 = zz[13] & M;
+ long zz_14 = zz[14] & M;
+ {
+ zz_7 += x_7 * x_0;
+ w = (int)zz_7;
+ zz[7] = (w << 1) | c;
+ c = w >>> 31;
+ zz_8 += (zz_7 >>> 32) + x_7 * x_1;
+ zz_9 += (zz_8 >>> 32) + x_7 * x_2;
+ zz_10 += (zz_9 >>> 32) + x_7 * x_3;
+ zz_11 += (zz_10 >>> 32) + x_7 * x_4;
+ zz_12 += (zz_11 >>> 32) + x_7 * x_5;
+ zz_13 += (zz_12 >>> 32) + x_7 * x_6;
+ zz_14 += zz_13 >>> 32;
+ }
+
+ w = (int)zz_8;
+ zz[8] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_9;
+ zz[9] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_10;
+ zz[10] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_11;
+ zz[11] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_12;
+ zz[12] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_13;
+ zz[13] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_14;
+ zz[14] = (w << 1) | c;
+ c = w >>> 31;
+ w = zz[15] + (int)(zz_14 >> 32);
+ zz[15] = (w << 1) | c;
+ }
+
+ public static void square(int[] x, int xOff, int[] zz, int zzOff)
+ {
+ long x_0 = x[xOff + 0] & M;
+ long zz_1;
+
+ int c = 0, w;
+ {
+ int i = 7, j = 16;
+ do
+ {
+ long xVal = (x[xOff + i--] & M);
+ long p = xVal * xVal;
+ zz[zzOff + --j] = (c << 31) | (int)(p >>> 33);
+ zz[zzOff + --j] = (int)(p >>> 1);
+ c = (int)p;
+ }
+ while (i > 0);
+
+ {
+ long p = x_0 * x_0;
+ zz_1 = ((c << 31) & M) | (p >>> 33);
+ zz[zzOff + 0] = (int)p;
+ c = (int)(p >>> 32) & 1;
+ }
+ }
+
+ long x_1 = x[xOff + 1] & M;
+ long zz_2 = zz[zzOff + 2] & M;
+
+ {
+ zz_1 += x_1 * x_0;
+ w = (int)zz_1;
+ zz[zzOff + 1] = (w << 1) | c;
+ c = w >>> 31;
+ zz_2 += zz_1 >>> 32;
+ }
+
+ long x_2 = x[xOff + 2] & M;
+ long zz_3 = zz[zzOff + 3] & M;
+ long zz_4 = zz[zzOff + 4] & M;
+ {
+ zz_2 += x_2 * x_0;
+ w = (int)zz_2;
+ zz[zzOff + 2] = (w << 1) | c;
+ c = w >>> 31;
+ zz_3 += (zz_2 >>> 32) + x_2 * x_1;
+ zz_4 += zz_3 >>> 32;
+ zz_3 &= M;
+ }
+
+ long x_3 = x[xOff + 3] & M;
+ long zz_5 = zz[zzOff + 5] & M;
+ long zz_6 = zz[zzOff + 6] & M;
+ {
+ zz_3 += x_3 * x_0;
+ w = (int)zz_3;
+ zz[zzOff + 3] = (w << 1) | c;
+ c = w >>> 31;
+ zz_4 += (zz_3 >>> 32) + x_3 * x_1;
+ zz_5 += (zz_4 >>> 32) + x_3 * x_2;
+ zz_4 &= M;
+ zz_6 += zz_5 >>> 32;
+ zz_5 &= M;
+ }
+
+ long x_4 = x[xOff + 4] & M;
+ long zz_7 = zz[zzOff + 7] & M;
+ long zz_8 = zz[zzOff + 8] & M;
+ {
+ zz_4 += x_4 * x_0;
+ w = (int)zz_4;
+ zz[zzOff + 4] = (w << 1) | c;
+ c = w >>> 31;
+ zz_5 += (zz_4 >>> 32) + x_4 * x_1;
+ zz_6 += (zz_5 >>> 32) + x_4 * x_2;
+ zz_5 &= M;
+ zz_7 += (zz_6 >>> 32) + x_4 * x_3;
+ zz_6 &= M;
+ zz_8 += zz_7 >>> 32;
+ zz_7 &= M;
+ }
+
+ long x_5 = x[xOff + 5] & M;
+ long zz_9 = zz[zzOff + 9] & M;
+ long zz_10 = zz[zzOff + 10] & M;
+ {
+ zz_5 += x_5 * x_0;
+ w = (int)zz_5;
+ zz[zzOff + 5] = (w << 1) | c;
+ c = w >>> 31;
+ zz_6 += (zz_5 >>> 32) + x_5 * x_1;
+ zz_7 += (zz_6 >>> 32) + x_5 * x_2;
+ zz_6 &= M;
+ zz_8 += (zz_7 >>> 32) + x_5 * x_3;
+ zz_7 &= M;
+ zz_9 += (zz_8 >>> 32) + x_5 * x_4;
+ zz_8 &= M;
+ zz_10 += zz_9 >>> 32;
+ zz_9 &= M;
+ }
+
+ long x_6 = x[xOff + 6] & M;
+ long zz_11 = zz[zzOff + 11] & M;
+ long zz_12 = zz[zzOff + 12] & M;
+ {
+ zz_6 += x_6 * x_0;
+ w = (int)zz_6;
+ zz[zzOff + 6] = (w << 1) | c;
+ c = w >>> 31;
+ zz_7 += (zz_6 >>> 32) + x_6 * x_1;
+ zz_8 += (zz_7 >>> 32) + x_6 * x_2;
+ zz_7 &= M;
+ zz_9 += (zz_8 >>> 32) + x_6 * x_3;
+ zz_8 &= M;
+ zz_10 += (zz_9 >>> 32) + x_6 * x_4;
+ zz_9 &= M;
+ zz_11 += (zz_10 >>> 32) + x_6 * x_5;
+ zz_10 &= M;
+ zz_12 += zz_11 >>> 32;
+ zz_11 &= M;
+ }
+
+ long x_7 = x[xOff + 7] & M;
+ long zz_13 = zz[zzOff + 13] & M;
+ long zz_14 = zz[zzOff + 14] & M;
+ {
+ zz_7 += x_7 * x_0;
+ w = (int)zz_7;
+ zz[zzOff + 7] = (w << 1) | c;
+ c = w >>> 31;
+ zz_8 += (zz_7 >>> 32) + x_7 * x_1;
+ zz_9 += (zz_8 >>> 32) + x_7 * x_2;
+ zz_10 += (zz_9 >>> 32) + x_7 * x_3;
+ zz_11 += (zz_10 >>> 32) + x_7 * x_4;
+ zz_12 += (zz_11 >>> 32) + x_7 * x_5;
+ zz_13 += (zz_12 >>> 32) + x_7 * x_6;
+ zz_14 += zz_13 >>> 32;
+ }
+
+ w = (int)zz_8;
+ zz[zzOff + 8] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_9;
+ zz[zzOff + 9] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_10;
+ zz[zzOff + 10] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_11;
+ zz[zzOff + 11] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_12;
+ zz[zzOff + 12] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_13;
+ zz[zzOff + 13] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_14;
+ zz[zzOff + 14] = (w << 1) | c;
+ c = w >>> 31;
+ w = zz[zzOff + 15] + (int)(zz_14 >> 32);
+ zz[zzOff + 15] = (w << 1) | c;
+ }
+
+ public static int sub(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) - (y[0] & M);
+ z[0] = (int)c;
+ c >>= 32;
+ c += (x[1] & M) - (y[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (x[2] & M) - (y[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ c += (x[3] & M) - (y[3] & M);
+ z[3] = (int)c;
+ c >>= 32;
+ c += (x[4] & M) - (y[4] & M);
+ z[4] = (int)c;
+ c >>= 32;
+ c += (x[5] & M) - (y[5] & M);
+ z[5] = (int)c;
+ c >>= 32;
+ c += (x[6] & M) - (y[6] & M);
+ z[6] = (int)c;
+ c >>= 32;
+ c += (x[7] & M) - (y[7] & M);
+ z[7] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int sub(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0;
+ c += (x[xOff + 0] & M) - (y[yOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 1] & M) - (y[yOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 2] & M) - (y[yOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 3] & M) - (y[yOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 4] & M) - (y[yOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 5] & M) - (y[yOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 6] & M) - (y[yOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 7] & M) - (y[yOff + 7] & M);
+ z[zOff + 7] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int subBothFrom(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (z[0] & M) - (x[0] & M) - (y[0] & M);
+ z[0] = (int)c;
+ c >>= 32;
+ c += (z[1] & M) - (x[1] & M) - (y[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (z[2] & M) - (x[2] & M) - (y[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ c += (z[3] & M) - (x[3] & M) - (y[3] & M);
+ z[3] = (int)c;
+ c >>= 32;
+ c += (z[4] & M) - (x[4] & M) - (y[4] & M);
+ z[4] = (int)c;
+ c >>= 32;
+ c += (z[5] & M) - (x[5] & M) - (y[5] & M);
+ z[5] = (int)c;
+ c >>= 32;
+ c += (z[6] & M) - (x[6] & M) - (y[6] & M);
+ z[6] = (int)c;
+ c >>= 32;
+ c += (z[7] & M) - (x[7] & M) - (y[7] & M);
+ z[7] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int subFrom(int[] x, int[] z)
+ {
+ long c = 0;
+ c += (z[0] & M) - (x[0] & M);
+ z[0] = (int)c;
+ c >>= 32;
+ c += (z[1] & M) - (x[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (z[2] & M) - (x[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ c += (z[3] & M) - (x[3] & M);
+ z[3] = (int)c;
+ c >>= 32;
+ c += (z[4] & M) - (x[4] & M);
+ z[4] = (int)c;
+ c >>= 32;
+ c += (z[5] & M) - (x[5] & M);
+ z[5] = (int)c;
+ c >>= 32;
+ c += (z[6] & M) - (x[6] & M);
+ z[6] = (int)c;
+ c >>= 32;
+ c += (z[7] & M) - (x[7] & M);
+ z[7] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int subFrom(int[] x, int xOff, int[] z, int zOff)
+ {
+ long c = 0;
+ c += (z[zOff + 0] & M) - (x[xOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 1] & M) - (x[xOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 2] & M) - (x[xOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 3] & M) - (x[xOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 4] & M) - (x[xOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 5] & M) - (x[xOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 6] & M) - (x[xOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 7] & M) - (x[xOff + 7] & M);
+ z[zOff + 7] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static BigInteger toBigInteger(int[] x)
+ {
+ byte[] bs = new byte[32];
+ for (int i = 0; i < 8; ++i)
+ {
+ int x_i = x[i];
+ if (x_i != 0)
+ {
+ Pack.intToBigEndian(x_i, bs, (7 - i) << 2);
+ }
+ }
+ return new BigInteger(1, bs);
+ }
+
+ public static void zero(int[] z)
+ {
+ z[0] = 0;
+ z[1] = 0;
+ z[2] = 0;
+ z[3] = 0;
+ z[4] = 0;
+ z[5] = 0;
+ z[6] = 0;
+ z[7] = 0;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/raw/Nat384.java b/core/src/main/java/org/spongycastle/math/raw/Nat384.java
new file mode 100644
index 00000000..d5b4b23c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/raw/Nat384.java
@@ -0,0 +1,43 @@
+package org.spongycastle.math.raw;
+
+
+public abstract class Nat384
+{
+ public static void mul(int[] x, int[] y, int[] zz)
+ {
+ Nat192.mul(x, y, zz);
+ Nat192.mul(x, 6, y, 6, zz, 12);
+
+ int c18 = Nat192.addToEachOther(zz, 6, zz, 12);
+ int c12 = c18 + Nat192.addTo(zz, 0, zz, 6, 0);
+ c18 += Nat192.addTo(zz, 18, zz, 12, c12);
+
+ int[] dx = Nat192.create(), dy = Nat192.create();
+ boolean neg = Nat192.diff(x, 6, x, 0, dx, 0) != Nat192.diff(y, 6, y, 0, dy, 0);
+
+ int[] tt = Nat192.createExt();
+ Nat192.mul(dx, dy, tt);
+
+ c18 += neg ? Nat.addTo(12, tt, 0, zz, 6) : Nat.subFrom(12, tt, 0, zz, 6);
+ Nat.addWordAt(24, c18, zz, 18);
+ }
+
+ public static void square(int[] x, int[] zz)
+ {
+ Nat192.square(x, zz);
+ Nat192.square(x, 6, zz, 12);
+
+ int c18 = Nat192.addToEachOther(zz, 6, zz, 12);
+ int c12 = c18 + Nat192.addTo(zz, 0, zz, 6, 0);
+ c18 += Nat192.addTo(zz, 18, zz, 12, c12);
+
+ int[] dx = Nat192.create();
+ Nat192.diff(x, 6, x, 0, dx, 0);
+
+ int[] tt = Nat192.createExt();
+ Nat192.square(dx, tt);
+
+ c18 += Nat.subFrom(12, tt, 0, zz, 6);
+ Nat.addWordAt(24, c18, zz, 18);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/math/raw/Nat512.java b/core/src/main/java/org/spongycastle/math/raw/Nat512.java
new file mode 100644
index 00000000..1b32342b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/math/raw/Nat512.java
@@ -0,0 +1,43 @@
+package org.spongycastle.math.raw;
+
+
+public abstract class Nat512
+{
+ public static void mul(int[] x, int[] y, int[] zz)
+ {
+ Nat256.mul(x, y, zz);
+ Nat256.mul(x, 8, y, 8, zz, 16);
+
+ int c24 = Nat256.addToEachOther(zz, 8, zz, 16);
+ int c16 = c24 + Nat256.addTo(zz, 0, zz, 8, 0);
+ c24 += Nat256.addTo(zz, 24, zz, 16, c16);
+
+ int[] dx = Nat256.create(), dy = Nat256.create();
+ boolean neg = Nat256.diff(x, 8, x, 0, dx, 0) != Nat256.diff(y, 8, y, 0, dy, 0);
+
+ int[] tt = Nat256.createExt();
+ Nat256.mul(dx, dy, tt);
+
+ c24 += neg ? Nat.addTo(16, tt, 0, zz, 8) : Nat.subFrom(16, tt, 0, zz, 8);
+ Nat.addWordAt(32, c24, zz, 24);
+ }
+
+ public static void square(int[] x, int[] zz)
+ {
+ Nat256.square(x, zz);
+ Nat256.square(x, 8, zz, 16);
+
+ int c24 = Nat256.addToEachOther(zz, 8, zz, 16);
+ int c16 = c24 + Nat256.addTo(zz, 0, zz, 8, 0);
+ c24 += Nat256.addTo(zz, 24, zz, 16, c16);
+
+ int[] dx = Nat256.create();
+ Nat256.diff(x, 8, x, 0, dx, 0);
+
+ int[] tt = Nat256.createExt();
+ Nat256.square(dx, tt);
+
+ c24 += Nat.subFrom(16, tt, 0, zz, 8);
+ Nat.addWordAt(32, c24, zz, 24);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/asn1/GMSSPrivateKey.java b/core/src/main/java/org/spongycastle/pqc/asn1/GMSSPrivateKey.java
new file mode 100644
index 00000000..b56974ad
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/asn1/GMSSPrivateKey.java
@@ -0,0 +1,1312 @@
+package org.spongycastle.pqc.asn1;
+
+import java.math.BigInteger;
+import java.util.Vector;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.pqc.crypto.gmss.GMSSLeaf;
+import org.spongycastle.pqc.crypto.gmss.GMSSParameters;
+import org.spongycastle.pqc.crypto.gmss.GMSSRootCalc;
+import org.spongycastle.pqc.crypto.gmss.GMSSRootSig;
+import org.spongycastle.pqc.crypto.gmss.Treehash;
+
+public class GMSSPrivateKey
+ extends ASN1Object
+{
+ private ASN1Primitive primitive;
+
+ private GMSSPrivateKey(ASN1Sequence mtsPrivateKey)
+ {
+ // --- Decode <index>.
+ ASN1Sequence indexPart = (ASN1Sequence)mtsPrivateKey.getObjectAt(0);
+ int[] index = new int[indexPart.size()];
+ for (int i = 0; i < indexPart.size(); i++)
+ {
+ index[i] = checkBigIntegerInIntRange(indexPart.getObjectAt(i));
+ }
+
+ // --- Decode <curSeeds>.
+ ASN1Sequence curSeedsPart = (ASN1Sequence)mtsPrivateKey.getObjectAt(1);
+ byte[][] curSeeds = new byte[curSeedsPart.size()][];
+ for (int i = 0; i < curSeeds.length; i++)
+ {
+ curSeeds[i] = ((DEROctetString)curSeedsPart.getObjectAt(i)).getOctets();
+ }
+
+ // --- Decode <nextNextSeeds>.
+ ASN1Sequence nextNextSeedsPart = (ASN1Sequence)mtsPrivateKey.getObjectAt(2);
+ byte[][] nextNextSeeds = new byte[nextNextSeedsPart.size()][];
+ for (int i = 0; i < nextNextSeeds.length; i++)
+ {
+ nextNextSeeds[i] = ((DEROctetString)nextNextSeedsPart.getObjectAt(i)).getOctets();
+ }
+
+ // --- Decode <curAuth>.
+ ASN1Sequence curAuthPart0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(3);
+ ASN1Sequence curAuthPart1;
+
+ byte[][][] curAuth = new byte[curAuthPart0.size()][][];
+ for (int i = 0; i < curAuth.length; i++)
+ {
+ curAuthPart1 = (ASN1Sequence)curAuthPart0.getObjectAt(i);
+ curAuth[i] = new byte[curAuthPart1.size()][];
+ for (int j = 0; j < curAuth[i].length; j++)
+ {
+ curAuth[i][j] = ((DEROctetString)curAuthPart1.getObjectAt(j)).getOctets();
+ }
+ }
+
+ // --- Decode <nextAuth>.
+ ASN1Sequence nextAuthPart0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(4);
+ ASN1Sequence nextAuthPart1;
+
+ byte[][][] nextAuth = new byte[nextAuthPart0.size()][][];
+ for (int i = 0; i < nextAuth.length; i++)
+ {
+ nextAuthPart1 = (ASN1Sequence)nextAuthPart0.getObjectAt(i);
+ nextAuth[i] = new byte[nextAuthPart1.size()][];
+ for (int j = 0; j < nextAuth[i].length; j++)
+ {
+ nextAuth[i][j] = ((DEROctetString)nextAuthPart1.getObjectAt(j)).getOctets();
+ }
+ }
+
+ // --- Decode <curTreehash>.
+ ASN1Sequence seqOfcurTreehash0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(5);
+ ASN1Sequence seqOfcurTreehash1;
+ ASN1Sequence seqOfcurTreehashStat;
+ ASN1Sequence seqOfcurTreehashBytes;
+ ASN1Sequence seqOfcurTreehashInts;
+ ASN1Sequence seqOfcurTreehashString;
+
+ Treehash[][] curTreehash = new Treehash[seqOfcurTreehash0.size()][];
+ /*
+ for (int i = 0; i < curTreehash.length; i++)
+ {
+ seqOfcurTreehash1 = (ASN1Sequence)seqOfcurTreehash0.getObjectAt(i);
+ curTreehash[i] = new Treehash[seqOfcurTreehash1.size()];
+ for (int j = 0; j < curTreehash[i].length; j++)
+ {
+ seqOfcurTreehashStat = (ASN1Sequence)seqOfcurTreehash1.getObjectAt(j);
+ seqOfcurTreehashString = (ASN1Sequence)seqOfcurTreehashStat
+ .getObjectAt(0);
+ seqOfcurTreehashBytes = (ASN1Sequence)seqOfcurTreehashStat
+ .getObjectAt(1);
+ seqOfcurTreehashInts = (ASN1Sequence)seqOfcurTreehashStat
+ .getObjectAt(2);
+
+ String[] name = new String[2];
+ name[0] = ((DERIA5String)seqOfcurTreehashString.getObjectAt(0)).getString();
+ name[1] = ((DERIA5String)seqOfcurTreehashString.getObjectAt(1)).getString();
+
+ int tailLength = checkBigIntegerInIntRange(seqOfcurTreehashInts.getObjectAt(1));
+ byte[][] statByte = new byte[3 + tailLength][];
+ statByte[0] = ((DEROctetString)seqOfcurTreehashBytes.getObjectAt(0)).getOctets();
+
+ if (statByte[0].length == 0)
+ { // if null was encoded
+ statByte[0] = null;
+ }
+
+ statByte[1] = ((DEROctetString)seqOfcurTreehashBytes.getObjectAt(1)).getOctets();
+ statByte[2] = ((DEROctetString)seqOfcurTreehashBytes.getObjectAt(2)).getOctets();
+ for (int k = 0; k < tailLength; k++)
+ {
+ statByte[3 + k] = ((DEROctetString)seqOfcurTreehashBytes
+ .getObjectAt(3 + k)).getOctets();
+ }
+ int[] statInt = new int[6 + tailLength];
+ statInt[0] = checkBigIntegerInIntRange(seqOfcurTreehashInts.getObjectAt(0));
+ statInt[1] = tailLength;
+ statInt[2] = checkBigIntegerInIntRange(seqOfcurTreehashInts.getObjectAt(2));
+ statInt[3] = checkBigIntegerInIntRange(seqOfcurTreehashInts.getObjectAt(3));
+ statInt[4] = checkBigIntegerInIntRange(seqOfcurTreehashInts.getObjectAt(4));
+ statInt[5] = checkBigIntegerInIntRange(seqOfcurTreehashInts.getObjectAt(5));
+ for (int k = 0; k < tailLength; k++)
+ {
+ statInt[6 + k] = checkBigIntegerInIntRange(seqOfcurTreehashInts.getObjectAt(6 + k));
+ }
+
+ // TODO: Check if we can do better than throwing away name[1] !!!
+ curTreehash[i][j] = new Treehash(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt);
+ }
+ }
+
+
+ // --- Decode <nextTreehash>.
+ ASN1Sequence seqOfNextTreehash0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(6);
+ ASN1Sequence seqOfNextTreehash1;
+ ASN1Sequence seqOfNextTreehashStat;
+ ASN1Sequence seqOfNextTreehashBytes;
+ ASN1Sequence seqOfNextTreehashInts;
+ ASN1Sequence seqOfNextTreehashString;
+
+ Treehash[][] nextTreehash = new Treehash[seqOfNextTreehash0.size()][];
+
+ for (int i = 0; i < nextTreehash.length; i++)
+ {
+ seqOfNextTreehash1 = (ASN1Sequence)seqOfNextTreehash0.getObjectAt(i);
+ nextTreehash[i] = new Treehash[seqOfNextTreehash1.size()];
+ for (int j = 0; j < nextTreehash[i].length; j++)
+ {
+ seqOfNextTreehashStat = (ASN1Sequence)seqOfNextTreehash1
+ .getObjectAt(j);
+ seqOfNextTreehashString = (ASN1Sequence)seqOfNextTreehashStat
+ .getObjectAt(0);
+ seqOfNextTreehashBytes = (ASN1Sequence)seqOfNextTreehashStat
+ .getObjectAt(1);
+ seqOfNextTreehashInts = (ASN1Sequence)seqOfNextTreehashStat
+ .getObjectAt(2);
+
+ String[] name = new String[2];
+ name[0] = ((DERIA5String)seqOfNextTreehashString.getObjectAt(0))
+ .getString();
+ name[1] = ((DERIA5String)seqOfNextTreehashString.getObjectAt(1))
+ .getString();
+
+ int tailLength = checkBigIntegerInIntRange(seqOfNextTreehashInts.getObjectAt(1));
+
+ byte[][] statByte = new byte[3 + tailLength][];
+ statByte[0] = ((DEROctetString)seqOfNextTreehashBytes.getObjectAt(0)).getOctets();
+ if (statByte[0].length == 0)
+ { // if null was encoded
+ statByte[0] = null;
+ }
+
+ statByte[1] = ((DEROctetString)seqOfNextTreehashBytes.getObjectAt(1)).getOctets();
+ statByte[2] = ((DEROctetString)seqOfNextTreehashBytes.getObjectAt(2)).getOctets();
+ for (int k = 0; k < tailLength; k++)
+ {
+ statByte[3 + k] = ((DEROctetString)seqOfNextTreehashBytes
+ .getObjectAt(3 + k)).getOctets();
+ }
+ int[] statInt = new int[6 + tailLength];
+ statInt[0] = checkBigIntegerInIntRange(seqOfNextTreehashInts.getObjectAt(0));
+
+ statInt[1] = tailLength;
+ statInt[2] = checkBigIntegerInIntRange(seqOfNextTreehashInts.getObjectAt(2));
+
+ statInt[3] = checkBigIntegerInIntRange(seqOfNextTreehashInts.getObjectAt(3));
+
+ statInt[4] = checkBigIntegerInIntRange(seqOfNextTreehashInts.getObjectAt(4));
+
+ statInt[5] = checkBigIntegerInIntRange(seqOfNextTreehashInts.getObjectAt(5));
+
+ for (int k = 0; k < tailLength; k++)
+ {
+ statInt[6 + k] = checkBigIntegerInIntRange(seqOfNextTreehashInts.getObjectAt(6 + k));
+
+ }
+ nextTreehash[i][j] = new Treehash(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt);
+ }
+ }
+
+
+ // --- Decode <keep>.
+ ASN1Sequence keepPart0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(7);
+ ASN1Sequence keepPart1;
+
+ byte[][][] keep = new byte[keepPart0.size()][][];
+ for (int i = 0; i < keep.length; i++)
+ {
+ keepPart1 = (ASN1Sequence)keepPart0.getObjectAt(i);
+ keep[i] = new byte[keepPart1.size()][];
+ for (int j = 0; j < keep[i].length; j++)
+ {
+ keep[i][j] = ((DEROctetString)keepPart1.getObjectAt(j)).getOctets();
+ }
+ }
+
+ // --- Decode <curStack>.
+ ASN1Sequence curStackPart0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(8);
+ ASN1Sequence curStackPart1;
+
+ Vector[] curStack = new Vector[curStackPart0.size()];
+ for (int i = 0; i < curStack.length; i++)
+ {
+ curStackPart1 = (ASN1Sequence)curStackPart0.getObjectAt(i);
+ curStack[i] = new Vector();
+ for (int j = 0; j < curStackPart1.size(); j++)
+ {
+ curStack[i].addElement(((DEROctetString)curStackPart1.getObjectAt(j)).getOctets());
+ }
+ }
+
+ // --- Decode <nextStack>.
+ ASN1Sequence nextStackPart0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(9);
+ ASN1Sequence nextStackPart1;
+
+ Vector[] nextStack = new Vector[nextStackPart0.size()];
+ for (int i = 0; i < nextStack.length; i++)
+ {
+ nextStackPart1 = (ASN1Sequence)nextStackPart0.getObjectAt(i);
+ nextStack[i] = new Vector();
+ for (int j = 0; j < nextStackPart1.size(); j++)
+ {
+ nextStack[i].addElement(((DEROctetString)nextStackPart1
+ .getObjectAt(j)).getOctets());
+ }
+ }
+
+ // --- Decode <curRetain>.
+ ASN1Sequence curRetainPart0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(10);
+ ASN1Sequence curRetainPart1;
+ ASN1Sequence curRetainPart2;
+
+ Vector[][] curRetain = new Vector[curRetainPart0.size()][];
+ for (int i = 0; i < curRetain.length; i++)
+ {
+ curRetainPart1 = (ASN1Sequence)curRetainPart0.getObjectAt(i);
+ curRetain[i] = new Vector[curRetainPart1.size()];
+ for (int j = 0; j < curRetain[i].length; j++)
+ {
+ curRetainPart2 = (ASN1Sequence)curRetainPart1.getObjectAt(j);
+ curRetain[i][j] = new Vector();
+ for (int k = 0; k < curRetainPart2.size(); k++)
+ {
+ curRetain[i][j]
+ .addElement(((DEROctetString)curRetainPart2
+ .getObjectAt(k)).getOctets());
+ }
+ }
+ }
+
+ // --- Decode <nextRetain>.
+ ASN1Sequence nextRetainPart0 = (ASN1Sequence)mtsPrivateKey.getObjectAt(11);
+ ASN1Sequence nextRetainPart1;
+ ASN1Sequence nextRetainPart2;
+
+ Vector[][] nextRetain = new Vector[nextRetainPart0.size()][];
+ for (int i = 0; i < nextRetain.length; i++)
+ {
+ nextRetainPart1 = (ASN1Sequence)nextRetainPart0.getObjectAt(i);
+ nextRetain[i] = new Vector[nextRetainPart1.size()];
+ for (int j = 0; j < nextRetain[i].length; j++)
+ {
+ nextRetainPart2 = (ASN1Sequence)nextRetainPart1.getObjectAt(j);
+ nextRetain[i][j] = new Vector();
+ for (int k = 0; k < nextRetainPart2.size(); k++)
+ {
+ nextRetain[i][j]
+ .addElement(((DEROctetString)nextRetainPart2
+ .getObjectAt(k)).getOctets());
+ }
+ }
+ }
+
+ // --- Decode <nextNextLeaf>.
+ ASN1Sequence seqOfLeafs = (ASN1Sequence)mtsPrivateKey.getObjectAt(12);
+ ASN1Sequence seqOfLeafStat;
+ ASN1Sequence seqOfLeafBytes;
+ ASN1Sequence seqOfLeafInts;
+ ASN1Sequence seqOfLeafString;
+
+ GMSSLeaf[] nextNextLeaf = new GMSSLeaf[seqOfLeafs.size()];
+
+ for (int i = 0; i < nextNextLeaf.length; i++)
+ {
+ seqOfLeafStat = (ASN1Sequence)seqOfLeafs.getObjectAt(i);
+ // nextNextAuth[i]= new byte[nextNextAuthPart1.size()][];
+ seqOfLeafString = (ASN1Sequence)seqOfLeafStat.getObjectAt(0);
+ seqOfLeafBytes = (ASN1Sequence)seqOfLeafStat.getObjectAt(1);
+ seqOfLeafInts = (ASN1Sequence)seqOfLeafStat.getObjectAt(2);
+
+ String[] name = new String[2];
+ name[0] = ((DERIA5String)seqOfLeafString.getObjectAt(0)).getString();
+ name[1] = ((DERIA5String)seqOfLeafString.getObjectAt(1)).getString();
+ byte[][] statByte = new byte[4][];
+ statByte[0] = ((DEROctetString)seqOfLeafBytes.getObjectAt(0))
+ .getOctets();
+ statByte[1] = ((DEROctetString)seqOfLeafBytes.getObjectAt(1))
+ .getOctets();
+ statByte[2] = ((DEROctetString)seqOfLeafBytes.getObjectAt(2))
+ .getOctets();
+ statByte[3] = ((DEROctetString)seqOfLeafBytes.getObjectAt(3))
+ .getOctets();
+ int[] statInt = new int[4];
+ statInt[0] = checkBigIntegerInIntRange(seqOfLeafInts.getObjectAt(0));
+ statInt[1] = checkBigIntegerInIntRange(seqOfLeafInts.getObjectAt(1));
+ statInt[2] = checkBigIntegerInIntRange(seqOfLeafInts.getObjectAt(2));
+ statInt[3] = checkBigIntegerInIntRange(seqOfLeafInts.getObjectAt(3));
+ nextNextLeaf[i] = new GMSSLeaf(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt);
+ }
+
+ // --- Decode <upperLeaf>.
+ ASN1Sequence seqOfUpperLeafs = (ASN1Sequence)mtsPrivateKey.getObjectAt(13);
+ ASN1Sequence seqOfUpperLeafStat;
+ ASN1Sequence seqOfUpperLeafBytes;
+ ASN1Sequence seqOfUpperLeafInts;
+ ASN1Sequence seqOfUpperLeafString;
+
+ GMSSLeaf[] upperLeaf = new GMSSLeaf[seqOfUpperLeafs.size()];
+
+ for (int i = 0; i < upperLeaf.length; i++)
+ {
+ seqOfUpperLeafStat = (ASN1Sequence)seqOfUpperLeafs.getObjectAt(i);
+ seqOfUpperLeafString = (ASN1Sequence)seqOfUpperLeafStat.getObjectAt(0);
+ seqOfUpperLeafBytes = (ASN1Sequence)seqOfUpperLeafStat.getObjectAt(1);
+ seqOfUpperLeafInts = (ASN1Sequence)seqOfUpperLeafStat.getObjectAt(2);
+
+ String[] name = new String[2];
+ name[0] = ((DERIA5String)seqOfUpperLeafString.getObjectAt(0)).getString();
+ name[1] = ((DERIA5String)seqOfUpperLeafString.getObjectAt(1)).getString();
+ byte[][] statByte = new byte[4][];
+ statByte[0] = ((DEROctetString)seqOfUpperLeafBytes.getObjectAt(0))
+ .getOctets();
+ statByte[1] = ((DEROctetString)seqOfUpperLeafBytes.getObjectAt(1))
+ .getOctets();
+ statByte[2] = ((DEROctetString)seqOfUpperLeafBytes.getObjectAt(2))
+ .getOctets();
+ statByte[3] = ((DEROctetString)seqOfUpperLeafBytes.getObjectAt(3))
+ .getOctets();
+ int[] statInt = new int[4];
+ statInt[0] = checkBigIntegerInIntRange(seqOfUpperLeafInts.getObjectAt(0));
+ statInt[1] = checkBigIntegerInIntRange(seqOfUpperLeafInts.getObjectAt(1));
+ statInt[2] = checkBigIntegerInIntRange(seqOfUpperLeafInts.getObjectAt(2));
+ statInt[3] = checkBigIntegerInIntRange(seqOfUpperLeafInts.getObjectAt(3));
+ upperLeaf[i] = new GMSSLeaf(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt);
+ }
+
+ // --- Decode <upperTreehashLeaf>.
+ ASN1Sequence seqOfUpperTHLeafs = (ASN1Sequence)mtsPrivateKey.getObjectAt(14);
+ ASN1Sequence seqOfUpperTHLeafStat;
+ ASN1Sequence seqOfUpperTHLeafBytes;
+ ASN1Sequence seqOfUpperTHLeafInts;
+ ASN1Sequence seqOfUpperTHLeafString;
+
+ GMSSLeaf[] upperTHLeaf = new GMSSLeaf[seqOfUpperTHLeafs.size()];
+
+ for (int i = 0; i < upperTHLeaf.length; i++)
+ {
+ seqOfUpperTHLeafStat = (ASN1Sequence)seqOfUpperTHLeafs.getObjectAt(i);
+ seqOfUpperTHLeafString = (ASN1Sequence)seqOfUpperTHLeafStat.getObjectAt(0);
+ seqOfUpperTHLeafBytes = (ASN1Sequence)seqOfUpperTHLeafStat.getObjectAt(1);
+ seqOfUpperTHLeafInts = (ASN1Sequence)seqOfUpperTHLeafStat.getObjectAt(2);
+
+ String[] name = new String[2];
+ name[0] = ((DERIA5String)seqOfUpperTHLeafString.getObjectAt(0))
+ .getString();
+ name[1] = ((DERIA5String)seqOfUpperTHLeafString.getObjectAt(1))
+ .getString();
+ byte[][] statByte = new byte[4][];
+ statByte[0] = ((DEROctetString)seqOfUpperTHLeafBytes.getObjectAt(0))
+ .getOctets();
+ statByte[1] = ((DEROctetString)seqOfUpperTHLeafBytes.getObjectAt(1))
+ .getOctets();
+ statByte[2] = ((DEROctetString)seqOfUpperTHLeafBytes.getObjectAt(2))
+ .getOctets();
+ statByte[3] = ((DEROctetString)seqOfUpperTHLeafBytes.getObjectAt(3))
+ .getOctets();
+ int[] statInt = new int[4];
+ statInt[0] = checkBigIntegerInIntRange(seqOfUpperTHLeafInts.getObjectAt(0));
+ statInt[1] = checkBigIntegerInIntRange(seqOfUpperTHLeafInts.getObjectAt(1));
+ statInt[2] = checkBigIntegerInIntRange(seqOfUpperTHLeafInts.getObjectAt(2));
+ statInt[3] = checkBigIntegerInIntRange(seqOfUpperTHLeafInts.getObjectAt(3));
+ upperTHLeaf[i] = new GMSSLeaf(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt);
+ }
+
+ // --- Decode <minTreehash>.
+ ASN1Sequence minTreehashPart = (ASN1Sequence)mtsPrivateKey.getObjectAt(15);
+ int[] minTreehash = new int[minTreehashPart.size()];
+ for (int i = 0; i < minTreehashPart.size(); i++)
+ {
+ minTreehash[i] = checkBigIntegerInIntRange(minTreehashPart.getObjectAt(i));
+ }
+
+ // --- Decode <nextRoot>.
+ ASN1Sequence seqOfnextRoots = (ASN1Sequence)mtsPrivateKey.getObjectAt(16);
+ byte[][] nextRoot = new byte[seqOfnextRoots.size()][];
+ for (int i = 0; i < nextRoot.length; i++)
+ {
+ nextRoot[i] = ((DEROctetString)seqOfnextRoots.getObjectAt(i))
+ .getOctets();
+ }
+
+ // --- Decode <nextNextRoot>.
+ ASN1Sequence seqOfnextNextRoot = (ASN1Sequence)mtsPrivateKey.getObjectAt(17);
+ ASN1Sequence seqOfnextNextRootStat;
+ ASN1Sequence seqOfnextNextRootBytes;
+ ASN1Sequence seqOfnextNextRootInts;
+ ASN1Sequence seqOfnextNextRootString;
+ ASN1Sequence seqOfnextNextRootTreeH;
+ ASN1Sequence seqOfnextNextRootRetain;
+
+ GMSSRootCalc[] nextNextRoot = new GMSSRootCalc[seqOfnextNextRoot.size()];
+
+ for (int i = 0; i < nextNextRoot.length; i++)
+ {
+ seqOfnextNextRootStat = (ASN1Sequence)seqOfnextNextRoot.getObjectAt(i);
+ seqOfnextNextRootString = (ASN1Sequence)seqOfnextNextRootStat
+ .getObjectAt(0);
+ seqOfnextNextRootBytes = (ASN1Sequence)seqOfnextNextRootStat
+ .getObjectAt(1);
+ seqOfnextNextRootInts = (ASN1Sequence)seqOfnextNextRootStat.getObjectAt(2);
+ seqOfnextNextRootTreeH = (ASN1Sequence)seqOfnextNextRootStat
+ .getObjectAt(3);
+ seqOfnextNextRootRetain = (ASN1Sequence)seqOfnextNextRootStat
+ .getObjectAt(4);
+
+ // decode treehash of nextNextRoot
+ // ---------------------------------
+ ASN1Sequence seqOfnextNextRootTreeHStat;
+ ASN1Sequence seqOfnextNextRootTreeHBytes;
+ ASN1Sequence seqOfnextNextRootTreeHInts;
+ ASN1Sequence seqOfnextNextRootTreeHString;
+
+ Treehash[] nnRTreehash = new Treehash[seqOfnextNextRootTreeH.size()];
+
+ for (int k = 0; k < nnRTreehash.length; k++)
+ {
+ seqOfnextNextRootTreeHStat = (ASN1Sequence)seqOfnextNextRootTreeH
+ .getObjectAt(k);
+ seqOfnextNextRootTreeHString = (ASN1Sequence)seqOfnextNextRootTreeHStat
+ .getObjectAt(0);
+ seqOfnextNextRootTreeHBytes = (ASN1Sequence)seqOfnextNextRootTreeHStat
+ .getObjectAt(1);
+ seqOfnextNextRootTreeHInts = (ASN1Sequence)seqOfnextNextRootTreeHStat
+ .getObjectAt(2);
+
+ String[] name = new String[2];
+ name[0] = ((DERIA5String)seqOfnextNextRootTreeHString.getObjectAt(0))
+ .getString();
+ name[1] = ((DERIA5String)seqOfnextNextRootTreeHString.getObjectAt(1))
+ .getString();
+
+ int tailLength = checkBigIntegerInIntRange(seqOfnextNextRootTreeHInts.getObjectAt(1));
+
+ byte[][] statByte = new byte[3 + tailLength][];
+ statByte[0] = ((DEROctetString)seqOfnextNextRootTreeHBytes
+ .getObjectAt(0)).getOctets();
+ if (statByte[0].length == 0)
+ { // if null was encoded
+ statByte[0] = null;
+ }
+
+ statByte[1] = ((DEROctetString)seqOfnextNextRootTreeHBytes
+ .getObjectAt(1)).getOctets();
+ statByte[2] = ((DEROctetString)seqOfnextNextRootTreeHBytes
+ .getObjectAt(2)).getOctets();
+ for (int j = 0; j < tailLength; j++)
+ {
+ statByte[3 + j] = ((DEROctetString)seqOfnextNextRootTreeHBytes
+ .getObjectAt(3 + j)).getOctets();
+ }
+ int[] statInt = new int[6 + tailLength];
+ statInt[0] = checkBigIntegerInIntRange(seqOfnextNextRootTreeHInts.getObjectAt(0));
+
+ statInt[1] = tailLength;
+ statInt[2] = checkBigIntegerInIntRange(seqOfnextNextRootTreeHInts.getObjectAt(2));
+
+ statInt[3] = checkBigIntegerInIntRange(seqOfnextNextRootTreeHInts.getObjectAt(3));
+
+ statInt[4] = checkBigIntegerInIntRange(seqOfnextNextRootTreeHInts.getObjectAt(4));
+
+ statInt[5] = checkBigIntegerInIntRange(seqOfnextNextRootTreeHInts.getObjectAt(5));
+
+ for (int j = 0; j < tailLength; j++)
+ {
+ statInt[6 + j] = checkBigIntegerInIntRange(seqOfnextNextRootTreeHInts
+ .getObjectAt(6 + j));
+ }
+ nnRTreehash[k] = new Treehash(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt);
+ }
+ // ---------------------------------
+
+ // decode retain of nextNextRoot
+ // ---------------------------------
+ // ASN1Sequence seqOfnextNextRootRetainPart0 =
+ // (ASN1Sequence)seqOfnextNextRootRetain.get(0);
+ ASN1Sequence seqOfnextNextRootRetainPart1;
+
+ Vector[] nnRRetain = new Vector[seqOfnextNextRootRetain.size()];
+ for (int j = 0; j < nnRRetain.length; j++)
+ {
+ seqOfnextNextRootRetainPart1 = (ASN1Sequence)seqOfnextNextRootRetain
+ .getObjectAt(j);
+ nnRRetain[j] = new Vector();
+ for (int k = 0; k < seqOfnextNextRootRetainPart1.size(); k++)
+ {
+ nnRRetain[j]
+ .addElement(((DEROctetString)seqOfnextNextRootRetainPart1
+ .getObjectAt(k)).getOctets());
+ }
+ }
+ // ---------------------------------
+
+ String[] name = new String[2];
+ name[0] = ((DERIA5String)seqOfnextNextRootString.getObjectAt(0))
+ .getString();
+ name[1] = ((DERIA5String)seqOfnextNextRootString.getObjectAt(1))
+ .getString();
+
+ int heightOfTree = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(0));
+ int tailLength = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(7));
+ byte[][] statByte = new byte[1 + heightOfTree + tailLength][];
+ statByte[0] = ((DEROctetString)seqOfnextNextRootBytes.getObjectAt(0))
+ .getOctets();
+ for (int j = 0; j < heightOfTree; j++)
+ {
+ statByte[1 + j] = ((DEROctetString)seqOfnextNextRootBytes
+ .getObjectAt(1 + j)).getOctets();
+ }
+ for (int j = 0; j < tailLength; j++)
+ {
+ statByte[1 + heightOfTree + j] = ((DEROctetString)seqOfnextNextRootBytes
+ .getObjectAt(1 + heightOfTree + j)).getOctets();
+ }
+ int[] statInt = new int[8 + heightOfTree + tailLength];
+ statInt[0] = heightOfTree;
+ statInt[1] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(1));
+ statInt[2] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(2));
+ statInt[3] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(3));
+ statInt[4] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(4));
+ statInt[5] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(5));
+ statInt[6] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(6));
+ statInt[7] = tailLength;
+ for (int j = 0; j < heightOfTree; j++)
+ {
+ statInt[8 + j] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(8 + j));
+ }
+ for (int j = 0; j < tailLength; j++)
+ {
+ statInt[8 + heightOfTree + j] = checkBigIntegerInIntRange(seqOfnextNextRootInts.getObjectAt(8
+ + heightOfTree + j));
+ }
+ nextNextRoot[i] = new GMSSRootCalc(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt,
+ nnRTreehash, nnRRetain);
+ }
+
+ // --- Decode <curRootSig>.
+ ASN1Sequence seqOfcurRootSig = (ASN1Sequence)mtsPrivateKey.getObjectAt(18);
+ byte[][] curRootSig = new byte[seqOfcurRootSig.size()][];
+ for (int i = 0; i < curRootSig.length; i++)
+ {
+ curRootSig[i] = ((DEROctetString)seqOfcurRootSig.getObjectAt(i))
+ .getOctets();
+ }
+
+ // --- Decode <nextRootSig>.
+ ASN1Sequence seqOfnextRootSigs = (ASN1Sequence)mtsPrivateKey.getObjectAt(19);
+ ASN1Sequence seqOfnRSStats;
+ ASN1Sequence seqOfnRSStrings;
+ ASN1Sequence seqOfnRSInts;
+ ASN1Sequence seqOfnRSBytes;
+
+ GMSSRootSig[] nextRootSig = new GMSSRootSig[seqOfnextRootSigs.size()];
+
+ for (int i = 0; i < nextRootSig.length; i++)
+ {
+ seqOfnRSStats = (ASN1Sequence)seqOfnextRootSigs.getObjectAt(i);
+ // nextNextAuth[i]= new byte[nextNextAuthPart1.size()][];
+ seqOfnRSStrings = (ASN1Sequence)seqOfnRSStats.getObjectAt(0);
+ seqOfnRSBytes = (ASN1Sequence)seqOfnRSStats.getObjectAt(1);
+ seqOfnRSInts = (ASN1Sequence)seqOfnRSStats.getObjectAt(2);
+
+ String[] name = new String[2];
+ name[0] = ((DERIA5String)seqOfnRSStrings.getObjectAt(0)).getString();
+ name[1] = ((DERIA5String)seqOfnRSStrings.getObjectAt(1)).getString();
+ byte[][] statByte = new byte[5][];
+ statByte[0] = ((DEROctetString)seqOfnRSBytes.getObjectAt(0))
+ .getOctets();
+ statByte[1] = ((DEROctetString)seqOfnRSBytes.getObjectAt(1))
+ .getOctets();
+ statByte[2] = ((DEROctetString)seqOfnRSBytes.getObjectAt(2))
+ .getOctets();
+ statByte[3] = ((DEROctetString)seqOfnRSBytes.getObjectAt(3))
+ .getOctets();
+ statByte[4] = ((DEROctetString)seqOfnRSBytes.getObjectAt(4))
+ .getOctets();
+ int[] statInt = new int[9];
+ statInt[0] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(0));
+ statInt[1] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(1));
+ statInt[2] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(2));
+ statInt[3] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(3));
+ statInt[4] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(4));
+ statInt[5] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(5));
+ statInt[6] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(6));
+ statInt[7] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(7));
+ statInt[8] = checkBigIntegerInIntRange(seqOfnRSInts.getObjectAt(8));
+ nextRootSig[i] = new GMSSRootSig(DigestFactory.getDigest(name[0]).getClass(), statByte, statInt);
+ }
+
+ // --- Decode <name>.
+
+ // TODO: Really check, why there are multiple algorithms, we only
+ // use the first one!!!
+ ASN1Sequence namePart = (ASN1Sequence)mtsPrivateKey.getObjectAt(20);
+ String[] name = new String[namePart.size()];
+ for (int i = 0; i < name.length; i++)
+ {
+ name[i] = ((DERIA5String)namePart.getObjectAt(i)).getString();
+ }
+ */
+ }
+
+ public GMSSPrivateKey(int[] index, byte[][] currentSeed,
+ byte[][] nextNextSeed, byte[][][] currentAuthPath,
+ byte[][][] nextAuthPath, Treehash[][] currentTreehash,
+ Treehash[][] nextTreehash, Vector[] currentStack,
+ Vector[] nextStack, Vector[][] currentRetain,
+ Vector[][] nextRetain, byte[][][] keep, GMSSLeaf[] nextNextLeaf,
+ GMSSLeaf[] upperLeaf, GMSSLeaf[] upperTreehashLeaf,
+ int[] minTreehash, byte[][] nextRoot, GMSSRootCalc[] nextNextRoot,
+ byte[][] currentRootSig, GMSSRootSig[] nextRootSig,
+ GMSSParameters gmssParameterset, AlgorithmIdentifier digestAlg)
+ {
+ AlgorithmIdentifier[] names = new AlgorithmIdentifier[] { digestAlg };
+ this.primitive = encode(index, currentSeed, nextNextSeed, currentAuthPath, nextAuthPath, keep, currentTreehash, nextTreehash, currentStack, nextStack, currentRetain, nextRetain, nextNextLeaf, upperLeaf, upperTreehashLeaf, minTreehash, nextRoot, nextNextRoot, currentRootSig, nextRootSig, gmssParameterset, names);
+ }
+
+
+ // TODO: change method signature to something more integrated into BouncyCastle
+
+ /**
+ * @param index tree indices
+ * @param currentSeeds seed for the generation of private OTS keys for the
+ * current subtrees (TREE)
+ * @param nextNextSeeds seed for the generation of private OTS keys for the
+ * subtrees after next (TREE++)
+ * @param currentAuthPaths array of current authentication paths (AUTHPATH)
+ * @param nextAuthPaths array of next authentication paths (AUTHPATH+)
+ * @param keep keep array for the authPath algorithm
+ * @param currentTreehash treehash for authPath algorithm of current tree
+ * @param nextTreehash treehash for authPath algorithm of next tree (TREE+)
+ * @param currentStack shared stack for authPath algorithm of current tree
+ * @param nextStack shared stack for authPath algorithm of next tree (TREE+)
+ * @param currentRetain retain stack for authPath algorithm of current tree
+ * @param nextRetain retain stack for authPath algorithm of next tree (TREE+)
+ * @param nextNextLeaf array of upcoming leafs of the tree after next (LEAF++) of
+ * each layer
+ * @param upperLeaf needed for precomputation of upper nodes
+ * @param upperTreehashLeaf needed for precomputation of upper treehash nodes
+ * @param minTreehash index of next treehash instance to receive an update
+ * @param nextRoot the roots of the next trees (ROOT+)
+ * @param nextNextRoot the roots of the tree after next (ROOT++)
+ * @param currentRootSig array of signatures of the roots of the current subtrees
+ * (SIG)
+ * @param nextRootSig array of signatures of the roots of the next subtree
+ * (SIG+)
+ * @param gmssParameterset the GMSS Parameterset
+ * @param algorithms An array of algorithm identifiers, containing the hash function details
+ */
+ private ASN1Primitive encode(int[] index, byte[][] currentSeeds,
+ byte[][] nextNextSeeds, byte[][][] currentAuthPaths,
+ byte[][][] nextAuthPaths, byte[][][] keep,
+ Treehash[][] currentTreehash, Treehash[][] nextTreehash,
+ Vector[] currentStack, Vector[] nextStack,
+ Vector[][] currentRetain, Vector[][] nextRetain,
+ GMSSLeaf[] nextNextLeaf, GMSSLeaf[] upperLeaf,
+ GMSSLeaf[] upperTreehashLeaf, int[] minTreehash, byte[][] nextRoot,
+ GMSSRootCalc[] nextNextRoot, byte[][] currentRootSig,
+ GMSSRootSig[] nextRootSig, GMSSParameters gmssParameterset,
+ AlgorithmIdentifier[] algorithms)
+ {
+
+ ASN1EncodableVector result = new ASN1EncodableVector();
+
+ // --- Encode <index>.
+ ASN1EncodableVector indexPart = new ASN1EncodableVector();
+ for (int i = 0; i < index.length; i++)
+ {
+ indexPart.add(new ASN1Integer(index[i]));
+ }
+ result.add(new DERSequence(indexPart));
+
+ // --- Encode <curSeeds>.
+ ASN1EncodableVector curSeedsPart = new ASN1EncodableVector();
+ for (int i = 0; i < currentSeeds.length; i++)
+ {
+ curSeedsPart.add(new DEROctetString(currentSeeds[i]));
+ }
+ result.add(new DERSequence(curSeedsPart));
+
+ // --- Encode <nextNextSeeds>.
+ ASN1EncodableVector nextNextSeedsPart = new ASN1EncodableVector();
+ for (int i = 0; i < nextNextSeeds.length; i++)
+ {
+ nextNextSeedsPart.add(new DEROctetString(nextNextSeeds[i]));
+ }
+ result.add(new DERSequence(nextNextSeedsPart));
+
+ // --- Encode <curAuth>.
+ ASN1EncodableVector curAuthPart0 = new ASN1EncodableVector();
+ ASN1EncodableVector curAuthPart1 = new ASN1EncodableVector();
+ for (int i = 0; i < currentAuthPaths.length; i++)
+ {
+ for (int j = 0; j < currentAuthPaths[i].length; j++)
+ {
+ curAuthPart0.add(new DEROctetString(currentAuthPaths[i][j]));
+ }
+ curAuthPart1.add(new DERSequence(curAuthPart0));
+ curAuthPart0 = new ASN1EncodableVector();
+ }
+ result.add(new DERSequence(curAuthPart1));
+
+ // --- Encode <nextAuth>.
+ ASN1EncodableVector nextAuthPart0 = new ASN1EncodableVector();
+ ASN1EncodableVector nextAuthPart1 = new ASN1EncodableVector();
+ for (int i = 0; i < nextAuthPaths.length; i++)
+ {
+ for (int j = 0; j < nextAuthPaths[i].length; j++)
+ {
+ nextAuthPart0.add(new DEROctetString(nextAuthPaths[i][j]));
+ }
+ nextAuthPart1.add(new DERSequence(nextAuthPart0));
+ nextAuthPart0 = new ASN1EncodableVector();
+ }
+ result.add(new DERSequence(nextAuthPart1));
+
+ // --- Encode <curTreehash>.
+ ASN1EncodableVector seqOfTreehash0 = new ASN1EncodableVector();
+ ASN1EncodableVector seqOfTreehash1 = new ASN1EncodableVector();
+ ASN1EncodableVector seqOfStat = new ASN1EncodableVector();
+ ASN1EncodableVector seqOfByte = new ASN1EncodableVector();
+ ASN1EncodableVector seqOfInt = new ASN1EncodableVector();
+
+ for (int i = 0; i < currentTreehash.length; i++)
+ {
+ for (int j = 0; j < currentTreehash[i].length; j++)
+ {
+ seqOfStat.add(new DERSequence(algorithms[0]));
+
+ int tailLength = currentTreehash[i][j].getStatInt()[1];
+
+ seqOfByte.add(new DEROctetString(currentTreehash[i][j]
+ .getStatByte()[0]));
+ seqOfByte.add(new DEROctetString(currentTreehash[i][j]
+ .getStatByte()[1]));
+ seqOfByte.add(new DEROctetString(currentTreehash[i][j]
+ .getStatByte()[2]));
+ for (int k = 0; k < tailLength; k++)
+ {
+ seqOfByte.add(new DEROctetString(currentTreehash[i][j]
+ .getStatByte()[3 + k]));
+ }
+ seqOfStat.add(new DERSequence(seqOfByte));
+ seqOfByte = new ASN1EncodableVector();
+
+ seqOfInt.add(new ASN1Integer(
+ currentTreehash[i][j].getStatInt()[0]));
+ seqOfInt.add(new ASN1Integer(tailLength));
+ seqOfInt.add(new ASN1Integer(
+ currentTreehash[i][j].getStatInt()[2]));
+ seqOfInt.add(new ASN1Integer(
+ currentTreehash[i][j].getStatInt()[3]));
+ seqOfInt.add(new ASN1Integer(
+ currentTreehash[i][j].getStatInt()[4]));
+ seqOfInt.add(new ASN1Integer(
+ currentTreehash[i][j].getStatInt()[5]));
+ for (int k = 0; k < tailLength; k++)
+ {
+ seqOfInt.add(new ASN1Integer(currentTreehash[i][j]
+ .getStatInt()[6 + k]));
+ }
+ seqOfStat.add(new DERSequence(seqOfInt));
+ seqOfInt = new ASN1EncodableVector();
+
+ seqOfTreehash1.add(new DERSequence(seqOfStat));
+ seqOfStat = new ASN1EncodableVector();
+ }
+ seqOfTreehash0.add(new DERSequence(seqOfTreehash1));
+ seqOfTreehash1 = new ASN1EncodableVector();
+ }
+ result.add(new DERSequence(seqOfTreehash0));
+
+ // --- Encode <nextTreehash>.
+ seqOfTreehash0 = new ASN1EncodableVector();
+ seqOfTreehash1 = new ASN1EncodableVector();
+ seqOfStat = new ASN1EncodableVector();
+ seqOfByte = new ASN1EncodableVector();
+ seqOfInt = new ASN1EncodableVector();
+
+ for (int i = 0; i < nextTreehash.length; i++)
+ {
+ for (int j = 0; j < nextTreehash[i].length; j++)
+ {
+ seqOfStat.add(new DERSequence(algorithms[0]));
+
+ int tailLength = nextTreehash[i][j].getStatInt()[1];
+
+ seqOfByte.add(new DEROctetString(nextTreehash[i][j]
+ .getStatByte()[0]));
+ seqOfByte.add(new DEROctetString(nextTreehash[i][j]
+ .getStatByte()[1]));
+ seqOfByte.add(new DEROctetString(nextTreehash[i][j]
+ .getStatByte()[2]));
+ for (int k = 0; k < tailLength; k++)
+ {
+ seqOfByte.add(new DEROctetString(nextTreehash[i][j]
+ .getStatByte()[3 + k]));
+ }
+ seqOfStat.add(new DERSequence(seqOfByte));
+ seqOfByte = new ASN1EncodableVector();
+
+ seqOfInt
+ .add(new ASN1Integer(nextTreehash[i][j].getStatInt()[0]));
+ seqOfInt.add(new ASN1Integer(tailLength));
+ seqOfInt
+ .add(new ASN1Integer(nextTreehash[i][j].getStatInt()[2]));
+ seqOfInt
+ .add(new ASN1Integer(nextTreehash[i][j].getStatInt()[3]));
+ seqOfInt
+ .add(new ASN1Integer(nextTreehash[i][j].getStatInt()[4]));
+ seqOfInt
+ .add(new ASN1Integer(nextTreehash[i][j].getStatInt()[5]));
+ for (int k = 0; k < tailLength; k++)
+ {
+ seqOfInt.add(new ASN1Integer(nextTreehash[i][j]
+ .getStatInt()[6 + k]));
+ }
+ seqOfStat.add(new DERSequence(seqOfInt));
+ seqOfInt = new ASN1EncodableVector();
+
+ seqOfTreehash1.add(new DERSequence(seqOfStat));
+ seqOfStat = new ASN1EncodableVector();
+ }
+ seqOfTreehash0.add(new DERSequence(new DERSequence(seqOfTreehash1)));
+ seqOfTreehash1 = new ASN1EncodableVector();
+ }
+ result.add(new DERSequence(seqOfTreehash0));
+
+ // --- Encode <keep>.
+ ASN1EncodableVector keepPart0 = new ASN1EncodableVector();
+ ASN1EncodableVector keepPart1 = new ASN1EncodableVector();
+ for (int i = 0; i < keep.length; i++)
+ {
+ for (int j = 0; j < keep[i].length; j++)
+ {
+ keepPart0.add(new DEROctetString(keep[i][j]));
+ }
+ keepPart1.add(new DERSequence(keepPart0));
+ keepPart0 = new ASN1EncodableVector();
+ }
+ result.add(new DERSequence(keepPart1));
+
+ // --- Encode <curStack>.
+ ASN1EncodableVector curStackPart0 = new ASN1EncodableVector();
+ ASN1EncodableVector curStackPart1 = new ASN1EncodableVector();
+ for (int i = 0; i < currentStack.length; i++)
+ {
+ for (int j = 0; j < currentStack[i].size(); j++)
+ {
+ curStackPart0.add(new DEROctetString((byte[])currentStack[i]
+ .elementAt(j)));
+ }
+ curStackPart1.add(new DERSequence(curStackPart0));
+ curStackPart0 = new ASN1EncodableVector();
+ }
+ result.add(new DERSequence(curStackPart1));
+
+ // --- Encode <nextStack>.
+ ASN1EncodableVector nextStackPart0 = new ASN1EncodableVector();
+ ASN1EncodableVector nextStackPart1 = new ASN1EncodableVector();
+ for (int i = 0; i < nextStack.length; i++)
+ {
+ for (int j = 0; j < nextStack[i].size(); j++)
+ {
+ nextStackPart0.add(new DEROctetString((byte[])nextStack[i]
+ .elementAt(j)));
+ }
+ nextStackPart1.add(new DERSequence(nextStackPart0));
+ nextStackPart0 = new ASN1EncodableVector();
+ }
+ result.add(new DERSequence(nextStackPart1));
+
+ // --- Encode <curRetain>.
+ ASN1EncodableVector currentRetainPart0 = new ASN1EncodableVector();
+ ASN1EncodableVector currentRetainPart1 = new ASN1EncodableVector();
+ ASN1EncodableVector currentRetainPart2 = new ASN1EncodableVector();
+ for (int i = 0; i < currentRetain.length; i++)
+ {
+ for (int j = 0; j < currentRetain[i].length; j++)
+ {
+ for (int k = 0; k < currentRetain[i][j].size(); k++)
+ {
+ currentRetainPart0.add(new DEROctetString(
+ (byte[])currentRetain[i][j].elementAt(k)));
+ }
+ currentRetainPart1.add(new DERSequence(currentRetainPart0));
+ currentRetainPart0 = new ASN1EncodableVector();
+ }
+ currentRetainPart2.add(new DERSequence(currentRetainPart1));
+ currentRetainPart1 = new ASN1EncodableVector();
+ }
+ result.add(new DERSequence(currentRetainPart2));
+
+ // --- Encode <nextRetain>.
+ ASN1EncodableVector nextRetainPart0 = new ASN1EncodableVector();
+ ASN1EncodableVector nextRetainPart1 = new ASN1EncodableVector();
+ ASN1EncodableVector nextRetainPart2 = new ASN1EncodableVector();
+ for (int i = 0; i < nextRetain.length; i++)
+ {
+ for (int j = 0; j < nextRetain[i].length; j++)
+ {
+ for (int k = 0; k < nextRetain[i][j].size(); k++)
+ {
+ nextRetainPart0.add(new DEROctetString(
+ (byte[])nextRetain[i][j].elementAt(k)));
+ }
+ nextRetainPart1.add(new DERSequence(nextRetainPart0));
+ nextRetainPart0 = new ASN1EncodableVector();
+ }
+ nextRetainPart2.add(new DERSequence(nextRetainPart1));
+ nextRetainPart1 = new ASN1EncodableVector();
+ }
+ result.add(new DERSequence(nextRetainPart2));
+
+ // --- Encode <nextNextLeaf>.
+ ASN1EncodableVector seqOfLeaf = new ASN1EncodableVector();
+ seqOfStat = new ASN1EncodableVector();
+ seqOfByte = new ASN1EncodableVector();
+ seqOfInt = new ASN1EncodableVector();
+
+ for (int i = 0; i < nextNextLeaf.length; i++)
+ {
+ seqOfStat.add(new DERSequence(algorithms[0]));
+
+ byte[][] tempByte = nextNextLeaf[i].getStatByte();
+ seqOfByte.add(new DEROctetString(tempByte[0]));
+ seqOfByte.add(new DEROctetString(tempByte[1]));
+ seqOfByte.add(new DEROctetString(tempByte[2]));
+ seqOfByte.add(new DEROctetString(tempByte[3]));
+ seqOfStat.add(new DERSequence(seqOfByte));
+ seqOfByte = new ASN1EncodableVector();
+
+ int[] tempInt = nextNextLeaf[i].getStatInt();
+ seqOfInt.add(new ASN1Integer(tempInt[0]));
+ seqOfInt.add(new ASN1Integer(tempInt[1]));
+ seqOfInt.add(new ASN1Integer(tempInt[2]));
+ seqOfInt.add(new ASN1Integer(tempInt[3]));
+ seqOfStat.add(new DERSequence(seqOfInt));
+ seqOfInt = new ASN1EncodableVector();
+
+ seqOfLeaf.add(new DERSequence(seqOfStat));
+ seqOfStat = new ASN1EncodableVector();
+ }
+ result.add(new DERSequence(seqOfLeaf));
+
+ // --- Encode <upperLEAF>.
+ ASN1EncodableVector seqOfUpperLeaf = new ASN1EncodableVector();
+ seqOfStat = new ASN1EncodableVector();
+ seqOfByte = new ASN1EncodableVector();
+ seqOfInt = new ASN1EncodableVector();
+
+ for (int i = 0; i < upperLeaf.length; i++)
+ {
+ seqOfStat.add(new DERSequence(algorithms[0]));
+
+ byte[][] tempByte = upperLeaf[i].getStatByte();
+ seqOfByte.add(new DEROctetString(tempByte[0]));
+ seqOfByte.add(new DEROctetString(tempByte[1]));
+ seqOfByte.add(new DEROctetString(tempByte[2]));
+ seqOfByte.add(new DEROctetString(tempByte[3]));
+ seqOfStat.add(new DERSequence(seqOfByte));
+ seqOfByte = new ASN1EncodableVector();
+
+ int[] tempInt = upperLeaf[i].getStatInt();
+ seqOfInt.add(new ASN1Integer(tempInt[0]));
+ seqOfInt.add(new ASN1Integer(tempInt[1]));
+ seqOfInt.add(new ASN1Integer(tempInt[2]));
+ seqOfInt.add(new ASN1Integer(tempInt[3]));
+ seqOfStat.add(new DERSequence(seqOfInt));
+ seqOfInt = new ASN1EncodableVector();
+
+ seqOfUpperLeaf.add(new DERSequence(seqOfStat));
+ seqOfStat = new ASN1EncodableVector();
+ }
+ result.add(new DERSequence(seqOfUpperLeaf));
+
+ // encode <upperTreehashLeaf>
+ ASN1EncodableVector seqOfUpperTreehashLeaf = new ASN1EncodableVector();
+ seqOfStat = new ASN1EncodableVector();
+ seqOfByte = new ASN1EncodableVector();
+ seqOfInt = new ASN1EncodableVector();
+
+ for (int i = 0; i < upperTreehashLeaf.length; i++)
+ {
+ seqOfStat.add(new DERSequence(algorithms[0]));
+
+ byte[][] tempByte = upperTreehashLeaf[i].getStatByte();
+ seqOfByte.add(new DEROctetString(tempByte[0]));
+ seqOfByte.add(new DEROctetString(tempByte[1]));
+ seqOfByte.add(new DEROctetString(tempByte[2]));
+ seqOfByte.add(new DEROctetString(tempByte[3]));
+ seqOfStat.add(new DERSequence(seqOfByte));
+ seqOfByte = new ASN1EncodableVector();
+
+ int[] tempInt = upperTreehashLeaf[i].getStatInt();
+ seqOfInt.add(new ASN1Integer(tempInt[0]));
+ seqOfInt.add(new ASN1Integer(tempInt[1]));
+ seqOfInt.add(new ASN1Integer(tempInt[2]));
+ seqOfInt.add(new ASN1Integer(tempInt[3]));
+ seqOfStat.add(new DERSequence(seqOfInt));
+ seqOfInt = new ASN1EncodableVector();
+
+ seqOfUpperTreehashLeaf.add(new DERSequence(seqOfStat));
+ seqOfStat = new ASN1EncodableVector();
+ }
+ result.add(new DERSequence(seqOfUpperTreehashLeaf));
+
+ // --- Encode <minTreehash>.
+ ASN1EncodableVector minTreehashPart = new ASN1EncodableVector();
+ for (int i = 0; i < minTreehash.length; i++)
+ {
+ minTreehashPart.add(new ASN1Integer(minTreehash[i]));
+ }
+ result.add(new DERSequence(minTreehashPart));
+
+ // --- Encode <nextRoot>.
+ ASN1EncodableVector nextRootPart = new ASN1EncodableVector();
+ for (int i = 0; i < nextRoot.length; i++)
+ {
+ nextRootPart.add(new DEROctetString(nextRoot[i]));
+ }
+ result.add(new DERSequence(nextRootPart));
+
+ // --- Encode <nextNextRoot>.
+ ASN1EncodableVector seqOfnextNextRoot = new ASN1EncodableVector();
+ ASN1EncodableVector seqOfnnRStats = new ASN1EncodableVector();
+ ASN1EncodableVector seqOfnnRStrings = new ASN1EncodableVector();
+ ASN1EncodableVector seqOfnnRBytes = new ASN1EncodableVector();
+ ASN1EncodableVector seqOfnnRInts = new ASN1EncodableVector();
+ ASN1EncodableVector seqOfnnRTreehash = new ASN1EncodableVector();
+ ASN1EncodableVector seqOfnnRRetain = new ASN1EncodableVector();
+
+ for (int i = 0; i < nextNextRoot.length; i++)
+ {
+ seqOfnnRStats.add(new DERSequence(algorithms[0]));
+ seqOfnnRStrings = new ASN1EncodableVector();
+
+ int heightOfTree = nextNextRoot[i].getStatInt()[0];
+ int tailLength = nextNextRoot[i].getStatInt()[7];
+
+ seqOfnnRBytes.add(new DEROctetString(
+ nextNextRoot[i].getStatByte()[0]));
+ for (int j = 0; j < heightOfTree; j++)
+ {
+ seqOfnnRBytes.add(new DEROctetString(nextNextRoot[i]
+ .getStatByte()[1 + j]));
+ }
+ for (int j = 0; j < tailLength; j++)
+ {
+ seqOfnnRBytes.add(new DEROctetString(nextNextRoot[i]
+ .getStatByte()[1 + heightOfTree + j]));
+ }
+
+ seqOfnnRStats.add(new DERSequence(seqOfnnRBytes));
+ seqOfnnRBytes = new ASN1EncodableVector();
+
+ seqOfnnRInts.add(new ASN1Integer(heightOfTree));
+ seqOfnnRInts.add(new ASN1Integer(nextNextRoot[i].getStatInt()[1]));
+ seqOfnnRInts.add(new ASN1Integer(nextNextRoot[i].getStatInt()[2]));
+ seqOfnnRInts.add(new ASN1Integer(nextNextRoot[i].getStatInt()[3]));
+ seqOfnnRInts.add(new ASN1Integer(nextNextRoot[i].getStatInt()[4]));
+ seqOfnnRInts.add(new ASN1Integer(nextNextRoot[i].getStatInt()[5]));
+ seqOfnnRInts.add(new ASN1Integer(nextNextRoot[i].getStatInt()[6]));
+ seqOfnnRInts.add(new ASN1Integer(tailLength));
+ for (int j = 0; j < heightOfTree; j++)
+ {
+ seqOfnnRInts.add(new ASN1Integer(
+ nextNextRoot[i].getStatInt()[8 + j]));
+ }
+ for (int j = 0; j < tailLength; j++)
+ {
+ seqOfnnRInts.add(new ASN1Integer(nextNextRoot[i].getStatInt()[8
+ + heightOfTree + j]));
+ }
+
+ seqOfnnRStats.add(new DERSequence(seqOfnnRInts));
+ seqOfnnRInts = new ASN1EncodableVector();
+
+ // add treehash of nextNextRoot object
+ // ----------------------------
+ seqOfStat = new ASN1EncodableVector();
+ seqOfByte = new ASN1EncodableVector();
+ seqOfInt = new ASN1EncodableVector();
+
+ if (nextNextRoot[i].getTreehash() != null)
+ {
+ for (int j = 0; j < nextNextRoot[i].getTreehash().length; j++)
+ {
+ seqOfStat.add(new DERSequence(algorithms[0]));
+
+ tailLength = nextNextRoot[i].getTreehash()[j].getStatInt()[1];
+
+ seqOfByte.add(new DEROctetString(nextNextRoot[i]
+ .getTreehash()[j].getStatByte()[0]));
+ seqOfByte.add(new DEROctetString(nextNextRoot[i]
+ .getTreehash()[j].getStatByte()[1]));
+ seqOfByte.add(new DEROctetString(nextNextRoot[i]
+ .getTreehash()[j].getStatByte()[2]));
+ for (int k = 0; k < tailLength; k++)
+ {
+ seqOfByte.add(new DEROctetString(nextNextRoot[i]
+ .getTreehash()[j].getStatByte()[3 + k]));
+ }
+ seqOfStat.add(new DERSequence(seqOfByte));
+ seqOfByte = new ASN1EncodableVector();
+
+ seqOfInt.add(new ASN1Integer(
+ nextNextRoot[i].getTreehash()[j].getStatInt()[0]));
+ seqOfInt.add(new ASN1Integer(tailLength));
+ seqOfInt.add(new ASN1Integer(
+ nextNextRoot[i].getTreehash()[j].getStatInt()[2]));
+ seqOfInt.add(new ASN1Integer(
+ nextNextRoot[i].getTreehash()[j].getStatInt()[3]));
+ seqOfInt.add(new ASN1Integer(
+ nextNextRoot[i].getTreehash()[j].getStatInt()[4]));
+ seqOfInt.add(new ASN1Integer(
+ nextNextRoot[i].getTreehash()[j].getStatInt()[5]));
+ for (int k = 0; k < tailLength; k++)
+ {
+ seqOfInt.add(new ASN1Integer(nextNextRoot[i]
+ .getTreehash()[j].getStatInt()[6 + k]));
+ }
+ seqOfStat.add(new DERSequence(seqOfInt));
+ seqOfInt = new ASN1EncodableVector();
+
+ seqOfnnRTreehash.add(new DERSequence(seqOfStat));
+ seqOfStat = new ASN1EncodableVector();
+ }
+ }
+ // ----------------------------
+ seqOfnnRStats.add(new DERSequence(seqOfnnRTreehash));
+ seqOfnnRTreehash = new ASN1EncodableVector();
+
+ // encode retain of nextNextRoot
+ // ----------------------------
+ // --- Encode <curRetain>.
+ currentRetainPart0 = new ASN1EncodableVector();
+ if (nextNextRoot[i].getRetain() != null)
+ {
+ for (int j = 0; j < nextNextRoot[i].getRetain().length; j++)
+ {
+ for (int k = 0; k < nextNextRoot[i].getRetain()[j].size(); k++)
+ {
+ currentRetainPart0.add(new DEROctetString(
+ (byte[])nextNextRoot[i].getRetain()[j]
+ .elementAt(k)));
+ }
+ seqOfnnRRetain.add(new DERSequence(currentRetainPart0));
+ currentRetainPart0 = new ASN1EncodableVector();
+ }
+ }
+ // ----------------------------
+ seqOfnnRStats.add(new DERSequence(seqOfnnRRetain));
+ seqOfnnRRetain = new ASN1EncodableVector();
+
+ seqOfnextNextRoot.add(new DERSequence(seqOfnnRStats));
+ seqOfnnRStats = new ASN1EncodableVector();
+ }
+ result.add(new DERSequence(seqOfnextNextRoot));
+
+ // --- Encode <curRootSig>.
+ ASN1EncodableVector curRootSigPart = new ASN1EncodableVector();
+ for (int i = 0; i < currentRootSig.length; i++)
+ {
+ curRootSigPart.add(new DEROctetString(currentRootSig[i]));
+ }
+ result.add(new DERSequence(curRootSigPart));
+
+ // --- Encode <nextRootSig>.
+ ASN1EncodableVector seqOfnextRootSigs = new ASN1EncodableVector();
+ ASN1EncodableVector seqOfnRSStats = new ASN1EncodableVector();
+ ASN1EncodableVector seqOfnRSStrings = new ASN1EncodableVector();
+ ASN1EncodableVector seqOfnRSBytes = new ASN1EncodableVector();
+ ASN1EncodableVector seqOfnRSInts = new ASN1EncodableVector();
+
+ for (int i = 0; i < nextRootSig.length; i++)
+ {
+ seqOfnRSStats.add(new DERSequence(algorithms[0]));
+ seqOfnRSStrings = new ASN1EncodableVector();
+
+ seqOfnRSBytes.add(new DEROctetString(
+ nextRootSig[i].getStatByte()[0]));
+ seqOfnRSBytes.add(new DEROctetString(
+ nextRootSig[i].getStatByte()[1]));
+ seqOfnRSBytes.add(new DEROctetString(
+ nextRootSig[i].getStatByte()[2]));
+ seqOfnRSBytes.add(new DEROctetString(
+ nextRootSig[i].getStatByte()[3]));
+ seqOfnRSBytes.add(new DEROctetString(
+ nextRootSig[i].getStatByte()[4]));
+
+ seqOfnRSStats.add(new DERSequence(seqOfnRSBytes));
+ seqOfnRSBytes = new ASN1EncodableVector();
+
+ seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[0]));
+ seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[1]));
+ seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[2]));
+ seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[3]));
+ seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[4]));
+ seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[5]));
+ seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[6]));
+ seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[7]));
+ seqOfnRSInts.add(new ASN1Integer(nextRootSig[i].getStatInt()[8]));
+
+ seqOfnRSStats.add(new DERSequence(seqOfnRSInts));
+ seqOfnRSInts = new ASN1EncodableVector();
+
+ seqOfnextRootSigs.add(new DERSequence(seqOfnRSStats));
+ seqOfnRSStats = new ASN1EncodableVector();
+ }
+ result.add(new DERSequence(seqOfnextRootSigs));
+
+ // --- Encode <parameterset>.
+ ASN1EncodableVector parSetPart0 = new ASN1EncodableVector();
+ ASN1EncodableVector parSetPart1 = new ASN1EncodableVector();
+ ASN1EncodableVector parSetPart2 = new ASN1EncodableVector();
+ ASN1EncodableVector parSetPart3 = new ASN1EncodableVector();
+
+ for (int i = 0; i < gmssParameterset.getHeightOfTrees().length; i++)
+ {
+ parSetPart1.add(new ASN1Integer(
+ gmssParameterset.getHeightOfTrees()[i]));
+ parSetPart2.add(new ASN1Integer(gmssParameterset
+ .getWinternitzParameter()[i]));
+ parSetPart3.add(new ASN1Integer(gmssParameterset.getK()[i]));
+ }
+ parSetPart0.add(new ASN1Integer(gmssParameterset.getNumOfLayers()));
+ parSetPart0.add(new DERSequence(parSetPart1));
+ parSetPart0.add(new DERSequence(parSetPart2));
+ parSetPart0.add(new DERSequence(parSetPart3));
+ result.add(new DERSequence(parSetPart0));
+
+ // --- Encode <names>.
+ ASN1EncodableVector namesPart = new ASN1EncodableVector();
+
+ for (int i = 0; i < algorithms.length; i++)
+ {
+ namesPart.add(algorithms[i]);
+ }
+
+ result.add(new DERSequence(namesPart));
+ return new DERSequence(result);
+
+ }
+
+ private static int checkBigIntegerInIntRange(ASN1Encodable a)
+ {
+ BigInteger b = ((ASN1Integer)a).getValue();
+ if ((b.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) ||
+ (b.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0))
+ {
+ throw new IllegalArgumentException("BigInteger not in Range: " + b.toString());
+ }
+ return b.intValue();
+ }
+
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return this.primitive;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/asn1/GMSSPublicKey.java b/core/src/main/java/org/spongycastle/pqc/asn1/GMSSPublicKey.java
new file mode 100644
index 00000000..77992283
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/asn1/GMSSPublicKey.java
@@ -0,0 +1,74 @@
+package org.spongycastle.pqc.asn1;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.util.Arrays;
+
+/**
+ * This class implements an ASN.1 encoded GMSS public key. The ASN.1 definition
+ * of this structure is:
+ * <pre>
+ * GMSSPublicKey ::= SEQUENCE{
+ * version INTEGER
+ * publicKey OCTET STRING
+ * }
+ * </pre>
+ */
+public class GMSSPublicKey
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private byte[] publicKey;
+
+ private GMSSPublicKey(ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("size of seq = " + seq.size());
+ }
+
+ this.version = ASN1Integer.getInstance(seq.getObjectAt(0));
+ this.publicKey = ASN1OctetString.getInstance(seq.getObjectAt(1)).getOctets();
+ }
+
+ public GMSSPublicKey(byte[] publicKeyBytes)
+ {
+ this.version = new ASN1Integer(0);
+ this.publicKey = publicKeyBytes;
+ }
+
+ public static GMSSPublicKey getInstance(Object o)
+ {
+ if (o instanceof GMSSPublicKey)
+ {
+ return (GMSSPublicKey)o;
+ }
+ else if (o != null)
+ {
+ return new GMSSPublicKey(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public byte[] getPublicKey()
+ {
+ return Arrays.clone(publicKey);
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(new DEROctetString(publicKey));
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/asn1/McElieceCCA2PrivateKey.java b/core/src/main/java/org/spongycastle/pqc/asn1/McElieceCCA2PrivateKey.java
new file mode 100644
index 00000000..5f6a8b9d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/asn1/McElieceCCA2PrivateKey.java
@@ -0,0 +1,173 @@
+package org.spongycastle.pqc.asn1;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+
+import org.spongycastle.pqc.math.linearalgebra.GF2Matrix;
+import org.spongycastle.pqc.math.linearalgebra.GF2mField;
+import org.spongycastle.pqc.math.linearalgebra.Permutation;
+import org.spongycastle.pqc.math.linearalgebra.PolynomialGF2mSmallM;
+
+public class McElieceCCA2PrivateKey
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier oid;
+ private int n;
+ private int k;
+ private byte[] encField;
+ private byte[] encGp;
+ private byte[] encP;
+ private byte[] encH;
+ private byte[][] encqInv;
+
+
+ public McElieceCCA2PrivateKey(ASN1ObjectIdentifier oid, int n, int k, GF2mField field, PolynomialGF2mSmallM goppaPoly, Permutation p, GF2Matrix h, PolynomialGF2mSmallM[] qInv)
+ {
+ this.oid = oid;
+ this.n = n;
+ this.k = k;
+ this.encField = field.getEncoded();
+ this.encGp = goppaPoly.getEncoded();
+ this.encP = p.getEncoded();
+ this.encH = h.getEncoded();
+ this.encqInv = new byte[qInv.length][];
+
+ for (int i = 0; i != qInv.length; i++)
+ {
+ encqInv[i] = qInv[i].getEncoded();
+ }
+ }
+
+ private McElieceCCA2PrivateKey(ASN1Sequence seq)
+ {
+ oid = ((ASN1ObjectIdentifier)seq.getObjectAt(0));
+
+ BigInteger bigN = ((ASN1Integer)seq.getObjectAt(1)).getValue();
+ n = bigN.intValue();
+
+ BigInteger bigK = ((ASN1Integer)seq.getObjectAt(2)).getValue();
+ k = bigK.intValue();
+
+ encField = ((ASN1OctetString)seq.getObjectAt(3)).getOctets();
+
+ encGp = ((ASN1OctetString)seq.getObjectAt(4)).getOctets();
+
+ encP = ((ASN1OctetString)seq.getObjectAt(5)).getOctets();
+
+ encH = ((ASN1OctetString)seq.getObjectAt(6)).getOctets();
+
+ ASN1Sequence asnQInv = (ASN1Sequence)seq.getObjectAt(7);
+ encqInv = new byte[asnQInv.size()][];
+ for (int i = 0; i < asnQInv.size(); i++)
+ {
+ encqInv[i] = ((ASN1OctetString)asnQInv.getObjectAt(i)).getOctets();
+ }
+ }
+
+ public ASN1ObjectIdentifier getOID()
+ {
+ return oid;
+ }
+
+ public int getN()
+ {
+ return n;
+ }
+
+ public int getK()
+ {
+ return k;
+ }
+
+ public GF2mField getField()
+ {
+ return new GF2mField(encField);
+ }
+
+ public PolynomialGF2mSmallM getGoppaPoly()
+ {
+ return new PolynomialGF2mSmallM(this.getField(), encGp);
+ }
+
+ public Permutation getP()
+ {
+ return new Permutation(encP);
+ }
+
+ public GF2Matrix getH()
+ {
+ return new GF2Matrix(encH);
+ }
+
+ public PolynomialGF2mSmallM[] getQInv()
+ {
+ PolynomialGF2mSmallM[] qInv = new PolynomialGF2mSmallM[encqInv.length];
+ GF2mField field = this.getField();
+
+ for (int i = 0; i < encqInv.length; i++)
+ {
+ qInv[i] = new PolynomialGF2mSmallM(field, encqInv[i]);
+ }
+
+ return qInv;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ // encode <oidString>
+ v.add(oid);
+ // encode <n>
+ v.add(new ASN1Integer(n));
+
+ // encode <k>
+ v.add(new ASN1Integer(k));
+
+ // encode <field>
+ v.add(new DEROctetString(encField));
+
+ // encode <gp>
+ v.add(new DEROctetString(encGp));
+
+ // encode <p>
+ v.add(new DEROctetString(encP));
+
+ // encode <h>
+ v.add(new DEROctetString(encH));
+
+ // encode <q>
+ ASN1EncodableVector asnQInv = new ASN1EncodableVector();
+ for (int i = 0; i < encqInv.length; i++)
+ {
+ asnQInv.add(new DEROctetString(encqInv[i]));
+ }
+
+ v.add(new DERSequence(asnQInv));
+
+ return new DERSequence(v);
+ }
+
+ public static McElieceCCA2PrivateKey getInstance(Object o)
+ {
+ if (o instanceof McElieceCCA2PrivateKey)
+ {
+ return (McElieceCCA2PrivateKey)o;
+ }
+ else if (o != null)
+ {
+ return new McElieceCCA2PrivateKey(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/asn1/McElieceCCA2PublicKey.java b/core/src/main/java/org/spongycastle/pqc/asn1/McElieceCCA2PublicKey.java
new file mode 100644
index 00000000..186d8ca4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/asn1/McElieceCCA2PublicKey.java
@@ -0,0 +1,96 @@
+package org.spongycastle.pqc.asn1;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.pqc.math.linearalgebra.GF2Matrix;
+
+public class McElieceCCA2PublicKey
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier oid;
+ private int n;
+ private int t;
+
+ private byte[] matrixG;
+
+ public McElieceCCA2PublicKey(ASN1ObjectIdentifier oid, int n, int t, GF2Matrix g)
+ {
+ this.oid = oid;
+ this.n = n;
+ this.t = t;
+ this.matrixG = g.getEncoded();
+ }
+
+ private McElieceCCA2PublicKey(ASN1Sequence seq)
+ {
+ oid = ((ASN1ObjectIdentifier)seq.getObjectAt(0));
+ BigInteger bigN = ((ASN1Integer)seq.getObjectAt(1)).getValue();
+ n = bigN.intValue();
+
+ BigInteger bigT = ((ASN1Integer)seq.getObjectAt(2)).getValue();
+ t = bigT.intValue();
+
+ matrixG = ((ASN1OctetString)seq.getObjectAt(3)).getOctets();
+ }
+
+ public ASN1ObjectIdentifier getOID()
+ {
+ return oid;
+ }
+
+ public int getN()
+ {
+ return n;
+ }
+
+ public int getT()
+ {
+ return t;
+ }
+
+ public GF2Matrix getG()
+ {
+ return new GF2Matrix(matrixG);
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ // encode <oidString>
+ v.add(oid);
+
+ // encode <n>
+ v.add(new ASN1Integer(n));
+
+ // encode <t>
+ v.add(new ASN1Integer(t));
+
+ // encode <matrixG>
+ v.add(new DEROctetString(matrixG));
+
+ return new DERSequence(v);
+ }
+
+ public static McElieceCCA2PublicKey getInstance(Object o)
+ {
+ if (o instanceof McElieceCCA2PublicKey)
+ {
+ return (McElieceCCA2PublicKey)o;
+ }
+ else if (o != null)
+ {
+ return new McElieceCCA2PublicKey(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/asn1/McEliecePrivateKey.java b/core/src/main/java/org/spongycastle/pqc/asn1/McEliecePrivateKey.java
new file mode 100644
index 00000000..e0ba1ed7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/asn1/McEliecePrivateKey.java
@@ -0,0 +1,197 @@
+package org.spongycastle.pqc.asn1;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.pqc.math.linearalgebra.GF2Matrix;
+import org.spongycastle.pqc.math.linearalgebra.GF2mField;
+import org.spongycastle.pqc.math.linearalgebra.Permutation;
+import org.spongycastle.pqc.math.linearalgebra.PolynomialGF2mSmallM;
+
+public class McEliecePrivateKey
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier oid;
+ private int n;
+ private int k;
+ private byte[] encField;
+ private byte[] encGp;
+ private byte[] encSInv;
+ private byte[] encP1;
+ private byte[] encP2;
+ private byte[] encH;
+ private byte[][] encqInv;
+
+
+ public McEliecePrivateKey(ASN1ObjectIdentifier oid, int n, int k, GF2mField field, PolynomialGF2mSmallM goppaPoly, GF2Matrix sInv, Permutation p1, Permutation p2, GF2Matrix h, PolynomialGF2mSmallM[] qInv)
+ {
+ this.oid = oid;
+ this.n = n;
+ this.k = k;
+ this.encField = field.getEncoded();
+ this.encGp = goppaPoly.getEncoded();
+ this.encSInv = sInv.getEncoded();
+ this.encP1 = p1.getEncoded();
+ this.encP2 = p2.getEncoded();
+ this.encH = h.getEncoded();
+ this.encqInv = new byte[qInv.length][];
+
+ for (int i = 0; i != qInv.length; i++)
+ {
+ encqInv[i] = qInv[i].getEncoded();
+ }
+ }
+
+ public static McEliecePrivateKey getInstance(Object o)
+ {
+ if (o instanceof McEliecePrivateKey)
+ {
+ return (McEliecePrivateKey)o;
+ }
+ else if (o != null)
+ {
+ return new McEliecePrivateKey(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ private McEliecePrivateKey(ASN1Sequence seq)
+ {
+ // <oidString>
+ oid = ((ASN1ObjectIdentifier)seq.getObjectAt(0));
+
+ BigInteger bigN = ((ASN1Integer)seq.getObjectAt(1)).getValue();
+ n = bigN.intValue();
+
+ BigInteger bigK = ((ASN1Integer)seq.getObjectAt(2)).getValue();
+ k = bigK.intValue();
+
+ encField = ((ASN1OctetString)seq.getObjectAt(3)).getOctets();
+
+ encGp = ((ASN1OctetString)seq.getObjectAt(4)).getOctets();
+
+ encSInv = ((ASN1OctetString)seq.getObjectAt(5)).getOctets();
+
+ encP1 = ((ASN1OctetString)seq.getObjectAt(6)).getOctets();
+
+ encP2 = ((ASN1OctetString)seq.getObjectAt(7)).getOctets();
+
+ encH = ((ASN1OctetString)seq.getObjectAt(8)).getOctets();
+
+ ASN1Sequence asnQInv = (ASN1Sequence)seq.getObjectAt(9);
+ encqInv = new byte[asnQInv.size()][];
+ for (int i = 0; i < asnQInv.size(); i++)
+ {
+ encqInv[i] = ((ASN1OctetString)asnQInv.getObjectAt(i)).getOctets();
+ }
+ }
+
+ public ASN1ObjectIdentifier getOID()
+ {
+ return oid;
+ }
+
+ public int getN()
+ {
+ return n;
+ }
+
+ public int getK()
+ {
+ return k;
+ }
+
+ public GF2mField getField()
+ {
+ return new GF2mField(encField);
+ }
+
+ public PolynomialGF2mSmallM getGoppaPoly()
+ {
+ return new PolynomialGF2mSmallM(this.getField(), encGp);
+ }
+
+ public GF2Matrix getSInv()
+ {
+ return new GF2Matrix(encSInv);
+ }
+
+ public Permutation getP1()
+ {
+ return new Permutation(encP1);
+ }
+
+ public Permutation getP2()
+ {
+ return new Permutation(encP2);
+ }
+
+ public GF2Matrix getH()
+ {
+ return new GF2Matrix(encH);
+ }
+
+ public PolynomialGF2mSmallM[] getQInv()
+ {
+ PolynomialGF2mSmallM[] qInv = new PolynomialGF2mSmallM[encqInv.length];
+ GF2mField field = this.getField();
+
+ for (int i = 0; i < encqInv.length; i++)
+ {
+ qInv[i] = new PolynomialGF2mSmallM(field, encqInv[i]);
+ }
+
+ return qInv;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ // encode <oidString>
+ v.add(oid);
+ // encode <n>
+ v.add(new ASN1Integer(n));
+
+ // encode <k>
+ v.add(new ASN1Integer(k));
+
+ // encode <fieldPoly>
+ v.add(new DEROctetString(encField));
+
+ // encode <goppaPoly>
+ v.add(new DEROctetString(encGp));
+
+ // encode <sInv>
+ v.add(new DEROctetString(encSInv));
+
+ // encode <p1>
+ v.add(new DEROctetString(encP1));
+
+ // encode <p2>
+ v.add(new DEROctetString(encP2));
+
+ // encode <h>
+ v.add(new DEROctetString(encH));
+
+ // encode <q>
+ ASN1EncodableVector asnQInv = new ASN1EncodableVector();
+ for (int i = 0; i < encqInv.length; i++)
+ {
+ asnQInv.add(new DEROctetString(encqInv[i]));
+ }
+
+ v.add(new DERSequence(asnQInv));
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/asn1/McEliecePublicKey.java b/core/src/main/java/org/spongycastle/pqc/asn1/McEliecePublicKey.java
new file mode 100644
index 00000000..1415587d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/asn1/McEliecePublicKey.java
@@ -0,0 +1,97 @@
+package org.spongycastle.pqc.asn1;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.pqc.math.linearalgebra.GF2Matrix;
+
+public class McEliecePublicKey
+ extends ASN1Object
+{
+
+ private ASN1ObjectIdentifier oid;
+ private int n;
+ private int t;
+
+ private byte[] matrixG;
+
+ public McEliecePublicKey(ASN1ObjectIdentifier oid, int n, int t, GF2Matrix g)
+ {
+ this.oid = oid;
+ this.n = n;
+ this.t = t;
+ this.matrixG = g.getEncoded();
+ }
+
+ private McEliecePublicKey(ASN1Sequence seq)
+ {
+ oid = ((ASN1ObjectIdentifier)seq.getObjectAt(0));
+ BigInteger bigN = ((ASN1Integer)seq.getObjectAt(1)).getValue();
+ n = bigN.intValue();
+
+ BigInteger bigT = ((ASN1Integer)seq.getObjectAt(2)).getValue();
+ t = bigT.intValue();
+
+ matrixG = ((ASN1OctetString)seq.getObjectAt(3)).getOctets();
+ }
+
+ public ASN1ObjectIdentifier getOID()
+ {
+ return oid;
+ }
+
+ public int getN()
+ {
+ return n;
+ }
+
+ public int getT()
+ {
+ return t;
+ }
+
+ public GF2Matrix getG()
+ {
+ return new GF2Matrix(matrixG);
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ // encode <oidString>
+ v.add(oid);
+
+ // encode <n>
+ v.add(new ASN1Integer(n));
+
+ // encode <t>
+ v.add(new ASN1Integer(t));
+
+ // encode <matrixG>
+ v.add(new DEROctetString(matrixG));
+
+ return new DERSequence(v);
+ }
+
+ public static McEliecePublicKey getInstance(Object o)
+ {
+ if (o instanceof McEliecePublicKey)
+ {
+ return (McEliecePublicKey)o;
+ }
+ else if (o != null)
+ {
+ return new McEliecePublicKey(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/asn1/PQCObjectIdentifiers.java b/core/src/main/java/org/spongycastle/pqc/asn1/PQCObjectIdentifiers.java
new file mode 100644
index 00000000..1a0e5ce7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/asn1/PQCObjectIdentifiers.java
@@ -0,0 +1,46 @@
+package org.spongycastle.pqc.asn1;
+
+import org.spongycastle.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");
+
+ /** 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");
+
+ /** 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");
+
+ /** 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");
+
+ /** 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/core/src/main/java/org/spongycastle/pqc/asn1/ParSet.java b/core/src/main/java/org/spongycastle/pqc/asn1/ParSet.java
new file mode 100644
index 00000000..d5110a2c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/asn1/ParSet.java
@@ -0,0 +1,140 @@
+package org.spongycastle.pqc.asn1;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.util.Arrays;
+
+/**
+ * <pre>
+ * ParSet ::= SEQUENCE {
+ * T INTEGER
+ * h SEQUENCE OF INTEGER
+ * w SEQUENCE OF INTEGER
+ * K SEQUENCE OF INTEGER
+ * }
+ * </pre>
+ */
+public class ParSet
+ extends ASN1Object
+{
+ private static final BigInteger ZERO = BigInteger.valueOf(0);
+
+ private int t;
+ private int[] h;
+ private int[] w;
+ private int[] k;
+
+ private static int checkBigIntegerInIntRangeAndPositive(BigInteger b)
+ {
+ if ((b.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) ||
+ (b.compareTo(ZERO) <= 0))
+ {
+ throw new IllegalArgumentException("BigInteger not in Range: " + b.toString());
+ }
+ return b.intValue();
+ }
+
+ private ParSet(ASN1Sequence seq)
+ {
+ if (seq.size() != 4)
+ {
+ throw new IllegalArgumentException("sie of seqOfParams = " + seq.size());
+ }
+ BigInteger asn1int = ((ASN1Integer)seq.getObjectAt(0)).getValue();
+
+ t = checkBigIntegerInIntRangeAndPositive(asn1int);
+
+ ASN1Sequence seqOfPSh = (ASN1Sequence)seq.getObjectAt(1);
+ ASN1Sequence seqOfPSw = (ASN1Sequence)seq.getObjectAt(2);
+ ASN1Sequence seqOfPSK = (ASN1Sequence)seq.getObjectAt(3);
+
+ if ((seqOfPSh.size() != t) ||
+ (seqOfPSw.size() != t) ||
+ (seqOfPSK.size() != t))
+ {
+ throw new IllegalArgumentException("invalid size of sequences");
+ }
+
+ h = new int[seqOfPSh.size()];
+ w = new int[seqOfPSw.size()];
+ k = new int[seqOfPSK.size()];
+
+ for (int i = 0; i < t; i++)
+ {
+ h[i] = checkBigIntegerInIntRangeAndPositive((((ASN1Integer)seqOfPSh.getObjectAt(i))).getValue());
+ w[i] = checkBigIntegerInIntRangeAndPositive((((ASN1Integer)seqOfPSw.getObjectAt(i))).getValue());
+ k[i] = checkBigIntegerInIntRangeAndPositive((((ASN1Integer)seqOfPSK.getObjectAt(i))).getValue());
+ }
+ }
+
+ public ParSet(int t, int[] h, int[] w, int[] k)
+ {
+ this.t = t;
+ this.h = h;
+ this.w = w;
+ this.k = k;
+ }
+
+ public static ParSet getInstance(Object o)
+ {
+ if (o instanceof ParSet)
+ {
+ return (ParSet)o;
+ }
+ else if (o != null)
+ {
+ return new ParSet(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public int getT()
+ {
+ return t;
+ }
+
+ public int[] getH()
+ {
+ return Arrays.clone(h);
+ }
+
+ public int[] getW()
+ {
+ return Arrays.clone(w);
+ }
+
+ public int[] getK()
+ {
+ return Arrays.clone(k);
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector seqOfPSh = new ASN1EncodableVector();
+ ASN1EncodableVector seqOfPSw = new ASN1EncodableVector();
+ ASN1EncodableVector seqOfPSK = new ASN1EncodableVector();
+
+ for (int i = 0; i < h.length; i++)
+ {
+ seqOfPSh.add(new ASN1Integer(h[i]));
+ seqOfPSw.add(new ASN1Integer(w[i]));
+ seqOfPSK.add(new ASN1Integer(k[i]));
+ }
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(t));
+ v.add(new DERSequence(seqOfPSh));
+ v.add(new DERSequence(seqOfPSw));
+ v.add(new DERSequence(seqOfPSK));
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/asn1/RainbowPrivateKey.java b/core/src/main/java/org/spongycastle/pqc/asn1/RainbowPrivateKey.java
new file mode 100644
index 00000000..96648900
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/asn1/RainbowPrivateKey.java
@@ -0,0 +1,349 @@
+package org.spongycastle.pqc.asn1;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.pqc.crypto.rainbow.Layer;
+import org.spongycastle.pqc.crypto.rainbow.util.RainbowUtil;
+
+/**
+ * Return the key data to encode in the PrivateKeyInfo structure.
+ * <p>
+ * The ASN.1 definition of the key structure is
+ * <pre>
+ * RainbowPrivateKey ::= SEQUENCE {
+ * CHOICE
+ * {
+ * oid OBJECT IDENTIFIER -- OID identifying the algorithm
+ * version INTEGER -- 0
+ * }
+ * A1inv SEQUENCE OF OCTET STRING -- inversed matrix of L1
+ * b1 OCTET STRING -- translation vector of L1
+ * A2inv SEQUENCE OF OCTET STRING -- inversed matrix of L2
+ * b2 OCTET STRING -- translation vector of L2
+ * vi OCTET STRING -- num of elmts in each Set S
+ * layers SEQUENCE OF Layer -- layers of F
+ * }
+ *
+ * Layer ::= SEQUENCE OF Poly
+ *
+ * Poly ::= SEQUENCE {
+ * alpha SEQUENCE OF OCTET STRING
+ * beta SEQUENCE OF OCTET STRING
+ * gamma OCTET STRING
+ * eta INTEGER
+ * }
+ * </pre>
+ */
+public class RainbowPrivateKey
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private ASN1ObjectIdentifier oid;
+
+ private byte[][] invA1;
+ private byte[] b1;
+ private byte[][] invA2;
+ private byte[] b2;
+ private byte[] vi;
+ private Layer[] layers;
+
+ private RainbowPrivateKey(ASN1Sequence seq)
+ {
+ // <oidString> or version
+ if (seq.getObjectAt(0) instanceof ASN1Integer)
+ {
+ version = ASN1Integer.getInstance(seq.getObjectAt(0));
+ }
+ else
+ {
+ oid = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+ }
+
+ // <A1inv>
+ ASN1Sequence asnA1 = (ASN1Sequence)seq.getObjectAt(1);
+ invA1 = new byte[asnA1.size()][];
+ for (int i = 0; i < asnA1.size(); i++)
+ {
+ invA1[i] = ((ASN1OctetString)asnA1.getObjectAt(i)).getOctets();
+ }
+
+ // <b1>
+ ASN1Sequence asnb1 = (ASN1Sequence)seq.getObjectAt(2);
+ b1 = ((ASN1OctetString)asnb1.getObjectAt(0)).getOctets();
+
+ // <A2inv>
+ ASN1Sequence asnA2 = (ASN1Sequence)seq.getObjectAt(3);
+ invA2 = new byte[asnA2.size()][];
+ for (int j = 0; j < asnA2.size(); j++)
+ {
+ invA2[j] = ((ASN1OctetString)asnA2.getObjectAt(j)).getOctets();
+ }
+
+ // <b2>
+ ASN1Sequence asnb2 = (ASN1Sequence)seq.getObjectAt(4);
+ b2 = ((ASN1OctetString)asnb2.getObjectAt(0)).getOctets();
+
+ // <vi>
+ ASN1Sequence asnvi = (ASN1Sequence)seq.getObjectAt(5);
+ vi = ((ASN1OctetString)asnvi.getObjectAt(0)).getOctets();
+
+ // <layers>
+ ASN1Sequence asnLayers = (ASN1Sequence)seq.getObjectAt(6);
+
+ byte[][][][] alphas = new byte[asnLayers.size()][][][];
+ byte[][][][] betas = new byte[asnLayers.size()][][][];
+ byte[][][] gammas = new byte[asnLayers.size()][][];
+ byte[][] etas = new byte[asnLayers.size()][];
+ // a layer:
+ for (int l = 0; l < asnLayers.size(); l++)
+ {
+ ASN1Sequence asnLayer = (ASN1Sequence)asnLayers.getObjectAt(l);
+
+ // alphas (num of alpha-2d-array = oi)
+ ASN1Sequence alphas3d = (ASN1Sequence)asnLayer.getObjectAt(0);
+ alphas[l] = new byte[alphas3d.size()][][];
+ for (int m = 0; m < alphas3d.size(); m++)
+ {
+ ASN1Sequence alphas2d = (ASN1Sequence)alphas3d.getObjectAt(m);
+ alphas[l][m] = new byte[alphas2d.size()][];
+ for (int n = 0; n < alphas2d.size(); n++)
+ {
+ alphas[l][m][n] = ((ASN1OctetString)alphas2d.getObjectAt(n)).getOctets();
+ }
+ }
+
+ // betas ....
+ ASN1Sequence betas3d = (ASN1Sequence)asnLayer.getObjectAt(1);
+ betas[l] = new byte[betas3d.size()][][];
+ for (int mb = 0; mb < betas3d.size(); mb++)
+ {
+ ASN1Sequence betas2d = (ASN1Sequence)betas3d.getObjectAt(mb);
+ betas[l][mb] = new byte[betas2d.size()][];
+ for (int nb = 0; nb < betas2d.size(); nb++)
+ {
+ betas[l][mb][nb] = ((ASN1OctetString)betas2d.getObjectAt(nb)).getOctets();
+ }
+ }
+
+ // gammas ...
+ ASN1Sequence gammas2d = (ASN1Sequence)asnLayer.getObjectAt(2);
+ gammas[l] = new byte[gammas2d.size()][];
+ for (int mg = 0; mg < gammas2d.size(); mg++)
+ {
+ gammas[l][mg] = ((ASN1OctetString)gammas2d.getObjectAt(mg)).getOctets();
+ }
+
+ // eta ...
+ etas[l] = ((ASN1OctetString)asnLayer.getObjectAt(3)).getOctets();
+ }
+
+ int numOfLayers = vi.length - 1;
+ this.layers = new Layer[numOfLayers];
+ for (int i = 0; i < numOfLayers; i++)
+ {
+ Layer l = new Layer(vi[i], vi[i + 1], RainbowUtil.convertArray(alphas[i]),
+ RainbowUtil.convertArray(betas[i]), RainbowUtil.convertArray(gammas[i]), RainbowUtil.convertArray(etas[i]));
+ this.layers[i] = l;
+
+ }
+ }
+
+ public RainbowPrivateKey(short[][] invA1, short[] b1, short[][] invA2,
+ short[] b2, int[] vi, Layer[] layers)
+ {
+ this.version = new ASN1Integer(1);
+ this.invA1 = RainbowUtil.convertArray(invA1);
+ this.b1 = RainbowUtil.convertArray(b1);
+ this.invA2 = RainbowUtil.convertArray(invA2);
+ this.b2 = RainbowUtil.convertArray(b2);
+ this.vi = RainbowUtil.convertIntArray(vi);
+ this.layers = layers;
+ }
+
+ public static RainbowPrivateKey getInstance(Object o)
+ {
+ if (o instanceof RainbowPrivateKey)
+ {
+ return (RainbowPrivateKey)o;
+ }
+ else if (o != null)
+ {
+ return new RainbowPrivateKey(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ /**
+ * Getter for the inverse matrix of A1.
+ *
+ * @return the A1inv inverse
+ */
+ public short[][] getInvA1()
+ {
+ return RainbowUtil.convertArray(invA1);
+ }
+
+ /**
+ * Getter for the translation part of the private quadratic map L1.
+ *
+ * @return b1 the translation part of L1
+ */
+ public short[] getB1()
+ {
+ return RainbowUtil.convertArray(b1);
+ }
+
+ /**
+ * Getter for the translation part of the private quadratic map L2.
+ *
+ * @return b2 the translation part of L2
+ */
+ public short[] getB2()
+ {
+ return RainbowUtil.convertArray(b2);
+ }
+
+ /**
+ * Getter for the inverse matrix of A2
+ *
+ * @return the A2inv
+ */
+ public short[][] getInvA2()
+ {
+ return RainbowUtil.convertArray(invA2);
+ }
+
+ /**
+ * Returns the layers contained in the private key
+ *
+ * @return layers
+ */
+ public Layer[] getLayers()
+ {
+ return this.layers;
+ }
+
+ /**
+ * Returns the array of vi-s
+ *
+ * @return the vi
+ */
+ public int[] getVi()
+ {
+ return RainbowUtil.convertArraytoInt(vi);
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ // encode <oidString> or version
+ if (version != null)
+ {
+ v.add(version);
+ }
+ else
+ {
+ v.add(oid);
+ }
+
+ // encode <A1inv>
+ ASN1EncodableVector asnA1 = new ASN1EncodableVector();
+ for (int i = 0; i < invA1.length; i++)
+ {
+ asnA1.add(new DEROctetString(invA1[i]));
+ }
+ v.add(new DERSequence(asnA1));
+
+ // encode <b1>
+ ASN1EncodableVector asnb1 = new ASN1EncodableVector();
+ asnb1.add(new DEROctetString(b1));
+ v.add(new DERSequence(asnb1));
+
+ // encode <A2inv>
+ ASN1EncodableVector asnA2 = new ASN1EncodableVector();
+ for (int i = 0; i < invA2.length; i++)
+ {
+ asnA2.add(new DEROctetString(invA2[i]));
+ }
+ v.add(new DERSequence(asnA2));
+
+ // encode <b2>
+ ASN1EncodableVector asnb2 = new ASN1EncodableVector();
+ asnb2.add(new DEROctetString(b2));
+ v.add(new DERSequence(asnb2));
+
+ // encode <vi>
+ ASN1EncodableVector asnvi = new ASN1EncodableVector();
+ asnvi.add(new DEROctetString(vi));
+ v.add(new DERSequence(asnvi));
+
+ // encode <layers>
+ ASN1EncodableVector asnLayers = new ASN1EncodableVector();
+ // a layer:
+ for (int l = 0; l < layers.length; l++)
+ {
+ ASN1EncodableVector aLayer = new ASN1EncodableVector();
+
+ // alphas (num of alpha-2d-array = oi)
+ byte[][][] alphas = RainbowUtil.convertArray(layers[l].getCoeffAlpha());
+ ASN1EncodableVector alphas3d = new ASN1EncodableVector();
+ for (int i = 0; i < alphas.length; i++)
+ {
+ ASN1EncodableVector alphas2d = new ASN1EncodableVector();
+ for (int j = 0; j < alphas[i].length; j++)
+ {
+ alphas2d.add(new DEROctetString(alphas[i][j]));
+ }
+ alphas3d.add(new DERSequence(alphas2d));
+ }
+ aLayer.add(new DERSequence(alphas3d));
+
+ // betas ....
+ byte[][][] betas = RainbowUtil.convertArray(layers[l].getCoeffBeta());
+ ASN1EncodableVector betas3d = new ASN1EncodableVector();
+ for (int i = 0; i < betas.length; i++)
+ {
+ ASN1EncodableVector betas2d = new ASN1EncodableVector();
+ for (int j = 0; j < betas[i].length; j++)
+ {
+ betas2d.add(new DEROctetString(betas[i][j]));
+ }
+ betas3d.add(new DERSequence(betas2d));
+ }
+ aLayer.add(new DERSequence(betas3d));
+
+ // gammas ...
+ byte[][] gammas = RainbowUtil.convertArray(layers[l].getCoeffGamma());
+ ASN1EncodableVector asnG = new ASN1EncodableVector();
+ for (int i = 0; i < gammas.length; i++)
+ {
+ asnG.add(new DEROctetString(gammas[i]));
+ }
+ aLayer.add(new DERSequence(asnG));
+
+ // eta
+ aLayer.add(new DEROctetString(RainbowUtil.convertArray(layers[l].getCoeffEta())));
+
+ // now, layer built up. add it!
+ asnLayers.add(new DERSequence(aLayer));
+ }
+
+ v.add(new DERSequence(asnLayers));
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/asn1/RainbowPublicKey.java b/core/src/main/java/org/spongycastle/pqc/asn1/RainbowPublicKey.java
new file mode 100644
index 00000000..c31aabb4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/asn1/RainbowPublicKey.java
@@ -0,0 +1,174 @@
+package org.spongycastle.pqc.asn1;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.pqc.crypto.rainbow.util.RainbowUtil;
+
+/**
+ * This class implements an ASN.1 encoded Rainbow public key. The ASN.1 definition
+ * of this structure is:
+ * <pre>
+ * RainbowPublicKey ::= SEQUENCE {
+ * CHOICE
+ * {
+ * oid OBJECT IDENTIFIER -- OID identifying the algorithm
+ * version INTEGER -- 0
+ * }
+ * docLength Integer -- length of the code
+ * coeffquadratic SEQUENCE OF OCTET STRING -- quadratic (mixed) coefficients
+ * coeffsingular SEQUENCE OF OCTET STRING -- singular coefficients
+ * coeffscalar SEQUENCE OF OCTET STRING -- scalar coefficients
+ * }
+ * </pre>
+ */
+public class RainbowPublicKey
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private ASN1ObjectIdentifier oid;
+ private ASN1Integer docLength;
+ private byte[][] coeffQuadratic;
+ private byte[][] coeffSingular;
+ private byte[] coeffScalar;
+
+ private RainbowPublicKey(ASN1Sequence seq)
+ {
+ // <oidString> or version
+ if (seq.getObjectAt(0) instanceof ASN1Integer)
+ {
+ version = ASN1Integer.getInstance(seq.getObjectAt(0));
+ }
+ else
+ {
+ oid = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+ }
+
+ docLength = ASN1Integer.getInstance(seq.getObjectAt(1));
+
+ ASN1Sequence asnCoeffQuad = ASN1Sequence.getInstance(seq.getObjectAt(2));
+ coeffQuadratic = new byte[asnCoeffQuad.size()][];
+ for (int quadSize = 0; quadSize < asnCoeffQuad.size(); quadSize++)
+ {
+ coeffQuadratic[quadSize] = ASN1OctetString.getInstance(asnCoeffQuad.getObjectAt(quadSize)).getOctets();
+ }
+
+ ASN1Sequence asnCoeffSing = (ASN1Sequence)seq.getObjectAt(3);
+ coeffSingular = new byte[asnCoeffSing.size()][];
+ for (int singSize = 0; singSize < asnCoeffSing.size(); singSize++)
+ {
+ coeffSingular[singSize] = ASN1OctetString.getInstance(asnCoeffSing.getObjectAt(singSize)).getOctets();
+ }
+
+ ASN1Sequence asnCoeffScalar = (ASN1Sequence)seq.getObjectAt(4);
+ coeffScalar = ASN1OctetString.getInstance(asnCoeffScalar.getObjectAt(0)).getOctets();
+ }
+
+ public RainbowPublicKey(int docLength, short[][] coeffQuadratic, short[][] coeffSingular, short[] coeffScalar)
+ {
+ this.version = new ASN1Integer(0);
+ this.docLength = new ASN1Integer(docLength);
+ this.coeffQuadratic = RainbowUtil.convertArray(coeffQuadratic);
+ this.coeffSingular = RainbowUtil.convertArray(coeffSingular);
+ this.coeffScalar = RainbowUtil.convertArray(coeffScalar);
+ }
+
+ public static RainbowPublicKey getInstance(Object o)
+ {
+ if (o instanceof RainbowPublicKey)
+ {
+ return (RainbowPublicKey)o;
+ }
+ else if (o != null)
+ {
+ return new RainbowPublicKey(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ /**
+ * @return the docLength
+ */
+ public int getDocLength()
+ {
+ return this.docLength.getValue().intValue();
+ }
+
+ /**
+ * @return the coeffquadratic
+ */
+ public short[][] getCoeffQuadratic()
+ {
+ return RainbowUtil.convertArray(coeffQuadratic);
+ }
+
+ /**
+ * @return the coeffsingular
+ */
+ public short[][] getCoeffSingular()
+ {
+ return RainbowUtil.convertArray(coeffSingular);
+ }
+
+ /**
+ * @return the coeffscalar
+ */
+ public short[] getCoeffScalar()
+ {
+ return RainbowUtil.convertArray(coeffScalar);
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ // encode <oidString> or version
+ if (version != null)
+ {
+ v.add(version);
+ }
+ else
+ {
+ v.add(oid);
+ }
+
+ // encode <docLength>
+ v.add(docLength);
+
+ // encode <coeffQuadratic>
+ ASN1EncodableVector asnCoeffQuad = new ASN1EncodableVector();
+ for (int i = 0; i < coeffQuadratic.length; i++)
+ {
+ asnCoeffQuad.add(new DEROctetString(coeffQuadratic[i]));
+ }
+ v.add(new DERSequence(asnCoeffQuad));
+
+ // encode <coeffSingular>
+ ASN1EncodableVector asnCoeffSing = new ASN1EncodableVector();
+ for (int i = 0; i < coeffSingular.length; i++)
+ {
+ asnCoeffSing.add(new DEROctetString(coeffSingular[i]));
+ }
+ v.add(new DERSequence(asnCoeffSing));
+
+ // encode <coeffScalar>
+ ASN1EncodableVector asnCoeffScalar = new ASN1EncodableVector();
+ asnCoeffScalar.add(new DEROctetString(coeffScalar));
+ v.add(new DERSequence(asnCoeffScalar));
+
+
+ return new DERSequence(v);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/DigestingMessageSigner.java b/core/src/main/java/org/spongycastle/pqc/crypto/DigestingMessageSigner.java
new file mode 100644
index 00000000..b58a5278
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/DigestingMessageSigner.java
@@ -0,0 +1,117 @@
+package org.spongycastle.pqc.crypto;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.Signer;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+
+
+/**
+ * Implements the sign and verify functions for a Signature Scheme which can use a hash function.
+ */
+public class DigestingMessageSigner
+ implements Signer
+{
+ private final Digest messDigest;
+ private final MessageSigner messSigner;
+ private boolean forSigning;
+
+ public DigestingMessageSigner(MessageSigner messSigner, Digest messDigest)
+ {
+ this.messSigner = messSigner;
+ this.messDigest = messDigest;
+ }
+
+ public void init(boolean forSigning,
+ CipherParameters param)
+ {
+
+ this.forSigning = forSigning;
+ AsymmetricKeyParameter k;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ k = (AsymmetricKeyParameter)((ParametersWithRandom)param).getParameters();
+ }
+ else
+ {
+ k = (AsymmetricKeyParameter)param;
+ }
+
+ if (forSigning && !k.isPrivate())
+ {
+ throw new IllegalArgumentException("Signing Requires Private Key.");
+ }
+
+ if (!forSigning && k.isPrivate())
+ {
+ throw new IllegalArgumentException("Verification Requires Public Key.");
+ }
+
+ reset();
+
+ messSigner.init(forSigning, param);
+ }
+
+
+ /**
+ * This function signs the message that has been updated, making use of the
+ * private key.
+ *
+ * @return the signature of the message.
+ */
+ public byte[] generateSignature()
+ {
+ if (!forSigning)
+ {
+ throw new IllegalStateException("RainbowDigestSigner not initialised for signature generation.");
+ }
+
+ byte[] hash = new byte[messDigest.getDigestSize()];
+ messDigest.doFinal(hash, 0);
+
+ return messSigner.generateSignature(hash);
+ }
+
+ /**
+ * This function verifies the signature of the message that has been
+ * updated, with the aid of the public key.
+ *
+ * @param signature the signature of the message is given as a byte array.
+ * @return true if the signature has been verified, false otherwise.
+ */
+ public boolean verify(byte[] signature)
+ {
+ if (forSigning)
+ {
+ throw new IllegalStateException("RainbowDigestSigner not initialised for verification");
+ }
+
+ byte[] hash = new byte[messDigest.getDigestSize()];
+ messDigest.doFinal(hash, 0);
+
+ return messSigner.verifySignature(hash, signature);
+
+ }
+
+ public void update(byte b)
+ {
+ messDigest.update(b);
+ }
+
+ public void update(byte[] in, int off, int len)
+ {
+ messDigest.update(in, off, len);
+ }
+
+ public void reset()
+ {
+ messDigest.reset();
+ }
+
+ public boolean verifySignature(byte[] signature)
+ {
+ return this.verify(signature);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/MessageEncryptor.java b/core/src/main/java/org/spongycastle/pqc/crypto/MessageEncryptor.java
new file mode 100644
index 00000000..4d5ea6b2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/MessageEncryptor.java
@@ -0,0 +1,30 @@
+package org.spongycastle.pqc.crypto;
+
+
+import org.spongycastle.crypto.CipherParameters;
+
+public interface MessageEncryptor
+{
+
+ /**
+ *
+ * @param forEncrypting true if we are encrypting a signature, false
+ * otherwise.
+ * @param param key parameters for encryption or decryption.
+ */
+ public void init(boolean forEncrypting, CipherParameters param);
+
+ /**
+ *
+ * @param message the message to be signed.
+ * @throws Exception
+ */
+ public byte[] messageEncrypt(byte[] message) throws Exception;
+
+ /**
+ *
+ * @param cipher the cipher text of the message
+ * @throws Exception
+ */
+ public byte[] messageDecrypt(byte[] cipher) throws Exception;
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/MessageSigner.java b/core/src/main/java/org/spongycastle/pqc/crypto/MessageSigner.java
new file mode 100644
index 00000000..b09c6195
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/MessageSigner.java
@@ -0,0 +1,32 @@
+package org.spongycastle.pqc.crypto;
+
+import org.spongycastle.crypto.CipherParameters;
+
+public interface MessageSigner
+{
+ /**
+ * initialise the signer for signature generation or signature
+ * verification.
+ *
+ * @param forSigning true if we are generating a signature, false
+ * otherwise.
+ * @param param key parameters for signature generation.
+ */
+ public void init(boolean forSigning, CipherParameters param);
+
+ /**
+ * sign the passed in message (usually the output of a hash function).
+ *
+ * @param message the message to be signed.
+ * @return the signature of the message
+ */
+ public byte[] generateSignature(byte[] message);
+
+ /**
+ * verify the message message against the signature values r and s.
+ *
+ * @param message the message that was supposed to have been signed.
+ * @param signature the signature of the message
+ */
+ public boolean verifySignature(byte[] message, byte[] signature);
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSDigestProvider.java b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSDigestProvider.java
new file mode 100644
index 00000000..373ca503
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSDigestProvider.java
@@ -0,0 +1,8 @@
+package org.spongycastle.pqc.crypto.gmss;
+
+import org.spongycastle.crypto.Digest;
+
+public interface GMSSDigestProvider
+{
+ Digest get();
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSKeyGenerationParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSKeyGenerationParameters.java
new file mode 100644
index 00000000..27d7b697
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSKeyGenerationParameters.java
@@ -0,0 +1,26 @@
+package org.spongycastle.pqc.crypto.gmss;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.KeyGenerationParameters;
+
+public class GMSSKeyGenerationParameters
+ extends KeyGenerationParameters
+{
+
+ private GMSSParameters params;
+
+ public GMSSKeyGenerationParameters(
+ SecureRandom random,
+ GMSSParameters params)
+ {
+ // XXX key size?
+ super(random, 1);
+ this.params = params;
+ }
+
+ public GMSSParameters getParameters()
+ {
+ return params;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSKeyPairGenerator.java b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSKeyPairGenerator.java
new file mode 100644
index 00000000..bb1ef36d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSKeyPairGenerator.java
@@ -0,0 +1,476 @@
+package org.spongycastle.pqc.crypto.gmss;
+
+import java.security.SecureRandom;
+import java.util.Vector;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.pqc.crypto.gmss.util.GMSSRandom;
+import org.spongycastle.pqc.crypto.gmss.util.WinternitzOTSVerify;
+import org.spongycastle.pqc.crypto.gmss.util.WinternitzOTSignature;
+
+
+/**
+ * This class implements key pair generation of the generalized Merkle signature
+ * scheme (GMSS).
+ *
+ * @see GMSSSigner
+ */
+public class GMSSKeyPairGenerator
+ implements AsymmetricCipherKeyPairGenerator
+{
+ /**
+ * The source of randomness for OTS private key generation
+ */
+ private GMSSRandom gmssRandom;
+
+ /**
+ * The hash function used for the construction of the authentication trees
+ */
+ private Digest messDigestTree;
+
+ /**
+ * An array of the seeds for the PRGN (for main tree, and all current
+ * subtrees)
+ */
+ private byte[][] currentSeeds;
+
+ /**
+ * An array of seeds for the PRGN (for all subtrees after next)
+ */
+ private byte[][] nextNextSeeds;
+
+ /**
+ * An array of the RootSignatures
+ */
+ private byte[][] currentRootSigs;
+
+ /**
+ * Class of hash function to use
+ */
+ private GMSSDigestProvider digestProvider;
+
+ /**
+ * The length of the seed for the PRNG
+ */
+ private int mdLength;
+
+ /**
+ * the number of Layers
+ */
+ private int numLayer;
+
+
+ /**
+ * Flag indicating if the class already has been initialized
+ */
+ private boolean initialized = false;
+
+ /**
+ * Instance of GMSSParameterset
+ */
+ private GMSSParameters gmssPS;
+
+ /**
+ * An array of the heights of the authentication trees of each layer
+ */
+ private int[] heightOfTrees;
+
+ /**
+ * An array of the Winternitz parameter 'w' of each layer
+ */
+ private int[] otsIndex;
+
+ /**
+ * The parameter K needed for the authentication path computation
+ */
+ private int[] K;
+
+ private GMSSKeyGenerationParameters gmssParams;
+
+ /**
+ * The GMSS OID.
+ */
+ public static final String OID = "1.3.6.1.4.1.8301.3.1.3.3";
+
+ /**
+ * The standard constructor tries to generate the GMSS algorithm identifier
+ * with the corresponding OID.
+ *
+ * @param digestProvider provider for digest implementations.
+ */
+ public GMSSKeyPairGenerator(GMSSDigestProvider digestProvider)
+ {
+ this.digestProvider = digestProvider;
+ messDigestTree = digestProvider.get();
+
+ // set mdLength
+ this.mdLength = messDigestTree.getDigestSize();
+ // construct randomizer
+ this.gmssRandom = new GMSSRandom(messDigestTree);
+
+ }
+
+ /**
+ * Generates the GMSS key pair. The public key is an instance of
+ * JDKGMSSPublicKey, the private key is an instance of JDKGMSSPrivateKey.
+ *
+ * @return Key pair containing a JDKGMSSPublicKey and a JDKGMSSPrivateKey
+ */
+ private AsymmetricCipherKeyPair genKeyPair()
+ {
+ if (!initialized)
+ {
+ initializeDefault();
+ }
+
+ // initialize authenticationPaths and treehash instances
+ byte[][][] currentAuthPaths = new byte[numLayer][][];
+ byte[][][] nextAuthPaths = new byte[numLayer - 1][][];
+ Treehash[][] currentTreehash = new Treehash[numLayer][];
+ Treehash[][] nextTreehash = new Treehash[numLayer - 1][];
+
+ Vector[] currentStack = new Vector[numLayer];
+ Vector[] nextStack = new Vector[numLayer - 1];
+
+ Vector[][] currentRetain = new Vector[numLayer][];
+ Vector[][] nextRetain = new Vector[numLayer - 1][];
+
+ for (int i = 0; i < numLayer; i++)
+ {
+ currentAuthPaths[i] = new byte[heightOfTrees[i]][mdLength];
+ currentTreehash[i] = new Treehash[heightOfTrees[i] - K[i]];
+
+ if (i > 0)
+ {
+ nextAuthPaths[i - 1] = new byte[heightOfTrees[i]][mdLength];
+ nextTreehash[i - 1] = new Treehash[heightOfTrees[i] - K[i]];
+ }
+
+ currentStack[i] = new Vector();
+ if (i > 0)
+ {
+ nextStack[i - 1] = new Vector();
+ }
+ }
+
+ // initialize roots
+ byte[][] currentRoots = new byte[numLayer][mdLength];
+ byte[][] nextRoots = new byte[numLayer - 1][mdLength];
+ // initialize seeds
+ byte[][] seeds = new byte[numLayer][mdLength];
+ // initialize seeds[] by copying starting-seeds of first trees of each
+ // layer
+ for (int i = 0; i < numLayer; i++)
+ {
+ System.arraycopy(currentSeeds[i], 0, seeds[i], 0, mdLength);
+ }
+
+ // initialize rootSigs
+ currentRootSigs = new byte[numLayer - 1][mdLength];
+
+ // -------------------------
+ // -------------------------
+ // --- calculation of current authpaths and current rootsigs (AUTHPATHS,
+ // SIG)------
+ // from bottom up to the root
+ for (int h = numLayer - 1; h >= 0; h--)
+ {
+ GMSSRootCalc tree = new GMSSRootCalc(this.heightOfTrees[h], this.K[h], digestProvider);
+ try
+ {
+ // on lowest layer no lower root is available, so just call
+ // the method with null as first parameter
+ if (h == numLayer - 1)
+ {
+ tree = this.generateCurrentAuthpathAndRoot(null, currentStack[h], seeds[h], h);
+ }
+ else
+ // otherwise call the method with the former computed root
+ // value
+ {
+ tree = this.generateCurrentAuthpathAndRoot(currentRoots[h + 1], currentStack[h], seeds[h], h);
+ }
+
+ }
+ catch (Exception e1)
+ {
+ e1.printStackTrace();
+ }
+
+ // set initial values needed for the private key construction
+ for (int i = 0; i < heightOfTrees[h]; i++)
+ {
+ System.arraycopy(tree.getAuthPath()[i], 0, currentAuthPaths[h][i], 0, mdLength);
+ }
+ currentRetain[h] = tree.getRetain();
+ currentTreehash[h] = tree.getTreehash();
+ System.arraycopy(tree.getRoot(), 0, currentRoots[h], 0, mdLength);
+ }
+
+ // --- calculation of next authpaths and next roots (AUTHPATHS+, ROOTS+)
+ // ------
+ for (int h = numLayer - 2; h >= 0; h--)
+ {
+ GMSSRootCalc tree = this.generateNextAuthpathAndRoot(nextStack[h], seeds[h + 1], h + 1);
+
+ // set initial values needed for the private key construction
+ for (int i = 0; i < heightOfTrees[h + 1]; i++)
+ {
+ System.arraycopy(tree.getAuthPath()[i], 0, nextAuthPaths[h][i], 0, mdLength);
+ }
+ nextRetain[h] = tree.getRetain();
+ nextTreehash[h] = tree.getTreehash();
+ System.arraycopy(tree.getRoot(), 0, nextRoots[h], 0, mdLength);
+
+ // create seed for the Merkle tree after next (nextNextSeeds)
+ // SEEDs++
+ System.arraycopy(seeds[h + 1], 0, this.nextNextSeeds[h], 0, mdLength);
+ }
+ // ------------
+
+ // generate JDKGMSSPublicKey
+ GMSSPublicKeyParameters publicKey = new GMSSPublicKeyParameters(currentRoots[0], gmssPS);
+
+ // generate the JDKGMSSPrivateKey
+ GMSSPrivateKeyParameters privateKey = new GMSSPrivateKeyParameters(currentSeeds, nextNextSeeds, currentAuthPaths,
+ nextAuthPaths, currentTreehash, nextTreehash, currentStack, nextStack, currentRetain, nextRetain, nextRoots, currentRootSigs, gmssPS, digestProvider);
+
+ // return the KeyPair
+ return (new AsymmetricCipherKeyPair(publicKey, privateKey));
+ }
+
+ /**
+ * calculates the authpath for tree in layer h which starts with seed[h]
+ * additionally computes the rootSignature of underlaying root
+ *
+ * @param currentStack stack used for the treehash instance created by this method
+ * @param lowerRoot stores the root of the lower tree
+ * @param seed starting seeds
+ * @param h actual layer
+ */
+ private GMSSRootCalc generateCurrentAuthpathAndRoot(byte[] lowerRoot, Vector currentStack, byte[] seed, int h)
+ {
+ byte[] help = new byte[mdLength];
+
+ byte[] OTSseed = new byte[mdLength];
+ OTSseed = gmssRandom.nextSeed(seed);
+
+ WinternitzOTSignature ots;
+
+ // data structure that constructs the whole tree and stores
+ // the initial values for treehash, Auth and retain
+ GMSSRootCalc treeToConstruct = new GMSSRootCalc(this.heightOfTrees[h], this.K[h], digestProvider);
+
+ treeToConstruct.initialize(currentStack);
+
+ // generate the first leaf
+ if (h == numLayer - 1)
+ {
+ ots = new WinternitzOTSignature(OTSseed, digestProvider.get(), otsIndex[h]);
+ help = ots.getPublicKey();
+ }
+ else
+ {
+ // for all layers except the lowest, generate the signature of the
+ // underlying root
+ // and reuse this signature to compute the first leaf of acual layer
+ // more efficiently (by verifiing the signature)
+ ots = new WinternitzOTSignature(OTSseed, digestProvider.get(), otsIndex[h]);
+ currentRootSigs[h] = ots.getSignature(lowerRoot);
+ WinternitzOTSVerify otsver = new WinternitzOTSVerify(digestProvider.get(), otsIndex[h]);
+ help = otsver.Verify(lowerRoot, currentRootSigs[h]);
+ }
+ // update the tree with the first leaf
+ treeToConstruct.update(help);
+
+ int seedForTreehashIndex = 3;
+ int count = 0;
+
+ // update the tree 2^(H) - 1 times, from the second to the last leaf
+ for (int i = 1; i < (1 << this.heightOfTrees[h]); i++)
+ {
+ // initialize the seeds for the leaf generation with index 3 * 2^h
+ if (i == seedForTreehashIndex && count < this.heightOfTrees[h] - this.K[h])
+ {
+ treeToConstruct.initializeTreehashSeed(seed, count);
+ seedForTreehashIndex *= 2;
+ count++;
+ }
+
+ OTSseed = gmssRandom.nextSeed(seed);
+ ots = new WinternitzOTSignature(OTSseed, digestProvider.get(), otsIndex[h]);
+ treeToConstruct.update(ots.getPublicKey());
+ }
+
+ if (treeToConstruct.wasFinished())
+ {
+ return treeToConstruct;
+ }
+ System.err.println("Baum noch nicht fertig konstruiert!!!");
+ return null;
+ }
+
+ /**
+ * calculates the authpath and root for tree in layer h which starts with
+ * seed[h]
+ *
+ * @param nextStack stack used for the treehash instance created by this method
+ * @param seed starting seeds
+ * @param h actual layer
+ */
+ private GMSSRootCalc generateNextAuthpathAndRoot(Vector nextStack, byte[] seed, int h)
+ {
+ byte[] OTSseed = new byte[numLayer];
+ WinternitzOTSignature ots;
+
+ // data structure that constructs the whole tree and stores
+ // the initial values for treehash, Auth and retain
+ GMSSRootCalc treeToConstruct = new GMSSRootCalc(this.heightOfTrees[h], this.K[h], this.digestProvider);
+ treeToConstruct.initialize(nextStack);
+
+ int seedForTreehashIndex = 3;
+ int count = 0;
+
+ // update the tree 2^(H) times, from the first to the last leaf
+ for (int i = 0; i < (1 << this.heightOfTrees[h]); i++)
+ {
+ // initialize the seeds for the leaf generation with index 3 * 2^h
+ if (i == seedForTreehashIndex && count < this.heightOfTrees[h] - this.K[h])
+ {
+ treeToConstruct.initializeTreehashSeed(seed, count);
+ seedForTreehashIndex *= 2;
+ count++;
+ }
+
+ OTSseed = gmssRandom.nextSeed(seed);
+ ots = new WinternitzOTSignature(OTSseed, digestProvider.get(), otsIndex[h]);
+ treeToConstruct.update(ots.getPublicKey());
+ }
+
+ if (treeToConstruct.wasFinished())
+ {
+ return treeToConstruct;
+ }
+ System.err.println("N�chster Baum noch nicht fertig konstruiert!!!");
+ return null;
+ }
+
+ /**
+ * This method initializes the GMSS KeyPairGenerator using an integer value
+ * <code>keySize</code> as input. It provides a simple use of the GMSS for
+ * testing demands.
+ * <p>
+ * A given <code>keysize</code> of less than 10 creates an amount 2^10
+ * signatures. A keySize between 10 and 20 creates 2^20 signatures. Given an
+ * integer greater than 20 the key pair generator creates 2^40 signatures.
+ *
+ * @param keySize Assigns the parameters used for the GMSS signatures. There are
+ * 3 choices:<br>
+ * 1. keysize &lt;= 10: creates 2^10 signatures using the
+ * parameterset<br>
+ * P = (2, (5, 5), (3, 3), (3, 3))<br>
+ * 2. keysize &gt; 10 and &lt;= 20: creates 2^20 signatures using the
+ * parameterset<br>
+ * P = (2, (10, 10), (5, 4), (2, 2))<br>
+ * 3. keysize &gt; 20: creates 2^40 signatures using the
+ * parameterset<br>
+ * P = (2, (10, 10, 10, 10), (9, 9, 9, 3), (2, 2, 2, 2))
+ * @param secureRandom not used by GMSS, the SHA1PRNG of the SUN Provider is always
+ * used
+ */
+ public void initialize(int keySize, SecureRandom secureRandom)
+ {
+
+ KeyGenerationParameters kgp;
+ if (keySize <= 10)
+ { // create 2^10 keys
+ int[] defh = {10};
+ int[] defw = {3};
+ int[] defk = {2};
+ // XXX sec random neede?
+ kgp = new GMSSKeyGenerationParameters(secureRandom, new GMSSParameters(defh.length, defh, defw, defk));
+ }
+ else if (keySize <= 20)
+ { // create 2^20 keys
+ int[] defh = {10, 10};
+ int[] defw = {5, 4};
+ int[] defk = {2, 2};
+ kgp = new GMSSKeyGenerationParameters(secureRandom, new GMSSParameters(defh.length, defh, defw, defk));
+ }
+ else
+ { // create 2^40 keys, keygen lasts around 80 seconds
+ int[] defh = {10, 10, 10, 10};
+ int[] defw = {9, 9, 9, 3};
+ int[] defk = {2, 2, 2, 2};
+ kgp = new GMSSKeyGenerationParameters(secureRandom, new GMSSParameters(defh.length, defh, defw, defk));
+ }
+
+ // call the initializer with the chosen parameters
+ this.initialize(kgp);
+
+ }
+
+
+ /**
+ * Initalizes the key pair generator using a parameter set as input
+ */
+ public void initialize(KeyGenerationParameters param)
+ {
+
+ this.gmssParams = (GMSSKeyGenerationParameters)param;
+
+ // generate GMSSParameterset
+ this.gmssPS = new GMSSParameters(gmssParams.getParameters().getNumOfLayers(), gmssParams.getParameters().getHeightOfTrees(),
+ gmssParams.getParameters().getWinternitzParameter(), gmssParams.getParameters().getK());
+
+ this.numLayer = gmssPS.getNumOfLayers();
+ this.heightOfTrees = gmssPS.getHeightOfTrees();
+ this.otsIndex = gmssPS.getWinternitzParameter();
+ this.K = gmssPS.getK();
+
+ // seeds
+ this.currentSeeds = new byte[numLayer][mdLength];
+ this.nextNextSeeds = new byte[numLayer - 1][mdLength];
+
+ // construct SecureRandom for initial seed generation
+ SecureRandom secRan = new SecureRandom();
+
+ // generation of initial seeds
+ for (int i = 0; i < numLayer; i++)
+ {
+ secRan.nextBytes(currentSeeds[i]);
+ gmssRandom.nextSeed(currentSeeds[i]);
+ }
+
+ this.initialized = true;
+ }
+
+ /**
+ * This method is called by generateKeyPair() in case that no other
+ * initialization method has been called by the user
+ */
+ private void initializeDefault()
+ {
+ int[] defh = {10, 10, 10, 10};
+ int[] defw = {3, 3, 3, 3};
+ int[] defk = {2, 2, 2, 2};
+
+ KeyGenerationParameters kgp = new GMSSKeyGenerationParameters(new SecureRandom(), new GMSSParameters(defh.length, defh, defw, defk));
+ this.initialize(kgp);
+
+ }
+
+ public void init(KeyGenerationParameters param)
+ {
+ this.initialize(param);
+
+ }
+
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+ return genKeyPair();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSKeyParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSKeyParameters.java
new file mode 100644
index 00000000..d2dcbba7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSKeyParameters.java
@@ -0,0 +1,22 @@
+package org.spongycastle.pqc.crypto.gmss;
+
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+
+public class GMSSKeyParameters
+ extends AsymmetricKeyParameter
+{
+ private GMSSParameters params;
+
+ public GMSSKeyParameters(
+ boolean isPrivate,
+ GMSSParameters params)
+ {
+ super(isPrivate);
+ this.params = params;
+ }
+
+ public GMSSParameters getParameters()
+ {
+ return params;
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSLeaf.java b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSLeaf.java
new file mode 100644
index 00000000..ade340ad
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSLeaf.java
@@ -0,0 +1,376 @@
+package org.spongycastle.pqc.crypto.gmss;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.pqc.crypto.gmss.util.GMSSRandom;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+
+
+/**
+ * This class implements the distributed computation of the public key of the
+ * Winternitz one-time signature scheme (OTSS). The class is used by the GMSS
+ * classes for calculation of upcoming leafs.
+ */
+public class GMSSLeaf
+{
+
+ /**
+ * The hash function used by the OTS and the PRNG
+ */
+ private Digest messDigestOTS;
+
+ /**
+ * The length of the message digest and private key
+ */
+ private int mdsize, keysize;
+
+ /**
+ * The source of randomness for OTS private key generation
+ */
+ private GMSSRandom gmssRandom;
+
+ /**
+ * Byte array for distributed computation of the upcoming leaf
+ */
+ private byte[] leaf;
+
+ /**
+ * Byte array for storing the concatenated hashes of private key parts
+ */
+ private byte[] concHashs;
+
+ /**
+ * indices for distributed computation
+ */
+ private int i, j;
+
+ /**
+ * storing 2^w
+ */
+ private int two_power_w;
+
+ /**
+ * Winternitz parameter w
+ */
+ private int w;
+
+ /**
+ * the amount of distributed computation steps when updateLeaf is called
+ */
+ private int steps;
+
+ /**
+ * the internal seed
+ */
+ private byte[] seed;
+
+ /**
+ * the OTS privateKey parts
+ */
+ byte[] privateKeyOTS;
+
+ /**
+ * This constructor regenerates a prior GMSSLeaf object
+ *
+ * @param digest an array of strings, containing the name of the used hash
+ * function and PRNG and the name of the corresponding
+ * provider
+ * @param otsIndex status bytes
+ * @param numLeafs status ints
+ */
+ public GMSSLeaf(Digest digest, byte[][] otsIndex, int[] numLeafs)
+ {
+ this.i = numLeafs[0];
+ this.j = numLeafs[1];
+ this.steps = numLeafs[2];
+ this.w = numLeafs[3];
+
+ messDigestOTS = digest;
+
+ gmssRandom = new GMSSRandom(messDigestOTS);
+
+ // calulate keysize for private key and the help array
+ mdsize = messDigestOTS.getDigestSize();
+ int mdsizeBit = mdsize << 3;
+ int messagesize = (int)Math.ceil((double)(mdsizeBit) / (double)w);
+ int checksumsize = getLog((messagesize << w) + 1);
+ this.keysize = messagesize
+ + (int)Math.ceil((double)checksumsize / (double)w);
+ this.two_power_w = 1 << w;
+
+ // calculate steps
+ // ((2^w)-1)*keysize + keysize + 1 / (2^h -1)
+
+ // initialize arrays
+ this.privateKeyOTS = otsIndex[0];
+ this.seed = otsIndex[1];
+ this.concHashs = otsIndex[2];
+ this.leaf = otsIndex[3];
+ }
+
+ /**
+ * The constructor precomputes some needed variables for distributed leaf
+ * calculation
+ *
+ * @param digest an array of strings, containing the digest of the used hash
+ * function and PRNG and the digest of the corresponding
+ * provider
+ * @param w the winterniz parameter of that tree the leaf is computed
+ * for
+ * @param numLeafs the number of leafs of the tree from where the distributed
+ * computation is called
+ */
+ GMSSLeaf(Digest digest, int w, int numLeafs)
+ {
+ this.w = w;
+
+ messDigestOTS = digest;
+
+ gmssRandom = new GMSSRandom(messDigestOTS);
+
+ // calulate keysize for private key and the help array
+ mdsize = messDigestOTS.getDigestSize();
+ int mdsizeBit = mdsize << 3;
+ int messagesize = (int)Math.ceil((double)(mdsizeBit) / (double)w);
+ int checksumsize = getLog((messagesize << w) + 1);
+ this.keysize = messagesize
+ + (int)Math.ceil((double)checksumsize / (double)w);
+ this.two_power_w = 1 << w;
+
+ // calculate steps
+ // ((2^w)-1)*keysize + keysize + 1 / (2^h -1)
+ this.steps = (int)Math
+ .ceil((double)(((1 << w) - 1) * keysize + 1 + keysize)
+ / (double)(numLeafs));
+
+ // initialize arrays
+ this.seed = new byte[mdsize];
+ this.leaf = new byte[mdsize];
+ this.privateKeyOTS = new byte[mdsize];
+ this.concHashs = new byte[mdsize * keysize];
+ }
+
+ public GMSSLeaf(Digest digest, int w, int numLeafs, byte[] seed0)
+ {
+ this.w = w;
+
+ messDigestOTS = digest;
+
+ gmssRandom = new GMSSRandom(messDigestOTS);
+
+ // calulate keysize for private key and the help array
+ mdsize = messDigestOTS.getDigestSize();
+ int mdsizeBit = mdsize << 3;
+ int messagesize = (int)Math.ceil((double)(mdsizeBit) / (double)w);
+ int checksumsize = getLog((messagesize << w) + 1);
+ this.keysize = messagesize
+ + (int)Math.ceil((double)checksumsize / (double)w);
+ this.two_power_w = 1 << w;
+
+ // calculate steps
+ // ((2^w)-1)*keysize + keysize + 1 / (2^h -1)
+ this.steps = (int)Math
+ .ceil((double)(((1 << w) - 1) * keysize + 1 + keysize)
+ / (double)(numLeafs));
+
+ // initialize arrays
+ this.seed = new byte[mdsize];
+ this.leaf = new byte[mdsize];
+ this.privateKeyOTS = new byte[mdsize];
+ this.concHashs = new byte[mdsize * keysize];
+
+ initLeafCalc(seed0);
+ }
+
+ private GMSSLeaf(GMSSLeaf original)
+ {
+ this.messDigestOTS = original.messDigestOTS;
+ this.mdsize = original.mdsize;
+ this.keysize = original.keysize;
+ this.gmssRandom = original.gmssRandom;
+ this.leaf = Arrays.clone(original.leaf);
+ this.concHashs = Arrays.clone(original.concHashs);
+ this.i = original.i;
+ this.j = original.j;
+ this.two_power_w = original.two_power_w;
+ this.w = original.w;
+ this.steps = original.steps;
+ this.seed = Arrays.clone(original.seed);
+ this.privateKeyOTS = Arrays.clone(original.privateKeyOTS);
+ }
+
+ /**
+ * initialize the distributed leaf calculation reset i,j and compute OTSseed
+ * with seed0
+ *
+ * @param seed0 the starting seed
+ */
+ // TODO: this really looks like it should be either always called from a constructor or nextLeaf.
+ void initLeafCalc(byte[] seed0)
+ {
+ this.i = 0;
+ this.j = 0;
+ byte[] dummy = new byte[mdsize];
+ System.arraycopy(seed0, 0, dummy, 0, seed.length);
+ this.seed = gmssRandom.nextSeed(dummy);
+ }
+
+ GMSSLeaf nextLeaf()
+ {
+ GMSSLeaf nextLeaf = new GMSSLeaf(this);
+
+ nextLeaf.updateLeafCalc();
+
+ return nextLeaf;
+ }
+
+ /**
+ * Processes <code>steps</code> steps of distributed leaf calculation
+ *
+ * @return true if leaf is completed, else false
+ */
+ private void updateLeafCalc()
+ {
+ byte[] buf = new byte[messDigestOTS.getDigestSize()];
+
+ // steps times do
+ // TODO: this really needs to be looked at, the 10000 has been added as
+ // prior to this the leaf value always ended up as zeros.
+ for (int s = 0; s < steps + 10000; s++)
+ {
+ if (i == keysize && j == two_power_w - 1)
+ { // [3] at last hash the
+ // concatenation
+ messDigestOTS.update(concHashs, 0, concHashs.length);
+ leaf = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(leaf, 0);
+ return;
+ }
+ else if (i == 0 || j == two_power_w - 1)
+ { // [1] at the
+ // beginning and
+ // when [2] is
+ // finished: get the
+ // next private key
+ // part
+ i++;
+ j = 0;
+ // get next privKey part
+ this.privateKeyOTS = gmssRandom.nextSeed(seed);
+ }
+ else
+ { // [2] hash the privKey part
+ messDigestOTS.update(privateKeyOTS, 0, privateKeyOTS.length);
+ privateKeyOTS = buf;
+ messDigestOTS.doFinal(privateKeyOTS, 0);
+ j++;
+ if (j == two_power_w - 1)
+ { // after w hashes add to the
+ // concatenated array
+ System.arraycopy(privateKeyOTS, 0, concHashs, mdsize
+ * (i - 1), mdsize);
+ }
+ }
+ }
+
+ throw new IllegalStateException("unable to updateLeaf in steps: " + steps + " " + i + " " + j);
+ }
+
+ /**
+ * Returns the leaf value.
+ *
+ * @return the leaf value
+ */
+ public byte[] getLeaf()
+ {
+ return Arrays.clone(leaf);
+ }
+
+ /**
+ * This method returns the least integer that is greater or equal to the
+ * logarithm to the base 2 of an integer <code>intValue</code>.
+ *
+ * @param intValue an integer
+ * @return The least integer greater or equal to the logarithm to the base 2
+ * of <code>intValue</code>
+ */
+ private int getLog(int intValue)
+ {
+ int log = 1;
+ int i = 2;
+ while (i < intValue)
+ {
+ i <<= 1;
+ log++;
+ }
+ return log;
+ }
+
+ /**
+ * Returns the status byte array used by the GMSSPrivateKeyASN.1 class
+ *
+ * @return The status bytes
+ */
+ public byte[][] getStatByte()
+ {
+
+ byte[][] statByte = new byte[4][];
+ statByte[0] = new byte[mdsize];
+ statByte[1] = new byte[mdsize];
+ statByte[2] = new byte[mdsize * keysize];
+ statByte[3] = new byte[mdsize];
+ statByte[0] = privateKeyOTS;
+ statByte[1] = seed;
+ statByte[2] = concHashs;
+ statByte[3] = leaf;
+
+ return statByte;
+ }
+
+ /**
+ * Returns the status int array used by the GMSSPrivateKeyASN.1 class
+ *
+ * @return The status ints
+ */
+ public int[] getStatInt()
+ {
+
+ int[] statInt = new int[4];
+ statInt[0] = i;
+ statInt[1] = j;
+ statInt[2] = steps;
+ statInt[3] = w;
+ return statInt;
+ }
+
+ /**
+ * Returns a String representation of the main part of this element
+ *
+ * @return a String representation of the main part of this element
+ */
+ public String toString()
+ {
+ String out = "";
+
+ for (int i = 0; i < 4; i++)
+ {
+ out = out + this.getStatInt()[i] + " ";
+ }
+ out = out + " " + this.mdsize + " " + this.keysize + " "
+ + this.two_power_w + " ";
+
+ byte[][] temp = this.getStatByte();
+ for (int i = 0; i < 4; i++)
+ {
+ if (temp[i] != null)
+ {
+ out = out + new String(Hex.encode(temp[i])) + " ";
+ }
+ else
+ {
+ out = out + "null ";
+ }
+ }
+ return out;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSParameters.java
new file mode 100644
index 00000000..c78d50e3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSParameters.java
@@ -0,0 +1,155 @@
+package org.spongycastle.pqc.crypto.gmss;
+
+import org.spongycastle.util.Arrays;
+
+/**
+ * This class provides a specification for the GMSS parameters that are used by
+ * the GMSSKeyPairGenerator and GMSSSignature classes.
+ *
+ * @see org.spongycastle.pqc.crypto.gmss.GMSSKeyPairGenerator
+ */
+public class GMSSParameters
+{
+ /**
+ * The number of authentication tree layers.
+ */
+ private int numOfLayers;
+
+ /**
+ * The height of the authentication trees of each layer.
+ */
+ private int[] heightOfTrees;
+
+ /**
+ * The Winternitz Parameter 'w' of each layer.
+ */
+ private int[] winternitzParameter;
+
+ /**
+ * The parameter K needed for the authentication path computation
+ */
+ private int[] K;
+
+ /**
+ * The constructor for the parameters of the GMSSKeyPairGenerator.
+ *
+ * @param layers the number of authentication tree layers
+ * @param heightOfTrees the height of the authentication trees
+ * @param winternitzParameter the Winternitz Parameter 'w' of each layer
+ * @param K parameter for authpath computation
+ */
+ public GMSSParameters(int layers, int[] heightOfTrees, int[] winternitzParameter, int[] K)
+ throws IllegalArgumentException
+ {
+ init(layers, heightOfTrees, winternitzParameter, K);
+ }
+
+ private void init(int layers, int[] heightOfTrees,
+ int[] winternitzParameter, int[] K)
+ throws IllegalArgumentException
+ {
+ boolean valid = true;
+ String errMsg = "";
+ this.numOfLayers = layers;
+ if ((numOfLayers != winternitzParameter.length)
+ || (numOfLayers != heightOfTrees.length)
+ || (numOfLayers != K.length))
+ {
+ valid = false;
+ errMsg = "Unexpected parameterset format";
+ }
+ for (int i = 0; i < numOfLayers; i++)
+ {
+ if ((K[i] < 2) || ((heightOfTrees[i] - K[i]) % 2 != 0))
+ {
+ valid = false;
+ errMsg = "Wrong parameter K (K >= 2 and H-K even required)!";
+ }
+
+ if ((heightOfTrees[i] < 4) || (winternitzParameter[i] < 2))
+ {
+ valid = false;
+ errMsg = "Wrong parameter H or w (H > 3 and w > 1 required)!";
+ }
+ }
+
+ if (valid)
+ {
+ this.heightOfTrees = Arrays.clone(heightOfTrees);
+ this.winternitzParameter = Arrays.clone(winternitzParameter);
+ this.K = Arrays.clone(K);
+ }
+ else
+ {
+ throw new IllegalArgumentException(errMsg);
+ }
+ }
+
+ public GMSSParameters(int keySize)
+ throws IllegalArgumentException
+ {
+ if (keySize <= 10)
+ { // create 2^10 keys
+ int[] defh = {10};
+ int[] defw = {3};
+ int[] defk = {2};
+ this.init(defh.length, defh, defw, defk);
+ }
+ else if (keySize <= 20)
+ { // create 2^20 keys
+ int[] defh = {10, 10};
+ int[] defw = {5, 4};
+ int[] defk = {2, 2};
+ this.init(defh.length, defh, defw, defk);
+ }
+ else
+ { // create 2^40 keys, keygen lasts around 80 seconds
+ int[] defh = {10, 10, 10, 10};
+ int[] defw = {9, 9, 9, 3};
+ int[] defk = {2, 2, 2, 2};
+ this.init(defh.length, defh, defw, defk);
+ }
+ }
+
+ /**
+ * Returns the number of levels of the authentication trees.
+ *
+ * @return The number of levels of the authentication trees.
+ */
+ public int getNumOfLayers()
+ {
+ return numOfLayers;
+ }
+
+ /**
+ * Returns the array of height (for each layer) of the authentication trees
+ *
+ * @return The array of height (for each layer) of the authentication trees
+ */
+ public int[] getHeightOfTrees()
+ {
+ return Arrays.clone(heightOfTrees);
+ }
+
+ /**
+ * Returns the array of WinternitzParameter (for each layer) of the
+ * authentication trees
+ *
+ * @return The array of WinternitzParameter (for each layer) of the
+ * authentication trees
+ */
+ public int[] getWinternitzParameter()
+ {
+ return Arrays.clone(winternitzParameter);
+ }
+
+ /**
+ * Returns the parameter K needed for authentication path computation
+ *
+ * @return The parameter K needed for authentication path computation
+ */
+ public int[] getK()
+ {
+ return Arrays.clone(K);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSPrivateKeyParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSPrivateKeyParameters.java
new file mode 100644
index 00000000..29e84b1f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSPrivateKeyParameters.java
@@ -0,0 +1,1041 @@
+package org.spongycastle.pqc.crypto.gmss;
+
+import java.util.Vector;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.pqc.crypto.gmss.util.GMSSRandom;
+import org.spongycastle.pqc.crypto.gmss.util.WinternitzOTSignature;
+import org.spongycastle.util.Arrays;
+
+
+/**
+ * This class provides a specification for a GMSS private key.
+ */
+public class GMSSPrivateKeyParameters
+ extends GMSSKeyParameters
+{
+ private int[] index;
+
+ private byte[][] currentSeeds;
+ private byte[][] nextNextSeeds;
+
+ private byte[][][] currentAuthPaths;
+ private byte[][][] nextAuthPaths;
+
+ private Treehash[][] currentTreehash;
+ private Treehash[][] nextTreehash;
+
+ private Vector[] currentStack;
+ private Vector[] nextStack;
+
+ private Vector[][] currentRetain;
+ private Vector[][] nextRetain;
+
+ private byte[][][] keep;
+
+ private GMSSLeaf[] nextNextLeaf;
+ private GMSSLeaf[] upperLeaf;
+ private GMSSLeaf[] upperTreehashLeaf;
+
+ private int[] minTreehash;
+
+ private GMSSParameters gmssPS;
+
+ private byte[][] nextRoot;
+ private GMSSRootCalc[] nextNextRoot;
+
+ private byte[][] currentRootSig;
+ private GMSSRootSig[] nextRootSig;
+
+ private GMSSDigestProvider digestProvider;
+
+ private boolean used = false;
+
+ /**
+ * An array of the heights of the authentication trees of each layer
+ */
+ private int[] heightOfTrees;
+
+ /**
+ * An array of the Winternitz parameter 'w' of each layer
+ */
+ private int[] otsIndex;
+
+ /**
+ * The parameter K needed for the authentication path computation
+ */
+ private int[] K;
+
+ /**
+ * the number of Layers
+ */
+ private int numLayer;
+
+ /**
+ * The hash function used to construct the authentication trees
+ */
+ private Digest messDigestTrees;
+
+ /**
+ * The message digest length
+ */
+ private int mdLength;
+
+ /**
+ * The PRNG used for private key generation
+ */
+ private GMSSRandom gmssRandom;
+
+
+ /**
+ * The number of leafs of one tree of each layer
+ */
+ private int[] numLeafs;
+
+
+ /**
+ * Generates a new GMSS private key
+ *
+ * @param currentSeed seed for the generation of private OTS keys for the
+ * current subtrees
+ * @param nextNextSeed seed for the generation of private OTS keys for the next
+ * subtrees
+ * @param currentAuthPath array of current authentication paths
+ * @param nextAuthPath array of next authentication paths
+ * @param currentTreehash array of current treehash instances
+ * @param nextTreehash array of next treehash instances
+ * @param currentStack array of current shared stacks
+ * @param nextStack array of next shared stacks
+ * @param currentRetain array of current retain stacks
+ * @param nextRetain array of next retain stacks
+ * @param nextRoot the roots of the next subtree
+ * @param currentRootSig array of signatures of the roots of the current subtrees
+ * @param gmssParameterset the GMSS Parameterset
+ * @see org.spongycastle.pqc.crypto.gmss.GMSSKeyPairGenerator
+ */
+
+ public GMSSPrivateKeyParameters(byte[][] currentSeed, byte[][] nextNextSeed,
+ byte[][][] currentAuthPath, byte[][][] nextAuthPath,
+ Treehash[][] currentTreehash, Treehash[][] nextTreehash,
+ Vector[] currentStack, Vector[] nextStack,
+ Vector[][] currentRetain, Vector[][] nextRetain, byte[][] nextRoot,
+ byte[][] currentRootSig, GMSSParameters gmssParameterset,
+ GMSSDigestProvider digestProvider)
+ {
+ this(null, currentSeed, nextNextSeed, currentAuthPath, nextAuthPath,
+ null, currentTreehash, nextTreehash, currentStack, nextStack,
+ currentRetain, nextRetain, null, null, null, null, nextRoot,
+ null, currentRootSig, null, gmssParameterset, digestProvider);
+ }
+
+ /**
+ * /**
+ *
+ * @param index tree indices
+ * @param keep keep array for the authPath algorithm
+ * @param currentTreehash treehash for authPath algorithm of current tree
+ * @param nextTreehash treehash for authPath algorithm of next tree (TREE+)
+ * @param currentStack shared stack for authPath algorithm of current tree
+ * @param nextStack shared stack for authPath algorithm of next tree (TREE+)
+ * @param currentRetain retain stack for authPath algorithm of current tree
+ * @param nextRetain retain stack for authPath algorithm of next tree (TREE+)
+ * @param nextNextLeaf array of upcoming leafs of the tree after next (LEAF++) of
+ * each layer
+ * @param upperLeaf needed for precomputation of upper nodes
+ * @param upperTreehashLeaf needed for precomputation of upper treehash nodes
+ * @param minTreehash index of next treehash instance to receive an update
+ * @param nextRoot the roots of the next trees (ROOT+)
+ * @param nextNextRoot the roots of the tree after next (ROOT++)
+ * @param currentRootSig array of signatures of the roots of the current subtrees
+ * (SIG)
+ * @param nextRootSig array of signatures of the roots of the next subtree
+ * (SIG+)
+ * @param gmssParameterset the GMSS Parameterset
+ */
+ public GMSSPrivateKeyParameters(int[] index, byte[][] currentSeeds,
+ byte[][] nextNextSeeds, byte[][][] currentAuthPaths,
+ byte[][][] nextAuthPaths, byte[][][] keep,
+ Treehash[][] currentTreehash, Treehash[][] nextTreehash,
+ Vector[] currentStack, Vector[] nextStack,
+ Vector[][] currentRetain, Vector[][] nextRetain,
+ GMSSLeaf[] nextNextLeaf, GMSSLeaf[] upperLeaf,
+ GMSSLeaf[] upperTreehashLeaf, int[] minTreehash, byte[][] nextRoot,
+ GMSSRootCalc[] nextNextRoot, byte[][] currentRootSig,
+ GMSSRootSig[] nextRootSig, GMSSParameters gmssParameterset,
+ GMSSDigestProvider digestProvider)
+ {
+
+ super(true, gmssParameterset);
+
+ // construct message digest
+
+ this.messDigestTrees = digestProvider.get();
+ this.mdLength = messDigestTrees.getDigestSize();
+
+
+ // Parameter
+ this.gmssPS = gmssParameterset;
+ this.otsIndex = gmssParameterset.getWinternitzParameter();
+ this.K = gmssParameterset.getK();
+ this.heightOfTrees = gmssParameterset.getHeightOfTrees();
+ // initialize numLayer
+ this.numLayer = gmssPS.getNumOfLayers();
+
+ // initialize index if null
+ if (index == null)
+ {
+ this.index = new int[numLayer];
+ for (int i = 0; i < numLayer; i++)
+ {
+ this.index[i] = 0;
+ }
+ }
+ else
+ {
+ this.index = index;
+ }
+
+ this.currentSeeds = currentSeeds;
+ this.nextNextSeeds = nextNextSeeds;
+
+ this.currentAuthPaths = currentAuthPaths;
+ this.nextAuthPaths = nextAuthPaths;
+
+ // initialize keep if null
+ if (keep == null)
+ {
+ this.keep = new byte[numLayer][][];
+ for (int i = 0; i < numLayer; i++)
+ {
+ this.keep[i] = new byte[(int)Math.floor(heightOfTrees[i] / 2)][mdLength];
+ }
+ }
+ else
+ {
+ this.keep = keep;
+ }
+
+ // initialize stack if null
+ if (currentStack == null)
+ {
+ this.currentStack = new Vector[numLayer];
+ for (int i = 0; i < numLayer; i++)
+ {
+ this.currentStack[i] = new Vector();
+ }
+ }
+ else
+ {
+ this.currentStack = currentStack;
+ }
+
+ // initialize nextStack if null
+ if (nextStack == null)
+ {
+ this.nextStack = new Vector[numLayer - 1];
+ for (int i = 0; i < numLayer - 1; i++)
+ {
+ this.nextStack[i] = new Vector();
+ }
+ }
+ else
+ {
+ this.nextStack = nextStack;
+ }
+
+ this.currentTreehash = currentTreehash;
+ this.nextTreehash = nextTreehash;
+
+ this.currentRetain = currentRetain;
+ this.nextRetain = nextRetain;
+
+ this.nextRoot = nextRoot;
+
+ this.digestProvider = digestProvider;
+
+ if (nextNextRoot == null)
+ {
+ this.nextNextRoot = new GMSSRootCalc[numLayer - 1];
+ for (int i = 0; i < numLayer - 1; i++)
+ {
+ this.nextNextRoot[i] = new GMSSRootCalc(
+ this.heightOfTrees[i + 1], this.K[i + 1], this.digestProvider);
+ }
+ }
+ else
+ {
+ this.nextNextRoot = nextNextRoot;
+ }
+ this.currentRootSig = currentRootSig;
+
+ // calculate numLeafs
+ numLeafs = new int[numLayer];
+ for (int i = 0; i < numLayer; i++)
+ {
+ numLeafs[i] = 1 << heightOfTrees[i];
+ }
+ // construct PRNG
+ this.gmssRandom = new GMSSRandom(messDigestTrees);
+
+ if (numLayer > 1)
+ {
+ // construct the nextNextLeaf (LEAFs++) array for upcoming leafs in
+ // tree after next (TREE++)
+ if (nextNextLeaf == null)
+ {
+ this.nextNextLeaf = new GMSSLeaf[numLayer - 2];
+ for (int i = 0; i < numLayer - 2; i++)
+ {
+ this.nextNextLeaf[i] = new GMSSLeaf(digestProvider.get(), otsIndex[i + 1], numLeafs[i + 2], this.nextNextSeeds[i]);
+ }
+ }
+ else
+ {
+ this.nextNextLeaf = nextNextLeaf;
+ }
+ }
+ else
+ {
+ this.nextNextLeaf = new GMSSLeaf[0];
+ }
+
+ // construct the upperLeaf array for upcoming leafs in tree over the
+ // actual
+ if (upperLeaf == null)
+ {
+ this.upperLeaf = new GMSSLeaf[numLayer - 1];
+ for (int i = 0; i < numLayer - 1; i++)
+ {
+ this.upperLeaf[i] = new GMSSLeaf(digestProvider.get(), otsIndex[i],
+ numLeafs[i + 1], this.currentSeeds[i]);
+ }
+ }
+ else
+ {
+ this.upperLeaf = upperLeaf;
+ }
+
+ // construct the leafs for upcoming leafs in treehashs in tree over the
+ // actual
+ if (upperTreehashLeaf == null)
+ {
+ this.upperTreehashLeaf = new GMSSLeaf[numLayer - 1];
+ for (int i = 0; i < numLayer - 1; i++)
+ {
+ this.upperTreehashLeaf[i] = new GMSSLeaf(digestProvider.get(), otsIndex[i], numLeafs[i + 1]);
+ }
+ }
+ else
+ {
+ this.upperTreehashLeaf = upperTreehashLeaf;
+ }
+
+ if (minTreehash == null)
+ {
+ this.minTreehash = new int[numLayer - 1];
+ for (int i = 0; i < numLayer - 1; i++)
+ {
+ this.minTreehash[i] = -1;
+ }
+ }
+ else
+ {
+ this.minTreehash = minTreehash;
+ }
+
+ // construct the nextRootSig (RootSig++)
+ byte[] dummy = new byte[mdLength];
+ byte[] OTSseed = new byte[mdLength];
+ if (nextRootSig == null)
+ {
+ this.nextRootSig = new GMSSRootSig[numLayer - 1];
+ for (int i = 0; i < numLayer - 1; i++)
+ {
+ System.arraycopy(currentSeeds[i], 0, dummy, 0, mdLength);
+ gmssRandom.nextSeed(dummy);
+ OTSseed = gmssRandom.nextSeed(dummy);
+ this.nextRootSig[i] = new GMSSRootSig(digestProvider.get(), otsIndex[i],
+ heightOfTrees[i + 1]);
+ this.nextRootSig[i].initSign(OTSseed, nextRoot[i]);
+ }
+ }
+ else
+ {
+ this.nextRootSig = nextRootSig;
+ }
+ }
+
+ // we assume this only gets called from nextKey so used is never copied.
+ private GMSSPrivateKeyParameters(GMSSPrivateKeyParameters original)
+ {
+ super(true, original.getParameters());
+
+ this.index = Arrays.clone(original.index);
+ this.currentSeeds = Arrays.clone(original.currentSeeds);
+ this.nextNextSeeds = Arrays.clone(original.nextNextSeeds);
+ this.currentAuthPaths = Arrays.clone(original.currentAuthPaths);
+ this.nextAuthPaths = Arrays.clone(original.nextAuthPaths);
+ this.currentTreehash = original.currentTreehash;
+ this.nextTreehash = original.nextTreehash;
+ this.currentStack = original.currentStack;
+ this.nextStack = original.nextStack;
+ this.currentRetain = original.currentRetain;
+ this.nextRetain = original.nextRetain;
+ this.keep = Arrays.clone(original.keep);
+ this.nextNextLeaf = original.nextNextLeaf;
+ this.upperLeaf = original.upperLeaf;
+ this.upperTreehashLeaf = original.upperTreehashLeaf;
+ this.minTreehash = original.minTreehash;
+ this.gmssPS = original.gmssPS;
+ this.nextRoot = Arrays.clone(original.nextRoot);
+ this.nextNextRoot = original.nextNextRoot;
+ this.currentRootSig = original.currentRootSig;
+ this.nextRootSig = original.nextRootSig;
+ this.digestProvider = original.digestProvider;
+ this.heightOfTrees = original.heightOfTrees;
+ this.otsIndex = original.otsIndex;
+ this.K = original.K;
+ this.numLayer = original.numLayer;
+ this.messDigestTrees = original.messDigestTrees;
+ this.mdLength = original.mdLength;
+ this.gmssRandom = original.gmssRandom;
+ this.numLeafs = original.numLeafs;
+ }
+
+ public boolean isUsed()
+ {
+ return this.used;
+ }
+
+ public void markUsed()
+ {
+ this.used = true;
+ }
+
+ public GMSSPrivateKeyParameters nextKey()
+ {
+ GMSSPrivateKeyParameters nKey = new GMSSPrivateKeyParameters(this);
+
+ nKey.nextKey(gmssPS.getNumOfLayers() - 1);
+
+ return nKey;
+ }
+
+ /**
+ * This method updates the GMSS private key for the next signature
+ *
+ * @param layer the layer where the next key is processed
+ */
+ private void nextKey(int layer)
+ {
+ // only for lowest layer ( other layers indices are raised in nextTree()
+ // method )
+ if (layer == numLayer - 1)
+ {
+ index[layer]++;
+ } // else System.out.println(" --- nextKey on layer " + layer + "
+ // index is now : " + index[layer]);
+
+ // if tree of this layer is depleted
+ if (index[layer] == numLeafs[layer])
+ {
+ if (numLayer != 1)
+ {
+ nextTree(layer);
+ index[layer] = 0;
+ }
+ }
+ else
+ {
+ updateKey(layer);
+ }
+ }
+
+ /**
+ * Switch to next subtree if the current one is depleted
+ *
+ * @param layer the layer where the next tree is processed
+ */
+ private void nextTree(int layer)
+ {
+ // System.out.println("NextTree method called on layer " + layer);
+ // dont create next tree for the top layer
+ if (layer > 0)
+ {
+ // raise index for upper layer
+ index[layer - 1]++;
+
+ // test if it is already the last tree
+ boolean lastTree = true;
+ int z = layer;
+ do
+ {
+ z--;
+ if (index[z] < numLeafs[z])
+ {
+ lastTree = false;
+ }
+ }
+ while (lastTree && (z > 0));
+
+ // only construct next subtree if last one is not already in use
+ if (!lastTree)
+ {
+ gmssRandom.nextSeed(currentSeeds[layer]);
+
+ // last step of distributed signature calculation
+ nextRootSig[layer - 1].updateSign();
+
+ // last step of distributed leaf calculation for nextNextLeaf
+ if (layer > 1)
+ {
+ nextNextLeaf[layer - 1 - 1] = nextNextLeaf[layer - 1 - 1].nextLeaf();
+ }
+
+ // last step of distributed leaf calculation for upper leaf
+ upperLeaf[layer - 1] = upperLeaf[layer - 1].nextLeaf();
+
+ // last step of distributed leaf calculation for all treehashs
+
+ if (minTreehash[layer - 1] >= 0)
+ {
+ upperTreehashLeaf[layer - 1] = upperTreehashLeaf[layer - 1].nextLeaf();
+ byte[] leaf = this.upperTreehashLeaf[layer - 1].getLeaf();
+ // if update is required use the precomputed leaf to update
+ // treehash
+ try
+ {
+ currentTreehash[layer - 1][minTreehash[layer - 1]]
+ .update(this.gmssRandom, leaf);
+ // System.out.println("UUUpdated TH " +
+ // minTreehash[layer - 1]);
+ if (currentTreehash[layer - 1][minTreehash[layer - 1]]
+ .wasFinished())
+ {
+ // System.out.println("FFFinished TH " +
+ // minTreehash[layer - 1]);
+ }
+ }
+ catch (Exception e)
+ {
+ System.out.println(e);
+ }
+ }
+
+ // last step of nextNextAuthRoot calculation
+ this.updateNextNextAuthRoot(layer);
+
+ // ******************************************************** /
+
+ // NOW: advance to next tree on layer 'layer'
+
+ // NextRootSig --> currentRootSigs
+ this.currentRootSig[layer - 1] = nextRootSig[layer - 1]
+ .getSig();
+
+ // -----------------------
+
+ // nextTreehash --> currentTreehash
+ // nextNextTreehash --> nextTreehash
+ for (int i = 0; i < heightOfTrees[layer] - K[layer]; i++)
+ {
+ this.currentTreehash[layer][i] = this.nextTreehash[layer - 1][i];
+ this.nextTreehash[layer - 1][i] = this.nextNextRoot[layer - 1]
+ .getTreehash()[i];
+ }
+
+ // NextAuthPath --> currentAuthPath
+ // nextNextAuthPath --> nextAuthPath
+ for (int i = 0; i < heightOfTrees[layer]; i++)
+ {
+ System.arraycopy(nextAuthPaths[layer - 1][i], 0,
+ currentAuthPaths[layer][i], 0, mdLength);
+ System.arraycopy(nextNextRoot[layer - 1].getAuthPath()[i],
+ 0, nextAuthPaths[layer - 1][i], 0, mdLength);
+ }
+
+ // nextRetain --> currentRetain
+ // nextNextRetain --> nextRetain
+ for (int i = 0; i < K[layer] - 1; i++)
+ {
+ this.currentRetain[layer][i] = this.nextRetain[layer - 1][i];
+ this.nextRetain[layer - 1][i] = this.nextNextRoot[layer - 1]
+ .getRetain()[i];
+ }
+
+ // nextStack --> currentStack
+ this.currentStack[layer] = this.nextStack[layer - 1];
+ // nextNextStack --> nextStack
+ this.nextStack[layer - 1] = this.nextNextRoot[layer - 1]
+ .getStack();
+
+ // nextNextRoot --> nextRoot
+ this.nextRoot[layer - 1] = this.nextNextRoot[layer - 1]
+ .getRoot();
+ // -----------------------
+
+ // -----------------
+ byte[] OTSseed = new byte[mdLength];
+ byte[] dummy = new byte[mdLength];
+ // gmssRandom.setSeed(currentSeeds[layer]);
+ System
+ .arraycopy(currentSeeds[layer - 1], 0, dummy, 0,
+ mdLength);
+ OTSseed = gmssRandom.nextSeed(dummy); // only need OTSSeed
+ OTSseed = gmssRandom.nextSeed(dummy);
+ OTSseed = gmssRandom.nextSeed(dummy);
+ // nextWinSig[layer-1]=new
+ // GMSSWinSig(OTSseed,algNames,otsIndex[layer-1],heightOfTrees[layer],nextRoot[layer-1]);
+ nextRootSig[layer - 1].initSign(OTSseed, nextRoot[layer - 1]);
+
+ // nextKey for upper layer
+ nextKey(layer - 1);
+ }
+ }
+ }
+
+ /**
+ * This method computes the authpath (AUTH) for the current tree,
+ * Additionally the root signature for the next tree (SIG+), the authpath
+ * (AUTH++) and root (ROOT++) for the tree after next in layer
+ * <code>layer</code>, and the LEAF++^1 for the next next tree in the
+ * layer above are updated This method is used by nextKey()
+ *
+ * @param layer
+ */
+ private void updateKey(int layer)
+ {
+ // ----------current tree processing of actual layer---------
+ // compute upcoming authpath for current Tree (AUTH)
+ computeAuthPaths(layer);
+
+ // -----------distributed calculations part------------
+ // not for highest tree layer
+ if (layer > 0)
+ {
+
+ // compute (partial) next leaf on TREE++ (not on layer 1 and 0)
+ if (layer > 1)
+ {
+ nextNextLeaf[layer - 1 - 1] = nextNextLeaf[layer - 1 - 1].nextLeaf();
+ }
+
+ // compute (partial) next leaf on tree above (not on layer 0)
+ upperLeaf[layer - 1] = upperLeaf[layer - 1].nextLeaf();
+
+ // compute (partial) next leaf for all treehashs on tree above (not
+ // on layer 0)
+
+ int t = (int)Math
+ .floor((double)(this.getNumLeafs(layer) * 2)
+ / (double)(this.heightOfTrees[layer - 1] - this.K[layer - 1]));
+
+ if (index[layer] % t == 1)
+ {
+ // System.out.println(" layer: " + layer + " index: " +
+ // index[layer] + " t : " + t);
+
+ // take precomputed node for treehash update
+ // ------------------------------------------------
+ if (index[layer] > 1 && minTreehash[layer - 1] >= 0)
+ {
+ byte[] leaf = this.upperTreehashLeaf[layer - 1].getLeaf();
+ // if update is required use the precomputed leaf to update
+ // treehash
+ try
+ {
+ currentTreehash[layer - 1][minTreehash[layer - 1]]
+ .update(this.gmssRandom, leaf);
+ // System.out.println("Updated TH " + minTreehash[layer
+ // - 1]);
+ if (currentTreehash[layer - 1][minTreehash[layer - 1]]
+ .wasFinished())
+ {
+ // System.out.println("Finished TH " +
+ // minTreehash[layer - 1]);
+ }
+ }
+ catch (Exception e)
+ {
+ System.out.println(e);
+ }
+ // ------------------------------------------------
+ }
+
+ // initialize next leaf precomputation
+ // ------------------------------------------------
+
+ // get lowest index of treehashs
+ this.minTreehash[layer - 1] = getMinTreehashIndex(layer - 1);
+
+ if (this.minTreehash[layer - 1] >= 0)
+ {
+ // initialize leaf
+ byte[] seed = this.currentTreehash[layer - 1][this.minTreehash[layer - 1]]
+ .getSeedActive();
+ this.upperTreehashLeaf[layer - 1] = new GMSSLeaf(
+ this.digestProvider.get(), this.otsIndex[layer - 1], t, seed);
+ this.upperTreehashLeaf[layer - 1] = this.upperTreehashLeaf[layer - 1].nextLeaf();
+ // System.out.println("restarted treehashleaf (" + (layer -
+ // 1) + "," + this.minTreehash[layer - 1] + ")");
+ }
+ // ------------------------------------------------
+
+ }
+ else
+ {
+ // update the upper leaf for the treehash one step
+ if (this.minTreehash[layer - 1] >= 0)
+ {
+ this.upperTreehashLeaf[layer - 1] = this.upperTreehashLeaf[layer - 1].nextLeaf();
+ // if (minTreehash[layer - 1] > 3)
+ // System.out.print("#");
+ }
+ }
+
+ // compute (partial) the signature of ROOT+ (RootSig+) (not on top
+ // layer)
+ nextRootSig[layer - 1].updateSign();
+
+ // compute (partial) AUTHPATH++ & ROOT++ (not on top layer)
+ if (index[layer] == 1)
+ {
+ // init root and authpath calculation for tree after next
+ // (AUTH++, ROOT++)
+ this.nextNextRoot[layer - 1].initialize(new Vector());
+ }
+
+ // update root and authpath calculation for tree after next (AUTH++,
+ // ROOT++)
+ this.updateNextNextAuthRoot(layer);
+ }
+ // ----------- end distributed calculations part-----------------
+ }
+
+ /**
+ * This method returns the index of the next Treehash instance that should
+ * receive an update
+ *
+ * @param layer the layer of the GMSS tree
+ * @return index of the treehash instance that should get the update
+ */
+ private int getMinTreehashIndex(int layer)
+ {
+ int minTreehash = -1;
+ for (int h = 0; h < heightOfTrees[layer] - K[layer]; h++)
+ {
+ if (currentTreehash[layer][h].wasInitialized()
+ && !currentTreehash[layer][h].wasFinished())
+ {
+ if (minTreehash == -1)
+ {
+ minTreehash = h;
+ }
+ else if (currentTreehash[layer][h].getLowestNodeHeight() < currentTreehash[layer][minTreehash]
+ .getLowestNodeHeight())
+ {
+ minTreehash = h;
+ }
+ }
+ }
+ return minTreehash;
+ }
+
+ /**
+ * Computes the upcoming currentAuthpath of layer <code>layer</code> using
+ * the revisited authentication path computation of Dahmen/Schneider 2008
+ *
+ * @param layer the actual layer
+ */
+ private void computeAuthPaths(int layer)
+ {
+
+ int Phi = index[layer];
+ int H = heightOfTrees[layer];
+ int K = this.K[layer];
+
+ // update all nextSeeds for seed scheduling
+ for (int i = 0; i < H - K; i++)
+ {
+ currentTreehash[layer][i].updateNextSeed(gmssRandom);
+ }
+
+ // STEP 1 of Algorithm
+ int Tau = heightOfPhi(Phi);
+
+ byte[] OTSseed = new byte[mdLength];
+ OTSseed = gmssRandom.nextSeed(currentSeeds[layer]);
+
+ // STEP 2 of Algorithm
+ // if phi's parent on height tau + 1 if left node, store auth_tau
+ // in keep_tau.
+ // TODO check it, formerly was
+ // int L = Phi / (int) Math.floor(Math.pow(2, Tau + 1));
+ // L %= 2;
+ int L = (Phi >>> (Tau + 1)) & 1;
+
+ byte[] tempKeep = new byte[mdLength];
+ // store the keep node not in keep[layer][tau/2] because it might be in
+ // use
+ // wait until the space is freed in step 4a
+ if (Tau < H - 1 && L == 0)
+ {
+ System.arraycopy(currentAuthPaths[layer][Tau], 0, tempKeep, 0,
+ mdLength);
+ }
+
+ byte[] help = new byte[mdLength];
+ // STEP 3 of Algorithm
+ // if phi is left child, compute and store leaf for next currentAuthPath
+ // path,
+ // (obtained by veriying current signature)
+ if (Tau == 0)
+ {
+ // LEAFCALC !!!
+ if (layer == numLayer - 1)
+ { // lowest layer computes the
+ // necessary leaf completely at this
+ // time
+ WinternitzOTSignature ots = new WinternitzOTSignature(OTSseed,
+ digestProvider.get(), otsIndex[layer]);
+ help = ots.getPublicKey();
+ }
+ else
+ { // other layers use the precomputed leafs in
+ // nextNextLeaf
+ byte[] dummy = new byte[mdLength];
+ System.arraycopy(currentSeeds[layer], 0, dummy, 0, mdLength);
+ gmssRandom.nextSeed(dummy);
+ help = upperLeaf[layer].getLeaf();
+ this.upperLeaf[layer].initLeafCalc(dummy);
+
+ // WinternitzOTSVerify otsver = new
+ // WinternitzOTSVerify(algNames, otsIndex[layer]);
+ // byte[] help2 = otsver.Verify(currentRoot[layer],
+ // currentRootSig[layer]);
+ // System.out.println(" --- " + layer + " " +
+ // ByteUtils.toHexString(help) + " " +
+ // ByteUtils.toHexString(help2));
+ }
+ System.arraycopy(help, 0, currentAuthPaths[layer][0], 0, mdLength);
+ }
+ else
+ {
+ // STEP 4a of Algorithm
+ // get new left currentAuthPath node on height tau
+ byte[] toBeHashed = new byte[mdLength << 1];
+ System.arraycopy(currentAuthPaths[layer][Tau - 1], 0, toBeHashed,
+ 0, mdLength);
+ // free the shared keep[layer][tau/2]
+ System.arraycopy(keep[layer][(int)Math.floor((Tau - 1) / 2)], 0,
+ toBeHashed, mdLength, mdLength);
+ messDigestTrees.update(toBeHashed, 0, toBeHashed.length);
+ currentAuthPaths[layer][Tau] = new byte[messDigestTrees.getDigestSize()];
+ messDigestTrees.doFinal(currentAuthPaths[layer][Tau], 0);
+
+ // STEP 4b and 4c of Algorithm
+ // copy right nodes to currentAuthPath on height 0..Tau-1
+ for (int i = 0; i < Tau; i++)
+ {
+
+ // STEP 4b of Algorithm
+ // 1st: copy from treehashs
+ if (i < H - K)
+ {
+ if (currentTreehash[layer][i].wasFinished())
+ {
+ System.arraycopy(currentTreehash[layer][i]
+ .getFirstNode(), 0, currentAuthPaths[layer][i],
+ 0, mdLength);
+ currentTreehash[layer][i].destroy();
+ }
+ else
+ {
+ System.err
+ .println("Treehash ("
+ + layer
+ + ","
+ + i
+ + ") not finished when needed in AuthPathComputation");
+ }
+ }
+
+ // 2nd: copy precomputed values from Retain
+ if (i < H - 1 && i >= H - K)
+ {
+ if (currentRetain[layer][i - (H - K)].size() > 0)
+ {
+ // pop element from retain
+ System.arraycopy(currentRetain[layer][i - (H - K)]
+ .lastElement(), 0, currentAuthPaths[layer][i],
+ 0, mdLength);
+ currentRetain[layer][i - (H - K)]
+ .removeElementAt(currentRetain[layer][i
+ - (H - K)].size() - 1);
+ }
+ }
+
+ // STEP 4c of Algorithm
+ // initialize new stack at heights 0..Tau-1
+ if (i < H - K)
+ {
+ // create stacks anew
+ int startPoint = Phi + 3 * (1 << i);
+ if (startPoint < numLeafs[layer])
+ {
+ // if (layer < 2) {
+ // System.out.println("initialized TH " + i + " on layer
+ // " + layer);
+ // }
+ currentTreehash[layer][i].initialize();
+ }
+ }
+ }
+ }
+
+ // now keep space is free to use
+ if (Tau < H - 1 && L == 0)
+ {
+ System.arraycopy(tempKeep, 0,
+ keep[layer][(int)Math.floor(Tau / 2)], 0, mdLength);
+ }
+
+ // only update empty stack at height h if all other stacks have
+ // tailnodes with height >h
+ // finds active stack with lowest node height, choses lower index in
+ // case of tie
+
+ // on the lowest layer leafs must be computed at once, no precomputation
+ // is possible. So all treehash updates are done at once here
+ if (layer == numLayer - 1)
+ {
+ for (int tmp = 1; tmp <= (H - K) / 2; tmp++)
+ {
+ // index of the treehash instance that receives the next update
+ int minTreehash = getMinTreehashIndex(layer);
+
+ // if active treehash is found update with a leaf
+ if (minTreehash >= 0)
+ {
+ try
+ {
+ byte[] seed = new byte[mdLength];
+ System.arraycopy(
+ this.currentTreehash[layer][minTreehash]
+ .getSeedActive(), 0, seed, 0, mdLength);
+ byte[] seed2 = gmssRandom.nextSeed(seed);
+ WinternitzOTSignature ots = new WinternitzOTSignature(
+ seed2, this.digestProvider.get(), this.otsIndex[layer]);
+ byte[] leaf = ots.getPublicKey();
+ currentTreehash[layer][minTreehash].update(
+ this.gmssRandom, leaf);
+ }
+ catch (Exception e)
+ {
+ System.out.println(e);
+ }
+ }
+ }
+ }
+ else
+ { // on higher layers the updates are done later
+ this.minTreehash[layer] = getMinTreehashIndex(layer);
+ }
+ }
+
+ /**
+ * Returns the largest h such that 2^h | Phi
+ *
+ * @param Phi the leaf index
+ * @return The largest <code>h</code> with <code>2^h | Phi</code> if
+ * <code>Phi!=0</code> else return <code>-1</code>
+ */
+ private int heightOfPhi(int Phi)
+ {
+ if (Phi == 0)
+ {
+ return -1;
+ }
+ int Tau = 0;
+ int modul = 1;
+ while (Phi % modul == 0)
+ {
+ modul *= 2;
+ Tau += 1;
+ }
+ return Tau - 1;
+ }
+
+ /**
+ * Updates the authentication path and root calculation for the tree after
+ * next (AUTH++, ROOT++) in layer <code>layer</code>
+ *
+ * @param layer
+ */
+ private void updateNextNextAuthRoot(int layer)
+ {
+
+ byte[] OTSseed = new byte[mdLength];
+ OTSseed = gmssRandom.nextSeed(nextNextSeeds[layer - 1]);
+
+ // get the necessary leaf
+ if (layer == numLayer - 1)
+ { // lowest layer computes the necessary
+ // leaf completely at this time
+ WinternitzOTSignature ots = new WinternitzOTSignature(OTSseed,
+ digestProvider.get(), otsIndex[layer]);
+ this.nextNextRoot[layer - 1].update(nextNextSeeds[layer - 1], ots
+ .getPublicKey());
+ }
+ else
+ { // other layers use the precomputed leafs in nextNextLeaf
+ this.nextNextRoot[layer - 1].update(nextNextSeeds[layer - 1], nextNextLeaf[layer - 1].getLeaf());
+ this.nextNextLeaf[layer - 1].initLeafCalc(nextNextSeeds[layer - 1]);
+ }
+ }
+
+ public int[] getIndex()
+ {
+ return index;
+ }
+
+ /**
+ * @return The current index of layer i
+ */
+ public int getIndex(int i)
+ {
+ return index[i];
+ }
+
+ public byte[][] getCurrentSeeds()
+ {
+ return Arrays.clone(currentSeeds);
+ }
+
+ public byte[][][] getCurrentAuthPaths()
+ {
+ return Arrays.clone(currentAuthPaths);
+ }
+
+ /**
+ * @return The one-time signature of the root of the current subtree
+ */
+ public byte[] getSubtreeRootSig(int i)
+ {
+ return currentRootSig[i];
+ }
+
+
+ public GMSSDigestProvider getName()
+ {
+ return digestProvider;
+ }
+
+ /**
+ * @return The number of leafs of each tree of layer i
+ */
+ public int getNumLeafs(int i)
+ {
+ return numLeafs[i];
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSPublicKeyParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSPublicKeyParameters.java
new file mode 100644
index 00000000..381ed00b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSPublicKeyParameters.java
@@ -0,0 +1,33 @@
+package org.spongycastle.pqc.crypto.gmss;
+
+
+public class GMSSPublicKeyParameters
+ extends GMSSKeyParameters
+{
+ /**
+ * The GMSS public key
+ */
+ private byte[] gmssPublicKey;
+
+ /**
+ * The constructor.
+ *
+ * @param key a raw GMSS public key
+ * @param gmssParameterSet an instance of GMSSParameterset
+ */
+ public GMSSPublicKeyParameters(byte[] key, GMSSParameters gmssParameterSet)
+ {
+ super(false, gmssParameterSet);
+ this.gmssPublicKey = key;
+ }
+
+ /**
+ * Returns the GMSS public key
+ *
+ * @return The GMSS public key
+ */
+ public byte[] getPublicKey()
+ {
+ return gmssPublicKey;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSRootCalc.java b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSRootCalc.java
new file mode 100644
index 00000000..88e87e9c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSRootCalc.java
@@ -0,0 +1,596 @@
+package org.spongycastle.pqc.crypto.gmss;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Integers;
+import org.spongycastle.util.encoders.Hex;
+
+
+/**
+ * This class computes a whole Merkle tree and saves the needed values for
+ * AuthPath computation. It is used for precomputation of the root of a
+ * following tree. After initialization, 2^H updates are required to complete
+ * the root. Every update requires one leaf value as parameter. While computing
+ * the root all initial values for the authentication path algorithm (treehash,
+ * auth, retain) are stored for later use.
+ */
+public class GMSSRootCalc
+{
+
+ /**
+ * max height of the tree
+ */
+ private int heightOfTree;
+
+ /**
+ * length of the messageDigest
+ */
+ private int mdLength;
+
+ /**
+ * the treehash instances of the tree
+ */
+ private Treehash[] treehash;
+
+ /**
+ * stores the retain nodes for authPath computation
+ */
+ private Vector[] retain;
+
+ /**
+ * finally stores the root of the tree when finished
+ */
+ private byte[] root;
+
+ /**
+ * stores the authentication path y_1(i), i = 0..H-1
+ */
+ private byte[][] AuthPath;
+
+ /**
+ * the value K for the authentication path computation
+ */
+ private int K;
+
+ /**
+ * Vector element that stores the nodes on the stack
+ */
+ private Vector tailStack;
+
+ /**
+ * stores the height of all nodes laying on the tailStack
+ */
+ private Vector heightOfNodes;
+ /**
+ * The hash function used for the construction of the authentication trees
+ */
+ private Digest messDigestTree;
+
+ /**
+ * An array of strings containing the name of the hash function used to
+ * construct the authentication trees and used by the OTS.
+ */
+ private GMSSDigestProvider digestProvider;
+
+ /**
+ * stores the index of the current node on each height of the tree
+ */
+ private int[] index;
+
+ /**
+ * true if instance was already initialized, false otherwise
+ */
+ private boolean isInitialized;
+
+ /**
+ * true it instance was finished
+ */
+ private boolean isFinished;
+
+ /**
+ * Integer that stores the index of the next seed that has to be omitted to
+ * the treehashs
+ */
+ private int indexForNextSeed;
+
+ /**
+ * temporary integer that stores the height of the next treehash instance
+ * that gets initialized with a seed
+ */
+ private int heightOfNextSeed;
+
+ /**
+ * This constructor regenerates a prior treehash object
+ *
+ * @param digest an array of strings, containing the digest of the used hash
+ * function and PRNG and the digest of the corresponding
+ * provider
+ * @param statByte status bytes
+ * @param statInt status ints
+ */
+ public GMSSRootCalc(Digest digest, byte[][] statByte, int[] statInt,
+ Treehash[] treeH, Vector[] ret)
+ {
+ this.messDigestTree = digestProvider.get();
+ this.digestProvider = digestProvider;
+ // decode statInt
+ this.heightOfTree = statInt[0];
+ this.mdLength = statInt[1];
+ this.K = statInt[2];
+ this.indexForNextSeed = statInt[3];
+ this.heightOfNextSeed = statInt[4];
+ if (statInt[5] == 1)
+ {
+ this.isFinished = true;
+ }
+ else
+ {
+ this.isFinished = false;
+ }
+ if (statInt[6] == 1)
+ {
+ this.isInitialized = true;
+ }
+ else
+ {
+ this.isInitialized = false;
+ }
+
+ int tailLength = statInt[7];
+
+ this.index = new int[heightOfTree];
+ for (int i = 0; i < heightOfTree; i++)
+ {
+ this.index[i] = statInt[8 + i];
+ }
+
+ this.heightOfNodes = new Vector();
+ for (int i = 0; i < tailLength; i++)
+ {
+ this.heightOfNodes.addElement(Integers.valueOf(statInt[8 + heightOfTree
+ + i]));
+ }
+
+ // decode statByte
+ this.root = statByte[0];
+
+ this.AuthPath = new byte[heightOfTree][mdLength];
+ for (int i = 0; i < heightOfTree; i++)
+ {
+ this.AuthPath[i] = statByte[1 + i];
+ }
+
+ this.tailStack = new Vector();
+ for (int i = 0; i < tailLength; i++)
+ {
+ this.tailStack.addElement(statByte[1 + heightOfTree + i]);
+ }
+
+ // decode treeH
+ this.treehash = GMSSUtils.clone(treeH);
+
+ // decode ret
+ this.retain = GMSSUtils.clone(ret);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param heightOfTree maximal height of the tree
+ * @param digestProvider an array of strings, containing the name of the used hash
+ * function and PRNG and the name of the corresponding
+ * provider
+ */
+ public GMSSRootCalc(int heightOfTree, int K, GMSSDigestProvider digestProvider)
+ {
+ this.heightOfTree = heightOfTree;
+ this.digestProvider = digestProvider;
+ this.messDigestTree = digestProvider.get();
+ this.mdLength = messDigestTree.getDigestSize();
+ this.K = K;
+ this.index = new int[heightOfTree];
+ this.AuthPath = new byte[heightOfTree][mdLength];
+ this.root = new byte[mdLength];
+ // this.treehash = new Treehash[this.heightOfTree - this.K];
+ this.retain = new Vector[this.K - 1];
+ for (int i = 0; i < K - 1; i++)
+ {
+ this.retain[i] = new Vector();
+ }
+
+ }
+
+ /**
+ * Initializes the calculation of a new root
+ *
+ * @param sharedStack the stack shared by all treehash instances of this tree
+ */
+ public void initialize(Vector sharedStack)
+ {
+ this.treehash = new Treehash[this.heightOfTree - this.K];
+ for (int i = 0; i < this.heightOfTree - this.K; i++)
+ {
+ this.treehash[i] = new Treehash(sharedStack, i, this.digestProvider.get());
+ }
+
+ this.index = new int[heightOfTree];
+ this.AuthPath = new byte[heightOfTree][mdLength];
+ this.root = new byte[mdLength];
+
+ this.tailStack = new Vector();
+ this.heightOfNodes = new Vector();
+ this.isInitialized = true;
+ this.isFinished = false;
+
+ for (int i = 0; i < heightOfTree; i++)
+ {
+ this.index[i] = -1;
+ }
+
+ this.retain = new Vector[this.K - 1];
+ for (int i = 0; i < K - 1; i++)
+ {
+ this.retain[i] = new Vector();
+ }
+
+ this.indexForNextSeed = 3;
+ this.heightOfNextSeed = 0;
+ }
+
+ /**
+ * updates the root with one leaf and stores needed values in retain,
+ * treehash or authpath. Additionally counts the seeds used. This method is
+ * used when performing the updates for TREE++.
+ *
+ * @param seed the initial seed for treehash: seedNext
+ * @param leaf the height of the treehash
+ */
+ public void update(byte[] seed, byte[] leaf)
+ {
+ if (this.heightOfNextSeed < (this.heightOfTree - this.K)
+ && this.indexForNextSeed - 2 == index[0])
+ {
+ this.initializeTreehashSeed(seed, this.heightOfNextSeed);
+ this.heightOfNextSeed++;
+ this.indexForNextSeed *= 2;
+ }
+ // now call the simple update
+ this.update(leaf);
+ }
+
+ /**
+ * Updates the root with one leaf and stores the needed values in retain,
+ * treehash or authpath
+ */
+ public void update(byte[] leaf)
+ {
+
+ if (isFinished)
+ {
+ System.out.print("Too much updates for Tree!!");
+ return;
+ }
+ if (!isInitialized)
+ {
+ System.err.println("GMSSRootCalc not initialized!");
+ return;
+ }
+
+ // a new leaf was omitted, so raise index on lowest layer
+ index[0]++;
+
+ // store the nodes on the lowest layer in treehash or authpath
+ if (index[0] == 1)
+ {
+ System.arraycopy(leaf, 0, AuthPath[0], 0, mdLength);
+ }
+ else if (index[0] == 3)
+ {
+ // store in treehash only if K < H
+ if (heightOfTree > K)
+ {
+ treehash[0].setFirstNode(leaf);
+ }
+ }
+
+ if ((index[0] - 3) % 2 == 0 && index[0] >= 3)
+ {
+ // store in retain if K = H
+ if (heightOfTree == K)
+ // TODO: check it
+ {
+ retain[0].insertElementAt(leaf, 0);
+ }
+ }
+
+ // if first update to this tree is made
+ if (index[0] == 0)
+ {
+ tailStack.addElement(leaf);
+ heightOfNodes.addElement(Integers.valueOf(0));
+ }
+ else
+ {
+
+ byte[] help = new byte[mdLength];
+ byte[] toBeHashed = new byte[mdLength << 1];
+
+ // store the new leaf in help
+ System.arraycopy(leaf, 0, help, 0, mdLength);
+ int helpHeight = 0;
+ // while top to nodes have same height
+ while (tailStack.size() > 0
+ && helpHeight == ((Integer)heightOfNodes.lastElement())
+ .intValue())
+ {
+
+ // help <-- hash(stack top element || help)
+ System.arraycopy(tailStack.lastElement(), 0, toBeHashed, 0,
+ mdLength);
+ tailStack.removeElementAt(tailStack.size() - 1);
+ heightOfNodes.removeElementAt(heightOfNodes.size() - 1);
+ System.arraycopy(help, 0, toBeHashed, mdLength, mdLength);
+
+ messDigestTree.update(toBeHashed, 0, toBeHashed.length);
+ help = new byte[messDigestTree.getDigestSize()];
+ messDigestTree.doFinal(help, 0);
+
+ // the new help node is one step higher
+ helpHeight++;
+ if (helpHeight < heightOfTree)
+ {
+ index[helpHeight]++;
+
+ // add index 1 element to initial authpath
+ if (index[helpHeight] == 1)
+ {
+ System.arraycopy(help, 0, AuthPath[helpHeight], 0,
+ mdLength);
+ }
+
+ if (helpHeight >= heightOfTree - K)
+ {
+ if (helpHeight == 0)
+ {
+ System.out.println("M���P");
+ }
+ // add help element to retain stack if it is a right
+ // node
+ // and not stored in treehash
+ if ((index[helpHeight] - 3) % 2 == 0
+ && index[helpHeight] >= 3)
+ // TODO: check it
+ {
+ retain[helpHeight - (heightOfTree - K)]
+ .insertElementAt(help, 0);
+ }
+ }
+ else
+ {
+ // if element is third in his line add it to treehash
+ if (index[helpHeight] == 3)
+ {
+ treehash[helpHeight].setFirstNode(help);
+ }
+ }
+ }
+ }
+ // push help element to the stack
+ tailStack.addElement(help);
+ heightOfNodes.addElement(Integers.valueOf(helpHeight));
+
+ // is the root calculation finished?
+ if (helpHeight == heightOfTree)
+ {
+ isFinished = true;
+ isInitialized = false;
+ root = (byte[])tailStack.lastElement();
+ }
+ }
+
+ }
+
+ /**
+ * initializes the seeds for the treehashs of the tree precomputed by this
+ * class
+ *
+ * @param seed the initial seed for treehash: seedNext
+ * @param index the height of the treehash
+ */
+ public void initializeTreehashSeed(byte[] seed, int index)
+ {
+ treehash[index].initializeSeed(seed);
+ }
+
+ /**
+ * Method to check whether the instance has been initialized or not
+ *
+ * @return true if treehash was already initialized
+ */
+ public boolean wasInitialized()
+ {
+ return isInitialized;
+ }
+
+ /**
+ * Method to check whether the instance has been finished or not
+ *
+ * @return true if tree has reached its maximum height
+ */
+ public boolean wasFinished()
+ {
+ return isFinished;
+ }
+
+ /**
+ * returns the authentication path of the first leaf of the tree
+ *
+ * @return the authentication path of the first leaf of the tree
+ */
+ public byte[][] getAuthPath()
+ {
+ return GMSSUtils.clone(AuthPath);
+ }
+
+ /**
+ * returns the initial treehash instances, storing value y_3(i)
+ *
+ * @return the initial treehash instances, storing value y_3(i)
+ */
+ public Treehash[] getTreehash()
+ {
+ return GMSSUtils.clone(treehash);
+ }
+
+ /**
+ * returns the retain stacks storing all right nodes near to the root
+ *
+ * @return the retain stacks storing all right nodes near to the root
+ */
+ public Vector[] getRetain()
+ {
+ return GMSSUtils.clone(retain);
+ }
+
+ /**
+ * returns the finished root value
+ *
+ * @return the finished root value
+ */
+ public byte[] getRoot()
+ {
+ return Arrays.clone(root);
+ }
+
+ /**
+ * returns the shared stack
+ *
+ * @return the shared stack
+ */
+ public Vector getStack()
+ {
+ Vector copy = new Vector();
+ for (Enumeration en = tailStack.elements(); en.hasMoreElements();)
+ {
+ copy.addElement(en.nextElement());
+ }
+ return copy;
+ }
+
+ /**
+ * Returns the status byte array used by the GMSSPrivateKeyASN.1 class
+ *
+ * @return The status bytes
+ */
+ public byte[][] getStatByte()
+ {
+
+ int tailLength;
+ if (tailStack == null)
+ {
+ tailLength = 0;
+ }
+ else
+ {
+ tailLength = tailStack.size();
+ }
+ byte[][] statByte = new byte[1 + heightOfTree + tailLength][64]; //FIXME: messDigestTree.getByteLength()
+ statByte[0] = root;
+
+ for (int i = 0; i < heightOfTree; i++)
+ {
+ statByte[1 + i] = AuthPath[i];
+ }
+ for (int i = 0; i < tailLength; i++)
+ {
+ statByte[1 + heightOfTree + i] = (byte[])tailStack.elementAt(i);
+ }
+
+ return statByte;
+ }
+
+ /**
+ * Returns the status int array used by the GMSSPrivateKeyASN.1 class
+ *
+ * @return The status ints
+ */
+ public int[] getStatInt()
+ {
+
+ int tailLength;
+ if (tailStack == null)
+ {
+ tailLength = 0;
+ }
+ else
+ {
+ tailLength = tailStack.size();
+ }
+ int[] statInt = new int[8 + heightOfTree + tailLength];
+ statInt[0] = heightOfTree;
+ statInt[1] = mdLength;
+ statInt[2] = K;
+ statInt[3] = indexForNextSeed;
+ statInt[4] = heightOfNextSeed;
+ if (isFinished)
+ {
+ statInt[5] = 1;
+ }
+ else
+ {
+ statInt[5] = 0;
+ }
+ if (isInitialized)
+ {
+ statInt[6] = 1;
+ }
+ else
+ {
+ statInt[6] = 0;
+ }
+ statInt[7] = tailLength;
+
+ for (int i = 0; i < heightOfTree; i++)
+ {
+ statInt[8 + i] = index[i];
+ }
+ for (int i = 0; i < tailLength; i++)
+ {
+ statInt[8 + heightOfTree + i] = ((Integer)heightOfNodes
+ .elementAt(i)).intValue();
+ }
+
+ return statInt;
+ }
+
+ /**
+ * @return a human readable version of the structure
+ */
+ public String toString()
+ {
+ String out = "";
+ int tailLength;
+ if (tailStack == null)
+ {
+ tailLength = 0;
+ }
+ else
+ {
+ tailLength = tailStack.size();
+ }
+
+ for (int i = 0; i < 8 + heightOfTree + tailLength; i++)
+ {
+ out = out + getStatInt()[i] + " ";
+ }
+ for (int i = 0; i < 1 + heightOfTree + tailLength; i++)
+ {
+ out = out + new String(Hex.encode(getStatByte()[i])) + " ";
+ }
+ out = out + " " + digestProvider.get().getDigestSize();
+ return out;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSRootSig.java b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSRootSig.java
new file mode 100644
index 00000000..f08529cf
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSRootSig.java
@@ -0,0 +1,666 @@
+package org.spongycastle.pqc.crypto.gmss;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.pqc.crypto.gmss.util.GMSSRandom;
+import org.spongycastle.util.encoders.Hex;
+
+
+/**
+ * This class implements the distributed signature generation of the Winternitz
+ * one-time signature scheme (OTSS), described in C.Dods, N.P. Smart, and M.
+ * Stam, "Hash Based Digital Signature Schemes", LNCS 3796, pages 96&#8211;115,
+ * 2005. The class is used by the GMSS classes.
+ */
+public class GMSSRootSig
+{
+
+ /**
+ * The hash function used by the OTS
+ */
+ private Digest messDigestOTS;
+
+ /**
+ * The length of the message digest and private key
+ */
+ private int mdsize, keysize;
+
+ /**
+ * The private key
+ */
+ private byte[] privateKeyOTS;
+
+ /**
+ * The message bytes
+ */
+ private byte[] hash;
+
+ /**
+ * The signature bytes
+ */
+ private byte[] sign;
+
+ /**
+ * The Winternitz parameter
+ */
+ private int w;
+
+ /**
+ * The source of randomness for OTS private key generation
+ */
+ private GMSSRandom gmssRandom;
+
+ /**
+ * Sizes of the message
+ */
+ private int messagesize;
+
+ /**
+ * Some precalculated values
+ */
+ private int k;
+
+ /**
+ * Some variables for storing the actual status of distributed signing
+ */
+ private int r, test, counter, ii;
+
+ /**
+ * variables for storing big numbers for the actual status of distributed
+ * signing
+ */
+ private long test8, big8;
+
+ /**
+ * The necessary steps of each updateSign() call
+ */
+ private int steps;
+
+ /**
+ * The checksum part
+ */
+ private int checksum;
+
+ /**
+ * The height of the tree
+ */
+ private int height;
+
+ /**
+ * The current intern OTSseed
+ */
+ private byte[] seed;
+
+ /**
+ * This constructor regenerates a prior GMSSRootSig object used by the
+ * GMSSPrivateKeyASN.1 class
+ *
+ * @param digest an array of strings, containing the digest of the used hash
+ * function, the digest of the PRGN and the names of the
+ * corresponding providers
+ * @param statByte status byte array
+ * @param statInt status int array
+ */
+ public GMSSRootSig(Digest digest, byte[][] statByte, int[] statInt)
+ {
+ messDigestOTS = digest;
+ gmssRandom = new GMSSRandom(messDigestOTS);
+
+ this.counter = statInt[0];
+ this.test = statInt[1];
+ this.ii = statInt[2];
+ this.r = statInt[3];
+ this.steps = statInt[4];
+ this.keysize = statInt[5];
+ this.height = statInt[6];
+ this.w = statInt[7];
+ this.checksum = statInt[8];
+
+ this.mdsize = messDigestOTS.getDigestSize();
+
+ this.k = (1 << w) - 1;
+
+ int mdsizeBit = mdsize << 3;
+ this.messagesize = (int)Math.ceil((double)(mdsizeBit) / (double)w);
+
+ this.privateKeyOTS = statByte[0];
+ this.seed = statByte[1];
+ this.hash = statByte[2];
+
+ this.sign = statByte[3];
+
+ this.test8 = ((statByte[4][0] & 0xff))
+ | ((long)(statByte[4][1] & 0xff) << 8)
+ | ((long)(statByte[4][2] & 0xff) << 16)
+ | ((long)(statByte[4][3] & 0xff)) << 24
+ | ((long)(statByte[4][4] & 0xff)) << 32
+ | ((long)(statByte[4][5] & 0xff)) << 40
+ | ((long)(statByte[4][6] & 0xff)) << 48
+ | ((long)(statByte[4][7] & 0xff)) << 56;
+
+ this.big8 = ((statByte[4][8] & 0xff))
+ | ((long)(statByte[4][9] & 0xff) << 8)
+ | ((long)(statByte[4][10] & 0xff) << 16)
+ | ((long)(statByte[4][11] & 0xff)) << 24
+ | ((long)(statByte[4][12] & 0xff)) << 32
+ | ((long)(statByte[4][13] & 0xff)) << 40
+ | ((long)(statByte[4][14] & 0xff)) << 48
+ | ((long)(statByte[4][15] & 0xff)) << 56;
+ }
+
+ /**
+ * The constructor generates the PRNG and initializes some variables
+ *
+ * @param digest an array of strings, containing the digest of the used hash
+ * function, the digest of the PRGN and the names of the
+ * corresponding providers
+ * @param w the winternitz parameter
+ * @param height the heigth of the tree
+ */
+ public GMSSRootSig(Digest digest, int w, int height)
+ {
+ messDigestOTS = digest;
+ gmssRandom = new GMSSRandom(messDigestOTS);
+
+ this.mdsize = messDigestOTS.getDigestSize();
+ this.w = w;
+ this.height = height;
+
+ this.k = (1 << w) - 1;
+
+ int mdsizeBit = mdsize << 3;
+ this.messagesize = (int)Math.ceil((double)(mdsizeBit) / (double)w);
+ }
+
+ /**
+ * This method initializes the distributed sigature calculation. Variables
+ * are reseted and necessary steps are calculated
+ *
+ * @param seed0 the initial OTSseed
+ * @param message the massage which will be signed
+ */
+ public void initSign(byte[] seed0, byte[] message)
+ {
+
+ // create hash of message m
+ this.hash = new byte[mdsize];
+ messDigestOTS.update(message, 0, message.length);
+ this.hash = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(this.hash, 0);
+
+ // variables for calculation of steps
+ byte[] messPart = new byte[mdsize];
+ System.arraycopy(hash, 0, messPart, 0, mdsize);
+ int checkPart = 0;
+ int sumH = 0;
+ int checksumsize = getLog((messagesize << w) + 1);
+
+ // ------- calculation of necessary steps ------
+ if (8 % w == 0)
+ {
+ int dt = 8 / w;
+ // message part
+ for (int a = 0; a < mdsize; a++)
+ {
+ // count necessary hashs in 'sumH'
+ for (int b = 0; b < dt; b++)
+ {
+ sumH += messPart[a] & k;
+ messPart[a] = (byte)(messPart[a] >>> w);
+ }
+ }
+ // checksum part
+ this.checksum = (messagesize << w) - sumH;
+ checkPart = checksum;
+ // count necessary hashs in 'sumH'
+ for (int b = 0; b < checksumsize; b += w)
+ {
+ sumH += checkPart & k;
+ checkPart >>>= w;
+ }
+ } // end if ( 8 % w == 0 )
+ else if (w < 8)
+ {
+ long big8;
+ int ii = 0;
+ int dt = mdsize / w;
+
+ // first d*w bytes of hash (main message part)
+ for (int i = 0; i < dt; i++)
+ {
+ big8 = 0;
+ for (int j = 0; j < w; j++)
+ {
+ big8 ^= (messPart[ii] & 0xff) << (j << 3);
+ ii++;
+ }
+ // count necessary hashs in 'sumH'
+ for (int j = 0; j < 8; j++)
+ {
+ sumH += (int)(big8 & k);
+ big8 >>>= w;
+ }
+ }
+ // rest of message part
+ dt = mdsize % w;
+ big8 = 0;
+ for (int j = 0; j < dt; j++)
+ {
+ big8 ^= (messPart[ii] & 0xff) << (j << 3);
+ ii++;
+ }
+ dt <<= 3;
+ // count necessary hashs in 'sumH'
+ for (int j = 0; j < dt; j += w)
+ {
+ sumH += (int)(big8 & k);
+ big8 >>>= w;
+ }
+ // checksum part
+ this.checksum = (messagesize << w) - sumH;
+ checkPart = checksum;
+ // count necessary hashs in 'sumH'
+ for (int i = 0; i < checksumsize; i += w)
+ {
+ sumH += checkPart & k;
+ checkPart >>>= w;
+ }
+ }// end if(w<8)
+ else if (w < 57)
+ {
+ long big8;
+ int r = 0;
+ int s, f, rest, ii;
+
+ // first a*w bits of hash where a*w <= 8*mdsize < (a+1)*w (main
+ // message part)
+ while (r <= ((mdsize << 3) - w))
+ {
+ s = r >>> 3;
+ rest = r % 8;
+ r += w;
+ f = (r + 7) >>> 3;
+ big8 = 0;
+ ii = 0;
+ for (int j = s; j < f; j++)
+ {
+ big8 ^= (messPart[j] & 0xff) << (ii << 3);
+ ii++;
+ }
+ big8 >>>= rest;
+ // count necessary hashs in 'sumH'
+ sumH += (big8 & k);
+
+ }
+ // rest of message part
+ s = r >>> 3;
+ if (s < mdsize)
+ {
+ rest = r % 8;
+ big8 = 0;
+ ii = 0;
+ for (int j = s; j < mdsize; j++)
+ {
+ big8 ^= (messPart[j] & 0xff) << (ii << 3);
+ ii++;
+ }
+
+ big8 >>>= rest;
+ // count necessary hashs in 'sumH'
+ sumH += (big8 & k);
+ }
+ // checksum part
+ this.checksum = (messagesize << w) - sumH;
+ checkPart = checksum;
+ // count necessary hashs in 'sumH'
+ for (int i = 0; i < checksumsize; i += w)
+ {
+ sumH += (checkPart & k);
+ checkPart >>>= w;
+ }
+ }// end if(w<57)
+
+ // calculate keysize
+ this.keysize = messagesize
+ + (int)Math.ceil((double)checksumsize / (double)w);
+
+ // calculate steps: 'keysize' times PRNG, 'sumH' times hashing,
+ // (1<<height)-1 updateSign() calls
+ this.steps = (int)Math.ceil((double)(keysize + sumH)
+ / (double)((1 << height)));
+ // ----------------------------
+
+ // reset variables
+ this.sign = new byte[keysize * mdsize];
+ this.counter = 0;
+ this.test = 0;
+ this.ii = 0;
+ this.test8 = 0;
+ this.r = 0;
+ // define the private key messagesize
+ this.privateKeyOTS = new byte[mdsize];
+ // copy the seed
+ this.seed = new byte[mdsize];
+ System.arraycopy(seed0, 0, this.seed, 0, mdsize);
+
+ }
+
+ /**
+ * This Method performs <code>steps</code> steps of distributed signature
+ * calculaion
+ *
+ * @return true if signature is generated completly, else false
+ */
+ public boolean updateSign()
+ {
+ // steps times do
+
+ for (int s = 0; s < steps; s++)
+ { // do 'step' times
+
+ if (counter < keysize)
+ { // generate the private key or perform
+ // the next hash
+ oneStep();
+ }
+ if (counter == keysize)
+ {// finish
+ return true;
+ }
+ }
+
+ return false; // leaf not finished yet
+ }
+
+ /**
+ * @return The private OTS key
+ */
+ public byte[] getSig()
+ {
+
+ return sign;
+ }
+
+ /**
+ * @return The one-time signature of the message, generated step by step
+ */
+ private void oneStep()
+ {
+ // -------- if (8 % w == 0) ----------
+ if (8 % w == 0)
+ {
+ if (test == 0)
+ {
+ // get current OTSprivateKey
+ this.privateKeyOTS = gmssRandom.nextSeed(seed);
+ // System.arraycopy(privateKeyOTS, 0, hlp, 0, mdsize);
+
+ if (ii < mdsize)
+ { // for main message part
+ test = hash[ii] & k;
+ hash[ii] = (byte)(hash[ii] >>> w);
+ }
+ else
+ { // for checksum part
+ test = checksum & k;
+ checksum >>>= w;
+ }
+ }
+ else if (test > 0)
+ { // hash the private Key 'test' times (on
+ // time each step)
+ messDigestOTS.update(privateKeyOTS, 0, privateKeyOTS.length);
+ privateKeyOTS = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(privateKeyOTS, 0);
+ test--;
+ }
+ if (test == 0)
+ { // if all hashes done copy result to siganture
+ // array
+ System.arraycopy(privateKeyOTS, 0, sign, counter * mdsize,
+ mdsize);
+ counter++;
+
+ if (counter % (8 / w) == 0)
+ { // raise array index for main
+ // massage part
+ ii++;
+ }
+ }
+
+ }// ----- end if (8 % w == 0) -----
+ // ---------- if ( w < 8 ) ----------------
+ else if (w < 8)
+ {
+
+ if (test == 0)
+ {
+ if (counter % 8 == 0 && ii < mdsize)
+ { // after every 8th "add
+ // to signature"-step
+ big8 = 0;
+ if (counter < ((mdsize / w) << 3))
+ {// main massage
+ // (generate w*8 Bits
+ // every time) part
+ for (int j = 0; j < w; j++)
+ {
+ big8 ^= (hash[ii] & 0xff) << (j << 3);
+ ii++;
+ }
+ }
+ else
+ { // rest of massage part (once)
+ for (int j = 0; j < mdsize % w; j++)
+ {
+ big8 ^= (hash[ii] & 0xff) << (j << 3);
+ ii++;
+ }
+ }
+ }
+ if (counter == messagesize)
+ { // checksum part (once)
+ big8 = checksum;
+ }
+
+ test = (int)(big8 & k);
+ // generate current OTSprivateKey
+ this.privateKeyOTS = gmssRandom.nextSeed(seed);
+ // System.arraycopy(privateKeyOTS, 0, hlp, 0, mdsize);
+
+ }
+ else if (test > 0)
+ { // hash the private Key 'test' times (on
+ // time each step)
+ messDigestOTS.update(privateKeyOTS, 0, privateKeyOTS.length);
+ privateKeyOTS = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(privateKeyOTS, 0);
+ test--;
+ }
+ if (test == 0)
+ { // if all hashes done copy result to siganture
+ // array
+ System.arraycopy(privateKeyOTS, 0, sign, counter * mdsize,
+ mdsize);
+ big8 >>>= w;
+ counter++;
+ }
+
+ }// ------- end if(w<8)--------------------------------
+ // --------- if w < 57 -----------------------------
+ else if (w < 57)
+ {
+
+ if (test8 == 0)
+ {
+ int s, f, rest;
+ big8 = 0;
+ ii = 0;
+ rest = r % 8;
+ s = r >>> 3;
+ // --- message part---
+ if (s < mdsize)
+ {
+ if (r <= ((mdsize << 3) - w))
+ { // first message part
+ r += w;
+ f = (r + 7) >>> 3;
+ }
+ else
+ { // rest of message part (once)
+ f = mdsize;
+ r += w;
+ }
+ // generate long 'big8' with minimum w next bits of the
+ // message array
+ for (int i = s; i < f; i++)
+ {
+ big8 ^= (hash[i] & 0xff) << (ii << 3);
+ ii++;
+ }
+ // delete bits on the right side, which were used already by
+ // the last loop
+ big8 >>>= rest;
+ test8 = (big8 & k);
+ }
+ // --- checksum part
+ else
+ {
+ test8 = (checksum & k);
+ checksum >>>= w;
+ }
+ // generate current OTSprivateKey
+ this.privateKeyOTS = gmssRandom.nextSeed(seed);
+ // System.arraycopy(privateKeyOTS, 0, hlp, 0, mdsize);
+
+ }
+ else if (test8 > 0)
+ { // hash the private Key 'test' times (on
+ // time each step)
+ messDigestOTS.update(privateKeyOTS, 0, privateKeyOTS.length);
+ privateKeyOTS = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(privateKeyOTS, 0);
+ test8--;
+ }
+ if (test8 == 0)
+ { // if all hashes done copy result to siganture
+ // array
+ System.arraycopy(privateKeyOTS, 0, sign, counter * mdsize,
+ mdsize);
+ counter++;
+ }
+
+ }
+ }
+
+ /**
+ * This method returns the least integer that is greater or equal to the
+ * logarithm to the base 2 of an integer <code>intValue</code>.
+ *
+ * @param intValue an integer
+ * @return The least integer greater or equal to the logarithm to the base 2
+ * of <code>intValue</code>
+ */
+ public int getLog(int intValue)
+ {
+ int log = 1;
+ int i = 2;
+ while (i < intValue)
+ {
+ i <<= 1;
+ log++;
+ }
+ return log;
+ }
+
+ /**
+ * This method returns the status byte array
+ *
+ * @return statBytes
+ */
+ public byte[][] getStatByte()
+ {
+
+ byte[][] statByte = new byte[5][mdsize];
+ statByte[0] = privateKeyOTS;
+ statByte[1] = seed;
+ statByte[2] = hash;
+ statByte[3] = sign;
+ statByte[4] = this.getStatLong();
+
+ return statByte;
+ }
+
+ /**
+ * This method returns the status int array
+ *
+ * @return statInt
+ */
+ public int[] getStatInt()
+ {
+ int[] statInt = new int[9];
+ statInt[0] = counter;
+ statInt[1] = test;
+ statInt[2] = ii;
+ statInt[3] = r;
+ statInt[4] = steps;
+ statInt[5] = keysize;
+ statInt[6] = height;
+ statInt[7] = w;
+ statInt[8] = checksum;
+ return statInt;
+ }
+
+ /**
+ * Converts the long parameters into byte arrays to store it in
+ * statByte-Array
+ */
+ public byte[] getStatLong()
+ {
+ byte[] bytes = new byte[16];
+
+ bytes[0] = (byte)((test8) & 0xff);
+ bytes[1] = (byte)((test8 >> 8) & 0xff);
+ bytes[2] = (byte)((test8 >> 16) & 0xff);
+ bytes[3] = (byte)((test8 >> 24) & 0xff);
+ bytes[4] = (byte)((test8) >> 32 & 0xff);
+ bytes[5] = (byte)((test8 >> 40) & 0xff);
+ bytes[6] = (byte)((test8 >> 48) & 0xff);
+ bytes[7] = (byte)((test8 >> 56) & 0xff);
+
+ bytes[8] = (byte)((big8) & 0xff);
+ bytes[9] = (byte)((big8 >> 8) & 0xff);
+ bytes[10] = (byte)((big8 >> 16) & 0xff);
+ bytes[11] = (byte)((big8 >> 24) & 0xff);
+ bytes[12] = (byte)((big8) >> 32 & 0xff);
+ bytes[13] = (byte)((big8 >> 40) & 0xff);
+ bytes[14] = (byte)((big8 >> 48) & 0xff);
+ bytes[15] = (byte)((big8 >> 56) & 0xff);
+
+ return bytes;
+ }
+
+ /**
+ * returns a string representation of the instance
+ *
+ * @return a string representation of the instance
+ */
+ public String toString()
+ {
+ String out = "" + this.big8 + " ";
+ int[] statInt = new int[9];
+ statInt = this.getStatInt();
+ byte[][] statByte = new byte[5][mdsize];
+ statByte = this.getStatByte();
+ for (int i = 0; i < 9; i++)
+ {
+ out = out + statInt[i] + " ";
+ }
+ for (int i = 0; i < 5; i++)
+ {
+ out = out + new String(Hex.encode(statByte[i])) + " ";
+ }
+
+ return out;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSSigner.java b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSSigner.java
new file mode 100644
index 00000000..2a78d385
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSSigner.java
@@ -0,0 +1,403 @@
+package org.spongycastle.pqc.crypto.gmss;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.pqc.crypto.MessageSigner;
+import org.spongycastle.pqc.crypto.gmss.util.GMSSRandom;
+import org.spongycastle.pqc.crypto.gmss.util.GMSSUtil;
+import org.spongycastle.pqc.crypto.gmss.util.WinternitzOTSVerify;
+import org.spongycastle.pqc.crypto.gmss.util.WinternitzOTSignature;
+import org.spongycastle.util.Arrays;
+
+/**
+ * This class implements the GMSS signature scheme.
+ */
+public class GMSSSigner
+ implements MessageSigner
+{
+
+ /**
+ * Instance of GMSSParameterSpec
+ */
+ //private GMSSParameterSpec gmssParameterSpec;
+
+ /**
+ * Instance of GMSSUtilities
+ */
+ private GMSSUtil gmssUtil = new GMSSUtil();
+
+
+ /**
+ * The raw GMSS public key
+ */
+ private byte[] pubKeyBytes;
+
+ /**
+ * Hash function for the construction of the authentication trees
+ */
+ private Digest messDigestTrees;
+
+ /**
+ * The length of the hash function output
+ */
+ private int mdLength;
+
+ /**
+ * The number of tree layers
+ */
+ private int numLayer;
+
+ /**
+ * The hash function used by the OTS
+ */
+ private Digest messDigestOTS;
+
+ /**
+ * An instance of the Winternitz one-time signature
+ */
+ private WinternitzOTSignature ots;
+
+ /**
+ * Array of strings containing the name of the hash function used by the OTS
+ * and the corresponding provider name
+ */
+ private GMSSDigestProvider digestProvider;
+
+ /**
+ * The current main tree and subtree indices
+ */
+ private int[] index;
+
+ /**
+ * Array of the authentication paths for the current trees of all layers
+ */
+ private byte[][][] currentAuthPaths;
+
+ /**
+ * The one-time signature of the roots of the current subtrees
+ */
+ private byte[][] subtreeRootSig;
+
+
+ /**
+ * The GMSSParameterset
+ */
+ private GMSSParameters gmssPS;
+
+ /**
+ * The PRNG
+ */
+ private GMSSRandom gmssRandom;
+
+ GMSSKeyParameters key;
+
+ // XXX needed? Source of randomness
+ private SecureRandom random;
+
+
+ /**
+ * The standard constructor tries to generate the MerkleTree Algorithm
+ * identifier with the corresponding OID.
+ *
+ * @param digest the digest to use
+ */
+ // TODO
+ public GMSSSigner(GMSSDigestProvider digest)
+ {
+ digestProvider = digest;
+ messDigestTrees = digest.get();
+ messDigestOTS = messDigestTrees;
+ mdLength = messDigestTrees.getDigestSize();
+ gmssRandom = new GMSSRandom(messDigestTrees);
+ }
+
+ public void init(boolean forSigning,
+ CipherParameters param)
+ {
+
+ if (forSigning)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ // XXX random needed?
+ this.random = rParam.getRandom();
+ this.key = (GMSSPrivateKeyParameters)rParam.getParameters();
+ initSign();
+
+ }
+ else
+ {
+
+ this.random = new SecureRandom();
+ this.key = (GMSSPrivateKeyParameters)param;
+ initSign();
+ }
+ }
+ else
+ {
+ this.key = (GMSSPublicKeyParameters)param;
+ initVerify();
+
+ }
+
+ }
+
+
+ /**
+ * Initializes the signature algorithm for signing a message.
+ */
+ private void initSign()
+ {
+ messDigestTrees.reset();
+ // set private key and take from it ots key, auth, tree and key
+ // counter, rootSign
+ GMSSPrivateKeyParameters gmssPrivateKey = (GMSSPrivateKeyParameters)key;
+
+ if (gmssPrivateKey.isUsed())
+ {
+ throw new IllegalStateException("Private key already used");
+ }
+
+ // check if last signature has been generated
+ if (gmssPrivateKey.getIndex(0) >= gmssPrivateKey.getNumLeafs(0))
+ {
+ throw new IllegalStateException("No more signatures can be generated");
+ }
+
+ // get Parameterset
+ this.gmssPS = gmssPrivateKey.getParameters();
+ // get numLayer
+ this.numLayer = gmssPS.getNumOfLayers();
+
+ // get OTS Instance of lowest layer
+ byte[] seed = gmssPrivateKey.getCurrentSeeds()[numLayer - 1];
+ byte[] OTSSeed = new byte[mdLength];
+ byte[] dummy = new byte[mdLength];
+ System.arraycopy(seed, 0, dummy, 0, mdLength);
+ OTSSeed = gmssRandom.nextSeed(dummy); // secureRandom.nextBytes(currentSeeds[currentSeeds.length-1]);secureRandom.nextBytes(OTSseed);
+ this.ots = new WinternitzOTSignature(OTSSeed, digestProvider.get(), gmssPS.getWinternitzParameter()[numLayer - 1]);
+
+ byte[][][] helpCurrentAuthPaths = gmssPrivateKey.getCurrentAuthPaths();
+ currentAuthPaths = new byte[numLayer][][];
+
+ // copy the main tree authentication path
+ for (int j = 0; j < numLayer; j++)
+ {
+ currentAuthPaths[j] = new byte[helpCurrentAuthPaths[j].length][mdLength];
+ for (int i = 0; i < helpCurrentAuthPaths[j].length; i++)
+ {
+ System.arraycopy(helpCurrentAuthPaths[j][i], 0, currentAuthPaths[j][i], 0, mdLength);
+ }
+ }
+
+ // copy index
+ index = new int[numLayer];
+ System.arraycopy(gmssPrivateKey.getIndex(), 0, index, 0, numLayer);
+
+ // copy subtreeRootSig
+ byte[] helpSubtreeRootSig;
+ subtreeRootSig = new byte[numLayer - 1][];
+ for (int i = 0; i < numLayer - 1; i++)
+ {
+ helpSubtreeRootSig = gmssPrivateKey.getSubtreeRootSig(i);
+ subtreeRootSig[i] = new byte[helpSubtreeRootSig.length];
+ System.arraycopy(helpSubtreeRootSig, 0, subtreeRootSig[i], 0, helpSubtreeRootSig.length);
+ }
+
+ gmssPrivateKey.markUsed();
+ }
+
+ /**
+ * Signs a message.
+ *
+ * @return the signature.
+ */
+ public byte[] generateSignature(byte[] message)
+ {
+
+ byte[] otsSig = new byte[mdLength];
+ byte[] authPathBytes;
+ byte[] indexBytes;
+
+ otsSig = ots.getSignature(message);
+
+ // get concatenated lowest layer tree authentication path
+ authPathBytes = gmssUtil.concatenateArray(currentAuthPaths[numLayer - 1]);
+
+ // put lowest layer index into a byte array
+ indexBytes = gmssUtil.intToBytesLittleEndian(index[numLayer - 1]);
+
+ // create first part of GMSS signature
+ byte[] gmssSigFirstPart = new byte[indexBytes.length + otsSig.length + authPathBytes.length];
+ System.arraycopy(indexBytes, 0, gmssSigFirstPart, 0, indexBytes.length);
+ System.arraycopy(otsSig, 0, gmssSigFirstPart, indexBytes.length, otsSig.length);
+ System.arraycopy(authPathBytes, 0, gmssSigFirstPart, (indexBytes.length + otsSig.length), authPathBytes.length);
+ // --- end first part
+
+ // --- next parts of the signature
+ // create initial array with length 0 for iteration
+ byte[] gmssSigNextPart = new byte[0];
+
+ for (int i = numLayer - 1 - 1; i >= 0; i--)
+ {
+
+ // get concatenated next tree authentication path
+ authPathBytes = gmssUtil.concatenateArray(currentAuthPaths[i]);
+
+ // put next tree index into a byte array
+ indexBytes = gmssUtil.intToBytesLittleEndian(index[i]);
+
+ // create next part of GMSS signature
+
+ // create help array and copy actual gmssSig into it
+ byte[] helpGmssSig = new byte[gmssSigNextPart.length];
+ System.arraycopy(gmssSigNextPart, 0, helpGmssSig, 0, gmssSigNextPart.length);
+ // adjust length of gmssSigNextPart for adding next part
+ gmssSigNextPart = new byte[helpGmssSig.length + indexBytes.length + subtreeRootSig[i].length + authPathBytes.length];
+
+ // copy old data (help array) and new data in gmssSigNextPart
+ System.arraycopy(helpGmssSig, 0, gmssSigNextPart, 0, helpGmssSig.length);
+ System.arraycopy(indexBytes, 0, gmssSigNextPart, helpGmssSig.length, indexBytes.length);
+ System.arraycopy(subtreeRootSig[i], 0, gmssSigNextPart, (helpGmssSig.length + indexBytes.length), subtreeRootSig[i].length);
+ System.arraycopy(authPathBytes, 0, gmssSigNextPart, (helpGmssSig.length + indexBytes.length + subtreeRootSig[i].length), authPathBytes.length);
+
+ }
+ // --- end next parts
+
+ // concatenate the two parts of the GMSS signature
+ byte[] gmssSig = new byte[gmssSigFirstPart.length + gmssSigNextPart.length];
+ System.arraycopy(gmssSigFirstPart, 0, gmssSig, 0, gmssSigFirstPart.length);
+ System.arraycopy(gmssSigNextPart, 0, gmssSig, gmssSigFirstPart.length, gmssSigNextPart.length);
+
+ // return the GMSS signature
+ return gmssSig;
+ }
+
+ /**
+ * Initializes the signature algorithm for verifying a signature.
+ */
+ private void initVerify()
+ {
+ messDigestTrees.reset();
+
+ GMSSPublicKeyParameters gmssPublicKey = (GMSSPublicKeyParameters)key;
+ pubKeyBytes = gmssPublicKey.getPublicKey();
+ gmssPS = gmssPublicKey.getParameters();
+ // get numLayer
+ this.numLayer = gmssPS.getNumOfLayers();
+
+
+ }
+
+ /**
+ * This function verifies the signature of the message that has been
+ * updated, with the aid of the public key.
+ *
+ * @param message the message
+ * @param signature the signature associated with the message
+ * @return true if the signature has been verified, false otherwise.
+ */
+ public boolean verifySignature(byte[] message, byte[] signature)
+ {
+
+ boolean success = false;
+ // int halfSigLength = signature.length >>> 1;
+ messDigestOTS.reset();
+ WinternitzOTSVerify otsVerify;
+ int otsSigLength;
+
+ byte[] help = message;
+
+ byte[] otsSig;
+ byte[] otsPublicKey;
+ byte[][] authPath;
+ byte[] dest;
+ int nextEntry = 0;
+ int index;
+ // Verify signature
+
+ // --- begin with message = 'message that was signed'
+ // and then in each step message = subtree root
+ for (int j = numLayer - 1; j >= 0; j--)
+ {
+ otsVerify = new WinternitzOTSVerify(digestProvider.get(), gmssPS.getWinternitzParameter()[j]);
+ otsSigLength = otsVerify.getSignatureLength();
+
+ message = help;
+ // get the subtree index
+ index = gmssUtil.bytesToIntLittleEndian(signature, nextEntry);
+
+ // 4 is the number of bytes in integer
+ nextEntry += 4;
+
+ // get one-time signature
+ otsSig = new byte[otsSigLength];
+ System.arraycopy(signature, nextEntry, otsSig, 0, otsSigLength);
+ nextEntry += otsSigLength;
+
+ // compute public OTS key from the one-time signature
+ otsPublicKey = otsVerify.Verify(message, otsSig);
+
+ // test if OTSsignature is correct
+ if (otsPublicKey == null)
+ {
+ System.err.println("OTS Public Key is null in GMSSSignature.verify");
+ return false;
+ }
+
+ // get authentication path from the signature
+ authPath = new byte[gmssPS.getHeightOfTrees()[j]][mdLength];
+ for (int i = 0; i < authPath.length; i++)
+ {
+ System.arraycopy(signature, nextEntry, authPath[i], 0, mdLength);
+ nextEntry = nextEntry + mdLength;
+ }
+
+ // compute the root of the subtree from the authentication path
+ help = new byte[mdLength];
+
+ help = otsPublicKey;
+
+ int count = 1 << authPath.length;
+ count = count + index;
+
+ for (int i = 0; i < authPath.length; i++)
+ {
+ dest = new byte[mdLength << 1];
+
+ if ((count % 2) == 0)
+ {
+ System.arraycopy(help, 0, dest, 0, mdLength);
+ System.arraycopy(authPath[i], 0, dest, mdLength, mdLength);
+ count = count / 2;
+ }
+ else
+ {
+ System.arraycopy(authPath[i], 0, dest, 0, mdLength);
+ System.arraycopy(help, 0, dest, mdLength, help.length);
+ count = (count - 1) / 2;
+ }
+ messDigestTrees.update(dest, 0, dest.length);
+ help = new byte[messDigestTrees.getDigestSize()];
+ messDigestTrees.doFinal(help, 0);
+ }
+ }
+
+ // now help contains the root of the maintree
+
+ // test if help is equal to the GMSS public key
+ if (Arrays.areEqual(pubKeyBytes, help))
+ {
+ success = true;
+ }
+
+ return success;
+ }
+
+
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSUtils.java b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSUtils.java
new file mode 100644
index 00000000..1f79bdde
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSUtils.java
@@ -0,0 +1,145 @@
+package org.spongycastle.pqc.crypto.gmss;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.spongycastle.util.Arrays;
+
+class GMSSUtils
+{
+ static GMSSLeaf[] clone(GMSSLeaf[] data)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ GMSSLeaf[] copy = new GMSSLeaf[data.length];
+
+ System.arraycopy(data, 0, copy, 0, data.length);
+
+ return copy;
+ }
+
+ static GMSSRootCalc[] clone(GMSSRootCalc[] data)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ GMSSRootCalc[] copy = new GMSSRootCalc[data.length];
+
+ System.arraycopy(data, 0, copy, 0, data.length);
+
+ return copy;
+ }
+
+ static GMSSRootSig[] clone(GMSSRootSig[] data)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ GMSSRootSig[] copy = new GMSSRootSig[data.length];
+
+ System.arraycopy(data, 0, copy, 0, data.length);
+
+ return copy;
+ }
+
+ static byte[][] clone(byte[][] data)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ byte[][] copy = new byte[data.length][];
+
+ for (int i = 0; i != data.length; i++)
+ {
+ copy[i] = Arrays.clone(data[i]);
+ }
+
+ return copy;
+ }
+
+ static byte[][][] clone(byte[][][] data)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ byte[][][] copy = new byte[data.length][][];
+
+ for (int i = 0; i != data.length; i++)
+ {
+ copy[i] = clone(data[i]);
+ }
+
+ return copy;
+ }
+
+ static Treehash[] clone(Treehash[] data)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ Treehash[] copy = new Treehash[data.length];
+
+ System.arraycopy(data, 0, copy, 0, data.length);
+
+ return copy;
+ }
+
+ static Treehash[][] clone(Treehash[][] data)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ Treehash[][] copy = new Treehash[data.length][];
+
+ for (int i = 0; i != data.length; i++)
+ {
+ copy[i] = clone(data[i]);
+ }
+
+ return copy;
+ }
+
+ static Vector[] clone(Vector[] data)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ Vector[] copy = new Vector[data.length];
+
+ for (int i = 0; i != data.length; i++)
+ {
+ copy[i] = new Vector();
+ for (Enumeration en = data[i].elements(); en.hasMoreElements();)
+ {
+ copy[i].addElement(en.nextElement());
+ }
+ }
+
+ return copy;
+ }
+
+ static Vector[][] clone(Vector[][] data)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ Vector[][] copy = new Vector[data.length][];
+
+ for (int i = 0; i != data.length; i++)
+ {
+ copy[i] = clone(data[i]);
+ }
+
+ return copy;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/gmss/Treehash.java b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/Treehash.java
new file mode 100644
index 00000000..82784e34
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/Treehash.java
@@ -0,0 +1,525 @@
+package org.spongycastle.pqc.crypto.gmss;
+
+import java.util.Vector;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.pqc.crypto.gmss.util.GMSSRandom;
+import org.spongycastle.util.Integers;
+import org.spongycastle.util.encoders.Hex;
+
+
+/**
+ * This class implements a treehash instance for the Merkle tree traversal
+ * algorithm. The first node of the stack is stored in this instance itself,
+ * additional tail nodes are stored on a tailstack.
+ */
+public class Treehash
+{
+
+ /**
+ * max height of current treehash instance.
+ */
+ private int maxHeight;
+
+ /**
+ * Vector element that stores the nodes on the stack
+ */
+ private Vector tailStack;
+
+ /**
+ * Vector element that stores the height of the nodes on the stack
+ */
+ private Vector heightOfNodes;
+
+ /**
+ * the first node is stored in the treehash instance itself, not on stack
+ */
+ private byte[] firstNode;
+
+ /**
+ * seedActive needed for the actual node
+ */
+ private byte[] seedActive;
+
+ /**
+ * the seed needed for the next re-initialization of the treehash instance
+ */
+ private byte[] seedNext;
+
+ /**
+ * number of nodes stored on the stack and belonging to this treehash
+ * instance
+ */
+ private int tailLength;
+
+ /**
+ * the height in the tree of the first node stored in treehash
+ */
+ private int firstNodeHeight;
+
+ /**
+ * true if treehash instance was already initialized, false otherwise
+ */
+ private boolean isInitialized;
+
+ /**
+ * true if the first node's height equals the maxHeight of the treehash
+ */
+ private boolean isFinished;
+
+ /**
+ * true if the nextSeed has been initialized with index 3*2^h needed for the
+ * seed scheduling
+ */
+ private boolean seedInitialized;
+
+ /**
+ * denotes the Message Digest used by the tree to create nodes
+ */
+ private Digest messDigestTree;
+
+ /**
+ * This constructor regenerates a prior treehash object
+ *
+ * @param name an array of strings, containing the name of the used hash
+ * function and PRNG and the name of the corresponding provider
+ * @param statByte status bytes
+ * @param statInt status ints
+ */
+ public Treehash(Digest name, byte[][] statByte, int[] statInt)
+ {
+ this.messDigestTree = name;
+
+ // decode statInt
+ this.maxHeight = statInt[0];
+ this.tailLength = statInt[1];
+ this.firstNodeHeight = statInt[2];
+
+ if (statInt[3] == 1)
+ {
+ this.isFinished = true;
+ }
+ else
+ {
+ this.isFinished = false;
+ }
+ if (statInt[4] == 1)
+ {
+ this.isInitialized = true;
+ }
+ else
+ {
+ this.isInitialized = false;
+ }
+ if (statInt[5] == 1)
+ {
+ this.seedInitialized = true;
+ }
+ else
+ {
+ this.seedInitialized = false;
+ }
+
+ this.heightOfNodes = new Vector();
+ for (int i = 0; i < tailLength; i++)
+ {
+ this.heightOfNodes.addElement(Integers.valueOf(statInt[6 + i]));
+ }
+
+ // decode statByte
+ this.firstNode = statByte[0];
+ this.seedActive = statByte[1];
+ this.seedNext = statByte[2];
+
+ this.tailStack = new Vector();
+ for (int i = 0; i < tailLength; i++)
+ {
+ this.tailStack.addElement(statByte[3 + i]);
+ }
+ }
+
+ /**
+ * Constructor
+ *
+ * @param tailStack a vector element where the stack nodes are stored
+ * @param maxHeight maximal height of the treehash instance
+ * @param digest an array of strings, containing the name of the used hash
+ * function and PRNG and the name of the corresponding provider
+ */
+ public Treehash(Vector tailStack, int maxHeight, Digest digest)
+ {
+ this.tailStack = tailStack;
+ this.maxHeight = maxHeight;
+ this.firstNode = null;
+ this.isInitialized = false;
+ this.isFinished = false;
+ this.seedInitialized = false;
+ this.messDigestTree = digest;
+
+ this.seedNext = new byte[messDigestTree.getDigestSize()];
+ this.seedActive = new byte[messDigestTree.getDigestSize()];
+ }
+
+ /**
+ * Method to initialize the seeds needed for the precomputation of right
+ * nodes. Should be initialized with index 3*2^i for treehash_i
+ *
+ * @param seedIn
+ */
+ public void initializeSeed(byte[] seedIn)
+ {
+ System.arraycopy(seedIn, 0, this.seedNext, 0, this.messDigestTree
+ .getDigestSize());
+ this.seedInitialized = true;
+ }
+
+ /**
+ * initializes the treehash instance. The seeds must already have been
+ * initialized to work correctly.
+ */
+ public void initialize()
+ {
+ if (!this.seedInitialized)
+ {
+ System.err.println("Seed " + this.maxHeight + " not initialized");
+ return;
+ }
+
+ this.heightOfNodes = new Vector();
+ this.tailLength = 0;
+ this.firstNode = null;
+ this.firstNodeHeight = -1;
+ this.isInitialized = true;
+ System.arraycopy(this.seedNext, 0, this.seedActive, 0, messDigestTree
+ .getDigestSize());
+ }
+
+ /**
+ * Calculates one update of the treehash instance, i.e. creates a new leaf
+ * and hashes if possible
+ *
+ * @param gmssRandom an instance of the PRNG
+ * @param leaf The byte value of the leaf needed for the update
+ */
+ public void update(GMSSRandom gmssRandom, byte[] leaf)
+ {
+
+ if (this.isFinished)
+ {
+ System.err
+ .println("No more update possible for treehash instance!");
+ return;
+ }
+ if (!this.isInitialized)
+ {
+ System.err
+ .println("Treehash instance not initialized before update");
+ return;
+ }
+
+ byte[] help = new byte[this.messDigestTree.getDigestSize()];
+ int helpHeight = -1;
+
+ gmssRandom.nextSeed(this.seedActive);
+
+ // if treehash gets first update
+ if (this.firstNode == null)
+ {
+ this.firstNode = leaf;
+ this.firstNodeHeight = 0;
+ }
+ else
+ {
+ // store the new node in help array, do not push it on the stack
+ help = leaf;
+ helpHeight = 0;
+
+ // hash the nodes on the stack if possible
+ while (this.tailLength > 0
+ && helpHeight == ((Integer)heightOfNodes.lastElement())
+ .intValue())
+ {
+ // put top element of the stack and help node in array
+ // 'tobehashed'
+ // and hash them together, put result again in help array
+ byte[] toBeHashed = new byte[this.messDigestTree
+ .getDigestSize() << 1];
+
+ // pop element from stack
+ System.arraycopy(this.tailStack.lastElement(), 0, toBeHashed,
+ 0, this.messDigestTree.getDigestSize());
+ this.tailStack.removeElementAt(this.tailStack.size() - 1);
+ this.heightOfNodes
+ .removeElementAt(this.heightOfNodes.size() - 1);
+
+ System.arraycopy(help, 0, toBeHashed, this.messDigestTree
+ .getDigestSize(), this.messDigestTree
+ .getDigestSize());
+ messDigestTree.update(toBeHashed, 0, toBeHashed.length);
+ help = new byte[messDigestTree.getDigestSize()];
+ messDigestTree.doFinal(help, 0);
+
+ // increase help height, stack was reduced by one element
+ helpHeight++;
+ this.tailLength--;
+ }
+
+ // push the new node on the stack
+ this.tailStack.addElement(help);
+ this.heightOfNodes.addElement(Integers.valueOf(helpHeight));
+ this.tailLength++;
+
+ // finally check whether the top node on stack and the first node
+ // in treehash have same height. If so hash them together
+ // and store them in treehash
+ if (((Integer)heightOfNodes.lastElement()).intValue() == this.firstNodeHeight)
+ {
+ byte[] toBeHashed = new byte[this.messDigestTree
+ .getDigestSize() << 1];
+ System.arraycopy(this.firstNode, 0, toBeHashed, 0,
+ this.messDigestTree.getDigestSize());
+
+ // pop element from tailStack and copy it into help2 array
+ System.arraycopy(this.tailStack.lastElement(), 0, toBeHashed,
+ this.messDigestTree.getDigestSize(),
+ this.messDigestTree.getDigestSize());
+ this.tailStack.removeElementAt(this.tailStack.size() - 1);
+ this.heightOfNodes
+ .removeElementAt(this.heightOfNodes.size() - 1);
+
+ // store new element in firstNode, stack is then empty
+ messDigestTree.update(toBeHashed, 0, toBeHashed.length);
+ this.firstNode = new byte[messDigestTree.getDigestSize()];
+ messDigestTree.doFinal(this.firstNode, 0);
+ this.firstNodeHeight++;
+
+ // empty the stack
+ this.tailLength = 0;
+ }
+ }
+
+ // check if treehash instance is completed
+ if (this.firstNodeHeight == this.maxHeight)
+ {
+ this.isFinished = true;
+ }
+ }
+
+ /**
+ * Destroys a treehash instance after the top node was taken for
+ * authentication path.
+ */
+ public void destroy()
+ {
+ this.isInitialized = false;
+ this.isFinished = false;
+ this.firstNode = null;
+ this.tailLength = 0;
+ this.firstNodeHeight = -1;
+ }
+
+ /**
+ * Returns the height of the lowest node stored either in treehash or on the
+ * stack. It must not be set to infinity (as mentioned in the paper) because
+ * this cases are considered in the computeAuthPaths method of
+ * JDKGMSSPrivateKey
+ *
+ * @return Height of the lowest node
+ */
+ public int getLowestNodeHeight()
+ {
+ if (this.firstNode == null)
+ {
+ return this.maxHeight;
+ }
+ else if (this.tailLength == 0)
+ {
+ return this.firstNodeHeight;
+ }
+ else
+ {
+ return Math.min(this.firstNodeHeight, ((Integer)heightOfNodes
+ .lastElement()).intValue());
+ }
+ }
+
+ /**
+ * Returns the top node height
+ *
+ * @return Height of the first node, the top node
+ */
+ public int getFirstNodeHeight()
+ {
+ if (firstNode == null)
+ {
+ return maxHeight;
+ }
+ return firstNodeHeight;
+ }
+
+ /**
+ * Method to check whether the instance has been initialized or not
+ *
+ * @return true if treehash was already initialized
+ */
+ public boolean wasInitialized()
+ {
+ return this.isInitialized;
+ }
+
+ /**
+ * Method to check whether the instance has been finished or not
+ *
+ * @return true if treehash has reached its maximum height
+ */
+ public boolean wasFinished()
+ {
+ return this.isFinished;
+ }
+
+ /**
+ * returns the first node stored in treehash instance itself
+ *
+ * @return the first node stored in treehash instance itself
+ */
+ public byte[] getFirstNode()
+ {
+ return this.firstNode;
+ }
+
+ /**
+ * returns the active seed
+ *
+ * @return the active seed
+ */
+ public byte[] getSeedActive()
+ {
+ return this.seedActive;
+ }
+
+ /**
+ * This method sets the first node stored in the treehash instance itself
+ *
+ * @param hash
+ */
+ public void setFirstNode(byte[] hash)
+ {
+ if (!this.isInitialized)
+ {
+ this.initialize();
+ }
+ this.firstNode = hash;
+ this.firstNodeHeight = this.maxHeight;
+ this.isFinished = true;
+ }
+
+ /**
+ * updates the nextSeed of this treehash instance one step needed for the
+ * schedulng of the seeds
+ *
+ * @param gmssRandom the prng used for the seeds
+ */
+ public void updateNextSeed(GMSSRandom gmssRandom)
+ {
+ gmssRandom.nextSeed(seedNext);
+ }
+
+ /**
+ * Returns the tailstack
+ *
+ * @return the tailstack
+ */
+ public Vector getTailStack()
+ {
+ return this.tailStack;
+ }
+
+ /**
+ * Returns the status byte array used by the GMSSPrivateKeyASN.1 class
+ *
+ * @return The status bytes
+ */
+ public byte[][] getStatByte()
+ {
+
+ byte[][] statByte = new byte[3 + tailLength][this.messDigestTree
+ .getDigestSize()];
+ statByte[0] = firstNode;
+ statByte[1] = seedActive;
+ statByte[2] = seedNext;
+ for (int i = 0; i < tailLength; i++)
+ {
+ statByte[3 + i] = (byte[])tailStack.elementAt(i);
+ }
+ return statByte;
+ }
+
+ /**
+ * Returns the status int array used by the GMSSPrivateKeyASN.1 class
+ *
+ * @return The status ints
+ */
+ public int[] getStatInt()
+ {
+
+ int[] statInt = new int[6 + tailLength];
+ statInt[0] = maxHeight;
+ statInt[1] = tailLength;
+ statInt[2] = firstNodeHeight;
+ if (this.isFinished)
+ {
+ statInt[3] = 1;
+ }
+ else
+ {
+ statInt[3] = 0;
+ }
+ if (this.isInitialized)
+ {
+ statInt[4] = 1;
+ }
+ else
+ {
+ statInt[4] = 0;
+ }
+ if (this.seedInitialized)
+ {
+ statInt[5] = 1;
+ }
+ else
+ {
+ statInt[5] = 0;
+ }
+ for (int i = 0; i < tailLength; i++)
+ {
+ statInt[6 + i] = ((Integer)heightOfNodes.elementAt(i)).intValue();
+ }
+ return statInt;
+ }
+
+ /**
+ * returns a String representation of the treehash instance
+ */
+ public String toString()
+ {
+ String out = "Treehash : ";
+ for (int i = 0; i < 6 + tailLength; i++)
+ {
+ out = out + this.getStatInt()[i] + " ";
+ }
+ for (int i = 0; i < 3 + tailLength; i++)
+ {
+ if (this.getStatByte()[i] != null)
+ {
+ out = out + new String(Hex.encode((this.getStatByte()[i]))) + " ";
+ }
+ else
+ {
+ out = out + "null ";
+ }
+ }
+ out = out + " " + this.messDigestTree.getDigestSize();
+ return out;
+ }
+
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/GMSSRandom.java b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/GMSSRandom.java
new file mode 100644
index 00000000..367aae0e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/GMSSRandom.java
@@ -0,0 +1,78 @@
+package org.spongycastle.pqc.crypto.gmss.util;
+
+import org.spongycastle.crypto.Digest;
+
+/**
+ * This class provides a PRNG for GMSS
+ */
+public class GMSSRandom
+{
+ /**
+ * Hash function for the construction of the authentication trees
+ */
+ private Digest messDigestTree;
+
+ /**
+ * Constructor
+ *
+ * @param messDigestTree2
+ */
+ public GMSSRandom(Digest messDigestTree2)
+ {
+
+ this.messDigestTree = messDigestTree2;
+ }
+
+ /**
+ * computes the next seed value, returns a random byte array and sets
+ * outseed to the next value
+ *
+ * @param outseed byte array in which ((1 + SEEDin +RAND) mod 2^n) will be
+ * stored
+ * @return byte array of H(SEEDin)
+ */
+ public byte[] nextSeed(byte[] outseed)
+ {
+ // RAND <-- H(SEEDin)
+ byte[] rand = new byte[outseed.length];
+ messDigestTree.update(outseed, 0, outseed.length);
+ rand = new byte[messDigestTree.getDigestSize()];
+ messDigestTree.doFinal(rand, 0);
+
+ // SEEDout <-- (1 + SEEDin +RAND) mod 2^n
+ addByteArrays(outseed, rand);
+ addOne(outseed);
+
+ // System.arraycopy(outseed, 0, outseed, 0, outseed.length);
+
+ return rand;
+ }
+
+ private void addByteArrays(byte[] a, byte[] b)
+ {
+
+ byte overflow = 0;
+ int temp;
+
+ for (int i = 0; i < a.length; i++)
+ {
+ temp = (0xFF & a[i]) + (0xFF & b[i]) + overflow;
+ a[i] = (byte)temp;
+ overflow = (byte)(temp >> 8);
+ }
+ }
+
+ private void addOne(byte[] a)
+ {
+
+ byte overflow = 1;
+ int temp;
+
+ for (int i = 0; i < a.length; i++)
+ {
+ temp = (0xFF & a[i]) + overflow;
+ a[i] = (byte)temp;
+ overflow = (byte)(temp >> 8);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/GMSSUtil.java b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/GMSSUtil.java
new file mode 100644
index 00000000..57678d85
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/GMSSUtil.java
@@ -0,0 +1,151 @@
+package org.spongycastle.pqc.crypto.gmss.util;
+
+/**
+ * This class provides several methods that are required by the GMSS classes.
+ */
+public class GMSSUtil
+{
+ /**
+ * Converts a 32 bit integer into a byte array beginning at
+ * <code>offset</code> (little-endian representation)
+ *
+ * @param value the integer to convert
+ */
+ public byte[] intToBytesLittleEndian(int value)
+ {
+ byte[] bytes = new byte[4];
+
+ bytes[0] = (byte)((value) & 0xff);
+ bytes[1] = (byte)((value >> 8) & 0xff);
+ bytes[2] = (byte)((value >> 16) & 0xff);
+ bytes[3] = (byte)((value >> 24) & 0xff);
+ return bytes;
+ }
+
+ /**
+ * Converts a byte array beginning at <code>offset</code> into a 32 bit
+ * integer (little-endian representation)
+ *
+ * @param bytes the byte array
+ * @return The resulting integer
+ */
+ public int bytesToIntLittleEndian(byte[] bytes)
+ {
+
+ return ((bytes[0] & 0xff)) | ((bytes[1] & 0xff) << 8)
+ | ((bytes[2] & 0xff) << 16) | ((bytes[3] & 0xff)) << 24;
+ }
+
+ /**
+ * Converts a byte array beginning at <code>offset</code> into a 32 bit
+ * integer (little-endian representation)
+ *
+ * @param bytes the byte array
+ * @param offset the integer offset into the byte array
+ * @return The resulting integer
+ */
+ public int bytesToIntLittleEndian(byte[] bytes, int offset)
+ {
+ return ((bytes[offset++] & 0xff)) | ((bytes[offset++] & 0xff) << 8)
+ | ((bytes[offset++] & 0xff) << 16)
+ | ((bytes[offset] & 0xff)) << 24;
+ }
+
+ /**
+ * This method concatenates a 2-dimensional byte array into a 1-dimensional
+ * byte array
+ *
+ * @param arraycp a 2-dimensional byte array.
+ * @return 1-dimensional byte array with concatenated input array
+ */
+ public byte[] concatenateArray(byte[][] arraycp)
+ {
+ byte[] dest = new byte[arraycp.length * arraycp[0].length];
+ int indx = 0;
+ for (int i = 0; i < arraycp.length; i++)
+ {
+ System.arraycopy(arraycp[i], 0, dest, indx, arraycp[i].length);
+ indx = indx + arraycp[i].length;
+ }
+ return dest;
+ }
+
+ /**
+ * This method prints the values of a 2-dimensional byte array
+ *
+ * @param text a String
+ * @param array a 2-dimensional byte array
+ */
+ public void printArray(String text, byte[][] array)
+ {
+ System.out.println(text);
+ int counter = 0;
+ for (int i = 0; i < array.length; i++)
+ {
+ for (int j = 0; j < array[0].length; j++)
+ {
+ System.out.println(counter + "; " + array[i][j]);
+ counter++;
+ }
+ }
+ }
+
+ /**
+ * This method prints the values of a 1-dimensional byte array
+ *
+ * @param text a String
+ * @param array a 1-dimensional byte array.
+ */
+ public void printArray(String text, byte[] array)
+ {
+ System.out.println(text);
+ int counter = 0;
+ for (int i = 0; i < array.length; i++)
+ {
+ System.out.println(counter + "; " + array[i]);
+ counter++;
+ }
+ }
+
+ /**
+ * This method tests if an integer is a power of 2.
+ *
+ * @param testValue an integer
+ * @return <code>TRUE</code> if <code>testValue</code> is a power of 2,
+ * <code>FALSE</code> otherwise
+ */
+ public boolean testPowerOfTwo(int testValue)
+ {
+ int a = 1;
+ while (a < testValue)
+ {
+ a <<= 1;
+ }
+ if (testValue == a)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * This method returns the least integer that is greater or equal to the
+ * logarithm to the base 2 of an integer <code>intValue</code>.
+ *
+ * @param intValue an integer
+ * @return The least integer greater or equal to the logarithm to the base 2
+ * of <code>intValue</code>
+ */
+ public int getLog(int intValue)
+ {
+ int log = 1;
+ int i = 2;
+ while (i < intValue)
+ {
+ i <<= 1;
+ log++;
+ }
+ return log;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/WinternitzOTSVerify.java b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/WinternitzOTSVerify.java
new file mode 100644
index 00000000..0a1e52eb
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/WinternitzOTSVerify.java
@@ -0,0 +1,344 @@
+package org.spongycastle.pqc.crypto.gmss.util;
+
+import org.spongycastle.crypto.Digest;
+
+/**
+ * This class implements signature verification of the Winternitz one-time
+ * signature scheme (OTSS), described in C.Dods, N.P. Smart, and M. Stam, "Hash
+ * Based Digital Signature Schemes", LNCS 3796, pages 96&#8211;115, 2005. The
+ * class is used by the GMSS classes.
+ */
+public class WinternitzOTSVerify
+{
+
+ private Digest messDigestOTS;
+
+ /**
+ * The Winternitz parameter
+ */
+ private int w;
+
+ /**
+ * The constructor
+ *
+ * @param digest the name of the hash function used by the OTS and the provider
+ * name of the hash function
+ * @param w the Winternitz parameter
+ */
+ public WinternitzOTSVerify(Digest digest, int w)
+ {
+ this.w = w;
+
+ messDigestOTS = digest;
+ }
+
+ /**
+ * @return The length of the one-time signature
+ */
+ public int getSignatureLength()
+ {
+ int mdsize = messDigestOTS.getDigestSize();
+ int size = ((mdsize << 3) + (w - 1)) / w;
+ int logs = getLog((size << w) + 1);
+ size += (logs + w - 1) / w;
+
+ return mdsize * size;
+ }
+
+ /**
+ * This method computes the public OTS key from the one-time signature of a
+ * message. This is *NOT* a complete OTS signature verification, but it
+ * suffices for usage with CMSS.
+ *
+ * @param message the message
+ * @param signature the one-time signature
+ * @return The public OTS key
+ */
+ public byte[] Verify(byte[] message, byte[] signature)
+ {
+
+ int mdsize = messDigestOTS.getDigestSize();
+ byte[] hash = new byte[mdsize]; // hash of message m
+
+ // create hash of message m
+ messDigestOTS.update(message, 0, message.length);
+ hash = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(hash, 0);
+
+ int size = ((mdsize << 3) + (w - 1)) / w;
+ int logs = getLog((size << w) + 1);
+ int keysize = size + (logs + w - 1) / w;
+
+ int testKeySize = mdsize * keysize;
+
+ if (testKeySize != signature.length)
+ {
+ return null;
+ }
+
+ byte[] testKey = new byte[testKeySize];
+
+ int c = 0;
+ int counter = 0;
+ int test;
+
+ if (8 % w == 0)
+ {
+ int d = 8 / w;
+ int k = (1 << w) - 1;
+ byte[] hlp = new byte[mdsize];
+
+ // verify signature
+ for (int i = 0; i < hash.length; i++)
+ {
+ for (int j = 0; j < d; j++)
+ {
+ test = hash[i] & k;
+ c += test;
+
+ System.arraycopy(signature, counter * mdsize, hlp, 0, mdsize);
+
+ while (test < k)
+ {
+ messDigestOTS.update(hlp, 0, hlp.length);
+ hlp = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(hlp, 0);
+ test++;
+ }
+
+ System.arraycopy(hlp, 0, testKey, counter * mdsize, mdsize);
+ hash[i] = (byte)(hash[i] >>> w);
+ counter++;
+ }
+ }
+
+ c = (size << w) - c;
+ for (int i = 0; i < logs; i += w)
+ {
+ test = c & k;
+
+ System.arraycopy(signature, counter * mdsize, hlp, 0, mdsize);
+
+ while (test < k)
+ {
+ messDigestOTS.update(hlp, 0, hlp.length);
+ hlp = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(hlp, 0);
+ test++;
+ }
+ System.arraycopy(hlp, 0, testKey, counter * mdsize, mdsize);
+ c >>>= w;
+ counter++;
+ }
+ }
+ else if (w < 8)
+ {
+ int d = mdsize / w;
+ int k = (1 << w) - 1;
+ byte[] hlp = new byte[mdsize];
+ long big8;
+ int ii = 0;
+ // create signature
+ // first d*w bytes of hash
+ for (int i = 0; i < d; i++)
+ {
+ big8 = 0;
+ for (int j = 0; j < w; j++)
+ {
+ big8 ^= (hash[ii] & 0xff) << (j << 3);
+ ii++;
+ }
+ for (int j = 0; j < 8; j++)
+ {
+ test = (int)(big8 & k);
+ c += test;
+
+ System.arraycopy(signature, counter * mdsize, hlp, 0, mdsize);
+
+ while (test < k)
+ {
+ messDigestOTS.update(hlp, 0, hlp.length);
+ hlp = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(hlp, 0);
+ test++;
+ }
+
+ System.arraycopy(hlp, 0, testKey, counter * mdsize, mdsize);
+ big8 >>>= w;
+ counter++;
+ }
+ }
+ // rest of hash
+ d = mdsize % w;
+ big8 = 0;
+ for (int j = 0; j < d; j++)
+ {
+ big8 ^= (hash[ii] & 0xff) << (j << 3);
+ ii++;
+ }
+ d <<= 3;
+ for (int j = 0; j < d; j += w)
+ {
+ test = (int)(big8 & k);
+ c += test;
+
+ System.arraycopy(signature, counter * mdsize, hlp, 0, mdsize);
+
+ while (test < k)
+ {
+ messDigestOTS.update(hlp, 0, hlp.length);
+ hlp = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(hlp, 0);
+ test++;
+ }
+
+ System.arraycopy(hlp, 0, testKey, counter * mdsize, mdsize);
+ big8 >>>= w;
+ counter++;
+ }
+
+ // check bytes
+ c = (size << w) - c;
+ for (int i = 0; i < logs; i += w)
+ {
+ test = c & k;
+
+ System.arraycopy(signature, counter * mdsize, hlp, 0, mdsize);
+
+ while (test < k)
+ {
+ messDigestOTS.update(hlp, 0, hlp.length);
+ hlp = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(hlp, 0);
+ test++;
+ }
+
+ System.arraycopy(hlp, 0, testKey, counter * mdsize, mdsize);
+ c >>>= w;
+ counter++;
+ }
+ }// end if(w<8)
+ else if (w < 57)
+ {
+ int d = (mdsize << 3) - w;
+ int k = (1 << w) - 1;
+ byte[] hlp = new byte[mdsize];
+ long big8, test8;
+ int r = 0;
+ int s, f, rest, ii;
+ // create signature
+ // first a*w bits of hash where a*w <= 8*mdsize < (a+1)*w
+ while (r <= d)
+ {
+ s = r >>> 3;
+ rest = r % 8;
+ r += w;
+ f = (r + 7) >>> 3;
+ big8 = 0;
+ ii = 0;
+ for (int j = s; j < f; j++)
+ {
+ big8 ^= (hash[j] & 0xff) << (ii << 3);
+ ii++;
+ }
+
+ big8 >>>= rest;
+ test8 = (big8 & k);
+ c += test8;
+
+ System.arraycopy(signature, counter * mdsize, hlp, 0, mdsize);
+
+ while (test8 < k)
+ {
+ messDigestOTS.update(hlp, 0, hlp.length);
+ hlp = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(hlp, 0);
+ test8++;
+ }
+
+ System.arraycopy(hlp, 0, testKey, counter * mdsize, mdsize);
+ counter++;
+
+ }
+ // rest of hash
+ s = r >>> 3;
+ if (s < mdsize)
+ {
+ rest = r % 8;
+ big8 = 0;
+ ii = 0;
+ for (int j = s; j < mdsize; j++)
+ {
+ big8 ^= (hash[j] & 0xff) << (ii << 3);
+ ii++;
+ }
+
+ big8 >>>= rest;
+ test8 = (big8 & k);
+ c += test8;
+
+ System.arraycopy(signature, counter * mdsize, hlp, 0, mdsize);
+
+ while (test8 < k)
+ {
+ messDigestOTS.update(hlp, 0, hlp.length);
+ hlp = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(hlp, 0);
+ test8++;
+ }
+
+ System.arraycopy(hlp, 0, testKey, counter * mdsize, mdsize);
+ counter++;
+ }
+ // check bytes
+ c = (size << w) - c;
+ for (int i = 0; i < logs; i += w)
+ {
+ test8 = (c & k);
+
+ System.arraycopy(signature, counter * mdsize, hlp, 0, mdsize);
+
+ while (test8 < k)
+ {
+ messDigestOTS.update(hlp, 0, hlp.length);
+ hlp = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(hlp, 0);
+ test8++;
+ }
+
+ System.arraycopy(hlp, 0, testKey, counter * mdsize, mdsize);
+ c >>>= w;
+ counter++;
+ }
+ }// end if(w<57)
+
+ byte[] TKey = new byte[mdsize];
+ messDigestOTS.update(testKey, 0, testKey.length);
+ TKey = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(TKey, 0);
+
+ return TKey;
+
+ }
+
+ /**
+ * This method returns the least integer that is greater or equal to the
+ * logarithm to the base 2 of an integer <code>intValue</code>.
+ *
+ * @param intValue an integer
+ * @return The least integer greater or equal to the logarithm to the base
+ * 256 of <code>intValue</code>
+ */
+ public int getLog(int intValue)
+ {
+ int log = 1;
+ int i = 2;
+ while (i < intValue)
+ {
+ i <<= 1;
+ log++;
+ }
+ return log;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/WinternitzOTSignature.java b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/WinternitzOTSignature.java
new file mode 100644
index 00000000..2ec2c1ad
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/WinternitzOTSignature.java
@@ -0,0 +1,404 @@
+package org.spongycastle.pqc.crypto.gmss.util;
+
+import org.spongycastle.crypto.Digest;
+
+/**
+ * This class implements key pair generation and signature generation of the
+ * Winternitz one-time signature scheme (OTSS), described in C.Dods, N.P. Smart,
+ * and M. Stam, "Hash Based Digital Signature Schemes", LNCS 3796, pages
+ * 96&#8211;115, 2005. The class is used by the GMSS classes.
+ */
+
+public class WinternitzOTSignature
+{
+
+ /**
+ * The hash function used by the OTS
+ */
+ private Digest messDigestOTS;
+
+ /**
+ * The length of the message digest and private key
+ */
+ private int mdsize, keysize;
+
+ /**
+ * An array of strings, containing the name of the used hash function, the
+ * name of the PRGN and the names of the corresponding providers
+ */
+ // private String[] name = new String[2];
+ /**
+ * The private key
+ */
+ private byte[][] privateKeyOTS;
+
+ /**
+ * The Winternitz parameter
+ */
+ private int w;
+
+ /**
+ * The source of randomness for OTS private key generation
+ */
+ private GMSSRandom gmssRandom;
+
+ /**
+ * Sizes of the message and the checksum, both
+ */
+ private int messagesize, checksumsize;
+
+ /**
+ * The constructor generates an OTS key pair, using <code>seed0</code> and
+ * the PRNG
+ *
+ * @param seed0 the seed for the PRGN
+ * @param digest an array of strings, containing the name of the used hash
+ * function, the name of the PRGN and the names of the
+ * corresponding providers
+ * @param w the Winternitz parameter
+ */
+ public WinternitzOTSignature(byte[] seed0, Digest digest, int w)
+ {
+ // this.name = name;
+ this.w = w;
+
+ messDigestOTS = digest;
+
+ gmssRandom = new GMSSRandom(messDigestOTS);
+
+ // calulate keysize for private and public key and also the help
+ // array
+
+ mdsize = messDigestOTS.getDigestSize();
+ int mdsizeBit = mdsize << 3;
+ messagesize = (int)Math.ceil((double)(mdsizeBit) / (double)w);
+
+ checksumsize = getLog((messagesize << w) + 1);
+
+ keysize = messagesize
+ + (int)Math.ceil((double)checksumsize / (double)w);
+
+ /*
+ * mdsize = messDigestOTS.getDigestLength(); messagesize =
+ * ((mdsize<<3)+(w-1))/w;
+ *
+ * checksumsize = getlog((messagesize<<w)+1);
+ *
+ * keysize = messagesize + (checksumsize+w-1)/w;
+ */
+ // define the private key messagesize
+ privateKeyOTS = new byte[keysize][mdsize];
+
+ // gmssRandom.setSeed(seed0);
+ byte[] dummy = new byte[mdsize];
+ System.arraycopy(seed0, 0, dummy, 0, dummy.length);
+
+ // generate random bytes and
+ // assign them to the private key
+ for (int i = 0; i < keysize; i++)
+ {
+ privateKeyOTS[i] = gmssRandom.nextSeed(dummy);
+ }
+ }
+
+ /**
+ * @return The private OTS key
+ */
+ public byte[][] getPrivateKey()
+ {
+ return privateKeyOTS;
+ }
+
+ /**
+ * @return The public OTS key
+ */
+ public byte[] getPublicKey()
+ {
+ byte[] helppubKey = new byte[keysize * mdsize];
+
+ byte[] help = new byte[mdsize];
+ int two_power_t = 1 << w;
+
+ for (int i = 0; i < keysize; i++)
+ {
+ // hash w-1 time the private key and assign it to the public key
+ messDigestOTS.update(privateKeyOTS[i], 0, privateKeyOTS[i].length);
+ help = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(help, 0);
+ for (int j = 2; j < two_power_t; j++)
+ {
+ messDigestOTS.update(help, 0, help.length);
+ help = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(help, 0);
+ }
+ System.arraycopy(help, 0, helppubKey, mdsize * i, mdsize);
+ }
+
+ messDigestOTS.update(helppubKey, 0, helppubKey.length);
+ byte[] tmp = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(tmp, 0);
+ return tmp;
+ }
+
+ /**
+ * @return The one-time signature of the message, generated with the private
+ * key
+ */
+ public byte[] getSignature(byte[] message)
+ {
+ byte[] sign = new byte[keysize * mdsize];
+ // byte [] message; // message m as input
+ byte[] hash = new byte[mdsize]; // hash of message m
+ int counter = 0;
+ int c = 0;
+ int test = 0;
+ // create hash of message m
+ messDigestOTS.update(message, 0, message.length);
+ hash = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(hash, 0);
+
+ if (8 % w == 0)
+ {
+ int d = 8 / w;
+ int k = (1 << w) - 1;
+ byte[] hlp = new byte[mdsize];
+
+ // create signature
+ for (int i = 0; i < hash.length; i++)
+ {
+ for (int j = 0; j < d; j++)
+ {
+ test = hash[i] & k;
+ c += test;
+
+ System.arraycopy(privateKeyOTS[counter], 0, hlp, 0, mdsize);
+
+ while (test > 0)
+ {
+ messDigestOTS.update(hlp, 0, hlp.length);
+ hlp = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(hlp, 0);
+ test--;
+ }
+ System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize);
+ hash[i] = (byte)(hash[i] >>> w);
+ counter++;
+ }
+ }
+
+ c = (messagesize << w) - c;
+ for (int i = 0; i < checksumsize; i += w)
+ {
+ test = c & k;
+
+ System.arraycopy(privateKeyOTS[counter], 0, hlp, 0, mdsize);
+
+ while (test > 0)
+ {
+ messDigestOTS.update(hlp, 0, hlp.length);
+ hlp = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(hlp, 0);
+ test--;
+ }
+ System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize);
+ c >>>= w;
+ counter++;
+ }
+ }
+ else if (w < 8)
+ {
+ int d = mdsize / w;
+ int k = (1 << w) - 1;
+ byte[] hlp = new byte[mdsize];
+ long big8;
+ int ii = 0;
+ // create signature
+ // first d*w bytes of hash
+ for (int i = 0; i < d; i++)
+ {
+ big8 = 0;
+ for (int j = 0; j < w; j++)
+ {
+ big8 ^= (hash[ii] & 0xff) << (j << 3);
+ ii++;
+ }
+ for (int j = 0; j < 8; j++)
+ {
+ test = (int)(big8 & k);
+ c += test;
+
+ System.arraycopy(privateKeyOTS[counter], 0, hlp, 0, mdsize);
+
+ while (test > 0)
+ {
+ messDigestOTS.update(hlp, 0, hlp.length);
+ hlp = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(hlp, 0);
+ test--;
+ }
+ System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize);
+ big8 >>>= w;
+ counter++;
+ }
+ }
+ // rest of hash
+ d = mdsize % w;
+ big8 = 0;
+ for (int j = 0; j < d; j++)
+ {
+ big8 ^= (hash[ii] & 0xff) << (j << 3);
+ ii++;
+ }
+ d <<= 3;
+ for (int j = 0; j < d; j += w)
+ {
+ test = (int)(big8 & k);
+ c += test;
+
+ System.arraycopy(privateKeyOTS[counter], 0, hlp, 0, mdsize);
+
+ while (test > 0)
+ {
+ messDigestOTS.update(hlp, 0, hlp.length);
+ hlp = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(hlp, 0);
+ test--;
+ }
+ System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize);
+ big8 >>>= w;
+ counter++;
+ }
+
+ // check bytes
+ c = (messagesize << w) - c;
+ for (int i = 0; i < checksumsize; i += w)
+ {
+ test = c & k;
+
+ System.arraycopy(privateKeyOTS[counter], 0, hlp, 0, mdsize);
+
+ while (test > 0)
+ {
+ messDigestOTS.update(hlp, 0, hlp.length);
+ hlp = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(hlp, 0);
+ test--;
+ }
+ System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize);
+ c >>>= w;
+ counter++;
+ }
+ }// end if(w<8)
+ else if (w < 57)
+ {
+ int d = (mdsize << 3) - w;
+ int k = (1 << w) - 1;
+ byte[] hlp = new byte[mdsize];
+ long big8, test8;
+ int r = 0;
+ int s, f, rest, ii;
+ // create signature
+ // first a*w bits of hash where a*w <= 8*mdsize < (a+1)*w
+ while (r <= d)
+ {
+ s = r >>> 3;
+ rest = r % 8;
+ r += w;
+ f = (r + 7) >>> 3;
+ big8 = 0;
+ ii = 0;
+ for (int j = s; j < f; j++)
+ {
+ big8 ^= (hash[j] & 0xff) << (ii << 3);
+ ii++;
+ }
+
+ big8 >>>= rest;
+ test8 = (big8 & k);
+ c += test8;
+
+ System.arraycopy(privateKeyOTS[counter], 0, hlp, 0, mdsize);
+ while (test8 > 0)
+ {
+ messDigestOTS.update(hlp, 0, hlp.length);
+ hlp = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(hlp, 0);
+ test8--;
+ }
+ System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize);
+ counter++;
+
+ }
+ // rest of hash
+ s = r >>> 3;
+ if (s < mdsize)
+ {
+ rest = r % 8;
+ big8 = 0;
+ ii = 0;
+ for (int j = s; j < mdsize; j++)
+ {
+ big8 ^= (hash[j] & 0xff) << (ii << 3);
+ ii++;
+ }
+
+ big8 >>>= rest;
+ test8 = (big8 & k);
+ c += test8;
+
+ System.arraycopy(privateKeyOTS[counter], 0, hlp, 0, mdsize);
+ while (test8 > 0)
+ {
+ messDigestOTS.update(hlp, 0, hlp.length);
+ hlp = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(hlp, 0);
+ test8--;
+ }
+ System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize);
+ counter++;
+ }
+ // check bytes
+ c = (messagesize << w) - c;
+ for (int i = 0; i < checksumsize; i += w)
+ {
+ test8 = (c & k);
+
+ System.arraycopy(privateKeyOTS[counter], 0, hlp, 0, mdsize);
+
+ while (test8 > 0)
+ {
+ messDigestOTS.update(hlp, 0, hlp.length);
+ hlp = new byte[messDigestOTS.getDigestSize()];
+ messDigestOTS.doFinal(hlp, 0);
+ test8--;
+ }
+ System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize);
+ c >>>= w;
+ counter++;
+ }
+ }// end if(w<57)
+
+ return sign;
+ }
+
+ /**
+ * This method returns the least integer that is greater or equal to the
+ * logarithm to the base 2 of an integer <code>intValue</code>.
+ *
+ * @param intValue an integer
+ * @return The least integer greater or equal to the logarithm to the base 2
+ * of <code>intValue</code>
+ */
+ public int getLog(int intValue)
+ {
+ int log = 1;
+ int i = 2;
+ while (i < intValue)
+ {
+ i <<= 1;
+ log++;
+ }
+ return log;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/Conversions.java b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/Conversions.java
new file mode 100644
index 00000000..9772d018
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/Conversions.java
@@ -0,0 +1,236 @@
+package org.spongycastle.pqc.crypto.mceliece;
+
+import java.math.BigInteger;
+
+import org.spongycastle.pqc.math.linearalgebra.BigIntUtils;
+import org.spongycastle.pqc.math.linearalgebra.GF2Vector;
+import org.spongycastle.pqc.math.linearalgebra.IntegerFunctions;
+
+
+/**
+ * Provides methods for CCA2-Secure Conversions of McEliece PKCS
+ */
+final class Conversions
+{
+ private static final BigInteger ZERO = BigInteger.valueOf(0);
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ /**
+ * Default constructor (private).
+ */
+ private Conversions()
+ {
+ }
+
+ /**
+ * Encode a number between 0 and (n|t) (binomial coefficient) into a binary
+ * vector of length n with weight t. The number is given as a byte array.
+ * Only the first s bits are used, where s = floor[log(n|t)].
+ *
+ * @param n integer
+ * @param t integer
+ * @param m the message as a byte array
+ * @return the encoded message as {@link GF2Vector}
+ */
+ public static GF2Vector encode(final int n, final int t, final byte[] m)
+ {
+ if (n < t)
+ {
+ throw new IllegalArgumentException("n < t");
+ }
+
+ // compute the binomial c = (n|t)
+ BigInteger c = IntegerFunctions.binomial(n, t);
+ // get the number encoded in m
+ BigInteger i = new BigInteger(1, m);
+ // compare
+ if (i.compareTo(c) >= 0)
+ {
+ throw new IllegalArgumentException("Encoded number too large.");
+ }
+
+ GF2Vector result = new GF2Vector(n);
+
+ int nn = n;
+ int tt = t;
+ for (int j = 0; j < n; j++)
+ {
+ c = c.multiply(BigInteger.valueOf(nn - tt)).divide(
+ BigInteger.valueOf(nn));
+ nn--;
+ if (c.compareTo(i) <= 0)
+ {
+ result.setBit(j);
+ i = i.subtract(c);
+ tt--;
+ if (nn == tt)
+ {
+ c = ONE;
+ }
+ else
+ {
+ c = (c.multiply(BigInteger.valueOf(tt + 1)))
+ .divide(BigInteger.valueOf(nn - tt));
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Decode a binary vector of length n and weight t into a number between 0
+ * and (n|t) (binomial coefficient). The result is given as a byte array of
+ * length floor[(s+7)/8], where s = floor[log(n|t)].
+ *
+ * @param n integer
+ * @param t integer
+ * @param vec the binary vector
+ * @return the decoded vector as a byte array
+ */
+ public static byte[] decode(int n, int t, GF2Vector vec)
+ {
+ if ((vec.getLength() != n) || (vec.getHammingWeight() != t))
+ {
+ throw new IllegalArgumentException(
+ "vector has wrong length or hamming weight");
+ }
+ int[] vecArray = vec.getVecArray();
+
+ BigInteger bc = IntegerFunctions.binomial(n, t);
+ BigInteger d = ZERO;
+ int nn = n;
+ int tt = t;
+ for (int i = 0; i < n; i++)
+ {
+ bc = bc.multiply(BigInteger.valueOf(nn - tt)).divide(
+ BigInteger.valueOf(nn));
+ nn--;
+
+ int q = i >> 5;
+ int e = vecArray[q] & (1 << (i & 0x1f));
+ if (e != 0)
+ {
+ d = d.add(bc);
+ tt--;
+ if (nn == tt)
+ {
+ bc = ONE;
+ }
+ else
+ {
+ bc = bc.multiply(BigInteger.valueOf(tt + 1)).divide(
+ BigInteger.valueOf(nn - tt));
+ }
+
+ }
+ }
+
+ return BigIntUtils.toMinimalByteArray(d);
+ }
+
+ /**
+ * Compute a message representative of a message given as a vector of length
+ * <tt>n</tt> bit and of hamming weight <tt>t</tt>. The result is a
+ * byte array of length <tt>(s+7)/8</tt>, where
+ * <tt>s = floor[log(n|t)]</tt>.
+ *
+ * @param n integer
+ * @param t integer
+ * @param m the message vector as a byte array
+ * @return a message representative for <tt>m</tt>
+ */
+ public static byte[] signConversion(int n, int t, byte[] m)
+ {
+ if (n < t)
+ {
+ throw new IllegalArgumentException("n < t");
+ }
+
+ BigInteger bc = IntegerFunctions.binomial(n, t);
+ // finds s = floor[log(binomial(n,t))]
+ int s = bc.bitLength() - 1;
+ // s = sq*8 + sr;
+ int sq = s >> 3;
+ int sr = s & 7;
+ if (sr == 0)
+ {
+ sq--;
+ sr = 8;
+ }
+
+ // n = nq*8+nr;
+ int nq = n >> 3;
+ int nr = n & 7;
+ if (nr == 0)
+ {
+ nq--;
+ nr = 8;
+ }
+ // take s bit from m
+ byte[] data = new byte[nq + 1];
+ if (m.length < data.length)
+ {
+ System.arraycopy(m, 0, data, 0, m.length);
+ for (int i = m.length; i < data.length; i++)
+ {
+ data[i] = 0;
+ }
+ }
+ else
+ {
+ System.arraycopy(m, 0, data, 0, nq);
+ int h = (1 << nr) - 1;
+ data[nq] = (byte)(h & m[nq]);
+ }
+
+ BigInteger d = ZERO;
+ int nn = n;
+ int tt = t;
+ for (int i = 0; i < n; i++)
+ {
+ bc = (bc.multiply(new BigInteger(Integer.toString(nn - tt))))
+ .divide(new BigInteger(Integer.toString(nn)));
+ nn--;
+
+ int q = i >>> 3;
+ int r = i & 7;
+ r = 1 << r;
+ byte e = (byte)(r & data[q]);
+ if (e != 0)
+ {
+ d = d.add(bc);
+ tt--;
+ if (nn == tt)
+ {
+ bc = ONE;
+ }
+ else
+ {
+ bc = (bc
+ .multiply(new BigInteger(Integer.toString(tt + 1))))
+ .divide(new BigInteger(Integer.toString(nn - tt)));
+ }
+ }
+ }
+
+ byte[] result = new byte[sq + 1];
+ byte[] help = d.toByteArray();
+ if (help.length < result.length)
+ {
+ System.arraycopy(help, 0, result, 0, help.length);
+ for (int i = help.length; i < result.length; i++)
+ {
+ result[i] = 0;
+ }
+ }
+ else
+ {
+ System.arraycopy(help, 0, result, 0, sq);
+ result[sq] = (byte)(((1 << sr) - 1) & help[sq]);
+ }
+
+ return result;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2KeyGenerationParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2KeyGenerationParameters.java
new file mode 100644
index 00000000..8095d291
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2KeyGenerationParameters.java
@@ -0,0 +1,25 @@
+package org.spongycastle.pqc.crypto.mceliece;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.KeyGenerationParameters;
+
+public class McElieceCCA2KeyGenerationParameters
+ extends KeyGenerationParameters
+{
+ private McElieceCCA2Parameters params;
+
+ public McElieceCCA2KeyGenerationParameters(
+ SecureRandom random,
+ McElieceCCA2Parameters params)
+ {
+ // XXX key size?
+ super(random, 128);
+ this.params = params;
+ }
+
+ public McElieceCCA2Parameters getParameters()
+ {
+ return params;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2KeyPairGenerator.java b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2KeyPairGenerator.java
new file mode 100644
index 00000000..c950bda7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2KeyPairGenerator.java
@@ -0,0 +1,119 @@
+package org.spongycastle.pqc.crypto.mceliece;
+
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.pqc.math.linearalgebra.GF2Matrix;
+import org.spongycastle.pqc.math.linearalgebra.GF2mField;
+import org.spongycastle.pqc.math.linearalgebra.GoppaCode;
+import org.spongycastle.pqc.math.linearalgebra.GoppaCode.MaMaPe;
+import org.spongycastle.pqc.math.linearalgebra.Permutation;
+import org.spongycastle.pqc.math.linearalgebra.PolynomialGF2mSmallM;
+import org.spongycastle.pqc.math.linearalgebra.PolynomialRingGF2m;
+
+
+/**
+ * This class implements key pair generation of the McEliece Public Key
+ * Cryptosystem (McEliecePKC).
+ */
+public class McElieceCCA2KeyPairGenerator
+ implements AsymmetricCipherKeyPairGenerator
+{
+
+
+ /**
+ * The OID of the algorithm.
+ */
+ public static final String OID = "1.3.6.1.4.1.8301.3.1.3.4.2";
+
+ private McElieceCCA2KeyGenerationParameters mcElieceCCA2Params;
+
+ // the extension degree of the finite field GF(2^m)
+ private int m;
+
+ // the length of the code
+ private int n;
+
+ // the error correction capability
+ private int t;
+
+ // the field polynomial
+ private int fieldPoly;
+
+ // the source of randomness
+ private SecureRandom random;
+
+ // flag indicating whether the key pair generator has been initialized
+ private boolean initialized = false;
+
+ /**
+ * Default initialization of the key pair generator.
+ */
+ private void initializeDefault()
+ {
+ McElieceCCA2KeyGenerationParameters mcCCA2Params = new McElieceCCA2KeyGenerationParameters(new SecureRandom(), new McElieceCCA2Parameters());
+ init(mcCCA2Params);
+ }
+
+ // TODO
+ public void init(
+ KeyGenerationParameters param)
+ {
+ this.mcElieceCCA2Params = (McElieceCCA2KeyGenerationParameters)param;
+
+ // set source of randomness
+ this.random = new SecureRandom();
+
+ this.m = this.mcElieceCCA2Params.getParameters().getM();
+ this.n = this.mcElieceCCA2Params.getParameters().getN();
+ this.t = this.mcElieceCCA2Params.getParameters().getT();
+ this.fieldPoly = this.mcElieceCCA2Params.getParameters().getFieldPoly();
+ this.initialized = true;
+ }
+
+
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+
+ if (!initialized)
+ {
+ initializeDefault();
+ }
+
+ // finite field GF(2^m)
+ GF2mField field = new GF2mField(m, fieldPoly);
+
+ // irreducible Goppa polynomial
+ PolynomialGF2mSmallM gp = new PolynomialGF2mSmallM(field, t,
+ PolynomialGF2mSmallM.RANDOM_IRREDUCIBLE_POLYNOMIAL, random);
+ PolynomialRingGF2m ring = new PolynomialRingGF2m(field, gp);
+
+ // matrix for computing square roots in (GF(2^m))^t
+ PolynomialGF2mSmallM[] qInv = ring.getSquareRootMatrix();
+
+ // generate canonical check matrix
+ GF2Matrix h = GoppaCode.createCanonicalCheckMatrix(field, gp);
+
+ // compute short systematic form of check matrix
+ MaMaPe mmp = GoppaCode.computeSystematicForm(h, random);
+ GF2Matrix shortH = mmp.getSecondMatrix();
+ Permutation p = mmp.getPermutation();
+
+ // compute short systematic form of generator matrix
+ GF2Matrix shortG = (GF2Matrix)shortH.computeTranspose();
+
+ // obtain number of rows of G (= dimension of the code)
+ int k = shortG.getNumRows();
+
+ // generate keys
+ McElieceCCA2PublicKeyParameters pubKey = new McElieceCCA2PublicKeyParameters(OID, n, t, shortG, mcElieceCCA2Params.getParameters());
+ McElieceCCA2PrivateKeyParameters privKey = new McElieceCCA2PrivateKeyParameters(OID, n, k,
+ field, gp, p, h, qInv, mcElieceCCA2Params.getParameters());
+
+ // return key pair
+ return new AsymmetricCipherKeyPair(pubKey, privKey);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2KeyParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2KeyParameters.java
new file mode 100644
index 00000000..4dc3b8d2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2KeyParameters.java
@@ -0,0 +1,25 @@
+package org.spongycastle.pqc.crypto.mceliece;
+
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+
+
+public class McElieceCCA2KeyParameters
+ extends AsymmetricKeyParameter
+{
+ private McElieceCCA2Parameters params;
+
+ public McElieceCCA2KeyParameters(
+ boolean isPrivate,
+ McElieceCCA2Parameters params)
+ {
+ super(isPrivate);
+ this.params = params;
+ }
+
+
+ public McElieceCCA2Parameters getParameters()
+ {
+ return params;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2Parameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2Parameters.java
new file mode 100644
index 00000000..11eae2e0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2Parameters.java
@@ -0,0 +1,51 @@
+package org.spongycastle.pqc.crypto.mceliece;
+
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+
+/**
+ * This class provides a specification for the parameters of the CCA2-secure
+ * variants of the McEliece PKCS that are used with
+ * {@link McElieceFujisakiCipher}, {@link McElieceKobaraImaiCipher}, and
+ * {@link McEliecePointchevalCipher}.
+ *
+ * @see McElieceFujisakiCipher
+ * @see McElieceKobaraImaiCipher
+ * @see McEliecePointchevalCipher
+ */
+public class McElieceCCA2Parameters
+ extends McElieceParameters
+{
+
+
+ public Digest digest;
+
+
+ /**
+ * Construct the default parameters.
+ * The default message digest is SHA256.
+ */
+ public McElieceCCA2Parameters()
+ {
+ this.digest = new SHA256Digest();
+ }
+
+ public McElieceCCA2Parameters(int m, int t)
+ {
+ super(m, t);
+ this.digest = new SHA256Digest();
+ }
+
+ public McElieceCCA2Parameters(Digest digest)
+ {
+ this.digest = digest;
+ }
+
+ public Digest getDigest()
+ {
+ return this.digest;
+ }
+
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2Primitives.java b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2Primitives.java
new file mode 100644
index 00000000..66c163a2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2Primitives.java
@@ -0,0 +1,86 @@
+package org.spongycastle.pqc.crypto.mceliece;
+
+import org.spongycastle.pqc.math.linearalgebra.GF2Matrix;
+import org.spongycastle.pqc.math.linearalgebra.GF2Vector;
+import org.spongycastle.pqc.math.linearalgebra.GF2mField;
+import org.spongycastle.pqc.math.linearalgebra.GoppaCode;
+import org.spongycastle.pqc.math.linearalgebra.Permutation;
+import org.spongycastle.pqc.math.linearalgebra.PolynomialGF2mSmallM;
+import org.spongycastle.pqc.math.linearalgebra.Vector;
+
+/**
+ * Core operations for the CCA-secure variants of McEliece.
+ */
+public final class McElieceCCA2Primitives
+{
+
+ /**
+ * Default constructor (private).
+ */
+ private McElieceCCA2Primitives()
+ {
+ }
+
+ /**
+ * The McEliece encryption primitive.
+ *
+ * @param pubKey the public key
+ * @param m the message vector
+ * @param z the error vector
+ * @return <tt>m*G + z</tt>
+ */
+
+
+ public static GF2Vector encryptionPrimitive(McElieceCCA2PublicKeyParameters pubKey,
+ GF2Vector m, GF2Vector z)
+ {
+
+ GF2Matrix matrixG = pubKey.getMatrixG();
+ Vector mG = matrixG.leftMultiplyLeftCompactForm(m);
+ return (GF2Vector)mG.add(z);
+ }
+
+ /**
+ * The McEliece decryption primitive.
+ *
+ * @param privKey the private key
+ * @param c the ciphertext vector <tt>c = m*G + z</tt>
+ * @return the message vector <tt>m</tt> and the error vector <tt>z</tt>
+ */
+ public static GF2Vector[] decryptionPrimitive(
+ McElieceCCA2PrivateKeyParameters privKey, GF2Vector c)
+ {
+
+ // obtain values from private key
+ int k = privKey.getK();
+ Permutation p = privKey.getP();
+ GF2mField field = privKey.getField();
+ PolynomialGF2mSmallM gp = privKey.getGoppaPoly();
+ GF2Matrix h = privKey.getH();
+ PolynomialGF2mSmallM[] q = privKey.getQInv();
+
+ // compute inverse permutation P^-1
+ Permutation pInv = p.computeInverse();
+
+ // multiply c with permutation P^-1
+ GF2Vector cPInv = (GF2Vector)c.multiply(pInv);
+
+ // compute syndrome of cP^-1
+ GF2Vector syndVec = (GF2Vector)h.rightMultiply(cPInv);
+
+ // decode syndrome
+ GF2Vector errors = GoppaCode.syndromeDecode(syndVec, field, gp, q);
+ GF2Vector mG = (GF2Vector)cPInv.add(errors);
+
+ // multiply codeword and error vector with P
+ mG = (GF2Vector)mG.multiply(p);
+ errors = (GF2Vector)errors.multiply(p);
+
+ // extract plaintext vector (last k columns of mG)
+ GF2Vector m = mG.extractRightVector(k);
+
+ // return vectors
+ return new GF2Vector[]{m, errors};
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2PrivateKeyParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2PrivateKeyParameters.java
new file mode 100644
index 00000000..a19a267b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2PrivateKeyParameters.java
@@ -0,0 +1,172 @@
+package org.spongycastle.pqc.crypto.mceliece;
+
+
+import org.spongycastle.pqc.math.linearalgebra.GF2Matrix;
+import org.spongycastle.pqc.math.linearalgebra.GF2mField;
+import org.spongycastle.pqc.math.linearalgebra.Permutation;
+import org.spongycastle.pqc.math.linearalgebra.PolynomialGF2mSmallM;
+
+/**
+ *
+ *
+ *
+ */
+public class McElieceCCA2PrivateKeyParameters
+ extends McElieceCCA2KeyParameters
+{
+
+ // the OID of the algorithm
+ private String oid;
+
+ // the length of the code
+ private int n;
+
+ // the dimension of the code
+ private int k;
+
+ // the finte field GF(2^m)
+ private GF2mField field;
+
+ // the irreducible Goppa polynomial
+ private PolynomialGF2mSmallM goppaPoly;
+
+ // the permutation
+ private Permutation p;
+
+ // the canonical check matrix
+ private GF2Matrix h;
+
+ // the matrix used to compute square roots in (GF(2^m))^t
+ private PolynomialGF2mSmallM[] qInv;
+
+ /**
+ * Constructor.
+ *
+ * @param n the length of the code
+ * @param k the dimension of the code
+ * @param field the finite field <tt>GF(2<sup>m</sup>)</tt>
+ * @param gp the irreducible Goppa polynomial
+ * @param p the permutation
+ * @param h the canonical check matrix
+ * @param qInv the matrix used to compute square roots in
+ * <tt>(GF(2^m))^t</tt>
+ * @param params McElieceCCA2Parameters
+ */
+ public McElieceCCA2PrivateKeyParameters(String oid, int n, int k, GF2mField field,
+ PolynomialGF2mSmallM gp, Permutation p, GF2Matrix h,
+ PolynomialGF2mSmallM[] qInv, McElieceCCA2Parameters params)
+ {
+ super(true, params);
+ this.oid = oid;
+ this.n = n;
+ this.k = k;
+ this.field = field;
+ this.goppaPoly = gp;
+ this.p = p;
+ this.h = h;
+ this.qInv = qInv;
+ }
+
+ /**
+ * Constructor used by the {@link McElieceKeyFactory}.
+ *
+ * @param n the length of the code
+ * @param k the dimension of the code
+ * @param encFieldPoly the encoded field polynomial defining the finite field
+ * <tt>GF(2<sup>m</sup>)</tt>
+ * @param encGoppaPoly the encoded irreducible Goppa polynomial
+ * @param encP the encoded permutation
+ * @param encH the encoded canonical check matrix
+ * @param encQInv the encoded matrix used to compute square roots in
+ * <tt>(GF(2^m))^t</tt>
+ * @param params McElieceCCA2Parameters
+ */
+ public McElieceCCA2PrivateKeyParameters(String oid, int n, int k, byte[] encFieldPoly,
+ byte[] encGoppaPoly, byte[] encP, byte[] encH, byte[][] encQInv, McElieceCCA2Parameters params)
+ {
+ super(true, params);
+ this.oid = oid;
+ this.n = n;
+ this.k = k;
+ field = new GF2mField(encFieldPoly);
+ goppaPoly = new PolynomialGF2mSmallM(field, encGoppaPoly);
+ p = new Permutation(encP);
+ h = new GF2Matrix(encH);
+ qInv = new PolynomialGF2mSmallM[encQInv.length];
+ for (int i = 0; i < encQInv.length; i++)
+ {
+ qInv[i] = new PolynomialGF2mSmallM(field, encQInv[i]);
+ }
+ }
+
+ /**
+ * @return the length of the code
+ */
+ public int getN()
+ {
+ return n;
+ }
+
+ /**
+ * @return the dimension of the code
+ */
+ public int getK()
+ {
+ return k;
+ }
+
+ /**
+ * @return the degree of the Goppa polynomial (error correcting capability)
+ */
+ public int getT()
+ {
+ return goppaPoly.getDegree();
+ }
+
+ /**
+ * @return the finite field
+ */
+ public GF2mField getField()
+ {
+ return field;
+ }
+
+ /**
+ * @return the irreducible Goppa polynomial
+ */
+ public PolynomialGF2mSmallM getGoppaPoly()
+ {
+ return goppaPoly;
+ }
+
+ /**
+ * @return the permutation P
+ */
+ public Permutation getP()
+ {
+ return p;
+ }
+
+ /**
+ * @return the canonical check matrix H
+ */
+ public GF2Matrix getH()
+ {
+ return h;
+ }
+
+ /**
+ * @return the matrix used to compute square roots in <tt>(GF(2^m))^t</tt>
+ */
+ public PolynomialGF2mSmallM[] getQInv()
+ {
+ return qInv;
+ }
+
+ public String getOIDString()
+ {
+ return oid;
+
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2PublicKeyParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2PublicKeyParameters.java
new file mode 100644
index 00000000..9b5ba0a6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceCCA2PublicKeyParameters.java
@@ -0,0 +1,97 @@
+package org.spongycastle.pqc.crypto.mceliece;
+
+import org.spongycastle.pqc.math.linearalgebra.GF2Matrix;
+
+/**
+ *
+ *
+ *
+ */
+public class McElieceCCA2PublicKeyParameters
+ extends McElieceCCA2KeyParameters
+{
+
+ // the OID of the algorithm
+ private String oid;
+
+ // the length of the code
+ private int n;
+
+ // the error correction capability of the code
+ private int t;
+
+ // the generator matrix
+ private GF2Matrix matrixG;
+
+ /**
+ * Constructor.
+ *
+ * @param n length of the code
+ * @param t error correction capability
+ * @param matrix generator matrix
+ * @param params McElieceCCA2Parameters
+ */
+ public McElieceCCA2PublicKeyParameters(String oid, int n, int t, GF2Matrix matrix, McElieceCCA2Parameters params)
+ {
+ super(false, params);
+ this.oid = oid;
+ this.n = n;
+ this.t = t;
+ this.matrixG = new GF2Matrix(matrix);
+ }
+
+ /**
+ * Constructor (used by {@link McElieceKeyFactory}).
+ *
+ * @param n length of the code
+ * @param t error correction capability of the code
+ * @param encMatrix encoded generator matrix
+ * @param params McElieceCCA2Parameters
+ */
+ public McElieceCCA2PublicKeyParameters(String oid, int n, int t, byte[] encMatrix, McElieceCCA2Parameters params)
+ {
+ super(false, params);
+ this.oid = oid;
+ this.n = n;
+ this.t = t;
+ this.matrixG = new GF2Matrix(encMatrix);
+ }
+
+ /**
+ * @return the length of the code
+ */
+ public int getN()
+ {
+ return n;
+ }
+
+ /**
+ * @return the error correction capability of the code
+ */
+ public int getT()
+ {
+ return t;
+ }
+
+ /**
+ * @return the generator matrix
+ */
+ public GF2Matrix getMatrixG()
+ {
+ return matrixG;
+ }
+
+ /**
+ * @return the dimension of the code
+ */
+ public int getK()
+ {
+ return matrixG.getNumRows();
+ }
+
+ public String getOIDString()
+ {
+ return oid;
+
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceFujisakiCipher.java b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceFujisakiCipher.java
new file mode 100644
index 00000000..810a69c8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceFujisakiCipher.java
@@ -0,0 +1,218 @@
+package org.spongycastle.pqc.crypto.mceliece;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.prng.DigestRandomGenerator;
+import org.spongycastle.pqc.crypto.MessageEncryptor;
+import org.spongycastle.pqc.math.linearalgebra.ByteUtils;
+import org.spongycastle.pqc.math.linearalgebra.GF2Vector;
+
+/**
+ * This class implements the Fujisaki/Okamoto conversion of the McEliecePKCS.
+ * Fujisaki and Okamoto propose hybrid encryption that merges a symmetric
+ * encryption scheme which is secure in the find-guess model with an asymmetric
+ * one-way encryption scheme which is sufficiently probabilistic to obtain a
+ * public key cryptosystem which is CCA2-secure. For details, see D. Engelbert,
+ * R. Overbeck, A. Schmidt, "A summary of the development of the McEliece
+ * Cryptosystem", technical report.
+ */
+public class McElieceFujisakiCipher
+ implements MessageEncryptor
+{
+
+
+ /**
+ * The OID of the algorithm.
+ */
+ public static final String OID = "1.3.6.1.4.1.8301.3.1.3.4.2.1";
+
+ private static final String DEFAULT_PRNG_NAME = "SHA1PRNG";
+
+ private Digest messDigest;
+
+ private SecureRandom sr;
+
+ /**
+ * The McEliece main parameters
+ */
+ private int n, k, t;
+
+ McElieceCCA2KeyParameters key;
+
+
+ public void init(boolean forSigning,
+ CipherParameters param)
+ {
+
+ if (forSigning)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.sr = rParam.getRandom();
+ this.key = (McElieceCCA2PublicKeyParameters)rParam.getParameters();
+ this.initCipherEncrypt((McElieceCCA2PublicKeyParameters)key);
+
+ }
+ else
+ {
+ this.sr = new SecureRandom();
+ this.key = (McElieceCCA2PublicKeyParameters)param;
+ this.initCipherEncrypt((McElieceCCA2PublicKeyParameters)key);
+ }
+ }
+ else
+ {
+ this.key = (McElieceCCA2PrivateKeyParameters)param;
+ this.initCipherDecrypt((McElieceCCA2PrivateKeyParameters)key);
+ }
+
+ }
+
+
+ public int getKeySize(McElieceCCA2KeyParameters key)
+ throws IllegalArgumentException
+ {
+
+ if (key instanceof McElieceCCA2PublicKeyParameters)
+ {
+ return ((McElieceCCA2PublicKeyParameters)key).getN();
+
+ }
+ if (key instanceof McElieceCCA2PrivateKeyParameters)
+ {
+ return ((McElieceCCA2PrivateKeyParameters)key).getN();
+ }
+ throw new IllegalArgumentException("unsupported type");
+
+ }
+
+
+ private void initCipherEncrypt(McElieceCCA2PublicKeyParameters pubKey)
+ {
+ this.sr = sr != null ? sr : new SecureRandom();
+ this.messDigest = pubKey.getParameters().getDigest();
+ n = pubKey.getN();
+ k = pubKey.getK();
+ t = pubKey.getT();
+ }
+
+
+ public void initCipherDecrypt(McElieceCCA2PrivateKeyParameters privKey)
+ {
+ this.messDigest = privKey.getParameters().getDigest();
+ n = privKey.getN();
+ t = privKey.getT();
+ }
+
+
+ public byte[] messageEncrypt(byte[] input)
+ throws Exception
+ {
+
+ // generate random vector r of length k bits
+ GF2Vector r = new GF2Vector(k, sr);
+
+ // convert r to byte array
+ byte[] rBytes = r.getEncoded();
+
+ // compute (r||input)
+ byte[] rm = ByteUtils.concatenate(rBytes, input);
+
+ // compute H(r||input)
+ messDigest.update(rm, 0, rm.length);
+ byte[] hrm = new byte[messDigest.getDigestSize()];
+ messDigest.doFinal(hrm, 0);
+
+ // convert H(r||input) to error vector z
+ GF2Vector z = Conversions.encode(n, t, hrm);
+
+ // compute c1 = E(r, z)
+ byte[] c1 = McElieceCCA2Primitives.encryptionPrimitive((McElieceCCA2PublicKeyParameters)key, r, z)
+ .getEncoded();
+
+ // get PRNG object
+ DigestRandomGenerator sr0 = new DigestRandomGenerator(new SHA1Digest());
+
+ // seed PRNG with r'
+ sr0.addSeedMaterial(rBytes);
+
+ // generate random c2
+ byte[] c2 = new byte[input.length];
+ sr0.nextBytes(c2);
+
+ // XOR with input
+ for (int i = 0; i < input.length; i++)
+ {
+ c2[i] ^= input[i];
+ }
+
+ // return (c1||c2)
+ return ByteUtils.concatenate(c1, c2);
+ }
+
+ public byte[] messageDecrypt(byte[] input)
+ throws Exception
+ {
+
+ int c1Len = (n + 7) >> 3;
+ int c2Len = input.length - c1Len;
+
+ // split ciphertext (c1||c2)
+ byte[][] c1c2 = ByteUtils.split(input, c1Len);
+ byte[] c1 = c1c2[0];
+ byte[] c2 = c1c2[1];
+
+ // decrypt c1 ...
+ GF2Vector hrmVec = GF2Vector.OS2VP(n, c1);
+ GF2Vector[] decC1 = McElieceCCA2Primitives.decryptionPrimitive((McElieceCCA2PrivateKeyParameters)key,
+ hrmVec);
+ byte[] rBytes = decC1[0].getEncoded();
+ // ... and obtain error vector z
+ GF2Vector z = decC1[1];
+
+ // get PRNG object
+ DigestRandomGenerator sr0 = new DigestRandomGenerator(new SHA1Digest());
+
+ // seed PRNG with r'
+ sr0.addSeedMaterial(rBytes);
+
+ // generate random sequence
+ byte[] mBytes = new byte[c2Len];
+ sr0.nextBytes(mBytes);
+
+ // XOR with c2 to obtain m
+ for (int i = 0; i < c2Len; i++)
+ {
+ mBytes[i] ^= c2[i];
+ }
+
+ // compute H(r||m)
+ byte[] rmBytes = ByteUtils.concatenate(rBytes, mBytes);
+ byte[] hrm = new byte[messDigest.getDigestSize()];
+ messDigest.update(rmBytes, 0, rmBytes.length);
+ messDigest.doFinal(hrm, 0);
+
+
+ // compute Conv(H(r||m))
+ hrmVec = Conversions.encode(n, t, hrm);
+
+ // check that Conv(H(m||r)) = z
+ if (!hrmVec.equals(z))
+ {
+
+ throw new Exception("Bad Padding: invalid ciphertext");
+
+ }
+
+ // return plaintext m
+ return mBytes;
+ }
+
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceFujisakiDigestCipher.java b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceFujisakiDigestCipher.java
new file mode 100644
index 00000000..9a5577ce
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceFujisakiDigestCipher.java
@@ -0,0 +1,128 @@
+package org.spongycastle.pqc.crypto.mceliece;
+
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.pqc.crypto.MessageEncryptor;
+
+// TODO should implement some interface?
+public class McElieceFujisakiDigestCipher
+{
+
+ private final Digest messDigest;
+
+ private final MessageEncryptor mcElieceCCA2Cipher;
+
+ private boolean forEncrypting;
+
+
+ public McElieceFujisakiDigestCipher(MessageEncryptor mcElieceCCA2Cipher, Digest messDigest)
+ {
+ this.mcElieceCCA2Cipher = mcElieceCCA2Cipher;
+ this.messDigest = messDigest;
+ }
+
+
+ public void init(boolean forEncrypting,
+ CipherParameters param)
+ {
+
+ this.forEncrypting = forEncrypting;
+ AsymmetricKeyParameter k;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ k = (AsymmetricKeyParameter)((ParametersWithRandom)param).getParameters();
+ }
+ else
+ {
+ k = (AsymmetricKeyParameter)param;
+ }
+
+ if (forEncrypting && k.isPrivate())
+ {
+ throw new IllegalArgumentException("Encrypting Requires Public Key.");
+ }
+
+ if (!forEncrypting && !k.isPrivate())
+ {
+ throw new IllegalArgumentException("Decrypting Requires Private Key.");
+ }
+
+ reset();
+
+ mcElieceCCA2Cipher.init(forEncrypting, param);
+ }
+
+
+ public byte[] messageEncrypt()
+ {
+ if (!forEncrypting)
+ {
+ throw new IllegalStateException("McElieceFujisakiDigestCipher not initialised for encrypting.");
+ }
+
+ byte[] hash = new byte[messDigest.getDigestSize()];
+ messDigest.doFinal(hash, 0);
+ byte[] enc = null;
+
+ try
+ {
+ enc = mcElieceCCA2Cipher.messageEncrypt(hash);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
+
+ return enc;
+ }
+
+
+ public byte[] messageDecrypt(byte[] ciphertext)
+ {
+ byte[] output = null;
+ if (forEncrypting)
+ {
+ throw new IllegalStateException("McElieceFujisakiDigestCipher not initialised for decrypting.");
+ }
+
+
+ try
+ {
+ output = mcElieceCCA2Cipher.messageDecrypt(ciphertext);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
+
+ return output;
+ }
+
+
+ public void update(byte b)
+ {
+ messDigest.update(b);
+
+ }
+
+ public void update(byte[] in, int off, int len)
+ {
+ messDigest.update(in, off, len);
+
+ }
+
+
+ public void reset()
+ {
+ messDigest.reset();
+
+ }
+
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceKeyGenerationParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceKeyGenerationParameters.java
new file mode 100644
index 00000000..129a704c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceKeyGenerationParameters.java
@@ -0,0 +1,25 @@
+package org.spongycastle.pqc.crypto.mceliece;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.KeyGenerationParameters;
+
+public class McElieceKeyGenerationParameters
+ extends KeyGenerationParameters
+{
+ private McElieceParameters params;
+
+ public McElieceKeyGenerationParameters(
+ SecureRandom random,
+ McElieceParameters params)
+ {
+ // XXX key size?
+ super(random, 256);
+ this.params = params;
+ }
+
+ public McElieceParameters getParameters()
+ {
+ return params;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceKeyPairGenerator.java b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceKeyPairGenerator.java
new file mode 100644
index 00000000..07db4cd6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceKeyPairGenerator.java
@@ -0,0 +1,151 @@
+package org.spongycastle.pqc.crypto.mceliece;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.pqc.math.linearalgebra.GF2Matrix;
+import org.spongycastle.pqc.math.linearalgebra.GF2mField;
+import org.spongycastle.pqc.math.linearalgebra.GoppaCode;
+import org.spongycastle.pqc.math.linearalgebra.GoppaCode.MaMaPe;
+import org.spongycastle.pqc.math.linearalgebra.Permutation;
+import org.spongycastle.pqc.math.linearalgebra.PolynomialGF2mSmallM;
+import org.spongycastle.pqc.math.linearalgebra.PolynomialRingGF2m;
+
+
+/**
+ * This class implements key pair generation of the McEliece Public Key
+ * Cryptosystem (McEliecePKC).
+ */
+public class McElieceKeyPairGenerator
+ implements AsymmetricCipherKeyPairGenerator
+{
+
+
+ public McElieceKeyPairGenerator()
+ {
+
+ }
+
+
+ /**
+ * The OID of the algorithm.
+ */
+ private static final String OID = "1.3.6.1.4.1.8301.3.1.3.4.1";
+
+ private McElieceKeyGenerationParameters mcElieceParams;
+
+ // the extension degree of the finite field GF(2^m)
+ private int m;
+
+ // the length of the code
+ private int n;
+
+ // the error correction capability
+ private int t;
+
+ // the field polynomial
+ private int fieldPoly;
+
+ // the source of randomness
+ private SecureRandom random;
+
+ // flag indicating whether the key pair generator has been initialized
+ private boolean initialized = false;
+
+
+ /**
+ * Default initialization of the key pair generator.
+ */
+ private void initializeDefault()
+ {
+ McElieceKeyGenerationParameters mcParams = new McElieceKeyGenerationParameters(new SecureRandom(), new McElieceParameters());
+ initialize(mcParams);
+ }
+
+ private void initialize(
+ KeyGenerationParameters param)
+ {
+ this.mcElieceParams = (McElieceKeyGenerationParameters)param;
+
+ // set source of randomness
+ this.random = new SecureRandom();
+
+ this.m = this.mcElieceParams.getParameters().getM();
+ this.n = this.mcElieceParams.getParameters().getN();
+ this.t = this.mcElieceParams.getParameters().getT();
+ this.fieldPoly = this.mcElieceParams.getParameters().getFieldPoly();
+ this.initialized = true;
+ }
+
+
+ private AsymmetricCipherKeyPair genKeyPair()
+ {
+
+ if (!initialized)
+ {
+ initializeDefault();
+ }
+
+ // finite field GF(2^m)
+ GF2mField field = new GF2mField(m, fieldPoly);
+
+ // irreducible Goppa polynomial
+ PolynomialGF2mSmallM gp = new PolynomialGF2mSmallM(field, t,
+ PolynomialGF2mSmallM.RANDOM_IRREDUCIBLE_POLYNOMIAL, random);
+ PolynomialRingGF2m ring = new PolynomialRingGF2m(field, gp);
+
+ // matrix used to compute square roots in (GF(2^m))^t
+ PolynomialGF2mSmallM[] sqRootMatrix = ring.getSquareRootMatrix();
+
+ // generate canonical check matrix
+ GF2Matrix h = GoppaCode.createCanonicalCheckMatrix(field, gp);
+
+ // compute short systematic form of check matrix
+ MaMaPe mmp = GoppaCode.computeSystematicForm(h, random);
+ GF2Matrix shortH = mmp.getSecondMatrix();
+ Permutation p1 = mmp.getPermutation();
+
+ // compute short systematic form of generator matrix
+ GF2Matrix shortG = (GF2Matrix)shortH.computeTranspose();
+
+ // extend to full systematic form
+ GF2Matrix gPrime = shortG.extendLeftCompactForm();
+
+ // obtain number of rows of G (= dimension of the code)
+ int k = shortG.getNumRows();
+
+ // generate random invertible (k x k)-matrix S and its inverse S^-1
+ GF2Matrix[] matrixSandInverse = GF2Matrix
+ .createRandomRegularMatrixAndItsInverse(k, random);
+
+ // generate random permutation P2
+ Permutation p2 = new Permutation(n, random);
+
+ // compute public matrix G=S*G'*P2
+ GF2Matrix g = (GF2Matrix)matrixSandInverse[0].rightMultiply(gPrime);
+ g = (GF2Matrix)g.rightMultiply(p2);
+
+
+ // generate keys
+ McEliecePublicKeyParameters pubKey = new McEliecePublicKeyParameters(OID, n, t, g, mcElieceParams.getParameters());
+ McEliecePrivateKeyParameters privKey = new McEliecePrivateKeyParameters(OID, n, k,
+ field, gp, matrixSandInverse[1], p1, p2, h, sqRootMatrix, mcElieceParams.getParameters());
+
+ // return key pair
+ return new AsymmetricCipherKeyPair(pubKey, privKey);
+ }
+
+ public void init(KeyGenerationParameters param)
+ {
+ this.initialize(param);
+
+ }
+
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+ return genKeyPair();
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceKeyParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceKeyParameters.java
new file mode 100644
index 00000000..a8b2ce84
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceKeyParameters.java
@@ -0,0 +1,25 @@
+package org.spongycastle.pqc.crypto.mceliece;
+
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+
+
+public class McElieceKeyParameters
+ extends AsymmetricKeyParameter
+{
+ private McElieceParameters params;
+
+ public McElieceKeyParameters(
+ boolean isPrivate,
+ McElieceParameters params)
+ {
+ super(isPrivate);
+ this.params = params;
+ }
+
+
+ public McElieceParameters getParameters()
+ {
+ return params;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceKobaraImaiCipher.java b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceKobaraImaiCipher.java
new file mode 100644
index 00000000..0be981be
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceKobaraImaiCipher.java
@@ -0,0 +1,319 @@
+package org.spongycastle.pqc.crypto.mceliece;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.prng.DigestRandomGenerator;
+import org.spongycastle.pqc.crypto.MessageEncryptor;
+import org.spongycastle.pqc.math.linearalgebra.ByteUtils;
+import org.spongycastle.pqc.math.linearalgebra.GF2Vector;
+import org.spongycastle.pqc.math.linearalgebra.IntegerFunctions;
+
+/**
+ * This class implements the Kobara/Imai conversion of the McEliecePKCS. This is
+ * a conversion of the McEliecePKCS which is CCA2-secure. For details, see D.
+ * Engelbert, R. Overbeck, A. Schmidt, "A summary of the development of the
+ * McEliece Cryptosystem", technical report.
+ */
+public class McElieceKobaraImaiCipher
+ implements MessageEncryptor
+{
+
+ /**
+ * The OID of the algorithm.
+ */
+ public static final String OID = "1.3.6.1.4.1.8301.3.1.3.4.2.3";
+
+ private static final String DEFAULT_PRNG_NAME = "SHA1PRNG";
+
+ /**
+ * A predetermined public constant.
+ */
+ public static final byte[] PUBLIC_CONSTANT = "a predetermined public constant"
+ .getBytes();
+
+
+ private Digest messDigest;
+
+ private SecureRandom sr;
+
+ McElieceCCA2KeyParameters key;
+
+ /**
+ * The McEliece main parameters
+ */
+ private int n, k, t;
+
+
+ public void init(boolean forSigning,
+ CipherParameters param)
+ {
+
+ if (forSigning)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.sr = rParam.getRandom();
+ this.key = (McElieceCCA2PublicKeyParameters)rParam.getParameters();
+ this.initCipherEncrypt((McElieceCCA2PublicKeyParameters)key);
+
+ }
+ else
+ {
+ this.sr = new SecureRandom();
+ this.key = (McElieceCCA2PublicKeyParameters)param;
+ this.initCipherEncrypt((McElieceCCA2PublicKeyParameters)key);
+ }
+ }
+ else
+ {
+ this.key = (McElieceCCA2PrivateKeyParameters)param;
+ this.initCipherDecrypt((McElieceCCA2PrivateKeyParameters)key);
+ }
+
+ }
+
+ /**
+ * Return the key size of the given key object.
+ *
+ * @param key the McElieceCCA2KeyParameters object
+ * @return the key size of the given key object
+ */
+ public int getKeySize(McElieceCCA2KeyParameters key)
+ {
+ if (key instanceof McElieceCCA2PublicKeyParameters)
+ {
+ return ((McElieceCCA2PublicKeyParameters)key).getN();
+
+ }
+ if (key instanceof McElieceCCA2PrivateKeyParameters)
+ {
+ return ((McElieceCCA2PrivateKeyParameters)key).getN();
+ }
+ throw new IllegalArgumentException("unsupported type");
+ }
+
+ private void initCipherEncrypt(McElieceCCA2PublicKeyParameters pubKey)
+ {
+ this.messDigest = pubKey.getParameters().getDigest();
+ n = pubKey.getN();
+ k = pubKey.getK();
+ t = pubKey.getT();
+
+ }
+
+ public void initCipherDecrypt(McElieceCCA2PrivateKeyParameters privKey)
+ {
+ this.messDigest = privKey.getParameters().getDigest();
+ n = privKey.getN();
+ k = privKey.getK();
+ t = privKey.getT();
+ }
+
+ public byte[] messageEncrypt(byte[] input)
+ throws Exception
+ {
+
+ int c2Len = messDigest.getDigestSize();
+ int c4Len = k >> 3;
+ int c5Len = (IntegerFunctions.binomial(n, t).bitLength() - 1) >> 3;
+
+
+ int mLen = c4Len + c5Len - c2Len - PUBLIC_CONSTANT.length;
+ if (input.length > mLen)
+ {
+ mLen = input.length;
+ }
+
+ int c1Len = mLen + PUBLIC_CONSTANT.length;
+ int c6Len = c1Len + c2Len - c4Len - c5Len;
+
+ // compute (m||const)
+ byte[] mConst = new byte[c1Len];
+ System.arraycopy(input, 0, mConst, 0, input.length);
+ System.arraycopy(PUBLIC_CONSTANT, 0, mConst, mLen,
+ PUBLIC_CONSTANT.length);
+
+ // generate random r of length c2Len bytes
+ byte[] r = new byte[c2Len];
+ sr.nextBytes(r);
+
+ // get PRNG object
+ // get PRNG object
+ DigestRandomGenerator sr0 = new DigestRandomGenerator(new SHA1Digest());
+
+ // seed PRNG with r'
+ sr0.addSeedMaterial(r);
+
+ // generate random sequence ...
+ byte[] c1 = new byte[c1Len];
+ sr0.nextBytes(c1);
+
+ // ... and XOR with (m||const) to obtain c1
+ for (int i = c1Len - 1; i >= 0; i--)
+ {
+ c1[i] ^= mConst[i];
+ }
+
+ // compute H(c1) ...
+ byte[] c2 = new byte[messDigest.getDigestSize()];
+ messDigest.update(c1, 0, c1.length);
+ messDigest.doFinal(c2, 0);
+
+ // ... and XOR with r
+ for (int i = c2Len - 1; i >= 0; i--)
+ {
+ c2[i] ^= r[i];
+ }
+
+ // compute (c2||c1)
+ byte[] c2c1 = ByteUtils.concatenate(c2, c1);
+
+ // split (c2||c1) into (c6||c5||c4), where c4Len is k/8 bytes, c5Len is
+ // floor[log(n|t)]/8 bytes, and c6Len is c1Len+c2Len-c4Len-c5Len (may be
+ // 0).
+ byte[] c6 = new byte[0];
+ if (c6Len > 0)
+ {
+ c6 = new byte[c6Len];
+ System.arraycopy(c2c1, 0, c6, 0, c6Len);
+ }
+
+ byte[] c5 = new byte[c5Len];
+ System.arraycopy(c2c1, c6Len, c5, 0, c5Len);
+
+ byte[] c4 = new byte[c4Len];
+ System.arraycopy(c2c1, c6Len + c5Len, c4, 0, c4Len);
+
+ // convert c4 to vector over GF(2)
+ GF2Vector c4Vec = GF2Vector.OS2VP(k, c4);
+
+ // convert c5 to error vector z
+ GF2Vector z = Conversions.encode(n, t, c5);
+
+ // compute encC4 = E(c4, z)
+ byte[] encC4 = McElieceCCA2Primitives.encryptionPrimitive((McElieceCCA2PublicKeyParameters)key,
+ c4Vec, z).getEncoded();
+
+ // if c6Len > 0
+ if (c6Len > 0)
+ {
+ // return (c6||encC4)
+ return ByteUtils.concatenate(c6, encC4);
+ }
+ // else, return encC4
+ return encC4;
+ }
+
+
+ public byte[] messageDecrypt(byte[] input)
+ throws Exception
+ {
+
+ int nDiv8 = n >> 3;
+
+ if (input.length < nDiv8)
+ {
+ throw new Exception("Bad Padding: Ciphertext too short.");
+ }
+
+ int c2Len = messDigest.getDigestSize();
+ int c4Len = k >> 3;
+ int c6Len = input.length - nDiv8;
+
+ // split cipher text (c6||encC4), where c6 may be empty
+ byte[] c6, encC4;
+ if (c6Len > 0)
+ {
+ byte[][] c6EncC4 = ByteUtils.split(input, c6Len);
+ c6 = c6EncC4[0];
+ encC4 = c6EncC4[1];
+ }
+ else
+ {
+ c6 = new byte[0];
+ encC4 = input;
+ }
+
+ // convert encC4 into vector over GF(2)
+ GF2Vector encC4Vec = GF2Vector.OS2VP(n, encC4);
+
+ // decrypt encC4Vec to obtain c4 and error vector z
+ GF2Vector[] c4z = McElieceCCA2Primitives.decryptionPrimitive((McElieceCCA2PrivateKeyParameters)key,
+ encC4Vec);
+ byte[] c4 = c4z[0].getEncoded();
+ GF2Vector z = c4z[1];
+
+ // if length of c4 is greater than c4Len (because of padding) ...
+ if (c4.length > c4Len)
+ {
+ // ... truncate the padding bytes
+ c4 = ByteUtils.subArray(c4, 0, c4Len);
+ }
+
+ // compute c5 = Conv^-1(z)
+ byte[] c5 = Conversions.decode(n, t, z);
+
+ // compute (c6||c5||c4)
+ byte[] c6c5c4 = ByteUtils.concatenate(c6, c5);
+ c6c5c4 = ByteUtils.concatenate(c6c5c4, c4);
+
+ // split (c6||c5||c4) into (c2||c1), where c2Len = mdLen and c1Len =
+ // input.length-c2Len bytes.
+ int c1Len = c6c5c4.length - c2Len;
+ byte[][] c2c1 = ByteUtils.split(c6c5c4, c2Len);
+ byte[] c2 = c2c1[0];
+ byte[] c1 = c2c1[1];
+
+ // compute H(c1) ...
+ byte[] rPrime = new byte[messDigest.getDigestSize()];
+ messDigest.update(c1, 0, c1.length);
+ messDigest.doFinal(rPrime, 0);
+
+ // ... and XOR with c2 to obtain r'
+ for (int i = c2Len - 1; i >= 0; i--)
+ {
+ rPrime[i] ^= c2[i];
+ }
+
+ // get PRNG object
+ DigestRandomGenerator sr0 = new DigestRandomGenerator(new SHA1Digest());
+
+ // seed PRNG with r'
+ sr0.addSeedMaterial(rPrime);
+
+ // generate random sequence R(r') ...
+ byte[] mConstPrime = new byte[c1Len];
+ sr0.nextBytes(mConstPrime);
+
+ // ... and XOR with c1 to obtain (m||const')
+ for (int i = c1Len - 1; i >= 0; i--)
+ {
+ mConstPrime[i] ^= c1[i];
+ }
+
+ if (mConstPrime.length < c1Len)
+ {
+ throw new Exception("Bad Padding: invalid ciphertext");
+ }
+
+ byte[][] temp = ByteUtils.split(mConstPrime, c1Len
+ - PUBLIC_CONSTANT.length);
+ byte[] mr = temp[0];
+ byte[] constPrime = temp[1];
+
+ if (!ByteUtils.equals(constPrime, PUBLIC_CONSTANT))
+ {
+ throw new Exception("Bad Padding: invalid ciphertext");
+ }
+
+ return mr;
+ }
+
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceKobaraImaiDigestCipher.java b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceKobaraImaiDigestCipher.java
new file mode 100644
index 00000000..7df9cc0d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceKobaraImaiDigestCipher.java
@@ -0,0 +1,128 @@
+package org.spongycastle.pqc.crypto.mceliece;
+
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.pqc.crypto.MessageEncryptor;
+
+// TODO should implement some interface?
+public class McElieceKobaraImaiDigestCipher
+{
+
+ private final Digest messDigest;
+
+ private final MessageEncryptor mcElieceCCA2Cipher;
+
+ private boolean forEncrypting;
+
+
+ public McElieceKobaraImaiDigestCipher(MessageEncryptor mcElieceCCA2Cipher, Digest messDigest)
+ {
+ this.mcElieceCCA2Cipher = mcElieceCCA2Cipher;
+ this.messDigest = messDigest;
+ }
+
+
+ public void init(boolean forEncrypting,
+ CipherParameters param)
+ {
+
+ this.forEncrypting = forEncrypting;
+ AsymmetricKeyParameter k;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ k = (AsymmetricKeyParameter)((ParametersWithRandom)param).getParameters();
+ }
+ else
+ {
+ k = (AsymmetricKeyParameter)param;
+ }
+
+ if (forEncrypting && k.isPrivate())
+ {
+ throw new IllegalArgumentException("Encrypting Requires Public Key.");
+ }
+
+ if (!forEncrypting && !k.isPrivate())
+ {
+ throw new IllegalArgumentException("Decrypting Requires Private Key.");
+ }
+
+ reset();
+
+ mcElieceCCA2Cipher.init(forEncrypting, param);
+ }
+
+
+ public byte[] messageEncrypt()
+ {
+ if (!forEncrypting)
+ {
+ throw new IllegalStateException("McElieceKobaraImaiDigestCipher not initialised for encrypting.");
+ }
+
+ byte[] hash = new byte[messDigest.getDigestSize()];
+ messDigest.doFinal(hash, 0);
+ byte[] enc = null;
+
+ try
+ {
+ enc = mcElieceCCA2Cipher.messageEncrypt(hash);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
+
+ return enc;
+ }
+
+
+ public byte[] messageDecrypt(byte[] ciphertext)
+ {
+ byte[] output = null;
+ if (forEncrypting)
+ {
+ throw new IllegalStateException("McElieceKobaraImaiDigestCipher not initialised for decrypting.");
+ }
+
+
+ try
+ {
+ output = mcElieceCCA2Cipher.messageDecrypt(ciphertext);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
+
+ return output;
+ }
+
+
+ public void update(byte b)
+ {
+ messDigest.update(b);
+
+ }
+
+ public void update(byte[] in, int off, int len)
+ {
+ messDigest.update(in, off, len);
+
+ }
+
+
+ public void reset()
+ {
+ messDigest.reset();
+
+ }
+
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePKCSCipher.java b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePKCSCipher.java
new file mode 100644
index 00000000..2e843aa0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePKCSCipher.java
@@ -0,0 +1,224 @@
+package org.spongycastle.pqc.crypto.mceliece;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.pqc.crypto.MessageEncryptor;
+import org.spongycastle.pqc.math.linearalgebra.GF2Matrix;
+import org.spongycastle.pqc.math.linearalgebra.GF2Vector;
+import org.spongycastle.pqc.math.linearalgebra.GF2mField;
+import org.spongycastle.pqc.math.linearalgebra.GoppaCode;
+import org.spongycastle.pqc.math.linearalgebra.Permutation;
+import org.spongycastle.pqc.math.linearalgebra.PolynomialGF2mSmallM;
+import org.spongycastle.pqc.math.linearalgebra.Vector;
+
+/**
+ * This class implements the McEliece Public Key cryptosystem (McEliecePKCS). It
+ * was first described in R.J. McEliece, "A public key cryptosystem based on
+ * algebraic coding theory", DSN progress report, 42-44:114-116, 1978. The
+ * McEliecePKCS is the first cryptosystem which is based on error correcting
+ * codes. The trapdoor for the McEliece cryptosystem using Goppa codes is the
+ * knowledge of the Goppa polynomial used to generate the code.
+ */
+public class McEliecePKCSCipher
+ implements MessageEncryptor
+{
+
+ /**
+ * The OID of the algorithm.
+ */
+ public static final String OID = "1.3.6.1.4.1.8301.3.1.3.4.1";
+
+
+ // the source of randomness
+ private SecureRandom sr;
+
+ // the McEliece main parameters
+ private int n, k, t;
+
+ // The maximum number of bytes the cipher can decrypt
+ public int maxPlainTextSize;
+
+ // The maximum number of bytes the cipher can encrypt
+ public int cipherTextSize;
+
+ McElieceKeyParameters key;
+
+
+ public void init(boolean forSigning,
+ CipherParameters param)
+ {
+
+ if (forSigning)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.sr = rParam.getRandom();
+ this.key = (McEliecePublicKeyParameters)rParam.getParameters();
+ this.initCipherEncrypt((McEliecePublicKeyParameters)key);
+
+ }
+ else
+ {
+ this.sr = new SecureRandom();
+ this.key = (McEliecePublicKeyParameters)param;
+ this.initCipherEncrypt((McEliecePublicKeyParameters)key);
+ }
+ }
+ else
+ {
+ this.key = (McEliecePrivateKeyParameters)param;
+ this.initCipherDecrypt((McEliecePrivateKeyParameters)key);
+ }
+
+ }
+
+
+ /**
+ * Return the key size of the given key object.
+ *
+ * @param key the McElieceKeyParameters object
+ * @return the keysize of the given key object
+ */
+
+ public int getKeySize(McElieceKeyParameters key)
+ {
+
+ if (key instanceof McEliecePublicKeyParameters)
+ {
+ return ((McEliecePublicKeyParameters)key).getN();
+
+ }
+ if (key instanceof McEliecePrivateKeyParameters)
+ {
+ return ((McEliecePrivateKeyParameters)key).getN();
+ }
+ throw new IllegalArgumentException("unsupported type");
+
+ }
+
+
+ public void initCipherEncrypt(McEliecePublicKeyParameters pubKey)
+ {
+ this.sr = sr != null ? sr : new SecureRandom();
+ n = pubKey.getN();
+ k = pubKey.getK();
+ t = pubKey.getT();
+ cipherTextSize = n >> 3;
+ maxPlainTextSize = (k >> 3);
+ }
+
+
+ public void initCipherDecrypt(McEliecePrivateKeyParameters privKey)
+ {
+ n = privKey.getN();
+ k = privKey.getK();
+
+ maxPlainTextSize = (k >> 3);
+ cipherTextSize = n >> 3;
+ }
+
+ /**
+ * Encrypt a plain text.
+ *
+ * @param input the plain text
+ * @return the cipher text
+ */
+ public byte[] messageEncrypt(byte[] input)
+ {
+ GF2Vector m = computeMessageRepresentative(input);
+ GF2Vector z = new GF2Vector(n, t, sr);
+
+ GF2Matrix g = ((McEliecePublicKeyParameters)key).getG();
+ Vector mG = g.leftMultiply(m);
+ GF2Vector mGZ = (GF2Vector)mG.add(z);
+
+ return mGZ.getEncoded();
+ }
+
+ private GF2Vector computeMessageRepresentative(byte[] input)
+ {
+ byte[] data = new byte[maxPlainTextSize + ((k & 0x07) != 0 ? 1 : 0)];
+ System.arraycopy(input, 0, data, 0, input.length);
+ data[input.length] = 0x01;
+ return GF2Vector.OS2VP(k, data);
+ }
+
+ /**
+ * Decrypt a cipher text.
+ *
+ * @param input the cipher text
+ * @return the plain text
+ * @throws Exception if the cipher text is invalid.
+ */
+ public byte[] messageDecrypt(byte[] input)
+ throws Exception
+ {
+ GF2Vector vec = GF2Vector.OS2VP(n, input);
+ McEliecePrivateKeyParameters privKey = (McEliecePrivateKeyParameters)key;
+ GF2mField field = privKey.getField();
+ PolynomialGF2mSmallM gp = privKey.getGoppaPoly();
+ GF2Matrix sInv = privKey.getSInv();
+ Permutation p1 = privKey.getP1();
+ Permutation p2 = privKey.getP2();
+ GF2Matrix h = privKey.getH();
+ PolynomialGF2mSmallM[] qInv = privKey.getQInv();
+
+ // compute permutation P = P1 * P2
+ Permutation p = p1.rightMultiply(p2);
+
+ // compute P^-1
+ Permutation pInv = p.computeInverse();
+
+ // compute c P^-1
+ GF2Vector cPInv = (GF2Vector)vec.multiply(pInv);
+
+ // compute syndrome of c P^-1
+ GF2Vector syndrome = (GF2Vector)h.rightMultiply(cPInv);
+
+ // decode syndrome
+ GF2Vector z = GoppaCode.syndromeDecode(syndrome, field, gp, qInv);
+ GF2Vector mSG = (GF2Vector)cPInv.add(z);
+
+ // multiply codeword with P1 and error vector with P
+ mSG = (GF2Vector)mSG.multiply(p1);
+ z = (GF2Vector)z.multiply(p);
+
+ // extract mS (last k columns of mSG)
+ GF2Vector mS = mSG.extractRightVector(k);
+
+ // compute plaintext vector
+ GF2Vector mVec = (GF2Vector)sInv.leftMultiply(mS);
+
+ // compute and return plaintext
+ return computeMessage(mVec);
+ }
+
+ private byte[] computeMessage(GF2Vector mr)
+ throws Exception
+ {
+ byte[] mrBytes = mr.getEncoded();
+ // find first non-zero byte
+ int index;
+ for (index = mrBytes.length - 1; index >= 0 && mrBytes[index] == 0; index--)
+ {
+ ;
+ }
+
+ // check if padding byte is valid
+ if (mrBytes[index] != 0x01)
+ {
+ throw new Exception("Bad Padding: invalid ciphertext");
+ }
+
+ // extract and return message
+ byte[] mBytes = new byte[index];
+ System.arraycopy(mrBytes, 0, mBytes, 0, index);
+ return mBytes;
+ }
+
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePKCSDigestCipher.java b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePKCSDigestCipher.java
new file mode 100644
index 00000000..901fe688
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePKCSDigestCipher.java
@@ -0,0 +1,128 @@
+package org.spongycastle.pqc.crypto.mceliece;
+
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.pqc.crypto.MessageEncryptor;
+
+// TODO should implement some interface?
+public class McEliecePKCSDigestCipher
+{
+
+ private final Digest messDigest;
+
+ private final MessageEncryptor mcElieceCipher;
+
+ private boolean forEncrypting;
+
+
+ public McEliecePKCSDigestCipher(MessageEncryptor mcElieceCipher, Digest messDigest)
+ {
+ this.mcElieceCipher = mcElieceCipher;
+ this.messDigest = messDigest;
+ }
+
+
+ public void init(boolean forEncrypting,
+ CipherParameters param)
+ {
+
+ this.forEncrypting = forEncrypting;
+ AsymmetricKeyParameter k;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ k = (AsymmetricKeyParameter)((ParametersWithRandom)param).getParameters();
+ }
+ else
+ {
+ k = (AsymmetricKeyParameter)param;
+ }
+
+ if (forEncrypting && k.isPrivate())
+ {
+ throw new IllegalArgumentException("Encrypting Requires Public Key.");
+ }
+
+ if (!forEncrypting && !k.isPrivate())
+ {
+ throw new IllegalArgumentException("Decrypting Requires Private Key.");
+ }
+
+ reset();
+
+ mcElieceCipher.init(forEncrypting, param);
+ }
+
+
+ public byte[] messageEncrypt()
+ {
+ if (!forEncrypting)
+ {
+ throw new IllegalStateException("McEliecePKCSDigestCipher not initialised for encrypting.");
+ }
+
+ byte[] hash = new byte[messDigest.getDigestSize()];
+ messDigest.doFinal(hash, 0);
+ byte[] enc = null;
+
+ try
+ {
+ enc = mcElieceCipher.messageEncrypt(hash);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
+
+ return enc;
+ }
+
+
+ public byte[] messageDecrypt(byte[] ciphertext)
+ {
+ byte[] output = null;
+ if (forEncrypting)
+ {
+ throw new IllegalStateException("McEliecePKCSDigestCipher not initialised for decrypting.");
+ }
+
+
+ try
+ {
+ output = mcElieceCipher.messageDecrypt(ciphertext);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
+
+ return output;
+ }
+
+
+ public void update(byte b)
+ {
+ messDigest.update(b);
+
+ }
+
+ public void update(byte[] in, int off, int len)
+ {
+ messDigest.update(in, off, len);
+
+ }
+
+
+ public void reset()
+ {
+ messDigest.reset();
+
+ }
+
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceParameters.java
new file mode 100644
index 00000000..d49f9279
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McElieceParameters.java
@@ -0,0 +1,181 @@
+package org.spongycastle.pqc.crypto.mceliece;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.pqc.math.linearalgebra.PolynomialRingGF2;
+
+public class McElieceParameters
+ implements CipherParameters
+{
+
+ /**
+ * The default extension degree
+ */
+ public static final int DEFAULT_M = 11;
+
+ /**
+ * The default error correcting capability.
+ */
+ public static final int DEFAULT_T = 50;
+
+ /**
+ * extension degree of the finite field GF(2^m)
+ */
+ private int m;
+
+ /**
+ * error correction capability of the code
+ */
+ private int t;
+
+ /**
+ * length of the code
+ */
+ private int n;
+
+ /**
+ * the field polynomial
+ */
+ private int fieldPoly;
+
+ /**
+ * Constructor. Set the default parameters: extension degree.
+ */
+ public McElieceParameters()
+ {
+ this(DEFAULT_M, DEFAULT_T);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param keysize the length of a Goppa code
+ * @throws IllegalArgumentException if <tt>keysize &lt; 1</tt>.
+ */
+ public McElieceParameters(int keysize)
+ throws IllegalArgumentException
+ {
+ if (keysize < 1)
+ {
+ throw new IllegalArgumentException("key size must be positive");
+ }
+ m = 0;
+ n = 1;
+ while (n < keysize)
+ {
+ n <<= 1;
+ m++;
+ }
+ t = n >>> 1;
+ t /= m;
+ fieldPoly = PolynomialRingGF2.getIrreduciblePolynomial(m);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param m degree of the finite field GF(2^m)
+ * @param t error correction capability of the code
+ * @throws IllegalArgumentException if <tt>m &lt; 1</tt> or <tt>m &gt; 32</tt> or
+ * <tt>t &lt; 0</tt> or <tt>t &gt; n</tt>.
+ */
+ public McElieceParameters(int m, int t)
+ throws IllegalArgumentException
+ {
+ if (m < 1)
+ {
+ throw new IllegalArgumentException("m must be positive");
+ }
+ if (m > 32)
+ {
+ throw new IllegalArgumentException("m is too large");
+ }
+ this.m = m;
+ n = 1 << m;
+ if (t < 0)
+ {
+ throw new IllegalArgumentException("t must be positive");
+ }
+ if (t > n)
+ {
+ throw new IllegalArgumentException("t must be less than n = 2^m");
+ }
+ this.t = t;
+ fieldPoly = PolynomialRingGF2.getIrreduciblePolynomial(m);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param m degree of the finite field GF(2^m)
+ * @param t error correction capability of the code
+ * @param poly the field polynomial
+ * @throws IllegalArgumentException if <tt>m &lt; 1</tt> or <tt>m &gt; 32</tt> or
+ * <tt>t &lt; 0</tt> or <tt>t &gt; n</tt> or
+ * <tt>poly</tt> is not an irreducible field polynomial.
+ */
+ public McElieceParameters(int m, int t, int poly)
+ throws IllegalArgumentException
+ {
+ this.m = m;
+ if (m < 1)
+ {
+ throw new IllegalArgumentException("m must be positive");
+ }
+ if (m > 32)
+ {
+ throw new IllegalArgumentException(" m is too large");
+ }
+ this.n = 1 << m;
+ this.t = t;
+ if (t < 0)
+ {
+ throw new IllegalArgumentException("t must be positive");
+ }
+ if (t > n)
+ {
+ throw new IllegalArgumentException("t must be less than n = 2^m");
+ }
+ if ((PolynomialRingGF2.degree(poly) == m)
+ && (PolynomialRingGF2.isIrreducible(poly)))
+ {
+ this.fieldPoly = poly;
+ }
+ else
+ {
+ throw new IllegalArgumentException(
+ "polynomial is not a field polynomial for GF(2^m)");
+ }
+ }
+
+ /**
+ * @return the extension degree of the finite field GF(2^m)
+ */
+ public int getM()
+ {
+ return m;
+ }
+
+ /**
+ * @return the length of the code
+ */
+ public int getN()
+ {
+ return n;
+ }
+
+ /**
+ * @return the error correction capability of the code
+ */
+ public int getT()
+ {
+ return t;
+ }
+
+ /**
+ * @return the field polynomial
+ */
+ public int getFieldPoly()
+ {
+ return fieldPoly;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePointchevalCipher.java b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePointchevalCipher.java
new file mode 100644
index 00000000..ba58258b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePointchevalCipher.java
@@ -0,0 +1,241 @@
+package org.spongycastle.pqc.crypto.mceliece;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.prng.DigestRandomGenerator;
+import org.spongycastle.pqc.crypto.MessageEncryptor;
+import org.spongycastle.pqc.math.linearalgebra.ByteUtils;
+import org.spongycastle.pqc.math.linearalgebra.GF2Vector;
+
+/**
+ * This class implements the Pointcheval conversion of the McEliecePKCS.
+ * Pointcheval presents a generic technique to make a CCA2-secure cryptosystem
+ * from any partially trapdoor one-way function in the random oracle model. For
+ * details, see D. Engelbert, R. Overbeck, A. Schmidt, "A summary of the
+ * development of the McEliece Cryptosystem", technical report.
+ */
+public class McEliecePointchevalCipher
+ implements MessageEncryptor
+{
+
+
+ /**
+ * The OID of the algorithm.
+ */
+ public static final String OID = "1.3.6.1.4.1.8301.3.1.3.4.2.2";
+
+ private Digest messDigest;
+
+ private SecureRandom sr;
+
+ /**
+ * The McEliece main parameters
+ */
+ private int n, k, t;
+
+ McElieceCCA2KeyParameters key;
+
+ public void init(boolean forSigning,
+ CipherParameters param)
+ {
+
+ if (forSigning)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.sr = rParam.getRandom();
+ this.key = (McElieceCCA2PublicKeyParameters)rParam.getParameters();
+ this.initCipherEncrypt((McElieceCCA2PublicKeyParameters)key);
+
+ }
+ else
+ {
+ this.sr = new SecureRandom();
+ this.key = (McElieceCCA2PublicKeyParameters)param;
+ this.initCipherEncrypt((McElieceCCA2PublicKeyParameters)key);
+ }
+ }
+ else
+ {
+ this.key = (McElieceCCA2PrivateKeyParameters)param;
+ this.initCipherDecrypt((McElieceCCA2PrivateKeyParameters)key);
+ }
+
+ }
+
+ /**
+ * Return the key size of the given key object.
+ *
+ * @param key the McElieceCCA2KeyParameters object
+ * @return the key size of the given key object
+ * @throws IllegalArgumentException if the key is invalid
+ */
+ public int getKeySize(McElieceCCA2KeyParameters key)
+ throws IllegalArgumentException
+ {
+
+ if (key instanceof McElieceCCA2PublicKeyParameters)
+ {
+ return ((McElieceCCA2PublicKeyParameters)key).getN();
+
+ }
+ if (key instanceof McElieceCCA2PrivateKeyParameters)
+ {
+ return ((McElieceCCA2PrivateKeyParameters)key).getN();
+ }
+ throw new IllegalArgumentException("unsupported type");
+
+ }
+
+
+ protected int decryptOutputSize(int inLen)
+ {
+ return 0;
+ }
+
+ protected int encryptOutputSize(int inLen)
+ {
+ return 0;
+ }
+
+
+ public void initCipherEncrypt(McElieceCCA2PublicKeyParameters pubKey)
+ {
+ this.sr = sr != null ? sr : new SecureRandom();
+ this.messDigest = pubKey.getParameters().getDigest();
+ n = pubKey.getN();
+ k = pubKey.getK();
+ t = pubKey.getT();
+ }
+
+ public void initCipherDecrypt(McElieceCCA2PrivateKeyParameters privKey)
+ {
+ this.messDigest = privKey.getParameters().getDigest();
+ n = privKey.getN();
+ k = privKey.getK();
+ t = privKey.getT();
+ }
+
+ public byte[] messageEncrypt(byte[] input)
+ throws Exception
+ {
+
+ int kDiv8 = k >> 3;
+
+ // generate random r of length k div 8 bytes
+ byte[] r = new byte[kDiv8];
+ sr.nextBytes(r);
+
+ // generate random vector r' of length k bits
+ GF2Vector rPrime = new GF2Vector(k, sr);
+
+ // convert r' to byte array
+ byte[] rPrimeBytes = rPrime.getEncoded();
+
+ // compute (input||r)
+ byte[] mr = ByteUtils.concatenate(input, r);
+
+ // compute H(input||r)
+ messDigest.update(mr, 0, mr.length);
+ byte[] hmr = new byte[messDigest.getDigestSize()];
+ messDigest.doFinal(hmr, 0);
+
+
+ // convert H(input||r) to error vector z
+ GF2Vector z = Conversions.encode(n, t, hmr);
+
+ // compute c1 = E(rPrime, z)
+ byte[] c1 = McElieceCCA2Primitives.encryptionPrimitive((McElieceCCA2PublicKeyParameters)key, rPrime,
+ z).getEncoded();
+
+ // get PRNG object
+ DigestRandomGenerator sr0 = new DigestRandomGenerator(new SHA1Digest());
+
+ // seed PRNG with r'
+ sr0.addSeedMaterial(rPrimeBytes);
+
+ // generate random c2
+ byte[] c2 = new byte[input.length + kDiv8];
+ sr0.nextBytes(c2);
+
+ // XOR with input
+ for (int i = 0; i < input.length; i++)
+ {
+ c2[i] ^= input[i];
+ }
+ // XOR with r
+ for (int i = 0; i < kDiv8; i++)
+ {
+ c2[input.length + i] ^= r[i];
+ }
+
+ // return (c1||c2)
+ return ByteUtils.concatenate(c1, c2);
+ }
+
+ public byte[] messageDecrypt(byte[] input)
+ throws Exception
+ {
+
+ int c1Len = (n + 7) >> 3;
+ int c2Len = input.length - c1Len;
+
+ // split cipher text (c1||c2)
+ byte[][] c1c2 = ByteUtils.split(input, c1Len);
+ byte[] c1 = c1c2[0];
+ byte[] c2 = c1c2[1];
+
+ // decrypt c1 ...
+ GF2Vector c1Vec = GF2Vector.OS2VP(n, c1);
+ GF2Vector[] c1Dec = McElieceCCA2Primitives.decryptionPrimitive((McElieceCCA2PrivateKeyParameters)key,
+ c1Vec);
+ byte[] rPrimeBytes = c1Dec[0].getEncoded();
+ // ... and obtain error vector z
+ GF2Vector z = c1Dec[1];
+
+ // get PRNG object
+ DigestRandomGenerator sr0 = new DigestRandomGenerator(new SHA1Digest());
+
+ // seed PRNG with r'
+ sr0.addSeedMaterial(rPrimeBytes);
+
+ // generate random sequence
+ byte[] mrBytes = new byte[c2Len];
+ sr0.nextBytes(mrBytes);
+
+ // XOR with c2 to obtain (m||r)
+ for (int i = 0; i < c2Len; i++)
+ {
+ mrBytes[i] ^= c2[i];
+ }
+
+ // compute H(m||r)
+ messDigest.update(mrBytes, 0, mrBytes.length);
+ byte[] hmr = new byte[messDigest.getDigestSize()];
+ messDigest.doFinal(hmr, 0);
+
+ // compute Conv(H(m||r))
+ c1Vec = Conversions.encode(n, t, hmr);
+
+ // check that Conv(H(m||r)) = z
+ if (!c1Vec.equals(z))
+ {
+ throw new Exception("Bad Padding: Invalid ciphertext.");
+ }
+
+ // split (m||r) to obtain m
+ int kDiv8 = k >> 3;
+ byte[][] mr = ByteUtils.split(mrBytes, c2Len - kDiv8);
+
+ // return plain text m
+ return mr[0];
+ }
+
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePointchevalDigestCipher.java b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePointchevalDigestCipher.java
new file mode 100644
index 00000000..bcfd1d87
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePointchevalDigestCipher.java
@@ -0,0 +1,128 @@
+package org.spongycastle.pqc.crypto.mceliece;
+
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.pqc.crypto.MessageEncryptor;
+
+// TODO should implement some interface?
+public class McEliecePointchevalDigestCipher
+{
+
+ private final Digest messDigest;
+
+ private final MessageEncryptor mcElieceCCA2Cipher;
+
+ private boolean forEncrypting;
+
+
+ public McEliecePointchevalDigestCipher(MessageEncryptor mcElieceCCA2Cipher, Digest messDigest)
+ {
+ this.mcElieceCCA2Cipher = mcElieceCCA2Cipher;
+ this.messDigest = messDigest;
+ }
+
+
+ public void init(boolean forEncrypting,
+ CipherParameters param)
+ {
+
+ this.forEncrypting = forEncrypting;
+ AsymmetricKeyParameter k;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ k = (AsymmetricKeyParameter)((ParametersWithRandom)param).getParameters();
+ }
+ else
+ {
+ k = (AsymmetricKeyParameter)param;
+ }
+
+ if (forEncrypting && k.isPrivate())
+ {
+ throw new IllegalArgumentException("Encrypting Requires Public Key.");
+ }
+
+ if (!forEncrypting && !k.isPrivate())
+ {
+ throw new IllegalArgumentException("Decrypting Requires Private Key.");
+ }
+
+ reset();
+
+ mcElieceCCA2Cipher.init(forEncrypting, param);
+ }
+
+
+ public byte[] messageEncrypt()
+ {
+ if (!forEncrypting)
+ {
+ throw new IllegalStateException("McEliecePointchevalDigestCipher not initialised for encrypting.");
+ }
+
+ byte[] hash = new byte[messDigest.getDigestSize()];
+ messDigest.doFinal(hash, 0);
+ byte[] enc = null;
+
+ try
+ {
+ enc = mcElieceCCA2Cipher.messageEncrypt(hash);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
+
+ return enc;
+ }
+
+
+ public byte[] messageDecrypt(byte[] ciphertext)
+ {
+ byte[] output = null;
+ if (forEncrypting)
+ {
+ throw new IllegalStateException("McEliecePointchevalDigestCipher not initialised for decrypting.");
+ }
+
+
+ try
+ {
+ output = mcElieceCCA2Cipher.messageDecrypt(ciphertext);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
+
+ return output;
+ }
+
+
+ public void update(byte b)
+ {
+ messDigest.update(b);
+
+ }
+
+ public void update(byte[] in, int off, int len)
+ {
+ messDigest.update(in, off, len);
+
+ }
+
+
+ public void reset()
+ {
+ messDigest.reset();
+
+ }
+
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePrivateKeyParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePrivateKeyParameters.java
new file mode 100644
index 00000000..3c4ef324
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePrivateKeyParameters.java
@@ -0,0 +1,197 @@
+package org.spongycastle.pqc.crypto.mceliece;
+
+import org.spongycastle.pqc.math.linearalgebra.GF2Matrix;
+import org.spongycastle.pqc.math.linearalgebra.GF2mField;
+import org.spongycastle.pqc.math.linearalgebra.Permutation;
+import org.spongycastle.pqc.math.linearalgebra.PolynomialGF2mSmallM;
+
+
+public class McEliecePrivateKeyParameters
+ extends McElieceKeyParameters
+{
+
+ // the OID of the algorithm
+ private String oid;
+
+ // the length of the code
+ private int n;
+
+ // the dimension of the code, where <tt>k &gt;= n - mt</tt>
+ private int k;
+
+ // the underlying finite field
+ private GF2mField field;
+
+ // the irreducible Goppa polynomial
+ private PolynomialGF2mSmallM goppaPoly;
+
+ // a k x k random binary non-singular matrix
+ private GF2Matrix sInv;
+
+ // the permutation used to generate the systematic check matrix
+ private Permutation p1;
+
+ // the permutation used to compute the public generator matrix
+ private Permutation p2;
+
+ // the canonical check matrix of the code
+ private GF2Matrix h;
+
+ // the matrix used to compute square roots in <tt>(GF(2^m))^t</tt>
+ private PolynomialGF2mSmallM[] qInv;
+
+ /**
+ * Constructor.
+ *
+ * @param oid
+ * @param n the length of the code
+ * @param k the dimension of the code
+ * @param field the field polynomial defining the finite field
+ * <tt>GF(2<sup>m</sup>)</tt>
+ * @param goppaPoly the irreducible Goppa polynomial
+ * @param sInv the matrix <tt>S<sup>-1</sup></tt>
+ * @param p1 the permutation used to generate the systematic check
+ * matrix
+ * @param p2 the permutation used to compute the public generator
+ * matrix
+ * @param h the canonical check matrix
+ * @param qInv the matrix used to compute square roots in
+ * <tt>(GF(2<sup>m</sup>))<sup>t</sup></tt>
+ * @param params McElieceParameters
+ */
+ public McEliecePrivateKeyParameters(String oid, int n, int k, GF2mField field,
+ PolynomialGF2mSmallM goppaPoly, GF2Matrix sInv, Permutation p1,
+ Permutation p2, GF2Matrix h, PolynomialGF2mSmallM[] qInv, McElieceParameters params)
+ {
+ super(true, params);
+ this.oid = oid;
+ this.k = k;
+ this.n = n;
+ this.field = field;
+ this.goppaPoly = goppaPoly;
+ this.sInv = sInv;
+ this.p1 = p1;
+ this.p2 = p2;
+ this.h = h;
+ this.qInv = qInv;
+ }
+
+ /**
+ * Constructor (used by the {@link McElieceKeyFactory}).
+ *
+ * @param oid
+ * @param n the length of the code
+ * @param k the dimension of the code
+ * @param encField the encoded field polynomial defining the finite field
+ * <tt>GF(2<sup>m</sup>)</tt>
+ * @param encGoppaPoly the encoded irreducible Goppa polynomial
+ * @param encSInv the encoded matrix <tt>S<sup>-1</sup></tt>
+ * @param encP1 the encoded permutation used to generate the systematic
+ * check matrix
+ * @param encP2 the encoded permutation used to compute the public
+ * generator matrix
+ * @param encH the encoded canonical check matrix
+ * @param encQInv the encoded matrix used to compute square roots in
+ * <tt>(GF(2<sup>m</sup>))<sup>t</sup></tt>
+ * @param params McElieceParameters
+ */
+ public McEliecePrivateKeyParameters(String oid, int n, int k, byte[] encField,
+ byte[] encGoppaPoly, byte[] encSInv, byte[] encP1, byte[] encP2,
+ byte[] encH, byte[][] encQInv, McElieceParameters params)
+ {
+ super(true, params);
+ this.oid = oid;
+ this.n = n;
+ this.k = k;
+ field = new GF2mField(encField);
+ goppaPoly = new PolynomialGF2mSmallM(field, encGoppaPoly);
+ sInv = new GF2Matrix(encSInv);
+ p1 = new Permutation(encP1);
+ p2 = new Permutation(encP2);
+ h = new GF2Matrix(encH);
+ qInv = new PolynomialGF2mSmallM[encQInv.length];
+ for (int i = 0; i < encQInv.length; i++)
+ {
+ qInv[i] = new PolynomialGF2mSmallM(field, encQInv[i]);
+ }
+ }
+
+ /**
+ * @return the length of the code
+ */
+ public int getN()
+ {
+ return n;
+ }
+
+ /**
+ * @return the dimension of the code
+ */
+ public int getK()
+ {
+ return k;
+ }
+
+ /**
+ * @return the finite field <tt>GF(2<sup>m</sup>)</tt>
+ */
+ public GF2mField getField()
+ {
+ return field;
+ }
+
+ /**
+ * @return the irreducible Goppa polynomial
+ */
+ public PolynomialGF2mSmallM getGoppaPoly()
+ {
+ return goppaPoly;
+ }
+
+ /**
+ * @return the k x k random binary non-singular matrix S^-1
+ */
+ public GF2Matrix getSInv()
+ {
+ return sInv;
+ }
+
+ /**
+ * @return the permutation used to generate the systematic check matrix
+ */
+ public Permutation getP1()
+ {
+ return p1;
+ }
+
+ /**
+ * @return the permutation used to compute the public generator matrix
+ */
+ public Permutation getP2()
+ {
+ return p2;
+ }
+
+ /**
+ * @return the canonical check matrix H
+ */
+ public GF2Matrix getH()
+ {
+ return h;
+ }
+
+ /**
+ * @return the matrix used to compute square roots in
+ * <tt>(GF(2<sup>m</sup>))<sup>t</sup></tt>
+ */
+ public PolynomialGF2mSmallM[] getQInv()
+ {
+ return qInv;
+ }
+
+ public String getOIDString()
+ {
+ return oid;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePublicKeyParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePublicKeyParameters.java
new file mode 100644
index 00000000..9f011243
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/mceliece/McEliecePublicKeyParameters.java
@@ -0,0 +1,96 @@
+package org.spongycastle.pqc.crypto.mceliece;
+
+import org.spongycastle.pqc.math.linearalgebra.GF2Matrix;
+
+
+public class McEliecePublicKeyParameters
+ extends McElieceKeyParameters
+{
+
+ // the OID of the algorithm
+ private String oid;
+
+ // the length of the code
+ private int n;
+
+ // the error correction capability of the code
+ private int t;
+
+ // the generator matrix
+ private GF2Matrix g;
+
+ /**
+ * Constructor (used by {@link McElieceKeyFactory}).
+ *
+ * @param oid
+ * @param n the length of the code
+ * @param t the error correction capability of the code
+ * @param g the generator matrix
+ * @param params McElieceParameters
+ */
+ public McEliecePublicKeyParameters(String oid, int n, int t, GF2Matrix g, McElieceParameters params)
+ {
+ super(false, params);
+ this.oid = oid;
+ this.n = n;
+ this.t = t;
+ this.g = new GF2Matrix(g);
+ }
+
+ /**
+ * Constructor (used by {@link McElieceKeyFactory}).
+ *
+ * @param oid
+ * @param n the length of the code
+ * @param t the error correction capability of the code
+ * @param encG the encoded generator matrix
+ * @param params McElieceParameters
+ */
+ public McEliecePublicKeyParameters(String oid, int t, int n, byte[] encG, McElieceParameters params)
+ {
+ super(false, params);
+ this.oid = oid;
+ this.n = n;
+ this.t = t;
+ this.g = new GF2Matrix(encG);
+ }
+
+ /**
+ * @return the length of the code
+ */
+ public int getN()
+ {
+ return n;
+ }
+
+ /**
+ * @return the error correction capability of the code
+ */
+ public int getT()
+ {
+ return t;
+ }
+
+ /**
+ * @return the generator matrix
+ */
+ public GF2Matrix getG()
+ {
+ return g;
+ }
+
+ public String getOIDString()
+ {
+ return oid;
+
+ }
+
+ /**
+ * @return the dimension of the code
+ */
+ public int getK()
+ {
+ return g.getNumRows();
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/ntru/IndexGenerator.java b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/IndexGenerator.java
new file mode 100644
index 00000000..01caf970
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/IndexGenerator.java
@@ -0,0 +1,239 @@
+package org.spongycastle.pqc.crypto.ntru;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.util.Arrays;
+
+/**
+ * An implementation of the Index Generation Function in IEEE P1363.1.
+ */
+public class IndexGenerator
+{
+ private byte[] seed;
+ private int N;
+ private int c;
+ private int minCallsR;
+ private int totLen;
+ private int remLen;
+ private BitString buf;
+ private int counter;
+ private boolean initialized;
+ private Digest hashAlg;
+ private int hLen;
+
+ /**
+ * Constructs a new index generator.
+ *
+ * @param seed a seed of arbitrary length to initialize the index generator with
+ * @param params NtruEncrypt parameters
+ */
+ IndexGenerator(byte[] seed, NTRUEncryptionParameters params)
+ {
+ this.seed = seed;
+ N = params.N;
+ c = params.c;
+ minCallsR = params.minCallsR;
+
+ totLen = 0;
+ remLen = 0;
+ counter = 0;
+ hashAlg = params.hashAlg;
+
+ hLen = hashAlg.getDigestSize(); // hash length
+ initialized = false;
+ }
+
+ /**
+ * Returns a number <code>i</code> such that <code>0 &lt;= i &lt; N</code>.
+ *
+ * @return
+ */
+ int nextIndex()
+ {
+ if (!initialized)
+ {
+ buf = new BitString();
+ byte[] hash = new byte[hashAlg.getDigestSize()];
+ while (counter < minCallsR)
+ {
+ appendHash(buf, hash);
+ counter++;
+ }
+ totLen = minCallsR * 8 * hLen;
+ remLen = totLen;
+ initialized = true;
+ }
+
+ while (true)
+ {
+ totLen += c;
+ BitString M = buf.getTrailing(remLen);
+ if (remLen < c)
+ {
+ int tmpLen = c - remLen;
+ int cThreshold = counter + (tmpLen + hLen - 1) / hLen;
+ byte[] hash = new byte[hashAlg.getDigestSize()];
+ while (counter < cThreshold)
+ {
+ appendHash(M, hash);
+ counter++;
+ if (tmpLen > 8 * hLen)
+ {
+ tmpLen -= 8 * hLen;
+ }
+ }
+ remLen = 8 * hLen - tmpLen;
+ buf = new BitString();
+ buf.appendBits(hash);
+ }
+ else
+ {
+ remLen -= c;
+ }
+
+ int i = M.getLeadingAsInt(c); // assume c<32
+ if (i < (1 << c) - ((1 << c) % N))
+ {
+ return i % N;
+ }
+ }
+ }
+
+ private void appendHash(BitString m, byte[] hash)
+ {
+ hashAlg.update(seed, 0, seed.length);
+
+ putInt(hashAlg, counter);
+
+ hashAlg.doFinal(hash, 0);
+
+ m.appendBits(hash);
+ }
+
+ private void putInt(Digest hashAlg, int counter)
+ {
+ hashAlg.update((byte)(counter >> 24));
+ hashAlg.update((byte)(counter >> 16));
+ hashAlg.update((byte)(counter >> 8));
+ hashAlg.update((byte)counter);
+ }
+
+ /**
+ * Represents a string of bits and supports appending, reading the head, and reading the tail.
+ */
+ public static class BitString
+ {
+ byte[] bytes = new byte[4];
+ int numBytes; // includes the last byte even if only some of its bits are used
+ int lastByteBits; // lastByteBits <= 8
+
+ /**
+ * Appends all bits in a byte array to the end of the bit string.
+ *
+ * @param bytes a byte array
+ */
+ void appendBits(byte[] bytes)
+ {
+ for (int i = 0; i != bytes.length; i++)
+ {
+ appendBits(bytes[i]);
+ }
+ }
+
+ /**
+ * Appends all bits in a byte to the end of the bit string.
+ *
+ * @param b a byte
+ */
+ public void appendBits(byte b)
+ {
+ if (numBytes == bytes.length)
+ {
+ bytes = copyOf(bytes, 2 * bytes.length);
+ }
+
+ if (numBytes == 0)
+ {
+ numBytes = 1;
+ bytes[0] = b;
+ lastByteBits = 8;
+ }
+ else if (lastByteBits == 8)
+ {
+ bytes[numBytes++] = b;
+ }
+ else
+ {
+ int s = 8 - lastByteBits;
+ bytes[numBytes - 1] |= (b & 0xFF) << lastByteBits;
+ bytes[numBytes++] = (byte)((b & 0xFF) >> s);
+ }
+ }
+
+ /**
+ * Returns the last <code>numBits</code> bits from the end of the bit string.
+ *
+ * @param numBits number of bits
+ * @return a new <code>BitString</code> of length <code>numBits</code>
+ */
+ public BitString getTrailing(int numBits)
+ {
+ BitString newStr = new BitString();
+ newStr.numBytes = (numBits + 7) / 8;
+ newStr.bytes = new byte[newStr.numBytes];
+ for (int i = 0; i < newStr.numBytes; i++)
+ {
+ newStr.bytes[i] = bytes[i];
+ }
+
+ newStr.lastByteBits = numBits % 8;
+ if (newStr.lastByteBits == 0)
+ {
+ newStr.lastByteBits = 8;
+ }
+ else
+ {
+ int s = 32 - newStr.lastByteBits;
+ newStr.bytes[newStr.numBytes - 1] = (byte)(newStr.bytes[newStr.numBytes - 1] << s >>> s);
+ }
+
+ return newStr;
+ }
+
+ /**
+ * Returns up to 32 bits from the beginning of the bit string.
+ *
+ * @param numBits number of bits
+ * @return an <code>int</code> whose lower <code>numBits</code> bits are the beginning of the bit string
+ */
+ public int getLeadingAsInt(int numBits)
+ {
+ int startBit = (numBytes - 1) * 8 + lastByteBits - numBits;
+ int startByte = startBit / 8;
+
+ int startBitInStartByte = startBit % 8;
+ int sum = (bytes[startByte] & 0xFF) >>> startBitInStartByte;
+ int shift = 8 - startBitInStartByte;
+ for (int i = startByte + 1; i < numBytes; i++)
+ {
+ sum |= (bytes[i] & 0xFF) << shift;
+ shift += 8;
+ }
+
+ return sum;
+ }
+
+ public byte[] getBytes()
+ {
+ return Arrays.clone(bytes);
+ }
+ }
+
+ private static byte[] copyOf(byte[] src, int len)
+ {
+ byte[] tmp = new byte[len];
+
+ System.arraycopy(src, 0, tmp, 0, len < src.length ? len : src.length);
+
+ return tmp;
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionKeyGenerationParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionKeyGenerationParameters.java
new file mode 100644
index 00000000..76cb839d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionKeyGenerationParameters.java
@@ -0,0 +1,463 @@
+package org.spongycastle.pqc.crypto.ntru;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.SecureRandom;
+import java.util.Arrays;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.digests.SHA512Digest;
+
+/**
+ * A set of parameters for NtruEncrypt. Several predefined parameter sets are available and new ones can be created as well.
+ */
+public class NTRUEncryptionKeyGenerationParameters
+ extends KeyGenerationParameters
+ implements Cloneable
+{
+ /**
+ * A conservative (in terms of security) parameter set that gives 256 bits of security and is optimized for key size.
+ */
+ public static final NTRUEncryptionKeyGenerationParameters EES1087EP2 = new NTRUEncryptionKeyGenerationParameters(1087, 2048, 120, 120, 256, 13, 25, 14, true, new byte[]{0, 6, 3}, true, false, new SHA512Digest());
+
+ /**
+ * A conservative (in terms of security) parameter set that gives 256 bits of security and is a tradeoff between key size and encryption/decryption speed.
+ */
+ public static final NTRUEncryptionKeyGenerationParameters EES1171EP1 = new NTRUEncryptionKeyGenerationParameters(1171, 2048, 106, 106, 256, 13, 20, 15, true, new byte[]{0, 6, 4}, true, false, new SHA512Digest());
+
+ /**
+ * A conservative (in terms of security) parameter set that gives 256 bits of security and is optimized for encryption/decryption speed.
+ */
+ public static final NTRUEncryptionKeyGenerationParameters EES1499EP1 = new NTRUEncryptionKeyGenerationParameters(1499, 2048, 79, 79, 256, 13, 17, 19, true, new byte[]{0, 6, 5}, true, false, new SHA512Digest());
+
+ /**
+ * A parameter set that gives 128 bits of security and uses simple ternary polynomials.
+ */
+ public static final NTRUEncryptionKeyGenerationParameters APR2011_439 = new NTRUEncryptionKeyGenerationParameters(439, 2048, 146, 130, 128, 9, 32, 9, true, new byte[]{0, 7, 101}, true, false, new SHA256Digest());
+
+ /**
+ * Like <code>APR2011_439</code>, this parameter set gives 128 bits of security but uses product-form polynomials and <code>f=1+pF</code>.
+ */
+ public static final NTRUEncryptionKeyGenerationParameters APR2011_439_FAST = new NTRUEncryptionKeyGenerationParameters(439, 2048, 9, 8, 5, 130, 128, 9, 32, 9, true, new byte[]{0, 7, 101}, true, true, new SHA256Digest());
+
+ /**
+ * A parameter set that gives 256 bits of security and uses simple ternary polynomials.
+ */
+ public static final NTRUEncryptionKeyGenerationParameters APR2011_743 = new NTRUEncryptionKeyGenerationParameters(743, 2048, 248, 220, 256, 10, 27, 14, true, new byte[]{0, 7, 105}, false, false, new SHA512Digest());
+
+ /**
+ * Like <code>APR2011_743</code>, this parameter set gives 256 bits of security but uses product-form polynomials and <code>f=1+pF</code>.
+ */
+ public static final NTRUEncryptionKeyGenerationParameters APR2011_743_FAST = new NTRUEncryptionKeyGenerationParameters(743, 2048, 11, 11, 15, 220, 256, 10, 27, 14, true, new byte[]{0, 7, 105}, false, true, new SHA512Digest());
+
+ public int N, q, df, df1, df2, df3;
+ public int dr;
+ public int dr1;
+ public int dr2;
+ public int dr3;
+ public int dg;
+ int llen;
+ public int maxMsgLenBytes;
+ public int db;
+ public int bufferLenBits;
+ int bufferLenTrits;
+ public int dm0;
+ public int pkLen;
+ public int c;
+ public int minCallsR;
+ public int minCallsMask;
+ public boolean hashSeed;
+ public byte[] oid;
+ public boolean sparse;
+ public boolean fastFp;
+ public int polyType;
+ public Digest hashAlg;
+
+ /**
+ * Constructs a parameter set that uses ternary private keys (i.e. <code>polyType=SIMPLE</code>).
+ *
+ * @param N number of polynomial coefficients
+ * @param q modulus
+ * @param df number of ones in the private polynomial <code>f</code>
+ * @param dm0 minimum acceptable number of -1's, 0's, and 1's in the polynomial <code>m'</code> in the last encryption step
+ * @param db number of random bits to prepend to the message
+ * @param c a parameter for the Index Generation Function ({@link org.spongycastle.pqc.crypto.ntru.IndexGenerator})
+ * @param minCallsR minimum number of hash calls for the IGF to make
+ * @param minCallsMask minimum number of calls to generate the masking polynomial
+ * @param hashSeed whether to hash the seed in the MGF first (true) or use the seed directly (false)
+ * @param oid three bytes that uniquely identify the parameter set
+ * @param sparse whether to treat ternary polynomials as sparsely populated ({@link org.spongycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial} vs {@link org.spongycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial})
+ * @param fastFp whether <code>f=1+p*F</code> for a ternary <code>F</code> (true) or <code>f</code> is ternary (false)
+ * @param hashAlg a valid identifier for a <code>java.security.MessageDigest</code> instance such as <code>SHA-256</code>. The <code>MessageDigest</code> must support the <code>getDigestLength()</code> method.
+ */
+ public NTRUEncryptionKeyGenerationParameters(int N, int q, int df, int dm0, int db, int c, int minCallsR, int minCallsMask, boolean hashSeed, byte[] oid, boolean sparse, boolean fastFp, Digest hashAlg)
+ {
+ super(new SecureRandom(), db);
+ this.N = N;
+ this.q = q;
+ this.df = df;
+ this.db = db;
+ this.dm0 = dm0;
+ this.c = c;
+ this.minCallsR = minCallsR;
+ this.minCallsMask = minCallsMask;
+ this.hashSeed = hashSeed;
+ this.oid = oid;
+ this.sparse = sparse;
+ this.fastFp = fastFp;
+ this.polyType = NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE;
+ this.hashAlg = hashAlg;
+ init();
+ }
+
+ /**
+ * Constructs a parameter set that uses product-form private keys (i.e. <code>polyType=PRODUCT</code>).
+ *
+ * @param N number of polynomial coefficients
+ * @param q modulus
+ * @param df1 number of ones in the private polynomial <code>f1</code>
+ * @param df2 number of ones in the private polynomial <code>f2</code>
+ * @param df3 number of ones in the private polynomial <code>f3</code>
+ * @param dm0 minimum acceptable number of -1's, 0's, and 1's in the polynomial <code>m'</code> in the last encryption step
+ * @param db number of random bits to prepend to the message
+ * @param c a parameter for the Index Generation Function ({@link org.spongycastle.pqc.crypto.ntru.IndexGenerator})
+ * @param minCallsR minimum number of hash calls for the IGF to make
+ * @param minCallsMask minimum number of calls to generate the masking polynomial
+ * @param hashSeed whether to hash the seed in the MGF first (true) or use the seed directly (false)
+ * @param oid three bytes that uniquely identify the parameter set
+ * @param sparse whether to treat ternary polynomials as sparsely populated ({@link org.spongycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial} vs {@link org.spongycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial})
+ * @param fastFp whether <code>f=1+p*F</code> for a ternary <code>F</code> (true) or <code>f</code> is ternary (false)
+ * @param hashAlg a valid identifier for a <code>java.security.MessageDigest</code> instance such as <code>SHA-256</code>
+ */
+ public NTRUEncryptionKeyGenerationParameters(int N, int q, int df1, int df2, int df3, int dm0, int db, int c, int minCallsR, int minCallsMask, boolean hashSeed, byte[] oid, boolean sparse, boolean fastFp, Digest hashAlg)
+ {
+ super(new SecureRandom(), db);
+
+ this.N = N;
+ this.q = q;
+ this.df1 = df1;
+ this.df2 = df2;
+ this.df3 = df3;
+ this.db = db;
+ this.dm0 = dm0;
+ this.c = c;
+ this.minCallsR = minCallsR;
+ this.minCallsMask = minCallsMask;
+ this.hashSeed = hashSeed;
+ this.oid = oid;
+ this.sparse = sparse;
+ this.fastFp = fastFp;
+ this.polyType = NTRUParameters.TERNARY_POLYNOMIAL_TYPE_PRODUCT;
+ this.hashAlg = hashAlg;
+ init();
+ }
+
+ private void init()
+ {
+ dr = df;
+ dr1 = df1;
+ dr2 = df2;
+ dr3 = df3;
+ dg = N / 3;
+ llen = 1; // ceil(log2(maxMsgLenBytes))
+ maxMsgLenBytes = N * 3 / 2 / 8 - llen - db / 8 - 1;
+ bufferLenBits = (N * 3 / 2 + 7) / 8 * 8 + 1;
+ bufferLenTrits = N - 1;
+ pkLen = db;
+ }
+
+ /**
+ * Reads a parameter set from an input stream.
+ *
+ * @param is an input stream
+ * @throws java.io.IOException
+ */
+ public NTRUEncryptionKeyGenerationParameters(InputStream is)
+ throws IOException
+ {
+ super(new SecureRandom(), -1);
+ DataInputStream dis = new DataInputStream(is);
+ N = dis.readInt();
+ q = dis.readInt();
+ df = dis.readInt();
+ df1 = dis.readInt();
+ df2 = dis.readInt();
+ df3 = dis.readInt();
+ db = dis.readInt();
+ dm0 = dis.readInt();
+ c = dis.readInt();
+ minCallsR = dis.readInt();
+ minCallsMask = dis.readInt();
+ hashSeed = dis.readBoolean();
+ oid = new byte[3];
+ dis.read(oid);
+ sparse = dis.readBoolean();
+ fastFp = dis.readBoolean();
+ polyType = dis.read();
+
+ String alg = dis.readUTF();
+
+ if ("SHA-512".equals(alg))
+ {
+ hashAlg = new SHA512Digest();
+ }
+ else if ("SHA-256".equals(alg))
+ {
+ hashAlg = new SHA256Digest();
+ }
+
+ init();
+ }
+
+ public NTRUEncryptionParameters getEncryptionParameters()
+ {
+ if (polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE)
+ {
+ return new NTRUEncryptionParameters(N, q, df, dm0, db, c, minCallsR, minCallsMask, hashSeed, oid, sparse, fastFp, hashAlg);
+ }
+ else
+ {
+ return new NTRUEncryptionParameters(N, q, df1, df2, df3, dm0, db, c, minCallsR, minCallsMask, hashSeed, oid, sparse, fastFp, hashAlg);
+ }
+ }
+
+ public NTRUEncryptionKeyGenerationParameters clone()
+ {
+ if (polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE)
+ {
+ return new NTRUEncryptionKeyGenerationParameters(N, q, df, dm0, db, c, minCallsR, minCallsMask, hashSeed, oid, sparse, fastFp, hashAlg);
+ }
+ else
+ {
+ return new NTRUEncryptionKeyGenerationParameters(N, q, df1, df2, df3, dm0, db, c, minCallsR, minCallsMask, hashSeed, oid, sparse, fastFp, hashAlg);
+ }
+ }
+
+ /**
+ * Returns the maximum length a plaintext message can be with this parameter set.
+ *
+ * @return the maximum length in bytes
+ */
+ public int getMaxMessageLength()
+ {
+ return maxMsgLenBytes;
+ }
+
+ /**
+ * Writes the parameter set to an output stream
+ *
+ * @param os an output stream
+ * @throws java.io.IOException
+ */
+ public void writeTo(OutputStream os)
+ throws IOException
+ {
+ DataOutputStream dos = new DataOutputStream(os);
+ dos.writeInt(N);
+ dos.writeInt(q);
+ dos.writeInt(df);
+ dos.writeInt(df1);
+ dos.writeInt(df2);
+ dos.writeInt(df3);
+ dos.writeInt(db);
+ dos.writeInt(dm0);
+ dos.writeInt(c);
+ dos.writeInt(minCallsR);
+ dos.writeInt(minCallsMask);
+ dos.writeBoolean(hashSeed);
+ dos.write(oid);
+ dos.writeBoolean(sparse);
+ dos.writeBoolean(fastFp);
+ dos.write(polyType);
+ dos.writeUTF(hashAlg.getAlgorithmName());
+ }
+
+
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + N;
+ result = prime * result + bufferLenBits;
+ result = prime * result + bufferLenTrits;
+ result = prime * result + c;
+ result = prime * result + db;
+ result = prime * result + df;
+ result = prime * result + df1;
+ result = prime * result + df2;
+ result = prime * result + df3;
+ result = prime * result + dg;
+ result = prime * result + dm0;
+ result = prime * result + dr;
+ result = prime * result + dr1;
+ result = prime * result + dr2;
+ result = prime * result + dr3;
+ result = prime * result + (fastFp ? 1231 : 1237);
+ result = prime * result + ((hashAlg == null) ? 0 : hashAlg.getAlgorithmName().hashCode());
+ result = prime * result + (hashSeed ? 1231 : 1237);
+ result = prime * result + llen;
+ result = prime * result + maxMsgLenBytes;
+ result = prime * result + minCallsMask;
+ result = prime * result + minCallsR;
+ result = prime * result + Arrays.hashCode(oid);
+ result = prime * result + pkLen;
+ result = prime * result + polyType;
+ result = prime * result + q;
+ result = prime * result + (sparse ? 1231 : 1237);
+ return result;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+ NTRUEncryptionKeyGenerationParameters other = (NTRUEncryptionKeyGenerationParameters)obj;
+ if (N != other.N)
+ {
+ return false;
+ }
+ if (bufferLenBits != other.bufferLenBits)
+ {
+ return false;
+ }
+ if (bufferLenTrits != other.bufferLenTrits)
+ {
+ return false;
+ }
+ if (c != other.c)
+ {
+ return false;
+ }
+ if (db != other.db)
+ {
+ return false;
+ }
+ if (df != other.df)
+ {
+ return false;
+ }
+ if (df1 != other.df1)
+ {
+ return false;
+ }
+ if (df2 != other.df2)
+ {
+ return false;
+ }
+ if (df3 != other.df3)
+ {
+ return false;
+ }
+ if (dg != other.dg)
+ {
+ return false;
+ }
+ if (dm0 != other.dm0)
+ {
+ return false;
+ }
+ if (dr != other.dr)
+ {
+ return false;
+ }
+ if (dr1 != other.dr1)
+ {
+ return false;
+ }
+ if (dr2 != other.dr2)
+ {
+ return false;
+ }
+ if (dr3 != other.dr3)
+ {
+ return false;
+ }
+ if (fastFp != other.fastFp)
+ {
+ return false;
+ }
+ if (hashAlg == null)
+ {
+ if (other.hashAlg != null)
+ {
+ return false;
+ }
+ }
+ else if (!hashAlg.getAlgorithmName().equals(other.hashAlg.getAlgorithmName()))
+ {
+ return false;
+ }
+ if (hashSeed != other.hashSeed)
+ {
+ return false;
+ }
+ if (llen != other.llen)
+ {
+ return false;
+ }
+ if (maxMsgLenBytes != other.maxMsgLenBytes)
+ {
+ return false;
+ }
+ if (minCallsMask != other.minCallsMask)
+ {
+ return false;
+ }
+ if (minCallsR != other.minCallsR)
+ {
+ return false;
+ }
+ if (!Arrays.equals(oid, other.oid))
+ {
+ return false;
+ }
+ if (pkLen != other.pkLen)
+ {
+ return false;
+ }
+ if (polyType != other.polyType)
+ {
+ return false;
+ }
+ if (q != other.q)
+ {
+ return false;
+ }
+ if (sparse != other.sparse)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public String toString()
+ {
+ StringBuilder output = new StringBuilder("EncryptionParameters(N=" + N + " q=" + q);
+ if (polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE)
+ {
+ output.append(" polyType=SIMPLE df=" + df);
+ }
+ else
+ {
+ output.append(" polyType=PRODUCT df1=" + df1 + " df2=" + df2 + " df3=" + df3);
+ }
+ output.append(" dm0=" + dm0 + " db=" + db + " c=" + c + " minCallsR=" + minCallsR + " minCallsMask=" + minCallsMask +
+ " hashSeed=" + hashSeed + " hashAlg=" + hashAlg + " oid=" + Arrays.toString(oid) + " sparse=" + sparse + ")");
+ return output.toString();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionKeyPairGenerator.java b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionKeyPairGenerator.java
new file mode 100644
index 00000000..fd483f09
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionKeyPairGenerator.java
@@ -0,0 +1,113 @@
+package org.spongycastle.pqc.crypto.ntru;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.Polynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.ProductFormPolynomial;
+import org.spongycastle.pqc.math.ntru.util.Util;
+
+/**
+ * Generates key pairs.<br>
+ * The parameter p is hardcoded to 3.
+ */
+public class NTRUEncryptionKeyPairGenerator
+ implements AsymmetricCipherKeyPairGenerator
+{
+ private NTRUEncryptionKeyGenerationParameters params;
+
+ /**
+ * Constructs a new instance with a set of encryption parameters.
+ *
+ * @param param encryption parameters
+ */
+ public void init(KeyGenerationParameters param)
+ {
+ this.params = (NTRUEncryptionKeyGenerationParameters)param;
+ }
+
+ /**
+ * Generates a new encryption key pair.
+ *
+ * @return a key pair
+ */
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+ int N = params.N;
+ int q = params.q;
+ int df = params.df;
+ int df1 = params.df1;
+ int df2 = params.df2;
+ int df3 = params.df3;
+ int dg = params.dg;
+ boolean fastFp = params.fastFp;
+ boolean sparse = params.sparse;
+
+ Polynomial t;
+ IntegerPolynomial fq;
+ IntegerPolynomial fp = null;
+
+ // choose a random f that is invertible mod 3 and q
+ while (true)
+ {
+ IntegerPolynomial f;
+
+ // choose random t, calculate f and fp
+ if (fastFp)
+ {
+ // if fastFp=true, f is always invertible mod 3
+ t = params.polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE ? Util.generateRandomTernary(N, df, df, sparse, params.getRandom()) : ProductFormPolynomial.generateRandom(N, df1, df2, df3, df3, params.getRandom());
+ f = t.toIntegerPolynomial();
+ f.mult(3);
+ f.coeffs[0] += 1;
+ }
+ else
+ {
+ t = params.polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE ? Util.generateRandomTernary(N, df, df - 1, sparse, params.getRandom()) : ProductFormPolynomial.generateRandom(N, df1, df2, df3, df3 - 1, params.getRandom());
+ f = t.toIntegerPolynomial();
+ fp = f.invertF3();
+ if (fp == null)
+ {
+ continue;
+ }
+ }
+
+ fq = f.invertFq(q);
+ if (fq == null)
+ {
+ continue;
+ }
+ break;
+ }
+
+ // if fastFp=true, fp=1
+ if (fastFp)
+ {
+ fp = new IntegerPolynomial(N);
+ fp.coeffs[0] = 1;
+ }
+
+ // choose a random g that is invertible mod q
+ DenseTernaryPolynomial g;
+ while (true)
+ {
+ g = DenseTernaryPolynomial.generateRandom(N, dg, dg - 1, params.getRandom());
+ if (g.invertFq(q) != null)
+ {
+ break;
+ }
+ }
+
+ IntegerPolynomial h = g.mult(fq, q);
+ h.mult3(q);
+ h.ensurePositive(q);
+ g.clear();
+ fq.clear();
+
+ NTRUEncryptionPrivateKeyParameters priv = new NTRUEncryptionPrivateKeyParameters(h, t, fp, params.getEncryptionParameters());
+ NTRUEncryptionPublicKeyParameters pub = new NTRUEncryptionPublicKeyParameters(h, params.getEncryptionParameters());
+ return new AsymmetricCipherKeyPair(pub, priv);
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionKeyParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionKeyParameters.java
new file mode 100644
index 00000000..a22eb286
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionKeyParameters.java
@@ -0,0 +1,20 @@
+package org.spongycastle.pqc.crypto.ntru;
+
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+
+public class NTRUEncryptionKeyParameters
+ extends AsymmetricKeyParameter
+{
+ final protected NTRUEncryptionParameters params;
+
+ public NTRUEncryptionKeyParameters(boolean privateKey, NTRUEncryptionParameters params)
+ {
+ super(privateKey);
+ this.params = params;
+ }
+
+ public NTRUEncryptionParameters getParameters()
+ {
+ return params;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionParameters.java
new file mode 100644
index 00000000..86dabae8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionParameters.java
@@ -0,0 +1,410 @@
+package org.spongycastle.pqc.crypto.ntru;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.digests.SHA512Digest;
+
+/**
+ * A set of parameters for NtruEncrypt. Several predefined parameter sets are available and new ones can be created as well.
+ */
+public class NTRUEncryptionParameters
+ implements Cloneable
+{
+
+ public int N, q, df, df1, df2, df3;
+ public int dr;
+ public int dr1;
+ public int dr2;
+ public int dr3;
+ public int dg;
+ int llen;
+ public int maxMsgLenBytes;
+ public int db;
+ public int bufferLenBits;
+ int bufferLenTrits;
+ public int dm0;
+ public int pkLen;
+ public int c;
+ public int minCallsR;
+ public int minCallsMask;
+ public boolean hashSeed;
+ public byte[] oid;
+ public boolean sparse;
+ public boolean fastFp;
+ public int polyType;
+ public Digest hashAlg;
+
+ /**
+ * Constructs a parameter set that uses ternary private keys (i.e. <code>polyType=SIMPLE</code>).
+ *
+ * @param N number of polynomial coefficients
+ * @param q modulus
+ * @param df number of ones in the private polynomial <code>f</code>
+ * @param dm0 minimum acceptable number of -1's, 0's, and 1's in the polynomial <code>m'</code> in the last encryption step
+ * @param db number of random bits to prepend to the message
+ * @param c a parameter for the Index Generation Function ({@link org.spongycastle.pqc.crypto.ntru.IndexGenerator})
+ * @param minCallsR minimum number of hash calls for the IGF to make
+ * @param minCallsMask minimum number of calls to generate the masking polynomial
+ * @param hashSeed whether to hash the seed in the MGF first (true) or use the seed directly (false)
+ * @param oid three bytes that uniquely identify the parameter set
+ * @param sparse whether to treat ternary polynomials as sparsely populated ({@link org.spongycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial} vs {@link org.spongycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial})
+ * @param fastFp whether <code>f=1+p*F</code> for a ternary <code>F</code> (true) or <code>f</code> is ternary (false)
+ * @param hashAlg a valid identifier for a <code>java.security.MessageDigest</code> instance such as <code>SHA-256</code>. The <code>MessageDigest</code> must support the <code>getDigestLength()</code> method.
+ */
+ public NTRUEncryptionParameters(int N, int q, int df, int dm0, int db, int c, int minCallsR, int minCallsMask, boolean hashSeed, byte[] oid, boolean sparse, boolean fastFp, Digest hashAlg)
+ {
+ this.N = N;
+ this.q = q;
+ this.df = df;
+ this.db = db;
+ this.dm0 = dm0;
+ this.c = c;
+ this.minCallsR = minCallsR;
+ this.minCallsMask = minCallsMask;
+ this.hashSeed = hashSeed;
+ this.oid = oid;
+ this.sparse = sparse;
+ this.fastFp = fastFp;
+ this.polyType = NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE;
+ this.hashAlg = hashAlg;
+ init();
+ }
+
+ /**
+ * Constructs a parameter set that uses product-form private keys (i.e. <code>polyType=PRODUCT</code>).
+ *
+ * @param N number of polynomial coefficients
+ * @param q modulus
+ * @param df1 number of ones in the private polynomial <code>f1</code>
+ * @param df2 number of ones in the private polynomial <code>f2</code>
+ * @param df3 number of ones in the private polynomial <code>f3</code>
+ * @param dm0 minimum acceptable number of -1's, 0's, and 1's in the polynomial <code>m'</code> in the last encryption step
+ * @param db number of random bits to prepend to the message
+ * @param c a parameter for the Index Generation Function ({@link org.spongycastle.pqc.crypto.ntru.IndexGenerator})
+ * @param minCallsR minimum number of hash calls for the IGF to make
+ * @param minCallsMask minimum number of calls to generate the masking polynomial
+ * @param hashSeed whether to hash the seed in the MGF first (true) or use the seed directly (false)
+ * @param oid three bytes that uniquely identify the parameter set
+ * @param sparse whether to treat ternary polynomials as sparsely populated ({@link org.spongycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial} vs {@link org.spongycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial})
+ * @param fastFp whether <code>f=1+p*F</code> for a ternary <code>F</code> (true) or <code>f</code> is ternary (false)
+ * @param hashAlg a valid identifier for a <code>java.security.MessageDigest</code> instance such as <code>SHA-256</code>
+ */
+ public NTRUEncryptionParameters(int N, int q, int df1, int df2, int df3, int dm0, int db, int c, int minCallsR, int minCallsMask, boolean hashSeed, byte[] oid, boolean sparse, boolean fastFp, Digest hashAlg)
+ {
+ this.N = N;
+ this.q = q;
+ this.df1 = df1;
+ this.df2 = df2;
+ this.df3 = df3;
+ this.db = db;
+ this.dm0 = dm0;
+ this.c = c;
+ this.minCallsR = minCallsR;
+ this.minCallsMask = minCallsMask;
+ this.hashSeed = hashSeed;
+ this.oid = oid;
+ this.sparse = sparse;
+ this.fastFp = fastFp;
+ this.polyType = NTRUParameters.TERNARY_POLYNOMIAL_TYPE_PRODUCT;
+ this.hashAlg = hashAlg;
+ init();
+ }
+
+ private void init()
+ {
+ dr = df;
+ dr1 = df1;
+ dr2 = df2;
+ dr3 = df3;
+ dg = N / 3;
+ llen = 1; // ceil(log2(maxMsgLenBytes))
+ maxMsgLenBytes = N * 3 / 2 / 8 - llen - db / 8 - 1;
+ bufferLenBits = (N * 3 / 2 + 7) / 8 * 8 + 1;
+ bufferLenTrits = N - 1;
+ pkLen = db;
+ }
+
+ /**
+ * Reads a parameter set from an input stream.
+ *
+ * @param is an input stream
+ * @throws IOException
+ */
+ public NTRUEncryptionParameters(InputStream is)
+ throws IOException
+ {
+ DataInputStream dis = new DataInputStream(is);
+ N = dis.readInt();
+ q = dis.readInt();
+ df = dis.readInt();
+ df1 = dis.readInt();
+ df2 = dis.readInt();
+ df3 = dis.readInt();
+ db = dis.readInt();
+ dm0 = dis.readInt();
+ c = dis.readInt();
+ minCallsR = dis.readInt();
+ minCallsMask = dis.readInt();
+ hashSeed = dis.readBoolean();
+ oid = new byte[3];
+ dis.read(oid);
+ sparse = dis.readBoolean();
+ fastFp = dis.readBoolean();
+ polyType = dis.read();
+
+ String alg = dis.readUTF();
+
+ if ("SHA-512".equals(alg))
+ {
+ hashAlg = new SHA512Digest();
+ }
+ else if ("SHA-256".equals(alg))
+ {
+ hashAlg = new SHA256Digest();
+ }
+
+ init();
+ }
+
+ public NTRUEncryptionParameters clone()
+ {
+ if (polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE)
+ {
+ return new NTRUEncryptionParameters(N, q, df, dm0, db, c, minCallsR, minCallsMask, hashSeed, oid, sparse, fastFp, hashAlg);
+ }
+ else
+ {
+ return new NTRUEncryptionParameters(N, q, df1, df2, df3, dm0, db, c, minCallsR, minCallsMask, hashSeed, oid, sparse, fastFp, hashAlg);
+ }
+ }
+
+ /**
+ * Returns the maximum length a plaintext message can be with this parameter set.
+ *
+ * @return the maximum length in bytes
+ */
+ public int getMaxMessageLength()
+ {
+ return maxMsgLenBytes;
+ }
+
+ /**
+ * Writes the parameter set to an output stream
+ *
+ * @param os an output stream
+ * @throws IOException
+ */
+ public void writeTo(OutputStream os)
+ throws IOException
+ {
+ DataOutputStream dos = new DataOutputStream(os);
+ dos.writeInt(N);
+ dos.writeInt(q);
+ dos.writeInt(df);
+ dos.writeInt(df1);
+ dos.writeInt(df2);
+ dos.writeInt(df3);
+ dos.writeInt(db);
+ dos.writeInt(dm0);
+ dos.writeInt(c);
+ dos.writeInt(minCallsR);
+ dos.writeInt(minCallsMask);
+ dos.writeBoolean(hashSeed);
+ dos.write(oid);
+ dos.writeBoolean(sparse);
+ dos.writeBoolean(fastFp);
+ dos.write(polyType);
+ dos.writeUTF(hashAlg.getAlgorithmName());
+ }
+
+
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + N;
+ result = prime * result + bufferLenBits;
+ result = prime * result + bufferLenTrits;
+ result = prime * result + c;
+ result = prime * result + db;
+ result = prime * result + df;
+ result = prime * result + df1;
+ result = prime * result + df2;
+ result = prime * result + df3;
+ result = prime * result + dg;
+ result = prime * result + dm0;
+ result = prime * result + dr;
+ result = prime * result + dr1;
+ result = prime * result + dr2;
+ result = prime * result + dr3;
+ result = prime * result + (fastFp ? 1231 : 1237);
+ result = prime * result + ((hashAlg == null) ? 0 : hashAlg.getAlgorithmName().hashCode());
+ result = prime * result + (hashSeed ? 1231 : 1237);
+ result = prime * result + llen;
+ result = prime * result + maxMsgLenBytes;
+ result = prime * result + minCallsMask;
+ result = prime * result + minCallsR;
+ result = prime * result + Arrays.hashCode(oid);
+ result = prime * result + pkLen;
+ result = prime * result + polyType;
+ result = prime * result + q;
+ result = prime * result + (sparse ? 1231 : 1237);
+ return result;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+ NTRUEncryptionParameters other = (NTRUEncryptionParameters)obj;
+ if (N != other.N)
+ {
+ return false;
+ }
+ if (bufferLenBits != other.bufferLenBits)
+ {
+ return false;
+ }
+ if (bufferLenTrits != other.bufferLenTrits)
+ {
+ return false;
+ }
+ if (c != other.c)
+ {
+ return false;
+ }
+ if (db != other.db)
+ {
+ return false;
+ }
+ if (df != other.df)
+ {
+ return false;
+ }
+ if (df1 != other.df1)
+ {
+ return false;
+ }
+ if (df2 != other.df2)
+ {
+ return false;
+ }
+ if (df3 != other.df3)
+ {
+ return false;
+ }
+ if (dg != other.dg)
+ {
+ return false;
+ }
+ if (dm0 != other.dm0)
+ {
+ return false;
+ }
+ if (dr != other.dr)
+ {
+ return false;
+ }
+ if (dr1 != other.dr1)
+ {
+ return false;
+ }
+ if (dr2 != other.dr2)
+ {
+ return false;
+ }
+ if (dr3 != other.dr3)
+ {
+ return false;
+ }
+ if (fastFp != other.fastFp)
+ {
+ return false;
+ }
+ if (hashAlg == null)
+ {
+ if (other.hashAlg != null)
+ {
+ return false;
+ }
+ }
+ else if (!hashAlg.getAlgorithmName().equals(other.hashAlg.getAlgorithmName()))
+ {
+ return false;
+ }
+ if (hashSeed != other.hashSeed)
+ {
+ return false;
+ }
+ if (llen != other.llen)
+ {
+ return false;
+ }
+ if (maxMsgLenBytes != other.maxMsgLenBytes)
+ {
+ return false;
+ }
+ if (minCallsMask != other.minCallsMask)
+ {
+ return false;
+ }
+ if (minCallsR != other.minCallsR)
+ {
+ return false;
+ }
+ if (!Arrays.equals(oid, other.oid))
+ {
+ return false;
+ }
+ if (pkLen != other.pkLen)
+ {
+ return false;
+ }
+ if (polyType != other.polyType)
+ {
+ return false;
+ }
+ if (q != other.q)
+ {
+ return false;
+ }
+ if (sparse != other.sparse)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public String toString()
+ {
+ StringBuilder output = new StringBuilder("EncryptionParameters(N=" + N + " q=" + q);
+ if (polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE)
+ {
+ output.append(" polyType=SIMPLE df=" + df);
+ }
+ else
+ {
+ output.append(" polyType=PRODUCT df1=" + df1 + " df2=" + df2 + " df3=" + df3);
+ }
+ output.append(" dm0=" + dm0 + " db=" + db + " c=" + c + " minCallsR=" + minCallsR + " minCallsMask=" + minCallsMask +
+ " hashSeed=" + hashSeed + " hashAlg=" + hashAlg + " oid=" + Arrays.toString(oid) + " sparse=" + sparse + ")");
+ return output.toString();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionPrivateKeyParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionPrivateKeyParameters.java
new file mode 100644
index 00000000..5b0adbea
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionPrivateKeyParameters.java
@@ -0,0 +1,199 @@
+package org.spongycastle.pqc.crypto.ntru;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.spongycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.Polynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.ProductFormPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial;
+
+/**
+ * A NtruEncrypt private key is essentially a polynomial named <code>f</code>
+ * which takes different forms depending on whether product-form polynomials are used,
+ * and on <code>fastP</code><br>
+ * The inverse of <code>f</code> modulo <code>p</code> is precomputed on initialization.
+ */
+public class NTRUEncryptionPrivateKeyParameters
+ extends NTRUEncryptionKeyParameters
+{
+ public Polynomial t;
+ public IntegerPolynomial fp;
+ public IntegerPolynomial h;
+
+ /**
+ * Constructs a new private key from a polynomial
+ *
+ * @param h the public polynomial for the key.
+ * @param t the polynomial which determines the key: if <code>fastFp=true</code>, <code>f=1+3t</code>; otherwise, <code>f=t</code>
+ * @param fp the inverse of <code>f</code>
+ * @param params the NtruEncrypt parameters to use
+ */
+ public NTRUEncryptionPrivateKeyParameters(IntegerPolynomial h, Polynomial t, IntegerPolynomial fp, NTRUEncryptionParameters params)
+ {
+ super(true, params);
+
+ this.h = h;
+ this.t = t;
+ this.fp = fp;
+ }
+
+ /**
+ * Converts a byte array to a polynomial <code>f</code> and constructs a new private key
+ *
+ * @param b an encoded polynomial
+ * @param params the NtruEncrypt parameters to use
+ * @see #getEncoded()
+ */
+ public NTRUEncryptionPrivateKeyParameters(byte[] b, NTRUEncryptionParameters params)
+ throws IOException
+ {
+ this(new ByteArrayInputStream(b), params);
+ }
+
+ /**
+ * Reads a polynomial <code>f</code> from an input stream and constructs a new private key
+ *
+ * @param is an input stream
+ * @param params the NtruEncrypt parameters to use
+ * @see #writeTo(OutputStream)
+ */
+ public NTRUEncryptionPrivateKeyParameters(InputStream is, NTRUEncryptionParameters params)
+ throws IOException
+ {
+ super(true, params);
+
+ if (params.polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_PRODUCT)
+ {
+ int N = params.N;
+ int df1 = params.df1;
+ int df2 = params.df2;
+ int df3Ones = params.df3;
+ int df3NegOnes = params.fastFp ? params.df3 : params.df3 - 1;
+ h = IntegerPolynomial.fromBinary(is, params.N, params.q);
+ t = ProductFormPolynomial.fromBinary(is, N, df1, df2, df3Ones, df3NegOnes);
+ }
+ else
+ {
+ h = IntegerPolynomial.fromBinary(is, params.N, params.q);
+ IntegerPolynomial fInt = IntegerPolynomial.fromBinary3Tight(is, params.N);
+ t = params.sparse ? new SparseTernaryPolynomial(fInt) : new DenseTernaryPolynomial(fInt);
+ }
+
+ init();
+ }
+
+ /**
+ * Initializes <code>fp</code> from t.
+ */
+ private void init()
+ {
+ if (params.fastFp)
+ {
+ fp = new IntegerPolynomial(params.N);
+ fp.coeffs[0] = 1;
+ }
+ else
+ {
+ fp = t.toIntegerPolynomial().invertF3();
+ }
+ }
+
+ /**
+ * Converts the key to a byte array
+ *
+ * @return the encoded key
+ * @see #NTRUEncryptionPrivateKeyParameters(byte[], NTRUEncryptionParameters)
+ */
+ public byte[] getEncoded()
+ {
+ byte[] hBytes = h.toBinary(params.q);
+ byte[] tBytes;
+
+ if (t instanceof ProductFormPolynomial)
+ {
+ tBytes = ((ProductFormPolynomial)t).toBinary();
+ }
+ else
+ {
+ tBytes = t.toIntegerPolynomial().toBinary3Tight();
+ }
+
+ byte[] res = new byte[hBytes.length + tBytes.length];
+
+ System.arraycopy(hBytes, 0, res, 0, hBytes.length);
+ System.arraycopy(tBytes, 0, res, hBytes.length, tBytes.length);
+
+ return res;
+ }
+
+ /**
+ * Writes the key to an output stream
+ *
+ * @param os an output stream
+ * @throws IOException
+ * @see #NTRUEncryptionPrivateKeyParameters(InputStream, NTRUEncryptionParameters)
+ */
+ public void writeTo(OutputStream os)
+ throws IOException
+ {
+ os.write(getEncoded());
+ }
+
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((params == null) ? 0 : params.hashCode());
+ result = prime * result + ((t == null) ? 0 : t.hashCode());
+ result = prime * result + ((h == null) ? 0 : h.hashCode());
+ return result;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof NTRUEncryptionPrivateKeyParameters))
+ {
+ return false;
+ }
+ NTRUEncryptionPrivateKeyParameters other = (NTRUEncryptionPrivateKeyParameters)obj;
+ if (params == null)
+ {
+ if (other.params != null)
+ {
+ return false;
+ }
+ }
+ else if (!params.equals(other.params))
+ {
+ return false;
+ }
+ if (t == null)
+ {
+ if (other.t != null)
+ {
+ return false;
+ }
+ }
+ else if (!t.equals(other.t))
+ {
+ return false;
+ }
+ if (!h.equals(other.h))
+ {
+ return false;
+ }
+ return true;
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionPublicKeyParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionPublicKeyParameters.java
new file mode 100644
index 00000000..0f3abd9c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionPublicKeyParameters.java
@@ -0,0 +1,131 @@
+package org.spongycastle.pqc.crypto.ntru;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.spongycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
+
+/**
+ * A NtruEncrypt public key is essentially a polynomial named <code>h</code>.
+ */
+public class NTRUEncryptionPublicKeyParameters
+ extends NTRUEncryptionKeyParameters
+{
+ public IntegerPolynomial h;
+
+ /**
+ * Constructs a new public key from a polynomial
+ *
+ * @param h the polynomial <code>h</code> which determines the key
+ * @param params the NtruEncrypt parameters to use
+ */
+ public NTRUEncryptionPublicKeyParameters(IntegerPolynomial h, NTRUEncryptionParameters params)
+ {
+ super(false, params);
+
+ this.h = h;
+ }
+
+ /**
+ * Converts a byte array to a polynomial <code>h</code> and constructs a new public key
+ *
+ * @param b an encoded polynomial
+ * @param params the NtruEncrypt parameters to use
+ * @see #getEncoded()
+ */
+ public NTRUEncryptionPublicKeyParameters(byte[] b, NTRUEncryptionParameters params)
+ {
+ super(false, params);
+
+ h = IntegerPolynomial.fromBinary(b, params.N, params.q);
+ }
+
+ /**
+ * Reads a polynomial <code>h</code> from an input stream and constructs a new public key
+ *
+ * @param is an input stream
+ * @param params the NtruEncrypt parameters to use
+ * @see #writeTo(OutputStream)
+ */
+ public NTRUEncryptionPublicKeyParameters(InputStream is, NTRUEncryptionParameters params)
+ throws IOException
+ {
+ super(false, params);
+
+ h = IntegerPolynomial.fromBinary(is, params.N, params.q);
+ }
+
+ /**
+ * Converts the key to a byte array
+ *
+ * @return the encoded key
+ * @see #NTRUEncryptionPublicKeyParameters(byte[], NTRUEncryptionParameters)
+ */
+ public byte[] getEncoded()
+ {
+ return h.toBinary(params.q);
+ }
+
+ /**
+ * Writes the key to an output stream
+ *
+ * @param os an output stream
+ * @throws IOException
+ * @see #NTRUEncryptionPublicKeyParameters(InputStream, NTRUEncryptionParameters)
+ */
+ public void writeTo(OutputStream os)
+ throws IOException
+ {
+ os.write(getEncoded());
+ }
+
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((h == null) ? 0 : h.hashCode());
+ result = prime * result + ((params == null) ? 0 : params.hashCode());
+ return result;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof NTRUEncryptionPublicKeyParameters))
+ {
+ return false;
+ }
+ NTRUEncryptionPublicKeyParameters other = (NTRUEncryptionPublicKeyParameters)obj;
+ if (h == null)
+ {
+ if (other.h != null)
+ {
+ return false;
+ }
+ }
+ else if (!h.equals(other.h))
+ {
+ return false;
+ }
+ if (params == null)
+ {
+ if (other.params != null)
+ {
+ return false;
+ }
+ }
+ else if (!params.equals(other.params))
+ {
+ return false;
+ }
+ return true;
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEngine.java b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEngine.java
new file mode 100644
index 00000000..571057e2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEngine.java
@@ -0,0 +1,495 @@
+package org.spongycastle.pqc.crypto.ntru;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.Polynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.ProductFormPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.TernaryPolynomial;
+import org.spongycastle.util.Arrays;
+
+/**
+ * Encrypts, decrypts data and generates key pairs.<br>
+ * The parameter p is hardcoded to 3.
+ */
+public class NTRUEngine
+ implements AsymmetricBlockCipher
+{
+ private boolean forEncryption;
+ private NTRUEncryptionParameters params;
+ private NTRUEncryptionPublicKeyParameters pubKey;
+ private NTRUEncryptionPrivateKeyParameters privKey;
+ private SecureRandom random;
+
+ /**
+ * Constructs a new instance with a set of encryption parameters.
+ *
+ */
+ public NTRUEngine()
+ {
+ }
+
+ public void init(boolean forEncryption, CipherParameters parameters)
+ {
+ this.forEncryption = forEncryption;
+ if (forEncryption)
+ {
+ if (parameters instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom p = (ParametersWithRandom)parameters;
+
+ this.random = p.getRandom();
+ this.pubKey = (NTRUEncryptionPublicKeyParameters)p.getParameters();
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ this.pubKey = (NTRUEncryptionPublicKeyParameters)parameters;
+ }
+
+ this.params = pubKey.getParameters();
+ }
+ else
+ {
+ this.privKey = (NTRUEncryptionPrivateKeyParameters)parameters;
+ this.params = privKey.getParameters();
+ }
+ }
+
+ public int getInputBlockSize()
+ {
+ return params.maxMsgLenBytes;
+ }
+
+ public int getOutputBlockSize()
+ {
+ return ((params.N * log2(params.q)) + 7) / 8;
+ }
+
+ public byte[] processBlock(byte[] in, int inOff, int len)
+ throws InvalidCipherTextException
+ {
+ byte[] tmp = new byte[len];
+
+ System.arraycopy(in, inOff, tmp, 0, len);
+
+ if (forEncryption)
+ {
+ return encrypt(tmp, pubKey);
+ }
+ else
+ {
+ return decrypt(tmp, privKey);
+ }
+ }
+
+ /**
+ * Encrypts a message.<br/>
+ * See P1363.1 section 9.2.2.
+ *
+ * @param m The message to encrypt
+ * @param pubKey the public key to encrypt the message with
+ * @return the encrypted message
+ */
+ private byte[] encrypt(byte[] m, NTRUEncryptionPublicKeyParameters pubKey)
+ {
+ IntegerPolynomial pub = pubKey.h;
+ int N = params.N;
+ int q = params.q;
+
+ int maxLenBytes = params.maxMsgLenBytes;
+ int db = params.db;
+ int bufferLenBits = params.bufferLenBits;
+ int dm0 = params.dm0;
+ int pkLen = params.pkLen;
+ int minCallsMask = params.minCallsMask;
+ boolean hashSeed = params.hashSeed;
+ byte[] oid = params.oid;
+
+ int l = m.length;
+ if (maxLenBytes > 255)
+ {
+ throw new IllegalArgumentException("llen values bigger than 1 are not supported");
+ }
+ if (l > maxLenBytes)
+ {
+ throw new DataLengthException("Message too long: " + l + ">" + maxLenBytes);
+ }
+
+ while (true)
+ {
+ // M = b|octL|m|p0
+ byte[] b = new byte[db / 8];
+ random.nextBytes(b);
+ byte[] p0 = new byte[maxLenBytes + 1 - l];
+ byte[] M = new byte[bufferLenBits / 8];
+
+ System.arraycopy(b, 0, M, 0, b.length);
+ M[b.length] = (byte)l;
+ System.arraycopy(m, 0, M, b.length + 1, m.length);
+ System.arraycopy(p0, 0, M, b.length + 1 + m.length, p0.length);
+
+ IntegerPolynomial mTrin = IntegerPolynomial.fromBinary3Sves(M, N);
+
+ // sData = OID|m|b|hTrunc
+ byte[] bh = pub.toBinary(q);
+ byte[] hTrunc = copyOf(bh, pkLen / 8);
+ byte[] sData = buildSData(oid, m, l, b, hTrunc);
+
+ Polynomial r = generateBlindingPoly(sData, M);
+ IntegerPolynomial R = r.mult(pub, q);
+ IntegerPolynomial R4 = (IntegerPolynomial)R.clone();
+ R4.modPositive(4);
+ byte[] oR4 = R4.toBinary(4);
+ IntegerPolynomial mask = MGF(oR4, N, minCallsMask, hashSeed);
+ mTrin.add(mask);
+ mTrin.mod3();
+
+ if (mTrin.count(-1) < dm0)
+ {
+ continue;
+ }
+ if (mTrin.count(0) < dm0)
+ {
+ continue;
+ }
+ if (mTrin.count(1) < dm0)
+ {
+ continue;
+ }
+
+ R.add(mTrin, q);
+ R.ensurePositive(q);
+ return R.toBinary(q);
+ }
+ }
+
+ private byte[] buildSData(byte[] oid, byte[] m, int l, byte[] b, byte[] hTrunc)
+ {
+ byte[] sData = new byte[oid.length + l + b.length + hTrunc.length];
+
+ System.arraycopy(oid, 0, sData, 0, oid.length);
+ System.arraycopy(m, 0, sData, oid.length, m.length);
+ System.arraycopy(b, 0, sData, oid.length + m.length, b.length);
+ System.arraycopy(hTrunc, 0, sData, oid.length + m.length + b.length, hTrunc.length);
+ return sData;
+ }
+
+ protected IntegerPolynomial encrypt(IntegerPolynomial m, TernaryPolynomial r, IntegerPolynomial pubKey)
+ {
+ IntegerPolynomial e = r.mult(pubKey, params.q);
+ e.add(m, params.q);
+ e.ensurePositive(params.q);
+ return e;
+ }
+
+ /**
+ * Deterministically generates a blinding polynomial from a seed and a message representative.
+ *
+ * @param seed
+ * @param M message representative
+ * @return a blinding polynomial
+ */
+ private Polynomial generateBlindingPoly(byte[] seed, byte[] M)
+ {
+ IndexGenerator ig = new IndexGenerator(seed, params);
+
+ if (params.polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_PRODUCT)
+ {
+ SparseTernaryPolynomial r1 = new SparseTernaryPolynomial(generateBlindingCoeffs(ig, params.dr1));
+ SparseTernaryPolynomial r2 = new SparseTernaryPolynomial(generateBlindingCoeffs(ig, params.dr2));
+ SparseTernaryPolynomial r3 = new SparseTernaryPolynomial(generateBlindingCoeffs(ig, params.dr3));
+ return new ProductFormPolynomial(r1, r2, r3);
+ }
+ else
+ {
+ int dr = params.dr;
+ boolean sparse = params.sparse;
+ int[] r = generateBlindingCoeffs(ig, dr);
+ if (sparse)
+ {
+ return new SparseTernaryPolynomial(r);
+ }
+ else
+ {
+ return new DenseTernaryPolynomial(r);
+ }
+ }
+ }
+
+ /**
+ * Generates an <code>int</code> array containing <code>dr</code> elements equal to <code>1</code>
+ * and <code>dr</code> elements equal to <code>-1</code> using an index generator.
+ *
+ * @param ig an index generator
+ * @param dr number of ones / negative ones
+ * @return an array containing numbers between <code>-1</code> and <code>1</code>
+ */
+ private int[] generateBlindingCoeffs(IndexGenerator ig, int dr)
+ {
+ int N = params.N;
+
+ int[] r = new int[N];
+ for (int coeff = -1; coeff <= 1; coeff += 2)
+ {
+ int t = 0;
+ while (t < dr)
+ {
+ int i = ig.nextIndex();
+ if (r[i] == 0)
+ {
+ r[i] = coeff;
+ t++;
+ }
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * An implementation of MGF-TP-1 from P1363.1 section 8.4.1.1.
+ *
+ * @param seed
+ * @param N
+ * @param minCallsR
+ * @param hashSeed whether to hash the seed
+ * @return
+ */
+ private IntegerPolynomial MGF(byte[] seed, int N, int minCallsR, boolean hashSeed)
+ {
+ Digest hashAlg = params.hashAlg;
+ int hashLen = hashAlg.getDigestSize();
+ byte[] buf = new byte[minCallsR * hashLen];
+ byte[] Z = hashSeed ? calcHash(hashAlg, seed) : seed;
+ int counter = 0;
+ while (counter < minCallsR)
+ {
+ hashAlg.update(Z, 0, Z.length);
+ putInt(hashAlg, counter);
+
+ byte[] hash = calcHash(hashAlg);
+ System.arraycopy(hash, 0, buf, counter * hashLen, hashLen);
+ counter++;
+ }
+
+ IntegerPolynomial i = new IntegerPolynomial(N);
+ while (true)
+ {
+ int cur = 0;
+ for (int index = 0; index != buf.length; index++)
+ {
+ int O = (int)buf[index] & 0xFF;
+ if (O >= 243) // 243 = 3^5
+ {
+ continue;
+ }
+
+ for (int terIdx = 0; terIdx < 4; terIdx++)
+ {
+ int rem3 = O % 3;
+ i.coeffs[cur] = rem3 - 1;
+ cur++;
+ if (cur == N)
+ {
+ return i;
+ }
+ O = (O - rem3) / 3;
+ }
+
+ i.coeffs[cur] = O - 1;
+ cur++;
+ if (cur == N)
+ {
+ return i;
+ }
+ }
+
+ if (cur >= N)
+ {
+ return i;
+ }
+
+ hashAlg.update(Z, 0, Z.length);
+ putInt(hashAlg, counter);
+
+ byte[] hash = calcHash(hashAlg);
+
+ buf = hash;
+
+ counter++;
+ }
+ }
+
+ private void putInt(Digest hashAlg, int counter)
+ {
+ hashAlg.update((byte)(counter >> 24));
+ hashAlg.update((byte)(counter >> 16));
+ hashAlg.update((byte)(counter >> 8));
+ hashAlg.update((byte)counter);
+ }
+
+ private byte[] calcHash(Digest hashAlg)
+ {
+ byte[] tmp = new byte[hashAlg.getDigestSize()];
+
+ hashAlg.doFinal(tmp, 0);
+
+ return tmp;
+ }
+
+ private byte[] calcHash(Digest hashAlg, byte[] input)
+ {
+ byte[] tmp = new byte[hashAlg.getDigestSize()];
+
+ hashAlg.update(input, 0, input.length);
+ hashAlg.doFinal(tmp, 0);
+
+ return tmp;
+ }
+ /**
+ * Decrypts a message.<br/>
+ * See P1363.1 section 9.2.3.
+ *
+ * @param data The message to decrypt
+ * @param privKey the corresponding private key
+ * @return the decrypted message
+ * @throws InvalidCipherTextException if the encrypted data is invalid, or <code>maxLenBytes</code> is greater than 255
+ */
+ private byte[] decrypt(byte[] data, NTRUEncryptionPrivateKeyParameters privKey)
+ throws InvalidCipherTextException
+ {
+ Polynomial priv_t = privKey.t;
+ IntegerPolynomial priv_fp = privKey.fp;
+ IntegerPolynomial pub = privKey.h;
+ int N = params.N;
+ int q = params.q;
+ int db = params.db;
+ int maxMsgLenBytes = params.maxMsgLenBytes;
+ int dm0 = params.dm0;
+ int pkLen = params.pkLen;
+ int minCallsMask = params.minCallsMask;
+ boolean hashSeed = params.hashSeed;
+ byte[] oid = params.oid;
+
+ if (maxMsgLenBytes > 255)
+ {
+ throw new DataLengthException("maxMsgLenBytes values bigger than 255 are not supported");
+ }
+
+ int bLen = db / 8;
+
+ IntegerPolynomial e = IntegerPolynomial.fromBinary(data, N, q);
+ IntegerPolynomial ci = decrypt(e, priv_t, priv_fp);
+
+ if (ci.count(-1) < dm0)
+ {
+ throw new InvalidCipherTextException("Less than dm0 coefficients equal -1");
+ }
+ if (ci.count(0) < dm0)
+ {
+ throw new InvalidCipherTextException("Less than dm0 coefficients equal 0");
+ }
+ if (ci.count(1) < dm0)
+ {
+ throw new InvalidCipherTextException("Less than dm0 coefficients equal 1");
+ }
+
+ IntegerPolynomial cR = (IntegerPolynomial)e.clone();
+ cR.sub(ci);
+ cR.modPositive(q);
+ IntegerPolynomial cR4 = (IntegerPolynomial)cR.clone();
+ cR4.modPositive(4);
+ byte[] coR4 = cR4.toBinary(4);
+ IntegerPolynomial mask = MGF(coR4, N, minCallsMask, hashSeed);
+ IntegerPolynomial cMTrin = ci;
+ cMTrin.sub(mask);
+ cMTrin.mod3();
+ byte[] cM = cMTrin.toBinary3Sves();
+
+ byte[] cb = new byte[bLen];
+ System.arraycopy(cM, 0, cb, 0, bLen);
+ int cl = cM[bLen] & 0xFF; // llen=1, so read one byte
+ if (cl > maxMsgLenBytes)
+ {
+ throw new InvalidCipherTextException("Message too long: " + cl + ">" + maxMsgLenBytes);
+ }
+ byte[] cm = new byte[cl];
+ System.arraycopy(cM, bLen + 1, cm, 0, cl);
+ byte[] p0 = new byte[cM.length - (bLen + 1 + cl)];
+ System.arraycopy(cM, bLen + 1 + cl, p0, 0, p0.length);
+ if (!Arrays.areEqual(p0, new byte[p0.length]))
+ {
+ throw new InvalidCipherTextException("The message is not followed by zeroes");
+ }
+
+ // sData = OID|m|b|hTrunc
+ byte[] bh = pub.toBinary(q);
+ byte[] hTrunc = copyOf(bh, pkLen / 8);
+ byte[] sData = buildSData(oid, cm, cl, cb, hTrunc);
+
+ Polynomial cr = generateBlindingPoly(sData, cm);
+ IntegerPolynomial cRPrime = cr.mult(pub);
+ cRPrime.modPositive(q);
+ if (!cRPrime.equals(cR))
+ {
+ throw new InvalidCipherTextException("Invalid message encoding");
+ }
+
+ return cm;
+ }
+
+ /**
+ * @param e
+ * @param priv_t a polynomial such that if <code>fastFp=true</code>, <code>f=1+3*priv_t</code>; otherwise, <code>f=priv_t</code>
+ * @param priv_fp
+ * @return
+ */
+ protected IntegerPolynomial decrypt(IntegerPolynomial e, Polynomial priv_t, IntegerPolynomial priv_fp)
+ {
+ IntegerPolynomial a;
+ if (params.fastFp)
+ {
+ a = priv_t.mult(e, params.q);
+ a.mult(3);
+ a.add(e);
+ }
+ else
+ {
+ a = priv_t.mult(e, params.q);
+ }
+ a.center0(params.q);
+ a.mod3();
+
+ IntegerPolynomial c = params.fastFp ? a : new DenseTernaryPolynomial(a).mult(priv_fp, 3);
+ c.center0(3);
+ return c;
+ }
+
+ private byte[] copyOf(byte[] src, int len)
+ {
+ byte[] tmp = new byte[len];
+
+ System.arraycopy(src, 0, tmp, 0, len < src.length ? len : src.length);
+
+ return tmp;
+ }
+
+ private int log2(int value)
+ {
+ if (value == 2048)
+ {
+ return 11;
+ }
+
+ throw new IllegalStateException("log2 not fully implemented");
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUParameters.java
new file mode 100644
index 00000000..3ce2154d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUParameters.java
@@ -0,0 +1,7 @@
+package org.spongycastle.pqc.crypto.ntru;
+
+public class NTRUParameters
+{
+ public static final int TERNARY_POLYNOMIAL_TYPE_SIMPLE = 0;
+ public static final int TERNARY_POLYNOMIAL_TYPE_PRODUCT = 1;
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigner.java b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigner.java
new file mode 100644
index 00000000..0886cff1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigner.java
@@ -0,0 +1,263 @@
+package org.spongycastle.pqc.crypto.ntru;
+
+import java.nio.ByteBuffer;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.Polynomial;
+
+/**
+* Signs, verifies data and generates key pairs.
+* @deprecated the NTRUSigner algorithm was broken in 2012 by Ducas and Nguyen. See
+* <a href="http://www.di.ens.fr/~ducas/NTRUSign_Cryptanalysis/DucasNguyen_Learning.pdf">
+* http://www.di.ens.fr/~ducas/NTRUSign_Cryptanalysis/DucasNguyen_Learning.pdf</a>
+* for details.
+*/
+public class NTRUSigner
+{
+ private NTRUSigningParameters params;
+ private Digest hashAlg;
+ private NTRUSigningPrivateKeyParameters signingKeyPair;
+ private NTRUSigningPublicKeyParameters verificationKey;
+
+ /**
+ * Constructs a new instance with a set of signature parameters.
+ *
+ * @param params signature parameters
+ */
+ public NTRUSigner(NTRUSigningParameters params)
+ {
+ this.params = params;
+ }
+
+ /**
+ * Resets the engine for signing a message.
+ *
+ * @param forSigning
+ * @param params
+ */
+ public void init(boolean forSigning, CipherParameters params)
+ {
+ if (forSigning)
+ {
+ this.signingKeyPair = (NTRUSigningPrivateKeyParameters)params;
+ }
+ else
+ {
+ this.verificationKey = (NTRUSigningPublicKeyParameters)params;
+ }
+ hashAlg = this.params.hashAlg;
+ hashAlg.reset();
+ }
+
+ /**
+ * Adds data to sign or verify.
+ *
+ * @param b data
+ */
+ public void update(byte b)
+ {
+ if (hashAlg == null)
+ {
+ throw new IllegalStateException("Call initSign or initVerify first!");
+ }
+
+ hashAlg.update(b);
+ }
+
+ /**
+ * Adds data to sign or verify.
+ *
+ * @param m data
+ * @param off offset
+ * @param length number of bytes
+ */
+ public void update(byte[] m, int off, int length)
+ {
+ if (hashAlg == null)
+ {
+ throw new IllegalStateException("Call initSign or initVerify first!");
+ }
+
+ hashAlg.update(m, off, length);
+ }
+
+ /**
+ * Adds data to sign and computes a signature over this data and any data previously added via {@link #update(byte[], int, int)}.
+ *
+ * @return a signature
+ * @throws IllegalStateException if <code>initSign</code> was not called
+ */
+ public byte[] generateSignature()
+ {
+ if (hashAlg == null || signingKeyPair == null)
+ {
+ throw new IllegalStateException("Call initSign first!");
+ }
+
+ byte[] msgHash = new byte[hashAlg.getDigestSize()];
+
+ hashAlg.doFinal(msgHash, 0);
+ return signHash(msgHash, signingKeyPair);
+ }
+
+ private byte[] signHash(byte[] msgHash, NTRUSigningPrivateKeyParameters kp)
+ {
+ int r = 0;
+ IntegerPolynomial s;
+ IntegerPolynomial i;
+
+ NTRUSigningPublicKeyParameters kPub = kp.getPublicKey();
+ do
+ {
+ r++;
+ if (r > params.signFailTolerance)
+ {
+ throw new IllegalStateException("Signing failed: too many retries (max=" + params.signFailTolerance + ")");
+ }
+ i = createMsgRep(msgHash, r);
+ s = sign(i, kp);
+ }
+ while (!verify(i, s, kPub.h));
+
+ byte[] rawSig = s.toBinary(params.q);
+ ByteBuffer sbuf = ByteBuffer.allocate(rawSig.length + 4);
+ sbuf.put(rawSig);
+ sbuf.putInt(r);
+ return sbuf.array();
+ }
+
+ private IntegerPolynomial sign(IntegerPolynomial i, NTRUSigningPrivateKeyParameters kp)
+ {
+ int N = params.N;
+ int q = params.q;
+ int perturbationBases = params.B;
+
+ NTRUSigningPrivateKeyParameters kPriv = kp;
+ NTRUSigningPublicKeyParameters kPub = kp.getPublicKey();
+
+ IntegerPolynomial s = new IntegerPolynomial(N);
+ int iLoop = perturbationBases;
+ while (iLoop >= 1)
+ {
+ Polynomial f = kPriv.getBasis(iLoop).f;
+ Polynomial fPrime = kPriv.getBasis(iLoop).fPrime;
+
+ IntegerPolynomial y = f.mult(i);
+ y.div(q);
+ y = fPrime.mult(y);
+
+ IntegerPolynomial x = fPrime.mult(i);
+ x.div(q);
+ x = f.mult(x);
+
+ IntegerPolynomial si = y;
+ si.sub(x);
+ s.add(si);
+
+ IntegerPolynomial hi = (IntegerPolynomial)kPriv.getBasis(iLoop).h.clone();
+ if (iLoop > 1)
+ {
+ hi.sub(kPriv.getBasis(iLoop - 1).h);
+ }
+ else
+ {
+ hi.sub(kPub.h);
+ }
+ i = si.mult(hi, q);
+
+ iLoop--;
+ }
+
+ Polynomial f = kPriv.getBasis(0).f;
+ Polynomial fPrime = kPriv.getBasis(0).fPrime;
+
+ IntegerPolynomial y = f.mult(i);
+ y.div(q);
+ y = fPrime.mult(y);
+
+ IntegerPolynomial x = fPrime.mult(i);
+ x.div(q);
+ x = f.mult(x);
+
+ y.sub(x);
+ s.add(y);
+ s.modPositive(q);
+ return s;
+ }
+
+ /**
+ * Verifies a signature for any data previously added via {@link #update(byte[], int, int)}.
+ *
+ * @param sig a signature
+ * @return whether the signature is valid
+ * @throws IllegalStateException if <code>initVerify</code> was not called
+ */
+ public boolean verifySignature(byte[] sig)
+ {
+ if (hashAlg == null || verificationKey == null)
+ {
+ throw new IllegalStateException("Call initVerify first!");
+ }
+
+ byte[] msgHash = new byte[hashAlg.getDigestSize()];
+
+ hashAlg.doFinal(msgHash, 0);
+
+ return verifyHash(msgHash, sig, verificationKey);
+ }
+
+ private boolean verifyHash(byte[] msgHash, byte[] sig, NTRUSigningPublicKeyParameters pub)
+ {
+ ByteBuffer sbuf = ByteBuffer.wrap(sig);
+ byte[] rawSig = new byte[sig.length - 4];
+ sbuf.get(rawSig);
+ IntegerPolynomial s = IntegerPolynomial.fromBinary(rawSig, params.N, params.q);
+ int r = sbuf.getInt();
+ return verify(createMsgRep(msgHash, r), s, pub.h);
+ }
+
+ private boolean verify(IntegerPolynomial i, IntegerPolynomial s, IntegerPolynomial h)
+ {
+ int q = params.q;
+ double normBoundSq = params.normBoundSq;
+ double betaSq = params.betaSq;
+
+ IntegerPolynomial t = h.mult(s, q);
+ t.sub(i);
+ long centeredNormSq = (long)(s.centeredNormSq(q) + betaSq * t.centeredNormSq(q));
+ return centeredNormSq <= normBoundSq;
+ }
+
+ protected IntegerPolynomial createMsgRep(byte[] msgHash, int r)
+ {
+ int N = params.N;
+ int q = params.q;
+
+ int c = 31 - Integer.numberOfLeadingZeros(q);
+ int B = (c + 7) / 8;
+ IntegerPolynomial i = new IntegerPolynomial(N);
+
+ ByteBuffer cbuf = ByteBuffer.allocate(msgHash.length + 4);
+ cbuf.put(msgHash);
+ cbuf.putInt(r);
+ NTRUSignerPrng prng = new NTRUSignerPrng(cbuf.array(), params.hashAlg);
+
+ for (int t = 0; t < N; t++)
+ {
+ byte[] o = prng.nextBytes(B);
+ int hi = o[o.length - 1];
+ hi >>= 8 * B - c;
+ hi <<= 8 * B - c;
+ o[o.length - 1] = (byte)hi;
+
+ ByteBuffer obuf = ByteBuffer.allocate(4);
+ obuf.put(o);
+ obuf.rewind();
+ // reverse byte order so it matches the endianness of java ints
+ i.coeffs[t] = Integer.reverseBytes(obuf.getInt());
+ }
+ return i;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSignerPrng.java b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSignerPrng.java
new file mode 100644
index 00000000..c9278dd5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSignerPrng.java
@@ -0,0 +1,64 @@
+package org.spongycastle.pqc.crypto.ntru;
+
+import java.nio.ByteBuffer;
+
+import org.spongycastle.crypto.Digest;
+
+/**
+ * An implementation of the deterministic pseudo-random generator in EESS section 3.7.3.1
+ */
+public class NTRUSignerPrng
+{
+ private int counter;
+ private byte[] seed;
+ private Digest hashAlg;
+
+ /**
+ * Constructs a new PRNG and seeds it with a byte array.
+ *
+ * @param seed a seed
+ * @param hashAlg the hash algorithm to use
+ */
+ NTRUSignerPrng(byte[] seed, Digest hashAlg)
+ {
+ counter = 0;
+ this.seed = seed;
+ this.hashAlg = hashAlg;
+ }
+
+ /**
+ * Returns <code>n</code> random bytes
+ *
+ * @param n number of bytes to return
+ * @return the next <code>n</code> random bytes
+ */
+ byte[] nextBytes(int n)
+ {
+ ByteBuffer buf = ByteBuffer.allocate(n);
+
+ while (buf.hasRemaining())
+ {
+ ByteBuffer cbuf = ByteBuffer.allocate(seed.length + 4);
+ cbuf.put(seed);
+ cbuf.putInt(counter);
+ byte[] array = cbuf.array();
+ byte[] hash = new byte[hashAlg.getDigestSize()];
+
+ hashAlg.update(array, 0, array.length);
+
+ hashAlg.doFinal(hash, 0);
+
+ if (buf.remaining() < hash.length)
+ {
+ buf.put(hash, 0, buf.remaining());
+ }
+ else
+ {
+ buf.put(hash);
+ }
+ counter++;
+ }
+
+ return buf.array();
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningKeyGenerationParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningKeyGenerationParameters.java
new file mode 100644
index 00000000..f9c17f1c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningKeyGenerationParameters.java
@@ -0,0 +1,407 @@
+package org.spongycastle.pqc.crypto.ntru;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.SecureRandom;
+import java.text.DecimalFormat;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.digests.SHA512Digest;
+
+/**
+ * A set of parameters for NtruSign. Several predefined parameter sets are available and new ones can be created as well.
+ */
+public class NTRUSigningKeyGenerationParameters
+ extends KeyGenerationParameters
+ implements Cloneable
+{
+ public static final int BASIS_TYPE_STANDARD = 0;
+ public static final int BASIS_TYPE_TRANSPOSE = 1;
+
+ public static final int KEY_GEN_ALG_RESULTANT = 0;
+ public static final int KEY_GEN_ALG_FLOAT = 1;
+
+ /**
+ * Gives 128 bits of security
+ */
+ public static final NTRUSigningKeyGenerationParameters APR2011_439 = new NTRUSigningKeyGenerationParameters(439, 2048, 146, 1, BASIS_TYPE_TRANSPOSE, 0.165, 490, 280, false, true, KEY_GEN_ALG_RESULTANT, new SHA256Digest());
+
+ /**
+ * Like <code>APR2011_439</code>, this parameter set gives 128 bits of security but uses product-form polynomials
+ */
+ public static final NTRUSigningKeyGenerationParameters APR2011_439_PROD = new NTRUSigningKeyGenerationParameters(439, 2048, 9, 8, 5, 1, BASIS_TYPE_TRANSPOSE, 0.165, 490, 280, false, true, KEY_GEN_ALG_RESULTANT, new SHA256Digest());
+
+ /**
+ * Gives 256 bits of security
+ */
+ public static final NTRUSigningKeyGenerationParameters APR2011_743 = new NTRUSigningKeyGenerationParameters(743, 2048, 248, 1, BASIS_TYPE_TRANSPOSE, 0.127, 560, 360, true, false, KEY_GEN_ALG_RESULTANT, new SHA512Digest());
+
+ /**
+ * Like <code>APR2011_439</code>, this parameter set gives 256 bits of security but uses product-form polynomials
+ */
+ public static final NTRUSigningKeyGenerationParameters APR2011_743_PROD = new NTRUSigningKeyGenerationParameters(743, 2048, 11, 11, 15, 1, BASIS_TYPE_TRANSPOSE, 0.127, 560, 360, true, false, KEY_GEN_ALG_RESULTANT, new SHA512Digest());
+
+ /**
+ * Generates key pairs quickly. Use for testing only.
+ */
+ public static final NTRUSigningKeyGenerationParameters TEST157 = new NTRUSigningKeyGenerationParameters(157, 256, 29, 1, BASIS_TYPE_TRANSPOSE, 0.38, 200, 80, false, false, KEY_GEN_ALG_RESULTANT, new SHA256Digest());
+ /**
+ * Generates key pairs quickly. Use for testing only.
+ */
+ public static final NTRUSigningKeyGenerationParameters TEST157_PROD = new NTRUSigningKeyGenerationParameters(157, 256, 5, 5, 8, 1, BASIS_TYPE_TRANSPOSE, 0.38, 200, 80, false, false, KEY_GEN_ALG_RESULTANT, new SHA256Digest());
+
+
+ public int N;
+ public int q;
+ public int d, d1, d2, d3, B;
+ double beta;
+ public double betaSq;
+ double normBound;
+ public double normBoundSq;
+ public int signFailTolerance = 100;
+ double keyNormBound;
+ public double keyNormBoundSq;
+ public boolean primeCheck; // true if N and 2N+1 are prime
+ public int basisType;
+ int bitsF = 6; // max #bits needed to encode one coefficient of the polynomial F
+ public boolean sparse; // whether to treat ternary polynomials as sparsely populated
+ public int keyGenAlg;
+ public Digest hashAlg;
+ public int polyType;
+
+ /**
+ * Constructs a parameter set that uses ternary private keys (i.e. <code>polyType=SIMPLE</code>).
+ *
+ * @param N number of polynomial coefficients
+ * @param q modulus
+ * @param d number of -1's in the private polynomials <code>f</code> and <code>g</code>
+ * @param B number of perturbations
+ * @param basisType whether to use the standard or transpose lattice
+ * @param beta balancing factor for the transpose lattice
+ * @param normBound maximum norm for valid signatures
+ * @param keyNormBound maximum norm for the ploynomials <code>F</code> and <code>G</code>
+ * @param primeCheck whether <code>2N+1</code> is prime
+ * @param sparse whether to treat ternary polynomials as sparsely populated ({@link org.spongycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial} vs {@link org.spongycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial})
+ * @param keyGenAlg <code>RESULTANT</code> produces better bases, <code>FLOAT</code> is slightly faster. <code>RESULTANT</code> follows the EESS standard while <code>FLOAT</code> is described in Hoffstein et al: An Introduction to Mathematical Cryptography.
+ * @param hashAlg a valid identifier for a <code>java.security.MessageDigest</code> instance such as <code>SHA-256</code>. The <code>MessageDigest</code> must support the <code>getDigestLength()</code> method.
+ */
+ public NTRUSigningKeyGenerationParameters(int N, int q, int d, int B, int basisType, double beta, double normBound, double keyNormBound, boolean primeCheck, boolean sparse, int keyGenAlg, Digest hashAlg)
+ {
+ super(new SecureRandom(), N);
+ this.N = N;
+ this.q = q;
+ this.d = d;
+ this.B = B;
+ this.basisType = basisType;
+ this.beta = beta;
+ this.normBound = normBound;
+ this.keyNormBound = keyNormBound;
+ this.primeCheck = primeCheck;
+ this.sparse = sparse;
+ this.keyGenAlg = keyGenAlg;
+ this.hashAlg = hashAlg;
+ polyType = NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE;
+ init();
+ }
+
+ /**
+ * Constructs a parameter set that uses product-form private keys (i.e. <code>polyType=PRODUCT</code>).
+ *
+ * @param N number of polynomial coefficients
+ * @param q modulus
+ * @param d1 number of -1's in the private polynomials <code>f</code> and <code>g</code>
+ * @param d2 number of -1's in the private polynomials <code>f</code> and <code>g</code>
+ * @param d3 number of -1's in the private polynomials <code>f</code> and <code>g</code>
+ * @param B number of perturbations
+ * @param basisType whether to use the standard or transpose lattice
+ * @param beta balancing factor for the transpose lattice
+ * @param normBound maximum norm for valid signatures
+ * @param keyNormBound maximum norm for the ploynomials <code>F</code> and <code>G</code>
+ * @param primeCheck whether <code>2N+1</code> is prime
+ * @param sparse whether to treat ternary polynomials as sparsely populated ({@link org.spongycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial} vs {@link org.spongycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial})
+ * @param keyGenAlg <code>RESULTANT</code> produces better bases, <code>FLOAT</code> is slightly faster. <code>RESULTANT</code> follows the EESS standard while <code>FLOAT</code> is described in Hoffstein et al: An Introduction to Mathematical Cryptography.
+ * @param hashAlg a valid identifier for a <code>java.security.MessageDigest</code> instance such as <code>SHA-256</code>. The <code>MessageDigest</code> must support the <code>getDigestLength()</code> method.
+ */
+ public NTRUSigningKeyGenerationParameters(int N, int q, int d1, int d2, int d3, int B, int basisType, double beta, double normBound, double keyNormBound, boolean primeCheck, boolean sparse, int keyGenAlg, Digest hashAlg)
+ {
+ super(new SecureRandom(), N);
+ this.N = N;
+ this.q = q;
+ this.d1 = d1;
+ this.d2 = d2;
+ this.d3 = d3;
+ this.B = B;
+ this.basisType = basisType;
+ this.beta = beta;
+ this.normBound = normBound;
+ this.keyNormBound = keyNormBound;
+ this.primeCheck = primeCheck;
+ this.sparse = sparse;
+ this.keyGenAlg = keyGenAlg;
+ this.hashAlg = hashAlg;
+ polyType = NTRUParameters.TERNARY_POLYNOMIAL_TYPE_PRODUCT;
+ init();
+ }
+
+ private void init()
+ {
+ betaSq = beta * beta;
+ normBoundSq = normBound * normBound;
+ keyNormBoundSq = keyNormBound * keyNormBound;
+ }
+
+ /**
+ * Reads a parameter set from an input stream.
+ *
+ * @param is an input stream
+ * @throws java.io.IOException
+ */
+ public NTRUSigningKeyGenerationParameters(InputStream is)
+ throws IOException
+ {
+ super(new SecureRandom(), 0); // TODO:
+ DataInputStream dis = new DataInputStream(is);
+ N = dis.readInt();
+ q = dis.readInt();
+ d = dis.readInt();
+ d1 = dis.readInt();
+ d2 = dis.readInt();
+ d3 = dis.readInt();
+ B = dis.readInt();
+ basisType = dis.readInt();
+ beta = dis.readDouble();
+ normBound = dis.readDouble();
+ keyNormBound = dis.readDouble();
+ signFailTolerance = dis.readInt();
+ primeCheck = dis.readBoolean();
+ sparse = dis.readBoolean();
+ bitsF = dis.readInt();
+ keyGenAlg = dis.read();
+ String alg = dis.readUTF();
+ if ("SHA-512".equals(alg))
+ {
+ hashAlg = new SHA512Digest();
+ }
+ else if ("SHA-256".equals(alg))
+ {
+ hashAlg = new SHA256Digest();
+ }
+ polyType = dis.read();
+ init();
+ }
+
+ /**
+ * Writes the parameter set to an output stream
+ *
+ * @param os an output stream
+ * @throws java.io.IOException
+ */
+ public void writeTo(OutputStream os)
+ throws IOException
+ {
+ DataOutputStream dos = new DataOutputStream(os);
+ dos.writeInt(N);
+ dos.writeInt(q);
+ dos.writeInt(d);
+ dos.writeInt(d1);
+ dos.writeInt(d2);
+ dos.writeInt(d3);
+ dos.writeInt(B);
+ dos.writeInt(basisType);
+ dos.writeDouble(beta);
+ dos.writeDouble(normBound);
+ dos.writeDouble(keyNormBound);
+ dos.writeInt(signFailTolerance);
+ dos.writeBoolean(primeCheck);
+ dos.writeBoolean(sparse);
+ dos.writeInt(bitsF);
+ dos.write(keyGenAlg);
+ dos.writeUTF(hashAlg.getAlgorithmName());
+ dos.write(polyType);
+ }
+
+ public NTRUSigningParameters getSigningParameters()
+ {
+ return new NTRUSigningParameters(N, q, d, B, beta, normBound, hashAlg);
+ }
+
+ public NTRUSigningKeyGenerationParameters clone()
+ {
+ if (polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE)
+ {
+ return new NTRUSigningKeyGenerationParameters(N, q, d, B, basisType, beta, normBound, keyNormBound, primeCheck, sparse, keyGenAlg, hashAlg);
+ }
+ else
+ {
+ return new NTRUSigningKeyGenerationParameters(N, q, d1, d2, d3, B, basisType, beta, normBound, keyNormBound, primeCheck, sparse, keyGenAlg, hashAlg);
+ }
+ }
+
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + B;
+ result = prime * result + N;
+ result = prime * result + basisType;
+ long temp;
+ temp = Double.doubleToLongBits(beta);
+ result = prime * result + (int)(temp ^ (temp >>> 32));
+ temp = Double.doubleToLongBits(betaSq);
+ result = prime * result + (int)(temp ^ (temp >>> 32));
+ result = prime * result + bitsF;
+ result = prime * result + d;
+ result = prime * result + d1;
+ result = prime * result + d2;
+ result = prime * result + d3;
+ result = prime * result + ((hashAlg == null) ? 0 : hashAlg.getAlgorithmName().hashCode());
+ result = prime * result + keyGenAlg;
+ temp = Double.doubleToLongBits(keyNormBound);
+ result = prime * result + (int)(temp ^ (temp >>> 32));
+ temp = Double.doubleToLongBits(keyNormBoundSq);
+ result = prime * result + (int)(temp ^ (temp >>> 32));
+ temp = Double.doubleToLongBits(normBound);
+ result = prime * result + (int)(temp ^ (temp >>> 32));
+ temp = Double.doubleToLongBits(normBoundSq);
+ result = prime * result + (int)(temp ^ (temp >>> 32));
+ result = prime * result + polyType;
+ result = prime * result + (primeCheck ? 1231 : 1237);
+ result = prime * result + q;
+ result = prime * result + signFailTolerance;
+ result = prime * result + (sparse ? 1231 : 1237);
+ return result;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof NTRUSigningKeyGenerationParameters))
+ {
+ return false;
+ }
+ NTRUSigningKeyGenerationParameters other = (NTRUSigningKeyGenerationParameters)obj;
+ if (B != other.B)
+ {
+ return false;
+ }
+ if (N != other.N)
+ {
+ return false;
+ }
+ if (basisType != other.basisType)
+ {
+ return false;
+ }
+ if (Double.doubleToLongBits(beta) != Double.doubleToLongBits(other.beta))
+ {
+ return false;
+ }
+ if (Double.doubleToLongBits(betaSq) != Double.doubleToLongBits(other.betaSq))
+ {
+ return false;
+ }
+ if (bitsF != other.bitsF)
+ {
+ return false;
+ }
+ if (d != other.d)
+ {
+ return false;
+ }
+ if (d1 != other.d1)
+ {
+ return false;
+ }
+ if (d2 != other.d2)
+ {
+ return false;
+ }
+ if (d3 != other.d3)
+ {
+ return false;
+ }
+ if (hashAlg == null)
+ {
+ if (other.hashAlg != null)
+ {
+ return false;
+ }
+ }
+ else if (!hashAlg.getAlgorithmName().equals(other.hashAlg.getAlgorithmName()))
+ {
+ return false;
+ }
+ if (keyGenAlg != other.keyGenAlg)
+ {
+ return false;
+ }
+ if (Double.doubleToLongBits(keyNormBound) != Double.doubleToLongBits(other.keyNormBound))
+ {
+ return false;
+ }
+ if (Double.doubleToLongBits(keyNormBoundSq) != Double.doubleToLongBits(other.keyNormBoundSq))
+ {
+ return false;
+ }
+ if (Double.doubleToLongBits(normBound) != Double.doubleToLongBits(other.normBound))
+ {
+ return false;
+ }
+ if (Double.doubleToLongBits(normBoundSq) != Double.doubleToLongBits(other.normBoundSq))
+ {
+ return false;
+ }
+ if (polyType != other.polyType)
+ {
+ return false;
+ }
+ if (primeCheck != other.primeCheck)
+ {
+ return false;
+ }
+ if (q != other.q)
+ {
+ return false;
+ }
+ if (signFailTolerance != other.signFailTolerance)
+ {
+ return false;
+ }
+ if (sparse != other.sparse)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public String toString()
+ {
+ DecimalFormat format = new DecimalFormat("0.00");
+
+ StringBuilder output = new StringBuilder("SignatureParameters(N=" + N + " q=" + q);
+ if (polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE)
+ {
+ output.append(" polyType=SIMPLE d=" + d);
+ }
+ else
+ {
+ output.append(" polyType=PRODUCT d1=" + d1 + " d2=" + d2 + " d3=" + d3);
+ }
+ output.append(" B=" + B + " basisType=" + basisType + " beta=" + format.format(beta) +
+ " normBound=" + format.format(normBound) + " keyNormBound=" + format.format(keyNormBound) +
+ " prime=" + primeCheck + " sparse=" + sparse + " keyGenAlg=" + keyGenAlg + " hashAlg=" + hashAlg + ")");
+ return output.toString();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningKeyPairGenerator.java b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningKeyPairGenerator.java
new file mode 100644
index 00000000..eac283aa
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningKeyPairGenerator.java
@@ -0,0 +1,357 @@
+package org.spongycastle.pqc.crypto.ntru;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.pqc.math.ntru.euclid.BigIntEuclidean;
+import org.spongycastle.pqc.math.ntru.polynomial.BigDecimalPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.BigIntPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.Polynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.ProductFormPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.Resultant;
+
+import static java.math.BigInteger.ONE;
+import static java.math.BigInteger.ZERO;
+
+public class NTRUSigningKeyPairGenerator
+ implements AsymmetricCipherKeyPairGenerator
+{
+ private NTRUSigningKeyGenerationParameters params;
+
+ public void init(KeyGenerationParameters param)
+ {
+ this.params = (NTRUSigningKeyGenerationParameters)param;
+ }
+
+ /**
+ * Generates a new signature key pair. Starts <code>B+1</code> threads.
+ *
+ * @return a key pair
+ */
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+ NTRUSigningPublicKeyParameters pub = null;
+ ExecutorService executor = Executors.newCachedThreadPool();
+ List<Future<NTRUSigningPrivateKeyParameters.Basis>> bases = new ArrayList<Future<NTRUSigningPrivateKeyParameters.Basis>>();
+ for (int k = params.B; k >= 0; k--)
+ {
+ bases.add(executor.submit(new BasisGenerationTask()));
+ }
+ executor.shutdown();
+
+ List<NTRUSigningPrivateKeyParameters.Basis> basises = new ArrayList<NTRUSigningPrivateKeyParameters.Basis>();
+
+ for (int k = params.B; k >= 0; k--)
+ {
+ Future<NTRUSigningPrivateKeyParameters.Basis> basis = bases.get(k);
+ try
+ {
+ basises.add(basis.get());
+ if (k == params.B)
+ {
+ pub = new NTRUSigningPublicKeyParameters(basis.get().h, params.getSigningParameters());
+ }
+ }
+ catch (Exception e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+ NTRUSigningPrivateKeyParameters priv = new NTRUSigningPrivateKeyParameters(basises, pub);
+ AsymmetricCipherKeyPair kp = new AsymmetricCipherKeyPair(pub, priv);
+ return kp;
+ }
+
+ /**
+ * Generates a new signature key pair. Runs in a single thread.
+ *
+ * @return a key pair
+ */
+ public AsymmetricCipherKeyPair generateKeyPairSingleThread()
+ {
+ List<NTRUSigningPrivateKeyParameters.Basis> basises = new ArrayList<NTRUSigningPrivateKeyParameters.Basis>();
+ NTRUSigningPublicKeyParameters pub = null;
+ for (int k = params.B; k >= 0; k--)
+ {
+ NTRUSigningPrivateKeyParameters.Basis basis = generateBoundedBasis();
+ basises.add(basis);
+ if (k == 0)
+ {
+ pub = new NTRUSigningPublicKeyParameters(basis.h, params.getSigningParameters());
+ }
+ }
+ NTRUSigningPrivateKeyParameters priv = new NTRUSigningPrivateKeyParameters(basises, pub);
+ return new AsymmetricCipherKeyPair(pub, priv);
+ }
+
+
+ /**
+ * Implementation of the optional steps 20 through 26 in EESS1v2.pdf, section 3.5.1.1.
+ * This doesn't seem to have much of an effect and sometimes actually increases the
+ * norm of F, but on average it slightly reduces the norm.<br/>
+ * This method changes <code>F</code> and <code>g</code> but leaves <code>f</code> and
+ * <code>g</code> unchanged.
+ *
+ * @param f
+ * @param g
+ * @param F
+ * @param G
+ * @param N
+ */
+ private void minimizeFG(IntegerPolynomial f, IntegerPolynomial g, IntegerPolynomial F, IntegerPolynomial G, int N)
+ {
+ int E = 0;
+ for (int j = 0; j < N; j++)
+ {
+ E += 2 * N * (f.coeffs[j] * f.coeffs[j] + g.coeffs[j] * g.coeffs[j]);
+ }
+
+ // [f(1)+g(1)]^2 = 4
+ E -= 4;
+
+ IntegerPolynomial u = (IntegerPolynomial)f.clone();
+ IntegerPolynomial v = (IntegerPolynomial)g.clone();
+ int j = 0;
+ int k = 0;
+ int maxAdjustment = N;
+ while (k < maxAdjustment && j < N)
+ {
+ int D = 0;
+ int i = 0;
+ while (i < N)
+ {
+ int D1 = F.coeffs[i] * f.coeffs[i];
+ int D2 = G.coeffs[i] * g.coeffs[i];
+ int D3 = 4 * N * (D1 + D2);
+ D += D3;
+ i++;
+ }
+ // f(1)+g(1) = 2
+ int D1 = 4 * (F.sumCoeffs() + G.sumCoeffs());
+ D -= D1;
+
+ if (D > E)
+ {
+ F.sub(u);
+ G.sub(v);
+ k++;
+ j = 0;
+ }
+ else if (D < -E)
+ {
+ F.add(u);
+ G.add(v);
+ k++;
+ j = 0;
+ }
+ j++;
+ u.rotate1();
+ v.rotate1();
+ }
+ }
+
+ /**
+ * Creates a NTRUSigner basis consisting of polynomials <code>f, g, F, G, h</code>.<br/>
+ * If <code>KeyGenAlg=FLOAT</code>, the basis may not be valid and this method must be rerun if that is the case.<br/>
+ *
+ * @see #generateBoundedBasis()
+ */
+ private FGBasis generateBasis()
+ {
+ int N = params.N;
+ int q = params.q;
+ int d = params.d;
+ int d1 = params.d1;
+ int d2 = params.d2;
+ int d3 = params.d3;
+ int basisType = params.basisType;
+
+ Polynomial f;
+ IntegerPolynomial fInt;
+ Polynomial g;
+ IntegerPolynomial gInt;
+ IntegerPolynomial fq;
+ Resultant rf;
+ Resultant rg;
+ BigIntEuclidean r;
+
+ int _2n1 = 2 * N + 1;
+ boolean primeCheck = params.primeCheck;
+
+ do
+ {
+ do
+ {
+ f = params.polyType== NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE ? DenseTernaryPolynomial.generateRandom(N, d + 1, d, new SecureRandom()) : ProductFormPolynomial.generateRandom(N, d1, d2, d3 + 1, d3, new SecureRandom());
+ fInt = f.toIntegerPolynomial();
+ }
+ while (primeCheck && fInt.resultant(_2n1).res.equals(ZERO));
+ fq = fInt.invertFq(q);
+ }
+ while (fq == null);
+ rf = fInt.resultant();
+
+ do
+ {
+ do
+ {
+ do
+ {
+ g = params.polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE ? DenseTernaryPolynomial.generateRandom(N, d + 1, d, new SecureRandom()) : ProductFormPolynomial.generateRandom(N, d1, d2, d3 + 1, d3, new SecureRandom());
+ gInt = g.toIntegerPolynomial();
+ }
+ while (primeCheck && gInt.resultant(_2n1).res.equals(ZERO));
+ }
+ while (gInt.invertFq(q) == null);
+ rg = gInt.resultant();
+ r = BigIntEuclidean.calculate(rf.res, rg.res);
+ }
+ while (!r.gcd.equals(ONE));
+
+ BigIntPolynomial A = (BigIntPolynomial)rf.rho.clone();
+ A.mult(r.x.multiply(BigInteger.valueOf(q)));
+ BigIntPolynomial B = (BigIntPolynomial)rg.rho.clone();
+ B.mult(r.y.multiply(BigInteger.valueOf(-q)));
+
+ BigIntPolynomial C;
+ if (params.keyGenAlg == NTRUSigningKeyGenerationParameters.KEY_GEN_ALG_RESULTANT)
+ {
+ int[] fRevCoeffs = new int[N];
+ int[] gRevCoeffs = new int[N];
+ fRevCoeffs[0] = fInt.coeffs[0];
+ gRevCoeffs[0] = gInt.coeffs[0];
+ for (int i = 1; i < N; i++)
+ {
+ fRevCoeffs[i] = fInt.coeffs[N - i];
+ gRevCoeffs[i] = gInt.coeffs[N - i];
+ }
+ IntegerPolynomial fRev = new IntegerPolynomial(fRevCoeffs);
+ IntegerPolynomial gRev = new IntegerPolynomial(gRevCoeffs);
+
+ IntegerPolynomial t = f.mult(fRev);
+ t.add(g.mult(gRev));
+ Resultant rt = t.resultant();
+ C = fRev.mult(B); // fRev.mult(B) is actually faster than new SparseTernaryPolynomial(fRev).mult(B), possibly due to cache locality?
+ C.add(gRev.mult(A));
+ C = C.mult(rt.rho);
+ C.div(rt.res);
+ }
+ else
+ { // KeyGenAlg.FLOAT
+ // calculate ceil(log10(N))
+ int log10N = 0;
+ for (int i = 1; i < N; i *= 10)
+ {
+ log10N++;
+ }
+
+ // * Cdec needs to be accurate to 1 decimal place so it can be correctly rounded;
+ // * fInv loses up to (#digits of longest coeff of B) places in fInv.mult(B);
+ // * multiplying fInv by B also multiplies the rounding error by a factor of N;
+ // so make #decimal places of fInv the sum of the above.
+ BigDecimalPolynomial fInv = rf.rho.div(new BigDecimal(rf.res), B.getMaxCoeffLength() + 1 + log10N);
+ BigDecimalPolynomial gInv = rg.rho.div(new BigDecimal(rg.res), A.getMaxCoeffLength() + 1 + log10N);
+
+ BigDecimalPolynomial Cdec = fInv.mult(B);
+ Cdec.add(gInv.mult(A));
+ Cdec.halve();
+ C = Cdec.round();
+ }
+
+ BigIntPolynomial F = (BigIntPolynomial)B.clone();
+ F.sub(f.mult(C));
+ BigIntPolynomial G = (BigIntPolynomial)A.clone();
+ G.sub(g.mult(C));
+
+ IntegerPolynomial FInt = new IntegerPolynomial(F);
+ IntegerPolynomial GInt = new IntegerPolynomial(G);
+ minimizeFG(fInt, gInt, FInt, GInt, N);
+
+ Polynomial fPrime;
+ IntegerPolynomial h;
+ if (basisType == NTRUSigningKeyGenerationParameters.BASIS_TYPE_STANDARD)
+ {
+ fPrime = FInt;
+ h = g.mult(fq, q);
+ }
+ else
+ {
+ fPrime = g;
+ h = FInt.mult(fq, q);
+ }
+ h.modPositive(q);
+
+ return new FGBasis(f, fPrime, h, FInt, GInt, params);
+ }
+
+ /**
+ * Creates a basis such that <code>|F| &lt; keyNormBound</code> and <code>|G| &lt; keyNormBound</code>
+ *
+ * @return a NTRUSigner basis
+ */
+ public NTRUSigningPrivateKeyParameters.Basis generateBoundedBasis()
+ {
+ while (true)
+ {
+ FGBasis basis = generateBasis();
+ if (basis.isNormOk())
+ {
+ return basis;
+ }
+ }
+ }
+
+ private class BasisGenerationTask
+ implements Callable<NTRUSigningPrivateKeyParameters.Basis>
+ {
+
+
+ public NTRUSigningPrivateKeyParameters.Basis call()
+ throws Exception
+ {
+ return generateBoundedBasis();
+ }
+ }
+
+ /**
+ * A subclass of Basis that additionally contains the polynomials <code>F</code> and <code>G</code>.
+ */
+ public class FGBasis
+ extends NTRUSigningPrivateKeyParameters.Basis
+ {
+ public IntegerPolynomial F;
+ public IntegerPolynomial G;
+
+ FGBasis(Polynomial f, Polynomial fPrime, IntegerPolynomial h, IntegerPolynomial F, IntegerPolynomial G, NTRUSigningKeyGenerationParameters params)
+ {
+ super(f, fPrime, h, params);
+ this.F = F;
+ this.G = G;
+ }
+
+ /**
+ * Returns <code>true</code> if the norms of the polynomials <code>F</code> and <code>G</code>
+ * are within {@link NTRUSigningKeyGenerationParameters#keyNormBound}.
+ *
+ * @return
+ */
+ boolean isNormOk()
+ {
+ double keyNormBoundSq = params.keyNormBoundSq;
+ int q = params.q;
+ return (F.centeredNormSq(q) < keyNormBoundSq && G.centeredNormSq(q) < keyNormBoundSq);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningParameters.java
new file mode 100644
index 00000000..bf9ba2cb
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningParameters.java
@@ -0,0 +1,269 @@
+package org.spongycastle.pqc.crypto.ntru;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.text.DecimalFormat;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.digests.SHA512Digest;
+
+/**
+ * A set of parameters for NtruSign. Several predefined parameter sets are available and new ones can be created as well.
+ */
+public class NTRUSigningParameters
+ implements Cloneable
+{
+ public int N;
+ public int q;
+ public int d, d1, d2, d3, B;
+ double beta;
+ public double betaSq;
+ double normBound;
+ public double normBoundSq;
+ public int signFailTolerance = 100;
+ int bitsF = 6; // max #bits needed to encode one coefficient of the polynomial F
+ public Digest hashAlg;
+
+ /**
+ * Constructs a parameter set that uses ternary private keys (i.e. <code>polyType=SIMPLE</code>).
+ *
+ * @param N number of polynomial coefficients
+ * @param q modulus
+ * @param d number of -1's in the private polynomials <code>f</code> and <code>g</code>
+ * @param B number of perturbations
+ * @param beta balancing factor for the transpose lattice
+ * @param normBound maximum norm for valid signatures
+ * @param hashAlg a valid identifier for a <code>java.security.MessageDigest</code> instance such as <code>SHA-256</code>. The <code>MessageDigest</code> must support the <code>getDigestLength()</code> method.
+ */
+ public NTRUSigningParameters(int N, int q, int d, int B, double beta, double normBound, Digest hashAlg)
+ {
+ this.N = N;
+ this.q = q;
+ this.d = d;
+ this.B = B;
+ this.beta = beta;
+ this.normBound = normBound;
+ this.hashAlg = hashAlg;
+ init();
+ }
+
+ /**
+ * Constructs a parameter set that uses product-form private keys (i.e. <code>polyType=PRODUCT</code>).
+ *
+ * @param N number of polynomial coefficients
+ * @param q modulus
+ * @param d1 number of -1's in the private polynomials <code>f</code> and <code>g</code>
+ * @param d2 number of -1's in the private polynomials <code>f</code> and <code>g</code>
+ * @param d3 number of -1's in the private polynomials <code>f</code> and <code>g</code>
+ * @param B number of perturbations
+ * @param beta balancing factor for the transpose lattice
+ * @param normBound maximum norm for valid signatures
+ * @param keyNormBound maximum norm for the ploynomials <code>F</code> and <code>G</code>
+ * @param hashAlg a valid identifier for a <code>java.security.MessageDigest</code> instance such as <code>SHA-256</code>. The <code>MessageDigest</code> must support the <code>getDigestLength()</code> method.
+ */
+ public NTRUSigningParameters(int N, int q, int d1, int d2, int d3, int B, double beta, double normBound, double keyNormBound, Digest hashAlg)
+ {
+ this.N = N;
+ this.q = q;
+ this.d1 = d1;
+ this.d2 = d2;
+ this.d3 = d3;
+ this.B = B;
+ this.beta = beta;
+ this.normBound = normBound;
+ this.hashAlg = hashAlg;
+ init();
+ }
+
+ private void init()
+ {
+ betaSq = beta * beta;
+ normBoundSq = normBound * normBound;
+ }
+
+ /**
+ * Reads a parameter set from an input stream.
+ *
+ * @param is an input stream
+ * @throws IOException
+ */
+ public NTRUSigningParameters(InputStream is)
+ throws IOException
+ {
+ DataInputStream dis = new DataInputStream(is);
+ N = dis.readInt();
+ q = dis.readInt();
+ d = dis.readInt();
+ d1 = dis.readInt();
+ d2 = dis.readInt();
+ d3 = dis.readInt();
+ B = dis.readInt();
+ beta = dis.readDouble();
+ normBound = dis.readDouble();
+ signFailTolerance = dis.readInt();
+ bitsF = dis.readInt();
+ String alg = dis.readUTF();
+ if ("SHA-512".equals(alg))
+ {
+ hashAlg = new SHA512Digest();
+ }
+ else if ("SHA-256".equals(alg))
+ {
+ hashAlg = new SHA256Digest();
+ }
+ init();
+ }
+
+ /**
+ * Writes the parameter set to an output stream
+ *
+ * @param os an output stream
+ * @throws IOException
+ */
+ public void writeTo(OutputStream os)
+ throws IOException
+ {
+ DataOutputStream dos = new DataOutputStream(os);
+ dos.writeInt(N);
+ dos.writeInt(q);
+ dos.writeInt(d);
+ dos.writeInt(d1);
+ dos.writeInt(d2);
+ dos.writeInt(d3);
+ dos.writeInt(B);
+ dos.writeDouble(beta);
+ dos.writeDouble(normBound);
+ dos.writeInt(signFailTolerance);
+ dos.writeInt(bitsF);
+ dos.writeUTF(hashAlg.getAlgorithmName());
+ }
+
+ public NTRUSigningParameters clone()
+ {
+ return new NTRUSigningParameters(N, q, d, B, beta, normBound, hashAlg);
+ }
+
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + B;
+ result = prime * result + N;
+ long temp;
+ temp = Double.doubleToLongBits(beta);
+ result = prime * result + (int)(temp ^ (temp >>> 32));
+ temp = Double.doubleToLongBits(betaSq);
+ result = prime * result + (int)(temp ^ (temp >>> 32));
+ result = prime * result + bitsF;
+ result = prime * result + d;
+ result = prime * result + d1;
+ result = prime * result + d2;
+ result = prime * result + d3;
+ result = prime * result + ((hashAlg == null) ? 0 : hashAlg.getAlgorithmName().hashCode());
+ temp = Double.doubleToLongBits(normBound);
+ result = prime * result + (int)(temp ^ (temp >>> 32));
+ temp = Double.doubleToLongBits(normBoundSq);
+ result = prime * result + (int)(temp ^ (temp >>> 32));
+ result = prime * result + q;
+ result = prime * result + signFailTolerance;
+ return result;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof NTRUSigningParameters))
+ {
+ return false;
+ }
+ NTRUSigningParameters other = (NTRUSigningParameters)obj;
+ if (B != other.B)
+ {
+ return false;
+ }
+ if (N != other.N)
+ {
+ return false;
+ }
+ if (Double.doubleToLongBits(beta) != Double.doubleToLongBits(other.beta))
+ {
+ return false;
+ }
+ if (Double.doubleToLongBits(betaSq) != Double.doubleToLongBits(other.betaSq))
+ {
+ return false;
+ }
+ if (bitsF != other.bitsF)
+ {
+ return false;
+ }
+ if (d != other.d)
+ {
+ return false;
+ }
+ if (d1 != other.d1)
+ {
+ return false;
+ }
+ if (d2 != other.d2)
+ {
+ return false;
+ }
+ if (d3 != other.d3)
+ {
+ return false;
+ }
+ if (hashAlg == null)
+ {
+ if (other.hashAlg != null)
+ {
+ return false;
+ }
+ }
+ else if (!hashAlg.getAlgorithmName().equals(other.hashAlg.getAlgorithmName()))
+ {
+ return false;
+ }
+ if (Double.doubleToLongBits(normBound) != Double.doubleToLongBits(other.normBound))
+ {
+ return false;
+ }
+ if (Double.doubleToLongBits(normBoundSq) != Double.doubleToLongBits(other.normBoundSq))
+ {
+ return false;
+ }
+ if (q != other.q)
+ {
+ return false;
+ }
+ if (signFailTolerance != other.signFailTolerance)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ public String toString()
+ {
+ DecimalFormat format = new DecimalFormat("0.00");
+
+ StringBuilder output = new StringBuilder("SignatureParameters(N=" + N + " q=" + q);
+
+ output.append(" B=" + B + " beta=" + format.format(beta) +
+ " normBound=" + format.format(normBound) +
+ " hashAlg=" + hashAlg + ")");
+ return output.toString();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningPrivateKeyParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningPrivateKeyParameters.java
new file mode 100644
index 00000000..bbbaaeef
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningPrivateKeyParameters.java
@@ -0,0 +1,385 @@
+package org.spongycastle.pqc.crypto.ntru;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.Polynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.ProductFormPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial;
+
+/**
+ * A NtruSign private key comprises one or more {@link NTRUSigningPrivateKeyParameters.Basis} of three polynomials each,
+ * except the zeroth basis for which <code>h</code> is undefined.
+ */
+public class NTRUSigningPrivateKeyParameters
+ extends AsymmetricKeyParameter
+{
+ private List<Basis> bases;
+ private NTRUSigningPublicKeyParameters publicKey;
+
+ /**
+ * Constructs a new private key from a byte array
+ *
+ * @param b an encoded private key
+ * @param params the NtruSign parameters to use
+ */
+ public NTRUSigningPrivateKeyParameters(byte[] b, NTRUSigningKeyGenerationParameters params)
+ throws IOException
+ {
+ this(new ByteArrayInputStream(b), params);
+ }
+
+ /**
+ * Constructs a new private key from an input stream
+ *
+ * @param is an input stream
+ * @param params the NtruSign parameters to use
+ */
+ public NTRUSigningPrivateKeyParameters(InputStream is, NTRUSigningKeyGenerationParameters params)
+ throws IOException
+ {
+ super(true);
+ bases = new ArrayList<Basis>();
+ for (int i = 0; i <= params.B; i++)
+ // include a public key h[i] in all bases except for the first one
+ {
+ add(new Basis(is, params, i != 0));
+ }
+ publicKey = new NTRUSigningPublicKeyParameters(is, params.getSigningParameters());
+ }
+
+ public NTRUSigningPrivateKeyParameters(List<Basis> bases, NTRUSigningPublicKeyParameters publicKey)
+ {
+ super(true);
+ this.bases = new ArrayList<Basis>(bases);
+ this.publicKey = publicKey;
+ }
+
+ /**
+ * Adds a basis to the key.
+ *
+ * @param b a NtruSign basis
+ */
+ private void add(Basis b)
+ {
+ bases.add(b);
+ }
+
+ /**
+ * Returns the <code>i</code>-th basis
+ *
+ * @param i the index
+ * @return the basis at index <code>i</code>
+ */
+ public Basis getBasis(int i)
+ {
+ return bases.get(i);
+ }
+
+ public NTRUSigningPublicKeyParameters getPublicKey()
+ {
+ return publicKey;
+ }
+
+ /**
+ * Converts the key to a byte array
+ *
+ * @return the encoded key
+ */
+ public byte[] getEncoded()
+ throws IOException
+ {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ for (int i = 0; i < bases.size(); i++)
+ {
+ // all bases except for the first one contain a public key
+ bases.get(i).encode(os, i != 0);
+ }
+
+ os.write(publicKey.getEncoded());
+
+ return os.toByteArray();
+ }
+
+ /**
+ * Writes the key to an output stream
+ *
+ * @param os an output stream
+ * @throws IOException
+ */
+ public void writeTo(OutputStream os)
+ throws IOException
+ {
+ os.write(getEncoded());
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((bases == null) ? 0 : bases.hashCode());
+ for (Basis basis : bases)
+ {
+ result += basis.hashCode();
+ }
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+ NTRUSigningPrivateKeyParameters other = (NTRUSigningPrivateKeyParameters)obj;
+ if (bases == null)
+ {
+ if (other.bases != null)
+ {
+ return false;
+ }
+ }
+ if (bases.size() != other.bases.size())
+ {
+ return false;
+ }
+ for (int i = 0; i < bases.size(); i++)
+ {
+ Basis basis1 = bases.get(i);
+ Basis basis2 = other.bases.get(i);
+ if (!basis1.f.equals(basis2.f))
+ {
+ return false;
+ }
+ if (!basis1.fPrime.equals(basis2.fPrime))
+ {
+ return false;
+ }
+ if (i != 0 && !basis1.h.equals(basis2.h)) // don't compare h for the 0th basis
+ {
+ return false;
+ }
+ if (!basis1.params.equals(basis2.params))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * A NtruSign basis. Contains three polynomials <code>f, f', h</code>.
+ */
+ public static class Basis
+ {
+ public Polynomial f;
+ public Polynomial fPrime;
+ public IntegerPolynomial h;
+ NTRUSigningKeyGenerationParameters params;
+
+ /**
+ * Constructs a new basis from polynomials <code>f, f', h</code>.
+ *
+ * @param f
+ * @param fPrime
+ * @param h
+ * @param params NtruSign parameters
+ */
+ protected Basis(Polynomial f, Polynomial fPrime, IntegerPolynomial h, NTRUSigningKeyGenerationParameters params)
+ {
+ this.f = f;
+ this.fPrime = fPrime;
+ this.h = h;
+ this.params = params;
+ }
+
+ /**
+ * Reads a basis from an input stream and constructs a new basis.
+ *
+ * @param is an input stream
+ * @param params NtruSign parameters
+ * @param include_h whether to read the polynomial <code>h</code> (<code>true</code>) or only <code>f</code> and <code>f'</code> (<code>false</code>)
+ */
+ Basis(InputStream is, NTRUSigningKeyGenerationParameters params, boolean include_h)
+ throws IOException
+ {
+ int N = params.N;
+ int q = params.q;
+ int d1 = params.d1;
+ int d2 = params.d2;
+ int d3 = params.d3;
+ boolean sparse = params.sparse;
+ this.params = params;
+
+ if (params.polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_PRODUCT)
+ {
+ f = ProductFormPolynomial.fromBinary(is, N, d1, d2, d3 + 1, d3);
+ }
+ else
+ {
+ IntegerPolynomial fInt = IntegerPolynomial.fromBinary3Tight(is, N);
+ f = sparse ? new SparseTernaryPolynomial(fInt) : new DenseTernaryPolynomial(fInt);
+ }
+
+ if (params.basisType == NTRUSigningKeyGenerationParameters.BASIS_TYPE_STANDARD)
+ {
+ IntegerPolynomial fPrimeInt = IntegerPolynomial.fromBinary(is, N, q);
+ for (int i = 0; i < fPrimeInt.coeffs.length; i++)
+ {
+ fPrimeInt.coeffs[i] -= q / 2;
+ }
+ fPrime = fPrimeInt;
+ }
+ else if (params.polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_PRODUCT)
+ {
+ fPrime = ProductFormPolynomial.fromBinary(is, N, d1, d2, d3 + 1, d3);
+ }
+ else
+ {
+ fPrime = IntegerPolynomial.fromBinary3Tight(is, N);
+ }
+
+ if (include_h)
+ {
+ h = IntegerPolynomial.fromBinary(is, N, q);
+ }
+ }
+
+ /**
+ * Writes the basis to an output stream
+ *
+ * @param os an output stream
+ * @param include_h whether to write the polynomial <code>h</code> (<code>true</code>) or only <code>f</code> and <code>f'</code> (<code>false</code>)
+ * @throws IOException
+ */
+ void encode(OutputStream os, boolean include_h)
+ throws IOException
+ {
+ int q = params.q;
+
+ os.write(getEncoded(f));
+ if (params.basisType == NTRUSigningKeyGenerationParameters.BASIS_TYPE_STANDARD)
+ {
+ IntegerPolynomial fPrimeInt = fPrime.toIntegerPolynomial();
+ for (int i = 0; i < fPrimeInt.coeffs.length; i++)
+ {
+ fPrimeInt.coeffs[i] += q / 2;
+ }
+ os.write(fPrimeInt.toBinary(q));
+ }
+ else
+ {
+ os.write(getEncoded(fPrime));
+ }
+ if (include_h)
+ {
+ os.write(h.toBinary(q));
+ }
+ }
+
+ private byte[] getEncoded(Polynomial p)
+ {
+ if (p instanceof ProductFormPolynomial)
+ {
+ return ((ProductFormPolynomial)p).toBinary();
+ }
+ else
+ {
+ return p.toIntegerPolynomial().toBinary3Tight();
+ }
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((f == null) ? 0 : f.hashCode());
+ result = prime * result + ((fPrime == null) ? 0 : fPrime.hashCode());
+ result = prime * result + ((h == null) ? 0 : h.hashCode());
+ result = prime * result + ((params == null) ? 0 : params.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof Basis))
+ {
+ return false;
+ }
+ Basis other = (Basis)obj;
+ if (f == null)
+ {
+ if (other.f != null)
+ {
+ return false;
+ }
+ }
+ else if (!f.equals(other.f))
+ {
+ return false;
+ }
+ if (fPrime == null)
+ {
+ if (other.fPrime != null)
+ {
+ return false;
+ }
+ }
+ else if (!fPrime.equals(other.fPrime))
+ {
+ return false;
+ }
+ if (h == null)
+ {
+ if (other.h != null)
+ {
+ return false;
+ }
+ }
+ else if (!h.equals(other.h))
+ {
+ return false;
+ }
+ if (params == null)
+ {
+ if (other.params != null)
+ {
+ return false;
+ }
+ }
+ else if (!params.equals(other.params))
+ {
+ return false;
+ }
+ return true;
+ }
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningPublicKeyParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningPublicKeyParameters.java
new file mode 100644
index 00000000..d7431b8b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningPublicKeyParameters.java
@@ -0,0 +1,132 @@
+package org.spongycastle.pqc.crypto.ntru;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
+
+/**
+ * A NtruSign public key is essentially a polynomial named <code>h</code>.
+ */
+public class NTRUSigningPublicKeyParameters
+ extends AsymmetricKeyParameter
+{
+ private NTRUSigningParameters params;
+ public IntegerPolynomial h;
+
+ /**
+ * Constructs a new public key from a polynomial
+ *
+ * @param h the polynomial <code>h</code> which determines the key
+ * @param params the NtruSign parameters to use
+ */
+ public NTRUSigningPublicKeyParameters(IntegerPolynomial h, NTRUSigningParameters params)
+ {
+ super(false);
+ this.h = h;
+ this.params = params;
+ }
+
+ /**
+ * Converts a byte array to a polynomial <code>h</code> and constructs a new public key
+ *
+ * @param b an encoded polynomial
+ * @param params the NtruSign parameters to use
+ */
+ public NTRUSigningPublicKeyParameters(byte[] b, NTRUSigningParameters params)
+ {
+ super(false);
+ h = IntegerPolynomial.fromBinary(b, params.N, params.q);
+ this.params = params;
+ }
+
+ /**
+ * Reads a polynomial <code>h</code> from an input stream and constructs a new public key
+ *
+ * @param is an input stream
+ * @param params the NtruSign parameters to use
+ */
+ public NTRUSigningPublicKeyParameters(InputStream is, NTRUSigningParameters params)
+ throws IOException
+ {
+ super(false);
+ h = IntegerPolynomial.fromBinary(is, params.N, params.q);
+ this.params = params;
+ }
+
+
+ /**
+ * Converts the key to a byte array
+ *
+ * @return the encoded key
+ */
+ public byte[] getEncoded()
+ {
+ return h.toBinary(params.q);
+ }
+
+ /**
+ * Writes the key to an output stream
+ *
+ * @param os an output stream
+ * @throws IOException
+ */
+ public void writeTo(OutputStream os)
+ throws IOException
+ {
+ os.write(getEncoded());
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((h == null) ? 0 : h.hashCode());
+ result = prime * result + ((params == null) ? 0 : params.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+ NTRUSigningPublicKeyParameters other = (NTRUSigningPublicKeyParameters)obj;
+ if (h == null)
+ {
+ if (other.h != null)
+ {
+ return false;
+ }
+ }
+ else if (!h.equals(other.h))
+ {
+ return false;
+ }
+ if (params == null)
+ {
+ if (other.params != null)
+ {
+ return false;
+ }
+ }
+ else if (!params.equals(other.params))
+ {
+ return false;
+ }
+ return true;
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/Layer.java b/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/Layer.java
new file mode 100644
index 00000000..0556531e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/Layer.java
@@ -0,0 +1,322 @@
+package org.spongycastle.pqc.crypto.rainbow;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.pqc.crypto.rainbow.util.GF2Field;
+import org.spongycastle.pqc.crypto.rainbow.util.RainbowUtil;
+import org.spongycastle.util.Arrays;
+
+
+/**
+ * This class represents a layer of the Rainbow Oil- and Vinegar Map. Each Layer
+ * consists of oi polynomials with their coefficients, generated at random.
+ * <p>
+ * To sign a document, we solve a LES (linear equation system) for each layer in
+ * order to find the oil variables of that layer and to be able to use the
+ * variables to compute the signature. This functionality is implemented in the
+ * RainbowSignature-class, by the aid of the private key.
+ * <p>
+ * Each layer is a part of the private key.
+ * <p>
+ * More information about the layer can be found in the paper of Jintai Ding,
+ * Dieter Schmidt: Rainbow, a New Multivariable Polynomial Signature Scheme.
+ * ACNS 2005: 164-175 (http://dx.doi.org/10.1007/11496137_12)
+ */
+public class Layer
+{
+ private int vi; // number of vinegars in this layer
+ private int viNext; // number of vinegars in next layer
+ private int oi; // number of oils in this layer
+
+ /*
+ * k : index of polynomial
+ *
+ * i,j : indices of oil and vinegar variables
+ */
+ private short[/* k */][/* i */][/* j */] coeff_alpha;
+ private short[/* k */][/* i */][/* j */] coeff_beta;
+ private short[/* k */][/* i */] coeff_gamma;
+ private short[/* k */] coeff_eta;
+
+ /**
+ * Constructor
+ *
+ * @param vi number of vinegar variables of this layer
+ * @param viNext number of vinegar variables of next layer. It's the same as
+ * (num of oils) + (num of vinegars) of this layer.
+ * @param coeffAlpha alpha-coefficients in the polynomials of this layer
+ * @param coeffBeta beta-coefficients in the polynomials of this layer
+ * @param coeffGamma gamma-coefficients in the polynomials of this layer
+ * @param coeffEta eta-coefficients in the polynomials of this layer
+ */
+ public Layer(byte vi, byte viNext, short[][][] coeffAlpha,
+ short[][][] coeffBeta, short[][] coeffGamma, short[] coeffEta)
+ {
+ this.vi = vi & 0xff;
+ this.viNext = viNext & 0xff;
+ this.oi = this.viNext - this.vi;
+
+ // the secret coefficients of all polynomials in this layer
+ this.coeff_alpha = coeffAlpha;
+ this.coeff_beta = coeffBeta;
+ this.coeff_gamma = coeffGamma;
+ this.coeff_eta = coeffEta;
+ }
+
+ /**
+ * This function generates the coefficients of all polynomials in this layer
+ * at random using random generator.
+ *
+ * @param sr the random generator which is to be used
+ */
+ public Layer(int vi, int viNext, SecureRandom sr)
+ {
+ this.vi = vi;
+ this.viNext = viNext;
+ this.oi = viNext - vi;
+
+ // the coefficients of all polynomials in this layer
+ this.coeff_alpha = new short[this.oi][this.oi][this.vi];
+ this.coeff_beta = new short[this.oi][this.vi][this.vi];
+ this.coeff_gamma = new short[this.oi][this.viNext];
+ this.coeff_eta = new short[this.oi];
+
+ int numOfPoly = this.oi; // number of polynomials per layer
+
+ // Alpha coeffs
+ for (int k = 0; k < numOfPoly; k++)
+ {
+ for (int i = 0; i < this.oi; i++)
+ {
+ for (int j = 0; j < this.vi; j++)
+ {
+ coeff_alpha[k][i][j] = (short)(sr.nextInt() & GF2Field.MASK);
+ }
+ }
+ }
+ // Beta coeffs
+ for (int k = 0; k < numOfPoly; k++)
+ {
+ for (int i = 0; i < this.vi; i++)
+ {
+ for (int j = 0; j < this.vi; j++)
+ {
+ coeff_beta[k][i][j] = (short)(sr.nextInt() & GF2Field.MASK);
+ }
+ }
+ }
+ // Gamma coeffs
+ for (int k = 0; k < numOfPoly; k++)
+ {
+ for (int i = 0; i < this.viNext; i++)
+ {
+ coeff_gamma[k][i] = (short)(sr.nextInt() & GF2Field.MASK);
+ }
+ }
+ // Eta
+ for (int k = 0; k < numOfPoly; k++)
+ {
+ coeff_eta[k] = (short)(sr.nextInt() & GF2Field.MASK);
+ }
+ }
+
+ /**
+ * This method plugs in the vinegar variables into the polynomials of this
+ * layer and computes the coefficients of the Oil-variables as well as the
+ * free coefficient in each polynomial.
+ * <p>
+ * It is needed for computing the Oil variables while signing.
+ *
+ * @param x vinegar variables of this layer that should be plugged into
+ * the polynomials.
+ * @return coeff the coefficients of Oil variables and the free coeff in the
+ * polynomials of this layer.
+ */
+ public short[][] plugInVinegars(short[] x)
+ {
+ // temporary variable needed for the multiplication
+ short tmpMult = 0;
+ // coeff: 1st index = which polynomial, 2nd index=which variable
+ short[][] coeff = new short[oi][oi + 1]; // gets returned
+ // free coefficient per polynomial
+ short[] sum = new short[oi];
+
+ /*
+ * evaluate the beta-part of the polynomials (it contains no oil
+ * variables)
+ */
+ for (int k = 0; k < oi; k++)
+ {
+ for (int i = 0; i < vi; i++)
+ {
+ for (int j = 0; j < vi; j++)
+ {
+ // tmp = beta * xi (plug in)
+ tmpMult = GF2Field.multElem(coeff_beta[k][i][j], x[i]);
+ // tmp = tmp * xj
+ tmpMult = GF2Field.multElem(tmpMult, x[j]);
+ // accumulate into the array for the free coefficients.
+ sum[k] = GF2Field.addElem(sum[k], tmpMult);
+ }
+ }
+ }
+
+ /* evaluate the alpha-part (it contains oils) */
+ for (int k = 0; k < oi; k++)
+ {
+ for (int i = 0; i < oi; i++)
+ {
+ for (int j = 0; j < vi; j++)
+ {
+ // alpha * xj (plug in)
+ tmpMult = GF2Field.multElem(coeff_alpha[k][i][j], x[j]);
+ // accumulate
+ coeff[k][i] = GF2Field.addElem(coeff[k][i], tmpMult);
+ }
+ }
+ }
+ /* evaluate the gama-part of the polynomial (containing no oils) */
+ for (int k = 0; k < oi; k++)
+ {
+ for (int i = 0; i < vi; i++)
+ {
+ // gamma * xi (plug in)
+ tmpMult = GF2Field.multElem(coeff_gamma[k][i], x[i]);
+ // accumulate in the array for the free coefficients (per
+ // polynomial).
+ sum[k] = GF2Field.addElem(sum[k], tmpMult);
+ }
+ }
+ /* evaluate the gama-part of the polynomial (but containing oils) */
+ for (int k = 0; k < oi; k++)
+ {
+ for (int i = vi; i < viNext; i++)
+ { // oils
+ // accumulate the coefficients of the oil variables (per
+ // polynomial).
+ coeff[k][i - vi] = GF2Field.addElem(coeff_gamma[k][i],
+ coeff[k][i - vi]);
+ }
+ }
+ /* evaluate the eta-part of the polynomial */
+ for (int k = 0; k < oi; k++)
+ {
+ // accumulate in the array for the free coefficients per polynomial.
+ sum[k] = GF2Field.addElem(sum[k], coeff_eta[k]);
+ }
+
+ /* put the free coefficients (sum) into the coeff-array as last column */
+ for (int k = 0; k < oi; k++)
+ {
+ coeff[k][oi] = sum[k];
+ }
+ return coeff;
+ }
+
+ /**
+ * Getter for the number of vinegar variables of this layer.
+ *
+ * @return the number of vinegar variables of this layer.
+ */
+ public int getVi()
+ {
+ return vi;
+ }
+
+ /**
+ * Getter for the number of vinegar variables of the next layer.
+ *
+ * @return the number of vinegar variables of the next layer.
+ */
+ public int getViNext()
+ {
+ return viNext;
+ }
+
+ /**
+ * Getter for the number of Oil variables of this layer.
+ *
+ * @return the number of oil variables of this layer.
+ */
+ public int getOi()
+ {
+ return oi;
+ }
+
+ /**
+ * Getter for the alpha-coefficients of the polynomials in this layer.
+ *
+ * @return the coefficients of alpha-terms of this layer.
+ */
+ public short[][][] getCoeffAlpha()
+ {
+ return coeff_alpha;
+ }
+
+ /**
+ * Getter for the beta-coefficients of the polynomials in this layer.
+ *
+ * @return the coefficients of beta-terms of this layer.
+ */
+
+ public short[][][] getCoeffBeta()
+ {
+ return coeff_beta;
+ }
+
+ /**
+ * Getter for the gamma-coefficients of the polynomials in this layer.
+ *
+ * @return the coefficients of gamma-terms of this layer
+ */
+ public short[][] getCoeffGamma()
+ {
+ return coeff_gamma;
+ }
+
+ /**
+ * Getter for the eta-coefficients of the polynomials in this layer.
+ *
+ * @return the coefficients eta of this layer
+ */
+ public short[] getCoeffEta()
+ {
+ return coeff_eta;
+ }
+
+ /**
+ * This function compares this Layer with another object.
+ *
+ * @param other the other object
+ * @return the result of the comparison
+ */
+ public boolean equals(Object other)
+ {
+ if (other == null || !(other instanceof Layer))
+ {
+ return false;
+ }
+ Layer otherLayer = (Layer)other;
+
+ return vi == otherLayer.getVi()
+ && viNext == otherLayer.getViNext()
+ && oi == otherLayer.getOi()
+ && RainbowUtil.equals(coeff_alpha, otherLayer.getCoeffAlpha())
+ && RainbowUtil.equals(coeff_beta, otherLayer.getCoeffBeta())
+ && RainbowUtil.equals(coeff_gamma, otherLayer.getCoeffGamma())
+ && RainbowUtil.equals(coeff_eta, otherLayer.getCoeffEta());
+ }
+
+ public int hashCode()
+ {
+ int hash = vi;
+ hash = hash * 37 + viNext;
+ hash = hash * 37 + oi;
+ hash = hash * 37 + Arrays.hashCode(coeff_alpha);
+ hash = hash * 37 + Arrays.hashCode(coeff_beta);
+ hash = hash * 37 + Arrays.hashCode(coeff_gamma);
+ hash = hash * 37 + Arrays.hashCode(coeff_eta);
+
+ return hash;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowKeyGenerationParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowKeyGenerationParameters.java
new file mode 100644
index 00000000..2cbc5b62
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowKeyGenerationParameters.java
@@ -0,0 +1,26 @@
+package org.spongycastle.pqc.crypto.rainbow;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.KeyGenerationParameters;
+
+public class RainbowKeyGenerationParameters
+ extends KeyGenerationParameters
+{
+ private RainbowParameters params;
+
+ public RainbowKeyGenerationParameters(
+ SecureRandom random,
+ RainbowParameters params)
+ {
+ // TODO: key size?
+ super(random, params.getVi()[params.getVi().length - 1] - params.getVi()[0]);
+ this.params = params;
+ }
+
+ public RainbowParameters getParameters()
+ {
+ return params;
+ }
+}
+
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowKeyPairGenerator.java b/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowKeyPairGenerator.java
new file mode 100644
index 00000000..1115d649
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowKeyPairGenerator.java
@@ -0,0 +1,413 @@
+package org.spongycastle.pqc.crypto.rainbow;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.pqc.crypto.rainbow.util.ComputeInField;
+import org.spongycastle.pqc.crypto.rainbow.util.GF2Field;
+
+/**
+ * This class implements AsymmetricCipherKeyPairGenerator. It is used
+ * as a generator for the private and public key of the Rainbow Signature
+ * Scheme.
+ * <p>
+ * Detailed information about the key generation is to be found in the paper of
+ * Jintai Ding, Dieter Schmidt: Rainbow, a New Multivariable Polynomial
+ * Signature Scheme. ACNS 2005: 164-175 (http://dx.doi.org/10.1007/11496137_12)
+ */
+public class RainbowKeyPairGenerator
+ implements AsymmetricCipherKeyPairGenerator
+{
+ private boolean initialized = false;
+ private SecureRandom sr;
+ private RainbowKeyGenerationParameters rainbowParams;
+
+ /* linear affine map L1: */
+ private short[][] A1; // matrix of the lin. affine map L1(n-v1 x n-v1 matrix)
+ private short[][] A1inv; // inverted A1
+ private short[] b1; // translation element of the lin.affine map L1
+
+ /* linear affine map L2: */
+ private short[][] A2; // matrix of the lin. affine map (n x n matrix)
+ private short[][] A2inv; // inverted A2
+ private short[] b2; // translation elemt of the lin.affine map L2
+
+ /* components of F: */
+ private int numOfLayers; // u (number of sets S)
+ private Layer layers[]; // layers of polynomials of F
+ private int[] vi; // set of vinegar vars per layer.
+
+ /* components of Public Key */
+ private short[][] pub_quadratic; // quadratic(mixed) coefficients
+ private short[][] pub_singular; // singular coefficients
+ private short[] pub_scalar; // scalars
+
+ // TODO
+
+ /**
+ * The standard constructor tries to generate the Rainbow algorithm identifier
+ * with the corresponding OID.
+ */
+ public RainbowKeyPairGenerator()
+ {
+ }
+
+
+ /**
+ * This function generates a Rainbow key pair.
+ *
+ * @return the generated key pair
+ */
+ public AsymmetricCipherKeyPair genKeyPair()
+ {
+ RainbowPrivateKeyParameters privKey;
+ RainbowPublicKeyParameters pubKey;
+
+ if (!initialized)
+ {
+ initializeDefault();
+ }
+
+ /* choose all coefficients at random */
+ keygen();
+
+ /* now marshall them to PrivateKey */
+ privKey = new RainbowPrivateKeyParameters(A1inv, b1, A2inv, b2, vi, layers);
+
+
+ /* marshall to PublicKey */
+ pubKey = new RainbowPublicKeyParameters(vi[vi.length - 1] - vi[0], pub_quadratic, pub_singular, pub_scalar);
+
+ return new AsymmetricCipherKeyPair(pubKey, privKey);
+ }
+
+ // TODO
+ public void initialize(
+ KeyGenerationParameters param)
+ {
+ this.rainbowParams = (RainbowKeyGenerationParameters)param;
+
+ // set source of randomness
+ this.sr = new SecureRandom();
+
+ // unmarshalling:
+ this.vi = this.rainbowParams.getParameters().getVi();
+ this.numOfLayers = this.rainbowParams.getParameters().getNumOfLayers();
+
+ this.initialized = true;
+ }
+
+ private void initializeDefault()
+ {
+ RainbowKeyGenerationParameters rbKGParams = new RainbowKeyGenerationParameters(new SecureRandom(), new RainbowParameters());
+ initialize(rbKGParams);
+ }
+
+ /**
+ * This function calls the functions for the random generation of the coefficients
+ * and the matrices needed for the private key and the method for computing the public key.
+ */
+ private void keygen()
+ {
+ generateL1();
+ generateL2();
+ generateF();
+ computePublicKey();
+ }
+
+ /**
+ * This function generates the invertible affine linear map L1 = A1*x + b1
+ * <p/>
+ * The translation part b1, is stored in a separate array. The inverse of
+ * the matrix-part of L1 A1inv is also computed here.
+ * <p/>
+ * This linear map hides the output of the map F. It is on k^(n-v1).
+ */
+ private void generateL1()
+ {
+
+ // dimension = n-v1 = vi[last] - vi[first]
+ int dim = vi[vi.length - 1] - vi[0];
+ this.A1 = new short[dim][dim];
+ this.A1inv = null;
+ ComputeInField c = new ComputeInField();
+
+ /* generation of A1 at random */
+ while (A1inv == null)
+ {
+ for (int i = 0; i < dim; i++)
+ {
+ for (int j = 0; j < dim; j++)
+ {
+ A1[i][j] = (short)(sr.nextInt() & GF2Field.MASK);
+ }
+ }
+ A1inv = c.inverse(A1);
+ }
+
+ /* generation of the translation vector at random */
+ b1 = new short[dim];
+ for (int i = 0; i < dim; i++)
+ {
+ b1[i] = (short)(sr.nextInt() & GF2Field.MASK);
+ }
+ }
+
+ /**
+ * This function generates the invertible affine linear map L2 = A2*x + b2
+ * <p/>
+ * The translation part b2, is stored in a separate array. The inverse of
+ * the matrix-part of L2 A2inv is also computed here.
+ * <p/>
+ * This linear map hides the output of the map F. It is on k^(n).
+ */
+ private void generateL2()
+ {
+
+ // dimension = n = vi[last]
+ int dim = vi[vi.length - 1];
+ this.A2 = new short[dim][dim];
+ this.A2inv = null;
+ ComputeInField c = new ComputeInField();
+
+ /* generation of A2 at random */
+ while (this.A2inv == null)
+ {
+ for (int i = 0; i < dim; i++)
+ {
+ for (int j = 0; j < dim; j++)
+ { // one col extra for b
+ A2[i][j] = (short)(sr.nextInt() & GF2Field.MASK);
+ }
+ }
+ this.A2inv = c.inverse(A2);
+ }
+ /* generation of the translation vector at random */
+ b2 = new short[dim];
+ for (int i = 0; i < dim; i++)
+ {
+ b2[i] = (short)(sr.nextInt() & GF2Field.MASK);
+ }
+
+ }
+
+ /**
+ * This function generates the private map F, which consists of u-1 layers.
+ * Each layer consists of oi polynomials where oi = vi[i+1]-vi[i].
+ * <p/>
+ * The methods for the generation of the coefficients of these polynomials
+ * are called here.
+ */
+ private void generateF()
+ {
+
+ this.layers = new Layer[this.numOfLayers];
+ for (int i = 0; i < this.numOfLayers; i++)
+ {
+ layers[i] = new Layer(this.vi[i], this.vi[i + 1], sr);
+ }
+ }
+
+ /**
+ * This function computes the public key from the private key.
+ * <p/>
+ * The composition of F with L2 is computed, followed by applying L1 to the
+ * composition's result. The singular and scalar values constitute to the
+ * public key as is, the quadratic terms are compacted in
+ * <tt>compactPublicKey()</tt>
+ */
+ private void computePublicKey()
+ {
+
+ ComputeInField c = new ComputeInField();
+ int rows = this.vi[this.vi.length - 1] - this.vi[0];
+ int vars = this.vi[this.vi.length - 1];
+ // Fpub
+ short[][][] coeff_quadratic_3dim = new short[rows][vars][vars];
+ this.pub_singular = new short[rows][vars];
+ this.pub_scalar = new short[rows];
+
+ // Coefficients of layers of Private Key F
+ short[][][] coeff_alpha;
+ short[][][] coeff_beta;
+ short[][] coeff_gamma;
+ short[] coeff_eta;
+
+ // Needed for counters;
+ int oils = 0;
+ int vins = 0;
+ int crnt_row = 0; // current row (polynomial)
+
+ short vect_tmp[] = new short[vars]; // vector tmp;
+ short sclr_tmp = 0;
+
+ // Composition of F and L2: Insert L2 = A2*x+b2 in F
+ for (int l = 0; l < this.layers.length; l++)
+ {
+ // get coefficients of current layer
+ coeff_alpha = this.layers[l].getCoeffAlpha();
+ coeff_beta = this.layers[l].getCoeffBeta();
+ coeff_gamma = this.layers[l].getCoeffGamma();
+ coeff_eta = this.layers[l].getCoeffEta();
+ oils = coeff_alpha[0].length;// this.layers[l].getOi();
+ vins = coeff_beta[0].length;// this.layers[l].getVi();
+ // compute polynomials of layer
+ for (int p = 0; p < oils; p++)
+ {
+ // multiply alphas
+ for (int x1 = 0; x1 < oils; x1++)
+ {
+ for (int x2 = 0; x2 < vins; x2++)
+ {
+ // multiply polynomial1 with polynomial2
+ vect_tmp = c.multVect(coeff_alpha[p][x1][x2],
+ this.A2[x1 + vins]);
+ coeff_quadratic_3dim[crnt_row + p] = c.addSquareMatrix(
+ coeff_quadratic_3dim[crnt_row + p], c
+ .multVects(vect_tmp, this.A2[x2]));
+ // mul poly1 with scalar2
+ vect_tmp = c.multVect(this.b2[x2], vect_tmp);
+ this.pub_singular[crnt_row + p] = c.addVect(vect_tmp,
+ this.pub_singular[crnt_row + p]);
+ // mul scalar1 with poly2
+ vect_tmp = c.multVect(coeff_alpha[p][x1][x2],
+ this.A2[x2]);
+ vect_tmp = c.multVect(b2[x1 + vins], vect_tmp);
+ this.pub_singular[crnt_row + p] = c.addVect(vect_tmp,
+ this.pub_singular[crnt_row + p]);
+ // mul scalar1 with scalar2
+ sclr_tmp = GF2Field.multElem(coeff_alpha[p][x1][x2],
+ this.b2[x1 + vins]);
+ this.pub_scalar[crnt_row + p] = GF2Field.addElem(
+ this.pub_scalar[crnt_row + p], GF2Field
+ .multElem(sclr_tmp, this.b2[x2]));
+ }
+ }
+ // multiply betas
+ for (int x1 = 0; x1 < vins; x1++)
+ {
+ for (int x2 = 0; x2 < vins; x2++)
+ {
+ // multiply polynomial1 with polynomial2
+ vect_tmp = c.multVect(coeff_beta[p][x1][x2],
+ this.A2[x1]);
+ coeff_quadratic_3dim[crnt_row + p] = c.addSquareMatrix(
+ coeff_quadratic_3dim[crnt_row + p], c
+ .multVects(vect_tmp, this.A2[x2]));
+ // mul poly1 with scalar2
+ vect_tmp = c.multVect(this.b2[x2], vect_tmp);
+ this.pub_singular[crnt_row + p] = c.addVect(vect_tmp,
+ this.pub_singular[crnt_row + p]);
+ // mul scalar1 with poly2
+ vect_tmp = c.multVect(coeff_beta[p][x1][x2],
+ this.A2[x2]);
+ vect_tmp = c.multVect(this.b2[x1], vect_tmp);
+ this.pub_singular[crnt_row + p] = c.addVect(vect_tmp,
+ this.pub_singular[crnt_row + p]);
+ // mul scalar1 with scalar2
+ sclr_tmp = GF2Field.multElem(coeff_beta[p][x1][x2],
+ this.b2[x1]);
+ this.pub_scalar[crnt_row + p] = GF2Field.addElem(
+ this.pub_scalar[crnt_row + p], GF2Field
+ .multElem(sclr_tmp, this.b2[x2]));
+ }
+ }
+ // multiply gammas
+ for (int n = 0; n < vins + oils; n++)
+ {
+ // mul poly with scalar
+ vect_tmp = c.multVect(coeff_gamma[p][n], this.A2[n]);
+ this.pub_singular[crnt_row + p] = c.addVect(vect_tmp,
+ this.pub_singular[crnt_row + p]);
+ // mul scalar with scalar
+ this.pub_scalar[crnt_row + p] = GF2Field.addElem(
+ this.pub_scalar[crnt_row + p], GF2Field.multElem(
+ coeff_gamma[p][n], this.b2[n]));
+ }
+ // add eta
+ this.pub_scalar[crnt_row + p] = GF2Field.addElem(
+ this.pub_scalar[crnt_row + p], coeff_eta[p]);
+ }
+ crnt_row = crnt_row + oils;
+ }
+
+ // Apply L1 = A1*x+b1 to composition of F and L2
+ {
+ // temporary coefficient arrays
+ short[][][] tmp_c_quad = new short[rows][vars][vars];
+ short[][] tmp_c_sing = new short[rows][vars];
+ short[] tmp_c_scal = new short[rows];
+ for (int r = 0; r < rows; r++)
+ {
+ for (int q = 0; q < A1.length; q++)
+ {
+ tmp_c_quad[r] = c.addSquareMatrix(tmp_c_quad[r], c
+ .multMatrix(A1[r][q], coeff_quadratic_3dim[q]));
+ tmp_c_sing[r] = c.addVect(tmp_c_sing[r], c.multVect(
+ A1[r][q], this.pub_singular[q]));
+ tmp_c_scal[r] = GF2Field.addElem(tmp_c_scal[r], GF2Field
+ .multElem(A1[r][q], this.pub_scalar[q]));
+ }
+ tmp_c_scal[r] = GF2Field.addElem(tmp_c_scal[r], b1[r]);
+ }
+ // set public key
+ coeff_quadratic_3dim = tmp_c_quad;
+ this.pub_singular = tmp_c_sing;
+ this.pub_scalar = tmp_c_scal;
+ }
+ compactPublicKey(coeff_quadratic_3dim);
+ }
+
+ /**
+ * The quadratic (or mixed) terms of the public key are compacted from a n x
+ * n matrix per polynomial to an upper diagonal matrix stored in one integer
+ * array of n (n + 1) / 2 elements per polynomial. The ordering of elements
+ * is lexicographic and the result is updating <tt>this.pub_quadratic</tt>,
+ * which stores the quadratic elements of the public key.
+ *
+ * @param coeff_quadratic_to_compact 3-dimensional array containing a n x n Matrix for each of the
+ * n - v1 polynomials
+ */
+ private void compactPublicKey(short[][][] coeff_quadratic_to_compact)
+ {
+ int polynomials = coeff_quadratic_to_compact.length;
+ int n = coeff_quadratic_to_compact[0].length;
+ int entries = n * (n + 1) / 2;// the small gauss
+ this.pub_quadratic = new short[polynomials][entries];
+ int offset = 0;
+
+ for (int p = 0; p < polynomials; p++)
+ {
+ offset = 0;
+ for (int x = 0; x < n; x++)
+ {
+ for (int y = x; y < n; y++)
+ {
+ if (y == x)
+ {
+ this.pub_quadratic[p][offset] = coeff_quadratic_to_compact[p][x][y];
+ }
+ else
+ {
+ this.pub_quadratic[p][offset] = GF2Field.addElem(
+ coeff_quadratic_to_compact[p][x][y],
+ coeff_quadratic_to_compact[p][y][x]);
+ }
+ offset++;
+ }
+ }
+ }
+ }
+
+ public void init(KeyGenerationParameters param)
+ {
+ this.initialize(param);
+ }
+
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+ return genKeyPair();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowKeyParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowKeyParameters.java
new file mode 100644
index 00000000..075afda4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowKeyParameters.java
@@ -0,0 +1,25 @@
+package org.spongycastle.pqc.crypto.rainbow;
+
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+
+public class RainbowKeyParameters
+ extends AsymmetricKeyParameter
+{
+ private int docLength;
+
+ public RainbowKeyParameters(
+ boolean isPrivate,
+ int docLength)
+ {
+ super(isPrivate);
+ this.docLength = docLength;
+ }
+
+ /**
+ * @return the docLength
+ */
+ public int getDocLength()
+ {
+ return this.docLength;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowParameters.java
new file mode 100644
index 00000000..edc0d023
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowParameters.java
@@ -0,0 +1,111 @@
+package org.spongycastle.pqc.crypto.rainbow;
+
+import org.spongycastle.crypto.CipherParameters;
+
+public class RainbowParameters
+ implements CipherParameters
+{
+
+ /**
+ * DEFAULT PARAMS
+ */
+ /*
+ * Vi = vinegars per layer whereas n is vu (vu = 33 = n) such that
+ *
+ * v1 = 6; o1 = 12-6 = 6
+ *
+ * v2 = 12; o2 = 17-12 = 5
+ *
+ * v3 = 17; o3 = 22-17 = 5
+ *
+ * v4 = 22; o4 = 33-22 = 11
+ *
+ * v5 = 33; (o5 = 0)
+ */
+ private final int[] DEFAULT_VI = {6, 12, 17, 22, 33};
+
+ private int[] vi;// set of vinegar vars per layer.
+
+ /**
+ * Default Constructor The elements of the array containing the number of
+ * Vinegar variables in each layer are set to the default values here.
+ */
+ public RainbowParameters()
+ {
+ this.vi = this.DEFAULT_VI;
+ }
+
+ /**
+ * Constructor with parameters
+ *
+ * @param vi The elements of the array containing the number of Vinegar
+ * variables per layer are set to the values of the input array.
+ */
+ public RainbowParameters(int[] vi)
+ {
+ this.vi = vi;
+ try
+ {
+ checkParams();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ private void checkParams()
+ throws Exception
+ {
+ if (vi == null)
+ {
+ throw new Exception("no layers defined.");
+ }
+ if (vi.length > 1)
+ {
+ for (int i = 0; i < vi.length - 1; i++)
+ {
+ if (vi[i] >= vi[i + 1])
+ {
+ throw new Exception(
+ "v[i] has to be smaller than v[i+1]");
+ }
+ }
+ }
+ else
+ {
+ throw new Exception(
+ "Rainbow needs at least 1 layer, such that v1 < v2.");
+ }
+ }
+
+ /**
+ * Getter for the number of layers
+ *
+ * @return the number of layers
+ */
+ public int getNumOfLayers()
+ {
+ return this.vi.length - 1;
+ }
+
+ /**
+ * Getter for the number of all the polynomials in Rainbow
+ *
+ * @return the number of the polynomials
+ */
+ public int getDocLength()
+ {
+ return vi[vi.length - 1] - vi[0];
+ }
+
+ /**
+ * Getter for the array containing the number of Vinegar-variables per layer
+ *
+ * @return the numbers of vinegars per layer
+ */
+ public int[] getVi()
+ {
+ return this.vi;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowPrivateKeyParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowPrivateKeyParameters.java
new file mode 100644
index 00000000..5d501a53
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowPrivateKeyParameters.java
@@ -0,0 +1,117 @@
+package org.spongycastle.pqc.crypto.rainbow;
+
+public class RainbowPrivateKeyParameters
+ extends RainbowKeyParameters
+{
+ /**
+ * Constructor
+ *
+ * @param A1inv the inverse of A1(the matrix part of the affine linear map L1)
+ * (n-v1 x n-v1 matrix)
+ * @param b1 translation vector, part of the linear affine map L1
+ * @param A2inv the inverse of A2(the matrix part of the affine linear map L2)
+ * (n x n matrix)
+ * @param b2 translation vector, part of the linear affine map L2
+ * @param vi the number of Vinegar-variables per layer
+ * @param layers the polynomials with their coefficients of private map F
+ */
+ public RainbowPrivateKeyParameters(short[][] A1inv, short[] b1,
+ short[][] A2inv, short[] b2, int[] vi, Layer[] layers)
+ {
+ super(true, vi[vi.length - 1] - vi[0]);
+
+ this.A1inv = A1inv;
+ this.b1 = b1;
+ this.A2inv = A2inv;
+ this.b2 = b2;
+ this.vi = vi;
+ this.layers = layers;
+ }
+
+ /*
+ * invertible affine linear map L1
+ */
+ // the inverse of A1, (n-v1 x n-v1 matrix)
+ private short[][] A1inv;
+
+ // translation vector of L1
+ private short[] b1;
+
+ /*
+ * invertible affine linear map L2
+ */
+ // the inverse of A2, (n x n matrix)
+ private short[][] A2inv;
+
+ // translation vector of L2
+ private short[] b2;
+
+ /*
+ * components of F
+ */
+ // the number of Vinegar-variables per layer.
+ private int[] vi;
+
+ // contains the polynomials with their coefficients of private map F
+ private Layer[] layers;
+
+ /**
+ * Getter for the translation part of the private quadratic map L1.
+ *
+ * @return b1 the translation part of L1
+ */
+ public short[] getB1()
+ {
+ return this.b1;
+ }
+
+ /**
+ * Getter for the inverse matrix of A1.
+ *
+ * @return the A1inv inverse
+ */
+ public short[][] getInvA1()
+ {
+ return this.A1inv;
+ }
+
+ /**
+ * Getter for the translation part of the private quadratic map L2.
+ *
+ * @return b2 the translation part of L2
+ */
+ public short[] getB2()
+ {
+ return this.b2;
+ }
+
+ /**
+ * Getter for the inverse matrix of A2
+ *
+ * @return the A2inv
+ */
+ public short[][] getInvA2()
+ {
+ return this.A2inv;
+ }
+
+ /**
+ * Returns the layers contained in the private key
+ *
+ * @return layers
+ */
+ public Layer[] getLayers()
+ {
+ return this.layers;
+ }
+
+ /**
+ * /** Returns the array of vi-s
+ *
+ * @return the vi
+ */
+ public int[] getVi()
+ {
+ return vi;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowPublicKeyParameters.java b/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowPublicKeyParameters.java
new file mode 100644
index 00000000..3a5314e1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowPublicKeyParameters.java
@@ -0,0 +1,53 @@
+package org.spongycastle.pqc.crypto.rainbow;
+
+public class RainbowPublicKeyParameters
+ extends RainbowKeyParameters
+{
+ private short[][] coeffquadratic;
+ private short[][] coeffsingular;
+ private short[] coeffscalar;
+
+ /**
+ * Constructor
+ *
+ * @param docLength
+ * @param coeffQuadratic
+ * @param coeffSingular
+ * @param coeffScalar
+ */
+ public RainbowPublicKeyParameters(int docLength,
+ short[][] coeffQuadratic, short[][] coeffSingular,
+ short[] coeffScalar)
+ {
+ super(false, docLength);
+
+ this.coeffquadratic = coeffQuadratic;
+ this.coeffsingular = coeffSingular;
+ this.coeffscalar = coeffScalar;
+
+ }
+
+ /**
+ * @return the coeffquadratic
+ */
+ public short[][] getCoeffQuadratic()
+ {
+ return coeffquadratic;
+ }
+
+ /**
+ * @return the coeffsingular
+ */
+ public short[][] getCoeffSingular()
+ {
+ return coeffsingular;
+ }
+
+ /**
+ * @return the coeffscalar
+ */
+ public short[] getCoeffScalar()
+ {
+ return coeffscalar;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowSigner.java b/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowSigner.java
new file mode 100644
index 00000000..9033b37e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowSigner.java
@@ -0,0 +1,301 @@
+package org.spongycastle.pqc.crypto.rainbow;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.pqc.crypto.MessageSigner;
+import org.spongycastle.pqc.crypto.rainbow.util.ComputeInField;
+import org.spongycastle.pqc.crypto.rainbow.util.GF2Field;
+
+/**
+ * It implements the sign and verify functions for the Rainbow Signature Scheme.
+ * Here the message, which has to be signed, is updated. The use of
+ * different hash functions is possible.
+ * <p>
+ * Detailed information about the signature and the verify-method is to be found
+ * in the paper of Jintai Ding, Dieter Schmidt: Rainbow, a New Multivariable
+ * Polynomial Signature Scheme. ACNS 2005: 164-175
+ * (http://dx.doi.org/10.1007/11496137_12)
+ */
+public class RainbowSigner
+ implements MessageSigner
+{
+ // Source of randomness
+ private SecureRandom random;
+
+ // The length of a document that can be signed with the privKey
+ int signableDocumentLength;
+
+ // Container for the oil and vinegar variables of all the layers
+ private short[] x;
+
+ private ComputeInField cf = new ComputeInField();
+
+ RainbowKeyParameters key;
+
+ public void init(boolean forSigning,
+ CipherParameters param)
+ {
+ if (forSigning)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.random = rParam.getRandom();
+ this.key = (RainbowPrivateKeyParameters)rParam.getParameters();
+
+ }
+ else
+ {
+
+ this.random = new SecureRandom();
+ this.key = (RainbowPrivateKeyParameters)param;
+ }
+ }
+ else
+ {
+ this.key = (RainbowPublicKeyParameters)param;
+ }
+
+ this.signableDocumentLength = this.key.getDocLength();
+ }
+
+
+ /**
+ * initial operations before solving the Linear equation system.
+ *
+ * @param layer the current layer for which a LES is to be solved.
+ * @param msg the message that should be signed.
+ * @return Y_ the modified document needed for solving LES, (Y_ =
+ * A1^{-1}*(Y-b1)) linear map L1 = A1 x + b1.
+ */
+ private short[] initSign(Layer[] layer, short[] msg)
+ {
+
+ /* preparation: Modifies the document with the inverse of L1 */
+ // tmp = Y - b1:
+ short[] tmpVec = new short[msg.length];
+
+ tmpVec = cf.addVect(((RainbowPrivateKeyParameters)this.key).getB1(), msg);
+
+ // Y_ = A1^{-1} * (Y - b1) :
+ short[] Y_ = cf.multiplyMatrix(((RainbowPrivateKeyParameters)this.key).getInvA1(), tmpVec);
+
+ /* generates the vinegar vars of the first layer at random */
+ for (int i = 0; i < layer[0].getVi(); i++)
+ {
+ x[i] = (short)random.nextInt();
+ x[i] = (short)(x[i] & GF2Field.MASK);
+ }
+
+ return Y_;
+ }
+
+ /**
+ * This function signs the message that has been updated, making use of the
+ * private key.
+ * <p>
+ * For computing the signature, L1 and L2 are needed, as well as LES should
+ * be solved for each layer in order to find the Oil-variables in the layer.
+ * <p>
+ * The Vinegar-variables of the first layer are random generated.
+ *
+ * @param message the message
+ * @return the signature of the message.
+ */
+ public byte[] generateSignature(byte[] message)
+ {
+ Layer[] layer = ((RainbowPrivateKeyParameters)this.key).getLayers();
+ int numberOfLayers = layer.length;
+
+ x = new short[((RainbowPrivateKeyParameters)this.key).getInvA2().length]; // all variables
+
+ short[] Y_; // modified document
+ short[] y_i; // part of Y_ each polynomial
+ int counter; // index of the current part of the doc
+
+ short[] solVec; // the solution of LES pro layer
+ short[] tmpVec;
+
+ // the signature as an array of shorts:
+ short[] signature;
+ // the signature as a byte-array:
+ byte[] S = new byte[layer[numberOfLayers - 1].getViNext()];
+
+ short[] msgHashVals = makeMessageRepresentative(message);
+
+ // shows if an exception is caught
+ boolean ok;
+ do
+ {
+ ok = true;
+ counter = 0;
+ try
+ {
+ Y_ = initSign(layer, msgHashVals);
+
+ for (int i = 0; i < numberOfLayers; i++)
+ {
+
+ y_i = new short[layer[i].getOi()];
+ solVec = new short[layer[i].getOi()]; // solution of LES
+
+ /* copy oi elements of Y_ into y_i */
+ for (int k = 0; k < layer[i].getOi(); k++)
+ {
+ y_i[k] = Y_[counter];
+ counter++; // current index of Y_
+ }
+
+ /*
+ * plug in the vars of the previous layer in order to get
+ * the vars of the current layer
+ */
+ solVec = cf.solveEquation(layer[i].plugInVinegars(x), y_i);
+
+ if (solVec == null)
+ { // LES is not solveable
+ throw new Exception("LES is not solveable!");
+ }
+
+ /* copy the new vars into the x-array */
+ for (int j = 0; j < solVec.length; j++)
+ {
+ x[layer[i].getVi() + j] = solVec[j];
+ }
+ }
+
+ /* apply the inverse of L2: (signature = A2^{-1}*(b2+x)) */
+ tmpVec = cf.addVect(((RainbowPrivateKeyParameters)this.key).getB2(), x);
+ signature = cf.multiplyMatrix(((RainbowPrivateKeyParameters)this.key).getInvA2(), tmpVec);
+
+ /* cast signature from short[] to byte[] */
+ for (int i = 0; i < S.length; i++)
+ {
+ S[i] = ((byte)signature[i]);
+ }
+ }
+ catch (Exception se)
+ {
+ // if one of the LESs was not solveable - sign again
+ ok = false;
+ }
+ }
+ while (!ok);
+ /* return the signature in bytes */
+ return S;
+ }
+
+ /**
+ * This function verifies the signature of the message that has been
+ * updated, with the aid of the public key.
+ *
+ * @param message the message
+ * @param signature the signature of the message
+ * @return true if the signature has been verified, false otherwise.
+ */
+ public boolean verifySignature(byte[] message, byte[] signature)
+ {
+ short[] sigInt = new short[signature.length];
+ short tmp;
+
+ for (int i = 0; i < signature.length; i++)
+ {
+ tmp = (short)signature[i];
+ tmp &= (short)0xff;
+ sigInt[i] = tmp;
+ }
+
+ short[] msgHashVal = makeMessageRepresentative(message);
+
+ // verify
+ short[] verificationResult = verifySignatureIntern(sigInt);
+
+ // compare
+ boolean verified = true;
+ if (msgHashVal.length != verificationResult.length)
+ {
+ return false;
+ }
+ for (int i = 0; i < msgHashVal.length; i++)
+ {
+ verified = verified && msgHashVal[i] == verificationResult[i];
+ }
+
+ return verified;
+ }
+
+ /**
+ * Signature verification using public key
+ *
+ * @param signature vector of dimension n
+ * @return document hash of length n - v1
+ */
+ private short[] verifySignatureIntern(short[] signature)
+ {
+
+ short[][] coeff_quadratic = ((RainbowPublicKeyParameters)this.key).getCoeffQuadratic();
+ short[][] coeff_singular = ((RainbowPublicKeyParameters)this.key).getCoeffSingular();
+ short[] coeff_scalar = ((RainbowPublicKeyParameters)this.key).getCoeffScalar();
+
+ short[] rslt = new short[coeff_quadratic.length];// n - v1
+ int n = coeff_singular[0].length;
+ int offset = 0; // array position
+ short tmp = 0; // for scalar
+
+ for (int p = 0; p < coeff_quadratic.length; p++)
+ { // no of polynomials
+ offset = 0;
+ for (int x = 0; x < n; x++)
+ {
+ // calculate quadratic terms
+ for (int y = x; y < n; y++)
+ {
+ tmp = GF2Field.multElem(coeff_quadratic[p][offset],
+ GF2Field.multElem(signature[x], signature[y]));
+ rslt[p] = GF2Field.addElem(rslt[p], tmp);
+ offset++;
+ }
+ // calculate singular terms
+ tmp = GF2Field.multElem(coeff_singular[p][x], signature[x]);
+ rslt[p] = GF2Field.addElem(rslt[p], tmp);
+ }
+ // add scalar
+ rslt[p] = GF2Field.addElem(rslt[p], coeff_scalar[p]);
+ }
+
+ return rslt;
+ }
+
+ /**
+ * This function creates the representative of the message which gets signed
+ * or verified.
+ *
+ * @param message the message
+ * @return message representative
+ */
+ private short[] makeMessageRepresentative(byte[] message)
+ {
+ // the message representative
+ short[] output = new short[this.signableDocumentLength];
+
+ int h = 0;
+ int i = 0;
+ do
+ {
+ if (i >= message.length)
+ {
+ break;
+ }
+ output[i] = (short)message[h];
+ output[i] &= (short)0xff;
+ h++;
+ i++;
+ }
+ while (i < output.length);
+
+ return output;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/util/ComputeInField.java b/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/util/ComputeInField.java
new file mode 100644
index 00000000..1e4b6c0f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/util/ComputeInField.java
@@ -0,0 +1,490 @@
+package org.spongycastle.pqc.crypto.rainbow.util;
+
+/**
+ * This class offers different operations on matrices in field GF2^8.
+ * <p>
+ * Implemented are functions:
+ * - finding inverse of a matrix
+ * - solving linear equation systems using the Gauss-Elimination method
+ * - basic operations like matrix multiplication, addition and so on.
+ */
+
+public class ComputeInField
+{
+
+ private short[][] A; // used by solveEquation and inverse
+ short[] x;
+
+ /**
+ * Constructor with no parameters
+ */
+ public ComputeInField()
+ {
+ }
+
+
+ /**
+ * This function finds a solution of the equation Bx = b.
+ * Exception is thrown if the linear equation system has no solution
+ *
+ * @param B this matrix is the left part of the
+ * equation (B in the equation above)
+ * @param b the right part of the equation
+ * (b in the equation above)
+ * @return x the solution of the equation if it is solvable
+ * null otherwise
+ * @throws RuntimeException if LES is not solvable
+ */
+ public short[] solveEquation(short[][] B, short[] b)
+ {
+ try
+ {
+
+ if (B.length != b.length)
+ {
+ throw new RuntimeException(
+ "The equation system is not solvable");
+ }
+
+ /** initialize **/
+ // this matrix stores B and b from the equation B*x = b
+ // b is stored as the last column.
+ // B contains one column more than rows.
+ // In this column we store a free coefficient that should be later subtracted from b
+ A = new short[B.length][B.length + 1];
+ // stores the solution of the LES
+ x = new short[B.length];
+
+ /** copy B into the global matrix A **/
+ for (int i = 0; i < B.length; i++)
+ { // rows
+ for (int j = 0; j < B[0].length; j++)
+ { // cols
+ A[i][j] = B[i][j];
+ }
+ }
+
+ /** copy the vector b into the global A **/
+ //the free coefficient, stored in the last column of A( A[i][b.length]
+ // is to be subtracted from b
+ for (int i = 0; i < b.length; i++)
+ {
+ A[i][b.length] = GF2Field.addElem(b[i], A[i][b.length]);
+ }
+
+ /** call the methods for gauss elimination and backward substitution **/
+ computeZerosUnder(false); // obtain zeros under the diagonal
+ substitute();
+
+ return x;
+
+ }
+ catch (RuntimeException rte)
+ {
+ return null; // the LES is not solvable!
+ }
+ }
+
+ /**
+ * This function computes the inverse of a given matrix using the Gauss-
+ * Elimination method.
+ * <p>
+ * An exception is thrown if the matrix has no inverse
+ *
+ * @param coef the matrix which inverse matrix is needed
+ * @return inverse matrix of the input matrix.
+ * If the matrix is singular, null is returned.
+ * @throws RuntimeException if the given matrix is not invertible
+ */
+ public short[][] inverse(short[][] coef)
+ {
+ try
+ {
+ /** Initialization: **/
+ short factor;
+ short[][] inverse;
+ A = new short[coef.length][2 * coef.length];
+ if (coef.length != coef[0].length)
+ {
+ throw new RuntimeException(
+ "The matrix is not invertible. Please choose another one!");
+ }
+
+ /** prepare: Copy coef and the identity matrix into the global A. **/
+ for (int i = 0; i < coef.length; i++)
+ {
+ for (int j = 0; j < coef.length; j++)
+ {
+ //copy the input matrix coef into A
+ A[i][j] = coef[i][j];
+ }
+ // copy the identity matrix into A.
+ for (int j = coef.length; j < 2 * coef.length; j++)
+ {
+ A[i][j] = 0;
+ }
+ A[i][i + A.length] = 1;
+ }
+
+ /** Elimination operations to get the identity matrix from the left side of A. **/
+ // modify A to get 0s under the diagonal.
+ computeZerosUnder(true);
+
+ // modify A to get only 1s on the diagonal: A[i][j] =A[i][j]/A[i][i].
+ for (int i = 0; i < A.length; i++)
+ {
+ factor = GF2Field.invElem(A[i][i]);
+ for (int j = i; j < 2 * A.length; j++)
+ {
+ A[i][j] = GF2Field.multElem(A[i][j], factor);
+ }
+ }
+
+ //modify A to get only 0s above the diagonal.
+ computeZerosAbove();
+
+ // copy the result (the second half of A) in the matrix inverse.
+ inverse = new short[A.length][A.length];
+ for (int i = 0; i < A.length; i++)
+ {
+ for (int j = A.length; j < 2 * A.length; j++)
+ {
+ inverse[i][j - A.length] = A[i][j];
+ }
+ }
+ return inverse;
+
+ }
+ catch (RuntimeException rte)
+ {
+ // The matrix is not invertible! A new one should be generated!
+ return null;
+ }
+ }
+
+ /**
+ * Elimination under the diagonal.
+ * This function changes a matrix so that it contains only zeros under the
+ * diagonal(Ai,i) using only Gauss-Elimination operations.
+ * <p/>
+ * It is used in solveEquaton as well as in the function for
+ * finding an inverse of a matrix: {@link}inverse. Both of them use the
+ * Gauss-Elimination Method.
+ * <p/>
+ * The result is stored in the global matrix A
+ *
+ * @param usedForInverse This parameter shows if the function is used by the
+ * solveEquation-function or by the inverse-function and according
+ * to this creates matrices of different sizes.
+ * @throws RuntimeException in case a multiplicative inverse of 0 is needed
+ */
+ private void computeZerosUnder(boolean usedForInverse)
+ throws RuntimeException
+ {
+
+ //the number of columns in the global A where the tmp results are stored
+ int length;
+ short tmp = 0;
+
+ //the function is used in inverse() - A should have 2 times more columns than rows
+ if (usedForInverse)
+ {
+ length = 2 * A.length;
+ }
+ //the function is used in solveEquation - A has 1 column more than rows
+ else
+ {
+ length = A.length + 1;
+ }
+
+ //elimination operations to modify A so that that it contains only 0s under the diagonal
+ for (int k = 0; k < A.length - 1; k++)
+ { // the fixed row
+ for (int i = k + 1; i < A.length; i++)
+ { // rows
+ short factor1 = A[i][k];
+ short factor2 = GF2Field.invElem(A[k][k]);
+
+ //The element which multiplicative inverse is needed, is 0
+ //in this case is the input matrix not invertible
+ if (factor2 == 0)
+ {
+ throw new RuntimeException("Matrix not invertible! We have to choose another one!");
+ }
+
+ for (int j = k; j < length; j++)
+ {// columns
+ // tmp=A[k,j] / A[k,k]
+ tmp = GF2Field.multElem(A[k][j], factor2);
+ // tmp = A[i,k] * A[k,j] / A[k,k]
+ tmp = GF2Field.multElem(factor1, tmp);
+ // A[i,j]=A[i,j]-A[i,k]/A[k,k]*A[k,j];
+ A[i][j] = GF2Field.addElem(A[i][j], tmp);
+ }
+ }
+ }
+ }
+
+ /**
+ * Elimination above the diagonal.
+ * This function changes a matrix so that it contains only zeros above the
+ * diagonal(Ai,i) using only Gauss-Elimination operations.
+ * <p/>
+ * It is used in the inverse-function
+ * The result is stored in the global matrix A
+ *
+ * @throws RuntimeException in case a multiplicative inverse of 0 is needed
+ */
+ private void computeZerosAbove()
+ throws RuntimeException
+ {
+ short tmp = 0;
+ for (int k = A.length - 1; k > 0; k--)
+ { // the fixed row
+ for (int i = k - 1; i >= 0; i--)
+ { // rows
+ short factor1 = A[i][k];
+ short factor2 = GF2Field.invElem(A[k][k]);
+ if (factor2 == 0)
+ {
+ throw new RuntimeException("The matrix is not invertible");
+ }
+ for (int j = k; j < 2 * A.length; j++)
+ { // columns
+ // tmp = A[k,j] / A[k,k]
+ tmp = GF2Field.multElem(A[k][j], factor2);
+ // tmp = A[i,k] * A[k,j] / A[k,k]
+ tmp = GF2Field.multElem(factor1, tmp);
+ // A[i,j] = A[i,j] - A[i,k] / A[k,k] * A[k,j];
+ A[i][j] = GF2Field.addElem(A[i][j], tmp);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * This function uses backward substitution to find x
+ * of the linear equation system (LES) B*x = b,
+ * where A a triangle-matrix is (contains only zeros under the diagonal)
+ * and b is a vector
+ * <p/>
+ * If the multiplicative inverse of 0 is needed, an exception is thrown.
+ * In this case is the LES not solvable
+ *
+ * @throws RuntimeException in case a multiplicative inverse of 0 is needed
+ */
+ private void substitute()
+ throws RuntimeException
+ {
+
+ // for the temporary results of the operations in field
+ short tmp, temp;
+
+ temp = GF2Field.invElem(A[A.length - 1][A.length - 1]);
+ if (temp == 0)
+ {
+ throw new RuntimeException("The equation system is not solvable");
+ }
+
+ /** backward substitution **/
+ x[A.length - 1] = GF2Field.multElem(A[A.length - 1][A.length], temp);
+ for (int i = A.length - 2; i >= 0; i--)
+ {
+ tmp = A[i][A.length];
+ for (int j = A.length - 1; j > i; j--)
+ {
+ temp = GF2Field.multElem(A[i][j], x[j]);
+ tmp = GF2Field.addElem(tmp, temp);
+ }
+
+ temp = GF2Field.invElem(A[i][i]);
+ if (temp == 0)
+ {
+ throw new RuntimeException("Not solvable equation system");
+ }
+ x[i] = GF2Field.multElem(tmp, temp);
+ }
+ }
+
+
+ /**
+ * This function multiplies two given matrices.
+ * If the given matrices cannot be multiplied due
+ * to different sizes, an exception is thrown.
+ *
+ * @param M1 -the 1st matrix
+ * @param M2 -the 2nd matrix
+ * @return A = M1*M2
+ * @throws RuntimeException in case the given matrices cannot be multiplied
+ * due to different dimensions.
+ */
+ public short[][] multiplyMatrix(short[][] M1, short[][] M2)
+ throws RuntimeException
+ {
+
+ if (M1[0].length != M2.length)
+ {
+ throw new RuntimeException("Multiplication is not possible!");
+ }
+ short tmp = 0;
+ A = new short[M1.length][M2[0].length];
+ for (int i = 0; i < M1.length; i++)
+ {
+ for (int j = 0; j < M2.length; j++)
+ {
+ for (int k = 0; k < M2[0].length; k++)
+ {
+ tmp = GF2Field.multElem(M1[i][j], M2[j][k]);
+ A[i][k] = GF2Field.addElem(A[i][k], tmp);
+ }
+ }
+ }
+ return A;
+ }
+
+ /**
+ * This function multiplies a given matrix with a one-dimensional array.
+ * <p>
+ * An exception is thrown, if the number of columns in the matrix and
+ * the number of rows in the one-dim. array differ.
+ *
+ * @param M1 the matrix to be multiplied
+ * @param m the one-dimensional array to be multiplied
+ * @return M1*m
+ * @throws RuntimeException in case of dimension inconsistency
+ */
+ public short[] multiplyMatrix(short[][] M1, short[] m)
+ throws RuntimeException
+ {
+ if (M1[0].length != m.length)
+ {
+ throw new RuntimeException("Multiplication is not possible!");
+ }
+ short tmp = 0;
+ short[] B = new short[M1.length];
+ for (int i = 0; i < M1.length; i++)
+ {
+ for (int j = 0; j < m.length; j++)
+ {
+ tmp = GF2Field.multElem(M1[i][j], m[j]);
+ B[i] = GF2Field.addElem(B[i], tmp);
+ }
+ }
+ return B;
+ }
+
+ /**
+ * Addition of two vectors
+ *
+ * @param vector1 first summand, always of dim n
+ * @param vector2 second summand, always of dim n
+ * @return addition of vector1 and vector2
+ * @throws RuntimeException in case the addition is impossible
+ * due to inconsistency in the dimensions
+ */
+ public short[] addVect(short[] vector1, short[] vector2)
+ {
+ if (vector1.length != vector2.length)
+ {
+ throw new RuntimeException("Multiplication is not possible!");
+ }
+ short rslt[] = new short[vector1.length];
+ for (int n = 0; n < rslt.length; n++)
+ {
+ rslt[n] = GF2Field.addElem(vector1[n], vector2[n]);
+ }
+ return rslt;
+ }
+
+ /**
+ * Multiplication of column vector with row vector
+ *
+ * @param vector1 column vector, always n x 1
+ * @param vector2 row vector, always 1 x n
+ * @return resulting n x n matrix of multiplication
+ * @throws RuntimeException in case the multiplication is impossible due to
+ * inconsistency in the dimensions
+ */
+ public short[][] multVects(short[] vector1, short[] vector2)
+ {
+ if (vector1.length != vector2.length)
+ {
+ throw new RuntimeException("Multiplication is not possible!");
+ }
+ short rslt[][] = new short[vector1.length][vector2.length];
+ for (int i = 0; i < vector1.length; i++)
+ {
+ for (int j = 0; j < vector2.length; j++)
+ {
+ rslt[i][j] = GF2Field.multElem(vector1[i], vector2[j]);
+ }
+ }
+ return rslt;
+ }
+
+ /**
+ * Multiplies vector with scalar
+ *
+ * @param scalar galois element to multiply vector with
+ * @param vector vector to be multiplied
+ * @return vector multiplied with scalar
+ */
+ public short[] multVect(short scalar, short[] vector)
+ {
+ short rslt[] = new short[vector.length];
+ for (int n = 0; n < rslt.length; n++)
+ {
+ rslt[n] = GF2Field.multElem(scalar, vector[n]);
+ }
+ return rslt;
+ }
+
+ /**
+ * Multiplies matrix with scalar
+ *
+ * @param scalar galois element to multiply matrix with
+ * @param matrix 2-dim n x n matrix to be multiplied
+ * @return matrix multiplied with scalar
+ */
+ public short[][] multMatrix(short scalar, short[][] matrix)
+ {
+ short[][] rslt = new short[matrix.length][matrix[0].length];
+ for (int i = 0; i < matrix.length; i++)
+ {
+ for (int j = 0; j < matrix[0].length; j++)
+ {
+ rslt[i][j] = GF2Field.multElem(scalar, matrix[i][j]);
+ }
+ }
+ return rslt;
+ }
+
+ /**
+ * Adds the n x n matrices matrix1 and matrix2
+ *
+ * @param matrix1 first summand
+ * @param matrix2 second summand
+ * @return addition of matrix1 and matrix2; both having the dimensions n x n
+ * @throws RuntimeException in case the addition is not possible because of
+ * different dimensions of the matrices
+ */
+ public short[][] addSquareMatrix(short[][] matrix1, short[][] matrix2)
+ {
+ if (matrix1.length != matrix2.length || matrix1[0].length != matrix2[0].length)
+ {
+ throw new RuntimeException("Addition is not possible!");
+ }
+
+ short[][] rslt = new short[matrix1.length][matrix1.length];//
+ for (int i = 0; i < matrix1.length; i++)
+ {
+ for (int j = 0; j < matrix2.length; j++)
+ {
+ rslt[i][j] = GF2Field.addElem(matrix1[i][j], matrix2[i][j]);
+ }
+ }
+ return rslt;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/util/GF2Field.java b/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/util/GF2Field.java
new file mode 100644
index 00000000..675f0ec5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/util/GF2Field.java
@@ -0,0 +1,139 @@
+package org.spongycastle.pqc.crypto.rainbow.util;
+
+/**
+ * This class provides the basic operations like addition, multiplication and
+ * finding the multiplicative inverse of an element in GF2^8.
+ * <p>
+ * The operations are implemented using the irreducible polynomial
+ * 1+x^2+x^3+x^6+x^8 ( 1 0100 1101 = 0x14d )
+ * <p>
+ * This class makes use of lookup tables(exps and logs) for implementing the
+ * operations in order to increase the efficiency of Rainbow.
+ */
+public class GF2Field
+{
+
+ public static final int MASK = 0xff;
+
+ /*
+ * this lookup table is needed for multiplication and computing the
+ * multiplicative inverse
+ */
+ static final short exps[] = {1, 2, 4, 8, 16, 32, 64, 128, 77, 154, 121, 242,
+ 169, 31, 62, 124, 248, 189, 55, 110, 220, 245, 167, 3, 6, 12, 24,
+ 48, 96, 192, 205, 215, 227, 139, 91, 182, 33, 66, 132, 69, 138, 89,
+ 178, 41, 82, 164, 5, 10, 20, 40, 80, 160, 13, 26, 52, 104, 208,
+ 237, 151, 99, 198, 193, 207, 211, 235, 155, 123, 246, 161, 15, 30,
+ 60, 120, 240, 173, 23, 46, 92, 184, 61, 122, 244, 165, 7, 14, 28,
+ 56, 112, 224, 141, 87, 174, 17, 34, 68, 136, 93, 186, 57, 114, 228,
+ 133, 71, 142, 81, 162, 9, 18, 36, 72, 144, 109, 218, 249, 191, 51,
+ 102, 204, 213, 231, 131, 75, 150, 97, 194, 201, 223, 243, 171, 27,
+ 54, 108, 216, 253, 183, 35, 70, 140, 85, 170, 25, 50, 100, 200,
+ 221, 247, 163, 11, 22, 44, 88, 176, 45, 90, 180, 37, 74, 148, 101,
+ 202, 217, 255, 179, 43, 86, 172, 21, 42, 84, 168, 29, 58, 116, 232,
+ 157, 119, 238, 145, 111, 222, 241, 175, 19, 38, 76, 152, 125, 250,
+ 185, 63, 126, 252, 181, 39, 78, 156, 117, 234, 153, 127, 254, 177,
+ 47, 94, 188, 53, 106, 212, 229, 135, 67, 134, 65, 130, 73, 146,
+ 105, 210, 233, 159, 115, 230, 129, 79, 158, 113, 226, 137, 95, 190,
+ 49, 98, 196, 197, 199, 195, 203, 219, 251, 187, 59, 118, 236, 149,
+ 103, 206, 209, 239, 147, 107, 214, 225, 143, 83, 166, 1};
+
+ /*
+ * this lookup table is needed for multiplication and computing the
+ * multiplicative inverse
+ */
+ static final short logs[] = {0, 0, 1, 23, 2, 46, 24, 83, 3, 106, 47, 147,
+ 25, 52, 84, 69, 4, 92, 107, 182, 48, 166, 148, 75, 26, 140, 53,
+ 129, 85, 170, 70, 13, 5, 36, 93, 135, 108, 155, 183, 193, 49, 43,
+ 167, 163, 149, 152, 76, 202, 27, 230, 141, 115, 54, 205, 130, 18,
+ 86, 98, 171, 240, 71, 79, 14, 189, 6, 212, 37, 210, 94, 39, 136,
+ 102, 109, 214, 156, 121, 184, 8, 194, 223, 50, 104, 44, 253, 168,
+ 138, 164, 90, 150, 41, 153, 34, 77, 96, 203, 228, 28, 123, 231, 59,
+ 142, 158, 116, 244, 55, 216, 206, 249, 131, 111, 19, 178, 87, 225,
+ 99, 220, 172, 196, 241, 175, 72, 10, 80, 66, 15, 186, 190, 199, 7,
+ 222, 213, 120, 38, 101, 211, 209, 95, 227, 40, 33, 137, 89, 103,
+ 252, 110, 177, 215, 248, 157, 243, 122, 58, 185, 198, 9, 65, 195,
+ 174, 224, 219, 51, 68, 105, 146, 45, 82, 254, 22, 169, 12, 139,
+ 128, 165, 74, 91, 181, 151, 201, 42, 162, 154, 192, 35, 134, 78,
+ 188, 97, 239, 204, 17, 229, 114, 29, 61, 124, 235, 232, 233, 60,
+ 234, 143, 125, 159, 236, 117, 30, 245, 62, 56, 246, 217, 63, 207,
+ 118, 250, 31, 132, 160, 112, 237, 20, 144, 179, 126, 88, 251, 226,
+ 32, 100, 208, 221, 119, 173, 218, 197, 64, 242, 57, 176, 247, 73,
+ 180, 11, 127, 81, 21, 67, 145, 16, 113, 187, 238, 191, 133, 200,
+ 161};
+
+ /**
+ * This function calculates the sum of two elements as an operation in GF2^8
+ *
+ * @param x the first element that is to be added
+ * @param y the second element that should be add
+ * @return the sum of the two elements x and y in GF2^8
+ */
+ public static short addElem(short x, short y)
+ {
+ return (short)(x ^ y);
+ }
+
+ /**
+ * This function computes the multiplicative inverse of a given element in
+ * GF2^8 The 0 has no multiplicative inverse and in this case 0 is returned.
+ *
+ * @param x the element which multiplicative inverse is to be computed
+ * @return the multiplicative inverse of the given element, in case it
+ * exists or 0, otherwise
+ */
+ public static short invElem(short x)
+ {
+ if (x == 0)
+ {
+ return 0;
+ }
+ return (exps[255 - logs[x]]);
+ }
+
+ /**
+ * This function multiplies two elements in GF2^8. If one of the two
+ * elements is 0, 0 is returned.
+ *
+ * @param x the first element to be multiplied.
+ * @param y the second element to be multiplied.
+ * @return the product of the two input elements in GF2^8.
+ */
+ public static short multElem(short x, short y)
+ {
+ if (x == 0 || y == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return (exps[(logs[x] + logs[y]) % 255]);
+ }
+ }
+
+ /**
+ * This function returns the values of exps-lookup table which correspond to
+ * the input
+ *
+ * @param x the index in the lookup table exps
+ * @return exps-value, corresponding to the input
+ */
+ public static short getExp(short x)
+ {
+ return exps[x];
+ }
+
+ /**
+ * This function returns the values of logs-lookup table which correspond to
+ * the input
+ *
+ * @param x the index in the lookup table logs
+ * @return logs-value, corresponding to the input
+ */
+ public static short getLog(short x)
+ {
+ return logs[x];
+ }
+
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/util/RainbowUtil.java b/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/util/RainbowUtil.java
new file mode 100644
index 00000000..1e4f40f4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/util/RainbowUtil.java
@@ -0,0 +1,230 @@
+package org.spongycastle.pqc.crypto.rainbow.util;
+
+/**
+ * This class is needed for the conversions while encoding and decoding, as well as for
+ * comparison between arrays of some dimensions
+ */
+public class RainbowUtil
+{
+
+ /**
+ * This function converts an one-dimensional array of bytes into a
+ * one-dimensional array of int
+ *
+ * @param in the array to be converted
+ * @return out
+ * the one-dimensional int-array that corresponds the input
+ */
+ public static int[] convertArraytoInt(byte[] in)
+ {
+ int[] out = new int[in.length];
+ for (int i = 0; i < in.length; i++)
+ {
+ out[i] = in[i] & GF2Field.MASK;
+ }
+ return out;
+ }
+
+ /**
+ * This function converts an one-dimensional array of bytes into a
+ * one-dimensional array of type short
+ *
+ * @param in the array to be converted
+ * @return out
+ * one-dimensional short-array that corresponds the input
+ */
+ public static short[] convertArray(byte[] in)
+ {
+ short[] out = new short[in.length];
+ for (int i = 0; i < in.length; i++)
+ {
+ out[i] = (short)(in[i] & GF2Field.MASK);
+ }
+ return out;
+ }
+
+ /**
+ * This function converts a matrix of bytes into a matrix of type short
+ *
+ * @param in the matrix to be converted
+ * @return out
+ * short-matrix that corresponds the input
+ */
+ public static short[][] convertArray(byte[][] in)
+ {
+ short[][] out = new short[in.length][in[0].length];
+ for (int i = 0; i < in.length; i++)
+ {
+ for (int j = 0; j < in[0].length; j++)
+ {
+ out[i][j] = (short)(in[i][j] & GF2Field.MASK);
+ }
+ }
+ return out;
+ }
+
+ /**
+ * This function converts a 3-dimensional array of bytes into a 3-dimensional array of type short
+ *
+ * @param in the array to be converted
+ * @return out
+ * short-array that corresponds the input
+ */
+ public static short[][][] convertArray(byte[][][] in)
+ {
+ short[][][] out = new short[in.length][in[0].length][in[0][0].length];
+ for (int i = 0; i < in.length; i++)
+ {
+ for (int j = 0; j < in[0].length; j++)
+ {
+ for (int k = 0; k < in[0][0].length; k++)
+ {
+ out[i][j][k] = (short)(in[i][j][k] & GF2Field.MASK);
+ }
+ }
+ }
+ return out;
+ }
+
+ /**
+ * This function converts an array of type int into an array of type byte
+ *
+ * @param in the array to be converted
+ * @return out
+ * the byte-array that corresponds the input
+ */
+ public static byte[] convertIntArray(int[] in)
+ {
+ byte[] out = new byte[in.length];
+ for (int i = 0; i < in.length; i++)
+ {
+ out[i] = (byte)in[i];
+ }
+ return out;
+ }
+
+
+ /**
+ * This function converts an array of type short into an array of type byte
+ *
+ * @param in the array to be converted
+ * @return out
+ * the byte-array that corresponds the input
+ */
+ public static byte[] convertArray(short[] in)
+ {
+ byte[] out = new byte[in.length];
+ for (int i = 0; i < in.length; i++)
+ {
+ out[i] = (byte)in[i];
+ }
+ return out;
+ }
+
+ /**
+ * This function converts a matrix of type short into a matrix of type byte
+ *
+ * @param in the matrix to be converted
+ * @return out
+ * the byte-matrix that corresponds the input
+ */
+ public static byte[][] convertArray(short[][] in)
+ {
+ byte[][] out = new byte[in.length][in[0].length];
+ for (int i = 0; i < in.length; i++)
+ {
+ for (int j = 0; j < in[0].length; j++)
+ {
+ out[i][j] = (byte)in[i][j];
+ }
+ }
+ return out;
+ }
+
+ /**
+ * This function converts a 3-dimensional array of type short into a 3-dimensional array of type byte
+ *
+ * @param in the array to be converted
+ * @return out
+ * the byte-array that corresponds the input
+ */
+ public static byte[][][] convertArray(short[][][] in)
+ {
+ byte[][][] out = new byte[in.length][in[0].length][in[0][0].length];
+ for (int i = 0; i < in.length; i++)
+ {
+ for (int j = 0; j < in[0].length; j++)
+ {
+ for (int k = 0; k < in[0][0].length; k++)
+ {
+ out[i][j][k] = (byte)in[i][j][k];
+ }
+ }
+ }
+ return out;
+ }
+
+ /**
+ * Compare two short arrays. No null checks are performed.
+ *
+ * @param left the first short array
+ * @param right the second short array
+ * @return the result of the comparison
+ */
+ public static boolean equals(short[] left, short[] right)
+ {
+ if (left.length != right.length)
+ {
+ return false;
+ }
+ boolean result = true;
+ for (int i = left.length - 1; i >= 0; i--)
+ {
+ result &= left[i] == right[i];
+ }
+ return result;
+ }
+
+ /**
+ * Compare two two-dimensional short arrays. No null checks are performed.
+ *
+ * @param left the first short array
+ * @param right the second short array
+ * @return the result of the comparison
+ */
+ public static boolean equals(short[][] left, short[][] right)
+ {
+ if (left.length != right.length)
+ {
+ return false;
+ }
+ boolean result = true;
+ for (int i = left.length - 1; i >= 0; i--)
+ {
+ result &= equals(left[i], right[i]);
+ }
+ return result;
+ }
+
+ /**
+ * Compare two three-dimensional short arrays. No null checks are performed.
+ *
+ * @param left the first short array
+ * @param right the second short array
+ * @return the result of the comparison
+ */
+ public static boolean equals(short[][][] left, short[][][] right)
+ {
+ if (left.length != right.length)
+ {
+ return false;
+ }
+ boolean result = true;
+ for (int i = left.length - 1; i >= 0; i--)
+ {
+ result &= equals(left[i], right[i]);
+ }
+ return result;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/BigEndianConversions.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/BigEndianConversions.java
new file mode 100644
index 00000000..4ed7f1c9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/BigEndianConversions.java
@@ -0,0 +1,306 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+
+/**
+ * This is a utility class containing data type conversions using big-endian
+ * byte order.
+ *
+ * @see LittleEndianConversions
+ */
+public final class BigEndianConversions
+{
+
+ /**
+ * Default constructor (private).
+ */
+ private BigEndianConversions()
+ {
+ // empty
+ }
+
+ /**
+ * Convert an integer to an octet string of length 4 according to IEEE 1363,
+ * Section 5.5.3.
+ *
+ * @param x the integer to convert
+ * @return the converted integer
+ */
+ public static byte[] I2OSP(int x)
+ {
+ byte[] result = new byte[4];
+ result[0] = (byte)(x >>> 24);
+ result[1] = (byte)(x >>> 16);
+ result[2] = (byte)(x >>> 8);
+ result[3] = (byte)x;
+ return result;
+ }
+
+ /**
+ * Convert an integer to an octet string according to IEEE 1363, Section
+ * 5.5.3. Length checking is performed.
+ *
+ * @param x the integer to convert
+ * @param oLen the desired length of the octet string
+ * @return an octet string of length <tt>oLen</tt> representing the
+ * integer <tt>x</tt>, or <tt>null</tt> if the integer is
+ * negative
+ * @throws ArithmeticException if <tt>x</tt> can't be encoded into <tt>oLen</tt>
+ * octets.
+ */
+ public static byte[] I2OSP(int x, int oLen)
+ throws ArithmeticException
+ {
+ if (x < 0)
+ {
+ return null;
+ }
+ int octL = IntegerFunctions.ceilLog256(x);
+ if (octL > oLen)
+ {
+ throw new ArithmeticException(
+ "Cannot encode given integer into specified number of octets.");
+ }
+ byte[] result = new byte[oLen];
+ for (int i = oLen - 1; i >= oLen - octL; i--)
+ {
+ result[i] = (byte)(x >>> (8 * (oLen - 1 - i)));
+ }
+ return result;
+ }
+
+ /**
+ * Convert an integer to an octet string of length 4 according to IEEE 1363,
+ * Section 5.5.3.
+ *
+ * @param input the integer to convert
+ * @param output byte array holding the output
+ * @param outOff offset in output array where the result is stored
+ */
+ public static void I2OSP(int input, byte[] output, int outOff)
+ {
+ output[outOff++] = (byte)(input >>> 24);
+ output[outOff++] = (byte)(input >>> 16);
+ output[outOff++] = (byte)(input >>> 8);
+ output[outOff] = (byte)input;
+ }
+
+ /**
+ * Convert an integer to an octet string of length 8 according to IEEE 1363,
+ * Section 5.5.3.
+ *
+ * @param input the integer to convert
+ * @return the converted integer
+ */
+ public static byte[] I2OSP(long input)
+ {
+ byte[] output = new byte[8];
+ output[0] = (byte)(input >>> 56);
+ output[1] = (byte)(input >>> 48);
+ output[2] = (byte)(input >>> 40);
+ output[3] = (byte)(input >>> 32);
+ output[4] = (byte)(input >>> 24);
+ output[5] = (byte)(input >>> 16);
+ output[6] = (byte)(input >>> 8);
+ output[7] = (byte)input;
+ return output;
+ }
+
+ /**
+ * Convert an integer to an octet string of length 8 according to IEEE 1363,
+ * Section 5.5.3.
+ *
+ * @param input the integer to convert
+ * @param output byte array holding the output
+ * @param outOff offset in output array where the result is stored
+ */
+ public static void I2OSP(long input, byte[] output, int outOff)
+ {
+ output[outOff++] = (byte)(input >>> 56);
+ output[outOff++] = (byte)(input >>> 48);
+ output[outOff++] = (byte)(input >>> 40);
+ output[outOff++] = (byte)(input >>> 32);
+ output[outOff++] = (byte)(input >>> 24);
+ output[outOff++] = (byte)(input >>> 16);
+ output[outOff++] = (byte)(input >>> 8);
+ output[outOff] = (byte)input;
+ }
+
+ /**
+ * Convert an integer to an octet string of the specified length according
+ * to IEEE 1363, Section 5.5.3. No length checking is performed (i.e., if
+ * the integer cannot be encoded into <tt>length</tt> octets, it is
+ * truncated).
+ *
+ * @param input the integer to convert
+ * @param output byte array holding the output
+ * @param outOff offset in output array where the result is stored
+ * @param length the length of the encoding
+ */
+ public static void I2OSP(int input, byte[] output, int outOff, int length)
+ {
+ for (int i = length - 1; i >= 0; i--)
+ {
+ output[outOff + i] = (byte)(input >>> (8 * (length - 1 - i)));
+ }
+ }
+
+ /**
+ * Convert an octet string to an integer according to IEEE 1363, Section
+ * 5.5.3.
+ *
+ * @param input the byte array holding the octet string
+ * @return an integer representing the octet string <tt>input</tt>, or
+ * <tt>0</tt> if the represented integer is negative or too large
+ * or the byte array is empty
+ * @throws ArithmeticException if the length of the given octet string is larger than 4.
+ */
+ public static int OS2IP(byte[] input)
+ {
+ if (input.length > 4)
+ {
+ throw new ArithmeticException("invalid input length");
+ }
+ if (input.length == 0)
+ {
+ return 0;
+ }
+ int result = 0;
+ for (int j = 0; j < input.length; j++)
+ {
+ result |= (input[j] & 0xff) << (8 * (input.length - 1 - j));
+ }
+ return result;
+ }
+
+ /**
+ * Convert a byte array of length 4 beginning at <tt>offset</tt> into an
+ * integer.
+ *
+ * @param input the byte array
+ * @param inOff the offset into the byte array
+ * @return the resulting integer
+ */
+ public static int OS2IP(byte[] input, int inOff)
+ {
+ int result = (input[inOff++] & 0xff) << 24;
+ result |= (input[inOff++] & 0xff) << 16;
+ result |= (input[inOff++] & 0xff) << 8;
+ result |= input[inOff] & 0xff;
+ return result;
+ }
+
+ /**
+ * Convert an octet string to an integer according to IEEE 1363, Section
+ * 5.5.3.
+ *
+ * @param input the byte array holding the octet string
+ * @param inOff the offset in the input byte array where the octet string
+ * starts
+ * @param inLen the length of the encoded integer
+ * @return an integer representing the octet string <tt>bytes</tt>, or
+ * <tt>0</tt> if the represented integer is negative or too large
+ * or the byte array is empty
+ */
+ public static int OS2IP(byte[] input, int inOff, int inLen)
+ {
+ if ((input.length == 0) || input.length < inOff + inLen - 1)
+ {
+ return 0;
+ }
+ int result = 0;
+ for (int j = 0; j < inLen; j++)
+ {
+ result |= (input[inOff + j] & 0xff) << (8 * (inLen - j - 1));
+ }
+ return result;
+ }
+
+ /**
+ * Convert a byte array of length 8 beginning at <tt>inOff</tt> into a
+ * long integer.
+ *
+ * @param input the byte array
+ * @param inOff the offset into the byte array
+ * @return the resulting long integer
+ */
+ public static long OS2LIP(byte[] input, int inOff)
+ {
+ long result = ((long)input[inOff++] & 0xff) << 56;
+ result |= ((long)input[inOff++] & 0xff) << 48;
+ result |= ((long)input[inOff++] & 0xff) << 40;
+ result |= ((long)input[inOff++] & 0xff) << 32;
+ result |= ((long)input[inOff++] & 0xff) << 24;
+ result |= (input[inOff++] & 0xff) << 16;
+ result |= (input[inOff++] & 0xff) << 8;
+ result |= input[inOff] & 0xff;
+ return result;
+ }
+
+ /**
+ * Convert an int array into a byte array.
+ *
+ * @param input the int array
+ * @return the converted array
+ */
+ public static byte[] toByteArray(final int[] input)
+ {
+ byte[] result = new byte[input.length << 2];
+ for (int i = 0; i < input.length; i++)
+ {
+ I2OSP(input[i], result, i << 2);
+ }
+ return result;
+ }
+
+ /**
+ * Convert an int array into a byte array of the specified length. No length
+ * checking is performed (i.e., if the last integer cannot be encoded into
+ * <tt>length % 4</tt> octets, it is truncated).
+ *
+ * @param input the int array
+ * @param length the length of the converted array
+ * @return the converted array
+ */
+ public static byte[] toByteArray(final int[] input, int length)
+ {
+ final int intLen = input.length;
+ byte[] result = new byte[length];
+ int index = 0;
+ for (int i = 0; i <= intLen - 2; i++, index += 4)
+ {
+ I2OSP(input[i], result, index);
+ }
+ I2OSP(input[intLen - 1], result, index, length - index);
+ return result;
+ }
+
+ /**
+ * Convert a byte array into an int array.
+ *
+ * @param input the byte array
+ * @return the converted array
+ */
+ public static int[] toIntArray(byte[] input)
+ {
+ final int intLen = (input.length + 3) / 4;
+ final int lastLen = input.length & 0x03;
+ int[] result = new int[intLen];
+
+ int index = 0;
+ for (int i = 0; i <= intLen - 2; i++, index += 4)
+ {
+ result[i] = OS2IP(input, index);
+ }
+ if (lastLen != 0)
+ {
+ result[intLen - 1] = OS2IP(input, index, lastLen);
+ }
+ else
+ {
+ result[intLen - 1] = OS2IP(input, index);
+ }
+
+ return result;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/BigIntUtils.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/BigIntUtils.java
new file mode 100644
index 00000000..19734977
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/BigIntUtils.java
@@ -0,0 +1,138 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+import java.math.BigInteger;
+
+/**
+ * FIXME: is this really necessary?!
+ */
+public final class BigIntUtils
+{
+
+ /**
+ * Default constructor (private).
+ */
+ private BigIntUtils()
+ {
+ // empty
+ }
+
+ /**
+ * Checks if two BigInteger arrays contain the same entries
+ *
+ * @param a first BigInteger array
+ * @param b second BigInteger array
+ * @return true or false
+ */
+ public static boolean equals(BigInteger[] a, BigInteger[] b)
+ {
+ int flag = 0;
+
+ if (a.length != b.length)
+ {
+ return false;
+ }
+ for (int i = 0; i < a.length; i++)
+ {
+ // avoid branches here!
+ // problem: compareTo on BigIntegers is not
+ // guaranteed constant-time!
+ flag |= a[i].compareTo(b[i]);
+ }
+ return flag == 0;
+ }
+
+ /**
+ * Fill the given BigInteger array with the given value.
+ *
+ * @param array the array
+ * @param value the value
+ */
+ public static void fill(BigInteger[] array, BigInteger value)
+ {
+ for (int i = array.length - 1; i >= 0; i--)
+ {
+ array[i] = value;
+ }
+ }
+
+ /**
+ * Generates a subarray of a given BigInteger array.
+ *
+ * @param input -
+ * the input BigInteger array
+ * @param start -
+ * the start index
+ * @param end -
+ * the end index
+ * @return a subarray of <tt>input</tt>, ranging from <tt>start</tt> to
+ * <tt>end</tt>
+ */
+ public static BigInteger[] subArray(BigInteger[] input, int start, int end)
+ {
+ BigInteger[] result = new BigInteger[end - start];
+ System.arraycopy(input, start, result, 0, end - start);
+ return result;
+ }
+
+ /**
+ * Converts a BigInteger array into an integer array
+ *
+ * @param input -
+ * the BigInteger array
+ * @return the integer array
+ */
+ public static int[] toIntArray(BigInteger[] input)
+ {
+ int[] result = new int[input.length];
+ for (int i = 0; i < input.length; i++)
+ {
+ result[i] = input[i].intValue();
+ }
+ return result;
+ }
+
+ /**
+ * Converts a BigInteger array into an integer array, reducing all
+ * BigIntegers mod q.
+ *
+ * @param q -
+ * the modulus
+ * @param input -
+ * the BigInteger array
+ * @return the integer array
+ */
+ public static int[] toIntArrayModQ(int q, BigInteger[] input)
+ {
+ BigInteger bq = BigInteger.valueOf(q);
+ int[] result = new int[input.length];
+ for (int i = 0; i < input.length; i++)
+ {
+ result[i] = input[i].mod(bq).intValue();
+ }
+ return result;
+ }
+
+ /**
+ * Return the value of <tt>big</tt> as a byte array. Although BigInteger
+ * has such a method, it uses an extra bit to indicate the sign of the
+ * number. For elliptic curve cryptography, the numbers usually are
+ * positive. Thus, this helper method returns a byte array of minimal
+ * length, ignoring the sign of the number.
+ *
+ * @param value the <tt>BigInteger</tt> value to be converted to a byte
+ * array
+ * @return the value <tt>big</tt> as byte array
+ */
+ public static byte[] toMinimalByteArray(BigInteger value)
+ {
+ byte[] valBytes = value.toByteArray();
+ if ((valBytes.length == 1) || (value.bitLength() & 0x07) != 0)
+ {
+ return valBytes;
+ }
+ byte[] result = new byte[value.bitLength() >> 3];
+ System.arraycopy(valBytes, 1, result, 0, result.length);
+ return result;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/ByteUtils.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/ByteUtils.java
new file mode 100644
index 00000000..0e234ae9
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/ByteUtils.java
@@ -0,0 +1,414 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+/**
+ * This class is a utility class for manipulating byte arrays.
+ */
+public final class ByteUtils
+{
+
+ private static final char[] HEX_CHARS = {'0', '1', '2', '3', '4', '5',
+ '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+
+ /**
+ * Default constructor (private)
+ */
+ private ByteUtils()
+ {
+ // empty
+ }
+
+ /**
+ * Compare two byte arrays (perform null checks beforehand).
+ *
+ * @param left the first byte array
+ * @param right the second byte array
+ * @return the result of the comparison
+ */
+ public static boolean equals(byte[] left, byte[] right)
+ {
+ if (left == null)
+ {
+ return right == null;
+ }
+ if (right == null)
+ {
+ return false;
+ }
+
+ if (left.length != right.length)
+ {
+ return false;
+ }
+ boolean result = true;
+ for (int i = left.length - 1; i >= 0; i--)
+ {
+ result &= left[i] == right[i];
+ }
+ return result;
+ }
+
+ /**
+ * Compare two two-dimensional byte arrays. No null checks are performed.
+ *
+ * @param left the first byte array
+ * @param right the second byte array
+ * @return the result of the comparison
+ */
+ public static boolean equals(byte[][] left, byte[][] right)
+ {
+ if (left.length != right.length)
+ {
+ return false;
+ }
+
+ boolean result = true;
+ for (int i = left.length - 1; i >= 0; i--)
+ {
+ result &= ByteUtils.equals(left[i], right[i]);
+ }
+
+ return result;
+ }
+
+ /**
+ * Compare two three-dimensional byte arrays. No null checks are performed.
+ *
+ * @param left the first byte array
+ * @param right the second byte array
+ * @return the result of the comparison
+ */
+ public static boolean equals(byte[][][] left, byte[][][] right)
+ {
+ if (left.length != right.length)
+ {
+ return false;
+ }
+
+ boolean result = true;
+ for (int i = left.length - 1; i >= 0; i--)
+ {
+ if (left[i].length != right[i].length)
+ {
+ return false;
+ }
+ for (int j = left[i].length - 1; j >= 0; j--)
+ {
+ result &= ByteUtils.equals(left[i][j], right[i][j]);
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Computes a hashcode based on the contents of a one-dimensional byte array
+ * rather than its identity.
+ *
+ * @param array the array to compute the hashcode of
+ * @return the hashcode
+ */
+ public static int deepHashCode(byte[] array)
+ {
+ int result = 1;
+ for (int i = 0; i < array.length; i++)
+ {
+ result = 31 * result + array[i];
+ }
+ return result;
+ }
+
+ /**
+ * Computes a hashcode based on the contents of a two-dimensional byte array
+ * rather than its identity.
+ *
+ * @param array the array to compute the hashcode of
+ * @return the hashcode
+ */
+ public static int deepHashCode(byte[][] array)
+ {
+ int result = 1;
+ for (int i = 0; i < array.length; i++)
+ {
+ result = 31 * result + deepHashCode(array[i]);
+ }
+ return result;
+ }
+
+ /**
+ * Computes a hashcode based on the contents of a three-dimensional byte
+ * array rather than its identity.
+ *
+ * @param array the array to compute the hashcode of
+ * @return the hashcode
+ */
+ public static int deepHashCode(byte[][][] array)
+ {
+ int result = 1;
+ for (int i = 0; i < array.length; i++)
+ {
+ result = 31 * result + deepHashCode(array[i]);
+ }
+ return result;
+ }
+
+
+ /**
+ * Return a clone of the given byte array (performs null check beforehand).
+ *
+ * @param array the array to clone
+ * @return the clone of the given array, or <tt>null</tt> if the array is
+ * <tt>null</tt>
+ */
+ public static byte[] clone(byte[] array)
+ {
+ if (array == null)
+ {
+ return null;
+ }
+ byte[] result = new byte[array.length];
+ System.arraycopy(array, 0, result, 0, array.length);
+ return result;
+ }
+
+ /**
+ * Convert a string containing hexadecimal characters to a byte-array.
+ *
+ * @param s a hex string
+ * @return a byte array with the corresponding value
+ */
+ public static byte[] fromHexString(String s)
+ {
+ char[] rawChars = s.toUpperCase().toCharArray();
+
+ int hexChars = 0;
+ for (int i = 0; i < rawChars.length; i++)
+ {
+ if ((rawChars[i] >= '0' && rawChars[i] <= '9')
+ || (rawChars[i] >= 'A' && rawChars[i] <= 'F'))
+ {
+ hexChars++;
+ }
+ }
+
+ byte[] byteString = new byte[(hexChars + 1) >> 1];
+
+ int pos = hexChars & 1;
+
+ for (int i = 0; i < rawChars.length; i++)
+ {
+ if (rawChars[i] >= '0' && rawChars[i] <= '9')
+ {
+ byteString[pos >> 1] <<= 4;
+ byteString[pos >> 1] |= rawChars[i] - '0';
+ }
+ else if (rawChars[i] >= 'A' && rawChars[i] <= 'F')
+ {
+ byteString[pos >> 1] <<= 4;
+ byteString[pos >> 1] |= rawChars[i] - 'A' + 10;
+ }
+ else
+ {
+ continue;
+ }
+ pos++;
+ }
+
+ return byteString;
+ }
+
+ /**
+ * Convert a byte array to the corresponding hexstring.
+ *
+ * @param input the byte array to be converted
+ * @return the corresponding hexstring
+ */
+ public static String toHexString(byte[] input)
+ {
+ String result = "";
+ for (int i = 0; i < input.length; i++)
+ {
+ result += HEX_CHARS[(input[i] >>> 4) & 0x0f];
+ result += HEX_CHARS[(input[i]) & 0x0f];
+ }
+ return result;
+ }
+
+ /**
+ * Convert a byte array to the corresponding hex string.
+ *
+ * @param input the byte array to be converted
+ * @param prefix the prefix to put at the beginning of the hex string
+ * @param seperator a separator string
+ * @return the corresponding hex string
+ */
+ public static String toHexString(byte[] input, String prefix,
+ String seperator)
+ {
+ String result = new String(prefix);
+ for (int i = 0; i < input.length; i++)
+ {
+ result += HEX_CHARS[(input[i] >>> 4) & 0x0f];
+ result += HEX_CHARS[(input[i]) & 0x0f];
+ if (i < input.length - 1)
+ {
+ result += seperator;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Convert a byte array to the corresponding bit string.
+ *
+ * @param input the byte array to be converted
+ * @return the corresponding bit string
+ */
+ public static String toBinaryString(byte[] input)
+ {
+ String result = "";
+ int i;
+ for (i = 0; i < input.length; i++)
+ {
+ int e = input[i];
+ for (int ii = 0; ii < 8; ii++)
+ {
+ int b = (e >>> ii) & 1;
+ result += b;
+ }
+ if (i != input.length - 1)
+ {
+ result += " ";
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Compute the bitwise XOR of two arrays of bytes. The arrays have to be of
+ * same length. No length checking is performed.
+ *
+ * @param x1 the first array
+ * @param x2 the second array
+ * @return x1 XOR x2
+ */
+ public static byte[] xor(byte[] x1, byte[] x2)
+ {
+ byte[] out = new byte[x1.length];
+
+ for (int i = x1.length - 1; i >= 0; i--)
+ {
+ out[i] = (byte)(x1[i] ^ x2[i]);
+ }
+ return out;
+ }
+
+ /**
+ * Concatenate two byte arrays. No null checks are performed.
+ *
+ * @param x1 the first array
+ * @param x2 the second array
+ * @return (x2||x1) (little-endian order, i.e. x1 is at lower memory
+ * addresses)
+ */
+ public static byte[] concatenate(byte[] x1, byte[] x2)
+ {
+ byte[] result = new byte[x1.length + x2.length];
+
+ System.arraycopy(x1, 0, result, 0, x1.length);
+ System.arraycopy(x2, 0, result, x1.length, x2.length);
+
+ return result;
+ }
+
+ /**
+ * Convert a 2-dimensional byte array into a 1-dimensional byte array by
+ * concatenating all entries.
+ *
+ * @param array a 2-dimensional byte array
+ * @return the concatenated input array
+ */
+ public static byte[] concatenate(byte[][] array)
+ {
+ int rowLength = array[0].length;
+ byte[] result = new byte[array.length * rowLength];
+ int index = 0;
+ for (int i = 0; i < array.length; i++)
+ {
+ System.arraycopy(array[i], 0, result, index, rowLength);
+ index += rowLength;
+ }
+ return result;
+ }
+
+ /**
+ * Split a byte array <tt>input</tt> into two arrays at <tt>index</tt>,
+ * i.e. the first array will have the lower <tt>index</tt> bytes, the
+ * second one the higher <tt>input.length - index</tt> bytes.
+ *
+ * @param input the byte array to be split
+ * @param index the index where the byte array is split
+ * @return the splitted input array as an array of two byte arrays
+ * @throws ArrayIndexOutOfBoundsException if <tt>index</tt> is out of bounds
+ */
+ public static byte[][] split(byte[] input, int index)
+ throws ArrayIndexOutOfBoundsException
+ {
+ if (index > input.length)
+ {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ byte[][] result = new byte[2][];
+ result[0] = new byte[index];
+ result[1] = new byte[input.length - index];
+ System.arraycopy(input, 0, result[0], 0, index);
+ System.arraycopy(input, index, result[1], 0, input.length - index);
+ return result;
+ }
+
+ /**
+ * Generate a subarray of a given byte array.
+ *
+ * @param input the input byte array
+ * @param start the start index
+ * @param end the end index
+ * @return a subarray of <tt>input</tt>, ranging from <tt>start</tt>
+ * (inclusively) to <tt>end</tt> (exclusively)
+ */
+ public static byte[] subArray(byte[] input, int start, int end)
+ {
+ byte[] result = new byte[end - start];
+ System.arraycopy(input, start, result, 0, end - start);
+ return result;
+ }
+
+ /**
+ * Generate a subarray of a given byte array.
+ *
+ * @param input the input byte array
+ * @param start the start index
+ * @return a subarray of <tt>input</tt>, ranging from <tt>start</tt> to
+ * the end of the array
+ */
+ public static byte[] subArray(byte[] input, int start)
+ {
+ return subArray(input, start, input.length);
+ }
+
+ /**
+ * Rewrite a byte array as a char array
+ *
+ * @param input -
+ * the byte array
+ * @return char array
+ */
+ public static char[] toCharArray(byte[] input)
+ {
+ char[] result = new char[input.length];
+ for (int i = 0; i < input.length; i++)
+ {
+ result[i] = (char)input[i];
+ }
+ return result;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/CharUtils.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/CharUtils.java
new file mode 100644
index 00000000..44f97716
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/CharUtils.java
@@ -0,0 +1,98 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+public final class CharUtils
+{
+
+ /**
+ * Default constructor (private)
+ */
+ private CharUtils()
+ {
+ // empty
+ }
+
+ /**
+ * Return a clone of the given char array. No null checks are performed.
+ *
+ * @param array the array to clone
+ * @return the clone of the given array
+ */
+ public static char[] clone(char[] array)
+ {
+ char[] result = new char[array.length];
+ System.arraycopy(array, 0, result, 0, array.length);
+ return result;
+ }
+
+ /**
+ * Convert the given char array into a byte array.
+ *
+ * @param chars the char array
+ * @return the converted array
+ */
+ public static byte[] toByteArray(char[] chars)
+ {
+ byte[] result = new byte[chars.length];
+ for (int i = chars.length - 1; i >= 0; i--)
+ {
+ result[i] = (byte)chars[i];
+ }
+ return result;
+ }
+
+ /**
+ * Convert the given char array into a
+ * byte array for use with PBE encryption.
+ *
+ * @param chars the char array
+ * @return the converted array
+ */
+ public static byte[] toByteArrayForPBE(char[] chars)
+ {
+
+ byte[] out = new byte[chars.length];
+
+ for (int i = 0; i < chars.length; i++)
+ {
+ out[i] = (byte)chars[i];
+ }
+
+ int length = out.length * 2;
+ byte[] ret = new byte[length + 2];
+
+ int j = 0;
+ for (int i = 0; i < out.length; i++)
+ {
+ j = i * 2;
+ ret[j] = 0;
+ ret[j + 1] = out[i];
+ }
+
+ ret[length] = 0;
+ ret[length + 1] = 0;
+
+ return ret;
+ }
+
+ /**
+ * Compare two char arrays. No null checks are performed.
+ *
+ * @param left the char byte array
+ * @param right the second char array
+ * @return the result of the comparison
+ */
+ public static boolean equals(char[] left, char[] right)
+ {
+ if (left.length != right.length)
+ {
+ return false;
+ }
+ boolean result = true;
+ for (int i = left.length - 1; i >= 0; i--)
+ {
+ result &= left[i] == right[i];
+ }
+ return result;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2Matrix.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2Matrix.java
new file mode 100644
index 00000000..7e2de19e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2Matrix.java
@@ -0,0 +1,1323 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+import java.security.SecureRandom;
+
+/**
+ * This class describes some operations with matrices over finite field GF(2)
+ * and is used in ecc and MQ-PKC (also has some specific methods and
+ * implementation)
+ */
+public class GF2Matrix
+ extends Matrix
+{
+
+ /**
+ * For the matrix representation the array of type int[][] is used, thus one
+ * element of the array keeps 32 elements of the matrix (from one row and 32
+ * columns)
+ */
+ private int[][] matrix;
+
+ /**
+ * the length of each array representing a row of this matrix, computed as
+ * <tt>(numColumns + 31) / 32</tt>
+ */
+ private int length;
+
+ /**
+ * Create the matrix from encoded form.
+ *
+ * @param enc the encoded matrix
+ */
+ public GF2Matrix(byte[] enc)
+ {
+ if (enc.length < 9)
+ {
+ throw new ArithmeticException(
+ "given array is not an encoded matrix over GF(2)");
+ }
+
+ numRows = LittleEndianConversions.OS2IP(enc, 0);
+ numColumns = LittleEndianConversions.OS2IP(enc, 4);
+
+ int n = ((numColumns + 7) >>> 3) * numRows;
+
+ if ((numRows <= 0) || (n != (enc.length - 8)))
+ {
+ throw new ArithmeticException(
+ "given array is not an encoded matrix over GF(2)");
+ }
+
+ length = (numColumns + 31) >>> 5;
+ matrix = new int[numRows][length];
+
+ // number of "full" integer
+ int q = numColumns >> 5;
+ // number of bits in non-full integer
+ int r = numColumns & 0x1f;
+
+ int count = 8;
+ for (int i = 0; i < numRows; i++)
+ {
+ for (int j = 0; j < q; j++, count += 4)
+ {
+ matrix[i][j] = LittleEndianConversions.OS2IP(enc, count);
+ }
+ for (int j = 0; j < r; j += 8)
+ {
+ matrix[i][q] ^= (enc[count++] & 0xff) << j;
+ }
+ }
+ }
+
+ /**
+ * Create the matrix with the contents of the given array. The matrix is not
+ * copied. Unused coefficients are masked out.
+ *
+ * @param numColumns the number of columns
+ * @param matrix the element array
+ */
+ public GF2Matrix(int numColumns, int[][] matrix)
+ {
+ if (matrix[0].length != (numColumns + 31) >> 5)
+ {
+ throw new ArithmeticException(
+ "Int array does not match given number of columns.");
+ }
+ this.numColumns = numColumns;
+ numRows = matrix.length;
+ length = matrix[0].length;
+ int rest = numColumns & 0x1f;
+ int bitMask;
+ if (rest == 0)
+ {
+ bitMask = 0xffffffff;
+ }
+ else
+ {
+ bitMask = (1 << rest) - 1;
+ }
+ for (int i = 0; i < numRows; i++)
+ {
+ matrix[i][length - 1] &= bitMask;
+ }
+ this.matrix = matrix;
+ }
+
+ /**
+ * Create an nxn matrix of the given type.
+ *
+ * @param n the number of rows (and columns)
+ * @param typeOfMatrix the martix type (see {@link Matrix} for predefined
+ * constants)
+ */
+ public GF2Matrix(int n, char typeOfMatrix)
+ {
+ this(n, typeOfMatrix, new java.security.SecureRandom());
+ }
+
+ /**
+ * Create an nxn matrix of the given type.
+ *
+ * @param n the matrix size
+ * @param typeOfMatrix the matrix type
+ * @param sr the source of randomness
+ */
+ public GF2Matrix(int n, char typeOfMatrix, SecureRandom sr)
+ {
+ if (n <= 0)
+ {
+ throw new ArithmeticException("Size of matrix is non-positive.");
+ }
+
+ switch (typeOfMatrix)
+ {
+
+ case Matrix.MATRIX_TYPE_ZERO:
+ assignZeroMatrix(n, n);
+ break;
+
+ case Matrix.MATRIX_TYPE_UNIT:
+ assignUnitMatrix(n);
+ break;
+
+ case Matrix.MATRIX_TYPE_RANDOM_LT:
+ assignRandomLowerTriangularMatrix(n, sr);
+ break;
+
+ case Matrix.MATRIX_TYPE_RANDOM_UT:
+ assignRandomUpperTriangularMatrix(n, sr);
+ break;
+
+ case Matrix.MATRIX_TYPE_RANDOM_REGULAR:
+ assignRandomRegularMatrix(n, sr);
+ break;
+
+ default:
+ throw new ArithmeticException("Unknown matrix type.");
+ }
+ }
+
+ /**
+ * Copy constructor.
+ *
+ * @param a another {@link GF2Matrix}
+ */
+ public GF2Matrix(GF2Matrix a)
+ {
+ numColumns = a.getNumColumns();
+ numRows = a.getNumRows();
+ length = a.length;
+ matrix = new int[a.matrix.length][];
+ for (int i = 0; i < matrix.length; i++)
+ {
+ matrix[i] = IntUtils.clone(a.matrix[i]);
+ }
+
+ }
+
+ /**
+ * create the mxn zero matrix
+ */
+ private GF2Matrix(int m, int n)
+ {
+ if ((n <= 0) || (m <= 0))
+ {
+ throw new ArithmeticException("size of matrix is non-positive");
+ }
+
+ assignZeroMatrix(m, n);
+ }
+
+ /**
+ * Create the mxn zero matrix.
+ *
+ * @param m number of rows
+ * @param n number of columns
+ */
+ private void assignZeroMatrix(int m, int n)
+ {
+ numRows = m;
+ numColumns = n;
+ length = (n + 31) >>> 5;
+ matrix = new int[numRows][length];
+ for (int i = 0; i < numRows; i++)
+ {
+ for (int j = 0; j < length; j++)
+ {
+ matrix[i][j] = 0;
+ }
+ }
+ }
+
+ /**
+ * Create the mxn unit matrix.
+ *
+ * @param n number of rows (and columns)
+ */
+ private void assignUnitMatrix(int n)
+ {
+ numRows = n;
+ numColumns = n;
+ length = (n + 31) >>> 5;
+ matrix = new int[numRows][length];
+ for (int i = 0; i < numRows; i++)
+ {
+ for (int j = 0; j < length; j++)
+ {
+ matrix[i][j] = 0;
+ }
+ }
+ for (int i = 0; i < numRows; i++)
+ {
+ int rest = i & 0x1f;
+ matrix[i][i >>> 5] = 1 << rest;
+ }
+ }
+
+ /**
+ * Create a nxn random lower triangular matrix.
+ *
+ * @param n number of rows (and columns)
+ * @param sr source of randomness
+ */
+ private void assignRandomLowerTriangularMatrix(int n, SecureRandom sr)
+ {
+ numRows = n;
+ numColumns = n;
+ length = (n + 31) >>> 5;
+ matrix = new int[numRows][length];
+ for (int i = 0; i < numRows; i++)
+ {
+ int q = i >>> 5;
+ int r = i & 0x1f;
+ int s = 31 - r;
+ r = 1 << r;
+ for (int j = 0; j < q; j++)
+ {
+ matrix[i][j] = sr.nextInt();
+ }
+ matrix[i][q] = (sr.nextInt() >>> s) | r;
+ for (int j = q + 1; j < length; j++)
+ {
+ matrix[i][j] = 0;
+ }
+
+ }
+
+ }
+
+ /**
+ * Create a nxn random upper triangular matrix.
+ *
+ * @param n number of rows (and columns)
+ * @param sr source of randomness
+ */
+ private void assignRandomUpperTriangularMatrix(int n, SecureRandom sr)
+ {
+ numRows = n;
+ numColumns = n;
+ length = (n + 31) >>> 5;
+ matrix = new int[numRows][length];
+ int rest = n & 0x1f;
+ int help;
+ if (rest == 0)
+ {
+ help = 0xffffffff;
+ }
+ else
+ {
+ help = (1 << rest) - 1;
+ }
+ for (int i = 0; i < numRows; i++)
+ {
+ int q = i >>> 5;
+ int r = i & 0x1f;
+ int s = r;
+ r = 1 << r;
+ for (int j = 0; j < q; j++)
+ {
+ matrix[i][j] = 0;
+ }
+ matrix[i][q] = (sr.nextInt() << s) | r;
+ for (int j = q + 1; j < length; j++)
+ {
+ matrix[i][j] = sr.nextInt();
+ }
+ matrix[i][length - 1] &= help;
+ }
+
+ }
+
+ /**
+ * Create an nxn random regular matrix.
+ *
+ * @param n number of rows (and columns)
+ * @param sr source of randomness
+ */
+ private void assignRandomRegularMatrix(int n, SecureRandom sr)
+ {
+ numRows = n;
+ numColumns = n;
+ length = (n + 31) >>> 5;
+ matrix = new int[numRows][length];
+ GF2Matrix lm = new GF2Matrix(n, Matrix.MATRIX_TYPE_RANDOM_LT, sr);
+ GF2Matrix um = new GF2Matrix(n, Matrix.MATRIX_TYPE_RANDOM_UT, sr);
+ GF2Matrix rm = (GF2Matrix)lm.rightMultiply(um);
+ Permutation perm = new Permutation(n, sr);
+ int[] p = perm.getVector();
+ for (int i = 0; i < n; i++)
+ {
+ System.arraycopy(rm.matrix[i], 0, matrix[p[i]], 0, length);
+ }
+ }
+
+ /**
+ * Create a nxn random regular matrix and its inverse.
+ *
+ * @param n number of rows (and columns)
+ * @param sr source of randomness
+ * @return the created random regular matrix and its inverse
+ */
+ public static GF2Matrix[] createRandomRegularMatrixAndItsInverse(int n,
+ SecureRandom sr)
+ {
+
+ GF2Matrix[] result = new GF2Matrix[2];
+
+ // ------------------------------------
+ // First part: create regular matrix
+ // ------------------------------------
+
+ // ------
+ int length = (n + 31) >> 5;
+ GF2Matrix lm = new GF2Matrix(n, Matrix.MATRIX_TYPE_RANDOM_LT, sr);
+ GF2Matrix um = new GF2Matrix(n, Matrix.MATRIX_TYPE_RANDOM_UT, sr);
+ GF2Matrix rm = (GF2Matrix)lm.rightMultiply(um);
+ Permutation p = new Permutation(n, sr);
+ int[] pVec = p.getVector();
+
+ int[][] matrix = new int[n][length];
+ for (int i = 0; i < n; i++)
+ {
+ System.arraycopy(rm.matrix[pVec[i]], 0, matrix[i], 0, length);
+ }
+
+ result[0] = new GF2Matrix(n, matrix);
+
+ // ------------------------------------
+ // Second part: create inverse matrix
+ // ------------------------------------
+
+ // inverse to lm
+ GF2Matrix invLm = new GF2Matrix(n, Matrix.MATRIX_TYPE_UNIT);
+ for (int i = 0; i < n; i++)
+ {
+ int rest = i & 0x1f;
+ int q = i >>> 5;
+ int r = 1 << rest;
+ for (int j = i + 1; j < n; j++)
+ {
+ int b = (lm.matrix[j][q]) & r;
+ if (b != 0)
+ {
+ for (int k = 0; k <= q; k++)
+ {
+ invLm.matrix[j][k] ^= invLm.matrix[i][k];
+ }
+ }
+ }
+ }
+ // inverse to um
+ GF2Matrix invUm = new GF2Matrix(n, Matrix.MATRIX_TYPE_UNIT);
+ for (int i = n - 1; i >= 0; i--)
+ {
+ int rest = i & 0x1f;
+ int q = i >>> 5;
+ int r = 1 << rest;
+ for (int j = i - 1; j >= 0; j--)
+ {
+ int b = (um.matrix[j][q]) & r;
+ if (b != 0)
+ {
+ for (int k = q; k < length; k++)
+ {
+ invUm.matrix[j][k] ^= invUm.matrix[i][k];
+ }
+ }
+ }
+ }
+
+ // inverse matrix
+ result[1] = (GF2Matrix)invUm.rightMultiply(invLm.rightMultiply(p));
+
+ return result;
+ }
+
+ /**
+ * @return the array keeping the matrix elements
+ */
+ public int[][] getIntArray()
+ {
+ return matrix;
+ }
+
+ /**
+ * @return the length of each array representing a row of this matrix
+ */
+ public int getLength()
+ {
+ return length;
+ }
+
+ /**
+ * Return the row of this matrix with the given index.
+ *
+ * @param index the index
+ * @return the row of this matrix with the given index
+ */
+ public int[] getRow(int index)
+ {
+ return matrix[index];
+ }
+
+ /**
+ * Returns encoded matrix, i.e., this matrix in byte array form
+ *
+ * @return the encoded matrix
+ */
+ public byte[] getEncoded()
+ {
+ int n = (numColumns + 7) >>> 3;
+ n *= numRows;
+ n += 8;
+ byte[] enc = new byte[n];
+
+ LittleEndianConversions.I2OSP(numRows, enc, 0);
+ LittleEndianConversions.I2OSP(numColumns, enc, 4);
+
+ // number of "full" integer
+ int q = numColumns >>> 5;
+ // number of bits in non-full integer
+ int r = numColumns & 0x1f;
+
+ int count = 8;
+ for (int i = 0; i < numRows; i++)
+ {
+ for (int j = 0; j < q; j++, count += 4)
+ {
+ LittleEndianConversions.I2OSP(matrix[i][j], enc, count);
+ }
+ for (int j = 0; j < r; j += 8)
+ {
+ enc[count++] = (byte)((matrix[i][q] >>> j) & 0xff);
+ }
+
+ }
+ return enc;
+ }
+
+
+ /**
+ * Returns the percentage of the number of "ones" in this matrix.
+ *
+ * @return the Hamming weight of this matrix (as a ratio).
+ */
+ public double getHammingWeight()
+ {
+ double counter = 0.0;
+ double elementCounter = 0.0;
+ int rest = numColumns & 0x1f;
+ int d;
+ if (rest == 0)
+ {
+ d = length;
+ }
+ else
+ {
+ d = length - 1;
+ }
+
+ for (int i = 0; i < numRows; i++)
+ {
+
+ for (int j = 0; j < d; j++)
+ {
+ int a = matrix[i][j];
+ for (int k = 0; k < 32; k++)
+ {
+ int b = (a >>> k) & 1;
+ counter = counter + b;
+ elementCounter = elementCounter + 1;
+ }
+ }
+ int a = matrix[i][length - 1];
+ for (int k = 0; k < rest; k++)
+ {
+ int b = (a >>> k) & 1;
+ counter = counter + b;
+ elementCounter = elementCounter + 1;
+ }
+ }
+
+ return counter / elementCounter;
+ }
+
+ /**
+ * Check if this is the zero matrix (i.e., all entries are zero).
+ *
+ * @return <tt>true</tt> if this is the zero matrix
+ */
+ public boolean isZero()
+ {
+ for (int i = 0; i < numRows; i++)
+ {
+ for (int j = 0; j < length; j++)
+ {
+ if (matrix[i][j] != 0)
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Get the quadratic submatrix of this matrix consisting of the leftmost
+ * <tt>numRows</tt> columns.
+ *
+ * @return the <tt>(numRows x numRows)</tt> submatrix
+ */
+ public GF2Matrix getLeftSubMatrix()
+ {
+ if (numColumns <= numRows)
+ {
+ throw new ArithmeticException("empty submatrix");
+ }
+ int length = (numRows + 31) >> 5;
+ int[][] result = new int[numRows][length];
+ int bitMask = (1 << (numRows & 0x1f)) - 1;
+ if (bitMask == 0)
+ {
+ bitMask = -1;
+ }
+ for (int i = numRows - 1; i >= 0; i--)
+ {
+ System.arraycopy(matrix[i], 0, result[i], 0, length);
+ result[i][length - 1] &= bitMask;
+ }
+ return new GF2Matrix(numRows, result);
+ }
+
+ /**
+ * Compute the full form matrix <tt>(this | Id)</tt> from this matrix in
+ * left compact form, where <tt>Id</tt> is the <tt>k x k</tt> identity
+ * matrix and <tt>k</tt> is the number of rows of this matrix.
+ *
+ * @return <tt>(this | Id)</tt>
+ */
+ public GF2Matrix extendLeftCompactForm()
+ {
+ int newNumColumns = numColumns + numRows;
+ GF2Matrix result = new GF2Matrix(numRows, newNumColumns);
+
+ int ind = numRows - 1 + numColumns;
+ for (int i = numRows - 1; i >= 0; i--, ind--)
+ {
+ // copy this matrix to first columns
+ System.arraycopy(matrix[i], 0, result.matrix[i], 0, length);
+ // store the identity in last columns
+ result.matrix[i][ind >> 5] |= 1 << (ind & 0x1f);
+ }
+
+ return result;
+ }
+
+ /**
+ * Get the submatrix of this matrix consisting of the rightmost
+ * <tt>numColumns-numRows</tt> columns.
+ *
+ * @return the <tt>(numRows x (numColumns-numRows))</tt> submatrix
+ */
+ public GF2Matrix getRightSubMatrix()
+ {
+ if (numColumns <= numRows)
+ {
+ throw new ArithmeticException("empty submatrix");
+ }
+
+ int q = numRows >> 5;
+ int r = numRows & 0x1f;
+
+ GF2Matrix result = new GF2Matrix(numRows, numColumns - numRows);
+
+ for (int i = numRows - 1; i >= 0; i--)
+ {
+ // if words have to be shifted
+ if (r != 0)
+ {
+ int ind = q;
+ // process all but last word
+ for (int j = 0; j < result.length - 1; j++)
+ {
+ // shift to correct position
+ result.matrix[i][j] = (matrix[i][ind++] >>> r)
+ | (matrix[i][ind] << (32 - r));
+ }
+ // process last word
+ result.matrix[i][result.length - 1] = matrix[i][ind++] >>> r;
+ if (ind < length)
+ {
+ result.matrix[i][result.length - 1] |= matrix[i][ind] << (32 - r);
+ }
+ }
+ else
+ {
+ // no shifting necessary
+ System.arraycopy(matrix[i], q, result.matrix[i], 0,
+ result.length);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Compute the full form matrix <tt>(Id | this)</tt> from this matrix in
+ * right compact form, where <tt>Id</tt> is the <tt>k x k</tt> identity
+ * matrix and <tt>k</tt> is the number of rows of this matrix.
+ *
+ * @return <tt>(Id | this)</tt>
+ */
+ public GF2Matrix extendRightCompactForm()
+ {
+ GF2Matrix result = new GF2Matrix(numRows, numRows + numColumns);
+
+ int q = numRows >> 5;
+ int r = numRows & 0x1f;
+
+ for (int i = numRows - 1; i >= 0; i--)
+ {
+ // store the identity in first columns
+ result.matrix[i][i >> 5] |= 1 << (i & 0x1f);
+
+ // copy this matrix to last columns
+
+ // if words have to be shifted
+ if (r != 0)
+ {
+ int ind = q;
+ // process all but last word
+ for (int j = 0; j < length - 1; j++)
+ {
+ // obtain matrix word
+ int mw = matrix[i][j];
+ // shift to correct position
+ result.matrix[i][ind++] |= mw << r;
+ result.matrix[i][ind] |= mw >>> (32 - r);
+ }
+ // process last word
+ int mw = matrix[i][length - 1];
+ result.matrix[i][ind++] |= mw << r;
+ if (ind < result.length)
+ {
+ result.matrix[i][ind] |= mw >>> (32 - r);
+ }
+ }
+ else
+ {
+ // no shifting necessary
+ System.arraycopy(matrix[i], 0, result.matrix[i], q, length);
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Compute the transpose of this matrix.
+ *
+ * @return <tt>(this)<sup>T</sup></tt>
+ */
+ public Matrix computeTranspose()
+ {
+ int[][] result = new int[numColumns][(numRows + 31) >>> 5];
+ for (int i = 0; i < numRows; i++)
+ {
+ for (int j = 0; j < numColumns; j++)
+ {
+ int qs = j >>> 5;
+ int rs = j & 0x1f;
+ int b = (matrix[i][qs] >>> rs) & 1;
+ int qt = i >>> 5;
+ int rt = i & 0x1f;
+ if (b == 1)
+ {
+ result[j][qt] |= 1 << rt;
+ }
+ }
+ }
+
+ return new GF2Matrix(numRows, result);
+ }
+
+ /**
+ * Compute the inverse of this matrix.
+ *
+ * @return the inverse of this matrix (newly created).
+ * @throws ArithmeticException if this matrix is not invertible.
+ */
+ public Matrix computeInverse()
+ {
+ if (numRows != numColumns)
+ {
+ throw new ArithmeticException("Matrix is not invertible.");
+ }
+
+ // clone this matrix
+ int[][] tmpMatrix = new int[numRows][length];
+ for (int i = numRows - 1; i >= 0; i--)
+ {
+ tmpMatrix[i] = IntUtils.clone(matrix[i]);
+ }
+
+ // initialize inverse matrix as unit matrix
+ int[][] invMatrix = new int[numRows][length];
+ for (int i = numRows - 1; i >= 0; i--)
+ {
+ int q = i >> 5;
+ int r = i & 0x1f;
+ invMatrix[i][q] = 1 << r;
+ }
+
+ // simultaneously compute Gaussian reduction of tmpMatrix and unit
+ // matrix
+ for (int i = 0; i < numRows; i++)
+ {
+ // i = q * 32 + (i mod 32)
+ int q = i >> 5;
+ int bitMask = 1 << (i & 0x1f);
+ // if diagonal element is zero
+ if ((tmpMatrix[i][q] & bitMask) == 0)
+ {
+ boolean foundNonZero = false;
+ // find a non-zero element in the same column
+ for (int j = i + 1; j < numRows; j++)
+ {
+ if ((tmpMatrix[j][q] & bitMask) != 0)
+ {
+ // found it, swap rows ...
+ foundNonZero = true;
+ swapRows(tmpMatrix, i, j);
+ swapRows(invMatrix, i, j);
+ // ... and quit searching
+ j = numRows;
+ continue;
+ }
+ }
+ // if no non-zero element was found ...
+ if (!foundNonZero)
+ {
+ // ... the matrix is not invertible
+ throw new ArithmeticException("Matrix is not invertible.");
+ }
+ }
+
+ // normalize all but i-th row
+ for (int j = numRows - 1; j >= 0; j--)
+ {
+ if ((j != i) && ((tmpMatrix[j][q] & bitMask) != 0))
+ {
+ addToRow(tmpMatrix[i], tmpMatrix[j], q);
+ addToRow(invMatrix[i], invMatrix[j], 0);
+ }
+ }
+ }
+
+ return new GF2Matrix(numColumns, invMatrix);
+ }
+
+ /**
+ * Compute the product of a permutation matrix (which is generated from an
+ * n-permutation) and this matrix.
+ *
+ * @param p the permutation
+ * @return {@link GF2Matrix} <tt>P*this</tt>
+ */
+ public Matrix leftMultiply(Permutation p)
+ {
+ int[] pVec = p.getVector();
+ if (pVec.length != numRows)
+ {
+ throw new ArithmeticException("length mismatch");
+ }
+
+ int[][] result = new int[numRows][];
+
+ for (int i = numRows - 1; i >= 0; i--)
+ {
+ result[i] = IntUtils.clone(matrix[pVec[i]]);
+ }
+
+ return new GF2Matrix(numRows, result);
+ }
+
+ /**
+ * compute product a row vector and this matrix
+ *
+ * @param vec a vector over GF(2)
+ * @return Vector product a*matrix
+ */
+ public Vector leftMultiply(Vector vec)
+ {
+
+ if (!(vec instanceof GF2Vector))
+ {
+ throw new ArithmeticException("vector is not defined over GF(2)");
+ }
+
+ if (vec.length != numRows)
+ {
+ throw new ArithmeticException("length mismatch");
+ }
+
+ int[] v = ((GF2Vector)vec).getVecArray();
+ int[] res = new int[length];
+
+ int q = numRows >> 5;
+ int r = 1 << (numRows & 0x1f);
+
+ // compute scalar products with full words of vector
+ int row = 0;
+ for (int i = 0; i < q; i++)
+ {
+ int bitMask = 1;
+ do
+ {
+ int b = v[i] & bitMask;
+ if (b != 0)
+ {
+ for (int j = 0; j < length; j++)
+ {
+ res[j] ^= matrix[row][j];
+ }
+ }
+ row++;
+ bitMask <<= 1;
+ }
+ while (bitMask != 0);
+ }
+
+ // compute scalar products with last word of vector
+ int bitMask = 1;
+ while (bitMask != r)
+ {
+ int b = v[q] & bitMask;
+ if (b != 0)
+ {
+ for (int j = 0; j < length; j++)
+ {
+ res[j] ^= matrix[row][j];
+ }
+ }
+ row++;
+ bitMask <<= 1;
+ }
+
+ return new GF2Vector(res, numColumns);
+ }
+
+ /**
+ * Compute the product of the matrix <tt>(this | Id)</tt> and a column
+ * vector, where <tt>Id</tt> is a <tt>(numRows x numRows)</tt> unit
+ * matrix.
+ *
+ * @param vec the vector over GF(2)
+ * @return <tt>(this | Id)*vector</tt>
+ */
+ public Vector leftMultiplyLeftCompactForm(Vector vec)
+ {
+ if (!(vec instanceof GF2Vector))
+ {
+ throw new ArithmeticException("vector is not defined over GF(2)");
+ }
+
+ if (vec.length != numRows)
+ {
+ throw new ArithmeticException("length mismatch");
+ }
+
+ int[] v = ((GF2Vector)vec).getVecArray();
+ int[] res = new int[(numRows + numColumns + 31) >>> 5];
+
+ // process full words of vector
+ int words = numRows >>> 5;
+ int row = 0;
+ for (int i = 0; i < words; i++)
+ {
+ int bitMask = 1;
+ do
+ {
+ int b = v[i] & bitMask;
+ if (b != 0)
+ {
+ // compute scalar product part
+ for (int j = 0; j < length; j++)
+ {
+ res[j] ^= matrix[row][j];
+ }
+ // set last bit
+ int q = (numColumns + row) >>> 5;
+ int r = (numColumns + row) & 0x1f;
+ res[q] |= 1 << r;
+ }
+ row++;
+ bitMask <<= 1;
+ }
+ while (bitMask != 0);
+ }
+
+ // process last word of vector
+ int rem = 1 << (numRows & 0x1f);
+ int bitMask = 1;
+ while (bitMask != rem)
+ {
+ int b = v[words] & bitMask;
+ if (b != 0)
+ {
+ // compute scalar product part
+ for (int j = 0; j < length; j++)
+ {
+ res[j] ^= matrix[row][j];
+ }
+ // set last bit
+ int q = (numColumns + row) >>> 5;
+ int r = (numColumns + row) & 0x1f;
+ res[q] |= 1 << r;
+ }
+ row++;
+ bitMask <<= 1;
+ }
+
+ return new GF2Vector(res, numRows + numColumns);
+ }
+
+ /**
+ * Compute the product of this matrix and a matrix A over GF(2).
+ *
+ * @param mat a matrix A over GF(2)
+ * @return matrix product <tt>this*matrixA</tt>
+ */
+ public Matrix rightMultiply(Matrix mat)
+ {
+ if (!(mat instanceof GF2Matrix))
+ {
+ throw new ArithmeticException("matrix is not defined over GF(2)");
+ }
+
+ if (mat.numRows != numColumns)
+ {
+ throw new ArithmeticException("length mismatch");
+ }
+
+ GF2Matrix a = (GF2Matrix)mat;
+ GF2Matrix result = new GF2Matrix(numRows, mat.numColumns);
+
+ int d;
+ int rest = numColumns & 0x1f;
+ if (rest == 0)
+ {
+ d = length;
+ }
+ else
+ {
+ d = length - 1;
+ }
+ for (int i = 0; i < numRows; i++)
+ {
+ int count = 0;
+ for (int j = 0; j < d; j++)
+ {
+ int e = matrix[i][j];
+ for (int h = 0; h < 32; h++)
+ {
+ int b = e & (1 << h);
+ if (b != 0)
+ {
+ for (int g = 0; g < a.length; g++)
+ {
+ result.matrix[i][g] ^= a.matrix[count][g];
+ }
+ }
+ count++;
+ }
+ }
+ int e = matrix[i][length - 1];
+ for (int h = 0; h < rest; h++)
+ {
+ int b = e & (1 << h);
+ if (b != 0)
+ {
+ for (int g = 0; g < a.length; g++)
+ {
+ result.matrix[i][g] ^= a.matrix[count][g];
+ }
+ }
+ count++;
+ }
+
+ }
+
+ return result;
+ }
+
+ /**
+ * Compute the product of this matrix and a permutation matrix which is
+ * generated from an n-permutation.
+ *
+ * @param p the permutation
+ * @return {@link GF2Matrix} <tt>this*P</tt>
+ */
+ public Matrix rightMultiply(Permutation p)
+ {
+
+ int[] pVec = p.getVector();
+ if (pVec.length != numColumns)
+ {
+ throw new ArithmeticException("length mismatch");
+ }
+
+ GF2Matrix result = new GF2Matrix(numRows, numColumns);
+
+ for (int i = numColumns - 1; i >= 0; i--)
+ {
+ int q = i >>> 5;
+ int r = i & 0x1f;
+ int pq = pVec[i] >>> 5;
+ int pr = pVec[i] & 0x1f;
+ for (int j = numRows - 1; j >= 0; j--)
+ {
+ result.matrix[j][q] |= ((matrix[j][pq] >>> pr) & 1) << r;
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Compute the product of this matrix and the given column vector.
+ *
+ * @param vec the vector over GF(2)
+ * @return <tt>this*vector</tt>
+ */
+ public Vector rightMultiply(Vector vec)
+ {
+ if (!(vec instanceof GF2Vector))
+ {
+ throw new ArithmeticException("vector is not defined over GF(2)");
+ }
+
+ if (vec.length != numColumns)
+ {
+ throw new ArithmeticException("length mismatch");
+ }
+
+ int[] v = ((GF2Vector)vec).getVecArray();
+ int[] res = new int[(numRows + 31) >>> 5];
+
+ for (int i = 0; i < numRows; i++)
+ {
+ // compute full word scalar products
+ int help = 0;
+ for (int j = 0; j < length; j++)
+ {
+ help ^= matrix[i][j] & v[j];
+ }
+ // compute single word scalar product
+ int bitValue = 0;
+ for (int j = 0; j < 32; j++)
+ {
+ bitValue ^= (help >>> j) & 1;
+ }
+ // set result bit
+ if (bitValue == 1)
+ {
+ res[i >>> 5] |= 1 << (i & 0x1f);
+ }
+ }
+
+ return new GF2Vector(res, numRows);
+ }
+
+ /**
+ * Compute the product of the matrix <tt>(Id | this)</tt> and a column
+ * vector, where <tt>Id</tt> is a <tt>(numRows x numRows)</tt> unit
+ * matrix.
+ *
+ * @param vec the vector over GF(2)
+ * @return <tt>(Id | this)*vector</tt>
+ */
+ public Vector rightMultiplyRightCompactForm(Vector vec)
+ {
+ if (!(vec instanceof GF2Vector))
+ {
+ throw new ArithmeticException("vector is not defined over GF(2)");
+ }
+
+ if (vec.length != numColumns + numRows)
+ {
+ throw new ArithmeticException("length mismatch");
+ }
+
+ int[] v = ((GF2Vector)vec).getVecArray();
+ int[] res = new int[(numRows + 31) >>> 5];
+
+ int q = numRows >> 5;
+ int r = numRows & 0x1f;
+
+ // for all rows
+ for (int i = 0; i < numRows; i++)
+ {
+ // get vector bit
+ int help = (v[i >> 5] >>> (i & 0x1f)) & 1;
+
+ // compute full word scalar products
+ int vInd = q;
+ // if words have to be shifted
+ if (r != 0)
+ {
+ int vw = 0;
+ // process all but last word
+ for (int j = 0; j < length - 1; j++)
+ {
+ // shift to correct position
+ vw = (v[vInd++] >>> r) | (v[vInd] << (32 - r));
+ help ^= matrix[i][j] & vw;
+ }
+ // process last word
+ vw = v[vInd++] >>> r;
+ if (vInd < v.length)
+ {
+ vw |= v[vInd] << (32 - r);
+ }
+ help ^= matrix[i][length - 1] & vw;
+ }
+ else
+ {
+ // no shifting necessary
+ for (int j = 0; j < length; j++)
+ {
+ help ^= matrix[i][j] & v[vInd++];
+ }
+ }
+
+ // compute single word scalar product
+ int bitValue = 0;
+ for (int j = 0; j < 32; j++)
+ {
+ bitValue ^= help & 1;
+ help >>>= 1;
+ }
+
+ // set result bit
+ if (bitValue == 1)
+ {
+ res[i >> 5] |= 1 << (i & 0x1f);
+ }
+ }
+
+ return new GF2Vector(res, numRows);
+ }
+
+ /**
+ * Compare this matrix with another object.
+ *
+ * @param other another object
+ * @return the result of the comparison
+ */
+ public boolean equals(Object other)
+ {
+
+ if (!(other instanceof GF2Matrix))
+ {
+ return false;
+ }
+ GF2Matrix otherMatrix = (GF2Matrix)other;
+
+ if ((numRows != otherMatrix.numRows)
+ || (numColumns != otherMatrix.numColumns)
+ || (length != otherMatrix.length))
+ {
+ return false;
+ }
+
+ for (int i = 0; i < numRows; i++)
+ {
+ if (!IntUtils.equals(matrix[i], otherMatrix.matrix[i]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * @return the hash code of this matrix
+ */
+ public int hashCode()
+ {
+ int hash = (numRows * 31 + numColumns) * 31 + length;
+ for (int i = 0; i < numRows; i++)
+ {
+ hash = hash * 31 + matrix[i].hashCode();
+ }
+ return hash;
+ }
+
+ /**
+ * @return a human readable form of the matrix
+ */
+ public String toString()
+ {
+ int rest = numColumns & 0x1f;
+ int d;
+ if (rest == 0)
+ {
+ d = length;
+ }
+ else
+ {
+ d = length - 1;
+ }
+
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < numRows; i++)
+ {
+ buf.append(i + ": ");
+ for (int j = 0; j < d; j++)
+ {
+ int a = matrix[i][j];
+ for (int k = 0; k < 32; k++)
+ {
+ int b = (a >>> k) & 1;
+ if (b == 0)
+ {
+ buf.append('0');
+ }
+ else
+ {
+ buf.append('1');
+ }
+ }
+ buf.append(' ');
+ }
+ int a = matrix[i][length - 1];
+ for (int k = 0; k < rest; k++)
+ {
+ int b = (a >>> k) & 1;
+ if (b == 0)
+ {
+ buf.append('0');
+ }
+ else
+ {
+ buf.append('1');
+ }
+ }
+ buf.append('\n');
+ }
+
+ return buf.toString();
+ }
+
+ /**
+ * Swap two rows of the given matrix.
+ *
+ * @param matrix the matrix
+ * @param first the index of the first row
+ * @param second the index of the second row
+ */
+ private static void swapRows(int[][] matrix, int first, int second)
+ {
+ int[] tmp = matrix[first];
+ matrix[first] = matrix[second];
+ matrix[second] = tmp;
+ }
+
+ /**
+ * Partially add one row to another.
+ *
+ * @param fromRow the addend
+ * @param toRow the row to add to
+ * @param startIndex the array index to start from
+ */
+ private static void addToRow(int[] fromRow, int[] toRow, int startIndex)
+ {
+ for (int i = toRow.length - 1; i >= startIndex; i--)
+ {
+ toRow[i] = fromRow[i] ^ toRow[i];
+ }
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2Polynomial.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2Polynomial.java
new file mode 100644
index 00000000..25bf099a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2Polynomial.java
@@ -0,0 +1,2039 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+
+import java.math.BigInteger;
+import java.util.Random;
+
+
+/**
+ * This class stores very long strings of bits and does some basic arithmetics.
+ * It is used by <tt>GF2nField</tt>, <tt>GF2nPolynomialField</tt> and
+ * <tt>GFnPolynomialElement</tt>.
+ *
+ * @see GF2nPolynomialElement
+ * @see GF2nField
+ */
+public class GF2Polynomial
+{
+
+ // number of bits stored in this GF2Polynomial
+ private int len;
+
+ // number of int used in value
+ private int blocks;
+
+ // storage
+ private int[] value;
+
+ // Random source
+ private static Random rand = new Random();
+
+ // Lookup-Table for vectorMult: parity[a]= #1(a) mod 2 == 1
+ private static final boolean[] parity = {false, true, true, false, true,
+ false, false, true, true, false, false, true, false, true, true,
+ false, true, false, false, true, false, true, true, false, false,
+ true, true, false, true, false, false, true, true, false, false,
+ true, false, true, true, false, false, true, true, false, true,
+ false, false, true, false, true, true, false, true, false, false,
+ true, true, false, false, true, false, true, true, false, true,
+ false, false, true, false, true, true, false, false, true, true,
+ false, true, false, false, true, false, true, true, false, true,
+ false, false, true, true, false, false, true, false, true, true,
+ false, false, true, true, false, true, false, false, true, true,
+ false, false, true, false, true, true, false, true, false, false,
+ true, false, true, true, false, false, true, true, false, true,
+ false, false, true, true, false, false, true, false, true, true,
+ false, false, true, true, false, true, false, false, true, false,
+ true, true, false, true, false, false, true, true, false, false,
+ true, false, true, true, false, false, true, true, false, true,
+ false, false, true, true, false, false, true, false, true, true,
+ false, true, false, false, true, false, true, true, false, false,
+ true, true, false, true, false, false, true, false, true, true,
+ false, true, false, false, true, true, false, false, true, false,
+ true, true, false, true, false, false, true, false, true, true,
+ false, false, true, true, false, true, false, false, true, true,
+ false, false, true, false, true, true, false, false, true, true,
+ false, true, false, false, true, false, true, true, false, true,
+ false, false, true, true, false, false, true, false, true, true,
+ false};
+
+ // Lookup-Table for Squaring: squaringTable[a]=a^2
+ private static final short[] squaringTable = {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};
+
+ // pre-computed Bitmask for fast masking, bitMask[a]=0x1 << a
+ private static final int[] bitMask = {0x00000001, 0x00000002, 0x00000004,
+ 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080,
+ 0x00000100, 0x00000200, 0x00000400, 0x00000800, 0x00001000,
+ 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000,
+ 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000,
+ 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000,
+ 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x00000000};
+
+ // pre-computed Bitmask for fast masking, rightMask[a]=0xffffffff >>> (32-a)
+ private static final int[] reverseRightMask = {0x00000000, 0x00000001,
+ 0x00000003, 0x00000007, 0x0000000f, 0x0000001f, 0x0000003f,
+ 0x0000007f, 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
+ 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
+ 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff, 0x001fffff,
+ 0x003fffff, 0x007fffff, 0x00ffffff, 0x01ffffff, 0x03ffffff,
+ 0x07ffffff, 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
+ 0xffffffff};
+
+ /**
+ * Creates a new GF2Polynomial of the given <i>length</i> and value zero.
+ *
+ * @param length the desired number of bits to store
+ */
+ public GF2Polynomial(int length)
+ {
+ int l = length;
+ if (l < 1)
+ {
+ l = 1;
+ }
+ blocks = ((l - 1) >> 5) + 1;
+ value = new int[blocks];
+ len = l;
+ }
+
+ /**
+ * Creates a new GF2Polynomial of the given <i>length</i> and random value.
+ *
+ * @param length the desired number of bits to store
+ * @param rand SecureRandom to use for randomization
+ */
+ public GF2Polynomial(int length, Random rand)
+ {
+ int l = length;
+ if (l < 1)
+ {
+ l = 1;
+ }
+ blocks = ((l - 1) >> 5) + 1;
+ value = new int[blocks];
+ len = l;
+ randomize(rand);
+ }
+
+ /**
+ * Creates a new GF2Polynomial of the given <i>length</i> and value
+ * selected by <i>value</i>:
+ * <UL>
+ * <LI>ZERO</LI>
+ * <LI>ONE</LI>
+ * <LI>RANDOM</LI>
+ * <LI>X</LI>
+ * <LI>ALL</LI>
+ * </UL>
+ *
+ * @param length the desired number of bits to store
+ * @param value the value described by a String
+ */
+ public GF2Polynomial(int length, String value)
+ {
+ int l = length;
+ if (l < 1)
+ {
+ l = 1;
+ }
+ blocks = ((l - 1) >> 5) + 1;
+ this.value = new int[blocks];
+ len = l;
+ if (value.equalsIgnoreCase("ZERO"))
+ {
+ assignZero();
+ }
+ else if (value.equalsIgnoreCase("ONE"))
+ {
+ assignOne();
+ }
+ else if (value.equalsIgnoreCase("RANDOM"))
+ {
+ randomize();
+ }
+ else if (value.equalsIgnoreCase("X"))
+ {
+ assignX();
+ }
+ else if (value.equalsIgnoreCase("ALL"))
+ {
+ assignAll();
+ }
+ else
+ {
+ throw new IllegalArgumentException(
+ "Error: GF2Polynomial was called using " + value
+ + " as value!");
+ }
+
+ }
+
+ /**
+ * Creates a new GF2Polynomial of the given <i>length</i> using the given
+ * int[]. LSB is contained in bs[0].
+ *
+ * @param length the desired number of bits to store
+ * @param bs contains the desired value, LSB in bs[0]
+ */
+ public GF2Polynomial(int length, int[] bs)
+ {
+ int leng = length;
+ if (leng < 1)
+ {
+ leng = 1;
+ }
+ blocks = ((leng - 1) >> 5) + 1;
+ value = new int[blocks];
+ len = leng;
+ int l = Math.min(blocks, bs.length);
+ System.arraycopy(bs, 0, value, 0, l);
+ zeroUnusedBits();
+ }
+
+ /**
+ * Creates a new GF2Polynomial by converting the given byte[] <i>os</i>
+ * according to 1363 and using the given <i>length</i>.
+ *
+ * @param length the intended length of this polynomial
+ * @param os the octet string to assign to this polynomial
+ * @see "P1363 5.5.2 p22f, OS2BSP"
+ */
+ public GF2Polynomial(int length, byte[] os)
+ {
+ int l = length;
+ if (l < 1)
+ {
+ l = 1;
+ }
+ blocks = ((l - 1) >> 5) + 1;
+ value = new int[blocks];
+ len = l;
+ int i, m;
+ int k = Math.min(((os.length - 1) >> 2) + 1, blocks);
+ for (i = 0; i < k - 1; i++)
+ {
+ m = os.length - (i << 2) - 1;
+ value[i] = (os[m]) & 0x000000ff;
+ value[i] |= (os[m - 1] << 8) & 0x0000ff00;
+ value[i] |= (os[m - 2] << 16) & 0x00ff0000;
+ value[i] |= (os[m - 3] << 24) & 0xff000000;
+ }
+ i = k - 1;
+ m = os.length - (i << 2) - 1;
+ value[i] = os[m] & 0x000000ff;
+ if (m > 0)
+ {
+ value[i] |= (os[m - 1] << 8) & 0x0000ff00;
+ }
+ if (m > 1)
+ {
+ value[i] |= (os[m - 2] << 16) & 0x00ff0000;
+ }
+ if (m > 2)
+ {
+ value[i] |= (os[m - 3] << 24) & 0xff000000;
+ }
+ zeroUnusedBits();
+ reduceN();
+ }
+
+ /**
+ * Creates a new GF2Polynomial by converting the given FlexiBigInt <i>bi</i>
+ * according to 1363 and using the given <i>length</i>.
+ *
+ * @param length the intended length of this polynomial
+ * @param bi the FlexiBigInt to assign to this polynomial
+ * @see "P1363 5.5.1 p22, I2BSP"
+ */
+ public GF2Polynomial(int length, BigInteger bi)
+ {
+ int l = length;
+ if (l < 1)
+ {
+ l = 1;
+ }
+ blocks = ((l - 1) >> 5) + 1;
+ value = new int[blocks];
+ len = l;
+ int i;
+ byte[] val = bi.toByteArray();
+ if (val[0] == 0)
+ {
+ byte[] dummy = new byte[val.length - 1];
+ System.arraycopy(val, 1, dummy, 0, dummy.length);
+ val = dummy;
+ }
+ int ov = val.length & 0x03;
+ int k = ((val.length - 1) >> 2) + 1;
+ for (i = 0; i < ov; i++)
+ {
+ value[k - 1] |= (val[i] & 0x000000ff) << ((ov - 1 - i) << 3);
+ }
+ int m = 0;
+ for (i = 0; i <= (val.length - 4) >> 2; i++)
+ {
+ m = val.length - 1 - (i << 2);
+ value[i] = (val[m]) & 0x000000ff;
+ value[i] |= ((val[m - 1]) << 8) & 0x0000ff00;
+ value[i] |= ((val[m - 2]) << 16) & 0x00ff0000;
+ value[i] |= ((val[m - 3]) << 24) & 0xff000000;
+ }
+ if ((len & 0x1f) != 0)
+ {
+ value[blocks - 1] &= reverseRightMask[len & 0x1f];
+ }
+ reduceN();
+ }
+
+ /**
+ * Creates a new GF2Polynomial by cloneing the given GF2Polynomial <i>b</i>.
+ *
+ * @param b the GF2Polynomial to clone
+ */
+ public GF2Polynomial(GF2Polynomial b)
+ {
+ len = b.len;
+ blocks = b.blocks;
+ value = IntUtils.clone(b.value);
+ }
+
+ /**
+ * @return a copy of this GF2Polynomial
+ */
+ public Object clone()
+ {
+ return new GF2Polynomial(this);
+ }
+
+ /**
+ * Returns the length of this GF2Polynomial. The length can be greater than
+ * the degree. To get the degree call reduceN() before calling getLength().
+ *
+ * @return the length of this GF2Polynomial
+ */
+ public int getLength()
+ {
+ return len;
+ }
+
+ /**
+ * Returns the value of this GF2Polynomial in an int[].
+ *
+ * @return the value of this GF2Polynomial in a new int[], LSB in int[0]
+ */
+ public int[] toIntegerArray()
+ {
+ int[] result;
+ result = new int[blocks];
+ System.arraycopy(value, 0, result, 0, blocks);
+ return result;
+ }
+
+ /**
+ * Returns a string representing this GF2Polynomials value using hexadecimal
+ * or binary radix in MSB-first order.
+ *
+ * @param radix the radix to use (2 or 16, otherwise 2 is used)
+ * @return a String representing this GF2Polynomials value.
+ */
+ public String toString(int radix)
+ {
+ final char[] HEX_CHARS = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
+ '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+ final String[] BIN_CHARS = {"0000", "0001", "0010", "0011", "0100",
+ "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100",
+ "1101", "1110", "1111"};
+ String res;
+ int i;
+ res = new String();
+ if (radix == 16)
+ {
+ for (i = blocks - 1; i >= 0; i--)
+ {
+ res += HEX_CHARS[(value[i] >>> 28) & 0x0f];
+ res += HEX_CHARS[(value[i] >>> 24) & 0x0f];
+ res += HEX_CHARS[(value[i] >>> 20) & 0x0f];
+ res += HEX_CHARS[(value[i] >>> 16) & 0x0f];
+ res += HEX_CHARS[(value[i] >>> 12) & 0x0f];
+ res += HEX_CHARS[(value[i] >>> 8) & 0x0f];
+ res += HEX_CHARS[(value[i] >>> 4) & 0x0f];
+ res += HEX_CHARS[(value[i]) & 0x0f];
+ res += " ";
+ }
+ }
+ else
+ {
+ for (i = blocks - 1; i >= 0; i--)
+ {
+ res += BIN_CHARS[(value[i] >>> 28) & 0x0f];
+ res += BIN_CHARS[(value[i] >>> 24) & 0x0f];
+ res += BIN_CHARS[(value[i] >>> 20) & 0x0f];
+ res += BIN_CHARS[(value[i] >>> 16) & 0x0f];
+ res += BIN_CHARS[(value[i] >>> 12) & 0x0f];
+ res += BIN_CHARS[(value[i] >>> 8) & 0x0f];
+ res += BIN_CHARS[(value[i] >>> 4) & 0x0f];
+ res += BIN_CHARS[(value[i]) & 0x0f];
+ res += " ";
+ }
+ }
+ return res;
+ }
+
+ /**
+ * Converts this polynomial to a byte[] (octet string) according to 1363.
+ *
+ * @return a byte[] representing the value of this polynomial
+ * @see "P1363 5.5.2 p22f, BS2OSP"
+ */
+ public byte[] toByteArray()
+ {
+ int k = ((len - 1) >> 3) + 1;
+ int ov = k & 0x03;
+ int m;
+ byte[] res = new byte[k];
+ int i;
+ for (i = 0; i < (k >> 2); i++)
+ {
+ m = k - (i << 2) - 1;
+ res[m] = (byte)((value[i] & 0x000000ff));
+ res[m - 1] = (byte)((value[i] & 0x0000ff00) >>> 8);
+ res[m - 2] = (byte)((value[i] & 0x00ff0000) >>> 16);
+ res[m - 3] = (byte)((value[i] & 0xff000000) >>> 24);
+ }
+ for (i = 0; i < ov; i++)
+ {
+ m = (ov - i - 1) << 3;
+ res[i] = (byte)((value[blocks - 1] & (0x000000ff << m)) >>> m);
+ }
+ return res;
+ }
+
+ /**
+ * Converts this polynomial to an integer according to 1363.
+ *
+ * @return a FlexiBigInt representing the value of this polynomial
+ * @see "P1363 5.5.1 p22, BS2IP"
+ */
+ public BigInteger toFlexiBigInt()
+ {
+ if (len == 0 || isZero())
+ {
+ return new BigInteger(0, new byte[0]);
+ }
+ return new BigInteger(1, toByteArray());
+ }
+
+ /**
+ * Sets the LSB to 1 and all other to 0, assigning 'one' to this
+ * GF2Polynomial.
+ */
+ public void assignOne()
+ {
+ int i;
+ for (i = 1; i < blocks; i++)
+ {
+ value[i] = 0x00;
+ }
+ value[0] = 0x01;
+ }
+
+ /**
+ * Sets Bit 1 to 1 and all other to 0, assigning 'x' to this GF2Polynomial.
+ */
+ public void assignX()
+ {
+ int i;
+ for (i = 1; i < blocks; i++)
+ {
+ value[i] = 0x00;
+ }
+ value[0] = 0x02;
+ }
+
+ /**
+ * Sets all Bits to 1.
+ */
+ public void assignAll()
+ {
+ int i;
+ for (i = 0; i < blocks; i++)
+ {
+ value[i] = 0xffffffff;
+ }
+ zeroUnusedBits();
+ }
+
+ /**
+ * Resets all bits to zero.
+ */
+ public void assignZero()
+ {
+ int i;
+ for (i = 0; i < blocks; i++)
+ {
+ value[i] = 0x00;
+ }
+ }
+
+ /**
+ * Fills all len bits of this GF2Polynomial with random values.
+ */
+ public void randomize()
+ {
+ int i;
+ for (i = 0; i < blocks; i++)
+ {
+ value[i] = rand.nextInt();
+ }
+ zeroUnusedBits();
+ }
+
+ /**
+ * Fills all len bits of this GF2Polynomial with random values using the
+ * specified source of randomness.
+ *
+ * @param rand the source of randomness
+ */
+ public void randomize(Random rand)
+ {
+ int i;
+ for (i = 0; i < blocks; i++)
+ {
+ value[i] = rand.nextInt();
+ }
+ zeroUnusedBits();
+ }
+
+ /**
+ * Returns true if two GF2Polynomials have the same size and value and thus
+ * are equal.
+ *
+ * @param other the other GF2Polynomial
+ * @return true if this GF2Polynomial equals <i>b</i> (<i>this</i> ==
+ * <i>b</i>)
+ */
+ public boolean equals(Object other)
+ {
+ if (other == null || !(other instanceof GF2Polynomial))
+ {
+ return false;
+ }
+
+ GF2Polynomial otherPol = (GF2Polynomial)other;
+
+ if (len != otherPol.len)
+ {
+ return false;
+ }
+ for (int i = 0; i < blocks; i++)
+ {
+ if (value[i] != otherPol.value[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @return the hash code of this polynomial
+ */
+ public int hashCode()
+ {
+ return len + value.hashCode();
+ }
+
+ /**
+ * Tests if all bits equal zero.
+ *
+ * @return true if this GF2Polynomial equals 'zero' (<i>this</i> == 0)
+ */
+ public boolean isZero()
+ {
+ int i;
+ if (len == 0)
+ {
+ return true;
+ }
+ for (i = 0; i < blocks; i++)
+ {
+ if (value[i] != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Tests if all bits are reset to 0 and LSB is set to 1.
+ *
+ * @return true if this GF2Polynomial equals 'one' (<i>this</i> == 1)
+ */
+ public boolean isOne()
+ {
+ int i;
+ for (i = 1; i < blocks; i++)
+ {
+ if (value[i] != 0)
+ {
+ return false;
+ }
+ }
+ if (value[0] != 0x01)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Adds <i>b</i> to this GF2Polynomial and assigns the result to this
+ * GF2Polynomial. <i>b</i> can be of different size.
+ *
+ * @param b GF2Polynomial to add to this GF2Polynomial
+ */
+ public void addToThis(GF2Polynomial b)
+ {
+ expandN(b.len);
+ xorThisBy(b);
+ }
+
+ /**
+ * Adds two GF2Polynomials, <i>this</i> and <i>b</i>, and returns the
+ * result. <i>this</i> and <i>b</i> can be of different size.
+ *
+ * @param b a GF2Polynomial
+ * @return a new GF2Polynomial (<i>this</i> + <i>b</i>)
+ */
+ public GF2Polynomial add(GF2Polynomial b)
+ {
+ return xor(b);
+ }
+
+ /**
+ * Subtracts <i>b</i> from this GF2Polynomial and assigns the result to
+ * this GF2Polynomial. <i>b</i> can be of different size.
+ *
+ * @param b a GF2Polynomial
+ */
+ public void subtractFromThis(GF2Polynomial b)
+ {
+ expandN(b.len);
+ xorThisBy(b);
+ }
+
+ /**
+ * Subtracts two GF2Polynomials, <i>this</i> and <i>b</i>, and returns the
+ * result in a new GF2Polynomial. <i>this</i> and <i>b</i> can be of
+ * different size.
+ *
+ * @param b a GF2Polynomial
+ * @return a new GF2Polynomial (<i>this</i> - <i>b</i>)
+ */
+ public GF2Polynomial subtract(GF2Polynomial b)
+ {
+ return xor(b);
+ }
+
+ /**
+ * Toggles the LSB of this GF2Polynomial, increasing its value by 'one'.
+ */
+ public void increaseThis()
+ {
+ xorBit(0);
+ }
+
+ /**
+ * Toggles the LSB of this GF2Polynomial, increasing the value by 'one' and
+ * returns the result in a new GF2Polynomial.
+ *
+ * @return <tt>this + 1</tt>
+ */
+ public GF2Polynomial increase()
+ {
+ GF2Polynomial result = new GF2Polynomial(this);
+ result.increaseThis();
+ return result;
+ }
+
+ /**
+ * Multiplies this GF2Polynomial with <i>b</i> and returns the result in a
+ * new GF2Polynomial. This method does not reduce the result in GF(2^N).
+ * This method uses classic multiplication (schoolbook).
+ *
+ * @param b a GF2Polynomial
+ * @return a new GF2Polynomial (<i>this</i> * <i>b</i>)
+ */
+ public GF2Polynomial multiplyClassic(GF2Polynomial b)
+ {
+ GF2Polynomial result = new GF2Polynomial(Math.max(len, b.len) << 1);
+ GF2Polynomial[] m = new GF2Polynomial[32];
+ int i, j;
+ m[0] = new GF2Polynomial(this);
+ for (i = 1; i <= 31; i++)
+ {
+ m[i] = m[i - 1].shiftLeft();
+ }
+ for (i = 0; i < b.blocks; i++)
+ {
+ for (j = 0; j <= 31; j++)
+ {
+ if ((b.value[i] & bitMask[j]) != 0)
+ {
+ result.xorThisBy(m[j]);
+ }
+ }
+ for (j = 0; j <= 31; j++)
+ {
+ m[j].shiftBlocksLeft();
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Multiplies this GF2Polynomial with <i>b</i> and returns the result in a
+ * new GF2Polynomial. This method does not reduce the result in GF(2^N).
+ * This method uses Karatzuba multiplication.
+ *
+ * @param b a GF2Polynomial
+ * @return a new GF2Polynomial (<i>this</i> * <i>b</i>)
+ */
+ public GF2Polynomial multiply(GF2Polynomial b)
+ {
+ int n = Math.max(len, b.len);
+ expandN(n);
+ b.expandN(n);
+ return karaMult(b);
+ }
+
+ /**
+ * Does the recursion for Karatzuba multiplication.
+ */
+ private GF2Polynomial karaMult(GF2Polynomial b)
+ {
+ GF2Polynomial result = new GF2Polynomial(len << 1);
+ if (len <= 32)
+ {
+ result.value = mult32(value[0], b.value[0]);
+ return result;
+ }
+ if (len <= 64)
+ {
+ result.value = mult64(value, b.value);
+ return result;
+ }
+ if (len <= 128)
+ {
+ result.value = mult128(value, b.value);
+ return result;
+ }
+ if (len <= 256)
+ {
+ result.value = mult256(value, b.value);
+ return result;
+ }
+ if (len <= 512)
+ {
+ result.value = mult512(value, b.value);
+ return result;
+ }
+
+ int n = IntegerFunctions.floorLog(len - 1);
+ n = bitMask[n];
+
+ GF2Polynomial a0 = lower(((n - 1) >> 5) + 1);
+ GF2Polynomial a1 = upper(((n - 1) >> 5) + 1);
+ GF2Polynomial b0 = b.lower(((n - 1) >> 5) + 1);
+ GF2Polynomial b1 = b.upper(((n - 1) >> 5) + 1);
+
+ GF2Polynomial c = a1.karaMult(b1); // c = a1*b1
+ GF2Polynomial e = a0.karaMult(b0); // e = a0*b0
+ a0.addToThis(a1); // a0 = a0 + a1
+ b0.addToThis(b1); // b0 = b0 + b1
+ GF2Polynomial d = a0.karaMult(b0); // d = (a0+a1)*(b0+b1)
+
+ result.shiftLeftAddThis(c, n << 1);
+ result.shiftLeftAddThis(c, n);
+ result.shiftLeftAddThis(d, n);
+ result.shiftLeftAddThis(e, n);
+ result.addToThis(e);
+ return result;
+ }
+
+ /**
+ * 16-Integer Version of Karatzuba multiplication.
+ */
+ private static int[] mult512(int[] a, int[] b)
+ {
+ int[] result = new int[32];
+ int[] a0 = new int[8];
+ System.arraycopy(a, 0, a0, 0, Math.min(8, a.length));
+ int[] a1 = new int[8];
+ if (a.length > 8)
+ {
+ System.arraycopy(a, 8, a1, 0, Math.min(8, a.length - 8));
+ }
+ int[] b0 = new int[8];
+ System.arraycopy(b, 0, b0, 0, Math.min(8, b.length));
+ int[] b1 = new int[8];
+ if (b.length > 8)
+ {
+ System.arraycopy(b, 8, b1, 0, Math.min(8, b.length - 8));
+ }
+ int[] c = mult256(a1, b1);
+ result[31] ^= c[15];
+ result[30] ^= c[14];
+ result[29] ^= c[13];
+ result[28] ^= c[12];
+ result[27] ^= c[11];
+ result[26] ^= c[10];
+ result[25] ^= c[9];
+ result[24] ^= c[8];
+ result[23] ^= c[7] ^ c[15];
+ result[22] ^= c[6] ^ c[14];
+ result[21] ^= c[5] ^ c[13];
+ result[20] ^= c[4] ^ c[12];
+ result[19] ^= c[3] ^ c[11];
+ result[18] ^= c[2] ^ c[10];
+ result[17] ^= c[1] ^ c[9];
+ result[16] ^= c[0] ^ c[8];
+ result[15] ^= c[7];
+ result[14] ^= c[6];
+ result[13] ^= c[5];
+ result[12] ^= c[4];
+ result[11] ^= c[3];
+ result[10] ^= c[2];
+ result[9] ^= c[1];
+ result[8] ^= c[0];
+ a1[0] ^= a0[0];
+ a1[1] ^= a0[1];
+ a1[2] ^= a0[2];
+ a1[3] ^= a0[3];
+ a1[4] ^= a0[4];
+ a1[5] ^= a0[5];
+ a1[6] ^= a0[6];
+ a1[7] ^= a0[7];
+ b1[0] ^= b0[0];
+ b1[1] ^= b0[1];
+ b1[2] ^= b0[2];
+ b1[3] ^= b0[3];
+ b1[4] ^= b0[4];
+ b1[5] ^= b0[5];
+ b1[6] ^= b0[6];
+ b1[7] ^= b0[7];
+ int[] d = mult256(a1, b1);
+ result[23] ^= d[15];
+ result[22] ^= d[14];
+ result[21] ^= d[13];
+ result[20] ^= d[12];
+ result[19] ^= d[11];
+ result[18] ^= d[10];
+ result[17] ^= d[9];
+ result[16] ^= d[8];
+ result[15] ^= d[7];
+ result[14] ^= d[6];
+ result[13] ^= d[5];
+ result[12] ^= d[4];
+ result[11] ^= d[3];
+ result[10] ^= d[2];
+ result[9] ^= d[1];
+ result[8] ^= d[0];
+ int[] e = mult256(a0, b0);
+ result[23] ^= e[15];
+ result[22] ^= e[14];
+ result[21] ^= e[13];
+ result[20] ^= e[12];
+ result[19] ^= e[11];
+ result[18] ^= e[10];
+ result[17] ^= e[9];
+ result[16] ^= e[8];
+ result[15] ^= e[7] ^ e[15];
+ result[14] ^= e[6] ^ e[14];
+ result[13] ^= e[5] ^ e[13];
+ result[12] ^= e[4] ^ e[12];
+ result[11] ^= e[3] ^ e[11];
+ result[10] ^= e[2] ^ e[10];
+ result[9] ^= e[1] ^ e[9];
+ result[8] ^= e[0] ^ e[8];
+ result[7] ^= e[7];
+ result[6] ^= e[6];
+ result[5] ^= e[5];
+ result[4] ^= e[4];
+ result[3] ^= e[3];
+ result[2] ^= e[2];
+ result[1] ^= e[1];
+ result[0] ^= e[0];
+ return result;
+ }
+
+ /**
+ * 8-Integer Version of Karatzuba multiplication.
+ */
+ private static int[] mult256(int[] a, int[] b)
+ {
+ int[] result = new int[16];
+ int[] a0 = new int[4];
+ System.arraycopy(a, 0, a0, 0, Math.min(4, a.length));
+ int[] a1 = new int[4];
+ if (a.length > 4)
+ {
+ System.arraycopy(a, 4, a1, 0, Math.min(4, a.length - 4));
+ }
+ int[] b0 = new int[4];
+ System.arraycopy(b, 0, b0, 0, Math.min(4, b.length));
+ int[] b1 = new int[4];
+ if (b.length > 4)
+ {
+ System.arraycopy(b, 4, b1, 0, Math.min(4, b.length - 4));
+ }
+ if (a1[3] == 0 && a1[2] == 0 && b1[3] == 0 && b1[2] == 0)
+ {
+ if (a1[1] == 0 && b1[1] == 0)
+ {
+ if (a1[0] != 0 || b1[0] != 0)
+ { // [3]=[2]=[1]=0, [0]!=0
+ int[] c = mult32(a1[0], b1[0]);
+ result[9] ^= c[1];
+ result[8] ^= c[0];
+ result[5] ^= c[1];
+ result[4] ^= c[0];
+ }
+ }
+ else
+ { // [3]=[2]=0 [1]!=0, [0]!=0
+ int[] c = mult64(a1, b1);
+ result[11] ^= c[3];
+ result[10] ^= c[2];
+ result[9] ^= c[1];
+ result[8] ^= c[0];
+ result[7] ^= c[3];
+ result[6] ^= c[2];
+ result[5] ^= c[1];
+ result[4] ^= c[0];
+ }
+ }
+ else
+ { // [3]!=0 [2]!=0 [1]!=0, [0]!=0
+ int[] c = mult128(a1, b1);
+ result[15] ^= c[7];
+ result[14] ^= c[6];
+ result[13] ^= c[5];
+ result[12] ^= c[4];
+ result[11] ^= c[3] ^ c[7];
+ result[10] ^= c[2] ^ c[6];
+ result[9] ^= c[1] ^ c[5];
+ result[8] ^= c[0] ^ c[4];
+ result[7] ^= c[3];
+ result[6] ^= c[2];
+ result[5] ^= c[1];
+ result[4] ^= c[0];
+ }
+ a1[0] ^= a0[0];
+ a1[1] ^= a0[1];
+ a1[2] ^= a0[2];
+ a1[3] ^= a0[3];
+ b1[0] ^= b0[0];
+ b1[1] ^= b0[1];
+ b1[2] ^= b0[2];
+ b1[3] ^= b0[3];
+ int[] d = mult128(a1, b1);
+ result[11] ^= d[7];
+ result[10] ^= d[6];
+ result[9] ^= d[5];
+ result[8] ^= d[4];
+ result[7] ^= d[3];
+ result[6] ^= d[2];
+ result[5] ^= d[1];
+ result[4] ^= d[0];
+ int[] e = mult128(a0, b0);
+ result[11] ^= e[7];
+ result[10] ^= e[6];
+ result[9] ^= e[5];
+ result[8] ^= e[4];
+ result[7] ^= e[3] ^ e[7];
+ result[6] ^= e[2] ^ e[6];
+ result[5] ^= e[1] ^ e[5];
+ result[4] ^= e[0] ^ e[4];
+ result[3] ^= e[3];
+ result[2] ^= e[2];
+ result[1] ^= e[1];
+ result[0] ^= e[0];
+ return result;
+ }
+
+ /**
+ * 4-Integer Version of Karatzuba multiplication.
+ */
+ private static int[] mult128(int[] a, int[] b)
+ {
+ int[] result = new int[8];
+ int[] a0 = new int[2];
+ System.arraycopy(a, 0, a0, 0, Math.min(2, a.length));
+ int[] a1 = new int[2];
+ if (a.length > 2)
+ {
+ System.arraycopy(a, 2, a1, 0, Math.min(2, a.length - 2));
+ }
+ int[] b0 = new int[2];
+ System.arraycopy(b, 0, b0, 0, Math.min(2, b.length));
+ int[] b1 = new int[2];
+ if (b.length > 2)
+ {
+ System.arraycopy(b, 2, b1, 0, Math.min(2, b.length - 2));
+ }
+ if (a1[1] == 0 && b1[1] == 0)
+ {
+ if (a1[0] != 0 || b1[0] != 0)
+ {
+ int[] c = mult32(a1[0], b1[0]);
+ result[5] ^= c[1];
+ result[4] ^= c[0];
+ result[3] ^= c[1];
+ result[2] ^= c[0];
+ }
+ }
+ else
+ {
+ int[] c = mult64(a1, b1);
+ result[7] ^= c[3];
+ result[6] ^= c[2];
+ result[5] ^= c[1] ^ c[3];
+ result[4] ^= c[0] ^ c[2];
+ result[3] ^= c[1];
+ result[2] ^= c[0];
+ }
+ a1[0] ^= a0[0];
+ a1[1] ^= a0[1];
+ b1[0] ^= b0[0];
+ b1[1] ^= b0[1];
+ if (a1[1] == 0 && b1[1] == 0)
+ {
+ int[] d = mult32(a1[0], b1[0]);
+ result[3] ^= d[1];
+ result[2] ^= d[0];
+ }
+ else
+ {
+ int[] d = mult64(a1, b1);
+ result[5] ^= d[3];
+ result[4] ^= d[2];
+ result[3] ^= d[1];
+ result[2] ^= d[0];
+ }
+ if (a0[1] == 0 && b0[1] == 0)
+ {
+ int[] e = mult32(a0[0], b0[0]);
+ result[3] ^= e[1];
+ result[2] ^= e[0];
+ result[1] ^= e[1];
+ result[0] ^= e[0];
+ }
+ else
+ {
+ int[] e = mult64(a0, b0);
+ result[5] ^= e[3];
+ result[4] ^= e[2];
+ result[3] ^= e[1] ^ e[3];
+ result[2] ^= e[0] ^ e[2];
+ result[1] ^= e[1];
+ result[0] ^= e[0];
+ }
+ return result;
+ }
+
+ /**
+ * 2-Integer Version of Karatzuba multiplication.
+ */
+ private static int[] mult64(int[] a, int[] b)
+ {
+ int[] result = new int[4];
+ int a0 = a[0];
+ int a1 = 0;
+ if (a.length > 1)
+ {
+ a1 = a[1];
+ }
+ int b0 = b[0];
+ int b1 = 0;
+ if (b.length > 1)
+ {
+ b1 = b[1];
+ }
+ if (a1 != 0 || b1 != 0)
+ {
+ int[] c = mult32(a1, b1);
+ result[3] ^= c[1];
+ result[2] ^= c[0] ^ c[1];
+ result[1] ^= c[0];
+ }
+ int[] d = mult32(a0 ^ a1, b0 ^ b1);
+ result[2] ^= d[1];
+ result[1] ^= d[0];
+ int[] e = mult32(a0, b0);
+ result[2] ^= e[1];
+ result[1] ^= e[0] ^ e[1];
+ result[0] ^= e[0];
+ return result;
+ }
+
+ /**
+ * 4-Byte Version of Karatzuba multiplication. Here the actual work is done.
+ */
+ private static int[] mult32(int a, int b)
+ {
+ int[] result = new int[2];
+ if (a == 0 || b == 0)
+ {
+ return result;
+ }
+ long b2 = b;
+ b2 &= 0x00000000ffffffffL;
+ int i;
+ long h = 0;
+ for (i = 1; i <= 32; i++)
+ {
+ if ((a & bitMask[i - 1]) != 0)
+ {
+ h ^= b2;
+ }
+ b2 <<= 1;
+ }
+ result[1] = (int)(h >>> 32);
+ result[0] = (int)(h & 0x00000000ffffffffL);
+ return result;
+ }
+
+ /**
+ * Returns a new GF2Polynomial containing the upper <i>k</i> bytes of this
+ * GF2Polynomial.
+ *
+ * @param k
+ * @return a new GF2Polynomial containing the upper <i>k</i> bytes of this
+ * GF2Polynomial
+ * @see GF2Polynomial#karaMult
+ */
+ private GF2Polynomial upper(int k)
+ {
+ int j = Math.min(k, blocks - k);
+ GF2Polynomial result = new GF2Polynomial(j << 5);
+ if (blocks >= k)
+ {
+ System.arraycopy(value, k, result.value, 0, j);
+ }
+ return result;
+ }
+
+ /**
+ * Returns a new GF2Polynomial containing the lower <i>k</i> bytes of this
+ * GF2Polynomial.
+ *
+ * @param k
+ * @return a new GF2Polynomial containing the lower <i>k</i> bytes of this
+ * GF2Polynomial
+ * @see GF2Polynomial#karaMult
+ */
+ private GF2Polynomial lower(int k)
+ {
+ GF2Polynomial result = new GF2Polynomial(k << 5);
+ System.arraycopy(value, 0, result.value, 0, Math.min(k, blocks));
+ return result;
+ }
+
+ /**
+ * Returns the remainder of <i>this</i> divided by <i>g</i> in a new
+ * GF2Polynomial.
+ *
+ * @param g GF2Polynomial != 0
+ * @return a new GF2Polynomial (<i>this</i> % <i>g</i>)
+ * @throws PolynomialIsZeroException if <i>g</i> equals zero
+ */
+ public GF2Polynomial remainder(GF2Polynomial g)
+ throws RuntimeException
+ {
+ /* a div b = q / r */
+ GF2Polynomial a = new GF2Polynomial(this);
+ GF2Polynomial b = new GF2Polynomial(g);
+ GF2Polynomial j;
+ int i;
+ if (b.isZero())
+ {
+ throw new RuntimeException();
+ }
+ a.reduceN();
+ b.reduceN();
+ if (a.len < b.len)
+ {
+ return a;
+ }
+ i = a.len - b.len;
+ while (i >= 0)
+ {
+ j = b.shiftLeft(i);
+ a.subtractFromThis(j);
+ a.reduceN();
+ i = a.len - b.len;
+ }
+ return a;
+ }
+
+ /**
+ * Returns the absolute quotient of <i>this</i> divided by <i>g</i> in a
+ * new GF2Polynomial.
+ *
+ * @param g GF2Polynomial != 0
+ * @return a new GF2Polynomial |_ <i>this</i> / <i>g</i> _|
+ * @throws PolynomialIsZeroException if <i>g</i> equals zero
+ */
+ public GF2Polynomial quotient(GF2Polynomial g)
+ throws RuntimeException
+ {
+ /* a div b = q / r */
+ GF2Polynomial q = new GF2Polynomial(len);
+ GF2Polynomial a = new GF2Polynomial(this);
+ GF2Polynomial b = new GF2Polynomial(g);
+ GF2Polynomial j;
+ int i;
+ if (b.isZero())
+ {
+ throw new RuntimeException();
+ }
+ a.reduceN();
+ b.reduceN();
+ if (a.len < b.len)
+ {
+ return new GF2Polynomial(0);
+ }
+ i = a.len - b.len;
+ q.expandN(i + 1);
+
+ while (i >= 0)
+ {
+ j = b.shiftLeft(i);
+ a.subtractFromThis(j);
+ a.reduceN();
+ q.xorBit(i);
+ i = a.len - b.len;
+ }
+
+ return q;
+ }
+
+ /**
+ * Divides <i>this</i> by <i>g</i> and returns the quotient and remainder
+ * in a new GF2Polynomial[2], quotient in [0], remainder in [1].
+ *
+ * @param g GF2Polynomial != 0
+ * @return a new GF2Polynomial[2] containing quotient and remainder
+ * @throws PolynomialIsZeroException if <i>g</i> equals zero
+ */
+ public GF2Polynomial[] divide(GF2Polynomial g)
+ throws RuntimeException
+ {
+ /* a div b = q / r */
+ GF2Polynomial[] result = new GF2Polynomial[2];
+ GF2Polynomial q = new GF2Polynomial(len);
+ GF2Polynomial a = new GF2Polynomial(this);
+ GF2Polynomial b = new GF2Polynomial(g);
+ GF2Polynomial j;
+ int i;
+ if (b.isZero())
+ {
+ throw new RuntimeException();
+ }
+ a.reduceN();
+ b.reduceN();
+ if (a.len < b.len)
+ {
+ result[0] = new GF2Polynomial(0);
+ result[1] = a;
+ return result;
+ }
+ i = a.len - b.len;
+ q.expandN(i + 1);
+
+ while (i >= 0)
+ {
+ j = b.shiftLeft(i);
+ a.subtractFromThis(j);
+ a.reduceN();
+ q.xorBit(i);
+ i = a.len - b.len;
+ }
+
+ result[0] = q;
+ result[1] = a;
+ return result;
+ }
+
+ /**
+ * Returns the greatest common divisor of <i>this</i> and <i>g</i> in a
+ * new GF2Polynomial.
+ *
+ * @param g GF2Polynomial != 0
+ * @return a new GF2Polynomial gcd(<i>this</i>,<i>g</i>)
+ * @throws ArithmeticException if <i>this</i> and <i>g</i> both are equal to zero
+ * @throws PolynomialIsZeroException to be API-compliant (should never be thrown).
+ */
+ public GF2Polynomial gcd(GF2Polynomial g)
+ throws RuntimeException
+ {
+ if (isZero() && g.isZero())
+ {
+ throw new ArithmeticException("Both operands of gcd equal zero.");
+ }
+ if (isZero())
+ {
+ return new GF2Polynomial(g);
+ }
+ if (g.isZero())
+ {
+ return new GF2Polynomial(this);
+ }
+ GF2Polynomial a = new GF2Polynomial(this);
+ GF2Polynomial b = new GF2Polynomial(g);
+ GF2Polynomial c;
+
+ while (!b.isZero())
+ {
+ c = a.remainder(b);
+ a = b;
+ b = c;
+ }
+
+ return a;
+ }
+
+ /**
+ * Checks if <i>this</i> is irreducible, according to IEEE P1363, A.5.5,
+ * p103.<br>
+ * Note: The algorithm from IEEE P1363, A5.5 can be used to check a
+ * polynomial with coefficients in GF(2^r) for irreducibility. As this class
+ * only represents polynomials with coefficients in GF(2), the algorithm is
+ * adapted to the case r=1.
+ *
+ * @return true if <i>this</i> is irreducible
+ * @see "P1363, A.5.5, p103"
+ */
+ public boolean isIrreducible()
+ {
+ if (isZero())
+ {
+ return false;
+ }
+ GF2Polynomial f = new GF2Polynomial(this);
+ int d, i;
+ GF2Polynomial u, g;
+ GF2Polynomial dummy;
+ f.reduceN();
+ d = f.len - 1;
+ u = new GF2Polynomial(f.len, "X");
+
+ for (i = 1; i <= (d >> 1); i++)
+ {
+ u.squareThisPreCalc();
+ u = u.remainder(f);
+ dummy = u.add(new GF2Polynomial(32, "X"));
+ if (!dummy.isZero())
+ {
+ g = f.gcd(dummy);
+ if (!g.isOne())
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Reduces this GF2Polynomial using the trinomial x^<i>m</i> + x^<i>tc</i> +
+ * 1.
+ *
+ * @param m the degree of the used field
+ * @param tc degree of the middle x in the trinomial
+ */
+ void reduceTrinomial(int m, int tc)
+ {
+ int i;
+ int p0, p1;
+ int q0, q1;
+ long t;
+ p0 = m >>> 5; // block which contains 2^m
+ q0 = 32 - (m & 0x1f); // (32-index) of 2^m within block p0
+ p1 = (m - tc) >>> 5; // block which contains 2^tc
+ q1 = 32 - ((m - tc) & 0x1f); // (32-index) of 2^tc within block q1
+ int max = ((m << 1) - 2) >>> 5; // block which contains 2^(2m-2)
+ int min = p0; // block which contains 2^m
+ for (i = max; i > min; i--)
+ { // for i = maxBlock to minBlock
+ // reduce coefficients contained in t
+ // t = block[i]
+ t = value[i] & 0x00000000ffffffffL;
+ // block[i-p0-1] ^= t << q0
+ value[i - p0 - 1] ^= (int)(t << q0);
+ // block[i-p0] ^= t >>> (32-q0)
+ value[i - p0] ^= t >>> (32 - q0);
+ // block[i-p1-1] ^= << q1
+ value[i - p1 - 1] ^= (int)(t << q1);
+ // block[i-p1] ^= t >>> (32-q1)
+ value[i - p1] ^= t >>> (32 - q1);
+ value[i] = 0x00;
+ }
+ // reduce last coefficients in block containing 2^m
+ t = value[min] & 0x00000000ffffffffL & (0xffffffffL << (m & 0x1f)); // t
+ // contains the last coefficients > m
+ value[0] ^= t >>> (32 - q0);
+ if (min - p1 - 1 >= 0)
+ {
+ value[min - p1 - 1] ^= (int)(t << q1);
+ }
+ value[min - p1] ^= t >>> (32 - q1);
+
+ value[min] &= reverseRightMask[m & 0x1f];
+ blocks = ((m - 1) >>> 5) + 1;
+ len = m;
+ }
+
+ /**
+ * Reduces this GF2Polynomial using the pentanomial x^<i>m</i> + x^<i>pc[2]</i> +
+ * x^<i>pc[1]</i> + x^<i>pc[0]</i> + 1.
+ *
+ * @param m the degree of the used field
+ * @param pc degrees of the middle x's in the pentanomial
+ */
+ void reducePentanomial(int m, int[] pc)
+ {
+ int i;
+ int p0, p1, p2, p3;
+ int q0, q1, q2, q3;
+ long t;
+ p0 = m >>> 5;
+ q0 = 32 - (m & 0x1f);
+ p1 = (m - pc[0]) >>> 5;
+ q1 = 32 - ((m - pc[0]) & 0x1f);
+ p2 = (m - pc[1]) >>> 5;
+ q2 = 32 - ((m - pc[1]) & 0x1f);
+ p3 = (m - pc[2]) >>> 5;
+ q3 = 32 - ((m - pc[2]) & 0x1f);
+ int max = ((m << 1) - 2) >>> 5;
+ int min = p0;
+ for (i = max; i > min; i--)
+ {
+ t = value[i] & 0x00000000ffffffffL;
+ value[i - p0 - 1] ^= (int)(t << q0);
+ value[i - p0] ^= t >>> (32 - q0);
+ value[i - p1 - 1] ^= (int)(t << q1);
+ value[i - p1] ^= t >>> (32 - q1);
+ value[i - p2 - 1] ^= (int)(t << q2);
+ value[i - p2] ^= t >>> (32 - q2);
+ value[i - p3 - 1] ^= (int)(t << q3);
+ value[i - p3] ^= t >>> (32 - q3);
+ value[i] = 0;
+ }
+ t = value[min] & 0x00000000ffffffffL & (0xffffffffL << (m & 0x1f));
+ value[0] ^= t >>> (32 - q0);
+ if (min - p1 - 1 >= 0)
+ {
+ value[min - p1 - 1] ^= (int)(t << q1);
+ }
+ value[min - p1] ^= t >>> (32 - q1);
+ if (min - p2 - 1 >= 0)
+ {
+ value[min - p2 - 1] ^= (int)(t << q2);
+ }
+ value[min - p2] ^= t >>> (32 - q2);
+ if (min - p3 - 1 >= 0)
+ {
+ value[min - p3 - 1] ^= (int)(t << q3);
+ }
+ value[min - p3] ^= t >>> (32 - q3);
+ value[min] &= reverseRightMask[m & 0x1f];
+
+ blocks = ((m - 1) >>> 5) + 1;
+ len = m;
+ }
+
+ /**
+ * Reduces len by finding the most significant bit set to one and reducing
+ * len and blocks.
+ */
+ public void reduceN()
+ {
+ int i, j, h;
+ i = blocks - 1;
+ while ((value[i] == 0) && (i > 0))
+ {
+ i--;
+ }
+ h = value[i];
+ j = 0;
+ while (h != 0)
+ {
+ h >>>= 1;
+ j++;
+ }
+ len = (i << 5) + j;
+ blocks = i + 1;
+ }
+
+ /**
+ * Expands len and int[] value to <i>i</i>. This is useful before adding
+ * two GF2Polynomials of different size.
+ *
+ * @param i the intended length
+ */
+ public void expandN(int i)
+ {
+ int k;
+ int[] bs;
+ if (len >= i)
+ {
+ return;
+ }
+ len = i;
+ k = ((i - 1) >>> 5) + 1;
+ if (blocks >= k)
+ {
+ return;
+ }
+ if (value.length >= k)
+ {
+ int j;
+ for (j = blocks; j < k; j++)
+ {
+ value[j] = 0;
+ }
+ blocks = k;
+ return;
+ }
+ bs = new int[k];
+ System.arraycopy(value, 0, bs, 0, blocks);
+ blocks = k;
+ value = null;
+ value = bs;
+ }
+
+ /**
+ * Squares this GF2Polynomial and expands it accordingly. This method does
+ * not reduce the result in GF(2^N). There exists a faster method for
+ * squaring in GF(2^N).
+ *
+ * @see GF2nPolynomialElement#square
+ */
+ public void squareThisBitwise()
+ {
+ int i, h, j, k;
+ if (isZero())
+ {
+ return;
+ }
+ int[] result = new int[blocks << 1];
+ for (i = blocks - 1; i >= 0; i--)
+ {
+ h = value[i];
+ j = 0x00000001;
+ for (k = 0; k < 16; k++)
+ {
+ if ((h & 0x01) != 0)
+ {
+ result[i << 1] |= j;
+ }
+ if ((h & 0x00010000) != 0)
+ {
+ result[(i << 1) + 1] |= j;
+ }
+ j <<= 2;
+ h >>>= 1;
+ }
+ }
+ value = null;
+ value = result;
+ blocks = result.length;
+ len = (len << 1) - 1;
+ }
+
+ /**
+ * Squares this GF2Polynomial by using precomputed values of squaringTable.
+ * This method does not reduce the result in GF(2^N).
+ */
+ public void squareThisPreCalc()
+ {
+ int i;
+ if (isZero())
+ {
+ return;
+ }
+ if (value.length >= (blocks << 1))
+ {
+ for (i = blocks - 1; i >= 0; i--)
+ {
+ value[(i << 1) + 1] = GF2Polynomial.squaringTable[(value[i] & 0x00ff0000) >>> 16]
+ | (GF2Polynomial.squaringTable[(value[i] & 0xff000000) >>> 24] << 16);
+ value[i << 1] = GF2Polynomial.squaringTable[value[i] & 0x000000ff]
+ | (GF2Polynomial.squaringTable[(value[i] & 0x0000ff00) >>> 8] << 16);
+ }
+ blocks <<= 1;
+ len = (len << 1) - 1;
+ }
+ else
+ {
+ int[] result = new int[blocks << 1];
+ for (i = 0; i < blocks; i++)
+ {
+ result[i << 1] = GF2Polynomial.squaringTable[value[i] & 0x000000ff]
+ | (GF2Polynomial.squaringTable[(value[i] & 0x0000ff00) >>> 8] << 16);
+ result[(i << 1) + 1] = GF2Polynomial.squaringTable[(value[i] & 0x00ff0000) >>> 16]
+ | (GF2Polynomial.squaringTable[(value[i] & 0xff000000) >>> 24] << 16);
+ }
+ value = null;
+ value = result;
+ blocks <<= 1;
+ len = (len << 1) - 1;
+ }
+ }
+
+ /**
+ * Does a vector-multiplication modulo 2 and returns the result as boolean.
+ *
+ * @param b GF2Polynomial
+ * @return this x <i>b</i> as boolean (1-&gt;true, 0-&gt;false)
+ * @throws PolynomialsHaveDifferentLengthException if <i>this</i> and <i>b</i> have a different length and
+ * thus cannot be vector-multiplied
+ */
+ public boolean vectorMult(GF2Polynomial b)
+ throws RuntimeException
+ {
+ int i;
+ int h;
+ boolean result = false;
+ if (len != b.len)
+ {
+ throw new RuntimeException();
+ }
+ for (i = 0; i < blocks; i++)
+ {
+ h = value[i] & b.value[i];
+ result ^= parity[h & 0x000000ff];
+ result ^= parity[(h >>> 8) & 0x000000ff];
+ result ^= parity[(h >>> 16) & 0x000000ff];
+ result ^= parity[(h >>> 24) & 0x000000ff];
+ }
+ return result;
+ }
+
+ /**
+ * Returns the bitwise exclusive-or of <i>this</i> and <i>b</i> in a new
+ * GF2Polynomial. <i>this</i> and <i>b</i> can be of different size.
+ *
+ * @param b GF2Polynomial
+ * @return a new GF2Polynomial (<i>this</i> ^ <i>b</i>)
+ */
+ public GF2Polynomial xor(GF2Polynomial b)
+ {
+ int i;
+ GF2Polynomial result;
+ int k = Math.min(blocks, b.blocks);
+ if (len >= b.len)
+ {
+ result = new GF2Polynomial(this);
+ for (i = 0; i < k; i++)
+ {
+ result.value[i] ^= b.value[i];
+ }
+ }
+ else
+ {
+ result = new GF2Polynomial(b);
+ for (i = 0; i < k; i++)
+ {
+ result.value[i] ^= value[i];
+ }
+ }
+ // If we xor'ed some bits too many by proceeding blockwise,
+ // restore them to zero:
+ result.zeroUnusedBits();
+ return result;
+ }
+
+ /**
+ * Computes the bitwise exclusive-or of this GF2Polynomial and <i>b</i> and
+ * stores the result in this GF2Polynomial. <i>b</i> can be of different
+ * size.
+ *
+ * @param b GF2Polynomial
+ */
+ public void xorThisBy(GF2Polynomial b)
+ {
+ int i;
+ for (i = 0; i < Math.min(blocks, b.blocks); i++)
+ {
+ value[i] ^= b.value[i];
+ }
+ // If we xor'ed some bits too many by proceeding blockwise,
+ // restore them to zero:
+ zeroUnusedBits();
+ }
+
+ /**
+ * If {@link #len} is not a multiple of the block size (32), some extra bits
+ * of the last block might have been modified during a blockwise operation.
+ * This method compensates for that by restoring these "extra" bits to zero.
+ */
+ private void zeroUnusedBits()
+ {
+ if ((len & 0x1f) != 0)
+ {
+ value[blocks - 1] &= reverseRightMask[len & 0x1f];
+ }
+ }
+
+ /**
+ * Sets the bit at position <i>i</i>.
+ *
+ * @param i int
+ * @throws BitDoesNotExistException if (<i>i</i> &lt; 0) || (<i>i</i> &gt; (len - 1))
+ */
+ public void setBit(int i)
+ throws RuntimeException
+ {
+ if (i < 0 || i > (len - 1))
+ {
+ throw new RuntimeException();
+ }
+ if (i > (len - 1))
+ {
+ return;
+ }
+ value[i >>> 5] |= bitMask[i & 0x1f];
+ return;
+ }
+
+ /**
+ * Returns the bit at position <i>i</i>.
+ *
+ * @param i int
+ * @return the bit at position <i>i</i> if <i>i</i> is a valid position, 0
+ * otherwise.
+ */
+ public int getBit(int i)
+ {
+ if (i < 0 || i > (len - 1))
+ {
+ return 0;
+ }
+ return ((value[i >>> 5] & bitMask[i & 0x1f]) != 0) ? 1 : 0;
+ }
+
+ /**
+ * Resets the bit at position <i>i</i>.
+ *
+ * @param i int
+ * @throws BitDoesNotExistException if (<i>i</i> &lt; 0) || (<i>i</i> &gt; (len - 1))
+ */
+ public void resetBit(int i)
+ throws RuntimeException
+ {
+ if (i < 0 || i > (len - 1))
+ {
+ throw new RuntimeException();
+ }
+ if (i > (len - 1))
+ {
+ return;
+ }
+ value[i >>> 5] &= ~bitMask[i & 0x1f];
+ }
+
+ /**
+ * Xors the bit at position <i>i</i>.
+ *
+ * @param i int
+ * @throws BitDoesNotExistException if (<i>i</i> &lt; 0) || (<i>i</i> &gt; (len - 1))
+ */
+ public void xorBit(int i)
+ throws RuntimeException
+ {
+ if (i < 0 || i > (len - 1))
+ {
+ throw new RuntimeException();
+ }
+ if (i > (len - 1))
+ {
+ return;
+ }
+ value[i >>> 5] ^= bitMask[i & 0x1f];
+ }
+
+ /**
+ * Tests the bit at position <i>i</i>.
+ *
+ * @param i the position of the bit to be tested
+ * @return true if the bit at position <i>i</i> is set (a(<i>i</i>) ==
+ * 1). False if (<i>i</i> &lt; 0) || (<i>i</i> &gt; (len - 1))
+ */
+ public boolean testBit(int i)
+ {
+ if (i < 0 || i > (len - 1))
+ {
+ return false;
+ }
+ return (value[i >>> 5] & bitMask[i & 0x1f]) != 0;
+ }
+
+ /**
+ * Returns this GF2Polynomial shift-left by 1 in a new GF2Polynomial.
+ *
+ * @return a new GF2Polynomial (this &lt;&lt; 1)
+ */
+ public GF2Polynomial shiftLeft()
+ {
+ GF2Polynomial result = new GF2Polynomial(len + 1, value);
+ int i;
+ for (i = result.blocks - 1; i >= 1; i--)
+ {
+ result.value[i] <<= 1;
+ result.value[i] |= result.value[i - 1] >>> 31;
+ }
+ result.value[0] <<= 1;
+ return result;
+ }
+
+ /**
+ * Shifts-left this by one and enlarges the size of value if necesary.
+ */
+ public void shiftLeftThis()
+ {
+ /** @todo This is untested. */
+ int i;
+ if ((len & 0x1f) == 0)
+ { // check if blocks increases
+ len += 1;
+ blocks += 1;
+ if (blocks > value.length)
+ { // enlarge value
+ int[] bs = new int[blocks];
+ System.arraycopy(value, 0, bs, 0, value.length);
+ value = null;
+ value = bs;
+ }
+ for (i = blocks - 1; i >= 1; i--)
+ {
+ value[i] |= value[i - 1] >>> 31;
+ value[i - 1] <<= 1;
+ }
+ }
+ else
+ {
+ len += 1;
+ for (i = blocks - 1; i >= 1; i--)
+ {
+ value[i] <<= 1;
+ value[i] |= value[i - 1] >>> 31;
+ }
+ value[0] <<= 1;
+ }
+ }
+
+ /**
+ * Returns this GF2Polynomial shift-left by <i>k</i> in a new
+ * GF2Polynomial.
+ *
+ * @param k int
+ * @return a new GF2Polynomial (this &lt;&lt; <i>k</i>)
+ */
+ public GF2Polynomial shiftLeft(int k)
+ {
+ // Variant 2, requiring a modified shiftBlocksLeft(k)
+ // In case of modification, consider a rename to doShiftBlocksLeft()
+ // with an explicit note that this method assumes that the polynomial
+ // has already been resized. Or consider doing things inline.
+ // Construct the resulting polynomial of appropriate length:
+ GF2Polynomial result = new GF2Polynomial(len + k, value);
+ // Shift left as many multiples of the block size as possible:
+ if (k >= 32)
+ {
+ result.doShiftBlocksLeft(k >>> 5);
+ }
+ // Shift left by the remaining (<32) amount:
+ final int remaining = k & 0x1f;
+ if (remaining != 0)
+ {
+ for (int i = result.blocks - 1; i >= 1; i--)
+ {
+ result.value[i] <<= remaining;
+ result.value[i] |= result.value[i - 1] >>> (32 - remaining);
+ }
+ result.value[0] <<= remaining;
+ }
+ return result;
+ }
+
+ /**
+ * Shifts left b and adds the result to Its a fast version of
+ * <tt>this = add(b.shl(k));</tt>
+ *
+ * @param b GF2Polynomial to shift and add to this
+ * @param k the amount to shift
+ * @see GF2nPolynomialElement#invertEEA
+ */
+ public void shiftLeftAddThis(GF2Polynomial b, int k)
+ {
+ if (k == 0)
+ {
+ addToThis(b);
+ return;
+ }
+ int i;
+ expandN(b.len + k);
+ int d = k >>> 5;
+ for (i = b.blocks - 1; i >= 0; i--)
+ {
+ if ((i + d + 1 < blocks) && ((k & 0x1f) != 0))
+ {
+ value[i + d + 1] ^= b.value[i] >>> (32 - (k & 0x1f));
+ }
+ value[i + d] ^= b.value[i] << (k & 0x1f);
+ }
+ }
+
+ /**
+ * Shifts-left this GF2Polynomial's value blockwise 1 block resulting in a
+ * shift-left by 32.
+ *
+ * @see GF2Polynomial#multiply
+ */
+ void shiftBlocksLeft()
+ {
+ blocks += 1;
+ len += 32;
+ if (blocks <= value.length)
+ {
+ int i;
+ for (i = blocks - 1; i >= 1; i--)
+ {
+ value[i] = value[i - 1];
+ }
+ value[0] = 0x00;
+ }
+ else
+ {
+ int[] result = new int[blocks];
+ System.arraycopy(value, 0, result, 1, blocks - 1);
+ value = null;
+ value = result;
+ }
+ }
+
+ /**
+ * Shifts left this GF2Polynomial's value blockwise <i>b</i> blocks
+ * resulting in a shift-left by b*32. This method assumes that {@link #len}
+ * and {@link #blocks} have already been updated to reflect the final state.
+ *
+ * @param b shift amount (in blocks)
+ */
+ private void doShiftBlocksLeft(int b)
+ {
+ if (blocks <= value.length)
+ {
+ int i;
+ for (i = blocks - 1; i >= b; i--)
+ {
+ value[i] = value[i - b];
+ }
+ for (i = 0; i < b; i++)
+ {
+ value[i] = 0x00;
+ }
+ }
+ else
+ {
+ int[] result = new int[blocks];
+ System.arraycopy(value, 0, result, b, blocks - b);
+ value = null;
+ value = result;
+ }
+ }
+
+ /**
+ * Returns this GF2Polynomial shift-right by 1 in a new GF2Polynomial.
+ *
+ * @return a new GF2Polynomial (this &lt;&lt; 1)
+ */
+ public GF2Polynomial shiftRight()
+ {
+ GF2Polynomial result = new GF2Polynomial(len - 1);
+ int i;
+ System.arraycopy(value, 0, result.value, 0, result.blocks);
+ for (i = 0; i <= result.blocks - 2; i++)
+ {
+ result.value[i] >>>= 1;
+ result.value[i] |= result.value[i + 1] << 31;
+ }
+ result.value[result.blocks - 1] >>>= 1;
+ if (result.blocks < blocks)
+ {
+ result.value[result.blocks - 1] |= value[result.blocks] << 31;
+ }
+ return result;
+ }
+
+ /**
+ * Shifts-right this GF2Polynomial by 1.
+ */
+ public void shiftRightThis()
+ {
+ int i;
+ len -= 1;
+ blocks = ((len - 1) >>> 5) + 1;
+ for (i = 0; i <= blocks - 2; i++)
+ {
+ value[i] >>>= 1;
+ value[i] |= value[i + 1] << 31;
+ }
+ value[blocks - 1] >>>= 1;
+ if ((len & 0x1f) == 0)
+ {
+ value[blocks - 1] |= value[blocks] << 31;
+ }
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2Vector.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2Vector.java
new file mode 100644
index 00000000..560ad216
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2Vector.java
@@ -0,0 +1,539 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+import java.security.SecureRandom;
+
+/**
+ * This class implements the abstract class <tt>Vector</tt> for the case of
+ * vectors over the finite field GF(2). <br>
+ * For the vector representation the array of type int[] is used, thus one
+ * element of the array holds 32 elements of the vector.
+ *
+ * @see Vector
+ */
+public class GF2Vector
+ extends Vector
+{
+
+ /**
+ * holds the elements of this vector
+ */
+ private int[] v;
+
+ /**
+ * Construct the zero vector of the given length.
+ *
+ * @param length the length of the vector
+ */
+ public GF2Vector(int length)
+ {
+ if (length < 0)
+ {
+ throw new ArithmeticException("Negative length.");
+ }
+ this.length = length;
+ v = new int[(length + 31) >> 5];
+ }
+
+ /**
+ * Construct a random GF2Vector of the given length.
+ *
+ * @param length the length of the vector
+ * @param sr the source of randomness
+ */
+ public GF2Vector(int length, SecureRandom sr)
+ {
+ this.length = length;
+
+ int size = (length + 31) >> 5;
+ v = new int[size];
+
+ // generate random elements
+ for (int i = size - 1; i >= 0; i--)
+ {
+ v[i] = sr.nextInt();
+ }
+
+ // erase unused bits
+ int r = length & 0x1f;
+ if (r != 0)
+ {
+ // erase unused bits
+ v[size - 1] &= (1 << r) - 1;
+ }
+ }
+
+ /**
+ * Construct a random GF2Vector of the given length with the specified
+ * number of non-zero coefficients.
+ *
+ * @param length the length of the vector
+ * @param t the number of non-zero coefficients
+ * @param sr the source of randomness
+ */
+ public GF2Vector(int length, int t, SecureRandom sr)
+ {
+ if (t > length)
+ {
+ throw new ArithmeticException(
+ "The hamming weight is greater than the length of vector.");
+ }
+ this.length = length;
+
+ int size = (length + 31) >> 5;
+ v = new int[size];
+
+ int[] help = new int[length];
+ for (int i = 0; i < length; i++)
+ {
+ help[i] = i;
+ }
+
+ int m = length;
+ for (int i = 0; i < t; i++)
+ {
+ int j = RandUtils.nextInt(sr, m);
+ setBit(help[j]);
+ m--;
+ help[j] = help[m];
+ }
+ }
+
+ /**
+ * Construct a GF2Vector of the given length and with elements from the
+ * given array. The array is copied and unused bits are masked out.
+ *
+ * @param length the length of the vector
+ * @param v the element array
+ */
+ public GF2Vector(int length, int[] v)
+ {
+ if (length < 0)
+ {
+ throw new ArithmeticException("negative length");
+ }
+ this.length = length;
+
+ int size = (length + 31) >> 5;
+
+ if (v.length != size)
+ {
+ throw new ArithmeticException("length mismatch");
+ }
+
+ this.v = IntUtils.clone(v);
+
+ int r = length & 0x1f;
+ if (r != 0)
+ {
+ // erase unused bits
+ this.v[size - 1] &= (1 << r) - 1;
+ }
+ }
+
+ /**
+ * Copy constructor.
+ *
+ * @param other another {@link GF2Vector}
+ */
+ public GF2Vector(GF2Vector other)
+ {
+ this.length = other.length;
+ this.v = IntUtils.clone(other.v);
+ }
+
+ /**
+ * Construct a new {@link GF2Vector} of the given length and with the given
+ * element array. The array is not changed and only a reference to the array
+ * is stored. No length checking is performed either.
+ *
+ * @param v the element array
+ * @param length the length of the vector
+ */
+ protected GF2Vector(int[] v, int length)
+ {
+ this.v = v;
+ this.length = length;
+ }
+
+ /**
+ * Construct a new GF2Vector with the given length out of the encoded
+ * vector.
+ *
+ * @param length the length of the vector
+ * @param encVec the encoded vector
+ * @return the decoded vector
+ */
+ public static GF2Vector OS2VP(int length, byte[] encVec)
+ {
+ if (length < 0)
+ {
+ throw new ArithmeticException("negative length");
+ }
+
+ int byteLen = (length + 7) >> 3;
+
+ if (encVec.length > byteLen)
+ {
+ throw new ArithmeticException("length mismatch");
+ }
+
+ return new GF2Vector(length, LittleEndianConversions.toIntArray(encVec));
+ }
+
+ /**
+ * Encode this vector as byte array.
+ *
+ * @return the encoded vector
+ */
+ public byte[] getEncoded()
+ {
+ int byteLen = (length + 7) >> 3;
+ return LittleEndianConversions.toByteArray(v, byteLen);
+ }
+
+ /**
+ * @return the int array representation of this vector
+ */
+ public int[] getVecArray()
+ {
+ return v;
+ }
+
+ /**
+ * Return the Hamming weight of this vector, i.e., compute the number of
+ * units of this vector.
+ *
+ * @return the Hamming weight of this vector
+ */
+ public int getHammingWeight()
+ {
+ int weight = 0;
+ for (int i = 0; i < v.length; i++)
+ {
+ int e = v[i];
+ for (int j = 0; j < 32; j++)
+ {
+ int b = e & 1;
+ if (b != 0)
+ {
+ weight++;
+ }
+ e >>>= 1;
+ }
+ }
+ return weight;
+ }
+
+ /**
+ * @return whether this is the zero vector (i.e., all elements are zero)
+ */
+ public boolean isZero()
+ {
+ for (int i = v.length - 1; i >= 0; i--)
+ {
+ if (v[i] != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Return the value of the bit of this vector at the specified index.
+ *
+ * @param index the index
+ * @return the value of the bit (0 or 1)
+ */
+ public int getBit(int index)
+ {
+ if (index >= length)
+ {
+ throw new IndexOutOfBoundsException();
+ }
+ int q = index >> 5;
+ int r = index & 0x1f;
+ return (v[q] & (1 << r)) >>> r;
+ }
+
+ /**
+ * Set the coefficient at the given index to 1. If the index is out of
+ * bounds, do nothing.
+ *
+ * @param index the index of the coefficient to set
+ */
+ public void setBit(int index)
+ {
+ if (index >= length)
+ {
+ throw new IndexOutOfBoundsException();
+ }
+ v[index >> 5] |= 1 << (index & 0x1f);
+ }
+
+ /**
+ * Adds another GF2Vector to this vector.
+ *
+ * @param other another GF2Vector
+ * @return <tt>this + other</tt>
+ * @throws ArithmeticException if the other vector is not a GF2Vector or has another
+ * length.
+ */
+ public Vector add(Vector other)
+ {
+ if (!(other instanceof GF2Vector))
+ {
+ throw new ArithmeticException("vector is not defined over GF(2)");
+ }
+
+ GF2Vector otherVec = (GF2Vector)other;
+ if (length != otherVec.length)
+ {
+ throw new ArithmeticException("length mismatch");
+ }
+
+ int[] vec = IntUtils.clone(((GF2Vector)other).v);
+
+ for (int i = vec.length - 1; i >= 0; i--)
+ {
+ vec[i] ^= v[i];
+ }
+
+ return new GF2Vector(length, vec);
+ }
+
+ /**
+ * Multiply this vector with a permutation.
+ *
+ * @param p the permutation
+ * @return <tt>this*p = p*this</tt>
+ */
+ public Vector multiply(Permutation p)
+ {
+ int[] pVec = p.getVector();
+ if (length != pVec.length)
+ {
+ throw new ArithmeticException("length mismatch");
+ }
+
+ GF2Vector result = new GF2Vector(length);
+
+ for (int i = 0; i < pVec.length; i++)
+ {
+ int e = v[pVec[i] >> 5] & (1 << (pVec[i] & 0x1f));
+ if (e != 0)
+ {
+ result.v[i >> 5] |= 1 << (i & 0x1f);
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Return a new vector consisting of the elements of this vector with the
+ * indices given by the set <tt>setJ</tt>.
+ *
+ * @param setJ the set of indices of elements to extract
+ * @return the new {@link GF2Vector}
+ * <tt>[this_setJ[0], this_setJ[1], ..., this_setJ[#setJ-1]]</tt>
+ */
+ public GF2Vector extractVector(int[] setJ)
+ {
+ int k = setJ.length;
+ if (setJ[k - 1] > length)
+ {
+ throw new ArithmeticException("invalid index set");
+ }
+
+ GF2Vector result = new GF2Vector(k);
+
+ for (int i = 0; i < k; i++)
+ {
+ int e = v[setJ[i] >> 5] & (1 << (setJ[i] & 0x1f));
+ if (e != 0)
+ {
+ result.v[i >> 5] |= 1 << (i & 0x1f);
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Return a new vector consisting of the first <tt>k</tt> elements of this
+ * vector.
+ *
+ * @param k the number of elements to extract
+ * @return a new {@link GF2Vector} consisting of the first <tt>k</tt>
+ * elements of this vector
+ */
+ public GF2Vector extractLeftVector(int k)
+ {
+ if (k > length)
+ {
+ throw new ArithmeticException("invalid length");
+ }
+
+ if (k == length)
+ {
+ return new GF2Vector(this);
+ }
+
+ GF2Vector result = new GF2Vector(k);
+
+ int q = k >> 5;
+ int r = k & 0x1f;
+
+ System.arraycopy(v, 0, result.v, 0, q);
+ if (r != 0)
+ {
+ result.v[q] = v[q] & ((1 << r) - 1);
+ }
+
+ return result;
+ }
+
+ /**
+ * Return a new vector consisting of the last <tt>k</tt> elements of this
+ * vector.
+ *
+ * @param k the number of elements to extract
+ * @return a new {@link GF2Vector} consisting of the last <tt>k</tt>
+ * elements of this vector
+ */
+ public GF2Vector extractRightVector(int k)
+ {
+ if (k > length)
+ {
+ throw new ArithmeticException("invalid length");
+ }
+
+ if (k == length)
+ {
+ return new GF2Vector(this);
+ }
+
+ GF2Vector result = new GF2Vector(k);
+
+ int q = (length - k) >> 5;
+ int r = (length - k) & 0x1f;
+ int length = (k + 31) >> 5;
+
+ int ind = q;
+ // if words have to be shifted
+ if (r != 0)
+ {
+ // process all but last word
+ for (int i = 0; i < length - 1; i++)
+ {
+ result.v[i] = (v[ind++] >>> r) | (v[ind] << (32 - r));
+ }
+ // process last word
+ result.v[length - 1] = v[ind++] >>> r;
+ if (ind < v.length)
+ {
+ result.v[length - 1] |= v[ind] << (32 - r);
+ }
+ }
+ else
+ {
+ // no shift necessary
+ System.arraycopy(v, q, result.v, 0, length);
+ }
+
+ return result;
+ }
+
+ /**
+ * Rewrite this vector as a vector over <tt>GF(2<sup>m</sup>)</tt> with
+ * <tt>t</tt> elements.
+ *
+ * @param field the finite field <tt>GF(2<sup>m</sup>)</tt>
+ * @return the converted vector over <tt>GF(2<sup>m</sup>)</tt>
+ */
+ public GF2mVector toExtensionFieldVector(GF2mField field)
+ {
+ int m = field.getDegree();
+ if ((length % m) != 0)
+ {
+ throw new ArithmeticException("conversion is impossible");
+ }
+
+ int t = length / m;
+ int[] result = new int[t];
+ int count = 0;
+ for (int i = t - 1; i >= 0; i--)
+ {
+ for (int j = field.getDegree() - 1; j >= 0; j--)
+ {
+ int q = count >>> 5;
+ int r = count & 0x1f;
+
+ int e = (v[q] >>> r) & 1;
+ if (e == 1)
+ {
+ result[i] ^= 1 << j;
+ }
+ count++;
+ }
+ }
+ return new GF2mVector(field, result);
+ }
+
+ /**
+ * Check if the given object is equal to this vector.
+ *
+ * @param other vector
+ * @return the result of the comparison
+ */
+ public boolean equals(Object other)
+ {
+
+ if (!(other instanceof GF2Vector))
+ {
+ return false;
+ }
+ GF2Vector otherVec = (GF2Vector)other;
+
+ return (length == otherVec.length) && IntUtils.equals(v, otherVec.v);
+ }
+
+ /**
+ * @return the hash code of this vector
+ */
+ public int hashCode()
+ {
+ int hash = length;
+ hash = hash * 31 + v.hashCode();
+ return hash;
+ }
+
+ /**
+ * @return a human readable form of this vector
+ */
+ public String toString()
+ {
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < length; i++)
+ {
+ if ((i != 0) && ((i & 0x1f) == 0))
+ {
+ buf.append(' ');
+ }
+ int q = i >> 5;
+ int r = i & 0x1f;
+ int bit = v[q] & (1 << r);
+ if (bit == 0)
+ {
+ buf.append('0');
+ }
+ else
+ {
+ buf.append('1');
+ }
+ }
+ return buf.toString();
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mField.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mField.java
new file mode 100644
index 00000000..b60cd598
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mField.java
@@ -0,0 +1,365 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+import java.security.SecureRandom;
+
+/**
+ * This class describes operations with elements from the finite field F =
+ * GF(2^m). ( GF(2^m)= GF(2)[A] where A is a root of irreducible polynomial with
+ * degree m, each field element B has a polynomial basis representation, i.e. it
+ * is represented by a different binary polynomial of degree less than m, B =
+ * poly(A) ) All operations are defined only for field with 1&lt; m &lt;32. For the
+ * representation of field elements the map f: F-&gt;Z, poly(A)-&gt;poly(2) is used,
+ * where integers have the binary representation. For example: A^7+A^3+A+1 -&gt;
+ * (00...0010001011)=139 Also for elements type Integer is used.
+ *
+ * @see PolynomialRingGF2
+ */
+public class GF2mField
+{
+
+ /*
+ * degree - degree of the field polynomial - the field polynomial ring -
+ * polynomial ring over the finite field GF(2)
+ */
+
+ private int degree = 0;
+
+ private int polynomial;
+
+ /**
+ * create a finite field GF(2^m)
+ *
+ * @param degree the degree of the field
+ */
+ public GF2mField(int degree)
+ {
+ if (degree >= 32)
+ {
+ throw new IllegalArgumentException(
+ " Error: the degree of field is too large ");
+ }
+ if (degree < 1)
+ {
+ throw new IllegalArgumentException(
+ " Error: the degree of field is non-positive ");
+ }
+ this.degree = degree;
+ polynomial = PolynomialRingGF2.getIrreduciblePolynomial(degree);
+ }
+
+ /**
+ * create a finite field GF(2^m) with the fixed field polynomial
+ *
+ * @param degree the degree of the field
+ * @param poly the field polynomial
+ */
+ public GF2mField(int degree, int poly)
+ {
+ if (degree != PolynomialRingGF2.degree(poly))
+ {
+ throw new IllegalArgumentException(
+ " Error: the degree is not correct");
+ }
+ if (!PolynomialRingGF2.isIrreducible(poly))
+ {
+ throw new IllegalArgumentException(
+ " Error: given polynomial is reducible");
+ }
+ this.degree = degree;
+ polynomial = poly;
+
+ }
+
+ public GF2mField(byte[] enc)
+ {
+ if (enc.length != 4)
+ {
+ throw new IllegalArgumentException(
+ "byte array is not an encoded finite field");
+ }
+ polynomial = LittleEndianConversions.OS2IP(enc);
+ if (!PolynomialRingGF2.isIrreducible(polynomial))
+ {
+ throw new IllegalArgumentException(
+ "byte array is not an encoded finite field");
+ }
+
+ degree = PolynomialRingGF2.degree(polynomial);
+ }
+
+ public GF2mField(GF2mField field)
+ {
+ degree = field.degree;
+ polynomial = field.polynomial;
+ }
+
+ /**
+ * return degree of the field
+ *
+ * @return degree of the field
+ */
+ public int getDegree()
+ {
+ return degree;
+ }
+
+ /**
+ * return the field polynomial
+ *
+ * @return the field polynomial
+ */
+ public int getPolynomial()
+ {
+ return polynomial;
+ }
+
+ /**
+ * return the encoded form of this field
+ *
+ * @return the field in byte array form
+ */
+ public byte[] getEncoded()
+ {
+ return LittleEndianConversions.I2OSP(polynomial);
+ }
+
+ /**
+ * Return sum of two elements
+ *
+ * @param a
+ * @param b
+ * @return a+b
+ */
+ public int add(int a, int b)
+ {
+ return a ^ b;
+ }
+
+ /**
+ * Return product of two elements
+ *
+ * @param a
+ * @param b
+ * @return a*b
+ */
+ public int mult(int a, int b)
+ {
+ return PolynomialRingGF2.modMultiply(a, b, polynomial);
+ }
+
+ /**
+ * compute exponentiation a^k
+ *
+ * @param a a field element a
+ * @param k k degree
+ * @return a^k
+ */
+ public int exp(int a, int k)
+ {
+ if (a == 0)
+ {
+ return 0;
+ }
+ if (a == 1)
+ {
+ return 1;
+ }
+ int result = 1;
+ if (k < 0)
+ {
+ a = inverse(a);
+ k = -k;
+ }
+ while (k != 0)
+ {
+ if ((k & 1) == 1)
+ {
+ result = mult(result, a);
+ }
+ a = mult(a, a);
+ k >>>= 1;
+ }
+ return result;
+ }
+
+ /**
+ * compute the multiplicative inverse of a
+ *
+ * @param a a field element a
+ * @return a<sup>-1</sup>
+ */
+ public int inverse(int a)
+ {
+ int d = (1 << degree) - 2;
+
+ return exp(a, d);
+ }
+
+ /**
+ * compute the square root of an integer
+ *
+ * @param a a field element a
+ * @return a<sup>1/2</sup>
+ */
+ public int sqRoot(int a)
+ {
+ for (int i = 1; i < degree; i++)
+ {
+ a = mult(a, a);
+ }
+ return a;
+ }
+
+ /**
+ * create a random field element using PRNG sr
+ *
+ * @param sr SecureRandom
+ * @return a random element
+ */
+ public int getRandomElement(SecureRandom sr)
+ {
+ int result = RandUtils.nextInt(sr, 1 << degree);
+ return result;
+ }
+
+ /**
+ * create a random non-zero field element
+ *
+ * @return a random element
+ */
+ public int getRandomNonZeroElement()
+ {
+ return getRandomNonZeroElement(new SecureRandom());
+ }
+
+ /**
+ * create a random non-zero field element using PRNG sr
+ *
+ * @param sr SecureRandom
+ * @return a random non-zero element
+ */
+ public int getRandomNonZeroElement(SecureRandom sr)
+ {
+ int controltime = 1 << 20;
+ int count = 0;
+ int result = RandUtils.nextInt(sr, 1 << degree);
+ while ((result == 0) && (count < controltime))
+ {
+ result = RandUtils.nextInt(sr, 1 << degree);
+ count++;
+ }
+ if (count == controltime)
+ {
+ result = 1;
+ }
+ return result;
+ }
+
+ /**
+ * @return true if e is encoded element of this field and false otherwise
+ */
+ public boolean isElementOfThisField(int e)
+ {
+ // e is encoded element of this field iff 0<= e < |2^m|
+ if (degree == 31)
+ {
+ return e >= 0;
+ }
+ return e >= 0 && e < (1 << degree);
+ }
+
+ /*
+ * help method for visual control
+ */
+ public String elementToStr(int a)
+ {
+ String s = "";
+ for (int i = 0; i < degree; i++)
+ {
+ if (((byte)a & 0x01) == 0)
+ {
+ s = "0" + s;
+ }
+ else
+ {
+ s = "1" + s;
+ }
+ a >>>= 1;
+ }
+ return s;
+ }
+
+ /**
+ * checks if given object is equal to this field.
+ * <p>
+ * The method returns false whenever the given object is not GF2m.
+ *
+ * @param other object
+ * @return true or false
+ */
+ public boolean equals(Object other)
+ {
+ if ((other == null) || !(other instanceof GF2mField))
+ {
+ return false;
+ }
+
+ GF2mField otherField = (GF2mField)other;
+
+ if ((degree == otherField.degree)
+ && (polynomial == otherField.polynomial))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public int hashCode()
+ {
+ return polynomial;
+ }
+
+ /**
+ * Returns a human readable form of this field.
+ *
+ * @return a human readable form of this field.
+ */
+ public String toString()
+ {
+ String str = "Finite Field GF(2^" + degree + ") = " + "GF(2)[X]/<"
+ + polyToString(polynomial) + "> ";
+ return str;
+ }
+
+ private static String polyToString(int p)
+ {
+ String str = "";
+ if (p == 0)
+ {
+ str = "0";
+ }
+ else
+ {
+ byte b = (byte)(p & 0x01);
+ if (b == 1)
+ {
+ str = "1";
+ }
+ p >>>= 1;
+ int i = 1;
+ while (p != 0)
+ {
+ b = (byte)(p & 0x01);
+ if (b == 1)
+ {
+ str = str + "+x^" + i;
+ }
+ p >>>= 1;
+ i++;
+ }
+ }
+ return str;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mMatrix.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mMatrix.java
new file mode 100644
index 00000000..d2989bcf
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mMatrix.java
@@ -0,0 +1,377 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+/**
+ * This class describes some operations with matrices over finite field <i>GF(2<sup>m</sup>)</i>
+ * with small <i>m</i> (1&lt; m &lt;32).
+ *
+ * @see Matrix
+ */
+public class GF2mMatrix
+ extends Matrix
+{
+
+ /**
+ * finite field GF(2^m)
+ */
+ protected GF2mField field;
+
+ /**
+ * For the matrix representation the array of type int[][] is used, thus
+ * every element of the array keeps one element of the matrix (element from
+ * finite field GF(2^m))
+ */
+ protected int[][] matrix;
+
+ /**
+ * Constructor.
+ *
+ * @param field a finite field GF(2^m)
+ * @param enc byte[] matrix in byte array form
+ */
+ public GF2mMatrix(GF2mField field, byte[] enc)
+ {
+
+ this.field = field;
+
+ // decode matrix
+ int d = 8;
+ int count = 1;
+ while (field.getDegree() > d)
+ {
+ count++;
+ d += 8;
+ }
+
+ if (enc.length < 5)
+ {
+ throw new IllegalArgumentException(
+ " Error: given array is not encoded matrix over GF(2^m)");
+ }
+
+ this.numRows = ((enc[3] & 0xff) << 24) ^ ((enc[2] & 0xff) << 16)
+ ^ ((enc[1] & 0xff) << 8) ^ (enc[0] & 0xff);
+
+ int n = count * this.numRows;
+
+ if ((this.numRows <= 0) || (((enc.length - 4) % n) != 0))
+ {
+ throw new IllegalArgumentException(
+ " Error: given array is not encoded matrix over GF(2^m)");
+ }
+
+ this.numColumns = (enc.length - 4) / n;
+
+ matrix = new int[this.numRows][this.numColumns];
+ count = 4;
+ for (int i = 0; i < this.numRows; i++)
+ {
+ for (int j = 0; j < this.numColumns; j++)
+ {
+ for (int jj = 0; jj < d; jj += 8)
+ {
+ matrix[i][j] ^= (enc[count++] & 0x000000ff) << jj;
+ }
+ if (!this.field.isElementOfThisField(matrix[i][j]))
+ {
+ throw new IllegalArgumentException(
+ " Error: given array is not encoded matrix over GF(2^m)");
+ }
+ }
+ }
+ }
+
+ /**
+ * Copy constructor.
+ *
+ * @param other another {@link GF2mMatrix}
+ */
+ public GF2mMatrix(GF2mMatrix other)
+ {
+ numRows = other.numRows;
+ numColumns = other.numColumns;
+ field = other.field;
+ matrix = new int[numRows][];
+ for (int i = 0; i < numRows; i++)
+ {
+ matrix[i] = IntUtils.clone(other.matrix[i]);
+ }
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param field a finite field GF(2^m)
+ * @param matrix the matrix as int array. Only the reference is copied.
+ */
+ protected GF2mMatrix(GF2mField field, int[][] matrix)
+ {
+ this.field = field;
+ this.matrix = matrix;
+ numRows = matrix.length;
+ numColumns = matrix[0].length;
+ }
+
+ /**
+ * @return a byte array encoding of this matrix
+ */
+ public byte[] getEncoded()
+ {
+ int d = 8;
+ int count = 1;
+ while (field.getDegree() > d)
+ {
+ count++;
+ d += 8;
+ }
+
+ byte[] bf = new byte[this.numRows * this.numColumns * count + 4];
+ bf[0] = (byte)(this.numRows & 0xff);
+ bf[1] = (byte)((this.numRows >>> 8) & 0xff);
+ bf[2] = (byte)((this.numRows >>> 16) & 0xff);
+ bf[3] = (byte)((this.numRows >>> 24) & 0xff);
+
+ count = 4;
+ for (int i = 0; i < this.numRows; i++)
+ {
+ for (int j = 0; j < this.numColumns; j++)
+ {
+ for (int jj = 0; jj < d; jj += 8)
+ {
+ bf[count++] = (byte)(matrix[i][j] >>> jj);
+ }
+ }
+ }
+
+ return bf;
+ }
+
+ /**
+ * Check if this is the zero matrix (i.e., all entries are zero).
+ *
+ * @return <tt>true</tt> if this is the zero matrix
+ */
+ public boolean isZero()
+ {
+ for (int i = 0; i < numRows; i++)
+ {
+ for (int j = 0; j < numColumns; j++)
+ {
+ if (matrix[i][j] != 0)
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Compute the inverse of this matrix.
+ *
+ * @return the inverse of this matrix (newly created).
+ */
+ public Matrix computeInverse()
+ {
+ if (numRows != numColumns)
+ {
+ throw new ArithmeticException("Matrix is not invertible.");
+ }
+
+ // clone this matrix
+ int[][] tmpMatrix = new int[numRows][numRows];
+ for (int i = numRows - 1; i >= 0; i--)
+ {
+ tmpMatrix[i] = IntUtils.clone(matrix[i]);
+ }
+
+ // initialize inverse matrix as unit matrix
+ int[][] invMatrix = new int[numRows][numRows];
+ for (int i = numRows - 1; i >= 0; i--)
+ {
+ invMatrix[i][i] = 1;
+ }
+
+ // simultaneously compute Gaussian reduction of tmpMatrix and unit
+ // matrix
+ for (int i = 0; i < numRows; i++)
+ {
+ // if diagonal element is zero
+ if (tmpMatrix[i][i] == 0)
+ {
+ boolean foundNonZero = false;
+ // find a non-zero element in the same column
+ for (int j = i + 1; j < numRows; j++)
+ {
+ if (tmpMatrix[j][i] != 0)
+ {
+ // found it, swap rows ...
+ foundNonZero = true;
+ swapColumns(tmpMatrix, i, j);
+ swapColumns(invMatrix, i, j);
+ // ... and quit searching
+ j = numRows;
+ continue;
+ }
+ }
+ // if no non-zero element was found
+ if (!foundNonZero)
+ {
+ // the matrix is not invertible
+ throw new ArithmeticException("Matrix is not invertible.");
+ }
+ }
+
+ // normalize i-th row
+ int coef = tmpMatrix[i][i];
+ int invCoef = field.inverse(coef);
+ multRowWithElementThis(tmpMatrix[i], invCoef);
+ multRowWithElementThis(invMatrix[i], invCoef);
+
+ // normalize all other rows
+ for (int j = 0; j < numRows; j++)
+ {
+ if (j != i)
+ {
+ coef = tmpMatrix[j][i];
+ if (coef != 0)
+ {
+ int[] tmpRow = multRowWithElement(tmpMatrix[i], coef);
+ int[] tmpInvRow = multRowWithElement(invMatrix[i], coef);
+ addToRow(tmpRow, tmpMatrix[j]);
+ addToRow(tmpInvRow, invMatrix[j]);
+ }
+ }
+ }
+ }
+
+ return new GF2mMatrix(field, invMatrix);
+ }
+
+ private static void swapColumns(int[][] matrix, int first, int second)
+ {
+ int[] tmp = matrix[first];
+ matrix[first] = matrix[second];
+ matrix[second] = tmp;
+ }
+
+ private void multRowWithElementThis(int[] row, int element)
+ {
+ for (int i = row.length - 1; i >= 0; i--)
+ {
+ row[i] = field.mult(row[i], element);
+ }
+ }
+
+ private int[] multRowWithElement(int[] row, int element)
+ {
+ int[] result = new int[row.length];
+ for (int i = row.length - 1; i >= 0; i--)
+ {
+ result[i] = field.mult(row[i], element);
+ }
+ return result;
+ }
+
+ /**
+ * Add one row to another.
+ *
+ * @param fromRow the addend
+ * @param toRow the row to add to
+ */
+ private void addToRow(int[] fromRow, int[] toRow)
+ {
+ for (int i = toRow.length - 1; i >= 0; i--)
+ {
+ toRow[i] = field.add(fromRow[i], toRow[i]);
+ }
+ }
+
+ public Matrix rightMultiply(Matrix a)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ public Matrix rightMultiply(Permutation perm)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ public Vector leftMultiply(Vector vector)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ public Vector rightMultiply(Vector vector)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /**
+ * Checks if given object is equal to this matrix. The method returns false
+ * whenever the given object is not a matrix over GF(2^m).
+ *
+ * @param other object
+ * @return true or false
+ */
+ public boolean equals(Object other)
+ {
+
+ if (other == null || !(other instanceof GF2mMatrix))
+ {
+ return false;
+ }
+
+ GF2mMatrix otherMatrix = (GF2mMatrix)other;
+
+ if ((!this.field.equals(otherMatrix.field))
+ || (otherMatrix.numRows != this.numColumns)
+ || (otherMatrix.numColumns != this.numColumns))
+ {
+ return false;
+ }
+
+ for (int i = 0; i < this.numRows; i++)
+ {
+ for (int j = 0; j < this.numColumns; j++)
+ {
+ if (this.matrix[i][j] != otherMatrix.matrix[i][j])
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ public int hashCode()
+ {
+ int hash = (this.field.hashCode() * 31 + numRows) * 31 + numColumns;
+ for (int i = 0; i < this.numRows; i++)
+ {
+ for (int j = 0; j < this.numColumns; j++)
+ {
+ hash = hash * 31 + matrix[i][j];
+ }
+ }
+ return hash;
+ }
+
+ public String toString()
+ {
+ String str = this.numRows + " x " + this.numColumns + " Matrix over "
+ + this.field.toString() + ": \n";
+
+ for (int i = 0; i < this.numRows; i++)
+ {
+ for (int j = 0; j < this.numColumns; j++)
+ {
+ str = str + this.field.elementToStr(matrix[i][j]) + " : ";
+ }
+ str = str + "\n";
+ }
+
+ return str;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mVector.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mVector.java
new file mode 100644
index 00000000..8e613e7b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mVector.java
@@ -0,0 +1,256 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+
+/**
+ * This class implements vectors over the finite field
+ * <tt>GF(2<sup>m</sup>)</tt> for small <tt>m</tt> (i.e.,
+ * <tt>1&lt;m&lt;32</tt>). It extends the abstract class {@link Vector}.
+ */
+public class GF2mVector
+ extends Vector
+{
+
+ /**
+ * the finite field this vector is defined over
+ */
+ private GF2mField field;
+
+ /**
+ * the element array
+ */
+ private int[] vector;
+
+ /**
+ * creates the vector over GF(2^m) of given length and with elements from
+ * array v (beginning at the first bit)
+ *
+ * @param field finite field
+ * @param v array with elements of vector
+ */
+ public GF2mVector(GF2mField field, byte[] v)
+ {
+ this.field = new GF2mField(field);
+
+ // decode vector
+ int d = 8;
+ int count = 1;
+ while (field.getDegree() > d)
+ {
+ count++;
+ d += 8;
+ }
+
+ if ((v.length % count) != 0)
+ {
+ throw new IllegalArgumentException(
+ "Byte array is not an encoded vector over the given finite field.");
+ }
+
+ length = v.length / count;
+ vector = new int[length];
+ count = 0;
+ for (int i = 0; i < vector.length; i++)
+ {
+ for (int j = 0; j < d; j += 8)
+ {
+ vector[i] |= (v[count++] & 0xff) << j;
+ }
+ if (!field.isElementOfThisField(vector[i]))
+ {
+ throw new IllegalArgumentException(
+ "Byte array is not an encoded vector over the given finite field.");
+ }
+ }
+ }
+
+ /**
+ * Create a new vector over <tt>GF(2<sup>m</sup>)</tt> of the given
+ * length and element array.
+ *
+ * @param field the finite field <tt>GF(2<sup>m</sup>)</tt>
+ * @param vector the element array
+ */
+ public GF2mVector(GF2mField field, int[] vector)
+ {
+ this.field = field;
+ length = vector.length;
+ for (int i = vector.length - 1; i >= 0; i--)
+ {
+ if (!field.isElementOfThisField(vector[i]))
+ {
+ throw new ArithmeticException(
+ "Element array is not specified over the given finite field.");
+ }
+ }
+ this.vector = IntUtils.clone(vector);
+ }
+
+ /**
+ * Copy constructor.
+ *
+ * @param other another {@link GF2mVector}
+ */
+ public GF2mVector(GF2mVector other)
+ {
+ field = new GF2mField(other.field);
+ length = other.length;
+ vector = IntUtils.clone(other.vector);
+ }
+
+ /**
+ * @return the finite field this vector is defined over
+ */
+ public GF2mField getField()
+ {
+ return field;
+ }
+
+ /**
+ * @return int[] form of this vector
+ */
+ public int[] getIntArrayForm()
+ {
+ return IntUtils.clone(vector);
+ }
+
+ /**
+ * @return a byte array encoding of this vector
+ */
+ public byte[] getEncoded()
+ {
+ int d = 8;
+ int count = 1;
+ while (field.getDegree() > d)
+ {
+ count++;
+ d += 8;
+ }
+
+ byte[] res = new byte[vector.length * count];
+ count = 0;
+ for (int i = 0; i < vector.length; i++)
+ {
+ for (int j = 0; j < d; j += 8)
+ {
+ res[count++] = (byte)(vector[i] >>> j);
+ }
+ }
+
+ return res;
+ }
+
+ /**
+ * @return whether this is the zero vector (i.e., all elements are zero)
+ */
+ public boolean isZero()
+ {
+ for (int i = vector.length - 1; i >= 0; i--)
+ {
+ if (vector[i] != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Add another vector to this vector. Method is not yet implemented.
+ *
+ * @param addend the other vector
+ * @return <tt>this + addend</tt>
+ * @throws ArithmeticException if the other vector is not defined over the same field as
+ * this vector.
+ * <p>
+ * TODO: implement this method
+ */
+ public Vector add(Vector addend)
+ {
+ throw new RuntimeException("not implemented");
+ }
+
+ /**
+ * Multiply this vector with a permutation.
+ *
+ * @param p the permutation
+ * @return <tt>this*p = p*this</tt>
+ */
+ public Vector multiply(Permutation p)
+ {
+ int[] pVec = p.getVector();
+ if (length != pVec.length)
+ {
+ throw new ArithmeticException(
+ "permutation size and vector size mismatch");
+ }
+
+ int[] result = new int[length];
+ for (int i = 0; i < pVec.length; i++)
+ {
+ result[i] = vector[pVec[i]];
+ }
+
+ return new GF2mVector(field, result);
+ }
+
+ /**
+ * Compare this vector with another object.
+ *
+ * @param other the other object
+ * @return the result of the comparison
+ */
+ public boolean equals(Object other)
+ {
+
+ if (!(other instanceof GF2mVector))
+ {
+ return false;
+ }
+ GF2mVector otherVec = (GF2mVector)other;
+
+ if (!field.equals(otherVec.field))
+ {
+ return false;
+ }
+
+ return IntUtils.equals(vector, otherVec.vector);
+ }
+
+ /**
+ * @return the hash code of this vector
+ */
+ public int hashCode()
+ {
+ int hash = this.field.hashCode();
+ hash = hash * 31 + vector.hashCode();
+ return hash;
+ }
+
+ /**
+ * @return a human readable form of this vector
+ */
+ public String toString()
+ {
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < vector.length; i++)
+ {
+ for (int j = 0; j < field.getDegree(); j++)
+ {
+ int r = j & 0x1f;
+ int bitMask = 1 << r;
+ int coeff = vector[i] & bitMask;
+ if (coeff != 0)
+ {
+ buf.append('1');
+ }
+ else
+ {
+ buf.append('0');
+ }
+ }
+ buf.append(' ');
+ }
+ return buf.toString();
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nElement.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nElement.java
new file mode 100644
index 00000000..a95b25f8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nElement.java
@@ -0,0 +1,186 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+
+/**
+ * This abstract class implements an element of the finite field <i>GF(2)<sup>n
+ * </sup></i> in either <i>optimal normal basis</i> representation (<i>ONB</i>)
+ * or in <i>polynomial</i> representation. It is extended by the classes <a
+ * href = GF2nONBElement.html><tt> GF2nONBElement</tt></a> and <a href =
+ * GF2nPolynomialElement.html> <tt>GF2nPolynomialElement</tt> </a>.
+ *
+ * @see GF2nPolynomialElement
+ * @see GF2nONBElement
+ * @see GF2nONBField
+ */
+public abstract class GF2nElement
+ implements GFElement
+{
+
+ // /////////////////////////////////////////////////////////////////////
+ // member variables
+ // /////////////////////////////////////////////////////////////////////
+
+ /**
+ * holds a pointer to this element's corresponding field.
+ */
+ protected GF2nField mField;
+
+ /**
+ * holds the extension degree <i>n</i> of this element's corresponding
+ * field.
+ */
+ protected int mDegree;
+
+ // /////////////////////////////////////////////////////////////////////
+ // pseudo-constructors
+ // /////////////////////////////////////////////////////////////////////
+
+ /**
+ * @return a copy of this GF2nElement
+ */
+ public abstract Object clone();
+
+ // /////////////////////////////////////////////////////////////////////
+ // assignments
+ // /////////////////////////////////////////////////////////////////////
+
+ /**
+ * Assign the value 0 to this element.
+ */
+ abstract void assignZero();
+
+ /**
+ * Assigns the value 1 to this element.
+ */
+ abstract void assignOne();
+
+ // /////////////////////////////////////////////////////////////////////
+ // access
+ // /////////////////////////////////////////////////////////////////////
+
+ /**
+ * Returns whether the rightmost bit of the bit representation is set. This
+ * is needed for data conversion according to 1363.
+ *
+ * @return true if the rightmost bit of this element is set
+ */
+ public abstract boolean testRightmostBit();
+
+ /**
+ * Checks whether the indexed bit of the bit representation is set
+ *
+ * @param index the index of the bit to test
+ * @return <tt>true</tt> if the indexed bit is set
+ */
+ abstract boolean testBit(int index);
+
+ /**
+ * Returns the field of this element.
+ *
+ * @return the field of this element
+ */
+ public final GF2nField getField()
+ {
+ return mField;
+ }
+
+ // /////////////////////////////////////////////////////////////////////
+ // arithmetic
+ // /////////////////////////////////////////////////////////////////////
+
+ /**
+ * Returns <tt>this</tt> element + 1.
+ *
+ * @return <tt>this</tt> + 1
+ */
+ public abstract GF2nElement increase();
+
+ /**
+ * Increases this element by one.
+ */
+ public abstract void increaseThis();
+
+ /**
+ * Compute the difference of this element and <tt>minuend</tt>.
+ *
+ * @param minuend the minuend
+ * @return <tt>this - minuend</tt> (newly created)
+ * @throws DifferentFieldsException if the elements are of different fields.
+ */
+ public final GFElement subtract(GFElement minuend)
+ throws RuntimeException
+ {
+ return add(minuend);
+ }
+
+ /**
+ * Compute the difference of this element and <tt>minuend</tt>,
+ * overwriting this element.
+ *
+ * @param minuend the minuend
+ * @throws DifferentFieldsException if the elements are of different fields.
+ */
+ public final void subtractFromThis(GFElement minuend)
+ {
+ addToThis(minuend);
+ }
+
+ /**
+ * Returns <tt>this</tt> element to the power of 2.
+ *
+ * @return <tt>this</tt><sup>2</sup>
+ */
+ public abstract GF2nElement square();
+
+ /**
+ * Squares <tt>this</tt> element.
+ */
+ public abstract void squareThis();
+
+ /**
+ * Compute the square root of this element and return the result in a new
+ * {@link GF2nElement}.
+ *
+ * @return <tt>this<sup>1/2</sup></tt> (newly created)
+ */
+ public abstract GF2nElement squareRoot();
+
+ /**
+ * Compute the square root of this element.
+ */
+ public abstract void squareRootThis();
+
+ /**
+ * Performs a basis transformation of this element to the given GF2nField
+ * <tt>basis</tt>.
+ *
+ * @param basis the GF2nField representation to transform this element to
+ * @return this element in the representation of <tt>basis</tt>
+ * @throws DifferentFieldsException if <tt>this</tt> cannot be converted according to
+ * <tt>basis</tt>.
+ */
+ public final GF2nElement convert(GF2nField basis)
+ throws RuntimeException
+ {
+ return mField.convert(this, basis);
+ }
+
+ /**
+ * Returns the trace of this element.
+ *
+ * @return the trace of this element
+ */
+ public abstract int trace();
+
+ /**
+ * Solves a quadratic equation.<br>
+ * Let z<sup>2</sup> + z = <tt>this</tt>. Then this method returns z.
+ *
+ * @return z with z<sup>2</sup> + z = <tt>this</tt>
+ * @throws NoSolutionException if z<sup>2</sup> + z = <tt>this</tt> does not have a
+ * solution
+ */
+ public abstract GF2nElement solveQuadraticEquation()
+ throws RuntimeException;
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nField.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nField.java
new file mode 100644
index 00000000..d1aa1363
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nField.java
@@ -0,0 +1,292 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+
+import java.util.Vector;
+
+
+/**
+ * This abstract class defines the finite field <i>GF(2<sup>n</sup>)</i>. It
+ * holds the extension degree <i>n</i>, the characteristic, the irreducible
+ * fieldpolynomial and conversion matrices. GF2nField is implemented by the
+ * classes GF2nPolynomialField and GF2nONBField.
+ *
+ * @see GF2nONBField
+ * @see GF2nPolynomialField
+ */
+public abstract class GF2nField
+{
+
+ /**
+ * the degree of this field
+ */
+ protected int mDegree;
+
+ /**
+ * the irreducible fieldPolynomial stored in normal order (also for ONB)
+ */
+ protected GF2Polynomial fieldPolynomial;
+
+ /**
+ * holds a list of GF2nFields to which elements have been converted and thus
+ * a COB-Matrix exists
+ */
+ protected Vector fields;
+
+ /**
+ * the COB matrices
+ */
+ protected Vector matrices;
+
+ /**
+ * Returns the degree <i>n</i> of this field.
+ *
+ * @return the degree <i>n</i> of this field
+ */
+ public final int getDegree()
+ {
+ return mDegree;
+ }
+
+ /**
+ * Returns the fieldpolynomial as a new Bitstring.
+ *
+ * @return a copy of the fieldpolynomial as a new Bitstring
+ */
+ public final GF2Polynomial getFieldPolynomial()
+ {
+ if (fieldPolynomial == null)
+ {
+ computeFieldPolynomial();
+ }
+ return new GF2Polynomial(fieldPolynomial);
+ }
+
+ /**
+ * Decides whether the given object <tt>other</tt> is the same as this
+ * field.
+ *
+ * @param other another object
+ * @return (this == other)
+ */
+ public final boolean equals(Object other)
+ {
+ if (other == null || !(other instanceof GF2nField))
+ {
+ return false;
+ }
+
+ GF2nField otherField = (GF2nField)other;
+
+ if (otherField.mDegree != mDegree)
+ {
+ return false;
+ }
+ if (!fieldPolynomial.equals(otherField.fieldPolynomial))
+ {
+ return false;
+ }
+ if ((this instanceof GF2nPolynomialField)
+ && !(otherField instanceof GF2nPolynomialField))
+ {
+ return false;
+ }
+ if ((this instanceof GF2nONBField)
+ && !(otherField instanceof GF2nONBField))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @return the hash code of this field
+ */
+ public int hashCode()
+ {
+ return mDegree + fieldPolynomial.hashCode();
+ }
+
+ /**
+ * Computes a random root from the given irreducible fieldpolynomial
+ * according to IEEE 1363 algorithm A.5.6. This cal take very long for big
+ * degrees.
+ *
+ * @param B0FieldPolynomial the fieldpolynomial if the other basis as a Bitstring
+ * @return a random root of BOFieldPolynomial in representation according to
+ * this field
+ * @see "P1363 A.5.6, p103f"
+ */
+ protected abstract GF2nElement getRandomRoot(GF2Polynomial B0FieldPolynomial);
+
+ /**
+ * Computes the change-of-basis matrix for basis conversion according to
+ * 1363. The result is stored in the lists fields and matrices.
+ *
+ * @param B1 the GF2nField to convert to
+ * @see "P1363 A.7.3, p111ff"
+ */
+ protected abstract void computeCOBMatrix(GF2nField B1);
+
+ /**
+ * Computes the fieldpolynomial. This can take a long time for big degrees.
+ */
+ protected abstract void computeFieldPolynomial();
+
+ /**
+ * Inverts the given matrix represented as bitstrings.
+ *
+ * @param matrix the matrix to invert as a Bitstring[]
+ * @return matrix^(-1)
+ */
+ protected final GF2Polynomial[] invertMatrix(GF2Polynomial[] matrix)
+ {
+ GF2Polynomial[] a = new GF2Polynomial[matrix.length];
+ GF2Polynomial[] inv = new GF2Polynomial[matrix.length];
+ GF2Polynomial dummy;
+ int i, j;
+ // initialize a as a copy of matrix and inv as E(inheitsmatrix)
+ for (i = 0; i < mDegree; i++)
+ {
+ try
+ {
+ a[i] = new GF2Polynomial(matrix[i]);
+ inv[i] = new GF2Polynomial(mDegree);
+ inv[i].setBit(mDegree - 1 - i);
+ }
+ catch (RuntimeException BDNEExc)
+ {
+ BDNEExc.printStackTrace();
+ }
+ }
+ // construct triangle matrix so that for each a[i] the first i bits are
+ // zero
+ for (i = 0; i < mDegree - 1; i++)
+ {
+ // find column where bit i is set
+ j = i;
+ while ((j < mDegree) && !a[j].testBit(mDegree - 1 - i))
+ {
+ j++;
+ }
+ if (j >= mDegree)
+ {
+ throw new RuntimeException(
+ "GF2nField.invertMatrix: Matrix cannot be inverted!");
+ }
+ if (i != j)
+ { // swap a[i]/a[j] and inv[i]/inv[j]
+ dummy = a[i];
+ a[i] = a[j];
+ a[j] = dummy;
+ dummy = inv[i];
+ inv[i] = inv[j];
+ inv[j] = dummy;
+ }
+ for (j = i + 1; j < mDegree; j++)
+ { // add column i to all columns>i
+ // having their i-th bit set
+ if (a[j].testBit(mDegree - 1 - i))
+ {
+ a[j].addToThis(a[i]);
+ inv[j].addToThis(inv[i]);
+ }
+ }
+ }
+ // construct Einheitsmatrix from a
+ for (i = mDegree - 1; i > 0; i--)
+ {
+ for (j = i - 1; j >= 0; j--)
+ { // eliminate the i-th bit in all
+ // columns < i
+ if (a[j].testBit(mDegree - 1 - i))
+ {
+ a[j].addToThis(a[i]);
+ inv[j].addToThis(inv[i]);
+ }
+ }
+ }
+ return inv;
+ }
+
+ /**
+ * Converts the given element in representation according to this field to a
+ * new element in representation according to B1 using the change-of-basis
+ * matrix calculated by computeCOBMatrix.
+ *
+ * @param elem the GF2nElement to convert
+ * @param basis the basis to convert <tt>elem</tt> to
+ * @return <tt>elem</tt> converted to a new element representation
+ * according to <tt>basis</tt>
+ * @throws DifferentFieldsException if <tt>elem</tt> cannot be converted according to
+ * <tt>basis</tt>.
+ * @see GF2nField#computeCOBMatrix
+ * @see GF2nField#getRandomRoot
+ * @see GF2nPolynomial
+ * @see "P1363 A.7 p109ff"
+ */
+ public final GF2nElement convert(GF2nElement elem, GF2nField basis)
+ throws RuntimeException
+ {
+ if (basis == this)
+ {
+ return (GF2nElement)elem.clone();
+ }
+ if (fieldPolynomial.equals(basis.fieldPolynomial))
+ {
+ return (GF2nElement)elem.clone();
+ }
+ if (mDegree != basis.mDegree)
+ {
+ throw new RuntimeException("GF2nField.convert: B1 has a"
+ + " different degree and thus cannot be coverted to!");
+ }
+
+ int i;
+ GF2Polynomial[] COBMatrix;
+ i = fields.indexOf(basis);
+ if (i == -1)
+ {
+ computeCOBMatrix(basis);
+ i = fields.indexOf(basis);
+ }
+ COBMatrix = (GF2Polynomial[])matrices.elementAt(i);
+
+ GF2nElement elemCopy = (GF2nElement)elem.clone();
+ if (elemCopy instanceof GF2nONBElement)
+ {
+ // remember: ONB treats its bits in reverse order
+ ((GF2nONBElement)elemCopy).reverseOrder();
+ }
+ GF2Polynomial bs = new GF2Polynomial(mDegree, elemCopy.toFlexiBigInt());
+ bs.expandN(mDegree);
+ GF2Polynomial result = new GF2Polynomial(mDegree);
+ for (i = 0; i < mDegree; i++)
+ {
+ if (bs.vectorMult(COBMatrix[i]))
+ {
+ result.setBit(mDegree - 1 - i);
+ }
+ }
+ if (basis instanceof GF2nPolynomialField)
+ {
+ return new GF2nPolynomialElement((GF2nPolynomialField)basis,
+ result);
+ }
+ else if (basis instanceof GF2nONBField)
+ {
+ GF2nONBElement res = new GF2nONBElement((GF2nONBField)basis,
+ result.toFlexiBigInt());
+ // TODO Remember: ONB treats its Bits in reverse order !!!
+ res.reverseOrder();
+ return res;
+ }
+ else
+ {
+ throw new RuntimeException(
+ "GF2nField.convert: B1 must be an instance of "
+ + "GF2nPolynomialField or GF2nONBField!");
+ }
+
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nONBElement.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nONBElement.java
new file mode 100644
index 00000000..b14fdd1a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nONBElement.java
@@ -0,0 +1,1154 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+
+import java.math.BigInteger;
+import java.util.Random;
+
+/**
+ * This class implements an element of the finite field <i>GF(2<sup>n </sup>)</i>.
+ * It is represented in an optimal normal basis representation and holds the
+ * pointer <tt>mField</tt> to its corresponding field.
+ *
+ * @see GF2nField
+ * @see GF2nElement
+ */
+public class GF2nONBElement
+ extends GF2nElement
+{
+
+ // /////////////////////////////////////////////////////////////////////
+ // member variables
+ // /////////////////////////////////////////////////////////////////////
+
+ private static final long[] mBitmask = new long[]{0x0000000000000001L,
+ 0x0000000000000002L, 0x0000000000000004L, 0x0000000000000008L,
+ 0x0000000000000010L, 0x0000000000000020L, 0x0000000000000040L,
+ 0x0000000000000080L, 0x0000000000000100L, 0x0000000000000200L,
+ 0x0000000000000400L, 0x0000000000000800L, 0x0000000000001000L,
+ 0x0000000000002000L, 0x0000000000004000L, 0x0000000000008000L,
+ 0x0000000000010000L, 0x0000000000020000L, 0x0000000000040000L,
+ 0x0000000000080000L, 0x0000000000100000L, 0x0000000000200000L,
+ 0x0000000000400000L, 0x0000000000800000L, 0x0000000001000000L,
+ 0x0000000002000000L, 0x0000000004000000L, 0x0000000008000000L,
+ 0x0000000010000000L, 0x0000000020000000L, 0x0000000040000000L,
+ 0x0000000080000000L, 0x0000000100000000L, 0x0000000200000000L,
+ 0x0000000400000000L, 0x0000000800000000L, 0x0000001000000000L,
+ 0x0000002000000000L, 0x0000004000000000L, 0x0000008000000000L,
+ 0x0000010000000000L, 0x0000020000000000L, 0x0000040000000000L,
+ 0x0000080000000000L, 0x0000100000000000L, 0x0000200000000000L,
+ 0x0000400000000000L, 0x0000800000000000L, 0x0001000000000000L,
+ 0x0002000000000000L, 0x0004000000000000L, 0x0008000000000000L,
+ 0x0010000000000000L, 0x0020000000000000L, 0x0040000000000000L,
+ 0x0080000000000000L, 0x0100000000000000L, 0x0200000000000000L,
+ 0x0400000000000000L, 0x0800000000000000L, 0x1000000000000000L,
+ 0x2000000000000000L, 0x4000000000000000L, 0x8000000000000000L};
+
+ private static final long[] mMaxmask = new long[]{0x0000000000000001L,
+ 0x0000000000000003L, 0x0000000000000007L, 0x000000000000000FL,
+ 0x000000000000001FL, 0x000000000000003FL, 0x000000000000007FL,
+ 0x00000000000000FFL, 0x00000000000001FFL, 0x00000000000003FFL,
+ 0x00000000000007FFL, 0x0000000000000FFFL, 0x0000000000001FFFL,
+ 0x0000000000003FFFL, 0x0000000000007FFFL, 0x000000000000FFFFL,
+ 0x000000000001FFFFL, 0x000000000003FFFFL, 0x000000000007FFFFL,
+ 0x00000000000FFFFFL, 0x00000000001FFFFFL, 0x00000000003FFFFFL,
+ 0x00000000007FFFFFL, 0x0000000000FFFFFFL, 0x0000000001FFFFFFL,
+ 0x0000000003FFFFFFL, 0x0000000007FFFFFFL, 0x000000000FFFFFFFL,
+ 0x000000001FFFFFFFL, 0x000000003FFFFFFFL, 0x000000007FFFFFFFL,
+ 0x00000000FFFFFFFFL, 0x00000001FFFFFFFFL, 0x00000003FFFFFFFFL,
+ 0x00000007FFFFFFFFL, 0x0000000FFFFFFFFFL, 0x0000001FFFFFFFFFL,
+ 0x0000003FFFFFFFFFL, 0x0000007FFFFFFFFFL, 0x000000FFFFFFFFFFL,
+ 0x000001FFFFFFFFFFL, 0x000003FFFFFFFFFFL, 0x000007FFFFFFFFFFL,
+ 0x00000FFFFFFFFFFFL, 0x00001FFFFFFFFFFFL, 0x00003FFFFFFFFFFFL,
+ 0x00007FFFFFFFFFFFL, 0x0000FFFFFFFFFFFFL, 0x0001FFFFFFFFFFFFL,
+ 0x0003FFFFFFFFFFFFL, 0x0007FFFFFFFFFFFFL, 0x000FFFFFFFFFFFFFL,
+ 0x001FFFFFFFFFFFFFL, 0x003FFFFFFFFFFFFFL, 0x007FFFFFFFFFFFFFL,
+ 0x00FFFFFFFFFFFFFFL, 0x01FFFFFFFFFFFFFFL, 0x03FFFFFFFFFFFFFFL,
+ 0x07FFFFFFFFFFFFFFL, 0x0FFFFFFFFFFFFFFFL, 0x1FFFFFFFFFFFFFFFL,
+ 0x3FFFFFFFFFFFFFFFL, 0x7FFFFFFFFFFFFFFFL, 0xFFFFFFFFFFFFFFFFL};
+
+ // mIBy64[j * 16 + i] = (j * 16 + i)/64
+ // i =
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ //
+ private static final int[] mIBY64 = new int[]{
+ // j =
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 8
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 9
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 10
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 11
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 12
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 13
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 14
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 15
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 16
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 17
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 18
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 19
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 20
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 21
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 22
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 // 23
+ };
+
+ private static final int MAXLONG = 64;
+
+ /**
+ * holds the lenght of the polynomial with 64 bit sized fields.
+ */
+ private int mLength;
+
+ /**
+ * holds the value of mDeg % MAXLONG.
+ */
+ private int mBit;
+
+ /**
+ * holds this element in ONB representation.
+ */
+ private long[] mPol;
+
+ // /////////////////////////////////////////////////////////////////////
+ // constructors
+ // /////////////////////////////////////////////////////////////////////
+
+ /**
+ * Construct a random element over the field <tt>gf2n</tt>, using the
+ * specified source of randomness.
+ *
+ * @param gf2n the field
+ * @param rand the source of randomness
+ */
+ public GF2nONBElement(GF2nONBField gf2n, Random rand)
+ {
+ mField = gf2n;
+ mDegree = mField.getDegree();
+ mLength = gf2n.getONBLength();
+ mBit = gf2n.getONBBit();
+ mPol = new long[mLength];
+ if (mLength > 1)
+ {
+ for (int j = 0; j < mLength - 1; j++)
+ {
+ mPol[j] = rand.nextLong();
+ }
+ long last = rand.nextLong();
+ mPol[mLength - 1] = last >>> (MAXLONG - mBit);
+ }
+ else
+ {
+ mPol[0] = rand.nextLong();
+ mPol[0] = mPol[0] >>> (MAXLONG - mBit);
+ }
+ }
+
+ /**
+ * Construct a new GF2nONBElement from its encoding.
+ *
+ * @param gf2n the field
+ * @param e the encoded element
+ */
+ public GF2nONBElement(GF2nONBField gf2n, byte[] e)
+ {
+ mField = gf2n;
+ mDegree = mField.getDegree();
+ mLength = gf2n.getONBLength();
+ mBit = gf2n.getONBBit();
+ mPol = new long[mLength];
+ assign(e);
+ }
+
+ /**
+ * Construct the element of the field <tt>gf2n</tt> with the specified
+ * value <tt>val</tt>.
+ *
+ * @param gf2n the field
+ * @param val the value represented by a BigInteger
+ */
+ public GF2nONBElement(GF2nONBField gf2n, BigInteger val)
+ {
+ mField = gf2n;
+ mDegree = mField.getDegree();
+ mLength = gf2n.getONBLength();
+ mBit = gf2n.getONBBit();
+ mPol = new long[mLength];
+ assign(val);
+ }
+
+ /**
+ * Construct the element of the field <tt>gf2n</tt> with the specified
+ * value <tt>val</tt>.
+ *
+ * @param gf2n the field
+ * @param val the value in ONB representation
+ */
+ private GF2nONBElement(GF2nONBField gf2n, long[] val)
+ {
+ mField = gf2n;
+ mDegree = mField.getDegree();
+ mLength = gf2n.getONBLength();
+ mBit = gf2n.getONBBit();
+ mPol = val;
+ }
+
+ // /////////////////////////////////////////////////////////////////////
+ // pseudo-constructors
+ // /////////////////////////////////////////////////////////////////////
+
+ /**
+ * Copy constructor.
+ *
+ * @param gf2n the field
+ */
+ public GF2nONBElement(GF2nONBElement gf2n)
+ {
+
+ mField = gf2n.mField;
+ mDegree = mField.getDegree();
+ mLength = ((GF2nONBField)mField).getONBLength();
+ mBit = ((GF2nONBField)mField).getONBBit();
+ mPol = new long[mLength];
+ assign(gf2n.getElement());
+ }
+
+ /**
+ * Create a new GF2nONBElement by cloning this GF2nPolynomialElement.
+ *
+ * @return a copy of this element
+ */
+ public Object clone()
+ {
+ return new GF2nONBElement(this);
+ }
+
+ /**
+ * Create the zero element.
+ *
+ * @param gf2n the finite field
+ * @return the zero element in the given finite field
+ */
+ public static GF2nONBElement ZERO(GF2nONBField gf2n)
+ {
+ long[] polynomial = new long[gf2n.getONBLength()];
+ return new GF2nONBElement(gf2n, polynomial);
+ }
+
+ /**
+ * Create the one element.
+ *
+ * @param gf2n the finite field
+ * @return the one element in the given finite field
+ */
+ public static GF2nONBElement ONE(GF2nONBField gf2n)
+ {
+ int mLength = gf2n.getONBLength();
+ long[] polynomial = new long[mLength];
+
+ // fill mDegree coefficients with one's
+ for (int i = 0; i < mLength - 1; i++)
+ {
+ polynomial[i] = 0xffffffffffffffffL;
+ }
+ polynomial[mLength - 1] = mMaxmask[gf2n.getONBBit() - 1];
+
+ return new GF2nONBElement(gf2n, polynomial);
+ }
+
+ // /////////////////////////////////////////////////////////////////////
+ // assignments
+ // /////////////////////////////////////////////////////////////////////
+
+ /**
+ * assigns to this element the zero element
+ */
+ void assignZero()
+ {
+ mPol = new long[mLength];
+ }
+
+ /**
+ * assigns to this element the one element
+ */
+ void assignOne()
+ {
+ // fill mDegree coefficients with one's
+ for (int i = 0; i < mLength - 1; i++)
+ {
+ mPol[i] = 0xffffffffffffffffL;
+ }
+ mPol[mLength - 1] = mMaxmask[mBit - 1];
+ }
+
+ /**
+ * assigns to this element the value <tt>val</tt>.
+ *
+ * @param val the value represented by a BigInteger
+ */
+ private void assign(BigInteger val)
+ {
+ assign(val.toByteArray());
+ }
+
+ /**
+ * assigns to this element the value <tt>val</tt>.
+ *
+ * @param val the value in ONB representation
+ */
+ private void assign(long[] val)
+ {
+ System.arraycopy(val, 0, mPol, 0, mLength);
+ }
+
+ /**
+ * assigns to this element the value <tt>val</tt>. First: inverting the
+ * order of val into reversed[]. That means: reversed[0] = val[length - 1],
+ * ..., reversed[reversed.length - 1] = val[0]. Second: mPol[0] = sum{i = 0,
+ * ... 7} (val[i]<<(i*8)) .... mPol[1] = sum{i = 8, ... 15} (val[i]<<(i*8))
+ *
+ * @param val the value in ONB representation
+ */
+ private void assign(byte[] val)
+ {
+ int j;
+ mPol = new long[mLength];
+ for (j = 0; j < val.length; j++)
+ {
+ mPol[j >>> 3] |= (val[val.length - 1 - j] & 0x00000000000000ffL) << ((j & 0x07) << 3);
+ }
+ }
+
+ // /////////////////////////////////////////////////////////////////
+ // comparison
+ // /////////////////////////////////////////////////////////////////
+
+ /**
+ * Checks whether this element is zero.
+ *
+ * @return <tt>true</tt> if <tt>this</tt> is the zero element
+ */
+ public boolean isZero()
+ {
+
+ boolean result = true;
+
+ for (int i = 0; i < mLength && result; i++)
+ {
+ result = result && ((mPol[i] & 0xFFFFFFFFFFFFFFFFL) == 0);
+ }
+
+ return result;
+ }
+
+ /**
+ * Checks whether this element is one.
+ *
+ * @return <tt>true</tt> if <tt>this</tt> is the one element
+ */
+ public boolean isOne()
+ {
+
+ boolean result = true;
+
+ for (int i = 0; i < mLength - 1 && result; i++)
+ {
+ result = result
+ && ((mPol[i] & 0xFFFFFFFFFFFFFFFFL) == 0xFFFFFFFFFFFFFFFFL);
+ }
+
+ if (result)
+ {
+ result = result
+ && ((mPol[mLength - 1] & mMaxmask[mBit - 1]) == mMaxmask[mBit - 1]);
+ }
+
+ return result;
+ }
+
+ /**
+ * Compare this element with another object.
+ *
+ * @param other the other object
+ * @return <tt>true</tt> if the two objects are equal, <tt>false</tt>
+ * otherwise
+ */
+ public boolean equals(Object other)
+ {
+ if (other == null || !(other instanceof GF2nONBElement))
+ {
+ return false;
+ }
+
+ GF2nONBElement otherElem = (GF2nONBElement)other;
+
+ for (int i = 0; i < mLength; i++)
+ {
+ if (mPol[i] != otherElem.mPol[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * @return the hash code of this element
+ */
+ public int hashCode()
+ {
+ return mPol.hashCode();
+ }
+
+ // /////////////////////////////////////////////////////////////////////
+ // access
+ // /////////////////////////////////////////////////////////////////////
+
+ /**
+ * Returns whether the highest bit of the bit representation is set
+ *
+ * @return true, if the highest bit of mPol is set, false, otherwise
+ */
+ public boolean testRightmostBit()
+ {
+ // due to the reverse bit order (compared to 1363) this method returns
+ // the value of the leftmost bit
+ return (mPol[mLength - 1] & mBitmask[mBit - 1]) != 0L;
+ }
+
+ /**
+ * Checks whether the indexed bit of the bit representation is set. Warning:
+ * GF2nONBElement currently stores its bits in reverse order (compared to
+ * 1363) !!!
+ *
+ * @param index the index of the bit to test
+ * @return <tt>true</tt> if the indexed bit of mPol is set, <tt>false</tt>
+ * otherwise.
+ */
+ boolean testBit(int index)
+ {
+ if (index < 0 || index > mDegree)
+ {
+ return false;
+ }
+ long test = mPol[index >>> 6] & mBitmask[index & 0x3f];
+ return test != 0x0L;
+ }
+
+ /**
+ * @return this element in its ONB representation
+ */
+ private long[] getElement()
+ {
+
+ long[] result = new long[mPol.length];
+ System.arraycopy(mPol, 0, result, 0, mPol.length);
+
+ return result;
+ }
+
+ /**
+ * Returns the ONB representation of this element. The Bit-Order is
+ * exchanged (according to 1363)!
+ *
+ * @return this element in its representation and reverse bit-order
+ */
+ private long[] getElementReverseOrder()
+ {
+ long[] result = new long[mPol.length];
+ for (int i = 0; i < mDegree; i++)
+ {
+ if (testBit(mDegree - i - 1))
+ {
+ result[i >>> 6] |= mBitmask[i & 0x3f];
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Reverses the bit-order in this element(according to 1363). This is a
+ * hack!
+ */
+ void reverseOrder()
+ {
+ mPol = getElementReverseOrder();
+ }
+
+ // /////////////////////////////////////////////////////////////////////
+ // arithmetic
+ // /////////////////////////////////////////////////////////////////////
+
+ /**
+ * Compute the sum of this element and <tt>addend</tt>.
+ *
+ * @param addend the addend
+ * @return <tt>this + other</tt> (newly created)
+ * @throws DifferentFieldsException if the elements are of different fields.
+ */
+ public GFElement add(GFElement addend)
+ throws RuntimeException
+ {
+ GF2nONBElement result = new GF2nONBElement(this);
+ result.addToThis(addend);
+ return result;
+ }
+
+ /**
+ * Compute <tt>this + addend</tt> (overwrite <tt>this</tt>).
+ *
+ * @param addend the addend
+ * @throws DifferentFieldsException if the elements are of different fields.
+ */
+ public void addToThis(GFElement addend)
+ throws RuntimeException
+ {
+ if (!(addend instanceof GF2nONBElement))
+ {
+ throw new RuntimeException();
+ }
+ if (!mField.equals(((GF2nONBElement)addend).mField))
+ {
+ throw new RuntimeException();
+ }
+
+ for (int i = 0; i < mLength; i++)
+ {
+ mPol[i] ^= ((GF2nONBElement)addend).mPol[i];
+ }
+ }
+
+ /**
+ * returns <tt>this</tt> element + 1.
+ *
+ * @return <tt>this</tt> + 1
+ */
+ public GF2nElement increase()
+ {
+ GF2nONBElement result = new GF2nONBElement(this);
+ result.increaseThis();
+ return result;
+ }
+
+ /**
+ * increases <tt>this</tt> element.
+ */
+ public void increaseThis()
+ {
+ addToThis(ONE((GF2nONBField)mField));
+ }
+
+ /**
+ * Compute the product of this element and <tt>factor</tt>.
+ *
+ * @param factor the factor
+ * @return <tt>this * factor</tt> (newly created)
+ * @throws DifferentFieldsException if the elements are of different fields.
+ */
+ public GFElement multiply(GFElement factor)
+ throws RuntimeException
+ {
+ GF2nONBElement result = new GF2nONBElement(this);
+ result.multiplyThisBy(factor);
+ return result;
+ }
+
+ /**
+ * Compute <tt>this * factor</tt> (overwrite <tt>this</tt>).
+ *
+ * @param factor the factor
+ * @throws DifferentFieldsException if the elements are of different fields.
+ */
+ public void multiplyThisBy(GFElement factor)
+ throws RuntimeException
+ {
+
+ if (!(factor instanceof GF2nONBElement))
+ {
+ throw new RuntimeException("The elements have different"
+ + " representation: not yet" + " implemented");
+ }
+ if (!mField.equals(((GF2nONBElement)factor).mField))
+ {
+ throw new RuntimeException();
+ }
+
+ if (equals(factor))
+ {
+ squareThis();
+ }
+ else
+ {
+
+ long[] a = mPol;
+ long[] b = ((GF2nONBElement)factor).mPol;
+ long[] c = new long[mLength];
+
+ int[][] m = ((GF2nONBField)mField).mMult;
+
+ int degf, degb, s, fielda, fieldb, bita, bitb;
+ degf = mLength - 1;
+ degb = mBit - 1;
+ s = 0;
+
+ long TWOTOMAXLONGM1 = mBitmask[MAXLONG - 1];
+ long TWOTODEGB = mBitmask[degb];
+
+ boolean old, now;
+
+ // the product c of a and b (a*b = c) is calculated in mDegree
+ // cicles
+ // in every cicle one coefficient of c is calculated and stored
+ // k indicates the coefficient
+ //
+ for (int k = 0; k < mDegree; k++)
+ {
+
+ s = 0;
+
+ for (int i = 0; i < mDegree; i++)
+ {
+
+ // fielda = i / MAXLONG
+ //
+ fielda = mIBY64[i];
+
+ // bita = i % MAXLONG
+ //
+ bita = i & (MAXLONG - 1);
+
+ // fieldb = m[i][0] / MAXLONG
+ //
+ fieldb = mIBY64[m[i][0]];
+
+ // bitb = m[i][0] % MAXLONG
+ //
+ bitb = m[i][0] & (MAXLONG - 1);
+
+ if ((a[fielda] & mBitmask[bita]) != 0)
+ {
+
+ if ((b[fieldb] & mBitmask[bitb]) != 0)
+ {
+ s ^= 1;
+ }
+
+ if (m[i][1] != -1)
+ {
+
+ // fieldb = m[i][1] / MAXLONG
+ //
+ fieldb = mIBY64[m[i][1]];
+
+ // bitb = m[i][1] % MAXLONG
+ //
+ bitb = m[i][1] & (MAXLONG - 1);
+
+ if ((b[fieldb] & mBitmask[bitb]) != 0)
+ {
+ s ^= 1;
+ }
+
+ }
+ }
+ }
+ fielda = mIBY64[k];
+ bita = k & (MAXLONG - 1);
+
+ if (s != 0)
+ {
+ c[fielda] ^= mBitmask[bita];
+ }
+
+ // Circular shift of x and y one bit to the right,
+ // respectively.
+
+ if (mLength > 1)
+ {
+
+ // Shift x.
+ //
+ old = (a[degf] & 1) == 1;
+
+ for (int i = degf - 1; i >= 0; i--)
+ {
+ now = (a[i] & 1) != 0;
+
+ a[i] = a[i] >>> 1;
+
+ if (old)
+ {
+ a[i] ^= TWOTOMAXLONGM1;
+ }
+
+ old = now;
+ }
+ a[degf] = a[degf] >>> 1;
+
+ if (old)
+ {
+ a[degf] ^= TWOTODEGB;
+ }
+
+ // Shift y.
+ //
+ old = (b[degf] & 1) == 1;
+
+ for (int i = degf - 1; i >= 0; i--)
+ {
+ now = (b[i] & 1) != 0;
+
+ b[i] = b[i] >>> 1;
+
+ if (old)
+ {
+ b[i] ^= TWOTOMAXLONGM1;
+ }
+
+ old = now;
+ }
+
+ b[degf] = b[degf] >>> 1;
+
+ if (old)
+ {
+ b[degf] ^= TWOTODEGB;
+ }
+ }
+ else
+ {
+ old = (a[0] & 1) == 1;
+ a[0] = a[0] >>> 1;
+
+ if (old)
+ {
+ a[0] ^= TWOTODEGB;
+ }
+
+ old = (b[0] & 1) == 1;
+ b[0] = b[0] >>> 1;
+
+ if (old)
+ {
+ b[0] ^= TWOTODEGB;
+ }
+ }
+ }
+ assign(c);
+ }
+ }
+
+ /**
+ * returns <tt>this</tt> element to the power of 2.
+ *
+ * @return <tt>this</tt><sup>2</sup>
+ */
+ public GF2nElement square()
+ {
+ GF2nONBElement result = new GF2nONBElement(this);
+ result.squareThis();
+ return result;
+ }
+
+ /**
+ * squares <tt>this</tt> element.
+ */
+ public void squareThis()
+ {
+
+ long[] pol = getElement();
+
+ int f = mLength - 1;
+ int b = mBit - 1;
+
+ // Shift the coefficients one bit to the left.
+ //
+ long TWOTOMAXLONGM1 = mBitmask[MAXLONG - 1];
+ boolean old, now;
+
+ old = (pol[f] & mBitmask[b]) != 0;
+
+ for (int i = 0; i < f; i++)
+ {
+
+ now = (pol[i] & TWOTOMAXLONGM1) != 0;
+
+ pol[i] = pol[i] << 1;
+
+ if (old)
+ {
+ pol[i] ^= 1;
+ }
+
+ old = now;
+ }
+ now = (pol[f] & mBitmask[b]) != 0;
+
+ pol[f] = pol[f] << 1;
+
+ if (old)
+ {
+ pol[f] ^= 1;
+ }
+
+ // Set the bit with index mDegree to zero.
+ //
+ if (now)
+ {
+ pol[f] ^= mBitmask[b + 1];
+ }
+
+ assign(pol);
+ }
+
+ /**
+ * Compute the multiplicative inverse of this element.
+ *
+ * @return <tt>this<sup>-1</sup></tt> (newly created)
+ * @throws ArithmeticException if <tt>this</tt> is the zero element.
+ */
+ public GFElement invert()
+ throws ArithmeticException
+ {
+ GF2nONBElement result = new GF2nONBElement(this);
+ result.invertThis();
+ return result;
+ }
+
+ /**
+ * Multiplicatively invert of this element (overwrite <tt>this</tt>).
+ *
+ * @throws ArithmeticException if <tt>this</tt> is the zero element.
+ */
+ public void invertThis()
+ throws ArithmeticException
+ {
+
+ if (isZero())
+ {
+ throw new ArithmeticException();
+ }
+ int r = 31; // mDegree kann nur 31 Bits lang sein!!!
+
+ // Bitlaenge von mDegree:
+ for (boolean found = false; !found && r >= 0; r--)
+ {
+
+ if (((mDegree - 1) & mBitmask[r]) != 0)
+ {
+ found = true;
+ }
+ }
+ r++;
+
+ GF2nElement m = ZERO((GF2nONBField)mField);
+ GF2nElement n = new GF2nONBElement(this);
+
+ int k = 1;
+
+ for (int i = r - 1; i >= 0; i--)
+ {
+ m = (GF2nElement)n.clone();
+ for (int j = 1; j <= k; j++)
+ {
+ m.squareThis();
+ }
+
+ n.multiplyThisBy(m);
+
+ k <<= 1;
+ if (((mDegree - 1) & mBitmask[i]) != 0)
+ {
+ n.squareThis();
+
+ n.multiplyThisBy(this);
+
+ k++;
+ }
+ }
+ n.squareThis();
+ }
+
+ /**
+ * returns the root of<tt>this</tt> element.
+ *
+ * @return <tt>this</tt><sup>1/2</sup>
+ */
+ public GF2nElement squareRoot()
+ {
+ GF2nONBElement result = new GF2nONBElement(this);
+ result.squareRootThis();
+ return result;
+ }
+
+ /**
+ * square roots <tt>this</tt> element.
+ */
+ public void squareRootThis()
+ {
+
+ long[] pol = getElement();
+
+ int f = mLength - 1;
+ int b = mBit - 1;
+
+ // Shift the coefficients one bit to the right.
+ //
+ long TWOTOMAXLONGM1 = mBitmask[MAXLONG - 1];
+ boolean old, now;
+
+ old = (pol[0] & 1) != 0;
+
+ for (int i = f; i >= 0; i--)
+ {
+ now = (pol[i] & 1) != 0;
+ pol[i] = pol[i] >>> 1;
+
+ if (old)
+ {
+ if (i == f)
+ {
+ pol[i] ^= mBitmask[b];
+ }
+ else
+ {
+ pol[i] ^= TWOTOMAXLONGM1;
+ }
+ }
+ old = now;
+ }
+ assign(pol);
+ }
+
+ /**
+ * Returns the trace of this element.
+ *
+ * @return the trace of this element
+ */
+ public int trace()
+ {
+
+ // trace = sum of coefficients
+ //
+
+ int result = 0;
+
+ int max = mLength - 1;
+
+ for (int i = 0; i < max; i++)
+ {
+
+ for (int j = 0; j < MAXLONG; j++)
+ {
+
+ if ((mPol[i] & mBitmask[j]) != 0)
+ {
+ result ^= 1;
+ }
+ }
+ }
+
+ int b = mBit;
+
+ for (int j = 0; j < b; j++)
+ {
+
+ if ((mPol[max] & mBitmask[j]) != 0)
+ {
+ result ^= 1;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Solves a quadratic equation.<br>
+ * Let z<sup>2</sup> + z = <tt>this</tt>. Then this method returns z.
+ *
+ * @return z with z<sup>2</sup> + z = <tt>this</tt>
+ * @throws NoSolutionException if z<sup>2</sup> + z = <tt>this</tt> does not have a
+ * solution
+ */
+ public GF2nElement solveQuadraticEquation()
+ throws RuntimeException
+ {
+
+ if (trace() == 1)
+ {
+ throw new RuntimeException();
+ }
+
+ long TWOTOMAXLONGM1 = mBitmask[MAXLONG - 1];
+ long ZERO = 0L;
+ long ONE = 1L;
+
+ long[] p = new long[mLength];
+ long z = 0L;
+ int j = 1;
+ for (int i = 0; i < mLength - 1; i++)
+ {
+
+ for (j = 1; j < MAXLONG; j++)
+ {
+
+ //
+ if (!((((mBitmask[j] & mPol[i]) != ZERO) && ((z & mBitmask[j - 1]) != ZERO)) || (((mPol[i] & mBitmask[j]) == ZERO) && ((z & mBitmask[j - 1]) == ZERO))))
+ {
+ z ^= mBitmask[j];
+ }
+ }
+ p[i] = z;
+
+ if (((TWOTOMAXLONGM1 & z) != ZERO && (ONE & mPol[i + 1]) == ONE)
+ || ((TWOTOMAXLONGM1 & z) == ZERO && (ONE & mPol[i + 1]) == ZERO))
+ {
+ z = ZERO;
+ }
+ else
+ {
+ z = ONE;
+ }
+ }
+
+ int b = mDegree & (MAXLONG - 1);
+
+ long LASTLONG = mPol[mLength - 1];
+
+ for (j = 1; j < b; j++)
+ {
+ if (!((((mBitmask[j] & LASTLONG) != ZERO) && ((mBitmask[j - 1] & z) != ZERO)) || (((mBitmask[j] & LASTLONG) == ZERO) && ((mBitmask[j - 1] & z) == ZERO))))
+ {
+ z ^= mBitmask[j];
+ }
+ }
+ p[mLength - 1] = z;
+ return new GF2nONBElement((GF2nONBField)mField, p);
+ }
+
+ // /////////////////////////////////////////////////////////////////
+ // conversion
+ // /////////////////////////////////////////////////////////////////
+
+ /**
+ * Returns a String representation of this element.
+ *
+ * @return String representation of this element with the specified radix
+ */
+ public String toString()
+ {
+ return toString(16);
+ }
+
+ /**
+ * Returns a String representation of this element. <tt>radix</tt>
+ * specifies the radix of the String representation.<br>
+ * NOTE: ONLY <tt>radix = 2</tt> or <tt>radix = 16</tt> IS IMPLEMENTED
+ *
+ * @param radix specifies the radix of the String representation
+ * @return String representation of this element with the specified radix
+ */
+ public String toString(int radix)
+ {
+ String s = "";
+
+ long[] a = getElement();
+ int b = mBit;
+
+ if (radix == 2)
+ {
+
+ for (int j = b - 1; j >= 0; j--)
+ {
+ if ((a[a.length - 1] & ((long)1 << j)) == 0)
+ {
+ s += "0";
+ }
+ else
+ {
+ s += "1";
+ }
+ }
+
+ for (int i = a.length - 2; i >= 0; i--)
+ {
+ for (int j = MAXLONG - 1; j >= 0; j--)
+ {
+ if ((a[i] & mBitmask[j]) == 0)
+ {
+ s += "0";
+ }
+ else
+ {
+ s += "1";
+ }
+ }
+ }
+ }
+ else if (radix == 16)
+ {
+ final char[] HEX_CHARS = {'0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+ for (int i = a.length - 1; i >= 0; i--)
+ {
+ s += HEX_CHARS[(int)(a[i] >>> 60) & 0x0f];
+ s += HEX_CHARS[(int)(a[i] >>> 56) & 0x0f];
+ s += HEX_CHARS[(int)(a[i] >>> 52) & 0x0f];
+ s += HEX_CHARS[(int)(a[i] >>> 48) & 0x0f];
+ s += HEX_CHARS[(int)(a[i] >>> 44) & 0x0f];
+ s += HEX_CHARS[(int)(a[i] >>> 40) & 0x0f];
+ s += HEX_CHARS[(int)(a[i] >>> 36) & 0x0f];
+ s += HEX_CHARS[(int)(a[i] >>> 32) & 0x0f];
+ s += HEX_CHARS[(int)(a[i] >>> 28) & 0x0f];
+ s += HEX_CHARS[(int)(a[i] >>> 24) & 0x0f];
+ s += HEX_CHARS[(int)(a[i] >>> 20) & 0x0f];
+ s += HEX_CHARS[(int)(a[i] >>> 16) & 0x0f];
+ s += HEX_CHARS[(int)(a[i] >>> 12) & 0x0f];
+ s += HEX_CHARS[(int)(a[i] >>> 8) & 0x0f];
+ s += HEX_CHARS[(int)(a[i] >>> 4) & 0x0f];
+ s += HEX_CHARS[(int)(a[i]) & 0x0f];
+ s += " ";
+ }
+ }
+ return s;
+ }
+
+ /**
+ * Returns this element as FlexiBigInt. The conversion is <a href =
+ * "http://grouper.ieee.org/groups/1363/">P1363</a>-conform.
+ *
+ * @return this element as BigInteger
+ */
+ public BigInteger toFlexiBigInt()
+ {
+ /** @todo this method does not reverse the bit-order as it should!!! */
+
+ return new BigInteger(1, toByteArray());
+ }
+
+ /**
+ * Returns this element as byte array. The conversion is <a href =
+ * "http://grouper.ieee.org/groups/1363/">P1363</a>-conform.
+ *
+ * @return this element as byte array
+ */
+ public byte[] toByteArray()
+ {
+ /** @todo this method does not reverse the bit-order as it should!!! */
+
+ int k = ((mDegree - 1) >> 3) + 1;
+ byte[] result = new byte[k];
+ int i;
+ for (i = 0; i < k; i++)
+ {
+ result[k - i - 1] = (byte)((mPol[i >>> 3] & (0x00000000000000ffL << ((i & 0x07) << 3))) >>> ((i & 0x07) << 3));
+ }
+ return result;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nONBField.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nONBField.java
new file mode 100644
index 00000000..60e5be41
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nONBField.java
@@ -0,0 +1,546 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+
+import java.util.Random;
+import java.util.Vector;
+
+
+/**
+ * This class implements the abstract class <tt>GF2nField</tt> for ONB
+ * representation. It computes the fieldpolynomial, multiplication matrix and
+ * one of its roots mONBRoot, (see for example <a
+ * href=http://www2.certicom.com/ecc/intro.htm>Certicoms Whitepapers</a>).
+ * GF2nField is used by GF2nONBElement which implements the elements of this
+ * field.
+ *
+ * @see GF2nField
+ * @see GF2nONBElement
+ */
+public class GF2nONBField
+ extends GF2nField
+{
+
+ // ///////////////////////////////////////////////////////////////////
+ // Hashtable for irreducible normal polynomials //
+ // ///////////////////////////////////////////////////////////////////
+
+ // i*5 + 0 i*5 + 1 i*5 + 2 i*5 + 3 i*5 + 4
+ /*
+ * private static int[][] mNB = {{0, 0, 0}, {0, 0, 0}, {1, 0, 0}, {1, 0, 0},
+ * {1, 0, 0}, // i = 0 {2, 0, 0}, {1, 0, 0}, {1, 0, 0}, {4, 3, 1}, {1, 0,
+ * 0}, // i = 1 {3, 0, 0}, {2, 0, 0}, {3, 0, 0}, {4, 3, 1}, {5, 0, 0}, // i =
+ * 2 {1, 0, 0}, {5, 3, 1}, {3, 0, 0}, {3, 0, 0}, {5, 2, 1}, // i = 3 {3, 0,
+ * 0}, {2, 0, 0}, {1, 0, 0}, {5, 0, 0}, {4, 3, 1}, // i = 4 {3, 0, 0}, {4,
+ * 3, 1}, {5, 2, 1}, {1, 0, 0}, {2, 0, 0}, // i = 5 {1, 0, 0}, {3, 0, 0},
+ * {7, 3, 2}, {10, 0, 0}, {7, 0, 0}, // i = 6 {2, 0, 0}, {9, 0, 0}, {6, 4,
+ * 1}, {6, 5, 1}, {4, 0, 0}, // i = 7 {5, 4, 3}, {3, 0, 0}, {7, 0, 0}, {6,
+ * 4, 3}, {5, 0, 0}, // i = 8 {4, 3, 1}, {1, 0, 0}, {5, 0, 0}, {5, 3, 2},
+ * {9, 0, 0}, // i = 9 {4, 3, 2}, {6, 3, 1}, {3, 0, 0}, {6, 2, 1}, {9, 0,
+ * 0}, // i = 10 {7, 0, 0}, {7, 4, 2}, {4, 0, 0}, {19, 0, 0}, {7, 4, 2}, //
+ * i = 11 {1, 0, 0}, {5, 2, 1}, {29, 0, 0}, {1, 0, 0}, {4, 3, 1}, // i = 12
+ * {18, 0, 0}, {3, 0, 0}, {5, 2, 1}, {9, 0, 0}, {6, 5, 2}, // i = 13 {5, 3,
+ * 1}, {6, 0, 0}, {10, 9, 3}, {25, 0, 0}, {35, 0, 0}, // i = 14 {6, 3, 1},
+ * {21, 0, 0}, {6, 5, 2}, {6, 5, 3}, {9, 0, 0}, // i = 15 {9, 4, 2}, {4, 0,
+ * 0}, {8, 3, 1}, {7, 4, 2}, {5, 0, 0}, // i = 16 {8, 2, 1}, {21, 0, 0},
+ * {13, 0, 0}, {7, 6, 2}, {38, 0, 0}, // i = 17 {27, 0, 0}, {8, 5, 1}, {21,
+ * 0, 0}, {2, 0, 0}, {21, 0, 0}, // i = 18 {11, 0, 0}, {10, 9, 6}, {6, 0,
+ * 0}, {11, 0, 0}, {6, 3, 1}, // i = 19 {15, 0, 0}, {7, 6, 1}, {29, 0, 0},
+ * {9, 0, 0}, {4, 3, 1}, // i = 20 {4, 0, 0}, {15, 0, 0}, {9, 7, 4}, {17, 0,
+ * 0}, {5, 4, 2}, // i = 21 {33, 0, 0}, {10, 0, 0}, {5, 4, 3}, {9, 0, 0},
+ * {5, 3, 2}, // i = 22 {8, 7, 5}, {4, 2, 1}, {5, 2, 1}, {33, 0, 0}, {8, 0,
+ * 0}, // i = 23 {4, 3, 1}, {18, 0, 0}, {6, 2, 1}, {2, 0, 0}, {19, 0, 0}, //
+ * i = 24 {7, 6, 5}, {21, 0, 0}, {1, 0, 0}, {7, 2, 1}, {5, 0, 0}, // i = 25
+ * {3, 0, 0}, {8, 3, 2}, {17, 0, 0}, {9, 8, 2}, {57, 0, 0}, // i = 26 {11,
+ * 0, 0}, {5, 3, 2}, {21, 0, 0}, {8, 7, 1}, {8, 5, 3}, // i = 27 {15, 0, 0},
+ * {10, 4, 1}, {21, 0, 0}, {5, 3, 2}, {7, 4, 2}, // i = 28 {52, 0, 0}, {71,
+ * 0, 0}, {14, 0, 0}, {27, 0, 0}, {10, 9, 7}, // i = 29 {53, 0, 0}, {3, 0,
+ * 0}, {6, 3, 2}, {1, 0, 0}, {15, 0, 0}, // i = 30 {62, 0, 0}, {9, 0, 0},
+ * {6, 5, 2}, {8, 6, 5}, {31, 0, 0}, // i = 31 {5, 3, 2}, {18, 0, 0 }, {27,
+ * 0, 0}, {7, 6, 3}, {10, 8, 7}, // i = 32 {9, 8, 3}, {37, 0, 0}, {6, 0, 0},
+ * {15, 3, 2}, {34, 0, 0}, // i = 33 {11, 0, 0}, {6, 5, 2}, {1, 0, 0}, {8,
+ * 5, 2}, {13, 0, 0}, // i = 34 {6, 0, 0}, {11, 3, 2}, {8, 0, 0}, {31, 0,
+ * 0}, {4, 2, 1}, // i = 35 {3, 0, 0}, {7, 6, 1}, {81, 0, 0}, {56, 0, 0},
+ * {9, 8, 7}, // i = 36 {24, 0, 0}, {11, 0, 0}, {7, 6, 5}, {6, 5, 2}, {6, 5,
+ * 2}, // i = 37 {8, 7, 6}, {9, 0, 0}, {7, 2, 1}, {15, 0, 0}, {87, 0, 0}, //
+ * i = 38 {8, 3, 2}, {3, 0, 0}, {9, 4, 2}, {9, 0, 0}, {34, 0, 0}, // i = 39
+ * {5, 3, 2}, {14, 0, 0}, {55, 0, 0}, {8, 7, 1}, {27, 0, 0}, // i = 40 {9,
+ * 5, 2}, {10, 9, 5}, {43, 0, 0}, {8, 6, 2}, {6, 0, 0}, // i = 41 {7, 0, 0},
+ * {11, 10, 8}, {105, 0, 0}, {6, 5, 2}, {73, 0, 0}}; // i = 42
+ */
+ // /////////////////////////////////////////////////////////////////////
+ // member variables
+ // /////////////////////////////////////////////////////////////////////
+ private static final int MAXLONG = 64;
+
+ /**
+ * holds the length of the array-representation of degree mDegree.
+ */
+ private int mLength;
+
+ /**
+ * holds the number of relevant bits in mONBPol[mLength-1].
+ */
+ private int mBit;
+
+ /**
+ * holds the type of mONB
+ */
+ private int mType;
+
+ /**
+ * holds the multiplication matrix
+ */
+ int[][] mMult;
+
+ // /////////////////////////////////////////////////////////////////////
+ // constructors
+ // /////////////////////////////////////////////////////////////////////
+
+ /**
+ * constructs an instance of the finite field with 2<sup>deg</sup>
+ * elements and characteristic 2.
+ *
+ * @param deg -
+ * the extention degree of this field
+ * @throws NoSuchBasisException if an ONB-implementation other than type 1 or type 2 is
+ * requested.
+ */
+ public GF2nONBField(int deg)
+ throws RuntimeException
+ {
+ if (deg < 3)
+ {
+ throw new IllegalArgumentException("k must be at least 3");
+ }
+
+ mDegree = deg;
+ mLength = mDegree / MAXLONG;
+ mBit = mDegree & (MAXLONG - 1);
+ if (mBit == 0)
+ {
+ mBit = MAXLONG;
+ }
+ else
+ {
+ mLength++;
+ }
+
+ computeType();
+
+ // only ONB-implementations for type 1 and type 2
+ //
+ if (mType < 3)
+ {
+ mMult = new int[mDegree][2];
+ for (int i = 0; i < mDegree; i++)
+ {
+ mMult[i][0] = -1;
+ mMult[i][1] = -1;
+ }
+ computeMultMatrix();
+ }
+ else
+ {
+ throw new RuntimeException("\nThe type of this field is "
+ + mType);
+ }
+ computeFieldPolynomial();
+ fields = new Vector();
+ matrices = new Vector();
+ }
+
+ // /////////////////////////////////////////////////////////////////////
+ // access
+ // /////////////////////////////////////////////////////////////////////
+
+ int getONBLength()
+ {
+ return mLength;
+ }
+
+ int getONBBit()
+ {
+ return mBit;
+ }
+
+ // /////////////////////////////////////////////////////////////////////
+ // arithmetic
+ // /////////////////////////////////////////////////////////////////////
+
+ /**
+ * Computes a random root of the given polynomial.
+ *
+ * @param polynomial a polynomial
+ * @return a random root of the polynomial
+ * @see "P1363 A.5.6, p103f"
+ */
+ protected GF2nElement getRandomRoot(GF2Polynomial polynomial)
+ {
+ // We are in B1!!!
+ GF2nPolynomial c;
+ GF2nPolynomial ut;
+ GF2nElement u;
+ GF2nPolynomial h;
+ int hDegree;
+ // 1. Set g(t) <- f(t)
+ GF2nPolynomial g = new GF2nPolynomial(polynomial, this);
+ int gDegree = g.getDegree();
+ int i;
+
+ // 2. while deg(g) > 1
+ while (gDegree > 1)
+ {
+ do
+ {
+ // 2.1 choose random u (element of) GF(2^m)
+ u = new GF2nONBElement(this, new Random());
+ ut = new GF2nPolynomial(2, GF2nONBElement.ZERO(this));
+ // 2.2 Set c(t) <- ut
+ ut.set(1, u);
+ c = new GF2nPolynomial(ut);
+ // 2.3 For i from 1 to m-1 do
+ for (i = 1; i <= mDegree - 1; i++)
+ {
+ // 2.3.1 c(t) <- (c(t)^2 + ut) mod g(t)
+ c = c.multiplyAndReduce(c, g);
+ c = c.add(ut);
+ }
+ // 2.4 set h(t) <- GCD(c(t), g(t))
+ h = c.gcd(g);
+ // 2.5 if h(t) is constant or deg(g) = deg(h) then go to
+ // step 2.1
+ hDegree = h.getDegree();
+ gDegree = g.getDegree();
+ }
+ while ((hDegree == 0) || (hDegree == gDegree));
+ // 2.6 If 2deg(h) > deg(g) then set g(t) <- g(t)/h(t) ...
+ if ((hDegree << 1) > gDegree)
+ {
+ g = g.quotient(h);
+ }
+ else
+ {
+ // ... else g(t) <- h(t)
+ g = new GF2nPolynomial(h);
+ }
+ gDegree = g.getDegree();
+ }
+ // 3. Output g(0)
+ return g.at(0);
+
+ }
+
+ /**
+ * Computes the change-of-basis matrix for basis conversion according to
+ * 1363. The result is stored in the lists fields and matrices.
+ *
+ * @param B1 the GF2nField to convert to
+ * @see "P1363 A.7.3, p111ff"
+ */
+ protected void computeCOBMatrix(GF2nField B1)
+ {
+ // we are in B0 here!
+ if (mDegree != B1.mDegree)
+ {
+ throw new IllegalArgumentException(
+ "GF2nField.computeCOBMatrix: B1 has a "
+ + "different degree and thus cannot be coverted to!");
+ }
+ int i, j;
+ GF2nElement[] gamma;
+ GF2nElement u;
+ GF2Polynomial[] COBMatrix = new GF2Polynomial[mDegree];
+ for (i = 0; i < mDegree; i++)
+ {
+ COBMatrix[i] = new GF2Polynomial(mDegree);
+ }
+
+ // find Random Root
+ do
+ {
+ // u is in representation according to B1
+ u = B1.getRandomRoot(fieldPolynomial);
+ }
+ while (u.isZero());
+
+ gamma = new GF2nPolynomialElement[mDegree];
+ // build gamma matrix by squaring
+ gamma[0] = (GF2nElement)u.clone();
+ for (i = 1; i < mDegree; i++)
+ {
+ gamma[i] = gamma[i - 1].square();
+ }
+ // convert horizontal gamma matrix by vertical Bitstrings
+ for (i = 0; i < mDegree; i++)
+ {
+ for (j = 0; j < mDegree; j++)
+ {
+ if (gamma[i].testBit(j))
+ {
+ COBMatrix[mDegree - j - 1].setBit(mDegree - i - 1);
+ }
+ }
+ }
+
+ fields.addElement(B1);
+ matrices.addElement(COBMatrix);
+ B1.fields.addElement(this);
+ B1.matrices.addElement(invertMatrix(COBMatrix));
+ }
+
+ /**
+ * Computes the field polynomial for a ONB according to IEEE 1363 A.7.2
+ * (p110f).
+ *
+ * @see "P1363 A.7.2, p110f"
+ */
+ protected void computeFieldPolynomial()
+ {
+ if (mType == 1)
+ {
+ fieldPolynomial = new GF2Polynomial(mDegree + 1, "ALL");
+ }
+ else if (mType == 2)
+ {
+ // 1. q = 1
+ GF2Polynomial q = new GF2Polynomial(mDegree + 1, "ONE");
+ // 2. p = t+1
+ GF2Polynomial p = new GF2Polynomial(mDegree + 1, "X");
+ p.addToThis(q);
+ GF2Polynomial r;
+ int i;
+ // 3. for i = 1 to (m-1) do
+ for (i = 1; i < mDegree; i++)
+ {
+ // r <- q
+ r = q;
+ // q <- p
+ q = p;
+ // p = tq+r
+ p = q.shiftLeft();
+ p.addToThis(r);
+ }
+ fieldPolynomial = p;
+ }
+ }
+
+ /**
+ * Compute the inverse of a matrix <tt>a</tt>.
+ *
+ * @param a the matrix
+ * @return <tt>a<sup>-1</sup></tt>
+ */
+ int[][] invMatrix(int[][] a)
+ {
+
+ int[][] A = new int[mDegree][mDegree];
+ A = a;
+ int[][] inv = new int[mDegree][mDegree];
+
+ for (int i = 0; i < mDegree; i++)
+ {
+ inv[i][i] = 1;
+ }
+
+ for (int i = 0; i < mDegree; i++)
+ {
+ for (int j = i; j < mDegree; j++)
+ {
+ A[mDegree - 1 - i][j] = A[i][i];
+ }
+ }
+ return null;
+ }
+
+ private void computeType()
+ throws RuntimeException
+ {
+ if ((mDegree & 7) == 0)
+ {
+ throw new RuntimeException(
+ "The extension degree is divisible by 8!");
+ }
+ // checking for the type
+ int s = 0;
+ int k = 0;
+ mType = 1;
+ for (int d = 0; d != 1; mType++)
+ {
+ s = mType * mDegree + 1;
+ if (IntegerFunctions.isPrime(s))
+ {
+ k = IntegerFunctions.order(2, s);
+ d = IntegerFunctions.gcd(mType * mDegree / k, mDegree);
+ }
+ }
+ mType--;
+ if (mType == 1)
+ {
+ s = (mDegree << 1) + 1;
+ if (IntegerFunctions.isPrime(s))
+ {
+ k = IntegerFunctions.order(2, s);
+ int d = IntegerFunctions.gcd((mDegree << 1) / k, mDegree);
+ if (d == 1)
+ {
+ mType++;
+ }
+ }
+ }
+ }
+
+ private void computeMultMatrix()
+ {
+
+ if ((mType & 7) != 0)
+ {
+ int p = mType * mDegree + 1;
+
+ // compute sequence F[1] ... F[p-1] via A.3.7. of 1363.
+ // F[0] will not be filled!
+ //
+ int[] F = new int[p];
+
+ int u;
+ if (mType == 1)
+ {
+ u = 1;
+ }
+ else if (mType == 2)
+ {
+ u = p - 1;
+ }
+ else
+ {
+ u = elementOfOrder(mType, p);
+ }
+
+ int w = 1;
+ int n;
+ for (int j = 0; j < mType; j++)
+ {
+ n = w;
+
+ for (int i = 0; i < mDegree; i++)
+ {
+ F[n] = i;
+ n = (n << 1) % p;
+ if (n < 0)
+ {
+ n += p;
+ }
+ }
+ w = u * w % p;
+ if (w < 0)
+ {
+ w += p;
+ }
+ }
+
+ // building the matrix (mDegree * 2)
+ //
+ if (mType == 1)
+ {
+ for (int k = 1; k < p - 1; k++)
+ {
+ if (mMult[F[k + 1]][0] == -1)
+ {
+ mMult[F[k + 1]][0] = F[p - k];
+ }
+ else
+ {
+ mMult[F[k + 1]][1] = F[p - k];
+ }
+ }
+
+ int m_2 = mDegree >> 1;
+ for (int k = 1; k <= m_2; k++)
+ {
+
+ if (mMult[k - 1][0] == -1)
+ {
+ mMult[k - 1][0] = m_2 + k - 1;
+ }
+ else
+ {
+ mMult[k - 1][1] = m_2 + k - 1;
+ }
+
+ if (mMult[m_2 + k - 1][0] == -1)
+ {
+ mMult[m_2 + k - 1][0] = k - 1;
+ }
+ else
+ {
+ mMult[m_2 + k - 1][1] = k - 1;
+ }
+ }
+ }
+ else if (mType == 2)
+ {
+ for (int k = 1; k < p - 1; k++)
+ {
+ if (mMult[F[k + 1]][0] == -1)
+ {
+ mMult[F[k + 1]][0] = F[p - k];
+ }
+ else
+ {
+ mMult[F[k + 1]][1] = F[p - k];
+ }
+ }
+ }
+ else
+ {
+ throw new RuntimeException("only type 1 or type 2 implemented");
+ }
+ }
+ else
+ {
+ throw new RuntimeException("bisher nur fuer Gausssche Normalbasen"
+ + " implementiert");
+ }
+ }
+
+ private int elementOfOrder(int k, int p)
+ {
+ Random random = new Random();
+ int m = 0;
+ while (m == 0)
+ {
+ m = random.nextInt();
+ m %= p - 1;
+ if (m < 0)
+ {
+ m += p - 1;
+ }
+ }
+
+ int l = IntegerFunctions.order(m, p);
+
+ while (l % k != 0 || l == 0)
+ {
+ while (m == 0)
+ {
+ m = random.nextInt();
+ m %= p - 1;
+ if (m < 0)
+ {
+ m += p - 1;
+ }
+ }
+ l = IntegerFunctions.order(m, p);
+ }
+ int r = m;
+
+ l = k / l;
+
+ for (int i = 2; i <= l; i++)
+ {
+ r *= m;
+ }
+
+ return r;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nPolynomial.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nPolynomial.java
new file mode 100644
index 00000000..97ee022c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nPolynomial.java
@@ -0,0 +1,587 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+
+/**
+ * This class implements polynomials over GF2nElements.
+ *
+ * @see GF2nElement
+ */
+
+public class GF2nPolynomial
+{
+
+ private GF2nElement[] coeff; // keeps the coefficients of this polynomial
+
+ private int size; // the size of this polynomial
+
+ /**
+ * Creates a new PolynomialGF2n of size <i>deg</i> and elem as
+ * coefficients.
+ *
+ * @param deg -
+ * the maximum degree + 1
+ * @param elem -
+ * a GF2nElement
+ */
+ public GF2nPolynomial(int deg, GF2nElement elem)
+ {
+ size = deg;
+ coeff = new GF2nElement[size];
+ for (int i = 0; i < size; i++)
+ {
+ coeff[i] = (GF2nElement)elem.clone();
+ }
+ }
+
+ /**
+ * Creates a new PolynomialGF2n of size <i>deg</i>.
+ *
+ * @param deg the maximum degree + 1
+ */
+ private GF2nPolynomial(int deg)
+ {
+ size = deg;
+ coeff = new GF2nElement[size];
+ }
+
+ /**
+ * Creates a new PolynomialGF2n by cloning the given PolynomialGF2n <i>a</i>.
+ *
+ * @param a the PolynomialGF2n to clone
+ */
+ public GF2nPolynomial(GF2nPolynomial a)
+ {
+ int i;
+ coeff = new GF2nElement[a.size];
+ size = a.size;
+ for (i = 0; i < size; i++)
+ {
+ coeff[i] = (GF2nElement)a.coeff[i].clone();
+ }
+ }
+
+ /**
+ * Creates a new PolynomialGF2n from the given Bitstring <i>polynomial</i>
+ * over the GF2nField <i>B1</i>.
+ *
+ * @param polynomial the Bitstring to use
+ * @param B1 the field
+ */
+ public GF2nPolynomial(GF2Polynomial polynomial, GF2nField B1)
+ {
+ size = B1.getDegree() + 1;
+ coeff = new GF2nElement[size];
+ int i;
+ if (B1 instanceof GF2nONBField)
+ {
+ for (i = 0; i < size; i++)
+ {
+ if (polynomial.testBit(i))
+ {
+ coeff[i] = GF2nONBElement.ONE((GF2nONBField)B1);
+ }
+ else
+ {
+ coeff[i] = GF2nONBElement.ZERO((GF2nONBField)B1);
+ }
+ }
+ }
+ else if (B1 instanceof GF2nPolynomialField)
+ {
+ for (i = 0; i < size; i++)
+ {
+ if (polynomial.testBit(i))
+ {
+ coeff[i] = GF2nPolynomialElement
+ .ONE((GF2nPolynomialField)B1);
+ }
+ else
+ {
+ coeff[i] = GF2nPolynomialElement
+ .ZERO((GF2nPolynomialField)B1);
+ }
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException(
+ "PolynomialGF2n(Bitstring, GF2nField): B1 must be "
+ + "an instance of GF2nONBField or GF2nPolynomialField!");
+ }
+ }
+
+ public final void assignZeroToElements()
+ {
+ int i;
+ for (i = 0; i < size; i++)
+ {
+ coeff[i].assignZero();
+ }
+ }
+
+ /**
+ * Returns the size (=maximum degree + 1) of this PolynomialGF2n. This is
+ * not the degree, use getDegree instead.
+ *
+ * @return the size (=maximum degree + 1) of this PolynomialGF2n.
+ */
+ public final int size()
+ {
+ return size;
+ }
+
+ /**
+ * Returns the degree of this PolynomialGF2n.
+ *
+ * @return the degree of this PolynomialGF2n.
+ */
+ public final int getDegree()
+ {
+ int i;
+ for (i = size - 1; i >= 0; i--)
+ {
+ if (!coeff[i].isZero())
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Enlarges the size of this PolynomialGF2n to <i>k</i> + 1.
+ *
+ * @param k the new maximum degree
+ */
+ public final void enlarge(int k)
+ {
+ if (k <= size)
+ {
+ return;
+ }
+ int i;
+ GF2nElement[] res = new GF2nElement[k];
+ System.arraycopy(coeff, 0, res, 0, size);
+ GF2nField f = coeff[0].getField();
+ if (coeff[0] instanceof GF2nPolynomialElement)
+ {
+ for (i = size; i < k; i++)
+ {
+ res[i] = GF2nPolynomialElement.ZERO((GF2nPolynomialField)f);
+ }
+ }
+ else if (coeff[0] instanceof GF2nONBElement)
+ {
+ for (i = size; i < k; i++)
+ {
+ res[i] = GF2nONBElement.ZERO((GF2nONBField)f);
+ }
+ }
+ size = k;
+ coeff = res;
+ }
+
+ public final void shrink()
+ {
+ int i = size - 1;
+ while (coeff[i].isZero() && (i > 0))
+ {
+ i--;
+ }
+ i++;
+ if (i < size)
+ {
+ GF2nElement[] res = new GF2nElement[i];
+ System.arraycopy(coeff, 0, res, 0, i);
+ coeff = res;
+ size = i;
+ }
+ }
+
+ /**
+ * Sets the coefficient at <i>index</i> to <i>elem</i>.
+ *
+ * @param index the index
+ * @param elem the GF2nElement to store as coefficient <i>index</i>
+ */
+ public final void set(int index, GF2nElement elem)
+ {
+ if (!(elem instanceof GF2nPolynomialElement)
+ && !(elem instanceof GF2nONBElement))
+ {
+ throw new IllegalArgumentException(
+ "PolynomialGF2n.set f must be an "
+ + "instance of either GF2nPolynomialElement or GF2nONBElement!");
+ }
+ coeff[index] = (GF2nElement)elem.clone();
+ }
+
+ /**
+ * Returns the coefficient at <i>index</i>.
+ *
+ * @param index the index
+ * @return the GF2nElement stored as coefficient <i>index</i>
+ */
+ public final GF2nElement at(int index)
+ {
+ return coeff[index];
+ }
+
+ /**
+ * Returns true if all coefficients equal zero.
+ *
+ * @return true if all coefficients equal zero.
+ */
+ public final boolean isZero()
+ {
+ int i;
+ for (i = 0; i < size; i++)
+ {
+ if (coeff[i] != null)
+ {
+ if (!coeff[i].isZero())
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ public final boolean equals(Object other)
+ {
+ if (other == null || !(other instanceof GF2nPolynomial))
+ {
+ return false;
+ }
+
+ GF2nPolynomial otherPol = (GF2nPolynomial)other;
+
+ if (getDegree() != otherPol.getDegree())
+ {
+ return false;
+ }
+ int i;
+ for (i = 0; i < size; i++)
+ {
+ if (!coeff[i].equals(otherPol.coeff[i]))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @return the hash code of this polynomial
+ */
+ public int hashCode()
+ {
+ return getDegree() + coeff.hashCode();
+ }
+
+ /**
+ * Adds the PolynomialGF2n <tt>b</tt> to <tt>this</tt> and returns the
+ * result in a new <tt>PolynomialGF2n</tt>.
+ *
+ * @param b -
+ * the <tt>PolynomialGF2n</tt> to add
+ * @return <tt>this + b</tt>
+ * @throws DifferentFieldsException if <tt>this</tt> and <tt>b</tt> are not defined over
+ * the same field.
+ */
+ public final GF2nPolynomial add(GF2nPolynomial b)
+ throws RuntimeException
+ {
+ GF2nPolynomial result;
+ if (size() >= b.size())
+ {
+ result = new GF2nPolynomial(size());
+ int i;
+ for (i = 0; i < b.size(); i++)
+ {
+ result.coeff[i] = (GF2nElement)coeff[i].add(b.coeff[i]);
+ }
+ for (; i < size(); i++)
+ {
+ result.coeff[i] = coeff[i];
+ }
+ }
+ else
+ {
+ result = new GF2nPolynomial(b.size());
+ int i;
+ for (i = 0; i < size(); i++)
+ {
+ result.coeff[i] = (GF2nElement)coeff[i].add(b.coeff[i]);
+ }
+ for (; i < b.size(); i++)
+ {
+ result.coeff[i] = b.coeff[i];
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Multiplies the scalar <i>s</i> to each coefficient of this
+ * PolynomialGF2n and returns the result in a new PolynomialGF2n.
+ *
+ * @param s the scalar to multiply
+ * @return <i>this</i> x <i>s</i>
+ * @throws DifferentFieldsException if <tt>this</tt> and <tt>s</tt> are not defined over
+ * the same field.
+ */
+ public final GF2nPolynomial scalarMultiply(GF2nElement s)
+ throws RuntimeException
+ {
+ GF2nPolynomial result = new GF2nPolynomial(size());
+ int i;
+ for (i = 0; i < size(); i++)
+ {
+ result.coeff[i] = (GF2nElement)coeff[i].multiply(s); // result[i]
+ // =
+ // a[i]*s
+ }
+ return result;
+ }
+
+ /**
+ * Multiplies <i>this</i> by <i>b</i> and returns the result in a new
+ * PolynomialGF2n.
+ *
+ * @param b the PolynomialGF2n to multiply
+ * @return <i>this</i> * <i>b</i>
+ * @throws DifferentFieldsException if <tt>this</tt> and <tt>b</tt> are not defined over
+ * the same field.
+ */
+ public final GF2nPolynomial multiply(GF2nPolynomial b)
+ throws RuntimeException
+ {
+ int i, j;
+ int aDegree = size();
+ int bDegree = b.size();
+ if (aDegree != bDegree)
+ {
+ throw new IllegalArgumentException(
+ "PolynomialGF2n.multiply: this and b must "
+ + "have the same size!");
+ }
+ GF2nPolynomial result = new GF2nPolynomial((aDegree << 1) - 1);
+ for (i = 0; i < size(); i++)
+ {
+ for (j = 0; j < b.size(); j++)
+ {
+ if (result.coeff[i + j] == null)
+ {
+ result.coeff[i + j] = (GF2nElement)coeff[i]
+ .multiply(b.coeff[j]);
+ }
+ else
+ {
+ result.coeff[i + j] = (GF2nElement)result.coeff[i + j]
+ .add(coeff[i].multiply(b.coeff[j]));
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Multiplies <i>this</i> by <i>b</i>, reduces the result by <i>g</i> and
+ * returns it in a new PolynomialGF2n.
+ *
+ * @param b the PolynomialGF2n to multiply
+ * @param g the modul
+ * @return <i>this</i> * <i>b</i> mod <i>g</i>
+ * @throws DifferentFieldsException if <tt>this</tt>, <tt>b</tt> and <tt>g</tt> are
+ * not all defined over the same field.
+ */
+ public final GF2nPolynomial multiplyAndReduce(GF2nPolynomial b,
+ GF2nPolynomial g)
+ throws RuntimeException,
+ ArithmeticException
+ {
+ return multiply(b).reduce(g);
+ }
+
+ /**
+ * Reduces <i>this</i> by <i>g</i> and returns the result in a new
+ * PolynomialGF2n.
+ *
+ * @param g -
+ * the modulus
+ * @return <i>this</i> % <i>g</i>
+ * @throws DifferentFieldsException if <tt>this</tt> and <tt>g</tt> are not defined over
+ * the same field.
+ */
+ public final GF2nPolynomial reduce(GF2nPolynomial g)
+ throws RuntimeException, ArithmeticException
+ {
+ return remainder(g); // return this % g
+ }
+
+ /**
+ * Shifts left <i>this</i> by <i>amount</i> and stores the result in
+ * <i>this</i> PolynomialGF2n.
+ *
+ * @param amount the amount to shift the coefficients
+ */
+ public final void shiftThisLeft(int amount)
+ {
+ if (amount > 0)
+ {
+ int i;
+ int oldSize = size;
+ GF2nField f = coeff[0].getField();
+ enlarge(size + amount);
+ for (i = oldSize - 1; i >= 0; i--)
+ {
+ coeff[i + amount] = coeff[i];
+ }
+ if (coeff[0] instanceof GF2nPolynomialElement)
+ {
+ for (i = amount - 1; i >= 0; i--)
+ {
+ coeff[i] = GF2nPolynomialElement
+ .ZERO((GF2nPolynomialField)f);
+ }
+ }
+ else if (coeff[0] instanceof GF2nONBElement)
+ {
+ for (i = amount - 1; i >= 0; i--)
+ {
+ coeff[i] = GF2nONBElement.ZERO((GF2nONBField)f);
+ }
+ }
+ }
+ }
+
+ public final GF2nPolynomial shiftLeft(int amount)
+ {
+ if (amount <= 0)
+ {
+ return new GF2nPolynomial(this);
+ }
+ GF2nPolynomial result = new GF2nPolynomial(size + amount, coeff[0]);
+ result.assignZeroToElements();
+ for (int i = 0; i < size; i++)
+ {
+ result.coeff[i + amount] = coeff[i];
+ }
+ return result;
+ }
+
+ /**
+ * Divides <i>this</i> by <i>b</i> and stores the result in a new
+ * PolynomialGF2n[2], quotient in result[0] and remainder in result[1].
+ *
+ * @param b the divisor
+ * @return the quotient and remainder of <i>this</i> / <i>b</i>
+ * @throws DifferentFieldsException if <tt>this</tt> and <tt>b</tt> are not defined over
+ * the same field.
+ */
+ public final GF2nPolynomial[] divide(GF2nPolynomial b)
+ throws RuntimeException, ArithmeticException
+ {
+ GF2nPolynomial[] result = new GF2nPolynomial[2];
+ GF2nPolynomial a = new GF2nPolynomial(this);
+ a.shrink();
+ GF2nPolynomial shift;
+ GF2nElement factor;
+ int bDegree = b.getDegree();
+ GF2nElement inv = (GF2nElement)b.coeff[bDegree].invert();
+ if (a.getDegree() < bDegree)
+ {
+ result[0] = new GF2nPolynomial(this);
+ result[0].assignZeroToElements();
+ result[0].shrink();
+ result[1] = new GF2nPolynomial(this);
+ result[1].shrink();
+ return result;
+ }
+ result[0] = new GF2nPolynomial(this);
+ result[0].assignZeroToElements();
+ int i = a.getDegree() - bDegree;
+ while (i >= 0)
+ {
+ factor = (GF2nElement)a.coeff[a.getDegree()].multiply(inv);
+ shift = b.scalarMultiply(factor);
+ shift.shiftThisLeft(i);
+ a = a.add(shift);
+ a.shrink();
+ result[0].coeff[i] = (GF2nElement)factor.clone();
+ i = a.getDegree() - bDegree;
+ }
+ result[1] = a;
+ result[0].shrink();
+ return result;
+ }
+
+ /**
+ * Divides <i>this</i> by <i>b</i> and stores the remainder in a new
+ * PolynomialGF2n.
+ *
+ * @param b the divisor
+ * @return the remainder <i>this</i> % <i>b</i>
+ * @throws DifferentFieldsException if <tt>this</tt> and <tt>b</tt> are not defined over
+ * the same field.
+ */
+ public final GF2nPolynomial remainder(GF2nPolynomial b)
+ throws RuntimeException, ArithmeticException
+ {
+ GF2nPolynomial[] result = new GF2nPolynomial[2];
+ result = divide(b);
+ return result[1];
+ }
+
+ /**
+ * Divides <i>this</i> by <i>b</i> and stores the quotient in a new
+ * PolynomialGF2n.
+ *
+ * @param b the divisor
+ * @return the quotient <i>this</i> / <i>b</i>
+ * @throws DifferentFieldsException if <tt>this</tt> and <tt>b</tt> are not defined over
+ * the same field.
+ */
+ public final GF2nPolynomial quotient(GF2nPolynomial b)
+ throws RuntimeException, ArithmeticException
+ {
+ GF2nPolynomial[] result = new GF2nPolynomial[2];
+ result = divide(b);
+ return result[0];
+ }
+
+ /**
+ * Computes the greatest common divisor of <i>this</i> and <i>g</i> and
+ * returns the result in a new PolynomialGF2n.
+ *
+ * @param g -
+ * a GF2nPolynomial
+ * @return gcd(<i>this</i>, <i>g</i>)
+ * @throws DifferentFieldsException if the coefficients of <i>this</i> and <i>g</i> use
+ * different fields
+ * @throws ArithmeticException if coefficients are zero.
+ */
+ public final GF2nPolynomial gcd(GF2nPolynomial g)
+ throws RuntimeException, ArithmeticException
+ {
+ GF2nPolynomial a = new GF2nPolynomial(this);
+ GF2nPolynomial b = new GF2nPolynomial(g);
+ a.shrink();
+ b.shrink();
+ GF2nPolynomial c;
+ GF2nPolynomial result;
+ GF2nElement alpha;
+ while (!b.isZero())
+ {
+ c = a.remainder(b);
+ a = b;
+ b = c;
+ }
+ alpha = a.coeff[a.getDegree()];
+ result = a.scalarMultiply((GF2nElement)alpha.invert());
+ return result;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nPolynomialElement.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nPolynomialElement.java
new file mode 100644
index 00000000..50e9d751
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nPolynomialElement.java
@@ -0,0 +1,1021 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+
+import java.math.BigInteger;
+import java.util.Random;
+
+
+/**
+ * This class implements elements of finite binary fields <i>GF(2<sup>n</sup>)</i>
+ * using polynomial representation. For more information on the arithmetic see
+ * for example IEEE Standard 1363 or <a
+ * href=http://www.certicom.com/research/online.html> Certicom online-tutorial</a>.
+ *
+ * @see "GF2nField"
+ * @see GF2nPolynomialField
+ * @see GF2nONBElement
+ * @see GF2Polynomial
+ */
+public class GF2nPolynomialElement
+ extends GF2nElement
+{
+
+ // pre-computed Bitmask for fast masking, bitMask[a]=0x1 << a
+ private static final int[] bitMask = {0x00000001, 0x00000002, 0x00000004,
+ 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080,
+ 0x00000100, 0x00000200, 0x00000400, 0x00000800, 0x00001000,
+ 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000,
+ 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000,
+ 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000,
+ 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x00000000};
+
+ // the used GF2Polynomial which stores the coefficients
+ private GF2Polynomial polynomial;
+
+ /**
+ * Create a new random GF2nPolynomialElement using the given field and
+ * source of randomness.
+ *
+ * @param f the GF2nField to use
+ * @param rand the source of randomness
+ */
+ public GF2nPolynomialElement(GF2nPolynomialField f, Random rand)
+ {
+ mField = f;
+ mDegree = mField.getDegree();
+ polynomial = new GF2Polynomial(mDegree);
+ randomize(rand);
+ }
+
+ /**
+ * Creates a new GF2nPolynomialElement using the given field and Bitstring.
+ *
+ * @param f the GF2nPolynomialField to use
+ * @param bs the desired value as Bitstring
+ */
+ public GF2nPolynomialElement(GF2nPolynomialField f, GF2Polynomial bs)
+ {
+ mField = f;
+ mDegree = mField.getDegree();
+ polynomial = new GF2Polynomial(bs);
+ polynomial.expandN(mDegree);
+ }
+
+ /**
+ * Creates a new GF2nPolynomialElement using the given field <i>f</i> and
+ * byte[] <i>os</i> as value. The conversion is done according to 1363.
+ *
+ * @param f the GF2nField to use
+ * @param os the octet string to assign to this GF2nPolynomialElement
+ * @see "P1363 5.5.5 p23, OS2FEP/OS2BSP"
+ */
+ public GF2nPolynomialElement(GF2nPolynomialField f, byte[] os)
+ {
+ mField = f;
+ mDegree = mField.getDegree();
+ polynomial = new GF2Polynomial(mDegree, os);
+ polynomial.expandN(mDegree);
+ }
+
+ /**
+ * Creates a new GF2nPolynomialElement using the given field <i>f</i> and
+ * int[] <i>is</i> as value.
+ *
+ * @param f the GF2nField to use
+ * @param is the integer string to assign to this GF2nPolynomialElement
+ */
+ public GF2nPolynomialElement(GF2nPolynomialField f, int[] is)
+ {
+ mField = f;
+ mDegree = mField.getDegree();
+ polynomial = new GF2Polynomial(mDegree, is);
+ polynomial.expandN(f.mDegree);
+ }
+
+ /**
+ * Creates a new GF2nPolynomialElement by cloning the given
+ * GF2nPolynomialElement <i>b</i>.
+ *
+ * @param other the GF2nPolynomialElement to clone
+ */
+ public GF2nPolynomialElement(GF2nPolynomialElement other)
+ {
+ mField = other.mField;
+ mDegree = other.mDegree;
+ polynomial = new GF2Polynomial(other.polynomial);
+ }
+
+ // /////////////////////////////////////////////////////////////////////
+ // pseudo-constructors
+ // /////////////////////////////////////////////////////////////////////
+
+ /**
+ * Creates a new GF2nPolynomialElement by cloning this
+ * GF2nPolynomialElement.
+ *
+ * @return a copy of this element
+ */
+ public Object clone()
+ {
+ return new GF2nPolynomialElement(this);
+ }
+
+ // /////////////////////////////////////////////////////////////////////
+ // assignments
+ // /////////////////////////////////////////////////////////////////////
+
+ /**
+ * Assigns the value 'zero' to this Polynomial.
+ */
+ void assignZero()
+ {
+ polynomial.assignZero();
+ }
+
+ /**
+ * Create the zero element.
+ *
+ * @param f the finite field
+ * @return the zero element in the given finite field
+ */
+ public static GF2nPolynomialElement ZERO(GF2nPolynomialField f)
+ {
+ GF2Polynomial polynomial = new GF2Polynomial(f.getDegree());
+ return new GF2nPolynomialElement(f, polynomial);
+ }
+
+ /**
+ * Create the one element.
+ *
+ * @param f the finite field
+ * @return the one element in the given finite field
+ */
+ public static GF2nPolynomialElement ONE(GF2nPolynomialField f)
+ {
+ GF2Polynomial polynomial = new GF2Polynomial(f.getDegree(),
+ new int[]{1});
+ return new GF2nPolynomialElement(f, polynomial);
+ }
+
+ /**
+ * Assigns the value 'one' to this Polynomial.
+ */
+ void assignOne()
+ {
+ polynomial.assignOne();
+ }
+
+ /**
+ * Assign a random value to this GF2nPolynomialElement using the specified
+ * source of randomness.
+ *
+ * @param rand the source of randomness
+ */
+ private void randomize(Random rand)
+ {
+ polynomial.expandN(mDegree);
+ polynomial.randomize(rand);
+ }
+
+ // /////////////////////////////////////////////////////////////////////
+ // comparison
+ // /////////////////////////////////////////////////////////////////////
+
+ /**
+ * Checks whether this element is zero.
+ *
+ * @return <tt>true</tt> if <tt>this</tt> is the zero element
+ */
+ public boolean isZero()
+ {
+ return polynomial.isZero();
+ }
+
+ /**
+ * Tests if the GF2nPolynomialElement has 'one' as value.
+ *
+ * @return true if <i>this</i> equals one (this == 1)
+ */
+ public boolean isOne()
+ {
+ return polynomial.isOne();
+ }
+
+ /**
+ * Compare this element with another object.
+ *
+ * @param other the other object
+ * @return <tt>true</tt> if the two objects are equal, <tt>false</tt>
+ * otherwise
+ */
+ public boolean equals(Object other)
+ {
+ if (other == null || !(other instanceof GF2nPolynomialElement))
+ {
+ return false;
+ }
+ GF2nPolynomialElement otherElem = (GF2nPolynomialElement)other;
+
+ if (mField != otherElem.mField)
+ {
+ if (!mField.getFieldPolynomial().equals(
+ otherElem.mField.getFieldPolynomial()))
+ {
+ return false;
+ }
+ }
+
+ return polynomial.equals(otherElem.polynomial);
+ }
+
+ /**
+ * @return the hash code of this element
+ */
+ public int hashCode()
+ {
+ return mField.hashCode() + polynomial.hashCode();
+ }
+
+ // /////////////////////////////////////////////////////////////////////
+ // access
+ // /////////////////////////////////////////////////////////////////////
+
+ /**
+ * Returns the value of this GF2nPolynomialElement in a new Bitstring.
+ *
+ * @return the value of this GF2nPolynomialElement in a new Bitstring
+ */
+ private GF2Polynomial getGF2Polynomial()
+ {
+ return new GF2Polynomial(polynomial);
+ }
+
+ /**
+ * Checks whether the indexed bit of the bit representation is set.
+ *
+ * @param index the index of the bit to test
+ * @return <tt>true</tt> if the indexed bit is set
+ */
+ boolean testBit(int index)
+ {
+ return polynomial.testBit(index);
+ }
+
+ /**
+ * Returns whether the rightmost bit of the bit representation is set. This
+ * is needed for data conversion according to 1363.
+ *
+ * @return true if the rightmost bit of this element is set
+ */
+ public boolean testRightmostBit()
+ {
+ return polynomial.testBit(0);
+ }
+
+ /**
+ * Compute the sum of this element and <tt>addend</tt>.
+ *
+ * @param addend the addend
+ * @return <tt>this + other</tt> (newly created)
+ * @throws DifferentFieldsException if the elements are of different fields.
+ */
+ public GFElement add(GFElement addend)
+ throws RuntimeException
+ {
+ GF2nPolynomialElement result = new GF2nPolynomialElement(this);
+ result.addToThis(addend);
+ return result;
+ }
+
+ /**
+ * Compute <tt>this + addend</tt> (overwrite <tt>this</tt>).
+ *
+ * @param addend the addend
+ * @throws DifferentFieldsException if the elements are of different fields.
+ */
+ public void addToThis(GFElement addend)
+ throws RuntimeException
+ {
+ if (!(addend instanceof GF2nPolynomialElement))
+ {
+ throw new RuntimeException();
+ }
+ if (!mField.equals(((GF2nPolynomialElement)addend).mField))
+ {
+ throw new RuntimeException();
+ }
+ polynomial.addToThis(((GF2nPolynomialElement)addend).polynomial);
+ }
+
+ /**
+ * Returns <tt>this</tt> element + 'one".
+ *
+ * @return <tt>this</tt> + 'one'
+ */
+ public GF2nElement increase()
+ {
+ GF2nPolynomialElement result = new GF2nPolynomialElement(this);
+ result.increaseThis();
+ return result;
+ }
+
+ /**
+ * Increases this element by 'one'.
+ */
+ public void increaseThis()
+ {
+ polynomial.increaseThis();
+ }
+
+ /**
+ * Compute the product of this element and <tt>factor</tt>.
+ *
+ * @param factor the factor
+ * @return <tt>this * factor</tt> (newly created)
+ * @throws DifferentFieldsException if the elements are of different fields.
+ */
+ public GFElement multiply(GFElement factor)
+ throws RuntimeException
+ {
+ GF2nPolynomialElement result = new GF2nPolynomialElement(this);
+ result.multiplyThisBy(factor);
+ return result;
+ }
+
+ /**
+ * Compute <tt>this * factor</tt> (overwrite <tt>this</tt>).
+ *
+ * @param factor the factor
+ * @throws DifferentFieldsException if the elements are of different fields.
+ */
+ public void multiplyThisBy(GFElement factor)
+ throws RuntimeException
+ {
+ if (!(factor instanceof GF2nPolynomialElement))
+ {
+ throw new RuntimeException();
+ }
+ if (!mField.equals(((GF2nPolynomialElement)factor).mField))
+ {
+ throw new RuntimeException();
+ }
+ if (equals(factor))
+ {
+ squareThis();
+ return;
+ }
+ polynomial = polynomial
+ .multiply(((GF2nPolynomialElement)factor).polynomial);
+ reduceThis();
+ }
+
+ /**
+ * Compute the multiplicative inverse of this element.
+ *
+ * @return <tt>this<sup>-1</sup></tt> (newly created)
+ * @throws ArithmeticException if <tt>this</tt> is the zero element.
+ * @see GF2nPolynomialElement#invertMAIA
+ * @see GF2nPolynomialElement#invertEEA
+ * @see GF2nPolynomialElement#invertSquare
+ */
+ public GFElement invert()
+ throws ArithmeticException
+ {
+ return invertMAIA();
+ }
+
+ /**
+ * Calculates the multiplicative inverse of <i>this</i> and returns the
+ * result in a new GF2nPolynomialElement.
+ *
+ * @return <i>this</i>^(-1)
+ * @throws ArithmeticException if <i>this</i> equals zero
+ */
+ public GF2nPolynomialElement invertEEA()
+ throws ArithmeticException
+ {
+ if (isZero())
+ {
+ throw new ArithmeticException();
+ }
+ GF2Polynomial b = new GF2Polynomial(mDegree + 32, "ONE");
+ b.reduceN();
+ GF2Polynomial c = new GF2Polynomial(mDegree + 32);
+ c.reduceN();
+ GF2Polynomial u = getGF2Polynomial();
+ GF2Polynomial v = mField.getFieldPolynomial();
+ GF2Polynomial h;
+ int j;
+ u.reduceN();
+ while (!u.isOne())
+ {
+ u.reduceN();
+ v.reduceN();
+ j = u.getLength() - v.getLength();
+ if (j < 0)
+ {
+ h = u;
+ u = v;
+ v = h;
+ h = b;
+ b = c;
+ c = h;
+ j = -j;
+ c.reduceN(); // this increases the performance
+ }
+ u.shiftLeftAddThis(v, j);
+ b.shiftLeftAddThis(c, j);
+ }
+ b.reduceN();
+ return new GF2nPolynomialElement((GF2nPolynomialField)mField, b);
+ }
+
+ /**
+ * Calculates the multiplicative inverse of <i>this</i> and returns the
+ * result in a new GF2nPolynomialElement.
+ *
+ * @return <i>this</i>^(-1)
+ * @throws ArithmeticException if <i>this</i> equals zero
+ */
+ public GF2nPolynomialElement invertSquare()
+ throws ArithmeticException
+ {
+ GF2nPolynomialElement n;
+ GF2nPolynomialElement u;
+ int i, j, k, b;
+
+ if (isZero())
+ {
+ throw new ArithmeticException();
+ }
+ // b = (n-1)
+ b = mField.getDegree() - 1;
+ // n = a
+ n = new GF2nPolynomialElement(this);
+ n.polynomial.expandN((mDegree << 1) + 32); // increase performance
+ n.polynomial.reduceN();
+ // k = 1
+ k = 1;
+
+ // for i = (r-1) downto 0 do, r=bitlength(b)
+ for (i = IntegerFunctions.floorLog(b) - 1; i >= 0; i--)
+ {
+ // u = n
+ u = new GF2nPolynomialElement(n);
+ // for j = 1 to k do
+ for (j = 1; j <= k; j++)
+ {
+ // u = u^2
+ u.squareThisPreCalc();
+ }
+ // n = nu
+ n.multiplyThisBy(u);
+ // k = 2k
+ k <<= 1;
+ // if b(i)==1
+ if ((b & bitMask[i]) != 0)
+ {
+ // n = n^2 * b
+ n.squareThisPreCalc();
+ n.multiplyThisBy(this);
+ // k = k+1
+ k += 1;
+ }
+ }
+
+ // outpur n^2
+ n.squareThisPreCalc();
+ return n;
+ }
+
+ /**
+ * Calculates the multiplicative inverse of <i>this</i> using the modified
+ * almost inverse algorithm and returns the result in a new
+ * GF2nPolynomialElement.
+ *
+ * @return <i>this</i>^(-1)
+ * @throws ArithmeticException if <i>this</i> equals zero
+ */
+ public GF2nPolynomialElement invertMAIA()
+ throws ArithmeticException
+ {
+ if (isZero())
+ {
+ throw new ArithmeticException();
+ }
+ GF2Polynomial b = new GF2Polynomial(mDegree, "ONE");
+ GF2Polynomial c = new GF2Polynomial(mDegree);
+ GF2Polynomial u = getGF2Polynomial();
+ GF2Polynomial v = mField.getFieldPolynomial();
+ GF2Polynomial h;
+ while (true)
+ {
+ while (!u.testBit(0))
+ { // x|u (x divides u)
+ u.shiftRightThis(); // u = u / x
+ if (!b.testBit(0))
+ {
+ b.shiftRightThis();
+ }
+ else
+ {
+ b.addToThis(mField.getFieldPolynomial());
+ b.shiftRightThis();
+ }
+ }
+ if (u.isOne())
+ {
+ return new GF2nPolynomialElement((GF2nPolynomialField)mField,
+ b);
+ }
+ u.reduceN();
+ v.reduceN();
+ if (u.getLength() < v.getLength())
+ {
+ h = u;
+ u = v;
+ v = h;
+ h = b;
+ b = c;
+ c = h;
+ }
+ u.addToThis(v);
+ b.addToThis(c);
+ }
+ }
+
+ /**
+ * This method is used internally to map the square()-calls within
+ * GF2nPolynomialElement to one of the possible squaring methods.
+ *
+ * @return <tt>this<sup>2</sup></tt> (newly created)
+ * @see GF2nPolynomialElement#squarePreCalc
+ */
+ public GF2nElement square()
+ {
+ return squarePreCalc();
+ }
+
+ /**
+ * This method is used internally to map the square()-calls within
+ * GF2nPolynomialElement to one of the possible squaring methods.
+ */
+ public void squareThis()
+ {
+ squareThisPreCalc();
+ }
+
+ /**
+ * Squares this GF2nPolynomialElement using GF2nField's squaring matrix.
+ * This is supposed to be fast when using a polynomial (no tri- or
+ * pentanomial) as fieldpolynomial. Use squarePreCalc when using a tri- or
+ * pentanomial as fieldpolynomial instead.
+ *
+ * @return <tt>this<sup>2</sup></tt> (newly created)
+ * @see GF2Polynomial#vectorMult
+ * @see GF2nPolynomialElement#squarePreCalc
+ * @see GF2nPolynomialElement#squareBitwise
+ */
+ public GF2nPolynomialElement squareMatrix()
+ {
+ GF2nPolynomialElement result = new GF2nPolynomialElement(this);
+ result.squareThisMatrix();
+ result.reduceThis();
+ return result;
+ }
+
+ /**
+ * Squares this GF2nPolynomialElement using GF2nFields squaring matrix. This
+ * is supposed to be fast when using a polynomial (no tri- or pentanomial)
+ * as fieldpolynomial. Use squarePreCalc when using a tri- or pentanomial as
+ * fieldpolynomial instead.
+ *
+ * @see GF2Polynomial#vectorMult
+ * @see GF2nPolynomialElement#squarePreCalc
+ * @see GF2nPolynomialElement#squareBitwise
+ */
+ public void squareThisMatrix()
+ {
+ GF2Polynomial result = new GF2Polynomial(mDegree);
+ for (int i = 0; i < mDegree; i++)
+ {
+ if (polynomial
+ .vectorMult(((GF2nPolynomialField)mField).squaringMatrix[mDegree
+ - i - 1]))
+ {
+ result.setBit(i);
+
+ }
+ }
+ polynomial = result;
+ }
+
+ /**
+ * Squares this GF2nPolynomialElement by shifting left its Bitstring and
+ * reducing. This is supposed to be the slowest method. Use squarePreCalc or
+ * squareMatrix instead.
+ *
+ * @return <tt>this<sup>2</sup></tt> (newly created)
+ * @see GF2nPolynomialElement#squareMatrix
+ * @see GF2nPolynomialElement#squarePreCalc
+ * @see GF2Polynomial#squareThisBitwise
+ */
+ public GF2nPolynomialElement squareBitwise()
+ {
+ GF2nPolynomialElement result = new GF2nPolynomialElement(this);
+ result.squareThisBitwise();
+ result.reduceThis();
+ return result;
+ }
+
+ /**
+ * Squares this GF2nPolynomialElement by shifting left its Bitstring and
+ * reducing. This is supposed to be the slowest method. Use squarePreCalc or
+ * squareMatrix instead.
+ *
+ * @see GF2nPolynomialElement#squareMatrix
+ * @see GF2nPolynomialElement#squarePreCalc
+ * @see GF2Polynomial#squareThisBitwise
+ */
+ public void squareThisBitwise()
+ {
+ polynomial.squareThisBitwise();
+ reduceThis();
+ }
+
+ /**
+ * Squares this GF2nPolynomialElement by using precalculated values and
+ * reducing. This is supposed to de fastest when using a trinomial or
+ * pentanomial as field polynomial. Use squareMatrix when using a ordinary
+ * polynomial as field polynomial.
+ *
+ * @return <tt>this<sup>2</sup></tt> (newly created)
+ * @see GF2nPolynomialElement#squareMatrix
+ * @see GF2Polynomial#squareThisPreCalc
+ */
+ public GF2nPolynomialElement squarePreCalc()
+ {
+ GF2nPolynomialElement result = new GF2nPolynomialElement(this);
+ result.squareThisPreCalc();
+ result.reduceThis();
+ return result;
+ }
+
+ /**
+ * Squares this GF2nPolynomialElement by using precalculated values and
+ * reducing. This is supposed to de fastest when using a tri- or pentanomial
+ * as fieldpolynomial. Use squareMatrix when using a ordinary polynomial as
+ * fieldpolynomial.
+ *
+ * @see GF2nPolynomialElement#squareMatrix
+ * @see GF2Polynomial#squareThisPreCalc
+ */
+ public void squareThisPreCalc()
+ {
+ polynomial.squareThisPreCalc();
+ reduceThis();
+ }
+
+ /**
+ * Calculates <i>this</i> to the power of <i>k</i> and returns the result
+ * in a new GF2nPolynomialElement.
+ *
+ * @param k the power
+ * @return <i>this</i>^<i>k</i> in a new GF2nPolynomialElement
+ */
+ public GF2nPolynomialElement power(int k)
+ {
+ if (k == 1)
+ {
+ return new GF2nPolynomialElement(this);
+ }
+
+ GF2nPolynomialElement result = GF2nPolynomialElement
+ .ONE((GF2nPolynomialField)mField);
+ if (k == 0)
+ {
+ return result;
+ }
+
+ GF2nPolynomialElement x = new GF2nPolynomialElement(this);
+ x.polynomial.expandN((x.mDegree << 1) + 32); // increase performance
+ x.polynomial.reduceN();
+
+ for (int i = 0; i < mDegree; i++)
+ {
+ if ((k & (1 << i)) != 0)
+ {
+ result.multiplyThisBy(x);
+ }
+ x.square();
+ }
+
+ return result;
+ }
+
+ /**
+ * Compute the square root of this element and return the result in a new
+ * {@link GF2nPolynomialElement}.
+ *
+ * @return <tt>this<sup>1/2</sup></tt> (newly created)
+ */
+ public GF2nElement squareRoot()
+ {
+ GF2nPolynomialElement result = new GF2nPolynomialElement(this);
+ result.squareRootThis();
+ return result;
+ }
+
+ /**
+ * Compute the square root of this element.
+ */
+ public void squareRootThis()
+ {
+ // increase performance
+ polynomial.expandN((mDegree << 1) + 32);
+ polynomial.reduceN();
+ for (int i = 0; i < mField.getDegree() - 1; i++)
+ {
+ squareThis();
+ }
+ }
+
+ /**
+ * Solves the quadratic equation <tt>z<sup>2</sup> + z = this</tt> if
+ * such a solution exists. This method returns one of the two possible
+ * solutions. The other solution is <tt>z + 1</tt>. Use z.increase() to
+ * compute this solution.
+ *
+ * @return a GF2nPolynomialElement representing one z satisfying the
+ * equation <tt>z<sup>2</sup> + z = this</tt>
+ * @throws NoSolutionException if no solution exists
+ * @see "IEEE 1363, Annex A.4.7"
+ */
+ public GF2nElement solveQuadraticEquation()
+ throws RuntimeException
+ {
+ if (isZero())
+ {
+ return ZERO((GF2nPolynomialField)mField);
+ }
+
+ if ((mDegree & 1) == 1)
+ {
+ return halfTrace();
+ }
+
+ // TODO this can be sped-up by precomputation of p and w's
+ GF2nPolynomialElement z, w;
+ do
+ {
+ // step 1.
+ GF2nPolynomialElement p = new GF2nPolynomialElement(
+ (GF2nPolynomialField)mField, new Random());
+ // step 2.
+ z = ZERO((GF2nPolynomialField)mField);
+ w = (GF2nPolynomialElement)p.clone();
+ // step 3.
+ for (int i = 1; i < mDegree; i++)
+ {
+ // compute z = z^2 + w^2 * this
+ // and w = w^2 + p
+ z.squareThis();
+ w.squareThis();
+ z.addToThis(w.multiply(this));
+ w.addToThis(p);
+ }
+ }
+ while (w.isZero()); // step 4.
+
+ if (!equals(z.square().add(z)))
+ {
+ throw new RuntimeException();
+ }
+
+ // step 5.
+ return z;
+ }
+
+ /**
+ * Returns the trace of this GF2nPolynomialElement.
+ *
+ * @return the trace of this GF2nPolynomialElement
+ */
+ public int trace()
+ {
+ GF2nPolynomialElement t = new GF2nPolynomialElement(this);
+ int i;
+
+ for (i = 1; i < mDegree; i++)
+ {
+ t.squareThis();
+ t.addToThis(this);
+ }
+
+ if (t.isOne())
+ {
+ return 1;
+ }
+ return 0;
+ }
+
+ /**
+ * Returns the half-trace of this GF2nPolynomialElement.
+ *
+ * @return a GF2nPolynomialElement representing the half-trace of this
+ * GF2nPolynomialElement.
+ * @throws DegreeIsEvenException if the degree of this GF2nPolynomialElement is even.
+ */
+ private GF2nPolynomialElement halfTrace()
+ throws RuntimeException
+ {
+ if ((mDegree & 0x01) == 0)
+ {
+ throw new RuntimeException();
+ }
+ int i;
+ GF2nPolynomialElement h = new GF2nPolynomialElement(this);
+
+ for (i = 1; i <= ((mDegree - 1) >> 1); i++)
+ {
+ h.squareThis();
+ h.squareThis();
+ h.addToThis(this);
+ }
+
+ return h;
+ }
+
+ /**
+ * Reduces this GF2nPolynomialElement modulo the field-polynomial.
+ *
+ * @see GF2Polynomial#reduceTrinomial
+ * @see GF2Polynomial#reducePentanomial
+ */
+ private void reduceThis()
+ {
+ if (polynomial.getLength() > mDegree)
+ { // really reduce ?
+ if (((GF2nPolynomialField)mField).isTrinomial())
+ { // fieldpolonomial
+ // is trinomial
+ int tc;
+ try
+ {
+ tc = ((GF2nPolynomialField)mField).getTc();
+ }
+ catch (RuntimeException NATExc)
+ {
+ throw new RuntimeException(
+ "GF2nPolynomialElement.reduce: the field"
+ + " polynomial is not a trinomial");
+ }
+ if (((mDegree - tc) <= 32) // do we have to use slow
+ // bitwise reduction ?
+ || (polynomial.getLength() > (mDegree << 1)))
+ {
+ reduceTrinomialBitwise(tc);
+ return;
+ }
+ polynomial.reduceTrinomial(mDegree, tc);
+ return;
+ }
+ else if (((GF2nPolynomialField)mField).isPentanomial())
+ { // fieldpolynomial
+ // is
+ // pentanomial
+ int[] pc;
+ try
+ {
+ pc = ((GF2nPolynomialField)mField).getPc();
+ }
+ catch (RuntimeException NATExc)
+ {
+ throw new RuntimeException(
+ "GF2nPolynomialElement.reduce: the field"
+ + " polynomial is not a pentanomial");
+ }
+ if (((mDegree - pc[2]) <= 32) // do we have to use slow
+ // bitwise reduction ?
+ || (polynomial.getLength() > (mDegree << 1)))
+ {
+ reducePentanomialBitwise(pc);
+ return;
+ }
+ polynomial.reducePentanomial(mDegree, pc);
+ return;
+ }
+ else
+ { // fieldpolynomial is something else
+ polynomial = polynomial.remainder(mField.getFieldPolynomial());
+ polynomial.expandN(mDegree);
+ return;
+ }
+ }
+ if (polynomial.getLength() < mDegree)
+ {
+ polynomial.expandN(mDegree);
+ }
+ }
+
+ /**
+ * Reduce this GF2nPolynomialElement using the trinomial x^n + x^tc + 1 as
+ * fieldpolynomial. The coefficients are reduced bit by bit.
+ */
+ private void reduceTrinomialBitwise(int tc)
+ {
+ int i;
+ int k = mDegree - tc;
+ for (i = polynomial.getLength() - 1; i >= mDegree; i--)
+ {
+ if (polynomial.testBit(i))
+ {
+
+ polynomial.xorBit(i);
+ polynomial.xorBit(i - k);
+ polynomial.xorBit(i - mDegree);
+
+ }
+ }
+ polynomial.reduceN();
+ polynomial.expandN(mDegree);
+ }
+
+ /**
+ * Reduce this GF2nPolynomialElement using the pentanomial x^n + x^pc[2] +
+ * x^pc[1] + x^pc[0] + 1 as fieldpolynomial. The coefficients are reduced
+ * bit by bit.
+ */
+ private void reducePentanomialBitwise(int[] pc)
+ {
+ int i;
+ int k = mDegree - pc[2];
+ int l = mDegree - pc[1];
+ int m = mDegree - pc[0];
+ for (i = polynomial.getLength() - 1; i >= mDegree; i--)
+ {
+ if (polynomial.testBit(i))
+ {
+ polynomial.xorBit(i);
+ polynomial.xorBit(i - k);
+ polynomial.xorBit(i - l);
+ polynomial.xorBit(i - m);
+ polynomial.xorBit(i - mDegree);
+
+ }
+ }
+ polynomial.reduceN();
+ polynomial.expandN(mDegree);
+ }
+
+ // /////////////////////////////////////////////////////////////////////
+ // conversion
+ // /////////////////////////////////////////////////////////////////////
+
+ /**
+ * Returns a string representing this Bitstrings value using hexadecimal
+ * radix in MSB-first order.
+ *
+ * @return a String representing this Bitstrings value.
+ */
+ public String toString()
+ {
+ return polynomial.toString(16);
+ }
+
+ /**
+ * Returns a string representing this Bitstrings value using hexadecimal or
+ * binary radix in MSB-first order.
+ *
+ * @param radix the radix to use (2 or 16, otherwise 2 is used)
+ * @return a String representing this Bitstrings value.
+ */
+ public String toString(int radix)
+ {
+ return polynomial.toString(radix);
+ }
+
+ /**
+ * Converts this GF2nPolynomialElement to a byte[] according to 1363.
+ *
+ * @return a byte[] representing the value of this GF2nPolynomialElement
+ * @see "P1363 5.5.2 p22f BS2OSP, FE2OSP"
+ */
+ public byte[] toByteArray()
+ {
+ return polynomial.toByteArray();
+ }
+
+ /**
+ * Converts this GF2nPolynomialElement to an integer according to 1363.
+ *
+ * @return a BigInteger representing the value of this
+ * GF2nPolynomialElement
+ * @see "P1363 5.5.1 p22 BS2IP"
+ */
+ public BigInteger toFlexiBigInt()
+ {
+ return polynomial.toFlexiBigInt();
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nPolynomialField.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nPolynomialField.java
new file mode 100644
index 00000000..f9ec0bca
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nPolynomialField.java
@@ -0,0 +1,553 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+
+import java.util.Random;
+import java.util.Vector;
+
+
+/**
+ * This class implements the abstract class <tt>GF2nField</tt> for polynomial
+ * representation. It computes the field polynomial and the squaring matrix.
+ * GF2nField is used by GF2nPolynomialElement which implements the elements of
+ * this field.
+ *
+ * @see GF2nField
+ * @see GF2nPolynomialElement
+ */
+public class GF2nPolynomialField
+ extends GF2nField
+{
+
+ /**
+ * Matrix used for fast squaring
+ */
+ GF2Polynomial[] squaringMatrix;
+
+ // field polynomial is a trinomial
+ private boolean isTrinomial = false;
+
+ // field polynomial is a pentanomial
+ private boolean isPentanomial = false;
+
+ // middle coefficient of the field polynomial in case it is a trinomial
+ private int tc;
+
+ // middle 3 coefficients of the field polynomial in case it is a pentanomial
+ private int[] pc = new int[3];
+
+ /**
+ * constructs an instance of the finite field with 2<sup>deg</sup>
+ * elements and characteristic 2.
+ *
+ * @param deg the extention degree of this field
+ */
+ public GF2nPolynomialField(int deg)
+ {
+ if (deg < 3)
+ {
+ throw new IllegalArgumentException("k must be at least 3");
+ }
+ mDegree = deg;
+ computeFieldPolynomial();
+ computeSquaringMatrix();
+ fields = new Vector();
+ matrices = new Vector();
+ }
+
+ /**
+ * constructs an instance of the finite field with 2<sup>deg</sup>
+ * elements and characteristic 2.
+ *
+ * @param deg the degree of this field
+ * @param file true if you want to read the field polynomial from the
+ * file false if you want to use a random fielpolynomial
+ * (this can take very long for huge degrees)
+ */
+ public GF2nPolynomialField(int deg, boolean file)
+ {
+ if (deg < 3)
+ {
+ throw new IllegalArgumentException("k must be at least 3");
+ }
+ mDegree = deg;
+ if (file)
+ {
+ computeFieldPolynomial();
+ }
+ else
+ {
+ computeFieldPolynomial2();
+ }
+ computeSquaringMatrix();
+ fields = new Vector();
+ matrices = new Vector();
+ }
+
+ /**
+ * Creates a new GF2nField of degree <i>i</i> and uses the given
+ * <i>polynomial</i> as field polynomial. The <i>polynomial</i> is checked
+ * whether it is irreducible. This can take some time if <i>i</i> is huge!
+ *
+ * @param deg degree of the GF2nField
+ * @param polynomial the field polynomial to use
+ * @throws PolynomialIsNotIrreducibleException if the given polynomial is not irreducible in GF(2^<i>i</i>)
+ */
+ public GF2nPolynomialField(int deg, GF2Polynomial polynomial)
+ throws RuntimeException
+ {
+ if (deg < 3)
+ {
+ throw new IllegalArgumentException("degree must be at least 3");
+ }
+ if (polynomial.getLength() != deg + 1)
+ {
+ throw new RuntimeException();
+ }
+ if (!polynomial.isIrreducible())
+ {
+ throw new RuntimeException();
+ }
+ mDegree = deg;
+ // fieldPolynomial = new Bitstring(polynomial);
+ fieldPolynomial = polynomial;
+ computeSquaringMatrix();
+ int k = 2; // check if the polynomial is a trinomial or pentanomial
+ for (int j = 1; j < fieldPolynomial.getLength() - 1; j++)
+ {
+ if (fieldPolynomial.testBit(j))
+ {
+ k++;
+ if (k == 3)
+ {
+ tc = j;
+ }
+ if (k <= 5)
+ {
+ pc[k - 3] = j;
+ }
+ }
+ }
+ if (k == 3)
+ {
+ isTrinomial = true;
+ }
+ if (k == 5)
+ {
+ isPentanomial = true;
+ }
+ fields = new Vector();
+ matrices = new Vector();
+ }
+
+ /**
+ * Returns true if the field polynomial is a trinomial. The coefficient can
+ * be retrieved using getTc().
+ *
+ * @return true if the field polynomial is a trinomial
+ */
+ public boolean isTrinomial()
+ {
+ return isTrinomial;
+ }
+
+ /**
+ * Returns true if the field polynomial is a pentanomial. The coefficients
+ * can be retrieved using getPc().
+ *
+ * @return true if the field polynomial is a pentanomial
+ */
+ public boolean isPentanomial()
+ {
+ return isPentanomial;
+ }
+
+ /**
+ * Returns the degree of the middle coefficient of the used field trinomial
+ * (x^n + x^(getTc()) + 1).
+ *
+ * @return the middle coefficient of the used field trinomial
+ * @throws GFException if the field polynomial is not a trinomial
+ */
+ public int getTc()
+ throws RuntimeException
+ {
+ if (!isTrinomial)
+ {
+ throw new RuntimeException();
+ }
+ return tc;
+ }
+
+ /**
+ * Returns the degree of the middle coefficients of the used field
+ * pentanomial (x^n + x^(getPc()[2]) + x^(getPc()[1]) + x^(getPc()[0]) + 1).
+ *
+ * @return the middle coefficients of the used field pentanomial
+ * @throws GFException if the field polynomial is not a pentanomial
+ */
+ public int[] getPc()
+ throws RuntimeException
+ {
+ if (!isPentanomial)
+ {
+ throw new RuntimeException();
+ }
+ int[] result = new int[3];
+ System.arraycopy(pc, 0, result, 0, 3);
+ return result;
+ }
+
+ /**
+ * Return row vector i of the squaring matrix.
+ *
+ * @param i the index of the row vector to return
+ * @return a copy of squaringMatrix[i]
+ * @see GF2nPolynomialElement#squareMatrix
+ */
+ public GF2Polynomial getSquaringVector(int i)
+ {
+ return new GF2Polynomial(squaringMatrix[i]);
+ }
+
+ /**
+ * Compute a random root of the given GF2Polynomial.
+ *
+ * @param polynomial the polynomial
+ * @return a random root of <tt>polynomial</tt>
+ */
+ protected GF2nElement getRandomRoot(GF2Polynomial polynomial)
+ {
+ // We are in B1!!!
+ GF2nPolynomial c;
+ GF2nPolynomial ut;
+ GF2nElement u;
+ GF2nPolynomial h;
+ int hDegree;
+ // 1. Set g(t) <- f(t)
+ GF2nPolynomial g = new GF2nPolynomial(polynomial, this);
+ int gDegree = g.getDegree();
+ int i;
+
+ // 2. while deg(g) > 1
+ while (gDegree > 1)
+ {
+ do
+ {
+ // 2.1 choose random u (element of) GF(2^m)
+ u = new GF2nPolynomialElement(this, new Random());
+ ut = new GF2nPolynomial(2, GF2nPolynomialElement.ZERO(this));
+ // 2.2 Set c(t) <- ut
+ ut.set(1, u);
+ c = new GF2nPolynomial(ut);
+ // 2.3 For i from 1 to m-1 do
+ for (i = 1; i <= mDegree - 1; i++)
+ {
+ // 2.3.1 c(t) <- (c(t)^2 + ut) mod g(t)
+ c = c.multiplyAndReduce(c, g);
+ c = c.add(ut);
+ }
+ // 2.4 set h(t) <- GCD(c(t), g(t))
+ h = c.gcd(g);
+ // 2.5 if h(t) is constant or deg(g) = deg(h) then go to
+ // step 2.1
+ hDegree = h.getDegree();
+ gDegree = g.getDegree();
+ }
+ while ((hDegree == 0) || (hDegree == gDegree));
+ // 2.6 If 2deg(h) > deg(g) then set g(t) <- g(t)/h(t) ...
+ if ((hDegree << 1) > gDegree)
+ {
+ g = g.quotient(h);
+ }
+ else
+ {
+ // ... else g(t) <- h(t)
+ g = new GF2nPolynomial(h);
+ }
+ gDegree = g.getDegree();
+ }
+ // 3. Output g(0)
+ return g.at(0);
+
+ }
+
+ /**
+ * Computes the change-of-basis matrix for basis conversion according to
+ * 1363. The result is stored in the lists fields and matrices.
+ *
+ * @param B1 the GF2nField to convert to
+ * @see "P1363 A.7.3, p111ff"
+ */
+ protected void computeCOBMatrix(GF2nField B1)
+ {
+ // we are in B0 here!
+ if (mDegree != B1.mDegree)
+ {
+ throw new IllegalArgumentException(
+ "GF2nPolynomialField.computeCOBMatrix: B1 has a different "
+ + "degree and thus cannot be coverted to!");
+ }
+ if (B1 instanceof GF2nONBField)
+ {
+ // speedup (calculation is done in PolynomialElements instead of
+ // ONB)
+ B1.computeCOBMatrix(this);
+ return;
+ }
+ int i, j;
+ GF2nElement[] gamma;
+ GF2nElement u;
+ GF2Polynomial[] COBMatrix = new GF2Polynomial[mDegree];
+ for (i = 0; i < mDegree; i++)
+ {
+ COBMatrix[i] = new GF2Polynomial(mDegree);
+ }
+
+ // find Random Root
+ do
+ {
+ // u is in representation according to B1
+ u = B1.getRandomRoot(fieldPolynomial);
+ }
+ while (u.isZero());
+
+ // build gamma matrix by multiplying by u
+ if (u instanceof GF2nONBElement)
+ {
+ gamma = new GF2nONBElement[mDegree];
+ gamma[mDegree - 1] = GF2nONBElement.ONE((GF2nONBField)B1);
+ }
+ else
+ {
+ gamma = new GF2nPolynomialElement[mDegree];
+ gamma[mDegree - 1] = GF2nPolynomialElement
+ .ONE((GF2nPolynomialField)B1);
+ }
+ gamma[mDegree - 2] = u;
+ for (i = mDegree - 3; i >= 0; i--)
+ {
+ gamma[i] = (GF2nElement)gamma[i + 1].multiply(u);
+ }
+ if (B1 instanceof GF2nONBField)
+ {
+ // convert horizontal gamma matrix by vertical Bitstrings
+ for (i = 0; i < mDegree; i++)
+ {
+ for (j = 0; j < mDegree; j++)
+ {
+ // TODO remember: ONB treats its Bits in reverse order !!!
+ if (gamma[i].testBit(mDegree - j - 1))
+ {
+ COBMatrix[mDegree - j - 1].setBit(mDegree - i - 1);
+ }
+ }
+ }
+ }
+ else
+ {
+ // convert horizontal gamma matrix by vertical Bitstrings
+ for (i = 0; i < mDegree; i++)
+ {
+ for (j = 0; j < mDegree; j++)
+ {
+ if (gamma[i].testBit(j))
+ {
+ COBMatrix[mDegree - j - 1].setBit(mDegree - i - 1);
+ }
+ }
+ }
+ }
+
+ // store field and matrix for further use
+ fields.addElement(B1);
+ matrices.addElement(COBMatrix);
+ // store field and inverse matrix for further use in B1
+ B1.fields.addElement(this);
+ B1.matrices.addElement(invertMatrix(COBMatrix));
+ }
+
+ /**
+ * Computes a new squaring matrix used for fast squaring.
+ *
+ * @see GF2nPolynomialElement#square
+ */
+ private void computeSquaringMatrix()
+ {
+ GF2Polynomial[] d = new GF2Polynomial[mDegree - 1];
+ int i, j;
+ squaringMatrix = new GF2Polynomial[mDegree];
+ for (i = 0; i < squaringMatrix.length; i++)
+ {
+ squaringMatrix[i] = new GF2Polynomial(mDegree, "ZERO");
+ }
+
+ for (i = 0; i < mDegree - 1; i++)
+ {
+ d[i] = new GF2Polynomial(1, "ONE").shiftLeft(mDegree + i)
+ .remainder(fieldPolynomial);
+ }
+ for (i = 1; i <= Math.abs(mDegree >> 1); i++)
+ {
+ for (j = 1; j <= mDegree; j++)
+ {
+ if (d[mDegree - (i << 1)].testBit(mDegree - j))
+ {
+ squaringMatrix[j - 1].setBit(mDegree - i);
+ }
+ }
+ }
+ for (i = Math.abs(mDegree >> 1) + 1; i <= mDegree; i++)
+ {
+ squaringMatrix[(i << 1) - mDegree - 1].setBit(mDegree - i);
+ }
+
+ }
+
+ /**
+ * Computes the field polynomial. This can take a long time for big degrees.
+ */
+ protected void computeFieldPolynomial()
+ {
+ if (testTrinomials())
+ {
+ return;
+ }
+ if (testPentanomials())
+ {
+ return;
+ }
+ testRandom();
+ }
+
+ /**
+ * Computes the field polynomial. This can take a long time for big degrees.
+ */
+ protected void computeFieldPolynomial2()
+ {
+ if (testTrinomials())
+ {
+ return;
+ }
+ if (testPentanomials())
+ {
+ return;
+ }
+ testRandom();
+ }
+
+ /**
+ * Tests all trinomials of degree (n+1) until a irreducible is found and
+ * stores the result in <i>field polynomial</i>. Returns false if no
+ * irreducible trinomial exists in GF(2^n). This can take very long for huge
+ * degrees.
+ *
+ * @return true if an irreducible trinomial is found
+ */
+ private boolean testTrinomials()
+ {
+ int i, l;
+ boolean done = false;
+ l = 0;
+
+ fieldPolynomial = new GF2Polynomial(mDegree + 1);
+ fieldPolynomial.setBit(0);
+ fieldPolynomial.setBit(mDegree);
+ for (i = 1; (i < mDegree) && !done; i++)
+ {
+ fieldPolynomial.setBit(i);
+ done = fieldPolynomial.isIrreducible();
+ l++;
+ if (done)
+ {
+ isTrinomial = true;
+ tc = i;
+ return done;
+ }
+ fieldPolynomial.resetBit(i);
+ done = fieldPolynomial.isIrreducible();
+ }
+
+ return done;
+ }
+
+ /**
+ * Tests all pentanomials of degree (n+1) until a irreducible is found and
+ * stores the result in <i>field polynomial</i>. Returns false if no
+ * irreducible pentanomial exists in GF(2^n). This can take very long for
+ * huge degrees.
+ *
+ * @return true if an irreducible pentanomial is found
+ */
+ private boolean testPentanomials()
+ {
+ int i, j, k, l;
+ boolean done = false;
+ l = 0;
+
+ fieldPolynomial = new GF2Polynomial(mDegree + 1);
+ fieldPolynomial.setBit(0);
+ fieldPolynomial.setBit(mDegree);
+ for (i = 1; (i <= (mDegree - 3)) && !done; i++)
+ {
+ fieldPolynomial.setBit(i);
+ for (j = i + 1; (j <= (mDegree - 2)) && !done; j++)
+ {
+ fieldPolynomial.setBit(j);
+ for (k = j + 1; (k <= (mDegree - 1)) && !done; k++)
+ {
+ fieldPolynomial.setBit(k);
+ if (((mDegree & 1) != 0) | ((i & 1) != 0) | ((j & 1) != 0)
+ | ((k & 1) != 0))
+ {
+ done = fieldPolynomial.isIrreducible();
+ l++;
+ if (done)
+ {
+ isPentanomial = true;
+ pc[0] = i;
+ pc[1] = j;
+ pc[2] = k;
+ return done;
+ }
+ }
+ fieldPolynomial.resetBit(k);
+ }
+ fieldPolynomial.resetBit(j);
+ }
+ fieldPolynomial.resetBit(i);
+ }
+
+ return done;
+ }
+
+ /**
+ * Tests random polynomials of degree (n+1) until an irreducible is found
+ * and stores the result in <i>field polynomial</i>. This can take very
+ * long for huge degrees.
+ *
+ * @return true
+ */
+ private boolean testRandom()
+ {
+ int l;
+ boolean done = false;
+
+ fieldPolynomial = new GF2Polynomial(mDegree + 1);
+ l = 0;
+ while (!done)
+ {
+ l++;
+ fieldPolynomial.randomize();
+ fieldPolynomial.setBit(mDegree);
+ fieldPolynomial.setBit(0);
+ if (fieldPolynomial.isIrreducible())
+ {
+ done = true;
+ return done;
+ }
+ }
+
+ return done;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GFElement.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GFElement.java
new file mode 100644
index 00000000..c33f1956
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GFElement.java
@@ -0,0 +1,158 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+import java.math.BigInteger;
+
+
+/**
+ * This interface defines a finite field element. It is implemented by the
+ * classes {@link GFPElement} and {@link GF2nElement}.
+ *
+ * @see GFPElement
+ * @see GF2nElement
+ */
+public interface GFElement
+{
+
+ /**
+ * @return a copy of this GFElement
+ */
+ Object clone();
+
+ // /////////////////////////////////////////////////////////////////
+ // comparison
+ // /////////////////////////////////////////////////////////////////
+
+ /**
+ * Compare this curve with another object.
+ *
+ * @param other the other object
+ * @return the result of the comparison
+ */
+ boolean equals(Object other);
+
+ /**
+ * @return the hash code of this element
+ */
+ int hashCode();
+
+ /**
+ * Checks whether this element is zero.
+ *
+ * @return <tt>true</tt> if <tt>this</tt> is the zero element
+ */
+ boolean isZero();
+
+ /**
+ * Checks whether this element is one.
+ *
+ * @return <tt>true</tt> if <tt>this</tt> is the one element
+ */
+ boolean isOne();
+
+ // /////////////////////////////////////////////////////////////////////
+ // arithmetic
+ // /////////////////////////////////////////////////////////////////////
+
+ /**
+ * Compute the sum of this element and the addend.
+ *
+ * @param addend the addend
+ * @return <tt>this + other</tt> (newly created)
+ * @throws DifferentFieldsException if the elements are of different fields.
+ */
+ GFElement add(GFElement addend)
+ throws RuntimeException;
+
+ /**
+ * Compute the sum of this element and the addend, overwriting this element.
+ *
+ * @param addend the addend
+ * @throws DifferentFieldsException if the elements are of different fields.
+ */
+ void addToThis(GFElement addend)
+ throws RuntimeException;
+
+ /**
+ * Compute the difference of this element and <tt>minuend</tt>.
+ *
+ * @param minuend the minuend
+ * @return <tt>this - minuend</tt> (newly created)
+ * @throws DifferentFieldsException if the elements are of different fields.
+ */
+ GFElement subtract(GFElement minuend)
+ throws RuntimeException;
+
+ /**
+ * Compute the difference of this element and <tt>minuend</tt>,
+ * overwriting this element.
+ *
+ * @param minuend the minuend
+ * @throws DifferentFieldsException if the elements are of different fields.
+ */
+ void subtractFromThis(GFElement minuend);
+
+ /**
+ * Compute the product of this element and <tt>factor</tt>.
+ *
+ * @param factor the factor
+ * @return <tt>this * factor</tt> (newly created)
+ * @throws DifferentFieldsException if the elements are of different fields.
+ */
+ GFElement multiply(GFElement factor)
+ throws RuntimeException;
+
+ /**
+ * Compute <tt>this * factor</tt> (overwrite <tt>this</tt>).
+ *
+ * @param factor the factor
+ * @throws DifferentFieldsException if the elements are of different fields.
+ */
+ void multiplyThisBy(GFElement factor)
+ throws RuntimeException;
+
+ /**
+ * Compute the multiplicative inverse of this element.
+ *
+ * @return <tt>this<sup>-1</sup></tt> (newly created)
+ * @throws ArithmeticException if <tt>this</tt> is the zero element.
+ */
+ GFElement invert()
+ throws ArithmeticException;
+
+ // /////////////////////////////////////////////////////////////////////
+ // conversion
+ // /////////////////////////////////////////////////////////////////////
+
+ /**
+ * Returns this element as FlexiBigInt. The conversion is <a
+ * href="http://grouper.ieee.org/groups/1363/">P1363</a>-conform.
+ *
+ * @return this element as BigInt
+ */
+ BigInteger toFlexiBigInt();
+
+ /**
+ * Returns this element as byte array. The conversion is <a href =
+ * "http://grouper.ieee.org/groups/1363/">P1363</a>-conform.
+ *
+ * @return this element as byte array
+ */
+ byte[] toByteArray();
+
+ /**
+ * Return a String representation of this element.
+ *
+ * @return String representation of this element
+ */
+ String toString();
+
+ /**
+ * Return a String representation of this element. <tt>radix</tt>
+ * specifies the radix of the String representation.
+ *
+ * @param radix specifies the radix of the String representation
+ * @return String representation of this element with the specified radix
+ */
+ String toString(int radix);
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GoppaCode.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GoppaCode.java
new file mode 100644
index 00000000..2249d936
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GoppaCode.java
@@ -0,0 +1,310 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+import java.security.SecureRandom;
+
+/**
+ * This class describes decoding operations of an irreducible binary Goppa code.
+ * A check matrix H of the Goppa code and an irreducible Goppa polynomial are
+ * used the operations are worked over a finite field GF(2^m)
+ *
+ * @see GF2mField
+ * @see PolynomialGF2mSmallM
+ */
+public final class GoppaCode
+{
+
+ /**
+ * Default constructor (private).
+ */
+ private GoppaCode()
+ {
+ // empty
+ }
+
+ /**
+ * This class is a container for two instances of {@link GF2Matrix} and one
+ * instance of {@link Permutation}. It is used to hold the systematic form
+ * <tt>S*H*P = (Id|M)</tt> of the check matrix <tt>H</tt> as returned by
+ * {@link GoppaCode#computeSystematicForm(GF2Matrix, SecureRandom)}.
+ *
+ * @see GF2Matrix
+ * @see Permutation
+ */
+ public static class MaMaPe
+ {
+
+ private GF2Matrix s, h;
+
+ private Permutation p;
+
+ /**
+ * Construct a new {@link MaMaPe} container with the given parameters.
+ *
+ * @param s the first matrix
+ * @param h the second matrix
+ * @param p the permutation
+ */
+ public MaMaPe(GF2Matrix s, GF2Matrix h, Permutation p)
+ {
+ this.s = s;
+ this.h = h;
+ this.p = p;
+ }
+
+ /**
+ * @return the first matrix
+ */
+ public GF2Matrix getFirstMatrix()
+ {
+ return s;
+ }
+
+ /**
+ * @return the second matrix
+ */
+ public GF2Matrix getSecondMatrix()
+ {
+ return h;
+ }
+
+ /**
+ * @return the permutation
+ */
+ public Permutation getPermutation()
+ {
+ return p;
+ }
+ }
+
+ /**
+ * This class is a container for an instance of {@link GF2Matrix} and one
+ * int[]. It is used to hold a generator matrix and the set of indices such
+ * that the submatrix of the generator matrix consisting of the specified
+ * columns is the identity.
+ *
+ * @see GF2Matrix
+ * @see Permutation
+ */
+ public static class MatrixSet
+ {
+
+ private GF2Matrix g;
+
+ private int[] setJ;
+
+ /**
+ * Construct a new {@link MatrixSet} container with the given
+ * parameters.
+ *
+ * @param g the generator matrix
+ * @param setJ the set of indices such that the submatrix of the
+ * generator matrix consisting of the specified columns
+ * is the identity
+ */
+ public MatrixSet(GF2Matrix g, int[] setJ)
+ {
+ this.g = g;
+ this.setJ = setJ;
+ }
+
+ /**
+ * @return the generator matrix
+ */
+ public GF2Matrix getG()
+ {
+ return g;
+ }
+
+ /**
+ * @return the set of indices such that the submatrix of the generator
+ * matrix consisting of the specified columns is the identity
+ */
+ public int[] getSetJ()
+ {
+ return setJ;
+ }
+ }
+
+ /**
+ * Construct the check matrix of a Goppa code in canonical form from the
+ * irreducible Goppa polynomial over the finite field
+ * <tt>GF(2<sup>m</sup>)</tt>.
+ *
+ * @param field the finite field
+ * @param gp the irreducible Goppa polynomial
+ */
+ public static GF2Matrix createCanonicalCheckMatrix(GF2mField field,
+ PolynomialGF2mSmallM gp)
+ {
+ int m = field.getDegree();
+ int n = 1 << m;
+ int t = gp.getDegree();
+
+ /* create matrix H over GF(2^m) */
+
+ int[][] hArray = new int[t][n];
+
+ // create matrix YZ
+ int[][] yz = new int[t][n];
+ for (int j = 0; j < n; j++)
+ {
+ // here j is used as index and as element of field GF(2^m)
+ yz[0][j] = field.inverse(gp.evaluateAt(j));
+ }
+
+ for (int i = 1; i < t; i++)
+ {
+ for (int j = 0; j < n; j++)
+ {
+ // here j is used as index and as element of field GF(2^m)
+ yz[i][j] = field.mult(yz[i - 1][j], j);
+ }
+ }
+
+ // create matrix H = XYZ
+ for (int i = 0; i < t; i++)
+ {
+ for (int j = 0; j < n; j++)
+ {
+ for (int k = 0; k <= i; k++)
+ {
+ hArray[i][j] = field.add(hArray[i][j], field.mult(yz[k][j],
+ gp.getCoefficient(t + k - i)));
+ }
+ }
+ }
+
+ /* convert to matrix over GF(2) */
+
+ int[][] result = new int[t * m][(n + 31) >>> 5];
+
+ for (int j = 0; j < n; j++)
+ {
+ int q = j >>> 5;
+ int r = 1 << (j & 0x1f);
+ for (int i = 0; i < t; i++)
+ {
+ int e = hArray[i][j];
+ for (int u = 0; u < m; u++)
+ {
+ int b = (e >>> u) & 1;
+ if (b != 0)
+ {
+ int ind = (i + 1) * m - u - 1;
+ result[ind][q] ^= r;
+ }
+ }
+ }
+ }
+
+ return new GF2Matrix(n, result);
+ }
+
+ /**
+ * Given a check matrix <tt>H</tt>, compute matrices <tt>S</tt>,
+ * <tt>M</tt>, and a random permutation <tt>P</tt> such that
+ * <tt>S*H*P = (Id|M)</tt>. Return <tt>S^-1</tt>, <tt>M</tt>, and
+ * <tt>P</tt> as {@link MaMaPe}. The matrix <tt>(Id | M)</tt> is called
+ * the systematic form of H.
+ *
+ * @param h the check matrix
+ * @param sr a source of randomness
+ * @return the tuple <tt>(S^-1, M, P)</tt>
+ */
+ public static MaMaPe computeSystematicForm(GF2Matrix h, SecureRandom sr)
+ {
+ int n = h.getNumColumns();
+ GF2Matrix hp, sInv;
+ GF2Matrix s = null;
+ Permutation p;
+ boolean found = false;
+
+ do
+ {
+ p = new Permutation(n, sr);
+ hp = (GF2Matrix)h.rightMultiply(p);
+ sInv = hp.getLeftSubMatrix();
+ try
+ {
+ found = true;
+ s = (GF2Matrix)sInv.computeInverse();
+ }
+ catch (ArithmeticException ae)
+ {
+ found = false;
+ }
+ }
+ while (!found);
+
+ GF2Matrix shp = (GF2Matrix)s.rightMultiply(hp);
+ GF2Matrix m = shp.getRightSubMatrix();
+
+ return new MaMaPe(sInv, m, p);
+ }
+
+ /**
+ * Find an error vector <tt>e</tt> over <tt>GF(2)</tt> from an input
+ * syndrome <tt>s</tt> over <tt>GF(2<sup>m</sup>)</tt>.
+ *
+ * @param syndVec the syndrome
+ * @param field the finite field
+ * @param gp the irreducible Goppa polynomial
+ * @param sqRootMatrix the matrix for computing square roots in
+ * <tt>(GF(2<sup>m</sup>))<sup>t</sup></tt>
+ * @return the error vector
+ */
+ public static GF2Vector syndromeDecode(GF2Vector syndVec, GF2mField field,
+ PolynomialGF2mSmallM gp, PolynomialGF2mSmallM[] sqRootMatrix)
+ {
+
+ int n = 1 << field.getDegree();
+
+ // the error vector
+ GF2Vector errors = new GF2Vector(n);
+
+ // if the syndrome vector is zero, the error vector is also zero
+ if (!syndVec.isZero())
+ {
+ // convert syndrome vector to polynomial over GF(2^m)
+ PolynomialGF2mSmallM syndrome = new PolynomialGF2mSmallM(syndVec
+ .toExtensionFieldVector(field));
+
+ // compute T = syndrome^-1 mod gp
+ PolynomialGF2mSmallM t = syndrome.modInverse(gp);
+
+ // compute tau = sqRoot(T + X) mod gp
+ PolynomialGF2mSmallM tau = t.addMonomial(1);
+ tau = tau.modSquareRootMatrix(sqRootMatrix);
+
+ // compute polynomials a and b satisfying a + b*tau = 0 mod gp
+ PolynomialGF2mSmallM[] ab = tau.modPolynomialToFracton(gp);
+
+ // compute the polynomial a^2 + X*b^2
+ PolynomialGF2mSmallM a2 = ab[0].multiply(ab[0]);
+ PolynomialGF2mSmallM b2 = ab[1].multiply(ab[1]);
+ PolynomialGF2mSmallM xb2 = b2.multWithMonomial(1);
+ PolynomialGF2mSmallM a2plusXb2 = a2.add(xb2);
+
+ // normalize a^2 + X*b^2 to obtain the error locator polynomial
+ int headCoeff = a2plusXb2.getHeadCoefficient();
+ int invHeadCoeff = field.inverse(headCoeff);
+ PolynomialGF2mSmallM elp = a2plusXb2.multWithElement(invHeadCoeff);
+
+ // for all elements i of GF(2^m)
+ for (int i = 0; i < n; i++)
+ {
+ // evaluate the error locator polynomial at i
+ int z = elp.evaluateAt(i);
+ // if polynomial evaluates to zero
+ if (z == 0)
+ {
+ // set the i-th coefficient of the error vector
+ errors.setBit(i);
+ }
+ }
+ }
+
+ return errors;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/IntUtils.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/IntUtils.java
new file mode 100644
index 00000000..e586666e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/IntUtils.java
@@ -0,0 +1,202 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+import java.math.BigInteger;
+
+/**
+ *
+ *
+ *
+ */
+public final class IntUtils
+{
+
+ /**
+ * Default constructor (private).
+ */
+ private IntUtils()
+ {
+ // empty
+ }
+
+ /**
+ * Compare two int arrays. No null checks are performed.
+ *
+ * @param left the first int array
+ * @param right the second int array
+ * @return the result of the comparison
+ */
+ public static boolean equals(int[] left, int[] right)
+ {
+ if (left.length != right.length)
+ {
+ return false;
+ }
+ boolean result = true;
+ for (int i = left.length - 1; i >= 0; i--)
+ {
+ result &= left[i] == right[i];
+ }
+ return result;
+ }
+
+ /**
+ * Return a clone of the given int array. No null checks are performed.
+ *
+ * @param array the array to clone
+ * @return the clone of the given array
+ */
+ public static int[] clone(int[] array)
+ {
+ int[] result = new int[array.length];
+ System.arraycopy(array, 0, result, 0, array.length);
+ return result;
+ }
+
+ /**
+ * Fill the given int array with the given value.
+ *
+ * @param array the array
+ * @param value the value
+ */
+ public static void fill(int[] array, int value)
+ {
+ for (int i = array.length - 1; i >= 0; i--)
+ {
+ array[i] = value;
+ }
+ }
+
+ /**
+ * Sorts this array of integers according to the Quicksort algorithm. After
+ * calling this method this array is sorted in ascending order with the
+ * smallest integer taking position 0 in the array.
+ * <p>
+ * This implementation is based on the quicksort algorithm as described in
+ * <code>Data Structures In Java</code> by Thomas A. Standish, Chapter 10,
+ * ISBN 0-201-30564-X.
+ *
+ * @param source the array of integers that needs to be sorted.
+ */
+ public static void quicksort(int[] source)
+ {
+ quicksort(source, 0, source.length - 1);
+ }
+
+ /**
+ * Sort a subarray of a source array. The subarray is specified by its start
+ * and end index.
+ *
+ * @param source the int array to be sorted
+ * @param left the start index of the subarray
+ * @param right the end index of the subarray
+ */
+ public static void quicksort(int[] source, int left, int right)
+ {
+ if (right > left)
+ {
+ int index = partition(source, left, right, right);
+ quicksort(source, left, index - 1);
+ quicksort(source, index + 1, right);
+ }
+ }
+
+ /**
+ * Split a subarray of a source array into two partitions. The left
+ * partition contains elements that have value less than or equal to the
+ * pivot element, the right partition contains the elements that have larger
+ * value.
+ *
+ * @param source the int array whose subarray will be splitted
+ * @param left the start position of the subarray
+ * @param right the end position of the subarray
+ * @param pivotIndex the index of the pivot element inside the array
+ * @return the new index of the pivot element inside the array
+ */
+ private static int partition(int[] source, int left, int right,
+ int pivotIndex)
+ {
+
+ int pivot = source[pivotIndex];
+ source[pivotIndex] = source[right];
+ source[right] = pivot;
+
+ int index = left;
+
+ for (int i = left; i < right; i++)
+ {
+ if (source[i] <= pivot)
+ {
+ int tmp = source[index];
+ source[index] = source[i];
+ source[i] = tmp;
+ index++;
+ }
+ }
+
+ int tmp = source[index];
+ source[index] = source[right];
+ source[right] = tmp;
+
+ return index;
+ }
+
+ /**
+ * Generates a subarray of a given int array.
+ *
+ * @param input -
+ * the input int array
+ * @param start -
+ * the start index
+ * @param end -
+ * the end index
+ * @return a subarray of <tt>input</tt>, ranging from <tt>start</tt> to
+ * <tt>end</tt>
+ */
+ public static int[] subArray(final int[] input, final int start,
+ final int end)
+ {
+ int[] result = new int[end - start];
+ System.arraycopy(input, start, result, 0, end - start);
+ return result;
+ }
+
+ /**
+ * Convert an int array to a {@link FlexiBigInt} array.
+ *
+ * @param input the int array
+ * @return the {@link FlexiBigInt} array
+ */
+ public static BigInteger[] toFlexiBigIntArray(int[] input)
+ {
+ BigInteger[] result = new BigInteger[input.length];
+ for (int i = 0; i < input.length; i++)
+ {
+ result[i] = BigInteger.valueOf(input[i]);
+ }
+ return result;
+ }
+
+ /**
+ * @param input an int array
+ * @return a human readable form of the given int array
+ */
+ public static String toString(int[] input)
+ {
+ String result = "";
+ for (int i = 0; i < input.length; i++)
+ {
+ result += input[i] + " ";
+ }
+ return result;
+ }
+
+ /**
+ * @param input an int arary
+ * @return the int array as hex string
+ */
+ public static String toHexString(int[] input)
+ {
+ return ByteUtils.toHexString(BigEndianConversions.toByteArray(input));
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/IntegerFunctions.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/IntegerFunctions.java
new file mode 100644
index 00000000..a6d5a181
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/IntegerFunctions.java
@@ -0,0 +1,1423 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * Class of number-theory related functions for use with integers represented as
+ * <tt>int</tt>'s or <tt>BigInteger</tt> objects.
+ */
+public final class IntegerFunctions
+{
+
+ private static final BigInteger ZERO = BigInteger.valueOf(0);
+
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ private static final BigInteger TWO = BigInteger.valueOf(2);
+
+ private static final BigInteger FOUR = BigInteger.valueOf(4);
+
+ private static final int[] SMALL_PRIMES = {3, 5, 7, 11, 13, 17, 19, 23,
+ 29, 31, 37, 41};
+
+ private static final long SMALL_PRIME_PRODUCT = 3L * 5 * 7 * 11 * 13 * 17
+ * 19 * 23 * 29 * 31 * 37 * 41;
+
+ private static SecureRandom sr = null;
+
+ // the jacobi function uses this lookup table
+ private static final int[] jacobiTable = {0, 1, 0, -1, 0, -1, 0, 1};
+
+ private IntegerFunctions()
+ {
+ // empty
+ }
+
+ /**
+ * Computes the value of the Jacobi symbol (A|B). The following properties
+ * hold for the Jacobi symbol which makes it a very efficient way to
+ * evaluate the Legendre symbol
+ * <p>
+ * (A|B) = 0 IF gcd(A,B) &gt; 1<br>
+ * (-1|B) = 1 IF n = 1 (mod 1)<br>
+ * (-1|B) = -1 IF n = 3 (mod 4)<br>
+ * (A|B) (C|B) = (AC|B)<br>
+ * (A|B) (A|C) = (A|CB)<br>
+ * (A|B) = (C|B) IF A = C (mod B)<br>
+ * (2|B) = 1 IF N = 1 OR 7 (mod 8)<br>
+ * (2|B) = 1 IF N = 3 OR 5 (mod 8)
+ *
+ * @param A integer value
+ * @param B integer value
+ * @return value of the jacobi symbol (A|B)
+ */
+ public static int jacobi(BigInteger A, BigInteger B)
+ {
+ BigInteger a, b, v;
+ long k = 1;
+
+ k = 1;
+
+ // test trivial cases
+ if (B.equals(ZERO))
+ {
+ a = A.abs();
+ return a.equals(ONE) ? 1 : 0;
+ }
+
+ if (!A.testBit(0) && !B.testBit(0))
+ {
+ return 0;
+ }
+
+ a = A;
+ b = B;
+
+ if (b.signum() == -1)
+ { // b < 0
+ b = b.negate(); // b = -b
+ if (a.signum() == -1)
+ {
+ k = -1;
+ }
+ }
+
+ v = ZERO;
+ while (!b.testBit(0))
+ {
+ v = v.add(ONE); // v = v + 1
+ b = b.divide(TWO); // b = b/2
+ }
+
+ if (v.testBit(0))
+ {
+ k = k * jacobiTable[a.intValue() & 7];
+ }
+
+ if (a.signum() < 0)
+ { // a < 0
+ if (b.testBit(1))
+ {
+ k = -k; // k = -k
+ }
+ a = a.negate(); // a = -a
+ }
+
+ // main loop
+ while (a.signum() != 0)
+ {
+ v = ZERO;
+ while (!a.testBit(0))
+ { // a is even
+ v = v.add(ONE);
+ a = a.divide(TWO);
+ }
+ if (v.testBit(0))
+ {
+ k = k * jacobiTable[b.intValue() & 7];
+ }
+
+ if (a.compareTo(b) < 0)
+ { // a < b
+ // swap and correct intermediate result
+ BigInteger x = a;
+ a = b;
+ b = x;
+ if (a.testBit(1) && b.testBit(1))
+ {
+ k = -k;
+ }
+ }
+ a = a.subtract(b);
+ }
+
+ return b.equals(ONE) ? (int)k : 0;
+ }
+
+ /**
+ * Computes the square root of a BigInteger modulo a prime employing the
+ * Shanks-Tonelli algorithm.
+ *
+ * @param a value out of which we extract the square root
+ * @param p prime modulus that determines the underlying field
+ * @return a number <tt>b</tt> such that b<sup>2</sup> = a (mod p) if
+ * <tt>a</tt> is a quadratic residue modulo <tt>p</tt>.
+ * @throws NoQuadraticResidueException if <tt>a</tt> is a quadratic non-residue modulo <tt>p</tt>
+ */
+ public static BigInteger ressol(BigInteger a, BigInteger p)
+ throws IllegalArgumentException
+ {
+
+ BigInteger v = null;
+
+ if (a.compareTo(ZERO) < 0)
+ {
+ a = a.add(p);
+ }
+
+ if (a.equals(ZERO))
+ {
+ return ZERO;
+ }
+
+ if (p.equals(TWO))
+ {
+ return a;
+ }
+
+ // p = 3 mod 4
+ if (p.testBit(0) && p.testBit(1))
+ {
+ if (jacobi(a, p) == 1)
+ { // a quadr. residue mod p
+ v = p.add(ONE); // v = p+1
+ v = v.shiftRight(2); // v = v/4
+ return a.modPow(v, p); // return a^v mod p
+ // return --> a^((p+1)/4) mod p
+ }
+ throw new IllegalArgumentException("No quadratic residue: " + a + ", " + p);
+ }
+
+ long t = 0;
+
+ // initialization
+ // compute k and s, where p = 2^s (2k+1) +1
+
+ BigInteger k = p.subtract(ONE); // k = p-1
+ long s = 0;
+ while (!k.testBit(0))
+ { // while k is even
+ s++; // s = s+1
+ k = k.shiftRight(1); // k = k/2
+ }
+
+ k = k.subtract(ONE); // k = k - 1
+ k = k.shiftRight(1); // k = k/2
+
+ // initial values
+ BigInteger r = a.modPow(k, p); // r = a^k mod p
+
+ BigInteger n = r.multiply(r).remainder(p); // n = r^2 % p
+ n = n.multiply(a).remainder(p); // n = n * a % p
+ r = r.multiply(a).remainder(p); // r = r * a %p
+
+ if (n.equals(ONE))
+ {
+ return r;
+ }
+
+ // non-quadratic residue
+ BigInteger z = TWO; // z = 2
+ while (jacobi(z, p) == 1)
+ {
+ // while z quadratic residue
+ z = z.add(ONE); // z = z + 1
+ }
+
+ v = k;
+ v = v.multiply(TWO); // v = 2k
+ v = v.add(ONE); // v = 2k + 1
+ BigInteger c = z.modPow(v, p); // c = z^v mod p
+
+ // iteration
+ while (n.compareTo(ONE) == 1)
+ { // n > 1
+ k = n; // k = n
+ t = s; // t = s
+ s = 0;
+
+ while (!k.equals(ONE))
+ { // k != 1
+ k = k.multiply(k).mod(p); // k = k^2 % p
+ s++; // s = s + 1
+ }
+
+ t -= s; // t = t - s
+ if (t == 0)
+ {
+ throw new IllegalArgumentException("No quadratic residue: " + a + ", " + p);
+ }
+
+ v = ONE;
+ for (long i = 0; i < t - 1; i++)
+ {
+ v = v.shiftLeft(1); // v = 1 * 2^(t - 1)
+ }
+ c = c.modPow(v, p); // c = c^v mod p
+ r = r.multiply(c).remainder(p); // r = r * c % p
+ c = c.multiply(c).remainder(p); // c = c^2 % p
+ n = n.multiply(c).mod(p); // n = n * c % p
+ }
+ return r;
+ }
+
+ /**
+ * Computes the greatest common divisor of the two specified integers
+ *
+ * @param u - first integer
+ * @param v - second integer
+ * @return gcd(a, b)
+ */
+ public static int gcd(int u, int v)
+ {
+ return BigInteger.valueOf(u).gcd(BigInteger.valueOf(v)).intValue();
+ }
+
+ /**
+ * Extended euclidian algorithm (computes gcd and representation).
+ *
+ * @param a the first integer
+ * @param b the second integer
+ * @return <tt>(g,u,v)</tt>, where <tt>g = gcd(abs(a),abs(b)) = ua + vb</tt>
+ */
+ public static int[] extGCD(int a, int b)
+ {
+ BigInteger ba = BigInteger.valueOf(a);
+ BigInteger bb = BigInteger.valueOf(b);
+ BigInteger[] bresult = extgcd(ba, bb);
+ int[] result = new int[3];
+ result[0] = bresult[0].intValue();
+ result[1] = bresult[1].intValue();
+ result[2] = bresult[2].intValue();
+ return result;
+ }
+
+ public static BigInteger divideAndRound(BigInteger a, BigInteger b)
+ {
+ if (a.signum() < 0)
+ {
+ return divideAndRound(a.negate(), b).negate();
+ }
+ if (b.signum() < 0)
+ {
+ return divideAndRound(a, b.negate()).negate();
+ }
+ return a.shiftLeft(1).add(b).divide(b.shiftLeft(1));
+ }
+
+ public static BigInteger[] divideAndRound(BigInteger[] a, BigInteger b)
+ {
+ BigInteger[] out = new BigInteger[a.length];
+ for (int i = 0; i < a.length; i++)
+ {
+ out[i] = divideAndRound(a[i], b);
+ }
+ return out;
+ }
+
+ /**
+ * Compute the smallest integer that is greater than or equal to the
+ * logarithm to the base 2 of the given BigInteger.
+ *
+ * @param a the integer
+ * @return ceil[log(a)]
+ */
+ public static int ceilLog(BigInteger a)
+ {
+ int result = 0;
+ BigInteger p = ONE;
+ while (p.compareTo(a) < 0)
+ {
+ result++;
+ p = p.shiftLeft(1);
+ }
+ return result;
+ }
+
+ /**
+ * Compute the smallest integer that is greater than or equal to the
+ * logarithm to the base 2 of the given integer.
+ *
+ * @param a the integer
+ * @return ceil[log(a)]
+ */
+ public static int ceilLog(int a)
+ {
+ int log = 0;
+ int i = 1;
+ while (i < a)
+ {
+ i <<= 1;
+ log++;
+ }
+ return log;
+ }
+
+ /**
+ * Compute <tt>ceil(log_256 n)</tt>, the number of bytes needed to encode
+ * the integer <tt>n</tt>.
+ *
+ * @param n the integer
+ * @return the number of bytes needed to encode <tt>n</tt>
+ */
+ public static int ceilLog256(int n)
+ {
+ if (n == 0)
+ {
+ return 1;
+ }
+ int m;
+ if (n < 0)
+ {
+ m = -n;
+ }
+ else
+ {
+ m = n;
+ }
+
+ int d = 0;
+ while (m > 0)
+ {
+ d++;
+ m >>>= 8;
+ }
+ return d;
+ }
+
+ /**
+ * Compute <tt>ceil(log_256 n)</tt>, the number of bytes needed to encode
+ * the long integer <tt>n</tt>.
+ *
+ * @param n the long integer
+ * @return the number of bytes needed to encode <tt>n</tt>
+ */
+ public static int ceilLog256(long n)
+ {
+ if (n == 0)
+ {
+ return 1;
+ }
+ long m;
+ if (n < 0)
+ {
+ m = -n;
+ }
+ else
+ {
+ m = n;
+ }
+
+ int d = 0;
+ while (m > 0)
+ {
+ d++;
+ m >>>= 8;
+ }
+ return d;
+ }
+
+ /**
+ * Compute the integer part of the logarithm to the base 2 of the given
+ * integer.
+ *
+ * @param a the integer
+ * @return floor[log(a)]
+ */
+ public static int floorLog(BigInteger a)
+ {
+ int result = -1;
+ BigInteger p = ONE;
+ while (p.compareTo(a) <= 0)
+ {
+ result++;
+ p = p.shiftLeft(1);
+ }
+ return result;
+ }
+
+ /**
+ * Compute the integer part of the logarithm to the base 2 of the given
+ * integer.
+ *
+ * @param a the integer
+ * @return floor[log(a)]
+ */
+ public static int floorLog(int a)
+ {
+ int h = 0;
+ if (a <= 0)
+ {
+ return -1;
+ }
+ int p = a >>> 1;
+ while (p > 0)
+ {
+ h++;
+ p >>>= 1;
+ }
+
+ return h;
+ }
+
+ /**
+ * Compute the largest <tt>h</tt> with <tt>2^h | a</tt> if <tt>a!=0</tt>.
+ *
+ * @param a an integer
+ * @return the largest <tt>h</tt> with <tt>2^h | a</tt> if <tt>a!=0</tt>,
+ * <tt>0</tt> otherwise
+ */
+ public static int maxPower(int a)
+ {
+ int h = 0;
+ if (a != 0)
+ {
+ int p = 1;
+ while ((a & p) == 0)
+ {
+ h++;
+ p <<= 1;
+ }
+ }
+
+ return h;
+ }
+
+ /**
+ * @param a an integer
+ * @return the number of ones in the binary representation of an integer
+ * <tt>a</tt>
+ */
+ public static int bitCount(int a)
+ {
+ int h = 0;
+ while (a != 0)
+ {
+ h += a & 1;
+ a >>>= 1;
+ }
+
+ return h;
+ }
+
+ /**
+ * determines the order of g modulo p, p prime and 1 &lt; g &lt; p. This algorithm
+ * is only efficient for small p (see X9.62-1998, p. 68).
+ *
+ * @param g an integer with 1 &lt; g &lt; p
+ * @param p a prime
+ * @return the order k of g (that is k is the smallest integer with
+ * g<sup>k</sup> = 1 mod p
+ */
+ public static int order(int g, int p)
+ {
+ int b, j;
+
+ b = g % p; // Reduce g mod p first.
+ j = 1;
+
+ // Check whether g == 0 mod p (avoiding endless loop).
+ if (b == 0)
+ {
+ throw new IllegalArgumentException(g + " is not an element of Z/("
+ + p + "Z)^*; it is not meaningful to compute its order.");
+ }
+
+ // Compute the order of g mod p:
+ while (b != 1)
+ {
+ b *= g;
+ b %= p;
+ if (b < 0)
+ {
+ b += p;
+ }
+ j++;
+ }
+
+ return j;
+ }
+
+ /**
+ * Reduces an integer into a given interval
+ *
+ * @param n - the integer
+ * @param begin - left bound of the interval
+ * @param end - right bound of the interval
+ * @return <tt>n</tt> reduced into <tt>[begin,end]</tt>
+ */
+ public static BigInteger reduceInto(BigInteger n, BigInteger begin,
+ BigInteger end)
+ {
+ return n.subtract(begin).mod(end.subtract(begin)).add(begin);
+ }
+
+ /**
+ * Compute <tt>a<sup>e</sup></tt>.
+ *
+ * @param a the base
+ * @param e the exponent
+ * @return <tt>a<sup>e</sup></tt>
+ */
+ public static int pow(int a, int e)
+ {
+ int result = 1;
+ while (e > 0)
+ {
+ if ((e & 1) == 1)
+ {
+ result *= a;
+ }
+ a *= a;
+ e >>>= 1;
+ }
+ return result;
+ }
+
+ /**
+ * Compute <tt>a<sup>e</sup></tt>.
+ *
+ * @param a the base
+ * @param e the exponent
+ * @return <tt>a<sup>e</sup></tt>
+ */
+ public static long pow(long a, int e)
+ {
+ long result = 1;
+ while (e > 0)
+ {
+ if ((e & 1) == 1)
+ {
+ result *= a;
+ }
+ a *= a;
+ e >>>= 1;
+ }
+ return result;
+ }
+
+ /**
+ * Compute <tt>a<sup>e</sup> mod n</tt>.
+ *
+ * @param a the base
+ * @param e the exponent
+ * @param n the modulus
+ * @return <tt>a<sup>e</sup> mod n</tt>
+ */
+ public static int modPow(int a, int e, int n)
+ {
+ if (n <= 0 || (n * n) > Integer.MAX_VALUE || e < 0)
+ {
+ return 0;
+ }
+ int result = 1;
+ a = (a % n + n) % n;
+ while (e > 0)
+ {
+ if ((e & 1) == 1)
+ {
+ result = (result * a) % n;
+ }
+ a = (a * a) % n;
+ e >>>= 1;
+ }
+ return result;
+ }
+
+ /**
+ * Extended euclidian algorithm (computes gcd and representation).
+ *
+ * @param a - the first integer
+ * @param b - the second integer
+ * @return <tt>(d,u,v)</tt>, where <tt>d = gcd(a,b) = ua + vb</tt>
+ */
+ public static BigInteger[] extgcd(BigInteger a, BigInteger b)
+ {
+ BigInteger u = ONE;
+ BigInteger v = ZERO;
+ BigInteger d = a;
+ if (b.signum() != 0)
+ {
+ BigInteger v1 = ZERO;
+ BigInteger v3 = b;
+ while (v3.signum() != 0)
+ {
+ BigInteger[] tmp = d.divideAndRemainder(v3);
+ BigInteger q = tmp[0];
+ BigInteger t3 = tmp[1];
+ BigInteger t1 = u.subtract(q.multiply(v1));
+ u = v1;
+ d = v3;
+ v1 = t1;
+ v3 = t3;
+ }
+ v = d.subtract(a.multiply(u)).divide(b);
+ }
+ return new BigInteger[]{d, u, v};
+ }
+
+ /**
+ * Computation of the least common multiple of a set of BigIntegers.
+ *
+ * @param numbers - the set of numbers
+ * @return the lcm(numbers)
+ */
+ public static BigInteger leastCommonMultiple(BigInteger[] numbers)
+ {
+ int n = numbers.length;
+ BigInteger result = numbers[0];
+ for (int i = 1; i < n; i++)
+ {
+ BigInteger gcd = result.gcd(numbers[i]);
+ result = result.multiply(numbers[i]).divide(gcd);
+ }
+ return result;
+ }
+
+ /**
+ * Returns a long integer whose value is <tt>(a mod m</tt>). This method
+ * differs from <tt>%</tt> in that it always returns a <i>non-negative</i>
+ * integer.
+ *
+ * @param a value on which the modulo operation has to be performed.
+ * @param m the modulus.
+ * @return <tt>a mod m</tt>
+ */
+ public static long mod(long a, long m)
+ {
+ long result = a % m;
+ if (result < 0)
+ {
+ result += m;
+ }
+ return result;
+ }
+
+ /**
+ * Computes the modular inverse of an integer a
+ *
+ * @param a - the integer to invert
+ * @param mod - the modulus
+ * @return <tt>a<sup>-1</sup> mod n</tt>
+ */
+ public static int modInverse(int a, int mod)
+ {
+ return BigInteger.valueOf(a).modInverse(BigInteger.valueOf(mod))
+ .intValue();
+ }
+
+ /**
+ * Computes the modular inverse of an integer a
+ *
+ * @param a - the integer to invert
+ * @param mod - the modulus
+ * @return <tt>a<sup>-1</sup> mod n</tt>
+ */
+ public static long modInverse(long a, long mod)
+ {
+ return BigInteger.valueOf(a).modInverse(BigInteger.valueOf(mod))
+ .longValue();
+ }
+
+ /**
+ * Tests whether an integer <tt>a</tt> is power of another integer
+ * <tt>p</tt>.
+ *
+ * @param a - the first integer
+ * @param p - the second integer
+ * @return n if a = p^n or -1 otherwise
+ */
+ public static int isPower(int a, int p)
+ {
+ if (a <= 0)
+ {
+ return -1;
+ }
+ int n = 0;
+ int d = a;
+ while (d > 1)
+ {
+ if (d % p != 0)
+ {
+ return -1;
+ }
+ d /= p;
+ n++;
+ }
+ return n;
+ }
+
+ /**
+ * Find and return the least non-trivial divisor of an integer <tt>a</tt>.
+ *
+ * @param a - the integer
+ * @return divisor p &gt;1 or 1 if a = -1,0,1
+ */
+ public static int leastDiv(int a)
+ {
+ if (a < 0)
+ {
+ a = -a;
+ }
+ if (a == 0)
+ {
+ return 1;
+ }
+ if ((a & 1) == 0)
+ {
+ return 2;
+ }
+ int p = 3;
+ while (p <= (a / p))
+ {
+ if ((a % p) == 0)
+ {
+ return p;
+ }
+ p += 2;
+ }
+
+ return a;
+ }
+
+ /**
+ * Miller-Rabin-Test, determines wether the given integer is probably prime
+ * or composite. This method returns <tt>true</tt> if the given integer is
+ * prime with probability <tt>1 - 2<sup>-20</sup></tt>.
+ *
+ * @param n the integer to test for primality
+ * @return <tt>true</tt> if the given integer is prime with probability
+ * 2<sup>-100</sup>, <tt>false</tt> otherwise
+ */
+ public static boolean isPrime(int n)
+ {
+ if (n < 2)
+ {
+ return false;
+ }
+ if (n == 2)
+ {
+ return true;
+ }
+ if ((n & 1) == 0)
+ {
+ return false;
+ }
+ if (n < 42)
+ {
+ for (int i = 0; i < SMALL_PRIMES.length; i++)
+ {
+ if (n == SMALL_PRIMES[i])
+ {
+ return true;
+ }
+ }
+ }
+
+ if ((n % 3 == 0) || (n % 5 == 0) || (n % 7 == 0) || (n % 11 == 0)
+ || (n % 13 == 0) || (n % 17 == 0) || (n % 19 == 0)
+ || (n % 23 == 0) || (n % 29 == 0) || (n % 31 == 0)
+ || (n % 37 == 0) || (n % 41 == 0))
+ {
+ return false;
+ }
+
+ return BigInteger.valueOf(n).isProbablePrime(20);
+ }
+
+ /**
+ * Short trial-division test to find out whether a number is not prime. This
+ * test is usually used before a Miller-Rabin primality test.
+ *
+ * @param candidate the number to test
+ * @return <tt>true</tt> if the number has no factor of the tested primes,
+ * <tt>false</tt> if the number is definitely composite
+ */
+ public static boolean passesSmallPrimeTest(BigInteger candidate)
+ {
+ final int[] smallPrime = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37,
+ 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103,
+ 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167,
+ 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
+ 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307,
+ 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379,
+ 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449,
+ 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523,
+ 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607,
+ 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677,
+ 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761,
+ 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853,
+ 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937,
+ 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019,
+ 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087,
+ 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153,
+ 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229,
+ 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297,
+ 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381,
+ 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453,
+ 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499};
+
+ for (int i = 0; i < smallPrime.length; i++)
+ {
+ if (candidate.mod(BigInteger.valueOf(smallPrime[i])).equals(
+ ZERO))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns the largest prime smaller than the given integer
+ *
+ * @param n - upper bound
+ * @return the largest prime smaller than <tt>n</tt>, or <tt>1</tt> if
+ * <tt>n &lt;= 2</tt>
+ */
+ public static int nextSmallerPrime(int n)
+ {
+ if (n <= 2)
+ {
+ return 1;
+ }
+
+ if (n == 3)
+ {
+ return 2;
+ }
+
+ if ((n & 1) == 0)
+ {
+ n--;
+ }
+ else
+ {
+ n -= 2;
+ }
+
+ while (n > 3 & !isPrime(n))
+ {
+ n -= 2;
+ }
+ return n;
+ }
+
+ /**
+ * Compute the next probable prime greater than <tt>n</tt> with the
+ * specified certainty.
+ *
+ * @param n a integer number
+ * @param certainty the certainty that the generated number is prime
+ * @return the next prime greater than <tt>n</tt>
+ */
+ public static BigInteger nextProbablePrime(BigInteger n, int certainty)
+ {
+
+ if (n.signum() < 0 || n.signum() == 0 || n.equals(ONE))
+ {
+ return TWO;
+ }
+
+ BigInteger result = n.add(ONE);
+
+ // Ensure an odd number
+ if (!result.testBit(0))
+ {
+ result = result.add(ONE);
+ }
+
+ while (true)
+ {
+ // Do cheap "pre-test" if applicable
+ if (result.bitLength() > 6)
+ {
+ long r = result.remainder(
+ BigInteger.valueOf(SMALL_PRIME_PRODUCT)).longValue();
+ if ((r % 3 == 0) || (r % 5 == 0) || (r % 7 == 0)
+ || (r % 11 == 0) || (r % 13 == 0) || (r % 17 == 0)
+ || (r % 19 == 0) || (r % 23 == 0) || (r % 29 == 0)
+ || (r % 31 == 0) || (r % 37 == 0) || (r % 41 == 0))
+ {
+ result = result.add(TWO);
+ continue; // Candidate is composite; try another
+ }
+ }
+
+ // All candidates of bitLength 2 and 3 are prime by this point
+ if (result.bitLength() < 4)
+ {
+ return result;
+ }
+
+ // The expensive test
+ if (result.isProbablePrime(certainty))
+ {
+ return result;
+ }
+
+ result = result.add(TWO);
+ }
+ }
+
+ /**
+ * Compute the next probable prime greater than <tt>n</tt> with the default
+ * certainty (20).
+ *
+ * @param n a integer number
+ * @return the next prime greater than <tt>n</tt>
+ */
+ public static BigInteger nextProbablePrime(BigInteger n)
+ {
+ return nextProbablePrime(n, 20);
+ }
+
+ /**
+ * Computes the next prime greater than n.
+ *
+ * @param n a integer number
+ * @return the next prime greater than n
+ */
+ public static BigInteger nextPrime(long n)
+ {
+ long i;
+ boolean found = false;
+ long result = 0;
+
+ if (n <= 1)
+ {
+ return BigInteger.valueOf(2);
+ }
+ if (n == 2)
+ {
+ return BigInteger.valueOf(3);
+ }
+
+ for (i = n + 1 + (n & 1); (i <= n << 1) && !found; i += 2)
+ {
+ for (long j = 3; (j <= i >> 1) && !found; j += 2)
+ {
+ if (i % j == 0)
+ {
+ found = true;
+ }
+ }
+ if (found)
+ {
+ found = false;
+ }
+ else
+ {
+ result = i;
+ found = true;
+ }
+ }
+ return BigInteger.valueOf(result);
+ }
+
+ /**
+ * Computes the binomial coefficient (n|t) ("n over t"). Formula:
+ * <ul>
+ * <li>if n !=0 and t != 0 then (n|t) = Mult(i=1, t): (n-(i-1))/i</li>
+ * <li>if t = 0 then (n|t) = 1</li>
+ * <li>if n = 0 and t &gt; 0 then (n|t) = 0</li>
+ * </ul>
+ *
+ * @param n - the "upper" integer
+ * @param t - the "lower" integer
+ * @return the binomialcoefficient "n over t" as BigInteger
+ */
+ public static BigInteger binomial(int n, int t)
+ {
+
+ BigInteger result = ONE;
+
+ if (n == 0)
+ {
+ if (t == 0)
+ {
+ return result;
+ }
+ return ZERO;
+ }
+
+ // the property (n|t) = (n|n-t) be used to reduce numbers of operations
+ if (t > (n >>> 1))
+ {
+ t = n - t;
+ }
+
+ for (int i = 1; i <= t; i++)
+ {
+ result = (result.multiply(BigInteger.valueOf(n - (i - 1))))
+ .divide(BigInteger.valueOf(i));
+ }
+
+ return result;
+ }
+
+ public static BigInteger randomize(BigInteger upperBound)
+ {
+ if (sr == null)
+ {
+ sr = new SecureRandom();
+ }
+ return randomize(upperBound, sr);
+ }
+
+ public static BigInteger randomize(BigInteger upperBound,
+ SecureRandom prng)
+ {
+ int blen = upperBound.bitLength();
+ BigInteger randomNum = BigInteger.valueOf(0);
+
+ if (prng == null)
+ {
+ prng = sr != null ? sr : new SecureRandom();
+ }
+
+ for (int i = 0; i < 20; i++)
+ {
+ randomNum = new BigInteger(blen, prng);
+ if (randomNum.compareTo(upperBound) < 0)
+ {
+ return randomNum;
+ }
+ }
+ return randomNum.mod(upperBound);
+ }
+
+ /**
+ * Extract the truncated square root of a BigInteger.
+ *
+ * @param a - value out of which we extract the square root
+ * @return the truncated square root of <tt>a</tt>
+ */
+ public static BigInteger squareRoot(BigInteger a)
+ {
+ int bl;
+ BigInteger result, remainder, b;
+
+ if (a.compareTo(ZERO) < 0)
+ {
+ throw new ArithmeticException(
+ "cannot extract root of negative number" + a + ".");
+ }
+
+ bl = a.bitLength();
+ result = ZERO;
+ remainder = ZERO;
+
+ // if the bit length is odd then extra step
+ if ((bl & 1) != 0)
+ {
+ result = result.add(ONE);
+ bl--;
+ }
+
+ while (bl > 0)
+ {
+ remainder = remainder.multiply(FOUR);
+ remainder = remainder.add(BigInteger.valueOf((a.testBit(--bl) ? 2
+ : 0)
+ + (a.testBit(--bl) ? 1 : 0)));
+ b = result.multiply(FOUR).add(ONE);
+ result = result.multiply(TWO);
+ if (remainder.compareTo(b) != -1)
+ {
+ result = result.add(ONE);
+ remainder = remainder.subtract(b);
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Takes an approximation of the root from an integer base, using newton's
+ * algorithm
+ *
+ * @param base the base to take the root from
+ * @param root the root, for example 2 for a square root
+ */
+ public static float intRoot(int base, int root)
+ {
+ float gNew = base / root;
+ float gOld = 0;
+ int counter = 0;
+ while (Math.abs(gOld - gNew) > 0.0001)
+ {
+ float gPow = floatPow(gNew, root);
+ while (Float.isInfinite(gPow))
+ {
+ gNew = (gNew + gOld) / 2;
+ gPow = floatPow(gNew, root);
+ }
+ counter += 1;
+ gOld = gNew;
+ gNew = gOld - (gPow - base) / (root * floatPow(gOld, root - 1));
+ }
+ return gNew;
+ }
+
+ /**
+ * Calculation of a logarithmus of a float param
+ *
+ * @param param
+ * @return
+ */
+ public static float floatLog(float param)
+ {
+ double arg = (param - 1) / (param + 1);
+ double arg2 = arg;
+ int counter = 1;
+ float result = (float)arg;
+
+ while (arg2 > 0.001)
+ {
+ counter += 2;
+ arg2 *= arg * arg;
+ result += (1. / counter) * arg2;
+ }
+ return 2 * result;
+ }
+
+ /**
+ * int power of a base float, only use for small ints
+ *
+ * @param f
+ * @param i
+ * @return
+ */
+ public static float floatPow(float f, int i)
+ {
+ float g = 1;
+ for (; i > 0; i--)
+ {
+ g *= f;
+ }
+ return g;
+ }
+
+ /**
+ * calculate the logarithm to the base 2.
+ *
+ * @param x any double value
+ * @return log_2(x)
+ * @deprecated use MathFunctions.log(double) instead
+ */
+ public static double log(double x)
+ {
+ if (x > 0 && x < 1)
+ {
+ double d = 1 / x;
+ double result = -log(d);
+ return result;
+ }
+
+ int tmp = 0;
+ double tmp2 = 1;
+ double d = x;
+
+ while (d > 2)
+ {
+ d = d / 2;
+ tmp += 1;
+ tmp2 *= 2;
+ }
+ double rem = x / tmp2;
+ rem = logBKM(rem);
+ return tmp + rem;
+ }
+
+ /**
+ * calculate the logarithm to the base 2.
+ *
+ * @param x any long value &gt;=1
+ * @return log_2(x)
+ * @deprecated use MathFunctions.log(long) instead
+ */
+ public static double log(long x)
+ {
+ int tmp = floorLog(BigInteger.valueOf(x));
+ long tmp2 = 1 << tmp;
+ double rem = (double)x / (double)tmp2;
+ rem = logBKM(rem);
+ return tmp + rem;
+ }
+
+ /**
+ * BKM Algorithm to calculate logarithms to the base 2.
+ *
+ * @param arg a double value with 1<= arg<= 4.768462058
+ * @return log_2(arg)
+ * @deprecated use MathFunctions.logBKM(double) instead
+ */
+ private static double logBKM(double arg)
+ {
+ double ae[] = // A_e[k] = log_2 (1 + 0.5^k)
+ {
+ 1.0000000000000000000000000000000000000000000000000000000000000000000000000000,
+ 0.5849625007211561814537389439478165087598144076924810604557526545410982276485,
+ 0.3219280948873623478703194294893901758648313930245806120547563958159347765589,
+ 0.1699250014423123629074778878956330175196288153849621209115053090821964552970,
+ 0.0874628412503394082540660108104043540112672823448206881266090643866965081686,
+ 0.0443941193584534376531019906736094674630459333742491317685543002674288465967,
+ 0.0223678130284545082671320837460849094932677948156179815932199216587899627785,
+ 0.0112272554232541203378805844158839407281095943600297940811823651462712311786,
+ 0.0056245491938781069198591026740666017211096815383520359072957784732489771013,
+ 0.0028150156070540381547362547502839489729507927389771959487826944878598909400,
+ 0.0014081943928083889066101665016890524233311715793462235597709051792834906001,
+ 0.0007042690112466432585379340422201964456668872087249334581924550139514213168,
+ 0.0003521774803010272377989609925281744988670304302127133979341729842842377649,
+ 0.0001760994864425060348637509459678580940163670081839283659942864068257522373,
+ 0.0000880524301221769086378699983597183301490534085738474534831071719854721939,
+ 0.0000440268868273167176441087067175806394819146645511899503059774914593663365,
+ 0.0000220136113603404964890728830697555571275493801909791504158295359319433723,
+ 0.0000110068476674814423006223021573490183469930819844945565597452748333526464,
+ 0.0000055034343306486037230640321058826431606183125807276574241540303833251704,
+ 0.0000027517197895612831123023958331509538486493412831626219340570294203116559,
+ 0.0000013758605508411382010566802834037147561973553922354232704569052932922954,
+ 0.0000006879304394358496786728937442939160483304056131990916985043387874690617,
+ 0.0000003439652607217645360118314743718005315334062644619363447395987584138324,
+ 0.0000001719826406118446361936972479533123619972434705828085978955697643547921,
+ 0.0000000859913228686632156462565208266682841603921494181830811515318381744650,
+ 0.0000000429956620750168703982940244684787907148132725669106053076409624949917,
+ 0.0000000214978311976797556164155504126645192380395989504741781512309853438587,
+ 0.0000000107489156388827085092095702361647949603617203979413516082280717515504,
+ 0.0000000053744578294520620044408178949217773318785601260677517784797554422804,
+ 0.0000000026872289172287079490026152352638891824761667284401180026908031182361,
+ 0.0000000013436144592400232123622589569799954658536700992739887706412976115422,
+ 0.0000000006718072297764289157920422846078078155859484240808550018085324187007,
+ 0.0000000003359036149273187853169587152657145221968468364663464125722491530858,
+ 0.0000000001679518074734354745159899223037458278711244127245990591908996412262,
+ 0.0000000000839759037391617577226571237484864917411614198675604731728132152582,
+ 0.0000000000419879518701918839775296677020135040214077417929807824842667285938,
+ 0.0000000000209939759352486932678195559552767641474249812845414125580747434389,
+ 0.0000000000104969879676625344536740142096218372850561859495065136990936290929,
+ 0.0000000000052484939838408141817781356260462777942148580518406975851213868092,
+ 0.0000000000026242469919227938296243586262369156865545638305682553644113887909,
+ 0.0000000000013121234959619935994960031017850191710121890821178731821983105443,
+ 0.0000000000006560617479811459709189576337295395590603644549624717910616347038,
+ 0.0000000000003280308739906102782522178545328259781415615142931952662153623493,
+ 0.0000000000001640154369953144623242936888032768768777422997704541618141646683,
+ 0.0000000000000820077184976595619616930350508356401599552034612281802599177300,
+ 0.0000000000000410038592488303636807330652208397742314215159774270270147020117,
+ 0.0000000000000205019296244153275153381695384157073687186580546938331088730952,
+ 0.0000000000000102509648122077001764119940017243502120046885379813510430378661,
+ 0.0000000000000051254824061038591928917243090559919209628584150482483994782302,
+ 0.0000000000000025627412030519318726172939815845367496027046030028595094737777,
+ 0.0000000000000012813706015259665053515049475574143952543145124550608158430592,
+ 0.0000000000000006406853007629833949364669629701200556369782295210193569318434,
+ 0.0000000000000003203426503814917330334121037829290364330169106716787999052925,
+ 0.0000000000000001601713251907458754080007074659337446341494733882570243497196,
+ 0.0000000000000000800856625953729399268240176265844257044861248416330071223615,
+ 0.0000000000000000400428312976864705191179247866966320469710511619971334577509,
+ 0.0000000000000000200214156488432353984854413866994246781519154793320684126179,
+ 0.0000000000000000100107078244216177339743404416874899847406043033792202127070,
+ 0.0000000000000000050053539122108088756700751579281894640362199287591340285355,
+ 0.0000000000000000025026769561054044400057638132352058574658089256646014899499,
+ 0.0000000000000000012513384780527022205455634651853807110362316427807660551208,
+ 0.0000000000000000006256692390263511104084521222346348012116229213309001913762,
+ 0.0000000000000000003128346195131755552381436585278035120438976487697544916191,
+ 0.0000000000000000001564173097565877776275512286165232838833090480508502328437,
+ 0.0000000000000000000782086548782938888158954641464170239072244145219054734086,
+ 0.0000000000000000000391043274391469444084776945327473574450334092075712154016,
+ 0.0000000000000000000195521637195734722043713378812583900953755962557525252782,
+ 0.0000000000000000000097760818597867361022187915943503728909029699365320287407,
+ 0.0000000000000000000048880409298933680511176764606054809062553340323879609794,
+ 0.0000000000000000000024440204649466840255609083961603140683286362962192177597,
+ 0.0000000000000000000012220102324733420127809717395445504379645613448652614939,
+ 0.0000000000000000000006110051162366710063906152551383735699323415812152114058,
+ 0.0000000000000000000003055025581183355031953399739107113727036860315024588989,
+ 0.0000000000000000000001527512790591677515976780735407368332862218276873443537,
+ 0.0000000000000000000000763756395295838757988410584167137033767056170417508383,
+ 0.0000000000000000000000381878197647919378994210346199431733717514843471513618,
+ 0.0000000000000000000000190939098823959689497106436628681671067254111334889005,
+ 0.0000000000000000000000095469549411979844748553534196582286585751228071408728,
+ 0.0000000000000000000000047734774705989922374276846068851506055906657137209047,
+ 0.0000000000000000000000023867387352994961187138442777065843718711089344045782,
+ 0.0000000000000000000000011933693676497480593569226324192944532044984865894525,
+ 0.0000000000000000000000005966846838248740296784614396011477934194852481410926,
+ 0.0000000000000000000000002983423419124370148392307506484490384140516252814304,
+ 0.0000000000000000000000001491711709562185074196153830361933046331030629430117,
+ 0.0000000000000000000000000745855854781092537098076934460888486730708440475045,
+ 0.0000000000000000000000000372927927390546268549038472050424734256652501673274,
+ 0.0000000000000000000000000186463963695273134274519237230207489851150821191330,
+ 0.0000000000000000000000000093231981847636567137259618916352525606281553180093,
+ 0.0000000000000000000000000046615990923818283568629809533488457973317312233323,
+ 0.0000000000000000000000000023307995461909141784314904785572277779202790023236,
+ 0.0000000000000000000000000011653997730954570892157452397493151087737428485431,
+ 0.0000000000000000000000000005826998865477285446078726199923328593402722606924,
+ 0.0000000000000000000000000002913499432738642723039363100255852559084863397344,
+ 0.0000000000000000000000000001456749716369321361519681550201473345138307215067,
+ 0.0000000000000000000000000000728374858184660680759840775119123438968122488047,
+ 0.0000000000000000000000000000364187429092330340379920387564158411083803465567,
+ 0.0000000000000000000000000000182093714546165170189960193783228378441837282509,
+ 0.0000000000000000000000000000091046857273082585094980096891901482445902524441,
+ 0.0000000000000000000000000000045523428636541292547490048446022564529197237262,
+ 0.0000000000000000000000000000022761714318270646273745024223029238091160103901};
+ int n = 53;
+ double x = 1;
+ double y = 0;
+ double z;
+ double s = 1;
+ int k;
+
+ for (k = 0; k < n; k++)
+ {
+ z = x + x * s;
+ if (z <= arg)
+ {
+ x = z;
+ y += ae[k];
+ }
+ s *= 0.5;
+ }
+ return y;
+ }
+
+ public static boolean isIncreasing(int[] a)
+ {
+ for (int i = 1; i < a.length; i++)
+ {
+ if (a[i - 1] >= a[i])
+ {
+ System.out.println("a[" + (i - 1) + "] = " + a[i - 1] + " >= "
+ + a[i] + " = a[" + i + "]");
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static byte[] integerToOctets(BigInteger val)
+ {
+ byte[] valBytes = val.abs().toByteArray();
+
+ // check whether the array includes a sign bit
+ if ((val.bitLength() & 7) != 0)
+ {
+ return valBytes;
+ }
+ // get rid of the sign bit (first byte)
+ byte[] tmp = new byte[val.bitLength() >> 3];
+ System.arraycopy(valBytes, 1, tmp, 0, tmp.length);
+ return tmp;
+ }
+
+ public static BigInteger octetsToInteger(byte[] data, int offset,
+ int length)
+ {
+ byte[] val = new byte[length + 1];
+
+ val[0] = 0;
+ System.arraycopy(data, offset, val, 1, length);
+ return new BigInteger(val);
+ }
+
+ public static BigInteger octetsToInteger(byte[] data)
+ {
+ return octetsToInteger(data, 0, data.length);
+ }
+
+ public static void main(String[] args)
+ {
+ System.out.println("test");
+ // System.out.println(intRoot(37, 5));
+ // System.out.println(floatPow((float)2.5, 4));
+ System.out.println(floatLog(10));
+ System.out.println("test2");
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/LittleEndianConversions.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/LittleEndianConversions.java
new file mode 100644
index 00000000..11169521
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/LittleEndianConversions.java
@@ -0,0 +1,230 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+/**
+ * This is a utility class containing data type conversions using little-endian
+ * byte order.
+ *
+ * @see BigEndianConversions
+ */
+public final class LittleEndianConversions
+{
+
+ /**
+ * Default constructor (private).
+ */
+ private LittleEndianConversions()
+ {
+ // empty
+ }
+
+ /**
+ * Convert an octet string of length 4 to an integer. No length checking is
+ * performed.
+ *
+ * @param input the byte array holding the octet string
+ * @return an integer representing the octet string <tt>input</tt>
+ * @throws ArithmeticException if the length of the given octet string is larger than 4.
+ */
+ public static int OS2IP(byte[] input)
+ {
+ return ((input[0] & 0xff)) | ((input[1] & 0xff) << 8)
+ | ((input[2] & 0xff) << 16) | ((input[3] & 0xff)) << 24;
+ }
+
+ /**
+ * Convert an byte array of length 4 beginning at <tt>offset</tt> into an
+ * integer.
+ *
+ * @param input the byte array
+ * @param inOff the offset into the byte array
+ * @return the resulting integer
+ */
+ public static int OS2IP(byte[] input, int inOff)
+ {
+ int result = input[inOff++] & 0xff;
+ result |= (input[inOff++] & 0xff) << 8;
+ result |= (input[inOff++] & 0xff) << 16;
+ result |= (input[inOff] & 0xff) << 24;
+ return result;
+ }
+
+ /**
+ * Convert a byte array of the given length beginning at <tt>offset</tt>
+ * into an integer.
+ *
+ * @param input the byte array
+ * @param inOff the offset into the byte array
+ * @param inLen the length of the encoding
+ * @return the resulting integer
+ */
+ public static int OS2IP(byte[] input, int inOff, int inLen)
+ {
+ int result = 0;
+ for (int i = inLen - 1; i >= 0; i--)
+ {
+ result |= (input[inOff + i] & 0xff) << (8 * i);
+ }
+ return result;
+ }
+
+ /**
+ * Convert a byte array of length 8 beginning at <tt>inOff</tt> into a
+ * long integer.
+ *
+ * @param input the byte array
+ * @param inOff the offset into the byte array
+ * @return the resulting long integer
+ */
+ public static long OS2LIP(byte[] input, int inOff)
+ {
+ long result = input[inOff++] & 0xff;
+ result |= (input[inOff++] & 0xff) << 8;
+ result |= (input[inOff++] & 0xff) << 16;
+ result |= ((long)input[inOff++] & 0xff) << 24;
+ result |= ((long)input[inOff++] & 0xff) << 32;
+ result |= ((long)input[inOff++] & 0xff) << 40;
+ result |= ((long)input[inOff++] & 0xff) << 48;
+ result |= ((long)input[inOff++] & 0xff) << 56;
+ return result;
+ }
+
+ /**
+ * Convert an integer to an octet string of length 4.
+ *
+ * @param x the integer to convert
+ * @return the converted integer
+ */
+ public static byte[] I2OSP(int x)
+ {
+ byte[] result = new byte[4];
+ result[0] = (byte)x;
+ result[1] = (byte)(x >>> 8);
+ result[2] = (byte)(x >>> 16);
+ result[3] = (byte)(x >>> 24);
+ return result;
+ }
+
+ /**
+ * Convert an integer into a byte array beginning at the specified offset.
+ *
+ * @param value the integer to convert
+ * @param output the byte array to hold the result
+ * @param outOff the integer offset into the byte array
+ */
+ public static void I2OSP(int value, byte[] output, int outOff)
+ {
+ output[outOff++] = (byte)value;
+ output[outOff++] = (byte)(value >>> 8);
+ output[outOff++] = (byte)(value >>> 16);
+ output[outOff++] = (byte)(value >>> 24);
+ }
+
+ /**
+ * Convert an integer to a byte array beginning at the specified offset. No
+ * length checking is performed (i.e., if the integer cannot be encoded with
+ * <tt>length</tt> octets, it is truncated).
+ *
+ * @param value the integer to convert
+ * @param output the byte array to hold the result
+ * @param outOff the integer offset into the byte array
+ * @param outLen the length of the encoding
+ */
+ public static void I2OSP(int value, byte[] output, int outOff, int outLen)
+ {
+ for (int i = outLen - 1; i >= 0; i--)
+ {
+ output[outOff + i] = (byte)(value >>> (8 * i));
+ }
+ }
+
+ /**
+ * Convert an integer to a byte array of length 8.
+ *
+ * @param input the integer to convert
+ * @return the converted integer
+ */
+ public static byte[] I2OSP(long input)
+ {
+ byte[] output = new byte[8];
+ output[0] = (byte)input;
+ output[1] = (byte)(input >>> 8);
+ output[2] = (byte)(input >>> 16);
+ output[3] = (byte)(input >>> 24);
+ output[4] = (byte)(input >>> 32);
+ output[5] = (byte)(input >>> 40);
+ output[6] = (byte)(input >>> 48);
+ output[7] = (byte)(input >>> 56);
+ return output;
+ }
+
+ /**
+ * Convert an integer to a byte array of length 8.
+ *
+ * @param input the integer to convert
+ * @param output byte array holding the output
+ * @param outOff offset in output array where the result is stored
+ */
+ public static void I2OSP(long input, byte[] output, int outOff)
+ {
+ output[outOff++] = (byte)input;
+ output[outOff++] = (byte)(input >>> 8);
+ output[outOff++] = (byte)(input >>> 16);
+ output[outOff++] = (byte)(input >>> 24);
+ output[outOff++] = (byte)(input >>> 32);
+ output[outOff++] = (byte)(input >>> 40);
+ output[outOff++] = (byte)(input >>> 48);
+ output[outOff] = (byte)(input >>> 56);
+ }
+
+ /**
+ * Convert an int array to a byte array of the specified length. No length
+ * checking is performed (i.e., if the last integer cannot be encoded with
+ * <tt>length % 4</tt> octets, it is truncated).
+ *
+ * @param input the int array
+ * @param outLen the length of the converted array
+ * @return the converted array
+ */
+ public static byte[] toByteArray(int[] input, int outLen)
+ {
+ int intLen = input.length;
+ byte[] result = new byte[outLen];
+ int index = 0;
+ for (int i = 0; i <= intLen - 2; i++, index += 4)
+ {
+ I2OSP(input[i], result, index);
+ }
+ I2OSP(input[intLen - 1], result, index, outLen - index);
+ return result;
+ }
+
+ /**
+ * Convert a byte array to an int array.
+ *
+ * @param input the byte array
+ * @return the converted array
+ */
+ public static int[] toIntArray(byte[] input)
+ {
+ int intLen = (input.length + 3) / 4;
+ int lastLen = input.length & 0x03;
+ int[] result = new int[intLen];
+
+ int index = 0;
+ for (int i = 0; i <= intLen - 2; i++, index += 4)
+ {
+ result[i] = OS2IP(input, index);
+ }
+ if (lastLen != 0)
+ {
+ result[intLen - 1] = OS2IP(input, index, lastLen);
+ }
+ else
+ {
+ result[intLen - 1] = OS2IP(input, index);
+ }
+
+ return result;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/Matrix.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/Matrix.java
new file mode 100644
index 00000000..170c5a21
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/Matrix.java
@@ -0,0 +1,131 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+/**
+ * This abstract class defines matrices. It holds the number of rows and the
+ * number of columns of the matrix and defines some basic methods.
+ */
+public abstract class Matrix
+{
+
+ /**
+ * number of rows
+ */
+ protected int numRows;
+
+ /**
+ * number of columns
+ */
+ protected int numColumns;
+
+ // ----------------------------------------------------
+ // some constants (matrix types)
+ // ----------------------------------------------------
+
+ /**
+ * zero matrix
+ */
+ public static final char MATRIX_TYPE_ZERO = 'Z';
+
+ /**
+ * unit matrix
+ */
+ public static final char MATRIX_TYPE_UNIT = 'I';
+
+ /**
+ * random lower triangular matrix
+ */
+ public static final char MATRIX_TYPE_RANDOM_LT = 'L';
+
+ /**
+ * random upper triangular matrix
+ */
+ public static final char MATRIX_TYPE_RANDOM_UT = 'U';
+
+ /**
+ * random regular matrix
+ */
+ public static final char MATRIX_TYPE_RANDOM_REGULAR = 'R';
+
+ // ----------------------------------------------------
+ // getters
+ // ----------------------------------------------------
+
+ /**
+ * @return the number of rows in the matrix
+ */
+ public int getNumRows()
+ {
+ return numRows;
+ }
+
+ /**
+ * @return the number of columns in the binary matrix
+ */
+ public int getNumColumns()
+ {
+ return numColumns;
+ }
+
+ /**
+ * @return the encoded matrix, i.e., this matrix in byte array form.
+ */
+ public abstract byte[] getEncoded();
+
+ // ----------------------------------------------------
+ // arithmetic
+ // ----------------------------------------------------
+
+ /**
+ * Compute the inverse of this matrix.
+ *
+ * @return the inverse of this matrix (newly created).
+ */
+ public abstract Matrix computeInverse();
+
+ /**
+ * Check if this is the zero matrix (i.e., all entries are zero).
+ *
+ * @return <tt>true</tt> if this is the zero matrix
+ */
+ public abstract boolean isZero();
+
+ /**
+ * Compute the product of this matrix and another matrix.
+ *
+ * @param a the other matrix
+ * @return <tt>this * a</tt> (newly created)
+ */
+ public abstract Matrix rightMultiply(Matrix a);
+
+ /**
+ * Compute the product of this matrix and a permutation.
+ *
+ * @param p the permutation
+ * @return <tt>this * p</tt> (newly created)
+ */
+ public abstract Matrix rightMultiply(Permutation p);
+
+ /**
+ * Compute the product of a vector and this matrix. If the length of the
+ * vector is greater than the number of rows of this matrix, the matrix is
+ * multiplied by each m-bit part of the vector.
+ *
+ * @param vector a vector
+ * @return <tt>vector * this</tt> (newly created)
+ */
+ public abstract Vector leftMultiply(Vector vector);
+
+ /**
+ * Compute the product of this matrix and a vector.
+ *
+ * @param vector a vector
+ * @return <tt>this * vector</tt> (newly created)
+ */
+ public abstract Vector rightMultiply(Vector vector);
+
+ /**
+ * @return a human readable form of the matrix.
+ */
+ public abstract String toString();
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/Permutation.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/Permutation.java
new file mode 100644
index 00000000..d156672f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/Permutation.java
@@ -0,0 +1,247 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+import java.security.SecureRandom;
+
+/**
+ * This class implements permutations of the set {0,1,...,n-1} for some given n
+ * &gt; 0, i.e., ordered sequences containing each number <tt>m</tt> (<tt>0 &lt;=
+ * m &lt; n</tt>)
+ * once and only once.
+ */
+public class Permutation
+{
+
+ /**
+ * perm holds the elements of the permutation vector, i.e. <tt>[perm(0),
+ * perm(1), ..., perm(n-1)]</tt>
+ */
+ private int[] perm;
+
+ /**
+ * Create the identity permutation of the given size.
+ *
+ * @param n the size of the permutation
+ */
+ public Permutation(int n)
+ {
+ if (n <= 0)
+ {
+ throw new IllegalArgumentException("invalid length");
+ }
+
+ perm = new int[n];
+ for (int i = n - 1; i >= 0; i--)
+ {
+ perm[i] = i;
+ }
+ }
+
+ /**
+ * Create a permutation using the given permutation vector.
+ *
+ * @param perm the permutation vector
+ */
+ public Permutation(int[] perm)
+ {
+ if (!isPermutation(perm))
+ {
+ throw new IllegalArgumentException(
+ "array is not a permutation vector");
+ }
+
+ this.perm = IntUtils.clone(perm);
+ }
+
+ /**
+ * Create a permutation from an encoded permutation.
+ *
+ * @param enc the encoded permutation
+ */
+ public Permutation(byte[] enc)
+ {
+ if (enc.length <= 4)
+ {
+ throw new IllegalArgumentException("invalid encoding");
+ }
+
+ int n = LittleEndianConversions.OS2IP(enc, 0);
+ int size = IntegerFunctions.ceilLog256(n - 1);
+
+ if (enc.length != 4 + n * size)
+ {
+ throw new IllegalArgumentException("invalid encoding");
+ }
+
+ perm = new int[n];
+ for (int i = 0; i < n; i++)
+ {
+ perm[i] = LittleEndianConversions.OS2IP(enc, 4 + i * size, size);
+ }
+
+ if (!isPermutation(perm))
+ {
+ throw new IllegalArgumentException("invalid encoding");
+ }
+
+ }
+
+ /**
+ * Create a random permutation of the given size.
+ *
+ * @param n the size of the permutation
+ * @param sr the source of randomness
+ */
+ public Permutation(int n, SecureRandom sr)
+ {
+ if (n <= 0)
+ {
+ throw new IllegalArgumentException("invalid length");
+ }
+
+ perm = new int[n];
+
+ int[] help = new int[n];
+ for (int i = 0; i < n; i++)
+ {
+ help[i] = i;
+ }
+
+ int k = n;
+ for (int j = 0; j < n; j++)
+ {
+ int i = RandUtils.nextInt(sr, k);
+ k--;
+ perm[j] = help[i];
+ help[i] = help[k];
+ }
+ }
+
+ /**
+ * Encode this permutation as byte array.
+ *
+ * @return the encoded permutation
+ */
+ public byte[] getEncoded()
+ {
+ int n = perm.length;
+ int size = IntegerFunctions.ceilLog256(n - 1);
+ byte[] result = new byte[4 + n * size];
+ LittleEndianConversions.I2OSP(n, result, 0);
+ for (int i = 0; i < n; i++)
+ {
+ LittleEndianConversions.I2OSP(perm[i], result, 4 + i * size, size);
+ }
+ return result;
+ }
+
+ /**
+ * @return the permutation vector <tt>(perm(0),perm(1),...,perm(n-1))</tt>
+ */
+ public int[] getVector()
+ {
+ return IntUtils.clone(perm);
+ }
+
+ /**
+ * Compute the inverse permutation <tt>P<sup>-1</sup></tt>.
+ *
+ * @return <tt>this<sup>-1</sup></tt>
+ */
+ public Permutation computeInverse()
+ {
+ Permutation result = new Permutation(perm.length);
+ for (int i = perm.length - 1; i >= 0; i--)
+ {
+ result.perm[perm[i]] = i;
+ }
+ return result;
+ }
+
+ /**
+ * Compute the product of this permutation and another permutation.
+ *
+ * @param p the other permutation
+ * @return <tt>this * p</tt>
+ */
+ public Permutation rightMultiply(Permutation p)
+ {
+ if (p.perm.length != perm.length)
+ {
+ throw new IllegalArgumentException("length mismatch");
+ }
+ Permutation result = new Permutation(perm.length);
+ for (int i = perm.length - 1; i >= 0; i--)
+ {
+ result.perm[i] = perm[p.perm[i]];
+ }
+ return result;
+ }
+
+ /**
+ * checks if given object is equal to this permutation.
+ * <p>
+ * The method returns false whenever the given object is not permutation.
+ *
+ * @param other -
+ * permutation
+ * @return true or false
+ */
+ public boolean equals(Object other)
+ {
+
+ if (!(other instanceof Permutation))
+ {
+ return false;
+ }
+ Permutation otherPerm = (Permutation)other;
+
+ return IntUtils.equals(perm, otherPerm.perm);
+ }
+
+ /**
+ * @return a human readable form of the permutation
+ */
+ public String toString()
+ {
+ String result = "[" + perm[0];
+ for (int i = 1; i < perm.length; i++)
+ {
+ result += ", " + perm[i];
+ }
+ result += "]";
+ return result;
+ }
+
+ /**
+ * @return the hash code of this permutation
+ */
+ public int hashCode()
+ {
+ return perm.hashCode();
+ }
+
+ /**
+ * Check that the given array corresponds to a permutation of the set
+ * <tt>{0, 1, ..., n-1}</tt>.
+ *
+ * @param perm permutation vector
+ * @return true if perm represents an n-permutation and false otherwise
+ */
+ private boolean isPermutation(int[] perm)
+ {
+ int n = perm.length;
+ boolean[] onlyOnce = new boolean[n];
+
+ for (int i = 0; i < n; i++)
+ {
+ if ((perm[i] < 0) || (perm[i] >= n) || onlyOnce[perm[i]])
+ {
+ return false;
+ }
+ onlyOnce[perm[i]] = true;
+ }
+
+ return true;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialGF2mSmallM.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialGF2mSmallM.java
new file mode 100644
index 00000000..6426a4ce
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialGF2mSmallM.java
@@ -0,0 +1,1124 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+import java.security.SecureRandom;
+
+/**
+ * This class describes operations with polynomials from the ring R =
+ * GF(2^m)[X], where 2 &lt;= m &lt;=31.
+ *
+ * @see GF2mField
+ * @see PolynomialRingGF2m
+ */
+public class PolynomialGF2mSmallM
+{
+
+ /**
+ * the finite field GF(2^m)
+ */
+ private GF2mField field;
+
+ /**
+ * the degree of this polynomial
+ */
+ private int degree;
+
+ /**
+ * For the polynomial representation the map f: R->Z*,
+ * <tt>poly(X) -> [coef_0, coef_1, ...]</tt> is used, where
+ * <tt>coef_i</tt> is the <tt>i</tt>th coefficient of the polynomial
+ * represented as int (see {@link GF2mField}). The polynomials are stored
+ * as int arrays.
+ */
+ private int[] coefficients;
+
+ /*
+ * some types of polynomials
+ */
+
+ /**
+ * Constant used for polynomial construction (see constructor
+ * {@link #PolynomialGF2mSmallM(GF2mField, int, char, SecureRandom)}).
+ */
+ public static final char RANDOM_IRREDUCIBLE_POLYNOMIAL = 'I';
+
+ /**
+ * Construct the zero polynomial over the finite field GF(2^m).
+ *
+ * @param field the finite field GF(2^m)
+ */
+ public PolynomialGF2mSmallM(GF2mField field)
+ {
+ this.field = field;
+ degree = -1;
+ coefficients = new int[1];
+ }
+
+ /**
+ * Construct a polynomial over the finite field GF(2^m).
+ *
+ * @param field the finite field GF(2^m)
+ * @param deg degree of polynomial
+ * @param typeOfPolynomial type of polynomial
+ * @param sr PRNG
+ */
+ public PolynomialGF2mSmallM(GF2mField field, int deg,
+ char typeOfPolynomial, SecureRandom sr)
+ {
+ this.field = field;
+
+ switch (typeOfPolynomial)
+ {
+ case PolynomialGF2mSmallM.RANDOM_IRREDUCIBLE_POLYNOMIAL:
+ coefficients = createRandomIrreduciblePolynomial(deg, sr);
+ break;
+ default:
+ throw new IllegalArgumentException(" Error: type "
+ + typeOfPolynomial
+ + " is not defined for GF2smallmPolynomial");
+ }
+ computeDegree();
+ }
+
+ /**
+ * Create an irreducible polynomial with the given degree over the field
+ * <tt>GF(2^m)</tt>.
+ *
+ * @param deg polynomial degree
+ * @param sr source of randomness
+ * @return the generated irreducible polynomial
+ */
+ private int[] createRandomIrreduciblePolynomial(int deg, SecureRandom sr)
+ {
+ int[] resCoeff = new int[deg + 1];
+ resCoeff[deg] = 1;
+ resCoeff[0] = field.getRandomNonZeroElement(sr);
+ for (int i = 1; i < deg; i++)
+ {
+ resCoeff[i] = field.getRandomElement(sr);
+ }
+ while (!isIrreducible(resCoeff))
+ {
+ int n = RandUtils.nextInt(sr, deg);
+ if (n == 0)
+ {
+ resCoeff[0] = field.getRandomNonZeroElement(sr);
+ }
+ else
+ {
+ resCoeff[n] = field.getRandomElement(sr);
+ }
+ }
+ return resCoeff;
+ }
+
+ /**
+ * Construct a monomial of the given degree over the finite field GF(2^m).
+ *
+ * @param field the finite field GF(2^m)
+ * @param degree the degree of the monomial
+ */
+ public PolynomialGF2mSmallM(GF2mField field, int degree)
+ {
+ this.field = field;
+ this.degree = degree;
+ coefficients = new int[degree + 1];
+ coefficients[degree] = 1;
+ }
+
+ /**
+ * Construct the polynomial over the given finite field GF(2^m) from the
+ * given coefficient vector.
+ *
+ * @param field finite field GF2m
+ * @param coeffs the coefficient vector
+ */
+ public PolynomialGF2mSmallM(GF2mField field, int[] coeffs)
+ {
+ this.field = field;
+ coefficients = normalForm(coeffs);
+ computeDegree();
+ }
+
+ /**
+ * Create a polynomial over the finite field GF(2^m).
+ *
+ * @param field the finite field GF(2^m)
+ * @param enc byte[] polynomial in byte array form
+ */
+ public PolynomialGF2mSmallM(GF2mField field, byte[] enc)
+ {
+ this.field = field;
+
+ // decodes polynomial
+ int d = 8;
+ int count = 1;
+ while (field.getDegree() > d)
+ {
+ count++;
+ d += 8;
+ }
+
+ if ((enc.length % count) != 0)
+ {
+ throw new IllegalArgumentException(
+ " Error: byte array is not encoded polynomial over given finite field GF2m");
+ }
+
+ coefficients = new int[enc.length / count];
+ count = 0;
+ for (int i = 0; i < coefficients.length; i++)
+ {
+ for (int j = 0; j < d; j += 8)
+ {
+ coefficients[i] ^= (enc[count++] & 0x000000ff) << j;
+ }
+ if (!this.field.isElementOfThisField(coefficients[i]))
+ {
+ throw new IllegalArgumentException(
+ " Error: byte array is not encoded polynomial over given finite field GF2m");
+ }
+ }
+ // if HC = 0 for non-zero polynomial, returns error
+ if ((coefficients.length != 1)
+ && (coefficients[coefficients.length - 1] == 0))
+ {
+ throw new IllegalArgumentException(
+ " Error: byte array is not encoded polynomial over given finite field GF2m");
+ }
+ computeDegree();
+ }
+
+ /**
+ * Copy constructor.
+ *
+ * @param other another {@link PolynomialGF2mSmallM}
+ */
+ public PolynomialGF2mSmallM(PolynomialGF2mSmallM other)
+ {
+ // field needs not to be cloned since it is immutable
+ field = other.field;
+ degree = other.degree;
+ coefficients = IntUtils.clone(other.coefficients);
+ }
+
+ /**
+ * Create a polynomial over the finite field GF(2^m) out of the given
+ * coefficient vector. The finite field is also obtained from the
+ * {@link GF2mVector}.
+ *
+ * @param vect the coefficient vector
+ */
+ public PolynomialGF2mSmallM(GF2mVector vect)
+ {
+ this(vect.getField(), vect.getIntArrayForm());
+ }
+
+ /*
+ * ------------------------
+ */
+
+ /**
+ * Return the degree of this polynomial
+ *
+ * @return int degree of this polynomial if this is zero polynomial return
+ * -1
+ */
+ public int getDegree()
+ {
+ int d = coefficients.length - 1;
+ if (coefficients[d] == 0)
+ {
+ return -1;
+ }
+ return d;
+ }
+
+ /**
+ * @return the head coefficient of this polynomial
+ */
+ public int getHeadCoefficient()
+ {
+ if (degree == -1)
+ {
+ return 0;
+ }
+ return coefficients[degree];
+ }
+
+ /**
+ * Return the head coefficient of a polynomial.
+ *
+ * @param a the polynomial
+ * @return the head coefficient of <tt>a</tt>
+ */
+ private static int headCoefficient(int[] a)
+ {
+ int degree = computeDegree(a);
+ if (degree == -1)
+ {
+ return 0;
+ }
+ return a[degree];
+ }
+
+ /**
+ * Return the coefficient with the given index.
+ *
+ * @param index the index
+ * @return the coefficient with the given index
+ */
+ public int getCoefficient(int index)
+ {
+ if ((index < 0) || (index > degree))
+ {
+ return 0;
+ }
+ return coefficients[index];
+ }
+
+ /**
+ * Returns encoded polynomial, i.e., this polynomial in byte array form
+ *
+ * @return the encoded polynomial
+ */
+ public byte[] getEncoded()
+ {
+ int d = 8;
+ int count = 1;
+ while (field.getDegree() > d)
+ {
+ count++;
+ d += 8;
+ }
+
+ byte[] res = new byte[coefficients.length * count];
+ count = 0;
+ for (int i = 0; i < coefficients.length; i++)
+ {
+ for (int j = 0; j < d; j += 8)
+ {
+ res[count++] = (byte)(coefficients[i] >>> j);
+ }
+ }
+
+ return res;
+ }
+
+ /**
+ * Evaluate this polynomial <tt>p</tt> at a value <tt>e</tt> (in
+ * <tt>GF(2^m)</tt>) with the Horner scheme.
+ *
+ * @param e the element of the finite field GF(2^m)
+ * @return <tt>this(e)</tt>
+ */
+ public int evaluateAt(int e)
+ {
+ int result = coefficients[degree];
+ for (int i = degree - 1; i >= 0; i--)
+ {
+ result = field.mult(result, e) ^ coefficients[i];
+ }
+ return result;
+ }
+
+ /**
+ * Compute the sum of this polynomial and the given polynomial.
+ *
+ * @param addend the addend
+ * @return <tt>this + a</tt> (newly created)
+ */
+ public PolynomialGF2mSmallM add(PolynomialGF2mSmallM addend)
+ {
+ int[] resultCoeff = add(coefficients, addend.coefficients);
+ return new PolynomialGF2mSmallM(field, resultCoeff);
+ }
+
+ /**
+ * Add the given polynomial to this polynomial (overwrite this).
+ *
+ * @param addend the addend
+ */
+ public void addToThis(PolynomialGF2mSmallM addend)
+ {
+ coefficients = add(coefficients, addend.coefficients);
+ computeDegree();
+ }
+
+ /**
+ * Compute the sum of two polynomials a and b over the finite field
+ * <tt>GF(2^m)</tt>.
+ *
+ * @param a the first polynomial
+ * @param b the second polynomial
+ * @return a + b
+ */
+ private int[] add(int[] a, int[] b)
+ {
+ int[] result, addend;
+ if (a.length < b.length)
+ {
+ result = new int[b.length];
+ System.arraycopy(b, 0, result, 0, b.length);
+ addend = a;
+ }
+ else
+ {
+ result = new int[a.length];
+ System.arraycopy(a, 0, result, 0, a.length);
+ addend = b;
+ }
+
+ for (int i = addend.length - 1; i >= 0; i--)
+ {
+ result[i] = field.add(result[i], addend[i]);
+ }
+
+ return result;
+ }
+
+ /**
+ * Compute the sum of this polynomial and the monomial of the given degree.
+ *
+ * @param degree the degree of the monomial
+ * @return <tt>this + X^k</tt>
+ */
+ public PolynomialGF2mSmallM addMonomial(int degree)
+ {
+ int[] monomial = new int[degree + 1];
+ monomial[degree] = 1;
+ int[] resultCoeff = add(coefficients, monomial);
+ return new PolynomialGF2mSmallM(field, resultCoeff);
+ }
+
+ /**
+ * Compute the product of this polynomial with an element from GF(2^m).
+ *
+ * @param element an element of the finite field GF(2^m)
+ * @return <tt>this * element</tt> (newly created)
+ * @throws ArithmeticException if <tt>element</tt> is not an element of the finite
+ * field this polynomial is defined over.
+ */
+ public PolynomialGF2mSmallM multWithElement(int element)
+ {
+ if (!field.isElementOfThisField(element))
+ {
+ throw new ArithmeticException(
+ "Not an element of the finite field this polynomial is defined over.");
+ }
+ int[] resultCoeff = multWithElement(coefficients, element);
+ return new PolynomialGF2mSmallM(field, resultCoeff);
+ }
+
+ /**
+ * Multiply this polynomial with an element from GF(2^m).
+ *
+ * @param element an element of the finite field GF(2^m)
+ * @throws ArithmeticException if <tt>element</tt> is not an element of the finite
+ * field this polynomial is defined over.
+ */
+ public void multThisWithElement(int element)
+ {
+ if (!field.isElementOfThisField(element))
+ {
+ throw new ArithmeticException(
+ "Not an element of the finite field this polynomial is defined over.");
+ }
+ coefficients = multWithElement(coefficients, element);
+ computeDegree();
+ }
+
+ /**
+ * Compute the product of a polynomial a with an element from the finite
+ * field <tt>GF(2^m)</tt>.
+ *
+ * @param a the polynomial
+ * @param element an element of the finite field GF(2^m)
+ * @return <tt>a * element</tt>
+ */
+ private int[] multWithElement(int[] a, int element)
+ {
+ int degree = computeDegree(a);
+ if (degree == -1 || element == 0)
+ {
+ return new int[1];
+ }
+
+ if (element == 1)
+ {
+ return IntUtils.clone(a);
+ }
+
+ int[] result = new int[degree + 1];
+ for (int i = degree; i >= 0; i--)
+ {
+ result[i] = field.mult(a[i], element);
+ }
+
+ return result;
+ }
+
+ /**
+ * Compute the product of this polynomial with a monomial X^k.
+ *
+ * @param k the degree of the monomial
+ * @return <tt>this * X^k</tt>
+ */
+ public PolynomialGF2mSmallM multWithMonomial(int k)
+ {
+ int[] resultCoeff = multWithMonomial(coefficients, k);
+ return new PolynomialGF2mSmallM(field, resultCoeff);
+ }
+
+ /**
+ * Compute the product of a polynomial with a monomial X^k.
+ *
+ * @param a the polynomial
+ * @param k the degree of the monomial
+ * @return <tt>a * X^k</tt>
+ */
+ private static int[] multWithMonomial(int[] a, int k)
+ {
+ int d = computeDegree(a);
+ if (d == -1)
+ {
+ return new int[1];
+ }
+ int[] result = new int[d + k + 1];
+ System.arraycopy(a, 0, result, k, d + 1);
+ return result;
+ }
+
+ /**
+ * Divide this polynomial by the given polynomial.
+ *
+ * @param f a polynomial
+ * @return polynomial pair = {q,r} where this = q*f+r and deg(r) &lt;
+ * deg(f);
+ */
+ public PolynomialGF2mSmallM[] div(PolynomialGF2mSmallM f)
+ {
+ int[][] resultCoeffs = div(coefficients, f.coefficients);
+ return new PolynomialGF2mSmallM[]{
+ new PolynomialGF2mSmallM(field, resultCoeffs[0]),
+ new PolynomialGF2mSmallM(field, resultCoeffs[1])};
+ }
+
+ /**
+ * Compute the result of the division of two polynomials over the field
+ * <tt>GF(2^m)</tt>.
+ *
+ * @param a the first polynomial
+ * @param f the second polynomial
+ * @return int[][] {q,r}, where a = q*f+r and deg(r) &lt; deg(f);
+ */
+ private int[][] div(int[] a, int[] f)
+ {
+ int df = computeDegree(f);
+ int da = computeDegree(a) + 1;
+ if (df == -1)
+ {
+ throw new ArithmeticException("Division by zero.");
+ }
+ int[][] result = new int[2][];
+ result[0] = new int[1];
+ result[1] = new int[da];
+ int hc = headCoefficient(f);
+ hc = field.inverse(hc);
+ result[0][0] = 0;
+ System.arraycopy(a, 0, result[1], 0, result[1].length);
+ while (df <= computeDegree(result[1]))
+ {
+ int[] q;
+ int[] coeff = new int[1];
+ coeff[0] = field.mult(headCoefficient(result[1]), hc);
+ q = multWithElement(f, coeff[0]);
+ int n = computeDegree(result[1]) - df;
+ q = multWithMonomial(q, n);
+ coeff = multWithMonomial(coeff, n);
+ result[0] = add(coeff, result[0]);
+ result[1] = add(q, result[1]);
+ }
+ return result;
+ }
+
+ /**
+ * Return the greatest common divisor of this and a polynomial <i>f</i>
+ *
+ * @param f polynomial
+ * @return GCD(this, f)
+ */
+ public PolynomialGF2mSmallM gcd(PolynomialGF2mSmallM f)
+ {
+ int[] resultCoeff = gcd(coefficients, f.coefficients);
+ return new PolynomialGF2mSmallM(field, resultCoeff);
+ }
+
+ /**
+ * Return the greatest common divisor of two polynomials over the field
+ * <tt>GF(2^m)</tt>.
+ *
+ * @param f the first polynomial
+ * @param g the second polynomial
+ * @return <tt>gcd(f, g)</tt>
+ */
+ private int[] gcd(int[] f, int[] g)
+ {
+ int[] a = f;
+ int[] b = g;
+ if (computeDegree(a) == -1)
+ {
+ return b;
+ }
+ while (computeDegree(b) != -1)
+ {
+ int[] c = mod(a, b);
+ a = new int[b.length];
+ System.arraycopy(b, 0, a, 0, a.length);
+ b = new int[c.length];
+ System.arraycopy(c, 0, b, 0, b.length);
+ }
+ int coeff = field.inverse(headCoefficient(a));
+ return multWithElement(a, coeff);
+ }
+
+ /**
+ * Compute the product of this polynomial and the given factor using a
+ * Karatzuba like scheme.
+ *
+ * @param factor the polynomial
+ * @return <tt>this * factor</tt>
+ */
+ public PolynomialGF2mSmallM multiply(PolynomialGF2mSmallM factor)
+ {
+ int[] resultCoeff = multiply(coefficients, factor.coefficients);
+ return new PolynomialGF2mSmallM(field, resultCoeff);
+ }
+
+ /**
+ * Compute the product of two polynomials over the field <tt>GF(2^m)</tt>
+ * using a Karatzuba like multiplication.
+ *
+ * @param a the first polynomial
+ * @param b the second polynomial
+ * @return a * b
+ */
+ private int[] multiply(int[] a, int[] b)
+ {
+ int[] mult1, mult2;
+ if (computeDegree(a) < computeDegree(b))
+ {
+ mult1 = b;
+ mult2 = a;
+ }
+ else
+ {
+ mult1 = a;
+ mult2 = b;
+ }
+
+ mult1 = normalForm(mult1);
+ mult2 = normalForm(mult2);
+
+ if (mult2.length == 1)
+ {
+ return multWithElement(mult1, mult2[0]);
+ }
+
+ int d1 = mult1.length;
+ int d2 = mult2.length;
+ int[] result = new int[d1 + d2 - 1];
+
+ if (d2 != d1)
+ {
+ int[] res1 = new int[d2];
+ int[] res2 = new int[d1 - d2];
+ System.arraycopy(mult1, 0, res1, 0, res1.length);
+ System.arraycopy(mult1, d2, res2, 0, res2.length);
+ res1 = multiply(res1, mult2);
+ res2 = multiply(res2, mult2);
+ res2 = multWithMonomial(res2, d2);
+ result = add(res1, res2);
+ }
+ else
+ {
+ d2 = (d1 + 1) >>> 1;
+ int d = d1 - d2;
+ int[] firstPartMult1 = new int[d2];
+ int[] firstPartMult2 = new int[d2];
+ int[] secondPartMult1 = new int[d];
+ int[] secondPartMult2 = new int[d];
+ System
+ .arraycopy(mult1, 0, firstPartMult1, 0,
+ firstPartMult1.length);
+ System.arraycopy(mult1, d2, secondPartMult1, 0,
+ secondPartMult1.length);
+ System
+ .arraycopy(mult2, 0, firstPartMult2, 0,
+ firstPartMult2.length);
+ System.arraycopy(mult2, d2, secondPartMult2, 0,
+ secondPartMult2.length);
+ int[] helpPoly1 = add(firstPartMult1, secondPartMult1);
+ int[] helpPoly2 = add(firstPartMult2, secondPartMult2);
+ int[] res1 = multiply(firstPartMult1, firstPartMult2);
+ int[] res2 = multiply(helpPoly1, helpPoly2);
+ int[] res3 = multiply(secondPartMult1, secondPartMult2);
+ res2 = add(res2, res1);
+ res2 = add(res2, res3);
+ res3 = multWithMonomial(res3, d2);
+ result = add(res2, res3);
+ result = multWithMonomial(result, d2);
+ result = add(result, res1);
+ }
+
+ return result;
+ }
+
+ /*
+ * ---------------- PART II ----------------
+ *
+ */
+
+ /**
+ * Check a polynomial for irreducibility over the field <tt>GF(2^m)</tt>.
+ *
+ * @param a the polynomial to check
+ * @return true if a is irreducible, false otherwise
+ */
+ private boolean isIrreducible(int[] a)
+ {
+ if (a[0] == 0)
+ {
+ return false;
+ }
+ int d = computeDegree(a) >> 1;
+ int[] u = {0, 1};
+ final int[] Y = {0, 1};
+ int fieldDegree = field.getDegree();
+ for (int i = 0; i < d; i++)
+ {
+ for (int j = fieldDegree - 1; j >= 0; j--)
+ {
+ u = modMultiply(u, u, a);
+ }
+ u = normalForm(u);
+ int[] g = gcd(add(u, Y), a);
+ if (computeDegree(g) != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Reduce this polynomial modulo another polynomial.
+ *
+ * @param f the reduction polynomial
+ * @return <tt>this mod f</tt>
+ */
+ public PolynomialGF2mSmallM mod(PolynomialGF2mSmallM f)
+ {
+ int[] resultCoeff = mod(coefficients, f.coefficients);
+ return new PolynomialGF2mSmallM(field, resultCoeff);
+ }
+
+ /**
+ * Reduce a polynomial modulo another polynomial.
+ *
+ * @param a the polynomial
+ * @param f the reduction polynomial
+ * @return <tt>a mod f</tt>
+ */
+ private int[] mod(int[] a, int[] f)
+ {
+ int df = computeDegree(f);
+ if (df == -1)
+ {
+ throw new ArithmeticException("Division by zero");
+ }
+ int[] result = new int[a.length];
+ int hc = headCoefficient(f);
+ hc = field.inverse(hc);
+ System.arraycopy(a, 0, result, 0, result.length);
+ while (df <= computeDegree(result))
+ {
+ int[] q;
+ int coeff = field.mult(headCoefficient(result), hc);
+ q = multWithMonomial(f, computeDegree(result) - df);
+ q = multWithElement(q, coeff);
+ result = add(q, result);
+ }
+ return result;
+ }
+
+ /**
+ * Compute the product of this polynomial and another polynomial modulo a
+ * third polynomial.
+ *
+ * @param a another polynomial
+ * @param b the reduction polynomial
+ * @return <tt>this * a mod b</tt>
+ */
+ public PolynomialGF2mSmallM modMultiply(PolynomialGF2mSmallM a,
+ PolynomialGF2mSmallM b)
+ {
+ int[] resultCoeff = modMultiply(coefficients, a.coefficients,
+ b.coefficients);
+ return new PolynomialGF2mSmallM(field, resultCoeff);
+ }
+
+ /**
+ * Square this polynomial using a squaring matrix.
+ *
+ * @param matrix the squaring matrix
+ * @return <tt>this^2</tt> modulo the reduction polynomial implicitly
+ * given via the squaring matrix
+ */
+ public PolynomialGF2mSmallM modSquareMatrix(PolynomialGF2mSmallM[] matrix)
+ {
+
+ int length = matrix.length;
+
+ int[] resultCoeff = new int[length];
+ int[] thisSquare = new int[length];
+
+ // square each entry of this polynomial
+ for (int i = 0; i < coefficients.length; i++)
+ {
+ thisSquare[i] = field.mult(coefficients[i], coefficients[i]);
+ }
+
+ // do matrix-vector multiplication
+ for (int i = 0; i < length; i++)
+ {
+ // compute scalar product of i-th row and coefficient vector
+ for (int j = 0; j < length; j++)
+ {
+ if (i >= matrix[j].coefficients.length)
+ {
+ continue;
+ }
+ int scalarTerm = field.mult(matrix[j].coefficients[i],
+ thisSquare[j]);
+ resultCoeff[i] = field.add(resultCoeff[i], scalarTerm);
+ }
+ }
+
+ return new PolynomialGF2mSmallM(field, resultCoeff);
+ }
+
+ /**
+ * Compute the product of two polynomials modulo a third polynomial over the
+ * finite field <tt>GF(2^m)</tt>.
+ *
+ * @param a the first polynomial
+ * @param b the second polynomial
+ * @param g the reduction polynomial
+ * @return <tt>a * b mod g</tt>
+ */
+ private int[] modMultiply(int[] a, int[] b, int[] g)
+ {
+ return mod(multiply(a, b), g);
+ }
+
+ /**
+ * Compute the square root of this polynomial modulo the given polynomial.
+ *
+ * @param a the reduction polynomial
+ * @return <tt>this^(1/2) mod a</tt>
+ */
+ public PolynomialGF2mSmallM modSquareRoot(PolynomialGF2mSmallM a)
+ {
+ int[] resultCoeff = IntUtils.clone(coefficients);
+ int[] help = modMultiply(resultCoeff, resultCoeff, a.coefficients);
+ while (!isEqual(help, coefficients))
+ {
+ resultCoeff = normalForm(help);
+ help = modMultiply(resultCoeff, resultCoeff, a.coefficients);
+ }
+
+ return new PolynomialGF2mSmallM(field, resultCoeff);
+ }
+
+ /**
+ * Compute the square root of this polynomial using a square root matrix.
+ *
+ * @param matrix the matrix for computing square roots in
+ * <tt>(GF(2^m))^t</tt> the polynomial ring defining the
+ * square root matrix
+ * @return <tt>this^(1/2)</tt> modulo the reduction polynomial implicitly
+ * given via the square root matrix
+ */
+ public PolynomialGF2mSmallM modSquareRootMatrix(
+ PolynomialGF2mSmallM[] matrix)
+ {
+
+ int length = matrix.length;
+
+ int[] resultCoeff = new int[length];
+
+ // do matrix multiplication
+ for (int i = 0; i < length; i++)
+ {
+ // compute scalar product of i-th row and j-th column
+ for (int j = 0; j < length; j++)
+ {
+ if (i >= matrix[j].coefficients.length)
+ {
+ continue;
+ }
+ if (j < coefficients.length)
+ {
+ int scalarTerm = field.mult(matrix[j].coefficients[i],
+ coefficients[j]);
+ resultCoeff[i] = field.add(resultCoeff[i], scalarTerm);
+ }
+ }
+ }
+
+ // compute the square root of each entry of the result coefficients
+ for (int i = 0; i < length; i++)
+ {
+ resultCoeff[i] = field.sqRoot(resultCoeff[i]);
+ }
+
+ return new PolynomialGF2mSmallM(field, resultCoeff);
+ }
+
+ /**
+ * Compute the result of the division of this polynomial by another
+ * polynomial modulo a third polynomial.
+ *
+ * @param divisor the divisor
+ * @param modulus the reduction polynomial
+ * @return <tt>this * divisor^(-1) mod modulus</tt>
+ */
+ public PolynomialGF2mSmallM modDiv(PolynomialGF2mSmallM divisor,
+ PolynomialGF2mSmallM modulus)
+ {
+ int[] resultCoeff = modDiv(coefficients, divisor.coefficients,
+ modulus.coefficients);
+ return new PolynomialGF2mSmallM(field, resultCoeff);
+ }
+
+ /**
+ * Compute the result of the division of two polynomials modulo a third
+ * polynomial over the field <tt>GF(2^m)</tt>.
+ *
+ * @param a the first polynomial
+ * @param b the second polynomial
+ * @param g the reduction polynomial
+ * @return <tt>a * b^(-1) mod g</tt>
+ */
+ private int[] modDiv(int[] a, int[] b, int[] g)
+ {
+ int[] r0 = normalForm(g);
+ int[] r1 = mod(b, g);
+ int[] s0 = {0};
+ int[] s1 = mod(a, g);
+ int[] s2;
+ int[][] q;
+ while (computeDegree(r1) != -1)
+ {
+ q = div(r0, r1);
+ r0 = normalForm(r1);
+ r1 = normalForm(q[1]);
+ s2 = add(s0, modMultiply(q[0], s1, g));
+ s0 = normalForm(s1);
+ s1 = normalForm(s2);
+
+ }
+ int hc = headCoefficient(r0);
+ s0 = multWithElement(s0, field.inverse(hc));
+ return s0;
+ }
+
+ /**
+ * Compute the inverse of this polynomial modulo the given polynomial.
+ *
+ * @param a the reduction polynomial
+ * @return <tt>this^(-1) mod a</tt>
+ */
+ public PolynomialGF2mSmallM modInverse(PolynomialGF2mSmallM a)
+ {
+ int[] unit = {1};
+ int[] resultCoeff = modDiv(unit, coefficients, a.coefficients);
+ return new PolynomialGF2mSmallM(field, resultCoeff);
+ }
+
+ /**
+ * Compute a polynomial pair (a,b) from this polynomial and the given
+ * polynomial g with the property b*this = a mod g and deg(a)&lt;=deg(g)/2.
+ *
+ * @param g the reduction polynomial
+ * @return PolynomialGF2mSmallM[] {a,b} with b*this = a mod g and deg(a)&lt;=
+ * deg(g)/2
+ */
+ public PolynomialGF2mSmallM[] modPolynomialToFracton(PolynomialGF2mSmallM g)
+ {
+ int dg = g.degree >> 1;
+ int[] a0 = normalForm(g.coefficients);
+ int[] a1 = mod(coefficients, g.coefficients);
+ int[] b0 = {0};
+ int[] b1 = {1};
+ while (computeDegree(a1) > dg)
+ {
+ int[][] q = div(a0, a1);
+ a0 = a1;
+ a1 = q[1];
+ int[] b2 = add(b0, modMultiply(q[0], b1, g.coefficients));
+ b0 = b1;
+ b1 = b2;
+ }
+
+ return new PolynomialGF2mSmallM[]{
+ new PolynomialGF2mSmallM(field, a1),
+ new PolynomialGF2mSmallM(field, b1)};
+ }
+
+ /**
+ * checks if given object is equal to this polynomial.
+ * <p>
+ * The method returns false whenever the given object is not polynomial over
+ * GF(2^m).
+ *
+ * @param other object
+ * @return true or false
+ */
+ public boolean equals(Object other)
+ {
+
+ if (other == null || !(other instanceof PolynomialGF2mSmallM))
+ {
+ return false;
+ }
+
+ PolynomialGF2mSmallM p = (PolynomialGF2mSmallM)other;
+
+ if ((field.equals(p.field)) && (degree == p.degree)
+ && (isEqual(coefficients, p.coefficients)))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Compare two polynomials given as int arrays.
+ *
+ * @param a the first polynomial
+ * @param b the second polynomial
+ * @return <tt>true</tt> if <tt>a</tt> and <tt>b</tt> represent the
+ * same polynomials, <tt>false</tt> otherwise
+ */
+ private static boolean isEqual(int[] a, int[] b)
+ {
+ int da = computeDegree(a);
+ int db = computeDegree(b);
+ if (da != db)
+ {
+ return false;
+ }
+ for (int i = 0; i <= da; i++)
+ {
+ if (a[i] != b[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @return the hash code of this polynomial
+ */
+ public int hashCode()
+ {
+ int hash = field.hashCode();
+ for (int j = 0; j < coefficients.length; j++)
+ {
+ hash = hash * 31 + coefficients[j];
+ }
+ return hash;
+ }
+
+ /**
+ * Returns a human readable form of the polynomial.
+ *
+ * @return a human readable form of the polynomial.
+ */
+ public String toString()
+ {
+ String str = " Polynomial over " + field.toString() + ": \n";
+
+ for (int i = 0; i < coefficients.length; i++)
+ {
+ str = str + field.elementToStr(coefficients[i]) + "Y^" + i + "+";
+ }
+ str = str + ";";
+
+ return str;
+ }
+
+ /**
+ * Compute the degree of this polynomial. If this is the zero polynomial,
+ * the degree is -1.
+ */
+ private void computeDegree()
+ {
+ for (degree = coefficients.length - 1; degree >= 0
+ && coefficients[degree] == 0; degree--)
+ {
+ ;
+ }
+ }
+
+ /**
+ * Compute the degree of a polynomial.
+ *
+ * @param a the polynomial
+ * @return the degree of the polynomial <tt>a</tt>. If <tt>a</tt> is
+ * the zero polynomial, return -1.
+ */
+ private static int computeDegree(int[] a)
+ {
+ int degree;
+ for (degree = a.length - 1; degree >= 0 && a[degree] == 0; degree--)
+ {
+ ;
+ }
+ return degree;
+ }
+
+ /**
+ * Strip leading zero coefficients from the given polynomial.
+ *
+ * @param a the polynomial
+ * @return the reduced polynomial
+ */
+ private static int[] normalForm(int[] a)
+ {
+ int d = computeDegree(a);
+
+ // if a is the zero polynomial
+ if (d == -1)
+ {
+ // return new zero polynomial
+ return new int[1];
+ }
+
+ // if a already is in normal form
+ if (a.length == d + 1)
+ {
+ // return a clone of a
+ return IntUtils.clone(a);
+ }
+
+ // else, reduce a
+ int[] result = new int[d + 1];
+ System.arraycopy(a, 0, result, 0, d + 1);
+ return result;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialRingGF2.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialRingGF2.java
new file mode 100644
index 00000000..850b5dbf
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialRingGF2.java
@@ -0,0 +1,278 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+/**
+ * This class describes operations with polynomials over finite field GF(2), i e
+ * polynomial ring R = GF(2)[X]. All operations are defined only for polynomials
+ * with degree &lt;=32. For the polynomial representation the map f: R-&gt;Z,
+ * poly(X)-&gt;poly(2) is used, where integers have the binary representation. For
+ * example: X^7+X^3+X+1 -&gt; (00...0010001011)=139 Also for polynomials type
+ * Integer is used.
+ *
+ * @see GF2mField
+ */
+public final class PolynomialRingGF2
+{
+
+ /**
+ * Default constructor (private).
+ */
+ private PolynomialRingGF2()
+ {
+ // empty
+ }
+
+ /**
+ * Return sum of two polyomials
+ *
+ * @param p polynomial
+ * @param q polynomial
+ * @return p+q
+ */
+
+ public static int add(int p, int q)
+ {
+ return p ^ q;
+ }
+
+ /**
+ * Return product of two polynomials
+ *
+ * @param p polynomial
+ * @param q polynomial
+ * @return p*q
+ */
+
+ public static long multiply(int p, int q)
+ {
+ long result = 0;
+ if (q != 0)
+ {
+ long q1 = q & 0x00000000ffffffffL;
+
+ while (p != 0)
+ {
+ byte b = (byte)(p & 0x01);
+ if (b == 1)
+ {
+ result ^= q1;
+ }
+ p >>>= 1;
+ q1 <<= 1;
+
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Compute the product of two polynomials modulo a third polynomial.
+ *
+ * @param a the first polynomial
+ * @param b the second polynomial
+ * @param r the reduction polynomial
+ * @return <tt>a * b mod r</tt>
+ */
+ public static int modMultiply(int a, int b, int r)
+ {
+ int result = 0;
+ int p = remainder(a, r);
+ int q = remainder(b, r);
+ if (q != 0)
+ {
+ int d = 1 << degree(r);
+
+ while (p != 0)
+ {
+ byte pMod2 = (byte)(p & 0x01);
+ if (pMod2 == 1)
+ {
+ result ^= q;
+ }
+ p >>>= 1;
+ q <<= 1;
+ if (q >= d)
+ {
+ q ^= r;
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Return the degree of a polynomial
+ *
+ * @param p polynomial p
+ * @return degree(p)
+ */
+
+ public static int degree(int p)
+ {
+ int result = -1;
+ while (p != 0)
+ {
+ result++;
+ p >>>= 1;
+ }
+ return result;
+ }
+
+ /**
+ * Return the degree of a polynomial
+ *
+ * @param p polynomial p
+ * @return degree(p)
+ */
+
+ public static int degree(long p)
+ {
+ int result = 0;
+ while (p != 0)
+ {
+ result++;
+ p >>>= 1;
+ }
+ return result - 1;
+ }
+
+ /**
+ * Return the remainder of a polynomial division of two polynomials.
+ *
+ * @param p dividend
+ * @param q divisor
+ * @return <tt>p mod q</tt>
+ */
+ public static int remainder(int p, int q)
+ {
+ int result = p;
+
+ if (q == 0)
+ {
+ System.err.println("Error: to be divided by 0");
+ return 0;
+ }
+
+ while (degree(result) >= degree(q))
+ {
+ result ^= q << (degree(result) - degree(q));
+ }
+
+ return result;
+ }
+
+ /**
+ * Return the rest of devision two polynomials
+ *
+ * @param p polinomial
+ * @param q polinomial
+ * @return p mod q
+ */
+
+ public static int rest(long p, int q)
+ {
+ long p1 = p;
+ if (q == 0)
+ {
+ System.err.println("Error: to be divided by 0");
+ return 0;
+ }
+ long q1 = q & 0x00000000ffffffffL;
+ while ((p1 >>> 32) != 0)
+ {
+ p1 ^= q1 << (degree(p1) - degree(q1));
+ }
+
+ int result = (int)(p1 & 0xffffffff);
+ while (degree(result) >= degree(q))
+ {
+ result ^= q << (degree(result) - degree(q));
+ }
+
+ return result;
+ }
+
+ /**
+ * Return the greatest common divisor of two polynomials
+ *
+ * @param p polinomial
+ * @param q polinomial
+ * @return GCD(p, q)
+ */
+
+ public static int gcd(int p, int q)
+ {
+ int a, b, c;
+ a = p;
+ b = q;
+ while (b != 0)
+ {
+ c = remainder(a, b);
+ a = b;
+ b = c;
+
+ }
+ return a;
+ }
+
+ /**
+ * Checking polynomial for irreducibility
+ *
+ * @param p polinomial
+ * @return true if p is irreducible and false otherwise
+ */
+
+ public static boolean isIrreducible(int p)
+ {
+ if (p == 0)
+ {
+ return false;
+ }
+ int d = degree(p) >>> 1;
+ int u = 2;
+ for (int i = 0; i < d; i++)
+ {
+ u = modMultiply(u, u, p);
+ if (gcd(u ^ 2, p) != 1)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Creates irreducible polynomial with degree d
+ *
+ * @param deg polynomial degree
+ * @return irreducible polynomial p
+ */
+ public static int getIrreduciblePolynomial(int deg)
+ {
+ if (deg < 0)
+ {
+ System.err.println("The Degree is negative");
+ return 0;
+ }
+ if (deg > 31)
+ {
+ System.err.println("The Degree is more then 31");
+ return 0;
+ }
+ if (deg == 0)
+ {
+ return 1;
+ }
+ int a = 1 << deg;
+ a++;
+ int b = 1 << (deg + 1);
+ for (int i = a; i < b; i += 2)
+ {
+ if (isIrreducible(i))
+ {
+ return i;
+ }
+ }
+ return 0;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialRingGF2m.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialRingGF2m.java
new file mode 100644
index 00000000..7700fe52
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialRingGF2m.java
@@ -0,0 +1,175 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+/**
+ * This class represents polynomial rings <tt>GF(2^m)[X]/p(X)</tt> for
+ * <tt>m&lt;32</tt>. If <tt>p(X)</tt> is irreducible, the polynomial ring
+ * is in fact an extension field of <tt>GF(2^m)</tt>.
+ */
+public class PolynomialRingGF2m
+{
+
+ /**
+ * the finite field this polynomial ring is defined over
+ */
+ private GF2mField field;
+
+ /**
+ * the reduction polynomial
+ */
+ private PolynomialGF2mSmallM p;
+
+ /**
+ * the squaring matrix for this polynomial ring (given as the array of its
+ * row vectors)
+ */
+ protected PolynomialGF2mSmallM[] sqMatrix;
+
+ /**
+ * the matrix for computing square roots in this polynomial ring (given as
+ * the array of its row vectors). This matrix is computed as the inverse of
+ * the squaring matrix.
+ */
+ protected PolynomialGF2mSmallM[] sqRootMatrix;
+
+ /**
+ * Constructor.
+ *
+ * @param field the finite field
+ * @param p the reduction polynomial
+ */
+ public PolynomialRingGF2m(GF2mField field, PolynomialGF2mSmallM p)
+ {
+ this.field = field;
+ this.p = p;
+ computeSquaringMatrix();
+ computeSquareRootMatrix();
+ }
+
+ /**
+ * @return the squaring matrix for this polynomial ring
+ */
+ public PolynomialGF2mSmallM[] getSquaringMatrix()
+ {
+ return sqMatrix;
+ }
+
+ /**
+ * @return the matrix for computing square roots for this polynomial ring
+ */
+ public PolynomialGF2mSmallM[] getSquareRootMatrix()
+ {
+ return sqRootMatrix;
+ }
+
+ /**
+ * Compute the squaring matrix for this polynomial ring, using the base
+ * field and the reduction polynomial.
+ */
+ private void computeSquaringMatrix()
+ {
+ int numColumns = p.getDegree();
+ sqMatrix = new PolynomialGF2mSmallM[numColumns];
+ for (int i = 0; i < numColumns >> 1; i++)
+ {
+ int[] monomCoeffs = new int[(i << 1) + 1];
+ monomCoeffs[i << 1] = 1;
+ sqMatrix[i] = new PolynomialGF2mSmallM(field, monomCoeffs);
+ }
+ for (int i = numColumns >> 1; i < numColumns; i++)
+ {
+ int[] monomCoeffs = new int[(i << 1) + 1];
+ monomCoeffs[i << 1] = 1;
+ PolynomialGF2mSmallM monomial = new PolynomialGF2mSmallM(field,
+ monomCoeffs);
+ sqMatrix[i] = monomial.mod(p);
+ }
+ }
+
+ /**
+ * Compute the matrix for computing square roots in this polynomial ring by
+ * inverting the squaring matrix.
+ */
+ private void computeSquareRootMatrix()
+ {
+ int numColumns = p.getDegree();
+
+ // clone squaring matrix
+ PolynomialGF2mSmallM[] tmpMatrix = new PolynomialGF2mSmallM[numColumns];
+ for (int i = numColumns - 1; i >= 0; i--)
+ {
+ tmpMatrix[i] = new PolynomialGF2mSmallM(sqMatrix[i]);
+ }
+
+ // initialize square root matrix as unit matrix
+ sqRootMatrix = new PolynomialGF2mSmallM[numColumns];
+ for (int i = numColumns - 1; i >= 0; i--)
+ {
+ sqRootMatrix[i] = new PolynomialGF2mSmallM(field, i);
+ }
+
+ // simultaneously compute Gaussian reduction of squaring matrix and unit
+ // matrix
+ for (int i = 0; i < numColumns; i++)
+ {
+ // if diagonal element is zero
+ if (tmpMatrix[i].getCoefficient(i) == 0)
+ {
+ boolean foundNonZero = false;
+ // find a non-zero element in the same row
+ for (int j = i + 1; j < numColumns; j++)
+ {
+ if (tmpMatrix[j].getCoefficient(i) != 0)
+ {
+ // found it, swap columns ...
+ foundNonZero = true;
+ swapColumns(tmpMatrix, i, j);
+ swapColumns(sqRootMatrix, i, j);
+ // ... and quit searching
+ j = numColumns;
+ continue;
+ }
+ }
+ // if no non-zero element was found
+ if (!foundNonZero)
+ {
+ // the matrix is not invertible
+ throw new ArithmeticException(
+ "Squaring matrix is not invertible.");
+ }
+ }
+
+ // normalize i-th column
+ int coef = tmpMatrix[i].getCoefficient(i);
+ int invCoef = field.inverse(coef);
+ tmpMatrix[i].multThisWithElement(invCoef);
+ sqRootMatrix[i].multThisWithElement(invCoef);
+
+ // normalize all other columns
+ for (int j = 0; j < numColumns; j++)
+ {
+ if (j != i)
+ {
+ coef = tmpMatrix[j].getCoefficient(i);
+ if (coef != 0)
+ {
+ PolynomialGF2mSmallM tmpSqColumn = tmpMatrix[i]
+ .multWithElement(coef);
+ PolynomialGF2mSmallM tmpInvColumn = sqRootMatrix[i]
+ .multWithElement(coef);
+ tmpMatrix[j].addToThis(tmpSqColumn);
+ sqRootMatrix[j].addToThis(tmpInvColumn);
+ }
+ }
+ }
+ }
+ }
+
+ private static void swapColumns(PolynomialGF2mSmallM[] matrix, int first,
+ int second)
+ {
+ PolynomialGF2mSmallM tmp = matrix[first];
+ matrix[first] = matrix[second];
+ matrix[second] = tmp;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/RandUtils.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/RandUtils.java
new file mode 100644
index 00000000..34862d7c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/RandUtils.java
@@ -0,0 +1,25 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+import java.security.SecureRandom;
+
+public class RandUtils
+{
+ static int nextInt(SecureRandom rand, int n)
+ {
+
+ if ((n & -n) == n) // i.e., n is a power of 2
+ {
+ return (int)((n * (long)(rand.nextInt() >>> 1)) >> 31);
+ }
+
+ int bits, value;
+ do
+ {
+ bits = rand.nextInt() >>> 1;
+ value = bits % n;
+ }
+ while (bits - value + (n - 1) < 0);
+
+ return value;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/Vector.java b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/Vector.java
new file mode 100644
index 00000000..7f33d735
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/Vector.java
@@ -0,0 +1,69 @@
+package org.spongycastle.pqc.math.linearalgebra;
+
+/**
+ * This abstract class defines vectors. It holds the length of vector.
+ */
+public abstract class Vector
+{
+
+ /**
+ * the length of this vector
+ */
+ protected int length;
+
+ /**
+ * @return the length of this vector
+ */
+ public final int getLength()
+ {
+ return length;
+ }
+
+ /**
+ * @return this vector as byte array
+ */
+ public abstract byte[] getEncoded();
+
+ /**
+ * Return whether this is the zero vector (i.e., all elements are zero).
+ *
+ * @return <tt>true</tt> if this is the zero vector, <tt>false</tt>
+ * otherwise
+ */
+ public abstract boolean isZero();
+
+ /**
+ * Add another vector to this vector.
+ *
+ * @param addend the other vector
+ * @return <tt>this + addend</tt>
+ */
+ public abstract Vector add(Vector addend);
+
+ /**
+ * Multiply this vector with a permutation.
+ *
+ * @param p the permutation
+ * @return <tt>this*p = p*this</tt>
+ */
+ public abstract Vector multiply(Permutation p);
+
+ /**
+ * Check if the given object is equal to this vector.
+ *
+ * @param other vector
+ * @return the result of the comparison
+ */
+ public abstract boolean equals(Object other);
+
+ /**
+ * @return the hash code of this vector
+ */
+ public abstract int hashCode();
+
+ /**
+ * @return a human readable form of this vector
+ */
+ public abstract String toString();
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/ntru/euclid/BigIntEuclidean.java b/core/src/main/java/org/spongycastle/pqc/math/ntru/euclid/BigIntEuclidean.java
new file mode 100644
index 00000000..e48d2a0c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/ntru/euclid/BigIntEuclidean.java
@@ -0,0 +1,54 @@
+package org.spongycastle.pqc.math.ntru.euclid;
+
+import java.math.BigInteger;
+
+/**
+ * Extended Euclidean Algorithm in <code>BigInteger</code>s
+ */
+public class BigIntEuclidean
+{
+ public BigInteger x, y, gcd;
+
+ private BigIntEuclidean()
+ {
+ }
+
+ /**
+ * Runs the EEA on two <code>BigInteger</code>s<br>
+ * Implemented from pseudocode on <a href="http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm">Wikipedia</a>.
+ *
+ * @param a
+ * @param b
+ * @return a <code>BigIntEuclidean</code> object that contains the result in the variables <code>x</code>, <code>y</code>, and <code>gcd</code>
+ */
+ public static BigIntEuclidean calculate(BigInteger a, BigInteger b)
+ {
+ BigInteger x = BigInteger.ZERO;
+ BigInteger lastx = BigInteger.ONE;
+ BigInteger y = BigInteger.ONE;
+ BigInteger lasty = BigInteger.ZERO;
+ while (!b.equals(BigInteger.ZERO))
+ {
+ BigInteger[] quotientAndRemainder = a.divideAndRemainder(b);
+ BigInteger quotient = quotientAndRemainder[0];
+
+ BigInteger temp = a;
+ a = b;
+ b = quotientAndRemainder[1];
+
+ temp = x;
+ x = lastx.subtract(quotient.multiply(x));
+ lastx = temp;
+
+ temp = y;
+ y = lasty.subtract(quotient.multiply(y));
+ lasty = temp;
+ }
+
+ BigIntEuclidean result = new BigIntEuclidean();
+ result.x = lastx;
+ result.y = lasty;
+ result.gcd = a;
+ return result;
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/pqc/math/ntru/euclid/IntEuclidean.java b/core/src/main/java/org/spongycastle/pqc/math/ntru/euclid/IntEuclidean.java
new file mode 100644
index 00000000..0791b01e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/ntru/euclid/IntEuclidean.java
@@ -0,0 +1,51 @@
+package org.spongycastle.pqc.math.ntru.euclid;
+
+/**
+ * Extended Euclidean Algorithm in <code>int</code>s
+ */
+public class IntEuclidean
+{
+ public int x, y, gcd;
+
+ private IntEuclidean()
+ {
+ }
+
+ /**
+ * Runs the EEA on two <code>int</code>s<br>
+ * Implemented from pseudocode on <a href="http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm">Wikipedia</a>.
+ *
+ * @param a
+ * @param b
+ * @return a <code>IntEuclidean</code> object that contains the result in the variables <code>x</code>, <code>y</code>, and <code>gcd</code>
+ */
+ public static IntEuclidean calculate(int a, int b)
+ {
+ int x = 0;
+ int lastx = 1;
+ int y = 1;
+ int lasty = 0;
+ while (b != 0)
+ {
+ int quotient = a / b;
+
+ int temp = a;
+ a = b;
+ b = temp % b;
+
+ temp = x;
+ x = lastx - quotient * x;
+ lastx = temp;
+
+ temp = y;
+ y = lasty - quotient * y;
+ lasty = temp;
+ }
+
+ IntEuclidean result = new IntEuclidean();
+ result.x = lastx;
+ result.y = lasty;
+ result.gcd = a;
+ return result;
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/BigDecimalPolynomial.java b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/BigDecimalPolynomial.java
new file mode 100644
index 00000000..a496060c
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/BigDecimalPolynomial.java
@@ -0,0 +1,258 @@
+package org.spongycastle.pqc.math.ntru.polynomial;
+
+import java.math.BigDecimal;
+
+/**
+ * A polynomial with {@link BigDecimal} coefficients.
+ * Some methods (like <code>add</code>) change the polynomial, others (like <code>mult</code>) do
+ * not but return the result as a new polynomial.
+ */
+public class BigDecimalPolynomial
+{
+ private static final BigDecimal ZERO = new BigDecimal("0");
+ private static final BigDecimal ONE_HALF = new BigDecimal("0.5");
+
+ BigDecimal[] coeffs;
+
+ /**
+ * Constructs a new polynomial with <code>N</code> coefficients initialized to 0.
+ *
+ * @param N the number of coefficients
+ */
+ BigDecimalPolynomial(int N)
+ {
+ coeffs = new BigDecimal[N];
+ for (int i = 0; i < N; i++)
+ {
+ coeffs[i] = ZERO;
+ }
+ }
+
+ /**
+ * Constructs a new polynomial with a given set of coefficients.
+ *
+ * @param coeffs the coefficients
+ */
+ BigDecimalPolynomial(BigDecimal[] coeffs)
+ {
+ this.coeffs = coeffs;
+ }
+
+ /**
+ * Constructs a <code>BigDecimalPolynomial</code> from a <code>BigIntPolynomial</code>. The two polynomials are independent of each other.
+ *
+ * @param p the original polynomial
+ */
+ public BigDecimalPolynomial(BigIntPolynomial p)
+ {
+ int N = p.coeffs.length;
+ coeffs = new BigDecimal[N];
+ for (int i = 0; i < N; i++)
+ {
+ coeffs[i] = new BigDecimal(p.coeffs[i]);
+ }
+ }
+
+ /**
+ * Divides all coefficients by 2.
+ */
+ public void halve()
+ {
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ coeffs[i] = coeffs[i].multiply(ONE_HALF);
+ }
+ }
+
+ /**
+ * Multiplies the polynomial by another. Does not change this polynomial
+ * but returns the result as a new polynomial.
+ *
+ * @param poly2 the polynomial to multiply by
+ * @return a new polynomial
+ */
+ public BigDecimalPolynomial mult(BigIntPolynomial poly2)
+ {
+ return mult(new BigDecimalPolynomial(poly2));
+ }
+
+ /**
+ * Multiplies the polynomial by another, taking the indices mod N. Does not
+ * change this polynomial but returns the result as a new polynomial.
+ *
+ * @param poly2 the polynomial to multiply by
+ * @return a new polynomial
+ */
+ public BigDecimalPolynomial mult(BigDecimalPolynomial poly2)
+ {
+ int N = coeffs.length;
+ if (poly2.coeffs.length != N)
+ {
+ throw new IllegalArgumentException("Number of coefficients must be the same");
+ }
+
+ BigDecimalPolynomial c = multRecursive(poly2);
+
+ if (c.coeffs.length > N)
+ {
+ for (int k = N; k < c.coeffs.length; k++)
+ {
+ c.coeffs[k - N] = c.coeffs[k - N].add(c.coeffs[k]);
+ }
+ c.coeffs = copyOf(c.coeffs, N);
+ }
+ return c;
+ }
+
+ /**
+ * Karazuba multiplication
+ */
+ private BigDecimalPolynomial multRecursive(BigDecimalPolynomial poly2)
+ {
+ BigDecimal[] a = coeffs;
+ BigDecimal[] b = poly2.coeffs;
+
+ int n = poly2.coeffs.length;
+ if (n <= 1)
+ {
+ BigDecimal[] c = coeffs.clone();
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ c[i] = c[i].multiply(poly2.coeffs[0]);
+ }
+ return new BigDecimalPolynomial(c);
+ }
+ else
+ {
+ int n1 = n / 2;
+
+ BigDecimalPolynomial a1 = new BigDecimalPolynomial(copyOf(a, n1));
+ BigDecimalPolynomial a2 = new BigDecimalPolynomial(copyOfRange(a, n1, n));
+ BigDecimalPolynomial b1 = new BigDecimalPolynomial(copyOf(b, n1));
+ BigDecimalPolynomial b2 = new BigDecimalPolynomial(copyOfRange(b, n1, n));
+
+ BigDecimalPolynomial A = (BigDecimalPolynomial)a1.clone();
+ A.add(a2);
+ BigDecimalPolynomial B = (BigDecimalPolynomial)b1.clone();
+ B.add(b2);
+
+ BigDecimalPolynomial c1 = a1.multRecursive(b1);
+ BigDecimalPolynomial c2 = a2.multRecursive(b2);
+ BigDecimalPolynomial c3 = A.multRecursive(B);
+ c3.sub(c1);
+ c3.sub(c2);
+
+ BigDecimalPolynomial c = new BigDecimalPolynomial(2 * n - 1);
+ for (int i = 0; i < c1.coeffs.length; i++)
+ {
+ c.coeffs[i] = c1.coeffs[i];
+ }
+ for (int i = 0; i < c3.coeffs.length; i++)
+ {
+ c.coeffs[n1 + i] = c.coeffs[n1 + i].add(c3.coeffs[i]);
+ }
+ for (int i = 0; i < c2.coeffs.length; i++)
+ {
+ c.coeffs[2 * n1 + i] = c.coeffs[2 * n1 + i].add(c2.coeffs[i]);
+ }
+ return c;
+ }
+ }
+
+ /**
+ * Adds another polynomial which can have a different number of coefficients.
+ *
+ * @param b another polynomial
+ */
+ public void add(BigDecimalPolynomial b)
+ {
+ if (b.coeffs.length > coeffs.length)
+ {
+ int N = coeffs.length;
+ coeffs = copyOf(coeffs, b.coeffs.length);
+ for (int i = N; i < coeffs.length; i++)
+ {
+ coeffs[i] = ZERO;
+ }
+ }
+ for (int i = 0; i < b.coeffs.length; i++)
+ {
+ coeffs[i] = coeffs[i].add(b.coeffs[i]);
+ }
+ }
+
+ /**
+ * Subtracts another polynomial which can have a different number of coefficients.
+ *
+ * @param b
+ */
+ void sub(BigDecimalPolynomial b)
+ {
+ if (b.coeffs.length > coeffs.length)
+ {
+ int N = coeffs.length;
+ coeffs = copyOf(coeffs, b.coeffs.length);
+ for (int i = N; i < coeffs.length; i++)
+ {
+ coeffs[i] = ZERO;
+ }
+ }
+ for (int i = 0; i < b.coeffs.length; i++)
+ {
+ coeffs[i] = coeffs[i].subtract(b.coeffs[i]);
+ }
+ }
+
+ /**
+ * Rounds all coefficients to the nearest integer.
+ *
+ * @return a new polynomial with <code>BigInteger</code> coefficients
+ */
+ public BigIntPolynomial round()
+ {
+ int N = coeffs.length;
+ BigIntPolynomial p = new BigIntPolynomial(N);
+ for (int i = 0; i < N; i++)
+ {
+ p.coeffs[i] = coeffs[i].setScale(0, BigDecimal.ROUND_HALF_EVEN).toBigInteger();
+ }
+ return p;
+ }
+
+ /**
+ * Makes a copy of the polynomial that is independent of the original.
+ */
+ public Object clone()
+ {
+ return new BigDecimalPolynomial(coeffs.clone());
+ }
+
+ private BigDecimal[] copyOf(BigDecimal[] a, int length)
+ {
+ BigDecimal[] tmp = new BigDecimal[length];
+
+ System.arraycopy(a, 0, tmp, 0, a.length < length ? a.length : length);
+
+ return tmp;
+ }
+
+ private BigDecimal[] copyOfRange(BigDecimal[] a, int from, int to)
+ {
+ int newLength = to - from;
+ BigDecimal[] tmp = new BigDecimal[to - from];
+
+ System.arraycopy(a, from, tmp, 0, (a.length - from) < newLength ? (a.length - from) : newLength);
+
+ return tmp;
+ }
+
+ public BigDecimal[] getCoeffs()
+ {
+ BigDecimal[] tmp = new BigDecimal[coeffs.length];
+
+ System.arraycopy(coeffs, 0, tmp, 0, coeffs.length);
+
+ return tmp;
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/BigIntPolynomial.java b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/BigIntPolynomial.java
new file mode 100644
index 00000000..2869fec8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/BigIntPolynomial.java
@@ -0,0 +1,394 @@
+package org.spongycastle.pqc.math.ntru.polynomial;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.spongycastle.util.Arrays;
+
+/**
+ * A polynomial with {@link BigInteger} coefficients.<br>
+ * Some methods (like <code>add</code>) change the polynomial, others (like <code>mult</code>) do
+ * not but return the result as a new polynomial.
+ */
+public class BigIntPolynomial
+{
+ private final static double LOG_10_2 = Math.log10(2);
+
+ BigInteger[] coeffs;
+
+ /**
+ * Constructs a new polynomial with <code>N</code> coefficients initialized to 0.
+ *
+ * @param N the number of coefficients
+ */
+ BigIntPolynomial(int N)
+ {
+ coeffs = new BigInteger[N];
+ for (int i = 0; i < N; i++)
+ {
+ coeffs[i] = Constants.BIGINT_ZERO;
+ }
+ }
+
+ /**
+ * Constructs a new polynomial with a given set of coefficients.
+ *
+ * @param coeffs the coefficients
+ */
+ BigIntPolynomial(BigInteger[] coeffs)
+ {
+ this.coeffs = coeffs;
+ }
+
+ /**
+ * Constructs a <code>BigIntPolynomial</code> from a <code>IntegerPolynomial</code>. The two polynomials are
+ * independent of each other.
+ *
+ * @param p the original polynomial
+ */
+ public BigIntPolynomial(IntegerPolynomial p)
+ {
+ coeffs = new BigInteger[p.coeffs.length];
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ coeffs[i] = BigInteger.valueOf(p.coeffs[i]);
+ }
+ }
+
+ /**
+ * Generates a random polynomial with <code>numOnes</code> coefficients equal to 1,
+ * <code>numNegOnes</code> coefficients equal to -1, and the rest equal to 0.
+ *
+ * @param N number of coefficients
+ * @param numOnes number of 1's
+ * @param numNegOnes number of -1's
+ * @return
+ */
+ static BigIntPolynomial generateRandomSmall(int N, int numOnes, int numNegOnes)
+ {
+ List coeffs = new ArrayList();
+ for (int i = 0; i < numOnes; i++)
+ {
+ coeffs.add(Constants.BIGINT_ONE);
+ }
+ for (int i = 0; i < numNegOnes; i++)
+ {
+ coeffs.add(BigInteger.valueOf(-1));
+ }
+ while (coeffs.size() < N)
+ {
+ coeffs.add(Constants.BIGINT_ZERO);
+ }
+ Collections.shuffle(coeffs, new SecureRandom());
+
+ BigIntPolynomial poly = new BigIntPolynomial(N);
+ for (int i = 0; i < coeffs.size(); i++)
+ {
+ poly.coeffs[i] = (BigInteger)coeffs.get(i);
+ }
+ return poly;
+ }
+
+ /**
+ * Multiplies the polynomial by another, taking the indices mod N. Does not
+ * change this polynomial but returns the result as a new polynomial.<br>
+ * Both polynomials must have the same number of coefficients.
+ *
+ * @param poly2 the polynomial to multiply by
+ * @return a new polynomial
+ */
+ public BigIntPolynomial mult(BigIntPolynomial poly2)
+ {
+ int N = coeffs.length;
+ if (poly2.coeffs.length != N)
+ {
+ throw new IllegalArgumentException("Number of coefficients must be the same");
+ }
+
+ BigIntPolynomial c = multRecursive(poly2);
+
+ if (c.coeffs.length > N)
+ {
+ for (int k = N; k < c.coeffs.length; k++)
+ {
+ c.coeffs[k - N] = c.coeffs[k - N].add(c.coeffs[k]);
+ }
+ c.coeffs = Arrays.copyOf(c.coeffs, N);
+ }
+ return c;
+ }
+
+ /**
+ * Karazuba multiplication
+ */
+ private BigIntPolynomial multRecursive(BigIntPolynomial poly2)
+ {
+ BigInteger[] a = coeffs;
+ BigInteger[] b = poly2.coeffs;
+
+ int n = poly2.coeffs.length;
+ if (n <= 1)
+ {
+ BigInteger[] c = Arrays.clone(coeffs);
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ c[i] = c[i].multiply(poly2.coeffs[0]);
+ }
+ return new BigIntPolynomial(c);
+ }
+ else
+ {
+ int n1 = n / 2;
+
+ BigIntPolynomial a1 = new BigIntPolynomial(Arrays.copyOf(a, n1));
+ BigIntPolynomial a2 = new BigIntPolynomial(Arrays.copyOfRange(a, n1, n));
+ BigIntPolynomial b1 = new BigIntPolynomial(Arrays.copyOf(b, n1));
+ BigIntPolynomial b2 = new BigIntPolynomial(Arrays.copyOfRange(b, n1, n));
+
+ BigIntPolynomial A = (BigIntPolynomial)a1.clone();
+ A.add(a2);
+ BigIntPolynomial B = (BigIntPolynomial)b1.clone();
+ B.add(b2);
+
+ BigIntPolynomial c1 = a1.multRecursive(b1);
+ BigIntPolynomial c2 = a2.multRecursive(b2);
+ BigIntPolynomial c3 = A.multRecursive(B);
+ c3.sub(c1);
+ c3.sub(c2);
+
+ BigIntPolynomial c = new BigIntPolynomial(2 * n - 1);
+ for (int i = 0; i < c1.coeffs.length; i++)
+ {
+ c.coeffs[i] = c1.coeffs[i];
+ }
+ for (int i = 0; i < c3.coeffs.length; i++)
+ {
+ c.coeffs[n1 + i] = c.coeffs[n1 + i].add(c3.coeffs[i]);
+ }
+ for (int i = 0; i < c2.coeffs.length; i++)
+ {
+ c.coeffs[2 * n1 + i] = c.coeffs[2 * n1 + i].add(c2.coeffs[i]);
+ }
+ return c;
+ }
+ }
+
+ /**
+ * Adds another polynomial which can have a different number of coefficients,
+ * and takes the coefficient values mod <code>modulus</code>.
+ *
+ * @param b another polynomial
+ */
+ void add(BigIntPolynomial b, BigInteger modulus)
+ {
+ add(b);
+ mod(modulus);
+ }
+
+ /**
+ * Adds another polynomial which can have a different number of coefficients.
+ *
+ * @param b another polynomial
+ */
+ public void add(BigIntPolynomial b)
+ {
+ if (b.coeffs.length > coeffs.length)
+ {
+ int N = coeffs.length;
+ coeffs = Arrays.copyOf(coeffs, b.coeffs.length);
+ for (int i = N; i < coeffs.length; i++)
+ {
+ coeffs[i] = Constants.BIGINT_ZERO;
+ }
+ }
+ for (int i = 0; i < b.coeffs.length; i++)
+ {
+ coeffs[i] = coeffs[i].add(b.coeffs[i]);
+ }
+ }
+
+ /**
+ * Subtracts another polynomial which can have a different number of coefficients.
+ *
+ * @param b another polynomial
+ */
+ public void sub(BigIntPolynomial b)
+ {
+ if (b.coeffs.length > coeffs.length)
+ {
+ int N = coeffs.length;
+ coeffs = Arrays.copyOf(coeffs, b.coeffs.length);
+ for (int i = N; i < coeffs.length; i++)
+ {
+ coeffs[i] = Constants.BIGINT_ZERO;
+ }
+ }
+ for (int i = 0; i < b.coeffs.length; i++)
+ {
+ coeffs[i] = coeffs[i].subtract(b.coeffs[i]);
+ }
+ }
+
+ /**
+ * Multiplies each coefficient by a <code>BigInteger</code>. Does not return a new polynomial but modifies this polynomial.
+ *
+ * @param factor
+ */
+ public void mult(BigInteger factor)
+ {
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ coeffs[i] = coeffs[i].multiply(factor);
+ }
+ }
+
+ /**
+ * Multiplies each coefficient by a <code>int</code>. Does not return a new polynomial but modifies this polynomial.
+ *
+ * @param factor
+ */
+ void mult(int factor)
+ {
+ mult(BigInteger.valueOf(factor));
+ }
+
+ /**
+ * Divides each coefficient by a <code>BigInteger</code> and rounds the result to the nearest whole number.<br>
+ * Does not return a new polynomial but modifies this polynomial.
+ *
+ * @param divisor the number to divide by
+ */
+ public void div(BigInteger divisor)
+ {
+ BigInteger d = divisor.add(Constants.BIGINT_ONE).divide(BigInteger.valueOf(2));
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ coeffs[i] = coeffs[i].compareTo(Constants.BIGINT_ZERO) > 0 ? coeffs[i].add(d) : coeffs[i].add(d.negate());
+ coeffs[i] = coeffs[i].divide(divisor);
+ }
+ }
+
+ /**
+ * Divides each coefficient by a <code>BigDecimal</code> and rounds the result to <code>decimalPlaces</code> places.
+ *
+ * @param divisor the number to divide by
+ * @param decimalPlaces the number of fractional digits to round the result to
+ * @return a new <code>BigDecimalPolynomial</code>
+ */
+ public BigDecimalPolynomial div(BigDecimal divisor, int decimalPlaces)
+ {
+ BigInteger max = maxCoeffAbs();
+ int coeffLength = (int)(max.bitLength() * LOG_10_2) + 1;
+ // factor = 1/divisor
+ BigDecimal factor = Constants.BIGDEC_ONE.divide(divisor, coeffLength + decimalPlaces + 1, BigDecimal.ROUND_HALF_EVEN);
+
+ // multiply each coefficient by factor
+ BigDecimalPolynomial p = new BigDecimalPolynomial(coeffs.length);
+ for (int i = 0; i < coeffs.length; i++)
+ // multiply, then truncate after decimalPlaces so subsequent operations aren't slowed down
+ {
+ p.coeffs[i] = new BigDecimal(coeffs[i]).multiply(factor).setScale(decimalPlaces, BigDecimal.ROUND_HALF_EVEN);
+ }
+
+ return p;
+ }
+
+ /**
+ * Returns the base10 length of the largest coefficient.
+ *
+ * @return length of the longest coefficient
+ */
+ public int getMaxCoeffLength()
+ {
+ return (int)(maxCoeffAbs().bitLength() * LOG_10_2) + 1;
+ }
+
+ private BigInteger maxCoeffAbs()
+ {
+ BigInteger max = coeffs[0].abs();
+ for (int i = 1; i < coeffs.length; i++)
+ {
+ BigInteger coeff = coeffs[i].abs();
+ if (coeff.compareTo(max) > 0)
+ {
+ max = coeff;
+ }
+ }
+ return max;
+ }
+
+ /**
+ * Takes each coefficient modulo a number.
+ *
+ * @param modulus
+ */
+ public void mod(BigInteger modulus)
+ {
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ coeffs[i] = coeffs[i].mod(modulus);
+ }
+ }
+
+ /**
+ * Returns the sum of all coefficients, i.e. evaluates the polynomial at 0.
+ *
+ * @return the sum of all coefficients
+ */
+ BigInteger sumCoeffs()
+ {
+ BigInteger sum = Constants.BIGINT_ZERO;
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ sum = sum.add(coeffs[i]);
+ }
+ return sum;
+ }
+
+ /**
+ * Makes a copy of the polynomial that is independent of the original.
+ */
+ public Object clone()
+ {
+ return new BigIntPolynomial(coeffs.clone());
+ }
+
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode(coeffs);
+ return result;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+ BigIntPolynomial other = (BigIntPolynomial)obj;
+ if (!Arrays.areEqual(coeffs, other.coeffs))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public BigInteger[] getCoeffs()
+ {
+ return Arrays.clone(coeffs);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/Constants.java b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/Constants.java
new file mode 100644
index 00000000..f29ce066
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/Constants.java
@@ -0,0 +1,12 @@
+package org.spongycastle.pqc.math.ntru.polynomial;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+public class Constants
+{
+ static final BigInteger BIGINT_ZERO = BigInteger.valueOf(0);
+ static final BigInteger BIGINT_ONE = BigInteger.valueOf(1);
+
+ static final BigDecimal BIGDEC_ONE = BigDecimal.valueOf(1);
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/DenseTernaryPolynomial.java b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/DenseTernaryPolynomial.java
new file mode 100644
index 00000000..007e7249
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/DenseTernaryPolynomial.java
@@ -0,0 +1,142 @@
+package org.spongycastle.pqc.math.ntru.polynomial;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.pqc.math.ntru.util.Util;
+import org.spongycastle.util.Arrays;
+
+/**
+ * A <code>TernaryPolynomial</code> with a "high" number of nonzero coefficients.
+ */
+public class DenseTernaryPolynomial
+ extends IntegerPolynomial
+ implements TernaryPolynomial
+{
+
+ /**
+ * Constructs a new <code>DenseTernaryPolynomial</code> with <code>N</code> coefficients.
+ *
+ * @param N the number of coefficients
+ */
+ DenseTernaryPolynomial(int N)
+ {
+ super(N);
+ checkTernarity();
+ }
+
+ /**
+ * Constructs a <code>DenseTernaryPolynomial</code> from a <code>IntegerPolynomial</code>. The two polynomials are
+ * independent of each other.
+ *
+ * @param intPoly the original polynomial
+ */
+ public DenseTernaryPolynomial(IntegerPolynomial intPoly)
+ {
+ this(intPoly.coeffs);
+ }
+
+ /**
+ * Constructs a new <code>DenseTernaryPolynomial</code> with a given set of coefficients.
+ *
+ * @param coeffs the coefficients
+ */
+ public DenseTernaryPolynomial(int[] coeffs)
+ {
+ super(coeffs);
+ checkTernarity();
+ }
+
+ private void checkTernarity()
+ {
+ for (int i = 0; i != coeffs.length; i++)
+ {
+ int c = coeffs[i];
+ if (c < -1 || c > 1)
+ {
+ throw new IllegalStateException("Illegal value: " + c + ", must be one of {-1, 0, 1}");
+ }
+ }
+ }
+
+ /**
+ * Generates a random polynomial with <code>numOnes</code> coefficients equal to 1,
+ * <code>numNegOnes</code> coefficients equal to -1, and the rest equal to 0.
+ *
+ * @param N number of coefficients
+ * @param numOnes number of 1's
+ * @param numNegOnes number of -1's
+ */
+ public static DenseTernaryPolynomial generateRandom(int N, int numOnes, int numNegOnes, SecureRandom random)
+ {
+ int[] coeffs = Util.generateRandomTernary(N, numOnes, numNegOnes, random);
+ return new DenseTernaryPolynomial(coeffs);
+ }
+
+ /**
+ * Generates a polynomial with coefficients randomly selected from <code>{-1, 0, 1}</code>.
+ *
+ * @param N number of coefficients
+ */
+ public static DenseTernaryPolynomial generateRandom(int N, SecureRandom random)
+ {
+ DenseTernaryPolynomial poly = new DenseTernaryPolynomial(N);
+ for (int i = 0; i < N; i++)
+ {
+ poly.coeffs[i] = random.nextInt(3) - 1;
+ }
+ return poly;
+ }
+
+ public IntegerPolynomial mult(IntegerPolynomial poly2, int modulus)
+ {
+ // even on 32-bit systems, LongPolynomial5 multiplies faster than IntegerPolynomial
+ if (modulus == 2048)
+ {
+ IntegerPolynomial poly2Pos = (IntegerPolynomial)poly2.clone();
+ poly2Pos.modPositive(2048);
+ LongPolynomial5 poly5 = new LongPolynomial5(poly2Pos);
+ return poly5.mult(this).toIntegerPolynomial();
+ }
+ else
+ {
+ return super.mult(poly2, modulus);
+ }
+ }
+
+ public int[] getOnes()
+ {
+ int N = coeffs.length;
+ int[] ones = new int[N];
+ int onesIdx = 0;
+ for (int i = 0; i < N; i++)
+ {
+ int c = coeffs[i];
+ if (c == 1)
+ {
+ ones[onesIdx++] = i;
+ }
+ }
+ return Arrays.copyOf(ones, onesIdx);
+ }
+
+ public int[] getNegOnes()
+ {
+ int N = coeffs.length;
+ int[] negOnes = new int[N];
+ int negOnesIdx = 0;
+ for (int i = 0; i < N; i++)
+ {
+ int c = coeffs[i];
+ if (c == -1)
+ {
+ negOnes[negOnesIdx++] = i;
+ }
+ }
+ return Arrays.copyOf(negOnes, negOnesIdx);
+ }
+
+ public int size()
+ {
+ return coeffs.length;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/IntegerPolynomial.java b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/IntegerPolynomial.java
new file mode 100644
index 00000000..41e921bf
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/IntegerPolynomial.java
@@ -0,0 +1,1358 @@
+package org.spongycastle.pqc.math.ntru.polynomial;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import org.spongycastle.pqc.math.ntru.euclid.BigIntEuclidean;
+import org.spongycastle.pqc.math.ntru.util.ArrayEncoder;
+import org.spongycastle.pqc.math.ntru.util.Util;
+import org.spongycastle.util.Arrays;
+
+/**
+ * A polynomial with <code>int</code> coefficients.<br>
+ * Some methods (like <code>add</code>) change the polynomial, others (like <code>mult</code>) do
+ * not but return the result as a new polynomial.
+ */
+public class IntegerPolynomial
+ implements Polynomial
+{
+ private static final int NUM_EQUAL_RESULTANTS = 3;
+ /**
+ * Prime numbers &gt; 4500 for resultant computation. Starting them below ~4400 causes incorrect results occasionally.
+ * Fortunately, 4500 is about the optimum number for performance.<br/>
+ * This array contains enough prime numbers so primes never have to be computed on-line for any standard {@link org.spongycastle.pqc.crypto.ntru.NTRUSigningParameters}.
+ */
+ private static final int[] PRIMES = new int[]{
+ 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583,
+ 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657,
+ 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751,
+ 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831,
+ 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937,
+ 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003,
+ 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087,
+ 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179,
+ 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279,
+ 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387,
+ 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443,
+ 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521,
+ 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639,
+ 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693,
+ 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791,
+ 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857,
+ 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939,
+ 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053,
+ 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133,
+ 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221,
+ 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301,
+ 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367,
+ 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473,
+ 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571,
+ 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673,
+ 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761,
+ 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833,
+ 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917,
+ 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997,
+ 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103,
+ 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207,
+ 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297,
+ 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411,
+ 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499,
+ 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561,
+ 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643,
+ 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723,
+ 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829,
+ 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919,
+ 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017,
+ 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111,
+ 8117, 8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209, 8219,
+ 8221, 8231, 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291,
+ 8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, 8377, 8387,
+ 8389, 8419, 8423, 8429, 8431, 8443, 8447, 8461, 8467, 8501,
+ 8513, 8521, 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597,
+ 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677,
+ 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741,
+ 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831,
+ 8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929,
+ 8933, 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011,
+ 9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109,
+ 9127, 9133, 9137, 9151, 9157, 9161, 9173, 9181, 9187, 9199,
+ 9203, 9209, 9221, 9227, 9239, 9241, 9257, 9277, 9281, 9283,
+ 9293, 9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377,
+ 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439,
+ 9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521, 9533,
+ 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629, 9631,
+ 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733,
+ 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811,
+ 9817, 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887,
+ 9901, 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973};
+ private static final List BIGINT_PRIMES;
+
+ static
+ {
+ BIGINT_PRIMES = new ArrayList();
+ for (int i = 0; i != PRIMES.length; i++)
+ {
+ BIGINT_PRIMES.add(BigInteger.valueOf(PRIMES[i]));
+ }
+ }
+
+ public int[] coeffs;
+
+ /**
+ * Constructs a new polynomial with <code>N</code> coefficients initialized to 0.
+ *
+ * @param N the number of coefficients
+ */
+ public IntegerPolynomial(int N)
+ {
+ coeffs = new int[N];
+ }
+
+ /**
+ * Constructs a new polynomial with a given set of coefficients.
+ *
+ * @param coeffs the coefficients
+ */
+ public IntegerPolynomial(int[] coeffs)
+ {
+ this.coeffs = coeffs;
+ }
+
+ /**
+ * Constructs a <code>IntegerPolynomial</code> from a <code>BigIntPolynomial</code>. The two polynomials are independent of each other.
+ *
+ * @param p the original polynomial
+ */
+ public IntegerPolynomial(BigIntPolynomial p)
+ {
+ coeffs = new int[p.coeffs.length];
+ for (int i = 0; i < p.coeffs.length; i++)
+ {
+ coeffs[i] = p.coeffs[i].intValue();
+ }
+ }
+
+ /**
+ * Decodes a byte array to a polynomial with <code>N</code> ternary coefficients<br>
+ * Ignores any excess bytes.
+ *
+ * @param data an encoded ternary polynomial
+ * @param N number of coefficients
+ * @return the decoded polynomial
+ */
+ public static IntegerPolynomial fromBinary3Sves(byte[] data, int N)
+ {
+ return new IntegerPolynomial(ArrayEncoder.decodeMod3Sves(data, N));
+ }
+
+ /**
+ * Converts a byte array produced by {@link #toBinary3Tight()} to a polynomial.
+ *
+ * @param b a byte array
+ * @param N number of coefficients
+ * @return the decoded polynomial
+ */
+ public static IntegerPolynomial fromBinary3Tight(byte[] b, int N)
+ {
+ return new IntegerPolynomial(ArrayEncoder.decodeMod3Tight(b, N));
+ }
+
+ /**
+ * Reads data produced by {@link #toBinary3Tight()} from an input stream and converts it to a polynomial.
+ *
+ * @param is an input stream
+ * @param N number of coefficients
+ * @return the decoded polynomial
+ */
+ public static IntegerPolynomial fromBinary3Tight(InputStream is, int N)
+ throws IOException
+ {
+ return new IntegerPolynomial(ArrayEncoder.decodeMod3Tight(is, N));
+ }
+
+ /**
+ * Returns a polynomial with N coefficients between <code>0</code> and <code>q-1</code>.<br>
+ * <code>q</code> must be a power of 2.<br>
+ * Ignores any excess bytes.
+ *
+ * @param data an encoded ternary polynomial
+ * @param N number of coefficients
+ * @param q
+ * @return the decoded polynomial
+ */
+ public static IntegerPolynomial fromBinary(byte[] data, int N, int q)
+ {
+ return new IntegerPolynomial(ArrayEncoder.decodeModQ(data, N, q));
+ }
+
+ /**
+ * Returns a polynomial with N coefficients between <code>0</code> and <code>q-1</code>.<br>
+ * <code>q</code> must be a power of 2.<br>
+ * Ignores any excess bytes.
+ *
+ * @param is an encoded ternary polynomial
+ * @param N number of coefficients
+ * @param q
+ * @return the decoded polynomial
+ */
+ public static IntegerPolynomial fromBinary(InputStream is, int N, int q)
+ throws IOException
+ {
+ return new IntegerPolynomial(ArrayEncoder.decodeModQ(is, N, q));
+ }
+
+ /**
+ * Encodes a polynomial with ternary coefficients to binary.
+ * <code>coeffs[2*i]</code> and <code>coeffs[2*i+1]</code> must not both equal -1 for any integer <code>i</code>,
+ * so this method is only safe to use with polynomials produced by <code>fromBinary3Sves()</code>.
+ *
+ * @return the encoded polynomial
+ */
+ public byte[] toBinary3Sves()
+ {
+ return ArrayEncoder.encodeMod3Sves(coeffs);
+ }
+
+ /**
+ * Converts a polynomial with ternary coefficients to binary.
+ *
+ * @return the encoded polynomial
+ */
+ public byte[] toBinary3Tight()
+ {
+ BigInteger sum = Constants.BIGINT_ZERO;
+ for (int i = coeffs.length - 1; i >= 0; i--)
+ {
+ sum = sum.multiply(BigInteger.valueOf(3));
+ sum = sum.add(BigInteger.valueOf(coeffs[i] + 1));
+ }
+
+ int size = (BigInteger.valueOf(3).pow(coeffs.length).bitLength() + 7) / 8;
+ byte[] arr = sum.toByteArray();
+
+ if (arr.length < size)
+ {
+ // pad with leading zeros so arr.length==size
+ byte[] arr2 = new byte[size];
+ System.arraycopy(arr, 0, arr2, size - arr.length, arr.length);
+ return arr2;
+ }
+
+ if (arr.length > size)
+ // drop sign bit
+ {
+ arr = Arrays.copyOfRange(arr, 1, arr.length);
+ }
+ return arr;
+ }
+
+ /**
+ * Encodes a polynomial whose coefficients are between 0 and q, to binary. q must be a power of 2.
+ *
+ * @param q
+ * @return the encoded polynomial
+ */
+ public byte[] toBinary(int q)
+ {
+ return ArrayEncoder.encodeModQ(coeffs, q);
+ }
+
+ /**
+ * Multiplies the polynomial with another, taking the values mod modulus and the indices mod N
+ */
+ public IntegerPolynomial mult(IntegerPolynomial poly2, int modulus)
+ {
+ IntegerPolynomial c = mult(poly2);
+ c.mod(modulus);
+ return c;
+ }
+
+ /**
+ * Multiplies the polynomial with another, taking the indices mod N
+ */
+ public IntegerPolynomial mult(IntegerPolynomial poly2)
+ {
+ int N = coeffs.length;
+ if (poly2.coeffs.length != N)
+ {
+ throw new IllegalArgumentException("Number of coefficients must be the same");
+ }
+
+ IntegerPolynomial c = multRecursive(poly2);
+
+ if (c.coeffs.length > N)
+ {
+ for (int k = N; k < c.coeffs.length; k++)
+ {
+ c.coeffs[k - N] += c.coeffs[k];
+ }
+ c.coeffs = Arrays.copyOf(c.coeffs, N);
+ }
+ return c;
+ }
+
+ public BigIntPolynomial mult(BigIntPolynomial poly2)
+ {
+ return new BigIntPolynomial(this).mult(poly2);
+ }
+
+ /**
+ * Karazuba multiplication
+ */
+ private IntegerPolynomial multRecursive(IntegerPolynomial poly2)
+ {
+ int[] a = coeffs;
+ int[] b = poly2.coeffs;
+
+ int n = poly2.coeffs.length;
+ if (n <= 32)
+ {
+ int cn = 2 * n - 1;
+ IntegerPolynomial c = new IntegerPolynomial(new int[cn]);
+ for (int k = 0; k < cn; k++)
+ {
+ for (int i = Math.max(0, k - n + 1); i <= Math.min(k, n - 1); i++)
+ {
+ c.coeffs[k] += b[i] * a[k - i];
+ }
+ }
+ return c;
+ }
+ else
+ {
+ int n1 = n / 2;
+
+ IntegerPolynomial a1 = new IntegerPolynomial(Arrays.copyOf(a, n1));
+ IntegerPolynomial a2 = new IntegerPolynomial(Arrays.copyOfRange(a, n1, n));
+ IntegerPolynomial b1 = new IntegerPolynomial(Arrays.copyOf(b, n1));
+ IntegerPolynomial b2 = new IntegerPolynomial(Arrays.copyOfRange(b, n1, n));
+
+ IntegerPolynomial A = (IntegerPolynomial)a1.clone();
+ A.add(a2);
+ IntegerPolynomial B = (IntegerPolynomial)b1.clone();
+ B.add(b2);
+
+ IntegerPolynomial c1 = a1.multRecursive(b1);
+ IntegerPolynomial c2 = a2.multRecursive(b2);
+ IntegerPolynomial c3 = A.multRecursive(B);
+ c3.sub(c1);
+ c3.sub(c2);
+
+ IntegerPolynomial c = new IntegerPolynomial(2 * n - 1);
+ for (int i = 0; i < c1.coeffs.length; i++)
+ {
+ c.coeffs[i] = c1.coeffs[i];
+ }
+ for (int i = 0; i < c3.coeffs.length; i++)
+ {
+ c.coeffs[n1 + i] += c3.coeffs[i];
+ }
+ for (int i = 0; i < c2.coeffs.length; i++)
+ {
+ c.coeffs[2 * n1 + i] += c2.coeffs[i];
+ }
+ return c;
+ }
+ }
+
+ /**
+ * Computes the inverse mod <code>q; q</code> must be a power of 2.<br>
+ * Returns <code>null</code> if the polynomial is not invertible.
+ *
+ * @param q the modulus
+ * @return a new polynomial
+ */
+ public IntegerPolynomial invertFq(int q)
+ {
+ int N = coeffs.length;
+ int k = 0;
+ IntegerPolynomial b = new IntegerPolynomial(N + 1);
+ b.coeffs[0] = 1;
+ IntegerPolynomial c = new IntegerPolynomial(N + 1);
+ IntegerPolynomial f = new IntegerPolynomial(N + 1);
+ f.coeffs = Arrays.copyOf(coeffs, N + 1);
+ f.modPositive(2);
+ // set g(x) = x^N − 1
+ IntegerPolynomial g = new IntegerPolynomial(N + 1);
+ g.coeffs[0] = 1;
+ g.coeffs[N] = 1;
+ while (true)
+ {
+ while (f.coeffs[0] == 0)
+ {
+ for (int i = 1; i <= N; i++)
+ {
+ f.coeffs[i - 1] = f.coeffs[i]; // f(x) = f(x) / x
+ c.coeffs[N + 1 - i] = c.coeffs[N - i]; // c(x) = c(x) * x
+ }
+ f.coeffs[N] = 0;
+ c.coeffs[0] = 0;
+ k++;
+ if (f.equalsZero())
+ {
+ return null; // not invertible
+ }
+ }
+ if (f.equalsOne())
+ {
+ break;
+ }
+ if (f.degree() < g.degree())
+ {
+ // exchange f and g
+ IntegerPolynomial temp = f;
+ f = g;
+ g = temp;
+ // exchange b and c
+ temp = b;
+ b = c;
+ c = temp;
+ }
+ f.add(g, 2);
+ b.add(c, 2);
+ }
+
+ if (b.coeffs[N] != 0)
+ {
+ return null;
+ }
+ // Fq(x) = x^(N-k) * b(x)
+ IntegerPolynomial Fq = new IntegerPolynomial(N);
+ int j = 0;
+ k %= N;
+ for (int i = N - 1; i >= 0; i--)
+ {
+ j = i - k;
+ if (j < 0)
+ {
+ j += N;
+ }
+ Fq.coeffs[j] = b.coeffs[i];
+ }
+
+ return mod2ToModq(Fq, q);
+ }
+
+ /**
+ * Computes the inverse mod q from the inverse mod 2
+ *
+ * @param Fq
+ * @param q
+ * @return The inverse of this polynomial mod q
+ */
+ private IntegerPolynomial mod2ToModq(IntegerPolynomial Fq, int q)
+ {
+ if (Util.is64BitJVM() && q == 2048)
+ {
+ LongPolynomial2 thisLong = new LongPolynomial2(this);
+ LongPolynomial2 FqLong = new LongPolynomial2(Fq);
+ int v = 2;
+ while (v < q)
+ {
+ v *= 2;
+ LongPolynomial2 temp = (LongPolynomial2)FqLong.clone();
+ temp.mult2And(v - 1);
+ FqLong = thisLong.mult(FqLong).mult(FqLong);
+ temp.subAnd(FqLong, v - 1);
+ FqLong = temp;
+ }
+ return FqLong.toIntegerPolynomial();
+ }
+ else
+ {
+ int v = 2;
+ while (v < q)
+ {
+ v *= 2;
+ IntegerPolynomial temp = new IntegerPolynomial(Arrays.copyOf(Fq.coeffs, Fq.coeffs.length));
+ temp.mult2(v);
+ Fq = mult(Fq, v).mult(Fq, v);
+ temp.sub(Fq, v);
+ Fq = temp;
+ }
+ return Fq;
+ }
+ }
+
+ /**
+ * Computes the inverse mod 3.
+ * Returns <code>null</code> if the polynomial is not invertible.
+ *
+ * @return a new polynomial
+ */
+ public IntegerPolynomial invertF3()
+ {
+ int N = coeffs.length;
+ int k = 0;
+ IntegerPolynomial b = new IntegerPolynomial(N + 1);
+ b.coeffs[0] = 1;
+ IntegerPolynomial c = new IntegerPolynomial(N + 1);
+ IntegerPolynomial f = new IntegerPolynomial(N + 1);
+ f.coeffs = Arrays.copyOf(coeffs, N + 1);
+ f.modPositive(3);
+ // set g(x) = x^N − 1
+ IntegerPolynomial g = new IntegerPolynomial(N + 1);
+ g.coeffs[0] = -1;
+ g.coeffs[N] = 1;
+ while (true)
+ {
+ while (f.coeffs[0] == 0)
+ {
+ for (int i = 1; i <= N; i++)
+ {
+ f.coeffs[i - 1] = f.coeffs[i]; // f(x) = f(x) / x
+ c.coeffs[N + 1 - i] = c.coeffs[N - i]; // c(x) = c(x) * x
+ }
+ f.coeffs[N] = 0;
+ c.coeffs[0] = 0;
+ k++;
+ if (f.equalsZero())
+ {
+ return null; // not invertible
+ }
+ }
+ if (f.equalsAbsOne())
+ {
+ break;
+ }
+ if (f.degree() < g.degree())
+ {
+ // exchange f and g
+ IntegerPolynomial temp = f;
+ f = g;
+ g = temp;
+ // exchange b and c
+ temp = b;
+ b = c;
+ c = temp;
+ }
+ if (f.coeffs[0] == g.coeffs[0])
+ {
+ f.sub(g, 3);
+ b.sub(c, 3);
+ }
+ else
+ {
+ f.add(g, 3);
+ b.add(c, 3);
+ }
+ }
+
+ if (b.coeffs[N] != 0)
+ {
+ return null;
+ }
+ // Fp(x) = [+-] x^(N-k) * b(x)
+ IntegerPolynomial Fp = new IntegerPolynomial(N);
+ int j = 0;
+ k %= N;
+ for (int i = N - 1; i >= 0; i--)
+ {
+ j = i - k;
+ if (j < 0)
+ {
+ j += N;
+ }
+ Fp.coeffs[j] = f.coeffs[0] * b.coeffs[i];
+ }
+
+ Fp.ensurePositive(3);
+ return Fp;
+ }
+
+ /**
+ * Resultant of this polynomial with <code>x^n-1</code> using a probabilistic algorithm.
+ * <p>
+ * Unlike EESS, this implementation does not compute all resultants modulo primes
+ * such that their product exceeds the maximum possible resultant, but rather stops
+ * when <code>NUM_EQUAL_RESULTANTS</code> consecutive modular resultants are equal.<br>
+ * This means the return value may be incorrect. Experiments show this happens in
+ * about 1 out of 100 cases when <code>N=439</code> and <code>NUM_EQUAL_RESULTANTS=2</code>,
+ * so the likelyhood of leaving the loop too early is <code>(1/100)^(NUM_EQUAL_RESULTANTS-1)</code>.
+ * <p>
+ * Because of the above, callers must verify the output and try a different polynomial if necessary.
+ *
+ * @return <code>(rho, res)</code> satisfying <code>res = rho*this + t*(x^n-1)</code> for some integer <code>t</code>.
+ */
+ public Resultant resultant()
+ {
+ int N = coeffs.length;
+
+ // Compute resultants modulo prime numbers. Continue until NUM_EQUAL_RESULTANTS consecutive modular resultants are equal.
+ LinkedList<ModularResultant> modResultants = new LinkedList<ModularResultant>();
+ BigInteger prime = null;
+ BigInteger pProd = Constants.BIGINT_ONE;
+ BigInteger res = Constants.BIGINT_ONE;
+ int numEqual = 1; // number of consecutive modular resultants equal to each other
+ Iterator<BigInteger> primes = BIGINT_PRIMES.iterator();
+ while (true)
+ {
+ prime = primes.hasNext() ? primes.next() : prime.nextProbablePrime();
+ ModularResultant crr = resultant(prime.intValue());
+ modResultants.add(crr);
+
+ BigInteger temp = pProd.multiply(prime);
+ BigIntEuclidean er = BigIntEuclidean.calculate(prime, pProd);
+ BigInteger resPrev = res;
+ res = res.multiply(er.x.multiply(prime));
+ BigInteger res2 = crr.res.multiply(er.y.multiply(pProd));
+ res = res.add(res2).mod(temp);
+ pProd = temp;
+
+ BigInteger pProd2 = pProd.divide(BigInteger.valueOf(2));
+ BigInteger pProd2n = pProd2.negate();
+ if (res.compareTo(pProd2) > 0)
+ {
+ res = res.subtract(pProd);
+ }
+ else if (res.compareTo(pProd2n) < 0)
+ {
+ res = res.add(pProd);
+ }
+
+ if (res.equals(resPrev))
+ {
+ numEqual++;
+ if (numEqual >= NUM_EQUAL_RESULTANTS)
+ {
+ break;
+ }
+ }
+ else
+ {
+ numEqual = 1;
+ }
+ }
+
+ // Combine modular rho's to obtain the final rho.
+ // For efficiency, first combine all pairs of small resultants to bigger resultants,
+ // then combine pairs of those, etc. until only one is left.
+ while (modResultants.size() > 1)
+ {
+ ModularResultant modRes1 = modResultants.removeFirst();
+ ModularResultant modRes2 = modResultants.removeFirst();
+ ModularResultant modRes3 = ModularResultant.combineRho(modRes1, modRes2);
+ modResultants.addLast(modRes3);
+ }
+ BigIntPolynomial rhoP = modResultants.getFirst().rho;
+
+ BigInteger pProd2 = pProd.divide(BigInteger.valueOf(2));
+ BigInteger pProd2n = pProd2.negate();
+ if (res.compareTo(pProd2) > 0)
+ {
+ res = res.subtract(pProd);
+ }
+ if (res.compareTo(pProd2n) < 0)
+ {
+ res = res.add(pProd);
+ }
+
+ for (int i = 0; i < N; i++)
+ {
+ BigInteger c = rhoP.coeffs[i];
+ if (c.compareTo(pProd2) > 0)
+ {
+ rhoP.coeffs[i] = c.subtract(pProd);
+ }
+ if (c.compareTo(pProd2n) < 0)
+ {
+ rhoP.coeffs[i] = c.add(pProd);
+ }
+ }
+
+ return new Resultant(rhoP, res);
+ }
+
+ /**
+ * Multithreaded version of {@link #resultant()}.
+ *
+ * @return <code>(rho, res)</code> satisfying <code>res = rho*this + t*(x^n-1)</code> for some integer <code>t</code>.
+ */
+ public Resultant resultantMultiThread()
+ {
+ int N = coeffs.length;
+
+ // upper bound for resultant(f, g) = ||f, 2||^deg(g) * ||g, 2||^deg(f) = squaresum(f)^(N/2) * 2^(deg(f)/2) because g(x)=x^N-1
+ // see http://jondalon.mathematik.uni-osnabrueck.de/staff/phpages/brunsw/CompAlg.pdf chapter 3
+ BigInteger max = squareSum().pow((N + 1) / 2);
+ max = max.multiply(BigInteger.valueOf(2).pow((degree() + 1) / 2));
+ BigInteger max2 = max.multiply(BigInteger.valueOf(2));
+
+ // compute resultants modulo prime numbers
+ BigInteger prime = BigInteger.valueOf(10000);
+ BigInteger pProd = Constants.BIGINT_ONE;
+ LinkedBlockingQueue<Future<ModularResultant>> resultantTasks = new LinkedBlockingQueue<Future<ModularResultant>>();
+ Iterator<BigInteger> primes = BIGINT_PRIMES.iterator();
+ ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
+ while (pProd.compareTo(max2) < 0)
+ {
+ if (primes.hasNext())
+ {
+ prime = primes.next();
+ }
+ else
+ {
+ prime = prime.nextProbablePrime();
+ }
+ Future<ModularResultant> task = executor.submit(new ModResultantTask(prime.intValue()));
+ resultantTasks.add(task);
+ pProd = pProd.multiply(prime);
+ }
+
+ // Combine modular resultants to obtain the resultant.
+ // For efficiency, first combine all pairs of small resultants to bigger resultants,
+ // then combine pairs of those, etc. until only one is left.
+ ModularResultant overallResultant = null;
+ while (!resultantTasks.isEmpty())
+ {
+ try
+ {
+ Future<ModularResultant> modRes1 = resultantTasks.take();
+ Future<ModularResultant> modRes2 = resultantTasks.poll();
+ if (modRes2 == null)
+ {
+ // modRes1 is the only one left
+ overallResultant = modRes1.get();
+ break;
+ }
+ Future<ModularResultant> newTask = executor.submit(new CombineTask(modRes1.get(), modRes2.get()));
+ resultantTasks.add(newTask);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalStateException(e.toString());
+ }
+ }
+ executor.shutdown();
+ BigInteger res = overallResultant.res;
+ BigIntPolynomial rhoP = overallResultant.rho;
+
+ BigInteger pProd2 = pProd.divide(BigInteger.valueOf(2));
+ BigInteger pProd2n = pProd2.negate();
+
+ if (res.compareTo(pProd2) > 0)
+ {
+ res = res.subtract(pProd);
+ }
+ if (res.compareTo(pProd2n) < 0)
+ {
+ res = res.add(pProd);
+ }
+
+ for (int i = 0; i < N; i++)
+ {
+ BigInteger c = rhoP.coeffs[i];
+ if (c.compareTo(pProd2) > 0)
+ {
+ rhoP.coeffs[i] = c.subtract(pProd);
+ }
+ if (c.compareTo(pProd2n) < 0)
+ {
+ rhoP.coeffs[i] = c.add(pProd);
+ }
+ }
+
+ return new Resultant(rhoP, res);
+ }
+
+ /**
+ * Resultant of this polynomial with <code>x^n-1 mod p</code>.
+ *
+ * @return <code>(rho, res)</code> satisfying <code>res = rho*this + t*(x^n-1) mod p</code> for some integer <code>t</code>.
+ */
+ public ModularResultant resultant(int p)
+ {
+ // Add a coefficient as the following operations involve polynomials of degree deg(f)+1
+ int[] fcoeffs = Arrays.copyOf(coeffs, coeffs.length + 1);
+ IntegerPolynomial f = new IntegerPolynomial(fcoeffs);
+ int N = fcoeffs.length;
+
+ IntegerPolynomial a = new IntegerPolynomial(N);
+ a.coeffs[0] = -1;
+ a.coeffs[N - 1] = 1;
+ IntegerPolynomial b = new IntegerPolynomial(f.coeffs);
+ IntegerPolynomial v1 = new IntegerPolynomial(N);
+ IntegerPolynomial v2 = new IntegerPolynomial(N);
+ v2.coeffs[0] = 1;
+ int da = N - 1;
+ int db = b.degree();
+ int ta = da;
+ int c = 0;
+ int r = 1;
+ while (db > 0)
+ {
+ c = Util.invert(b.coeffs[db], p);
+ c = (c * a.coeffs[da]) % p;
+ a.multShiftSub(b, c, da - db, p);
+ v1.multShiftSub(v2, c, da - db, p);
+
+ da = a.degree();
+ if (da < db)
+ {
+ r *= Util.pow(b.coeffs[db], ta - da, p);
+ r %= p;
+ if (ta % 2 == 1 && db % 2 == 1)
+ {
+ r = (-r) % p;
+ }
+ IntegerPolynomial temp = a;
+ a = b;
+ b = temp;
+ int tempdeg = da;
+ da = db;
+ temp = v1;
+ v1 = v2;
+ v2 = temp;
+ ta = db;
+ db = tempdeg;
+ }
+ }
+ r *= Util.pow(b.coeffs[0], da, p);
+ r %= p;
+ c = Util.invert(b.coeffs[0], p);
+ v2.mult(c);
+ v2.mod(p);
+ v2.mult(r);
+ v2.mod(p);
+
+ // drop the highest coefficient so #coeffs matches the original input
+ v2.coeffs = Arrays.copyOf(v2.coeffs, v2.coeffs.length - 1);
+ return new ModularResultant(new BigIntPolynomial(v2), BigInteger.valueOf(r), BigInteger.valueOf(p));
+ }
+
+ /**
+ * Computes <code>this-b*c*(x^k) mod p</code> and stores the result in this polynomial.<br/>
+ * See steps 4a,4b in EESS algorithm 2.2.7.1.
+ *
+ * @param b
+ * @param c
+ * @param k
+ * @param p
+ */
+ private void multShiftSub(IntegerPolynomial b, int c, int k, int p)
+ {
+ int N = coeffs.length;
+ for (int i = k; i < N; i++)
+ {
+ coeffs[i] = (coeffs[i] - b.coeffs[i - k] * c) % p;
+ }
+ }
+
+ /**
+ * Adds the squares of all coefficients.
+ *
+ * @return the sum of squares
+ */
+ private BigInteger squareSum()
+ {
+ BigInteger sum = Constants.BIGINT_ZERO;
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ sum = sum.add(BigInteger.valueOf(coeffs[i] * coeffs[i]));
+ }
+ return sum;
+ }
+
+ /**
+ * Returns the degree of the polynomial
+ *
+ * @return the degree
+ */
+ int degree()
+ {
+ int degree = coeffs.length - 1;
+ while (degree > 0 && coeffs[degree] == 0)
+ {
+ degree--;
+ }
+ return degree;
+ }
+
+ /**
+ * Adds another polynomial which can have a different number of coefficients,
+ * and takes the coefficient values mod <code>modulus</code>.
+ *
+ * @param b another polynomial
+ */
+ public void add(IntegerPolynomial b, int modulus)
+ {
+ add(b);
+ mod(modulus);
+ }
+
+ /**
+ * Adds another polynomial which can have a different number of coefficients.
+ *
+ * @param b another polynomial
+ */
+ public void add(IntegerPolynomial b)
+ {
+ if (b.coeffs.length > coeffs.length)
+ {
+ coeffs = Arrays.copyOf(coeffs, b.coeffs.length);
+ }
+ for (int i = 0; i < b.coeffs.length; i++)
+ {
+ coeffs[i] += b.coeffs[i];
+ }
+ }
+
+ /**
+ * Subtracts another polynomial which can have a different number of coefficients,
+ * and takes the coefficient values mod <code>modulus</code>.
+ *
+ * @param b another polynomial
+ */
+ public void sub(IntegerPolynomial b, int modulus)
+ {
+ sub(b);
+ mod(modulus);
+ }
+
+ /**
+ * Subtracts another polynomial which can have a different number of coefficients.
+ *
+ * @param b another polynomial
+ */
+ public void sub(IntegerPolynomial b)
+ {
+ if (b.coeffs.length > coeffs.length)
+ {
+ coeffs = Arrays.copyOf(coeffs, b.coeffs.length);
+ }
+ for (int i = 0; i < b.coeffs.length; i++)
+ {
+ coeffs[i] -= b.coeffs[i];
+ }
+ }
+
+ /**
+ * Subtracts a <code>int</code> from each coefficient. Does not return a new polynomial but modifies this polynomial.
+ *
+ * @param b
+ */
+ void sub(int b)
+ {
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ coeffs[i] -= b;
+ }
+ }
+
+ /**
+ * Multiplies each coefficient by a <code>int</code>. Does not return a new polynomial but modifies this polynomial.
+ *
+ * @param factor
+ */
+ public void mult(int factor)
+ {
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ coeffs[i] *= factor;
+ }
+ }
+
+ /**
+ * Multiplies each coefficient by a 2 and applies a modulus. Does not return a new polynomial but modifies this polynomial.
+ *
+ * @param modulus a modulus
+ */
+ private void mult2(int modulus)
+ {
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ coeffs[i] *= 2;
+ coeffs[i] %= modulus;
+ }
+ }
+
+ /**
+ * Multiplies each coefficient by a 2 and applies a modulus. Does not return a new polynomial but modifies this polynomial.
+ *
+ * @param modulus a modulus
+ */
+ public void mult3(int modulus)
+ {
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ coeffs[i] *= 3;
+ coeffs[i] %= modulus;
+ }
+ }
+
+ /**
+ * Divides each coefficient by <code>k</code> and rounds to the nearest integer. Does not return a new polynomial but modifies this polynomial.
+ *
+ * @param k the divisor
+ */
+ public void div(int k)
+ {
+ int k2 = (k + 1) / 2;
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ coeffs[i] += coeffs[i] > 0 ? k2 : -k2;
+ coeffs[i] /= k;
+ }
+ }
+
+ /**
+ * Takes each coefficient modulo 3 such that all coefficients are ternary.
+ */
+ public void mod3()
+ {
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ coeffs[i] %= 3;
+ if (coeffs[i] > 1)
+ {
+ coeffs[i] -= 3;
+ }
+ if (coeffs[i] < -1)
+ {
+ coeffs[i] += 3;
+ }
+ }
+ }
+
+ /**
+ * Ensures all coefficients are between 0 and <code>modulus-1</code>
+ *
+ * @param modulus a modulus
+ */
+ public void modPositive(int modulus)
+ {
+ mod(modulus);
+ ensurePositive(modulus);
+ }
+
+ /**
+ * Reduces all coefficients to the interval [-modulus/2, modulus/2)
+ */
+ void modCenter(int modulus)
+ {
+ mod(modulus);
+ for (int j = 0; j < coeffs.length; j++)
+ {
+ while (coeffs[j] < modulus / 2)
+ {
+ coeffs[j] += modulus;
+ }
+ while (coeffs[j] >= modulus / 2)
+ {
+ coeffs[j] -= modulus;
+ }
+ }
+ }
+
+ /**
+ * Takes each coefficient modulo <code>modulus</code>.
+ */
+ public void mod(int modulus)
+ {
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ coeffs[i] %= modulus;
+ }
+ }
+
+ /**
+ * Adds <code>modulus</code> until all coefficients are above 0.
+ *
+ * @param modulus a modulus
+ */
+ public void ensurePositive(int modulus)
+ {
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ while (coeffs[i] < 0)
+ {
+ coeffs[i] += modulus;
+ }
+ }
+ }
+
+ /**
+ * Computes the centered euclidean norm of the polynomial.
+ *
+ * @param q a modulus
+ * @return the centered norm
+ */
+ public long centeredNormSq(int q)
+ {
+ int N = coeffs.length;
+ IntegerPolynomial p = (IntegerPolynomial)clone();
+ p.shiftGap(q);
+
+ long sum = 0;
+ long sqSum = 0;
+ for (int i = 0; i != p.coeffs.length; i++)
+ {
+ int c = p.coeffs[i];
+ sum += c;
+ sqSum += c * c;
+ }
+
+ long centeredNormSq = sqSum - sum * sum / N;
+ return centeredNormSq;
+ }
+
+ /**
+ * Shifts all coefficients so the largest gap is centered around <code>-q/2</code>.
+ *
+ * @param q a modulus
+ */
+ void shiftGap(int q)
+ {
+ modCenter(q);
+
+ int[] sorted = Arrays.clone(coeffs);
+
+ sort(sorted);
+
+ int maxrange = 0;
+ int maxrangeStart = 0;
+ for (int i = 0; i < sorted.length - 1; i++)
+ {
+ int range = sorted[i + 1] - sorted[i];
+ if (range > maxrange)
+ {
+ maxrange = range;
+ maxrangeStart = sorted[i];
+ }
+ }
+
+ int pmin = sorted[0];
+ int pmax = sorted[sorted.length - 1];
+
+ int j = q - pmax + pmin;
+ int shift;
+ if (j > maxrange)
+ {
+ shift = (pmax + pmin) / 2;
+ }
+ else
+ {
+ shift = maxrangeStart + maxrange / 2 + q / 2;
+ }
+
+ sub(shift);
+ }
+
+ private void sort(int[] ints)
+ {
+ boolean swap = true;
+
+ while (swap)
+ {
+ swap = false;
+ for (int i = 0; i != ints.length - 1; i++)
+ {
+ if (ints[i] > ints[i+1])
+ {
+ int tmp = ints[i];
+ ints[i] = ints[i+1];
+ ints[i+1] = tmp;
+ swap = true;
+ }
+ }
+ }
+ }
+
+ /**
+ * Shifts the values of all coefficients to the interval <code>[-q/2, q/2]</code>.
+ *
+ * @param q a modulus
+ */
+ public void center0(int q)
+ {
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ while (coeffs[i] < -q / 2)
+ {
+ coeffs[i] += q;
+ }
+ while (coeffs[i] > q / 2)
+ {
+ coeffs[i] -= q;
+ }
+ }
+ }
+
+ /**
+ * Returns the sum of all coefficients, i.e. evaluates the polynomial at 0.
+ *
+ * @return the sum of all coefficients
+ */
+ public int sumCoeffs()
+ {
+ int sum = 0;
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ sum += coeffs[i];
+ }
+ return sum;
+ }
+
+ /**
+ * Tests if <code>p(x) = 0</code>.
+ *
+ * @return true iff all coefficients are zeros
+ */
+ private boolean equalsZero()
+ {
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ if (coeffs[i] != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Tests if <code>p(x) = 1</code>.
+ *
+ * @return true iff all coefficients are equal to zero, except for the lowest coefficient which must equal 1
+ */
+ public boolean equalsOne()
+ {
+ for (int i = 1; i < coeffs.length; i++)
+ {
+ if (coeffs[i] != 0)
+ {
+ return false;
+ }
+ }
+ return coeffs[0] == 1;
+ }
+
+ /**
+ * Tests if <code>|p(x)| = 1</code>.
+ *
+ * @return true iff all coefficients are equal to zero, except for the lowest coefficient which must equal 1 or -1
+ */
+ private boolean equalsAbsOne()
+ {
+ for (int i = 1; i < coeffs.length; i++)
+ {
+ if (coeffs[i] != 0)
+ {
+ return false;
+ }
+ }
+ return Math.abs(coeffs[0]) == 1;
+ }
+
+ /**
+ * Counts the number of coefficients equal to an integer
+ *
+ * @param value an integer
+ * @return the number of coefficients equal to <code>value</code>
+ */
+ public int count(int value)
+ {
+ int count = 0;
+ for (int i = 0; i != coeffs.length; i++)
+ {
+ if (coeffs[i] == value)
+ {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ /**
+ * Multiplication by <code>X</code> in <code>Z[X]/Z[X^n-1]</code>.
+ */
+ public void rotate1()
+ {
+ int clast = coeffs[coeffs.length - 1];
+ for (int i = coeffs.length - 1; i > 0; i--)
+ {
+ coeffs[i] = coeffs[i - 1];
+ }
+ coeffs[0] = clast;
+ }
+
+ public void clear()
+ {
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ coeffs[i] = 0;
+ }
+ }
+
+ public IntegerPolynomial toIntegerPolynomial()
+ {
+ return (IntegerPolynomial)clone();
+ }
+
+ public Object clone()
+ {
+ return new IntegerPolynomial(coeffs.clone());
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof IntegerPolynomial)
+ {
+ return Arrays.areEqual(coeffs, ((IntegerPolynomial)obj).coeffs);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Calls {@link IntegerPolynomial#resultant(int)
+ */
+ private class ModResultantTask
+ implements Callable<ModularResultant>
+ {
+ private int modulus;
+
+ private ModResultantTask(int modulus)
+ {
+ this.modulus = modulus;
+ }
+
+ public ModularResultant call()
+ {
+ return resultant(modulus);
+ }
+ }
+
+ /**
+ * Calls {@link ModularResultant#combineRho(ModularResultant, ModularResultant)
+ */
+ private class CombineTask
+ implements Callable<ModularResultant>
+ {
+ private ModularResultant modRes1;
+ private ModularResultant modRes2;
+
+ private CombineTask(ModularResultant modRes1, ModularResultant modRes2)
+ {
+ this.modRes1 = modRes1;
+ this.modRes2 = modRes2;
+ }
+
+ public ModularResultant call()
+ {
+ return ModularResultant.combineRho(modRes1, modRes2);
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/LongPolynomial2.java b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/LongPolynomial2.java
new file mode 100644
index 00000000..513cac50
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/LongPolynomial2.java
@@ -0,0 +1,255 @@
+package org.spongycastle.pqc.math.ntru.polynomial;
+
+import org.spongycastle.util.Arrays;
+
+/**
+ * A polynomial class that combines two coefficients into one <code>long</code> value for
+ * faster multiplication in 64 bit environments.<br>
+ * Coefficients can be between 0 and 2047 and are stored in pairs in the bits 0..10 and 24..34 of a <code>long</code> number.
+ */
+public class LongPolynomial2
+{
+ private long[] coeffs; // each representing two coefficients in the original IntegerPolynomial
+ private int numCoeffs;
+
+ /**
+ * Constructs a <code>LongPolynomial2</code> from a <code>IntegerPolynomial</code>. The two polynomials are independent of each other.
+ *
+ * @param p the original polynomial. Coefficients must be between 0 and 2047.
+ */
+ public LongPolynomial2(IntegerPolynomial p)
+ {
+ numCoeffs = p.coeffs.length;
+ coeffs = new long[(numCoeffs + 1) / 2];
+ int idx = 0;
+ for (int pIdx = 0; pIdx < numCoeffs; )
+ {
+ int c0 = p.coeffs[pIdx++];
+ while (c0 < 0)
+ {
+ c0 += 2048;
+ }
+ long c1 = pIdx < numCoeffs ? p.coeffs[pIdx++] : 0;
+ while (c1 < 0)
+ {
+ c1 += 2048;
+ }
+ coeffs[idx] = c0 + (c1 << 24);
+ idx++;
+ }
+ }
+
+ private LongPolynomial2(long[] coeffs)
+ {
+ this.coeffs = coeffs;
+ }
+
+ private LongPolynomial2(int N)
+ {
+ coeffs = new long[N];
+ }
+
+ /**
+ * Multiplies the polynomial with another, taking the indices mod N and the values mod 2048.
+ */
+ public LongPolynomial2 mult(LongPolynomial2 poly2)
+ {
+ int N = coeffs.length;
+ if (poly2.coeffs.length != N || numCoeffs != poly2.numCoeffs)
+ {
+ throw new IllegalArgumentException("Number of coefficients must be the same");
+ }
+
+ LongPolynomial2 c = multRecursive(poly2);
+
+ if (c.coeffs.length > N)
+ {
+ if (numCoeffs % 2 == 0)
+ {
+ for (int k = N; k < c.coeffs.length; k++)
+ {
+ c.coeffs[k - N] = (c.coeffs[k - N] + c.coeffs[k]) & 0x7FF0007FFL;
+ }
+ c.coeffs = Arrays.copyOf(c.coeffs, N);
+ }
+ else
+ {
+ for (int k = N; k < c.coeffs.length; k++)
+ {
+ c.coeffs[k - N] = c.coeffs[k - N] + (c.coeffs[k - 1] >> 24);
+ c.coeffs[k - N] = c.coeffs[k - N] + ((c.coeffs[k] & 2047) << 24);
+ c.coeffs[k - N] &= 0x7FF0007FFL;
+ }
+ c.coeffs = Arrays.copyOf(c.coeffs, N);
+ c.coeffs[c.coeffs.length - 1] &= 2047;
+ }
+ }
+
+ c = new LongPolynomial2(c.coeffs);
+ c.numCoeffs = numCoeffs;
+ return c;
+ }
+
+ public IntegerPolynomial toIntegerPolynomial()
+ {
+ int[] intCoeffs = new int[numCoeffs];
+ int uIdx = 0;
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ intCoeffs[uIdx++] = (int)(coeffs[i] & 2047);
+ if (uIdx < numCoeffs)
+ {
+ intCoeffs[uIdx++] = (int)((coeffs[i] >> 24) & 2047);
+ }
+ }
+ return new IntegerPolynomial(intCoeffs);
+ }
+
+ /**
+ * Karazuba multiplication
+ */
+ private LongPolynomial2 multRecursive(LongPolynomial2 poly2)
+ {
+ long[] a = coeffs;
+ long[] b = poly2.coeffs;
+
+ int n = poly2.coeffs.length;
+ if (n <= 32)
+ {
+ int cn = 2 * n;
+ LongPolynomial2 c = new LongPolynomial2(new long[cn]);
+ for (int k = 0; k < cn; k++)
+ {
+ for (int i = Math.max(0, k - n + 1); i <= Math.min(k, n - 1); i++)
+ {
+ long c0 = a[k - i] * b[i];
+ long cu = c0 & 0x7FF000000L + (c0 & 2047);
+ long co = (c0 >>> 48) & 2047;
+
+ c.coeffs[k] = (c.coeffs[k] + cu) & 0x7FF0007FFL;
+ c.coeffs[k + 1] = (c.coeffs[k + 1] + co) & 0x7FF0007FFL;
+ }
+ }
+ return c;
+ }
+ else
+ {
+ int n1 = n / 2;
+
+ LongPolynomial2 a1 = new LongPolynomial2(Arrays.copyOf(a, n1));
+ LongPolynomial2 a2 = new LongPolynomial2(Arrays.copyOfRange(a, n1, n));
+ LongPolynomial2 b1 = new LongPolynomial2(Arrays.copyOf(b, n1));
+ LongPolynomial2 b2 = new LongPolynomial2(Arrays.copyOfRange(b, n1, n));
+
+ LongPolynomial2 A = (LongPolynomial2)a1.clone();
+ A.add(a2);
+ LongPolynomial2 B = (LongPolynomial2)b1.clone();
+ B.add(b2);
+
+ LongPolynomial2 c1 = a1.multRecursive(b1);
+ LongPolynomial2 c2 = a2.multRecursive(b2);
+ LongPolynomial2 c3 = A.multRecursive(B);
+ c3.sub(c1);
+ c3.sub(c2);
+
+ LongPolynomial2 c = new LongPolynomial2(2 * n);
+ for (int i = 0; i < c1.coeffs.length; i++)
+ {
+ c.coeffs[i] = c1.coeffs[i] & 0x7FF0007FFL;
+ }
+ for (int i = 0; i < c3.coeffs.length; i++)
+ {
+ c.coeffs[n1 + i] = (c.coeffs[n1 + i] + c3.coeffs[i]) & 0x7FF0007FFL;
+ }
+ for (int i = 0; i < c2.coeffs.length; i++)
+ {
+ c.coeffs[2 * n1 + i] = (c.coeffs[2 * n1 + i] + c2.coeffs[i]) & 0x7FF0007FFL;
+ }
+ return c;
+ }
+ }
+
+ /**
+ * Adds another polynomial which can have a different number of coefficients.
+ *
+ * @param b another polynomial
+ */
+ private void add(LongPolynomial2 b)
+ {
+ if (b.coeffs.length > coeffs.length)
+ {
+ coeffs = Arrays.copyOf(coeffs, b.coeffs.length);
+ }
+ for (int i = 0; i < b.coeffs.length; i++)
+ {
+ coeffs[i] = (coeffs[i] + b.coeffs[i]) & 0x7FF0007FFL;
+ }
+ }
+
+ /**
+ * Subtracts another polynomial which can have a different number of coefficients.
+ *
+ * @param b another polynomial
+ */
+ private void sub(LongPolynomial2 b)
+ {
+ if (b.coeffs.length > coeffs.length)
+ {
+ coeffs = Arrays.copyOf(coeffs, b.coeffs.length);
+ }
+ for (int i = 0; i < b.coeffs.length; i++)
+ {
+ coeffs[i] = (0x0800000800000L + coeffs[i] - b.coeffs[i]) & 0x7FF0007FFL;
+ }
+ }
+
+ /**
+ * Subtracts another polynomial which must have the same number of coefficients,
+ * and applies an AND mask to the upper and lower halves of each coefficients.
+ *
+ * @param b another polynomial
+ * @param mask a bit mask less than 2048 to apply to each 11-bit coefficient
+ */
+ public void subAnd(LongPolynomial2 b, int mask)
+ {
+ long longMask = (((long)mask) << 24) + mask;
+ for (int i = 0; i < b.coeffs.length; i++)
+ {
+ coeffs[i] = (0x0800000800000L + coeffs[i] - b.coeffs[i]) & longMask;
+ }
+ }
+
+ /**
+ * Multiplies this polynomial by 2 and applies an AND mask to the upper and
+ * lower halves of each coefficients.
+ *
+ * @param mask a bit mask less than 2048 to apply to each 11-bit coefficient
+ */
+ public void mult2And(int mask)
+ {
+ long longMask = (((long)mask) << 24) + mask;
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ coeffs[i] = (coeffs[i] << 1) & longMask;
+ }
+ }
+
+ public Object clone()
+ {
+ LongPolynomial2 p = new LongPolynomial2(coeffs.clone());
+ p.numCoeffs = numCoeffs;
+ return p;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof LongPolynomial2)
+ {
+ return Arrays.areEqual(coeffs, ((LongPolynomial2)obj).coeffs);
+ }
+ else
+ {
+ return false;
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/LongPolynomial5.java b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/LongPolynomial5.java
new file mode 100644
index 00000000..f8764c68
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/LongPolynomial5.java
@@ -0,0 +1,149 @@
+package org.spongycastle.pqc.math.ntru.polynomial;
+
+import org.spongycastle.util.Arrays;
+
+/**
+ * A polynomial class that combines five coefficients into one <code>long</code> value for
+ * faster multiplication by a ternary polynomial.<br>
+ * Coefficients can be between 0 and 2047 and are stored in bits 0..11, 12..23, ..., 48..59 of a <code>long</code> number.
+ */
+public class LongPolynomial5
+{
+ private long[] coeffs; // groups of 5 coefficients
+ private int numCoeffs;
+
+ /**
+ * Constructs a <code>LongPolynomial5</code> from a <code>IntegerPolynomial</code>. The two polynomials are independent of each other.
+ *
+ * @param p the original polynomial. Coefficients must be between 0 and 2047.
+ */
+ public LongPolynomial5(IntegerPolynomial p)
+ {
+ numCoeffs = p.coeffs.length;
+
+ coeffs = new long[(numCoeffs + 4) / 5];
+ int cIdx = 0;
+ int shift = 0;
+ for (int i = 0; i < numCoeffs; i++)
+ {
+ coeffs[cIdx] |= ((long)p.coeffs[i]) << shift;
+ shift += 12;
+ if (shift >= 60)
+ {
+ shift = 0;
+ cIdx++;
+ }
+ }
+ }
+
+ private LongPolynomial5(long[] coeffs, int numCoeffs)
+ {
+ this.coeffs = coeffs;
+ this.numCoeffs = numCoeffs;
+ }
+
+ /**
+ * Multiplies the polynomial with a <code>TernaryPolynomial</code>, taking the indices mod N and the values mod 2048.
+ */
+ public LongPolynomial5 mult(TernaryPolynomial poly2)
+ {
+ long[][] prod = new long[5][coeffs.length + (poly2.size() + 4) / 5 - 1]; // intermediate results, the subarrays are shifted by 0,...,4 coefficients
+
+ // multiply ones
+ int[] ones = poly2.getOnes();
+ for (int idx = 0; idx != ones.length; idx++)
+ {
+ int pIdx = ones[idx];
+ int cIdx = pIdx / 5;
+ int m = pIdx - cIdx * 5; // m = pIdx % 5
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ prod[m][cIdx] = (prod[m][cIdx] + coeffs[i]) & 0x7FF7FF7FF7FF7FFL;
+ cIdx++;
+ }
+ }
+
+ // multiply negative ones
+ int[] negOnes = poly2.getNegOnes();
+ for (int idx = 0; idx != negOnes.length; idx++)
+ {
+ int pIdx = negOnes[idx];
+ int cIdx = pIdx / 5;
+ int m = pIdx - cIdx * 5; // m = pIdx % 5
+ for (int i = 0; i < coeffs.length; i++)
+ {
+ prod[m][cIdx] = (0x800800800800800L + prod[m][cIdx] - coeffs[i]) & 0x7FF7FF7FF7FF7FFL;
+ cIdx++;
+ }
+ }
+
+ // combine shifted coefficients (5 arrays) into a single array of length prod[*].length+1
+ long[] cCoeffs = Arrays.copyOf(prod[0], prod[0].length + 1);
+ for (int m = 1; m <= 4; m++)
+ {
+ int shift = m * 12;
+ int shift60 = 60 - shift;
+ long mask = (1L << shift60) - 1;
+ int pLen = prod[m].length;
+ for (int i = 0; i < pLen; i++)
+ {
+ long upper, lower;
+ upper = prod[m][i] >> shift60;
+ lower = prod[m][i] & mask;
+
+ cCoeffs[i] = (cCoeffs[i] + (lower << shift)) & 0x7FF7FF7FF7FF7FFL;
+ int nextIdx = i + 1;
+ cCoeffs[nextIdx] = (cCoeffs[nextIdx] + upper) & 0x7FF7FF7FF7FF7FFL;
+ }
+ }
+
+ // reduce indices of cCoeffs modulo numCoeffs
+ int shift = 12 * (numCoeffs % 5);
+ for (int cIdx = coeffs.length - 1; cIdx < cCoeffs.length; cIdx++)
+ {
+ long iCoeff; // coefficient to shift into the [0..numCoeffs-1] range
+ int newIdx;
+ if (cIdx == coeffs.length - 1)
+ {
+ iCoeff = numCoeffs == 5 ? 0 : cCoeffs[cIdx] >> shift;
+ newIdx = 0;
+ }
+ else
+ {
+ iCoeff = cCoeffs[cIdx];
+ newIdx = cIdx * 5 - numCoeffs;
+ }
+
+ int base = newIdx / 5;
+ int m = newIdx - base * 5; // m = newIdx % 5
+ long lower = iCoeff << (12 * m);
+ long upper = iCoeff >> (12 * (5 - m));
+ cCoeffs[base] = (cCoeffs[base] + lower) & 0x7FF7FF7FF7FF7FFL;
+ int base1 = base + 1;
+ if (base1 < coeffs.length)
+ {
+ cCoeffs[base1] = (cCoeffs[base1] + upper) & 0x7FF7FF7FF7FF7FFL;
+ }
+ }
+
+ return new LongPolynomial5(cCoeffs, numCoeffs);
+ }
+
+ public IntegerPolynomial toIntegerPolynomial()
+ {
+ int[] intCoeffs = new int[numCoeffs];
+ int cIdx = 0;
+ int shift = 0;
+ for (int i = 0; i < numCoeffs; i++)
+ {
+ intCoeffs[i] = (int)((coeffs[cIdx] >> shift) & 2047);
+ shift += 12;
+ if (shift >= 60)
+ {
+ shift = 0;
+ cIdx++;
+ }
+ }
+ return new IntegerPolynomial(intCoeffs);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/ModularResultant.java b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/ModularResultant.java
new file mode 100644
index 00000000..7e8031fe
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/ModularResultant.java
@@ -0,0 +1,46 @@
+package org.spongycastle.pqc.math.ntru.polynomial;
+
+import java.math.BigInteger;
+
+import org.spongycastle.pqc.math.ntru.euclid.BigIntEuclidean;
+
+/**
+ * A resultant modulo a <code>BigInteger</code>
+ */
+public class ModularResultant
+ extends Resultant
+{
+ BigInteger modulus;
+
+ ModularResultant(BigIntPolynomial rho, BigInteger res, BigInteger modulus)
+ {
+ super(rho, res);
+ this.modulus = modulus;
+ }
+
+ /**
+ * Calculates a <code>rho</code> modulo <code>m1*m2</code> from
+ * two resultants whose <code>rho</code>s are modulo <code>m1</code> and <code>m2</code>.<br/>
+ * </code>res</code> is set to <code>null</code>.
+ *
+ * @param modRes1
+ * @param modRes2
+ * @return <code>rho</code> modulo <code>modRes1.modulus * modRes2.modulus</code>, and <code>null</code> for </code>res</code>.
+ */
+ static ModularResultant combineRho(ModularResultant modRes1, ModularResultant modRes2)
+ {
+ BigInteger mod1 = modRes1.modulus;
+ BigInteger mod2 = modRes2.modulus;
+ BigInteger prod = mod1.multiply(mod2);
+ BigIntEuclidean er = BigIntEuclidean.calculate(mod2, mod1);
+
+ BigIntPolynomial rho1 = (BigIntPolynomial)modRes1.rho.clone();
+ rho1.mult(er.x.multiply(mod2));
+ BigIntPolynomial rho2 = (BigIntPolynomial)modRes2.rho.clone();
+ rho2.mult(er.y.multiply(mod1));
+ rho1.add(rho2);
+ rho1.mod(prod);
+
+ return new ModularResultant(rho1, null, prod);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/Polynomial.java b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/Polynomial.java
new file mode 100644
index 00000000..1d1f1dfb
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/Polynomial.java
@@ -0,0 +1,42 @@
+package org.spongycastle.pqc.math.ntru.polynomial;
+
+public interface Polynomial
+{
+
+ /**
+ * Multiplies the polynomial by an <code>IntegerPolynomial</code>,
+ * taking the indices mod <code>N</code>.
+ *
+ * @param poly2 a polynomial
+ * @return the product of the two polynomials
+ */
+ IntegerPolynomial mult(IntegerPolynomial poly2);
+
+ /**
+ * Multiplies the polynomial by an <code>IntegerPolynomial</code>,
+ * taking the coefficient values mod <code>modulus</code> and the indices mod <code>N</code>.
+ *
+ * @param poly2 a polynomial
+ * @param modulus a modulus to apply
+ * @return the product of the two polynomials
+ */
+ IntegerPolynomial mult(IntegerPolynomial poly2, int modulus);
+
+ /**
+ * Returns a polynomial that is equal to this polynomial (in the sense that {@link #mult(IntegerPolynomial, int)}
+ * returns equal <code>IntegerPolynomial</code>s). The new polynomial is guaranteed to be independent of the original.
+ *
+ * @return a new <code>IntegerPolynomial</code>.
+ */
+ IntegerPolynomial toIntegerPolynomial();
+
+ /**
+ * Multiplies the polynomial by a <code>BigIntPolynomial</code>, taking the indices mod N. Does not
+ * change this polynomial but returns the result as a new polynomial.<br>
+ * Both polynomials must have the same number of coefficients.
+ *
+ * @param poly2 the polynomial to multiply by
+ * @return a new polynomial
+ */
+ BigIntPolynomial mult(BigIntPolynomial poly2);
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/ProductFormPolynomial.java b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/ProductFormPolynomial.java
new file mode 100644
index 00000000..e60ce8b8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/ProductFormPolynomial.java
@@ -0,0 +1,153 @@
+package org.spongycastle.pqc.math.ntru.polynomial;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.SecureRandom;
+
+import org.spongycastle.util.Arrays;
+
+/**
+ * A polynomial of the form <code>f1*f2+f3</code>, where
+ * <code>f1,f2,f3</code> are very sparsely populated ternary polynomials.
+ */
+public class ProductFormPolynomial
+ implements Polynomial
+{
+ private SparseTernaryPolynomial f1, f2, f3;
+
+ public ProductFormPolynomial(SparseTernaryPolynomial f1, SparseTernaryPolynomial f2, SparseTernaryPolynomial f3)
+ {
+ this.f1 = f1;
+ this.f2 = f2;
+ this.f3 = f3;
+ }
+
+ public static ProductFormPolynomial generateRandom(int N, int df1, int df2, int df3Ones, int df3NegOnes, SecureRandom random)
+ {
+ SparseTernaryPolynomial f1 = SparseTernaryPolynomial.generateRandom(N, df1, df1, random);
+ SparseTernaryPolynomial f2 = SparseTernaryPolynomial.generateRandom(N, df2, df2, random);
+ SparseTernaryPolynomial f3 = SparseTernaryPolynomial.generateRandom(N, df3Ones, df3NegOnes, random);
+ return new ProductFormPolynomial(f1, f2, f3);
+ }
+
+ public static ProductFormPolynomial fromBinary(byte[] data, int N, int df1, int df2, int df3Ones, int df3NegOnes)
+ throws IOException
+ {
+ return fromBinary(new ByteArrayInputStream(data), N, df1, df2, df3Ones, df3NegOnes);
+ }
+
+ public static ProductFormPolynomial fromBinary(InputStream is, int N, int df1, int df2, int df3Ones, int df3NegOnes)
+ throws IOException
+ {
+ SparseTernaryPolynomial f1;
+
+ f1 = SparseTernaryPolynomial.fromBinary(is, N, df1, df1);
+ SparseTernaryPolynomial f2 = SparseTernaryPolynomial.fromBinary(is, N, df2, df2);
+ SparseTernaryPolynomial f3 = SparseTernaryPolynomial.fromBinary(is, N, df3Ones, df3NegOnes);
+ return new ProductFormPolynomial(f1, f2, f3);
+ }
+
+ public byte[] toBinary()
+ {
+ byte[] f1Bin = f1.toBinary();
+ byte[] f2Bin = f2.toBinary();
+ byte[] f3Bin = f3.toBinary();
+
+ byte[] all = Arrays.copyOf(f1Bin, f1Bin.length + f2Bin.length + f3Bin.length);
+ System.arraycopy(f2Bin, 0, all, f1Bin.length, f2Bin.length);
+ System.arraycopy(f3Bin, 0, all, f1Bin.length + f2Bin.length, f3Bin.length);
+ return all;
+ }
+
+ public IntegerPolynomial mult(IntegerPolynomial b)
+ {
+ IntegerPolynomial c = f1.mult(b);
+ c = f2.mult(c);
+ c.add(f3.mult(b));
+ return c;
+ }
+
+ public BigIntPolynomial mult(BigIntPolynomial b)
+ {
+ BigIntPolynomial c = f1.mult(b);
+ c = f2.mult(c);
+ c.add(f3.mult(b));
+ return c;
+ }
+
+ public IntegerPolynomial toIntegerPolynomial()
+ {
+ IntegerPolynomial i = f1.mult(f2.toIntegerPolynomial());
+ i.add(f3.toIntegerPolynomial());
+ return i;
+ }
+
+ public IntegerPolynomial mult(IntegerPolynomial poly2, int modulus)
+ {
+ IntegerPolynomial c = mult(poly2);
+ c.mod(modulus);
+ return c;
+ }
+
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((f1 == null) ? 0 : f1.hashCode());
+ result = prime * result + ((f2 == null) ? 0 : f2.hashCode());
+ result = prime * result + ((f3 == null) ? 0 : f3.hashCode());
+ return result;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+ ProductFormPolynomial other = (ProductFormPolynomial)obj;
+ if (f1 == null)
+ {
+ if (other.f1 != null)
+ {
+ return false;
+ }
+ }
+ else if (!f1.equals(other.f1))
+ {
+ return false;
+ }
+ if (f2 == null)
+ {
+ if (other.f2 != null)
+ {
+ return false;
+ }
+ }
+ else if (!f2.equals(other.f2))
+ {
+ return false;
+ }
+ if (f3 == null)
+ {
+ if (other.f3 != null)
+ {
+ return false;
+ }
+ }
+ else if (!f3.equals(other.f3))
+ {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/Resultant.java b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/Resultant.java
new file mode 100644
index 00000000..8fa13328
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/Resultant.java
@@ -0,0 +1,28 @@
+package org.spongycastle.pqc.math.ntru.polynomial;
+
+import java.math.BigInteger;
+
+/**
+ * Contains a resultant and a polynomial <code>rho</code> such that
+ * <code>res = rho*this + t*(x^n-1) for some integer t</code>.
+ *
+ * @see IntegerPolynomial#resultant()
+ * @see IntegerPolynomial#resultant(int)
+ */
+public class Resultant
+{
+ /**
+ * A polynomial such that <code>res = rho*this + t*(x^n-1) for some integer t</code>
+ */
+ public BigIntPolynomial rho;
+ /**
+ * Resultant of a polynomial with <code>x^n-1</code>
+ */
+ public BigInteger res;
+
+ Resultant(BigIntPolynomial rho, BigInteger res)
+ {
+ this.rho = rho;
+ this.res = res;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/SparseTernaryPolynomial.java b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/SparseTernaryPolynomial.java
new file mode 100644
index 00000000..2fbd70a4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/SparseTernaryPolynomial.java
@@ -0,0 +1,320 @@
+package org.spongycastle.pqc.math.ntru.polynomial;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.pqc.math.ntru.util.ArrayEncoder;
+import org.spongycastle.pqc.math.ntru.util.Util;
+import org.spongycastle.util.Arrays;
+
+/**
+ * A <code>TernaryPolynomial</code> with a "low" number of nonzero coefficients.
+ */
+public class SparseTernaryPolynomial
+ implements TernaryPolynomial
+{
+ /**
+ * Number of bits to use for each coefficient. Determines the upper bound for <code>N</code>.
+ */
+ private static final int BITS_PER_INDEX = 11;
+
+ private int N;
+ private int[] ones;
+ private int[] negOnes;
+
+ /**
+ * Constructs a new polynomial.
+ *
+ * @param N total number of coefficients including zeros
+ * @param ones indices of coefficients equal to 1
+ * @param negOnes indices of coefficients equal to -1
+ */
+ SparseTernaryPolynomial(int N, int[] ones, int[] negOnes)
+ {
+ this.N = N;
+ this.ones = ones;
+ this.negOnes = negOnes;
+ }
+
+ /**
+ * Constructs a <code>DenseTernaryPolynomial</code> from a <code>IntegerPolynomial</code>. The two polynomials are
+ * independent of each other.
+ *
+ * @param intPoly the original polynomial
+ */
+ public SparseTernaryPolynomial(IntegerPolynomial intPoly)
+ {
+ this(intPoly.coeffs);
+ }
+
+ /**
+ * Constructs a new <code>SparseTernaryPolynomial</code> with a given set of coefficients.
+ *
+ * @param coeffs the coefficients
+ */
+ public SparseTernaryPolynomial(int[] coeffs)
+ {
+ N = coeffs.length;
+ ones = new int[N];
+ negOnes = new int[N];
+ int onesIdx = 0;
+ int negOnesIdx = 0;
+ for (int i = 0; i < N; i++)
+ {
+ int c = coeffs[i];
+ switch (c)
+ {
+ case 1:
+ ones[onesIdx++] = i;
+ break;
+ case -1:
+ negOnes[negOnesIdx++] = i;
+ break;
+ case 0:
+ break;
+ default:
+ throw new IllegalArgumentException("Illegal value: " + c + ", must be one of {-1, 0, 1}");
+ }
+ }
+ ones = Arrays.copyOf(ones, onesIdx);
+ negOnes = Arrays.copyOf(negOnes, negOnesIdx);
+ }
+
+ /**
+ * Decodes a byte array encoded with {@link #toBinary()} to a ploynomial.
+ *
+ * @param is an input stream containing an encoded polynomial
+ * @param N number of coefficients including zeros
+ * @param numOnes number of coefficients equal to 1
+ * @param numNegOnes number of coefficients equal to -1
+ * @return the decoded polynomial
+ * @throws IOException
+ */
+ public static SparseTernaryPolynomial fromBinary(InputStream is, int N, int numOnes, int numNegOnes)
+ throws IOException
+ {
+ int maxIndex = 1 << BITS_PER_INDEX;
+ int bitsPerIndex = 32 - Integer.numberOfLeadingZeros(maxIndex - 1);
+
+ int data1Len = (numOnes * bitsPerIndex + 7) / 8;
+ byte[] data1 = Util.readFullLength(is, data1Len);
+ int[] ones = ArrayEncoder.decodeModQ(data1, numOnes, maxIndex);
+
+ int data2Len = (numNegOnes * bitsPerIndex + 7) / 8;
+ byte[] data2 = Util.readFullLength(is, data2Len);
+ int[] negOnes = ArrayEncoder.decodeModQ(data2, numNegOnes, maxIndex);
+
+ return new SparseTernaryPolynomial(N, ones, negOnes);
+ }
+
+ /**
+ * Generates a random polynomial with <code>numOnes</code> coefficients equal to 1,
+ * <code>numNegOnes</code> coefficients equal to -1, and the rest equal to 0.
+ *
+ * @param N number of coefficients
+ * @param numOnes number of 1's
+ * @param numNegOnes number of -1's
+ */
+ public static SparseTernaryPolynomial generateRandom(int N, int numOnes, int numNegOnes, SecureRandom random)
+ {
+ int[] coeffs = Util.generateRandomTernary(N, numOnes, numNegOnes, random);
+ return new SparseTernaryPolynomial(coeffs);
+ }
+
+ public IntegerPolynomial mult(IntegerPolynomial poly2)
+ {
+ int[] b = poly2.coeffs;
+ if (b.length != N)
+ {
+ throw new IllegalArgumentException("Number of coefficients must be the same");
+ }
+
+ int[] c = new int[N];
+ for (int idx = 0; idx != ones.length; idx++)
+ {
+ int i = ones[idx];
+ int j = N - 1 - i;
+ for (int k = N - 1; k >= 0; k--)
+ {
+ c[k] += b[j];
+ j--;
+ if (j < 0)
+ {
+ j = N - 1;
+ }
+ }
+ }
+
+ for (int idx = 0; idx != negOnes.length; idx++)
+ {
+ int i = negOnes[idx];
+ int j = N - 1 - i;
+ for (int k = N - 1; k >= 0; k--)
+ {
+ c[k] -= b[j];
+ j--;
+ if (j < 0)
+ {
+ j = N - 1;
+ }
+ }
+ }
+
+ return new IntegerPolynomial(c);
+ }
+
+ public IntegerPolynomial mult(IntegerPolynomial poly2, int modulus)
+ {
+ IntegerPolynomial c = mult(poly2);
+ c.mod(modulus);
+ return c;
+ }
+
+ public BigIntPolynomial mult(BigIntPolynomial poly2)
+ {
+ BigInteger[] b = poly2.coeffs;
+ if (b.length != N)
+ {
+ throw new IllegalArgumentException("Number of coefficients must be the same");
+ }
+
+ BigInteger[] c = new BigInteger[N];
+ for (int i = 0; i < N; i++)
+ {
+ c[i] = BigInteger.ZERO;
+ }
+
+ for (int idx = 0; idx != ones.length; idx++)
+ {
+ int i = ones[idx];
+ int j = N - 1 - i;
+ for (int k = N - 1; k >= 0; k--)
+ {
+ c[k] = c[k].add(b[j]);
+ j--;
+ if (j < 0)
+ {
+ j = N - 1;
+ }
+ }
+ }
+
+ for (int idx = 0; idx != negOnes.length; idx++)
+ {
+ int i = negOnes[idx];
+ int j = N - 1 - i;
+ for (int k = N - 1; k >= 0; k--)
+ {
+ c[k] = c[k].subtract(b[j]);
+ j--;
+ if (j < 0)
+ {
+ j = N - 1;
+ }
+ }
+ }
+
+ return new BigIntPolynomial(c);
+ }
+
+ public int[] getOnes()
+ {
+ return ones;
+ }
+
+ public int[] getNegOnes()
+ {
+ return negOnes;
+ }
+
+ /**
+ * Encodes the polynomial to a byte array writing <code>BITS_PER_INDEX</code> bits for each coefficient.
+ *
+ * @return the encoded polynomial
+ */
+ public byte[] toBinary()
+ {
+ int maxIndex = 1 << BITS_PER_INDEX;
+ byte[] bin1 = ArrayEncoder.encodeModQ(ones, maxIndex);
+ byte[] bin2 = ArrayEncoder.encodeModQ(negOnes, maxIndex);
+
+ byte[] bin = Arrays.copyOf(bin1, bin1.length + bin2.length);
+ System.arraycopy(bin2, 0, bin, bin1.length, bin2.length);
+ return bin;
+ }
+
+ public IntegerPolynomial toIntegerPolynomial()
+ {
+ int[] coeffs = new int[N];
+ for (int idx = 0; idx != ones.length; idx++)
+ {
+ int i = ones[idx];
+ coeffs[i] = 1;
+ }
+ for (int idx = 0; idx != negOnes.length; idx++)
+ {
+ int i = negOnes[idx];
+ coeffs[i] = -1;
+ }
+ return new IntegerPolynomial(coeffs);
+ }
+
+ public int size()
+ {
+ return N;
+ }
+
+ public void clear()
+ {
+ for (int i = 0; i < ones.length; i++)
+ {
+ ones[i] = 0;
+ }
+ for (int i = 0; i < negOnes.length; i++)
+ {
+ negOnes[i] = 0;
+ }
+ }
+
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + N;
+ result = prime * result + Arrays.hashCode(negOnes);
+ result = prime * result + Arrays.hashCode(ones);
+ return result;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+ SparseTernaryPolynomial other = (SparseTernaryPolynomial)obj;
+ if (N != other.N)
+ {
+ return false;
+ }
+ if (!Arrays.areEqual(negOnes, other.negOnes))
+ {
+ return false;
+ }
+ if (!Arrays.areEqual(ones, other.ones))
+ {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/TernaryPolynomial.java b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/TernaryPolynomial.java
new file mode 100644
index 00000000..6b9530b3
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/TernaryPolynomial.java
@@ -0,0 +1,25 @@
+package org.spongycastle.pqc.math.ntru.polynomial;
+
+/**
+ * A polynomial whose coefficients are all equal to -1, 0, or 1
+ */
+public interface TernaryPolynomial
+ extends Polynomial
+{
+
+ /**
+ * Multiplies the polynomial by an <code>IntegerPolynomial</code>, taking the indices mod N
+ */
+ IntegerPolynomial mult(IntegerPolynomial poly2);
+
+ int[] getOnes();
+
+ int[] getNegOnes();
+
+ /**
+ * Returns the maximum number of coefficients the polynomial can have
+ */
+ int size();
+
+ void clear();
+}
diff --git a/core/src/main/java/org/spongycastle/pqc/math/ntru/util/ArrayEncoder.java b/core/src/main/java/org/spongycastle/pqc/math/ntru/util/ArrayEncoder.java
new file mode 100644
index 00000000..c4888cfc
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/ntru/util/ArrayEncoder.java
@@ -0,0 +1,292 @@
+package org.spongycastle.pqc.math.ntru.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+
+import org.spongycastle.util.Arrays;
+
+/**
+ * Converts a coefficient array to a compact byte array and vice versa.
+ */
+public class ArrayEncoder
+{
+ /**
+ * Bit string to coefficient conversion table from P1363.1. Also found at
+ * {@link http://stackoverflow.com/questions/1562548/how-to-make-a-message-into-a-polynomial}
+ * <p/>
+ * Convert each three-bit quantity to two ternary coefficients as follows, and concatenate the resulting
+ * ternary quantities to obtain [the output].
+ * <p/>
+ * <code>
+ * {0, 0, 0} -> {0, 0}<br/>
+ * {0, 0, 1} -> {0, 1}<br/>
+ * {0, 1, 0} -> {0, -1}<br/>
+ * {0, 1, 1} -> {1, 0}<br/>
+ * {1, 0, 0} -> {1, 1}<br/>
+ * {1, 0, 1} -> {1, -1}<br/>
+ * {1, 1, 0} -> {-1, 0}<br/>
+ * {1, 1, 1} -> {-1, 1}<br/>
+ * </code>
+ */
+ private static final int[] COEFF1_TABLE = {0, 0, 0, 1, 1, 1, -1, -1};
+ private static final int[] COEFF2_TABLE = {0, 1, -1, 0, 1, -1, 0, 1};
+ /**
+ * Coefficient to bit string conversion table from P1363.1. Also found at
+ * {@link http://stackoverflow.com/questions/1562548/how-to-make-a-message-into-a-polynomial}
+ * <p/>
+ * Convert each set of two ternary coefficients to three bits as follows, and concatenate the resulting bit
+ * quantities to obtain [the output]:
+ * <p/>
+ * <code>
+ * {-1, -1} -> set "fail" to 1 and set bit string to {1, 1, 1}
+ * {-1, 0} -> {1, 1, 0}<br/>
+ * {-1, 1} -> {1, 1, 1}<br/>
+ * {0, -1} -> {0, 1, 0}<br/>
+ * {0, 0} -> {0, 0, 0}<br/>
+ * {0, 1} -> {0, 0, 1}<br/>
+ * {1, -1} -> {1, 0, 1}<br/>
+ * {1, 0} -> {0, 1, 1}<br/>
+ * {1, 1} -> {1, 0, 0}<br/>
+ * </code>
+ */
+ private static final int[] BIT1_TABLE = {1, 1, 1, 0, 0, 0, 1, 0, 1};
+ private static final int[] BIT2_TABLE = {1, 1, 1, 1, 0, 0, 0, 1, 0};
+ private static final int[] BIT3_TABLE = {1, 0, 1, 0, 0, 1, 1, 1, 0};
+
+ /**
+ * Encodes an int array whose elements are between 0 and <code>q</code>,
+ * to a byte array leaving no gaps between bits.<br>
+ * <code>q</code> must be a power of 2.
+ *
+ * @param a the input array
+ * @param q the modulus
+ * @return the encoded array
+ */
+ public static byte[] encodeModQ(int[] a, int q)
+ {
+ int bitsPerCoeff = 31 - Integer.numberOfLeadingZeros(q);
+ int numBits = a.length * bitsPerCoeff;
+ int numBytes = (numBits + 7) / 8;
+ byte[] data = new byte[numBytes];
+ int bitIndex = 0;
+ int byteIndex = 0;
+ for (int i = 0; i < a.length; i++)
+ {
+ for (int j = 0; j < bitsPerCoeff; j++)
+ {
+ int currentBit = (a[i] >> j) & 1;
+ data[byteIndex] |= currentBit << bitIndex;
+ if (bitIndex == 7)
+ {
+ bitIndex = 0;
+ byteIndex++;
+ }
+ else
+ {
+ bitIndex++;
+ }
+ }
+ }
+ return data;
+ }
+
+ /**
+ * Decodes a <code>byte</code> array encoded with {@link #encodeModQ(int[], int)} back to an <code>int</code> array.<br>
+ * <code>N</code> is the number of coefficients. <code>q</code> must be a power of <code>2</code>.<br>
+ * Ignores any excess bytes.
+ *
+ * @param data an encoded ternary polynomial
+ * @param N number of coefficients
+ * @param q
+ * @return an array containing <code>N</code> coefficients between <code>0</code> and <code>q-1</code>
+ */
+ public static int[] decodeModQ(byte[] data, int N, int q)
+ {
+ int[] coeffs = new int[N];
+ int bitsPerCoeff = 31 - Integer.numberOfLeadingZeros(q);
+ int numBits = N * bitsPerCoeff;
+ int coeffIndex = 0;
+ for (int bitIndex = 0; bitIndex < numBits; bitIndex++)
+ {
+ if (bitIndex > 0 && bitIndex % bitsPerCoeff == 0)
+ {
+ coeffIndex++;
+ }
+ int bit = getBit(data, bitIndex);
+ coeffs[coeffIndex] += bit << (bitIndex % bitsPerCoeff);
+ }
+ return coeffs;
+ }
+
+ /**
+ * Decodes data encoded with {@link #encodeModQ(int[], int)} back to an <code>int</code> array.<br>
+ * <code>N</code> is the number of coefficients. <code>q</code> must be a power of <code>2</code>.<br>
+ * Ignores any excess bytes.
+ *
+ * @param is an encoded ternary polynomial
+ * @param N number of coefficients
+ * @param q
+ * @return the decoded polynomial
+ */
+ public static int[] decodeModQ(InputStream is, int N, int q)
+ throws IOException
+ {
+ int qBits = 31 - Integer.numberOfLeadingZeros(q);
+ int size = (N * qBits + 7) / 8;
+ byte[] arr = Util.readFullLength(is, size);
+ return decodeModQ(arr, N, q);
+ }
+
+ /**
+ * Decodes a <code>byte</code> array encoded with {@link #encodeMod3Sves(int[])} back to an <code>int</code> array
+ * with <code>N</code> coefficients between <code>-1</code> and <code>1</code>.<br>
+ * Ignores any excess bytes.<br>
+ * See P1363.1 section 9.2.2.
+ *
+ * @param data an encoded ternary polynomial
+ * @param N number of coefficients
+ * @return the decoded coefficients
+ */
+ public static int[] decodeMod3Sves(byte[] data, int N)
+ {
+ int[] coeffs = new int[N];
+ int coeffIndex = 0;
+ for (int bitIndex = 0; bitIndex < data.length * 8; )
+ {
+ int bit1 = getBit(data, bitIndex++);
+ int bit2 = getBit(data, bitIndex++);
+ int bit3 = getBit(data, bitIndex++);
+ int coeffTableIndex = bit1 * 4 + bit2 * 2 + bit3;
+ coeffs[coeffIndex++] = COEFF1_TABLE[coeffTableIndex];
+ coeffs[coeffIndex++] = COEFF2_TABLE[coeffTableIndex];
+ // ignore bytes that can't fit
+ if (coeffIndex > N - 2)
+ {
+ break;
+ }
+ }
+ return coeffs;
+ }
+
+ /**
+ * Encodes an <code>int</code> array whose elements are between <code>-1</code> and <code>1</code>, to a byte array.
+ * <code>coeffs[2*i]</code> and <code>coeffs[2*i+1]</code> must not both equal -1 for any integer <code>i</code>,
+ * so this method is only safe to use with arrays produced by {@link #decodeMod3Sves(byte[], int)}.<br>
+ * See P1363.1 section 9.2.3.
+ *
+ * @param arr
+ * @return the encoded array
+ */
+ public static byte[] encodeMod3Sves(int[] arr)
+ {
+ int numBits = (arr.length * 3 + 1) / 2;
+ int numBytes = (numBits + 7) / 8;
+ byte[] data = new byte[numBytes];
+ int bitIndex = 0;
+ int byteIndex = 0;
+ for (int i = 0; i < arr.length / 2 * 2; )
+ { // if length is an odd number, throw away the highest coeff
+ int coeff1 = arr[i++] + 1;
+ int coeff2 = arr[i++] + 1;
+ if (coeff1 == 0 && coeff2 == 0)
+ {
+ throw new IllegalStateException("Illegal encoding!");
+ }
+ int bitTableIndex = coeff1 * 3 + coeff2;
+ int[] bits = new int[]{BIT1_TABLE[bitTableIndex], BIT2_TABLE[bitTableIndex], BIT3_TABLE[bitTableIndex]};
+ for (int j = 0; j < 3; j++)
+ {
+ data[byteIndex] |= bits[j] << bitIndex;
+ if (bitIndex == 7)
+ {
+ bitIndex = 0;
+ byteIndex++;
+ }
+ else
+ {
+ bitIndex++;
+ }
+ }
+ }
+ return data;
+ }
+
+ /**
+ * Encodes an <code>int</code> array whose elements are between <code>-1</code> and <code>1</code>, to a byte array.
+ *
+ * @return the encoded array
+ */
+ public static byte[] encodeMod3Tight(int[] intArray)
+ {
+ BigInteger sum = BigInteger.ZERO;
+ for (int i = intArray.length - 1; i >= 0; i--)
+ {
+ sum = sum.multiply(BigInteger.valueOf(3));
+ sum = sum.add(BigInteger.valueOf(intArray[i] + 1));
+ }
+
+ int size = (BigInteger.valueOf(3).pow(intArray.length).bitLength() + 7) / 8;
+ byte[] arr = sum.toByteArray();
+
+ if (arr.length < size)
+ {
+ // pad with leading zeros so arr.length==size
+ byte[] arr2 = new byte[size];
+ System.arraycopy(arr, 0, arr2, size - arr.length, arr.length);
+ return arr2;
+ }
+
+ if (arr.length > size)
+ // drop sign bit
+ {
+ arr = Arrays.copyOfRange(arr, 1, arr.length);
+ }
+ return arr;
+ }
+
+ /**
+ * Converts a byte array produced by {@link #encodeMod3Tight(int[])} back to an <code>int</code> array.
+ *
+ * @param b a byte array
+ * @param N number of coefficients
+ * @return the decoded array
+ */
+ public static int[] decodeMod3Tight(byte[] b, int N)
+ {
+ BigInteger sum = new BigInteger(1, b);
+ int[] coeffs = new int[N];
+ for (int i = 0; i < N; i++)
+ {
+ coeffs[i] = sum.mod(BigInteger.valueOf(3)).intValue() - 1;
+ if (coeffs[i] > 1)
+ {
+ coeffs[i] -= 3;
+ }
+ sum = sum.divide(BigInteger.valueOf(3));
+ }
+ return coeffs;
+ }
+
+ /**
+ * Converts data produced by {@link #encodeMod3Tight(int[])} back to an <code>int</code> array.
+ *
+ * @param is an input stream containing the data to decode
+ * @param N number of coefficients
+ * @return the decoded array
+ */
+ public static int[] decodeMod3Tight(InputStream is, int N)
+ throws IOException
+ {
+ int size = (int)Math.ceil(N * Math.log(3) / Math.log(2) / 8);
+ byte[] arr = Util.readFullLength(is, size);
+ return decodeMod3Tight(arr, N);
+ }
+
+ private static int getBit(byte[] arr, int bitIndex)
+ {
+ int byteIndex = bitIndex / 8;
+ int arrElem = arr[byteIndex] & 0xFF;
+ return (arrElem >> (bitIndex % 8)) & 1;
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/pqc/math/ntru/util/Util.java b/core/src/main/java/org/spongycastle/pqc/math/ntru/util/Util.java
new file mode 100644
index 00000000..b07e1cb8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/pqc/math/ntru/util/Util.java
@@ -0,0 +1,158 @@
+package org.spongycastle.pqc.math.ntru.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.spongycastle.pqc.math.ntru.euclid.IntEuclidean;
+import org.spongycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.TernaryPolynomial;
+import org.spongycastle.util.Integers;
+
+public class Util
+{
+ private static volatile boolean IS_64_BITNESS_KNOWN;
+ private static volatile boolean IS_64_BIT_JVM;
+
+ /**
+ * Calculates the inverse of n mod modulus
+ */
+ public static int invert(int n, int modulus)
+ {
+ n %= modulus;
+ if (n < 0)
+ {
+ n += modulus;
+ }
+ return IntEuclidean.calculate(n, modulus).x;
+ }
+
+ /**
+ * Calculates a^b mod modulus
+ */
+ public static int pow(int a, int b, int modulus)
+ {
+ int p = 1;
+ for (int i = 0; i < b; i++)
+ {
+ p = (p * a) % modulus;
+ }
+ return p;
+ }
+
+ /**
+ * Calculates a^b mod modulus
+ */
+ public static long pow(long a, int b, long modulus)
+ {
+ long p = 1;
+ for (int i = 0; i < b; i++)
+ {
+ p = (p * a) % modulus;
+ }
+ return p;
+ }
+
+ /**
+ * Generates a "sparse" or "dense" polynomial containing numOnes ints equal to 1,
+ * numNegOnes int equal to -1, and the rest equal to 0.
+ *
+ * @param N
+ * @param numOnes
+ * @param numNegOnes
+ * @param sparse whether to create a {@link SparseTernaryPolynomial} or {@link DenseTernaryPolynomial}
+ * @return a ternary polynomial
+ */
+ public static TernaryPolynomial generateRandomTernary(int N, int numOnes, int numNegOnes, boolean sparse, SecureRandom random)
+ {
+ if (sparse)
+ {
+ return SparseTernaryPolynomial.generateRandom(N, numOnes, numNegOnes, random);
+ }
+ else
+ {
+ return DenseTernaryPolynomial.generateRandom(N, numOnes, numNegOnes, random);
+ }
+ }
+
+ /**
+ * Generates an array containing numOnes ints equal to 1,
+ * numNegOnes int equal to -1, and the rest equal to 0.
+ *
+ * @param N
+ * @param numOnes
+ * @param numNegOnes
+ * @return an array of integers
+ */
+ public static int[] generateRandomTernary(int N, int numOnes, int numNegOnes, SecureRandom random)
+ {
+ Integer one = Integers.valueOf(1);
+ Integer minusOne = Integers.valueOf(-1);
+ Integer zero = Integers.valueOf(0);
+
+ List list = new ArrayList();
+ for (int i = 0; i < numOnes; i++)
+ {
+ list.add(one);
+ }
+ for (int i = 0; i < numNegOnes; i++)
+ {
+ list.add(minusOne);
+ }
+ while (list.size() < N)
+ {
+ list.add(zero);
+ }
+
+ Collections.shuffle(list, random);
+
+ int[] arr = new int[N];
+ for (int i = 0; i < N; i++)
+ {
+ arr[i] = ((Integer)list.get(i)).intValue();
+ }
+ return arr;
+ }
+
+ /**
+ * Takes an educated guess as to whether 64 bits are supported by the JVM.
+ *
+ * @return <code>true</code> if 64-bit support detected, <code>false</code> otherwise
+ */
+ public static boolean is64BitJVM()
+ {
+ if (!IS_64_BITNESS_KNOWN)
+ {
+ String arch = System.getProperty("os.arch");
+ String sunModel = System.getProperty("sun.arch.data.model");
+ IS_64_BIT_JVM = "amd64".equals(arch) || "x86_64".equals(arch) || "ppc64".equals(arch) || "64".equals(sunModel);
+ IS_64_BITNESS_KNOWN = true;
+ }
+ return IS_64_BIT_JVM;
+ }
+
+ /**
+ * Reads a given number of bytes from an <code>InputStream</code>.
+ * If there are not enough bytes in the stream, an <code>IOException</code>
+ * is thrown.
+ *
+ * @param is
+ * @param length
+ * @return an array of length <code>length</code>
+ * @throws IOException
+ */
+ public static byte[] readFullLength(InputStream is, int length)
+ throws IOException
+ {
+ byte[] arr = new byte[length];
+ if (is.read(arr) != arr.length)
+ {
+ throw new IOException("Not enough bytes to read.");
+ }
+ return arr;
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/util/Arrays.java b/core/src/main/java/org/spongycastle/util/Arrays.java
new file mode 100644
index 00000000..a847f721
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/Arrays.java
@@ -0,0 +1,971 @@
+package org.spongycastle.util;
+
+import java.math.BigInteger;
+
+/**
+ * General array utilities.
+ */
+public final class Arrays
+{
+ private Arrays()
+ {
+ // static class, hide constructor
+ }
+
+ public static boolean areEqual(
+ boolean[] a,
+ boolean[] 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] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static boolean areEqual(
+ char[] a,
+ char[] 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] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static boolean areEqual(
+ byte[] a,
+ byte[] 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] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * A constant time equals comparison - does not terminate early if
+ * test will fail.
+ *
+ * @param a first array
+ * @param b second array
+ * @return true if arrays equal, false otherwise.
+ */
+ public static boolean constantTimeAreEqual(
+ byte[] a,
+ byte[] b)
+ {
+ if (a == b)
+ {
+ return true;
+ }
+
+ if (a == null || b == null)
+ {
+ return false;
+ }
+
+ if (a.length != b.length)
+ {
+ return false;
+ }
+
+ int nonEqual = 0;
+
+ for (int i = 0; i != a.length; i++)
+ {
+ nonEqual |= (a[i] ^ b[i]);
+ }
+
+ return nonEqual == 0;
+ }
+
+ public static boolean areEqual(
+ int[] a,
+ int[] 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] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static boolean areEqual(
+ long[] a,
+ long[] 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] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ 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++)
+ {
+ 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)
+ {
+ for (int i = 0; i < array.length; i++)
+ {
+ array[i] = value;
+ }
+ }
+
+ public static void fill(
+ char[] array,
+ char value)
+ {
+ for (int i = 0; i < array.length; i++)
+ {
+ array[i] = value;
+ }
+ }
+
+ public static void fill(
+ long[] array,
+ long value)
+ {
+ for (int i = 0; i < array.length; i++)
+ {
+ array[i] = value;
+ }
+ }
+
+ public static void fill(
+ short[] array,
+ short value)
+ {
+ for (int i = 0; i < array.length; i++)
+ {
+ array[i] = value;
+ }
+ }
+
+ public static void fill(
+ int[] array,
+ int value)
+ {
+ for (int i = 0; i < array.length; i++)
+ {
+ array[i] = value;
+ }
+ }
+
+ public static int hashCode(byte[] data)
+ {
+ if (data == null)
+ {
+ return 0;
+ }
+
+ int i = data.length;
+ int hc = i + 1;
+
+ while (--i >= 0)
+ {
+ hc *= 257;
+ hc ^= data[i];
+ }
+
+ return hc;
+ }
+
+ public static int hashCode(byte[] data, int off, int len)
+ {
+ if (data == null)
+ {
+ return 0;
+ }
+
+ int i = len;
+ int hc = i + 1;
+
+ while (--i >= 0)
+ {
+ hc *= 257;
+ hc ^= data[off + i];
+ }
+
+ return hc;
+ }
+
+ public static int hashCode(char[] data)
+ {
+ if (data == null)
+ {
+ return 0;
+ }
+
+ int i = data.length;
+ int hc = i + 1;
+
+ while (--i >= 0)
+ {
+ hc *= 257;
+ hc ^= data[i];
+ }
+
+ return hc;
+ }
+
+ public static int hashCode(int[][] ints)
+ {
+ int hc = 0;
+
+ for (int i = 0; i != ints.length; i++)
+ {
+ hc = hc * 257 + hashCode(ints[i]);
+ }
+
+ return hc;
+ }
+
+ public static int hashCode(int[] data)
+ {
+ if (data == null)
+ {
+ return 0;
+ }
+
+ int i = data.length;
+ int hc = i + 1;
+
+ while (--i >= 0)
+ {
+ hc *= 257;
+ hc ^= data[i];
+ }
+
+ return hc;
+ }
+
+ public static int hashCode(int[] data, int off, int len)
+ {
+ if (data == null)
+ {
+ return 0;
+ }
+
+ int i = len;
+ int hc = i + 1;
+
+ while (--i >= 0)
+ {
+ hc *= 257;
+ hc ^= data[off + i];
+ }
+
+ return hc;
+ }
+
+ public static int hashCode(short[][][] shorts)
+ {
+ int hc = 0;
+
+ for (int i = 0; i != shorts.length; i++)
+ {
+ hc = hc * 257 + hashCode(shorts[i]);
+ }
+
+ return hc;
+ }
+
+ public static int hashCode(short[][] shorts)
+ {
+ int hc = 0;
+
+ for (int i = 0; i != shorts.length; i++)
+ {
+ hc = hc * 257 + hashCode(shorts[i]);
+ }
+
+ return hc;
+ }
+
+ public static int hashCode(short[] data)
+ {
+ if (data == null)
+ {
+ return 0;
+ }
+
+ int i = data.length;
+ int hc = i + 1;
+
+ while (--i >= 0)
+ {
+ hc *= 257;
+ hc ^= (data[i] & 0xff);
+ }
+
+ return hc;
+ }
+
+ public static int hashCode(Object[] data)
+ {
+ if (data == null)
+ {
+ return 0;
+ }
+
+ int i = data.length;
+ int hc = i + 1;
+
+ while (--i >= 0)
+ {
+ hc *= 257;
+ hc ^= data[i].hashCode();
+ }
+
+ return hc;
+ }
+
+ public static byte[] clone(byte[] data)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ byte[] copy = new byte[data.length];
+
+ System.arraycopy(data, 0, copy, 0, data.length);
+
+ 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)
+ {
+ return null;
+ }
+
+ byte[][] copy = new byte[data.length][];
+
+ for (int i = 0; i != copy.length; i++)
+ {
+ copy[i] = clone(data[i]);
+ }
+
+ return copy;
+ }
+
+ public static byte[][][] clone(byte[][][] data)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+
+ byte[][][] copy = new byte[data.length][][];
+
+ for (int i = 0; i != copy.length; i++)
+ {
+ copy[i] = clone(data[i]);
+ }
+
+ return copy;
+ }
+
+ public static int[] clone(int[] data)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ int[] copy = new int[data.length];
+
+ System.arraycopy(data, 0, copy, 0, data.length);
+
+ 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)
+ {
+ return null;
+ }
+ short[] copy = new short[data.length];
+
+ System.arraycopy(data, 0, copy, 0, data.length);
+
+ return copy;
+ }
+
+ public static BigInteger[] clone(BigInteger[] data)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ BigInteger[] copy = new BigInteger[data.length];
+
+ System.arraycopy(data, 0, copy, 0, data.length);
+
+ return copy;
+ }
+
+ public static byte[] copyOf(byte[] data, int newLength)
+ {
+ byte[] tmp = new byte[newLength];
+
+ if (newLength < data.length)
+ {
+ System.arraycopy(data, 0, tmp, 0, newLength);
+ }
+ else
+ {
+ System.arraycopy(data, 0, tmp, 0, data.length);
+ }
+
+ return tmp;
+ }
+
+ public static char[] copyOf(char[] data, int newLength)
+ {
+ char[] tmp = new char[newLength];
+
+ if (newLength < data.length)
+ {
+ System.arraycopy(data, 0, tmp, 0, newLength);
+ }
+ else
+ {
+ System.arraycopy(data, 0, tmp, 0, data.length);
+ }
+
+ return tmp;
+ }
+
+ public static int[] copyOf(int[] data, int newLength)
+ {
+ int[] tmp = new int[newLength];
+
+ if (newLength < data.length)
+ {
+ System.arraycopy(data, 0, tmp, 0, newLength);
+ }
+ else
+ {
+ System.arraycopy(data, 0, tmp, 0, data.length);
+ }
+
+ return tmp;
+ }
+
+ public static long[] copyOf(long[] data, int newLength)
+ {
+ long[] tmp = new long[newLength];
+
+ if (newLength < data.length)
+ {
+ System.arraycopy(data, 0, tmp, 0, newLength);
+ }
+ else
+ {
+ System.arraycopy(data, 0, tmp, 0, data.length);
+ }
+
+ return tmp;
+ }
+
+ public static BigInteger[] copyOf(BigInteger[] data, int newLength)
+ {
+ BigInteger[] tmp = new BigInteger[newLength];
+
+ if (newLength < data.length)
+ {
+ System.arraycopy(data, 0, tmp, 0, newLength);
+ }
+ else
+ {
+ System.arraycopy(data, 0, tmp, 0, data.length);
+ }
+
+ 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);
+
+ byte[] tmp = new byte[newLength];
+
+ if (data.length - from < newLength)
+ {
+ System.arraycopy(data, from, tmp, 0, data.length - from);
+ }
+ else
+ {
+ System.arraycopy(data, from, tmp, 0, newLength);
+ }
+
+ return tmp;
+ }
+
+ public static int[] copyOfRange(int[] data, int from, int to)
+ {
+ int newLength = getLength(from, to);
+
+ int[] tmp = new int[newLength];
+
+ if (data.length - from < newLength)
+ {
+ System.arraycopy(data, from, tmp, 0, data.length - from);
+ }
+ else
+ {
+ System.arraycopy(data, from, tmp, 0, newLength);
+ }
+
+ return tmp;
+ }
+
+ public static long[] copyOfRange(long[] data, int from, int to)
+ {
+ int newLength = getLength(from, to);
+
+ long[] tmp = new long[newLength];
+
+ if (data.length - from < newLength)
+ {
+ System.arraycopy(data, from, tmp, 0, data.length - from);
+ }
+ else
+ {
+ System.arraycopy(data, from, tmp, 0, newLength);
+ }
+
+ return tmp;
+ }
+
+ public static BigInteger[] copyOfRange(BigInteger[] data, int from, int to)
+ {
+ int newLength = getLength(from, to);
+
+ BigInteger[] tmp = new BigInteger[newLength];
+
+ if (data.length - from < newLength)
+ {
+ System.arraycopy(data, from, tmp, 0, data.length - from);
+ }
+ else
+ {
+ System.arraycopy(data, from, tmp, 0, newLength);
+ }
+
+ return tmp;
+ }
+
+ private static int getLength(int from, int to)
+ {
+ int newLength = to - from;
+ if (newLength < 0)
+ {
+ StringBuffer sb = new StringBuffer(from);
+ sb.append(" > ").append(to);
+ throw new IllegalArgumentException(sb.toString());
+ }
+ 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 short[] append(short[] a, short b)
+ {
+ if (a == null)
+ {
+ return new short[]{ b };
+ }
+
+ int length = a.length;
+ short[] result = new short[length + 1];
+ System.arraycopy(a, 0, result, 0, length);
+ result[length] = b;
+ return result;
+ }
+
+ public static int[] append(int[] a, int b)
+ {
+ if (a == null)
+ {
+ 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)
+ {
+ byte[] rv = new byte[a.length + b.length];
+
+ System.arraycopy(a, 0, rv, 0, a.length);
+ System.arraycopy(b, 0, rv, a.length, b.length);
+
+ return rv;
+ }
+ else if (b != null)
+ {
+ return clone(b);
+ }
+ else
+ {
+ return clone(a);
+ }
+ }
+
+ public static byte[] concatenate(byte[] a, byte[] b, byte[] c)
+ {
+ if (a != null && b != null && c != null)
+ {
+ byte[] rv = new byte[a.length + b.length + c.length];
+
+ System.arraycopy(a, 0, rv, 0, a.length);
+ System.arraycopy(b, 0, rv, a.length, b.length);
+ System.arraycopy(c, 0, rv, a.length + b.length, c.length);
+
+ return rv;
+ }
+ else if (b == null)
+ {
+ return concatenate(a, c);
+ }
+ else
+ {
+ return concatenate(a, b);
+ }
+ }
+
+ public static byte[] concatenate(byte[] a, byte[] b, byte[] c, byte[] d)
+ {
+ if (a != null && b != null && c != null && d != null)
+ {
+ byte[] rv = new byte[a.length + b.length + c.length + d.length];
+
+ System.arraycopy(a, 0, rv, 0, a.length);
+ System.arraycopy(b, 0, rv, a.length, b.length);
+ System.arraycopy(c, 0, rv, a.length + b.length, c.length);
+ System.arraycopy(d, 0, rv, a.length + b.length + c.length, d.length);
+
+ return rv;
+ }
+ else if (d == null)
+ {
+ return concatenate(a, b, c);
+ }
+ else if (c == null)
+ {
+ return concatenate(a, b, d);
+ }
+ else if (b == null)
+ {
+ return concatenate(a, c, d);
+ }
+ else
+ {
+ return concatenate(b, c, d);
+ }
+ }
+
+ public static int[] concatenate(int[] a, int[] b)
+ {
+ if (a == null)
+ {
+ return clone(b);
+ }
+ if (b == null)
+ {
+ return clone(a);
+ }
+
+ int[] c = new int[a.length + b.length];
+ System.arraycopy(a, 0, c, 0, a.length);
+ System.arraycopy(b, 0, c, a.length, b.length);
+ return c;
+ }
+
+ public static byte[] prepend(byte[] a, byte b)
+ {
+ if (a == null)
+ {
+ 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;
+ }
+
+ public static short[] prepend(short[] a, short b)
+ {
+ if (a == null)
+ {
+ return new short[]{ b };
+ }
+
+ int length = a.length;
+ short[] result = new short[length + 1];
+ System.arraycopy(a, 0, result, 1, length);
+ result[0] = b;
+ return result;
+ }
+
+ public static int[] prepend(int[] a, int b)
+ {
+ if (a == null)
+ {
+ return new int[]{ b };
+ }
+
+ int length = a.length;
+ int[] result = new int[length + 1];
+ System.arraycopy(a, 0, result, 1, length);
+ result[0] = b;
+ return result;
+ }
+
+ public static byte[] reverse(byte[] a)
+ {
+ if (a == null)
+ {
+ return null;
+ }
+
+ int p1 = 0, p2 = a.length;
+ byte[] result = new byte[p2];
+
+ while (--p2 >= 0)
+ {
+ result[p2] = a[p1++];
+ }
+
+ return result;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/BigIntegers.java b/core/src/main/java/org/spongycastle/util/BigIntegers.java
new file mode 100644
index 00000000..93c11347
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/BigIntegers.java
@@ -0,0 +1,121 @@
+package org.spongycastle.util;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * BigInteger utilities.
+ */
+public final class BigIntegers
+{
+ private static final int MAX_ITERATIONS = 1000;
+ private static final BigInteger ZERO = BigInteger.valueOf(0);
+
+ /**
+ * Return the passed in value as an unsigned byte array.
+ *
+ * @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(
+ BigInteger value)
+ {
+ byte[] bytes = value.toByteArray();
+
+ if (bytes[0] == 0)
+ {
+ byte[] tmp = new byte[bytes.length - 1];
+
+ System.arraycopy(bytes, 1, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+
+ return bytes;
+ }
+
+ /**
+ * Return the passed in value as an unsigned byte array.
+ *
+ * @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)
+ {
+ byte[] bytes = value.toByteArray();
+ if (bytes.length == length)
+ {
+ return bytes;
+ }
+
+ int start = bytes[0] == 0 ? 1 : 0;
+ int count = bytes.length - start;
+
+ 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;
+ }
+
+ /**
+ * Return a random BigInteger not less than 'min' and not greater than 'max'
+ *
+ * @param min the least value that may be generated
+ * @param max the greatest value that may be generated
+ * @param random the source of randomness
+ * @return a random BigInteger value in the range [min,max]
+ */
+ public static BigInteger createRandomInRange(
+ BigInteger min,
+ BigInteger max,
+ SecureRandom random)
+ {
+ int cmp = min.compareTo(max);
+ if (cmp >= 0)
+ {
+ if (cmp > 0)
+ {
+ throw new IllegalArgumentException("'min' may not be greater than 'max'");
+ }
+
+ return min;
+ }
+
+ if (min.bitLength() > max.bitLength() / 2)
+ {
+ return createRandomInRange(ZERO, max.subtract(min), random).add(min);
+ }
+
+ for (int i = 0; i < MAX_ITERATIONS; ++i)
+ {
+ BigInteger x = new BigInteger(max.bitLength(), random);
+ if (x.compareTo(min) >= 0 && x.compareTo(max) <= 0)
+ {
+ return x;
+ }
+ }
+
+ // 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/core/src/main/java/org/spongycastle/util/CollectionStore.java b/core/src/main/java/org/spongycastle/util/CollectionStore.java
new file mode 100644
index 00000000..fa4c9fe5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/CollectionStore.java
@@ -0,0 +1,57 @@
+package org.spongycastle.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * A simple collection backed store.
+ */
+public class CollectionStore
+ implements Store
+{
+ private Collection _local;
+
+ /**
+ * Basic constructor.
+ *
+ * @param collection - initial contents for the store, this is copied.
+ */
+ public CollectionStore(
+ Collection collection)
+ {
+ _local = new ArrayList(collection);
+ }
+
+ /**
+ * Return the matches in the collection for the passed in selector.
+ *
+ * @param selector the selector to match against.
+ * @return a possibly empty collection of matching objects.
+ */
+ public Collection getMatches(Selector selector)
+ {
+ if (selector == null)
+ {
+ return new ArrayList(_local);
+ }
+ else
+ {
+ List col = new ArrayList();
+ Iterator iter = _local.iterator();
+
+ while (iter.hasNext())
+ {
+ Object obj = iter.next();
+
+ if (selector.match(obj))
+ {
+ col.add(obj);
+ }
+ }
+
+ return col;
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/IPAddress.java b/core/src/main/java/org/spongycastle/util/IPAddress.java
new file mode 100644
index 00000000..14c49cad
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/IPAddress.java
@@ -0,0 +1,188 @@
+package org.spongycastle.util;
+
+public class IPAddress
+{
+ /**
+ * Validate the given IPv4 or IPv6 address.
+ *
+ * @param address the IP address as a String.
+ *
+ * @return true if a valid address, false otherwise
+ */
+ public static boolean isValid(
+ String address)
+ {
+ return isValidIPv4(address) || isValidIPv6(address);
+ }
+
+ /**
+ * Validate the given IPv4 or IPv6 address and netmask.
+ *
+ * @param address the IP address as a String.
+ *
+ * @return true if a valid address with netmask, false otherwise
+ */
+ public static boolean isValidWithNetMask(
+ String address)
+ {
+ return isValidIPv4WithNetmask(address) || isValidIPv6WithNetmask(address);
+ }
+
+ /**
+ * Validate the given IPv4 address.
+ *
+ * @param address the IP address as a String.
+ *
+ * @return true if a valid IPv4 address, false otherwise
+ */
+ public static boolean isValidIPv4(
+ String address)
+ {
+ if (address.length() == 0)
+ {
+ return false;
+ }
+
+ int octet;
+ int octets = 0;
+
+ String temp = address+".";
+
+ int pos;
+ int start = 0;
+ while (start < temp.length()
+ && (pos = temp.indexOf('.', start)) > start)
+ {
+ if (octets == 4)
+ {
+ return false;
+ }
+ try
+ {
+ octet = Integer.parseInt(temp.substring(start, pos));
+ }
+ catch (NumberFormatException ex)
+ {
+ return false;
+ }
+ if (octet < 0 || octet > 255)
+ {
+ return false;
+ }
+ start = pos + 1;
+ octets++;
+ }
+
+ return octets == 4;
+ }
+
+ public static boolean isValidIPv4WithNetmask(
+ String address)
+ {
+ int index = address.indexOf("/");
+ String mask = address.substring(index + 1);
+
+ return (index > 0) && isValidIPv4(address.substring(0, index))
+ && (isValidIPv4(mask) || isMaskValue(mask, 32));
+ }
+
+ public static boolean isValidIPv6WithNetmask(
+ String address)
+ {
+ int index = address.indexOf("/");
+ String mask = address.substring(index + 1);
+
+ return (index > 0) && (isValidIPv6(address.substring(0, index))
+ && (isValidIPv6(mask) || isMaskValue(mask, 128)));
+ }
+
+ private static boolean isMaskValue(String component, int size)
+ {
+ try
+ {
+ int value = Integer.parseInt(component);
+
+ return value >= 0 && value <= size;
+ }
+ catch (NumberFormatException e)
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Validate the given IPv6 address.
+ *
+ * @param address the IP address as a String.
+ *
+ * @return true if a valid IPv4 address, false otherwise
+ */
+ public static boolean isValidIPv6(
+ String address)
+ {
+ if (address.length() == 0)
+ {
+ return false;
+ }
+
+ int octet;
+ int octets = 0;
+
+ String temp = address + ":";
+ boolean doubleColonFound = false;
+ int pos;
+ int start = 0;
+ while (start < temp.length()
+ && (pos = temp.indexOf(':', start)) >= start)
+ {
+ if (octets == 8)
+ {
+ return false;
+ }
+
+ if (start != pos)
+ {
+ String value = temp.substring(start, pos);
+
+ if (pos == (temp.length() - 1) && value.indexOf('.') > 0)
+ {
+ if (!isValidIPv4(value))
+ {
+ return false;
+ }
+
+ octets++; // add an extra one as address covers 2 words.
+ }
+ else
+ {
+ try
+ {
+ octet = Integer.parseInt(temp.substring(start, pos), 16);
+ }
+ catch (NumberFormatException ex)
+ {
+ return false;
+ }
+ if (octet < 0 || octet > 0xffff)
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ if (pos != 1 && pos != temp.length() - 1 && doubleColonFound)
+ {
+ return false;
+ }
+ doubleColonFound = true;
+ }
+ start = pos + 1;
+ octets++;
+ }
+
+ return octets == 8 || doubleColonFound;
+ }
+}
+
+
diff --git a/core/src/main/java/org/spongycastle/util/Integers.java b/core/src/main/java/org/spongycastle/util/Integers.java
new file mode 100644
index 00000000..e212c9fc
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/Integers.java
@@ -0,0 +1,19 @@
+package org.spongycastle.util;
+
+public class Integers
+{
+ public static int rotateLeft(int i, int distance)
+ {
+ return Integer.rotateLeft(i, distance);
+ }
+
+ public static int rotateRight(int i, int distance)
+ {
+ return Integer.rotateRight(i, distance);
+ }
+
+ public static Integer valueOf(int value)
+ {
+ return Integer.valueOf(value);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/Memoable.java b/core/src/main/java/org/spongycastle/util/Memoable.java
new file mode 100644
index 00000000..5680c857
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/Memoable.java
@@ -0,0 +1,23 @@
+package org.spongycastle.util;
+
+public interface Memoable
+{
+ /**
+ * Produce a copy of this object with its configuration and in its current state.
+ * <p>
+ * The returned object may be used simply to store the state, or may be used as a similar object
+ * starting from the copied state.
+ */
+ public Memoable copy();
+
+ /**
+ * Restore a copied object state into this object.
+ * <p>
+ * Implementations of this method <em>should</em> try to avoid or minimise memory allocation to perform the reset.
+ *
+ * @param other an object originally {@link #copy() copied} from an object of the same type as this instance.
+ * @throws ClassCastException if the provided object is not of the correct type.
+ * @throws MemoableResetException if the <b>other</b> parameter is in some other way invalid.
+ */
+ public void reset(Memoable other);
+}
diff --git a/core/src/main/java/org/spongycastle/util/MemoableResetException.java b/core/src/main/java/org/spongycastle/util/MemoableResetException.java
new file mode 100644
index 00000000..6d579ed5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/MemoableResetException.java
@@ -0,0 +1,22 @@
+package org.spongycastle.util;
+
+/**
+ * Exception to be thrown on a failure to reset an object implementing Memoable.
+ * <p>
+ * The exception extends ClassCastException to enable users to have a single handling case,
+ * only introducing specific handling of this one if required.
+ * </p>
+ */
+public class MemoableResetException
+ extends ClassCastException
+{
+ /**
+ * Basic Constructor.
+ *
+ * @param msg message to be associated with this exception.
+ */
+ public MemoableResetException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/Pack.java b/core/src/main/java/org/spongycastle/util/Pack.java
new file mode 100644
index 00000000..bad72850
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/Pack.java
@@ -0,0 +1,201 @@
+package org.spongycastle.util;
+
+public abstract class Pack
+{
+ public static int bigEndianToInt(byte[] bs, int off)
+ {
+ int n = bs[ off] << 24;
+ n |= (bs[++off] & 0xff) << 16;
+ n |= (bs[++off] & 0xff) << 8;
+ n |= (bs[++off] & 0xff);
+ return n;
+ }
+
+ public static void bigEndianToInt(byte[] bs, int off, int[] ns)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ ns[i] = bigEndianToInt(bs, off);
+ off += 4;
+ }
+ }
+
+ public static byte[] intToBigEndian(int n)
+ {
+ byte[] bs = new byte[4];
+ intToBigEndian(n, bs, 0);
+ return bs;
+ }
+
+ public static void intToBigEndian(int n, byte[] bs, int off)
+ {
+ bs[ off] = (byte)(n >>> 24);
+ bs[++off] = (byte)(n >>> 16);
+ bs[++off] = (byte)(n >>> 8);
+ bs[++off] = (byte)(n );
+ }
+
+ public static byte[] intToBigEndian(int[] ns)
+ {
+ byte[] bs = new byte[4 * ns.length];
+ intToBigEndian(ns, bs, 0);
+ return bs;
+ }
+
+ public static void intToBigEndian(int[] ns, byte[] bs, int off)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ intToBigEndian(ns[i], bs, off);
+ off += 4;
+ }
+ }
+
+ public static long bigEndianToLong(byte[] bs, int off)
+ {
+ int hi = bigEndianToInt(bs, off);
+ int lo = bigEndianToInt(bs, off + 4);
+ return ((long)(hi & 0xffffffffL) << 32) | (long)(lo & 0xffffffffL);
+ }
+
+ public static void bigEndianToLong(byte[] bs, int off, long[] ns)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ ns[i] = bigEndianToLong(bs, off);
+ off += 8;
+ }
+ }
+
+ public static byte[] longToBigEndian(long n)
+ {
+ byte[] bs = new byte[8];
+ longToBigEndian(n, bs, 0);
+ return bs;
+ }
+
+ public static void longToBigEndian(long n, byte[] bs, int off)
+ {
+ intToBigEndian((int)(n >>> 32), bs, off);
+ intToBigEndian((int)(n & 0xffffffffL), bs, off + 4);
+ }
+
+ public static byte[] longToBigEndian(long[] ns)
+ {
+ byte[] bs = new byte[8 * ns.length];
+ longToBigEndian(ns, bs, 0);
+ return bs;
+ }
+
+ public static void longToBigEndian(long[] ns, byte[] bs, int off)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ longToBigEndian(ns[i], bs, off);
+ off += 8;
+ }
+ }
+
+ public static int littleEndianToInt(byte[] bs, int off)
+ {
+ int n = bs[ off] & 0xff;
+ n |= (bs[++off] & 0xff) << 8;
+ n |= (bs[++off] & 0xff) << 16;
+ n |= bs[++off] << 24;
+ return n;
+ }
+
+ public static void littleEndianToInt(byte[] bs, int off, int[] ns)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ ns[i] = littleEndianToInt(bs, off);
+ off += 4;
+ }
+ }
+
+ public static void littleEndianToInt(byte[] bs, int bOff, int[] ns, int nOff, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ ns[nOff + i] = littleEndianToInt(bs, bOff);
+ bOff += 4;
+ }
+ }
+
+ public static byte[] intToLittleEndian(int n)
+ {
+ byte[] bs = new byte[4];
+ intToLittleEndian(n, bs, 0);
+ return bs;
+ }
+
+ public static void intToLittleEndian(int n, byte[] bs, int off)
+ {
+ bs[ off] = (byte)(n );
+ bs[++off] = (byte)(n >>> 8);
+ bs[++off] = (byte)(n >>> 16);
+ bs[++off] = (byte)(n >>> 24);
+ }
+
+ public static byte[] intToLittleEndian(int[] ns)
+ {
+ byte[] bs = new byte[4 * ns.length];
+ intToLittleEndian(ns, bs, 0);
+ return bs;
+ }
+
+ public static void intToLittleEndian(int[] ns, byte[] bs, int off)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ intToLittleEndian(ns[i], bs, off);
+ off += 4;
+ }
+ }
+
+ public static long littleEndianToLong(byte[] bs, int off)
+ {
+ int lo = littleEndianToInt(bs, off);
+ int hi = littleEndianToInt(bs, off + 4);
+ return ((long)(hi & 0xffffffffL) << 32) | (long)(lo & 0xffffffffL);
+ }
+
+ public static void littleEndianToLong(byte[] bs, int off, long[] ns)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ ns[i] = littleEndianToLong(bs, off);
+ off += 8;
+ }
+ }
+
+ public static byte[] longToLittleEndian(long n)
+ {
+ byte[] bs = new byte[8];
+ longToLittleEndian(n, bs, 0);
+ return bs;
+ }
+
+ public static void longToLittleEndian(long n, byte[] bs, int off)
+ {
+ intToLittleEndian((int)(n & 0xffffffffL), bs, off);
+ intToLittleEndian((int)(n >>> 32), bs, off + 4);
+ }
+
+ public static byte[] longToLittleEndian(long[] ns)
+ {
+ byte[] bs = new byte[8 * ns.length];
+ longToLittleEndian(ns, bs, 0);
+ return bs;
+ }
+
+ public static void longToLittleEndian(long[] ns, byte[] bs, int off)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ longToLittleEndian(ns[i], bs, off);
+ off += 8;
+ }
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/Selector.java b/core/src/main/java/org/spongycastle/util/Selector.java
new file mode 100644
index 00000000..6ed23f2a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/Selector.java
@@ -0,0 +1,9 @@
+package org.spongycastle.util;
+
+public interface Selector
+ extends Cloneable
+{
+ boolean match(Object obj);
+
+ Object clone();
+}
diff --git a/core/src/main/java/org/spongycastle/util/Shorts.java b/core/src/main/java/org/spongycastle/util/Shorts.java
new file mode 100644
index 00000000..0faaeb0d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/Shorts.java
@@ -0,0 +1,9 @@
+package org.spongycastle.util;
+
+public class Shorts
+{
+ public static Short valueOf(short value)
+ {
+ return Short.valueOf(value);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/Store.java b/core/src/main/java/org/spongycastle/util/Store.java
new file mode 100644
index 00000000..b19f6947
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/Store.java
@@ -0,0 +1,9 @@
+package org.spongycastle.util;
+
+import java.util.Collection;
+
+public interface Store
+{
+ Collection getMatches(Selector selector)
+ throws StoreException;
+}
diff --git a/core/src/main/java/org/spongycastle/util/StoreException.java b/core/src/main/java/org/spongycastle/util/StoreException.java
new file mode 100644
index 00000000..a02eee26
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/StoreException.java
@@ -0,0 +1,18 @@
+package org.spongycastle.util;
+
+public class StoreException
+ extends RuntimeException
+{
+ private Throwable _e;
+
+ public StoreException(String s, Throwable e)
+ {
+ super(s);
+ _e = e;
+ }
+
+ public Throwable getCause()
+ {
+ return _e;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/StreamParser.java b/core/src/main/java/org/spongycastle/util/StreamParser.java
new file mode 100644
index 00000000..ba962824
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/StreamParser.java
@@ -0,0 +1,10 @@
+package org.spongycastle.util;
+
+import java.util.Collection;
+
+public interface StreamParser
+{
+ Object read() throws StreamParsingException;
+
+ Collection readAll() throws StreamParsingException;
+}
diff --git a/core/src/main/java/org/spongycastle/util/StreamParsingException.java b/core/src/main/java/org/spongycastle/util/StreamParsingException.java
new file mode 100644
index 00000000..081219d7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/StreamParsingException.java
@@ -0,0 +1,18 @@
+package org.spongycastle.util;
+
+public class StreamParsingException
+ extends Exception
+{
+ Throwable _e;
+
+ public StreamParsingException(String message, Throwable e)
+ {
+ super(message);
+ _e = e;
+ }
+
+ public Throwable getCause()
+ {
+ return _e;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/Strings.java b/core/src/main/java/org/spongycastle/util/Strings.java
new file mode 100644
index 00000000..7e269455
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/Strings.java
@@ -0,0 +1,314 @@
+package org.spongycastle.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Vector;
+
+public final class Strings
+{
+ public static String fromUTF8ByteArray(byte[] bytes)
+ {
+ int i = 0;
+ int length = 0;
+
+ while (i < bytes.length)
+ {
+ length++;
+ if ((bytes[i] & 0xf0) == 0xf0)
+ {
+ // surrogate pair
+ length++;
+ i += 4;
+ }
+ else if ((bytes[i] & 0xe0) == 0xe0)
+ {
+ i += 3;
+ }
+ else if ((bytes[i] & 0xc0) == 0xc0)
+ {
+ i += 2;
+ }
+ else
+ {
+ i += 1;
+ }
+ }
+
+ char[] cs = new char[length];
+
+ i = 0;
+ length = 0;
+
+ while (i < bytes.length)
+ {
+ char ch;
+
+ if ((bytes[i] & 0xf0) == 0xf0)
+ {
+ int codePoint = ((bytes[i] & 0x03) << 18) | ((bytes[i+1] & 0x3F) << 12) | ((bytes[i+2] & 0x3F) << 6) | (bytes[i+3] & 0x3F);
+ int U = codePoint - 0x10000;
+ char W1 = (char)(0xD800 | (U >> 10));
+ char W2 = (char)(0xDC00 | (U & 0x3FF));
+ cs[length++] = W1;
+ ch = W2;
+ i += 4;
+ }
+ else if ((bytes[i] & 0xe0) == 0xe0)
+ {
+ ch = (char)(((bytes[i] & 0x0f) << 12)
+ | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f));
+ i += 3;
+ }
+ else if ((bytes[i] & 0xd0) == 0xd0)
+ {
+ ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f));
+ i += 2;
+ }
+ else if ((bytes[i] & 0xc0) == 0xc0)
+ {
+ ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f));
+ i += 2;
+ }
+ else
+ {
+ ch = (char)(bytes[i] & 0xff);
+ i += 1;
+ }
+
+ cs[length++] = ch;
+ }
+
+ return new String(cs);
+ }
+
+ public static byte[] toUTF8ByteArray(String string)
+ {
+ return toUTF8ByteArray(string.toCharArray());
+ }
+
+ public static byte[] toUTF8ByteArray(char[] string)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ toUTF8ByteArray(string, bOut);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("cannot encode string to byte array!");
+ }
+
+ return bOut.toByteArray();
+ }
+
+ public static void toUTF8ByteArray(char[] string, OutputStream sOut)
+ throws IOException
+ {
+ char[] c = string;
+ int i = 0;
+
+ while (i < c.length)
+ {
+ char ch = c[i];
+
+ if (ch < 0x0080)
+ {
+ sOut.write(ch);
+ }
+ else if (ch < 0x0800)
+ {
+ sOut.write(0xc0 | (ch >> 6));
+ sOut.write(0x80 | (ch & 0x3f));
+ }
+ // surrogate pair
+ else if (ch >= 0xD800 && ch <= 0xDFFF)
+ {
+ // in error - can only happen, if the Java String class has a
+ // bug.
+ if (i + 1 >= c.length)
+ {
+ throw new IllegalStateException("invalid UTF-16 codepoint");
+ }
+ char W1 = ch;
+ ch = c[++i];
+ char W2 = ch;
+ // in error - can only happen, if the Java String class has a
+ // bug.
+ if (W1 > 0xDBFF)
+ {
+ throw new IllegalStateException("invalid UTF-16 codepoint");
+ }
+ int codePoint = (((W1 & 0x03FF) << 10) | (W2 & 0x03FF)) + 0x10000;
+ sOut.write(0xf0 | (codePoint >> 18));
+ sOut.write(0x80 | ((codePoint >> 12) & 0x3F));
+ sOut.write(0x80 | ((codePoint >> 6) & 0x3F));
+ sOut.write(0x80 | (codePoint & 0x3F));
+ }
+ else
+ {
+ sOut.write(0xe0 | (ch >> 12));
+ sOut.write(0x80 | ((ch >> 6) & 0x3F));
+ sOut.write(0x80 | (ch & 0x3F));
+ }
+
+ i++;
+ }
+ }
+
+ /**
+ * A locale independent version of toUpperCase.
+ *
+ * @param string input to be converted
+ * @return a US Ascii uppercase version
+ */
+ public static String toUpperCase(String string)
+ {
+ boolean changed = false;
+ char[] chars = string.toCharArray();
+
+ for (int i = 0; i != chars.length; i++)
+ {
+ char ch = chars[i];
+ if ('a' <= ch && 'z' >= ch)
+ {
+ changed = true;
+ chars[i] = (char)(ch - 'a' + 'A');
+ }
+ }
+
+ if (changed)
+ {
+ return new String(chars);
+ }
+
+ return string;
+ }
+
+ /**
+ * A locale independent version of toLowerCase.
+ *
+ * @param string input to be converted
+ * @return a US ASCII lowercase version
+ */
+ public static String toLowerCase(String string)
+ {
+ boolean changed = false;
+ char[] chars = string.toCharArray();
+
+ for (int i = 0; i != chars.length; i++)
+ {
+ char ch = chars[i];
+ if ('A' <= ch && 'Z' >= ch)
+ {
+ changed = true;
+ chars[i] = (char)(ch - 'A' + 'a');
+ }
+ }
+
+ if (changed)
+ {
+ return new String(chars);
+ }
+
+ return string;
+ }
+
+ public static byte[] toByteArray(char[] chars)
+ {
+ byte[] bytes = new byte[chars.length];
+
+ for (int i = 0; i != bytes.length; i++)
+ {
+ bytes[i] = (byte)chars[i];
+ }
+
+ return bytes;
+ }
+
+ public static byte[] toByteArray(String string)
+ {
+ byte[] bytes = new byte[string.length()];
+
+ for (int i = 0; i != bytes.length; i++)
+ {
+ char ch = string.charAt(i);
+
+ bytes[i] = (byte)ch;
+ }
+
+ return bytes;
+ }
+
+ public static int toByteArray(String s, byte[] buf, int off)
+ {
+ int count = s.length();
+ for (int i = 0; i < count; ++i)
+ {
+ char c = s.charAt(i);
+ buf[off + i] = (byte)c;
+ }
+ return count;
+ }
+
+ /**
+ * Convert an array of 8 bit characters into a string.
+ *
+ * @param bytes 8 bit characters.
+ * @return resulting String.
+ */
+ public static String fromByteArray(byte[] bytes)
+ {
+ return new String(asCharArray(bytes));
+ }
+
+ /**
+ * Do a simple conversion of an array of 8 bit characters into a string.
+ *
+ * @param bytes 8 bit characters.
+ * @return resulting String.
+ */
+ public static char[] asCharArray(byte[] bytes)
+ {
+ char[] chars = new char[bytes.length];
+
+ for (int i = 0; i != chars.length; i++)
+ {
+ chars[i] = (char)(bytes[i] & 0xff);
+ }
+
+ return chars;
+ }
+
+ public static String[] split(String input, char delimiter)
+ {
+ Vector v = new Vector();
+ boolean moreTokens = true;
+ String subString;
+
+ while (moreTokens)
+ {
+ int tokenLocation = input.indexOf(delimiter);
+ if (tokenLocation > 0)
+ {
+ subString = input.substring(0, tokenLocation);
+ v.addElement(subString);
+ input = input.substring(tokenLocation + 1);
+ }
+ else
+ {
+ moreTokens = false;
+ v.addElement(input);
+ }
+ }
+
+ String[] res = new String[v.size()];
+
+ for (int i = 0; i != res.length; i++)
+ {
+ res[i] = (String)v.elementAt(i);
+ }
+ return res;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/Times.java b/core/src/main/java/org/spongycastle/util/Times.java
new file mode 100644
index 00000000..71d49e31
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/Times.java
@@ -0,0 +1,9 @@
+package org.spongycastle.util;
+
+public final class Times
+{
+ public static long nanoTime()
+ {
+ return System.nanoTime();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/encoders/Base64.java b/core/src/main/java/org/spongycastle/util/encoders/Base64.java
new file mode 100644
index 00000000..a2b5aff8
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/encoders/Base64.java
@@ -0,0 +1,154 @@
+package org.spongycastle.util.encoders;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.spongycastle.util.Strings;
+
+/**
+ * Utility class for converting Base64 data to bytes and back again.
+ */
+public class Base64
+{
+ private static final Encoder encoder = new Base64Encoder();
+
+ public static String toBase64String(
+ byte[] data)
+ {
+ return toBase64String(data, 0, data.length);
+ }
+
+ public static String toBase64String(
+ byte[] data,
+ int off,
+ int length)
+ {
+ byte[] encoded = encode(data, off, length);
+ return Strings.fromByteArray(encoded);
+ }
+
+ /**
+ * encode the input data producing a base 64 encoded byte array.
+ *
+ * @return a byte array containing the base 64 encoded data.
+ */
+ public static byte[] encode(
+ byte[] data)
+ {
+ return encode(data, 0, data.length);
+ }
+
+ /**
+ * encode the input data producing a base 64 encoded byte array.
+ *
+ * @return a byte array containing the base 64 encoded data.
+ */
+ public static byte[] encode(
+ byte[] data,
+ int off,
+ int length)
+ {
+ int len = (length + 2) / 3 * 4;
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);
+
+ try
+ {
+ encoder.encode(data, off, length, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new EncoderException("exception encoding base64 string: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * Encode the byte data to base 64 writing it to the given output stream.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int encode(
+ byte[] data,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.encode(data, 0, data.length, out);
+ }
+
+ /**
+ * Encode the byte data to base 64 writing it to the given output stream.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int encode(
+ byte[] data,
+ int off,
+ int length,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.encode(data, off, length, out);
+ }
+
+ /**
+ * decode the base 64 encoded input data. It is assumed the input data is valid.
+ *
+ * @return a byte array representing the decoded data.
+ */
+ public static byte[] decode(
+ byte[] data)
+ {
+ int len = data.length / 4 * 3;
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);
+
+ try
+ {
+ encoder.decode(data, 0, data.length, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new DecoderException("unable to decode base64 data: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * decode the base 64 encoded String data - whitespace will be ignored.
+ *
+ * @return a byte array representing the decoded data.
+ */
+ public static byte[] decode(
+ String data)
+ {
+ int len = data.length() / 4 * 3;
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);
+
+ try
+ {
+ encoder.decode(data, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new DecoderException("unable to decode base64 string: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * decode the base 64 encoded String data writing it to the given output stream,
+ * whitespace characters will be ignored.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int decode(
+ String data,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.decode(data, out);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/encoders/Base64Encoder.java b/core/src/main/java/org/spongycastle/util/encoders/Base64Encoder.java
new file mode 100644
index 00000000..17bae1dd
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/encoders/Base64Encoder.java
@@ -0,0 +1,331 @@
+package org.spongycastle.util.encoders;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * A streaming Base64 encoder.
+ */
+public class Base64Encoder
+ implements Encoder
+{
+ protected final byte[] encodingTable =
+ {
+ (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
+ (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
+ (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
+ (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
+ (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
+ (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
+ (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
+ (byte)'v',
+ (byte)'w', (byte)'x', (byte)'y', (byte)'z',
+ (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6',
+ (byte)'7', (byte)'8', (byte)'9',
+ (byte)'+', (byte)'/'
+ };
+
+ protected byte padding = (byte)'=';
+
+ /*
+ * set up the decoding table.
+ */
+ protected final byte[] decodingTable = new byte[128];
+
+ protected void initialiseDecodingTable()
+ {
+ for (int i = 0; i < decodingTable.length; i++)
+ {
+ decodingTable[i] = (byte)0xff;
+ }
+
+ for (int i = 0; i < encodingTable.length; i++)
+ {
+ decodingTable[encodingTable[i]] = (byte)i;
+ }
+ }
+
+ public Base64Encoder()
+ {
+ initialiseDecodingTable();
+ }
+
+ /**
+ * encode the input data producing a base 64 output stream.
+ *
+ * @return the number of bytes produced.
+ */
+ public int encode(
+ byte[] data,
+ int off,
+ int length,
+ OutputStream out)
+ throws IOException
+ {
+ int modulus = length % 3;
+ int dataLength = (length - modulus);
+ int a1, a2, a3;
+
+ for (int i = off; i < off + dataLength; i += 3)
+ {
+ a1 = data[i] & 0xff;
+ a2 = data[i + 1] & 0xff;
+ a3 = data[i + 2] & 0xff;
+
+ out.write(encodingTable[(a1 >>> 2) & 0x3f]);
+ out.write(encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f]);
+ out.write(encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f]);
+ out.write(encodingTable[a3 & 0x3f]);
+ }
+
+ /*
+ * process the tail end.
+ */
+ int b1, b2, b3;
+ int d1, d2;
+
+ switch (modulus)
+ {
+ case 0: /* nothing left to do */
+ break;
+ case 1:
+ d1 = data[off + dataLength] & 0xff;
+ b1 = (d1 >>> 2) & 0x3f;
+ b2 = (d1 << 4) & 0x3f;
+
+ out.write(encodingTable[b1]);
+ out.write(encodingTable[b2]);
+ out.write(padding);
+ out.write(padding);
+ break;
+ case 2:
+ d1 = data[off + dataLength] & 0xff;
+ d2 = data[off + dataLength + 1] & 0xff;
+
+ b1 = (d1 >>> 2) & 0x3f;
+ b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f;
+ b3 = (d2 << 2) & 0x3f;
+
+ out.write(encodingTable[b1]);
+ out.write(encodingTable[b2]);
+ out.write(encodingTable[b3]);
+ out.write(padding);
+ break;
+ }
+
+ return (dataLength / 3) * 4 + ((modulus == 0) ? 0 : 4);
+ }
+
+ private boolean ignore(
+ char c)
+ {
+ return (c == '\n' || c =='\r' || c == '\t' || c == ' ');
+ }
+
+ /**
+ * decode the base 64 encoded byte data writing it to the given output stream,
+ * whitespace characters will be ignored.
+ *
+ * @return the number of bytes produced.
+ */
+ public int decode(
+ byte[] data,
+ int off,
+ int length,
+ OutputStream out)
+ throws IOException
+ {
+ byte b1, b2, b3, b4;
+ int outLen = 0;
+
+ int end = off + length;
+
+ while (end > off)
+ {
+ if (!ignore((char)data[end - 1]))
+ {
+ break;
+ }
+
+ end--;
+ }
+
+ int i = off;
+ int finish = end - 4;
+
+ i = nextI(data, i, finish);
+
+ while (i < finish)
+ {
+ b1 = decodingTable[data[i++]];
+
+ i = nextI(data, i, finish);
+
+ b2 = decodingTable[data[i++]];
+
+ i = nextI(data, i, finish);
+
+ b3 = decodingTable[data[i++]];
+
+ i = nextI(data, i, finish);
+
+ b4 = decodingTable[data[i++]];
+
+ if ((b1 | b2 | b3 | b4) < 0)
+ {
+ throw new IOException("invalid characters encountered in base64 data");
+ }
+
+ out.write((b1 << 2) | (b2 >> 4));
+ out.write((b2 << 4) | (b3 >> 2));
+ out.write((b3 << 6) | b4);
+
+ outLen += 3;
+
+ i = nextI(data, i, finish);
+ }
+
+ outLen += decodeLastBlock(out, (char)data[end - 4], (char)data[end - 3], (char)data[end - 2], (char)data[end - 1]);
+
+ return outLen;
+ }
+
+ private int nextI(byte[] data, int i, int finish)
+ {
+ while ((i < finish) && ignore((char)data[i]))
+ {
+ i++;
+ }
+ return i;
+ }
+
+ /**
+ * decode the base 64 encoded String data writing it to the given output stream,
+ * whitespace characters will be ignored.
+ *
+ * @return the number of bytes produced.
+ */
+ public int decode(
+ String data,
+ OutputStream out)
+ throws IOException
+ {
+ byte b1, b2, b3, b4;
+ int length = 0;
+
+ int end = data.length();
+
+ while (end > 0)
+ {
+ if (!ignore(data.charAt(end - 1)))
+ {
+ break;
+ }
+
+ end--;
+ }
+
+ int i = 0;
+ int finish = end - 4;
+
+ i = nextI(data, i, finish);
+
+ while (i < finish)
+ {
+ b1 = decodingTable[data.charAt(i++)];
+
+ i = nextI(data, i, finish);
+
+ b2 = decodingTable[data.charAt(i++)];
+
+ i = nextI(data, i, finish);
+
+ b3 = decodingTable[data.charAt(i++)];
+
+ i = nextI(data, i, finish);
+
+ b4 = decodingTable[data.charAt(i++)];
+
+ if ((b1 | b2 | b3 | b4) < 0)
+ {
+ throw new IOException("invalid characters encountered in base64 data");
+ }
+
+ out.write((b1 << 2) | (b2 >> 4));
+ out.write((b2 << 4) | (b3 >> 2));
+ out.write((b3 << 6) | b4);
+
+ length += 3;
+
+ i = nextI(data, i, finish);
+ }
+
+ length += decodeLastBlock(out, data.charAt(end - 4), data.charAt(end - 3), data.charAt(end - 2), data.charAt(end - 1));
+
+ return length;
+ }
+
+ private int decodeLastBlock(OutputStream out, char c1, char c2, char c3, char c4)
+ throws IOException
+ {
+ byte b1, b2, b3, b4;
+
+ if (c3 == padding)
+ {
+ b1 = decodingTable[c1];
+ b2 = decodingTable[c2];
+
+ if ((b1 | b2) < 0)
+ {
+ throw new IOException("invalid characters encountered at end of base64 data");
+ }
+
+ out.write((b1 << 2) | (b2 >> 4));
+
+ return 1;
+ }
+ else if (c4 == padding)
+ {
+ b1 = decodingTable[c1];
+ b2 = decodingTable[c2];
+ b3 = decodingTable[c3];
+
+ if ((b1 | b2 | b3) < 0)
+ {
+ throw new IOException("invalid characters encountered at end of base64 data");
+ }
+
+ out.write((b1 << 2) | (b2 >> 4));
+ out.write((b2 << 4) | (b3 >> 2));
+
+ return 2;
+ }
+ else
+ {
+ b1 = decodingTable[c1];
+ b2 = decodingTable[c2];
+ b3 = decodingTable[c3];
+ b4 = decodingTable[c4];
+
+ if ((b1 | b2 | b3 | b4) < 0)
+ {
+ throw new IOException("invalid characters encountered at end of base64 data");
+ }
+
+ out.write((b1 << 2) | (b2 >> 4));
+ out.write((b2 << 4) | (b3 >> 2));
+ out.write((b3 << 6) | b4);
+
+ return 3;
+ }
+ }
+
+ private int nextI(String data, int i, int finish)
+ {
+ while ((i < finish) && ignore(data.charAt(i)))
+ {
+ i++;
+ }
+ return i;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/encoders/BufferedDecoder.java b/core/src/main/java/org/spongycastle/util/encoders/BufferedDecoder.java
new file mode 100644
index 00000000..31c702ae
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/encoders/BufferedDecoder.java
@@ -0,0 +1,96 @@
+package org.spongycastle.util.encoders;
+
+
+/**
+ * A buffering class to allow translation from one format to another to
+ * be done in discrete chunks.
+ */
+public class BufferedDecoder
+{
+ protected byte[] buf;
+ protected int bufOff;
+
+ protected Translator translator;
+
+ /**
+ * @param translator the translator to use.
+ * @param bufSize amount of input to buffer for each chunk.
+ */
+ public BufferedDecoder(
+ Translator translator,
+ int bufSize)
+ {
+ this.translator = translator;
+
+ if ((bufSize % translator.getEncodedBlockSize()) != 0)
+ {
+ throw new IllegalArgumentException("buffer size not multiple of input block size");
+ }
+
+ buf = new byte[bufSize];
+ bufOff = 0;
+ }
+
+ public int processByte(
+ byte in,
+ byte[] out,
+ int outOff)
+ {
+ int resultLen = 0;
+
+ buf[bufOff++] = in;
+
+ if (bufOff == buf.length)
+ {
+ resultLen = translator.decode(buf, 0, buf.length, out, outOff);
+ bufOff = 0;
+ }
+
+ return resultLen;
+ }
+
+ public int processBytes(
+ byte[] in,
+ int inOff,
+ int len,
+ byte[] out,
+ int outOff)
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ int resultLen = 0;
+ int gapLen = buf.length - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ resultLen += translator.decode(buf, 0, buf.length, out, outOff);
+
+ bufOff = 0;
+
+ len -= gapLen;
+ inOff += gapLen;
+ outOff += resultLen;
+
+ int chunkSize = len - (len % buf.length);
+
+ resultLen += translator.decode(in, inOff, chunkSize, out, outOff);
+
+ len -= chunkSize;
+ inOff += chunkSize;
+ }
+
+ if (len != 0)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+ }
+
+ return resultLen;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/encoders/BufferedEncoder.java b/core/src/main/java/org/spongycastle/util/encoders/BufferedEncoder.java
new file mode 100644
index 00000000..fbeb92b6
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/encoders/BufferedEncoder.java
@@ -0,0 +1,96 @@
+package org.spongycastle.util.encoders;
+
+
+/**
+ * A buffering class to allow translation from one format to another to
+ * be done in discrete chunks.
+ */
+public class BufferedEncoder
+{
+ protected byte[] buf;
+ protected int bufOff;
+
+ protected Translator translator;
+
+ /**
+ * @param translator the translator to use.
+ * @param bufSize amount of input to buffer for each chunk.
+ */
+ public BufferedEncoder(
+ Translator translator,
+ int bufSize)
+ {
+ this.translator = translator;
+
+ if ((bufSize % translator.getEncodedBlockSize()) != 0)
+ {
+ throw new IllegalArgumentException("buffer size not multiple of input block size");
+ }
+
+ buf = new byte[bufSize];
+ bufOff = 0;
+ }
+
+ public int processByte(
+ byte in,
+ byte[] out,
+ int outOff)
+ {
+ int resultLen = 0;
+
+ buf[bufOff++] = in;
+
+ if (bufOff == buf.length)
+ {
+ resultLen = translator.encode(buf, 0, buf.length, out, outOff);
+ bufOff = 0;
+ }
+
+ return resultLen;
+ }
+
+ public int processBytes(
+ byte[] in,
+ int inOff,
+ int len,
+ byte[] out,
+ int outOff)
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ int resultLen = 0;
+ int gapLen = buf.length - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ resultLen += translator.encode(buf, 0, buf.length, out, outOff);
+
+ bufOff = 0;
+
+ len -= gapLen;
+ inOff += gapLen;
+ outOff += resultLen;
+
+ int chunkSize = len - (len % buf.length);
+
+ resultLen += translator.encode(in, inOff, chunkSize, out, outOff);
+
+ len -= chunkSize;
+ inOff += chunkSize;
+ }
+
+ if (len != 0)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+ }
+
+ return resultLen;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/encoders/DecoderException.java b/core/src/main/java/org/spongycastle/util/encoders/DecoderException.java
new file mode 100644
index 00000000..88e0b7c0
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/encoders/DecoderException.java
@@ -0,0 +1,22 @@
+package org.spongycastle.util.encoders;
+
+/**
+ * Exception thrown if an attempt is made to decode invalid data, or some other failure occurs.
+ */
+public class DecoderException
+ extends IllegalStateException
+{
+ private Throwable cause;
+
+ DecoderException(String msg, Throwable cause)
+ {
+ super(msg);
+
+ this.cause = cause;
+ }
+
+ public Throwable getCause()
+ {
+ return cause;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/encoders/Encoder.java b/core/src/main/java/org/spongycastle/util/encoders/Encoder.java
new file mode 100644
index 00000000..106c36b7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/encoders/Encoder.java
@@ -0,0 +1,17 @@
+package org.spongycastle.util.encoders;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Encode and decode byte arrays (typically from binary to 7-bit ASCII
+ * encodings).
+ */
+public interface Encoder
+{
+ int encode(byte[] data, int off, int length, OutputStream out) throws IOException;
+
+ int decode(byte[] data, int off, int length, OutputStream out) throws IOException;
+
+ int decode(String data, OutputStream out) throws IOException;
+}
diff --git a/core/src/main/java/org/spongycastle/util/encoders/EncoderException.java b/core/src/main/java/org/spongycastle/util/encoders/EncoderException.java
new file mode 100644
index 00000000..936fce02
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/encoders/EncoderException.java
@@ -0,0 +1,22 @@
+package org.spongycastle.util.encoders;
+
+/**
+ * Exception thrown if an attempt is made to encode invalid data, or some other failure occurs.
+ */
+public class EncoderException
+ extends IllegalStateException
+{
+ private Throwable cause;
+
+ EncoderException(String msg, Throwable cause)
+ {
+ super(msg);
+
+ this.cause = cause;
+ }
+
+ public Throwable getCause()
+ {
+ return cause;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/encoders/Hex.java b/core/src/main/java/org/spongycastle/util/encoders/Hex.java
new file mode 100644
index 00000000..5d0efc13
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/encoders/Hex.java
@@ -0,0 +1,151 @@
+package org.spongycastle.util.encoders;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.spongycastle.util.Strings;
+
+/**
+ * Utility class for converting hex data to bytes and back again.
+ */
+public class Hex
+{
+ private static final Encoder encoder = new HexEncoder();
+
+ public static String toHexString(
+ byte[] data)
+ {
+ return toHexString(data, 0, data.length);
+ }
+
+ public static String toHexString(
+ byte[] data,
+ int off,
+ int length)
+ {
+ byte[] encoded = encode(data, off, length);
+ return Strings.fromByteArray(encoded);
+ }
+
+ /**
+ * encode the input data producing a Hex encoded byte array.
+ *
+ * @return a byte array containing the Hex encoded data.
+ */
+ public static byte[] encode(
+ byte[] data)
+ {
+ return encode(data, 0, data.length);
+ }
+
+ /**
+ * encode the input data producing a Hex encoded byte array.
+ *
+ * @return a byte array containing the Hex encoded data.
+ */
+ public static byte[] encode(
+ byte[] data,
+ int off,
+ int length)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ encoder.encode(data, off, length, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new EncoderException("exception encoding Hex string: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * Hex encode the byte data writing it to the given output stream.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int encode(
+ byte[] data,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.encode(data, 0, data.length, out);
+ }
+
+ /**
+ * Hex encode the byte data writing it to the given output stream.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int encode(
+ byte[] data,
+ int off,
+ int length,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.encode(data, off, length, out);
+ }
+
+ /**
+ * decode the Hex encoded input data. It is assumed the input data is valid.
+ *
+ * @return a byte array representing the decoded data.
+ */
+ public static byte[] decode(
+ byte[] data)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ encoder.decode(data, 0, data.length, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new DecoderException("exception decoding Hex data: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * decode the Hex encoded String data - whitespace will be ignored.
+ *
+ * @return a byte array representing the decoded data.
+ */
+ public static byte[] decode(
+ String data)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ encoder.decode(data, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new DecoderException("exception decoding Hex string: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * decode the Hex encoded String data writing it to the given output stream,
+ * whitespace characters will be ignored.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int decode(
+ String data,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.decode(data, out);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/encoders/HexEncoder.java b/core/src/main/java/org/spongycastle/util/encoders/HexEncoder.java
new file mode 100644
index 00000000..16120129
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/encoders/HexEncoder.java
@@ -0,0 +1,190 @@
+package org.spongycastle.util.encoders;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * A streaming Hex encoder.
+ */
+public class HexEncoder
+ implements Encoder
+{
+ protected final byte[] encodingTable =
+ {
+ (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
+ (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'
+ };
+
+ /*
+ * set up the decoding table.
+ */
+ protected final byte[] decodingTable = new byte[128];
+
+ protected void initialiseDecodingTable()
+ {
+ for (int i = 0; i < decodingTable.length; i++)
+ {
+ decodingTable[i] = (byte)0xff;
+ }
+
+ for (int i = 0; i < encodingTable.length; i++)
+ {
+ decodingTable[encodingTable[i]] = (byte)i;
+ }
+
+ decodingTable['A'] = decodingTable['a'];
+ decodingTable['B'] = decodingTable['b'];
+ decodingTable['C'] = decodingTable['c'];
+ decodingTable['D'] = decodingTable['d'];
+ decodingTable['E'] = decodingTable['e'];
+ decodingTable['F'] = decodingTable['f'];
+ }
+
+ public HexEncoder()
+ {
+ initialiseDecodingTable();
+ }
+
+ /**
+ * encode the input data producing a Hex output stream.
+ *
+ * @return the number of bytes produced.
+ */
+ public int encode(
+ byte[] data,
+ int off,
+ int length,
+ OutputStream out)
+ throws IOException
+ {
+ for (int i = off; i < (off + length); i++)
+ {
+ int v = data[i] & 0xff;
+
+ out.write(encodingTable[(v >>> 4)]);
+ out.write(encodingTable[v & 0xf]);
+ }
+
+ return length * 2;
+ }
+
+ private static boolean ignore(
+ char c)
+ {
+ return c == '\n' || c =='\r' || c == '\t' || c == ' ';
+ }
+
+ /**
+ * decode the Hex encoded byte data writing it to the given output stream,
+ * whitespace characters will be ignored.
+ *
+ * @return the number of bytes produced.
+ */
+ public int decode(
+ byte[] data,
+ int off,
+ int length,
+ OutputStream out)
+ throws IOException
+ {
+ byte b1, b2;
+ int outLen = 0;
+
+ int end = off + length;
+
+ while (end > off)
+ {
+ if (!ignore((char)data[end - 1]))
+ {
+ break;
+ }
+
+ end--;
+ }
+
+ int i = off;
+ while (i < end)
+ {
+ while (i < end && ignore((char)data[i]))
+ {
+ i++;
+ }
+
+ b1 = decodingTable[data[i++]];
+
+ while (i < end && ignore((char)data[i]))
+ {
+ i++;
+ }
+
+ b2 = decodingTable[data[i++]];
+
+ if ((b1 | b2) < 0)
+ {
+ throw new IOException("invalid characters encountered in Hex data");
+ }
+
+ out.write((b1 << 4) | b2);
+
+ outLen++;
+ }
+
+ return outLen;
+ }
+
+ /**
+ * decode the Hex encoded String data writing it to the given output stream,
+ * whitespace characters will be ignored.
+ *
+ * @return the number of bytes produced.
+ */
+ public int decode(
+ String data,
+ OutputStream out)
+ throws IOException
+ {
+ byte b1, b2;
+ int length = 0;
+
+ int end = data.length();
+
+ while (end > 0)
+ {
+ if (!ignore(data.charAt(end - 1)))
+ {
+ break;
+ }
+
+ end--;
+ }
+
+ int i = 0;
+ while (i < end)
+ {
+ while (i < end && ignore(data.charAt(i)))
+ {
+ i++;
+ }
+
+ b1 = decodingTable[data.charAt(i++)];
+
+ while (i < end && ignore(data.charAt(i)))
+ {
+ i++;
+ }
+
+ b2 = decodingTable[data.charAt(i++)];
+
+ if ((b1 | b2) < 0)
+ {
+ throw new IOException("invalid characters encountered in Hex string");
+ }
+
+ out.write((b1 << 4) | b2);
+
+ length++;
+ }
+
+ return length;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/encoders/HexTranslator.java b/core/src/main/java/org/spongycastle/util/encoders/HexTranslator.java
new file mode 100644
index 00000000..066f883d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/encoders/HexTranslator.java
@@ -0,0 +1,87 @@
+package org.spongycastle.util.encoders;
+
+/**
+ * Converters for going from hex to binary and back. Note: this class assumes ASCII processing.
+ */
+public class HexTranslator
+ implements Translator
+{
+ private static final byte[] hexTable =
+ {
+ (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
+ (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'
+ };
+
+ /**
+ * size of the output block on encoding produced by getDecodedBlockSize()
+ * bytes.
+ */
+ public int getEncodedBlockSize()
+ {
+ return 2;
+ }
+
+ public int encode(
+ byte[] in,
+ int inOff,
+ int length,
+ byte[] out,
+ int outOff)
+ {
+ for (int i = 0, j = 0; i < length; i++, j += 2)
+ {
+ out[outOff + j] = hexTable[(in[inOff] >> 4) & 0x0f];
+ out[outOff + j + 1] = hexTable[in[inOff] & 0x0f];
+
+ inOff++;
+ }
+
+ return length * 2;
+ }
+
+ /**
+ * size of the output block on decoding produced by getEncodedBlockSize()
+ * bytes.
+ */
+ public int getDecodedBlockSize()
+ {
+ return 1;
+ }
+
+ public int decode(
+ byte[] in,
+ int inOff,
+ int length,
+ byte[] out,
+ int outOff)
+ {
+ int halfLength = length / 2;
+ byte left, right;
+ for (int i = 0; i < halfLength; i++)
+ {
+ left = in[inOff + i * 2];
+ right = in[inOff + i * 2 + 1];
+
+ if (left < (byte)'a')
+ {
+ out[outOff] = (byte)((left - '0') << 4);
+ }
+ else
+ {
+ out[outOff] = (byte)((left - 'a' + 10) << 4);
+ }
+ if (right < (byte)'a')
+ {
+ out[outOff] += (byte)(right - '0');
+ }
+ else
+ {
+ out[outOff] += (byte)(right - 'a' + 10);
+ }
+
+ outOff++;
+ }
+
+ return halfLength;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/encoders/Translator.java b/core/src/main/java/org/spongycastle/util/encoders/Translator.java
new file mode 100644
index 00000000..819b761a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/encoders/Translator.java
@@ -0,0 +1,23 @@
+package org.spongycastle.util.encoders;
+
+/**
+ * General interface for an translator.
+ */
+public interface Translator
+{
+ /**
+ * size of the output block on encoding produced by getDecodedBlockSize()
+ * bytes.
+ */
+ public int getEncodedBlockSize();
+
+ public int encode(byte[] in, int inOff, int length, byte[] out, int outOff);
+
+ /**
+ * size of the output block on decoding produced by getEncodedBlockSize()
+ * bytes.
+ */
+ public int getDecodedBlockSize();
+
+ public int decode(byte[] in, int inOff, int length, byte[] out, int outOff);
+}
diff --git a/core/src/main/java/org/spongycastle/util/encoders/UrlBase64.java b/core/src/main/java/org/spongycastle/util/encoders/UrlBase64.java
new file mode 100644
index 00000000..18fb0eb4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/encoders/UrlBase64.java
@@ -0,0 +1,129 @@
+package org.spongycastle.util.encoders;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Convert binary data to and from UrlBase64 encoding. This is identical to
+ * Base64 encoding, except that the padding character is "." and the other
+ * non-alphanumeric characters are "-" and "_" instead of "+" and "/".
+ * <p>
+ * The purpose of UrlBase64 encoding is to provide a compact encoding of binary
+ * data that is safe for use as an URL parameter. Base64 encoding does not
+ * produce encoded values that are safe for use in URLs, since "/" can be
+ * interpreted as a path delimiter; "+" is the encoded form of a space; and
+ * "=" is used to separate a name from the corresponding value in an URL
+ * parameter.
+ */
+public class UrlBase64
+{
+ private static final Encoder encoder = new UrlBase64Encoder();
+
+ /**
+ * Encode the input data producing a URL safe base 64 encoded byte array.
+ *
+ * @return a byte array containing the URL safe base 64 encoded data.
+ */
+ public static byte[] encode(
+ byte[] data)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ encoder.encode(data, 0, data.length, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new EncoderException("exception encoding URL safe base64 data: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * Encode the byte data writing it to the given output stream.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int encode(
+ byte[] data,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.encode(data, 0, data.length, out);
+ }
+
+ /**
+ * Decode the URL safe base 64 encoded input data - white space will be ignored.
+ *
+ * @return a byte array representing the decoded data.
+ */
+ public static byte[] decode(
+ byte[] data)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ encoder.decode(data, 0, data.length, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new DecoderException("exception decoding URL safe base64 string: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * decode the URL safe base 64 encoded byte data writing it to the given output stream,
+ * whitespace characters will be ignored.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int decode(
+ byte[] data,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.decode(data, 0, data.length, out);
+ }
+
+ /**
+ * decode the URL safe base 64 encoded String data - whitespace will be ignored.
+ *
+ * @return a byte array representing the decoded data.
+ */
+ public static byte[] decode(
+ String data)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ encoder.decode(data, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new DecoderException("exception decoding URL safe base64 string: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * Decode the URL safe base 64 encoded String data writing it to the given output stream,
+ * whitespace characters will be ignored.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int decode(
+ String data,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.decode(data, out);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/encoders/UrlBase64Encoder.java b/core/src/main/java/org/spongycastle/util/encoders/UrlBase64Encoder.java
new file mode 100644
index 00000000..dc6f1ed7
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/encoders/UrlBase64Encoder.java
@@ -0,0 +1,25 @@
+package org.spongycastle.util.encoders;
+
+/**
+ * Convert binary data to and from UrlBase64 encoding. This is identical to
+ * Base64 encoding, except that the padding character is "." and the other
+ * non-alphanumeric characters are "-" and "_" instead of "+" and "/".
+ * <p>
+ * The purpose of UrlBase64 encoding is to provide a compact encoding of binary
+ * data that is safe for use as an URL parameter. Base64 encoding does not
+ * produce encoded values that are safe for use in URLs, since "/" can be
+ * interpreted as a path delimiter; "+" is the encoded form of a space; and
+ * "=" is used to separate a name from the corresponding value in an URL
+ * parameter.
+ */
+public class UrlBase64Encoder extends Base64Encoder
+{
+ public UrlBase64Encoder()
+ {
+ encodingTable[encodingTable.length - 2] = (byte) '-';
+ encodingTable[encodingTable.length - 1] = (byte) '_';
+ padding = (byte) '.';
+ // we must re-create the decoding table with the new encoded values.
+ initialiseDecodingTable();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/io/BufferingOutputStream.java b/core/src/main/java/org/spongycastle/util/io/BufferingOutputStream.java
new file mode 100644
index 00000000..ae4abec4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/io/BufferingOutputStream.java
@@ -0,0 +1,108 @@
+package org.spongycastle.util.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.spongycastle.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/core/src/main/java/org/spongycastle/util/io/StreamOverflowException.java b/core/src/main/java/org/spongycastle/util/io/StreamOverflowException.java
new file mode 100644
index 00000000..47f85a3f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/io/StreamOverflowException.java
@@ -0,0 +1,15 @@
+package org.spongycastle.util.io;
+
+import java.io.IOException;
+
+/**
+ * Exception thrown when too much data is written to an InputStream
+ */
+public class StreamOverflowException
+ extends IOException
+{
+ public StreamOverflowException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/io/Streams.java b/core/src/main/java/org/spongycastle/util/io/Streams.java
new file mode 100644
index 00000000..210620c4
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/io/Streams.java
@@ -0,0 +1,145 @@
+package org.spongycastle.util.io;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Utility methods to assist with stream processing.
+ */
+public final class Streams
+{
+ private static int BUFFER_SIZE = 512;
+
+ /**
+ * Read stream till EOF is encountered.
+ *
+ * @param inStr stream to be emptied.
+ * @throws IOException in case of underlying IOException.
+ */
+ public static void drain(InputStream inStr)
+ throws IOException
+ {
+ byte[] bs = new byte[BUFFER_SIZE];
+ while (inStr.read(bs, 0, bs.length) >= 0)
+ {
+ }
+ }
+
+ /**
+ * Read stream fully, returning contents in a byte array.
+ *
+ * @param inStr stream to be read.
+ * @return a byte array representing the contents of inStr.
+ * @throws IOException in case of underlying IOException.
+ */
+ public static byte[] readAll(InputStream inStr)
+ throws IOException
+ {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ pipeAll(inStr, buf);
+ return buf.toByteArray();
+ }
+
+ /**
+ * Read from inStr up to a maximum number of bytes, throwing an exception if more the maximum amount
+ * of requested data is available.
+ *
+ * @param inStr stream to be read.
+ * @param limit maximum number of bytes that can be read.
+ * @return a byte array representing the contents of inStr.
+ * @throws IOException in case of underlying IOException, or if limit is reached on inStr still has data in it.
+ */
+ public static byte[] readAllLimited(InputStream inStr, int limit)
+ throws IOException
+ {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ pipeAllLimited(inStr, limit, buf);
+ return buf.toByteArray();
+ }
+
+ /**
+ * Fully read in buf's length in data, or up to EOF, whichever occurs first,
+ *
+ * @param inStr the stream to be read.
+ * @param buf the buffer to be read into.
+ * @return the number of bytes read into the buffer.
+ * @throws IOException in case of underlying IOException.
+ */
+ public static int readFully(InputStream inStr, byte[] buf)
+ throws IOException
+ {
+ return readFully(inStr, buf, 0, buf.length);
+ }
+
+ /**
+ * Fully read in len's bytes of data into buf, or up to EOF, whichever occurs first,
+ *
+ * @param inStr the stream to be read.
+ * @param buf the buffer to be read into.
+ * @param off offset into buf to start putting bytes into.
+ * @param len the number of bytes to be read.
+ * @return the number of bytes read into the buffer.
+ * @throws IOException in case of underlying IOException.
+ */
+ public static int readFully(InputStream inStr, byte[] buf, int off, int len)
+ throws IOException
+ {
+ int totalRead = 0;
+ while (totalRead < len)
+ {
+ int numRead = inStr.read(buf, off + totalRead, len - totalRead);
+ if (numRead < 0)
+ {
+ break;
+ }
+ totalRead += numRead;
+ }
+ return totalRead;
+ }
+
+ /**
+ * Write the full contents of inStr to the destination stream outStr.
+ *
+ * @param inStr source input stream.
+ * @param outStr destination output stream.
+ * @throws IOException in case of underlying IOException.
+ */
+ public static void pipeAll(InputStream inStr, OutputStream outStr)
+ throws IOException
+ {
+ byte[] bs = new byte[BUFFER_SIZE];
+ int numRead;
+ while ((numRead = inStr.read(bs, 0, bs.length)) >= 0)
+ {
+ outStr.write(bs, 0, numRead);
+ }
+ }
+
+ /**
+ * Write up to limit bytes of data from inStr to the destination stream outStr.
+ *
+ * @param inStr source input stream.
+ * @param limit the maximum number of bytes allowed to be read.
+ * @param outStr destination output stream.
+ * @throws IOException in case of underlying IOException, or if limit is reached on inStr still has data in it.
+ */
+ public static long pipeAllLimited(InputStream inStr, long limit, OutputStream outStr)
+ throws IOException
+ {
+ long total = 0;
+ byte[] bs = new byte[BUFFER_SIZE];
+ int numRead;
+ while ((numRead = inStr.read(bs, 0, bs.length)) >= 0)
+ {
+ total += numRead;
+ if (total > limit)
+ {
+ throw new StreamOverflowException("Data Overflow");
+ }
+ outStr.write(bs, 0, numRead);
+ }
+ return total;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/io/TeeInputStream.java b/core/src/main/java/org/spongycastle/util/io/TeeInputStream.java
new file mode 100644
index 00000000..9647528d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/io/TeeInputStream.java
@@ -0,0 +1,71 @@
+package org.spongycastle.util.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * An input stream which copies anything read through it to another stream.
+ */
+public class TeeInputStream
+ extends InputStream
+{
+ private final InputStream input;
+ private final OutputStream output;
+
+ /**
+ * Base constructor.
+ *
+ * @param input input stream to be wrapped.
+ * @param output output stream to copy any input read to.
+ */
+ public TeeInputStream(InputStream input, OutputStream output)
+ {
+ this.input = input;
+ this.output = output;
+ }
+
+ public int read(byte[] buf)
+ throws IOException
+ {
+ return read(buf, 0, buf.length);
+ }
+
+ public int read(byte[] buf, int off, int len)
+ throws IOException
+ {
+ int i = input.read(buf, off, len);
+
+ if (i > 0)
+ {
+ output.write(buf, off, i);
+ }
+
+ return i;
+ }
+
+ public int read()
+ throws IOException
+ {
+ int i = input.read();
+
+ if (i >= 0)
+ {
+ output.write(i);
+ }
+
+ return i;
+ }
+
+ public void close()
+ throws IOException
+ {
+ this.input.close();
+ this.output.close();
+ }
+
+ public OutputStream getOutputStream()
+ {
+ return output;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/io/TeeOutputStream.java b/core/src/main/java/org/spongycastle/util/io/TeeOutputStream.java
new file mode 100644
index 00000000..c7cdcf6e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/io/TeeOutputStream.java
@@ -0,0 +1,62 @@
+package org.spongycastle.util.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+
+/**
+ * An output stream which copies anything written into it to another stream.
+ */
+public class TeeOutputStream
+ extends OutputStream
+{
+ private OutputStream output1;
+ private OutputStream output2;
+
+ /**
+ * Base constructor.
+ *
+ * @param output1 the output stream that is wrapped.
+ * @param output2 a secondary stream that anything written to output1 is also written to.
+ */
+ public TeeOutputStream(OutputStream output1, OutputStream output2)
+ {
+ this.output1 = output1;
+ this.output2 = output2;
+ }
+
+ public void write(byte[] buf)
+ throws IOException
+ {
+ this.output1.write(buf);
+ this.output2.write(buf);
+ }
+
+ public void write(byte[] buf, int off, int len)
+ throws IOException
+ {
+ this.output1.write(buf, off, len);
+ this.output2.write(buf, off, len);
+ }
+
+ public void write(int b)
+ throws IOException
+ {
+ this.output1.write(b);
+ this.output2.write(b);
+ }
+
+ public void flush()
+ throws IOException
+ {
+ this.output1.flush();
+ this.output2.flush();
+ }
+
+ public void close()
+ throws IOException
+ {
+ this.output1.close();
+ this.output2.close();
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/org/spongycastle/util/io/pem/PemGenerationException.java b/core/src/main/java/org/spongycastle/util/io/pem/PemGenerationException.java
new file mode 100644
index 00000000..676b82d1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/io/pem/PemGenerationException.java
@@ -0,0 +1,28 @@
+package org.spongycastle.util.io.pem;
+
+import java.io.IOException;
+
+/**
+ * Exception thrown on failure to generate a PEM object.
+ */
+public class PemGenerationException
+ extends IOException
+{
+ private Throwable cause;
+
+ public PemGenerationException(String message, Throwable cause)
+ {
+ super(message);
+ this.cause = cause;
+ }
+
+ public PemGenerationException(String message)
+ {
+ super(message);
+ }
+
+ public Throwable getCause()
+ {
+ return cause;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/io/pem/PemHeader.java b/core/src/main/java/org/spongycastle/util/io/pem/PemHeader.java
new file mode 100644
index 00000000..14293267
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/io/pem/PemHeader.java
@@ -0,0 +1,75 @@
+package org.spongycastle.util.io.pem;
+
+/**
+ * Class representing a PEM header (name, value) pair.
+ */
+public class PemHeader
+{
+ private String name;
+ private String value;
+
+ /**
+ * Base constructor.
+ *
+ * @param name name of the header property.
+ * @param value value of the header property.
+ */
+ public PemHeader(String name, String value)
+ {
+ this.name = name;
+ this.value = value;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public String getValue()
+ {
+ return value;
+ }
+
+ public int hashCode()
+ {
+ return getHashCode(this.name) + 31 * getHashCode(this.value);
+ }
+
+ public boolean equals(Object o)
+ {
+ if (!(o instanceof PemHeader))
+ {
+ return false;
+ }
+
+ PemHeader other = (PemHeader)o;
+
+ return other == this || (isEqual(this.name, other.name) && isEqual(this.value, other.value));
+ }
+
+ private int getHashCode(String s)
+ {
+ if (s == null)
+ {
+ return 1;
+ }
+
+ return s.hashCode();
+ }
+
+ private boolean isEqual(String s1, String s2)
+ {
+ if (s1 == s2)
+ {
+ return true;
+ }
+
+ if (s1 == null || s2 == null)
+ {
+ return false;
+ }
+
+ return s1.equals(s2);
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/util/io/pem/PemObject.java b/core/src/main/java/org/spongycastle/util/io/pem/PemObject.java
new file mode 100644
index 00000000..16c5c4f5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/io/pem/PemObject.java
@@ -0,0 +1,64 @@
+package org.spongycastle.util.io.pem;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A generic PEM object - type, header properties, and byte content.
+ */
+public class PemObject
+ implements PemObjectGenerator
+{
+ private static final List EMPTY_LIST = Collections.unmodifiableList(new ArrayList());
+
+ private String type;
+ private List headers;
+ private byte[] content;
+
+ /**
+ * Generic constructor for object without headers.
+ *
+ * @param type pem object type.
+ * @param content the binary content of the object.
+ */
+ public PemObject(String type, byte[] content)
+ {
+ this(type, EMPTY_LIST, content);
+ }
+
+ /**
+ * Generic constructor for object with headers.
+ *
+ * @param type pem object type.
+ * @param headers a list of PemHeader objects.
+ * @param content the binary content of the object.
+ */
+ public PemObject(String type, List headers, byte[] content)
+ {
+ this.type = type;
+ this.headers = Collections.unmodifiableList(headers);
+ this.content = content;
+ }
+
+ public String getType()
+ {
+ return type;
+ }
+
+ public List getHeaders()
+ {
+ return headers;
+ }
+
+ public byte[] getContent()
+ {
+ return content;
+ }
+
+ public PemObject generate()
+ throws PemGenerationException
+ {
+ return this;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/io/pem/PemObjectGenerator.java b/core/src/main/java/org/spongycastle/util/io/pem/PemObjectGenerator.java
new file mode 100644
index 00000000..0df180ce
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/io/pem/PemObjectGenerator.java
@@ -0,0 +1,16 @@
+package org.spongycastle.util.io.pem;
+
+/**
+ * Base interface for generators of PEM objects.
+ */
+public interface PemObjectGenerator
+{
+ /**
+ * Generate a PEM object.
+ *
+ * @return the generated object.
+ * @throws PemGenerationException on failure.
+ */
+ PemObject generate()
+ throws PemGenerationException;
+}
diff --git a/core/src/main/java/org/spongycastle/util/io/pem/PemObjectParser.java b/core/src/main/java/org/spongycastle/util/io/pem/PemObjectParser.java
new file mode 100644
index 00000000..5192078f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/io/pem/PemObjectParser.java
@@ -0,0 +1,19 @@
+package org.spongycastle.util.io.pem;
+
+import java.io.IOException;
+
+/**
+ * Base interface for parsers to convert PEM objects into specific objects.
+ */
+public interface PemObjectParser
+{
+ /**
+ * Parse an object out of the PEM object passed in.
+ *
+ * @param obj the PEM object containing the details for the specific object.
+ * @return a specific object represented by the PEM object.
+ * @throws IOException on a parsing error.
+ */
+ Object parseObject(PemObject obj)
+ throws IOException;
+}
diff --git a/core/src/main/java/org/spongycastle/util/io/pem/PemReader.java b/core/src/main/java/org/spongycastle/util/io/pem/PemReader.java
new file mode 100644
index 00000000..0b909167
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/io/pem/PemReader.java
@@ -0,0 +1,87 @@
+package org.spongycastle.util.io.pem;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.spongycastle.util.encoders.Base64;
+
+/**
+ * A generic PEM reader, based on the format outlined in RFC 1421
+ */
+public class PemReader
+ extends BufferedReader
+{
+ private static final String BEGIN = "-----BEGIN ";
+ private static final String END = "-----END ";
+
+ public PemReader(Reader reader)
+ {
+ super(reader);
+ }
+
+ public PemObject readPemObject()
+ throws IOException
+ {
+ String line = readLine();
+
+ while (line != null && !line.startsWith(BEGIN))
+ {
+ line = readLine();
+ }
+
+ if (line != null)
+ {
+ line = line.substring(BEGIN.length());
+ int index = line.indexOf('-');
+ String type = line.substring(0, index);
+
+ if (index > 0)
+ {
+ return loadObject(type);
+ }
+ }
+
+ return null;
+ }
+
+ private PemObject loadObject(String type)
+ throws IOException
+ {
+ String line;
+ String endMarker = END + type;
+ StringBuffer buf = new StringBuffer();
+ List headers = new ArrayList();
+
+ while ((line = readLine()) != null)
+ {
+ if (line.indexOf(":") >= 0)
+ {
+ int index = line.indexOf(':');
+ String hdr = line.substring(0, index);
+ String value = line.substring(index + 1).trim();
+
+ headers.add(new PemHeader(hdr, value));
+
+ continue;
+ }
+
+ if (line.indexOf(endMarker) != -1)
+ {
+ break;
+ }
+
+ buf.append(line.trim());
+ }
+
+ if (line == null)
+ {
+ throw new IOException(endMarker + " not found");
+ }
+
+ return new PemObject(type, headers, Base64.decode(buf.toString()));
+ }
+
+}
diff --git a/core/src/main/java/org/spongycastle/util/io/pem/PemWriter.java b/core/src/main/java/org/spongycastle/util/io/pem/PemWriter.java
new file mode 100644
index 00000000..02dde96b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/io/pem/PemWriter.java
@@ -0,0 +1,137 @@
+package org.spongycastle.util.io.pem;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Iterator;
+
+import org.spongycastle.util.encoders.Base64;
+
+/**
+ * A generic PEM writer, based on RFC 1421
+ */
+public class PemWriter
+ extends BufferedWriter
+{
+ private static final int LINE_LENGTH = 64;
+
+ private final int nlLength;
+ private char[] buf = new char[LINE_LENGTH];
+
+ /**
+ * Base constructor.
+ *
+ * @param out output stream to use.
+ */
+ public PemWriter(Writer out)
+ {
+ super(out);
+
+ String nl = System.getProperty("line.separator");
+ if (nl != null)
+ {
+ nlLength = nl.length();
+ }
+ else
+ {
+ nlLength = 2;
+ }
+ }
+
+ /**
+ * Return the number of bytes or characters required to contain the
+ * passed in object if it is PEM encoded.
+ *
+ * @param obj pem object to be output
+ * @return an estimate of the number of bytes
+ */
+ public int getOutputSize(PemObject obj)
+ {
+ // BEGIN and END boundaries.
+ int size = (2 * (obj.getType().length() + 10 + nlLength)) + 6 + 4;
+
+ if (!obj.getHeaders().isEmpty())
+ {
+ for (Iterator it = obj.getHeaders().iterator(); it.hasNext();)
+ {
+ PemHeader hdr = (PemHeader)it.next();
+
+ size += hdr.getName().length() + ": ".length() + hdr.getValue().length() + nlLength;
+ }
+
+ size += nlLength;
+ }
+
+ // base64 encoding
+ int dataLen = ((obj.getContent().length + 2) / 3) * 4;
+
+ size += dataLen + (((dataLen + LINE_LENGTH - 1) / LINE_LENGTH) * nlLength);
+
+ return size;
+ }
+
+ public void writeObject(PemObjectGenerator objGen)
+ throws IOException
+ {
+ PemObject obj = objGen.generate();
+
+ writePreEncapsulationBoundary(obj.getType());
+
+ if (!obj.getHeaders().isEmpty())
+ {
+ for (Iterator it = obj.getHeaders().iterator(); it.hasNext();)
+ {
+ PemHeader hdr = (PemHeader)it.next();
+
+ this.write(hdr.getName());
+ this.write(": ");
+ this.write(hdr.getValue());
+ this.newLine();
+ }
+
+ this.newLine();
+ }
+
+ writeEncoded(obj.getContent());
+ writePostEncapsulationBoundary(obj.getType());
+ }
+
+ private void writeEncoded(byte[] bytes)
+ throws IOException
+ {
+ bytes = Base64.encode(bytes);
+
+ for (int i = 0; i < bytes.length; i += buf.length)
+ {
+ int index = 0;
+
+ while (index != buf.length)
+ {
+ if ((i + index) >= bytes.length)
+ {
+ break;
+ }
+ buf[index] = (char)bytes[i + index];
+ index++;
+ }
+ this.write(buf, 0, index);
+ this.newLine();
+ }
+ }
+
+ private void writePreEncapsulationBoundary(
+ String type)
+ throws IOException
+ {
+ this.write("-----BEGIN " + type + "-----");
+ this.newLine();
+ }
+
+ private void writePostEncapsulationBoundary(
+ String type)
+ throws IOException
+ {
+ this.write("-----END " + type + "-----");
+ this.newLine();
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/test/FixedSecureRandom.java b/core/src/main/java/org/spongycastle/util/test/FixedSecureRandom.java
new file mode 100644
index 00000000..a11f5e91
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/test/FixedSecureRandom.java
@@ -0,0 +1,135 @@
+package org.spongycastle.util.test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.SecureRandom;
+
+public class FixedSecureRandom
+ extends SecureRandom
+{
+ private byte[] _data;
+
+ private int _index;
+ private int _intPad;
+
+ public FixedSecureRandom(byte[] value)
+ {
+ this(false, new byte[][] { value });
+ }
+
+ public FixedSecureRandom(
+ byte[][] values)
+ {
+ this(false, values);
+ }
+
+ /**
+ * Pad the data on integer boundaries. This is necessary for the classpath project's BigInteger
+ * implementation.
+ */
+ public FixedSecureRandom(
+ boolean intPad,
+ byte[] value)
+ {
+ this(intPad, new byte[][] { value });
+ }
+
+ /**
+ * Pad the data on integer boundaries. This is necessary for the classpath project's BigInteger
+ * implementation.
+ */
+ public FixedSecureRandom(
+ boolean intPad,
+ byte[][] values)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ for (int i = 0; i != values.length; i++)
+ {
+ try
+ {
+ bOut.write(values[i]);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("can't save value array.");
+ }
+ }
+
+ _data = bOut.toByteArray();
+
+ if (intPad)
+ {
+ _intPad = _data.length % 4;
+ }
+ }
+
+ public void nextBytes(byte[] bytes)
+ {
+ System.arraycopy(_data, _index, bytes, 0, bytes.length);
+
+ _index += bytes.length;
+ }
+
+ //
+ // 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.
+ //
+ public int nextInt()
+ {
+ int val = 0;
+
+ val |= nextValue() << 24;
+ val |= nextValue() << 16;
+
+ if (_intPad == 2)
+ {
+ _intPad--;
+ }
+ else
+ {
+ val |= nextValue() << 8;
+ }
+
+ if (_intPad == 1)
+ {
+ _intPad--;
+ }
+ else
+ {
+ val |= nextValue();
+ }
+
+ return val;
+ }
+
+ //
+ // 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.
+ //
+ public long nextLong()
+ {
+ long val = 0;
+
+ val |= (long)nextValue() << 56;
+ val |= (long)nextValue() << 48;
+ val |= (long)nextValue() << 40;
+ val |= (long)nextValue() << 32;
+ val |= (long)nextValue() << 24;
+ val |= (long)nextValue() << 16;
+ val |= (long)nextValue() << 8;
+ val |= (long)nextValue();
+
+ return val;
+ }
+
+ public boolean isExhausted()
+ {
+ return _index == _data.length;
+ }
+
+ private int nextValue()
+ {
+ return _data[_index++] & 0xff;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/test/NumberParsing.java b/core/src/main/java/org/spongycastle/util/test/NumberParsing.java
new file mode 100644
index 00000000..2082cb71
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/test/NumberParsing.java
@@ -0,0 +1,34 @@
+package org.spongycastle.util.test;
+
+/**
+ * Parsing
+ */
+public final class NumberParsing
+{
+ private NumberParsing()
+ {
+ // Hide constructor
+ }
+
+ public static long decodeLongFromHex(String longAsString)
+ {
+ if ((longAsString.charAt(1) == 'x')
+ || (longAsString.charAt(1) == 'X'))
+ {
+ return Long.parseLong(longAsString.substring(2), 16);
+ }
+
+ return Long.parseLong(longAsString, 16);
+ }
+
+ public static int decodeIntFromHex(String intAsString)
+ {
+ if ((intAsString.charAt(1) == 'x')
+ || (intAsString.charAt(1) == 'X'))
+ {
+ return Integer.parseInt(intAsString.substring(2), 16);
+ }
+
+ return Integer.parseInt(intAsString, 16);
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/test/SimpleTest.java b/core/src/main/java/org/spongycastle/util/test/SimpleTest.java
new file mode 100644
index 00000000..e5508355
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/test/SimpleTest.java
@@ -0,0 +1,84 @@
+package org.spongycastle.util.test;
+
+import java.io.PrintStream;
+
+import org.spongycastle.util.Arrays;
+
+public abstract class SimpleTest
+ implements Test
+{
+ public abstract String getName();
+
+ private TestResult success()
+ {
+ return SimpleTestResult.successful(this, "Okay");
+ }
+
+ protected void fail(
+ String message)
+ {
+ throw new TestFailedException(SimpleTestResult.failed(this, message));
+ }
+
+ protected void fail(
+ String message,
+ Throwable throwable)
+ {
+ throw new TestFailedException(SimpleTestResult.failed(this, message, throwable));
+ }
+
+ protected void fail(
+ String message,
+ Object expected,
+ Object found)
+ {
+ throw new TestFailedException(SimpleTestResult.failed(this, message, expected, found));
+ }
+
+ protected boolean areEqual(
+ byte[] a,
+ byte[] b)
+ {
+ return Arrays.areEqual(a, b);
+ }
+
+ public TestResult perform()
+ {
+ try
+ {
+ performTest();
+
+ return success();
+ }
+ catch (TestFailedException e)
+ {
+ return e.getResult();
+ }
+ catch (Exception e)
+ {
+ return SimpleTestResult.failed(this, "Exception: " + e, e);
+ }
+ }
+
+ protected static void runTest(
+ Test test)
+ {
+ runTest(test, System.out);
+ }
+
+ protected static void runTest(
+ Test test,
+ PrintStream out)
+ {
+ TestResult result = test.perform();
+
+ out.println(result.toString());
+ if (result.getException() != null)
+ {
+ result.getException().printStackTrace(out);
+ }
+ }
+
+ public abstract void performTest()
+ throws Exception;
+}
diff --git a/core/src/main/java/org/spongycastle/util/test/SimpleTestResult.java b/core/src/main/java/org/spongycastle/util/test/SimpleTestResult.java
new file mode 100644
index 00000000..cb47c91a
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/test/SimpleTestResult.java
@@ -0,0 +1,80 @@
+package org.spongycastle.util.test;
+
+public class SimpleTestResult implements TestResult
+{
+ private static final String SEPARATOR = System.getProperty("line.separator");
+
+ private boolean success;
+ private String message;
+ private Throwable exception;
+
+ public SimpleTestResult(boolean success, String message)
+ {
+ this.success = success;
+ this.message = message;
+ }
+
+ public SimpleTestResult(boolean success, String message, Throwable exception)
+ {
+ this.success = success;
+ this.message = message;
+ this.exception = exception;
+ }
+
+ public static TestResult successful(
+ Test test,
+ String message)
+ {
+ return new SimpleTestResult(true, test.getName() + ": " + message);
+ }
+
+ public static TestResult failed(
+ Test test,
+ String message)
+ {
+ return new SimpleTestResult(false, test.getName() + ": " + message);
+ }
+
+ public static TestResult failed(
+ Test test,
+ String message,
+ Throwable t)
+ {
+ return new SimpleTestResult(false, test.getName() + ": " + message, t);
+ }
+
+ public static TestResult failed(
+ Test test,
+ String message,
+ Object expected,
+ Object found)
+ {
+ return failed(test, message + SEPARATOR + "Expected: " + expected + SEPARATOR + "Found : " + found);
+ }
+
+ public static String failedMessage(String algorithm, String testName, String expected,
+ String actual)
+ {
+ StringBuffer sb = new StringBuffer(algorithm);
+ sb.append(" failing ").append(testName);
+ sb.append(SEPARATOR).append(" expected: ").append(expected);
+ sb.append(SEPARATOR).append(" got : ").append(actual);
+
+ return sb.toString();
+ }
+
+ public boolean isSuccessful()
+ {
+ return success;
+ }
+
+ public String toString()
+ {
+ return message;
+ }
+
+ public Throwable getException()
+ {
+ return exception;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/test/Test.java b/core/src/main/java/org/spongycastle/util/test/Test.java
new file mode 100644
index 00000000..50a9f2e2
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/test/Test.java
@@ -0,0 +1,8 @@
+package org.spongycastle.util.test;
+
+public interface Test
+{
+ String getName();
+
+ TestResult perform();
+}
diff --git a/core/src/main/java/org/spongycastle/util/test/TestFailedException.java b/core/src/main/java/org/spongycastle/util/test/TestFailedException.java
new file mode 100644
index 00000000..e3d7180f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/test/TestFailedException.java
@@ -0,0 +1,18 @@
+package org.spongycastle.util.test;
+
+public class TestFailedException
+ extends RuntimeException
+{
+ private TestResult _result;
+
+ public TestFailedException(
+ TestResult result)
+ {
+ _result = result;
+ }
+
+ public TestResult getResult()
+ {
+ return _result;
+ }
+}
diff --git a/core/src/main/java/org/spongycastle/util/test/TestResult.java b/core/src/main/java/org/spongycastle/util/test/TestResult.java
new file mode 100644
index 00000000..edf3803e
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/test/TestResult.java
@@ -0,0 +1,10 @@
+package org.spongycastle.util.test;
+
+public interface TestResult
+{
+ public boolean isSuccessful();
+
+ public Throwable getException();
+
+ public String toString();
+}
diff --git a/core/src/main/java/org/spongycastle/util/test/UncloseableOutputStream.java b/core/src/main/java/org/spongycastle/util/test/UncloseableOutputStream.java
new file mode 100644
index 00000000..55e9dc2d
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/test/UncloseableOutputStream.java
@@ -0,0 +1,23 @@
+package org.spongycastle.util.test;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class UncloseableOutputStream extends FilterOutputStream
+{
+ public UncloseableOutputStream(OutputStream s)
+ {
+ super(s);
+ }
+
+ public void close()
+ {
+ throw new RuntimeException("close() called on UncloseableOutputStream");
+ }
+
+ public void write(byte[] b, int off, int len) throws IOException
+ {
+ out.write(b, off, len);
+ }
+ }
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/bc/package.html b/core/src/main/javadoc/org/spongycastle/asn1/bc/package.html
index a8beb00a..a8beb00a 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/bc/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/bc/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/bsi/package.html b/core/src/main/javadoc/org/spongycastle/asn1/bsi/package.html
index be9bd80b..be9bd80b 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/bsi/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/bsi/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/cmp/package.html b/core/src/main/javadoc/org/spongycastle/asn1/cmp/package.html
index d5ce6b95..d5ce6b95 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/cmp/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/cmp/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/cms/ecc/package.html b/core/src/main/javadoc/org/spongycastle/asn1/cms/ecc/package.html
index 9d330250..9d330250 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/cms/ecc/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/cms/ecc/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/cms/package.html b/core/src/main/javadoc/org/spongycastle/asn1/cms/package.html
index c165a7a6..c165a7a6 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/cms/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/cms/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/crmf/package.html b/core/src/main/javadoc/org/spongycastle/asn1/crmf/package.html
index c8049240..c8049240 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/crmf/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/crmf/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/cryptopro/package.html b/core/src/main/javadoc/org/spongycastle/asn1/cryptopro/package.html
index 2b0af9e0..2b0af9e0 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/cryptopro/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/cryptopro/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/dvcs/package.html b/core/src/main/javadoc/org/spongycastle/asn1/dvcs/package.html
index a9419222..a9419222 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/dvcs/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/dvcs/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/eac/package.html b/core/src/main/javadoc/org/spongycastle/asn1/eac/package.html
index 360d598b..360d598b 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/eac/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/eac/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/esf/package.html b/core/src/main/javadoc/org/spongycastle/asn1/esf/package.html
index de273675..de273675 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/esf/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/esf/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/ess/package.html b/core/src/main/javadoc/org/spongycastle/asn1/ess/package.html
index 21854b36..21854b36 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/ess/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/ess/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/gnu/package.html b/core/src/main/javadoc/org/spongycastle/asn1/gnu/package.html
index cdb9f59d..cdb9f59d 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/gnu/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/gnu/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/iana/package.html b/core/src/main/javadoc/org/spongycastle/asn1/iana/package.html
index bb60b438..bb60b438 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/iana/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/iana/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/icao/package.html b/core/src/main/javadoc/org/spongycastle/asn1/icao/package.html
index f2301dbe..f2301dbe 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/icao/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/icao/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/isismtt/ocsp/package.html b/core/src/main/javadoc/org/spongycastle/asn1/isismtt/ocsp/package.html
index cd95ca33..cd95ca33 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/isismtt/ocsp/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/isismtt/ocsp/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/isismtt/package.html b/core/src/main/javadoc/org/spongycastle/asn1/isismtt/package.html
index 14ab3901..14ab3901 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/isismtt/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/isismtt/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/isismtt/x509/package.html b/core/src/main/javadoc/org/spongycastle/asn1/isismtt/x509/package.html
index fa411ec7..fa411ec7 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/isismtt/x509/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/isismtt/x509/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/kisa/package.html b/core/src/main/javadoc/org/spongycastle/asn1/kisa/package.html
index 48b5afdf..48b5afdf 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/kisa/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/kisa/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/microsoft/package.html b/core/src/main/javadoc/org/spongycastle/asn1/microsoft/package.html
index 35d12486..35d12486 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/microsoft/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/microsoft/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/misc/package.html b/core/src/main/javadoc/org/spongycastle/asn1/misc/package.html
index e3bda640..e3bda640 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/misc/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/misc/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/mozilla/package.html b/core/src/main/javadoc/org/spongycastle/asn1/mozilla/package.html
index 40776b01..40776b01 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/mozilla/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/mozilla/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/nist/package.html b/core/src/main/javadoc/org/spongycastle/asn1/nist/package.html
index 1cdca769..1cdca769 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/nist/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/nist/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/ntt/package.html b/core/src/main/javadoc/org/spongycastle/asn1/ntt/package.html
index 4b9d05dd..4b9d05dd 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/ntt/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/ntt/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/ocsp/package.html b/core/src/main/javadoc/org/spongycastle/asn1/ocsp/package.html
index 22c560d2..22c560d2 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/ocsp/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/ocsp/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/oiw/package.html b/core/src/main/javadoc/org/spongycastle/asn1/oiw/package.html
index 44eb2fe8..44eb2fe8 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/oiw/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/oiw/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/package.html b/core/src/main/javadoc/org/spongycastle/asn1/package.html
index 1ac16a55..1ac16a55 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/pkcs/package.html b/core/src/main/javadoc/org/spongycastle/asn1/pkcs/package.html
index ab800f44..ab800f44 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/pkcs/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/pkcs/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/sec/package.html b/core/src/main/javadoc/org/spongycastle/asn1/sec/package.html
index 5e34dec4..5e34dec4 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/sec/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/sec/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/smime/package.html b/core/src/main/javadoc/org/spongycastle/asn1/smime/package.html
index d527abad..d527abad 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/smime/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/smime/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/teletrust/package.html b/core/src/main/javadoc/org/spongycastle/asn1/teletrust/package.html
index 86606c39..86606c39 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/teletrust/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/teletrust/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/tsp/package.html b/core/src/main/javadoc/org/spongycastle/asn1/tsp/package.html
index d6265f04..d6265f04 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/tsp/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/tsp/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/ua/package.html b/core/src/main/javadoc/org/spongycastle/asn1/ua/package.html
index 0fc273f1..0fc273f1 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/ua/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/ua/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/util/package.html b/core/src/main/javadoc/org/spongycastle/asn1/util/package.html
index 1db893d1..1db893d1 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/util/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/util/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/x500/package.html b/core/src/main/javadoc/org/spongycastle/asn1/x500/package.html
index 9a3f9c60..9a3f9c60 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/x500/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/x500/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/x500/style/package.html b/core/src/main/javadoc/org/spongycastle/asn1/x500/style/package.html
index 219d3f54..219d3f54 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/x500/style/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/x500/style/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/x509/package.html b/core/src/main/javadoc/org/spongycastle/asn1/x509/package.html
index 728921a1..728921a1 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/x509/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/x509/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/x509/qualified/package.html b/core/src/main/javadoc/org/spongycastle/asn1/x509/qualified/package.html
index 28cfef90..28cfef90 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/x509/qualified/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/x509/qualified/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/x509/sigi/package.html b/core/src/main/javadoc/org/spongycastle/asn1/x509/sigi/package.html
index 4e073cef..4e073cef 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/x509/sigi/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/x509/sigi/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/asn1/x9/package.html b/core/src/main/javadoc/org/spongycastle/asn1/x9/package.html
index 42fc97c7..42fc97c7 100644
--- a/core/src/main/javadoc/org/bouncycastle/asn1/x9/package.html
+++ b/core/src/main/javadoc/org/spongycastle/asn1/x9/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/agreement/jpake/package.html b/core/src/main/javadoc/org/spongycastle/crypto/agreement/jpake/package.html
index df16b4fe..df16b4fe 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/agreement/jpake/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/agreement/jpake/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/agreement/kdf/package.html b/core/src/main/javadoc/org/spongycastle/crypto/agreement/kdf/package.html
index a00160f3..a00160f3 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/agreement/kdf/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/agreement/kdf/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/agreement/package.html b/core/src/main/javadoc/org/spongycastle/crypto/agreement/package.html
index 4b49331c..4b49331c 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/agreement/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/agreement/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/agreement/srp/package.html b/core/src/main/javadoc/org/spongycastle/crypto/agreement/srp/package.html
index c125ffe2..c125ffe2 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/agreement/srp/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/agreement/srp/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/commitments/package.html b/core/src/main/javadoc/org/spongycastle/crypto/commitments/package.html
index 5bab3fc1..5bab3fc1 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/commitments/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/commitments/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/digests/package.html b/core/src/main/javadoc/org/spongycastle/crypto/digests/package.html
index 0a0d95ce..0a0d95ce 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/digests/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/digests/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/ec/package.html b/core/src/main/javadoc/org/spongycastle/crypto/ec/package.html
index 223823e7..223823e7 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/ec/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/ec/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/encodings/package.html b/core/src/main/javadoc/org/spongycastle/crypto/encodings/package.html
index fc56f634..fc56f634 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/encodings/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/encodings/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/engines/package.html b/core/src/main/javadoc/org/spongycastle/crypto/engines/package.html
index e945dac0..e945dac0 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/engines/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/engines/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/examples/package.html b/core/src/main/javadoc/org/spongycastle/crypto/examples/package.html
index 390a5400..390a5400 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/examples/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/examples/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/generators/package.html b/core/src/main/javadoc/org/spongycastle/crypto/generators/package.html
index 9d73ce3e..9d73ce3e 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/generators/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/generators/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/io/package.html b/core/src/main/javadoc/org/spongycastle/crypto/io/package.html
index f2c9e406..f2c9e406 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/io/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/io/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/kems/package.html b/core/src/main/javadoc/org/spongycastle/crypto/kems/package.html
index 88fddd0e..88fddd0e 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/kems/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/kems/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/macs/package.html b/core/src/main/javadoc/org/spongycastle/crypto/macs/package.html
index 0b1f86dd..0b1f86dd 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/macs/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/macs/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/modes/gcm/package.html b/core/src/main/javadoc/org/spongycastle/crypto/modes/gcm/package.html
index 09c42f03..09c42f03 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/modes/gcm/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/modes/gcm/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/modes/package.html b/core/src/main/javadoc/org/spongycastle/crypto/modes/package.html
index 5402df44..5402df44 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/modes/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/modes/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/package.html b/core/src/main/javadoc/org/spongycastle/crypto/package.html
index ee5487ff..ee5487ff 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/paddings/package.html b/core/src/main/javadoc/org/spongycastle/crypto/paddings/package.html
index 2b82e60f..2b82e60f 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/paddings/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/paddings/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/params/package.html b/core/src/main/javadoc/org/spongycastle/crypto/params/package.html
index 4e00a754..4e00a754 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/params/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/params/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/parsers/package.html b/core/src/main/javadoc/org/spongycastle/crypto/parsers/package.html
index 03d05c79..03d05c79 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/parsers/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/parsers/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/prng/drbg/package.html b/core/src/main/javadoc/org/spongycastle/crypto/prng/drbg/package.html
index c0061660..c0061660 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/prng/drbg/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/prng/drbg/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/prng/package.html b/core/src/main/javadoc/org/spongycastle/crypto/prng/package.html
index bb583abd..bb583abd 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/prng/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/prng/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/signers/package.html b/core/src/main/javadoc/org/spongycastle/crypto/signers/package.html
index 151d3d5e..151d3d5e 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/signers/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/signers/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/tls/package.html b/core/src/main/javadoc/org/spongycastle/crypto/tls/package.html
index ee59f8af..ee59f8af 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/tls/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/tls/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/crypto/util/package.html b/core/src/main/javadoc/org/spongycastle/crypto/util/package.html
index 787b892e..787b892e 100644
--- a/core/src/main/javadoc/org/bouncycastle/crypto/util/package.html
+++ b/core/src/main/javadoc/org/spongycastle/crypto/util/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/math/ec/custom/djb/package.html b/core/src/main/javadoc/org/spongycastle/math/ec/custom/djb/package.html
index 344418b9..344418b9 100644
--- a/core/src/main/javadoc/org/bouncycastle/math/ec/custom/djb/package.html
+++ b/core/src/main/javadoc/org/spongycastle/math/ec/custom/djb/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/math/ec/custom/sec/package.html b/core/src/main/javadoc/org/spongycastle/math/ec/custom/sec/package.html
index bb2845c3..bb2845c3 100644
--- a/core/src/main/javadoc/org/bouncycastle/math/ec/custom/sec/package.html
+++ b/core/src/main/javadoc/org/spongycastle/math/ec/custom/sec/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/math/ec/package.html b/core/src/main/javadoc/org/spongycastle/math/ec/package.html
index a02605ba..a02605ba 100644
--- a/core/src/main/javadoc/org/bouncycastle/math/ec/package.html
+++ b/core/src/main/javadoc/org/spongycastle/math/ec/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/math/raw/package.html b/core/src/main/javadoc/org/spongycastle/math/raw/package.html
index 061958b7..061958b7 100644
--- a/core/src/main/javadoc/org/bouncycastle/math/raw/package.html
+++ b/core/src/main/javadoc/org/spongycastle/math/raw/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/util/encoders/package.html b/core/src/main/javadoc/org/spongycastle/util/encoders/package.html
index 3be222b2..3be222b2 100644
--- a/core/src/main/javadoc/org/bouncycastle/util/encoders/package.html
+++ b/core/src/main/javadoc/org/spongycastle/util/encoders/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/util/io/package.html b/core/src/main/javadoc/org/spongycastle/util/io/package.html
index e987ccaf..e987ccaf 100644
--- a/core/src/main/javadoc/org/bouncycastle/util/io/package.html
+++ b/core/src/main/javadoc/org/spongycastle/util/io/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/util/io/pem/package.html b/core/src/main/javadoc/org/spongycastle/util/io/pem/package.html
index c5cc4a5d..c5cc4a5d 100644
--- a/core/src/main/javadoc/org/bouncycastle/util/io/pem/package.html
+++ b/core/src/main/javadoc/org/spongycastle/util/io/pem/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/util/package.html b/core/src/main/javadoc/org/spongycastle/util/package.html
index c9247ea4..c9247ea4 100644
--- a/core/src/main/javadoc/org/bouncycastle/util/package.html
+++ b/core/src/main/javadoc/org/spongycastle/util/package.html
diff --git a/core/src/main/javadoc/org/bouncycastle/util/test/package.html b/core/src/main/javadoc/org/spongycastle/util/test/package.html
index e723fd11..e723fd11 100644
--- a/core/src/main/javadoc/org/bouncycastle/util/test/package.html
+++ b/core/src/main/javadoc/org/spongycastle/util/test/package.html
diff --git a/core/src/main/jdk1.1/java/security/cert/CertUtil.java b/core/src/main/jdk1.1/java/security/cert/CertUtil.java
index c390efa9..216a8d8e 100644
--- a/core/src/main/jdk1.1/java/security/cert/CertUtil.java
+++ b/core/src/main/jdk1.1/java/security/cert/CertUtil.java
@@ -7,13 +7,13 @@ import java.security.NoSuchProviderException;
import java.security.Provider;
import java.security.Security;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DEROutputStream;
-import org.bouncycastle.asn1.OIDTokenizer;
-import org.bouncycastle.asn1.x509.X509Name;
-import org.bouncycastle.util.Strings;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.DEROutputStream;
+import org.spongycastle.asn1.OIDTokenizer;
+import org.spongycastle.asn1.x509.X509Name;
+import org.spongycastle.util.Strings;
class CertUtil
{
@@ -287,7 +287,7 @@ class CertUtil
* Throw an IOException if the first component is not 0, 1 or 2 or the
* second component is greater than 39.<br />
* <br />
- * User {@link org.bouncycastle.asn1.OIDTokenizer OIDTokenizer}
+ * User {@link org.spongycastle.asn1.OIDTokenizer OIDTokenizer}
*
* @param the
* OID to be checked.
diff --git a/core/src/main/jdk1.1/java/security/cert/PolicyQualifierInfo.java b/core/src/main/jdk1.1/java/security/cert/PolicyQualifierInfo.java
index 5073669e..a17f49bf 100644
--- a/core/src/main/jdk1.1/java/security/cert/PolicyQualifierInfo.java
+++ b/core/src/main/jdk1.1/java/security/cert/PolicyQualifierInfo.java
@@ -4,12 +4,12 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEROutputStream;
-import org.bouncycastle.asn1.util.ASN1Dump;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROutputStream;
+import org.spongycastle.asn1.util.ASN1Dump;
/**
* An immutable policy qualifier represented by the ASN.1 PolicyQualifierInfo
@@ -63,11 +63,11 @@ import org.bouncycastle.asn1.util.ASN1Dump;
* allows them to be passed around to various pieces of code without worrying
* about coordinating access.<br />
* <br />
- * Uses {@link org.bouncycastle.asn1.ASN1InputStream ASN1InputStream},
- * {@link org.bouncycastle.asn1.ASN1Sequence ASN1Sequence},
- * {@link org.bouncycastle.asn1.ASN1ObjectIdentifier ASN1ObjectIdentifier},
- * {@link org.bouncycastle.asn1.DEROutputStream DEROutputStream},
- * {@link org.bouncycastle.asn1.ASN1Object ASN1Object}
+ * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream},
+ * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence},
+ * {@link org.spongycastle.asn1.ASN1ObjectIdentifier ASN1ObjectIdentifier},
+ * {@link org.spongycastle.asn1.DEROutputStream DEROutputStream},
+ * {@link org.spongycastle.asn1.ASN1Object ASN1Object}
*/
public final class PolicyQualifierInfo
{
@@ -81,10 +81,10 @@ public final class PolicyQualifierInfo
* Creates an instance of <code>PolicyQualifierInfo</code> from the
* encoded bytes. The encoded byte array is copied on construction.<br />
* <br />
- * Uses {@link org.bouncycastle.asn1.ASN1InputStream ASN1InputStream},
- * {@link org.bouncycastle.asn1.ASN1Sequence ASN1Sequence},
- * {@link org.bouncycastle.asn1.ASN1ObjectIdentifier ASN1ObjectIdentifier} and
- * {@link org.bouncycastle.asn1.DEROutputStream DEROutputStream}
+ * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream},
+ * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence},
+ * {@link org.spongycastle.asn1.ASN1ObjectIdentifier ASN1ObjectIdentifier} and
+ * {@link org.spongycastle.asn1.DEROutputStream DEROutputStream}
*
* @param encoded
* a byte array containing the qualifier in DER encoding
@@ -165,8 +165,8 @@ public final class PolicyQualifierInfo
* Return a printable representation of this
* <code>PolicyQualifierInfo</code>.<br />
* <br />
- * Uses {@link org.bouncycastle.asn1.ASN1InputStream ASN1InputStream},
- * {@link org.bouncycastle.asn1.ASN1Object ASN1Object}
+ * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream},
+ * {@link org.spongycastle.asn1.ASN1Object ASN1Object}
*
* @return a <code>String</code> describing the contents of this
* <code>PolicyQualifierInfo</code>
diff --git a/core/src/main/jdk1.1/java/security/cert/TrustAnchor.java b/core/src/main/jdk1.1/java/security/cert/TrustAnchor.java
index 23ced2f7..f139a742 100644
--- a/core/src/main/jdk1.1/java/security/cert/TrustAnchor.java
+++ b/core/src/main/jdk1.1/java/security/cert/TrustAnchor.java
@@ -5,9 +5,9 @@ import java.io.IOException;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1Sequence;
/**
* A trust anchor or most-trusted Certification Authority (CA). <br />
diff --git a/core/src/main/jdk1.1/java/security/cert/X509CRLSelector.java b/core/src/main/jdk1.1/java/security/cert/X509CRLSelector.java
index 5917765c..8d4ed9c4 100644
--- a/core/src/main/jdk1.1/java/security/cert/X509CRLSelector.java
+++ b/core/src/main/jdk1.1/java/security/cert/X509CRLSelector.java
@@ -12,14 +12,14 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.x509.X509Extensions;
-import org.bouncycastle.asn1.x509.X509Name;
-import org.bouncycastle.jce.PrincipalUtil;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.x509.X509Extensions;
+import org.spongycastle.asn1.x509.X509Name;
+import org.spongycastle.jce.PrincipalUtil;
/**
* A <code>CRLSelector</code> that selects <code>X509CRLs</code> that match
@@ -47,12 +47,12 @@ import org.bouncycastle.jce.PrincipalUtil;
* locking. Multiple threads each manipulating separate objects need not
* synchronize.<br />
* <br />
- * Uses {@link org.bouncycastle.asn1.ASN1InputStream ASN1InputStream},
- * {@link org.bouncycastle.asn1.ASN1Sequence ASN1Sequence},
- * {@link org.bouncycastle.asn1.ASN1ObjectIdentifier ASN1ObjectIdentifier},
- * {@link org.bouncycastle.asn1.DEROutputStream DEROutputStream},
- * {@link org.bouncycastle.asn1.ASN1Object ASN1Object},
- * {@link org.bouncycastle.asn1.x509.X509Name X509Name}
+ * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream},
+ * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence},
+ * {@link org.spongycastle.asn1.ASN1ObjectIdentifier ASN1ObjectIdentifier},
+ * {@link org.spongycastle.asn1.DEROutputStream DEROutputStream},
+ * {@link org.spongycastle.asn1.ASN1Object ASN1Object},
+ * {@link org.spongycastle.asn1.x509.X509Name X509Name}
*
* @see CRLSelector
* @see X509CRL
@@ -184,7 +184,7 @@ public class X509CRLSelector implements CRLSelector
* any previous value for the issuerNames criterion. If the specified name
* is a duplicate, it may be ignored.<br />
* <br />
- * Uses {@link org.bouncycastle.asn1.x509.X509Name X509Name} for parsing the
+ * Uses {@link org.spongycastle.asn1.x509.X509Name X509Name} for parsing the
* name
*
* @param name
@@ -233,10 +233,10 @@ public class X509CRLSelector implements CRLSelector
* Note that the byte array supplied here is cloned to protect against
* subsequent modifications.<br />
* <br />
- * Uses {@link org.bouncycastle.asn1.x509.X509Name X509Name} for parsing the
- * name, {@link org.bouncycastle.asn1.ASN1InputStream ASN1InputStream},
- * {@link org.bouncycastle.asn1.ASN1Object ASN1Object} and
- * {@link org.bouncycastle.asn1.ASN1Sequence ASN1Sequence}
+ * Uses {@link org.spongycastle.asn1.x509.X509Name X509Name} for parsing the
+ * name, {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream},
+ * {@link org.spongycastle.asn1.ASN1Object ASN1Object} and
+ * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence}
*
* @param name
* a byte array containing the name in ASN.1 DER encoded form
@@ -457,7 +457,7 @@ public class X509CRLSelector implements CRLSelector
* Returns a printable representation of the <code>X509CRLSelector</code>.<br />
* <br />
* Uses
- * {@link org.bouncycastle.asn1.x509.X509Name#toString X509Name.toString} to
+ * {@link org.spongycastle.asn1.x509.X509Name#toString X509Name.toString} to
* format the output
*
* @return a <code>String</code> describing the contents of the
@@ -500,9 +500,9 @@ public class X509CRLSelector implements CRLSelector
* Decides whether a <code>CRL</code> should be selected.<br />
* <br />
* Uses
- * {@link org.bouncycastle.asn1.x509.X509Name#toString X509Name.toString} to
+ * {@link org.spongycastle.asn1.x509.X509Name#toString X509Name.toString} to
* parse and to compare the crl parameter issuer and
- * {@link org.bouncycastle.asn1.x509.X509Extensions#CRLNumber CRLNumber} to
+ * {@link org.spongycastle.asn1.x509.X509Extensions#CRLNumber CRLNumber} to
* access the CRL number extension.
*
* @param crl
diff --git a/core/src/main/jdk1.1/java/security/cert/X509CertSelector.java b/core/src/main/jdk1.1/java/security/cert/X509CertSelector.java
index 0ac127f6..9292c2e3 100644
--- a/core/src/main/jdk1.1/java/security/cert/X509CertSelector.java
+++ b/core/src/main/jdk1.1/java/security/cert/X509CertSelector.java
@@ -20,24 +20,24 @@ import java.util.Iterator;
import java.util.List;
import java.util.Set;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.DERGeneralizedTime;
-import org.bouncycastle.asn1.DEROutputStream;
-import org.bouncycastle.asn1.util.ASN1Dump;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
-import org.bouncycastle.asn1.x509.KeyPurposeId;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.asn1.x509.X509Extensions;
-import org.bouncycastle.asn1.x509.X509Name;
-import org.bouncycastle.jce.PrincipalUtil;
-import org.bouncycastle.util.Integers;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.DERGeneralizedTime;
+import org.spongycastle.asn1.DEROutputStream;
+import org.spongycastle.asn1.util.ASN1Dump;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.ExtendedKeyUsage;
+import org.spongycastle.asn1.x509.KeyPurposeId;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.spongycastle.asn1.x509.X509Extensions;
+import org.spongycastle.asn1.x509.X509Name;
+import org.spongycastle.jce.PrincipalUtil;
+import org.spongycastle.util.Integers;
/**
* A <code>CertSelector</code> that selects
@@ -76,18 +76,18 @@ import org.bouncycastle.util.Integers;
* <b>TODO: implement name constraints</b>
* <b>TODO: implement match check for path to names</b><br />
* <br />
- * Uses {@link org.bouncycastle.asn1.ASN1InputStream ASN1InputStream},
- * {@link org.bouncycastle.asn1.ASN1Sequence ASN1Sequence},
- * {@link org.bouncycastle.asn1.ASN1ObjectIdentifier ASN1ObjectIdentifier},
- * {@link org.bouncycastle.asn1.DEROutputStream DEROutputStream},
- * {@link org.bouncycastle.asn1.ASN1Object ASN1Object},
- * {@link org.bouncycastle.asn1.OIDTokenizer OIDTokenizer},
- * {@link org.bouncycastle.asn1.x509.X509Name X509Name},
- * {@link org.bouncycastle.asn1.x509.X509Extensions X509Extensions},
- * {@link org.bouncycastle.asn1.x509.ExtendedKeyUsage ExtendedKeyUsage},
- * {@link org.bouncycastle.asn1.x509.KeyPurposeId KeyPurposeId},
- * {@link org.bouncycastle.asn1.x509.SubjectPublicKeyInfo SubjectPublicKeyInfo},
- * {@link org.bouncycastle.asn1.x509.AlgorithmIdentifier AlgorithmIdentifier}
+ * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream},
+ * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence},
+ * {@link org.spongycastle.asn1.ASN1ObjectIdentifier ASN1ObjectIdentifier},
+ * {@link org.spongycastle.asn1.DEROutputStream DEROutputStream},
+ * {@link org.spongycastle.asn1.ASN1Object ASN1Object},
+ * {@link org.spongycastle.asn1.OIDTokenizer OIDTokenizer},
+ * {@link org.spongycastle.asn1.x509.X509Name X509Name},
+ * {@link org.spongycastle.asn1.x509.X509Extensions X509Extensions},
+ * {@link org.spongycastle.asn1.x509.ExtendedKeyUsage ExtendedKeyUsage},
+ * {@link org.spongycastle.asn1.x509.KeyPurposeId KeyPurposeId},
+ * {@link org.spongycastle.asn1.x509.SubjectPublicKeyInfo SubjectPublicKeyInfo},
+ * {@link org.spongycastle.asn1.x509.AlgorithmIdentifier AlgorithmIdentifier}
*/
public class X509CertSelector implements CertSelector
{
@@ -210,7 +210,7 @@ public class X509CertSelector implements CertSelector
* If <code>issuerDN</code> is not <code>null</code>, it should contain
* a distinguished name, in RFC 2253 format.<br />
* <br />
- * Uses {@link org.bouncycastle.asn1.x509.X509Name X509Name} for parsing the
+ * Uses {@link org.spongycastle.asn1.x509.X509Name X509Name} for parsing the
* issuerDN.
*
* @param issuerDN
@@ -283,10 +283,10 @@ public class X509CertSelector implements CertSelector
* Note that the byte array specified here is cloned to protect against
* subsequent modifications.<br />
* <br />
- * Uses {@link org.bouncycastle.asn1.ASN1InputStream ASN1InputStream},
- * {@link org.bouncycastle.asn1.ASN1Object ASN1Object},
- * {@link org.bouncycastle.asn1.ASN1Sequence ASN1Sequence},
- * {@link org.bouncycastle.asn1.x509.X509Name X509Name}
+ * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream},
+ * {@link org.spongycastle.asn1.ASN1Object ASN1Object},
+ * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence},
+ * {@link org.spongycastle.asn1.x509.X509Name X509Name}
*
* @param issuerDN -
* a byte array containing the distinguished name in ASN.1 DER
@@ -327,7 +327,7 @@ public class X509CertSelector implements CertSelector
* If <code>subjectDN</code> is not <code>null</code>, it should
* contain a distinguished name, in RFC 2253 format.<br />
* <br />
- * Uses {@link org.bouncycastle.asn1.x509.X509Name X509Name} for parsing the
+ * Uses {@link org.spongycastle.asn1.x509.X509Name X509Name} for parsing the
* subjectDN.
*
* @param subjectDN
@@ -370,10 +370,10 @@ public class X509CertSelector implements CertSelector
* the ASN.1 notation for this structure, see
* {@link #setIssuer(byte []) setIssuer(byte [] issuerDN)}.<br />
* <br />
- * Uses {@link org.bouncycastle.asn1.ASN1InputStream ASN1InputStream},
- * {@link org.bouncycastle.asn1.ASN1Object ASN1Object},
- * {@link org.bouncycastle.asn1.ASN1Sequence ASN1Sequence},
- * {@link org.bouncycastle.asn1.x509.X509Name X509Name}
+ * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream},
+ * {@link org.spongycastle.asn1.ASN1Object ASN1Object},
+ * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence},
+ * {@link org.spongycastle.asn1.x509.X509Name X509Name}
*
* @param subjectDN
* a byte array containing the distinguished name in ASN.1 DER
@@ -709,7 +709,7 @@ public class X509CertSelector implements CertSelector
* <br />
* Note that the Set is cloned to protect against subsequent modifications.<br />
* <br />
- * Uses {@link org.bouncycastle.asn1.x509.KeyPurposeId KeyPurposeId}
+ * Uses {@link org.spongycastle.asn1.x509.KeyPurposeId KeyPurposeId}
*
* @param keyPurposeSet
* a <code>Set</code> of key purpose OIDs in string format (or
@@ -1322,7 +1322,7 @@ public class X509CertSelector implements CertSelector
* If the value returned is not <code>null</code>, it is a distinguished
* name, in RFC 2253 format.<br />
* <br />
- * Uses {@link org.bouncycastle.asn1.x509.X509Name X509Name} for formatiing
+ * Uses {@link org.spongycastle.asn1.x509.X509Name X509Name} for formatiing
* byte[] issuerDN to String.
*
* @return the required issuer distinguished name in RFC 2253 format (or
@@ -1356,8 +1356,8 @@ public class X509CertSelector implements CertSelector
* Note that the byte array returned is cloned to protect against subsequent
* modifications.<br />
* <br />
- * Uses {@link org.bouncycastle.asn1.DEROutputStream DEROutputStream},
- * {@link org.bouncycastle.asn1.x509.X509Name X509Name} to gnerate byte[]
+ * Uses {@link org.spongycastle.asn1.DEROutputStream DEROutputStream},
+ * {@link org.spongycastle.asn1.x509.X509Name X509Name} to gnerate byte[]
* output for String issuerDN.
*
* @return a byte array containing the required issuer distinguished name in
@@ -1395,7 +1395,7 @@ public class X509CertSelector implements CertSelector
* If the value returned is not <code>null</code>, it is a distinguished
* name, in RFC 2253 format.<br />
* <br />
- * Uses {@link org.bouncycastle.asn1.x509.X509Name X509Name} for formatiing
+ * Uses {@link org.spongycastle.asn1.x509.X509Name X509Name} for formatiing
* byte[] subjectDN to String.
*
* @return the required subject distinguished name in RFC 2253 format (or
@@ -1429,8 +1429,8 @@ public class X509CertSelector implements CertSelector
* Note that the byte array returned is cloned to protect against subsequent
* modifications.<br />
* <br />
- * Uses {@link org.bouncycastle.asn1.DEROutputStream DEROutputStream},
- * {@link org.bouncycastle.asn1.x509.X509Name X509Name} to gnerate byte[]
+ * Uses {@link org.spongycastle.asn1.DEROutputStream DEROutputStream},
+ * {@link org.spongycastle.asn1.x509.X509Name X509Name} to gnerate byte[]
* output for String subjectDN.
*
* @return a byte array containing the required subject distinguished name
@@ -1861,9 +1861,9 @@ public class X509CertSelector implements CertSelector
* <b>TODO: implement output for currently unsupported options(name
* constraints)</b><br />
* <br />
- * Uses {@link org.bouncycastle.asn1.ASN1InputStream ASN1InputStream},
- * {@link org.bouncycastle.asn1.ASN1Object ASN1Object},
- * {@link org.bouncycastle.asn1.x509.KeyPurposeId KeyPurposeId}
+ * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream},
+ * {@link org.spongycastle.asn1.ASN1Object ASN1Object},
+ * {@link org.spongycastle.asn1.x509.KeyPurposeId KeyPurposeId}
*
* @return a <code>String</code> describing the contents of the
* <code>CertSelector</code>
@@ -2004,17 +2004,17 @@ public class X509CertSelector implements CertSelector
* <br />
* <b>TODO: implement missing tests (name constraints and path to names)</b><br />
* <br />
- * Uses {@link org.bouncycastle.asn1.ASN1InputStream ASN1InputStream},
- * {@link org.bouncycastle.asn1.ASN1Sequence ASN1Sequence},
- * {@link org.bouncycastle.asn1.ASN1ObjectIdentifier ASN1ObjectIdentifier},
- * {@link org.bouncycastle.asn1.ASN1Object ASN1Object},
- * {@link org.bouncycastle.asn1.DERGeneralizedTime DERGeneralizedTime},
- * {@link org.bouncycastle.asn1.x509.X509Name X509Name},
- * {@link org.bouncycastle.asn1.x509.X509Extensions X509Extensions},
- * {@link org.bouncycastle.asn1.x509.ExtendedKeyUsage ExtendedKeyUsage},
- * {@link org.bouncycastle.asn1.x509.KeyPurposeId KeyPurposeId},
- * {@link org.bouncycastle.asn1.x509.SubjectPublicKeyInfo SubjectPublicKeyInfo},
- * {@link org.bouncycastle.asn1.x509.AlgorithmIdentifier AlgorithmIdentifier}
+ * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream},
+ * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence},
+ * {@link org.spongycastle.asn1.ASN1ObjectIdentifier ASN1ObjectIdentifier},
+ * {@link org.spongycastle.asn1.ASN1Object ASN1Object},
+ * {@link org.spongycastle.asn1.DERGeneralizedTime DERGeneralizedTime},
+ * {@link org.spongycastle.asn1.x509.X509Name X509Name},
+ * {@link org.spongycastle.asn1.x509.X509Extensions X509Extensions},
+ * {@link org.spongycastle.asn1.x509.ExtendedKeyUsage ExtendedKeyUsage},
+ * {@link org.spongycastle.asn1.x509.KeyPurposeId KeyPurposeId},
+ * {@link org.spongycastle.asn1.x509.SubjectPublicKeyInfo SubjectPublicKeyInfo},
+ * {@link org.spongycastle.asn1.x509.AlgorithmIdentifier AlgorithmIdentifier}
* to access X509 extensions
*
* @param cert
diff --git a/core/src/main/jdk1.1/org/bouncycastle/asn1/ASN1InputStream.java b/core/src/main/jdk1.1/org/bouncycastle/asn1/ASN1InputStream.java
deleted file mode 100644
index 7c156266..00000000
--- a/core/src/main/jdk1.1/org/bouncycastle/asn1/ASN1InputStream.java
+++ /dev/null
@@ -1,466 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayInputStream;
-import java.io.EOFException;
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.bouncycastle.util.io.Streams;
-
-/**
- * a general purpose ASN.1 decoder - note: this class differs from the
- * others in that it returns null after it has read the last object in
- * the stream. If an ASN.1 NULL is encountered a DER/BER Null object is
- * returned.
- */
-public class ASN1InputStream
- extends FilterInputStream
- implements BERTags
-{
- private int limit;
- private boolean lazyEvaluate;
-
- private byte[][] tmpBuffers;
-
- public ASN1InputStream(
- InputStream is)
- {
- this(is, StreamUtil.findLimit(is));
- }
-
- /**
- * Create an ASN1InputStream based on the input byte array. The length of DER objects in
- * the stream is automatically limited to the length of the input array.
- *
- * @param input array containing ASN.1 encoded data.
- */
- public ASN1InputStream(
- byte[] input)
- {
- this(new ByteArrayInputStream(input), input.length);
- }
-
- /**
- * Create an ASN1InputStream based on the input byte array. The length of DER objects in
- * the stream is automatically limited to the length of the input array.
- *
- * @param input array containing ASN.1 encoded data.
- * @param lazyEvaluate true if parsing inside constructed objects can be delayed.
- */
- public ASN1InputStream(
- byte[] input,
- boolean lazyEvaluate)
- {
- this(new ByteArrayInputStream(input), input.length, lazyEvaluate);
- }
-
- /**
- * Create an ASN1InputStream where no DER object will be longer than limit.
- *
- * @param input stream containing ASN.1 encoded data.
- * @param limit maximum size of a DER encoded object.
- */
- public ASN1InputStream(
- InputStream input,
- int limit)
- {
- this(input, limit, false);
- }
-
- /**
- * Create an ASN1InputStream where no DER object will be longer than limit, and constructed
- * objects such as sequences will be parsed lazily.
- *
- * @param input stream containing ASN.1 encoded data.
- * @param lazyEvaluate true if parsing inside constructed objects can be delayed.
- */
- public ASN1InputStream(
- InputStream input,
- boolean lazyEvaluate)
- {
- this(input, StreamUtil.findLimit(input), lazyEvaluate);
- }
-
- /**
- * Create an ASN1InputStream where no DER object will be longer than limit, and constructed
- * objects such as sequences will be parsed lazily.
- *
- * @param input stream containing ASN.1 encoded data.
- * @param limit maximum size of a DER encoded object.
- * @param lazyEvaluate true if parsing inside constructed objects can be delayed.
- */
- public ASN1InputStream(
- InputStream input,
- int limit,
- boolean lazyEvaluate)
- {
- super(input);
- this.limit = limit;
- this.lazyEvaluate = lazyEvaluate;
- this.tmpBuffers = new byte[11][];
- }
-
- int getLimit()
- {
- return limit;
- }
-
- protected int readLength()
- throws IOException
- {
- return readLength(this, limit);
- }
-
- protected void readFully(
- byte[] bytes)
- throws IOException
- {
- if (Streams.readFully(this, bytes) != bytes.length)
- {
- throw new EOFException("EOF encountered in middle of object");
- }
- }
-
- /**
- * build an object given its tag and the number of bytes to construct it from.
- */
- protected ASN1Primitive buildObject(
- int tag,
- int tagNo,
- int length)
- throws IOException
- {
- boolean isConstructed = (tag & CONSTRUCTED) != 0;
-
- DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this, length);
-
- if ((tag & APPLICATION) != 0)
- {
- return new DERApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
- }
-
- if ((tag & TAGGED) != 0)
- {
- return new ASN1StreamParser(defIn).readTaggedObject(isConstructed, tagNo);
- }
-
- if (isConstructed)
- {
- // TODO There are other tags that may be constructed (e.g. BIT_STRING)
- switch (tagNo)
- {
- case OCTET_STRING:
- //
- // yes, people actually do this...
- //
- ASN1EncodableVector v = buildDEREncodableVector(defIn);
- ASN1OctetString[] strings = new ASN1OctetString[v.size()];
-
- for (int i = 0; i != strings.length; i++)
- {
- strings[i] = (ASN1OctetString)v.get(i);
- }
-
- return new BEROctetString(strings);
- case SEQUENCE:
- if (lazyEvaluate)
- {
- return new LazyEncodedSequence(defIn.toByteArray());
- }
- else
- {
- return DERFactory.createSequence(buildDEREncodableVector(defIn));
- }
- case SET:
- return DERFactory.createSet(buildDEREncodableVector(defIn));
- case EXTERNAL:
- return new DERExternal(buildDEREncodableVector(defIn));
- default:
- throw new IOException("unknown tag " + tagNo + " encountered");
- }
- }
-
- return createPrimitiveDERObject(tagNo, defIn, tmpBuffers);
- }
-
- ASN1EncodableVector buildEncodableVector()
- throws IOException
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- ASN1Primitive o;
-
- while ((o = readObject()) != null)
- {
- v.add(o);
- }
-
- return v;
- }
-
- ASN1EncodableVector buildDEREncodableVector(
- DefiniteLengthInputStream dIn) throws IOException
- {
- return new ASN1InputStream(dIn).buildEncodableVector();
- }
-
- public ASN1Primitive readObject()
- throws IOException
- {
- int tag = read();
- if (tag <= 0)
- {
- if (tag == 0)
- {
- throw new IOException("unexpected end-of-contents marker");
- }
-
- return null;
- }
-
- //
- // calculate tag number
- //
- int tagNo = readTagNumber(this, tag);
-
- boolean isConstructed = (tag & CONSTRUCTED) != 0;
-
- //
- // calculate length
- //
- int length = readLength();
-
- if (length < 0) // indefinite length method
- {
- if (!isConstructed)
- {
- throw new IOException("indefinite length primitive encoding encountered");
- }
-
- IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this, limit);
- ASN1StreamParser sp = new ASN1StreamParser(indIn, limit);
-
- if ((tag & APPLICATION) != 0)
- {
- return new BERApplicationSpecificParser(tagNo, sp).getLoadedObject();
- }
-
- if ((tag & TAGGED) != 0)
- {
- return new BERTaggedObjectParser(true, tagNo, sp).getLoadedObject();
- }
-
- // TODO There are other tags that may be constructed (e.g. BIT_STRING)
- switch (tagNo)
- {
- case OCTET_STRING:
- return new BEROctetStringParser(sp).getLoadedObject();
- case SEQUENCE:
- return new BERSequenceParser(sp).getLoadedObject();
- case SET:
- return new BERSetParser(sp).getLoadedObject();
- case EXTERNAL:
- return new DERExternalParser(sp).getLoadedObject();
- default:
- throw new IOException("unknown BER object encountered");
- }
- }
- else
- {
- try
- {
- return buildObject(tag, tagNo, length);
- }
- catch (IllegalArgumentException e)
- {
- throw new ASN1Exception("corrupted stream detected", e);
- }
- }
- }
-
- static int readTagNumber(InputStream s, int tag)
- throws IOException
- {
- int tagNo = tag & 0x1f;
-
- //
- // with tagged object tag number is bottom 5 bits, or stored at the start of the content
- //
- if (tagNo == 0x1f)
- {
- tagNo = 0;
-
- int b = s.read();
-
- // X.690-0207 8.1.2.4.2
- // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
- if ((b & 0x7f) == 0) // Note: -1 will pass
- {
- throw new IOException("corrupted stream - invalid high tag number found");
- }
-
- while ((b >= 0) && ((b & 0x80) != 0))
- {
- tagNo |= (b & 0x7f);
- tagNo <<= 7;
- b = s.read();
- }
-
- if (b < 0)
- {
- throw new EOFException("EOF found inside tag value.");
- }
-
- tagNo |= (b & 0x7f);
- }
-
- return tagNo;
- }
-
- static int readLength(InputStream s, int limit)
- throws IOException
- {
- int length = s.read();
- if (length < 0)
- {
- throw new EOFException("EOF found when length expected");
- }
-
- if (length == 0x80)
- {
- return -1; // indefinite-length encoding
- }
-
- if (length > 127)
- {
- int size = length & 0x7f;
-
- // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
- if (size > 4)
- {
- throw new IOException("DER length more than 4 bytes: " + size);
- }
-
- length = 0;
- for (int i = 0; i < size; i++)
- {
- int next = s.read();
-
- if (next < 0)
- {
- throw new EOFException("EOF found reading length");
- }
-
- length = (length << 8) + next;
- }
-
- if (length < 0)
- {
- throw new IOException("corrupted stream - negative length found");
- }
-
- if (length >= limit) // after all we must have read at least 1 byte
- {
- throw new IOException("corrupted stream - out of bounds length found");
- }
- }
-
- return length;
- }
-
- private static byte[] getBuffer(DefiniteLengthInputStream defIn, byte[][] tmpBuffers)
- throws IOException
- {
- int len = defIn.getRemaining();
- if (defIn.getRemaining() < tmpBuffers.length)
- {
- byte[] buf = tmpBuffers[len];
-
- if (buf == null)
- {
- buf = tmpBuffers[len] = new byte[len];
- }
-
- Streams.readFully(defIn, buf);
-
- return buf;
- }
- else
- {
- return defIn.toByteArray();
- }
- }
-
- private static char[] getBMPCharBuffer(DefiniteLengthInputStream defIn)
- throws IOException
- {
- int len = defIn.getRemaining() / 2;
- char[] buf = new char[len];
- int totalRead = 0;
- while (totalRead < len)
- {
- int ch1 = defIn.read();
- if (ch1 < 0)
- {
- break;
- }
- int ch2 = defIn.read();
- if (ch2 < 0)
- {
- break;
- }
- buf[totalRead++] = (char)((ch1 << 8) | (ch2 & 0xff));
- }
-
- return buf;
- }
-
- static ASN1Primitive createPrimitiveDERObject(
- int tagNo,
- DefiniteLengthInputStream defIn,
- byte[][] tmpBuffers)
- throws IOException
- {
- switch (tagNo)
- {
- case BIT_STRING:
- return DERBitString.fromInputStream(defIn.getRemaining(), defIn);
- case BMP_STRING:
- return new DERBMPString(getBMPCharBuffer(defIn));
- case BOOLEAN:
- return ASN1Boolean.fromOctetString(getBuffer(defIn, tmpBuffers));
- case ENUMERATED:
- return ASN1Enumerated.fromOctetString(getBuffer(defIn, tmpBuffers));
- case GENERALIZED_TIME:
- return new ASN1GeneralizedTime(defIn.toByteArray());
- case GENERAL_STRING:
- return new DERGeneralString(defIn.toByteArray());
- case IA5_STRING:
- return new DERIA5String(defIn.toByteArray());
- case INTEGER:
- return new ASN1Integer(defIn.toByteArray(), false);
- case NULL:
- return DERNull.INSTANCE; // actual content is ignored (enforce 0 length?)
- case NUMERIC_STRING:
- return new DERNumericString(defIn.toByteArray());
- case OBJECT_IDENTIFIER:
- return ASN1ObjectIdentifier.fromOctetString(getBuffer(defIn, tmpBuffers));
- case OCTET_STRING:
- return new DEROctetString(defIn.toByteArray());
- case PRINTABLE_STRING:
- return new DERPrintableString(defIn.toByteArray());
- case T61_STRING:
- return new DERT61String(defIn.toByteArray());
- case UNIVERSAL_STRING:
- return new DERUniversalString(defIn.toByteArray());
- case UTC_TIME:
- return new ASN1UTCTime(defIn.toByteArray());
- case UTF8_STRING:
- return new DERUTF8String(defIn.toByteArray());
- case VISIBLE_STRING:
- return new DERVisibleString(defIn.toByteArray());
- default:
- throw new IOException("unknown tag " + tagNo + " encountered");
- }
- }
-}
diff --git a/core/src/main/jdk1.1/org/bouncycastle/asn1/ASN1StreamParser.java b/core/src/main/jdk1.1/org/bouncycastle/asn1/ASN1StreamParser.java
deleted file mode 100644
index 8ef5f3e6..00000000
--- a/core/src/main/jdk1.1/org/bouncycastle/asn1/ASN1StreamParser.java
+++ /dev/null
@@ -1,247 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-public class ASN1StreamParser
-{
- private InputStream _in;
- private int _limit;
- private byte[][] tmpBuffers;
-
- public ASN1StreamParser(
- InputStream in)
- {
- this(in, StreamUtil.findLimit(in));
- }
-
- public ASN1StreamParser(
- InputStream in,
- int limit)
- {
- this._in = in;
- this._limit = limit;
-
- this.tmpBuffers = new byte[11][];
- }
-
- public ASN1StreamParser(
- byte[] encoding)
- {
- this(new ByteArrayInputStream(encoding), encoding.length);
- }
-
- ASN1Encodable readIndef(int tagValue) throws IOException
- {
- // Note: INDEF => CONSTRUCTED
-
- // TODO There are other tags that may be constructed (e.g. BIT_STRING)
- switch (tagValue)
- {
- case BERTags.EXTERNAL:
- return new DERExternalParser(this);
- case BERTags.OCTET_STRING:
- return new BEROctetStringParser(this);
- case BERTags.SEQUENCE:
- return new BERSequenceParser(this);
- case BERTags.SET:
- return new BERSetParser(this);
- default:
- throw new ASN1Exception("unknown BER object encountered: 0x" + Integer.toHexString(tagValue));
- }
- }
-
- ASN1Encodable readImplicit(boolean constructed, int tag) throws IOException
- {
- if (_in instanceof IndefiniteLengthInputStream)
- {
- if (!constructed)
- {
- throw new IOException("indefinite length primitive encoding encountered");
- }
-
- return readIndef(tag);
- }
-
- if (constructed)
- {
- switch (tag)
- {
- case BERTags.SET:
- return new DERSetParser(this);
- case BERTags.SEQUENCE:
- return new DERSequenceParser(this);
- case BERTags.OCTET_STRING:
- return new BEROctetStringParser(this);
- }
- }
- else
- {
- switch (tag)
- {
- case BERTags.SET:
- throw new ASN1Exception("sequences must use constructed encoding (see X.690 8.9.1/8.10.1)");
- case BERTags.SEQUENCE:
- throw new ASN1Exception("sets must use constructed encoding (see X.690 8.11.1/8.12.1)");
- case BERTags.OCTET_STRING:
- return new DEROctetStringParser((DefiniteLengthInputStream)_in);
- }
- }
-
- // TODO ASN1Exception
- throw new RuntimeException("implicit tagging not implemented");
- }
-
- ASN1Primitive readTaggedObject(boolean constructed, int tag) throws IOException
- {
- if (!constructed)
- {
- // Note: !CONSTRUCTED => IMPLICIT
- DefiniteLengthInputStream defIn = (DefiniteLengthInputStream)_in;
- return new DERTaggedObject(false, tag, new DEROctetString(defIn.toByteArray()));
- }
-
- ASN1EncodableVector v = readVector();
-
- if (_in instanceof IndefiniteLengthInputStream)
- {
- return v.size() == 1
- ? new BERTaggedObject(true, tag, v.get(0))
- : new BERTaggedObject(false, tag, BERFactory.createSequence(v));
- }
-
- return v.size() == 1
- ? new DERTaggedObject(true, tag, v.get(0))
- : new DERTaggedObject(false, tag, DERFactory.createSequence(v));
- }
-
- public ASN1Encodable readObject()
- throws IOException
- {
- int tag = _in.read();
- if (tag == -1)
- {
- return null;
- }
-
- //
- // turn of looking for "00" while we resolve the tag
- //
- set00Check(false);
-
- //
- // calculate tag number
- //
- int tagNo = ASN1InputStream.readTagNumber(_in, tag);
-
- boolean isConstructed = (tag & BERTags.CONSTRUCTED) != 0;
-
- //
- // calculate length
- //
- int length = ASN1InputStream.readLength(_in, _limit);
-
- if (length < 0) // indefinite length method
- {
- if (!isConstructed)
- {
- throw new IOException("indefinite length primitive encoding encountered");
- }
-
- IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in, _limit);
- ASN1StreamParser sp = new ASN1StreamParser(indIn, _limit);
-
- if ((tag & BERTags.APPLICATION) != 0)
- {
- return new BERApplicationSpecificParser(tagNo, sp);
- }
-
- if ((tag & BERTags.TAGGED) != 0)
- {
- return new BERTaggedObjectParser(true, tagNo, sp);
- }
-
- return sp.readIndef(tagNo);
- }
- else
- {
- DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length);
-
- if ((tag & BERTags.APPLICATION) != 0)
- {
- return new DERApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
- }
-
- if ((tag & BERTags.TAGGED) != 0)
- {
- return new BERTaggedObjectParser(isConstructed, tagNo, new ASN1StreamParser(defIn));
- }
-
- if (isConstructed)
- {
- // TODO There are other tags that may be constructed (e.g. BIT_STRING)
- switch (tagNo)
- {
- case BERTags.OCTET_STRING:
- //
- // yes, people actually do this...
- //
- return new BEROctetStringParser(new ASN1StreamParser(defIn));
- case BERTags.SEQUENCE:
- return new DERSequenceParser(new ASN1StreamParser(defIn));
- case BERTags.SET:
- return new DERSetParser(new ASN1StreamParser(defIn));
- case BERTags.EXTERNAL:
- return new DERExternalParser(new ASN1StreamParser(defIn));
- default:
- throw new IOException("unknown tag " + tagNo + " encountered");
- }
- }
-
- // Some primitive encodings can be handled by parsers too...
- switch (tagNo)
- {
- case BERTags.OCTET_STRING:
- return new DEROctetStringParser(defIn);
- }
-
- try
- {
- return ASN1InputStream.createPrimitiveDERObject(tagNo, defIn, tmpBuffers);
- }
- catch (IllegalArgumentException e)
- {
- throw new ASN1Exception("corrupted stream detected", e);
- }
- }
- }
-
- private void set00Check(boolean enabled)
- {
- if (_in instanceof IndefiniteLengthInputStream)
- {
- ((IndefiniteLengthInputStream)_in).setEofOn00(enabled);
- }
- }
-
- ASN1EncodableVector readVector() throws IOException
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- ASN1Encodable obj;
- while ((obj = readObject()) != null)
- {
- if (obj instanceof InMemoryRepresentable)
- {
- v.add(((InMemoryRepresentable)obj).getLoadedObject());
- }
- else
- {
- v.add(obj.toASN1Primitive());
- }
- }
-
- return v;
- }
-}
diff --git a/core/src/main/jdk1.1/org/bouncycastle/asn1/DERApplicationSpecific.java b/core/src/main/jdk1.1/org/bouncycastle/asn1/DERApplicationSpecific.java
deleted file mode 100644
index 2726d6e9..00000000
--- a/core/src/main/jdk1.1/org/bouncycastle/asn1/DERApplicationSpecific.java
+++ /dev/null
@@ -1,276 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * Base class for an application specific object
- */
-public class DERApplicationSpecific
- extends ASN1Primitive
-{
- private boolean isConstructed;
- private int tag;
- private byte[] octets;
-
- DERApplicationSpecific(
- boolean isConstructed,
- int tag,
- byte[] octets)
- {
- this.isConstructed = isConstructed;
- this.tag = tag;
- this.octets = octets;
- }
-
- public DERApplicationSpecific(
- int tag,
- byte[] octets)
- {
- this(false, tag, octets);
- }
-
- public DERApplicationSpecific(
- int tag,
- ASN1Encodable object)
- throws IOException
- {
- this(true, tag, object);
- }
-
- public DERApplicationSpecific(
- boolean explicit,
- int tag,
- ASN1Encodable object)
- throws IOException
- {
- ASN1Primitive primitive = object.toASN1Primitive();
-
- byte[] data = primitive.getEncoded(ASN1Encoding.DER);
-
- this.isConstructed = explicit || (primitive instanceof ASN1Set || primitive instanceof ASN1Sequence);
- this.tag = tag;
-
- if (explicit)
- {
- this.octets = data;
- }
- else
- {
- int lenBytes = getLengthOfHeader(data);
- byte[] tmp = new byte[data.length - lenBytes];
- System.arraycopy(data, lenBytes, tmp, 0, tmp.length);
- this.octets = tmp;
- }
- }
-
- public DERApplicationSpecific(int tagNo, ASN1EncodableVector vec)
- {
- this.tag = tagNo;
- this.isConstructed = true;
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- for (int i = 0; i != vec.size(); i++)
- {
- try
- {
- bOut.write(((ASN1Object)vec.get(i)).getEncoded(ASN1Encoding.DER));
- }
- catch (IOException e)
- {
- throw new ASN1ParsingException("malformed object: " + e, e);
- }
- }
- this.octets = bOut.toByteArray();
- }
-
- public static DERApplicationSpecific getInstance(Object obj)
- {
- if (obj == null || obj instanceof DERApplicationSpecific)
- {
- return (DERApplicationSpecific)obj;
- }
- else if (obj instanceof byte[])
- {
- try
- {
- return DERApplicationSpecific.getInstance(ASN1Primitive.fromByteArray((byte[])obj));
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("failed to construct object from byte[]: " + e.getMessage());
- }
- }
- else if (obj instanceof ASN1Encodable)
- {
- ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive();
-
- if (primitive instanceof ASN1Sequence)
- {
- return (DERApplicationSpecific)primitive;
- }
- }
-
- throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
- }
-
- private int getLengthOfHeader(byte[] data)
- {
- int length = data[1] & 0xff; // TODO: assumes 1 byte tag
-
- if (length == 0x80)
- {
- return 2; // indefinite-length encoding
- }
-
- if (length > 127)
- {
- int size = length & 0x7f;
-
- // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
- if (size > 4)
- {
- throw new IllegalStateException("DER length more than 4 bytes: " + size);
- }
-
- return size + 2;
- }
-
- return 2;
- }
-
- public boolean isConstructed()
- {
- return isConstructed;
- }
-
- public byte[] getContents()
- {
- return octets;
- }
-
- public int getApplicationTag()
- {
- return tag;
- }
-
- /**
- * Return the enclosed object assuming explicit tagging.
- *
- * @return the resulting object
- * @throws IOException if reconstruction fails.
- */
- public ASN1Primitive getObject()
- throws IOException
- {
- return new ASN1InputStream(getContents()).readObject();
- }
-
- /**
- * Return the enclosed object assuming implicit tagging.
- *
- * @param derTagNo the type tag that should be applied to the object's contents.
- * @return the resulting object
- * @throws IOException if reconstruction fails.
- */
- public ASN1Primitive getObject(int derTagNo)
- throws IOException
- {
- if (derTagNo >= 0x1f)
- {
- throw new IOException("unsupported tag number");
- }
-
- byte[] orig = this.getEncoded();
- byte[] tmp = replaceTagNumber(derTagNo, orig);
-
- if ((orig[0] & BERTags.CONSTRUCTED) != 0)
- {
- tmp[0] |= BERTags.CONSTRUCTED;
- }
-
- return new ASN1InputStream(tmp).readObject();
- }
-
- int encodedLength()
- throws IOException
- {
- return StreamUtil.calculateTagLength(tag) + StreamUtil.calculateBodyLength(octets.length) + octets.length;
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.asn1.ASN1Primitive#encode(org.bouncycastle.asn1.DEROutputStream)
- */
- void encode(ASN1OutputStream out) throws IOException
- {
- int classBits = BERTags.APPLICATION;
- if (isConstructed)
- {
- classBits |= BERTags.CONSTRUCTED;
- }
-
- out.writeEncoded(classBits, tag, octets);
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof DERApplicationSpecific))
- {
- return false;
- }
-
- DERApplicationSpecific other = (DERApplicationSpecific)o;
-
- return isConstructed == other.isConstructed
- && tag == other.tag
- && Arrays.areEqual(octets, other.octets);
- }
-
- public int hashCode()
- {
- return (isConstructed ? 1 : 0) ^ tag ^ Arrays.hashCode(octets);
- }
-
- private byte[] replaceTagNumber(int newTag, byte[] input)
- throws IOException
- {
- int tagNo = input[0] & 0x1f;
- int index = 1;
- //
- // with tagged object tag number is bottom 5 bits, or stored at the start of the content
- //
- if (tagNo == 0x1f)
- {
- tagNo = 0;
-
- int b = input[index++] & 0xff;
-
- // X.690-0207 8.1.2.4.2
- // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
- if ((b & 0x7f) == 0) // Note: -1 will pass
- {
- throw new ASN1ParsingException("corrupted stream - invalid high tag number found");
- }
-
- while ((b >= 0) && ((b & 0x80) != 0))
- {
- tagNo |= (b & 0x7f);
- tagNo <<= 7;
- b = input[index++] & 0xff;
- }
-
- tagNo |= (b & 0x7f);
- }
-
- byte[] tmp = new byte[input.length - index + 1];
-
- System.arraycopy(input, index, tmp, 1, tmp.length - 1);
-
- tmp[0] = (byte)newTag;
-
- return tmp;
- }
-}
diff --git a/core/src/main/jdk1.1/org/bouncycastle/asn1/x500/style/BCStyle.java b/core/src/main/jdk1.1/org/bouncycastle/asn1/x500/style/BCStyle.java
deleted file mode 100644
index 15e3c2a7..00000000
--- a/core/src/main/jdk1.1/org/bouncycastle/asn1/x500/style/BCStyle.java
+++ /dev/null
@@ -1,481 +0,0 @@
-package org.bouncycastle.asn1.x500.style;
-
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Hashtable;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DERPrintableString;
-import org.bouncycastle.asn1.DERUTF8String;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.asn1.x500.AttributeTypeAndValue;
-import org.bouncycastle.asn1.x500.RDN;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x500.X500NameStyle;
-import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
-
-public class BCStyle
- implements X500NameStyle
-{
- /**
- * country code - StringType(SIZE(2))
- */
- public static final ASN1ObjectIdentifier C = new ASN1ObjectIdentifier("2.5.4.6");
-
- /**
- * organization - StringType(SIZE(1..64))
- */
- public static final ASN1ObjectIdentifier O = new ASN1ObjectIdentifier("2.5.4.10");
-
- /**
- * organizational unit name - StringType(SIZE(1..64))
- */
- public static final ASN1ObjectIdentifier OU = new ASN1ObjectIdentifier("2.5.4.11");
-
- /**
- * Title
- */
- public static final ASN1ObjectIdentifier T = new ASN1ObjectIdentifier("2.5.4.12");
-
- /**
- * common name - StringType(SIZE(1..64))
- */
- public static final ASN1ObjectIdentifier CN = new ASN1ObjectIdentifier("2.5.4.3");
-
- /**
- * device serial number name - StringType(SIZE(1..64))
- */
- public static final ASN1ObjectIdentifier SN = new ASN1ObjectIdentifier("2.5.4.5");
-
- /**
- * street - StringType(SIZE(1..64))
- */
- public static final ASN1ObjectIdentifier STREET = new ASN1ObjectIdentifier("2.5.4.9");
-
- /**
- * device serial number name - StringType(SIZE(1..64))
- */
- public static final ASN1ObjectIdentifier SERIALNUMBER = SN;
-
- /**
- * locality name - StringType(SIZE(1..64))
- */
- public static final ASN1ObjectIdentifier L = new ASN1ObjectIdentifier("2.5.4.7");
-
- /**
- * state, or province name - StringType(SIZE(1..64))
- */
- public static final ASN1ObjectIdentifier ST = new ASN1ObjectIdentifier("2.5.4.8");
-
- /**
- * Naming attributes of type X520name
- */
- public static final ASN1ObjectIdentifier SURNAME = new ASN1ObjectIdentifier("2.5.4.4");
- public static final ASN1ObjectIdentifier GIVENNAME = new ASN1ObjectIdentifier("2.5.4.42");
- public static final ASN1ObjectIdentifier INITIALS = new ASN1ObjectIdentifier("2.5.4.43");
- public static final ASN1ObjectIdentifier GENERATION = new ASN1ObjectIdentifier("2.5.4.44");
- public static final ASN1ObjectIdentifier UNIQUE_IDENTIFIER = new ASN1ObjectIdentifier("2.5.4.45");
-
- /**
- * businessCategory - DirectoryString(SIZE(1..128)
- */
- public static final ASN1ObjectIdentifier BUSINESS_CATEGORY = new ASN1ObjectIdentifier(
- "2.5.4.15");
-
- /**
- * postalCode - DirectoryString(SIZE(1..40)
- */
- public static final ASN1ObjectIdentifier POSTAL_CODE = new ASN1ObjectIdentifier(
- "2.5.4.17");
-
- /**
- * dnQualifier - DirectoryString(SIZE(1..64)
- */
- public static final ASN1ObjectIdentifier DN_QUALIFIER = new ASN1ObjectIdentifier(
- "2.5.4.46");
-
- /**
- * RFC 3039 Pseudonym - DirectoryString(SIZE(1..64)
- */
- public static final ASN1ObjectIdentifier PSEUDONYM = new ASN1ObjectIdentifier(
- "2.5.4.65");
-
-
- /**
- * RFC 3039 DateOfBirth - GeneralizedTime - YYYYMMDD000000Z
- */
- public static final ASN1ObjectIdentifier DATE_OF_BIRTH = new ASN1ObjectIdentifier(
- "1.3.6.1.5.5.7.9.1");
-
- /**
- * RFC 3039 PlaceOfBirth - DirectoryString(SIZE(1..128)
- */
- public static final ASN1ObjectIdentifier PLACE_OF_BIRTH = new ASN1ObjectIdentifier(
- "1.3.6.1.5.5.7.9.2");
-
- /**
- * RFC 3039 Gender - PrintableString (SIZE(1)) -- "M", "F", "m" or "f"
- */
- public static final ASN1ObjectIdentifier GENDER = new ASN1ObjectIdentifier(
- "1.3.6.1.5.5.7.9.3");
-
- /**
- * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
- * codes only
- */
- public static final ASN1ObjectIdentifier COUNTRY_OF_CITIZENSHIP = new ASN1ObjectIdentifier(
- "1.3.6.1.5.5.7.9.4");
-
- /**
- * RFC 3039 CountryOfResidence - PrintableString (SIZE (2)) -- ISO 3166
- * codes only
- */
- public static final ASN1ObjectIdentifier COUNTRY_OF_RESIDENCE = new ASN1ObjectIdentifier(
- "1.3.6.1.5.5.7.9.5");
-
-
- /**
- * ISIS-MTT NameAtBirth - DirectoryString(SIZE(1..64)
- */
- public static final ASN1ObjectIdentifier NAME_AT_BIRTH = new ASN1ObjectIdentifier("1.3.36.8.3.14");
-
- /**
- * RFC 3039 PostalAddress - SEQUENCE SIZE (1..6) OF
- * DirectoryString(SIZE(1..30))
- */
- public static final ASN1ObjectIdentifier POSTAL_ADDRESS = new ASN1ObjectIdentifier("2.5.4.16");
-
- /**
- * RFC 2256 dmdName
- */
- public static final ASN1ObjectIdentifier DMD_NAME = new ASN1ObjectIdentifier("2.5.4.54");
-
- /**
- * id-at-telephoneNumber
- */
- public static final ASN1ObjectIdentifier TELEPHONE_NUMBER = X509ObjectIdentifiers.id_at_telephoneNumber;
-
- /**
- * id-at-name
- */
- public static final ASN1ObjectIdentifier NAME = X509ObjectIdentifiers.id_at_name;
-
- /**
- * Email address (RSA PKCS#9 extension) - IA5String.
- * <p>Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.
- */
- public static final ASN1ObjectIdentifier EmailAddress = PKCSObjectIdentifiers.pkcs_9_at_emailAddress;
-
- /**
- * more from PKCS#9
- */
- public static final ASN1ObjectIdentifier UnstructuredName = PKCSObjectIdentifiers.pkcs_9_at_unstructuredName;
- public static final ASN1ObjectIdentifier UnstructuredAddress = PKCSObjectIdentifiers.pkcs_9_at_unstructuredAddress;
-
- /**
- * email address in Verisign certificates
- */
- public static final ASN1ObjectIdentifier E = EmailAddress;
-
- /*
- * others...
- */
- public static final ASN1ObjectIdentifier DC = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.25");
-
- /**
- * LDAP User id.
- */
- public static final ASN1ObjectIdentifier UID = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.1");
-
- /**
- * default look up table translating OID values into their common symbols following
- * the convention in RFC 2253 with a few extras
- */
- private static final Hashtable DefaultSymbols = new Hashtable();
-
- /**
- * look up table translating common symbols into their OIDS.
- */
- private static final Hashtable DefaultLookUp = new Hashtable();
-
- static
- {
- DefaultSymbols.put(C, "C");
- DefaultSymbols.put(O, "O");
- DefaultSymbols.put(T, "T");
- DefaultSymbols.put(OU, "OU");
- DefaultSymbols.put(CN, "CN");
- DefaultSymbols.put(L, "L");
- DefaultSymbols.put(ST, "ST");
- DefaultSymbols.put(SN, "SERIALNUMBER");
- DefaultSymbols.put(EmailAddress, "E");
- DefaultSymbols.put(DC, "DC");
- DefaultSymbols.put(UID, "UID");
- DefaultSymbols.put(STREET, "STREET");
- DefaultSymbols.put(SURNAME, "SURNAME");
- DefaultSymbols.put(GIVENNAME, "GIVENNAME");
- DefaultSymbols.put(INITIALS, "INITIALS");
- DefaultSymbols.put(GENERATION, "GENERATION");
- DefaultSymbols.put(UnstructuredAddress, "unstructuredAddress");
- DefaultSymbols.put(UnstructuredName, "unstructuredName");
- DefaultSymbols.put(UNIQUE_IDENTIFIER, "UniqueIdentifier");
- DefaultSymbols.put(DN_QUALIFIER, "DN");
- DefaultSymbols.put(PSEUDONYM, "Pseudonym");
- DefaultSymbols.put(POSTAL_ADDRESS, "PostalAddress");
- DefaultSymbols.put(NAME_AT_BIRTH, "NameAtBirth");
- DefaultSymbols.put(COUNTRY_OF_CITIZENSHIP, "CountryOfCitizenship");
- DefaultSymbols.put(COUNTRY_OF_RESIDENCE, "CountryOfResidence");
- DefaultSymbols.put(GENDER, "Gender");
- DefaultSymbols.put(PLACE_OF_BIRTH, "PlaceOfBirth");
- DefaultSymbols.put(DATE_OF_BIRTH, "DateOfBirth");
- DefaultSymbols.put(POSTAL_CODE, "PostalCode");
- DefaultSymbols.put(BUSINESS_CATEGORY, "BusinessCategory");
- DefaultSymbols.put(TELEPHONE_NUMBER, "TelephoneNumber");
- DefaultSymbols.put(NAME, "Name");
-
- DefaultLookUp.put("c", C);
- DefaultLookUp.put("o", O);
- DefaultLookUp.put("t", T);
- DefaultLookUp.put("ou", OU);
- DefaultLookUp.put("cn", CN);
- DefaultLookUp.put("l", L);
- DefaultLookUp.put("st", ST);
- DefaultLookUp.put("sn", SN);
- DefaultLookUp.put("serialnumber", SN);
- DefaultLookUp.put("street", STREET);
- DefaultLookUp.put("emailaddress", E);
- DefaultLookUp.put("dc", DC);
- DefaultLookUp.put("e", E);
- DefaultLookUp.put("uid", UID);
- DefaultLookUp.put("surname", SURNAME);
- DefaultLookUp.put("givenname", GIVENNAME);
- DefaultLookUp.put("initials", INITIALS);
- DefaultLookUp.put("generation", GENERATION);
- DefaultLookUp.put("unstructuredaddress", UnstructuredAddress);
- DefaultLookUp.put("unstructuredname", UnstructuredName);
- DefaultLookUp.put("uniqueidentifier", UNIQUE_IDENTIFIER);
- DefaultLookUp.put("dn", DN_QUALIFIER);
- DefaultLookUp.put("pseudonym", PSEUDONYM);
- DefaultLookUp.put("postaladdress", POSTAL_ADDRESS);
- DefaultLookUp.put("nameofbirth", NAME_AT_BIRTH);
- DefaultLookUp.put("countryofcitizenship", COUNTRY_OF_CITIZENSHIP);
- DefaultLookUp.put("countryofresidence", COUNTRY_OF_RESIDENCE);
- DefaultLookUp.put("gender", GENDER);
- DefaultLookUp.put("placeofbirth", PLACE_OF_BIRTH);
- DefaultLookUp.put("dateofbirth", DATE_OF_BIRTH);
- DefaultLookUp.put("postalcode", POSTAL_CODE);
- DefaultLookUp.put("businesscategory", BUSINESS_CATEGORY);
- DefaultLookUp.put("telephonenumber", TELEPHONE_NUMBER);
- DefaultLookUp.put("name", NAME);
- }
-
- /**
- * Singleton instance.
- */
- public static final X500NameStyle INSTANCE = new BCStyle();
-
- protected Hashtable defaultLookUp;
- protected Hashtable defaultSymbols;
-
- protected BCStyle()
- {
- defaultSymbols = copyHashTable(DefaultSymbols);
- defaultLookUp = copyHashTable(DefaultLookUp);
- }
-
- public ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value)
- {
- if (value.length() != 0 && value.charAt(0) == '#')
- {
- try
- {
- return IETFUtils.valueFromHexString(value, 1);
- }
- catch (IOException e)
- {
- throw new RuntimeException("can't recode value for oid " + oid.getId());
- }
- }
- else
- {
- if (value.length() != 0 && value.charAt(0) == '\\')
- {
- value = value.substring(1);
- }
- if (oid.equals(EmailAddress) || oid.equals(DC))
- {
- return new DERIA5String(value);
- }
- else if (oid.equals(DATE_OF_BIRTH)) // accept time string as well as # (for compatibility)
- {
- return new ASN1GeneralizedTime(value);
- }
- else if (oid.equals(C) || oid.equals(SN) || oid.equals(DN_QUALIFIER)
- || oid.equals(TELEPHONE_NUMBER))
- {
- return new DERPrintableString(value);
- }
- }
-
- return new DERUTF8String(value);
- }
-
- public String oidToDisplayName(ASN1ObjectIdentifier oid)
- {
- return (String)DefaultSymbols.get(oid);
- }
-
- public String[] oidToAttrNames(ASN1ObjectIdentifier oid)
- {
- return IETFUtils.findAttrNamesForOID(oid, defaultLookUp);
- }
-
- public ASN1ObjectIdentifier attrNameToOID(String attrName)
- {
- return IETFUtils.decodeAttrName(attrName, defaultLookUp);
- }
-
- public boolean areEqual(X500Name name1, X500Name name2)
- {
- RDN[] rdns1 = name1.getRDNs();
- RDN[] rdns2 = name2.getRDNs();
-
- if (rdns1.length != rdns2.length)
- {
- return false;
- }
-
- boolean reverse = false;
-
- if (rdns1[0].getFirst() != null && rdns2[0].getFirst() != null)
- {
- reverse = !rdns1[0].getFirst().getType().equals(rdns2[0].getFirst().getType()); // guess forward
- }
-
- for (int i = 0; i != rdns1.length; i++)
- {
- if (!foundMatch(reverse, rdns1[i], rdns2))
- {
- return false;
- }
- }
-
- return true;
- }
-
- private boolean foundMatch(boolean reverse, RDN rdn, RDN[] possRDNs)
- {
- if (reverse)
- {
- for (int i = possRDNs.length - 1; i >= 0; i--)
- {
- if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
- {
- possRDNs[i] = null;
- return true;
- }
- }
- }
- else
- {
- for (int i = 0; i != possRDNs.length; i++)
- {
- if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
- {
- possRDNs[i] = null;
- return true;
- }
- }
- }
-
- return false;
- }
-
- protected boolean rdnAreEqual(RDN rdn1, RDN rdn2)
- {
- return IETFUtils.rDNAreEqual(rdn1, rdn2);
- }
-
- public RDN[] fromString(String dirName)
- {
- return IETFUtils.rDNsFromString(dirName, this);
- }
-
- public int calculateHashCode(X500Name name)
- {
- int hashCodeValue = 0;
- RDN[] rdns = name.getRDNs();
-
- // this needs to be order independent, like equals
- for (int i = 0; i != rdns.length; i++)
- {
- if (rdns[i].isMultiValued())
- {
- AttributeTypeAndValue[] atv = rdns[i].getTypesAndValues();
-
- for (int j = 0; j != atv.length; j++)
- {
- hashCodeValue ^= atv[j].getType().hashCode();
- hashCodeValue ^= calcHashCode(atv[j].getValue());
- }
- }
- else
- {
- hashCodeValue ^= rdns[i].getFirst().getType().hashCode();
- hashCodeValue ^= calcHashCode(rdns[i].getFirst().getValue());
- }
- }
-
- return hashCodeValue;
- }
-
- private int calcHashCode(ASN1Encodable enc)
- {
- String value = IETFUtils.valueToString(enc);
-
- value = IETFUtils.canonicalize(value);
-
- return value.hashCode();
- }
-
- public String toString(X500Name name)
- {
- StringBuffer buf = new StringBuffer();
- boolean first = true;
-
- RDN[] rdns = name.getRDNs();
-
- for (int i = 0; i < rdns.length; i++)
- {
- if (first)
- {
- first = false;
- }
- else
- {
- buf.append(',');
- }
-
- 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/core/src/main/jdk1.1/org/bouncycastle/asn1/x500/style/RFC4519Style.java b/core/src/main/jdk1.1/org/bouncycastle/asn1/x500/style/RFC4519Style.java
deleted file mode 100644
index e5ff6a11..00000000
--- a/core/src/main/jdk1.1/org/bouncycastle/asn1/x500/style/RFC4519Style.java
+++ /dev/null
@@ -1,380 +0,0 @@
-package org.bouncycastle.asn1.x500.style;
-
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Hashtable;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DERPrintableString;
-import org.bouncycastle.asn1.DERUTF8String;
-import org.bouncycastle.asn1.x500.AttributeTypeAndValue;
-import org.bouncycastle.asn1.x500.RDN;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x500.X500NameStyle;
-
-public class RFC4519Style
- implements X500NameStyle
-{
- public static final ASN1ObjectIdentifier businessCategory = new ASN1ObjectIdentifier("2.5.4.15");
- public static final ASN1ObjectIdentifier c = new ASN1ObjectIdentifier("2.5.4.6");
- public static final ASN1ObjectIdentifier cn = new ASN1ObjectIdentifier("2.5.4.3");
- public static final ASN1ObjectIdentifier dc = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.25");
- public static final ASN1ObjectIdentifier description = new ASN1ObjectIdentifier("2.5.4.13");
- public static final ASN1ObjectIdentifier destinationIndicator = new ASN1ObjectIdentifier("2.5.4.27");
- public static final ASN1ObjectIdentifier distinguishedName = new ASN1ObjectIdentifier("2.5.4.49");
- public static final ASN1ObjectIdentifier dnQualifier = new ASN1ObjectIdentifier("2.5.4.46");
- public static final ASN1ObjectIdentifier enhancedSearchGuide = new ASN1ObjectIdentifier("2.5.4.47");
- public static final ASN1ObjectIdentifier facsimileTelephoneNumber = new ASN1ObjectIdentifier("2.5.4.23");
- public static final ASN1ObjectIdentifier generationQualifier = new ASN1ObjectIdentifier("2.5.4.44");
- public static final ASN1ObjectIdentifier givenName = new ASN1ObjectIdentifier("2.5.4.42");
- public static final ASN1ObjectIdentifier houseIdentifier = new ASN1ObjectIdentifier("2.5.4.51");
- public static final ASN1ObjectIdentifier initials = new ASN1ObjectIdentifier("2.5.4.43");
- public static final ASN1ObjectIdentifier internationalISDNNumber = new ASN1ObjectIdentifier("2.5.4.25");
- public static final ASN1ObjectIdentifier l = new ASN1ObjectIdentifier("2.5.4.7");
- public static final ASN1ObjectIdentifier member = new ASN1ObjectIdentifier("2.5.4.31");
- public static final ASN1ObjectIdentifier name = new ASN1ObjectIdentifier("2.5.4.41");
- public static final ASN1ObjectIdentifier o = new ASN1ObjectIdentifier("2.5.4.10");
- public static final ASN1ObjectIdentifier ou = new ASN1ObjectIdentifier("2.5.4.11");
- public static final ASN1ObjectIdentifier owner = new ASN1ObjectIdentifier("2.5.4.32");
- public static final ASN1ObjectIdentifier physicalDeliveryOfficeName = new ASN1ObjectIdentifier("2.5.4.19");
- public static final ASN1ObjectIdentifier postalAddress = new ASN1ObjectIdentifier("2.5.4.16");
- public static final ASN1ObjectIdentifier postalCode = new ASN1ObjectIdentifier("2.5.4.17");
- public static final ASN1ObjectIdentifier postOfficeBox = new ASN1ObjectIdentifier("2.5.4.18");
- public static final ASN1ObjectIdentifier preferredDeliveryMethod = new ASN1ObjectIdentifier("2.5.4.28");
- public static final ASN1ObjectIdentifier registeredAddress = new ASN1ObjectIdentifier("2.5.4.26");
- public static final ASN1ObjectIdentifier roleOccupant = new ASN1ObjectIdentifier("2.5.4.33");
- public static final ASN1ObjectIdentifier searchGuide = new ASN1ObjectIdentifier("2.5.4.14");
- public static final ASN1ObjectIdentifier seeAlso = new ASN1ObjectIdentifier("2.5.4.34");
- public static final ASN1ObjectIdentifier serialNumber = new ASN1ObjectIdentifier("2.5.4.5");
- public static final ASN1ObjectIdentifier sn = new ASN1ObjectIdentifier("2.5.4.4");
- public static final ASN1ObjectIdentifier st = new ASN1ObjectIdentifier("2.5.4.8");
- public static final ASN1ObjectIdentifier street = new ASN1ObjectIdentifier("2.5.4.9");
- public static final ASN1ObjectIdentifier telephoneNumber = new ASN1ObjectIdentifier("2.5.4.20");
- public static final ASN1ObjectIdentifier teletexTerminalIdentifier = new ASN1ObjectIdentifier("2.5.4.22");
- public static final ASN1ObjectIdentifier telexNumber = new ASN1ObjectIdentifier("2.5.4.21");
- public static final ASN1ObjectIdentifier title = new ASN1ObjectIdentifier("2.5.4.12");
- public static final ASN1ObjectIdentifier uid = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.1");
- public static final ASN1ObjectIdentifier uniqueMember = new ASN1ObjectIdentifier("2.5.4.50");
- public static final ASN1ObjectIdentifier userPassword = new ASN1ObjectIdentifier("2.5.4.35");
- public static final ASN1ObjectIdentifier x121Address = new ASN1ObjectIdentifier("2.5.4.24");
- public static final ASN1ObjectIdentifier x500UniqueIdentifier = new ASN1ObjectIdentifier("2.5.4.45");
-
- /**
- * default look up table translating OID values into their common symbols following
- * the convention in RFC 2253 with a few extras
- */
- private static final Hashtable DefaultSymbols = new Hashtable();
-
- /**
- * look up table translating common symbols into their OIDS.
- */
- private static final Hashtable DefaultLookUp = new Hashtable();
-
- static
- {
- DefaultSymbols.put(businessCategory, "businessCategory");
- DefaultSymbols.put(c, "c");
- DefaultSymbols.put(cn, "cn");
- DefaultSymbols.put(dc, "dc");
- DefaultSymbols.put(description, "description");
- DefaultSymbols.put(destinationIndicator, "destinationIndicator");
- DefaultSymbols.put(distinguishedName, "distinguishedName");
- DefaultSymbols.put(dnQualifier, "dnQualifier");
- DefaultSymbols.put(enhancedSearchGuide, "enhancedSearchGuide");
- DefaultSymbols.put(facsimileTelephoneNumber, "facsimileTelephoneNumber");
- DefaultSymbols.put(generationQualifier, "generationQualifier");
- DefaultSymbols.put(givenName, "givenName");
- DefaultSymbols.put(houseIdentifier, "houseIdentifier");
- DefaultSymbols.put(initials, "initials");
- DefaultSymbols.put(internationalISDNNumber, "internationalISDNNumber");
- DefaultSymbols.put(l, "l");
- DefaultSymbols.put(member, "member");
- DefaultSymbols.put(name, "name");
- DefaultSymbols.put(o, "o");
- DefaultSymbols.put(ou, "ou");
- DefaultSymbols.put(owner, "owner");
- DefaultSymbols.put(physicalDeliveryOfficeName, "physicalDeliveryOfficeName");
- DefaultSymbols.put(postalAddress, "postalAddress");
- DefaultSymbols.put(postalCode, "postalCode");
- DefaultSymbols.put(postOfficeBox, "postOfficeBox");
- DefaultSymbols.put(preferredDeliveryMethod, "preferredDeliveryMethod");
- DefaultSymbols.put(registeredAddress, "registeredAddress");
- DefaultSymbols.put(roleOccupant, "roleOccupant");
- DefaultSymbols.put(searchGuide, "searchGuide");
- DefaultSymbols.put(seeAlso, "seeAlso");
- DefaultSymbols.put(serialNumber, "serialNumber");
- DefaultSymbols.put(sn, "sn");
- DefaultSymbols.put(st, "st");
- DefaultSymbols.put(street, "street");
- DefaultSymbols.put(telephoneNumber, "telephoneNumber");
- DefaultSymbols.put(teletexTerminalIdentifier, "teletexTerminalIdentifier");
- DefaultSymbols.put(telexNumber, "telexNumber");
- DefaultSymbols.put(title, "title");
- DefaultSymbols.put(uid, "uid");
- DefaultSymbols.put(uniqueMember, "uniqueMember");
- DefaultSymbols.put(userPassword, "userPassword");
- DefaultSymbols.put(x121Address, "x121Address");
- DefaultSymbols.put(x500UniqueIdentifier, "x500UniqueIdentifier");
-
- DefaultLookUp.put("businesscategory", businessCategory);
- DefaultLookUp.put("c", c);
- DefaultLookUp.put("cn", cn);
- DefaultLookUp.put("dc", dc);
- DefaultLookUp.put("description", description);
- DefaultLookUp.put("destinationindicator", destinationIndicator);
- DefaultLookUp.put("distinguishedname", distinguishedName);
- DefaultLookUp.put("dnqualifier", dnQualifier);
- DefaultLookUp.put("enhancedsearchguide", enhancedSearchGuide);
- DefaultLookUp.put("facsimiletelephonenumber", facsimileTelephoneNumber);
- DefaultLookUp.put("generationqualifier", generationQualifier);
- DefaultLookUp.put("givenname", givenName);
- DefaultLookUp.put("houseidentifier", houseIdentifier);
- DefaultLookUp.put("initials", initials);
- DefaultLookUp.put("internationalisdnnumber", internationalISDNNumber);
- DefaultLookUp.put("l", l);
- DefaultLookUp.put("member", member);
- DefaultLookUp.put("name", name);
- DefaultLookUp.put("o", o);
- DefaultLookUp.put("ou", ou);
- DefaultLookUp.put("owner", owner);
- DefaultLookUp.put("physicaldeliveryofficename", physicalDeliveryOfficeName);
- DefaultLookUp.put("postaladdress", postalAddress);
- DefaultLookUp.put("postalcode", postalCode);
- DefaultLookUp.put("postofficebox", postOfficeBox);
- DefaultLookUp.put("preferreddeliverymethod", preferredDeliveryMethod);
- DefaultLookUp.put("registeredaddress", registeredAddress);
- DefaultLookUp.put("roleoccupant", roleOccupant);
- DefaultLookUp.put("searchguide", searchGuide);
- DefaultLookUp.put("seealso", seeAlso);
- DefaultLookUp.put("serialnumber", serialNumber);
- DefaultLookUp.put("sn", sn);
- DefaultLookUp.put("st", st);
- DefaultLookUp.put("street", street);
- DefaultLookUp.put("telephonenumber", telephoneNumber);
- DefaultLookUp.put("teletexterminalidentifier", teletexTerminalIdentifier);
- DefaultLookUp.put("telexnumber", telexNumber);
- DefaultLookUp.put("title", title);
- DefaultLookUp.put("uid", uid);
- DefaultLookUp.put("uniquemember", uniqueMember);
- DefaultLookUp.put("userpassword", userPassword);
- DefaultLookUp.put("x121address", x121Address);
- DefaultLookUp.put("x500uniqueidentifier", x500UniqueIdentifier);
-
- // TODO: need to add correct matching for equality comparisons.
- }
-
- /**
- * Singleton instance.
- */
- public static final X500NameStyle INSTANCE = new RFC4519Style();
-
- protected Hashtable defaultLookUp;
- protected Hashtable defaultSymbols;
-
- protected RFC4519Style()
- {
- defaultSymbols = copyHashTable(DefaultSymbols);
- defaultLookUp = copyHashTable(DefaultLookUp);
- }
-
- public ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value)
- {
- if (value.length() != 0 && value.charAt(0) == '#')
- {
- try
- {
- return IETFUtils.valueFromHexString(value, 1);
- }
- catch (IOException e)
- {
- throw new RuntimeException("can't recode value for oid " + oid.getId());
- }
- }
- else
- {
- if (value.length() != 0 && value.charAt(0) == '\\')
- {
- value = value.substring(1);
- }
- if (oid.equals(dc))
- {
- return new DERIA5String(value);
- }
- else if (oid.equals(c) || oid.equals(serialNumber) || oid.equals(dnQualifier)
- || oid.equals(telephoneNumber))
- {
- return new DERPrintableString(value);
- }
- }
-
- return new DERUTF8String(value);
- }
-
- public String oidToDisplayName(ASN1ObjectIdentifier oid)
- {
- return (String)DefaultSymbols.get(oid);
- }
-
- public String[] oidToAttrNames(ASN1ObjectIdentifier oid)
- {
- return IETFUtils.findAttrNamesForOID(oid, defaultLookUp);
- }
-
- public ASN1ObjectIdentifier attrNameToOID(String attrName)
- {
- return IETFUtils.decodeAttrName(attrName, defaultLookUp);
- }
-
- public boolean areEqual(X500Name name1, X500Name name2)
- {
- RDN[] rdns1 = name1.getRDNs();
- RDN[] rdns2 = name2.getRDNs();
-
- if (rdns1.length != rdns2.length)
- {
- return false;
- }
-
- boolean reverse = false;
-
- if (rdns1[0].getFirst() != null && rdns2[0].getFirst() != null)
- {
- reverse = !rdns1[0].getFirst().getType().equals(rdns2[0].getFirst().getType()); // guess forward
- }
-
- for (int i = 0; i != rdns1.length; i++)
- {
- if (!foundMatch(reverse, rdns1[i], rdns2))
- {
- return false;
- }
- }
-
- return true;
- }
-
- private boolean foundMatch(boolean reverse, RDN rdn, RDN[] possRDNs)
- {
- if (reverse)
- {
- for (int i = possRDNs.length - 1; i >= 0; i--)
- {
- if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
- {
- possRDNs[i] = null;
- return true;
- }
- }
- }
- else
- {
- for (int i = 0; i != possRDNs.length; i++)
- {
- if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
- {
- possRDNs[i] = null;
- return true;
- }
- }
- }
-
- return false;
- }
-
- protected boolean rdnAreEqual(RDN rdn1, RDN rdn2)
- {
- return IETFUtils.rDNAreEqual(rdn1, rdn2);
- }
-
- // parse backwards
- public RDN[] fromString(String dirName)
- {
- RDN[] tmp = IETFUtils.rDNsFromString(dirName, this);
- RDN[] res = new RDN[tmp.length];
-
- for (int i = 0; i != tmp.length; i++)
- {
- res[res.length - i - 1] = tmp[i];
- }
-
- return res;
- }
-
- public int calculateHashCode(X500Name name)
- {
- int hashCodeValue = 0;
- RDN[] rdns = name.getRDNs();
-
- // this needs to be order independent, like equals
- for (int i = 0; i != rdns.length; i++)
- {
- if (rdns[i].isMultiValued())
- {
- AttributeTypeAndValue[] atv = rdns[i].getTypesAndValues();
-
- for (int j = 0; j != atv.length; j++)
- {
- hashCodeValue ^= atv[j].getType().hashCode();
- hashCodeValue ^= calcHashCode(atv[j].getValue());
- }
- }
- else
- {
- hashCodeValue ^= rdns[i].getFirst().getType().hashCode();
- hashCodeValue ^= calcHashCode(rdns[i].getFirst().getValue());
- }
- }
-
- return hashCodeValue;
- }
-
- private int calcHashCode(ASN1Encodable enc)
- {
- String value = IETFUtils.valueToString(enc);
-
- value = IETFUtils.canonicalize(value);
-
- return value.hashCode();
- }
-
- // convert in reverse
- public String toString(X500Name name)
- {
- StringBuffer buf = new StringBuffer();
- boolean first = true;
-
- RDN[] rdns = name.getRDNs();
-
- for (int i = rdns.length - 1; i >= 0; i--)
- {
- if (first)
- {
- first = false;
- }
- else
- {
- buf.append(',');
- }
-
- 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/core/src/main/jdk1.1/org/bouncycastle/crypto/agreement/jpake/JPAKEParticipant.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/agreement/jpake/JPAKEParticipant.java
deleted file mode 100644
index 30808802..00000000
--- a/core/src/main/jdk1.1/org/bouncycastle/crypto/agreement/jpake/JPAKEParticipant.java
+++ /dev/null
@@ -1,573 +0,0 @@
-package org.bouncycastle.crypto.agreement.jpake;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.util.Arrays;
-
-/**
- * A participant in a Password Authenticated Key Exchange by Juggling (J-PAKE) exchange.
- * <p/>
- * <p/>
- * The J-PAKE exchange is defined by Feng Hao and Peter Ryan in the paper
- * <a href="http://grouper.ieee.org/groups/1363/Research/contributions/hao-ryan-2008.pdf">
- * "Password Authenticated Key Exchange by Juggling, 2008."</a>
- * <p/>
- * <p/>
- * The J-PAKE protocol is symmetric.
- * There is no notion of a <i>client</i> or <i>server</i>, but rather just two <i>participants</i>.
- * An instance of {@link JPAKEParticipant} represents one participant, and
- * is the primary interface for executing the exchange.
- * <p/>
- * <p/>
- * To execute an exchange, construct a {@link JPAKEParticipant} on each end,
- * and call the following 7 methods
- * (once and only once, in the given order, for each participant, sending messages between them as described):
- * <ol>
- * <li>{@link #createRound1PayloadToSend()} - and send the payload to the other participant</li>
- * <li>{@link #validateRound1PayloadReceived(JPAKERound1Payload)} - use the payload received from the other participant</li>
- * <li>{@link #createRound2PayloadToSend()} - and send the payload to the other participant</li>
- * <li>{@link #validateRound2PayloadReceived(JPAKERound2Payload)} - use the payload received from the other participant</li>
- * <li>{@link #calculateKeyingMaterial()}</li>
- * <li>{@link #createRound3PayloadToSend(BigInteger)} - and send the payload to the other participant</li>
- * <li>{@link #validateRound3PayloadReceived(JPAKERound3Payload, BigInteger)} - use the payload received from the other participant</li>
- * </ol>
- * <p/>
- * <p/>
- * Each side should derive a session key from the keying material returned by {@link #calculateKeyingMaterial()}.
- * The caller is responsible for deriving the session key using a secure key derivation function (KDF).
- * <p/>
- * <p/>
- * Round 3 is an optional key confirmation process.
- * If you do not execute round 3, then there is no assurance that both participants are using the same key.
- * (i.e. if the participants used different passwords, then their session keys will differ.)
- * <p/>
- * <p/>
- * If the round 3 validation succeeds, then the keys are guaranteed to be the same on both sides.
- * <p/>
- * <p/>
- * The symmetric design can easily support the asymmetric cases when one party initiates the communication.
- * e.g. Sometimes the round1 payload and round2 payload may be sent in one pass.
- * Also, in some cases, the key confirmation payload can be sent together with the round2 payload.
- * These are the trivial techniques to optimize the communication.
- * <p/>
- * <p/>
- * The key confirmation process is implemented as specified in
- * <a href="http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf">NIST SP 800-56A Revision 1</a>,
- * Section 8.2 Unilateral Key Confirmation for Key Agreement Schemes.
- * <p/>
- * <p/>
- * This class is stateful and NOT threadsafe.
- * Each instance should only be used for ONE complete J-PAKE exchange
- * (i.e. a new {@link JPAKEParticipant} should be constructed for each new J-PAKE exchange).
- * <p/>
- * <p/>
- * See {@link JPAKEExample} for example usage.
- */
-public class JPAKEParticipant
-{
- /*
- * Possible internal states. Used for state checking.
- */
-
- public static final int STATE_INITIALIZED = 0;
- public static final int STATE_ROUND_1_CREATED = 10;
- public static final int STATE_ROUND_1_VALIDATED = 20;
- public static final int STATE_ROUND_2_CREATED = 30;
- public static final int STATE_ROUND_2_VALIDATED = 40;
- public static final int STATE_KEY_CALCULATED = 50;
- public static final int STATE_ROUND_3_CREATED = 60;
- public static final int STATE_ROUND_3_VALIDATED = 70;
-
- /**
- * Unique identifier of this participant.
- * The two participants in the exchange must NOT share the same id.
- */
- private String participantId;
-
- /**
- * Shared secret. This only contains the secret between construction
- * and the call to {@link #calculateKeyingMaterial()}.
- * <p/>
- * i.e. When {@link #calculateKeyingMaterial()} is called, this buffer overwritten with 0's,
- * and the field is set to null.
- */
- private char[] password;
-
- /**
- * Digest to use during calculations.
- */
- private Digest digest;
-
- /**
- * Source of secure random data.
- */
- private SecureRandom random;
-
- private BigInteger p;
- private BigInteger q;
- private BigInteger g;
-
- /**
- * The participantId of the other participant in this exchange.
- */
- private String partnerParticipantId;
-
- /**
- * Alice's x1 or Bob's x3.
- */
- private BigInteger x1;
- /**
- * Alice's x2 or Bob's x4.
- */
- private BigInteger x2;
- /**
- * Alice's g^x1 or Bob's g^x3.
- */
- private BigInteger gx1;
- /**
- * Alice's g^x2 or Bob's g^x4.
- */
- private BigInteger gx2;
- /**
- * Alice's g^x3 or Bob's g^x1.
- */
- private BigInteger gx3;
- /**
- * Alice's g^x4 or Bob's g^x2.
- */
- private BigInteger gx4;
- /**
- * Alice's B or Bob's A.
- */
- private BigInteger b;
-
- /**
- * The current state.
- * See the <tt>STATE_*</tt> constants for possible values.
- */
- private int state;
-
- /**
- * Convenience constructor for a new {@link JPAKEParticipant} that uses
- * the {@link JPAKEPrimeOrderGroups#NIST_3072} prime order group,
- * a SHA-256 digest, and a default {@link SecureRandom} implementation.
- * <p/>
- * After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}.
- *
- * @param participantId unique identifier of this participant.
- * The two participants in the exchange must NOT share the same id.
- * @param password shared secret.
- * A defensive copy of this array is made (and cleared once {@link #calculateKeyingMaterial()} is called).
- * Caller should clear the input password as soon as possible.
- * @throws NullPointerException if any argument is null
- * @throws IllegalArgumentException if password is empty
- */
- public JPAKEParticipant(
- String participantId,
- char[] password)
- {
- this(
- participantId,
- password,
- JPAKEPrimeOrderGroups.NIST_3072);
- }
-
-
- /**
- * Convenience constructor for a new {@link JPAKEParticipant} that uses
- * a SHA-256 digest and a default {@link SecureRandom} implementation.
- * <p/>
- * After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}.
- *
- * @param participantId unique identifier of this participant.
- * The two participants in the exchange must NOT share the same id.
- * @param password shared secret.
- * A defensive copy of this array is made (and cleared once {@link #calculateKeyingMaterial()} is called).
- * Caller should clear the input password as soon as possible.
- * @param group prime order group.
- * See {@link JPAKEPrimeOrderGroups} for standard groups
- * @throws NullPointerException if any argument is null
- * @throws IllegalArgumentException if password is empty
- */
- public JPAKEParticipant(
- String participantId,
- char[] password,
- JPAKEPrimeOrderGroup group)
- {
- this(
- participantId,
- password,
- group,
- new SHA256Digest(),
- new SecureRandom());
- }
-
-
- /**
- * Construct a new {@link JPAKEParticipant}.
- * <p/>
- * After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}.
- *
- * @param participantId unique identifier of this participant.
- * The two participants in the exchange must NOT share the same id.
- * @param password shared secret.
- * A defensive copy of this array is made (and cleared once {@link #calculateKeyingMaterial()} is called).
- * Caller should clear the input password as soon as possible.
- * @param group prime order group.
- * See {@link JPAKEPrimeOrderGroups} for standard groups
- * @param digest digest to use during zero knowledge proofs and key confirmation (SHA-256 or stronger preferred)
- * @param random source of secure random data for x1 and x2, and for the zero knowledge proofs
- * @throws NullPointerException if any argument is null
- * @throws IllegalArgumentException if password is empty
- */
- public JPAKEParticipant(
- String participantId,
- char[] password,
- JPAKEPrimeOrderGroup group,
- Digest digest,
- SecureRandom random)
- {
- JPAKEUtil.validateNotNull(participantId, "participantId");
- JPAKEUtil.validateNotNull(password, "password");
- JPAKEUtil.validateNotNull(group, "p");
- JPAKEUtil.validateNotNull(digest, "digest");
- JPAKEUtil.validateNotNull(random, "random");
- if (password.length == 0)
- {
- throw new IllegalArgumentException("Password must not be empty.");
- }
-
- this.participantId = participantId;
-
- /*
- * Create a defensive copy so as to fully encapsulate the password.
- *
- * This array will contain the password for the lifetime of this
- * participant BEFORE {@link #calculateKeyingMaterial()} is called.
- *
- * i.e. When {@link #calculateKeyingMaterial()} is called, the array will be cleared
- * in order to remove the password from memory.
- *
- * The caller is responsible for clearing the original password array
- * given as input to this constructor.
- */
- this.password = Arrays.copyOf(password, password.length);
-
- this.p = group.getP();
- this.q = group.getQ();
- this.g = group.getG();
-
- this.digest = digest;
- this.random = random;
-
- this.state = STATE_INITIALIZED;
- }
-
- /**
- * Gets the current state of this participant.
- * See the <tt>STATE_*</tt> constants for possible values.
- */
- public int getState()
- {
- return this.state;
- }
-
- /**
- * Creates and returns the payload to send to the other participant during round 1.
- * <p/>
- * <p/>
- * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_1_CREATED}.
- */
- public JPAKERound1Payload createRound1PayloadToSend()
- {
- if (this.state >= STATE_ROUND_1_CREATED)
- {
- throw new IllegalStateException("Round1 payload already created for " + participantId);
- }
-
- this.x1 = JPAKEUtil.generateX1(q, random);
- this.x2 = JPAKEUtil.generateX2(q, random);
-
- this.gx1 = JPAKEUtil.calculateGx(p, g, x1);
- this.gx2 = JPAKEUtil.calculateGx(p, g, x2);
- BigInteger[] knowledgeProofForX1 = JPAKEUtil.calculateZeroKnowledgeProof(p, q, g, gx1, x1, participantId, digest, random);
- BigInteger[] knowledgeProofForX2 = JPAKEUtil.calculateZeroKnowledgeProof(p, q, g, gx2, x2, participantId, digest, random);
-
- this.state = STATE_ROUND_1_CREATED;
-
- return new JPAKERound1Payload(participantId, gx1, gx2, knowledgeProofForX1, knowledgeProofForX2);
- }
-
- /**
- * Validates the payload received from the other participant during round 1.
- * <p/>
- * <p/>
- * Must be called prior to {@link #createRound2PayloadToSend()}.
- * <p/>
- * <p/>
- * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_1_VALIDATED}.
- *
- * @throws CryptoException if validation fails.
- * @throws IllegalStateException if called multiple times.
- */
- public void validateRound1PayloadReceived(JPAKERound1Payload round1PayloadReceived)
- throws CryptoException
- {
- if (this.state >= STATE_ROUND_1_VALIDATED)
- {
- throw new IllegalStateException("Validation already attempted for round1 payload for" + participantId);
- }
- this.partnerParticipantId = round1PayloadReceived.getParticipantId();
- this.gx3 = round1PayloadReceived.getGx1();
- this.gx4 = round1PayloadReceived.getGx2();
-
- BigInteger[] knowledgeProofForX3 = round1PayloadReceived.getKnowledgeProofForX1();
- BigInteger[] knowledgeProofForX4 = round1PayloadReceived.getKnowledgeProofForX2();
-
- JPAKEUtil.validateParticipantIdsDiffer(participantId, round1PayloadReceived.getParticipantId());
- JPAKEUtil.validateGx4(gx4);
- JPAKEUtil.validateZeroKnowledgeProof(p, q, g, gx3, knowledgeProofForX3, round1PayloadReceived.getParticipantId(), digest);
- JPAKEUtil.validateZeroKnowledgeProof(p, q, g, gx4, knowledgeProofForX4, round1PayloadReceived.getParticipantId(), digest);
-
- this.state = STATE_ROUND_1_VALIDATED;
- }
-
- /**
- * Creates and returns the payload to send to the other participant during round 2.
- * <p/>
- * <p/>
- * {@link #validateRound1PayloadReceived(JPAKERound1Payload)} must be called prior to this method.
- * <p/>
- * <p/>
- * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_2_CREATED}.
- *
- * @throws IllegalStateException if called prior to {@link #validateRound1PayloadReceived(JPAKERound1Payload)}, or multiple times
- */
- public JPAKERound2Payload createRound2PayloadToSend()
- {
- if (this.state >= STATE_ROUND_2_CREATED)
- {
- throw new IllegalStateException("Round2 payload already created for " + this.participantId);
- }
- if (this.state < STATE_ROUND_1_VALIDATED)
- {
- throw new IllegalStateException("Round1 payload must be validated prior to creating Round2 payload for " + this.participantId);
- }
- BigInteger gA = JPAKEUtil.calculateGA(p, gx1, gx3, gx4);
- BigInteger s = JPAKEUtil.calculateS(password);
- BigInteger x2s = JPAKEUtil.calculateX2s(q, x2, s);
- BigInteger A = JPAKEUtil.calculateA(p, q, gA, x2s);
- BigInteger[] knowledgeProofForX2s = JPAKEUtil.calculateZeroKnowledgeProof(p, q, gA, A, x2s, participantId, digest, random);
-
- this.state = STATE_ROUND_2_CREATED;
-
- return new JPAKERound2Payload(participantId, A, knowledgeProofForX2s);
- }
-
- /**
- * Validates the payload received from the other participant during round 2.
- * <p/>
- * <p/>
- * Note that this DOES NOT detect a non-common password.
- * The only indication of a non-common password is through derivation
- * of different keys (which can be detected explicitly by executing round 3 and round 4)
- * <p/>
- * <p/>
- * Must be called prior to {@link #calculateKeyingMaterial()}.
- * <p/>
- * <p/>
- * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_2_VALIDATED}.
- *
- * @throws CryptoException if validation fails.
- * @throws IllegalStateException if called prior to {@link #validateRound1PayloadReceived(JPAKERound1Payload)}, or multiple times
- */
- public void validateRound2PayloadReceived(JPAKERound2Payload round2PayloadReceived)
- throws CryptoException
- {
- if (this.state >= STATE_ROUND_2_VALIDATED)
- {
- throw new IllegalStateException("Validation already attempted for round2 payload for" + participantId);
- }
- if (this.state < STATE_ROUND_1_VALIDATED)
- {
- throw new IllegalStateException("Round1 payload must be validated prior to validating Round2 payload for " + this.participantId);
- }
- BigInteger gB = JPAKEUtil.calculateGA(p, gx3, gx1, gx2);
- this.b = round2PayloadReceived.getA();
- BigInteger[] knowledgeProofForX4s = round2PayloadReceived.getKnowledgeProofForX2s();
-
- JPAKEUtil.validateParticipantIdsDiffer(participantId, round2PayloadReceived.getParticipantId());
- JPAKEUtil.validateParticipantIdsEqual(this.partnerParticipantId, round2PayloadReceived.getParticipantId());
- JPAKEUtil.validateGa(gB);
- JPAKEUtil.validateZeroKnowledgeProof(p, q, gB, b, knowledgeProofForX4s, round2PayloadReceived.getParticipantId(), digest);
-
- this.state = STATE_ROUND_2_VALIDATED;
- }
-
- /**
- * Calculates and returns the key material.
- * A session key must be derived from this key material using a secure key derivation function (KDF).
- * The KDF used to derive the key is handled externally (i.e. not by {@link JPAKEParticipant}).
- * <p/>
- * <p/>
- * The keying material will be identical for each participant if and only if
- * each participant's password is the same. i.e. If the participants do not
- * share the same password, then each participant will derive a different key.
- * Therefore, if you immediately start using a key derived from
- * the keying material, then you must handle detection of incorrect keys.
- * If you want to handle this detection explicitly, you can optionally perform
- * rounds 3 and 4. See {@link JPAKEParticipant} for details on how to execute
- * rounds 3 and 4.
- * <p/>
- * <p/>
- * The keying material will be in the range <tt>[0, p-1]</tt>.
- * <p/>
- * <p/>
- * {@link #validateRound2PayloadReceived(JPAKERound2Payload)} must be called prior to this method.
- * <p/>
- * <p/>
- * As a side effect, the internal {@link #password} array is cleared, since it is no longer needed.
- * <p/>
- * <p/>
- * After execution, the {@link #getState() state} will be {@link #STATE_KEY_CALCULATED}.
- *
- * @throws IllegalStateException if called prior to {@link #validateRound2PayloadReceived(JPAKERound2Payload)},
- * or if called multiple times.
- */
- public BigInteger calculateKeyingMaterial()
- {
- if (this.state >= STATE_KEY_CALCULATED)
- {
- throw new IllegalStateException("Key already calculated for " + participantId);
- }
- if (this.state < STATE_ROUND_2_VALIDATED)
- {
- throw new IllegalStateException("Round2 payload must be validated prior to creating key for " + participantId);
- }
- BigInteger s = JPAKEUtil.calculateS(password);
-
- /*
- * Clear the password array from memory, since we don't need it anymore.
- *
- * Also set the field to null as a flag to indicate that the key has already been calculated.
- */
- Arrays.fill(password, (char)0);
- this.password = null;
-
- BigInteger keyingMaterial = JPAKEUtil.calculateKeyingMaterial(p, q, gx4, x2, s, b);
-
- /*
- * Clear the ephemeral private key fields as well.
- * Note that we're relying on the garbage collector to do its job to clean these up.
- * The old objects will hang around in memory until the garbage collector destroys them.
- *
- * If the ephemeral private keys x1 and x2 are leaked,
- * the attacker might be able to brute-force the password.
- */
- this.x1 = null;
- this.x2 = null;
- this.b = null;
-
- /*
- * Do not clear gx* yet, since those are needed by round 3.
- */
-
- this.state = STATE_KEY_CALCULATED;
-
- return keyingMaterial;
- }
-
-
- /**
- * Creates and returns the payload to send to the other participant during round 3.
- * <p/>
- * <p/>
- * See {@link JPAKEParticipant} for more details on round 3.
- * <p/>
- * <p/>
- * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_3_CREATED}.
- *
- * @param keyingMaterial The keying material as returned from {@link #calculateKeyingMaterial()}.
- * @throws IllegalStateException if called prior to {@link #calculateKeyingMaterial()}, or multiple times
- */
- public JPAKERound3Payload createRound3PayloadToSend(BigInteger keyingMaterial)
- {
- if (this.state >= STATE_ROUND_3_CREATED)
- {
- throw new IllegalStateException("Round3 payload already created for " + this.participantId);
- }
- if (this.state < STATE_KEY_CALCULATED)
- {
- throw new IllegalStateException("Keying material must be calculated prior to creating Round3 payload for " + this.participantId);
- }
-
- BigInteger macTag = JPAKEUtil.calculateMacTag(
- this.participantId,
- this.partnerParticipantId,
- this.gx1,
- this.gx2,
- this.gx3,
- this.gx4,
- keyingMaterial,
- this.digest);
-
- this.state = STATE_ROUND_3_CREATED;
-
- return new JPAKERound3Payload(participantId, macTag);
- }
-
- /**
- * Validates the payload received from the other participant during round 3.
- * <p/>
- * <p/>
- * See {@link JPAKEParticipant} for more details on round 3.
- * <p/>
- * <p/>
- * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_3_VALIDATED}.
- *
- * @param keyingMaterial The keying material as returned from {@link #calculateKeyingMaterial()}.
- * @throws CryptoException if validation fails.
- * @throws IllegalStateException if called prior to {@link #calculateKeyingMaterial()}, or multiple times
- */
- public void validateRound3PayloadReceived(JPAKERound3Payload round3PayloadReceived, BigInteger keyingMaterial)
- throws CryptoException
- {
- if (this.state >= STATE_ROUND_3_VALIDATED)
- {
- throw new IllegalStateException("Validation already attempted for round3 payload for" + participantId);
- }
- if (this.state < STATE_KEY_CALCULATED)
- {
- throw new IllegalStateException("Keying material must be calculated validated prior to validating Round3 payload for " + this.participantId);
- }
- JPAKEUtil.validateParticipantIdsDiffer(participantId, round3PayloadReceived.getParticipantId());
- JPAKEUtil.validateParticipantIdsEqual(this.partnerParticipantId, round3PayloadReceived.getParticipantId());
-
- JPAKEUtil.validateMacTag(
- this.participantId,
- this.partnerParticipantId,
- this.gx1,
- this.gx2,
- this.gx3,
- this.gx4,
- keyingMaterial,
- this.digest,
- round3PayloadReceived.getMacTag());
-
-
- /*
- * Clear the rest of the fields.
- */
- this.gx1 = null;
- this.gx2 = null;
- this.gx3 = null;
- this.gx4 = null;
-
- this.state = STATE_ROUND_3_VALIDATED;
- }
-
-}
diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java
deleted file mode 100644
index 5a2f4022..00000000
--- a/core/src/main/jdk1.1/org/bouncycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java
+++ /dev/null
@@ -1,122 +0,0 @@
-package org.bouncycastle.crypto.agreement.jpake;
-
-import java.math.BigInteger;
-
-/**
- * A pre-computed prime order group for use during a J-PAKE exchange.
- * <p/>
- * <p/>
- * Typically a Schnorr group is used. In general, J-PAKE can use any prime order group
- * that is suitable for public key cryptography, including elliptic curve cryptography.
- * <p/>
- * <p/>
- * See {@link JPAKEPrimeOrderGroups} for convenient standard groups.
- * <p/>
- * <p/>
- * NIST <a href="http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/DSA2_All.pdf">publishes</a>
- * many groups that can be used for the desired level of security.
- */
-public class JPAKEPrimeOrderGroup
-{
- private BigInteger p;
- private BigInteger q;
- private BigInteger g;
-
- /**
- * Constructs a new {@link JPAKEPrimeOrderGroup}.
- * <p/>
- * <p/>
- * In general, you should use one of the pre-approved groups from
- * {@link JPAKEPrimeOrderGroups}, rather than manually constructing one.
- * <p/>
- * <p/>
- * The following basic checks are performed:
- * <ul>
- * <li>p-1 must be evenly divisible by q</li>
- * <li>g must be in [2, p-1]</li>
- * <li>g^q mod p must equal 1</li>
- * <li>p must be prime (within reasonably certainty)</li>
- * <li>q must be prime (within reasonably certainty)</li>
- * </ul>
- * <p/>
- * <p/>
- * The prime checks are performed using {@link BigInteger#isProbablePrime(int)},
- * and are therefore subject to the same probability guarantees.
- * <p/>
- * <p/>
- * These checks prevent trivial mistakes.
- * However, due to the small uncertainties if p and q are not prime,
- * advanced attacks are not prevented.
- * Use it at your own risk.
- *
- * @throws NullPointerException if any argument is null
- * @throws IllegalArgumentException if any of the above validations fail
- */
- public JPAKEPrimeOrderGroup(BigInteger p, BigInteger q, BigInteger g)
- {
- /*
- * Don't skip the checks on user-specified groups.
- */
- this(p, q, g, false);
- }
-
- /**
- * Internal package-private constructor used by the pre-approved
- * groups in {@link JPAKEPrimeOrderGroups}.
- * These pre-approved groups can avoid the expensive checks.
- */
- JPAKEPrimeOrderGroup(BigInteger p, BigInteger q, BigInteger g, boolean skipChecks)
- {
- JPAKEUtil.validateNotNull(p, "p");
- JPAKEUtil.validateNotNull(q, "q");
- JPAKEUtil.validateNotNull(g, "g");
-
- if (!skipChecks)
- {
- if (!p.subtract(JPAKEUtil.ONE).mod(q).equals(JPAKEUtil.ZERO))
- {
- throw new IllegalArgumentException("p-1 must be evenly divisible by q");
- }
- if (g.compareTo(BigInteger.valueOf(2)) == -1 || g.compareTo(p.subtract(JPAKEUtil.ONE)) == 1)
- {
- throw new IllegalArgumentException("g must be in [2, p-1]");
- }
- if (!g.modPow(q, p).equals(JPAKEUtil.ONE))
- {
- throw new IllegalArgumentException("g^q mod p must equal 1");
- }
- /*
- * Note that these checks do not guarantee that p and q are prime.
- * We just have reasonable certainty that they are prime.
- */
- if (!p.isProbablePrime(20))
- {
- throw new IllegalArgumentException("p must be prime");
- }
- if (!q.isProbablePrime(20))
- {
- throw new IllegalArgumentException("q must be prime");
- }
- }
-
- this.p = p;
- this.q = q;
- this.g = g;
- }
-
- public BigInteger getP()
- {
- return p;
- }
-
- public BigInteger getQ()
- {
- return q;
- }
-
- public BigInteger getG()
- {
- return g;
- }
-
-}
diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/digests/SkeinEngine.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/digests/SkeinEngine.java
deleted file mode 100644
index 5bfee7e6..00000000
--- a/core/src/main/jdk1.1/org/bouncycastle/crypto/digests/SkeinEngine.java
+++ /dev/null
@@ -1,817 +0,0 @@
-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
- */
- private ThreefishEngine threefish;
-
- /**
- * Size of the digest output, in bytes
- */
- private 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 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/core/src/main/jdk1.1/org/bouncycastle/crypto/encodings/PKCS1Encoding.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
deleted file mode 100644
index 76051c3f..00000000
--- a/core/src/main/jdk1.1/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
+++ /dev/null
@@ -1,410 +0,0 @@
-package org.bouncycastle.crypto.encodings;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-
-/**
- * this does your basic PKCS 1 v1.5 padding - whether or not you should be using this
- * depends on your application - see PKCS1 Version 2 for details.
- */
-public class PKCS1Encoding
- implements AsymmetricBlockCipher
-{
- /**
- * some providers fail to include the leading zero in PKCS1 encoded blocks. If you need to
- * work with one of these set the system property org.bouncycastle.pkcs1.strict to false.
- * <p>
- * The system property is checked during construction of the encoding object, it is set to
- * true by default.
- * </p>
- */
- public static final String STRICT_LENGTH_ENABLED_PROPERTY = "org.bouncycastle.pkcs1.strict";
-
- private static final int HEADER_LENGTH = 10;
-
- private SecureRandom random;
- private AsymmetricBlockCipher engine;
- private boolean forEncryption;
- private boolean forPrivateKey;
- private boolean useStrictLength;
- private int pLen = -1;
- private byte[] fallback = null;
-
- /**
- * Basic constructor.
- * @param cipher
- */
- public PKCS1Encoding(
- AsymmetricBlockCipher cipher)
- {
- this.engine = cipher;
- this.useStrictLength = useStrict();
- }
-
- /**
- * Constructor for decryption with a fixed plaintext length.
- *
- * @param cipher The cipher to use for cryptographic operation.
- * @param pLen Length of the expected plaintext.
- */
- public PKCS1Encoding(
- AsymmetricBlockCipher cipher,
- int pLen)
- {
- this.engine = cipher;
- this.useStrictLength = useStrict();
- this.pLen = pLen;
- }
-
- /**
- * Constructor for decryption with a fixed plaintext length and a fallback
- * value that is returned, if the padding is incorrect.
- *
- * @param cipher
- * The cipher to use for cryptographic operation.
- * @param fallback
- * The fallback value, we don't to a arraycopy here.
- */
- public PKCS1Encoding(
- AsymmetricBlockCipher cipher,
- byte[] fallback)
- {
- this.engine = cipher;
- this.useStrictLength = useStrict();
- this.fallback = fallback;
- this.pLen = fallback.length;
- }
-
-
-
- //
- // for J2ME compatibility
- //
- private boolean useStrict()
- {
- // required if security manager has been installed.
- String strict = System.getProperty(STRICT_LENGTH_ENABLED_PROPERTY);
-
- return strict == null || strict.equals("true");
- }
-
- public AsymmetricBlockCipher getUnderlyingCipher()
- {
- return engine;
- }
-
- public void init(
- boolean forEncryption,
- CipherParameters param)
- {
- AsymmetricKeyParameter kParam;
-
- if (param instanceof ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
-
- this.random = rParam.getRandom();
- kParam = (AsymmetricKeyParameter)rParam.getParameters();
- }
- else
- {
- this.random = new SecureRandom();
- kParam = (AsymmetricKeyParameter)param;
- }
-
- engine.init(forEncryption, param);
-
- this.forPrivateKey = kParam.isPrivate();
- this.forEncryption = forEncryption;
- }
-
- public int getInputBlockSize()
- {
- int baseBlockSize = engine.getInputBlockSize();
-
- if (forEncryption)
- {
- return baseBlockSize - HEADER_LENGTH;
- }
- else
- {
- return baseBlockSize;
- }
- }
-
- public int getOutputBlockSize()
- {
- int baseBlockSize = engine.getOutputBlockSize();
-
- if (forEncryption)
- {
- return baseBlockSize;
- }
- else
- {
- return baseBlockSize - HEADER_LENGTH;
- }
- }
-
- public byte[] processBlock(
- byte[] in,
- int inOff,
- int inLen)
- throws InvalidCipherTextException
- {
- if (forEncryption)
- {
- return encodeBlock(in, inOff, inLen);
- }
- else
- {
- return decodeBlock(in, inOff, inLen);
- }
- }
-
- private byte[] encodeBlock(
- byte[] in,
- int inOff,
- int inLen)
- throws InvalidCipherTextException
- {
- if (inLen > getInputBlockSize())
- {
- throw new IllegalArgumentException("input data too large");
- }
-
- byte[] block = new byte[engine.getInputBlockSize()];
-
- if (forPrivateKey)
- {
- block[0] = 0x01; // type code 1
-
- for (int i = 1; i != block.length - inLen - 1; i++)
- {
- block[i] = (byte)0xFF;
- }
- }
- else
- {
- random.nextBytes(block); // random fill
-
- block[0] = 0x02; // type code 2
-
- //
- // a zero byte marks the end of the padding, so all
- // the pad bytes must be non-zero.
- //
- for (int i = 1; i != block.length - inLen - 1; i++)
- {
- while (block[i] == 0)
- {
- block[i] = (byte)random.nextInt();
- }
- }
- }
-
- block[block.length - inLen - 1] = 0x00; // mark the end of the padding
- System.arraycopy(in, inOff, block, block.length - inLen, inLen);
-
- return engine.processBlock(block, 0, block.length);
- }
-
- /**
- * Checks if the argument is a correctly PKCS#1.5 encoded Plaintext
- * for encryption.
- *
- * @param encoded The Plaintext.
- * @param pLen Expected length of the plaintext.
- * @return Either 0, if the encoding is correct, or -1, if it is incorrect.
- */
- private static int checkPkcs1Encoding(byte[] encoded, int pLen) {
- int correct = 0;
- /*
- * Check if the first two bytes are 0 2
- */
- correct |= (encoded[0] ^ 2);
-
- /*
- * Now the padding check, check for no 0 byte in the padding
- */
- int plen = encoded.length - (
- pLen /* Lenght of the PMS */
- + 1 /* Final 0-byte before PMS */
- );
-
- for (int i = 1; i < plen; i++) {
- int tmp = encoded[i];
- tmp |= tmp >> 1;
- tmp |= tmp >> 2;
- tmp |= tmp >> 4;
- correct |= (tmp & 1) - 1;
- }
-
- /*
- * Make sure the padding ends with a 0 byte.
- */
- correct |= encoded[encoded.length - (pLen +1)];
-
- /*
- * Return 0 or 1, depending on the result.
- */
- correct |= correct >> 1;
- correct |= correct >> 2;
- correct |= correct >> 4;
- return ~((correct & 1) - 1);
- }
-
-
- /**
- * Decode PKCS#1.5 encoding, and return a random value if the padding is not correct.
- *
- * @param in The encrypted block.
- * @param inOff Offset in the encrypted block.
- * @param inLen Length of the encrypted block.
- * //@param pLen Length of the desired output.
- * @return The plaintext without padding, or a random value if the padding was incorrect.
- *
- * @throws InvalidCipherTextException
- */
- private byte[] decodeBlockOrRandom(byte[] in, int inOff, int inLen)
- throws InvalidCipherTextException
- {
- if (!forPrivateKey)
- {
- throw new InvalidCipherTextException("sorry, this method is only for decryption, not for signing");
- }
-
- byte[] block = engine.processBlock(in, inOff, inLen);
- byte[] random = null;
- if (this.fallback == null)
- {
- random = new byte[this.pLen];
- this.random.nextBytes(random);
- }
- else
- {
- random = fallback;
- }
-
- /*
- * TODO: This is a potential dangerous side channel. However, you can
- * fix this by changing the RSA engine in a way, that it will always
- * return blocks of the same length and prepend them with 0 bytes if
- * needed.
- */
- if (block.length < getOutputBlockSize())
- {
- throw new InvalidCipherTextException("block truncated");
- }
-
- /*
- * TODO: Potential side channel. Fix it by making the engine always
- * return blocks of the correct length.
- */
- if (useStrictLength && block.length != engine.getOutputBlockSize())
- {
- throw new InvalidCipherTextException("block incorrect size");
- }
-
- /*
- * Check the padding.
- */
- int correct = PKCS1Encoding.checkPkcs1Encoding(block, this.pLen);
-
- /*
- * Now, to a constant time constant memory copy of the decrypted value
- * or the random value, depending on the validity of the padding.
- */
- byte[] result = new byte[this.pLen];
- for (int i = 0; i < this.pLen; i++)
- {
- result[i] = (byte)((block[i + (block.length - pLen)] & (~correct)) | (random[i] & correct));
- }
-
- return result;
- }
-
- /**
- * @exception InvalidCipherTextException if the decrypted block is not in PKCS1 format.
- */
- private byte[] decodeBlock(
- byte[] in,
- int inOff,
- int inLen)
- throws InvalidCipherTextException
- {
- /*
- * If the length of the expected plaintext is known, we use a constant-time decryption.
- * If the decryption fails, we return a random value.
- */
- if (this.pLen != -1) {
- return this.decodeBlockOrRandom(in, inOff, inLen);
- }
-
- byte[] block = engine.processBlock(in, inOff, inLen);
-
- if (block.length < getOutputBlockSize())
- {
- throw new InvalidCipherTextException("block truncated");
- }
-
- byte type = block[0];
-
- if (forPrivateKey)
- {
- if (type != 2)
- {
- throw new InvalidCipherTextException("unknown block type");
- }
- }
- else
- {
- if (type != 1)
- {
- throw new InvalidCipherTextException("unknown block type");
- }
- }
-
- if (useStrictLength && block.length != engine.getOutputBlockSize())
- {
- throw new InvalidCipherTextException("block incorrect size");
- }
-
- //
- // find and extract the message block.
- //
- int start;
-
- for (start = 1; start != block.length; start++)
- {
- byte pad = block[start];
-
- if (pad == 0)
- {
- break;
- }
- if (type == 1 && pad != (byte)0xff)
- {
- throw new InvalidCipherTextException("block padding incorrect");
- }
- }
-
- start++; // data should start at the next byte
-
- if (start > block.length || start < HEADER_LENGTH)
- {
- throw new InvalidCipherTextException("no data in block");
- }
-
- byte[] result = new byte[block.length - start];
-
- System.arraycopy(block, start, result, 0, result.length);
-
- return result;
- }
-}
diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/engines/NullEngine.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/engines/NullEngine.java
deleted file mode 100644
index b5c74512..00000000
--- a/core/src/main/jdk1.1/org/bouncycastle/crypto/engines/NullEngine.java
+++ /dev/null
@@ -1,96 +0,0 @@
-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;
-
-/**
- * The no-op engine that just copies bytes through, irrespective of whether encrypting and decrypting.
- * Provided for the sake of completeness.
- */
-public class NullEngine implements BlockCipher
-{
- private boolean initialised;
- protected static final int DEFAULT_BLOCK_SIZE = 1;
- private int blockSize;
-
- /**
- * Constructs a null engine with a block size of 1 byte.
- */
- public NullEngine()
- {
- 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)
- * @see org.bouncycastle.crypto.BlockCipher#init(boolean, org.bouncycastle.crypto.CipherParameters)
- */
- public void init(boolean forEncryption, CipherParameters params) throws IllegalArgumentException
- {
- // we don't mind any parameters that may come in
- this.initialised = true;
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.crypto.BlockCipher#getAlgorithmName()
- */
- public String getAlgorithmName()
- {
- return "Null";
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.crypto.BlockCipher#getBlockSize()
- */
- public int getBlockSize()
- {
- return blockSize;
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.crypto.BlockCipher#processBlock(byte[], int, byte[], int)
- */
- public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
- throws DataLengthException, IllegalStateException
- {
- if (!initialised)
- {
- throw new IllegalStateException("Null engine not initialised");
- }
- 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];
- }
-
- return blockSize;
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.crypto.BlockCipher#reset()
- */
- public void reset()
- {
- // nothing needs to be done
- }
-}
diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/params/DSAParameterGenerationParameters.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/params/DSAParameterGenerationParameters.java
deleted file mode 100644
index 3cbe9182..00000000
--- a/core/src/main/jdk1.1/org/bouncycastle/crypto/params/DSAParameterGenerationParameters.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.security.SecureRandom;
-
-public class DSAParameterGenerationParameters
-{
- public static final int DIGITAL_SIGNATURE_USAGE = 1;
- public static final int KEY_ESTABLISHMENT_USAGE = 2;
-
- private int l;
- private int n;
- private int usageIndex;
- private int certainty;
- private SecureRandom random;
-
- /**
- * Construct without a usage index, this will do a random construction of G.
- *
- * @param L desired length of prime P in bits (the effective key size).
- * @param N desired length of prime Q in bits.
- * @param certainty certainty level for prime number generation.
- * @param random the source of randomness to use.
- */
- public DSAParameterGenerationParameters(
- int L,
- int N,
- int certainty,
- SecureRandom random)
- {
- this(L, N, certainty, random, -1);
- }
-
- /**
- * Construct for a specific usage index - this has the effect of using verifiable canonical generation of G.
- *
- * @param L desired length of prime P in bits (the effective key size).
- * @param N desired length of prime Q in bits.
- * @param certainty certainty level for prime number generation.
- * @param random the source of randomness to use.
- * @param usageIndex a valid usage index.
- */
- public DSAParameterGenerationParameters(
- int L,
- int N,
- int certainty,
- SecureRandom random,
- int usageIndex)
- {
- this.l = L;
- this.n = N;
- this.certainty = certainty;
- this.usageIndex = usageIndex;
- this.random = random;
- }
-
- public int getL()
- {
- return l;
- }
-
- public int getN()
- {
- return n;
- }
-
- public int getCertainty()
- {
- return certainty;
- }
-
- public SecureRandom getRandom()
- {
- return random;
- }
-
- public int getUsageIndex()
- {
- return usageIndex;
- }
-}
diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/params/HKDFParameters.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/params/HKDFParameters.java
deleted file mode 100644
index 0f41955a..00000000
--- a/core/src/main/jdk1.1/org/bouncycastle/crypto/params/HKDFParameters.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.DerivationParameters;
-import org.bouncycastle.util.Arrays;
-
-/**
- * Parameter class for the HKDFBytesGenerator class.
- */
-public class HKDFParameters
- implements DerivationParameters
-{
- private byte[] ikm;
- private boolean skipExpand;
- private byte[] salt;
- private byte[] info;
-
- private HKDFParameters(final byte[] ikm, final boolean skip,
- final byte[] salt, final byte[] info)
- {
- if (ikm == null)
- {
- throw new IllegalArgumentException(
- "IKM (input keying material) should not be null");
- }
-
- this.ikm = Arrays.clone(ikm);
-
- this.skipExpand = skip;
-
- if (salt == null || salt.length == 0)
- {
- this.salt = null;
- }
- else
- {
- this.salt = Arrays.clone(salt);
- }
-
- if (info == null)
- {
- this.info = new byte[0];
- }
- else
- {
- this.info = Arrays.clone(info);
- }
- }
-
- /**
- * Generates parameters for HKDF, specifying both the optional salt and
- * optional info. Step 1: Extract won't be skipped.
- *
- * @param ikm the input keying material or seed
- * @param salt the salt to use, may be null for a salt for hashLen zeros
- * @param info the info to use, may be null for an info field of zero bytes
- */
- public HKDFParameters(final byte[] ikm, final byte[] salt, final byte[] info)
- {
- this(ikm, false, salt, info);
- }
-
- /**
- * Factory method that makes the HKDF skip the extract part of the key
- * derivation function.
- *
- * @param ikm the input keying material or seed, directly used for step 2:
- * Expand
- * @param info the info to use, may be null for an info field of zero bytes
- * @return HKDFParameters that makes the implementation skip step 1
- */
- public static HKDFParameters skipExtractParameters(final byte[] ikm,
- final byte[] info)
- {
-
- return new HKDFParameters(ikm, true, null, info);
- }
-
- public static HKDFParameters defaultParameters(final byte[] ikm)
- {
- return new HKDFParameters(ikm, false, null, null);
- }
-
- /**
- * Returns the input keying material or seed.
- *
- * @return the keying material
- */
- public byte[] getIKM()
- {
- return Arrays.clone(ikm);
- }
-
- /**
- * Returns if step 1: extract has to be skipped or not
- *
- * @return true for skipping, false for no skipping of step 1
- */
- public boolean skipExtract()
- {
- return skipExpand;
- }
-
- /**
- * Returns the salt, or null if the salt should be generated as a byte array
- * of HashLen zeros.
- *
- * @return the salt, or null
- */
- public byte[] getSalt()
- {
- return Arrays.clone(salt);
- }
-
- /**
- * Returns the info field, which may be empty (null is converted to empty).
- *
- * @return the info field, never null
- */
- public byte[] getInfo()
- {
- return Arrays.clone(info);
- }
-}
diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/prng/BasicEntropySourceProvider.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/prng/BasicEntropySourceProvider.java
deleted file mode 100644
index ded87a71..00000000
--- a/core/src/main/jdk1.1/org/bouncycastle/crypto/prng/BasicEntropySourceProvider.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.bouncycastle.crypto.prng;
-
-import java.security.SecureRandom;
-
-/**
- * An EntropySourceProvider where entropy generation is based on a SecureRandom output using SecureRandom.generateSeed().
- */
-public class BasicEntropySourceProvider
- implements EntropySourceProvider
-{
- private SecureRandom _sr;
- private boolean _predictionResistant;
-
- /**
- * Create a entropy source provider based on the passed in SecureRandom.
- *
- * @param random the SecureRandom to base EntropySource construction on.
- * @param isPredictionResistant boolean indicating if the SecureRandom is based on prediction resistant entropy or not (true if it is).
- */
- public BasicEntropySourceProvider(SecureRandom random, boolean isPredictionResistant)
- {
- _sr = random;
- _predictionResistant = isPredictionResistant;
- }
-
- /**
- * Return an entropy source that will create bitsRequired bits of entropy on
- * each invocation of getEntropy().
- *
- * @param bitsRequired size (in bits) of entropy to be created by the provided source.
- * @return an EntropySource that generates bitsRequired bits of entropy on each call to its getEntropy() method.
- */
- public EntropySource get(final int bitsRequired)
- {
- return new EntropySource()
- {
- public boolean isPredictionResistant()
- {
- return _predictionResistant;
- }
-
- public byte[] getEntropy()
- {
- byte[] rv = new byte[(bitsRequired + 7) / 8];
-
- _sr.nextBytes(rv);
-
- return rv;
- }
-
- public int entropySize()
- {
- return bitsRequired;
- }
- };
- }
-}
diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/prng/SP800SecureRandomBuilder.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/prng/SP800SecureRandomBuilder.java
deleted file mode 100644
index 666a8541..00000000
--- a/core/src/main/jdk1.1/org/bouncycastle/crypto/prng/SP800SecureRandomBuilder.java
+++ /dev/null
@@ -1,289 +0,0 @@
-package org.bouncycastle.crypto.prng;
-
-import java.security.SecureRandom;
-
-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;
-import org.bouncycastle.crypto.prng.drbg.SP80090DRBG;
-
-/**
- * Builder class for making SecureRandom objects based on SP 800-90A Deterministic Random Bit Generators (DRBG).
- */
-public class SP800SecureRandomBuilder
-{
- private SecureRandom random;
- private EntropySourceProvider entropySourceProvider;
-
- private byte[] personalizationString;
- private int securityStrength = 256;
- private int entropyBitsRequired = 256;
-
- /**
- * Basic constructor, creates a builder using an EntropySourceProvider based on the default SecureRandom with
- * predictionResistant set to false.
- * <p>
- * Any SecureRandom created from a builder constructed like this will make use of input passed to SecureRandom.setSeed() if
- * the default SecureRandom does for its generateSeed() call.
- * </p>
- */
- public SP800SecureRandomBuilder()
- {
- this(new SecureRandom(), false);
- }
-
- /**
- * Construct a builder with an EntropySourceProvider based on the passed in SecureRandom and the passed in value
- * for prediction resistance.
- * <p>
- * Any SecureRandom created from a builder constructed like this will make use of input passed to SecureRandom.setSeed() if
- * the passed in SecureRandom does for its generateSeed() call.
- * </p>
- * @param entropySource
- * @param predictionResistant
- */
- public SP800SecureRandomBuilder(SecureRandom entropySource, boolean predictionResistant)
- {
- this.random = entropySource;
- this.entropySourceProvider = new BasicEntropySourceProvider(random, predictionResistant);
- }
-
- /**
- * Create a builder which makes creates the SecureRandom objects from a specified entropy source provider.
- * <p>
- * <b>Note:</b> If this constructor is used any calls to setSeed() in the resulting SecureRandom will be ignored.
- * </p>
- * @param entropySourceProvider a provider of EntropySource objects.
- */
- public SP800SecureRandomBuilder(EntropySourceProvider entropySourceProvider)
- {
- this.random = null;
- this.entropySourceProvider = entropySourceProvider;
- }
-
- /**
- * Set the personalization string for DRBG SecureRandoms created by this builder
- * @param personalizationString the personalisation string for the underlying DRBG.
- * @return the current builder.
- */
- public SP800SecureRandomBuilder setPersonalizationString(byte[] personalizationString)
- {
- this.personalizationString = personalizationString;
-
- return this;
- }
-
- /**
- * Set the security strength required for DRBGs used in building SecureRandom objects.
- *
- * @param securityStrength the security strength (in bits)
- * @return the current builder.
- */
- public SP800SecureRandomBuilder setSecurityStrength(int securityStrength)
- {
- this.securityStrength = securityStrength;
-
- return this;
- }
-
- /**
- * Set the amount of entropy bits required for seeding and reseeding DRBGs used in building SecureRandom objects.
- *
- * @param entropyBitsRequired the number of bits of entropy to be requested from the entropy source on each seed/reseed.
- * @return the current builder.
- */
- public SP800SecureRandomBuilder setEntropyBitsRequired(int entropyBitsRequired)
- {
- this.entropyBitsRequired = entropyBitsRequired;
-
- return this;
- }
-
- /**
- * Build a SecureRandom based on a SP 800-90A Hash DRBG.
- *
- * @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 Hash DRBG.
- */
- public SP800SecureRandom buildHash(Digest digest, byte[] nonce, boolean predictionResistant)
- {
- return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new HashDRBGProvider(digest, nonce, personalizationString, securityStrength), predictionResistant);
- }
-
- /**
- * Build a SecureRandom based on a SP 800-90A CTR DRBG.
- *
- * @param cipher the block cipher to base the DRBG on.
- * @param keySizeInBits key size in bits to be used with the block cipher.
- * @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 CTR DRBG.
- */
- public SP800SecureRandom buildCTR(BlockCipher cipher, int keySizeInBits, byte[] nonce, boolean predictionResistant)
- {
- return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new CTRDRBGProvider(cipher, keySizeInBits, nonce, personalizationString, securityStrength), predictionResistant);
- }
-
- /**
- * Build a SecureRandom based on a SP 800-90A HMAC DRBG.
- *
- * @param hMac HMAC 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 HMAC DRBG.
- */
- public SP800SecureRandom buildHMAC(Mac hMac, byte[] nonce, boolean predictionResistant)
- {
- return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new HMacDRBGProvider(hMac, nonce, personalizationString, securityStrength), predictionResistant);
- }
-
- /**
- * Build a SecureRandom based on a SP 800-90A Dual EC DRBG.
- *
- * @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(Digest digest, byte[] nonce, boolean predictionResistant)
- {
- 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.
- *
- * @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
- {
- private final Digest digest;
- private final byte[] nonce;
- private final byte[] personalizationString;
- private final int securityStrength;
-
- public HashDRBGProvider(Digest digest, byte[] nonce, byte[] personalizationString, int securityStrength)
- {
- this.digest = digest;
- this.nonce = nonce;
- this.personalizationString = personalizationString;
- this.securityStrength = securityStrength;
- }
-
- public SP80090DRBG get(EntropySource entropySource)
- {
- return new HashSP800DRBG(digest, securityStrength, entropySource, personalizationString, nonce);
- }
- }
-
- private static class DualECDRBGProvider
- implements DRBGProvider
- {
- private final Digest digest;
- private final byte[] nonce;
- private final byte[] personalizationString;
- private final int securityStrength;
-
- public DualECDRBGProvider(Digest digest, byte[] nonce, byte[] personalizationString, int securityStrength)
- {
- this.digest = digest;
- this.nonce = nonce;
- this.personalizationString = personalizationString;
- this.securityStrength = securityStrength;
- }
-
- public SP80090DRBG get(EntropySource entropySource)
- {
- return new DualECSP800DRBG(digest, securityStrength, entropySource, personalizationString, nonce);
- }
- }
-
- 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
- {
- private final Mac hMac;
- private final byte[] nonce;
- private final byte[] personalizationString;
- private final int securityStrength;
-
- public HMacDRBGProvider(Mac hMac, byte[] nonce, byte[] personalizationString, int securityStrength)
- {
- this.hMac = hMac;
- this.nonce = nonce;
- this.personalizationString = personalizationString;
- this.securityStrength = securityStrength;
- }
-
- public SP80090DRBG get(EntropySource entropySource)
- {
- return new HMacSP800DRBG(hMac, securityStrength, entropySource, personalizationString, nonce);
- }
- }
-
- private static class CTRDRBGProvider
- implements DRBGProvider
- {
-
- private final BlockCipher blockCipher;
- private final int keySizeInBits;
- private final byte[] nonce;
- private final byte[] personalizationString;
- private final int securityStrength;
-
- public CTRDRBGProvider(BlockCipher blockCipher, int keySizeInBits, byte[] nonce, byte[] personalizationString, int securityStrength)
- {
- this.blockCipher = blockCipher;
- this.keySizeInBits = keySizeInBits;
- this.nonce = nonce;
- this.personalizationString = personalizationString;
- this.securityStrength = securityStrength;
- }
-
- public SP80090DRBG get(EntropySource entropySource)
- {
- return new CTRSP800DRBG(blockCipher, keySizeInBits, securityStrength, entropySource, personalizationString, nonce);
- }
- }
-}
diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/signers/RSADigestSigner.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/signers/RSADigestSigner.java
deleted file mode 100644
index f15e4047..00000000
--- a/core/src/main/jdk1.1/org/bouncycastle/crypto/signers/RSADigestSigner.java
+++ /dev/null
@@ -1,238 +0,0 @@
-package org.bouncycastle.crypto.signers;
-
-import java.io.IOException;
-import java.util.Hashtable;
-
-import org.bouncycastle.asn1.ASN1Encoding;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.DigestInfo;
-import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.Signer;
-import org.bouncycastle.crypto.encodings.PKCS1Encoding;
-import org.bouncycastle.crypto.engines.RSABlindedEngine;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.util.Arrays;
-
-public class RSADigestSigner
- implements Signer
-{
- private final AsymmetricBlockCipher rsaEngine = new PKCS1Encoding(new RSABlindedEngine());
- private AlgorithmIdentifier algId;
- private Digest digest;
- private boolean forSigning;
-
- private static final Hashtable oidMap = new Hashtable();
-
- /*
- * Load OID table.
- */
- static
- {
- oidMap.put("RIPEMD128", TeleTrusTObjectIdentifiers.ripemd128);
- oidMap.put("RIPEMD160", TeleTrusTObjectIdentifiers.ripemd160);
- oidMap.put("RIPEMD256", TeleTrusTObjectIdentifiers.ripemd256);
-
- oidMap.put("SHA-1", X509ObjectIdentifiers.id_SHA1);
- oidMap.put("SHA-224", NISTObjectIdentifiers.id_sha224);
- oidMap.put("SHA-256", NISTObjectIdentifiers.id_sha256);
- oidMap.put("SHA-384", NISTObjectIdentifiers.id_sha384);
- oidMap.put("SHA-512", NISTObjectIdentifiers.id_sha512);
-
- oidMap.put("MD2", PKCSObjectIdentifiers.md2);
- oidMap.put("MD4", PKCSObjectIdentifiers.md4);
- oidMap.put("MD5", PKCSObjectIdentifiers.md5);
- }
-
- public RSADigestSigner(
- Digest digest)
- {
- this(digest, (ASN1ObjectIdentifier)oidMap.get(digest.getAlgorithmName()));
- }
-
- public RSADigestSigner(
- Digest digest,
- ASN1ObjectIdentifier digestOid)
- {
- this.digest = digest;
- this.algId = new AlgorithmIdentifier(digestOid, DERNull.INSTANCE);
- }
-
- /**
- * @deprecated
- */
- public String getAlgorithmName()
- {
- return digest.getAlgorithmName() + "withRSA";
- }
-
- /**
- * initialise the signer for signing or verification.
- *
- * @param forSigning
- * true if for signing, false otherwise
- * @param parameters
- * necessary parameters.
- */
- public void init(
- boolean forSigning,
- CipherParameters parameters)
- {
- this.forSigning = forSigning;
- AsymmetricKeyParameter k;
-
- if (parameters instanceof ParametersWithRandom)
- {
- k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).getParameters();
- }
- else
- {
- k = (AsymmetricKeyParameter)parameters;
- }
-
- if (forSigning && !k.isPrivate())
- {
- throw new IllegalArgumentException("signing requires private key");
- }
-
- if (!forSigning && k.isPrivate())
- {
- throw new IllegalArgumentException("verification requires public key");
- }
-
- reset();
-
- rsaEngine.init(forSigning, parameters);
- }
-
- /**
- * update the internal digest with the byte b
- */
- public void update(
- byte input)
- {
- digest.update(input);
- }
-
- /**
- * update the internal digest with the byte array in
- */
- public void update(
- byte[] input,
- int inOff,
- int length)
- {
- digest.update(input, inOff, length);
- }
-
- /**
- * Generate a signature for the message we've been loaded with using the key
- * we were initialised with.
- */
- public byte[] generateSignature()
- throws CryptoException, DataLengthException
- {
- if (!forSigning)
- {
- throw new IllegalStateException("RSADigestSigner not initialised for signature generation.");
- }
-
- byte[] hash = new byte[digest.getDigestSize()];
- digest.doFinal(hash, 0);
-
- try
- {
- byte[] data = derEncode(hash);
- return rsaEngine.processBlock(data, 0, data.length);
- }
- catch (IOException e)
- {
- throw new CryptoException("unable to encode signature: " + e.getMessage(), e);
- }
- }
-
- /**
- * return true if the internal state represents the signature described in
- * the passed in array.
- */
- public boolean verifySignature(
- byte[] signature)
- {
- if (forSigning)
- {
- throw new IllegalStateException("RSADigestSigner not initialised for verification");
- }
-
- byte[] hash = new byte[digest.getDigestSize()];
-
- digest.doFinal(hash, 0);
-
- byte[] sig;
- byte[] expected;
-
- try
- {
- sig = rsaEngine.processBlock(signature, 0, signature.length);
- expected = derEncode(hash);
- }
- catch (Exception e)
- {
- return false;
- }
-
- if (sig.length == expected.length)
- {
- return Arrays.constantTimeAreEqual(sig, expected);
- }
- else if (sig.length == expected.length - 2) // NULL left out
- {
- int sigOffset = sig.length - hash.length - 2;
- int expectedOffset = expected.length - hash.length - 2;
-
- expected[1] -= 2; // adjust lengths
- expected[3] -= 2;
-
- int nonEqual = 0;
-
- for (int i = 0; i < hash.length; i++)
- {
- nonEqual |= (sig[sigOffset + i] ^ expected[expectedOffset + i]);
- }
-
- for (int i = 0; i < sigOffset; i++)
- {
- nonEqual |= (sig[i] ^ expected[i]); // check header less NULL
- }
-
- return nonEqual == 0;
- }
- else
- {
- return false;
- }
- }
-
- public void reset()
- {
- digest.reset();
- }
-
- private byte[] derEncode(
- byte[] hash)
- throws IOException
- {
- DigestInfo dInfo = new DigestInfo(algId, hash);
-
- return dInfo.getEncoded(ASN1Encoding.DER);
- }
-}
diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/AbstractTlsContext.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/AbstractTlsContext.java
deleted file mode 100644
index b8153b06..00000000
--- a/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/AbstractTlsContext.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.prng.DigestRandomGenerator;
-import org.bouncycastle.crypto.prng.RandomGenerator;
-import org.bouncycastle.util.Times;
-
-abstract class AbstractTlsContext
- implements TlsContext
-{
- private static long counter = Times.nanoTime();
-
- private synchronized static long nextCounterValue()
- {
- return ++counter;
- }
-
- private RandomGenerator nonceRandom;
- 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)
- {
- secureRandom.setSeed(nextCounterValue());
- secureRandom.setSeed(Times.nanoTime());
-
- this.nonceRandom = new DigestRandomGenerator(TlsUtils.createHash(HashAlgorithm.sha256));
- byte[] nonceSeed = new byte[32];
- secureRandom.nextBytes(nonceSeed);
- this.nonceRandom.addSeedMaterial(nonceSeed);
-
- this.secureRandom = secureRandom;
- this.securityParameters = securityParameters;
- }
-
- public RandomGenerator getNonceRandomGenerator()
- {
- return nonceRandom;
- }
-
- public SecureRandom getSecureRandom()
- {
- return secureRandom;
- }
-
- public SecurityParameters getSecurityParameters()
- {
- return securityParameters;
- }
-
- public ProtocolVersion getClientVersion()
- {
- return clientVersion;
- }
-
- void setClientVersion(ProtocolVersion clientVersion)
- {
- this.clientVersion = clientVersion;
- }
-
- public ProtocolVersion getServerVersion()
- {
- return 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;
- }
-
- public void setUserObject(Object userObject)
- {
- this.userObject = userObject;
- }
-
- 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();
-
- int seedLength = cr.length + sr.length;
- if (context_value != null)
- {
- seedLength += (2 + context_value.length);
- }
-
- byte[] seed = new byte[seedLength];
- int seedPos = 0;
-
- System.arraycopy(cr, 0, seed, seedPos, cr.length);
- seedPos += cr.length;
- System.arraycopy(sr, 0, seed, seedPos, sr.length);
- seedPos += sr.length;
- if (context_value != null)
- {
- TlsUtils.writeUint16(context_value.length, seed, seedPos);
- seedPos += 2;
- System.arraycopy(context_value, 0, seed, seedPos, context_value.length);
- seedPos += context_value.length;
- }
-
- if (seedPos != seedLength)
- {
- throw new IllegalStateException("error in calculation of seed for export");
- }
-
- return TlsUtils.PRF(this, sp.getMasterSecret(), asciiLabel, seed, length);
- }
-}
diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/DTLSReassembler.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/DTLSReassembler.java
deleted file mode 100644
index 2d3cf267..00000000
--- a/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/DTLSReassembler.java
+++ /dev/null
@@ -1,136 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.util.Vector;
-
-class DTLSReassembler
-{
-
- private short msg_type;
- private byte[] body;
-
- private Vector missing = new Vector();
-
- DTLSReassembler(short msg_type, int length)
- {
- this.msg_type = msg_type;
- this.body = new byte[length];
- this.missing.addElement(new Range(0, length));
- }
-
- short getType()
- {
- return msg_type;
- }
-
- byte[] getBodyIfComplete()
- {
- return missing.isEmpty() ? body : null;
- }
-
- void contributeFragment(short msg_type, int length, byte[] buf, int off, int fragment_offset,
- int fragment_length)
- {
-
- int fragment_end = fragment_offset + fragment_length;
-
- if (this.msg_type != msg_type || this.body.length != length || fragment_end > length)
- {
- return;
- }
-
- if (fragment_length == 0)
- {
- // NOTE: Empty messages still require an empty fragment to complete it
- if (fragment_offset == 0 && !missing.isEmpty())
- {
- Range firstRange = (Range)missing.firstElement();
- if (firstRange.getEnd() == 0)
- {
- missing.removeElementAt(0);
- }
- }
- return;
- }
-
- for (int i = 0; i < missing.size(); ++i)
- {
- Range range = (Range)missing.elementAt(i);
- if (range.getStart() >= fragment_end)
- {
- break;
- }
- if (range.getEnd() > fragment_offset)
- {
-
- int copyStart = Math.max(range.getStart(), fragment_offset);
- int copyEnd = Math.min(range.getEnd(), fragment_end);
- int copyLength = copyEnd - copyStart;
-
- System.arraycopy(buf, off + copyStart - fragment_offset, body, copyStart,
- copyLength);
-
- if (copyStart == range.getStart())
- {
- if (copyEnd == range.getEnd())
- {
- missing.removeElementAt(i--);
- }
- else
- {
- range.setStart(copyEnd);
- }
- }
- else
- {
- if (copyEnd == range.getEnd())
- {
- range.setEnd(copyStart);
- }
- else
- {
- missing.insertElementAt(new Range(copyEnd, range.getEnd()), ++i);
- range.setEnd(copyStart);
- }
- }
- }
- }
- }
-
- void reset()
- {
- this.missing.removeAllElements();
- this.missing.addElement(new Range(0, body.length));
- }
-
- private static class Range
- {
-
- private int start, end;
-
- Range(int start, int end)
- {
- this.start = start;
- this.end = end;
- }
-
- public int getStart()
- {
- return start;
- }
-
- public void setStart(int start)
- {
- this.start = start;
- }
-
- public int getEnd()
- {
- return end;
- }
-
- public void setEnd(int end)
- {
- this.end = end;
- }
- }
-}
diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/DTLSReliableHandshake.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/DTLSReliableHandshake.java
deleted file mode 100644
index af694ac9..00000000
--- a/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/DTLSReliableHandshake.java
+++ /dev/null
@@ -1,457 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.util.Integers;
-
-class DTLSReliableHandshake
-{
- private final static int MAX_RECEIVE_AHEAD = 10;
-
- private DTLSRecordLayer recordLayer;
-
- private TlsHandshakeHash handshakeHash;
-
- private Hashtable currentInboundFlight = new Hashtable();
- private Hashtable previousInboundFlight = null;
- private Vector outboundFlight = new Vector();
- private boolean sending = true;
-
- private int message_seq = 0, next_receive_seq = 0;
-
- DTLSReliableHandshake(TlsContext context, DTLSRecordLayer transport)
- {
- this.recordLayer = transport;
- this.handshakeHash = new DeferredHash();
- this.handshakeHash.init(context);
- }
-
- void notifyHelloComplete()
- {
- this.handshakeHash = handshakeHash.notifyPRFDetermined();
- }
-
- TlsHandshakeHash getHandshakeHash()
- {
- return handshakeHash;
- }
-
- TlsHandshakeHash prepareToFinish()
- {
- TlsHandshakeHash result = handshakeHash;
- this.handshakeHash = handshakeHash.stopTracking();
- return result;
- }
-
- void sendMessage(short msg_type, byte[] body)
- throws IOException
- {
- TlsUtils.checkUint24(body.length);
-
- if (!sending)
- {
- checkInboundFlight();
- sending = true;
- outboundFlight.removeAllElements();
- }
-
- Message message = new Message(message_seq++, msg_type, body);
-
- outboundFlight.addElement(message);
-
- writeMessage(message);
- updateHandshakeMessagesDigest(message);
- }
-
- 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;
- prepareInboundFlight();
- }
-
- // Check if we already have the next message waiting
- {
- DTLSReassembler next = (DTLSReassembler)currentInboundFlight.get(Integers.valueOf(next_receive_seq));
- if (next != null)
- {
- byte[] body = next.getBodyIfComplete();
- if (body != null)
- {
- previousInboundFlight = null;
- return updateHandshakeMessagesDigest(new Message(next_receive_seq++, next.getType(), body));
- }
- }
- }
-
- byte[] buf = null;
-
- // TODO Check the conditions under which we should reset this
- int readTimeoutMillis = 1000;
-
- for (; ; )
- {
- int receiveLimit = recordLayer.getReceiveLimit();
- if (buf == null || buf.length < receiveLimit)
- {
- buf = new byte[receiveLimit];
- }
-
- // TODO Handle records containing multiple handshake messages
-
- try
- {
- for (; ; )
- {
- int received = recordLayer.receive(buf, 0, receiveLimit, readTimeoutMillis);
- if (received < 0)
- {
- break;
- }
- if (received < 12)
- {
- continue;
- }
- int fragment_length = TlsUtils.readUint24(buf, 9);
- if (received != (fragment_length + 12))
- {
- continue;
- }
- int seq = TlsUtils.readUint16(buf, 4);
- if (seq > (next_receive_seq + MAX_RECEIVE_AHEAD))
- {
- continue;
- }
- short msg_type = TlsUtils.readUint8(buf, 0);
- int length = TlsUtils.readUint24(buf, 1);
- int fragment_offset = TlsUtils.readUint24(buf, 6);
- if (fragment_offset + fragment_length > length)
- {
- continue;
- }
-
- if (seq < next_receive_seq)
- {
- /*
- * NOTE: If we receive the previous flight of incoming messages in full
- * again, retransmit our last flight
- */
- if (previousInboundFlight != null)
- {
- DTLSReassembler reassembler = (DTLSReassembler)previousInboundFlight.get(Integers
- .valueOf(seq));
- if (reassembler != null)
- {
-
- reassembler.contributeFragment(msg_type, length, buf, 12, fragment_offset,
- fragment_length);
-
- if (checkAll(previousInboundFlight))
- {
-
- resendOutboundFlight();
-
- /*
- * TODO[DTLS] implementations SHOULD back off handshake packet
- * size during the retransmit backoff.
- */
- readTimeoutMillis = Math.min(readTimeoutMillis * 2, 60000);
-
- resetAll(previousInboundFlight);
- }
- }
- }
- }
- else
- {
-
- DTLSReassembler reassembler = (DTLSReassembler)currentInboundFlight.get(Integers.valueOf(seq));
- if (reassembler == null)
- {
- reassembler = new DTLSReassembler(msg_type, length);
- currentInboundFlight.put(Integers.valueOf(seq), reassembler);
- }
-
- reassembler.contributeFragment(msg_type, length, buf, 12, fragment_offset, fragment_length);
-
- if (seq == next_receive_seq)
- {
- byte[] body = reassembler.getBodyIfComplete();
- if (body != null)
- {
- previousInboundFlight = null;
- return updateHandshakeMessagesDigest(new Message(next_receive_seq++,
- reassembler.getType(), body));
- }
- }
- }
- }
- }
- catch (IOException e)
- {
- // NOTE: Assume this is a timeout for the moment
- }
-
- resendOutboundFlight();
-
- /*
- * TODO[DTLS] implementations SHOULD back off handshake packet size during the
- * retransmit backoff.
- */
- readTimeoutMillis = Math.min(readTimeoutMillis * 2, 60000);
- }
- }
-
- void finish()
- {
- DTLSHandshakeRetransmit retransmit = null;
- if (!sending)
- {
- checkInboundFlight();
- }
- else if (currentInboundFlight != null)
- {
- /*
- * RFC 6347 4.2.4. In addition, for at least twice the default MSL defined for [TCP],
- * when in the FINISHED state, the node that transmits the last flight (the server in an
- * ordinary handshake or the client in a resumed handshake) MUST respond to a retransmit
- * of the peer's last flight with a retransmit of the last flight.
- */
- retransmit = new DTLSHandshakeRetransmit()
- {
- public void receivedHandshakeRecord(int epoch, byte[] buf, int off, int len)
- throws IOException
- {
- /*
- * TODO Need to handle the case where the previous inbound flight contains
- * messages from two epochs.
- */
- if (len < 12)
- {
- return;
- }
- int fragment_length = TlsUtils.readUint24(buf, off + 9);
- if (len != (fragment_length + 12))
- {
- return;
- }
- int seq = TlsUtils.readUint16(buf, off + 4);
- if (seq >= next_receive_seq)
- {
- return;
- }
-
- short msg_type = TlsUtils.readUint8(buf, off);
-
- // TODO This is a hack that only works until we try to support renegotiation
- int expectedEpoch = msg_type == HandshakeType.finished ? 1 : 0;
- if (epoch != expectedEpoch)
- {
- return;
- }
-
- int length = TlsUtils.readUint24(buf, off + 1);
- int fragment_offset = TlsUtils.readUint24(buf, off + 6);
- if (fragment_offset + fragment_length > length)
- {
- return;
- }
-
- DTLSReassembler reassembler = (DTLSReassembler)currentInboundFlight.get(Integers.valueOf(seq));
- if (reassembler != null)
- {
- reassembler.contributeFragment(msg_type, length, buf, off + 12, fragment_offset,
- fragment_length);
- if (checkAll(currentInboundFlight))
- {
- resendOutboundFlight();
- resetAll(currentInboundFlight);
- }
- }
- }
- };
- }
-
- recordLayer.handshakeSuccessful(retransmit);
- }
-
- void resetHandshakeMessagesDigest()
- {
- handshakeHash.reset();
- }
-
- /**
- * Check that there are no "extra" messages left in the current inbound flight
- */
- private void checkInboundFlight()
- {
- Enumeration e = currentInboundFlight.keys();
- while (e.hasMoreElements())
- {
- Integer key = (Integer)e.nextElement();
- if (key.intValue() >= next_receive_seq)
- {
- // TODO Should this be considered an error?
- }
- }
- }
-
- private void prepareInboundFlight()
- {
- resetAll(currentInboundFlight);
- previousInboundFlight = currentInboundFlight;
- currentInboundFlight = new Hashtable();
- }
-
- private void resendOutboundFlight()
- throws IOException
- {
- recordLayer.resetWriteEpoch();
- for (int i = 0; i < outboundFlight.size(); ++i)
- {
- writeMessage((Message)outboundFlight.elementAt(i));
- }
- }
-
- private Message updateHandshakeMessagesDigest(Message message)
- throws IOException
- {
- if (message.getType() != HandshakeType.hello_request)
- {
- byte[] body = message.getBody();
- byte[] buf = new byte[12];
- TlsUtils.writeUint8(message.getType(), buf, 0);
- TlsUtils.writeUint24(body.length, buf, 1);
- TlsUtils.writeUint16(message.getSeq(), buf, 4);
- TlsUtils.writeUint24(0, buf, 6);
- TlsUtils.writeUint24(body.length, buf, 9);
- handshakeHash.update(buf, 0, buf.length);
- handshakeHash.update(body, 0, body.length);
- }
- return message;
- }
-
- private void writeMessage(Message message)
- throws IOException
- {
- int sendLimit = recordLayer.getSendLimit();
- int fragmentLimit = sendLimit - 12;
-
- // TODO Support a higher minimum fragment size?
- if (fragmentLimit < 1)
- {
- // TODO Should we be throwing an exception here?
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- int length = message.getBody().length;
-
- // NOTE: Must still send a fragment if body is empty
- int fragment_offset = 0;
- do
- {
- int fragment_length = Math.min(length - fragment_offset, fragmentLimit);
- writeHandshakeFragment(message, fragment_offset, fragment_length);
- fragment_offset += fragment_length;
- }
- while (fragment_offset < length);
- }
-
- private void writeHandshakeFragment(Message message, int fragment_offset, int fragment_length)
- throws IOException
- {
- 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)
- {
- Enumeration e = inboundFlight.elements();
- while (e.hasMoreElements())
- {
- if (((DTLSReassembler)e.nextElement()).getBodyIfComplete() == null)
- {
- return false;
- }
- }
- return true;
- }
-
- private static void resetAll(Hashtable inboundFlight)
- {
- Enumeration e = inboundFlight.elements();
- while (e.hasMoreElements())
- {
- ((DTLSReassembler)e.nextElement()).reset();
- }
- }
-
- static class Message
- {
- private final int message_seq;
- private final short msg_type;
- private final byte[] body;
-
- private Message(int message_seq, short msg_type, byte[] body)
- {
- this.message_seq = message_seq;
- this.msg_type = msg_type;
- this.body = body;
- }
-
- public int getSeq()
- {
- return message_seq;
- }
-
- public short getType()
- {
- return msg_type;
- }
-
- public byte[] getBody()
- {
- 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/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/UDPTransport.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/UDPTransport.java
deleted file mode 100644
index f6c96b92..00000000
--- a/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/UDPTransport.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-import java.net.DatagramPacket;
-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;
-
- protected final DatagramSocket socket;
- protected final int receiveLimit, sendLimit;
-
- public UDPTransport(DatagramSocket socket, int mtu)
- throws IOException
- {
- //
- // In 1.3 and earlier sockets were bound and connected during creation
- //
- //if (!socket.isBound() || !socket.isConnected())
- //{
- // throw new IllegalArgumentException("'socket' must be bound and connected");
- //}
-
- this.socket = socket;
-
- // NOTE: As of JDK 1.6, can use NetworkInterface.getMTU
-
- this.receiveLimit = mtu - MIN_IP_OVERHEAD - UDP_OVERHEAD;
- this.sendLimit = mtu - MAX_IP_OVERHEAD - UDP_OVERHEAD;
- }
-
- public int getReceiveLimit()
- {
- return receiveLimit;
- }
-
- public int getSendLimit()
- {
- // TODO[DTLS] Implement Path-MTU discovery?
- return sendLimit;
- }
-
- public int receive(byte[] buf, int off, int len, int waitMillis)
- throws IOException
- {
- socket.setSoTimeout(waitMillis);
-
- if (off == 0)
- {
- DatagramPacket packet = new DatagramPacket(buf, len);
- socket.receive(packet);
-
- return packet.getLength();
- }
- else
- {
- byte[] rv = new byte[len];
-
- DatagramPacket packet = new DatagramPacket(rv, len);
- socket.receive(packet);
-
- System.arraycopy(rv, 0, buf, off, packet.getLength());
-
- return packet.getLength();
- }
- }
-
- public void send(byte[] buf, int off, int len)
- throws IOException
- {
- if (len > getSendLimit())
- {
- /*
- * RFC 4347 4.1.1. "If the application attempts to send a record larger than the MTU,
- * the DTLS implementation SHOULD generate an error, thus avoiding sending a packet
- * which will be fragmented."
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- if (off == 0)
- {
- DatagramPacket packet = new DatagramPacket(buf, len);
- socket.send(packet);
- }
- else
- {
- byte[] data = new byte[len];
-
- System.arraycopy(buf, off, data, 0, len);
-
- DatagramPacket packet = new DatagramPacket(data, len);
- socket.send(packet);
- }
- }
-
- public void close()
- throws IOException
- {
- socket.close();
- }
-}
diff --git a/core/src/main/jdk1.1/org/bouncycastle/i18n/LocalizedMessage.java b/core/src/main/jdk1.1/org/bouncycastle/i18n/LocalizedMessage.java
deleted file mode 100644
index c1c4c58a..00000000
--- a/core/src/main/jdk1.1/org/bouncycastle/i18n/LocalizedMessage.java
+++ /dev/null
@@ -1,464 +0,0 @@
-package org.bouncycastle.i18n;
-
-import org.bouncycastle.i18n.filter.Filter;
-import org.bouncycastle.i18n.filter.TrustedInput;
-import org.bouncycastle.i18n.filter.UntrustedInput;
-import org.bouncycastle.i18n.filter.UntrustedUrlInput;
-
-import java.io.UnsupportedEncodingException;
-import java.text.DateFormat;
-import java.text.Format;
-import java.text.MessageFormat;
-import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-import java.util.TimeZone;
-
-public class LocalizedMessage
-{
- protected static final int NO_FILTER = 0;
- protected static final int FILTER = 1;
- protected static final int FILTER_URL = 2;
-
- protected String id;
- protected String resource;
-
- // ISO-8859-1 is the default encoding
- public static final String DEFAULT_ENCODING = "ISO-8859-1";
- protected String encoding = DEFAULT_ENCODING;
-
- protected FilteredArguments arguments;
- protected FilteredArguments extraArgs = null;
-
- protected Filter filter = null;
-
- protected ClassLoader loader = null;
-
- /**
- * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- */
- public LocalizedMessage(String resource,String id) throws NullPointerException
- {
- if (resource == null || id == null)
- {
- throw new NullPointerException();
- }
- this.id = id;
- this.resource = resource;
- arguments = new FilteredArguments();
- }
-
- /**
- * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @param encoding the encoding of the resource file
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- * @throws UnsupportedEncodingException if the encoding is not supported
- */
- public LocalizedMessage(String resource,String id, String encoding) throws NullPointerException, UnsupportedEncodingException
- {
- if (resource == null || id == null)
- {
- throw new NullPointerException();
- }
- this.id = id;
- this.resource = resource;
- arguments = new FilteredArguments();
- this.encoding = encoding;
- }
-
- /**
- * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @param arguments an array containing the arguments for the message
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- */
- public LocalizedMessage(String resource, String id, Object[] arguments) throws NullPointerException
- {
- if (resource == null || id == null || arguments == null)
- {
- throw new NullPointerException();
- }
- this.id = id;
- this.resource = resource;
- this.arguments = new FilteredArguments(arguments);
- }
-
- /**
- * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @param encoding the encoding of the resource file
- * @param arguments an array containing the arguments for the message
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- * @throws UnsupportedEncodingException if the encoding is not supported
- */
- public LocalizedMessage(String resource, String id, String encoding, Object[] arguments) throws NullPointerException, UnsupportedEncodingException
- {
- if (resource == null || id == null || arguments == null)
- {
- throw new NullPointerException();
- }
- this.id = id;
- this.resource = resource;
- this.arguments = new FilteredArguments(arguments);
- this.encoding = encoding;
- }
-
- /**
- * Reads the entry <code>id + "." + key</code> from the resource file and returns a
- * formated message for the given Locale and TimeZone.
- * @param key second part of the entry id
- * @param loc the used {@link Locale}
- * @param timezone the used {@link TimeZone}
- * @return a Strng containing the localized message
- * @throws MissingEntryException if the resource file is not available or the entry does not exist.
- */
- public String getEntry(String key,Locale loc, TimeZone timezone) throws MissingEntryException
- {
- String entry = id;
- if (key != null)
- {
- entry += "." + key;
- }
-
- try
- {
- ResourceBundle bundle;
- if (loader == null)
- {
- bundle = ResourceBundle.getBundle(resource,loc);
- }
- else
- {
- bundle = ResourceBundle.getBundle(resource, loc);
- }
- String result = bundle.getString(entry);
- if (!encoding.equals(DEFAULT_ENCODING))
- {
- result = new String(result.getBytes(DEFAULT_ENCODING), encoding);
- }
- if (!arguments.isEmpty())
- {
- result = formatWithTimeZone(result,arguments.getFilteredArgs(loc),loc,timezone);
- }
- result = addExtraArgs(result, loc);
- return result;
- }
- catch (MissingResourceException mre)
- {
- throw new MissingEntryException("Can't find entry " + entry + " in resource file " + resource + ".",
- resource,
- entry,
- loc,
- loader != null ? loader : this.getClassLoader());
- }
- catch (UnsupportedEncodingException use)
- {
- // should never occur - cause we already test this in the constructor
- throw new RuntimeException(use.toString());
- }
- }
-
- protected String formatWithTimeZone(
- String template,
- Object[] arguments,
- Locale locale,
- TimeZone timezone)
- {
- MessageFormat mf = new MessageFormat(" ");
- mf.setLocale(locale);
- mf.applyPattern(template);
- if (!timezone.equals(TimeZone.getDefault()))
- {
- Format[] formats = mf.getFormats();
- for (int i = 0; i < formats.length; i++)
- {
- if (formats[i] instanceof DateFormat)
- {
- DateFormat temp = (DateFormat) formats[i];
- temp.setTimeZone(timezone);
- mf.setFormat(i,temp);
- }
- }
- }
- return mf.format(arguments);
- }
-
- protected String addExtraArgs(String msg, Locale locale)
- {
- if (extraArgs != null)
- {
- StringBuffer sb = new StringBuffer(msg);
- Object[] filteredArgs = extraArgs.getFilteredArgs(locale);
- for (int i = 0; i < filteredArgs.length; i++)
- {
- sb.append(filteredArgs[i]);
- }
- msg = sb.toString();
- }
- return msg;
- }
-
- /**
- * Sets the {@link Filter} that is used to filter the arguments of this message
- * @param filter the {@link Filter} to use. <code>null</code> to disable filtering.
- */
- public void setFilter(Filter filter)
- {
- arguments.setFilter(filter);
- if (extraArgs != null)
- {
- extraArgs.setFilter(filter);
- }
- this.filter = filter;
- }
-
- /**
- * Returns the current filter.
- * @return the current filter
- */
- public Filter getFilter()
- {
- return filter;
- }
-
- /**
- * Set the {@link ClassLoader} which loads the resource files. If it is set to <code>null</code>
- * then the default {@link ClassLoader} is used.
- * @param loader the {@link ClassLoader} which loads the resource files
- */
- public void setClassLoader(ClassLoader loader)
- {
- this.loader = loader;
- }
-
- /**
- * Returns the {@link ClassLoader} which loads the resource files or <code>null</code>
- * if the default ClassLoader is used.
- * @return the {@link ClassLoader} which loads the resource files
- */
- public ClassLoader getClassLoader()
- {
- return loader;
- }
-
- /**
- * Returns the id of the message in the resource bundle.
- * @return the id of the message
- */
- public String getId()
- {
- return id;
- }
-
- /**
- * Returns the name of the resource bundle for this message
- * @return name of the resource file
- */
- public String getResource()
- {
- return resource;
- }
-
- /**
- * Returns an <code>Object[]</code> containing the message arguments.
- * @return the message arguments
- */
- public Object[] getArguments()
- {
- return arguments.getArguments();
- }
-
- /**
- *
- * @param extraArg
- */
- public void setExtraArgument(Object extraArg)
- {
- setExtraArguments(new Object[] {extraArg});
- }
-
- /**
- *
- * @param extraArgs
- */
- public void setExtraArguments(Object[] extraArgs)
- {
- if (extraArgs != null)
- {
- this.extraArgs = new FilteredArguments(extraArgs);
- this.extraArgs.setFilter(filter);
- }
- else
- {
- this.extraArgs = null;
- }
- }
-
- /**
- *
- * @return
- */
- public Object[] getExtraArgs()
- {
- return (extraArgs == null) ? null : extraArgs.getArguments();
- }
-
- protected class FilteredArguments
- {
-
- protected Filter filter = null;
-
- protected boolean[] isLocaleSpecific;
- protected int[] argFilterType;
- protected Object[] arguments;
- protected Object[] unpackedArgs;
- protected Object[] filteredArgs;
-
- FilteredArguments()
- {
- this(new Object[0]);
- }
-
- FilteredArguments(Object[] args)
- {
- this.arguments = args;
- this.unpackedArgs = new Object[args.length];
- this.filteredArgs = new Object[args.length];
- this.isLocaleSpecific = new boolean[args.length];
- this.argFilterType = new int[args.length];
- for (int i = 0; i < args.length; i++)
- {
- if (args[i] instanceof TrustedInput)
- {
- this.unpackedArgs[i] = ((TrustedInput) args[i]).getInput();
- argFilterType[i] = NO_FILTER;
- }
- else if (args[i] instanceof UntrustedInput)
- {
- this.unpackedArgs[i] = ((UntrustedInput) args[i]).getInput();
- if (args[i] instanceof UntrustedUrlInput)
- {
- argFilterType[i] = FILTER_URL;
- }
- else
- {
- argFilterType[i] = FILTER;
- }
- }
- else
- {
- this.unpackedArgs[i] = args[i];
- argFilterType[i] = FILTER;
- }
-
- // locale specific
- this.isLocaleSpecific[i] = (this.unpackedArgs[i] instanceof LocaleString);
- }
- }
-
- public boolean isEmpty()
- {
- return unpackedArgs.length == 0;
- }
-
- public Object[] getArguments()
- {
- return arguments;
- }
-
- public Object[] getFilteredArgs(Locale locale)
- {
- Object[] result = new Object[unpackedArgs.length];
- for (int i = 0; i < unpackedArgs.length; i++)
- {
- Object arg;
- if (filteredArgs[i] != null)
- {
- arg = filteredArgs[i];
- }
- else
- {
- arg = unpackedArgs[i];
- if (isLocaleSpecific[i])
- {
- // get locale
- arg = ((LocaleString) arg).getLocaleString(locale);
- arg = filter(argFilterType[i], arg);
- }
- else
- {
- arg = filter(argFilterType[i], arg);
- filteredArgs[i] = arg;
- }
- }
- result[i] = arg;
- }
- return result;
- }
-
- private Object filter(int type, Object obj)
- {
- if (filter != null)
- {
- Object o = (null == obj) ? "null" : obj;
- switch (type)
- {
- case NO_FILTER:
- return o;
- case FILTER:
- return filter.doFilter(o.toString());
- case FILTER_URL:
- return filter.doFilterUrl(o.toString());
- default:
- return null;
- }
- }
- else
- {
- return obj;
- }
- }
-
- public Filter getFilter()
- {
- return filter;
- }
-
- public void setFilter(Filter filter)
- {
- if (filter != this.filter)
- {
- for (int i = 0; i < unpackedArgs.length; i++)
- {
- filteredArgs[i] = null;
- }
- }
- this.filter = filter;
- }
-
- }
-
- public String toString()
- {
- StringBuffer sb = new StringBuffer();
- sb.append("Resource: \"").append(resource);
- sb.append("\" Id: \"").append(id).append("\"");
- sb.append(" Arguments: ").append(arguments.getArguments().length).append(" normal, ")
- .append(extraArgs.getArguments().length).append(" extra");
- sb.append(" Encoding: ").append(encoding);
- sb.append(" ClassLoader: ").append(loader);
- return sb.toString();
- }
-
-}
diff --git a/core/src/main/jdk1.1/org/bouncycastle/i18n/MissingEntryException.java b/core/src/main/jdk1.1/org/bouncycastle/i18n/MissingEntryException.java
deleted file mode 100644
index 1400338f..00000000
--- a/core/src/main/jdk1.1/org/bouncycastle/i18n/MissingEntryException.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package org.bouncycastle.i18n;
-
-import java.net.URL;
-import java.util.Locale;
-
-public class MissingEntryException extends RuntimeException
-{
-
- protected final String resource;
- protected final String key;
- protected final ClassLoader loader;
- protected final Locale locale;
-
- private String debugMsg;
-
- public MissingEntryException(String message, String resource, String key, Locale locale, ClassLoader loader)
- {
- super(message);
- this.resource = resource;
- this.key = key;
- this.locale = locale;
- this.loader = loader;
- }
-
- public MissingEntryException(String message, Throwable cause, String resource, String key, Locale locale, ClassLoader loader)
- {
- super(message + ": " + cause);
- this.resource = resource;
- this.key = key;
- this.locale = locale;
- this.loader = loader;
- }
-
- public String getKey()
- {
- return key;
- }
-
- public String getResource()
- {
- return resource;
- }
-
- public ClassLoader getClassLoader()
- {
- return loader;
- }
-
- public Locale getLocale()
- {
- return locale;
- }
-
- public String getDebugMsg()
- {
- if (debugMsg == null)
- {
- debugMsg = "Can not find entry " + key + " in resource file " + resource + " for the locale " + locale + ".";
- }
- return debugMsg;
- }
-
-}
diff --git a/core/src/main/jdk1.1/org/spongycastle/asn1/ASN1InputStream.java b/core/src/main/jdk1.1/org/spongycastle/asn1/ASN1InputStream.java
new file mode 100644
index 00000000..8c6571de
--- /dev/null
+++ b/core/src/main/jdk1.1/org/spongycastle/asn1/ASN1InputStream.java
@@ -0,0 +1,466 @@
+package org.spongycastle.asn1;
+
+import java.io.ByteArrayInputStream;
+import java.io.EOFException;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.spongycastle.util.io.Streams;
+
+/**
+ * a general purpose ASN.1 decoder - note: this class differs from the
+ * others in that it returns null after it has read the last object in
+ * the stream. If an ASN.1 NULL is encountered a DER/BER Null object is
+ * returned.
+ */
+public class ASN1InputStream
+ extends FilterInputStream
+ implements BERTags
+{
+ private int limit;
+ private boolean lazyEvaluate;
+
+ private byte[][] tmpBuffers;
+
+ public ASN1InputStream(
+ InputStream is)
+ {
+ this(is, StreamUtil.findLimit(is));
+ }
+
+ /**
+ * Create an ASN1InputStream based on the input byte array. The length of DER objects in
+ * the stream is automatically limited to the length of the input array.
+ *
+ * @param input array containing ASN.1 encoded data.
+ */
+ public ASN1InputStream(
+ byte[] input)
+ {
+ this(new ByteArrayInputStream(input), input.length);
+ }
+
+ /**
+ * Create an ASN1InputStream based on the input byte array. The length of DER objects in
+ * the stream is automatically limited to the length of the input array.
+ *
+ * @param input array containing ASN.1 encoded data.
+ * @param lazyEvaluate true if parsing inside constructed objects can be delayed.
+ */
+ public ASN1InputStream(
+ byte[] input,
+ boolean lazyEvaluate)
+ {
+ this(new ByteArrayInputStream(input), input.length, lazyEvaluate);
+ }
+
+ /**
+ * Create an ASN1InputStream where no DER object will be longer than limit.
+ *
+ * @param input stream containing ASN.1 encoded data.
+ * @param limit maximum size of a DER encoded object.
+ */
+ public ASN1InputStream(
+ InputStream input,
+ int limit)
+ {
+ this(input, limit, false);
+ }
+
+ /**
+ * Create an ASN1InputStream where no DER object will be longer than limit, and constructed
+ * objects such as sequences will be parsed lazily.
+ *
+ * @param input stream containing ASN.1 encoded data.
+ * @param lazyEvaluate true if parsing inside constructed objects can be delayed.
+ */
+ public ASN1InputStream(
+ InputStream input,
+ boolean lazyEvaluate)
+ {
+ this(input, StreamUtil.findLimit(input), lazyEvaluate);
+ }
+
+ /**
+ * Create an ASN1InputStream where no DER object will be longer than limit, and constructed
+ * objects such as sequences will be parsed lazily.
+ *
+ * @param input stream containing ASN.1 encoded data.
+ * @param limit maximum size of a DER encoded object.
+ * @param lazyEvaluate true if parsing inside constructed objects can be delayed.
+ */
+ public ASN1InputStream(
+ InputStream input,
+ int limit,
+ boolean lazyEvaluate)
+ {
+ super(input);
+ this.limit = limit;
+ this.lazyEvaluate = lazyEvaluate;
+ this.tmpBuffers = new byte[11][];
+ }
+
+ int getLimit()
+ {
+ return limit;
+ }
+
+ protected int readLength()
+ throws IOException
+ {
+ return readLength(this, limit);
+ }
+
+ protected void readFully(
+ byte[] bytes)
+ throws IOException
+ {
+ if (Streams.readFully(this, bytes) != bytes.length)
+ {
+ throw new EOFException("EOF encountered in middle of object");
+ }
+ }
+
+ /**
+ * build an object given its tag and the number of bytes to construct it from.
+ */
+ protected ASN1Primitive buildObject(
+ int tag,
+ int tagNo,
+ int length)
+ throws IOException
+ {
+ boolean isConstructed = (tag & CONSTRUCTED) != 0;
+
+ DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this, length);
+
+ if ((tag & APPLICATION) != 0)
+ {
+ return new DERApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
+ }
+
+ if ((tag & TAGGED) != 0)
+ {
+ return new ASN1StreamParser(defIn).readTaggedObject(isConstructed, tagNo);
+ }
+
+ if (isConstructed)
+ {
+ // TODO There are other tags that may be constructed (e.g. BIT_STRING)
+ switch (tagNo)
+ {
+ case OCTET_STRING:
+ //
+ // yes, people actually do this...
+ //
+ ASN1EncodableVector v = buildDEREncodableVector(defIn);
+ ASN1OctetString[] strings = new ASN1OctetString[v.size()];
+
+ for (int i = 0; i != strings.length; i++)
+ {
+ strings[i] = (ASN1OctetString)v.get(i);
+ }
+
+ return new BEROctetString(strings);
+ case SEQUENCE:
+ if (lazyEvaluate)
+ {
+ return new LazyEncodedSequence(defIn.toByteArray());
+ }
+ else
+ {
+ return DERFactory.createSequence(buildDEREncodableVector(defIn));
+ }
+ case SET:
+ return DERFactory.createSet(buildDEREncodableVector(defIn));
+ case EXTERNAL:
+ return new DERExternal(buildDEREncodableVector(defIn));
+ default:
+ throw new IOException("unknown tag " + tagNo + " encountered");
+ }
+ }
+
+ return createPrimitiveDERObject(tagNo, defIn, tmpBuffers);
+ }
+
+ ASN1EncodableVector buildEncodableVector()
+ throws IOException
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ ASN1Primitive o;
+
+ while ((o = readObject()) != null)
+ {
+ v.add(o);
+ }
+
+ return v;
+ }
+
+ ASN1EncodableVector buildDEREncodableVector(
+ DefiniteLengthInputStream dIn) throws IOException
+ {
+ return new ASN1InputStream(dIn).buildEncodableVector();
+ }
+
+ public ASN1Primitive readObject()
+ throws IOException
+ {
+ int tag = read();
+ if (tag <= 0)
+ {
+ if (tag == 0)
+ {
+ throw new IOException("unexpected end-of-contents marker");
+ }
+
+ return null;
+ }
+
+ //
+ // calculate tag number
+ //
+ int tagNo = readTagNumber(this, tag);
+
+ boolean isConstructed = (tag & CONSTRUCTED) != 0;
+
+ //
+ // calculate length
+ //
+ int length = readLength();
+
+ if (length < 0) // indefinite length method
+ {
+ if (!isConstructed)
+ {
+ throw new IOException("indefinite length primitive encoding encountered");
+ }
+
+ IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this, limit);
+ ASN1StreamParser sp = new ASN1StreamParser(indIn, limit);
+
+ if ((tag & APPLICATION) != 0)
+ {
+ return new BERApplicationSpecificParser(tagNo, sp).getLoadedObject();
+ }
+
+ if ((tag & TAGGED) != 0)
+ {
+ return new BERTaggedObjectParser(true, tagNo, sp).getLoadedObject();
+ }
+
+ // TODO There are other tags that may be constructed (e.g. BIT_STRING)
+ switch (tagNo)
+ {
+ case OCTET_STRING:
+ return new BEROctetStringParser(sp).getLoadedObject();
+ case SEQUENCE:
+ return new BERSequenceParser(sp).getLoadedObject();
+ case SET:
+ return new BERSetParser(sp).getLoadedObject();
+ case EXTERNAL:
+ return new DERExternalParser(sp).getLoadedObject();
+ default:
+ throw new IOException("unknown BER object encountered");
+ }
+ }
+ else
+ {
+ try
+ {
+ return buildObject(tag, tagNo, length);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new ASN1Exception("corrupted stream detected", e);
+ }
+ }
+ }
+
+ static int readTagNumber(InputStream s, int tag)
+ throws IOException
+ {
+ int tagNo = tag & 0x1f;
+
+ //
+ // with tagged object tag number is bottom 5 bits, or stored at the start of the content
+ //
+ if (tagNo == 0x1f)
+ {
+ tagNo = 0;
+
+ int b = s.read();
+
+ // X.690-0207 8.1.2.4.2
+ // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
+ if ((b & 0x7f) == 0) // Note: -1 will pass
+ {
+ throw new IOException("corrupted stream - invalid high tag number found");
+ }
+
+ while ((b >= 0) && ((b & 0x80) != 0))
+ {
+ tagNo |= (b & 0x7f);
+ tagNo <<= 7;
+ b = s.read();
+ }
+
+ if (b < 0)
+ {
+ throw new EOFException("EOF found inside tag value.");
+ }
+
+ tagNo |= (b & 0x7f);
+ }
+
+ return tagNo;
+ }
+
+ static int readLength(InputStream s, int limit)
+ throws IOException
+ {
+ int length = s.read();
+ if (length < 0)
+ {
+ throw new EOFException("EOF found when length expected");
+ }
+
+ if (length == 0x80)
+ {
+ return -1; // indefinite-length encoding
+ }
+
+ if (length > 127)
+ {
+ int size = length & 0x7f;
+
+ // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
+ if (size > 4)
+ {
+ throw new IOException("DER length more than 4 bytes: " + size);
+ }
+
+ length = 0;
+ for (int i = 0; i < size; i++)
+ {
+ int next = s.read();
+
+ if (next < 0)
+ {
+ throw new EOFException("EOF found reading length");
+ }
+
+ length = (length << 8) + next;
+ }
+
+ if (length < 0)
+ {
+ throw new IOException("corrupted stream - negative length found");
+ }
+
+ if (length >= limit) // after all we must have read at least 1 byte
+ {
+ throw new IOException("corrupted stream - out of bounds length found");
+ }
+ }
+
+ return length;
+ }
+
+ private static byte[] getBuffer(DefiniteLengthInputStream defIn, byte[][] tmpBuffers)
+ throws IOException
+ {
+ int len = defIn.getRemaining();
+ if (defIn.getRemaining() < tmpBuffers.length)
+ {
+ byte[] buf = tmpBuffers[len];
+
+ if (buf == null)
+ {
+ buf = tmpBuffers[len] = new byte[len];
+ }
+
+ Streams.readFully(defIn, buf);
+
+ return buf;
+ }
+ else
+ {
+ return defIn.toByteArray();
+ }
+ }
+
+ private static char[] getBMPCharBuffer(DefiniteLengthInputStream defIn)
+ throws IOException
+ {
+ int len = defIn.getRemaining() / 2;
+ char[] buf = new char[len];
+ int totalRead = 0;
+ while (totalRead < len)
+ {
+ int ch1 = defIn.read();
+ if (ch1 < 0)
+ {
+ break;
+ }
+ int ch2 = defIn.read();
+ if (ch2 < 0)
+ {
+ break;
+ }
+ buf[totalRead++] = (char)((ch1 << 8) | (ch2 & 0xff));
+ }
+
+ return buf;
+ }
+
+ static ASN1Primitive createPrimitiveDERObject(
+ int tagNo,
+ DefiniteLengthInputStream defIn,
+ byte[][] tmpBuffers)
+ throws IOException
+ {
+ switch (tagNo)
+ {
+ case BIT_STRING:
+ return DERBitString.fromInputStream(defIn.getRemaining(), defIn);
+ case BMP_STRING:
+ return new DERBMPString(getBMPCharBuffer(defIn));
+ case BOOLEAN:
+ return ASN1Boolean.fromOctetString(getBuffer(defIn, tmpBuffers));
+ case ENUMERATED:
+ return ASN1Enumerated.fromOctetString(getBuffer(defIn, tmpBuffers));
+ case GENERALIZED_TIME:
+ return new ASN1GeneralizedTime(defIn.toByteArray());
+ case GENERAL_STRING:
+ return new DERGeneralString(defIn.toByteArray());
+ case IA5_STRING:
+ return new DERIA5String(defIn.toByteArray());
+ case INTEGER:
+ return new ASN1Integer(defIn.toByteArray(), false);
+ case NULL:
+ return DERNull.INSTANCE; // actual content is ignored (enforce 0 length?)
+ case NUMERIC_STRING:
+ return new DERNumericString(defIn.toByteArray());
+ case OBJECT_IDENTIFIER:
+ return ASN1ObjectIdentifier.fromOctetString(getBuffer(defIn, tmpBuffers));
+ case OCTET_STRING:
+ return new DEROctetString(defIn.toByteArray());
+ case PRINTABLE_STRING:
+ return new DERPrintableString(defIn.toByteArray());
+ case T61_STRING:
+ return new DERT61String(defIn.toByteArray());
+ case UNIVERSAL_STRING:
+ return new DERUniversalString(defIn.toByteArray());
+ case UTC_TIME:
+ return new ASN1UTCTime(defIn.toByteArray());
+ case UTF8_STRING:
+ return new DERUTF8String(defIn.toByteArray());
+ case VISIBLE_STRING:
+ return new DERVisibleString(defIn.toByteArray());
+ default:
+ throw new IOException("unknown tag " + tagNo + " encountered");
+ }
+ }
+}
diff --git a/core/src/main/jdk1.1/org/spongycastle/asn1/ASN1StreamParser.java b/core/src/main/jdk1.1/org/spongycastle/asn1/ASN1StreamParser.java
new file mode 100644
index 00000000..bbaef056
--- /dev/null
+++ b/core/src/main/jdk1.1/org/spongycastle/asn1/ASN1StreamParser.java
@@ -0,0 +1,247 @@
+package org.spongycastle.asn1;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class ASN1StreamParser
+{
+ private InputStream _in;
+ private int _limit;
+ private byte[][] tmpBuffers;
+
+ public ASN1StreamParser(
+ InputStream in)
+ {
+ this(in, StreamUtil.findLimit(in));
+ }
+
+ public ASN1StreamParser(
+ InputStream in,
+ int limit)
+ {
+ this._in = in;
+ this._limit = limit;
+
+ this.tmpBuffers = new byte[11][];
+ }
+
+ public ASN1StreamParser(
+ byte[] encoding)
+ {
+ this(new ByteArrayInputStream(encoding), encoding.length);
+ }
+
+ ASN1Encodable readIndef(int tagValue) throws IOException
+ {
+ // Note: INDEF => CONSTRUCTED
+
+ // TODO There are other tags that may be constructed (e.g. BIT_STRING)
+ switch (tagValue)
+ {
+ case BERTags.EXTERNAL:
+ return new DERExternalParser(this);
+ case BERTags.OCTET_STRING:
+ return new BEROctetStringParser(this);
+ case BERTags.SEQUENCE:
+ return new BERSequenceParser(this);
+ case BERTags.SET:
+ return new BERSetParser(this);
+ default:
+ throw new ASN1Exception("unknown BER object encountered: 0x" + Integer.toHexString(tagValue));
+ }
+ }
+
+ ASN1Encodable readImplicit(boolean constructed, int tag) throws IOException
+ {
+ if (_in instanceof IndefiniteLengthInputStream)
+ {
+ if (!constructed)
+ {
+ throw new IOException("indefinite length primitive encoding encountered");
+ }
+
+ return readIndef(tag);
+ }
+
+ if (constructed)
+ {
+ switch (tag)
+ {
+ case BERTags.SET:
+ return new DERSetParser(this);
+ case BERTags.SEQUENCE:
+ return new DERSequenceParser(this);
+ case BERTags.OCTET_STRING:
+ return new BEROctetStringParser(this);
+ }
+ }
+ else
+ {
+ switch (tag)
+ {
+ case BERTags.SET:
+ throw new ASN1Exception("sequences must use constructed encoding (see X.690 8.9.1/8.10.1)");
+ case BERTags.SEQUENCE:
+ throw new ASN1Exception("sets must use constructed encoding (see X.690 8.11.1/8.12.1)");
+ case BERTags.OCTET_STRING:
+ return new DEROctetStringParser((DefiniteLengthInputStream)_in);
+ }
+ }
+
+ // TODO ASN1Exception
+ throw new RuntimeException("implicit tagging not implemented");
+ }
+
+ ASN1Primitive readTaggedObject(boolean constructed, int tag) throws IOException
+ {
+ if (!constructed)
+ {
+ // Note: !CONSTRUCTED => IMPLICIT
+ DefiniteLengthInputStream defIn = (DefiniteLengthInputStream)_in;
+ return new DERTaggedObject(false, tag, new DEROctetString(defIn.toByteArray()));
+ }
+
+ ASN1EncodableVector v = readVector();
+
+ if (_in instanceof IndefiniteLengthInputStream)
+ {
+ return v.size() == 1
+ ? new BERTaggedObject(true, tag, v.get(0))
+ : new BERTaggedObject(false, tag, BERFactory.createSequence(v));
+ }
+
+ return v.size() == 1
+ ? new DERTaggedObject(true, tag, v.get(0))
+ : new DERTaggedObject(false, tag, DERFactory.createSequence(v));
+ }
+
+ public ASN1Encodable readObject()
+ throws IOException
+ {
+ int tag = _in.read();
+ if (tag == -1)
+ {
+ return null;
+ }
+
+ //
+ // turn of looking for "00" while we resolve the tag
+ //
+ set00Check(false);
+
+ //
+ // calculate tag number
+ //
+ int tagNo = ASN1InputStream.readTagNumber(_in, tag);
+
+ boolean isConstructed = (tag & BERTags.CONSTRUCTED) != 0;
+
+ //
+ // calculate length
+ //
+ int length = ASN1InputStream.readLength(_in, _limit);
+
+ if (length < 0) // indefinite length method
+ {
+ if (!isConstructed)
+ {
+ throw new IOException("indefinite length primitive encoding encountered");
+ }
+
+ IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in, _limit);
+ ASN1StreamParser sp = new ASN1StreamParser(indIn, _limit);
+
+ if ((tag & BERTags.APPLICATION) != 0)
+ {
+ return new BERApplicationSpecificParser(tagNo, sp);
+ }
+
+ if ((tag & BERTags.TAGGED) != 0)
+ {
+ return new BERTaggedObjectParser(true, tagNo, sp);
+ }
+
+ return sp.readIndef(tagNo);
+ }
+ else
+ {
+ DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length);
+
+ if ((tag & BERTags.APPLICATION) != 0)
+ {
+ return new DERApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
+ }
+
+ if ((tag & BERTags.TAGGED) != 0)
+ {
+ return new BERTaggedObjectParser(isConstructed, tagNo, new ASN1StreamParser(defIn));
+ }
+
+ if (isConstructed)
+ {
+ // TODO There are other tags that may be constructed (e.g. BIT_STRING)
+ switch (tagNo)
+ {
+ case BERTags.OCTET_STRING:
+ //
+ // yes, people actually do this...
+ //
+ return new BEROctetStringParser(new ASN1StreamParser(defIn));
+ case BERTags.SEQUENCE:
+ return new DERSequenceParser(new ASN1StreamParser(defIn));
+ case BERTags.SET:
+ return new DERSetParser(new ASN1StreamParser(defIn));
+ case BERTags.EXTERNAL:
+ return new DERExternalParser(new ASN1StreamParser(defIn));
+ default:
+ throw new IOException("unknown tag " + tagNo + " encountered");
+ }
+ }
+
+ // Some primitive encodings can be handled by parsers too...
+ switch (tagNo)
+ {
+ case BERTags.OCTET_STRING:
+ return new DEROctetStringParser(defIn);
+ }
+
+ try
+ {
+ return ASN1InputStream.createPrimitiveDERObject(tagNo, defIn, tmpBuffers);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new ASN1Exception("corrupted stream detected", e);
+ }
+ }
+ }
+
+ private void set00Check(boolean enabled)
+ {
+ if (_in instanceof IndefiniteLengthInputStream)
+ {
+ ((IndefiniteLengthInputStream)_in).setEofOn00(enabled);
+ }
+ }
+
+ ASN1EncodableVector readVector() throws IOException
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ ASN1Encodable obj;
+ while ((obj = readObject()) != null)
+ {
+ if (obj instanceof InMemoryRepresentable)
+ {
+ v.add(((InMemoryRepresentable)obj).getLoadedObject());
+ }
+ else
+ {
+ v.add(obj.toASN1Primitive());
+ }
+ }
+
+ return v;
+ }
+}
diff --git a/core/src/main/jdk1.1/org/spongycastle/asn1/DERApplicationSpecific.java b/core/src/main/jdk1.1/org/spongycastle/asn1/DERApplicationSpecific.java
new file mode 100644
index 00000000..30c66ab6
--- /dev/null
+++ b/core/src/main/jdk1.1/org/spongycastle/asn1/DERApplicationSpecific.java
@@ -0,0 +1,276 @@
+package org.spongycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import org.spongycastle.util.Arrays;
+
+/**
+ * Base class for an application specific object
+ */
+public class DERApplicationSpecific
+ extends ASN1Primitive
+{
+ private boolean isConstructed;
+ private int tag;
+ private byte[] octets;
+
+ DERApplicationSpecific(
+ boolean isConstructed,
+ int tag,
+ byte[] octets)
+ {
+ this.isConstructed = isConstructed;
+ this.tag = tag;
+ this.octets = octets;
+ }
+
+ public DERApplicationSpecific(
+ int tag,
+ byte[] octets)
+ {
+ this(false, tag, octets);
+ }
+
+ public DERApplicationSpecific(
+ int tag,
+ ASN1Encodable object)
+ throws IOException
+ {
+ this(true, tag, object);
+ }
+
+ public DERApplicationSpecific(
+ boolean explicit,
+ int tag,
+ ASN1Encodable object)
+ throws IOException
+ {
+ ASN1Primitive primitive = object.toASN1Primitive();
+
+ byte[] data = primitive.getEncoded(ASN1Encoding.DER);
+
+ this.isConstructed = explicit || (primitive instanceof ASN1Set || primitive instanceof ASN1Sequence);
+ this.tag = tag;
+
+ if (explicit)
+ {
+ this.octets = data;
+ }
+ else
+ {
+ int lenBytes = getLengthOfHeader(data);
+ byte[] tmp = new byte[data.length - lenBytes];
+ System.arraycopy(data, lenBytes, tmp, 0, tmp.length);
+ this.octets = tmp;
+ }
+ }
+
+ public DERApplicationSpecific(int tagNo, ASN1EncodableVector vec)
+ {
+ this.tag = tagNo;
+ this.isConstructed = true;
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ for (int i = 0; i != vec.size(); i++)
+ {
+ try
+ {
+ bOut.write(((ASN1Object)vec.get(i)).getEncoded(ASN1Encoding.DER));
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException("malformed object: " + e, e);
+ }
+ }
+ this.octets = bOut.toByteArray();
+ }
+
+ public static DERApplicationSpecific getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof DERApplicationSpecific)
+ {
+ return (DERApplicationSpecific)obj;
+ }
+ else if (obj instanceof byte[])
+ {
+ try
+ {
+ return DERApplicationSpecific.getInstance(ASN1Primitive.fromByteArray((byte[])obj));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("failed to construct object from byte[]: " + e.getMessage());
+ }
+ }
+ else if (obj instanceof ASN1Encodable)
+ {
+ ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive();
+
+ if (primitive instanceof ASN1Sequence)
+ {
+ return (DERApplicationSpecific)primitive;
+ }
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
+ }
+
+ private int getLengthOfHeader(byte[] data)
+ {
+ int length = data[1] & 0xff; // TODO: assumes 1 byte tag
+
+ if (length == 0x80)
+ {
+ return 2; // indefinite-length encoding
+ }
+
+ if (length > 127)
+ {
+ int size = length & 0x7f;
+
+ // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
+ if (size > 4)
+ {
+ throw new IllegalStateException("DER length more than 4 bytes: " + size);
+ }
+
+ return size + 2;
+ }
+
+ return 2;
+ }
+
+ public boolean isConstructed()
+ {
+ return isConstructed;
+ }
+
+ public byte[] getContents()
+ {
+ return octets;
+ }
+
+ public int getApplicationTag()
+ {
+ return tag;
+ }
+
+ /**
+ * Return the enclosed object assuming explicit tagging.
+ *
+ * @return the resulting object
+ * @throws IOException if reconstruction fails.
+ */
+ public ASN1Primitive getObject()
+ throws IOException
+ {
+ return new ASN1InputStream(getContents()).readObject();
+ }
+
+ /**
+ * Return the enclosed object assuming implicit tagging.
+ *
+ * @param derTagNo the type tag that should be applied to the object's contents.
+ * @return the resulting object
+ * @throws IOException if reconstruction fails.
+ */
+ public ASN1Primitive getObject(int derTagNo)
+ throws IOException
+ {
+ if (derTagNo >= 0x1f)
+ {
+ throw new IOException("unsupported tag number");
+ }
+
+ byte[] orig = this.getEncoded();
+ byte[] tmp = replaceTagNumber(derTagNo, orig);
+
+ if ((orig[0] & BERTags.CONSTRUCTED) != 0)
+ {
+ tmp[0] |= BERTags.CONSTRUCTED;
+ }
+
+ return new ASN1InputStream(tmp).readObject();
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ return StreamUtil.calculateTagLength(tag) + StreamUtil.calculateBodyLength(octets.length) + octets.length;
+ }
+
+ /* (non-Javadoc)
+ * @see org.spongycastle.asn1.ASN1Primitive#encode(org.spongycastle.asn1.DEROutputStream)
+ */
+ void encode(ASN1OutputStream out) throws IOException
+ {
+ int classBits = BERTags.APPLICATION;
+ if (isConstructed)
+ {
+ classBits |= BERTags.CONSTRUCTED;
+ }
+
+ out.writeEncoded(classBits, tag, octets);
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERApplicationSpecific))
+ {
+ return false;
+ }
+
+ DERApplicationSpecific other = (DERApplicationSpecific)o;
+
+ return isConstructed == other.isConstructed
+ && tag == other.tag
+ && Arrays.areEqual(octets, other.octets);
+ }
+
+ public int hashCode()
+ {
+ return (isConstructed ? 1 : 0) ^ tag ^ Arrays.hashCode(octets);
+ }
+
+ private byte[] replaceTagNumber(int newTag, byte[] input)
+ throws IOException
+ {
+ int tagNo = input[0] & 0x1f;
+ int index = 1;
+ //
+ // with tagged object tag number is bottom 5 bits, or stored at the start of the content
+ //
+ if (tagNo == 0x1f)
+ {
+ tagNo = 0;
+
+ int b = input[index++] & 0xff;
+
+ // X.690-0207 8.1.2.4.2
+ // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
+ if ((b & 0x7f) == 0) // Note: -1 will pass
+ {
+ throw new ASN1ParsingException("corrupted stream - invalid high tag number found");
+ }
+
+ while ((b >= 0) && ((b & 0x80) != 0))
+ {
+ tagNo |= (b & 0x7f);
+ tagNo <<= 7;
+ b = input[index++] & 0xff;
+ }
+
+ tagNo |= (b & 0x7f);
+ }
+
+ byte[] tmp = new byte[input.length - index + 1];
+
+ System.arraycopy(input, index, tmp, 1, tmp.length - 1);
+
+ tmp[0] = (byte)newTag;
+
+ return tmp;
+ }
+}
diff --git a/core/src/main/jdk1.1/org/spongycastle/asn1/x500/style/BCStyle.java b/core/src/main/jdk1.1/org/spongycastle/asn1/x500/style/BCStyle.java
new file mode 100644
index 00000000..2591e4cd
--- /dev/null
+++ b/core/src/main/jdk1.1/org/spongycastle/asn1/x500/style/BCStyle.java
@@ -0,0 +1,481 @@
+package org.spongycastle.asn1.x500.style;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.DERPrintableString;
+import org.spongycastle.asn1.DERUTF8String;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.x500.AttributeTypeAndValue;
+import org.spongycastle.asn1.x500.RDN;
+import org.spongycastle.asn1.x500.X500Name;
+import org.spongycastle.asn1.x500.X500NameStyle;
+import org.spongycastle.asn1.x509.X509ObjectIdentifiers;
+
+public class BCStyle
+ implements X500NameStyle
+{
+ /**
+ * country code - StringType(SIZE(2))
+ */
+ public static final ASN1ObjectIdentifier C = new ASN1ObjectIdentifier("2.5.4.6");
+
+ /**
+ * organization - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier O = new ASN1ObjectIdentifier("2.5.4.10");
+
+ /**
+ * organizational unit name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier OU = new ASN1ObjectIdentifier("2.5.4.11");
+
+ /**
+ * Title
+ */
+ public static final ASN1ObjectIdentifier T = new ASN1ObjectIdentifier("2.5.4.12");
+
+ /**
+ * common name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier CN = new ASN1ObjectIdentifier("2.5.4.3");
+
+ /**
+ * device serial number name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier SN = new ASN1ObjectIdentifier("2.5.4.5");
+
+ /**
+ * street - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier STREET = new ASN1ObjectIdentifier("2.5.4.9");
+
+ /**
+ * device serial number name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier SERIALNUMBER = SN;
+
+ /**
+ * locality name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier L = new ASN1ObjectIdentifier("2.5.4.7");
+
+ /**
+ * state, or province name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier ST = new ASN1ObjectIdentifier("2.5.4.8");
+
+ /**
+ * Naming attributes of type X520name
+ */
+ public static final ASN1ObjectIdentifier SURNAME = new ASN1ObjectIdentifier("2.5.4.4");
+ public static final ASN1ObjectIdentifier GIVENNAME = new ASN1ObjectIdentifier("2.5.4.42");
+ public static final ASN1ObjectIdentifier INITIALS = new ASN1ObjectIdentifier("2.5.4.43");
+ public static final ASN1ObjectIdentifier GENERATION = new ASN1ObjectIdentifier("2.5.4.44");
+ public static final ASN1ObjectIdentifier UNIQUE_IDENTIFIER = new ASN1ObjectIdentifier("2.5.4.45");
+
+ /**
+ * businessCategory - DirectoryString(SIZE(1..128)
+ */
+ public static final ASN1ObjectIdentifier BUSINESS_CATEGORY = new ASN1ObjectIdentifier(
+ "2.5.4.15");
+
+ /**
+ * postalCode - DirectoryString(SIZE(1..40)
+ */
+ public static final ASN1ObjectIdentifier POSTAL_CODE = new ASN1ObjectIdentifier(
+ "2.5.4.17");
+
+ /**
+ * dnQualifier - DirectoryString(SIZE(1..64)
+ */
+ public static final ASN1ObjectIdentifier DN_QUALIFIER = new ASN1ObjectIdentifier(
+ "2.5.4.46");
+
+ /**
+ * RFC 3039 Pseudonym - DirectoryString(SIZE(1..64)
+ */
+ public static final ASN1ObjectIdentifier PSEUDONYM = new ASN1ObjectIdentifier(
+ "2.5.4.65");
+
+
+ /**
+ * RFC 3039 DateOfBirth - GeneralizedTime - YYYYMMDD000000Z
+ */
+ public static final ASN1ObjectIdentifier DATE_OF_BIRTH = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.1");
+
+ /**
+ * RFC 3039 PlaceOfBirth - DirectoryString(SIZE(1..128)
+ */
+ public static final ASN1ObjectIdentifier PLACE_OF_BIRTH = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.2");
+
+ /**
+ * RFC 3039 Gender - PrintableString (SIZE(1)) -- "M", "F", "m" or "f"
+ */
+ public static final ASN1ObjectIdentifier GENDER = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.3");
+
+ /**
+ * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
+ * codes only
+ */
+ public static final ASN1ObjectIdentifier COUNTRY_OF_CITIZENSHIP = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.4");
+
+ /**
+ * RFC 3039 CountryOfResidence - PrintableString (SIZE (2)) -- ISO 3166
+ * codes only
+ */
+ public static final ASN1ObjectIdentifier COUNTRY_OF_RESIDENCE = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.5");
+
+
+ /**
+ * ISIS-MTT NameAtBirth - DirectoryString(SIZE(1..64)
+ */
+ public static final ASN1ObjectIdentifier NAME_AT_BIRTH = new ASN1ObjectIdentifier("1.3.36.8.3.14");
+
+ /**
+ * RFC 3039 PostalAddress - SEQUENCE SIZE (1..6) OF
+ * DirectoryString(SIZE(1..30))
+ */
+ public static final ASN1ObjectIdentifier POSTAL_ADDRESS = new ASN1ObjectIdentifier("2.5.4.16");
+
+ /**
+ * RFC 2256 dmdName
+ */
+ public static final ASN1ObjectIdentifier DMD_NAME = new ASN1ObjectIdentifier("2.5.4.54");
+
+ /**
+ * id-at-telephoneNumber
+ */
+ public static final ASN1ObjectIdentifier TELEPHONE_NUMBER = X509ObjectIdentifiers.id_at_telephoneNumber;
+
+ /**
+ * id-at-name
+ */
+ public static final ASN1ObjectIdentifier NAME = X509ObjectIdentifiers.id_at_name;
+
+ /**
+ * Email address (RSA PKCS#9 extension) - IA5String.
+ * <p>Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.
+ */
+ public static final ASN1ObjectIdentifier EmailAddress = PKCSObjectIdentifiers.pkcs_9_at_emailAddress;
+
+ /**
+ * more from PKCS#9
+ */
+ public static final ASN1ObjectIdentifier UnstructuredName = PKCSObjectIdentifiers.pkcs_9_at_unstructuredName;
+ public static final ASN1ObjectIdentifier UnstructuredAddress = PKCSObjectIdentifiers.pkcs_9_at_unstructuredAddress;
+
+ /**
+ * email address in Verisign certificates
+ */
+ public static final ASN1ObjectIdentifier E = EmailAddress;
+
+ /*
+ * others...
+ */
+ public static final ASN1ObjectIdentifier DC = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.25");
+
+ /**
+ * LDAP User id.
+ */
+ public static final ASN1ObjectIdentifier UID = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.1");
+
+ /**
+ * default look up table translating OID values into their common symbols following
+ * the convention in RFC 2253 with a few extras
+ */
+ private static final Hashtable DefaultSymbols = new Hashtable();
+
+ /**
+ * look up table translating common symbols into their OIDS.
+ */
+ private static final Hashtable DefaultLookUp = new Hashtable();
+
+ static
+ {
+ DefaultSymbols.put(C, "C");
+ DefaultSymbols.put(O, "O");
+ DefaultSymbols.put(T, "T");
+ DefaultSymbols.put(OU, "OU");
+ DefaultSymbols.put(CN, "CN");
+ DefaultSymbols.put(L, "L");
+ DefaultSymbols.put(ST, "ST");
+ DefaultSymbols.put(SN, "SERIALNUMBER");
+ DefaultSymbols.put(EmailAddress, "E");
+ DefaultSymbols.put(DC, "DC");
+ DefaultSymbols.put(UID, "UID");
+ DefaultSymbols.put(STREET, "STREET");
+ DefaultSymbols.put(SURNAME, "SURNAME");
+ DefaultSymbols.put(GIVENNAME, "GIVENNAME");
+ DefaultSymbols.put(INITIALS, "INITIALS");
+ DefaultSymbols.put(GENERATION, "GENERATION");
+ DefaultSymbols.put(UnstructuredAddress, "unstructuredAddress");
+ DefaultSymbols.put(UnstructuredName, "unstructuredName");
+ DefaultSymbols.put(UNIQUE_IDENTIFIER, "UniqueIdentifier");
+ DefaultSymbols.put(DN_QUALIFIER, "DN");
+ DefaultSymbols.put(PSEUDONYM, "Pseudonym");
+ DefaultSymbols.put(POSTAL_ADDRESS, "PostalAddress");
+ DefaultSymbols.put(NAME_AT_BIRTH, "NameAtBirth");
+ DefaultSymbols.put(COUNTRY_OF_CITIZENSHIP, "CountryOfCitizenship");
+ DefaultSymbols.put(COUNTRY_OF_RESIDENCE, "CountryOfResidence");
+ DefaultSymbols.put(GENDER, "Gender");
+ DefaultSymbols.put(PLACE_OF_BIRTH, "PlaceOfBirth");
+ DefaultSymbols.put(DATE_OF_BIRTH, "DateOfBirth");
+ DefaultSymbols.put(POSTAL_CODE, "PostalCode");
+ DefaultSymbols.put(BUSINESS_CATEGORY, "BusinessCategory");
+ DefaultSymbols.put(TELEPHONE_NUMBER, "TelephoneNumber");
+ DefaultSymbols.put(NAME, "Name");
+
+ DefaultLookUp.put("c", C);
+ DefaultLookUp.put("o", O);
+ DefaultLookUp.put("t", T);
+ DefaultLookUp.put("ou", OU);
+ DefaultLookUp.put("cn", CN);
+ DefaultLookUp.put("l", L);
+ DefaultLookUp.put("st", ST);
+ DefaultLookUp.put("sn", SN);
+ DefaultLookUp.put("serialnumber", SN);
+ DefaultLookUp.put("street", STREET);
+ DefaultLookUp.put("emailaddress", E);
+ DefaultLookUp.put("dc", DC);
+ DefaultLookUp.put("e", E);
+ DefaultLookUp.put("uid", UID);
+ DefaultLookUp.put("surname", SURNAME);
+ DefaultLookUp.put("givenname", GIVENNAME);
+ DefaultLookUp.put("initials", INITIALS);
+ DefaultLookUp.put("generation", GENERATION);
+ DefaultLookUp.put("unstructuredaddress", UnstructuredAddress);
+ DefaultLookUp.put("unstructuredname", UnstructuredName);
+ DefaultLookUp.put("uniqueidentifier", UNIQUE_IDENTIFIER);
+ DefaultLookUp.put("dn", DN_QUALIFIER);
+ DefaultLookUp.put("pseudonym", PSEUDONYM);
+ DefaultLookUp.put("postaladdress", POSTAL_ADDRESS);
+ DefaultLookUp.put("nameofbirth", NAME_AT_BIRTH);
+ DefaultLookUp.put("countryofcitizenship", COUNTRY_OF_CITIZENSHIP);
+ DefaultLookUp.put("countryofresidence", COUNTRY_OF_RESIDENCE);
+ DefaultLookUp.put("gender", GENDER);
+ DefaultLookUp.put("placeofbirth", PLACE_OF_BIRTH);
+ DefaultLookUp.put("dateofbirth", DATE_OF_BIRTH);
+ DefaultLookUp.put("postalcode", POSTAL_CODE);
+ DefaultLookUp.put("businesscategory", BUSINESS_CATEGORY);
+ DefaultLookUp.put("telephonenumber", TELEPHONE_NUMBER);
+ DefaultLookUp.put("name", NAME);
+ }
+
+ /**
+ * Singleton instance.
+ */
+ public static final X500NameStyle INSTANCE = new BCStyle();
+
+ protected Hashtable defaultLookUp;
+ protected Hashtable defaultSymbols;
+
+ protected BCStyle()
+ {
+ defaultSymbols = copyHashTable(DefaultSymbols);
+ defaultLookUp = copyHashTable(DefaultLookUp);
+ }
+
+ public ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value)
+ {
+ if (value.length() != 0 && value.charAt(0) == '#')
+ {
+ try
+ {
+ return IETFUtils.valueFromHexString(value, 1);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("can't recode value for oid " + oid.getId());
+ }
+ }
+ else
+ {
+ if (value.length() != 0 && value.charAt(0) == '\\')
+ {
+ value = value.substring(1);
+ }
+ if (oid.equals(EmailAddress) || oid.equals(DC))
+ {
+ return new DERIA5String(value);
+ }
+ else if (oid.equals(DATE_OF_BIRTH)) // accept time string as well as # (for compatibility)
+ {
+ return new ASN1GeneralizedTime(value);
+ }
+ else if (oid.equals(C) || oid.equals(SN) || oid.equals(DN_QUALIFIER)
+ || oid.equals(TELEPHONE_NUMBER))
+ {
+ return new DERPrintableString(value);
+ }
+ }
+
+ return new DERUTF8String(value);
+ }
+
+ public String oidToDisplayName(ASN1ObjectIdentifier oid)
+ {
+ return (String)DefaultSymbols.get(oid);
+ }
+
+ public String[] oidToAttrNames(ASN1ObjectIdentifier oid)
+ {
+ return IETFUtils.findAttrNamesForOID(oid, defaultLookUp);
+ }
+
+ public ASN1ObjectIdentifier attrNameToOID(String attrName)
+ {
+ return IETFUtils.decodeAttrName(attrName, defaultLookUp);
+ }
+
+ public boolean areEqual(X500Name name1, X500Name name2)
+ {
+ RDN[] rdns1 = name1.getRDNs();
+ RDN[] rdns2 = name2.getRDNs();
+
+ if (rdns1.length != rdns2.length)
+ {
+ return false;
+ }
+
+ boolean reverse = false;
+
+ if (rdns1[0].getFirst() != null && rdns2[0].getFirst() != null)
+ {
+ reverse = !rdns1[0].getFirst().getType().equals(rdns2[0].getFirst().getType()); // guess forward
+ }
+
+ for (int i = 0; i != rdns1.length; i++)
+ {
+ if (!foundMatch(reverse, rdns1[i], rdns2))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private boolean foundMatch(boolean reverse, RDN rdn, RDN[] possRDNs)
+ {
+ if (reverse)
+ {
+ for (int i = possRDNs.length - 1; i >= 0; i--)
+ {
+ if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
+ {
+ possRDNs[i] = null;
+ return true;
+ }
+ }
+ }
+ else
+ {
+ for (int i = 0; i != possRDNs.length; i++)
+ {
+ if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
+ {
+ possRDNs[i] = null;
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ protected boolean rdnAreEqual(RDN rdn1, RDN rdn2)
+ {
+ return IETFUtils.rDNAreEqual(rdn1, rdn2);
+ }
+
+ public RDN[] fromString(String dirName)
+ {
+ return IETFUtils.rDNsFromString(dirName, this);
+ }
+
+ public int calculateHashCode(X500Name name)
+ {
+ int hashCodeValue = 0;
+ RDN[] rdns = name.getRDNs();
+
+ // this needs to be order independent, like equals
+ for (int i = 0; i != rdns.length; i++)
+ {
+ if (rdns[i].isMultiValued())
+ {
+ AttributeTypeAndValue[] atv = rdns[i].getTypesAndValues();
+
+ for (int j = 0; j != atv.length; j++)
+ {
+ hashCodeValue ^= atv[j].getType().hashCode();
+ hashCodeValue ^= calcHashCode(atv[j].getValue());
+ }
+ }
+ else
+ {
+ hashCodeValue ^= rdns[i].getFirst().getType().hashCode();
+ hashCodeValue ^= calcHashCode(rdns[i].getFirst().getValue());
+ }
+ }
+
+ return hashCodeValue;
+ }
+
+ private int calcHashCode(ASN1Encodable enc)
+ {
+ String value = IETFUtils.valueToString(enc);
+
+ value = IETFUtils.canonicalize(value);
+
+ return value.hashCode();
+ }
+
+ public String toString(X500Name name)
+ {
+ StringBuffer buf = new StringBuffer();
+ boolean first = true;
+
+ RDN[] rdns = name.getRDNs();
+
+ for (int i = 0; i < rdns.length; i++)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ buf.append(',');
+ }
+
+ 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/core/src/main/jdk1.1/org/spongycastle/asn1/x500/style/RFC4519Style.java b/core/src/main/jdk1.1/org/spongycastle/asn1/x500/style/RFC4519Style.java
new file mode 100644
index 00000000..0fd11785
--- /dev/null
+++ b/core/src/main/jdk1.1/org/spongycastle/asn1/x500/style/RFC4519Style.java
@@ -0,0 +1,380 @@
+package org.spongycastle.asn1.x500.style;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.DERPrintableString;
+import org.spongycastle.asn1.DERUTF8String;
+import org.spongycastle.asn1.x500.AttributeTypeAndValue;
+import org.spongycastle.asn1.x500.RDN;
+import org.spongycastle.asn1.x500.X500Name;
+import org.spongycastle.asn1.x500.X500NameStyle;
+
+public class RFC4519Style
+ implements X500NameStyle
+{
+ public static final ASN1ObjectIdentifier businessCategory = new ASN1ObjectIdentifier("2.5.4.15");
+ public static final ASN1ObjectIdentifier c = new ASN1ObjectIdentifier("2.5.4.6");
+ public static final ASN1ObjectIdentifier cn = new ASN1ObjectIdentifier("2.5.4.3");
+ public static final ASN1ObjectIdentifier dc = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.25");
+ public static final ASN1ObjectIdentifier description = new ASN1ObjectIdentifier("2.5.4.13");
+ public static final ASN1ObjectIdentifier destinationIndicator = new ASN1ObjectIdentifier("2.5.4.27");
+ public static final ASN1ObjectIdentifier distinguishedName = new ASN1ObjectIdentifier("2.5.4.49");
+ public static final ASN1ObjectIdentifier dnQualifier = new ASN1ObjectIdentifier("2.5.4.46");
+ public static final ASN1ObjectIdentifier enhancedSearchGuide = new ASN1ObjectIdentifier("2.5.4.47");
+ public static final ASN1ObjectIdentifier facsimileTelephoneNumber = new ASN1ObjectIdentifier("2.5.4.23");
+ public static final ASN1ObjectIdentifier generationQualifier = new ASN1ObjectIdentifier("2.5.4.44");
+ public static final ASN1ObjectIdentifier givenName = new ASN1ObjectIdentifier("2.5.4.42");
+ public static final ASN1ObjectIdentifier houseIdentifier = new ASN1ObjectIdentifier("2.5.4.51");
+ public static final ASN1ObjectIdentifier initials = new ASN1ObjectIdentifier("2.5.4.43");
+ public static final ASN1ObjectIdentifier internationalISDNNumber = new ASN1ObjectIdentifier("2.5.4.25");
+ public static final ASN1ObjectIdentifier l = new ASN1ObjectIdentifier("2.5.4.7");
+ public static final ASN1ObjectIdentifier member = new ASN1ObjectIdentifier("2.5.4.31");
+ public static final ASN1ObjectIdentifier name = new ASN1ObjectIdentifier("2.5.4.41");
+ public static final ASN1ObjectIdentifier o = new ASN1ObjectIdentifier("2.5.4.10");
+ public static final ASN1ObjectIdentifier ou = new ASN1ObjectIdentifier("2.5.4.11");
+ public static final ASN1ObjectIdentifier owner = new ASN1ObjectIdentifier("2.5.4.32");
+ public static final ASN1ObjectIdentifier physicalDeliveryOfficeName = new ASN1ObjectIdentifier("2.5.4.19");
+ public static final ASN1ObjectIdentifier postalAddress = new ASN1ObjectIdentifier("2.5.4.16");
+ public static final ASN1ObjectIdentifier postalCode = new ASN1ObjectIdentifier("2.5.4.17");
+ public static final ASN1ObjectIdentifier postOfficeBox = new ASN1ObjectIdentifier("2.5.4.18");
+ public static final ASN1ObjectIdentifier preferredDeliveryMethod = new ASN1ObjectIdentifier("2.5.4.28");
+ public static final ASN1ObjectIdentifier registeredAddress = new ASN1ObjectIdentifier("2.5.4.26");
+ public static final ASN1ObjectIdentifier roleOccupant = new ASN1ObjectIdentifier("2.5.4.33");
+ public static final ASN1ObjectIdentifier searchGuide = new ASN1ObjectIdentifier("2.5.4.14");
+ public static final ASN1ObjectIdentifier seeAlso = new ASN1ObjectIdentifier("2.5.4.34");
+ public static final ASN1ObjectIdentifier serialNumber = new ASN1ObjectIdentifier("2.5.4.5");
+ public static final ASN1ObjectIdentifier sn = new ASN1ObjectIdentifier("2.5.4.4");
+ public static final ASN1ObjectIdentifier st = new ASN1ObjectIdentifier("2.5.4.8");
+ public static final ASN1ObjectIdentifier street = new ASN1ObjectIdentifier("2.5.4.9");
+ public static final ASN1ObjectIdentifier telephoneNumber = new ASN1ObjectIdentifier("2.5.4.20");
+ public static final ASN1ObjectIdentifier teletexTerminalIdentifier = new ASN1ObjectIdentifier("2.5.4.22");
+ public static final ASN1ObjectIdentifier telexNumber = new ASN1ObjectIdentifier("2.5.4.21");
+ public static final ASN1ObjectIdentifier title = new ASN1ObjectIdentifier("2.5.4.12");
+ public static final ASN1ObjectIdentifier uid = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.1");
+ public static final ASN1ObjectIdentifier uniqueMember = new ASN1ObjectIdentifier("2.5.4.50");
+ public static final ASN1ObjectIdentifier userPassword = new ASN1ObjectIdentifier("2.5.4.35");
+ public static final ASN1ObjectIdentifier x121Address = new ASN1ObjectIdentifier("2.5.4.24");
+ public static final ASN1ObjectIdentifier x500UniqueIdentifier = new ASN1ObjectIdentifier("2.5.4.45");
+
+ /**
+ * default look up table translating OID values into their common symbols following
+ * the convention in RFC 2253 with a few extras
+ */
+ private static final Hashtable DefaultSymbols = new Hashtable();
+
+ /**
+ * look up table translating common symbols into their OIDS.
+ */
+ private static final Hashtable DefaultLookUp = new Hashtable();
+
+ static
+ {
+ DefaultSymbols.put(businessCategory, "businessCategory");
+ DefaultSymbols.put(c, "c");
+ DefaultSymbols.put(cn, "cn");
+ DefaultSymbols.put(dc, "dc");
+ DefaultSymbols.put(description, "description");
+ DefaultSymbols.put(destinationIndicator, "destinationIndicator");
+ DefaultSymbols.put(distinguishedName, "distinguishedName");
+ DefaultSymbols.put(dnQualifier, "dnQualifier");
+ DefaultSymbols.put(enhancedSearchGuide, "enhancedSearchGuide");
+ DefaultSymbols.put(facsimileTelephoneNumber, "facsimileTelephoneNumber");
+ DefaultSymbols.put(generationQualifier, "generationQualifier");
+ DefaultSymbols.put(givenName, "givenName");
+ DefaultSymbols.put(houseIdentifier, "houseIdentifier");
+ DefaultSymbols.put(initials, "initials");
+ DefaultSymbols.put(internationalISDNNumber, "internationalISDNNumber");
+ DefaultSymbols.put(l, "l");
+ DefaultSymbols.put(member, "member");
+ DefaultSymbols.put(name, "name");
+ DefaultSymbols.put(o, "o");
+ DefaultSymbols.put(ou, "ou");
+ DefaultSymbols.put(owner, "owner");
+ DefaultSymbols.put(physicalDeliveryOfficeName, "physicalDeliveryOfficeName");
+ DefaultSymbols.put(postalAddress, "postalAddress");
+ DefaultSymbols.put(postalCode, "postalCode");
+ DefaultSymbols.put(postOfficeBox, "postOfficeBox");
+ DefaultSymbols.put(preferredDeliveryMethod, "preferredDeliveryMethod");
+ DefaultSymbols.put(registeredAddress, "registeredAddress");
+ DefaultSymbols.put(roleOccupant, "roleOccupant");
+ DefaultSymbols.put(searchGuide, "searchGuide");
+ DefaultSymbols.put(seeAlso, "seeAlso");
+ DefaultSymbols.put(serialNumber, "serialNumber");
+ DefaultSymbols.put(sn, "sn");
+ DefaultSymbols.put(st, "st");
+ DefaultSymbols.put(street, "street");
+ DefaultSymbols.put(telephoneNumber, "telephoneNumber");
+ DefaultSymbols.put(teletexTerminalIdentifier, "teletexTerminalIdentifier");
+ DefaultSymbols.put(telexNumber, "telexNumber");
+ DefaultSymbols.put(title, "title");
+ DefaultSymbols.put(uid, "uid");
+ DefaultSymbols.put(uniqueMember, "uniqueMember");
+ DefaultSymbols.put(userPassword, "userPassword");
+ DefaultSymbols.put(x121Address, "x121Address");
+ DefaultSymbols.put(x500UniqueIdentifier, "x500UniqueIdentifier");
+
+ DefaultLookUp.put("businesscategory", businessCategory);
+ DefaultLookUp.put("c", c);
+ DefaultLookUp.put("cn", cn);
+ DefaultLookUp.put("dc", dc);
+ DefaultLookUp.put("description", description);
+ DefaultLookUp.put("destinationindicator", destinationIndicator);
+ DefaultLookUp.put("distinguishedname", distinguishedName);
+ DefaultLookUp.put("dnqualifier", dnQualifier);
+ DefaultLookUp.put("enhancedsearchguide", enhancedSearchGuide);
+ DefaultLookUp.put("facsimiletelephonenumber", facsimileTelephoneNumber);
+ DefaultLookUp.put("generationqualifier", generationQualifier);
+ DefaultLookUp.put("givenname", givenName);
+ DefaultLookUp.put("houseidentifier", houseIdentifier);
+ DefaultLookUp.put("initials", initials);
+ DefaultLookUp.put("internationalisdnnumber", internationalISDNNumber);
+ DefaultLookUp.put("l", l);
+ DefaultLookUp.put("member", member);
+ DefaultLookUp.put("name", name);
+ DefaultLookUp.put("o", o);
+ DefaultLookUp.put("ou", ou);
+ DefaultLookUp.put("owner", owner);
+ DefaultLookUp.put("physicaldeliveryofficename", physicalDeliveryOfficeName);
+ DefaultLookUp.put("postaladdress", postalAddress);
+ DefaultLookUp.put("postalcode", postalCode);
+ DefaultLookUp.put("postofficebox", postOfficeBox);
+ DefaultLookUp.put("preferreddeliverymethod", preferredDeliveryMethod);
+ DefaultLookUp.put("registeredaddress", registeredAddress);
+ DefaultLookUp.put("roleoccupant", roleOccupant);
+ DefaultLookUp.put("searchguide", searchGuide);
+ DefaultLookUp.put("seealso", seeAlso);
+ DefaultLookUp.put("serialnumber", serialNumber);
+ DefaultLookUp.put("sn", sn);
+ DefaultLookUp.put("st", st);
+ DefaultLookUp.put("street", street);
+ DefaultLookUp.put("telephonenumber", telephoneNumber);
+ DefaultLookUp.put("teletexterminalidentifier", teletexTerminalIdentifier);
+ DefaultLookUp.put("telexnumber", telexNumber);
+ DefaultLookUp.put("title", title);
+ DefaultLookUp.put("uid", uid);
+ DefaultLookUp.put("uniquemember", uniqueMember);
+ DefaultLookUp.put("userpassword", userPassword);
+ DefaultLookUp.put("x121address", x121Address);
+ DefaultLookUp.put("x500uniqueidentifier", x500UniqueIdentifier);
+
+ // TODO: need to add correct matching for equality comparisons.
+ }
+
+ /**
+ * Singleton instance.
+ */
+ public static final X500NameStyle INSTANCE = new RFC4519Style();
+
+ protected Hashtable defaultLookUp;
+ protected Hashtable defaultSymbols;
+
+ protected RFC4519Style()
+ {
+ defaultSymbols = copyHashTable(DefaultSymbols);
+ defaultLookUp = copyHashTable(DefaultLookUp);
+ }
+
+ public ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value)
+ {
+ if (value.length() != 0 && value.charAt(0) == '#')
+ {
+ try
+ {
+ return IETFUtils.valueFromHexString(value, 1);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("can't recode value for oid " + oid.getId());
+ }
+ }
+ else
+ {
+ if (value.length() != 0 && value.charAt(0) == '\\')
+ {
+ value = value.substring(1);
+ }
+ if (oid.equals(dc))
+ {
+ return new DERIA5String(value);
+ }
+ else if (oid.equals(c) || oid.equals(serialNumber) || oid.equals(dnQualifier)
+ || oid.equals(telephoneNumber))
+ {
+ return new DERPrintableString(value);
+ }
+ }
+
+ return new DERUTF8String(value);
+ }
+
+ public String oidToDisplayName(ASN1ObjectIdentifier oid)
+ {
+ return (String)DefaultSymbols.get(oid);
+ }
+
+ public String[] oidToAttrNames(ASN1ObjectIdentifier oid)
+ {
+ return IETFUtils.findAttrNamesForOID(oid, defaultLookUp);
+ }
+
+ public ASN1ObjectIdentifier attrNameToOID(String attrName)
+ {
+ return IETFUtils.decodeAttrName(attrName, defaultLookUp);
+ }
+
+ public boolean areEqual(X500Name name1, X500Name name2)
+ {
+ RDN[] rdns1 = name1.getRDNs();
+ RDN[] rdns2 = name2.getRDNs();
+
+ if (rdns1.length != rdns2.length)
+ {
+ return false;
+ }
+
+ boolean reverse = false;
+
+ if (rdns1[0].getFirst() != null && rdns2[0].getFirst() != null)
+ {
+ reverse = !rdns1[0].getFirst().getType().equals(rdns2[0].getFirst().getType()); // guess forward
+ }
+
+ for (int i = 0; i != rdns1.length; i++)
+ {
+ if (!foundMatch(reverse, rdns1[i], rdns2))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private boolean foundMatch(boolean reverse, RDN rdn, RDN[] possRDNs)
+ {
+ if (reverse)
+ {
+ for (int i = possRDNs.length - 1; i >= 0; i--)
+ {
+ if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
+ {
+ possRDNs[i] = null;
+ return true;
+ }
+ }
+ }
+ else
+ {
+ for (int i = 0; i != possRDNs.length; i++)
+ {
+ if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
+ {
+ possRDNs[i] = null;
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ protected boolean rdnAreEqual(RDN rdn1, RDN rdn2)
+ {
+ return IETFUtils.rDNAreEqual(rdn1, rdn2);
+ }
+
+ // parse backwards
+ public RDN[] fromString(String dirName)
+ {
+ RDN[] tmp = IETFUtils.rDNsFromString(dirName, this);
+ RDN[] res = new RDN[tmp.length];
+
+ for (int i = 0; i != tmp.length; i++)
+ {
+ res[res.length - i - 1] = tmp[i];
+ }
+
+ return res;
+ }
+
+ public int calculateHashCode(X500Name name)
+ {
+ int hashCodeValue = 0;
+ RDN[] rdns = name.getRDNs();
+
+ // this needs to be order independent, like equals
+ for (int i = 0; i != rdns.length; i++)
+ {
+ if (rdns[i].isMultiValued())
+ {
+ AttributeTypeAndValue[] atv = rdns[i].getTypesAndValues();
+
+ for (int j = 0; j != atv.length; j++)
+ {
+ hashCodeValue ^= atv[j].getType().hashCode();
+ hashCodeValue ^= calcHashCode(atv[j].getValue());
+ }
+ }
+ else
+ {
+ hashCodeValue ^= rdns[i].getFirst().getType().hashCode();
+ hashCodeValue ^= calcHashCode(rdns[i].getFirst().getValue());
+ }
+ }
+
+ return hashCodeValue;
+ }
+
+ private int calcHashCode(ASN1Encodable enc)
+ {
+ String value = IETFUtils.valueToString(enc);
+
+ value = IETFUtils.canonicalize(value);
+
+ return value.hashCode();
+ }
+
+ // convert in reverse
+ public String toString(X500Name name)
+ {
+ StringBuffer buf = new StringBuffer();
+ boolean first = true;
+
+ RDN[] rdns = name.getRDNs();
+
+ for (int i = rdns.length - 1; i >= 0; i--)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ buf.append(',');
+ }
+
+ 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/core/src/main/jdk1.1/org/spongycastle/crypto/agreement/jpake/JPAKEParticipant.java b/core/src/main/jdk1.1/org/spongycastle/crypto/agreement/jpake/JPAKEParticipant.java
new file mode 100644
index 00000000..17554b96
--- /dev/null
+++ b/core/src/main/jdk1.1/org/spongycastle/crypto/agreement/jpake/JPAKEParticipant.java
@@ -0,0 +1,573 @@
+package org.spongycastle.crypto.agreement.jpake;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.util.Arrays;
+
+/**
+ * A participant in a Password Authenticated Key Exchange by Juggling (J-PAKE) exchange.
+ * <p/>
+ * <p/>
+ * The J-PAKE exchange is defined by Feng Hao and Peter Ryan in the paper
+ * <a href="http://grouper.ieee.org/groups/1363/Research/contributions/hao-ryan-2008.pdf">
+ * "Password Authenticated Key Exchange by Juggling, 2008."</a>
+ * <p/>
+ * <p/>
+ * The J-PAKE protocol is symmetric.
+ * There is no notion of a <i>client</i> or <i>server</i>, but rather just two <i>participants</i>.
+ * An instance of {@link JPAKEParticipant} represents one participant, and
+ * is the primary interface for executing the exchange.
+ * <p/>
+ * <p/>
+ * To execute an exchange, construct a {@link JPAKEParticipant} on each end,
+ * and call the following 7 methods
+ * (once and only once, in the given order, for each participant, sending messages between them as described):
+ * <ol>
+ * <li>{@link #createRound1PayloadToSend()} - and send the payload to the other participant</li>
+ * <li>{@link #validateRound1PayloadReceived(JPAKERound1Payload)} - use the payload received from the other participant</li>
+ * <li>{@link #createRound2PayloadToSend()} - and send the payload to the other participant</li>
+ * <li>{@link #validateRound2PayloadReceived(JPAKERound2Payload)} - use the payload received from the other participant</li>
+ * <li>{@link #calculateKeyingMaterial()}</li>
+ * <li>{@link #createRound3PayloadToSend(BigInteger)} - and send the payload to the other participant</li>
+ * <li>{@link #validateRound3PayloadReceived(JPAKERound3Payload, BigInteger)} - use the payload received from the other participant</li>
+ * </ol>
+ * <p/>
+ * <p/>
+ * Each side should derive a session key from the keying material returned by {@link #calculateKeyingMaterial()}.
+ * The caller is responsible for deriving the session key using a secure key derivation function (KDF).
+ * <p/>
+ * <p/>
+ * Round 3 is an optional key confirmation process.
+ * If you do not execute round 3, then there is no assurance that both participants are using the same key.
+ * (i.e. if the participants used different passwords, then their session keys will differ.)
+ * <p/>
+ * <p/>
+ * If the round 3 validation succeeds, then the keys are guaranteed to be the same on both sides.
+ * <p/>
+ * <p/>
+ * The symmetric design can easily support the asymmetric cases when one party initiates the communication.
+ * e.g. Sometimes the round1 payload and round2 payload may be sent in one pass.
+ * Also, in some cases, the key confirmation payload can be sent together with the round2 payload.
+ * These are the trivial techniques to optimize the communication.
+ * <p/>
+ * <p/>
+ * The key confirmation process is implemented as specified in
+ * <a href="http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf">NIST SP 800-56A Revision 1</a>,
+ * Section 8.2 Unilateral Key Confirmation for Key Agreement Schemes.
+ * <p/>
+ * <p/>
+ * This class is stateful and NOT threadsafe.
+ * Each instance should only be used for ONE complete J-PAKE exchange
+ * (i.e. a new {@link JPAKEParticipant} should be constructed for each new J-PAKE exchange).
+ * <p/>
+ * <p/>
+ * See {@link JPAKEExample} for example usage.
+ */
+public class JPAKEParticipant
+{
+ /*
+ * Possible internal states. Used for state checking.
+ */
+
+ public static final int STATE_INITIALIZED = 0;
+ public static final int STATE_ROUND_1_CREATED = 10;
+ public static final int STATE_ROUND_1_VALIDATED = 20;
+ public static final int STATE_ROUND_2_CREATED = 30;
+ public static final int STATE_ROUND_2_VALIDATED = 40;
+ public static final int STATE_KEY_CALCULATED = 50;
+ public static final int STATE_ROUND_3_CREATED = 60;
+ public static final int STATE_ROUND_3_VALIDATED = 70;
+
+ /**
+ * Unique identifier of this participant.
+ * The two participants in the exchange must NOT share the same id.
+ */
+ private String participantId;
+
+ /**
+ * Shared secret. This only contains the secret between construction
+ * and the call to {@link #calculateKeyingMaterial()}.
+ * <p/>
+ * i.e. When {@link #calculateKeyingMaterial()} is called, this buffer overwritten with 0's,
+ * and the field is set to null.
+ */
+ private char[] password;
+
+ /**
+ * Digest to use during calculations.
+ */
+ private Digest digest;
+
+ /**
+ * Source of secure random data.
+ */
+ private SecureRandom random;
+
+ private BigInteger p;
+ private BigInteger q;
+ private BigInteger g;
+
+ /**
+ * The participantId of the other participant in this exchange.
+ */
+ private String partnerParticipantId;
+
+ /**
+ * Alice's x1 or Bob's x3.
+ */
+ private BigInteger x1;
+ /**
+ * Alice's x2 or Bob's x4.
+ */
+ private BigInteger x2;
+ /**
+ * Alice's g^x1 or Bob's g^x3.
+ */
+ private BigInteger gx1;
+ /**
+ * Alice's g^x2 or Bob's g^x4.
+ */
+ private BigInteger gx2;
+ /**
+ * Alice's g^x3 or Bob's g^x1.
+ */
+ private BigInteger gx3;
+ /**
+ * Alice's g^x4 or Bob's g^x2.
+ */
+ private BigInteger gx4;
+ /**
+ * Alice's B or Bob's A.
+ */
+ private BigInteger b;
+
+ /**
+ * The current state.
+ * See the <tt>STATE_*</tt> constants for possible values.
+ */
+ private int state;
+
+ /**
+ * Convenience constructor for a new {@link JPAKEParticipant} that uses
+ * the {@link JPAKEPrimeOrderGroups#NIST_3072} prime order group,
+ * a SHA-256 digest, and a default {@link SecureRandom} implementation.
+ * <p/>
+ * After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}.
+ *
+ * @param participantId unique identifier of this participant.
+ * The two participants in the exchange must NOT share the same id.
+ * @param password shared secret.
+ * A defensive copy of this array is made (and cleared once {@link #calculateKeyingMaterial()} is called).
+ * Caller should clear the input password as soon as possible.
+ * @throws NullPointerException if any argument is null
+ * @throws IllegalArgumentException if password is empty
+ */
+ public JPAKEParticipant(
+ String participantId,
+ char[] password)
+ {
+ this(
+ participantId,
+ password,
+ JPAKEPrimeOrderGroups.NIST_3072);
+ }
+
+
+ /**
+ * Convenience constructor for a new {@link JPAKEParticipant} that uses
+ * a SHA-256 digest and a default {@link SecureRandom} implementation.
+ * <p/>
+ * After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}.
+ *
+ * @param participantId unique identifier of this participant.
+ * The two participants in the exchange must NOT share the same id.
+ * @param password shared secret.
+ * A defensive copy of this array is made (and cleared once {@link #calculateKeyingMaterial()} is called).
+ * Caller should clear the input password as soon as possible.
+ * @param group prime order group.
+ * See {@link JPAKEPrimeOrderGroups} for standard groups
+ * @throws NullPointerException if any argument is null
+ * @throws IllegalArgumentException if password is empty
+ */
+ public JPAKEParticipant(
+ String participantId,
+ char[] password,
+ JPAKEPrimeOrderGroup group)
+ {
+ this(
+ participantId,
+ password,
+ group,
+ new SHA256Digest(),
+ new SecureRandom());
+ }
+
+
+ /**
+ * Construct a new {@link JPAKEParticipant}.
+ * <p/>
+ * After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}.
+ *
+ * @param participantId unique identifier of this participant.
+ * The two participants in the exchange must NOT share the same id.
+ * @param password shared secret.
+ * A defensive copy of this array is made (and cleared once {@link #calculateKeyingMaterial()} is called).
+ * Caller should clear the input password as soon as possible.
+ * @param group prime order group.
+ * See {@link JPAKEPrimeOrderGroups} for standard groups
+ * @param digest digest to use during zero knowledge proofs and key confirmation (SHA-256 or stronger preferred)
+ * @param random source of secure random data for x1 and x2, and for the zero knowledge proofs
+ * @throws NullPointerException if any argument is null
+ * @throws IllegalArgumentException if password is empty
+ */
+ public JPAKEParticipant(
+ String participantId,
+ char[] password,
+ JPAKEPrimeOrderGroup group,
+ Digest digest,
+ SecureRandom random)
+ {
+ JPAKEUtil.validateNotNull(participantId, "participantId");
+ JPAKEUtil.validateNotNull(password, "password");
+ JPAKEUtil.validateNotNull(group, "p");
+ JPAKEUtil.validateNotNull(digest, "digest");
+ JPAKEUtil.validateNotNull(random, "random");
+ if (password.length == 0)
+ {
+ throw new IllegalArgumentException("Password must not be empty.");
+ }
+
+ this.participantId = participantId;
+
+ /*
+ * Create a defensive copy so as to fully encapsulate the password.
+ *
+ * This array will contain the password for the lifetime of this
+ * participant BEFORE {@link #calculateKeyingMaterial()} is called.
+ *
+ * i.e. When {@link #calculateKeyingMaterial()} is called, the array will be cleared
+ * in order to remove the password from memory.
+ *
+ * The caller is responsible for clearing the original password array
+ * given as input to this constructor.
+ */
+ this.password = Arrays.copyOf(password, password.length);
+
+ this.p = group.getP();
+ this.q = group.getQ();
+ this.g = group.getG();
+
+ this.digest = digest;
+ this.random = random;
+
+ this.state = STATE_INITIALIZED;
+ }
+
+ /**
+ * Gets the current state of this participant.
+ * See the <tt>STATE_*</tt> constants for possible values.
+ */
+ public int getState()
+ {
+ return this.state;
+ }
+
+ /**
+ * Creates and returns the payload to send to the other participant during round 1.
+ * <p/>
+ * <p/>
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_1_CREATED}.
+ */
+ public JPAKERound1Payload createRound1PayloadToSend()
+ {
+ if (this.state >= STATE_ROUND_1_CREATED)
+ {
+ throw new IllegalStateException("Round1 payload already created for " + participantId);
+ }
+
+ this.x1 = JPAKEUtil.generateX1(q, random);
+ this.x2 = JPAKEUtil.generateX2(q, random);
+
+ this.gx1 = JPAKEUtil.calculateGx(p, g, x1);
+ this.gx2 = JPAKEUtil.calculateGx(p, g, x2);
+ BigInteger[] knowledgeProofForX1 = JPAKEUtil.calculateZeroKnowledgeProof(p, q, g, gx1, x1, participantId, digest, random);
+ BigInteger[] knowledgeProofForX2 = JPAKEUtil.calculateZeroKnowledgeProof(p, q, g, gx2, x2, participantId, digest, random);
+
+ this.state = STATE_ROUND_1_CREATED;
+
+ return new JPAKERound1Payload(participantId, gx1, gx2, knowledgeProofForX1, knowledgeProofForX2);
+ }
+
+ /**
+ * Validates the payload received from the other participant during round 1.
+ * <p/>
+ * <p/>
+ * Must be called prior to {@link #createRound2PayloadToSend()}.
+ * <p/>
+ * <p/>
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_1_VALIDATED}.
+ *
+ * @throws CryptoException if validation fails.
+ * @throws IllegalStateException if called multiple times.
+ */
+ public void validateRound1PayloadReceived(JPAKERound1Payload round1PayloadReceived)
+ throws CryptoException
+ {
+ if (this.state >= STATE_ROUND_1_VALIDATED)
+ {
+ throw new IllegalStateException("Validation already attempted for round1 payload for" + participantId);
+ }
+ this.partnerParticipantId = round1PayloadReceived.getParticipantId();
+ this.gx3 = round1PayloadReceived.getGx1();
+ this.gx4 = round1PayloadReceived.getGx2();
+
+ BigInteger[] knowledgeProofForX3 = round1PayloadReceived.getKnowledgeProofForX1();
+ BigInteger[] knowledgeProofForX4 = round1PayloadReceived.getKnowledgeProofForX2();
+
+ JPAKEUtil.validateParticipantIdsDiffer(participantId, round1PayloadReceived.getParticipantId());
+ JPAKEUtil.validateGx4(gx4);
+ JPAKEUtil.validateZeroKnowledgeProof(p, q, g, gx3, knowledgeProofForX3, round1PayloadReceived.getParticipantId(), digest);
+ JPAKEUtil.validateZeroKnowledgeProof(p, q, g, gx4, knowledgeProofForX4, round1PayloadReceived.getParticipantId(), digest);
+
+ this.state = STATE_ROUND_1_VALIDATED;
+ }
+
+ /**
+ * Creates and returns the payload to send to the other participant during round 2.
+ * <p/>
+ * <p/>
+ * {@link #validateRound1PayloadReceived(JPAKERound1Payload)} must be called prior to this method.
+ * <p/>
+ * <p/>
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_2_CREATED}.
+ *
+ * @throws IllegalStateException if called prior to {@link #validateRound1PayloadReceived(JPAKERound1Payload)}, or multiple times
+ */
+ public JPAKERound2Payload createRound2PayloadToSend()
+ {
+ if (this.state >= STATE_ROUND_2_CREATED)
+ {
+ throw new IllegalStateException("Round2 payload already created for " + this.participantId);
+ }
+ if (this.state < STATE_ROUND_1_VALIDATED)
+ {
+ throw new IllegalStateException("Round1 payload must be validated prior to creating Round2 payload for " + this.participantId);
+ }
+ BigInteger gA = JPAKEUtil.calculateGA(p, gx1, gx3, gx4);
+ BigInteger s = JPAKEUtil.calculateS(password);
+ BigInteger x2s = JPAKEUtil.calculateX2s(q, x2, s);
+ BigInteger A = JPAKEUtil.calculateA(p, q, gA, x2s);
+ BigInteger[] knowledgeProofForX2s = JPAKEUtil.calculateZeroKnowledgeProof(p, q, gA, A, x2s, participantId, digest, random);
+
+ this.state = STATE_ROUND_2_CREATED;
+
+ return new JPAKERound2Payload(participantId, A, knowledgeProofForX2s);
+ }
+
+ /**
+ * Validates the payload received from the other participant during round 2.
+ * <p/>
+ * <p/>
+ * Note that this DOES NOT detect a non-common password.
+ * The only indication of a non-common password is through derivation
+ * of different keys (which can be detected explicitly by executing round 3 and round 4)
+ * <p/>
+ * <p/>
+ * Must be called prior to {@link #calculateKeyingMaterial()}.
+ * <p/>
+ * <p/>
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_2_VALIDATED}.
+ *
+ * @throws CryptoException if validation fails.
+ * @throws IllegalStateException if called prior to {@link #validateRound1PayloadReceived(JPAKERound1Payload)}, or multiple times
+ */
+ public void validateRound2PayloadReceived(JPAKERound2Payload round2PayloadReceived)
+ throws CryptoException
+ {
+ if (this.state >= STATE_ROUND_2_VALIDATED)
+ {
+ throw new IllegalStateException("Validation already attempted for round2 payload for" + participantId);
+ }
+ if (this.state < STATE_ROUND_1_VALIDATED)
+ {
+ throw new IllegalStateException("Round1 payload must be validated prior to validating Round2 payload for " + this.participantId);
+ }
+ BigInteger gB = JPAKEUtil.calculateGA(p, gx3, gx1, gx2);
+ this.b = round2PayloadReceived.getA();
+ BigInteger[] knowledgeProofForX4s = round2PayloadReceived.getKnowledgeProofForX2s();
+
+ JPAKEUtil.validateParticipantIdsDiffer(participantId, round2PayloadReceived.getParticipantId());
+ JPAKEUtil.validateParticipantIdsEqual(this.partnerParticipantId, round2PayloadReceived.getParticipantId());
+ JPAKEUtil.validateGa(gB);
+ JPAKEUtil.validateZeroKnowledgeProof(p, q, gB, b, knowledgeProofForX4s, round2PayloadReceived.getParticipantId(), digest);
+
+ this.state = STATE_ROUND_2_VALIDATED;
+ }
+
+ /**
+ * Calculates and returns the key material.
+ * A session key must be derived from this key material using a secure key derivation function (KDF).
+ * The KDF used to derive the key is handled externally (i.e. not by {@link JPAKEParticipant}).
+ * <p/>
+ * <p/>
+ * The keying material will be identical for each participant if and only if
+ * each participant's password is the same. i.e. If the participants do not
+ * share the same password, then each participant will derive a different key.
+ * Therefore, if you immediately start using a key derived from
+ * the keying material, then you must handle detection of incorrect keys.
+ * If you want to handle this detection explicitly, you can optionally perform
+ * rounds 3 and 4. See {@link JPAKEParticipant} for details on how to execute
+ * rounds 3 and 4.
+ * <p/>
+ * <p/>
+ * The keying material will be in the range <tt>[0, p-1]</tt>.
+ * <p/>
+ * <p/>
+ * {@link #validateRound2PayloadReceived(JPAKERound2Payload)} must be called prior to this method.
+ * <p/>
+ * <p/>
+ * As a side effect, the internal {@link #password} array is cleared, since it is no longer needed.
+ * <p/>
+ * <p/>
+ * After execution, the {@link #getState() state} will be {@link #STATE_KEY_CALCULATED}.
+ *
+ * @throws IllegalStateException if called prior to {@link #validateRound2PayloadReceived(JPAKERound2Payload)},
+ * or if called multiple times.
+ */
+ public BigInteger calculateKeyingMaterial()
+ {
+ if (this.state >= STATE_KEY_CALCULATED)
+ {
+ throw new IllegalStateException("Key already calculated for " + participantId);
+ }
+ if (this.state < STATE_ROUND_2_VALIDATED)
+ {
+ throw new IllegalStateException("Round2 payload must be validated prior to creating key for " + participantId);
+ }
+ BigInteger s = JPAKEUtil.calculateS(password);
+
+ /*
+ * Clear the password array from memory, since we don't need it anymore.
+ *
+ * Also set the field to null as a flag to indicate that the key has already been calculated.
+ */
+ Arrays.fill(password, (char)0);
+ this.password = null;
+
+ BigInteger keyingMaterial = JPAKEUtil.calculateKeyingMaterial(p, q, gx4, x2, s, b);
+
+ /*
+ * Clear the ephemeral private key fields as well.
+ * Note that we're relying on the garbage collector to do its job to clean these up.
+ * The old objects will hang around in memory until the garbage collector destroys them.
+ *
+ * If the ephemeral private keys x1 and x2 are leaked,
+ * the attacker might be able to brute-force the password.
+ */
+ this.x1 = null;
+ this.x2 = null;
+ this.b = null;
+
+ /*
+ * Do not clear gx* yet, since those are needed by round 3.
+ */
+
+ this.state = STATE_KEY_CALCULATED;
+
+ return keyingMaterial;
+ }
+
+
+ /**
+ * Creates and returns the payload to send to the other participant during round 3.
+ * <p/>
+ * <p/>
+ * See {@link JPAKEParticipant} for more details on round 3.
+ * <p/>
+ * <p/>
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_3_CREATED}.
+ *
+ * @param keyingMaterial The keying material as returned from {@link #calculateKeyingMaterial()}.
+ * @throws IllegalStateException if called prior to {@link #calculateKeyingMaterial()}, or multiple times
+ */
+ public JPAKERound3Payload createRound3PayloadToSend(BigInteger keyingMaterial)
+ {
+ if (this.state >= STATE_ROUND_3_CREATED)
+ {
+ throw new IllegalStateException("Round3 payload already created for " + this.participantId);
+ }
+ if (this.state < STATE_KEY_CALCULATED)
+ {
+ throw new IllegalStateException("Keying material must be calculated prior to creating Round3 payload for " + this.participantId);
+ }
+
+ BigInteger macTag = JPAKEUtil.calculateMacTag(
+ this.participantId,
+ this.partnerParticipantId,
+ this.gx1,
+ this.gx2,
+ this.gx3,
+ this.gx4,
+ keyingMaterial,
+ this.digest);
+
+ this.state = STATE_ROUND_3_CREATED;
+
+ return new JPAKERound3Payload(participantId, macTag);
+ }
+
+ /**
+ * Validates the payload received from the other participant during round 3.
+ * <p/>
+ * <p/>
+ * See {@link JPAKEParticipant} for more details on round 3.
+ * <p/>
+ * <p/>
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_3_VALIDATED}.
+ *
+ * @param keyingMaterial The keying material as returned from {@link #calculateKeyingMaterial()}.
+ * @throws CryptoException if validation fails.
+ * @throws IllegalStateException if called prior to {@link #calculateKeyingMaterial()}, or multiple times
+ */
+ public void validateRound3PayloadReceived(JPAKERound3Payload round3PayloadReceived, BigInteger keyingMaterial)
+ throws CryptoException
+ {
+ if (this.state >= STATE_ROUND_3_VALIDATED)
+ {
+ throw new IllegalStateException("Validation already attempted for round3 payload for" + participantId);
+ }
+ if (this.state < STATE_KEY_CALCULATED)
+ {
+ throw new IllegalStateException("Keying material must be calculated validated prior to validating Round3 payload for " + this.participantId);
+ }
+ JPAKEUtil.validateParticipantIdsDiffer(participantId, round3PayloadReceived.getParticipantId());
+ JPAKEUtil.validateParticipantIdsEqual(this.partnerParticipantId, round3PayloadReceived.getParticipantId());
+
+ JPAKEUtil.validateMacTag(
+ this.participantId,
+ this.partnerParticipantId,
+ this.gx1,
+ this.gx2,
+ this.gx3,
+ this.gx4,
+ keyingMaterial,
+ this.digest,
+ round3PayloadReceived.getMacTag());
+
+
+ /*
+ * Clear the rest of the fields.
+ */
+ this.gx1 = null;
+ this.gx2 = null;
+ this.gx3 = null;
+ this.gx4 = null;
+
+ this.state = STATE_ROUND_3_VALIDATED;
+ }
+
+}
diff --git a/core/src/main/jdk1.1/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java b/core/src/main/jdk1.1/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java
new file mode 100644
index 00000000..59e93385
--- /dev/null
+++ b/core/src/main/jdk1.1/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java
@@ -0,0 +1,122 @@
+package org.spongycastle.crypto.agreement.jpake;
+
+import java.math.BigInteger;
+
+/**
+ * A pre-computed prime order group for use during a J-PAKE exchange.
+ * <p/>
+ * <p/>
+ * Typically a Schnorr group is used. In general, J-PAKE can use any prime order group
+ * that is suitable for public key cryptography, including elliptic curve cryptography.
+ * <p/>
+ * <p/>
+ * See {@link JPAKEPrimeOrderGroups} for convenient standard groups.
+ * <p/>
+ * <p/>
+ * NIST <a href="http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/DSA2_All.pdf">publishes</a>
+ * many groups that can be used for the desired level of security.
+ */
+public class JPAKEPrimeOrderGroup
+{
+ private BigInteger p;
+ private BigInteger q;
+ private BigInteger g;
+
+ /**
+ * Constructs a new {@link JPAKEPrimeOrderGroup}.
+ * <p/>
+ * <p/>
+ * In general, you should use one of the pre-approved groups from
+ * {@link JPAKEPrimeOrderGroups}, rather than manually constructing one.
+ * <p/>
+ * <p/>
+ * The following basic checks are performed:
+ * <ul>
+ * <li>p-1 must be evenly divisible by q</li>
+ * <li>g must be in [2, p-1]</li>
+ * <li>g^q mod p must equal 1</li>
+ * <li>p must be prime (within reasonably certainty)</li>
+ * <li>q must be prime (within reasonably certainty)</li>
+ * </ul>
+ * <p/>
+ * <p/>
+ * The prime checks are performed using {@link BigInteger#isProbablePrime(int)},
+ * and are therefore subject to the same probability guarantees.
+ * <p/>
+ * <p/>
+ * These checks prevent trivial mistakes.
+ * However, due to the small uncertainties if p and q are not prime,
+ * advanced attacks are not prevented.
+ * Use it at your own risk.
+ *
+ * @throws NullPointerException if any argument is null
+ * @throws IllegalArgumentException if any of the above validations fail
+ */
+ public JPAKEPrimeOrderGroup(BigInteger p, BigInteger q, BigInteger g)
+ {
+ /*
+ * Don't skip the checks on user-specified groups.
+ */
+ this(p, q, g, false);
+ }
+
+ /**
+ * Internal package-private constructor used by the pre-approved
+ * groups in {@link JPAKEPrimeOrderGroups}.
+ * These pre-approved groups can avoid the expensive checks.
+ */
+ JPAKEPrimeOrderGroup(BigInteger p, BigInteger q, BigInteger g, boolean skipChecks)
+ {
+ JPAKEUtil.validateNotNull(p, "p");
+ JPAKEUtil.validateNotNull(q, "q");
+ JPAKEUtil.validateNotNull(g, "g");
+
+ if (!skipChecks)
+ {
+ if (!p.subtract(JPAKEUtil.ONE).mod(q).equals(JPAKEUtil.ZERO))
+ {
+ throw new IllegalArgumentException("p-1 must be evenly divisible by q");
+ }
+ if (g.compareTo(BigInteger.valueOf(2)) == -1 || g.compareTo(p.subtract(JPAKEUtil.ONE)) == 1)
+ {
+ throw new IllegalArgumentException("g must be in [2, p-1]");
+ }
+ if (!g.modPow(q, p).equals(JPAKEUtil.ONE))
+ {
+ throw new IllegalArgumentException("g^q mod p must equal 1");
+ }
+ /*
+ * Note that these checks do not guarantee that p and q are prime.
+ * We just have reasonable certainty that they are prime.
+ */
+ if (!p.isProbablePrime(20))
+ {
+ throw new IllegalArgumentException("p must be prime");
+ }
+ if (!q.isProbablePrime(20))
+ {
+ throw new IllegalArgumentException("q must be prime");
+ }
+ }
+
+ this.p = p;
+ this.q = q;
+ this.g = g;
+ }
+
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public BigInteger getG()
+ {
+ return g;
+ }
+
+}
diff --git a/core/src/main/jdk1.1/org/spongycastle/crypto/digests/SkeinEngine.java b/core/src/main/jdk1.1/org/spongycastle/crypto/digests/SkeinEngine.java
new file mode 100644
index 00000000..a278ff4e
--- /dev/null
+++ b/core/src/main/jdk1.1/org/spongycastle/crypto/digests/SkeinEngine.java
@@ -0,0 +1,817 @@
+package org.spongycastle.crypto.digests;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.engines.ThreefishEngine;
+import org.spongycastle.crypto.macs.SkeinMac;
+import org.spongycastle.crypto.params.SkeinParameters;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.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
+ */
+ private ThreefishEngine threefish;
+
+ /**
+ * Size of the digest output, in bytes
+ */
+ private 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 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/core/src/main/jdk1.1/org/spongycastle/crypto/encodings/PKCS1Encoding.java b/core/src/main/jdk1.1/org/spongycastle/crypto/encodings/PKCS1Encoding.java
new file mode 100644
index 00000000..7af31f36
--- /dev/null
+++ b/core/src/main/jdk1.1/org/spongycastle/crypto/encodings/PKCS1Encoding.java
@@ -0,0 +1,410 @@
+package org.spongycastle.crypto.encodings;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+
+/**
+ * this does your basic PKCS 1 v1.5 padding - whether or not you should be using this
+ * depends on your application - see PKCS1 Version 2 for details.
+ */
+public class PKCS1Encoding
+ implements AsymmetricBlockCipher
+{
+ /**
+ * some providers fail to include the leading zero in PKCS1 encoded blocks. If you need to
+ * work with one of these set the system property org.spongycastle.pkcs1.strict to false.
+ * <p>
+ * The system property is checked during construction of the encoding object, it is set to
+ * true by default.
+ * </p>
+ */
+ public static final String STRICT_LENGTH_ENABLED_PROPERTY = "org.spongycastle.pkcs1.strict";
+
+ private static final int HEADER_LENGTH = 10;
+
+ private SecureRandom random;
+ private AsymmetricBlockCipher engine;
+ private boolean forEncryption;
+ private boolean forPrivateKey;
+ private boolean useStrictLength;
+ private int pLen = -1;
+ private byte[] fallback = null;
+
+ /**
+ * Basic constructor.
+ * @param cipher
+ */
+ public PKCS1Encoding(
+ AsymmetricBlockCipher cipher)
+ {
+ this.engine = cipher;
+ this.useStrictLength = useStrict();
+ }
+
+ /**
+ * Constructor for decryption with a fixed plaintext length.
+ *
+ * @param cipher The cipher to use for cryptographic operation.
+ * @param pLen Length of the expected plaintext.
+ */
+ public PKCS1Encoding(
+ AsymmetricBlockCipher cipher,
+ int pLen)
+ {
+ this.engine = cipher;
+ this.useStrictLength = useStrict();
+ this.pLen = pLen;
+ }
+
+ /**
+ * Constructor for decryption with a fixed plaintext length and a fallback
+ * value that is returned, if the padding is incorrect.
+ *
+ * @param cipher
+ * The cipher to use for cryptographic operation.
+ * @param fallback
+ * The fallback value, we don't to a arraycopy here.
+ */
+ public PKCS1Encoding(
+ AsymmetricBlockCipher cipher,
+ byte[] fallback)
+ {
+ this.engine = cipher;
+ this.useStrictLength = useStrict();
+ this.fallback = fallback;
+ this.pLen = fallback.length;
+ }
+
+
+
+ //
+ // for J2ME compatibility
+ //
+ private boolean useStrict()
+ {
+ // required if security manager has been installed.
+ String strict = System.getProperty(STRICT_LENGTH_ENABLED_PROPERTY);
+
+ return strict == null || strict.equals("true");
+ }
+
+ public AsymmetricBlockCipher getUnderlyingCipher()
+ {
+ return engine;
+ }
+
+ public void init(
+ boolean forEncryption,
+ CipherParameters param)
+ {
+ AsymmetricKeyParameter kParam;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.random = rParam.getRandom();
+ kParam = (AsymmetricKeyParameter)rParam.getParameters();
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ kParam = (AsymmetricKeyParameter)param;
+ }
+
+ engine.init(forEncryption, param);
+
+ this.forPrivateKey = kParam.isPrivate();
+ this.forEncryption = forEncryption;
+ }
+
+ public int getInputBlockSize()
+ {
+ int baseBlockSize = engine.getInputBlockSize();
+
+ if (forEncryption)
+ {
+ return baseBlockSize - HEADER_LENGTH;
+ }
+ else
+ {
+ return baseBlockSize;
+ }
+ }
+
+ public int getOutputBlockSize()
+ {
+ int baseBlockSize = engine.getOutputBlockSize();
+
+ if (forEncryption)
+ {
+ return baseBlockSize;
+ }
+ else
+ {
+ return baseBlockSize - HEADER_LENGTH;
+ }
+ }
+
+ public byte[] processBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ if (forEncryption)
+ {
+ return encodeBlock(in, inOff, inLen);
+ }
+ else
+ {
+ return decodeBlock(in, inOff, inLen);
+ }
+ }
+
+ private byte[] encodeBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ if (inLen > getInputBlockSize())
+ {
+ throw new IllegalArgumentException("input data too large");
+ }
+
+ byte[] block = new byte[engine.getInputBlockSize()];
+
+ if (forPrivateKey)
+ {
+ block[0] = 0x01; // type code 1
+
+ for (int i = 1; i != block.length - inLen - 1; i++)
+ {
+ block[i] = (byte)0xFF;
+ }
+ }
+ else
+ {
+ random.nextBytes(block); // random fill
+
+ block[0] = 0x02; // type code 2
+
+ //
+ // a zero byte marks the end of the padding, so all
+ // the pad bytes must be non-zero.
+ //
+ for (int i = 1; i != block.length - inLen - 1; i++)
+ {
+ while (block[i] == 0)
+ {
+ block[i] = (byte)random.nextInt();
+ }
+ }
+ }
+
+ block[block.length - inLen - 1] = 0x00; // mark the end of the padding
+ System.arraycopy(in, inOff, block, block.length - inLen, inLen);
+
+ return engine.processBlock(block, 0, block.length);
+ }
+
+ /**
+ * Checks if the argument is a correctly PKCS#1.5 encoded Plaintext
+ * for encryption.
+ *
+ * @param encoded The Plaintext.
+ * @param pLen Expected length of the plaintext.
+ * @return Either 0, if the encoding is correct, or -1, if it is incorrect.
+ */
+ private static int checkPkcs1Encoding(byte[] encoded, int pLen) {
+ int correct = 0;
+ /*
+ * Check if the first two bytes are 0 2
+ */
+ correct |= (encoded[0] ^ 2);
+
+ /*
+ * Now the padding check, check for no 0 byte in the padding
+ */
+ int plen = encoded.length - (
+ pLen /* Lenght of the PMS */
+ + 1 /* Final 0-byte before PMS */
+ );
+
+ for (int i = 1; i < plen; i++) {
+ int tmp = encoded[i];
+ tmp |= tmp >> 1;
+ tmp |= tmp >> 2;
+ tmp |= tmp >> 4;
+ correct |= (tmp & 1) - 1;
+ }
+
+ /*
+ * Make sure the padding ends with a 0 byte.
+ */
+ correct |= encoded[encoded.length - (pLen +1)];
+
+ /*
+ * Return 0 or 1, depending on the result.
+ */
+ correct |= correct >> 1;
+ correct |= correct >> 2;
+ correct |= correct >> 4;
+ return ~((correct & 1) - 1);
+ }
+
+
+ /**
+ * Decode PKCS#1.5 encoding, and return a random value if the padding is not correct.
+ *
+ * @param in The encrypted block.
+ * @param inOff Offset in the encrypted block.
+ * @param inLen Length of the encrypted block.
+ * //@param pLen Length of the desired output.
+ * @return The plaintext without padding, or a random value if the padding was incorrect.
+ *
+ * @throws InvalidCipherTextException
+ */
+ private byte[] decodeBlockOrRandom(byte[] in, int inOff, int inLen)
+ throws InvalidCipherTextException
+ {
+ if (!forPrivateKey)
+ {
+ throw new InvalidCipherTextException("sorry, this method is only for decryption, not for signing");
+ }
+
+ byte[] block = engine.processBlock(in, inOff, inLen);
+ byte[] random = null;
+ if (this.fallback == null)
+ {
+ random = new byte[this.pLen];
+ this.random.nextBytes(random);
+ }
+ else
+ {
+ random = fallback;
+ }
+
+ /*
+ * TODO: This is a potential dangerous side channel. However, you can
+ * fix this by changing the RSA engine in a way, that it will always
+ * return blocks of the same length and prepend them with 0 bytes if
+ * needed.
+ */
+ if (block.length < getOutputBlockSize())
+ {
+ throw new InvalidCipherTextException("block truncated");
+ }
+
+ /*
+ * TODO: Potential side channel. Fix it by making the engine always
+ * return blocks of the correct length.
+ */
+ if (useStrictLength && block.length != engine.getOutputBlockSize())
+ {
+ throw new InvalidCipherTextException("block incorrect size");
+ }
+
+ /*
+ * Check the padding.
+ */
+ int correct = PKCS1Encoding.checkPkcs1Encoding(block, this.pLen);
+
+ /*
+ * Now, to a constant time constant memory copy of the decrypted value
+ * or the random value, depending on the validity of the padding.
+ */
+ byte[] result = new byte[this.pLen];
+ for (int i = 0; i < this.pLen; i++)
+ {
+ result[i] = (byte)((block[i + (block.length - pLen)] & (~correct)) | (random[i] & correct));
+ }
+
+ return result;
+ }
+
+ /**
+ * @exception InvalidCipherTextException if the decrypted block is not in PKCS1 format.
+ */
+ private byte[] decodeBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ /*
+ * If the length of the expected plaintext is known, we use a constant-time decryption.
+ * If the decryption fails, we return a random value.
+ */
+ if (this.pLen != -1) {
+ return this.decodeBlockOrRandom(in, inOff, inLen);
+ }
+
+ byte[] block = engine.processBlock(in, inOff, inLen);
+
+ if (block.length < getOutputBlockSize())
+ {
+ throw new InvalidCipherTextException("block truncated");
+ }
+
+ byte type = block[0];
+
+ if (forPrivateKey)
+ {
+ if (type != 2)
+ {
+ throw new InvalidCipherTextException("unknown block type");
+ }
+ }
+ else
+ {
+ if (type != 1)
+ {
+ throw new InvalidCipherTextException("unknown block type");
+ }
+ }
+
+ if (useStrictLength && block.length != engine.getOutputBlockSize())
+ {
+ throw new InvalidCipherTextException("block incorrect size");
+ }
+
+ //
+ // find and extract the message block.
+ //
+ int start;
+
+ for (start = 1; start != block.length; start++)
+ {
+ byte pad = block[start];
+
+ if (pad == 0)
+ {
+ break;
+ }
+ if (type == 1 && pad != (byte)0xff)
+ {
+ throw new InvalidCipherTextException("block padding incorrect");
+ }
+ }
+
+ start++; // data should start at the next byte
+
+ if (start > block.length || start < HEADER_LENGTH)
+ {
+ throw new InvalidCipherTextException("no data in block");
+ }
+
+ byte[] result = new byte[block.length - start];
+
+ System.arraycopy(block, start, result, 0, result.length);
+
+ return result;
+ }
+}
diff --git a/core/src/main/jdk1.1/org/spongycastle/crypto/engines/NullEngine.java b/core/src/main/jdk1.1/org/spongycastle/crypto/engines/NullEngine.java
new file mode 100644
index 00000000..21927272
--- /dev/null
+++ b/core/src/main/jdk1.1/org/spongycastle/crypto/engines/NullEngine.java
@@ -0,0 +1,96 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+
+/**
+ * The no-op engine that just copies bytes through, irrespective of whether encrypting and decrypting.
+ * Provided for the sake of completeness.
+ */
+public class NullEngine implements BlockCipher
+{
+ private boolean initialised;
+ protected static final int DEFAULT_BLOCK_SIZE = 1;
+ private int blockSize;
+
+ /**
+ * Constructs a null engine with a block size of 1 byte.
+ */
+ public NullEngine()
+ {
+ 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)
+ * @see org.spongycastle.crypto.BlockCipher#init(boolean, org.spongycastle.crypto.CipherParameters)
+ */
+ public void init(boolean forEncryption, CipherParameters params) throws IllegalArgumentException
+ {
+ // we don't mind any parameters that may come in
+ this.initialised = true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.spongycastle.crypto.BlockCipher#getAlgorithmName()
+ */
+ public String getAlgorithmName()
+ {
+ return "Null";
+ }
+
+ /* (non-Javadoc)
+ * @see org.spongycastle.crypto.BlockCipher#getBlockSize()
+ */
+ public int getBlockSize()
+ {
+ return blockSize;
+ }
+
+ /* (non-Javadoc)
+ * @see org.spongycastle.crypto.BlockCipher#processBlock(byte[], int, byte[], int)
+ */
+ public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException("Null engine not initialised");
+ }
+ 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];
+ }
+
+ return blockSize;
+ }
+
+ /* (non-Javadoc)
+ * @see org.spongycastle.crypto.BlockCipher#reset()
+ */
+ public void reset()
+ {
+ // nothing needs to be done
+ }
+}
diff --git a/core/src/main/jdk1.1/org/spongycastle/crypto/params/DSAParameterGenerationParameters.java b/core/src/main/jdk1.1/org/spongycastle/crypto/params/DSAParameterGenerationParameters.java
new file mode 100644
index 00000000..2b57f23c
--- /dev/null
+++ b/core/src/main/jdk1.1/org/spongycastle/crypto/params/DSAParameterGenerationParameters.java
@@ -0,0 +1,80 @@
+package org.spongycastle.crypto.params;
+
+import java.security.SecureRandom;
+
+public class DSAParameterGenerationParameters
+{
+ public static final int DIGITAL_SIGNATURE_USAGE = 1;
+ public static final int KEY_ESTABLISHMENT_USAGE = 2;
+
+ private int l;
+ private int n;
+ private int usageIndex;
+ private int certainty;
+ private SecureRandom random;
+
+ /**
+ * Construct without a usage index, this will do a random construction of G.
+ *
+ * @param L desired length of prime P in bits (the effective key size).
+ * @param N desired length of prime Q in bits.
+ * @param certainty certainty level for prime number generation.
+ * @param random the source of randomness to use.
+ */
+ public DSAParameterGenerationParameters(
+ int L,
+ int N,
+ int certainty,
+ SecureRandom random)
+ {
+ this(L, N, certainty, random, -1);
+ }
+
+ /**
+ * Construct for a specific usage index - this has the effect of using verifiable canonical generation of G.
+ *
+ * @param L desired length of prime P in bits (the effective key size).
+ * @param N desired length of prime Q in bits.
+ * @param certainty certainty level for prime number generation.
+ * @param random the source of randomness to use.
+ * @param usageIndex a valid usage index.
+ */
+ public DSAParameterGenerationParameters(
+ int L,
+ int N,
+ int certainty,
+ SecureRandom random,
+ int usageIndex)
+ {
+ this.l = L;
+ this.n = N;
+ this.certainty = certainty;
+ this.usageIndex = usageIndex;
+ this.random = random;
+ }
+
+ public int getL()
+ {
+ return l;
+ }
+
+ public int getN()
+ {
+ return n;
+ }
+
+ public int getCertainty()
+ {
+ return certainty;
+ }
+
+ public SecureRandom getRandom()
+ {
+ return random;
+ }
+
+ public int getUsageIndex()
+ {
+ return usageIndex;
+ }
+}
diff --git a/core/src/main/jdk1.1/org/spongycastle/crypto/params/HKDFParameters.java b/core/src/main/jdk1.1/org/spongycastle/crypto/params/HKDFParameters.java
new file mode 100644
index 00000000..4b125a7c
--- /dev/null
+++ b/core/src/main/jdk1.1/org/spongycastle/crypto/params/HKDFParameters.java
@@ -0,0 +1,123 @@
+package org.spongycastle.crypto.params;
+
+import org.spongycastle.crypto.DerivationParameters;
+import org.spongycastle.util.Arrays;
+
+/**
+ * Parameter class for the HKDFBytesGenerator class.
+ */
+public class HKDFParameters
+ implements DerivationParameters
+{
+ private byte[] ikm;
+ private boolean skipExpand;
+ private byte[] salt;
+ private byte[] info;
+
+ private HKDFParameters(final byte[] ikm, final boolean skip,
+ final byte[] salt, final byte[] info)
+ {
+ if (ikm == null)
+ {
+ throw new IllegalArgumentException(
+ "IKM (input keying material) should not be null");
+ }
+
+ this.ikm = Arrays.clone(ikm);
+
+ this.skipExpand = skip;
+
+ if (salt == null || salt.length == 0)
+ {
+ this.salt = null;
+ }
+ else
+ {
+ this.salt = Arrays.clone(salt);
+ }
+
+ if (info == null)
+ {
+ this.info = new byte[0];
+ }
+ else
+ {
+ this.info = Arrays.clone(info);
+ }
+ }
+
+ /**
+ * Generates parameters for HKDF, specifying both the optional salt and
+ * optional info. Step 1: Extract won't be skipped.
+ *
+ * @param ikm the input keying material or seed
+ * @param salt the salt to use, may be null for a salt for hashLen zeros
+ * @param info the info to use, may be null for an info field of zero bytes
+ */
+ public HKDFParameters(final byte[] ikm, final byte[] salt, final byte[] info)
+ {
+ this(ikm, false, salt, info);
+ }
+
+ /**
+ * Factory method that makes the HKDF skip the extract part of the key
+ * derivation function.
+ *
+ * @param ikm the input keying material or seed, directly used for step 2:
+ * Expand
+ * @param info the info to use, may be null for an info field of zero bytes
+ * @return HKDFParameters that makes the implementation skip step 1
+ */
+ public static HKDFParameters skipExtractParameters(final byte[] ikm,
+ final byte[] info)
+ {
+
+ return new HKDFParameters(ikm, true, null, info);
+ }
+
+ public static HKDFParameters defaultParameters(final byte[] ikm)
+ {
+ return new HKDFParameters(ikm, false, null, null);
+ }
+
+ /**
+ * Returns the input keying material or seed.
+ *
+ * @return the keying material
+ */
+ public byte[] getIKM()
+ {
+ return Arrays.clone(ikm);
+ }
+
+ /**
+ * Returns if step 1: extract has to be skipped or not
+ *
+ * @return true for skipping, false for no skipping of step 1
+ */
+ public boolean skipExtract()
+ {
+ return skipExpand;
+ }
+
+ /**
+ * Returns the salt, or null if the salt should be generated as a byte array
+ * of HashLen zeros.
+ *
+ * @return the salt, or null
+ */
+ public byte[] getSalt()
+ {
+ return Arrays.clone(salt);
+ }
+
+ /**
+ * Returns the info field, which may be empty (null is converted to empty).
+ *
+ * @return the info field, never null
+ */
+ public byte[] getInfo()
+ {
+ return Arrays.clone(info);
+ }
+}
diff --git a/core/src/main/jdk1.1/org/spongycastle/crypto/prng/BasicEntropySourceProvider.java b/core/src/main/jdk1.1/org/spongycastle/crypto/prng/BasicEntropySourceProvider.java
new file mode 100644
index 00000000..31c85036
--- /dev/null
+++ b/core/src/main/jdk1.1/org/spongycastle/crypto/prng/BasicEntropySourceProvider.java
@@ -0,0 +1,57 @@
+package org.spongycastle.crypto.prng;
+
+import java.security.SecureRandom;
+
+/**
+ * An EntropySourceProvider where entropy generation is based on a SecureRandom output using SecureRandom.generateSeed().
+ */
+public class BasicEntropySourceProvider
+ implements EntropySourceProvider
+{
+ private SecureRandom _sr;
+ private boolean _predictionResistant;
+
+ /**
+ * Create a entropy source provider based on the passed in SecureRandom.
+ *
+ * @param random the SecureRandom to base EntropySource construction on.
+ * @param isPredictionResistant boolean indicating if the SecureRandom is based on prediction resistant entropy or not (true if it is).
+ */
+ public BasicEntropySourceProvider(SecureRandom random, boolean isPredictionResistant)
+ {
+ _sr = random;
+ _predictionResistant = isPredictionResistant;
+ }
+
+ /**
+ * Return an entropy source that will create bitsRequired bits of entropy on
+ * each invocation of getEntropy().
+ *
+ * @param bitsRequired size (in bits) of entropy to be created by the provided source.
+ * @return an EntropySource that generates bitsRequired bits of entropy on each call to its getEntropy() method.
+ */
+ public EntropySource get(final int bitsRequired)
+ {
+ return new EntropySource()
+ {
+ public boolean isPredictionResistant()
+ {
+ return _predictionResistant;
+ }
+
+ public byte[] getEntropy()
+ {
+ byte[] rv = new byte[(bitsRequired + 7) / 8];
+
+ _sr.nextBytes(rv);
+
+ return rv;
+ }
+
+ public int entropySize()
+ {
+ return bitsRequired;
+ }
+ };
+ }
+}
diff --git a/core/src/main/jdk1.1/org/spongycastle/crypto/prng/SP800SecureRandomBuilder.java b/core/src/main/jdk1.1/org/spongycastle/crypto/prng/SP800SecureRandomBuilder.java
new file mode 100644
index 00000000..e682f687
--- /dev/null
+++ b/core/src/main/jdk1.1/org/spongycastle/crypto/prng/SP800SecureRandomBuilder.java
@@ -0,0 +1,289 @@
+package org.spongycastle.crypto.prng;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.prng.drbg.CTRSP800DRBG;
+import org.spongycastle.crypto.prng.drbg.DualECPoints;
+import org.spongycastle.crypto.prng.drbg.DualECSP800DRBG;
+import org.spongycastle.crypto.prng.drbg.HMacSP800DRBG;
+import org.spongycastle.crypto.prng.drbg.HashSP800DRBG;
+import org.spongycastle.crypto.prng.drbg.SP80090DRBG;
+
+/**
+ * Builder class for making SecureRandom objects based on SP 800-90A Deterministic Random Bit Generators (DRBG).
+ */
+public class SP800SecureRandomBuilder
+{
+ private SecureRandom random;
+ private EntropySourceProvider entropySourceProvider;
+
+ private byte[] personalizationString;
+ private int securityStrength = 256;
+ private int entropyBitsRequired = 256;
+
+ /**
+ * Basic constructor, creates a builder using an EntropySourceProvider based on the default SecureRandom with
+ * predictionResistant set to false.
+ * <p>
+ * Any SecureRandom created from a builder constructed like this will make use of input passed to SecureRandom.setSeed() if
+ * the default SecureRandom does for its generateSeed() call.
+ * </p>
+ */
+ public SP800SecureRandomBuilder()
+ {
+ this(new SecureRandom(), false);
+ }
+
+ /**
+ * Construct a builder with an EntropySourceProvider based on the passed in SecureRandom and the passed in value
+ * for prediction resistance.
+ * <p>
+ * Any SecureRandom created from a builder constructed like this will make use of input passed to SecureRandom.setSeed() if
+ * the passed in SecureRandom does for its generateSeed() call.
+ * </p>
+ * @param entropySource
+ * @param predictionResistant
+ */
+ public SP800SecureRandomBuilder(SecureRandom entropySource, boolean predictionResistant)
+ {
+ this.random = entropySource;
+ this.entropySourceProvider = new BasicEntropySourceProvider(random, predictionResistant);
+ }
+
+ /**
+ * Create a builder which makes creates the SecureRandom objects from a specified entropy source provider.
+ * <p>
+ * <b>Note:</b> If this constructor is used any calls to setSeed() in the resulting SecureRandom will be ignored.
+ * </p>
+ * @param entropySourceProvider a provider of EntropySource objects.
+ */
+ public SP800SecureRandomBuilder(EntropySourceProvider entropySourceProvider)
+ {
+ this.random = null;
+ this.entropySourceProvider = entropySourceProvider;
+ }
+
+ /**
+ * Set the personalization string for DRBG SecureRandoms created by this builder
+ * @param personalizationString the personalisation string for the underlying DRBG.
+ * @return the current builder.
+ */
+ public SP800SecureRandomBuilder setPersonalizationString(byte[] personalizationString)
+ {
+ this.personalizationString = personalizationString;
+
+ return this;
+ }
+
+ /**
+ * Set the security strength required for DRBGs used in building SecureRandom objects.
+ *
+ * @param securityStrength the security strength (in bits)
+ * @return the current builder.
+ */
+ public SP800SecureRandomBuilder setSecurityStrength(int securityStrength)
+ {
+ this.securityStrength = securityStrength;
+
+ return this;
+ }
+
+ /**
+ * Set the amount of entropy bits required for seeding and reseeding DRBGs used in building SecureRandom objects.
+ *
+ * @param entropyBitsRequired the number of bits of entropy to be requested from the entropy source on each seed/reseed.
+ * @return the current builder.
+ */
+ public SP800SecureRandomBuilder setEntropyBitsRequired(int entropyBitsRequired)
+ {
+ this.entropyBitsRequired = entropyBitsRequired;
+
+ return this;
+ }
+
+ /**
+ * Build a SecureRandom based on a SP 800-90A Hash DRBG.
+ *
+ * @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 Hash DRBG.
+ */
+ public SP800SecureRandom buildHash(Digest digest, byte[] nonce, boolean predictionResistant)
+ {
+ return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new HashDRBGProvider(digest, nonce, personalizationString, securityStrength), predictionResistant);
+ }
+
+ /**
+ * Build a SecureRandom based on a SP 800-90A CTR DRBG.
+ *
+ * @param cipher the block cipher to base the DRBG on.
+ * @param keySizeInBits key size in bits to be used with the block cipher.
+ * @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 CTR DRBG.
+ */
+ public SP800SecureRandom buildCTR(BlockCipher cipher, int keySizeInBits, byte[] nonce, boolean predictionResistant)
+ {
+ return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new CTRDRBGProvider(cipher, keySizeInBits, nonce, personalizationString, securityStrength), predictionResistant);
+ }
+
+ /**
+ * Build a SecureRandom based on a SP 800-90A HMAC DRBG.
+ *
+ * @param hMac HMAC 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 HMAC DRBG.
+ */
+ public SP800SecureRandom buildHMAC(Mac hMac, byte[] nonce, boolean predictionResistant)
+ {
+ return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new HMacDRBGProvider(hMac, nonce, personalizationString, securityStrength), predictionResistant);
+ }
+
+ /**
+ * Build a SecureRandom based on a SP 800-90A Dual EC DRBG.
+ *
+ * @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(Digest digest, byte[] nonce, boolean predictionResistant)
+ {
+ 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.
+ *
+ * @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
+ {
+ private final Digest digest;
+ private final byte[] nonce;
+ private final byte[] personalizationString;
+ private final int securityStrength;
+
+ public HashDRBGProvider(Digest digest, byte[] nonce, byte[] personalizationString, int securityStrength)
+ {
+ this.digest = digest;
+ this.nonce = nonce;
+ this.personalizationString = personalizationString;
+ this.securityStrength = securityStrength;
+ }
+
+ public SP80090DRBG get(EntropySource entropySource)
+ {
+ return new HashSP800DRBG(digest, securityStrength, entropySource, personalizationString, nonce);
+ }
+ }
+
+ private static class DualECDRBGProvider
+ implements DRBGProvider
+ {
+ private final Digest digest;
+ private final byte[] nonce;
+ private final byte[] personalizationString;
+ private final int securityStrength;
+
+ public DualECDRBGProvider(Digest digest, byte[] nonce, byte[] personalizationString, int securityStrength)
+ {
+ this.digest = digest;
+ this.nonce = nonce;
+ this.personalizationString = personalizationString;
+ this.securityStrength = securityStrength;
+ }
+
+ public SP80090DRBG get(EntropySource entropySource)
+ {
+ return new DualECSP800DRBG(digest, securityStrength, entropySource, personalizationString, nonce);
+ }
+ }
+
+ 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
+ {
+ private final Mac hMac;
+ private final byte[] nonce;
+ private final byte[] personalizationString;
+ private final int securityStrength;
+
+ public HMacDRBGProvider(Mac hMac, byte[] nonce, byte[] personalizationString, int securityStrength)
+ {
+ this.hMac = hMac;
+ this.nonce = nonce;
+ this.personalizationString = personalizationString;
+ this.securityStrength = securityStrength;
+ }
+
+ public SP80090DRBG get(EntropySource entropySource)
+ {
+ return new HMacSP800DRBG(hMac, securityStrength, entropySource, personalizationString, nonce);
+ }
+ }
+
+ private static class CTRDRBGProvider
+ implements DRBGProvider
+ {
+
+ private final BlockCipher blockCipher;
+ private final int keySizeInBits;
+ private final byte[] nonce;
+ private final byte[] personalizationString;
+ private final int securityStrength;
+
+ public CTRDRBGProvider(BlockCipher blockCipher, int keySizeInBits, byte[] nonce, byte[] personalizationString, int securityStrength)
+ {
+ this.blockCipher = blockCipher;
+ this.keySizeInBits = keySizeInBits;
+ this.nonce = nonce;
+ this.personalizationString = personalizationString;
+ this.securityStrength = securityStrength;
+ }
+
+ public SP80090DRBG get(EntropySource entropySource)
+ {
+ return new CTRSP800DRBG(blockCipher, keySizeInBits, securityStrength, entropySource, personalizationString, nonce);
+ }
+ }
+}
diff --git a/core/src/main/jdk1.1/org/spongycastle/crypto/signers/RSADigestSigner.java b/core/src/main/jdk1.1/org/spongycastle/crypto/signers/RSADigestSigner.java
new file mode 100644
index 00000000..e6a99d89
--- /dev/null
+++ b/core/src/main/jdk1.1/org/spongycastle/crypto/signers/RSADigestSigner.java
@@ -0,0 +1,238 @@
+package org.spongycastle.crypto.signers;
+
+import java.io.IOException;
+import java.util.Hashtable;
+
+import org.spongycastle.asn1.ASN1Encoding;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.DERNull;
+import org.spongycastle.asn1.nist.NISTObjectIdentifiers;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.DigestInfo;
+import org.spongycastle.asn1.x509.X509ObjectIdentifiers;
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.Signer;
+import org.spongycastle.crypto.encodings.PKCS1Encoding;
+import org.spongycastle.crypto.engines.RSABlindedEngine;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.util.Arrays;
+
+public class RSADigestSigner
+ implements Signer
+{
+ private final AsymmetricBlockCipher rsaEngine = new PKCS1Encoding(new RSABlindedEngine());
+ private AlgorithmIdentifier algId;
+ private Digest digest;
+ private boolean forSigning;
+
+ private static final Hashtable oidMap = new Hashtable();
+
+ /*
+ * Load OID table.
+ */
+ static
+ {
+ oidMap.put("RIPEMD128", TeleTrusTObjectIdentifiers.ripemd128);
+ oidMap.put("RIPEMD160", TeleTrusTObjectIdentifiers.ripemd160);
+ oidMap.put("RIPEMD256", TeleTrusTObjectIdentifiers.ripemd256);
+
+ oidMap.put("SHA-1", X509ObjectIdentifiers.id_SHA1);
+ oidMap.put("SHA-224", NISTObjectIdentifiers.id_sha224);
+ oidMap.put("SHA-256", NISTObjectIdentifiers.id_sha256);
+ oidMap.put("SHA-384", NISTObjectIdentifiers.id_sha384);
+ oidMap.put("SHA-512", NISTObjectIdentifiers.id_sha512);
+
+ oidMap.put("MD2", PKCSObjectIdentifiers.md2);
+ oidMap.put("MD4", PKCSObjectIdentifiers.md4);
+ oidMap.put("MD5", PKCSObjectIdentifiers.md5);
+ }
+
+ public RSADigestSigner(
+ Digest digest)
+ {
+ this(digest, (ASN1ObjectIdentifier)oidMap.get(digest.getAlgorithmName()));
+ }
+
+ public RSADigestSigner(
+ Digest digest,
+ ASN1ObjectIdentifier digestOid)
+ {
+ this.digest = digest;
+ this.algId = new AlgorithmIdentifier(digestOid, DERNull.INSTANCE);
+ }
+
+ /**
+ * @deprecated
+ */
+ public String getAlgorithmName()
+ {
+ return digest.getAlgorithmName() + "withRSA";
+ }
+
+ /**
+ * initialise the signer for signing or verification.
+ *
+ * @param forSigning
+ * true if for signing, false otherwise
+ * @param parameters
+ * necessary parameters.
+ */
+ public void init(
+ boolean forSigning,
+ CipherParameters parameters)
+ {
+ this.forSigning = forSigning;
+ AsymmetricKeyParameter k;
+
+ if (parameters instanceof ParametersWithRandom)
+ {
+ k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).getParameters();
+ }
+ else
+ {
+ k = (AsymmetricKeyParameter)parameters;
+ }
+
+ if (forSigning && !k.isPrivate())
+ {
+ throw new IllegalArgumentException("signing requires private key");
+ }
+
+ if (!forSigning && k.isPrivate())
+ {
+ throw new IllegalArgumentException("verification requires public key");
+ }
+
+ reset();
+
+ rsaEngine.init(forSigning, parameters);
+ }
+
+ /**
+ * update the internal digest with the byte b
+ */
+ public void update(
+ byte input)
+ {
+ digest.update(input);
+ }
+
+ /**
+ * update the internal digest with the byte array in
+ */
+ public void update(
+ byte[] input,
+ int inOff,
+ int length)
+ {
+ digest.update(input, inOff, length);
+ }
+
+ /**
+ * Generate a signature for the message we've been loaded with using the key
+ * we were initialised with.
+ */
+ public byte[] generateSignature()
+ throws CryptoException, DataLengthException
+ {
+ if (!forSigning)
+ {
+ throw new IllegalStateException("RSADigestSigner not initialised for signature generation.");
+ }
+
+ byte[] hash = new byte[digest.getDigestSize()];
+ digest.doFinal(hash, 0);
+
+ try
+ {
+ byte[] data = derEncode(hash);
+ return rsaEngine.processBlock(data, 0, data.length);
+ }
+ catch (IOException e)
+ {
+ throw new CryptoException("unable to encode signature: " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * return true if the internal state represents the signature described in
+ * the passed in array.
+ */
+ public boolean verifySignature(
+ byte[] signature)
+ {
+ if (forSigning)
+ {
+ throw new IllegalStateException("RSADigestSigner not initialised for verification");
+ }
+
+ byte[] hash = new byte[digest.getDigestSize()];
+
+ digest.doFinal(hash, 0);
+
+ byte[] sig;
+ byte[] expected;
+
+ try
+ {
+ sig = rsaEngine.processBlock(signature, 0, signature.length);
+ expected = derEncode(hash);
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+
+ if (sig.length == expected.length)
+ {
+ return Arrays.constantTimeAreEqual(sig, expected);
+ }
+ else if (sig.length == expected.length - 2) // NULL left out
+ {
+ int sigOffset = sig.length - hash.length - 2;
+ int expectedOffset = expected.length - hash.length - 2;
+
+ expected[1] -= 2; // adjust lengths
+ expected[3] -= 2;
+
+ int nonEqual = 0;
+
+ for (int i = 0; i < hash.length; i++)
+ {
+ nonEqual |= (sig[sigOffset + i] ^ expected[expectedOffset + i]);
+ }
+
+ for (int i = 0; i < sigOffset; i++)
+ {
+ nonEqual |= (sig[i] ^ expected[i]); // check header less NULL
+ }
+
+ return nonEqual == 0;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public void reset()
+ {
+ digest.reset();
+ }
+
+ private byte[] derEncode(
+ byte[] hash)
+ throws IOException
+ {
+ DigestInfo dInfo = new DigestInfo(algId, hash);
+
+ return dInfo.getEncoded(ASN1Encoding.DER);
+ }
+}
diff --git a/core/src/main/jdk1.1/org/spongycastle/crypto/tls/AbstractTlsContext.java b/core/src/main/jdk1.1/org/spongycastle/crypto/tls/AbstractTlsContext.java
new file mode 100644
index 00000000..cd6f7a8c
--- /dev/null
+++ b/core/src/main/jdk1.1/org/spongycastle/crypto/tls/AbstractTlsContext.java
@@ -0,0 +1,135 @@
+package org.spongycastle.crypto.tls;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.prng.DigestRandomGenerator;
+import org.spongycastle.crypto.prng.RandomGenerator;
+import org.spongycastle.util.Times;
+
+abstract class AbstractTlsContext
+ implements TlsContext
+{
+ private static long counter = Times.nanoTime();
+
+ private synchronized static long nextCounterValue()
+ {
+ return ++counter;
+ }
+
+ private RandomGenerator nonceRandom;
+ 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)
+ {
+ secureRandom.setSeed(nextCounterValue());
+ secureRandom.setSeed(Times.nanoTime());
+
+ this.nonceRandom = new DigestRandomGenerator(TlsUtils.createHash(HashAlgorithm.sha256));
+ byte[] nonceSeed = new byte[32];
+ secureRandom.nextBytes(nonceSeed);
+ this.nonceRandom.addSeedMaterial(nonceSeed);
+
+ this.secureRandom = secureRandom;
+ this.securityParameters = securityParameters;
+ }
+
+ public RandomGenerator getNonceRandomGenerator()
+ {
+ return nonceRandom;
+ }
+
+ public SecureRandom getSecureRandom()
+ {
+ return secureRandom;
+ }
+
+ public SecurityParameters getSecurityParameters()
+ {
+ return securityParameters;
+ }
+
+ public ProtocolVersion getClientVersion()
+ {
+ return clientVersion;
+ }
+
+ void setClientVersion(ProtocolVersion clientVersion)
+ {
+ this.clientVersion = clientVersion;
+ }
+
+ public ProtocolVersion getServerVersion()
+ {
+ return 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;
+ }
+
+ public void setUserObject(Object userObject)
+ {
+ this.userObject = userObject;
+ }
+
+ 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();
+
+ int seedLength = cr.length + sr.length;
+ if (context_value != null)
+ {
+ seedLength += (2 + context_value.length);
+ }
+
+ byte[] seed = new byte[seedLength];
+ int seedPos = 0;
+
+ System.arraycopy(cr, 0, seed, seedPos, cr.length);
+ seedPos += cr.length;
+ System.arraycopy(sr, 0, seed, seedPos, sr.length);
+ seedPos += sr.length;
+ if (context_value != null)
+ {
+ TlsUtils.writeUint16(context_value.length, seed, seedPos);
+ seedPos += 2;
+ System.arraycopy(context_value, 0, seed, seedPos, context_value.length);
+ seedPos += context_value.length;
+ }
+
+ if (seedPos != seedLength)
+ {
+ throw new IllegalStateException("error in calculation of seed for export");
+ }
+
+ return TlsUtils.PRF(this, sp.getMasterSecret(), asciiLabel, seed, length);
+ }
+}
diff --git a/core/src/main/jdk1.1/org/spongycastle/crypto/tls/DTLSReassembler.java b/core/src/main/jdk1.1/org/spongycastle/crypto/tls/DTLSReassembler.java
new file mode 100644
index 00000000..baf9c92f
--- /dev/null
+++ b/core/src/main/jdk1.1/org/spongycastle/crypto/tls/DTLSReassembler.java
@@ -0,0 +1,136 @@
+package org.spongycastle.crypto.tls;
+
+import java.util.Vector;
+
+class DTLSReassembler
+{
+
+ private short msg_type;
+ private byte[] body;
+
+ private Vector missing = new Vector();
+
+ DTLSReassembler(short msg_type, int length)
+ {
+ this.msg_type = msg_type;
+ this.body = new byte[length];
+ this.missing.addElement(new Range(0, length));
+ }
+
+ short getType()
+ {
+ return msg_type;
+ }
+
+ byte[] getBodyIfComplete()
+ {
+ return missing.isEmpty() ? body : null;
+ }
+
+ void contributeFragment(short msg_type, int length, byte[] buf, int off, int fragment_offset,
+ int fragment_length)
+ {
+
+ int fragment_end = fragment_offset + fragment_length;
+
+ if (this.msg_type != msg_type || this.body.length != length || fragment_end > length)
+ {
+ return;
+ }
+
+ if (fragment_length == 0)
+ {
+ // NOTE: Empty messages still require an empty fragment to complete it
+ if (fragment_offset == 0 && !missing.isEmpty())
+ {
+ Range firstRange = (Range)missing.firstElement();
+ if (firstRange.getEnd() == 0)
+ {
+ missing.removeElementAt(0);
+ }
+ }
+ return;
+ }
+
+ for (int i = 0; i < missing.size(); ++i)
+ {
+ Range range = (Range)missing.elementAt(i);
+ if (range.getStart() >= fragment_end)
+ {
+ break;
+ }
+ if (range.getEnd() > fragment_offset)
+ {
+
+ int copyStart = Math.max(range.getStart(), fragment_offset);
+ int copyEnd = Math.min(range.getEnd(), fragment_end);
+ int copyLength = copyEnd - copyStart;
+
+ System.arraycopy(buf, off + copyStart - fragment_offset, body, copyStart,
+ copyLength);
+
+ if (copyStart == range.getStart())
+ {
+ if (copyEnd == range.getEnd())
+ {
+ missing.removeElementAt(i--);
+ }
+ else
+ {
+ range.setStart(copyEnd);
+ }
+ }
+ else
+ {
+ if (copyEnd == range.getEnd())
+ {
+ range.setEnd(copyStart);
+ }
+ else
+ {
+ missing.insertElementAt(new Range(copyEnd, range.getEnd()), ++i);
+ range.setEnd(copyStart);
+ }
+ }
+ }
+ }
+ }
+
+ void reset()
+ {
+ this.missing.removeAllElements();
+ this.missing.addElement(new Range(0, body.length));
+ }
+
+ private static class Range
+ {
+
+ private int start, end;
+
+ Range(int start, int end)
+ {
+ this.start = start;
+ this.end = end;
+ }
+
+ public int getStart()
+ {
+ return start;
+ }
+
+ public void setStart(int start)
+ {
+ this.start = start;
+ }
+
+ public int getEnd()
+ {
+ return end;
+ }
+
+ public void setEnd(int end)
+ {
+ this.end = end;
+ }
+ }
+}
diff --git a/core/src/main/jdk1.1/org/spongycastle/crypto/tls/DTLSReliableHandshake.java b/core/src/main/jdk1.1/org/spongycastle/crypto/tls/DTLSReliableHandshake.java
new file mode 100644
index 00000000..1a991161
--- /dev/null
+++ b/core/src/main/jdk1.1/org/spongycastle/crypto/tls/DTLSReliableHandshake.java
@@ -0,0 +1,457 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.util.Integers;
+
+class DTLSReliableHandshake
+{
+ private final static int MAX_RECEIVE_AHEAD = 10;
+
+ private DTLSRecordLayer recordLayer;
+
+ private TlsHandshakeHash handshakeHash;
+
+ private Hashtable currentInboundFlight = new Hashtable();
+ private Hashtable previousInboundFlight = null;
+ private Vector outboundFlight = new Vector();
+ private boolean sending = true;
+
+ private int message_seq = 0, next_receive_seq = 0;
+
+ DTLSReliableHandshake(TlsContext context, DTLSRecordLayer transport)
+ {
+ this.recordLayer = transport;
+ this.handshakeHash = new DeferredHash();
+ this.handshakeHash.init(context);
+ }
+
+ void notifyHelloComplete()
+ {
+ this.handshakeHash = handshakeHash.notifyPRFDetermined();
+ }
+
+ TlsHandshakeHash getHandshakeHash()
+ {
+ return handshakeHash;
+ }
+
+ TlsHandshakeHash prepareToFinish()
+ {
+ TlsHandshakeHash result = handshakeHash;
+ this.handshakeHash = handshakeHash.stopTracking();
+ return result;
+ }
+
+ void sendMessage(short msg_type, byte[] body)
+ throws IOException
+ {
+ TlsUtils.checkUint24(body.length);
+
+ if (!sending)
+ {
+ checkInboundFlight();
+ sending = true;
+ outboundFlight.removeAllElements();
+ }
+
+ Message message = new Message(message_seq++, msg_type, body);
+
+ outboundFlight.addElement(message);
+
+ writeMessage(message);
+ updateHandshakeMessagesDigest(message);
+ }
+
+ 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;
+ prepareInboundFlight();
+ }
+
+ // Check if we already have the next message waiting
+ {
+ DTLSReassembler next = (DTLSReassembler)currentInboundFlight.get(Integers.valueOf(next_receive_seq));
+ if (next != null)
+ {
+ byte[] body = next.getBodyIfComplete();
+ if (body != null)
+ {
+ previousInboundFlight = null;
+ return updateHandshakeMessagesDigest(new Message(next_receive_seq++, next.getType(), body));
+ }
+ }
+ }
+
+ byte[] buf = null;
+
+ // TODO Check the conditions under which we should reset this
+ int readTimeoutMillis = 1000;
+
+ for (; ; )
+ {
+ int receiveLimit = recordLayer.getReceiveLimit();
+ if (buf == null || buf.length < receiveLimit)
+ {
+ buf = new byte[receiveLimit];
+ }
+
+ // TODO Handle records containing multiple handshake messages
+
+ try
+ {
+ for (; ; )
+ {
+ int received = recordLayer.receive(buf, 0, receiveLimit, readTimeoutMillis);
+ if (received < 0)
+ {
+ break;
+ }
+ if (received < 12)
+ {
+ continue;
+ }
+ int fragment_length = TlsUtils.readUint24(buf, 9);
+ if (received != (fragment_length + 12))
+ {
+ continue;
+ }
+ int seq = TlsUtils.readUint16(buf, 4);
+ if (seq > (next_receive_seq + MAX_RECEIVE_AHEAD))
+ {
+ continue;
+ }
+ short msg_type = TlsUtils.readUint8(buf, 0);
+ int length = TlsUtils.readUint24(buf, 1);
+ int fragment_offset = TlsUtils.readUint24(buf, 6);
+ if (fragment_offset + fragment_length > length)
+ {
+ continue;
+ }
+
+ if (seq < next_receive_seq)
+ {
+ /*
+ * NOTE: If we receive the previous flight of incoming messages in full
+ * again, retransmit our last flight
+ */
+ if (previousInboundFlight != null)
+ {
+ DTLSReassembler reassembler = (DTLSReassembler)previousInboundFlight.get(Integers
+ .valueOf(seq));
+ if (reassembler != null)
+ {
+
+ reassembler.contributeFragment(msg_type, length, buf, 12, fragment_offset,
+ fragment_length);
+
+ if (checkAll(previousInboundFlight))
+ {
+
+ resendOutboundFlight();
+
+ /*
+ * TODO[DTLS] implementations SHOULD back off handshake packet
+ * size during the retransmit backoff.
+ */
+ readTimeoutMillis = Math.min(readTimeoutMillis * 2, 60000);
+
+ resetAll(previousInboundFlight);
+ }
+ }
+ }
+ }
+ else
+ {
+
+ DTLSReassembler reassembler = (DTLSReassembler)currentInboundFlight.get(Integers.valueOf(seq));
+ if (reassembler == null)
+ {
+ reassembler = new DTLSReassembler(msg_type, length);
+ currentInboundFlight.put(Integers.valueOf(seq), reassembler);
+ }
+
+ reassembler.contributeFragment(msg_type, length, buf, 12, fragment_offset, fragment_length);
+
+ if (seq == next_receive_seq)
+ {
+ byte[] body = reassembler.getBodyIfComplete();
+ if (body != null)
+ {
+ previousInboundFlight = null;
+ return updateHandshakeMessagesDigest(new Message(next_receive_seq++,
+ reassembler.getType(), body));
+ }
+ }
+ }
+ }
+ }
+ catch (IOException e)
+ {
+ // NOTE: Assume this is a timeout for the moment
+ }
+
+ resendOutboundFlight();
+
+ /*
+ * TODO[DTLS] implementations SHOULD back off handshake packet size during the
+ * retransmit backoff.
+ */
+ readTimeoutMillis = Math.min(readTimeoutMillis * 2, 60000);
+ }
+ }
+
+ void finish()
+ {
+ DTLSHandshakeRetransmit retransmit = null;
+ if (!sending)
+ {
+ checkInboundFlight();
+ }
+ else if (currentInboundFlight != null)
+ {
+ /*
+ * RFC 6347 4.2.4. In addition, for at least twice the default MSL defined for [TCP],
+ * when in the FINISHED state, the node that transmits the last flight (the server in an
+ * ordinary handshake or the client in a resumed handshake) MUST respond to a retransmit
+ * of the peer's last flight with a retransmit of the last flight.
+ */
+ retransmit = new DTLSHandshakeRetransmit()
+ {
+ public void receivedHandshakeRecord(int epoch, byte[] buf, int off, int len)
+ throws IOException
+ {
+ /*
+ * TODO Need to handle the case where the previous inbound flight contains
+ * messages from two epochs.
+ */
+ if (len < 12)
+ {
+ return;
+ }
+ int fragment_length = TlsUtils.readUint24(buf, off + 9);
+ if (len != (fragment_length + 12))
+ {
+ return;
+ }
+ int seq = TlsUtils.readUint16(buf, off + 4);
+ if (seq >= next_receive_seq)
+ {
+ return;
+ }
+
+ short msg_type = TlsUtils.readUint8(buf, off);
+
+ // TODO This is a hack that only works until we try to support renegotiation
+ int expectedEpoch = msg_type == HandshakeType.finished ? 1 : 0;
+ if (epoch != expectedEpoch)
+ {
+ return;
+ }
+
+ int length = TlsUtils.readUint24(buf, off + 1);
+ int fragment_offset = TlsUtils.readUint24(buf, off + 6);
+ if (fragment_offset + fragment_length > length)
+ {
+ return;
+ }
+
+ DTLSReassembler reassembler = (DTLSReassembler)currentInboundFlight.get(Integers.valueOf(seq));
+ if (reassembler != null)
+ {
+ reassembler.contributeFragment(msg_type, length, buf, off + 12, fragment_offset,
+ fragment_length);
+ if (checkAll(currentInboundFlight))
+ {
+ resendOutboundFlight();
+ resetAll(currentInboundFlight);
+ }
+ }
+ }
+ };
+ }
+
+ recordLayer.handshakeSuccessful(retransmit);
+ }
+
+ void resetHandshakeMessagesDigest()
+ {
+ handshakeHash.reset();
+ }
+
+ /**
+ * Check that there are no "extra" messages left in the current inbound flight
+ */
+ private void checkInboundFlight()
+ {
+ Enumeration e = currentInboundFlight.keys();
+ while (e.hasMoreElements())
+ {
+ Integer key = (Integer)e.nextElement();
+ if (key.intValue() >= next_receive_seq)
+ {
+ // TODO Should this be considered an error?
+ }
+ }
+ }
+
+ private void prepareInboundFlight()
+ {
+ resetAll(currentInboundFlight);
+ previousInboundFlight = currentInboundFlight;
+ currentInboundFlight = new Hashtable();
+ }
+
+ private void resendOutboundFlight()
+ throws IOException
+ {
+ recordLayer.resetWriteEpoch();
+ for (int i = 0; i < outboundFlight.size(); ++i)
+ {
+ writeMessage((Message)outboundFlight.elementAt(i));
+ }
+ }
+
+ private Message updateHandshakeMessagesDigest(Message message)
+ throws IOException
+ {
+ if (message.getType() != HandshakeType.hello_request)
+ {
+ byte[] body = message.getBody();
+ byte[] buf = new byte[12];
+ TlsUtils.writeUint8(message.getType(), buf, 0);
+ TlsUtils.writeUint24(body.length, buf, 1);
+ TlsUtils.writeUint16(message.getSeq(), buf, 4);
+ TlsUtils.writeUint24(0, buf, 6);
+ TlsUtils.writeUint24(body.length, buf, 9);
+ handshakeHash.update(buf, 0, buf.length);
+ handshakeHash.update(body, 0, body.length);
+ }
+ return message;
+ }
+
+ private void writeMessage(Message message)
+ throws IOException
+ {
+ int sendLimit = recordLayer.getSendLimit();
+ int fragmentLimit = sendLimit - 12;
+
+ // TODO Support a higher minimum fragment size?
+ if (fragmentLimit < 1)
+ {
+ // TODO Should we be throwing an exception here?
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ int length = message.getBody().length;
+
+ // NOTE: Must still send a fragment if body is empty
+ int fragment_offset = 0;
+ do
+ {
+ int fragment_length = Math.min(length - fragment_offset, fragmentLimit);
+ writeHandshakeFragment(message, fragment_offset, fragment_length);
+ fragment_offset += fragment_length;
+ }
+ while (fragment_offset < length);
+ }
+
+ private void writeHandshakeFragment(Message message, int fragment_offset, int fragment_length)
+ throws IOException
+ {
+ 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)
+ {
+ Enumeration e = inboundFlight.elements();
+ while (e.hasMoreElements())
+ {
+ if (((DTLSReassembler)e.nextElement()).getBodyIfComplete() == null)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static void resetAll(Hashtable inboundFlight)
+ {
+ Enumeration e = inboundFlight.elements();
+ while (e.hasMoreElements())
+ {
+ ((DTLSReassembler)e.nextElement()).reset();
+ }
+ }
+
+ static class Message
+ {
+ private final int message_seq;
+ private final short msg_type;
+ private final byte[] body;
+
+ private Message(int message_seq, short msg_type, byte[] body)
+ {
+ this.message_seq = message_seq;
+ this.msg_type = msg_type;
+ this.body = body;
+ }
+
+ public int getSeq()
+ {
+ return message_seq;
+ }
+
+ public short getType()
+ {
+ return msg_type;
+ }
+
+ public byte[] getBody()
+ {
+ 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/core/src/main/jdk1.1/org/spongycastle/crypto/tls/UDPTransport.java b/core/src/main/jdk1.1/org/spongycastle/crypto/tls/UDPTransport.java
new file mode 100644
index 00000000..913c1e55
--- /dev/null
+++ b/core/src/main/jdk1.1/org/spongycastle/crypto/tls/UDPTransport.java
@@ -0,0 +1,106 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+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;
+
+ protected final DatagramSocket socket;
+ protected final int receiveLimit, sendLimit;
+
+ public UDPTransport(DatagramSocket socket, int mtu)
+ throws IOException
+ {
+ //
+ // In 1.3 and earlier sockets were bound and connected during creation
+ //
+ //if (!socket.isBound() || !socket.isConnected())
+ //{
+ // throw new IllegalArgumentException("'socket' must be bound and connected");
+ //}
+
+ this.socket = socket;
+
+ // NOTE: As of JDK 1.6, can use NetworkInterface.getMTU
+
+ this.receiveLimit = mtu - MIN_IP_OVERHEAD - UDP_OVERHEAD;
+ this.sendLimit = mtu - MAX_IP_OVERHEAD - UDP_OVERHEAD;
+ }
+
+ public int getReceiveLimit()
+ {
+ return receiveLimit;
+ }
+
+ public int getSendLimit()
+ {
+ // TODO[DTLS] Implement Path-MTU discovery?
+ return sendLimit;
+ }
+
+ public int receive(byte[] buf, int off, int len, int waitMillis)
+ throws IOException
+ {
+ socket.setSoTimeout(waitMillis);
+
+ if (off == 0)
+ {
+ DatagramPacket packet = new DatagramPacket(buf, len);
+ socket.receive(packet);
+
+ return packet.getLength();
+ }
+ else
+ {
+ byte[] rv = new byte[len];
+
+ DatagramPacket packet = new DatagramPacket(rv, len);
+ socket.receive(packet);
+
+ System.arraycopy(rv, 0, buf, off, packet.getLength());
+
+ return packet.getLength();
+ }
+ }
+
+ public void send(byte[] buf, int off, int len)
+ throws IOException
+ {
+ if (len > getSendLimit())
+ {
+ /*
+ * RFC 4347 4.1.1. "If the application attempts to send a record larger than the MTU,
+ * the DTLS implementation SHOULD generate an error, thus avoiding sending a packet
+ * which will be fragmented."
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ if (off == 0)
+ {
+ DatagramPacket packet = new DatagramPacket(buf, len);
+ socket.send(packet);
+ }
+ else
+ {
+ byte[] data = new byte[len];
+
+ System.arraycopy(buf, off, data, 0, len);
+
+ DatagramPacket packet = new DatagramPacket(data, len);
+ socket.send(packet);
+ }
+ }
+
+ public void close()
+ throws IOException
+ {
+ socket.close();
+ }
+}
diff --git a/core/src/main/jdk1.1/org/spongycastle/i18n/LocalizedMessage.java b/core/src/main/jdk1.1/org/spongycastle/i18n/LocalizedMessage.java
new file mode 100644
index 00000000..1eab110c
--- /dev/null
+++ b/core/src/main/jdk1.1/org/spongycastle/i18n/LocalizedMessage.java
@@ -0,0 +1,464 @@
+package org.spongycastle.i18n;
+
+import org.spongycastle.i18n.filter.Filter;
+import org.spongycastle.i18n.filter.TrustedInput;
+import org.spongycastle.i18n.filter.UntrustedInput;
+import org.spongycastle.i18n.filter.UntrustedUrlInput;
+
+import java.io.UnsupportedEncodingException;
+import java.text.DateFormat;
+import java.text.Format;
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.TimeZone;
+
+public class LocalizedMessage
+{
+ protected static final int NO_FILTER = 0;
+ protected static final int FILTER = 1;
+ protected static final int FILTER_URL = 2;
+
+ protected String id;
+ protected String resource;
+
+ // ISO-8859-1 is the default encoding
+ public static final String DEFAULT_ENCODING = "ISO-8859-1";
+ protected String encoding = DEFAULT_ENCODING;
+
+ protected FilteredArguments arguments;
+ protected FilteredArguments extraArgs = null;
+
+ protected Filter filter = null;
+
+ protected ClassLoader loader = null;
+
+ /**
+ * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ */
+ public LocalizedMessage(String resource,String id) throws NullPointerException
+ {
+ if (resource == null || id == null)
+ {
+ throw new NullPointerException();
+ }
+ this.id = id;
+ this.resource = resource;
+ arguments = new FilteredArguments();
+ }
+
+ /**
+ * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param encoding the encoding of the resource file
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ * @throws UnsupportedEncodingException if the encoding is not supported
+ */
+ public LocalizedMessage(String resource,String id, String encoding) throws NullPointerException, UnsupportedEncodingException
+ {
+ if (resource == null || id == null)
+ {
+ throw new NullPointerException();
+ }
+ this.id = id;
+ this.resource = resource;
+ arguments = new FilteredArguments();
+ this.encoding = encoding;
+ }
+
+ /**
+ * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param arguments an array containing the arguments for the message
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ */
+ public LocalizedMessage(String resource, String id, Object[] arguments) throws NullPointerException
+ {
+ if (resource == null || id == null || arguments == null)
+ {
+ throw new NullPointerException();
+ }
+ this.id = id;
+ this.resource = resource;
+ this.arguments = new FilteredArguments(arguments);
+ }
+
+ /**
+ * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param encoding the encoding of the resource file
+ * @param arguments an array containing the arguments for the message
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ * @throws UnsupportedEncodingException if the encoding is not supported
+ */
+ public LocalizedMessage(String resource, String id, String encoding, Object[] arguments) throws NullPointerException, UnsupportedEncodingException
+ {
+ if (resource == null || id == null || arguments == null)
+ {
+ throw new NullPointerException();
+ }
+ this.id = id;
+ this.resource = resource;
+ this.arguments = new FilteredArguments(arguments);
+ this.encoding = encoding;
+ }
+
+ /**
+ * Reads the entry <code>id + "." + key</code> from the resource file and returns a
+ * formated message for the given Locale and TimeZone.
+ * @param key second part of the entry id
+ * @param loc the used {@link Locale}
+ * @param timezone the used {@link TimeZone}
+ * @return a Strng containing the localized message
+ * @throws MissingEntryException if the resource file is not available or the entry does not exist.
+ */
+ public String getEntry(String key,Locale loc, TimeZone timezone) throws MissingEntryException
+ {
+ String entry = id;
+ if (key != null)
+ {
+ entry += "." + key;
+ }
+
+ try
+ {
+ ResourceBundle bundle;
+ if (loader == null)
+ {
+ bundle = ResourceBundle.getBundle(resource,loc);
+ }
+ else
+ {
+ bundle = ResourceBundle.getBundle(resource, loc);
+ }
+ String result = bundle.getString(entry);
+ if (!encoding.equals(DEFAULT_ENCODING))
+ {
+ result = new String(result.getBytes(DEFAULT_ENCODING), encoding);
+ }
+ if (!arguments.isEmpty())
+ {
+ result = formatWithTimeZone(result,arguments.getFilteredArgs(loc),loc,timezone);
+ }
+ result = addExtraArgs(result, loc);
+ return result;
+ }
+ catch (MissingResourceException mre)
+ {
+ throw new MissingEntryException("Can't find entry " + entry + " in resource file " + resource + ".",
+ resource,
+ entry,
+ loc,
+ loader != null ? loader : this.getClassLoader());
+ }
+ catch (UnsupportedEncodingException use)
+ {
+ // should never occur - cause we already test this in the constructor
+ throw new RuntimeException(use.toString());
+ }
+ }
+
+ protected String formatWithTimeZone(
+ String template,
+ Object[] arguments,
+ Locale locale,
+ TimeZone timezone)
+ {
+ MessageFormat mf = new MessageFormat(" ");
+ mf.setLocale(locale);
+ mf.applyPattern(template);
+ if (!timezone.equals(TimeZone.getDefault()))
+ {
+ Format[] formats = mf.getFormats();
+ for (int i = 0; i < formats.length; i++)
+ {
+ if (formats[i] instanceof DateFormat)
+ {
+ DateFormat temp = (DateFormat) formats[i];
+ temp.setTimeZone(timezone);
+ mf.setFormat(i,temp);
+ }
+ }
+ }
+ return mf.format(arguments);
+ }
+
+ protected String addExtraArgs(String msg, Locale locale)
+ {
+ if (extraArgs != null)
+ {
+ StringBuffer sb = new StringBuffer(msg);
+ Object[] filteredArgs = extraArgs.getFilteredArgs(locale);
+ for (int i = 0; i < filteredArgs.length; i++)
+ {
+ sb.append(filteredArgs[i]);
+ }
+ msg = sb.toString();
+ }
+ return msg;
+ }
+
+ /**
+ * Sets the {@link Filter} that is used to filter the arguments of this message
+ * @param filter the {@link Filter} to use. <code>null</code> to disable filtering.
+ */
+ public void setFilter(Filter filter)
+ {
+ arguments.setFilter(filter);
+ if (extraArgs != null)
+ {
+ extraArgs.setFilter(filter);
+ }
+ this.filter = filter;
+ }
+
+ /**
+ * Returns the current filter.
+ * @return the current filter
+ */
+ public Filter getFilter()
+ {
+ return filter;
+ }
+
+ /**
+ * Set the {@link ClassLoader} which loads the resource files. If it is set to <code>null</code>
+ * then the default {@link ClassLoader} is used.
+ * @param loader the {@link ClassLoader} which loads the resource files
+ */
+ public void setClassLoader(ClassLoader loader)
+ {
+ this.loader = loader;
+ }
+
+ /**
+ * Returns the {@link ClassLoader} which loads the resource files or <code>null</code>
+ * if the default ClassLoader is used.
+ * @return the {@link ClassLoader} which loads the resource files
+ */
+ public ClassLoader getClassLoader()
+ {
+ return loader;
+ }
+
+ /**
+ * Returns the id of the message in the resource bundle.
+ * @return the id of the message
+ */
+ public String getId()
+ {
+ return id;
+ }
+
+ /**
+ * Returns the name of the resource bundle for this message
+ * @return name of the resource file
+ */
+ public String getResource()
+ {
+ return resource;
+ }
+
+ /**
+ * Returns an <code>Object[]</code> containing the message arguments.
+ * @return the message arguments
+ */
+ public Object[] getArguments()
+ {
+ return arguments.getArguments();
+ }
+
+ /**
+ *
+ * @param extraArg
+ */
+ public void setExtraArgument(Object extraArg)
+ {
+ setExtraArguments(new Object[] {extraArg});
+ }
+
+ /**
+ *
+ * @param extraArgs
+ */
+ public void setExtraArguments(Object[] extraArgs)
+ {
+ if (extraArgs != null)
+ {
+ this.extraArgs = new FilteredArguments(extraArgs);
+ this.extraArgs.setFilter(filter);
+ }
+ else
+ {
+ this.extraArgs = null;
+ }
+ }
+
+ /**
+ *
+ * @return
+ */
+ public Object[] getExtraArgs()
+ {
+ return (extraArgs == null) ? null : extraArgs.getArguments();
+ }
+
+ protected class FilteredArguments
+ {
+
+ protected Filter filter = null;
+
+ protected boolean[] isLocaleSpecific;
+ protected int[] argFilterType;
+ protected Object[] arguments;
+ protected Object[] unpackedArgs;
+ protected Object[] filteredArgs;
+
+ FilteredArguments()
+ {
+ this(new Object[0]);
+ }
+
+ FilteredArguments(Object[] args)
+ {
+ this.arguments = args;
+ this.unpackedArgs = new Object[args.length];
+ this.filteredArgs = new Object[args.length];
+ this.isLocaleSpecific = new boolean[args.length];
+ this.argFilterType = new int[args.length];
+ for (int i = 0; i < args.length; i++)
+ {
+ if (args[i] instanceof TrustedInput)
+ {
+ this.unpackedArgs[i] = ((TrustedInput) args[i]).getInput();
+ argFilterType[i] = NO_FILTER;
+ }
+ else if (args[i] instanceof UntrustedInput)
+ {
+ this.unpackedArgs[i] = ((UntrustedInput) args[i]).getInput();
+ if (args[i] instanceof UntrustedUrlInput)
+ {
+ argFilterType[i] = FILTER_URL;
+ }
+ else
+ {
+ argFilterType[i] = FILTER;
+ }
+ }
+ else
+ {
+ this.unpackedArgs[i] = args[i];
+ argFilterType[i] = FILTER;
+ }
+
+ // locale specific
+ this.isLocaleSpecific[i] = (this.unpackedArgs[i] instanceof LocaleString);
+ }
+ }
+
+ public boolean isEmpty()
+ {
+ return unpackedArgs.length == 0;
+ }
+
+ public Object[] getArguments()
+ {
+ return arguments;
+ }
+
+ public Object[] getFilteredArgs(Locale locale)
+ {
+ Object[] result = new Object[unpackedArgs.length];
+ for (int i = 0; i < unpackedArgs.length; i++)
+ {
+ Object arg;
+ if (filteredArgs[i] != null)
+ {
+ arg = filteredArgs[i];
+ }
+ else
+ {
+ arg = unpackedArgs[i];
+ if (isLocaleSpecific[i])
+ {
+ // get locale
+ arg = ((LocaleString) arg).getLocaleString(locale);
+ arg = filter(argFilterType[i], arg);
+ }
+ else
+ {
+ arg = filter(argFilterType[i], arg);
+ filteredArgs[i] = arg;
+ }
+ }
+ result[i] = arg;
+ }
+ return result;
+ }
+
+ private Object filter(int type, Object obj)
+ {
+ if (filter != null)
+ {
+ Object o = (null == obj) ? "null" : obj;
+ switch (type)
+ {
+ case NO_FILTER:
+ return o;
+ case FILTER:
+ return filter.doFilter(o.toString());
+ case FILTER_URL:
+ return filter.doFilterUrl(o.toString());
+ default:
+ return null;
+ }
+ }
+ else
+ {
+ return obj;
+ }
+ }
+
+ public Filter getFilter()
+ {
+ return filter;
+ }
+
+ public void setFilter(Filter filter)
+ {
+ if (filter != this.filter)
+ {
+ for (int i = 0; i < unpackedArgs.length; i++)
+ {
+ filteredArgs[i] = null;
+ }
+ }
+ this.filter = filter;
+ }
+
+ }
+
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append("Resource: \"").append(resource);
+ sb.append("\" Id: \"").append(id).append("\"");
+ sb.append(" Arguments: ").append(arguments.getArguments().length).append(" normal, ")
+ .append(extraArgs.getArguments().length).append(" extra");
+ sb.append(" Encoding: ").append(encoding);
+ sb.append(" ClassLoader: ").append(loader);
+ return sb.toString();
+ }
+
+}
diff --git a/core/src/main/jdk1.1/org/spongycastle/i18n/MissingEntryException.java b/core/src/main/jdk1.1/org/spongycastle/i18n/MissingEntryException.java
new file mode 100644
index 00000000..d876a91a
--- /dev/null
+++ b/core/src/main/jdk1.1/org/spongycastle/i18n/MissingEntryException.java
@@ -0,0 +1,63 @@
+package org.spongycastle.i18n;
+
+import java.net.URL;
+import java.util.Locale;
+
+public class MissingEntryException extends RuntimeException
+{
+
+ protected final String resource;
+ protected final String key;
+ protected final ClassLoader loader;
+ protected final Locale locale;
+
+ private String debugMsg;
+
+ public MissingEntryException(String message, String resource, String key, Locale locale, ClassLoader loader)
+ {
+ super(message);
+ this.resource = resource;
+ this.key = key;
+ this.locale = locale;
+ this.loader = loader;
+ }
+
+ public MissingEntryException(String message, Throwable cause, String resource, String key, Locale locale, ClassLoader loader)
+ {
+ super(message + ": " + cause);
+ this.resource = resource;
+ this.key = key;
+ this.locale = locale;
+ this.loader = loader;
+ }
+
+ public String getKey()
+ {
+ return key;
+ }
+
+ public String getResource()
+ {
+ return resource;
+ }
+
+ public ClassLoader getClassLoader()
+ {
+ return loader;
+ }
+
+ public Locale getLocale()
+ {
+ return locale;
+ }
+
+ public String getDebugMsg()
+ {
+ if (debugMsg == null)
+ {
+ debugMsg = "Can not find entry " + key + " in resource file " + resource + " for the locale " + locale + ".";
+ }
+ return debugMsg;
+ }
+
+}
diff --git a/core/src/main/jdk1.2/org/bouncycastle/i18n/LocalizedMessage.java b/core/src/main/jdk1.2/org/bouncycastle/i18n/LocalizedMessage.java
deleted file mode 100644
index c1c4c58a..00000000
--- a/core/src/main/jdk1.2/org/bouncycastle/i18n/LocalizedMessage.java
+++ /dev/null
@@ -1,464 +0,0 @@
-package org.bouncycastle.i18n;
-
-import org.bouncycastle.i18n.filter.Filter;
-import org.bouncycastle.i18n.filter.TrustedInput;
-import org.bouncycastle.i18n.filter.UntrustedInput;
-import org.bouncycastle.i18n.filter.UntrustedUrlInput;
-
-import java.io.UnsupportedEncodingException;
-import java.text.DateFormat;
-import java.text.Format;
-import java.text.MessageFormat;
-import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-import java.util.TimeZone;
-
-public class LocalizedMessage
-{
- protected static final int NO_FILTER = 0;
- protected static final int FILTER = 1;
- protected static final int FILTER_URL = 2;
-
- protected String id;
- protected String resource;
-
- // ISO-8859-1 is the default encoding
- public static final String DEFAULT_ENCODING = "ISO-8859-1";
- protected String encoding = DEFAULT_ENCODING;
-
- protected FilteredArguments arguments;
- protected FilteredArguments extraArgs = null;
-
- protected Filter filter = null;
-
- protected ClassLoader loader = null;
-
- /**
- * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- */
- public LocalizedMessage(String resource,String id) throws NullPointerException
- {
- if (resource == null || id == null)
- {
- throw new NullPointerException();
- }
- this.id = id;
- this.resource = resource;
- arguments = new FilteredArguments();
- }
-
- /**
- * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @param encoding the encoding of the resource file
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- * @throws UnsupportedEncodingException if the encoding is not supported
- */
- public LocalizedMessage(String resource,String id, String encoding) throws NullPointerException, UnsupportedEncodingException
- {
- if (resource == null || id == null)
- {
- throw new NullPointerException();
- }
- this.id = id;
- this.resource = resource;
- arguments = new FilteredArguments();
- this.encoding = encoding;
- }
-
- /**
- * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @param arguments an array containing the arguments for the message
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- */
- public LocalizedMessage(String resource, String id, Object[] arguments) throws NullPointerException
- {
- if (resource == null || id == null || arguments == null)
- {
- throw new NullPointerException();
- }
- this.id = id;
- this.resource = resource;
- this.arguments = new FilteredArguments(arguments);
- }
-
- /**
- * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @param encoding the encoding of the resource file
- * @param arguments an array containing the arguments for the message
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- * @throws UnsupportedEncodingException if the encoding is not supported
- */
- public LocalizedMessage(String resource, String id, String encoding, Object[] arguments) throws NullPointerException, UnsupportedEncodingException
- {
- if (resource == null || id == null || arguments == null)
- {
- throw new NullPointerException();
- }
- this.id = id;
- this.resource = resource;
- this.arguments = new FilteredArguments(arguments);
- this.encoding = encoding;
- }
-
- /**
- * Reads the entry <code>id + "." + key</code> from the resource file and returns a
- * formated message for the given Locale and TimeZone.
- * @param key second part of the entry id
- * @param loc the used {@link Locale}
- * @param timezone the used {@link TimeZone}
- * @return a Strng containing the localized message
- * @throws MissingEntryException if the resource file is not available or the entry does not exist.
- */
- public String getEntry(String key,Locale loc, TimeZone timezone) throws MissingEntryException
- {
- String entry = id;
- if (key != null)
- {
- entry += "." + key;
- }
-
- try
- {
- ResourceBundle bundle;
- if (loader == null)
- {
- bundle = ResourceBundle.getBundle(resource,loc);
- }
- else
- {
- bundle = ResourceBundle.getBundle(resource, loc);
- }
- String result = bundle.getString(entry);
- if (!encoding.equals(DEFAULT_ENCODING))
- {
- result = new String(result.getBytes(DEFAULT_ENCODING), encoding);
- }
- if (!arguments.isEmpty())
- {
- result = formatWithTimeZone(result,arguments.getFilteredArgs(loc),loc,timezone);
- }
- result = addExtraArgs(result, loc);
- return result;
- }
- catch (MissingResourceException mre)
- {
- throw new MissingEntryException("Can't find entry " + entry + " in resource file " + resource + ".",
- resource,
- entry,
- loc,
- loader != null ? loader : this.getClassLoader());
- }
- catch (UnsupportedEncodingException use)
- {
- // should never occur - cause we already test this in the constructor
- throw new RuntimeException(use.toString());
- }
- }
-
- protected String formatWithTimeZone(
- String template,
- Object[] arguments,
- Locale locale,
- TimeZone timezone)
- {
- MessageFormat mf = new MessageFormat(" ");
- mf.setLocale(locale);
- mf.applyPattern(template);
- if (!timezone.equals(TimeZone.getDefault()))
- {
- Format[] formats = mf.getFormats();
- for (int i = 0; i < formats.length; i++)
- {
- if (formats[i] instanceof DateFormat)
- {
- DateFormat temp = (DateFormat) formats[i];
- temp.setTimeZone(timezone);
- mf.setFormat(i,temp);
- }
- }
- }
- return mf.format(arguments);
- }
-
- protected String addExtraArgs(String msg, Locale locale)
- {
- if (extraArgs != null)
- {
- StringBuffer sb = new StringBuffer(msg);
- Object[] filteredArgs = extraArgs.getFilteredArgs(locale);
- for (int i = 0; i < filteredArgs.length; i++)
- {
- sb.append(filteredArgs[i]);
- }
- msg = sb.toString();
- }
- return msg;
- }
-
- /**
- * Sets the {@link Filter} that is used to filter the arguments of this message
- * @param filter the {@link Filter} to use. <code>null</code> to disable filtering.
- */
- public void setFilter(Filter filter)
- {
- arguments.setFilter(filter);
- if (extraArgs != null)
- {
- extraArgs.setFilter(filter);
- }
- this.filter = filter;
- }
-
- /**
- * Returns the current filter.
- * @return the current filter
- */
- public Filter getFilter()
- {
- return filter;
- }
-
- /**
- * Set the {@link ClassLoader} which loads the resource files. If it is set to <code>null</code>
- * then the default {@link ClassLoader} is used.
- * @param loader the {@link ClassLoader} which loads the resource files
- */
- public void setClassLoader(ClassLoader loader)
- {
- this.loader = loader;
- }
-
- /**
- * Returns the {@link ClassLoader} which loads the resource files or <code>null</code>
- * if the default ClassLoader is used.
- * @return the {@link ClassLoader} which loads the resource files
- */
- public ClassLoader getClassLoader()
- {
- return loader;
- }
-
- /**
- * Returns the id of the message in the resource bundle.
- * @return the id of the message
- */
- public String getId()
- {
- return id;
- }
-
- /**
- * Returns the name of the resource bundle for this message
- * @return name of the resource file
- */
- public String getResource()
- {
- return resource;
- }
-
- /**
- * Returns an <code>Object[]</code> containing the message arguments.
- * @return the message arguments
- */
- public Object[] getArguments()
- {
- return arguments.getArguments();
- }
-
- /**
- *
- * @param extraArg
- */
- public void setExtraArgument(Object extraArg)
- {
- setExtraArguments(new Object[] {extraArg});
- }
-
- /**
- *
- * @param extraArgs
- */
- public void setExtraArguments(Object[] extraArgs)
- {
- if (extraArgs != null)
- {
- this.extraArgs = new FilteredArguments(extraArgs);
- this.extraArgs.setFilter(filter);
- }
- else
- {
- this.extraArgs = null;
- }
- }
-
- /**
- *
- * @return
- */
- public Object[] getExtraArgs()
- {
- return (extraArgs == null) ? null : extraArgs.getArguments();
- }
-
- protected class FilteredArguments
- {
-
- protected Filter filter = null;
-
- protected boolean[] isLocaleSpecific;
- protected int[] argFilterType;
- protected Object[] arguments;
- protected Object[] unpackedArgs;
- protected Object[] filteredArgs;
-
- FilteredArguments()
- {
- this(new Object[0]);
- }
-
- FilteredArguments(Object[] args)
- {
- this.arguments = args;
- this.unpackedArgs = new Object[args.length];
- this.filteredArgs = new Object[args.length];
- this.isLocaleSpecific = new boolean[args.length];
- this.argFilterType = new int[args.length];
- for (int i = 0; i < args.length; i++)
- {
- if (args[i] instanceof TrustedInput)
- {
- this.unpackedArgs[i] = ((TrustedInput) args[i]).getInput();
- argFilterType[i] = NO_FILTER;
- }
- else if (args[i] instanceof UntrustedInput)
- {
- this.unpackedArgs[i] = ((UntrustedInput) args[i]).getInput();
- if (args[i] instanceof UntrustedUrlInput)
- {
- argFilterType[i] = FILTER_URL;
- }
- else
- {
- argFilterType[i] = FILTER;
- }
- }
- else
- {
- this.unpackedArgs[i] = args[i];
- argFilterType[i] = FILTER;
- }
-
- // locale specific
- this.isLocaleSpecific[i] = (this.unpackedArgs[i] instanceof LocaleString);
- }
- }
-
- public boolean isEmpty()
- {
- return unpackedArgs.length == 0;
- }
-
- public Object[] getArguments()
- {
- return arguments;
- }
-
- public Object[] getFilteredArgs(Locale locale)
- {
- Object[] result = new Object[unpackedArgs.length];
- for (int i = 0; i < unpackedArgs.length; i++)
- {
- Object arg;
- if (filteredArgs[i] != null)
- {
- arg = filteredArgs[i];
- }
- else
- {
- arg = unpackedArgs[i];
- if (isLocaleSpecific[i])
- {
- // get locale
- arg = ((LocaleString) arg).getLocaleString(locale);
- arg = filter(argFilterType[i], arg);
- }
- else
- {
- arg = filter(argFilterType[i], arg);
- filteredArgs[i] = arg;
- }
- }
- result[i] = arg;
- }
- return result;
- }
-
- private Object filter(int type, Object obj)
- {
- if (filter != null)
- {
- Object o = (null == obj) ? "null" : obj;
- switch (type)
- {
- case NO_FILTER:
- return o;
- case FILTER:
- return filter.doFilter(o.toString());
- case FILTER_URL:
- return filter.doFilterUrl(o.toString());
- default:
- return null;
- }
- }
- else
- {
- return obj;
- }
- }
-
- public Filter getFilter()
- {
- return filter;
- }
-
- public void setFilter(Filter filter)
- {
- if (filter != this.filter)
- {
- for (int i = 0; i < unpackedArgs.length; i++)
- {
- filteredArgs[i] = null;
- }
- }
- this.filter = filter;
- }
-
- }
-
- public String toString()
- {
- StringBuffer sb = new StringBuffer();
- sb.append("Resource: \"").append(resource);
- sb.append("\" Id: \"").append(id).append("\"");
- sb.append(" Arguments: ").append(arguments.getArguments().length).append(" normal, ")
- .append(extraArgs.getArguments().length).append(" extra");
- sb.append(" Encoding: ").append(encoding);
- sb.append(" ClassLoader: ").append(loader);
- return sb.toString();
- }
-
-}
diff --git a/core/src/main/jdk1.2/org/bouncycastle/i18n/MissingEntryException.java b/core/src/main/jdk1.2/org/bouncycastle/i18n/MissingEntryException.java
deleted file mode 100644
index 1400338f..00000000
--- a/core/src/main/jdk1.2/org/bouncycastle/i18n/MissingEntryException.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package org.bouncycastle.i18n;
-
-import java.net.URL;
-import java.util.Locale;
-
-public class MissingEntryException extends RuntimeException
-{
-
- protected final String resource;
- protected final String key;
- protected final ClassLoader loader;
- protected final Locale locale;
-
- private String debugMsg;
-
- public MissingEntryException(String message, String resource, String key, Locale locale, ClassLoader loader)
- {
- super(message);
- this.resource = resource;
- this.key = key;
- this.locale = locale;
- this.loader = loader;
- }
-
- public MissingEntryException(String message, Throwable cause, String resource, String key, Locale locale, ClassLoader loader)
- {
- super(message + ": " + cause);
- this.resource = resource;
- this.key = key;
- this.locale = locale;
- this.loader = loader;
- }
-
- public String getKey()
- {
- return key;
- }
-
- public String getResource()
- {
- return resource;
- }
-
- public ClassLoader getClassLoader()
- {
- return loader;
- }
-
- public Locale getLocale()
- {
- return locale;
- }
-
- public String getDebugMsg()
- {
- if (debugMsg == null)
- {
- debugMsg = "Can not find entry " + key + " in resource file " + resource + " for the locale " + locale + ".";
- }
- return debugMsg;
- }
-
-}
diff --git a/core/src/main/jdk1.2/org/spongycastle/i18n/LocalizedMessage.java b/core/src/main/jdk1.2/org/spongycastle/i18n/LocalizedMessage.java
new file mode 100644
index 00000000..1eab110c
--- /dev/null
+++ b/core/src/main/jdk1.2/org/spongycastle/i18n/LocalizedMessage.java
@@ -0,0 +1,464 @@
+package org.spongycastle.i18n;
+
+import org.spongycastle.i18n.filter.Filter;
+import org.spongycastle.i18n.filter.TrustedInput;
+import org.spongycastle.i18n.filter.UntrustedInput;
+import org.spongycastle.i18n.filter.UntrustedUrlInput;
+
+import java.io.UnsupportedEncodingException;
+import java.text.DateFormat;
+import java.text.Format;
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.TimeZone;
+
+public class LocalizedMessage
+{
+ protected static final int NO_FILTER = 0;
+ protected static final int FILTER = 1;
+ protected static final int FILTER_URL = 2;
+
+ protected String id;
+ protected String resource;
+
+ // ISO-8859-1 is the default encoding
+ public static final String DEFAULT_ENCODING = "ISO-8859-1";
+ protected String encoding = DEFAULT_ENCODING;
+
+ protected FilteredArguments arguments;
+ protected FilteredArguments extraArgs = null;
+
+ protected Filter filter = null;
+
+ protected ClassLoader loader = null;
+
+ /**
+ * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ */
+ public LocalizedMessage(String resource,String id) throws NullPointerException
+ {
+ if (resource == null || id == null)
+ {
+ throw new NullPointerException();
+ }
+ this.id = id;
+ this.resource = resource;
+ arguments = new FilteredArguments();
+ }
+
+ /**
+ * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param encoding the encoding of the resource file
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ * @throws UnsupportedEncodingException if the encoding is not supported
+ */
+ public LocalizedMessage(String resource,String id, String encoding) throws NullPointerException, UnsupportedEncodingException
+ {
+ if (resource == null || id == null)
+ {
+ throw new NullPointerException();
+ }
+ this.id = id;
+ this.resource = resource;
+ arguments = new FilteredArguments();
+ this.encoding = encoding;
+ }
+
+ /**
+ * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param arguments an array containing the arguments for the message
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ */
+ public LocalizedMessage(String resource, String id, Object[] arguments) throws NullPointerException
+ {
+ if (resource == null || id == null || arguments == null)
+ {
+ throw new NullPointerException();
+ }
+ this.id = id;
+ this.resource = resource;
+ this.arguments = new FilteredArguments(arguments);
+ }
+
+ /**
+ * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param encoding the encoding of the resource file
+ * @param arguments an array containing the arguments for the message
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ * @throws UnsupportedEncodingException if the encoding is not supported
+ */
+ public LocalizedMessage(String resource, String id, String encoding, Object[] arguments) throws NullPointerException, UnsupportedEncodingException
+ {
+ if (resource == null || id == null || arguments == null)
+ {
+ throw new NullPointerException();
+ }
+ this.id = id;
+ this.resource = resource;
+ this.arguments = new FilteredArguments(arguments);
+ this.encoding = encoding;
+ }
+
+ /**
+ * Reads the entry <code>id + "." + key</code> from the resource file and returns a
+ * formated message for the given Locale and TimeZone.
+ * @param key second part of the entry id
+ * @param loc the used {@link Locale}
+ * @param timezone the used {@link TimeZone}
+ * @return a Strng containing the localized message
+ * @throws MissingEntryException if the resource file is not available or the entry does not exist.
+ */
+ public String getEntry(String key,Locale loc, TimeZone timezone) throws MissingEntryException
+ {
+ String entry = id;
+ if (key != null)
+ {
+ entry += "." + key;
+ }
+
+ try
+ {
+ ResourceBundle bundle;
+ if (loader == null)
+ {
+ bundle = ResourceBundle.getBundle(resource,loc);
+ }
+ else
+ {
+ bundle = ResourceBundle.getBundle(resource, loc);
+ }
+ String result = bundle.getString(entry);
+ if (!encoding.equals(DEFAULT_ENCODING))
+ {
+ result = new String(result.getBytes(DEFAULT_ENCODING), encoding);
+ }
+ if (!arguments.isEmpty())
+ {
+ result = formatWithTimeZone(result,arguments.getFilteredArgs(loc),loc,timezone);
+ }
+ result = addExtraArgs(result, loc);
+ return result;
+ }
+ catch (MissingResourceException mre)
+ {
+ throw new MissingEntryException("Can't find entry " + entry + " in resource file " + resource + ".",
+ resource,
+ entry,
+ loc,
+ loader != null ? loader : this.getClassLoader());
+ }
+ catch (UnsupportedEncodingException use)
+ {
+ // should never occur - cause we already test this in the constructor
+ throw new RuntimeException(use.toString());
+ }
+ }
+
+ protected String formatWithTimeZone(
+ String template,
+ Object[] arguments,
+ Locale locale,
+ TimeZone timezone)
+ {
+ MessageFormat mf = new MessageFormat(" ");
+ mf.setLocale(locale);
+ mf.applyPattern(template);
+ if (!timezone.equals(TimeZone.getDefault()))
+ {
+ Format[] formats = mf.getFormats();
+ for (int i = 0; i < formats.length; i++)
+ {
+ if (formats[i] instanceof DateFormat)
+ {
+ DateFormat temp = (DateFormat) formats[i];
+ temp.setTimeZone(timezone);
+ mf.setFormat(i,temp);
+ }
+ }
+ }
+ return mf.format(arguments);
+ }
+
+ protected String addExtraArgs(String msg, Locale locale)
+ {
+ if (extraArgs != null)
+ {
+ StringBuffer sb = new StringBuffer(msg);
+ Object[] filteredArgs = extraArgs.getFilteredArgs(locale);
+ for (int i = 0; i < filteredArgs.length; i++)
+ {
+ sb.append(filteredArgs[i]);
+ }
+ msg = sb.toString();
+ }
+ return msg;
+ }
+
+ /**
+ * Sets the {@link Filter} that is used to filter the arguments of this message
+ * @param filter the {@link Filter} to use. <code>null</code> to disable filtering.
+ */
+ public void setFilter(Filter filter)
+ {
+ arguments.setFilter(filter);
+ if (extraArgs != null)
+ {
+ extraArgs.setFilter(filter);
+ }
+ this.filter = filter;
+ }
+
+ /**
+ * Returns the current filter.
+ * @return the current filter
+ */
+ public Filter getFilter()
+ {
+ return filter;
+ }
+
+ /**
+ * Set the {@link ClassLoader} which loads the resource files. If it is set to <code>null</code>
+ * then the default {@link ClassLoader} is used.
+ * @param loader the {@link ClassLoader} which loads the resource files
+ */
+ public void setClassLoader(ClassLoader loader)
+ {
+ this.loader = loader;
+ }
+
+ /**
+ * Returns the {@link ClassLoader} which loads the resource files or <code>null</code>
+ * if the default ClassLoader is used.
+ * @return the {@link ClassLoader} which loads the resource files
+ */
+ public ClassLoader getClassLoader()
+ {
+ return loader;
+ }
+
+ /**
+ * Returns the id of the message in the resource bundle.
+ * @return the id of the message
+ */
+ public String getId()
+ {
+ return id;
+ }
+
+ /**
+ * Returns the name of the resource bundle for this message
+ * @return name of the resource file
+ */
+ public String getResource()
+ {
+ return resource;
+ }
+
+ /**
+ * Returns an <code>Object[]</code> containing the message arguments.
+ * @return the message arguments
+ */
+ public Object[] getArguments()
+ {
+ return arguments.getArguments();
+ }
+
+ /**
+ *
+ * @param extraArg
+ */
+ public void setExtraArgument(Object extraArg)
+ {
+ setExtraArguments(new Object[] {extraArg});
+ }
+
+ /**
+ *
+ * @param extraArgs
+ */
+ public void setExtraArguments(Object[] extraArgs)
+ {
+ if (extraArgs != null)
+ {
+ this.extraArgs = new FilteredArguments(extraArgs);
+ this.extraArgs.setFilter(filter);
+ }
+ else
+ {
+ this.extraArgs = null;
+ }
+ }
+
+ /**
+ *
+ * @return
+ */
+ public Object[] getExtraArgs()
+ {
+ return (extraArgs == null) ? null : extraArgs.getArguments();
+ }
+
+ protected class FilteredArguments
+ {
+
+ protected Filter filter = null;
+
+ protected boolean[] isLocaleSpecific;
+ protected int[] argFilterType;
+ protected Object[] arguments;
+ protected Object[] unpackedArgs;
+ protected Object[] filteredArgs;
+
+ FilteredArguments()
+ {
+ this(new Object[0]);
+ }
+
+ FilteredArguments(Object[] args)
+ {
+ this.arguments = args;
+ this.unpackedArgs = new Object[args.length];
+ this.filteredArgs = new Object[args.length];
+ this.isLocaleSpecific = new boolean[args.length];
+ this.argFilterType = new int[args.length];
+ for (int i = 0; i < args.length; i++)
+ {
+ if (args[i] instanceof TrustedInput)
+ {
+ this.unpackedArgs[i] = ((TrustedInput) args[i]).getInput();
+ argFilterType[i] = NO_FILTER;
+ }
+ else if (args[i] instanceof UntrustedInput)
+ {
+ this.unpackedArgs[i] = ((UntrustedInput) args[i]).getInput();
+ if (args[i] instanceof UntrustedUrlInput)
+ {
+ argFilterType[i] = FILTER_URL;
+ }
+ else
+ {
+ argFilterType[i] = FILTER;
+ }
+ }
+ else
+ {
+ this.unpackedArgs[i] = args[i];
+ argFilterType[i] = FILTER;
+ }
+
+ // locale specific
+ this.isLocaleSpecific[i] = (this.unpackedArgs[i] instanceof LocaleString);
+ }
+ }
+
+ public boolean isEmpty()
+ {
+ return unpackedArgs.length == 0;
+ }
+
+ public Object[] getArguments()
+ {
+ return arguments;
+ }
+
+ public Object[] getFilteredArgs(Locale locale)
+ {
+ Object[] result = new Object[unpackedArgs.length];
+ for (int i = 0; i < unpackedArgs.length; i++)
+ {
+ Object arg;
+ if (filteredArgs[i] != null)
+ {
+ arg = filteredArgs[i];
+ }
+ else
+ {
+ arg = unpackedArgs[i];
+ if (isLocaleSpecific[i])
+ {
+ // get locale
+ arg = ((LocaleString) arg).getLocaleString(locale);
+ arg = filter(argFilterType[i], arg);
+ }
+ else
+ {
+ arg = filter(argFilterType[i], arg);
+ filteredArgs[i] = arg;
+ }
+ }
+ result[i] = arg;
+ }
+ return result;
+ }
+
+ private Object filter(int type, Object obj)
+ {
+ if (filter != null)
+ {
+ Object o = (null == obj) ? "null" : obj;
+ switch (type)
+ {
+ case NO_FILTER:
+ return o;
+ case FILTER:
+ return filter.doFilter(o.toString());
+ case FILTER_URL:
+ return filter.doFilterUrl(o.toString());
+ default:
+ return null;
+ }
+ }
+ else
+ {
+ return obj;
+ }
+ }
+
+ public Filter getFilter()
+ {
+ return filter;
+ }
+
+ public void setFilter(Filter filter)
+ {
+ if (filter != this.filter)
+ {
+ for (int i = 0; i < unpackedArgs.length; i++)
+ {
+ filteredArgs[i] = null;
+ }
+ }
+ this.filter = filter;
+ }
+
+ }
+
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append("Resource: \"").append(resource);
+ sb.append("\" Id: \"").append(id).append("\"");
+ sb.append(" Arguments: ").append(arguments.getArguments().length).append(" normal, ")
+ .append(extraArgs.getArguments().length).append(" extra");
+ sb.append(" Encoding: ").append(encoding);
+ sb.append(" ClassLoader: ").append(loader);
+ return sb.toString();
+ }
+
+}
diff --git a/core/src/main/jdk1.2/org/spongycastle/i18n/MissingEntryException.java b/core/src/main/jdk1.2/org/spongycastle/i18n/MissingEntryException.java
new file mode 100644
index 00000000..d876a91a
--- /dev/null
+++ b/core/src/main/jdk1.2/org/spongycastle/i18n/MissingEntryException.java
@@ -0,0 +1,63 @@
+package org.spongycastle.i18n;
+
+import java.net.URL;
+import java.util.Locale;
+
+public class MissingEntryException extends RuntimeException
+{
+
+ protected final String resource;
+ protected final String key;
+ protected final ClassLoader loader;
+ protected final Locale locale;
+
+ private String debugMsg;
+
+ public MissingEntryException(String message, String resource, String key, Locale locale, ClassLoader loader)
+ {
+ super(message);
+ this.resource = resource;
+ this.key = key;
+ this.locale = locale;
+ this.loader = loader;
+ }
+
+ public MissingEntryException(String message, Throwable cause, String resource, String key, Locale locale, ClassLoader loader)
+ {
+ super(message + ": " + cause);
+ this.resource = resource;
+ this.key = key;
+ this.locale = locale;
+ this.loader = loader;
+ }
+
+ public String getKey()
+ {
+ return key;
+ }
+
+ public String getResource()
+ {
+ return resource;
+ }
+
+ public ClassLoader getClassLoader()
+ {
+ return loader;
+ }
+
+ public Locale getLocale()
+ {
+ return locale;
+ }
+
+ public String getDebugMsg()
+ {
+ if (debugMsg == null)
+ {
+ debugMsg = "Can not find entry " + key + " in resource file " + resource + " for the locale " + locale + ".";
+ }
+ return debugMsg;
+ }
+
+}
diff --git a/core/src/main/jdk1.3/org/bouncycastle/asn1/StreamUtil.java b/core/src/main/jdk1.3/org/bouncycastle/asn1/StreamUtil.java
deleted file mode 100644
index 6bc9914a..00000000
--- a/core/src/main/jdk1.3/org/bouncycastle/asn1/StreamUtil.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayInputStream;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-class StreamUtil
-{
- /**
- * Find out possible longest length...
- *
- * @param in input stream of interest
- * @return length calculation or MAX_VALUE.
- */
- static int findLimit(InputStream in)
- {
- if (in instanceof LimitedInputStream)
- {
- return ((LimitedInputStream)in).getRemaining();
- }
- else if (in instanceof ASN1InputStream)
- {
- return ((ASN1InputStream)in).getLimit();
- }
- else if (in instanceof ByteArrayInputStream)
- {
- return ((ByteArrayInputStream)in).available();
- }
-
- return Integer.MAX_VALUE;
- }
-
- static int calculateBodyLength(
- int length)
- {
- int count = 1;
-
- if (length > 127)
- {
- int size = 1;
- int val = length;
-
- while ((val >>>= 8) != 0)
- {
- size++;
- }
-
- for (int i = (size - 1) * 8; i >= 0; i -= 8)
- {
- count++;
- }
- }
-
- return count;
- }
-
- static int calculateTagLength(int tagNo)
- throws IOException
- {
- int length = 1;
-
- if (tagNo >= 31)
- {
- if (tagNo < 128)
- {
- length++;
- }
- else
- {
- byte[] stack = new byte[5];
- int pos = stack.length;
-
- stack[--pos] = (byte)(tagNo & 0x7F);
-
- do
- {
- tagNo >>= 7;
- stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
- }
- while (tagNo > 127);
-
- length += stack.length - pos;
- }
- }
-
- return length;
- }
-}
diff --git a/core/src/main/jdk1.3/org/bouncycastle/crypto/tls/UDPTransport.java b/core/src/main/jdk1.3/org/bouncycastle/crypto/tls/UDPTransport.java
deleted file mode 100644
index a55617fe..00000000
--- a/core/src/main/jdk1.3/org/bouncycastle/crypto/tls/UDPTransport.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.bouncycastle.crypto.tls;
-
-import java.io.IOException;
-import java.net.DatagramPacket;
-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;
-
- protected final DatagramSocket socket;
- protected final int receiveLimit, sendLimit;
-
- public UDPTransport(DatagramSocket socket, int mtu)
- throws IOException
- {
- //
- // In 1.3 and earlier sockets were bound and connected during creation
- //
- //if (!socket.isBound() || !socket.isConnected())
- //{
- // throw new IllegalArgumentException("'socket' must be bound and connected");
- //}
-
- this.socket = socket;
-
- // NOTE: As of JDK 1.6, can use NetworkInterface.getMTU
-
- this.receiveLimit = mtu - MIN_IP_OVERHEAD - UDP_OVERHEAD;
- this.sendLimit = mtu - MAX_IP_OVERHEAD - UDP_OVERHEAD;
- }
-
- public int getReceiveLimit()
- {
- return receiveLimit;
- }
-
- public int getSendLimit()
- {
- // TODO[DTLS] Implement Path-MTU discovery?
- return sendLimit;
- }
-
- public int receive(byte[] buf, int off, int len, int waitMillis)
- throws IOException
- {
- socket.setSoTimeout(waitMillis);
- DatagramPacket packet = new DatagramPacket(buf, off, len);
- socket.receive(packet);
- return packet.getLength();
- }
-
- public void send(byte[] buf, int off, int len)
- throws IOException
- {
- if (len > getSendLimit())
- {
- /*
- * RFC 4347 4.1.1. "If the application attempts to send a record larger than the MTU,
- * the DTLS implementation SHOULD generate an error, thus avoiding sending a packet
- * which will be fragmented."
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- DatagramPacket packet = new DatagramPacket(buf, off, len);
- socket.send(packet);
- }
-
- public void close()
- throws IOException
- {
- socket.close();
- }
-}
diff --git a/core/src/main/jdk1.3/org/bouncycastle/i18n/LocalizedMessage.java b/core/src/main/jdk1.3/org/bouncycastle/i18n/LocalizedMessage.java
deleted file mode 100644
index dda5342b..00000000
--- a/core/src/main/jdk1.3/org/bouncycastle/i18n/LocalizedMessage.java
+++ /dev/null
@@ -1,464 +0,0 @@
-package org.bouncycastle.i18n;
-
-import org.bouncycastle.i18n.filter.Filter;
-import org.bouncycastle.i18n.filter.TrustedInput;
-import org.bouncycastle.i18n.filter.UntrustedInput;
-import org.bouncycastle.i18n.filter.UntrustedUrlInput;
-
-import java.io.UnsupportedEncodingException;
-import java.text.DateFormat;
-import java.text.Format;
-import java.text.MessageFormat;
-import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-import java.util.TimeZone;
-
-public class LocalizedMessage
-{
-
- protected final String id;
- protected final String resource;
-
- // ISO-8859-1 is the default encoding
- public static final String DEFAULT_ENCODING = "ISO-8859-1";
- protected String encoding = DEFAULT_ENCODING;
-
- protected FilteredArguments arguments;
- protected FilteredArguments extraArgs = null;
-
- protected Filter filter = null;
-
- protected ClassLoader loader = null;
-
- /**
- * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- */
- public LocalizedMessage(String resource,String id) throws NullPointerException
- {
- if (resource == null || id == null)
- {
- throw new NullPointerException();
- }
- this.id = id;
- this.resource = resource;
- arguments = new FilteredArguments();
- }
-
- /**
- * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @param encoding the encoding of the resource file
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- * @throws UnsupportedEncodingException if the encoding is not supported
- */
- public LocalizedMessage(String resource,String id, String encoding) throws NullPointerException, UnsupportedEncodingException
- {
- if (resource == null || id == null)
- {
- throw new NullPointerException();
- }
- this.id = id;
- this.resource = resource;
- arguments = new FilteredArguments();
- this.encoding = encoding;
- }
-
- /**
- * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @param arguments an array containing the arguments for the message
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- */
- public LocalizedMessage(String resource, String id, Object[] arguments) throws NullPointerException
- {
- if (resource == null || id == null || arguments == null)
- {
- throw new NullPointerException();
- }
- this.id = id;
- this.resource = resource;
- this.arguments = new FilteredArguments(arguments);
- }
-
- /**
- * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
- * RessourceBundle and <code>id</code> as the message bundle id the resource file.
- * @param resource base name of the resource file
- * @param id the id of the corresponding bundle in the resource file
- * @param encoding the encoding of the resource file
- * @param arguments an array containing the arguments for the message
- * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
- * @throws UnsupportedEncodingException if the encoding is not supported
- */
- public LocalizedMessage(String resource, String id, String encoding, Object[] arguments) throws NullPointerException, UnsupportedEncodingException
- {
- if (resource == null || id == null || arguments == null)
- {
- throw new NullPointerException();
- }
- this.id = id;
- this.resource = resource;
- this.arguments = new FilteredArguments(arguments);
- this.encoding = encoding;
- }
-
- /**
- * Reads the entry <code>id + "." + key</code> from the resource file and returns a
- * formated message for the given Locale and TimeZone.
- * @param key second part of the entry id
- * @param loc the used {@link Locale}
- * @param timezone the used {@link TimeZone}
- * @return a Strng containing the localized message
- * @throws MissingEntryException if the resource file is not available or the entry does not exist.
- */
- public String getEntry(String key,Locale loc, TimeZone timezone) throws MissingEntryException
- {
- String entry = id;
- if (key != null)
- {
- entry += "." + key;
- }
-
- try
- {
- ResourceBundle bundle;
- if (loader == null)
- {
- bundle = ResourceBundle.getBundle(resource,loc);
- }
- else
- {
- bundle = ResourceBundle.getBundle(resource, loc, loader);
- }
- String result = bundle.getString(entry);
- if (!encoding.equals(DEFAULT_ENCODING))
- {
- result = new String(result.getBytes(DEFAULT_ENCODING), encoding);
- }
- if (!arguments.isEmpty())
- {
- result = formatWithTimeZone(result,arguments.getFilteredArgs(loc),loc,timezone);
- }
- result = addExtraArgs(result, loc);
- return result;
- }
- catch (MissingResourceException mre)
- {
- throw new MissingEntryException("Can't find entry " + entry + " in resource file " + resource + ".",
- resource,
- entry,
- loc,
- loader != null ? loader : this.getClassLoader());
- }
- catch (UnsupportedEncodingException use)
- {
- // should never occur - cause we already test this in the constructor
- throw new RuntimeException(use.toString());
- }
- }
-
- protected String formatWithTimeZone(
- String template,
- Object[] arguments,
- Locale locale,
- TimeZone timezone)
- {
- MessageFormat mf = new MessageFormat(" ");
- mf.setLocale(locale);
- mf.applyPattern(template);
- if (!timezone.equals(TimeZone.getDefault()))
- {
- Format[] formats = mf.getFormats();
- for (int i = 0; i < formats.length; i++)
- {
- if (formats[i] instanceof DateFormat)
- {
- DateFormat temp = (DateFormat) formats[i];
- temp.setTimeZone(timezone);
- mf.setFormat(i,temp);
- }
- }
- }
- return mf.format(arguments);
- }
-
- protected String addExtraArgs(String msg, Locale locale)
- {
- if (extraArgs != null)
- {
- StringBuffer sb = new StringBuffer(msg);
- Object[] filteredArgs = extraArgs.getFilteredArgs(locale);
- for (int i = 0; i < filteredArgs.length; i++)
- {
- sb.append(filteredArgs[i]);
- }
- msg = sb.toString();
- }
- return msg;
- }
-
- /**
- * Sets the {@link Filter} that is used to filter the arguments of this message
- * @param filter the {@link Filter} to use. <code>null</code> to disable filtering.
- */
- public void setFilter(Filter filter)
- {
- arguments.setFilter(filter);
- if (extraArgs != null)
- {
- extraArgs.setFilter(filter);
- }
- this.filter = filter;
- }
-
- /**
- * Returns the current filter.
- * @return the current filter
- */
- public Filter getFilter()
- {
- return filter;
- }
-
- /**
- * Set the {@link ClassLoader} which loads the resource files. If it is set to <code>null</code>
- * then the default {@link ClassLoader} is used.
- * @param loader the {@link ClassLoader} which loads the resource files
- */
- public void setClassLoader(ClassLoader loader)
- {
- this.loader = loader;
- }
-
- /**
- * Returns the {@link ClassLoader} which loads the resource files or <code>null</code>
- * if the default ClassLoader is used.
- * @return the {@link ClassLoader} which loads the resource files
- */
- public ClassLoader getClassLoader()
- {
- return loader;
- }
-
- /**
- * Returns the id of the message in the resource bundle.
- * @return the id of the message
- */
- public String getId()
- {
- return id;
- }
-
- /**
- * Returns the name of the resource bundle for this message
- * @return name of the resource file
- */
- public String getResource()
- {
- return resource;
- }
-
- /**
- * Returns an <code>Object[]</code> containing the message arguments.
- * @return the message arguments
- */
- public Object[] getArguments()
- {
- return arguments.getArguments();
- }
-
- /**
- *
- * @param extraArg
- */
- public void setExtraArgument(Object extraArg)
- {
- setExtraArguments(new Object[] {extraArg});
- }
-
- /**
- *
- * @param extraArgs
- */
- public void setExtraArguments(Object[] extraArgs)
- {
- if (extraArgs != null)
- {
- this.extraArgs = new FilteredArguments(extraArgs);
- this.extraArgs.setFilter(filter);
- }
- else
- {
- this.extraArgs = null;
- }
- }
-
- /**
- *
- * @return
- */
- public Object[] getExtraArgs()
- {
- return (extraArgs == null) ? null : extraArgs.getArguments();
- }
-
- protected class FilteredArguments
- {
- protected static final int NO_FILTER = 0;
- protected static final int FILTER = 1;
- protected static final int FILTER_URL = 2;
-
- protected Filter filter = null;
-
- protected boolean[] isLocaleSpecific;
- protected int[] argFilterType;
- protected Object[] arguments;
- protected Object[] unpackedArgs;
- protected Object[] filteredArgs;
-
- FilteredArguments()
- {
- this(new Object[0]);
- }
-
- FilteredArguments(Object[] args)
- {
- this.arguments = args;
- this.unpackedArgs = new Object[args.length];
- this.filteredArgs = new Object[args.length];
- this.isLocaleSpecific = new boolean[args.length];
- this.argFilterType = new int[args.length];
- for (int i = 0; i < args.length; i++)
- {
- if (args[i] instanceof TrustedInput)
- {
- this.unpackedArgs[i] = ((TrustedInput) args[i]).getInput();
- argFilterType[i] = NO_FILTER;
- }
- else if (args[i] instanceof UntrustedInput)
- {
- this.unpackedArgs[i] = ((UntrustedInput) args[i]).getInput();
- if (args[i] instanceof UntrustedUrlInput)
- {
- argFilterType[i] = FILTER_URL;
- }
- else
- {
- argFilterType[i] = FILTER;
- }
- }
- else
- {
- this.unpackedArgs[i] = args[i];
- argFilterType[i] = FILTER;
- }
-
- // locale specific
- this.isLocaleSpecific[i] = (this.unpackedArgs[i] instanceof LocaleString);
- }
- }
-
- public boolean isEmpty()
- {
- return unpackedArgs.length == 0;
- }
-
- public Object[] getArguments()
- {
- return arguments;
- }
-
- public Object[] getFilteredArgs(Locale locale)
- {
- Object[] result = new Object[unpackedArgs.length];
- for (int i = 0; i < unpackedArgs.length; i++)
- {
- Object arg;
- if (filteredArgs[i] != null)
- {
- arg = filteredArgs[i];
- }
- else
- {
- arg = unpackedArgs[i];
- if (isLocaleSpecific[i])
- {
- // get locale
- arg = ((LocaleString) arg).getLocaleString(locale);
- arg = filter(argFilterType[i], arg);
- }
- else
- {
- arg = filter(argFilterType[i], arg);
- filteredArgs[i] = arg;
- }
- }
- result[i] = arg;
- }
- return result;
- }
-
- private Object filter(int type, Object obj)
- {
- if (filter != null)
- {
- Object o = (null == obj) ? "null" : obj;
- switch (type)
- {
- case NO_FILTER:
- return o;
- case FILTER:
- return filter.doFilter(o.toString());
- case FILTER_URL:
- return filter.doFilterUrl(o.toString());
- default:
- return null;
- }
- }
- else
- {
- return obj;
- }
- }
-
- public Filter getFilter()
- {
- return filter;
- }
-
- public void setFilter(Filter filter)
- {
- if (filter != this.filter)
- {
- for (int i = 0; i < unpackedArgs.length; i++)
- {
- filteredArgs[i] = null;
- }
- }
- this.filter = filter;
- }
-
- }
-
- public String toString()
- {
- StringBuffer sb = new StringBuffer();
- sb.append("Resource: \"").append(resource);
- sb.append("\" Id: \"").append(id).append("\"");
- sb.append(" Arguments: ").append(arguments.getArguments().length).append(" normal, ")
- .append(extraArgs.getArguments().length).append(" extra");
- sb.append(" Encoding: ").append(encoding);
- sb.append(" ClassLoader: ").append(loader);
- return sb.toString();
- }
-
-}
diff --git a/core/src/main/jdk1.3/org/bouncycastle/i18n/MissingEntryException.java b/core/src/main/jdk1.3/org/bouncycastle/i18n/MissingEntryException.java
deleted file mode 100644
index 34022832..00000000
--- a/core/src/main/jdk1.3/org/bouncycastle/i18n/MissingEntryException.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package org.bouncycastle.i18n;
-
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.Locale;
-
-public class MissingEntryException
- extends RuntimeException
-{
-
- protected final String resource;
- protected final String key;
- protected final ClassLoader loader;
- protected final Locale locale;
-
- private Throwable cause;
- private String debugMsg;
-
- public MissingEntryException(String message, String resource, String key, Locale locale, ClassLoader loader)
- {
- super(message);
- this.resource = resource;
- this.key = key;
- this.locale = locale;
- this.loader = loader;
- }
-
- public MissingEntryException(String message, Throwable cause, String resource, String key, Locale locale, ClassLoader loader)
- {
- super(message);
- this.cause = cause;
- this.resource = resource;
- this.key = key;
- this.locale = locale;
- this.loader = loader;
- }
-
- public Throwable getCause()
- {
- return cause;
- }
-
- public String getKey()
- {
- return key;
- }
-
- public String getResource()
- {
- return resource;
- }
-
- public ClassLoader getClassLoader()
- {
- return loader;
- }
-
- public Locale getLocale()
- {
- return locale;
- }
-
- public String getDebugMsg()
- {
- if (debugMsg == null)
- {
- debugMsg = "Can not find entry " + key + " in resource file " + resource + " for the locale " + locale + ".";
- if (loader instanceof URLClassLoader)
- {
- URL[] urls = ((URLClassLoader) loader).getURLs();
- debugMsg += " The following entries in the classpath were searched: ";
- for (int i = 0; i != urls.length; i++)
- {
- debugMsg += urls[i] + " ";
- }
- }
- }
- return debugMsg;
- }
-
-}
diff --git a/core/src/main/jdk1.3/org/spongycastle/asn1/StreamUtil.java b/core/src/main/jdk1.3/org/spongycastle/asn1/StreamUtil.java
new file mode 100644
index 00000000..0b0b183e
--- /dev/null
+++ b/core/src/main/jdk1.3/org/spongycastle/asn1/StreamUtil.java
@@ -0,0 +1,89 @@
+package org.spongycastle.asn1;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+class StreamUtil
+{
+ /**
+ * Find out possible longest length...
+ *
+ * @param in input stream of interest
+ * @return length calculation or MAX_VALUE.
+ */
+ static int findLimit(InputStream in)
+ {
+ if (in instanceof LimitedInputStream)
+ {
+ return ((LimitedInputStream)in).getRemaining();
+ }
+ else if (in instanceof ASN1InputStream)
+ {
+ return ((ASN1InputStream)in).getLimit();
+ }
+ else if (in instanceof ByteArrayInputStream)
+ {
+ return ((ByteArrayInputStream)in).available();
+ }
+
+ return Integer.MAX_VALUE;
+ }
+
+ static int calculateBodyLength(
+ int length)
+ {
+ int count = 1;
+
+ if (length > 127)
+ {
+ int size = 1;
+ int val = length;
+
+ while ((val >>>= 8) != 0)
+ {
+ size++;
+ }
+
+ for (int i = (size - 1) * 8; i >= 0; i -= 8)
+ {
+ count++;
+ }
+ }
+
+ return count;
+ }
+
+ static int calculateTagLength(int tagNo)
+ throws IOException
+ {
+ int length = 1;
+
+ if (tagNo >= 31)
+ {
+ if (tagNo < 128)
+ {
+ length++;
+ }
+ else
+ {
+ byte[] stack = new byte[5];
+ int pos = stack.length;
+
+ stack[--pos] = (byte)(tagNo & 0x7F);
+
+ do
+ {
+ tagNo >>= 7;
+ stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
+ }
+ while (tagNo > 127);
+
+ length += stack.length - pos;
+ }
+ }
+
+ return length;
+ }
+}
diff --git a/core/src/main/jdk1.3/org/spongycastle/crypto/tls/UDPTransport.java b/core/src/main/jdk1.3/org/spongycastle/crypto/tls/UDPTransport.java
new file mode 100644
index 00000000..9391e1d2
--- /dev/null
+++ b/core/src/main/jdk1.3/org/spongycastle/crypto/tls/UDPTransport.java
@@ -0,0 +1,78 @@
+package org.spongycastle.crypto.tls;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+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;
+
+ protected final DatagramSocket socket;
+ protected final int receiveLimit, sendLimit;
+
+ public UDPTransport(DatagramSocket socket, int mtu)
+ throws IOException
+ {
+ //
+ // In 1.3 and earlier sockets were bound and connected during creation
+ //
+ //if (!socket.isBound() || !socket.isConnected())
+ //{
+ // throw new IllegalArgumentException("'socket' must be bound and connected");
+ //}
+
+ this.socket = socket;
+
+ // NOTE: As of JDK 1.6, can use NetworkInterface.getMTU
+
+ this.receiveLimit = mtu - MIN_IP_OVERHEAD - UDP_OVERHEAD;
+ this.sendLimit = mtu - MAX_IP_OVERHEAD - UDP_OVERHEAD;
+ }
+
+ public int getReceiveLimit()
+ {
+ return receiveLimit;
+ }
+
+ public int getSendLimit()
+ {
+ // TODO[DTLS] Implement Path-MTU discovery?
+ return sendLimit;
+ }
+
+ public int receive(byte[] buf, int off, int len, int waitMillis)
+ throws IOException
+ {
+ socket.setSoTimeout(waitMillis);
+ DatagramPacket packet = new DatagramPacket(buf, off, len);
+ socket.receive(packet);
+ return packet.getLength();
+ }
+
+ public void send(byte[] buf, int off, int len)
+ throws IOException
+ {
+ if (len > getSendLimit())
+ {
+ /*
+ * RFC 4347 4.1.1. "If the application attempts to send a record larger than the MTU,
+ * the DTLS implementation SHOULD generate an error, thus avoiding sending a packet
+ * which will be fragmented."
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ DatagramPacket packet = new DatagramPacket(buf, off, len);
+ socket.send(packet);
+ }
+
+ public void close()
+ throws IOException
+ {
+ socket.close();
+ }
+}
diff --git a/core/src/main/jdk1.3/org/spongycastle/i18n/LocalizedMessage.java b/core/src/main/jdk1.3/org/spongycastle/i18n/LocalizedMessage.java
new file mode 100644
index 00000000..e0a4d84c
--- /dev/null
+++ b/core/src/main/jdk1.3/org/spongycastle/i18n/LocalizedMessage.java
@@ -0,0 +1,464 @@
+package org.spongycastle.i18n;
+
+import org.spongycastle.i18n.filter.Filter;
+import org.spongycastle.i18n.filter.TrustedInput;
+import org.spongycastle.i18n.filter.UntrustedInput;
+import org.spongycastle.i18n.filter.UntrustedUrlInput;
+
+import java.io.UnsupportedEncodingException;
+import java.text.DateFormat;
+import java.text.Format;
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.TimeZone;
+
+public class LocalizedMessage
+{
+
+ protected final String id;
+ protected final String resource;
+
+ // ISO-8859-1 is the default encoding
+ public static final String DEFAULT_ENCODING = "ISO-8859-1";
+ protected String encoding = DEFAULT_ENCODING;
+
+ protected FilteredArguments arguments;
+ protected FilteredArguments extraArgs = null;
+
+ protected Filter filter = null;
+
+ protected ClassLoader loader = null;
+
+ /**
+ * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ */
+ public LocalizedMessage(String resource,String id) throws NullPointerException
+ {
+ if (resource == null || id == null)
+ {
+ throw new NullPointerException();
+ }
+ this.id = id;
+ this.resource = resource;
+ arguments = new FilteredArguments();
+ }
+
+ /**
+ * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param encoding the encoding of the resource file
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ * @throws UnsupportedEncodingException if the encoding is not supported
+ */
+ public LocalizedMessage(String resource,String id, String encoding) throws NullPointerException, UnsupportedEncodingException
+ {
+ if (resource == null || id == null)
+ {
+ throw new NullPointerException();
+ }
+ this.id = id;
+ this.resource = resource;
+ arguments = new FilteredArguments();
+ this.encoding = encoding;
+ }
+
+ /**
+ * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param arguments an array containing the arguments for the message
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ */
+ public LocalizedMessage(String resource, String id, Object[] arguments) throws NullPointerException
+ {
+ if (resource == null || id == null || arguments == null)
+ {
+ throw new NullPointerException();
+ }
+ this.id = id;
+ this.resource = resource;
+ this.arguments = new FilteredArguments(arguments);
+ }
+
+ /**
+ * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the
+ * RessourceBundle and <code>id</code> as the message bundle id the resource file.
+ * @param resource base name of the resource file
+ * @param id the id of the corresponding bundle in the resource file
+ * @param encoding the encoding of the resource file
+ * @param arguments an array containing the arguments for the message
+ * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code>
+ * @throws UnsupportedEncodingException if the encoding is not supported
+ */
+ public LocalizedMessage(String resource, String id, String encoding, Object[] arguments) throws NullPointerException, UnsupportedEncodingException
+ {
+ if (resource == null || id == null || arguments == null)
+ {
+ throw new NullPointerException();
+ }
+ this.id = id;
+ this.resource = resource;
+ this.arguments = new FilteredArguments(arguments);
+ this.encoding = encoding;
+ }
+
+ /**
+ * Reads the entry <code>id + "." + key</code> from the resource file and returns a
+ * formated message for the given Locale and TimeZone.
+ * @param key second part of the entry id
+ * @param loc the used {@link Locale}
+ * @param timezone the used {@link TimeZone}
+ * @return a Strng containing the localized message
+ * @throws MissingEntryException if the resource file is not available or the entry does not exist.
+ */
+ public String getEntry(String key,Locale loc, TimeZone timezone) throws MissingEntryException
+ {
+ String entry = id;
+ if (key != null)
+ {
+ entry += "." + key;
+ }
+
+ try
+ {
+ ResourceBundle bundle;
+ if (loader == null)
+ {
+ bundle = ResourceBundle.getBundle(resource,loc);
+ }
+ else
+ {
+ bundle = ResourceBundle.getBundle(resource, loc, loader);
+ }
+ String result = bundle.getString(entry);
+ if (!encoding.equals(DEFAULT_ENCODING))
+ {
+ result = new String(result.getBytes(DEFAULT_ENCODING), encoding);
+ }
+ if (!arguments.isEmpty())
+ {
+ result = formatWithTimeZone(result,arguments.getFilteredArgs(loc),loc,timezone);
+ }
+ result = addExtraArgs(result, loc);
+ return result;
+ }
+ catch (MissingResourceException mre)
+ {
+ throw new MissingEntryException("Can't find entry " + entry + " in resource file " + resource + ".",
+ resource,
+ entry,
+ loc,
+ loader != null ? loader : this.getClassLoader());
+ }
+ catch (UnsupportedEncodingException use)
+ {
+ // should never occur - cause we already test this in the constructor
+ throw new RuntimeException(use.toString());
+ }
+ }
+
+ protected String formatWithTimeZone(
+ String template,
+ Object[] arguments,
+ Locale locale,
+ TimeZone timezone)
+ {
+ MessageFormat mf = new MessageFormat(" ");
+ mf.setLocale(locale);
+ mf.applyPattern(template);
+ if (!timezone.equals(TimeZone.getDefault()))
+ {
+ Format[] formats = mf.getFormats();
+ for (int i = 0; i < formats.length; i++)
+ {
+ if (formats[i] instanceof DateFormat)
+ {
+ DateFormat temp = (DateFormat) formats[i];
+ temp.setTimeZone(timezone);
+ mf.setFormat(i,temp);
+ }
+ }
+ }
+ return mf.format(arguments);
+ }
+
+ protected String addExtraArgs(String msg, Locale locale)
+ {
+ if (extraArgs != null)
+ {
+ StringBuffer sb = new StringBuffer(msg);
+ Object[] filteredArgs = extraArgs.getFilteredArgs(locale);
+ for (int i = 0; i < filteredArgs.length; i++)
+ {
+ sb.append(filteredArgs[i]);
+ }
+ msg = sb.toString();
+ }
+ return msg;
+ }
+
+ /**
+ * Sets the {@link Filter} that is used to filter the arguments of this message
+ * @param filter the {@link Filter} to use. <code>null</code> to disable filtering.
+ */
+ public void setFilter(Filter filter)
+ {
+ arguments.setFilter(filter);
+ if (extraArgs != null)
+ {
+ extraArgs.setFilter(filter);
+ }
+ this.filter = filter;
+ }
+
+ /**
+ * Returns the current filter.
+ * @return the current filter
+ */
+ public Filter getFilter()
+ {
+ return filter;
+ }
+
+ /**
+ * Set the {@link ClassLoader} which loads the resource files. If it is set to <code>null</code>
+ * then the default {@link ClassLoader} is used.
+ * @param loader the {@link ClassLoader} which loads the resource files
+ */
+ public void setClassLoader(ClassLoader loader)
+ {
+ this.loader = loader;
+ }
+
+ /**
+ * Returns the {@link ClassLoader} which loads the resource files or <code>null</code>
+ * if the default ClassLoader is used.
+ * @return the {@link ClassLoader} which loads the resource files
+ */
+ public ClassLoader getClassLoader()
+ {
+ return loader;
+ }
+
+ /**
+ * Returns the id of the message in the resource bundle.
+ * @return the id of the message
+ */
+ public String getId()
+ {
+ return id;
+ }
+
+ /**
+ * Returns the name of the resource bundle for this message
+ * @return name of the resource file
+ */
+ public String getResource()
+ {
+ return resource;
+ }
+
+ /**
+ * Returns an <code>Object[]</code> containing the message arguments.
+ * @return the message arguments
+ */
+ public Object[] getArguments()
+ {
+ return arguments.getArguments();
+ }
+
+ /**
+ *
+ * @param extraArg
+ */
+ public void setExtraArgument(Object extraArg)
+ {
+ setExtraArguments(new Object[] {extraArg});
+ }
+
+ /**
+ *
+ * @param extraArgs
+ */
+ public void setExtraArguments(Object[] extraArgs)
+ {
+ if (extraArgs != null)
+ {
+ this.extraArgs = new FilteredArguments(extraArgs);
+ this.extraArgs.setFilter(filter);
+ }
+ else
+ {
+ this.extraArgs = null;
+ }
+ }
+
+ /**
+ *
+ * @return
+ */
+ public Object[] getExtraArgs()
+ {
+ return (extraArgs == null) ? null : extraArgs.getArguments();
+ }
+
+ protected class FilteredArguments
+ {
+ protected static final int NO_FILTER = 0;
+ protected static final int FILTER = 1;
+ protected static final int FILTER_URL = 2;
+
+ protected Filter filter = null;
+
+ protected boolean[] isLocaleSpecific;
+ protected int[] argFilterType;
+ protected Object[] arguments;
+ protected Object[] unpackedArgs;
+ protected Object[] filteredArgs;
+
+ FilteredArguments()
+ {
+ this(new Object[0]);
+ }
+
+ FilteredArguments(Object[] args)
+ {
+ this.arguments = args;
+ this.unpackedArgs = new Object[args.length];
+ this.filteredArgs = new Object[args.length];
+ this.isLocaleSpecific = new boolean[args.length];
+ this.argFilterType = new int[args.length];
+ for (int i = 0; i < args.length; i++)
+ {
+ if (args[i] instanceof TrustedInput)
+ {
+ this.unpackedArgs[i] = ((TrustedInput) args[i]).getInput();
+ argFilterType[i] = NO_FILTER;
+ }
+ else if (args[i] instanceof UntrustedInput)
+ {
+ this.unpackedArgs[i] = ((UntrustedInput) args[i]).getInput();
+ if (args[i] instanceof UntrustedUrlInput)
+ {
+ argFilterType[i] = FILTER_URL;
+ }
+ else
+ {
+ argFilterType[i] = FILTER;
+ }
+ }
+ else
+ {
+ this.unpackedArgs[i] = args[i];
+ argFilterType[i] = FILTER;
+ }
+
+ // locale specific
+ this.isLocaleSpecific[i] = (this.unpackedArgs[i] instanceof LocaleString);
+ }
+ }
+
+ public boolean isEmpty()
+ {
+ return unpackedArgs.length == 0;
+ }
+
+ public Object[] getArguments()
+ {
+ return arguments;
+ }
+
+ public Object[] getFilteredArgs(Locale locale)
+ {
+ Object[] result = new Object[unpackedArgs.length];
+ for (int i = 0; i < unpackedArgs.length; i++)
+ {
+ Object arg;
+ if (filteredArgs[i] != null)
+ {
+ arg = filteredArgs[i];
+ }
+ else
+ {
+ arg = unpackedArgs[i];
+ if (isLocaleSpecific[i])
+ {
+ // get locale
+ arg = ((LocaleString) arg).getLocaleString(locale);
+ arg = filter(argFilterType[i], arg);
+ }
+ else
+ {
+ arg = filter(argFilterType[i], arg);
+ filteredArgs[i] = arg;
+ }
+ }
+ result[i] = arg;
+ }
+ return result;
+ }
+
+ private Object filter(int type, Object obj)
+ {
+ if (filter != null)
+ {
+ Object o = (null == obj) ? "null" : obj;
+ switch (type)
+ {
+ case NO_FILTER:
+ return o;
+ case FILTER:
+ return filter.doFilter(o.toString());
+ case FILTER_URL:
+ return filter.doFilterUrl(o.toString());
+ default:
+ return null;
+ }
+ }
+ else
+ {
+ return obj;
+ }
+ }
+
+ public Filter getFilter()
+ {
+ return filter;
+ }
+
+ public void setFilter(Filter filter)
+ {
+ if (filter != this.filter)
+ {
+ for (int i = 0; i < unpackedArgs.length; i++)
+ {
+ filteredArgs[i] = null;
+ }
+ }
+ this.filter = filter;
+ }
+
+ }
+
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append("Resource: \"").append(resource);
+ sb.append("\" Id: \"").append(id).append("\"");
+ sb.append(" Arguments: ").append(arguments.getArguments().length).append(" normal, ")
+ .append(extraArgs.getArguments().length).append(" extra");
+ sb.append(" Encoding: ").append(encoding);
+ sb.append(" ClassLoader: ").append(loader);
+ return sb.toString();
+ }
+
+}
diff --git a/core/src/main/jdk1.3/org/spongycastle/i18n/MissingEntryException.java b/core/src/main/jdk1.3/org/spongycastle/i18n/MissingEntryException.java
new file mode 100644
index 00000000..582b9ab9
--- /dev/null
+++ b/core/src/main/jdk1.3/org/spongycastle/i18n/MissingEntryException.java
@@ -0,0 +1,81 @@
+package org.spongycastle.i18n;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Locale;
+
+public class MissingEntryException
+ extends RuntimeException
+{
+
+ protected final String resource;
+ protected final String key;
+ protected final ClassLoader loader;
+ protected final Locale locale;
+
+ private Throwable cause;
+ private String debugMsg;
+
+ public MissingEntryException(String message, String resource, String key, Locale locale, ClassLoader loader)
+ {
+ super(message);
+ this.resource = resource;
+ this.key = key;
+ this.locale = locale;
+ this.loader = loader;
+ }
+
+ public MissingEntryException(String message, Throwable cause, String resource, String key, Locale locale, ClassLoader loader)
+ {
+ super(message);
+ this.cause = cause;
+ this.resource = resource;
+ this.key = key;
+ this.locale = locale;
+ this.loader = loader;
+ }
+
+ public Throwable getCause()
+ {
+ return cause;
+ }
+
+ public String getKey()
+ {
+ return key;
+ }
+
+ public String getResource()
+ {
+ return resource;
+ }
+
+ public ClassLoader getClassLoader()
+ {
+ return loader;
+ }
+
+ public Locale getLocale()
+ {
+ return locale;
+ }
+
+ public String getDebugMsg()
+ {
+ if (debugMsg == null)
+ {
+ debugMsg = "Can not find entry " + key + " in resource file " + resource + " for the locale " + locale + ".";
+ if (loader instanceof URLClassLoader)
+ {
+ URL[] urls = ((URLClassLoader) loader).getURLs();
+ debugMsg += " The following entries in the classpath were searched: ";
+ for (int i = 0; i != urls.length; i++)
+ {
+ debugMsg += urls[i] + " ";
+ }
+ }
+ }
+ return debugMsg;
+ }
+
+}
diff --git a/core/src/main/jdk1.4/org/bouncycastle/util/Integers.java b/core/src/main/jdk1.4/org/bouncycastle/util/Integers.java
deleted file mode 100644
index e461a77c..00000000
--- a/core/src/main/jdk1.4/org/bouncycastle/util/Integers.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.bouncycastle.util;
-
-public class Integers
-{
- public static int rotateLeft(int i, int distance)
- {
- return (i << distance) ^ (i >>> -distance);
- }
-
- public static int rotateRight(int i, int distance)
- {
- return (i >>> distance) ^ (i << -distance);
- }
-
- public static Integer valueOf(int value)
- {
- return new Integer(value);
- }
-}
diff --git a/core/src/main/jdk1.4/org/bouncycastle/util/Shorts.java b/core/src/main/jdk1.4/org/bouncycastle/util/Shorts.java
deleted file mode 100644
index 71f04fd0..00000000
--- a/core/src/main/jdk1.4/org/bouncycastle/util/Shorts.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.bouncycastle.util;
-
-public class Shorts
-{
- public static Short valueOf(short value)
- {
- return new Short(value);
- }
-}
diff --git a/core/src/main/jdk1.4/org/bouncycastle/util/Times.java b/core/src/main/jdk1.4/org/bouncycastle/util/Times.java
deleted file mode 100644
index d21518fa..00000000
--- a/core/src/main/jdk1.4/org/bouncycastle/util/Times.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.bouncycastle.util;
-
-public final class Times
-{
- private static long NANOS_PER_MILLI = 1000000L;
-
- public static long nanoTime()
- {
- return NANOS_PER_MILLI * System.currentTimeMillis();
- }
-}
diff --git a/core/src/main/jdk1.4/org/spongycastle/util/Integers.java b/core/src/main/jdk1.4/org/spongycastle/util/Integers.java
new file mode 100644
index 00000000..bf6b5e34
--- /dev/null
+++ b/core/src/main/jdk1.4/org/spongycastle/util/Integers.java
@@ -0,0 +1,19 @@
+package org.spongycastle.util;
+
+public class Integers
+{
+ public static int rotateLeft(int i, int distance)
+ {
+ return (i << distance) ^ (i >>> -distance);
+ }
+
+ public static int rotateRight(int i, int distance)
+ {
+ return (i >>> distance) ^ (i << -distance);
+ }
+
+ public static Integer valueOf(int value)
+ {
+ return new Integer(value);
+ }
+}
diff --git a/core/src/main/jdk1.4/org/spongycastle/util/Shorts.java b/core/src/main/jdk1.4/org/spongycastle/util/Shorts.java
new file mode 100644
index 00000000..66a992f7
--- /dev/null
+++ b/core/src/main/jdk1.4/org/spongycastle/util/Shorts.java
@@ -0,0 +1,9 @@
+package org.spongycastle.util;
+
+public class Shorts
+{
+ public static Short valueOf(short value)
+ {
+ return new Short(value);
+ }
+}
diff --git a/core/src/main/jdk1.4/org/spongycastle/util/Times.java b/core/src/main/jdk1.4/org/spongycastle/util/Times.java
new file mode 100644
index 00000000..f88b5395
--- /dev/null
+++ b/core/src/main/jdk1.4/org/spongycastle/util/Times.java
@@ -0,0 +1,11 @@
+package org.spongycastle.util;
+
+public final class Times
+{
+ private static long NANOS_PER_MILLI = 1000000L;
+
+ public static long nanoTime()
+ {
+ return NANOS_PER_MILLI * System.currentTimeMillis();
+ }
+}
diff --git a/core/src/test/j2me/java/math/test/BigIntegerTest.java b/core/src/test/j2me/java/math/test/BigIntegerTest.java
index 379765b0..235d695a 100644
--- a/core/src/test/j2me/java/math/test/BigIntegerTest.java
+++ b/core/src/test/j2me/java/math/test/BigIntegerTest.java
@@ -2,7 +2,7 @@ package java.math.test;
import java.math.BigInteger;
import java.security.SecureRandom;
-import org.bouncycastle.util.test.*;
+import org.spongycastle.util.test.*;
public class BigIntegerTest
extends SimpleTest
diff --git a/core/src/test/j2me/java/math/test/RegressionTest.java b/core/src/test/j2me/java/math/test/RegressionTest.java
index bbfc2995..79d8b590 100644
--- a/core/src/test/j2me/java/math/test/RegressionTest.java
+++ b/core/src/test/j2me/java/math/test/RegressionTest.java
@@ -1,7 +1,7 @@
package java.math.test;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
public class RegressionTest
{
diff --git a/core/src/test/j2me/org/bouncycastle/asn1/test/GeneralizedTimeTest.java b/core/src/test/j2me/org/bouncycastle/asn1/test/GeneralizedTimeTest.java
deleted file mode 100644
index 22844c29..00000000
--- a/core/src/test/j2me/org/bouncycastle/asn1/test/GeneralizedTimeTest.java
+++ /dev/null
@@ -1,189 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.util.Date;
-import java.util.TimeZone;
-
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.DERGeneralizedTime;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * X.690 test example
- */
-public class GeneralizedTimeTest
- extends SimpleTest
-{
- String[] input =
- {
- "20020122122220",
- "20020122122220Z",
- "20020122122220-1000",
- "20020122122220+00",
- "20020122122220.1",
- "20020122122220.1Z",
- "20020122122220.1-1000",
- "20020122122220.1+00",
- "20020122122220.01",
- "20020122122220.01Z",
- "20020122122220.01-1000",
- "20020122122220.01+00",
- "20020122122220.001",
- "20020122122220.001Z",
- "20020122122220.001-1000",
- "20020122122220.001+00",
- "20020122122220.0001",
- "20020122122220.0001Z",
- "20020122122220.0001-1000",
- "20020122122220.0001+00",
- "20020122122220.0001+1000"
- };
-
- String[] output = {
- "20020122122220",
- "20020122122220GMT+00:00",
- "20020122122220GMT-10:00",
- "20020122122220GMT+00:00",
- "20020122122220.1",
- "20020122122220.1GMT+00:00",
- "20020122122220.1GMT-10:00",
- "20020122122220.1GMT+00:00",
- "20020122122220.01",
- "20020122122220.01GMT+00:00",
- "20020122122220.01GMT-10:00",
- "20020122122220.01GMT+00:00",
- "20020122122220.001",
- "20020122122220.001GMT+00:00",
- "20020122122220.001GMT-10:00",
- "20020122122220.001GMT+00:00",
- "20020122122220.0001",
- "20020122122220.0001GMT+00:00",
- "20020122122220.0001GMT-10:00",
- "20020122122220.0001GMT+00:00",
- "20020122122220.0001GMT+10:00" };
-
- String[] zOutput = {
- "20020122122220Z",
- "20020122122220Z",
- "20020122222220Z",
- "20020122122220Z",
- "20020122122220Z",
- "20020122122220Z",
- "20020122222220Z",
- "20020122122220Z",
- "20020122122220Z",
- "20020122122220Z",
- "20020122222220Z",
- "20020122122220Z",
- "20020122122220Z",
- "20020122122220Z",
- "20020122222220Z",
- "20020122122220Z",
- "20020122122220Z",
- "20020122122220Z",
- "20020122222220Z",
- "20020122122220Z",
- "20020122022220Z"
- };
-
- String[] mzOutput = {
- "20020122122220.000Z",
- "20020122122220.000Z",
- "20020122222220.000Z",
- "20020122122220.000Z",
- "20020122122220.100Z",
- "20020122122220.100Z",
- "20020122222220.100Z",
- "20020122122220.100Z",
- "20020122122220.010Z",
- "20020122122220.010Z",
- "20020122222220.010Z",
- "20020122122220.010Z",
- "20020122122220.001Z",
- "20020122122220.001Z",
- "20020122222220.001Z",
- "20020122122220.001Z",
- "20020122122220.000Z",
- "20020122122220.000Z",
- "20020122222220.000Z",
- "20020122122220.000Z",
- "20020122022220.000Z"
- };
-
- public String getName()
- {
- return "GeneralizedTime";
- }
-
- public void performTest()
- throws Exception
- {
- for (int i = 0; i != input.length; i++)
- {
- DERGeneralizedTime t = new DERGeneralizedTime(input[i]);
-
- if (output[i].indexOf('G') > 0) // don't check local time the same way
- {
- if (!t.getTime().equals(output[i]))
- {
- fail("failed conversion test");
- }
- }
- else
- {
- String offset = calculateGMTOffset(t.getDate());
-
- if (!t.getTime().equals(output[i] + offset))
- {
- fail("failed conversion test");
- }
- }
- }
-
- for (int i = 0; i != input.length; i++)
- {
- ASN1GeneralizedTime t = new ASN1GeneralizedTime(mzOutput[i]);
-
- if (!new ASN1GeneralizedTime(t.getDate(), true).getDate().equals(t.getDate()))
- {
- fail("failed equality test");
- }
- }
- }
-
- private String calculateGMTOffset(Date date)
- {
- String sign = "+";
- TimeZone timeZone = TimeZone.getDefault();
- int offset = timeZone.getRawOffset();
- if (offset < 0)
- {
- sign = "-";
- offset = -offset;
- }
- int hours = offset / (60 * 60 * 1000);
- int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000);
-
-// if (timeZone.useDaylightTime() && timeZone.inDaylightTime(date))
-// {
-// hours += sign.equals("+") ? 1 : -1;
-// }
-
- return "GMT" + sign + convert(hours) + ":" + convert(minutes);
- }
-
- private String convert(int time)
- {
- if (time < 10)
- {
- return "0" + time;
- }
-
- return Integer.toString(time);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new GeneralizedTimeTest());
- }
-}
diff --git a/core/src/test/j2me/org/bouncycastle/asn1/test/RegressionTest.java b/core/src/test/j2me/org/bouncycastle/asn1/test/RegressionTest.java
deleted file mode 100644
index 54c2ea77..00000000
--- a/core/src/test/j2me/org/bouncycastle/asn1/test/RegressionTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-public class RegressionTest
-{
- public static Test[] tests = {
- new CertificateTest(),
- new CMSTest(),
- new OCSPTest(),
- new OIDTest(),
- new PKCS10Test(),
- new PKCS12Test(),
- new X509NameTest(),
- new X500NameTest(),
- new X509ExtensionsTest(),
- new BitStringTest(),
- new MiscTest(),
- new X9Test(),
- new EncryptedPrivateKeyInfoTest(),
- new StringTest(),
- new RequestedCertificateUnitTest(),
- new OtherCertIDUnitTest(),
- new OtherSigningCertificateUnitTest(),
- new ContentHintsUnitTest(),
- new CertHashUnitTest(),
- new AdditionalInformationSyntaxUnitTest(),
- new AdmissionSyntaxUnitTest(),
- new AdmissionsUnitTest(),
- new DeclarationOfMajorityUnitTest(),
- new ProcurationSyntaxUnitTest(),
- new ProfessionInfoUnitTest(),
- new RestrictionUnitTest(),
- new NamingAuthorityUnitTest(),
- new MonetaryLimitUnitTest(),
- new DERApplicationSpecificTest(),
- new IssuingDistributionPointUnitTest(),
- new TargetInformationTest(),
- new SubjectKeyIdentifierTest(),
- new ESSCertIDv2UnitTest(),
- new ParsingTest(),
- new GeneralNameTest(),
- new RFC4519Test()
- };
-
- public static void main(
- String[] args)
- {
- for (int i = 0; i != tests.length; i++)
- {
- TestResult result = tests[i].perform();
-
- if (result.getException() != null)
- {
- result.getException().printStackTrace();
- }
-
- System.out.println(result);
- }
- }
-}
-
diff --git a/core/src/test/j2me/org/bouncycastle/asn1/test/UTCTimeTest.java b/core/src/test/j2me/org/bouncycastle/asn1/test/UTCTimeTest.java
deleted file mode 100644
index e25bd9cd..00000000
--- a/core/src/test/j2me/org/bouncycastle/asn1/test/UTCTimeTest.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import org.bouncycastle.asn1.ASN1UTCTime;
-import org.bouncycastle.asn1.DERUTCTime;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * X.690 test example
- */
-public class UTCTimeTest
- extends SimpleTest
-{
- String[] input =
- {
- "020122122220Z",
- "020122122220-1000",
- "020122122220+1000",
- "020122122220+00",
- "0201221222Z",
- "0201221222-1000",
- "0201221222+1000",
- "0201221222+00",
- "550122122220Z",
- "5501221222Z"
- };
-
- String[] output = {
- "20020122122220GMT+00:00",
- "20020122122220GMT-10:00",
- "20020122122220GMT+10:00",
- "20020122122220GMT+00:00",
- "20020122122200GMT+00:00",
- "20020122122200GMT-10:00",
- "20020122122200GMT+10:00",
- "20020122122200GMT+00:00",
- "19550122122220GMT+00:00",
- "19550122122200GMT+00:00"
- };
-
- String[] zOutput1 = {
- "20020122122220Z",
- "20020122222220Z",
- "20020122022220Z",
- "20020122122220Z",
- "20020122122200Z",
- "20020122222200Z",
- "20020122022200Z",
- "20020122122200Z",
- "19550122122220Z",
- "19550122122200Z"
- };
-
- String[] zOutput2 = {
- "20020122122220Z",
- "20020122222220Z",
- "20020122022220Z",
- "20020122122220Z",
- "20020122122200Z",
- "20020122222200Z",
- "20020122022200Z",
- "20020122122200Z",
- "19550122122220Z",
- "19550122122200Z"
- };
-
- public String getName()
- {
- return "UTCTime";
- }
-
- public void performTest()
- throws Exception
- {
-
- for (int i = 0; i != input.length; i++)
- {
- DERUTCTime t = new DERUTCTime(input[i]);
-
- if (!t.getAdjustedTime().equals(output[i]))
- {
- fail("failed conversion test " + i);
- }
-
- t = new ASN1UTCTime(zOutput1[i].substring(2));
-
- if (!new ASN1UTCTime(t.getAdjustedDate()).getAdjustedTime().equals(t.getAdjustedTime()))
- {
- fail("failed equality test");
- }
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new UTCTimeTest());
- }
-}
diff --git a/core/src/test/j2me/org/bouncycastle/crypto/test/BigIntegerTest.java b/core/src/test/j2me/org/bouncycastle/crypto/test/BigIntegerTest.java
deleted file mode 100644
index 025f4775..00000000
--- a/core/src/test/j2me/org/bouncycastle/crypto/test/BigIntegerTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.util.test.*;
-
-public class BigIntegerTest
-{
- public static Test[] tests = {
- new DHTest(),
- new ElGamalTest(),
- new DSATest(),
- new ECTest(),
- new ECIESTest(),
- new RSATest(),
- new ISO9796Test(),
- new OAEPTest(),
- new PSSTest(),
- new CTSTest(),
- new PKCS5Test(),
- new PKCS12Test()
- };
-
- public static void main(
- String[] args)
- {
- for (int i = 0; i != tests.length; i++)
- {
- TestResult result = tests[i].perform();
- System.out.println(result);
- }
- }
-}
-
diff --git a/core/src/test/j2me/org/bouncycastle/crypto/test/CryptoRegressionTest.java b/core/src/test/j2me/org/bouncycastle/crypto/test/CryptoRegressionTest.java
deleted file mode 100644
index 1780ac0f..00000000
--- a/core/src/test/j2me/org/bouncycastle/crypto/test/CryptoRegressionTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.util.test.*;
-
-public class CryptoRegressionTest
-{
- public static Test[] tests = {
- new AESTest(),
- new DESTest(),
- new DESedeTest(),
- new ModeTest(),
- new DHTest(),
- new ElGamalTest(),
- new DSATest(),
- new ECTest(),
- new ECIESTest(),
- new MacTest(),
- new RC2Test(),
- new RC4Test(),
- new RC5Test(),
- new RC6Test(),
- new RijndaelTest(),
- new SerpentTest(),
- new SkipjackTest(),
- new BlowfishTest(),
- new TwofishTest(),
- new CAST5Test(),
- new CAST6Test(),
- new IDEATest(),
- new CamelliaTest(),
- new RSATest(),
- new ISO9796Test(),
- new MD2DigestTest(),
- new MD4DigestTest(),
- new MD5DigestTest(),
- new SHA1DigestTest(),
- new SHA256DigestTest(),
- new SHA384DigestTest(),
- new SHA512DigestTest(),
- new RIPEMD128DigestTest(),
- new RIPEMD160DigestTest(),
- new TigerDigestTest(),
- new MD5HMacTest(),
- new SHA1HMacTest(),
- new RIPEMD128HMacTest(),
- new RIPEMD160HMacTest(),
- /* new OAEPTest() */
- new PSSTest(),
- new CTSTest(),
- /* new PKCS5Test() */
- new PKCS12Test()
- };
-
- public static void main(
- String[] args)
- {
- for (int i = 0; i != tests.length; i++)
- {
- TestResult result = tests[i].perform();
- System.out.println(result);
- }
- }
-}
-
diff --git a/core/src/test/j2me/org/bouncycastle/crypto/test/RSATest.java b/core/src/test/j2me/org/bouncycastle/crypto/test/RSATest.java
deleted file mode 100644
index 2369d1c5..00000000
--- a/core/src/test/j2me/org/bouncycastle/crypto/test/RSATest.java
+++ /dev/null
@@ -1,480 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.encodings.OAEPEncoding;
-import org.bouncycastle.crypto.encodings.PKCS1Encoding;
-import org.bouncycastle.crypto.engines.RSAEngine;
-import org.bouncycastle.crypto.generators.RSAKeyPairGenerator;
-import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class RSATest
- extends SimpleTest
-{
- static BigInteger mod = new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16);
- static BigInteger pubExp = new BigInteger("11", 16);
- static BigInteger privExp = new BigInteger("92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619", 16);
- static BigInteger p = new BigInteger("f75e80839b9b9379f1cf1128f321639757dba514642c206bbbd99f9a4846208b3e93fbbe5e0527cc59b1d4b929d9555853004c7c8b30ee6a213c3d1bb7415d03", 16);
- static BigInteger q = new BigInteger("b892d9ebdbfc37e397256dd8a5d3123534d1f03726284743ddc6be3a709edb696fc40c7d902ed804c6eee730eee3d5b20bf6bd8d87a296813c87d3b3cc9d7947", 16);
- static BigInteger pExp = new BigInteger("1d1a2d3ca8e52068b3094d501c9a842fec37f54db16e9a67070a8b3f53cc03d4257ad252a1a640eadd603724d7bf3737914b544ae332eedf4f34436cac25ceb5", 16);
- static BigInteger qExp = new BigInteger("6c929e4e81672fef49d9c825163fec97c4b7ba7acb26c0824638ac22605d7201c94625770984f78a56e6e25904fe7db407099cad9b14588841b94f5ab498dded", 16);
- static BigInteger crtCoef = new BigInteger("dae7651ee69ad1d081ec5e7188ae126f6004ff39556bde90e0b870962fa7b926d070686d8244fe5a9aa709a95686a104614834b0ada4b10f53197a5cb4c97339", 16);
-
- static String input = "4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
-
- //
- // to check that we handling byte extension by big number correctly.
- //
- static String edgeInput = "ff6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
-
- static byte[] oversizedSig = Hex.decode("01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
- static byte[] dudBlock = Hex.decode("000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
- static byte[] truncatedDataBlock = Hex.decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
- static byte[] incorrectPadding = Hex.decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
- static byte[] missingDataBlock = Hex.decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
-
- public String getName()
- {
- return "RSA";
- }
-
- private void testStrictPKCS1Length(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
- {
- AsymmetricBlockCipher eng = new RSAEngine();
-
- eng.init(true, privParameters);
-
- byte[] data = null;
-
- try
- {
- data = eng.processBlock(oversizedSig, 0, oversizedSig.length);
- }
- catch (Exception e)
- {
- fail("RSA: failed - exception " + e.toString(), e);
- }
-
- eng = new PKCS1Encoding(eng);
-
- eng.init(false, pubParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
-
- fail("oversized signature block not recognised");
- }
- catch (InvalidCipherTextException e)
- {
- if (!e.getMessage().equals("block incorrect size"))
- {
- fail("RSA: failed - exception " + e.toString(), e);
- }
- }
- }
-
- private void testTruncatedPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
- {
- checkForPKCS1Exception(pubParameters, privParameters, truncatedDataBlock, "block truncated");
- }
-
- private void testDudPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
- {
- checkForPKCS1Exception(pubParameters, privParameters, dudBlock, "unknown block type");
- }
-
- private void testWrongPaddingPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
- {
- checkForPKCS1Exception(pubParameters, privParameters, incorrectPadding, "block padding incorrect");
- }
-
- private void testMissingDataPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
- {
- checkForPKCS1Exception(pubParameters, privParameters, missingDataBlock, "no data in block");
- }
-
- private void checkForPKCS1Exception(RSAKeyParameters pubParameters, RSAKeyParameters privParameters, byte[] inputData, String expectedMessage)
- {
- AsymmetricBlockCipher eng = new RSAEngine();
-
- eng.init(true, privParameters);
-
- byte[] data = null;
-
- try
- {
- data = eng.processBlock(inputData, 0, inputData.length);
- }
- catch (Exception e)
- {
- fail("RSA: failed - exception " + e.toString(), e);
- }
-
- eng = new PKCS1Encoding(eng);
-
- eng.init(false, pubParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
-
- fail("missing data block not recognised");
- }
- catch (InvalidCipherTextException e)
- {
- if (!e.getMessage().equals(expectedMessage))
- {
- fail("RSA: failed - exception " + e.toString(), e);
- }
- }
- }
-
- private void testOAEP(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
- {
- //
- // OAEP - public encrypt, private decrypt
- //
- AsymmetricBlockCipher eng = new OAEPEncoding(new RSAEngine());
- byte[] data = Hex.decode(input);
-
- eng.init(true, pubParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- eng.init(false, privParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- if (!input.equals(new String(Hex.encode(data))))
- {
- fail("failed OAEP Test");
- }
- }
-
- private void zeroBlockTest(CipherParameters encParameters, CipherParameters decParameters)
- {
- AsymmetricBlockCipher eng = new PKCS1Encoding(new RSAEngine());
-
- eng.init(true, encParameters);
-
- if (eng.getOutputBlockSize() != ((PKCS1Encoding)eng).getUnderlyingCipher().getOutputBlockSize())
- {
- fail("PKCS1 output block size incorrect");
- }
-
- byte[] zero = new byte[0];
- byte[] data = null;
-
- try
- {
- data = eng.processBlock(zero, 0, zero.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- eng.init(false, decParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- if (!Arrays.areEqual(zero, data))
- {
- fail("failed PKCS1 zero Test");
- }
- }
-
- public void performTest()
- {
- RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod, pubExp);
- RSAKeyParameters privParameters = new RSAPrivateCrtKeyParameters(mod, pubExp, privExp, p, q, pExp, qExp, crtCoef);
- byte[] data = Hex.decode(edgeInput);
-
- //
- // RAW
- //
- AsymmetricBlockCipher eng = new RSAEngine();
-
- eng.init(true, pubParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("RSA: failed - exception " + e.toString(), e);
- }
-
- eng.init(false, privParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- if (!edgeInput.equals(new String(Hex.encode(data))))
- {
- fail("failed RAW edge Test");
- }
-
- data = Hex.decode(input);
-
- eng.init(true, pubParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- eng.init(false, privParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- if (!input.equals(new String(Hex.encode(data))))
- {
- fail("failed RAW Test");
- }
-
- //
- // PKCS1 - public encrypt, private decrypt
- //
- eng = new PKCS1Encoding(eng);
-
- eng.init(true, pubParameters);
-
- if (eng.getOutputBlockSize() != ((PKCS1Encoding)eng).getUnderlyingCipher().getOutputBlockSize())
- {
- fail("PKCS1 output block size incorrect");
- }
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- eng.init(false, privParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- if (!input.equals(new String(Hex.encode(data))))
- {
- fail("failed PKCS1 public/private Test");
- }
-
- //
- // PKCS1 - private encrypt, public decrypt
- //
- eng = new PKCS1Encoding(((PKCS1Encoding)eng).getUnderlyingCipher());
-
- eng.init(true, privParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- eng.init(false, pubParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- if (!input.equals(new String(Hex.encode(data))))
- {
- fail("failed PKCS1 private/public Test");
- }
-
- zeroBlockTest(pubParameters, privParameters);
- zeroBlockTest(privParameters, pubParameters);
-
- //
- // key generation test
- //
- RSAKeyPairGenerator pGen = new RSAKeyPairGenerator();
- RSAKeyGenerationParameters genParam = new RSAKeyGenerationParameters(
- BigInteger.valueOf(0x11), new SecureRandom(), 768, 25);
-
- pGen.init(genParam);
-
- AsymmetricCipherKeyPair pair = pGen.generateKeyPair();
-
- eng = new RSAEngine();
-
- if (((RSAKeyParameters)pair.getPublic()).getModulus().bitLength() < 768)
- {
- fail("failed key generation (768) length test");
- }
-
- eng.init(true, pair.getPublic());
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- eng.init(false, pair.getPrivate());
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- if (!input.equals(new String(Hex.encode(data))))
- {
- fail("failed key generation (768) Test");
- }
-
- genParam = new RSAKeyGenerationParameters(BigInteger.valueOf(0x11), new SecureRandom(), 1024, 25);
-
- pGen.init(genParam);
- pair = pGen.generateKeyPair();
-
- eng.init(true, pair.getPublic());
-
- if (((RSAKeyParameters)pair.getPublic()).getModulus().bitLength() < 1024)
- {
- fail("failed key generation (1024) length test");
- }
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- eng.init(false, pair.getPrivate());
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- if (!input.equals(new String(Hex.encode(data))))
- {
- fail("failed key generation (1024) test");
- }
-
- genParam = new RSAKeyGenerationParameters(
- BigInteger.valueOf(0x11), new SecureRandom(), 16, 25);
- pGen.init(genParam);
-
- for (int i = 0; i < 100; ++i)
- {
- pair = pGen.generateKeyPair();
- RSAPrivateCrtKeyParameters privKey = (RSAPrivateCrtKeyParameters) pair.getPrivate();
- BigInteger pqDiff = privKey.getP().subtract(privKey.getQ()).abs();
-
- if (pqDiff.bitLength() < 5)
- {
- fail("P and Q too close in RSA key pair");
- }
- }
-
- testOAEP(pubParameters, privParameters);
- testStrictPKCS1Length(pubParameters, privParameters);
- testDudPKCS1Block(pubParameters, privParameters);
- testMissingDataPKCS1Block(pubParameters, privParameters);
- testTruncatedPKCS1Block(pubParameters, privParameters);
- testWrongPaddingPKCS1Block(pubParameters, privParameters);
-
- try
- {
- new RSAEngine().processBlock(new byte[]{ 1 }, 0, 1);
- fail("failed initialisation check");
- }
- catch (IllegalStateException e)
- {
- // expected
- }
- }
-
-
- public static void main(
- String[] args)
- {
- runTest(new RSATest());
- }
-}
diff --git a/core/src/test/j2me/org/bouncycastle/crypto/test/RegressionTest.java b/core/src/test/j2me/org/bouncycastle/crypto/test/RegressionTest.java
deleted file mode 100644
index f8d37aaa..00000000
--- a/core/src/test/j2me/org/bouncycastle/crypto/test/RegressionTest.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-public final class RegressionTest
-{
- public static Test[] tests = {
- new AESTest(),
- new DESTest(),
- new DESedeTest(),
- new ModeTest(),
- new DHTest(),
- new ElGamalTest(),
- new DSATest(),
- new ECTest(),
- new ECIESTest(),
- new MacTest(),
- new RC2Test(),
- new RC4Test(),
- new RC5Test(),
- new RC6Test(),
- new RijndaelTest(),
- new SerpentTest(),
- new SkipjackTest(),
- new BlowfishTest(),
- new TwofishTest(),
- new CAST5Test(),
- new CAST6Test(),
- new IDEATest(),
- new CamelliaTest(),
- new RSATest(),
- new ISO9796Test(),
- new MD2DigestTest(),
- new MD4DigestTest(),
- new MD5DigestTest(),
- new SHA1DigestTest(),
- new SHA256DigestTest(),
- new SHA384DigestTest(),
- new SHA512DigestTest(),
- new RIPEMD128DigestTest(),
- new RIPEMD160DigestTest(),
- new TigerDigestTest(),
- new MD5HMacTest(),
- new SHA1HMacTest(),
- new RIPEMD128HMacTest(),
- new RIPEMD160HMacTest(),
- new OAEPTest(),
- new PSSTest(),
- new CTSTest(),
- new PKCS5Test(),
- new PKCS12Test(),
- new GOST28147Test(),
- new GOST3410Test(),
- new WhirlpoolDigestTest()
- };
-
- public static void main(
- String[] args)
- {
- for (int i = 0; i != tests.length; i++)
- {
- TestResult result = tests[i].perform();
- System.out.println(result);
- }
- }
-}
-
diff --git a/core/src/test/j2me/org/spongycastle/asn1/test/GeneralizedTimeTest.java b/core/src/test/j2me/org/spongycastle/asn1/test/GeneralizedTimeTest.java
new file mode 100644
index 00000000..707fcb99
--- /dev/null
+++ b/core/src/test/j2me/org/spongycastle/asn1/test/GeneralizedTimeTest.java
@@ -0,0 +1,189 @@
+package org.spongycastle.asn1.test;
+
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.DERGeneralizedTime;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * X.690 test example
+ */
+public class GeneralizedTimeTest
+ extends SimpleTest
+{
+ String[] input =
+ {
+ "20020122122220",
+ "20020122122220Z",
+ "20020122122220-1000",
+ "20020122122220+00",
+ "20020122122220.1",
+ "20020122122220.1Z",
+ "20020122122220.1-1000",
+ "20020122122220.1+00",
+ "20020122122220.01",
+ "20020122122220.01Z",
+ "20020122122220.01-1000",
+ "20020122122220.01+00",
+ "20020122122220.001",
+ "20020122122220.001Z",
+ "20020122122220.001-1000",
+ "20020122122220.001+00",
+ "20020122122220.0001",
+ "20020122122220.0001Z",
+ "20020122122220.0001-1000",
+ "20020122122220.0001+00",
+ "20020122122220.0001+1000"
+ };
+
+ String[] output = {
+ "20020122122220",
+ "20020122122220GMT+00:00",
+ "20020122122220GMT-10:00",
+ "20020122122220GMT+00:00",
+ "20020122122220.1",
+ "20020122122220.1GMT+00:00",
+ "20020122122220.1GMT-10:00",
+ "20020122122220.1GMT+00:00",
+ "20020122122220.01",
+ "20020122122220.01GMT+00:00",
+ "20020122122220.01GMT-10:00",
+ "20020122122220.01GMT+00:00",
+ "20020122122220.001",
+ "20020122122220.001GMT+00:00",
+ "20020122122220.001GMT-10:00",
+ "20020122122220.001GMT+00:00",
+ "20020122122220.0001",
+ "20020122122220.0001GMT+00:00",
+ "20020122122220.0001GMT-10:00",
+ "20020122122220.0001GMT+00:00",
+ "20020122122220.0001GMT+10:00" };
+
+ String[] zOutput = {
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122222220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122222220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122222220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122222220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122222220Z",
+ "20020122122220Z",
+ "20020122022220Z"
+ };
+
+ String[] mzOutput = {
+ "20020122122220.000Z",
+ "20020122122220.000Z",
+ "20020122222220.000Z",
+ "20020122122220.000Z",
+ "20020122122220.100Z",
+ "20020122122220.100Z",
+ "20020122222220.100Z",
+ "20020122122220.100Z",
+ "20020122122220.010Z",
+ "20020122122220.010Z",
+ "20020122222220.010Z",
+ "20020122122220.010Z",
+ "20020122122220.001Z",
+ "20020122122220.001Z",
+ "20020122222220.001Z",
+ "20020122122220.001Z",
+ "20020122122220.000Z",
+ "20020122122220.000Z",
+ "20020122222220.000Z",
+ "20020122122220.000Z",
+ "20020122022220.000Z"
+ };
+
+ public String getName()
+ {
+ return "GeneralizedTime";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ for (int i = 0; i != input.length; i++)
+ {
+ DERGeneralizedTime t = new DERGeneralizedTime(input[i]);
+
+ if (output[i].indexOf('G') > 0) // don't check local time the same way
+ {
+ if (!t.getTime().equals(output[i]))
+ {
+ fail("failed conversion test");
+ }
+ }
+ else
+ {
+ String offset = calculateGMTOffset(t.getDate());
+
+ if (!t.getTime().equals(output[i] + offset))
+ {
+ fail("failed conversion test");
+ }
+ }
+ }
+
+ for (int i = 0; i != input.length; i++)
+ {
+ ASN1GeneralizedTime t = new ASN1GeneralizedTime(mzOutput[i]);
+
+ if (!new ASN1GeneralizedTime(t.getDate(), true).getDate().equals(t.getDate()))
+ {
+ fail("failed equality test");
+ }
+ }
+ }
+
+ private String calculateGMTOffset(Date date)
+ {
+ String sign = "+";
+ TimeZone timeZone = TimeZone.getDefault();
+ int offset = timeZone.getRawOffset();
+ if (offset < 0)
+ {
+ sign = "-";
+ offset = -offset;
+ }
+ int hours = offset / (60 * 60 * 1000);
+ int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000);
+
+// if (timeZone.useDaylightTime() && timeZone.inDaylightTime(date))
+// {
+// hours += sign.equals("+") ? 1 : -1;
+// }
+
+ return "GMT" + sign + convert(hours) + ":" + convert(minutes);
+ }
+
+ private String convert(int time)
+ {
+ if (time < 10)
+ {
+ return "0" + time;
+ }
+
+ return Integer.toString(time);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new GeneralizedTimeTest());
+ }
+}
diff --git a/core/src/test/j2me/org/spongycastle/asn1/test/RegressionTest.java b/core/src/test/j2me/org/spongycastle/asn1/test/RegressionTest.java
new file mode 100644
index 00000000..a559705f
--- /dev/null
+++ b/core/src/test/j2me/org/spongycastle/asn1/test/RegressionTest.java
@@ -0,0 +1,63 @@
+package org.spongycastle.asn1.test;
+
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+public class RegressionTest
+{
+ public static Test[] tests = {
+ new CertificateTest(),
+ new CMSTest(),
+ new OCSPTest(),
+ new OIDTest(),
+ new PKCS10Test(),
+ new PKCS12Test(),
+ new X509NameTest(),
+ new X500NameTest(),
+ new X509ExtensionsTest(),
+ new BitStringTest(),
+ new MiscTest(),
+ new X9Test(),
+ new EncryptedPrivateKeyInfoTest(),
+ new StringTest(),
+ new RequestedCertificateUnitTest(),
+ new OtherCertIDUnitTest(),
+ new OtherSigningCertificateUnitTest(),
+ new ContentHintsUnitTest(),
+ new CertHashUnitTest(),
+ new AdditionalInformationSyntaxUnitTest(),
+ new AdmissionSyntaxUnitTest(),
+ new AdmissionsUnitTest(),
+ new DeclarationOfMajorityUnitTest(),
+ new ProcurationSyntaxUnitTest(),
+ new ProfessionInfoUnitTest(),
+ new RestrictionUnitTest(),
+ new NamingAuthorityUnitTest(),
+ new MonetaryLimitUnitTest(),
+ new DERApplicationSpecificTest(),
+ new IssuingDistributionPointUnitTest(),
+ new TargetInformationTest(),
+ new SubjectKeyIdentifierTest(),
+ new ESSCertIDv2UnitTest(),
+ new ParsingTest(),
+ new GeneralNameTest(),
+ new RFC4519Test()
+ };
+
+ public static void main(
+ String[] args)
+ {
+ for (int i = 0; i != tests.length; i++)
+ {
+ TestResult result = tests[i].perform();
+
+ if (result.getException() != null)
+ {
+ result.getException().printStackTrace();
+ }
+
+ System.out.println(result);
+ }
+ }
+}
+
diff --git a/core/src/test/j2me/org/spongycastle/asn1/test/UTCTimeTest.java b/core/src/test/j2me/org/spongycastle/asn1/test/UTCTimeTest.java
new file mode 100644
index 00000000..c1154f05
--- /dev/null
+++ b/core/src/test/j2me/org/spongycastle/asn1/test/UTCTimeTest.java
@@ -0,0 +1,98 @@
+package org.spongycastle.asn1.test;
+
+import org.spongycastle.asn1.ASN1UTCTime;
+import org.spongycastle.asn1.DERUTCTime;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * X.690 test example
+ */
+public class UTCTimeTest
+ extends SimpleTest
+{
+ String[] input =
+ {
+ "020122122220Z",
+ "020122122220-1000",
+ "020122122220+1000",
+ "020122122220+00",
+ "0201221222Z",
+ "0201221222-1000",
+ "0201221222+1000",
+ "0201221222+00",
+ "550122122220Z",
+ "5501221222Z"
+ };
+
+ String[] output = {
+ "20020122122220GMT+00:00",
+ "20020122122220GMT-10:00",
+ "20020122122220GMT+10:00",
+ "20020122122220GMT+00:00",
+ "20020122122200GMT+00:00",
+ "20020122122200GMT-10:00",
+ "20020122122200GMT+10:00",
+ "20020122122200GMT+00:00",
+ "19550122122220GMT+00:00",
+ "19550122122200GMT+00:00"
+ };
+
+ String[] zOutput1 = {
+ "20020122122220Z",
+ "20020122222220Z",
+ "20020122022220Z",
+ "20020122122220Z",
+ "20020122122200Z",
+ "20020122222200Z",
+ "20020122022200Z",
+ "20020122122200Z",
+ "19550122122220Z",
+ "19550122122200Z"
+ };
+
+ String[] zOutput2 = {
+ "20020122122220Z",
+ "20020122222220Z",
+ "20020122022220Z",
+ "20020122122220Z",
+ "20020122122200Z",
+ "20020122222200Z",
+ "20020122022200Z",
+ "20020122122200Z",
+ "19550122122220Z",
+ "19550122122200Z"
+ };
+
+ public String getName()
+ {
+ return "UTCTime";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+
+ for (int i = 0; i != input.length; i++)
+ {
+ DERUTCTime t = new DERUTCTime(input[i]);
+
+ if (!t.getAdjustedTime().equals(output[i]))
+ {
+ fail("failed conversion test " + i);
+ }
+
+ t = new ASN1UTCTime(zOutput1[i].substring(2));
+
+ if (!new ASN1UTCTime(t.getAdjustedDate()).getAdjustedTime().equals(t.getAdjustedTime()))
+ {
+ fail("failed equality test");
+ }
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new UTCTimeTest());
+ }
+}
diff --git a/core/src/test/j2me/org/spongycastle/crypto/test/BigIntegerTest.java b/core/src/test/j2me/org/spongycastle/crypto/test/BigIntegerTest.java
new file mode 100644
index 00000000..ef223693
--- /dev/null
+++ b/core/src/test/j2me/org/spongycastle/crypto/test/BigIntegerTest.java
@@ -0,0 +1,32 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.util.test.*;
+
+public class BigIntegerTest
+{
+ public static Test[] tests = {
+ new DHTest(),
+ new ElGamalTest(),
+ new DSATest(),
+ new ECTest(),
+ new ECIESTest(),
+ new RSATest(),
+ new ISO9796Test(),
+ new OAEPTest(),
+ new PSSTest(),
+ new CTSTest(),
+ new PKCS5Test(),
+ new PKCS12Test()
+ };
+
+ public static void main(
+ String[] args)
+ {
+ for (int i = 0; i != tests.length; i++)
+ {
+ TestResult result = tests[i].perform();
+ System.out.println(result);
+ }
+ }
+}
+
diff --git a/core/src/test/j2me/org/spongycastle/crypto/test/CryptoRegressionTest.java b/core/src/test/j2me/org/spongycastle/crypto/test/CryptoRegressionTest.java
new file mode 100644
index 00000000..e66d6270
--- /dev/null
+++ b/core/src/test/j2me/org/spongycastle/crypto/test/CryptoRegressionTest.java
@@ -0,0 +1,64 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.util.test.*;
+
+public class CryptoRegressionTest
+{
+ public static Test[] tests = {
+ new AESTest(),
+ new DESTest(),
+ new DESedeTest(),
+ new ModeTest(),
+ new DHTest(),
+ new ElGamalTest(),
+ new DSATest(),
+ new ECTest(),
+ new ECIESTest(),
+ new MacTest(),
+ new RC2Test(),
+ new RC4Test(),
+ new RC5Test(),
+ new RC6Test(),
+ new RijndaelTest(),
+ new SerpentTest(),
+ new SkipjackTest(),
+ new BlowfishTest(),
+ new TwofishTest(),
+ new CAST5Test(),
+ new CAST6Test(),
+ new IDEATest(),
+ new CamelliaTest(),
+ new RSATest(),
+ new ISO9796Test(),
+ new MD2DigestTest(),
+ new MD4DigestTest(),
+ new MD5DigestTest(),
+ new SHA1DigestTest(),
+ new SHA256DigestTest(),
+ new SHA384DigestTest(),
+ new SHA512DigestTest(),
+ new RIPEMD128DigestTest(),
+ new RIPEMD160DigestTest(),
+ new TigerDigestTest(),
+ new MD5HMacTest(),
+ new SHA1HMacTest(),
+ new RIPEMD128HMacTest(),
+ new RIPEMD160HMacTest(),
+ /* new OAEPTest() */
+ new PSSTest(),
+ new CTSTest(),
+ /* new PKCS5Test() */
+ new PKCS12Test()
+ };
+
+ public static void main(
+ String[] args)
+ {
+ for (int i = 0; i != tests.length; i++)
+ {
+ TestResult result = tests[i].perform();
+ System.out.println(result);
+ }
+ }
+}
+
diff --git a/core/src/test/j2me/org/spongycastle/crypto/test/RSATest.java b/core/src/test/j2me/org/spongycastle/crypto/test/RSATest.java
new file mode 100644
index 00000000..b0f2fc55
--- /dev/null
+++ b/core/src/test/j2me/org/spongycastle/crypto/test/RSATest.java
@@ -0,0 +1,480 @@
+package org.spongycastle.crypto.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.encodings.OAEPEncoding;
+import org.spongycastle.crypto.encodings.PKCS1Encoding;
+import org.spongycastle.crypto.engines.RSAEngine;
+import org.spongycastle.crypto.generators.RSAKeyPairGenerator;
+import org.spongycastle.crypto.params.RSAKeyGenerationParameters;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+import org.spongycastle.crypto.params.RSAPrivateCrtKeyParameters;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class RSATest
+ extends SimpleTest
+{
+ static BigInteger mod = new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16);
+ static BigInteger pubExp = new BigInteger("11", 16);
+ static BigInteger privExp = new BigInteger("92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619", 16);
+ static BigInteger p = new BigInteger("f75e80839b9b9379f1cf1128f321639757dba514642c206bbbd99f9a4846208b3e93fbbe5e0527cc59b1d4b929d9555853004c7c8b30ee6a213c3d1bb7415d03", 16);
+ static BigInteger q = new BigInteger("b892d9ebdbfc37e397256dd8a5d3123534d1f03726284743ddc6be3a709edb696fc40c7d902ed804c6eee730eee3d5b20bf6bd8d87a296813c87d3b3cc9d7947", 16);
+ static BigInteger pExp = new BigInteger("1d1a2d3ca8e52068b3094d501c9a842fec37f54db16e9a67070a8b3f53cc03d4257ad252a1a640eadd603724d7bf3737914b544ae332eedf4f34436cac25ceb5", 16);
+ static BigInteger qExp = new BigInteger("6c929e4e81672fef49d9c825163fec97c4b7ba7acb26c0824638ac22605d7201c94625770984f78a56e6e25904fe7db407099cad9b14588841b94f5ab498dded", 16);
+ static BigInteger crtCoef = new BigInteger("dae7651ee69ad1d081ec5e7188ae126f6004ff39556bde90e0b870962fa7b926d070686d8244fe5a9aa709a95686a104614834b0ada4b10f53197a5cb4c97339", 16);
+
+ static String input = "4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
+
+ //
+ // to check that we handling byte extension by big number correctly.
+ //
+ static String edgeInput = "ff6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
+
+ static byte[] oversizedSig = Hex.decode("01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+ static byte[] dudBlock = Hex.decode("000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+ static byte[] truncatedDataBlock = Hex.decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+ static byte[] incorrectPadding = Hex.decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+ static byte[] missingDataBlock = Hex.decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
+
+ public String getName()
+ {
+ return "RSA";
+ }
+
+ private void testStrictPKCS1Length(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
+ {
+ AsymmetricBlockCipher eng = new RSAEngine();
+
+ eng.init(true, privParameters);
+
+ byte[] data = null;
+
+ try
+ {
+ data = eng.processBlock(oversizedSig, 0, oversizedSig.length);
+ }
+ catch (Exception e)
+ {
+ fail("RSA: failed - exception " + e.toString(), e);
+ }
+
+ eng = new PKCS1Encoding(eng);
+
+ eng.init(false, pubParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+
+ fail("oversized signature block not recognised");
+ }
+ catch (InvalidCipherTextException e)
+ {
+ if (!e.getMessage().equals("block incorrect size"))
+ {
+ fail("RSA: failed - exception " + e.toString(), e);
+ }
+ }
+ }
+
+ private void testTruncatedPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
+ {
+ checkForPKCS1Exception(pubParameters, privParameters, truncatedDataBlock, "block truncated");
+ }
+
+ private void testDudPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
+ {
+ checkForPKCS1Exception(pubParameters, privParameters, dudBlock, "unknown block type");
+ }
+
+ private void testWrongPaddingPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
+ {
+ checkForPKCS1Exception(pubParameters, privParameters, incorrectPadding, "block padding incorrect");
+ }
+
+ private void testMissingDataPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
+ {
+ checkForPKCS1Exception(pubParameters, privParameters, missingDataBlock, "no data in block");
+ }
+
+ private void checkForPKCS1Exception(RSAKeyParameters pubParameters, RSAKeyParameters privParameters, byte[] inputData, String expectedMessage)
+ {
+ AsymmetricBlockCipher eng = new RSAEngine();
+
+ eng.init(true, privParameters);
+
+ byte[] data = null;
+
+ try
+ {
+ data = eng.processBlock(inputData, 0, inputData.length);
+ }
+ catch (Exception e)
+ {
+ fail("RSA: failed - exception " + e.toString(), e);
+ }
+
+ eng = new PKCS1Encoding(eng);
+
+ eng.init(false, pubParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+
+ fail("missing data block not recognised");
+ }
+ catch (InvalidCipherTextException e)
+ {
+ if (!e.getMessage().equals(expectedMessage))
+ {
+ fail("RSA: failed - exception " + e.toString(), e);
+ }
+ }
+ }
+
+ private void testOAEP(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
+ {
+ //
+ // OAEP - public encrypt, private decrypt
+ //
+ AsymmetricBlockCipher eng = new OAEPEncoding(new RSAEngine());
+ byte[] data = Hex.decode(input);
+
+ eng.init(true, pubParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, privParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!input.equals(new String(Hex.encode(data))))
+ {
+ fail("failed OAEP Test");
+ }
+ }
+
+ private void zeroBlockTest(CipherParameters encParameters, CipherParameters decParameters)
+ {
+ AsymmetricBlockCipher eng = new PKCS1Encoding(new RSAEngine());
+
+ eng.init(true, encParameters);
+
+ if (eng.getOutputBlockSize() != ((PKCS1Encoding)eng).getUnderlyingCipher().getOutputBlockSize())
+ {
+ fail("PKCS1 output block size incorrect");
+ }
+
+ byte[] zero = new byte[0];
+ byte[] data = null;
+
+ try
+ {
+ data = eng.processBlock(zero, 0, zero.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, decParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!Arrays.areEqual(zero, data))
+ {
+ fail("failed PKCS1 zero Test");
+ }
+ }
+
+ public void performTest()
+ {
+ RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod, pubExp);
+ RSAKeyParameters privParameters = new RSAPrivateCrtKeyParameters(mod, pubExp, privExp, p, q, pExp, qExp, crtCoef);
+ byte[] data = Hex.decode(edgeInput);
+
+ //
+ // RAW
+ //
+ AsymmetricBlockCipher eng = new RSAEngine();
+
+ eng.init(true, pubParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("RSA: failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, privParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!edgeInput.equals(new String(Hex.encode(data))))
+ {
+ fail("failed RAW edge Test");
+ }
+
+ data = Hex.decode(input);
+
+ eng.init(true, pubParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, privParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!input.equals(new String(Hex.encode(data))))
+ {
+ fail("failed RAW Test");
+ }
+
+ //
+ // PKCS1 - public encrypt, private decrypt
+ //
+ eng = new PKCS1Encoding(eng);
+
+ eng.init(true, pubParameters);
+
+ if (eng.getOutputBlockSize() != ((PKCS1Encoding)eng).getUnderlyingCipher().getOutputBlockSize())
+ {
+ fail("PKCS1 output block size incorrect");
+ }
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, privParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!input.equals(new String(Hex.encode(data))))
+ {
+ fail("failed PKCS1 public/private Test");
+ }
+
+ //
+ // PKCS1 - private encrypt, public decrypt
+ //
+ eng = new PKCS1Encoding(((PKCS1Encoding)eng).getUnderlyingCipher());
+
+ eng.init(true, privParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, pubParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!input.equals(new String(Hex.encode(data))))
+ {
+ fail("failed PKCS1 private/public Test");
+ }
+
+ zeroBlockTest(pubParameters, privParameters);
+ zeroBlockTest(privParameters, pubParameters);
+
+ //
+ // key generation test
+ //
+ RSAKeyPairGenerator pGen = new RSAKeyPairGenerator();
+ RSAKeyGenerationParameters genParam = new RSAKeyGenerationParameters(
+ BigInteger.valueOf(0x11), new SecureRandom(), 768, 25);
+
+ pGen.init(genParam);
+
+ AsymmetricCipherKeyPair pair = pGen.generateKeyPair();
+
+ eng = new RSAEngine();
+
+ if (((RSAKeyParameters)pair.getPublic()).getModulus().bitLength() < 768)
+ {
+ fail("failed key generation (768) length test");
+ }
+
+ eng.init(true, pair.getPublic());
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, pair.getPrivate());
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!input.equals(new String(Hex.encode(data))))
+ {
+ fail("failed key generation (768) Test");
+ }
+
+ genParam = new RSAKeyGenerationParameters(BigInteger.valueOf(0x11), new SecureRandom(), 1024, 25);
+
+ pGen.init(genParam);
+ pair = pGen.generateKeyPair();
+
+ eng.init(true, pair.getPublic());
+
+ if (((RSAKeyParameters)pair.getPublic()).getModulus().bitLength() < 1024)
+ {
+ fail("failed key generation (1024) length test");
+ }
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, pair.getPrivate());
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!input.equals(new String(Hex.encode(data))))
+ {
+ fail("failed key generation (1024) test");
+ }
+
+ genParam = new RSAKeyGenerationParameters(
+ BigInteger.valueOf(0x11), new SecureRandom(), 16, 25);
+ pGen.init(genParam);
+
+ for (int i = 0; i < 100; ++i)
+ {
+ pair = pGen.generateKeyPair();
+ RSAPrivateCrtKeyParameters privKey = (RSAPrivateCrtKeyParameters) pair.getPrivate();
+ BigInteger pqDiff = privKey.getP().subtract(privKey.getQ()).abs();
+
+ if (pqDiff.bitLength() < 5)
+ {
+ fail("P and Q too close in RSA key pair");
+ }
+ }
+
+ testOAEP(pubParameters, privParameters);
+ testStrictPKCS1Length(pubParameters, privParameters);
+ testDudPKCS1Block(pubParameters, privParameters);
+ testMissingDataPKCS1Block(pubParameters, privParameters);
+ testTruncatedPKCS1Block(pubParameters, privParameters);
+ testWrongPaddingPKCS1Block(pubParameters, privParameters);
+
+ try
+ {
+ new RSAEngine().processBlock(new byte[]{ 1 }, 0, 1);
+ fail("failed initialisation check");
+ }
+ catch (IllegalStateException e)
+ {
+ // expected
+ }
+ }
+
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new RSATest());
+ }
+}
diff --git a/core/src/test/j2me/org/spongycastle/crypto/test/RegressionTest.java b/core/src/test/j2me/org/spongycastle/crypto/test/RegressionTest.java
new file mode 100644
index 00000000..d1a1f786
--- /dev/null
+++ b/core/src/test/j2me/org/spongycastle/crypto/test/RegressionTest.java
@@ -0,0 +1,68 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+public final class RegressionTest
+{
+ public static Test[] tests = {
+ new AESTest(),
+ new DESTest(),
+ new DESedeTest(),
+ new ModeTest(),
+ new DHTest(),
+ new ElGamalTest(),
+ new DSATest(),
+ new ECTest(),
+ new ECIESTest(),
+ new MacTest(),
+ new RC2Test(),
+ new RC4Test(),
+ new RC5Test(),
+ new RC6Test(),
+ new RijndaelTest(),
+ new SerpentTest(),
+ new SkipjackTest(),
+ new BlowfishTest(),
+ new TwofishTest(),
+ new CAST5Test(),
+ new CAST6Test(),
+ new IDEATest(),
+ new CamelliaTest(),
+ new RSATest(),
+ new ISO9796Test(),
+ new MD2DigestTest(),
+ new MD4DigestTest(),
+ new MD5DigestTest(),
+ new SHA1DigestTest(),
+ new SHA256DigestTest(),
+ new SHA384DigestTest(),
+ new SHA512DigestTest(),
+ new RIPEMD128DigestTest(),
+ new RIPEMD160DigestTest(),
+ new TigerDigestTest(),
+ new MD5HMacTest(),
+ new SHA1HMacTest(),
+ new RIPEMD128HMacTest(),
+ new RIPEMD160HMacTest(),
+ new OAEPTest(),
+ new PSSTest(),
+ new CTSTest(),
+ new PKCS5Test(),
+ new PKCS12Test(),
+ new GOST28147Test(),
+ new GOST3410Test(),
+ new WhirlpoolDigestTest()
+ };
+
+ public static void main(
+ String[] args)
+ {
+ for (int i = 0; i != tests.length; i++)
+ {
+ TestResult result = tests[i].perform();
+ System.out.println(result);
+ }
+ }
+}
+
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/ASN1SequenceParserTest.java b/core/src/test/java/org/bouncycastle/asn1/test/ASN1SequenceParserTest.java
deleted file mode 100644
index e0cd1af2..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/ASN1SequenceParserTest.java
+++ /dev/null
@@ -1,372 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.util.Arrays;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Null;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1SequenceParser;
-import org.bouncycastle.asn1.ASN1StreamParser;
-import org.bouncycastle.asn1.BERSequenceGenerator;
-import org.bouncycastle.asn1.DERSequenceGenerator;
-import org.bouncycastle.util.encoders.Hex;
-
-public class ASN1SequenceParserTest
- extends TestCase
-{
- private static final byte[] seqData = Hex.decode("3006020100060129");
- private static final byte[] nestedSeqData = Hex.decode("300b0201000601293003020101");
- private static final byte[] expTagSeqData = Hex.decode("a1083006020100060129");
- private static final byte[] implTagSeqData = Hex.decode("a106020100060129");
- private static final byte[] nestedSeqExpTagData = Hex.decode("300d020100060129a1053003020101");
- private static final byte[] nestedSeqImpTagData = Hex.decode("300b020100060129a103020101");
-
- private static final byte[] berSeqData = Hex.decode("30800201000601290000");
- private static final byte[] berDERNestedSeqData = Hex.decode("308002010006012930030201010000");
- private static final byte[] berNestedSeqData = Hex.decode("3080020100060129308002010100000000");
- private static final byte[] berExpTagSeqData = Hex.decode("a180308002010006012900000000");
-
- private static final byte[] berSeqWithDERNullData = Hex.decode("308005000201000601290000");
-
- public void testDERWriting()
- throws Exception
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- DERSequenceGenerator seqGen = new DERSequenceGenerator(bOut);
-
- seqGen.addObject(new ASN1Integer(BigInteger.valueOf(0)));
-
- seqGen.addObject(new ASN1ObjectIdentifier("1.1"));
-
- seqGen.close();
-
- assertTrue("basic DER writing test failed.", Arrays.equals(seqData, bOut.toByteArray()));
- }
-
- public void testNestedDERWriting()
- throws Exception
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- DERSequenceGenerator seqGen1 = new DERSequenceGenerator(bOut);
-
- seqGen1.addObject(new ASN1Integer(BigInteger.valueOf(0)));
-
- seqGen1.addObject(new ASN1ObjectIdentifier("1.1"));
-
- DERSequenceGenerator seqGen2 = new DERSequenceGenerator(seqGen1.getRawOutputStream());
-
- seqGen2.addObject(new ASN1Integer(BigInteger.valueOf(1)));
-
- seqGen2.close();
-
- seqGen1.close();
-
- assertTrue("nested DER writing test failed.", Arrays.equals(nestedSeqData, bOut.toByteArray()));
- }
-
- public void testDERExplicitTaggedSequenceWriting()
- throws Exception
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- DERSequenceGenerator seqGen = new DERSequenceGenerator(bOut, 1, true);
-
- seqGen.addObject(new ASN1Integer(BigInteger.valueOf(0)));
-
- seqGen.addObject(new ASN1ObjectIdentifier("1.1"));
-
- seqGen.close();
-
- assertTrue("explicit tag writing test failed.", Arrays.equals(expTagSeqData, bOut.toByteArray()));
- }
-
- public void testDERImplicitTaggedSequenceWriting()
- throws Exception
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- DERSequenceGenerator seqGen = new DERSequenceGenerator(bOut, 1, false);
-
- seqGen.addObject(new ASN1Integer(BigInteger.valueOf(0)));
-
- seqGen.addObject(new ASN1ObjectIdentifier("1.1"));
-
- seqGen.close();
-
- assertTrue("implicit tag writing test failed.", Arrays.equals(implTagSeqData, bOut.toByteArray()));
- }
-
- public void testNestedExplicitTagDERWriting()
- throws Exception
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- DERSequenceGenerator seqGen1 = new DERSequenceGenerator(bOut);
-
- seqGen1.addObject(new ASN1Integer(BigInteger.valueOf(0)));
-
- seqGen1.addObject(new ASN1ObjectIdentifier("1.1"));
-
- DERSequenceGenerator seqGen2 = new DERSequenceGenerator(seqGen1.getRawOutputStream(), 1, true);
-
- seqGen2.addObject(new ASN1Integer(BigInteger.valueOf(1)));
-
- seqGen2.close();
-
- seqGen1.close();
-
- assertTrue("nested explicit tagged DER writing test failed.", Arrays.equals(nestedSeqExpTagData, bOut.toByteArray()));
- }
-
- public void testNestedImplicitTagDERWriting()
- throws Exception
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- DERSequenceGenerator seqGen1 = new DERSequenceGenerator(bOut);
-
- seqGen1.addObject(new ASN1Integer(BigInteger.valueOf(0)));
-
- seqGen1.addObject(new ASN1ObjectIdentifier("1.1"));
-
- DERSequenceGenerator seqGen2 = new DERSequenceGenerator(seqGen1.getRawOutputStream(), 1, false);
-
- seqGen2.addObject(new ASN1Integer(BigInteger.valueOf(1)));
-
- seqGen2.close();
-
- seqGen1.close();
-
- assertTrue("nested implicit tagged DER writing test failed.", Arrays.equals(nestedSeqImpTagData, bOut.toByteArray()));
- }
-
- public void testBERWriting()
- throws Exception
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- BERSequenceGenerator seqGen = new BERSequenceGenerator(bOut);
-
- seqGen.addObject(new ASN1Integer(BigInteger.valueOf(0)));
-
- seqGen.addObject(new ASN1ObjectIdentifier("1.1"));
-
- seqGen.close();
-
- assertTrue("basic BER writing test failed.", Arrays.equals(berSeqData, bOut.toByteArray()));
- }
-
- public void testNestedBERDERWriting()
- throws Exception
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- BERSequenceGenerator seqGen1 = new BERSequenceGenerator(bOut);
-
- seqGen1.addObject(new ASN1Integer(BigInteger.valueOf(0)));
-
- seqGen1.addObject(new ASN1ObjectIdentifier("1.1"));
-
- DERSequenceGenerator seqGen2 = new DERSequenceGenerator(seqGen1.getRawOutputStream());
-
- seqGen2.addObject(new ASN1Integer(BigInteger.valueOf(1)));
-
- seqGen2.close();
-
- seqGen1.close();
-
- assertTrue("nested BER/DER writing test failed.", Arrays.equals(berDERNestedSeqData, bOut.toByteArray()));
- }
-
- public void testNestedBERWriting()
- throws Exception
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- BERSequenceGenerator seqGen1 = new BERSequenceGenerator(bOut);
-
- seqGen1.addObject(new ASN1Integer(BigInteger.valueOf(0)));
-
- seqGen1.addObject(new ASN1ObjectIdentifier("1.1"));
-
- BERSequenceGenerator seqGen2 = new BERSequenceGenerator(seqGen1.getRawOutputStream());
-
- seqGen2.addObject(new ASN1Integer(BigInteger.valueOf(1)));
-
- seqGen2.close();
-
- seqGen1.close();
-
- assertTrue("nested BER writing test failed.", Arrays.equals(berNestedSeqData, bOut.toByteArray()));
- }
-
- public void testDERReading()
- throws Exception
- {
- ASN1StreamParser aIn = new ASN1StreamParser(seqData);
-
- ASN1SequenceParser seq = (ASN1SequenceParser)aIn.readObject();
- Object o;
- int count = 0;
-
- assertNotNull("null sequence returned", seq);
-
- while ((o = seq.readObject()) != null)
- {
- switch (count)
- {
- case 0:
- assertTrue(o instanceof ASN1Integer);
- break;
- case 1:
- assertTrue(o instanceof ASN1ObjectIdentifier);
- break;
- }
- count++;
- }
-
- assertEquals("wrong number of objects in sequence", 2, count);
- }
-
- private void testNestedReading(
- byte[] data)
- throws Exception
- {
- ASN1StreamParser aIn = new ASN1StreamParser(data);
-
- ASN1SequenceParser seq = (ASN1SequenceParser)aIn.readObject();
- Object o;
- int count = 0;
-
- assertNotNull("null sequence returned", seq);
-
- while ((o = seq.readObject()) != null)
- {
- switch (count)
- {
- case 0:
- assertTrue(o instanceof ASN1Integer);
- break;
- case 1:
- assertTrue(o instanceof ASN1ObjectIdentifier);
- break;
- case 2:
- assertTrue(o instanceof ASN1SequenceParser);
-
- ASN1SequenceParser s = (ASN1SequenceParser)o;
-
- // NB: Must exhaust the nested parser
- while (s.readObject() != null)
- {
- // Nothing
- }
-
- break;
- }
- count++;
- }
-
- assertEquals("wrong number of objects in sequence", 3, count);
- }
-
- public void testNestedDERReading()
- throws Exception
- {
- testNestedReading(nestedSeqData);
- }
-
- public void testBERReading()
- throws Exception
- {
- ASN1StreamParser aIn = new ASN1StreamParser(berSeqData);
-
- ASN1SequenceParser seq = (ASN1SequenceParser)aIn.readObject();
- Object o;
- int count = 0;
-
- assertNotNull("null sequence returned", seq);
-
- while ((o = seq.readObject()) != null)
- {
- switch (count)
- {
- case 0:
- assertTrue(o instanceof ASN1Integer);
- break;
- case 1:
- assertTrue(o instanceof ASN1ObjectIdentifier);
- break;
- }
- count++;
- }
-
- assertEquals("wrong number of objects in sequence", 2, count);
- }
-
- public void testNestedBERDERReading()
- throws Exception
- {
- testNestedReading(berDERNestedSeqData);
- }
-
- public void testNestedBERReading()
- throws Exception
- {
- testNestedReading(berNestedSeqData);
- }
-
- public void testBERExplicitTaggedSequenceWriting()
- throws Exception
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- BERSequenceGenerator seqGen = new BERSequenceGenerator(bOut, 1, true);
-
- seqGen.addObject(new ASN1Integer(BigInteger.valueOf(0)));
-
- seqGen.addObject(new ASN1ObjectIdentifier("1.1"));
-
- seqGen.close();
-
- assertTrue("explicit BER tag writing test failed.", Arrays.equals(berExpTagSeqData, bOut.toByteArray()));
- }
-
- public void testSequenceWithDERNullReading()
- throws Exception
- {
- testParseWithNull(berSeqWithDERNullData);
- }
-
- private void testParseWithNull(byte[] data)
- throws IOException
- {
- ASN1StreamParser aIn = new ASN1StreamParser(data);
- ASN1SequenceParser seq = (ASN1SequenceParser)aIn.readObject();
- Object o;
- int count = 0;
-
- assertNotNull("null sequence returned", seq);
-
- while ((o = seq.readObject()) != null)
- {
- switch (count)
- {
- case 0:
- assertTrue(o instanceof ASN1Null);
- break;
- case 1:
- assertTrue(o instanceof ASN1Integer);
- break;
- case 2:
- assertTrue(o instanceof ASN1ObjectIdentifier);
- break;
- }
- count++;
- }
-
- assertEquals("wrong number of objects in sequence", 3, count);
- }
-
- public static Test suite()
- {
- return new TestSuite(ASN1SequenceParserTest.class);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/ASN1UnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/ASN1UnitTest.java
deleted file mode 100644
index d51cc6af..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/ASN1UnitTest.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.util.test.SimpleTest;
-
-import java.math.BigInteger;
-
-public abstract class ASN1UnitTest
- extends SimpleTest
-{
- protected void checkMandatoryField(String name, ASN1Encodable expected, ASN1Encodable present)
- {
- if (!expected.equals(present))
- {
- fail(name + " field doesn't match.");
- }
- }
-
- protected void checkMandatoryField(String name, String expected, String present)
- {
- if (!expected.equals(present))
- {
- fail(name + " field doesn't match.");
- }
- }
-
- protected void checkMandatoryField(String name, byte[] expected, byte[] present)
- {
- if (!areEqual(expected, present))
- {
- fail(name + " field doesn't match.");
- }
- }
-
- protected void checkMandatoryField(String name, int expected, int present)
- {
- if (expected != present)
- {
- fail(name + " field doesn't match.");
- }
- }
-
- protected void checkOptionalField(String name, ASN1Encodable expected, ASN1Encodable present)
- {
- if (expected != null)
- {
- if (!expected.equals(present))
- {
- fail(name + " field doesn't match.");
- }
- }
- else if (present != null)
- {
- fail(name + " field found when none expected.");
- }
- }
-
- protected void checkOptionalField(String name, String expected, String present)
- {
- if (expected != null)
- {
- if (!expected.equals(present))
- {
- fail(name + " field doesn't match.");
- }
- }
- else if (present != null)
- {
- fail(name + " field found when none expected.");
- }
- }
-
- protected void checkOptionalField(String name, BigInteger expected, BigInteger present)
- {
- if (expected != null)
- {
- if (!expected.equals(present))
- {
- fail(name + " field doesn't match.");
- }
- }
- else if (present != null)
- {
- fail(name + " field found when none expected.");
- }
- }
-
-
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/AdditionalInformationSyntaxUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/AdditionalInformationSyntaxUnitTest.java
deleted file mode 100644
index baf0750f..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/AdditionalInformationSyntaxUnitTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1String;
-import org.bouncycastle.asn1.isismtt.x509.AdditionalInformationSyntax;
-import org.bouncycastle.asn1.x500.DirectoryString;
-
-public class AdditionalInformationSyntaxUnitTest
- extends ASN1UnitTest
-{
- public String getName()
- {
- return "AdditionalInformationSyntax";
- }
-
- public void performTest()
- throws Exception
- {
- AdditionalInformationSyntax syntax = new AdditionalInformationSyntax("hello world");
-
- checkConstruction(syntax, new DirectoryString("hello world"));
-
- try
- {
- AdditionalInformationSyntax.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- AdditionalInformationSyntax syntax,
- DirectoryString information)
- throws IOException
- {
- checkValues(syntax, information);
-
- syntax = AdditionalInformationSyntax.getInstance(syntax);
-
- checkValues(syntax, information);
-
- ASN1InputStream aIn = new ASN1InputStream(syntax.toASN1Object().getEncoded());
-
- ASN1String info = (ASN1String)aIn.readObject();
-
- syntax = AdditionalInformationSyntax.getInstance(info);
-
- checkValues(syntax, information);
- }
-
- private void checkValues(
- AdditionalInformationSyntax syntax,
- DirectoryString information)
- {
- checkMandatoryField("information", information, syntax.getInformation());
- }
-
- public static void main(
- String[] args)
- {
- runTest(new AdditionalInformationSyntaxUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/AdmissionSyntaxUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/AdmissionSyntaxUnitTest.java
deleted file mode 100644
index ad0e9259..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/AdmissionSyntaxUnitTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.isismtt.x509.AdmissionSyntax;
-import org.bouncycastle.asn1.isismtt.x509.Admissions;
-import org.bouncycastle.asn1.isismtt.x509.NamingAuthority;
-import org.bouncycastle.asn1.isismtt.x509.ProfessionInfo;
-import org.bouncycastle.asn1.x500.DirectoryString;
-import org.bouncycastle.asn1.x509.GeneralName;
-import org.bouncycastle.asn1.x509.X509Name;
-
-public class AdmissionSyntaxUnitTest
- extends ASN1UnitTest
-{
- public String getName()
- {
- return "AdmissionSyntax";
- }
-
- public void performTest()
- throws Exception
- {
- GeneralName name = new GeneralName(new X509Name("CN=hello world"));
- ASN1Sequence admissions = new DERSequence(
- new Admissions(name,
- new NamingAuthority(new ASN1ObjectIdentifier("1.2.3"), "url", new DirectoryString("fred")),
- new ProfessionInfo[0]));
- AdmissionSyntax syntax = new AdmissionSyntax(name, admissions);
-
- checkConstruction(syntax, name, admissions);
-
- syntax = AdmissionSyntax.getInstance(null);
-
- if (syntax != null)
- {
- fail("null getInstance() failed.");
- }
-
- try
- {
- AdmissionSyntax.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- AdmissionSyntax syntax,
- GeneralName authority,
- ASN1Sequence admissions)
- throws IOException
- {
- checkValues(syntax, authority, admissions);
-
- syntax = AdmissionSyntax.getInstance(syntax);
-
- checkValues(syntax, authority, admissions);
-
- ASN1InputStream aIn = new ASN1InputStream(syntax.toASN1Object().getEncoded());
-
- ASN1Sequence info = (ASN1Sequence)aIn.readObject();
-
- syntax = AdmissionSyntax.getInstance(info);
-
- checkValues(syntax, authority, admissions);
- }
-
- private void checkValues(
- AdmissionSyntax syntax,
- GeneralName authority,
- ASN1Sequence admissions)
- {
- checkMandatoryField("admissionAuthority", authority, syntax.getAdmissionAuthority());
-
- Admissions[] adm = syntax.getContentsOfAdmissions();
-
- if (adm.length != 1 || !adm[0].equals(admissions.getObjectAt(0)))
- {
- fail("admissions check failed");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new AdmissionSyntaxUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/AdmissionsUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/AdmissionsUnitTest.java
deleted file mode 100644
index 171faec4..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/AdmissionsUnitTest.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.isismtt.x509.Admissions;
-import org.bouncycastle.asn1.isismtt.x509.NamingAuthority;
-import org.bouncycastle.asn1.isismtt.x509.ProfessionInfo;
-import org.bouncycastle.asn1.x500.DirectoryString;
-import org.bouncycastle.asn1.x509.GeneralName;
-import org.bouncycastle.asn1.x509.X509Name;
-
-public class AdmissionsUnitTest
- extends ASN1UnitTest
-{
- public String getName()
- {
- return "Admissions";
- }
-
- public void performTest()
- throws Exception
- {
- GeneralName name = new GeneralName(new X509Name("CN=hello world"));
- NamingAuthority auth = new NamingAuthority(new ASN1ObjectIdentifier("1.2.3"), "url", new DirectoryString("fred"));
- Admissions admissions = new Admissions(name, auth, new ProfessionInfo[0]);
-
- checkConstruction(admissions, name, auth);
-
- admissions = Admissions.getInstance(null);
-
- if (admissions != null)
- {
- fail("null getInstance() failed.");
- }
-
- try
- {
- Admissions.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- Admissions admissions,
- GeneralName name,
- NamingAuthority auth)
- throws IOException
- {
- checkValues(admissions, name, auth);
-
- admissions = Admissions.getInstance(admissions);
-
- checkValues(admissions, name, auth);
-
- ASN1InputStream aIn = new ASN1InputStream(admissions.toASN1Object().getEncoded());
-
- ASN1Sequence info = (ASN1Sequence)aIn.readObject();
-
- admissions = Admissions.getInstance(info);
-
- checkValues(admissions, name, auth);
- }
-
- private void checkValues(
- Admissions admissions,
- GeneralName name,
- NamingAuthority auth)
- {
- checkMandatoryField("admissionAuthority", name, admissions.getAdmissionAuthority());
- checkMandatoryField("namingAuthority", auth, admissions.getNamingAuthority());
- }
-
- public static void main(
- String[] args)
- {
- runTest(new AdmissionsUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/AllTests.java b/core/src/test/java/org/bouncycastle/asn1/test/AllTests.java
deleted file mode 100644
index 5b647b3e..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/AllTests.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-import org.bouncycastle.util.test.SimpleTestResult;
-
-public class AllTests
- extends TestCase
-{
- public void testASN1()
- {
- org.bouncycastle.util.test.Test[] tests = RegressionTest.tests;
-
- for (int i = 0; i != tests.length; i++)
- {
- SimpleTestResult result = (SimpleTestResult)tests[i].perform();
-
- if (!result.isSuccessful())
- {
- fail(result.toString());
- }
- }
- }
-
- public static void main (String[] args)
- {
- junit.textui.TestRunner.run(suite());
- }
-
- public static Test suite()
- {
- TestSuite suite = new TestSuite("ASN.1 Tests");
-
- suite.addTestSuite(AllTests.class);
- suite.addTestSuite(GetInstanceTest.class);
- suite.addTestSuite(ASN1SequenceParserTest.class);
- suite.addTestSuite(OctetStringTest.class);
- suite.addTestSuite(ParseTest.class);
-
- return suite;
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/AttributeTableUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/AttributeTableUnitTest.java
deleted file mode 100644
index 337fb1a5..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/AttributeTableUnitTest.java
+++ /dev/null
@@ -1,144 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.util.Hashtable;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.DERSet;
-import org.bouncycastle.asn1.cms.Attribute;
-import org.bouncycastle.asn1.cms.AttributeTable;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class AttributeTableUnitTest
- extends SimpleTest
-{
- private static final ASN1ObjectIdentifier type1 = new ASN1ObjectIdentifier("1.1.1");
- private static final ASN1ObjectIdentifier type2 = new ASN1ObjectIdentifier("1.1.2");
- private static final ASN1ObjectIdentifier type3 = new ASN1ObjectIdentifier("1.1.3");
-
- public String getName()
- {
- return "AttributeTable";
- }
-
- public void performTest()
- throws Exception
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(new Attribute(type1, new DERSet(type1)));
- v.add(new Attribute(type2, new DERSet(type2)));
-
- AttributeTable table = new AttributeTable(v);
-
- Attribute a = table.get(type1);
- if (a == null)
- {
- fail("type1 attribute not found.");
- }
- if (!a.getAttrValues().equals(new DERSet(type1)))
- {
- fail("wrong value retrieved for type1!");
- }
-
- a = table.get(type2);
- if (a == null)
- {
- fail("type2 attribute not found.");
- }
- if (!a.getAttrValues().equals(new DERSet(type2)))
- {
- fail("wrong value retrieved for type2!");
- }
-
- a = table.get(type3);
- if (a != null)
- {
- fail("type3 attribute found when none expected.");
- }
-
- ASN1EncodableVector vec = table.getAll(type1);
- if (vec.size() != 1)
- {
- fail("wrong vector size for type1.");
- }
-
- vec = table.getAll(type3);
- if (vec.size() != 0)
- {
- fail("wrong vector size for type3.");
- }
-
- vec = table.toASN1EncodableVector();
- if (vec.size() != 2)
- {
- fail("wrong vector size for single.");
- }
-
- Hashtable t = table.toHashtable();
-
- if (t.size() != 2)
- {
- fail("hashtable wrong size.");
- }
-
- // multiple
-
- v = new ASN1EncodableVector();
-
- v.add(new Attribute(type1, new DERSet(type1)));
- v.add(new Attribute(type1, new DERSet(type2)));
- v.add(new Attribute(type1, new DERSet(type3)));
- v.add(new Attribute(type2, new DERSet(type2)));
-
- table = new AttributeTable(v);
-
- a = table.get(type1);
- if (!a.getAttrValues().equals(new DERSet(type1)))
- {
- fail("wrong value retrieved for type1 multi get!");
- }
-
- vec = table.getAll(type1);
- if (vec.size() != 3)
- {
- fail("wrong vector size for multiple type1.");
- }
-
- a = (Attribute)vec.get(0);
- if (!a.getAttrValues().equals(new DERSet(type1)))
- {
- fail("wrong value retrieved for type1(0)!");
- }
-
- a = (Attribute)vec.get(1);
- if (!a.getAttrValues().equals(new DERSet(type2)))
- {
- fail("wrong value retrieved for type1(1)!");
- }
-
- a = (Attribute)vec.get(2);
- if (!a.getAttrValues().equals(new DERSet(type3)))
- {
- fail("wrong value retrieved for type1(2)!");
- }
-
- vec = table.getAll(type2);
- if (vec.size() != 1)
- {
- fail("wrong vector size for multiple type2.");
- }
-
- vec = table.toASN1EncodableVector();
- if (vec.size() != 4)
- {
- fail("wrong vector size for multiple.");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new AttributeTableUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/BiometricDataUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/BiometricDataUnitTest.java
deleted file mode 100644
index b4c2ea42..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/BiometricDataUnitTest.java
+++ /dev/null
@@ -1,133 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.qualified.BiometricData;
-import org.bouncycastle.asn1.x509.qualified.TypeOfBiometricData;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class BiometricDataUnitTest
- extends SimpleTest
-{
- public String getName()
- {
- return "BiometricData";
- }
-
- private byte[] generateHash()
- {
- SecureRandom rand = new SecureRandom();
- byte[] bytes = new byte[20];
-
- rand.nextBytes(bytes);
-
- return bytes;
- }
-
- public void performTest()
- throws Exception
- {
- TypeOfBiometricData dataType = new TypeOfBiometricData(TypeOfBiometricData.HANDWRITTEN_SIGNATURE);
- AlgorithmIdentifier hashAlgorithm = new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE);
- ASN1OctetString dataHash = new DEROctetString(generateHash());
- BiometricData bd = new BiometricData(dataType, hashAlgorithm, dataHash);
-
- checkConstruction(bd, dataType, hashAlgorithm, dataHash, null);
-
- DERIA5String dataUri = new DERIA5String("http://test");
-
- bd = new BiometricData(dataType, hashAlgorithm, dataHash, dataUri);
-
- checkConstruction(bd, dataType, hashAlgorithm, dataHash, dataUri);
-
- bd = BiometricData.getInstance(null);
-
- if (bd != null)
- {
- fail("null getInstance() failed.");
- }
-
- try
- {
- BiometricData.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- BiometricData bd,
- TypeOfBiometricData dataType,
- AlgorithmIdentifier hashAlgorithm,
- ASN1OctetString dataHash,
- DERIA5String dataUri)
- throws Exception
- {
- checkValues(bd, dataType, hashAlgorithm, dataHash, dataUri);
-
- bd = BiometricData.getInstance(bd);
-
- checkValues(bd, dataType, hashAlgorithm, dataHash, dataUri);
-
- ASN1InputStream aIn = new ASN1InputStream(bd.toASN1Object().getEncoded());
-
- ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
-
- bd = BiometricData.getInstance(seq);
-
- checkValues(bd, dataType, hashAlgorithm, dataHash, dataUri);
- }
-
- private void checkValues(
- BiometricData bd,
- TypeOfBiometricData dataType,
- AlgorithmIdentifier algID,
- ASN1OctetString dataHash,
- DERIA5String sourceDataURI)
- {
- if (!bd.getTypeOfBiometricData().equals(dataType))
- {
- fail("types don't match.");
- }
-
- if (!bd.getHashAlgorithm().equals(algID))
- {
- fail("hash algorithms don't match.");
- }
-
- if (!bd.getBiometricDataHash().equals(dataHash))
- {
- fail("hash algorithms don't match.");
- }
-
- if (sourceDataURI != null)
- {
- if (!bd.getSourceDataUri().equals(sourceDataURI))
- {
- fail("data uris don't match.");
- }
- }
- else if (bd.getSourceDataUri() != null)
- {
- fail("data uri found when none expected.");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new BiometricDataUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/BitStringConstantTester.java b/core/src/test/java/org/bouncycastle/asn1/test/BitStringConstantTester.java
deleted file mode 100644
index bbea4a3d..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/BitStringConstantTester.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-public class BitStringConstantTester
-{
- private static final int[] bits =
- {
- 1 << 7, 1 << 6, 1 << 5, 1 << 4, 1 << 3, 1 << 2, 1 << 1, 1 << 0,
- 1 << 15, 1 << 14, 1 << 13, 1 << 12, 1 << 11, 1 << 10, 1 << 9, 1 << 8,
- 1 << 23, 1 << 22, 1 << 21, 1 << 20, 1 << 19, 1 << 18, 1 << 17, 1 << 16,
- 1 << 31, 1 << 30, 1 << 29, 1 << 28, 1 << 27, 1 << 26, 1 << 25, 1 << 24
- };
-
- public static void testFlagValueCorrect(
- int bitNo,
- int value)
- {
- if (bits[bitNo] != value)
- {
- throw new IllegalArgumentException("bit value " + bitNo + " wrong");
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/BitStringTest.java b/core/src/test/java/org/bouncycastle/asn1/test/BitStringTest.java
deleted file mode 100644
index 1cd5bd3a..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/BitStringTest.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.x509.KeyUsage;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-public class BitStringTest
- implements Test
-{
- public TestResult perform()
- {
- KeyUsage k = new KeyUsage(KeyUsage.digitalSignature);
- if ((k.getBytes()[0] != (byte)KeyUsage.digitalSignature) || (k.getPadBits() != 7))
- {
- return new SimpleTestResult(false, getName() + ": failed digitalSignature");
- }
-
- k = new KeyUsage(KeyUsage.nonRepudiation);
- if ((k.getBytes()[0] != (byte)KeyUsage.nonRepudiation) || (k.getPadBits() != 6))
- {
- return new SimpleTestResult(false, getName() + ": failed nonRepudiation");
- }
-
- k = new KeyUsage(KeyUsage.keyEncipherment);
- if ((k.getBytes()[0] != (byte)KeyUsage.keyEncipherment) || (k.getPadBits() != 5))
- {
- return new SimpleTestResult(false, getName() + ": failed keyEncipherment");
- }
-
- k = new KeyUsage(KeyUsage.cRLSign);
- if ((k.getBytes()[0] != (byte)KeyUsage.cRLSign) || (k.getPadBits() != 1))
- {
- return new SimpleTestResult(false, getName() + ": failed cRLSign");
- }
-
- k = new KeyUsage(KeyUsage.decipherOnly);
- if ((k.getBytes()[1] != (byte)(KeyUsage.decipherOnly >> 8)) || (k.getPadBits() != 7))
- {
- return new SimpleTestResult(false, getName() + ": failed decipherOnly");
- }
-
- // test for zero length bit string
- try
- {
- ASN1Primitive.fromByteArray(new DERBitString(new byte[0], 0).getEncoded());
- }
- catch (IOException e)
- {
- return new SimpleTestResult(false, getName() + ": " + e);
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
-
- public String getName()
- {
- return "BitString";
- }
-
- public static void main(
- String[] args)
- {
- BitStringTest test = new BitStringTest();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/CMSTest.java b/core/src/test/java/org/bouncycastle/asn1/test/CMSTest.java
deleted file mode 100644
index 873b27c0..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/CMSTest.java
+++ /dev/null
@@ -1,358 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1OctetStringParser;
-import org.bouncycastle.asn1.ASN1OutputStream;
-import org.bouncycastle.asn1.ASN1SequenceParser;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.ASN1SetParser;
-import org.bouncycastle.asn1.ASN1StreamParser;
-import org.bouncycastle.asn1.BERTags;
-import org.bouncycastle.asn1.DERSet;
-import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
-import org.bouncycastle.asn1.cms.CompressedData;
-import org.bouncycastle.asn1.cms.ContentInfo;
-import org.bouncycastle.asn1.cms.ContentInfoParser;
-import org.bouncycastle.asn1.cms.EncryptedContentInfoParser;
-import org.bouncycastle.asn1.cms.EnvelopedData;
-import org.bouncycastle.asn1.cms.EnvelopedDataParser;
-import org.bouncycastle.asn1.cms.KEKRecipientInfo;
-import org.bouncycastle.asn1.cms.KeyTransRecipientInfo;
-import org.bouncycastle.asn1.cms.RecipientInfo;
-import org.bouncycastle.asn1.cms.SignedData;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.io.Streams;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-public class CMSTest
- implements Test
-{
- //
- // compressed data object
- //
- 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");
-
- //
- // enveloped data
- //
- byte[] envDataKeyTrns = Base64.decode(
- "MIAGCSqGSIb3DQEHA6CAMIACAQAxgcQwgcECAQAwKjAlMRYwFAYDVQQKEw1Cb3Vu"
- + "Y3kgQ2FzdGxlMQswCQYDVQQGEwJBVQIBCjANBgkqhkiG9w0BAQEFAASBgC5vdGrB"
- + "itQSGwifLf3KwPILjaB4WEXgT/IIO1KDzrsbItCJsMA0Smq2y0zptxT0pSRL6JRg"
- + "NMxLk1ySnrIrvGiEPLMR1zjxlT8yQ6VLX+kEoK43ztd1aaLw0oBfrcXcLN7BEpZ1"
- + "TIdjlBfXIOx1S88WY1MiYqJJFc3LMwRUaTEDMIAGCSqGSIb3DQEHATAdBglghkgB"
- + "ZQMEARYEEAfxLMWeaBOTTZQwUq0Y5FuggAQgwOJhL04rjSZCBCSOv5i5XpFfGsOd"
- + "YSHSqwntGpFqCx4AAAAAAAAAAAAA");
-
- byte[] envDataKEK = Base64.decode(
- "MIAGCSqGSIb3DQEHA6CAMIACAQIxUqJQAgEEMAcEBQECAwQFMBAGCyqGSIb3DQEJE"
- + "AMHAgE6BDC7G/HyUPilIrin2Yeajqmj795VoLWETRnZAAFcAiQdoQWyz+oCh6WY/H"
- + "jHHi+0y+cwgAYJKoZIhvcNAQcBMBQGCCqGSIb3DQMHBAiY3eDBBbF6naCABBiNdzJb"
- + "/v6+UZB3XXKipxFDUpz9GyjzB+gAAAAAAAAAAAAA");
-
- byte[] envDataNestedNDEF = Base64.decode(
- "MIAGCSqGSIb3DQEHA6CAMIACAQAxge8wgewCAQAwgZUwgY8xKDAmBgNVBAoMH1RoZSBMZWdpb24g"
- + "b2YgdGhlIEJvdW5jeSBDYXN0bGUxLzAtBgkqhkiG9w0BCQEWIGZlZWRiYWNrLWNyeXB0b0Bib3Vu"
- + "Y3ljYXN0bGUub3JnMREwDwYDVQQIDAhWaWN0b3JpYTESMBAGA1UEBwwJTWVsYm91cm5lMQswCQYD"
- + "VQQGEwJBVQIBATANBgkqhkiG9w0BAQEFAARABIXMd8xiTyWDKO/LQfvdGYTPW3I9oSQWwtm4OIaN"
- + "VINpfY2lfwTvbmE6VXiLKeALC0dMBV8z7DEM9hE0HVmvLDCABgkqhkiG9w0BBwEwHQYJYIZIAWUD"
- + "BAECBBB32ko6WrVxDTqwUYEpV6IUoIAEggKgS6RowrhNlmWWI13zxD/lryxkZ5oWXPUfNiUxYX/P"
- + "r5iscW3s8VKJKUpJ4W5SNA7JGL4l/5LmSnJ4Qu/xzxcoH4r4vmt75EDE9p2Ob2Xi1NuSFAZubJFc"
- + "Zlnp4e05UHKikmoaz0PbiAi277sLQlK2FcVsntTYVT00y8+IwuuQu0ATVqkXC+VhfjV/sK6vQZnw"
- + "2rQKedZhLB7B4dUkmxCujb/UAq4lgSpLMXg2P6wMimTczXyQxRiZxPeI4ByCENjkafXbfcJft2eD"
- + "gv1DEDdYM5WrW9Z75b4lmJiOJ/xxDniHCvum7KGXzpK1d1mqTlpzPC2xoz08/MO4lRf5Mb0bYdq6"
- + "CjMaYqVwGsYryp/2ayX+d8H+JphEG+V9Eg8uPcDoibwhDI4KkoyGHstPw5bxcy7vVFt7LXUdNjJc"
- + "K1wxaUKEXDGKt9Vj93FnBTLMX0Pc9HpueV5o1ipX34dn/P3HZB9XK8ScbrE38B1VnIgylStnhVFO"
- + "Cj9s7qSVqI2L+xYHJRHsxaMumIRnmRuOqdXDfIo28EZAnFtQ/b9BziMGVvAW5+A8h8s2oazhSmK2"
- + "23ftV7uv98ScgE8fCd3PwT1kKJM83ThTYyBzokvMfPYCCvsonMV+kTWXhWcwjYTS4ukrpR452ZdW"
- + "l3aJqDnzobt5FK4T8OGciOj+1PxYFZyRmCuafm2Dx6o7Et2Tu/T5HYvhdY9jHyqtDl2PXH4CTnVi"
- + "gA1YOAArjPVmsZVwAM3Ml46uyXXhcsXwQ1X0Tv4D+PSa/id4UQ2cObOw8Cj1eW2GB8iJIZVqkZaU"
- + "XBexqgWYOIoxjqODSeoZKiBsTK3c+oOUBqBDueY1i55swE2o6dDt95FluX6iyr/q4w2wLt3upY1J"
- + "YL+TuvZxAKviuAczMS1bAAAAAAAAAAAAAA==");
-
- //
- // signed data
- //
- byte[] signedData = Base64.decode(
- "MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAaCA"
- + "JIAEDEhlbGxvIFdvcmxkIQAAAAAAAKCCBGIwggINMIIBdqADAgECAgEBMA0GCSqG"
- + "SIb3DQEBBAUAMCUxFjAUBgNVBAoTDUJvdW5jeSBDYXN0bGUxCzAJBgNVBAYTAkFV"
- + "MB4XDTA0MTAyNDA0MzA1OFoXDTA1MDIwMTA0MzA1OFowJTEWMBQGA1UEChMNQm91"
- + "bmN5IENhc3RsZTELMAkGA1UEBhMCQVUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ"
- + "AoGBAJj3OAshAOgDmPcYZ1jdNSuhOHRH9VhC/PG17FdiInVGc2ulJhEifEQga/uq"
- + "ZCpSd1nHsJUZKm9k1bVneWzC0941i9Znfxgb2jnXXsa5kwB2KEVESrOWsRjSRtnY"
- + "iLgqBG0rzpaMn5A5ntu7N0406EesBhe19cjZAageEHGZDbufAgMBAAGjTTBLMB0G"
- + "A1UdDgQWBBR/iHNKOo6f4ByWFFywRNZ65XSr1jAfBgNVHSMEGDAWgBR/iHNKOo6f"
- + "4ByWFFywRNZ65XSr1jAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBBAUAA4GBAFMJJ7QO"
- + "pHo30bnlQ4Ny3PCnK+Se+Gw3TpaYGp84+a8fGD9Dme78G6NEsgvpFGTyoLxvJ4CB"
- + "84Kzys+1p2HdXzoZiyXAer5S4IwptE3TxxFwKyj28cRrM6dK47DDyXUkV0qwBAMN"
- + "luwnk/no4K7ilzN2MZk5l7wXyNa9yJ6CHW6dMIICTTCCAbagAwIBAgIBAjANBgkq"
- + "hkiG9w0BAQQFADAlMRYwFAYDVQQKEw1Cb3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJB"
- + "VTAeFw0wNDEwMjQwNDMwNTlaFw0wNTAyMDEwNDMwNTlaMGUxGDAWBgNVBAMTD0Vy"
- + "aWMgSC4gRWNoaWRuYTEkMCIGCSqGSIb3DQEJARYVZXJpY0Bib3VuY3ljYXN0bGUu"
- + "b3JnMRYwFAYDVQQKEw1Cb3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJBVTCBnzANBgkq"
- + "hkiG9w0BAQEFAAOBjQAwgYkCgYEAm+5CnGU6W45iUpCsaGkn5gDruZv3j/o7N6ag"
- + "mRZhikaLG2JF6ECaX13iioVJfmzBsPKxAACWwuTXCoSSXG8viK/qpSHwJpfQHYEh"
- + "tcC0CxIqlnltv3KQAGwh/PdwpSPvSNnkQBGvtFq++9gnXDBbynfP8b2L2Eis0X9U"
- + "2y6gFiMCAwEAAaNNMEswHQYDVR0OBBYEFEAmOksnF66FoQm6IQBVN66vJo1TMB8G"
- + "A1UdIwQYMBaAFH+Ic0o6jp/gHJYUXLBE1nrldKvWMAkGA1UdEwQCMAAwDQYJKoZI"
- + "hvcNAQEEBQADgYEAEeIjvNkKMPU/ZYCu1TqjGZPEqi+glntg2hC/CF0oGyHFpMuG"
- + "tMepF3puW+uzKM1s61ar3ahidp3XFhr/GEU/XxK24AolI3yFgxP8PRgUWmQizTQX"
- + "pWUmhlsBe1uIKVEfNAzCgtYfJQ8HJIKsUCcdWeCKVKs4jRionsek1rozkPExggEv"
- + "MIIBKwIBATAqMCUxFjAUBgNVBAoTDUJvdW5jeSBDYXN0bGUxCzAJBgNVBAYTAkFV"
- + "AgECMAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqG"
- + "SIb3DQEJBTEPFw0wNDEwMjQwNDMwNTlaMCMGCSqGSIb3DQEJBDEWBBQu973mCM5U"
- + "BOl9XwQvlfifHCMocTANBgkqhkiG9w0BAQEFAASBgGHbe3/jcZu6b/erRhc3PEji"
- + "MUO8mEIRiNYBr5/vFNhkry8TrGfOpI45m7gu1MS0/vdas7ykvidl/sNZfO0GphEI"
- + "UaIjMRT3U6yuTWF4aLpatJbbRsIepJO/B2kdIAbV5SCbZgVDJIPOR2qnruHN2wLF"
- + "a+fEv4J8wQ8Xwvk0C8iMAAAAAAAA");
-
- private boolean isSameAs(
- byte[] a,
- byte[] b)
- {
- if (a.length != b.length)
- {
- return false;
- }
-
- for (int i = 0; i != a.length; i++)
- {
- if (a[i] != b[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- private TestResult compressionTest()
- {
- try
- {
- ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(compData));
-
- ContentInfo info = ContentInfo.getInstance(aIn.readObject());
- CompressedData data = CompressedData.getInstance(info.getContent());
-
- data = new CompressedData(data.getCompressionAlgorithmIdentifier(), data.getEncapContentInfo());
- info = new ContentInfo(CMSObjectIdentifiers.compressedData, data);
-
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- ASN1OutputStream aOut = new ASN1OutputStream(bOut);
-
- aOut.writeObject(info);
-
- if (!isSameAs(bOut.toByteArray(), compData))
- {
- return new SimpleTestResult(false, getName() + ": CMS compression failed to re-encode");
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
- catch (Exception e)
- {
- return new SimpleTestResult(false, getName() + ": CMS compression failed - " + e.toString(), e);
- }
- }
-
- private TestResult envelopedTest()
- {
- try
- {
- //
- // Key trans
- //
- ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(envDataKeyTrns));
-
- ContentInfo info = ContentInfo.getInstance(aIn.readObject());
- EnvelopedData envData = EnvelopedData.getInstance(info.getContent());
- ASN1Set s = envData.getRecipientInfos();
-
- if (s.size() != 1)
- {
- return new SimpleTestResult(false, getName() + ": CMS KeyTrans enveloped, wrong number of recipients");
- }
-
- RecipientInfo recip = RecipientInfo.getInstance(s.getObjectAt(0));
-
- if (recip.getInfo() instanceof KeyTransRecipientInfo)
- {
- KeyTransRecipientInfo inf = KeyTransRecipientInfo.getInstance(recip.getInfo());
-
- inf = new KeyTransRecipientInfo(inf.getRecipientIdentifier(), inf.getKeyEncryptionAlgorithm(), inf.getEncryptedKey());
-
- s = new DERSet(new RecipientInfo(inf));
- }
- else
- {
- return new SimpleTestResult(false, getName() + ": CMS KeyTrans enveloped, wrong recipient type");
- }
-
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- ASN1OutputStream aOut = new ASN1OutputStream(bOut);
-
- envData = new EnvelopedData(envData.getOriginatorInfo(), s, envData.getEncryptedContentInfo(), envData.getUnprotectedAttrs());
- info = new ContentInfo(CMSObjectIdentifiers.envelopedData, envData);
-
- aOut.writeObject(info);
-
- if (!isSameAs(bOut.toByteArray(), envDataKeyTrns))
- {
- return new SimpleTestResult(false, getName() + ": CMS KeyTrans enveloped failed to re-encode");
- }
-
- //
- // KEK
- //
- aIn = new ASN1InputStream(new ByteArrayInputStream(envDataKEK));
-
- info = ContentInfo.getInstance(aIn.readObject());
- envData = EnvelopedData.getInstance(info.getContent());
- s = envData.getRecipientInfos();
-
- if (s.size() != 1)
- {
- return new SimpleTestResult(false, getName() + ": CMS KEK enveloped, wrong number of recipients");
- }
-
- recip = RecipientInfo.getInstance(s.getObjectAt(0));
-
- if (recip.getInfo() instanceof KEKRecipientInfo)
- {
- KEKRecipientInfo inf = KEKRecipientInfo.getInstance(recip.getInfo());
-
- inf = new KEKRecipientInfo(inf.getKekid(), inf.getKeyEncryptionAlgorithm(), inf.getEncryptedKey());
-
- s = new DERSet(new RecipientInfo(inf));
- }
- else
- {
- return new SimpleTestResult(false, getName() + ": CMS KEK enveloped, wrong recipient type");
- }
-
- bOut = new ByteArrayOutputStream();
- aOut = new ASN1OutputStream(bOut);
-
- envData = new EnvelopedData(envData.getOriginatorInfo(), s, envData.getEncryptedContentInfo(), envData.getUnprotectedAttrs());
- info = new ContentInfo(CMSObjectIdentifiers.envelopedData, envData);
-
- aOut.writeObject(info);
-
- if (!isSameAs(bOut.toByteArray(), envDataKEK))
- { System.out.println(new String(Base64.encode(bOut.toByteArray())));
- return new SimpleTestResult(false, getName() + ": CMS KEK enveloped failed to re-encode");
- }
-
- // Nested NDEF problem
- ASN1StreamParser asn1In = new ASN1StreamParser(new ByteArrayInputStream(envDataNestedNDEF));
- ContentInfoParser ci = new ContentInfoParser((ASN1SequenceParser)asn1In.readObject());
- EnvelopedDataParser ed = new EnvelopedDataParser((ASN1SequenceParser)ci
- .getContent(BERTags.SEQUENCE));
- ed.getVersion();
- ed.getOriginatorInfo();
- ed.getRecipientInfos().toASN1Primitive();
- EncryptedContentInfoParser eci = ed.getEncryptedContentInfo();
- eci.getContentType();
- eci.getContentEncryptionAlgorithm();
-
- InputStream dataIn = ((ASN1OctetStringParser)eci.getEncryptedContent(BERTags.OCTET_STRING))
- .getOctetStream();
- Streams.drain(dataIn);
- dataIn.close();
-
- // Test data doesn't have unprotected attrs, bug was being thrown by this call
- ASN1SetParser upa = ed.getUnprotectedAttrs();
- if (upa != null)
- {
- upa.toASN1Primitive();
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
- catch (Exception e)
- {
- return new SimpleTestResult(false, getName() + ": CMS enveloped failed - " + e.toString(), e);
- }
- }
-
- private TestResult signedTest()
- {
- try
- {
- ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(signedData));
-
- ContentInfo info = ContentInfo.getInstance(aIn.readObject());
- SignedData sData = SignedData.getInstance(info.getContent());
-
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- ASN1OutputStream aOut = new ASN1OutputStream(bOut);
-
- sData = new SignedData(sData.getDigestAlgorithms(), sData.getEncapContentInfo(), sData.getCertificates(), sData.getCRLs(), sData.getSignerInfos());
- info = new ContentInfo(CMSObjectIdentifiers.signedData, sData);
-
- aOut.writeObject(info);
-
- if (!isSameAs(bOut.toByteArray(), signedData))
- {
- return new SimpleTestResult(false, getName() + ": CMS signed failed to re-encode");
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
- catch (Exception e)
- {
- return new SimpleTestResult(false, getName() + ": CMS signed failed - " + e.toString(), e);
- }
- }
-
- public TestResult perform()
- {
- TestResult res = compressionTest();
-
- if (!res.isSuccessful())
- {
- return res;
- }
-
- res = envelopedTest();
- if (!res.isSuccessful())
- {
- return res;
- }
-
- return signedTest();
- }
-
- public String getName()
- {
- return "CMS";
- }
-
- public static void main(
- String[] args)
- {
- CMSTest test = new CMSTest();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/CertHashUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/CertHashUnitTest.java
deleted file mode 100644
index 62c81d45..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/CertHashUnitTest.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.isismtt.ocsp.CertHash;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-public class CertHashUnitTest
- extends ASN1UnitTest
-{
- public String getName()
- {
- return "CertHash";
- }
-
- public void performTest()
- throws Exception
- {
- AlgorithmIdentifier algId = new AlgorithmIdentifier(new ASN1ObjectIdentifier("1.2.2.3"));
- byte[] digest = new byte[20];
-
- CertHash certID = new CertHash(algId, digest);
-
- checkConstruction(certID, algId, digest);
-
- certID = CertHash.getInstance(null);
-
- if (certID != null)
- {
- fail("null getInstance() failed.");
- }
-
- try
- {
- CertHash.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- CertHash certHash,
- AlgorithmIdentifier algId,
- byte[] digest)
- throws IOException
- {
- checkValues(certHash, algId, digest);
-
- certHash = CertHash.getInstance(certHash);
-
- checkValues(certHash, algId, digest);
-
- ASN1InputStream aIn = new ASN1InputStream(certHash.toASN1Object().getEncoded());
-
- ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
-
- certHash = CertHash.getInstance(seq);
-
- checkValues(certHash, algId, digest);
- }
-
- private void checkValues(
- CertHash certHash,
- AlgorithmIdentifier algId,
- byte[] digest)
- {
- checkMandatoryField("algorithmHash", algId, certHash.getHashAlgorithm());
-
- checkMandatoryField("certificateHash", digest, certHash.getCertificateHash());
- }
-
- public static void main(
- String[] args)
- {
- runTest(new CertHashUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/CertificateTest.java b/core/src/test/java/org/bouncycastle/asn1/test/CertificateTest.java
deleted file mode 100644
index 1eebd195..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/CertificateTest.java
+++ /dev/null
@@ -1,574 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.ByteArrayInputStream;
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.AttCertIssuer;
-import org.bouncycastle.asn1.x509.AttCertValidityPeriod;
-import org.bouncycastle.asn1.x509.Attribute;
-import org.bouncycastle.asn1.x509.AttributeCertificate;
-import org.bouncycastle.asn1.x509.AttributeCertificateInfo;
-import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
-import org.bouncycastle.asn1.x509.BasicConstraints;
-import org.bouncycastle.asn1.x509.CRLDistPoint;
-import org.bouncycastle.asn1.x509.Certificate;
-import org.bouncycastle.asn1.x509.DistributionPoint;
-import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
-import org.bouncycastle.asn1.x509.Extension;
-import org.bouncycastle.asn1.x509.Extensions;
-import org.bouncycastle.asn1.x509.GeneralName;
-import org.bouncycastle.asn1.x509.GeneralNames;
-import org.bouncycastle.asn1.x509.Holder;
-import org.bouncycastle.asn1.x509.KeyPurposeId;
-import org.bouncycastle.asn1.x509.KeyUsage;
-import org.bouncycastle.asn1.x509.PolicyInformation;
-import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
-import org.bouncycastle.asn1.x509.TBSCertificate;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class CertificateTest
- extends SimpleTest
-{
- //
- // server.crt
- //
- byte[] cert1 = Base64.decode(
- "MIIDXjCCAsegAwIBAgIBBzANBgkqhkiG9w0BAQQFADCBtzELMAkGA1UEBhMCQVUx"
- + "ETAPBgNVBAgTCFZpY3RvcmlhMRgwFgYDVQQHEw9Tb3V0aCBNZWxib3VybmUxGjAY"
- + "BgNVBAoTEUNvbm5lY3QgNCBQdHkgTHRkMR4wHAYDVQQLExVDZXJ0aWZpY2F0ZSBB"
- + "dXRob3JpdHkxFTATBgNVBAMTDENvbm5lY3QgNCBDQTEoMCYGCSqGSIb3DQEJARYZ"
- + "d2VibWFzdGVyQGNvbm5lY3Q0LmNvbS5hdTAeFw0wMDA2MDIwNzU2MjFaFw0wMTA2"
- + "MDIwNzU2MjFaMIG4MQswCQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExGDAW"
- + "BgNVBAcTD1NvdXRoIE1lbGJvdXJuZTEaMBgGA1UEChMRQ29ubmVjdCA0IFB0eSBM"
- + "dGQxFzAVBgNVBAsTDldlYnNlcnZlciBUZWFtMR0wGwYDVQQDExR3d3cyLmNvbm5l"
- + "Y3Q0LmNvbS5hdTEoMCYGCSqGSIb3DQEJARYZd2VibWFzdGVyQGNvbm5lY3Q0LmNv"
- + "bS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArvDxclKAhyv7Q/Wmr2re"
- + "Gw4XL9Cnh9e+6VgWy2AWNy/MVeXdlxzd7QAuc1eOWQkGQEiLPy5XQtTY+sBUJ3AO"
- + "Rvd2fEVJIcjf29ey7bYua9J/vz5MG2KYo9/WCHIwqD9mmG9g0xLcfwq/s8ZJBswE"
- + "7sb85VU+h94PTvsWOsWuKaECAwEAAaN3MHUwJAYDVR0RBB0wG4EZd2VibWFzdGVy"
- + "QGNvbm5lY3Q0LmNvbS5hdTA6BglghkgBhvhCAQ0ELRYrbW9kX3NzbCBnZW5lcmF0"
- + "ZWQgY3VzdG9tIHNlcnZlciBjZXJ0aWZpY2F0ZTARBglghkgBhvhCAQEEBAMCBkAw"
- + "DQYJKoZIhvcNAQEEBQADgYEAotccfKpwSsIxM1Hae8DR7M/Rw8dg/RqOWx45HNVL"
- + "iBS4/3N/TO195yeQKbfmzbAA2jbPVvIvGgTxPgO1MP4ZgvgRhasaa0qCJCkWvpM4"
- + "yQf33vOiYQbpv4rTwzU8AmRlBG45WdjyNIigGV+oRc61aKCTnLq7zB8N3z1TF/bF"
- + "5/8=");
-
- //
- // ca.crt
- //
- byte[] cert2 = Base64.decode(
- "MIIDbDCCAtWgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBtzELMAkGA1UEBhMCQVUx"
- + "ETAPBgNVBAgTCFZpY3RvcmlhMRgwFgYDVQQHEw9Tb3V0aCBNZWxib3VybmUxGjAY"
- + "BgNVBAoTEUNvbm5lY3QgNCBQdHkgTHRkMR4wHAYDVQQLExVDZXJ0aWZpY2F0ZSBB"
- + "dXRob3JpdHkxFTATBgNVBAMTDENvbm5lY3QgNCBDQTEoMCYGCSqGSIb3DQEJARYZ"
- + "d2VibWFzdGVyQGNvbm5lY3Q0LmNvbS5hdTAeFw0wMDA2MDIwNzU1MzNaFw0wMTA2"
- + "MDIwNzU1MzNaMIG3MQswCQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExGDAW"
- + "BgNVBAcTD1NvdXRoIE1lbGJvdXJuZTEaMBgGA1UEChMRQ29ubmVjdCA0IFB0eSBM"
- + "dGQxHjAcBgNVBAsTFUNlcnRpZmljYXRlIEF1dGhvcml0eTEVMBMGA1UEAxMMQ29u"
- + "bmVjdCA0IENBMSgwJgYJKoZIhvcNAQkBFhl3ZWJtYXN0ZXJAY29ubmVjdDQuY29t"
- + "LmF1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgs5ptNG6Qv1ZpCDuUNGmv"
- + "rhjqMDPd3ri8JzZNRiiFlBA4e6/ReaO1U8ASewDeQMH6i9R6degFdQRLngbuJP0s"
- + "xcEE+SksEWNvygfzLwV9J/q+TQDyJYK52utb++lS0b48A1KPLwEsyL6kOAgelbur"
- + "ukwxowprKUIV7Knf1ajetQIDAQABo4GFMIGCMCQGA1UdEQQdMBuBGXdlYm1hc3Rl"
- + "ckBjb25uZWN0NC5jb20uYXUwDwYDVR0TBAgwBgEB/wIBADA2BglghkgBhvhCAQ0E"
- + "KRYnbW9kX3NzbCBnZW5lcmF0ZWQgY3VzdG9tIENBIGNlcnRpZmljYXRlMBEGCWCG"
- + "SAGG+EIBAQQEAwICBDANBgkqhkiG9w0BAQQFAAOBgQCsGvfdghH8pPhlwm1r3pQk"
- + "msnLAVIBb01EhbXm2861iXZfWqGQjrGAaA0ZpXNk9oo110yxoqEoSJSzniZa7Xtz"
- + "soTwNUpE0SLHvWf/SlKdFWlzXA+vOZbzEv4UmjeelekTm7lc01EEa5QRVzOxHFtQ"
- + "DhkaJ8VqOMajkQFma2r9iA==");
-
- //
- // testx509.pem
- //
- byte[] cert3 = Base64.decode(
- "MIIBWzCCAQYCARgwDQYJKoZIhvcNAQEEBQAwODELMAkGA1UEBhMCQVUxDDAKBgNV"
- + "BAgTA1FMRDEbMBkGA1UEAxMSU1NMZWF5L3JzYSB0ZXN0IENBMB4XDTk1MDYxOTIz"
- + "MzMxMloXDTk1MDcxNzIzMzMxMlowOjELMAkGA1UEBhMCQVUxDDAKBgNVBAgTA1FM"
- + "RDEdMBsGA1UEAxMUU1NMZWF5L3JzYSB0ZXN0IGNlcnQwXDANBgkqhkiG9w0BAQEF"
- + "AANLADBIAkEAqtt6qS5GTxVxGZYWa0/4u+IwHf7p2LNZbcPBp9/OfIcYAXBQn8hO"
- + "/Re1uwLKXdCjIoaGs4DLdG88rkzfyK5dPQIDAQABMAwGCCqGSIb3DQIFBQADQQAE"
- + "Wc7EcF8po2/ZO6kNCwK/ICH6DobgLekA5lSLr5EvuioZniZp5lFzAw4+YzPQ7XKJ"
- + "zl9HYIMxATFyqSiD9jsx");
-
- //
- // v3-cert1.pem
- //
- byte[] cert4 = Base64.decode(
- "MIICjTCCAfigAwIBAgIEMaYgRzALBgkqhkiG9w0BAQQwRTELMAkGA1UEBhMCVVMx"
- + "NjA0BgNVBAoTLU5hdGlvbmFsIEFlcm9uYXV0aWNzIGFuZCBTcGFjZSBBZG1pbmlz"
- + "dHJhdGlvbjAmFxE5NjA1MjgxMzQ5MDUrMDgwMBcROTgwNTI4MTM0OTA1KzA4MDAw"
- + "ZzELMAkGA1UEBhMCVVMxNjA0BgNVBAoTLU5hdGlvbmFsIEFlcm9uYXV0aWNzIGFu"
- + "ZCBTcGFjZSBBZG1pbmlzdHJhdGlvbjEgMAkGA1UEBRMCMTYwEwYDVQQDEwxTdGV2"
- + "ZSBTY2hvY2gwWDALBgkqhkiG9w0BAQEDSQAwRgJBALrAwyYdgxmzNP/ts0Uyf6Bp"
- + "miJYktU/w4NG67ULaN4B5CnEz7k57s9o3YY3LecETgQ5iQHmkwlYDTL2fTgVfw0C"
- + "AQOjgaswgagwZAYDVR0ZAQH/BFowWDBWMFQxCzAJBgNVBAYTAlVTMTYwNAYDVQQK"
- + "Ey1OYXRpb25hbCBBZXJvbmF1dGljcyBhbmQgU3BhY2UgQWRtaW5pc3RyYXRpb24x"
- + "DTALBgNVBAMTBENSTDEwFwYDVR0BAQH/BA0wC4AJODMyOTcwODEwMBgGA1UdAgQR"
- + "MA8ECTgzMjk3MDgyM4ACBSAwDQYDVR0KBAYwBAMCBkAwCwYJKoZIhvcNAQEEA4GB"
- + "AH2y1VCEw/A4zaXzSYZJTTUi3uawbbFiS2yxHvgf28+8Js0OHXk1H1w2d6qOHH21"
- + "X82tZXd/0JtG0g1T9usFFBDvYK8O0ebgz/P5ELJnBL2+atObEuJy1ZZ0pBDWINR3"
- + "WkDNLCGiTkCKp0F5EWIrVDwh54NNevkCQRZita+z4IBO");
-
- //
- // v3-cert2.pem
- //
- byte[] cert5 = Base64.decode(
- "MIICiTCCAfKgAwIBAgIEMeZfHzANBgkqhkiG9w0BAQQFADB9MQswCQYDVQQGEwJD"
- + "YTEPMA0GA1UEBxMGTmVwZWFuMR4wHAYDVQQLExVObyBMaWFiaWxpdHkgQWNjZXB0"
- + "ZWQxHzAdBgNVBAoTFkZvciBEZW1vIFB1cnBvc2VzIE9ubHkxHDAaBgNVBAMTE0Vu"
- + "dHJ1c3QgRGVtbyBXZWIgQ0EwHhcNOTYwNzEyMTQyMDE1WhcNOTYxMDEyMTQyMDE1"
- + "WjB0MSQwIgYJKoZIhvcNAQkBExVjb29rZUBpc3NsLmF0bC5ocC5jb20xCzAJBgNV"
- + "BAYTAlVTMScwJQYDVQQLEx5IZXdsZXR0IFBhY2thcmQgQ29tcGFueSAoSVNTTCkx"
- + "FjAUBgNVBAMTDVBhdWwgQS4gQ29va2UwXDANBgkqhkiG9w0BAQEFAANLADBIAkEA"
- + "6ceSq9a9AU6g+zBwaL/yVmW1/9EE8s5you1mgjHnj0wAILuoB3L6rm6jmFRy7QZT"
- + "G43IhVZdDua4e+5/n1ZslwIDAQABo2MwYTARBglghkgBhvhCAQEEBAMCB4AwTAYJ"
- + "YIZIAYb4QgENBD8WPVRoaXMgY2VydGlmaWNhdGUgaXMgb25seSBpbnRlbmRlZCBm"
- + "b3IgZGVtb25zdHJhdGlvbiBwdXJwb3Nlcy4wDQYJKoZIhvcNAQEEBQADgYEAi8qc"
- + "F3zfFqy1sV8NhjwLVwOKuSfhR/Z8mbIEUeSTlnH3QbYt3HWZQ+vXI8mvtZoBc2Fz"
- + "lexKeIkAZXCesqGbs6z6nCt16P6tmdfbZF3I3AWzLquPcOXjPf4HgstkyvVBn0Ap"
- + "jAFN418KF/Cx4qyHB4cjdvLrRjjQLnb2+ibo7QU=");
-
- byte[] cert6 = Base64.decode(
- "MIIEDjCCAvagAwIBAgIEFAAq2jANBgkqhkiG9w0BAQUFADBLMSowKAYDVQQDEyFT"
- + "dW4gTWljcm9zeXN0ZW1zIEluYyBDQSAoQ2xhc3MgQikxHTAbBgNVBAoTFFN1biBN"
- + "aWNyb3N5c3RlbXMgSW5jMB4XDTA0MDIyOTAwNDMzNFoXDTA5MDMwMTAwNDMzNFow"
- + "NzEdMBsGA1UEChMUU3VuIE1pY3Jvc3lzdGVtcyBJbmMxFjAUBgNVBAMTDXN0b3Jl"
- + "LnN1bi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAP9ErzFT7MPg2bVV"
- + "LNmHTgN4kmiRNlPpuLGWS7EDIXYBbLeSSOCp/e1ANcOGnsuf0WIq9ejd/CPyEfh4"
- + "sWoVvQzpOfHZ/Jyei29PEuxzWT+4kQmCx3+sLK25lAnDFsz1KiFmB6Y3GJ/JSjpp"
- + "L0Yy1R9YlIc82I8gSw44y5JDABW5AgMBAAGjggGQMIIBjDAOBgNVHQ8BAf8EBAMC"
- + "BaAwHQYDVR0OBBYEFG1WB3PApZM7OPPVWJ31UrERaoKWMEcGA1UdIARAMD4wPAYL"
- + "YIZIAYb3AIN9k18wLTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5zdW4uY29tL3Br"
- + "aS9jcHMuaHRtbDCBhQYDVR0fBH4wfDB6oCegJYYjaHR0cDovL3d3dy5zdW4uY29t"
- + "L3BraS9wa2lzbWljYS5jcmyiT6RNMEsxKjAoBgNVBAMTIVN1biBNaWNyb3N5c3Rl"
- + "bXMgSW5jIENBIChDbGFzcyBCKTEdMBsGA1UEChMUU3VuIE1pY3Jvc3lzdGVtcyBJ"
- + "bmMwHwYDVR0jBBgwFoAUT7ZnqR/EEBSgG6h1wdYMI5RiiWswVAYIKwYBBQUHAQEE"
- + "SDBGMB0GCCsGAQUFBzABhhFodHRwOi8vdmEuc3VuLmNvbTAlBggrBgEFBQcwAYYZ"
- + "aHR0cDovL3ZhLmNlbnRyYWwuc3VuLmNvbTATBgNVHSUEDDAKBggrBgEFBQcDATAN"
- + "BgkqhkiG9w0BAQUFAAOCAQEAq3byQgyU24tBpR07iQK7agm1zQyzDQ6itdbji0ln"
- + "T7fOd5Pnp99iig8ovwWliNtXKAmgtJY60jWz7nEuk38AioZJhS+RPWIWX/+2PRV7"
- + "s2aWTzM3n43BypD+jU2qF9c9kDWP/NW9K9IcrS7SfU/2MZVmiCMD/9FEL+CWndwE"
- + "JJQ/oenXm44BFISI/NjV7fMckN8EayPvgtzQkD5KnEiggOD6HOrwTDFR+tmAEJ0K"
- + "ZttQNwOzCOcEdxXTg6qBHUbONdL7bjTT5NzV+JR/bnfiCqHzdnGwfbHzhmrnXw8j"
- + "QCVXcfBfL9++nmpNNRlnJMRdYGeCY6OAfh/PRo8/fXak1Q==");
-
- byte[] cert7 = Base64.decode(
- "MIIFJDCCBAygAwIBAgIKEcJZuwAAAAAABzANBgkqhkiG9w0BAQUFADAPMQ0wCwYD"
- + "VQQDEwRNU0NBMB4XDTA0MDUyMjE2MTM1OFoXDTA1MDUyMjE2MjM1OFowaTEbMBkG"
- + "CSqGSIb3DQEJCBMMMTkyLjE2OC4xLjMzMScwJQYJKoZIhvcNAQkCExhwaXhmaXJl"
- + "d2FsbC5jaXNjb3BpeC5jb20xITAfBgNVBAMTGHBpeGZpcmV3YWxsLmNpc2NvcGl4"
- + "LmNvbTB8MA0GCSqGSIb3DQEBAQUAA2sAMGgCYQCbcsY7vrjweXZiFQdhUafEjJV+"
- + "HRy5UKmuCy0237ffmYrN+XNLw0h90cdCSK6KPZebd2E2Bc2UmTikc/FY8meBT3/E"
- + "O/Osmywzi++Ur8/IrDvtuR1zd0c/xEPnV1ZRezkCAwEAAaOCAs4wggLKMAsGA1Ud"
- + "DwQEAwIFoDAdBgNVHQ4EFgQUzJBSxkQiN9TKvhTMQ1/Aq4gZnHswHwYDVR0jBBgw"
- + "FoAUMsxzXVh+5UKMNpwNHmqSfcRYfJ4wgfcGA1UdHwSB7zCB7DCB6aCB5qCB44aB"
- + "r2xkYXA6Ly8vQ049TVNDQSxDTj1NQVVELENOPUNEUCxDTj1QdWJsaWMlMjBLZXkl"
- + "MjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25maWd1cmF0aW9uLERDPWludCxE"
- + "Qz1wcmltZWtleSxEQz1zZT9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0P2Jhc2U/"
- + "b2JqZWN0Q2xhc3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnSGL2h0dHA6Ly9tYXVkLmlu"
- + "dC5wcmltZWtleS5zZS9DZXJ0RW5yb2xsL01TQ0EuY3JsMIIBEAYIKwYBBQUHAQEE"
- + "ggECMIH/MIGqBggrBgEFBQcwAoaBnWxkYXA6Ly8vQ049TVNDQSxDTj1BSUEsQ049"
- + "UHVibGljJTIwS2V5JTIwU2VydmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJh"
- + "dGlvbixEQz1pbnQsREM9cHJpbWVrZXksREM9c2U/Y0FDZXJ0aWZpY2F0ZT9iYXNl"
- + "P29iamVjdENsYXNzPWNlcnRpZmljYXRpb25BdXRob3JpdHkwUAYIKwYBBQUHMAKG"
- + "RGh0dHA6Ly9tYXVkLmludC5wcmltZWtleS5zZS9DZXJ0RW5yb2xsL01BVUQuaW50"
- + "LnByaW1la2V5LnNlX01TQ0EuY3J0MCwGA1UdEQEB/wQiMCCCGHBpeGZpcmV3YWxs"
- + "LmNpc2NvcGl4LmNvbYcEwKgBITA/BgkrBgEEAYI3FAIEMh4wAEkAUABTAEUAQwBJ"
- + "AG4AdABlAHIAbQBlAGQAaQBhAHQAZQBPAGYAZgBsAGkAbgBlMA0GCSqGSIb3DQEB"
- + "BQUAA4IBAQCa0asiPbObLJjpSz6ndJ7y4KOWMiuuBc/VQBnLr7RBCF3ZlZ6z1+e6"
- + "dmv8se/z11NgateKfxw69IhLCriA960HEgX9Z61MiVG+DrCFpbQyp8+hPFHoqCZN"
- + "b7upc8k2OtJW6KPaP9k0DW52YQDIky4Vb2rZeC4AMCorWN+KlndHhr1HFA14HxwA"
- + "4Mka0FM6HNWnBV2UmTjBZMDr/OrGH1jLYIceAaZK0X2R+/DWXeeqIga8jwP5empq"
- + "JetYnkXdtTbEh3xL0BX+mZl8vDI+/PGcwox/7YjFmyFWphRMxk9CZ3rF2/FQWMJP"
- + "YqQpKiQOmQg5NAhcwffLAuVjVVibPYqi");
-
- byte[] cert8 = Base64.decode(
- "MIIB0zCCATwCAQEwbqBsMGekZTBjMQswCQYDVQQGEwJERTELMAkGA1UECBMCQlkx"
- + "EzARBgNVBAcTClJlZ2Vuc2J1cmcxEDAOBgNVBAoTB0FDIFRlc3QxCzAJBgNVBAsT"
- + "AkNBMRMwEQYDVQQDEwpBQyBUZXN0IENBAgEBoHYwdKRyMHAxCzAJBgNVBAYTAkRF"
- + "MQswCQYDVQQIEwJCWTETMBEGA1UEBxMKUmVnZW5zYnVyZzESMBAGA1UEChMJQUMg"
- + "SXNzdWVyMRowGAYDVQQLExFBQyBJc3N1ZXIgc2VjdGlvbjEPMA0GA1UEAxMGQUMg"
- + "TWFuMA0GCSqGSIb3DQEBBQUAAgEBMCIYDzIwMDQxMTI2MTI1MjUxWhgPMjAwNDEy"
- + "MzEyMzAwMDBaMBkwFwYDVRhIMRAwDoEMREFVMTIzNDU2Nzg5MA0GCSqGSIb3DQEB"
- + "BQUAA4GBABd4Odx3yEMGL/BvItuT1RafNR2uuWuZbajg0pD6bshUsl+WCIfRiEkq"
- + "lHMkpI7WqAZikdnAEQ5jQsVWEuVejWxR6gjejKxc0fb9qpIui7/GoI5Eh6dmG20e"
- + "xbwJL3+6YYFrZwxR8cC5rPvWrblUR5XKJy+Zp/H5+t9iANnL1L8J");
-
- // V1 attribute certificate
- private static final byte[] attrCertv1 = Base64.decode(
- "MIIFdDCCBFygXTBbMFOkUTBPMQswCQYDVQQGEwJERTEcMBoGA1UECgwTRGV1"
- + "dHNjaGUgVGVsZWtvbSBBRzEiMCAGA1UEAwwZVGVsZVNlYyBQS1MgU2lnRyBD"
- + "QSAxNzpQTgIEG1toDjBTpFEwTzELMAkGA1UEBhMCREUxHDAaBgNVBAoME0Rl"
- + "dXRzY2hlIFRlbGVrb20gQUcxIjAgBgNVBAMMGVRlbGVTZWMgUEtTIFNpZ0cg"
- + "Q0EgMjU6UE4wDQYJKoZIhvcNAQELBQACBCep3f0wIhgPMjAxMDA0MTIxMTI5"
- + "MTJaGA8yMDEyMDQxMjEwNTkyOFowggGmMIIBogYFKyQIAwgxggGXDIIBk1Ro"
- + "ZSBxdWFsaWZpZWQgc2lnbmF0dXJlIGF0IGhhbmQgaXMgcmVzdHJpY3RlZCB0"
- + "byBwcmVzZW50aW5nIGludm9pY2VzIG9yIGNyZWRpdHMgdG8gY3VzdG9tZXJz"
- + "IGFjY29yZGluZyB0byBFVSBDb3VuY2lsIGRpcmVjdGl2ZSAyMDAxLzExNS9F"
- + "QyAoMjB0aCBEZWNlbWJlciAyMDAxKSBhbmQgR2VybWFuIFZBVCB0YXggKMKn"
- + "MTQgVVN0RykuICBEaWUgdm9ybGllZ2VuZGUgcXVhbGlmaXppZXJ0ZSBTaWdu"
- + "YXR1ciBpc3QgYXVmIGRpZSAgUHJhZXNlbnRhdGlvbiB2b24gUmVjaG51bmdl"
- + "biBvZGVyIEd1dHNjaHJpZnRlbiBnZW1hZXNzIEVVIERpcmVrdGl2ZSAyMDAx"
- + "LzExNS9FQyAoMjAuIERlemVtYmVyIDIwMDEpIHVuZCBkZXV0c2NoZW0gVW1z"
- + "YXR6c3RldWVyZ2VzZXR6ICAowqcxNCBVU3RHKSBiZXNjaHJhZW5rdC4wggHB"
- + "MB8GA1UdIwQYMBaAFM6i1yR/z8IikpxpU/Fdh8BPxhq8MEMGA1UdIAQ8MDow"
- + "OAYFKyQIAQEwLzAtBggrBgEFBQcCARYhaHR0cDovL3Brcy50ZWxlc2VjLmRl"
- + "L2Nwcy9jcHMucGRmMIIBBAYDVR0fBIH8MIH5MIH2oG2ga4Y1bGRhcDovL3Br"
- + "cy1sZGFwLnRlbGVzZWMuZGUvbz1EZXV0c2NoZSBUZWxla29tIEFHLGM9ZGWG"
- + "Mmh0dHA6Ly9wa3MudGVsZXNlYy5kZS90ZWxlc2VjL3NlcnZsZXQvZG93bmxv"
- + "YWRfY3JsooGEpIGBMH8xCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2No"
- + "ZSBUZWxla29tIEFHMR8wHQYDVQQLFBZQcm9kdWt0emVudHJ1bSBUZWxlU2Vj"
- + "MTEwDAYHAoIGAQoHFBMBMTAhBgNVBAMUGlRlbGVTZWMgUEtTIFNpZ0cgRElS"
- + "IDM1OlBOMDcGCCsGAQUFBwEBBCswKTAnBggrBgEFBQcwAYYbaHR0cDovL3Br"
- + "cy50ZWxlc2VjLmRlL29jc3ByMBgGCCsGAQUFBwEDBAwwCjAIBgYEAI5GAQEw"
- + "DQYJKoZIhvcNAQELBQADggEBAEz2OvU9YytJUKHMDQcND5njIyUXTkSrlWjV"
- + "F28uwxVlveO4JPTAY7PvXy69HUuTPwlvqCfJIUF2RLPZFQx0wFto8ajC9v5X"
- + "SqwQcINXRakpE6FPAdQFnH44TaIQWXW1hy9xr8GuD0uhQLTJGYqVzHfLoM8e"
- + "llPNHUVhC7CEOxDb1PTHCUlQFNkFRmeeqzEVoj1F0pM6wI5zf8+w2WwrFPCD"
- + "jrjEr/VoBRoEi/tKnsLq6oOkizUKT0KJEnSyYxoOa7euT1yX+Co94SPnMZi5"
- + "qukHSj8Kiio6Jecl//qDPG/mHo1ro+8rH+rbze7EEfKMp5yeWCwXGthL9oYo"
- + "RYl+UuI=");
-
- String[] subjects =
- {
- "C=AU,ST=Victoria,L=South Melbourne,O=Connect 4 Pty Ltd,OU=Webserver Team,CN=www2.connect4.com.au,E=webmaster@connect4.com.au",
- "C=AU,ST=Victoria,L=South Melbourne,O=Connect 4 Pty Ltd,OU=Certificate Authority,CN=Connect 4 CA,E=webmaster@connect4.com.au",
- "C=AU,ST=QLD,CN=SSLeay/rsa test cert",
- "C=US,O=National Aeronautics and Space Administration,SERIALNUMBER=16+CN=Steve Schoch",
- "E=cooke@issl.atl.hp.com,C=US,OU=Hewlett Packard Company (ISSL),CN=Paul A. Cooke",
- "O=Sun Microsystems Inc,CN=store.sun.com",
- "unstructuredAddress=192.168.1.33,unstructuredName=pixfirewall.ciscopix.com,CN=pixfirewall.ciscopix.com"
- };
-
- public String getName()
- {
- return "Certificate";
- }
-
- public void checkCertificate(
- int id,
- byte[] cert)
- throws Exception
- {
- ByteArrayInputStream bIn = new ByteArrayInputStream(cert);
- ASN1InputStream aIn = new ASN1InputStream(bIn);
-
- ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
-// String dump = ASN1Dump.dumpAsString(seq);
-
- Certificate obj = Certificate.getInstance(seq);
- TBSCertificate tbsCert = obj.getTBSCertificate();
-
- if (!tbsCert.getSubject().toString().equals(subjects[id - 1]))
- {
- fail("failed subject test for certificate id " + id + " got " + tbsCert.getSubject().toString());
- }
-
- if (tbsCert.getVersionNumber() == 3)
- {
- Extensions ext = tbsCert.getExtensions();
- if (ext != null)
- {
- Enumeration en = ext.oids();
- while (en.hasMoreElements())
- {
- ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)en.nextElement();
- Extension extVal = ext.getExtension(oid);
-
- ASN1OctetString oct = extVal.getExtnValue();
- ASN1InputStream extIn = new ASN1InputStream(new ByteArrayInputStream(oct.getOctets()));
-
- if (oid.equals(Extension.subjectKeyIdentifier))
- {
- SubjectKeyIdentifier si = SubjectKeyIdentifier.getInstance(extIn.readObject());
-
- if (!si.equals(SubjectKeyIdentifier.fromExtensions(ext)))
- {
- fail("SubjectKeyIdentifier not matched");
- }
- }
- else if (oid.equals(Extension.keyUsage))
- {
- KeyUsage ku = KeyUsage.getInstance(extIn.readObject());
-
- if (!ku.equals(KeyUsage.fromExtensions(ext)))
- {
- fail("KeyUsage not matched");
- }
- }
- else if (oid.equals(Extension.extendedKeyUsage))
- {
- ExtendedKeyUsage ku = ExtendedKeyUsage.getInstance(extIn.readObject());
-
- ASN1Sequence sq = (ASN1Sequence)ku.toASN1Primitive();
- for (int i = 0; i != sq.size(); i++)
- {
- ASN1ObjectIdentifier p = ASN1ObjectIdentifier.getInstance(KeyPurposeId.getInstance(sq.getObjectAt(i)));
- }
-
- if (!ku.equals(ExtendedKeyUsage.fromExtensions(ext)))
- {
- fail("ExtendedKeyUsage not matched");
- }
- }
- else if (oid.equals(Extension.subjectAlternativeName))
- {
- GeneralNames gn = GeneralNames.getInstance(extIn.readObject());
-
- ASN1Sequence sq = (ASN1Sequence)gn.toASN1Primitive();
- for (int i = 0; i != sq.size(); i++)
- {
- GeneralName n = GeneralName.getInstance(sq.getObjectAt(i));
- }
- }
- else if (oid.equals(Extension.issuerAlternativeName))
- {
- GeneralNames gn = GeneralNames.getInstance(extIn.readObject());
-
- ASN1Sequence sq = (ASN1Sequence)gn.toASN1Primitive();
- for (int i = 0; i != sq.size(); i++)
- {
- GeneralName n = GeneralName.getInstance(sq.getObjectAt(i));
- }
- }
- else if (oid.equals(Extension.cRLDistributionPoints))
- {
- CRLDistPoint p = CRLDistPoint.getInstance(extIn.readObject());
-
- DistributionPoint[] points = p.getDistributionPoints();
- for (int i = 0; i != points.length; i++)
- {
- // do nothing
- }
- }
- else if (oid.equals(Extension.certificatePolicies))
- {
- ASN1Sequence cp = (ASN1Sequence)extIn.readObject();
-
- for (int i = 0; i != cp.size(); i++)
- {
- PolicyInformation.getInstance(cp.getObjectAt(i));
- }
- }
- else if (oid.equals(Extension.authorityKeyIdentifier))
- {
- AuthorityKeyIdentifier auth = AuthorityKeyIdentifier.getInstance(extIn.readObject());
-
- if (!auth.equals(AuthorityKeyIdentifier.fromExtensions(ext)))
- {
- fail("AuthorityKeyIdentifier not matched");
- }
- }
- else if (oid.equals(Extension.basicConstraints))
- {
- BasicConstraints bc = BasicConstraints.getInstance(extIn.readObject());
-
- if (!bc.equals(BasicConstraints.fromExtensions(ext)))
- {
- fail("BasicConstraints not matched");
- }
- }
- else
- {
- //System.out.println(oid.getId());
- }
- }
- }
- }
- }
-
-
- public void checkAttributeCertificate(
- int id,
- byte[] cert)
- throws Exception
- {
- ByteArrayInputStream bIn;
- ASN1InputStream aIn;
-
- bIn = new ByteArrayInputStream(cert);
- aIn = new ASN1InputStream(bIn);
-
- ASN1Sequence seq = (ASN1Sequence) aIn.readObject();
-// String dump = ASN1Dump.dumpAsString(seq);
-
- AttributeCertificate obj = AttributeCertificate.getInstance(seq);
- AttributeCertificateInfo acInfo = obj.getAcinfo();
-
- // Version
- if (!(acInfo.getVersion().equals(new ASN1Integer(1)))
- && (!(acInfo.getVersion().equals(new ASN1Integer(2)))))
- {
- fail(
- "failed AC Version test for id " + id);
- }
-
- // Holder
- Holder h = acInfo.getHolder();
- if (h == null)
- {
- fail(
- "failed AC Holder test, it's null, for id " + id);
- }
-
- // Issuer
- AttCertIssuer aci = acInfo.getIssuer();
- if (aci == null)
- {
- fail(
- "failed AC Issuer test, it's null, for id " + id);
- }
-
- // Signature
- AlgorithmIdentifier sig = acInfo.getSignature();
- if (sig == null)
- {
- fail(
- "failed AC Signature test for id " + id);
- }
-
- // Serial
- ASN1Integer serial = acInfo.getSerialNumber();
-
- // Validity
- AttCertValidityPeriod validity = acInfo.getAttrCertValidityPeriod();
- if (validity == null)
- {
- fail("failed AC AttCertValidityPeriod test for id " + id);
- }
-
- // Attributes
- ASN1Sequence attribSeq = acInfo.getAttributes();
- Attribute att[] = new Attribute[attribSeq.size()];
- for (int i = 0; i < attribSeq.size(); i++)
- {
- att[i] = Attribute.getInstance(attribSeq.getObjectAt(i));
- }
-
- // IssuerUniqueId
- // TODO, how to best test?
-
- // X509 Extensions
- Extensions ext = acInfo.getExtensions();
- if (ext != null)
- {
- Enumeration en = ext.oids();
- while (en.hasMoreElements())
- {
- ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier) en
- .nextElement();
- Extension extVal = ext.getExtension(oid);
- }
- }
- }
-
- public void checkV1AttributeCertificate(
- int id,
- byte[] cert)
- throws Exception
- {
- ByteArrayInputStream bIn;
- ASN1InputStream aIn;
-
- bIn = new ByteArrayInputStream(cert);
- aIn = new ASN1InputStream(bIn);
-
- ASN1Sequence seq = (ASN1Sequence) aIn.readObject();
- //String dump = ASN1Dump.dumpAsString(seq);
-
- AttributeCertificate obj = AttributeCertificate.getInstance(seq);
- AttributeCertificateInfo acInfo = obj.getAcinfo();
-
- // Version
- if (!(acInfo.getVersion().equals(new ASN1Integer(0))))
- {
- fail(
- "failed AC Version test for id " + id);
- }
-
- // Holder
- Holder h = acInfo.getHolder();
- if (h == null)
- {
- fail(
- "failed AC Holder test, it's null, for id " + id);
- }
-
- // Issuer
- AttCertIssuer aci = acInfo.getIssuer();
- if (aci == null)
- {
- fail(
- "failed AC Issuer test, it's null, for id " + id);
- }
-
- // Signature
- AlgorithmIdentifier sig = acInfo.getSignature();
- if (sig == null)
- {
- fail(
- "failed AC Signature test for id " + id);
- }
-
- // Serial
- ASN1Integer serial = acInfo.getSerialNumber();
-
- // Validity
- AttCertValidityPeriod validity = acInfo.getAttrCertValidityPeriod();
- if (validity == null)
- {
- fail("failed AC AttCertValidityPeriod test for id " + id);
- }
-
- // Attributes
- ASN1Sequence attribSeq = acInfo.getAttributes();
- Attribute att[] = new Attribute[attribSeq.size()];
- for (int i = 0; i < attribSeq.size(); i++)
- {
- att[i] = Attribute.getInstance(attribSeq.getObjectAt(i));
- }
-
- // IssuerUniqueId
- // TODO, how to best test?
-
- // X509 Extensions
- Extensions ext = acInfo.getExtensions();
- if (ext != null)
- {
- Enumeration en = ext.oids();
- while (en.hasMoreElements())
- {
- ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier) en
- .nextElement();
- Extension extVal = ext.getExtension(oid);
- }
- }
- }
-
- public void performTest()
- throws Exception
- {
- checkCertificate(1, cert1);
- checkCertificate(2, cert2);
- checkCertificate(3, cert3);
- checkCertificate(4, cert4);
- checkCertificate(5, cert5);
- checkCertificate(6, cert6);
- checkCertificate(7, cert7);
- checkAttributeCertificate(8,cert8);
- checkV1AttributeCertificate(9, attrCertv1);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new CertificateTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/CommitmentTypeIndicationUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/CommitmentTypeIndicationUnitTest.java
deleted file mode 100644
index 0ce1c236..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/CommitmentTypeIndicationUnitTest.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.esf.CommitmentTypeIdentifier;
-import org.bouncycastle.asn1.esf.CommitmentTypeIndication;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class CommitmentTypeIndicationUnitTest
- extends SimpleTest
-{
- public String getName()
- {
- return "CommitmentTypeIndication";
- }
-
- public void performTest()
- throws Exception
- {
- CommitmentTypeIndication cti = new CommitmentTypeIndication(CommitmentTypeIdentifier.proofOfOrigin);
-
- checkConstruction(cti, CommitmentTypeIdentifier.proofOfOrigin, null);
-
- ASN1Sequence qualifier = new DERSequence(new ASN1ObjectIdentifier("1.2"));
-
- cti = new CommitmentTypeIndication(CommitmentTypeIdentifier.proofOfOrigin, qualifier);
-
- checkConstruction(cti, CommitmentTypeIdentifier.proofOfOrigin, qualifier);
-
- cti = CommitmentTypeIndication.getInstance(null);
-
- if (cti != null)
- {
- fail("null getInstance() failed.");
- }
-
- try
- {
- CommitmentTypeIndication.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- CommitmentTypeIndication mv,
- ASN1ObjectIdentifier commitmenttTypeId,
- ASN1Encodable qualifier)
- throws IOException
- {
- checkStatement(mv, commitmenttTypeId, qualifier);
-
- mv = CommitmentTypeIndication.getInstance(mv);
-
- checkStatement(mv, commitmenttTypeId, qualifier);
-
- ASN1InputStream aIn = new ASN1InputStream(mv.toASN1Object().getEncoded());
-
- ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
-
- mv = CommitmentTypeIndication.getInstance(seq);
-
- checkStatement(mv, commitmenttTypeId, qualifier);
- }
-
- private void checkStatement(
- CommitmentTypeIndication cti,
- ASN1ObjectIdentifier commitmentTypeId,
- ASN1Encodable qualifier)
- {
- if (!cti.getCommitmentTypeId().equals(commitmentTypeId))
- {
- fail("commitmentTypeIds don't match.");
- }
-
- if (qualifier != null)
- {
- if (!cti.getCommitmentTypeQualifier().equals(qualifier))
- {
- fail("qualifiers don't match.");
- }
- }
- else if (cti.getCommitmentTypeQualifier() != null)
- {
- fail("qualifier found when none expected.");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new CommitmentTypeIndicationUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/CommitmentTypeQualifierUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/CommitmentTypeQualifierUnitTest.java
deleted file mode 100644
index 2d782ba9..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/CommitmentTypeQualifierUnitTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.esf.CommitmentTypeIdentifier;
-import org.bouncycastle.asn1.esf.CommitmentTypeQualifier;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class CommitmentTypeQualifierUnitTest
- extends SimpleTest
-{
- public String getName()
- {
- return "CommitmentTypeQualifier";
- }
-
- public void performTest()
- throws Exception
- {
- CommitmentTypeQualifier ctq = new CommitmentTypeQualifier(CommitmentTypeIdentifier.proofOfOrigin);
-
- checkConstruction(ctq, CommitmentTypeIdentifier.proofOfOrigin, null);
-
- ASN1Encodable info = new ASN1ObjectIdentifier("1.2");
-
- ctq = new CommitmentTypeQualifier(CommitmentTypeIdentifier.proofOfOrigin, info);
-
- checkConstruction(ctq, CommitmentTypeIdentifier.proofOfOrigin, info);
-
- ctq = CommitmentTypeQualifier.getInstance(null);
-
- if (ctq != null)
- {
- fail("null getInstance() failed.");
- }
-
- try
- {
- CommitmentTypeQualifier.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- CommitmentTypeQualifier mv,
- ASN1ObjectIdentifier commitmenttTypeId,
- ASN1Encodable qualifier)
- throws IOException
- {
- checkStatement(mv, commitmenttTypeId, qualifier);
-
- mv = CommitmentTypeQualifier.getInstance(mv);
-
- checkStatement(mv, commitmenttTypeId, qualifier);
-
- ASN1InputStream aIn = new ASN1InputStream(mv.toASN1Object().getEncoded());
-
- ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
-
- mv = CommitmentTypeQualifier.getInstance(seq);
-
- checkStatement(mv, commitmenttTypeId, qualifier);
- }
-
- private void checkStatement(
- CommitmentTypeQualifier ctq,
- ASN1ObjectIdentifier commitmentTypeId,
- ASN1Encodable qualifier)
- {
- if (!ctq.getCommitmentTypeIdentifier().equals(commitmentTypeId))
- {
- fail("commitmentTypeIds don't match.");
- }
-
- if (qualifier != null)
- {
- if (!ctq.getQualifier().equals(qualifier))
- {
- fail("qualifiers don't match.");
- }
- }
- else if (ctq.getQualifier() != null)
- {
- fail("qualifier found when none expected.");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new CommitmentTypeQualifierUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/ContentHintsUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/ContentHintsUnitTest.java
deleted file mode 100644
index 1ae15e7b..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/ContentHintsUnitTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERUTF8String;
-import org.bouncycastle.asn1.ess.ContentHints;
-
-public class ContentHintsUnitTest
- extends ASN1UnitTest
-{
- public String getName()
- {
- return "ContentHints";
- }
-
- public void performTest()
- throws Exception
- {
- DERUTF8String contentDescription = new DERUTF8String("Description");
- ASN1ObjectIdentifier contentType = new ASN1ObjectIdentifier("1.2.2.3");
-
- ContentHints hints = new ContentHints(contentType);
-
- checkConstruction(hints, contentType, null);
-
- hints = new ContentHints(contentType, contentDescription);
-
- checkConstruction(hints, contentType, contentDescription);
-
- hints = ContentHints.getInstance(null);
-
- if (hints != null)
- {
- fail("null getInstance() failed.");
- }
-
- try
- {
- ContentHints.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- ContentHints hints,
- ASN1ObjectIdentifier contentType,
- DERUTF8String description)
- throws IOException
- {
- checkValues(hints, contentType, description);
-
- hints = ContentHints.getInstance(hints);
-
- checkValues(hints, contentType, description);
-
- ASN1InputStream aIn = new ASN1InputStream(hints.toASN1Primitive().getEncoded());
-
- ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
-
- hints = ContentHints.getInstance(seq);
-
- checkValues(hints, contentType, description);
- }
-
- private void checkValues(
- ContentHints hints,
- ASN1ObjectIdentifier contentType,
- DERUTF8String description)
- {
- checkMandatoryField("contentType", contentType, hints.getContentType());
- checkOptionalField("description", description, hints.getContentDescription());
- }
-
- public static void main(
- String[] args)
- {
- runTest(new ContentHintsUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/CscaMasterListTest.java b/core/src/test/java/org/bouncycastle/asn1/test/CscaMasterListTest.java
deleted file mode 100644
index c8700697..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/CscaMasterListTest.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.icao.CscaMasterList;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.io.Streams;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class CscaMasterListTest
- extends SimpleTest
-{
- public String getName()
- {
- return "CscaMasterList";
- }
-
- public void performTest()
- throws Exception
- {
- byte[] input = getInput("masterlist-content.data");
- CscaMasterList parsedList
- = CscaMasterList.getInstance(ASN1Primitive.fromByteArray(input));
-
- if (parsedList.getCertStructs().length != 3)
- {
- fail("Cert structure parsing failed: incorrect length");
- }
-
- byte[] output = parsedList.getEncoded();
- if (!Arrays.areEqual(input, output))
- {
- fail("Encoding failed after parse");
- }
- }
-
- private byte[] getInput(String name)
- throws IOException
- {
- return Streams.readAll(getClass().getResourceAsStream(name));
- }
-
- public static void main(
- String[] args)
- {
- runTest(new CscaMasterListTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/DERApplicationSpecificTest.java b/core/src/test/java/org/bouncycastle/asn1/test/DERApplicationSpecificTest.java
deleted file mode 100644
index 2e047dee..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/DERApplicationSpecificTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import org.bouncycastle.asn1.ASN1Encoding;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.BERTags;
-import org.bouncycastle.asn1.DERApplicationSpecific;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class DERApplicationSpecificTest
- extends SimpleTest
-{
- private static final byte[] impData = Hex.decode("430109");
-
- private static final byte[] certData = Hex.decode(
- "7F218201897F4E8201495F290100420E44454356434145504153533030317F49"
- + "81FD060A04007F00070202020202811CD7C134AA264366862A18302575D1D787"
- + "B09F075797DA89F57EC8C0FF821C68A5E62CA9CE6C1C299803A6C1530B514E18"
- + "2AD8B0042A59CAD29F43831C2580F63CCFE44138870713B1A92369E33E2135D2"
- + "66DBB372386C400B8439040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C"
- + "1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D376"
- + "1402CD851CD7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A793"
- + "9F863904393EE8E06DB6C7F528F8B4260B49AA93309824D92CDB1807E5437EE2"
- + "E26E29B73A7111530FA86B350037CB9415E153704394463797139E148701015F"
- + "200E44454356434145504153533030317F4C0E060904007F0007030102015301"
- + "C15F25060007000400015F24060009000400015F37384CCF25C59F3612EEE188"
- + "75F6C5F2E2D21F0395683B532A26E4C189B71EFE659C3F26E0EB9AEAE9986310"
- + "7F9B0DADA16414FFA204516AEE2B");
-
- public String getName()
- {
- return "DERApplicationSpecific";
- }
-
- public void performTest()
- throws Exception
- {
- ASN1Integer value = new ASN1Integer(9);
-
- DERApplicationSpecific tagged = new DERApplicationSpecific(false, 3, value);
-
- if (!areEqual(impData, tagged.getEncoded()))
- {
- fail("implicit encoding failed");
- }
-
- ASN1Integer recVal = (ASN1Integer)tagged.getObject(BERTags.INTEGER);
-
- if (!value.equals(recVal))
- {
- fail("implicit read back failed");
- }
-
- DERApplicationSpecific certObj = (DERApplicationSpecific)
- ASN1Primitive.fromByteArray(certData);
-
- if (!certObj.isConstructed() || certObj.getApplicationTag() != 33)
- {
- fail("parsing of certificate data failed");
- }
-
- byte[] encoded = certObj.getEncoded(ASN1Encoding.DER);
-
- if (!Arrays.areEqual(certData, encoded))
- {
- fail("re-encoding of certificate data failed");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new DERApplicationSpecificTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/DERUTF8StringTest.java b/core/src/test/java/org/bouncycastle/asn1/test/DERUTF8StringTest.java
deleted file mode 100644
index 7e38d7da..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/DERUTF8StringTest.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERUTF8String;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Strings;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-public class DERUTF8StringTest
- implements Test
-{
-
- /**
- * Unicode code point U+10400 coded as surrogate in two native Java UTF-16
- * code units
- */
- private final static char[] glyph1_utf16 = { 0xd801, 0xdc00 };
-
- /**
- * U+10400 coded in UTF-8
- */
- private final static byte[] glyph1_utf8 = { (byte)0xF0, (byte)0x90, (byte)0x90, (byte)0x80 };
-
- /**
- * Unicode code point U+6771 in native Java UTF-16
- */
- private final static char[] glyph2_utf16 = { 0x6771 };
-
- /**
- * U+6771 coded in UTF-8
- */
- private final static byte[] glyph2_utf8 = { (byte)0xE6, (byte)0x9D, (byte)0xB1 };
-
- /**
- * Unicode code point U+00DF in native Java UTF-16
- */
- private final static char[] glyph3_utf16 = { 0x00DF };
-
- /**
- * U+00DF coded in UTF-8
- */
- private final static byte[] glyph3_utf8 = { (byte)0xC3, (byte)0x9f };
-
- /**
- * Unicode code point U+0041 in native Java UTF-16
- */
- private final static char[] glyph4_utf16 = { 0x0041 };
-
- /**
- * U+0041 coded in UTF-8
- */
- private final static byte[] glyph4_utf8 = { 0x41 };
-
- private final static byte[][] glyphs_utf8 = { glyph1_utf8, glyph2_utf8, glyph3_utf8, glyph4_utf8 };
-
- private final static char[][] glyphs_utf16 = { glyph1_utf16, glyph2_utf16, glyph3_utf16, glyph4_utf16 };
-
- public TestResult perform()
- {
- try
- {
- for (int i = 0; i < glyphs_utf16.length; i++)
- {
- String s = new String(glyphs_utf16[i]);
- byte[] b1 = new DERUTF8String(s).getEncoded();
- byte temp[] = new byte[b1.length - 2];
- System.arraycopy(b1, 2, temp, 0, b1.length - 2);
- byte[] b2 = new DERUTF8String(Strings.fromUTF8ByteArray(new DEROctetString(temp).getOctets())).getEncoded();
- if (!Arrays.areEqual(b1, b2))
- {
- return new SimpleTestResult(false, getName() + ": failed UTF-8 encoding and decoding");
- }
- if (!Arrays.areEqual(temp, glyphs_utf8[i]))
- {
- return new SimpleTestResult(false, getName() + ": failed UTF-8 encoding and decoding");
- }
- }
- }
- catch (Exception e)
- {
- return new SimpleTestResult(false, getName() + ": failed with Exception " + e.getMessage());
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
-
- public String getName()
- {
- return "DERUTF8String";
- }
-
- public static void main(String[] args)
- {
- DERUTF8StringTest test = new DERUTF8StringTest();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/DataGroupHashUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/DataGroupHashUnitTest.java
deleted file mode 100644
index 85f01e98..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/DataGroupHashUnitTest.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-import java.util.Random;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.icao.DataGroupHash;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class DataGroupHashUnitTest
- extends SimpleTest
-{
- public String getName()
- {
- return "DataGroupHash";
- }
-
- private byte[] generateHash()
- {
- Random rand = new Random();
- byte[] bytes = new byte[20];
-
- for (int i = 0; i != bytes.length; i++)
- {
- bytes[i] = (byte)rand.nextInt();
- }
-
- return bytes;
- }
-
- public void performTest()
- throws Exception
- {
- int dataGroupNumber = 1;
- ASN1OctetString dataHash = new DEROctetString(generateHash());
- DataGroupHash dg = new DataGroupHash(dataGroupNumber, dataHash);
-
- checkConstruction(dg, dataGroupNumber, dataHash);
-
- try
- {
- DataGroupHash.getInstance(null);
- }
- catch (Exception e)
- {
- fail("getInstance() failed to handle null.");
- }
-
- try
- {
- DataGroupHash.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- DataGroupHash dg,
- int dataGroupNumber,
- ASN1OctetString dataGroupHashValue)
- throws IOException
- {
- checkValues(dg, dataGroupNumber, dataGroupHashValue);
-
- dg = DataGroupHash.getInstance(dg);
-
- checkValues(dg, dataGroupNumber, dataGroupHashValue);
-
- ASN1InputStream aIn = new ASN1InputStream(dg.toASN1Object().getEncoded());
-
- ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
-
- dg = DataGroupHash.getInstance(seq);
-
- checkValues(dg, dataGroupNumber, dataGroupHashValue);
- }
-
- private void checkValues(
- DataGroupHash dg,
- int dataGroupNumber,
- ASN1OctetString dataGroupHashValue)
- {
- if (dg.getDataGroupNumber() != dataGroupNumber)
- {
- fail("group number don't match.");
- }
-
- if (!dg.getDataGroupHashValue().equals(dataGroupHashValue))
- {
- fail("hash value don't match.");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new DataGroupHashUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/DeclarationOfMajorityUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/DeclarationOfMajorityUnitTest.java
deleted file mode 100644
index cd42340c..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/DeclarationOfMajorityUnitTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.isismtt.x509.DeclarationOfMajority;
-
-public class DeclarationOfMajorityUnitTest
- extends ASN1UnitTest
-{
- public String getName()
- {
- return "DeclarationOfMajority";
- }
-
- public void performTest()
- throws Exception
- {
- ASN1GeneralizedTime dateOfBirth = new ASN1GeneralizedTime("20070315173729Z");
- DeclarationOfMajority decl = new DeclarationOfMajority(dateOfBirth);
-
- checkConstruction(decl, DeclarationOfMajority.dateOfBirth, dateOfBirth, -1);
-
- decl = new DeclarationOfMajority(6);
-
- checkConstruction(decl, DeclarationOfMajority.notYoungerThan, null, 6);
-
- decl = DeclarationOfMajority.getInstance(null);
-
- if (decl != null)
- {
- fail("null getInstance() failed.");
- }
-
- try
- {
- DeclarationOfMajority.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- DeclarationOfMajority decl,
- int type,
- ASN1GeneralizedTime dateOfBirth,
- int notYoungerThan)
- throws IOException
- {
- checkValues(decl, type, dateOfBirth, notYoungerThan);
-
- decl = DeclarationOfMajority.getInstance(decl);
-
- checkValues(decl, type, dateOfBirth, notYoungerThan);
-
- ASN1InputStream aIn = new ASN1InputStream(decl.toASN1Object().getEncoded());
-
- DERTaggedObject info = (DERTaggedObject)aIn.readObject();
-
- decl = DeclarationOfMajority.getInstance(info);
-
- checkValues(decl, type, dateOfBirth, notYoungerThan);
- }
-
- private void checkValues(
- DeclarationOfMajority decl,
- int type,
- ASN1GeneralizedTime dateOfBirth,
- int notYoungerThan)
- {
- checkMandatoryField("type", type, decl.getType());
- checkOptionalField("dateOfBirth", dateOfBirth, decl.getDateOfBirth());
- if (notYoungerThan != -1 && notYoungerThan != decl.notYoungerThan())
- {
- fail("notYoungerThan mismatch");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new DeclarationOfMajorityUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/ESSCertIDv2UnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/ESSCertIDv2UnitTest.java
deleted file mode 100644
index e8978cad..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/ESSCertIDv2UnitTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ess.ESSCertIDv2;
-import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-public class ESSCertIDv2UnitTest
- extends ASN1UnitTest
-{
- public String getName()
- {
- return "ESSCertIDv2";
- }
-
- public void performTest()
- throws Exception
- {
- // check getInstance on default algorithm.
- byte[] digest = new byte [256];
- ESSCertIDv2 essCertIdv2 = new ESSCertIDv2(new AlgorithmIdentifier(
- NISTObjectIdentifiers.id_sha256), digest);
- ASN1Primitive asn1Object = essCertIdv2.toASN1Primitive();
-
- ESSCertIDv2.getInstance(asn1Object);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new ESSCertIDv2UnitTest());
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/EncryptedPrivateKeyInfoTest.java b/core/src/test/java/org/bouncycastle/asn1/test/EncryptedPrivateKeyInfoTest.java
deleted file mode 100644
index f4732cf2..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/EncryptedPrivateKeyInfoTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.DEROutputStream;
-import org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo;
-import org.bouncycastle.asn1.util.ASN1Dump;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * Test the reading and writing of EncryptedPrivateKeyInfo objects using
- * the test vectors provided at
- * <a href=http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html>
- * RSA's PKCS5 Page</a>.
- * <br>
- * The vectors are Base 64 encoded and encrypted using the password "password"
- * (without quotes). They should all yield the same PrivateKeyInfo object.
- */
-public class EncryptedPrivateKeyInfoTest
- extends SimpleTest
-{
- static byte[] sample1 = Base64.decode(
- "MIIBozA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQIfWBDXwLp4K4CAggA"
- + "MBEGBSsOAwIHBAiaCF/AvOgQ6QSCAWDWX4BdAzCRNSQSANSuNsT5X8mWYO27mr3Y"
- + "9c9LoBVXGNmYWKA77MI4967f7SmjNcgXj3xNE/jmnVz6hhsjS8E5VPT3kfyVkpdZ"
- + "0lr5e9Yk2m3JWpPU7++v5zBkZmC4V/MwV/XuIs6U+vykgzMgpxQg0oZKS9zgmiZo"
- + "f/4dOCL0UtCDnyOSvqT7mCVIcMDIEKu8QbVlgZYBop08l60EuEU3gARUo8WsYQmO"
- + "Dz/ldx0Z+znIT0SXVuOwc+RVItC5T/Qx+aijmmpt+9l14nmaGBrEkmuhmtdvU/4v"
- + "aptewGRgmjOfD6cqK+zs0O5NrrJ3P/6ZSxXj91CQgrThGfOv72bUncXEMNtc8pks"
- + "2jpHFjGMdKufnadAD7XuMgzkkaklEXZ4f5tU6heIIwr51g0GBEGF96gYPFnjnSQM"
- + "75JE02Clo+DfcfXpcybPTwwFg2jd6JTTOfkdf6OdSlA/1XNK43FA");
-
- static byte[] sample2 = Base64.decode(
- "MIIBpjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIeFeOWl1jywYCAggA"
- + "MBQGCCqGSIb3DQMHBAjUJ5eGBhQGtQSCAWBrHrRgqO8UUMLcWzZEtpk1l3mjxiF/"
- + "koCMkHsFwowgyWhEbgIkTgbSViK54LVK8PskekcGNLph+rB6bGZ7pPbL5pbXASJ8"
- + "+MkQcG3FZdlS4Ek9tTJDApj3O1UubZGFG4uvTlJJFbF1BOJ3MkY3XQ9Gl1qwv7j5"
- + "6e103Da7Cq9+oIDKmznza78XXQYrUsPo8mJGjUxPskEYlzwvHjKubRnYm/K6RKhi"
- + "5f4zX4BQ/Dt3H812ZjRXrsjAJP0KrD/jyD/jCT7zNBVPH1izBds+RwizyQAHwfNJ"
- + "BFR78TH4cgzB619X47FDVOnT0LqQNVd0O3cSwnPrXE9XR3tPayE+iOB15llFSmi8"
- + "z0ByOXldEpkezCn92Umk++suzIVj1qfsK+bv2phZWJPbLEIWPDRHUbYf76q5ArAr"
- + "u4xtxT/hoK3krEs/IN3d70qjlUJ36SEw1UaZ82PWhakQbdtu39ZraMJB");
-
- static byte[] sample3 = Base64.decode(
- "MIIBrjBIBgkqhkiG9w0BBQ0wOzAeBgkqhkiG9w0BBQwwEQQIrHyQPBZqWLUCAggA"
- + "AgEQMBkGCCqGSIb3DQMCMA0CAToECEhbh7YZKiPSBIIBYCT1zp6o5jpFlIkgwPop"
- + "7bW1+8ACr4exqzkeb3WflQ8cWJ4cURxzVdvxUnXeW1VJdaQZtjS/QHs5GhPTG/0f"
- + "wtvnaPfwrIJ3FeGaZfcg2CrYhalOFmEb4xrE4KyoEQmUN8tb/Cg94uzd16BOPw21"
- + "RDnE8bnPdIGY7TyL95kbkqH23mK53pi7h+xWIgduW+atIqDyyt55f7WMZcvDvlj6"
- + "VpN/V0h+qxBHL274WA4dj6GYgeyUFpi60HdGCK7By2TBy8h1ZvKGjmB9h8jZvkx1"
- + "MkbRumXxyFsowTZawyYvO8Um6lbfEDP9zIEUq0IV8RqH2MRyblsPNSikyYhxX/cz"
- + "tdDxRKhilySbSBg5Kr8OfcwKp9bpinN96nmG4xr3Tch1bnVvqJzOQ5+Vva2WwVvH"
- + "2JkWvYm5WaANg4Q6bRxu9vz7DuhbJjQdZbxFezIAgrJdSe92B00jO/0Kny1WjiVO"
- + "6DA=");
-
- public String getName()
- {
- return "EncryptedPrivateKeyInfoTest";
- }
-
- private void test(
- int id,
- byte[] sample)
- {
- ByteArrayInputStream bIn = new ByteArrayInputStream(sample);
- ASN1InputStream aIn = new ASN1InputStream(bIn);
- EncryptedPrivateKeyInfo info = null;
-
- try
- {
- info = EncryptedPrivateKeyInfo.getInstance(aIn.readObject());
- }
- catch (Exception e)
- {
- fail("test " + id + " failed construction - exception " + e.toString(), e);
- }
-
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- DEROutputStream dOut = new DEROutputStream(bOut);
-
- try
- {
- dOut.writeObject(info);
- }
- catch (Exception e)
- {
- fail("test " + id + " failed writing - exception " + e.toString(), e);
- }
-
- byte[] bytes = bOut.toByteArray();
-
- if (bytes.length != sample.length)
- {
- try
- {
- bIn = new ByteArrayInputStream(bytes);
- aIn = new ASN1InputStream(bIn);
-
- ASN1Primitive obj = aIn.readObject();
-
- fail("test " + id + " length mismatch - expected " + sample.length + System.getProperty("line.separator") + ASN1Dump.dumpAsString(info) + " got " + bytes.length + System.getProperty("line.separator") + ASN1Dump.dumpAsString(obj));
- }
- catch (Exception e)
- {
- fail("test " + id + " length mismatch - exception " + e.toString());
- }
- }
-
- for (int i = 0; i != bytes.length; i++)
- {
- if (bytes[i] != sample[i])
- {
- fail("test " + id + " data mismatch");
- }
- }
- }
-
- public void performTest()
- {
- test(0, sample1);
- test(1, sample2);
- test(2, sample3);
- }
-
-
- public static void main(
- String[] args)
- {
- runTest(new EncryptedPrivateKeyInfoTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/EnumeratedTest.java b/core/src/test/java/org/bouncycastle/asn1/test/EnumeratedTest.java
deleted file mode 100644
index c1c3b3bf..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/EnumeratedTest.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import junit.framework.TestCase;
-
-import org.bouncycastle.asn1.ASN1Boolean;
-import org.bouncycastle.asn1.ASN1Enumerated;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.util.encoders.Hex;
-
-/**
- * Tests used to verify correct decoding of the ENUMERATED type.
- */
-public class EnumeratedTest
- extends TestCase
-{
- /**
- * Test vector used to test decoding of multiple items. This sample uses an ENUMERATED and a BOOLEAN.
- */
- private static final byte[] MultipleSingleByteItems = Hex.decode("30060a01010101ff");
-
- /**
- * Test vector used to test decoding of multiple items. This sample uses two ENUMERATEDs.
- */
- private static final byte[] MultipleDoubleByteItems = Hex.decode("30080a0201010a020202");
-
- /**
- * Test vector used to test decoding of multiple items. This sample uses an ENUMERATED and an OBJECT IDENTIFIER.
- */
- private static final byte[] MultipleTripleByteItems = Hex.decode("300a0a0301010106032b0601");
-
- /**
- * Makes sure multiple identically sized values are parsed correctly.
- */
- public void testReadingMultipleSingleByteItems()
- throws IOException
- {
- ASN1Primitive obj = ASN1Primitive.fromByteArray(MultipleSingleByteItems);
-
- assertTrue("Null ASN.1 SEQUENCE", obj instanceof ASN1Sequence);
-
- ASN1Sequence sequence = (ASN1Sequence)obj;
-
- assertEquals("2 items expected", 2, sequence.size());
-
- ASN1Enumerated enumerated = ASN1Enumerated.getInstance(sequence.getObjectAt(0));
-
- assertNotNull("ENUMERATED expected", enumerated);
-
- assertEquals("Unexpected ENUMERATED value", 1, enumerated.getValue().intValue());
-
- ASN1Boolean b = ASN1Boolean.getInstance(sequence.getObjectAt(1));
-
- assertNotNull("BOOLEAN expected", b);
-
- assertTrue("Unexpected BOOLEAN value", b.isTrue());
- }
-
- /**
- * Makes sure multiple identically sized values are parsed correctly.
- */
- public void testReadingMultipleDoubleByteItems()
- throws IOException
- {
- ASN1Primitive obj = ASN1Primitive.fromByteArray(MultipleDoubleByteItems);
-
- assertTrue("Null ASN.1 SEQUENCE", obj instanceof ASN1Sequence);
-
- ASN1Sequence sequence = (ASN1Sequence)obj;
-
- assertEquals("2 items expected", 2, sequence.size());
-
- ASN1Enumerated enumerated1 = ASN1Enumerated.getInstance(sequence.getObjectAt(0));
-
- assertNotNull("ENUMERATED expected", enumerated1);
-
- assertEquals("Unexpected ENUMERATED value", 257, enumerated1.getValue().intValue());
-
- ASN1Enumerated enumerated2 = ASN1Enumerated.getInstance(sequence.getObjectAt(1));
-
- assertNotNull("ENUMERATED expected", enumerated2);
-
- assertEquals("Unexpected ENUMERATED value", 514, enumerated2.getValue().intValue());
- }
-
- /**
- * Makes sure multiple identically sized values are parsed correctly.
- */
- public void testReadingMultipleTripleByteItems()
- throws IOException
- {
- ASN1Primitive obj = ASN1Primitive.fromByteArray(MultipleTripleByteItems);
-
- assertTrue("Null ASN.1 SEQUENCE", obj instanceof ASN1Sequence);
-
- ASN1Sequence sequence = (ASN1Sequence)obj;
-
- assertEquals("2 items expected", 2, sequence.size());
-
- ASN1Enumerated enumerated = ASN1Enumerated.getInstance(sequence.getObjectAt(0));
-
- assertNotNull("ENUMERATED expected", enumerated);
-
- assertEquals("Unexpected ENUMERATED value", 65793, enumerated.getValue().intValue());
-
- ASN1ObjectIdentifier objectId = ASN1ObjectIdentifier.getInstance(sequence.getObjectAt(1));
-
- assertNotNull("OBJECT IDENTIFIER expected", objectId);
-
- assertEquals("Unexpected OBJECT IDENTIFIER value", "1.3.6.1", objectId.getId());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/EqualsAndHashCodeTest.java b/core/src/test/java/org/bouncycastle/asn1/test/EqualsAndHashCodeTest.java
deleted file mode 100644
index 3da4e6ad..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/EqualsAndHashCodeTest.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.util.Date;
-
-import org.bouncycastle.asn1.ASN1Boolean;
-import org.bouncycastle.asn1.ASN1Enumerated;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OutputStream;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.BERConstructedOctetString;
-import org.bouncycastle.asn1.BERSequence;
-import org.bouncycastle.asn1.BERSet;
-import org.bouncycastle.asn1.BERTaggedObject;
-import org.bouncycastle.asn1.DERApplicationSpecific;
-import org.bouncycastle.asn1.DERBMPString;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERGeneralString;
-import org.bouncycastle.asn1.DERGeneralizedTime;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.DERNumericString;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERPrintableString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERSet;
-import org.bouncycastle.asn1.DERT61String;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.DERUTCTime;
-import org.bouncycastle.asn1.DERUTF8String;
-import org.bouncycastle.asn1.DERUniversalString;
-import org.bouncycastle.asn1.DERVisibleString;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-public class EqualsAndHashCodeTest
- implements Test
-{
- public TestResult perform()
- {
- byte[] data = { 0, 1, 0, 1, 0, 0, 1 };
-
- ASN1Primitive values[] = {
- new BERConstructedOctetString(data),
- new BERSequence(new DERPrintableString("hello world")),
- new BERSet(new DERPrintableString("hello world")),
- new BERTaggedObject(0, new DERPrintableString("hello world")),
- new DERApplicationSpecific(0, data),
- new DERBitString(data),
- new DERBMPString("hello world"),
- new ASN1Boolean(true),
- new ASN1Boolean(false),
- new ASN1Enumerated(100),
- new DERGeneralizedTime("20070315173729Z"),
- new DERGeneralString("hello world"),
- new DERIA5String("hello"),
- new ASN1Integer(1000),
- new DERNull(),
- new DERNumericString("123456"),
- new ASN1ObjectIdentifier("1.1.1.10000.1"),
- new DEROctetString(data),
- new DERPrintableString("hello world"),
- new DERSequence(new DERPrintableString("hello world")),
- new DERSet(new DERPrintableString("hello world")),
- new DERT61String("hello world"),
- new DERTaggedObject(0, new DERPrintableString("hello world")),
- new DERUniversalString(data),
- new DERUTCTime(new Date()),
- new DERUTF8String("hello world"),
- new DERVisibleString("hello world")
- };
-
- try
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- ASN1OutputStream aOut = new ASN1OutputStream(bOut);
-
- for (int i = 0; i != values.length; i++)
- {
- aOut.writeObject(values[i]);
- }
-
- ASN1Primitive[] readValues = new ASN1Primitive[values.length];
-
- ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
- ASN1InputStream aIn = new ASN1InputStream(bIn);
-
- for (int i = 0; i != values.length; i++)
- {
- ASN1Primitive o = aIn.readObject();
- if (!o.equals(values[i]))
- {
- return new SimpleTestResult(false, getName() + ": Failed equality test for " + o.getClass());
- }
-
- if (o.hashCode() != values[i].hashCode())
- {
- return new SimpleTestResult(false, getName() + ": Failed hashCode test for " + o.getClass());
- }
- }
- }
- catch (Exception e)
- {
- return new SimpleTestResult(false, getName() + ": Failed - exception " + e.toString(), e);
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
-
- public String getName()
- {
- return "EqualsAndHashCode";
- }
-
- public static void main(
- String[] args)
- {
- EqualsAndHashCodeTest test = new EqualsAndHashCodeTest();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/GeneralNameTest.java b/core/src/test/java/org/bouncycastle/asn1/test/GeneralNameTest.java
deleted file mode 100644
index f88a83cd..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/GeneralNameTest.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import org.bouncycastle.asn1.x509.GeneralName;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class GeneralNameTest
- extends SimpleTest
-{
- private static final byte[] ipv4 = Hex.decode("87040a090800");
- private static final byte[] ipv4WithMask1 = Hex.decode("87080a090800ffffff00");
- private static final byte[] ipv4WithMask2 = Hex.decode("87080a090800ffff8000");
- private static final byte[] ipv4WithMask3 = Hex.decode("87080a090800ffffc000");
-
- private static final byte[] ipv6a = Hex.decode("871020010db885a308d313198a2e03707334");
- private static final byte[] ipv6b = Hex.decode("871020010db885a3000013198a2e03707334");
- private static final byte[] ipv6c = Hex.decode("871000000000000000000000000000000001");
- private static final byte[] ipv6d = Hex.decode("871020010db885a3000000008a2e03707334");
- private static final byte[] ipv6e = Hex.decode("871020010db885a3000000008a2e0a090800");
- private static final byte[] ipv6f = Hex.decode("872020010db885a3000000008a2e0a090800ffffffffffff00000000000000000000");
- private static final byte[] ipv6g = Hex.decode("872020010db885a3000000008a2e0a090800ffffffffffffffffffffffffffffffff");
- private static final byte[] ipv6h = Hex.decode("872020010db885a300000000000000000000ffffffffffff00000000000000000000");
- private static final byte[] ipv6i = Hex.decode("872020010db885a300000000000000000000fffffffffffe00000000000000000000");
- private static final byte[] ipv6j = Hex.decode("872020010db885a300000000000000000000ffffffffffff80000000000000000000");
-
- public String getName()
- {
- return "GeneralName";
- }
-
- public void performTest()
- throws Exception
- {
- GeneralName nm = new GeneralName(GeneralName.iPAddress, "10.9.8.0");
- if (!Arrays.areEqual(nm.getEncoded(), ipv4))
- {
- fail("ipv4 encoding failed");
- }
-
- nm = new GeneralName(GeneralName.iPAddress, "10.9.8.0/255.255.255.0");
- if (!Arrays.areEqual(nm.getEncoded(), ipv4WithMask1))
- {
- fail("ipv4 with netmask 1 encoding failed");
- }
-
- nm = new GeneralName(GeneralName.iPAddress, "10.9.8.0/24");
- if (!Arrays.areEqual(nm.getEncoded(), ipv4WithMask1))
- {
- fail("ipv4 with netmask 2 encoding failed");
- }
-
- nm = new GeneralName(GeneralName.iPAddress, "10.9.8.0/255.255.128.0");
- if (!Arrays.areEqual(nm.getEncoded(), ipv4WithMask2))
- {
- fail("ipv4 with netmask 3a encoding failed");
- }
-
- nm = new GeneralName(GeneralName.iPAddress, "10.9.8.0/17");
- if (!Arrays.areEqual(nm.getEncoded(), ipv4WithMask2))
- {
- fail("ipv4 with netmask 3b encoding failed");
- }
-
- nm = new GeneralName(GeneralName.iPAddress, "10.9.8.0/255.255.192.0");
- if (!Arrays.areEqual(nm.getEncoded(), ipv4WithMask3))
- {
- fail("ipv4 with netmask 3a encoding failed");
- }
-
- nm = new GeneralName(GeneralName.iPAddress, "10.9.8.0/18");
- if (!Arrays.areEqual(nm.getEncoded(), ipv4WithMask3))
- {
- fail("ipv4 with netmask 3b encoding failed");
- }
-
- nm = new GeneralName(GeneralName.iPAddress, "2001:0db8:85a3:08d3:1319:8a2e:0370:7334");
- if (!Arrays.areEqual(nm.getEncoded(), ipv6a))
- {
- fail("ipv6 with netmask encoding failed");
- }
-
- nm = new GeneralName(GeneralName.iPAddress, "2001:0db8:85a3::1319:8a2e:0370:7334");
- if (!Arrays.areEqual(nm.getEncoded(), ipv6b))
- {
- fail("ipv6b encoding failed");
- }
-
- nm = new GeneralName(GeneralName.iPAddress, "::1");
- if (!Arrays.areEqual(nm.getEncoded(), ipv6c))
- {
- fail("ipv6c failed");
- }
-
- nm = new GeneralName(GeneralName.iPAddress, "2001:0db8:85a3::8a2e:0370:7334");
- if (!Arrays.areEqual(nm.getEncoded(), ipv6d))
- {
- fail("ipv6d failed");
- }
-
- nm = new GeneralName(GeneralName.iPAddress, "2001:0db8:85a3::8a2e:10.9.8.0");
- if (!Arrays.areEqual(nm.getEncoded(), ipv6e))
- {
- fail("ipv6e failed");
- }
-
- nm = new GeneralName(GeneralName.iPAddress, "2001:0db8:85a3::8a2e:10.9.8.0/ffff:ffff:ffff::0000");
- if (!Arrays.areEqual(nm.getEncoded(), ipv6f))
- {
- fail("ipv6f failed");
- }
-
- nm = new GeneralName(GeneralName.iPAddress, "2001:0db8:85a3::8a2e:10.9.8.0/128");
- if (!Arrays.areEqual(nm.getEncoded(), ipv6g))
- {
- fail("ipv6g failed");
- }
-
- nm = new GeneralName(GeneralName.iPAddress, "2001:0db8:85a3::/48");
- if (!Arrays.areEqual(nm.getEncoded(), ipv6h))
- {
- fail("ipv6h failed");
- }
-
- nm = new GeneralName(GeneralName.iPAddress, "2001:0db8:85a3::/47");
- if (!Arrays.areEqual(nm.getEncoded(), ipv6i))
- {
- fail("ipv6i failed");
- }
-
- nm = new GeneralName(GeneralName.iPAddress, "2001:0db8:85a3::/49");
- if (!Arrays.areEqual(nm.getEncoded(), ipv6j))
- {
- fail("ipv6j failed");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new GeneralNameTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/GeneralizedTimeTest.java b/core/src/test/java/org/bouncycastle/asn1/test/GeneralizedTimeTest.java
deleted file mode 100644
index 3a86370c..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/GeneralizedTimeTest.java
+++ /dev/null
@@ -1,201 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.SimpleTimeZone;
-import java.util.TimeZone;
-
-import org.bouncycastle.asn1.DERGeneralizedTime;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * X.690 test example
- */
-public class GeneralizedTimeTest
- extends SimpleTest
-{
- String[] input =
- {
- "20020122122220",
- "20020122122220Z",
- "20020122122220-1000",
- "20020122122220+00",
- "20020122122220.1",
- "20020122122220.1Z",
- "20020122122220.1-1000",
- "20020122122220.1+00",
- "20020122122220.01",
- "20020122122220.01Z",
- "20020122122220.01-1000",
- "20020122122220.01+00",
- "20020122122220.001",
- "20020122122220.001Z",
- "20020122122220.001-1000",
- "20020122122220.001+00",
- "20020122122220.0001",
- "20020122122220.0001Z",
- "20020122122220.0001-1000",
- "20020122122220.0001+00",
- "20020122122220.0001+1000"
- };
-
- String[] output = {
- "20020122122220",
- "20020122122220GMT+00:00",
- "20020122122220GMT-10:00",
- "20020122122220GMT+00:00",
- "20020122122220.1",
- "20020122122220.1GMT+00:00",
- "20020122122220.1GMT-10:00",
- "20020122122220.1GMT+00:00",
- "20020122122220.01",
- "20020122122220.01GMT+00:00",
- "20020122122220.01GMT-10:00",
- "20020122122220.01GMT+00:00",
- "20020122122220.001",
- "20020122122220.001GMT+00:00",
- "20020122122220.001GMT-10:00",
- "20020122122220.001GMT+00:00",
- "20020122122220.0001",
- "20020122122220.0001GMT+00:00",
- "20020122122220.0001GMT-10:00",
- "20020122122220.0001GMT+00:00",
- "20020122122220.0001GMT+10:00" };
-
- String[] zOutput = {
- "20020122122220Z",
- "20020122122220Z",
- "20020122222220Z",
- "20020122122220Z",
- "20020122122220Z",
- "20020122122220Z",
- "20020122222220Z",
- "20020122122220Z",
- "20020122122220Z",
- "20020122122220Z",
- "20020122222220Z",
- "20020122122220Z",
- "20020122122220Z",
- "20020122122220Z",
- "20020122222220Z",
- "20020122122220Z",
- "20020122122220Z",
- "20020122122220Z",
- "20020122222220Z",
- "20020122122220Z",
- "20020122022220Z"
- };
-
- String[] mzOutput = {
- "20020122122220.000Z",
- "20020122122220.000Z",
- "20020122222220.000Z",
- "20020122122220.000Z",
- "20020122122220.100Z",
- "20020122122220.100Z",
- "20020122222220.100Z",
- "20020122122220.100Z",
- "20020122122220.010Z",
- "20020122122220.010Z",
- "20020122222220.010Z",
- "20020122122220.010Z",
- "20020122122220.001Z",
- "20020122122220.001Z",
- "20020122222220.001Z",
- "20020122122220.001Z",
- "20020122122220.000Z",
- "20020122122220.000Z",
- "20020122222220.000Z",
- "20020122122220.000Z",
- "20020122022220.000Z"
- };
-
- public String getName()
- {
- return "GeneralizedTime";
- }
-
- public void performTest()
- throws Exception
- {
- SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
-
- dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
-
- for (int i = 0; i != input.length; i++)
- {
- DERGeneralizedTime t = new DERGeneralizedTime(input[i]);
-
- if (output[i].indexOf('G') > 0) // don't check local time the same way
- {
- if (!t.getTime().equals(output[i]))
- {
- fail("failed conversion test");
- }
- if (!dateF.format(t.getDate()).equals(zOutput[i]))
- {
- fail("failed date conversion test");
- }
- }
- else
- {
- String offset = calculateGMTOffset(t.getDate());
- if (!t.getTime().equals(output[i] + offset))
- {
- fail("failed conversion test");
- }
- }
- }
-
- dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS'Z'");
-
- dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
-
- for (int i = 0; i != input.length; i++)
- {
- DERGeneralizedTime t = new DERGeneralizedTime(input[i]);
-
- if (!dateF.format(t.getDate()).equals(mzOutput[i]))
- {
- fail("failed long date conversion test");
- }
- }
- }
-
- private String calculateGMTOffset(Date date)
- {
- String sign = "+";
- TimeZone timeZone = TimeZone.getDefault();
- int offset = timeZone.getRawOffset();
- if (offset < 0)
- {
- sign = "-";
- offset = -offset;
- }
- int hours = offset / (60 * 60 * 1000);
- int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000);
-
- if (timeZone.useDaylightTime() && timeZone.inDaylightTime(date))
- {
- hours += sign.equals("+") ? 1 : -1;
- }
-
- return "GMT" + sign + convert(hours) + ":" + convert(minutes);
- }
-
- private String convert(int time)
- {
- if (time < 10)
- {
- return "0" + time;
- }
-
- return Integer.toString(time);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new GeneralizedTimeTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/GenerationTest.java b/core/src/test/java/org/bouncycastle/asn1/test/GenerationTest.java
deleted file mode 100644
index aa5444fb..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/GenerationTest.java
+++ /dev/null
@@ -1,441 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.text.ParseException;
-import java.util.Date;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1OutputStream;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.oiw.ElGamalParameter;
-import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
-import org.bouncycastle.asn1.x509.CRLReason;
-import org.bouncycastle.asn1.x509.Extension;
-import org.bouncycastle.asn1.x509.Extensions;
-import org.bouncycastle.asn1.x509.ExtensionsGenerator;
-import org.bouncycastle.asn1.x509.GeneralName;
-import org.bouncycastle.asn1.x509.GeneralNames;
-import org.bouncycastle.asn1.x509.IssuingDistributionPoint;
-import org.bouncycastle.asn1.x509.KeyUsage;
-import org.bouncycastle.asn1.x509.RSAPublicKeyStructure;
-import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.asn1.x509.TBSCertList;
-import org.bouncycastle.asn1.x509.TBSCertificate;
-import org.bouncycastle.asn1.x509.Time;
-import org.bouncycastle.asn1.x509.V1TBSCertificateGenerator;
-import org.bouncycastle.asn1.x509.V2TBSCertListGenerator;
-import org.bouncycastle.asn1.x509.V3TBSCertificateGenerator;
-import org.bouncycastle.asn1.x509.X509Extension;
-import org.bouncycastle.asn1.x509.X509Extensions;
-import org.bouncycastle.asn1.x509.X509Name;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class GenerationTest
- extends SimpleTest
-{
- private byte[] v1Cert = Base64.decode(
- "MIGtAgEBMA0GCSqGSIb3DQEBBAUAMCUxCzAJBgNVBAMMAkFVMRYwFAYDVQQKDA1Cb"
- + "3VuY3kgQ2FzdGxlMB4XDTcwMDEwMTAwMDAwMVoXDTcwMDEwMTAwMDAxMlowNjELMA"
- + "kGA1UEAwwCQVUxFjAUBgNVBAoMDUJvdW5jeSBDYXN0bGUxDzANBgNVBAsMBlRlc3Q"
- + "gMTAaMA0GCSqGSIb3DQEBAQUAAwkAMAYCAQECAQI=");
-
- private byte[] v3Cert = Base64.decode(
- "MIIBSKADAgECAgECMA0GCSqGSIb3DQEBBAUAMCUxCzAJBgNVBAMMAkFVMRYwFAYD"
- + "VQQKDA1Cb3VuY3kgQ2FzdGxlMB4XDTcwMDEwMTAwMDAwMVoXDTcwMDEwMTAwMDAw"
- + "MlowNjELMAkGA1UEAwwCQVUxFjAUBgNVBAoMDUJvdW5jeSBDYXN0bGUxDzANBgNV"
- + "BAsMBlRlc3QgMjAYMBAGBisOBwIBATAGAgEBAgECAwQAAgEDo4GVMIGSMGEGA1Ud"
- + "IwEB/wRXMFWAFDZPdpHPzKi7o8EJokkQU2uqCHRRoTqkODA2MQswCQYDVQQDDAJB"
- + "VTEWMBQGA1UECgwNQm91bmN5IENhc3RsZTEPMA0GA1UECwwGVGVzdCAyggECMCAG"
- + "A1UdDgEB/wQWBBQ2T3aRz8you6PBCaJJEFNrqgh0UTALBgNVHQ8EBAMCBBA=");
-
- private byte[] v3CertNullSubject = Base64.decode(
- "MIHGoAMCAQICAQIwDQYJKoZIhvcNAQEEBQAwJTELMAkGA1UEAwwCQVUxFjAUBgNVB"
- + "AoMDUJvdW5jeSBDYXN0bGUwHhcNNzAwMTAxMDAwMDAxWhcNNzAwMTAxMDAwMDAyWj"
- + "AAMBgwEAYGKw4HAgEBMAYCAQECAQIDBAACAQOjSjBIMEYGA1UdEQEB/wQ8MDqkODA"
- + "2MQswCQYDVQQDDAJBVTEWMBQGA1UECgwNQm91bmN5IENhc3RsZTEPMA0GA1UECwwG"
- + "VGVzdCAy");
-
- private byte[] v2CertList = Base64.decode(
- "MIIBQwIBATANBgkqhkiG9w0BAQUFADAlMQswCQYDVQQDDAJBVTEWMBQGA1UECgwN" +
- "Qm91bmN5IENhc3RsZRcNNzAwMTAxMDAwMDAwWhcNNzAwMTAxMDAwMDAyWjAiMCAC" +
- "AQEXDTcwMDEwMTAwMDAwMVowDDAKBgNVHRUEAwoBCqCBxTCBwjBhBgNVHSMBAf8E" +
- "VzBVgBQ2T3aRz8you6PBCaJJEFNrqgh0UaE6pDgwNjELMAkGA1UEAwwCQVUxFjAU" +
- "BgNVBAoMDUJvdW5jeSBDYXN0bGUxDzANBgNVBAsMBlRlc3QgMoIBAjBDBgNVHRIE" +
- "PDA6pDgwNjELMAkGA1UEAwwCQVUxFjAUBgNVBAoMDUJvdW5jeSBDYXN0bGUxDzAN" +
- "BgNVBAsMBlRlc3QgMzAKBgNVHRQEAwIBATAMBgNVHRwBAf8EAjAA");
-
- private void tbsV1CertGen()
- throws IOException
- {
- V1TBSCertificateGenerator gen = new V1TBSCertificateGenerator();
- Date startDate = new Date(1000);
- Date endDate = new Date(12000);
-
- gen.setSerialNumber(new ASN1Integer(1));
-
- gen.setStartDate(new Time(startDate));
- gen.setEndDate(new Time(endDate));
-
- gen.setIssuer(new X500Name("CN=AU,O=Bouncy Castle"));
- gen.setSubject(new X500Name("CN=AU,O=Bouncy Castle,OU=Test 1"));
-
- gen.setSignature(new AlgorithmIdentifier(PKCSObjectIdentifiers.md5WithRSAEncryption, DERNull.INSTANCE));
-
- SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE),
- new RSAPublicKeyStructure(BigInteger.valueOf(1), BigInteger.valueOf(2)));
-
- gen.setSubjectPublicKeyInfo(info);
-
- TBSCertificate tbs = gen.generateTBSCertificate();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- ASN1OutputStream aOut = new ASN1OutputStream(bOut);
-
- aOut.writeObject(tbs);
-
- if (!Arrays.areEqual(bOut.toByteArray(), v1Cert))
- {
- fail("failed v1 cert generation");
- }
-
- //
- // read back test
- //
- ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(v1Cert));
- ASN1Primitive o = aIn.readObject();
-
- bOut = new ByteArrayOutputStream();
- aOut = new ASN1OutputStream(bOut);
-
- aOut.writeObject(o);
-
- if (!Arrays.areEqual(bOut.toByteArray(), v1Cert))
- {
- fail("failed v1 cert read back test");
- }
- }
-
- private AuthorityKeyIdentifier createAuthorityKeyId(
- SubjectPublicKeyInfo info,
- X500Name name,
- int sNumber)
- {
- GeneralName genName = new GeneralName(name);
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(genName);
-
- return new AuthorityKeyIdentifier(
- info, GeneralNames.getInstance(new DERSequence(v)), BigInteger.valueOf(sNumber));
- }
-
- private void tbsV3CertGen()
- throws IOException
- {
- V3TBSCertificateGenerator gen = new V3TBSCertificateGenerator();
- Date startDate = new Date(1000);
- Date endDate = new Date(2000);
-
- gen.setSerialNumber(new ASN1Integer(2));
-
- gen.setStartDate(new Time(startDate));
- gen.setEndDate(new Time(endDate));
-
- gen.setIssuer(new X500Name("CN=AU,O=Bouncy Castle"));
- gen.setSubject(new X500Name("CN=AU,O=Bouncy Castle,OU=Test 2"));
-
- gen.setSignature(new AlgorithmIdentifier(PKCSObjectIdentifiers.md5WithRSAEncryption, DERNull.INSTANCE));
-
- SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(OIWObjectIdentifiers.elGamalAlgorithm, new ElGamalParameter(BigInteger.valueOf(1), BigInteger.valueOf(2))), new ASN1Integer(3));
-
- gen.setSubjectPublicKeyInfo(info);
-
- //
- // add extensions
- //
- Vector order = new Vector();
- Hashtable extensions = new Hashtable();
-
- order.addElement(X509Extension.authorityKeyIdentifier);
- order.addElement(X509Extension.subjectKeyIdentifier);
- order.addElement(X509Extension.keyUsage);
-
- extensions.put(X509Extension.authorityKeyIdentifier, new X509Extension(true, new DEROctetString(createAuthorityKeyId(info, new X500Name("CN=AU,O=Bouncy Castle,OU=Test 2"), 2))));
- extensions.put(X509Extension.subjectKeyIdentifier, new X509Extension(true, new DEROctetString(new SubjectKeyIdentifier(getDigest(info)))));
- extensions.put(X509Extension.keyUsage, new X509Extension(false, new DEROctetString(new KeyUsage(KeyUsage.dataEncipherment))));
-
- X509Extensions ex = new X509Extensions(order, extensions);
-
- gen.setExtensions(ex);
-
- TBSCertificate tbs = gen.generateTBSCertificate();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- ASN1OutputStream aOut = new ASN1OutputStream(bOut);
-
- aOut.writeObject(tbs);
-
- if (!Arrays.areEqual(bOut.toByteArray(), v3Cert))
- {
- fail("failed v3 cert generation");
- }
-
- //
- // read back test
- //
- ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(v3Cert));
- ASN1Primitive o = aIn.readObject();
-
- bOut = new ByteArrayOutputStream();
- aOut = new ASN1OutputStream(bOut);
-
- aOut.writeObject(o);
-
- if (!Arrays.areEqual(bOut.toByteArray(), v3Cert))
- {
- fail("failed v3 cert read back test");
- }
- }
-
- private void tbsV3CertGenWithNullSubject()
- throws IOException
- {
- V3TBSCertificateGenerator gen = new V3TBSCertificateGenerator();
- Date startDate = new Date(1000);
- Date endDate = new Date(2000);
-
- gen.setSerialNumber(new ASN1Integer(2));
-
- gen.setStartDate(new Time(startDate));
- gen.setEndDate(new Time(endDate));
-
- gen.setIssuer(new X500Name("CN=AU,O=Bouncy Castle"));
-
- gen.setSignature(new AlgorithmIdentifier(PKCSObjectIdentifiers.md5WithRSAEncryption, DERNull.INSTANCE));
-
- SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(OIWObjectIdentifiers.elGamalAlgorithm, new ElGamalParameter(BigInteger.valueOf(1), BigInteger.valueOf(2))), new ASN1Integer(3));
-
- gen.setSubjectPublicKeyInfo(info);
-
- try
- {
- gen.generateTBSCertificate();
- fail("null subject not caught!");
- }
- catch (IllegalStateException e)
- {
- if (!e.getMessage().equals("not all mandatory fields set in V3 TBScertificate generator"))
- {
- fail("unexpected exception", e);
- }
- }
-
- //
- // add extensions
- //
- Vector order = new Vector();
- Hashtable extensions = new Hashtable();
-
- order.addElement(X509Extension.subjectAlternativeName);
-
- extensions.put(X509Extension.subjectAlternativeName, new X509Extension(true, new DEROctetString(new GeneralNames(new GeneralName(new X509Name("CN=AU,O=Bouncy Castle,OU=Test 2"))))));
-
- X509Extensions ex = new X509Extensions(order, extensions);
-
- gen.setExtensions(ex);
-
- TBSCertificate tbs = gen.generateTBSCertificate();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- ASN1OutputStream aOut = new ASN1OutputStream(bOut);
-
- aOut.writeObject(tbs);
-
- if (!Arrays.areEqual(bOut.toByteArray(), v3CertNullSubject))
- {
- fail("failed v3 null sub cert generation");
- }
-
- //
- // read back test
- //
- ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(v3CertNullSubject));
- ASN1Primitive o = aIn.readObject();
-
- bOut = new ByteArrayOutputStream();
- aOut = new ASN1OutputStream(bOut);
-
- aOut.writeObject(o);
-
- if (!Arrays.areEqual(bOut.toByteArray(), v3CertNullSubject))
- {
- fail("failed v3 null sub cert read back test");
- }
- }
-
- private void tbsV2CertListGen()
- throws IOException
- {
- V2TBSCertListGenerator gen = new V2TBSCertListGenerator();
-
- gen.setIssuer(new X500Name("CN=AU,O=Bouncy Castle"));
-
- gen.addCRLEntry(new ASN1Integer(1), new Time(new Date(1000)), CRLReason.aACompromise);
-
- gen.setNextUpdate(new Time(new Date(2000)));
-
- gen.setThisUpdate(new Time(new Date(500)));
-
- gen.setSignature(new AlgorithmIdentifier(PKCSObjectIdentifiers.sha1WithRSAEncryption, DERNull.INSTANCE));
-
- //
- // extensions
- //
- SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(OIWObjectIdentifiers.elGamalAlgorithm, new ElGamalParameter(BigInteger.valueOf(1), BigInteger.valueOf(2))), new ASN1Integer(3));
-
- ExtensionsGenerator extGen = new ExtensionsGenerator();
-
- extGen.addExtension(Extension.authorityKeyIdentifier, true, createAuthorityKeyId(info, new X500Name("CN=AU,O=Bouncy Castle,OU=Test 2"), 2));
- extGen.addExtension(Extension.issuerAlternativeName, false, new GeneralNames(new GeneralName(new X500Name("CN=AU,O=Bouncy Castle,OU=Test 3"))));
- extGen.addExtension(Extension.cRLNumber, false, new ASN1Integer(1));
- extGen.addExtension(Extension.issuingDistributionPoint, true, IssuingDistributionPoint.getInstance(new DERSequence()));
-
- Extensions ex = extGen.generate();
-
- gen.setExtensions(ex);
-
- TBSCertList tbs = gen.generateTBSCertList();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- ASN1OutputStream aOut = new ASN1OutputStream(bOut);
-
- aOut.writeObject(tbs);
-
- if (!Arrays.areEqual(bOut.toByteArray(), v2CertList))
- {
- System.out.println(new String(Base64.encode(bOut.toByteArray())));
- fail("failed v2 cert list generation");
- }
-
- //
- // read back test
- //
- ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(v2CertList));
- ASN1Primitive o = aIn.readObject();
-
- bOut = new ByteArrayOutputStream();
- aOut = new ASN1OutputStream(bOut);
-
- aOut.writeObject(o);
-
- if (!Arrays.areEqual(bOut.toByteArray(), v2CertList))
- {
- fail("failed v2 cert list read back test");
- }
-
- //
- // check we can add a custom reason
- //
- gen.addCRLEntry(new ASN1Integer(1), new Time(new Date(1000)), CRLReason.aACompromise);
-
- //
- // check invalidity date
- gen.addCRLEntry(new ASN1Integer(2), new Time(new Date(1000)), CRLReason.affiliationChanged, new ASN1GeneralizedTime(new Date(2000)));
-
- TBSCertList crl = gen.generateTBSCertList();
-
- TBSCertList.CRLEntry[] entries = crl.getRevokedCertificates();
- for (int i = 0; i != entries.length; i++)
- {
- TBSCertList.CRLEntry entry = entries[i];
-
- if (entry.getUserCertificate().equals(new ASN1Integer(1)))
- {
- Extensions extensions = entry.getExtensions();
- Extension ext = extensions.getExtension(Extension.reasonCode);
-
- CRLReason r = CRLReason.getInstance(ext.getParsedValue());
-
- if (r.getValue().intValue() != CRLReason.aACompromise)
- {
- fail("reason code mismatch");
- }
- }
- else if (entry.getUserCertificate().equals(new ASN1Integer(2)))
- {
- Extensions extensions = entry.getExtensions();
- Extension ext = extensions.getExtension(Extension.reasonCode);
-
- CRLReason r = CRLReason.getInstance(ext.getParsedValue());
-
- if (r.getValue().intValue() != CRLReason.affiliationChanged)
- {
- fail("reason code mismatch");
- }
-
- ext = extensions.getExtension(Extension.invalidityDate);
-
- ASN1GeneralizedTime t = ASN1GeneralizedTime.getInstance(ext.getParsedValue());
-
- try
- {
- if (!t.getDate().equals(new Date(2000)))
- {
- fail("invalidity date mismatch");
- }
- }
- catch (ParseException e)
- {
- fail("can't parse date", e);
- }
- }
- }
- }
-
- public void performTest()
- throws Exception
- {
- tbsV1CertGen();
- tbsV3CertGen();
- tbsV3CertGenWithNullSubject();
- tbsV2CertListGen();
- }
-
- public String getName()
- {
- return "Generation";
- }
-
- private static byte[] getDigest(SubjectPublicKeyInfo spki)
- {
- Digest digest = new SHA1Digest();
- byte[] resBuf = new byte[digest.getDigestSize()];
-
- byte[] bytes = spki.getPublicKeyData().getBytes();
- digest.update(bytes, 0, bytes.length);
- digest.doFinal(resBuf, 0);
- return resBuf;
- }
-
- public static void main(
- String[] args)
- {
- runTest(new GenerationTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/GetInstanceTest.java b/core/src/test/java/org/bouncycastle/asn1/test/GetInstanceTest.java
deleted file mode 100644
index cda7c500..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/GetInstanceTest.java
+++ /dev/null
@@ -1,888 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.lang.reflect.Method;
-import java.math.BigInteger;
-import java.util.Date;
-import java.util.Vector;
-
-import junit.framework.TestCase;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Enumerated;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.ASN1UTCTime;
-import org.bouncycastle.asn1.DERBMPString;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERGeneralString;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.DERNumericString;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERPrintableString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERSet;
-import org.bouncycastle.asn1.DERT61String;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.DERUTF8String;
-import org.bouncycastle.asn1.DERUniversalString;
-import org.bouncycastle.asn1.DERVisibleString;
-import org.bouncycastle.asn1.cmp.CAKeyUpdAnnContent;
-import org.bouncycastle.asn1.cmp.CMPCertificate;
-import org.bouncycastle.asn1.cmp.CRLAnnContent;
-import org.bouncycastle.asn1.cmp.CertConfirmContent;
-import org.bouncycastle.asn1.cmp.CertOrEncCert;
-import org.bouncycastle.asn1.cmp.CertRepMessage;
-import org.bouncycastle.asn1.cmp.CertResponse;
-import org.bouncycastle.asn1.cmp.CertifiedKeyPair;
-import org.bouncycastle.asn1.cmp.Challenge;
-import org.bouncycastle.asn1.cmp.ErrorMsgContent;
-import org.bouncycastle.asn1.cmp.GenMsgContent;
-import org.bouncycastle.asn1.cmp.GenRepContent;
-import org.bouncycastle.asn1.cmp.InfoTypeAndValue;
-import org.bouncycastle.asn1.cmp.KeyRecRepContent;
-import org.bouncycastle.asn1.cmp.OOBCertHash;
-import org.bouncycastle.asn1.cmp.PBMParameter;
-import org.bouncycastle.asn1.cmp.PKIBody;
-import org.bouncycastle.asn1.cmp.PKIConfirmContent;
-import org.bouncycastle.asn1.cmp.PKIFailureInfo;
-import org.bouncycastle.asn1.cmp.PKIFreeText;
-import org.bouncycastle.asn1.cmp.PKIHeader;
-import org.bouncycastle.asn1.cmp.PKIMessage;
-import org.bouncycastle.asn1.cmp.PKIMessages;
-import org.bouncycastle.asn1.cmp.PKIStatus;
-import org.bouncycastle.asn1.cmp.PKIStatusInfo;
-import org.bouncycastle.asn1.cmp.POPODecKeyChallContent;
-import org.bouncycastle.asn1.cmp.POPODecKeyRespContent;
-import org.bouncycastle.asn1.cmp.PollRepContent;
-import org.bouncycastle.asn1.cmp.PollReqContent;
-import org.bouncycastle.asn1.cmp.ProtectedPart;
-import org.bouncycastle.asn1.cmp.RevAnnContent;
-import org.bouncycastle.asn1.cmp.RevDetails;
-import org.bouncycastle.asn1.cmp.RevRepContent;
-import org.bouncycastle.asn1.cmp.RevReqContent;
-import org.bouncycastle.asn1.cms.Attribute;
-import org.bouncycastle.asn1.cms.Attributes;
-import org.bouncycastle.asn1.cms.AuthEnvelopedData;
-import org.bouncycastle.asn1.cms.AuthenticatedData;
-import org.bouncycastle.asn1.cms.CompressedData;
-import org.bouncycastle.asn1.cms.ContentInfo;
-import org.bouncycastle.asn1.cms.EncryptedContentInfo;
-import org.bouncycastle.asn1.cms.EncryptedData;
-import org.bouncycastle.asn1.cms.EnvelopedData;
-import org.bouncycastle.asn1.cms.Evidence;
-import org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
-import org.bouncycastle.asn1.cms.KEKIdentifier;
-import org.bouncycastle.asn1.cms.KEKRecipientInfo;
-import org.bouncycastle.asn1.cms.KeyAgreeRecipientIdentifier;
-import org.bouncycastle.asn1.cms.KeyAgreeRecipientInfo;
-import org.bouncycastle.asn1.cms.KeyTransRecipientInfo;
-import org.bouncycastle.asn1.cms.MetaData;
-import org.bouncycastle.asn1.cms.OriginatorIdentifierOrKey;
-import org.bouncycastle.asn1.cms.OriginatorInfo;
-import org.bouncycastle.asn1.cms.OriginatorPublicKey;
-import org.bouncycastle.asn1.cms.OtherKeyAttribute;
-import org.bouncycastle.asn1.cms.OtherRecipientInfo;
-import org.bouncycastle.asn1.cms.PasswordRecipientInfo;
-import org.bouncycastle.asn1.cms.RecipientEncryptedKey;
-import org.bouncycastle.asn1.cms.RecipientIdentifier;
-import org.bouncycastle.asn1.cms.RecipientInfo;
-import org.bouncycastle.asn1.cms.RecipientKeyIdentifier;
-import org.bouncycastle.asn1.cms.SignerIdentifier;
-import org.bouncycastle.asn1.cms.SignerInfo;
-import org.bouncycastle.asn1.cms.TimeStampAndCRL;
-import org.bouncycastle.asn1.cms.TimeStampTokenEvidence;
-import org.bouncycastle.asn1.cms.TimeStampedData;
-import org.bouncycastle.asn1.cms.ecc.MQVuserKeyingMaterial;
-import org.bouncycastle.asn1.crmf.AttributeTypeAndValue;
-import org.bouncycastle.asn1.crmf.CertId;
-import org.bouncycastle.asn1.crmf.CertReqMessages;
-import org.bouncycastle.asn1.crmf.CertReqMsg;
-import org.bouncycastle.asn1.crmf.CertRequest;
-import org.bouncycastle.asn1.crmf.CertTemplate;
-import org.bouncycastle.asn1.crmf.Controls;
-import org.bouncycastle.asn1.crmf.EncKeyWithID;
-import org.bouncycastle.asn1.crmf.EncryptedKey;
-import org.bouncycastle.asn1.crmf.EncryptedValue;
-import org.bouncycastle.asn1.crmf.OptionalValidity;
-import org.bouncycastle.asn1.crmf.PKIArchiveOptions;
-import org.bouncycastle.asn1.crmf.PKIPublicationInfo;
-import org.bouncycastle.asn1.crmf.PKMACValue;
-import org.bouncycastle.asn1.crmf.POPOPrivKey;
-import org.bouncycastle.asn1.crmf.POPOSigningKey;
-import org.bouncycastle.asn1.crmf.POPOSigningKeyInput;
-import org.bouncycastle.asn1.crmf.ProofOfPossession;
-import org.bouncycastle.asn1.crmf.SinglePubInfo;
-import org.bouncycastle.asn1.cryptopro.ECGOST3410ParamSetParameters;
-import org.bouncycastle.asn1.cryptopro.GOST28147Parameters;
-import org.bouncycastle.asn1.cryptopro.GOST3410ParamSetParameters;
-import org.bouncycastle.asn1.cryptopro.GOST3410PublicKeyAlgParameters;
-import org.bouncycastle.asn1.eac.CVCertificate;
-import org.bouncycastle.asn1.eac.CVCertificateRequest;
-import org.bouncycastle.asn1.eac.CertificateBody;
-import org.bouncycastle.asn1.eac.PublicKeyDataObject;
-import org.bouncycastle.asn1.eac.RSAPublicKey;
-import org.bouncycastle.asn1.eac.UnsignedInteger;
-import org.bouncycastle.asn1.esf.CommitmentTypeIndication;
-import org.bouncycastle.asn1.esf.CommitmentTypeQualifier;
-import org.bouncycastle.asn1.esf.CompleteRevocationRefs;
-import org.bouncycastle.asn1.esf.CrlIdentifier;
-import org.bouncycastle.asn1.esf.CrlListID;
-import org.bouncycastle.asn1.esf.CrlOcspRef;
-import org.bouncycastle.asn1.esf.CrlValidatedID;
-import org.bouncycastle.asn1.esf.OcspIdentifier;
-import org.bouncycastle.asn1.esf.OcspListID;
-import org.bouncycastle.asn1.esf.OcspResponsesID;
-import org.bouncycastle.asn1.esf.OtherHash;
-import org.bouncycastle.asn1.esf.OtherHashAlgAndValue;
-import org.bouncycastle.asn1.esf.OtherRevRefs;
-import org.bouncycastle.asn1.esf.OtherRevVals;
-import org.bouncycastle.asn1.esf.RevocationValues;
-import org.bouncycastle.asn1.esf.SPUserNotice;
-import org.bouncycastle.asn1.esf.SPuri;
-import org.bouncycastle.asn1.esf.SigPolicyQualifierInfo;
-import org.bouncycastle.asn1.esf.SigPolicyQualifiers;
-import org.bouncycastle.asn1.esf.SignaturePolicyId;
-import org.bouncycastle.asn1.esf.SignaturePolicyIdentifier;
-import org.bouncycastle.asn1.esf.SignerAttribute;
-import org.bouncycastle.asn1.esf.SignerLocation;
-import org.bouncycastle.asn1.ess.ContentHints;
-import org.bouncycastle.asn1.ess.ContentIdentifier;
-import org.bouncycastle.asn1.ess.ESSCertID;
-import org.bouncycastle.asn1.ess.ESSCertIDv2;
-import org.bouncycastle.asn1.ess.OtherCertID;
-import org.bouncycastle.asn1.ess.OtherSigningCertificate;
-import org.bouncycastle.asn1.ess.SigningCertificate;
-import org.bouncycastle.asn1.ess.SigningCertificateV2;
-import org.bouncycastle.asn1.icao.CscaMasterList;
-import org.bouncycastle.asn1.icao.DataGroupHash;
-import org.bouncycastle.asn1.icao.LDSSecurityObject;
-import org.bouncycastle.asn1.icao.LDSVersionInfo;
-import org.bouncycastle.asn1.isismtt.ocsp.CertHash;
-import org.bouncycastle.asn1.isismtt.ocsp.RequestedCertificate;
-import org.bouncycastle.asn1.isismtt.x509.AdditionalInformationSyntax;
-import org.bouncycastle.asn1.isismtt.x509.AdmissionSyntax;
-import org.bouncycastle.asn1.isismtt.x509.Admissions;
-import org.bouncycastle.asn1.isismtt.x509.DeclarationOfMajority;
-import org.bouncycastle.asn1.isismtt.x509.MonetaryLimit;
-import org.bouncycastle.asn1.isismtt.x509.NamingAuthority;
-import org.bouncycastle.asn1.isismtt.x509.ProcurationSyntax;
-import org.bouncycastle.asn1.isismtt.x509.ProfessionInfo;
-import org.bouncycastle.asn1.isismtt.x509.Restriction;
-import org.bouncycastle.asn1.misc.CAST5CBCParameters;
-import org.bouncycastle.asn1.misc.IDEACBCPar;
-import org.bouncycastle.asn1.mozilla.PublicKeyAndChallenge;
-import org.bouncycastle.asn1.ocsp.BasicOCSPResponse;
-import org.bouncycastle.asn1.ocsp.CertID;
-import org.bouncycastle.asn1.ocsp.CertStatus;
-import org.bouncycastle.asn1.ocsp.CrlID;
-import org.bouncycastle.asn1.ocsp.OCSPRequest;
-import org.bouncycastle.asn1.ocsp.OCSPResponse;
-import org.bouncycastle.asn1.ocsp.OCSPResponseStatus;
-import org.bouncycastle.asn1.ocsp.Request;
-import org.bouncycastle.asn1.ocsp.ResponderID;
-import org.bouncycastle.asn1.ocsp.ResponseBytes;
-import org.bouncycastle.asn1.ocsp.ResponseData;
-import org.bouncycastle.asn1.ocsp.RevokedInfo;
-import org.bouncycastle.asn1.ocsp.Signature;
-import org.bouncycastle.asn1.ocsp.SingleResponse;
-import org.bouncycastle.asn1.ocsp.TBSRequest;
-import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
-import org.bouncycastle.asn1.pkcs.AuthenticatedSafe;
-import org.bouncycastle.asn1.pkcs.CertificationRequest;
-import org.bouncycastle.asn1.pkcs.CertificationRequestInfo;
-import org.bouncycastle.asn1.pkcs.DHParameter;
-import org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo;
-import org.bouncycastle.asn1.pkcs.MacData;
-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.Pfx;
-import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
-import org.bouncycastle.asn1.pkcs.RC2CBCParameter;
-import org.bouncycastle.asn1.pkcs.RSAESOAEPparams;
-import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
-import org.bouncycastle.asn1.pkcs.RSASSAPSSparams;
-import org.bouncycastle.asn1.pkcs.SafeBag;
-import org.bouncycastle.asn1.pkcs.SignedData;
-import org.bouncycastle.asn1.sec.ECPrivateKey;
-import org.bouncycastle.asn1.smime.SMIMECapabilities;
-import org.bouncycastle.asn1.smime.SMIMECapability;
-import org.bouncycastle.asn1.tsp.Accuracy;
-import org.bouncycastle.asn1.tsp.MessageImprint;
-import org.bouncycastle.asn1.tsp.TSTInfo;
-import org.bouncycastle.asn1.tsp.TimeStampReq;
-import org.bouncycastle.asn1.tsp.TimeStampResp;
-import org.bouncycastle.asn1.x500.DirectoryString;
-import org.bouncycastle.asn1.x500.RDN;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x509.AccessDescription;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.AttCertIssuer;
-import org.bouncycastle.asn1.x509.AttCertValidityPeriod;
-import org.bouncycastle.asn1.x509.AttributeCertificate;
-import org.bouncycastle.asn1.x509.AttributeCertificateInfo;
-import org.bouncycastle.asn1.x509.AuthorityInformationAccess;
-import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
-import org.bouncycastle.asn1.x509.BasicConstraints;
-import org.bouncycastle.asn1.x509.CRLDistPoint;
-import org.bouncycastle.asn1.x509.CRLNumber;
-import org.bouncycastle.asn1.x509.CRLReason;
-import org.bouncycastle.asn1.x509.Certificate;
-import org.bouncycastle.asn1.x509.CertificateList;
-import org.bouncycastle.asn1.x509.CertificatePair;
-import org.bouncycastle.asn1.x509.CertificatePolicies;
-import org.bouncycastle.asn1.x509.DSAParameter;
-import org.bouncycastle.asn1.x509.DigestInfo;
-import org.bouncycastle.asn1.x509.DisplayText;
-import org.bouncycastle.asn1.x509.DistributionPoint;
-import org.bouncycastle.asn1.x509.DistributionPointName;
-import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
-import org.bouncycastle.asn1.x509.Extensions;
-import org.bouncycastle.asn1.x509.GeneralName;
-import org.bouncycastle.asn1.x509.GeneralNames;
-import org.bouncycastle.asn1.x509.GeneralSubtree;
-import org.bouncycastle.asn1.x509.Holder;
-import org.bouncycastle.asn1.x509.IetfAttrSyntax;
-import org.bouncycastle.asn1.x509.IssuerSerial;
-import org.bouncycastle.asn1.x509.IssuingDistributionPoint;
-import org.bouncycastle.asn1.x509.NameConstraints;
-import org.bouncycastle.asn1.x509.NoticeReference;
-import org.bouncycastle.asn1.x509.ObjectDigestInfo;
-import org.bouncycastle.asn1.x509.PolicyInformation;
-import org.bouncycastle.asn1.x509.PolicyMappings;
-import org.bouncycastle.asn1.x509.PolicyQualifierInfo;
-import org.bouncycastle.asn1.x509.PrivateKeyUsagePeriod;
-import org.bouncycastle.asn1.x509.RSAPublicKeyStructure;
-import org.bouncycastle.asn1.x509.RoleSyntax;
-import org.bouncycastle.asn1.x509.SubjectDirectoryAttributes;
-import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.asn1.x509.TBSCertList;
-import org.bouncycastle.asn1.x509.TBSCertificate;
-import org.bouncycastle.asn1.x509.TBSCertificateStructure;
-import org.bouncycastle.asn1.x509.Target;
-import org.bouncycastle.asn1.x509.TargetInformation;
-import org.bouncycastle.asn1.x509.Targets;
-import org.bouncycastle.asn1.x509.Time;
-import org.bouncycastle.asn1.x509.UserNotice;
-import org.bouncycastle.asn1.x509.V2Form;
-import org.bouncycastle.asn1.x509.X509CertificateStructure;
-import org.bouncycastle.asn1.x509.X509Extensions;
-import org.bouncycastle.asn1.x509.X509Name;
-import org.bouncycastle.asn1.x509.qualified.BiometricData;
-import org.bouncycastle.asn1.x509.qualified.Iso4217CurrencyCode;
-import org.bouncycastle.asn1.x509.qualified.MonetaryValue;
-import org.bouncycastle.asn1.x509.qualified.QCStatement;
-import org.bouncycastle.asn1.x509.qualified.SemanticsInformation;
-import org.bouncycastle.asn1.x509.qualified.TypeOfBiometricData;
-import org.bouncycastle.asn1.x509.sigi.NameOrPseudonym;
-import org.bouncycastle.asn1.x509.sigi.PersonalData;
-import org.bouncycastle.asn1.x9.DHDomainParameters;
-import org.bouncycastle.asn1.x9.DHPublicKey;
-import org.bouncycastle.asn1.x9.DHValidationParms;
-import org.bouncycastle.asn1.x9.X962Parameters;
-import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.util.Integers;
-import org.bouncycastle.util.encoders.Base64;
-
-public class GetInstanceTest
- extends TestCase
-{
- public static byte[] attrCert = Base64.decode(
- "MIIHQDCCBqkCAQEwgZChgY2kgYowgYcxHDAaBgkqhkiG9w0BCQEWDW1sb3JjaEB2"
- + "dC5lZHUxHjAcBgNVBAMTFU1hcmt1cyBMb3JjaCAobWxvcmNoKTEbMBkGA1UECxMS"
- + "VmlyZ2luaWEgVGVjaCBVc2VyMRAwDgYDVQQLEwdDbGFzcyAyMQswCQYDVQQKEwJ2"
- + "dDELMAkGA1UEBhMCVVMwgYmkgYYwgYMxGzAZBgkqhkiG9w0BCQEWDHNzaGFoQHZ0"
- + "LmVkdTEbMBkGA1UEAxMSU3VtaXQgU2hhaCAoc3NoYWgpMRswGQYDVQQLExJWaXJn"
- + "aW5pYSBUZWNoIFVzZXIxEDAOBgNVBAsTB0NsYXNzIDExCzAJBgNVBAoTAnZ0MQsw"
- + "CQYDVQQGEwJVUzANBgkqhkiG9w0BAQQFAAIBBTAiGA8yMDAzMDcxODE2MDgwMloY"
- + "DzIwMDMwNzI1MTYwODAyWjCCBU0wggVJBgorBgEEAbRoCAEBMYIFORaCBTU8UnVs"
- + "ZSBSdWxlSWQ9IkZpbGUtUHJpdmlsZWdlLVJ1bGUiIEVmZmVjdD0iUGVybWl0Ij4K"
- + "IDxUYXJnZXQ+CiAgPFN1YmplY3RzPgogICA8U3ViamVjdD4KICAgIDxTdWJqZWN0"
- + "TWF0Y2ggTWF0Y2hJZD0idXJuOm9hc2lzOm5hbWVzOnRjOnhhY21sOjEuMDpmdW5j"
- + "dGlvbjpzdHJpbmctZXF1YWwiPgogICAgIDxBdHRyaWJ1dGVWYWx1ZSBEYXRhVHlw"
- + "ZT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEjc3RyaW5nIj4KICAg"
- + "ICAgIENOPU1hcmt1cyBMb3JjaDwvQXR0cmlidXRlVmFsdWU+CiAgICAgPFN1Ympl"
- + "Y3RBdHRyaWJ1dGVEZXNpZ25hdG9yIEF0dHJpYnV0ZUlkPSJ1cm46b2FzaXM6bmFt"
- + "ZXM6dGM6eGFjbWw6MS4wOnN1YmplY3Q6c3ViamVjdC1pZCIgRGF0YVR5cGU9Imh0"
- + "dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hI3N0cmluZyIgLz4gCiAgICA8"
- + "L1N1YmplY3RNYXRjaD4KICAgPC9TdWJqZWN0PgogIDwvU3ViamVjdHM+CiAgPFJl"
- + "c291cmNlcz4KICAgPFJlc291cmNlPgogICAgPFJlc291cmNlTWF0Y2ggTWF0Y2hJ"
- + "ZD0idXJuOm9hc2lzOm5hbWVzOnRjOnhhY21sOjEuMDpmdW5jdGlvbjpzdHJpbmct"
- + "ZXF1YWwiPgogICAgIDxBdHRyaWJ1dGVWYWx1ZSBEYXRhVHlwZT0iaHR0cDovL3d3"
- + "dy53My5vcmcvMjAwMS9YTUxTY2hlbWEjYW55VVJJIj4KICAgICAgaHR0cDovL3p1"
- + "bmkuY3MudnQuZWR1PC9BdHRyaWJ1dGVWYWx1ZT4KICAgICA8UmVzb3VyY2VBdHRy"
- + "aWJ1dGVEZXNpZ25hdG9yIEF0dHJpYnV0ZUlkPSJ1cm46b2FzaXM6bmFtZXM6dGM6"
- + "eGFjbWw6MS4wOnJlc291cmNlOnJlc291cmNlLWlkIiBEYXRhVHlwZT0iaHR0cDov"
- + "L3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEjYW55VVJJIiAvPiAKICAgIDwvUmVz"
- + "b3VyY2VNYXRjaD4KICAgPC9SZXNvdXJjZT4KICA8L1Jlc291cmNlcz4KICA8QWN0"
- + "aW9ucz4KICAgPEFjdGlvbj4KICAgIDxBY3Rpb25NYXRjaCBNYXRjaElkPSJ1cm46"
- + "b2FzaXM6bmFtZXM6dGM6eGFjbWw6MS4wOmZ1bmN0aW9uOnN0cmluZy1lcXVhbCI+"
- + "CiAgICAgPEF0dHJpYnV0ZVZhbHVlIERhdGFUeXBlPSJodHRwOi8vd3d3LnczLm9y"
- + "Zy8yMDAxL1hNTFNjaGVtYSNzdHJpbmciPgpEZWxlZ2F0ZSBBY2Nlc3MgICAgIDwv"
- + "QXR0cmlidXRlVmFsdWU+CgkgIDxBY3Rpb25BdHRyaWJ1dGVEZXNpZ25hdG9yIEF0"
- + "dHJpYnV0ZUlkPSJ1cm46b2FzaXM6bmFtZXM6dGM6eGFjbWw6MS4wOmFjdGlvbjph"
- + "Y3Rpb24taWQiIERhdGFUeXBlPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNj"
- + "aGVtYSNzdHJpbmciIC8+IAogICAgPC9BY3Rpb25NYXRjaD4KICAgPC9BY3Rpb24+"
- + "CiAgPC9BY3Rpb25zPgogPC9UYXJnZXQ+CjwvUnVsZT4KMA0GCSqGSIb3DQEBBAUA"
- + "A4GBAGiJSM48XsY90HlYxGmGVSmNR6ZW2As+bot3KAfiCIkUIOAqhcphBS23egTr"
- + "6asYwy151HshbPNYz+Cgeqs45KkVzh7bL/0e1r8sDVIaaGIkjHK3CqBABnfSayr3"
- + "Rd1yBoDdEv8Qb+3eEPH6ab9021AsLEnJ6LWTmybbOpMNZ3tv");
-
- byte[] cert1 = Base64.decode(
- "MIIDXjCCAsegAwIBAgIBBzANBgkqhkiG9w0BAQQFADCBtzELMAkGA1UEBhMCQVUx"
- + "ETAPBgNVBAgTCFZpY3RvcmlhMRgwFgYDVQQHEw9Tb3V0aCBNZWxib3VybmUxGjAY"
- + "BgNVBAoTEUNvbm5lY3QgNCBQdHkgTHRkMR4wHAYDVQQLExVDZXJ0aWZpY2F0ZSBB"
- + "dXRob3JpdHkxFTATBgNVBAMTDENvbm5lY3QgNCBDQTEoMCYGCSqGSIb3DQEJARYZ"
- + "d2VibWFzdGVyQGNvbm5lY3Q0LmNvbS5hdTAeFw0wMDA2MDIwNzU2MjFaFw0wMTA2"
- + "MDIwNzU2MjFaMIG4MQswCQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExGDAW"
- + "BgNVBAcTD1NvdXRoIE1lbGJvdXJuZTEaMBgGA1UEChMRQ29ubmVjdCA0IFB0eSBM"
- + "dGQxFzAVBgNVBAsTDldlYnNlcnZlciBUZWFtMR0wGwYDVQQDExR3d3cyLmNvbm5l"
- + "Y3Q0LmNvbS5hdTEoMCYGCSqGSIb3DQEJARYZd2VibWFzdGVyQGNvbm5lY3Q0LmNv"
- + "bS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArvDxclKAhyv7Q/Wmr2re"
- + "Gw4XL9Cnh9e+6VgWy2AWNy/MVeXdlxzd7QAuc1eOWQkGQEiLPy5XQtTY+sBUJ3AO"
- + "Rvd2fEVJIcjf29ey7bYua9J/vz5MG2KYo9/WCHIwqD9mmG9g0xLcfwq/s8ZJBswE"
- + "7sb85VU+h94PTvsWOsWuKaECAwEAAaN3MHUwJAYDVR0RBB0wG4EZd2VibWFzdGVy"
- + "QGNvbm5lY3Q0LmNvbS5hdTA6BglghkgBhvhCAQ0ELRYrbW9kX3NzbCBnZW5lcmF0"
- + "ZWQgY3VzdG9tIHNlcnZlciBjZXJ0aWZpY2F0ZTARBglghkgBhvhCAQEEBAMCBkAw"
- + "DQYJKoZIhvcNAQEEBQADgYEAotccfKpwSsIxM1Hae8DR7M/Rw8dg/RqOWx45HNVL"
- + "iBS4/3N/TO195yeQKbfmzbAA2jbPVvIvGgTxPgO1MP4ZgvgRhasaa0qCJCkWvpM4"
- + "yQf33vOiYQbpv4rTwzU8AmRlBG45WdjyNIigGV+oRc61aKCTnLq7zB8N3z1TF/bF"
- + "5/8=");
-
- private byte[] v2CertList = Base64.decode(
- "MIICjTCCAfowDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMxIDAeBgNVBAoT"
- + "F1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2VydmVy"
- + "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5Fw05NTA1MDIwMjEyMjZaFw05NTA2MDEw"
- + "MDAxNDlaMIIBaDAWAgUCQQAABBcNOTUwMjAxMTcyNDI2WjAWAgUCQQAACRcNOTUw"
- + "MjEwMDIxNjM5WjAWAgUCQQAADxcNOTUwMjI0MDAxMjQ5WjAWAgUCQQAADBcNOTUw"
- + "MjI1MDA0NjQ0WjAWAgUCQQAAGxcNOTUwMzEzMTg0MDQ5WjAWAgUCQQAAFhcNOTUw"
- + "MzE1MTkxNjU0WjAWAgUCQQAAGhcNOTUwMzE1MTk0MDQxWjAWAgUCQQAAHxcNOTUw"
- + "MzI0MTk0NDMzWjAWAgUCcgAABRcNOTUwMzI5MjAwNzExWjAWAgUCcgAAERcNOTUw"
- + "MzMwMDIzNDI2WjAWAgUCQQAAIBcNOTUwNDA3MDExMzIxWjAWAgUCcgAAHhcNOTUw"
- + "NDA4MDAwMjU5WjAWAgUCcgAAQRcNOTUwNDI4MTcxNzI0WjAWAgUCcgAAOBcNOTUw"
- + "NDI4MTcyNzIxWjAWAgUCcgAATBcNOTUwNTAyMDIxMjI2WjANBgkqhkiG9w0BAQIF"
- + "AAN+AHqOEJXSDejYy0UwxxrH/9+N2z5xu/if0J6qQmK92W0hW158wpJg+ovV3+wQ"
- + "wvIEPRL2rocL0tKfAsVq1IawSJzSNgxG0lrcla3MrJBnZ4GaZDu4FutZh72MR3Gt"
- + "JaAL3iTJHJD55kK2D/VoyY1djlsPuNh6AEgdVwFAyp0v");
-
- private static final Object[] NULL_ARGS = new Object[] { null };
-
- private void doFullGetInstanceTest(Class clazz, ASN1Object o1)
- throws Exception
- {
- Method m;
-
- try
- {
- m = clazz.getMethod("getInstance", Object.class);
- }
- catch (NoSuchMethodException e)
- {
- fail("no getInstance method found");
- return;
- }
-
- ASN1Object o2 = (ASN1Object)m.invoke(clazz, NULL_ARGS);
- if (o2 != null)
- {
- fail(clazz.getName() + " null failed");
- }
-
- o2 = (ASN1Object)m.invoke(clazz, o1);
-
- if (!o1.equals(o2) || !clazz.isInstance(o2))
- {
- fail(clazz.getName() + " equality failed");
- }
-
- o2 = (ASN1Object)m.invoke(clazz, o1.getEncoded());
- if (!o1.equals(o2) || !clazz.isInstance(o2))
- {
- fail(clazz.getName() + " encoded equality failed");
- }
-
- o2 = (ASN1Object)m.invoke(clazz, o1.toASN1Primitive());
- if (!o1.equals(o2) || !clazz.isInstance(o2))
- {
- fail(clazz.getName() + " sequence equality failed");
- }
-
- try
- {
- m = clazz.getMethod("getInstance", ASN1TaggedObject.class, Boolean.TYPE);
- }
- catch (NoSuchMethodException e)
- {
- return;
- }
-
- ASN1TaggedObject t = new DERTaggedObject(true, 0, o1);
- o2 = (ASN1Object)m.invoke(clazz, t, true);
- if (!o1.equals(o2) || !clazz.isInstance(o2))
- {
- fail(clazz.getName() + " tag equality failed");
- }
-
- t = new DERTaggedObject(true, 0, o1.toASN1Primitive());
- o2 = (ASN1Object)m.invoke(clazz, t, true);
- if (!o1.equals(o2) || !clazz.isInstance(o2))
- {
- fail(clazz.getName() + " tag equality failed");
- }
-
- t = ASN1TaggedObject.getInstance(t.getEncoded());
- o2 = (ASN1Object)m.invoke(clazz, t, true);
- if (!o1.equals(o2) || !clazz.isInstance(o2))
- {
- fail(clazz.getName() + " tag equality failed");
- }
-
- t = new DERTaggedObject(false, 0, o1);
- o2 = (ASN1Object)m.invoke(clazz, t, false);
- if (!o1.equals(o2) || !clazz.isInstance(o2))
- {
- fail(clazz.getName() + " tag equality failed");
- }
-
- t = new DERTaggedObject(false, 0, o1.toASN1Primitive());
- o2 = (ASN1Object)m.invoke(clazz, t, false);
- if (!o1.equals(o2) || !clazz.isInstance(o2))
- {
- fail(clazz.getName() + " tag equality failed");
- }
-
- t = ASN1TaggedObject.getInstance(t.getEncoded());
- o2 = (ASN1Object)m.invoke(clazz, t, false);
- if (!o1.equals(o2) || !clazz.isInstance(o2))
- {
- fail(clazz.getName() + " tag equality failed");
- }
- }
-
- public void testGetInstance()
- throws Exception
- {
- doFullGetInstanceTest(DERPrintableString.class, new DERPrintableString("hello world"));
- doFullGetInstanceTest(DERBMPString.class, new DERBMPString("hello world"));
- doFullGetInstanceTest(DERUTF8String.class, new DERUTF8String("hello world"));
- doFullGetInstanceTest(DERUniversalString.class, new DERUniversalString(new byte[20]));
- doFullGetInstanceTest(DERIA5String.class, new DERIA5String("hello world"));
- doFullGetInstanceTest(DERGeneralString.class, new DERGeneralString("hello world"));
- doFullGetInstanceTest(DERNumericString.class, new DERNumericString("hello world"));
- doFullGetInstanceTest(DERNumericString.class, new DERNumericString("99999", true));
- doFullGetInstanceTest(DERT61String.class, new DERT61String("hello world"));
- doFullGetInstanceTest(DERVisibleString.class, new DERVisibleString("hello world"));
-
- doFullGetInstanceTest(ASN1Integer.class, new ASN1Integer(1));
- doFullGetInstanceTest(ASN1GeneralizedTime.class, new ASN1GeneralizedTime(new Date()));
- doFullGetInstanceTest(ASN1UTCTime.class, new ASN1UTCTime(new Date()));
- doFullGetInstanceTest(ASN1Enumerated.class, new ASN1Enumerated(1));
-
- CMPCertificate cmpCert = new CMPCertificate(Certificate.getInstance(cert1));
- CertificateList crl = CertificateList.getInstance(v2CertList);
- AttributeCertificate attributeCert = AttributeCertificate.getInstance(attrCert);
-
- doFullGetInstanceTest(CAKeyUpdAnnContent.class, new CAKeyUpdAnnContent(cmpCert, cmpCert, cmpCert));
-
- CertConfirmContent.getInstance(null);
- CertifiedKeyPair.getInstance(null);
- CertOrEncCert.getInstance(null);
- CertRepMessage.getInstance(null);
- doFullGetInstanceTest(CertResponse.class, new CertResponse(new ASN1Integer(1), new PKIStatusInfo(PKIStatus.granted)));
- doFullGetInstanceTest(org.bouncycastle.asn1.cmp.CertStatus.class, new org.bouncycastle.asn1.cmp.CertStatus(new byte[10], BigInteger.valueOf(1), new PKIStatusInfo(PKIStatus.granted)));
- doFullGetInstanceTest(Challenge.class, new Challenge(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE), new byte[10], new byte[10]));
-
- doFullGetInstanceTest(CMPCertificate.class, cmpCert);
- doFullGetInstanceTest(CRLAnnContent.class, new CRLAnnContent(crl));
- doFullGetInstanceTest(ErrorMsgContent.class, new ErrorMsgContent(new PKIStatusInfo(PKIStatus.granted), new ASN1Integer(1), new PKIFreeText("fred")));
- GenMsgContent.getInstance(null);
- GenRepContent.getInstance(null);
- InfoTypeAndValue.getInstance(null);
- KeyRecRepContent.getInstance(null);
- OOBCertHash.getInstance(null);
- PBMParameter.getInstance(null);
- PKIBody.getInstance(null);
- PKIConfirmContent.getInstance(null);
- PKIFreeText.getInstance(null);
- doFullGetInstanceTest(PKIFreeText.class, new PKIFreeText("hello world"));
- doFullGetInstanceTest(PKIFreeText.class, new PKIFreeText(new String[]{"hello", "world"}));
- doFullGetInstanceTest(PKIFreeText.class, new PKIFreeText(new DERUTF8String[]{new DERUTF8String("hello"), new DERUTF8String("world")}));
- PKIHeader.getInstance(null);
- PKIMessage.getInstance(null);
- PKIMessages.getInstance(null);
- doFullGetInstanceTest(PKIStatusInfo.class, new PKIStatusInfo(PKIStatus.rejection, new PKIFreeText("hello world"), new PKIFailureInfo(PKIFailureInfo.badAlg)));
- doFullGetInstanceTest(PKIStatusInfo.class, new PKIStatusInfo(PKIStatus.granted, new PKIFreeText("hello world")));
- PKIStatus.getInstance(null);
- PollRepContent.getInstance(null);
- PollReqContent.getInstance(null);
- POPODecKeyChallContent.getInstance(null);
- POPODecKeyRespContent.getInstance(null);
- ProtectedPart.getInstance(null);
- RevAnnContent.getInstance(null);
- RevDetails.getInstance(null);
- RevRepContent.getInstance(null);
- RevReqContent.getInstance(null);
- Attribute.getInstance(null);
- Attributes.getInstance(null);
- AuthenticatedData.getInstance(null);
- AuthenticatedData.getInstance(null);
- AuthEnvelopedData.getInstance(null);
- AuthEnvelopedData.getInstance(null);
- CompressedData.getInstance(null);
- CompressedData.getInstance(null);
- ContentInfo.getInstance(null);
- EncryptedContentInfo.getInstance(null);
- EncryptedData.getInstance(null);
- EnvelopedData.getInstance(null);
- EnvelopedData.getInstance(null);
- Evidence.getInstance(null);
- IssuerAndSerialNumber.getInstance(null);
- KEKIdentifier.getInstance(null);
- KEKIdentifier.getInstance(null);
- KEKRecipientInfo.getInstance(null);
- KEKRecipientInfo.getInstance(null);
- KeyAgreeRecipientIdentifier.getInstance(null);
- KeyAgreeRecipientIdentifier.getInstance(null);
- KeyAgreeRecipientInfo.getInstance(null);
- KeyAgreeRecipientInfo.getInstance(null);
- KeyTransRecipientInfo.getInstance(null);
- MetaData.getInstance(null);
- OriginatorIdentifierOrKey.getInstance(null);
- OriginatorIdentifierOrKey.getInstance(null);
- OriginatorInfo.getInstance(null);
- OriginatorInfo.getInstance(null);
- OriginatorPublicKey.getInstance(null);
- OriginatorPublicKey.getInstance(null);
- OtherKeyAttribute.getInstance(null);
- OtherRecipientInfo.getInstance(null);
- OtherRecipientInfo.getInstance(null);
- PasswordRecipientInfo.getInstance(null);
- PasswordRecipientInfo.getInstance(null);
- RecipientEncryptedKey.getInstance(null);
- RecipientIdentifier.getInstance(null);
- RecipientInfo.getInstance(null);
- RecipientKeyIdentifier.getInstance(null);
- RecipientKeyIdentifier.getInstance(null);
- SignedData.getInstance(null);
- SignerIdentifier.getInstance(null);
- SignerInfo.getInstance(null);
- Time.getInstance(null);
- Time.getInstance(null);
- TimeStampAndCRL.getInstance(null);
- TimeStampedData.getInstance(null);
- TimeStampTokenEvidence.getInstance(null);
- AttributeTypeAndValue.getInstance(null);
-
- doFullGetInstanceTest(CertId.class, new CertId(new GeneralName(new X500Name("CN=Test")), BigInteger.valueOf(1)));
-
-
- CertReqMessages.getInstance(null);
- CertReqMsg.getInstance(null);
- CertRequest.getInstance(null);
- CertTemplate.getInstance(null);
- Controls.getInstance(null);
- EncKeyWithID.getInstance(null);
- EncryptedKey.getInstance(null);
- EncryptedValue.getInstance(null);
- OptionalValidity.getInstance(null);
- PKIArchiveOptions.getInstance(null);
- PKIPublicationInfo.getInstance(null);
- PKMACValue.getInstance(null);
- PKMACValue.getInstance(null);
- POPOPrivKey.getInstance(null);
- POPOSigningKeyInput.getInstance(null);
- POPOSigningKey.getInstance(null);
- POPOSigningKey.getInstance(null);
- ProofOfPossession.getInstance(null);
- SinglePubInfo.getInstance(null);
- ECGOST3410ParamSetParameters.getInstance(null);
- ECGOST3410ParamSetParameters.getInstance(null);
- GOST28147Parameters.getInstance(null);
- GOST28147Parameters.getInstance(null);
- GOST3410ParamSetParameters.getInstance(null);
- GOST3410ParamSetParameters.getInstance(null);
- GOST3410PublicKeyAlgParameters.getInstance(null);
- GOST3410PublicKeyAlgParameters.getInstance(null);
- CertificateBody.getInstance(null);
- CVCertificate.getInstance(null);
- CVCertificateRequest.getInstance(null);
- PublicKeyDataObject.getInstance(null);
- UnsignedInteger.getInstance(null);
- CommitmentTypeIndication.getInstance(null);
- CommitmentTypeQualifier.getInstance(null);
-
- OcspIdentifier ocspIdentifier = new OcspIdentifier(new ResponderID(new X500Name("CN=Test")), new ASN1GeneralizedTime(new Date()));
- CrlListID crlListID = new CrlListID(new CrlValidatedID[]{new CrlValidatedID(new OtherHash(new byte[20]))});
- OcspListID ocspListID = new OcspListID(new OcspResponsesID[] { new OcspResponsesID(ocspIdentifier) });
- OtherRevRefs otherRevRefs = new OtherRevRefs(new ASN1ObjectIdentifier("1.2.1"), new DERSequence());
- OtherRevVals otherRevVals = new OtherRevVals(new ASN1ObjectIdentifier("1.2.1"), new DERSequence());
- CrlOcspRef crlOcspRef = new CrlOcspRef(crlListID, ocspListID, otherRevRefs);
- doFullGetInstanceTest(CompleteRevocationRefs.class, new CompleteRevocationRefs(new CrlOcspRef[]{crlOcspRef, crlOcspRef}));
-
- doFullGetInstanceTest(CrlIdentifier.class, new CrlIdentifier(new X500Name("CN=Test"), new ASN1UTCTime(new Date()), BigInteger.valueOf(1)));
-
-
- doFullGetInstanceTest(CrlListID.class, crlListID);
- doFullGetInstanceTest(CrlOcspRef.class, crlOcspRef);
- doFullGetInstanceTest(CrlValidatedID.class, new CrlValidatedID(new OtherHash(new byte[20])));
- doFullGetInstanceTest(OcspIdentifier.class, ocspIdentifier);
- doFullGetInstanceTest(OcspListID.class, ocspListID);
- doFullGetInstanceTest(OcspResponsesID.class, new OcspResponsesID(ocspIdentifier));
-
- OtherHashAlgAndValue otherHashAlgAndValue = new OtherHashAlgAndValue(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE), new DEROctetString(new byte[10]));
- doFullGetInstanceTest(OtherHashAlgAndValue.class, otherHashAlgAndValue);
- OtherHash.getInstance(null);
- doFullGetInstanceTest(OtherRevRefs.class, otherRevRefs);
- doFullGetInstanceTest(OtherRevVals.class, otherRevVals);
- doFullGetInstanceTest(RevocationValues.class, new RevocationValues(new CertificateList[]{crl}, null, otherRevVals));
-
- SignaturePolicyId signaturePolicyId = new SignaturePolicyId(new ASN1ObjectIdentifier("1.2.1"), otherHashAlgAndValue);
- doFullGetInstanceTest(SignaturePolicyIdentifier.class, new SignaturePolicyIdentifier());
- doFullGetInstanceTest(SignaturePolicyIdentifier.class, new SignaturePolicyIdentifier(signaturePolicyId));
- doFullGetInstanceTest(SignaturePolicyId.class, signaturePolicyId);
- doFullGetInstanceTest(SignerAttribute.class, new SignerAttribute(new org.bouncycastle.asn1.x509.Attribute[]{new org.bouncycastle.asn1.x509.Attribute(new ASN1ObjectIdentifier("1.2.1"), new DERSet())}));
- doFullGetInstanceTest(SignerAttribute.class, new SignerAttribute(attributeCert));
-
- ASN1EncodableVector postalAddr = new ASN1EncodableVector();
-
- postalAddr.add(new DERUTF8String("line 1"));
- postalAddr.add(new DERUTF8String("line 2"));
-
- doFullGetInstanceTest(SignerLocation.class, new SignerLocation(new DERUTF8String("AU"), new DERUTF8String("Melbourne"), new DERSequence(postalAddr)));
- doFullGetInstanceTest(SigPolicyQualifierInfo.class, new SigPolicyQualifierInfo(new ASN1ObjectIdentifier("1.2.1"), new DERSequence()));
- SigPolicyQualifiers.getInstance(null);
- SPuri.getInstance(null);
- Vector v = new Vector();
-
- v.add(Integers.valueOf(1));
- v.add(BigInteger.valueOf(2));
- NoticeReference noticeReference = new NoticeReference("BC", v);
- doFullGetInstanceTest(SPUserNotice.class, new SPUserNotice(noticeReference, new DisplayText("hello world")));
- ContentHints.getInstance(null);
- ContentIdentifier.getInstance(null);
- ESSCertID.getInstance(null);
- ESSCertIDv2.getInstance(null);
- OtherCertID.getInstance(null);
- OtherSigningCertificate.getInstance(null);
- SigningCertificate.getInstance(null);
- SigningCertificateV2.getInstance(null);
- CscaMasterList.getInstance(null);
- DataGroupHash.getInstance(null);
- LDSSecurityObject.getInstance(null);
- LDSVersionInfo.getInstance(null);
- CAST5CBCParameters.getInstance(null);
- IDEACBCPar.getInstance(null);
- PublicKeyAndChallenge.getInstance(null);
- BasicOCSPResponse.getInstance(null);
- BasicOCSPResponse.getInstance(null);
-
- doFullGetInstanceTest(CertID.class, new CertID(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE), new DEROctetString(new byte[1]), new DEROctetString(new byte[1]), new ASN1Integer(1)));
-
- CertStatus.getInstance(null);
- CertStatus.getInstance(null);
- CrlID.getInstance(null);
- OCSPRequest.getInstance(null);
- OCSPRequest.getInstance(null);
- OCSPResponse.getInstance(null);
- OCSPResponse.getInstance(null);
- OCSPResponseStatus.getInstance(null);
- Request.getInstance(null);
- Request.getInstance(null);
- ResponderID.getInstance(null);
- ResponderID.getInstance(null);
- ResponseBytes.getInstance(null);
- ResponseBytes.getInstance(null);
- ResponseData.getInstance(null);
- ResponseData.getInstance(null);
- RevokedInfo.getInstance(null);
- RevokedInfo.getInstance(null);
- Signature.getInstance(null);
- Signature.getInstance(null);
- SingleResponse.getInstance(null);
- SingleResponse.getInstance(null);
- TBSRequest.getInstance(null);
- TBSRequest.getInstance(null);
- Attribute.getInstance(null);
- AuthenticatedSafe.getInstance(null);
- CertificationRequestInfo.getInstance(null);
- CertificationRequest.getInstance(null);
- ContentInfo.getInstance(null);
- DHParameter.getInstance(null);
- EncryptedData.getInstance(null);
- EncryptedPrivateKeyInfo.getInstance(null);
- AlgorithmIdentifier.getInstance(null);
- IssuerAndSerialNumber.getInstance(null);
- MacData.getInstance(null);
- PBEParameter.getInstance(null);
- PBES2Parameters.getInstance(null);
- PBKDF2Params.getInstance(null);
- Pfx.getInstance(null);
- PKCS12PBEParams.getInstance(null);
- PrivateKeyInfo.getInstance(null);
- PrivateKeyInfo.getInstance(null);
- RC2CBCParameter.getInstance(null);
- RSAESOAEPparams.getInstance(null);
- RSAPrivateKey.getInstance(null);
- RSAPrivateKey.getInstance(null);
- RSAPublicKey.getInstance(null);
- RSAPublicKey.getInstance(null);
- RSASSAPSSparams.getInstance(null);
- SafeBag.getInstance(null);
- SignedData.getInstance(null);
- SignerInfo.getInstance(null);
- ECPrivateKey.getInstance(null);
- SMIMECapabilities.getInstance(null);
- SMIMECapability.getInstance(null);
- Accuracy.getInstance(null);
- MessageImprint.getInstance(null);
- TimeStampReq.getInstance(null);
- TimeStampResp.getInstance(null);
- TSTInfo.getInstance(null);
- AttributeTypeAndValue.getInstance(null);
- DirectoryString.getInstance(null);
- DirectoryString.getInstance(null);
- RDN.getInstance(null);
- X500Name.getInstance(null);
- X500Name.getInstance(null);
- AccessDescription.getInstance(null);
- AlgorithmIdentifier.getInstance(null);
- AlgorithmIdentifier.getInstance(null);
- AttCertIssuer.getInstance(null);
- AttCertIssuer.getInstance(null);
- AttCertValidityPeriod.getInstance(null);
- AttributeCertificateInfo.getInstance(null);
- AttributeCertificateInfo.getInstance(null);
- AttributeCertificate.getInstance(null);
- Attribute.getInstance(null);
- AuthorityInformationAccess.getInstance(null);
- AuthorityKeyIdentifier.getInstance(null);
- AuthorityKeyIdentifier.getInstance(null);
- BasicConstraints.getInstance(null);
- BasicConstraints.getInstance(null);
- Certificate.getInstance(null);
- Certificate.getInstance(null);
- CertificateList.getInstance(null);
- CertificateList.getInstance(null);
- CertificatePair.getInstance(null);
- CertificatePolicies.getInstance(null);
- CertificatePolicies.getInstance(null);
- CRLDistPoint.getInstance(null);
- CRLDistPoint.getInstance(null);
- CRLNumber.getInstance(null);
- CRLReason.getInstance(null);
- DigestInfo.getInstance(null);
- DigestInfo.getInstance(null);
- DisplayText.getInstance(null);
- DisplayText.getInstance(null);
- DistributionPoint.getInstance(null);
- DistributionPoint.getInstance(null);
- DistributionPointName.getInstance(null);
- DistributionPointName.getInstance(null);
- DSAParameter.getInstance(null);
- DSAParameter.getInstance(null);
- ExtendedKeyUsage.getInstance(null);
- ExtendedKeyUsage.getInstance(null);
- Extensions.getInstance(null);
- Extensions.getInstance(null);
- GeneralName.getInstance(null);
- GeneralName.getInstance(null);
- GeneralNames.getInstance(null);
- GeneralNames.getInstance(null);
-
- GeneralSubtree generalSubtree = new GeneralSubtree(new GeneralName(new X500Name("CN=Test")));
- ASN1ObjectIdentifier algOid = new ASN1ObjectIdentifier("1.2.1");
- ObjectDigestInfo objectDigestInfo = new ObjectDigestInfo(ObjectDigestInfo.otherObjectDigest, algOid, new AlgorithmIdentifier(algOid), new byte[20]);
-
- doFullGetInstanceTest(GeneralSubtree.class, generalSubtree);
- doFullGetInstanceTest(Holder.class, new Holder(objectDigestInfo));
- IetfAttrSyntax.getInstance(null);
- IssuerSerial.getInstance(null);
- IssuerSerial.getInstance(null);
- IssuingDistributionPoint.getInstance(null);
- IssuingDistributionPoint.getInstance(null);
- DERBitString.getInstance(null);
-
- v.clear();
- v.add(generalSubtree);
-
- doFullGetInstanceTest(NameConstraints.class, new NameConstraints(null, null));
- doFullGetInstanceTest(NoticeReference.class, noticeReference);
- doFullGetInstanceTest(ObjectDigestInfo.class, objectDigestInfo);
-
- PolicyInformation.getInstance(null);
- PolicyMappings.getInstance(null);
- PolicyQualifierInfo.getInstance(null);
- PrivateKeyUsagePeriod.getInstance(null);
- doFullGetInstanceTest(RoleSyntax.class, new RoleSyntax(new GeneralNames(new GeneralName(new X500Name("CN=Test"))), new GeneralName(GeneralName.uniformResourceIdentifier, "http://bc")));
- RSAPublicKeyStructure.getInstance(null);
- RSAPublicKeyStructure.getInstance(null);
- SubjectDirectoryAttributes.getInstance(null);
- SubjectKeyIdentifier.getInstance(null);
- SubjectKeyIdentifier.getInstance(null);
- SubjectPublicKeyInfo.getInstance(null);
- SubjectPublicKeyInfo.getInstance(null);
- TargetInformation.getInstance(null);
- Target.getInstance(null);
- Targets.getInstance(null);
- TBSCertificate.getInstance(null);
- TBSCertificate.getInstance(null);
- TBSCertificateStructure.getInstance(null);
- TBSCertificateStructure.getInstance(null);
- TBSCertList.CRLEntry.getInstance(null);
- TBSCertList.getInstance(null);
- TBSCertList.getInstance(null);
- Time.getInstance(null);
- Time.getInstance(null);
- doFullGetInstanceTest(UserNotice.class, new UserNotice(noticeReference, "hello world"));
- V2Form.getInstance(null);
- V2Form.getInstance(null);
- X509CertificateStructure.getInstance(null);
- X509CertificateStructure.getInstance(null);
- X509Extensions.getInstance(null);
- X509Extensions.getInstance(null);
- X509Name.getInstance(null);
- X509Name.getInstance(null);
- DHDomainParameters.getInstance(null);
- DHDomainParameters.getInstance(null);
- DHPublicKey.getInstance(null);
- DHPublicKey.getInstance(null);
- DHValidationParms.getInstance(null);
- DHValidationParms.getInstance(null);
- X962Parameters.getInstance(null);
- X962Parameters.getInstance(null);
- X9ECParameters.getInstance(null);
- MQVuserKeyingMaterial.getInstance(null);
- MQVuserKeyingMaterial.getInstance(null);
- CertHash.getInstance(null);
- RequestedCertificate.getInstance(null);
- RequestedCertificate.getInstance(null);
- AdditionalInformationSyntax.getInstance(null);
- Admissions.getInstance(null);
- AdmissionSyntax.getInstance(null);
- DeclarationOfMajority.getInstance(null);
- MonetaryLimit.getInstance(null);
- NamingAuthority.getInstance(null);
- NamingAuthority.getInstance(null);
- ProcurationSyntax.getInstance(null);
- ProfessionInfo.getInstance(null);
- Restriction.getInstance(null);
- BiometricData.getInstance(null);
- Iso4217CurrencyCode.getInstance(null);
- MonetaryValue.getInstance(null);
- QCStatement.getInstance(null);
- SemanticsInformation.getInstance(null);
- TypeOfBiometricData.getInstance(null);
- NameOrPseudonym.getInstance(null);
- PersonalData.getInstance(null);
- }
-
- public String getName()
- {
- return "GetInstanceNullTest";
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/InputStreamTest.java b/core/src/test/java/org/bouncycastle/asn1/test/InputStreamTest.java
deleted file mode 100644
index 819d285f..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/InputStreamTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class InputStreamTest
- extends SimpleTest
-{
- private static final byte[] outOfBoundsLength = new byte[] { (byte)0x30, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff };
- private static final byte[] negativeLength = new byte[] { (byte)0x30, (byte)0x84, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff };
- private static final byte[] outsideLimitLength = new byte[] { (byte)0x30, (byte)0x83, (byte)0x0f, (byte)0xff, (byte)0xff };
-
-
- public String getName()
- {
- return "InputStream";
- }
-
- public void performTest()
- throws Exception
- {
- ASN1InputStream aIn = new ASN1InputStream(outOfBoundsLength);
-
- try
- {
- aIn.readObject();
- fail("out of bounds length not detected.");
- }
- catch (IOException e)
- {
- if (!e.getMessage().startsWith("DER length more than 4 bytes"))
- {
- fail("wrong exception: " + e.getMessage());
- }
- }
-
- aIn = new ASN1InputStream(negativeLength);
-
- try
- {
- aIn.readObject();
- fail("negative length not detected.");
- }
- catch (IOException e)
- {
- if (!e.getMessage().equals("corrupted stream - negative length found"))
- {
- fail("wrong exception: " + e.getMessage());
- }
- }
-
- aIn = new ASN1InputStream(outsideLimitLength);
-
- try
- {
- aIn.readObject();
- fail("outside limit length not detected.");
- }
- catch (IOException e)
- {
- if (!e.getMessage().equals("corrupted stream - out of bounds length found"))
- {
- fail("wrong exception: " + e.getMessage());
- }
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new InputStreamTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/Iso4217CurrencyCodeUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/Iso4217CurrencyCodeUnitTest.java
deleted file mode 100644
index 9a1d6a87..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/Iso4217CurrencyCodeUnitTest.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.x509.qualified.Iso4217CurrencyCode;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class Iso4217CurrencyCodeUnitTest
- extends SimpleTest
-{
- private static final String ALPHABETIC_CURRENCY_CODE = "AUD";
- private static final int NUMERIC_CURRENCY_CODE = 1;
-
- public String getName()
- {
- return "Iso4217CurrencyCode";
- }
-
- public void performTest()
- throws Exception
- {
- //
- // alphabetic
- //
- Iso4217CurrencyCode cc = new Iso4217CurrencyCode(ALPHABETIC_CURRENCY_CODE);
-
- checkNumeric(cc, ALPHABETIC_CURRENCY_CODE);
-
- cc = Iso4217CurrencyCode.getInstance(cc);
-
- checkNumeric(cc, ALPHABETIC_CURRENCY_CODE);
-
- ASN1Primitive obj = cc.toASN1Object();
-
- cc = Iso4217CurrencyCode.getInstance(obj);
-
- checkNumeric(cc, ALPHABETIC_CURRENCY_CODE);
-
- //
- // numeric
- //
- cc = new Iso4217CurrencyCode(NUMERIC_CURRENCY_CODE);
-
- checkNumeric(cc, NUMERIC_CURRENCY_CODE);
-
- cc = Iso4217CurrencyCode.getInstance(cc);
-
- checkNumeric(cc, NUMERIC_CURRENCY_CODE);
-
- obj = cc.toASN1Object();
-
- cc = Iso4217CurrencyCode.getInstance(obj);
-
- checkNumeric(cc, NUMERIC_CURRENCY_CODE);
-
- cc = Iso4217CurrencyCode.getInstance(null);
-
- if (cc != null)
- {
- fail("null getInstance() failed.");
- }
-
- try
- {
- Iso4217CurrencyCode.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- try
- {
- new Iso4217CurrencyCode("ABCD");
-
- fail("constructor failed to detect out of range currencycode.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- try
- {
- new Iso4217CurrencyCode(0);
-
- fail("constructor failed to detect out of range small numeric code.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- try
- {
- new Iso4217CurrencyCode(1000);
-
- fail("constructor failed to detect out of range large numeric code.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkNumeric(
- Iso4217CurrencyCode cc,
- String code)
- {
- if (!cc.isAlphabetic())
- {
- fail("non-alphabetic code found when one expected.");
- }
-
- if (!cc.getAlphabetic().equals(code))
- {
- fail("string codes don't match.");
- }
- }
-
- private void checkNumeric(
- Iso4217CurrencyCode cc,
- int code)
- {
- if (cc.isAlphabetic())
- {
- fail("alphabetic code found when one not expected.");
- }
-
- if (cc.getNumeric() != code)
- {
- fail("numeric codes don't match.");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new Iso4217CurrencyCodeUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/IssuingDistributionPointUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/IssuingDistributionPointUnitTest.java
deleted file mode 100644
index 3f27f191..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/IssuingDistributionPointUnitTest.java
+++ /dev/null
@@ -1,122 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.x509.DistributionPointName;
-import org.bouncycastle.asn1.x509.GeneralName;
-import org.bouncycastle.asn1.x509.GeneralNames;
-import org.bouncycastle.asn1.x509.IssuingDistributionPoint;
-import org.bouncycastle.asn1.x509.ReasonFlags;
-import org.bouncycastle.asn1.x509.X509Name;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class IssuingDistributionPointUnitTest
- extends SimpleTest
-{
- public String getName()
- {
- return "IssuingDistributionPoint";
- }
-
- public void performTest()
- throws Exception
- {
- DistributionPointName name = new DistributionPointName(
- new GeneralNames(new GeneralName(new X509Name("cn=test"))));
- ReasonFlags reasonFlags = new ReasonFlags(ReasonFlags.cACompromise);
-
- checkPoint(6, name, true, true, reasonFlags, true, true);
-
- checkPoint(2, name, false, false, reasonFlags, false, false);
-
- checkPoint(0, null, false, false, null, false, false);
-
- try
- {
- IssuingDistributionPoint.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkPoint(
- int size,
- DistributionPointName distributionPoint,
- boolean onlyContainsUserCerts,
- boolean onlyContainsCACerts,
- ReasonFlags onlySomeReasons,
- boolean indirectCRL,
- boolean onlyContainsAttributeCerts)
- throws IOException
- {
- IssuingDistributionPoint point = new IssuingDistributionPoint(distributionPoint, onlyContainsUserCerts, onlyContainsCACerts, onlySomeReasons, indirectCRL, onlyContainsAttributeCerts);
-
- checkValues(point, distributionPoint, onlyContainsUserCerts, onlyContainsCACerts, onlySomeReasons, indirectCRL, onlyContainsAttributeCerts);
-
- ASN1Sequence seq = ASN1Sequence.getInstance(ASN1Primitive.fromByteArray(point.getEncoded()));
-
- if (seq.size() != size)
- {
- fail("size mismatch");
- }
-
- point = IssuingDistributionPoint.getInstance(seq);
-
- checkValues(point, distributionPoint, onlyContainsUserCerts, onlyContainsCACerts, onlySomeReasons, indirectCRL, onlyContainsAttributeCerts);
- }
-
- private void checkValues(IssuingDistributionPoint point, DistributionPointName distributionPoint, boolean onlyContainsUserCerts, boolean onlyContainsCACerts, ReasonFlags onlySomeReasons, boolean indirectCRL, boolean onlyContainsAttributeCerts)
- {
- if (point.onlyContainsUserCerts() != onlyContainsUserCerts)
- {
- fail("mismatch on onlyContainsUserCerts");
- }
-
- if (point.onlyContainsCACerts() != onlyContainsCACerts)
- {
- fail("mismatch on onlyContainsCACerts");
- }
-
- if (point.isIndirectCRL() != indirectCRL)
- {
- fail("mismatch on indirectCRL");
- }
-
- if (point.onlyContainsAttributeCerts() != onlyContainsAttributeCerts)
- {
- fail("mismatch on onlyContainsAttributeCerts");
- }
-
- if (!isEquiv(onlySomeReasons, point.getOnlySomeReasons()))
- {
- fail("mismatch on onlySomeReasons");
- }
-
- if (!isEquiv(distributionPoint, point.getDistributionPoint()))
- {
- fail("mismatch on distributionPoint");
- }
- }
-
- private boolean isEquiv(Object o1, Object o2)
- {
- if (o1 == null)
- {
- return o2 == null;
- }
-
- return o1.equals(o2);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new IssuingDistributionPointUnitTest());
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/KeyUsageTest.java b/core/src/test/java/org/bouncycastle/asn1/test/KeyUsageTest.java
deleted file mode 100644
index f5c90cd0..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/KeyUsageTest.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.x509.KeyUsage;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class KeyUsageTest
- extends SimpleTest
-{
- public String getName()
- {
- return "KeyUsage";
- }
-
- public void performTest()
- throws IOException
- {
- BitStringConstantTester.testFlagValueCorrect(0, KeyUsage.digitalSignature);
- BitStringConstantTester.testFlagValueCorrect(1, KeyUsage.nonRepudiation);
- BitStringConstantTester.testFlagValueCorrect(2, KeyUsage.keyEncipherment);
- BitStringConstantTester.testFlagValueCorrect(3, KeyUsage.dataEncipherment);
- BitStringConstantTester.testFlagValueCorrect(4, KeyUsage.keyAgreement);
- BitStringConstantTester.testFlagValueCorrect(5, KeyUsage.keyCertSign);
- BitStringConstantTester.testFlagValueCorrect(6, KeyUsage.cRLSign);
- BitStringConstantTester.testFlagValueCorrect(7, KeyUsage.encipherOnly);
- BitStringConstantTester.testFlagValueCorrect(8, KeyUsage.decipherOnly);
-
- if (!new KeyUsage(KeyUsage.keyCertSign).hasUsages(KeyUsage.keyCertSign))
- {
- fail("usages bit test failed 1");
- }
-
- if (new KeyUsage(KeyUsage.cRLSign).hasUsages(KeyUsage.keyCertSign))
- {
- fail("usages bit test failed 2");
- }
-
- if (!new KeyUsage(KeyUsage.cRLSign | KeyUsage.decipherOnly).hasUsages(KeyUsage.cRLSign | KeyUsage.decipherOnly))
- {
- fail("usages bit test failed 3");
- }
-
- if (new KeyUsage(KeyUsage.cRLSign | KeyUsage.decipherOnly).hasUsages(KeyUsage.cRLSign | KeyUsage.decipherOnly | KeyUsage.keyCertSign))
- {
- fail("usages bit test failed 4");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new KeyUsageTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/LDSSecurityObjectUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/LDSSecurityObjectUnitTest.java
deleted file mode 100644
index 3c7cd5fc..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/LDSSecurityObjectUnitTest.java
+++ /dev/null
@@ -1,214 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-import java.util.Random;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.icao.DataGroupHash;
-import org.bouncycastle.asn1.icao.LDSSecurityObject;
-import org.bouncycastle.asn1.icao.LDSVersionInfo;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class LDSSecurityObjectUnitTest
- extends SimpleTest
-{
- public String getName()
- {
- return "LDSSecurityObject";
- }
-
- private byte[] generateHash()
- {
- Random rand = new Random();
- byte[] bytes = new byte[20];
-
- for (int i = 0; i != bytes.length; i++)
- {
- bytes[i] = (byte)rand.nextInt();
- }
-
- return bytes;
- }
-
- public void performTest()
- throws Exception
- {
- AlgorithmIdentifier algoId = new AlgorithmIdentifier("1.3.14.3.2.26");
- DataGroupHash[] datas = new DataGroupHash[2];
-
- datas[0] = new DataGroupHash(1, new DEROctetString(generateHash()));
- datas[1] = new DataGroupHash(2, new DEROctetString(generateHash()));
-
- LDSSecurityObject so = new LDSSecurityObject(algoId, datas);
-
- checkConstruction(so, algoId, datas);
-
- LDSVersionInfo versionInfo = new LDSVersionInfo("Hello", "world");
-
- so = new LDSSecurityObject(algoId, datas, versionInfo);
-
- checkConstruction(so, algoId, datas, versionInfo);
-
- try
- {
- LDSSecurityObject.getInstance(null);
- }
- catch (Exception e)
- {
- fail("getInstance() failed to handle null.");
- }
-
- try
- {
- LDSSecurityObject.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- try
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- LDSSecurityObject.getInstance(new DERSequence(v));
-
- fail("constructor failed to detect empty sequence.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- try
- {
- new LDSSecurityObject(algoId, new DataGroupHash[1]);
-
- fail("constructor failed to detect small DataGroupHash array.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- try
- {
- new LDSSecurityObject(algoId, new DataGroupHash[LDSSecurityObject.ub_DataGroups + 1]);
-
- fail("constructor failed to out of bounds DataGroupHash array.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- LDSSecurityObject so,
- AlgorithmIdentifier digestAlgorithmIdentifier,
- DataGroupHash[] datagroupHash)
- throws IOException
- {
- checkStatement(so, digestAlgorithmIdentifier, datagroupHash, null);
-
- so = LDSSecurityObject.getInstance(so);
-
- checkStatement(so, digestAlgorithmIdentifier, datagroupHash, null);
-
- ASN1InputStream aIn = new ASN1InputStream(so.toASN1Object().getEncoded());
-
- ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
-
- so = LDSSecurityObject.getInstance(seq);
-
- checkStatement(so, digestAlgorithmIdentifier, datagroupHash, null);
- }
-
- private void checkConstruction(
- LDSSecurityObject so,
- AlgorithmIdentifier digestAlgorithmIdentifier,
- DataGroupHash[] datagroupHash,
- LDSVersionInfo versionInfo)
- throws IOException
- {
- if (so.getVersion() != 1)
- {
- fail("version number not 1");
- }
-
- checkStatement(so, digestAlgorithmIdentifier, datagroupHash, versionInfo);
-
- so = LDSSecurityObject.getInstance(so);
-
- checkStatement(so, digestAlgorithmIdentifier, datagroupHash, versionInfo);
-
- ASN1InputStream aIn = new ASN1InputStream(so.toASN1Object().getEncoded());
-
- ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
-
- so = LDSSecurityObject.getInstance(seq);
-
- checkStatement(so, digestAlgorithmIdentifier, datagroupHash, versionInfo);
- }
-
- private void checkStatement(
- LDSSecurityObject so,
- AlgorithmIdentifier digestAlgorithmIdentifier,
- DataGroupHash[] datagroupHash,
- LDSVersionInfo versionInfo)
- {
- if (digestAlgorithmIdentifier != null)
- {
- if (!so.getDigestAlgorithmIdentifier().equals(digestAlgorithmIdentifier))
- {
- fail("ids don't match.");
- }
- }
- else if (so.getDigestAlgorithmIdentifier() != null)
- {
- fail("digest algorithm Id found when none expected.");
- }
-
- if (datagroupHash != null)
- {
- DataGroupHash[] datas = so.getDatagroupHash();
-
- for (int i = 0; i != datas.length; i++)
- {
- if (!datagroupHash[i].equals(datas[i]))
- {
- fail("name registration authorities don't match.");
- }
- }
- }
- else if (so.getDatagroupHash() != null)
- {
- fail("data hash groups found when none expected.");
- }
-
- if (versionInfo != null)
- {
- if (!versionInfo.equals(so.getVersionInfo()))
- {
- fail("versionInfo doesn't match");
- }
- }
- else if (so.getVersionInfo() != null)
- {
- fail("version info found when none expected.");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new LDSSecurityObjectUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/MiscTest.java b/core/src/test/java/org/bouncycastle/asn1/test/MiscTest.java
deleted file mode 100644
index 2a5f09a7..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/MiscTest.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1OutputStream;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.misc.CAST5CBCParameters;
-import org.bouncycastle.asn1.misc.IDEACBCPar;
-import org.bouncycastle.asn1.misc.NetscapeCertType;
-import org.bouncycastle.asn1.misc.NetscapeRevocationURL;
-import org.bouncycastle.asn1.misc.VerisignCzagExtension;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-public class MiscTest
- implements Test
-{
- private boolean isSameAs(
- byte[] a,
- byte[] b)
- {
- if (a.length != b.length)
- {
- return false;
- }
-
- for (int i = 0; i != a.length; i++)
- {
- if (a[i] != b[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- public TestResult perform()
- {
- byte[] testIv = { 1, 2, 3, 4, 5, 6, 7, 8 };
-
- ASN1Encodable[] values = {
- new CAST5CBCParameters(testIv, 128),
- new NetscapeCertType(NetscapeCertType.smime),
- new VerisignCzagExtension(new DERIA5String("hello")),
- new IDEACBCPar(testIv),
- new NetscapeRevocationURL(new DERIA5String("http://test"))
- };
-
- byte[] data = Base64.decode("MA4ECAECAwQFBgcIAgIAgAMCBSAWBWhlbGxvMAoECAECAwQFBgcIFgtodHRwOi8vdGVzdA==");
-
- try
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- ASN1OutputStream aOut = new ASN1OutputStream(bOut);
-
- for (int i = 0; i != values.length; i++)
- {
- aOut.writeObject(values[i]);
- }
-
- ASN1Primitive[] readValues = new ASN1Primitive[values.length];
-
- if (!isSameAs(bOut.toByteArray(), data))
- {
- return new SimpleTestResult(false, getName() + ": Failed data check");
- }
-
- ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
- ASN1InputStream aIn = new ASN1InputStream(bIn);
-
- for (int i = 0; i != values.length; i++)
- {
- ASN1Primitive o = aIn.readObject();
- if (!values[i].equals(o))
- {
- return new SimpleTestResult(false, getName() + ": Failed equality test for " + o);
- }
-
- if (o.hashCode() != values[i].hashCode())
- {
- return new SimpleTestResult(false, getName() + ": Failed hashCode test for " + o);
- }
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
- catch (Exception e)
- {
- return new SimpleTestResult(false, getName() + ": Failed - exception " + e.toString(), e);
- }
- }
-
- public String getName()
- {
- return "Misc";
- }
-
- public static void main(
- String[] args)
- {
- MiscTest test = new MiscTest();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/MonetaryLimitUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/MonetaryLimitUnitTest.java
deleted file mode 100644
index 8456661a..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/MonetaryLimitUnitTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.isismtt.x509.MonetaryLimit;
-
-import java.io.IOException;
-
-public class MonetaryLimitUnitTest
- extends ASN1UnitTest
-{
- public String getName()
- {
- return "MonetaryLimit";
- }
-
- public void performTest()
- throws Exception
- {
- String currency = "AUD";
- int amount = 1;
- int exponent = 2;
-
- MonetaryLimit limit = new MonetaryLimit(currency, amount, exponent);
-
- checkConstruction(limit, currency, amount, exponent);
-
- limit = MonetaryLimit.getInstance(null);
-
- if (limit != null)
- {
- fail("null getInstance() failed.");
- }
-
- try
- {
- MonetaryLimit.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- MonetaryLimit limit,
- String currency,
- int amount,
- int exponent)
- throws IOException
- {
- checkValues(limit, currency, amount, exponent);
-
- limit = MonetaryLimit.getInstance(limit);
-
- checkValues(limit, currency, amount, exponent);
-
- ASN1InputStream aIn = new ASN1InputStream(limit.toASN1Object().getEncoded());
-
- ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
-
- limit = MonetaryLimit.getInstance(seq);
-
- checkValues(limit, currency, amount, exponent);
- }
-
- private void checkValues(
- MonetaryLimit limit,
- String currency,
- int amount,
- int exponent)
- {
- checkMandatoryField("currency", currency, limit.getCurrency());
- checkMandatoryField("amount", amount, limit.getAmount().intValue());
- checkMandatoryField("exponent", exponent, limit.getExponent().intValue());
- }
-
- public static void main(
- String[] args)
- {
- runTest(new MonetaryLimitUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/MonetaryValueUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/MonetaryValueUnitTest.java
deleted file mode 100644
index dd564693..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/MonetaryValueUnitTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.x509.qualified.Iso4217CurrencyCode;
-import org.bouncycastle.asn1.x509.qualified.MonetaryValue;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class MonetaryValueUnitTest
- extends SimpleTest
-{
- private static final int TEST_AMOUNT = 100;
- private static final int ZERO_EXPONENT = 0;
-
- private static final String CURRENCY_CODE = "AUD";
-
- public String getName()
- {
- return "MonetaryValue";
- }
-
- public void performTest()
- throws Exception
- {
- MonetaryValue mv = new MonetaryValue(new Iso4217CurrencyCode(CURRENCY_CODE), TEST_AMOUNT, ZERO_EXPONENT);
-
- checkValues(mv, TEST_AMOUNT, ZERO_EXPONENT);
-
- mv = MonetaryValue.getInstance(mv);
-
- checkValues(mv, TEST_AMOUNT, ZERO_EXPONENT);
-
- ASN1InputStream aIn = new ASN1InputStream(mv.toASN1Object().getEncoded());
-
- ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
-
- mv = MonetaryValue.getInstance(seq);
-
- checkValues(mv, TEST_AMOUNT, ZERO_EXPONENT);
-
- mv = MonetaryValue.getInstance(null);
-
- if (mv != null)
- {
- fail("null getInstance() failed.");
- }
-
- try
- {
- MonetaryValue.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkValues(
- MonetaryValue mv,
- int amount,
- int exponent)
- {
- if (mv.getAmount().intValue() != amount)
- {
- fail("amounts don't match.");
- }
-
- if (mv.getExponent().intValue() != exponent)
- {
- fail("exponents don't match.");
- }
-
- Iso4217CurrencyCode cc = mv.getCurrency();
-
- if (!cc.getAlphabetic().equals(CURRENCY_CODE))
- {
- fail("currency code wrong");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new MonetaryValueUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/NameOrPseudonymUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/NameOrPseudonymUnitTest.java
deleted file mode 100644
index 3fbaa10a..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/NameOrPseudonymUnitTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1String;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x500.DirectoryString;
-import org.bouncycastle.asn1.x509.sigi.NameOrPseudonym;
-
-public class NameOrPseudonymUnitTest
- extends ASN1UnitTest
-{
- public String getName()
- {
- return "NameOrPseudonym";
- }
-
- public void performTest()
- throws Exception
- {
- String pseudonym = "pseudonym";
- DirectoryString surname = new DirectoryString("surname");
- ASN1Sequence givenName = new DERSequence(new DirectoryString("givenName"));
-
- NameOrPseudonym id = new NameOrPseudonym(pseudonym);
-
- checkConstruction(id, pseudonym, null, null);
-
- id = new NameOrPseudonym(surname, givenName);
-
- checkConstruction(id, null, surname, givenName);
-
- id = NameOrPseudonym.getInstance(null);
-
- if (id != null)
- {
- fail("null getInstance() failed.");
- }
-
- try
- {
- NameOrPseudonym.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- NameOrPseudonym id,
- String pseudonym,
- DirectoryString surname,
- ASN1Sequence givenName)
- throws IOException
- {
- checkValues(id, pseudonym, surname, givenName);
-
- id = NameOrPseudonym.getInstance(id);
-
- checkValues(id, pseudonym, surname, givenName);
-
- ASN1InputStream aIn = new ASN1InputStream(id.toASN1Object().getEncoded());
-
- if (surname != null)
- {
- ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
-
- id = NameOrPseudonym.getInstance(seq);
- }
- else
- {
- ASN1String s = (ASN1String)aIn.readObject();
-
- id = NameOrPseudonym.getInstance(s);
- }
-
- checkValues(id, pseudonym, surname, givenName);
- }
-
- private void checkValues(
- NameOrPseudonym id,
- String pseudonym,
- DirectoryString surname,
- ASN1Sequence givenName)
- {
-
- if (surname != null)
- {
- checkMandatoryField("surname", surname, id.getSurname());
- checkMandatoryField("givenName", givenName, new DERSequence(id.getGivenName()[0]));
- }
- else
- {
- checkOptionalField("pseudonym", new DirectoryString(pseudonym), id.getPseudonym());
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new NameOrPseudonymUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/NamingAuthorityUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/NamingAuthorityUnitTest.java
deleted file mode 100644
index 8dfcf8cd..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/NamingAuthorityUnitTest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.isismtt.x509.NamingAuthority;
-import org.bouncycastle.asn1.x500.DirectoryString;
-
-public class NamingAuthorityUnitTest
- extends ASN1UnitTest
-{
- public String getName()
- {
- return "NamingAuthority";
- }
-
- public void performTest()
- throws Exception
- {
- ASN1ObjectIdentifier namingAuthorityID = new ASN1ObjectIdentifier("1.2.3");
- String namingAuthorityURL = "url";
- DirectoryString namingAuthorityText = new DirectoryString("text");
-
- NamingAuthority auth = new NamingAuthority(namingAuthorityID, namingAuthorityURL, namingAuthorityText);
-
- checkConstruction(auth, namingAuthorityID, namingAuthorityURL, namingAuthorityText);
-
- auth = new NamingAuthority(null, namingAuthorityURL, namingAuthorityText);
-
- checkConstruction(auth, null, namingAuthorityURL, namingAuthorityText);
-
- auth = new NamingAuthority(namingAuthorityID, null, namingAuthorityText);
-
- checkConstruction(auth, namingAuthorityID, null, namingAuthorityText);
-
- auth = new NamingAuthority(namingAuthorityID, namingAuthorityURL, null);
-
- checkConstruction(auth, namingAuthorityID, namingAuthorityURL, null);
-
- auth = NamingAuthority.getInstance(null);
-
- if (auth != null)
- {
- fail("null getInstance() failed.");
- }
-
- try
- {
- NamingAuthority.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- NamingAuthority auth,
- ASN1ObjectIdentifier namingAuthorityID,
- String namingAuthorityURL,
- DirectoryString namingAuthorityText)
- throws IOException
- {
- checkValues(auth, namingAuthorityID, namingAuthorityURL, namingAuthorityText);
-
- auth = NamingAuthority.getInstance(auth);
-
- checkValues(auth, namingAuthorityID, namingAuthorityURL, namingAuthorityText);
-
- ASN1InputStream aIn = new ASN1InputStream(auth.toASN1Object().getEncoded());
-
- ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
-
- auth = NamingAuthority.getInstance(seq);
-
- checkValues(auth, namingAuthorityID, namingAuthorityURL, namingAuthorityText);
- }
-
- private void checkValues(
- NamingAuthority auth,
- ASN1ObjectIdentifier namingAuthorityId,
- String namingAuthorityURL,
- DirectoryString namingAuthorityText)
- {
- checkOptionalField("namingAuthorityId", namingAuthorityId, auth.getNamingAuthorityId());
- checkOptionalField("namingAuthorityURL", namingAuthorityURL, auth.getNamingAuthorityUrl());
- checkOptionalField("namingAuthorityText", namingAuthorityText, auth.getNamingAuthorityText());
- }
-
- public static void main(
- String[] args)
- {
- runTest(new NamingAuthorityUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/NetscapeCertTypeTest.java b/core/src/test/java/org/bouncycastle/asn1/test/NetscapeCertTypeTest.java
deleted file mode 100644
index e5aa96ec..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/NetscapeCertTypeTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.misc.NetscapeCertType;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class NetscapeCertTypeTest
- extends SimpleTest
-{
- public String getName()
- {
- return "NetscapeCertType";
- }
-
- public void performTest()
- throws IOException
- {
- BitStringConstantTester.testFlagValueCorrect(0, NetscapeCertType.sslClient);
- BitStringConstantTester.testFlagValueCorrect(1, NetscapeCertType.sslServer);
- BitStringConstantTester.testFlagValueCorrect(2, NetscapeCertType.smime);
- BitStringConstantTester.testFlagValueCorrect(3, NetscapeCertType.objectSigning);
- BitStringConstantTester.testFlagValueCorrect(4, NetscapeCertType.reserved);
- BitStringConstantTester.testFlagValueCorrect(5, NetscapeCertType.sslCA);
- BitStringConstantTester.testFlagValueCorrect(6, NetscapeCertType.smimeCA);
- BitStringConstantTester.testFlagValueCorrect(7, NetscapeCertType.objectSigningCA);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new NetscapeCertTypeTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/OCSPTest.java b/core/src/test/java/org/bouncycastle/asn1/test/OCSPTest.java
deleted file mode 100644
index ae1b035a..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/OCSPTest.java
+++ /dev/null
@@ -1,193 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.ByteArrayInputStream;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.ocsp.BasicOCSPResponse;
-import org.bouncycastle.asn1.ocsp.OCSPRequest;
-import org.bouncycastle.asn1.ocsp.OCSPResponse;
-import org.bouncycastle.asn1.ocsp.ResponseBytes;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-import org.bouncycastle.util.test.SimpleTestResult;
-
-public class OCSPTest
- implements Test
-{
- private byte[] unsignedReq = Base64.decode(
- "MEIwQDA+MDwwOjAJBgUrDgMCGgUABBRDb9GODnq7lRhSkEqw4XX24huERwQUkY4j"
- + "a6eKuDlkVP9hRgkEvIWqHPECAQE=");
-
- private byte[] signedReq = Base64.decode(
- "MIIC9jBAMD4wPDA6MAkGBSsOAwIaBQAEFENv0Y4OeruVGFKQSrDhdfbiG4RHBBTc"
- + "Mr1fP+mZAxbF2ZdehWxn6mtAngIBAaCCArAwggKsMA0GCSqGSIb3DQEBBQUAA4GB"
- + "AAzHBm4nL5AcRQB3Jkz7ScNeZF+GbRZ0p4kBDTnqi3IeESuso12yJhpqqyijdnj5"
- + "gd4/GsSAgdluLHyYZ6wgozV7G9MDXCnFnG4PBUW05HaVX81JYAp+amVyU0NOgNrG"
- + "90npVBsHb0o+UlkxNgMiEbSkp/TeGb6YURsYKhmwp7BgoIICFTCCAhEwggINMIIB"
- + "dqADAgECAgEBMA0GCSqGSIb3DQEBBAUAMCUxFjAUBgNVBAoTDUJvdW5jeSBDYXN0"
- + "bGUxCzAJBgNVBAYTAkFVMB4XDTA0MTAyNDEzNDc0M1oXDTA1MDIwMTEzNDc0M1ow"
- + "JTEWMBQGA1UEChMNQm91bmN5IENhc3RsZTELMAkGA1UEBhMCQVUwgZ8wDQYJKoZI"
- + "hvcNAQEBBQADgY0AMIGJAoGBAJBmLeIzthMHUeTkOeJ76iBxcMHY31o/i3a9VT12"
- + "y2FcS/ejJmeUCMTdtwl5alOwXY66vF4DyT1VU/nJG3mHpSoqq7qrMXOIFGcXg1Wf"
- + "oJRrQgTOLdQ6bod7i9ME/EjEJy70orh0nVS7NGcu0R5TjcbLde2J5zxjb/W9wqfy"
- + "RovJAgMBAAGjTTBLMB0GA1UdDgQWBBTcMr1fP+mZAxbF2ZdehWxn6mtAnjAfBgNV"
- + "HSMEGDAWgBTcMr1fP+mZAxbF2ZdehWxn6mtAnjAJBgNVHRMEAjAAMA0GCSqGSIb3"
- + "DQEBBAUAA4GBAF/4EH1KkNrNxocJPIp7lThmG1KIVYESIadowMowrbok46ESofRF"
- + "OIPku07W+e1Y1Y1KXLIiPMG3IGwrBrn04iLsbbBUiN37BcC/VyT4xKJ2MYscGjKL"
- + "ua/9bU0lOyeTRAwqb8towWRd5lLYAI3RQ7dhStUTFp3Vqd803PJ/cpR6");
-
- private byte[] response = Base64.decode(
- "MIIFnAoBAKCCBZUwggWRBgkrBgEFBQcwAQEEggWCMIIFfjCCARehgZ8wgZwx"
- + "CzAJBgNVBAYTAklOMRcwFQYDVQQIEw5BbmRocmEgcHJhZGVzaDESMBAGA1UE"
- + "BxMJSHlkZXJhYmFkMQwwCgYDVQQKEwNUQ1MxDDAKBgNVBAsTA0FUQzEeMBwG"
- + "A1UEAxMVVENTLUNBIE9DU1AgUmVzcG9uZGVyMSQwIgYJKoZIhvcNAQkBFhVv"
- + "Y3NwQHRjcy1jYS50Y3MuY28uaW4YDzIwMDMwNDAyMTIzNDU4WjBiMGAwOjAJ"
- + "BgUrDgMCGgUABBRs07IuoCWNmcEl1oHwIak1BPnX8QQUtGyl/iL9WJ1VxjxF"
- + "j0hAwJ/s1AcCAQKhERgPMjAwMjA4MjkwNzA5MjZaGA8yMDAzMDQwMjEyMzQ1"
- + "OFowDQYJKoZIhvcNAQEFBQADgYEAfbN0TCRFKdhsmvOdUoiJ+qvygGBzDxD/"
- + "VWhXYA+16AphHLIWNABR3CgHB3zWtdy2j7DJmQ/R7qKj7dUhWLSqclAiPgFt"
- + "QQ1YvSJAYfEIdyHkxv4NP0LSogxrumANcDyC9yt/W9yHjD2ICPBIqCsZLuLk"
- + "OHYi5DlwWe9Zm9VFwCGgggPMMIIDyDCCA8QwggKsoAMCAQICAQYwDQYJKoZI"
- + "hvcNAQEFBQAwgZQxFDASBgNVBAMTC1RDUy1DQSBPQ1NQMSYwJAYJKoZIhvcN"
- + "AQkBFhd0Y3MtY2FAdGNzLWNhLnRjcy5jby5pbjEMMAoGA1UEChMDVENTMQww"
- + "CgYDVQQLEwNBVEMxEjAQBgNVBAcTCUh5ZGVyYWJhZDEXMBUGA1UECBMOQW5k"
- + "aHJhIHByYWRlc2gxCzAJBgNVBAYTAklOMB4XDTAyMDgyOTA3MTE0M1oXDTAz"
- + "MDgyOTA3MTE0M1owgZwxCzAJBgNVBAYTAklOMRcwFQYDVQQIEw5BbmRocmEg"
- + "cHJhZGVzaDESMBAGA1UEBxMJSHlkZXJhYmFkMQwwCgYDVQQKEwNUQ1MxDDAK"
- + "BgNVBAsTA0FUQzEeMBwGA1UEAxMVVENTLUNBIE9DU1AgUmVzcG9uZGVyMSQw"
- + "IgYJKoZIhvcNAQkBFhVvY3NwQHRjcy1jYS50Y3MuY28uaW4wgZ8wDQYJKoZI"
- + "hvcNAQEBBQADgY0AMIGJAoGBAM+XWW4caMRv46D7L6Bv8iwtKgmQu0SAybmF"
- + "RJiz12qXzdvTLt8C75OdgmUomxp0+gW/4XlTPUqOMQWv463aZRv9Ust4f8MH"
- + "EJh4ekP/NS9+d8vEO3P40ntQkmSMcFmtA9E1koUtQ3MSJlcs441JjbgUaVnm"
- + "jDmmniQnZY4bU3tVAgMBAAGjgZowgZcwDAYDVR0TAQH/BAIwADALBgNVHQ8E"
- + "BAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwkwNgYIKwYBBQUHAQEEKjAoMCYG"
- + "CCsGAQUFBzABhhpodHRwOi8vMTcyLjE5LjQwLjExMDo3NzAwLzAtBgNVHR8E"
- + "JjAkMCKgIKAehhxodHRwOi8vMTcyLjE5LjQwLjExMC9jcmwuY3JsMA0GCSqG"
- + "SIb3DQEBBQUAA4IBAQB6FovM3B4VDDZ15o12gnADZsIk9fTAczLlcrmXLNN4"
- + "PgmqgnwF0Ymj3bD5SavDOXxbA65AZJ7rBNAguLUo+xVkgxmoBH7R2sBxjTCc"
- + "r07NEadxM3HQkt0aX5XYEl8eRoifwqYAI9h0ziZfTNes8elNfb3DoPPjqq6V"
- + "mMg0f0iMS4W8LjNPorjRB+kIosa1deAGPhq0eJ8yr0/s2QR2/WFD5P4aXc8I"
- + "KWleklnIImS3zqiPrq6tl2Bm8DZj7vXlTOwmraSQxUwzCKwYob1yGvNOUQTq"
- + "pG6jxn7jgDawHU1+WjWQe4Q34/pWeGLysxTraMa+Ug9kPe+jy/qRX2xwvKBZ");
-
- private boolean isSameAs(
- byte[] a,
- byte[] b)
- {
- if (a.length != b.length)
- {
- return false;
- }
-
- for (int i = 0; i != a.length; i++)
- {
- if (a[i] != b[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- private TestResult unsignedRequest()
- {
- try
- {
- ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(unsignedReq));
- OCSPRequest req = OCSPRequest.getInstance(aIn.readObject());
-
- if (!isSameAs(req.getEncoded(), unsignedReq))
- {
- return new SimpleTestResult(false, getName() + ": OCSP unsigned request failed to re-encode");
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
- catch (Exception e)
- {
- return new SimpleTestResult(false, getName() + ": failed unsigned exception - " + e.toString(), e);
- }
- }
-
- private TestResult signedRequest()
- {
- try
- {
- ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(signedReq));
- OCSPRequest req = OCSPRequest.getInstance(aIn.readObject());
-
- if (!isSameAs(req.getEncoded(), signedReq))
- {
- return new SimpleTestResult(false, getName() + ": OCSP signed request failed to re-encode");
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
- catch (Exception e)
- {
- return new SimpleTestResult(false, getName() + ": failed signed exception - " + e.toString(), e);
- }
- }
-
- private TestResult response()
- {
- try
- {
- ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(response));
- OCSPResponse resp = OCSPResponse.getInstance(aIn.readObject());
- ResponseBytes rBytes = ResponseBytes.getInstance(resp.getResponseBytes());
-
- aIn = new ASN1InputStream(new ByteArrayInputStream(rBytes.getResponse().getOctets()));
-
- BasicOCSPResponse bResp = BasicOCSPResponse.getInstance(aIn.readObject());
-
- resp = new OCSPResponse(resp.getResponseStatus(), new ResponseBytes(rBytes.getResponseType(), new DEROctetString(bResp.getEncoded())));
-
- if (!isSameAs(resp.getEncoded(), response))
- {
- return new SimpleTestResult(false, getName() + ": OCSP response failed to re-encode");
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
- catch (Exception e)
- {
- return new SimpleTestResult(false, getName() + ": failed response exception - " + e.toString(), e);
- }
- }
-
- public TestResult perform()
- {
- TestResult res = unsignedRequest();
-
- if (!res.isSuccessful())
- {
- return res;
- }
-
- res = signedRequest();
- if (!res.isSuccessful())
- {
- return res;
- }
-
- return response();
- }
-
- public String getName()
- {
- return "OCSP";
- }
-
- public static void main(
- String[] args)
- {
- OCSPTest test = new OCSPTest();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/OIDTest.java b/core/src/test/java/org/bouncycastle/asn1/test/OIDTest.java
deleted file mode 100644
index fa5aa61b..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/OIDTest.java
+++ /dev/null
@@ -1,165 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OutputStream;
-import org.bouncycastle.asn1.DEROutputStream;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-
-/**
- * X.690 test example
- */
-public class OIDTest
- extends SimpleTest
-{
- byte[] req1 = Hex.decode("0603813403");
- byte[] req2 = Hex.decode("06082A36FFFFFFDD6311");
-
- public String getName()
- {
- return "OID";
- }
-
- private void recodeCheck(
- String oid,
- byte[] enc)
- throws IOException
- {
- ByteArrayInputStream bIn = new ByteArrayInputStream(enc);
- ASN1InputStream aIn = new ASN1InputStream(bIn);
-
- ASN1ObjectIdentifier o = new ASN1ObjectIdentifier(oid);
- ASN1ObjectIdentifier encO = (ASN1ObjectIdentifier)aIn.readObject();
-
- if (!o.equals(encO))
- {
- fail("oid ID didn't match", o, encO);
- }
-
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- DEROutputStream dOut = new DEROutputStream(bOut);
-
- dOut.writeObject(o);
-
- byte[] bytes = bOut.toByteArray();
-
- if (bytes.length != enc.length)
- {
- fail("failed length test");
- }
-
- for (int i = 0; i != enc.length; i++)
- {
- if (bytes[i] != enc[i])
- {
- fail("failed comparison test", new String(Hex.encode(enc)), new String(Hex.encode(bytes)));
- }
- }
- }
-
- private void validOidCheck(
- String oid)
- throws IOException
- {
- ASN1ObjectIdentifier o = new ASN1ObjectIdentifier(oid);
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- ASN1OutputStream aOut = new ASN1OutputStream(bOut);
-
- aOut.writeObject(o);
-
- ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
- ASN1InputStream aIn = new ASN1InputStream(bIn);
-
- o = (ASN1ObjectIdentifier)aIn.readObject();
-
- if (!o.getId().equals(oid))
- {
- fail("failed oid check for " + oid);
- }
- }
-
- private void invalidOidCheck(
- String oid)
- {
- try
- {
- new ASN1ObjectIdentifier(oid);
- fail("failed to catch bad oid: " + oid);
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void branchCheck(String stem, String branch)
- {
- String expected = stem + "." + branch;
- String actual = new ASN1ObjectIdentifier(stem).branch(branch).getId();
-
- if (!expected.equals(actual))
- {
- fail("failed 'branch' check for " + stem + "/" + branch);
- }
- }
-
- private void onCheck(String stem, String test, boolean expected)
- {
- if (expected != new ASN1ObjectIdentifier(test).on(new ASN1ObjectIdentifier(stem)))
- {
- fail("failed 'on' check for " + stem + "/" + test);
- }
- }
-
- public void performTest()
- throws IOException
- {
- recodeCheck("2.100.3", req1);
- recodeCheck("1.2.54.34359733987.17", req2);
-
- validOidCheck(PKCSObjectIdentifiers.pkcs_9_at_contentType.getId());
- validOidCheck("0.1");
- validOidCheck("1.1.127.32512.8323072.2130706432.545460846592.139637976727552.35747322042253312.9151314442816847872");
- validOidCheck("1.2.123.12345678901.1.1.1");
- validOidCheck("2.25.196556539987194312349856245628873852187.1");
-
- invalidOidCheck("0");
- invalidOidCheck("1");
- invalidOidCheck("2");
- invalidOidCheck("3.1");
- invalidOidCheck("..1");
- invalidOidCheck("192.168.1.1");
- invalidOidCheck(".123452");
- invalidOidCheck("1.");
- invalidOidCheck("1.345.23.34..234");
- invalidOidCheck("1.345.23.34.234.");
- invalidOidCheck(".12.345.77.234");
- invalidOidCheck(".12.345.77.234.");
- invalidOidCheck("1.2.3.4.A.5");
- invalidOidCheck("1,2");
-
- branchCheck("1.1", "2.2");
-
- onCheck("1.1", "1.1", false);
- onCheck("1.1", "1.2", false);
- onCheck("1.1", "1.2.1", false);
- onCheck("1.1", "2.1", false);
- onCheck("1.1", "1.11", false);
- onCheck("1.12", "1.1.2", false);
- onCheck("1.1", "1.1.1", true);
- onCheck("1.1", "1.1.2", true);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new OIDTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/ObjectIdentifierTest.java b/core/src/test/java/org/bouncycastle/asn1/test/ObjectIdentifierTest.java
deleted file mode 100644
index bd665ecd..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/ObjectIdentifierTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.util.test.SimpleTest;
-import org.bouncycastle.util.test.TestResult;
-
-public class ObjectIdentifierTest
- extends SimpleTest
-{
- public String getName()
- {
- return "ObjectIdentifier";
- }
-
- public void performTest()
- throws Exception
- {
- // exercise the object cache
- for (int i = 0; i < 1024; i++)
- {
- for (int j = 0; j != 17000; j++)
- {
- byte[] encoded = new ASN1ObjectIdentifier("1.1." + i + "." + j).getEncoded();
-
- ASN1ObjectIdentifier.getInstance(encoded);
- }
- }
- }
-
- public static void main(
- String[] args)
- {
- ObjectIdentifierTest test = new ObjectIdentifierTest();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/OctetStringTest.java b/core/src/test/java/org/bouncycastle/asn1/test/OctetStringTest.java
deleted file mode 100644
index 68ed5da5..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/OctetStringTest.java
+++ /dev/null
@@ -1,203 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetStringParser;
-import org.bouncycastle.asn1.ASN1SequenceParser;
-import org.bouncycastle.asn1.ASN1StreamParser;
-import org.bouncycastle.asn1.BEROctetStringGenerator;
-import org.bouncycastle.asn1.BERSequenceGenerator;
-import org.bouncycastle.asn1.BERTags;
-import org.bouncycastle.asn1.DERSequenceGenerator;
-import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
-import org.bouncycastle.asn1.cms.CompressedDataParser;
-import org.bouncycastle.asn1.cms.ContentInfoParser;
-
-public class OctetStringTest
- extends TestCase
-{
- public void testReadingWriting()
- throws Exception
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- BEROctetStringGenerator octGen = new BEROctetStringGenerator(bOut);
-
- OutputStream out = octGen.getOctetOutputStream();
-
- out.write(new byte[] { 1, 2, 3, 4 });
- out.write(new byte[4]);
-
- out.close();
-
- ASN1StreamParser aIn = new ASN1StreamParser(bOut.toByteArray());
-
- ASN1OctetStringParser s = (ASN1OctetStringParser)aIn.readObject();
-
- InputStream in = s.getOctetStream();
- int count = 0;
-
- while (in.read() >= 0)
- {
- count++;
- }
-
- assertEquals(8, count);
- }
-
- public void testReadingWritingZeroInLength()
- throws Exception
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- BEROctetStringGenerator octGen = new BEROctetStringGenerator(bOut);
-
- OutputStream out = octGen.getOctetOutputStream();
-
- out.write(new byte[] { 1, 2, 3, 4 });
- out.write(new byte[512]); // forces a zero to appear in length
-
- out.close();
-
- ASN1StreamParser aIn = new ASN1StreamParser(bOut.toByteArray());
-
- ASN1OctetStringParser s = (ASN1OctetStringParser)aIn.readObject();
-
- InputStream in = s.getOctetStream();
- int count = 0;
-
- while (in.read() >= 0)
- {
- count++;
- }
-
- assertEquals(516, count);
- }
-
- public void testReadingWritingNested()
- throws Exception
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- BERSequenceGenerator sGen = new BERSequenceGenerator(bOut);
- BEROctetStringGenerator octGen = new BEROctetStringGenerator(sGen.getRawOutputStream());
-
- OutputStream out = octGen.getOctetOutputStream();
-
- BERSequenceGenerator inSGen = new BERSequenceGenerator(out);
-
- BEROctetStringGenerator inOctGen = new BEROctetStringGenerator(inSGen.getRawOutputStream());
-
- OutputStream inOut = inOctGen.getOctetOutputStream();
-
- inOut.write(new byte[] { 1, 2, 3, 4 });
- inOut.write(new byte[10]);
-
- inOut.close();
-
- inSGen.close();
-
- out.close();
-
- sGen.close();
-
- ASN1StreamParser aIn = new ASN1StreamParser(bOut.toByteArray());
-
- ASN1SequenceParser sq = (ASN1SequenceParser)aIn.readObject();
-
- ASN1OctetStringParser s = (ASN1OctetStringParser)sq.readObject();
-
- ASN1StreamParser aIn2 = new ASN1StreamParser(s.getOctetStream());
-
- ASN1SequenceParser sq2 = (ASN1SequenceParser)aIn2.readObject();
-
- ASN1OctetStringParser inS = (ASN1OctetStringParser)sq2.readObject();
-
- InputStream in = inS.getOctetStream();
- int count = 0;
-
- while (in.read() >= 0)
- {
- count++;
- }
-
- assertEquals(14, count);
- }
-
- public void testNestedStructure()
- throws Exception
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- BERSequenceGenerator sGen = new BERSequenceGenerator(bOut);
-
- sGen.addObject(new ASN1ObjectIdentifier(CMSObjectIdentifiers.compressedData.getId()));
-
- BERSequenceGenerator cGen = new BERSequenceGenerator(sGen.getRawOutputStream(), 0, true);
-
- cGen.addObject(new ASN1Integer(0));
-
- //
- // AlgorithmIdentifier
- //
- DERSequenceGenerator algGen = new DERSequenceGenerator(cGen.getRawOutputStream());
-
- algGen.addObject(new ASN1ObjectIdentifier("1.2"));
-
- algGen.close();
-
- //
- // Encapsulated ContentInfo
- //
- BERSequenceGenerator eiGen = new BERSequenceGenerator(cGen.getRawOutputStream());
-
- eiGen.addObject(new ASN1ObjectIdentifier("1.1"));
-
- BEROctetStringGenerator octGen = new BEROctetStringGenerator(eiGen.getRawOutputStream(), 0, true);
-
- //
- // output containing zeroes
- //
- OutputStream out = octGen.getOctetOutputStream();
-
- out.write(new byte[] { 1, 2, 3, 4 });
- out.write(new byte[4]);
- out.write(new byte[20]);
-
- out.close();
- eiGen.close();
- cGen.close();
- sGen.close();
-
- //
- // reading back
- //
- ASN1StreamParser aIn = new ASN1StreamParser(bOut.toByteArray());
-
- ContentInfoParser cp = new ContentInfoParser((ASN1SequenceParser)aIn.readObject());
-
- CompressedDataParser comData = new CompressedDataParser((ASN1SequenceParser)cp.getContent(BERTags.SEQUENCE));
- ContentInfoParser content = comData.getEncapContentInfo();
-
- ASN1OctetStringParser bytes = (ASN1OctetStringParser)content.getContent(BERTags.OCTET_STRING);
-
- InputStream in = bytes.getOctetStream();
- int count = 0;
-
- while (in.read() >= 0)
- {
- count++;
- }
-
- assertEquals(28, count);
- }
-
- public static Test suite()
- {
- return new TestSuite(OctetStringTest.class);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/OtherCertIDUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/OtherCertIDUnitTest.java
deleted file mode 100644
index 9a85ceac..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/OtherCertIDUnitTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ess.OtherCertID;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.GeneralName;
-import org.bouncycastle.asn1.x509.GeneralNames;
-import org.bouncycastle.asn1.x509.IssuerSerial;
-import org.bouncycastle.asn1.x509.X509Name;
-
-public class OtherCertIDUnitTest
- extends ASN1UnitTest
-{
- public String getName()
- {
- return "OtherCertID";
- }
-
- public void performTest()
- throws Exception
- {
- AlgorithmIdentifier algId = new AlgorithmIdentifier(new ASN1ObjectIdentifier("1.2.2.3"));
- byte[] digest = new byte[20];
- IssuerSerial issuerSerial = new IssuerSerial(new GeneralNames(new GeneralName(new X509Name("CN=test"))), new ASN1Integer(1));
-
- OtherCertID certID = new OtherCertID(algId, digest);
-
- checkConstruction(certID, algId, digest, null);
-
- certID = new OtherCertID(algId, digest, issuerSerial);
-
- checkConstruction(certID, algId, digest, issuerSerial);
-
- certID = OtherCertID.getInstance(null);
-
- if (certID != null)
- {
- fail("null getInstance() failed.");
- }
-
- try
- {
- OtherCertID.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- OtherCertID certID,
- AlgorithmIdentifier algId,
- byte[] digest,
- IssuerSerial issuerSerial)
- throws IOException
- {
- checkValues(certID, algId, digest, issuerSerial);
-
- certID = OtherCertID.getInstance(certID);
-
- checkValues(certID, algId, digest, issuerSerial);
-
- ASN1InputStream aIn = new ASN1InputStream(certID.toASN1Object().getEncoded());
-
- ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
-
- certID = OtherCertID.getInstance(seq);
-
- checkValues(certID, algId, digest, issuerSerial);
- }
-
- private void checkValues(
- OtherCertID certID,
- AlgorithmIdentifier algId,
- byte[] digest,
- IssuerSerial issuerSerial)
- {
- checkMandatoryField("algorithmHash", algId, certID.getAlgorithmHash());
- checkMandatoryField("certHash", digest, certID.getCertHash());
-
- checkOptionalField("issuerSerial", issuerSerial, certID.getIssuerSerial());
- }
-
- public static void main(
- String[] args)
- {
- runTest(new OtherCertIDUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/OtherSigningCertificateUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/OtherSigningCertificateUnitTest.java
deleted file mode 100644
index 9de12ee8..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/OtherSigningCertificateUnitTest.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ess.OtherCertID;
-import org.bouncycastle.asn1.ess.OtherSigningCertificate;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-public class OtherSigningCertificateUnitTest
- extends ASN1UnitTest
-{
- public String getName()
- {
- return "OtherSigningCertificate";
- }
-
- public void performTest()
- throws Exception
- {
- AlgorithmIdentifier algId = new AlgorithmIdentifier(new ASN1ObjectIdentifier("1.2.2.3"));
- byte[] digest = new byte[20];
- OtherCertID otherCertID = new OtherCertID(algId, digest);
-
- OtherSigningCertificate otherCert = new OtherSigningCertificate(otherCertID);
-
- checkConstruction(otherCert, otherCertID);
-
- otherCert = OtherSigningCertificate.getInstance(null);
-
- if (otherCert != null)
- {
- fail("null getInstance() failed.");
- }
-
- try
- {
- OtherCertID.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- OtherSigningCertificate otherCert,
- OtherCertID otherCertID)
- throws IOException
- {
- checkValues(otherCert, otherCertID);
-
- otherCert = OtherSigningCertificate.getInstance(otherCert);
-
- checkValues(otherCert, otherCertID);
-
- ASN1InputStream aIn = new ASN1InputStream(otherCert.toASN1Object().getEncoded());
-
- ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
-
- otherCert = OtherSigningCertificate.getInstance(seq);
-
- checkValues(otherCert, otherCertID);
- }
-
- private void checkValues(
- OtherSigningCertificate otherCert,
- OtherCertID otherCertID)
- {
- if (otherCert.getCerts().length != 1)
- {
- fail("getCerts() length wrong");
- }
- checkMandatoryField("getCerts()[0]", otherCertID, otherCert.getCerts()[0]);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new OtherSigningCertificateUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/PKCS10Test.java b/core/src/test/java/org/bouncycastle/asn1/test/PKCS10Test.java
deleted file mode 100644
index da6571d2..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/PKCS10Test.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEROutputStream;
-import org.bouncycastle.asn1.pkcs.CertificationRequest;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-public class PKCS10Test
- implements Test
-{
- byte[] req1 = Base64.decode(
- "MIHoMIGTAgEAMC4xDjAMBgNVBAMTBVRlc3QyMQ8wDQYDVQQKEwZBbmFUb20xCzAJBgNVBAYTAlNF"
- + "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALlEt31Tzt2MlcOljvacJgzQVhmlMoqAOgqJ9Pgd3Gux"
- + "Z7/WcIlgW4QCB7WZT21O1YoghwBhPDMcNGrHei9kHQkCAwEAAaAAMA0GCSqGSIb3DQEBBQUAA0EA"
- + "NDEI4ecNtJ3uHwGGlitNFq9WxcoZ0djbQJ5hABMotav6gtqlrwKXY2evaIrsNwkJtNdwwH18aQDU"
- + "KCjOuBL38Q==");
-
- byte[] req2 = Base64.decode(
- "MIIB6TCCAVICAQAwgagxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRQwEgYDVQQH"
- + "EwtTYW50YSBDbGFyYTEMMAoGA1UEChMDQUJCMVEwTwYDVQQLHEhQAAAAAAAAAG8AAAAAAAAAdwAA"
- + "AAAAAABlAAAAAAAAAHIAAAAAAAAAIAAAAAAAAABUAAAAAAAAABxIAAAAAAAARAAAAAAAAAAxDTAL"
- + "BgNVBAMTBGJsdWUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANETRZ+6occCOrFxNhfKIp4C"
- + "mMkxwhBNb7TnnahpbM9O0r4hrBPcfYuL7u9YX/jN0YNUP+/CiT39HhSe/bikaBPDEyNsl988I8vX"
- + "piEdgxYq/+LTgGHbjRsRYCkPtmzwBbuBldNF8bV7pu0v4UScSsExmGqqDlX1TbPU8KkPU1iTAgMB"
- + "AAGgADANBgkqhkiG9w0BAQQFAAOBgQAFbrs9qUwh93CtETk7DeUD5HcdCnxauo1bck44snSV6MZV"
- + "OCIGaYu1501kmhEvAtVVRr6SEHwimfQDDIjnrWwYsEr/DT6tkTZAbfRd3qUu3iKjT0H0vlUZp0hJ"
- + "66mINtBM84uZFBfoXiWY8M3FuAnGmvy6ah/dYtJorTxLKiGkew==");
-
- public String getName()
- {
- return "PKCS10";
- }
-
- public TestResult pkcs10Test(
- String testName,
- byte[] req)
- {
- try
- {
- ByteArrayInputStream bIn = new ByteArrayInputStream(req);
- ASN1InputStream aIn = new ASN1InputStream(bIn);
-
- CertificationRequest r = new CertificationRequest((ASN1Sequence)aIn.readObject());
-
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- DEROutputStream dOut = new DEROutputStream(bOut);
-
- dOut.writeObject(r.toASN1Primitive());
-
- byte[] bytes = bOut.toByteArray();
-
- if (bytes.length != req.length)
- {
- return new SimpleTestResult(false, getName() + ": " + testName + " failed length test");
- }
-
- for (int i = 0; i != req.length; i++)
- {
- if (bytes[i] != req[i])
- {
- return new SimpleTestResult(false, getName() + ": " + testName + " failed comparison test");
- }
- }
- }
- catch (Exception e)
- {
- return new SimpleTestResult(false, getName() + ": Exception - " + testName + " " + e.toString());
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
-
- public TestResult perform()
- {
- TestResult res = pkcs10Test("basic CR", req1);
-
- if (!res.isSuccessful())
- {
- return res;
- }
-
- return pkcs10Test("Universal CR", req2);
- }
-
- public static void main(
- String[] args)
- {
- Test test = new PKCS10Test();
-
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/PKCS12Test.java b/core/src/test/java/org/bouncycastle/asn1/test/PKCS12Test.java
deleted file mode 100644
index f533a652..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/PKCS12Test.java
+++ /dev/null
@@ -1,227 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1OutputStream;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.BEROctetString;
-import org.bouncycastle.asn1.DLSequence;
-import org.bouncycastle.asn1.pkcs.AuthenticatedSafe;
-import org.bouncycastle.asn1.pkcs.ContentInfo;
-import org.bouncycastle.asn1.pkcs.EncryptedData;
-import org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo;
-import org.bouncycastle.asn1.pkcs.MacData;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.asn1.pkcs.Pfx;
-import org.bouncycastle.asn1.pkcs.SafeBag;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.DigestInfo;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class PKCS12Test
- extends SimpleTest
-{
- byte[] pkcs12 = Base64.decode(
- "MIACAQMwgAYJKoZIhvcNAQcBoIAkgASCA+gwgDCABgkqhkiG9w0BBwGggCSA"
- + "BIIDRDCCA0AwggM8BgsqhkiG9w0BDAoBAqCCArEwggKtMCcGCiqGSIb3DQEM"
- + "AQMwGQQUFlnNVpQoEHc+J3UEGxARipkHu5kCAWQEggKAAH9tmy40lly6QDoc"
- + "1TfmY9y2qysD+lrgk+dnxP04RfoJfycTRDeaz2sPLImZtio9nsqCFqtzU/sl"
- + "eWigbH34BpKU1sC0Gq1cyik0GO65sW95S6YjKtGcGOBfQCPk1oQjfiqnfU3G"
- + "oeOaG3COQJukMFj8unv55u0xbX1hwO8SsZmr9RjPzLrVaeY6BP5+CCzOKBaj"
- + "GxneIDqnQW7/kBIVWK7M+JXGdgQyiKhD6NvXL/zD8oKEne0nIX7IokQuWEn6"
- + "8Sglv5OSclsSdvHTk57bCuV5lVzoIzczA4J/LZWdrtITeVefBLQSalBzpRde"
- + "rSTMj485z2x5ChizhjE627/KQ5vkKQkQVqXYYXVyeTvKZRpL7vz13C4DUCwN"
- + "im1XvNSCNebXS1yHJRtcONDhGJN3UsrVjHr+2kCfE5SCEeSU/dqgNLuLa1tk"
- + "5+jwZFNj/HjO88wlOwPCol1uuJjDpaEW7dxu5qsVSfZhEXWHs8rZAMttFMzi"
- + "yxsEkZe8kqngRbNJOY6KpppYedsMWDusUJGfIHo+8zymiw3gv/z+lmFOlDGt"
- + "CKMk9Es/MgfjpbfhbTVYHOBKS6Qyrz7LdTuBMI8XdsZMuN+Uf73690ggLmKW"
- + "IELUg8h1RX0ra2n6jOc/1rnebAifMhiMkL1ABQvqOobfOrG/9h9XcXoi64Qr"
- + "htc3T7yMAHafBX5KUcNkbcn6kssYhpvd8bPADoLBnbx3GxGh/uziB0zKQEI0"
- + "GnaY4SL7aR4C5xNNi41lYtsR6ohKyfPEGslhrhd4axx0cKxC2sHgVl0k+r8B"
- + "8Vu44XHbW8LqdspjOHN9qg2erES1Dvgj05SfHDup+V6a3ogJo2YKXOiu3DF4"
- + "MFEGCSqGSIb3DQEJFDFEHkIARABhAHYAaQBkACAARwAuACAASABvAG8AawAn"
- + "AHMAIABWAGUAcgBpAFMAaQBnAG4ALAAgAEkAbgBjAC4AIABJAEQwIwYJKoZI"
- + "hvcNAQkVMRYEFKEcMJ798oZLFkH0OnpbUBnrTLgWAAAAAAAAMIAGCSqGSIb3"
- + "DQEHBqCAMIACAQAwgAYJKoZIhvcNAQcBMCcGCiqGSIb3DQEMAQYwGQQUTErH"
- + "kWZ8nBXZYWO53FH4yqRZZsECAWSggASCDGCreuCr6/azcOv5w04bN3jkg4G2"
- + "dsvTPAjL8bichaEOQCykhuNPt1dv3FsjUsdFC550K0+Y48RyBIID6JTiN9Gj"
- + "K+a5aLPaXgTRdY74Toof1hYtZ4DIcVyq25LezVQHoe/++pAgEpWjqHTxVDIv"
- + "YFAgT2oDB+2vkeXM61XnNWOjwCY3pXpk/VGjyN4USkD7Q/Y6tPjQOywvQE7c"
- + "Ab1z62k9iMia7Yk/qmh+zJu4SSneo0/RLLdMZOlGZv89MResVG038TC8MTA9"
- + "Uf+wDRcS20d7XDbTaBAgju8TpFIw5/lbDi0feUVlk6L+jkT1ktaTc1Pwtxn7"
- + "psXMFW6HAWB4exOi09297R9BCOQX6vcetK/iA/3jIC6NuTdizYof0DWetdGy"
- + "haIkMiEnERYE3unJocH4fq585Rw6mE+BYssPVPkVWZZInF3l69bKduuxsQt+"
- + "pcApgBVsTjsU+1FOiUxuW2wWKi70RcQprPv5Ef1A5FRNxPFp+7IzLNlE4qCo"
- + "wvC6NTpeuRw3aGsXSfqHmSddrHugNPmghNgG5lv1Ef7A8MUuyp8fyjAgxCDk"
- + "4Hpb8PCHGj5t//Fr6Cd0MygJMIFQmv4kUd2LVHxQ9A9WFNCqTz/nBe+ZRLJL"
- + "NghTv6gGpjGJiBnXYv6Sod2fs+5J2GIvex4qbdh6gzZIU2YTAwpj6Aca3SjA"
- + "X8+m8AXt2SC3Z6T5+m8SxyiNp2P511paV/TZKtLWXQGKeEX1JXhQkaM6Q5W/"
- + "IhSgC8/gppk1gbIraBqrW8bEnGBnC03wi0OnMz3ohM4CVHyaW3dQquT2+u6F"
- + "8VeGXAYHU022NkrpPl/VlfNNEAyisU2+oJqpPZkqL6FsDWF3k6Fq2jXBLL+/"
- + "a0WA82jIpgjNeXze/cgoHtU023V9E9Qcu+5nPBYdCTR4sRxvHLANii0W8lPv"
- + "tvU5XO1UsEjHDfKL4E1bhGzGpb/OU5yg/98EN95r/xdFL5G+XVyHeR0UtkcB"
- + "IuvyBdhkwoprCjkcgLZe8FPIBNw84HRe7Ye6f2gDW/F5uej6rBehJS1VFvCh"
- + "DXzkajGmK40Gc2APS1/1vZqPu68polgw9dT84rem36PLEOq4KuU7n4QE0g7T"
- + "YR2G8+4FNgQTjjg/qw3lX+sj6yLn1lYt1dOVvkiM8i8tdZg/3pCKKAW1uV7a"
- + "astlBxVSkFfn1BrFTc2oFGkTrlUg90a+parOfGHTfDiaHX8ouEg63fk0+Xdi"
- + "FCarXsqHNPDbpmWLKw8TAmdeneGipyScntJJk4ajy+jROQBgGew3ofOmfkqm"
- + "oJFNwUvKOXN2ucViLZgsdK/7YgV1OR7oiTh8knQNPk3d5fRYSMFf9GJTjQRV"
- + "y2CLdICAVzvrUXf9k7miWYkjIp2/HGD7pOH018sX9MrpfJKqvdPFOssZiFd0"
- + "I2FUbgcEggPotvnT0XoabEiurTm8EPPpw66NKmK/H1kQL0hEtdIazPxfLmm/"
- + "ZUDokwa7d4bE3BwFh0weQfEvMzJu6Y5E7ir2MqD33XaGMOGys1nst1SPPyDB"
- + "WpOWD9w7Ng3yU1JVzqFWuVXaXDYbfnlG7AGevKF5PYNZj/RIQBBf5Xle9hTd"
- + "c9CtxPkrsJwA8DeAwKl2WIfbXGzAYLSnXoYUcoTkWn/O81BlUFgAXv80gLe8"
- + "NUrH7bhsnyGaPY953NyDk8IWUYrsn/sXvxTy5B0/7/WGMh3CSZrLX3p7TcFY"
- + "yBrL6SRas4q9rrcwuhBq0tUUbbgWi92nhZl4bOGmx7ehHnwuUId2HWXyVGoB"
- + "qToee/2E4PZFxSZwKCY6dahswFq5QGDrQKN2/qpOLZcJib6SvSGyEZl2pqr0"
- + "lqk7tVPzBkN/4uP0qrcbZCDbGW6IXwu3RGMRehqj/HEJcs92lZKfVrk/U07X"
- + "MBAiQHqV+kLw7kStECR/MGJG1c0xhqqBrf0W74+LpJiv/Q9iFNdWbXvE/cAk"
- + "G7+OTUABd2kI88uA43T0UoRuPOi5KnLuD3AG+7IuyGyP69Xncd4u0srMg2fn"
- + "DiLLZUy6vWmxwRFsSMCEfQNLtZaggukoPIihQvbX3mQS9izwLs6D89WtEcZ5"
- + "6DVbIlUqUinnNKsT8vW1DZo5FMJkUxB666YIPVmkQbbJOEUU89dZg5Gw0og6"
- + "rn4irEr4xHFdx+S7iqJXhzs9THg/9e4/k8KQ136z7LALOqDookcSdBzW6H8c"
- + "STjs4qKQyNimsLB90mEuIEApzhseAaLFl+kgORGJv/2a+uoukZchMsJ98MVo"
- + "sEPS1oBXJl2m9AshkWfON2GDeJatgcw6CyC1mSx++Gg602ZKUZZUaWxkz1Sw"
- + "zTj3nhiJe+SZsdfxhsojNq7zfxqgY/Rq7BwvphU3StjnxvkB4rTkbmbiGOBO"
- + "cvTFg4yOtQGRcifk2/XH/bgYiPqQrYSXpO3WRASV005RaSGufcpTtj3YlHGe"
- + "8FUgZfDtfiGezhNET9KO3/Q0i34bGEpoIb/9uOWH4ZHULIlfdSm1ynV50nE4"
- + "mJTXccrF6BE80KZI5GWGhqXdfPFaHTK1S20+XCw7bRJCGeiwVxvGfB+C0SZ4"
- + "ndtqx165dKG5JwFukcygiIZN6foh0/PhwzmFxmPtZuPQt9dtuIQ35Y7PSDsy"
- + "IH2Ot0Hh0YIN99lHJ6n9HomSjpwcgDXGssEuevbpz27u/MI/Uhq4Gfx0k5RF"
- + "0pcRYtk1dYSx44a+8WgqZLF8DUNtyjSE/H8P5iGa6tqOl7kNyeeEkfoTtKst"
- + "asGFwL4Qxxus4GC7repyVi7IJgSCA+iopiqKQJ2IqUHvoIEuD//sZooDx0Je"
- + "oFRO5VakkTO6WHd8JpOOEU2f6Zjg++HdIl0QK7xcUaRH075LzEfqgn1vyw6J"
- + "N6ex8D76sf/nAy01NvDPij48Z50XDwXu4kJGJvv0AJwId8BpjziBF0j3K/DI"
- + "YOOpd6nW4EvdivCgaCnxqlIU/u1OP4BwpO+AUjJh6RKlKviGihQpi103DFhR"
- + "yXNDhh55pqgCCCuNeEB+ovRt7UxzlGAVRSxJh1Zbjp/+iQun0E32RlSR4Diz"
- + "p5vDk8NBZpIiKRqI+8GWZc3G1igp7dvViTLw4OdWMKwhccV5+3Ll/W72aNVm"
- + "azYUoYOVn+OYS1NJkER0tjFOCozRGm5hfkxGlP+02wbH5uu/AQoJMqWIxT6l"
- + "46IWC24lmAnDCXuM+gWmwUvyXLwuBdejVK8iG1Lnfg1qztoLpYRbBROgRdpt"
- + "2cbPRm+9seqrth3eJbtmxCvuh3bZ3pR2e0/r5Tob/fDcOc5Kp+j4ndXWkwpa"
- + "OuH1yxam7zNJR+mcYp1Wiujia5qIeY1QCAEY5QgAWaSHtjlEprwUuootA2Xm"
- + "V7D8Vsr9BValhm9zMKj6IzsPmM+HZJWlhHcoucuAmPK6Lnys3Kv/mbkSgNOq"
- + "fJDY901veFfKeqiCbAm6hZjNWoQDNJKFhjXUALrcOv9VCFPA3bMW3Xul/sB4"
- + "Mq595e+x/1HkNOgZorBv97C6X7ENVDaAFcyZvrRU/ZeDnvFhisfxS4EJhzxl"
- + "cWWnQhzD+ur1FTTlkmUFzgoB/rW+i3XigiHOuRRnkcoMy1uV17rwH8eELHJu"
- + "Yni5vu2QUaD4jNEhliE2XCsn8Sm6bcXnfzBa7FXC39QvAcdJHzqcD6iIwjIz"
- + "hKLu+/XoWFMFFNsgV78AwzPAn6TRya8LLCYPoIZkEP4qBoeZtUZ8PIS/Y7M9"
- + "QStMwa/NI9SPswb3iScTGvor/obUEQS4QM6mVxFMpQWfwJfyU6jingX4EHRE"
- + "mqvZ3ehzU8ZLOdKzRKuk022YDT7hwEQ+VL0Fg0Ld9oexqT96nQpUTHZtDRMV"
- + "iTuJoUYTneDs2c9tsY4mWBqamZQSfTegj4sLMZagkuSUp/SpPM2zSGuD3nY6"
- + "u3553gIM9jYhvLBEXwjGudVCwMd3bqo/4EhnKb2PcwUzdaMkipQlNteHZjBT"
- + "1ici63xjJva+di0qTV+W9cyYyHwg1927X2qcMh06BhbHlcXQKbgmbL18KJEt"
- + "K+GGhGNkP7mtPyHHgBb6vref/z8p7oxT2CG+oBuN/z+xQoYfe9c4IC3e/kNN"
- + "DIoyYvPyEzAdfMS2aL8qDxzc5GH9UE9kcusJ/2dNEFTzBH2GK1CItL3IACv/"
- + "LwX1SkI0w7oIQTL127CSnuTrUUkvJ/+rOYScQTMD/ntZPdLdu2ffszg3SzhN"
- + "ELgojK8ss1OBlruWRHw/fP736Nx8MNsuOvXMnO8lruz+uyuEhF3BLv96oTcg"
- + "XVHdWhPmOoqNdBQdRgAAAAAAAAAAAAAAAAAAAAAAADA8MCEwCQYFKw4DAhoF"
- + "AAQUJMZn7MEKv4vW/+voCVyHBa6B0EMEFJOzH/BEjRtNNsZWlo/4L840aE5r"
- + "AgFkAAA=");
-
- public void performTest()
- throws Exception
- {
- ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(pkcs12));
- ASN1Sequence obj = (ASN1Sequence)aIn.readObject();
- Pfx bag = Pfx.getInstance(obj);
- ContentInfo info = bag.getAuthSafe();
- MacData mData = bag.getMacData();
- DigestInfo dInfo = mData.getMac();
- AlgorithmIdentifier algId = dInfo.getAlgorithmId();
- byte[] salt = mData.getSalt();
- int itCount = mData.getIterationCount().intValue();
-
- aIn = new ASN1InputStream(new ByteArrayInputStream(((ASN1OctetString)info.getContent()).getOctets()));
-
- AuthenticatedSafe authSafe = AuthenticatedSafe.getInstance(aIn.readObject());
- ContentInfo[] c = authSafe.getContentInfo();
-
- //
- // private key section
- //
- if (!c[0].getContentType().equals(PKCSObjectIdentifiers.data))
- {
- fail("failed comparison data test");
- }
-
- aIn = new ASN1InputStream(new ByteArrayInputStream(((ASN1OctetString)c[0].getContent()).getOctets()));
- ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
-
- SafeBag b = SafeBag.getInstance(seq.getObjectAt(0));
- if (!b.getBagId().equals(PKCSObjectIdentifiers.pkcs8ShroudedKeyBag))
- {
- fail("failed comparison shroudedKeyBag test");
- }
-
- EncryptedPrivateKeyInfo encInfo = EncryptedPrivateKeyInfo.getInstance(b.getBagValue());
-
- encInfo = new EncryptedPrivateKeyInfo(encInfo.getEncryptionAlgorithm(), encInfo.getEncryptedData());
-
- b = new SafeBag(PKCSObjectIdentifiers.pkcs8ShroudedKeyBag, encInfo.toASN1Primitive(), b.getBagAttributes());
-
- ByteArrayOutputStream abOut = new ByteArrayOutputStream();
- ASN1OutputStream berOut = new ASN1OutputStream(abOut);
-
- berOut.writeObject(new DLSequence(b));
-
- c[0] = new ContentInfo(PKCSObjectIdentifiers.data, new BEROctetString(abOut.toByteArray()));
-
- //
- // certificates
- //
- if (!c[1].getContentType().equals(PKCSObjectIdentifiers.encryptedData))
- {
- fail("failed comparison encryptedData test");
- }
-
- EncryptedData eData = EncryptedData.getInstance(c[1].getContent());
-
- c[1] = new ContentInfo(PKCSObjectIdentifiers.encryptedData, eData);
-
- //
- // create an octet stream represent the BER encoding of authSafe
- //
- authSafe = new AuthenticatedSafe(c);
-
- abOut = new ByteArrayOutputStream();
- berOut = new ASN1OutputStream(abOut);
-
- berOut.writeObject(authSafe);
-
- info = new ContentInfo(PKCSObjectIdentifiers.data, new BEROctetString(abOut.toByteArray()));
-
- mData = new MacData(new DigestInfo(algId, dInfo.getDigest()), salt, itCount);
-
- bag = new Pfx(info, mData);
-
- //
- // comparison test
- //
-
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- ASN1OutputStream aOut = new ASN1OutputStream(bOut);
-
- aOut.writeObject(bag);
-
- if (!Arrays.areEqual(bOut.toByteArray(), pkcs12))
- {
- fail("failed comparison test");
- }
- }
-
- public String getName()
- {
- return "PKCS12";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new PKCS12Test());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/PKIFailureInfoTest.java b/core/src/test/java/org/bouncycastle/asn1/test/PKIFailureInfoTest.java
deleted file mode 100644
index 164f5a6f..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/PKIFailureInfoTest.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Encoding;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.cmp.PKIFailureInfo;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.test.SimpleTest;
-
-
-/**
- * PKIFailureInfoTest
- */
-public class PKIFailureInfoTest
- extends SimpleTest
-{
- // A correct hex encoded BAD_DATA_FORMAT PKIFailureInfo
- private static final byte[] CORRECT_FAILURE_INFO = Base64.decode("AwIANQ==");
-
- public String getName()
- {
- return "PKIFailureInfo";
- }
-
- private void testEncoding()
- throws IOException
- {
- DERBitString bitString = (DERBitString)new ASN1InputStream(CORRECT_FAILURE_INFO).readObject();
- PKIFailureInfo correct = new PKIFailureInfo(bitString);
-
- PKIFailureInfo bug = new PKIFailureInfo(PKIFailureInfo.badRequest | PKIFailureInfo.badTime |PKIFailureInfo.badDataFormat | PKIFailureInfo.incorrectData);
-
- if (!areEqual(correct.getEncoded(ASN1Encoding.DER),bug.getEncoded(ASN1Encoding.DER)))
- {
- fail("encoding doesn't match");
- }
- }
-
- public void performTest()
- throws IOException
- {
- BitStringConstantTester.testFlagValueCorrect(0, PKIFailureInfo.badAlg);
- BitStringConstantTester.testFlagValueCorrect(1, PKIFailureInfo.badMessageCheck);
- BitStringConstantTester.testFlagValueCorrect(2, PKIFailureInfo.badRequest);
- BitStringConstantTester.testFlagValueCorrect(3, PKIFailureInfo.badTime);
- BitStringConstantTester.testFlagValueCorrect(4, PKIFailureInfo.badCertId);
- BitStringConstantTester.testFlagValueCorrect(5, PKIFailureInfo.badDataFormat);
- BitStringConstantTester.testFlagValueCorrect(6, PKIFailureInfo.wrongAuthority);
- BitStringConstantTester.testFlagValueCorrect(7, PKIFailureInfo.incorrectData);
- BitStringConstantTester.testFlagValueCorrect(8, PKIFailureInfo.missingTimeStamp);
- BitStringConstantTester.testFlagValueCorrect(9, PKIFailureInfo.badPOP);
- BitStringConstantTester.testFlagValueCorrect(14, PKIFailureInfo.timeNotAvailable);
- BitStringConstantTester.testFlagValueCorrect(15, PKIFailureInfo.unacceptedPolicy);
- BitStringConstantTester.testFlagValueCorrect(16, PKIFailureInfo.unacceptedExtension);
- BitStringConstantTester.testFlagValueCorrect(17, PKIFailureInfo.addInfoNotAvailable);
- BitStringConstantTester.testFlagValueCorrect(25, PKIFailureInfo.systemFailure);
-
- testEncoding();
- }
-
- public static void main(
- String[] args)
- {
- runTest(new PKIFailureInfoTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/ParseTest.java b/core/src/test/java/org/bouncycastle/asn1/test/ParseTest.java
deleted file mode 100644
index 2e5112a3..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/ParseTest.java
+++ /dev/null
@@ -1,308 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import junit.framework.TestCase;
-import org.bouncycastle.asn1.ASN1OctetStringParser;
-import org.bouncycastle.asn1.ASN1SequenceParser;
-import org.bouncycastle.asn1.ASN1StreamParser;
-import org.bouncycastle.asn1.ASN1TaggedObjectParser;
-import org.bouncycastle.asn1.BERTags;
-import org.bouncycastle.asn1.cms.ContentInfoParser;
-import org.bouncycastle.asn1.cms.EncryptedContentInfoParser;
-import org.bouncycastle.asn1.cms.EnvelopedDataParser;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.io.Streams;
-
-public class ParseTest
- extends TestCase
-{
- private static byte[] classCastTest = Base64.decode(
- "MIIXqAYJKoZIhvcNAQcDoIIXmTCCF5UCAQAxggG1MIIBsQIBADCBmDCBkDEL"
- + "MAkGA1UEBhMCVVMxETAPBgNVBAgTCE1pY2hpZ2FuMQ0wCwYDVQQHEwRUcm95"
- + "MQwwCgYDVQQKEwNFRFMxGTAXBgNVBAsTEEVMSVQgRW5naW5lZXJpbmcxJDAi"
- + "BgkqhkiG9w0BCQEWFUVsaXQuU2VydmljZXNAZWRzLmNvbTEQMA4GA1UEAxMH"
- + "RURTRUxJVAIDD6FBMA0GCSqGSIb3DQEBAQUABIIBAGh04C2SyEnH9J2Va18w"
- + "3vdp5L7immD5h5CDZFgdgHln5QBzT7hodXMVHmyGnycsWnAjYqpsil96H3xQ"
- + "A6+9a7yB6TYSLTNv8zhL2qU3IrfdmUJyxxfsFJlWFO1MlRmu9xEAW5CeauXs"
- + "RurQCT+C5tLc5uytbvw0Jqbz+Qp1+eaRbfvyhWFGkO/BYZ89hVL9Yl1sg/Ls"
- + "mA5jwTj2AvHkAwis+F33ZhYlto2QDvbPsUa0cldnX8+1Pz4QzKMHmfUbFD2D"
- + "ngaYN1tDlmezCsYFQmNx1th1SaQtTefvPr+qaqRsm8KEXlWbJQXmIfdyi0zY"
- + "qiwztEtO81hXZYkKqc5fKMMwghXVBgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcE"
- + "CEq3cLLWVds9gIIVsAAik3al6Nn5pr7r0mSy9Ki3vEeCBcV9EzEG44BvNHNA"
- + "WyEsqQsdSxuF7h1/DJAMuZFwCbGflaRGx/1L94zrmtpeuH501lzPMvvZCmpj"
- + "KrOF8e1B4MVQ5TfQTdUVyRnbcDa6E4V1ZZIdAI7BgDeJttS4+L6btquXfxUg"
- + "ttPYQkevF7MdShYNnfLkY4vUMDOp3+iVzrOlq0elM95dfSA7OdBavgDJbz/7"
- + "mro3AFTytnWjGz8TUos+oUujTk9/kHOn4cEAIm0hHrNhPS5qoj3QnNduNrad"
- + "rLpGtcYyNlHIsYCsvPMxwoHmIw+r9xQQRjjzmVYzidn+cNOt0FmLs6YE8ds4"
- + "wvHRO9S69TgKPHRgk2bihgHqII9lF9qIzfG40YwJLHzGoEwVO1O0+wn8j2EP"
- + "O9I/Q3vreCH+5VbpUD2NGTwsMwZ3YlUesurLwse/YICxmgdN5Ro4DeQJSa9M"
- + "iJnRFYWRq+58cKgr+L11mNc9nApZBShlpPP7pdNqWOafStIEjo+dsY/J+iyS"
- + "6WLlUvNt/12qF4NAgZMb3FvRQ9PrMe87lqSRnHcpLWHcFjuKbMKCBvcdWGWI"
- + "R7JR8UNzUvoLGGAUI9Ck+yTq4QtfgtL5MLmdBGxSKzgs44Mmek+LnrFx+e9n"
- + "pkrdDf2gM/m7E50FnLYqzUjctKYGLNYpXQorq9MJx6TB20CHXcqOOoQqesXa"
- + "9jL9PIOtBQy1Ow5Bh4SP07nTFWFSMI/Wt4ZvNvWJj3ecA9KjMOA9EXWUDS/H"
- + "k9iCb2EEMo7fe5mhoyxMxPO+EIa1sEC9A1+rDACKPQCHOLI0uPmsdo0AEECC"
- + "QLgOQkcwQlkHexOyHiOOtBxehtGZ1eBQQZ+31DF+RRU6WvS6grg58eS4gGOQ"
- + "bd7CS9yYebvAQkz61J8KprWdtZuG1gBGma12wKMuQuC6RuWlKsj+rPMvaQCt"
- + "8mucGbkElPGZVhdyD8/BvpSCNbgRwb6iSiw4EECovu4P4GFJaMGUYEuCA711"
- + "itEieYc1QqS6ULjb3LFL/RcwSw0fGdjnt6B2nHckC2VsYKU1NwU7j0R1Omb4"
- + "y5AvSgpuWjTXWnHnE9Ey0B+KP5ERZA+jJGiwYz48ynYlvQFSbBm4I6nh/DuI"
- + "dWB2dLNxWuhdfzafBGtEHhLHzjW3WQwwRZsKesgHLrrj9hBUObodl1uvqvZN"
- + "AjMOj8DrqbGOhAClj1t4S1Zk1ZekuMjsuoxEL+/lgtbT+056ES0k3A/LnpRb"
- + "uxA1ZBr26Im+GVFzEcsV0hB4vNujSwStTTZH5jX5rMyi085yJfnikcLYUn9N"
- + "apl+srhpIZlDJPw7IHaw8tsqXKDxF7MozIXo8B45CKv5Am+BMrIemCMX/ehu"
- + "PODICl98Ur8tNAn1L+m0nj7H3c8HW2vNuBLEI3SEHHgm2Ij3IY5pyyeVUaWC"
- + "pumhy8Ru5dj3fZcfKgYuJBQxWMf+UqPsf4iUK3923pouJ1cQ8XU8gOXIRrtX"
- + "e41d/yR+UAZXSig6SITLw+wLtvitSvtxvjcUSUOI9CYTovKyuz1PQKiaLsV5"
- + "4CoJhMQ5uRlVFS3H829I2d2gLRpSp6pNWeIZO2NMBxPYf2qcSHyHqQjR7xP2"
- + "ZTg7U3OO6dZHORfXxzAnW2ExavBIYQmZh1gLn5jSS4wXFPXyvnJAsF4s5wed"
- + "YHsyAqM/ek0n2Oo/zAh7UcP2vcb9FOoeRK8qC9HjTciS6WbjskRN0ft4T69G"
- + "+1RsH8/edBxo2LZeA48BSCXDXOlBZJBsOptzYJD8HSZONPnef0jn23lk0fkU"
- + "C3BjJu2ubFChctRvJniTko4klpidkHwuJgrTnL4er8rG3RfiiEHn/d5era15"
- + "E1cekdVYWqwQOObOd4v+0gZSJgI48TBc5Qdy8F6wIU38DR2pn/5uNthNDgXk"
- + "NcV9a2gOE3DoLe8CEIPMihqYMPY8NuSp97eHB2YhKpjP7qX9TUMoOdE2Iat2"
- + "klNxadJt6JTFeiBPL6R9RHAD5sVBrkrl0S+oYtgF92f9WHVwAXU7zP6IgM4x"
- + "hhzeJT07yyIp44mKd//F+7ntbgQjZ/iLbHh0mtOlUmzkFsDR0UNSXEQoourZ"
- + "EY4A62HXj0DMqEQbik6QwEF7FKuwZX2opdOyVKH9MzJxNfDLd5dc8wAc8bCX"
- + "jcCx5/GzHx2S5DndWQEVhp2hOQYuoJS3r6QCYFaHtDPKnFHS2PBFyFWL+2UK"
- + "c0WsvVaHYqYKnksmxse9I9oU75kx5O05DZCThPX6h8J8MHRuxU9tcuuleIUQ"
- + "XY8On+JeEtLSUZgp+Z7ITLuagf6yuKQpaR396MlDii/449/dvBiXAXeduyO1"
- + "QzSkQCh37fdasqGL3mP0ssMcxM/qpOwQsx3gMtwiHQRi1oQE1QHb8qZHDE4m"
- + "I5afQJ9O/H/m/EVlGUSn2yYOsPlZrWuI3BBZKoRzRq1lZOQDtOh18BE3tWmX"
- + "viGIAxajam0i2Ce3h2U7vNwtiePRNEgPmQ7RwTTv0U6X8qqkjeYskiF4Cv9G"
- + "nrB0WreC19ih5psEWLIkCYKTr+OhQuRrtv7RcyUi9QSneh7BjcvRjlGB6joA"
- + "F6J4Y6ENAA/nzOZJ699VkljTi59bbNJYlONpQhOeRTu8M/wExkIJz7yR9DTY"
- + "bY4/JdbdHNFf5DSDmYAHaFLmdnnfuRy+tC9CGGJvlcLVv5LMFJQGt2Wi15p8"
- + "lctx7sL6yNCi7OakWbEOCvGPOxY7ejnvOjVK/Krx1T+dAXNUqrsDZmvmakOP"
- + "We+P4Di1GqcyLVOTP8wNCkuAUoN0JFoBHy336/Xnae91KlY4DciPMpEOIpPN"
- + "oB+3h6CozV7IWX5Wh3rhfC25nyGJshIBUS6cMXAsswQI8rOylMlGaekNcSU4"
- + "gNKNDZAK5jNkS0Z/ziIrElSvMNTfYbnx3gCkY0pV18uadmchXihVT11Bt77O"
- + "8KCKHycR39WYFIRO09wvGv6P42CRBFTdQbWFtkSwRiH8l6x39Z7pIkDFxokT"
- + "Dp6Htkj3ywfQXNbFgRXZUXqgD1gZVFDFx920hcJnuu65CKz6pEL6X0XUwNPg"
- + "vtraA2nj4wjVB/y+Cxc+1FgzeELB4CAmWO1OfRVLjYe7WEe/X5DPT6p8HBkB"
- + "5mWuv+iQ3e37e1Lrsjt2frRYQWoOSP5Lv7c8tZiNfuIp07IYnJKBWZLTqNf9"
- + "60uiY93ssE0gr3mfYOj+fSbbjy6NgAenT7NRZmFCjFwAfmapIV0hJoqnquaN"
- + "jj5KKOP72hp+Zr9l8cEcvIhG/BbkY3kYbx3JJ9lnujBVr69PphHQTdw67CNB"
- + "mDkH7y3bvZ+YaDY0vdKOJif9YwW2qoALXKgVBu1T2BONbCTIUTOzrKhWEvW8"
- + "D6x03JsWrMMqOKeoyomf1iMt4dIOjp7yGl/lQ3iserzzLsAzR699W2+PWrAT"
- + "5vLgklJPX/Fb3Tojbsc074lBq669WZe3xzlj85hFcBmoLPPyBE91BLhEwlGC"
- + "+lWmwFOENLFGZE0mGoRN+KYxwqfA2N6H8TWoz6m0oPUW4uQvy9sGtYTSyQO9"
- + "6ZwVNT3ndlFrP5p2atdEFVc5aO5FsK8/Fenwez06B2wv9cE9QTVpFrnJkKtF"
- + "SaPCZkignj64XN7cHbk7Ys6nC3WIrTCcj1UOyp5ihuMS9eL9vosYADsmrR6M"
- + "uqqeqHsf2+6U1sO1JBkDYtLzoaILTJoqg9/eH7cTA0T0mEfxVos9kAzk5nVN"
- + "nVOKFrCGVIbOStpYlWP6wyykIKVkssfO6D42D5Im0zmgUwgNEkB+Vxvs8bEs"
- + "l1wPuB2YPRDCEvwM3A5d5vTKhPtKMECIcDxpdwkD5RmLt+iaYN6oSFzyeeU0"
- + "YvXBQzq8gfpqJu/lP8cFsjEJ0qCKdDHVTAAeWE6s5XpIzXt5cEWa5JK7Us+I"
- + "VbSmri4z0sVwSpuopXmhLqLlNWLGXRDyTjZSGGJbguczXCq5XJ2E3E4WGYd6"
- + "mUWhnP5H7gfW7ILOUN8HLbwOWon8A6xZlMQssL/1PaP3nL8ukvOqzbIBCZQY"
- + "nrIYGowGKDU83zhO6IOgO8RIVQBJsdjXbN0FyV/sFCs5Sf5WyPlXw/dUAXIA"
- + "cQiVKM3GiVeAg/q8f5nfrr8+OD4TGMVtUVYujfJocDEtdjxBuyFz3aUaKj0F"
- + "r9DM3ozAxgWcEvl2CUqJLPHH+AWn5kM7bDyQ2sTIUf5M6hdeick09hwrmXRF"
- + "NdIoUpn7rZORh0h2VX3XytLj2ERmvv/jPVC97VKU916n1QeMJLprjIsp7GsH"
- + "KieC1RCKEfg4i9uHoIyHo/VgnKrnTOGX/ksj2ArMhviUJ0yjDDx5jo/k5wLn"
- + "Rew2+bhiQdghRSriUMkubFh7TN901yl1kF2BBP5PHbpgfTP6R7qfl8ZEwzzO"
- + "elHe7t7SvI7ff5LkwDvUXSEIrHPGajYvBNZsgro+4Sx5rmaE0QSXACG228OQ"
- + "Qaju8qWqA2UaPhcHSPHO/u7ad/r8kHceu0dYnSFNe1p5v9Tjux0Yn6y1c+xf"
- + "V1cu3plCwzW3Byw14PH9ATmi8KJpZQaJOqTxn+zD9TvOa93blK/9b5KDY1QM"
- + "1s70+VOq0lEMI6Ch3QhFbXaslpgMUJLgvEa5fz3GhmD6+BRHkqjjwlLdwmyR"
- + "qbr4v6o+vnJKucoUmzvDT8ZH9nH2WCtiiEtQaLNU2vsJ4kZvEy0CEajOrqUF"
- + "d8qgEAHgh9it5oiyGBB2X/52notXWOi6OMKgWlxxKHPTJDvEVcQ4zZUverII"
- + "4vYrveRXdiDodggfrafziDrA/0eEKWpcZj7fDBYjUBazwjrsn5VIWfwP2AUE"
- + "wNn+xR81/so8Nl7EDBeoRXttyH7stbZYdRnkPK025CQug9RLzfhEAgjdgQYw"
- + "uG+z0IuyctJW1Q1E8YSOpWEFcOK5okQkLFUfB63sO1M2LS0dDHzmdZriCfIE"
- + "F+9aPMzojaHg3OQmZD7MiIjioV6w43bzVmtMRG22weZIYH/Sh3lDRZn13AS9"
- + "YV6L7hbFtKKYrie79SldtYazYT8FTSNml/+Qv2TvYTjVwYwHpm7t479u+MLh"
- + "LxMRVsVeJeSxjgufHmiLk7yYJajNyS2j9Kx/fmXmJbWZNcerrfLP+q+b594Y"
- + "1TGWr8E6ZTh9I1gU2JR7WYl/hB2/eT6sgSYHTPyGSxTEvEHP242lmjkiHY94"
- + "CfiTMDu281gIsnAskl05aeCBkj2M5S0BWCxy7bpVAVFf5nhf74EFIBOtHaJl"
- + "/8psz1kGVF3TzgYHkZXpUjVX/mJX8FG0R8HN7g/xK73HSvqeamr4qVz3Kmm/"
- + "kMtYRbZre7E1D10qh/ksNYnOkYBcG4P2JyjZ5q+8CQNungz2/b0Glg5LztNz"
- + "hUgG27xDOUraJXjkkZl/GOh0eTqhfLHXC/TfyoEAQOPcA59MKqvroFC5Js0Q"
- + "sTgqm2lWzaLNz+PEXpJHuSifHFXaYIkLUJs+8X5711+0M03y8iP4jZeEOrjI"
- + "l9t3ZYbazwsI3hBIke2hGprw4m3ZmSvQ22g+N6+hnitnDALMsZThesjb6aJd"
- + "XOwhjLkWRD4nQN594o6ZRrfv4bFEPTp4ev8l6diouKlXSFFnVqz7AZw3Pe53"
- + "BvIsoh66zHBpZhauPV/s/uLb5x6Z8sU2OK6AoJ7b8R9V/AT7zvonBi/XQNw3"
- + "nwkwGnTS9Mh7PFnGHLJWTKKlYXrSpNviR1vPxqHMO6b+Lki10d/YMY0vHQrY"
- + "P6oSVkA6RIKsepHWo11+rV838+2NRrdedCe91foUmOs+eoWQnwmTy2CTZmQ5"
- + "b7/TTcau9ewimZAqI+MtDWcmWoZfgibZmnIITGcduNOJDRn+aLt9dz+zr1qA"
- + "HxlLXCOyBPdtfx6eo4Jon+fVte37i3HmxHk+8ZGMMSS9hJbLQEkA59b4E+7L"
- + "GI3JZjvEkhizB4n/aFeG7KT7K3x072DMbHLZ7VgsXQ1VDDmcZmizFwgyNqKy"
- + "hKCKxU+I2O10IMtiZUpEzV1Pw7hD5Kv/eFCsJFPXOJ2j3KP6qPtX5IYki1qH"
- + "Juo5C5uGKtqNc6OzkXsvNUfBz5sJkEYl0WfitSSo4ARyshFUNh2hGxNxUVKM"
- + "2opOcuHSxBgwUSmVprym50C305zdHulBXv3mLzGjvRstE9qfkQ8qVJYLQEkL"
- + "1Yn7E92ex71YsC8JhNNMy0/YZwMkiFrqyaFd/LrblWpBbGumhe4reCJ4K3mk"
- + "lFGEsICcMoe+zU1+QuLlz/bQ+UtvClHUe8hTyIjfY04Fwo2vbdSc1U/SHho5"
- + "thQy+lOZ/HijzCmfWK3aTqYMdwCUTCsoxri2N8vyD/K2kbMLQWUfUlBQfDOK"
- + "VrksBoSfcluNVaO56uEUw3enPhhJghfNlJnpr5gUcrAMES53DfkjNr0dCsfM"
- + "JOY2ZfQEwwYey1c4W1MNNMoegSTg4aXzjVc0xDgKa7RGbtRmVNbOxIhUNAVi"
- + "thQV3Qujoz1ehDt2GyLpjGjHSpQo3WlIU4OUqJaQfF6EH+3khFqUmp1LT7Iq"
- + "zH3ydYsoCDjvdXSSEY3hLcZVijUJqoaNWBLb/LF8OG5qTjsM2gLgy2vgO/lM"
- + "NsqkHnWTtDimoaRRjZBlYLhdzf6QlfLi7RPmmRriiAOM0nXmylF5xBPHQLoz"
- + "LO9lXYIfNbVJVqQsV43z52MvEQCqPNpGqjB+Au/PZalYHbosiVOQLgTB9hTI"
- + "sGutSXXeLnf5rftCFvWyL3n5DgURzDFLibrbyVGGKAk166bK1RyVP9XZJonr"
- + "hPYELk4KawCysJJSmC0E8sSsuXpfd6PPDru6nCV1EdXKR7DybS7NVHCktiPR"
- + "4B4y8O/AgfJX8sb6LuxmjaINtUKEJ1+O88Gb69uy6b/Kpu2ri/SUBaNNw4Sn"
- + "/tuaD+jxroL7RlZmt9ME/saNKn9OmLuggd6IUKAL4Ifsx9i7+JKcYuP8Cjdf"
- + "Rx6U6H4qkEwwYGXnZYqF3jxplyOfqA2Vpvp4rnf8mST6dRLKk49IhKGTzwZr"
- + "4za/RZhyl6lyoRAFDrVs1b+tj6RYZk0QnK3dLiN1MFYojLyz5Uvi5KlSyFw9"
- + "trsvXyfyWdyRmJqo1fT7OUe0ImJW2RN3v/qs1k+EXizgb7DW4Rc2goDsCGrZ"
- + "ZdMwuAdpRnyg9WNtmWwp4XXeb66u3hJHr4RwMd5oyKFB1GsmzZF7aOhSIb2B"
- + "t3coNXo/Y+WpEj9fD7/snq7I1lS2+3Jrnna1048O7N4b5S4b5TtEcCBILP1C"
- + "SRvaHyZhBtJpoH6UyimKfabXi08ksrcHmbs1+HRvn+3pl0bHcdeBIQS/wjk1"
- + "TVEDtaP+K9zkJxaExtoa45QvqowxtcKtMftNoznF45LvwriXEDV9jCXvKMcO"
- + "nxG5aQ//fbnn4j4q1wsKXxn61wuLUW5Nrg9fIhX7nTNAAooETO7bMUeOWjig"
- + "2S1nscmtwaV+Sumyz/XUhvWynwE0AXveLrA8Gxfx");
-
- private static byte[] derExpTest = Base64.decode(
- "MIIS6AYJKoZIhvcNAQcDoIIS2TCCEtUCAQAxggG1MIIBsQIBADCBmDCBkDEL"
- + "MAkGA1UEBhMCVVMxETAPBgNVBAgTCE1pY2hpZ2FuMQ0wCwYDVQQHEwRUcm95"
- + "MQwwCgYDVQQKEwNFRFMxGTAXBgNVBAsTEEVMSVQgRW5naW5lZXJpbmcxJDAi"
- + "BgkqhkiG9w0BCQEWFUVsaXQuU2VydmljZXNAZWRzLmNvbTEQMA4GA1UEAxMH"
- + "RURTRUxJVAIDD6FBMA0GCSqGSIb3DQEBAQUABIIBAGsRYK/jP1YujirddAMl"
- + "ATysfLCwd0eZhENohVqLiMleH25Dnwf+tBaH4a9hyW+7VrWw/LC6ILPVbKpo"
- + "oLBAOical40cw6C3zulajc4gM3AlE2KEeAWtI+bgPMXhumqiWDb4byX/APYk"
- + "53Gk7WXF6Xs4hj3tmrHSJxCUOsTdHKUJYvOqjwKGARPQDjP0EUbVJezeAwBA"
- + "RMlJ/qBVLBj2UW28n5oJZm3oaSaU93Uc6GPVIk43IWrmEUcWVPiMfUtUCwcX"
- + "tRNtHuQ9os++rmdNBiuB5p+vtUeA45KWnTUtkwJXvrzE6Sf9AUH/p8uOvvZJ"
- + "3yt9LhPxcZukGIVvcQnBxLswghEVBgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcE"
- + "CGObmTycubs2gIIQ8AKUC8ciGPxa3sFJ1EPeX/nRwYGNAarlpVnG+07NITL2"
- + "pUzqZSgsYh5JiKd8TptQBZNdebzNmCvjrVv5s9PaescGcypL7FNVPEubh0w/"
- + "8h9rTACqUpF5yRgfcgpAGeK29F1hyZ1WaIH43avUCaDnrZcOKB7wc1ats1aQ"
- + "TSDLImyFn4KjSo5k0Ec/xSoWnfg391vebp8eOsyHZhFMffFtKQMaayZNHJ7Q"
- + "BzG3r/ysUbkgI5x+0bX0QfZjEIs7yuV5Wt8DxMTueCm3RQ+HkR4lNdTBkM4V"
- + "qozCqC1SjcAF5YHB0WFkGouEPGgTlmyvLqR2xerEXVZn9YwSnT48kOde3oGt"
- + "EAYyg0yHbNbL0sp6LDM7upRmrgWwxf0BR6lP4wyWdv/XSLatEB7twSNiPBJ4"
- + "PJ+QagK08yQJ84UB7YpMTudKsaUs7zW76eA7KkW3TndfDYGdhbmZ5wxNl+5x"
- + "yPZc/jcQHW7vplMfWglUVxnzibNW12th0QXSB57Mzk8v1Rvc/HLGvAOJZG/S"
- + "N12FZOxbUrMIHGi3kXsmfWznVyq92X4P9tuDDD7sxkSGsyUAm/UJIZ3KsXhV"
- + "QeaRHVTVDxtJtnbYxBupy1FDBO6AhVrp16Blvnip9cPn/aLfxDoFHzmsZmEg"
- + "IcOFqpT1fW+KN6i/JxLD3mn3gKzzdL1/8F36A2GxhCbefQFp0MfIovlnMLFv"
- + "mrINwMP8a9VnP8gIV5oW5CxmmMUPHuGkXrfg+69iVACaC2sTq6KGebhtg9OC"
- + "8vZhmu7+Eescst694pYa3b8Sbr5bTFXV68mMMjuRnhvF2NZgF+O0jzU+sFps"
- + "o7s1rUloCBk1clJUJ/r+j9vbhVahCeJQw62JAqjZu4R1JYAzON3S7jWU5zJ7"
- + "pWYPSAQkLYUz3FmRRS2Yv65mXDNHqR9vqkHTIphwA9CLMKC2rIONxSVB57q1"
- + "Npa/TFkVdXnw+cmYjyFWiWeDP7Mw0Kwy7tO008UrBY0rKQU466RI5ezDqYPc"
- + "Lm73dUH2EjUYmKUi8zCtXpzgfTYVa/DmkbVUL9ThHMVRq1OpT2nctE7kpXZk"
- + "OsZjEZHZX4MCrSOlc10ZW7MJIRreWMs70n7JX7MISU+8fK6JKOuaQNG8XcQp"
- + "5IrCTIH8vmN2rVt4UT8zgm640FtO3jWUxScvxCtUJJ49hGCwK+HwDDpO6fLw"
- + "LFuybey+6hnAbtaDyqgsgDh2KN8GSkQT9wixqwQPWsMQ4h0xQixf4IMdFOjP"
- + "ciwp3ul8KAp/q70i0xldWGqcDjUasx6WHKc++rFjVJjoVvijKgEhlod5wJIw"
- + "BqQVMKRsXle07NS1MOB+CRTVW6mwBEhDDERL+ym2GT2Q4uSDzoolmLq2y5vL"
- + "+RfDHuh3W0UeC3Q5D2bJclgMsVjgfQUN19iD+lPFp2xvLTaNWi5fYDn4uuJL"
- + "lgVDXIMmM8I+Z2hlTXTM1Pldz2/UFe3QXTbYnjP6kfd7Bo2Webhhgs/YmSR2"
- + "XPuA42tWNAAjlK77lETWodxi3UC7XELjZ9xoGPRbxjOklXXvev9v5Vo+vcmN"
- + "0KrLXhLdkyHRSm81SRsWoadCTSyT8ibv66P00GOt+OlIUOt0YKSUkULQfPvC"
- + "EgMpeTm1/9l8n9bJ6td5fpJFDqLDm+FpJX6T2sWevV/Tyt6aoDPuET5iHBHW"
- + "PoHxKl8YPRHBf+nRWoh45QMGQWNSrJRDlO8oYOhdznh4wxLn3DXEfDr0Z7Kd"
- + "gEg6xr1XCobBn6Gi7wWXp5FDTaRF41t7fH8VxPwwDa8Yfu3vsgB6q426kjAj"
- + "Q77wx1QFIg8gOYopTOgqze1i4h1U8ehP9btznDD6OR8+hPsVKoXYGp8Ukkc7"
- + "JBA0o8l9O2DSGh0StsD94UhdYzn+ri7ozkXFy2SHFT2/saC34NHLoIF0v/aw"
- + "L9G506Dtz6xXOACZ4brCG+NNnPLIcGblXIrYTy4+sm0KSdsl6BGzYh9uc8tu"
- + "tfCh+iDuhT0n+nfnvdCmPwonONFb53Is1+dz5sisILfjB7OPRW4ngyfjgfHm"
- + "oxxHDC/N01uoJIdmQRIisLi2nLhG+si8+Puz0SyPaB820VuV2mp77Y2osTAB"
- + "0hTDv/sU0DQjqcuepYPUMvMs3SlkEmaEzNSiu7xOOBQYB8FoK4PeOXDIW6n2"
- + "0hv6iS17hcZ+8GdhwC4x2Swkxt99ikRM0AxWrh1lCk5BagVN5xG79c/ZQ1M7"
- + "a0k3WTzYF1Y4d6QPNOYeOBP9+G7/a2o3hGXDRRXnFpO7gQtlXy9A15RfvsWH"
- + "O+UuFsOTtuiiZk1qRgWW5nkSCPCl2rP1Z7bwr3VD7o6VYhNCSdjuFfxwgNbW"
- + "x8t35dBn6xLkc6QcBs2SZaRxvPTSAfjON++Ke0iK5w3mec0Br4QSNB1B0Aza"
- + "w3t3AleqPyJC6IP1OQl5bi+PA+h3YZthwQmcwgXgW9bWxNDqUjUPZfsnNNDX"
- + "MU9ANDLjITxvwr3F3ZSfJyeeDdbhr3EJUTtnzzWC6157EL9dt0jdPO35V0w4"
- + "iUyZIW1FcYlCJp6t6Sy9n3TmxeLbq2xML4hncJBClaDMOp2QfabJ0XEYrD8F"
- + "jq+aDM0NEUHng+Gt9WNqnjc8GzNlhxTNm3eQ6gyM/9Ip154GhH6c9hsmkMy5"
- + "DlMjGFpFnsSTNFka2+DOzumWUiXLGbe4M3RePl1N4MLwXrkR2llguQynyoqF"
- + "Ptat2Ky5yW2q9+IQHY49NJTlsCpunE5HFkAK9rY/4lM4/Q7hVunP6U4a0Kbu"
- + "beFuOQMKQlBZvcplnYBefXD79uarY/q7ui6nFHlqND5mlXMknMrsQk3papfp"
- + "OpMS4T07rCTLek0ODtb5KsHdIF76NZXevko4+d/xbv7HLCUYd8xuOuqf+y4I"
- + "VJiT1FmYtZd9w+ubfHrOfHxY+SBtN6fs02WAccZqBXUYzZEijRbN2YUv1OnG"
- + "rfYe4EcfOu/Sa+wLbB7msYpLfvUfEO3iseKf4LXZkgtF5P610PBZR8edeSgr"
- + "YZW+J0K78PRAl5nEi1mvzBxi9DyNf6iQ9mWLyyCmr9p9HGE+aCMKVCn9jfZH"
- + "WeBDAJNYDcUh5NEckqJtbEc2S1FJM7yZBWLQUt3NCQvj+nvQT45osZ3BJvFg"
- + "IcGJ0CysoblVz4fCLybrYxby9HP89WMLHqdqsIeVX8IJ3x84SqLPuzrqf9FT"
- + "ZVYLo0F2oBjAzjT7obt9+NJc/psOMCg+OGQkAfwj3VNvaqkkQsVxSiozgxrC"
- + "7KaTXuAL6eKKspman96kz4QVk9P0usUPii+LFnW4XYc0RNfgJVO6BgJT7pLX"
- + "NWwv/izMIMNAqSiWfzHHRVkhq4f1TMSF91auXOSICpJb3QQ4XFh52Mgl8+zs"
- + "fobsb0geyb49WqFrZhUu+X+8LfQztppGmiUpFL+8EW0aPHbfaf4y9J1/Wthy"
- + "c28Yqu62j/ljXq4Qa21uaEkoxzH1wPKCoKM9TXJtZJ39Yl9cf119Qy4M6QsB"
- + "6oMXExlMjqIMCCWaLXLRiqbc2Y7rZHgEr08msibdoYHbSkEl8U+Kii2p6Vdx"
- + "zyiEIz4CadrFbrAzxmrR/+3u8JuBdq0K3KNR0WWx73BU+G0rgBX56GnP7Ixy"
- + "fuvkRb4YfJUF4PkDa50BGVhybPrIhoFteT6bSh6LQtBm9c4Kop8Svx3ZbqOT"
- + "kgQDa0n+O0iR7x3fvNZ0Wz4YJrKGnVOPCqJSlSsnX6v2JScmaNdrSwkMTnUf"
- + "F9450Hasd88+skC4jVAv3WAB03Gz1MtiGDhdUKFnHnU9HeHUnh38peCFEfnK"
- + "WihakVQNfc72YoFVZHeJI5fJAW8P7xGTZ95ysyirtirxt2zkRVJa5p7semOw"
- + "bL/lBC1bp4J6xHF/NHY8NQjvuhqkDyNlh3dRpIBVBu6Z04hRhLFW6IBxcCCv"
- + "pjfoxJoox9yxKQKpr3J6MiZKBlndZRbSogO/wYwFeh7HhUzMNM1xIy3jWVVC"
- + "CrzWp+Q1uxnL74SwrMP/EcZh+jZO4CYWk6guUMhTo1kbW03BZfyAqbPM+X+e"
- + "ZqMZljydH8AWgl0MZd2IAfajDxI03/6XZSgzq24n+J7wKMYWS3WzB98OIwr+"
- + "oKoQ7aKwaaT/KtR8ggUVYsCLs4ScFY24MnjUvMm+gQcVyeX74UlqR30Aipnf"
- + "qzDRVcAUMMNcs0fuqePcrZ/yxPo+P135YClPDo9J8bwNpioUY8g+BQxjEQTj"
- + "py3i2rAoX+Z5fcGjnZQVPMog0niIvLPRJ1Xl7yzPW0SevhlnMo6uDYDjWgQ2"
- + "TLeTehRCiSd3z7ZunYR3kvJIw1Kzo4YjdO3l3WNf3RQvxPmJcSKzeqKVxWxU"
- + "QBMIC/dIzmRDcY787qjAlKDZOdDp7qBKIqnfodWolxBA0KhvE61eYabZqUCT"
- + "G2HJaQE1SvOdL9KM4ORFlxE3/dqv8ttBJ6N1qKk423CJjajZHYTwf1dCfj8T"
- + "VAE/A3INTc6vg02tfkig+7ebmbeXJRH93KveEo2Wi1xQDsWNA+3DVzsMyTqV"
- + "+AgfSjjwKouXAznhpgNc5QjmD2I6RyTf+hngftve18ZmVhtlW5+K6qi62M7o"
- + "aM83KweH1QgCS12/p2tMEAfz//pPbod2NrFDxnmozhp2ZnD04wC+6HGz6bX/"
- + "h8x2PDaXrpuqnZREFEYzUDKQqxdglXj5oE/chBR8+eBfYSS4JW3TBkW6RfwM"
- + "KOBBOOv8pe3Sfq/bg7OLq5bn0jKwulqP50bysZJNlQUG/KqJagKRx60fnTqB"
- + "7gZRebvtqgn3JQU3fRCm8ikmGz9XHruoPlrUQJitWIt4AWFxjyl3oj+suLJn"
- + "7sK62KwsqAztLV7ztoC9dxldJF34ykok1XQ2cMT+uSrD6ghYZrmrG5QDkiKW"
- + "tOQCUvVh/CorZNlON2rt67UvueMoW+ua25K4pLKDW316c2hGZRf/jmCpRSdb"
- + "Xr3RDaRFIK6JpmEiFMMOEnk9yf4rChnS6MHrun7vPkf82w6Q0VxoR8NRdFyW"
- + "3mETtm2mmG5zPFMMD8uM0BYJ/mlJ2zUcD4P3hWZ8NRiU5y1kazvrC6v7NijV"
- + "o459AKOasZUj1rDMlXDLPloTHT2ViURHh/8GKqFHi2PDhIjPYUlLR5IrPRAl"
- + "3m6DLZ7/tvZ1hHEu9lUMMcjrt7EJ3ujS/RRkuxhrM9BFlwzpa2VK8eckuCHm"
- + "j89UH5Nn7TvH964K67hp3TeV5DKV6WTJmtIoZKCxSi6FFzMlky73gHZM4Vur"
- + "eccwycFHu+8o+tQqbIAVXaJvdDstHpluUCMtb2SzVmI0bxABXp5XrkOOCg8g"
- + "EDZz1I7rKLFcyERSifhsnXaC5E99BY0DJ/7v668ZR3bE5cU7Pmo/YmJctK3n"
- + "m8cThrYDXJNbUi0c5vrAs36ZQECn7BY/bdDDk2NPgi36UfePI8XsbezcyrUR"
- + "ZZwT+uQ5LOB931NjD5GOMEb96cjmECONcRjB0uD7DoTiVeS3QoWmf7Yz4g0p"
- + "v9894YWQgOl+CvmTERO4dxd7X5wJsM3Y0acGPwneDF+HtQrIpJlslm2DivEv"
- + "sikc6DtAQrnVRSNDr67HPPeIpgzThbxH3bm5UjvnP/zcGV1W8Nzk/OBQWi0l"
- + "fQM9DccS6P/DW3XPSD1+fDtUK5dfH8DFf8wwgnxeVwi/1hCBq9+33XPwiVpz"
- + "489DnjGhHqq7BdHjTIqAZvNm8UPQfXRpeexbkFZx1mJvS7so54Cs58/hHgQN"
- + "GHJh4AUCLEt0v7Hc3CMy38ovLr3Q8eZsyNGKO5GvGNa7EffGjzOKxgqtMwT2"
- + "yv8TOTFCWnZEUTtVA9+2CpwfmuEjD2UQ4vxoM+o=");
-
- byte[] longTagged = Hex.decode("9f1f023330");
-
- public void testClassCast()
- throws IOException
- {
- parseEnveloped(classCastTest);
- }
-
- public void testDerExp()
- throws IOException
- {
- parseEnveloped(derExpTest);
- }
-
- public void testLongTag()
- throws IOException
- {
- ASN1StreamParser aIn = new ASN1StreamParser(longTagged);
-
- ASN1TaggedObjectParser tagged = (ASN1TaggedObjectParser)aIn.readObject();
-
- assertEquals(31, tagged.getTagNo());
- }
-
- private void parseEnveloped(byte[] data) throws IOException
- {
- ASN1StreamParser aIn = new ASN1StreamParser(data);
-
- ContentInfoParser cP = new ContentInfoParser((ASN1SequenceParser)aIn.readObject());
-
- EnvelopedDataParser eP = new EnvelopedDataParser((ASN1SequenceParser)cP.getContent(BERTags.SEQUENCE));
-
- eP.getRecipientInfos().toASN1Primitive(); // Must drain the parser!
-
- EncryptedContentInfoParser ecP = eP.getEncryptedContentInfo();
-
- ASN1OctetStringParser content = (ASN1OctetStringParser)ecP.getEncryptedContent(BERTags.OCTET_STRING);
-
- Streams.drain(content.getOctetStream());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/ParsingTest.java b/core/src/test/java/org/bouncycastle/asn1/test/ParsingTest.java
deleted file mode 100644
index c5a33532..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/ParsingTest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1StreamParser;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class ParsingTest
- extends SimpleTest
-{
- String[] streams = {
- "oRNphCO0F+jcMQKC1uMO8qFBPikDDYmtfVGeB45xvbfj1qu696YGjdW2igRnePYM/KkQtADG7gMHIhqBRcl7dBtkejNeolOklPNA3NgsACTiVN9JFUsYq0a5842+TU+U2/6Kt/D0kvz0WmwWFRPHWEWVM9PYOWabGsh28Iucc6s7eEqmr8NEzWUx/jM3dmjpFYVpSpxt2KbbT+yUO0EqFQyy8hQ7JvKRgv1AoWQfPjMsfjkKgxnA8DjenmwXaZnDaKEvQIKQl46L1Yyu3boN082SQliSJMJVgNuNNLFIt5QSUdG1ant5O6f9Yr0niAkAoqGzmqz+LZE1S7RrGHWiQ3DowE9NzviBuaAoI4WdCn1ClMwb9fdEmBMU4C7DJSgs3qaJzPUuaAT9vU3GhZqZ0wcTV5DHxSRzGLqg9JEJRi4qyeuG3Qkg3YBtathl+FiLJ7mVoO3dFIccRuuqp2MpMhfuP1DxHLNLNiUZEhLMQ0CLTGabUISBuyQudVFlKBZIpcLD0k7fKpMPuywrYiDrTinMc2ZP3fOGevoR5fnZ6kZAE5oMTtMNokzBuctGqVapblXNrVMLYbriT538oYz5",
- "KEKVhHxtyUR9D3v5K4IJbVQLAMiVKoK9z7wFWUjzvLFNLg9C/r8zKfBa3YgZrt0Nq64+MxBePMbiNLCnfditc2qUcQZUHnvNnhwT6uGK37JmXg7MvQiKwvi31EIYt6ghqBZVs1iaqc0ep7wuQ16uwSQMlaDdXc9Qf1L0dGO/6eLyREz+p4UR4NOXK+GooQLfMxYL40zJlYcwNyR0rigvIr84WP2IMS2hZjqXtyS6HMM4yUv70hkIorjr7+JC4GtU1MyWuPuNSAGen0AZTaEEXd5sMbqXMqWg3jeM4mzRH1Kb3WdAChO5vMJZPBj9jZZKgXzmxkUh5GlIhUdYgztoNceBzQ3PIc7slCDUw9I2PjB87xsfy7jA5tFtFADs2EUyxUTMCuhilP664jSHgwbrr80k9Xc4sU+MCwCq2nQmcZYcPgKb4M31VJMlKwnZF3JUU2Jtqgg4gbErw58YoBwSkEcMJ2Juhiyx9U36MzxHs9OcTURfpsilMy+mDL8arCDx1knM1KkAHCLjWuJI+p1PvuIypgCwVc+MtGfd7wW8iR1JPJLBiuoZyNJ+xx9htd/HVB+rLtB57H8Gz8W+R00f",
- "Ol9I/rXMwbLpxTY97v70B+HCl2+cojz2574x/cC56A7KGVF13La8RdzOOvSkl338ct9T/blEFa6QwNz3GmF+MoPdH9lncwz+tqixIqGU02Bp5swH0qjbp/Yjaeq91eR6B+9fl+KKrpglBr8S1BrI4Ey5v3AxxJdCWP8Gd+6Sp15/HMYanwlHBpCsW4+Kq8sGJoJXUXpQ/GBUJKs+WjX1zE6PsvF7/B8cByuqE3NJt7x4Oa+qZtF8qNc0CFDNj31Yhdt7JkAoD30IAd+ue9OhImQMCWwFwySRIRJXU3865K2dBR+VhLuI2aKzLh7MlgVKJk6b2P/ZIkc86ksR1sOUiHrs9EdoYuIssAgMc8QGzn4VN8lxopdzQYVG6pbXGS/VQlHkGdyLd+OHt4srz/NTUWiOquVTRxa6GgtlBFfIXikPTb+iT2pZKyKUlBvpgo0BY9vVUadsteHAI5qrFZBrL5ecK/Qtl9hf/M8qEjyjt2aCXe9B96Hg2QR5A53qW2PJW5VzS0AeB3g+zJSPCTpygrBs20q5Xrna0ux2l17r6HT9Q/AXIOkwPZUXXn0d02igS4D6Hxrg3Fhdp+OTXL8G",
- "o3eXWpwAGmUkxHEKm/pGkDb1ZQQctCQ06lltZjeMXDp9AkowmA0KXjPQCQwyWE/nqEvk2g/58AxNU0TWSujo5uU0h4/hdMZ7Mrj33NSskWvDpKe7lE5tUjPi74Rmc5RRS+1T/EQobpNxoic3+tTO7NBbZfJtcUYeZ3jqxL+3YQL3PrGe/Zpno9TnQW8mWbbhKhDRtKY4p3Pgk9hPSpJCM9xYo3EMAOAIiH2P6RKH6uX/gSaUY2b6DE/TT0V6v/jdSmYM4+cnYiTyJCi5txI35jfCqIlVCXJd7klirvUMg9SXBhGR25AgQ5Z8yjd7lbB8FvD8JQAXZrp6xiHxbLIW7G11fWEo7RGLFtALI6H38Ud0vKjsEN7N5AibJcxS2A/CWk9R00sTHRBHFUP8o5mz8nE7FeCiwJPs/+tCt04nGb9wxBFMsmWcPEDfIzphCaO6U/D/tQHlA846gbKoikv/6LI0ussSR/i85XBclNcvzTctxylSbCR02lZ+go6fe5rmMouiel/0Tndz8t1YpQGilVeOQ3mqAFyAJk3dgfTNKZuOhNzVIZ5GWScKQ5ZtNcWrg6siR+6YwKvLiRb/TJZk",
- "PwRUnW4yU8PI7ggbI1BIO9fcTup8optkqCirodyHCiqsPOMZ4g28bJ2+kpfQRujWGlKFYQzA1ZT32s9hdci+fvXPX0KAjcUgcxsGzMABFbEm04BwDF2WLgg9s4/x71r5JrgME1S08I3mCo4N0eFHWDeLJL1b5YNNo6tfO5V2WpIE867N9zdAgvp1gijVjUNWqEB3A/NLb3reLMu2hYgqRFTCVBfcFclD46k0XEfUJqwWdQhOz92WNl/3g53bjKX1hDZgjLIzK6m+SU6+J/h4NidrS7E0gOBevZW8gRYdKMVqNWxzUfxv6kgG+kIeF9JqMcO6jdh/Zu/0tpZoHFeCweZ1jT1eEtltFu1FcTTPc1UT0pT+ZNVgefrBONoGnvn8+dBjPese6F2TmRCExJq9taKlIh/kHdkbpaa7vwrBpYRgVGfARPyM9SSCaE7pVBDuwkFeYiGU4tamm5Gq10ojRQgetJ3UOg/PGTJcxo97GBiG5zAST9NdHdgK3eI4FAbWpGwmWxNpPWOst0a7zuGKAzYU+1IQh8XA3IgJ2vy3+w0JihU6G+12LUzsL2aQtpG7d1PqLhwOqHq3Qqv3SDsB",
- "ZIAKizvGzbvqvqOlxOeVgHGHV9TfKNjjqyzbCj8tggv2yp7kkq1D3yRlC349tuul3zN9g4u83Ctio9Gg3HiLzMULxoOImF/hKRDhJpPLbLm0jSq1fyF+N7/YvyLeFhGoPhYEBUihDcxo1NIcWy66aBt3EuOlTyDQWrDe0Za3mrTrrl10uLHVKcQMgeD+UMgjQqmHzQJR8wdNjHPKHWVvZEdiwI031nV2giHJHXv08Jvf4vmw4dAlH2drCl6cBgg33jy7ohK8IiXz6eCw6iY9Ri8YaMzxOhgE2BOHzEz5ZC2hilL4xO/ambTER4bhb4+9VTUIehHP18FcXm8TKPQRMqyKP2fMlzWW3/uelYfPP5SHlyLAULa1KjDCkLIDunEKZDpv2ljGB6JPrTlNwFsvlZcihfOAwjbr2jW3MwP704OA8xzd/dynBU47unIZEu0LAvQ3TUz3PLga0GGO1LZGtg0Foo9zFG2wuVCdgYHmozOQ+8I3gRguW1CjGy7ZCTBuN1GZ510ERhae+bRQtldHsLeiHTghnkU1xEX1+W0iEf3csDYrgpuq3NaBYRGirovDiPBYFHmru0AMclhFnpcX",
- "uG0wQ55kMlfZtJFAqTl0bnYW/oy9NFOi0e4FqAYwsvMxGO4JtGzXgkVwEUAC0AUDItRUjxBl+TkoPTYaprgn0M/NQvKPpXJ+yzI7Ssi+F2alLR0T6eF/4rQ32AVjnANJaghXZm0ZKduckbhSxk5lilJVJRuzXKchZRtlPluvlj448bq+iThktsEQoNP8NMpi7n/EVxovp+dow4Q6t7msSRP4cGXtyYoWKbf/7e5XzBKOZZ1/f3s86uJke4dcKIaljpJfBrtuFxZC6NYXzX6PkoDoBgqQ8RBrxsX54S9cBDAPxxmkq8zviAOW3oqPMULGGmQzHBiRwE8oeDFoMnzF5aR/lkbNuTLOxhbIkosgLWlDNVEFYx9bVhdLzO7VwaAK829dimlPOo5loKB7Pd2G7ekRKXwu7wNvJBq8KRkhtLKbKoS8D6TaRWUMb9VBJ1CMy4mrw+YwTmAKURQ6Dko9J/RgzRg5Y/sUlwdMYS9HOnvKiTVu5I/ha35wwkhIPVm+FCn05tstntZaXXXu4xExHeugAKNBhkcc/SQt+GFdxXDd+R4C2LfKxGDSyZKVTFYojHTdZUo8Gx6SZLY6b2SZ",
- "sH0kIwIq1THAfTLfqUKJfG1YauCQKPc9/mk3l39yK6zgxSpCH2IjZIwhhJtGm3F+8PTneT725OuyR617nxqrgqMGkkZkyY4DA5CjsikpBo5mo8TspX1g+vtXXtxymJMTMo8JwX3nSH4gSb3vPia+gwOW2TcJmxVdp3ITPA4gJpMfqoMBqRM+eDWO6QXW5ijVL4+wnp40u5bU4fQLVzpg25+QGLqBHD6PZTQaN6F9Vy5XpsAGDlncCklVuX3Lkp3Xb9cTiNa/4ii04uwZqx0juszjwFAMPPb6u56crvN1x4FXfXzabWECHbdQLlKazowvU9bEnqG2i4H44Ae+v8Iw8HK5mbZ6ercLTD9oPgs7Ogal037l2WwLApUz/fmD5fV8SxHh+vKDpfOzv6xcQxynS82jAJw9AdUwE/4ndGzzHPIu2M81gbAgZQ02EurMMU62hYgiXeridrtyh+H5R+CiwQdEyX7/op6WVihsYj2O3O/1hgjhGQRFD6sGwnko50jgWRxaMMfJGNlyGoT8WT5k931jU7547u7Ovr7XP/t8r3G7ceCiCcYjQgdwXdvIStzPvvV7Yy02isZjiJF8TLJQ",
- "tycxf1mOz1yLE6cT/ZlCxMeTxlEEHFeIdw0+nF/40Tsw4vLco+4kR2A6cVml611CSpN6l/RMKk2LnAkprrbJ/Uam902WBnQ+I6Vsl6GkFFq7362bdixojqMFVKYytXLCT8I78f6s8M6a3jSALQloD6Ftvn+cc+cctO3weaaaPgAlrz+f2MFs8bqpnLQYbbY/JS9IAYJFH+yVtLz7eKcedEp9JMlJ3/43szU2fDN9ZMxBoQnxEmF3WZv6GF0WRc8VhTblXRgk4mlz6Fu3IXvwW/rbn+VCYYIk/XaVLrxFAnnw6mBozAF7vmV0OrIYBlSDU8rMb+F7AvE7pwErO9TJtCE8IUvQf8TsJYRoYv21/X57pzcBedtqVeU3DnTlmESHxG6H1uJbadSFLWSxKS4svfp8T9FWqX5815yD/UplAKEIeorLTAlPIC2ASKDU6SQW260biNAfY8FYQCWa8btaTwFuY8NMwSHzyqgU0aoPKnagi/4hOIWNO5rZ8Xcnzx+ELtEl33hQnzc4OUlT5eeVYQWkz2IWVQ6Re4JWF3L4OXzNZWgefKGMzZU6IHoBeCgfi+popLRJpaOx0dcvwGjk",
- "oDsoFvUA+sGOoMyZY6w1UhY3NBkeoozzjEkDSRN1golyXJ1dC5CtYNEjvAJYKj+sqNwg9mBlYyybYpnI3GSP125zMeBHPCoy5CoNOkJW4OH/oLyjVeQbFNic/b2Jcz6lTguYhep8hq9EM2XuFV8T1rm5+4ucI7fH1UiOqRZyuHBAJ0Cna5kv6D3efsa9rd+swybiMIUjmPWpyxzNOOihCYuf4JqRh/D5eZKm6x0Zj2uRhTAYYxI7Q3czd0R9490ufG8VbF8ASBMireMONNNAA/OZCpxJh6xnIANBqV6YDeysws3NBWY2QuNumvg5Kr3/g+VMzJHi4wGuJjraKWi9+ylMfelHF5h/h+pAQVxCotq8JU3OTnMUW4rQp2a8BR5S+mZqPSPlb87tDG9r0+yqb1uO4UIo71C7Xxwoq4M0tXjk6mSmtP/sm+Lh14qfUzKRhTHVdz91TK104mbTJNXbK+jGPD/2BJO9fiaXY8IYanpfDLBfJo06VYbm6HehRZTwnDHnN50j7ki4aMS3COZvffjRInXD8dS5h9zmtKNpoqg//lPg4gpS+4Th2sJ3SGtBV0Ne89r7AfZMAVa26PMK",
- "MIDLuZTrtZnEBOB6l14iSEyokAg5Wf5JviumhfPeL7WSFTHfOodU2hrvhyvM6oAlRHY1blTj7mw+Tcf9Tmc+/FHT6PGu0NT5UAqaqChX0gS9jizgAE2Yfhd4X/DoeQySMAixKuhu8TbvDxb54jeW9+7LVkmlntJ/0SkMgsT+WQ31OfpwDmEGDczYc+Ol14aJS+EW+rnGv9d38bo/cy+EnpNh8iV2rGGoC8fDzFHKU4gqGFSZF/tnD2OfCne0Vjr/GD6kyp2MVcHig19DBg2toGRkHnuY5kLkwOanztXA80IaAmv8e6s62U8CE8ozUZeDBcvBigEkSGx79Vsyiks8+9Kq9xLHLeS5kRT6zSl8whe8U1fIfrgic34KPlozcQVahwCru1XWyQ+9uevih8x4zMftkJ3JBZhPrnlgtx9McntH/Ss9fdUEkNwWpDnq8Xby8/5gMMMwQ13XDB73vqqteDiltMq8i7LRez4iIHfSBBfIkZIzMZAblQXaSm029iBcAAUes7wcGHUl7KOpRy18jNtI3+h7e1Ri6sT2vJYQaove0nzZ5xAjpBKnbJX+lpGVlI00fC2YSTfyNqFA0jkL",
- "MG4QbKLbQR3enPn6Z/kEUtHrzWBIqYKR7Gvs5QHLPF6417p1O58suZq38Bb8dO5udtgOqNEVAPGmOuidYygWWfWOP5ReggTUk5XlrkvRxCU0MHWbkSKkJ+T4nLjozreqTJ0io41sFVrpxuOugAvXJ6QtMmixSABUaNgU9SkkWf9pOEiJI8dfND51HxJCbXHwsMCMBp5FbaMZmlWPwirRdAox4wbLk9ZLmoWUcorUjdaWhKvT/LnjMgPmwnwwKpN/4MOnRDdAPdzXX3aWHdkzpfsQnqt3UJsTsSaJlzeUja5C5L4CXGyt99qmfcwB8OB9TL4EYTIl3maD/gUWBfckOsji8x2E2c2iuKKrcmMmcChYr4wCjtTjEeVKOAZ2m9mU2MKc2z2hDw3AuZxsY6aOtdAjnrwl5QXGRg9I5LVl5SI5RwnLwk90pJzDGuSSCtSmzh9DUZ4WpfN+1393aTGRqCMOsB4KxbXjspUbVMFJbnXXlsSNWaoFTpHjK6b6Ghi2/re7KJpoKElM3nGs3qvxdvGTKu7LKr/sgKDL6uQLRKoyk8AHSIGX9c8ZUTk7Sq9jV9p4QfV1WFVpaBxSsEmw",
- "MR0BACgWKis9/AKwG9/ARgGWJn1aM3nU8YXzWG+b7aeRUkVCjl4WxeL38E3FAMLW4UcyLzxeb+CskOqhPPTglmxhK7jQcrNILsWcZvdZfApYIvk5uKqA5FKuUuL48uvD0aKGRENe/VEUFlkQru5YX4Xnp+ZThrJJlgn7ANat/qAdP6ULEcLaOQlLYcGRh5ttsJTRT4+cZQggTJjWt+9idUQ66HfC6zQ1qHcMuochy7GHiUmNXAs0AgwOF9Jwet/Qh74KGMtmppJ9gkEqiYECFQA2gVgKc1AufHJS6S6Re72FfH/UkL41L2hvlwktkD5/hZrUZ1R+RG12Eip2zKgus4g/aGl0V8B/JvkcnFUsZJ6uxs24arOBDJOuzzxky5F5B/hwVGPEdcfHunqndUcx26/KCK72hOljlqTXl8yEbXlcMqVFNByZLr7TnGzGGUlO7kuHPW/ItZUJvrHokpsLLrb3ZhEZ8pTQd75gFcf0Ve8CYzEtk2ISHtNJQV6Iz4AZHWssU6F6YWM/OlJz5JGTtPHfGMJXgl4oxbBjeenS3JQ0X7vWXYMwPe3U1dat6m5hrRC1KzI6e6w+gPDtF8GQ",
- "DH2WX6XoIseX6lHIey3seUr3DAz82fyk0jL7xc5IDTrDfqS64QBhHDpqHETF/81MrPXsM3IANBfjDOl9g/gua8wWPpPNxuWZMNh0GLcAr6PJ939TCbjE3soZHF2wiA82nZEO8jIZosDVRWFUfJS6Y3nrJz63SExqB6OUdBfvSfz1Y1M/90ofBxkfeuS85deMdn+1rZdsnZJYwz2Z6lCDvYjUTfrSwfVFJBP8Y2BXr8WClUYkfGG4eNG7IPNBRuMmhrhHj5y9z+5Jor+EbbTi5F5Jvdu2/bDM7s32XsaMNLYuVtNYONrbQ+3QZ746/yKZM4hDREvxyGLgDx3Apz7pyvwKm0//iTCY3yJLxZifGLh2uc28cFBln7IH1x8oui4Xq9vF+Z2EH4Ow48Ln5pzggBKMGy4dsfW6266TNYd/Z3SZUi28sxondqhGCSGUo7ZVPAOoYDcYKvjdI/cJ688PHliyZSYBYVmR5HBxZ57sqWwgZQ7zVvwv4CHHysvb92sPrXijHxBIkwpNuK56UMyQCcywlTRLDCMAMNAEGi4fWbDQIoPfn+NixMhEieg3Zh7GXPwHxW8morlgBW5aF76P",
- "AwClK6Tq9R2DYGf8RAHu9dEttLeOfUVmS4WPwX0NehsnyM7y7n2sgGnXsiva3yFqK1hKZICkVukvHF7/bpgEEm/jRwcAhQUoG+c1qVde38eHJXj58YOBGTveruc+021or9/tHBtenmYPO6+arLQtONi43NKm7+I6ugkgQlp6iBr4haa0XMDTzMX9c8Qm/O+MrVo3qESYKkVtoSSK7SGZTBaRWNF/dOM0NQxeMP+XTVOuroqE23ZNsubBTEZnd4vUilFb/iKnhyT9XnIo7gM/Yz7HLVU5yc3yIj2sFUE+DcwpvcNO5EnPhj3bHsJvf3N4r72+5my2KjoR3KAJE1Imabd54o4xZ/9UaR93qLkVuXMkLRCCU/zlZDtfbJDsRR0C5rSYd2k6IPlNcl7PgmUpsNPUyoDYqvhuRUZxgoUAfKbogzJX8FU/QpllsKVtt68ucBi0bqC5pVKu23j79nDvYQsSlYY3JwJQaM5M558J5qpP1yEF2p4kSRphnB9UR29wWgch5eWZ4a02LlHVM5Msl6W5PdmHt+eFARBRv6edIyYDFzxm4WZroH5F/GxBhM0KObgawkxa5VWsYm0VhhXb",
- "KACwq8rZuOLHuNnZJA07WzI7kppCwptbcYU2B7t86QcZrnadCtxoM5QNcl9rsbMA26iWCPV3VlDAmLSWcxtMoSKWuo4edJpk8K915xkFU5U6I/901vx5hqAECQDy/Q+QDWmWTXDoVHqFV9wvIj3wCJPpJL/Ewpl0NZd+68jjOjUhjIdNebLrWNK2nhTPiIjFjkcVqEgashpOmnbHT+2MV/CHoixmUEiuRI1B0dvSf7FHGRgbXGBubisuu60g8XTens5zyRo4Qn/LTxIu2aj4LTtyLonV3sXr+y35A1zq5mCrE1f1nOINVzwYYY76iJGIaBkZuMU3366FPIbYkmXwla6RQU1FA0Y7n05qczw7Ie5TveRTByKFtUqW8OAb9vH+H2ezJ4CXE3AGbu/nTj64KClO/zL499GA+97g+X6tTN6xOJdNknlqw6ZnFNtCL8+A3hL4OyOgWD0IGC+xFvcKjDUaaJenCtQvprCJaFrvoOS+yYmixnFqglnPYL/64/Lca8NmDVpPzlHI8HNwUDzKiXTw3q7GnQZWmUYzu1vLIEi6/hyqrULRN1vLdd/8HCMNQFj4ot61UftHtOG8MCKa",
- "rUABPQ3SEWE5rY16pM+o+7EObLNM1jEa5YCMQM/aen0PWajWNax3Pyo6TZL8aGDXZF0yWqDM3b2m6UHOr6yqsUSrD+0jXPT48QN1VdBmh+AFRK+UcaYO383a0nvtv0c9uHt4yfceXLPGWrNjW+uTnS/lKpCdpE4GfLF1SFHIUcMxT+3At7hwDHNkLXllEXqbgDP8LyQSlYwT5jQUDCOzwc8CSxAryUOj6fN+iLKAiw4haPV/WZDG+JOmDMG2azo8SoBMi3y6Z2Le2fz2dMuvn5DUvCUvazrUmWYx4NEdSzc9GfBc6cXkduMqCs+lT2Ik2GHO0WjhrEB6j5NULOaCtbrislM85P6QutN4Pj9l18pcD6vZCcDTOwMj/BznclH342jeMn7rBgpW1YSzbNGP6KC4NeNW1H2xqNtuyhcJvasx4dwhzO18A36H6HtkiQyJNnfnVHh1oviO6mi3atmnh9B/55ugXM1Wf/6Kv8kJyaKtK8cWo+jCAR0/P/EsPtzToJM9Yk2+qxaPFd3k7T2KXvCQ9D1jLeECxL59L+WDvdBtxOEBD7W0a/Mn/9LuQPOiwARKJSTU+blJ6ezTeo83",
- "poA1hF4zRh7HF0xVglYoLFqkUR7Pru/qYFnfMKBPuEOOGdgO3MMcAvIZ+w+Ug4THr/6+Vux0TN3wdOB+beObOboLgNE2zaD65lyMFbaulzrEnWjUgIg63CdpQJ2ESaimHGg/GmsipUCndRJ37TbUtn8W112SehsAgrsjiBcuJhw61i4bVfAZEcycq4Y/FlEDxtzoH8WzDoESNbl+r5agLcHGr37BFi81IXS8TLihC1T8b7d6tLb6lpXT+9IR4xAyZTw1IFMDZZEzVmHgYE/Et20/WhkX/oGghkWSpCxR0kynDplk+BEK2oyGKnl+rf4vymhsse2iQ/C99PhaodZjDfuGVSwPLoU0AYyAKaEwmgHPOFbDlrAmNk4iBp+IZYm9guZM2hcQ4GeA5WQyZzw4C1yMywWbdjtL9ZhpClmmPZ28nmwNORAat7tXPJoBBdXFB0gNT/wU7UYIKU5GnAiDIFJ0o8ijnuAMat3AsBki2vxwdypuBq5M6OF9DVA0HRUjOA0l4JHjK8Y282mz3U34PDPQvwCT342uD9cO3uXoSr3T2FnDmsVHz4Q9zYpSjioLmZk9ZTnQWgN5V5Oyat6m"
- };
-
- public String getName()
- {
- return "ParsingTest";
- }
-
- public void performTest()
- throws Exception
- {
- inputStreamTest();
- parserTest();
- }
-
- private void parserTest()
- {
- for (int i = 0; i != streams.length; i++)
- {
- ASN1StreamParser aIn = new ASN1StreamParser(Base64.decode(streams[i]));
-
- try
- {
- Object obj;
-
- while ((obj = aIn.readObject()) != null)
- {
-
- }
-
- fail("bad stream parsed successfully!");
- }
- catch (IOException e)
- {
- // ignore
- }
- }
- }
-
- private void inputStreamTest()
- {
- for (int i = 0; i != streams.length; i++)
- {
- ASN1InputStream aIn = new ASN1InputStream(Base64.decode(streams[i]));
-
- try
- {
- Object obj;
-
- while ((obj = aIn.readObject()) != null)
- {
-
- }
-
- fail("bad stream parsed successfully!");
- }
- catch (IOException e)
- {
- // ignore
- }
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new ParsingTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/PersonalDataUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/PersonalDataUnitTest.java
deleted file mode 100644
index 95a3120a..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/PersonalDataUnitTest.java
+++ /dev/null
@@ -1,121 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.x500.DirectoryString;
-import org.bouncycastle.asn1.x509.sigi.NameOrPseudonym;
-import org.bouncycastle.asn1.x509.sigi.PersonalData;
-
-public class PersonalDataUnitTest
- extends ASN1UnitTest
-{
- public String getName()
- {
- return "PersonalData";
- }
-
- public void performTest()
- throws Exception
- {
- NameOrPseudonym nameOrPseudonym = new NameOrPseudonym("pseudonym");
- BigInteger nameDistinguisher = BigInteger.valueOf(10);
- ASN1GeneralizedTime dateOfBirth= new ASN1GeneralizedTime("20070315173729Z");
- DirectoryString placeOfBirth = new DirectoryString("placeOfBirth");
- String gender = "M";
- DirectoryString postalAddress = new DirectoryString("address");
-
- PersonalData data = new PersonalData(nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, gender, postalAddress);
-
- checkConstruction(data, nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, gender, postalAddress);
-
- data = new PersonalData(nameOrPseudonym, null, dateOfBirth, placeOfBirth, gender, postalAddress);
-
- checkConstruction(data, nameOrPseudonym, null, dateOfBirth, placeOfBirth, gender, postalAddress);
-
- data = new PersonalData(nameOrPseudonym, nameDistinguisher, null, placeOfBirth, gender, postalAddress);
-
- checkConstruction(data, nameOrPseudonym, nameDistinguisher, null, placeOfBirth, gender, postalAddress);
-
- data = new PersonalData(nameOrPseudonym, nameDistinguisher, dateOfBirth, null, gender, postalAddress);
-
- checkConstruction(data, nameOrPseudonym, nameDistinguisher, dateOfBirth, null, gender, postalAddress);
-
- data = new PersonalData(nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, null, postalAddress);
-
- checkConstruction(data, nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, null, postalAddress);
-
- data = new PersonalData(nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, gender, null);
-
- checkConstruction(data, nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, gender, null);
-
- data = PersonalData.getInstance(null);
-
- if (data != null)
- {
- fail("null getInstance() failed.");
- }
-
- try
- {
- PersonalData.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- PersonalData data,
- NameOrPseudonym nameOrPseudonym,
- BigInteger nameDistinguisher,
- ASN1GeneralizedTime dateOfBirth,
- DirectoryString placeOfBirth,
- String gender,
- DirectoryString postalAddress)
- throws IOException
- {
- checkValues(data, nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, gender, postalAddress);
-
- data = PersonalData.getInstance(data);
-
- checkValues(data, nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, gender, postalAddress);
-
- ASN1InputStream aIn = new ASN1InputStream(data.toASN1Object().getEncoded());
-
- ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
-
- data = PersonalData.getInstance(seq);
-
- checkValues(data, nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, gender, postalAddress);
- }
-
- private void checkValues(
- PersonalData data,
- NameOrPseudonym nameOrPseudonym,
- BigInteger nameDistinguisher,
- ASN1GeneralizedTime dateOfBirth,
- DirectoryString placeOfBirth,
- String gender,
- DirectoryString postalAddress)
- {
- checkMandatoryField("nameOrPseudonym", nameOrPseudonym, data.getNameOrPseudonym());
- checkOptionalField("nameDistinguisher", nameDistinguisher, data.getNameDistinguisher());
- checkOptionalField("dateOfBirth", dateOfBirth, data.getDateOfBirth());
- checkOptionalField("placeOfBirth", placeOfBirth, data.getPlaceOfBirth());
- checkOptionalField("gender", gender, data.getGender());
- checkOptionalField("postalAddress", postalAddress, data.getPostalAddress());
- }
-
- public static void main(
- String[] args)
- {
- runTest(new PersonalDataUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/ProcurationSyntaxUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/ProcurationSyntaxUnitTest.java
deleted file mode 100644
index 32120bb2..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/ProcurationSyntaxUnitTest.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.isismtt.x509.ProcurationSyntax;
-import org.bouncycastle.asn1.x500.DirectoryString;
-import org.bouncycastle.asn1.x509.GeneralName;
-import org.bouncycastle.asn1.x509.GeneralNames;
-import org.bouncycastle.asn1.x509.IssuerSerial;
-import org.bouncycastle.asn1.x509.X509Name;
-
-public class ProcurationSyntaxUnitTest
- extends ASN1UnitTest
-{
- public String getName()
- {
- return "ProcurationSyntax";
- }
-
- public void performTest()
- throws Exception
- {
- String country = "AU";
- DirectoryString typeOfSubstitution = new DirectoryString("substitution");
- GeneralName thirdPerson = new GeneralName(new X509Name("CN=thirdPerson"));
- IssuerSerial certRef = new IssuerSerial(new GeneralNames(new GeneralName(new X509Name("CN=test"))), new ASN1Integer(1));
-
- ProcurationSyntax procuration = new ProcurationSyntax(country, typeOfSubstitution, thirdPerson);
-
- checkConstruction(procuration, country, typeOfSubstitution, thirdPerson, null);
-
- procuration = new ProcurationSyntax(country, typeOfSubstitution, certRef);
-
- checkConstruction(procuration, country, typeOfSubstitution, null, certRef);
-
- procuration = new ProcurationSyntax(null, typeOfSubstitution, certRef);
-
- checkConstruction(procuration, null, typeOfSubstitution, null, certRef);
-
- procuration = new ProcurationSyntax(country, null, certRef);
-
- checkConstruction(procuration, country, null, null, certRef);
-
- procuration = ProcurationSyntax.getInstance(null);
-
- if (procuration != null)
- {
- fail("null getInstance() failed.");
- }
-
- try
- {
- ProcurationSyntax.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- ProcurationSyntax procuration,
- String country,
- DirectoryString typeOfSubstitution,
- GeneralName thirdPerson,
- IssuerSerial certRef)
- throws IOException
- {
- checkValues(procuration, country, typeOfSubstitution, thirdPerson, certRef);
-
- procuration = ProcurationSyntax.getInstance(procuration);
-
- checkValues(procuration, country, typeOfSubstitution, thirdPerson, certRef);
-
- ASN1InputStream aIn = new ASN1InputStream(procuration.toASN1Object().getEncoded());
-
- ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
-
- procuration = ProcurationSyntax.getInstance(seq);
-
- checkValues(procuration, country, typeOfSubstitution, thirdPerson, certRef);
- }
-
- private void checkValues(
- ProcurationSyntax procuration,
- String country,
- DirectoryString typeOfSubstitution,
- GeneralName thirdPerson,
- IssuerSerial certRef)
- {
- checkOptionalField("country", country, procuration.getCountry());
- checkOptionalField("typeOfSubstitution", typeOfSubstitution, procuration.getTypeOfSubstitution());
- checkOptionalField("thirdPerson", thirdPerson, procuration.getThirdPerson());
- checkOptionalField("certRef", certRef, procuration.getCertRef());
- }
-
- public static void main(
- String[] args)
- {
- runTest(new ProcurationSyntaxUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/ProfessionInfoUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/ProfessionInfoUnitTest.java
deleted file mode 100644
index 34b33070..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/ProfessionInfoUnitTest.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.isismtt.x509.NamingAuthority;
-import org.bouncycastle.asn1.isismtt.x509.ProcurationSyntax;
-import org.bouncycastle.asn1.isismtt.x509.ProfessionInfo;
-import org.bouncycastle.asn1.x500.DirectoryString;
-
-public class ProfessionInfoUnitTest
- extends ASN1UnitTest
-{
- public String getName()
- {
- return "ProfessionInfo";
- }
-
- public void performTest()
- throws Exception
- {
- NamingAuthority auth = new NamingAuthority(new ASN1ObjectIdentifier("1.2.3"), "url", new DirectoryString("fred"));
- DirectoryString[] professionItems = { new DirectoryString("substitution") };
- ASN1ObjectIdentifier[] professionOids = { new ASN1ObjectIdentifier("1.2.3") };
- String registrationNumber = "12345";
- DEROctetString addProfInfo = new DEROctetString(new byte[20]);
-
- ProfessionInfo info = new ProfessionInfo(auth, professionItems, professionOids, registrationNumber, addProfInfo);
-
- checkConstruction(info, auth, professionItems, professionOids, registrationNumber, addProfInfo);
-
- info = new ProfessionInfo(null, professionItems, professionOids, registrationNumber, addProfInfo);
-
- checkConstruction(info, null, professionItems, professionOids, registrationNumber, addProfInfo);
-
- info = new ProfessionInfo(auth, professionItems, null, registrationNumber, addProfInfo);
-
- checkConstruction(info, auth, professionItems, null, registrationNumber, addProfInfo);
-
- info = new ProfessionInfo(auth, professionItems, professionOids, null, addProfInfo);
-
- checkConstruction(info, auth, professionItems, professionOids, null, addProfInfo);
-
- info = new ProfessionInfo(auth, professionItems, professionOids, registrationNumber, null);
-
- checkConstruction(info, auth, professionItems, professionOids, registrationNumber, null);
-
- info = ProfessionInfo.getInstance(null);
-
- if (info != null)
- {
- fail("null getInstance() failed.");
- }
-
- try
- {
- ProcurationSyntax.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- ProfessionInfo profInfo,
- NamingAuthority auth,
- DirectoryString[] professionItems,
- ASN1ObjectIdentifier[] professionOids,
- String registrationNumber,
- DEROctetString addProfInfo)
- throws IOException
- {
- checkValues(profInfo, auth, professionItems, professionOids, registrationNumber, addProfInfo);
-
- profInfo = ProfessionInfo.getInstance(profInfo);
-
- checkValues(profInfo, auth, professionItems, professionOids, registrationNumber, addProfInfo);
-
- ASN1InputStream aIn = new ASN1InputStream(profInfo.toASN1Object().getEncoded());
-
- ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
-
- profInfo = ProfessionInfo.getInstance(seq);
-
- checkValues(profInfo, auth, professionItems, professionOids, registrationNumber, addProfInfo);
- }
-
- private void checkValues(
- ProfessionInfo profInfo,
- NamingAuthority auth,
- DirectoryString[] professionItems,
- ASN1ObjectIdentifier[] professionOids,
- String registrationNumber,
- DEROctetString addProfInfo)
- {
- checkOptionalField("auth", auth, profInfo.getNamingAuthority());
- checkMandatoryField("professionItems", professionItems[0], profInfo.getProfessionItems()[0]);
- if (professionOids != null)
- {
- checkOptionalField("professionOids", professionOids[0], profInfo.getProfessionOIDs()[0]);
- }
- checkOptionalField("registrationNumber", registrationNumber, profInfo.getRegistrationNumber());
- checkOptionalField("addProfessionInfo", addProfInfo, profInfo.getAddProfessionInfo());
- }
-
- public static void main(
- String[] args)
- {
- runTest(new ProfessionInfoUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/QCStatementUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/QCStatementUnitTest.java
deleted file mode 100644
index d7a84a5e..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/QCStatementUnitTest.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.x509.qualified.QCStatement;
-import org.bouncycastle.asn1.x509.qualified.RFC3739QCObjectIdentifiers;
-import org.bouncycastle.asn1.x509.qualified.SemanticsInformation;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class QCStatementUnitTest
- extends SimpleTest
-{
- public String getName()
- {
- return "QCStatement";
- }
-
- public void performTest()
- throws Exception
- {
- QCStatement mv = new QCStatement(RFC3739QCObjectIdentifiers.id_qcs_pkixQCSyntax_v1);
-
- checkConstruction(mv, RFC3739QCObjectIdentifiers.id_qcs_pkixQCSyntax_v1, null);
-
- ASN1Encodable info = new SemanticsInformation(new ASN1ObjectIdentifier("1.2"));
-
- mv = new QCStatement(RFC3739QCObjectIdentifiers.id_qcs_pkixQCSyntax_v1, info);
-
- checkConstruction(mv, RFC3739QCObjectIdentifiers.id_qcs_pkixQCSyntax_v1, info);
-
- mv = QCStatement.getInstance(null);
-
- if (mv != null)
- {
- fail("null getInstance() failed.");
- }
-
- try
- {
- QCStatement.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- QCStatement mv,
- ASN1ObjectIdentifier statementId,
- ASN1Encodable statementInfo)
- throws IOException
- {
- checkStatement(mv, statementId, statementInfo);
-
- mv = QCStatement.getInstance(mv);
-
- checkStatement(mv, statementId, statementInfo);
-
- ASN1InputStream aIn = new ASN1InputStream(mv.toASN1Object().getEncoded());
-
- ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
-
- mv = QCStatement.getInstance(seq);
-
- checkStatement(mv, statementId, statementInfo);
- }
-
- private void checkStatement(
- QCStatement qcs,
- ASN1ObjectIdentifier statementId,
- ASN1Encodable statementInfo)
- throws IOException
- {
- if (!qcs.getStatementId().equals(statementId))
- {
- fail("statementIds don't match.");
- }
-
- if (statementInfo != null)
- {
- if (!qcs.getStatementInfo().equals(statementInfo))
- {
- fail("statementInfos don't match.");
- }
- }
- else if (qcs.getStatementInfo() != null)
- {
- fail("statementInfo found when none expected.");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new QCStatementUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/RFC4519Test.java b/core/src/test/java/org/bouncycastle/asn1/test/RFC4519Test.java
deleted file mode 100644
index 8d7e1756..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/RFC4519Test.java
+++ /dev/null
@@ -1,149 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x500.X500NameStyle;
-import org.bouncycastle.asn1.x500.style.RFC4519Style;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class RFC4519Test
- extends SimpleTest
-{
- static String[] attributeTypes =
- {
- "businessCategory",
- "c",
- "cn",
- "dc",
- "description",
- "destinationIndicator",
- "distinguishedName",
- "dnQualifier",
- "enhancedSearchGuide",
- "facsimileTelephoneNumber",
- "generationQualifier",
- "givenName",
- "houseIdentifier",
- "initials",
- "internationalISDNNumber",
- "l",
- "member",
- "name",
- "o",
- "ou",
- "owner",
- "physicalDeliveryOfficeName",
- "postalAddress",
- "postalCode",
- "postOfficeBox",
- "preferredDeliveryMethod",
- "registeredAddress",
- "roleOccupant",
- "searchGuide",
- "seeAlso",
- "serialNumber",
- "sn",
- "st",
- "street",
- "telephoneNumber",
- "teletexTerminalIdentifier",
- "telexNumber",
- "title",
- "uid",
- "uniqueMember",
- "userPassword",
- "x121Address",
- "x500UniqueIdentifier"
- };
-
- static ASN1ObjectIdentifier[] attributeTypeOIDs =
- {
- new ASN1ObjectIdentifier("2.5.4.15"),
- new ASN1ObjectIdentifier("2.5.4.6"),
- new ASN1ObjectIdentifier("2.5.4.3"),
- new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.25"),
- new ASN1ObjectIdentifier("2.5.4.13"),
- new ASN1ObjectIdentifier("2.5.4.27"),
- new ASN1ObjectIdentifier("2.5.4.49"),
- new ASN1ObjectIdentifier("2.5.4.46"),
- new ASN1ObjectIdentifier("2.5.4.47"),
- new ASN1ObjectIdentifier("2.5.4.23"),
- new ASN1ObjectIdentifier("2.5.4.44"),
- new ASN1ObjectIdentifier("2.5.4.42"),
- new ASN1ObjectIdentifier("2.5.4.51"),
- new ASN1ObjectIdentifier("2.5.4.43"),
- new ASN1ObjectIdentifier("2.5.4.25"),
- new ASN1ObjectIdentifier("2.5.4.7"),
- new ASN1ObjectIdentifier("2.5.4.31"),
- new ASN1ObjectIdentifier("2.5.4.41"),
- new ASN1ObjectIdentifier("2.5.4.10"),
- new ASN1ObjectIdentifier("2.5.4.11"),
- new ASN1ObjectIdentifier("2.5.4.32"),
- new ASN1ObjectIdentifier("2.5.4.19"),
- new ASN1ObjectIdentifier("2.5.4.16"),
- new ASN1ObjectIdentifier("2.5.4.17"),
- new ASN1ObjectIdentifier("2.5.4.18"),
- new ASN1ObjectIdentifier("2.5.4.28"),
- new ASN1ObjectIdentifier("2.5.4.26"),
- new ASN1ObjectIdentifier("2.5.4.33"),
- new ASN1ObjectIdentifier("2.5.4.14"),
- new ASN1ObjectIdentifier("2.5.4.34"),
- new ASN1ObjectIdentifier("2.5.4.5"),
- new ASN1ObjectIdentifier("2.5.4.4"),
- new ASN1ObjectIdentifier("2.5.4.8"),
- new ASN1ObjectIdentifier("2.5.4.9"),
- new ASN1ObjectIdentifier("2.5.4.20"),
- new ASN1ObjectIdentifier("2.5.4.22"),
- new ASN1ObjectIdentifier("2.5.4.21"),
- new ASN1ObjectIdentifier("2.5.4.12"),
- new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.1"),
- new ASN1ObjectIdentifier("2.5.4.50"),
- new ASN1ObjectIdentifier("2.5.4.35"),
- new ASN1ObjectIdentifier("2.5.4.24"),
- new ASN1ObjectIdentifier("2.5.4.45")
- };
-
- public String getName()
- {
- return "RFC4519Test";
- }
-
- public void performTest()
- throws Exception
- {
- X500NameStyle style = RFC4519Style.INSTANCE;
-
- for (int i = 0; i != attributeTypes.length; i++)
- {
- if (!attributeTypeOIDs[i].equals(style.attrNameToOID(attributeTypes[i])))
- {
- fail("mismatch for " + attributeTypes[i]);
- }
- }
-
- byte[] enc = Hex.decode("305e310b300906035504061302415531283026060355040a0c1f546865204c6567696f6e206f662074686520426f756e637920436173746c653125301006035504070c094d656c626f75726e653011060355040b0c0a4173636f742056616c65");
-
- X500Name n = new X500Name(style, X500Name.getInstance(enc));
-
- if (!n.toString().equals("l=Melbourne+ou=Ascot Vale,o=The Legion of the Bouncy Castle,c=AU"))
- {
- fail("Failed composite to string test got: " + n.toString());
- }
-
- n = new X500Name(style, "l=Melbourne+ou=Ascot Vale,o=The Legion of the Bouncy Castle,c=AU");
-
- if (!Arrays.areEqual(n.getEncoded(), enc))
- {
- fail("re-encoding test after parse failed");
- }
- }
-
-
- public static void main(
- String[] args)
- {
- runTest(new RFC4519Test());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/ReasonFlagsTest.java b/core/src/test/java/org/bouncycastle/asn1/test/ReasonFlagsTest.java
deleted file mode 100644
index ebfd126f..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/ReasonFlagsTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.x509.ReasonFlags;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class ReasonFlagsTest
- extends SimpleTest
-{
- public String getName()
- {
- return "ReasonFlags";
- }
-
- public void performTest()
- throws IOException
- {
- BitStringConstantTester.testFlagValueCorrect(0, ReasonFlags.unused);
- BitStringConstantTester.testFlagValueCorrect(1, ReasonFlags.keyCompromise);
- BitStringConstantTester.testFlagValueCorrect(2, ReasonFlags.cACompromise);
- BitStringConstantTester.testFlagValueCorrect(3, ReasonFlags.affiliationChanged);
- BitStringConstantTester.testFlagValueCorrect(4, ReasonFlags.superseded);
- BitStringConstantTester.testFlagValueCorrect(5, ReasonFlags.cessationOfOperation);
- BitStringConstantTester.testFlagValueCorrect(6, ReasonFlags.certificateHold);
- BitStringConstantTester.testFlagValueCorrect(7, ReasonFlags.privilegeWithdrawn);
- BitStringConstantTester.testFlagValueCorrect(8, ReasonFlags.aACompromise);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new ReasonFlagsTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/RegressionTest.java b/core/src/test/java/org/bouncycastle/asn1/test/RegressionTest.java
deleted file mode 100644
index e4427294..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/RegressionTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-public class RegressionTest
-{
- public static Test[] tests = {
- new InputStreamTest(),
- new EqualsAndHashCodeTest(),
- new TagTest(),
- new SetTest(),
- new DERUTF8StringTest(),
- new CertificateTest(),
- new GenerationTest(),
- new CMSTest(),
- new OCSPTest(),
- new OIDTest(),
- new PKCS10Test(),
- new PKCS12Test(),
- new X509NameTest(),
- new X500NameTest(),
- new X509ExtensionsTest(),
- new GeneralizedTimeTest(),
- new BitStringTest(),
- new MiscTest(),
- new SMIMETest(),
- new X9Test(),
- new MonetaryValueUnitTest(),
- new BiometricDataUnitTest(),
- new Iso4217CurrencyCodeUnitTest(),
- new SemanticsInformationUnitTest(),
- new QCStatementUnitTest(),
- new TypeOfBiometricDataUnitTest(),
- new SignerLocationUnitTest(),
- new CommitmentTypeQualifierUnitTest(),
- new CommitmentTypeIndicationUnitTest(),
- new EncryptedPrivateKeyInfoTest(),
- new DataGroupHashUnitTest(),
- new LDSSecurityObjectUnitTest(),
- new CscaMasterListTest(),
- new AttributeTableUnitTest(),
- new ReasonFlagsTest(),
- new NetscapeCertTypeTest(),
- new PKIFailureInfoTest(),
- new KeyUsageTest(),
- new StringTest(),
- new UTCTimeTest(),
- new RequestedCertificateUnitTest(),
- new OtherCertIDUnitTest(),
- new OtherSigningCertificateUnitTest(),
- new ContentHintsUnitTest(),
- new CertHashUnitTest(),
- new AdditionalInformationSyntaxUnitTest(),
- new AdmissionSyntaxUnitTest(),
- new AdmissionsUnitTest(),
- new DeclarationOfMajorityUnitTest(),
- new ProcurationSyntaxUnitTest(),
- new ProfessionInfoUnitTest(),
- new RestrictionUnitTest(),
- new NamingAuthorityUnitTest(),
- new MonetaryLimitUnitTest(),
- new NameOrPseudonymUnitTest(),
- new PersonalDataUnitTest(),
- new DERApplicationSpecificTest(),
- new IssuingDistributionPointUnitTest(),
- new TargetInformationTest(),
- new SubjectKeyIdentifierTest(),
- new ESSCertIDv2UnitTest(),
- new ParsingTest(),
- new GeneralNameTest(),
- new ObjectIdentifierTest(),
- new RFC4519Test()
- };
-
- public static void main(
- String[] args)
- {
- for (int i = 0; i != tests.length; i++)
- {
- TestResult result = tests[i].perform();
-
- if (result.getException() != null)
- {
- result.getException().printStackTrace();
- }
-
- System.out.println(result);
- }
- }
-}
-
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/RequestedCertificateUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/RequestedCertificateUnitTest.java
deleted file mode 100644
index b167e4e2..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/RequestedCertificateUnitTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.isismtt.ocsp.RequestedCertificate;
-import org.bouncycastle.asn1.x509.Certificate;
-import org.bouncycastle.util.encoders.Base64;
-
-public class RequestedCertificateUnitTest
- extends ASN1UnitTest
-{
- byte[] certBytes = Base64.decode(
- "MIIBWzCCAQYCARgwDQYJKoZIhvcNAQEEBQAwODELMAkGA1UEBhMCQVUxDDAKBgNV"
- + "BAgTA1FMRDEbMBkGA1UEAxMSU1NMZWF5L3JzYSB0ZXN0IENBMB4XDTk1MDYxOTIz"
- + "MzMxMloXDTk1MDcxNzIzMzMxMlowOjELMAkGA1UEBhMCQVUxDDAKBgNVBAgTA1FM"
- + "RDEdMBsGA1UEAxMUU1NMZWF5L3JzYSB0ZXN0IGNlcnQwXDANBgkqhkiG9w0BAQEF"
- + "AANLADBIAkEAqtt6qS5GTxVxGZYWa0/4u+IwHf7p2LNZbcPBp9/OfIcYAXBQn8hO"
- + "/Re1uwLKXdCjIoaGs4DLdG88rkzfyK5dPQIDAQABMAwGCCqGSIb3DQIFBQADQQAE"
- + "Wc7EcF8po2/ZO6kNCwK/ICH6DobgLekA5lSLr5EvuioZniZp5lFzAw4+YzPQ7XKJ"
- + "zl9HYIMxATFyqSiD9jsx");
-
- public String getName()
- {
- return "RequestedCertificate";
- }
-
- public void performTest()
- throws Exception
- {
- int type = 1;
- byte[] certOctets = new byte[20];
- Certificate cert = Certificate.getInstance(certBytes);
-
- RequestedCertificate requested = new RequestedCertificate(type, certOctets);
-
- checkConstruction(requested, type, certOctets, null);
-
- requested = new RequestedCertificate(cert);
-
- checkConstruction(requested, RequestedCertificate.certificate, null, cert);
-
- requested = RequestedCertificate.getInstance(null);
-
- if (requested != null)
- {
- fail("null getInstance() failed.");
- }
-
- try
- {
- RequestedCertificate.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- RequestedCertificate requested,
- int type,
- byte[] certOctets,
- Certificate cert)
- throws IOException
- {
- checkValues(requested, type, certOctets, cert);
-
- requested = RequestedCertificate.getInstance(requested);
-
- checkValues(requested, type, certOctets, cert);
-
- ASN1InputStream aIn = new ASN1InputStream(requested.toASN1Object().getEncoded());
-
- Object obj = aIn.readObject();
-
- requested = RequestedCertificate.getInstance(obj);
-
- checkValues(requested, type, certOctets, cert);
- }
-
- private void checkValues(
- RequestedCertificate requested,
- int type,
- byte[] certOctets,
- Certificate cert)
- throws IOException
- {
- checkMandatoryField("certType", type, requested.getType());
-
- if (requested.getType() == RequestedCertificate.certificate)
- {
- checkMandatoryField("certificate", cert.getEncoded(), requested.getCertificateBytes());
- }
- else
- {
- checkMandatoryField("certificateOctets", certOctets, requested.getCertificateBytes());
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new RequestedCertificateUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/RestrictionUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/RestrictionUnitTest.java
deleted file mode 100644
index 3b11305a..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/RestrictionUnitTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1String;
-import org.bouncycastle.asn1.isismtt.x509.Restriction;
-import org.bouncycastle.asn1.x500.DirectoryString;
-
-public class RestrictionUnitTest
- extends ASN1UnitTest
-{
- public String getName()
- {
- return "Restriction";
- }
-
- public void performTest()
- throws Exception
- {
- DirectoryString res = new DirectoryString("test");
- Restriction restriction = new Restriction(res.getString());
-
- checkConstruction(restriction, res);
-
- try
- {
- Restriction.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- Restriction restriction,
- DirectoryString res)
- throws IOException
- {
- checkValues(restriction, res);
-
- restriction = Restriction.getInstance(restriction);
-
- checkValues(restriction, res);
-
- ASN1InputStream aIn = new ASN1InputStream(restriction.toASN1Object().getEncoded());
-
- ASN1String str = (ASN1String)aIn.readObject();
-
- restriction = Restriction.getInstance(str);
-
- checkValues(restriction, res);
- }
-
- private void checkValues(
- Restriction restriction,
- DirectoryString res)
- {
- checkMandatoryField("restriction", res, restriction.getRestriction());
- }
-
- public static void main(
- String[] args)
- {
- runTest(new RestrictionUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/SMIMETest.java b/core/src/test/java/org/bouncycastle/asn1/test/SMIMETest.java
deleted file mode 100644
index 44d6b1c0..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/SMIMETest.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.ByteArrayInputStream;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.DERGeneralizedTime;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.cms.RecipientKeyIdentifier;
-import org.bouncycastle.asn1.smime.SMIMECapabilitiesAttribute;
-import org.bouncycastle.asn1.smime.SMIMECapability;
-import org.bouncycastle.asn1.smime.SMIMECapabilityVector;
-import org.bouncycastle.asn1.smime.SMIMEEncryptionKeyPreferenceAttribute;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-public class SMIMETest
- implements Test
-{
- byte[] attrBytes = Base64.decode("MDQGCSqGSIb3DQEJDzEnMCUwCgYIKoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMAcGBSsOAwIH");
- byte[] prefBytes = Base64.decode("MCwGCyqGSIb3DQEJEAILMR2hGwQIAAAAAAAAAAAYDzIwMDcwMzE1MTczNzI5Wg==");
-
- private boolean isSameAs(
- byte[] a,
- byte[] b)
- {
- if (a.length != b.length)
- {
- return false;
- }
-
- for (int i = 0; i != a.length; i++)
- {
- if (a[i] != b[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- public TestResult perform()
- {
- SMIMECapabilityVector caps = new SMIMECapabilityVector();
-
- caps.addCapability(SMIMECapability.dES_EDE3_CBC);
- caps.addCapability(SMIMECapability.rC2_CBC, 128);
- caps.addCapability(SMIMECapability.dES_CBC);
-
- SMIMECapabilitiesAttribute attr = new SMIMECapabilitiesAttribute(caps);
-
- SMIMEEncryptionKeyPreferenceAttribute pref = new SMIMEEncryptionKeyPreferenceAttribute(
- new RecipientKeyIdentifier(new DEROctetString(new byte[8]), new DERGeneralizedTime("20070315173729Z"), null));
-
- try
- {
- if (!isSameAs(attr.getEncoded(), attrBytes))
- {
- return new SimpleTestResult(false, getName() + ": Failed attr data check");
- }
-
- ByteArrayInputStream bIn = new ByteArrayInputStream(attrBytes);
- ASN1InputStream aIn = new ASN1InputStream(bIn);
-
- ASN1Primitive o = aIn.readObject();
- if (!attr.equals(o))
- {
- return new SimpleTestResult(false, getName() + ": Failed equality test for attr");
- }
-
- if (!isSameAs(pref.getEncoded(), prefBytes))
- {
- return new SimpleTestResult(false, getName() + ": Failed attr data check");
- }
-
- bIn = new ByteArrayInputStream(prefBytes);
- aIn = new ASN1InputStream(bIn);
-
- o = aIn.readObject();
- if (!pref.equals(o))
- {
- return new SimpleTestResult(false, getName() + ": Failed equality test for pref");
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
- catch (Exception e)
- {
- return new SimpleTestResult(false, getName() + ": Failed - exception " + e.toString(), e);
- }
- }
-
- public String getName()
- {
- return "SMIME";
- }
-
- public static void main(
- String[] args)
- {
- SMIMETest test = new SMIMETest();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/SemanticsInformationUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/SemanticsInformationUnitTest.java
deleted file mode 100644
index 3fd26db5..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/SemanticsInformationUnitTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.GeneralName;
-import org.bouncycastle.asn1.x509.X509Name;
-import org.bouncycastle.asn1.x509.qualified.SemanticsInformation;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class SemanticsInformationUnitTest
- extends SimpleTest
-{
- public String getName()
- {
- return "SemanticsInformation";
- }
-
- public void performTest()
- throws Exception
- {
- ASN1ObjectIdentifier statementId = new ASN1ObjectIdentifier("1.1");
- SemanticsInformation mv = new SemanticsInformation(statementId);
-
- checkConstruction(mv, statementId, null);
-
- GeneralName[] names = new GeneralName[2];
-
- names[0] = new GeneralName(GeneralName.rfc822Name, "test@test.org");
- names[1] = new GeneralName(new X509Name("cn=test"));
-
- mv = new SemanticsInformation(statementId, names);
-
- checkConstruction(mv, statementId, names);
-
- mv = new SemanticsInformation(names);
-
- checkConstruction(mv, null, names);
-
- mv = SemanticsInformation.getInstance(null);
-
- if (mv != null)
- {
- fail("null getInstance() failed.");
- }
-
- try
- {
- SemanticsInformation.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- try
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- SemanticsInformation.getInstance(new DERSequence(v));
-
- fail("constructor failed to detect empty sequence.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- SemanticsInformation mv,
- ASN1ObjectIdentifier semanticsIdentifier,
- GeneralName[] names)
- throws Exception
- {
- checkStatement(mv, semanticsIdentifier, names);
-
- mv = SemanticsInformation.getInstance(mv);
-
- checkStatement(mv, semanticsIdentifier, names);
-
- ASN1InputStream aIn = new ASN1InputStream(mv.toASN1Object().getEncoded());
-
- ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
-
- mv = SemanticsInformation.getInstance(seq);
-
- checkStatement(mv, semanticsIdentifier, names);
- }
-
- private void checkStatement(
- SemanticsInformation si,
- ASN1ObjectIdentifier id,
- GeneralName[] names)
- {
- if (id != null)
- {
- if (!si.getSemanticsIdentifier().equals(id))
- {
- fail("ids don't match.");
- }
- }
- else if (si.getSemanticsIdentifier() != null)
- {
- fail("statementId found when none expected.");
- }
-
- if (names != null)
- {
- GeneralName[] siNames = si.getNameRegistrationAuthorities();
-
- for (int i = 0; i != siNames.length; i++)
- {
- if (!names[i].equals(siNames[i]))
- {
- fail("name registration authorities don't match.");
- }
- }
- }
- else if (si.getNameRegistrationAuthorities() != null)
- {
- fail("name registration authorities found when none expected.");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new SemanticsInformationUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/SetTest.java b/core/src/test/java/org/bouncycastle/asn1/test/SetTest.java
deleted file mode 100644
index 2e4fb392..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/SetTest.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import org.bouncycastle.asn1.ASN1Boolean;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.BERSet;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERSet;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * Set sorting test example
- */
-public class SetTest
- extends SimpleTest
-{
-
- public String getName()
- {
- return "Set";
- }
-
- private void checkedSortedSet(int attempt, ASN1Set s)
- {
- if (s.getObjectAt(0) instanceof ASN1Boolean
- && s.getObjectAt(1) instanceof ASN1Integer
- && s.getObjectAt(2) instanceof DERBitString
- && s.getObjectAt(3) instanceof DEROctetString)
- {
- return;
- }
-
- fail("sorting failed on attempt: " + attempt);
- }
-
- public void performTest()
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- byte[] data = new byte[10];
-
- v.add(new DEROctetString(data));
- v.add(new DERBitString(data));
- v.add(new ASN1Integer(100));
- v.add(new ASN1Boolean(true));
-
- checkedSortedSet(0, new DERSet(v));
-
- v = new ASN1EncodableVector();
- v.add(new ASN1Integer(100));
- v.add(new ASN1Boolean(true));
- v.add(new DEROctetString(data));
- v.add(new DERBitString(data));
-
- checkedSortedSet(1, new DERSet(v));
-
- v = new ASN1EncodableVector();
- v.add(new ASN1Boolean(true));
- v.add(new DEROctetString(data));
- v.add(new DERBitString(data));
- v.add(new ASN1Integer(100));
-
-
- checkedSortedSet(2, new DERSet(v));
-
- v = new ASN1EncodableVector();
- v.add(new DERBitString(data));
- v.add(new DEROctetString(data));
- v.add(new ASN1Integer(100));
- v.add(new ASN1Boolean(true));
-
- checkedSortedSet(3, new DERSet(v));
-
- v = new ASN1EncodableVector();
- v.add(new DEROctetString(data));
- v.add(new DERBitString(data));
- v.add(new ASN1Integer(100));
- v.add(new ASN1Boolean(true));
-
- ASN1Set s = new BERSet(v);
-
- if (!(s.getObjectAt(0) instanceof DEROctetString))
- {
- fail("BER set sort order changed.");
- }
-
- // create an implicitly tagged "set" without sorting
- ASN1TaggedObject tag = new DERTaggedObject(false, 1, new DERSequence(v));
- s = ASN1Set.getInstance(tag, false);
-
- if (s.getObjectAt(0) instanceof ASN1Boolean)
- {
- fail("sorted when shouldn't be.");
- }
-
- // equality test
- v = new ASN1EncodableVector();
-
- v.add(new ASN1Boolean(true));
- v.add(new ASN1Boolean(true));
- v.add(new ASN1Boolean(true));
-
- s = new DERSet(v);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new SetTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/SignerLocationUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/SignerLocationUnitTest.java
deleted file mode 100644
index 8d2c2c06..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/SignerLocationUnitTest.java
+++ /dev/null
@@ -1,197 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.DERUTF8String;
-import org.bouncycastle.asn1.esf.SignerLocation;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class SignerLocationUnitTest
- extends SimpleTest
-{
- public String getName()
- {
- return "SignerLocation";
- }
-
- public void performTest()
- throws Exception
- {
- DERUTF8String countryName = new DERUTF8String("Australia");
-
- SignerLocation sl = new SignerLocation(countryName, null, null);
-
- checkConstruction(sl, countryName, null, null);
-
- DERUTF8String localityName = new DERUTF8String("Melbourne");
-
- sl = new SignerLocation(null, localityName, null);
-
- checkConstruction(sl, null, localityName, null);
-
- sl = new SignerLocation(countryName, localityName, null);
-
- checkConstruction(sl, countryName, localityName, null);
-
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(new DERUTF8String("line 1"));
- v.add(new DERUTF8String("line 2"));
-
- ASN1Sequence postalAddress = new DERSequence(v);
-
- sl = new SignerLocation(null, null, postalAddress);
-
- checkConstruction(sl, null, null, postalAddress);
-
- sl = new SignerLocation(countryName, null, postalAddress);
-
- checkConstruction(sl, countryName, null, postalAddress);
-
- sl = new SignerLocation(countryName, localityName, postalAddress);
-
- checkConstruction(sl, countryName, localityName, postalAddress);
-
- sl = SignerLocation.getInstance(null);
-
- if (sl != null)
- {
- fail("null getInstance() failed.");
- }
-
- try
- {
- SignerLocation.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- //
- // out of range postal address
- //
- v = new ASN1EncodableVector();
-
- v.add(new DERUTF8String("line 1"));
- v.add(new DERUTF8String("line 2"));
- v.add(new DERUTF8String("line 3"));
- v.add(new DERUTF8String("line 4"));
- v.add(new DERUTF8String("line 5"));
- v.add(new DERUTF8String("line 6"));
- v.add(new DERUTF8String("line 7"));
-
- postalAddress = new DERSequence(v);
-
- try
- {
- new SignerLocation(null, null, postalAddress);
-
- fail("constructor failed to detect bad postalAddress.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- try
- {
- SignerLocation.getInstance(new DERSequence(new DERTaggedObject(2, postalAddress)));
-
- fail("sequence constructor failed to detect bad postalAddress.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- try
- {
- SignerLocation.getInstance(new DERSequence(new DERTaggedObject(5, postalAddress)));
-
- fail("sequence constructor failed to detect bad tag.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- private void checkConstruction(
- SignerLocation sl,
- DERUTF8String countryName,
- DERUTF8String localityName,
- ASN1Sequence postalAddress)
- throws IOException
- {
- checkValues(sl, countryName, localityName, postalAddress);
-
- sl = SignerLocation.getInstance(sl);
-
- checkValues(sl, countryName, localityName, postalAddress);
-
- ASN1InputStream aIn = new ASN1InputStream(sl.toASN1Object().getEncoded());
-
- ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
-
- sl = SignerLocation.getInstance(seq);
-
- checkValues(sl, countryName, localityName, postalAddress);
- }
-
- private void checkValues(
- SignerLocation sl,
- DERUTF8String countryName,
- DERUTF8String localityName,
- ASN1Sequence postalAddress)
- {
- if (countryName != null)
- {
- if (!countryName.equals(sl.getCountryName()))
- {
- fail("countryNames don't match.");
- }
- }
- else if (sl.getCountryName() != null)
- {
- fail("countryName found when none expected.");
- }
-
- if (localityName != null)
- {
- if (!localityName.equals(sl.getLocalityName()))
- {
- fail("localityNames don't match.");
- }
- }
- else if (sl.getLocalityName() != null)
- {
- fail("localityName found when none expected.");
- }
-
- if (postalAddress != null)
- {
- if (!postalAddress.equals(sl.getPostalAddress()))
- {
- fail("postalAddresses don't match.");
- }
- }
- else if (sl.getPostalAddress() != null)
- {
- fail("postalAddress found when none expected.");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new SignerLocationUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/StringTest.java b/core/src/test/java/org/bouncycastle/asn1/test/StringTest.java
deleted file mode 100644
index 426c06ac..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/StringTest.java
+++ /dev/null
@@ -1,161 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1String;
-import org.bouncycastle.asn1.DERBMPString;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERGeneralString;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DERNumericString;
-import org.bouncycastle.asn1.DERPrintableString;
-import org.bouncycastle.asn1.DERT61String;
-import org.bouncycastle.asn1.DERUTF8String;
-import org.bouncycastle.asn1.DERUniversalString;
-import org.bouncycastle.asn1.DERVisibleString;
-import org.bouncycastle.util.Strings;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * X.690 test example
- */
-public class StringTest
- extends SimpleTest
-{
- public String getName()
- {
- return "String";
- }
-
- public void performTest()
- throws IOException
- {
- DERBitString bs = new DERBitString(
- new byte[] { (byte)0x01,(byte)0x23,(byte)0x45,(byte)0x67,(byte)0x89,(byte)0xab,(byte)0xcd,(byte)0xef });
-
- if (!bs.getString().equals("#0309000123456789ABCDEF"))
- {
- fail("DERBitString.getString() result incorrect");
- }
-
- if (!bs.toString().equals("#0309000123456789ABCDEF"))
- {
- fail("DERBitString.toString() result incorrect");
- }
-
- bs = new DERBitString(
- new byte[] { (byte)0xfe,(byte)0xdc,(byte)0xba,(byte)0x98,(byte)0x76,(byte)0x54,(byte)0x32,(byte)0x10 });
-
- if (!bs.getString().equals("#030900FEDCBA9876543210"))
- {
- fail("DERBitString.getString() result incorrect");
- }
-
- if (!bs.toString().equals("#030900FEDCBA9876543210"))
- {
- fail("DERBitString.toString() result incorrect");
- }
-
- DERUniversalString us = new DERUniversalString(
- new byte[] { (byte)0x01,(byte)0x23,(byte)0x45,(byte)0x67,(byte)0x89,(byte)0xab,(byte)0xcd,(byte)0xef });
-
- if (!us.getString().equals("#1C080123456789ABCDEF"))
- {
- fail("DERUniversalString.getString() result incorrect");
- }
-
- if (!us.toString().equals("#1C080123456789ABCDEF"))
- {
- fail("DERUniversalString.toString() result incorrect");
- }
-
- us = new DERUniversalString(
- new byte[] { (byte)0xfe,(byte)0xdc,(byte)0xba,(byte)0x98,(byte)0x76,(byte)0x54,(byte)0x32,(byte)0x10 });
-
- if (!us.getString().equals("#1C08FEDCBA9876543210"))
- {
- fail("DERUniversalString.getString() result incorrect");
- }
-
- if (!us.toString().equals("#1C08FEDCBA9876543210"))
- {
- fail("DERUniversalString.toString() result incorrect");
- }
-
- byte[] t61Bytes = new byte[] { -1, -2, -3, -4, -5, -6, -7, -8 };
- String t61String = new String(t61Bytes, "iso-8859-1");
- DERT61String t61 = new DERT61String(Strings.fromByteArray(t61Bytes));
-
- if (!t61.getString().equals(t61String))
- {
- fail("DERT61String.getString() result incorrect");
- }
-
- if (!t61.toString().equals(t61String))
- {
- fail("DERT61String.toString() result incorrect");
- }
-
- char[] shortChars = new char[] { 'a', 'b', 'c', 'd', 'e'};
- char[] longChars = new char[1000];
-
- for (int i = 0; i != longChars.length; i++)
- {
- longChars[i] = 'X';
- }
-
- checkString(new DERBMPString(new String(shortChars)), new DERBMPString(new String(longChars)));
- checkString(new DERUTF8String(new String(shortChars)), new DERUTF8String(new String(longChars)));
- checkString(new DERIA5String(new String(shortChars)), new DERIA5String(new String(longChars)));
- checkString(new DERPrintableString(new String(shortChars)), new DERPrintableString(new String(longChars)));
- checkString(new DERVisibleString(new String(shortChars)), new DERVisibleString(new String(longChars)));
- checkString(new DERGeneralString(new String(shortChars)), new DERGeneralString(new String(longChars)));
- checkString(new DERT61String(new String(shortChars)), new DERT61String(new String(longChars)));
-
- shortChars = new char[] { '1', '2', '3', '4', '5'};
- longChars = new char[1000];
-
- for (int i = 0; i != longChars.length; i++)
- {
- longChars[i] = '1';
- }
-
- checkString(new DERNumericString(new String(shortChars)), new DERNumericString(new String(longChars)));
-
- byte[] shortBytes = new byte[] { (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e'};
- byte[] longBytes = new byte[1000];
-
- for (int i = 0; i != longChars.length; i++)
- {
- longBytes[i] = (byte)'X';
- }
-
- checkString(new DERUniversalString(shortBytes), new DERUniversalString(longBytes));
-
- }
-
- private void checkString(ASN1String shortString, ASN1String longString)
- throws IOException
- {
- ASN1String short2 = (ASN1String)ASN1Primitive.fromByteArray(((ASN1Primitive)shortString).getEncoded());
-
- if (!shortString.toString().equals(short2.toString()))
- {
- fail(short2.getClass().getName() + " shortBytes result incorrect");
- }
-
- ASN1String long2 = (ASN1String)ASN1Primitive.fromByteArray(((ASN1Primitive)longString).getEncoded());
-
- if (!longString.toString().equals(long2.toString()))
- {
- fail(long2.getClass().getName() + " longBytes result incorrect");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new StringTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/SubjectKeyIdentifierTest.java b/core/src/test/java/org/bouncycastle/asn1/test/SubjectKeyIdentifierTest.java
deleted file mode 100644
index 9887a31e..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/SubjectKeyIdentifierTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class SubjectKeyIdentifierTest
- extends SimpleTest
-{
- private static byte[] pubKeyInfo = Base64.decode(
- "MFgwCwYJKoZIhvcNAQEBA0kAMEYCQQC6wMMmHYMZszT/7bNFMn+gaZoiWJLVP8ODRuu1C2jeAe" +
- "QpxM+5Oe7PaN2GNy3nBE4EOYkB5pMJWA0y9n04FX8NAgED");
-
- private static byte[] shaID = Hex.decode("d8128a06d6c2feb0865994a2936e7b75b836a021");
- private static byte[] shaTruncID = Hex.decode("436e7b75b836a021");
-
- public String getName()
- {
- return "SubjectKeyIdentifier";
- }
-
- public void performTest()
- throws IOException
- {
-// SubjectPublicKeyInfo pubInfo = SubjectPublicKeyInfo.getInstance(ASN1Primitive.fromByteArray(pubKeyInfo));
-// SubjectKeyIdentifier ski = SubjectKeyIdentifier.createSHA1KeyIdentifier(pubInfo);
-//
-// if (!Arrays.areEqual(shaID, ski.getKeyIdentifier()))
-// {
-// fail("SHA-1 ID does not match");
-// }
-//
-// ski = SubjectKeyIdentifier.createTruncatedSHA1KeyIdentifier(pubInfo);
-//
-// if (!Arrays.areEqual(shaTruncID, ski.getKeyIdentifier()))
-// {
-// fail("truncated SHA-1 ID does not match");
-// }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new SubjectKeyIdentifierTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/TagTest.java b/core/src/test/java/org/bouncycastle/asn1/test/TagTest.java
deleted file mode 100644
index 90489a7d..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/TagTest.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-import java.security.SecureRandom;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERApplicationSpecific;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-
-/**
- * X.690 test example
- */
-public class TagTest
- extends SimpleTest
-{
- byte[] longTagged = Base64.decode(
- "ZSRzIp8gEEZFRENCQTk4NzY1NDMyMTCfIQwyMDA2MDQwMTEyMzSUCCAFERVz"
- + "A4kCAHEXGBkalAggBRcYGRqUCCAFZS6QAkRFkQlURUNITklLRVKSBQECAwQF"
- + "kxAREhMUFRYXGBkalAggBREVcwOJAgBxFxgZGpQIIAUXGBkalAggBWUukAJE"
- + "RZEJVEVDSE5JS0VSkgUBAgMEBZMQERITFBUWFxgZGpQIIAURFXMDiQIAcRcY"
- + "GRqUCCAFFxgZGpQIIAVlLpACREWRCVRFQ0hOSUtFUpIFAQIDBAWTEBESExQV"
- + "FhcYGRqUCCAFERVzA4kCAHEXGBkalAggBRcYGRqUCCAFFxgZGpQIIAUXGBka"
- + "lAg=");
-
- byte[] longAppSpecificTag = Hex.decode("5F610101");
-
- public String getName()
- {
- return "Tag";
- }
-
- public void performTest()
- throws IOException
- {
- ASN1InputStream aIn = new ASN1InputStream(longTagged);
-
- DERApplicationSpecific app = (DERApplicationSpecific)aIn.readObject();
-
- aIn = new ASN1InputStream(app.getContents());
-
- app = (DERApplicationSpecific)aIn.readObject();
-
- aIn = new ASN1InputStream(app.getContents());
-
- ASN1TaggedObject tagged = (ASN1TaggedObject)aIn.readObject();
-
- if (tagged.getTagNo() != 32)
- {
- fail("unexpected tag value found - not 32");
- }
-
- tagged = (ASN1TaggedObject)ASN1Primitive.fromByteArray(tagged.getEncoded());
-
- if (tagged.getTagNo() != 32)
- {
- fail("unexpected tag value found on recode - not 32");
- }
-
- tagged = (ASN1TaggedObject)aIn.readObject();
-
- if (tagged.getTagNo() != 33)
- {
- fail("unexpected tag value found - not 33");
- }
-
- tagged = (ASN1TaggedObject)ASN1Primitive.fromByteArray(tagged.getEncoded());
-
- if (tagged.getTagNo() != 33)
- {
- fail("unexpected tag value found on recode - not 33");
- }
-
- aIn = new ASN1InputStream(longAppSpecificTag);
-
- app = (DERApplicationSpecific)aIn.readObject();
-
- if (app.getApplicationTag() != 97)
- {
- fail("incorrect tag number read");
- }
-
- app = (DERApplicationSpecific)ASN1Primitive.fromByteArray(app.getEncoded());
-
- if (app.getApplicationTag() != 97)
- {
- fail("incorrect tag number read on recode");
- }
-
- SecureRandom sr = new SecureRandom();
- for (int i = 0; i < 100; ++i)
- {
- int testTag = sr.nextInt() >>> (1 + (sr.nextInt() >>> 1) % 26);
- app = new DERApplicationSpecific(testTag, new byte[]{ 1 });
- app = (DERApplicationSpecific)ASN1Primitive.fromByteArray(app.getEncoded());
-
- if (app.getApplicationTag() != testTag)
- {
- fail("incorrect tag number read on recode (random test value: " + testTag + ")");
- }
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new TagTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/TargetInformationTest.java b/core/src/test/java/org/bouncycastle/asn1/test/TargetInformationTest.java
deleted file mode 100644
index 34dc70fd..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/TargetInformationTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import org.bouncycastle.asn1.x509.GeneralName;
-import org.bouncycastle.asn1.x509.Target;
-import org.bouncycastle.asn1.x509.TargetInformation;
-import org.bouncycastle.asn1.x509.Targets;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class TargetInformationTest
- extends SimpleTest
-{
-
- public String getName()
- {
- return "TargetInformation";
- }
-
- public void performTest() throws Exception
- {
- Target[] targets = new Target[2];
- Target targetName = new Target(Target.targetName, new GeneralName(GeneralName.dNSName, "www.test.com"));
- Target targetGroup = new Target(Target.targetGroup, new GeneralName(GeneralName.directoryName, "o=Test, ou=Test"));
- targets[0] = targetName;
- targets[1] = targetGroup;
- Targets targetss = new Targets(targets);
- TargetInformation targetInformation1 = new TargetInformation(targetss);
- // use an Target array
- TargetInformation targetInformation2 = new TargetInformation(targets);
- // targetInformation1 and targetInformation2 must have same
- // encoding.
- if (!targetInformation1.equals(targetInformation2))
- {
- fail("targetInformation1 and targetInformation2 should have the same encoding.");
- }
- TargetInformation targetInformation3 = TargetInformation.getInstance(targetInformation1);
- TargetInformation targetInformation4 = TargetInformation.getInstance(targetInformation2);
- if (!targetInformation3.equals(targetInformation4))
- {
- fail("targetInformation3 and targetInformation4 should have the same encoding.");
- }
- }
-
- public static void main(String[] args)
- {
- runTest(new TargetInformationTest());
- }
-}
-
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/TypeOfBiometricDataUnitTest.java b/core/src/test/java/org/bouncycastle/asn1/test/TypeOfBiometricDataUnitTest.java
deleted file mode 100644
index add21ce3..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/TypeOfBiometricDataUnitTest.java
+++ /dev/null
@@ -1,144 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.x509.qualified.TypeOfBiometricData;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class TypeOfBiometricDataUnitTest
- extends SimpleTest
-{
- public String getName()
- {
- return "TypeOfBiometricData";
- }
-
- public void performTest()
- throws Exception
- {
- //
- // predefined
- //
- checkPredefinedType(TypeOfBiometricData.PICTURE);
-
- checkPredefinedType(TypeOfBiometricData.HANDWRITTEN_SIGNATURE);
-
- //
- // non-predefined
- //
- ASN1ObjectIdentifier localType = new ASN1ObjectIdentifier("1.1");
-
- TypeOfBiometricData type = new TypeOfBiometricData(localType);
-
- checkNonPredefined(type, localType);
-
- type = TypeOfBiometricData.getInstance(type);
-
- checkNonPredefined(type, localType);
-
- ASN1Primitive obj = type.toASN1Primitive();
-
- type = TypeOfBiometricData.getInstance(obj);
-
- checkNonPredefined(type, localType);
-
- type = TypeOfBiometricData.getInstance(null);
-
- if (type != null)
- {
- fail("null getInstance() failed.");
- }
-
- try
- {
- TypeOfBiometricData.getInstance(new Object());
-
- fail("getInstance() failed to detect bad object.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- try
- {
- new TypeOfBiometricData(100);
-
- fail("constructor failed to detect bad predefined type.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- if (TypeOfBiometricData.PICTURE != 0)
- {
- fail("predefined picture should be 0");
- }
-
- if (TypeOfBiometricData.HANDWRITTEN_SIGNATURE != 1)
- {
- fail("predefined handwritten signature should be 1");
- }
- }
-
- private void checkPredefinedType(
- int predefinedType)
- throws IOException
- {
- TypeOfBiometricData type = new TypeOfBiometricData(predefinedType);
-
- checkPredefined(type, predefinedType);
-
- type = TypeOfBiometricData.getInstance(type);
-
- checkPredefined(type, predefinedType);
-
- ASN1InputStream aIn = new ASN1InputStream(type.toASN1Object().getEncoded());
-
- ASN1Primitive obj = aIn.readObject();
-
- type = TypeOfBiometricData.getInstance(obj);
-
- checkPredefined(type, predefinedType);
- }
-
- private void checkPredefined(
- TypeOfBiometricData type,
- int value)
- {
- if (!type.isPredefined())
- {
- fail("predefined type expected but not found.");
- }
-
- if (type.getPredefinedBiometricType() != value)
- {
- fail("predefined type does not match.");
- }
- }
-
- private void checkNonPredefined(
- TypeOfBiometricData type,
- ASN1ObjectIdentifier value)
- {
- if (type.isPredefined())
- {
- fail("predefined type found when not expected.");
- }
-
- if (!type.getBiometricDataOid().equals(value))
- {
- fail("data oid does not match.");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new TypeOfBiometricDataUnitTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/UTCTimeTest.java b/core/src/test/java/org/bouncycastle/asn1/test/UTCTimeTest.java
deleted file mode 100644
index 8067e78c..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/UTCTimeTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import org.bouncycastle.asn1.DERUTCTime;
-import org.bouncycastle.util.test.SimpleTest;
-
-import java.text.SimpleDateFormat;
-import java.util.SimpleTimeZone;
-
-/**
- * X.690 test example
- */
-public class UTCTimeTest
- extends SimpleTest
-{
- String[] input =
- {
- "020122122220Z",
- "020122122220-1000",
- "020122122220+1000",
- "020122122220+00",
- "0201221222Z",
- "0201221222-1000",
- "0201221222+1000",
- "0201221222+00",
- "550122122220Z",
- "5501221222Z"
- };
-
- String[] output = {
- "20020122122220GMT+00:00",
- "20020122122220GMT-10:00",
- "20020122122220GMT+10:00",
- "20020122122220GMT+00:00",
- "20020122122200GMT+00:00",
- "20020122122200GMT-10:00",
- "20020122122200GMT+10:00",
- "20020122122200GMT+00:00",
- "19550122122220GMT+00:00",
- "19550122122200GMT+00:00"
- };
-
- String[] zOutput1 = {
- "20020122122220Z",
- "20020122222220Z",
- "20020122022220Z",
- "20020122122220Z",
- "20020122122200Z",
- "20020122222200Z",
- "20020122022200Z",
- "20020122122200Z",
- "19550122122220Z",
- "19550122122200Z"
- };
-
- String[] zOutput2 = {
- "20020122122220Z",
- "20020122222220Z",
- "20020122022220Z",
- "20020122122220Z",
- "20020122122200Z",
- "20020122222200Z",
- "20020122022200Z",
- "20020122122200Z",
- "19550122122220Z",
- "19550122122200Z"
- };
-
- public String getName()
- {
- return "UTCTime";
- }
-
- public void performTest()
- throws Exception
- {
- SimpleDateFormat yyyyF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
- SimpleDateFormat yyF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
-
- yyyyF.setTimeZone(new SimpleTimeZone(0,"Z"));
- yyF.setTimeZone(new SimpleTimeZone(0,"Z"));
-
- for (int i = 0; i != input.length; i++)
- {
- DERUTCTime t = new DERUTCTime(input[i]);
-
- if (!t.getAdjustedTime().equals(output[i]))
- {
- fail("failed conversion test " + i);
- }
-
- if (!yyyyF.format(t.getAdjustedDate()).equals(zOutput1[i]))
- {
- fail("failed date conversion test " + i);
- }
-
- if (!yyF.format(t.getDate()).equals(zOutput2[i]))
- {
- fail("failed date shortened conversion test " + i);
- }
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new UTCTimeTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/X500NameTest.java b/core/src/test/java/org/bouncycastle/asn1/test/X500NameTest.java
deleted file mode 100644
index 32cf60fb..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/X500NameTest.java
+++ /dev/null
@@ -1,771 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OutputStream;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.ASN1String;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DERPrintableString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERSet;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.DERUTF8String;
-import org.bouncycastle.asn1.x500.RDN;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x500.X500NameBuilder;
-import org.bouncycastle.asn1.x500.style.BCStrictStyle;
-import org.bouncycastle.asn1.x500.style.BCStyle;
-import org.bouncycastle.asn1.x500.style.IETFUtils;
-import org.bouncycastle.asn1.x509.X509DefaultEntryConverter;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class X500NameTest
- extends SimpleTest
-{
- String[] subjects =
- {
- "C=AU,ST=Victoria,L=South Melbourne,O=Connect 4 Pty Ltd,OU=Webserver Team,CN=www2.connect4.com.au,E=webmaster@connect4.com.au",
- "C=AU,ST=Victoria,L=South Melbourne,O=Connect 4 Pty Ltd,OU=Certificate Authority,CN=Connect 4 CA,E=webmaster@connect4.com.au",
- "C=AU,ST=QLD,CN=SSLeay/rsa test cert",
- "C=US,O=National Aeronautics and Space Administration,SERIALNUMBER=16+CN=Steve Schoch",
- "E=cooke@issl.atl.hp.com,C=US,OU=Hewlett Packard Company (ISSL),CN=Paul A. Cooke",
- "O=Sun Microsystems Inc,CN=store.sun.com",
- "unstructuredAddress=192.168.1.33,unstructuredName=pixfirewall.ciscopix.com,CN=pixfirewall.ciscopix.com",
- "CN=*.canal-plus.com,OU=Provided by TBS INTERNET http://www.tbs-certificats.com/,OU=\\ CANAL \\+,O=CANAL\\+DISTRIBUTION,L=issy les moulineaux,ST=Hauts de Seine,C=FR",
- "O=Bouncy Castle,CN=www.bouncycastle.org\\ ",
- "O=Bouncy Castle,CN=c:\\\\fred\\\\bob",
- };
-
- String[] hexSubjects =
- {
- "CN=\\20Test\\20X,O=\\20Test,C=GB", // input
- "CN=\\ Test X,O=\\ Test,C=GB", // expected
- "CN=\\20Test\\20X\\20,O=\\20Test,C=GB", // input
- "CN=\\ Test X\\ ,O=\\ Test,C=GB" // expected
- };
-
- public String getName()
- {
- return "X500Name";
- }
-
- private static X500Name fromBytes(
- byte[] bytes)
- throws IOException
- {
- return X500Name.getInstance(new ASN1InputStream(new ByteArrayInputStream(bytes)).readObject());
- }
-
- private ASN1Encodable createEntryValue(ASN1ObjectIdentifier oid, String value)
- {
- X500NameBuilder builder = new X500NameBuilder(BCStyle.INSTANCE);
-
- builder.addRDN(oid, value);
-
- X500Name name = builder.build();
-
- ASN1Sequence seq = (ASN1Sequence)name.toASN1Primitive();
- ASN1Set set = ASN1Set.getInstance(seq.getObjectAt(0).toASN1Primitive());
- seq = (ASN1Sequence)set.getObjectAt(0);
-
- return seq.getObjectAt(1);
- }
-
- private ASN1Encodable createEntryValueFromString(ASN1ObjectIdentifier oid, String value)
- {
- X500NameBuilder builder = new X500NameBuilder(BCStyle.INSTANCE);
-
- builder.addRDN(oid, value);
-
- X500Name name = new X500Name(builder.build().toString());
-
- ASN1Sequence seq = (ASN1Sequence)name.toASN1Primitive();
- ASN1Set set = ASN1Set.getInstance(seq.getObjectAt(0).toASN1Primitive());
- seq = (ASN1Sequence)set.getObjectAt(0);
-
- return seq.getObjectAt(1);
- }
-
- private void testEncodingPrintableString(ASN1ObjectIdentifier oid, String value)
- {
- ASN1Encodable converted = createEntryValue(oid, value);
- if (!(converted instanceof DERPrintableString))
- {
- fail("encoding for " + oid + " not printable string");
- }
- }
-
- private void testEncodingIA5String(ASN1ObjectIdentifier oid, String value)
- {
- ASN1Encodable converted = createEntryValue(oid, value);
- if (!(converted instanceof DERIA5String))
- {
- fail("encoding for " + oid + " not IA5String");
- }
- }
-
- private void testEncodingUTF8String(ASN1ObjectIdentifier oid, String value)
- throws IOException
- {
- ASN1Encodable converted = createEntryValue(oid, value);
- if (!(converted instanceof DERUTF8String))
- {
- fail("encoding for " + oid + " not IA5String");
- }
- if (!value.equals((DERUTF8String.getInstance(converted.toASN1Primitive().getEncoded()).getString())))
- {
- fail("decoding not correct");
- }
- }
-
- private void testEncodingGeneralizedTime(ASN1ObjectIdentifier oid, String value)
- {
- ASN1Encodable converted = createEntryValue(oid, value);
- if (!(converted instanceof ASN1GeneralizedTime))
- {
- fail("encoding for " + oid + " not GeneralizedTime");
- }
- converted = createEntryValueFromString(oid, value);
- if (!(converted instanceof ASN1GeneralizedTime))
- {
- fail("encoding for " + oid + " not GeneralizedTime");
- }
- }
-
- public void performTest()
- throws Exception
- {
- ietfUtilsTest();
-
- testEncodingPrintableString(BCStyle.C, "AU");
- testEncodingPrintableString(BCStyle.SERIALNUMBER, "123456");
- testEncodingPrintableString(BCStyle.DN_QUALIFIER, "123456");
- testEncodingIA5String(BCStyle.EmailAddress, "test@test.com");
- testEncodingIA5String(BCStyle.DC, "test");
- // correct encoding
- testEncodingGeneralizedTime(BCStyle.DATE_OF_BIRTH, "#180F32303032303132323132323232305A");
- // compatibility encoding
- testEncodingGeneralizedTime(BCStyle.DATE_OF_BIRTH, "20020122122220Z");
- testEncodingUTF8String(BCStyle.CN, "Mörsky");
-
- //
- // composite
- //
- X500NameBuilder builder = new X500NameBuilder(BCStyle.INSTANCE);
-
- builder.addRDN(BCStyle.C, "AU");
- builder.addRDN(BCStyle.O, "The Legion of the Bouncy Castle");
- builder.addRDN(BCStyle.L, "Melbourne");
- builder.addRDN(BCStyle.ST, "Victoria");
- builder.addRDN(BCStyle.E, "feedback-crypto@bouncycastle.org");
-
- X500Name name1 = builder.build();
-
- if (!name1.equals(name1))
- {
- fail("Failed same object test");
- }
-
-// if (!name1.equals(name1, true))
-// {
-// fail("Failed same object test - in Order");
-// }
-
- builder = new X500NameBuilder(BCStyle.INSTANCE);
-
- builder.addRDN(BCStyle.C, "AU");
- builder.addRDN(BCStyle.O, "The Legion of the Bouncy Castle");
- builder.addRDN(BCStyle.L, "Melbourne");
- builder.addRDN(BCStyle.ST, "Victoria");
- builder.addRDN(BCStyle.E, "feedback-crypto@bouncycastle.org");
-
- X500Name name2 = builder.build();
-
- if (!name1.equals(name2))
- {
- fail("Failed same name test");
- }
-
-// if (!name1.equals(name2, true))
-// {
-// fail("Failed same name test - in Order");
-// }
-
- if (name1.hashCode() != name2.hashCode())
- {
- fail("Failed same name test - in Order");
- }
-
- X500NameBuilder builder1 = new X500NameBuilder(BCStyle.INSTANCE);
-
- builder.addRDN(BCStyle.C, "AU");
- builder.addRDN(BCStyle.O, "The Legion of the Bouncy Castle");
- builder.addRDN(BCStyle.L, "Melbourne");
- builder.addRDN(BCStyle.ST, "Victoria");
- builder.addRDN(BCStyle.E, "feedback-crypto@bouncycastle.org");
-
- X500NameBuilder builder2 = new X500NameBuilder(BCStyle.INSTANCE);
-
- builder.addRDN(BCStyle.E, "feedback-crypto@bouncycastle.org");
- builder.addRDN(BCStyle.C, "AU");
- builder.addRDN(BCStyle.O, "The Legion of the Bouncy Castle");
- builder.addRDN(BCStyle.L, "Melbourne");
- builder.addRDN(BCStyle.ST, "Victoria");
-
- name1 = builder1.build();
- name2 = builder2.build();
-
- if (!name1.equals(name2))
- {
- fail("Failed reverse name test");
- }
-
- if (name1.hashCode() != name2.hashCode())
- {
- fail("Failed reverse name test hashCode");
- }
-
-// if (name1.equals(name2, true))
-// {
-// fail("Failed reverse name test - in Order");
-// }
-//
-// if (!name1.equals(name2, false))
-// {
-// fail("Failed reverse name test - in Order false");
-// }
-
-// Vector oids = name1.getOIDs();
-// if (!compareVectors(oids, ord1))
-// {
-// fail("oid comparison test");
-// }
- /*
- Vector val1 = new Vector();
-
- val1.addElement("AU");
- val1.addElement("The Legion of the Bouncy Castle");
- val1.addElement("Melbourne");
- val1.addElement("Victoria");
- val1.addElement("feedback-crypto@bouncycastle.org");
-
- name1 = new X500Name(ord1, val1);
-
- Vector values = name1.getValues();
- if (!compareVectors(values, val1))
- {
- fail("value comparison test");
- }
-
- ord2 = new Vector();
-
- ord2.addElement(X500Name.ST);
- ord2.addElement(X500Name.ST);
- ord2.addElement(X500Name.L);
- ord2.addElement(X500Name.O);
- ord2.addElement(X500Name.C);
-
- name1 = new X500Name(ord1, attrs);
- name2 = new X500Name(ord2, attrs);
-
- if (name1.equals(name2))
- {
- fail("Failed different name test");
- }
-
- ord2 = new Vector();
-
- ord2.addElement(X500Name.ST);
- ord2.addElement(X500Name.L);
- ord2.addElement(X500Name.O);
- ord2.addElement(X500Name.C);
-
- name1 = new X500Name(ord1, attrs);
- name2 = new X500Name(ord2, attrs);
-
- if (name1.equals(name2))
- {
- fail("Failed subset name test");
- }
-
- compositeTest();
- */
- ByteArrayOutputStream bOut;
- ASN1OutputStream aOut;
- ASN1InputStream aIn;
- /*
- //
- // getValues test
- //
- Vector v1 = name1.getValues(X500Name.O);
-
- if (v1.size() != 1 || !v1.elementAt(0).equals("The Legion of the Bouncy Castle"))
- {
- fail("O test failed");
- }
-
- Vector v2 = name1.getValues(X500Name.L);
-
- if (v2.size() != 1 || !v2.elementAt(0).equals("Melbourne"))
- {
- fail("L test failed");
- }
- */
- //
- // general subjects test
- //
- for (int i = 0; i != subjects.length; i++)
- {
- X500Name name = new X500Name(subjects[i]);
-
- bOut = new ByteArrayOutputStream();
- aOut = new ASN1OutputStream(bOut);
-
- aOut.writeObject(name);
-
- aIn = new ASN1InputStream(new ByteArrayInputStream(bOut.toByteArray()));
-
- name = X500Name.getInstance(aIn.readObject());
- if (!name.toString().equals(subjects[i]))
- {
- fail("failed regeneration test " + i + " got: " + name.toString() + " expected " + subjects[i]);
- }
- }
-
- for (int i = 0; i < hexSubjects.length; i += 2)
- {
- X500Name name = new X500Name(hexSubjects[i]);
-
- bOut = new ByteArrayOutputStream();
- aOut = new ASN1OutputStream(bOut);
-
- aOut.writeObject(name);
-
- aIn = new ASN1InputStream(new ByteArrayInputStream(bOut.toByteArray()));
-
- name = X500Name.getInstance(aIn.readObject());
- if (!name.toString().equals(hexSubjects[i + 1]))
- {
- fail("failed hex regeneration test " + i + " got: " + name.toString() + " expected " + subjects[i]);
- }
- }
-
- //
- // sort test
- //
- X500Name unsorted = new X500Name("SERIALNUMBER=BBB + CN=AA");
-
- if (!fromBytes(unsorted.getEncoded()).toString().equals("CN=AA+SERIALNUMBER=BBB"))
- {
- fail("failed sort test 1");
- }
-
- unsorted = new X500Name("CN=AA + SERIALNUMBER=BBB");
-
- if (!fromBytes(unsorted.getEncoded()).toString().equals("CN=AA+SERIALNUMBER=BBB"))
- {
- fail("failed sort test 2");
- }
-
- unsorted = new X500Name("SERIALNUMBER=B + CN=AA");
-
- if (!fromBytes(unsorted.getEncoded()).toString().equals("SERIALNUMBER=B+CN=AA"))
- {
- fail("failed sort test 3");
- }
-
- unsorted = new X500Name("CN=AA + SERIALNUMBER=B");
-
- if (!fromBytes(unsorted.getEncoded()).toString().equals("SERIALNUMBER=B+CN=AA"))
- {
- fail("failed sort test 4");
- }
-
- //
- // equality tests
- //
- equalityTest(new X500Name("CN=The Legion"), new X500Name("CN=The Legion"));
- equalityTest(new X500Name("CN= The Legion"), new X500Name("CN=The Legion"));
- equalityTest(new X500Name("CN=The Legion "), new X500Name("CN=The Legion"));
- equalityTest(new X500Name("CN= The Legion "), new X500Name("CN=The Legion"));
- equalityTest(new X500Name("CN= the legion "), new X500Name("CN=The Legion"));
-
- equalityTest(new X500Name("CN= the legion+C=AU, O=Legion "), new X500Name("CN=The Legion+C=AU, O=Legion"));
- // # test
-
- X500Name n1 = new X500Name("SERIALNUMBER=8,O=ABC,CN=ABC Class 3 CA,C=LT");
- X500Name n2 = new X500Name("2.5.4.5=8,O=ABC,CN=ABC Class 3 CA,C=LT");
- X500Name n3 = new X500Name("2.5.4.5=#130138,O=ABC,CN=ABC Class 3 CA,C=LT");
-
- equalityTest(n1, n2);
- equalityTest(n2, n3);
- equalityTest(n3, n1);
-
- n1 = new X500Name("2.5.4.5=#130138,CN=SSC Class 3 CA,O=UAB Skaitmeninio sertifikavimo centras,C=LT");
- n2 = new X500Name("SERIALNUMBER=#130138,CN=SSC Class 3 CA,O=UAB Skaitmeninio sertifikavimo centras,C=LT");
- n3 = X500Name.getInstance(ASN1Primitive.fromByteArray(Hex.decode("3063310b3009060355040613024c54312f302d060355040a1326"
- + "55414220536b6169746d656e696e696f20736572746966696b6176696d6f2063656e74726173311730150603550403130e53534320436c6173732033204341310a30080603550405130138")));
-
- equalityTest(n1, n2);
- equalityTest(n2, n3);
- equalityTest(n3, n1);
-
- n1 = new X500Name("SERIALNUMBER=8,O=XX,CN=ABC Class 3 CA,C=LT");
- n2 = new X500Name("2.5.4.5=8,O=,CN=ABC Class 3 CA,C=LT");
-
-// if (n1.equals(n2))
-// {
-// fail("empty inequality check failed");
-// }
-
- n1 = new X500Name("SERIALNUMBER=8,O=,CN=ABC Class 3 CA,C=LT");
- n2 = new X500Name("2.5.4.5=8,O=,CN=ABC Class 3 CA,C=LT");
-
- equalityTest(n1, n2);
-
- equalityTest(X500Name.getInstance(BCStrictStyle.INSTANCE, n1), X500Name.getInstance(BCStrictStyle.INSTANCE, n2));
-
- n2 = new X500Name("C=LT,2.5.4.5=8,O=,CN=ABC Class 3 CA");
-
- equalityTest(n1, n2);
-
- if (X500Name.getInstance(BCStrictStyle.INSTANCE, n1).equals(X500Name.getInstance(BCStrictStyle.INSTANCE, n2)))
- {
- fail("strict comparison failed");
- }
-
- //
- // inequality to sequences
- //
- name1 = new X500Name("CN=The Legion");
-
- if (name1.equals(new DERSequence()))
- {
- fail("inequality test with sequence");
- }
-
- if (name1.equals(new DERSequence(new DERSet())))
- {
- fail("inequality test with sequence and set");
- }
-
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(new ASN1ObjectIdentifier("1.1"));
- v.add(new ASN1ObjectIdentifier("1.1"));
- if (name1.equals(new DERSequence(new DERSet(new DERSet(v)))))
- {
- fail("inequality test with sequence and bad set");
- }
-
- if (name1.equals(new DERSequence(new DERSet(new DERSet(v)))))
- {
- fail("inequality test with sequence and bad set");
- }
-
- if (name1.equals(new DERSequence(new DERSet(new DERSequence()))))
- {
- fail("inequality test with sequence and short sequence");
- }
-
- if (name1.equals(new DERSequence(new DERSet(new DERSequence()))))
- {
- fail("inequality test with sequence and short sequence");
- }
-
- v = new ASN1EncodableVector();
-
- v.add(new ASN1ObjectIdentifier("1.1"));
- v.add(new DERSequence());
-
- if (name1.equals(new DERSequence(new DERSet(new DERSequence(v)))))
- {
- fail("inequality test with sequence and bad sequence");
- }
-
- if (name1.equals(null))
- {
- fail("inequality test with null");
- }
-
-// if (name1.equals(null, true))
-// {
-// fail("inequality test with null");
-// }
-
- //
- // this is contrived but it checks sorting of sets with equal elements
- //
- unsorted = new X500Name("CN=AA + CN=AA + CN=AA");
-
- ASN1ObjectIdentifier[] types = unsorted.getAttributeTypes();
- if (types.length != 3 || !types[0].equals(BCStyle.CN) || !types[1].equals(BCStyle.CN) || !types[2].equals(BCStyle.CN))
- {
- fail("types not matched correctly");
- }
-
- // general type test
- X500Name nested = new X500Name("CN=AA + CN=AA, C=AU");
-
- types = nested.getAttributeTypes();
- if (types.length != 3 || !types[0].equals(BCStyle.CN) || !types[1].equals(BCStyle.CN) || !types[2].equals(BCStyle.C))
- {
- fail("nested types not matched correctly");
- }
- //
- // tagging test - only works if CHOICE implemented
- //
- ASN1TaggedObject tag = new DERTaggedObject(false, 1, new X500Name("CN=AA"));
-
- if (!tag.isExplicit())
- {
- fail("failed to explicitly tag CHOICE object");
- }
-
- X500Name name = X500Name.getInstance(tag, false);
-
- if (!name.equals(new X500Name("CN=AA")))
- {
- fail("failed to recover tagged name");
- }
-
- DERUTF8String testString = new DERUTF8String("The Legion of the Bouncy Castle");
- byte[] encodedBytes = testString.getEncoded();
- byte[] hexEncodedBytes = Hex.encode(encodedBytes);
- String hexEncodedString = "#" + new String(hexEncodedBytes);
-
- DERUTF8String converted = (DERUTF8String)
- new X509DefaultEntryConverter().getConvertedValue(
- BCStyle.L , hexEncodedString);
-
- if (!converted.equals(testString))
- {
- fail("failed X509DefaultEntryConverter test");
- }
-
- //
- // try escaped.
- //
- converted = (DERUTF8String)
- new X509DefaultEntryConverter().getConvertedValue(
- BCStyle.L , "\\" + hexEncodedString);
-
- if (!converted.equals(new DERUTF8String(hexEncodedString)))
- {
- fail("failed X509DefaultEntryConverter test got " + converted + " expected: " + hexEncodedString);
- }
-
- //
- // try a weird value
- //
- X500Name n = new X500Name("CN=\\#nothex#string");
-
- if (!n.toString().equals("CN=\\#nothex#string"))
- {
- fail("# string not properly escaped.");
- }
-
- RDN[] vls = n.getRDNs(BCStyle.CN);
- if (vls.length != 1 || !getValue(vls[0]).equals("#nothex#string"))
- {
- fail("escaped # not reduced properly");
- }
-
- types = n.getAttributeTypes();
- if (types.length != 1 || !types[0].equals(BCStyle.CN))
- {
- fail("type not matched correctly");
- }
-
- n = new X500Name("CN=\"a+b\"");
-
- vls = n.getRDNs(BCStyle.CN);
- if (vls.length != 1 || !getValue(vls[0]).equals("a+b"))
- {
- fail("escaped + not reduced properly");
- }
-
- n = new X500Name("CN=a\\+b");
-
- vls = n.getRDNs(BCStyle.CN);
- if (vls.length != 1 || !getValue(vls[0]).equals("a+b"))
- {
- fail("escaped + not reduced properly");
- }
-
- if (!n.toString().equals("CN=a\\+b"))
- {
- fail("+ in string not properly escaped.");
- }
-
- n = new X500Name("CN=a\\=b");
-
- vls = n.getRDNs(BCStyle.CN);
- if (vls.length != 1 || !getValue(vls[0]).equals("a=b"))
- {
- fail("escaped = not reduced properly");
- }
-
- if (!n.toString().equals("CN=a\\=b"))
- {
- fail("= in string not properly escaped.");
- }
-
- n = new X500Name("TELEPHONENUMBER=\"+61999999999\"");
-
- vls = n.getRDNs(BCStyle.TELEPHONE_NUMBER);
- if (vls.length != 1 || !getValue(vls[0]).equals("+61999999999"))
- {
- fail("telephonenumber escaped + not reduced properly");
- }
-
- n = new X500Name("TELEPHONENUMBER=\\+61999999999");
-
- vls = n.getRDNs(BCStyle.TELEPHONE_NUMBER);
- if (vls.length != 1 || !getValue(vls[0]).equals("+61999999999"))
- {
- fail("telephonenumber escaped + not reduced properly");
- }
-
- // test query methods
- if (!"E".equals(BCStyle.INSTANCE.oidToDisplayName(BCStyle.EmailAddress)))
- {
- fail("display name for E incorrect");
- }
-
- String[] aliases = BCStyle.INSTANCE.oidToAttrNames(BCStyle.EmailAddress);
- if (aliases.length != 2)
- {
- fail("no aliases found");
- }
- if (!("e".equals(aliases[0]) || "e".equals(aliases[1])))
- {
- fail("first alias name for E incorrect");
- }
- if (!("emailaddress".equals(aliases[0]) || "emailaddress".equals(aliases[1])))
- {
- fail("second alias name for E incorrect");
- }
-
- if (BCStyle.INSTANCE.oidToDisplayName(new ASN1ObjectIdentifier("1.2.1")) != null)
- {
- fail("unknown oid matched!");
- }
-
- if (BCStyle.INSTANCE.oidToAttrNames(new ASN1ObjectIdentifier("1.2.1")).length != 0)
- {
- fail("unknown oid matched aliases!");
- }
- }
-
- private String getValue(RDN vl)
- {
- return ((ASN1String)vl.getFirst().getValue()).getString();
- }
-
- private void ietfUtilsTest()
- throws Exception
- {
- IETFUtils.valueToString(new DERUTF8String(" "));
- }
-
- /*
- private boolean compareVectors(Vector a, Vector b) // for compatibility with early JDKs
- {
- if (a.size() != b.size())
- {
- return false;
- }
-
- for (int i = 0; i != a.size(); i++)
- {
- if (!a.elementAt(i).equals(b.elementAt(i)))
- {
- return false;
- }
- }
-
- return true;
- }
-
- private void compositeTest()
- throws IOException
- {
- //
- // composite test
- //
- byte[] enc = Hex.decode("305e310b300906035504061302415531283026060355040a0c1f546865204c6567696f6e206f662074686520426f756e637920436173746c653125301006035504070c094d656c626f75726e653011060355040b0c0a4173636f742056616c65");
- ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(enc));
-
- X500Name n = X500Name.getInstance(aIn.readObject());
-
- if (!n.toString().equals("C=AU,O=The Legion of the Bouncy Castle,L=Melbourne+OU=Ascot Vale"))
- {
- fail("Failed composite to string test got: " + n.toString());
- }
-
- if (!n.toString(true, X500Name.DefaultSymbols).equals("L=Melbourne+OU=Ascot Vale,O=The Legion of the Bouncy Castle,C=AU"))
- {
- fail("Failed composite to string test got: " + n.toString(true, X500Name.DefaultSymbols));
- }
-
- n = new X500Name(true, "L=Melbourne+OU=Ascot Vale,O=The Legion of the Bouncy Castle,C=AU");
- if (!n.toString().equals("C=AU,O=The Legion of the Bouncy Castle,L=Melbourne+OU=Ascot Vale"))
- {
- fail("Failed composite to string reversal test got: " + n.toString());
- }
-
- n = new X500Name("C=AU, O=The Legion of the Bouncy Castle, L=Melbourne + OU=Ascot Vale");
-
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- ASN1OutputStream aOut = new ASN1OutputStream(bOut);
-
- aOut.writeObject(n);
-
- byte[] enc2 = bOut.toByteArray();
-
- if (!Arrays.areEqual(enc, enc2))
- {
- fail("Failed composite string to encoding test");
- }
-
- //
- // dud name test - handle empty DN without barfing.
- //
- n = new X500Name("C=CH,O=,OU=dummy,CN=mail@dummy.com");
-
- n = X500Name.getInstance(ASN1Object.fromByteArray(n.getEncoded()));
- }
- */
- private void equalityTest(X500Name name1, X500Name name2)
- {
- if (!name1.equals(name2))
- {
- fail("equality test failed for " + name1 + " : " + name2);
- }
-
- if (name1.hashCode() != name2.hashCode())
- {
- fail("hashCodeTest test failed for " + name1 + " : " + name2);
- }
- }
-
-
- public static void main(
- String[] args)
- {
- runTest(new X500NameTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/X509ExtensionsTest.java b/core/src/test/java/org/bouncycastle/asn1/test/X509ExtensionsTest.java
deleted file mode 100644
index 008d4d8c..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/X509ExtensionsTest.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.x509.X509Extensions;
-import org.bouncycastle.asn1.x509.X509ExtensionsGenerator;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class X509ExtensionsTest
- extends SimpleTest
-{
- private static final ASN1ObjectIdentifier OID_2 = new ASN1ObjectIdentifier("1.2.2");
- private static final ASN1ObjectIdentifier OID_3 = new ASN1ObjectIdentifier("1.2.3");
- private static final ASN1ObjectIdentifier OID_1 = new ASN1ObjectIdentifier("1.2.1");
-
- public String getName()
- {
- return "X509Extensions";
- }
-
- public void performTest() throws Exception
- {
- X509ExtensionsGenerator gen = new X509ExtensionsGenerator();
-
- gen.addExtension(OID_1, true, new byte[20]);
- gen.addExtension(OID_2, true, new byte[20]);
-
- X509Extensions ext1 = gen.generate();
- X509Extensions ext2 = gen.generate();
-
- if (!ext1.equals(ext2))
- {
- fail("equals test failed");
- }
-
- gen.reset();
-
- gen.addExtension(OID_2, true, new byte[20]);
- gen.addExtension(OID_1, true, new byte[20]);
-
- ext2 = gen.generate();
-
- if (ext1.equals(ext2))
- {
- fail("inequality test failed");
- }
-
- if (!ext1.equivalent(ext2))
- {
- fail("equivalence true failed");
- }
-
- gen.reset();
-
- gen.addExtension(OID_1, true, new byte[22]);
- gen.addExtension(OID_2, true, new byte[20]);
-
- ext2 = gen.generate();
-
- if (ext1.equals(ext2))
- {
- fail("inequality 1 failed");
- }
-
- if (ext1.equivalent(ext2))
- {
- fail("non-equivalence 1 failed");
- }
-
- gen.reset();
-
- gen.addExtension(OID_3, true, new byte[20]);
- gen.addExtension(OID_2, true, new byte[20]);
-
- ext2 = gen.generate();
-
- if (ext1.equals(ext2))
- {
- fail("inequality 2 failed");
- }
-
- if (ext1.equivalent(ext2))
- {
- fail("non-equivalence 2 failed");
- }
-
- try
- {
- gen.addExtension(OID_2, true, new byte[20]);
- fail("repeated oid");
- }
- catch (IllegalArgumentException e)
- {
- if (!e.getMessage().equals("extension 1.2.2 already added"))
- {
- fail("wrong exception on repeated oid: " + e.getMessage());
- }
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new X509ExtensionsTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/X509NameTest.java b/core/src/test/java/org/bouncycastle/asn1/test/X509NameTest.java
deleted file mode 100644
index f1ae757d..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/X509NameTest.java
+++ /dev/null
@@ -1,693 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1GeneralizedTime;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OutputStream;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DERPrintableString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERSet;
-import org.bouncycastle.asn1.DERUTF8String;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x500.X500NameBuilder;
-import org.bouncycastle.asn1.x500.style.BCStyle;
-import org.bouncycastle.asn1.x509.X509DefaultEntryConverter;
-import org.bouncycastle.asn1.x509.X509Name;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class X509NameTest
- extends SimpleTest
-{
- String[] subjects =
- {
- "C=AU,ST=Victoria,L=South Melbourne,O=Connect 4 Pty Ltd,OU=Webserver Team,CN=www2.connect4.com.au,E=webmaster@connect4.com.au",
- "C=AU,ST=Victoria,L=South Melbourne,O=Connect 4 Pty Ltd,OU=Certificate Authority,CN=Connect 4 CA,E=webmaster@connect4.com.au",
- "C=AU,ST=QLD,CN=SSLeay/rsa test cert",
- "C=US,O=National Aeronautics and Space Administration,SERIALNUMBER=16+CN=Steve Schoch",
- "E=cooke@issl.atl.hp.com,C=US,OU=Hewlett Packard Company (ISSL),CN=Paul A. Cooke",
- "O=Sun Microsystems Inc,CN=store.sun.com",
- "unstructuredAddress=192.168.1.33,unstructuredName=pixfirewall.ciscopix.com,CN=pixfirewall.ciscopix.com",
- "CN=*.canal-plus.com,OU=Provided by TBS INTERNET http://www.tbs-certificats.com/,OU=\\ CANAL \\+,O=CANAL\\+DISTRIBUTION,L=issy les moulineaux,ST=Hauts de Seine,C=FR",
- "O=Bouncy Castle,CN=www.bouncycastle.org\\ ",
- "O=Bouncy Castle,CN=c:\\\\fred\\\\bob"
- };
-
- public String getName()
- {
- return "X509Name";
- }
-
- private static X509Name fromBytes(
- byte[] bytes)
- throws IOException
- {
- return X509Name.getInstance(new ASN1InputStream(new ByteArrayInputStream(bytes)).readObject());
- }
-
- private ASN1Encodable createEntryValue(ASN1ObjectIdentifier oid, String value)
- {
- Hashtable attrs = new Hashtable();
-
- attrs.put(oid, value);
-
- Vector order = new Vector();
-
- order.addElement(oid);
-
- X509Name name = new X509Name(order, attrs);
-
- ASN1Sequence seq = (ASN1Sequence)name.toASN1Primitive();
- ASN1Set set = (ASN1Set)seq.getObjectAt(0);
- seq = (ASN1Sequence)set.getObjectAt(0);
-
- return seq.getObjectAt(1);
- }
-
- private ASN1Encodable createEntryValueFromString(ASN1ObjectIdentifier oid, String value)
- {
- Hashtable attrs = new Hashtable();
-
- attrs.put(oid, value);
-
- Vector order = new Vector();
-
- order.addElement(oid);
-
- X509Name name = new X509Name(new X509Name(order, attrs).toString());
-
- ASN1Sequence seq = (ASN1Sequence)name.toASN1Primitive();
- ASN1Set set = (ASN1Set)seq.getObjectAt(0);
- seq = (ASN1Sequence)set.getObjectAt(0);
-
- return seq.getObjectAt(1);
- }
-
- private void testEncodingPrintableString(ASN1ObjectIdentifier oid, String value)
- {
- ASN1Encodable converted = createEntryValue(oid, value);
- if (!(converted instanceof DERPrintableString))
- {
- fail("encoding for " + oid + " not printable string");
- }
- }
-
- private void testEncodingIA5String(ASN1ObjectIdentifier oid, String value)
- {
- ASN1Encodable converted = createEntryValue(oid, value);
- if (!(converted instanceof DERIA5String))
- {
- fail("encoding for " + oid + " not IA5String");
- }
- }
-
-
- private void testEncodingUTF8String(ASN1ObjectIdentifier oid, String value)
- throws IOException
- {
- ASN1Encodable converted = createEntryValue(oid, value);
- if (!(converted instanceof DERUTF8String))
- {
- fail("encoding for " + oid + " not IA5String");
- }
- if (!value.equals((DERUTF8String.getInstance(converted.toASN1Primitive().getEncoded()).getString())))
- {
- fail("decoding not correct");
- }
- }
-
- private void testEncodingGeneralizedTime(ASN1ObjectIdentifier oid, String value)
- {
- ASN1Encodable converted = createEntryValue(oid, value);
- if (!(converted instanceof ASN1GeneralizedTime))
- {
- fail("encoding for " + oid + " not GeneralizedTime");
- }
- converted = createEntryValueFromString(oid, value);
- if (!(converted instanceof ASN1GeneralizedTime))
- {
- fail("encoding for " + oid + " not GeneralizedTime");
- }
- }
-
- public void performTest()
- throws Exception
- {
- testEncodingPrintableString(X509Name.C, "AU");
- testEncodingPrintableString(X509Name.SERIALNUMBER, "123456");
- testEncodingPrintableString(X509Name.DN_QUALIFIER, "123456");
- testEncodingIA5String(X509Name.EmailAddress, "test@test.com");
- testEncodingIA5String(X509Name.DC, "test");
- // correct encoding
- testEncodingGeneralizedTime(X509Name.DATE_OF_BIRTH, "#180F32303032303132323132323232305A");
- // compatibility encoding
- testEncodingGeneralizedTime(X509Name.DATE_OF_BIRTH, "20020122122220Z");
- testEncodingUTF8String(X509Name.CN, "Mörsky");
- //
- // composite
- //
- Hashtable attrs = new Hashtable();
-
- attrs.put(X509Name.C, "AU");
- attrs.put(X509Name.O, "The Legion of the Bouncy Castle");
- attrs.put(X509Name.L, "Melbourne");
- attrs.put(X509Name.ST, "Victoria");
- attrs.put(X509Name.E, "feedback-crypto@bouncycastle.org");
-
- Vector order = new Vector();
-
- order.addElement(X509Name.C);
- order.addElement(X509Name.O);
- order.addElement(X509Name.L);
- order.addElement(X509Name.ST);
- order.addElement(X509Name.E);
-
- X509Name name1 = new X509Name(order, attrs);
-
- if (!name1.equals(name1))
- {
- fail("Failed same object test");
- }
-
- if (!name1.equals(name1, true))
- {
- fail("Failed same object test - in Order");
- }
-
- X509Name name2 = new X509Name(order, attrs);
-
- if (!name1.equals(name2))
- {
- fail("Failed same name test");
- }
-
- if (!name1.equals(name2, true))
- {
- fail("Failed same name test - in Order");
- }
-
- if (name1.hashCode() != name2.hashCode())
- {
- fail("Failed same name test - in Order");
- }
-
- Vector ord1 = new Vector();
-
- ord1.addElement(X509Name.C);
- ord1.addElement(X509Name.O);
- ord1.addElement(X509Name.L);
- ord1.addElement(X509Name.ST);
- ord1.addElement(X509Name.E);
-
- Vector ord2 = new Vector();
-
- ord2.addElement(X509Name.E);
- ord2.addElement(X509Name.ST);
- ord2.addElement(X509Name.L);
- ord2.addElement(X509Name.O);
- ord2.addElement(X509Name.C);
-
- name1 = new X509Name(ord1, attrs);
- name2 = new X509Name(ord2, attrs);
-
- if (!name1.equals(name2))
- {
- fail("Failed reverse name test");
- }
-
- if (name1.hashCode() != name2.hashCode())
- {
- fail("Failed reverse name test hashCode");
- }
-
- if (name1.equals(name2, true))
- {
- fail("Failed reverse name test - in Order");
- }
-
- if (!name1.equals(name2, false))
- {
- fail("Failed reverse name test - in Order false");
- }
-
- Vector oids = name1.getOIDs();
- if (!compareVectors(oids, ord1))
- {
- fail("oid comparison test");
- }
-
- Vector val1 = new Vector();
-
- val1.addElement("AU");
- val1.addElement("The Legion of the Bouncy Castle");
- val1.addElement("Melbourne");
- val1.addElement("Victoria");
- val1.addElement("feedback-crypto@bouncycastle.org");
-
- name1 = new X509Name(ord1, val1);
-
- Vector values = name1.getValues();
- if (!compareVectors(values, val1))
- {
- fail("value comparison test");
- }
-
- ord2 = new Vector();
-
- ord2.addElement(X509Name.ST);
- ord2.addElement(X509Name.ST);
- ord2.addElement(X509Name.L);
- ord2.addElement(X509Name.O);
- ord2.addElement(X509Name.C);
-
- name1 = new X509Name(ord1, attrs);
- name2 = new X509Name(ord2, attrs);
-
- if (name1.equals(name2))
- {
- fail("Failed different name test");
- }
-
- ord2 = new Vector();
-
- ord2.addElement(X509Name.ST);
- ord2.addElement(X509Name.L);
- ord2.addElement(X509Name.O);
- ord2.addElement(X509Name.C);
-
- name1 = new X509Name(ord1, attrs);
- name2 = new X509Name(ord2, attrs);
-
- if (name1.equals(name2))
- {
- fail("Failed subset name test");
- }
-
- compositeTest();
-
- ByteArrayOutputStream bOut;
- ASN1OutputStream aOut;
- ASN1InputStream aIn;
-
- //
- // getValues test
- //
- Vector v1 = name1.getValues(X509Name.O);
-
- if (v1.size() != 1 || !v1.elementAt(0).equals("The Legion of the Bouncy Castle"))
- {
- fail("O test failed");
- }
-
- Vector v2 = name1.getValues(X509Name.L);
-
- if (v2.size() != 1 || !v2.elementAt(0).equals("Melbourne"))
- {
- fail("L test failed");
- }
-
- //
- // general subjects test
- //
- for (int i = 0; i != subjects.length; i++)
- {
- X509Name name = new X509Name(subjects[i]);
-
- bOut = new ByteArrayOutputStream();
- aOut = new ASN1OutputStream(bOut);
-
- aOut.writeObject(name);
-
- aIn = new ASN1InputStream(new ByteArrayInputStream(bOut.toByteArray()));
-
- name = X509Name.getInstance(aIn.readObject());
-
- if (!name.toString().equals(subjects[i]))
- {
- fail("failed regeneration test " + i + " got " + name.toString());
- }
- }
-
- //
- // sort test
- //
- X509Name unsorted = new X509Name("SERIALNUMBER=BBB + CN=AA");
-
- if (!fromBytes(unsorted.getEncoded()).toString().equals("CN=AA+SERIALNUMBER=BBB"))
- {
- fail("failed sort test 1");
- }
-
- unsorted = new X509Name("CN=AA + SERIALNUMBER=BBB");
-
- if (!fromBytes(unsorted.getEncoded()).toString().equals("CN=AA+SERIALNUMBER=BBB"))
- {
- fail("failed sort test 2");
- }
-
- unsorted = new X509Name("SERIALNUMBER=B + CN=AA");
-
- if (!fromBytes(unsorted.getEncoded()).toString().equals("SERIALNUMBER=B+CN=AA"))
- {
- fail("failed sort test 3");
- }
-
- unsorted = new X509Name("CN=AA + SERIALNUMBER=B");
-
- if (!fromBytes(unsorted.getEncoded()).toString().equals("SERIALNUMBER=B+CN=AA"))
- {
- fail("failed sort test 4");
- }
-
- //
- // equality tests
- //
- equalityTest(new X509Name("CN=The Legion"), new X509Name("CN=The Legion"));
- equalityTest(new X509Name("CN= The Legion"), new X509Name("CN=The Legion"));
- equalityTest(new X509Name("CN=The Legion "), new X509Name("CN=The Legion"));
- equalityTest(new X509Name("CN= The Legion "), new X509Name("CN=The Legion"));
- equalityTest(new X509Name("CN= the legion "), new X509Name("CN=The Legion"));
-
- // # test
-
- X509Name n1 = new X509Name("SERIALNUMBER=8,O=ABC,CN=ABC Class 3 CA,C=LT");
- X509Name n2 = new X509Name("2.5.4.5=8,O=ABC,CN=ABC Class 3 CA,C=LT");
- X509Name n3 = new X509Name("2.5.4.5=#130138,O=ABC,CN=ABC Class 3 CA,C=LT");
-
- equalityTest(n1, n2);
- equalityTest(n2, n3);
- equalityTest(n3, n1);
-
- n1 = new X509Name(true, "2.5.4.5=#130138,CN=SSC Class 3 CA,O=UAB Skaitmeninio sertifikavimo centras,C=LT");
- n2 = new X509Name(true, "SERIALNUMBER=#130138,CN=SSC Class 3 CA,O=UAB Skaitmeninio sertifikavimo centras,C=LT");
- n3 = X509Name.getInstance(ASN1Primitive.fromByteArray(Hex.decode("3063310b3009060355040613024c54312f302d060355040a1326"
- + "55414220536b6169746d656e696e696f20736572746966696b6176696d6f2063656e74726173311730150603550403130e53534320436c6173732033204341310a30080603550405130138")));
-
- equalityTest(n1, n2);
- equalityTest(n2, n3);
- equalityTest(n3, n1);
-
- n1 = new X509Name("SERIALNUMBER=8,O=XX,CN=ABC Class 3 CA,C=LT");
- n2 = new X509Name("2.5.4.5=8,O=,CN=ABC Class 3 CA,C=LT");
-
- if (n1.equals(n2))
- {
- fail("empty inequality check failed");
- }
-
- n1 = new X509Name("SERIALNUMBER=8,O=,CN=ABC Class 3 CA,C=LT");
- n2 = new X509Name("2.5.4.5=8,O=,CN=ABC Class 3 CA,C=LT");
-
- equalityTest(n1, n2);
-
- //
- // inequality to sequences
- //
- name1 = new X509Name("CN=The Legion");
-
- if (name1.equals(new DERSequence()))
- {
- fail("inequality test with sequence");
- }
-
- if (name1.equals(new DERSequence(new DERSet())))
- {
- fail("inequality test with sequence and set");
- }
-
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(new ASN1ObjectIdentifier("1.1"));
- v.add(new ASN1ObjectIdentifier("1.1"));
- if (name1.equals(new DERSequence(new DERSet(new DERSet(v)))))
- {
- fail("inequality test with sequence and bad set");
- }
-
- if (name1.equals(new DERSequence(new DERSet(new DERSet(v))), true))
- {
- fail("inequality test with sequence and bad set");
- }
-
- if (name1.equals(new DERSequence(new DERSet(new DERSequence()))))
- {
- fail("inequality test with sequence and short sequence");
- }
-
- if (name1.equals(new DERSequence(new DERSet(new DERSequence())), true))
- {
- fail("inequality test with sequence and short sequence");
- }
-
- v = new ASN1EncodableVector();
-
- v.add(new ASN1ObjectIdentifier("1.1"));
- v.add(new DERSequence());
-
- if (name1.equals(new DERSequence(new DERSet(new DERSequence(v)))))
- {
- fail("inequality test with sequence and bad sequence");
- }
-
- if (name1.equals(null))
- {
- fail("inequality test with null");
- }
-
- if (name1.equals(null, true))
- {
- fail("inequality test with null");
- }
-
- //
- // this is contrived but it checks sorting of sets with equal elements
- //
- unsorted = new X509Name("CN=AA + CN=AA + CN=AA");
-
- //
- // tagging test - only works if CHOICE implemented
- //
- /*
- ASN1TaggedObject tag = new DERTaggedObject(false, 1, new X509Name("CN=AA"));
-
- if (!tag.isExplicit())
- {
- fail("failed to explicitly tag CHOICE object");
- }
-
- X509Name name = X509Name.getInstance(tag, false);
-
- if (!name.equals(new X509Name("CN=AA")))
- {
- fail("failed to recover tagged name");
- }
- */
-
- DERUTF8String testString = new DERUTF8String("The Legion of the Bouncy Castle");
- byte[] encodedBytes = testString.getEncoded();
- byte[] hexEncodedBytes = Hex.encode(encodedBytes);
- String hexEncodedString = "#" + new String(hexEncodedBytes);
-
- DERUTF8String converted = (DERUTF8String)
- new X509DefaultEntryConverter().getConvertedValue(
- X509Name.L , hexEncodedString);
-
- if (!converted.equals(testString))
- {
- fail("failed X509DefaultEntryConverter test");
- }
-
- //
- // try escaped.
- //
- converted = (DERUTF8String)
- new X509DefaultEntryConverter().getConvertedValue(
- X509Name.L , "\\" + hexEncodedString);
-
- if (!converted.equals(new DERUTF8String(hexEncodedString)))
- {
- fail("failed X509DefaultEntryConverter test got " + converted + " expected: " + hexEncodedString);
- }
-
- //
- // try a weird value
- //
- X509Name n = new X509Name("CN=\\#nothex#string");
-
- if (!n.toString().equals("CN=\\#nothex#string"))
- {
- fail("# string not properly escaped.");
- }
-
- Vector vls = n.getValues(X509Name.CN);
- if (vls.size() != 1 || !vls.elementAt(0).equals("#nothex#string"))
- {
- fail("escaped # not reduced properly");
- }
-
- n = new X509Name("CN=\"a+b\"");
-
- vls = n.getValues(X509Name.CN);
- if (vls.size() != 1 || !vls.elementAt(0).equals("a+b"))
- {
- fail("escaped + not reduced properly");
- }
-
- n = new X509Name("CN=a\\+b");
-
- vls = n.getValues(X509Name.CN);
- if (vls.size() != 1 || !vls.elementAt(0).equals("a+b"))
- {
- fail("escaped + not reduced properly");
- }
-
- if (!n.toString().equals("CN=a\\+b"))
- {
- fail("+ in string not properly escaped.");
- }
-
- n = new X509Name("CN=a\\=b");
-
- vls = n.getValues(X509Name.CN);
- if (vls.size() != 1 || !vls.elementAt(0).equals("a=b"))
- {
- fail("escaped = not reduced properly");
- }
-
- if (!n.toString().equals("CN=a\\=b"))
- {
- fail("= in string not properly escaped.");
- }
-
- n = new X509Name("TELEPHONENUMBER=\"+61999999999\"");
-
- vls = n.getValues(X509Name.TELEPHONE_NUMBER);
- if (vls.size() != 1 || !vls.elementAt(0).equals("+61999999999"))
- {
- fail("telephonenumber escaped + not reduced properly");
- }
-
- n = new X509Name("TELEPHONENUMBER=\\+61999999999");
-
- vls = n.getValues(X509Name.TELEPHONE_NUMBER);
- if (vls.size() != 1 || !vls.elementAt(0).equals("+61999999999"))
- {
- fail("telephonenumber escaped + not reduced properly");
- }
-
- // migration
- X500NameBuilder builder = new X500NameBuilder(BCStyle.INSTANCE);
- builder.addMultiValuedRDN(new ASN1ObjectIdentifier[] { BCStyle.CN, BCStyle.SN }, new String[] { "Thomas", "CVR:12341233-UID:1111" });
- builder.addRDN(BCStyle.O, "Test");
- builder.addRDN(BCStyle.C, "DK");
-
- X500Name subject = builder.build();
- ASN1Primitive derObject = subject.toASN1Primitive();
- X509Name instance = X509Name.getInstance(derObject);
- }
-
- private boolean compareVectors(Vector a, Vector b) // for compatibility with early JDKs
- {
- if (a.size() != b.size())
- {
- return false;
- }
-
- for (int i = 0; i != a.size(); i++)
- {
- if (!a.elementAt(i).equals(b.elementAt(i)))
- {
- return false;
- }
- }
-
- return true;
- }
-
- private void compositeTest()
- throws IOException
- {
- //
- // composite test
- //
- byte[] enc = Hex.decode("305e310b300906035504061302415531283026060355040a0c1f546865204c6567696f6e206f662074686520426f756e637920436173746c653125301006035504070c094d656c626f75726e653011060355040b0c0a4173636f742056616c65");
- ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(enc));
-
- X509Name n = X509Name.getInstance(aIn.readObject());
-
- if (!n.toString().equals("C=AU,O=The Legion of the Bouncy Castle,L=Melbourne+OU=Ascot Vale"))
- {
- fail("Failed composite to string test got: " + n.toString());
- }
-
- if (!n.toString(true, X509Name.DefaultSymbols).equals("L=Melbourne+OU=Ascot Vale,O=The Legion of the Bouncy Castle,C=AU"))
- {
- fail("Failed composite to string test got: " + n.toString(true, X509Name.DefaultSymbols));
- }
-
- n = new X509Name(true, "L=Melbourne+OU=Ascot Vale,O=The Legion of the Bouncy Castle,C=AU");
- if (!n.toString().equals("C=AU,O=The Legion of the Bouncy Castle,L=Melbourne+OU=Ascot Vale"))
- {
- fail("Failed composite to string reversal test got: " + n.toString());
- }
-
- n = new X509Name("C=AU, O=The Legion of the Bouncy Castle, L=Melbourne + OU=Ascot Vale");
-
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- ASN1OutputStream aOut = new ASN1OutputStream(bOut);
-
- aOut.writeObject(n);
-
- byte[] enc2 = bOut.toByteArray();
-
- if (!Arrays.areEqual(enc, enc2))
- {
- //fail("Failed composite string to encoding test");
- }
-
- //
- // dud name test - handle empty DN without barfing.
- //
- n = new X509Name("C=CH,O=,OU=dummy,CN=mail@dummy.com");
-
- n = X509Name.getInstance(ASN1Primitive.fromByteArray(n.getEncoded()));
- }
-
- private void equalityTest(X509Name x509Name, X509Name x509Name1)
- {
- if (!x509Name.equals(x509Name1))
- {
- fail("equality test failed for " + x509Name + " : " + x509Name1);
- }
-
- if (x509Name.hashCode() != x509Name1.hashCode())
- {
- fail("hashCodeTest test failed for " + x509Name + " : " + x509Name1);
- }
-
- if (!x509Name.equals(x509Name1, true))
- {
- fail("equality test failed for " + x509Name + " : " + x509Name1);
- }
- }
-
-
- public static void main(
- String[] args)
- {
- runTest(new X509NameTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/asn1/test/X9Test.java b/core/src/test/java/org/bouncycastle/asn1/test/X9Test.java
deleted file mode 100644
index 79f5fc56..00000000
--- a/core/src/test/java/org/bouncycastle/asn1/test/X9Test.java
+++ /dev/null
@@ -1,168 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
-import org.bouncycastle.asn1.sec.ECPrivateKey;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.asn1.x9.X962NamedCurves;
-import org.bouncycastle.asn1.x9.X962Parameters;
-import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.asn1.x9.X9ECPoint;
-import org.bouncycastle.asn1.x9.X9IntegerConverter;
-import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class X9Test
- extends SimpleTest
-{
- private byte[] namedPub = Base64.decode("MDcwEwYHKoZIzj0CAQYIKoZIzj0DAQEDIAADG5xRI+Iki/JrvL20hoDUa7Cggzorv5B9yyqSMjYu");
- private byte[] expPub = Base64.decode(
- "MIH8MIHXBgcqhkjOPQIBMIHLAgEBMCkGByqGSM49AQECHn///////////////3///////4AAAA" +
- "AAAH///////zBXBB5///////////////9///////+AAAAAAAB///////wEHiVXBfoqMGZUsfTL" +
- "A9anUKMMJQEC1JiHF9m6FattPgMVAH1zdBaP/jRxtgqFdoahlHXTv6L/BB8DZ2iujhi7ks/PAF" +
- "yUmqLG2UhT0OZgu/hUsclQX+laAh5///////////////9///+XXetBs6YFfDxDIUZSZVECAQED" +
- "IAADG5xRI+Iki/JrvL20hoDUa7Cggzorv5B9yyqSMjYu");
-
- private byte[] namedPriv = Base64.decode("MCICAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQEECDAGAgEBBAEK");
- private byte[] expPriv = Base64.decode(
- "MIHnAgEAMIHXBgcqhkjOPQIBMIHLAgEBMCkGByqGSM49AQECHn///////////////3///////4"
- + "AAAAAAAH///////zBXBB5///////////////9///////+AAAAAAAB///////wEHiVXBfoqMGZU"
- + "sfTLA9anUKMMJQEC1JiHF9m6FattPgMVAH1zdBaP/jRxtgqFdoahlHXTv6L/BB8DZ2iujhi7ks"
- + "/PAFyUmqLG2UhT0OZgu/hUsclQX+laAh5///////////////9///+XXetBs6YFfDxDIUZSZVEC"
- + "AQEECDAGAgEBBAEU");
-
- private void encodePublicKey()
- throws Exception
- {
- X9ECParameters ecP = X962NamedCurves.getByOID(X9ObjectIdentifiers.prime239v3);
-
- X9IntegerConverter conv = new X9IntegerConverter();
-
- if (conv.getByteLength(ecP.getCurve()) != 30)
- {
- fail("wrong byte length reported for curve");
- }
-
- if (ecP.getCurve().getFieldSize() != 239)
- {
- fail("wrong field size reported for curve");
- }
-
- //
- // named curve
- //
- X962Parameters params = new X962Parameters(X9ObjectIdentifiers.prime192v1);
- ECPoint point = ecP.getG().multiply(BigInteger.valueOf(100));
-
- ASN1OctetString p = new DEROctetString(point.getEncoded(true));
-
- SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), p.getOctets());
- if (!areEqual(info.getEncoded(), namedPub))
- {
- fail("failed public named generation");
- }
-
- X9ECPoint x9P = new X9ECPoint(ecP.getCurve(), p);
-
- if (!Arrays.areEqual(p.getOctets(), x9P.getPoint().getEncoded()))
- {
- fail("point encoding not preserved");
- }
-
- ASN1Primitive o = ASN1Primitive.fromByteArray(namedPub);
-
- if (!info.equals(o))
- {
- fail("failed public named equality");
- }
-
- //
- // explicit curve parameters
- //
- params = new X962Parameters(ecP);
-
- info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), p.getOctets());
-
- if (!areEqual(info.getEncoded(), expPub))
- {
- fail("failed public explicit generation");
- }
-
- o = ASN1Primitive.fromByteArray(expPub);
-
- if (!info.equals(o))
- {
- fail("failed public explicit equality");
- }
- }
-
- private void encodePrivateKey()
- throws Exception
- {
- X9ECParameters ecP = X962NamedCurves.getByOID(X9ObjectIdentifiers.prime239v3);
-
- //
- // named curve
- //
- X962Parameters params = new X962Parameters(X9ObjectIdentifiers.prime192v1);
-
- PrivateKeyInfo info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), new ECPrivateKey(BigInteger.valueOf(10)));
-
- if (!areEqual(info.getEncoded(), namedPriv))
- {
- fail("failed private named generation");
- }
-
- ASN1Primitive o = ASN1Primitive.fromByteArray(namedPriv);
-
- if (!info.equals(o))
- {
- fail("failed private named equality");
- }
-
- //
- // explicit curve parameters
- //
- params = new X962Parameters(ecP);
-
- info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), new ECPrivateKey(BigInteger.valueOf(20)));
-
- if (!areEqual(info.getEncoded(), expPriv))
- {
- fail("failed private explicit generation");
- }
-
- o = ASN1Primitive.fromByteArray(expPriv);
-
- if (!info.equals(o))
- {
- fail("failed private explicit equality");
- }
- }
-
- public void performTest()
- throws Exception
- {
- encodePublicKey();
- encodePrivateKey();
- }
-
- public String getName()
- {
- return "X9";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new X9Test());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/agreement/test/AllTests.java b/core/src/test/java/org/bouncycastle/crypto/agreement/test/AllTests.java
deleted file mode 100644
index cb5a862b..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/agreement/test/AllTests.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.crypto.agreement.test;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-public class AllTests
- extends TestCase
-{
- public static void main(String[] args)
- {
- junit.textui.TestRunner.run(suite());
- }
-
- public static Test suite()
- {
- TestSuite suite = new TestSuite("JPKAE Engine Tests");
-
- suite.addTestSuite(JPAKEParticipantTest.class);
- suite.addTestSuite(JPAKEPrimeOrderGroupTest.class);
- suite.addTestSuite(JPAKEUtilTest.class);
-
- return suite;
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/agreement/test/JPAKEParticipantTest.java b/core/src/test/java/org/bouncycastle/crypto/agreement/test/JPAKEParticipantTest.java
deleted file mode 100644
index c6ecba22..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/agreement/test/JPAKEParticipantTest.java
+++ /dev/null
@@ -1,561 +0,0 @@
-package org.bouncycastle.crypto.agreement.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import junit.framework.TestCase;
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.agreement.jpake.JPAKEParticipant;
-import org.bouncycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroup;
-import org.bouncycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroups;
-import org.bouncycastle.crypto.agreement.jpake.JPAKERound1Payload;
-import org.bouncycastle.crypto.agreement.jpake.JPAKERound2Payload;
-import org.bouncycastle.crypto.agreement.jpake.JPAKERound3Payload;
-import org.bouncycastle.crypto.agreement.jpake.JPAKEUtil;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-
-public class JPAKEParticipantTest
- extends TestCase
-{
-
- public void testConstruction()
- throws CryptoException
- {
- JPAKEPrimeOrderGroup group = JPAKEPrimeOrderGroups.SUN_JCE_1024;
- SecureRandom random = new SecureRandom();
- Digest digest = new SHA256Digest();
- String participantId = "participantId";
- char[] password = "password".toCharArray();
-
- // should succeed
- new JPAKEParticipant(participantId, password, group, digest, random);
-
- // null participantId
- try
- {
- new JPAKEParticipant(null, password, group, digest, random);
- fail();
- }
- catch (NullPointerException e)
- {
- // pass
- }
-
- // null password
- try
- {
- new JPAKEParticipant(participantId, null, group, digest, random);
- fail();
- }
- catch (NullPointerException e)
- {
- // pass
- }
-
- // empty password
- try
- {
- new JPAKEParticipant(participantId, "".toCharArray(), group, digest, random);
- fail();
- }
- catch (IllegalArgumentException e)
- {
- // pass
- }
-
- // null group
- try
- {
- new JPAKEParticipant(participantId, password, null, digest, random);
- fail();
- }
- catch (NullPointerException e)
- {
- // pass
- }
-
- // null digest
- try
- {
- new JPAKEParticipant(participantId, password, group, null, random);
- fail();
- }
- catch (NullPointerException e)
- {
- // pass
- }
-
- // null random
- try
- {
- new JPAKEParticipant(participantId, password, group, digest, null);
- fail();
- }
- catch (NullPointerException e)
- {
- // pass
- }
- }
-
- public void testSuccessfulExchange()
- throws CryptoException
- {
-
- JPAKEParticipant alice = createAlice();
- JPAKEParticipant bob = createBob();
-
- ExchangeAfterRound2Creation exchange = runExchangeUntilRound2Creation(alice, bob);
-
- alice.validateRound2PayloadReceived(exchange.bobRound2Payload);
- bob.validateRound2PayloadReceived(exchange.aliceRound2Payload);
-
- BigInteger aliceKeyingMaterial = alice.calculateKeyingMaterial();
- BigInteger bobKeyingMaterial = bob.calculateKeyingMaterial();
-
- JPAKERound3Payload aliceRound3Payload = alice.createRound3PayloadToSend(aliceKeyingMaterial);
- JPAKERound3Payload bobRound3Payload = bob.createRound3PayloadToSend(bobKeyingMaterial);
-
- alice.validateRound3PayloadReceived(bobRound3Payload, aliceKeyingMaterial);
- bob.validateRound3PayloadReceived(aliceRound3Payload, bobKeyingMaterial);
-
- assertEquals(aliceKeyingMaterial, bobKeyingMaterial);
-
- }
-
- public void testIncorrectPassword()
- throws CryptoException
- {
-
- JPAKEParticipant alice = createAlice();
- JPAKEParticipant bob = createBobWithWrongPassword();
-
- ExchangeAfterRound2Creation exchange = runExchangeUntilRound2Creation(alice, bob);
-
- alice.validateRound2PayloadReceived(exchange.bobRound2Payload);
- bob.validateRound2PayloadReceived(exchange.aliceRound2Payload);
-
- BigInteger aliceKeyingMaterial = alice.calculateKeyingMaterial();
- BigInteger bobKeyingMaterial = bob.calculateKeyingMaterial();
-
- JPAKERound3Payload aliceRound3Payload = alice.createRound3PayloadToSend(aliceKeyingMaterial);
- JPAKERound3Payload bobRound3Payload = bob.createRound3PayloadToSend(bobKeyingMaterial);
-
- try
- {
- alice.validateRound3PayloadReceived(bobRound3Payload, aliceKeyingMaterial);
- fail();
- }
- catch (CryptoException e)
- {
- // pass
- }
-
- try
- {
- bob.validateRound3PayloadReceived(aliceRound3Payload, bobKeyingMaterial);
- fail();
- }
- catch (CryptoException e)
- {
- // pass
- }
-
- }
-
- /**
- * Tests that {@link JPAKEParticipant} throws appropriate {@link IllegalStateException}s
- * when the methods are called in the wrong order.
- */
- public void testStateValidation()
- throws CryptoException
- {
-
- JPAKEParticipant alice = createAlice();
- JPAKEParticipant bob = createBob();
-
- // We're testing alice here. Bob is just used for help.
-
- // START ROUND 1 CHECKS
-
- assertEquals(JPAKEParticipant.STATE_INITIALIZED, alice.getState());
-
- // create round 2 before round 1
- try
- {
- alice.createRound2PayloadToSend();
- fail();
- }
- catch (IllegalStateException e)
- {
- // pass
- }
-
- JPAKERound1Payload aliceRound1Payload = alice.createRound1PayloadToSend();
-
- assertEquals(JPAKEParticipant.STATE_ROUND_1_CREATED, alice.getState());
-
- // create round 1 payload twice
- try
- {
- alice.createRound1PayloadToSend();
- fail();
- }
- catch (IllegalStateException e)
- {
- // pass
- }
-
- // create round 2 before validating round 1
- try
- {
- alice.createRound2PayloadToSend();
- fail();
- }
- catch (IllegalStateException e)
- {
- // pass
- }
-
- // validate round 2 before validating round 1
- try
- {
- alice.validateRound2PayloadReceived(null);
- fail();
- }
- catch (IllegalStateException e)
- {
- // pass
- }
-
- JPAKERound1Payload bobRound1Payload = bob.createRound1PayloadToSend();
-
- alice.validateRound1PayloadReceived(bobRound1Payload);
-
- assertEquals(JPAKEParticipant.STATE_ROUND_1_VALIDATED, alice.getState());
-
- // validate round 1 payload twice
- try
- {
- alice.validateRound1PayloadReceived(bobRound1Payload);
- fail();
- }
- catch (IllegalStateException e)
- {
- // pass
- }
-
- bob.validateRound1PayloadReceived(aliceRound1Payload);
-
- // START ROUND 2 CHECKS
-
- JPAKERound2Payload aliceRound2Payload = alice.createRound2PayloadToSend();
-
- assertEquals(JPAKEParticipant.STATE_ROUND_2_CREATED, alice.getState());
-
- // create round 2 payload twice
- try
- {
- alice.createRound2PayloadToSend();
- fail();
- }
- catch (IllegalStateException e)
- {
- // pass
- }
-
- // create key before validating round 2
- try
- {
- alice.calculateKeyingMaterial();
- fail();
- }
- catch (IllegalStateException e)
- {
- // pass
- }
-
- // validate round 3 before validating round 2
- try
- {
- alice.validateRound3PayloadReceived(null, null);
- fail();
- }
- catch (IllegalStateException e)
- {
- // pass
- }
-
- JPAKERound2Payload bobRound2Payload = bob.createRound2PayloadToSend();
-
- alice.validateRound2PayloadReceived(bobRound2Payload);
-
- assertEquals(JPAKEParticipant.STATE_ROUND_2_VALIDATED, alice.getState());
-
- // validate round 2 payload twice
- try
- {
- alice.validateRound2PayloadReceived(bobRound2Payload);
- fail();
- }
- catch (IllegalStateException e)
- {
- // pass
- }
-
- bob.validateRound2PayloadReceived(aliceRound2Payload);
-
- // create round 3 before calculating key
- try
- {
- alice.createRound3PayloadToSend(BigInteger.ONE);
- fail();
- }
- catch (IllegalStateException e)
- {
- // pass
- }
-
- // START KEY CALCULATION CHECKS
-
- BigInteger aliceKeyingMaterial = alice.calculateKeyingMaterial();
-
- assertEquals(JPAKEParticipant.STATE_KEY_CALCULATED, alice.getState());
-
- // calculate key twice
- try
- {
- alice.calculateKeyingMaterial();
- fail();
- }
- catch (IllegalStateException e)
- {
- // pass
- }
-
- BigInteger bobKeyingMaterial = bob.calculateKeyingMaterial();
-
- // START ROUND 3 CHECKS
-
- JPAKERound3Payload aliceRound3Payload = alice.createRound3PayloadToSend(aliceKeyingMaterial);
-
- assertEquals(JPAKEParticipant.STATE_ROUND_3_CREATED, alice.getState());
-
- // create round 3 payload twice
- try
- {
- alice.createRound3PayloadToSend(aliceKeyingMaterial);
- fail();
- }
- catch (IllegalStateException e)
- {
- // pass
- }
-
- JPAKERound3Payload bobRound3Payload = bob.createRound3PayloadToSend(bobKeyingMaterial);
-
- alice.validateRound3PayloadReceived(bobRound3Payload, aliceKeyingMaterial);
-
- assertEquals(JPAKEParticipant.STATE_ROUND_3_VALIDATED, alice.getState());
-
- // validate round 3 payload twice
- try
- {
- alice.validateRound3PayloadReceived(bobRound3Payload, aliceKeyingMaterial);
- fail();
- }
- catch (IllegalStateException e)
- {
- // pass
- }
-
- bob.validateRound3PayloadReceived(aliceRound3Payload, bobKeyingMaterial);
-
-
- }
-
- /**
- * Tests that {@link JPAKEParticipant#validateRound1PayloadReceived(JPAKERound1Payload)}
- * calls the appropriate validate methods in {@link JPAKEUtil}.
- * Note that {@link JPAKEUtilTest} tests the individual validate methods
- * called by {@link JPAKEParticipant} more extensively.
- */
- public void testValidateRound1PayloadReceived()
- throws CryptoException
- {
-
- // We're testing alice here. Bob is just used for help.
-
- JPAKERound1Payload bobRound1Payload = createBob().createRound1PayloadToSend();
-
- // should succeed
- createAlice().validateRound1PayloadReceived(bobRound1Payload);
-
- // alice verifies alice's payload
- try
- {
- JPAKEParticipant alice = createAlice();
- alice.validateRound1PayloadReceived(alice.createRound1PayloadToSend());
- fail();
- }
- catch (CryptoException e)
- {
- // pass
- }
-
- // g^x4 == 1
- try
- {
- createAlice().validateRound1PayloadReceived(new JPAKERound1Payload(
- bobRound1Payload.getParticipantId(),
- bobRound1Payload.getGx1(),
- BigInteger.ONE,
- bobRound1Payload.getKnowledgeProofForX1(),
- bobRound1Payload.getKnowledgeProofForX2()));
- fail();
- }
- catch (CryptoException e)
- {
- // pass
- }
-
- // zero knowledge proof for x3 fails
- try
- {
- JPAKERound1Payload bobRound1Payload2 = createBob().createRound1PayloadToSend();
- createAlice().validateRound1PayloadReceived(new JPAKERound1Payload(
- bobRound1Payload.getParticipantId(),
- bobRound1Payload.getGx1(),
- bobRound1Payload.getGx2(),
- bobRound1Payload2.getKnowledgeProofForX1(),
- bobRound1Payload.getKnowledgeProofForX2()));
- fail();
- }
- catch (CryptoException e)
- {
- // pass
- }
-
- // zero knowledge proof for x4 fails
- try
- {
- JPAKERound1Payload bobRound1Payload2 = createBob().createRound1PayloadToSend();
- createAlice().validateRound1PayloadReceived(new JPAKERound1Payload(
- bobRound1Payload.getParticipantId(),
- bobRound1Payload.getGx1(),
- bobRound1Payload.getGx2(),
- bobRound1Payload.getKnowledgeProofForX1(),
- bobRound1Payload2.getKnowledgeProofForX2()));
- fail();
- }
- catch (CryptoException e)
- {
- // pass
- }
-
- }
-
- /**
- * Tests that {@link JPAKEParticipant#validateRound2PayloadReceived(JPAKERound2Payload)}
- * calls the appropriate validate methods in {@link JPAKEUtil}.
- * Note that {@link JPAKEUtilTest} tests the individual validate methods
- * called by {@link JPAKEParticipant} more extensively.
- */
- public void testValidateRound2PayloadReceived()
- throws CryptoException
- {
-
- // We're testing alice here. Bob is just used for help.
-
- // should succeed
- ExchangeAfterRound2Creation exchange1 = runExchangeUntilRound2Creation(createAlice(), createBob());
- exchange1.alice.validateRound2PayloadReceived(exchange1.bobRound2Payload);
-
- // alice verifies alice's payload
- ExchangeAfterRound2Creation exchange2 = runExchangeUntilRound2Creation(createAlice(), createBob());
- try
- {
- exchange2.alice.validateRound2PayloadReceived(exchange2.aliceRound2Payload);
- fail();
- }
- catch (CryptoException e)
- {
- // pass
- }
-
- // wrong z
- ExchangeAfterRound2Creation exchange3 = runExchangeUntilRound2Creation(createAlice(), createBob());
- ExchangeAfterRound2Creation exchange4 = runExchangeUntilRound2Creation(createAlice(), createBob());
- try
- {
- exchange3.alice.validateRound2PayloadReceived(exchange4.bobRound2Payload);
- fail();
- }
- catch (CryptoException e)
- {
- // pass
- }
-
- }
-
- private static class ExchangeAfterRound2Creation
- {
-
- public JPAKEParticipant alice;
- public JPAKERound2Payload aliceRound2Payload;
- public JPAKERound2Payload bobRound2Payload;
-
- public ExchangeAfterRound2Creation(
- JPAKEParticipant alice,
- JPAKERound2Payload aliceRound2Payload,
- JPAKERound2Payload bobRound2Payload)
- {
- this.alice = alice;
- this.aliceRound2Payload = aliceRound2Payload;
- this.bobRound2Payload = bobRound2Payload;
- }
-
- }
-
- private ExchangeAfterRound2Creation runExchangeUntilRound2Creation(JPAKEParticipant alice, JPAKEParticipant bob)
- throws CryptoException
- {
- JPAKERound1Payload aliceRound1Payload = alice.createRound1PayloadToSend();
- JPAKERound1Payload bobRound1Payload = bob.createRound1PayloadToSend();
-
- alice.validateRound1PayloadReceived(bobRound1Payload);
- bob.validateRound1PayloadReceived(aliceRound1Payload);
-
- JPAKERound2Payload aliceRound2Payload = alice.createRound2PayloadToSend();
- JPAKERound2Payload bobRound2Payload = bob.createRound2PayloadToSend();
-
- return new ExchangeAfterRound2Creation(
- alice,
- aliceRound2Payload,
- bobRound2Payload);
- }
-
- private JPAKEParticipant createAlice()
- {
- return createParticipant("alice", "password");
- }
-
- private JPAKEParticipant createBob()
- {
- return createParticipant("bob", "password");
- }
-
- private JPAKEParticipant createBobWithWrongPassword()
- {
- return createParticipant("bob", "wrong");
- }
-
- private JPAKEParticipant createParticipant(String participantId, String password)
- {
- return new JPAKEParticipant(
- participantId,
- password.toCharArray(),
- JPAKEPrimeOrderGroups.SUN_JCE_1024);
- }
-
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/agreement/test/JPAKEPrimeOrderGroupTest.java b/core/src/test/java/org/bouncycastle/crypto/agreement/test/JPAKEPrimeOrderGroupTest.java
deleted file mode 100644
index 7d22f16a..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/agreement/test/JPAKEPrimeOrderGroupTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package org.bouncycastle.crypto.agreement.test;
-
-import java.math.BigInteger;
-
-import junit.framework.TestCase;
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroup;
-
-public class JPAKEPrimeOrderGroupTest
- extends TestCase
-{
-
- public void testConstruction()
- throws CryptoException
- {
- // p-1 not evenly divisible by q
- try
- {
- new JPAKEPrimeOrderGroup(BigInteger.valueOf(7), BigInteger.valueOf(5), BigInteger.valueOf(6));
- fail();
- }
- catch (IllegalArgumentException e)
- {
- // pass
- }
-
- // g < 2
- try
- {
- new JPAKEPrimeOrderGroup(BigInteger.valueOf(11), BigInteger.valueOf(5), BigInteger.valueOf(1));
- fail();
- }
- catch (IllegalArgumentException e)
- {
- // pass
- }
-
- // g > p-1
- try
- {
- new JPAKEPrimeOrderGroup(BigInteger.valueOf(11), BigInteger.valueOf(5), BigInteger.valueOf(11));
- fail();
- }
- catch (IllegalArgumentException e)
- {
- // pass
- }
-
- // g^q mod p not equal 1
- try
- {
- new JPAKEPrimeOrderGroup(BigInteger.valueOf(11), BigInteger.valueOf(5), BigInteger.valueOf(6));
- fail();
- }
- catch (IllegalArgumentException e)
- {
- // pass
- }
-
- // p not prime
- try
- {
- new JPAKEPrimeOrderGroup(BigInteger.valueOf(15), BigInteger.valueOf(2), BigInteger.valueOf(4));
- fail();
- }
- catch (IllegalArgumentException e)
- {
- // pass
- }
-
- // q not prime
- try
- {
- new JPAKEPrimeOrderGroup(BigInteger.valueOf(7), BigInteger.valueOf(6), BigInteger.valueOf(3));
- fail();
- }
- catch (IllegalArgumentException e)
- {
- // pass
- }
-
- // should succeed
- new JPAKEPrimeOrderGroup(BigInteger.valueOf(7), BigInteger.valueOf(3), BigInteger.valueOf(4));
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/agreement/test/JPAKEUtilTest.java b/core/src/test/java/org/bouncycastle/crypto/agreement/test/JPAKEUtilTest.java
deleted file mode 100644
index 20268b8d..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/agreement/test/JPAKEUtilTest.java
+++ /dev/null
@@ -1,267 +0,0 @@
-package org.bouncycastle.crypto.agreement.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import junit.framework.TestCase;
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroup;
-import org.bouncycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroups;
-import org.bouncycastle.crypto.agreement.jpake.JPAKEUtil;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-
-public class JPAKEUtilTest
- extends TestCase
-{
- private static final BigInteger TEN = BigInteger.valueOf(10);
-
- public void testValidateGx4()
- throws CryptoException
- {
- JPAKEUtil.validateGx4(TEN);
-
- try
- {
- JPAKEUtil.validateGx4(BigInteger.ONE);
- fail();
- }
- catch (CryptoException e)
- {
- // pass
- }
- }
-
- public void testValidateGa()
- throws CryptoException
- {
- JPAKEUtil.validateGa(TEN);
-
- try
- {
- JPAKEUtil.validateGa(BigInteger.ONE);
- fail();
- }
- catch (CryptoException e)
- {
- // pass
- }
- }
-
- public void testValidateParticipantIdsDiffer()
- throws CryptoException
- {
- JPAKEUtil.validateParticipantIdsDiffer("a", "b");
- JPAKEUtil.validateParticipantIdsDiffer("a", "A");
-
- try
- {
- JPAKEUtil.validateParticipantIdsDiffer("a", "a");
- fail();
- }
- catch (CryptoException e)
- {
- // pass
- }
- }
-
- public void testValidateParticipantIdsEqual()
- throws CryptoException
- {
- JPAKEUtil.validateParticipantIdsEqual("a", "a");
-
- try
- {
- JPAKEUtil.validateParticipantIdsEqual("a", "b");
- fail();
- }
- catch (CryptoException e)
- {
- // pass
- }
- }
-
- public void testValidateMacTag()
- throws CryptoException
- {
- JPAKEPrimeOrderGroup pg1 = JPAKEPrimeOrderGroups.SUN_JCE_1024;
-
- SecureRandom random = new SecureRandom();
- Digest digest = new SHA256Digest();
-
- BigInteger x1 = JPAKEUtil.generateX1(pg1.getQ(), random);
- BigInteger x2 = JPAKEUtil.generateX2(pg1.getQ(), random);
- BigInteger x3 = JPAKEUtil.generateX1(pg1.getQ(), random);
- BigInteger x4 = JPAKEUtil.generateX2(pg1.getQ(), random);
-
- BigInteger gx1 = JPAKEUtil.calculateGx(pg1.getP(), pg1.getG(), x1);
- BigInteger gx2 = JPAKEUtil.calculateGx(pg1.getP(), pg1.getG(), x2);
- BigInteger gx3 = JPAKEUtil.calculateGx(pg1.getP(), pg1.getG(), x3);
- BigInteger gx4 = JPAKEUtil.calculateGx(pg1.getP(), pg1.getG(), x4);
-
- BigInteger gB = JPAKEUtil.calculateGA(pg1.getP(), gx3, gx1, gx2);
-
- BigInteger s = JPAKEUtil.calculateS("password".toCharArray());
-
- BigInteger xs = JPAKEUtil.calculateX2s(pg1.getQ(), x4, s);
-
- BigInteger B = JPAKEUtil.calculateA(pg1.getP(), pg1.getQ(), gB, xs);
-
- BigInteger keyingMaterial = JPAKEUtil.calculateKeyingMaterial(pg1.getP(), pg1.getQ(), gx4, x2, s, B);
-
- BigInteger macTag = JPAKEUtil.calculateMacTag("participantId", "partnerParticipantId", gx1, gx2, gx3, gx4, keyingMaterial, digest);
-
- // should succed
- JPAKEUtil.validateMacTag("partnerParticipantId", "participantId", gx3, gx4, gx1, gx2, keyingMaterial, digest, macTag);
-
- // validating own macTag (as opposed to the other party's mactag)
- try
- {
- JPAKEUtil.validateMacTag("participantId", "partnerParticipantId", gx1, gx2, gx3, gx4, keyingMaterial, digest, macTag);
- fail();
- }
- catch (CryptoException e)
- {
- // pass
- }
-
- // participant ids switched
- try
- {
- JPAKEUtil.validateMacTag("participantId", "partnerParticipantId", gx3, gx4, gx1, gx2, keyingMaterial, digest, macTag);
- fail();
- }
- catch (CryptoException e)
- {
- // pass
- }
- }
-
- public void testValidateNotNull()
- {
- JPAKEUtil.validateNotNull("a", "description");
-
- try
- {
- JPAKEUtil.validateNotNull(null, "description");
- fail();
- }
- catch (NullPointerException e)
- {
- // pass
- }
- }
-
- public void testValidateZeroKnowledgeProof()
- throws CryptoException
- {
- JPAKEPrimeOrderGroup pg1 = JPAKEPrimeOrderGroups.SUN_JCE_1024;
-
- SecureRandom random = new SecureRandom();
- Digest digest1 = new SHA256Digest();
-
- BigInteger x1 = JPAKEUtil.generateX1(pg1.getQ(), random);
- BigInteger gx1 = JPAKEUtil.calculateGx(pg1.getP(), pg1.getG(), x1);
- String participantId1 = "participant1";
-
- BigInteger[] zkp1 = JPAKEUtil.calculateZeroKnowledgeProof(pg1.getP(), pg1.getQ(), pg1.getG(), gx1, x1, participantId1, digest1, random);
-
- // should succeed
- JPAKEUtil.validateZeroKnowledgeProof(pg1.getP(), pg1.getQ(), pg1.getG(), gx1, zkp1, participantId1, digest1);
-
- // wrong group
- JPAKEPrimeOrderGroup pg2 = JPAKEPrimeOrderGroups.NIST_3072;
- try
- {
- JPAKEUtil.validateZeroKnowledgeProof(pg2.getP(), pg2.getQ(), pg2.getG(), gx1, zkp1, participantId1, digest1);
- fail();
- }
- catch (CryptoException e)
- {
- // pass
- }
-
- // wrong digest
- Digest digest2 = new SHA1Digest();
- try
- {
- JPAKEUtil.validateZeroKnowledgeProof(pg1.getP(), pg1.getQ(), pg1.getG(), gx1, zkp1, participantId1, digest2);
- fail();
- }
- catch (CryptoException e)
- {
- // pass
- }
-
- // wrong participant
- String participantId2 = "participant2";
- try
- {
- JPAKEUtil.validateZeroKnowledgeProof(pg1.getP(), pg1.getQ(), pg1.getG(), gx1, zkp1, participantId2, digest1);
- fail();
- }
- catch (CryptoException e)
- {
- // pass
- }
-
- // wrong gx
- BigInteger x2 = JPAKEUtil.generateX1(pg1.getQ(), random);
- BigInteger gx2 = JPAKEUtil.calculateGx(pg1.getP(), pg1.getG(), x2);
- try
- {
- JPAKEUtil.validateZeroKnowledgeProof(pg1.getP(), pg1.getQ(), pg1.getG(), gx2, zkp1, participantId1, digest1);
- fail();
- }
- catch (CryptoException e)
- {
- // pass
- }
-
- // wrong zkp
- BigInteger[] zkp2 = JPAKEUtil.calculateZeroKnowledgeProof(pg1.getP(), pg1.getQ(), pg1.getG(), gx2, x2, participantId1, digest1, random);
- try
- {
- JPAKEUtil.validateZeroKnowledgeProof(pg1.getP(), pg1.getQ(), pg1.getG(), gx1, zkp2, participantId1, digest1);
- fail();
- }
- catch (CryptoException e)
- {
- // pass
- }
-
- // gx <= 0
- try
- {
- JPAKEUtil.validateZeroKnowledgeProof(pg1.getP(), pg1.getQ(), pg1.getG(), BigInteger.ZERO, zkp1, participantId1, digest1);
- fail();
- }
- catch (CryptoException e)
- {
- // pass
- }
-
- // gx >= p
- try
- {
- JPAKEUtil.validateZeroKnowledgeProof(pg1.getP(), pg1.getQ(), pg1.getG(), pg1.getP(), zkp1, participantId1, digest1);
- fail();
- }
- catch (CryptoException e)
- {
- // pass
- }
-
- // gx mod q == 1
- try
- {
- JPAKEUtil.validateZeroKnowledgeProof(pg1.getP(), pg1.getQ(), pg1.getG(), pg1.getQ().add(BigInteger.ONE), zkp1, participantId1, digest1);
- fail();
- }
- catch (CryptoException e)
- {
- // pass
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/ec/test/AllTests.java b/core/src/test/java/org/bouncycastle/crypto/ec/test/AllTests.java
deleted file mode 100644
index ba75c06b..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/ec/test/AllTests.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.bouncycastle.crypto.ec.test;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-import org.bouncycastle.util.test.SimpleTestResult;
-
-public class AllTests
- extends TestCase
-{
- public void testCrypto()
- {
- org.bouncycastle.util.test.Test[] tests = { new ECElGamalTest(), new ECTransformationTest() };
-
- for (int i = 0; i != tests.length; i++)
- {
- SimpleTestResult result = (SimpleTestResult)tests[i].perform();
-
- if (!result.isSuccessful())
- {
- fail(result.toString());
- }
- }
- }
-
- public static void main (String[] args)
- {
- junit.textui.TestRunner.run(suite());
- }
-
- public static Test suite()
- {
- TestSuite suite = new TestSuite("Lightweight EC ElGamal Tests");
-
- suite.addTestSuite(AllTests.class);
-
- return suite;
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/ec/test/ECElGamalTest.java b/core/src/test/java/org/bouncycastle/crypto/ec/test/ECElGamalTest.java
deleted file mode 100644
index 629c1a43..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/ec/test/ECElGamalTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package org.bouncycastle.crypto.ec.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.ec.ECDecryptor;
-import org.bouncycastle.crypto.ec.ECElGamalDecryptor;
-import org.bouncycastle.crypto.ec.ECElGamalEncryptor;
-import org.bouncycastle.crypto.ec.ECEncryptor;
-import org.bouncycastle.crypto.ec.ECPair;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class ECElGamalTest
- extends SimpleTest
-{
- public String getName()
- {
- return "ECElGamal";
- }
-
- public void performTest()
- throws Exception
- {
- BigInteger n = new BigInteger("6277101735386680763835789423176059013767194773182842284081");
-
- ECCurve.Fp curve = new ECCurve.Fp(
- new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q
- new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a
- new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16), // b
- n, ECConstants.ONE);
-
- ECDomainParameters params = new ECDomainParameters(
- curve,
- curve.decodePoint(Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), // G
- n);
-
- ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
- curve.decodePoint(Hex.decode("0262b12d60690cdcf330babab6e69763b471f994dd702d16a5")), // Q
- params);
-
- ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
- new BigInteger("651056770906015076056810763456358567190100156695615665659"), // d
- params);
-
- ParametersWithRandom pRandom = new ParametersWithRandom(pubKey, new SecureRandom());
-
- doTest(priKey, pRandom, BigInteger.valueOf(20));
-
- BigInteger rand = new BigInteger(pubKey.getParameters().getN().bitLength() - 1, new SecureRandom());
-
- doTest(priKey, pRandom, rand);
- }
-
- private void doTest(ECPrivateKeyParameters priKey, ParametersWithRandom pRandom, BigInteger value)
- {
- ECPoint data = priKey.getParameters().getG().multiply(value);
-
- ECEncryptor encryptor = new ECElGamalEncryptor();
-
- encryptor.init(pRandom);
-
- ECPair pair = encryptor.encrypt(data);
-
- ECDecryptor decryptor = new ECElGamalDecryptor();
-
- decryptor.init(priKey);
-
- ECPoint result = decryptor.decrypt(pair);
-
- if (!data.equals(result))
- {
- fail("point pair failed to decrypt back to original");
- }
- }
-
- public static void main(String[] args)
- {
- runTest(new ECElGamalTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/ec/test/ECTransformationTest.java b/core/src/test/java/org/bouncycastle/crypto/ec/test/ECTransformationTest.java
deleted file mode 100644
index 96ada144..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/ec/test/ECTransformationTest.java
+++ /dev/null
@@ -1,149 +0,0 @@
-package org.bouncycastle.crypto.ec.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.ec.ECDecryptor;
-import org.bouncycastle.crypto.ec.ECElGamalDecryptor;
-import org.bouncycastle.crypto.ec.ECElGamalEncryptor;
-import org.bouncycastle.crypto.ec.ECEncryptor;
-import org.bouncycastle.crypto.ec.ECNewPublicKeyTransform;
-import org.bouncycastle.crypto.ec.ECNewRandomnessTransform;
-import org.bouncycastle.crypto.ec.ECPair;
-import org.bouncycastle.crypto.ec.ECPairTransform;
-import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class ECTransformationTest
- extends SimpleTest
-{
- public String getName()
- {
- return "ECTransformationTest";
- }
-
- public void performTest()
- throws Exception
- {
- BigInteger n = new BigInteger("6277101735386680763835789423176059013767194773182842284081");
-
- ECCurve.Fp curve = new ECCurve.Fp(
- new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q
- new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a
- new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16), // b
- n, ECConstants.ONE);
-
- ECDomainParameters params = new ECDomainParameters(
- curve,
- curve.decodePoint(Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), // G
- n);
-
- ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
- curve.decodePoint(Hex.decode("0262b12d60690cdcf330babab6e69763b471f994dd702d16a5")), // Q
- params);
-
- ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
- new BigInteger("651056770906015076056810763456358567190100156695615665659"), // d
- params);
-
-
- ParametersWithRandom pRandom = new ParametersWithRandom(pubKey, new SecureRandom());
-
- doTest(priKey, pRandom, BigInteger.valueOf(20));
-
- BigInteger rand = new BigInteger(pubKey.getParameters().getN().bitLength() - 1, new SecureRandom());
-
- doTest(priKey, pRandom, rand);
- doSameKeyTest(priKey, pRandom, rand);
- }
-
- private void doTest(ECPrivateKeyParameters priKey, ParametersWithRandom pRandom, BigInteger value)
- {
- ECPoint data = priKey.getParameters().getG().multiply(value);
-
- ECEncryptor encryptor = new ECElGamalEncryptor();
-
- encryptor.init(pRandom);
-
- ECPair pair = encryptor.encrypt(data);
-
- ECKeyPairGenerator ecGen = new ECKeyPairGenerator();
-
- ecGen.init(new ECKeyGenerationParameters(priKey.getParameters(), new SecureRandom()));
-
- AsymmetricCipherKeyPair reEncKP = ecGen.generateKeyPair();
-
- ECPairTransform ecr = new ECNewPublicKeyTransform();
-
- ecr.init(reEncKP.getPublic());
-
- ECPair srcPair = pair;
-
- // re-encrypt the message portion
- pair = ecr.transform(srcPair);
-
- ECDecryptor decryptor = new ECElGamalDecryptor();
-
- decryptor.init(priKey);
-
- // decrypt out the original private key
- ECPoint p = decryptor.decrypt(new ECPair(srcPair.getX(), pair.getY()));
-
- decryptor.init(reEncKP.getPrivate());
-
- // decrypt the fully transformed point.
- ECPoint result = decryptor.decrypt(new ECPair(pair.getX(), p));
-
- if (!data.equals(result))
- {
- fail("point pair failed to decrypt back to original");
- }
- }
-
- private void doSameKeyTest(ECPrivateKeyParameters priKey, ParametersWithRandom pRandom, BigInteger value)
- {
- ECPoint data = priKey.getParameters().getG().multiply(value);
-
- ECEncryptor encryptor = new ECElGamalEncryptor();
-
- encryptor.init(pRandom);
-
- ECPair pair = encryptor.encrypt(data);
-
- ECPairTransform ecr = new ECNewRandomnessTransform();
-
- ecr.init(pRandom);
-
- ECPair srcPair = pair;
-
- // re-encrypt the message portion
- pair = ecr.transform(srcPair);
-
- ECDecryptor decryptor = new ECElGamalDecryptor();
-
- decryptor.init(priKey);
-
- // decrypt the fully transformed point.
- ECPoint result = decryptor.decrypt(pair);
-
- if (!data.equals(result))
- {
- fail("point pair failed to decrypt back to original");
- }
- }
-
- public static void main(String[] args)
- {
- runTest(new ECTransformationTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/prng/test/AllTests.java b/core/src/test/java/org/bouncycastle/crypto/prng/test/AllTests.java
deleted file mode 100644
index 4c0504f8..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/prng/test/AllTests.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.bouncycastle.crypto.prng.test;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-import org.bouncycastle.util.test.SimpleTestResult;
-
-public class AllTests
- extends TestCase
-{
- public void testCrypto()
- {
- org.bouncycastle.util.test.Test[] tests = RegressionTest.tests;
-
- for (int i = 0; i != tests.length; i++)
- {
- SimpleTestResult result = (SimpleTestResult)tests[i].perform();
-
- if (!result.isSuccessful())
- {
- fail(result.toString());
- }
- }
- }
-
- public static void main (String[] args)
- {
- junit.textui.TestRunner.run(suite());
- }
-
- public static Test suite()
- {
- TestSuite suite = new TestSuite("Lightweight Crypto PRNG Tests");
-
- suite.addTestSuite(AllTests.class);
-
- return suite;
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/prng/test/CTRDRBGTest.java b/core/src/test/java/org/bouncycastle/crypto/prng/test/CTRDRBGTest.java
deleted file mode 100644
index ca555c18..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/prng/test/CTRDRBGTest.java
+++ /dev/null
@@ -1,513 +0,0 @@
-package org.bouncycastle.crypto.prng.test;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.engines.AESEngine;
-import org.bouncycastle.crypto.engines.AESFastEngine;
-import org.bouncycastle.crypto.engines.DESedeEngine;
-import org.bouncycastle.crypto.params.DESedeParameters;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.prng.drbg.CTRSP800DRBG;
-import org.bouncycastle.crypto.prng.drbg.SP80090DRBG;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * CTR DRBG Test
- */
-public class CTRDRBGTest
- extends SimpleTest
-{
- public String getName()
- {
- return "CTRDRBGTest";
- }
-
- public static void main(String[] args)
- {
- runTest(new CTRDRBGTest());
- }
-
- private DRBGTestVector[] createTestVectorData()
- {
- return new DRBGTestVector[]
- {
- new DRBGTestVector(
- new DESedeEngine(), 168,
- new Bit232EntropyProvider().get(232),
- false,
- "20212223242526",
- 112,
- new String[]
- {
- "ABC88224514D0316EA3D48AEE3C9A2B4",
- "D3D3F372E43E7ABDC4FA293743EED076"
- }
- ),
- new DRBGTestVector(
- new DESedeEngine(), 168,
- new Bit232EntropyProvider().get(232),
- false,
- "20212223242526",
- 112,
- new String[]
- {
- "D4564EE072ACA5BD279536E14F94CB12",
- "1CCD9AFEF15A9679BA75E35225585DEA"
- }
- )
- .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C")
- .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBC"),
- new DRBGTestVector(
- new DESedeEngine(), 168,
- new Bit232EntropyProvider().get(232),
- false,
- "20212223242526",
- 112,
- new String[]
- {
- "760BED7D92B083B10AF31CF0656081EB",
- "FD1AC41482384D823CF3FD6F0E6C88B3"
- }
- )
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C"),
- new DRBGTestVector(
- new DESedeEngine(), 168,
- new Bit232EntropyProvider().get(232),
- false,
- "20212223242526",
- 112,
- new String[]
- {
- "7A4C1D7ADC8A67FDB50100ED23583A2C",
- "43044D311C0E07541CA5C8B0916976B2"
- }
- )
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C")
- .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C")
- .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBC"),
- new DRBGTestVector(
- new DESedeEngine(), 168,
- new Bit232EntropyProvider().get(232),
- true,
- "20212223242526",
- 112,
- new String[]
- {
- "8FB78ABCA75C9F284E974E36141866BC",
- "9D9745FF31C42A4488CBB771B13B5D86"
- }
- ),
- new DRBGTestVector(
- new DESedeEngine(), 168,
- new Bit232EntropyProvider().get(232),
- true,
- "20212223242526",
- 112,
- new String[]
- {
- "0E389920A09B485AA4ABD0CA7E60D89C",
- "F4478EC6659A0D3577625B0C73A211DD"
- }
- )
- .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C")
- .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBC"),
- new DRBGTestVector(
- new DESedeEngine(), 168,
- new Bit232EntropyProvider().get(232),
- true,
- "20212223242526",
- 112,
- new String[]
- {
- "64983055D014550B39DE699E43130B64",
- "035FDDA8582A2214EC722C410A8D95D3"
- }
- )
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C"),
- new DRBGTestVector(
- new DESedeEngine(), 168,
- new Bit232EntropyProvider().get(232),
- true,
- "20212223242526",
- 112,
- new String[]
- {
- "A29C1A8C42FBC562D7D1DBA7DC541FFE",
- "0BDA66B049429061C013E4228C2F44C6"
- }
- )
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C")
- .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C")
- .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBC"),
- new DRBGTestVector(
- new AESFastEngine(), 128,
- new Bit256EntropyProvider().get(256),
- false,
- "2021222324252627",
- 128,
- new String[]
- {
- "8CF59C8CF6888B96EB1C1E3E79D82387AF08A9E5FF75E23F1FBCD4559B6B997E",
- "69CDEF912C692D61B1DA4C05146B52EB7B8849BD87937835328254EC25A9180E"
- }
- ),
- new DRBGTestVector(
- new AESFastEngine(), 128,
- new Bit256EntropyProvider().get(256),
- false,
- "2021222324252627",
- 128,
- new String[]
- {
- "E8C74A4B7BFFB53BEB80E78CA86BB6DF70E2032AEB473E0DD54D2339CEFCE9D0",
- "26B3F823B4DBAFC23B141375E10B3AEB7A0B5DEF1C7D760B6F827D01ECD17AC7"
- }
- )
- .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F")
- .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"),
- new DRBGTestVector(
- new AESFastEngine(), 128,
- new Bit256EntropyProvider().get(256),
- false,
- "2021222324252627",
- 128,
- new String[]
- {
- "18FDEFBDC43D7A36D5D6D862205765D1D701C9F237007030DF1B8E70EE4EEE29",
- "9888F1D38BB1CCE31B363AA1BD9B39616876C30DEE1FF0B7BD8C4C441715C833"
- }
- )
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F"),
- new DRBGTestVector(
- new AESFastEngine(), 128,
- new Bit256EntropyProvider().get(256),
- true,
- "2021222324252627",
- 128,
- new String[]
- {
- "BFF4B85D68C84529F24F69F9ACF1756E29BA648DDEB825C225FA32BA490EF4A9",
- "9BD2635137A52AF7D0FCBEFEFB97EA93A0F4C438BD98956C0DACB04F15EE25B3"
- }
- ),
- new DRBGTestVector(
- new AESFastEngine(), 128,
- new Bit256EntropyProvider().get(256),
- true,
- "2021222324252627",
- 128,
- new String[]
- {
- "4573AC8BBB33D7CC4DBEF3EEDF6EAE748B536C3A1082CEE4948CDB51C83A7F9C",
- "99C628CDD87BD8C2F1FE443AA7F761DA16886436326323354DA6311FFF5BC678"
- }
- )
- .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F")
- .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"),
- new DRBGTestVector(
- new AESFastEngine(), 128,
- new Bit256EntropyProvider().get(256),
- true,
- "2021222324252627",
- 128,
- new String[]
- {
- "F324104E2FA14F79D8AA60DF06B93B3BC157324958F0A7EE1E193677A70E0250",
- "78F4C840134F40DC001BFAD3A90B5EF4DEBDBFAC3CFDF0CD69A89DC4FD34713F"
- }
- )
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F"),
- new DRBGTestVector(
- new AESFastEngine(), 192,
- new Bit320EntropyProvider().get(320),
- false,
- "202122232425262728292A2B",
- 192,
- new String[]
- {
- "E231244B3235B085C81604424357E85201E3828B5C45568679A5555F867AAC8C",
- "DDD0F7BCCADADAA31A67652259CE569A271DD85CF66C3D6A7E9FAED61F38D219"
- }
- )
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F6061626364656667"),
- new DRBGTestVector(
- new AESFastEngine(), 192,
- new Bit320EntropyProvider().get(320),
- true,
- "202122232425262728292A2B",
- 192,
- new String[]
- {
- "F780D4A2C25CF8EE7407D948EC0B724A4235D8B20E65081392755CA7912AD7C0",
- "BA14617F915BA964CB79276BDADC840C14B631BBD1A59097054FA6DFF863B238"
- }
- )
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F6061626364656667"),
- new DRBGTestVector(
- new AESFastEngine(), 256,
- new Bit384EntropyProvider().get(384),
- false,
- "202122232425262728292A2B2C2D2E2F",
- 256,
- new String[]
- {
- "47111E146562E9AA2FB2A1B095D37A8165AF8FC7CA611D632BE7D4C145C83900",
- "98A28E3B1BA363C9DAF0F6887A1CF52B833D3354D77A7C10837DD63DD2E645F8"
- }
- )
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F")
- .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F")
- .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"),
- new DRBGTestVector(
- new AESFastEngine(), 256,
- new Bit384EntropyProvider().get(384),
- true,
- "202122232425262728292A2B2C2D2E2F",
- 256,
- new String[]
- {
- "71BB3F9C9CEAF4E6C92A83EB4C7225010EE150AC75E23F5F77AD5073EF24D88A",
- "386DEBBBF091BBF0502957B0329938FB836B82E594A2F5FDD5EB28D4E35528F4"
- }
- )
- .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F")
- .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"),
- new DRBGTestVector(
- new AESFastEngine(), 256,
- new Bit384EntropyProvider().get(384),
- true,
- "202122232425262728292A2B2C2D2E2F",
- 256,
- new String[]
- {
- "1A2E3FEE9056E98D375525FDC2B63B95B47CE51FCF594D804BD5A17F2E01139B",
- "601F95384F0D85946301D1EACE8F645A825CE38F1E2565B0C0C439448E9CA8AC"
- }
- )
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F"),
- new DRBGTestVector(
- new AESFastEngine(), 256,
- new Bit384EntropyProvider().get(384),
- true,
- "202122232425262728292A2B2C2D2E2F",
- 256,
- new String[]
- {
- "EAE6BCE781807E524D26605EA198077932D01EEB445B9AC6C5D99C101D29F46E",
- "738E99C95AF59519AAD37FF3D5180986ADEBAB6E95836725097E50A8D1D0BD28"
- }
- )
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F")
- .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F")
- .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF")
- };
- }
-
- public void performTest()
- throws Exception
- {
- DRBGTestVector[] tests = createTestVectorData();
-
- for (int i = 0; i != tests.length; i++)
- {
- DRBGTestVector tv = tests[i];
-
- byte[] nonce = tv.nonce();
- byte[] personalisationString = tv.personalizationString();
-
- SP80090DRBG d = new CTRSP800DRBG(tv.getCipher(), tv.keySizeInBits(), tv.securityStrength(), tv.entropySource(), personalisationString, nonce);
-
- byte[] output = new byte[tv.expectedValue(0).length];
-
- d.generate(output, tv.additionalInput(0), tv.predictionResistance());
-
- byte[] expected = tv.expectedValue(0);
-
- if (!areEqual(expected, output))
- {
- fail("Test #" + (i + 1) + ".1 failed, expected " + new String(Hex.encode(tv.expectedValue(0))) + " got " + new String(Hex.encode(output)));
- }
-
- output = new byte[tv.expectedValue(0).length];
-
- d.generate(output, tv.additionalInput(1), tv.predictionResistance());
-
- expected = tv.expectedValue(1);
- if (!areEqual(expected, output))
- {
- fail("Test #" + (i + 1) + ".2 failed, expected " + new String(Hex.encode(tv.expectedValue(1))) + " got " + new String(Hex.encode(output)));
- }
- }
-
- // DESede/TDEA key parity test
- DRBGTestVector tv = tests[0];
-
- SP80090DRBG drbg = new CTRSP800DRBG(new KeyParityCipher(tv.getCipher()), tv.keySizeInBits(), tv.securityStrength(), tv.entropySource(), tv.personalizationString(), tv.nonce());
-
- byte[] output = new byte[tv.expectedValue(0).length];
-
- drbg.generate(output, tv.additionalInput(0), tv.predictionResistance());
-
- // Exception tests
- SP80090DRBG d;
- try
- {
- d = new CTRSP800DRBG(new AESEngine(), 256, 256, new Bit232EntropyProvider().get(128), null, null);
- fail("no exception thrown");
- }
- catch (IllegalArgumentException e)
- {
- if (!e.getMessage().equals("Not enough entropy for security strength required"))
- {
- fail("Wrong exception", e);
- }
- }
-
- try
- {
- d = new CTRSP800DRBG(new DESedeEngine(), 256, 256, new Bit232EntropyProvider().get(232), null, null);
- fail("no exception thrown");
- }
- catch (IllegalArgumentException e)
- {
- if (!e.getMessage().equals("Requested security strength is not supported by block cipher and key size"))
- {
- fail("Wrong exception", e);
- }
- }
-
- try
- {
- d = new CTRSP800DRBG(new DESedeEngine(), 168, 256, new Bit232EntropyProvider().get(232), null, null);
- fail("no exception thrown");
- }
- catch (IllegalArgumentException e)
- {
- if (!e.getMessage().equals("Requested security strength is not supported by block cipher and key size"))
- {
- fail("Wrong exception", e);
- }
- }
-
- try
- {
- d = new CTRSP800DRBG(new AESEngine(), 192, 256, new Bit232EntropyProvider().get(232), null, null);
- fail("no exception thrown");
- }
- catch (IllegalArgumentException e)
- {
- if (!e.getMessage().equals("Requested security strength is not supported by block cipher and key size"))
- {
- fail("Wrong exception", e);
- }
- }
- }
-
- private class Bit232EntropyProvider
- extends TestEntropySourceProvider
- {
- Bit232EntropyProvider()
- {
- super(Hex.decode(
- "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C" +
- "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C" +
- "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDC"), true);
- }
- }
-
- private class Bit256EntropyProvider
- extends TestEntropySourceProvider
- {
- Bit256EntropyProvider()
- {
- super(Hex.decode(
- "0001020304050607"+
- "08090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"+
- "8081828384858687"+
- "88898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F"+
- "C0C1C2C3C4C5C6C7"+
- "C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"), true);
- }
- }
-
- private class Bit320EntropyProvider
- extends TestEntropySourceProvider
- {
- Bit320EntropyProvider()
- {
- super(Hex.decode(
- "000102030405060708090A0B0C0D0E0F"+
- "101112131415161718191A1B1C1D1E1F2021222324252627"+
- "808182838485868788898A8B8C8D8E8F"+
- "909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7"+
- "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"+
- "D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7"), true);
- }
- }
-
- private class Bit384EntropyProvider
- extends TestEntropySourceProvider
- {
- Bit384EntropyProvider()
- {
- super(Hex.decode(
- "000102030405060708090A0B0C0D0E0F1011121314151617" +
- "18191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F" +
- "808182838485868788898A8B8C8D8E8F9091929394959697" +
- "98999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAF" +
- "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7" +
- "D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF"), true);
- }
- }
-
- private class KeyParityCipher
- implements BlockCipher
- {
- private BlockCipher cipher;
-
- KeyParityCipher(BlockCipher cipher)
- {
- this.cipher = cipher;
- }
-
- public void init(boolean forEncryption, CipherParameters params)
- throws IllegalArgumentException
- {
- byte[] k = Arrays.clone(((KeyParameter)params).getKey());
-
- DESedeParameters.setOddParity(k);
-
- if (!Arrays.areEqual(((KeyParameter)params).getKey(), k))
- {
- fail("key not odd parity");
- }
-
- cipher.init(forEncryption, params);
- }
-
- public String getAlgorithmName()
- {
- return cipher.getAlgorithmName();
- }
-
- public int getBlockSize()
- {
- return cipher.getBlockSize();
- }
-
- public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
- throws DataLengthException, IllegalStateException
- {
- return cipher.processBlock(in, inOff, out, outOff);
- }
-
- public void reset()
- {
- cipher.reset();
- }
- }
-
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/prng/test/DRBGTestVector.java b/core/src/test/java/org/bouncycastle/crypto/prng/test/DRBGTestVector.java
deleted file mode 100644
index dd6801c5..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/prng/test/DRBGTestVector.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package org.bouncycastle.crypto.prng.test;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.prng.EntropySource;
-import org.bouncycastle.util.encoders.Hex;
-
-public class DRBGTestVector
-{
- private Digest _digest;
- private BlockCipher _cipher;
- private int _keySizeInBits;
- private EntropySource _eSource;
- private boolean _pr;
- private String _nonce;
- private String _personalisation;
- private int _ss;
- private String[] _ev;
- private List _ai = new ArrayList();
-
- public DRBGTestVector(Digest digest, EntropySource eSource, boolean predictionResistance, String nonce, int securityStrength, String[] expected)
- {
- _digest = digest;
- _eSource = eSource;
- _pr = predictionResistance;
- _nonce = nonce;
- _ss = securityStrength;
- _ev = expected;
- _personalisation = null;
- }
-
- public DRBGTestVector(BlockCipher cipher, int keySizeInBits, EntropySource eSource, boolean predictionResistance, String nonce, int securityStrength, String[] expected)
- {
- _cipher = cipher;
- _keySizeInBits = keySizeInBits;
- _eSource = eSource;
- _pr = predictionResistance;
- _nonce = nonce;
- _ss = securityStrength;
- _ev = expected;
- _personalisation = null;
- }
-
- public Digest getDigest()
- {
- return _digest;
- }
-
- public BlockCipher getCipher()
- {
- return _cipher;
- }
-
- public int keySizeInBits()
- {
- return _keySizeInBits;
- }
-
- public DRBGTestVector addAdditionalInput(String input)
- {
- _ai.add(input);
-
- return this;
- }
-
- public DRBGTestVector setPersonalizationString(String p)
- {
- _personalisation = p;
-
- return this;
- }
-
- public EntropySource entropySource()
- {
- return _eSource;
- }
-
- public boolean predictionResistance()
- {
- return _pr;
- }
-
- public byte[] nonce()
- {
- if (_nonce == null)
- {
- return null;
- }
-
- return Hex.decode(_nonce);
- }
-
- public byte[] personalizationString()
- {
- if (_personalisation == null)
- {
- return null;
- }
-
- return Hex.decode(_personalisation);
- }
-
- public int securityStrength()
- {
- return _ss;
- }
-
- public byte[] expectedValue(int index)
- {
- return Hex.decode(_ev[index]);
- }
-
- public byte[] additionalInput(int position)
- {
- int len = _ai.size();
- byte[] rv;
- if (position >= len)
- {
- rv = null;
- }
- else
- {
- rv = Hex.decode((String)(_ai.get(position)));
- }
- return rv;
- }
-
- }
diff --git a/core/src/test/java/org/bouncycastle/crypto/prng/test/DualECDRBGTest.java b/core/src/test/java/org/bouncycastle/crypto/prng/test/DualECDRBGTest.java
deleted file mode 100644
index d6c26307..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/prng/test/DualECDRBGTest.java
+++ /dev/null
@@ -1,415 +0,0 @@
-package org.bouncycastle.crypto.prng.test;
-
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.digests.SHA384Digest;
-import org.bouncycastle.crypto.digests.SHA512Digest;
-import org.bouncycastle.crypto.prng.drbg.DualECSP800DRBG;
-import org.bouncycastle.crypto.prng.drbg.SP80090DRBG;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * Dual EC SP800-90 DRBG test
- */
-public class DualECDRBGTest
- extends SimpleTest
-{
- public String getName()
- {
- return "DualECDRBG";
- }
-
- public static void main(String[] args)
- {
- runTest(new DualECDRBGTest());
- }
-
- private DRBGTestVector[] createTestVectorData()
- {
- return new DRBGTestVector[]
- {
- new DRBGTestVector(
- new SHA256Digest(),
- new SHA256EntropyProvider().get(128),
- false,
- "2021222324252627",
- 128,
- new String[]
- {
- "FF5163C388F791E96F1052D5C8F0BD6FBF7144839C4890FF85487C5C12702E4C9849AF518AE68DEB14D3A62702BBDE4B98AB211765FD87ACA12FC2A6",
- "9A0A11F2DFB88F7260559DD8DA6134EB2B34CC0415FA8FD0474DB6B85E1A08385F41B435DF81296B1B4EDF66E0107C0844E3D28A89B05046B89177F2"
- }),
- new DRBGTestVector(
- new SHA256Digest(),
- new SHA256EntropyProvider().get(128),
- false,
- "2021222324252627",
- 128,
- new String[]
- {
- "C08E954FCD486D0B0934A0236692AC705A835D1A3C94D2ACD4684AB26E978D7D42E73CC06D6EC1472C63E51BED7F71518395836E2052BBD73A20CABB",
- "1D76DEE36FCC5F9478C112EAFA1C4CCD0635435A6F3A247A3BA3849790B5245070E95C1A67BE7A39BFB213F2C0EFCC171A3253DA6D54DA4362EA2099"
- })
- .addAdditionalInput("606162636465666768696A6B6C6D6E6F")
- .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAF"),
- new DRBGTestVector(
- new SHA256Digest(),
- new SHA256EntropyProvider().get(128),
- false,
- "2021222324252627",
- 128,
- new String[]
- {
- "3AB095CC493A8730D70DE923108B2E4710799044FFC27D0A1156250DDF97E8B05ACE055E49F3E3F5B928CCD18317A3E68FCB0B6F0459ADF9ECF79C87",
- "7B902FC35B0AF50F57F8822936D08A96E41B16967C6B1AA0BC05032F0D53919DC587B664C883E2FE8F3948002FCD8BCBFC4706BCAA2075EF6BF41167"
- })
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F"),
- new DRBGTestVector(
- new SHA256Digest(),
- new SHA256EntropyProvider().get(128),
- false,
- "2021222324252627",
- 128,
- new String[]
- {
- "3B68A1D95ED0312150AC1991189780F37EC50E75249F915CD806BBA0C44F9E3A919B2390805E1E90C1D2D1C823B17B96DB44535B72E0CFB62723529D",
- "250B933475E3BD4FC85D97FD797834B599DEDEDF8B6F15474E1F31B4AF215CFA7A8C0A0296A2E374B3886BB0CC7E49DBB19324564B451E64F12864F9"
- })
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F")
- .addAdditionalInput("606162636465666768696A6B6C6D6E6F")
- .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAF"),
- new DRBGTestVector(
- new SHA256Digest(),
- new SHA256EntropyProvider().get(128),
- true,
- "2021222324252627",
- 128,
- new String[]
- {
- "8C77288EDBEA9A742464F78D55E33593C1BF5F9D8CD8609D6D53BAC4E4B42252A227A99BAD0F2358B05955CD35723B549401C71C9C1F32F8A2018E24",
- "56ECA61C64F69C1C232E992623C71418BD0B96D783118FAAD94A09E3A9DB74D15E805BA7F14625995CA77612B2EF7A05863699ECBABF70D3D422C014"
- }),
- new DRBGTestVector(
- new SHA256Digest(),
- new SHA256EntropyProvider().get(128),
- true,
- "2021222324252627",
- 128,
- new String[]
- {
- "A5C397DFEB540E86F0470E9625D5C5AC2D50016FB201E8DF574F2201DFBB42A799FEB9E238AAD301A493382250EEE60D2E2927E500E848E57535ABD1",
- "BF9894630BEBAF0A0EDFE726285EB055FD2ED678B76673803DD327F49DBEDE87D3E447A6EB73B5D5C52A40078132677F412E9E7DE32B9B1CB32421B9"
- })
- .addAdditionalInput("606162636465666768696A6B6C6D6E6F")
- .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAF"),
- new DRBGTestVector(
- new SHA384Digest(),
- new SHA384EntropyProvider().get(192),
- false,
- "202122232425262728292A2B",
- 192,
- new String[]
- {
- "1F858858B65357D6360E1ED8F8475767B08DAB30718CCA01C6FAE77A4BDCE2702C76D0FB4758EA1ED6AA587CFD26B9011DC8A75D0B4154193BB2C1798FFA52BCAB208310" +
- "3CD2AAD44BEED56D042FC2B8915D7D9BED6437EFEB1582EE",
- "6E4AAB63938212C870F24BB067A32CA9E7FC2343" +
- "5D411729268C8BA6F90E87074D04888CE2CC5A916B7AC93F" +
- "EDE85E2995645DFCC4CE44B9FB41F1BFCC5E9F59EE3A8E1B" +
- "8F85247F741B7C480521EE6BF8BA319B59048E65F08FAA76"
- }),
- new DRBGTestVector(
- new SHA384Digest(),
- new SHA384EntropyProvider().get(192),
- false,
- "202122232425262728292A2B",
- 192,
- new String[]
- {
- "E6A30AB0C9AFCBA673E4F1C94B3DB1F0C7D78B3D" +
- "87B967281BE1E7B3CAF5200AED502C26B84FC169FE8336BD" +
- "23271CB299812F2CF1955AA63FC362044ABA246EF1610F9E" +
- "DC613924A84A00F8DB3FC65C13373F3171EB20848FA9A70E",
- "8585764DF1C86EA12ACCB882525BF6217B447486" +
- "5EBFDA367B8657FA80471139BAC626172B9F219DF2CE9099" +
- "F65833E07CD1A8DD80468779EA3C26620A2C9C9F5C7EFCDD" +
- "C036E6F6C8BF70316D3C37FC246A4CC79B3F1DB971D72ED0"
- })
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F5051525354555657"),
- new DRBGTestVector(
- new SHA384Digest(),
- new SHA384EntropyProvider().get(192),
- false,
- "202122232425262728292A2B",
- 192,
- new String[]
- {
- "13F6EA9BBA7BABDC2A52A3B9FD73D65ECAA638A0" +
- "4C74BCCA2ACDE6FD29FEA4B5D884E095E87D1B7C0DEB9D37" +
- "7AD81FBFEEA2D5EF82C0F6F52B9FCC359E769AC9DF2A876C" +
- "58BAF21657814F3E66D1680B1D4EBD65581E42534F85197D",
- "FC0A36F4D20F8F83BE3430AA3C36A49191821A82" +
- "072BBC3D5AFF8D7EC39484D646277CE87599B6FE8CCA9862" +
- "559703A10F4DE1066BFD30B80C325E774B512525BC6D3734" +
- "4C93906368243D31F89E99C4D2A6E9BEB24D5F7267360DCA"
- })
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F5051525354555657")
- .addAdditionalInput("606162636465666768696A6B6C6D6E6F7071727374757677")
- .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7"),
- new DRBGTestVector(
- new SHA384Digest(),
- new SHA384EntropyProvider().get(192),
- true,
- "202122232425262728292A2B",
- 192,
- new String[]
- {
- "FE55601BF734493013705CCEB76E44AAD48373F7" +
- "42E72B83D4701FA6549255F1CDE6217953522FF973BA4F6E" +
- "C96D2BDCF14A76BE7DEB61781E34B99335BD714F17C91739" +
- "B4E2AB57E36E9C3116E215D3D94FCFAD532636874875CAC7",
- "F5E59D0ABADE81F62FFAB9D4A6A26FF200016608" +
- "A7215E389858FFED83FBC75CFD33DBA6688C89AA32AD22E4" +
- "80EA3D04EADFB35567B67564207E64B77844E8E4A87502D5" +
- "02DBBB6D8277F1CACDB7CF8D293D09DB7DD59A950821507A"
- })
- .addAdditionalInput("606162636465666768696A6B6C6D6E6F7071727374757677")
- .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7"),
- new DRBGTestVector(
- new SHA384Digest(),
- new SHA384EntropyProvider().get(192),
- true,
- "202122232425262728292A2B",
- 192,
- new String[]
- {
- "CC788F70FB08F256D9604333630D85936D400F45" +
- "718DC3F939A8B9F6F75D3E4EC17D68FBB924AEACB7021295" +
- "48FA63CE9BCB82176639B64DE890A47025B5582312FE934E" +
- "F0D0A12697C0F05D2DA108CCADB511BA0EB62F4051BB2354",
- "2C922EA620D76E4137B315EBC29E518F80951B3F" +
- "0E6173FA2BFD94A230EE513EE2E4EB330D802F620DD24911" +
- "534EC0F95A1F1D44A2125F5D57476A666FC372092B55D0D6" +
- "8B49738F5BC466EC206AB3CF6A972B38BCFAE5FCD53C7E21 "
- }),
- new DRBGTestVector(
- new SHA512Digest(),
- new SHA512EntropyProvider().get(256),
- false,
- "202122232425262728292A2B2C2D2E2F",
- 256,
- new String[]
- {
- "7A8313798EE1" +
- "D1898712683F2D0B0DEE5804146ABA64FDA8DB4E539CC8D1" +
- "E59C74EE5AA48E73E958C8EC85DD529D42E68B4F7E02FFAF" +
- "3E3EF8312AEA68BC08A414885E60A7DF0B55F9D90210B319" +
- "E9B8FD23E078A4153636F29AA3CAC8198CB1D5D846151653" +
- "ECE275A591089261238014E5058410065AB8229EB9115E8E",
- "918B5D79E646" +
- "64966D954BC5E2946BF48F061BF0C2701C3C2D1F75EA821E" +
- "1DA05D5B3C2C4EEA246E806B53BF6BDB3F3D53A3AE756C2A" +
- "45C72603973A3DE1BC367C283CA124A5589CEAB30E5D2D74" +
- "8A40DD874FF15B032CF4F4B2AAD590B0DB91A0D38FCE93C5" +
- "AAD4E55AC482F86FF06FAE66B7C7CCA7E45557E1A5A3B85D"
- }),
- new DRBGTestVector(
- new SHA512Digest(),
- new SHA512EntropyProvider().get(256),
- true,
- "202122232425262728292A2B2C2D2E2F",
- 256,
- new String[]
- {
- "C7ED88A2C690" +
- "1C04802BA2BB04262921B19664835A4A3C002CB9F13E35E3" +
- "DEB3698A436BF1C85B070E9E6977CA78A5130905AA0C01A9" +
- "4130F5133DF904A4ACF59A7DD01227E8FCA1C8D51F093839" +
- "46ECD950113104760D7E216CAF581FE9D3AACE6FC4CDDC4C" +
- "CD736D26A60BE8BE2A6A78CD752D1EC7CCC802638B177307",
- "83B78B206785" +
- "4412EEB24AEA86064D510C68FD96DBF94EAC1BC2022752D7" +
- "558AEB9F97B9CBC1B9648FE4D88E2C82A6F530675E1DB92D" +
- "396D6D85BDAD2A23CBD10AD808ECCCFBFC811EB68AE835E4" +
- "912E011DD10A4399C8DE2D9D88F81B6168B05D282B9DAC1E" +
- "65E0A45F61043E1FA047870DD582295E6C50DD1185B13594 "
- })
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F")
- .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F")
- .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"),
- new DRBGTestVector(
- new SHA512Digest(),
- new SHA512EntropyProvider().get(256),
- true,
- "202122232425262728292A2B2C2D2E2F",
- 256,
- new String[]
- {
- "CC7035C73040" +
- "5CF5DF7137ED9E10744B75B540AFFC68EB564B71C0F737E8" +
- "F656B6171940497FA90D8F383EFB6FC6717BA14AAA164EF5" +
- "6641C0F513312551DCD21D0A5B0DBDCD97F627E968DFD752" +
- "56C11CF2BCCA5822EAACE796A34CB7D2F8CD8CC6DBE76274" +
- "498289BBC4C2F1CADA6185D82605CF992EC285BC4945EE9E",
- "0E6C329AD1BE" +
- "681EB1E6F5E03A89E3D80153D6CCDD5A3ECF865003EE4A2D" +
- "E5A23B7F43681361CFAFC3A3FEF17777E75CF9D6685573C8" +
- "87A3962CB955076D45D6F1E45EE4B8CB31A4731CDA031FA2" +
- "815B6D34E29F2603526CE186576F4CCA3FEDF7F8ACDB37C9" +
- "9D762706ABE4967D44739C8CFCFCC76C58B1ED243AC394C0"
- }),
- // From http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip
- // modified to test partial block processing.
- new DRBGTestVector(
- new SHA256Digest(),
- new TestEntropySourceProvider(Hex.decode("a826f1cd3fa24b9e71c316e5bf2bafff"), false).get(128),
- false,
- "82bc3bf050614b34",
- 128,
- new String[]
- {
- "14949b876e30f832331f59f2e687350bea9ba22b78549521a70748ca916c74ebff0b638266aa" +
- "d81e089545eb60bfe332f7d134d91ed3c104f975fae0f71391add71e3380a725251ed5552a84" +
- "650637eddfc88b5ab26311277cbc429aa152b2cfac61c67846512d7564114177a622f25e870a" +
- "acec37c0977d",
- "7050bf74a887809673ecd295071f7a457d1e2e227f68ef4b4445e34f3904b95d4833180ee522" +
- "104bfc996234063e2c76173937b883c66b0e64a56643877228cad5212cddbf839270ef80889b" +
- "c83424c141c2419f2231004c8860f8fd95435e2c9f8ac7409fcbfb6a74851fadc7d99bf5d68b" +
- "591892f0e3a1"
- }),
- new DRBGTestVector(
- new SHA256Digest(),
- new TestEntropySourceProvider(Hex.decode("a826f1cd3fa24b9e71c316e5bf2bafff"), false).get(128),
- false,
- "82bc3bf050614b34",
- 128,
- new String[]
- {
- "14949b876e30f832331f59f2e687350bea9ba22b78549521a70748ca916c74ebff0b638266aa" +
- "d81e089545eb60bfe332f7d134d91ed3c104f975fae0f71391add71e3380a725251ed5552a84" +
- "650637eddfc88b5ab26311277cbc429aa152b2cfac61c67846512d7564114177a622f25e870a" +
- "acec37c0977d",
- "7050bf74a887809673ecd295071f7a457d1e2e227f68ef4b4445e34f3904b95d4833180ee522" +
- "104bfc996234063e2c76173937b883c66b0e64a56643877228cad5212cddbf839270ef80889b" +
- "c83424c141c2419f2231004c8860f8fd95435e2c9f8ac7409fcbfb6a74851fadc7d99bf5d68b" +
- "591892f0e3"
- })
- };
- }
-
- public void performTest()
- throws Exception
- {
- DRBGTestVector[] tests = createTestVectorData();
-
- for (int i = 0; i != tests.length; i++)
- {
- DRBGTestVector tv = tests[i];
-
- byte[] nonce = tv.nonce();
- byte[] personalisationString = tv.personalizationString();
-
- SP80090DRBG d = new DualECSP800DRBG(tv.getDigest(), tv.securityStrength(), tv.entropySource(), personalisationString, nonce);
-
- byte[] output = new byte[tv.expectedValue(0).length];
-
- d.generate(output, tv.additionalInput(0), tv.predictionResistance());
-
- byte[] expected = tv.expectedValue(0);
-
- if (!areEqual(expected, output))
- {
- fail("Test #" + (i + 1) + ".1 failed, expected " + new String(Hex.encode(tv.expectedValue(0))) + " got " + new String(Hex.encode(output)));
- }
-
- output = new byte[tv.expectedValue(1).length];
-
- d.generate(output, tv.additionalInput(1), tv.predictionResistance());
-
- expected = tv.expectedValue(1);
- if (!areEqual(expected, output))
- {
- fail("Test #" + (i + 1) + ".2 failed, expected " + new String(Hex.encode(tv.expectedValue(1))) + " got " + new String(Hex.encode(output)));
- }
- }
-
- // Exception tests
- //
- SP80090DRBG d;
-
- try
- {
- d = new DualECSP800DRBG(new SHA256Digest(), 256, new SHA256EntropyProvider().get(128), null, null);
- fail("no exception thrown");
- }
- catch (IllegalArgumentException e)
- {
- if (!e.getMessage().equals("EntropySource must provide between 256 and 4096 bits"))
- {
- fail("Wrong exception", e);
- }
- }
-
- try
- {
- d = new DualECSP800DRBG(new SHA256Digest(), 256, new SHA256EntropyProvider().get(1 << (13 - 1) + 1), null, null);
- fail("no exception thrown");
- }
- catch (IllegalArgumentException e)
- {
- if (!e.getMessage().equals("EntropySource must provide between 256 and 4096 bits"))
- {
- fail("Wrong exception", e);
- }
- }
-
- try
- {
- d = new DualECSP800DRBG(new SHA1Digest(), 256, new SHA256EntropyProvider().get(256), null, null);
- fail("no exception thrown");
- }
- catch (IllegalArgumentException e)
- {
- if (!e.getMessage().equals("Requested security strength is not supported by digest"))
- {
- fail("Wrong exception", e);
- }
- }
- }
-
- private class SHA256EntropyProvider
- extends TestEntropySourceProvider
- {
- SHA256EntropyProvider()
- {
- super(Hex.decode(
- "000102030405060708090A0B0C0D0E0F " +
- "808182838485868788898A8B8C8D8E8F" +
- "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"), true);
- }
- }
-
- private class SHA384EntropyProvider
- extends TestEntropySourceProvider
- {
- SHA384EntropyProvider()
- {
- super(Hex.decode(
- "000102030405060708090A0B0C0D0E0F1011121314151617" +
- "808182838485868788898A8B8C8D8E8F9091929394959697" +
- "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7"), true);
- }
- }
-
- private class SHA512EntropyProvider
- extends TestEntropySourceProvider
- {
- SHA512EntropyProvider()
- {
- super(Hex.decode(
- "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F" +
- "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F" +
- "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"), true);
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/prng/test/FixedSecureRandomTest.java b/core/src/test/java/org/bouncycastle/crypto/prng/test/FixedSecureRandomTest.java
deleted file mode 100644
index 24fc238a..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/prng/test/FixedSecureRandomTest.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.bouncycastle.crypto.prng.test;
-
-import org.bouncycastle.crypto.prng.FixedSecureRandom;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class FixedSecureRandomTest
- extends SimpleTest
-{
- byte[] base = Hex.decode("deadbeefdeadbeef");
- byte[] r1 = Hex.decode("cafebabecafebabe");
- byte[] r2 = Hex.decode("ffffffffcafebabedeadbeef");
-
- public String getName()
- {
- return "FixedSecureRandom";
- }
-
- public void performTest()
- throws Exception
- {
- FixedSecureRandom fixed = new FixedSecureRandom(base);
- byte[] buf = new byte[8];
-
- fixed.nextBytes(buf);
-
- if (!Arrays.areEqual(buf, base))
- {
- fail("wrong data returned");
- }
-
- fixed = new FixedSecureRandom(base);
-
- byte[] seed = fixed.generateSeed(8);
-
- if (!Arrays.areEqual(seed, base))
- {
- fail("wrong seed data returned");
- }
-
- if (!fixed.isExhausted())
- {
- fail("not exhausted");
- }
-
- fixed = new FixedSecureRandom(new byte[][] { r1, r2 });
-
- seed = fixed.generateSeed(12);
-
- if (!Arrays.areEqual(seed, Hex.decode("cafebabecafebabeffffffff")))
- {
- fail("wrong seed data returned - composite");
- }
-
- fixed.nextBytes(buf);
-
- if (!Arrays.areEqual(buf, Hex.decode("cafebabedeadbeef")))
- {
- fail("wrong data returned");
- }
- }
-
- public static void main(String[] args)
- {
- runTest(new FixedSecureRandomTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/prng/test/HMacDRBGTest.java b/core/src/test/java/org/bouncycastle/crypto/prng/test/HMacDRBGTest.java
deleted file mode 100644
index add77d5a..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/prng/test/HMacDRBGTest.java
+++ /dev/null
@@ -1,508 +0,0 @@
-package org.bouncycastle.crypto.prng.test;
-
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.digests.SHA384Digest;
-import org.bouncycastle.crypto.digests.SHA512Digest;
-import org.bouncycastle.crypto.macs.HMac;
-import org.bouncycastle.crypto.prng.drbg.HMacSP800DRBG;
-import org.bouncycastle.crypto.prng.drbg.SP80090DRBG;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * HMAC SP800-90 DRBG
- */
-public class HMacDRBGTest
- extends SimpleTest
-{
- public String getName()
- {
- return "HMacDRBG";
- }
-
- public static void main(String[] args)
- {
- runTest(new HMacDRBGTest());
- }
-
- private DRBGTestVector[] createTestVectorData()
- {
- return new DRBGTestVector[]
- {
- new DRBGTestVector(
- new SHA1Digest(),
- new SHA1EntropyProvider().get(440),
- false,
- "2021222324",
- 80,
- new String[]
- {
- "5A7D3B449F481CB38DF79AD2B1FCC01E57F8135E8C0B22CD0630BFB0127FB5408C8EFC17A929896E",
- "82cf772ec3e84b00fc74f5df104efbfb2428554e9ce367d03aeade37827fa8e9cb6a08196115d948"
- }),
- new DRBGTestVector(
- new SHA1Digest(),
- new SHA1EntropyProvider().get(440),
- false,
- "2021222324",
- 80,
- new String[]
- {
- "B3BD05246CBA12A64735A4E3FDE599BC1BE30F439BD060208EEA7D71F9D123DF47B3CE069D98EDE6",
- "B5DADA380E2872DF935BCA55B882C8C9376902AB639765472B71ACEBE2EA8B1B6B49629CB67317E0"
- })
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576"),
- new DRBGTestVector(
- new SHA1Digest(),
- new SHA1EntropyProvider().get(440),
- false,
- "2021222324",
- 80,
- new String[]
- {
- "C7AAAC583C6EF6300714C2CC5D06C148CFFB40449AD0BB26FAC0497B5C57E161E36681BCC930CE80",
- "6EBD2B7B5E0A2AD7A24B1BF9A1DBA47D43271719B9C37B7FE81BA94045A14A7CB514B446666EA5A7"
- })
- .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90919293949596")
- .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6"),
- new DRBGTestVector(
- new SHA1Digest(),
- new SHA1EntropyProvider().get(440),
- true,
- "2021222324",
- 80,
- new String[]
- {
- "FEC4597F06A3A8CC8529D59557B9E661053809C0BC0EFC282ABD87605CC90CBA9B8633DCB1DAE02E",
- "84ADD5E2D2041C01723A4DE4335B13EFDF16B0E51A0AD39BD15E862E644F31E4A2D7D843E57C5968"
- }),
- new DRBGTestVector(
- new SHA1Digest(),
- new SHA1EntropyProvider().get(440),
- true,
- "2021222324",
- 80,
- new String[]
- {
- "6C37FDD729AA40F80BC6AB08CA7CC649794F6998B57081E4220F22C5C283E2C91B8E305AB869C625",
- "CAF57DCFEA393B9236BF691FA456FEA7FDF1DF8361482CA54D5FA723F4C88B4FA504BF03277FA783"
- })
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576"),
- new DRBGTestVector(
- new SHA1Digest(),
- new SHA1EntropyProvider().get(440),
- true,
- "2021222324",
- 80,
- new String[]
- {
- "A1BA8FA58BB5013F43F7B6ED52B4539FA16DC77957AEE815B9C07004C7E992EB8C7E591964AFEEA2",
- "84264A73A818C95C2F424B37D3CC990B046FB50C2DC64A164211889A010F2471A0912FFEA1BF0195"
- })
- .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90919293949596")
- .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6"),
- new DRBGTestVector(
- new SHA256Digest(),
- new SHA256EntropyProvider().get(440),
- false,
- "2021222324252627",
- 128,
- new String[]
- {
- "D67B8C1734F46FA3F763CF57C6F9F4F2" +
- "DC1089BD8BC1F6F023950BFC5617635208C8501238AD7A44" +
- "00DEFEE46C640B61AF77C2D1A3BFAA90EDE5D207406E5403",
- "8FDAEC20F8B421407059E3588920DA7E" +
- "DA9DCE3CF8274DFA1C59C108C1D0AA9B0FA38DA5C792037C" +
- "4D33CD070CA7CD0C5608DBA8B885654639DE2187B74CB263"
- }),
- new DRBGTestVector(
- new SHA256Digest(),
- new SHA256EntropyProvider().get(440),
- true,
- "2021222324252627",
- 128,
- new String[]
- {
- "FABD0AE25C69DC2EFDEFB7F20C5A31B5" +
- "7AC938AB771AA19BF8F5F1468F665C938C9A1A5DF0628A56" +
- "90F15A1AD8A613F31BBD65EEAD5457D5D26947F29FE91AA7",
- "6BD925B0E1C232EFD67CCD84F722E927" +
- "ECB46AB2B740014777AF14BA0BBF53A45BDBB62B3F7D0B9C" +
- "8EEAD057C0EC754EF8B53E60A1F434F05946A8B686AFBC7A"
- }),
- new DRBGTestVector(
- new SHA384Digest(),
- new SHA384EntropyProvider().get(888),
- false,
- "202122232425262728292A2B",
- 192,
- new String[]{
- "03AB8BCE4D1DBBB636C5C5B7E1C58499FEB1C619CDD11D35" +
- "CD6CF6BB8F20EF27B6F5F9054FF900DB9EBF7BF30ED4DCBB" +
- "BC8D5B51C965EA226FFEE2CA5AB2EFD00754DC32F357BF7A" +
- "E42275E0F7704DC44E50A5220AD05AB698A22640AC634829",
- "B907E77144FD55A54E9BA1A6A0EED0AAC780020C41A15DD8" +
- "9A6C163830BA1D094E6A17100FF71EE30A96E1EE04D2A966" +
- "03832A4E404F1966C2B5F4CB61B9927E8D12AC1E1A24CF23" +
- "88C14E8EC96C35181EAEE32AAA46330DEAAFE5E7CE783C74"})
- .setPersonalizationString(
- "404142434445464748494A4B4C4D4E" +
- "4F505152535455565758595A5B5C5D5E5F60616263646566" +
- "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" +
- "7F808182838485868788898A8B8C8D8E8F90919293949596" +
- "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"),
- new DRBGTestVector(
- new SHA384Digest(),
- new SHA384EntropyProvider().get(888),
- true,
- "202122232425262728292A2B",
- 192,
- new String[]{
- "804A3AD720F4FCE8738D0632514FEF16430CB7D63A8DF1A5" +
- "F02A3CE3BD7ED6A668B69E63E2BB93F096EE753D6194A0F1" +
- "A32711063653009636337D22167CC4402D019AC216FA574F" +
- "091CF6EA283568D737A77BE38E8F09382C69E76B142ABC3A",
- "73B8E55C753202176A17B9B9754A9FE6F23B01861FCD4059" +
- "6AEAA301AF1AEF8AF0EAF22FBF34541EFFAB1431666ACACC" +
- "759338C7E28672819D53CFEF10A3E19DAFBD53295F1980A9" +
- "F491504A2725506784B7AC826D92C838A8668171CAAA86E7"})
- .setPersonalizationString(
- "404142434445464748494A4B4C4D4E" +
- "4F505152535455565758595A5B5C5D5E5F60616263646566" +
- "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" +
- "7F808182838485868788898A8B8C8D8E8F90919293949596" +
- "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"),
- new DRBGTestVector(
- new SHA512Digest(),
- new SHA512EntropyProvider().get(888),
- false,
- "202122232425262728292A2B2C2D2E2F",
- 256,
- new String[]{
- "2A5FF6520C20F66E" +
- "D5EA431BD4AEAC58F975EEC9A015137D5C94B73AA09CB8B5" +
- "9D611DDEECEB34A52BB999424009EB9EAC5353F92A6699D2" +
- "0A02164EEBBC6492941E10426323898465DFD731C7E04730" +
- "60A5AA8973841FDF3446FB6E72A58DA8BDA2A57A36F3DD98" +
- "6DF85C8A5C6FF31CDE660BF8A841B21DD6AA9D3AC356B87B",
- "0EDC8D7D7CEEC7FE" +
- "36333FB30C0A9A4B27AA0BECBF075568B006C1C3693B1C29" +
- "0F84769C213F98EB5880909EDF068FDA6BFC43503987BBBD" +
- "4FC23AFBE982FE4B4B007910CC4874EEC217405421C8D8A1" +
- "BA87EC684D0AF9A6101D9DB787AE82C3A6A25ED478DF1B12" +
- "212CEC325466F3AC7C48A56166DD0B119C8673A1A9D54F67"})
- .setPersonalizationString(
- "404142434445464748494A4B4C4D4E" +
- "4F505152535455565758595A5B5C5D5E5F60616263646566" +
- "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" +
- "7F808182838485868788898A8B8C8D8E8F90919293949596" +
- "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"),
- new DRBGTestVector(
- new SHA512Digest(),
- new SHA512EntropyProvider().get(888),
- true,
- "202122232425262728292A2B2C2D2E2F",
- 256,
- new String[]{
- "AAE4DC3C9ECC74D9" +
- "061DD527117EF3D29E1E52B26853C539D6CA797E8DA3D0BB" +
- "171D8E30B8B194D8C28F7F6BE3B986B88506DC6A01B294A7" +
- "165DD1C3470F7BE7B396AA0DB7D50C4051E7C7E1C8A7D21A" +
- "2B5878C0BCB163CAA79366E7A1162FDC88429616CD3E6977" +
- "8D327520A6BBBF71D8AA2E03EC4A9DAA0E77CF93E1EE30D2 ",
- "129FF6D31A23FFBC" +
- "870632B35EE477C2280DDD2ECDABEDB900C78418BE2D243B" +
- "B9D8E5093ECE7B6BF48638D8F704D134ADDEB7F4E9D5C142" +
- "CD05683E72B516486AF24AEC15D61E81E270DD4EBED91B62" +
- "12EB8896A6250D5C8BC3A4A12F7E3068FBDF856F47EB23D3" +
- "79F82C1EBCD1585FB260B9C0C42625FBCEE68CAD773CD5B1"})
- .setPersonalizationString(
- "404142434445464748494A4B4C4D4E" +
- "4F505152535455565758595A5B5C5D5E5F60616263646566" +
- "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" +
- "7F808182838485868788898A8B8C8D8E8F90919293949596" +
- "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"),
- new DRBGTestVector(
- new SHA512Digest(),
- new SHA512EntropyProvider().get(888),
- false,
- "202122232425262728292A2B2C2D2E2F",
- 256,
- new String[]{
- "7AE31A2DEC31075F" +
- "E5972660C16D22ECC0D415C5693001BE5A468B590BC1AE2C" +
- "43F647F8D681AEEA0D87B79B0B4E5D089CA2C9D327534234" +
- "0254E6B04690D77A71A294DA9568479EEF8BB2A2110F18B6" +
- "22F60F35235DE0E8F9D7E98105D84AA24AF0757AF005DFD5" +
- "2FA51DE3F44FCE0C5F3A27FCE8B0F6E4A3F7C7B53CE34A3D",
- "D83A8084630F286D" +
- "A4DB49B9F6F608C8993F7F1397EA0D6F4A72CF3EF2733A11" +
- "AB823C29F2EBDEC3EDE962F93D920A1DB59C84E1E879C29F" +
- "5F9995FC3A6A3AF9B587CA7C13EA197D423E81E1D6469942" +
- "B6E2CA83A97E91F6B298266AC148A1809776C26AF5E239A5" +
- "5A2BEB9E752203A694E1F3FE2B3E6A0C9C314421CDB55FBD "})
- .setPersonalizationString(
- "404142434445464748494A4B4C4D4E" +
- "4F505152535455565758595A5B5C5D5E5F60616263646566" +
- "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" +
- "7F808182838485868788898A8B8C8D8E8F90919293949596" +
- "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE")
- .addAdditionalInput(
- "606162636465666768696A6B6C6D6E" +
- "6F707172737475767778797A7B7C7D7E7F80818283848586" +
- "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" +
- "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" +
- "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE")
- .addAdditionalInput(
- "A0A1A2A3A4A5A6A7A8A9AAABACADAE" +
- "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" +
- "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" +
- "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" +
- "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E"),
- new DRBGTestVector(
- new SHA512Digest(),
- new SHA512EntropyProvider().get(888),
- true,
- "202122232425262728292A2B2C2D2E2F",
- 256,
- new String[]{
- "28FD6060C4F35F4D" +
- "317AB2060EE32019E0DAA330F3F5650BBCA57CB67EE6AF1C" +
- "6F25D1B01F3601EDA85DC2ED29A9B2BA4C85CF491CE7185F" +
- "1A2BD9378AE3C655BD1CEC2EE108AE7FC382989F6D4FEA8A" +
- "B01499697C2F07945CE02C5ED617D04287FEAF3BA638A4CE" +
- "F3BB6B827E40AF16279580FCF1FDAD830930F7FDE341E2AF",
- "C0B1601AFE39338B" +
- "58DC2BE7C256AEBE3C21C5A939BEEC7E97B3528AC420F0C6" +
- "341847187666E0FF578A8EB0A37809F877365A28DF2FA0F0" +
- "6354A6F02496747369375B9A9D6B756FDC4A8FB308E08256" +
- "9D79A85BB960F747256626389A3B45B0ABE7ECBC39D5CD7B" +
- "2C18DF2E5FDE8C9B8D43474C54B6F9839468445929B438C7"}),
- new DRBGTestVector(
- new SHA512Digest(),
- new SHA512EntropyProvider().get(888),
- true,
- "202122232425262728292A2B2C2D2E2F",
- 256,
- new String[]{
- "72691D2103FB567C" +
- "CD30370715B36666F63430087B1C688281CA0974DB456BDB" +
- "A7EB5C48CFF62EA05F9508F3B530CE995A272B11EC079C13" +
- "923EEF8E011A93C19B58CC6716BC7CB8BD886CAA60C14D85" +
- "C023348BD77738C475D6C7E1D9BFF4B12C43D8CC73F838DC" +
- "4F8BD476CF8328EEB71B3D873D6B7B859C9B21065638FF95",
- "8570DA3D47E1E160" +
- "5CF3E44B8D328B995EFC64107B6292D1B1036B5F88CE3160" +
- "2F12BEB71D801C0942E7C0864B3DB67A9356DB203490D881" +
- "24FE86BCE38AC2269B4FDA6ABAA884039DF80A0336A24D79" +
- "1EB3067C8F5F0CF0F18DD73B66A7B316FB19E02835CC6293" +
- "65FCD1D3BE640178ED9093B91B36E1D68135F2785BFF505C"})
- .addAdditionalInput(
- "606162636465666768696A6B6C6D6E" +
- "6F707172737475767778797A7B7C7D7E7F80818283848586" +
- "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" +
- "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" +
- "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE")
- .addAdditionalInput(
- "A0A1A2A3A4A5A6A7A8A9AAABACADAE" +
- "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" +
- "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" +
- "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" +
- "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E"),
- new DRBGTestVector(
- new SHA512Digest(),
- new SHA512EntropyProvider().get(888),
- true,
- "202122232425262728292A2B2C2D2E2F",
- 256,
- new String[]{
- "AAE4DC3C9ECC74D9" +
- "061DD527117EF3D29E1E52B26853C539D6CA797E8DA3D0BB" +
- "171D8E30B8B194D8C28F7F6BE3B986B88506DC6A01B294A7" +
- "165DD1C3470F7BE7B396AA0DB7D50C4051E7C7E1C8A7D21A" +
- "2B5878C0BCB163CAA79366E7A1162FDC88429616CD3E6977" +
- "8D327520A6BBBF71D8AA2E03EC4A9DAA0E77CF93E1EE30D2 ",
- "129FF6D31A23FFBC" +
- "870632B35EE477C2280DDD2ECDABEDB900C78418BE2D243B" +
- "B9D8E5093ECE7B6BF48638D8F704D134ADDEB7F4E9D5C142" +
- "CD05683E72B516486AF24AEC15D61E81E270DD4EBED91B62" +
- "12EB8896A6250D5C8BC3A4A12F7E3068FBDF856F47EB23D3" +
- "79F82C1EBCD1585FB260B9C0C42625FBCEE68CAD773CD5B1"})
- .setPersonalizationString(
- "404142434445464748494A4B4C4D4E" +
- "4F505152535455565758595A5B5C5D5E5F60616263646566" +
- "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" +
- "7F808182838485868788898A8B8C8D8E8F90919293949596" +
- "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"),
- new DRBGTestVector(
- new SHA512Digest(),
- new SHA512EntropyProvider().get(888),
- true,
- "202122232425262728292A2B2C2D2E2F",
- 256,
- new String[]{
- "B8E827652175E6E0" +
- "6E513C7BE94B5810C14ED94AD903647940CAEB7EE014C848" +
- "8DCBBE6D4D6616D06656A3DC707CDAC4F02EE6D8408C065F" +
- "CB068C0760DA47C5D60E5D70D09DC3929B6979615D117F7B" +
- "EDCC661A98514B3A1F55B2CBABDCA59F11823E4838065F1F" +
- "8431CBF28A577738234AF3F188C7190CC19739E72E9BBFFF",
- "7ED41B9CFDC8C256" +
- "83BBB4C553CC2DC61F690E62ABC9F038A16B8C519690CABE" +
- "BD1B5C196C57CF759BB9871BE0C163A57315EA96F615136D" +
- "064572F09F26D659D24211F9610FFCDFFDA8CE23FFA96735" +
- "7595182660877766035EED800B05364CE324A75EB63FD9B3" +
- "EED956D147480B1D0A42DF8AA990BB628666F6F61D60CBE2"})
- .setPersonalizationString(
- "404142434445464748494A4B4C4D4E" +
- "4F505152535455565758595A5B5C5D5E5F60616263646566" +
- "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" +
- "7F808182838485868788898A8B8C8D8E8F90919293949596" +
- "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE")
- .addAdditionalInput(
- "606162636465666768696A6B6C6D6E" +
- "6F707172737475767778797A7B7C7D7E7F80818283848586" +
- "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" +
- "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" +
- "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE")
- .addAdditionalInput(
- "A0A1A2A3A4A5A6A7A8A9AAABACADAE" +
- "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" +
- "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" +
- "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" +
- "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E")
- };
- }
-
- public void performTest()
- throws Exception
- {
- DRBGTestVector[] tests = createTestVectorData();
-
- for (int i = 0; i != tests.length; i++)
- {
- DRBGTestVector tv = tests[i];
-
- byte[] nonce = tv.nonce();
- byte[] personalisationString = tv.personalizationString();
-
- SP80090DRBG d = new HMacSP800DRBG(new HMac(tv.getDigest()), tv.securityStrength(), tv.entropySource(), personalisationString, nonce);
-
- byte[] output = new byte[tv.expectedValue(0).length];
-
- d.generate(output, tv.additionalInput(0), tv.predictionResistance());
-
- byte[] expected = tv.expectedValue(0);
-
- if (!areEqual(expected, output))
- {
- fail("Test #" + (i + 1) + ".1 failed, expected " + new String(Hex.encode(tv.expectedValue(0))) + " got " + new String(Hex.encode(output)));
- }
-
- output = new byte[tv.expectedValue(0).length];
-
- d.generate(output, tv.additionalInput(1), tv.predictionResistance());
-
- expected = tv.expectedValue(1);
- if (!areEqual(expected, output))
- {
- fail("Test #" + (i + 1) + ".2 failed, expected " + new String(Hex.encode(tv.expectedValue(1))) + " got " + new String(Hex.encode(output)));
- }
- }
-
- // Exception tests
- //
- SP80090DRBG d;
- try
- {
- d = new HMacSP800DRBG(new HMac(new SHA256Digest()), 256, new SHA256EntropyProvider().get(128), null, null);
- fail("no exception thrown");
- }
- catch (IllegalArgumentException e)
- {
- if (!e.getMessage().equals("Not enough entropy for security strength required"))
- {
- fail("Wrong exception", e);
- }
- }
- }
-
- private class SHA1EntropyProvider
- extends TestEntropySourceProvider
- {
- SHA1EntropyProvider()
- {
- super(
- Hex.decode(
- "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233343536"
- + "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6"
- + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6"), true);
- }
- }
-
- private class SHA256EntropyProvider
- extends TestEntropySourceProvider
- {
- SHA256EntropyProvider()
- {
- super(Hex.decode(
- "00010203040506" +
- "0708090A0B0C0D0E0F101112131415161718191A1B1C1D1E" +
- "1F202122232425262728292A2B2C2D2E2F30313233343536" +
- "80818283848586" +
- "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" +
- "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" +
- "C0C1C2C3C4C5C6" +
- "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" +
- "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6"), true);
- }
- }
-
- private class SHA384EntropyProvider
- extends TestEntropySourceProvider
- {
- SHA384EntropyProvider()
- {
- super(Hex.decode(
- "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223242526"
- + "2728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F50515253545556"
- + "5758595A5B5C5D5E5F606162636465666768696A6B6C6D6E" +
- "808182838485868788898A8B8C8D8E" +
- "8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6" +
- "A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBE" +
- "BFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6" +
- "D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE" +
- "C0C1C2C3C4C5C6C7C8C9CACBCCCDCE" +
- "CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6" +
- "E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" +
- "FF000102030405060708090A0B0C0D0E0F10111213141516" +
- "1718191A1B1C1D1E1F202122232425262728292A2B2C2D2E"), true);
- }
- }
-
- private class SHA512EntropyProvider
- extends TestEntropySourceProvider
- {
- SHA512EntropyProvider()
- {
- super(Hex.decode(
- "000102030405060708090A0B0C0D0E" +
- "0F101112131415161718191A1B1C1D1E1F20212223242526" +
- "2728292A2B2C2D2E2F303132333435363738393A3B3C3D3E" +
- "3F404142434445464748494A4B4C4D4E4F50515253545556" +
- "5758595A5B5C5D5E5F606162636465666768696A6B6C6D6E" +
- "808182838485868788898A8B8C8D8E" +
- "8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6" +
- "A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBE" +
- "BFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6" +
- "D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE" +
- "C0C1C2C3C4C5C6C7C8C9CACBCCCDCE" +
- "CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6" +
- "E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" +
- "FF000102030405060708090A0B0C0D0E0F10111213141516" +
- "1718191A1B1C1D1E1F202122232425262728292A2B2C2D2E"), true);
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/prng/test/HashDRBGTest.java b/core/src/test/java/org/bouncycastle/crypto/prng/test/HashDRBGTest.java
deleted file mode 100644
index ee632033..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/prng/test/HashDRBGTest.java
+++ /dev/null
@@ -1,481 +0,0 @@
-package org.bouncycastle.crypto.prng.test;
-
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.digests.SHA384Digest;
-import org.bouncycastle.crypto.digests.SHA512Digest;
-import org.bouncycastle.crypto.prng.drbg.HashSP800DRBG;
-import org.bouncycastle.crypto.prng.drbg.SP80090DRBG;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * DRBG Test
- */
-public class HashDRBGTest
- extends SimpleTest
-{
- public String getName()
- {
- return "HashDRBG";
- }
-
- public static void main(String[] args)
- {
- runTest(new HashDRBGTest());
- }
-
- private DRBGTestVector[] createTestVectorData()
- {
- return new DRBGTestVector[]
- {
- new DRBGTestVector(
- new SHA1Digest(),
- new SHA1EntropyProvider().get(440),
- false,
- "2021222324",
- 80,
- new String[]
- {
- "9F7CFF1ECA23E750F66326969F11800F12088BA68E441D15D888B3FE12BF66FE057494F4546DE2F1",
- "B77AA5C0CD55BBCEED7574AF223AFD988C7EEC8EFF4A94E5E89D26A04F58FA79F5E0D3702D7A9A6A"
- }
- ),
- new DRBGTestVector(
- new SHA1Digest(),
- new SHA1EntropyProvider().get(440),
- false,
- "2021222324",
- 80,
- new String[]
- {
- "AB438BD3B01A0AF85CFEE29F7D7B71621C4908B909124D430E7B406FB1086EA994C582E0D656D989",
- "29D9098F987E7005314A0F51B3DD2B8122F4AED706735DE6AD5DDBF223177C1E5F3AEBC52FAB90B9"
- })
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576"),
- new DRBGTestVector(
- new SHA1Digest(),
- new SHA1EntropyProvider().get(440),
- false,
- "2021222324",
- 80,
- new String[]
- {
- "E76B4EDD5C865BC8AFD809A59B69B429AC7F4352A579BCF3F75E56249A3491F87C3CA6848B0FAB25",
- "6577B6B4F87A93240B199FE51A3B335313683103DECE171E3256FB7E803586CA4E45DD242EB01F70"
- })
- .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90919293949596")
- .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6"),
- new DRBGTestVector(
- new SHA1Digest(),
- new SHA1EntropyProvider().get(440),
- true,
- "2021222324",
- 80,
- new String[]
- {
- "56EF4913373994D5539F4D7D17AFE7448CDF5E72416CC6A71A340059FA0D5AE526B23250C46C0944",
- "575B37A2739814F966C63B60A2C4F149CA9ACC84FC4B25493289B085C67B2E30F5F0B99A2C349E2A"
- }),
- new DRBGTestVector(
- new SHA1Digest(),
- new SHA1EntropyProvider().get(440),
- true,
- "2021222324",
- 80,
- new String[]
- {
- "532CA1165DCFF21C55592687639884AF4BC4B057DF8F41DE653AB44E2ADEC7C9303E75ABE277EDBF",
- "73C2C67C696D686D0C4DBCEB5C2AF7DDF6F020B6874FAE4390F102117ECAAFF54418529A367005A0"
- })
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576"),
- new DRBGTestVector(
- new SHA1Digest(),
- new SHA1EntropyProvider().get(440),
- true,
- "2021222324",
- 80,
- new String[]
- {
- "183C242A1430E46C4ED70B4DBE1BF9AB0AB8721CDCA2A2D1820AD6F6C956858543B2AA191D8D1287",
- "F196F9BD021C745CBD5AC7BFCE48EAAF0D0E7C091FBF436940E63A198EE770D9A4F0718669AF2BC9"
- })
- .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90919293949596")
- .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6"),
- new DRBGTestVector(
- new SHA256Digest(),
- new SHA256EntropyProvider().get(440),
- false,
- "2021222324252627",
- 128,
- new String[]
- {
- "77E05A0E7DC78AB5D8934D5E93E82C06" +
- "A07C04CEE6C9C53045EEB485872777CF3B3E35C474F976B8" +
- "94BF301A86FA651F463970E89D4A0534B2ECAD29EC044E7E",
- "5FF4BA493C40CFFF3B01E472C575668C" +
- "CE3880B9290B05BFEDE5EC96ED5E9B2898508B09BC800EEE" +
- "099A3C90602ABD4B1D4F343D497C6055C87BB956D53BF351"
- }
- ),
- new DRBGTestVector(
- new SHA256Digest(),
- new SHA256EntropyProvider().get(440),
- true,
- "2021222324252627",
- 128,
- new String[]
- {
- "92275523C70E567BCF9B35EC50B933F8" +
- "12616DF586B7F72EE1BC7735A5C2654373CBBC72316DFF84" +
- "20A33BF02B97AC8D1952583F270ACD7005CC027F4CF1187E",
- "681A46B2AA8694A0FE4DEEA720927A84" +
- "EAAA985E59C19F8BE0984D8CBEF8C69B754167641946E040" +
- "EE2043E1CCB29DCF063C0A50830E428E6DCA262ECD77C542"
- }),
- new DRBGTestVector(
- new SHA384Digest(),
- new SHA384EntropyProvider().get(888),
- false,
- "202122232425262728292A2B",
- 192,
- new String[]
- {
- "04FF23AD15E78790ADD36B438BBC097C7A11747CC2CCEEDE" +
- "2C978B23B3DC63B732C953061D7764990ABFEFC47A581B92" +
- "1BC0428C4F12212460E406A0F0651E7F0CB9A90ABFDB07B5" +
- "25565C74F0AA085082F6CF213AAFAD0C0646895078F1E1FE",
- "4F35B85F95DEE3E873054905CFD02341653E18F529930CBE" +
- "14D909F37FEAF2C790D22FAE7516B4590BE35D53E2FE1A35" +
- "AFE4B6607CB358589C3B4D094A1D81FE0717F1DF5BDDEB3E" +
- "114F130BB781E66C22B5B770E8AE115FF39F8ADAF66DEEDF"
- }
- ),
- new DRBGTestVector(
- new SHA384Digest(),
- new SHA384EntropyProvider().get(888),
- true,
- "202122232425262728292A2B",
- 192,
- new String[]
- {
- "97993B78F7C31C0E876DC92EB7D6C408E09D608AD6B99D0E" +
- "A2229B05A578C426334FCC8A1C7E676ED2D89A5B4CDF5B3F" +
- "4ADF11936BF14F4E10909DBA9C24F4FDFFDE72351DA8E2CC" +
- "3B135A395373899E5F1A5955B880CA9B9E9DD4C9CA7FA4D4",
- "F5983946320E36C64EF283CA1F65D197CF81624EC6778E77" +
- "0E78949D84EF21A45CDD62D1DB76920D4C2836FC6AE5299F" +
- "AF1357D9701FAD10FBD88D1E2832239436D76EB271BDC3CA" +
- "04425EC88BC0E89A4D5C37FFCE7C6C3ABDE9C413AE6D3FEA"
- }
- ),
- new DRBGTestVector(
- new SHA512Digest(),
- new SHA512EntropyProvider().get(888),
- false,
- "202122232425262728292A2B2C2D2E2F",
- 256,
- new String[]
- {
- "DA126CF95C6BF97E" +
- "2F731F2137A907ACC70FD7AC9EBACD1C6E31C74029B052E3" +
- "AABC48F3B00993F2B2381F7650A55322A968C86E05DE88E6" +
- "367F6EF89A601DB4342E9086C7AC13B5E56C32E9E668040B" +
- "73847893C5BFD38A1CF44F348B4EEE4CD68ADB7E7B8C837F" +
- "19BC4F902761F7CFF24AB1D704FD11C4E929D8553753B55D",
- "400B977CE8A2BB6A" +
- "84C6FD1CF901459685ABF5408CFF4588CEDF52E2D2DC300A" +
- "A9B4FAED8CD0161C2172B1FD269253195883D6EBF21020F2" +
- "C20E5F2C81AE60C8595B834A229B1F5B726C1125717E6207" +
- "8886EF38E61E32707AD5F8116C6393DFB6E7C7AE0E8E92BB" +
- "D7E0C3D04BBA02F5169F2F569A58158915FEE4C9D28D45DB"
- }
- )
- .setPersonalizationString(
- "404142434445464748494A4B4C4D4E" +
- "4F505152535455565758595A5B5C5D5E5F60616263646566" +
- "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" +
- "7F808182838485868788898A8B8C8D8E8F90919293949596" +
- "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE")
- .addAdditionalInput(
- "606162636465666768696A6B6C6D6E" +
- "6F707172737475767778797A7B7C7D7E7F80818283848586" +
- "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" +
- "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" +
- "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE")
- .addAdditionalInput(
- "A0A1A2A3A4A5A6A7A8A9AAABACADAE" +
- "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" +
- "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" +
- "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" +
- "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E"),
- new DRBGTestVector(
- new SHA512Digest(),
- new SHA512EntropyProvider().get(888),
- true,
- "202122232425262728292A2B2C2D2E2F",
- 256,
- new String[]
- {
- "F93CA6855590A77F" +
- "07354097E90E026648B6115DF008FFEDBD9D9811F54E8286" +
- "EF00FDD6BA1E58DF2535E3FBDD9A9BA3754A97F36EE83322" +
- "1582060A1F37FCE4EE8826636B28EAD589593F4CA8B64738" +
- "8F24EB3F0A34796968D21BDEE6F81FD5DF93536F935937B8" +
- "025EC8CBF57DDB0C61F2E41463CC1516D657DA2829C6BF90",
- "4817618F48C60FB1" +
- "CE5BFBDA0CAF4591882A31F6EE3FE0F78779992A06EC60F3" +
- "7FB9A8D6108C231F0A927754B0599FA4FA27A4E25E065EF0" +
- "3085B892979DC0E7A1080883CAEBFDFD3665A8F2D061C521" +
- "F7D6E3DA2AF8B97B6B43B6EC831AF515070A83BBB9AC95ED" +
- "4EF49B756A2377A5F0833D847E27A88DDB0C2CE4AD782E7B "
- }
- ),
- new DRBGTestVector(
- new SHA512Digest(),
- new SHA512EntropyProvider().get(888),
- true,
- "202122232425262728292A2B2C2D2E2F",
- 256,
- new String[]
- {
- "0455DD4AD7DBACB2" +
- "410BE58DF7248D765A4547ABAEE1743B0BCAD37EBD06DA7C" +
- "F7CE5E2216E525327E9E2005EBEF2CE53BD733B18128627D" +
- "3FD6153089373AF2606A1584646A0EA488BFEF45228699A0" +
- "89CEA8AEC44502D86D9591F3552C688B7F7B45FCB0C3C2B9" +
- "43C1CD8A6FC63DF4D81C3DA543C9CF2843855EA84E4F959C",
- "C047D46D7F614E4E" +
- "4A7952C79A451F8F7ACA379967E2977C401C626A2ED70D74" +
- "A63660579A354115BC8C8C8CC3AEA3050686A0CFCDB6FA9C" +
- "F78D4C2165BAF851C6F9B1CD16A2E14C15C6DAAC56C16E75" +
- "FC84A14D58B41622E88B0F1B1995587FD8BAA999CBA98025" +
- "4C8AB9A9691DF7B84D88B639A9A3106DEABEB63748B99C09"
- }
- )
- .addAdditionalInput(
- "606162636465666768696A6B6C6D6E" +
- "6F707172737475767778797A7B7C7D7E7F80818283848586" +
- "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" +
- "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" +
- "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE")
- .addAdditionalInput(
- "A0A1A2A3A4A5A6A7A8A9AAABACADAE" +
- "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" +
- "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" +
- "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" +
- "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E"),
- new DRBGTestVector(
- new SHA512Digest(),
- new SHA512EntropyProvider().get(888),
- true,
- "202122232425262728292A2B2C2D2E2F",
- 256,
- new String[]
- {
- "22EB93A67911DA73" +
- "85D9180C78127DE1A04FF713114C07C9C615F7CC5EF72744" +
- "A2DDCD7C3CB85E65DED8EF5F240FBDCBEBBDE2BAAC8ECF7D" +
- "CBC8AC333E54607AD41DC495D83DF72A05EF55B127C1441C" +
- "9A0EFFDA2C7954DB6C2D04342EB812E5E0B11D6C395F41ED" +
- "A2702ECE5BA479E2DFA18F953097492636C12FE30CE5C968",
- "E66698CFBF1B3F2E" +
- "919C03036E584EAA81CF1C6666240AF05F70637043733954" +
- "D8A1E5A66A04C53C6900FDC145D4A3A80A31F5868ACE9AC9" +
- "4E14E2051F624A05EEA1F8B684AA5410BCE315E76EA07C71" +
- "5D6F34731320FF0DCF78D795E6EFA2DF92B98BE636CDFBA2" +
- "9008DD392112AEC202F2E481CB9D83F987FEA69CD1B368BB"
- }
- )
- .setPersonalizationString(
- "404142434445464748494A4B4C4D4E" +
- "4F505152535455565758595A5B5C5D5E5F60616263646566" +
- "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" +
- "7F808182838485868788898A8B8C8D8E8F90919293949596" +
- "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"),
- new DRBGTestVector(
- new SHA512Digest(),
- new SHA512EntropyProvider().get(888),
- true,
- "202122232425262728292A2B2C2D2E2F",
- 256,
- new String[]
- {
- "7596A76372308BD5" +
- "A5613439934678B35521A94D81ABFE63A21ACF61ABB88B61" +
- "E86A12C37F308F2BBBE32BE4B38D03AE808386494D70EF52" +
- "E9E1365DD18B7784CAB826F31D47579E4D57F69D8BF3152B" +
- "95741946CEBE58571DF58ED39980D9AF44E69F01E8989759" +
- "8E40171101A0E3302838E0AD9E849C01988993CF9F6E5263",
- "DBE5EE36FCD85301" +
- "303E1C3617C1AC5E23C08885D0BEFAAD0C85A0D89F85B9F1" +
- "6ECE3D88A24EB96504F2F13EFA7049621782F5DE2C416A0D" +
- "294CCFE53545C4E309C48E1E285A2B829A574B72B3C2FBE1" +
- "34D01E3706B486F2401B9820E17298A342666918E15B8462" +
- "87F8C5AF2D96B20FAF3D0BB392E15F4A06CDB0DECD1B6AD7"
- }
- )
- .setPersonalizationString(
- "404142434445464748494A4B4C4D4E" +
- "4F505152535455565758595A5B5C5D5E5F60616263646566" +
- "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" +
- "7F808182838485868788898A8B8C8D8E8F90919293949596" +
- "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE")
- .addAdditionalInput(
- "606162636465666768696A6B6C6D6E" +
- "6F707172737475767778797A7B7C7D7E7F80818283848586" +
- "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" +
- "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" +
- "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE")
- .addAdditionalInput(
- "A0A1A2A3A4A5A6A7A8A9AAABACADAE" +
- "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" +
- "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" +
- "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" +
- "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E")
- };
- }
-
- public void performTest()
- throws Exception
- {
- DRBGTestVector[] tests = createTestVectorData();
-
- for (int i = 0; i != tests.length; i++)
- {
- DRBGTestVector tv = tests[i];
-
- byte[] nonce = tv.nonce();
- byte[] personalisationString = tv.personalizationString();
-
- SP80090DRBG d = new HashSP800DRBG(tv.getDigest(), tv.securityStrength(), tv.entropySource(), personalisationString, nonce);
-
- byte[] output = new byte[tv.expectedValue(0).length];
-
- d.generate(output, tv.additionalInput(0), tv.predictionResistance());
-
- byte[] expected = tv.expectedValue(0);
-
- if (!areEqual(expected, output))
- {
- fail("Test #" + (i + 1) + ".1 failed, expected " + new String(Hex.encode(tv.expectedValue(0))) + " got " + new String(Hex.encode(output)));
- }
-
- output = new byte[tv.expectedValue(0).length];
-
- d.generate(output, tv.additionalInput(1), tv.predictionResistance());
-
- expected = tv.expectedValue(1);
- if (!areEqual(expected, output))
- {
- fail("Test #" + (i + 1) + ".2 failed, expected " + new String(Hex.encode(tv.expectedValue(1))) + " got " + new String(Hex.encode(output)));
- }
- }
-
- // Exception tests
- //
- SP80090DRBG d;
- try
- {
- d = new HashSP800DRBG(new SHA256Digest(), 256, new SHA256EntropyProvider().get(128), null, null);
- fail("no exception thrown");
- }
- catch (IllegalArgumentException e)
- {
- if (!e.getMessage().equals("Not enough entropy for security strength required"))
- {
- fail("Wrong exception", e);
- }
- }
-
- try
- {
- d = new HashSP800DRBG(new SHA1Digest(), 256, new SHA256EntropyProvider().get(256), null, null);
- fail("no exception thrown");
- }
- catch (IllegalArgumentException e)
- {
- if (!e.getMessage().equals("Requested security strength is not supported by the derivation function"))
- {
- fail("Wrong exception", e);
- }
- }
- }
-
- private class SHA1EntropyProvider
- extends TestEntropySourceProvider
- {
- SHA1EntropyProvider()
- {
- super(
- Hex.decode(
- "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233343536"
- + "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6"
- + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6"), true);
- }
- }
-
- private class SHA256EntropyProvider
- extends TestEntropySourceProvider
- {
- SHA256EntropyProvider()
- {
- super(Hex.decode(
- "00010203040506" +
- "0708090A0B0C0D0E0F101112131415161718191A1B1C1D1E" +
- "1F202122232425262728292A2B2C2D2E2F30313233343536" +
- "80818283848586" +
- "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" +
- "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" +
- "C0C1C2C3C4C5C6" +
- "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" +
- "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6"), true);
- }
- }
-
- private class SHA384EntropyProvider
- extends TestEntropySourceProvider
- {
- SHA384EntropyProvider()
- {
- super(Hex.decode(
- "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223242526"
- + "2728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F50515253545556"
- + "5758595A5B5C5D5E5F606162636465666768696A6B6C6D6E" +
- "808182838485868788898A8B8C8D8E" +
- "8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6" +
- "A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBE" +
- "BFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6" +
- "D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE" +
- "C0C1C2C3C4C5C6C7C8C9CACBCCCDCE" +
- "CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6" +
- "E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" +
- "FF000102030405060708090A0B0C0D0E0F10111213141516" +
- "1718191A1B1C1D1E1F202122232425262728292A2B2C2D2E"), true);
- }
- }
-
- private class SHA512EntropyProvider
- extends TestEntropySourceProvider
- {
- SHA512EntropyProvider()
- {
- super(Hex.decode(
- "000102030405060708090A0B0C0D0E" +
- "0F101112131415161718191A1B1C1D1E1F20212223242526" +
- "2728292A2B2C2D2E2F303132333435363738393A3B3C3D3E" +
- "3F404142434445464748494A4B4C4D4E4F50515253545556" +
- "5758595A5B5C5D5E5F606162636465666768696A6B6C6D6E" +
- "808182838485868788898A8B8C8D8E" +
- "8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6" +
- "A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBE" +
- "BFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6" +
- "D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE" +
- "C0C1C2C3C4C5C6C7C8C9CACBCCCDCE" +
- "CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6" +
- "E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" +
- "FF000102030405060708090A0B0C0D0E0F10111213141516" +
- "1718191A1B1C1D1E1F202122232425262728292A2B2C2D2E"), true);
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/prng/test/RegressionTest.java b/core/src/test/java/org/bouncycastle/crypto/prng/test/RegressionTest.java
deleted file mode 100644
index 7539f380..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/prng/test/RegressionTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.bouncycastle.crypto.prng.test;
-
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-public class RegressionTest
-{
- public static Test[] tests = {
- new CTRDRBGTest(),
- new DualECDRBGTest(),
- new HashDRBGTest(),
- new HMacDRBGTest(),
- new SP800RandomTest(),
- new FixedSecureRandomTest()
- };
-
- public static void main(
- String[] args)
- {
- for (int i = 0; i != tests.length; i++)
- {
- TestResult result = tests[i].perform();
-
- if (result.getException() != null)
- {
- result.getException().printStackTrace();
- }
-
- System.out.println(result);
- }
- }
-}
-
diff --git a/core/src/test/java/org/bouncycastle/crypto/prng/test/SP800RandomTest.java b/core/src/test/java/org/bouncycastle/crypto/prng/test/SP800RandomTest.java
deleted file mode 100644
index a164f8fc..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/prng/test/SP800RandomTest.java
+++ /dev/null
@@ -1,319 +0,0 @@
-package org.bouncycastle.crypto.prng.test;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.engines.DESedeEngine;
-import org.bouncycastle.crypto.macs.HMac;
-import org.bouncycastle.crypto.prng.SP800SecureRandomBuilder;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class SP800RandomTest
- extends SimpleTest
-{
-
- public String getName()
- {
- return "SP800RandomTest";
- }
-
- private void testHashRandom()
- {
- DRBGTestVector tv = new DRBGTestVector(
- new SHA1Digest(),
- new SHA1EntropyProvider().get(440),
- true,
- "2021222324",
- 80,
- new String[]
- {
- "532CA1165DCFF21C55592687639884AF4BC4B057DF8F41DE653AB44E2ADEC7C9303E75ABE277EDBF",
- "73C2C67C696D686D0C4DBCEB5C2AF7DDF6F020B6874FAE4390F102117ECAAFF54418529A367005A0"
- })
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576");
-
- doHashTest(0, tv);
-
- tv = new DRBGTestVector(
- new SHA1Digest(),
- new SHA1EntropyProvider().get(440),
- false,
- "2021222324",
- 80,
- new String[]
- {
- "AB438BD3B01A0AF85CFEE29F7D7B71621C4908B909124D430E7B406FB1086EA994C582E0D656D989",
- "29D9098F987E7005314A0F51B3DD2B8122F4AED706735DE6AD5DDBF223177C1E5F3AEBC52FAB90B9"
- })
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576");
-
- doHashTest(1, tv);
- }
-
- private void doHashTest(int index, DRBGTestVector tv)
- {
- SP800SecureRandomBuilder rBuild = new SP800SecureRandomBuilder(new SHA1EntropyProvider());
-
- rBuild.setPersonalizationString(tv.personalizationString());
- rBuild.setSecurityStrength(tv.securityStrength());
- rBuild.setEntropyBitsRequired(tv.entropySource().getEntropy().length * 8);
-
- SecureRandom random = rBuild.buildHash(tv.getDigest(), tv.nonce(), tv.predictionResistance());
-
- byte[] expected = tv.expectedValue(0);
- byte[] produced = new byte[expected.length];
-
- random.nextBytes(produced);
-
- if (!Arrays.areEqual(expected, produced))
- {
- fail(index + " SP800 Hash SecureRandom produced incorrect result (1)");
- }
-
- random.nextBytes(produced);
- expected = tv.expectedValue(1);
-
- if (!Arrays.areEqual(expected, produced))
- {
- fail(index + " SP800 Hash SecureRandom produced incorrect result (2)");
- }
- }
-
- private void testHMACRandom()
- {
- DRBGTestVector tv = new DRBGTestVector(
- new SHA1Digest(),
- new SHA1EntropyProvider().get(440),
- true,
- "2021222324",
- 80,
- new String[]
- {
- "6C37FDD729AA40F80BC6AB08CA7CC649794F6998B57081E4220F22C5C283E2C91B8E305AB869C625",
- "CAF57DCFEA393B9236BF691FA456FEA7FDF1DF8361482CA54D5FA723F4C88B4FA504BF03277FA783"
- })
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576");
-
- doHMACTest(tv);
-
- tv = new DRBGTestVector(
- new SHA1Digest(),
- new SHA1EntropyProvider().get(440),
- false,
- "2021222324",
- 80,
- new String[]
- {
- "5A7D3B449F481CB38DF79AD2B1FCC01E57F8135E8C0B22CD0630BFB0127FB5408C8EFC17A929896E",
- "82cf772ec3e84b00fc74f5df104efbfb2428554e9ce367d03aeade37827fa8e9cb6a08196115d948"
- });
-
- doHMACTest(tv);
- }
-
- private void doHMACTest(DRBGTestVector tv)
- {
- SP800SecureRandomBuilder rBuild = new SP800SecureRandomBuilder(new SHA1EntropyProvider());
-
- rBuild.setPersonalizationString(tv.personalizationString());
- rBuild.setSecurityStrength(tv.securityStrength());
- rBuild.setEntropyBitsRequired(tv.entropySource().getEntropy().length * 8);
-
- SecureRandom random = rBuild.buildHMAC(new HMac(tv.getDigest()), tv.nonce(), tv.predictionResistance());
-
- byte[] expected = tv.expectedValue(0);
- byte[] produced = new byte[expected.length];
-
- random.nextBytes(produced);
- if (!Arrays.areEqual(expected, produced))
- {
- fail("SP800 HMAC SecureRandom produced incorrect result (1)");
- }
-
- random.nextBytes(produced);
- expected = tv.expectedValue(1);
-
- if (!Arrays.areEqual(expected, produced))
- {
- fail("SP800 HMAC SecureRandom produced incorrect result (2)");
- }
- }
-
- private void testDualECRandom()
- {
- DRBGTestVector tv = new DRBGTestVector(
- new SHA256Digest(),
- new SHA256EntropyProvider().get(128),
- false,
- "2021222324252627",
- 128,
- new String[]
- {
- "3AB095CC493A8730D70DE923108B2E4710799044FFC27D0A1156250DDF97E8B05ACE055E49F3E3F5B928CCD18317A3E68FCB0B6F0459ADF9ECF79C87",
- "7B902FC35B0AF50F57F8822936D08A96E41B16967C6B1AA0BC05032F0D53919DC587B664C883E2FE8F3948002FCD8BCBFC4706BCAA2075EF6BF41167"
- })
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F");
-
- doDualECTest(1, tv);
-
- tv = new DRBGTestVector(
- new SHA256Digest(),
- new SHA256EntropyProvider().get(128),
- true,
- "2021222324252627",
- 128,
- new String[]
- {
- "8C77288EDBEA9A742464F78D55E33593C1BF5F9D8CD8609D6D53BAC4E4B42252A227A99BAD0F2358B05955CD35723B549401C71C9C1F32F8A2018E24",
- "56ECA61C64F69C1C232E992623C71418BD0B96D783118FAAD94A09E3A9DB74D15E805BA7F14625995CA77612B2EF7A05863699ECBABF70D3D422C014"
- });
-
- doDualECTest(2, tv);
- }
-
- private void doDualECTest(int index, DRBGTestVector tv)
- {
- SP800SecureRandomBuilder rBuild = new SP800SecureRandomBuilder(new SHA256EntropyProvider());
-
- rBuild.setPersonalizationString(tv.personalizationString());
- rBuild.setSecurityStrength(tv.securityStrength());
- rBuild.setEntropyBitsRequired(tv.securityStrength());
-
- SecureRandom random = rBuild.buildDualEC(tv.getDigest(), tv.nonce(), tv.predictionResistance());
-
- byte[] expected = tv.expectedValue(0);
- byte[] produced = new byte[expected.length];
-
- random.nextBytes(produced);
- if (!Arrays.areEqual(expected, produced))
- {
- fail(index + " SP800 Dual EC SecureRandom produced incorrect result (1)");
- }
-
- random.nextBytes(produced);
- expected = tv.expectedValue(1);
-
- if (!Arrays.areEqual(expected, produced))
- {
- fail(index + " SP800 Dual EC SecureRandom produced incorrect result (2)");
- }
- }
-
- private void testCTRRandom()
- {
- DRBGTestVector tv = new DRBGTestVector(
- new DESedeEngine(), 168,
- new Bit232EntropyProvider().get(232),
- false,
- "20212223242526",
- 112,
- new String[]
- {
- "ABC88224514D0316EA3D48AEE3C9A2B4",
- "D3D3F372E43E7ABDC4FA293743EED076"
- }
- );
-
- doCTRTest(tv);
-
- tv = new DRBGTestVector(
- new DESedeEngine(), 168,
- new Bit232EntropyProvider().get(232),
- true,
- "20212223242526",
- 112,
- new String[]
- {
- "64983055D014550B39DE699E43130B64",
- "035FDDA8582A2214EC722C410A8D95D3"
- }
- )
- .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C");
-
- doCTRTest(tv);
- }
-
- private void doCTRTest(DRBGTestVector tv)
- {
- SP800SecureRandomBuilder rBuild = new SP800SecureRandomBuilder(new Bit232EntropyProvider());
-
- rBuild.setPersonalizationString(tv.personalizationString());
- rBuild.setSecurityStrength(tv.securityStrength());
- rBuild.setEntropyBitsRequired(tv.entropySource().getEntropy().length * 8);
-
- SecureRandom random = rBuild.buildCTR(tv.getCipher(), tv.keySizeInBits(), tv.nonce(), tv.predictionResistance());
-
- byte[] expected = tv.expectedValue(0);
- byte[] produced = new byte[expected.length];
-
- random.nextBytes(produced);
- if (!Arrays.areEqual(expected, produced))
- {
- fail("SP800 CTR SecureRandom produced incorrect result (1)");
- }
-
- random.nextBytes(produced);
- expected = tv.expectedValue(1);
-
- if (!Arrays.areEqual(expected, produced))
- {
- fail("SP800 CTR SecureRandom produced incorrect result (2)");
- }
- }
-
- public void performTest()
- throws Exception
- {
- testHashRandom();
- testHMACRandom();
- testCTRRandom();
- testDualECRandom();
- }
-
- public static void main(String[] args)
- {
- runTest(new SP800RandomTest());
- }
-
- // for HMAC/Hash
- private class SHA1EntropyProvider
- extends TestEntropySourceProvider
- {
- SHA1EntropyProvider()
- {
- super(
- Hex.decode(
- "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233343536"
- + "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6"
- + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6"), true);
- }
- }
-
- // for Dual EC
- private class SHA256EntropyProvider
- extends TestEntropySourceProvider
- {
- SHA256EntropyProvider()
- {
- super(Hex.decode(
- "000102030405060708090A0B0C0D0E0F " +
- "808182838485868788898A8B8C8D8E8F" +
- "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"), true);
- }
- }
-
- private class Bit232EntropyProvider
- extends TestEntropySourceProvider
- {
- Bit232EntropyProvider()
- {
- super(Hex.decode(
- "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C" +
- "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C" +
- "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDC"), true);
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/prng/test/TestEntropySourceProvider.java b/core/src/test/java/org/bouncycastle/crypto/prng/test/TestEntropySourceProvider.java
deleted file mode 100644
index 64e75958..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/prng/test/TestEntropySourceProvider.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.bouncycastle.crypto.prng.test;
-
-import org.bouncycastle.crypto.prng.EntropySource;
-import org.bouncycastle.crypto.prng.EntropySourceProvider;
-
-public class TestEntropySourceProvider
- implements EntropySourceProvider
-{
- private final byte[] data;
- private final boolean isPredictionResistant;
-
- protected TestEntropySourceProvider(byte[] data, boolean isPredictionResistant)
- {
- this.data = data;
- this.isPredictionResistant = isPredictionResistant;
- }
-
- public EntropySource get(final int bitsRequired)
- {
- return new EntropySource()
- {
- int index = 0;
-
- public boolean isPredictionResistant()
- {
- return isPredictionResistant;
- }
-
- public byte[] getEntropy()
- {
- byte[] rv = new byte[bitsRequired / 8];
-
- System.arraycopy(data, index, rv, 0, rv.length);
-
- index += bitsRequired / 8;
-
- return rv;
- }
-
- public int entropySize()
- {
- return bitsRequired;
- }
- };
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/AEADTestUtil.java b/core/src/test/java/org/bouncycastle/crypto/test/AEADTestUtil.java
deleted file mode 100644
index 5ffa72a1..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/AEADTestUtil.java
+++ /dev/null
@@ -1,474 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.OutputLengthException;
-import org.bouncycastle.crypto.modes.AEADBlockCipher;
-import org.bouncycastle.crypto.params.AEADParameters;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestFailedException;
-
-public class AEADTestUtil
-{
- public static void testTampering(Test test, AEADBlockCipher cipher, CipherParameters params)
- throws InvalidCipherTextException
- {
- byte[] plaintext = new byte[1000];
- for (int i = 0; i < plaintext.length; i++)
- {
- plaintext[i] = (byte)i;
- }
- cipher.init(true, params);
-
- byte[] ciphertext = new byte[cipher.getOutputSize(plaintext.length)];
- int len = cipher.processBytes(plaintext, 0, plaintext.length, ciphertext, 0);
- cipher.doFinal(ciphertext, len);
-
- int macLength = cipher.getMac().length;
-
- // Test tampering with a single byte
- cipher.init(false, params);
- byte[] tampered = new byte[ciphertext.length];
- byte[] output = new byte[plaintext.length];
- System.arraycopy(ciphertext, 0, tampered, 0, tampered.length);
- tampered[0] += 1;
-
- cipher.processBytes(tampered, 0, tampered.length, output, 0);
- try
- {
- cipher.doFinal(output, 0);
- throw new TestFailedException(
- new SimpleTestResult(false, test + " : tampering of ciphertext not detected."));
- }
- catch (InvalidCipherTextException e)
- {
- // Expected
- }
-
- // Test truncation of ciphertext to < tag length
- cipher.init(false, params);
- byte[] truncated = new byte[macLength - 1];
- System.arraycopy(ciphertext, 0, truncated, 0, truncated.length);
-
- cipher.processBytes(truncated, 0, truncated.length, output, 0);
- try
- {
- cipher.doFinal(output, 0);
- fail(test, "tampering of ciphertext not detected.");
- }
- catch (InvalidCipherTextException e)
- {
- // Expected
- }
- }
-
- private static void fail(Test test, String message)
- {
- throw new TestFailedException(SimpleTestResult.failed(test, message));
- }
-
- private static void fail(Test test, String message, String expected, String result)
- {
- throw new TestFailedException(SimpleTestResult.failed(test, message, expected, result));
- }
-
- public static void testReset(Test test, AEADBlockCipher cipher1, AEADBlockCipher cipher2, CipherParameters params)
- throws InvalidCipherTextException
- {
- cipher1.init(true, params);
-
- byte[] plaintext = new byte[1000];
- byte[] ciphertext = new byte[cipher1.getOutputSize(plaintext.length)];
-
- // Establish baseline answer
- crypt(cipher1, plaintext, ciphertext);
-
- // Test encryption resets
- checkReset(test, cipher1, params, true, plaintext, ciphertext);
-
- // Test decryption resets with fresh instance
- cipher2.init(false, params);
- checkReset(test, cipher2, params, false, ciphertext, plaintext);
- }
-
- private static void checkReset(Test test,
- AEADBlockCipher cipher,
- CipherParameters params,
- boolean encrypt,
- byte[] pretext,
- byte[] posttext)
- throws InvalidCipherTextException
- {
- // Do initial run
- byte[] output = new byte[posttext.length];
- crypt(cipher, pretext, output);
-
- // Check encrypt resets cipher
- crypt(cipher, pretext, output);
- if (!Arrays.areEqual(output, posttext))
- {
- fail(test, (encrypt ? "Encrypt" : "Decrypt") + " did not reset cipher.");
- }
-
- // Check init resets data
- cipher.processBytes(pretext, 0, 100, output, 0);
- cipher.init(encrypt, params);
-
- try
- {
- crypt(cipher, pretext, output);
- }
- catch (DataLengthException e)
- {
- fail(test, "Init did not reset data.");
- }
- if (!Arrays.areEqual(output, posttext))
- {
- fail(test, "Init did not reset data.", new String(Hex.encode(posttext)), new String(Hex.encode(output)));
- }
-
- // Check init resets AD
- cipher.processAADBytes(pretext, 0, 100);
- cipher.init(encrypt, params);
-
- try
- {
- crypt(cipher, pretext, output);
- }
- catch (DataLengthException e)
- {
- fail(test, "Init did not reset additional data.");
- }
- if (!Arrays.areEqual(output, posttext))
- {
- fail(test, "Init did not reset additional data.");
- }
-
- // Check reset resets data
- cipher.processBytes(pretext, 0, 100, output, 0);
- cipher.reset();
-
- try
- {
- crypt(cipher, pretext, output);
- }
- catch (DataLengthException e)
- {
- fail(test, "Init did not reset data.");
- }
- if (!Arrays.areEqual(output, posttext))
- {
- fail(test, "Reset did not reset data.");
- }
-
- // Check reset resets AD
- cipher.processAADBytes(pretext, 0, 100);
- cipher.reset();
-
- try
- {
- crypt(cipher, pretext, output);
- }
- catch (DataLengthException e)
- {
- fail(test, "Init did not reset data.");
- }
- if (!Arrays.areEqual(output, posttext))
- {
- fail(test, "Reset did not reset additional data.");
- }
- }
-
- private static void crypt(AEADBlockCipher cipher, byte[] plaintext, byte[] output)
- throws InvalidCipherTextException
- {
- int len = cipher.processBytes(plaintext, 0, plaintext.length, output, 0);
- cipher.doFinal(output, len);
- }
-
- public static void testOutputSizes(Test test, AEADBlockCipher cipher, AEADParameters params)
- throws IllegalStateException,
- InvalidCipherTextException
- {
- int maxPlaintext = cipher.getUnderlyingCipher().getBlockSize() * 10;
- byte[] plaintext = new byte[maxPlaintext];
- byte[] ciphertext = new byte[maxPlaintext * 2];
-
- // Check output size calculations for truncated ciphertext lengths
- cipher.init(true, params);
- cipher.doFinal(ciphertext, 0);
- int macLength = cipher.getMac().length;
-
- cipher.init(false, params);
- for (int i = 0; i < macLength; i++)
- {
- cipher.reset();
- if (cipher.getUpdateOutputSize(i) != 0)
- {
- fail(test, "AE cipher should not produce update output with ciphertext length <= macSize");
- }
- if (cipher.getOutputSize(i) != 0)
- {
- fail(test, "AE cipher should not produce output with ciphertext length <= macSize");
- }
- }
-
- for (int i = 0; i < plaintext.length; i++)
- {
- cipher.init(true, params);
- int expectedCTUpdateSize = cipher.getUpdateOutputSize(i);
- int expectedCTOutputSize = cipher.getOutputSize(i);
-
- if (expectedCTUpdateSize < 0)
- {
- fail(test, "Encryption update output size should not be < 0 for size " + i);
- }
-
- if (expectedCTOutputSize < 0)
- {
- fail(test, "Encryption update output size should not be < 0 for size " + i);
- }
-
- int actualCTSize = cipher.processBytes(plaintext, 0, i, ciphertext, 0);
-
- if (expectedCTUpdateSize != actualCTSize)
- {
- fail(test, "Encryption update output size did not match calculated for plaintext length " + i,
- String.valueOf(expectedCTUpdateSize), String.valueOf(actualCTSize));
- }
-
- actualCTSize += cipher.doFinal(ciphertext, actualCTSize);
-
- if (expectedCTOutputSize != actualCTSize)
- {
- fail(test, "Encryption actual final output size did not match calculated for plaintext length " + i,
- String.valueOf(expectedCTOutputSize), String.valueOf(actualCTSize));
- }
-
- cipher.init(false, params);
- int expectedPTUpdateSize = cipher.getUpdateOutputSize(actualCTSize);
- int expectedPTOutputSize = cipher.getOutputSize(actualCTSize);
-
- if (expectedPTOutputSize != i)
- {
- fail(test, "Decryption update output size did not original plaintext length " + i,
- String.valueOf(expectedPTUpdateSize), String.valueOf(i));
- }
-
- int actualPTSize = cipher.processBytes(ciphertext, 0, actualCTSize, plaintext, 0);
-
- if (expectedPTUpdateSize != actualPTSize)
- {
- fail(test, "Decryption update output size did not match calculated for plaintext length " + i,
- String.valueOf(expectedPTUpdateSize), String.valueOf(actualPTSize));
- }
-
- actualPTSize += cipher.doFinal(plaintext, actualPTSize);
-
- if (expectedPTOutputSize != actualPTSize)
- {
- fail(test, "Decryption update output size did not match calculated for plaintext length " + i,
- String.valueOf(expectedPTOutputSize), String.valueOf(actualPTSize));
- }
-
- }
- }
-
- public static void testBufferSizeChecks(Test test, AEADBlockCipher cipher, AEADParameters params)
- throws IllegalStateException,
- InvalidCipherTextException
- {
- int blockSize = cipher.getUnderlyingCipher().getBlockSize();
- int maxPlaintext = (blockSize * 10);
- byte[] plaintext = new byte[maxPlaintext];
-
-
- cipher.init(true, params);
-
- int expectedUpdateOutputSize = cipher.getUpdateOutputSize(plaintext.length);
- byte[] ciphertext = new byte[cipher.getOutputSize(plaintext.length)];
-
- try
- {
- cipher.processBytes(new byte[maxPlaintext - 1], 0, maxPlaintext, new byte[expectedUpdateOutputSize], 0);
- fail(test, "processBytes should validate input buffer length");
- }
- catch (DataLengthException e)
- {
- // Expected
- }
- cipher.reset();
-
- if (expectedUpdateOutputSize > 0)
- {
- int outputTrigger = 0;
- // Process bytes until output would be produced
- for(int i = 0; i < plaintext.length; i++) {
- if (cipher.getUpdateOutputSize(1) != 0)
- {
- outputTrigger = i + 1;
- break;
- }
- cipher.processByte(plaintext[i], ciphertext, 0);
- }
- if (outputTrigger == 0)
- {
- fail(test, "Failed to find output trigger size");
- }
- try
- {
- cipher.processByte(plaintext[0], new byte[cipher.getUpdateOutputSize(1) - 1], 0);
- fail(test, "Encrypt processByte should validate output buffer length");
- }
- catch (OutputLengthException e)
- {
- // Expected
- }
- cipher.reset();
-
- // Repeat checking with entire input at once
- try
- {
- cipher.processBytes(plaintext, 0, outputTrigger,
- new byte[cipher.getUpdateOutputSize(outputTrigger) - 1], 0);
- fail(test, "Encrypt processBytes should validate output buffer length");
- }
- catch (OutputLengthException e)
- {
- // Expected
- }
- cipher.reset();
-
- }
-
- // Remember the actual ciphertext for later
- int actualOutputSize = cipher.processBytes(plaintext, 0, plaintext.length, ciphertext, 0);
- actualOutputSize += cipher.doFinal(ciphertext, actualOutputSize);
- int macSize = cipher.getMac().length;
-
- cipher.reset();
- try
- {
- cipher.processBytes(plaintext, 0, plaintext.length, ciphertext, 0);
- cipher.doFinal(new byte[cipher.getOutputSize(0) - 1], 0);
- fail(test, "Encrypt doFinal should validate output buffer length");
- }
- catch (OutputLengthException e)
- {
- // Expected
- }
-
- // Decryption tests
-
- cipher.init(false, params);
- expectedUpdateOutputSize = cipher.getUpdateOutputSize(actualOutputSize);
-
- if (expectedUpdateOutputSize > 0)
- {
- // Process bytes until output would be produced
- int outputTrigger = 0;
- for (int i = 0; i < plaintext.length; i++)
- {
- if (cipher.getUpdateOutputSize(1) != 0)
- {
- outputTrigger = i + 1;
- break;
- }
- cipher.processByte(ciphertext[i], plaintext, 0);
- }
- if (outputTrigger == 0)
- {
- fail(test, "Failed to find output trigger size");
- }
-
- try
- {
- cipher.processByte(ciphertext[0], new byte[cipher.getUpdateOutputSize(1) - 1], 0);
- fail(test, "Decrypt processByte should validate output buffer length");
- }
- catch (OutputLengthException e)
- {
- // Expected
- }
- cipher.reset();
-
- // Repeat test with processBytes
- try
- {
- cipher.processBytes(ciphertext, 0, outputTrigger,
- new byte[cipher.getUpdateOutputSize(outputTrigger) - 1], 0);
- fail(test, "Decrypt processBytes should validate output buffer length");
- }
- catch (OutputLengthException e)
- {
- // Expected
- }
- }
-
- cipher.reset();
- // Data less than mac length should fail before output length check
- try
- {
- // Assumes AE cipher on decrypt can't return any data until macSize bytes are received
- if (cipher.processBytes(ciphertext, 0, macSize - 1, plaintext, 0) != 0)
- {
- fail(test, "AE cipher unexpectedly produced output");
- }
- cipher.doFinal(new byte[0], 0);
- fail(test, "Decrypt doFinal should check ciphertext length");
- }
- catch (InvalidCipherTextException e)
- {
- // Expected
- }
-
- try
- {
- // Search through plaintext lengths until one is found that creates >= 1 buffered byte
- // during decryption of ciphertext for doFinal to handle
- for (int i = 2; i < plaintext.length; i++)
- {
- cipher.init(true, params);
- int encrypted = cipher.processBytes(plaintext, 0, i, ciphertext, 0);
- encrypted += cipher.doFinal(ciphertext, encrypted);
-
- cipher.init(false, params);
- cipher.processBytes(ciphertext, 0, encrypted - 1, plaintext, 0);
- if (cipher.processByte(ciphertext[encrypted - 1], plaintext, 0) == 0)
- {
- cipher.doFinal(new byte[cipher.getOutputSize(0) - 1], 0);
- fail(test, "Decrypt doFinal should check output length");
- cipher.reset();
-
- // Truncated Mac should be reported in preference to inability to output
- // buffered plaintext byte
- try
- {
- cipher.processBytes(ciphertext, 0, actualOutputSize - 1, plaintext, 0);
- cipher.doFinal(new byte[cipher.getOutputSize(0) - 1], 0);
- fail(test, "Decrypt doFinal should check ciphertext length");
- }
- catch (InvalidCipherTextException e)
- {
- // Expected
- }
- cipher.reset();
- }
- }
- fail(test, "Decrypt doFinal test couldn't find a ciphertext length that buffered for doFinal");
- }
- catch (OutputLengthException e)
- {
- // Expected
- }
- }
-
- static AEADParameters reuseKey(AEADParameters p)
- {
- return new AEADParameters(null, p.getMacSize(), p.getNonce(), p.getAssociatedText());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/AESFastTest.java b/core/src/test/java/org/bouncycastle/crypto/test/AESFastTest.java
deleted file mode 100644
index c94b1182..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/AESFastTest.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.engines.AESFastEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * Test vectors from the NIST standard tests and Brian Gladman's vector set
- * <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">
- * http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
- */
-public class AESFastTest
- extends CipherTest
-{
- static SimpleTest[] tests =
- {
- new BlockCipherVectorTest(0, new AESFastEngine(),
- new KeyParameter(Hex.decode("80000000000000000000000000000000")),
- "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
- new BlockCipherVectorTest(1, new AESFastEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000080")),
- "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
- new BlockCipherMonteCarloTest(2, 10000, new AESFastEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000")),
- "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
- new BlockCipherMonteCarloTest(3, 10000, new AESFastEngine(),
- new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")),
- "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
- new BlockCipherVectorTest(4, new AESFastEngine(),
- new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
- "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
- new BlockCipherMonteCarloTest(5, 10000, new AESFastEngine(),
- new KeyParameter(Hex.decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
- "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
- new BlockCipherVectorTest(6, new AESFastEngine(),
- new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
- "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
- new BlockCipherMonteCarloTest(7, 10000, new AESFastEngine(),
- new KeyParameter(Hex.decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
- "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168"),
- new BlockCipherVectorTest(8, new AESFastEngine(),
- new KeyParameter(Hex.decode("80000000000000000000000000000000")),
- "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
- new BlockCipherVectorTest(9, new AESFastEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000080")),
- "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
- new BlockCipherMonteCarloTest(10, 10000, new AESFastEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000")),
- "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
- new BlockCipherMonteCarloTest(11, 10000, new AESFastEngine(),
- new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")),
- "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
- new BlockCipherVectorTest(12, new AESFastEngine(),
- new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
- "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
- new BlockCipherMonteCarloTest(13, 10000, new AESFastEngine(),
- new KeyParameter(Hex.decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
- "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
- new BlockCipherVectorTest(14, new AESFastEngine(),
- new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
- "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
- new BlockCipherMonteCarloTest(15, 10000, new AESFastEngine(),
- new KeyParameter(Hex.decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
- "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168"),
- new BlockCipherVectorTest(16, new AESFastEngine(),
- new KeyParameter(Hex.decode("80000000000000000000000000000000")),
- "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
- new BlockCipherVectorTest(17, new AESFastEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000080")),
- "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
- new BlockCipherMonteCarloTest(18, 10000, new AESFastEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000")),
- "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
- new BlockCipherMonteCarloTest(19, 10000, new AESFastEngine(),
- new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")),
- "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
- new BlockCipherVectorTest(20, new AESFastEngine(),
- new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
- "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
- new BlockCipherMonteCarloTest(21, 10000, new AESFastEngine(),
- new KeyParameter(Hex.decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
- "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
- new BlockCipherVectorTest(22, new AESFastEngine(),
- new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
- "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
- new BlockCipherMonteCarloTest(23, 10000, new AESFastEngine(),
- new KeyParameter(Hex.decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
- "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168")
- };
-
- private BlockCipher _engine = new AESFastEngine();
-
- AESFastTest()
- {
- super(tests, new AESFastEngine(), new KeyParameter(new byte[16]));
- }
-
- public String getName()
- {
- return "AESFast";
- }
-
- public void performTest()
- throws Exception
- {
- super.performTest();
-
- byte[] keyBytes = new byte[16];
-
- _engine.init(true, new KeyParameter(keyBytes));
-
- //
- // init tests
- //
- try
- {
- byte[] dudKey = new byte[6];
-
- _engine.init(true, new KeyParameter(dudKey));
-
- fail("failed key length check");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- try
- {
- byte[] iv = new byte[16];
-
- _engine.init(true, new ParametersWithIV(null, iv));
-
- fail("failed parameter check");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new AESFastTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/AESLightTest.java b/core/src/test/java/org/bouncycastle/crypto/test/AESLightTest.java
deleted file mode 100644
index 5e989f42..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/AESLightTest.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.engines.AESLightEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * Test vectors from the NIST standard tests and Brian Gladman's vector set
- * <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">
- * http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
- */
-public class AESLightTest
- extends CipherTest
-{
- static SimpleTest[] tests =
- {
- new BlockCipherVectorTest(0, new AESLightEngine(),
- new KeyParameter(Hex.decode("80000000000000000000000000000000")),
- "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
- new BlockCipherVectorTest(1, new AESLightEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000080")),
- "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
- new BlockCipherMonteCarloTest(2, 10000, new AESLightEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000")),
- "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
- new BlockCipherMonteCarloTest(3, 10000, new AESLightEngine(),
- new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")),
- "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
- new BlockCipherVectorTest(4, new AESLightEngine(),
- new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
- "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
- new BlockCipherMonteCarloTest(5, 10000, new AESLightEngine(),
- new KeyParameter(Hex.decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
- "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
- new BlockCipherVectorTest(6, new AESLightEngine(),
- new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
- "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
- new BlockCipherMonteCarloTest(7, 10000, new AESLightEngine(),
- new KeyParameter(Hex.decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
- "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168"),
- new BlockCipherVectorTest(8, new AESLightEngine(),
- new KeyParameter(Hex.decode("80000000000000000000000000000000")),
- "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
- new BlockCipherVectorTest(9, new AESLightEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000080")),
- "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
- new BlockCipherMonteCarloTest(10, 10000, new AESLightEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000")),
- "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
- new BlockCipherMonteCarloTest(11, 10000, new AESLightEngine(),
- new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")),
- "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
- new BlockCipherVectorTest(12, new AESLightEngine(),
- new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
- "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
- new BlockCipherMonteCarloTest(13, 10000, new AESLightEngine(),
- new KeyParameter(Hex.decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
- "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
- new BlockCipherVectorTest(14, new AESLightEngine(),
- new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
- "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
- new BlockCipherMonteCarloTest(15, 10000, new AESLightEngine(),
- new KeyParameter(Hex.decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
- "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168"),
- new BlockCipherVectorTest(16, new AESLightEngine(),
- new KeyParameter(Hex.decode("80000000000000000000000000000000")),
- "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
- new BlockCipherVectorTest(17, new AESLightEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000080")),
- "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
- new BlockCipherMonteCarloTest(18, 10000, new AESLightEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000")),
- "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
- new BlockCipherMonteCarloTest(19, 10000, new AESLightEngine(),
- new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")),
- "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
- new BlockCipherVectorTest(20, new AESLightEngine(),
- new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
- "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
- new BlockCipherMonteCarloTest(21, 10000, new AESLightEngine(),
- new KeyParameter(Hex.decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
- "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
- new BlockCipherVectorTest(22, new AESLightEngine(),
- new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
- "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
- new BlockCipherMonteCarloTest(23, 10000, new AESLightEngine(),
- new KeyParameter(Hex.decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
- "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168")
- };
-
- private BlockCipher _engine = new AESLightEngine();
-
- AESLightTest()
- {
- super(tests, new AESLightEngine(), new KeyParameter(new byte[16]));
- }
-
- public String getName()
- {
- return "AESLight";
- }
-
- public void performTest()
- throws Exception
- {
- super.performTest();
-
- byte[] keyBytes = new byte[16];
-
- _engine.init(true, new KeyParameter(keyBytes));
-
- //
- // init tests
- //
- try
- {
- byte[] dudKey = new byte[6];
-
- _engine.init(true, new KeyParameter(dudKey));
-
- fail("failed key length check");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- try
- {
- byte[] iv = new byte[16];
-
- _engine.init(true, new ParametersWithIV(null, iv));
-
- fail("failed parameter check");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new AESLightTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/AESTest.java b/core/src/test/java/org/bouncycastle/crypto/test/AESTest.java
deleted file mode 100644
index 84be7dee..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/AESTest.java
+++ /dev/null
@@ -1,442 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.BufferedBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.engines.AESEngine;
-import org.bouncycastle.crypto.modes.CBCBlockCipher;
-import org.bouncycastle.crypto.modes.CFBBlockCipher;
-import org.bouncycastle.crypto.modes.OFBBlockCipher;
-import org.bouncycastle.crypto.modes.SICBlockCipher;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * Test vectors from the NIST standard tests and Brian Gladman's vector set
- * <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">
- * http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
- */
-public class AESTest
- extends CipherTest
-{
- private static final byte[] tData = Hex.decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114F3F6752AE8D7831138F041560631B1145A01020304050607");
- private static final byte[] outCBC1 = Hex.decode("a444a9a4d46eb30cb7ed34d62873a89f8fdf2bf8a54e1aeadd06fd85c9cb46f021ee7cd4f418fa0bb72e9d07c70d5d20");
- private static final byte[] outCBC2 = Hex.decode("585681354f0e01a86b32f94ebb6a675045d923cf201263c2aaecca2b4de82da0edd74ca5efd654c688f8a58e61955b11");
- private static final byte[] outSIC1 = Hex.decode("82a1744e8ebbd053ca72362d5e570326e0b6fdaf824ab673fbf029042886b23c75129a015852913790f81f94447475a0");
- private static final byte[] outSIC2 = Hex.decode("146cbb581d9e12c3333dd9c736fbb93043c92019f78580da48f81f80b3f551d58ea836fed480fc6912fefa9c5c89cc24");
- private static final byte[] outCFB1 = Hex.decode("82a1744e8ebbd053ca72362d5e5703264b4182de3208c374b8ac4fa36af9c5e5f4f87d1e3b67963d06acf5eb13914c90");
- private static final byte[] outCFB2 = Hex.decode("146cbb581d9e12c3333dd9c736fbb9303c8a3eb5185e2809e9d3c28e25cc2d2b6f5c11ee28d6530f72c412b1438a816a");
- private static final byte[] outOFB1 = Hex.decode("82a1744e8ebbd053ca72362d5e5703261ebf1fdbec05e57b3465b583132f84b43bf95b2c89040ad1677b22d42db69a7a");
- private static final byte[] outOFB2 = Hex.decode("146cbb581d9e12c3333dd9c736fbb9309ea4c2a7696c84959a2dada49f2f1c5905db1f0cec3a31acbc4701e74ab05e1f");
-
- static SimpleTest[] tests =
- {
- new BlockCipherVectorTest(0, new AESEngine(),
- new KeyParameter(Hex.decode("80000000000000000000000000000000")),
- "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
- new BlockCipherVectorTest(1, new AESEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000080")),
- "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
- new BlockCipherMonteCarloTest(2, 10000, new AESEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000")),
- "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
- new BlockCipherMonteCarloTest(3, 10000, new AESEngine(),
- new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")),
- "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
- new BlockCipherVectorTest(4, new AESEngine(),
- new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
- "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
- new BlockCipherMonteCarloTest(5, 10000, new AESEngine(),
- new KeyParameter(Hex.decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
- "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
- new BlockCipherVectorTest(6, new AESEngine(),
- new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
- "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
- new BlockCipherMonteCarloTest(7, 10000, new AESEngine(),
- new KeyParameter(Hex.decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
- "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168"),
- new BlockCipherVectorTest(8, new AESEngine(),
- new KeyParameter(Hex.decode("80000000000000000000000000000000")),
- "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
- new BlockCipherVectorTest(9, new AESEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000080")),
- "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
- new BlockCipherMonteCarloTest(10, 10000, new AESEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000")),
- "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
- new BlockCipherMonteCarloTest(11, 10000, new AESEngine(),
- new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")),
- "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
- new BlockCipherVectorTest(12, new AESEngine(),
- new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
- "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
- new BlockCipherMonteCarloTest(13, 10000, new AESEngine(),
- new KeyParameter(Hex.decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
- "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
- new BlockCipherVectorTest(14, new AESEngine(),
- new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
- "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
- new BlockCipherMonteCarloTest(15, 10000, new AESEngine(),
- new KeyParameter(Hex.decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
- "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168"),
- new BlockCipherVectorTest(16, new AESEngine(),
- new KeyParameter(Hex.decode("80000000000000000000000000000000")),
- "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
- new BlockCipherVectorTest(17, new AESEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000080")),
- "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
- new BlockCipherMonteCarloTest(18, 10000, new AESEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000")),
- "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
- new BlockCipherMonteCarloTest(19, 10000, new AESEngine(),
- new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")),
- "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
- new BlockCipherVectorTest(20, new AESEngine(),
- new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
- "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
- new BlockCipherMonteCarloTest(21, 10000, new AESEngine(),
- new KeyParameter(Hex.decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
- "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
- new BlockCipherVectorTest(22, new AESEngine(),
- new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
- "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
- new BlockCipherMonteCarloTest(23, 10000, new AESEngine(),
- new KeyParameter(Hex.decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
- "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168")
- };
-
- private BlockCipher _engine = new AESEngine();
-
- public AESTest()
- {
- super(tests, new AESEngine(), new KeyParameter(new byte[16]));
- }
-
- public String getName()
- {
- return "AES";
- }
-
- private void testNullSIC()
- throws InvalidCipherTextException
- {
- BufferedBlockCipher b = new BufferedBlockCipher(new SICBlockCipher(new AESEngine()));
- KeyParameter kp = new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917"));
-
- b.init(true, new ParametersWithIV(kp, new byte[16]));
-
- byte[] out = new byte[b.getOutputSize(tData.length)];
-
- int len = b.processBytes(tData, 0, tData.length, out, 0);
-
- len += b.doFinal(out, len);
-
- if (!areEqual(outSIC1, out))
- {
- fail("no match on first nullSIC check");
- }
-
- b.init(true, new ParametersWithIV(null, Hex.decode("000102030405060708090a0b0c0d0e0f")));
-
- len = b.processBytes(tData, 0, tData.length, out, 0);
-
- len += b.doFinal(out, len);
-
- if (!areEqual(outSIC2, out))
- {
- fail("no match on second nullSIC check");
- }
- }
-
- private void testNullCBC()
- throws InvalidCipherTextException
- {
- BufferedBlockCipher b = new BufferedBlockCipher(new CBCBlockCipher(new AESEngine()));
- KeyParameter kp = new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917"));
-
- b.init(true, new ParametersWithIV(kp, new byte[16]));
-
- byte[] out = new byte[b.getOutputSize(tData.length)];
-
- int len = b.processBytes(tData, 0, tData.length, out, 0);
-
- len += b.doFinal(out, len);
-
- if (!areEqual(outCBC1, out))
- {
- fail("no match on first nullCBC check");
- }
-
- b.init(true, new ParametersWithIV(null, Hex.decode("000102030405060708090a0b0c0d0e0f")));
-
- len = b.processBytes(tData, 0, tData.length, out, 0);
-
- len += b.doFinal(out, len);
-
- if (!areEqual(outCBC2, out))
- {
- fail("no match on second nullCBC check");
- }
- }
-
- private void testNullOFB()
- throws InvalidCipherTextException
- {
- BufferedBlockCipher b = new BufferedBlockCipher(new OFBBlockCipher(new AESEngine(), 128));
- KeyParameter kp = new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917"));
-
- b.init(true, new ParametersWithIV(kp, new byte[16]));
-
- byte[] out = new byte[b.getOutputSize(tData.length)];
-
- int len = b.processBytes(tData, 0, tData.length, out, 0);
-
- len += b.doFinal(out, len);
-
- if (!areEqual(outOFB1, out))
- {
- fail("no match on first nullOFB check");
- }
-
- b.init(true, new ParametersWithIV(null, Hex.decode("000102030405060708090a0b0c0d0e0f")));
-
- len = b.processBytes(tData, 0, tData.length, out, 0);
-
- len += b.doFinal(out, len);
-
- if (!areEqual(outOFB2, out))
- {
- fail("no match on second nullOFB check");
- }
- }
-
- private void testNullCFB()
- throws InvalidCipherTextException
- {
- BufferedBlockCipher b = new BufferedBlockCipher(new CFBBlockCipher(new AESEngine(), 128));
- KeyParameter kp = new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917"));
-
- b.init(true, new ParametersWithIV(kp, new byte[16]));
-
- byte[] out = new byte[b.getOutputSize(tData.length)];
-
- int len = b.processBytes(tData, 0, tData.length, out, 0);
-
- len += b.doFinal(out, len);
-
- if (!areEqual(outCFB1, out))
- {
- fail("no match on first nullCFB check");
- }
-
- b.init(true, new ParametersWithIV(null, Hex.decode("000102030405060708090a0b0c0d0e0f")));
-
- len = b.processBytes(tData, 0, tData.length, out, 0);
-
- len += b.doFinal(out, len);
-
- if (!areEqual(outCFB2, out))
- {
- fail("no match on second nullCFB check");
- }
- }
-
- private boolean areEqual(byte[] a, int aOff, byte[] b, int bOff)
- {
- for (int i = bOff; i != b.length; i++)
- {
- if (a[aOff + i - bOff] != b[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- private void skipTest()
- {
- CipherParameters params = new ParametersWithIV(new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")), Hex.decode("00000000000000000000000000000000"));
- SICBlockCipher engine = new SICBlockCipher(new AESEngine());
-
- engine.init(true, params);
-
- SecureRandom rand = new SecureRandom();
- byte[] plain = new byte[5000];
- byte[] cipher = new byte[5000];
-
- rand.nextBytes(plain);
- engine.processBytes(plain, 0, plain.length, cipher, 0);
-
- byte[] fragment = new byte[20];
-
- engine.init(true, params);
-
- engine.skip(10);
-
- if (engine.getPosition() != 10)
- {
- fail("skip position incorrect - 10 got " + engine.getPosition());
- }
-
- engine.processBytes(plain, 10, fragment.length, fragment, 0);
-
- if (!areEqual(cipher, 10, fragment, 0))
- {
- fail("skip forward 10 failed");
- }
-
- engine.skip(1000);
-
- if (engine.getPosition() != 1010 + fragment.length)
- {
- fail("skip position incorrect - " + (1010 + fragment.length) + " got " + engine.getPosition());
- }
-
- engine.processBytes(plain, 1010 + fragment.length, fragment.length, fragment, 0);
-
- if (!areEqual(cipher, 1010 + fragment.length, fragment, 0))
- {
- fail("skip forward 1000 failed");
- }
-
- engine.skip(-10);
-
- if (engine.getPosition() != 1010 + 2 * fragment.length - 10)
- {
- fail("skip position incorrect - " + (1010 + 2 * fragment.length - 10) + " got " + engine.getPosition());
- }
-
- engine.processBytes(plain, 1010 + 2 * fragment.length - 10, fragment.length, fragment, 0);
-
- if (!areEqual(cipher, 1010 + 2 * fragment.length - 10, fragment, 0))
- {
- fail("skip back 10 failed");
- }
-
- engine.skip(-1000);
-
- if (engine.getPosition() != 60)
- {
- fail("skip position incorrect - " + 60 + " got " + engine.getPosition());
- }
-
- engine.processBytes(plain, 60, fragment.length, fragment, 0);
-
- if (!areEqual(cipher, 60, fragment, 0))
- {
- fail("skip back 1000 failed");
- }
-
- long pos = engine.seekTo(1010);
-
- if (pos != 1010)
- {
- fail("position incorrect - " + 1010 + " got " + pos);
- }
-
- engine.processBytes(plain, 1010, fragment.length, fragment, 0);
-
- if (!areEqual(cipher, 1010, fragment, 0))
- {
- fail("seek to 1010 failed");
- }
-
- engine.reset();
-
- for (int i = 0; i != 1000; i++)
- {
- engine.skip(i);
-
- if (engine.getPosition() != i)
- {
- fail("skip forward at wrong position");
- }
-
- engine.processBytes(plain, i, fragment.length, fragment, 0);
-
- if (!areEqual(cipher, i, fragment, 0))
- {
- fail("skip forward i failed: " + i);
- }
-
- if (engine.getPosition() != i + fragment.length)
- {
- fail("cipher at wrong position: " + engine.getPosition() + " [" + i + "]");
- }
-
- engine.skip(-fragment.length);
-
- if (engine.getPosition() != i)
- {
- fail("skip back at wrong position");
- }
-
- engine.processBytes(plain, i, fragment.length, fragment, 0);
-
- if (!areEqual(cipher, i, fragment, 0))
- {
- fail("skip back i failed: " + i);
- }
-
- engine.reset();
- }
- }
-
- public void performTest()
- throws Exception
- {
- super.performTest();
-
- byte[] keyBytes = new byte[16];
-
- _engine.init(true, new KeyParameter(keyBytes));
-
- //
- // init tests
- //
- try
- {
- byte[] dudKey = new byte[6];
-
- _engine.init(true, new KeyParameter(dudKey));
-
- fail("failed key length check");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- try
- {
- byte[] iv = new byte[16];
-
- _engine.init(true, new ParametersWithIV(null, iv));
-
- fail("failed parameter check");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- testNullCBC();
- testNullSIC();
- testNullOFB();
- testNullCFB();
-
- skipTest();
- }
-
- public static void main(
- String[] args)
- {
- runTest(new AESTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/AESVectorFileTest.java b/core/src/test/java/org/bouncycastle/crypto/test/AESVectorFileTest.java
deleted file mode 100644
index cfd48430..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/AESVectorFileTest.java
+++ /dev/null
@@ -1,258 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.engines.AESEngine;
-import org.bouncycastle.crypto.engines.AESFastEngine;
-import org.bouncycastle.crypto.engines.AESLightEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-/**
- * Test vectors from the NIST standard tests and Brian Gladman's vector set
- * <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">
- * http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
- */
-public class AESVectorFileTest
- implements Test
-{
-
- private int countOfTests = 0;
- private int testNum = 0;
-
- protected BlockCipher createNewEngineForTest()
- {
- return new AESEngine();
- }
-
- private Test[] readTestVectors(InputStream inStream)
- {
- // initialize key, plaintext, ciphertext = null
- // read until find BLOCKSIZE=
- // return if not 128
- // read KEYSIZE= or ignore
- // loop
- // read a line
- // if starts with BLOCKSIZE=
- // parse the rest. return if not 128
- // if starts with KEY=
- // parse the rest and set KEY
- // if starts with PT=
- // parse the rest and set plaintext
- // if starts with CT=
- // parse the rest and set ciphertext
- // if starts with TEST= or end of file
- // if key, plaintext, ciphertext are all not null
- // save away their values as the next test
- // until end of file
- List tests = new ArrayList();
- String key = null;
- String plaintext = null;
- String ciphertext = null;
-
- BufferedReader in = new BufferedReader(new InputStreamReader(inStream));
-
- try
- {
- String line = in.readLine();
-
- while (line != null)
- {
- line = line.trim().toLowerCase();
- if (line.startsWith("blocksize="))
- {
- int i = 0;
- try
- {
- i = Integer.parseInt(line.substring(10).trim());
- }
- catch (Exception e)
- {
- }
- if (i != 128)
- {
- return null;
- }
- }
- else if (line.startsWith("keysize="))
- {
- int i = 0;
- try
- {
- i = Integer.parseInt(line.substring(10).trim());
- }
- catch (Exception e)
- {
- }
- if ((i != 128) && (i != 192) && (i != 256))
- {
- return null;
- }
- }
- else if (line.startsWith("key="))
- {
- key = line.substring(4).trim();
- }
- else if (line.startsWith("pt="))
- {
- plaintext = line.substring(3).trim();
- }
- else if (line.startsWith("ct="))
- {
- ciphertext = line.substring(3).trim();
- }
- else if (line.startsWith("test="))
- {
- if ((key != null) && (plaintext != null)
- && (ciphertext != null))
- {
- tests.add(new BlockCipherVectorTest(testNum++,
- createNewEngineForTest(), new KeyParameter(Hex
- .decode(key)), plaintext, ciphertext));
- }
- }
-
- line = in.readLine();
- }
- try
- {
- in.close();
- }
- catch (IOException e)
- {
- }
- }
- catch (IOException e)
- {
- }
- if ((key != null) && (plaintext != null) && (ciphertext != null))
- {
- tests.add(new BlockCipherVectorTest(testNum++,
- createNewEngineForTest(),
- new KeyParameter(Hex.decode(key)), plaintext, ciphertext));
- }
- return (Test[])(tests.toArray(new Test[tests.size()]));
- }
-
- public String getName()
- {
- return "AES";
- }
-
- private TestResult performTestsFromZipFile(File zfile)
- {
- try
- {
- ZipFile inZip = new ZipFile(zfile);
- for (Enumeration files = inZip.entries(); files.hasMoreElements();)
- {
- Test[] tests = null;
- try
- {
- tests = readTestVectors(inZip
- .getInputStream((ZipEntry)(files.nextElement())));
- }
- catch (Exception e)
- {
- return new SimpleTestResult(false, getName() + ": threw "
- + e);
- }
- if (tests != null)
- {
- for (int i = 0; i != tests.length; i++)
- {
- TestResult res = tests[i].perform();
- countOfTests++;
-
- if (!res.isSuccessful())
- {
- return res;
- }
- }
- }
- }
- inZip.close();
- return new SimpleTestResult(true, getName() + ": Okay");
- }
- catch (Exception e)
- {
- return new SimpleTestResult(false, getName() + ": threw " + e);
- }
- }
-
- private static final String[] zipFileNames = { "rijn.tv.ecbnk.zip",
- "rijn.tv.ecbnt.zip", "rijn.tv.ecbvk.zip", "rijn.tv.ecbvt.zip" };
-
- public TestResult perform()
- {
- countOfTests = 0;
- for (int i = 0; i < zipFileNames.length; i++)
- {
- File inf = new File(zipFileNames[i]);
- TestResult res = performTestsFromZipFile(inf);
- if (!res.isSuccessful())
- {
- return res;
- }
- }
- return new SimpleTestResult(true, getName() + ": " + countOfTests
- + " performed Okay");
- }
-
- public static void main(String[] args)
- {
- AESVectorFileTest test = new AESVectorFileTest();
- TestResult result = test.perform();
- System.out.println(result);
-
- test = new AESLightVectorFileTest();
- result = test.perform();
- System.out.println(result);
-
- test = new AESFastVectorFileTest();
- result = test.perform();
- System.out.println(result);
-
- }
-
- private static class AESLightVectorFileTest extends AESVectorFileTest
- {
- protected BlockCipher createNewEngineForTest()
- {
- return new AESLightEngine();
- }
-
- public String getName()
- {
- return "AESLight";
- }
-
- }
-
- private static class AESFastVectorFileTest extends AESVectorFileTest
- {
- protected BlockCipher createNewEngineForTest()
- {
- return new AESFastEngine();
- }
-
- public String getName()
- {
- return "AESFast";
- }
-
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/AESWrapPadTest.java b/core/src/test/java/org/bouncycastle/crypto/test/AESWrapPadTest.java
deleted file mode 100644
index fcf5979f..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/AESWrapPadTest.java
+++ /dev/null
@@ -1,146 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.Wrapper;
-import org.bouncycastle.crypto.engines.AESWrapPadEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * This is a test harness I use because I cannot modify the BC test harness without
- * invalidating the signature on their signed provider library. The code here is not
- * high quality but it does test the RFC vectors as well as randomly generated values.
- * The RFC test vectors are tested by making sure both the ciphertext and decrypted
- * values match the expected values whereas the random values are just checked to make
- * sure that:
- * <p>unwrap(wrap(random_value, random_kek), random_kek) == random_value.</p>
- */
-
-public class AESWrapPadTest
- extends SimpleTest
-{
-
- private final int numOfRandomIterations = 100;
-
- public AESWrapPadTest()
- {
-
- }
-
- private void wrapAndUnwrap(byte[] kek, byte[] key, byte[] expected)
- throws Exception
- {
- Wrapper wrapper = new AESWrapPadEngine();
-
- wrapper.init(true, new KeyParameter(kek));
-
- byte[] cipherText = wrapper.wrap(key, 0, key.length);
- if (!areEqual(cipherText, expected))
- {
- fail("Wrapped value does not match expected.");
- }
- wrapper.init(false, new KeyParameter(kek));
- byte[] plainText = wrapper.unwrap(cipherText, 0, cipherText.length);
-
- if (!areEqual(key, plainText))
- {
- fail("Unwrapped value does not match original.");
- }
- }
-
- private void wrapAndUnwrap(byte[] kek, byte[] key)
- throws Exception
- {
- Wrapper wrapper = new AESWrapPadEngine();
-
- wrapper.init(true, new KeyParameter(kek));
-
- byte[] cipherText = wrapper.wrap(key, 0, key.length);
-
- wrapper.init(false, new KeyParameter(kek));
- byte[] plainText = wrapper.unwrap(cipherText, 0, cipherText.length);
-
- if (!areEqual(key, plainText))
- {
- fail("Unwrapped value does not match original.");
- }
- }
-
- public String getName()
- {
- return "AESWrapPad";
- }
-
- public void performTest()
- throws Exception
- {
- // test RFC 5649 test vectors
- byte[] kek = Hex.decode("5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8");
- byte[] key = Hex.decode("c37b7e6492584340bed12207808941155068f738");
- byte[] wrap = Hex.decode("138bdeaa9b8fa7fc61f97742e72248ee5ae6ae5360d1ae6a5f54f373fa543b6a");
-
- wrapAndUnwrap(kek, key, wrap);
-
- wrap = Hex.decode("afbeb0f07dfbf5419200f2ccb50bb24f");
- key = Hex.decode("466f7250617369");
- wrapAndUnwrap(kek, key, wrap);
-
-
- //
- // offset test
- //
- Wrapper wrapper = new AESWrapPadEngine();
-
- byte[] pText = new byte[5 + key.length];
- byte[] cText;
-
- System.arraycopy(key, 0, pText, 5, key.length);
-
- wrapper.init(true, new KeyParameter(kek));
-
- cText = wrapper.wrap(pText, 5, key.length);
- if (!Arrays.areEqual(cText, wrap))
- {
- fail("failed offset wrap test expected " + new String(Hex.encode(wrap)) + " got " + new String(Hex.encode(cText)));
- }
-
- wrapper.init(false, new KeyParameter(kek));
-
- cText = new byte[6 + wrap.length];
- System.arraycopy(wrap, 0, cText, 6, wrap.length);
-
- pText = wrapper.unwrap(cText, 6, wrap.length);
- if (!Arrays.areEqual(pText, key))
- {
- fail("failed offset unwrap test expected " + new String(Hex.encode(key)) + " got " + new String(Hex.encode(pText)));
- }
-
- // test random values
- SecureRandom rnd = new SecureRandom();
- for (int i = 0; i < numOfRandomIterations; i++)
- {
- int kekLength = 128;
- boolean shouldIncrease = (rnd.nextInt() & 0x01) != 0;
- if (shouldIncrease)
- {
- kekLength = 256;
- }
- kek = new byte[kekLength / 8];
- rnd.nextBytes(kek);
- int keyToWrapSize = rnd.nextInt(256 / 8 - 8) + 8;
- byte[] keyToWrap = new byte[keyToWrapSize];
- rnd.nextBytes(keyToWrap);
- wrapAndUnwrap(kek, keyToWrap);
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new AESWrapPadTest());
- }
-}
-
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/AESWrapTest.java b/core/src/test/java/org/bouncycastle/crypto/test/AESWrapTest.java
deleted file mode 100644
index f00c6ce6..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/AESWrapTest.java
+++ /dev/null
@@ -1,238 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.Wrapper;
-import org.bouncycastle.crypto.engines.AESWrapEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-/**
- * Wrap Test
- */
-public class AESWrapTest
- implements Test
-{
- public String getName()
- {
- return "AESWrap";
- }
-
- private TestResult wrapTest(
- int id,
- byte[] kek,
- byte[] in,
- byte[] out)
- {
- Wrapper wrapper = new AESWrapEngine();
-
- wrapper.init(true, new KeyParameter(kek));
-
- try
- {
- byte[] cText = wrapper.wrap(in, 0, in.length);
- if (!Arrays.areEqual(cText, out))
- {
- return new SimpleTestResult(false, getName() + ": failed wrap test " + id + " expected " + new String(Hex.encode(out)) + " got " + new String(Hex.encode(cText)));
- }
- }
- catch (Exception e)
- {
- return new SimpleTestResult(false, getName() + ": failed wrap test exception " + e.toString());
- }
-
- wrapper.init(false, new KeyParameter(kek));
-
- try
- {
- byte[] pText = wrapper.unwrap(out, 0, out.length);
- if (!Arrays.areEqual(pText, in))
- {
- return new SimpleTestResult(false, getName() + ": failed unwrap test " + id + " expected " + new String(Hex.encode(in)) + " got " + new String(Hex.encode(pText)));
- }
- }
- catch (Exception e)
- {
- return new SimpleTestResult(false, getName() + ": failed unwrap test exception.", e);
- }
-
- //
- // offset test
- //
- byte[] pText = new byte[5 + in.length];
- byte[] cText;
-
- System.arraycopy(in, 0, pText, 5, in.length);
-
- wrapper.init(true, new KeyParameter(kek));
-
- try
- {
- cText = wrapper.wrap(pText, 5, in.length);
- if (!Arrays.areEqual(cText, out))
- {
- return new SimpleTestResult(false, getName() + ": failed wrap test " + id + " expected " + new String(Hex.encode(out)) + " got " + new String(Hex.encode(cText)));
- }
- }
- catch (Exception e)
- {
- return new SimpleTestResult(false, getName() + ": failed wrap test exception " + e.toString());
- }
-
- wrapper.init(false, new KeyParameter(kek));
-
- cText = new byte[6 + out.length];
- System.arraycopy(out, 0, cText, 6, out.length);
-
- try
- {
- pText = wrapper.unwrap(cText, 6, out.length);
- if (!Arrays.areEqual(pText, in))
- {
- return new SimpleTestResult(false, getName() + ": failed unwrap test " + id + " expected " + new String(Hex.encode(in)) + " got " + new String(Hex.encode(pText)));
- }
- }
- catch (Exception e)
- {
- return new SimpleTestResult(false, getName() + ": failed unwrap test exception.", e);
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
-
- public TestResult perform()
- {
- byte[] kek1 = Hex.decode("000102030405060708090a0b0c0d0e0f");
- byte[] in1 = Hex.decode("00112233445566778899aabbccddeeff");
- byte[] out1 = Hex.decode("1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5");
- TestResult result = wrapTest(1, kek1, in1, out1);
-
- if (!result.isSuccessful())
- {
- return result;
- }
-
- byte[] kek2 = Hex.decode("000102030405060708090a0b0c0d0e0f1011121314151617");
- byte[] in2 = Hex.decode("00112233445566778899aabbccddeeff");
- byte[] out2 = Hex.decode("96778b25ae6ca435f92b5b97c050aed2468ab8a17ad84e5d");
- result = wrapTest(2, kek2, in2, out2);
- if (!result.isSuccessful())
- {
- return result;
- }
-
- byte[] kek3 = Hex.decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
- byte[] in3 = Hex.decode("00112233445566778899aabbccddeeff");
- byte[] out3 = Hex.decode("64e8c3f9ce0f5ba263e9777905818a2a93c8191e7d6e8ae7");
- result = wrapTest(3, kek3, in3, out3);
- if (!result.isSuccessful())
- {
- return result;
- }
-
- byte[] kek4 = Hex.decode("000102030405060708090a0b0c0d0e0f1011121314151617");
- byte[] in4 = Hex.decode("00112233445566778899aabbccddeeff0001020304050607");
- byte[] out4 = Hex.decode("031d33264e15d33268f24ec260743edce1c6c7ddee725a936ba814915c6762d2");
- result = wrapTest(4, kek4, in4, out4);
- if (!result.isSuccessful())
- {
- return result;
- }
-
- byte[] kek5 = Hex.decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
- byte[] in5 = Hex.decode("00112233445566778899aabbccddeeff0001020304050607");
- byte[] out5 = Hex.decode("a8f9bc1612c68b3ff6e6f4fbe30e71e4769c8b80a32cb8958cd5d17d6b254da1");
- result = wrapTest(5, kek5, in5, out5);
- if (!result.isSuccessful())
- {
- return result;
- }
-
- byte[] kek6 = Hex.decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
- byte[] in6 = Hex.decode("00112233445566778899aabbccddeeff000102030405060708090a0b0c0d0e0f");
- byte[] out6 = Hex.decode("28c9f404c4b810f4cbccb35cfb87f8263f5786e2d80ed326cbc7f0e71a99f43bfb988b9b7a02dd21");
- result = wrapTest(6, kek6, in6, out6);
- if (!result.isSuccessful())
- {
- return result;
- }
-
- Wrapper wrapper = new AESWrapEngine();
- KeyParameter key = new KeyParameter(new byte[16]);
- byte[] buf = new byte[16];
-
- try
- {
- wrapper.init(true, key);
-
- wrapper.unwrap(buf, 0, buf.length);
-
- return new SimpleTestResult(false, getName() + ": failed unwrap state test.");
- }
- catch (IllegalStateException e)
- {
- // expected
- }
- catch (InvalidCipherTextException e)
- {
- return new SimpleTestResult(false, getName() + ": unexpected exception: " + e, e);
- }
-
- try
- {
- wrapper.init(false, key);
-
- wrapper.wrap(buf, 0, buf.length);
-
- return new SimpleTestResult(false, getName() + ": failed unwrap state test.");
- }
- catch (IllegalStateException e)
- {
- // expected
- }
-
- //
- // short test
- //
- try
- {
- wrapper.init(false, key);
-
- wrapper.unwrap(buf, 0, buf.length / 2);
-
- return new SimpleTestResult(false, getName() + ": failed unwrap short test.");
- }
- catch (InvalidCipherTextException e)
- {
- // expected
- }
-
- try
- {
- wrapper.init(true, key);
-
- wrapper.wrap(buf, 0, 15);
-
- return new SimpleTestResult(false, getName() + ": failed wrap length test.");
- }
- catch (DataLengthException e)
- {
- // expected
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
-
- public static void main(
- String[] args)
- {
- AESWrapTest test = new AESWrapTest();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/AllTests.java b/core/src/test/java/org/bouncycastle/crypto/test/AllTests.java
deleted file mode 100644
index 35bf2350..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/AllTests.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-import org.bouncycastle.util.test.SimpleTestResult;
-
-public class AllTests
- extends TestCase
-{
- public void testCrypto()
- {
- org.bouncycastle.util.test.Test[] tests = RegressionTest.tests;
-
- for (int i = 0; i != tests.length; i++)
- {
- SimpleTestResult result = (SimpleTestResult)tests[i].perform();
-
- if (!result.isSuccessful())
- {
- fail(result.toString());
- }
- }
- }
-
- public static void main (String[] args)
- {
- junit.textui.TestRunner.run(suite());
- }
-
- public static Test suite()
- {
- TestSuite suite = new TestSuite("Lightweight Crypto Tests");
-
- suite.addTestSuite(AllTests.class);
- suite.addTestSuite(GCMReorderTest.class);
-
- return suite;
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/BlockCipherMonteCarloTest.java b/core/src/test/java/org/bouncycastle/crypto/test/BlockCipherMonteCarloTest.java
deleted file mode 100644
index 72242c58..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/BlockCipherMonteCarloTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.BufferedBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * a basic test that takes a cipher, key parameter, and an input
- * and output string. This test wraps the engine in a buffered block
- * cipher with padding disabled.
- */
-public class BlockCipherMonteCarloTest
- extends SimpleTest
-{
- int id;
- int iterations;
- BlockCipher engine;
- CipherParameters param;
- byte[] input;
- byte[] output;
-
- public BlockCipherMonteCarloTest(
- int id,
- int iterations,
- BlockCipher engine,
- CipherParameters param,
- String input,
- String output)
- {
- this.id = id;
- this.iterations = iterations;
- this.engine = engine;
- this.param = param;
- this.input = Hex.decode(input);
- this.output = Hex.decode(output);
- }
-
- public String getName()
- {
- return engine.getAlgorithmName() + " Monte Carlo Test " + id;
- }
-
- public void performTest()
- throws Exception
- {
- BufferedBlockCipher cipher = new BufferedBlockCipher(engine);
-
- cipher.init(true, param);
-
- byte[] out = new byte[input.length];
-
- System.arraycopy(input, 0, out, 0, out.length);
-
- for (int i = 0; i != iterations; i++)
- {
- int len1 = cipher.processBytes(out, 0, out.length, out, 0);
-
- cipher.doFinal(out, len1);
- }
-
- if (!areEqual(out, output))
- {
- fail("failed - " + "expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
- }
-
- cipher.init(false, param);
-
- for (int i = 0; i != iterations; i++)
- {
- int len1 = cipher.processBytes(out, 0, out.length, out, 0);
-
- cipher.doFinal(out, len1);
- }
-
- if (!areEqual(input, out))
- {
- fail("failed reversal");
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/BlockCipherResetTest.java b/core/src/test/java/org/bouncycastle/crypto/test/BlockCipherResetTest.java
deleted file mode 100644
index a35835b0..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/BlockCipherResetTest.java
+++ /dev/null
@@ -1,206 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.engines.AESEngine;
-import org.bouncycastle.crypto.engines.AESFastEngine;
-import org.bouncycastle.crypto.engines.AESLightEngine;
-import org.bouncycastle.crypto.engines.BlowfishEngine;
-import org.bouncycastle.crypto.engines.CAST5Engine;
-import org.bouncycastle.crypto.engines.CAST6Engine;
-import org.bouncycastle.crypto.engines.DESEngine;
-import org.bouncycastle.crypto.engines.DESedeEngine;
-import org.bouncycastle.crypto.engines.NoekeonEngine;
-import org.bouncycastle.crypto.engines.RC6Engine;
-import org.bouncycastle.crypto.engines.SEEDEngine;
-import org.bouncycastle.crypto.engines.SerpentEngine;
-import org.bouncycastle.crypto.engines.TEAEngine;
-import org.bouncycastle.crypto.engines.TwofishEngine;
-import org.bouncycastle.crypto.engines.XTEAEngine;
-import org.bouncycastle.crypto.modes.CBCBlockCipher;
-import org.bouncycastle.crypto.modes.CFBBlockCipher;
-import org.bouncycastle.crypto.modes.GOFBBlockCipher;
-import org.bouncycastle.crypto.modes.OFBBlockCipher;
-import org.bouncycastle.crypto.modes.OpenPGPCFBBlockCipher;
-import org.bouncycastle.crypto.modes.PGPCFBBlockCipher;
-import org.bouncycastle.crypto.modes.SICBlockCipher;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * Test whether block ciphers implement reset contract on init, encrypt/decrypt and reset.
- */
-public class BlockCipherResetTest
- extends SimpleTest
-{
-
- public String getName()
- {
- return "Block Cipher Reset";
- }
-
- public void performTest()
- throws Exception
- {
- // 128 bit block ciphers
- testReset("AESFastEngine", new AESFastEngine(), new AESFastEngine(), new KeyParameter(new byte[16]));
- testReset("AESEngine", new AESEngine(), new AESEngine(), new KeyParameter(new byte[16]));
- testReset("AESLightEngine", new AESLightEngine(), new AESLightEngine(), new KeyParameter(new byte[16]));
- testReset("Twofish", new TwofishEngine(), new TwofishEngine(), new KeyParameter(new byte[16]));
- testReset("NoekeonEngine", new NoekeonEngine(), new NoekeonEngine(), new KeyParameter(new byte[16]));
- testReset("SerpentEngine", new SerpentEngine(), new SerpentEngine(), new KeyParameter(new byte[16]));
- testReset("SEEDEngine", new SEEDEngine(), new SEEDEngine(), new KeyParameter(new byte[16]));
- testReset("CAST6Engine", new CAST6Engine(), new CAST6Engine(), new KeyParameter(new byte[16]));
- testReset("RC6Engine", new RC6Engine(), new RC6Engine(), new KeyParameter(new byte[16]));
-
- // 64 bit block ciphers
- testReset("DESEngine", new DESEngine(), new DESEngine(), new KeyParameter(new byte[8]));
- testReset("BlowfishEngine", new BlowfishEngine(), new BlowfishEngine(), new KeyParameter(new byte[8]));
- testReset("CAST5Engine", new CAST5Engine(), new CAST5Engine(), new KeyParameter(new byte[8]));
- testReset("DESedeEngine", new DESedeEngine(), new DESedeEngine(), new KeyParameter(new byte[24]));
- testReset("TEAEngine", new TEAEngine(), new TEAEngine(), new KeyParameter(new byte[16]));
- testReset("XTEAEngine", new XTEAEngine(), new XTEAEngine(), new KeyParameter(new byte[16]));
-
- // primitive block cipher modes (don't reset on processBlock)
- testModeReset("AES/CBC", new CBCBlockCipher(new AESEngine()), new CBCBlockCipher(new AESEngine()),
- new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]));
- testModeReset("AES/SIC", new SICBlockCipher(new AESEngine()), new SICBlockCipher(new AESEngine()),
- new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]));
- testModeReset("AES/CFB", new CFBBlockCipher(new AESEngine(), 128), new CFBBlockCipher(new AESEngine(), 128),
- new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]));
- testModeReset("AES/OFB", new OFBBlockCipher(new AESEngine(), 128), new OFBBlockCipher(new AESEngine(), 128),
- new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]));
- testModeReset("AES/GCTR", new GOFBBlockCipher(new DESEngine()), new GOFBBlockCipher(new DESEngine()),
- new ParametersWithIV(new KeyParameter(new byte[8]), new byte[8]));
- testModeReset("AES/OpenPGPCFB", new OpenPGPCFBBlockCipher(new AESEngine()), new OpenPGPCFBBlockCipher(
- new AESEngine()), new KeyParameter(new byte[16]));
- testModeReset("AES/PGPCFB", new PGPCFBBlockCipher(new AESEngine(), false), new PGPCFBBlockCipher(
- new AESEngine(), false), new KeyParameter(new byte[16]));
-
- // PGPCFB with IV is broken (it's also not a PRP, so probably shouldn't be a BlockCipher)
- // testModeReset("AES/PGPCFBwithIV", new PGPCFBBlockCipher(new AESEngine(), true), new
- // PGPCFBBlockCipher(
- // new AESEngine(), true), new ParametersWithIV(new KeyParameter(new byte[16]), new
- // byte[16]));
- // testModeReset("AES/PGPCFBwithIV_NoIV", new PGPCFBBlockCipher(new AESEngine(), true), new
- // PGPCFBBlockCipher(
- // new AESEngine(), true), new KeyParameter(new byte[16]));
-
- }
-
- private void testModeReset(String test, BlockCipher cipher1, BlockCipher cipher2, CipherParameters params)
- throws InvalidCipherTextException
- {
- testReset(test, false, cipher1, cipher2, params);
- }
-
- private void testReset(String test, BlockCipher cipher1, BlockCipher cipher2, CipherParameters params)
- throws InvalidCipherTextException
- {
- testReset(test, true, cipher1, cipher2, params);
- }
-
- private void testReset(String test,
- boolean testCryptReset,
- BlockCipher cipher1,
- BlockCipher cipher2,
- CipherParameters params)
- throws InvalidCipherTextException
- {
- cipher1.init(true, params);
-
- byte[] plaintext = new byte[cipher1.getBlockSize()];
- byte[] ciphertext = new byte[(cipher1.getAlgorithmName().indexOf("PGPCFBwithIV")) > -1 ? 2 * cipher1.getBlockSize() + 2
- : cipher1.getBlockSize()];
-
- // Establish baseline answer
- crypt(cipher1, true, plaintext, ciphertext);
-
- // Test encryption resets
- checkReset(test, testCryptReset, cipher1, params, true, plaintext, ciphertext);
-
- // Test decryption resets with fresh instance
- cipher2.init(false, params);
- checkReset(test, testCryptReset, cipher2, params, false, ciphertext, plaintext);
- }
-
- private void checkReset(String test,
- boolean testCryptReset,
- BlockCipher cipher,
- CipherParameters params,
- boolean encrypt,
- byte[] pretext,
- byte[] posttext)
- throws InvalidCipherTextException
- {
- // Do initial run
- byte[] output = new byte[posttext.length];
- crypt(cipher, encrypt, pretext, output);
-
- // Check encrypt resets cipher
- if (testCryptReset)
- {
- crypt(cipher, encrypt, pretext, output);
- if (!Arrays.areEqual(output, posttext))
- {
- fail(test + (encrypt ? " encrypt" : " decrypt") + " did not reset cipher.");
- }
- }
-
- // Check init resets data
- cipher.processBlock(pretext, 0, output, 0);
- cipher.init(encrypt, params);
-
- try
- {
- crypt(cipher, encrypt, pretext, output);
- }
- catch (DataLengthException e)
- {
- fail(test + " init did not reset data.");
- }
- if (!Arrays.areEqual(output, posttext))
- {
- fail(test + " init did not reset data.", new String(Hex.encode(posttext)), new String(Hex.encode(output)));
- }
-
- // Check reset resets data
- cipher.processBlock(pretext, 0, output, 0);
- cipher.reset();
-
- try
- {
- crypt(cipher, encrypt, pretext, output);
- }
- catch (DataLengthException e)
- {
- fail(test + " reset did not reset data.");
- }
- if (!Arrays.areEqual(output, posttext))
- {
- fail(test + " reset did not reset data.");
- }
- }
-
- private static void crypt(BlockCipher cipher1, boolean encrypt, byte[] plaintext, byte[] output)
- throws InvalidCipherTextException
- {
- cipher1.processBlock(plaintext, 0, output, 0);
- if ((cipher1.getAlgorithmName().indexOf("PGPCFBwithIV") > -1) && !encrypt)
- {
- // Process past IV in first block
- cipher1.processBlock(plaintext, cipher1.getBlockSize(), output, 0);
- }
- }
-
- public static void main(String[] args)
- {
- runTest(new BlockCipherResetTest());
- }
-
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/BlockCipherVectorTest.java b/core/src/test/java/org/bouncycastle/crypto/test/BlockCipherVectorTest.java
deleted file mode 100644
index 36b729c6..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/BlockCipherVectorTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.BufferedBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * a basic test that takes a cipher, key parameter, and an input
- * and output string. This test wraps the engine in a buffered block
- * cipher with padding disabled.
- */
-public class BlockCipherVectorTest
- extends SimpleTest
-{
- int id;
- BlockCipher engine;
- CipherParameters param;
- byte[] input;
- byte[] output;
-
- public BlockCipherVectorTest(
- int id,
- BlockCipher engine,
- CipherParameters param,
- String input,
- String output)
- {
- this.id = id;
- this.engine = engine;
- this.param = param;
- this.input = Hex.decode(input);
- this.output = Hex.decode(output);
- }
-
- public String getName()
- {
- return engine.getAlgorithmName() + " Vector Test " + id;
- }
-
- public void performTest()
- throws Exception
- {
- BufferedBlockCipher cipher = new BufferedBlockCipher(engine);
-
- cipher.init(true, param);
-
- byte[] out = new byte[input.length];
-
- int len1 = cipher.processBytes(input, 0, input.length, out, 0);
-
- cipher.doFinal(out, len1);
-
- if (!areEqual(out, output))
- {
- fail("failed - " + "expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
- }
-
- cipher.init(false, param);
-
- int len2 = cipher.processBytes(output, 0, output.length, out, 0);
-
- cipher.doFinal(out, len2);
-
- if (!areEqual(input, out))
- {
- fail("failed reversal got " + new String(Hex.encode(out)));
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/BlowfishTest.java b/core/src/test/java/org/bouncycastle/crypto/test/BlowfishTest.java
deleted file mode 100644
index 757788ed..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/BlowfishTest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.engines.BlowfishEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * blowfish tester - vectors from http://www.counterpane.com/vectors.txt
- */
-public class BlowfishTest
- extends CipherTest
-{
- static SimpleTest[] tests =
- {
- new BlockCipherVectorTest(0, new BlowfishEngine(),
- new KeyParameter(Hex.decode("0000000000000000")),
- "0000000000000000", "4EF997456198DD78"),
- new BlockCipherVectorTest(1, new BlowfishEngine(),
- new KeyParameter(Hex.decode("FFFFFFFFFFFFFFFF")),
- "FFFFFFFFFFFFFFFF", "51866FD5B85ECB8A"),
- new BlockCipherVectorTest(2, new BlowfishEngine(),
- new KeyParameter(Hex.decode("3000000000000000")),
- "1000000000000001", "7D856F9A613063F2"),
- new BlockCipherVectorTest(3, new BlowfishEngine(),
- new KeyParameter(Hex.decode("1111111111111111")),
- "1111111111111111", "2466DD878B963C9D"),
- new BlockCipherVectorTest(4, new BlowfishEngine(),
- new KeyParameter(Hex.decode("0123456789ABCDEF")),
- "1111111111111111", "61F9C3802281B096"),
- new BlockCipherVectorTest(5, new BlowfishEngine(),
- new KeyParameter(Hex.decode("FEDCBA9876543210")),
- "0123456789ABCDEF", "0ACEAB0FC6A0A28D"),
- new BlockCipherVectorTest(6, new BlowfishEngine(),
- new KeyParameter(Hex.decode("7CA110454A1A6E57")),
- "01A1D6D039776742", "59C68245EB05282B"),
- new BlockCipherVectorTest(7, new BlowfishEngine(),
- new KeyParameter(Hex.decode("0131D9619DC1376E")),
- "5CD54CA83DEF57DA", "B1B8CC0B250F09A0"),
- };
-
- BlowfishTest()
- {
- super(tests, new BlowfishEngine(), new KeyParameter(new byte[16]));
- }
-
- public String getName()
- {
- return "Blowfish";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new BlowfishTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/CAST5Test.java b/core/src/test/java/org/bouncycastle/crypto/test/CAST5Test.java
deleted file mode 100644
index c651d873..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/CAST5Test.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.engines.CAST5Engine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * cast tester - vectors from http://www.ietf.org/rfc/rfc2144.txt
- */
-public class CAST5Test
- extends CipherTest
-{
- static SimpleTest[] tests = {
- new BlockCipherVectorTest(0, new CAST5Engine(),
- new KeyParameter(Hex.decode("0123456712345678234567893456789A")),
- "0123456789ABCDEF",
- "238B4FE5847E44B2"),
- new BlockCipherVectorTest(0, new CAST5Engine(),
- new KeyParameter(Hex.decode("01234567123456782345")),
- "0123456789ABCDEF",
- "EB6A711A2C02271B"),
- new BlockCipherVectorTest(0, new CAST5Engine(),
- new KeyParameter(Hex.decode("0123456712")),
- "0123456789ABCDEF",
- "7Ac816d16E9B302E"),
- };
-
- CAST5Test()
- {
- super(tests, new CAST5Engine(), new KeyParameter(new byte[16]));
- }
-
- public String getName()
- {
- return "CAST5";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new CAST5Test());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/CAST6Test.java b/core/src/test/java/org/bouncycastle/crypto/test/CAST6Test.java
deleted file mode 100644
index ef035a5d..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/CAST6Test.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.engines.CAST6Engine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * cast6 tester - vectors from http://www.ietf.org/rfc/rfc2612.txt
- */
-public class CAST6Test
- extends CipherTest
-{
- static SimpleTest[] tests = {
- new BlockCipherVectorTest(0, new CAST6Engine(),
- new KeyParameter(Hex.decode("2342bb9efa38542c0af75647f29f615d")),
- "00000000000000000000000000000000",
- "c842a08972b43d20836c91d1b7530f6b"),
- new BlockCipherVectorTest(0, new CAST6Engine(),
- new KeyParameter(Hex.decode("2342bb9efa38542cbed0ac83940ac298bac77a7717942863")),
- "00000000000000000000000000000000",
- "1b386c0210dcadcbdd0e41aa08a7a7e8"),
- new BlockCipherVectorTest(0, new CAST6Engine(),
- new KeyParameter(Hex.decode("2342bb9efa38542cbed0ac83940ac2988d7c47ce264908461cc1b5137ae6b604")),
- "00000000000000000000000000000000",
- "4f6a2038286897b9c9870136553317fa")
- };
-
- CAST6Test()
- {
- super(tests, new CAST6Engine(), new KeyParameter(new byte[16]));
- }
-
- public String getName()
- {
- return "CAST6";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new CAST6Test());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/CCMTest.java b/core/src/test/java/org/bouncycastle/crypto/test/CCMTest.java
deleted file mode 100644
index 2bbfe2a0..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/CCMTest.java
+++ /dev/null
@@ -1,305 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.engines.AESEngine;
-import org.bouncycastle.crypto.engines.DESEngine;
-import org.bouncycastle.crypto.modes.CCMBlockCipher;
-import org.bouncycastle.crypto.params.AEADParameters;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Strings;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * First four test vectors from
- * NIST Special Publication 800-38C.
- */
-public class CCMTest
- extends SimpleTest
-{
- private byte[] K1 = Hex.decode("404142434445464748494a4b4c4d4e4f");
- private byte[] N1 = Hex.decode("10111213141516");
- private byte[] A1 = Hex.decode("0001020304050607");
- private byte[] P1 = Hex.decode("20212223");
- private byte[] C1 = Hex.decode("7162015b4dac255d");
- private byte[] T1 = Hex.decode("6084341b");
-
- private byte[] K2 = Hex.decode("404142434445464748494a4b4c4d4e4f");
- private byte[] N2 = Hex.decode("1011121314151617");
- private byte[] A2 = Hex.decode("000102030405060708090a0b0c0d0e0f");
- private byte[] P2 = Hex.decode("202122232425262728292a2b2c2d2e2f");
- private byte[] C2 = Hex.decode("d2a1f0e051ea5f62081a7792073d593d1fc64fbfaccd");
- private byte[] T2 = Hex.decode("7f479ffca464");
-
- private byte[] K3 = Hex.decode("404142434445464748494a4b4c4d4e4f");
- private byte[] N3 = Hex.decode("101112131415161718191a1b");
- private byte[] A3 = Hex.decode("000102030405060708090a0b0c0d0e0f10111213");
- private byte[] P3 = Hex.decode("202122232425262728292a2b2c2d2e2f3031323334353637");
- private byte[] C3 = Hex.decode("e3b201a9f5b71a7a9b1ceaeccd97e70b6176aad9a4428aa5484392fbc1b09951");
- private byte[] T3 = Hex.decode("67c99240c7d51048");
-
- private byte[] K4 = Hex.decode("404142434445464748494a4b4c4d4e4f");
- private byte[] N4 = Hex.decode("101112131415161718191a1b1c");
- private byte[] A4 = Hex.decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
- private byte[] P4 = Hex.decode("202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f");
- private byte[] C4 = Hex.decode("69915dad1e84c6376a68c2967e4dab615ae0fd1faec44cc484828529463ccf72b4ac6bec93e8598e7f0dadbcea5b");
- private byte[] T4 = Hex.decode("f4dd5d0ee404617225ffe34fce91");
-
- //
- // long data vector
- //
- private byte[] C5 = Hex.decode("49b17d8d3ea4e6174a48e2b65e6d8b417ac0dd3f8ee46ce4a4a2a509661cef52528c1cd9805333a5cfd482fa3f095a3c2fdd1cc47771c5e55fddd60b5c8d6d3fa5c8dd79d08b16242b6642106e7c0c28bd1064b31e6d7c9800c8397dbc3fa8071e6a38278b386c18d65d39c6ad1ef9501a5c8f68d38eb6474799f3cc898b4b9b97e87f9c95ce5c51bc9d758f17119586663a5684e0a0daf6520ec572b87473eb141d10471e4799ded9e607655402eca5176bbf792ef39dd135ac8d710da8e9e854fd3b95c681023f36b5ebe2fb213d0b62dd6e9e3cfe190b792ccb20c53423b2dca128f861a61d306910e1af418839467e466f0ec361d2539eedd99d4724f1b51c07beb40e875a87491ec8b27cd1");
- private byte[] T5 = Hex.decode("5c768856796b627b13ec8641581b");
-
- public void performTest()
- throws Exception
- {
- CCMBlockCipher ccm = new CCMBlockCipher(new AESEngine());
-
- checkVectors(0, ccm, K1, 32, N1, A1, P1, T1, C1);
- checkVectors(1, ccm, K2, 48, N2, A2, P2, T2, C2);
- checkVectors(2, ccm, K3, 64, N3, A3, P3, T3, C3);
-
- ivParamTest(0, ccm, K1, N1);
-
- //
- // 4 has a reduced associated text which needs to be replicated
- //
- byte[] a4 = new byte[65536]; // 524288 / 8
-
- for (int i = 0; i < a4.length; i += A4.length)
- {
- System.arraycopy(A4, 0, a4, i, A4.length);
- }
-
- checkVectors(3, ccm, K4, 112, N4, a4, P4, T4, C4);
-
- //
- // long data test
- //
- checkVectors(4, ccm, K4, 112, N4, A4, A4, T5, C5);
-
- // decryption with output specified, non-zero offset.
- ccm.init(false, new AEADParameters(new KeyParameter(K2), 48, N2, A2));
-
- byte[] inBuf = new byte[C2.length + 10];
- byte[] outBuf = new byte[ccm.getOutputSize(C2.length) + 10];
-
- System.arraycopy(C2, 0, inBuf, 10, C2.length);
-
- int len = ccm.processPacket(inBuf, 10, C2.length, outBuf, 10);
- byte[] out = ccm.processPacket(C2, 0, C2.length);
-
- if (len != out.length || !isEqual(out, outBuf, 10))
- {
- fail("decryption output incorrect");
- }
-
- // encryption with output specified, non-zero offset.
- ccm.init(true, new AEADParameters(new KeyParameter(K2), 48, N2, A2));
-
- int inLen = len;
- inBuf = outBuf;
- outBuf = new byte[ccm.getOutputSize(inLen) + 10];
-
- len = ccm.processPacket(inBuf, 10, inLen, outBuf, 10);
- out = ccm.processPacket(inBuf, 10, inLen);
-
- if (len != out.length || !isEqual(out, outBuf, 10))
- {
- fail("encryption output incorrect");
- }
-
- //
- // exception tests
- //
-
- try
- {
- ccm.init(false, new AEADParameters(new KeyParameter(K1), 32, N2, A2));
-
- ccm.processPacket(C2, 0, C2.length);
-
- fail("invalid cipher text not picked up");
- }
- catch (InvalidCipherTextException e)
- {
- // expected
- }
-
- try
- {
- ccm = new CCMBlockCipher(new DESEngine());
-
- fail("incorrect block size not picked up");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- try
- {
- ccm.init(false, new KeyParameter(K1));
-
- fail("illegal argument not picked up");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- AEADTestUtil.testReset(this, new CCMBlockCipher(new AESEngine()), new CCMBlockCipher(new AESEngine()), new AEADParameters(new KeyParameter(K1), 32, N2));
- AEADTestUtil.testTampering(this, ccm, new AEADParameters(new KeyParameter(K1), 32, N2));
- AEADTestUtil.testOutputSizes(this, new CCMBlockCipher(new AESEngine()), new AEADParameters(
- new KeyParameter(K1), 32, N2));
- AEADTestUtil.testBufferSizeChecks(this, new CCMBlockCipher(new AESEngine()), new AEADParameters(
- new KeyParameter(K1), 32, N2));
- }
-
- private boolean isEqual(byte[] exp, byte[] other, int off)
- {
- for (int i = 0; i != exp.length; i++)
- {
- if (exp[i] != other[off + i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- private void checkVectors(
- int count,
- CCMBlockCipher ccm,
- byte[] k,
- int macSize,
- byte[] n,
- byte[] a,
- byte[] p,
- byte[] t,
- byte[] c)
- throws InvalidCipherTextException
- {
- byte[] fa = new byte[a.length / 2];
- byte[] la = new byte[a.length - (a.length / 2)];
- System.arraycopy(a, 0, fa, 0, fa.length);
- System.arraycopy(a, fa.length, la, 0, la.length);
-
- checkVectors(count, ccm, "all initial associated data", k, macSize, n, a, null, p, t, c);
- checkVectors(count, ccm, "subsequent associated data", k, macSize, n, null, a, p, t, c);
- checkVectors(count, ccm, "split associated data", k, macSize, n, fa, la, p, t, c);
- checkVectors(count, ccm, "reuse key", null, macSize, n, fa, la, p, t, c);
- }
-
- private void checkVectors(
- int count,
- CCMBlockCipher ccm,
- String additionalDataType,
- byte[] k,
- int macSize,
- byte[] n,
- byte[] a,
- byte[] sa,
- byte[] p,
- byte[] t,
- byte[] c)
- throws InvalidCipherTextException
- {
- KeyParameter keyParam = (k == null) ? null : new KeyParameter(k);
-
- ccm.init(true, new AEADParameters(keyParam, macSize, n, a));
-
- byte[] enc = new byte[c.length];
-
- if (sa != null)
- {
- ccm.processAADBytes(sa, 0, sa.length);
- }
-
- int len = ccm.processBytes(p, 0, p.length, enc, 0);
-
- len += ccm.doFinal(enc, len);
-
- if (!areEqual(c, enc))
- {
- fail("encrypted stream fails to match in test " + count + " with " + additionalDataType);
- }
-
- ccm.init(false, new AEADParameters(keyParam, macSize, n, a));
-
- byte[] tmp = new byte[enc.length];
-
- if (sa != null)
- {
- ccm.processAADBytes(sa, 0, sa.length);
- }
-
- len = ccm.processBytes(enc, 0, enc.length, tmp, 0);
-
- len += ccm.doFinal(tmp, len);
-
- byte[] dec = new byte[len];
-
- System.arraycopy(tmp, 0, dec, 0, len);
-
- if (!areEqual(p, dec))
- {
- fail("decrypted stream fails to match in test " + count + " with " + additionalDataType,
- new String(Hex.encode(p)), new String(Hex.encode(dec)));
- }
-
- if (!areEqual(t, ccm.getMac()))
- {
- fail("MAC fails to match in test " + count + " with " + additionalDataType);
- }
- }
-
- private void ivParamTest(
- int count,
- CCMBlockCipher ccm,
- byte[] k,
- byte[] n)
- throws InvalidCipherTextException
- {
- byte[] p = Strings.toByteArray("hello world!!");
-
- ccm.init(true, new ParametersWithIV(new KeyParameter(k), n));
-
- byte[] enc = new byte[p.length + 8];
-
- int len = ccm.processBytes(p, 0, p.length, enc, 0);
-
- len += ccm.doFinal(enc, len);
-
- ccm.init(false, new ParametersWithIV(new KeyParameter(k), n));
-
- byte[] tmp = new byte[enc.length];
-
- len = ccm.processBytes(enc, 0, enc.length, tmp, 0);
-
- len += ccm.doFinal(tmp, len);
-
- byte[] dec = new byte[len];
-
- System.arraycopy(tmp, 0, dec, 0, len);
-
- if (!areEqual(p, dec))
- {
- fail("decrypted stream fails to match in test " + count);
- }
- }
-
- public String getName()
- {
- return "CCM";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new CCMTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/CMacTest.java b/core/src/test/java/org/bouncycastle/crypto/test/CMacTest.java
deleted file mode 100644
index 720f8ea3..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/CMacTest.java
+++ /dev/null
@@ -1,321 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.engines.AESEngine;
-import org.bouncycastle.crypto.engines.AESFastEngine;
-import org.bouncycastle.crypto.macs.CMac;
-import org.bouncycastle.crypto.macs.CMacWithIV;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * CMAC tester - <a href="http://www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/tv/omac1-tv.txt">Official Test Vectors</a>.
- */
-public class CMacTest
- extends SimpleTest
-{
- private static final byte[] keyBytes128 = Hex.decode("2b7e151628aed2a6abf7158809cf4f3c");
- private static final byte[] keyBytes192 = Hex.decode(
- "8e73b0f7da0e6452c810f32b809079e5"
- + "62f8ead2522c6b7b");
- private static final byte[] keyBytes256 = Hex.decode(
- "603deb1015ca71be2b73aef0857d7781"
- + "1f352c073b6108d72d9810a30914dff4");
-
- private static final byte[] input0 = Hex.decode("");
- private static final byte[] input16 = Hex.decode("6bc1bee22e409f96e93d7e117393172a");
- private static final byte[] input40 = Hex.decode(
- "6bc1bee22e409f96e93d7e117393172a"
- + "ae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411");
- private static final byte[] input64 = Hex.decode(
- "6bc1bee22e409f96e93d7e117393172a"
- + "ae2d8a571e03ac9c9eb76fac45af8e51"
- + "30c81c46a35ce411e5fbc1191a0a52ef"
- + "f69f2445df4f9b17ad2b417be66c3710");
-
- private static final byte[] output_k128_m0 = Hex.decode("bb1d6929e95937287fa37d129b756746");
- private static final byte[] output_k128_m16 = Hex.decode("070a16b46b4d4144f79bdd9dd04a287c");
- private static final byte[] output_k128_m40 = Hex.decode("dfa66747de9ae63030ca32611497c827");
- private static final byte[] output_k128_m64 = Hex.decode("51f0bebf7e3b9d92fc49741779363cfe");
-
- private static final byte[] output_k192_m0 = Hex.decode("d17ddf46adaacde531cac483de7a9367");
- private static final byte[] output_k192_m16 = Hex.decode("9e99a7bf31e710900662f65e617c5184");
- private static final byte[] output_k192_m40 = Hex.decode("8a1de5be2eb31aad089a82e6ee908b0e");
- private static final byte[] output_k192_m64 = Hex.decode("a1d5df0eed790f794d77589659f39a11");
-
- private static final byte[] output_k256_m0 = Hex.decode("028962f61b7bf89efc6b551f4667d983");
- private static final byte[] output_k256_m16 = Hex.decode("28a7023f452e8f82bd4bf28d8c37c35c");
- private static final byte[] output_k256_m40 = Hex.decode("aaf3d8f1de5640c232f5b169b9c911e6");
- private static final byte[] output_k256_m64 = Hex.decode("e1992190549f6ed5696a2c056c315410");
-
- public CMacTest()
- {
- }
-
- public void performTest()
- {
- BlockCipher cipher = new AESFastEngine();
- Mac mac = new CMac(cipher, 128);
-
- //128 bytes key
-
- KeyParameter key = new KeyParameter(keyBytes128);
-
- // 0 bytes message - 128 bytes key
- mac.init(key);
-
- mac.update(input0, 0, input0.length);
-
- byte[] out = new byte[16];
-
- mac.doFinal(out, 0);
-
- if (!areEqual(out, output_k128_m0))
- {
- fail("Failed - expected " + new String(Hex.encode(output_k128_m0))
- + " got " + new String(Hex.encode(out)));
- }
-
- // 16 bytes message - 128 bytes key
- mac.init(key);
-
- mac.update(input16, 0, input16.length);
-
- out = new byte[16];
-
- mac.doFinal(out, 0);
-
- if (!areEqual(out, output_k128_m16))
- {
- fail("Failed - expected " + new String(Hex.encode(output_k128_m16))
- + " got " + new String(Hex.encode(out)));
- }
-
- // 40 bytes message - 128 bytes key
- mac.init(key);
-
- mac.update(input40, 0, input40.length);
-
- out = new byte[16];
-
- mac.doFinal(out, 0);
-
- if (!areEqual(out, output_k128_m40))
- {
- fail("Failed - expected " + new String(Hex.encode(output_k128_m40))
- + " got " + new String(Hex.encode(out)));
- }
-
- // 64 bytes message - 128 bytes key
- mac.init(key);
-
- mac.update(input64, 0, input64.length);
-
- out = new byte[16];
-
- mac.doFinal(out, 0);
-
- if (!areEqual(out, output_k128_m64))
- {
- fail("Failed - expected " + new String(Hex.encode(output_k128_m64))
- + " got " + new String(Hex.encode(out)));
- }
-
- //192 bytes key
-
- key = new KeyParameter(keyBytes192);
-
- // 0 bytes message - 192 bytes key
- mac.init(key);
-
- mac.update(input0, 0, input0.length);
-
- out = new byte[16];
-
- mac.doFinal(out, 0);
-
- if (!areEqual(out, output_k192_m0))
- {
- fail("Failed - expected " + new String(Hex.encode(output_k192_m0))
- + " got " + new String(Hex.encode(out)));
- }
-
- // 16 bytes message - 192 bytes key
- mac.init(key);
-
- mac.update(input16, 0, input16.length);
-
- out = new byte[16];
-
- mac.doFinal(out, 0);
-
- if (!areEqual(out, output_k192_m16))
- {
- fail("Failed - expected " + new String(Hex.encode(output_k192_m16))
- + " got " + new String(Hex.encode(out)));
- }
-
- // 40 bytes message - 192 bytes key
- mac.init(key);
-
- mac.update(input40, 0, input40.length);
-
- out = new byte[16];
-
- mac.doFinal(out, 0);
-
- if (!areEqual(out, output_k192_m40))
- {
- fail("Failed - expected " + new String(Hex.encode(output_k192_m40))
- + " got " + new String(Hex.encode(out)));
- }
-
- // 64 bytes message - 192 bytes key
- mac.init(key);
-
- mac.update(input64, 0, input64.length);
-
- out = new byte[16];
-
- mac.doFinal(out, 0);
-
- if (!areEqual(out, output_k192_m64))
- {
- fail("Failed - expected " + new String(Hex.encode(output_k192_m64))
- + " got " + new String(Hex.encode(out)));
- }
-
- //256 bytes key
-
- key = new KeyParameter(keyBytes256);
-
- // 0 bytes message - 256 bytes key
- mac.init(key);
-
- mac.update(input0, 0, input0.length);
-
- out = new byte[16];
-
- mac.doFinal(out, 0);
-
- if (!areEqual(out, output_k256_m0))
- {
- fail("Failed - expected " + new String(Hex.encode(output_k256_m0))
- + " got " + new String(Hex.encode(out)));
- }
-
- // 16 bytes message - 256 bytes key
- mac.init(key);
-
- mac.update(input16, 0, input16.length);
-
- out = new byte[16];
-
- mac.doFinal(out, 0);
-
- if (!areEqual(out, output_k256_m16))
- {
- fail("Failed - expected " + new String(Hex.encode(output_k256_m16))
- + " got " + new String(Hex.encode(out)));
- }
-
- // 40 bytes message - 256 bytes key
- mac.init(key);
-
- mac.update(input40, 0, input40.length);
-
- out = new byte[16];
-
- mac.doFinal(out, 0);
-
- if (!areEqual(out, output_k256_m40))
- {
- fail("Failed - expected " + new String(Hex.encode(output_k256_m40))
- + " got " + new String(Hex.encode(out)));
- }
-
- // 64 bytes message - 256 bytes key
- mac.init(key);
-
- mac.update(input64, 0, input64.length);
-
- out = new byte[16];
-
- mac.doFinal(out, 0);
-
- if (!areEqual(out, output_k256_m64))
- {
- fail("Failed - expected " + new String(Hex.encode(output_k256_m64))
- + " got " + new String(Hex.encode(out)));
- }
-
- // CMAC with IV
- // 16 bytes message - 256 bytes key
- mac = new CMacWithIV(new AESFastEngine());
-
- mac.init(key);
-
- mac.update(input16, 0, input16.length);
-
- out = new byte[16];
-
- mac.doFinal(out, 0);
-
- if (!areEqual(out, output_k256_m16))
- {
- fail("Failed - expected " + new String(Hex.encode(output_k256_m16))
- + " got " + new String(Hex.encode(out)));
- }
-
- // CMAC with IV
- // 16 bytes message - 256 bytes key
- mac = new CMacWithIV(new AESFastEngine());
-
- mac.init(new ParametersWithIV(key, Hex.decode("000102030405060708090a0b0c0d0e0f")));
-
- mac.update(input16, 0, input16.length);
-
- out = new byte[16];
-
- mac.doFinal(out, 0);
-
- if (areEqual(out, output_k256_m16))
- {
- fail("Failed - got " + new String(Hex.encode(output_k256_m16)));
- }
-
- if (!areEqual(out, Hex.decode("9347a60c64061b9ff2a92522ca8e08fc")))
- {
- fail("Failed - expected " + "9347a60c64061b9ff2a92522ca8e08fc"
- + " got " + new String(Hex.encode(out)));
- }
-
- testExceptions();
- }
-
- private void testExceptions()
- {
- try
- {
- CMac mac = new CMac(new AESEngine());
- mac.init(new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]));
- fail("CMac does not accept IV");
- } catch(IllegalArgumentException e)
- {
- // Expected
- }
- }
-
- public String getName()
- {
- return "CMac";
- }
-
- public static void main(String[] args)
- {
- runTest(new CMacTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/CTSTest.java b/core/src/test/java/org/bouncycastle/crypto/test/CTSTest.java
deleted file mode 100644
index 28fcc201..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/CTSTest.java
+++ /dev/null
@@ -1,212 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.BufferedBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.engines.AESEngine;
-import org.bouncycastle.crypto.engines.DESEngine;
-import org.bouncycastle.crypto.engines.SkipjackEngine;
-import org.bouncycastle.crypto.modes.CBCBlockCipher;
-import org.bouncycastle.crypto.modes.CTSBlockCipher;
-import org.bouncycastle.crypto.modes.OldCTSBlockCipher;
-import org.bouncycastle.crypto.modes.SICBlockCipher;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * CTS tester
- */
-public class CTSTest
- extends SimpleTest
-{
- static byte[] in1 = Hex.decode("4e6f7720697320746865207420");
- static byte[] in2 = Hex.decode("000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f0aaa");
- static byte[] out1 = Hex.decode("9952f131588465033fa40e8a98");
- static byte[] out2 = Hex.decode("358f84d01eb42988dc34efb994");
- static byte[] out3 = Hex.decode("170171cfad3f04530c509b0c1f0be0aefbd45a8e3755a873bff5ea198504b71683c6");
-
- private void testCTS(
- int id,
- BlockCipher cipher,
- CipherParameters params,
- byte[] input,
- byte[] output)
- throws Exception
- {
- byte[] out = new byte[input.length];
- BufferedBlockCipher engine = new CTSBlockCipher(cipher);
-
- engine.init(true, params);
-
- int len = engine.processBytes(input, 0, input.length, out, 0);
-
- engine.doFinal(out, len);
-
- if (!areEqual(output, out))
- {
- fail("failed encryption expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
- }
-
- engine.init(false, params);
-
- len = engine.processBytes(output, 0, output.length, out, 0);
-
- engine.doFinal(out, len);
-
- if (!areEqual(input, out))
- {
- fail("failed decryption expected " + new String(Hex.encode(input)) + " got " + new String(Hex.encode(out)));
- }
- }
-
- private void testOldCTS(
- int id,
- BlockCipher cipher,
- CipherParameters params,
- byte[] input,
- byte[] output)
- throws Exception
- {
- byte[] out = new byte[input.length];
- BufferedBlockCipher engine = new OldCTSBlockCipher(cipher);
-
- engine.init(true, params);
-
- int len = engine.processBytes(input, 0, input.length, out, 0);
-
- engine.doFinal(out, len);
-
- if (!areEqual(output, out))
- {
- fail("failed encryption expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
- }
-
- engine.init(false, params);
-
- len = engine.processBytes(output, 0, output.length, out, 0);
-
- engine.doFinal(out, len);
-
- if (!areEqual(input, out))
- {
- fail("failed decryption expected " + new String(Hex.encode(input)) + " got " + new String(Hex.encode(out)));
- }
- }
-
- private void testExceptions() throws InvalidCipherTextException
- {
- BufferedBlockCipher engine = new CTSBlockCipher(new DESEngine());
- CipherParameters params = new KeyParameter(new byte[engine.getBlockSize()]);
- engine.init(true, params);
-
- byte[] out = new byte[engine.getOutputSize(engine.getBlockSize())];
-
- engine.processBytes(new byte[engine.getBlockSize() - 1], 0, engine.getBlockSize() - 1, out, 0);
- try
- {
- engine.doFinal(out, 0);
- fail("Expected CTS encrypt error on < 1 block input");
- } catch(DataLengthException e)
- {
- // Expected
- }
-
- engine.init(true, params);
- engine.processBytes(new byte[engine.getBlockSize()], 0, engine.getBlockSize(), out, 0);
- try
- {
- engine.doFinal(out, 0);
- } catch(DataLengthException e)
- {
- fail("Unexpected CTS encrypt error on == 1 block input");
- }
-
- engine.init(false, params);
- engine.processBytes(new byte[engine.getBlockSize() - 1], 0, engine.getBlockSize() - 1, out, 0);
- try
- {
- engine.doFinal(out, 0);
- fail("Expected CTS decrypt error on < 1 block input");
- } catch(DataLengthException e)
- {
- // Expected
- }
-
- engine.init(false, params);
- engine.processBytes(new byte[engine.getBlockSize()], 0, engine.getBlockSize(), out, 0);
- try
- {
- engine.doFinal(out, 0);
- } catch(DataLengthException e)
- {
- fail("Unexpected CTS decrypt error on == 1 block input");
- }
-
- try
- {
- new CTSBlockCipher(new SICBlockCipher(new AESEngine()));
- fail("Expected CTS construction error - only ECB/CBC supported.");
- } catch(IllegalArgumentException e)
- {
- // Expected
- }
-
- }
-
- public String getName()
- {
- return "CTS";
- }
-
- public void performTest()
- throws Exception
- {
- byte[] key1 = { (byte)0x01, (byte)0x23, (byte)0x45, (byte)0x67, (byte)0x89, (byte)0xAB, (byte)0xCD, (byte)0xEF };
- byte[] key2 = { (byte)0x01, (byte)0x23, (byte)0x45, (byte)0x67, (byte)0x89, (byte)0xAB, (byte)0xCD, (byte)0xEF, (byte)0xee, (byte)0xff };
- byte[] iv = { 1, 2, 3, 4, 5, 6, 7, 8 };
-
- testCTS(1, new DESEngine(), new KeyParameter(key1), in1, out1);
- testCTS(2, new CBCBlockCipher(new DESEngine()), new ParametersWithIV(new KeyParameter(key1), iv), in1, out2);
- testCTS(3, new CBCBlockCipher(new SkipjackEngine()), new ParametersWithIV(new KeyParameter(key2), iv), in2, out3);
-
- //
- // test vectors from rfc3962
- //
- byte[] aes128 = Hex.decode("636869636b656e207465726979616b69");
- byte[] aesIn1 = Hex.decode("4920776f756c64206c696b652074686520");
- byte[] aesOut1 = Hex.decode("c6353568f2bf8cb4d8a580362da7ff7f97");
- byte[] aesIn2 = Hex.decode("4920776f756c64206c696b65207468652047656e6572616c20476175277320");
- byte[] aesOut2 = Hex.decode("fc00783e0efdb2c1d445d4c8eff7ed2297687268d6ecccc0c07b25e25ecfe5");
- byte[] aesIn3 = Hex.decode("4920776f756c64206c696b65207468652047656e6572616c2047617527732043");
- byte[] aesOut3 = Hex.decode("39312523a78662d5be7fcbcc98ebf5a897687268d6ecccc0c07b25e25ecfe584");
-
- testCTS(4, new CBCBlockCipher(new AESEngine()), new ParametersWithIV(new KeyParameter(aes128), new byte[16]), aesIn1, aesOut1);
- testCTS(5, new CBCBlockCipher(new AESEngine()), new ParametersWithIV(new KeyParameter(aes128), new byte[16]), aesIn2, aesOut2);
- testCTS(6, new CBCBlockCipher(new AESEngine()), new ParametersWithIV(new KeyParameter(aes128), new byte[16]), aesIn3, aesOut3);
-
- testOldCTS(4, new CBCBlockCipher(new AESEngine()), new ParametersWithIV(new KeyParameter(aes128), new byte[16]), aesIn1, aesOut1);
- testOldCTS(5, new CBCBlockCipher(new AESEngine()), new ParametersWithIV(new KeyParameter(aes128), new byte[16]), aesIn2, aesOut2);
- testOldCTS(6, new CBCBlockCipher(new AESEngine()), new ParametersWithIV(new KeyParameter(aes128), new byte[16]), aesIn3, aesOut3);
-
- byte[] aes1Block = Hex.decode("4920776f756c64206c696b6520746865");
- byte[] preErrata = Hex.decode("e7664c13ff28c965b0d2a0e7ec353706"); // CTS style one block
- byte[] pstErrata = Hex.decode("97687268d6ecccc0c07b25e25ecfe584"); // CBC style one block
- byte[] pstErrataNonZeroIV = Hex.decode("571f5108c53fe95ab52df783df933fa3");
-
- testCTS(7, new CBCBlockCipher(new AESEngine()), new ParametersWithIV(new KeyParameter(aes128), new byte[16]), aes1Block, pstErrata);
- testCTS(8, new CBCBlockCipher(new AESEngine()), new ParametersWithIV(new KeyParameter(aes128), aes1Block), aes1Block, pstErrataNonZeroIV);
- testOldCTS(7, new CBCBlockCipher(new AESEngine()), new ParametersWithIV(new KeyParameter(aes128), new byte[16]), aes1Block, preErrata);
-
- testExceptions();
- }
-
- public static void main(
- String[] args)
- {
- runTest(new CTSTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/CamelliaLightTest.java b/core/src/test/java/org/bouncycastle/crypto/test/CamelliaLightTest.java
deleted file mode 100644
index 6198ce66..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/CamelliaLightTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.engines.CamelliaLightEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * Camellia tester - vectors from https://www.cosic.esat.kuleuven.be/nessie/testvectors/ and RFC 3713
- */
-public class CamelliaLightTest
- extends CipherTest
-{
- static SimpleTest[] tests =
- {
- new BlockCipherVectorTest(0, new CamelliaLightEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000")),
- "80000000000000000000000000000000", "07923A39EB0A817D1C4D87BDB82D1F1C"),
- new BlockCipherVectorTest(1, new CamelliaLightEngine(),
- new KeyParameter(Hex.decode("80000000000000000000000000000000")),
- "00000000000000000000000000000000", "6C227F749319A3AA7DA235A9BBA05A2C"),
- new BlockCipherVectorTest(2, new CamelliaLightEngine(),
- new KeyParameter(Hex.decode("0123456789abcdeffedcba9876543210")),
- "0123456789abcdeffedcba9876543210", "67673138549669730857065648eabe43"),
- //
- // 192 bit
- //
- new BlockCipherVectorTest(3, new CamelliaLightEngine(),
- new KeyParameter(Hex.decode("0123456789abcdeffedcba98765432100011223344556677")),
- "0123456789abcdeffedcba9876543210", "b4993401b3e996f84ee5cee7d79b09b9"),
- new BlockCipherVectorTest(4, new CamelliaLightEngine(),
- new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
- "00040000000000000000000000000000", "9BCA6C88B928C1B0F57F99866583A9BC"),
- new BlockCipherVectorTest(5, new CamelliaLightEngine(),
- new KeyParameter(Hex.decode("949494949494949494949494949494949494949494949494")),
- "636EB22D84B006381235641BCF0308D2", "94949494949494949494949494949494"),
- //
- // 256 bit
- //
- new BlockCipherVectorTest(6, new CamelliaLightEngine(),
- new KeyParameter(Hex.decode("0123456789abcdeffedcba987654321000112233445566778899aabbccddeeff")),
- "0123456789abcdeffedcba9876543210", "9acc237dff16d76c20ef7c919e3a7509"),
- new BlockCipherVectorTest(7, new CamelliaLightEngine(),
- new KeyParameter(Hex.decode("4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A")),
- "057764FE3A500EDBD988C5C3B56CBA9A", "4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A"),
- new BlockCipherVectorTest(8, new CamelliaLightEngine(),
- new KeyParameter(Hex.decode("0303030303030303030303030303030303030303030303030303030303030303")),
- "7968B08ABA92193F2295121EF8D75C8A", "03030303030303030303030303030303"),
- };
-
- CamelliaLightTest()
- {
- super(tests, new CamelliaLightEngine(), new KeyParameter(new byte[32]));
- }
-
- public String getName()
- {
- return "CamelliaLight";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new CamelliaLightTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/CamelliaTest.java b/core/src/test/java/org/bouncycastle/crypto/test/CamelliaTest.java
deleted file mode 100644
index e69a82ad..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/CamelliaTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.engines.CamelliaEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-import org.bouncycastle.util.test.TestResult;
-
-/**
- * Camellia tester - vectors from https://www.cosic.esat.kuleuven.be/nessie/testvectors/ and RFC 3713
- */
-public class CamelliaTest
- extends CipherTest
-{
- static SimpleTest[] tests =
- {
- new BlockCipherVectorTest(0, new CamelliaEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000")),
- "80000000000000000000000000000000", "07923A39EB0A817D1C4D87BDB82D1F1C"),
- new BlockCipherVectorTest(1, new CamelliaEngine(),
- new KeyParameter(Hex.decode("80000000000000000000000000000000")),
- "00000000000000000000000000000000", "6C227F749319A3AA7DA235A9BBA05A2C"),
- new BlockCipherVectorTest(2, new CamelliaEngine(),
- new KeyParameter(Hex.decode("0123456789abcdeffedcba9876543210")),
- "0123456789abcdeffedcba9876543210", "67673138549669730857065648eabe43"),
- //
- // 192 bit
- //
- new BlockCipherVectorTest(3, new CamelliaEngine(),
- new KeyParameter(Hex.decode("0123456789abcdeffedcba98765432100011223344556677")),
- "0123456789abcdeffedcba9876543210", "b4993401b3e996f84ee5cee7d79b09b9"),
- new BlockCipherVectorTest(4, new CamelliaEngine(),
- new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
- "00040000000000000000000000000000", "9BCA6C88B928C1B0F57F99866583A9BC"),
- new BlockCipherVectorTest(5, new CamelliaEngine(),
- new KeyParameter(Hex.decode("949494949494949494949494949494949494949494949494")),
- "636EB22D84B006381235641BCF0308D2", "94949494949494949494949494949494"),
- //
- // 256 bit
- //
- new BlockCipherVectorTest(6, new CamelliaEngine(),
- new KeyParameter(Hex.decode("0123456789abcdeffedcba987654321000112233445566778899aabbccddeeff")),
- "0123456789abcdeffedcba9876543210", "9acc237dff16d76c20ef7c919e3a7509"),
- new BlockCipherVectorTest(7, new CamelliaEngine(),
- new KeyParameter(Hex.decode("4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A")),
- "057764FE3A500EDBD988C5C3B56CBA9A", "4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A"),
- new BlockCipherVectorTest(8, new CamelliaEngine(),
- new KeyParameter(Hex.decode("0303030303030303030303030303030303030303030303030303030303030303")),
- "7968B08ABA92193F2295121EF8D75C8A", "03030303030303030303030303030303"),
- };
-
- CamelliaTest()
- {
- super(tests, new CamelliaEngine(), new KeyParameter(new byte[32]));
- }
-
- public String getName()
- {
- return "Camellia";
- }
-
- public static void main(
- String[] args)
- {
- CamelliaTest test = new CamelliaTest();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/ChaChaTest.java b/core/src/test/java/org/bouncycastle/crypto/test/ChaChaTest.java
deleted file mode 100644
index 45c063fe..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/ChaChaTest.java
+++ /dev/null
@@ -1,403 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.StreamCipher;
-import org.bouncycastle.crypto.engines.ChaChaEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * ChaCha Test
- * <p>
- * Test cases generated using ref version of ChaCha20 in estreambench-20080905.
- */
-public class ChaChaTest
- extends SimpleTest
-{
- byte[] zeroes = Hex.decode(
- "00000000000000000000000000000000"
- + "00000000000000000000000000000000"
- + "00000000000000000000000000000000"
- + "00000000000000000000000000000000");
-
- String set1v0_0 = "FBB87FBB8395E05DAA3B1D683C422046"
- + "F913985C2AD9B23CFC06C1D8D04FF213"
- + "D44A7A7CDB84929F915420A8A3DC58BF"
- + "0F7ECB4B1F167BB1A5E6153FDAF4493D";
-
- String set1v0_192 = "D9485D55B8B82D792ED1EEA8E93E9BC1"
- + "E2834AD0D9B11F3477F6E106A2F6A5F2"
- + "EA8244D5B925B8050EAB038F58D4DF57"
- + "7FAFD1B89359DAE508B2B10CBD6B488E";
-
- String set1v0_256 = "08661A35D6F02D3D9ACA8087F421F7C8"
- + "A42579047D6955D937925BA21396DDD4"
- + "74B1FC4ACCDCAA33025B4BCE817A4FBF"
- + "3E5D07D151D7E6FE04934ED466BA4779";
-
- String set1v0_448 = "A7E16DD38BA48CCB130E5BE9740CE359"
- + "D631E91600F85C8A5D0785A612D1D987"
- + "90780ACDDC26B69AB106CCF6D866411D"
- + "10637483DBF08CC5591FD8B3C87A3AE0";
-
- String set1v9_0 = "A276339F99316A913885A0A4BE870F06"
- + "91E72B00F1B3F2239F714FE81E88E00C"
- + "BBE52B4EBBE1EA15894E29658C4CB145"
- + "E6F89EE4ABB045A78514482CE75AFB7C";
-
- String set1v9_192 = "0DFB9BD4F87F68DE54FBC1C6428FDEB0"
- + "63E997BE8490C9B7A4694025D6EBA2B1"
- + "5FE429DB82A7CAE6AAB22918E8D00449"
- + "6FB6291467B5AE81D4E85E81D8795EBB";
-
- String set1v9_256 = "546F5BB315E7F71A46E56D4580F90889"
- + "639A2BA528F757CF3B048738BA141AF3"
- + "B31607CB21561BAD94721048930364F4"
- + "B1227CFEB7CDECBA881FB44903550E68";
-
- String set1v9_448 = "6F813586E76691305A0CF048C0D8586D"
- + "C89460207D8B230CD172398AA33D19E9"
- + "2D24883C3A9B0BB7CD8C6B2668DB142E"
- + "37A97948A7A01498A21110297984CD20";
-
- String set6v0_0 = "57459975BC46799394788DE80B928387"
- + "862985A269B9E8E77801DE9D874B3F51"
- + "AC4610B9F9BEE8CF8CACD8B5AD0BF17D"
- + "3DDF23FD7424887EB3F81405BD498CC3";
-
- String set6v0_65472 = "EF9AEC58ACE7DB427DF012B2B91A0C1E"
- + "8E4759DCE9CDB00A2BD59207357BA06C"
- + "E02D327C7719E83D6348A6104B081DB0"
- + "3908E5186986AE41E3AE95298BB7B713";
-
- String set6v0_65536 = "17EF5FF454D85ABBBA280F3A94F1D26E"
- + "950C7D5B05C4BB3A78326E0DC5731F83"
- + "84205C32DB867D1B476CE121A0D7074B"
- + "AA7EE90525D15300F48EC0A6624BD0AF";
-
- String set6v1_0 = "92A2508E2C4084567195F2A1005E552B"
- + "4874EC0504A9CD5E4DAF739AB553D2E7"
- + "83D79C5BA11E0653BEBB5C116651302E"
- + "8D381CB728CA627B0B246E83942A2B99";
-
- String set6v1_65472 = "E1974EC3063F7BD0CBA58B1CE34BC874"
- + "67AAF5759B05EA46682A5D4306E5A76B"
- + "D99A448DB8DE73AF97A73F5FBAE2C776"
- + "35040464524CF14D7F08D4CE1220FD84";
-
- String set6v1_65536 = "BE3436141CFD62D12FF7D852F80C1344"
- + "81F152AD0235ECF8CA172C55CA8C031B"
- + "2E785D773A988CA8D4BDA6FAE0E493AA"
- + "71DCCC4C894D1F106CAC62A9FC0A9607";
-
- // ChaCha12
- String chacha12_set1v0_0 = "36CF0D56E9F7FBF287BC5460D95FBA94"
- + "AA6CBF17D74E7C784DDCF7E0E882DDAE"
- + "3B5A58243EF32B79A04575A8E2C2B73D"
- + "C64A52AA15B9F88305A8F0CA0B5A1A25";
-
- String chacha12_set1v0_192 = "83496792AB68FEC75ADB16D3044420A4"
- + "A00A6E9ADC41C3A63DBBF317A8258C85"
- + "A9BC08B4F76B413A4837324AEDF8BC2A"
- + "67D53C9AB9E1C5BC5F379D48DF9AF730";
-
- String chacha12_set1v0_256 = "BAA28ED593690FD760ADA07C95E3B888"
- + "4B4B64E488CA7A2D9BDC262243AB9251"
- + "394C5037E255F8BCCDCD31306C508FFB"
- + "C9E0161380F7911FCB137D46D9269250";
-
- String chacha12_set1v0_448 = "B7ECFB6AE0B51915762FE1FD03A14D0C"
- + "9E54DA5DC76EB16EBA5313BC535DE63D"
- + "C72D7F9F1874E301E99C8531819F4E37"
- + "75793F6A5D19C717FA5C78A39EB804A6";
-
- // ChaCha8
- String chacha8_set1v0_0 = "BEB1E81E0F747E43EE51922B3E87FB38"
- + "D0163907B4ED49336032AB78B67C2457"
- + "9FE28F751BD3703E51D876C017FAA435"
- + "89E63593E03355A7D57B2366F30047C5";
-
- String chacha8_set1v0_192 = "33B8B7CA8F8E89F0095ACE75A379C651"
- + "FD6BDD55703C90672E44C6BAB6AACDD8"
- + "7C976A87FD264B906E749429284134C2"
- + "38E3B88CF74A68245B860D119A8BDF43";
-
- String chacha8_set1v0_256 = "F7CA95BF08688BD3BE8A27724210F9DC"
- + "16F32AF974FBFB09E9F757C577A245AB"
- + "F35F824B70A4C02CB4A8D7191FA8A5AD"
- + "6A84568743844703D353B7F00A8601F4";
-
- String chacha8_set1v0_448 = "7B4117E8BFFD595CD8482270B08920FB"
- + "C9B97794E1809E07BB271BF07C861003"
- + "4C38DBA6ECA04E5474F399A284CBF6E2"
- + "7F70142E604D0977797DE5B58B6B25E0";
-
-
-
- public String getName()
- {
- return "ChaCha";
- }
-
- public void performTest()
- {
- chachaTest1(20, new ParametersWithIV(new KeyParameter(Hex.decode("80000000000000000000000000000000")), Hex.decode("0000000000000000")),
- set1v0_0, set1v0_192, set1v0_256, set1v0_448);
- chachaTest1(20, new ParametersWithIV(new KeyParameter(Hex.decode("00400000000000000000000000000000")), Hex.decode("0000000000000000")),
- set1v9_0, set1v9_192, set1v9_256, set1v9_448);
- chachaTest1(12, new ParametersWithIV(new KeyParameter(Hex.decode("80000000000000000000000000000000")), Hex.decode("0000000000000000")),
- chacha12_set1v0_0, chacha12_set1v0_192, chacha12_set1v0_256, chacha12_set1v0_448);
- chachaTest1(8, new ParametersWithIV(new KeyParameter(Hex.decode("80000000000000000000000000000000")), Hex.decode("0000000000000000")),
- chacha8_set1v0_0, chacha8_set1v0_192, chacha8_set1v0_256, chacha8_set1v0_448);
- chachaTest2(new ParametersWithIV(new KeyParameter(Hex.decode("0053A6F94C9FF24598EB3E91E4378ADD3083D6297CCF2275C81B6EC11467BA0D")), Hex.decode("0D74DB42A91077DE")),
- set6v0_0, set6v0_65472, set6v0_65536);
- chachaTest2(new ParametersWithIV(new KeyParameter(Hex.decode("0558ABFE51A4F74A9DF04396E93C8FE23588DB2E81D4277ACD2073C6196CBF12")), Hex.decode("167DE44BB21980E7")),
- set6v1_0, set6v1_65472, set6v1_65536);
- reinitBug();
- skipTest();
- }
-
- private void chachaTest1(int rounds, CipherParameters params, String v0, String v192, String v256, String v448)
- {
- StreamCipher chaCha = new ChaChaEngine(rounds);
- byte[] buf = new byte[64];
-
- chaCha.init(true, params);
-
- for (int i = 0; i != 7; i++)
- {
- chaCha.processBytes(zeroes, 0, 64, buf, 0);
- switch (i)
- {
- case 0:
- if (!areEqual(buf, Hex.decode(v0)))
- {
- mismatch("v0/" + rounds, v0, buf);
- }
- break;
- case 3:
- if (!areEqual(buf, Hex.decode(v192)))
- {
- mismatch("v192/" + rounds, v192, buf);
- }
- break;
- case 4:
- if (!areEqual(buf, Hex.decode(v256)))
- {
- mismatch("v256/" + rounds, v256, buf);
- }
- break;
- default:
- // ignore
- }
- }
-
- for (int i = 0; i != 64; i++)
- {
- buf[i] = chaCha.returnByte(zeroes[i]);
- }
-
- if (!areEqual(buf, Hex.decode(v448)))
- {
- mismatch("v448", v448, buf);
- }
- }
-
- private void chachaTest2(CipherParameters params, String v0, String v65472, String v65536)
- {
- StreamCipher chaCha = new ChaChaEngine();
- byte[] buf = new byte[64];
-
- chaCha.init(true, params);
-
- for (int i = 0; i != 1025; i++)
- {
- chaCha.processBytes(zeroes, 0, 64, buf, 0);
- switch (i)
- {
- case 0:
- if (!areEqual(buf, Hex.decode(v0)))
- {
- mismatch("v0", v0, buf);
- }
- break;
- case 1023:
- if (!areEqual(buf, Hex.decode(v65472)))
- {
- mismatch("v65472", v65472, buf);
- }
- break;
- case 1024:
- if (!areEqual(buf, Hex.decode(v65536)))
- {
- mismatch("v65536", v65536, buf);
- }
- break;
- default:
- // ignore
- }
- }
- }
-
- private void mismatch(String name, String expected, byte[] found)
- {
- fail("mismatch on " + name, expected, new String(Hex.encode(found)));
- }
-
-
- private void reinitBug()
- {
- KeyParameter key = new KeyParameter(Hex.decode("80000000000000000000000000000000"));
- ParametersWithIV parameters = new ParametersWithIV(key, Hex.decode("0000000000000000"));
-
- StreamCipher salsa = new ChaChaEngine();
-
- salsa.init(true, parameters);
-
- try
- {
- salsa.init(true, key);
- fail("Salsa20 should throw exception if no IV in Init");
- }
- catch (IllegalArgumentException e)
- {
- }
- }
-
- private boolean areEqual(byte[] a, int aOff, byte[] b, int bOff)
- {
- for (int i = bOff; i != b.length; i++)
- {
- if (a[aOff + i - bOff] != b[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- private void skipTest()
- {
- SecureRandom rand = new SecureRandom();
- byte[] plain = new byte[5000];
- byte[] cipher = new byte[5000];
-
- rand.nextBytes(plain);
-
- CipherParameters params = new ParametersWithIV(new KeyParameter(Hex.decode("0053A6F94C9FF24598EB3E91E4378ADD3083D6297CCF2275C81B6EC11467BA0D")), Hex.decode("0D74DB42A91077DE"));
- ChaChaEngine engine = new ChaChaEngine();
-
- engine.init(true, params);
-
- engine.processBytes(plain, 0, plain.length, cipher, 0);
-
- byte[] fragment = new byte[20];
-
- engine.init(true, params);
-
- engine.skip(10);
-
- engine.processBytes(plain, 10, fragment.length, fragment, 0);
-
- if (!areEqual(cipher, 10, fragment, 0))
- {
- fail("skip forward 10 failed");
- }
-
- engine.skip(1000);
-
- engine.processBytes(plain, 1010 + fragment.length, fragment.length, fragment, 0);
-
- if (!areEqual(cipher, 1010 + fragment.length, fragment, 0))
- {
- fail("skip forward 1000 failed");
- }
-
- engine.skip(-10);
-
- engine.processBytes(plain, 1010 + 2 * fragment.length - 10, fragment.length, fragment, 0);
-
- if (!areEqual(cipher, 1010 + 2 * fragment.length - 10, fragment, 0))
- {
- fail("skip back 10 failed");
- }
-
- engine.skip(-1000);
-
- if (engine.getPosition() != 60)
- {
- fail("skip position incorrect - " + 60 + " got " + engine.getPosition());
- }
-
- engine.processBytes(plain, 60, fragment.length, fragment, 0);
-
- if (!areEqual(cipher, 60, fragment, 0))
- {
- fail("skip back 1000 failed");
- }
-
- long pos = engine.seekTo(1010);
- if (pos != 1010)
- {
- fail("position wrong");
- }
-
- engine.processBytes(plain, 1010, fragment.length, fragment, 0);
-
- if (!areEqual(cipher, 1010, fragment, 0))
- {
- fail("seek to 1010 failed");
- }
-
- engine.reset();
-
- for (int i = 0; i != 1000; i++)
- {
- engine.skip(i);
-
- if (engine.getPosition() != i)
- {
- fail("skip forward at wrong position");
- }
-
- engine.processBytes(plain, i, fragment.length, fragment, 0);
-
- if (!areEqual(cipher, i, fragment, 0))
- {
- fail("skip forward i failed: " + i);
- }
-
- if (engine.getPosition() != i + fragment.length)
- {
- fail("cipher at wrong position: " + engine.getPosition() + " [" + i + "]");
- }
-
- engine.skip(-fragment.length);
-
- if (engine.getPosition() != i)
- {
- fail("skip back at wrong position");
- }
-
- engine.processBytes(plain, i, fragment.length, fragment, 0);
-
- if (!areEqual(cipher, i, fragment, 0))
- {
- fail("skip back i failed: " + i);
- }
-
- engine.reset();
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new ChaChaTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/CipherStreamTest.java b/core/src/test/java/org/bouncycastle/crypto/test/CipherStreamTest.java
deleted file mode 100644
index aaf20310..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/CipherStreamTest.java
+++ /dev/null
@@ -1,699 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.BufferedBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.StreamCipher;
-import org.bouncycastle.crypto.engines.AESEngine;
-import org.bouncycastle.crypto.engines.BlowfishEngine;
-import org.bouncycastle.crypto.engines.CAST5Engine;
-import org.bouncycastle.crypto.engines.CAST6Engine;
-import org.bouncycastle.crypto.engines.CamelliaEngine;
-import org.bouncycastle.crypto.engines.ChaChaEngine;
-import org.bouncycastle.crypto.engines.DESEngine;
-import org.bouncycastle.crypto.engines.DESedeEngine;
-import org.bouncycastle.crypto.engines.Grain128Engine;
-import org.bouncycastle.crypto.engines.Grainv1Engine;
-import org.bouncycastle.crypto.engines.HC128Engine;
-import org.bouncycastle.crypto.engines.HC256Engine;
-import org.bouncycastle.crypto.engines.NoekeonEngine;
-import org.bouncycastle.crypto.engines.RC2Engine;
-import org.bouncycastle.crypto.engines.RC4Engine;
-import org.bouncycastle.crypto.engines.RC6Engine;
-import org.bouncycastle.crypto.engines.SEEDEngine;
-import org.bouncycastle.crypto.engines.Salsa20Engine;
-import org.bouncycastle.crypto.engines.SerpentEngine;
-import org.bouncycastle.crypto.engines.TEAEngine;
-import org.bouncycastle.crypto.engines.ThreefishEngine;
-import org.bouncycastle.crypto.engines.TwofishEngine;
-import org.bouncycastle.crypto.engines.XSalsa20Engine;
-import org.bouncycastle.crypto.engines.XTEAEngine;
-import org.bouncycastle.crypto.io.CipherInputStream;
-import org.bouncycastle.crypto.io.CipherOutputStream;
-import org.bouncycastle.crypto.io.InvalidCipherTextIOException;
-import org.bouncycastle.crypto.modes.AEADBlockCipher;
-import org.bouncycastle.crypto.modes.CBCBlockCipher;
-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.GCMBlockCipher;
-import org.bouncycastle.crypto.modes.OCBBlockCipher;
-import org.bouncycastle.crypto.modes.OFBBlockCipher;
-import org.bouncycastle.crypto.modes.SICBlockCipher;
-import org.bouncycastle.crypto.paddings.PKCS7Padding;
-import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class CipherStreamTest
- extends SimpleTest
-{
- private int streamSize;
-
- public String getName()
- {
- return "CipherStreamTest";
- }
-
- private void testMode(Object cipher, CipherParameters params)
- throws Exception
- {
- testWriteRead(cipher, params, false);
- testWriteRead(cipher, params, true);
- testReadWrite(cipher, params, false);
- testReadWrite(cipher, params, true);
-
- if (!(cipher instanceof CTSBlockCipher))
- {
- testWriteReadEmpty(cipher, params, false);
- testWriteReadEmpty(cipher, params, true);
- }
-
- if (cipher instanceof AEADBlockCipher)
- {
- testTamperedRead((AEADBlockCipher)cipher, params);
- testTruncatedRead((AEADBlockCipher)cipher, params);
- testTamperedWrite((AEADBlockCipher)cipher, params);
- }
- }
-
- private OutputStream createCipherOutputStream(OutputStream output, Object cipher)
- {
- if (cipher instanceof BufferedBlockCipher)
- {
- return new CipherOutputStream(output, (BufferedBlockCipher)cipher);
- }
- else if (cipher instanceof AEADBlockCipher)
- {
- return new CipherOutputStream(output, (AEADBlockCipher)cipher);
- }
- else
- {
- return new CipherOutputStream(output, (StreamCipher)cipher);
- }
- }
-
- private InputStream createCipherInputStream(byte[] data, Object cipher)
- {
- ByteArrayInputStream input = new ByteArrayInputStream(data);
- if (cipher instanceof BufferedBlockCipher)
- {
- return new CipherInputStream(input, (BufferedBlockCipher)cipher);
- }
- else if (cipher instanceof AEADBlockCipher)
- {
- return new CipherInputStream(input, (AEADBlockCipher)cipher);
- }
- else
- {
- return new CipherInputStream(input, (StreamCipher)cipher);
- }
- }
-
- /**
- * Test tampering of ciphertext followed by read from decrypting CipherInputStream
- */
- private void testTamperedRead(AEADBlockCipher cipher, CipherParameters params)
- throws Exception
- {
- cipher.init(true, params);
-
- byte[] ciphertext = new byte[cipher.getOutputSize(streamSize)];
- cipher.doFinal(ciphertext, cipher.processBytes(new byte[streamSize], 0, streamSize, ciphertext, 0));
-
- // Tamper
- ciphertext[0] += 1;
-
- cipher.init(false, params);
- InputStream input = createCipherInputStream(ciphertext, cipher);
- try
- {
- while (input.read() >= 0)
- {
- }
- fail("Expected invalid ciphertext after tamper and read : " + cipher.getAlgorithmName());
- }
- catch (InvalidCipherTextIOException e)
- {
- // Expected
- }
- try
- {
- input.close();
- }
- catch (Exception e)
- {
- fail("Unexpected exception after tamper and read : " + cipher.getAlgorithmName());
- }
- }
-
- /**
- * Test truncation of ciphertext to make tag calculation impossible, followed by read from
- * decrypting CipherInputStream
- */
- private void testTruncatedRead(AEADBlockCipher cipher, CipherParameters params)
- throws Exception
- {
- cipher.init(true, params);
-
- byte[] ciphertext = new byte[cipher.getOutputSize(streamSize)];
- cipher.doFinal(ciphertext, cipher.processBytes(new byte[streamSize], 0, streamSize, ciphertext, 0));
-
- // Truncate to just smaller than complete tag
- byte[] truncated = new byte[ciphertext.length - streamSize - 1];
- System.arraycopy(ciphertext, 0, truncated, 0, truncated.length);
-
- cipher.init(false, params);
- InputStream input = createCipherInputStream(truncated, cipher);
- while (true)
- {
- int read = 0;
- try
- {
- read = input.read();
- }
- catch (InvalidCipherTextIOException e)
- {
- // Expected
- break;
- }
- catch (Exception e)
- {
- fail("Unexpected exception on truncated read : " + cipher.getAlgorithmName());
- break;
- }
- if (read < 0)
- {
- fail("Expected invalid ciphertext after truncate and read : " + cipher.getAlgorithmName());
- break;
- }
- }
- try
- {
- input.close();
- }
- catch (Exception e)
- {
- fail("Unexpected exception after truncate and read : " + cipher.getAlgorithmName());
- }
- }
-
- /**
- * Test tampering of ciphertext followed by write to decrypting CipherOutputStream
- */
- private void testTamperedWrite(AEADBlockCipher cipher, CipherParameters params)
- throws Exception
- {
- cipher.init(true, params);
-
- byte[] ciphertext = new byte[cipher.getOutputSize(streamSize)];
- cipher.doFinal(ciphertext, cipher.processBytes(new byte[streamSize], 0, streamSize, ciphertext, 0));
-
- // Tamper
- ciphertext[0] += 1;
-
- cipher.init(false, params);
- ByteArrayOutputStream plaintext = new ByteArrayOutputStream();
- OutputStream output = createCipherOutputStream(plaintext, cipher);
-
- for (int i = 0; i < ciphertext.length; i++)
- {
- output.write(ciphertext[i]);
- }
- try
- {
- output.close();
- fail("Expected invalid ciphertext after tamper and write : " + cipher.getAlgorithmName());
- }
- catch (InvalidCipherTextIOException e)
- {
- // Expected
- }
- }
-
- /**
- * Test CipherOutputStream in ENCRYPT_MODE, CipherInputStream in DECRYPT_MODE
- */
- private void testWriteRead(Object cipher, CipherParameters params, boolean blocks)
- throws Exception
- {
- byte[] data = new byte[streamSize];
- for (int i = 0; i < data.length; i++)
- {
- data[i] = (byte)(i % 255);
- }
-
- testWriteRead(cipher, params, blocks, data);
- }
-
- /**
- * Test CipherOutputStream in ENCRYPT_MODE, CipherInputStream in DECRYPT_MODE
- */
- private void testWriteReadEmpty(Object cipher, CipherParameters params, boolean blocks)
- throws Exception
- {
- byte[] data = new byte[0];
-
- testWriteRead(cipher, params, blocks, data);
- }
-
- private void testWriteRead(Object cipher, CipherParameters params, boolean blocks, byte[] data)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- try
- {
- init(cipher, true, params);
-
- OutputStream cOut = createCipherOutputStream(bOut, cipher);
- if (blocks)
- {
- int chunkSize = Math.max(1, data.length / 8);
- for (int i = 0; i < data.length; i += chunkSize)
- {
- cOut.write(data, i, Math.min(chunkSize, data.length - i));
- }
- }
- else
- {
- for (int i = 0; i < data.length; i++)
- {
- cOut.write(data[i]);
- }
- }
- cOut.close();
-
- byte[] cipherText = bOut.toByteArray();
- bOut.reset();
- init(cipher, false, params);
- InputStream cIn = createCipherInputStream(cipherText, cipher);
-
- if (blocks)
- {
- byte[] block = new byte[getBlockSize(cipher) + 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 " + getName(cipher), e);
- }
-
- byte[] decrypted = bOut.toByteArray();
- if (!Arrays.areEqual(data, decrypted))
- {
- fail("Failed - decrypted data doesn't match: " + getName(cipher));
- }
- }
-
- private String getName(Object cipher)
- {
- if (cipher instanceof BufferedBlockCipher)
- {
- return ((BufferedBlockCipher)cipher).getUnderlyingCipher().getAlgorithmName();
- }
- else if (cipher instanceof AEADBlockCipher)
- {
- return ((AEADBlockCipher)cipher).getUnderlyingCipher().getAlgorithmName();
- }
- else if (cipher instanceof StreamCipher)
- {
- return ((StreamCipher)cipher).getAlgorithmName();
- }
- return null;
- }
-
- private int getBlockSize(Object cipher)
- {
- if (cipher instanceof BlockCipher)
- {
- return ((BlockCipher)cipher).getBlockSize();
- }
- else if (cipher instanceof BufferedBlockCipher)
- {
- return ((BufferedBlockCipher)cipher).getBlockSize();
- }
- else if (cipher instanceof AEADBlockCipher)
- {
- return ((AEADBlockCipher)cipher).getUnderlyingCipher().getBlockSize();
- }
- else if (cipher instanceof StreamCipher)
- {
- return 1;
- }
- return 0;
- }
-
- private void init(Object cipher, boolean forEncrypt, CipherParameters params)
- {
- if (cipher instanceof BufferedBlockCipher)
- {
- ((BufferedBlockCipher)cipher).init(forEncrypt, params);
- }
- else if (cipher instanceof AEADBlockCipher)
- {
- ((AEADBlockCipher)cipher).init(forEncrypt, params);
- }
- else if (cipher instanceof StreamCipher)
- {
- ((StreamCipher)cipher).init(forEncrypt, params);
- }
- }
-
- 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);
- }
- }
-
- /**
- * Test CipherInputStream in ENCRYPT_MODE, CipherOutputStream in DECRYPT_MODE
- */
- private void testReadWrite(Object cipher, CipherParameters params, boolean blocks)
- throws Exception
- {
- String lCode = "ABCDEFGHIJKLMNOPQRSTU";
-
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- try
- {
- init(cipher, true, params);
-
- InputStream cIn = createCipherInputStream(lCode.getBytes(), cipher);
- ByteArrayOutputStream ct = new ByteArrayOutputStream();
-
- if (blocks)
- {
- byte[] block = new byte[getBlockSize(cipher) + 1];
- int c;
- while ((c = cIn.read(block)) >= 0)
- {
- ct.write(block, 0, c);
- }
- }
- else
- {
- int c;
- while ((c = cIn.read()) >= 0)
- {
- ct.write(c);
- }
- }
- cIn.close();
-
- init(cipher, false, params);
- ByteArrayInputStream dataIn = new ByteArrayInputStream(ct.toByteArray());
- OutputStream cOut = createCipherOutputStream(bOut, cipher);
-
- if (blocks)
- {
- byte[] block = new byte[getBlockSize(cipher) + 1];
- int c;
- while ((c = dataIn.read(block)) >= 0)
- {
- cOut.write(block, 0, c);
- }
- }
- else
- {
- int c;
- while ((c = dataIn.read()) >= 0)
- {
- cOut.write(c);
- }
- }
- cOut.flush();
- cOut.close();
-
- }
- catch (Exception e)
- {
- fail("Unexpected exception " + getName(cipher), e);
- }
-
- String res = new String(bOut.toByteArray());
- if (!res.equals(lCode))
- {
- fail("Failed read/write - decrypted data doesn't match: " + getName(cipher), lCode, res);
- }
- }
-
- public void performTest()
- throws Exception
- {
- int[] testSizes = new int[]{0, 1, 7, 8, 9, 15, 16, 17, 1023, 1024, 1025, 2047, 2048, 2049, 4095, 4096, 4097};
- for (int i = 0; i < testSizes.length; i++)
- {
- this.streamSize = testSizes[i];
- performTests();
- }
- }
-
- private void performTests()
- throws Exception
- {
- testModes(new BlowfishEngine(), new BlowfishEngine(), 16);
- testModes(new DESEngine(), new DESEngine(), 8);
- testModes(new DESedeEngine(), new DESedeEngine(), 24);
- testModes(new TEAEngine(), new TEAEngine(), 16);
- testModes(new CAST5Engine(), new CAST5Engine(), 16);
- testModes(new RC2Engine(), new RC2Engine(), 16);
- testModes(new XTEAEngine(), new XTEAEngine(), 16);
-
- testModes(new AESEngine(), new AESEngine(), 16);
- testModes(new NoekeonEngine(), new NoekeonEngine(), 16);
- testModes(new TwofishEngine(), new TwofishEngine(), 16);
- testModes(new CAST6Engine(), new CAST6Engine(), 16);
- testModes(new SEEDEngine(), new SEEDEngine(), 16);
- testModes(new SerpentEngine(), new SerpentEngine(), 16);
- testModes(new RC6Engine(), new RC6Engine(), 16);
- testModes(new CamelliaEngine(), new CamelliaEngine(), 16);
- testModes(new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512),
- new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512), 64);
-
- testMode(new RC4Engine(), new KeyParameter(new byte[16]));
- testMode(new Salsa20Engine(), new ParametersWithIV(new KeyParameter(new byte[16]), new byte[8]));
- testMode(new XSalsa20Engine(), new ParametersWithIV(new KeyParameter(new byte[32]), new byte[24]));
- testMode(new ChaChaEngine(), new ParametersWithIV(new KeyParameter(new byte[16]), new byte[8]));
- testMode(new Grainv1Engine(), new ParametersWithIV(new KeyParameter(new byte[16]), new byte[8]));
- testMode(new Grain128Engine(), new ParametersWithIV(new KeyParameter(new byte[16]), new byte[12]));
- testMode(new HC128Engine(), new KeyParameter(new byte[16]));
- testMode(new HC256Engine(), new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]));
-
- testSkipping(new Salsa20Engine(), new ParametersWithIV(new KeyParameter(new byte[16]), new byte[8]));
- testSkipping(new SICBlockCipher(new AESEngine()), new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]));
- }
-
- private void testModes(BlockCipher cipher1, BlockCipher cipher2, int keySize)
- throws Exception
- {
- final KeyParameter key = new KeyParameter(new byte[keySize]);
- final int blockSize = getBlockSize(cipher1);
- final CipherParameters withIv = new ParametersWithIV(key, new byte[blockSize]);
-
- if (blockSize > 1)
- {
- testMode(new PaddedBufferedBlockCipher(cipher1, new PKCS7Padding()), key);
-
- testMode(new PaddedBufferedBlockCipher(new CBCBlockCipher(cipher1), new PKCS7Padding()), withIv);
-
- testMode(new BufferedBlockCipher(new OFBBlockCipher(cipher1, blockSize)), withIv);
- testMode(new BufferedBlockCipher(new CFBBlockCipher(cipher1, blockSize)), withIv);
- testMode(new BufferedBlockCipher(new SICBlockCipher(cipher1)), withIv);
- }
- // CTS requires at least one block
- if (blockSize <= 16 && streamSize >= blockSize)
- {
- testMode(new CTSBlockCipher(cipher1), key);
- }
- if (blockSize == 8 || blockSize == 16)
- {
- testMode(new EAXBlockCipher(cipher1), withIv);
- }
- if (blockSize == 16)
- {
- testMode(new CCMBlockCipher(cipher1), new ParametersWithIV(key, new byte[7]));
- testMode(new GCMBlockCipher(cipher1), withIv);
- testMode(new OCBBlockCipher(cipher1, cipher2), new ParametersWithIV(key, new byte[15]));
- }
- }
-
- private void testSkipping(StreamCipher cipher, CipherParameters params)
- throws Exception
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- init(cipher, true, params);
-
- OutputStream cOut = createCipherOutputStream(bOut, cipher);
- byte[] data = new byte[5000];
-
- new SecureRandom().nextBytes(data);
-
- cOut.write(data);
-
- cOut.close();
-
- init(cipher, false, params);
-
- InputStream cIn = createCipherInputStream(bOut.toByteArray(), cipher);
-
- long skip = cIn.skip(50);
- if (skip != 50)
- {
- fail("wrong number of bytes skipped: " + skip);
- }
-
- byte[] block = new byte[50];
-
- cIn.read(block);
-
- if (!areEqual(data, 50, block, 0))
- {
- fail("initial skip mismatch");
- }
-
- skip = cIn.skip(3000);
- if (skip != 3000)
- {
- fail("wrong number of bytes skipped: " + skip);
- }
-
- cIn.read(block);
-
- if (!areEqual(data, 3100, block, 0))
- {
- fail("second skip mismatch");
- }
-
- cipher.reset();
-
- cIn = createCipherInputStream(bOut.toByteArray(), cipher);
- if (!cIn.markSupported())
- {
- fail("marking not supported");
- }
-
- cIn.mark(100);
-
- cIn.read(block);
-
- if (!areEqual(data, 0, block, 0))
- {
- fail("initial mark read failed");
- }
-
- cIn.reset();
-
- cIn.read(block);
-
- if (!areEqual(data, 0, block, 0))
- {
- fail(cipher.getAlgorithmName() + " initial reset read failed");
- }
-
- cIn.reset();
-
- cIn.read(block);
-
- cIn.mark(100);
-
- cIn.read(block);
-
- if (!areEqual(data, 50, block, 0))
- {
- fail("second mark read failed");
- }
-
- cIn.reset();
-
- cIn.read(block);
-
- if (!areEqual(data, 50, block, 0))
- {
- fail(cipher.getAlgorithmName() + " second reset read failed");
- }
-
- cIn.mark(3000);
-
- skip = cIn.skip(2050);
- if (skip != 2050)
- {
- fail("wrong number of bytes skipped: " + skip);
- }
-
- cIn.reset();
-
- cIn.read(block);
-
- if (!areEqual(data, 100, block, 0))
- {
- fail(cipher.getAlgorithmName() + " third reset read failed");
- }
-
- cIn.read(new byte[2150]);
-
- cIn.reset();
-
- cIn.read(block);
-
- if (!areEqual(data, 100, block, 0))
- {
- fail(cipher.getAlgorithmName() + " fourth reset read failed");
- }
-
- cIn.close();
- }
-
- private boolean areEqual(byte[] a, int aOff, byte[] b, int bOff)
- {
- for (int i = bOff; i != b.length; i++)
- {
- if (a[aOff + i - bOff] != b[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- public static void main(String[] args)
- {
- runTest(new CipherStreamTest());
- }
-
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/CipherTest.java b/core/src/test/java/org/bouncycastle/crypto/test/CipherTest.java
deleted file mode 100644
index 407a0440..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/CipherTest.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.test.SimpleTest;
-
-public abstract class CipherTest
- extends SimpleTest
-{
- private SimpleTest[] _tests;
- private BlockCipher _engine;
- private KeyParameter _validKey;
-
-// protected CipherTest(
-// SimpleTest[] tests)
-// {
-// _tests = tests;
-// }
-
- protected CipherTest(
- SimpleTest[] tests,
- BlockCipher engine,
- KeyParameter validKey)
- {
- _tests = tests;
- _engine = engine;
- _validKey = validKey;
- }
-
- public abstract String getName();
-
- public void performTest()
- throws Exception
- {
- for (int i = 0; i != _tests.length; i++)
- {
- _tests[i].performTest();
- }
-
- if (_engine != null)
- {
- //
- // state tests
- //
- byte[] buf = new byte[128];
-
- try
- {
- _engine.processBlock(buf, 0, buf, 0);
-
- fail("failed initialisation check");
- }
- catch (IllegalStateException e)
- {
- // expected
- }
-
- bufferSizeCheck((_engine));
- }
- }
-
- private void bufferSizeCheck(
- BlockCipher engine)
- {
- byte[] correctBuf = new byte[engine.getBlockSize()];
- byte[] shortBuf = new byte[correctBuf.length / 2];
-
- engine.init(true, _validKey);
-
- try
- {
- engine.processBlock(shortBuf, 0, correctBuf, 0);
-
- fail("failed short input check");
- }
- catch (DataLengthException e)
- {
- // expected
- }
-
- try
- {
- engine.processBlock(correctBuf, 0, shortBuf, 0);
-
- fail("failed short output check");
- }
- catch (DataLengthException e)
- {
- // expected
- }
-
- engine.init(false, _validKey);
-
- try
- {
- engine.processBlock(shortBuf, 0, correctBuf, 0);
-
- fail("failed short input check");
- }
- catch (DataLengthException e)
- {
- // expected
- }
-
- try
- {
- engine.processBlock(correctBuf, 0, shortBuf, 0);
-
- fail("failed short output check");
- }
- catch (DataLengthException e)
- {
- // expected
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/CramerShoupTest.java b/core/src/test/java/org/bouncycastle/crypto/test/CramerShoupTest.java
deleted file mode 100644
index e9633572..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/CramerShoupTest.java
+++ /dev/null
@@ -1,147 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.agreement.DHStandardGroups;
-import org.bouncycastle.crypto.engines.CramerShoupCiphertext;
-import org.bouncycastle.crypto.engines.CramerShoupCoreEngine;
-import org.bouncycastle.crypto.engines.CramerShoupCoreEngine.CramerShoupCiphertextException;
-import org.bouncycastle.crypto.generators.CramerShoupKeyPairGenerator;
-import org.bouncycastle.crypto.generators.CramerShoupParametersGenerator;
-import org.bouncycastle.crypto.params.CramerShoupKeyGenerationParameters;
-import org.bouncycastle.crypto.params.CramerShoupParameters;
-import org.bouncycastle.util.BigIntegers;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class CramerShoupTest
- extends SimpleTest
-{
- private static final BigInteger ONE = BigInteger.valueOf(1);
-
- private static final SecureRandom RND = new SecureRandom();
-
- private AsymmetricCipherKeyPair keyPair;
-
- public static void main(String[] args)
- {
- runTest(new CramerShoupTest());
- }
-
- public String getName()
- {
- return "CramerShoup";
- }
-
-
- public void performTest()
- throws Exception
- {
- BigInteger pSubOne = DHStandardGroups.rfc3526_2048.getP().subtract(ONE);
- for (int i = 0; i < 10; ++i)
- {
- BigInteger message = BigIntegers.createRandomInRange(ONE, pSubOne, RND);
-
- BigInteger m1 = encDecTest(message);
- BigInteger m2 = labelledEncDecTest(message, "myRandomLabel");
- BigInteger m3 = encDecEncodingTest(message);
- BigInteger m4 = labelledEncDecEncodingTest(message, "myOtherCoolLabel");
-
- if (!message.equals(m1) || !message.equals(m2) || !message.equals(m3) || !message.equals(m4))
- {
- fail("decrypted message != original message");
- }
- }
- }
-
- private BigInteger encDecEncodingTest(BigInteger m)
- {
- CramerShoupCiphertext ciphertext = encrypt(m);
- byte[] c = ciphertext.toByteArray();
- CramerShoupCiphertext decC = new CramerShoupCiphertext(c);
- return decrypt(decC);
- }
-
- private BigInteger labelledEncDecEncodingTest(BigInteger m, String l)
- {
- byte[] c = encrypt(m, l).toByteArray();
- return decrypt(new CramerShoupCiphertext(c), l);
- }
-
- private BigInteger encDecTest(BigInteger m)
- {
- CramerShoupCiphertext c = encrypt(m);
- return decrypt(c);
- }
-
- private BigInteger labelledEncDecTest(BigInteger m, String l)
- {
- CramerShoupCiphertext c = encrypt(m, l);
- return decrypt(c, l);
- }
-
-
- private BigInteger decrypt(CramerShoupCiphertext ciphertext)
- {
- return decrypt(ciphertext, null);
- }
-
- private BigInteger decrypt(CramerShoupCiphertext ciphertext, String label)
- {
-
- CramerShoupCoreEngine engine = new CramerShoupCoreEngine();
- if (label != null)
- {
- engine.init(false, keyPair.getPrivate(), label);
- }
- else
- {
- engine.init(false, keyPair.getPrivate());
- }
- try
- {
- BigInteger m = engine.decryptBlock(ciphertext);
-
- return m;
- }
- catch (CramerShoupCiphertextException e)
- {
- e.printStackTrace();
- }
-
- return null;
- }
-
- private CramerShoupCiphertext encrypt(BigInteger message)
- {
- return encrypt(message, null);
- }
-
- private CramerShoupCiphertext encrypt(BigInteger message, String label)
- {
- CramerShoupKeyPairGenerator kpGen = new CramerShoupKeyPairGenerator();
- CramerShoupParametersGenerator pGen = new CramerShoupParametersGenerator();
-
- pGen.init(2048, 1, RND);
- CramerShoupParameters params = pGen.generateParameters(DHStandardGroups.rfc3526_2048);
- CramerShoupKeyGenerationParameters param = new CramerShoupKeyGenerationParameters(RND, params);
-
- kpGen.init(param);
- keyPair = kpGen.generateKeyPair();
-
- CramerShoupCoreEngine engine = new CramerShoupCoreEngine();
- if (label != null)
- {
- engine.init(true, keyPair.getPublic(), label);
- }
- else
- {
- engine.init(true, keyPair.getPublic());
- }
-
- CramerShoupCiphertext ciphertext = engine.encryptBlock(message);
-
- return ciphertext;
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/DESTest.java b/core/src/test/java/org/bouncycastle/crypto/test/DESTest.java
deleted file mode 100644
index 08056fc4..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/DESTest.java
+++ /dev/null
@@ -1,206 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.engines.DESEngine;
-import org.bouncycastle.crypto.generators.DESKeyGenerator;
-import org.bouncycastle.crypto.modes.CBCBlockCipher;
-import org.bouncycastle.crypto.modes.CFBBlockCipher;
-import org.bouncycastle.crypto.modes.OFBBlockCipher;
-import org.bouncycastle.crypto.params.DESParameters;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-import java.security.SecureRandom;
-
-class DESParityTest
- extends SimpleTest
-{
- public String getName()
- {
- return "DESParityTest";
- }
-
- public void performTest()
- {
- byte[] k1In = { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff,
- (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff };
- byte[] k1Out = { (byte)0xfe, (byte)0xfe, (byte)0xfe, (byte)0xfe,
- (byte)0xfe, (byte)0xfe, (byte)0xfe, (byte)0xfe };
-
- byte[] k2In = { (byte)0xef, (byte)0xcb, (byte)0xda, (byte)0x4f,
- (byte)0xaa, (byte)0x99, (byte)0x7f, (byte)0x63 };
- byte[] k2Out = { (byte)0xef, (byte)0xcb, (byte)0xda, (byte)0x4f,
- (byte)0xab, (byte)0x98, (byte)0x7f, (byte)0x62 };
-
- DESParameters.setOddParity(k1In);
-
- for (int i = 0; i != k1In.length; i++)
- {
- if (k1In[i] != k1Out[i])
- {
- fail("Failed "
- + "got " + new String(Hex.encode(k1In))
- + " expected " + new String(Hex.encode(k1Out)));
- }
- }
-
- DESParameters.setOddParity(k2In);
-
- for (int i = 0; i != k2In.length; i++)
- {
- if (k2In[i] != k2Out[i])
- {
- fail("Failed "
- + "got " + new String(Hex.encode(k2In))
- + " expected " + new String(Hex.encode(k2Out)));
- }
- }
- }
-}
-
-class KeyGenTest
- extends SimpleTest
-{
- public String getName()
- {
- return "KeyGenTest";
- }
-
- public void performTest()
- {
- DESKeyGenerator keyGen = new DESKeyGenerator();
-
- keyGen.init(new KeyGenerationParameters(new SecureRandom(), 56));
-
- byte[] kB = keyGen.generateKey();
-
- if (kB.length != 8)
- {
- fail("DES bit key wrong length.");
- }
- }
-}
-
-class DESParametersTest
- extends SimpleTest
-{
- static private byte[] weakKeys =
- {
- (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01, (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01,
- (byte)0x1f,(byte)0x1f,(byte)0x1f,(byte)0x1f, (byte)0x0e,(byte)0x0e,(byte)0x0e,(byte)0x0e,
- (byte)0xe0,(byte)0xe0,(byte)0xe0,(byte)0xe0, (byte)0xf1,(byte)0xf1,(byte)0xf1,(byte)0xf1,
- (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe, (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe,
- /* semi-weak keys */
- (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe, (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe,
- (byte)0x1f,(byte)0xe0,(byte)0x1f,(byte)0xe0, (byte)0x0e,(byte)0xf1,(byte)0x0e,(byte)0xf1,
- (byte)0x01,(byte)0xe0,(byte)0x01,(byte)0xe0, (byte)0x01,(byte)0xf1,(byte)0x01,(byte)0xf1,
- (byte)0x1f,(byte)0xfe,(byte)0x1f,(byte)0xfe, (byte)0x0e,(byte)0xfe,(byte)0x0e,(byte)0xfe,
- (byte)0x01,(byte)0x1f,(byte)0x01,(byte)0x1f, (byte)0x01,(byte)0x0e,(byte)0x01,(byte)0x0e,
- (byte)0xe0,(byte)0xfe,(byte)0xe0,(byte)0xfe, (byte)0xf1,(byte)0xfe,(byte)0xf1,(byte)0xfe,
- (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01, (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01,
- (byte)0xe0,(byte)0x1f,(byte)0xe0,(byte)0x1f, (byte)0xf1,(byte)0x0e,(byte)0xf1,(byte)0x0e,
- (byte)0xe0,(byte)0x01,(byte)0xe0,(byte)0x01, (byte)0xf1,(byte)0x01,(byte)0xf1,(byte)0x01,
- (byte)0xfe,(byte)0x1f,(byte)0xfe,(byte)0x1f, (byte)0xfe,(byte)0x0e,(byte)0xfe,(byte)0x0e,
- (byte)0x1f,(byte)0x01,(byte)0x1f,(byte)0x01, (byte)0x0e,(byte)0x01,(byte)0x0e,(byte)0x01,
- (byte)0xfe,(byte)0xe0,(byte)0xfe,(byte)0xe0, (byte)0xfe,(byte)0xf1,(byte)0xfe,(byte)0xf1
- };
-
- public String getName()
- {
- return "DESParameters";
- }
-
- public void performTest() throws Exception
- {
- try
- {
- DESParameters.isWeakKey(new byte[4], 0);
- fail("no exception on small key");
- }
- catch (IllegalArgumentException e)
- {
- if (!e.getMessage().equals("key material too short."))
- {
- fail("wrong exception");
- }
- }
-
- try
- {
- new DESParameters(weakKeys);
- fail("no exception on weak key");
- }
- catch (IllegalArgumentException e)
- {
- if (!e.getMessage().equals("attempt to create weak DES key"))
- {
- fail("wrong exception");
- }
- }
-
- for (int i = 0; i != weakKeys.length; i += 8)
- {
- if (!DESParameters.isWeakKey(weakKeys, i))
- {
- fail("weakKey test failed");
- }
- }
- }
-}
-
-/**
- * DES tester - vectors from <a href=http://www.itl.nist.gov/fipspubs/fip81.htm>FIPS 81</a>
- */
-public class DESTest
- extends CipherTest
-{
- static String input1 = "4e6f77206973207468652074696d6520666f7220616c6c20";
- static String input2 = "4e6f7720697320746865";
- static String input3 = "4e6f7720697320746865aabbcc";
-
- static SimpleTest[] tests =
- {
- new BlockCipherVectorTest(0, new DESEngine(),
- new KeyParameter(Hex.decode("0123456789abcdef")),
- input1, "3fa40e8a984d48156a271787ab8883f9893d51ec4b563b53"),
- new BlockCipherVectorTest(1, new CBCBlockCipher(new DESEngine()),
- new ParametersWithIV(new KeyParameter(Hex.decode("0123456789abcdef")), Hex.decode("1234567890abcdef")),
- input1, "e5c7cdde872bf27c43e934008c389c0f683788499a7c05f6"),
- new BlockCipherVectorTest(2, new CFBBlockCipher(new DESEngine(), 8),
- new ParametersWithIV(new KeyParameter(Hex.decode("0123456789abcdef")), Hex.decode("1234567890abcdef")),
- input2, "f31fda07011462ee187f"),
- new BlockCipherVectorTest(3, new CFBBlockCipher(new DESEngine(), 64),
- new ParametersWithIV(new KeyParameter(Hex.decode("0123456789abcdef")), Hex.decode("1234567890abcdef")),
- input1, "f3096249c7f46e51a69e839b1a92f78403467133898ea622"),
- new BlockCipherVectorTest(4, new OFBBlockCipher(new DESEngine(), 8),
- new ParametersWithIV(new KeyParameter(Hex.decode("0123456789abcdef")), Hex.decode("1234567890abcdef")),
- input2, "f34a2850c9c64985d684"),
- new BlockCipherVectorTest(5, new CFBBlockCipher(new DESEngine(), 64),
- new ParametersWithIV(new KeyParameter(Hex.decode("0123456789abcdef")), Hex.decode("1234567890abcdef")),
- input3, "f3096249c7f46e51a69e0954bf"),
- new BlockCipherVectorTest(6, new OFBBlockCipher(new DESEngine(), 64),
- new ParametersWithIV(new KeyParameter(Hex.decode("0123456789abcdef")), Hex.decode("1234567890abcdef")),
- input3, "f3096249c7f46e5135f2c0eb8b"),
- new DESParityTest(),
- new DESParametersTest(),
- new KeyGenTest()
- };
-
- public DESTest()
- {
- super(tests, new DESEngine(), new KeyParameter(new byte[8]));
- }
-
- public String getName()
- {
- return "DES";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new DESTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/DESedeTest.java b/core/src/test/java/org/bouncycastle/crypto/test/DESedeTest.java
deleted file mode 100644
index b14897fa..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/DESedeTest.java
+++ /dev/null
@@ -1,177 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.Wrapper;
-import org.bouncycastle.crypto.engines.DESedeEngine;
-import org.bouncycastle.crypto.engines.DESedeWrapEngine;
-import org.bouncycastle.crypto.generators.DESedeKeyGenerator;
-import org.bouncycastle.crypto.params.DESedeParameters;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-import java.security.SecureRandom;
-
-/**
- * DESede tester
- */
-public class DESedeTest
- extends CipherTest
-{
- static private byte[] weakKey = // first 8 bytes non-weak
- {
- (byte)0x06,(byte)0x01,(byte)0x01,(byte)0x01, (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01,
- (byte)0x1f,(byte)0x1f,(byte)0x1f,(byte)0x1f, (byte)0x0e,(byte)0x0e,(byte)0x0e,(byte)0x0e,
- (byte)0xe0,(byte)0xe0,(byte)0xe0,(byte)0xe0, (byte)0xf1,(byte)0xf1,(byte)0xf1,(byte)0xf1,
- };
-
- static String input1 = "4e6f77206973207468652074696d6520666f7220616c6c20";
- static String input2 = "4e6f7720697320746865";
-
- static SimpleTest[] tests =
- {
- new BlockCipherVectorTest(0, new DESedeEngine(),
- new DESedeParameters(Hex.decode("0123456789abcdef0123456789abcdef")),
- input1, "3fa40e8a984d48156a271787ab8883f9893d51ec4b563b53"),
- new BlockCipherVectorTest(1, new DESedeEngine(),
- new DESedeParameters(Hex.decode("0123456789abcdeffedcba9876543210")),
- input1, "d80a0d8b2bae5e4e6a0094171abcfc2775d2235a706e232c"),
- new BlockCipherVectorTest(2, new DESedeEngine(),
- new DESedeParameters(Hex.decode("0123456789abcdef0123456789abcdef0123456789abcdef")),
- input1, "3fa40e8a984d48156a271787ab8883f9893d51ec4b563b53"),
- new BlockCipherVectorTest(3, new DESedeEngine(),
- new DESedeParameters(Hex.decode("0123456789abcdeffedcba98765432100123456789abcdef")),
- input1, "d80a0d8b2bae5e4e6a0094171abcfc2775d2235a706e232c")
- };
-
- DESedeTest()
- {
- super(tests, new DESedeEngine(), new KeyParameter(new byte[16]));
- }
-
- private void wrapTest(
- int id,
- byte[] kek,
- byte[] iv,
- byte[] in,
- byte[] out)
- {
- Wrapper wrapper = new DESedeWrapEngine();
-
- wrapper.init(true, new ParametersWithIV(new KeyParameter(kek), iv));
-
- try
- {
- byte[] cText = wrapper.wrap(in, 0, in.length);
- if (!areEqual(cText, out))
- {
- fail(": failed wrap test " + id + " expected " + new String(Hex.encode(out)) + " got " + new String(Hex.encode(cText)));
- }
- }
- catch (Exception e)
- {
- fail("failed wrap test exception: " + e.toString(), e);
- }
-
- wrapper.init(false, new KeyParameter(kek));
-
- try
- {
- byte[] pText = wrapper.unwrap(out, 0, out.length);
- if (!areEqual(pText, in))
- {
- fail("failed unwrap test " + id + " expected " + new String(Hex.encode(in)) + " got " + new String(Hex.encode(pText)));
- }
- }
- catch (Exception e)
- {
- fail("failed unwrap test exception: " + e.toString(), e);
- }
- }
-
- public void performTest()
- throws Exception
- {
- super.performTest();
-
- byte[] kek1 = Hex.decode("255e0d1c07b646dfb3134cc843ba8aa71f025b7c0838251f");
- byte[] iv1 = Hex.decode("5dd4cbfc96f5453b");
- byte[] in1 = Hex.decode("2923bf85e06dd6ae529149f1f1bae9eab3a7da3d860d3e98");
- byte[] out1 = Hex.decode("690107618ef092b3b48ca1796b234ae9fa33ebb4159604037db5d6a84eb3aac2768c632775a467d4");
-
- wrapTest(1, kek1, iv1, in1, out1);
-
- //
- // key generation
- //
- SecureRandom random = new SecureRandom();
- DESedeKeyGenerator keyGen = new DESedeKeyGenerator();
-
- keyGen.init(new KeyGenerationParameters(random, 112));
-
- byte[] kB = keyGen.generateKey();
-
- if (kB.length != 16)
- {
- fail("112 bit key wrong length.");
- }
-
- keyGen.init(new KeyGenerationParameters(random, 168));
-
- kB = keyGen.generateKey();
-
- if (kB.length != 24)
- {
- fail("168 bit key wrong length.");
- }
-
- try
- {
- keyGen.init(new KeyGenerationParameters(random, 200));
-
- fail("invalid key length not detected.");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- try
- {
- DESedeParameters.isWeakKey(new byte[4], 0);
- fail("no exception on small key");
- }
- catch (IllegalArgumentException e)
- {
- if (!e.getMessage().equals("key material too short."))
- {
- fail("wrong exception");
- }
- }
-
- try
- {
- new DESedeParameters(weakKey);
- fail("no exception on weak key");
- }
- catch (IllegalArgumentException e)
- {
- if (!e.getMessage().equals("attempt to create weak DESede key"))
- {
- fail("wrong exception");
- }
- }
- }
-
- public String getName()
- {
- return "DESede";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new DESedeTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/DHKEKGeneratorTest.java b/core/src/test/java/org/bouncycastle/crypto/test/DHKEKGeneratorTest.java
deleted file mode 100644
index 8a83d2a3..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/DHKEKGeneratorTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.crypto.DerivationFunction;
-import org.bouncycastle.crypto.DerivationParameters;
-import org.bouncycastle.crypto.agreement.kdf.DHKDFParameters;
-import org.bouncycastle.crypto.agreement.kdf.DHKEKGenerator;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * DHKEK Generator tests - from RFC 2631.
- */
-public class DHKEKGeneratorTest
- extends SimpleTest
-{
- private byte[] seed1 = Hex.decode("000102030405060708090a0b0c0d0e0f10111213");
- private ASN1ObjectIdentifier alg1 = PKCSObjectIdentifiers.id_alg_CMS3DESwrap;
- private byte[] result1 = Hex.decode("a09661392376f7044d9052a397883246b67f5f1ef63eb5fb");
-
- private byte[] seed2 = Hex.decode("000102030405060708090a0b0c0d0e0f10111213");
- private ASN1ObjectIdentifier alg2 = PKCSObjectIdentifiers.id_alg_CMSRC2wrap;
- private byte[] partyAInfo = Hex.decode(
- "0123456789abcdeffedcba9876543201"
- + "0123456789abcdeffedcba9876543201"
- + "0123456789abcdeffedcba9876543201"
- + "0123456789abcdeffedcba9876543201");
- private byte[] result2 = Hex.decode("48950c46e0530075403cce72889604e0");
-
- public DHKEKGeneratorTest()
- {
- }
-
- public void performTest()
- {
- checkMask(1, new DHKEKGenerator(new SHA1Digest()), new DHKDFParameters(alg1, 192, seed1), result1);
- checkMask(2, new DHKEKGenerator(new SHA1Digest()), new DHKDFParameters(alg2, 128, seed2, partyAInfo), result2);
- }
-
- private void checkMask(
- int count,
- DerivationFunction kdf,
- DerivationParameters params,
- byte[] result)
- {
- byte[] data = new byte[result.length];
-
- kdf.init(params);
-
- kdf.generateBytes(data, 0, data.length);
-
- if (!areEqual(result, data))
- {
- fail("DHKEKGenerator failed generator test " + count);
- }
- }
-
- public String getName()
- {
- return "DHKEKGenerator";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new DHKEKGeneratorTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/DHTest.java b/core/src/test/java/org/bouncycastle/crypto/test/DHTest.java
deleted file mode 100644
index 862b9f25..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/DHTest.java
+++ /dev/null
@@ -1,414 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.agreement.DHAgreement;
-import org.bouncycastle.crypto.agreement.DHBasicAgreement;
-import org.bouncycastle.crypto.generators.DHBasicKeyPairGenerator;
-import org.bouncycastle.crypto.generators.DHKeyPairGenerator;
-import org.bouncycastle.crypto.generators.DHParametersGenerator;
-import org.bouncycastle.crypto.params.DHKeyGenerationParameters;
-import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
-import org.bouncycastle.crypto.params.DHPublicKeyParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class DHTest
- extends SimpleTest
-{
- private BigInteger g512 = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16);
- private BigInteger p512 = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16);
-
- private BigInteger g768 = new BigInteger("7c240073c1316c621df461b71ebb0cdcc90a6e5527e5e126633d131f87461c4dc4afc60c2cb0f053b6758871489a69613e2a8b4c8acde23954c08c81cbd36132cfd64d69e4ed9f8e51ed6e516297206672d5c0a69135df0a5dcf010d289a9ca1", 16);
- private BigInteger p768 = new BigInteger("8c9dd223debed1b80103b8b309715be009d48860ed5ae9b9d5d8159508efd802e3ad4501a7f7e1cfec78844489148cd72da24b21eddd01aa624291c48393e277cfc529e37075eccef957f3616f962d15b44aeab4039d01b817fde9eaa12fd73f", 16);
-
- private BigInteger g1024 = new BigInteger("1db17639cdf96bc4eabba19454f0b7e5bd4e14862889a725c96eb61048dcd676ceb303d586e30f060dbafd8a571a39c4d823982117da5cc4e0f89c77388b7a08896362429b94a18a327604eb7ff227bffbc83459ade299e57b5f77b50fb045250934938efa145511166e3197373e1b5b1e52de713eb49792bedde722c6717abf", 16);
- private BigInteger p1024 = new BigInteger("a00e283b3c624e5b2b4d9fbc2653b5185d99499b00fd1bf244c6f0bb817b4d1c451b2958d62a0f8a38caef059fb5ecd25d75ed9af403f5b5bdab97a642902f824e3c13789fed95fa106ddfe0ff4a707c85e2eb77d49e68f2808bcea18ce128b178cd287c6bc00efa9a1ad2a673fe0dceace53166f75b81d6709d5f8af7c66bb7", 16);
-
- public String getName()
- {
- return "DH";
- }
-
- private void testDH(
- int size,
- BigInteger g,
- BigInteger p)
- {
- DHKeyPairGenerator kpGen = getDHKeyPairGenerator(g, p);
-
- //
- // generate first pair
- //
- AsymmetricCipherKeyPair pair = kpGen.generateKeyPair();
-
- DHPublicKeyParameters pu1 = (DHPublicKeyParameters)pair.getPublic();
- DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.getPrivate();
- //
- // generate second pair
- //
- pair = kpGen.generateKeyPair();
-
- DHPublicKeyParameters pu2 = (DHPublicKeyParameters)pair.getPublic();
- DHPrivateKeyParameters pv2 = (DHPrivateKeyParameters)pair.getPrivate();
-
- //
- // two way
- //
- DHAgreement e1 = new DHAgreement();
- DHAgreement e2 = new DHAgreement();
-
- e1.init(pv1);
- e2.init(pv2);
-
- BigInteger m1 = e1.calculateMessage();
- BigInteger m2 = e2.calculateMessage();
-
- BigInteger k1 = e1.calculateAgreement(pu2, m2);
- BigInteger k2 = e2.calculateAgreement(pu1, m1);
-
- if (!k1.equals(k2))
- {
- fail(size + " bit 2-way test failed");
- }
- }
-
- private void testDHBasic(
- int size,
- int privateValueSize,
- BigInteger g,
- BigInteger p)
- {
- DHBasicKeyPairGenerator kpGen = getDHBasicKeyPairGenerator(g, p, privateValueSize);
-
- //
- // generate first pair
- //
- AsymmetricCipherKeyPair pair = kpGen.generateKeyPair();
-
- DHPublicKeyParameters pu1 = (DHPublicKeyParameters)pair.getPublic();
- DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.getPrivate();
-
- checkKeySize(privateValueSize, pv1);
- //
- // generate second pair
- //
- pair = kpGen.generateKeyPair();
-
- DHPublicKeyParameters pu2 = (DHPublicKeyParameters)pair.getPublic();
- DHPrivateKeyParameters pv2 = (DHPrivateKeyParameters)pair.getPrivate();
-
- checkKeySize(privateValueSize, pv2);
- //
- // two way
- //
- DHBasicAgreement e1 = new DHBasicAgreement();
- DHBasicAgreement e2 = new DHBasicAgreement();
-
- e1.init(pv1);
- e2.init(pv2);
-
- BigInteger k1 = e1.calculateAgreement(pu2);
- BigInteger k2 = e2.calculateAgreement(pu1);
-
- if (!k1.equals(k2))
- {
- fail("basic " + size + " bit 2-way test failed");
- }
- }
-
- private void checkKeySize(
- int privateValueSize,
- DHPrivateKeyParameters priv)
- {
- if (privateValueSize != 0)
- {
- if (priv.getX().bitLength() != privateValueSize)
- {
- fail("limited key check failed for key size " + privateValueSize);
- }
- }
- }
-
- private void testGPWithRandom(
- DHKeyPairGenerator kpGen)
- {
- //
- // generate first pair
- //
- AsymmetricCipherKeyPair pair = kpGen.generateKeyPair();
-
- DHPublicKeyParameters pu1 = (DHPublicKeyParameters)pair.getPublic();
- DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.getPrivate();
- //
- // generate second pair
- //
- pair = kpGen.generateKeyPair();
-
- DHPublicKeyParameters pu2 = (DHPublicKeyParameters)pair.getPublic();
- DHPrivateKeyParameters pv2 = (DHPrivateKeyParameters)pair.getPrivate();
-
- //
- // two way
- //
- DHAgreement e1 = new DHAgreement();
- DHAgreement e2 = new DHAgreement();
-
- e1.init(new ParametersWithRandom(pv1, new SecureRandom()));
- e2.init(new ParametersWithRandom(pv2, new SecureRandom()));
-
- BigInteger m1 = e1.calculateMessage();
- BigInteger m2 = e2.calculateMessage();
-
- BigInteger k1 = e1.calculateAgreement(pu2, m2);
- BigInteger k2 = e2.calculateAgreement(pu1, m1);
-
- if (!k1.equals(k2))
- {
- fail("basic with random 2-way test failed");
- }
- }
-
- private void testSimpleWithRandom(
- DHBasicKeyPairGenerator kpGen)
- {
- //
- // generate first pair
- //
- AsymmetricCipherKeyPair pair = kpGen.generateKeyPair();
-
- DHPublicKeyParameters pu1 = (DHPublicKeyParameters)pair.getPublic();
- DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.getPrivate();
- //
- // generate second pair
- //
- pair = kpGen.generateKeyPair();
-
- DHPublicKeyParameters pu2 = (DHPublicKeyParameters)pair.getPublic();
- DHPrivateKeyParameters pv2 = (DHPrivateKeyParameters)pair.getPrivate();
-
- //
- // two way
- //
- DHBasicAgreement e1 = new DHBasicAgreement();
- DHBasicAgreement e2 = new DHBasicAgreement();
-
- e1.init(new ParametersWithRandom(pv1, new SecureRandom()));
- e2.init(new ParametersWithRandom(pv2, new SecureRandom()));
-
- BigInteger k1 = e1.calculateAgreement(pu2);
- BigInteger k2 = e2.calculateAgreement(pu1);
-
- if (!k1.equals(k2))
- {
- fail("basic with random 2-way test failed");
- }
- }
-
- private DHBasicKeyPairGenerator getDHBasicKeyPairGenerator(
- BigInteger g,
- BigInteger p,
- int privateValueSize)
- {
- DHParameters dhParams = new DHParameters(p, g, null, privateValueSize);
- DHKeyGenerationParameters params = new DHKeyGenerationParameters(new SecureRandom(), dhParams);
- DHBasicKeyPairGenerator kpGen = new DHBasicKeyPairGenerator();
-
- kpGen.init(params);
-
- return kpGen;
- }
-
- private DHKeyPairGenerator getDHKeyPairGenerator(
- BigInteger g,
- BigInteger p)
- {
- DHParameters dhParams = new DHParameters(p, g);
- DHKeyGenerationParameters params = new DHKeyGenerationParameters(new SecureRandom(), dhParams);
- DHKeyPairGenerator kpGen = new DHKeyPairGenerator();
-
- kpGen.init(params);
-
- return kpGen;
- }
-
- /**
- * this test is can take quiet a while
- */
- private void testGeneration(
- int size)
- {
- DHParametersGenerator pGen = new DHParametersGenerator();
-
- pGen.init(size, 10, new SecureRandom());
-
- DHParameters dhParams = pGen.generateParameters();
-
- if (dhParams.getL() != 0)
- {
- fail("DHParametersGenerator failed to set J to 0 in generated DHParameters");
- }
-
- DHKeyGenerationParameters params = new DHKeyGenerationParameters(new SecureRandom(), dhParams);
-
- DHBasicKeyPairGenerator kpGen = new DHBasicKeyPairGenerator();
-
- kpGen.init(params);
-
- //
- // generate first pair
- //
- AsymmetricCipherKeyPair pair = kpGen.generateKeyPair();
-
- DHPublicKeyParameters pu1 = (DHPublicKeyParameters)pair.getPublic();
- DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.getPrivate();
-
- //
- // generate second pair
- //
- params = new DHKeyGenerationParameters(new SecureRandom(), pu1.getParameters());
-
- kpGen.init(params);
-
- pair = kpGen.generateKeyPair();
-
- DHPublicKeyParameters pu2 = (DHPublicKeyParameters)pair.getPublic();
- DHPrivateKeyParameters pv2 = (DHPrivateKeyParameters)pair.getPrivate();
-
- //
- // two way
- //
- DHBasicAgreement e1 = new DHBasicAgreement();
- DHBasicAgreement e2 = new DHBasicAgreement();
-
- e1.init(new ParametersWithRandom(pv1, new SecureRandom()));
- e2.init(new ParametersWithRandom(pv2, new SecureRandom()));
-
- BigInteger k1 = e1.calculateAgreement(pu2);
- BigInteger k2 = e2.calculateAgreement(pu1);
-
- if (!k1.equals(k2))
- {
- fail("basic with " + size + " bit 2-way test failed");
- }
- }
- private void testBounds()
- {
- BigInteger p1 = new BigInteger("00C8028E9151C6B51BCDB35C1F6B2527986A72D8546AE7A4BF41DC4289FF9837EE01592D36C324A0F066149B8B940C86C87D194206A39038AE3396F8E12435BB74449B70222D117B8A2BB77CB0D67A5D664DDE7B75E0FEC13CE0CAF258DAF3ADA0773F6FF0F2051D1859929AAA53B07809E496B582A89C3D7DA8B6E38305626621", 16);
- BigInteger g1 = new BigInteger("1F869713181464577FE4026B47102FA0D7675503A4FCDA810881FAEC3524E6DBAEA9B96561EF7F8BEA76466DF11C2F3EB1A90CC5851735BF860606481257EECE6418C0204E61004E85D7131CE54BCBC7AD67E53C79DCB715E7C8D083DCD85D728283EC8F96839B4C9FA7C0727C472BEB94E4613CAFA8D580119C0AF4BF8AF252", 16);
- int l1 = 1023;
-
- BigInteger p2 = new BigInteger("00B333C98720220CC3946F494E25231B3E19F9AD5F6B19F4E7ABF80D8826C491C3224D4F7415A14A7C11D1BE584405FED12C3554F103E56A72D986CA5E325BB9DE07AC37D1EAE5E5AC724D32EF638F0E4462D4C1FC7A45B9FD3A5DF5EC36A1FA4DAA3FBB66AA42B1B71DF416AB547E987513426C7BB8634F5F4D37705514FDC1E1", 16);
- BigInteger g2 = new BigInteger("2592F5A99FE46313650CCE66C94C15DBED9F4A45BD05C329986CF5D3E12139F0405A47C6385FEA27BFFEDC4CBABC5BB151F3BEE7CC3D51567F1E2B12A975AA9F48A70BDAAE7F5B87E70ADCF902490A3CBEFEDA41EBA8E12E02B56120B5FDEFBED07F5EAD3AE020DF3C8233216F8F0D35E13A7AE4DA5CBCC0D91EADBF20C281C6", 16);
- int l2 = 1024;
-
- DHKeyGenerationParameters params1 = new DHKeyGenerationParameters(new SecureRandom(), new DHParameters(p1, g1, null, l1));
- DHKeyGenerationParameters params2 = new DHKeyGenerationParameters(new SecureRandom(), new DHParameters(p2, g2, null, l2));
-
- DHBasicKeyPairGenerator kpGen = new DHBasicKeyPairGenerator();
-
- kpGen.init(params1);
- kpGen.init(params2);
- }
-
- public void performTest()
- {
- testDHBasic(512, 0, g512, p512);
- testDHBasic(768, 0, g768, p768);
- testDHBasic(1024, 0, g1024, p1024);
-
- testDHBasic(512, 64, g512, p512);
- testDHBasic(768, 128, g768, p768);
- testDHBasic(1024, 256, g1024, p1024);
-
- testDH(512, g512, p512);
- testDH(768, g768, p768);
- testDH(1024, g1024, p1024);
-
- testBounds();
-
- //
- // generation test.
- //
- testGeneration(256);
-
- //
- // with random test
- //
- DHBasicKeyPairGenerator kpBasicGen = getDHBasicKeyPairGenerator(g512, p512, 0);
-
- testSimpleWithRandom(kpBasicGen);
-
- DHKeyPairGenerator kpGen = getDHKeyPairGenerator(g512, p512);
-
- testGPWithRandom(kpGen);
-
- //
- // parameter tests
- //
- DHAgreement dh = new DHAgreement();
- AsymmetricCipherKeyPair dhPair = kpGen.generateKeyPair();
-
- try
- {
- dh.init(dhPair.getPublic());
- fail("DHAgreement key check failed");
- }
- catch (IllegalArgumentException e)
- {
- // ignore
- }
-
- DHKeyPairGenerator kpGen768 = getDHKeyPairGenerator(g768, p768);
-
- try
- {
- dh.init(dhPair.getPrivate());
-
- dh.calculateAgreement((DHPublicKeyParameters)kpGen768.generateKeyPair().getPublic(), BigInteger.valueOf(100));
-
- fail("DHAgreement agreement check failed");
- }
- catch (IllegalArgumentException e)
- {
- // ignore
- }
-
- DHBasicAgreement dhBasic = new DHBasicAgreement();
- AsymmetricCipherKeyPair dhBasicPair = kpBasicGen.generateKeyPair();
-
- try
- {
- dhBasic.init(dhBasicPair.getPublic());
- fail("DHBasicAgreement key check failed");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- DHBasicKeyPairGenerator kpBasicGen768 = getDHBasicKeyPairGenerator(g768, p768, 0);
-
- try
- {
- dhBasic.init(dhPair.getPrivate());
-
- dhBasic.calculateAgreement((DHPublicKeyParameters)kpBasicGen768.generateKeyPair().getPublic());
-
- fail("DHBasicAgreement agreement check failed");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new DHTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/DSATest.java b/core/src/test/java/org/bouncycastle/crypto/test/DSATest.java
deleted file mode 100644
index 02c748fa..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/DSATest.java
+++ /dev/null
@@ -1,602 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.digests.SHA224Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.generators.DSAKeyPairGenerator;
-import org.bouncycastle.crypto.generators.DSAParametersGenerator;
-import org.bouncycastle.crypto.params.DSAKeyGenerationParameters;
-import org.bouncycastle.crypto.params.DSAParameterGenerationParameters;
-import org.bouncycastle.crypto.params.DSAParameters;
-import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
-import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
-import org.bouncycastle.crypto.params.DSAValidationParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.signers.DSASigner;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.BigIntegers;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.FixedSecureRandom;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * Test based on FIPS 186-2, Appendix 5, an example of DSA, and FIPS 168-3 test vectors.
- */
-public class DSATest
- extends SimpleTest
-{
- byte[] k1 = Hex.decode("d5014e4b60ef2ba8b6211b4062ba3224e0427dd3");
- byte[] k2 = Hex.decode("345e8d05c075c3a508df729a1685690e68fcfb8c8117847e89063bca1f85d968fd281540b6e13bd1af989a1fbf17e06462bf511f9d0b140fb48ac1b1baa5bded");
-
- SecureRandom random = new FixedSecureRandom(new byte[][] { k1, k2});
-
- byte[] keyData = Hex.decode("b5014e4b60ef2ba8b6211b4062ba3224e0427dd3");
-
- SecureRandom keyRandom = new FixedSecureRandom(new byte[][] { keyData, keyData });
-
- BigInteger pValue = new BigInteger("8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291", 16);
- BigInteger qValue = new BigInteger("c773218c737ec8ee993b4f2ded30f48edace915f", 16);
-
- public String getName()
- {
- return "DSA";
- }
-
- public void performTest()
- {
- BigInteger r = new BigInteger("68076202252361894315274692543577577550894681403");
- BigInteger s = new BigInteger("1089214853334067536215539335472893651470583479365");
- DSAParametersGenerator pGen = new DSAParametersGenerator();
-
- pGen.init(512, 80, random);
-
- DSAParameters params = pGen.generateParameters();
- DSAValidationParameters pValid = params.getValidationParameters();
-
- if (pValid.getCounter() != 105)
- {
- fail("Counter wrong");
- }
-
- if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
- {
- fail("p or q wrong");
- }
-
- DSAKeyPairGenerator dsaKeyGen = new DSAKeyPairGenerator();
- DSAKeyGenerationParameters genParam = new DSAKeyGenerationParameters(keyRandom, params);
-
- dsaKeyGen.init(genParam);
-
- AsymmetricCipherKeyPair pair = dsaKeyGen.generateKeyPair();
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), keyRandom);
-
- DSASigner dsa = new DSASigner();
-
- dsa.init(true, param);
-
- byte[] message = BigIntegers.asUnsignedByteArray(new BigInteger("968236873715988614170569073515315707566766479517"));
- BigInteger[] sig = dsa.generateSignature(message);
-
- if (!r.equals(sig[0]))
- {
- fail("r component wrong.", r, sig[0]);
- }
-
- if (!s.equals(sig[1]))
- {
- fail("s component wrong.", s, sig[1]);
- }
-
- dsa.init(false, pair.getPublic());
-
- if (!dsa.verifySignature(message, sig[0], sig[1]))
- {
- fail("verification fails");
- }
-
- dsa2Test1();
- dsa2Test2();
- dsa2Test3();
- dsa2Test4();
- }
-
- private void dsa2Test1()
- {
- byte[] seed = Hex.decode("ED8BEE8D1CB89229D2903CBF0E51EE7377F48698");
-
- DSAParametersGenerator pGen = new DSAParametersGenerator();
-
- pGen.init(new DSAParameterGenerationParameters(1024, 160, 80, new DSATestSecureRandom(seed)));
-
- DSAParameters params = pGen.generateParameters();
-
- DSAValidationParameters pv = params.getValidationParameters();
-
- if (pv.getCounter() != 5)
- {
- fail("counter incorrect");
- }
-
- if (!Arrays.areEqual(seed, pv.getSeed()))
- {
- fail("seed incorrect");
- }
-
- if (!params.getQ().equals(new BigInteger("E950511EAB424B9A19A2AEB4E159B7844C589C4F", 16)))
- {
- fail("Q incorrect");
- }
-
- if (!params.getP().equals(new BigInteger(
- "E0A67598CD1B763B" +
- "C98C8ABB333E5DDA0CD3AA0E5E1FB5BA8A7B4EABC10BA338" +
- "FAE06DD4B90FDA70D7CF0CB0C638BE3341BEC0AF8A7330A3" +
- "307DED2299A0EE606DF035177A239C34A912C202AA5F83B9" +
- "C4A7CF0235B5316BFC6EFB9A248411258B30B839AF172440" +
- "F32563056CB67A861158DDD90E6A894C72A5BBEF9E286C6B", 16)))
- {
- fail("P incorrect");
- }
-
- if (!params.getG().equals(new BigInteger(
- "D29D5121B0423C27" +
- "69AB21843E5A3240FF19CACC792264E3BB6BE4F78EDD1B15" +
- "C4DFF7F1D905431F0AB16790E1F773B5CE01C804E509066A" +
- "9919F5195F4ABC58189FD9FF987389CB5BEDF21B4DAB4F8B" +
- "76A055FFE2770988FE2EC2DE11AD92219F0B351869AC24DA" +
- "3D7BA87011A701CE8EE7BFE49486ED4527B7186CA4610A75", 16)))
- {
- fail("G incorrect");
- }
-
- DSAKeyPairGenerator kpGen = new DSAKeyPairGenerator();
-
- kpGen.init(new DSAKeyGenerationParameters(new FixedSecureRandom(Hex.decode("D0EC4E50BB290A42E9E355C73D8809345DE2E139")), params));
-
- AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();
-
- DSAPublicKeyParameters pub = (DSAPublicKeyParameters)kp.getPublic();
- DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)kp.getPrivate();
-
- if (!pub.getY().equals(new BigInteger(
- "25282217F5730501" +
- "DD8DBA3EDFCF349AAFFEC20921128D70FAC44110332201BB" +
- "A3F10986140CBB97C726938060473C8EC97B4731DB004293" +
- "B5E730363609DF9780F8D883D8C4D41DED6A2F1E1BBBDC97" +
- "9E1B9D6D3C940301F4E978D65B19041FCF1E8B518F5C0576" +
- "C770FE5A7A485D8329EE2914A2DE1B5DA4A6128CEAB70F79", 16)))
- {
- fail("Y value incorrect");
- }
-
- if (!priv.getX().equals(
- new BigInteger("D0EC4E50BB290A42E9E355C73D8809345DE2E139", 16)))
- {
- fail("X value incorrect");
- }
-
- DSASigner signer = new DSASigner();
-
- signer.init(true, new ParametersWithRandom(kp.getPrivate(), new FixedSecureRandom(Hex.decode("349C55648DCF992F3F33E8026CFAC87C1D2BA075"))));
-
- byte[] msg = Hex.decode("A9993E364706816ABA3E25717850C26C9CD0D89D");
-
- BigInteger[] sig = signer.generateSignature(msg);
-
- if (!sig[0].equals(new BigInteger("636155AC9A4633B4665D179F9E4117DF68601F34", 16)))
- {
- fail("R value incorrect");
- }
-
- if (!sig[1].equals(new BigInteger("6C540B02D9D4852F89DF8CFC99963204F4347704", 16)))
- {
- fail("S value incorrect");
- }
-
- signer.init(false, kp.getPublic());
-
- if (!signer.verifySignature(msg, sig[0], sig[1]))
- {
- fail("signature not verified");
- }
-
- }
-
- private void dsa2Test2()
- {
- byte[] seed = Hex.decode("5AFCC1EFFC079A9CCA6ECA86D6E3CC3B18642D9BE1CC6207C84002A9");
-
- DSAParametersGenerator pGen = new DSAParametersGenerator(new SHA224Digest());
-
- pGen.init(new DSAParameterGenerationParameters(2048, 224, 80, new DSATestSecureRandom(seed)));
-
- DSAParameters params = pGen.generateParameters();
-
- DSAValidationParameters pv = params.getValidationParameters();
-
- if (pv.getCounter() != 21)
- {
- fail("counter incorrect");
- }
-
- if (!Arrays.areEqual(seed, pv.getSeed()))
- {
- fail("seed incorrect");
- }
-
- if (!params.getQ().equals(new BigInteger("90EAF4D1AF0708B1B612FF35E0A2997EB9E9D263C9CE659528945C0D", 16)))
- {
- fail("Q incorrect");
- }
-
- if (!params.getP().equals(new BigInteger(
- "C196BA05AC29E1F9C3C72D56DFFC6154" +
- "A033F1477AC88EC37F09BE6C5BB95F51C296DD20D1A28A06" +
- "7CCC4D4316A4BD1DCA55ED1066D438C35AEBAABF57E7DAE4" +
- "28782A95ECA1C143DB701FD48533A3C18F0FE23557EA7AE6" +
- "19ECACC7E0B51652A8776D02A425567DED36EABD90CA33A1" +
- "E8D988F0BBB92D02D1D20290113BB562CE1FC856EEB7CDD9" +
- "2D33EEA6F410859B179E7E789A8F75F645FAE2E136D252BF" +
- "FAFF89528945C1ABE705A38DBC2D364AADE99BE0D0AAD82E" +
- "5320121496DC65B3930E38047294FF877831A16D5228418D" +
- "E8AB275D7D75651CEFED65F78AFC3EA7FE4D79B35F62A040" +
- "2A1117599ADAC7B269A59F353CF450E6982D3B1702D9CA83", 16)))
- {
- fail("P incorrect");
- }
-
- if (!params.getG().equals(new BigInteger(
- "A59A749A11242C58C894E9E5A91804E8"+
- "FA0AC64B56288F8D47D51B1EDC4D65444FECA0111D78F35F"+
- "C9FDD4CB1F1B79A3BA9CBEE83A3F811012503C8117F98E50"+
- "48B089E387AF6949BF8784EBD9EF45876F2E6A5A495BE64B"+
- "6E770409494B7FEE1DBB1E4B2BC2A53D4F893D418B715959"+
- "2E4FFFDF6969E91D770DAEBD0B5CB14C00AD68EC7DC1E574"+
- "5EA55C706C4A1C5C88964E34D09DEB753AD418C1AD0F4FDF"+
- "D049A955E5D78491C0B7A2F1575A008CCD727AB376DB6E69"+
- "5515B05BD412F5B8C2F4C77EE10DA48ABD53F5DD498927EE"+
- "7B692BBBCDA2FB23A516C5B4533D73980B2A3B60E384ED20"+
- "0AE21B40D273651AD6060C13D97FD69AA13C5611A51B9085", 16)))
- {
- fail("G incorrect");
- }
-
- DSAKeyPairGenerator kpGen = new DSAKeyPairGenerator();
-
- kpGen.init(new DSAKeyGenerationParameters(new FixedSecureRandom(Hex.decode("00D0F09ED3E2568F6CADF9224117DA2AEC5A4300E009DE1366023E17")), params));
-
- AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();
-
- DSAPublicKeyParameters pub = (DSAPublicKeyParameters)kp.getPublic();
- DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)kp.getPrivate();
-
- if (!pub.getY().equals(new BigInteger(
- "70035C9A3B225B258F16741F3941FBF0" +
- "6F3D056CD7BD864604CBB5EE9DD85304EE8E8E4ABD5E9032" +
- "11DDF25CE149075510ACE166970AFDC7DF552B7244F342FA" +
- "02F7A621405B754909D757F97290E1FE5036E904CF593446" +
- "0C046D95659821E1597ED9F2B1F0E20863A6BBD0CE74DACB" +
- "A5D8C68A90B29C2157CDEDB82EC12B81EE3068F9BF5F7F34" +
- "6ECA41ED174CCCD7D154FA4F42F80FFE1BF46AE9D8125DEB" +
- "5B4BA08A72BDD86596DBEDDC9550FDD650C58F5AE5133509" +
- "A702F79A31ECB490F7A3C5581631F7C5BE4FF7F9E9F27FA3" +
- "90E47347AD1183509FED6FCF198BA9A71AB3335B4F38BE8D" +
- "15496A00B6DC2263E20A5F6B662320A3A1EC033AA61E3B68", 16)))
- {
- fail("Y value incorrect");
- }
-
- if (!priv.getX().equals(
- new BigInteger("00D0F09ED3E2568F6CADF9224117DA2AEC5A4300E009DE1366023E17", 16)))
- {
- fail("X value incorrect");
- }
-
- DSASigner signer = new DSASigner();
-
- signer.init(true, new ParametersWithRandom(kp.getPrivate(), new FixedSecureRandom(Hex.decode("735959CC4463B8B440E407EECA8A473BF6A6D1FE657546F67D401F05"))));
-
- byte[] msg = Hex.decode("23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7");
-
- BigInteger[] sig = signer.generateSignature(msg);
-
- if (!sig[0].equals(new BigInteger("4400138D05F9639CAF54A583CAAF25D2B76D0C3EAD752CE17DBC85FE", 16)))
- {
- fail("R value incorrect");
- }
-
- if (!sig[1].equals(new BigInteger("874D4F12CB13B61732D398445698CFA9D92381D938AA57EE2C9327B3", 16)))
- {
- fail("S value incorrect");
- }
-
- signer.init(false, kp.getPublic());
-
- if (!signer.verifySignature(msg, sig[0], sig[1]))
- {
- fail("signature not verified");
- }
- }
-
- private void dsa2Test3()
- {
- byte[] seed = Hex.decode("4783081972865EA95D43318AB2EAF9C61A2FC7BBF1B772A09017BDF5A58F4FF0");
-
- DSAParametersGenerator pGen = new DSAParametersGenerator(new SHA256Digest());
-
- pGen.init(new DSAParameterGenerationParameters(2048, 256, 80, new DSATestSecureRandom(seed)));
-
- DSAParameters params = pGen.generateParameters();
-
- DSAValidationParameters pv = params.getValidationParameters();
-
- if (pv.getCounter() != 12)
- {
- fail("counter incorrect");
- }
-
- if (!Arrays.areEqual(seed, pv.getSeed()))
- {
- fail("seed incorrect");
- }
-
- if (!params.getQ().equals(new BigInteger("C24ED361870B61E0D367F008F99F8A1F75525889C89DB1B673C45AF5867CB467", 16)))
- {
- fail("Q incorrect");
- }
-
- if (!params.getP().equals(new BigInteger(
- "F56C2A7D366E3EBDEAA1891FD2A0D099" +
- "436438A673FED4D75F594959CFFEBCA7BE0FC72E4FE67D91" +
- "D801CBA0693AC4ED9E411B41D19E2FD1699C4390AD27D94C" +
- "69C0B143F1DC88932CFE2310C886412047BD9B1C7A67F8A2" +
- "5909132627F51A0C866877E672E555342BDF9355347DBD43" +
- "B47156B2C20BAD9D2B071BC2FDCF9757F75C168C5D9FC431" +
- "31BE162A0756D1BDEC2CA0EB0E3B018A8B38D3EF2487782A" +
- "EB9FBF99D8B30499C55E4F61E5C7DCEE2A2BB55BD7F75FCD" +
- "F00E48F2E8356BDB59D86114028F67B8E07B127744778AFF" +
- "1CF1399A4D679D92FDE7D941C5C85C5D7BFF91BA69F9489D" +
- "531D1EBFA727CFDA651390F8021719FA9F7216CEB177BD75", 16)))
- {
- fail("P incorrect");
- }
-
- if (!params.getG().equals(new BigInteger(
- "8DC6CC814CAE4A1C05A3E186A6FE27EA" +
- "BA8CDB133FDCE14A963A92E809790CBA096EAA26140550C1" +
- "29FA2B98C16E84236AA33BF919CD6F587E048C52666576DB" +
- "6E925C6CBE9B9EC5C16020F9A44C9F1C8F7A8E611C1F6EC2" +
- "513EA6AA0B8D0F72FED73CA37DF240DB57BBB27431D61869" +
- "7B9E771B0B301D5DF05955425061A30DC6D33BB6D2A32BD0" +
- "A75A0A71D2184F506372ABF84A56AEEEA8EB693BF29A6403" +
- "45FA1298A16E85421B2208D00068A5A42915F82CF0B858C8" +
- "FA39D43D704B6927E0B2F916304E86FB6A1B487F07D8139E" +
- "428BB096C6D67A76EC0B8D4EF274B8A2CF556D279AD267CC" +
- "EF5AF477AFED029F485B5597739F5D0240F67C2D948A6279", 16)))
- {
- fail("G incorrect");
- }
-
- DSAKeyPairGenerator kpGen = new DSAKeyPairGenerator();
-
- kpGen.init(new DSAKeyGenerationParameters(new FixedSecureRandom(Hex.decode("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C")), params));
-
- AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();
-
- DSAPublicKeyParameters pub = (DSAPublicKeyParameters)kp.getPublic();
- DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)kp.getPrivate();
-
- if (!pub.getY().equals(new BigInteger(
- "2828003D7C747199143C370FDD07A286" +
- "1524514ACC57F63F80C38C2087C6B795B62DE1C224BF8D1D" +
- "1424E60CE3F5AE3F76C754A2464AF292286D873A7A30B7EA" +
- "CBBC75AAFDE7191D9157598CDB0B60E0C5AA3F6EBE425500" +
- "C611957DBF5ED35490714A42811FDCDEB19AF2AB30BEADFF" +
- "2907931CEE7F3B55532CFFAEB371F84F01347630EB227A41" +
- "9B1F3F558BC8A509D64A765D8987D493B007C4412C297CAF" +
- "41566E26FAEE475137EC781A0DC088A26C8804A98C23140E" +
- "7C936281864B99571EE95C416AA38CEEBB41FDBFF1EB1D1D" +
- "C97B63CE1355257627C8B0FD840DDB20ED35BE92F08C49AE" +
- "A5613957D7E5C7A6D5A5834B4CB069E0831753ECF65BA02B", 16)))
- {
- fail("Y value incorrect");
- }
-
- if (!priv.getX().equals(
- new BigInteger("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C", 16)))
- {
- fail("X value incorrect");
- }
-
- DSASigner signer = new DSASigner();
-
- signer.init(true, new ParametersWithRandom(kp.getPrivate(), new FixedSecureRandom(Hex.decode("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C"))));
-
- byte[] msg = Hex.decode("BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD");
-
- BigInteger[] sig = signer.generateSignature(msg);
-
- if (!sig[0].equals(new BigInteger("315C875DCD4850E948B8AC42824E9483A32D5BA5ABE0681B9B9448D444F2BE3C", 16)))
- {
- fail("R value incorrect");
- }
-
- if (!sig[1].equals(new BigInteger("89718D12E54A8D9ED066E4A55F7ED5A2229CD23B9A3CEE78F83ED6AA61F6BCB9", 16)))
- {
- fail("S value incorrect");
- }
-
- signer.init(false, kp.getPublic());
-
- if (!signer.verifySignature(msg, sig[0], sig[1]))
- {
- fail("signature not verified");
- }
- }
-
- private void dsa2Test4()
- {
- byte[] seed = Hex.decode("193AFCA7C1E77B3C1ECC618C81322E47B8B8B997C9C83515C59CC446C2D9BD47");
-
- DSAParametersGenerator pGen = new DSAParametersGenerator(new SHA256Digest());
-
- pGen.init(new DSAParameterGenerationParameters(3072, 256, 80, new DSATestSecureRandom(seed)));
-
- DSAParameters params = pGen.generateParameters();
-
- DSAValidationParameters pv = params.getValidationParameters();
-
- if (pv.getCounter() != 20)
- {
- fail("counter incorrect");
- }
-
- if (!Arrays.areEqual(seed, pv.getSeed()))
- {
- fail("seed incorrect");
- }
-
- if (!params.getQ().equals(new BigInteger("CFA0478A54717B08CE64805B76E5B14249A77A4838469DF7F7DC987EFCCFB11D", 16)))
- {
- fail("Q incorrect");
- }
-
- if (!params.getP().equals(new BigInteger(
- "90066455B5CFC38F9CAA4A48B4281F292C260FEEF01FD610" +
- "37E56258A7795A1C7AD46076982CE6BB956936C6AB4DCFE0" +
- "5E6784586940CA544B9B2140E1EB523F009D20A7E7880E4E" +
- "5BFA690F1B9004A27811CD9904AF70420EEFD6EA11EF7DA1" +
- "29F58835FF56B89FAA637BC9AC2EFAAB903402229F491D8D" +
- "3485261CD068699B6BA58A1DDBBEF6DB51E8FE34E8A78E54" +
- "2D7BA351C21EA8D8F1D29F5D5D15939487E27F4416B0CA63" +
- "2C59EFD1B1EB66511A5A0FBF615B766C5862D0BD8A3FE7A0" +
- "E0DA0FB2FE1FCB19E8F9996A8EA0FCCDE538175238FC8B0E" +
- "E6F29AF7F642773EBE8CD5402415A01451A840476B2FCEB0" +
- "E388D30D4B376C37FE401C2A2C2F941DAD179C540C1C8CE0" +
- "30D460C4D983BE9AB0B20F69144C1AE13F9383EA1C08504F" +
- "B0BF321503EFE43488310DD8DC77EC5B8349B8BFE97C2C56" +
- "0EA878DE87C11E3D597F1FEA742D73EEC7F37BE43949EF1A" +
- "0D15C3F3E3FC0A8335617055AC91328EC22B50FC15B941D3" +
- "D1624CD88BC25F3E941FDDC6200689581BFEC416B4B2CB73", 16)))
- {
- fail("P incorrect");
- }
-
- if (!params.getG().equals(new BigInteger(
- "5E5CBA992E0A680D885EB903AEA78E4A45A469103D448EDE" +
- "3B7ACCC54D521E37F84A4BDD5B06B0970CC2D2BBB715F7B8" +
- "2846F9A0C393914C792E6A923E2117AB805276A975AADB52" +
- "61D91673EA9AAFFEECBFA6183DFCB5D3B7332AA19275AFA1" +
- "F8EC0B60FB6F66CC23AE4870791D5982AAD1AA9485FD8F4A" +
- "60126FEB2CF05DB8A7F0F09B3397F3937F2E90B9E5B9C9B6" +
- "EFEF642BC48351C46FB171B9BFA9EF17A961CE96C7E7A7CC" +
- "3D3D03DFAD1078BA21DA425198F07D2481622BCE45969D9C" +
- "4D6063D72AB7A0F08B2F49A7CC6AF335E08C4720E31476B6" +
- "7299E231F8BD90B39AC3AE3BE0C6B6CACEF8289A2E2873D5" +
- "8E51E029CAFBD55E6841489AB66B5B4B9BA6E2F784660896" +
- "AFF387D92844CCB8B69475496DE19DA2E58259B090489AC8" +
- "E62363CDF82CFD8EF2A427ABCD65750B506F56DDE3B98856" +
- "7A88126B914D7828E2B63A6D7ED0747EC59E0E0A23CE7D8A" +
- "74C1D2C2A7AFB6A29799620F00E11C33787F7DED3B30E1A2" +
- "2D09F1FBDA1ABBBFBF25CAE05A13F812E34563F99410E73B", 16)))
- {
- fail("G incorrect");
- }
-
- DSAKeyPairGenerator kpGen = new DSAKeyPairGenerator();
-
- kpGen.init(new DSAKeyGenerationParameters(new FixedSecureRandom(Hex.decode("3ABC1587297CE7B9EA1AD6651CF2BC4D7F92ED25CABC8553F567D1B40EBB8764")), params));
-
- AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();
-
- DSAPublicKeyParameters pub = (DSAPublicKeyParameters)kp.getPublic();
- DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)kp.getPrivate();
-
- if (!pub.getY().equals(new BigInteger(
- "8B891C8692D3DE875879390F2698B26FBECCA6B075535DCE" +
- "6B0C862577F9FA0DEF6074E7A7624121224A595896ABD4CD" +
- "A56B2CEFB942E025D2A4282FFAA98A48CDB47E1A6FCB5CFB" +
- "393EF35AF9DF913102BB303C2B5C36C3F8FC04ED7B8B69FE" +
- "FE0CF3E1FC05CFA713B3435B2656E913BA8874AEA9F93600" +
- "6AEB448BCD005D18EC3562A33D04CF25C8D3D69844343442" +
- "FA3DB7DE618C5E2DA064573E61E6D5581BFB694A23AC87FD" +
- "5B52D62E954E1376DB8DDB524FFC0D469DF978792EE44173" +
- "8E5DB05A7DC43E94C11A2E7A4FBE383071FA36D2A7EC8A93" +
- "88FE1C4F79888A99D3B6105697C2556B79BB4D7E781CEBB3" +
- "D4866AD825A5E830846072289FDBC941FA679CA82F5F78B7" +
- "461B2404DB883D215F4E0676CF5493950AC5591697BFEA8D" +
- "1EE6EC016B89BA51CAFB5F9C84C989FA117375E94578F28B" +
- "E0B34CE0545DA46266FD77F62D8F2CEE92AB77012AFEBC11" +
- "008985A821CD2D978C7E6FE7499D1AAF8DE632C21BB48CA5" +
- "CBF9F31098FD3FD3854C49A65D9201744AACE540354974F9", 16)))
- {
- fail("Y value incorrect");
- }
-
- if (!priv.getX().equals(
- new BigInteger("3ABC1587297CE7B9EA1AD6651CF2BC4D7F92ED25CABC8553F567D1B40EBB8764", 16)))
- {
- fail("X value incorrect");
- }
-
- DSASigner signer = new DSASigner();
-
- signer.init(true, new ParametersWithRandom(kp.getPrivate(), new FixedSecureRandom(Hex.decode("A6902C1E6E3943C5628061588A8B007BCCEA91DBF12915483F04B24AB0678BEE"))));
-
- byte[] msg = Hex.decode("BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD");
-
- BigInteger[] sig = signer.generateSignature(msg);
-
- if (!sig[0].equals(new BigInteger("5F184E645A38BE8FB4A6871B6503A9D12924C7ABE04B71410066C2ECA6E3BE3E", 16)))
- {
- fail("R value incorrect");
- }
-
- if (!sig[1].equals(new BigInteger("91EB0C7BA3D4B9B60B825C3D9F2CADA8A2C9D7723267B033CBCDCF8803DB9C18", 16)))
- {
- fail("S value incorrect");
- }
-
- signer.init(false, kp.getPublic());
-
- if (!signer.verifySignature(msg, sig[0], sig[1]))
- {
- fail("signature not verified");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new DSATest());
- }
-
- private class DSATestSecureRandom
- extends FixedSecureRandom
- {
- private boolean first = true;
-
- public DSATestSecureRandom(byte[] value)
- {
- super(value);
- }
-
- public void nextBytes(byte[] bytes)
- {
- if (first)
- {
- super.nextBytes(bytes);
- first = false;
- }
- else
- {
- bytes[bytes.length - 1] = 2;
- }
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/DSTU4145Test.java b/core/src/test/java/org/bouncycastle/crypto/test/DSTU4145Test.java
deleted file mode 100644
index 2d3013d4..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/DSTU4145Test.java
+++ /dev/null
@@ -1,278 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.signers.DSTU4145Signer;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.FixedSecureRandom;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class DSTU4145Test
- extends SimpleTest
-{
- private static final BigInteger ZERO = BigInteger.valueOf(0);
- private static final BigInteger ONE = BigInteger.valueOf(1);
-
- public static void main(String[] args)
- {
- runTest(new DSTU4145Test());
- }
-
- public String getName()
- {
- return "DSTU4145";
- }
-
- private void test163()
- throws Exception
- {
- SecureRandom random = new FixedSecureRandom(Hex.decode("01025e40bd97db012b7a1d79de8e12932d247f61c6"));
-
- byte[] hash = Hex.decode("09c9c44277910c9aaee486883a2eb95b7180166ddf73532eeb76edaef52247ff");
- for (int i = 0; i < hash.length / 2; i++)
- {
- byte tmp = hash[i];
- hash[i] = hash[hash.length - 1 - i];
- hash[hash.length - 1 - i] = tmp;
- }
-
- BigInteger r = new BigInteger("274ea2c0caa014a0d80a424f59ade7a93068d08a7", 16);
- BigInteger s = new BigInteger("2100d86957331832b8e8c230f5bd6a332b3615aca", 16);
-
- ECCurve.F2m curve = new ECCurve.F2m(163, 3, 6, 7, ONE, new BigInteger("5FF6108462A2DC8210AB403925E638A19C1455D21", 16));
- ECPoint P = curve.createPoint(new BigInteger("72d867f93a93ac27df9ff01affe74885c8c540420", 16), new BigInteger("0224a9c3947852b97c5599d5f4ab81122adc3fd9b", 16));
- BigInteger n = new BigInteger("400000000000000000002BEC12BE2262D39BCF14D", 16);
-
- BigInteger d = new BigInteger("183f60fdf7951ff47d67193f8d073790c1c9b5a3e", 16);
- ECPoint Q = P.multiply(d).negate();
-
- ECDomainParameters domain = new ECDomainParameters(curve, P, n);
- CipherParameters privKey = new ParametersWithRandom(new ECPrivateKeyParameters(d, domain), random);
- ECPublicKeyParameters pubKey = new ECPublicKeyParameters(Q, domain);
-
- DSTU4145Signer dstuSigner = new DSTU4145Signer();
- dstuSigner.init(true, privKey);
- BigInteger[] rs = dstuSigner.generateSignature(hash);
-
- if (rs[0].compareTo(r) != 0)
- {
- fail("r component wrong");
- }
-
- if (rs[1].compareTo(s) != 0)
- {
- fail("s component wrong");
- }
-
- dstuSigner.init(false, pubKey);
- if (!dstuSigner.verifySignature(hash, r, s))
- {
- fail("verification fails");
- }
- }
-
- private void test173()
- throws Exception
- {
- SecureRandom random = new FixedSecureRandom(Hex.decode("0000137449348C1249971759D99C252FFE1E14D8B31F"));
-
- byte[] hash = Hex.decode("0137187EA862117EF1484289470ECAC802C5A651FDA8");
- for (int i = 0; i < hash.length / 2; i++)
- {
- byte tmp = hash[i];
- hash[i] = hash[hash.length - 1 - i];
- hash[hash.length - 1 - i] = tmp;
- }
-
- BigInteger r = new BigInteger("13ae89746386709cdbd237cc5ec20ca30004a82ead8", 16);
- BigInteger s = new BigInteger("3597912cdd093b3e711ccb74a79d3c4ab4c7cccdc60", 16);
-
- ECCurve.F2m curve = new ECCurve.F2m(173, 1, 2, 10, ZERO, new BigInteger("108576C80499DB2FC16EDDF6853BBB278F6B6FB437D9", 16));
- ECPoint P = curve.createPoint(new BigInteger("BE6628EC3E67A91A4E470894FBA72B52C515F8AEE9", 16), new BigInteger("D9DEEDF655CF5412313C11CA566CDC71F4DA57DB45C", 16));
- BigInteger n = new BigInteger("800000000000000000000189B4E67606E3825BB2831", 16);
-
- BigInteger d = new BigInteger("955CD7E344303D1034E66933DC21C8044D42ADB8", 16);
- ECPoint Q = P.multiply(d).negate();
-
- ECDomainParameters domain = new ECDomainParameters(curve, P, n);
- CipherParameters privKey = new ParametersWithRandom(new ECPrivateKeyParameters(d, domain), random);
- ECPublicKeyParameters pubKey = new ECPublicKeyParameters(Q, domain);
-
- DSTU4145Signer dstuSigner = new DSTU4145Signer();
- dstuSigner.init(true, privKey);
- BigInteger[] rs = dstuSigner.generateSignature(hash);
-
- if (rs[0].compareTo(r) != 0)
- {
- fail("r component wrong");
- }
-
- if (rs[1].compareTo(s) != 0)
- {
- fail("s component wrong");
- }
-
- dstuSigner.init(false, pubKey);
- if (!dstuSigner.verifySignature(hash, r, s))
- {
- fail("verification fails");
- }
- }
-
- private void test283()
- throws Exception
- {
- SecureRandom random = new FixedSecureRandom(Hex.decode("00000000245383CB3AD41BF30F5F7E8FBA858509B2D5558C92D539A6D994BFA98BC6940E"));
-
- byte[] hash = Hex.decode("0137187EA862117EF1484289470ECAC802C5A651FDA8");
- for (int i = 0; i < hash.length / 2; i++)
- {
- byte tmp = hash[i];
- hash[i] = hash[hash.length - 1 - i];
- hash[hash.length - 1 - i] = tmp;
- }
-
- BigInteger r = new BigInteger("12a5edcc38d92208ff23036d75b000c7e4bc0f9af2d40b35f15d6fd15e01234e67781a8", 16);
- BigInteger s = new BigInteger("2de0775577f75b643cf5afc80d4fe10b21100690f17e2cab7bdc9b50ec87c5727aeb515", 16);
-
- ECCurve.F2m curve = new ECCurve.F2m(283, 5, 7, 12, ONE, new BigInteger("27B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5", 16));
- ECPoint P = curve.createPoint(new BigInteger("4D95820ACE761110824CE425C8089129487389B7F0E0A9D043DDC0BB0A4CC9EB25", 16), new BigInteger("954C9C4029B2C62DE35C2B9C2A164984BF1101951E3A68ED03DF234DDE5BB2013152F2", 16));
- BigInteger n = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307", 16);
-
- BigInteger d = new BigInteger("B844EEAF15213E4BAD4FB84796D68F2448DB8EB7B4621EC0D51929874892C43E", 16);
- ECPoint Q = P.multiply(d).negate();
-
- ECDomainParameters domain = new ECDomainParameters(curve, P, n);
- CipherParameters privKey = new ParametersWithRandom(new ECPrivateKeyParameters(d, domain), random);
- ECPublicKeyParameters pubKey = new ECPublicKeyParameters(Q, domain);
-
- DSTU4145Signer dstuSigner = new DSTU4145Signer();
- dstuSigner.init(true, privKey);
- BigInteger[] rs = dstuSigner.generateSignature(hash);
-
- if (rs[0].compareTo(r) != 0)
- {
- fail("r component wrong");
- }
-
- if (rs[1].compareTo(s) != 0)
- {
- fail("s component wrong");
- }
-
- dstuSigner.init(false, pubKey);
- if (!dstuSigner.verifySignature(hash, r, s))
- {
- fail("verification fails");
- }
- }
-
- private void test431()
- throws Exception
- {
- SecureRandom random = new FixedSecureRandom(Hex.decode("0000C4224DBBD800988DBAA39DE838294C345CDA5F5929D1174AA8D9340A5E79D10ACADE6B53CF873E7301A3871C2073AD75AB530457"));
-
- byte[] hash = Hex.decode("0137187EA862117EF1484289470ECAC802C5A651FDA8");
- for (int i = 0; i < hash.length / 2; i++)
- {
- byte tmp = hash[i];
- hash[i] = hash[hash.length - 1 - i];
- hash[hash.length - 1 - i] = tmp;
- }
-
- BigInteger r = new BigInteger("1911fefb1f494bebcf8dffdf5276946ff9c9f662192ee18c718db47310a439c784fe07577b16e1edbe16179876e0792a634f1c9c3a2e", 16);
- BigInteger s = new BigInteger("3852170ee801c2083c52f1ea77b987a5432acecd9c654f064e87bf179e0a397151edbca430082e43bd38a67b55424b5bbc7f2713f620", 16);
-
- ECCurve.F2m curve = new ECCurve.F2m(431, 1, 3, 5, ONE, new BigInteger("3CE10490F6A708FC26DFE8C3D27C4F94E690134D5BFF988D8D28AAEAEDE975936C66BAC536B18AE2DC312CA493117DAA469C640CAF3", 16));
- ECPoint P = curve.createPoint(new BigInteger("9548BCDF314CEEEAF099C780FFEFBF93F9FE5B5F55547603C9C8FC1A2774170882B3BE35E892C6D4296B8DEA282EC30FB344272791", 16), new BigInteger("4C6CBD7C62A8EEEFDE17A8B5E196E49A22CE6DE128ABD9FBD81FA4411AD5A38E2A810BEDE09A7C6226BCDCB4A4A5DA37B4725E00AA74", 16));
- BigInteger n = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBA3175458009A8C0A724F02F81AA8A1FCBAF80D90C7A95110504CF", 16);
-
- BigInteger d = new BigInteger("D0F97354E314191FD773E2404F478C8AEE0FF5109F39E6F37D1FEEC8B2ED1691D84C9882CC729E716A71CC013F66CAC60E29E22C", 16);
- ECPoint Q = P.multiply(d).negate();
-
- ECDomainParameters domain = new ECDomainParameters(curve, P, n);
- CipherParameters privKey = new ParametersWithRandom(new ECPrivateKeyParameters(d, domain), random);
- ECPublicKeyParameters pubKey = new ECPublicKeyParameters(Q, domain);
-
- DSTU4145Signer dstuSigner = new DSTU4145Signer();
- dstuSigner.init(true, privKey);
- BigInteger[] rs = dstuSigner.generateSignature(hash);
-
- if (rs[0].compareTo(r) != 0)
- {
- fail("r component wrong");
- }
-
- if (rs[1].compareTo(s) != 0)
- {
- fail("s component wrong");
- }
-
- dstuSigner.init(false, pubKey);
- if (!dstuSigner.verifySignature(hash, r, s))
- {
- fail("verification fails");
- }
- }
-
- private void testTruncation()
- {
- SecureRandom random = new FixedSecureRandom(Hex.decode("0000C4224DBBD800988DBAA39DE838294C345CDA5F5929D1174AA8D9340A5E79D10ACADE6B53CF873E7301A3871C2073AD75AB530457"));
-
- // use extra long "hash" with set bits...
- byte[] hash = Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
-
- ECCurve.F2m curve = new ECCurve.F2m(173, 1, 2, 10, ZERO, new BigInteger("108576C80499DB2FC16EDDF6853BBB278F6B6FB437D9", 16));
- ECPoint P = curve.createPoint(new BigInteger("BE6628EC3E67A91A4E470894FBA72B52C515F8AEE9", 16), new BigInteger("D9DEEDF655CF5412313C11CA566CDC71F4DA57DB45C", 16));
- BigInteger n = new BigInteger("800000000000000000000189B4E67606E3825BB2831", 16);
-
- BigInteger d = new BigInteger("955CD7E344303D1034E66933DC21C8044D42ADB8", 16);
- ECPoint Q = P.multiply(d).negate();
-
- ECDomainParameters domain = new ECDomainParameters(curve, P, n);
- CipherParameters privKey = new ParametersWithRandom(new ECPrivateKeyParameters(d, domain), random);
- ECPublicKeyParameters pubKey = new ECPublicKeyParameters(Q, domain);
-
- DSTU4145Signer dstuSigner = new DSTU4145Signer();
- dstuSigner.init(true, privKey);
- BigInteger[] rs = dstuSigner.generateSignature(hash);
-
- BigInteger r = new BigInteger("6bb5c0cb82e5067485458ebfe81025f03b687c63a27", 16);
- BigInteger s = new BigInteger("34d6b1868969b86ecf934167c8fe352c63d1074bd", 16);
-
- if (rs[0].compareTo(r) != 0)
- {
- fail("r component wrong");
- }
-
- if (rs[1].compareTo(s) != 0)
- {
- fail("s component wrong");
- }
-
- dstuSigner.init(false, pubKey);
- if (!dstuSigner.verifySignature(hash, rs[0], rs[1]))
- {
- fail("verification fails");
- }
- }
-
- public void performTest()
- throws Exception
- {
- test163();
- test173();
- test283();
- test431();
- testTruncation();
- }
-
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/DeterministicDSATest.java b/core/src/test/java/org/bouncycastle/crypto/test/DeterministicDSATest.java
deleted file mode 100644
index c47cf8e8..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/DeterministicDSATest.java
+++ /dev/null
@@ -1,513 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.nist.NISTNamedCurves;
-import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DSA;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.SHA224Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.digests.SHA384Digest;
-import org.bouncycastle.crypto.digests.SHA512Digest;
-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.signers.DSASigner;
-import org.bouncycastle.crypto.signers.ECDSASigner;
-import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
-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 DeterministicDSATest
- 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()
- {
- DSAParameters dsaParameters = new DSAParameters(
- new BigInteger("86F5CA03DCFEB225063FF830A0C769B9DD9D6153AD91D7CE27F787C43278B447" +
- "E6533B86B18BED6E8A48B784A14C252C5BE0DBF60B86D6385BD2F12FB763ED88" +
- "73ABFD3F5BA2E0A8C0A59082EAC056935E529DAF7C610467899C77ADEDFC846C" +
- "881870B7B19B2B58F9BE0521A17002E3BDD6B86685EE90B3D9A1B02B782B1779", 16),
- new BigInteger("996F967F6C8E388D9E28D01E205FBA957A5698B1", 16),
- new BigInteger("07B0F92546150B62514BB771E2A0C0CE387F03BDA6C56B505209FF25FD3C133D" +
- "89BBCD97E904E09114D9A7DEFDEADFC9078EA544D2E401AEECC40BB9FBBF78FD" +
- "87995A10A1C27CB7789B594BA7EFB5C4326A9FE59A070E136DB77175464ADCA4" +
- "17BE5DCE2F40D10A46A3A3943F26AB7FD9C0398FF8C76EE0A56826A8A88F1DBD", 16));
-
- DSAPrivateKeyParameters privKey = new DSAPrivateKeyParameters(new BigInteger("411602CB19A6CCC34494D79D98EF1E7ED5AF25F7", 16), dsaParameters);
-
- doTestHMACDetDSASample(new SHA1Digest(), privKey, new BigInteger("2E1A0C2562B2912CAAF89186FB0F42001585DA55", 16), new BigInteger("29EFB6B0AFF2D7A68EB70CA313022253B9A88DF5", 16));
- doTestHMACDetDSASample(new SHA224Digest(), privKey, new BigInteger("4BC3B686AEA70145856814A6F1BB53346F02101E", 16), new BigInteger("410697B92295D994D21EDD2F4ADA85566F6F94C1", 16));
- doTestHMACDetDSASample(new SHA256Digest(), privKey, new BigInteger("81F2F5850BE5BC123C43F71A3033E9384611C545", 16), new BigInteger("4CDD914B65EB6C66A8AAAD27299BEE6B035F5E89", 16));
- doTestHMACDetDSASample(new SHA384Digest(), privKey, new BigInteger("07F2108557EE0E3921BC1774F1CA9B410B4CE65A", 16), new BigInteger("54DF70456C86FAC10FAB47C1949AB83F2C6F7595", 16));
- doTestHMACDetDSASample(new SHA512Digest(), privKey, new BigInteger("16C3491F9B8C3FBBDD5E7A7B667057F0D8EE8E1B", 16), new BigInteger("02C36A127A7B89EDBB72E4FFBC71DABC7D4FC69C", 16));
-
- doTestHMACDetDSATest(new SHA1Digest(), privKey, new BigInteger("42AB2052FD43E123F0607F115052A67DCD9C5C77", 16), new BigInteger("183916B0230D45B9931491D4C6B0BD2FB4AAF088", 16));
- doTestHMACDetDSATest(new SHA224Digest(), privKey, new BigInteger("6868E9964E36C1689F6037F91F28D5F2C30610F2", 16), new BigInteger("49CEC3ACDC83018C5BD2674ECAAD35B8CD22940F", 16));
- doTestHMACDetDSATest(new SHA256Digest(), privKey, new BigInteger("22518C127299B0F6FDC9872B282B9E70D0790812", 16), new BigInteger("6837EC18F150D55DE95B5E29BE7AF5D01E4FE160", 16));
- doTestHMACDetDSATest(new SHA384Digest(), privKey, new BigInteger("854CF929B58D73C3CBFDC421E8D5430CD6DB5E66", 16), new BigInteger("91D0E0F53E22F898D158380676A871A157CDA622", 16));
- doTestHMACDetDSATest(new SHA512Digest(), privKey, new BigInteger("8EA47E475BA8AC6F2D821DA3BD212D11A3DEB9A0", 16), new BigInteger("7C670C7AD72B6C050C109E1790008097125433E8", 16));
-
- dsaParameters = new DSAParameters(
- new BigInteger("9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48" +
- "C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44F" +
- "FE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5" +
- "B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51743BF33050C38DE2" +
- "35567E1B34C3D6A5C0CEAA1A0F368213C3D19843D0B4B09DCB9FC72D39C8DE41" +
- "F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE" +
- "92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA15" +
- "3E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B", 16),
- new BigInteger("F2C3119374CE76C9356990B465374A17F23F9ED35089BD969F61C6DDE9998C1F", 16),
- new BigInteger("5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613" +
- "D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C4" +
- "6A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472" +
- "085057F3494309FFA73C611F78B32ADBB5740C361C9F35BE90997DB2014E2EF5" +
- "AA61782F52ABEB8BD6432C4DD097BC5423B285DAFB60DC364E8161F4A2A35ACA" +
- "3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71" +
- "BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0" +
- "DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7", 16));
-
- privKey = new DSAPrivateKeyParameters(new BigInteger("69C7548C21D0DFEA6B9A51C9EAD4E27C33D3B3F180316E5BCAB92C933F0E4DBC", 16), dsaParameters);
-
- doTestHMACDetDSASample(new SHA1Digest(), privKey, new BigInteger("3A1B2DBD7489D6ED7E608FD036C83AF396E290DBD602408E8677DAABD6E7445A", 16), new BigInteger("D26FCBA19FA3E3058FFC02CA1596CDBB6E0D20CB37B06054F7E36DED0CDBBCCF", 16));
- doTestHMACDetDSASample(new SHA224Digest(), privKey, new BigInteger("DC9F4DEADA8D8FF588E98FED0AB690FFCE858DC8C79376450EB6B76C24537E2C", 16), new BigInteger("A65A9C3BC7BABE286B195D5DA68616DA8D47FA0097F36DD19F517327DC848CEC", 16));
- doTestHMACDetDSASample(new SHA256Digest(), privKey, new BigInteger("EACE8BDBBE353C432A795D9EC556C6D021F7A03F42C36E9BC87E4AC7932CC809", 16), new BigInteger("7081E175455F9247B812B74583E9E94F9EA79BD640DC962533B0680793A38D53", 16));
- doTestHMACDetDSASample(new SHA384Digest(), privKey, new BigInteger("B2DA945E91858834FD9BF616EBAC151EDBC4B45D27D0DD4A7F6A22739F45C00B", 16), new BigInteger("19048B63D9FD6BCA1D9BAE3664E1BCB97F7276C306130969F63F38FA8319021B", 16));
- doTestHMACDetDSASample(new SHA512Digest(), privKey, new BigInteger("2016ED092DC5FB669B8EFB3D1F31A91EECB199879BE0CF78F02BA062CB4C942E", 16), new BigInteger("D0C76F84B5F091E141572A639A4FB8C230807EEA7D55C8A154A224400AFF2351", 16));
-
- doTestHMACDetDSATest(new SHA1Digest(), privKey, new BigInteger("C18270A93CFC6063F57A4DFA86024F700D980E4CF4E2CB65A504397273D98EA0", 16), new BigInteger("414F22E5F31A8B6D33295C7539C1C1BA3A6160D7D68D50AC0D3A5BEAC2884FAA", 16));
- doTestHMACDetDSATest(new SHA224Digest(), privKey, new BigInteger("272ABA31572F6CC55E30BF616B7A265312018DD325BE031BE0CC82AA17870EA3", 16), new BigInteger("E9CC286A52CCE201586722D36D1E917EB96A4EBDB47932F9576AC645B3A60806", 16));
- doTestHMACDetDSATest(new SHA256Digest(), privKey, new BigInteger("8190012A1969F9957D56FCCAAD223186F423398D58EF5B3CEFD5A4146A4476F0", 16), new BigInteger("7452A53F7075D417B4B013B278D1BB8BBD21863F5E7B1CEE679CF2188E1AB19E", 16));
- doTestHMACDetDSATest(new SHA384Digest(), privKey, new BigInteger("239E66DDBE8F8C230A3D071D601B6FFBDFB5901F94D444C6AF56F732BEB954BE", 16), new BigInteger("6BD737513D5E72FE85D1C750E0F73921FE299B945AAD1C802F15C26A43D34961", 16));
- doTestHMACDetDSATest(new SHA512Digest(), privKey, new BigInteger("89EC4BB1400ECCFF8E7D9AA515CD1DE7803F2DAFF09693EE7FD1353E90A68307", 16), new BigInteger("C9F0BDABCC0D880BB137A994CC7F3980CE91CC10FAF529FC46565B15CEA854E1", 16));
- }
-
- private void doTestHMACDetDSASample(Digest digest, DSAPrivateKeyParameters privKey, BigInteger r, BigInteger s)
- {
- doTestHMACDetECDSA(new DSASigner(new HMacDSAKCalculator(digest)), digest, SAMPLE, privKey, r, s);
- }
-
- private void doTestHMACDetDSATest(Digest digest, DSAPrivateKeyParameters privKey, BigInteger r, BigInteger s)
- {
- doTestHMACDetECDSA(new DSASigner(new HMacDSAKCalculator(digest)), digest, TEST, privKey, r, s);
- }
-
- // test vectors from appendix in RFC 6979
- private void testECHMacDeterministic()
- {
- X9ECParameters x9ECParameters = NISTNamedCurves.getByName("P-192");
- ECDomainParameters ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
-
- ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(new BigInteger("6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4", 16), ecDomainParameters);
-
- doTestHMACDetECDSASample(new SHA1Digest(), privKey, new BigInteger("98C6BD12B23EAF5E2A2045132086BE3EB8EBD62ABF6698FF", 16), new BigInteger("57A22B07DEA9530F8DE9471B1DC6624472E8E2844BC25B64", 16));
- doTestHMACDetECDSASample(new SHA224Digest(), privKey, new BigInteger("A1F00DAD97AEEC91C95585F36200C65F3C01812AA60378F5", 16), new BigInteger("E07EC1304C7C6C9DEBBE980B9692668F81D4DE7922A0F97A", 16));
- doTestHMACDetECDSASample(new SHA256Digest(), privKey, new BigInteger("4B0B8CE98A92866A2820E20AA6B75B56382E0F9BFD5ECB55", 16), new BigInteger("CCDB006926EA9565CBADC840829D8C384E06DE1F1E381B85", 16));
- doTestHMACDetECDSASample(new SHA384Digest(), privKey, new BigInteger("DA63BF0B9ABCF948FBB1E9167F136145F7A20426DCC287D5", 16), new BigInteger("C3AA2C960972BD7A2003A57E1C4C77F0578F8AE95E31EC5E", 16));
- doTestHMACDetECDSASample(new SHA512Digest(), privKey, new BigInteger("4D60C5AB1996BD848343B31C00850205E2EA6922DAC2E4B8", 16), new BigInteger("3F6E837448F027A1BF4B34E796E32A811CBB4050908D8F67", 16));
-
- doTestHMACDetECDSATest(new SHA1Digest(), privKey, new BigInteger("0F2141A0EBBC44D2E1AF90A50EBCFCE5E197B3B7D4DE036D", 16), new BigInteger("EB18BC9E1F3D7387500CB99CF5F7C157070A8961E38700B7", 16));
- doTestHMACDetECDSATest(new SHA224Digest(), privKey, new BigInteger("6945A1C1D1B2206B8145548F633BB61CEF04891BAF26ED34", 16), new BigInteger("B7FB7FDFC339C0B9BD61A9F5A8EAF9BE58FC5CBA2CB15293", 16));
- doTestHMACDetECDSATest(new SHA256Digest(), privKey, new BigInteger("3A718BD8B4926C3B52EE6BBE67EF79B18CB6EB62B1AD97AE", 16), new BigInteger("5662E6848A4A19B1F1AE2F72ACD4B8BBE50F1EAC65D9124F", 16));
- doTestHMACDetECDSATest(new SHA384Digest(), privKey, new BigInteger("B234B60B4DB75A733E19280A7A6034BD6B1EE88AF5332367", 16), new BigInteger("7994090B2D59BB782BE57E74A44C9A1C700413F8ABEFE77A", 16));
- doTestHMACDetECDSATest(new SHA512Digest(), privKey, new BigInteger("FE4F4AE86A58B6507946715934FE2D8FF9D95B6B098FE739", 16), new BigInteger("74CF5605C98FBA0E1EF34D4B5A1577A7DCF59457CAE52290", 16));
-
- x9ECParameters = NISTNamedCurves.getByName("P-224");
- ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
-
- privKey = new ECPrivateKeyParameters(new BigInteger("F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1", 16), ecDomainParameters);
-
- doTestHMACDetECDSASample(new SHA1Digest(), privKey, new BigInteger("22226F9D40A96E19C4A301CE5B74B115303C0F3A4FD30FC257FB57AC", 16), new BigInteger("66D1CDD83E3AF75605DD6E2FEFF196D30AA7ED7A2EDF7AF475403D69", 16));
- doTestHMACDetECDSASample(new SHA224Digest(), privKey, new BigInteger("1CDFE6662DDE1E4A1EC4CDEDF6A1F5A2FB7FBD9145C12113E6ABFD3E", 16), new BigInteger("A6694FD7718A21053F225D3F46197CA699D45006C06F871808F43EBC", 16));
- doTestHMACDetECDSASample(new SHA256Digest(), privKey, new BigInteger("61AA3DA010E8E8406C656BC477A7A7189895E7E840CDFE8FF42307BA", 16), new BigInteger("BC814050DAB5D23770879494F9E0A680DC1AF7161991BDE692B10101", 16));
- doTestHMACDetECDSASample(new SHA384Digest(), privKey, new BigInteger("0B115E5E36F0F9EC81F1325A5952878D745E19D7BB3EABFABA77E953", 16), new BigInteger("830F34CCDFE826CCFDC81EB4129772E20E122348A2BBD889A1B1AF1D", 16));
- doTestHMACDetECDSASample(new SHA512Digest(), privKey, new BigInteger("074BD1D979D5F32BF958DDC61E4FB4872ADCAFEB2256497CDAC30397", 16), new BigInteger("A4CECA196C3D5A1FF31027B33185DC8EE43F288B21AB342E5D8EB084", 16));
-
- doTestHMACDetECDSATest(new SHA1Digest(), privKey, new BigInteger("DEAA646EC2AF2EA8AD53ED66B2E2DDAA49A12EFD8356561451F3E21C", 16), new BigInteger("95987796F6CF2062AB8135271DE56AE55366C045F6D9593F53787BD2", 16));
- doTestHMACDetECDSATest(new SHA224Digest(), privKey, new BigInteger("C441CE8E261DED634E4CF84910E4C5D1D22C5CF3B732BB204DBEF019", 16), new BigInteger("902F42847A63BDC5F6046ADA114953120F99442D76510150F372A3F4", 16));
- doTestHMACDetECDSATest(new SHA256Digest(), privKey, new BigInteger("AD04DDE87B84747A243A631EA47A1BA6D1FAA059149AD2440DE6FBA6", 16), new BigInteger("178D49B1AE90E3D8B629BE3DB5683915F4E8C99FDF6E666CF37ADCFD", 16));
- doTestHMACDetECDSATest(new SHA384Digest(), privKey, new BigInteger("389B92682E399B26518A95506B52C03BC9379A9DADF3391A21FB0EA4", 16), new BigInteger("414A718ED3249FF6DBC5B50C27F71F01F070944DA22AB1F78F559AAB", 16));
- doTestHMACDetECDSATest(new SHA512Digest(), privKey, new BigInteger("049F050477C5ADD858CAC56208394B5A55BAEBBE887FDF765047C17C", 16), new BigInteger("077EB13E7005929CEFA3CD0403C7CDCC077ADF4E44F3C41B2F60ECFF", 16));
-
- x9ECParameters = NISTNamedCurves.getByName("P-256");
- ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
-
- privKey = new ECPrivateKeyParameters(new BigInteger("C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721", 16), ecDomainParameters);
-
- doTestHMACDetECDSASample(new SHA1Digest(), privKey, new BigInteger("61340C88C3AAEBEB4F6D667F672CA9759A6CCAA9FA8811313039EE4A35471D32", 16), new BigInteger("6D7F147DAC089441BB2E2FE8F7A3FA264B9C475098FDCF6E00D7C996E1B8B7EB", 16));
- doTestHMACDetECDSASample(new SHA224Digest(), privKey, new BigInteger("53B2FFF5D1752B2C689DF257C04C40A587FABABB3F6FC2702F1343AF7CA9AA3F", 16), new BigInteger("B9AFB64FDC03DC1A131C7D2386D11E349F070AA432A4ACC918BEA988BF75C74C", 16));
- doTestHMACDetECDSASample(new SHA256Digest(), privKey, new BigInteger("EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716", 16), new BigInteger("F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8", 16));
- doTestHMACDetECDSASample(new SHA384Digest(), privKey, new BigInteger("0EAFEA039B20E9B42309FB1D89E213057CBF973DC0CFC8F129EDDDC800EF7719", 16), new BigInteger("4861F0491E6998B9455193E34E7B0D284DDD7149A74B95B9261F13ABDE940954", 16));
- doTestHMACDetECDSASample(new SHA512Digest(), privKey, new BigInteger("8496A60B5E9B47C825488827E0495B0E3FA109EC4568FD3F8D1097678EB97F00", 16), new BigInteger("2362AB1ADBE2B8ADF9CB9EDAB740EA6049C028114F2460F96554F61FAE3302FE", 16));
-
- doTestHMACDetECDSATest(new SHA1Digest(), privKey, new BigInteger("0CBCC86FD6ABD1D99E703E1EC50069EE5C0B4BA4B9AC60E409E8EC5910D81A89", 16), new BigInteger("01B9D7B73DFAA60D5651EC4591A0136F87653E0FD780C3B1BC872FFDEAE479B1", 16));
- doTestHMACDetECDSATest(new SHA224Digest(), privKey, new BigInteger("C37EDB6F0AE79D47C3C27E962FA269BB4F441770357E114EE511F662EC34A692", 16), new BigInteger("C820053A05791E521FCAAD6042D40AEA1D6B1A540138558F47D0719800E18F2D", 16));
- doTestHMACDetECDSATest(new SHA256Digest(), privKey, new BigInteger("F1ABB023518351CD71D881567B1EA663ED3EFCF6C5132B354F28D3B0B7D38367", 16), new BigInteger("019F4113742A2B14BD25926B49C649155F267E60D3814B4C0CC84250E46F0083", 16));
- doTestHMACDetECDSATest(new SHA384Digest(), privKey, new BigInteger("83910E8B48BB0C74244EBDF7F07A1C5413D61472BD941EF3920E623FBCCEBEB6", 16), new BigInteger("8DDBEC54CF8CD5874883841D712142A56A8D0F218F5003CB0296B6B509619F2C", 16));
- doTestHMACDetECDSATest(new SHA512Digest(), privKey, new BigInteger("461D93F31B6540894788FD206C07CFA0CC35F46FA3C91816FFF1040AD1581A04", 16), new BigInteger("39AF9F15DE0DB8D97E72719C74820D304CE5226E32DEDAE67519E840D1194E55", 16));
-
- x9ECParameters = NISTNamedCurves.getByName("P-384");
- ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
-
- privKey = new ECPrivateKeyParameters(new BigInteger("6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D8" +
- "96D5724E4C70A825F872C9EA60D2EDF5", 16), ecDomainParameters);
-
- doTestHMACDetECDSASample(new SHA1Digest(), privKey, new BigInteger("EC748D839243D6FBEF4FC5C4859A7DFFD7F3ABDDF72014540C16D73309834FA3" +
- "7B9BA002899F6FDA3A4A9386790D4EB2", 16),
- new BigInteger("A3BCFA947BEEF4732BF247AC17F71676CB31A847B9FF0CBC9C9ED4C1A5B3FACF" +
- "26F49CA031D4857570CCB5CA4424A443", 16));
- doTestHMACDetECDSASample(new SHA224Digest(), privKey, new BigInteger("42356E76B55A6D9B4631C865445DBE54E056D3B3431766D0509244793C3F9366" +
- "450F76EE3DE43F5A125333A6BE060122", 16),
- new BigInteger("9DA0C81787064021E78DF658F2FBB0B042BF304665DB721F077A4298B095E483" +
- "4C082C03D83028EFBF93A3C23940CA8D", 16));
- doTestHMACDetECDSASample(new SHA256Digest(), privKey, new BigInteger("21B13D1E013C7FA1392D03C5F99AF8B30C570C6F98D4EA8E354B63A21D3DAA33" +
- "BDE1E888E63355D92FA2B3C36D8FB2CD", 16),
- new BigInteger("F3AA443FB107745BF4BD77CB3891674632068A10CA67E3D45DB2266FA7D1FEEB" +
- "EFDC63ECCD1AC42EC0CB8668A4FA0AB0", 16));
- doTestHMACDetECDSASample(new SHA384Digest(), privKey, new BigInteger("94EDBB92A5ECB8AAD4736E56C691916B3F88140666CE9FA73D64C4EA95AD133C" +
- "81A648152E44ACF96E36DD1E80FABE46", 16),
- new BigInteger("99EF4AEB15F178CEA1FE40DB2603138F130E740A19624526203B6351D0A3A94F" +
- "A329C145786E679E7B82C71A38628AC8", 16));
- doTestHMACDetECDSASample(new SHA512Digest(), privKey, new BigInteger("ED0959D5880AB2D869AE7F6C2915C6D60F96507F9CB3E047C0046861DA4A799C" +
- "FE30F35CC900056D7C99CD7882433709", 16),
- new BigInteger("512C8CCEEE3890A84058CE1E22DBC2198F42323CE8ACA9135329F03C068E5112" +
- "DC7CC3EF3446DEFCEB01A45C2667FDD5", 16));
-
- doTestHMACDetECDSATest(new SHA1Digest(), privKey, new BigInteger("4BC35D3A50EF4E30576F58CD96CE6BF638025EE624004A1F7789A8B8E43D0678" +
- "ACD9D29876DAF46638645F7F404B11C7", 16),
- new BigInteger("D5A6326C494ED3FF614703878961C0FDE7B2C278F9A65FD8C4B7186201A29916" +
- "95BA1C84541327E966FA7B50F7382282", 16));
- doTestHMACDetECDSATest(new SHA224Digest(), privKey, new BigInteger("E8C9D0B6EA72A0E7837FEA1D14A1A9557F29FAA45D3E7EE888FC5BF954B5E624" +
- "64A9A817C47FF78B8C11066B24080E72", 16),
- new BigInteger("07041D4A7A0379AC7232FF72E6F77B6DDB8F09B16CCE0EC3286B2BD43FA8C614" +
- "1C53EA5ABEF0D8231077A04540A96B66", 16));
- doTestHMACDetECDSATest(new SHA256Digest(), privKey, new BigInteger("6D6DEFAC9AB64DABAFE36C6BF510352A4CC27001263638E5B16D9BB51D451559" +
- "F918EEDAF2293BE5B475CC8F0188636B", 16),
- new BigInteger("2D46F3BECBCC523D5F1A1256BF0C9B024D879BA9E838144C8BA6BAEB4B53B47D" +
- "51AB373F9845C0514EEFB14024787265", 16));
- doTestHMACDetECDSATest(new SHA384Digest(), privKey, new BigInteger("8203B63D3C853E8D77227FB377BCF7B7B772E97892A80F36AB775D509D7A5FEB" +
- "0542A7F0812998DA8F1DD3CA3CF023DB", 16),
- new BigInteger("DDD0760448D42D8A43AF45AF836FCE4DE8BE06B485E9B61B827C2F13173923E0" +
- "6A739F040649A667BF3B828246BAA5A5", 16));
- doTestHMACDetECDSATest(new SHA512Digest(), privKey, new BigInteger("A0D5D090C9980FAF3C2CE57B7AE951D31977DD11C775D314AF55F76C676447D0" +
- "6FB6495CD21B4B6E340FC236584FB277", 16),
- new BigInteger("976984E59B4C77B0E8E4460DCA3D9F20E07B9BB1F63BEEFAF576F6B2E8B22463" +
- "4A2092CD3792E0159AD9CEE37659C736", 16));
-
- x9ECParameters = NISTNamedCurves.getByName("P-521");
- ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
-
- privKey = new ECPrivateKeyParameters(new BigInteger("0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75C" +
- "AA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83" +
- "538", 16), ecDomainParameters);
-
- doTestHMACDetECDSASample(new SHA1Digest(), privKey, new BigInteger("0343B6EC45728975EA5CBA6659BBB6062A5FF89EEA58BE3C80B619F322C87910" +
- "FE092F7D45BB0F8EEE01ED3F20BABEC079D202AE677B243AB40B5431D497C55D" +
- "75D", 16),
- new BigInteger("0E7B0E675A9B24413D448B8CC119D2BF7B2D2DF032741C096634D6D65D0DBE3D" +
- "5694625FB9E8104D3B842C1B0E2D0B98BEA19341E8676AEF66AE4EBA3D5475D5" +
- "D16", 16));
- doTestHMACDetECDSASample(new SHA224Digest(), privKey, new BigInteger("1776331CFCDF927D666E032E00CF776187BC9FDD8E69D0DABB4109FFE1B5E2A3" +
- "0715F4CC923A4A5E94D2503E9ACFED92857B7F31D7152E0F8C00C15FF3D87E2E" +
- "D2E", 16),
- new BigInteger("050CB5265417FE2320BBB5A122B8E1A32BD699089851128E360E620A30C7E17B" +
- "A41A666AF126CE100E5799B153B60528D5300D08489CA9178FB610A2006C254B" +
- "41F", 16));
- doTestHMACDetECDSASample(new SHA256Digest(), privKey, new BigInteger("1511BB4D675114FE266FC4372B87682BAECC01D3CC62CF2303C92B3526012659" +
- "D16876E25C7C1E57648F23B73564D67F61C6F14D527D54972810421E7D87589E" +
- "1A7", 16),
- new BigInteger("04A171143A83163D6DF460AAF61522695F207A58B95C0644D87E52AA1A347916" +
- "E4F7A72930B1BC06DBE22CE3F58264AFD23704CBB63B29B931F7DE6C9D949A7E" +
- "CFC", 16));
- doTestHMACDetECDSASample(new SHA384Digest(), privKey, new BigInteger("1EA842A0E17D2DE4F92C15315C63DDF72685C18195C2BB95E572B9C5136CA4B4" +
- "B576AD712A52BE9730627D16054BA40CC0B8D3FF035B12AE75168397F5D50C67" +
- "451", 16),
- new BigInteger("1F21A3CEE066E1961025FB048BD5FE2B7924D0CD797BABE0A83B66F1E35EEAF5" +
- "FDE143FA85DC394A7DEE766523393784484BDF3E00114A1C857CDE1AA203DB65" +
- "D61", 16));
- doTestHMACDetECDSASample(new SHA512Digest(), privKey, new BigInteger("0C328FAFCBD79DD77850370C46325D987CB525569FB63C5D3BC53950E6D4C5F1" +
- "74E25A1EE9017B5D450606ADD152B534931D7D4E8455CC91F9B15BF05EC36E37" +
- "7FA", 16),
- new BigInteger("0617CCE7CF5064806C467F678D3B4080D6F1CC50AF26CA209417308281B68AF2" +
- "82623EAA63E5B5C0723D8B8C37FF0777B1A20F8CCB1DCCC43997F1EE0E44DA4A" +
- "67A", 16));
-
- doTestHMACDetECDSATest(new SHA1Digest(), privKey, new BigInteger("13BAD9F29ABE20DE37EBEB823C252CA0F63361284015A3BF430A46AAA80B87B0" +
- "693F0694BD88AFE4E661FC33B094CD3B7963BED5A727ED8BD6A3A202ABE009D0" +
- "367", 16),
- new BigInteger("1E9BB81FF7944CA409AD138DBBEE228E1AFCC0C890FC78EC8604639CB0DBDC90" +
- "F717A99EAD9D272855D00162EE9527567DD6A92CBD629805C0445282BBC91679" +
- "7FF", 16));
- doTestHMACDetECDSATest(new SHA224Digest(), privKey, new BigInteger("1C7ED902E123E6815546065A2C4AF977B22AA8EADDB68B2C1110E7EA44D42086" +
- "BFE4A34B67DDC0E17E96536E358219B23A706C6A6E16BA77B65E1C595D43CAE1" +
- "7FB", 16),
- new BigInteger("177336676304FCB343CE028B38E7B4FBA76C1C1B277DA18CAD2A8478B2A9A9F5" +
- "BEC0F3BA04F35DB3E4263569EC6AADE8C92746E4C82F8299AE1B8F1739F8FD51" +
- "9A4", 16));
- doTestHMACDetECDSATest(new SHA256Digest(), privKey, new BigInteger("00E871C4A14F993C6C7369501900C4BC1E9C7B0B4BA44E04868B30B41D807104" +
- "2EB28C4C250411D0CE08CD197E4188EA4876F279F90B3D8D74A3C76E6F1E4656" +
- "AA8", 16),
- new BigInteger("0CD52DBAA33B063C3A6CD8058A1FB0A46A4754B034FCC644766CA14DA8CA5CA9" +
- "FDE00E88C1AD60CCBA759025299079D7A427EC3CC5B619BFBC828E7769BCD694" +
- "E86", 16));
- doTestHMACDetECDSATest(new SHA384Digest(), privKey, new BigInteger("14BEE21A18B6D8B3C93FAB08D43E739707953244FDBE924FA926D76669E7AC8C" +
- "89DF62ED8975C2D8397A65A49DCC09F6B0AC62272741924D479354D74FF60755" +
- "78C", 16),
- new BigInteger("133330865C067A0EAF72362A65E2D7BC4E461E8C8995C3B6226A21BD1AA78F0E" +
- "D94FE536A0DCA35534F0CD1510C41525D163FE9D74D134881E35141ED5E8E95B" +
- "979", 16));
- doTestHMACDetECDSATest(new SHA512Digest(), privKey, new BigInteger("13E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10" +
- "CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47E" +
- "E6D", 16),
- new BigInteger("1FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78" +
- "A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4D" +
- "CE3", 16));
-
- x9ECParameters = NISTNamedCurves.getByName("B-163");
- ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
-
- privKey = new ECPrivateKeyParameters(new BigInteger("35318FC447D48D7E6BC93B48617DDDEDF26AA658F", 16), ecDomainParameters);
-
- doTestHMACDetECDSASample(new SHA1Digest(), privKey, new BigInteger("153FEBD179A69B6122DEBF5BC61EB947B24C93526", 16), new BigInteger("37AC9C670F8CF18045049BAE7DD35553545C19E49", 16));
- doTestHMACDetECDSASample(new SHA224Digest(), privKey, new BigInteger("0A379E69C44F9C16EA3215EA39EB1A9B5D58CC955", 16), new BigInteger("04BAFF5308DA2A7FE2C1742769265AD3ED1D24E74", 16));
- doTestHMACDetECDSASample(new SHA256Digest(), privKey, new BigInteger("134E00F78FC1CB9501675D91C401DE20DDF228CDC", 16), new BigInteger("373273AEC6C36CB7BAFBB1903A5F5EA6A1D50B624", 16));
- doTestHMACDetECDSASample(new SHA384Digest(), privKey, new BigInteger("29430B935AF8E77519B0CA4F6903B0B82E6A21A66", 16), new BigInteger("1EA1415306E9353FA5AA54BC7C2581DFBB888440D", 16));
- doTestHMACDetECDSASample(new SHA512Digest(), privKey, new BigInteger("0B2F177A99F9DF2D51CCAF55F015F326E4B65E7A0", 16), new BigInteger("0DF1FB4487E9B120C5E970EFE48F55E406306C3A1", 16));
-
- doTestHMACDetECDSATest(new SHA1Digest(), privKey, new BigInteger("256D4079C6C7169B8BC92529D701776A269D56308", 16), new BigInteger("341D3FFEC9F1EB6A6ACBE88E3C86A1C8FDEB8B8E1", 16));
- doTestHMACDetECDSATest(new SHA224Digest(), privKey, new BigInteger("28ECC6F1272CE80EA59DCF32F7AC2D861BA803393", 16), new BigInteger("0AD4AE2C06E60183C1567D2B82F19421FE3053CE2", 16));
- doTestHMACDetECDSATest(new SHA256Digest(), privKey, new BigInteger("227DF377B3FA50F90C1CB3CDCBBDBA552C1D35104", 16), new BigInteger("1F7BEAD92583FE920D353F368C1960D0E88B46A56", 16));
- doTestHMACDetECDSATest(new SHA384Digest(), privKey, new BigInteger("11811DAFEEA441845B6118A0DFEE8A0061231337D", 16), new BigInteger("36258301865EE48C5C6F91D63F62695002AB55B57", 16));
- doTestHMACDetECDSATest(new SHA512Digest(), privKey, new BigInteger("3B6BB95CA823BE2ED8E3972FF516EB8972D765571", 16), new BigInteger("13DC6F420628969DF900C3FCC48220B38BE24A541", 16));
-
- x9ECParameters = NISTNamedCurves.getByName("B-233");
- ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
-
- privKey = new ECPrivateKeyParameters(new BigInteger("07ADC13DD5BF34D1DDEEB50B2CE23B5F5E6D18067306D60C5F6FF11E5D3", 16), ecDomainParameters);
-
- doTestHMACDetECDSASample(new SHA1Digest(), privKey, new BigInteger("015CC6FD78BB06E0878E71465515EA5A21A2C18E6FC77B4B158DBEB3944", 16), new BigInteger("0822A4A6C2EB2DF213A5E90BF40377956365EE8C4B4A5A4E2EB9270CB6A", 16));
- doTestHMACDetECDSASample(new SHA224Digest(), privKey, new BigInteger("05D9920B53471148E10502AB49AB7A3F11084820A074FD89883CF51BC1A", 16), new BigInteger("04D3938900C0A9AAA7080D1DFEB56CFB0FADABE4214536C7ED5117ED13A", 16));
- doTestHMACDetECDSASample(new SHA256Digest(), privKey, new BigInteger("0A797F3B8AEFCE7456202DF1E46CCC291EA5A49DA3D4BDDA9A4B62D5E0D", 16), new BigInteger("01F6F81DA55C22DA4152134C661588F4BD6F82FDBAF0C5877096B070DC2", 16));
- doTestHMACDetECDSASample(new SHA384Digest(), privKey, new BigInteger("015E85A8D46225DD7E314A1C4289731FC14DECE949349FE535D11043B85", 16), new BigInteger("03F189D37F50493EFD5111A129443A662AB3C6B289129AD8C0CAC85119C", 16));
- doTestHMACDetECDSASample(new SHA512Digest(), privKey, new BigInteger("03B62A4BF783919098B1E42F496E65F7621F01D1D466C46940F0F132A95", 16), new BigInteger("0F4BE031C6E5239E7DAA014CBBF1ED19425E49DAEB426EC9DF4C28A2E30", 16));
-
- doTestHMACDetECDSATest(new SHA1Digest(), privKey, new BigInteger("02F1FEDC57BE203E4C8C6B8C1CEB35E13C1FCD956AB41E3BD4C8A6EFB1F", 16), new BigInteger("05738EC8A8EDEA8E435EE7266AD3EDE1EEFC2CEBE2BE1D614008D5D2951", 16));
- doTestHMACDetECDSATest(new SHA224Digest(), privKey, new BigInteger("0CCE175124D3586BA7486F7146894C65C2A4A5A1904658E5C7F9DF5FA5D", 16), new BigInteger("08804B456D847ACE5CA86D97BF79FD6335E5B17F6C0D964B5D0036C867E", 16));
- doTestHMACDetECDSATest(new SHA256Digest(), privKey, new BigInteger("035C3D6DFEEA1CFB29B93BE3FDB91A7B130951770C2690C16833A159677", 16), new BigInteger("0600F7301D12AB376B56D4459774159ADB51F97E282FF384406AFD53A02", 16));
- doTestHMACDetECDSATest(new SHA384Digest(), privKey, new BigInteger("061602FC8068BFD5FB86027B97455D200EC603057446CCE4D76DB8EF42C", 16), new BigInteger("03396DD0D59C067BB999B422D9883736CF9311DFD6951F91033BD03CA8D", 16));
- doTestHMACDetECDSATest(new SHA512Digest(), privKey, new BigInteger("07E12CB60FDD614958E8E34B3C12DDFF35D85A9C5800E31EA2CC2EF63B1", 16), new BigInteger("0E8970FD99D836F3CC1C807A2C58760DE6EDAA23705A82B9CB1CE93FECC", 16));
-
- x9ECParameters = NISTNamedCurves.getByName("B-283");
- ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
-
- privKey = new ECPrivateKeyParameters(new BigInteger("14510D4BC44F2D26F4553942C98073C1BD35545CEABB5CC138853C5158D2729EA408836", 16), ecDomainParameters);
-
- doTestHMACDetECDSASample(new SHA1Digest(), privKey, new BigInteger("201E18D48C6DB3D5D097C4DCE1E25587E1501FC3CF47BDB5B4289D79E273D6A9" +
- "ACB8285", 16), new BigInteger("151AE05712B024CE617358260774C8CA8B0E7A7E72EF8229BF2ACE7609560CB3" +
- "0322C4F", 16));
- doTestHMACDetECDSASample(new SHA224Digest(), privKey, new BigInteger("143E878DDFD4DF40D97B8CD638B3C4706501C2201CF7108F2FB91478C11D6947" +
- "3246925", 16), new BigInteger("0CBF1B9717FEEA3AABB09D9654110144267098E0E1E8D0289A6211BE0EEDFDD8" +
- "6A3DB79", 16));
- doTestHMACDetECDSASample(new SHA256Digest(), privKey, new BigInteger("29FD82497FB3E5CEF65579272138DE59E2B666B8689466572B3B69A172CEE83B" +
- "E145659", 16), new BigInteger("05A89D9166B40795AF0FE5958201B9C0523E500013CA12B4840EA2BC53F25F9B" +
- "3CE87C0", 16));
- doTestHMACDetECDSASample(new SHA384Digest(), privKey, new BigInteger("2F00689C1BFCD2A8C7A41E0DE55AE182E6463A152828EF89FE3525139B660329" +
- "4E69353", 16), new BigInteger("1744514FE0A37447250C8A329EAAADA81572226CABA16F39270EE5DD03F27B1F" +
- "665EB5D", 16));
- doTestHMACDetECDSASample(new SHA512Digest(), privKey, new BigInteger("0DA43A9ADFAA6AD767998A054C6A8F1CF77A562924628D73C62761847AD8286E" +
- "0D91B47", 16), new BigInteger("1D118733AE2C88357827CAFC6F68ABC25C80C640532925E95CFE66D40F8792F3" +
- "AC44C42", 16));
-
- doTestHMACDetECDSATest(new SHA1Digest(), privKey, new BigInteger("05A408133919F2CDCDBE5E4C14FBC706C1F71BADAFEF41F5DE4EC27272FC1CA9" +
- "366FBB2", 16), new BigInteger("012966272872C097FEA7BCE64FAB1A81982A773E26F6E4EF7C99969846E67CA9" +
- "CBE1692", 16));
- doTestHMACDetECDSATest(new SHA224Digest(), privKey, new BigInteger("08F3824E40C16FF1DDA8DC992776D26F4A5981AB5092956C4FDBB4F1AE0A711E" +
- "EAA10E5", 16), new BigInteger("0A64B91EFADB213E11483FB61C73E3EF63D3B44EEFC56EA401B99DCC60CC28E9" +
- "9F0F1FA", 16));
- doTestHMACDetECDSATest(new SHA256Digest(), privKey, new BigInteger("3597B406F5329D11A79E887847E5EC60861CCBB19EC61F252DB7BD549C699951" +
- "C182796", 16), new BigInteger("0A6A100B997BC622D91701D9F5C6F6D3815517E577622DA69D3A0E8917C1CBE6" +
- "3ACD345", 16));
- doTestHMACDetECDSATest(new SHA384Digest(), privKey, new BigInteger("1BB490926E5A1FDC7C5AA86D0835F9B994EDA315CA408002AF54A298728D422E" +
- "BF59E4C", 16), new BigInteger("36C682CFC9E2C89A782BFD3A191609D1F0C1910D5FD6981442070393159D65FB" +
- "CC0A8BA", 16));
- doTestHMACDetECDSATest(new SHA512Digest(), privKey, new BigInteger("19944AA68F9778C2E3D6E240947613E6DA60EFCE9B9B2C063FF5466D72745B5A" +
- "0B25BA2", 16), new BigInteger("03F1567B3C5B02DF15C874F0EE22850824693D5ADC4663BAA19E384E550B1DD4" +
- "1F31EE6", 16));
-
- x9ECParameters = NISTNamedCurves.getByName("B-409");
- ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
-
- privKey = new ECPrivateKeyParameters(new BigInteger("0494994CC325B08E7B4CE038BD9436F90B5E59A2C13C3140CD3AE07C04A01FC489F572CE0569A6DB7B8060393DE76330C624177", 16), ecDomainParameters);
-
- doTestHMACDetECDSASample(new SHA1Digest(), privKey, new BigInteger("0D8783188E1A540E2022D389E1D35B32F56F8C2BB5636B8ABF7718806B27A713" +
- "EBAE37F63ECD4B61445CEF5801B62594EF3E982", 16), new BigInteger("03A6B4A80E204DB0DE12E7415C13C9EC091C52935658316B4A0C591216A38791" +
- "54BEB1712560E346E7EF26517707435B55C3141", 16));
- doTestHMACDetECDSASample(new SHA224Digest(), privKey, new BigInteger("0EE4F39ACC2E03CE96C3D9FCBAFA5C22C89053662F8D4117752A9B10F09ADFDA" +
- "59DB061E247FE5321D6B170EE758ACE1BE4D157", 16), new BigInteger("00A2B83265B456A430A8BF27DCC8A9488B3F126C10F0D6D64BF7B8A218FAAF20" +
- "E51A295A3AE78F205E5A4A6AE224C3639F1BB34", 16));
- doTestHMACDetECDSASample(new SHA256Digest(), privKey, new BigInteger("02D8B1B31E33E74D7EB46C30FDE5AD2CA04EC8FE08FBA0E73BA5E568953AC5EA" +
- "307C072942238DFC07F4A4D7C7C6A9F86436D17", 16), new BigInteger("079F7D471E6CB73234AF7F7C381D2CE15DE35BAF8BB68393B73235B3A26EC2DF" +
- "4842CE433FB492D6E074E604D4870024D42189A", 16));
- doTestHMACDetECDSASample(new SHA384Digest(), privKey, new BigInteger("07BC638B7E7CE6FEE5E9C64A0F966D722D01BB4BC3F3A35F30D4CDDA92DFC5F7" +
- "F0B4BBFE8065D9AD452FD77A1914BE3A2440C18", 16), new BigInteger("06D904429850521B28A32CBF55C7C0FDF35DC4E0BDA2552C7BF68A171E970E67" +
- "88ACC0B9521EACB4796E057C70DD9B95FED5BFB", 16));
- doTestHMACDetECDSASample(new SHA512Digest(), privKey, new BigInteger("05D178DECAFD2D02A3DA0D8BA1C4C1D95EE083C760DF782193A9F7B4A8BE6FC5" +
- "C21FD60613BCA65C063A61226E050A680B3ABD4", 16), new BigInteger("013B7581E98F6A63FBBCB3E49BCDA60F816DB230B888506D105DC229600497C3" +
- "B46588C784BE3AA9343BEF82F7C9C80AEB63C3B", 16));
-
- doTestHMACDetECDSATest(new SHA1Digest(), privKey, new BigInteger("049F54E7C10D2732B4638473053782C6919218BBEFCEC8B51640FC193E832291" +
- "F05FA12371E9B448417B3290193F08EE9319195", 16), new BigInteger("0499E267DEC84E02F6F108B10E82172C414F15B1B7364BE8BFD66ADC0C5DE23F" +
- "EE3DF0D811134C25AFE0E05A6672F98889F28F1", 16));
- doTestHMACDetECDSATest(new SHA224Digest(), privKey, new BigInteger("0B1527FFAA7DD7C7E46B628587A5BEC0539A2D04D3CF27C54841C2544E1BBDB4" +
- "2FDBDAAF8671A4CA86DFD619B1E3732D7BB56F2", 16), new BigInteger("0442C68C044868DF4832C807F1EDDEBF7F5052A64B826FD03451440794063F52" +
- "B022DF304F47403D4069234CA9EB4C964B37C02", 16));
- doTestHMACDetECDSATest(new SHA256Digest(), privKey, new BigInteger("0BB27755B991D6D31757BCBF68CB01225A38E1CFA20F775E861055DD108ED7EA" +
- "455E4B96B2F6F7CD6C6EC2B3C70C3EDDEB9743B", 16), new BigInteger("0C5BE90980E7F444B5F7A12C9E9AC7A04CA81412822DD5AD1BE7C45D5032555E" +
- "A070864245CF69266871FEB8CD1B7EDC30EF6D5", 16));
- doTestHMACDetECDSATest(new SHA384Digest(), privKey, new BigInteger("04EFEB7098772187907C87B33E0FBBA4584226C50C11E98CA7AAC6986F8D3BE0" +
- "44E5B52D201A410B852536527724CA5F8CE6549", 16), new BigInteger("09574102FEB3EF87E6D66B94119F5A6062950FF4F902EA1E6BD9E2037F33FF99" +
- "1E31F5956C23AFE48FCDC557FD6F088C7C9B2B3", 16));
- doTestHMACDetECDSATest(new SHA512Digest(), privKey, new BigInteger("07E0249C68536AE2AEC2EC30090340DA49E6DC9E9EEC8F85E5AABFB234B6DA7D" +
- "2E9524028CF821F21C6019770474CC40B01FAF6", 16), new BigInteger("08125B5A03FB44AE81EA46D446130C2A415ECCA265910CA69D55F2453E16CD7B" +
- "2DFA4E28C50FA8137F9C0C6CEE4CD37ABCCF6D8", 16));
-
- x9ECParameters = NISTNamedCurves.getByName("B-571");
- ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
-
- privKey = new ECPrivateKeyParameters(new BigInteger("028A04857F24C1C082DF0D909C0E72F453F2E2340CCB071F0E389BCA2575DA19" +
- "124198C57174929AD26E348CF63F78D28021EF5A9BF2D5CBEAF6B7CCB6C4DA82" +
- "4DD5C82CFB24E11", 16), ecDomainParameters);
-
- doTestHMACDetECDSASample(new SHA1Digest(), privKey, new BigInteger("147D3EB0EDA9F2152DFD014363D6A9CE816D7A1467D326A625FC4AB0C786E1B7" +
- "4DDF7CD4D0E99541391B266C704BB6B6E8DCCD27B460802E0867143727AA4155" +
- "55454321EFE5CB6", 16),
- new BigInteger("17319571CAF533D90D2E78A64060B9C53169AB7FC908947B3EDADC54C79CCF0A" +
- "7920B4C64A4EAB6282AFE9A459677CDA37FD6DD50BEF18709590FE18B923BDF7" +
- "4A66B189A850819", 16));
-
- doTestHMACDetECDSASample(new SHA224Digest(), privKey, new BigInteger("10F4B63E79B2E54E4F4F6A2DBC786D8F4A143ECA7B2AD97810F6472AC6AE2085" +
- "3222854553BE1D44A7974599DB7061AE8560DF57F2675BE5F9DD94ABAF3D47F1" +
- "582B318E459748B", 16),
- new BigInteger("3BBEA07C6B269C2B7FE9AE4DDB118338D0C2F0022920A7F9DCFCB7489594C03B" +
- "536A9900C4EA6A10410007222D3DAE1A96F291C4C9275D75D98EB290DC0EEF17" +
- "6037B2C7A7A39A3", 16));
-
- doTestHMACDetECDSASample(new SHA256Digest(), privKey, new BigInteger("213EF9F3B0CFC4BF996B8AF3A7E1F6CACD2B87C8C63820000800AC787F17EC99" +
- "C04BCEDF29A8413CFF83142BB88A50EF8D9A086AF4EB03E97C567500C21D8657" +
- "14D832E03C6D054", 16),
- new BigInteger("3D32322559B094E20D8935E250B6EC139AC4AAB77920812C119AF419FB62B332" +
- "C8D226C6C9362AE3C1E4AABE19359B8428EA74EC8FBE83C8618C2BCCB6B43FBA" +
- "A0F2CCB7D303945", 16));
-
- doTestHMACDetECDSASample(new SHA384Digest(), privKey, new BigInteger("375D8F49C656A0BBD21D3F54CDA287D853C4BB1849983CD891EF6CD6BB56A62B" +
- "687807C16685C2C9BCA2663C33696ACCE344C45F3910B1DF806204FF731ECB28" +
- "9C100EF4D1805EC", 16),
- new BigInteger("1CDEC6F46DFEEE44BCE71D41C60550DC67CF98D6C91363625AC2553E4368D2DF" +
- "B734A8E8C72E118A76ACDB0E58697940A0F3DF49E72894BD799450FC9E550CC0" +
- "4B9FF9B0380021C", 16));
- doTestHMACDetECDSASample(new SHA512Digest(), privKey, new BigInteger("1C26F40D940A7EAA0EB1E62991028057D91FEDA0366B606F6C434C361F04E545" +
- "A6A51A435E26416F6838FFA260C617E798E946B57215284182BE55F29A355E60" +
- "24FE32A47289CF0", 16),
- new BigInteger("3691DE4369D921FE94EDDA67CB71FBBEC9A436787478063EB1CC778B3DCDC1C4" +
- "162662752D28DEEDF6F32A269C82D1DB80C87CE4D3B662E03AC347806E3F19D1" +
- "8D6D4DE7358DF7E", 16));
-
- doTestHMACDetECDSATest(new SHA1Digest(), privKey, new BigInteger("133F5414F2A9BC41466D339B79376038A64D045E5B0F792A98E5A7AA87E0AD01" +
- "6419E5F8D176007D5C9C10B5FD9E2E0AB8331B195797C0358BA05ECBF24ACE59" +
- "C5F368A6C0997CC", 16),
- new BigInteger("3D16743AE9F00F0B1A500F738719C5582550FEB64689DA241665C4CE4F328BA0" +
- "E34A7EF527ED13BFA5889FD2D1D214C11EB17D6BC338E05A56F41CAFF1AF7B8D" +
- "574DB62EF0D0F21", 16));
-
- doTestHMACDetECDSATest(new SHA224Digest(), privKey, new BigInteger("3048E76506C5C43D92B2E33F62B33E3111CEEB87F6C7DF7C7C01E3CDA28FA5E8" +
- "BE04B5B23AA03C0C70FEF8F723CBCEBFF0B7A52A3F5C8B84B741B4F6157E69A5" +
- "FB0524B48F31828", 16),
- new BigInteger("2C99078CCFE5C82102B8D006E3703E020C46C87C75163A2CD839C885550BA5CB" +
- "501AC282D29A1C26D26773B60FBE05AAB62BFA0BA32127563D42F7669C97784C" +
- "8897C22CFB4B8FA", 16));
-
- doTestHMACDetECDSATest(new SHA256Digest(), privKey, new BigInteger("184BC808506E11A65D628B457FDA60952803C604CC7181B59BD25AEE1411A66D" +
- "12A777F3A0DC99E1190C58D0037807A95E5080FA1B2E5CCAA37B50D401CFFC34" +
- "17C005AEE963469", 16),
- new BigInteger("27280D45F81B19334DBDB07B7E63FE8F39AC7E9AE14DE1D2A6884D2101850289" +
- "D70EE400F26ACA5E7D73F534A14568478E59D00594981ABE6A1BA18554C13EB5" +
- "E03921E4DC98333", 16));
-
- doTestHMACDetECDSATest(new SHA384Digest(), privKey, new BigInteger("319EE57912E7B0FAA1FBB145B0505849A89C6DB1EC06EA20A6A7EDE072A6268A" +
- "F6FD9C809C7E422A5F33C6C3326EAD7402467DF3272A1B2726C1C20975950F0F" +
- "50D8324578F13EC", 16),
- new BigInteger("2CF3EA27EADD0612DD2F96F46E89AB894B01A10DF985C5FC099CFFE0EA083EB4" +
- "4BE682B08BFE405DAD5F37D0A2C59015BA41027E24B99F8F75A70B6B7385BF39" +
- "BBEA02513EB880C", 16));
- doTestHMACDetECDSATest(new SHA512Digest(), privKey, new BigInteger("2AA1888EAB05F7B00B6A784C4F7081D2C833D50794D9FEAF6E22B8BE728A2A90" +
- "BFCABDC803162020AA629718295A1489EE7ED0ECB8AAA197B9BDFC49D18DDD78" +
- "FC85A48F9715544", 16),
- new BigInteger("0AA5371FE5CA671D6ED9665849C37F394FED85D51FEF72DA2B5F28EDFB2C6479" +
- "CA63320C19596F5E1101988E2C619E302DD05112F47E8823040CE540CD3E90DC" +
- "F41DBC461744EE9", 16));
-
- }
-
- private void doTestHMACDetECDSASample(Digest digest, ECPrivateKeyParameters privKey, BigInteger r, BigInteger s)
- {
- doTestHMACDetECDSA(new ECDSASigner(new HMacDSAKCalculator(digest)), digest, SAMPLE, privKey, r, s);
- }
-
- private void doTestHMACDetECDSATest(Digest digest, ECPrivateKeyParameters privKey, BigInteger r, BigInteger s)
- {
- doTestHMACDetECDSA(new ECDSASigner(new HMacDSAKCalculator(digest)), digest, TEST, privKey, r, s);
- }
-
- private void doTestHMACDetECDSA(DSA detSigner, Digest digest, byte[] data, CipherParameters privKey, BigInteger r, BigInteger s)
- {
- byte[] m = new byte[digest.getDigestSize()];
-
- digest.update(data, 0, data.length);
-
- digest.doFinal(m, 0);
-
- detSigner.init(true, privKey);
-
- BigInteger[] rs = detSigner.generateSignature(m);
-
- if (!r.equals(rs[0]))
- {
- fail("r value wrong");
- }
- if (!s.equals(rs[1]))
- {
- fail("s value wrong");
- }
- }
-
- public String getName()
- {
- return "DeterministicDSA";
- }
-
- public void performTest()
- {
- testHMacDeterministic();
- testECHMacDeterministic();
- }
-
-
- public static void main(
- String[] args)
- {
- runTest(new DeterministicDSATest());
- }
-}
-
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/DigestRandomNumberTest.java b/core/src/test/java/org/bouncycastle/crypto/test/DigestRandomNumberTest.java
deleted file mode 100644
index 7bcaea8a..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/DigestRandomNumberTest.java
+++ /dev/null
@@ -1,152 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.util.test.SimpleTest;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.crypto.prng.DigestRandomGenerator;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.Digest;
-
-public class DigestRandomNumberTest
- extends SimpleTest
-{
- private static final byte[] ZERO_SEED = { 0, 0, 0, 0, 0, 0, 0, 0 };
-
- private static final byte[] TEST_SEED = Hex.decode("81dcfafc885914057876");
-
- private static final byte[] expected0SHA1 = Hex.decode("95bca677b3d4ff793213c00892d2356ec729ee02");
- private static final byte[] noCycle0SHA1 = Hex.decode("d57ccd0eb12c3938d59226412bc1268037b6b846");
- private static final byte[] expected0SHA256 = Hex.decode("587e2dfd597d086e47ddcd343eac983a5c913bef8c6a1a560a5c1bc3a74b0991");
- private static final byte[] noCycle0SHA256 = Hex.decode("e5776c4483486ba7be081f4e1b9dafbab25c8fae290fd5474c1ceda2c16f9509");
- private static final byte[] expected100SHA1 = Hex.decode("b9d924092546e0876cafd4937d7364ebf9efa4be");
- private static final byte[] expected100SHA256 = Hex.decode("fbc4aa54b948b99de104c44563a552899d718bb75d1941cc62a2444b0506abaf");
- private static final byte[] expectedTestSHA1 = Hex.decode("e9ecef9f5306daf1ac51a89a211a64cb24415649");
- private static final byte[] expectedTestSHA256 = Hex.decode("bdab3ca831b472a2fa09bd1bade541ef16c96640a91fcec553679a136061de98");
-
- private static final byte[] sha1Xors = Hex.decode("7edcc1216934f3891b03ffa65821611a3e2b1f79");
- private static final byte[] sha256Xors = Hex.decode("5ec48189cc0aa71e79c707bc3c33ffd47bbba368a83d6cfebf3cd3969d7f3eed");
-
- public String getName()
- {
- return "DigestRandomNumber";
- }
-
- private void doExpectedTest(Digest digest, int seed, byte[] expected)
- {
- doExpectedTest(digest, seed, expected, null);
- }
-
- private void doExpectedTest(Digest digest, int seed, byte[] expected, byte[] noCycle)
- {
- DigestRandomGenerator rGen = new DigestRandomGenerator(digest);
- byte[] output = new byte[digest.getDigestSize()];
-
- rGen.addSeedMaterial(seed);
-
- for (int i = 0; i != 1024; i++)
- {
- rGen.nextBytes(output);
- }
-
- if (noCycle != null)
- {
- if (Arrays.areEqual(noCycle, output))
- {
- fail("seed not being cycled!");
- }
- }
-
- if (!Arrays.areEqual(expected, output))
- {
- fail("expected output doesn't match");
- }
- }
-
- private void doExpectedTest(Digest digest, byte[] seed, byte[] expected)
- {
- DigestRandomGenerator rGen = new DigestRandomGenerator(digest);
- byte[] output = new byte[digest.getDigestSize()];
-
- rGen.addSeedMaterial(seed);
-
- for (int i = 0; i != 1024; i++)
- {
- rGen.nextBytes(output);
- }
-
- if (!Arrays.areEqual(expected, output))
- {
- fail("expected output doesn't match");
- }
- }
-
- private void doCountTest(Digest digest, byte[] seed, byte[] expectedXors)
- {
- DigestRandomGenerator rGen = new DigestRandomGenerator(digest);
- byte[] output = new byte[digest.getDigestSize()];
- int[] averages = new int[digest.getDigestSize()];
- byte[] ands = new byte[digest.getDigestSize()];
- byte[] xors = new byte[digest.getDigestSize()];
- byte[] ors = new byte[digest.getDigestSize()];
-
- rGen.addSeedMaterial(seed);
-
- for (int i = 0; i != 1000000; i++)
- {
- rGen.nextBytes(output);
- for (int j = 0; j != output.length; j++)
- {
- averages[j] += output[j] & 0xff;
- ands[j] &= output[j];
- xors[j] ^= output[j];
- ors[j] |= output[j];
- }
- }
-
- for (int i = 0; i != output.length; i++)
- {
- if ((averages[i] / 1000000) != 127)
- {
- fail("average test failed for " + digest.getAlgorithmName());
- }
- if (ands[i] != 0)
- {
- fail("and test failed for " + digest.getAlgorithmName());
- }
- if ((ors[i] & 0xff) != 0xff)
- {
- fail("or test failed for " + digest.getAlgorithmName());
- }
- if (xors[i] != expectedXors[i])
- {
- fail("xor test failed for " + digest.getAlgorithmName());
- }
- }
- }
-
- public void performTest()
- throws Exception
- {
- doExpectedTest(new SHA1Digest(), 0, expected0SHA1, noCycle0SHA1);
- doExpectedTest(new SHA256Digest(), 0, expected0SHA256, noCycle0SHA256);
-
- doExpectedTest(new SHA1Digest(), 100, expected100SHA1);
- doExpectedTest(new SHA256Digest(), 100, expected100SHA256);
-
- doExpectedTest(new SHA1Digest(), ZERO_SEED, expected0SHA1);
- doExpectedTest(new SHA256Digest(), ZERO_SEED, expected0SHA256);
-
- doExpectedTest(new SHA1Digest(), TEST_SEED, expectedTestSHA1);
- doExpectedTest(new SHA256Digest(), TEST_SEED, expectedTestSHA256);
-
- doCountTest(new SHA1Digest(), TEST_SEED, sha1Xors);
- doCountTest(new SHA256Digest(), TEST_SEED, sha256Xors);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new DigestRandomNumberTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/DigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/DigestTest.java
deleted file mode 100644
index db9b490e..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/DigestTest.java
+++ /dev/null
@@ -1,226 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.EncodableDigest;
-import org.bouncycastle.util.Memoable;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public abstract class DigestTest
- extends SimpleTest
-{
- private Digest digest;
- private String[] input;
- private String[] results;
-
- DigestTest(
- Digest digest,
- String[] input,
- String[] results)
- {
- this.digest = digest;
- this.input = input;
- this.results = results;
- }
-
- public String getName()
- {
- return digest.getAlgorithmName();
- }
-
- public void performTest()
- {
- byte[] resBuf = new byte[digest.getDigestSize()];
-
- for (int i = 0; i < input.length - 1; i++)
- {
- byte[] m = toByteArray(input[i]);
-
- vectorTest(digest, i, resBuf, m, Hex.decode(results[i]));
- }
-
- byte[] lastV = toByteArray(input[input.length - 1]);
- byte[] lastDigest = Hex.decode(results[input.length - 1]);
-
- vectorTest(digest, input.length - 1, resBuf, lastV, Hex.decode(results[input.length - 1]));
-
- testClone(resBuf, lastV, lastDigest);
- testMemo(resBuf, lastV, lastDigest);
- if (digest instanceof EncodableDigest)
- {
- testEncodedState(resBuf, lastV, lastDigest);
- }
- }
-
- private void testEncodedState(byte[] resBuf, byte[] input, byte[] expected)
- {
- // test state encoding;
- digest.update(input, 0, input.length / 2);
-
- // copy the Digest
- Digest copy1 = cloneDigest(((EncodableDigest)digest).getEncodedState());
- Digest copy2 = cloneDigest(((EncodableDigest)copy1).getEncodedState());
-
- digest.update(input, input.length / 2, input.length - input.length / 2);
-
- digest.doFinal(resBuf, 0);
-
- if (!areEqual(expected, resBuf))
- {
- fail("failing state vector test", expected, new String(Hex.encode(resBuf)));
- }
-
- copy1.update(input, input.length / 2, input.length - input.length / 2);
- copy1.doFinal(resBuf, 0);
-
- if (!areEqual(expected, resBuf))
- {
- fail("failing state copy1 vector test", expected, new String(Hex.encode(resBuf)));
- }
-
- copy2.update(input, input.length / 2, input.length - input.length / 2);
- copy2.doFinal(resBuf, 0);
-
- if (!areEqual(expected, resBuf))
- {
- fail("failing state copy2 vector test", expected, new String(Hex.encode(resBuf)));
- }
- }
-
- private void testMemo(byte[] resBuf, byte[] input, byte[] expected)
- {
- Memoable m = (Memoable)digest;
-
- digest.update(input, 0, input.length/2);
-
- // copy the Digest
- Memoable copy1 = m.copy();
- Memoable copy2 = copy1.copy();
-
- digest.update(input, input.length/2, input.length - input.length/2);
- digest.doFinal(resBuf, 0);
-
- if (!areEqual(expected, resBuf))
- {
- fail("failing memo vector test", results[results.length - 1], new String(Hex.encode(resBuf)));
- }
-
- m.reset(copy1);
-
- digest.update(input, input.length/2, input.length - input.length/2);
- digest.doFinal(resBuf, 0);
-
- if (!areEqual(expected, resBuf))
- {
- fail("failing memo reset vector test", results[results.length - 1], new String(Hex.encode(resBuf)));
- }
-
- Digest md = (Digest)copy2;
-
- md.update(input, input.length/2, input.length - input.length/2);
- md.doFinal(resBuf, 0);
-
- if (!areEqual(expected, resBuf))
- {
- fail("failing memo copy vector test", results[results.length - 1], new String(Hex.encode(resBuf)));
- }
- }
-
- private void testClone(byte[] resBuf, byte[] input, byte[] expected)
- {
- digest.update(input, 0, input.length/2);
-
- // clone the Digest
- Digest d = cloneDigest(digest);
-
- digest.update(input, input.length/2, input.length - input.length/2);
- digest.doFinal(resBuf, 0);
-
- if (!areEqual(expected, resBuf))
- {
- fail("failing clone vector test", results[results.length - 1], new String(Hex.encode(resBuf)));
- }
-
- d.update(input, input.length/2, input.length - input.length/2);
- d.doFinal(resBuf, 0);
-
- if (!areEqual(expected, resBuf))
- {
- fail("failing second clone vector test", results[results.length - 1], new String(Hex.encode(resBuf)));
- }
- }
-
- protected byte[] toByteArray(String input)
- {
- byte[] bytes = new byte[input.length()];
-
- for (int i = 0; i != bytes.length; i++)
- {
- bytes[i] = (byte)input.charAt(i);
- }
-
- return bytes;
- }
-
- private void vectorTest(
- Digest digest,
- int count,
- byte[] resBuf,
- byte[] input,
- byte[] expected)
- {
- digest.update(input, 0, input.length);
- digest.doFinal(resBuf, 0);
-
- if (!areEqual(resBuf, expected))
- {
- fail("Vector " + count + " failed got " + new String(Hex.encode(resBuf)));
- }
- }
-
- protected abstract Digest cloneDigest(Digest digest);
-
- protected Digest cloneDigest(byte[] encodedState)
- {
- throw new IllegalStateException("Unsupported");
- }
-
- //
- // optional tests
- //
- protected void millionATest(
- String expected)
- {
- byte[] resBuf = new byte[digest.getDigestSize()];
-
- for (int i = 0; i < 1000000; i++)
- {
- digest.update((byte)'a');
- }
-
- digest.doFinal(resBuf, 0);
-
- if (!areEqual(resBuf, Hex.decode(expected)))
- {
- fail("Million a's failed", expected, new String(Hex.encode(resBuf)));
- }
- }
-
- protected void sixtyFourKTest(
- String expected)
- {
- byte[] resBuf = new byte[digest.getDigestSize()];
-
- for (int i = 0; i < 65536; i++)
- {
- digest.update((byte)(i & 0xff));
- }
-
- digest.doFinal(resBuf, 0);
-
- if (!areEqual(resBuf, Hex.decode(expected)))
- {
- fail("64k test failed", expected, new String(Hex.encode(resBuf)));
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/EAXTest.java b/core/src/test/java/org/bouncycastle/crypto/test/EAXTest.java
deleted file mode 100644
index 401d9fa3..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/EAXTest.java
+++ /dev/null
@@ -1,355 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.engines.AESEngine;
-import org.bouncycastle.crypto.engines.AESFastEngine;
-import org.bouncycastle.crypto.modes.AEADBlockCipher;
-import org.bouncycastle.crypto.modes.EAXBlockCipher;
-import org.bouncycastle.crypto.params.AEADParameters;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Strings;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class EAXTest
- extends SimpleTest
-{
- private byte[] K1 = Hex.decode("233952DEE4D5ED5F9B9C6D6FF80FF478");
- private byte[] N1 = Hex.decode("62EC67F9C3A4A407FCB2A8C49031A8B3");
- private byte[] A1 = Hex.decode("6BFB914FD07EAE6B");
- private byte[] P1 = Hex.decode("");
- private byte[] C1 = Hex.decode("E037830E8389F27B025A2D6527E79D01");
- private byte[] T1 = Hex.decode("E037830E8389F27B025A2D6527E79D01");
-
- 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");
- private byte[] T2 = Hex.decode("5C4C9331049D0BDAB0277408F67967E5");
-
- private byte[] K3 = Hex.decode("01F74AD64077F2E704C0F60ADA3DD523");
- private byte[] N3 = Hex.decode("70C3DB4F0D26368400A10ED05D2BFF5E");
- private byte[] A3 = Hex.decode("234A3463C1264AC6");
- private byte[] P3 = Hex.decode("1A47CB4933");
- private byte[] C3 = Hex.decode("D851D5BAE03A59F238A23E39199DC9266626C40F80");
- private byte[] T3 = Hex.decode("3A59F238A23E39199DC9266626C40F80");
-
- private byte[] K4 = Hex.decode("D07CF6CBB7F313BDDE66B727AFD3C5E8");
- private byte[] N4 = Hex.decode("8408DFFF3C1A2B1292DC199E46B7D617");
- private byte[] A4 = Hex.decode("33CCE2EABFF5A79D");
- private byte[] P4 = Hex.decode("481C9E39B1");
- private byte[] C4 = Hex.decode("632A9D131AD4C168A4225D8E1FF755939974A7BEDE");
- private byte[] T4 = Hex.decode("D4C168A4225D8E1FF755939974A7BEDE");
-
- private byte[] K5 = Hex.decode("35B6D0580005BBC12B0587124557D2C2");
- private byte[] N5 = Hex.decode("FDB6B06676EEDC5C61D74276E1F8E816");
- private byte[] A5 = Hex.decode("AEB96EAEBE2970E9");
- private byte[] P5 = Hex.decode("40D0C07DA5E4");
- private byte[] C5 = Hex.decode("071DFE16C675CB0677E536F73AFE6A14B74EE49844DD");
- private byte[] T5 = Hex.decode("CB0677E536F73AFE6A14B74EE49844DD");
-
- private byte[] K6 = Hex.decode("BD8E6E11475E60B268784C38C62FEB22");
- private byte[] N6 = Hex.decode("6EAC5C93072D8E8513F750935E46DA1B");
- private byte[] A6 = Hex.decode("D4482D1CA78DCE0F");
- private byte[] P6 = Hex.decode("4DE3B35C3FC039245BD1FB7D");
- private byte[] C6 = Hex.decode("835BB4F15D743E350E728414ABB8644FD6CCB86947C5E10590210A4F");
- private byte[] T6 = Hex.decode("ABB8644FD6CCB86947C5E10590210A4F");
-
- private byte[] K7 = Hex.decode("7C77D6E813BED5AC98BAA417477A2E7D");
- private byte[] N7 = Hex.decode("1A8C98DCD73D38393B2BF1569DEEFC19");
- private byte[] A7 = Hex.decode("65D2017990D62528");
- private byte[] P7 = Hex.decode("8B0A79306C9CE7ED99DAE4F87F8DD61636");
- private byte[] C7 = Hex.decode("02083E3979DA014812F59F11D52630DA30137327D10649B0AA6E1C181DB617D7F2");
- private byte[] T7 = Hex.decode("137327D10649B0AA6E1C181DB617D7F2");
-
- private byte[] K8 = Hex.decode("5FFF20CAFAB119CA2FC73549E20F5B0D");
- private byte[] N8 = Hex.decode("DDE59B97D722156D4D9AFF2BC7559826");
- private byte[] A8 = Hex.decode("54B9F04E6A09189A");
- private byte[] P8 = Hex.decode("1BDA122BCE8A8DBAF1877D962B8592DD2D56");
- private byte[] C8 = Hex.decode("2EC47B2C4954A489AFC7BA4897EDCDAE8CC33B60450599BD02C96382902AEF7F832A");
- private byte[] T8 = Hex.decode("3B60450599BD02C96382902AEF7F832A");
-
- private byte[] K9 = Hex.decode("A4A4782BCFFD3EC5E7EF6D8C34A56123");
- private byte[] N9 = Hex.decode("B781FCF2F75FA5A8DE97A9CA48E522EC");
- private byte[] A9 = Hex.decode("899A175897561D7E");
- private byte[] P9 = Hex.decode("6CF36720872B8513F6EAB1A8A44438D5EF11");
- private byte[] C9 = Hex.decode("0DE18FD0FDD91E7AF19F1D8EE8733938B1E8E7F6D2231618102FDB7FE55FF1991700");
- private byte[] T9 = Hex.decode("E7F6D2231618102FDB7FE55FF1991700");
-
- private byte[] K10 = Hex.decode("8395FCF1E95BEBD697BD010BC766AAC3");
- private byte[] N10 = Hex.decode("22E7ADD93CFC6393C57EC0B3C17D6B44");
- private byte[] A10 = Hex.decode("126735FCC320D25A");
- private byte[] P10 = Hex.decode("CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7");
- private byte[] C10 = Hex.decode("CB8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC253B4652B1AF3795B124AB6E");
- private byte[] T10 = Hex.decode("CFC46AFC253B4652B1AF3795B124AB6E");
-
- private byte[] K11 = Hex.decode("8395FCF1E95BEBD697BD010BC766AAC3");
- private byte[] N11 = Hex.decode("22E7ADD93CFC6393C57EC0B3C17D6B44");
- private byte[] A11 = Hex.decode("126735FCC320D25A");
- private byte[] P11 = Hex.decode("CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7");
- private byte[] C11 = Hex.decode("CB8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC");
- private byte[] T11 = Hex.decode("CFC46AFC");
-
- private static final int NONCE_LEN = 8;
- private static final int MAC_LEN = 8;
- private static final int AUTHEN_LEN = 20;
-
- public String getName()
- {
- return "EAX";
- }
-
- public void performTest()
- throws Exception
- {
- checkVectors(1, K1, 128, N1, A1, P1, T1, C1);
- checkVectors(2, K2, 128, N2, A2, P2, T2, C2);
- checkVectors(3, K3, 128, N3, A3, P3, T3, C3);
- checkVectors(4, K4, 128, N4, A4, P4, T4, C4);
- checkVectors(5, K5, 128, N5, A5, P5, T5, C5);
- checkVectors(6, K6, 128, N6, A6, P6, T6, C6);
- checkVectors(7, K7, 128, N7, A7, P7, T7, C7);
- checkVectors(8, K8, 128, N8, A8, P8, T8, C8);
- checkVectors(9, K9, 128, N9, A9, P9, T9, C9);
- checkVectors(10, K10, 128, N10, A10, P10, T10, C10);
- checkVectors(11, K11, 32, N11, A11, P11, T11, C11);
-
- EAXBlockCipher eax = new EAXBlockCipher(new AESFastEngine());
- ivParamTest(1, eax, K1, N1);
-
- //
- // exception tests
- //
-
- try
- {
- eax.init(false, new AEADParameters(new KeyParameter(K1), 32, N2, A2));
-
- byte[] enc = new byte[C2.length];
- int len = eax.processBytes(C2, 0, C2.length, enc, 0);
-
- len += eax.doFinal(enc, len);
-
- fail("invalid cipher text not picked up");
- }
- catch (InvalidCipherTextException e)
- {
- // expected
- }
-
- try
- {
- eax.init(false, new KeyParameter(K1));
-
- fail("illegal argument not picked up");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- randomTests();
- AEADTestUtil.testReset(this, new EAXBlockCipher(new AESEngine()), new EAXBlockCipher(new AESEngine()), new AEADParameters(new KeyParameter(K1), 32, N2));
- AEADTestUtil.testTampering(this, eax, new AEADParameters(new KeyParameter(K1), 32, N2));
- AEADTestUtil.testOutputSizes(this, new EAXBlockCipher(new AESEngine()), new AEADParameters(
- new KeyParameter(K1), 32, N2));
- AEADTestUtil.testBufferSizeChecks(this, new EAXBlockCipher(new AESEngine()), new AEADParameters(
- new KeyParameter(K1), 32, N2));
- }
-
- private void checkVectors(
- int count,
- byte[] k,
- int macSize,
- byte[] n,
- byte[] a,
- byte[] p,
- byte[] t,
- byte[] c)
- throws InvalidCipherTextException
- {
- byte[] fa = new byte[a.length / 2];
- byte[] la = new byte[a.length - (a.length / 2)];
- System.arraycopy(a, 0, fa, 0, fa.length);
- System.arraycopy(a, fa.length, la, 0, la.length);
-
- checkVectors(count, "all initial associated data", k, macSize, n, a, null, p, t, c);
- checkVectors(count, "subsequent associated data", k, macSize, n, null, a, p, t, c);
- checkVectors(count, "split associated data", k, macSize, n, fa, la, p, t, c);
- }
-
- private void checkVectors(
- int count,
- String additionalDataType,
- byte[] k,
- int macSize,
- byte[] n,
- byte[] a,
- byte[] sa,
- byte[] p,
- byte[] t,
- byte[] c)
- throws InvalidCipherTextException
- {
- EAXBlockCipher encEax = new EAXBlockCipher(new AESFastEngine());
- EAXBlockCipher decEax = new EAXBlockCipher(new AESFastEngine());
-
- AEADParameters parameters = new AEADParameters(new KeyParameter(k), macSize, n, a);
- encEax.init(true, parameters);
- decEax.init(false, parameters);
-
- runCheckVectors(count, encEax, decEax, additionalDataType, sa, p, t, c);
- runCheckVectors(count, encEax, decEax, additionalDataType, sa, p, t, c);
-
- // key reuse test
- parameters = new AEADParameters(null, macSize, n, a);
- encEax.init(true, parameters);
- decEax.init(false, parameters);
-
- runCheckVectors(count, encEax, decEax, additionalDataType, sa, p, t, c);
- runCheckVectors(count, encEax, decEax, additionalDataType, sa, p, t, c);
- }
-
- private void runCheckVectors(
- int count,
- EAXBlockCipher encEax,
- EAXBlockCipher decEax,
- String additionalDataType,
- byte[] sa,
- byte[] p,
- byte[] t,
- byte[] c)
- throws InvalidCipherTextException
- {
- byte[] enc = new byte[c.length];
-
- if (sa != null)
- {
- encEax.processAADBytes(sa, 0, sa.length);
- }
-
- int len = encEax.processBytes(p, 0, p.length, enc, 0);
-
- len += encEax.doFinal(enc, len);
-
- if (!areEqual(c, enc))
- {
- fail("encrypted stream fails to match in test " + count + " with " + additionalDataType);
- }
-
- byte[] tmp = new byte[enc.length];
-
- if (sa != null)
- {
- decEax.processAADBytes(sa, 0, sa.length);
- }
-
- len = decEax.processBytes(enc, 0, enc.length, tmp, 0);
-
- len += decEax.doFinal(tmp, len);
-
- byte[] dec = new byte[len];
-
- System.arraycopy(tmp, 0, dec, 0, len);
-
- if (!areEqual(p, dec))
- {
- fail("decrypted stream fails to match in test " + count + " with " + additionalDataType);
- }
-
- if (!areEqual(t, decEax.getMac()))
- {
- fail("MAC fails to match in test " + count + " with " + additionalDataType);
- }
- }
-
- private void ivParamTest(
- int count,
- AEADBlockCipher eax,
- byte[] k,
- byte[] n)
- throws InvalidCipherTextException
- {
- byte[] p = Strings.toByteArray("hello world!!");
-
- eax.init(true, new ParametersWithIV(new KeyParameter(k), n));
-
- byte[] enc = new byte[p.length + 8];
-
- int len = eax.processBytes(p, 0, p.length, enc, 0);
-
- len += eax.doFinal(enc, len);
-
- eax.init(false, new ParametersWithIV(new KeyParameter(k), n));
-
- byte[] tmp = new byte[enc.length];
-
- len = eax.processBytes(enc, 0, enc.length, tmp, 0);
-
- len += eax.doFinal(tmp, len);
-
- byte[] dec = new byte[len];
-
- System.arraycopy(tmp, 0, dec, 0, len);
-
- if (!areEqual(p, dec))
- {
- fail("decrypted stream fails to match in test " + count);
- }
- }
-
- private void randomTests()
- throws InvalidCipherTextException
- {
- SecureRandom srng = new SecureRandom();
- for (int i = 0; i < 10; ++i)
- {
- randomTest(srng);
- }
- }
-
- private void randomTest(
- SecureRandom srng)
- throws InvalidCipherTextException
- {
- int DAT_LEN = srng.nextInt() >>> 22; // Note: JDK1.0 compatibility
- byte[] nonce = new byte[NONCE_LEN];
- byte[] authen = new byte[AUTHEN_LEN];
- byte[] datIn = new byte[DAT_LEN];
- byte[] key = new byte[16];
- srng.nextBytes(nonce);
- srng.nextBytes(authen);
- srng.nextBytes(datIn);
- srng.nextBytes(key);
-
- AESFastEngine engine = new AESFastEngine();
- KeyParameter sessKey = new KeyParameter(key);
- EAXBlockCipher eaxCipher = new EAXBlockCipher(engine);
-
- AEADParameters params = new AEADParameters(sessKey, MAC_LEN * 8, nonce, authen);
- eaxCipher.init(true, params);
-
- byte[] intrDat = new byte[eaxCipher.getOutputSize(datIn.length)];
- int outOff = eaxCipher.processBytes(datIn, 0, DAT_LEN, intrDat, 0);
- outOff += eaxCipher.doFinal(intrDat, outOff);
-
- eaxCipher.init(false, params);
- byte[] datOut = new byte[eaxCipher.getOutputSize(outOff)];
- int resultLen = eaxCipher.processBytes(intrDat, 0, outOff, datOut, 0);
- eaxCipher.doFinal(datOut, resultLen);
-
- if (!areEqual(datIn, datOut))
- {
- fail("EAX roundtrip failed to match");
- }
- }
-
- public static void main(String[] args)
- {
- runTest(new EAXTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/ECDHKEKGeneratorTest.java b/core/src/test/java/org/bouncycastle/crypto/test/ECDHKEKGeneratorTest.java
deleted file mode 100644
index d75b1396..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/ECDHKEKGeneratorTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.crypto.DerivationFunction;
-import org.bouncycastle.crypto.DerivationParameters;
-import org.bouncycastle.crypto.agreement.kdf.DHKDFParameters;
-import org.bouncycastle.crypto.agreement.kdf.ECDHKEKGenerator;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * ECDHKEK Generator tests.
- */
-public class ECDHKEKGeneratorTest
- extends SimpleTest
-{
- private byte[] seed1 = Hex.decode("db4a8daba1f98791d54e940175dd1a5f3a0826a1066aa9b668d4dc1e1e0790158dcad1533c03b44214d1b61fefa8b579");
- private ASN1ObjectIdentifier alg1 = NISTObjectIdentifiers.id_aes256_wrap;
- private byte[] result1 = Hex.decode("8ecc6d85caf25eaba823a7d620d4ab0d33e4c645f2");
-
- private byte[] seed2 = Hex.decode("75d7487b5d3d2bfb3c69ce0365fe64e3bfab5d0d63731628a9f47eb8fddfa28c65decaf228a0b38f0c51c6a3356d7c56");
- private ASN1ObjectIdentifier alg2 = NISTObjectIdentifiers.id_aes128_wrap;
- private byte[] result2 = Hex.decode("042be1faca3a4a8fc859241bfb87ba35");
-
- private byte[] seed3 = Hex.decode("fdeb6d809f997e8ac174d638734dc36d37aaf7e876e39967cd82b1cada3de772449788461ee7f856bad9305627f8e48b");
- private ASN1ObjectIdentifier alg3 = PKCSObjectIdentifiers.id_alg_CMS3DESwrap;
- private byte[] result3 = Hex.decode("bcd701fc92109b1b9d6f3b6497ad5ca9627fa8a597010305");
-
- public ECDHKEKGeneratorTest()
- {
- }
-
- public void performTest()
- {
- checkMask(1, new ECDHKEKGenerator(new SHA1Digest()), new DHKDFParameters(alg1, 256, seed1), result1);
- checkMask(2, new ECDHKEKGenerator(new SHA1Digest()), new DHKDFParameters(alg2, 128, seed2), result2);
- checkMask(3, new ECDHKEKGenerator(new SHA1Digest()), new DHKDFParameters(alg3, 192, seed3), result3);
- }
-
- private void checkMask(
- int count,
- DerivationFunction kdf,
- DerivationParameters params,
- byte[] result)
- {
- byte[] data = new byte[result.length];
-
- kdf.init(params);
-
- kdf.generateBytes(data, 0, data.length);
-
- if (!areEqual(result, data))
- {
- fail("ECDHKEKGenerator failed generator test " + count);
- }
- }
-
- public String getName()
- {
- return "ECDHKEKGenerator";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new ECDHKEKGeneratorTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/ECGOST3410Test.java b/core/src/test/java/org/bouncycastle/crypto/test/ECGOST3410Test.java
deleted file mode 100644
index 175835cd..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/ECGOST3410Test.java
+++ /dev/null
@@ -1,327 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.digests.GOST3411Digest;
-import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.signers.ECGOST3410Signer;
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.FixedSecureRandom;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * ECGOST3410 tests are taken from GOST R 34.10-2001.
- */
-public class ECGOST3410Test
- extends SimpleTest
- {
- byte[] hashmessage = Hex.decode("3042453136414534424341374533364339313734453431443642453241453435");
-
- /**
- * ECGOST3410 over the field Fp<br>
- */
- BigInteger r = new BigInteger("29700980915817952874371204983938256990422752107994319651632687982059210933395");
- BigInteger s = new BigInteger("574973400270084654178925310019147038455227042649098563933718999175515839552");
-
- byte[] kData = new BigInteger("53854137677348463731403841147996619241504003434302020712960838528893196233395").toByteArray();
-
- SecureRandom k = new FixedSecureRandom(kData);
-
- private void ecGOST3410_TEST()
- {
- BigInteger mod_p = new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564821041"); //p
- BigInteger mod_q = new BigInteger("57896044618658097711785492504343953927082934583725450622380973592137631069619");
-
- ECCurve.Fp curve = new ECCurve.Fp(
- mod_p, // p
- new BigInteger("7"), // a
- new BigInteger("43308876546767276905765904595650931995942111794451039583252968842033849580414"), // b
- mod_q, ECConstants.ONE);
-
- ECDomainParameters params = new ECDomainParameters(
- curve,
- curve.createPoint(
- new BigInteger("2"), // x
- new BigInteger("4018974056539037503335449422937059775635739389905545080690979365213431566280")), // y
- mod_q);
-
- ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
- new BigInteger("55441196065363246126355624130324183196576709222340016572108097750006097525544"), // d
- params);
-
- ParametersWithRandom param = new ParametersWithRandom(priKey, k);
-
- ECGOST3410Signer ecgost3410 = new ECGOST3410Signer();
-
- ecgost3410.init(true, param);
-
- byte[] mVal = new BigInteger("20798893674476452017134061561508270130637142515379653289952617252661468872421").toByteArray();
- byte[] message = new byte[mVal.length];
-
- for (int i = 0; i != mVal.length; i++)
- {
- message[i] = mVal[mVal.length - 1 - i];
- }
-
- BigInteger[] sig = ecgost3410.generateSignature(message);
-
- if (!r.equals(sig[0]))
- {
- fail("r component wrong.", r, sig[0]);
- }
-
- if (!s.equals(sig[1]))
- {
- fail("s component wrong.", s, sig[1]);
- }
-
- // Verify the signature
- ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
- curve.createPoint(
- new BigInteger("57520216126176808443631405023338071176630104906313632182896741342206604859403"), // x
- new BigInteger("17614944419213781543809391949654080031942662045363639260709847859438286763994")), // y
- params);
-
- ecgost3410.init(false, pubKey);
- if (!ecgost3410.verifySignature(message, sig[0], sig[1]))
- {
- fail("verification fails");
- }
- }
-
- /**
- * Test Sign & Verify with test parameters
- * see: http://www.ietf.org/internet-drafts/draft-popov-cryptopro-cpalgs-01.txt
- * gostR3410-2001-TestParamSet P.46
- */
- private void ecGOST3410_TestParam()
- {
- SecureRandom random = new SecureRandom();
-
- BigInteger mod_p = new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564821041"); //p
- BigInteger mod_q = new BigInteger("57896044618658097711785492504343953927082934583725450622380973592137631069619");
-
- ECCurve.Fp curve = new ECCurve.Fp(
- mod_p, // p
- new BigInteger("7"), // a
- new BigInteger("43308876546767276905765904595650931995942111794451039583252968842033849580414"), // b
- mod_q, ECConstants.ONE);
-
- ECDomainParameters params = new ECDomainParameters(
- curve,
- curve.createPoint(
- new BigInteger("2"), // x
- new BigInteger("4018974056539037503335449422937059775635739389905545080690979365213431566280")), // y
- mod_q);
-
- ECKeyPairGenerator pGen = new ECKeyPairGenerator();
- ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(
- params,
- random);
-
- pGen.init(genParam);
-
- AsymmetricCipherKeyPair pair = pGen.generateKeyPair();
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
-
- ECGOST3410Signer ecgost3410 = new ECGOST3410Signer();
-
- ecgost3410.init(true, param);
-
- //get hash message using the digest GOST3411.
- byte[] message = "Message for sign".getBytes();
- GOST3411Digest gost3411 = new GOST3411Digest();
- gost3411.update(message, 0, message.length);
- byte[] hashmessage = new byte[gost3411.getDigestSize()];
- gost3411.doFinal(hashmessage, 0);
-
- BigInteger[] sig = ecgost3410.generateSignature(hashmessage);
-
- ecgost3410.init(false, pair.getPublic());
-
- if (!ecgost3410.verifySignature(hashmessage, sig[0], sig[1]))
- {
- fail("signature fails");
- }
- }
-
- /**
- * Test Sign & Verify with A parameters
- * see: http://www.ietf.org/internet-drafts/draft-popov-cryptopro-cpalgs-01.txt
- * gostR3410-2001-CryptoPro-A-ParamSet P.47
- */
- public void ecGOST3410_AParam()
- {
- SecureRandom random = new SecureRandom();
-
- BigInteger mod_p = new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639319"); //p
- BigInteger mod_q = new BigInteger("115792089237316195423570985008687907853073762908499243225378155805079068850323");
-
- ECCurve.Fp curve = new ECCurve.Fp(
- mod_p, // p
- new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639316"), // a
- new BigInteger("166"), // b
- mod_q, ECConstants.ONE);
-
- ECDomainParameters params = new ECDomainParameters(
- curve,
- curve.createPoint(
- new BigInteger("1"), // x
- new BigInteger("64033881142927202683649881450433473985931760268884941288852745803908878638612")), // y
- mod_q);
-
- ECKeyPairGenerator pGen = new ECKeyPairGenerator();
- ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(
- params,
- random);
-
- pGen.init(genParam);
-
- AsymmetricCipherKeyPair pair = pGen.generateKeyPair();
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
-
- ECGOST3410Signer ecgost3410 = new ECGOST3410Signer();
-
- ecgost3410.init(true, param);
-
- BigInteger[] sig = ecgost3410.generateSignature(hashmessage);
-
- ecgost3410.init(false, pair.getPublic());
-
- if (!ecgost3410.verifySignature(hashmessage, sig[0], sig[1]))
- {
- fail("signature fails");
- }
- }
-
- /**
- * Test Sign & Verify with B parameters
- * see: http://www.ietf.org/internet-drafts/draft-popov-cryptopro-cpalgs-01.txt
- * gostR3410-2001-CryptoPro-B-ParamSet P.47-48
- */
- private void ecGOST3410_BParam()
- {
- SecureRandom random = new SecureRandom();
-
- BigInteger mod_p = new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564823193"); //p
- BigInteger mod_q = new BigInteger("57896044618658097711785492504343953927102133160255826820068844496087732066703");
-
- ECCurve.Fp curve = new ECCurve.Fp(
- mod_p, // p
- new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564823190"), // a
- new BigInteger("28091019353058090096996979000309560759124368558014865957655842872397301267595"), // b
- mod_q, ECConstants.ONE);
-
- ECDomainParameters params = new ECDomainParameters(
- curve,
- curve.createPoint(
- new BigInteger("1"), // x
- new BigInteger("28792665814854611296992347458380284135028636778229113005756334730996303888124")), // y
- mod_q);
-
- ECKeyPairGenerator pGen = new ECKeyPairGenerator();
- ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(
- params,
- random);
-
- pGen.init(genParam);
-
- AsymmetricCipherKeyPair pair = pGen.generateKeyPair();
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
-
- ECGOST3410Signer ecgost3410 = new ECGOST3410Signer();
-
- ecgost3410.init(true, param);
-
- BigInteger[] sig = ecgost3410.generateSignature(hashmessage);
-
- ecgost3410.init(false, pair.getPublic());
-
- if (!ecgost3410.verifySignature(hashmessage, sig[0], sig[1]))
- {
- fail("signature fails");
- }
- }
-
- /**
- * Test Sign & Verify with C parameters
- * see: http://www.ietf.org/internet-drafts/draft-popov-cryptopro-cpalgs-01.txt
- * gostR3410-2001-CryptoPro-C-ParamSet P.48
- */
- private void ecGOST3410_CParam()
- {
- SecureRandom random = new SecureRandom();
-
- BigInteger mod_p = new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502619"); //p
- BigInteger mod_q = new BigInteger("70390085352083305199547718019018437840920882647164081035322601458352298396601");
-
- ECCurve.Fp curve = new ECCurve.Fp(
- mod_p, // p
- new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502616"), // a
- new BigInteger("32858"), // b
- mod_q, ECConstants.ONE);
-
- ECDomainParameters params = new ECDomainParameters(
- curve,
- curve.createPoint(
- new BigInteger("0"), // x
- new BigInteger("29818893917731240733471273240314769927240550812383695689146495261604565990247")), // y
- mod_q);
-
- ECKeyPairGenerator pGen = new ECKeyPairGenerator();
- ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(
- params,
- random);
-
- pGen.init(genParam);
-
- AsymmetricCipherKeyPair pair = pGen.generateKeyPair();
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
-
- ECGOST3410Signer ecgost3410 = new ECGOST3410Signer();
-
- ecgost3410.init(true, param);
-
- BigInteger[] sig = ecgost3410.generateSignature(hashmessage);
-
- ecgost3410.init(false, pair.getPublic());
-
- if (!ecgost3410.verifySignature(hashmessage, sig[0], sig[1]))
- {
- fail("signature fails");
- }
- }
-
- public String getName()
- {
- return "ECGOST3410";
- }
-
- public void performTest()
- {
- ecGOST3410_TEST();
- ecGOST3410_TestParam();
- ecGOST3410_AParam();
- ecGOST3410_BParam();
- ecGOST3410_CParam();
- }
-
- public static void main(
- String[] args)
- {
- runTest(new ECGOST3410Test());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/ECIESKeyEncapsulationTest.java b/core/src/test/java/org/bouncycastle/crypto/test/ECIESKeyEncapsulationTest.java
deleted file mode 100755
index 64d19f50..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/ECIESKeyEncapsulationTest.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.asn1.sec.SECNamedCurves;
-import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
-import org.bouncycastle.crypto.generators.KDF2BytesGenerator;
-import org.bouncycastle.crypto.kems.ECIESKeyEncapsulation;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * Tests for the ECIES Key Encapsulation Mechanism
- */
-public class ECIESKeyEncapsulationTest
- extends SimpleTest
-{
- public String getName()
- {
- return "ECIESKeyEncapsulation";
- }
-
- public void performTest()
- throws Exception
- {
-
- // Set EC domain parameters and generate key pair
- X9ECParameters spec = SECNamedCurves.getByName("secp224r1");
- ECDomainParameters ecDomain = new ECDomainParameters(spec.getCurve(), spec.getG(), spec.getN());
- ECKeyPairGenerator ecGen = new ECKeyPairGenerator();
-
- ecGen.init(new ECKeyGenerationParameters(ecDomain, new SecureRandom()));
-
- AsymmetricCipherKeyPair keys = ecGen.generateKeyPair();
-
- // Set ECIES-KEM parameters
- ECIESKeyEncapsulation kem;
- KDF2BytesGenerator kdf = new KDF2BytesGenerator(new SHA1Digest());
- SecureRandom rnd = new SecureRandom();
- byte[] out = new byte[57];
- KeyParameter key1, key2;
-
- // Test basic ECIES-KEM
- kem = new ECIESKeyEncapsulation(kdf, rnd);
-
- kem.init(keys.getPublic());
- key1 = (KeyParameter)kem.encrypt(out, 128);
-
- kem.init(keys.getPrivate());
- key2 = (KeyParameter)kem.decrypt(out, 128);
-
- if (!areEqual(key1.getKey(), key2.getKey()))
- {
- fail("failed basic test");
- }
-
- // Test ECIES-KEM using new cofactor mode
- kem = new ECIESKeyEncapsulation(kdf, rnd, true, false, false);
-
- kem.init(keys.getPublic());
- key1 = (KeyParameter)kem.encrypt(out, 128);
-
- kem.init(keys.getPrivate());
- key2 = (KeyParameter)kem.decrypt(out, 128);
-
- if (!areEqual(key1.getKey(), key2.getKey()))
- {
- fail("failed cofactor test");
- }
-
- // Test ECIES-KEM using old cofactor mode
- kem = new ECIESKeyEncapsulation(kdf, rnd, false, true, false);
-
- kem.init(keys.getPublic());
- key1 = (KeyParameter)kem.encrypt(out, 128);
-
- kem.init(keys.getPrivate());
- key2 = (KeyParameter)kem.decrypt(out, 128);
-
- if (!areEqual(key1.getKey(), key2.getKey()))
- {
- fail("failed old cofactor test");
- }
-
- // Test ECIES-KEM using single hash mode
- kem = new ECIESKeyEncapsulation(kdf, rnd, false, false, true);
-
- kem.init(keys.getPublic());
- key1 = (KeyParameter)kem.encrypt(out, 128);
-
- kem.init(keys.getPrivate());
- key2 = (KeyParameter)kem.decrypt(out, 128);
-
- if (!areEqual(key1.getKey(), key2.getKey()))
- {
- fail("failed single hash test");
- }
-
- // Test ECIES-KEM using new cofactor mode and single hash mode
- kem = new ECIESKeyEncapsulation(kdf, rnd, true, false, true);
-
- kem.init(keys.getPublic());
- key1 = (KeyParameter)kem.encrypt(out, 128);
-
- kem.init(keys.getPrivate());
- key2 = (KeyParameter)kem.decrypt(out, 128);
-
- if (!areEqual(key1.getKey(), key2.getKey()))
- {
- fail("failed cofactor and single hash test");
- }
-
- // Test ECIES-KEM using old cofactor mode and single hash mode
- kem = new ECIESKeyEncapsulation(kdf, rnd, false, true, true);
-
- kem.init(keys.getPublic());
- key1 = (KeyParameter)kem.encrypt(out, 128);
-
- kem.init(keys.getPrivate());
- key2 = (KeyParameter)kem.decrypt(out, 128);
-
- if (!areEqual(key1.getKey(), key2.getKey()))
- {
- fail("failed old cofactor and single hash test");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new ECIESKeyEncapsulationTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/ECIESTest.java b/core/src/test/java/org/bouncycastle/crypto/test/ECIESTest.java
deleted file mode 100644
index 737cd860..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/ECIESTest.java
+++ /dev/null
@@ -1,377 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.BufferedBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.KeyEncoder;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.agreement.ECDHBasicAgreement;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.engines.IESEngine;
-import org.bouncycastle.crypto.engines.TwofishEngine;
-import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
-import org.bouncycastle.crypto.generators.EphemeralKeyPairGenerator;
-import org.bouncycastle.crypto.generators.KDF2BytesGenerator;
-import org.bouncycastle.crypto.macs.HMac;
-import org.bouncycastle.crypto.modes.CBCBlockCipher;
-import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.params.IESParameters;
-import org.bouncycastle.crypto.params.IESWithCipherParameters;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.crypto.parsers.ECIESPublicKeyParser;
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * test for ECIES - Elliptic Curve Integrated Encryption Scheme
- */
-public class ECIESTest
- extends SimpleTest
-{
- private static byte[] TWOFISH_IV = Hex.decode("000102030405060708090a0b0c0d0e0f");
-
- ECIESTest()
- {
- }
-
- public String getName()
- {
- return "ECIES";
- }
-
- private void doStaticTest(byte[] iv)
- throws Exception
- {
- BigInteger n = new BigInteger("6277101735386680763835789423176059013767194773182842284081");
-
- ECCurve.Fp curve = new ECCurve.Fp(
- new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q
- new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a
- new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16), // b
- n, ECConstants.ONE);
-
- ECDomainParameters params = new ECDomainParameters(
- curve,
- curve.decodePoint(Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), // G
- n);
-
- ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
- new BigInteger("651056770906015076056810763456358567190100156695615665659"), // d
- params);
-
- ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
- curve.decodePoint(Hex.decode("0262b12d60690cdcf330babab6e69763b471f994dd702d16a5")), // Q
- params);
-
- AsymmetricCipherKeyPair p1 = new AsymmetricCipherKeyPair(pubKey, priKey);
- AsymmetricCipherKeyPair p2 = new AsymmetricCipherKeyPair(pubKey, priKey);
-
- //
- // stream test
- //
- IESEngine i1 = new IESEngine(
- new ECDHBasicAgreement(),
- new KDF2BytesGenerator(new SHA1Digest()),
- new HMac(new SHA1Digest()));
- IESEngine i2 = new IESEngine(
- new ECDHBasicAgreement(),
- new KDF2BytesGenerator(new SHA1Digest()),
- new HMac(new SHA1Digest()));
- byte[] d = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
- byte[] e = new byte[] { 8, 7, 6, 5, 4, 3, 2, 1 };
- CipherParameters p = new IESParameters(d, e, 64);
-
- i1.init(true, p1.getPrivate(), p2.getPublic(), p);
- i2.init(false, p2.getPrivate(), p1.getPublic(), p);
-
- byte[] message = Hex.decode("1234567890abcdef");
-
- byte[] out1 = i1.processBlock(message, 0, message.length);
-
- if (!areEqual(out1, Hex.decode("468d89877e8238802403ec4cb6b329faeccfa6f3a730f2cdb3c0a8e8")))
- {
- fail("stream cipher test failed on enc");
- }
-
- byte[] out2 = i2.processBlock(out1, 0, out1.length);
-
- if (!areEqual(out2, message))
- {
- fail("stream cipher test failed");
- }
-
- //
- // twofish with CBC
- //
- BufferedBlockCipher c1 = new PaddedBufferedBlockCipher(
- new CBCBlockCipher(new TwofishEngine()));
- BufferedBlockCipher c2 = new PaddedBufferedBlockCipher(
- new CBCBlockCipher(new TwofishEngine()));
- i1 = new IESEngine(
- new ECDHBasicAgreement(),
- new KDF2BytesGenerator(new SHA1Digest()),
- new HMac(new SHA1Digest()),
- c1);
- i2 = new IESEngine(
- new ECDHBasicAgreement(),
- new KDF2BytesGenerator(new SHA1Digest()),
- new HMac(new SHA1Digest()),
- c2);
- d = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
- e = new byte[] { 8, 7, 6, 5, 4, 3, 2, 1 };
- p = new IESWithCipherParameters(d, e, 64, 128);
-
- if (iv != null)
- {
- p = new ParametersWithIV(p, iv);
- }
-
- i1.init(true, p1.getPrivate(), p2.getPublic(), p);
- i2.init(false, p2.getPrivate(), p1.getPublic(), p);
-
- message = Hex.decode("1234567890abcdef");
-
- out1 = i1.processBlock(message, 0, message.length);
-
- if (!areEqual(out1, (iv == null) ?
- Hex.decode("b8a06ea5c2b9df28b58a0a90a734cde8c9c02903e5c220021fe4417410d1e53a32a71696")
- : Hex.decode("f246b0e26a2711992cac9c590d08e45c5e730b7c0f4218bb064e27b7dd7c8a3bd8bf01c3")))
- {
- fail("twofish cipher test failed on enc");
- }
-
- out2 = i2.processBlock(out1, 0, out1.length);
-
- if (!areEqual(out2, message))
- {
- fail("twofish cipher test failed");
- }
- }
-
- private void doEphemeralTest(byte[] iv)
- throws Exception
- {
- BigInteger n = new BigInteger("6277101735386680763835789423176059013767194773182842284081");
-
- ECCurve.Fp curve = new ECCurve.Fp(
- new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q
- new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a
- new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16), // b
- n, ECConstants.ONE);
-
- ECDomainParameters params = new ECDomainParameters(
- curve,
- curve.decodePoint(Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), // G
- n);
-
- ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
- new BigInteger("651056770906015076056810763456358567190100156695615665659"), // d
- params);
-
- ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
- curve.decodePoint(Hex.decode("0262b12d60690cdcf330babab6e69763b471f994dd702d16a5")), // Q
- params);
-
- AsymmetricCipherKeyPair p1 = new AsymmetricCipherKeyPair(pubKey, priKey);
- AsymmetricCipherKeyPair p2 = new AsymmetricCipherKeyPair(pubKey, priKey);
-
- // Generate the ephemeral key pair
- ECKeyPairGenerator gen = new ECKeyPairGenerator();
- gen.init(new ECKeyGenerationParameters(params, new SecureRandom()));
-
- EphemeralKeyPairGenerator ephKeyGen = new EphemeralKeyPairGenerator(gen, new KeyEncoder()
- {
- public byte[] getEncoded(AsymmetricKeyParameter keyParameter)
- {
- return ((ECPublicKeyParameters)keyParameter).getQ().getEncoded();
- }
- });
-
- //
- // stream test
- //
- IESEngine i1 = new IESEngine(
- new ECDHBasicAgreement(),
- new KDF2BytesGenerator(new SHA1Digest()),
- new HMac(new SHA1Digest()));
- IESEngine i2 = new IESEngine(
- new ECDHBasicAgreement(),
- new KDF2BytesGenerator(new SHA1Digest()),
- new HMac(new SHA1Digest()));
-
- byte[] d = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
- byte[] e = new byte[] { 8, 7, 6, 5, 4, 3, 2, 1 };
- CipherParameters p = new IESParameters(d, e, 64);
-
- i1.init(p2.getPublic(), p, ephKeyGen);
- i2.init(p2.getPrivate(), p, new ECIESPublicKeyParser(params));
-
- byte[] message = Hex.decode("1234567890abcdef");
-
- byte[] out1 = i1.processBlock(message, 0, message.length);
-
- byte[] out2 = i2.processBlock(out1, 0, out1.length);
-
- if (!areEqual(out2, message))
- {
- fail("stream cipher test failed");
- }
-
- //
- // twofish with CBC
- //
- BufferedBlockCipher c1 = new PaddedBufferedBlockCipher(
- new CBCBlockCipher(new TwofishEngine()));
- BufferedBlockCipher c2 = new PaddedBufferedBlockCipher(
- new CBCBlockCipher(new TwofishEngine()));
- i1 = new IESEngine(
- new ECDHBasicAgreement(),
- new KDF2BytesGenerator(new SHA1Digest()),
- new HMac(new SHA1Digest()),
- c1);
- i2 = new IESEngine(
- new ECDHBasicAgreement(),
- new KDF2BytesGenerator(new SHA1Digest()),
- new HMac(new SHA1Digest()),
- c2);
- d = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
- e = new byte[] { 8, 7, 6, 5, 4, 3, 2, 1 };
- p = new IESWithCipherParameters(d, e, 64, 128);
-
- if (iv != null)
- {
- p = new ParametersWithIV(p, iv);
- }
-
- i1.init(p2.getPublic(), p, ephKeyGen);
- i2.init(p2.getPrivate(), p, new ECIESPublicKeyParser(params));
-
- message = Hex.decode("1234567890abcdef");
-
- out1 = i1.processBlock(message, 0, message.length);
-
- out2 = i2.processBlock(out1, 0, out1.length);
-
- if (!areEqual(out2, message))
- {
- fail("twofish cipher test failed");
- }
- }
-
- private void doTest(AsymmetricCipherKeyPair p1, AsymmetricCipherKeyPair p2)
- throws Exception
- {
- //
- // stream test
- //
- IESEngine i1 = new IESEngine(
- new ECDHBasicAgreement(),
- new KDF2BytesGenerator(new SHA1Digest()),
- new HMac(new SHA1Digest()));
- IESEngine i2 = new IESEngine(
- new ECDHBasicAgreement(),
- new KDF2BytesGenerator(new SHA1Digest()),
- new HMac(new SHA1Digest()));
- byte[] d = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
- byte[] e = new byte[] { 8, 7, 6, 5, 4, 3, 2, 1 };
- IESParameters p = new IESParameters(d, e, 64);
-
- i1.init(true, p1.getPrivate(), p2.getPublic(), p);
- i2.init(false, p2.getPrivate(), p1.getPublic(), p);
-
- byte[] message = Hex.decode("1234567890abcdef");
-
- byte[] out1 = i1.processBlock(message, 0, message.length);
-
- byte[] out2 = i2.processBlock(out1, 0, out1.length);
-
- if (!areEqual(out2, message))
- {
- fail("stream cipher test failed");
- }
-
- //
- // twofish with CBC
- //
- BufferedBlockCipher c1 = new PaddedBufferedBlockCipher(
- new CBCBlockCipher(new TwofishEngine()));
- BufferedBlockCipher c2 = new PaddedBufferedBlockCipher(
- new CBCBlockCipher(new TwofishEngine()));
- i1 = new IESEngine(
- new ECDHBasicAgreement(),
- new KDF2BytesGenerator(new SHA1Digest()),
- new HMac(new SHA1Digest()),
- c1);
- i2 = new IESEngine(
- new ECDHBasicAgreement(),
- new KDF2BytesGenerator(new SHA1Digest()),
- new HMac(new SHA1Digest()),
- c2);
- d = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
- e = new byte[] { 8, 7, 6, 5, 4, 3, 2, 1 };
- p = new IESWithCipherParameters(d, e, 64, 128);
-
- i1.init(true, p1.getPrivate(), p2.getPublic(), p);
- i2.init(false, p2.getPrivate(), p1.getPublic(), p);
-
- message = Hex.decode("1234567890abcdef");
-
- out1 = i1.processBlock(message, 0, message.length);
-
- out2 = i2.processBlock(out1, 0, out1.length);
-
- if (!areEqual(out2, message))
- {
- fail("twofish cipher test failed");
- }
- }
-
- public void performTest()
- throws Exception
- {
- doStaticTest(null);
- doStaticTest(TWOFISH_IV);
-
- BigInteger n = new BigInteger("6277101735386680763835789423176059013767194773182842284081");
-
- ECCurve.Fp curve = new ECCurve.Fp(
- new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q
- new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a
- new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16), // b
- n, ECConstants.ONE);
-
- ECDomainParameters params = new ECDomainParameters(
- curve,
- curve.decodePoint(Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), // G
- n);
-
- ECKeyPairGenerator eGen = new ECKeyPairGenerator();
- KeyGenerationParameters gParam = new ECKeyGenerationParameters(params, new SecureRandom());
-
- eGen.init(gParam);
-
- AsymmetricCipherKeyPair p1 = eGen.generateKeyPair();
- AsymmetricCipherKeyPair p2 = eGen.generateKeyPair();
-
- doTest(p1, p2);
-
- doEphemeralTest(null);
- doEphemeralTest(TWOFISH_IV);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new ECIESTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/ECNRTest.java b/core/src/test/java/org/bouncycastle/crypto/test/ECNRTest.java
deleted file mode 100644
index d4cf7419..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/ECNRTest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.signers.ECNRSigner;
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.util.BigIntegers;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.FixedSecureRandom;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * ECNR tests.
- */
-public class ECNRTest
- extends SimpleTest
-{
- /**
- * a basic regression test with 239 bit prime
- */
- BigInteger r = new BigInteger("308636143175167811492623515537541734843573549327605293463169625072911693");
- BigInteger s = new BigInteger("852401710738814635664888632022555967400445256405412579597015412971797143");
-
- byte[] kData = BigIntegers.asUnsignedByteArray(new BigInteger("700000017569056646655505781757157107570501575775705779575555657156756655"));
-
- SecureRandom k = new FixedSecureRandom(true, kData);
-
- private void ecNR239bitPrime()
- {
- BigInteger n = new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307");
-
- ECCurve.Fp curve = new ECCurve.Fp(
- new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
- new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
- new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16), // b
- n, ECConstants.ONE);
-
- ECDomainParameters params = new ECDomainParameters(
- curve,
- curve.decodePoint(Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
- n);
-
- ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
- new BigInteger("876300101507107567501066130761671078357010671067781776716671676178726717"), // d
- params);
-
- ECNRSigner ecnr = new ECNRSigner();
- ParametersWithRandom param = new ParametersWithRandom(priKey, k);
-
- ecnr.init(true, param);
-
- byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").toByteArray();
- BigInteger[] sig = ecnr.generateSignature(message);
-
- if (!r.equals(sig[0]))
- {
- fail("r component wrong.", r, sig[0]);
- }
-
- if (!s.equals(sig[1]))
- {
- fail("s component wrong.", s, sig[1]);
- }
-
- // Verify the signature
- ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
- curve.decodePoint(Hex.decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q
- params);
-
- ecnr.init(false, pubKey);
- if (!ecnr.verifySignature(message, sig[0], sig[1]))
- {
- fail("signature fails");
- }
- }
-
- public String getName()
- {
- return "ECNR";
- }
-
- public void performTest()
- {
- ecNR239bitPrime();
- }
-
- public static void main(
- String[] args)
- {
- runTest(new ECNRTest());
- }
-}
-
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/ECTest.java b/core/src/test/java/org/bouncycastle/crypto/test/ECTest.java
deleted file mode 100644
index fc11276a..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/ECTest.java
+++ /dev/null
@@ -1,926 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.asn1.nist.NISTNamedCurves;
-import org.bouncycastle.asn1.sec.SECNamedCurves;
-import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.BasicAgreement;
-import org.bouncycastle.crypto.agreement.ECDHBasicAgreement;
-import org.bouncycastle.crypto.agreement.ECDHCBasicAgreement;
-import org.bouncycastle.crypto.agreement.ECMQVBasicAgreement;
-import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.params.MQVPrivateParameters;
-import org.bouncycastle.crypto.params.MQVPublicParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.signers.ECDSASigner;
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.util.BigIntegers;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.FixedSecureRandom;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * ECDSA tests are taken from X9.62.
- */
-public class ECTest
- extends SimpleTest
-{
- /**
- * X9.62 - 1998,<br>
- * J.3.1, Page 152, ECDSA over the field Fp<br>
- * an example with 192 bit prime
- */
- private void testECDSA192bitPrime()
- {
- BigInteger r = new BigInteger("3342403536405981729393488334694600415596881826869351677613");
- BigInteger s = new BigInteger("5735822328888155254683894997897571951568553642892029982342");
-
- byte[] kData = BigIntegers.asUnsignedByteArray(new BigInteger("6140507067065001063065065565667405560006161556565665656654"));
-
- SecureRandom k = new FixedSecureRandom(kData);
-
- BigInteger n = new BigInteger("6277101735386680763835789423176059013767194773182842284081");
-
- ECCurve.Fp curve = new ECCurve.Fp(
- new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q
- new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a
- new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16), // b
- n, ECConstants.ONE);
-
- ECDomainParameters params = new ECDomainParameters(
- curve,
- curve.decodePoint(Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), // G
- n);
-
- ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
- new BigInteger("651056770906015076056810763456358567190100156695615665659"), // d
- params);
-
- ParametersWithRandom param = new ParametersWithRandom(priKey, k);
-
- ECDSASigner ecdsa = new ECDSASigner();
-
- ecdsa.init(true, param);
-
- byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").toByteArray();
- BigInteger[] sig = ecdsa.generateSignature(message);
-
- if (!r.equals(sig[0]))
- {
- fail("r component wrong." + System.getProperty("line.separator")
- + " expecting: " + r + System.getProperty("line.separator")
- + " got : " + sig[0]);
- }
-
- if (!s.equals(sig[1]))
- {
- fail("s component wrong." + System.getProperty("line.separator")
- + " expecting: " + s + System.getProperty("line.separator")
- + " got : " + sig[1]);
- }
-
- // Verify the signature
- ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
- curve.decodePoint(Hex.decode("0262b12d60690cdcf330babab6e69763b471f994dd702d16a5")), // Q
- params);
-
- ecdsa.init(false, pubKey);
- if (!ecdsa.verifySignature(message, sig[0], sig[1]))
- {
- fail("verification fails");
- }
- }
-
- private void decodeTest()
- {
- ECCurve.Fp curve = new ECCurve.Fp(
- new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q
- new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a
- new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16)); // b
-
- ECPoint p = curve.decodePoint(Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")).normalize();
-
- if (!p.getAffineXCoord().toBigInteger().equals(new BigInteger("188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 16)))
- {
- fail("x uncompressed incorrectly");
- }
-
- if (!p.getAffineYCoord().toBigInteger().equals(new BigInteger("7192b95ffc8da78631011ed6b24cdd573f977a11e794811", 16)))
- {
- fail("y uncompressed incorrectly");
- }
-
- byte[] encoding = p.getEncoded();
-
- if (!areEqual(encoding, Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")))
- {
- fail("point compressed incorrectly");
- }
- }
-
- /**
- * X9.62 - 1998,<br>
- * J.3.2, Page 155, ECDSA over the field Fp<br>
- * an example with 239 bit prime
- */
- private void testECDSA239bitPrime()
- {
- BigInteger r = new BigInteger("308636143175167811492622547300668018854959378758531778147462058306432176");
- BigInteger s = new BigInteger("323813553209797357708078776831250505931891051755007842781978505179448783");
-
- byte[] kData = BigIntegers.asUnsignedByteArray(new BigInteger("700000017569056646655505781757157107570501575775705779575555657156756655"));
-
- SecureRandom k = new FixedSecureRandom(true, kData);
-
- BigInteger n = new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307");
-
- ECCurve.Fp curve = new ECCurve.Fp(
- new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
- new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
- new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16), // b
- n, ECConstants.ONE);
-
- ECDomainParameters params = new ECDomainParameters(
- curve,
- curve.decodePoint(Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
- n);
-
- ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
- new BigInteger("876300101507107567501066130761671078357010671067781776716671676178726717"), // d
- params);
-
- ECDSASigner ecdsa = new ECDSASigner();
- ParametersWithRandom param = new ParametersWithRandom(priKey, k);
-
- ecdsa.init(true, param);
-
- byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").toByteArray();
- BigInteger[] sig = ecdsa.generateSignature(message);
-
- if (!r.equals(sig[0]))
- {
- fail("r component wrong." + System.getProperty("line.separator")
- + " expecting: " + r + System.getProperty("line.separator")
- + " got : " + sig[0]);
- }
-
- if (!s.equals(sig[1]))
- {
- fail("s component wrong." + System.getProperty("line.separator")
- + " expecting: " + s + System.getProperty("line.separator")
- + " got : " + sig[1]);
- }
-
- // Verify the signature
- ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
- curve.decodePoint(Hex.decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q
- params);
-
- ecdsa.init(false, pubKey);
- if (!ecdsa.verifySignature(message, sig[0], sig[1]))
- {
- fail("signature fails");
- }
- }
-
-
- /**
- * X9.62 - 1998,<br>
- * J.2.1, Page 100, ECDSA over the field F2m<br>
- * an example with 191 bit binary field
- */
- private void testECDSA191bitBinary()
- {
- BigInteger r = new BigInteger("87194383164871543355722284926904419997237591535066528048");
- BigInteger s = new BigInteger("308992691965804947361541664549085895292153777025772063598");
-
- byte[] kData = BigIntegers.asUnsignedByteArray(new BigInteger("1542725565216523985789236956265265265235675811949404040041"));
-
- SecureRandom k = new FixedSecureRandom(kData);
-
- BigInteger n = new BigInteger("1569275433846670190958947355803350458831205595451630533029");
- BigInteger h = BigInteger.valueOf(2);
-
- ECCurve.F2m curve = new ECCurve.F2m(
- 191, // m
- 9, //k
- new BigInteger("2866537B676752636A68F56554E12640276B649EF7526267", 16), // a
- new BigInteger("2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC", 16), // b
- n, h);
-
- ECDomainParameters params = new ECDomainParameters(
- curve,
- curve.decodePoint(Hex.decode("0436B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D765BE73433B3F95E332932E70EA245CA2418EA0EF98018FB")), // G
- n, h);
-
- ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
- new BigInteger("1275552191113212300012030439187146164646146646466749494799"), // d
- params);
-
- ECDSASigner ecdsa = new ECDSASigner();
- ParametersWithRandom param = new ParametersWithRandom(priKey, k);
-
- ecdsa.init(true, param);
-
- byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").toByteArray();
- BigInteger[] sig = ecdsa.generateSignature(message);
-
- if (!r.equals(sig[0]))
- {
- fail("r component wrong." + System.getProperty("line.separator")
- + " expecting: " + r + System.getProperty("line.separator")
- + " got : " + sig[0]);
- }
-
- if (!s.equals(sig[1]))
- {
- fail("s component wrong." + System.getProperty("line.separator")
- + " expecting: " + s + System.getProperty("line.separator")
- + " got : " + sig[1]);
- }
-
- // Verify the signature
- ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
- curve.decodePoint(Hex.decode("045DE37E756BD55D72E3768CB396FFEB962614DEA4CE28A2E755C0E0E02F5FB132CAF416EF85B229BBB8E1352003125BA1")), // Q
- params);
-
- ecdsa.init(false, pubKey);
- if (!ecdsa.verifySignature(message, sig[0], sig[1]))
- {
- fail("signature fails");
- }
- }
-
-
- /**
- * X9.62 - 1998,<br>
- * J.2.1, Page 100, ECDSA over the field F2m<br>
- * an example with 191 bit binary field
- */
- private void testECDSA239bitBinary()
- {
- BigInteger r = new BigInteger("21596333210419611985018340039034612628818151486841789642455876922391552");
- BigInteger s = new BigInteger("197030374000731686738334997654997227052849804072198819102649413465737174");
-
- byte[] kData = BigIntegers.asUnsignedByteArray(new BigInteger("171278725565216523967285789236956265265265235675811949404040041670216363"));
-
- SecureRandom k = new FixedSecureRandom(kData);
-
- BigInteger n = new BigInteger("220855883097298041197912187592864814557886993776713230936715041207411783");
- BigInteger h = BigInteger.valueOf(4);
-
- ECCurve.F2m curve = new ECCurve.F2m(
- 239, // m
- 36, //k
- new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), // a
- new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16), // b
- n, h);
-
- ECDomainParameters params = new ECDomainParameters(
- curve,
- curve.decodePoint(Hex.decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G
- n, h);
-
- ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
- new BigInteger("145642755521911534651321230007534120304391871461646461466464667494947990"), // d
- params);
-
- ECDSASigner ecdsa = new ECDSASigner();
- ParametersWithRandom param = new ParametersWithRandom(priKey, k);
-
- ecdsa.init(true, param);
-
- byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").toByteArray();
- BigInteger[] sig = ecdsa.generateSignature(message);
-
- if (!r.equals(sig[0]))
- {
- fail("r component wrong." + System.getProperty("line.separator")
- + " expecting: " + r + System.getProperty("line.separator")
- + " got : " + sig[0]);
- }
-
- if (!s.equals(sig[1]))
- {
- fail("s component wrong." + System.getProperty("line.separator")
- + " expecting: " + s + System.getProperty("line.separator")
- + " got : " + sig[1]);
- }
-
- // Verify the signature
- ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
- curve.decodePoint(Hex.decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q
- params);
-
- ecdsa.init(false, pubKey);
- if (!ecdsa.verifySignature(message, sig[0], sig[1]))
- {
- fail("signature fails");
- }
- }
-
- // L 4.1 X9.62 2005
- private void testECDSAP224sha224()
- {
- X9ECParameters p = NISTNamedCurves.getByName("P-224");
- ECDomainParameters params = new ECDomainParameters(p.getCurve(), p.getG(), p.getN(), p.getH());
- ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
- new BigInteger("6081831502424510080126737029209236539191290354021104541805484120491"), // d
- params);
- SecureRandom k = new FixedSecureRandom(BigIntegers.asUnsignedByteArray(new BigInteger("15456715103636396133226117016818339719732885723579037388121116732601")));
-
- byte[] M = Hex.decode("8797A3C693CC292441039A4E6BAB7387F3B4F2A63D00ED384B378C79");
-
- ECDSASigner dsa = new ECDSASigner();
-
- dsa.init(true, new ParametersWithRandom(priKey, k));
-
- BigInteger[] sig = dsa.generateSignature(M);
-
- BigInteger r = new BigInteger("26477406756127720855365980332052585411804331993436302005017227573742");
- BigInteger s = new BigInteger("17694958233103667059888193972742186995283044672015112738919822429978");
-
- if (!r.equals(sig[0]))
- {
- fail("r component wrong." + System.getProperty("line.separator")
- + " expecting: " + r + System.getProperty("line.separator")
- + " got : " + sig[0]);
- }
-
- if (!s.equals(sig[1]))
- {
- fail("s component wrong." + System.getProperty("line.separator")
- + " expecting: " + s + System.getProperty("line.separator")
- + " got : " + sig[1]);
- }
-
- // Verify the signature
- ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
- params.getCurve().decodePoint(Hex.decode("03FD44EC11F9D43D9D23B1E1D1C9ED6519B40ECF0C79F48CF476CC43F1")), // Q
- params);
-
- dsa.init(false, pubKey);
- if (!dsa.verifySignature(M, sig[0], sig[1]))
- {
- fail("signature fails");
- }
- }
-
- private void testECDSASecP224k1sha256()
- {
- X9ECParameters p = SECNamedCurves.getByName("secp224k1");
- ECDomainParameters params = new ECDomainParameters(p.getCurve(), p.getG(), p.getN(), p.getH());
- ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
- new BigInteger("BE6F6E91FE96840A6518B56F3FE21689903A64FA729057AB872A9F51", 16), // d
- params);
- SecureRandom k = new FixedSecureRandom(Hex.decode("00c39beac93db21c3266084429eb9b846b787c094f23a4de66447efbb3"));
-
- byte[] M = Hex.decode("E5D5A7ADF73C5476FAEE93A2C76CE94DC0557DB04CDC189504779117920B896D");
-
- ECDSASigner dsa = new ECDSASigner();
-
- dsa.init(true, new ParametersWithRandom(priKey, k));
-
- BigInteger[] sig = dsa.generateSignature(M);
-
- BigInteger r = new BigInteger("8163E5941BED41DA441B33E653C632A55A110893133351E20CE7CB75", 16);
- BigInteger s = new BigInteger("D12C3FC289DDD5F6890DCE26B65792C8C50E68BF551D617D47DF15A8", 16);
-
- if (!r.equals(sig[0]))
- {
- fail("r component wrong." + System.getProperty("line.separator")
- + " expecting: " + r + System.getProperty("line.separator")
- + " got : " + sig[0]);
- }
-
- if (!s.equals(sig[1]))
- {
- fail("s component wrong." + System.getProperty("line.separator")
- + " expecting: " + s + System.getProperty("line.separator")
- + " got : " + sig[1]);
- }
-
- // Verify the signature
- ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
- params.getCurve().decodePoint(Hex.decode("04C5C9B38D3603FCCD6994CBB9594E152B658721E483669BB42728520F484B537647EC816E58A8284D3B89DFEDB173AFDC214ECA95A836FA7C")), // Q
- params);
-
- dsa.init(false, pubKey);
- if (!dsa.verifySignature(M, sig[0], sig[1]))
- {
- fail("signature fails");
- }
- }
-
- // L4.2 X9.62 2005
- private void testECDSAP256sha256()
- {
- X9ECParameters p = NISTNamedCurves.getByName("P-256");
- ECDomainParameters params = new ECDomainParameters(p.getCurve(), p.getG(), p.getN(), p.getH());
- ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
- new BigInteger("20186677036482506117540275567393538695075300175221296989956723148347484984008"), // d
- params);
- SecureRandom k = new FixedSecureRandom(BigIntegers.asUnsignedByteArray(new BigInteger("72546832179840998877302529996971396893172522460793442785601695562409154906335")));
-
- byte[] M = Hex.decode("1BD4ED430B0F384B4E8D458EFF1A8A553286D7AC21CB2F6806172EF5F94A06AD");
-
- ECDSASigner dsa = new ECDSASigner();
-
- dsa.init(true, new ParametersWithRandom(priKey, k));
-
- BigInteger[] sig = dsa.generateSignature(M);
-
- BigInteger r = new BigInteger("97354732615802252173078420023658453040116611318111190383344590814578738210384");
- BigInteger s = new BigInteger("98506158880355671805367324764306888225238061309262649376965428126566081727535");
-
- if (!r.equals(sig[0]))
- {
- fail("r component wrong." + System.getProperty("line.separator")
- + " expecting: " + r + System.getProperty("line.separator")
- + " got : " + sig[0]);
- }
-
- if (!s.equals(sig[1]))
- {
- fail("s component wrong." + System.getProperty("line.separator")
- + " expecting: " + s + System.getProperty("line.separator")
- + " got : " + sig[1]);
- }
-
- // Verify the signature
- ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
- params.getCurve().decodePoint(Hex.decode("03596375E6CE57E0F20294FC46BDFCFD19A39F8161B58695B3EC5B3D16427C274D")), // Q
- params);
-
- dsa.init(false, pubKey);
- if (!dsa.verifySignature(M, sig[0], sig[1]))
- {
- fail("signature fails");
- }
- }
-
- private void testECDSAP224OneByteOver()
- {
- X9ECParameters p = NISTNamedCurves.getByName("P-224");
- ECDomainParameters params = new ECDomainParameters(p.getCurve(), p.getG(), p.getN(), p.getH());
- ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
- new BigInteger("6081831502424510080126737029209236539191290354021104541805484120491"), // d
- params);
- SecureRandom k = new FixedSecureRandom(BigIntegers.asUnsignedByteArray(new BigInteger("15456715103636396133226117016818339719732885723579037388121116732601")));
-
- byte[] M = Hex.decode("8797A3C693CC292441039A4E6BAB7387F3B4F2A63D00ED384B378C79FF");
-
- ECDSASigner dsa = new ECDSASigner();
-
- dsa.init(true, new ParametersWithRandom(priKey, k));
-
- BigInteger[] sig = dsa.generateSignature(M);
-
- BigInteger r = new BigInteger("26477406756127720855365980332052585411804331993436302005017227573742");
- BigInteger s = new BigInteger("17694958233103667059888193972742186995283044672015112738919822429978");
-
- if (!r.equals(sig[0]))
- {
- fail("r component wrong." + System.getProperty("line.separator")
- + " expecting: " + r + System.getProperty("line.separator")
- + " got : " + sig[0]);
- }
-
- if (!s.equals(sig[1]))
- {
- fail("s component wrong." + System.getProperty("line.separator")
- + " expecting: " + s + System.getProperty("line.separator")
- + " got : " + sig[1]);
- }
-
- // Verify the signature
- ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
- params.getCurve().decodePoint(Hex.decode("03FD44EC11F9D43D9D23B1E1D1C9ED6519B40ECF0C79F48CF476CC43F1")), // Q
- params);
-
- dsa.init(false, pubKey);
- if (!dsa.verifySignature(M, sig[0], sig[1]))
- {
- fail("signature fails");
- }
- }
-
- // L4.3 X9.62 2005
- private void testECDSAP521sha512()
- {
- X9ECParameters p = NISTNamedCurves.getByName("P-521");
- ECDomainParameters params = new ECDomainParameters(p.getCurve(), p.getG(), p.getN(), p.getH());
- ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
- new BigInteger("617573726813476282316253885608633222275541026607493641741273231656161177732180358888434629562647985511298272498852936680947729040673640492310550142822667389"), // d
- params);
- SecureRandom k = new FixedSecureRandom(BigIntegers.asUnsignedByteArray(new BigInteger("6806532878215503520845109818432174847616958675335397773700324097584974639728725689481598054743894544060040710846048585856076812050552869216017728862957612913")));
-
- byte[] M = Hex.decode("6893B64BD3A9615C39C3E62DDD269C2BAAF1D85915526083183CE14C2E883B48B193607C1ED871852C9DF9C3147B574DC1526C55DE1FE263A676346A20028A66");
-
- ECDSASigner dsa = new ECDSASigner();
-
- dsa.init(true, new ParametersWithRandom(priKey, k));
-
- BigInteger[] sig = dsa.generateSignature(M);
-
- BigInteger r = new BigInteger("1368926195812127407956140744722257403535864168182534321188553460365652865686040549247096155740756318290773648848859639978618869784291633651685766829574104630");
- BigInteger s = new BigInteger("1624754720348883715608122151214003032398685415003935734485445999065609979304811509538477657407457976246218976767156629169821116579317401249024208611945405790");
-
- if (!r.equals(sig[0]))
- {
- fail("r component wrong." + System.getProperty("line.separator")
- + " expecting: " + r + System.getProperty("line.separator")
- + " got : " + sig[0]);
- }
-
- if (!s.equals(sig[1]))
- {
- fail("s component wrong." + System.getProperty("line.separator")
- + " expecting: " + s + System.getProperty("line.separator")
- + " got : " + sig[1]);
- }
-
- // Verify the signature
- ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
- params.getCurve().decodePoint(Hex.decode("020145E221AB9F71C5FE740D8D2B94939A09E2816E2167A7D058125A06A80C014F553E8D6764B048FB6F2B687CEC72F39738F223D4CE6AFCBFF2E34774AA5D3C342CB3")), // Q
- params);
-
- dsa.init(false, pubKey);
- if (!dsa.verifySignature(M, sig[0], sig[1]))
- {
- fail("signature fails");
- }
- }
-
- /**
- * General test for long digest.
- */
- private void testECDSA239bitBinaryAndLargeDigest()
- {
- BigInteger r = new BigInteger("21596333210419611985018340039034612628818151486841789642455876922391552");
- BigInteger s = new BigInteger("144940322424411242416373536877786566515839911620497068645600824084578597");
-
- byte[] kData = BigIntegers.asUnsignedByteArray(new BigInteger("171278725565216523967285789236956265265265235675811949404040041670216363"));
-
- SecureRandom k = new FixedSecureRandom(kData);
-
- BigInteger n = new BigInteger("220855883097298041197912187592864814557886993776713230936715041207411783");
- BigInteger h = BigInteger.valueOf(4);
-
- ECCurve.F2m curve = new ECCurve.F2m(
- 239, // m
- 36, //k
- new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), // a
- new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16), // b
- n, h);
-
- ECDomainParameters params = new ECDomainParameters(
- curve,
- curve.decodePoint(Hex.decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G
- n, h);
-
- ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
- new BigInteger("145642755521911534651321230007534120304391871461646461466464667494947990"), // d
- params);
-
- ECDSASigner ecdsa = new ECDSASigner();
- ParametersWithRandom param = new ParametersWithRandom(priKey, k);
-
- ecdsa.init(true, param);
-
- byte[] message = new BigInteger("968236873715988614170569073515315707566766479517968236873715988614170569073515315707566766479517968236873715988614170569073515315707566766479517").toByteArray();
- BigInteger[] sig = ecdsa.generateSignature(message);
-
- if (!r.equals(sig[0]))
- {
- fail("r component wrong." + System.getProperty("line.separator")
- + " expecting: " + r + System.getProperty("line.separator")
- + " got : " + sig[0]);
- }
-
- if (!s.equals(sig[1]))
- {
- fail("s component wrong." + System.getProperty("line.separator")
- + " expecting: " + s + System.getProperty("line.separator")
- + " got : " + sig[1]);
- }
-
- // Verify the signature
- ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
- curve.decodePoint(Hex.decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q
- params);
-
- ecdsa.init(false, pubKey);
- if (!ecdsa.verifySignature(message, sig[0], sig[1]))
- {
- fail("signature fails");
- }
- }
-
- /**
- * key generation test
- */
- private void testECDSAKeyGenTest()
- {
- SecureRandom random = new SecureRandom();
-
- BigInteger n = new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307");
-
- ECCurve.Fp curve = new ECCurve.Fp(
- new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
- new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
- new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16), // b
- n, ECConstants.ONE);
-
- ECDomainParameters params = new ECDomainParameters(
- curve,
- curve.decodePoint(Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
- n);
-
- ECKeyPairGenerator pGen = new ECKeyPairGenerator();
- ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(
- params,
- random);
-
- pGen.init(genParam);
-
- AsymmetricCipherKeyPair pair = pGen.generateKeyPair();
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
-
- ECDSASigner ecdsa = new ECDSASigner();
-
- ecdsa.init(true, param);
-
- byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").toByteArray();
- BigInteger[] sig = ecdsa.generateSignature(message);
-
- ecdsa.init(false, pair.getPublic());
-
- if (!ecdsa.verifySignature(message, sig[0], sig[1]))
- {
- fail("signature fails");
- }
- }
-
- /**
- * Basic Key Agreement Test
- */
- private void testECBasicAgreementTest()
- {
- SecureRandom random = new SecureRandom();
-
- BigInteger n = new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307");
-
- ECCurve.Fp curve = new ECCurve.Fp(
- new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
- new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
- new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16), // b
- n, ECConstants.ONE);
-
- ECDomainParameters params = new ECDomainParameters(
- curve,
- curve.decodePoint(Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
- n);
-
- ECKeyPairGenerator pGen = new ECKeyPairGenerator();
- ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(
- params,
- random);
-
- pGen.init(genParam);
-
- AsymmetricCipherKeyPair p1 = pGen.generateKeyPair();
- AsymmetricCipherKeyPair p2 = pGen.generateKeyPair();
-
- //
- // two way
- //
- BasicAgreement e1 = new ECDHBasicAgreement();
- BasicAgreement e2 = new ECDHBasicAgreement();
-
- e1.init(p1.getPrivate());
- e2.init(p2.getPrivate());
-
- BigInteger k1 = e1.calculateAgreement(p2.getPublic());
- BigInteger k2 = e2.calculateAgreement(p1.getPublic());
-
- if (!k1.equals(k2))
- {
- fail("calculated agreement test failed");
- }
-
- //
- // two way
- //
- e1 = new ECDHCBasicAgreement();
- e2 = new ECDHCBasicAgreement();
-
- e1.init(p1.getPrivate());
- e2.init(p2.getPrivate());
-
- k1 = e1.calculateAgreement(p2.getPublic());
- k2 = e2.calculateAgreement(p1.getPublic());
-
- if (!k1.equals(k2))
- {
- fail("calculated agreement test failed");
- }
- }
-
- private void testECMQVTestVector1()
- {
- // Test Vector from GEC-2
-
- X9ECParameters x9 = SECNamedCurves.getByName("secp160r1");
- ECDomainParameters p = new ECDomainParameters(
- x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
-
- AsymmetricCipherKeyPair U1 = new AsymmetricCipherKeyPair(
- new ECPublicKeyParameters(
- p.getCurve().decodePoint(Hex.decode("0251B4496FECC406ED0E75A24A3C03206251419DC0")), p),
- new ECPrivateKeyParameters(
- new BigInteger("AA374FFC3CE144E6B073307972CB6D57B2A4E982", 16), p));
-
- AsymmetricCipherKeyPair U2 = new AsymmetricCipherKeyPair(
- new ECPublicKeyParameters(
- p.getCurve().decodePoint(Hex.decode("03D99CE4D8BF52FA20BD21A962C6556B0F71F4CA1F")), p),
- new ECPrivateKeyParameters(
- new BigInteger("149EC7EA3A220A887619B3F9E5B4CA51C7D1779C", 16), p));
-
- AsymmetricCipherKeyPair V1 = new AsymmetricCipherKeyPair(
- new ECPublicKeyParameters(
- p.getCurve().decodePoint(Hex.decode("0349B41E0E9C0369C2328739D90F63D56707C6E5BC")), p),
- new ECPrivateKeyParameters(
- new BigInteger("45FB58A92A17AD4B15101C66E74F277E2B460866", 16), p));
-
- AsymmetricCipherKeyPair V2 = new AsymmetricCipherKeyPair(
- new ECPublicKeyParameters(
- p.getCurve().decodePoint(Hex.decode("02706E5D6E1F640C6E9C804E75DBC14521B1E5F3B5")), p),
- new ECPrivateKeyParameters(
- new BigInteger("18C13FCED9EADF884F7C595C8CB565DEFD0CB41E", 16), p));
-
- BigInteger x = calculateAgreement(U1, U2, V1, V2);
-
- if (x == null
- || !x.equals(new BigInteger("5A6955CEFDB4E43255FB7FCF718611E4DF8E05AC", 16)))
- {
- fail("MQV Test Vector #1 agreement failed");
- }
- }
-
- private void testECMQVTestVector2()
- {
- // Test Vector from GEC-2
-
- X9ECParameters x9 = SECNamedCurves.getByName("sect163k1");
- ECDomainParameters p = new ECDomainParameters(
- x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
-
- AsymmetricCipherKeyPair U1 = new AsymmetricCipherKeyPair(
- new ECPublicKeyParameters(
- p.getCurve().decodePoint(Hex.decode("03037D529FA37E42195F10111127FFB2BB38644806BC")), p),
- new ECPrivateKeyParameters(
- new BigInteger("03A41434AA99C2EF40C8495B2ED9739CB2155A1E0D", 16), p));
-
- AsymmetricCipherKeyPair U2 = new AsymmetricCipherKeyPair(
- new ECPublicKeyParameters(
- p.getCurve().decodePoint(Hex.decode("02015198E74BC2F1E5C9A62B80248DF0D62B9ADF8429")), p),
- new ECPrivateKeyParameters(
- new BigInteger("032FC4C61A8211E6A7C4B8B0C03CF35F7CF20DBD52", 16), p));
-
- AsymmetricCipherKeyPair V1 = new AsymmetricCipherKeyPair(
- new ECPublicKeyParameters(
- p.getCurve().decodePoint(Hex.decode("03072783FAAB9549002B4F13140B88132D1C75B3886C")), p),
- new ECPrivateKeyParameters(
- new BigInteger("57E8A78E842BF4ACD5C315AA0569DB1703541D96", 16), p));
-
- AsymmetricCipherKeyPair V2 = new AsymmetricCipherKeyPair(
- new ECPublicKeyParameters(
- p.getCurve().decodePoint(Hex.decode("03067E3AEA3510D69E8EDD19CB2A703DDC6CF5E56E32")), p),
- new ECPrivateKeyParameters(
- new BigInteger("02BD198B83A667A8D908EA1E6F90FD5C6D695DE94F", 16), p));
-
- BigInteger x = calculateAgreement(U1, U2, V1, V2);
-
- if (x == null
- || !x.equals(new BigInteger("038359FFD30C0D5FC1E6154F483B73D43E5CF2B503", 16)))
- {
- fail("MQV Test Vector #2 agreement failed");
- }
- }
-
- private void testECMQVRandom()
- {
- SecureRandom random = new SecureRandom();
-
- BigInteger n = new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307");
-
- ECCurve.Fp curve = new ECCurve.Fp(
- new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
- new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
- new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16), // b
- n, ECConstants.ONE);
-
- ECDomainParameters parameters = new ECDomainParameters(
- curve,
- curve.decodePoint(Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
- n);
-
- ECKeyPairGenerator pGen = new ECKeyPairGenerator();
-
- pGen.init(new ECKeyGenerationParameters(parameters, random));
-
-
- // Pre-established key pairs
- AsymmetricCipherKeyPair U1 = pGen.generateKeyPair();
- AsymmetricCipherKeyPair V1 = pGen.generateKeyPair();
-
- // Ephemeral key pairs
- AsymmetricCipherKeyPair U2 = pGen.generateKeyPair();
- AsymmetricCipherKeyPair V2 = pGen.generateKeyPair();
-
- BigInteger x = calculateAgreement(U1, U2, V1, V2);
-
- if (x == null)
- {
- fail("MQV Test Vector (random) agreement failed");
- }
- }
-
- private static BigInteger calculateAgreement(
- AsymmetricCipherKeyPair U1,
- AsymmetricCipherKeyPair U2,
- AsymmetricCipherKeyPair V1,
- AsymmetricCipherKeyPair V2)
- {
- ECMQVBasicAgreement u = new ECMQVBasicAgreement();
- u.init(new MQVPrivateParameters(
- (ECPrivateKeyParameters)U1.getPrivate(),
- (ECPrivateKeyParameters)U2.getPrivate(),
- (ECPublicKeyParameters)U2.getPublic()));
- BigInteger ux = u.calculateAgreement(new MQVPublicParameters(
- (ECPublicKeyParameters)V1.getPublic(),
- (ECPublicKeyParameters)V2.getPublic()));
-
- ECMQVBasicAgreement v = new ECMQVBasicAgreement();
- v.init(new MQVPrivateParameters(
- (ECPrivateKeyParameters)V1.getPrivate(),
- (ECPrivateKeyParameters)V2.getPrivate(),
- (ECPublicKeyParameters)V2.getPublic()));
- BigInteger vx = v.calculateAgreement(new MQVPublicParameters(
- (ECPublicKeyParameters)U1.getPublic(),
- (ECPublicKeyParameters)U2.getPublic()));
-
- if (ux.equals(vx))
- {
- return ux;
- }
-
- return null;
- }
-
- public String getName()
- {
- return "EC";
- }
-
- public void performTest()
- {
- decodeTest();
- testECDSA192bitPrime();
- testECDSA239bitPrime();
- testECDSA191bitBinary();
- testECDSA239bitBinary();
- testECDSAKeyGenTest();
- testECBasicAgreementTest();
-
- testECDSAP224sha224();
- testECDSAP224OneByteOver();
- testECDSAP256sha256();
- testECDSAP521sha512();
- testECDSASecP224k1sha256();
- testECDSA239bitBinaryAndLargeDigest();
-
- testECMQVTestVector1();
- testECMQVTestVector2();
- testECMQVRandom();
- }
-
-
- public static void main(
- String[] args)
- {
- runTest(new ECTest());
- }
-}
-
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/ElGamalTest.java b/core/src/test/java/org/bouncycastle/crypto/test/ElGamalTest.java
deleted file mode 100644
index fb936993..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/ElGamalTest.java
+++ /dev/null
@@ -1,285 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.engines.ElGamalEngine;
-import org.bouncycastle.crypto.generators.ElGamalKeyPairGenerator;
-import org.bouncycastle.crypto.generators.ElGamalParametersGenerator;
-import org.bouncycastle.crypto.params.ElGamalKeyGenerationParameters;
-import org.bouncycastle.crypto.params.ElGamalParameters;
-import org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ElGamalPublicKeyParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.BigIntegers;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class ElGamalTest
- extends SimpleTest
-{
- private BigInteger g512 = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16);
- private BigInteger p512 = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16);
-
- private BigInteger g768 = new BigInteger("7c240073c1316c621df461b71ebb0cdcc90a6e5527e5e126633d131f87461c4dc4afc60c2cb0f053b6758871489a69613e2a8b4c8acde23954c08c81cbd36132cfd64d69e4ed9f8e51ed6e516297206672d5c0a69135df0a5dcf010d289a9ca1", 16);
- private BigInteger p768 = new BigInteger("8c9dd223debed1b80103b8b309715be009d48860ed5ae9b9d5d8159508efd802e3ad4501a7f7e1cfec78844489148cd72da24b21eddd01aa624291c48393e277cfc529e37075eccef957f3616f962d15b44aeab4039d01b817fde9eaa12fd73f", 16);
-
- private BigInteger g1024 = new BigInteger("1db17639cdf96bc4eabba19454f0b7e5bd4e14862889a725c96eb61048dcd676ceb303d586e30f060dbafd8a571a39c4d823982117da5cc4e0f89c77388b7a08896362429b94a18a327604eb7ff227bffbc83459ade299e57b5f77b50fb045250934938efa145511166e3197373e1b5b1e52de713eb49792bedde722c6717abf", 16);
- private BigInteger p1024 = new BigInteger("a00e283b3c624e5b2b4d9fbc2653b5185d99499b00fd1bf244c6f0bb817b4d1c451b2958d62a0f8a38caef059fb5ecd25d75ed9af403f5b5bdab97a642902f824e3c13789fed95fa106ddfe0ff4a707c85e2eb77d49e68f2808bcea18ce128b178cd287c6bc00efa9a1ad2a673fe0dceace53166f75b81d6709d5f8af7c66bb7", 16);
-
- private BigInteger yPgpBogusPSamp = new BigInteger("de4688497cc05b45fe8559bc9918c45afcad69b74123a7236eba409fd9de8ea34c7869839ee9df35e3d97576145d089841aa65b5b4e061fae52c37e430354269a02496b8ed8456f2d0d7c9b0db985fbcb21ae9f78507ed6e3a29db595b201b1a4f931c7d791eede65ccf918e8a61cf146859151c78c41ad48853694623467d78", 16);
- private BigInteger xPgpBogusPSamp = new BigInteger("cbaf780f2cfe4f987bbc5fcb0738bbd7912060ccfdf37cbfeea65c0fd857e74a8df6cc359375f28cf5725d081813c614410a78cbe4b06d677beea9ff0fa10b1dbc47a6ed8c5b8466d6a95d6574029dbdf72596392e1b6b230faf9916dc8455821c10527a375a4d1c8a54947d1fe714d321aca25ad486b4b456506999fd2fd11a", 16);
- private BigInteger gPgpBogusPSamp = new BigInteger("153ffe9522076d1cbd6e75f0816a0fc2ebd8b0e0091406587387a1763022088a03b411eed07ff50efb82b21f1608c352d10f63ba7e7e981a2f3387cec8af2915953d00493857663ae8919f517fe90f1d2abe7af4305a344b10d1a25d75f65902cd7fd775853d3ac43d7c5253ad666e1e63ee98cdcb10af81273d4ff053ff07d51", 16);
- private BigInteger pPgpBogusPSamp = new BigInteger("15061b26cdab4e865098a01c86f13b03220104c5443e950658b36b85245aa0c616a0c0d8d99c454bea087c172315e45b3bc9b925443948a2b6ba47608a6035b9a79a4ef34a78d7274a12ede8364f02d5030db864988643d7e92753df603bd69fbd2682ab0af64d1a866d1131a2cb13333cedb0a9e6eefddd9fff8154d34c2daab", 16);
- private int lPgpBogusPSamp = 0;
-
- public String getName()
- {
- return "ElGamal";
- }
-
- private void testEnc(
- int size,
- int privateValueSize,
- BigInteger g,
- BigInteger p)
- {
- ElGamalParameters dhParams = new ElGamalParameters(p, g, privateValueSize);
- ElGamalKeyGenerationParameters params = new ElGamalKeyGenerationParameters(new SecureRandom(), dhParams);
- ElGamalKeyPairGenerator kpGen = new ElGamalKeyPairGenerator();
-
- kpGen.init(params);
-
- //
- // generate pair
- //
- AsymmetricCipherKeyPair pair = kpGen.generateKeyPair();
-
- ElGamalPublicKeyParameters pu = (ElGamalPublicKeyParameters)pair.getPublic();
- ElGamalPrivateKeyParameters pv = (ElGamalPrivateKeyParameters)pair.getPrivate();
-
- checkKeySize(privateValueSize, pv);
-
- ElGamalEngine e = new ElGamalEngine();
-
- e.init(true, pu);
-
- if (e.getOutputBlockSize() != size / 4)
- {
- fail(size + " getOutputBlockSize() on encryption failed.");
- }
-
- byte[] message = Hex.decode("5468697320697320612074657374");
-
- byte[] pText = message;
- byte[] cText = e.processBlock(pText, 0, pText.length);
-
- e.init(false, pv);
-
- if (e.getOutputBlockSize() != (size / 8) - 1)
- {
- fail(size + " getOutputBlockSize() on decryption failed.");
- }
-
- pText = e.processBlock(cText, 0, cText.length);
-
- if (!Arrays.areEqual(message, pText))
- {
- fail(size + " bit test failed");
- }
-
- e.init(true, pu);
-
- byte[] bytes = new byte[e.getInputBlockSize() + 2];
-
- try
- {
- e.processBlock(bytes, 0, bytes.length);
-
- fail("out of range block not detected");
- }
- catch (DataLengthException ex)
- {
- // expected
- }
-
- try
- {
- bytes[0] = (byte)0xff;
-
- e.processBlock(bytes, 0, bytes.length - 1);
-
- fail("out of range block not detected");
- }
- catch (DataLengthException ex)
- {
- // expected
- }
-
- try
- {
- bytes[0] = (byte)0x7f;
-
- e.processBlock(bytes, 0, bytes.length - 1);
- }
- catch (DataLengthException ex)
- {
- fail("in range block failed");
- }
-
- try
- {
- bytes = BigIntegers.asUnsignedByteArray(p);
-
- e.processBlock(bytes, 0, bytes.length);
-
- fail("out of range block not detected");
- }
- catch (DataLengthException ex)
- {
- // expected
- }
-
- try
- {
- bytes = BigIntegers.asUnsignedByteArray(p.subtract(BigInteger.valueOf(1)));
-
- e.processBlock(bytes, 0, bytes.length);
- }
- catch (DataLengthException ex)
- {
- fail("boundary block rejected");
- }
- }
-
- private void checkKeySize(
- int privateValueSize,
- ElGamalPrivateKeyParameters priv)
- {
- if (privateValueSize != 0)
- {
- if (priv.getX().bitLength() != privateValueSize)
- {
- fail("limited key check failed for key size " + privateValueSize);
- }
- }
- }
-
- /**
- * this test is can take quiet a while
- *
- * @param size size of key in bits.
- */
- private void testGeneration(
- int size)
- {
- ElGamalParametersGenerator pGen = new ElGamalParametersGenerator();
-
- pGen.init(size, 10, new SecureRandom());
-
- ElGamalParameters elParams = pGen.generateParameters();
-
- if (elParams.getL() != 0)
- {
- fail("ElGamalParametersGenerator failed to set L to 0 in generated ElGamalParameters");
- }
-
- ElGamalKeyGenerationParameters params = new ElGamalKeyGenerationParameters(new SecureRandom(), elParams);
-
- ElGamalKeyPairGenerator kpGen = new ElGamalKeyPairGenerator();
-
- kpGen.init(params);
-
- //
- // generate first pair
- //
- AsymmetricCipherKeyPair pair = kpGen.generateKeyPair();
-
- ElGamalPublicKeyParameters pu = (ElGamalPublicKeyParameters)pair.getPublic();
- ElGamalPrivateKeyParameters pv = (ElGamalPrivateKeyParameters)pair.getPrivate();
-
- ElGamalEngine e = new ElGamalEngine();
-
- e.init(true, new ParametersWithRandom(pu, new SecureRandom()));
-
- byte[] message = Hex.decode("5468697320697320612074657374");
-
- byte[] pText = message;
- byte[] cText = e.processBlock(pText, 0, pText.length);
-
- e.init(false, pv);
-
- pText = e.processBlock(cText, 0, cText.length);
-
- if (!Arrays.areEqual(message, pText))
- {
- fail("generation test failed");
- }
- }
-
- private void testInitCheck()
- {
- try
- {
- new ElGamalEngine().processBlock(new byte[]{ 1 }, 0, 1);
- fail("failed initialisation check");
- }
- catch (IllegalStateException e)
- {
- // expected
- }
- }
-
- private void testInvalidP()
- {
- ElGamalParameters dhParams = new ElGamalParameters(pPgpBogusPSamp, gPgpBogusPSamp, lPgpBogusPSamp);
- ElGamalPublicKeyParameters pu = new ElGamalPublicKeyParameters(yPgpBogusPSamp, dhParams);
- ElGamalPrivateKeyParameters pv = new ElGamalPrivateKeyParameters(xPgpBogusPSamp, dhParams);
-
- ElGamalEngine e = new ElGamalEngine();
-
- e.init(true, pu);
-
- byte[] message = Hex.decode("5468697320697320612074657374");
-
- byte[] pText = message;
- byte[] cText = e.processBlock(pText, 0, pText.length);
-
- e.init(false, pv);
-
- pText = e.processBlock(cText, 0, cText.length);
-
- if (Arrays.areEqual(message, pText))
- {
- fail("invalid test failed");
- }
- }
-
- public void performTest()
- {
- testInvalidP();
-
- testEnc(512, 0, g512, p512);
- testEnc(768, 0, g768, p768);
- testEnc(1024, 0, g1024, p1024);
-
- testEnc(512, 64, g512, p512);
- testEnc(768, 128, g768, p768);
-
- //
- // generation test.
- //
- testGeneration(258);
-
- testInitCheck();
- }
-
- public static void main(
- String[] args)
- {
- runTest(new ElGamalTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/EqualsHashCodeTest.java b/core/src/test/java/org/bouncycastle/crypto/test/EqualsHashCodeTest.java
deleted file mode 100644
index 1ab7cc49..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/EqualsHashCodeTest.java
+++ /dev/null
@@ -1,261 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.generators.DHKeyPairGenerator;
-import org.bouncycastle.crypto.generators.ElGamalKeyPairGenerator;
-import org.bouncycastle.crypto.params.DHKeyGenerationParameters;
-import org.bouncycastle.crypto.params.DHKeyParameters;
-import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
-import org.bouncycastle.crypto.params.DHPublicKeyParameters;
-import org.bouncycastle.crypto.params.DHValidationParameters;
-import org.bouncycastle.crypto.params.DSAParameters;
-import org.bouncycastle.crypto.params.DSAValidationParameters;
-import org.bouncycastle.crypto.params.ElGamalKeyGenerationParameters;
-import org.bouncycastle.crypto.params.ElGamalKeyParameters;
-import org.bouncycastle.crypto.params.ElGamalParameters;
-import org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ElGamalPublicKeyParameters;
-import org.bouncycastle.crypto.params.GOST3410Parameters;
-import org.bouncycastle.crypto.params.GOST3410ValidationParameters;
-import org.bouncycastle.util.test.SimpleTest;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-class DHTestKeyParameters
- extends DHKeyParameters
-{
- protected DHTestKeyParameters(boolean isPrivate, DHParameters params)
- {
- super(isPrivate, params);
- }
-}
-
-class ElGamalTestKeyParameters
- extends ElGamalKeyParameters
-{
- protected ElGamalTestKeyParameters(boolean isPrivate, ElGamalParameters params)
- {
- super(isPrivate, params);
- }
-}
-
-public class EqualsHashCodeTest
- extends SimpleTest
-{
- private static Object OTHER = new Object();
-
- public String getName()
- {
- return "EqualsHashCode";
- }
-
- private void doTest(Object a, Object equalsA, Object notEqualsA)
- {
- if (a.equals(null))
- {
- fail("a equaled null");
- }
-
- if (!a.equals(equalsA) || !equalsA.equals(a))
- {
- fail("equality failed");
- }
-
- if (a.equals(OTHER))
- {
- fail("other inequality failed");
- }
-
- if (a.equals(notEqualsA) || notEqualsA.equals(a))
- {
- fail("inequality failed");
- }
-
- if (a.hashCode() != equalsA.hashCode())
- {
- fail("hashCode equality failed");
- }
- }
-
- private void dhTest()
- {
- BigInteger g512 = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16);
- BigInteger p512 = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16);
-
- DHParameters dhParams = new DHParameters(p512, g512);
- DHKeyGenerationParameters params = new DHKeyGenerationParameters(new SecureRandom(), dhParams); DHKeyPairGenerator kpGen = new DHKeyPairGenerator();
-
- kpGen.init(params);
-
- AsymmetricCipherKeyPair pair = kpGen.generateKeyPair();
- DHPublicKeyParameters pu1 = (DHPublicKeyParameters)pair.getPublic();
- DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.getPrivate();
-
- DHPublicKeyParameters pu2 = new DHPublicKeyParameters(pu1.getY(), pu1.getParameters());
- DHPrivateKeyParameters pv2 = new DHPrivateKeyParameters(pv1.getX(), pv1.getParameters());
- DHPublicKeyParameters pu3 = new DHPublicKeyParameters(pv1.getX(), pu1.getParameters());
- DHPrivateKeyParameters pv3 = new DHPrivateKeyParameters(pu1.getY(), pu1.getParameters());
-
- doTest(pu1, pu2, pu3);
- doTest(pv1, pv2, pv3);
-
- DHParameters pr1 = pu1.getParameters();
- DHParameters pr2 = new DHParameters(pr1.getP(), pr1.getG(), pr1.getQ(), pr1.getM(), pr1.getL(), pr1.getJ(), pr1.getValidationParameters());
- DHParameters pr3 = new DHParameters(pr1.getG(), pr1.getP(), pr1.getQ(), pr1.getM(), pr1.getL(), pr1.getJ(), pr1.getValidationParameters());
-
- doTest(pr1, pr2, pr3);
-
- pr3 = new DHParameters(pr1.getG(), pr1.getP(), null, pr1.getM(), pr1.getL(), pr1.getJ(), pr1.getValidationParameters());
-
- doTest(pr1, pr2, pr3);
-
- pu2 = new DHPublicKeyParameters(pu1.getY(), pr2);
- pv2 = new DHPrivateKeyParameters(pv1.getX(), pr2);
-
- doTest(pu1, pu2, pu3);
- doTest(pv1, pv2, pv3);
-
- DHValidationParameters vp1 = new DHValidationParameters(new byte[20], 1024);
- DHValidationParameters vp2 = new DHValidationParameters(new byte[20], 1024);
- DHValidationParameters vp3 = new DHValidationParameters(new byte[24], 1024);
-
- doTest(vp1, vp1, vp3);
- doTest(vp1, vp2, vp3);
-
- byte[] bytes = new byte[20];
- bytes[0] = 1;
-
- vp3 = new DHValidationParameters(bytes, 1024);
-
- doTest(vp1, vp2, vp3);
-
- vp3 = new DHValidationParameters(new byte[20], 2048);
-
- doTest(vp1, vp2, vp3);
-
- DHTestKeyParameters k1 = new DHTestKeyParameters(false, null);
- DHTestKeyParameters k2 = new DHTestKeyParameters(false, null);
- DHTestKeyParameters k3 = new DHTestKeyParameters(false, pu1.getParameters());
-
- doTest(k1, k2, k3);
- }
-
- private void elGamalTest()
- {
- BigInteger g512 = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16);
- BigInteger p512 = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16);
-
- ElGamalParameters dhParams = new ElGamalParameters(p512, g512);
- ElGamalKeyGenerationParameters params = new ElGamalKeyGenerationParameters(new SecureRandom(), dhParams); ElGamalKeyPairGenerator kpGen = new ElGamalKeyPairGenerator();
-
- kpGen.init(params);
-
- AsymmetricCipherKeyPair pair = kpGen.generateKeyPair();
- ElGamalPublicKeyParameters pu1 = (ElGamalPublicKeyParameters)pair.getPublic();
- ElGamalPrivateKeyParameters pv1 = (ElGamalPrivateKeyParameters)pair.getPrivate();
-
- ElGamalPublicKeyParameters pu2 = new ElGamalPublicKeyParameters(pu1.getY(), pu1.getParameters());
- ElGamalPrivateKeyParameters pv2 = new ElGamalPrivateKeyParameters(pv1.getX(), pv1.getParameters());
- ElGamalPublicKeyParameters pu3 = new ElGamalPublicKeyParameters(pv1.getX(), pu1.getParameters());
- ElGamalPrivateKeyParameters pv3 = new ElGamalPrivateKeyParameters(pu1.getY(), pu1.getParameters());
-
- doTest(pu1, pu2, pu3);
- doTest(pv1, pv2, pv3);
-
- ElGamalParameters pr1 = pu1.getParameters();
- ElGamalParameters pr2 = new ElGamalParameters(pr1.getP(), pr1.getG());
- ElGamalParameters pr3 = new ElGamalParameters(pr1.getG(), pr1.getP());
-
- doTest(pr1, pr2, pr3);
-
- pu2 = new ElGamalPublicKeyParameters(pu1.getY(), pr2);
- pv2 = new ElGamalPrivateKeyParameters(pv1.getX(), pr2);
-
- doTest(pu1, pu2, pu3);
- doTest(pv1, pv2, pv3);
-
- ElGamalTestKeyParameters k1 = new ElGamalTestKeyParameters(false, null);
- ElGamalTestKeyParameters k2 = new ElGamalTestKeyParameters(false, null);
- ElGamalTestKeyParameters k3 = new ElGamalTestKeyParameters(false, pu1.getParameters());
-
- doTest(k1, k2, k3);
- }
-
- private void dsaTest()
- {
- BigInteger a = BigInteger.valueOf(1), b = BigInteger.valueOf(2), c = BigInteger.valueOf(3);
-
- DSAParameters dsaP1 = new DSAParameters(a, b, c);
- DSAParameters dsaP2 = new DSAParameters(a, b, c);
- DSAParameters dsaP3 = new DSAParameters(b, c, a);
-
- doTest(dsaP1, dsaP2, dsaP3);
-
- DSAValidationParameters vp1 = new DSAValidationParameters(new byte[20], 1024);
- DSAValidationParameters vp2 = new DSAValidationParameters(new byte[20], 1024);
- DSAValidationParameters vp3 = new DSAValidationParameters(new byte[24], 1024);
-
- doTest(vp1, vp1, vp3);
- doTest(vp1, vp2, vp3);
-
- byte[] bytes = new byte[20];
- bytes[0] = 1;
-
- vp3 = new DSAValidationParameters(bytes, 1024);
-
- doTest(vp1, vp2, vp3);
-
- vp3 = new DSAValidationParameters(new byte[20], 2048);
-
- doTest(vp1, vp2, vp3);
- }
-
- private void gost3410Test()
- {
- BigInteger a = BigInteger.valueOf(1), b = BigInteger.valueOf(2), c = BigInteger.valueOf(3);
-
- GOST3410Parameters g1 = new GOST3410Parameters(a, b, c);
- GOST3410Parameters g2 = new GOST3410Parameters(a, b, c);
- GOST3410Parameters g3 = new GOST3410Parameters(a, c, c);
-
- doTest(g1, g2, g3);
-
- GOST3410ValidationParameters v1 = new GOST3410ValidationParameters(100, 1);
- GOST3410ValidationParameters v2 = new GOST3410ValidationParameters(100, 1);
- GOST3410ValidationParameters v3 = new GOST3410ValidationParameters(101, 1);
-
- doTest(v1, v2, v3);
-
- v3 = new GOST3410ValidationParameters(100, 2);
-
- doTest(v1, v2, v3);
-
- v1 = new GOST3410ValidationParameters(100L, 1L);
- v2 = new GOST3410ValidationParameters(100L, 1L);
- v3 = new GOST3410ValidationParameters(101L, 1L);
-
- doTest(v1, v2, v3);
-
- v3 = new GOST3410ValidationParameters(100L, 2L);
-
- doTest(v1, v2, v3);
-
- }
-
- public void performTest()
- throws Exception
- {
- dhTest();
- elGamalTest();
- gost3410Test();
- dsaTest();
- }
-
- public static void main(
- String[] args)
- {
- runTest(new EqualsHashCodeTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/GCMReorderTest.java b/core/src/test/java/org/bouncycastle/crypto/test/GCMReorderTest.java
deleted file mode 100644
index efac338f..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/GCMReorderTest.java
+++ /dev/null
@@ -1,347 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.io.IOException;
-import java.security.SecureRandom;
-
-import junit.framework.TestCase;
-import org.bouncycastle.crypto.modes.gcm.GCMExponentiator;
-import org.bouncycastle.crypto.modes.gcm.GCMMultiplier;
-import org.bouncycastle.crypto.modes.gcm.Tables1kGCMExponentiator;
-import org.bouncycastle.crypto.modes.gcm.Tables64kGCMMultiplier;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Pack;
-import org.bouncycastle.util.encoders.Hex;
-
-public class GCMReorderTest
- extends TestCase
-{
- private static final byte[] H;
- private static final SecureRandom random = new SecureRandom();
- private static final GCMMultiplier mul = new Tables64kGCMMultiplier();
- private static final GCMExponentiator exp = new Tables1kGCMExponentiator();
- private static final byte[] EMPTY = new byte[0];
-
- static
- {
- H = new byte[16];
- random.nextBytes(H);
- mul.init(Arrays.clone(H));
- exp.init(Arrays.clone(H));
- }
-
- public void testCombine() throws Exception
- {
- for (int count = 0; count < 10; ++count)
- {
- byte[] A = randomBytes(1000);
- byte[] C = randomBytes(1000);
-
- byte[] ghashA_ = GHASH(A, EMPTY);
- byte[] ghash_C = GHASH(EMPTY, C);
- byte[] ghashAC = GHASH(A, C);
-
- byte[] ghashCombine = combine_GHASH(ghashA_, (long)A.length * 8, ghash_C, (long)C.length * 8);
-
- assertTrue(Arrays.areEqual(ghashAC, ghashCombine));
- }
- }
-
- public void testConcatAuth() throws Exception
- {
- for (int count = 0; count < 10; ++count)
- {
- byte[] P = randomBlocks(100);
- byte[] A = randomBytes(1000);
- byte[] PA = concatArrays(P, A);
-
- byte[] ghashP_ = GHASH(P, EMPTY);
- byte[] ghashA_ = GHASH(A, EMPTY);
- byte[] ghashPA_ = GHASH(PA, EMPTY);
- byte[] ghashConcat = concatAuth_GHASH(ghashP_, (long)P.length * 8, ghashA_, (long)A.length * 8);
-
- assertTrue(Arrays.areEqual(ghashPA_, ghashConcat));
- }
- }
-
- public void testConcatCrypt() throws Exception
- {
- for (int count = 0; count < 10; ++count)
- {
- byte[] P = randomBlocks(100);
- byte[] A = randomBytes(1000);
- byte[] PA = concatArrays(P, A);
-
- byte[] ghash_P = GHASH(EMPTY, P);
- byte[] ghash_A = GHASH(EMPTY, A);
- byte[] ghash_PA = GHASH(EMPTY, PA);
- byte[] ghashConcat = concatCrypt_GHASH(ghash_P, (long)P.length * 8, ghash_A, (long)A.length * 8);
-
- assertTrue(Arrays.areEqual(ghash_PA, ghashConcat));
- }
- }
-
- public void testExp()
- {
- {
- byte[] buf1 = new byte[16];
- buf1[0] = (byte)0x80;
-
- byte[] buf2 = new byte[16];
-
- for (int pow = 0; pow != 100; ++pow)
- {
- exp.exponentiateX(pow, buf2);
-
- assertTrue(Arrays.areEqual(buf1, buf2));
-
- mul.multiplyH(buf1);
- }
- }
-
- long[] testPow = new long[]{ 10, 1, 8, 17, 24, 13, 2, 13, 2, 3 };
- byte[][] testData = new byte[][]{
- Hex.decode("9185848a877bd87ba071e281f476e8e7"),
- Hex.decode("697ce3052137d80745d524474fb6b290"),
- Hex.decode("2696fc47198bb23b11296e4f88720a17"),
- Hex.decode("01f2f0ead011a4ae0cf3572f1b76dd8e"),
- Hex.decode("a53060694a044e4b7fa1e661c5a7bb6b"),
- Hex.decode("39c0392e8b6b0e04a7565c85394c2c4c"),
- Hex.decode("519c362d502e07f2d8b7597a359a5214"),
- Hex.decode("5a527a393675705e19b2117f67695af4"),
- Hex.decode("27fc0901d1d332a53ba4d4386c2109d2"),
- Hex.decode("93ca9b57174aabedf8220e83366d7df6"),
- };
-
- for (int i = 0; i != 10; ++i)
- {
- long pow = testPow[i];
- byte[] data = Arrays.clone(testData[i]);
-
- byte[] expected = Arrays.clone(data);
- for (int j = 0; j < pow; ++j)
- {
- mul.multiplyH(expected);
- }
-
- byte[] H_a = new byte[16];
- exp.exponentiateX(pow, H_a);
- byte[] actual = multiply(data, H_a);
-
- assertTrue(Arrays.areEqual(expected, actual));
- }
- }
-
- public void testMultiply()
- {
- byte[] expected = Arrays.clone(H);
- mul.multiplyH(expected);
-
- assertTrue(Arrays.areEqual(expected, multiply(H, H)));
-
- for (int count = 0; count < 10; ++count)
- {
- byte[] a = new byte[16];
- random.nextBytes(a);
-
- byte[] b = new byte[16];
- random.nextBytes(b);
-
- expected = Arrays.clone(a);
- mul.multiplyH(expected);
- assertTrue(Arrays.areEqual(expected, multiply(a, H)));
- assertTrue(Arrays.areEqual(expected, multiply(H, a)));
-
- expected = Arrays.clone(b);
- mul.multiplyH(expected);
- assertTrue(Arrays.areEqual(expected, multiply(b, H)));
- assertTrue(Arrays.areEqual(expected, multiply(H, b)));
-
- assertTrue(Arrays.areEqual(multiply(a, b), multiply(b, a)));
- }
- }
-
- private byte[] randomBlocks(int upper)
- {
- byte[] bs = new byte[16 * random.nextInt(upper)];
- random.nextBytes(bs);
- return bs;
- }
-
- private byte[] randomBytes(int upper)
- {
- byte[] bs = new byte[random.nextInt(upper)];
- random.nextBytes(bs);
- return bs;
- }
-
- private byte[] concatArrays(byte[] a, byte[] b) throws IOException
- {
- byte[] ab = new byte[a.length + b.length];
- System.arraycopy(a, 0, ab, 0, a.length);
- System.arraycopy(b, 0, ab, a.length, b.length);
- return ab;
- }
-
- private byte[] combine_GHASH(byte[] ghashA_, long bitlenA, byte[] ghash_C, long bitlenC)
- {
- // Note: bitlenA must be aligned to the block size
-
- long c = (bitlenC + 127) >>> 7;
-
- byte[] H_c = new byte[16];
- exp.exponentiateX(c, H_c);
-
- byte[] tmp1 = lengthBlock(bitlenA, 0);
- mul.multiplyH(tmp1);
-
- byte[] ghashAC = Arrays.clone(ghashA_);
- xor(ghashAC, tmp1);
- ghashAC = multiply(ghashAC, H_c);
- // No need to touch the len(C) part (second 8 bytes)
- xor(ghashAC, tmp1);
- xor(ghashAC, ghash_C);
-
- return ghashAC;
- }
-
- private byte[] concatAuth_GHASH(byte[] ghashP, long bitlenP, byte[] ghashA, long bitlenA)
- {
- // Note: bitlenP must be aligned to the block size
-
- long a = (bitlenA + 127) >>> 7;
-
- byte[] tmp1 = lengthBlock(bitlenP, 0);
- mul.multiplyH(tmp1);
-
- byte[] tmp2 = lengthBlock(bitlenA ^ (bitlenP + bitlenA), 0);
- mul.multiplyH(tmp2);
-
- byte[] H_a = new byte[16];
- exp.exponentiateX(a, H_a);
-
- byte[] ghashC = Arrays.clone(ghashP);
- xor(ghashC, tmp1);
- ghashC = multiply(ghashC, H_a);
- xor(ghashC, tmp2);
- xor(ghashC, ghashA);
- return ghashC;
- }
-
- private byte[] concatCrypt_GHASH(byte[] ghashP, long bitlenP, byte[] ghashA, long bitlenA)
- {
- // Note: bitlenP must be aligned to the block size
-
- long a = (bitlenA + 127) >>> 7;
-
- byte[] tmp1 = lengthBlock(0, bitlenP);
- mul.multiplyH(tmp1);
-
- byte[] tmp2 = lengthBlock(0, bitlenA ^ (bitlenP + bitlenA));
- mul.multiplyH(tmp2);
-
- byte[] H_a = new byte[16];
- exp.exponentiateX(a, H_a);
-
- byte[] ghashC = Arrays.clone(ghashP);
- xor(ghashC, tmp1);
- ghashC = multiply(ghashC, H_a);
- xor(ghashC, tmp2);
- xor(ghashC, ghashA);
- return ghashC;
- }
-
- private byte[] GHASH(byte[] A, byte[] C)
- {
- byte[] X = new byte[16];
-
- {
- for (int pos = 0; pos < A.length; pos += 16)
- {
- byte[] tmp = new byte[16];
- int num = Math.min(A.length - pos, 16);
- System.arraycopy(A, pos, tmp, 0, num);
- xor(X, tmp);
- mul.multiplyH(X);
- }
- }
-
- {
- for (int pos = 0; pos < C.length; pos += 16)
- {
- byte[] tmp = new byte[16];
- int num = Math.min(C.length - pos, 16);
- System.arraycopy(C, pos, tmp, 0, num);
- xor(X, tmp);
- mul.multiplyH(X);
- }
- }
-
- {
- xor(X, lengthBlock((long)A.length * 8, (long)C.length * 8));
- mul.multiplyH(X);
- }
-
- return X;
- }
-
- private static byte[] lengthBlock(long bitlenA, long bitlenC)
- {
- byte[] tmp = new byte[16];
- Pack.longToBigEndian(bitlenA, tmp, 0);
- Pack.longToBigEndian(bitlenC, tmp, 8);
- return tmp;
- }
-
- private static void xor(byte[] block, byte[] val)
- {
- for (int i = 15; i >= 0; --i)
- {
- block[i] ^= val[i];
- }
- }
-
- private static byte[] multiply(byte[] a, byte[] b)
- {
- byte[] c = new byte[16];
- byte[] tmp = Arrays.clone(b);
-
- for (int i = 0; i < 16; ++i)
- {
- byte bits = a[i];
- for (int j = 7; j >= 0; --j)
- {
- if ((bits & (1 << j)) != 0)
- {
- xor(c, tmp);
- }
-
- boolean lsb = (tmp[15] & 1) != 0;
- shiftRight(tmp);
- if (lsb)
- {
- // R = new byte[]{ 0xe1, ... };
-// GCMUtil.xor(v, R);
- tmp[0] ^= (byte)0xe1;
- }
- }
- }
-
- return c;
- }
-
- private static void shiftRight(byte[] block)
- {
- int i = 0;
- int bit = 0;
- for (;;)
- {
- int b = block[i] & 0xff;
- block[i] = (byte) ((b >>> 1) | bit);
- if (++i == 16)
- {
- break;
- }
- bit = (b & 1) << 7;
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/GCMTest.java b/core/src/test/java/org/bouncycastle/crypto/test/GCMTest.java
deleted file mode 100644
index b34cc4e9..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/GCMTest.java
+++ /dev/null
@@ -1,687 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.engines.AESFastEngine;
-import org.bouncycastle.crypto.engines.DESEngine;
-import org.bouncycastle.crypto.modes.GCMBlockCipher;
-import org.bouncycastle.crypto.modes.gcm.BasicGCMMultiplier;
-import org.bouncycastle.crypto.modes.gcm.GCMMultiplier;
-import org.bouncycastle.crypto.modes.gcm.Tables64kGCMMultiplier;
-import org.bouncycastle.crypto.modes.gcm.Tables8kGCMMultiplier;
-import org.bouncycastle.crypto.params.AEADParameters;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Times;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * Test vectors from "The Galois/Counter Mode of Operation (GCM)", McGrew/Viega, Appendix B
- */
-public class GCMTest
- extends SimpleTest
-{
- private static final String[][] TEST_VECTORS = new String[][] {
- {
- "Test Case 1",
- "00000000000000000000000000000000",
- "",
- "",
- "000000000000000000000000",
- "",
- "58e2fccefa7e3061367f1d57a4e7455a",
- },
- {
- "Test Case 2",
- "00000000000000000000000000000000",
- "00000000000000000000000000000000",
- "",
- "000000000000000000000000",
- "0388dace60b6a392f328c2b971b2fe78",
- "ab6e47d42cec13bdf53a67b21257bddf",
- },
- {
- "Test Case 3",
- "feffe9928665731c6d6a8f9467308308",
- "d9313225f88406e5a55909c5aff5269a"
- + "86a7a9531534f7da2e4c303d8a318a72"
- + "1c3c0c95956809532fcf0e2449a6b525"
- + "b16aedf5aa0de657ba637b391aafd255",
- "",
- "cafebabefacedbaddecaf888",
- "42831ec2217774244b7221b784d0d49c"
- + "e3aa212f2c02a4e035c17e2329aca12e"
- + "21d514b25466931c7d8f6a5aac84aa05"
- + "1ba30b396a0aac973d58e091473f5985",
- "4d5c2af327cd64a62cf35abd2ba6fab4",
- },
- {
- "Test Case 4",
- "feffe9928665731c6d6a8f9467308308",
- "d9313225f88406e5a55909c5aff5269a"
- + "86a7a9531534f7da2e4c303d8a318a72"
- + "1c3c0c95956809532fcf0e2449a6b525"
- + "b16aedf5aa0de657ba637b39",
- "feedfacedeadbeeffeedfacedeadbeef"
- + "abaddad2",
- "cafebabefacedbaddecaf888",
- "42831ec2217774244b7221b784d0d49c"
- + "e3aa212f2c02a4e035c17e2329aca12e"
- + "21d514b25466931c7d8f6a5aac84aa05"
- + "1ba30b396a0aac973d58e091",
- "5bc94fbc3221a5db94fae95ae7121a47",
- },
- {
- "Test Case 5",
- "feffe9928665731c6d6a8f9467308308",
- "d9313225f88406e5a55909c5aff5269a"
- + "86a7a9531534f7da2e4c303d8a318a72"
- + "1c3c0c95956809532fcf0e2449a6b525"
- + "b16aedf5aa0de657ba637b39",
- "feedfacedeadbeeffeedfacedeadbeef"
- + "abaddad2",
- "cafebabefacedbad",
- "61353b4c2806934a777ff51fa22a4755"
- + "699b2a714fcdc6f83766e5f97b6c7423"
- + "73806900e49f24b22b097544d4896b42"
- + "4989b5e1ebac0f07c23f4598",
- "3612d2e79e3b0785561be14aaca2fccb",
- },
- {
- "Test Case 6",
- "feffe9928665731c6d6a8f9467308308",
- "d9313225f88406e5a55909c5aff5269a"
- + "86a7a9531534f7da2e4c303d8a318a72"
- + "1c3c0c95956809532fcf0e2449a6b525"
- + "b16aedf5aa0de657ba637b39",
- "feedfacedeadbeeffeedfacedeadbeef"
- + "abaddad2",
- "9313225df88406e555909c5aff5269aa"
- + "6a7a9538534f7da1e4c303d2a318a728"
- + "c3c0c95156809539fcf0e2429a6b5254"
- + "16aedbf5a0de6a57a637b39b",
- "8ce24998625615b603a033aca13fb894"
- + "be9112a5c3a211a8ba262a3cca7e2ca7"
- + "01e4a9a4fba43c90ccdcb281d48c7c6f"
- + "d62875d2aca417034c34aee5",
- "619cc5aefffe0bfa462af43c1699d050",
- },
- {
- "Test Case 7",
- "00000000000000000000000000000000"
- + "0000000000000000",
- "",
- "",
- "000000000000000000000000",
- "",
- "cd33b28ac773f74ba00ed1f312572435",
- },
- {
- "Test Case 8",
- "00000000000000000000000000000000"
- + "0000000000000000",
- "00000000000000000000000000000000",
- "",
- "000000000000000000000000",
- "98e7247c07f0fe411c267e4384b0f600",
- "2ff58d80033927ab8ef4d4587514f0fb",
- },
- {
- "Test Case 9",
- "feffe9928665731c6d6a8f9467308308"
- + "feffe9928665731c",
- "d9313225f88406e5a55909c5aff5269a"
- + "86a7a9531534f7da2e4c303d8a318a72"
- + "1c3c0c95956809532fcf0e2449a6b525"
- + "b16aedf5aa0de657ba637b391aafd255",
- "",
- "cafebabefacedbaddecaf888",
- "3980ca0b3c00e841eb06fac4872a2757"
- + "859e1ceaa6efd984628593b40ca1e19c"
- + "7d773d00c144c525ac619d18c84a3f47"
- + "18e2448b2fe324d9ccda2710acade256",
- "9924a7c8587336bfb118024db8674a14",
- },
- {
- "Test Case 10",
- "feffe9928665731c6d6a8f9467308308"
- + "feffe9928665731c",
- "d9313225f88406e5a55909c5aff5269a"
- + "86a7a9531534f7da2e4c303d8a318a72"
- + "1c3c0c95956809532fcf0e2449a6b525"
- + "b16aedf5aa0de657ba637b39",
- "feedfacedeadbeeffeedfacedeadbeef"
- + "abaddad2",
- "cafebabefacedbaddecaf888",
- "3980ca0b3c00e841eb06fac4872a2757"
- + "859e1ceaa6efd984628593b40ca1e19c"
- + "7d773d00c144c525ac619d18c84a3f47"
- + "18e2448b2fe324d9ccda2710",
- "2519498e80f1478f37ba55bd6d27618c",
- },
- {
- "Test Case 11",
- "feffe9928665731c6d6a8f9467308308"
- + "feffe9928665731c",
- "d9313225f88406e5a55909c5aff5269a"
- + "86a7a9531534f7da2e4c303d8a318a72"
- + "1c3c0c95956809532fcf0e2449a6b525"
- + "b16aedf5aa0de657ba637b39",
- "feedfacedeadbeeffeedfacedeadbeef"
- + "abaddad2",
- "cafebabefacedbad",
- "0f10f599ae14a154ed24b36e25324db8"
- + "c566632ef2bbb34f8347280fc4507057"
- + "fddc29df9a471f75c66541d4d4dad1c9"
- + "e93a19a58e8b473fa0f062f7",
- "65dcc57fcf623a24094fcca40d3533f8",
- },
- {
- "Test Case 12",
- "feffe9928665731c6d6a8f9467308308"
- + "feffe9928665731c",
- "d9313225f88406e5a55909c5aff5269a"
- + "86a7a9531534f7da2e4c303d8a318a72"
- + "1c3c0c95956809532fcf0e2449a6b525"
- + "b16aedf5aa0de657ba637b39",
- "feedfacedeadbeeffeedfacedeadbeef"
- + "abaddad2",
- "9313225df88406e555909c5aff5269aa"
- + "6a7a9538534f7da1e4c303d2a318a728"
- + "c3c0c95156809539fcf0e2429a6b5254"
- + "16aedbf5a0de6a57a637b39b",
- "d27e88681ce3243c4830165a8fdcf9ff"
- + "1de9a1d8e6b447ef6ef7b79828666e45"
- + "81e79012af34ddd9e2f037589b292db3"
- + "e67c036745fa22e7e9b7373b",
- "dcf566ff291c25bbb8568fc3d376a6d9",
- },
- {
- "Test Case 13",
- "00000000000000000000000000000000"
- + "00000000000000000000000000000000",
- "",
- "",
- "000000000000000000000000",
- "",
- "530f8afbc74536b9a963b4f1c4cb738b",
- },
- {
- "Test Case 14",
- "00000000000000000000000000000000"
- + "00000000000000000000000000000000",
- "00000000000000000000000000000000",
- "",
- "000000000000000000000000",
- "cea7403d4d606b6e074ec5d3baf39d18",
- "d0d1c8a799996bf0265b98b5d48ab919",
- },
- {
- "Test Case 15",
- "feffe9928665731c6d6a8f9467308308"
- + "feffe9928665731c6d6a8f9467308308",
- "d9313225f88406e5a55909c5aff5269a"
- + "86a7a9531534f7da2e4c303d8a318a72"
- + "1c3c0c95956809532fcf0e2449a6b525"
- + "b16aedf5aa0de657ba637b391aafd255",
- "",
- "cafebabefacedbaddecaf888",
- "522dc1f099567d07f47f37a32a84427d"
- + "643a8cdcbfe5c0c97598a2bd2555d1aa"
- + "8cb08e48590dbb3da7b08b1056828838"
- + "c5f61e6393ba7a0abcc9f662898015ad",
- "b094dac5d93471bdec1a502270e3cc6c",
- },
- {
- "Test Case 16",
- "feffe9928665731c6d6a8f9467308308"
- + "feffe9928665731c6d6a8f9467308308",
- "d9313225f88406e5a55909c5aff5269a"
- + "86a7a9531534f7da2e4c303d8a318a72"
- + "1c3c0c95956809532fcf0e2449a6b525"
- + "b16aedf5aa0de657ba637b39",
- "feedfacedeadbeeffeedfacedeadbeef"
- + "abaddad2",
- "cafebabefacedbaddecaf888",
- "522dc1f099567d07f47f37a32a84427d"
- + "643a8cdcbfe5c0c97598a2bd2555d1aa"
- + "8cb08e48590dbb3da7b08b1056828838"
- + "c5f61e6393ba7a0abcc9f662",
- "76fc6ece0f4e1768cddf8853bb2d551b",
- },
- {
- "Test Case 17",
- "feffe9928665731c6d6a8f9467308308"
- + "feffe9928665731c6d6a8f9467308308",
- "d9313225f88406e5a55909c5aff5269a"
- + "86a7a9531534f7da2e4c303d8a318a72"
- + "1c3c0c95956809532fcf0e2449a6b525"
- + "b16aedf5aa0de657ba637b39",
- "feedfacedeadbeeffeedfacedeadbeef"
- + "abaddad2",
- "cafebabefacedbad",
- "c3762df1ca787d32ae47c13bf19844cb"
- + "af1ae14d0b976afac52ff7d79bba9de0"
- + "feb582d33934a4f0954cc2363bc73f78"
- + "62ac430e64abe499f47c9b1f",
- "3a337dbf46a792c45e454913fe2ea8f2",
- },
- {
- "Test Case 18",
- "feffe9928665731c6d6a8f9467308308"
- + "feffe9928665731c6d6a8f9467308308",
- "d9313225f88406e5a55909c5aff5269a"
- + "86a7a9531534f7da2e4c303d8a318a72"
- + "1c3c0c95956809532fcf0e2449a6b525"
- + "b16aedf5aa0de657ba637b39",
- "feedfacedeadbeeffeedfacedeadbeef"
- + "abaddad2",
- "9313225df88406e555909c5aff5269aa"
- + "6a7a9538534f7da1e4c303d2a318a728"
- + "c3c0c95156809539fcf0e2429a6b5254"
- + "16aedbf5a0de6a57a637b39b",
- "5a8def2f0c9e53f1f75d7853659e2a20"
- + "eeb2b22aafde6419a058ab4f6f746bf4"
- + "0fc0c3b780f244452da3ebf1c5d82cde"
- + "a2418997200ef82e44ae7e3f",
- "a44a8266ee1c8eb0c8b5d4cf5ae9f19a",
- },
- };
-
- public String getName()
- {
- return "GCM";
- }
-
- public void performTest() throws Exception
- {
- for (int i = 0; i < TEST_VECTORS.length; ++i)
- {
- runTestCase(TEST_VECTORS[i]);
- }
-
- randomTests();
- outputSizeTests();
- testExceptions();
- }
-
- protected BlockCipher createAESEngine()
- {
- return new AESFastEngine();
- }
-
- private void testExceptions() throws InvalidCipherTextException
- {
- GCMBlockCipher gcm = new GCMBlockCipher(createAESEngine());
-
- try
- {
- gcm = new GCMBlockCipher(new DESEngine());
-
- fail("incorrect block size not picked up");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- try
- {
- gcm.init(false, new KeyParameter(new byte[16]));
-
- fail("illegal argument not picked up");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- AEADTestUtil.testReset(this, new GCMBlockCipher(createAESEngine()), new GCMBlockCipher(createAESEngine()), new AEADParameters(new KeyParameter(new byte[16]), 128, new byte[16]));
- AEADTestUtil.testTampering(this, gcm, new AEADParameters(new KeyParameter(new byte[16]), 128, new byte[16]));
- AEADTestUtil.testOutputSizes(this, new GCMBlockCipher(createAESEngine()), new AEADParameters(new KeyParameter(
- new byte[16]), 128, new byte[16]));
- AEADTestUtil.testBufferSizeChecks(this, new GCMBlockCipher(createAESEngine()), new AEADParameters(
- new KeyParameter(new byte[16]), 128, new byte[16]));
- }
-
- private void runTestCase(String[] testVector)
- throws InvalidCipherTextException
- {
- for (int macLength = 12; macLength <= 16; ++macLength)
- {
- runTestCase(testVector, macLength);
- }
- }
-
- private void runTestCase(String[] testVector, int macLength)
- throws InvalidCipherTextException
- {
- int pos = 0;
- String testName = testVector[pos++];
- byte[] K = Hex.decode(testVector[pos++]);
- byte[] P = Hex.decode(testVector[pos++]);
- byte[] A = Hex.decode(testVector[pos++]);
- byte[] IV = Hex.decode(testVector[pos++]);
- byte[] C = Hex.decode(testVector[pos++]);
-
- // For short MAC, take leading bytes
- byte[] t = Hex.decode(testVector[pos++]);
- byte[] T = new byte[macLength];
- System.arraycopy(t, 0, T, 0, T.length);
-
- // Default multiplier
- runTestCase(null, null, testName, K, IV, A, P, C, T);
-
- runTestCase(new BasicGCMMultiplier(), new BasicGCMMultiplier(), testName, K, IV, A, P, C, T);
- runTestCase(new Tables8kGCMMultiplier(), new Tables8kGCMMultiplier(), testName, K, IV, A, P, C, T);
- runTestCase(new Tables64kGCMMultiplier(), new Tables64kGCMMultiplier(), testName, K, IV, A, P, C, T);
- }
-
- private void runTestCase(
- GCMMultiplier encM,
- GCMMultiplier decM,
- String testName,
- byte[] K,
- byte[] IV,
- byte[] A,
- byte[] P,
- byte[] C,
- byte[] T)
- throws InvalidCipherTextException
- {
- byte[] fa = new byte[A.length / 2];
- byte[] la = new byte[A.length - (A.length / 2)];
- System.arraycopy(A, 0, fa, 0, fa.length);
- System.arraycopy(A, fa.length, la, 0, la.length);
-
- runTestCase(encM, decM, testName + " all initial associated data", K, IV, A, null, P, C, T);
- runTestCase(encM, decM, testName + " all subsequent associated data", K, IV, null, A, P, C, T);
- runTestCase(encM, decM, testName + " split associated data", K, IV, fa, la, P, C, T);
- }
-
- private void runTestCase(
- GCMMultiplier encM,
- GCMMultiplier decM,
- String testName,
- byte[] K,
- byte[] IV,
- byte[] A,
- byte[] SA,
- byte[] P,
- byte[] C,
- byte[] T)
- throws InvalidCipherTextException
- {
- AEADParameters parameters = new AEADParameters(new KeyParameter(K), T.length * 8, IV, A);
- GCMBlockCipher encCipher = initCipher(encM, true, parameters);
- GCMBlockCipher decCipher = initCipher(decM, false, parameters);
- checkTestCase(encCipher, decCipher, testName, SA, P, C, T);
- checkTestCase(encCipher, decCipher, testName + " (reused)", SA, P, C, T);
-
- // Key reuse
- AEADParameters keyReuseParams = AEADTestUtil.reuseKey(parameters);
- encCipher.init(true, keyReuseParams);
- decCipher.init(false, keyReuseParams);
- checkTestCase(encCipher, decCipher, testName + " (key reuse)", SA, P, C, T);
- }
-
- private GCMBlockCipher initCipher(GCMMultiplier m, boolean forEncryption, AEADParameters parameters)
- {
- GCMBlockCipher c = new GCMBlockCipher(createAESEngine(), m);
- c.init(forEncryption, parameters);
- return c;
- }
-
- private void checkTestCase(
- GCMBlockCipher encCipher,
- GCMBlockCipher decCipher,
- String testName,
- byte[] SA,
- byte[] P,
- byte[] C,
- byte[] T)
- throws InvalidCipherTextException
- {
- byte[] enc = new byte[encCipher.getOutputSize(P.length)];
- if (SA != null)
- {
- encCipher.processAADBytes(SA, 0, SA.length);
- }
- int len = encCipher.processBytes(P, 0, P.length, enc, 0);
- len += encCipher.doFinal(enc, len);
-
- if (enc.length != len)
- {
-// System.out.println("" + enc.length + "/" + len);
- fail("encryption reported incorrect length: " + testName);
- }
-
- byte[] mac = encCipher.getMac();
-
- byte[] data = new byte[P.length];
- System.arraycopy(enc, 0, data, 0, data.length);
- byte[] tail = new byte[enc.length - P.length];
- System.arraycopy(enc, P.length, tail, 0, tail.length);
-
- if (!areEqual(C, data))
- {
- fail("incorrect encrypt in: " + testName);
- }
-
- if (!areEqual(T, mac))
- {
- fail("getMac() returned wrong mac in: " + testName);
- }
-
- if (!areEqual(T, tail))
- {
- fail("stream contained wrong mac in: " + testName);
- }
-
- byte[] dec = new byte[decCipher.getOutputSize(enc.length)];
- if (SA != null)
- {
- decCipher.processAADBytes(SA, 0, SA.length);
- }
- len = decCipher.processBytes(enc, 0, enc.length, dec, 0);
- len += decCipher.doFinal(dec, len);
- mac = decCipher.getMac();
-
- data = new byte[C.length];
- System.arraycopy(dec, 0, data, 0, data.length);
-
- if (!areEqual(P, data))
- {
- fail("incorrect decrypt in: " + testName);
- }
- }
-
- private void randomTests()
- throws InvalidCipherTextException
- {
- SecureRandom srng = new SecureRandom();
- srng.setSeed(Times.nanoTime());
- randomTests(srng, null);
- randomTests(srng, new BasicGCMMultiplier());
- randomTests(srng, new Tables8kGCMMultiplier());
- randomTests(srng, new Tables64kGCMMultiplier());
- }
-
- private void randomTests(SecureRandom srng, GCMMultiplier m)
- throws InvalidCipherTextException
- {
- for (int i = 0; i < 10; ++i)
- {
- randomTest(srng, m);
- }
- }
-
- private void randomTest(SecureRandom srng, GCMMultiplier m)
- throws InvalidCipherTextException
- {
- int kLength = 16 + 8 * (Math.abs(srng.nextInt()) % 3);
- byte[] K = new byte[kLength];
- srng.nextBytes(K);
-
- int pLength = srng.nextInt() >>> 16;
- byte[] P = new byte[pLength];
- srng.nextBytes(P);
-
- int aLength = srng.nextInt() >>> 24;
- byte[] A = new byte[aLength];
- srng.nextBytes(A);
-
- int saLength = srng.nextInt() >>> 24;
- byte[] SA = new byte[saLength];
- srng.nextBytes(SA);
-
- int ivLength = 1 + (srng.nextInt() >>> 24);
- byte[] IV = new byte[ivLength];
- srng.nextBytes(IV);
-
- AEADParameters parameters = new AEADParameters(new KeyParameter(K), 16 * 8, IV, A);
- GCMBlockCipher cipher = initCipher(m, true, parameters);
- byte[] C = new byte[cipher.getOutputSize(P.length)];
- int predicted = cipher.getUpdateOutputSize(P.length);
-
- int split = nextInt(srng, SA.length + 1);
- cipher.processAADBytes(SA, 0, split);
- int len = cipher.processBytes(P, 0, P.length, C, 0);
- cipher.processAADBytes(SA, split, SA.length - split);
-
- if (predicted != len)
- {
- fail("encryption reported incorrect update length in randomised test");
- }
-
- len += cipher.doFinal(C, len);
-
- if (C.length != len)
- {
- fail("encryption reported incorrect length in randomised test");
- }
-
- byte[] encT = cipher.getMac();
- byte[] tail = new byte[C.length - P.length];
- System.arraycopy(C, P.length, tail, 0, tail.length);
-
- if (!areEqual(encT, tail))
- {
- fail("stream contained wrong mac in randomised test");
- }
-
- cipher.init(false, parameters);
- byte[] decP = new byte[cipher.getOutputSize(C.length)];
- predicted = cipher.getUpdateOutputSize(C.length);
-
- split = nextInt(srng, SA.length + 1);
- cipher.processAADBytes(SA, 0, split);
- len = cipher.processBytes(C, 0, C.length, decP, 0);
- cipher.processAADBytes(SA, split, SA.length - split);
-
- if (predicted != len)
- {
- fail("decryption reported incorrect update length in randomised test");
- }
-
- len += cipher.doFinal(decP, len);
-
- if (!areEqual(P, decP))
- {
- fail("incorrect decrypt in randomised test");
- }
-
- byte[] decT = cipher.getMac();
- if (!areEqual(encT, decT))
- {
- fail("decryption produced different mac from encryption");
- }
-
- //
- // key reuse test
- //
- cipher.init(false, AEADTestUtil.reuseKey(parameters));
- decP = new byte[cipher.getOutputSize(C.length)];
-
- split = nextInt(srng, SA.length + 1);
- cipher.processAADBytes(SA, 0, split);
- len = cipher.processBytes(C, 0, C.length, decP, 0);
- cipher.processAADBytes(SA, split, SA.length - split);
-
- len += cipher.doFinal(decP, len);
-
- if (!areEqual(P, decP))
- {
- fail("incorrect decrypt in randomised test");
- }
-
- decT = cipher.getMac();
- if (!areEqual(encT, decT))
- {
- fail("decryption produced different mac from encryption");
- }
- }
-
- private void outputSizeTests()
- {
- byte[] K = new byte[16];
- byte[] A = null;
- byte[] IV = new byte[16];
-
- AEADParameters parameters = new AEADParameters(new KeyParameter(K), 16 * 8, IV, A);
- GCMBlockCipher cipher = initCipher(null, true, parameters);
-
- if (cipher.getUpdateOutputSize(0) != 0)
- {
- fail("incorrect getUpdateOutputSize for initial 0 bytes encryption");
- }
-
- if (cipher.getOutputSize(0) != 16)
- {
- fail("incorrect getOutputSize for initial 0 bytes encryption");
- }
-
- cipher.init(false, parameters);
-
- if (cipher.getUpdateOutputSize(0) != 0)
- {
- fail("incorrect getUpdateOutputSize for initial 0 bytes decryption");
- }
-
- // NOTE: 0 bytes would be truncated data, but we want it to fail in the doFinal, not here
- if (cipher.getOutputSize(0) != 0)
- {
- fail("fragile getOutputSize for initial 0 bytes decryption");
- }
-
- if (cipher.getOutputSize(16) != 0)
- {
- fail("incorrect getOutputSize for initial MAC-size bytes decryption");
- }
- }
-
- private static int nextInt(SecureRandom rand, int n)
- {
- if ((n & -n) == n) // i.e., n is a power of 2
- {
- return (int)((n * (long)(rand.nextInt() >>> 1)) >> 31);
- }
-
- int bits, value;
- do
- {
- bits = rand.nextInt() >>> 1;
- value = bits % n;
- }
- while (bits - value + (n - 1) < 0);
-
- return value;
- }
-
- public static void main(String[] args)
- {
- runTest(new GCMTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/GMacTest.java b/core/src/test/java/org/bouncycastle/crypto/test/GMacTest.java
deleted file mode 100644
index 082aac61..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/GMacTest.java
+++ /dev/null
@@ -1,174 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.engines.AESFastEngine;
-import org.bouncycastle.crypto.macs.GMac;
-import org.bouncycastle.crypto.modes.GCMBlockCipher;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * Test vectors for AES-GMAC, extracted from <a
- * href="http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip">NIST CAVP GCM test
- * vectors</a>.
- *
- */
-public class GMacTest extends SimpleTest
-{
- private static class TestCase
- {
- private byte[] key;
- private byte[] iv;
- private byte[] ad;
- private byte[] tag;
- private String name;
-
- private TestCase(final String name, final String key, final String iv, final String ad, final String tag)
- {
- this.name = name;
- this.key = Hex.decode(key);
- this.iv = Hex.decode(iv);
- this.ad = Hex.decode(ad);
- this.tag = Hex.decode(tag);
- }
-
- public String getName()
- {
- return name;
- }
-
- public byte[] getKey()
- {
- return key;
- }
-
- public byte[] getIv()
- {
- return iv;
- }
-
- public byte[] getAd()
- {
- return ad;
- }
-
- public byte[] getTag()
- {
- return tag;
- }
- }
-
- private static TestCase[] TEST_VECTORS = new TestCase[] {
- // Count = 0, from each of the PTlen = 0 test vector sequences
- new TestCase("128/96/0/128", "11754cd72aec309bf52f7687212e8957", "3c819d9a9bed087615030b65", "",
- "250327c674aaf477aef2675748cf6971"),
- new TestCase("128/96/0/120", "272f16edb81a7abbea887357a58c1917", "794ec588176c703d3d2a7a07", "",
- "b6e6f197168f5049aeda32dafbdaeb"),
- new TestCase("128/96/0/112", "81b6844aab6a568c4556a2eb7eae752f", "ce600f59618315a6829bef4d", "",
- "89b43e9dbc1b4f597dbbc7655bb5"),
- new TestCase("128/96/0/104", "cde2f9a9b1a004165ef9dc981f18651b", "29512c29566c7322e1e33e8e", "",
- "2e58ce7dabd107c82759c66a75"),
- new TestCase("128/96/0/96", "b01e45cc3088aaba9fa43d81d481823f", "5a2c4a66468713456a4bd5e1", "",
- "014280f944f53c681164b2ff"),
-
- new TestCase("128/96/128/128", "77be63708971c4e240d1cb79e8d77feb", "e0e00f19fed7ba0136a797f3",
- "7a43ec1d9c0a5a78a0b16533a6213cab", "209fcc8d3675ed938e9c7166709dd946"),
- new TestCase("128/96/128/96", "bea48ae4980d27f357611014d4486625", "32bddb5c3aa998a08556454c",
- "8a50b0b8c7654bced884f7f3afda2ead", "8e0f6d8bf05ffebe6f500eb1"),
-
- new TestCase("128/96/384/128", "99e3e8793e686e571d8285c564f75e2b", "c2dd0ab868da6aa8ad9c0d23",
- "b668e42d4e444ca8b23cfdd95a9fedd5178aa521144890b093733cf5cf22526c5917ee476541809ac6867a8c399309fc",
- "3f4fba100eaf1f34b0baadaae9995d85"),
- new TestCase("128/96/384/96", "c77acd1b0918e87053cb3e51651e7013", "39ff857a81745d10f718ac00",
- "407992f82ea23b56875d9a3cb843ceb83fd27cb954f7c5534d58539fe96fb534502a1b38ea4fac134db0a42de4be1137",
- "2a5dc173285375dc82835876"),
-
- new TestCase(
- "128/1024/0/128",
- "d0f1f4defa1e8c08b4b26d576392027c",
- "42b4f01eb9f5a1ea5b1eb73b0fb0baed54f387ecaa0393c7d7dffc6af50146ecc021abf7eb9038d4303d91f8d741a11743166c0860208bcc02c6258fd9511a2fa626f96d60b72fcff773af4e88e7a923506e4916ecbd814651e9f445adef4ad6a6b6c7290cc13b956130eef5b837c939fcac0cbbcc9656cd75b13823ee5acdac",
- "", "7ab49b57ddf5f62c427950111c5c4f0d"),
- new TestCase(
- "128/1024/384/96",
- "3cce72d37933394a8cac8a82deada8f0",
- "aa2f0d676d705d9733c434e481972d4888129cf7ea55c66511b9c0d25a92a174b1e28aa072f27d4de82302828955aadcb817c4907361869bd657b45ff4a6f323871987fcf9413b0702d46667380cd493ed24331a28b9ce5bbfa82d3a6e7679fcce81254ba64abcad14fd18b22c560a9d2c1cd1d3c42dac44c683edf92aced894",
- "5686b458e9c176f4de8428d9ebd8e12f569d1c7595cf49a4b0654ab194409f86c0dd3fdb8eb18033bb4338c70f0b97d1",
- "a3a9444b21f330c3df64c8b6"), };
-
- public void performTest()
- {
- for (int i = 0; i < TEST_VECTORS.length; i++)
- {
- TestCase testCase = TEST_VECTORS[i];
-
- Mac mac = new GMac(new GCMBlockCipher(new AESFastEngine()), testCase.getTag().length * 8);
- CipherParameters key = new KeyParameter(testCase.getKey());
- mac.init(new ParametersWithIV(key, testCase.getIv()));
-
- testSingleByte(mac, testCase);
- testMultibyte(mac, testCase);
- }
-
- // Invalid mac size
- testInvalidMacSize(97);
- testInvalidMacSize(136);
- testInvalidMacSize(24);
- }
-
- private void testInvalidMacSize(int size)
- {
- try
- {
- GMac mac = new GMac(new GCMBlockCipher(new AESFastEngine()), size);
- mac.init(new ParametersWithIV(null, new byte[16]));
- fail("Expected failure for illegal mac size " + size);
- }
- catch (IllegalArgumentException e)
- {
- if (!e.getMessage().startsWith("Invalid value for MAC size"))
- {
- fail("Illegal mac size failed with unexpected message");
- }
- }
- }
-
- private void testMultibyte(Mac mac, TestCase testCase)
- {
- mac.update(testCase.getAd(), 0, testCase.getAd().length);
- checkMac(mac, testCase);
- }
-
- private void testSingleByte(Mac mac, TestCase testCase)
- {
- final byte[] ad = testCase.getAd();
- for (int i = 0; i < ad.length; i++)
- {
- mac.update(ad[i]);
- }
- checkMac(mac, testCase);
- }
-
- private void checkMac(Mac mac, TestCase testCase)
- {
- final byte[] generatedMac = new byte[mac.getMacSize()];
- mac.doFinal(generatedMac, 0);
- if (!areEqual(testCase.getTag(), generatedMac))
- {
- fail("Failed " + testCase.getName() + " - expected " + new String(Hex.encode(testCase.getTag())) + " got "
- + new String(Hex.encode(generatedMac)));
- }
- }
-
- public String getName()
- {
- return "GMac";
- }
-
- public static void main(String[] args)
- {
- runTest(new GMacTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/GOST28147MacTest.java b/core/src/test/java/org/bouncycastle/crypto/test/GOST28147MacTest.java
deleted file mode 100644
index 8faaca1a..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/GOST28147MacTest.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.engines.GOST28147Engine;
-import org.bouncycastle.crypto.macs.GOST28147Mac;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithSBox;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-/**
- * GOST 28147 MAC tester
- */
-public class GOST28147MacTest
- implements Test
-{
- //
- // these GOSTMac for testing.
- //
- static byte[] gkeyBytes1 = Hex.decode("6d145dc993f4019e104280df6fcd8cd8e01e101e4c113d7ec4f469ce6dcd9e49");
- static byte[] gkeyBytes2 = Hex.decode("6d145dc993f4019e104280df6fcd8cd8e01e101e4c113d7ec4f469ce6dcd9e49");
-
- static byte[] input3 = Hex.decode("7768617420646f2079612077616e7420666f72206e6f7468696e673f");
- static byte[] input4 = Hex.decode("7768617420646f2079612077616e7420666f72206e6f7468696e673f");
-
- static byte[] output7 = Hex.decode("93468a46");
- static byte[] output8 = Hex.decode("93468a46");
-
- public GOST28147MacTest()
- {
- }
-
- public TestResult perform()
- {
- // test1
- Mac mac = new GOST28147Mac();
- KeyParameter key = new KeyParameter(gkeyBytes1);
-
- mac.init(key);
-
- mac.update(input3, 0, input3.length);
-
- byte[] out = new byte[4];
-
- mac.doFinal(out, 0);
-
- if (!Arrays.areEqual(out, output7))
- {
- return new SimpleTestResult(false, getName() + ": Failed test 1 - expected " + new String(Hex.encode(output7)) + " got " + new String(Hex.encode(out)));
- }
-
- // test2
- key = new KeyParameter(gkeyBytes2);
-
- ParametersWithSBox gparam = new ParametersWithSBox(key, GOST28147Engine.getSBox("E-A"));
-
- mac.init(gparam);
-
- mac.update(input4, 0, input4.length);
-
- out = new byte[4];
-
- mac.doFinal(out, 0);
-
- if (!Arrays.areEqual(out, output8))
- {
- return new SimpleTestResult(false, getName() + ": Failed test 2 - expected " + new String(Hex.encode(output8)) + " got " + new String(Hex.encode(out)));
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
-
- public String getName()
- {
- return "GOST28147Mac";
- }
-
- public static void main(
- String[] args)
- {
- GOST28147MacTest test = new GOST28147MacTest();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/GOST28147Test.java b/core/src/test/java/org/bouncycastle/crypto/test/GOST28147Test.java
deleted file mode 100644
index 8de84406..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/GOST28147Test.java
+++ /dev/null
@@ -1,328 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.BufferedBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.digests.GOST3411Digest;
-import org.bouncycastle.crypto.engines.GOST28147Engine;
-import org.bouncycastle.crypto.modes.CBCBlockCipher;
-import org.bouncycastle.crypto.modes.CFBBlockCipher;
-import org.bouncycastle.crypto.modes.GOFBBlockCipher;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.crypto.params.ParametersWithSBox;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class GOST28147Test
- extends CipherTest
-{
- static String input1 = "0000000000000000";
- static String output1 = "1b0bbc32cebcab42";
- static String input2 = "bc350e71aac5f5c2";
- static String output2 = "d35ab653493b49f5";
- static String input3 = "bc350e71aa11345709acde";
- static String output3 = "8824c124c4fd14301fb1e8";
- static String input4 = "000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f";
- static String output4 = "29b7083e0a6d955ca0ec5b04fdb4ea41949f1dd2efdf17baffc1780b031f3934";
-
- static byte TestSBox[] = {
- 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF,
- 0xF,0xE,0xD,0xC,0xB,0xA,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0,
- 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF,
- 0xF,0xE,0xD,0xC,0xB,0xA,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0,
- 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF,
- 0xF,0xE,0xD,0xC,0xB,0xA,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0,
- 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF,
- 0xF,0xE,0xD,0xC,0xB,0xA,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0
- };
-
- static SimpleTest[] tests =
- { new BlockCipherVectorTest(1, new GOST28147Engine(),
- new KeyParameter(Hex.decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")),
- input1, output1),
- new BlockCipherVectorTest(2, new CBCBlockCipher(new GOST28147Engine()),
- new ParametersWithIV(new KeyParameter(Hex.decode("00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF")),
- Hex.decode("1234567890abcdef")), input2, output2),
- new BlockCipherVectorTest(3, new GOFBBlockCipher(new GOST28147Engine()),
- new ParametersWithIV(new KeyParameter(Hex.decode("0011223344556677889900112233445566778899001122334455667788990011")),
- Hex.decode("1234567890abcdef")), //IV
- input3, output3),
- new BlockCipherVectorTest(4, new CFBBlockCipher(new GOST28147Engine(), 64),
- new ParametersWithIV(new KeyParameter(Hex.decode("aafd12f659cae63489b479e5076ddec2f06cb58faafd12f659cae63489b479e5")),
- Hex.decode("aafd12f659cae634")), input4, output4),
-
- //tests with parameters, set S-box.
- new BlockCipherVectorTest(5, new GOST28147Engine(),
- new KeyParameter(Hex.decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")),//key , default parameter S-box set to D-Test
- input1, output1),
- new BlockCipherVectorTest(6, new CFBBlockCipher(new GOST28147Engine(), 64),
- new ParametersWithIV(
- new ParametersWithSBox(
- new KeyParameter(Hex.decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
- GOST28147Engine.getSBox("D-Test")), //type S-box
- Hex.decode("1234567890abcdef")), //IV
- "0000000000000000", //input message
- "b587f7a0814c911d"), //encrypt message
- new BlockCipherVectorTest(7, new CFBBlockCipher(new GOST28147Engine(), 64),
- new ParametersWithIV(
- new ParametersWithSBox(
- new KeyParameter(Hex.decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
- GOST28147Engine.getSBox("E-Test")), //type S-box
- Hex.decode("1234567890abcdef")), //IV
- "0000000000000000", //input message
- "e8287f53f991d52b"), //encrypt message
- new BlockCipherVectorTest(8, new CFBBlockCipher(new GOST28147Engine(), 64),
- new ParametersWithIV(
- new ParametersWithSBox(
- new KeyParameter(Hex.decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
- GOST28147Engine.getSBox("E-A")), //type S-box
- Hex.decode("1234567890abcdef")), //IV
- "0000000000000000", //input message
- "c41009dba22ebe35"), //encrypt message
- new BlockCipherVectorTest(9, new CFBBlockCipher(new GOST28147Engine(), 8),
- new ParametersWithIV(
- new ParametersWithSBox(
- new KeyParameter(Hex.decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
- GOST28147Engine.getSBox("E-B")), //type S-box
- Hex.decode("1234567890abcdef")), //IV
- "0000000000000000", //input message
- "80d8723fcd3aba28"), //encrypt message
- new BlockCipherVectorTest(10, new CFBBlockCipher(new GOST28147Engine(), 8),
- new ParametersWithIV(
- new ParametersWithSBox(
- new KeyParameter(Hex.decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
- GOST28147Engine.getSBox("E-C")), //type S-box
- Hex.decode("1234567890abcdef")), //IV
- "0000000000000000", //input message
- "739f6f95068499b5"), //encrypt message
- new BlockCipherVectorTest(11, new CFBBlockCipher(new GOST28147Engine(), 8),
- new ParametersWithIV(
- new ParametersWithSBox(
- new KeyParameter(Hex.decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
- GOST28147Engine.getSBox("E-D")), //type S-box
- Hex.decode("1234567890abcdef")), //IV
- "0000000000000000", //input message
- "4663f720f4340f57"), //encrypt message
- new BlockCipherVectorTest(12, new CFBBlockCipher(new GOST28147Engine(), 8),
- new ParametersWithIV(
- new ParametersWithSBox(
- new KeyParameter(Hex.decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
- GOST28147Engine.getSBox("D-A")), //type S-box
- Hex.decode("1234567890abcdef")), //IV
- "0000000000000000", //input message
- "5bb0a31d218ed564"), //encrypt message
- new BlockCipherVectorTest(13, new CFBBlockCipher(new GOST28147Engine(), 8),
- new ParametersWithIV(
- new ParametersWithSBox(
- new KeyParameter(Hex.decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
- TestSBox), //set own S-box
- Hex.decode("1234567890abcdef")), //IV
- "0000000000000000", //input message
- "c3af96ef788667c5"), //encrypt message
- new BlockCipherVectorTest(14, new GOFBBlockCipher(new GOST28147Engine()),
- new ParametersWithIV(
- new ParametersWithSBox(
- new KeyParameter(Hex.decode("4ef72b778f0b0bebeef4f077551cb74a927b470ad7d7f2513454569a247e989d")), //key
- GOST28147Engine.getSBox("E-A")), //type S-box
- Hex.decode("1234567890abcdef")), //IV
- "bc350e71aa11345709acde", //input message
- "1bcc2282707c676fb656dc"), //encrypt message
-
- };
-
- static private final int GOST28147_KEY_LENGTH = 32;
-
- private byte[] generateKey(byte[] startkey)
- {
- byte[] newKey = new byte[GOST28147_KEY_LENGTH];
-
- GOST3411Digest digest = new GOST3411Digest();
-
- digest.update(startkey, 0, startkey.length);
- digest.doFinal(newKey, 0);
-
- return newKey;
- }
-
- GOST28147Test()
- {
- super(tests, new GOST28147Engine(), new KeyParameter(new byte[32]));
- }
-
- public void performTest()
- throws Exception
- {
- super.performTest();
-
- //advanced tests with GOST28147KeyGenerator:
- //encrypt on hesh message; ECB mode:
- byte[] in = Hex.decode("4e6f77206973207468652074696d6520666f7220616c6c20");
- byte[] output = Hex.decode("8ad3c8f56b27ff1fbd46409359bdc796bc350e71aac5f5c0");
- byte[] out = new byte[in.length];
-
- byte[] key = generateKey(Hex.decode("0123456789abcdef")); //!!! heshing start_key - get 256 bits !!!
-// System.out.println(new String(Hex.encode(key)));
- CipherParameters param = new ParametersWithSBox(new KeyParameter(key), GOST28147Engine.getSBox("E-A"));
- //CipherParameters param = new GOST28147Parameters(key,"D-Test");
- BufferedBlockCipher cipher = new BufferedBlockCipher(new GOST28147Engine());
-
- cipher.init(true, param);
- int len1 = cipher.processBytes(in, 0, in.length, out, 0);
- try
- {
- cipher.doFinal(out, len1);
- }
- catch (CryptoException e)
- {
- fail("failed - exception " + e.toString(), e);
- }
- if (out.length != output.length)
- {
- fail("failed - "
- + "expected " + new String(Hex.encode(output)) + " got "
- + new String(Hex.encode(out)));
- }
- for (int i = 0; i != out.length; i++)
- {
- if (out[i] != output[i])
- {
- fail("failed - " + "expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
- }
- }
-
-
- //encrypt on hesh message; CFB mode:
- in = Hex.decode("bc350e71aac5f5c2");
- output = Hex.decode("0ebbbafcf38f14a5");
- out = new byte[in.length];
-
- key = generateKey(Hex.decode("0123456789abcdef")); //!!! heshing start_key - get 256 bits !!!
- param = new ParametersWithIV(new ParametersWithSBox(
- new KeyParameter(key), //key
- GOST28147Engine.getSBox("E-A")), //type S-box
- Hex.decode("1234567890abcdef")); //IV
-
- cipher = new BufferedBlockCipher(new CFBBlockCipher(new GOST28147Engine(), 64));
-
- cipher.init(true, param);
- len1 = cipher.processBytes(in, 0, in.length, out, 0);
- try
- {
- cipher.doFinal(out, len1);
- }
- catch (CryptoException e)
- {
- fail("failed - exception " + e.toString(), e);
- }
- if (out.length != output.length)
- {
- fail("failed - " + "expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
- }
- for (int i = 0; i != out.length; i++)
- {
- if (out[i] != output[i])
- {
- fail("failed - " + "expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
- }
- }
-
-
- //encrypt on hesh message; CFB mode:
- in = Hex.decode("000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f");
- output = Hex.decode("64988982819f0a1655e226e19ecad79d10cc73bac95c5d7da034786c12294225");
- out = new byte[in.length];
-
- key = generateKey(Hex.decode("aafd12f659cae63489b479e5076ddec2f06cb58faafd12f659cae63489b479e5")); //!!! heshing start_key - get 256 bits !!!
- param = new ParametersWithIV(new ParametersWithSBox(
- new KeyParameter(key), //key
- GOST28147Engine.getSBox("E-A")), //type S-box
- Hex.decode("aafd12f659cae634")); //IV
-
- cipher = new BufferedBlockCipher(new CFBBlockCipher(new GOST28147Engine(), 64));
-
- cipher.init(true, param);
- len1 = cipher.processBytes(in, 0, in.length, out, 0);
-
- cipher.doFinal(out, len1);
-
- if (out.length != output.length)
- {
- fail("failed - " + "expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
- }
-
- for (int i = 0; i != out.length; i++)
- {
- if (out[i] != output[i])
- {
- fail("failed - " + "expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
- }
- }
-
- //encrypt on hesh message; OFB mode:
- in = Hex.decode("bc350e71aa11345709acde");
- output = Hex.decode("1bcc2282707c676fb656dc");
- out = new byte[in.length];
-
- key = generateKey(Hex.decode("0123456789abcdef")); //!!! heshing start_key - get 256 bits !!!
- param = new ParametersWithIV(new ParametersWithSBox(
- new KeyParameter(key), //key
- GOST28147Engine.getSBox("E-A")), //type S-box
- Hex.decode("1234567890abcdef")); //IV
-
- cipher = new BufferedBlockCipher(new GOFBBlockCipher(new GOST28147Engine()));
-
- cipher.init(true, param);
- len1 = cipher.processBytes(in, 0, in.length, out, 0);
-
- cipher.doFinal(out, len1);
-
- if (out.length != output.length)
- {
- fail("failed - " + "expected "
- + new String(Hex.encode(output)) + " got "
- + new String(Hex.encode(out)));
- }
- for (int i = 0; i != out.length; i++)
- {
- if (out[i] != output[i])
- {
- fail("failed - " + "expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
- }
- }
-
- // key reuse test
- param = new ParametersWithIV(null, // key and sbox reused
- Hex.decode("1234567890abcdef")); //IV
-
- cipher.init(true, param);
- len1 = cipher.processBytes(in, 0, in.length, out, 0);
-
- cipher.doFinal(out, len1);
-
- if (out.length != output.length)
- {
- fail("failed - " + "expected "
- + new String(Hex.encode(output)) + " got "
- + new String(Hex.encode(out)));
- }
- for (int i = 0; i != out.length; i++)
- {
- if (out[i] != output[i])
- {
- fail("failed - " + "expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
- }
- }
- }
-
- public String getName()
- {
- return "GOST28147";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new GOST28147Test());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/GOST3410Test.java b/core/src/test/java/org/bouncycastle/crypto/test/GOST3410Test.java
deleted file mode 100644
index 17de3fee..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/GOST3410Test.java
+++ /dev/null
@@ -1,1570 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.generators.GOST3410KeyPairGenerator;
-import org.bouncycastle.crypto.generators.GOST3410ParametersGenerator;
-import org.bouncycastle.crypto.params.GOST3410KeyGenerationParameters;
-import org.bouncycastle.crypto.params.GOST3410Parameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.signers.GOST3410Signer;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.FixedSecureRandom;
-import org.bouncycastle.util.test.NumberParsing;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-public class GOST3410Test
- implements Test
-{
- byte[] hashmessage = Hex.decode("3042453136414534424341374533364339313734453431443642453241453435");
-
- private byte[] zeroTwo(int length)
- {
- byte[] data = new byte[length];
- data[data.length - 1] = 0x02;
- return data;
- }
-
- private class GOST3410_TEST1_512
- implements Test
- {
- public String getName()
- {
- return "GOST3410-TEST1-512";
- }
-
- FixedSecureRandom init_random = new FixedSecureRandom(new byte[][] { Hex.decode("00005EC900007341"), zeroTwo(64) });
- FixedSecureRandom random = new FixedSecureRandom(Hex.decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A"));
- FixedSecureRandom keyRandom = new FixedSecureRandom(Hex.decode("3036314538303830343630454235324435324234314132373832433138443046"));
-
- BigInteger pValue = new BigInteger("EE8172AE8996608FB69359B89EB82A69854510E2977A4D63BC97322CE5DC3386EA0A12B343E9190F23177539845839786BB0C345D165976EF2195EC9B1C379E3", 16);
- BigInteger qValue = new BigInteger("98915E7EC8265EDFCDA31E88F24809DDB064BDC7285DD50D7289F0AC6F49DD2D", 16);
-
- public TestResult perform()
- {
- BigInteger r = new BigInteger("3e5f895e276d81d2d52c0763270a458157b784c57abdbd807bc44fd43a32ac06",16);
- BigInteger s = new BigInteger("3f0dd5d4400d47c08e4ce505ff7434b6dbf729592e37c74856dab85115a60955",16);
- GOST3410ParametersGenerator pGen = new GOST3410ParametersGenerator();
-
- pGen.init(512, 1, init_random);
-
- GOST3410Parameters params = pGen.generateParameters();
-
- if (params.getValidationParameters() == null)
- {
- return new SimpleTestResult(false, getName() + "validation parameters wrong");
- }
- if (params.getValidationParameters().getC() != 29505
- || params.getValidationParameters().getX0() != 24265)
- {
- return new SimpleTestResult(false, getName() + "validation parameters values wrong");
- }
- if (!init_random.isExhausted())
- {
- return new SimpleTestResult(false, getName()
- + ": unexpected number of bytes used from 'init_random'.");
- }
-
- if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
- {
- return new SimpleTestResult(false, getName() + ": p or q wrong");
- }
-
- GOST3410KeyPairGenerator GOST3410KeyGen = new GOST3410KeyPairGenerator();
- GOST3410KeyGenerationParameters genParam = new GOST3410KeyGenerationParameters(keyRandom, params);
-
- GOST3410KeyGen.init(genParam);
-
- AsymmetricCipherKeyPair pair = GOST3410KeyGen.generateKeyPair();
-
- if (!keyRandom.isExhausted())
- {
- return new SimpleTestResult(false, getName()
- + ": unexpected number of bytes used from 'keyRandom'.");
- }
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
-
- GOST3410Signer gost3410 = new GOST3410Signer();
-
- gost3410.init(true, param);
-
- BigInteger[] sig = gost3410.generateSignature(hashmessage);
-
- if (!random.isExhausted())
- {
- return new SimpleTestResult(false, getName()
- + ": unexpected number of bytes used from 'random'.");
- }
-
- if (!r.equals(sig[0]))
- {
- return new SimpleTestResult(false, getName()
- + ": r component wrong." + System.getProperty("line.separator")
- + " expecting: " + r.toString(16) + System.getProperty("line.separator")
- + " got : " + sig[0].toString(16));
- }
-
- if (!s.equals(sig[1]))
- {
- return new SimpleTestResult(false, getName()
- + ": s component wrong." + System.getProperty("line.separator")
- + " expecting: " + s.toString(16) + System.getProperty("line.separator")
- + " got : " + sig[1].toString(16));
- }
-
- gost3410.init(false, pair.getPublic());
-
- if (gost3410.verifySignature(hashmessage, sig[0], sig[1]))
- {
- return new SimpleTestResult(true, getName() + ": Okay");
- }
- else
- {
- return new SimpleTestResult(false, getName() + ": verification fails");
- }
- }
- }
-
- private class GOST3410_TEST2_512
- implements Test
- {
- public String getName()
- {
- return "GOST3410-TEST2-512";
- }
-
- FixedSecureRandom init_random = new FixedSecureRandom(new byte[][] { Hex.decode("000000003DFC46F1000000000000000D"), zeroTwo(64) });
- FixedSecureRandom random = new FixedSecureRandom(Hex.decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A"));
- FixedSecureRandom keyRandom = new FixedSecureRandom(Hex.decode("3036314538303830343630454235324435324234314132373832433138443046"));
-
- BigInteger pValue = new BigInteger("8b08eb135af966aab39df294538580c7da26765d6d38d30cf1c06aae0d1228c3316a0e29198460fad2b19dc381c15c888c6dfd0fc2c565abb0bf1faff9518f85", 16);
- BigInteger qValue = new BigInteger("931a58fb6f0dcdf2fe7549bc3f19f4724b56898f7f921a076601edb18c93dc75", 16);
-
- public TestResult perform()
- {
- BigInteger r = new BigInteger("7c07c8cf035c2a1cb2b7fae5807ac7cd623dfca7a1a68f6d858317822f1ea00d",16);
- BigInteger s = new BigInteger("7e9e036a6ff87dbf9b004818252b1f6fc310bdd4d17cb8c37d9c36c7884de60c",16);
- GOST3410ParametersGenerator pGen = new GOST3410ParametersGenerator();
-
- pGen.init(512, 2, init_random);
-
- GOST3410Parameters params = pGen.generateParameters();
-
- if (!init_random.isExhausted())
- {
- return new SimpleTestResult(false, getName()
- + ": unexpected number of bytes used from 'init_random'.");
- }
-
- if (params.getValidationParameters() == null)
- {
- return new SimpleTestResult(false, getName() + ": validation parameters wrong");
- }
-
- if (params.getValidationParameters().getCL() != 13
- || params.getValidationParameters().getX0L() != 1039943409)
- {
- return new SimpleTestResult(false, getName() + ": validation parameters values wrong");
- }
-
- if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
- {
- return new SimpleTestResult(false, getName() + ": p or q wrong");
- }
-
- GOST3410KeyPairGenerator GOST3410KeyGen = new GOST3410KeyPairGenerator();
- GOST3410KeyGenerationParameters genParam = new GOST3410KeyGenerationParameters(keyRandom, params);
-
- GOST3410KeyGen.init(genParam);
-
- AsymmetricCipherKeyPair pair = GOST3410KeyGen.generateKeyPair();
-
- if (!keyRandom.isExhausted())
- {
- return new SimpleTestResult(false, getName()
- + ": unexpected number of bytes used from 'keyRandom'.");
- }
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
-
- GOST3410Signer GOST3410 = new GOST3410Signer();
-
- GOST3410.init(true, param);
-
- BigInteger[] sig = GOST3410.generateSignature(hashmessage);
-
- if (!random.isExhausted())
- {
- return new SimpleTestResult(false, getName()
- + ": unexpected number of bytes used from 'random'.");
- }
-
- if (!r.equals(sig[0]))
- {
- return new SimpleTestResult(false, getName()
- + ": r component wrong." + System.getProperty("line.separator")
- + " expecting: " + r.toString(16) + System.getProperty("line.separator")
- + " got : " + sig[0].toString(16));
- }
-
- if (!s.equals(sig[1]))
- {
- return new SimpleTestResult(false, getName()
- + ": s component wrong." + System.getProperty("line.separator")
- + " expecting: " + s.toString(16) + System.getProperty("line.separator")
- + " got : " + sig[1].toString(16));
- }
-
- GOST3410.init(false, pair.getPublic());
-
- if (GOST3410.verifySignature(hashmessage, sig[0], sig[1]))
- {
- return new SimpleTestResult(true, getName() + ": Okay");
- }
- else
- {
- return new SimpleTestResult(false, getName() + ": verification fails");
- }
- }
- }
-
- private class GOST3410_TEST1_1024
- implements Test
- {
- public String getName()
- {
- return "GOST3410-TEST1-1024";
- }
-
- SecureRandom init_random = new SecureRandom()
- {
- boolean firstInt = true;
-
- public int nextInt()
- {
- String x0 = "0xA565";
- String c = "0x538B";
-
- if (firstInt)
- {
- firstInt = false;
- return NumberParsing.decodeIntFromHex(x0);
- }
- return NumberParsing.decodeIntFromHex(c);
- }
-
- public void nextBytes(byte[] bytes)
- {
-
- byte[] d = Hex.decode("02");
-
- System.arraycopy(d, 0, bytes, bytes.length-d.length, d.length);
- }
- };
-
- SecureRandom random = new SecureRandom()
- {
- public void nextBytes(byte[] bytes)
- {
- byte[] k = Hex.decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
-
- int i;
-
- for (i = 0; i < (bytes.length - k.length); i += k.length)
- {
- System.arraycopy(k, 0, bytes, i, k.length);
- }
-
- if (i > bytes.length)
- {
- System.arraycopy(k, 0, bytes, i - k.length, bytes.length - (i - k.length));
- }
- else
- {
- System.arraycopy(k, 0, bytes, i, bytes.length - i);
- }
- }
- };
-
- SecureRandom keyRandom = new SecureRandom()
- {
- public void nextBytes(byte[] bytes)
- {
- byte[] x = Hex.decode("3036314538303830343630454235324435324234314132373832433138443046");
-
- int i;
-
- for (i = 0; i < (bytes.length - x.length); i += x.length)
- {
- System.arraycopy(x, 0, bytes, i, x.length);
- }
-
- if (i > bytes.length)
- {
- System.arraycopy(x, 0, bytes, i - x.length, bytes.length - (i - x.length));
- }
- else
- {
- System.arraycopy(x, 0, bytes, i, bytes.length - i);
- }
- }
- };
-
- BigInteger pValue = new BigInteger("ab8f37938356529e871514c1f48c5cbce77b2f4fc9a2673ac2c1653da8984090c0ac73775159a26bef59909d4c9846631270e16653a6234668f2a52a01a39b921490e694c0f104b58d2e14970fccb478f98d01e975a1028b9536d912de5236d2dd2fc396b77153594d4178780e5f16f718471e2111c8ce64a7d7e196fa57142d", 16);
- BigInteger qValue = new BigInteger("bcc02ca0ce4f0753ec16105ee5d530aa00d39f3171842ab2c334a26b5f576e0f", 16);
-
- public TestResult perform()
- {
- BigInteger r = new BigInteger("a8790aabbd5a998ff524bad048ac69cd1faff2dab048265c8d60d1471c44a9ee",16);
- BigInteger s = new BigInteger("30df5ba32ac77170b9632559bef7d37620017756dff3fea1088b4267db0944b8",16);
- GOST3410ParametersGenerator pGen = new GOST3410ParametersGenerator();
-
- pGen.init(1024, 1, init_random);
-
- GOST3410Parameters params = pGen.generateParameters();
-
- if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
- {
- return new SimpleTestResult(false, getName() + ": p or q wrong");
- }
-
- GOST3410KeyPairGenerator GOST3410KeyGen = new GOST3410KeyPairGenerator();
- GOST3410KeyGenerationParameters genParam = new GOST3410KeyGenerationParameters(keyRandom, params);
-
- GOST3410KeyGen.init(genParam);
-
- AsymmetricCipherKeyPair pair = GOST3410KeyGen.generateKeyPair();
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
-
- GOST3410Signer GOST3410 = new GOST3410Signer();
-
- GOST3410.init(true, param);
-
- BigInteger[] sig = GOST3410.generateSignature(hashmessage);
-
- if (!r.equals(sig[0]))
- {
- return new SimpleTestResult(false, getName()
- + ": r component wrong." + System.getProperty("line.separator")
- + " expecting: " + r.toString(16) + System.getProperty("line.separator")
- + " got : " + sig[0].toString(16));
- }
-
- if (!s.equals(sig[1]))
- {
- return new SimpleTestResult(false, getName()
- + ": s component wrong." + System.getProperty("line.separator")
- + " expecting: " + s.toString(16) + System.getProperty("line.separator")
- + " got : " + sig[1].toString(16));
- }
-
- GOST3410.init(false, pair.getPublic());
-
- if (GOST3410.verifySignature(hashmessage, sig[0], sig[1]))
- {
- return new SimpleTestResult(true, getName() + ": Okay");
- }
- else
- {
- return new SimpleTestResult(false, getName() + ": verification fails");
- }
- }
- }
-
- private class GOST3410_TEST2_1024
- implements Test
- {
- public String getName()
- {
- return "GOST3410-TEST2-1024";
- }
-
- SecureRandom init_random = new SecureRandom()
- {
- boolean firstLong = true;
-
- public long nextLong()
- {
- String x0 = "0x3DFC46F1";
- String c = "0xD";
-
- if (firstLong)
- {
- firstLong = false;
- return NumberParsing.decodeLongFromHex(x0);
- }
- return NumberParsing.decodeLongFromHex(c);
- }
-
- public void nextBytes(byte[] bytes)
- {
-
- byte[] d = Hex.decode("02");
-
- System.arraycopy(d, 0, bytes, bytes.length-d.length, d.length);
- }
- };
-
- SecureRandom random = new SecureRandom()
- {
- public void nextBytes(byte[] bytes)
- {
- byte[] k = Hex.decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
-
- int i;
-
- for (i = 0; i < (bytes.length - k.length); i += k.length)
- {
- System.arraycopy(k, 0, bytes, i, k.length);
- }
-
- if (i > bytes.length)
- {
- System.arraycopy(k, 0, bytes, i - k.length, bytes.length - (i - k.length));
- }
- else
- {
- System.arraycopy(k, 0, bytes, i, bytes.length - i);
- }
- }
- };
-
- SecureRandom keyRandom = new SecureRandom()
- {
- public void nextBytes(byte[] bytes)
- {
- byte[] x = Hex.decode("3036314538303830343630454235324435324234314132373832433138443046");
-
- int i;
-
- for (i = 0; i < (bytes.length - x.length); i += x.length)
- {
- System.arraycopy(x, 0, bytes, i, x.length);
- }
-
- if (i > bytes.length)
- {
- System.arraycopy(x, 0, bytes, i - x.length, bytes.length - (i - x.length));
- }
- else
- {
- System.arraycopy(x, 0, bytes, i, bytes.length - i);
- }
- }
- };
-
- BigInteger pValue = new BigInteger("e2c4191c4b5f222f9ac2732562f6d9b4f18e7fb67a290ea1e03d750f0b9806755fc730d975bf3faa606d05c218b35a6c3706919aab92e0c58b1de4531c8fa8e7af43c2bff016251e21b2870897f6a27ac4450bca235a5b748ad386e4a0e4dfcb09152435abcfe48bd0b126a8122c7382f285a9864615c66decddf6afd355dfb7", 16);
- BigInteger qValue = new BigInteger("931a58fb6f0dcdf2fe7549bc3f19f4724b56898f7f921a076601edb18c93dc75", 16);
-
- public TestResult perform()
- {
- BigInteger r = new BigInteger("81d69a192e9c7ac21fc07da41bd07e230ba6a94eb9f3c1fd104c7bd976733ca5",16);
- BigInteger s = new BigInteger("315c879c8414f35feb4deb15e7cc0278c48e6ca1596325d6959338d860b0c47a",16);
- GOST3410ParametersGenerator pGen = new GOST3410ParametersGenerator();
-
- pGen.init(1024, 2, init_random);
-
- GOST3410Parameters params = pGen.generateParameters();
-
- if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
- {
- return new SimpleTestResult(false, getName() + ": p or q wrong");
- }
-
- GOST3410KeyPairGenerator GOST3410KeyGen = new GOST3410KeyPairGenerator();
- GOST3410KeyGenerationParameters genParam = new GOST3410KeyGenerationParameters(keyRandom, params);
-
- GOST3410KeyGen.init(genParam);
-
- AsymmetricCipherKeyPair pair = GOST3410KeyGen.generateKeyPair();
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
-
- GOST3410Signer GOST3410 = new GOST3410Signer();
-
- GOST3410.init(true, param);
-
- BigInteger[] sig = GOST3410.generateSignature(hashmessage);
-
- if (!r.equals(sig[0]))
- {
- return new SimpleTestResult(false, getName()
- + ": r component wrong." + System.getProperty("line.separator")
- + " expecting: " + r.toString(16) + System.getProperty("line.separator")
- + " got : " + sig[0].toString(16));
- }
-
- if (!s.equals(sig[1]))
- {
- return new SimpleTestResult(false, getName()
- + ": s component wrong." + System.getProperty("line.separator")
- + " expecting: " + s.toString(16) + System.getProperty("line.separator")
- + " got : " + sig[1].toString(16));
- }
-
- GOST3410.init(false, pair.getPublic());
-
- if (GOST3410.verifySignature(hashmessage, sig[0], sig[1]))
- {
- return new SimpleTestResult(true, getName() + ": Okay");
- }
- else
- {
- return new SimpleTestResult(false, getName() + ": verification fails");
- }
- }
- }
-
- private class GOST3410_AParam
- implements Test
- {
- public String getName()
- {
- return "GOST3410-AParam";
- }
-
- SecureRandom init_random = new SecureRandom()
- {
- boolean firstLong = true;
-
- public long nextLong()
- {
- String x0 = "0x520874F5";
- String c = "0xEE39ADB3";
-
- if (firstLong)
- {
- firstLong = false;
- return NumberParsing.decodeLongFromHex(x0);
- }
- return NumberParsing.decodeLongFromHex(c);
- }
-
- public void nextBytes(byte[] bytes)
- {
-
- byte[] d = Hex.decode("02");
-
- System.arraycopy(d, 0, bytes, bytes.length-d.length, d.length);
- }
- };
-
- SecureRandom random = new SecureRandom()
- {
- public void nextBytes(byte[] bytes)
- {
- byte[] k = Hex.decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
-
- int i;
-
- for (i = 0; i < (bytes.length - k.length); i += k.length)
- {
- System.arraycopy(k, 0, bytes, i, k.length);
- }
-
- if (i > bytes.length)
- {
- System.arraycopy(k, 0, bytes, i - k.length, bytes.length - (i - k.length));
- }
- else
- {
- System.arraycopy(k, 0, bytes, i, bytes.length - i);
- }
- }
- };
-
- SecureRandom keyRandom = new SecureRandom()
- {
- public void nextBytes(byte[] bytes)
- {
- byte[] x = Hex.decode("3036314538303830343630454235324435324234314132373832433138443046");
-
- int i;
-
- for (i = 0; i < (bytes.length - x.length); i += x.length)
- {
- System.arraycopy(x, 0, bytes, i, x.length);
- }
-
- if (i > bytes.length)
- {
- System.arraycopy(x, 0, bytes, i - x.length, bytes.length - (i - x.length));
- }
- else
- {
- System.arraycopy(x, 0, bytes, i, bytes.length - i);
- }
- }
- };
-
- BigInteger pValue = new BigInteger("b4e25efb018e3c8b87505e2a67553c5edc56c2914b7e4f89d23f03f03377e70a2903489dd60e78418d3d851edb5317c4871e40b04228c3b7902963c4b7d85d52b9aa88f2afdbeb28da8869d6df846a1d98924e925561bd69300b9ddd05d247b5922d967cbb02671881c57d10e5ef72d3e6dad4223dc82aa1f7d0294651a480df", 16);
- BigInteger qValue = new BigInteger("972432a437178b30bd96195b773789ab2fff15594b176dd175b63256ee5af2cf", 16);
-
- public TestResult perform()
- {
- BigInteger r = new BigInteger("64a8856628e5669d85f62cd763dd4a99bc56d33dc0e1859122855d141e9e4774",16);
- BigInteger s = new BigInteger("319ebac97092b288d469a4b988248794f60c865bc97858d9a3135c6d1a1bf2dd",16);
- GOST3410ParametersGenerator pGen = new GOST3410ParametersGenerator();
-
- pGen.init(1024, 2, init_random);
-
- GOST3410Parameters params = pGen.generateParameters();
-
- if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
- {
- return new SimpleTestResult(false, getName() + ": p or q wrong");
- }
-
- GOST3410KeyPairGenerator GOST3410KeyGen = new GOST3410KeyPairGenerator();
- GOST3410KeyGenerationParameters genParam = new GOST3410KeyGenerationParameters(keyRandom, params);
-
- GOST3410KeyGen.init(genParam);
-
- AsymmetricCipherKeyPair pair = GOST3410KeyGen.generateKeyPair();
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
-
- GOST3410Signer GOST3410 = new GOST3410Signer();
-
- GOST3410.init(true, param);
-
- BigInteger[] sig = GOST3410.generateSignature(hashmessage);
-
- if (!r.equals(sig[0]))
- {
- return new SimpleTestResult(false, getName()
- + ": r component wrong." + System.getProperty("line.separator")
- + " expecting: " + r.toString(16) + System.getProperty("line.separator")
- + " got : " + sig[0].toString(16));
- }
-
- if (!s.equals(sig[1]))
- {
- return new SimpleTestResult(false, getName()
- + ": s component wrong." + System.getProperty("line.separator")
- + " expecting: " + s.toString(16) + System.getProperty("line.separator")
- + " got : " + sig[1].toString(16));
- }
-
- GOST3410.init(false, pair.getPublic());
-
- if (GOST3410.verifySignature(hashmessage, sig[0], sig[1]))
- {
- return new SimpleTestResult(true, getName() + ": Okay");
- }
- else
- {
- return new SimpleTestResult(false, getName() + ": verification fails");
- }
- }
- }
-
- private class GOST3410_BParam
- implements Test
- {
- public String getName()
- {
- return "GOST3410-BParam";
- }
-
- SecureRandom init_random = new SecureRandom()
- {
- boolean firstLong = true;
-
- public long nextLong()
- {
- String x0 = "0x5B977CDB";
- String c = "0x6E9692DD";
-
- if (firstLong)
- {
- firstLong = false;
- return NumberParsing.decodeLongFromHex(x0);
- }
- return NumberParsing.decodeLongFromHex(c);
- }
-
- public void nextBytes(byte[] bytes)
- {
- byte[] d = Hex.decode("bc3cbbdb7e6f848286e19ad9a27a8e297e5b71c53dd974cdf60f937356df69cbc97a300ccc71685c553046147f11568c4fddf363d9d886438345a62c3b75963d6546adfabf31b31290d12cae65ecb8309ef66782");
-
- System.arraycopy(d, 0, bytes, bytes.length-d.length, d.length);
- }
- };
-
- SecureRandom random = new SecureRandom()
- {
- public void nextBytes(byte[] bytes)
- {
- byte[] k = Hex.decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
-
- int i;
-
- for (i = 0; i < (bytes.length - k.length); i += k.length)
- {
- System.arraycopy(k, 0, bytes, i, k.length);
- }
-
- if (i > bytes.length)
- {
- System.arraycopy(k, 0, bytes, i - k.length, bytes.length - (i - k.length));
- }
- else
- {
- System.arraycopy(k, 0, bytes, i, bytes.length - i);
- }
- }
- };
-
- SecureRandom keyRandom = new SecureRandom()
- {
- public void nextBytes(byte[] bytes)
- {
- byte[] x = Hex.decode("3036314538303830343630454235324435324234314132373832433138443046");
-
- int i;
-
- for (i = 0; i < (bytes.length - x.length); i += x.length)
- {
- System.arraycopy(x, 0, bytes, i, x.length);
- }
-
- if (i > bytes.length)
- {
- System.arraycopy(x, 0, bytes, i - x.length, bytes.length - (i - x.length));
- }
- else
- {
- System.arraycopy(x, 0, bytes, i, bytes.length - i);
- }
- }
- };
-
- BigInteger pValue = new BigInteger("c6971fc57524b30c9018c5e621de15499736854f56a6f8aee65a7a404632b3540f09020f67f04dc2e6783b141dceffd21a703035b7d0187c6e12cb4229922bafdb2225b73e6b23a0de36e20047065aea000c1a374283d0ad8dc1981e3995f0bb8c72526041fcb98ae6163e1e71a669d8364e9c4c3188f673c5f8ee6fadb41abf", 16);
- BigInteger qValue = new BigInteger("b09d634c10899cd7d4c3a7657403e05810b07c61a688bab2c37f475e308b0607", 16);
-
- public TestResult perform()
- {
- BigInteger r = new BigInteger("860d82c60e9502cd00c0e9e1f6563feafec304801974d745c5e02079946f729e",16);
- BigInteger s = new BigInteger("7ef49264ef022801aaa03033cd97915235fbab4c823ed936b0f360c22114688a",16);
- GOST3410ParametersGenerator pGen = new GOST3410ParametersGenerator();
-
- pGen.init(1024, 2, init_random);
-
- GOST3410Parameters params = pGen.generateParameters();
-
- if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
- {
- return new SimpleTestResult(false, getName() + ": p or q wrong");
- }
-
- GOST3410KeyPairGenerator GOST3410KeyGen = new GOST3410KeyPairGenerator();
- GOST3410KeyGenerationParameters genParam = new GOST3410KeyGenerationParameters(keyRandom, params);
-
- GOST3410KeyGen.init(genParam);
-
- AsymmetricCipherKeyPair pair = GOST3410KeyGen.generateKeyPair();
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
-
- GOST3410Signer GOST3410 = new GOST3410Signer();
-
- GOST3410.init(true, param);
-
- BigInteger[] sig = GOST3410.generateSignature(hashmessage);
-
- if (!r.equals(sig[0]))
- {
- return new SimpleTestResult(false, getName()
- + ": r component wrong." + System.getProperty("line.separator")
- + " expecting: " + r.toString(16) + System.getProperty("line.separator")
- + " got : " + sig[0].toString(16));
- }
-
- if (!s.equals(sig[1]))
- {
- return new SimpleTestResult(false, getName()
- + ": s component wrong." + System.getProperty("line.separator")
- + " expecting: " + s.toString(16) + System.getProperty("line.separator")
- + " got : " + sig[1].toString(16));
- }
-
- GOST3410.init(false, pair.getPublic());
-
- if (GOST3410.verifySignature(hashmessage, sig[0], sig[1]))
- {
- return new SimpleTestResult(true, getName() + ": Okay");
- }
- else
- {
- return new SimpleTestResult(false, getName() + ": verification fails");
- }
- }
- }
-
- private class GOST3410_CParam
- implements Test
- {
- public String getName()
- {
- return "GOST3410-CParam";
- }
-
- SecureRandom init_random = new SecureRandom()
- {
- boolean firstLong = true;
-
- public long nextLong()
- {
- String x0 = "0x43848744";
- String c = "0xB50A826D";
-
- if (firstLong)
- {
- firstLong = false;
- return NumberParsing.decodeLongFromHex(x0);
- }
- return NumberParsing.decodeLongFromHex(c);
- }
-
- public void nextBytes(byte[] bytes)
- {
- byte[] d = Hex.decode("7F575E8194BC5BDF");
-
- System.arraycopy(d, 0, bytes, bytes.length-d.length, d.length);
- }
- };
-
- SecureRandom random = new SecureRandom()
- {
- public void nextBytes(byte[] bytes)
- {
- byte[] k = Hex.decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
-
- int i;
-
- for (i = 0; i < (bytes.length - k.length); i += k.length)
- {
- System.arraycopy(k, 0, bytes, i, k.length);
- }
-
- if (i > bytes.length)
- {
- System.arraycopy(k, 0, bytes, i - k.length, bytes.length - (i - k.length));
- }
- else
- {
- System.arraycopy(k, 0, bytes, i, bytes.length - i);
- }
- }
- };
-
- SecureRandom keyRandom = new SecureRandom()
- {
- public void nextBytes(byte[] bytes)
- {
- byte[] x = Hex.decode("3036314538303830343630454235324435324234314132373832433138443046");
-
- int i;
-
- for (i = 0; i < (bytes.length - x.length); i += x.length)
- {
- System.arraycopy(x, 0, bytes, i, x.length);
- }
-
- if (i > bytes.length)
- {
- System.arraycopy(x, 0, bytes, i - x.length, bytes.length - (i - x.length));
- }
- else
- {
- System.arraycopy(x, 0, bytes, i, bytes.length - i);
- }
- }
- };
-
- BigInteger pValue = new BigInteger("9d88e6d7fe3313bd2e745c7cdd2ab9ee4af3c8899e847de74a33783ea68bc30588ba1f738c6aaf8ab350531f1854c3837cc3c860ffd7e2e106c3f63b3d8a4c034ce73942a6c3d585b599cf695ed7a3c4a93b2b947b7157bb1a1c043ab41ec8566c6145e938a611906de0d32e562494569d7e999a0dda5c879bdd91fe124df1e9", 16);
- BigInteger qValue = new BigInteger("fadd197abd19a1b4653eecf7eca4d6a22b1f7f893b641f901641fbb555354faf", 16);
-
- public TestResult perform()
- {
- BigInteger r = new BigInteger("4deb95a0b35e7ed7edebe9bef5a0f93739e16b7ff27fe794d989d0c13159cfbc",16);
- BigInteger s = new BigInteger("e1d0d30345c24cfeb33efde3deee5fbbda78ddc822b719d860cd0ba1fb6bd43b",16);
- GOST3410ParametersGenerator pGen = new GOST3410ParametersGenerator();
-
- pGen.init(1024, 2, init_random);
-
- GOST3410Parameters params = pGen.generateParameters();
-
- if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
- {
- return new SimpleTestResult(false, getName() + ": p or q wrong");
- }
-
- GOST3410KeyPairGenerator GOST3410KeyGen = new GOST3410KeyPairGenerator();
- GOST3410KeyGenerationParameters genParam = new GOST3410KeyGenerationParameters(keyRandom, params);
-
- GOST3410KeyGen.init(genParam);
-
- AsymmetricCipherKeyPair pair = GOST3410KeyGen.generateKeyPair();
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
-
- GOST3410Signer GOST3410 = new GOST3410Signer();
-
- GOST3410.init(true, param);
-
- BigInteger[] sig = GOST3410.generateSignature(hashmessage);
-
- if (!r.equals(sig[0]))
- {
- return new SimpleTestResult(false, getName()
- + ": r component wrong." + System.getProperty("line.separator")
- + " expecting: " + r.toString(16) + System.getProperty("line.separator")
- + " got : " + sig[0].toString(16));
- }
-
- if (!s.equals(sig[1]))
- {
- return new SimpleTestResult(false, getName()
- + ": s component wrong." + System.getProperty("line.separator")
- + " expecting: " + s.toString(16) + System.getProperty("line.separator")
- + " got : " + sig[1].toString(16));
- }
-
- GOST3410.init(false, pair.getPublic());
-
- if (GOST3410.verifySignature(hashmessage, sig[0], sig[1]))
- {
- return new SimpleTestResult(true, getName() + ": Okay");
- }
- else
- {
- return new SimpleTestResult(false, getName() + ": verification fails");
- }
- }
- }
-
- private class GOST3410_DParam
- implements Test
- {
- public String getName()
- {
- return "GOST3410-DParam";
- }
-
- SecureRandom init_random = new SecureRandom()
- {
- boolean firstLong = true;
-
- public long nextLong()
- {
- String x0 = "0x13DA8B9D";
- String c = "0xA0E9DE4B";
-
- if (firstLong)
- {
- firstLong = false;
- return NumberParsing.decodeLongFromHex(x0);
- }
- return NumberParsing.decodeLongFromHex(c);
- }
-
- public void nextBytes(byte[] bytes)
- {
-
- byte[] d = Hex.decode("41ab97857f42614355d32db0b1069f109a4da283676c7c53a68185b4");
-
- System.arraycopy(d, 0, bytes, bytes.length-d.length, d.length);
- }
- };
-
- SecureRandom random = new SecureRandom()
- {
- public void nextBytes(byte[] bytes)
- {
- byte[] k = Hex.decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
-
- int i;
-
- for (i = 0; i < (bytes.length - k.length); i += k.length)
- {
- System.arraycopy(k, 0, bytes, i, k.length);
- }
-
- if (i > bytes.length)
- {
- System.arraycopy(k, 0, bytes, i - k.length, bytes.length - (i - k.length));
- }
- else
- {
- System.arraycopy(k, 0, bytes, i, bytes.length - i);
- }
- }
- };
-
- SecureRandom keyRandom = new SecureRandom()
- {
- public void nextBytes(byte[] bytes)
- {
- byte[] x = Hex.decode("3036314538303830343630454235324435324234314132373832433138443046");
-
- int i;
-
- for (i = 0; i < (bytes.length - x.length); i += x.length)
- {
- System.arraycopy(x, 0, bytes, i, x.length);
- }
-
- if (i > bytes.length)
- {
- System.arraycopy(x, 0, bytes, i - x.length, bytes.length - (i - x.length));
- }
- else
- {
- System.arraycopy(x, 0, bytes, i, bytes.length - i);
- }
- }
- };
-
- BigInteger pValue = new BigInteger("80f102d32b0fd167d069c27a307adad2c466091904dbaa55d5b8cc7026f2f7a1919b890cb652c40e054e1e9306735b43d7b279eddf9102001cd9e1a831fe8a163eed89ab07cf2abe8242ac9dedddbf98d62cddd1ea4f5f15d3a42a6677bdd293b24260c0f27c0f1d15948614d567b66fa902baa11a69ae3bceadbb83e399c9b5", 16);
- BigInteger qValue = new BigInteger("f0f544c418aac234f683f033511b65c21651a6078bda2d69bb9f732867502149", 16);
-
- public TestResult perform()
- {
- BigInteger r = new BigInteger("712592d285b792e33b8a9a11e8e6c4f512ddf0042972bbfd1abb0a93e8fc6f54",16);
- BigInteger s = new BigInteger("2cf26758321258b130d5612111339f09ceb8668241f3482e38baa56529963f07",16);
- GOST3410ParametersGenerator pGen = new GOST3410ParametersGenerator();
-
- pGen.init(1024, 2, init_random);
-
- GOST3410Parameters params = pGen.generateParameters();
-
- if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
- {
- return new SimpleTestResult(false, getName() + ": p or q wrong");
- }
-
- GOST3410KeyPairGenerator GOST3410KeyGen = new GOST3410KeyPairGenerator();
- GOST3410KeyGenerationParameters genParam = new GOST3410KeyGenerationParameters(keyRandom, params);
-
- GOST3410KeyGen.init(genParam);
-
- AsymmetricCipherKeyPair pair = GOST3410KeyGen.generateKeyPair();
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
-
- GOST3410Signer GOST3410 = new GOST3410Signer();
-
- GOST3410.init(true, param);
-
- BigInteger[] sig = GOST3410.generateSignature(hashmessage);
-
- if (!r.equals(sig[0]))
- {
- return new SimpleTestResult(false, getName()
- + ": r component wrong." + System.getProperty("line.separator")
- + " expecting: " + r.toString(16) + System.getProperty("line.separator")
- + " got : " + sig[0].toString(16));
- }
-
- if (!s.equals(sig[1]))
- {
- return new SimpleTestResult(false, getName()
- + ": s component wrong." + System.getProperty("line.separator")
- + " expecting: " + s.toString(16) + System.getProperty("line.separator")
- + " got : " + sig[1].toString(16));
- }
-
- GOST3410.init(false, pair.getPublic());
-
- if (GOST3410.verifySignature(hashmessage, sig[0], sig[1]))
- {
- return new SimpleTestResult(true, getName() + ": Okay");
- }
- else
- {
- return new SimpleTestResult(false, getName() + ": verification fails");
- }
- }
- }
-
- private class GOST3410_AExParam
- implements Test
- {
- public String getName()
- {
- return "GOST3410-AExParam";
- }
-
- SecureRandom init_random = new SecureRandom()
- {
- boolean firstLong = true;
-
- public long nextLong()
- {
- String x0 = "0xD05E9F14";
- String c = "0x46304C5F";
-
- if (firstLong)
- {
- firstLong = false;
- return NumberParsing.decodeLongFromHex(x0);
- }
- return NumberParsing.decodeLongFromHex(c);
- }
-
- public void nextBytes(byte[] bytes)
- {
- byte[] d = Hex.decode("35ab875399cda33c146ca629660e5a5e5c07714ca326db032dd6751995cdb90a612b9228932d8302704ec24a5def7739c5813d83");
-
- System.arraycopy(d, 0, bytes, bytes.length-d.length, d.length);
- }
- };
-
- SecureRandom random = new SecureRandom()
- {
- public void nextBytes(byte[] bytes)
- {
- byte[] k = Hex.decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
-
- int i;
-
- for (i = 0; i < (bytes.length - k.length); i += k.length)
- {
- System.arraycopy(k, 0, bytes, i, k.length);
- }
-
- if (i > bytes.length)
- {
- System.arraycopy(k, 0, bytes, i - k.length, bytes.length - (i - k.length));
- }
- else
- {
- System.arraycopy(k, 0, bytes, i, bytes.length - i);
- }
- }
- };
-
- SecureRandom keyRandom = new SecureRandom()
- {
- public void nextBytes(byte[] bytes)
- {
- byte[] x = Hex.decode("3036314538303830343630454235324435324234314132373832433138443046");
-
- int i;
-
- for (i = 0; i < (bytes.length - x.length); i += x.length)
- {
- System.arraycopy(x, 0, bytes, i, x.length);
- }
-
- if (i > bytes.length)
- {
- System.arraycopy(x, 0, bytes, i - x.length, bytes.length - (i - x.length));
- }
- else
- {
- System.arraycopy(x, 0, bytes, i, bytes.length - i);
- }
- }
- };
-
- BigInteger pValue = new BigInteger("ca3b3f2eee9fd46317d49595a9e7518e6c63d8f4eb4d22d10d28af0b8839f079f8289e603b03530784b9bb5a1e76859e4850c670c7b71c0df84ca3e0d6c177fe9f78a9d8433230a883cd82a2b2b5c7a3306980278570cdb79bf01074a69c9623348824b0c53791d53c6a78cab69e1cfb28368611a397f50f541e16db348dbe5f", 16);
- BigInteger qValue = new BigInteger("cae4d85f80c147704b0ca48e85fb00a9057aa4acc44668e17f1996d7152690d9", 16);
-
- public TestResult perform()
- {
- BigInteger r = new BigInteger("90892707282f433398488f19d31ac48523a8e2ded68944e0da91c6895ee7045e",16);
- BigInteger s = new BigInteger("3be4620ee88f1ee8f9dd63c7d145b7e554839feeca125049118262ea4651e9de",16);
- GOST3410ParametersGenerator pGen = new GOST3410ParametersGenerator();
-
- pGen.init(1024, 2, init_random);
-
- GOST3410Parameters params = pGen.generateParameters();
-
- if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
- {
- return new SimpleTestResult(false, getName() + ": p or q wrong");
- }
-
- GOST3410KeyPairGenerator GOST3410KeyGen = new GOST3410KeyPairGenerator();
- GOST3410KeyGenerationParameters genParam = new GOST3410KeyGenerationParameters(keyRandom, params);
-
- GOST3410KeyGen.init(genParam);
-
- AsymmetricCipherKeyPair pair = GOST3410KeyGen.generateKeyPair();
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
-
- GOST3410Signer GOST3410 = new GOST3410Signer();
-
- GOST3410.init(true, param);
-
- BigInteger[] sig = GOST3410.generateSignature(hashmessage);
-
- if (!r.equals(sig[0]))
- {
- return new SimpleTestResult(false, getName()
- + ": r component wrong." + System.getProperty("line.separator")
- + " expecting: " + r.toString(16) + System.getProperty("line.separator")
- + " got : " + sig[0].toString(16));
- }
-
- if (!s.equals(sig[1]))
- {
- return new SimpleTestResult(false, getName()
- + ": s component wrong." + System.getProperty("line.separator")
- + " expecting: " + s.toString(16) + System.getProperty("line.separator")
- + " got : " + sig[1].toString(16));
- }
-
- GOST3410.init(false, pair.getPublic());
-
- if (GOST3410.verifySignature(hashmessage, sig[0], sig[1]))
- {
- return new SimpleTestResult(true, getName() + ": Okay");
- }
- else
- {
- return new SimpleTestResult(false, getName() + ": verification fails");
- }
- }
- }
-
- private class GOST3410_BExParam
- implements Test
- {
- public String getName()
- {
- return "GOST3410-BExParam";
- }
-
- SecureRandom init_random = new SecureRandom()
- {
- boolean firstLong = true;
-
- public long nextLong()
- {
- String x0 = "0x7A007804";
- String c = "0xD31A4FF7";
-
- if (firstLong)
- {
- firstLong = false;
- return NumberParsing.decodeLongFromHex(x0);
- }
- return NumberParsing.decodeLongFromHex(c);
- }
-
- public void nextBytes(byte[] bytes)
- {
- byte[] d = Hex.decode("7ec123d161477762838c2bea9dbdf33074af6d41d108a066a1e7a07ab3048de2");
-
- System.arraycopy(d, 0, bytes, bytes.length-d.length, d.length);
- }
- };
-
- SecureRandom random = new SecureRandom()
- {
- public void nextBytes(byte[] bytes)
- {
- byte[] k = Hex.decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
-
- int i;
-
- for (i = 0; i < (bytes.length - k.length); i += k.length)
- {
- System.arraycopy(k, 0, bytes, i, k.length);
- }
-
- if (i > bytes.length)
- {
- System.arraycopy(k, 0, bytes, i - k.length, bytes.length - (i - k.length));
- }
- else
- {
- System.arraycopy(k, 0, bytes, i, bytes.length - i);
- }
- }
- };
-
- SecureRandom keyRandom = new SecureRandom()
- {
- public void nextBytes(byte[] bytes)
- {
- byte[] x = Hex.decode("3036314538303830343630454235324435324234314132373832433138443046");
-
- int i;
-
- for (i = 0; i < (bytes.length - x.length); i += x.length)
- {
- System.arraycopy(x, 0, bytes, i, x.length);
- }
-
- if (i > bytes.length)
- {
- System.arraycopy(x, 0, bytes, i - x.length, bytes.length - (i - x.length));
- }
- else
- {
- System.arraycopy(x, 0, bytes, i, bytes.length - i);
- }
- }
- };
-
- BigInteger pValue = new BigInteger("9286dbda91eccfc3060aa5598318e2a639f5ba90a4ca656157b2673fb191cd0589ee05f4cef1bd13508408271458c30851ce7a4ef534742bfb11f4743c8f787b11193ba304c0e6bca25701bf88af1cb9b8fd4711d89f88e32b37d95316541bf1e5dbb4989b3df13659b88c0f97a3c1087b9f2d5317d557dcd4afc6d0a754e279", 16);
- BigInteger qValue = new BigInteger("c966e9b3b8b7cdd82ff0f83af87036c38f42238ec50a876cd390e43d67b6013f", 16);
-
- public TestResult perform()
- {
- BigInteger r = new BigInteger("8f79a582513df84dc247bcb624340cc0e5a34c4324a20ce7fe3ab8ff38a9db71",16);
- BigInteger s = new BigInteger("7508d22fd6cbb45efd438cb875e43f137247088d0f54b29a7c91f68a65b5fa85",16);
- GOST3410ParametersGenerator pGen = new GOST3410ParametersGenerator();
-
- pGen.init(1024, 2, init_random);
-
- GOST3410Parameters params = pGen.generateParameters();
-
- if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
- {
- return new SimpleTestResult(false, getName() + ": p or q wrong");
- }
-
- GOST3410KeyPairGenerator GOST3410KeyGen = new GOST3410KeyPairGenerator();
- GOST3410KeyGenerationParameters genParam = new GOST3410KeyGenerationParameters(keyRandom, params);
-
- GOST3410KeyGen.init(genParam);
-
- AsymmetricCipherKeyPair pair = GOST3410KeyGen.generateKeyPair();
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
-
- GOST3410Signer GOST3410 = new GOST3410Signer();
-
- GOST3410.init(true, param);
-
- BigInteger[] sig = GOST3410.generateSignature(hashmessage);
-
- if (!r.equals(sig[0]))
- {
- return new SimpleTestResult(false, getName()
- + ": r component wrong." + System.getProperty("line.separator")
- + " expecting: " + r.toString(16) + System.getProperty("line.separator")
- + " got : " + sig[0].toString(16));
- }
-
- if (!s.equals(sig[1]))
- {
- return new SimpleTestResult(false, getName()
- + ": s component wrong." + System.getProperty("line.separator")
- + " expecting: " + s.toString(16) + System.getProperty("line.separator")
- + " got : " + sig[1].toString(16));
- }
-
- GOST3410.init(false, pair.getPublic());
-
- if (GOST3410.verifySignature(hashmessage, sig[0], sig[1]))
- {
- return new SimpleTestResult(true, getName() + ": Okay");
- }
- else
- {
- return new SimpleTestResult(false, getName() + ": verification fails");
- }
- }
- }
-
- private class GOST3410_CExParam
- implements Test
- {
- public String getName()
- {
- return "GOST3410-CExParam";
- }
-
- SecureRandom init_random = new SecureRandom()
- {
- boolean firstLong = true;
-
- public long nextLong()
- {
- String x0 = "0x162AB910";
- String c = "0x93F828D3";
-
- if (firstLong)
- {
- firstLong = false;
- return NumberParsing.decodeLongFromHex(x0);
- }
- return NumberParsing.decodeLongFromHex(c);
- }
-
- public void nextBytes(byte[] bytes)
- {
- byte[] d = Hex.decode("ca82cce78a738bc46f103d53b9bf809745ec845e4f6da462606c51f60ecf302e31204b81");
-
- System.arraycopy(d, 0, bytes, bytes.length-d.length, d.length);
- }
- };
-
- SecureRandom random = new SecureRandom()
- {
- public void nextBytes(byte[] bytes)
- {
- byte[] k = Hex.decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
-
- int i;
-
- for (i = 0; i < (bytes.length - k.length); i += k.length)
- {
- System.arraycopy(k, 0, bytes, i, k.length);
- }
-
- if (i > bytes.length)
- {
- System.arraycopy(k, 0, bytes, i - k.length, bytes.length - (i - k.length));
- }
- else
- {
- System.arraycopy(k, 0, bytes, i, bytes.length - i);
- }
- }
- };
-
- SecureRandom keyRandom = new SecureRandom()
- {
- public void nextBytes(byte[] bytes)
- {
- byte[] x = Hex.decode("3036314538303830343630454235324435324234314132373832433138443046");
-
- int i;
-
- for (i = 0; i < (bytes.length - x.length); i += x.length)
- {
- System.arraycopy(x, 0, bytes, i, x.length);
- }
-
- if (i > bytes.length)
- {
- System.arraycopy(x, 0, bytes, i - x.length, bytes.length - (i - x.length));
- }
- else
- {
- System.arraycopy(x, 0, bytes, i, bytes.length - i);
- }
- }
- };
-
- BigInteger pValue = new BigInteger("b194036ace14139d36d64295ae6c50fc4b7d65d8b340711366ca93f383653908ee637be428051d86612670ad7b402c09b820fa77d9da29c8111a8496da6c261a53ed252e4d8a69a20376e6addb3bdcd331749a491a184b8fda6d84c31cf05f9119b5ed35246ea4562d85928ba1136a8d0e5a7e5c764ba8902029a1336c631a1d", 16);
- BigInteger qValue = new BigInteger("96120477df0f3896628e6f4a88d83c93204c210ff262bccb7dae450355125259", 16);
-
- public TestResult perform()
- {
- BigInteger r = new BigInteger("169fdb2dc09f690b71332432bfec806042e258fa9a21dafe73c6abfbc71407d9",16);
- BigInteger s = new BigInteger("9002551808ae40d19f6f31fb67e4563101243cf07cffd5f2f8ff4c537b0c9866",16);
- GOST3410ParametersGenerator pGen = new GOST3410ParametersGenerator();
-
- pGen.init(1024, 2, init_random);
-
- GOST3410Parameters params = pGen.generateParameters();
-
- if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
- {
- return new SimpleTestResult(false, getName() + ": p or q wrong");
- }
-
- GOST3410KeyPairGenerator GOST3410KeyGen = new GOST3410KeyPairGenerator();
- GOST3410KeyGenerationParameters genParam = new GOST3410KeyGenerationParameters(keyRandom, params);
-
- GOST3410KeyGen.init(genParam);
-
- AsymmetricCipherKeyPair pair = GOST3410KeyGen.generateKeyPair();
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
-
- GOST3410Signer GOST3410 = new GOST3410Signer();
-
- GOST3410.init(true, param);
-
- BigInteger[] sig = GOST3410.generateSignature(hashmessage);
-
- if (!r.equals(sig[0]))
- {
- return new SimpleTestResult(false, getName()
- + ": r component wrong." + System.getProperty("line.separator")
- + " expecting: " + r.toString(16) + System.getProperty("line.separator")
- + " got : " + sig[0].toString(16));
- }
-
- if (!s.equals(sig[1]))
- {
- return new SimpleTestResult(false, getName()
- + ": s component wrong." + System.getProperty("line.separator")
- + " expecting: " + s.toString(16) + System.getProperty("line.separator")
- + " got : " + sig[1].toString(16));
- }
-
- GOST3410.init(false, pair.getPublic());
-
- if (GOST3410.verifySignature(hashmessage, sig[0], sig[1]))
- {
- return new SimpleTestResult(true, getName() + ": Okay");
- }
- else
- {
- return new SimpleTestResult(false, getName() + ": verification fails");
- }
- }
- }
-
- Test tests[] =
- {
- new GOST3410_TEST1_512(),
- new GOST3410_TEST2_512(),
-// new GOST3410_TEST1_1024(),
-// new GOST3410_TEST2_1024(),
-// new GOST3410_AParam(),
-// new GOST3410_BParam(),
-// new GOST3410_CParam(),
-// new GOST3410_DParam(),
-// new GOST3410_AExParam(),
-// new GOST3410_BExParam(),
-// new GOST3410_CExParam()
- };
-
- public String getName()
- {
- return "GOST3410";
- }
-
- public TestResult perform()
- {
- for (int i = 0; i != tests.length; i++)
- {
- TestResult result = tests[i].perform();
-
- if (!result.isSuccessful())
- {
- return result;
- }
- }
-
- return new SimpleTestResult(true, "GOST3410: Okay");
- }
-
- public static void main(
- String[] args)
- {
- GOST3410Test test = new GOST3410Test();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/GOST3411DigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/GOST3411DigestTest.java
deleted file mode 100644
index 45962fe7..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/GOST3411DigestTest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.GOST3411Digest;
-import org.bouncycastle.crypto.generators.PKCS5S1ParametersGenerator;
-import org.bouncycastle.crypto.macs.HMac;
-import org.bouncycastle.crypto.params.KeyParameter;
-
-public class GOST3411DigestTest
- extends DigestTest
-{
- private static final String[] messages =
- {
- "",
- "This is message, length=32 bytes",
- "Suppose the original message has length = 50 bytes",
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
- };
-
-// If S-box = D-A (see: digest/GOST3411Digest.java; function: E(byte[] in, byte[] key); string: CipherParameters param = new GOST28147Parameters(key,"D-A");)
- private static final String[] digests =
- {
- "981e5f3ca30c841487830f84fb433e13ac1101569b9c13584ac483234cd656c0",
- "2cefc2f7b7bdc514e18ea57fa74ff357e7fa17d652c75f69cb1be7893ede48eb",
- "c3730c5cbccacf915ac292676f21e8bd4ef75331d9405e5f1a61dc3130a65011",
- "73b70a39497de53a6e08c67b6d4db853540f03e9389299d9b0156ef7e85d0f61"
- };
-
-// If S-box = D-Test (see: digest/GOST3411Digest.java; function:E(byte[] in, byte[] key); string: CipherParameters param = new GOST28147Parameters(key,"D-Test");)
-// private static final String[] digests =
-// {
-// "ce85b99cc46752fffee35cab9a7b0278abb4c2d2055cff685af4912c49490f8d",
-// "b1c466d37519b82e8319819ff32595e047a28cb6f83eff1c6916a815a637fffa",
-// "471aba57a60a770d3a76130635c1fbea4ef14de51f78b4ae57dd893b62f55208",
-// "95c1af627c356496d80274330b2cff6a10c67b5f597087202f94d06d2338cf8e"
-// };
-
- // 1 million 'a'
- static private String million_a_digest = "8693287aa62f9478f7cb312ec0866b6c4e4a0f11160441e8f4ffcd2715dd554f";
-
- GOST3411DigestTest()
- {
- super(new GOST3411Digest(), messages, digests);
- }
-
- public void performTest()
- {
- super.performTest();
-
- millionATest(million_a_digest);
-
- HMac gMac = new HMac(new GOST3411Digest());
-
- gMac.init(new KeyParameter(PKCS5S1ParametersGenerator.PKCS5PasswordToUTF8Bytes("1".toCharArray())));
-
- byte[] data = "fred".getBytes();
-
- gMac.update(data, 0, data.length);
- byte[] mac = new byte[gMac.getMacSize()];
-
- gMac.doFinal(mac, 0);
- }
-
- protected Digest cloneDigest(Digest digest)
- {
- return new GOST3411Digest((GOST3411Digest)digest);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new GOST3411DigestTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/Grain128Test.java b/core/src/test/java/org/bouncycastle/crypto/test/Grain128Test.java
deleted file mode 100644
index afac2e0a..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/Grain128Test.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.StreamCipher;
-import org.bouncycastle.crypto.engines.Grain128Engine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * Grain-128 Test
- */
-public class Grain128Test
- extends SimpleTest
-{
-
- String keyStream1 = "f09b7bf7d7f6b5c2de2ffc73ac21397f";
- String keyStream2 = "afb5babfa8de896b4b9c6acaf7c4fbfd";
-
- public String getName()
- {
- return "Grain-128";
- }
-
- public void performTest()
- {
- Grain128Test1(new ParametersWithIV(new KeyParameter(Hex
- .decode("00000000000000000000000000000000")), Hex
- .decode("000000000000000000000000")));
- Grain128Test2(new ParametersWithIV(new KeyParameter(Hex
- .decode("0123456789abcdef123456789abcdef0")), Hex
- .decode("0123456789abcdef12345678")));
- Grain128Test3(new ParametersWithIV(new KeyParameter(Hex
- .decode("0123456789abcdef123456789abcdef0")), Hex
- .decode("0123456789abcdef12345678")));
- }
-
- private void Grain128Test1(CipherParameters params)
- {
- StreamCipher grain = new Grain128Engine();
- byte[] in = new byte[16];
- byte[] out = new byte[16];
-
- grain.init(true, params);
-
- grain.processBytes(in, 0, in.length, out, 0);
-
- if (!areEqual(out, Hex.decode(keyStream1)))
- {
- mismatch("Keystream 1", keyStream1, out);
- }
-
- grain.reset();
-
- grain.processBytes(in, 0, in.length, out, 0);
-
- if (!areEqual(out, Hex.decode(keyStream1)))
- {
- mismatch("Keystream 1", keyStream1, out);
- }
- }
-
- private void Grain128Test2(CipherParameters params)
- {
- StreamCipher grain = new Grain128Engine();
- byte[] in = new byte[16];
- byte[] out = new byte[16];
-
- grain.init(true, params);
-
- grain.processBytes(in, 0, in.length, out, 0);
-
- if (!areEqual(out, Hex.decode(keyStream2)))
- {
- mismatch("Keystream 2", keyStream2, out);
- }
-
- grain.reset();
-
- grain.processBytes(in, 0, in.length, out, 0);
-
- if (!areEqual(out, Hex.decode(keyStream2)))
- {
- mismatch("Keystream 2", keyStream2, out);
- }
- }
-
- private void Grain128Test3(CipherParameters params)
- {
- StreamCipher grain = new Grain128Engine();
- byte[] in = "Encrypt me!".getBytes();
- byte[] cipher = new byte[in.length];
- byte[] clear = new byte[in.length];
-
- grain.init(true, params);
-
- grain.processBytes(in, 0, in.length, cipher, 0);
- grain.reset();
- grain.processBytes(cipher, 0, cipher.length, clear, 0);
-
- if (!areEqual(in, clear))
- {
- mismatch("Test 3", new String(Hex.encode(in)), clear);
- }
- }
-
- private void mismatch(String name, String expected, byte[] found)
- {
- fail("mismatch on " + name, expected, new String(Hex.encode(found)));
- }
-
- public static void main(String[] args)
- {
- runTest(new Grain128Test());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/Grainv1Test.java b/core/src/test/java/org/bouncycastle/crypto/test/Grainv1Test.java
deleted file mode 100644
index b76c1f27..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/Grainv1Test.java
+++ /dev/null
@@ -1,140 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.StreamCipher;
-import org.bouncycastle.crypto.engines.Grainv1Engine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * Grain v1 Test
- */
-public class Grainv1Test
- extends SimpleTest
-{
-
- String keyStream1 = "dee931cf1662a72f77d0";
- String keyStream2 = "7f362bd3f7abae203664";
- String keyStream4 = "017D13ECB20AE0C9ACF784CB06525F72"
- + "CE6D52BEBB948F124668C35064559024"
- + "49EEA505C19F3EE4D052C3D19DA9C4D1"
- + "B92DBC7F07AFEA6A3D845DE60D8471FD";
-
- public String getName()
- {
- return "Grain v1";
- }
-
- public void performTest()
- {
- Grainv1Test1(new ParametersWithIV(new KeyParameter(Hex
- .decode("00000000000000000000")), Hex
- .decode("0000000000000000")));
- Grainv1Test2(new ParametersWithIV(new KeyParameter(Hex
- .decode("0123456789abcdef1234")), Hex
- .decode("0123456789abcdef")));
- Grainv1Test3(new ParametersWithIV(new KeyParameter(Hex
- .decode("0123456789abcdef1234")), Hex
- .decode("0123456789abcdef")));
- Grainv1Test4(new ParametersWithIV(new KeyParameter(Hex
- .decode("0F62B5085BAE0154A7FA")), Hex
- .decode("288FF65DC42B92F9")));
- }
-
- private void Grainv1Test1(CipherParameters params)
- {
- StreamCipher grain = new Grainv1Engine();
- byte[] in = new byte[10];
- byte[] out = new byte[10];
-
- grain.init(true, params);
-
- grain.processBytes(in, 0, in.length, out, 0);
-
- if (!areEqual(out, Hex.decode(keyStream1)))
- {
- mismatch("Keystream 1", keyStream1, out);
- }
-
- grain.reset();
-
- grain.processBytes(in, 0, in.length, out, 0);
-
- if (!areEqual(out, Hex.decode(keyStream1)))
- {
- mismatch("Keystream 1", keyStream1, out);
- }
- }
-
- private void Grainv1Test2(CipherParameters params)
- {
- StreamCipher grain = new Grainv1Engine();
- byte[] in = new byte[10];
- byte[] out = new byte[10];
-
- grain.init(true, params);
-
- grain.processBytes(in, 0, in.length, out, 0);
-
- if (!areEqual(out, Hex.decode(keyStream2)))
- {
- mismatch("Keystream 2", keyStream2, out);
- }
-
- grain.reset();
-
- grain.processBytes(in, 0, in.length, out, 0);
-
- if (!areEqual(out, Hex.decode(keyStream2)))
- {
- mismatch("Keystream 2", keyStream2, out);
- }
- }
-
- private void Grainv1Test3(CipherParameters params)
- {
- StreamCipher grain = new Grainv1Engine();
- byte[] in = "Encrypt me!".getBytes();
- byte[] cipher = new byte[in.length];
- byte[] clear = new byte[in.length];
-
- grain.init(true, params);
-
- grain.processBytes(in, 0, in.length, cipher, 0);
- grain.reset();
- grain.processBytes(cipher, 0, cipher.length, clear, 0);
-
- if (!areEqual(in, clear))
- {
- mismatch("Test 3", new String(Hex.encode(in)), clear);
- }
- }
-
- private void Grainv1Test4(CipherParameters params)
- {
- StreamCipher grain = new Grainv1Engine();
- byte[] in = new byte[keyStream4.length() / 2];
- byte[] out = new byte[in.length];
-
- grain.init(true, params);
-
- grain.processBytes(in, 0, in.length, out, 0);
-
- if (!areEqual(out, Hex.decode(keyStream4)))
- {
- mismatch("Keystream 4", keyStream4, out);
- }
- }
-
- private void mismatch(String name, String expected, byte[] found)
- {
- fail("mismatch on " + name, expected, new String(Hex.encode(found)));
- }
-
- public static void main(String[] args)
- {
- runTest(new Grainv1Test());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/HCFamilyTest.java b/core/src/test/java/org/bouncycastle/crypto/test/HCFamilyTest.java
deleted file mode 100644
index 5604d9cc..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/HCFamilyTest.java
+++ /dev/null
@@ -1,192 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.StreamCipher;
-import org.bouncycastle.crypto.engines.HC128Engine;
-import org.bouncycastle.crypto.engines.HC256Engine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * HC-128 and HC-256 Tests. Based on the test vectors in the official reference
- * papers, respectively:
- * <pre>
- * http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc128_p3.pdf
- * http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc256_p3.pdf
- * </pre>
- * See HCFamilyVecTest for a more exhaustive test based on the ecrypt vectors.
- */
-public class HCFamilyTest
- extends SimpleTest
-{
- private static final byte[] MSG = new byte[64];
-
- private static String[][] HC128_VerifiedTest =
- {
- {
- "Set 2, vector# 0",
- "00000000000000000000000000000000",
- "00000000000000000000000000000000",
- "82001573A003FD3B7FD72FFB0EAF63AA" +
- "C62F12DEB629DCA72785A66268EC758B" +
- "1EDB36900560898178E0AD009ABF1F49" +
- "1330DC1C246E3D6CB264F6900271D59C"
- },
- {
- "Set 6, vector# 0",
- "0053A6F94C9FF24598EB3E91E4378ADD",
- "0D74DB42A91077DE45AC137AE148AF16",
- "2E1ED12A8551C05AF41FF39D8F9DF933" +
- "122B5235D48FC2A6F20037E69BDBBCE8" +
- "05782EFC16C455A4B3FF06142317535E" +
- "F876104C32445138CB26EBC2F88A684C"
- },
- {
- "Set 6, vector# 1",
- "0558ABFE51A4F74A9DF04396E93C8FE2",
- "167DE44BB21980E74EB51C83EA51B81F",
- "4F864BF3C96D0363B1903F0739189138" +
- "F6ED2BC0AF583FEEA0CEA66BA7E06E63" +
- "FB28BF8B3CA0031D24ABB511C57DD17B" +
- "FC2861C32400072CB680DF2E58A5CECC"
- },
- {
- "Set 6, vector# 2",
- "0A5DB00356A9FC4FA2F5489BEE4194E7",
- "1F86ED54BB2289F057BE258CF35AC128",
- "82168AB0023B79AAF1E6B4D823855E14" +
- "A7084378036A951B1CFEF35173875ED8" +
- "6CB66AB8410491A08582BE40080C3102" +
- "193BA567F9E95D096C3CC60927DD7901"
- },
- {
- "Set 6, vector# 3",
- "0F62B5085BAE0154A7FA4DA0F34699EC",
- "288FF65DC42B92F960C72E95FC63CA31",
- "1CD8AEDDFE52E217E835D0B7E84E2922" +
- "D04B1ADBCA53C4522B1AA604C42856A9" +
- "0AF83E2614BCE65C0AECABDD8975B557" +
- "00D6A26D52FFF0888DA38F1DE20B77B7"
- }
- };
-
- private static String[][] HC256_VerifiedTest =
- {
- {
- "Set 2, vector# 0",
- "00000000000000000000000000000000",
- "00000000000000000000000000000000",
- "5B078985D8F6F30D42C5C02FA6B67951" +
- "53F06534801F89F24E74248B720B4818" +
- "CD9227ECEBCF4DBF8DBF6977E4AE14FA" +
- "E8504C7BC8A9F3EA6C0106F5327E6981"
- },
- {
- "Set 2, vector# 9",
- "09090909090909090909090909090909",
- "00000000000000000000000000000000",
- "F5C2926651AEED9AF1A9C2F04C03D081" +
- "2145B56AEA46EB283A25A4C9E3D8BEB4" +
- "821B418F06F2B9DCDF1A85AB8C02CD14" +
- "62E1BBCAEC9AB0E99AA6AFF918BA627C"
- },
- {
- "Set 2, vector#135",
- "87878787878787878787878787878787",
- "00000000000000000000000000000000",
- "CEC0C3852E3B98233EBCB975C10B1191" +
- "3C69F2275EB97A1402EDF16C6FBE19BE" +
- "79D65360445BCB63676E6553B609A065" +
- "0155C3B22DD1975AC0F3F65063A2E16E"
- },
- {
- "Set 6, vector# 0",
- "0053A6F94C9FF24598EB3E91E4378ADD" +
- "3083D6297CCF2275C81B6EC11467BA0D",
- "0D74DB42A91077DE45AC137AE148AF16" +
- "7DE44BB21980E74EB51C83EA51B81F86",
- "23D9E70A45EB0127884D66D9F6F23C01" +
- "D1F88AFD629270127247256C1FFF91E9" +
- "1A797BD98ADD23AE15BEE6EEA3CEFDBF" +
- "A3ED6D22D9C4F459DB10C40CDF4F4DFF"
- },
- {
- "Set 6, vector# 1",
- "0558ABFE51A4F74A9DF04396E93C8FE2" +
- "3588DB2E81D4277ACD2073C6196CBF12",
- "167DE44BB21980E74EB51C83EA51B81F" +
- "86ED54BB2289F057BE258CF35AC1288F",
- "C44B5262F2EAD9C018213127686DB742" +
- "A72D3F2D61D18F0F4E7DE5B4F7ADABE0" +
- "7E0C82033B139F02BAACB4E2F2D0BE30" +
- "110C3A8A2B621523756692877C905DD0"
- },
- {
- "Set 6, vector# 2",
- "0A5DB00356A9FC4FA2F5489BEE4194E7" +
- "3A8DE03386D92C7FD22578CB1E71C417",
- "1F86ED54BB2289F057BE258CF35AC128" +
- "8FF65DC42B92F960C72E95FC63CA3198",
- "9D13AA06122F4F03AE60D507701F1ED0" +
- "63D7530FF35EE76CAEDCBFB01D8A239E" +
- "FA4A44B272DE9B4092E2AD56E87C3A60" +
- "89F5A074D1F6E5B8FC6FABEE0C936F06"
- },
- {
- "Set 6, vector# 3",
- "0F62B5085BAE0154A7FA4DA0F34699EC" +
- "3F92E5388BDE3184D72A7DD02376C91C",
- "288FF65DC42B92F960C72E95FC63CA31" +
- "98FF66CD349B0269D0379E056CD33AA1",
- "C8632038DA61679C4685288B37D3E232" +
- "7BC2D28C266B041FE0CA0D3CFEED8FD5" +
- "753259BAB757168F85EA96ADABD823CA" +
- "4684E918423E091565713FEDDE2CCFE0"
- }
- };
-
- public String getName()
- {
- return "HC-128 and HC-256";
- }
-
- public void performTest()
- {
- StreamCipher hc = new HC256Engine();
-
- for (int i = 0; i != HC256_VerifiedTest.length; i++)
- {
- String[] test = HC256_VerifiedTest[i];
- HCTest(hc, "HC-256 - " + test[0], Hex.decode(test[1]), Hex.decode(test[2]), Hex.decode(test[3]));
- }
-
- hc = new HC128Engine();
-
- for (int i = 0; i != HC128_VerifiedTest.length; i++)
- {
- String[] test = HC128_VerifiedTest[i];
- HCTest(hc, "HC-128 - " + test[0], Hex.decode(test[1]), Hex.decode(test[2]), Hex.decode(test[3]));
- }
- }
-
- private void HCTest(StreamCipher hc, String test, byte[] key, byte[] IV, byte[] expected)
- {
- KeyParameter kp = new KeyParameter(key);
- ParametersWithIV ivp = new ParametersWithIV(kp, IV);
-
- hc.init(true, ivp);
- for (int i = 0; i < 64; i++)
- {
- if (hc.returnByte(MSG[i]) != expected[i])
- {
- fail(test + " failure at byte " + i);
- }
- }
- }
-
- public static void main(String[] args)
- {
- runTest(new HCFamilyTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/HCFamilyVecTest.java b/core/src/test/java/org/bouncycastle/crypto/test/HCFamilyVecTest.java
deleted file mode 100644
index 51247e6a..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/HCFamilyVecTest.java
+++ /dev/null
@@ -1,199 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.StreamCipher;
-import org.bouncycastle.crypto.engines.HC128Engine;
-import org.bouncycastle.crypto.engines.HC256Engine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * HC-128 and HC-256 Tests. Based on the test vectors in the official reference
- * papers, respectively:
- *
- * http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc128_p3.pdf
- * http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc256_p3.pdf
- */
-public class HCFamilyVecTest
- extends SimpleTest
-{
- private static class PeekableLineReader extends BufferedReader
- {
- public PeekableLineReader(Reader r) throws IOException
- {
- super(r);
-
- peek = super.readLine();
- }
-
- public String peekLine()
- {
- return peek;
- }
-
- public String readLine() throws IOException
- {
- String tmp = peek;
- peek = super.readLine();
- return tmp;
- }
-
- private String peek;
- }
-
- public String getName()
- {
- return "HC-128 and HC-256 (ecrypt)";
- }
-
- public void performTest() throws Exception
- {
- runTests(new HC128Engine(), "ecrypt_HC-128.txt");
- runTests(new HC256Engine(), "ecrypt_HC-256_128K_128IV.txt");
- runTests(new HC256Engine(), "ecrypt_HC-256_256K_128IV.txt");
- runTests(new HC256Engine(), "ecrypt_HC-256_128K_256IV.txt");
- runTests(new HC256Engine(), "ecrypt_HC-256_256K_256IV.txt");
- }
-
- private void runTests(StreamCipher hc, String fileName) throws IOException
- {
- Reader resource = new InputStreamReader(getClass().getResourceAsStream(fileName));
- PeekableLineReader r = new PeekableLineReader(resource);
- runAllVectors(hc, fileName, r);
- }
-
- private void runAllVectors(StreamCipher hc, String fileName, PeekableLineReader r)
- throws IOException
- {
- for (;;)
- {
- String line = r.readLine();
- if (line == null)
- {
- break;
- }
-
- line = line.trim();
-
- if (line.startsWith("Set "))
- {
- runVector(hc, fileName, r, dellChar(line, ':'));
- }
- }
- }
-
- private String dellChar(String s, char c)
- {
- StringBuffer b = new StringBuffer();
-
- for (int i = 0; i != s.length(); i++)
- {
- if (s.charAt(i) != c)
- {
- b.append(s.charAt(i));
- }
- }
-
- return b.toString();
- }
-
- private void runVector(StreamCipher hc, String fileName, PeekableLineReader r, String vectorName)
- throws IOException
- {
-// System.out.println(fileName + " => " + vectorName);
- String hexKey = readBlock(r);
- String hexIV = readBlock(r);
-
- CipherParameters cp = new KeyParameter(Hex.decode(hexKey));
- cp = new ParametersWithIV(cp, Hex.decode(hexIV));
- hc.init(true, cp);
-
- byte[] input = new byte[64];
- byte[] output = new byte[64];
- byte[] digest = new byte[64];
- int pos = 0;
-
- for (;;)
- {
- String line1 = r.peekLine().trim();
- int equalsPos = line1.indexOf('=');
- String lead = line1.substring(0, equalsPos - 1);
-
- String hexData = readBlock(r);
- byte[] data = Hex.decode(hexData);
-
- if (lead.equals("xor-digest"))
- {
- if (!Arrays.areEqual(data, digest))
- {
- fail("Failed in " + fileName + " for test vector: " + vectorName + " at " + lead);
-// System.out.println(fileName + " => " + vectorName + " failed at " + lead); return;
- }
- break;
- }
-
- int posA = lead.indexOf('[');
- int posB = lead.indexOf("..");
- int posC = lead.indexOf(']');
- int start = Integer.parseInt(lead.substring(posA + 1, posB));
- int end = Integer.parseInt(lead.substring(posB + 2, posC));
-
- if (start % 64 != 0 || (end - start != 63))
- {
- throw new IllegalStateException(vectorName + ": " + lead + " not on 64 byte boundaries");
- }
-
- while (pos < end)
- {
- hc.processBytes(input, 0, input.length, output, 0);
- xor(digest, output);
- pos += 64;
- }
-
- if (!Arrays.areEqual(data, output))
- {
- fail("Failed in " + fileName + " for test vector: " + vectorName + " at " + lead);
-// System.out.println(fileName + " => " + vectorName + " failed at " + lead); return;
- }
- }
- }
-
- private static String readBlock(PeekableLineReader r) throws IOException
- {
- String first = r.readLine().trim();
- String result = first.substring(first.lastIndexOf(' ') + 1);
-
- for (;;)
- {
- String peek = r.peekLine().trim();
- if (peek.length() < 1 || peek.indexOf('=') >= 0)
- {
- break;
- }
- result += r.readLine().trim();
- }
-
- return result;
- }
-
- private static void xor(byte[] digest, byte[] block)
- {
- for (int i = 0; i < digest.length; ++i)
- {
- digest[i] ^= block[i];
- }
- }
-
- public static void main(String[] args)
- {
- runTest(new HCFamilyVecTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/HKDFGeneratorTest.java b/core/src/test/java/org/bouncycastle/crypto/test/HKDFGeneratorTest.java
deleted file mode 100644
index 95135174..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/HKDFGeneratorTest.java
+++ /dev/null
@@ -1,304 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.generators.HKDFBytesGenerator;
-import org.bouncycastle.crypto.params.HKDFParameters;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * HKDF tests - vectors from RFC 5869, + 2 more, 101 and 102
- */
-public class HKDFGeneratorTest
- extends SimpleTest
-{
-
- public HKDFGeneratorTest()
- {
- }
-
- private void compareOKM(int test, byte[] calculatedOKM, byte[] testOKM)
- {
-
- if (!areEqual(calculatedOKM, testOKM))
- {
- fail("HKDF failed generator test " + test);
- }
- }
-
- public void performTest()
- {
- {
- // === A.1. Test Case 1 - Basic test case with SHA-256 ===
-
- Digest hash = new SHA256Digest();
- byte[] ikm = Hex
- .decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
- byte[] salt = Hex.decode("000102030405060708090a0b0c");
- byte[] info = Hex.decode("f0f1f2f3f4f5f6f7f8f9");
- int l = 42;
- byte[] okm = new byte[l];
-
- HKDFParameters params = new HKDFParameters(ikm, salt, info);
-
- HKDFBytesGenerator hkdf = new HKDFBytesGenerator(hash);
- hkdf.init(params);
- hkdf.generateBytes(okm, 0, l);
-
- compareOKM(1, okm, Hex.decode(
- "3cb25f25faacd57a90434f64d0362f2a" +
- "2d2d0a90cf1a5a4c5db02d56ecc4c5bf" +
- "34007208d5b887185865"));
- }
-
- // === A.2. Test Case 2 - Test with SHA-256 and longer inputs/outputs
- // ===
- {
- Digest hash = new SHA256Digest();
- byte[] ikm = Hex.decode("000102030405060708090a0b0c0d0e0f"
- + "101112131415161718191a1b1c1d1e1f"
- + "202122232425262728292a2b2c2d2e2f"
- + "303132333435363738393a3b3c3d3e3f"
- + "404142434445464748494a4b4c4d4e4f");
- byte[] salt = Hex.decode("606162636465666768696a6b6c6d6e6f"
- + "707172737475767778797a7b7c7d7e7f"
- + "808182838485868788898a8b8c8d8e8f"
- + "909192939495969798999a9b9c9d9e9f"
- + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf");
- byte[] info = Hex.decode("b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
- + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
- + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
- + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
- + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
- int l = 82;
- byte[] okm = new byte[l];
-
- HKDFParameters params = new HKDFParameters(ikm, salt, info);
-
- HKDFBytesGenerator hkdf = new HKDFBytesGenerator(hash);
- hkdf.init(params);
- hkdf.generateBytes(okm, 0, l);
-
- compareOKM(2, okm, Hex.decode(
- "b11e398dc80327a1c8e7f78c596a4934" +
- "4f012eda2d4efad8a050cc4c19afa97c" +
- "59045a99cac7827271cb41c65e590e09" +
- "da3275600c2f09b8367793a9aca3db71" +
- "cc30c58179ec3e87c14c01d5c1f3434f" +
- "1d87"));
- }
-
- {
- // === A.3. Test Case 3 - Test with SHA-256 and zero-length
- // salt/info ===
-
- // setting salt to an empty byte array means that the salt is set to
- // HashLen zero valued bytes
- // setting info to null generates an empty byte array as info
- // structure
-
- Digest hash = new SHA256Digest();
- byte[] ikm = Hex
- .decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
- byte[] salt = new byte[0];
- byte[] info = null;
- int l = 42;
- byte[] okm = new byte[l];
-
- HKDFParameters params = new HKDFParameters(ikm, salt, info);
-
- HKDFBytesGenerator hkdf = new HKDFBytesGenerator(hash);
- hkdf.init(params);
- hkdf.generateBytes(okm, 0, l);
-
- compareOKM(3, okm, Hex.decode(
- "8da4e775a563c18f715f802a063c5a31" +
- "b8a11f5c5ee1879ec3454e5f3c738d2d" +
- "9d201395faa4b61a96c8"));
- }
-
- {
- // === A.4. Test Case 4 - Basic test case with SHA-1 ===
-
- Digest hash = new SHA1Digest();
- byte[] ikm = Hex.decode("0b0b0b0b0b0b0b0b0b0b0b");
- byte[] salt = Hex.decode("000102030405060708090a0b0c");
- byte[] info = Hex.decode("f0f1f2f3f4f5f6f7f8f9");
- int l = 42;
- byte[] okm = new byte[l];
-
- HKDFParameters params = new HKDFParameters(ikm, salt, info);
-
- HKDFBytesGenerator hkdf = new HKDFBytesGenerator(hash);
- hkdf.init(params);
- hkdf.generateBytes(okm, 0, l);
-
- compareOKM(4, okm, Hex.decode(
- "085a01ea1b10f36933068b56efa5ad81" +
- "a4f14b822f5b091568a9cdd4f155fda2" +
- "c22e422478d305f3f896"));
- }
-
- // === A.5. Test Case 5 - Test with SHA-1 and longer inputs/outputs ===
- {
- Digest hash = new SHA1Digest();
- byte[] ikm = Hex.decode("000102030405060708090a0b0c0d0e0f"
- + "101112131415161718191a1b1c1d1e1f"
- + "202122232425262728292a2b2c2d2e2f"
- + "303132333435363738393a3b3c3d3e3f"
- + "404142434445464748494a4b4c4d4e4f");
- byte[] salt = Hex.decode("606162636465666768696a6b6c6d6e6f"
- + "707172737475767778797a7b7c7d7e7f"
- + "808182838485868788898a8b8c8d8e8f"
- + "909192939495969798999a9b9c9d9e9f"
- + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf");
- byte[] info = Hex.decode("b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
- + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
- + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
- + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
- + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
- int l = 82;
- byte[] okm = new byte[l];
-
- HKDFParameters params = new HKDFParameters(ikm, salt, info);
-
- HKDFBytesGenerator hkdf = new HKDFBytesGenerator(hash);
- hkdf.init(params);
- hkdf.generateBytes(okm, 0, l);
-
- compareOKM(5, okm, Hex.decode(
- "0bd770a74d1160f7c9f12cd5912a06eb" +
- "ff6adcae899d92191fe4305673ba2ffe" +
- "8fa3f1a4e5ad79f3f334b3b202b2173c" +
- "486ea37ce3d397ed034c7f9dfeb15c5e" +
- "927336d0441f4c4300e2cff0d0900b52" +
- "d3b4"));
- }
-
- {
- // === A.6. Test Case 6 - Test with SHA-1 and zero-length salt/info
- // ===
-
- // setting salt to null should generate a new salt of HashLen zero
- // valued bytes
-
- Digest hash = new SHA1Digest();
- byte[] ikm = Hex
- .decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
- byte[] salt = null;
- byte[] info = new byte[0];
- int l = 42;
- byte[] okm = new byte[l];
-
- HKDFParameters params = new HKDFParameters(ikm, salt, info);
-
- HKDFBytesGenerator hkdf = new HKDFBytesGenerator(hash);
- hkdf.init(params);
- hkdf.generateBytes(okm, 0, l);
-
- compareOKM(6, okm, Hex.decode(
- "0ac1af7002b3d761d1e55298da9d0506" +
- "b9ae52057220a306e07b6b87e8df21d0" +
- "ea00033de03984d34918"));
- }
-
- {
- // === A.7. Test Case 7 - Test with SHA-1, salt not provided,
- // zero-length info ===
- // (salt defaults to HashLen zero octets)
-
- // this test is identical to test 6 in all ways bar the IKM value
-
- Digest hash = new SHA1Digest();
- byte[] ikm = Hex
- .decode("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c");
- byte[] salt = null;
- byte[] info = new byte[0];
- int l = 42;
- byte[] okm = new byte[l];
-
- HKDFParameters params = new HKDFParameters(ikm, salt, info);
-
- HKDFBytesGenerator hkdf = new HKDFBytesGenerator(hash);
- hkdf.init(params);
- hkdf.generateBytes(okm, 0, l);
-
- compareOKM(7, okm, Hex.decode(
- "2c91117204d745f3500d636a62f64f0a" +
- "b3bae548aa53d423b0d1f27ebba6f5e5" +
- "673a081d70cce7acfc48"));
- }
-
- {
- // === A.101. Additional Test Case - Test with SHA-1, skipping extract
- // zero-length info ===
- // (salt defaults to HashLen zero octets)
-
- // this test is identical to test 7 in all ways bar the IKM value
- // which is set to the PRK value
-
- Digest hash = new SHA1Digest();
- byte[] ikm = Hex
- .decode("2adccada18779e7c2077ad2eb19d3f3e731385dd");
- byte[] info = new byte[0];
- int l = 42;
- byte[] okm = new byte[l];
-
- HKDFParameters params = HKDFParameters.skipExtractParameters(ikm, info);
-
- HKDFBytesGenerator hkdf = new HKDFBytesGenerator(hash);
- hkdf.init(params);
- hkdf.generateBytes(okm, 0, l);
-
- compareOKM(101, okm, Hex.decode(
- "2c91117204d745f3500d636a62f64f0a" +
- "b3bae548aa53d423b0d1f27ebba6f5e5" +
- "673a081d70cce7acfc48"));
- }
-
- // === A.102. Additional Test Case - Test with SHA-1, maximum output ===
- // (salt defaults to HashLen zero octets)
-
- // this test is identical to test 7 in all ways bar the IKM value
-
- Digest hash = new SHA1Digest();
- byte[] ikm = Hex
- .decode("2adccada18779e7c2077ad2eb19d3f3e731385dd");
- byte[] info = new byte[0];
- int l = 255 * hash.getDigestSize();
- byte[] okm = new byte[l];
-
- HKDFParameters params = HKDFParameters.skipExtractParameters(ikm, info);
-
- HKDFBytesGenerator hkdf = new HKDFBytesGenerator(hash);
- hkdf.init(params);
- hkdf.generateBytes(okm, 0, l);
-
- int zeros = 0;
- for (int i = 0; i < hash.getDigestSize(); i++)
- {
- if (okm[i] == 0)
- {
- zeros++;
- }
- }
-
- if (zeros == hash.getDigestSize())
- {
- fail("HKDF failed generator test " + 102);
- }
- }
-
- public String getName()
- {
- return "HKDF";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new HKDFGeneratorTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/HashCommitmentTest.java b/core/src/test/java/org/bouncycastle/crypto/test/HashCommitmentTest.java
deleted file mode 100644
index ed83c64e..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/HashCommitmentTest.java
+++ /dev/null
@@ -1,152 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.Commitment;
-import org.bouncycastle.crypto.Committer;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.commitments.GeneralHashCommitter;
-import org.bouncycastle.crypto.commitments.HashCommitter;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class HashCommitmentTest
- extends SimpleTest
-{
- public String getName()
- {
- return "HashCommitmentTest";
- }
-
- public void performBasicTest()
- throws Exception
- {
- byte[] data = Hex.decode("4e6f77206973207468652074696d6520666f7220616c6c20");
-
- Committer committer = new HashCommitter(new SHA256Digest(), new SecureRandom());
-
- Commitment c = committer.commit(data);
-
- committer = new HashCommitter(new SHA256Digest(), new SecureRandom());
-
- if (!committer.isRevealed(c, data))
- {
- fail("commitment failed to validate");
- }
-
- committer = new HashCommitter(new SHA1Digest(), new SecureRandom());
-
- if (committer.isRevealed(c, data))
- {
- fail("commitment validated!!");
- }
-
- try
- {
- committer.isRevealed(c, new byte[data.length + 1]);
- }
- catch (Exception e)
- {
- if (!e.getMessage().equals("Message and witness secret lengths do not match."))
- {
- fail("exception thrown but wrong message");
- }
- }
-
- // SHA1 has a block size of 512 bits, try a message that's too big
-
- try
- {
- c = committer.commit(new byte[33]);
- }
- catch (DataLengthException e)
- {
- if (!e.getMessage().equals("Message to be committed to too large for digest."))
- {
- fail("exception thrown but wrong message");
- }
- }
- }
-
- public void performGeneralTest()
- throws Exception
- {
- byte[] data = Hex.decode("4e6f77206973207468652074696d6520666f7220616c6c20");
-
- Committer committer = new GeneralHashCommitter(new SHA256Digest(), new SecureRandom());
-
- Commitment c = committer.commit(data);
-
- committer = new GeneralHashCommitter(new SHA256Digest(), new SecureRandom());
-
- if (!committer.isRevealed(c, data))
- {
- fail("general commitment failed to validate");
- }
-
- committer = new GeneralHashCommitter(new SHA1Digest(), new SecureRandom());
-
- if (committer.isRevealed(c, data))
- {
- fail("general commitment validated!!");
- }
-
- c = committer.commit(data);
-
- // try and fool it.
- byte[] s = c.getSecret();
- byte[] newS = Arrays.copyOfRange(s, 0, s.length - 1);
- byte[] newData = new byte[data.length + 1];
-
- newData[0] = s[s.length - 1];
- System.arraycopy(data, 0, newData, 1, data.length);
-
- c = new Commitment(newS, c.getCommitment());
-
- if (committer.isRevealed(c, newData))
- {
- fail("general commitment validated!!");
- }
-
- try
- {
- committer.isRevealed(c, new byte[data.length + 1]);
- }
- catch (Exception e)
- {
- if (!e.getMessage().equals("Message and witness secret lengths do not match."))
- {
- fail("exception thrown but wrong message");
- }
- }
-
- // SHA1 has a block size of 512 bits, try a message that's too big
-
- try
- {
- c = committer.commit(new byte[33]);
- }
- catch (DataLengthException e)
- {
- if (!e.getMessage().equals("Message to be committed to too large for digest."))
- {
- fail("exception thrown but wrong message");
- }
- }
- }
-
- public void performTest()
- throws Exception
- {
- performBasicTest();
- performGeneralTest();
- }
-
- public static void main(String[] args)
- {
- runTest(new HashCommitmentTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/IDEATest.java b/core/src/test/java/org/bouncycastle/crypto/test/IDEATest.java
deleted file mode 100644
index 64c673ee..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/IDEATest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.engines.IDEAEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- */
-public class IDEATest
- extends CipherTest
-{
- static SimpleTest[] tests =
- {
- new BlockCipherVectorTest(0, new IDEAEngine(),
- new KeyParameter(Hex.decode("00112233445566778899AABBCCDDEEFF")),
- "000102030405060708090a0b0c0d0e0f", "ed732271a7b39f475b4b2b6719f194bf"),
- new BlockCipherVectorTest(0, new IDEAEngine(),
- new KeyParameter(Hex.decode("00112233445566778899AABBCCDDEEFF")),
- "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", "b8bc6ed5c899265d2bcfad1fc6d4287d")
- };
-
- IDEATest()
- {
- super(tests, new IDEAEngine(), new KeyParameter(new byte[32]));
- }
-
- public String getName()
- {
- return "IDEA";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new IDEATest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/ISAACTest.java b/core/src/test/java/org/bouncycastle/crypto/test/ISAACTest.java
deleted file mode 100644
index 02319a38..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/ISAACTest.java
+++ /dev/null
@@ -1,180 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.engines.ISAACEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * ISAAC Test - see http://www.burtleburtle.net/bob/rand/isaacafa.html
- */
-public class ISAACTest
- extends SimpleTest
-{
- byte[] out = Hex.decode(
- "f650e4c8e448e96d98db2fb4f5fad54f433f1afbedec154ad837048746ca4f9a" +
- "5de3743e88381097f1d444eb823cedb66a83e1e04a5f6355c744243325890e2e" +
- "7452e31957161df638a824f3002ed71329f5544951c08d83d78cb99ea0cc74f3" +
- "8f651659cbc8b7c2f5f71c6912ad6419e5792e1b860536b809b3ce98d45d6d81" +
- "f3b2612917e38f8529cf72ce349947b0c998f9ffb5e13dae32ae2a2bf7cf814c" +
- "8ebfa303cf22e0640b923200eca4d58aef53cec4d0f7b37d9c411a2affdf8a80" +
- "b40e27bcb4d2f97644b89b08f37c71d51a70e7e90bdb9c3060dc5207b3c3f24b" +
- "d7386806229749b54e232cd091dabc65a70e11018b87437e5781414fcdbc62e2" +
- "8107c9ff69d2e4ae3b18e752b143b6886f4e077295138769943c3c74afc17a97" +
- "0fd439636a529b0bd8c58a6aa8bcc22d2db35dfea7a2f4026cb167db538e1f4e" +
- "7275e2771d3b8e97ecc5dc9115e3a5b90369661430ab93ecac9fe69d7bc76811" +
- "60eda8da28833522d5295ebc5adb60e7f7e1cdd097166d14b67ec13a210f3925" +
- "64af0fef0d0286843aea3decb058bafbb8b0ccfcf2b5cc05e3a662d9814bc24c" +
- "2364a1aa37c0ed052b36505c451e7ec85d2a542fe43d0fbb91c8d92560d4d5f8" +
- "12a0594b9e8a51dacd49ebdb1b0dcdc1cd57c7f7e63444517ded386f2f36fa86" +
- "a6d1210133bc405db388d96cdb6dbe96fe29661c13edc0cbcb0eee4a70cc94ae" +
- "de11ed340606cf9f3a6ce38923d74f4ea37f63ff917bdec2d73f72d40e7e0e67" +
- "3d77d9a213add9228891b3db01a9bd7056a001e3d51f093dcc033ce35ad0d3b0" +
- "34105a8c6a123f57bd2e50247364944be89b1a3b21835c4d9f39e2d9d405ded8" +
- "294d37e5bccaaeed35a124b56708a2bcb00960ba2a98121a4d8fae820bb3263f" +
- "12595a196a1075890809e49421c171ec884d682514c8009bb0b84e7b03fb88f4" +
- "28e7cb789388b13bdd2dc1d5848f520a07c28cd168a3935872c9137d127dd430" +
- "c613f1578c2f0d55f7d3f39f309bfb788406b13746c0a6f53718d59708607f04" +
- "76904b6d04db4e13cd7411a7b510ce0ebfc7f7ccb83f957afdfef62dc35e4580" +
- "3ff1e5244112d96c02c9b944d5990dfbe7e265810d9c7e7e826dfa8966f1e0ab" +
- "30bcc764eadebeaced35e5ee0c571a7de4f3a26af7f58f7badf6bc235d023e65" +
- "1ed3ff4eec46b0b6d2a93b51e75b41c97e315aeb61119a5a53245b7933f6d7b1" +
- "cae8deba50fc8194afa92a6dc87c80064188bfcd8bace62e78ffa5685597ec0f" +
- "b4415f7d08294766ad56764309c36f903dde9f394a0a283c18080c8e080c79ec" +
- "79ae4c10cb9e15637cdd662f62d31911a4ca0cf15cf824cd3b708f991e16614c" +
- "b6b9d7665de87abb7229ea81d5b2d75056e6cd21fe1e42d596da2655c2b9aa36" +
- "b8f6fd4a6a158d1001913fd3af7d1fb80b5e435f90c107576554abda7a68710f" +
- "82ac484fd7e1c7be95c85eaa94a302f44d3cfbda786b29081010b27582d53d12" +
- "21e2a51c3d1e9150b059261dd0638e1a31860f0581f2864dff4cfc350451516d" +
- "bd086f26bc5654c165dfa427a82427f5582e3014b8d2486dc79a17499a1d7745" +
- "8766bb541e04a7f73d3dff8ad5ec6bf4dbef7d9f36ec0ea31feb2e4f15cfcc5c" +
- "d8c423fbd0ef3cc9eb244925ba5590c8a5f48ac433c5321c613b67b2479c3a22" +
- "e21339cc10d210aa931dd7e2ef05ee06b82f2703a385cb2c5d67133c877eb7b4" +
- "1e3437f75afb43ae53c078f394d904811d96458908063a85e13222281956b1e5" +
- "31860f132e7b022f21182ca396f703ac46819e2e0d28fe523724d4dca0eabe6b" +
- "c66699fdc6112fdd19c1e69c04d3658a4b55dd9931907d62f854b5224d678f26" +
- "22ae0582eafed133e4a51d2184bd6dd6c1a513753f28ee63fb737b1a70a1660e" +
- "8a8dfaa31be79937f7476978513c1764531ac6bf12c06908001cdb951a4b6a53" +
- "d067fce512b2cfb69ddb477f740e006639ddf25acc8bfa2df1b20eaf64f2632c" +
- "9783cdee63bfd4d80084cfe575f4e9e219b48fd06c48ddd87a36af9371865c4c" +
- "9ce0199d867027d72cb7b77f84ef01da72f5972f040f7074df9afa29c921f94e" +
- "75c08a3618c1ef9ad649a428c5b719378a30738ad97cd348858129a6239e3b0a" +
- "bbb8abc480fac4c2ecfcf20bd9d711f9e2a4ef71b5fe87c0be8b06b2aafef5a7" +
- "9c15db3b0aeb81654389a84a253b1d7a19047c797cdc78a2d20adf0356f55a71" +
- "3e730fa8fd8650d8959e234eb7546681dad1b22a142a6e858ef4bce668235b9d" +
- "85a13f8574096ae7a949bea229322d0dd568385882846526403dae086dd1943a" +
- "e1279bff9e7e4f041c3a4524484525e481d4cc5fe24124c0037464c0bf1bd691" +
- "26ceb003275ead3ac5bde90826414ff3a30519add7b43abe2ce5d3d588412761" +
- "97ca2070e5fbb9c7276df0b4308f751f37a97df6c9cd808cfe4cb3803d469303" +
- "aee19096c0d5d42a4e823ad3f5f9cc3b4286619c9ca45e1c66c97340891aec49" +
- "45bae606c798f04752649d6cce86fdfc80c6e402d6ec2f2b27c822821fe26ce0" +
- "92f57ea7de462f4d07497cae5a48755c721502dd6cbe7935836d80039ead7f70" +
- "9ab3a42f4c8652d632e39273e8fa38601da4f25a0cd6ef8102503f7d8854a0a1" +
- "9a30c4e88815715305efe29457c4c9252887d96fc1a71e3ce9f841632d0985de" +
- "d21e796c6fb5ce5602614abfc3c7be2cb54fed6fa617a083c3142d8f6079e4ce" +
- "ceffc1471d0cb81bdc153e5fe36ef5bbd531161a165b10157aa114ed3f7579b3" +
- "f7f395f1bc6172c7a86f875e0e6c51b3cdfec2af73c0e762824c2009c5a87748" +
- "94d401258aba3ffbd32be0608c17eff021e2547e07cffad905340e15f3310c92" +
- "9d8d190886ba527ff943f672ef73fbf046d95ca5c54cd95b9d855e894bb5af29");
-
- byte[] outFFFFFFFF = Hex.decode(
- "de3b3f3c19e0629c1fc8b7836695d523e7804edd86ff7ce9b106f52caebae9d9" +
- "72f845d49ce17d7da44e49bae954aac0d0b1284b98a88eec1524fb6bc91a16b5" +
- "1192ac5334131446ac2442de9ff3d5867b9b9148881ee30a6e87dd88e5d1f7cd" +
- "98db31ff36f70d9850cfefaef42abb00ecc39ed308bf4b8030cdc2b6b7e42f0e" +
- "908030dd282f96edacc888b3a986e109c129998f89baa1b5da8970b07a6ab012" +
- "f10264f23c315c9c8e0c164955c68517b6a4f982b2626db70787f869ac6d551b" +
- "e34931627c7058e965c502e18d2cd370e6db3b70d947d61aa9717cf8394f48c6" +
- "3c796f3a154950846badb28b70d982f29bc670254e3e5e0f8e36b0a5f6da0a04" +
- "6b235ed6a42988c012bde74d879fa8eb5d59f5f40ed5e76601c9847b3edb2690");
-
- byte[] outFFFF0000 = Hex.decode(
- "26c54b1f8c4e3fc582e9e8180f7aba5380463dcf58b03cbeda0ecc8ba90ccff8" +
- "5bd50896313d7efed44015faeac6964b241a7fb8a2e37127a7cbea0fd7c020f2" +
- "406371b87ef5185089504751e5e44352eff63e00e5c28f5dff0616a9a3a00f1f" +
- "4a1350e3a17be9abddfc2c94571450a0dc4c3c0c7c7f98e80c95f607d50c676a" +
- "9a3006f9d279a79a4d66b2ab0c52930c9ee84bc09895e70fa041b1a3a2966f11" +
- "6a47fd09705124b1f5c7ae055e54536e66584b1608f3612d81b72f109a385831" +
- "121945b207b90ac72437a248f27a121c2801f4153a8699fb047e193f7ba69e1b" +
- "b117869675d4c963e6070c2ca3d332ce830cb5e3d9ed2eee7faf0acc20fbe154" +
- "188ae789e95bd5c1f459dbd150aab6eb833170257084bc5d44e9df09f5624f9d" +
- "afecd0c9340ac8587f8625d343f7efd1cc8abcf7a6f90eabd4e8e2d906278d6e" +
- "431fcade165c8c467887fbf5c26d341557b064b98c60dd40ab262dc046d69647" +
- "56f3ddc1a07ae5f87be878b9334fcde40add68d2ca1dc05fb1670f998c7c4607" +
- "9a6e48bdb330ad8d30b61b5cc8dc156f5733905931949783f89ac396b65aa4b8" +
- "51f746b53ed8ea66130e1d75e8eab136e60450e3e600226bc8e17d03744ce94c" +
- "0eec9234fea5f18eef65d81f2f10cfbc0b112b8cde17c32eb33ed81d7356eac3" +
- "eb1cb9cefa6604c2d707949b6e5a83e60705bf6aae76dcc7d35d68ff149c1ac5" +
- "424bb4a39e2f496f886637fce3db4ba4ad12c1a32d25e1606f6635ff636486f6" +
- "714997b45477f38813c02afce4bebf196b813332f0decd567c745f441e736364");
-
- byte[] out0000FFFF = Hex.decode(
- "bc31712f2a2f467a5abc737c57ce0f8d49d2f775eb850fc8f856daf19310fee2"+
- "5bab40e78403c9ef4ccd971418992faf4e85ca643fa6b482f30c4659066158a6"+
- "5bc3e620ba7ea5c34dd0eac5aabb2cf078d915fd1f8c437ed00423076c10f701"+
- "eefa7fc7c461aca5db8a87be29d925c4212d4adcfa71ff5b06af15c048aa0dfd"+
- "f0e645bc09fea200c430a88eb38c466ff358b836f1159656a078f6fc752f6db1"+
- "6680bb30fc771a6a785bbb2298e947d7b3500e557775962248bedf4e82c16e66"+
- "f39283ccb95e5399061056a11c4a280f00f7487888199487905273c7aa13012b"+
- "4849eca626cbf071c782e084f9fded57de92313e5f61a6e81117fb1115eff275"+
- "66fd5c755bb3b01bba69aeb8f1b1b1cc9709734be31b35bc707d372ba6fe70d1"+
- "e2c3b0e5e74a7058faff6b11d3a168f19fecc9fcb36b3e6a5f828c01c22ac0c2"+
- "5da2a3a9eec7e0ebbbf51472e430ed4cf1c7ab57ef9aea511e40250846d260b6"+
- "17a3fdeba16cf4afaf700144d3296b58b22a3c79ed96f3e2fc8d9e3c660ae153"+
- "8e0c285ccdc48b59117e80413bd0ad24c6a8d4f133fe1496f14351bb89904fa5"+
- "e10c4b8d50e0604578389c336a9ab3d292beb90ce640fc028e697cf54e021e2f"+
- "c0ca3fe0471fde5e5462f221739a74f5a13ae0621fe2a82e752bc294f63de48d"+
- "e85430af71307a30441b861ab5380e6a6dbe1251c9baa567da14e38e5a0ccddf"+
- "0127205c38fc3b77065e98101d219246103438d223ec7f8f533d4bb3a3d3407a"+
- "944910f11e8e5492e86de7a0471250eca32f0838b3db02fffe71898712af3261");
-
- public String getName()
- {
- return "ISAAC";
- }
-
- public void performTest()
- {
- ISAACEngine engine = new ISAACEngine();
-
- doTest(engine, Hex.decode("00000000"), out);
- doTest(engine, Hex.decode("ffffffff"), outFFFFFFFF);
-
- byte[] k = new byte[256 * 4];
- for (int i = 0; i != k.length; i++)
- {
- k[i] = (byte)((i % 4 == 0 || i % 4 == 1) ? 0xff : 0x00);
- }
- doTest(engine, k, outFFFF0000);
- k = new byte[256 * 4];
- for (int i = 0; i != k.length; i++)
- {
- k[i] = (byte)((i % 4 == 2 || i % 4 == 3) ? 0xff : 0x00);
- }
- doTest(engine, k, out0000FFFF);
- }
-
- private void doTest(ISAACEngine engine, byte[] key, byte[] output)
- {
- byte[] in = new byte[output.length];
- byte[] enc = new byte[output.length];
- engine.init(true, new KeyParameter(key));
- engine.processBytes(in, 0, in.length, enc, 0);
- if (!areEqual(enc, output))
- {
- fail("ciphertext mismatch");
- }
- engine.init(false, new KeyParameter(key));
- engine.processBytes(enc, 0, enc.length, enc, 0);
- if (!areEqual(enc, in))
- {
- fail("plaintext mismatch");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new ISAACTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/ISO9796Test.java b/core/src/test/java/org/bouncycastle/crypto/test/ISO9796Test.java
deleted file mode 100644
index 88d41aaa..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/ISO9796Test.java
+++ /dev/null
@@ -1,972 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.RIPEMD128Digest;
-import org.bouncycastle.crypto.digests.RIPEMD160Digest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.encodings.ISO9796d1Encoding;
-import org.bouncycastle.crypto.engines.RSABlindedEngine;
-import org.bouncycastle.crypto.engines.RSAEngine;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithSalt;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.signers.ISO9796d2PSSSigner;
-import org.bouncycastle.crypto.signers.ISO9796d2Signer;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * test vectors from ISO 9796-1 and ISO 9796-2 edition 1.
- */
-public class ISO9796Test
- extends SimpleTest
-{
- static BigInteger mod1 = new BigInteger("0100000000000000000000000000000000bba2d15dbb303c8a21c5ebbcbae52b7125087920dd7cdf358ea119fd66fb064012ec8ce692f0a0b8e8321b041acd40b7", 16);
-
- static BigInteger pub1 = new BigInteger("03", 16);
-
- static BigInteger pri1 = new BigInteger("2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac9f0783a49dd5f6c5af651f4c9d0dc9281c96a3f16a85f9572d7cc3f2d0f25a9dbf1149e4cdc32273faadd3fda5dcda7", 16);
-
- static BigInteger mod2 = new BigInteger("ffffff7fa27087c35ebead78412d2bdffe0301edd494df13458974ea89b364708f7d0f5a00a50779ddf9f7d4cb80b8891324da251a860c4ec9ef288104b3858d", 16);
-
- static BigInteger pub2 = new BigInteger("03", 16);
-
- static BigInteger pri2 = new BigInteger("2aaaaa9545bd6bf5e51fc7940adcdca5550080524e18cfd88b96e8d1c19de6121b13fac0eb0495d47928e047724d91d1740f6968457ce53ec8e24c9362ce84b5", 16);
-
- static byte msg1[] = Hex.decode("0cbbaa99887766554433221100");
-
- //
- // you'll need to see the ISO 9796 to make sense of this
- //
- static byte sig1[] = mod1.subtract(new BigInteger("309f873d8ded8379490f6097eaafdabc137d3ebfd8f25ab5f138d56a719cdc526bdd022ea65dabab920a81013a85d092e04d3e421caab717c90d89ea45a8d23a", 16)).toByteArray();
-
- static byte msg2[] = Hex.decode("fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210");
-
- static byte sig2[] = new BigInteger("319bb9becb49f3ed1bca26d0fcf09b0b0a508e4d0bd43b350f959b72cd25b3af47d608fdcd248eada74fbe19990dbeb9bf0da4b4e1200243a14e5cab3f7e610c", 16).toByteArray();
-
- static byte msg3[] = Hex.decode("0112233445566778899aabbccd");
-
- static byte sig3[] = mod2.subtract(new BigInteger("58e59ffb4b1fb1bcdbf8d1fe9afa3730c78a318a1134f5791b7313d480ff07ac319b068edf8f212945cb09cf33df30ace54f4a063fcca0b732f4b662dc4e2454", 16)).toByteArray();
-
- //
- // ISO 9796-2
- //
- static BigInteger mod3 = new BigInteger("ffffffff78f6c55506c59785e871211ee120b0b5dd644aa796d82413a47b24573f1be5745b5cd9950f6b389b52350d4e01e90009669a8720bf265a2865994190a661dea3c7828e2e7ca1b19651adc2d5", 16);
-
- static BigInteger pub3 = new BigInteger("03", 16);
-
- static BigInteger pri3 = new BigInteger("2aaaaaaa942920e38120ee965168302fd0301d73a4e60c7143ceb0adf0bf30b9352f50e8b9e4ceedd65343b2179005b2f099915e4b0c37e41314bb0821ad8330d23cba7f589e0f129b04c46b67dfce9d", 16);
-
- static BigInteger mod4 = new BigInteger("FFFFFFFF45f1903ebb83d4d363f70dc647b839f2a84e119b8830b2dec424a1ce0c9fd667966b81407e89278283f27ca8857d40979407fc6da4cc8a20ecb4b8913b5813332409bc1f391a94c9c328dfe46695daf922259174544e2bfbe45cc5cd", 16);
- static BigInteger pub4 = new BigInteger("02", 16);
- static BigInteger pri4 = new BigInteger("1fffffffe8be3207d7707a9a6c7ee1b8c8f7073e5509c2337106165bd8849439c193faccf2cd70280fd124f0507e4f94cb66447680c6b87b6599d1b61c8f3600854a618262e9c1cb1438e485e47437be036d94b906087a61ee74ab0d9a1accd8", 16);
-
- static byte msg4[] = Hex.decode("6162636462636465636465666465666765666768666768696768696a68696a6b696a6b6c6a6b6c6d6b6c6d6e6c6d6e6f6d6e6f706e6f7071");
- static byte sig4[] = Hex.decode("374695b7ee8b273925b4656cc2e008d41463996534aa5aa5afe72a52ffd84e118085f8558f36631471d043ad342de268b94b080bee18a068c10965f581e7f32899ad378835477064abed8ef3bd530fce");
-
- static byte msg5[] = Hex.decode("fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210");
- static byte sig5[] = Hex.decode("5cf9a01854dbacaec83aae8efc563d74538192e95466babacd361d7c86000fe42dcb4581e48e4feb862d04698da9203b1803b262105104d510b365ee9c660857ba1c001aa57abfd1c8de92e47c275cae");
-
- //
- // scheme 2 data
- //
- static BigInteger mod6 = new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16);
- static BigInteger pub6 = new BigInteger("11", 16);
- static BigInteger pri6 = new BigInteger("92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619", 16);
-
- static byte sig6[] = new BigInteger("0073FEAF13EB12914A43FE635022BB4AB8188A8F3ABD8D8A9E4AD6C355EE920359C7F237AE36B1212FE947F676C68FE362247D27D1F298CA9302EB21F4A64C26CE44471EF8C0DFE1A54606F0BA8E63E87CDACA993BFA62973B567473B4D38FAE73AB228600934A9CC1D3263E632E21FD52D2B95C5F7023DA63DE9509C01F6C7BBC", 16).modPow(pri6, mod6).toByteArray();
-
- static byte msg7[] = Hex.decode("6162636462636465636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F70716F70717270717273");
- static byte sig7[] = new BigInteger("296B06224010E1EC230D4560A5F88F03550AAFCE31C805CE81E811E5E53E5F71AE64FC2A2A486B193E87972D90C54B807A862F21A21919A43ECF067240A8C8C641DE8DCDF1942CF790D136728FFC0D98FB906E7939C1EC0E64C0E067F0A7443D6170E411DF91F797D1FFD74009C4638462E69D5923E7433AEC028B9A90E633CC", 16).modPow(pri6, mod6).toByteArray();
-
- static byte msg8[] = Hex.decode("FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA98");
- static byte sig8[] = new BigInteger("01402B29ABA104079677CE7FC3D5A84DB24494D6F9508B4596484F5B3CC7E8AFCC4DDE7081F21CAE9D4F94D6D2CCCB43FCEDA0988FFD4EF2EAE72CFDEB4A2638F0A34A0C49664CD9DB723315759D758836C8BA26AC4348B66958AC94AE0B5A75195B57ABFB9971E21337A4B517F2E820B81F26BCE7C66F48A2DB12A8F3D731CC", 16).modPow(pri6, mod6).toByteArray();
-
- static byte msg9[] = Hex.decode("6162636462636465636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F70716F707172707172737172737472737475737475767475767775767778767778797778797A78797A61797A61627A6162636162636462636465");
- static byte sig9[] = new BigInteger("6F2BB97571FE2EF205B66000E9DD06656655C1977F374E8666D636556A5FEEEEAF645555B25F45567C4EE5341F96FED86508C90A9E3F11B26E8D496139ED3E55ECE42860A6FB3A0817DAFBF13019D93E1D382DA07264FE99D9797D2F0B7779357CA7E74EE440D8855B7DDF15F000AC58EE3FFF144845E771907C0C83324A6FBC", 16).modPow(pri6, mod6).toByteArray();
-
- public String getName()
- {
- return "ISO9796";
- }
-
- private boolean isSameAs(
- byte[] a,
- int off,
- byte[] b)
- {
- if ((a.length - off) != b.length)
- {
- return false;
- }
-
- for (int i = 0; i != b.length; i++)
- {
- if (a[i + off] != b[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- private boolean startsWith(
- byte[] a,
- byte[] b)
- {
- if (a.length < b.length)
- {
- return false;
- }
-
- for (int i = 0; i != b.length; i++)
- {
- if (a[i] != b[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- private void doTest1()
- throws Exception
- {
- RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod1, pub1);
- RSAKeyParameters privParameters = new RSAKeyParameters(true, mod1, pri1);
- RSAEngine rsa = new RSAEngine();
- byte[] data;
-
- //
- // ISO 9796-1 - public encrypt, private decrypt
- //
- ISO9796d1Encoding eng = new ISO9796d1Encoding(rsa);
-
- eng.init(true, privParameters);
-
- eng.setPadBits(4);
-
- data = eng.processBlock(msg1, 0, msg1.length);
-
- eng.init(false, pubParameters);
-
- if (!areEqual(sig1, data))
- {
- fail("failed ISO9796-1 generation Test 1");
- }
-
- data = eng.processBlock(data, 0, data.length);
-
- if (!areEqual(msg1, data))
- {
- fail("failed ISO9796-1 retrieve Test 1");
- }
- }
-
- private void doTest2()
- throws Exception
- {
- RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod1, pub1);
- RSAKeyParameters privParameters = new RSAKeyParameters(true, mod1, pri1);
- RSAEngine rsa = new RSAEngine();
- byte[] data;
-
- //
- // ISO 9796-1 - public encrypt, private decrypt
- //
- ISO9796d1Encoding eng = new ISO9796d1Encoding(rsa);
-
- eng.init(true, privParameters);
-
- data = eng.processBlock(msg2, 0, msg2.length);
-
- eng.init(false, pubParameters);
-
- if (!isSameAs(data, 1, sig2))
- {
- fail("failed ISO9796-1 generation Test 2");
- }
-
- data = eng.processBlock(data, 0, data.length);
-
-
- if (!areEqual(msg2, data))
- {
- fail("failed ISO9796-1 retrieve Test 2");
- }
- }
-
- public void doTest3()
- throws Exception
- {
- RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod2, pub2);
- RSAKeyParameters privParameters = new RSAKeyParameters(true, mod2, pri2);
- RSAEngine rsa = new RSAEngine();
- byte[] data;
-
- //
- // ISO 9796-1 - public encrypt, private decrypt
- //
- ISO9796d1Encoding eng = new ISO9796d1Encoding(rsa);
-
- eng.init(true, privParameters);
-
- eng.setPadBits(4);
-
- data = eng.processBlock(msg3, 0, msg3.length);
-
- eng.init(false, pubParameters);
-
- if (!isSameAs(sig3, 1, data))
- {
- fail("failed ISO9796-1 generation Test 3");
- }
-
- data = eng.processBlock(data, 0, data.length);
-
- if (!isSameAs(msg3, 0, data))
- {
- fail("failed ISO9796-1 retrieve Test 3");
- }
- }
-
- public void doTest4()
- throws Exception
- {
- RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod3, pub3);
- RSAKeyParameters privParameters = new RSAKeyParameters(true, mod3, pri3);
- RSAEngine rsa = new RSAEngine();
- byte[] data;
-
- //
- // ISO 9796-2 - Signing
- //
- ISO9796d2Signer eng = new ISO9796d2Signer(rsa, new RIPEMD128Digest());
-
- eng.init(true, privParameters);
-
- eng.update(msg4[0]);
- eng.update(msg4, 1, msg4.length - 1);
-
- data = eng.generateSignature();
-
- eng.init(false, pubParameters);
-
- if (!isSameAs(sig4, 0, data))
- {
- fail("failed ISO9796-2 generation Test 4");
- }
-
- eng.update(msg4[0]);
- eng.update(msg4, 1, msg4.length - 1);
-
- if (!eng.verifySignature(sig4))
- {
- fail("failed ISO9796-2 verify Test 4");
- }
-
- if (eng.hasFullMessage())
- {
- eng = new ISO9796d2Signer(rsa, new RIPEMD128Digest());
-
- eng.init(false, pubParameters);
-
- if (!eng.verifySignature(sig4))
- {
- fail("failed ISO9796-2 verify and recover Test 4");
- }
-
- if (!isSameAs(eng.getRecoveredMessage(), 0, msg4))
- {
- fail("failed ISO9796-2 recovered message Test 4");
- }
-
- // try update with recovered
- eng.updateWithRecoveredMessage(sig4);
-
- if (!isSameAs(eng.getRecoveredMessage(), 0, msg4))
- {
- fail("failed ISO9796-2 updateWithRecovered recovered message Test 4");
- }
-
- if (!eng.verifySignature(sig4))
- {
- fail("failed ISO9796-2 updateWithRecovered verify and recover Test 4");
- }
-
- if (!isSameAs(eng.getRecoveredMessage(), 0, msg4))
- {
- fail("failed ISO9796-2 updateWithRecovered recovered verify message Test 4");
- }
-
- // should fail
- eng.updateWithRecoveredMessage(sig4);
-
- eng.update(msg4, 0, msg4.length);
-
- if (eng.verifySignature(sig4))
- {
- fail("failed ISO9796-2 updateWithRecovered verify and recover Test 4");
- }
- }
- else
- {
- fail("full message flag false - Test 4");
- }
- }
-
- public void doTest5()
- throws Exception
- {
- RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod3, pub3);
- RSAKeyParameters privParameters = new RSAKeyParameters(true, mod3, pri3);
- RSAEngine rsa = new RSAEngine();
- byte[] data;
-
- //
- // ISO 9796-2 - Signing
- //
- ISO9796d2Signer eng = new ISO9796d2Signer(rsa, new RIPEMD160Digest(), true);
-
- eng.init(true, privParameters);
-
- eng.update(msg5[0]);
- eng.update(msg5, 1, msg5.length - 1);
-
- data = eng.generateSignature();
-
- eng.init(false, pubParameters);
-
- if (!isSameAs(sig5, 0, data))
- {
- fail("failed ISO9796-2 generation Test 5");
- }
-
- eng.update(msg5[0]);
- eng.update(msg5, 1, msg5.length - 1);
-
- if (!eng.verifySignature(sig5))
- {
- fail("failed ISO9796-2 verify Test 5");
- }
-
- if (eng.hasFullMessage())
- {
- fail("fullMessage true - Test 5");
- }
-
- if (!startsWith(msg5, eng.getRecoveredMessage()))
- {
- fail("failed ISO9796-2 partial recovered message Test 5");
- }
-
- int length = eng.getRecoveredMessage().length;
-
- if (length >= msg5.length)
- {
- fail("Test 5 recovered message too long");
- }
-
- eng = new ISO9796d2Signer(rsa, new RIPEMD160Digest(), true);
-
- eng.init(false, pubParameters);
-
- eng.updateWithRecoveredMessage(sig5);
-
- if (!startsWith(msg5, eng.getRecoveredMessage()))
- {
- fail("failed ISO9796-2 updateWithRecovered partial recovered message Test 5");
- }
-
- if (eng.hasFullMessage())
- {
- fail("fullMessage updateWithRecovered true - Test 5");
- }
-
- for (int i = length; i != msg5.length; i++)
- {
- eng.update(msg5[i]);
- }
-
- if (!eng.verifySignature(sig5))
- {
- fail("failed ISO9796-2 verify Test 5");
- }
-
- if (eng.hasFullMessage())
- {
- fail("fullMessage updateWithRecovered true - Test 5");
- }
-
- // should fail
- eng.updateWithRecoveredMessage(sig5);
-
- eng.update(msg5, 0, msg5.length);
-
- if (eng.verifySignature(sig5))
- {
- fail("failed ISO9796-2 updateWithRecovered verify fail Test 5");
- }
- }
-
- //
- // against a zero length string
- //
-
- public void doTest6()
- throws Exception
- {
- byte[] salt = Hex.decode("61DF870C4890FE85D6E3DD87C3DCE3723F91DB49");
- RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod6, pub6);
- RSAKeyParameters privParameters = new RSAKeyParameters(true, mod6, pri6);
- ParametersWithSalt sigParameters = new ParametersWithSalt(privParameters, salt);
- RSAEngine rsa = new RSAEngine();
- byte[] data;
-
- //
- // ISO 9796-2 - PSS Signing
- //
- ISO9796d2PSSSigner eng = new ISO9796d2PSSSigner(rsa, new RIPEMD160Digest(), 20, true);
-
- eng.init(true, sigParameters);
-
- data = eng.generateSignature();
-
- eng.init(false, pubParameters);
-
- if (!isSameAs(sig6, 1, data))
- {
- fail("failed ISO9796-2 generation Test 6");
- }
-
- if (!eng.verifySignature(data))
- {
- fail("failed ISO9796-2 verify Test 6");
- }
- }
-
- public void doTest7()
- throws Exception
- {
- byte[] salt = new byte[0];
- RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod6, pub6);
- RSAKeyParameters privParameters = new RSAKeyParameters(true, mod6, pri6);
- ParametersWithSalt sigParameters = new ParametersWithSalt(privParameters, salt);
- RSAEngine rsa = new RSAEngine();
- byte[] data;
-
- //
- // ISO 9796-2 - PSS Signing
- //
- ISO9796d2PSSSigner eng = new ISO9796d2PSSSigner(rsa, new SHA1Digest(), 0, false);
-
- eng.init(true, sigParameters);
-
- eng.update(msg7[0]);
- eng.update(msg7, 1, msg7.length - 1);
-
- data = eng.generateSignature();
-
- eng.init(false, pubParameters);
-
- if (!isSameAs(sig7, 0, data))
- {
- fail("failed ISO9796-2 generation Test 7");
- }
-
- eng.update(msg7[0]);
- eng.update(msg7, 1, msg7.length - 1);
-
- if (!eng.verifySignature(sig7))
- {
- fail("failed ISO9796-2 verify Test 7");
- }
-
- if (!isSameAs(msg7, 0, eng.getRecoveredMessage()))
- {
- fail("failed ISO9796-2 recovery Test 7");
- }
- }
-
- public void doTest8()
- throws Exception
- {
- byte[] salt = Hex.decode("78E293203CBA1B7F92F05F4D171FF8CA3E738FF8");
- RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod6, pub6);
- RSAKeyParameters privParameters = new RSAKeyParameters(true, mod6, pri6);
- ParametersWithSalt sigParameters = new ParametersWithSalt(privParameters, salt);
- RSAEngine rsa = new RSAEngine();
- byte[] data;
-
- //
- // ISO 9796-2 - PSS Signing
- //
- ISO9796d2PSSSigner eng = new ISO9796d2PSSSigner(rsa, new RIPEMD160Digest(), 20, false);
-
- eng.init(true, sigParameters);
-
- eng.update(msg8[0]);
- eng.update(msg8, 1, msg8.length - 1);
-
- data = eng.generateSignature();
-
- eng.init(false, pubParameters);
-
- if (!isSameAs(sig8, 0, data))
- {
- fail("failed ISO9796-2 generation Test 8");
- }
-
- eng.update(msg8[0]);
- eng.update(msg8, 1, msg8.length - 1);
-
- if (!eng.verifySignature(sig8))
- {
- fail("failed ISO9796-2 verify Test 8");
- }
- }
-
- public void doTest9()
- throws Exception
- {
- RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod6, pub6);
- RSAKeyParameters privParameters = new RSAKeyParameters(true, mod6, pri6);
- RSAEngine rsa = new RSAEngine();
- byte[] data;
-
- //
- // ISO 9796-2 - PSS Signing
- //
- ISO9796d2PSSSigner eng = new ISO9796d2PSSSigner(rsa, new RIPEMD160Digest(), 0, true);
-
- eng.init(true, privParameters);
-
- eng.update(msg9[0]);
- eng.update(msg9, 1, msg9.length - 1);
-
- data = eng.generateSignature();
-
- eng.init(false, pubParameters);
-
- if (!isSameAs(sig9, 0, data))
- {
- fail("failed ISO9796-2 generation Test 9");
- }
-
- eng.update(msg9[0]);
- eng.update(msg9, 1, msg9.length - 1);
-
- if (!eng.verifySignature(sig9))
- {
- fail("failed ISO9796-2 verify Test 9");
- }
- }
-
- public void doTest10()
- throws Exception
- {
- BigInteger mod = new BigInteger("B3ABE6D91A4020920F8B3847764ECB34C4EB64151A96FDE7B614DC986C810FF2FD73575BDF8532C06004C8B4C8B64F700A50AEC68C0701ED10E8D211A4EA554D", 16);
- BigInteger pubExp = new BigInteger("65537", 10);
- BigInteger priExp = new BigInteger("AEE76AE4716F77C5782838F328327012C097BD67E5E892E75C1356E372CCF8EE1AA2D2CBDFB4DA19F703743F7C0BA42B2D69202BA7338C294D1F8B6A5771FF41", 16);
- RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod, pubExp);
- RSAKeyParameters privParameters = new RSAKeyParameters(true, mod, priExp);
- RSAEngine rsa = new RSAEngine();
- byte[] data;
-
- //
- // ISO 9796-2 - PSS Signing
- //
- Digest dig = new SHA1Digest();
- ISO9796d2PSSSigner eng = new ISO9796d2PSSSigner(rsa, dig, dig.getDigestSize());
-
- //
- // as the padding is random this test needs to repeat a few times to
- // make sure
- //
- for (int i = 0; i != 500; i++)
- {
- eng.init(true, privParameters);
-
- eng.update(msg9[0]);
- eng.update(msg9, 1, msg9.length - 1);
-
- data = eng.generateSignature();
-
- eng.init(false, pubParameters);
-
- eng.update(msg9[0]);
- eng.update(msg9, 1, msg9.length - 1);
-
- if (!eng.verifySignature(data))
- {
- fail("failed ISO9796-2 verify Test 10");
- }
- }
- }
-
- public void doTest11()
- throws Exception
- {
- BigInteger mod = new BigInteger("B3ABE6D91A4020920F8B3847764ECB34C4EB64151A96FDE7B614DC986C810FF2FD73575BDF8532C06004C8B4C8B64F700A50AEC68C0701ED10E8D211A4EA554D", 16);
- BigInteger pubExp = new BigInteger("65537", 10);
- BigInteger priExp = new BigInteger("AEE76AE4716F77C5782838F328327012C097BD67E5E892E75C1356E372CCF8EE1AA2D2CBDFB4DA19F703743F7C0BA42B2D69202BA7338C294D1F8B6A5771FF41", 16);
- RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod, pubExp);
- RSAKeyParameters privParameters = new RSAKeyParameters(true, mod, priExp);
- RSAEngine rsa = new RSAEngine();
- byte[] data;
- byte[] m1 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
- byte[] m2 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
- byte[] m3 = {1, 2, 3, 4, 5, 6, 7, 8};
-
- //
- // ISO 9796-2 - PSS Signing
- //
- Digest dig = new SHA1Digest();
- ISO9796d2PSSSigner eng = new ISO9796d2PSSSigner(rsa, dig, dig.getDigestSize());
-
- //
- // check message bounds
- //
- eng.init(true, privParameters);
-
- eng.update(m1, 0, m1.length);
-
- data = eng.generateSignature();
-
- eng.init(false, pubParameters);
-
- eng.update(m2, 0, m2.length);
-
- if (eng.verifySignature(data))
- {
- fail("failed ISO9796-2 m2 verify Test 11");
- }
-
- eng.init(false, pubParameters);
-
- eng.update(m3, 0, m3.length);
-
- if (eng.verifySignature(data))
- {
- fail("failed ISO9796-2 m3 verify Test 11");
- }
-
- eng.init(false, pubParameters);
-
- eng.update(m1, 0, m1.length);
-
- if (!eng.verifySignature(data))
- {
- fail("failed ISO9796-2 verify Test 11");
- }
- }
-
- public void doTest12()
- throws Exception
- {
- BigInteger mod = new BigInteger("B3ABE6D91A4020920F8B3847764ECB34C4EB64151A96FDE7B614DC986C810FF2FD73575BDF8532C06004C8B4C8B64F700A50AEC68C0701ED10E8D211A4EA554D", 16);
- BigInteger pubExp = new BigInteger("65537", 10);
- BigInteger priExp = new BigInteger("AEE76AE4716F77C5782838F328327012C097BD67E5E892E75C1356E372CCF8EE1AA2D2CBDFB4DA19F703743F7C0BA42B2D69202BA7338C294D1F8B6A5771FF41", 16);
- RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod, pubExp);
- RSAKeyParameters privParameters = new RSAKeyParameters(true, mod, priExp);
- RSAEngine rsa = new RSAEngine();
- byte[] data;
- byte[] m1 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
- byte[] m2 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
- byte[] m3 = {1, 2, 3, 4, 5, 6, 7, 8};
-
- //
- // ISO 9796-2 - Signing
- //
- Digest dig = new SHA1Digest();
- ISO9796d2Signer eng = new ISO9796d2Signer(rsa, dig);
-
- //
- // check message bounds
- //
- eng.init(true, privParameters);
-
- eng.update(m1, 0, m1.length);
-
- data = eng.generateSignature();
-
- eng.init(false, pubParameters);
-
- eng.update(m2, 0, m2.length);
-
- if (eng.verifySignature(data))
- {
- fail("failed ISO9796-2 m2 verify Test 12");
- }
-
- eng.init(false, pubParameters);
-
- eng.update(m3, 0, m3.length);
-
- if (eng.verifySignature(data))
- {
- fail("failed ISO9796-2 m3 verify Test 12");
- }
-
- eng.init(false, pubParameters);
-
- eng.update(m1, 0, m1.length);
-
- if (!eng.verifySignature(data))
- {
- fail("failed ISO9796-2 verify Test 12");
- }
- }
-
- private void doTest13()
- throws Exception
- {
- BigInteger modulus = new BigInteger(1, Hex.decode("CDCBDABBF93BE8E8294E32B055256BBD0397735189BF75816341BB0D488D05D627991221DF7D59835C76A4BB4808ADEEB779E7794504E956ADC2A661B46904CDC71337DD29DDDD454124EF79CFDD7BC2C21952573CEFBA485CC38C6BD2428809B5A31A898A6B5648CAA4ED678D9743B589134B7187478996300EDBA16271A861"));
- BigInteger pubExp = new BigInteger(1, Hex.decode("010001"));
- BigInteger privExp = new BigInteger(1, Hex.decode("4BA6432AD42C74AA5AFCB6DF60FD57846CBC909489994ABD9C59FE439CC6D23D6DE2F3EA65B8335E796FD7904CA37C248367997257AFBD82B26F1A30525C447A236C65E6ADE43ECAAF7283584B2570FA07B340D9C9380D88EAACFFAEEFE7F472DBC9735C3FF3A3211E8A6BBFD94456B6A33C17A2C4EC18CE6335150548ED126D"));
-
- RSAKeyParameters pubParams = new RSAKeyParameters(false, modulus, pubExp);
- RSAKeyParameters privParams = new RSAKeyParameters(true, modulus, privExp);
-
- AsymmetricBlockCipher rsaEngine = new RSABlindedEngine();
- Digest digest = new SHA256Digest();
-
- // set challenge to all zero's for verification
- byte[] challenge = new byte[8];
-
- // DOES NOT USE FINAL BOOLEAN TO INDICATE RECOVERY
- ISO9796d2Signer signer = new ISO9796d2Signer(rsaEngine, digest, false);
-
- // sign
- signer.init(true, privParams);
- signer.update(challenge, 0, challenge.length);
-
- byte[] sig = signer.generateSignature();
-
- // verify
- signer.init(false, pubParams);
- signer.update(challenge, 0, challenge.length);
-
- if (!signer.verifySignature(sig))
- {
- fail("basic verification failed");
- }
-
- // === LETS ACTUALLY DO SOME RECOVERY, USING INPUT FROM INTERNAL AUTHENTICATE ===
-
- signer.reset();
-
- final String args0 = "482E20D1EDDED34359C38F5E7C01203F9D6B2641CDCA5C404D49ADAEDE034C7481D781D043722587761C90468DE69C6585A1E8B9C322F90E1B580EEDAB3F6007D0C366CF92B4DB8B41C8314929DCE2BE889C0129123484D2FD3D12763D2EBFD12AC8E51D7061AFCA1A53DEDEC7B9A617472A78C952CCC72467AE008E5F132994";
-
- digest = new SHA1Digest();
-
- signer = new ISO9796d2Signer(rsaEngine, digest, true);
-
-
- signer.init(false, pubParams);
- final byte[] signature = Hex.decode(args0);
- signer.updateWithRecoveredMessage(signature);
- signer.update(challenge, 0, challenge.length);
-
- if (!signer.verifySignature(signature))
- {
- fail("recovered + challenge signature failed");
- }
-
- // === FINALLY, USING SHA-256 ===
-
- signer.reset();
-
- digest = new SHA256Digest();
-
- // NOTE setting implit to false does not actually do anything for verification !!!
- signer = new ISO9796d2Signer(rsaEngine, digest, false);
-
-
- signer.init(true, privParams);
- // generate NONCE of correct length using some inner knowledge
- int nonceLength = modulus.bitLength() / 8 - 1 - digest.getDigestSize() - 2;
- final byte[] nonce = new byte[nonceLength];
- SecureRandom rnd = new SecureRandom();
-
- rnd.nextBytes(nonce);
-
- signer.update(nonce, 0, nonce.length);
- signer.update(challenge, 0, challenge.length);
- byte[] sig3 = signer.generateSignature();
-
- signer.init(false, pubParams);
- signer.updateWithRecoveredMessage(sig3);
- signer.update(challenge, 0, challenge.length);
- if (signer.verifySignature(sig3))
- {
- if (signer.hasFullMessage())
- {
- fail("signer indicates full message");
- }
- byte[] recoverableMessage = signer.getRecoveredMessage();
-
- // sanity check, normally the nonce is ignored in eMRTD specs (PKI Technical Report)
- if (!Arrays.areEqual(nonce, recoverableMessage))
- {
- fail("Nonce compare with recoverable part of message failed");
- }
- }
- else
- {
- fail("recoverable + nonce failed.");
- }
- }
-
- private static final byte[] longMessage = Base64.decode(
- "VVNIKzErU0U2ODAxNTMyOTcxOSsyKzErNisyKzErMTo6OTk5OTk5OTk5OTk5"
- + "OTo6OSsyOjo3Nzc3Nzc3Nzc3Nzc3Ojo5Kys1OjIwMTMwNDA1OjExMzUyMCdV"
- + "U0ErMTo6OjE2OjEnVVNDKzRmYjk3YzFhNDI5ZGIyZDYnVVNBKzY6MTY6MTox"
- + "MDoxKzE0OjIwNDgrMTI6/vn3S0h96eNhfmPN6OZUxXhd815h0tP871Hl+V1r"
- + "fHHUXvrPXmjHV0vdb8fYY1zxwvnQUcFBWXT43PFi7Xbow0/9e9l6/mhs1UJq"
- + "VPvp+ELbeXfn4Nj02ttk0e3H5Hfa69NYRuHv1WBO6lfizNnM9m9XYmh9TOrg"
- + "f9rDRtd+ZNbf4lz9fPTt9OXyxOJWRPr/0FLzxUVsddplfHxM3ndETFD7ffjI"
- + "/mhRYuL8WXZ733LeWFRCeOzKzmDz/HvT3GZx/XJMbFpqyOZjedzh6vZr1vrD"
- + "615TQfN7wtJJ29bN2Hvzb2f1xGHaXl7af0/w9dpR2dr7/HzuZEJKYc7JSkv4"
- + "/k37yERIbcrfbVTeVtR+dcVoeeRT41fmzMfzf8RnWOX4YMNifl0rMTM68EFA"
- + "QSdCR00rMzgwKzk5OTk5OTk5J0RUTSsxMzc6MjAxMzA0MDU6MTAyJ0ZUWCtB"
- + "QUkrKytJTlZPSUNFIFRFU1QnUkZGK09OOjEyMzQ1NidSRkYrRFE6MjIyMjIy"
- + "MjIyJ0RUTSsxNzE6MjAxMzA0MDE6MTAyJ05BRCtTVSs5OTk5OTk5OTk5OTk5"
- + "Ojo5KytURVNUIFNVUFBMSUVSOjpUcmFzZSByZWdpc3RlciBYWFhYWFhYK1Rl"
- + "c3QgYWRkcmVzcyBzdXBwbGllcitDaXR5KysxMjM0NStERSdSRkYrVkE6QTEy"
- + "MzQ1Njc4J05BRCtTQ08rOTk5OTk5OTk5OTk5OTo6OSsrVEVTVCBTVVBQTElF"
- + "Ujo6VHJhc2UgcmVnaXN0ZXIgWFhYWFhYWCtUZXN0IGFkZHJlc3Mgc3VwcGxp"
- + "ZXIrQ2l0eSsrMTIzNDUrREUnUkZGK1ZBOkExMjM0NTY3OCdOQUQrQlkrODg4"
- + "ODg4ODg4ODg4ODo6OSdOQUQrSVYrNzc3Nzc3Nzc3Nzc3Nzo6OSsrVEVTVCBC"
- + "VVlFUitUZXN0IGFkZHJlc3MgYnV5ZXIrQ2l0eTIrKzU0MzIxK0RFJ1JGRitW"
- + "QTpKODc2NTQzMjEnTkFEK0JDTys3Nzc3Nzc3Nzc3Nzc3Ojo5KytURVNUIEJV"
- + "WUVSK1Rlc3QgYWRkcmVzcyBidXllcitDaXR5MisrNTQzMjErREUnUkZGK1ZB"
- + "Oko4NzY1NDMyMSdOQUQrRFArODg4ODg4ODg4ODg4ODo6OSdOQUQrUFIrNzc3"
- + "Nzc3Nzc3Nzc3Nzo6OSdDVVgrMjpFVVI6NCdQQVQrMzUnRFRNKzEzOjIwMTMw"
- + "NjI0OjEwMidMSU4rMSsrMTExMTExMTExMTExMTpFTidQSUErMStBQUFBQUFB"
- + "OlNBJ0lNRCtGK00rOjo6UFJPRFVDVCBURVNUIDEnUVRZKzQ3OjEwLjAwMCdN"
- + "T0ErNjY6Ny4wMCdQUkkrQUFCOjEuMDAnUFJJK0FBQTowLjcwJ1JGRitPTjox"
- + "MjM0NTYnUkZGK0RROjIyMjIyMjIyMidUQVgrNytWQVQrKys6OjoyMS4wMDAn"
- + "QUxDK0ErKysxK1REJ1BDRCsxOjMwLjAwMCdNT0ErMjA0OjMuMDAnTElOKzIr"
- + "KzIyMjIyMjIyMjIyMjI6RU4nUElBKzErQkJCQkJCQjpTQSdJTUQrRitNKzo6"
- + "OlBST0RVQ1QgVEVTVCAyJ1FUWSs0NzoyMC4wMDAnTU9BKzY2OjgwLjAwJ1BS"
- + "SStBQUI6NS4wMCdQUkkrQUFBOjQuMDAnUkZGK09OOjEyMzQ1NidSRkYrRFE6"
- + "MjIyMjIyMjIyJ1RBWCs3K1ZBVCsrKzo6OjIxLjAwMCdBTEMrQSsrKzErVEQn"
- + "UENEKzE6MjAuMDAwJ01PQSsyMDQ6MjAuMDAnVU5TK1MnQ05UKzI6MidNT0Er"
- + "Nzk6ODcuMDAnTU9BKzEzOToxMDUuMjcnTU9BKzEyNTo4Ny4wMCdNT0ErMjYw"
- + "OjAuMDAnTU9BKzI1OTowLjAwJ01PQSsxNzY6MTguMjcnVEFYKzcrVkFUKysr"
- + "Ojo6MjEuMDAwJ01PQSsxNzY6MTguMjcnTU9BKzEyNTo4Ny4wMCc=");
-
- private static final byte[] shortPartialSig = Base64.decode(
- "sb8yyKk6HM1cJhICScMx7QRQunRyrZ1fbI42+T+TBGNjOknvzKuvG7aftGX7"
- + "O/RXuYgk6LTxpXv7+O5noUhMBsR2PKaHveuylU1WSPmDxDCui3kp4frqVH0w"
- + "8Vjpl5CsKqBsmKkbGCKE+smM0xFXhYxV8QUTB2XsWNCQiFiHPgwbpfWzZUNY"
- + "QPWd0A99P64EuUIYz1tkkDnLFmwQ19/PJu1a8orIQInmkVYWSsBsZ/7Ks6lx"
- + "nDHpAvgiRe+OXmJ/yuQy1O3FJYdyoqvjYRPBu3qYeBK9+9L3lExLilImH5aD"
- + "nJznaXcO8QFOxVPbrF2s4GdPIMDonEyAHdrnzoghlg==");
-
- private void doShortPartialTest()
- throws Exception
- {
- byte[] recovered = Hex.decode("5553482b312b534536383031353332393731392b322b312b362b322b312b313a3a393939393939393939393939393a3a392b323a3a373737373737373737373737373a3a392b2b353a32303133303430353a313133");
- BigInteger exp = new BigInteger("10001", 16);
- BigInteger mod = new BigInteger("b9b70b083da9e37e23cde8e654855db31e21d2d3fc11a5f91d2b3c311efa8f5e28c757dd6fc798631cb1b9d051c14119749cb122ad76e8c3fd7bd93abe282c026a14fba9f8023977a7a0d8b49a24d1ad87e4379a931846a1ef9520ea57e28c998cf65722683d0caaa0da8306973e2496a25cbd3cb4adb4b284e25604fabf12f385456c75da7c3c4cde37440cfb7db8c8fe6851e2bc59767b9f7218540238ac8acef3bc7bd3dc6671320c2c1a2ac8a6799ce1eaf62b9683ab1e1341b37b9249dbd6cd987b2f27b5c4619a1eda7f0fb0b59a519afbbc3cee640261cec90a4bb8fefbc844082dca9f549e56943e758579a453a357e6ccb37fc46718a5b8c3227e5d", 16);
-
- AsymmetricKeyParameter pubKey = new RSAKeyParameters(false, mod, exp);
-
- ISO9796d2PSSSigner pssSign = new ISO9796d2PSSSigner(new RSAEngine(), new SHA1Digest(), 20);
-
- pssSign.init(false, pubKey);
-
- pssSign.updateWithRecoveredMessage(shortPartialSig);
-
- pssSign.update(longMessage, pssSign.getRecoveredMessage().length, longMessage.length - pssSign.getRecoveredMessage().length);
-
- if (!pssSign.verifySignature(shortPartialSig))
- {
- fail("short partial PSS sig verification failed.");
- }
-
- byte[] mm = pssSign.getRecoveredMessage();
-
- if (!Arrays.areEqual(recovered, mm))
- {
- fail("short partial PSS recovery failed");
- }
- }
-
- private void doFullMessageTest()
- throws Exception
- {
- BigInteger modulus = new BigInteger(1, Hex.decode("CDCBDABBF93BE8E8294E32B055256BBD0397735189BF75816341BB0D488D05D627991221DF7D59835C76A4BB4808ADEEB779E7794504E956ADC2A661B46904CDC71337DD29DDDD454124EF79CFDD7BC2C21952573CEFBA485CC38C6BD2428809B5A31A898A6B5648CAA4ED678D9743B589134B7187478996300EDBA16271A861"));
- BigInteger pubExp = new BigInteger(1, Hex.decode("010001"));
- BigInteger privExp = new BigInteger(1, Hex.decode("4BA6432AD42C74AA5AFCB6DF60FD57846CBC909489994ABD9C59FE439CC6D23D6DE2F3EA65B8335E796FD7904CA37C248367997257AFBD82B26F1A30525C447A236C65E6ADE43ECAAF7283584B2570FA07B340D9C9380D88EAACFFAEEFE7F472DBC9735C3FF3A3211E8A6BBFD94456B6A33C17A2C4EC18CE6335150548ED126D"));
-
- RSAKeyParameters pubParams = new RSAKeyParameters(false, modulus, pubExp);
- RSAKeyParameters privParams = new RSAKeyParameters(true, modulus, privExp);
-
- AsymmetricBlockCipher rsaEngine = new RSABlindedEngine();
-
- // set challenge to all zero's for verification
- byte[] challenge = new byte[8];
-
- ISO9796d2PSSSigner pssSign = new ISO9796d2PSSSigner(new RSAEngine(), new SHA256Digest(), 20, true);
-
- pssSign.init(true, privParams);
-
- pssSign.update(challenge, 0, challenge.length);
-
- byte[] sig = pssSign.generateSignature();
-
- pssSign.init(false, pubParams);
-
- pssSign.updateWithRecoveredMessage(sig);
-
- if (!pssSign.verifySignature(sig))
- {
- fail("challenge PSS sig verification failed.");
- }
-
- byte[] mm = pssSign.getRecoveredMessage();
-
- if (!Arrays.areEqual(challenge, mm))
- {
- fail("challenge partial PSS recovery failed");
- }
- }
-
- public void performTest()
- throws Exception
- {
- doTest1();
- doTest2();
- doTest3();
- doTest4();
- doTest5();
- doTest6();
- doTest7();
- doTest8();
- doTest9();
- doTest10();
- doTest11();
- doTest12();
- doTest13();
- doShortPartialTest();
- doFullMessageTest();
- }
-
- public static void main(
- String[] args)
- {
- runTest(new ISO9796Test());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/ISO9797Alg3MacTest.java b/core/src/test/java/org/bouncycastle/crypto/test/ISO9797Alg3MacTest.java
deleted file mode 100644
index 96b5fc46..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/ISO9797Alg3MacTest.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.engines.DESEngine;
-import org.bouncycastle.crypto.macs.ISO9797Alg3Mac;
-import org.bouncycastle.crypto.paddings.ISO7816d4Padding;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class ISO9797Alg3MacTest
- extends SimpleTest
-{
- static byte[] keyBytes = Hex.decode("7CA110454A1A6E570131D9619DC1376E");
-
- static byte[] input1 = "Hello World !!!!".getBytes();
-
- static byte[] output1 = Hex.decode("F09B856213BAB83B");
-
- public ISO9797Alg3MacTest()
- {
- }
-
- public void performTest()
- {
- KeyParameter key = new KeyParameter(keyBytes);
- BlockCipher cipher = new DESEngine();
- Mac mac = new ISO9797Alg3Mac(cipher);
-
- //
- // standard DAC - zero IV
- //
- mac.init(key);
-
- mac.update(input1, 0, input1.length);
-
- byte[] out = new byte[8];
-
- mac.doFinal(out, 0);
-
- if (!areEqual(out, output1))
- {
- fail("Failed - expected " + new String(Hex.encode(output1)) + " got " + new String(Hex.encode(out)));
- }
-
- //
- // reset
- //
- mac.reset();
-
- mac.init(key);
-
- for (int i = 0; i != input1.length / 2; i++)
- {
- mac.update(input1[i]);
- }
-
- mac.update(input1, input1.length / 2, input1.length - (input1.length / 2));
-
- mac.doFinal(out, 0);
-
- if (!areEqual(out, output1))
- {
- fail("Reset failed - expected " + new String(Hex.encode(output1)) + " got " + new String(Hex.encode(out)));
- }
-
- testMacWithIv();
- }
-
- private void testMacWithIv()
- {
- byte[] inputData = new byte[]{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8};
- byte[] key = new byte[]{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8};
- byte[] zeroIv = new byte[8];
- byte[] nonZeroIv = new byte[]{0x5, 0x6, 0x7, 0x8, 0x1, 0x2, 0x3, 0x4};
-
- KeyParameter simpleParameter = new KeyParameter(key);
- ParametersWithIV zeroIvParameter = new ParametersWithIV(new KeyParameter(key), zeroIv);
-
- ISO9797Alg3Mac mac1 = new ISO9797Alg3Mac(new DESEngine(), new ISO7816d4Padding());
-
- // we calculate a reference MAC with a null IV
- mac1.init(simpleParameter);
- mac1.update(inputData, 0, inputData.length);
- byte[] output1 = new byte[mac1.getMacSize()];
- mac1.doFinal(output1, 0);
-
- // we then check that passing a vector of 0s is the same as not using any IV
- ISO9797Alg3Mac mac2 = new ISO9797Alg3Mac(new DESEngine(), new ISO7816d4Padding());
- mac2.init(zeroIvParameter);
- mac2.update(inputData, 0, inputData.length);
- byte[] output2 = new byte[mac2.getMacSize()];
- mac2.doFinal(output2, 0);
- if (!Arrays.areEqual(output1, output2))
- {
- fail("zero IV test failed");
- }
-
- // and then check that a non zero IV parameter produces a different results.
- ParametersWithIV nonZeroIvParameter = new ParametersWithIV(new KeyParameter(key), nonZeroIv);
- mac2 = new ISO9797Alg3Mac(new DESEngine(), new ISO7816d4Padding());
- mac2.init(nonZeroIvParameter);
- mac2.update(inputData, 0, inputData.length);
- output2 = new byte[mac2.getMacSize()];
- mac2.doFinal(output2, 0);
- if (Arrays.areEqual(output1, output2))
- {
- fail("non-zero IV test failed");
- }
- }
-
- public String getName()
- {
- return "ISO9797Alg3Mac";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new ISO9797Alg3MacTest());
- }
-}
-
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/KDF1GeneratorTest.java b/core/src/test/java/org/bouncycastle/crypto/test/KDF1GeneratorTest.java
deleted file mode 100644
index 62f9997f..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/KDF1GeneratorTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.DerivationFunction;
-import org.bouncycastle.crypto.digests.ShortenedDigest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.generators.KDF1BytesGenerator;
-import org.bouncycastle.crypto.params.ISO18033KDFParameters;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * KDF1 tests - vectors from ISO 18033.
- */
-public class KDF1GeneratorTest
- extends SimpleTest
-{
- private byte[] seed1 = Hex.decode("d6e168c5f256a2dcff7ef12facd390f393c7a88d");
- private byte[] mask1 = Hex.decode(
- "0742ba966813af75536bb6149cc44fc256fd6406df79665bc31dc5"
- + "a62f70535e52c53015b9d37d412ff3c1193439599e1b628774c50d9c"
- + "cb78d82c425e4521ee47b8c36a4bcffe8b8112a89312fc04420a39de"
- + "99223890e74ce10378bc515a212b97b8a6447ba6a8870278");
-
- private byte[] seed2 = Hex.decode(
- "032e45326fa859a72ec235acff929b15d1372e30b207255f0611b8f785d7643741"
- + "52e0ac009e509e7ba30cd2f1778e113b64e135cf4e2292c75efe5288edfda4");
- private byte[] mask2 = Hex.decode(
- "5f8de105b5e96b2e490ddecbd147dd1def7e3b8e0e6a26eb7b956ccb8b3bdc1ca9"
- + "75bc57c3989e8fbad31a224655d800c46954840ff32052cdf0d640562bdfadfa263c"
- + "fccf3c52b29f2af4a1869959bc77f854cf15bd7a25192985a842dbff8e13efee5b7e"
- + "7e55bbe4d389647c686a9a9ab3fb889b2d7767d3837eea4e0a2f04");
-
- private byte[] seed3 = seed2;
- private byte[] mask3= Hex.decode(
- "09e2decf2a6e1666c2f6071ff4298305e2643fd510a2403db42a8743cb989de86e"
- + "668d168cbe604611ac179f819a3d18412e9eb45668f2923c087c12fee0c5a0d2a8aa"
- + "70185401fbbd99379ec76c663e875a60b4aacb1319fa11c3365a8b79a44669f26fb5"
- + "55c80391847b05eca1cb5cf8c2d531448d33fbaca19f6410ee1fcb");
-
-
- public KDF1GeneratorTest()
- {
- }
-
- public void performTest()
- {
- checkMask(1, new KDF1BytesGenerator(new ShortenedDigest(new SHA256Digest(), 20)), seed1, mask1);
- checkMask(2, new KDF1BytesGenerator(new SHA1Digest()), seed2, mask2);
- checkMask(3, new KDF1BytesGenerator(new ShortenedDigest(new SHA256Digest(), 20)), seed3, mask3);
-
- try
- {
- new KDF1BytesGenerator(new SHA1Digest()).generateBytes(new byte[10], 0, 20);
-
- fail("short input array not caught");
- }
- catch (DataLengthException e)
- {
- // expected
- }
- }
-
- private void checkMask(
- int count,
- DerivationFunction kdf,
- byte[] seed,
- byte[] result)
- {
- byte[] data = new byte[result.length];
-
- kdf.init(new ISO18033KDFParameters(seed));
-
- kdf.generateBytes(data, 0, data.length);
-
- if (!areEqual(result, data))
- {
- fail("KDF1 failed generator test " + count);
- }
- }
-
- public String getName()
- {
- return "KDF1";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new KDF1GeneratorTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/KDF2GeneratorTest.java b/core/src/test/java/org/bouncycastle/crypto/test/KDF2GeneratorTest.java
deleted file mode 100644
index 84a435a6..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/KDF2GeneratorTest.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.DerivationFunction;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.digests.ShortenedDigest;
-import org.bouncycastle.crypto.generators.KDF2BytesGenerator;
-import org.bouncycastle.crypto.params.KDFParameters;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * KDF2 tests - vectors from ISO 18033.
- */
-public class KDF2GeneratorTest
- extends SimpleTest
-{
- private byte[] seed1 = Hex.decode("d6e168c5f256a2dcff7ef12facd390f393c7a88d");
- private byte[] mask1 = Hex.decode(
- "df79665bc31dc5a62f70535e52c53015b9d37d412ff3c119343959"
- + "9e1b628774c50d9ccb78d82c425e4521ee47b8c36a4bcffe8b8112a8"
- + "9312fc04420a39de99223890e74ce10378bc515a212b97b8a6447ba6"
- + "a8870278f0262727ca041fa1aa9f7b5d1cf7f308232fe861");
-
- private byte[] seed2 = Hex.decode(
- "032e45326fa859a72ec235acff929b15d1372e30b207255f0611b8f785d7643741"
- + "52e0ac009e509e7ba30cd2f1778e113b64e135cf4e2292c75efe5288edfda4");
- private byte[] mask2 = Hex.decode(
- "10a2403db42a8743cb989de86e668d168cbe604611ac179f819a3d18412e9eb456"
- + "68f2923c087c12fee0c5a0d2a8aa70185401fbbd99379ec76c663e875a60b4aacb13"
- + "19fa11c3365a8b79a44669f26fb555c80391847b05eca1cb5cf8c2d531448d33fbac"
- + "a19f6410ee1fcb260892670e0814c348664f6a7248aaf998a3acc6");
- private byte[] adjustedMask2 = Hex.decode(
- "10a2403db42a8743cb989de86e668d168cbe6046e23ff26f741e87949a3bba1311ac1"
- + "79f819a3d18412e9eb45668f2923c087c1299005f8d5fd42ca257bc93e8fee0c5a0d2"
- + "a8aa70185401fbbd99379ec76c663e9a29d0b70f3fe261a59cdc24875a60b4aacb131"
- + "9fa11c3365a8b79a44669f26fba933d012db213d7e3b16349");
-
- private byte[] sha1Mask = Hex.decode(
- "0e6a26eb7b956ccb8b3bdc1ca975bc57c3989e8fbad31a224655d800c46954840ff32"
- + "052cdf0d640562bdfadfa263cfccf3c52b29f2af4a1869959bc77f854cf15bd7a2519"
- + "2985a842dbff8e13efee5b7e7e55bbe4d389647c686a9a9ab3fb889b2d7767d3837ee"
- + "a4e0a2f04b53ca8f50fb31225c1be2d0126c8c7a4753b0807");
-
- private byte[] seed3 = Hex.decode("CA7C0F8C3FFA87A96E1B74AC8E6AF594347BB40A");
- private byte[] mask3 = Hex.decode("744AB703F5BC082E59185F6D049D2D367DB245C2");
-
- private byte[] seed4 = Hex.decode("0499B502FC8B5BAFB0F4047E731D1F9FD8CD0D8881");
- private byte[] mask4 = Hex.decode("03C62280C894E103C680B13CD4B4AE740A5EF0C72547292F82DC6B1777F47D63BA9D1EA732DBF386");
-
- public KDF2GeneratorTest()
- {
- }
-
- public void performTest()
- {
- checkMask(1, new KDF2BytesGenerator(new ShortenedDigest(new SHA256Digest(), 20)), seed1, mask1);
- checkMask(2, new KDF2BytesGenerator(new ShortenedDigest(new SHA256Digest(), 20)), seed2, mask2);
- checkMask(3, new KDF2BytesGenerator(new SHA256Digest()), seed2, adjustedMask2);
- checkMask(4, new KDF2BytesGenerator(new SHA1Digest()), seed2, sha1Mask);
- checkMask(5, new KDF2BytesGenerator(new SHA1Digest()), seed3, mask3);
- checkMask(6, new KDF2BytesGenerator(new SHA1Digest()), seed4, mask4);
-
- try
- {
- new KDF2BytesGenerator(new SHA1Digest()).generateBytes(new byte[10], 0, 20);
-
- fail("short input array not caught");
- }
- catch (DataLengthException e)
- {
- // expected
- }
- }
-
- private void checkMask(
- int count,
- DerivationFunction kdf,
- byte[] seed,
- byte[] result)
- {
- byte[] data = new byte[result.length];
-
- kdf.init(new KDFParameters(seed, new byte[0]));
-
- kdf.generateBytes(data, 0, data.length);
-
- if (!areEqual(result, data))
- {
- fail("KDF2 failed generator test " + count);
- }
- }
-
- public String getName()
- {
- return "KDF2";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new KDF2GeneratorTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/KDFCounterGeneratorTest.java b/core/src/test/java/org/bouncycastle/crypto/test/KDFCounterGeneratorTest.java
deleted file mode 100644
index 7078da26..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/KDFCounterGeneratorTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.nio.charset.Charset;
-
-import org.bouncycastle.crypto.test.cavp.CAVPReader;
-import org.bouncycastle.crypto.test.cavp.KDFCounterTests;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class KDFCounterGeneratorTest
- extends SimpleTest
-{
-
- private static void testCounter()
- {
-
- CAVPReader cavpReader = new CAVPReader(new KDFCounterTests());
-
- final InputStream stream = CAVPReader.class.getResourceAsStream("KDFCTR_gen.rsp");
- final Reader reader = new InputStreamReader(stream, Charset.forName("UTF-8"));
- cavpReader.setInput("KDFCounter", reader);
-
- try
- {
- cavpReader.readAll();
- }
- catch (IOException e)
- {
- throw new IllegalStateException("Something is rotten in the state of Denmark", e);
- }
- }
-
- public String getName()
- {
- return this.getClass().getSimpleName();
- }
-
- public void performTest()
- throws Exception
- {
- testCounter();
- }
-
- public static void main(String[] args)
- {
- runTest(new KDFCounterGeneratorTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/KDFDoublePipelineIteratorGeneratorTest.java b/core/src/test/java/org/bouncycastle/crypto/test/KDFDoublePipelineIteratorGeneratorTest.java
deleted file mode 100644
index 37aaf668..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/KDFDoublePipelineIteratorGeneratorTest.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.nio.charset.Charset;
-
-import org.bouncycastle.crypto.test.cavp.CAVPReader;
-import org.bouncycastle.crypto.test.cavp.KDFDoublePipelineCounterTests;
-import org.bouncycastle.crypto.test.cavp.KDFDoublePipelineIterationNoCounterTests;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class KDFDoublePipelineIteratorGeneratorTest
- extends SimpleTest
-{
- public String getName()
- {
- return this.getClass().getSimpleName();
- }
-
- public void performTest()
- throws Exception
- {
- testDoublePipelineIterationCounter();
- testDoublePipelineIterationNoCounter();
- }
-
- private static void testDoublePipelineIterationCounter()
- {
-
- CAVPReader cavpReader = new CAVPReader(new KDFDoublePipelineCounterTests());
-
- final InputStream stream = CAVPReader.class.getResourceAsStream("KDFDblPipelineCounter_gen.rsp");
- final Reader reader = new InputStreamReader(stream, Charset.forName("UTF-8"));
- cavpReader.setInput("KDFDoublePipelineIterationCounter", reader);
-
- try
- {
- cavpReader.readAll();
- }
- catch (IOException e)
- {
- throw new IllegalStateException("Something is rotten in the state of Denmark", e);
- }
- }
-
- private static void testDoublePipelineIterationNoCounter()
- {
-
- CAVPReader cavpReader = new CAVPReader(new KDFDoublePipelineIterationNoCounterTests());
-
- final InputStream stream = CAVPReader.class.getResourceAsStream("KDFDblPipelineNoCounter_gen.rsp");
- final Reader reader = new InputStreamReader(stream, Charset.forName("UTF-8"));
- cavpReader.setInput("KDFDblPipelineIterationNoCounter", reader);
-
- try
- {
- cavpReader.readAll();
- }
- catch (IOException e)
- {
- throw new IllegalStateException("Something is rotten in the state of Denmark", e);
- }
- }
-
- public static void main(String[] args)
- {
- runTest(new KDFDoublePipelineIteratorGeneratorTest());
- }
-
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/KDFFeedbackGeneratorTest.java b/core/src/test/java/org/bouncycastle/crypto/test/KDFFeedbackGeneratorTest.java
deleted file mode 100644
index 0eba7068..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/KDFFeedbackGeneratorTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.nio.charset.Charset;
-
-import org.bouncycastle.crypto.test.cavp.CAVPReader;
-import org.bouncycastle.crypto.test.cavp.KDFFeedbackCounterTests;
-import org.bouncycastle.crypto.test.cavp.KDFFeedbackNoCounterTests;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class KDFFeedbackGeneratorTest
- extends SimpleTest
-{
- public String getName()
- {
- return this.getClass().getSimpleName();
- }
-
- public void performTest()
- throws Exception
- {
- testFeedbackCounter();
- testFeedbackNoCounter();
- }
-
- private static void testFeedbackCounter()
- {
-
- CAVPReader cavpReader = new CAVPReader(new KDFFeedbackCounterTests());
-
- final InputStream stream = CAVPReader.class.getResourceAsStream("KDFFeedbackCounter_gen.rsp");
- final Reader reader = new InputStreamReader(stream, Charset.forName("UTF-8"));
- cavpReader.setInput("KDFFeedbackCounter", reader);
-
- try
- {
- cavpReader.readAll();
- }
- catch (IOException e)
- {
- throw new IllegalStateException("Something is rotten in the state of Denmark ", e);
- }
- }
-
- private static void testFeedbackNoCounter()
- {
-
- CAVPReader cavpReader = new CAVPReader(new KDFFeedbackNoCounterTests());
-
- final InputStream stream = CAVPReader.class.getResourceAsStream("KDFFeedbackNoCounter_gen.rsp");
- final Reader reader = new InputStreamReader(stream, Charset.forName("UTF-8"));
- cavpReader.setInput("KDFFeedbackNoCounter", reader);
-
- try
- {
- cavpReader.readAll();
- }
- catch (IOException e)
- {
- throw new IllegalStateException("Something is rotten in the state of Denmark", e);
- }
- }
-
- public static void main(String[] args)
- {
- runTest(new KDFDoublePipelineIteratorGeneratorTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/MD2DigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/MD2DigestTest.java
deleted file mode 100644
index 443ec2e0..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/MD2DigestTest.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.MD2Digest;
-
-/**
- * standard vector test for MD2
- * from RFC1319 by B.Kaliski of RSA Laboratories April 1992
- *
- */
-public class MD2DigestTest
- extends DigestTest
-{
- static final String messages[] =
- {
- "",
- "a",
- "abc",
- "message digest",
- "abcdefghijklmnopqrstuvwxyz",
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
- "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
- };
-
- static final String digests[] =
- {
- "8350e5a3e24c153df2275c9f80692773",
- "32ec01ec4a6dac72c0ab96fb34c0b5d1",
- "da853b0d3f88d99b30283a69e6ded6bb",
- "ab4f496bfb2a530b219ff33031fe06b0",
- "4e8ddff3650292ab5a4108c3aa47940b",
- "da33def2a42df13975352846c30338cd",
- "d5976f79d83d3a0dc9806c3c66f3efd8"
- };
-
- MD2DigestTest()
- {
- super(new MD2Digest(), messages, digests);
- }
-
- protected Digest cloneDigest(
- Digest digest)
- {
- return new MD2Digest((MD2Digest)digest);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new MD2DigestTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/MD4DigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/MD4DigestTest.java
deleted file mode 100644
index d57a29ce..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/MD4DigestTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.MD4Digest;
-
-/**
- * standard vector test for MD4 from RFC 1320.
- */
-public class MD4DigestTest
- extends DigestTest
-{
- static private String[] messages =
- {
- "",
- "a",
- "abc",
- "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
- };
-
- static private String[] digests =
- {
- "31d6cfe0d16ae931b73c59d7e0c089c0",
- "bde52cb31de33e46245e05fbdbd6fb24",
- "a448017aaf21d8525fc10ae87aa6729d",
- "e33b4ddc9c38f2199c3e7b164fcc0536"
- };
-
- MD4DigestTest()
- {
- super(new MD4Digest(), messages, digests);
- }
-
- protected Digest cloneDigest(Digest digest)
- {
- return new MD4Digest((MD4Digest)digest);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new MD4DigestTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/MD5DigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/MD5DigestTest.java
deleted file mode 100644
index ab9cab27..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/MD5DigestTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.MD5Digest;
-
-/**
- * standard vector test for MD5 from "Handbook of Applied Cryptography", page 345.
- */
-public class MD5DigestTest
- extends DigestTest
-{
- static final String[] messages =
- {
- "",
- "a",
- "abc",
- "abcdefghijklmnopqrstuvwxyz"
- };
-
- static final String[] digests =
- {
- "d41d8cd98f00b204e9800998ecf8427e",
- "0cc175b9c0f1b6a831c399e269772661",
- "900150983cd24fb0d6963f7d28e17f72",
- "c3fcd3d76192e4007dfb496cca67e13b"
- };
-
- MD5DigestTest()
- {
- super(new MD5Digest(), messages, digests);
- }
-
- protected Digest cloneDigest(Digest digest)
- {
- return new MD5Digest((MD5Digest)digest);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new MD5DigestTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/MD5HMacTest.java b/core/src/test/java/org/bouncycastle/crypto/test/MD5HMacTest.java
deleted file mode 100644
index cfce1d91..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/MD5HMacTest.java
+++ /dev/null
@@ -1,98 +0,0 @@
-
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.digests.MD5Digest;
-import org.bouncycastle.crypto.macs.HMac;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * MD5 HMac Test, test vectors from RFC 2202
- */
-public class MD5HMacTest
- extends SimpleTest
-{
- final static String[] keys = {
- "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
- "4a656665",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
- "0102030405060708090a0b0c0d0e0f10111213141516171819",
- "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- };
-
- final static String[] digests = {
- "9294727a3638bb1c13f48ef8158bfc9d",
- "750c783e6ab0b503eaa86e310a5db738",
- "56be34521d144c88dbb8c733f0e8b3f6",
- "697eaf0aca3a3aea3a75164746ffaa79",
- "56461ef2342edc00f9bab995690efd4c",
- "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd",
- "6f630fad67cda0ee1fb1f562db3aa53e"
- };
-
- final static String[] messages = {
- "Hi There",
- "what do ya want for nothing?",
- "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
- "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
- "Test With Truncation",
- "Test Using Larger Than Block-Size Key - Hash Key First",
- "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
- };
-
- public String getName()
- {
- return "MD5HMac";
- }
-
- public void performTest()
- {
- HMac hmac = new HMac(new MD5Digest());
- byte[] resBuf = new byte[hmac.getMacSize()];
-
- for (int i = 0; i < messages.length; i++)
- {
- byte[] m = messages[i].getBytes();
- if (messages[i].startsWith("0x"))
- {
- m = Hex.decode(messages[i].substring(2));
- }
- hmac.init(new KeyParameter(Hex.decode(keys[i])));
- hmac.update(m, 0, m.length);
- hmac.doFinal(resBuf, 0);
-
- if (!areEqual(resBuf, Hex.decode(digests[i])))
- {
- fail("Vector " + i + " failed");
- }
- }
-
- // test reset
- int vector = 0; // vector used for test
- byte[] m = messages[vector].getBytes();
- if (messages[vector].startsWith("0x"))
- {
- m = Hex.decode(messages[vector].substring(2));
- }
- hmac.init(new KeyParameter(Hex.decode(keys[vector])));
- hmac.update(m, 0, m.length);
- hmac.doFinal(resBuf, 0);
- hmac.reset();
- hmac.update(m, 0, m.length);
- hmac.doFinal(resBuf, 0);
-
- if (!areEqual(resBuf, Hex.decode(digests[vector])))
- {
- fail("Reset with vector " + vector + " failed");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new MD5HMacTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/MGF1GeneratorTest.java b/core/src/test/java/org/bouncycastle/crypto/test/MGF1GeneratorTest.java
deleted file mode 100644
index e7e99fe2..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/MGF1GeneratorTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.DerivationFunction;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.digests.ShortenedDigest;
-import org.bouncycastle.crypto.generators.MGF1BytesGenerator;
-import org.bouncycastle.crypto.params.MGFParameters;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * MGF1 tests - vectors from ISO 18033 for KDF1 (equivalent).
- */
-public class MGF1GeneratorTest
- extends SimpleTest
-{
- private byte[] seed1 = Hex.decode("d6e168c5f256a2dcff7ef12facd390f393c7a88d");
- private byte[] mask1 = Hex.decode(
- "0742ba966813af75536bb6149cc44fc256fd6406df79665bc31dc5"
- + "a62f70535e52c53015b9d37d412ff3c1193439599e1b628774c50d9c"
- + "cb78d82c425e4521ee47b8c36a4bcffe8b8112a89312fc04420a39de"
- + "99223890e74ce10378bc515a212b97b8a6447ba6a8870278");
-
- private byte[] seed2 = Hex.decode(
- "032e45326fa859a72ec235acff929b15d1372e30b207255f0611b8f785d7643741"
- + "52e0ac009e509e7ba30cd2f1778e113b64e135cf4e2292c75efe5288edfda4");
- private byte[] mask2 = Hex.decode(
- "5f8de105b5e96b2e490ddecbd147dd1def7e3b8e0e6a26eb7b956ccb8b3bdc1ca9"
- + "75bc57c3989e8fbad31a224655d800c46954840ff32052cdf0d640562bdfadfa263c"
- + "fccf3c52b29f2af4a1869959bc77f854cf15bd7a25192985a842dbff8e13efee5b7e"
- + "7e55bbe4d389647c686a9a9ab3fb889b2d7767d3837eea4e0a2f04");
-
- private byte[] seed3 = seed2;
- private byte[] mask3= Hex.decode(
- "09e2decf2a6e1666c2f6071ff4298305e2643fd510a2403db42a8743cb989de86e"
- + "668d168cbe604611ac179f819a3d18412e9eb45668f2923c087c12fee0c5a0d2a8aa"
- + "70185401fbbd99379ec76c663e875a60b4aacb1319fa11c3365a8b79a44669f26fb5"
- + "55c80391847b05eca1cb5cf8c2d531448d33fbaca19f6410ee1fcb");
-
- public void performTest()
- {
- checkMask(1, new MGF1BytesGenerator(new ShortenedDigest(new SHA256Digest(), 20)), seed1, mask1);
- checkMask(2, new MGF1BytesGenerator(new SHA1Digest()), seed2, mask2);
- checkMask(3, new MGF1BytesGenerator(new ShortenedDigest(new SHA256Digest(), 20)), seed3, mask3);
-
- try
- {
- new MGF1BytesGenerator(new SHA1Digest()).generateBytes(new byte[10], 0, 20);
-
- fail("short input array not caught");
- }
- catch (DataLengthException e)
- {
- // expected
- }
- }
-
- private void checkMask(
- int count,
- DerivationFunction kdf,
- byte[] seed,
- byte[] result)
- {
- byte[] data = new byte[result.length];
-
- kdf.init(new MGFParameters(seed));
-
- kdf.generateBytes(data, 0, data.length);
-
- if (!areEqual(result, data))
- {
- fail("MGF1 failed generator test " + count);
- }
- }
-
- public String getName()
- {
- return "MGF1";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new MGF1GeneratorTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/MacTest.java b/core/src/test/java/org/bouncycastle/crypto/test/MacTest.java
deleted file mode 100644
index 5b05a608..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/MacTest.java
+++ /dev/null
@@ -1,181 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.engines.DESEngine;
-import org.bouncycastle.crypto.macs.CBCBlockCipherMac;
-import org.bouncycastle.crypto.macs.CFBBlockCipherMac;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.crypto.paddings.PKCS7Padding;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * MAC tester - vectors from
- * <a href=http://www.itl.nist.gov/fipspubs/fip81.htm>FIP 81</a> and
- * <a href=http://www.itl.nist.gov/fipspubs/fip113.htm>FIP 113</a>.
- */
-public class MacTest
- extends SimpleTest
-{
- static byte[] keyBytes = Hex.decode("0123456789abcdef");
- static byte[] ivBytes = Hex.decode("1234567890abcdef");
-
- static byte[] input1 = Hex.decode("37363534333231204e6f77206973207468652074696d6520666f7220");
-
- static byte[] output1 = Hex.decode("f1d30f68");
- static byte[] output2 = Hex.decode("58d2e77e");
- static byte[] output3 = Hex.decode("cd647403");
-
- //
- // these aren't NIST vectors, just for regression testing.
- //
- static byte[] input2 = Hex.decode("3736353433323120");
-
- static byte[] output4 = Hex.decode("3af549c9");
- static byte[] output5 = Hex.decode("188fbdd5");
- static byte[] output6 = Hex.decode("7045eecd");
-
- public MacTest()
- {
- }
-
- public void performTest()
- {
- KeyParameter key = new KeyParameter(keyBytes);
- BlockCipher cipher = new DESEngine();
- Mac mac = new CBCBlockCipherMac(cipher);
-
- //
- // standard DAC - zero IV
- //
- mac.init(key);
-
- mac.update(input1, 0, input1.length);
-
- byte[] out = new byte[4];
-
- mac.doFinal(out, 0);
-
- if (!areEqual(out, output1))
- {
- fail("Failed - expected " + new String(Hex.encode(output1)) + " got " + new String(Hex.encode(out)));
- }
-
- //
- // mac with IV.
- //
- ParametersWithIV param = new ParametersWithIV(key, ivBytes);
-
- mac.init(param);
-
- mac.update(input1, 0, input1.length);
-
- out = new byte[4];
-
- mac.doFinal(out, 0);
-
- if (!areEqual(out, output2))
- {
- fail("Failed - expected " + new String(Hex.encode(output2)) + " got " + new String(Hex.encode(out)));
- }
-
- //
- // CFB mac with IV - 8 bit CFB mode
- //
- param = new ParametersWithIV(key, ivBytes);
-
- mac = new CFBBlockCipherMac(cipher);
-
- mac.init(param);
-
- mac.update(input1, 0, input1.length);
-
- out = new byte[4];
-
- mac.doFinal(out, 0);
-
- if (!areEqual(out, output3))
- {
- fail("Failed - expected " + new String(Hex.encode(output3)) + " got " + new String(Hex.encode(out)));
- }
-
- //
- // word aligned data - zero IV
- //
- mac.init(key);
-
- mac.update(input2, 0, input2.length);
-
- out = new byte[4];
-
- mac.doFinal(out, 0);
-
- if (!areEqual(out, output4))
- {
- fail("Failed - expected " + new String(Hex.encode(output4)) + " got " + new String(Hex.encode(out)));
- }
-
- //
- // word aligned data - zero IV - CBC padding
- //
- mac = new CBCBlockCipherMac(cipher, new PKCS7Padding());
-
- mac.init(key);
-
- mac.update(input2, 0, input2.length);
-
- out = new byte[4];
-
- mac.doFinal(out, 0);
-
- if (!areEqual(out, output5))
- {
- fail("Failed - expected " + new String(Hex.encode(output5)) + " got " + new String(Hex.encode(out)));
- }
-
- //
- // non-word aligned data - zero IV - CBC padding
- //
- mac.reset();
-
- mac.update(input1, 0, input1.length);
-
- out = new byte[4];
-
- mac.doFinal(out, 0);
-
- if (!areEqual(out, output6))
- {
- fail("Failed - expected " + new String(Hex.encode(output6)) + " got " + new String(Hex.encode(out)));
- }
-
- //
- // non-word aligned data - zero IV - CBC padding
- //
- mac.init(key);
-
- mac.update(input1, 0, input1.length);
-
- out = new byte[4];
-
- mac.doFinal(out, 0);
-
- if (!areEqual(out, output6))
- {
- fail("Failed - expected " + new String(Hex.encode(output6)) + " got " + new String(Hex.encode(out)));
- }
- }
-
- public String getName()
- {
- return "Mac";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new MacTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/ModeTest.java b/core/src/test/java/org/bouncycastle/crypto/test/ModeTest.java
deleted file mode 100644
index 6619b652..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/ModeTest.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.engines.DESEngine;
-import org.bouncycastle.crypto.modes.CFBBlockCipher;
-import org.bouncycastle.crypto.modes.OFBBlockCipher;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-/**
- * CFB/OFB Mode test of IV padding.
- */
-public class ModeTest
- implements Test
-{
- public ModeTest()
- {
- }
-
- private boolean isEqualTo(
- byte[] a,
- byte[] b)
- {
- for (int i = 0; i != a.length; i++)
- {
- if (a[i] != b[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- public TestResult perform()
- {
- KeyParameter key = new KeyParameter(Hex.decode("0011223344556677"));
- byte[] input = Hex.decode("4e6f7720");
- byte[] out1 = new byte[4];
- byte[] out2 = new byte[4];
-
-
- BlockCipher ofb = new OFBBlockCipher(new DESEngine(), 32);
-
- ofb.init(true, new ParametersWithIV(key, Hex.decode("1122334455667788")));
-
- ofb.processBlock(input, 0, out1, 0);
-
- ofb.init(false, new ParametersWithIV(key, Hex.decode("1122334455667788")));
- ofb.processBlock(out1, 0, out2, 0);
-
- if (!isEqualTo(out2, input))
- {
- return new SimpleTestResult(false, getName() + ": test 1 - in != out");
- }
-
- ofb.init(true, new ParametersWithIV(key, Hex.decode("11223344")));
-
- ofb.processBlock(input, 0, out1, 0);
-
- ofb.init(false, new ParametersWithIV(key, Hex.decode("0000000011223344")));
- ofb.processBlock(out1, 0, out2, 0);
-
- if (!isEqualTo(out2, input))
- {
- return new SimpleTestResult(false, getName() + ": test 2 - in != out");
- }
-
- BlockCipher cfb = new CFBBlockCipher(new DESEngine(), 32);
-
- cfb.init(true, new ParametersWithIV(key, Hex.decode("1122334455667788")));
-
- cfb.processBlock(input, 0, out1, 0);
-
- cfb.init(false, new ParametersWithIV(key, Hex.decode("1122334455667788")));
- cfb.processBlock(out1, 0, out2, 0);
-
- if (!isEqualTo(out2, input))
- {
- return new SimpleTestResult(false, getName() + ": test 3 - in != out");
- }
-
- cfb.init(true, new ParametersWithIV(key, Hex.decode("11223344")));
-
- cfb.processBlock(input, 0, out1, 0);
-
- cfb.init(false, new ParametersWithIV(key, Hex.decode("0000000011223344")));
- cfb.processBlock(out1, 0, out2, 0);
-
- if (!isEqualTo(out2, input))
- {
- return new SimpleTestResult(false, getName() + ": test 4 - in != out");
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
-
- public String getName()
- {
- return "ModeTest";
- }
-
- public static void main(
- String[] args)
- {
- ModeTest test = new ModeTest();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/NaccacheSternTest.java b/core/src/test/java/org/bouncycastle/crypto/test/NaccacheSternTest.java
deleted file mode 100644
index 90558558..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/NaccacheSternTest.java
+++ /dev/null
@@ -1,354 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-import java.util.Vector;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.engines.NaccacheSternEngine;
-import org.bouncycastle.crypto.generators.NaccacheSternKeyPairGenerator;
-import org.bouncycastle.crypto.params.NaccacheSternKeyGenerationParameters;
-import org.bouncycastle.crypto.params.NaccacheSternKeyParameters;
-import org.bouncycastle.crypto.params.NaccacheSternPrivateKeyParameters;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * Test case for NaccacheStern cipher. For details on this cipher, please see
- *
- * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
- *
- * Performs the following tests:
- * <ul>
- * <li> Toy example from the NaccacheSternPaper </li>
- * <li> 768 bit test with text "Now is the time for all good men." (ripped from RSA test) and
- * the same test with the first byte replaced by 0xFF </li>
- * <li> 1024 bit test analog to 768 bit test </li>
- * </ul>
- */
-public class NaccacheSternTest
- extends SimpleTest
-{
- static final boolean debug = false;
-
- static final NaccacheSternEngine cryptEng = new NaccacheSternEngine();
-
- static final NaccacheSternEngine decryptEng = new NaccacheSternEngine();
-
- static
- {
- cryptEng.setDebug(debug);
- decryptEng.setDebug(debug);
- }
-
- // Values from NaccacheStern paper
- static final BigInteger a = BigInteger.valueOf(101);
-
- static final BigInteger u1 = BigInteger.valueOf(3);
-
- static final BigInteger u2 = BigInteger.valueOf(5);
-
- static final BigInteger u3 = BigInteger.valueOf(7);
-
- static final BigInteger b = BigInteger.valueOf(191);
-
- static final BigInteger v1 = BigInteger.valueOf(11);
-
- static final BigInteger v2 = BigInteger.valueOf(13);
-
- static final BigInteger v3 = BigInteger.valueOf(17);
-
- static final BigInteger ONE = BigInteger.valueOf(1);
-
- static final BigInteger TWO = BigInteger.valueOf(2);
-
- static final BigInteger sigma = u1.multiply(u2).multiply(u3).multiply(v1)
- .multiply(v2).multiply(v3);
-
- static final BigInteger p = TWO.multiply(a).multiply(u1).multiply(u2)
- .multiply(u3).add(ONE);
-
- static final BigInteger q = TWO.multiply(b).multiply(v1).multiply(v2)
- .multiply(v3).add(ONE);
-
- static final BigInteger n = p.multiply(q);
-
- static final BigInteger phi_n = p.subtract(ONE).multiply(q.subtract(ONE));
-
- static final BigInteger g = BigInteger.valueOf(131);
-
- static final Vector smallPrimes = new Vector();
-
- // static final BigInteger paperTest = BigInteger.valueOf(202);
-
- static final String input = "4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
-
- static final BigInteger paperTest = BigInteger.valueOf(202);
-
- //
- // to check that we handling byte extension by big number correctly.
- //
- static final String edgeInput = "ff6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
-
- public String getName()
- {
- return "NaccacheStern";
- }
-
- public void performTest()
- {
- // Test with given key from NaccacheSternPaper (totally insecure)
-
- // First the Parameters from the NaccacheStern Paper
- // (see http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf )
-
- smallPrimes.addElement(u1);
- smallPrimes.addElement(u2);
- smallPrimes.addElement(u3);
- smallPrimes.addElement(v1);
- smallPrimes.addElement(v2);
- smallPrimes.addElement(v3);
-
- NaccacheSternKeyParameters pubParameters = new NaccacheSternKeyParameters(false, g, n, sigma.bitLength());
-
- NaccacheSternPrivateKeyParameters privParameters = new NaccacheSternPrivateKeyParameters(g, n, sigma.bitLength(), smallPrimes, phi_n);
-
- AsymmetricCipherKeyPair pair = new AsymmetricCipherKeyPair(pubParameters, privParameters);
-
- // Initialize Engines with KeyPair
-
- if (debug)
- {
- System.out.println("initializing encryption engine");
- }
- cryptEng.init(true, pair.getPublic());
-
- if (debug)
- {
- System.out.println("initializing decryption engine");
- }
- decryptEng.init(false, pair.getPrivate());
-
- byte[] data = paperTest.toByteArray();
-
- if (!new BigInteger(data).equals(new BigInteger(enDeCrypt(data))))
- {
- fail("failed NaccacheStern paper test");
- }
-
- //
- // key generation test
- //
-
- //
- // 768 Bit test
- //
-
- if (debug)
- {
- System.out.println();
- System.out.println("768 Bit TEST");
- }
-
- // specify key generation parameters
- NaccacheSternKeyGenerationParameters genParam
- = new NaccacheSternKeyGenerationParameters(new SecureRandom(), 768, 8, 30, debug);
-
- // Initialize Key generator and generate key pair
- NaccacheSternKeyPairGenerator pGen = new NaccacheSternKeyPairGenerator();
- pGen.init(genParam);
-
- pair = pGen.generateKeyPair();
-
- if (((NaccacheSternKeyParameters)pair.getPublic()).getModulus().bitLength() < 768)
- {
- System.out.println("FAILED: key size is <786 bit, exactly "
- + ((NaccacheSternKeyParameters)pair.getPublic()).getModulus().bitLength() + " bit");
- fail("failed key generation (768) length test");
- }
-
- // Initialize Engines with KeyPair
-
- if (debug)
- {
- System.out.println("initializing " + genParam.getStrength() + " bit encryption engine");
- }
- cryptEng.init(true, pair.getPublic());
-
- if (debug)
- {
- System.out.println("initializing " + genParam.getStrength() + " bit decryption engine");
- }
- decryptEng.init(false, pair.getPrivate());
-
- // Basic data input
- data = Hex.decode(input);
-
- if (!new BigInteger(1, data).equals(new BigInteger(1, enDeCrypt(data))))
- {
- fail("failed encryption decryption (" + genParam.getStrength() + ") basic test");
- }
-
- // Data starting with FF byte (would be interpreted as negative
- // BigInteger)
-
- data = Hex.decode(edgeInput);
-
- if (!new BigInteger(1, data).equals(new BigInteger(1, enDeCrypt(data))))
- {
- fail("failed encryption decryption (" + genParam.getStrength() + ") edgeInput test");
- }
-
- //
- // 1024 Bit Test
- //
-/*
- if (debug)
- {
- System.out.println();
- System.out.println("1024 Bit TEST");
- }
-
- // specify key generation parameters
- genParam = new NaccacheSternKeyGenerationParameters(new SecureRandom(), 1024, 8, 40);
-
- pGen.init(genParam);
- pair = pGen.generateKeyPair();
-
- if (((NaccacheSternKeyParameters)pair.getPublic()).getModulus().bitLength() < 1024)
- {
- if (debug)
- {
- System.out.println("FAILED: key size is <1024 bit, exactly "
- + ((NaccacheSternKeyParameters)pair.getPublic()).getModulus().bitLength() + " bit");
- }
- fail("failed key generation (1024) length test");
- }
-
- // Initialize Engines with KeyPair
-
- if (debug)
- {
- System.out.println("initializing " + genParam.getStrength() + " bit encryption engine");
- }
- cryptEng.init(true, pair.getPublic());
-
- if (debug)
- {
- System.out.println("initializing " + genParam.getStrength() + " bit decryption engine");
- }
- decryptEng.init(false, pair.getPrivate());
-
- if (debug)
- {
- System.out.println("Data is " + new BigInteger(1, data));
- }
-
- // Basic data input
- data = Hex.decode(input);
-
- if (!new BigInteger(1, data).equals(new BigInteger(1, enDeCrypt(data))))
- {
- fail("failed encryption decryption (" + genParam.getStrength() + ") basic test");
- }
-
- // Data starting with FF byte (would be interpreted as negative
- // BigInteger)
-
- data = Hex.decode(edgeInput);
-
- if (!new BigInteger(1, data).equals(new BigInteger(1, enDeCrypt(data))))
- {
- fail("failed encryption decryption (" + genParam.getStrength() + ") edgeInput test");
- }
-*/
- // END OF TEST CASE
-
- try
- {
- new NaccacheSternEngine().processBlock(new byte[]{ 1 }, 0, 1);
- fail("failed initialisation check");
- }
- catch (IllegalStateException e)
- {
- // expected
- }
- catch (InvalidCipherTextException e)
- {
- fail("failed initialisation check");
- }
-
- if (debug)
- {
- System.out.println("All tests successful");
- }
- }
-
- private byte[] enDeCrypt(byte[] input)
- {
-
- // create work array
- byte[] data = new byte[input.length];
- System.arraycopy(input, 0, data, 0, data.length);
-
- // Perform encryption like in the paper from Naccache-Stern
- if (debug)
- {
- System.out.println("encrypting data. Data representation\n"
- // + "As String:.... " + new String(data) + "\n"
- + "As BigInteger: " + new BigInteger(1, data));
- System.out.println("data length is " + data.length);
- }
-
- try
- {
- data = cryptEng.processData(data);
- }
- catch (InvalidCipherTextException e)
- {
- if (debug)
- {
- System.out.println("failed - exception " + e.toString() + "\n" + e.getMessage());
- }
- fail("failed - exception " + e.toString() + "\n" + e.getMessage());
- }
-
- if (debug)
- {
- System.out.println("enrypted data representation\n"
- // + "As String:.... " + new String(data) + "\n"
- + "As BigInteger: " + new BigInteger(1, data));
- System.out.println("data length is " + data.length);
- }
-
- try
- {
- data = decryptEng.processData(data);
- }
- catch (InvalidCipherTextException e)
- {
- if (debug)
- {
- System.out.println("failed - exception " + e.toString() + "\n" + e.getMessage());
- }
- fail("failed - exception " + e.toString() + "\n" + e.getMessage());
- }
-
- if (debug)
- {
- System.out.println("decrypted data representation\n"
- // + "As String:.... " + new String(data) + "\n"
- + "As BigInteger: " + new BigInteger(1, data));
- System.out.println("data length is " + data.length);
- }
-
- return data;
-
- }
-
- public static void main(String[] args)
- {
- runTest(new NaccacheSternTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/NoekeonTest.java b/core/src/test/java/org/bouncycastle/crypto/test/NoekeonTest.java
deleted file mode 100644
index ebebbd64..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/NoekeonTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.engines.NoekeonEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * Noekeon tester
- */
-public class NoekeonTest
- extends CipherTest
-{
- static SimpleTest[] tests =
- {
- new BlockCipherVectorTest(0, new NoekeonEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000")),
- "00000000000000000000000000000000",
- "b1656851699e29fa24b70148503d2dfc"),
- new BlockCipherVectorTest(1, new NoekeonEngine(),
- new KeyParameter(Hex.decode("ffffffffffffffffffffffffffffffff")),
- "ffffffffffffffffffffffffffffffff",
- "2a78421b87c7d0924f26113f1d1349b2"),
- new BlockCipherVectorTest(2, new NoekeonEngine(),
- new KeyParameter(Hex.decode("b1656851699e29fa24b70148503d2dfc")),
- "2a78421b87c7d0924f26113f1d1349b2",
- "e2f687e07b75660ffc372233bc47532c")
- };
-
- NoekeonTest()
- {
- super(tests, new NoekeonEngine(), new KeyParameter(new byte[16]));
- }
-
- public String getName()
- {
- return "Noekeon";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new NoekeonTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/NonMemoableDigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/NonMemoableDigestTest.java
deleted file mode 100644
index d332393b..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/NonMemoableDigestTest.java
+++ /dev/null
@@ -1,112 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.digests.NonMemoableDigest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.macs.HMac;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-/**
- * SHA1 HMac Test, test vectors from RFC 2202
- */
-public class NonMemoableDigestTest
- implements Test
-{
- final static String[] keys = {
- "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
- "4a656665",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
- "0102030405060708090a0b0c0d0e0f10111213141516171819",
- "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- };
-
- final static String[] digests = {
- "b617318655057264e28bc0b6fb378c8ef146be00",
- "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79",
- "125d7342b9ac11cd91a39af48aa17b4f63f175d3",
- "4c9007f4026250c6bc8414f9bf50c86c2d7235da",
- "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04",
- "aa4ae5e15272d00e95705637ce8a3b55ed402112",
- "e8e99d0f45237d786d6bbaa7965c7808bbff1a91",
- "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04",
- "aa4ae5e15272d00e95705637ce8a3b55ed402112",
- "e8e99d0f45237d786d6bbaa7965c7808bbff1a91"
- };
-
- final static String[] messages = {
- "Hi There",
- "what do ya want for nothing?",
- "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
- "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
- "Test With Truncation",
- "Test Using Larger Than Block-Size Key - Hash Key First",
- "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
- };
-
- public String getName()
- {
- return "NonMemoableDigest";
- }
-
- public TestResult perform()
- {
- HMac hmac = new HMac(new NonMemoableDigest(new SHA1Digest()));
- byte[] resBuf = new byte[hmac.getMacSize()];
-
- for (int i = 0; i < messages.length; i++)
- {
- byte[] m = messages[i].getBytes();
- if (messages[i].startsWith("0x"))
- {
- m = Hex.decode(messages[i].substring(2));
- }
- hmac.init(new KeyParameter(Hex.decode(keys[i])));
- hmac.update(m, 0, m.length);
- hmac.doFinal(resBuf, 0);
-
- if (!Arrays.areEqual(resBuf, Hex.decode(digests[i])))
- {
- return new SimpleTestResult(false, getName() + ": Vector " + i + " failed");
- }
- }
-
- //
- // test reset
- //
- int vector = 0; // vector used for test
- byte[] m = messages[vector].getBytes();
- if (messages[vector].startsWith("0x"))
- {
- m = Hex.decode(messages[vector].substring(2));
- }
- hmac.init(new KeyParameter(Hex.decode(keys[vector])));
- hmac.update(m, 0, m.length);
- hmac.doFinal(resBuf, 0);
- hmac.reset();
- hmac.update(m, 0, m.length);
- hmac.doFinal(resBuf, 0);
-
- if (!Arrays.areEqual(resBuf, Hex.decode(digests[vector])))
- {
- return new SimpleTestResult(false, getName() +
- "Reset with vector " + vector + " failed");
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
-
- public static void main(
- String[] args)
- {
- NonMemoableDigestTest test = new NonMemoableDigestTest();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/NullTest.java b/core/src/test/java/org/bouncycastle/crypto/test/NullTest.java
deleted file mode 100644
index ef8ff4b5..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/NullTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.engines.NullEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class NullTest
- extends CipherTest
-{
- static SimpleTest[] tests =
- {
- new BlockCipherVectorTest(0, new NullEngine(),
- new KeyParameter(Hex.decode("00")), "00", "00")
- };
-
- NullTest()
- {
- super(tests, new NullEngine(), new KeyParameter(new byte[2]));
- }
-
- public String getName()
- {
- return "Null";
- }
-
- public void performTest()
- throws Exception
- {
- super.performTest();
-
- BlockCipher engine = new NullEngine();
-
- engine.init(true, null);
-
- byte[] buf = new byte[1];
-
- engine.processBlock(buf, 0, buf, 0);
-
- if (buf[0] != 0)
- {
- fail("NullCipher changed data!");
- }
-
- byte[] shortBuf = new byte[0];
-
- try
- {
- engine.processBlock(shortBuf, 0, buf, 0);
-
- fail("failed short input check");
- }
- catch (DataLengthException e)
- {
- // expected
- }
-
- try
- {
- engine.processBlock(buf, 0, shortBuf, 0);
-
- fail("failed short output check");
- }
- catch (DataLengthException e)
- {
- // expected
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new NullTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/OAEPTest.java b/core/src/test/java/org/bouncycastle/crypto/test/OAEPTest.java
deleted file mode 100644
index 9d6b0cba..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/OAEPTest.java
+++ /dev/null
@@ -1,830 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.io.ByteArrayInputStream;
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
-import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
-import org.bouncycastle.asn1.pkcs.RSAPublicKey;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.encodings.OAEPEncoding;
-import org.bouncycastle.crypto.engines.RSAEngine;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class OAEPTest
- extends SimpleTest
-{
- static byte[] pubKeyEnc1 =
- {
- (byte)0x30, (byte)0x5a, (byte)0x30, (byte)0x0d, (byte)0x06, (byte)0x09, (byte)0x2a, (byte)0x86,
- (byte)0x48, (byte)0x86, (byte)0xf7, (byte)0x0d, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x05,
- (byte)0x00, (byte)0x03, (byte)0x49, (byte)0x00, (byte)0x30, (byte)0x46, (byte)0x02, (byte)0x41,
- (byte)0x00, (byte)0xaa, (byte)0x36, (byte)0xab, (byte)0xce, (byte)0x88, (byte)0xac, (byte)0xfd,
- (byte)0xff, (byte)0x55, (byte)0x52, (byte)0x3c, (byte)0x7f, (byte)0xc4, (byte)0x52, (byte)0x3f,
- (byte)0x90, (byte)0xef, (byte)0xa0, (byte)0x0d, (byte)0xf3, (byte)0x77, (byte)0x4a, (byte)0x25,
- (byte)0x9f, (byte)0x2e, (byte)0x62, (byte)0xb4, (byte)0xc5, (byte)0xd9, (byte)0x9c, (byte)0xb5,
- (byte)0xad, (byte)0xb3, (byte)0x00, (byte)0xa0, (byte)0x28, (byte)0x5e, (byte)0x53, (byte)0x01,
- (byte)0x93, (byte)0x0e, (byte)0x0c, (byte)0x70, (byte)0xfb, (byte)0x68, (byte)0x76, (byte)0x93,
- (byte)0x9c, (byte)0xe6, (byte)0x16, (byte)0xce, (byte)0x62, (byte)0x4a, (byte)0x11, (byte)0xe0,
- (byte)0x08, (byte)0x6d, (byte)0x34, (byte)0x1e, (byte)0xbc, (byte)0xac, (byte)0xa0, (byte)0xa1,
- (byte)0xf5, (byte)0x02, (byte)0x01, (byte)0x11
- };
-
- static byte[] privKeyEnc1 =
- {
- (byte)0x30, (byte)0x82, (byte)0x01, (byte)0x52, (byte)0x02, (byte)0x01, (byte)0x00, (byte)0x30,
- (byte)0x0d, (byte)0x06, (byte)0x09, (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0x86, (byte)0xf7,
- (byte)0x0d, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x05, (byte)0x00, (byte)0x04, (byte)0x82,
- (byte)0x01, (byte)0x3c, (byte)0x30, (byte)0x82, (byte)0x01, (byte)0x38, (byte)0x02, (byte)0x01,
- (byte)0x00, (byte)0x02, (byte)0x41, (byte)0x00, (byte)0xaa, (byte)0x36, (byte)0xab, (byte)0xce,
- (byte)0x88, (byte)0xac, (byte)0xfd, (byte)0xff, (byte)0x55, (byte)0x52, (byte)0x3c, (byte)0x7f,
- (byte)0xc4, (byte)0x52, (byte)0x3f, (byte)0x90, (byte)0xef, (byte)0xa0, (byte)0x0d, (byte)0xf3,
- (byte)0x77, (byte)0x4a, (byte)0x25, (byte)0x9f, (byte)0x2e, (byte)0x62, (byte)0xb4, (byte)0xc5,
- (byte)0xd9, (byte)0x9c, (byte)0xb5, (byte)0xad, (byte)0xb3, (byte)0x00, (byte)0xa0, (byte)0x28,
- (byte)0x5e, (byte)0x53, (byte)0x01, (byte)0x93, (byte)0x0e, (byte)0x0c, (byte)0x70, (byte)0xfb,
- (byte)0x68, (byte)0x76, (byte)0x93, (byte)0x9c, (byte)0xe6, (byte)0x16, (byte)0xce, (byte)0x62,
- (byte)0x4a, (byte)0x11, (byte)0xe0, (byte)0x08, (byte)0x6d, (byte)0x34, (byte)0x1e, (byte)0xbc,
- (byte)0xac, (byte)0xa0, (byte)0xa1, (byte)0xf5, (byte)0x02, (byte)0x01, (byte)0x11, (byte)0x02,
- (byte)0x40, (byte)0x0a, (byte)0x03, (byte)0x37, (byte)0x48, (byte)0x62, (byte)0x64, (byte)0x87,
- (byte)0x69, (byte)0x5f, (byte)0x5f, (byte)0x30, (byte)0xbc, (byte)0x38, (byte)0xb9, (byte)0x8b,
- (byte)0x44, (byte)0xc2, (byte)0xcd, (byte)0x2d, (byte)0xff, (byte)0x43, (byte)0x40, (byte)0x98,
- (byte)0xcd, (byte)0x20, (byte)0xd8, (byte)0xa1, (byte)0x38, (byte)0xd0, (byte)0x90, (byte)0xbf,
- (byte)0x64, (byte)0x79, (byte)0x7c, (byte)0x3f, (byte)0xa7, (byte)0xa2, (byte)0xcd, (byte)0xcb,
- (byte)0x3c, (byte)0xd1, (byte)0xe0, (byte)0xbd, (byte)0xba, (byte)0x26, (byte)0x54, (byte)0xb4,
- (byte)0xf9, (byte)0xdf, (byte)0x8e, (byte)0x8a, (byte)0xe5, (byte)0x9d, (byte)0x73, (byte)0x3d,
- (byte)0x9f, (byte)0x33, (byte)0xb3, (byte)0x01, (byte)0x62, (byte)0x4a, (byte)0xfd, (byte)0x1d,
- (byte)0x51, (byte)0x02, (byte)0x21, (byte)0x00, (byte)0xd8, (byte)0x40, (byte)0xb4, (byte)0x16,
- (byte)0x66, (byte)0xb4, (byte)0x2e, (byte)0x92, (byte)0xea, (byte)0x0d, (byte)0xa3, (byte)0xb4,
- (byte)0x32, (byte)0x04, (byte)0xb5, (byte)0xcf, (byte)0xce, (byte)0x33, (byte)0x52, (byte)0x52,
- (byte)0x4d, (byte)0x04, (byte)0x16, (byte)0xa5, (byte)0xa4, (byte)0x41, (byte)0xe7, (byte)0x00,
- (byte)0xaf, (byte)0x46, (byte)0x12, (byte)0x0d, (byte)0x02, (byte)0x21, (byte)0x00, (byte)0xc9,
- (byte)0x7f, (byte)0xb1, (byte)0xf0, (byte)0x27, (byte)0xf4, (byte)0x53, (byte)0xf6, (byte)0x34,
- (byte)0x12, (byte)0x33, (byte)0xea, (byte)0xaa, (byte)0xd1, (byte)0xd9, (byte)0x35, (byte)0x3f,
- (byte)0x6c, (byte)0x42, (byte)0xd0, (byte)0x88, (byte)0x66, (byte)0xb1, (byte)0xd0, (byte)0x5a,
- (byte)0x0f, (byte)0x20, (byte)0x35, (byte)0x02, (byte)0x8b, (byte)0x9d, (byte)0x89, (byte)0x02,
- (byte)0x20, (byte)0x59, (byte)0x0b, (byte)0x95, (byte)0x72, (byte)0xa2, (byte)0xc2, (byte)0xa9,
- (byte)0xc4, (byte)0x06, (byte)0x05, (byte)0x9d, (byte)0xc2, (byte)0xab, (byte)0x2f, (byte)0x1d,
- (byte)0xaf, (byte)0xeb, (byte)0x7e, (byte)0x8b, (byte)0x4f, (byte)0x10, (byte)0xa7, (byte)0x54,
- (byte)0x9e, (byte)0x8e, (byte)0xed, (byte)0xf5, (byte)0xb4, (byte)0xfc, (byte)0xe0, (byte)0x9e,
- (byte)0x05, (byte)0x02, (byte)0x21, (byte)0x00, (byte)0x8e, (byte)0x3c, (byte)0x05, (byte)0x21,
- (byte)0xfe, (byte)0x15, (byte)0xe0, (byte)0xea, (byte)0x06, (byte)0xa3, (byte)0x6f, (byte)0xf0,
- (byte)0xf1, (byte)0x0c, (byte)0x99, (byte)0x52, (byte)0xc3, (byte)0x5b, (byte)0x7a, (byte)0x75,
- (byte)0x14, (byte)0xfd, (byte)0x32, (byte)0x38, (byte)0xb8, (byte)0x0a, (byte)0xad, (byte)0x52,
- (byte)0x98, (byte)0x62, (byte)0x8d, (byte)0x51, (byte)0x02, (byte)0x20, (byte)0x36, (byte)0x3f,
- (byte)0xf7, (byte)0x18, (byte)0x9d, (byte)0xa8, (byte)0xe9, (byte)0x0b, (byte)0x1d, (byte)0x34,
- (byte)0x1f, (byte)0x71, (byte)0xd0, (byte)0x9b, (byte)0x76, (byte)0xa8, (byte)0xa9, (byte)0x43,
- (byte)0xe1, (byte)0x1d, (byte)0x10, (byte)0xb2, (byte)0x4d, (byte)0x24, (byte)0x9f, (byte)0x2d,
- (byte)0xea, (byte)0xfe, (byte)0xf8, (byte)0x0c, (byte)0x18, (byte)0x26
- };
-
- static byte[] output1 =
- {
- (byte)0x1b, (byte)0x8f, (byte)0x05, (byte)0xf9, (byte)0xca, (byte)0x1a, (byte)0x79, (byte)0x52,
- (byte)0x6e, (byte)0x53, (byte)0xf3, (byte)0xcc, (byte)0x51, (byte)0x4f, (byte)0xdb, (byte)0x89,
- (byte)0x2b, (byte)0xfb, (byte)0x91, (byte)0x93, (byte)0x23, (byte)0x1e, (byte)0x78, (byte)0xb9,
- (byte)0x92, (byte)0xe6, (byte)0x8d, (byte)0x50, (byte)0xa4, (byte)0x80, (byte)0xcb, (byte)0x52,
- (byte)0x33, (byte)0x89, (byte)0x5c, (byte)0x74, (byte)0x95, (byte)0x8d, (byte)0x5d, (byte)0x02,
- (byte)0xab, (byte)0x8c, (byte)0x0f, (byte)0xd0, (byte)0x40, (byte)0xeb, (byte)0x58, (byte)0x44,
- (byte)0xb0, (byte)0x05, (byte)0xc3, (byte)0x9e, (byte)0xd8, (byte)0x27, (byte)0x4a, (byte)0x9d,
- (byte)0xbf, (byte)0xa8, (byte)0x06, (byte)0x71, (byte)0x40, (byte)0x94, (byte)0x39, (byte)0xd2
- };
-
- static byte[] pubKeyEnc2 =
- {
- (byte)0x30, (byte)0x4c, (byte)0x30, (byte)0x0d, (byte)0x06, (byte)0x09, (byte)0x2a, (byte)0x86,
- (byte)0x48, (byte)0x86, (byte)0xf7, (byte)0x0d, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x05,
- (byte)0x00, (byte)0x03, (byte)0x3b, (byte)0x00, (byte)0x30, (byte)0x38, (byte)0x02, (byte)0x33,
- (byte)0x00, (byte)0xa3, (byte)0x07, (byte)0x9a, (byte)0x90, (byte)0xdf, (byte)0x0d, (byte)0xfd,
- (byte)0x72, (byte)0xac, (byte)0x09, (byte)0x0c, (byte)0xcc, (byte)0x2a, (byte)0x78, (byte)0xb8,
- (byte)0x74, (byte)0x13, (byte)0x13, (byte)0x3e, (byte)0x40, (byte)0x75, (byte)0x9c, (byte)0x98,
- (byte)0xfa, (byte)0xf8, (byte)0x20, (byte)0x4f, (byte)0x35, (byte)0x8a, (byte)0x0b, (byte)0x26,
- (byte)0x3c, (byte)0x67, (byte)0x70, (byte)0xe7, (byte)0x83, (byte)0xa9, (byte)0x3b, (byte)0x69,
- (byte)0x71, (byte)0xb7, (byte)0x37, (byte)0x79, (byte)0xd2, (byte)0x71, (byte)0x7b, (byte)0xe8,
- (byte)0x34, (byte)0x77, (byte)0xcf, (byte)0x02, (byte)0x01, (byte)0x03
- };
-
- static byte[] privKeyEnc2 =
- {
- (byte)0x30, (byte)0x82, (byte)0x01, (byte)0x13, (byte)0x02, (byte)0x01, (byte)0x00, (byte)0x30,
- (byte)0x0d, (byte)0x06, (byte)0x09, (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0x86, (byte)0xf7,
- (byte)0x0d, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x05, (byte)0x00, (byte)0x04, (byte)0x81,
- (byte)0xfe, (byte)0x30, (byte)0x81, (byte)0xfb, (byte)0x02, (byte)0x01, (byte)0x00, (byte)0x02,
- (byte)0x33, (byte)0x00, (byte)0xa3, (byte)0x07, (byte)0x9a, (byte)0x90, (byte)0xdf, (byte)0x0d,
- (byte)0xfd, (byte)0x72, (byte)0xac, (byte)0x09, (byte)0x0c, (byte)0xcc, (byte)0x2a, (byte)0x78,
- (byte)0xb8, (byte)0x74, (byte)0x13, (byte)0x13, (byte)0x3e, (byte)0x40, (byte)0x75, (byte)0x9c,
- (byte)0x98, (byte)0xfa, (byte)0xf8, (byte)0x20, (byte)0x4f, (byte)0x35, (byte)0x8a, (byte)0x0b,
- (byte)0x26, (byte)0x3c, (byte)0x67, (byte)0x70, (byte)0xe7, (byte)0x83, (byte)0xa9, (byte)0x3b,
- (byte)0x69, (byte)0x71, (byte)0xb7, (byte)0x37, (byte)0x79, (byte)0xd2, (byte)0x71, (byte)0x7b,
- (byte)0xe8, (byte)0x34, (byte)0x77, (byte)0xcf, (byte)0x02, (byte)0x01, (byte)0x03, (byte)0x02,
- (byte)0x32, (byte)0x6c, (byte)0xaf, (byte)0xbc, (byte)0x60, (byte)0x94, (byte)0xb3, (byte)0xfe,
- (byte)0x4c, (byte)0x72, (byte)0xb0, (byte)0xb3, (byte)0x32, (byte)0xc6, (byte)0xfb, (byte)0x25,
- (byte)0xa2, (byte)0xb7, (byte)0x62, (byte)0x29, (byte)0x80, (byte)0x4e, (byte)0x68, (byte)0x65,
- (byte)0xfc, (byte)0xa4, (byte)0x5a, (byte)0x74, (byte)0xdf, (byte)0x0f, (byte)0x8f, (byte)0xb8,
- (byte)0x41, (byte)0x3b, (byte)0x52, (byte)0xc0, (byte)0xd0, (byte)0xe5, (byte)0x3d, (byte)0x9b,
- (byte)0x59, (byte)0x0f, (byte)0xf1, (byte)0x9b, (byte)0xe7, (byte)0x9f, (byte)0x49, (byte)0xdd,
- (byte)0x21, (byte)0xe5, (byte)0xeb, (byte)0x02, (byte)0x1a, (byte)0x00, (byte)0xcf, (byte)0x20,
- (byte)0x35, (byte)0x02, (byte)0x8b, (byte)0x9d, (byte)0x86, (byte)0x98, (byte)0x40, (byte)0xb4,
- (byte)0x16, (byte)0x66, (byte)0xb4, (byte)0x2e, (byte)0x92, (byte)0xea, (byte)0x0d, (byte)0xa3,
- (byte)0xb4, (byte)0x32, (byte)0x04, (byte)0xb5, (byte)0xcf, (byte)0xce, (byte)0x91, (byte)0x02,
- (byte)0x1a, (byte)0x00, (byte)0xc9, (byte)0x7f, (byte)0xb1, (byte)0xf0, (byte)0x27, (byte)0xf4,
- (byte)0x53, (byte)0xf6, (byte)0x34, (byte)0x12, (byte)0x33, (byte)0xea, (byte)0xaa, (byte)0xd1,
- (byte)0xd9, (byte)0x35, (byte)0x3f, (byte)0x6c, (byte)0x42, (byte)0xd0, (byte)0x88, (byte)0x66,
- (byte)0xb1, (byte)0xd0, (byte)0x5f, (byte)0x02, (byte)0x1a, (byte)0x00, (byte)0x8a, (byte)0x15,
- (byte)0x78, (byte)0xac, (byte)0x5d, (byte)0x13, (byte)0xaf, (byte)0x10, (byte)0x2b, (byte)0x22,
- (byte)0xb9, (byte)0x99, (byte)0xcd, (byte)0x74, (byte)0x61, (byte)0xf1, (byte)0x5e, (byte)0x6d,
- (byte)0x22, (byte)0xcc, (byte)0x03, (byte)0x23, (byte)0xdf, (byte)0xdf, (byte)0x0b, (byte)0x02,
- (byte)0x1a, (byte)0x00, (byte)0x86, (byte)0x55, (byte)0x21, (byte)0x4a, (byte)0xc5, (byte)0x4d,
- (byte)0x8d, (byte)0x4e, (byte)0xcd, (byte)0x61, (byte)0x77, (byte)0xf1, (byte)0xc7, (byte)0x36,
- (byte)0x90, (byte)0xce, (byte)0x2a, (byte)0x48, (byte)0x2c, (byte)0x8b, (byte)0x05, (byte)0x99,
- (byte)0xcb, (byte)0xe0, (byte)0x3f, (byte)0x02, (byte)0x1a, (byte)0x00, (byte)0x83, (byte)0xef,
- (byte)0xef, (byte)0xb8, (byte)0xa9, (byte)0xa4, (byte)0x0d, (byte)0x1d, (byte)0xb6, (byte)0xed,
- (byte)0x98, (byte)0xad, (byte)0x84, (byte)0xed, (byte)0x13, (byte)0x35, (byte)0xdc, (byte)0xc1,
- (byte)0x08, (byte)0xf3, (byte)0x22, (byte)0xd0, (byte)0x57, (byte)0xcf, (byte)0x8d
- };
-
- static byte[] output2 =
- {
- (byte)0x14, (byte)0xbd, (byte)0xdd, (byte)0x28, (byte)0xc9, (byte)0x83, (byte)0x35, (byte)0x19,
- (byte)0x23, (byte)0x80, (byte)0xe8, (byte)0xe5, (byte)0x49, (byte)0xb1, (byte)0x58, (byte)0x2a,
- (byte)0x8b, (byte)0x40, (byte)0xb4, (byte)0x48, (byte)0x6d, (byte)0x03, (byte)0xa6, (byte)0xa5,
- (byte)0x31, (byte)0x1f, (byte)0x1f, (byte)0xd5, (byte)0xf0, (byte)0xa1, (byte)0x80, (byte)0xe4,
- (byte)0x17, (byte)0x53, (byte)0x03, (byte)0x29, (byte)0xa9, (byte)0x34, (byte)0x90, (byte)0x74,
- (byte)0xb1, (byte)0x52, (byte)0x13, (byte)0x54, (byte)0x29, (byte)0x08, (byte)0x24, (byte)0x52,
- (byte)0x62, (byte)0x51
- };
-
- static byte[] pubKeyEnc3 =
- {
- (byte)0x30, (byte)0x81, (byte)0x9d, (byte)0x30, (byte)0x0d, (byte)0x06, (byte)0x09, (byte)0x2a,
- (byte)0x86, (byte)0x48, (byte)0x86, (byte)0xf7, (byte)0x0d, (byte)0x01, (byte)0x01, (byte)0x01,
- (byte)0x05, (byte)0x00, (byte)0x03, (byte)0x81, (byte)0x8b, (byte)0x00, (byte)0x30, (byte)0x81,
- (byte)0x87, (byte)0x02, (byte)0x81, (byte)0x81, (byte)0x00, (byte)0xbb, (byte)0xf8, (byte)0x2f,
- (byte)0x09, (byte)0x06, (byte)0x82, (byte)0xce, (byte)0x9c, (byte)0x23, (byte)0x38, (byte)0xac,
- (byte)0x2b, (byte)0x9d, (byte)0xa8, (byte)0x71, (byte)0xf7, (byte)0x36, (byte)0x8d, (byte)0x07,
- (byte)0xee, (byte)0xd4, (byte)0x10, (byte)0x43, (byte)0xa4, (byte)0x40, (byte)0xd6, (byte)0xb6,
- (byte)0xf0, (byte)0x74, (byte)0x54, (byte)0xf5, (byte)0x1f, (byte)0xb8, (byte)0xdf, (byte)0xba,
- (byte)0xaf, (byte)0x03, (byte)0x5c, (byte)0x02, (byte)0xab, (byte)0x61, (byte)0xea, (byte)0x48,
- (byte)0xce, (byte)0xeb, (byte)0x6f, (byte)0xcd, (byte)0x48, (byte)0x76, (byte)0xed, (byte)0x52,
- (byte)0x0d, (byte)0x60, (byte)0xe1, (byte)0xec, (byte)0x46, (byte)0x19, (byte)0x71, (byte)0x9d,
- (byte)0x8a, (byte)0x5b, (byte)0x8b, (byte)0x80, (byte)0x7f, (byte)0xaf, (byte)0xb8, (byte)0xe0,
- (byte)0xa3, (byte)0xdf, (byte)0xc7, (byte)0x37, (byte)0x72, (byte)0x3e, (byte)0xe6, (byte)0xb4,
- (byte)0xb7, (byte)0xd9, (byte)0x3a, (byte)0x25, (byte)0x84, (byte)0xee, (byte)0x6a, (byte)0x64,
- (byte)0x9d, (byte)0x06, (byte)0x09, (byte)0x53, (byte)0x74, (byte)0x88, (byte)0x34, (byte)0xb2,
- (byte)0x45, (byte)0x45, (byte)0x98, (byte)0x39, (byte)0x4e, (byte)0xe0, (byte)0xaa, (byte)0xb1,
- (byte)0x2d, (byte)0x7b, (byte)0x61, (byte)0xa5, (byte)0x1f, (byte)0x52, (byte)0x7a, (byte)0x9a,
- (byte)0x41, (byte)0xf6, (byte)0xc1, (byte)0x68, (byte)0x7f, (byte)0xe2, (byte)0x53, (byte)0x72,
- (byte)0x98, (byte)0xca, (byte)0x2a, (byte)0x8f, (byte)0x59, (byte)0x46, (byte)0xf8, (byte)0xe5,
- (byte)0xfd, (byte)0x09, (byte)0x1d, (byte)0xbd, (byte)0xcb, (byte)0x02, (byte)0x01, (byte)0x11
- };
-
- static byte[] privKeyEnc3 =
- {
- (byte)0x30, (byte)0x82, (byte)0x02, (byte)0x75, (byte)0x02, (byte)0x01, (byte)0x00, (byte)0x30,
- (byte)0x0d, (byte)0x06, (byte)0x09, (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0x86, (byte)0xf7,
- (byte)0x0d, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x05, (byte)0x00, (byte)0x04, (byte)0x82,
- (byte)0x02, (byte)0x5f, (byte)0x30, (byte)0x82, (byte)0x02, (byte)0x5b, (byte)0x02, (byte)0x01,
- (byte)0x00, (byte)0x02, (byte)0x81, (byte)0x81, (byte)0x00, (byte)0xbb, (byte)0xf8, (byte)0x2f,
- (byte)0x09, (byte)0x06, (byte)0x82, (byte)0xce, (byte)0x9c, (byte)0x23, (byte)0x38, (byte)0xac,
- (byte)0x2b, (byte)0x9d, (byte)0xa8, (byte)0x71, (byte)0xf7, (byte)0x36, (byte)0x8d, (byte)0x07,
- (byte)0xee, (byte)0xd4, (byte)0x10, (byte)0x43, (byte)0xa4, (byte)0x40, (byte)0xd6, (byte)0xb6,
- (byte)0xf0, (byte)0x74, (byte)0x54, (byte)0xf5, (byte)0x1f, (byte)0xb8, (byte)0xdf, (byte)0xba,
- (byte)0xaf, (byte)0x03, (byte)0x5c, (byte)0x02, (byte)0xab, (byte)0x61, (byte)0xea, (byte)0x48,
- (byte)0xce, (byte)0xeb, (byte)0x6f, (byte)0xcd, (byte)0x48, (byte)0x76, (byte)0xed, (byte)0x52,
- (byte)0x0d, (byte)0x60, (byte)0xe1, (byte)0xec, (byte)0x46, (byte)0x19, (byte)0x71, (byte)0x9d,
- (byte)0x8a, (byte)0x5b, (byte)0x8b, (byte)0x80, (byte)0x7f, (byte)0xaf, (byte)0xb8, (byte)0xe0,
- (byte)0xa3, (byte)0xdf, (byte)0xc7, (byte)0x37, (byte)0x72, (byte)0x3e, (byte)0xe6, (byte)0xb4,
- (byte)0xb7, (byte)0xd9, (byte)0x3a, (byte)0x25, (byte)0x84, (byte)0xee, (byte)0x6a, (byte)0x64,
- (byte)0x9d, (byte)0x06, (byte)0x09, (byte)0x53, (byte)0x74, (byte)0x88, (byte)0x34, (byte)0xb2,
- (byte)0x45, (byte)0x45, (byte)0x98, (byte)0x39, (byte)0x4e, (byte)0xe0, (byte)0xaa, (byte)0xb1,
- (byte)0x2d, (byte)0x7b, (byte)0x61, (byte)0xa5, (byte)0x1f, (byte)0x52, (byte)0x7a, (byte)0x9a,
- (byte)0x41, (byte)0xf6, (byte)0xc1, (byte)0x68, (byte)0x7f, (byte)0xe2, (byte)0x53, (byte)0x72,
- (byte)0x98, (byte)0xca, (byte)0x2a, (byte)0x8f, (byte)0x59, (byte)0x46, (byte)0xf8, (byte)0xe5,
- (byte)0xfd, (byte)0x09, (byte)0x1d, (byte)0xbd, (byte)0xcb, (byte)0x02, (byte)0x01, (byte)0x11,
- (byte)0x02, (byte)0x81, (byte)0x81, (byte)0x00, (byte)0xa5, (byte)0xda, (byte)0xfc, (byte)0x53,
- (byte)0x41, (byte)0xfa, (byte)0xf2, (byte)0x89, (byte)0xc4, (byte)0xb9, (byte)0x88, (byte)0xdb,
- (byte)0x30, (byte)0xc1, (byte)0xcd, (byte)0xf8, (byte)0x3f, (byte)0x31, (byte)0x25, (byte)0x1e,
- (byte)0x06, (byte)0x68, (byte)0xb4, (byte)0x27, (byte)0x84, (byte)0x81, (byte)0x38, (byte)0x01,
- (byte)0x57, (byte)0x96, (byte)0x41, (byte)0xb2, (byte)0x94, (byte)0x10, (byte)0xb3, (byte)0xc7,
- (byte)0x99, (byte)0x8d, (byte)0x6b, (byte)0xc4, (byte)0x65, (byte)0x74, (byte)0x5e, (byte)0x5c,
- (byte)0x39, (byte)0x26, (byte)0x69, (byte)0xd6, (byte)0x87, (byte)0x0d, (byte)0xa2, (byte)0xc0,
- (byte)0x82, (byte)0xa9, (byte)0x39, (byte)0xe3, (byte)0x7f, (byte)0xdc, (byte)0xb8, (byte)0x2e,
- (byte)0xc9, (byte)0x3e, (byte)0xda, (byte)0xc9, (byte)0x7f, (byte)0xf3, (byte)0xad, (byte)0x59,
- (byte)0x50, (byte)0xac, (byte)0xcf, (byte)0xbc, (byte)0x11, (byte)0x1c, (byte)0x76, (byte)0xf1,
- (byte)0xa9, (byte)0x52, (byte)0x94, (byte)0x44, (byte)0xe5, (byte)0x6a, (byte)0xaf, (byte)0x68,
- (byte)0xc5, (byte)0x6c, (byte)0x09, (byte)0x2c, (byte)0xd3, (byte)0x8d, (byte)0xc3, (byte)0xbe,
- (byte)0xf5, (byte)0xd2, (byte)0x0a, (byte)0x93, (byte)0x99, (byte)0x26, (byte)0xed, (byte)0x4f,
- (byte)0x74, (byte)0xa1, (byte)0x3e, (byte)0xdd, (byte)0xfb, (byte)0xe1, (byte)0xa1, (byte)0xce,
- (byte)0xcc, (byte)0x48, (byte)0x94, (byte)0xaf, (byte)0x94, (byte)0x28, (byte)0xc2, (byte)0xb7,
- (byte)0xb8, (byte)0x88, (byte)0x3f, (byte)0xe4, (byte)0x46, (byte)0x3a, (byte)0x4b, (byte)0xc8,
- (byte)0x5b, (byte)0x1c, (byte)0xb3, (byte)0xc1, (byte)0x02, (byte)0x41, (byte)0x00, (byte)0xee,
- (byte)0xcf, (byte)0xae, (byte)0x81, (byte)0xb1, (byte)0xb9, (byte)0xb3, (byte)0xc9, (byte)0x08,
- (byte)0x81, (byte)0x0b, (byte)0x10, (byte)0xa1, (byte)0xb5, (byte)0x60, (byte)0x01, (byte)0x99,
- (byte)0xeb, (byte)0x9f, (byte)0x44, (byte)0xae, (byte)0xf4, (byte)0xfd, (byte)0xa4, (byte)0x93,
- (byte)0xb8, (byte)0x1a, (byte)0x9e, (byte)0x3d, (byte)0x84, (byte)0xf6, (byte)0x32, (byte)0x12,
- (byte)0x4e, (byte)0xf0, (byte)0x23, (byte)0x6e, (byte)0x5d, (byte)0x1e, (byte)0x3b, (byte)0x7e,
- (byte)0x28, (byte)0xfa, (byte)0xe7, (byte)0xaa, (byte)0x04, (byte)0x0a, (byte)0x2d, (byte)0x5b,
- (byte)0x25, (byte)0x21, (byte)0x76, (byte)0x45, (byte)0x9d, (byte)0x1f, (byte)0x39, (byte)0x75,
- (byte)0x41, (byte)0xba, (byte)0x2a, (byte)0x58, (byte)0xfb, (byte)0x65, (byte)0x99, (byte)0x02,
- (byte)0x41, (byte)0x00, (byte)0xc9, (byte)0x7f, (byte)0xb1, (byte)0xf0, (byte)0x27, (byte)0xf4,
- (byte)0x53, (byte)0xf6, (byte)0x34, (byte)0x12, (byte)0x33, (byte)0xea, (byte)0xaa, (byte)0xd1,
- (byte)0xd9, (byte)0x35, (byte)0x3f, (byte)0x6c, (byte)0x42, (byte)0xd0, (byte)0x88, (byte)0x66,
- (byte)0xb1, (byte)0xd0, (byte)0x5a, (byte)0x0f, (byte)0x20, (byte)0x35, (byte)0x02, (byte)0x8b,
- (byte)0x9d, (byte)0x86, (byte)0x98, (byte)0x40, (byte)0xb4, (byte)0x16, (byte)0x66, (byte)0xb4,
- (byte)0x2e, (byte)0x92, (byte)0xea, (byte)0x0d, (byte)0xa3, (byte)0xb4, (byte)0x32, (byte)0x04,
- (byte)0xb5, (byte)0xcf, (byte)0xce, (byte)0x33, (byte)0x52, (byte)0x52, (byte)0x4d, (byte)0x04,
- (byte)0x16, (byte)0xa5, (byte)0xa4, (byte)0x41, (byte)0xe7, (byte)0x00, (byte)0xaf, (byte)0x46,
- (byte)0x15, (byte)0x03, (byte)0x02, (byte)0x40, (byte)0x54, (byte)0x49, (byte)0x4c, (byte)0xa6,
- (byte)0x3e, (byte)0xba, (byte)0x03, (byte)0x37, (byte)0xe4, (byte)0xe2, (byte)0x40, (byte)0x23,
- (byte)0xfc, (byte)0xd6, (byte)0x9a, (byte)0x5a, (byte)0xeb, (byte)0x07, (byte)0xdd, (byte)0xdc,
- (byte)0x01, (byte)0x83, (byte)0xa4, (byte)0xd0, (byte)0xac, (byte)0x9b, (byte)0x54, (byte)0xb0,
- (byte)0x51, (byte)0xf2, (byte)0xb1, (byte)0x3e, (byte)0xd9, (byte)0x49, (byte)0x09, (byte)0x75,
- (byte)0xea, (byte)0xb7, (byte)0x74, (byte)0x14, (byte)0xff, (byte)0x59, (byte)0xc1, (byte)0xf7,
- (byte)0x69, (byte)0x2e, (byte)0x9a, (byte)0x2e, (byte)0x20, (byte)0x2b, (byte)0x38, (byte)0xfc,
- (byte)0x91, (byte)0x0a, (byte)0x47, (byte)0x41, (byte)0x74, (byte)0xad, (byte)0xc9, (byte)0x3c,
- (byte)0x1f, (byte)0x67, (byte)0xc9, (byte)0x81, (byte)0x02, (byte)0x40, (byte)0x47, (byte)0x1e,
- (byte)0x02, (byte)0x90, (byte)0xff, (byte)0x0a, (byte)0xf0, (byte)0x75, (byte)0x03, (byte)0x51,
- (byte)0xb7, (byte)0xf8, (byte)0x78, (byte)0x86, (byte)0x4c, (byte)0xa9, (byte)0x61, (byte)0xad,
- (byte)0xbd, (byte)0x3a, (byte)0x8a, (byte)0x7e, (byte)0x99, (byte)0x1c, (byte)0x5c, (byte)0x05,
- (byte)0x56, (byte)0xa9, (byte)0x4c, (byte)0x31, (byte)0x46, (byte)0xa7, (byte)0xf9, (byte)0x80,
- (byte)0x3f, (byte)0x8f, (byte)0x6f, (byte)0x8a, (byte)0xe3, (byte)0x42, (byte)0xe9, (byte)0x31,
- (byte)0xfd, (byte)0x8a, (byte)0xe4, (byte)0x7a, (byte)0x22, (byte)0x0d, (byte)0x1b, (byte)0x99,
- (byte)0xa4, (byte)0x95, (byte)0x84, (byte)0x98, (byte)0x07, (byte)0xfe, (byte)0x39, (byte)0xf9,
- (byte)0x24, (byte)0x5a, (byte)0x98, (byte)0x36, (byte)0xda, (byte)0x3d, (byte)0x02, (byte)0x41,
- (byte)0x00, (byte)0xb0, (byte)0x6c, (byte)0x4f, (byte)0xda, (byte)0xbb, (byte)0x63, (byte)0x01,
- (byte)0x19, (byte)0x8d, (byte)0x26, (byte)0x5b, (byte)0xdb, (byte)0xae, (byte)0x94, (byte)0x23,
- (byte)0xb3, (byte)0x80, (byte)0xf2, (byte)0x71, (byte)0xf7, (byte)0x34, (byte)0x53, (byte)0x88,
- (byte)0x50, (byte)0x93, (byte)0x07, (byte)0x7f, (byte)0xcd, (byte)0x39, (byte)0xe2, (byte)0x11,
- (byte)0x9f, (byte)0xc9, (byte)0x86, (byte)0x32, (byte)0x15, (byte)0x4f, (byte)0x58, (byte)0x83,
- (byte)0xb1, (byte)0x67, (byte)0xa9, (byte)0x67, (byte)0xbf, (byte)0x40, (byte)0x2b, (byte)0x4e,
- (byte)0x9e, (byte)0x2e, (byte)0x0f, (byte)0x96, (byte)0x56, (byte)0xe6, (byte)0x98, (byte)0xea,
- (byte)0x36, (byte)0x66, (byte)0xed, (byte)0xfb, (byte)0x25, (byte)0x79, (byte)0x80, (byte)0x39,
- (byte)0xf7
- };
-
- static byte[] output3 = Hex.decode(
- "b8246b56a6ed5881aeb585d9a25b2ad790c417e080681bf1ac2bc3deb69d8bce"
- + "f0c4366fec400af052a72e9b0effb5b3f2f192dbeaca03c12740057113bf1f06"
- + "69ac22e9f3a7852e3c15d913cab0b8863a95c99294ce8674214954610346f4d4"
- + "74b26f7c48b42ee68e1f572a1fc4026ac456b4f59f7b621ea1b9d88f64202fb1");
-
- byte[] seed = {
- (byte)0xaa, (byte)0xfd, (byte)0x12, (byte)0xf6, (byte)0x59,
- (byte)0xca, (byte)0xe6, (byte)0x34, (byte)0x89, (byte)0xb4,
- (byte)0x79, (byte)0xe5, (byte)0x07, (byte)0x6d, (byte)0xde,
- (byte)0xc2, (byte)0xf0, (byte)0x6c, (byte)0xb5, (byte)0x8f
- };
-
- private class VecRand extends SecureRandom
- {
- byte[] seed;
-
- VecRand(byte[] seed)
- {
- this.seed = seed;
- }
-
- public void nextBytes(
- byte[] bytes)
- {
- System.arraycopy(seed, 0, bytes, 0, bytes.length);
- }
- }
-
- private void baseOaepTest(
- int id,
- byte[] pubKeyEnc,
- byte[] privKeyEnc,
- byte[] output)
- throws Exception
- {
- ByteArrayInputStream bIn = new ByteArrayInputStream(pubKeyEnc);
- ASN1InputStream dIn = new ASN1InputStream(bIn);
-
- //
- // extract the public key info.
- //
- RSAPublicKey pubStruct;
-
- pubStruct = RSAPublicKey.getInstance(new SubjectPublicKeyInfo((ASN1Sequence)dIn.readObject()).parsePublicKey());
-
-
- bIn = new ByteArrayInputStream(privKeyEnc);
- dIn = new ASN1InputStream(bIn);
-
- //
- // extract the private key info.
- //
- RSAPrivateKey privStruct;
-
- privStruct = RSAPrivateKey.getInstance(new PrivateKeyInfo((ASN1Sequence)dIn.readObject()).parsePrivateKey());
-
- RSAKeyParameters pubParameters = new RSAKeyParameters(
- false,
- pubStruct.getModulus(),
- pubStruct.getPublicExponent());
-
- RSAKeyParameters privParameters = new RSAPrivateCrtKeyParameters(
- privStruct.getModulus(),
- privStruct.getPublicExponent(),
- privStruct.getPrivateExponent(),
- privStruct.getPrime1(),
- privStruct.getPrime2(),
- privStruct.getExponent1(),
- privStruct.getExponent2(),
- privStruct.getCoefficient());
-
- byte[] input = new byte[]
- { (byte)0x54, (byte)0x85, (byte)0x9b, (byte)0x34, (byte)0x2c, (byte)0x49, (byte)0xea, (byte)0x2a };
-
- encDec("id(" + id + ")", pubParameters, privParameters, seed, input, output);
-
- }
-
- private void encDec(
- String label,
- RSAKeyParameters pubParameters,
- RSAKeyParameters privParameters,
- byte[] seed,
- byte[] input,
- byte[] output)
- throws InvalidCipherTextException
- {
- AsymmetricBlockCipher cipher = new OAEPEncoding(new RSAEngine());
-
- cipher.init(true, new ParametersWithRandom(pubParameters, new VecRand(seed)));
-
- byte[] out;
-
- out = cipher.processBlock(input, 0, input.length);
-
- for (int i = 0; i != output.length; i++)
- {
- if (out[i] != output[i])
- {
- fail(label + " failed encryption");
- }
- }
-
- cipher.init(false, privParameters);
-
- out = cipher.processBlock(output, 0, output.length);
-
- for (int i = 0; i != input.length; i++)
- {
- if (out[i] != input[i])
- {
- fail(label + " failed decoding");
- }
- }
- }
-
- /*
- * RSA vector tests from PKCS#1 page
- */
- byte[] modulus_1024 = Hex.decode(
- "a8b3b284af8eb50b387034a860f146c4"
- + "919f318763cd6c5598c8ae4811a1e0ab"
- + "c4c7e0b082d693a5e7fced675cf46685"
- + "12772c0cbc64a742c6c630f533c8cc72"
- + "f62ae833c40bf25842e984bb78bdbf97"
- + "c0107d55bdb662f5c4e0fab9845cb514"
- + "8ef7392dd3aaff93ae1e6b667bb3d424"
- + "7616d4f5ba10d4cfd226de88d39f16fb");
-
- byte[] pubExp_1024 = Hex.decode(
- "010001");
-
- byte[] privExp_1024 = Hex.decode(
- "53339cfdb79fc8466a655c7316aca85c"
- + "55fd8f6dd898fdaf119517ef4f52e8fd"
- + "8e258df93fee180fa0e4ab29693cd83b"
- + "152a553d4ac4d1812b8b9fa5af0e7f55"
- + "fe7304df41570926f3311f15c4d65a73"
- + "2c483116ee3d3d2d0af3549ad9bf7cbf"
- + "b78ad884f84d5beb04724dc7369b31de"
- + "f37d0cf539e9cfcdd3de653729ead5d1");
-
- byte[] prime1_1024 = Hex.decode(
- "d32737e7267ffe1341b2d5c0d150a81b"
- + "586fb3132bed2f8d5262864a9cb9f30a"
- + "f38be448598d413a172efb802c21acf1"
- + "c11c520c2f26a471dcad212eac7ca39d");
-
- byte[] prime2_1024 = Hex.decode(
- "cc8853d1d54da630fac004f471f281c7"
- + "b8982d8224a490edbeb33d3e3d5cc93c"
- + "4765703d1dd791642f1f116a0dd852be"
- + "2419b2af72bfe9a030e860b0288b5d77");
-
- byte[] primeExp1_1024 = Hex.decode(
- "0e12bf1718e9cef5599ba1c3882fe804"
- + "6a90874eefce8f2ccc20e4f2741fb0a3"
- + "3a3848aec9c9305fbecbd2d76819967d"
- + "4671acc6431e4037968db37878e695c1");
-
- byte[] primeExp2_1024 = Hex.decode(
- "95297b0f95a2fa67d00707d609dfd4fc"
- + "05c89dafc2ef6d6ea55bec771ea33373"
- + "4d9251e79082ecda866efef13c459e1a"
- + "631386b7e354c899f5f112ca85d71583");
-
- byte[] crtCoef_1024 = Hex.decode(
- "4f456c502493bdc0ed2ab756a3a6ed4d"
- + "67352a697d4216e93212b127a63d5411"
- + "ce6fa98d5dbefd73263e372814274381"
- + "8166ed7dd63687dd2a8ca1d2f4fbd8e1");
-
- byte[] input_1024_1 = Hex.decode(
- "6628194e12073db03ba94cda9ef95323"
- + "97d50dba79b987004afefe34");
-
- byte[] seed_1024_1 = Hex.decode(
- "18b776ea21069d69776a33e96bad48e1"
- + "dda0a5ef");
-
- byte[] output_1024_1 = Hex.decode(
- "354fe67b4a126d5d35fe36c777791a3f"
- + "7ba13def484e2d3908aff722fad468fb"
- + "21696de95d0be911c2d3174f8afcc201"
- + "035f7b6d8e69402de5451618c21a535f"
- + "a9d7bfc5b8dd9fc243f8cf927db31322"
- + "d6e881eaa91a996170e657a05a266426"
- + "d98c88003f8477c1227094a0d9fa1e8c"
- + "4024309ce1ecccb5210035d47ac72e8a");
-
- byte[] input_1024_2 = Hex.decode(
- "750c4047f547e8e41411856523298ac9"
- + "bae245efaf1397fbe56f9dd5");
-
- byte[] seed_1024_2 = Hex.decode(
- "0cc742ce4a9b7f32f951bcb251efd925"
- + "fe4fe35f");
-
- byte[] output_1024_2 = Hex.decode(
- "640db1acc58e0568fe5407e5f9b701df"
- + "f8c3c91e716c536fc7fcec6cb5b71c11"
- + "65988d4a279e1577d730fc7a29932e3f"
- + "00c81515236d8d8e31017a7a09df4352"
- + "d904cdeb79aa583adcc31ea698a4c052"
- + "83daba9089be5491f67c1a4ee48dc74b"
- + "bbe6643aef846679b4cb395a352d5ed1"
- + "15912df696ffe0702932946d71492b44");
-
- byte[] input_1024_3 = Hex.decode(
- "d94ae0832e6445ce42331cb06d531a82"
- + "b1db4baad30f746dc916df24d4e3c245"
- + "1fff59a6423eb0e1d02d4fe646cf699d"
- + "fd818c6e97b051");
-
- byte[] seed_1024_3 = Hex.decode(
- "2514df4695755a67b288eaf4905c36ee"
- + "c66fd2fd");
-
- byte[] output_1024_3 = Hex.decode(
- "423736ed035f6026af276c35c0b3741b"
- + "365e5f76ca091b4e8c29e2f0befee603"
- + "595aa8322d602d2e625e95eb81b2f1c9"
- + "724e822eca76db8618cf09c5343503a4"
- + "360835b5903bc637e3879fb05e0ef326"
- + "85d5aec5067cd7cc96fe4b2670b6eac3"
- + "066b1fcf5686b68589aafb7d629b02d8"
- + "f8625ca3833624d4800fb081b1cf94eb");
-
- byte[] input_1024_4 = Hex.decode(
- "52e650d98e7f2a048b4f86852153b97e"
- + "01dd316f346a19f67a85");
-
- byte[] seed_1024_4 = Hex.decode(
- "c4435a3e1a18a68b6820436290a37cef"
- + "b85db3fb");
-
- byte[] output_1024_4 = Hex.decode(
- "45ead4ca551e662c9800f1aca8283b05"
- + "25e6abae30be4b4aba762fa40fd3d38e"
- + "22abefc69794f6ebbbc05ddbb1121624"
- + "7d2f412fd0fba87c6e3acd888813646f"
- + "d0e48e785204f9c3f73d6d8239562722"
- + "dddd8771fec48b83a31ee6f592c4cfd4"
- + "bc88174f3b13a112aae3b9f7b80e0fc6"
- + "f7255ba880dc7d8021e22ad6a85f0755");
-
- byte[] input_1024_5 = Hex.decode(
- "8da89fd9e5f974a29feffb462b49180f"
- + "6cf9e802");
-
- byte[] seed_1024_5 = Hex.decode(
- "b318c42df3be0f83fea823f5a7b47ed5"
- + "e425a3b5");
-
- byte[] output_1024_5 = Hex.decode(
- "36f6e34d94a8d34daacba33a2139d00a"
- + "d85a9345a86051e73071620056b920e2"
- + "19005855a213a0f23897cdcd731b4525"
- + "7c777fe908202befdd0b58386b1244ea"
- + "0cf539a05d5d10329da44e13030fd760"
- + "dcd644cfef2094d1910d3f433e1c7c6d"
- + "d18bc1f2df7f643d662fb9dd37ead905"
- + "9190f4fa66ca39e869c4eb449cbdc439");
-
- byte[] input_1024_6 = Hex.decode(
- "26521050844271");
-
- byte[] seed_1024_6 = Hex.decode(
- "e4ec0982c2336f3a677f6a356174eb0c"
- + "e887abc2");
-
- byte[] output_1024_6 = Hex.decode(
- "42cee2617b1ecea4db3f4829386fbd61"
- + "dafbf038e180d837c96366df24c097b4"
- + "ab0fac6bdf590d821c9f10642e681ad0"
- + "5b8d78b378c0f46ce2fad63f74e0ad3d"
- + "f06b075d7eb5f5636f8d403b9059ca76"
- + "1b5c62bb52aa45002ea70baace08ded2"
- + "43b9d8cbd62a68ade265832b56564e43"
- + "a6fa42ed199a099769742df1539e8255");
-
- byte[] modulus_1027 = Hex.decode(
- "051240b6cc0004fa48d0134671c078c7"
- + "c8dec3b3e2f25bc2564467339db38853"
- + "d06b85eea5b2de353bff42ac2e46bc97"
- + "fae6ac9618da9537a5c8f553c1e35762"
- + "5991d6108dcd7885fb3a25413f53efca"
- + "d948cb35cd9b9ae9c1c67626d113d57d"
- + "de4c5bea76bb5bb7de96c00d07372e96"
- + "85a6d75cf9d239fa148d70931b5f3fb0"
- + "39");
-
- byte[] pubExp_1027 = Hex.decode(
- "010001");
-
- byte[] privExp_1027 = Hex.decode(
- "0411ffca3b7ca5e9e9be7fe38a85105e"
- + "353896db05c5796aecd2a725161eb365"
- + "1c8629a9b862b904d7b0c7b37f8cb5a1"
- + "c2b54001018a00a1eb2cafe4ee4e9492"
- + "c348bc2bedab4b9ebbf064e8eff322b9"
- + "009f8eec653905f40df88a3cdc49d456"
- + "7f75627d41aca624129b46a0b7c698e5"
- + "e65f2b7ba102c749a10135b6540d0401");
-
- byte[] prime1_1027 = Hex.decode(
- "027458c19ec1636919e736c9af25d609"
- + "a51b8f561d19c6bf6943dd1ee1ab8a4a"
- + "3f232100bd40b88decc6ba235548b6ef"
- + "792a11c9de823d0a7922c7095b6eba57"
- + "01");
-
- byte[] prime2_1027 = Hex.decode(
- "0210ee9b33ab61716e27d251bd465f4b"
- + "35a1a232e2da00901c294bf22350ce49"
- + "0d099f642b5375612db63ba1f2038649"
- + "2bf04d34b3c22bceb909d13441b53b51"
- + "39");
-
- byte[] primeExp1_1027 = Hex.decode(
- "39fa028b826e88c1121b750a8b242fa9"
- + "a35c5b66bdfd1fa637d3cc48a84a4f45"
- + "7a194e7727e49f7bcc6e5a5a412657fc"
- + "470c7322ebc37416ef458c307a8c0901");
-
- byte[] primeExp2_1027 = Hex.decode(
- "015d99a84195943979fa9e1be2c3c1b6"
- + "9f432f46fd03e47d5befbbbfd6b1d137"
- + "1d83efb330a3e020942b2fed115e5d02"
- + "be24fd92c9019d1cecd6dd4cf1e54cc8"
- + "99");
-
- byte[] crtCoef_1027 = Hex.decode(
- "01f0b7015170b3f5e42223ba30301c41"
- + "a6d87cbb70e30cb7d3c67d25473db1f6"
- + "cbf03e3f9126e3e97968279a865b2c2b"
- + "426524cfc52a683d31ed30eb984be412"
- + "ba");
-
- byte[] input_1027_1 = Hex.decode(
- "4a86609534ee434a6cbca3f7e962e76d"
- + "455e3264c19f605f6e5ff6137c65c56d"
- + "7fb344cd52bc93374f3d166c9f0c6f9c"
- + "506bad19330972d2");
-
- byte[] seed_1027_1 = Hex.decode(
- "1cac19ce993def55f98203f6852896c9"
- + "5ccca1f3");
-
- byte[] output_1027_1 = Hex.decode(
- "04cce19614845e094152a3fe18e54e33"
- + "30c44e5efbc64ae16886cb1869014cc5"
- + "781b1f8f9e045384d0112a135ca0d12e"
- + "9c88a8e4063416deaae3844f60d6e96f"
- + "e155145f4525b9a34431ca3766180f70"
- + "e15a5e5d8e8b1a516ff870609f13f896"
- + "935ced188279a58ed13d07114277d75c"
- + "6568607e0ab092fd803a223e4a8ee0b1"
- + "a8");
-
- byte[] input_1027_2 = Hex.decode(
- "b0adc4f3fe11da59ce992773d9059943"
- + "c03046497ee9d9f9a06df1166db46d98"
- + "f58d27ec074c02eee6cbe2449c8b9fc5"
- + "080c5c3f4433092512ec46aa793743c8");
-
- byte[] seed_1027_2 = Hex.decode(
- "f545d5897585e3db71aa0cb8da76c51d"
- + "032ae963");
-
- byte[] output_1027_2 = Hex.decode(
- "0097b698c6165645b303486fbf5a2a44"
- + "79c0ee85889b541a6f0b858d6b6597b1"
- + "3b854eb4f839af03399a80d79bda6578"
- + "c841f90d645715b280d37143992dd186"
- + "c80b949b775cae97370e4ec97443136c"
- + "6da484e970ffdb1323a20847821d3b18"
- + "381de13bb49aaea66530c4a4b8271f3e"
- + "ae172cd366e07e6636f1019d2a28aed1"
- + "5e");
-
- byte[] input_1027_3 = Hex.decode(
- "bf6d42e701707b1d0206b0c8b45a1c72"
- + "641ff12889219a82bdea965b5e79a96b"
- + "0d0163ed9d578ec9ada20f2fbcf1ea3c"
- + "4089d83419ba81b0c60f3606da99");
-
- byte[] seed_1027_3 = Hex.decode(
- "ad997feef730d6ea7be60d0dc52e72ea"
- + "cbfdd275");
-
- byte[] output_1027_3 = Hex.decode(
- "0301f935e9c47abcb48acbbe09895d9f"
- + "5971af14839da4ff95417ee453d1fd77"
- + "319072bb7297e1b55d7561cd9d1bb24c"
- + "1a9a37c619864308242804879d86ebd0"
- + "01dce5183975e1506989b70e5a834341"
- + "54d5cbfd6a24787e60eb0c658d2ac193"
- + "302d1192c6e622d4a12ad4b53923bca2"
- + "46df31c6395e37702c6a78ae081fb9d0"
- + "65");
-
- byte[] input_1027_4 = Hex.decode(
- "fb2ef112f5e766eb94019297934794f7"
- + "be2f6fc1c58e");
-
- byte[] seed_1027_4 = Hex.decode(
- "136454df5730f73c807a7e40d8c1a312"
- + "ac5b9dd3");
-
- byte[] output_1027_4 = Hex.decode(
- "02d110ad30afb727beb691dd0cf17d0a"
- + "f1a1e7fa0cc040ec1a4ba26a42c59d0a"
- + "796a2e22c8f357ccc98b6519aceb682e"
- + "945e62cb734614a529407cd452bee3e4"
- + "4fece8423cc19e55548b8b994b849c7e"
- + "cde4933e76037e1d0ce44275b08710c6"
- + "8e430130b929730ed77e09b015642c55"
- + "93f04e4ffb9410798102a8e96ffdfe11"
- + "e4");
-
- byte[] input_1027_5 = Hex.decode(
- "28ccd447bb9e85166dabb9e5b7d1adad"
- + "c4b9d39f204e96d5e440ce9ad928bc1c"
- + "2284");
-
- byte[] seed_1027_5 = Hex.decode(
- "bca8057f824b2ea257f2861407eef63d"
- + "33208681");
-
- byte[] output_1027_5 = Hex.decode(
- "00dbb8a7439d90efd919a377c54fae8f"
- + "e11ec58c3b858362e23ad1b8a4431079"
- + "9066b99347aa525691d2adc58d9b06e3"
- + "4f288c170390c5f0e11c0aa3645959f1"
- + "8ee79e8f2be8d7ac5c23d061f18dd74b"
- + "8c5f2a58fcb5eb0c54f99f01a8324756"
- + "8292536583340948d7a8c97c4acd1e98"
- + "d1e29dc320e97a260532a8aa7a758a1e"
- + "c2");
-
- byte[] input_1027_6 = Hex.decode(
- "f22242751ec6b1");
-
- byte[] seed_1027_6 = Hex.decode(
- "2e7e1e17f647b5ddd033e15472f90f68"
- + "12f3ac4e");
-
- byte[] output_1027_6 = Hex.decode(
- "00a5ffa4768c8bbecaee2db77e8f2eec"
- + "99595933545520835e5ba7db9493d3e1"
- + "7cddefe6a5f567624471908db4e2d83a"
- + "0fbee60608fc84049503b2234a07dc83"
- + "b27b22847ad8920ff42f674ef79b7628"
- + "0b00233d2b51b8cb2703a9d42bfbc825"
- + "0c96ec32c051e57f1b4ba528db89c37e"
- + "4c54e27e6e64ac69635ae887d9541619"
- + "a9");
-
- private void oaepVecTest(
- int keySize,
- int no,
- RSAKeyParameters pubParam,
- RSAKeyParameters privParam,
- byte[] seed,
- byte[] input,
- byte[] output)
- throws Exception
- {
- encDec(keySize + " " + no, pubParam, privParam, seed, input, output);
- }
-
- public OAEPTest()
- {
- }
-
- public String getName()
- {
- return "OAEP";
- }
-
- public void performTest() throws Exception
- {
- baseOaepTest(1, pubKeyEnc1, privKeyEnc1, output1);
- baseOaepTest(2, pubKeyEnc2, privKeyEnc2, output2);
- baseOaepTest(3, pubKeyEnc3, privKeyEnc3, output3);
-
- RSAKeyParameters pubParam = new RSAKeyParameters(false, new BigInteger(1, modulus_1024), new BigInteger(1, pubExp_1024));
- RSAKeyParameters privParam = new RSAPrivateCrtKeyParameters(pubParam.getModulus(), pubParam.getExponent(), new BigInteger(1, privExp_1024), new BigInteger(1, prime1_1024), new BigInteger(1, prime2_1024), new BigInteger(1, primeExp1_1024), new BigInteger(1, primeExp2_1024), new BigInteger(1, crtCoef_1024));
-
- oaepVecTest(1024, 1, pubParam, privParam, seed_1024_1, input_1024_1, output_1024_1);
- oaepVecTest(1024, 2, pubParam, privParam, seed_1024_2, input_1024_2, output_1024_2);
- oaepVecTest(1024, 3, pubParam, privParam, seed_1024_3, input_1024_3, output_1024_3);
- oaepVecTest(1024, 4, pubParam, privParam, seed_1024_4, input_1024_4, output_1024_4);
- oaepVecTest(1024, 5, pubParam, privParam, seed_1024_5, input_1024_5, output_1024_5);
- oaepVecTest(1024, 6, pubParam, privParam, seed_1024_6, input_1024_6, output_1024_6);
-
- pubParam = new RSAKeyParameters(false, new BigInteger(1, modulus_1027), new BigInteger(1, pubExp_1027));
- privParam = new RSAPrivateCrtKeyParameters(pubParam.getModulus(), pubParam.getExponent(), new BigInteger(1, privExp_1027), new BigInteger(1, prime1_1027), new BigInteger(1, prime2_1027), new BigInteger(1, primeExp1_1027), new BigInteger(1, primeExp2_1027), new BigInteger(1, crtCoef_1027));
-
- oaepVecTest(1027, 1, pubParam, privParam, seed_1027_1, input_1027_1, output_1027_1);
- oaepVecTest(1027, 2, pubParam, privParam, seed_1027_2, input_1027_2, output_1027_2);
- oaepVecTest(1027, 3, pubParam, privParam, seed_1027_3, input_1027_3, output_1027_3);
- oaepVecTest(1027, 4, pubParam, privParam, seed_1027_4, input_1027_4, output_1027_4);
- oaepVecTest(1027, 5, pubParam, privParam, seed_1027_5, input_1027_5, output_1027_5);
- oaepVecTest(1027, 6, pubParam, privParam, seed_1027_6, input_1027_6, output_1027_6);
-
- //
- // OAEP - public encrypt, private decrypt differring hashes
- //
- AsymmetricBlockCipher cipher = new OAEPEncoding(new RSAEngine(), new SHA256Digest(), new SHA1Digest(), new byte[10]);
-
- cipher.init(true, new ParametersWithRandom(pubParam, new SecureRandom()));
-
- byte[] input = new byte[10];
-
- byte[] out = cipher.processBlock(input, 0, input.length);
-
- cipher.init(false, privParam);
-
- out = cipher.processBlock(out, 0, out.length);
-
- for (int i = 0; i != input.length; i++)
- {
- if (out[i] != input[i])
- {
- fail("mixed digest failed decoding");
- }
- }
-
- cipher = new OAEPEncoding(new RSAEngine(), new SHA1Digest(), new SHA256Digest(), new byte[10]);
-
- cipher.init(true, new ParametersWithRandom(pubParam, new SecureRandom()));
-
- out = cipher.processBlock(input, 0, input.length);
-
- cipher.init(false, privParam);
-
- out = cipher.processBlock(out, 0, out.length);
-
- for (int i = 0; i != input.length; i++)
- {
- if (out[i] != input[i])
- {
- fail("mixed digest failed decoding");
- }
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new OAEPTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/OCBTest.java b/core/src/test/java/org/bouncycastle/crypto/test/OCBTest.java
deleted file mode 100644
index 26d7d124..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/OCBTest.java
+++ /dev/null
@@ -1,520 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.engines.AESEngine;
-import org.bouncycastle.crypto.engines.DESEngine;
-import org.bouncycastle.crypto.modes.AEADBlockCipher;
-import org.bouncycastle.crypto.modes.OCBBlockCipher;
-import org.bouncycastle.crypto.params.AEADParameters;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Times;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * Test vectors from <a href="http://tools.ietf.org/html/rfc7253">RFC 7253 on The OCB
- * Authenticated-Encryption Algorithm</a>
- */
-public class OCBTest
- extends SimpleTest
-{
- private static final String KEY_128 = "000102030405060708090A0B0C0D0E0F";
- private static final String KEY_96 = "0F0E0D0C0B0A09080706050403020100";
-
- /*
- * Test vectors from Appendix A of the specification, containing the strings N, A, P, C in order
- */
-
- private static final String[][] TEST_VECTORS_128 = new String[][]{
- { "BBAA99887766554433221100",
- "",
- "",
- "785407BFFFC8AD9EDCC5520AC9111EE6" },
- { "BBAA99887766554433221101",
- "0001020304050607",
- "0001020304050607",
- "6820B3657B6F615A5725BDA0D3B4EB3A257C9AF1F8F03009" },
- { "BBAA99887766554433221102",
- "0001020304050607",
- "",
- "81017F8203F081277152FADE694A0A00" },
- { "BBAA99887766554433221103",
- "",
- "0001020304050607",
- "45DD69F8F5AAE72414054CD1F35D82760B2CD00D2F99BFA9" },
- { "BBAA99887766554433221104",
- "000102030405060708090A0B0C0D0E0F",
- "000102030405060708090A0B0C0D0E0F",
- "571D535B60B277188BE5147170A9A22C3AD7A4FF3835B8C5701C1CCEC8FC3358" },
- { "BBAA99887766554433221105",
- "000102030405060708090A0B0C0D0E0F",
- "",
- "8CF761B6902EF764462AD86498CA6B97" },
- { "BBAA99887766554433221106",
- "",
- "000102030405060708090A0B0C0D0E0F",
- "5CE88EC2E0692706A915C00AEB8B2396F40E1C743F52436BDF06D8FA1ECA343D" },
- { "BBAA99887766554433221107",
- "000102030405060708090A0B0C0D0E0F1011121314151617",
- "000102030405060708090A0B0C0D0E0F1011121314151617",
- "1CA2207308C87C010756104D8840CE1952F09673A448A122C92C62241051F57356D7F3C90BB0E07F" },
- { "BBAA99887766554433221108",
- "000102030405060708090A0B0C0D0E0F1011121314151617",
- "",
- "6DC225A071FC1B9F7C69F93B0F1E10DE" },
- { "BBAA99887766554433221109",
- "",
- "000102030405060708090A0B0C0D0E0F1011121314151617",
- "221BD0DE7FA6FE993ECCD769460A0AF2D6CDED0C395B1C3CE725F32494B9F914D85C0B1EB38357FF" },
- { "BBAA9988776655443322110A",
- "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
- "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
- "BD6F6C496201C69296C11EFD138A467ABD3C707924B964DEAFFC40319AF5A48540FBBA186C5553C68AD9F592A79A4240" },
- { "BBAA9988776655443322110B",
- "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
- "",
- "FE80690BEE8A485D11F32965BC9D2A32" },
- { "BBAA9988776655443322110C",
- "",
- "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
- "2942BFC773BDA23CABC6ACFD9BFD5835BD300F0973792EF46040C53F1432BCDFB5E1DDE3BC18A5F840B52E653444D5DF" },
- { "BBAA9988776655443322110D",
- "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
- "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
- "D5CA91748410C1751FF8A2F618255B68A0A12E093FF454606E59F9C1D0DDC54B65E8628E568BAD7AED07BA06A4A69483A7035490C5769E60" },
- { "BBAA9988776655443322110E",
- "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
- "",
- "C5CD9D1850C141E358649994EE701B68" },
- { "BBAA9988776655443322110F",
- "",
- "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
- "4412923493C57D5DE0D700F753CCE0D1D2D95060122E9F15A5DDBFC5787E50B5CC55EE507BCB084E479AD363AC366B95A98CA5F3000B1479" },
- };
-
- private static final String[][] TEST_VECTORS_96 = new String[][]{
- { "BBAA9988776655443322110D",
- "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
- "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
- "1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FDAC4F02AA" },
- };
-
- public String getName()
- {
- return "OCB";
- }
-
- public void performTest()
- throws Exception
- {
- byte[] K128 = Hex.decode(KEY_128);
- for (int i = 0; i < TEST_VECTORS_128.length; ++i)
- {
- runTestCase("Test Case " + i, TEST_VECTORS_128[i], 128, K128);
- }
-
- byte[] K96 = Hex.decode(KEY_96);
- for (int i = 0; i < TEST_VECTORS_96.length; ++i)
- {
- runTestCase("Test Case " + i, TEST_VECTORS_96[i], 96, K96);
- }
-
- runLongerTestCase(128, 128, "67E944D23256C5E0B6C61FA22FDF1EA2");
- runLongerTestCase(192, 128, "F673F2C3E7174AAE7BAE986CA9F29E17");
- runLongerTestCase(256, 128, "D90EB8E9C977C88B79DD793D7FFA161C");
- runLongerTestCase(128, 96, "77A3D8E73589158D25D01209");
- runLongerTestCase(192, 96, "05D56EAD2752C86BE6932C5E");
- runLongerTestCase(256, 96, "5458359AC23B0CBA9E6330DD");
- runLongerTestCase(128, 64, "192C9B7BD90BA06A");
- runLongerTestCase(192, 64, "0066BC6E0EF34E24");
- runLongerTestCase(256, 64, "7D4EA5D445501CBE");
-
- randomTests();
- outputSizeTests();
- testExceptions();
- }
-
- private void testExceptions() throws InvalidCipherTextException
- {
- AEADBlockCipher ocb = createOCBCipher();
-
- try
- {
- ocb = new OCBBlockCipher(new DESEngine(), new DESEngine());
-
- fail("incorrect block size not picked up");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- try
- {
- ocb.init(false, new KeyParameter(new byte[16]));
-
- fail("illegal argument not picked up");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- AEADTestUtil.testReset(this, createOCBCipher(), createOCBCipher(), new AEADParameters(new KeyParameter(new byte[16]), 128, new byte[15]));
- AEADTestUtil.testTampering(this, ocb, new AEADParameters(new KeyParameter(new byte[16]), 128, new byte[15]));
- AEADTestUtil.testOutputSizes(this, createOCBCipher(), new AEADParameters(new KeyParameter(new byte[16]), 128,
- new byte[15]));
- AEADTestUtil.testBufferSizeChecks(this, createOCBCipher(), new AEADParameters(new KeyParameter(new byte[16]),
- 128, new byte[15]));
- }
-
- private void runTestCase(String testName, String[] testVector, int macLengthBits, byte[] K)
- throws InvalidCipherTextException
- {
- int pos = 0;
- byte[] N = Hex.decode(testVector[pos++]);
- byte[] A = Hex.decode(testVector[pos++]);
- byte[] P = Hex.decode(testVector[pos++]);
- byte[] C = Hex.decode(testVector[pos++]);
-
- int macLengthBytes = macLengthBits / 8;
-
- KeyParameter keyParameter = new KeyParameter(K);
- AEADParameters parameters = new AEADParameters(keyParameter, macLengthBits, N, A);
-
- AEADBlockCipher encCipher = initOCBCipher(true, parameters);
- AEADBlockCipher decCipher = initOCBCipher(false, parameters);
-
- checkTestCase(encCipher, decCipher, testName, macLengthBytes, P, C);
- checkTestCase(encCipher, decCipher, testName + " (reused)", macLengthBytes, P, C);
-
- // Key reuse
- AEADParameters keyReuseParams = AEADTestUtil.reuseKey(parameters);
- encCipher.init(true, keyReuseParams);
- decCipher.init(false, keyReuseParams);
- checkTestCase(encCipher, decCipher, testName + " (key reuse)", macLengthBytes, P, C);
- }
-
- private BlockCipher createUnderlyingCipher()
- {
- return new AESEngine();
- }
-
- private AEADBlockCipher createOCBCipher()
- {
- return new OCBBlockCipher(createUnderlyingCipher(), createUnderlyingCipher());
- }
-
- private AEADBlockCipher initOCBCipher(boolean forEncryption, AEADParameters parameters)
- {
- AEADBlockCipher c = createOCBCipher();
- c.init(forEncryption, parameters);
- return c;
- }
-
- private void checkTestCase(AEADBlockCipher encCipher, AEADBlockCipher decCipher, String testName,
- int macLengthBytes, byte[] P, byte[] C)
- throws InvalidCipherTextException
- {
- byte[] tag = Arrays.copyOfRange(C, C.length - macLengthBytes, C.length);
-
- {
- byte[] enc = new byte[encCipher.getOutputSize(P.length)];
- int len = encCipher.processBytes(P, 0, P.length, enc, 0);
- len += encCipher.doFinal(enc, len);
-
- if (enc.length != len)
- {
- fail("encryption reported incorrect length: " + testName);
- }
-
- if (!areEqual(C, enc))
- {
- fail("incorrect encrypt in: " + testName);
- }
-
- if (!areEqual(tag, encCipher.getMac()))
- {
- fail("getMac() not the same as the appended tag: " + testName);
- }
- }
-
- {
- byte[] dec = new byte[decCipher.getOutputSize(C.length)];
- int len = decCipher.processBytes(C, 0, C.length, dec, 0);
- len += decCipher.doFinal(dec, len);
-
- if (dec.length != len)
- {
- fail("decryption reported incorrect length: " + testName);
- }
-
- if (!areEqual(P, dec))
- {
- fail("incorrect decrypt in: " + testName);
- }
-
- if (!areEqual(tag, decCipher.getMac()))
- {
- fail("getMac() not the same as the appended tag: " + testName);
- }
- }
- }
-
- private void runLongerTestCase(int keyLen, int tagLen, String expectedOutputHex)
- throws InvalidCipherTextException
- {
- byte[] expectedOutput = Hex.decode(expectedOutputHex);
- byte[] keyBytes = new byte[keyLen / 8];
- keyBytes[keyBytes.length - 1] = (byte)tagLen;
- KeyParameter key = new KeyParameter(keyBytes);
-
- AEADBlockCipher c1 = initOCBCipher(true, new AEADParameters(key, tagLen, createNonce(385)));
- AEADBlockCipher c2 = createOCBCipher();
-
- long total = 0;
-
- byte[] S = new byte[128];
-
- int n = 0;
- for (int i = 0; i < 128; ++i)
- {
- c2.init(true, new AEADParameters(key, tagLen, createNonce(++n)));
- total += updateCiphers(c1, c2, S, i, true, true);
- c2.init(true, new AEADParameters(key, tagLen, createNonce(++n)));
- total += updateCiphers(c1, c2, S, i, false, true);
- c2.init(true, new AEADParameters(key, tagLen, createNonce(++n)));
- total += updateCiphers(c1, c2, S, i, true, false);
- }
-
- long expectedTotal = 16256 + (48 * tagLen);
-
- if (total != expectedTotal)
- {
- fail("test generated the wrong amount of input: " + total);
- }
-
- byte[] output = new byte[c1.getOutputSize(0)];
- c1.doFinal(output, 0);
-
- if (!areEqual(expectedOutput, output))
- {
- fail("incorrect encrypt in long-form test");
- }
- }
-
- private byte[] createNonce(int n)
- {
- return new byte[]{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte)(n >>> 8), (byte)n };
- }
-
- private int updateCiphers(AEADBlockCipher c1, AEADBlockCipher c2, byte[] S, int i,
- boolean includeAAD, boolean includePlaintext)
- throws InvalidCipherTextException
- {
- int inputLen = includePlaintext ? i : 0;
- int outputLen = c2.getOutputSize(inputLen);
-
- byte[] output = new byte[outputLen];
-
- int len = 0;
-
- if (includeAAD)
- {
- c2.processAADBytes(S, 0, i);
- }
-
- if (includePlaintext)
- {
- len += c2.processBytes(S, 0, i, output, len);
- }
-
- len += c2.doFinal(output, len);
-
- c1.processAADBytes(output, 0, len);
-
- return len;
- }
-
- private void randomTests()
- throws InvalidCipherTextException
- {
- SecureRandom srng = new SecureRandom();
- srng.setSeed(Times.nanoTime());
- for (int i = 0; i < 10; ++i)
- {
- randomTest(srng);
- }
- }
-
- private void randomTest(SecureRandom srng)
- throws InvalidCipherTextException
- {
- int kLength = 16 + 8 * (Math.abs(srng.nextInt()) % 3);
- byte[] K = new byte[kLength];
- srng.nextBytes(K);
-
- int pLength = srng.nextInt() >>> 16;
- byte[] P = new byte[pLength];
- srng.nextBytes(P);
-
- int aLength = srng.nextInt() >>> 24;
- byte[] A = new byte[aLength];
- srng.nextBytes(A);
-
- int saLength = srng.nextInt() >>> 24;
- byte[] SA = new byte[saLength];
- srng.nextBytes(SA);
-
- int ivLength = 1 + nextInt(srng, 15);
- byte[] IV = new byte[ivLength];
- srng.nextBytes(IV);
-
- AEADParameters parameters = new AEADParameters(new KeyParameter(K), 16 * 8, IV, A);
- AEADBlockCipher cipher = initOCBCipher(true, parameters);
- byte[] C = new byte[cipher.getOutputSize(P.length)];
- int predicted = cipher.getUpdateOutputSize(P.length);
-
- int split = nextInt(srng, SA.length + 1);
- cipher.processAADBytes(SA, 0, split);
- int len = cipher.processBytes(P, 0, P.length, C, 0);
- cipher.processAADBytes(SA, split, SA.length - split);
-
- if (predicted != len)
- {
- fail("encryption reported incorrect update length in randomised test");
- }
-
- len += cipher.doFinal(C, len);
-
- if (C.length != len)
- {
- fail("encryption reported incorrect length in randomised test");
- }
-
- byte[] encT = cipher.getMac();
- byte[] tail = new byte[C.length - P.length];
- System.arraycopy(C, P.length, tail, 0, tail.length);
-
- if (!areEqual(encT, tail))
- {
- fail("stream contained wrong mac in randomised test");
- }
-
- cipher.init(false, parameters);
- byte[] decP = new byte[cipher.getOutputSize(C.length)];
- predicted = cipher.getUpdateOutputSize(C.length);
-
- split = nextInt(srng, SA.length + 1);
- cipher.processAADBytes(SA, 0, split);
- len = cipher.processBytes(C, 0, C.length, decP, 0);
- cipher.processAADBytes(SA, split, SA.length - split);
-
- if (predicted != len)
- {
- fail("decryption reported incorrect update length in randomised test");
- }
-
- len += cipher.doFinal(decP, len);
-
- if (!areEqual(P, decP))
- {
- fail("incorrect decrypt in randomised test");
- }
-
- byte[] decT = cipher.getMac();
- if (!areEqual(encT, decT))
- {
- fail("decryption produced different mac from encryption");
- }
-
- //
- // key reuse test
- //
- cipher.init(false, AEADTestUtil.reuseKey(parameters));
- decP = new byte[cipher.getOutputSize(C.length)];
-
- split = nextInt(srng, SA.length + 1);
- cipher.processAADBytes(SA, 0, split);
- len = cipher.processBytes(C, 0, C.length, decP, 0);
- cipher.processAADBytes(SA, split, SA.length - split);
-
- len += cipher.doFinal(decP, len);
-
- if (!areEqual(P, decP))
- {
- fail("incorrect decrypt in randomised test");
- }
-
- decT = cipher.getMac();
- if (!areEqual(encT, decT))
- {
- fail("decryption produced different mac from encryption");
- }
- }
-
- private void outputSizeTests()
- {
- byte[] K = new byte[16];
- byte[] A = null;
- byte[] IV = new byte[15];
-
- AEADParameters parameters = new AEADParameters(new KeyParameter(K), 16 * 8, IV, A);
- AEADBlockCipher cipher = initOCBCipher(true, parameters);
-
- if (cipher.getUpdateOutputSize(0) != 0)
- {
- fail("incorrect getUpdateOutputSize for initial 0 bytes encryption");
- }
-
- if (cipher.getOutputSize(0) != 16)
- {
- fail("incorrect getOutputSize for initial 0 bytes encryption");
- }
-
- cipher.init(false, parameters);
-
- if (cipher.getUpdateOutputSize(0) != 0)
- {
- fail("incorrect getUpdateOutputSize for initial 0 bytes decryption");
- }
-
- // NOTE: 0 bytes would be truncated data, but we want it to fail in the doFinal, not here
- if (cipher.getOutputSize(0) != 0)
- {
- fail("fragile getOutputSize for initial 0 bytes decryption");
- }
-
- if (cipher.getOutputSize(16) != 0)
- {
- fail("incorrect getOutputSize for initial MAC-size bytes decryption");
- }
- }
-
- private static int nextInt(SecureRandom rand, int n)
- {
- if ((n & -n) == n) // i.e., n is a power of 2
- {
- return (int)((n * (long)(rand.nextInt() >>> 1)) >> 31);
- }
-
- int bits, value;
- do
- {
- bits = rand.nextInt() >>> 1;
- value = bits % n;
- }
- while (bits - value + (n - 1) < 0);
-
- return value;
- }
-
- public static void main(String[] args)
- {
- runTest(new OCBTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/PKCS12Test.java b/core/src/test/java/org/bouncycastle/crypto/test/PKCS12Test.java
deleted file mode 100644
index c5c7aa34..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/PKCS12Test.java
+++ /dev/null
@@ -1,206 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.PBEParametersGenerator;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.generators.PKCS12ParametersGenerator;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-/**
- * test for PKCS12 key generation - vectors from
- * <a href=http://www.drh-consultancy.demon.co.uk/test.txt>
- * http://www.drh-consultancy.demon.co.uk/test.txt</a>
- */
-public class PKCS12Test
- implements Test
-{
- char[] password1 = { 's', 'm', 'e', 'g' };
- char[] password2 = { 'q', 'u', 'e', 'e', 'g' };
-
- private boolean isEqual(
- byte[] a,
- byte[] b)
- {
- if (a.length != b.length)
- {
- return false;
- }
-
- for (int i = 0; i != a.length; i++)
- {
- if (a[i] != b[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- private TestResult run1(
- int id,
- char[] password,
- byte[] salt,
- int iCount,
- byte[] result)
- {
- PBEParametersGenerator generator = new PKCS12ParametersGenerator(
- new SHA1Digest());
-
- generator.init(
- PBEParametersGenerator.PKCS12PasswordToBytes(password),
- salt,
- iCount);
-
- CipherParameters key = generator.generateDerivedParameters(24 * 8);
-
- if (isEqual(result, ((KeyParameter)key).getKey()))
- {
- return new SimpleTestResult(true, "PKCS12Test: Okay");
- }
- else
- {
- return new SimpleTestResult(false, "PKCS12Test: id "
- + id + " Failed");
- }
- }
-
- private TestResult run2(
- int id,
- char[] password,
- byte[] salt,
- int iCount,
- byte[] result)
- {
- PBEParametersGenerator generator = new PKCS12ParametersGenerator(
- new SHA1Digest());
-
- generator.init(
- PBEParametersGenerator.PKCS12PasswordToBytes(password),
- salt,
- iCount);
-
- ParametersWithIV params = (ParametersWithIV)generator.generateDerivedParameters(64, 64);
-
- if (isEqual(result, params.getIV()))
- {
- return new SimpleTestResult(true, "PKCS12Test: Okay");
- }
- else
- {
- return new SimpleTestResult(false, "PKCS12Test: id "
- + id + " Failed");
- }
- }
-
- private TestResult run3(
- int id,
- char[] password,
- byte[] salt,
- int iCount,
- byte[] result)
- {
- PBEParametersGenerator generator = new PKCS12ParametersGenerator(
- new SHA1Digest());
-
- generator.init(
- PBEParametersGenerator.PKCS12PasswordToBytes(password),
- salt,
- iCount);
-
- CipherParameters key = generator.generateDerivedMacParameters(160);
-
- if (isEqual(result, ((KeyParameter)key).getKey()))
- {
- return new SimpleTestResult(true, "PKCS12Test: Okay");
- }
- else
- {
- return new SimpleTestResult(false, "PKCS12Test: id "
- + id + " Failed");
- }
- }
-
- public String getName()
- {
- return "PKCS12Test";
- }
-
- public TestResult perform()
- {
- TestResult result;
-
- result = run1(1, password1, Hex.decode("0A58CF64530D823F"), 1,
- Hex.decode("8AAAE6297B6CB04642AB5B077851284EB7128F1A2A7FBCA3"));
-
- if (result.isSuccessful())
- {
- result = run2(2, password1, Hex.decode("0A58CF64530D823F"), 1,
- Hex.decode("79993DFE048D3B76"));
- }
-
- if (result.isSuccessful())
- {
- result = run1(3, password1, Hex.decode("642B99AB44FB4B1F"), 1,
- Hex.decode("F3A95FEC48D7711E985CFE67908C5AB79FA3D7C5CAA5D966"));
- }
-
- if (result.isSuccessful())
- {
- result = run2(4, password1, Hex.decode("642B99AB44FB4B1F"), 1,
- Hex.decode("C0A38D64A79BEA1D"));
- }
-
- if (result.isSuccessful())
- {
- result = run3(5, password1, Hex.decode("3D83C0E4546AC140"), 1,
- Hex.decode("8D967D88F6CAA9D714800AB3D48051D63F73A312"));
- }
-
- if (result.isSuccessful())
- {
- result = run1(6, password2, Hex.decode("05DEC959ACFF72F7"), 1000,
- Hex.decode("ED2034E36328830FF09DF1E1A07DD357185DAC0D4F9EB3D4"));
- }
-
- if (result.isSuccessful())
- {
- result = run2(7, password2, Hex.decode("05DEC959ACFF72F7"), 1000,
- Hex.decode("11DEDAD7758D4860"));
- }
-
- if (result.isSuccessful())
- {
- result = run1(8, password2, Hex.decode("1682C0FC5B3F7EC5"), 1000,
- Hex.decode("483DD6E919D7DE2E8E648BA8F862F3FBFBDC2BCB2C02957F"));
- }
-
- if (result.isSuccessful())
- {
- result = run2(9, password2, Hex.decode("1682C0FC5B3F7EC5"), 1000,
- Hex.decode("9D461D1B00355C50"));
- }
-
- if (result.isSuccessful())
- {
- result = run3(10, password2, Hex.decode("263216FCC2FAB31C"), 1000,
- Hex.decode("5EC4C7A80DF652294C3925B6489A7AB857C83476"));
- }
-
- return result;
- }
-
- public static void main(
- String[] args)
- {
- PKCS12Test test = new PKCS12Test();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/PKCS5Test.java b/core/src/test/java/org/bouncycastle/crypto/test/PKCS5Test.java
deleted file mode 100644
index 6145114e..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/PKCS5Test.java
+++ /dev/null
@@ -1,265 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.io.ByteArrayInputStream;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo;
-import org.bouncycastle.asn1.pkcs.EncryptionScheme;
-import org.bouncycastle.asn1.pkcs.KeyDerivationFunc;
-import org.bouncycastle.asn1.pkcs.PBES2Parameters;
-import org.bouncycastle.asn1.pkcs.PBKDF2Params;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.asn1.pkcs.RC2CBCParameter;
-import org.bouncycastle.crypto.BufferedBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.PBEParametersGenerator;
-import org.bouncycastle.crypto.engines.DESEngine;
-import org.bouncycastle.crypto.engines.DESedeEngine;
-import org.bouncycastle.crypto.engines.RC2Engine;
-import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
-import org.bouncycastle.crypto.modes.CBCBlockCipher;
-import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * A test class for PKCS5 PBES2 with PBKDF2 (PKCS5 v2.0) using
- * test vectors provider at
- * <a href=http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html>
- * RSA's PKCS5 Page</a>
- * <br>
- * The vectors are Base 64 encoded and encrypted using the password "password"
- * (without quotes). They should all yield the same PrivateKeyInfo object.
- */
-public class PKCS5Test
- extends SimpleTest
-{
- /**
- * encrypted using des-cbc.
- */
- static byte[] sample1 = Base64.decode(
- "MIIBozA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQIfWBDXwLp4K4CAggA"
- + "MBEGBSsOAwIHBAiaCF/AvOgQ6QSCAWDWX4BdAzCRNSQSANSuNsT5X8mWYO27mr3Y"
- + "9c9LoBVXGNmYWKA77MI4967f7SmjNcgXj3xNE/jmnVz6hhsjS8E5VPT3kfyVkpdZ"
- + "0lr5e9Yk2m3JWpPU7++v5zBkZmC4V/MwV/XuIs6U+vykgzMgpxQg0oZKS9zgmiZo"
- + "f/4dOCL0UtCDnyOSvqT7mCVIcMDIEKu8QbVlgZYBop08l60EuEU3gARUo8WsYQmO"
- + "Dz/ldx0Z+znIT0SXVuOwc+RVItC5T/Qx+aijmmpt+9l14nmaGBrEkmuhmtdvU/4v"
- + "aptewGRgmjOfD6cqK+zs0O5NrrJ3P/6ZSxXj91CQgrThGfOv72bUncXEMNtc8pks"
- + "2jpHFjGMdKufnadAD7XuMgzkkaklEXZ4f5tU6heIIwr51g0GBEGF96gYPFnjnSQM"
- + "75JE02Clo+DfcfXpcybPTwwFg2jd6JTTOfkdf6OdSlA/1XNK43FA");
-
- /**
- * encrypted using des-ede3-cbc.
- */
- static byte[] sample2 = Base64.decode(
- "MIIBpjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIeFeOWl1jywYCAggA"
- + "MBQGCCqGSIb3DQMHBAjUJ5eGBhQGtQSCAWBrHrRgqO8UUMLcWzZEtpk1l3mjxiF/"
- + "koCMkHsFwowgyWhEbgIkTgbSViK54LVK8PskekcGNLph+rB6bGZ7pPbL5pbXASJ8"
- + "+MkQcG3FZdlS4Ek9tTJDApj3O1UubZGFG4uvTlJJFbF1BOJ3MkY3XQ9Gl1qwv7j5"
- + "6e103Da7Cq9+oIDKmznza78XXQYrUsPo8mJGjUxPskEYlzwvHjKubRnYm/K6RKhi"
- + "5f4zX4BQ/Dt3H812ZjRXrsjAJP0KrD/jyD/jCT7zNBVPH1izBds+RwizyQAHwfNJ"
- + "BFR78TH4cgzB619X47FDVOnT0LqQNVd0O3cSwnPrXE9XR3tPayE+iOB15llFSmi8"
- + "z0ByOXldEpkezCn92Umk++suzIVj1qfsK+bv2phZWJPbLEIWPDRHUbYf76q5ArAr"
- + "u4xtxT/hoK3krEs/IN3d70qjlUJ36SEw1UaZ82PWhakQbdtu39ZraMJB");
-
- /**
- * encrypted using rc2-cbc.
- */
- static byte[] sample3 = Base64.decode(
- "MIIBrjBIBgkqhkiG9w0BBQ0wOzAeBgkqhkiG9w0BBQwwEQQIrHyQPBZqWLUCAggA"
- + "AgEQMBkGCCqGSIb3DQMCMA0CAToECEhbh7YZKiPSBIIBYCT1zp6o5jpFlIkgwPop"
- + "7bW1+8ACr4exqzkeb3WflQ8cWJ4cURxzVdvxUnXeW1VJdaQZtjS/QHs5GhPTG/0f"
- + "wtvnaPfwrIJ3FeGaZfcg2CrYhalOFmEb4xrE4KyoEQmUN8tb/Cg94uzd16BOPw21"
- + "RDnE8bnPdIGY7TyL95kbkqH23mK53pi7h+xWIgduW+atIqDyyt55f7WMZcvDvlj6"
- + "VpN/V0h+qxBHL274WA4dj6GYgeyUFpi60HdGCK7By2TBy8h1ZvKGjmB9h8jZvkx1"
- + "MkbRumXxyFsowTZawyYvO8Um6lbfEDP9zIEUq0IV8RqH2MRyblsPNSikyYhxX/cz"
- + "tdDxRKhilySbSBg5Kr8OfcwKp9bpinN96nmG4xr3Tch1bnVvqJzOQ5+Vva2WwVvH"
- + "2JkWvYm5WaANg4Q6bRxu9vz7DuhbJjQdZbxFezIAgrJdSe92B00jO/0Kny1WjiVO"
- + "6DA=");
-
- static byte[] result = Hex.decode(
- "30820155020100300d06092a864886f70d01010105000482013f3082013b020100024100"
- + "debbfc2c09d61bada2a9462f24224e54cc6b3cc0755f15ce318ef57e79df17026b6a85cc"
- + "a12428027245045df2052a329a2f9ad3d17b78a10572ad9b22bf343b020301000102402d"
- + "90a96adcec472743527bc023153d8f0d6e96b40c8ed228276d467d843306429f8670559b"
- + "f376dd41857f6397c2fc8d95e0e53ed62de420b855430ee4a1b8a1022100ffcaf0838239"
- + "31e073ff534f06a5d415b3d414bc614a4544a3dff7ed271817eb022100deea30242117db"
- + "2d3b8837f58f1da530ff83cf9283680da33683ec4e583610f1022100e6026381adb0a683"
- + "f16a8f4c096b462979b9e4277cc89f3ed8a905b46fa9ff9f02210097c146d4d1d2b3dbaf"
- + "53a504ff51674c5c271800de84d003f4f10ac6ab36e38102202bfa141f10bda874e1017d"
- + "845e82767c1c38e82745daf421f0c8cd09d7652387");
-
- private class PBETest
- extends SimpleTest
- {
- int id;
- BufferedBlockCipher cipher;
- byte[] sample;
- int keySize;
-
- PBETest(
- int id,
- BufferedBlockCipher cipher,
- byte[] sample,
- int keySize)
- {
- this.id = id;
- this.cipher = cipher;
- this.sample = sample;
- this.keySize = keySize;
- }
-
- public String getName()
- {
- return cipher.getUnderlyingCipher().getAlgorithmName() + " PKCS5S2 Test " + id;
- }
-
- public void performTest()
- {
- char[] password = { 'p', 'a', 's', 's', 'w', 'o', 'r', 'd' };
- PBEParametersGenerator generator = new PKCS5S2ParametersGenerator();
- ByteArrayInputStream bIn = new ByteArrayInputStream(sample);
- ASN1InputStream dIn = new ASN1InputStream(bIn);
- EncryptedPrivateKeyInfo info = null;
-
- try
- {
- info = EncryptedPrivateKeyInfo.getInstance(dIn.readObject());
- }
- catch (Exception e)
- {
- fail("failed construction - exception " + e.toString(), e);
- }
-
- PBES2Parameters alg = PBES2Parameters.getInstance(info.getEncryptionAlgorithm().getParameters());
- PBKDF2Params func = PBKDF2Params.getInstance(alg.getKeyDerivationFunc().getParameters());
- EncryptionScheme scheme = alg.getEncryptionScheme();
-
- if (func.getKeyLength() != null)
- {
- keySize = func.getKeyLength().intValue() * 8;
- }
-
- int iterationCount = func.getIterationCount().intValue();
- byte[] salt = func.getSalt();
-
- generator.init(
- PBEParametersGenerator.PKCS5PasswordToBytes(password),
- salt,
- iterationCount);
-
- CipherParameters param;
-
- if (scheme.getAlgorithm().equals(PKCSObjectIdentifiers.RC2_CBC))
- {
- RC2CBCParameter rc2Params = RC2CBCParameter.getInstance(scheme.getParameters());
- byte[] iv = rc2Params.getIV();
-
- param = new ParametersWithIV(generator.generateDerivedParameters(keySize), iv);
- }
- else
- {
- byte[] iv = ASN1OctetString.getInstance(scheme.getParameters()).getOctets();
-
- param = new ParametersWithIV(generator.generateDerivedParameters(keySize), iv);
- }
-
- cipher.init(false, param);
-
- byte[] data = info.getEncryptedData();
- byte[] out = new byte[cipher.getOutputSize(data.length)];
- int len = cipher.processBytes(data, 0, data.length, out, 0);
-
- try
- {
- len += cipher.doFinal(out, len);
- }
- catch (Exception e)
- {
- fail("failed doFinal - exception " + e.toString());
- }
-
- if (result.length != len)
- {
- fail("failed length");
- }
-
- for (int i = 0; i != len; i++)
- {
- if (out[i] != result[i])
- {
- fail("failed comparison");
- }
- }
- }
- }
-
- public String getName()
- {
- return "PKCS5S2";
- }
-
- public void performTest()
- throws Exception
- {
- BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new DESEngine()));
- SimpleTest test = new PBETest(0, cipher, sample1, 64);
-
- test.performTest();
-
- cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new DESedeEngine()));
- test = new PBETest(1, cipher, sample2, 192);
-
- test.performTest();
-
- cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new RC2Engine()));
- test = new PBETest(2, cipher, sample3, 0);
- test.performTest();
-
- //
- // RFC 3211 tests
- //
- char[] password = { 'p', 'a', 's', 's', 'w', 'o', 'r', 'd' };
- PBEParametersGenerator generator = new PKCS5S2ParametersGenerator();
-
- byte[] salt = Hex.decode("1234567878563412");
-
- generator.init(
- PBEParametersGenerator.PKCS5PasswordToBytes(password),
- salt,
- 5);
-
- if (!areEqual(((KeyParameter)generator.generateDerivedParameters(64)).getKey(), Hex.decode("d1daa78615f287e6")))
- {
- fail("64 test failed");
- }
-
- password = "All n-entities must communicate with other n-entities via n-1 entiteeheehees".toCharArray();
-
- generator.init(
- PBEParametersGenerator.PKCS5PasswordToBytes(password),
- salt,
- 500);
-
- if (!areEqual(((KeyParameter)generator.generateDerivedParameters(192)).getKey(), Hex.decode("6a8970bf68c92caea84a8df28510858607126380cc47ab2d")))
- {
- fail("192 test failed");
- }
-
- generator.init(PBEParametersGenerator.PKCS5PasswordToBytes(password), salt, 60000);
- if (!areEqual(((KeyParameter)generator.generateDerivedParameters(192)).getKey(), Hex.decode("29aaef810c12ecd2236bbcfb55407f9852b5573dc1c095bb")))
- {
- fail("192 (60000) test failed");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new PKCS5Test());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/PSSBlindTest.java b/core/src/test/java/org/bouncycastle/crypto/test/PSSBlindTest.java
deleted file mode 100644
index 5e391ae2..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/PSSBlindTest.java
+++ /dev/null
@@ -1,398 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.engines.RSABlindingEngine;
-import org.bouncycastle.crypto.engines.RSAEngine;
-import org.bouncycastle.crypto.generators.RSABlindingFactorGenerator;
-import org.bouncycastle.crypto.generators.RSAKeyPairGenerator;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.params.RSABlindingParameters;
-import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
-import org.bouncycastle.crypto.signers.PSSSigner;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-/*
- * RSA PSS test vectors for PKCS#1 V2.1 with blinding
- */
-public class PSSBlindTest
- extends SimpleTest
-{
- private final int DATA_LENGTH = 1000;
- private final int NUM_TESTS = 50;
- private final int NUM_TESTS_WITH_KEY_GENERATION = 10;
-
- private class FixedRandom
- extends SecureRandom
- {
- byte[] vals;
-
- FixedRandom(
- byte[] vals)
- {
- this.vals = vals;
- }
-
- public void nextBytes(
- byte[] bytes)
- {
- System.arraycopy(vals, 0, bytes, 0, vals.length);
- }
- }
-
- //
- // Example 1: A 1024-bit RSA keypair
- //
- private RSAKeyParameters pub1 = new RSAKeyParameters(false,
- new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",16),
- new BigInteger("010001",16));
-
- private RSAKeyParameters prv1 = new RSAPrivateCrtKeyParameters(
- new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",16),
- new BigInteger("010001",16),
- new BigInteger("33a5042a90b27d4f5451ca9bbbd0b44771a101af884340aef9885f2a4bbe92e894a724ac3c568c8f97853ad07c0266c8c6a3ca0929f1e8f11231884429fc4d9ae55fee896a10ce707c3ed7e734e44727a39574501a532683109c2abacaba283c31b4bd2f53c3ee37e352cee34f9e503bd80c0622ad79c6dcee883547c6a3b325",16),
- new BigInteger("e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443",16),
- new BigInteger("b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd",16),
- new BigInteger("28fa13938655be1f8a159cbaca5a72ea190c30089e19cd274a556f36c4f6e19f554b34c077790427bbdd8dd3ede2448328f385d81b30e8e43b2fffa027861979",16),
- new BigInteger("1a8b38f398fa712049898d7fb79ee0a77668791299cdfa09efc0e507acb21ed74301ef5bfd48be455eaeb6e1678255827580a8e4e8e14151d1510a82a3f2e729",16),
- new BigInteger("27156aba4126d24a81f3a528cbfb27f56886f840a9f6e86e17a44b94fe9319584b8e22fdde1e5a2e3bd8aa5ba8d8584194eb2190acf832b847f13a3d24a79f4d",16));
-
- // PSSExample1.1
-
- private byte[] msg1a = Hex.decode("cdc87da223d786df3b45e0bbbc721326d1ee2af806cc315475cc6f0d9c66e1b62371d45ce2392e1ac92844c310102f156a0d8d52c1f4c40ba3aa65095786cb769757a6563ba958fed0bcc984e8b517a3d5f515b23b8a41e74aa867693f90dfb061a6e86dfaaee64472c00e5f20945729cbebe77f06ce78e08f4098fba41f9d6193c0317e8b60d4b6084acb42d29e3808a3bc372d85e331170fcbf7cc72d0b71c296648b3a4d10f416295d0807aa625cab2744fd9ea8fd223c42537029828bd16be02546f130fd2e33b936d2676e08aed1b73318b750a0167d0");
-
- private byte[] slt1a = Hex.decode("dee959c7e06411361420ff80185ed57f3e6776af");
-
- private byte[] sig1a = Hex.decode("9074308fb598e9701b2294388e52f971faac2b60a5145af185df5287b5ed2887e57ce7fd44dc8634e407c8e0e4360bc226f3ec227f9d9e54638e8d31f5051215df6ebb9c2f9579aa77598a38f914b5b9c1bd83c4e2f9f382a0d0aa3542ffee65984a601bc69eb28deb27dca12c82c2d4c3f66cd500f1ff2b994d8a4e30cbb33c");
-
- // PSSExample1.2
-
- private byte[] msg1b = Hex.decode("851384cdfe819c22ed6c4ccb30daeb5cf059bc8e1166b7e3530c4c233e2b5f8f71a1cca582d43ecc72b1bca16dfc7013226b9e");
-
- private byte[] slt1b = Hex.decode("ef2869fa40c346cb183dab3d7bffc98fd56df42d");
-
- private byte[] sig1b = Hex.decode("3ef7f46e831bf92b32274142a585ffcefbdca7b32ae90d10fb0f0c729984f04ef29a9df0780775ce43739b97838390db0a5505e63de927028d9d29b219ca2c4517832558a55d694a6d25b9dab66003c4cccd907802193be5170d26147d37b93590241be51c25055f47ef62752cfbe21418fafe98c22c4d4d47724fdb5669e843");
-
- //
- // Example 2: A 1025-bit RSA keypair
- //
-
- private RSAKeyParameters pub2 = new RSAKeyParameters(false,
- new BigInteger("01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9", 16),
- new BigInteger("010001", 16));
-
- private RSAKeyParameters prv2 = new RSAPrivateCrtKeyParameters(
- new BigInteger("01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9", 16),
- new BigInteger("010001", 16),
- new BigInteger("027d147e4673057377fd1ea201565772176a7dc38358d376045685a2e787c23c15576bc16b9f444402d6bfc5d98a3e88ea13ef67c353eca0c0ddba9255bd7b8bb50a644afdfd1dd51695b252d22e7318d1b6687a1c10ff75545f3db0fe602d5f2b7f294e3601eab7b9d1cecd767f64692e3e536ca2846cb0c2dd486a39fa75b1", 16),
- new BigInteger("016601e926a0f8c9e26ecab769ea65a5e7c52cc9e080ef519457c644da6891c5a104d3ea7955929a22e7c68a7af9fcad777c3ccc2b9e3d3650bce404399b7e59d1", 16),
- new BigInteger("014eafa1d4d0184da7e31f877d1281ddda625664869e8379e67ad3b75eae74a580e9827abd6eb7a002cb5411f5266797768fb8e95ae40e3e8a01f35ff89e56c079", 16),
- new BigInteger("e247cce504939b8f0a36090de200938755e2444b29539a7da7a902f6056835c0db7b52559497cfe2c61a8086d0213c472c78851800b171f6401de2e9c2756f31", 16),
- new BigInteger("b12fba757855e586e46f64c38a70c68b3f548d93d787b399999d4c8f0bbd2581c21e19ed0018a6d5d3df86424b3abcad40199d31495b61309f27c1bf55d487c1", 16),
- new BigInteger("564b1e1fa003bda91e89090425aac05b91da9ee25061e7628d5f51304a84992fdc33762bd378a59f030a334d532bd0dae8f298ea9ed844636ad5fb8cbdc03cad", 16));
-
- // PSS Example 2.1
-
- private byte[] msg2a = Hex.decode("daba032066263faedb659848115278a52c44faa3a76f37515ed336321072c40a9d9b53bc05014078adf520875146aae70ff060226dcb7b1f1fc27e9360");
- private byte[] slt2a = Hex.decode("57bf160bcb02bb1dc7280cf0458530b7d2832ff7");
- private byte[] sig2a = Hex.decode("014c5ba5338328ccc6e7a90bf1c0ab3fd606ff4796d3c12e4b639ed9136a5fec6c16d8884bdd99cfdc521456b0742b736868cf90de099adb8d5ffd1deff39ba4007ab746cefdb22d7df0e225f54627dc65466131721b90af445363a8358b9f607642f78fab0ab0f43b7168d64bae70d8827848d8ef1e421c5754ddf42c2589b5b3");
-
- // PSS Example 2.2
-
- private byte[] msg2b = Hex.decode("e4f8601a8a6da1be34447c0959c058570c3668cfd51dd5f9ccd6ad4411fe8213486d78a6c49f93efc2ca2288cebc2b9b60bd04b1e220d86e3d4848d709d032d1e8c6a070c6af9a499fcf95354b14ba6127c739de1bb0fd16431e46938aec0cf8ad9eb72e832a7035de9b7807bdc0ed8b68eb0f5ac2216be40ce920c0db0eddd3860ed788efaccaca502d8f2bd6d1a7c1f41ff46f1681c8f1f818e9c4f6d91a0c7803ccc63d76a6544d843e084e363b8acc55aa531733edb5dee5b5196e9f03e8b731b3776428d9e457fe3fbcb3db7274442d785890e9cb0854b6444dace791d7273de1889719338a77fe");
- private byte[] slt2b = Hex.decode("7f6dd359e604e60870e898e47b19bf2e5a7b2a90");
- private byte[] sig2b = Hex.decode("010991656cca182b7f29d2dbc007e7ae0fec158eb6759cb9c45c5ff87c7635dd46d150882f4de1e9ae65e7f7d9018f6836954a47c0a81a8a6b6f83f2944d6081b1aa7c759b254b2c34b691da67cc0226e20b2f18b42212761dcd4b908a62b371b5918c5742af4b537e296917674fb914194761621cc19a41f6fb953fbcbb649dea");
-
- //
- // Example 4: A 1027-bit RSA key pair
- //
-
- private RSAKeyParameters pub4 = new RSAKeyParameters(false,
- new BigInteger("054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705", 16),
- new BigInteger("010001", 16));
-
- private RSAKeyParameters prv4 = new RSAPrivateCrtKeyParameters(
- new BigInteger("054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705", 16),
- new BigInteger("010001", 16),
- new BigInteger("fa041f8cd9697ceed38ec8caa275523b4dd72b09a301d3541d72f5d31c05cbce2d6983b36183af10690bd46c46131e35789431a556771dd0049b57461bf060c1f68472e8a67c25f357e5b6b4738fa541a730346b4a07649a2dfa806a69c975b6aba64678acc7f5913e89c622f2d8abb1e3e32554e39df94ba60c002e387d9011", 16),
- new BigInteger("029232336d2838945dba9dd7723f4e624a05f7375b927a87abe6a893a1658fd49f47f6c7b0fa596c65fa68a23f0ab432962d18d4343bd6fd671a5ea8d148413995", 16),
- new BigInteger("020ef5efe7c5394aed2272f7e81a74f4c02d145894cb1b3cab23a9a0710a2afc7e3329acbb743d01f680c4d02afb4c8fde7e20930811bb2b995788b5e872c20bb1", 16),
- new BigInteger("026e7e28010ecf2412d9523ad704647fb4fe9b66b1a681581b0e15553a89b1542828898f27243ebab45ff5e1acb9d4df1b051fbc62824dbc6f6c93261a78b9a759", 16),
- new BigInteger("012ddcc86ef655998c39ddae11718669e5e46cf1495b07e13b1014cd69b3af68304ad2a6b64321e78bf3bbca9bb494e91d451717e2d97564c6549465d0205cf421", 16),
- new BigInteger("010600c4c21847459fe576703e2ebecae8a5094ee63f536bf4ac68d3c13e5e4f12ac5cc10ab6a2d05a199214d1824747d551909636b774c22cac0b837599abcc75", 16));
-
- // PSS Example 4.1
-
- private byte[] msg4a = Hex.decode("9fb03b827c8217d9");
-
- private byte[] slt4a = Hex.decode("ed7c98c95f30974fbe4fbddcf0f28d6021c0e91d");
-
- private byte[] sig4a = Hex.decode("0323d5b7bf20ba4539289ae452ae4297080feff4518423ff4811a817837e7d82f1836cdfab54514ff0887bddeebf40bf99b047abc3ecfa6a37a3ef00f4a0c4a88aae0904b745c846c4107e8797723e8ac810d9e3d95dfa30ff4966f4d75d13768d20857f2b1406f264cfe75e27d7652f4b5ed3575f28a702f8c4ed9cf9b2d44948");
-
- // PSS Example 4.2
-
- private byte[] msg4b = Hex.decode("0ca2ad77797ece86de5bf768750ddb5ed6a3116ad99bbd17edf7f782f0db1cd05b0f677468c5ea420dc116b10e80d110de2b0461ea14a38be68620392e7e893cb4ea9393fb886c20ff790642305bf302003892e54df9f667509dc53920df583f50a3dd61abb6fab75d600377e383e6aca6710eeea27156e06752c94ce25ae99fcbf8592dbe2d7e27453cb44de07100ebb1a2a19811a478adbeab270f94e8fe369d90b3ca612f9f");
-
- private byte[] slt4b = Hex.decode("22d71d54363a4217aa55113f059b3384e3e57e44");
-
- private byte[] sig4b = Hex.decode("049d0185845a264d28feb1e69edaec090609e8e46d93abb38371ce51f4aa65a599bdaaa81d24fba66a08a116cb644f3f1e653d95c89db8bbd5daac2709c8984000178410a7c6aa8667ddc38c741f710ec8665aa9052be929d4e3b16782c1662114c5414bb0353455c392fc28f3db59054b5f365c49e1d156f876ee10cb4fd70598");
-
-
- //
- // Example 8: A 1031-bit RSA key pair
- //
-
- private RSAKeyParameters pub8 = new RSAKeyParameters(false,
- new BigInteger("495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f", 16),
- new BigInteger("010001", 16));
-
- private RSAKeyParameters prv8 = new RSAPrivateCrtKeyParameters(
- new BigInteger("495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f", 16),
- new BigInteger("010001", 16),
- new BigInteger("6c66ffe98980c38fcdeab5159898836165f4b4b817c4f6a8d486ee4ea9130fe9b9092bd136d184f95f504a607eac565846d2fdd6597a8967c7396ef95a6eeebb4578a643966dca4d8ee3de842de63279c618159c1ab54a89437b6a6120e4930afb52a4ba6ced8a4947ac64b30a3497cbe701c2d6266d517219ad0ec6d347dbe9", 16),
- new BigInteger("08dad7f11363faa623d5d6d5e8a319328d82190d7127d2846c439b0ab72619b0a43a95320e4ec34fc3a9cea876422305bd76c5ba7be9e2f410c8060645a1d29edb", 16),
- new BigInteger("0847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca4174825b48f49706d", 16),
- new BigInteger("05c2a83c124b3621a2aa57ea2c3efe035eff4560f33ddebb7adab81fce69a0c8c2edc16520dda83d59a23be867963ac65f2cc710bbcfb96ee103deb771d105fd85", 16),
- new BigInteger("04cae8aa0d9faa165c87b682ec140b8ed3b50b24594b7a3b2c220b3669bb819f984f55310a1ae7823651d4a02e99447972595139363434e5e30a7e7d241551e1b9", 16),
- new BigInteger("07d3e47bf686600b11ac283ce88dbb3f6051e8efd04680e44c171ef531b80b2b7c39fc766320e2cf15d8d99820e96ff30dc69691839c4b40d7b06e45307dc91f3f", 16));
-
- // PSS Example 8.1
-
- private byte[] msg8a = Hex.decode("81332f4be62948415ea1d899792eeacf6c6e1db1da8be13b5cea41db2fed467092e1ff398914c714259775f595f8547f735692a575e6923af78f22c6997ddb90fb6f72d7bb0dd5744a31decd3dc3685849836ed34aec596304ad11843c4f88489f209735f5fb7fdaf7cec8addc5818168f880acbf490d51005b7a8e84e43e54287977571dd99eea4b161eb2df1f5108f12a4142a83322edb05a75487a3435c9a78ce53ed93bc550857d7a9fb");
-
- private byte[] slt8a = Hex.decode("1d65491d79c864b373009be6f6f2467bac4c78fa");
-
- private byte[] sig8a = Hex.decode("0262ac254bfa77f3c1aca22c5179f8f040422b3c5bafd40a8f21cf0fa5a667ccd5993d42dbafb409c520e25fce2b1ee1e716577f1efa17f3da28052f40f0419b23106d7845aaf01125b698e7a4dfe92d3967bb00c4d0d35ba3552ab9a8b3eef07c7fecdbc5424ac4db1e20cb37d0b2744769940ea907e17fbbca673b20522380c5");
-
- // PSS Example 8.2
-
- private byte[] msg8b = Hex.decode("e2f96eaf0e05e7ba326ecca0ba7fd2f7c02356f3cede9d0faabf4fcc8e60a973e5595fd9ea08");
-
- private byte[] slt8b = Hex.decode("435c098aa9909eb2377f1248b091b68987ff1838");
-
- private byte[] sig8b = Hex.decode("2707b9ad5115c58c94e932e8ec0a280f56339e44a1b58d4ddcff2f312e5f34dcfe39e89c6a94dcee86dbbdae5b79ba4e0819a9e7bfd9d982e7ee6c86ee68396e8b3a14c9c8f34b178eb741f9d3f121109bf5c8172fada2e768f9ea1433032c004a8aa07eb990000a48dc94c8bac8aabe2b09b1aa46c0a2aa0e12f63fbba775ba7e");
-
- //
- // Example 9: A 1536-bit RSA key pair
- //
-
- private RSAKeyParameters pub9 = new RSAKeyParameters(false,
- new BigInteger("e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b", 16),
- new BigInteger("010001", 16));
-
- private RSAKeyParameters prv9 = new RSAPrivateCrtKeyParameters(
- new BigInteger("e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b", 16),
- new BigInteger("010001", 16),
- new BigInteger("6a7fd84fb85fad073b34406db74f8d61a6abc12196a961dd79565e9da6e5187bce2d980250f7359575359270d91590bb0e427c71460b55d51410b191bcf309fea131a92c8e702738fa719f1e0041f52e40e91f229f4d96a1e6f172e15596b4510a6daec26105f2bebc53316b87bdf21311666070e8dfee69d52c71a976caae79c72b68d28580dc686d9f5129d225f82b3d615513a882b3db91416b48ce08888213e37eeb9af800d81cab328ce420689903c00c7b5fd31b75503a6d419684d629", 16),
- new BigInteger("f8eb97e98df12664eefdb761596a69ddcd0e76daece6ed4bf5a1b50ac086f7928a4d2f8726a77e515b74da41988f220b1cc87aa1fc810ce99a82f2d1ce821edced794c6941f42c7a1a0b8c4d28c75ec60b652279f6154a762aed165d47dee367", 16),
- new BigInteger("ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e4728cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b489c176128092d629e49d3d", 16),
- new BigInteger("2bb68bddfb0c4f56c8558bffaf892d8043037841e7fa81cfa61a38c5e39b901c8ee71122a5da2227bd6cdeeb481452c12ad3d61d5e4f776a0ab556591befe3e59e5a7fddb8345e1f2f35b9f4cee57c32414c086aec993e9353e480d9eec6289f", 16),
- new BigInteger("4ff897709fad079746494578e70fd8546130eeab5627c49b080f05ee4ad9f3e4b7cba9d6a5dff113a41c3409336833f190816d8a6bc42e9bec56b7567d0f3c9c696db619b245d901dd856db7c8092e77e9a1cccd56ee4dba42c5fdb61aec2669", 16),
- new BigInteger("77b9d1137b50404a982729316efafc7dfe66d34e5a182600d5f30a0a8512051c560d081d4d0a1835ec3d25a60f4e4d6aa948b2bf3dbb5b124cbbc3489255a3a948372f6978496745f943e1db4f18382ceaa505dfc65757bb3f857a58dce52156", 16));
-
- // PSS Example 9.1
-
- private byte[] msg9a = Hex.decode("a88e265855e9d7ca36c68795f0b31b591cd6587c71d060a0b3f7f3eaef43795922028bc2b6ad467cfc2d7f659c5385aa70ba3672cdde4cfe4970cc7904601b278872bf51321c4a972f3c95570f3445d4f57980e0f20df54846e6a52c668f1288c03f95006ea32f562d40d52af9feb32f0fa06db65b588a237b34e592d55cf979f903a642ef64d2ed542aa8c77dc1dd762f45a59303ed75e541ca271e2b60ca709e44fa0661131e8d5d4163fd8d398566ce26de8730e72f9cca737641c244159420637028df0a18079d6208ea8b4711a2c750f5");
-
- private byte[] slt9a = Hex.decode("c0a425313df8d7564bd2434d311523d5257eed80");
-
- private byte[] sig9a = Hex.decode("586107226c3ce013a7c8f04d1a6a2959bb4b8e205ba43a27b50f124111bc35ef589b039f5932187cb696d7d9a32c0c38300a5cdda4834b62d2eb240af33f79d13dfbf095bf599e0d9686948c1964747b67e89c9aba5cd85016236f566cc5802cb13ead51bc7ca6bef3b94dcbdbb1d570469771df0e00b1a8a06777472d2316279edae86474668d4e1efff95f1de61c6020da32ae92bbf16520fef3cf4d88f61121f24bbd9fe91b59caf1235b2a93ff81fc403addf4ebdea84934a9cdaf8e1a9e");
-
- // PSS Example 9.2
-
- private byte[] msg9b = Hex.decode("c8c9c6af04acda414d227ef23e0820c3732c500dc87275e95b0d095413993c2658bc1d988581ba879c2d201f14cb88ced153a01969a7bf0a7be79c84c1486bc12b3fa6c59871b6827c8ce253ca5fefa8a8c690bf326e8e37cdb96d90a82ebab69f86350e1822e8bd536a2e");
-
- private byte[] slt9b = Hex.decode("b307c43b4850a8dac2f15f32e37839ef8c5c0e91");
-
- private byte[] sig9b = Hex.decode("80b6d643255209f0a456763897ac9ed259d459b49c2887e5882ecb4434cfd66dd7e1699375381e51cd7f554f2c271704b399d42b4be2540a0eca61951f55267f7c2878c122842dadb28b01bd5f8c025f7e228418a673c03d6bc0c736d0a29546bd67f786d9d692ccea778d71d98c2063b7a71092187a4d35af108111d83e83eae46c46aa34277e06044589903788f1d5e7cee25fb485e92949118814d6f2c3ee361489016f327fb5bc517eb50470bffa1afa5f4ce9aa0ce5b8ee19bf5501b958");
-
-
- public String getName()
- {
- return "PSSBlindTest";
- }
-
- private void testSig(
- int id,
- RSAKeyParameters pub,
- RSAKeyParameters prv,
- byte[] slt,
- byte[] msg,
- byte[] sig)
- throws Exception
- {
- RSABlindingFactorGenerator blindFactorGen = new RSABlindingFactorGenerator();
- RSABlindingEngine blindingEngine = new RSABlindingEngine();
- PSSSigner blindSigner = new PSSSigner(blindingEngine, new SHA1Digest(), 20);
- PSSSigner signer = new PSSSigner(new RSAEngine(), new SHA1Digest(), 20);
-
- blindFactorGen.init(pub);
-
- BigInteger blindFactor = blindFactorGen.generateBlindingFactor();
- RSABlindingParameters params = new RSABlindingParameters(pub, blindFactor);
-
- // generate a blind signature
- blindSigner.init(true, new ParametersWithRandom(params, new FixedRandom(slt)));
-
- blindSigner.update(msg, 0, msg.length);
-
- byte[] blindedData = blindSigner.generateSignature();
-
- RSAEngine signerEngine = new RSAEngine();
-
- signerEngine.init(true, prv);
-
- byte[] blindedSig = signerEngine.processBlock(blindedData, 0, blindedData.length);
-
- // unblind the signature
- blindingEngine.init(false, params);
-
- byte[] s = blindingEngine.processBlock(blindedSig, 0, blindedSig.length);
-
- //signature verification
- if (!areEqual(s, sig))
- {
- fail("test " + id + " failed generation");
- }
-
- //verify signature with PSSSigner
- signer.init(false, pub);
- signer.update(msg, 0, msg.length);
-
- if (!signer.verifySignature(s))
- {
- fail("test " + id + " failed PSSSigner verification");
- }
- }
-
- private boolean isProcessingOkay(
- RSAKeyParameters pub,
- RSAKeyParameters prv,
- byte[] data,
- SecureRandom random)
- throws Exception
- {
- RSABlindingFactorGenerator blindFactorGen = new RSABlindingFactorGenerator();
- RSABlindingEngine blindingEngine = new RSABlindingEngine();
- PSSSigner blindSigner = new PSSSigner(blindingEngine, new SHA1Digest(), 20);
- PSSSigner pssEng = new PSSSigner(new RSAEngine(), new SHA1Digest(), 20);
-
- random.nextBytes(data);
-
- blindFactorGen.init(pub);
-
- BigInteger blindFactor = blindFactorGen.generateBlindingFactor();
- RSABlindingParameters params = new RSABlindingParameters(pub, blindFactor);
-
- // generate a blind signature
- blindSigner.init(true, new ParametersWithRandom(params, random));
-
- blindSigner.update(data, 0, data.length);
-
- byte[] blindedData = blindSigner.generateSignature();
-
- RSAEngine signerEngine = new RSAEngine();
-
- signerEngine.init(true, prv);
-
- byte[] blindedSig = signerEngine.processBlock(blindedData, 0, blindedData.length);
-
- // unblind the signature
- blindingEngine.init(false, params);
-
- byte[] s = blindingEngine.processBlock(blindedSig, 0, blindedSig.length);
-
- //verify signature with PSSSigner
- pssEng.init(false, pub);
- pssEng.update(data, 0, data.length);
-
- return pssEng.verifySignature(s);
- }
-
- public void performTest()
- throws Exception
- {
- testSig(1, pub1, prv1, slt1a, msg1a, sig1a);
- testSig(2, pub1, prv1, slt1b, msg1b, sig1b);
- testSig(3, pub2, prv2, slt2a, msg2a, sig2a);
- testSig(4, pub2, prv2, slt2b, msg2b, sig2b);
- testSig(5, pub4, prv4, slt4a, msg4a, sig4a);
- testSig(6, pub4, prv4, slt4b, msg4b, sig4b);
- testSig(7, pub8, prv8, slt8a, msg8a, sig8a);
- testSig(8, pub8, prv8, slt8b, msg8b, sig8b);
- testSig(9, pub9, prv9, slt9a, msg9a, sig9a);
- testSig(10, pub9, prv9, slt9b, msg9b, sig9b);
-
- //
- // loop test
- //
- int failed = 0;
- byte[] data = new byte[DATA_LENGTH];
-
- SecureRandom random = new SecureRandom();
-
-
- RSAKeyParameters[] kprv ={prv1, prv2, prv4, prv8, prv9};
- RSAKeyParameters[] kpub ={pub1, pub2, pub4, pub8, pub9};
-
- int i = 0;
- for (int j = 0; j < NUM_TESTS; j++, i++)
- {
- if (i == kprv.length)
- {
- i = 0;
- }
-
- if (!isProcessingOkay(kpub[i], kprv[i], data, random))
- {
- failed++;
- }
- }
-
- if (failed != 0)
- {
- fail("loop test failed - failures: " + failed);
- }
-
- //
- // key generation test
- //
- RSAKeyPairGenerator pGen = new RSAKeyPairGenerator();
- RSAKeyGenerationParameters genParam = new RSAKeyGenerationParameters(
- BigInteger.valueOf(0x11), new SecureRandom(), 1024, 25);
-
- pGen.init(genParam);
- failed = 0;
-
- for (int k = 0; k < NUM_TESTS_WITH_KEY_GENERATION; k++)
- {
- AsymmetricCipherKeyPair pair = pGen.generateKeyPair();
-
- for (int j = 0; j < NUM_TESTS; j++)
- {
- if (!isProcessingOkay((RSAKeyParameters)pair.getPublic(), (RSAKeyParameters)pair.getPrivate(), data, random))
- {
- failed++;
- }
- }
-
- }
-
- if (failed != 0)
- {
- fail("loop test with key generation failed - failures: " + failed);
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new PSSBlindTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/PSSTest.java b/core/src/test/java/org/bouncycastle/crypto/test/PSSTest.java
deleted file mode 100644
index a718f8cd..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/PSSTest.java
+++ /dev/null
@@ -1,332 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.engines.RSAEngine;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
-import org.bouncycastle.crypto.signers.PSSSigner;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/*
- * RSA PSS test vectors for PKCS#1 V2.1
- */
-public class PSSTest
- extends SimpleTest
-{
- private final int DATA_LENGTH = 1000;
- private final int NUM_TESTS = 500;
-
- private class FixedRandom
- extends SecureRandom
- {
- byte[] vals;
-
- FixedRandom(
- byte[] vals)
- {
- this.vals = vals;
- }
-
- public void nextBytes(
- byte[] bytes)
- {
- System.arraycopy(vals, 0, bytes, 0, vals.length);
- }
- }
-
- //
- // Example 1: A 1024-bit RSA keypair
- //
- private RSAKeyParameters pub1 = new RSAKeyParameters(false,
- new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",16),
- new BigInteger("010001",16));
-
- private RSAKeyParameters prv1 = new RSAPrivateCrtKeyParameters(
- new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",16),
- new BigInteger("010001",16),
- new BigInteger("33a5042a90b27d4f5451ca9bbbd0b44771a101af884340aef9885f2a4bbe92e894a724ac3c568c8f97853ad07c0266c8c6a3ca0929f1e8f11231884429fc4d9ae55fee896a10ce707c3ed7e734e44727a39574501a532683109c2abacaba283c31b4bd2f53c3ee37e352cee34f9e503bd80c0622ad79c6dcee883547c6a3b325",16),
- new BigInteger("e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443",16),
- new BigInteger("b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd",16),
- new BigInteger("28fa13938655be1f8a159cbaca5a72ea190c30089e19cd274a556f36c4f6e19f554b34c077790427bbdd8dd3ede2448328f385d81b30e8e43b2fffa027861979",16),
- new BigInteger("1a8b38f398fa712049898d7fb79ee0a77668791299cdfa09efc0e507acb21ed74301ef5bfd48be455eaeb6e1678255827580a8e4e8e14151d1510a82a3f2e729",16),
- new BigInteger("27156aba4126d24a81f3a528cbfb27f56886f840a9f6e86e17a44b94fe9319584b8e22fdde1e5a2e3bd8aa5ba8d8584194eb2190acf832b847f13a3d24a79f4d",16));
-
- // PSSExample1.1
-
- private byte[] msg1a = Hex.decode("cdc87da223d786df3b45e0bbbc721326d1ee2af806cc315475cc6f0d9c66e1b62371d45ce2392e1ac92844c310102f156a0d8d52c1f4c40ba3aa65095786cb769757a6563ba958fed0bcc984e8b517a3d5f515b23b8a41e74aa867693f90dfb061a6e86dfaaee64472c00e5f20945729cbebe77f06ce78e08f4098fba41f9d6193c0317e8b60d4b6084acb42d29e3808a3bc372d85e331170fcbf7cc72d0b71c296648b3a4d10f416295d0807aa625cab2744fd9ea8fd223c42537029828bd16be02546f130fd2e33b936d2676e08aed1b73318b750a0167d0");
-
- private byte[] slt1a = Hex.decode("dee959c7e06411361420ff80185ed57f3e6776af");
-
- private byte[] sig1a = Hex.decode("9074308fb598e9701b2294388e52f971faac2b60a5145af185df5287b5ed2887e57ce7fd44dc8634e407c8e0e4360bc226f3ec227f9d9e54638e8d31f5051215df6ebb9c2f9579aa77598a38f914b5b9c1bd83c4e2f9f382a0d0aa3542ffee65984a601bc69eb28deb27dca12c82c2d4c3f66cd500f1ff2b994d8a4e30cbb33c");
-
- // PSSExample1.2
-
- private byte[] msg1b = Hex.decode("851384cdfe819c22ed6c4ccb30daeb5cf059bc8e1166b7e3530c4c233e2b5f8f71a1cca582d43ecc72b1bca16dfc7013226b9e");
-
- private byte[] slt1b = Hex.decode("ef2869fa40c346cb183dab3d7bffc98fd56df42d");
-
- private byte[] sig1b = Hex.decode("3ef7f46e831bf92b32274142a585ffcefbdca7b32ae90d10fb0f0c729984f04ef29a9df0780775ce43739b97838390db0a5505e63de927028d9d29b219ca2c4517832558a55d694a6d25b9dab66003c4cccd907802193be5170d26147d37b93590241be51c25055f47ef62752cfbe21418fafe98c22c4d4d47724fdb5669e843");
-
- //
- // Example 2: A 1025-bit RSA keypair
- //
-
- private RSAKeyParameters pub2 = new RSAKeyParameters(false,
- new BigInteger("01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9", 16),
- new BigInteger("010001", 16));
-
- private RSAKeyParameters prv2 = new RSAPrivateCrtKeyParameters(
- new BigInteger("01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9", 16),
- new BigInteger("010001", 16),
- new BigInteger("027d147e4673057377fd1ea201565772176a7dc38358d376045685a2e787c23c15576bc16b9f444402d6bfc5d98a3e88ea13ef67c353eca0c0ddba9255bd7b8bb50a644afdfd1dd51695b252d22e7318d1b6687a1c10ff75545f3db0fe602d5f2b7f294e3601eab7b9d1cecd767f64692e3e536ca2846cb0c2dd486a39fa75b1", 16),
- new BigInteger("016601e926a0f8c9e26ecab769ea65a5e7c52cc9e080ef519457c644da6891c5a104d3ea7955929a22e7c68a7af9fcad777c3ccc2b9e3d3650bce404399b7e59d1", 16),
- new BigInteger("014eafa1d4d0184da7e31f877d1281ddda625664869e8379e67ad3b75eae74a580e9827abd6eb7a002cb5411f5266797768fb8e95ae40e3e8a01f35ff89e56c079", 16),
- new BigInteger("e247cce504939b8f0a36090de200938755e2444b29539a7da7a902f6056835c0db7b52559497cfe2c61a8086d0213c472c78851800b171f6401de2e9c2756f31", 16),
- new BigInteger("b12fba757855e586e46f64c38a70c68b3f548d93d787b399999d4c8f0bbd2581c21e19ed0018a6d5d3df86424b3abcad40199d31495b61309f27c1bf55d487c1", 16),
- new BigInteger("564b1e1fa003bda91e89090425aac05b91da9ee25061e7628d5f51304a84992fdc33762bd378a59f030a334d532bd0dae8f298ea9ed844636ad5fb8cbdc03cad", 16));
-
- // PSS Example 2.1
-
- private byte[] msg2a = Hex.decode("daba032066263faedb659848115278a52c44faa3a76f37515ed336321072c40a9d9b53bc05014078adf520875146aae70ff060226dcb7b1f1fc27e9360");
- private byte[] slt2a = Hex.decode("57bf160bcb02bb1dc7280cf0458530b7d2832ff7");
- private byte[] sig2a = Hex.decode("014c5ba5338328ccc6e7a90bf1c0ab3fd606ff4796d3c12e4b639ed9136a5fec6c16d8884bdd99cfdc521456b0742b736868cf90de099adb8d5ffd1deff39ba4007ab746cefdb22d7df0e225f54627dc65466131721b90af445363a8358b9f607642f78fab0ab0f43b7168d64bae70d8827848d8ef1e421c5754ddf42c2589b5b3");
-
- // PSS Example 2.2
-
- private byte[] msg2b = Hex.decode("e4f8601a8a6da1be34447c0959c058570c3668cfd51dd5f9ccd6ad4411fe8213486d78a6c49f93efc2ca2288cebc2b9b60bd04b1e220d86e3d4848d709d032d1e8c6a070c6af9a499fcf95354b14ba6127c739de1bb0fd16431e46938aec0cf8ad9eb72e832a7035de9b7807bdc0ed8b68eb0f5ac2216be40ce920c0db0eddd3860ed788efaccaca502d8f2bd6d1a7c1f41ff46f1681c8f1f818e9c4f6d91a0c7803ccc63d76a6544d843e084e363b8acc55aa531733edb5dee5b5196e9f03e8b731b3776428d9e457fe3fbcb3db7274442d785890e9cb0854b6444dace791d7273de1889719338a77fe");
- private byte[] slt2b = Hex.decode("7f6dd359e604e60870e898e47b19bf2e5a7b2a90");
- private byte[] sig2b = Hex.decode("010991656cca182b7f29d2dbc007e7ae0fec158eb6759cb9c45c5ff87c7635dd46d150882f4de1e9ae65e7f7d9018f6836954a47c0a81a8a6b6f83f2944d6081b1aa7c759b254b2c34b691da67cc0226e20b2f18b42212761dcd4b908a62b371b5918c5742af4b537e296917674fb914194761621cc19a41f6fb953fbcbb649dea");
-
- //
- // Example 4: A 1027-bit RSA key pair
- //
-
- private RSAKeyParameters pub4 = new RSAKeyParameters(false,
- new BigInteger("054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705", 16),
- new BigInteger("010001", 16));
-
- private RSAKeyParameters prv4 = new RSAPrivateCrtKeyParameters(
- new BigInteger("054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705", 16),
- new BigInteger("010001", 16),
- new BigInteger("fa041f8cd9697ceed38ec8caa275523b4dd72b09a301d3541d72f5d31c05cbce2d6983b36183af10690bd46c46131e35789431a556771dd0049b57461bf060c1f68472e8a67c25f357e5b6b4738fa541a730346b4a07649a2dfa806a69c975b6aba64678acc7f5913e89c622f2d8abb1e3e32554e39df94ba60c002e387d9011", 16),
- new BigInteger("029232336d2838945dba9dd7723f4e624a05f7375b927a87abe6a893a1658fd49f47f6c7b0fa596c65fa68a23f0ab432962d18d4343bd6fd671a5ea8d148413995", 16),
- new BigInteger("020ef5efe7c5394aed2272f7e81a74f4c02d145894cb1b3cab23a9a0710a2afc7e3329acbb743d01f680c4d02afb4c8fde7e20930811bb2b995788b5e872c20bb1", 16),
- new BigInteger("026e7e28010ecf2412d9523ad704647fb4fe9b66b1a681581b0e15553a89b1542828898f27243ebab45ff5e1acb9d4df1b051fbc62824dbc6f6c93261a78b9a759", 16),
- new BigInteger("012ddcc86ef655998c39ddae11718669e5e46cf1495b07e13b1014cd69b3af68304ad2a6b64321e78bf3bbca9bb494e91d451717e2d97564c6549465d0205cf421", 16),
- new BigInteger("010600c4c21847459fe576703e2ebecae8a5094ee63f536bf4ac68d3c13e5e4f12ac5cc10ab6a2d05a199214d1824747d551909636b774c22cac0b837599abcc75", 16));
-
- // PSS Example 4.1
-
- private byte[] msg4a = Hex.decode("9fb03b827c8217d9");
-
- private byte[] slt4a = Hex.decode("ed7c98c95f30974fbe4fbddcf0f28d6021c0e91d");
-
- private byte[] sig4a = Hex.decode("0323d5b7bf20ba4539289ae452ae4297080feff4518423ff4811a817837e7d82f1836cdfab54514ff0887bddeebf40bf99b047abc3ecfa6a37a3ef00f4a0c4a88aae0904b745c846c4107e8797723e8ac810d9e3d95dfa30ff4966f4d75d13768d20857f2b1406f264cfe75e27d7652f4b5ed3575f28a702f8c4ed9cf9b2d44948");
-
- // PSS Example 4.2
-
- private byte[] msg4b = Hex.decode("0ca2ad77797ece86de5bf768750ddb5ed6a3116ad99bbd17edf7f782f0db1cd05b0f677468c5ea420dc116b10e80d110de2b0461ea14a38be68620392e7e893cb4ea9393fb886c20ff790642305bf302003892e54df9f667509dc53920df583f50a3dd61abb6fab75d600377e383e6aca6710eeea27156e06752c94ce25ae99fcbf8592dbe2d7e27453cb44de07100ebb1a2a19811a478adbeab270f94e8fe369d90b3ca612f9f");
-
- private byte[] slt4b = Hex.decode("22d71d54363a4217aa55113f059b3384e3e57e44");
-
- private byte[] sig4b = Hex.decode("049d0185845a264d28feb1e69edaec090609e8e46d93abb38371ce51f4aa65a599bdaaa81d24fba66a08a116cb644f3f1e653d95c89db8bbd5daac2709c8984000178410a7c6aa8667ddc38c741f710ec8665aa9052be929d4e3b16782c1662114c5414bb0353455c392fc28f3db59054b5f365c49e1d156f876ee10cb4fd70598");
-
-
- //
- // Example 8: A 1031-bit RSA key pair
- //
-
- private RSAKeyParameters pub8 = new RSAKeyParameters(false,
- new BigInteger("495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f", 16),
- new BigInteger("010001", 16));
-
- private RSAKeyParameters prv8 = new RSAPrivateCrtKeyParameters(
- new BigInteger("495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f", 16),
- new BigInteger("010001", 16),
- new BigInteger("6c66ffe98980c38fcdeab5159898836165f4b4b817c4f6a8d486ee4ea9130fe9b9092bd136d184f95f504a607eac565846d2fdd6597a8967c7396ef95a6eeebb4578a643966dca4d8ee3de842de63279c618159c1ab54a89437b6a6120e4930afb52a4ba6ced8a4947ac64b30a3497cbe701c2d6266d517219ad0ec6d347dbe9", 16),
- new BigInteger("08dad7f11363faa623d5d6d5e8a319328d82190d7127d2846c439b0ab72619b0a43a95320e4ec34fc3a9cea876422305bd76c5ba7be9e2f410c8060645a1d29edb", 16),
- new BigInteger("0847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca4174825b48f49706d", 16),
- new BigInteger("05c2a83c124b3621a2aa57ea2c3efe035eff4560f33ddebb7adab81fce69a0c8c2edc16520dda83d59a23be867963ac65f2cc710bbcfb96ee103deb771d105fd85", 16),
- new BigInteger("04cae8aa0d9faa165c87b682ec140b8ed3b50b24594b7a3b2c220b3669bb819f984f55310a1ae7823651d4a02e99447972595139363434e5e30a7e7d241551e1b9", 16),
- new BigInteger("07d3e47bf686600b11ac283ce88dbb3f6051e8efd04680e44c171ef531b80b2b7c39fc766320e2cf15d8d99820e96ff30dc69691839c4b40d7b06e45307dc91f3f", 16));
-
- // PSS Example 8.1
-
- private byte[] msg8a = Hex.decode("81332f4be62948415ea1d899792eeacf6c6e1db1da8be13b5cea41db2fed467092e1ff398914c714259775f595f8547f735692a575e6923af78f22c6997ddb90fb6f72d7bb0dd5744a31decd3dc3685849836ed34aec596304ad11843c4f88489f209735f5fb7fdaf7cec8addc5818168f880acbf490d51005b7a8e84e43e54287977571dd99eea4b161eb2df1f5108f12a4142a83322edb05a75487a3435c9a78ce53ed93bc550857d7a9fb");
-
- private byte[] slt8a = Hex.decode("1d65491d79c864b373009be6f6f2467bac4c78fa");
-
- private byte[] sig8a = Hex.decode("0262ac254bfa77f3c1aca22c5179f8f040422b3c5bafd40a8f21cf0fa5a667ccd5993d42dbafb409c520e25fce2b1ee1e716577f1efa17f3da28052f40f0419b23106d7845aaf01125b698e7a4dfe92d3967bb00c4d0d35ba3552ab9a8b3eef07c7fecdbc5424ac4db1e20cb37d0b2744769940ea907e17fbbca673b20522380c5");
-
- // PSS Example 8.2
-
- private byte[] msg8b = Hex.decode("e2f96eaf0e05e7ba326ecca0ba7fd2f7c02356f3cede9d0faabf4fcc8e60a973e5595fd9ea08");
-
- private byte[] slt8b = Hex.decode("435c098aa9909eb2377f1248b091b68987ff1838");
-
- private byte[] sig8b = Hex.decode("2707b9ad5115c58c94e932e8ec0a280f56339e44a1b58d4ddcff2f312e5f34dcfe39e89c6a94dcee86dbbdae5b79ba4e0819a9e7bfd9d982e7ee6c86ee68396e8b3a14c9c8f34b178eb741f9d3f121109bf5c8172fada2e768f9ea1433032c004a8aa07eb990000a48dc94c8bac8aabe2b09b1aa46c0a2aa0e12f63fbba775ba7e");
-
- //
- // Example 9: A 1536-bit RSA key pair
- //
-
- private RSAKeyParameters pub9 = new RSAKeyParameters(false,
- new BigInteger("e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b", 16),
- new BigInteger("010001", 16));
-
- private RSAKeyParameters prv9 = new RSAPrivateCrtKeyParameters(
- new BigInteger("e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b", 16),
- new BigInteger("010001", 16),
- new BigInteger("6a7fd84fb85fad073b34406db74f8d61a6abc12196a961dd79565e9da6e5187bce2d980250f7359575359270d91590bb0e427c71460b55d51410b191bcf309fea131a92c8e702738fa719f1e0041f52e40e91f229f4d96a1e6f172e15596b4510a6daec26105f2bebc53316b87bdf21311666070e8dfee69d52c71a976caae79c72b68d28580dc686d9f5129d225f82b3d615513a882b3db91416b48ce08888213e37eeb9af800d81cab328ce420689903c00c7b5fd31b75503a6d419684d629", 16),
- new BigInteger("f8eb97e98df12664eefdb761596a69ddcd0e76daece6ed4bf5a1b50ac086f7928a4d2f8726a77e515b74da41988f220b1cc87aa1fc810ce99a82f2d1ce821edced794c6941f42c7a1a0b8c4d28c75ec60b652279f6154a762aed165d47dee367", 16),
- new BigInteger("ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e4728cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b489c176128092d629e49d3d", 16),
- new BigInteger("2bb68bddfb0c4f56c8558bffaf892d8043037841e7fa81cfa61a38c5e39b901c8ee71122a5da2227bd6cdeeb481452c12ad3d61d5e4f776a0ab556591befe3e59e5a7fddb8345e1f2f35b9f4cee57c32414c086aec993e9353e480d9eec6289f", 16),
- new BigInteger("4ff897709fad079746494578e70fd8546130eeab5627c49b080f05ee4ad9f3e4b7cba9d6a5dff113a41c3409336833f190816d8a6bc42e9bec56b7567d0f3c9c696db619b245d901dd856db7c8092e77e9a1cccd56ee4dba42c5fdb61aec2669", 16),
- new BigInteger("77b9d1137b50404a982729316efafc7dfe66d34e5a182600d5f30a0a8512051c560d081d4d0a1835ec3d25a60f4e4d6aa948b2bf3dbb5b124cbbc3489255a3a948372f6978496745f943e1db4f18382ceaa505dfc65757bb3f857a58dce52156", 16));
-
- // PSS Example 9.1
-
- private byte[] msg9a = Hex.decode("a88e265855e9d7ca36c68795f0b31b591cd6587c71d060a0b3f7f3eaef43795922028bc2b6ad467cfc2d7f659c5385aa70ba3672cdde4cfe4970cc7904601b278872bf51321c4a972f3c95570f3445d4f57980e0f20df54846e6a52c668f1288c03f95006ea32f562d40d52af9feb32f0fa06db65b588a237b34e592d55cf979f903a642ef64d2ed542aa8c77dc1dd762f45a59303ed75e541ca271e2b60ca709e44fa0661131e8d5d4163fd8d398566ce26de8730e72f9cca737641c244159420637028df0a18079d6208ea8b4711a2c750f5");
-
- private byte[] slt9a = Hex.decode("c0a425313df8d7564bd2434d311523d5257eed80");
-
- private byte[] sig9a = Hex.decode("586107226c3ce013a7c8f04d1a6a2959bb4b8e205ba43a27b50f124111bc35ef589b039f5932187cb696d7d9a32c0c38300a5cdda4834b62d2eb240af33f79d13dfbf095bf599e0d9686948c1964747b67e89c9aba5cd85016236f566cc5802cb13ead51bc7ca6bef3b94dcbdbb1d570469771df0e00b1a8a06777472d2316279edae86474668d4e1efff95f1de61c6020da32ae92bbf16520fef3cf4d88f61121f24bbd9fe91b59caf1235b2a93ff81fc403addf4ebdea84934a9cdaf8e1a9e");
-
- // PSS Example 9.2
-
- private byte[] msg9b = Hex.decode("c8c9c6af04acda414d227ef23e0820c3732c500dc87275e95b0d095413993c2658bc1d988581ba879c2d201f14cb88ced153a01969a7bf0a7be79c84c1486bc12b3fa6c59871b6827c8ce253ca5fefa8a8c690bf326e8e37cdb96d90a82ebab69f86350e1822e8bd536a2e");
-
- private byte[] slt9b = Hex.decode("b307c43b4850a8dac2f15f32e37839ef8c5c0e91");
-
- private byte[] sig9b = Hex.decode("80b6d643255209f0a456763897ac9ed259d459b49c2887e5882ecb4434cfd66dd7e1699375381e51cd7f554f2c271704b399d42b4be2540a0eca61951f55267f7c2878c122842dadb28b01bd5f8c025f7e228418a673c03d6bc0c736d0a29546bd67f786d9d692ccea778d71d98c2063b7a71092187a4d35af108111d83e83eae46c46aa34277e06044589903788f1d5e7cee25fb485e92949118814d6f2c3ee361489016f327fb5bc517eb50470bffa1afa5f4ce9aa0ce5b8ee19bf5501b958");
-
-
- public String getName()
- {
- return "PSSTest";
- }
-
- private void testSig(
- int id,
- RSAKeyParameters pub,
- RSAKeyParameters prv,
- byte[] slt,
- byte[] msg,
- byte[] sig)
- throws Exception
- {
- PSSSigner eng = new PSSSigner(new RSAEngine(), new SHA1Digest(), 20);
-
- eng.init(true, new ParametersWithRandom(prv, new FixedRandom(slt)));
-
- eng.update(msg, 0, msg.length);
-
- byte[] s = eng.generateSignature();
-
- if (!areEqual(s, sig))
- {
- fail("test " + id + " failed generation");
- }
-
- eng.init(false, pub);
-
- eng.update(msg, 0, msg.length);
-
- if (!eng.verifySignature(s))
- {
- fail("test " + id + " failed verification");
- }
- }
-
- public void performTest()
- throws Exception
- {
- testSig(1, pub1, prv1, slt1a, msg1a, sig1a);
- testSig(2, pub1, prv1, slt1b, msg1b, sig1b);
- testSig(3, pub2, prv2, slt2a, msg2a, sig2a);
- testSig(4, pub2, prv2, slt2b, msg2b, sig2b);
- testSig(5, pub4, prv4, slt4a, msg4a, sig4a);
- testSig(6, pub4, prv4, slt4b, msg4b, sig4b);
- testSig(7, pub8, prv8, slt8a, msg8a, sig8a);
- testSig(8, pub8, prv8, slt8b, msg8b, sig8b);
- testSig(9, pub9, prv9, slt9a, msg9a, sig9a);
- testSig(10, pub9, prv9, slt9b, msg9b, sig9b);
-
- //
- // loop test - sha-1 only
- //
- PSSSigner eng = new PSSSigner(new RSAEngine(), new SHA1Digest(), 20);
- int failed = 0;
- byte[] data = new byte[DATA_LENGTH];
-
- SecureRandom random = new SecureRandom();
- random.nextBytes(data);
-
- for (int j = 0; j < NUM_TESTS; j++)
- {
- eng.init(true, new ParametersWithRandom(prv8, random));
-
- eng.update(data, 0, data.length);
-
- byte[] s = eng.generateSignature();
-
- eng.init(false, pub8);
-
- eng.update(data, 0, data.length);
-
- if (!eng.verifySignature(s))
- {
- failed++;
- }
- }
-
- if (failed != 0)
- {
- fail("loop test failed - failures: " + failed);
- }
-
- //
- // loop test - sha-256 and sha-1
- //
- eng = new PSSSigner(new RSAEngine(), new SHA256Digest(), new SHA1Digest(), 20);
- failed = 0;
- data = new byte[DATA_LENGTH];
-
- random.nextBytes(data);
-
- for (int j = 0; j < NUM_TESTS; j++)
- {
- eng.init(true, new ParametersWithRandom(prv8, random));
-
- eng.update(data, 0, data.length);
-
- byte[] s = eng.generateSignature();
-
- eng.init(false, pub8);
-
- eng.update(data, 0, data.length);
-
- if (!eng.verifySignature(s))
- {
- failed++;
- }
- }
-
- if (failed != 0)
- {
- fail("loop test failed - failures: " + failed);
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new PSSTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/PaddingTest.java b/core/src/test/java/org/bouncycastle/crypto/test/PaddingTest.java
deleted file mode 100644
index c963b26e..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/PaddingTest.java
+++ /dev/null
@@ -1,200 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.engines.DESEngine;
-import org.bouncycastle.crypto.paddings.BlockCipherPadding;
-import org.bouncycastle.crypto.paddings.ISO10126d2Padding;
-import org.bouncycastle.crypto.paddings.ISO7816d4Padding;
-import org.bouncycastle.crypto.paddings.PKCS7Padding;
-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.KeyParameter;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * General Padding tests.
- */
-public class PaddingTest
- extends SimpleTest
-{
- public PaddingTest()
- {
- }
-
- private void blockCheck(
- PaddedBufferedBlockCipher cipher,
- BlockCipherPadding padding,
- KeyParameter key,
- byte[] data)
- {
- byte[] out = new byte[data.length + 8];
- byte[] dec = new byte[data.length];
-
- try
- {
- cipher.init(true, key);
-
- int len = cipher.processBytes(data, 0, data.length, out, 0);
-
- len += cipher.doFinal(out, len);
-
- cipher.init(false, key);
-
- int decLen = cipher.processBytes(out, 0, len, dec, 0);
-
- decLen += cipher.doFinal(dec, decLen);
-
- if (!areEqual(data, dec))
- {
- fail("failed to decrypt - i = " + data.length + ", padding = " + padding.getPaddingName());
- }
- }
- catch (Exception e)
- {
- fail("Exception - " + e.toString(), e);
- }
- }
-
- public void testPadding(
- BlockCipherPadding padding,
- SecureRandom rand,
- byte[] ffVector,
- byte[] ZeroVector)
- {
- PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new DESEngine(), padding);
- KeyParameter key = new KeyParameter(Hex.decode("0011223344556677"));
-
- //
- // ff test
- //
- byte[] data = { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0 };
-
- if (ffVector != null)
- {
- padding.addPadding(data, 3);
-
- if (!areEqual(data, ffVector))
- {
- fail("failed ff test for " + padding.getPaddingName());
- }
- }
-
- //
- // zero test
- //
- if (ZeroVector != null)
- {
- data = new byte[8];
- padding.addPadding(data, 4);
-
- if (!areEqual(data, ZeroVector))
- {
- fail("failed zero test for " + padding.getPaddingName());
- }
- }
-
- for (int i = 1; i != 200; i++)
- {
- data = new byte[i];
-
- rand.nextBytes(data);
-
- blockCheck(cipher, padding, key, data);
- }
- }
-
- private void testOutputSizes()
- {
- PaddedBufferedBlockCipher bc = new PaddedBufferedBlockCipher(new DESEngine(), new PKCS7Padding());
- KeyParameter key = new KeyParameter(Hex.decode("0011223344556677"));
-
- for (int i = 0; i < bc.getBlockSize() * 2; i++)
- {
- bc.init(true, key);
- if (bc.getUpdateOutputSize(i) < 0)
- {
- fail("Padded cipher encrypt negative update output size for input size " + i);
- }
- if (bc.getOutputSize(i) < 0)
- {
- fail("Padded cipher encrypt negative output size for input size " + i);
- }
-
- bc.init(false, key);
- if (bc.getUpdateOutputSize(i) < 0)
- {
- fail("Padded cipher decrypt negative update output size for input size " + i);
- }
- if (bc.getOutputSize(i) < 0)
- {
- fail("Padded cipher decrypt negative output size for input size " + i);
- }
-
- }
- }
-
- public void performTest()
- {
- SecureRandom rand = new SecureRandom(new byte[20]);
-
- rand.setSeed(System.currentTimeMillis());
-
- testPadding(new PKCS7Padding(), rand,
- Hex.decode("ffffff0505050505"),
- Hex.decode("0000000004040404"));
-
- PKCS7Padding padder = new PKCS7Padding();
- try
- {
- padder.padCount(new byte[8]);
-
- fail("invalid padding not detected");
- }
- catch (InvalidCipherTextException e)
- {
- if (!"pad block corrupted".equals(e.getMessage()))
- {
- fail("wrong exception for corrupt padding: " + e);
- }
- }
-
- testPadding(new ISO10126d2Padding(), rand,
- null,
- null);
-
- testPadding(new X923Padding(), rand,
- null,
- null);
-
- testPadding(new TBCPadding(), rand,
- Hex.decode("ffffff0000000000"),
- Hex.decode("00000000ffffffff"));
-
- testPadding(new ZeroBytePadding(), rand,
- Hex.decode("ffffff0000000000"),
- null);
-
- testPadding(new ISO7816d4Padding(), rand,
- Hex.decode("ffffff8000000000"),
- Hex.decode("0000000080000000"));
-
- testOutputSizes();
-
- }
-
- public String getName()
- {
- return "PaddingTest";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new PaddingTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/Poly1305Test.java b/core/src/test/java/org/bouncycastle/crypto/test/Poly1305Test.java
deleted file mode 100644
index 08ee8e10..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/Poly1305Test.java
+++ /dev/null
@@ -1,388 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherKeyGenerator;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.engines.AESFastEngine;
-import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
-import org.bouncycastle.crypto.macs.Poly1305;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/*
- */
-public class Poly1305Test
- extends SimpleTest
-{
- private static final int MAXLEN = 1000;
-
- private static class KeyEngine
- implements BlockCipher
- {
-
- private byte[] key;
- private final int blockSize;
-
- public KeyEngine(int blockSize)
- {
- this.blockSize = blockSize;
- }
-
- public void init(boolean forEncryption, CipherParameters params)
- throws IllegalArgumentException
- {
- if (params instanceof KeyParameter)
- {
- this.key = ((KeyParameter)params).getKey();
- }
- }
-
- public String getAlgorithmName()
- {
- return "Key";
- }
-
- public int getBlockSize()
- {
- return blockSize;
- }
-
- public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
- throws DataLengthException,
- IllegalStateException
- {
- System.arraycopy(key, 0, out, outOff, key.length);
- return key.length;
- }
-
- public void reset()
- {
- }
-
- }
-
- private static class TestCase
- {
- private final byte[] key;
- private final byte[] nonce;
- private final byte[] message;
- private final byte[] expectedMac;
-
- public TestCase(String key, String nonce, String message, String expectedMac)
- {
- this.key = Hex.decode(key);
- // nacl test case keys are not pre-clamped
- Poly1305KeyGenerator.clamp(this.key);
- this.nonce = (nonce == null) ? null : Hex.decode(nonce);
- this.message = Hex.decode(message);
- this.expectedMac = Hex.decode(expectedMac);
- }
- }
-
- private static TestCase[] CASES = {
- // Raw Poly1305
- // onetimeauth.c from nacl-20110221
- new TestCase("2539121d8e234e652d651fa4c8cff880eea6a7251c1e72916d11c2cb214d3c25", null,
- "8e993b9f48681273c29650ba32fc76ce48332ea7164d96a4476fb8c531a1186a"
- + "c0dfc17c98dce87b4da7f011ec48c97271d2c20f9b928fe2270d6fb863d51738"
- + "b48eeee314a7cc8ab932164548e526ae90224368517acfeabd6bb3732bc0e9da"
- + "99832b61ca01b6de56244a9e88d5f9b37973f622a43d14a6599b1f654cb45a74e355a5",
- "f3ffc7703f9400e52a7dfb4b3d3305d9"),
-
- // Poly1305-AES
- // Loop 1 of test-poly1305aes from poly1305aes-20050218
- new TestCase("0000000000000000000000000000000000000000000000000000000000000000",
- "00000000000000000000000000000000", "", "66e94bd4ef8a2c3b884cfa59ca342b2e"),
- new TestCase("f795bd4a52e29ed713d313fa20e98dbcf795bd0a50e29e0710d3130a20e98d0c",
- "917cf69ebd68b2ec9b9fe9a3eadda692", "66f7", "5ca585c75e8f8f025e710cabc9a1508b"),
- new TestCase("e69dae0aab9f91c03a325dcc9436fa903ef49901c8e11c000430d90ad45e7603",
- "166450152e2394835606a9d1dd2cdc8b", "66f75c0e0c7a406586", "2924f51b9c2eff5df09db61dd03a9ca1"),
- new TestCase("85a4ea91a7de0b0d96eed0d4bf6ecf1cda4afc035087d90e503f8f0ea08c3e0d",
- "0b6ef7a0b8f8c738b0f8d5995415271f",
- "66f75c0e0c7a40658629e3392f7f8e3349a02191ffd49f39879a8d9d1d0e23ea",
- "3c5a13adb18d31c64cc29972030c917d"),
- new TestCase(
- "25eb69bac5cdf7d6bfcee4d9d5507b82ca3c6a0da0a864024ca3090628c28e0d",
- "046772a4f0a8de92e4f0d628cdb04484",
- "66f75c0e0c7a40658629e3392f7f8e3349a02191ffd49f39879a8d9d1d0e23ea3caa4d240bd2ab8a8c4a6bb8d3288d9de4b793f05e97646dd4d98055de",
- "fc5fb58dc65daf19b14d1d05da1064e8"),
-
- // Specific test cases generated from test-poly1305aes from poly1305aes-20050218 that
- // expose Java unsigned integer problems
- new TestCase(
- "95cc0e44d0b79a8856afcae1bec4fe3c" + "01bcb20bfc8b6e03609ddd09f44b060f",
- null,
- "66f75c0e0c7a40658629e3392f7f8e3349a02191ffd49f39879a8d9d1d0e23ea3caa4d240bd2ab8a8c4a6bb8d3288d9de4b793f05e97646dd4d98055de"
- + "fc3e0677d956b4c62664bac15962ab15d93ccbbc03aafdbde779162ed93b55361f0f8acaa41d50ef5175927fe79ea316186516eef15001cd04d3524a55"
- + "e4fa3c5ca479d3aaa8a897c21807f721b6270ffc68b6889d81a116799f6aaa35d8e04c7a7dd5e6da2519e8759f54e906696f5772fee093283bcef7b930"
- + "aed50323bcbc8c820c67422c1e16bdc022a9c0277c9d95fef0ea4ee11e2b27276da811523c5acb80154989f8a67ee9e3fa30b73b0c1c34bf46e3464d97"
- + "7cd7fcd0ac3b82721080bb0d9b982ee2c77feee983d7ba35da88ce86955002940652ab63bc56fb16f994da2b01d74356509d7d1b6d7956b0e5a557757b"
- + "d1ced2eef8650bc5b6d426108c1518abcbd0befb6a0d5fd57a3e2dbf31458eab63df66613653d4beae73f5c40eb438fbcfdcf4a4ba46320184b9ca0da4"
- + "dfae77de7ccc910356caea3243f33a3c81b064b3b7cedc7435c223f664227215715980e6e0bb570d459ba80d7512dbe458c8f0f3f52d659b6e8eef19ee"
- + "71aea2ced85c7a42ffca6522a62db49a2a46eff72bd7f7e0883acd087183f0627f3537a4d558754ed63358e8182bee196735b361dc9bd64d5e34e1074a"
- + "855655d2974cc6fa1653754cf40f561d8c7dc526aab2908ec2d2b977cde1a1fb1071e32f40e049ea20f30368ba1592b4fe57fb51595d23acbdace324cd"
- + "d78060a17187c662368854e915402d9b52fb21e984663e41c26a109437e162cfaf071b53f77e50000a5388ff183b82ce7a1af476c416d7d204157b3633"
- + "b2f4ec077b699b032816997e37bceded8d4a04976fd7d0c0b029f290794c3be504c5242287ea2f831f11ed5690d92775cd6e863d7731fd4da687ebfb13"
- + "df4c41dc0fb8", "ae345d555eb04d6947bb95c0965237e2"),
- new TestCase(
- "76fb3635a2dc92a1f768163ab12f2187" + "cd07fd0ef8c0be0afcbdb30af4af0009",
- null,
- "f05204a74f0f88a7fa1a95b84ec3d8ffb36fcdc7723ea65dfe7cd464e86e0abf6b9d51db3220cfd8496ad6e6d36ebee8d990f9ce0d3bb7f72b7ab5b3ab0a73240d11efe772c857021ae859db4933cdde4387b471d2ce700fef4b81087f8f47c307881fd83017afcd15b8d21edf9b704677f46df97b07e5b83f87c8abd90af9b1d0f9e2710e8ebd0d4d1c6a055abea861f42368bed94d9373e909c1d3715b221c16bc524c55c31ec3eab204850bb2474a84f9917038eff9d921130951391b5c54f09b5e1de833ea2cd7d3b306740abb7096d1e173da83427da2adddd3631eda30b54dbf487f2b082e8646f07d6e0a87e97522ca38d4ace4954bf3db6dd3a93b06fa18eb56856627ed6cffcd7ae26374554ca18ab8905f26331d323fe10e6e70624c7bc07a70f06ecd804b48f8f7e75e910165e1beb554f1f0ec7949c9c8d429a206b4d5c0653102249b6098e6b45fac2a07ff0220b0b8ae8f4c6bcc0c813a7cd141fa8b398b42575fc395747c5a0257ac41d6c1f434cfbf5dfe8349f5347ef6b60e611f5d6c3cbc20ca2555274d1934325824cef4809da293ea13f181929e2af025bbd1c9abdc3af93afd4c50a2854ade3887f4d2c8c225168052c16e74d76d2dd3e9467a2c5b8e15c06ffbffa42b8536384139f07e195a8c9f70f514f31dca4eb2cf262c0dcbde53654b6250a29efe21d54e83c80e005a1cad36d5934ff01c32e4bc5fe06d03064ff4a268517df4a94c759289f323734318cfa5d859d4ce9c16e63d02dff0896976f521607638535d2ee8dd3312e1ddc80a55d34fe829ab954c1ebd54d929954770f1be9d32b4c05003c5c9e97943b6431e2afe820b1e967b19843e5985a131b1100517cdc363799104af91e2cf3f53cb8fd003653a6dd8a31a3f9d566a7124b0ffe9695bcb87c482eb60106f88198f766a40bc0f4873c23653c5f9e7a8e446f770beb8034cf01d21028ba15ccee21a8db918c4829d61c88bfa927bc5def831501796c5b401a60a6b1b433c9fb905c8cd40412fffee81ab",
- "045be28cc52009f506bdbfabedacf0b4"),
-
- };
-
- public String getName()
- {
- return "Poly1305";
- }
-
- public void performTest()
- throws Exception
- {
- testKeyGenerator();
- testInit();
- for (int i = 0; i < CASES.length; i++)
- {
- testCase(i);
- }
- testSequential();
- testReset();
- }
-
- private void testCase(int i)
- {
- byte[] out = new byte[16];
- TestCase tc = CASES[i];
-
- final Mac mac;
- if (tc.nonce == null)
- {
- // Raw Poly1305 test - don't do any transform on AES key part
- mac = new Poly1305(new KeyEngine(16));
- mac.init(new ParametersWithIV(new KeyParameter(tc.key), new byte[16]));
- }
- else
- {
- mac = new Poly1305(new AESFastEngine());
- mac.init(new ParametersWithIV(new KeyParameter(tc.key), tc.nonce));
- }
- mac.update(tc.message, 0, tc.message.length);
- mac.doFinal(out, 0);
-
- if (!Arrays.areEqual(out, tc.expectedMac))
- {
- fail("Mismatched output " + i, new String(Hex.encode(tc.expectedMac)), new String(Hex.encode(out)));
- }
- }
-
- private void testSequential()
- {
- // Sequential test, adapted from test-poly1305aes
- int len;
- byte[] kr = new byte[32];
- byte[] m = new byte[MAXLEN];
- byte[] n = new byte[16];
- byte[] out = new byte[16];
-
- int c = 0;
- final Mac mac = new Poly1305(new AESFastEngine());
- for (int loop = 0; loop < 13; loop++)
- {
- len = 0;
- for (;;)
- {
- c++;
- mac.init(new ParametersWithIV(new KeyParameter(kr), n));
- mac.update(m, 0, len);
- mac.doFinal(out, 0);
-
- // if (c == 678)
- // {
- // TestCase tc = CASES[0];
- //
- // if (!Arrays.areEqual(tc.key, kr))
- // {
- // System.err.println("Key bad");
- // System.err.println(new String(Hex.encode(tc.key)));
- // System.err.println(new String(Hex.encode(kr)));
- // System.exit(1);
- // }
- // if (!Arrays.areEqual(tc.nonce, n))
- // {
- // System.err.println("Nonce bad");
- // System.exit(1);
- // }
- // System.out.printf("[%d] m: %s\n", c, new String(Hex.encode(m, 0, len)));
- // System.out.printf("[%d] K: %s\n", c, new String(Hex.encodje(kr)));
- // System.out.printf("[%d] N: %s\n", c, new String(Hex.encode(n)));
- // System.out.printf("[%d] M: ", c);
- // }
- // System.out.printf("%d/%s\n", c, new String(Hex.encode(out)));
-
- if (len >= MAXLEN)
- break;
- n[0] ^= loop;
- for (int i = 0; i < 16; ++i)
- n[i] ^= out[i];
- if (len % 2 != 0)
- for (int i = 0; i < 16; ++i)
- kr[i] ^= out[i];
- if (len % 3 != 0)
- for (int i = 0; i < 16; ++i)
- kr[i + 16] ^= out[i];
- Poly1305KeyGenerator.clamp(kr);
- m[len++] ^= out[0];
- }
- }
- // Output after 13 loops as generated by poly1305 ref
- if (c != 13013 || !Arrays.areEqual(out, Hex.decode("c96f60a23701a5b0fd2016f58cbe4f7e")))
- {
- fail("Sequential Poly1305 " + c, "c96f60a23701a5b0fd2016f58cbe4f7e", new String(Hex.encode(out)));
- }
- }
-
- private void testReset()
- {
- CipherKeyGenerator gen = new Poly1305KeyGenerator();
- gen.init(new KeyGenerationParameters(new SecureRandom(), 256));
- byte[] k = gen.generateKey();
-
- byte[] m = new byte[10000];
- byte[] check = new byte[16];
- byte[] out = new byte[16];
-
- // Generate baseline
- Mac poly = new Poly1305(new AESFastEngine());
- poly.init(new ParametersWithIV(new KeyParameter(k), new byte[16]));
-
- poly.update(m, 0, m.length);
- poly.doFinal(check, 0);
-
- // Check reset after doFinal
- poly.update(m, 0, m.length);
- poly.doFinal(out, 0);
-
- if (!Arrays.areEqual(check, out))
- {
- fail("Mac not reset after doFinal");
- }
-
- // Check reset
- poly.update((byte)1);
- poly.update((byte)2);
- poly.reset();
- poly.update(m, 0, m.length);
- poly.doFinal(out, 0);
-
- if (!Arrays.areEqual(check, out))
- {
- fail("Mac not reset after doFinal");
- }
-
- // Check init resets
- poly.update((byte)1);
- poly.update((byte)2);
- poly.init(new ParametersWithIV(new KeyParameter(k), new byte[16]));
- poly.update(m, 0, m.length);
- poly.doFinal(out, 0);
-
- if (!Arrays.areEqual(check, out))
- {
- fail("Mac not reset after doFinal");
- }
- }
-
- private void testInit()
- {
- CipherKeyGenerator gen = new Poly1305KeyGenerator();
- gen.init(new KeyGenerationParameters(new SecureRandom(), 256));
- byte[] k = gen.generateKey();
-
- Mac poly = new Poly1305(new AESFastEngine());
- poly.init(new ParametersWithIV(new KeyParameter(k), new byte[16]));
-
- try
- {
- poly.init(new ParametersWithIV(new KeyParameter(k), new byte[15]));
- fail("16 byte nonce required");
- } catch (IllegalArgumentException e)
- {
- // Expected
- }
-
- try
- {
- byte[] k2 = new byte[k.length - 1];
- System.arraycopy(k, 0, k2, 0, k2.length);
- poly.init(new ParametersWithIV(new KeyParameter(k2), new byte[16]));
- fail("32 byte key required");
- } catch (IllegalArgumentException e)
- {
- // Expected
- }
-
- try
- {
- k[19] = (byte)0xFF;
- poly.init(new ParametersWithIV(new KeyParameter(k), new byte[16]));
- fail("Unclamped key should not be accepted.");
- } catch (IllegalArgumentException e)
- {
- // Expected
- }
-
- }
-
- private void testKeyGenerator()
- {
- CipherKeyGenerator gen = new Poly1305KeyGenerator();
- gen.init(new KeyGenerationParameters(new SecureRandom(), 256));
- byte[] k = gen.generateKey();
-
- if (k.length != 32)
- {
- fail("Poly1305 key should be 256 bits.");
- }
-
- try
- {
- Poly1305KeyGenerator.checkKey(k);
- } catch (IllegalArgumentException e)
- {
- fail("Poly1305 key should be clamped on generation.");
- }
-
- byte[] k2 = new byte[k.length];
- System.arraycopy(k, 0, k2, 0, k2.length);
- Poly1305KeyGenerator.clamp(k);
- if (!Arrays.areEqual(k, k2))
- {
- fail("Poly1305 key should be clamped on generation.");
- }
-
- try
- {
- k2[19] = (byte)0xff;
- Poly1305KeyGenerator.checkKey(k2);
- fail("Unclamped key should fail check.");
- } catch (IllegalArgumentException e)
- {
- // Expected
- }
- }
-
- public static void main(String[] args)
- throws Exception
- {
- runTest(new Poly1305Test());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/RC2Test.java b/core/src/test/java/org/bouncycastle/crypto/test/RC2Test.java
deleted file mode 100644
index 3c4e569b..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/RC2Test.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.engines.RC2Engine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.RC2Parameters;
-import org.bouncycastle.util.encoders.Hex;
-
-/**
- * RC2 tester - vectors from ftp://ftp.isi.edu/in-notes/rfc2268.txt
- *
- * RFC 2268 "A Description of the RC2(r) Encryption Algorithm"
- */
-public class RC2Test
- extends CipherTest
-{
- static BlockCipherVectorTest[] tests =
- {
- new BlockCipherVectorTest(0, new RC2Engine(),
- new RC2Parameters(Hex.decode("0000000000000000"), 63),
- "0000000000000000", "ebb773f993278eff"),
-
- new BlockCipherVectorTest(1, new RC2Engine(),
- new RC2Parameters(Hex.decode("ffffffffffffffff"), 64),
- "ffffffffffffffff", "278b27e42e2f0d49"),
-
- new BlockCipherVectorTest(2, new RC2Engine(),
- new RC2Parameters(Hex.decode("3000000000000000"), 64),
- "1000000000000001", "30649edf9be7d2c2"),
-
- new BlockCipherVectorTest(3, new RC2Engine(),
- new RC2Parameters(Hex.decode("88"), 64),
- "0000000000000000", "61a8a244adacccf0"),
-
- new BlockCipherVectorTest(4, new RC2Engine(),
- new RC2Parameters(Hex.decode("88bca90e90875a"), 64),
- "0000000000000000", "6ccf4308974c267f"),
-
- new BlockCipherVectorTest(5, new RC2Engine(),
- new RC2Parameters(Hex.decode("88bca90e90875a7f0f79c384627bafb2"), 64),
- "0000000000000000", "1a807d272bbe5db1"),
-
- new BlockCipherVectorTest(6, new RC2Engine(),
- new RC2Parameters(Hex.decode("88bca90e90875a7f0f79c384627bafb2"), 128),
- "0000000000000000", "2269552ab0f85ca6"),
-
- new BlockCipherVectorTest(7, new RC2Engine(),
- new RC2Parameters(Hex.decode("88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e"), 129),
- "0000000000000000", "5b78d3a43dfff1f1")
- };
-
- RC2Test()
- {
- super(tests, new RC2Engine(), new KeyParameter(new byte[16]));
- }
-
- public String getName()
- {
- return "RC2";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new RC2Test());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/RC2WrapTest.java b/core/src/test/java/org/bouncycastle/crypto/test/RC2WrapTest.java
deleted file mode 100644
index 0b52a60b..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/RC2WrapTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Wrapper;
-import org.bouncycastle.crypto.engines.RC2WrapEngine;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.params.RC2Parameters;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-/**
- * RC2 wrap tester
- */
-public class RC2WrapTest
- implements Test
-{
- private class RFCRandom
- extends SecureRandom
- {
- public void nextBytes(
- byte[] nextBytes)
- {
- System.arraycopy(Hex.decode("4845cce7fd1250"), 0, nextBytes, 0, nextBytes.length);
- }
- }
-
- private TestResult wrapTest(
- int id,
- CipherParameters paramsWrap,
- CipherParameters paramsUnwrap,
- byte[] in,
- byte[] out)
- {
- Wrapper wrapper = new RC2WrapEngine();
-
- wrapper.init(true, paramsWrap);
-
- try
- {
- byte[] cText = wrapper.wrap(in, 0, in.length);
- if (!Arrays.areEqual(cText, out))
- {
- return new SimpleTestResult(false, getName() + ": failed wrap test " + id + " expected " + new String(Hex.encode(out)) + " got " + new String(Hex.encode(cText)));
- }
- }
- catch (Exception e)
- {
- return new SimpleTestResult(false, getName() + ": failed wrap test exception " + e.toString(), e);
- }
-
- wrapper.init(false, paramsUnwrap);
-
- try
- {
- byte[] pText = wrapper.unwrap(out, 0, out.length);
- if (!Arrays.areEqual(pText, in))
- {
- return new SimpleTestResult(false, getName() + ": failed unwrap test " + id + " expected " + new String(Hex.encode(in)) + " got " + new String(Hex.encode(pText)));
- }
- }
- catch (Exception e)
- {
- return new SimpleTestResult(false, getName() + ": failed unwrap test exception " + e.toString(), e);
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
-
- public TestResult perform()
- {
- byte[] kek1 = Hex.decode("fd04fd08060707fb0003fefffd02fe05");
- byte[] iv1 = Hex.decode("c7d90059b29e97f7");
- byte[] in1 = Hex.decode("b70a25fbc9d86a86050ce0d711ead4d9");
- byte[] out1 = Hex.decode("70e699fb5701f7833330fb71e87c85a420bdc99af05d22af5a0e48d35f3138986cbaafb4b28d4f35");
- //
- // note the RFC 3217 test specifies a key to be used with an effective key size of
- // 40 bits which is why it is done here - in practice nothing less than 128 bits should be used.
- //
- CipherParameters paramWrap = new ParametersWithRandom(new ParametersWithIV(new RC2Parameters(kek1, 40), iv1), new RFCRandom());
- CipherParameters paramUnwrap = new RC2Parameters(kek1, 40);
-
- TestResult result = wrapTest(1, paramWrap, paramUnwrap, in1, out1);
-
- if (!result.isSuccessful())
- {
- return result;
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
-
- public String getName()
- {
- return "RC2Wrap";
- }
-
- public static void main(
- String[] args)
- {
- RC2WrapTest test = new RC2WrapTest();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/RC4Test.java b/core/src/test/java/org/bouncycastle/crypto/test/RC4Test.java
deleted file mode 100644
index e4d39743..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/RC4Test.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.engines.RC4Engine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * RC4 Test
- */
-public class RC4Test
- extends SimpleTest
-{
- StreamCipherVectorTest[] tests =
- {
- new StreamCipherVectorTest(0, new RC4Engine(),
- new KeyParameter(Hex.decode("0123456789ABCDEF")),
- "4e6f772069732074", "3afbb5c77938280d"),
- new StreamCipherVectorTest(0, new RC4Engine(),
- new KeyParameter(Hex.decode("0123456789ABCDEF")),
- "68652074696d6520", "1cf1e29379266d59"),
- new StreamCipherVectorTest(0, new RC4Engine(),
- new KeyParameter(Hex.decode("0123456789ABCDEF")),
- "666f7220616c6c20", "12fbb0c771276459")
- };
-
- public String getName()
- {
- return "RC4";
- }
-
- public void performTest()
- {
- for (int i = 0; i != tests.length; i++)
- {
- tests[i].performTest();
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new RC4Test());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/RC5Test.java b/core/src/test/java/org/bouncycastle/crypto/test/RC5Test.java
deleted file mode 100644
index 0ffdc89a..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/RC5Test.java
+++ /dev/null
@@ -1,188 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.engines.RC532Engine;
-import org.bouncycastle.crypto.engines.RC564Engine;
-import org.bouncycastle.crypto.modes.CBCBlockCipher;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.crypto.params.RC5Parameters;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-/**
- * RC5 tester - vectors from ftp://ftp.nordu.net/rfc/rfc2040.txt
- *
- * RFC 2040 "The RC5, RC5-CBC, RC5-CBC-Pad, and RC5-CTS Algorithms"
- */
-public class RC5Test
- implements Test
-{
- BlockCipherVectorTest[] tests =
- {
- new BlockCipherVectorTest(0, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("00"), 0),
- Hex.decode("0000000000000000")),
- "0000000000000000", "7a7bba4d79111d1e"),
- new BlockCipherVectorTest(1, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("00"), 0),
- Hex.decode("0000000000000000")),
- "ffffffffffffffff", "797bba4d78111d1e"),
- new BlockCipherVectorTest(2, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("00"), 0),
- Hex.decode("0000000000000001")),
- "0000000000000000", "7a7bba4d79111d1f"),
- new BlockCipherVectorTest(3, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("00"), 0),
- Hex.decode("0000000000000000")),
- "0000000000000001", "7a7bba4d79111d1f"),
- new BlockCipherVectorTest(4, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("00"), 0),
- Hex.decode("0102030405060708")),
- "1020304050607080", "8b9ded91ce7794a6"),
- new BlockCipherVectorTest(5, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("11"), 1),
- Hex.decode("0000000000000000")),
- "0000000000000000", "2f759fe7ad86a378"),
- new BlockCipherVectorTest(6, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("00"), 2),
- Hex.decode("0000000000000000")),
- "0000000000000000", "dca2694bf40e0788"),
- new BlockCipherVectorTest(7, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("00000000"), 2),
- Hex.decode("0000000000000000")),
- "0000000000000000", "dca2694bf40e0788"),
- new BlockCipherVectorTest(8, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("00000000"), 8),
- Hex.decode("0000000000000000")),
- "0000000000000000", "dcfe098577eca5ff"),
- new BlockCipherVectorTest(9, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("00"), 8),
- Hex.decode("0102030405060708")),
- "1020304050607080", "9646fb77638f9ca8"),
- new BlockCipherVectorTest(10, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("00"), 12),
- Hex.decode("0102030405060708")),
- "1020304050607080", "b2b3209db6594da4"),
- new BlockCipherVectorTest(11, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("00"), 16),
- Hex.decode("0102030405060708")),
- "1020304050607080", "545f7f32a5fc3836"),
- new BlockCipherVectorTest(12, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("01020304"), 8),
- Hex.decode("0000000000000000")),
- "ffffffffffffffff", "8285e7c1b5bc7402"),
- new BlockCipherVectorTest(13, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("01020304"), 12),
- Hex.decode("0000000000000000")),
- "ffffffffffffffff", "fc586f92f7080934"),
- new BlockCipherVectorTest(14, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("01020304"), 16),
- Hex.decode("0000000000000000")),
- "ffffffffffffffff", "cf270ef9717ff7c4"),
- new BlockCipherVectorTest(15, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("0102030405060708"), 12),
- Hex.decode("0000000000000000")),
- "ffffffffffffffff", "e493f1c1bb4d6e8c"),
- new BlockCipherVectorTest(16, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("0102030405060708"), 8),
- Hex.decode("0102030405060708")),
- "1020304050607080", "5c4c041e0f217ac3"),
- new BlockCipherVectorTest(17, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("0102030405060708"), 12),
- Hex.decode("0102030405060708")),
- "1020304050607080", "921f12485373b4f7"),
- new BlockCipherVectorTest(18, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("0102030405060708"), 16),
- Hex.decode("0102030405060708")),
- "1020304050607080", "5ba0ca6bbe7f5fad"),
- new BlockCipherVectorTest(19, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("01020304050607081020304050607080"), 8),
- Hex.decode("0102030405060708")),
- "1020304050607080", "c533771cd0110e63"),
- new BlockCipherVectorTest(20, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("01020304050607081020304050607080"), 12),
- Hex.decode("0102030405060708")),
- "1020304050607080", "294ddb46b3278d60"),
- new BlockCipherVectorTest(21, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("01020304050607081020304050607080"), 16),
- Hex.decode("0102030405060708")),
- "1020304050607080", "dad6bda9dfe8f7e8"),
- new BlockCipherVectorTest(22, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("0102030405"), 12),
- Hex.decode("0000000000000000")),
- "ffffffffffffffff", "97e0787837ed317f"),
- new BlockCipherVectorTest(23, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("0102030405"), 8),
- Hex.decode("0000000000000000")),
- "ffffffffffffffff", "7875dbf6738c6478"),
- new BlockCipherVectorTest(23, new CBCBlockCipher(new RC532Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("0102030405"), 8),
- Hex.decode("7875dbf6738c6478")),
- "0808080808080808", "8f34c3c681c99695"),
- new BlockCipherVectorTest(640, new CBCBlockCipher(new RC564Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("00"), 0),
- Hex.decode("00000000000000000000000000000000")),
- "00000000000000000000000000000000", "9f09b98d3f6062d9d4d59973d00e0e63"),
- new BlockCipherVectorTest(641, new CBCBlockCipher(new RC564Engine()),
- new ParametersWithIV(
- new RC5Parameters(Hex.decode("00"), 0),
- Hex.decode("00000000000000000000000000000000")),
- "ffffffffffffffffffffffffffffffff", "9e09b98d3f6062d9d3d59973d00e0e63")
- };
-
- public String getName()
- {
- return "RC5";
- }
-
- public TestResult perform()
- {
- for (int i = 0; i != tests.length; i++)
- {
- TestResult res = tests[i].perform();
-
- if (!res.isSuccessful())
- {
- return res;
- }
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
-
- public static void main(
- String[] args)
- {
- RC5Test test = new RC5Test();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/RC6Test.java b/core/src/test/java/org/bouncycastle/crypto/test/RC6Test.java
deleted file mode 100644
index 254c1378..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/RC6Test.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.engines.RC6Engine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * RC6 Test - test vectors from AES Submitted RSA Reference implementation.
- * ftp://ftp.funet.fi/pub/crypt/cryptography/symmetric/aes/rc6-unix-refc.tar
- */
-public class RC6Test
- extends CipherTest
-{
- static SimpleTest[] tests =
- {
- new BlockCipherVectorTest(0, new RC6Engine(),
- new KeyParameter(
- Hex.decode("00000000000000000000000000000000")),
- "80000000000000000000000000000000",
- "f71f65e7b80c0c6966fee607984b5cdf"),
- new BlockCipherVectorTest(1, new RC6Engine(),
- new KeyParameter(
- Hex.decode("000000000000000000000000000000008000000000000000")),
- "00000000000000000000000000000000",
- "dd04c176440bbc6686c90aee775bd368"),
- new BlockCipherVectorTest(2, new RC6Engine(),
- new KeyParameter(
- Hex.decode("000000000000000000000000000000000000001000000000")),
- "00000000000000000000000000000000",
- "937fe02d20fcb72f0f57201012b88ba4"),
- new BlockCipherVectorTest(3, new RC6Engine(),
- new KeyParameter(
- Hex.decode("00000001000000000000000000000000")),
- "00000000000000000000000000000000",
- "8a380594d7396453771a1dfbe2914c8e"),
- new BlockCipherVectorTest(4, new RC6Engine(),
- new KeyParameter(
- Hex.decode("1000000000000000000000000000000000000000000000000000000000000000")),
- "00000000000000000000000000000000",
- "11395d4bfe4c8258979ee2bf2d24dff4"),
- new BlockCipherVectorTest(5, new RC6Engine(),
- new KeyParameter(
- Hex.decode("0000000000000000000000000000000000080000000000000000000000000000")),
- "00000000000000000000000000000000",
- "3d6f7e99f6512553bb983e8f75672b97")
- };
-
- RC6Test()
- {
- super(tests, new RC6Engine(), new KeyParameter(new byte[32]));
- }
-
- public String getName()
- {
- return "RC6";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new RC6Test());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/RFC3211WrapTest.java b/core/src/test/java/org/bouncycastle/crypto/test/RFC3211WrapTest.java
deleted file mode 100644
index f556cff6..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/RFC3211WrapTest.java
+++ /dev/null
@@ -1,220 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.Wrapper;
-import org.bouncycastle.crypto.engines.DESEngine;
-import org.bouncycastle.crypto.engines.DESedeEngine;
-import org.bouncycastle.crypto.engines.RFC3211WrapEngine;
-import org.bouncycastle.crypto.modes.CBCBlockCipher;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-import java.security.SecureRandom;
-
-/**
- * Wrap Test based on RFC3211 test vectors
- */
-public class RFC3211WrapTest
- extends SimpleTest
-{
- SecureRandom r1 = new SecureRandom()
- {
- int[] ints = { 0xC4, 0x36, 0xF5, 0x41 };
- int count = 0;
-
- public int nextInt()
- {
- return ints[count++];
- }
- };
-
- SecureRandom r2 = new SecureRandom()
- {
- int[] ints = { 0xFA, 0x06, 0x0A, 0x45 };
- int count = 0;
-
- public int nextInt()
- {
- return ints[count++];
- }
- };
-
- public String getName()
- {
- return "RFC3211Wrap";
- }
-
- private void wrapTest(
- int id,
- BlockCipher engine,
- byte[] kek,
- byte[] iv,
- SecureRandom rand,
- byte[] in,
- byte[] out)
- throws Exception
- {
- Wrapper wrapper = new RFC3211WrapEngine(engine);
-
- wrapper.init(true, new ParametersWithRandom(new ParametersWithIV(new KeyParameter(kek), iv), rand));
-
- byte[] cText = wrapper.wrap(in, 0, in.length);
- if (!Arrays.areEqual(cText, out))
- {
- fail("failed wrap test " + id + " expected " + new String(Hex.encode(out)) + " got " + new String(Hex.encode(cText)));
- }
-
- wrapper.init(false, new ParametersWithIV(new KeyParameter(kek), iv));
-
- byte[] pText = wrapper.unwrap(out, 0, out.length);
- if (!Arrays.areEqual(pText, in))
- {
- fail("rfailed unwrap test " + id + " expected " + new String(Hex.encode(in)) + " got " + new String(Hex.encode(pText)));
- }
- }
-
- private void testCorruption()
- throws InvalidCipherTextException
- {
- byte[] kek = Hex.decode("D1DAA78615F287E6");
- byte[] iv = Hex.decode("EFE598EF21B33D6D");
-
- Wrapper wrapper = new RFC3211WrapEngine(new DESEngine());
-
- wrapper.init(false, new ParametersWithIV(new KeyParameter(kek), iv));
-
- byte[] block = Hex.decode("ff739D838C627C897323A2F8C436F541");
- encryptBlock(kek, iv, block);
-
- try
- {
- wrapper.unwrap(block, 0, block.length);
-
- fail("bad length not detected");
- }
- catch (InvalidCipherTextException e)
- {
- if (!e.getMessage().equals("wrapped key corrupted"))
- {
- fail("wrong exception on length");
- }
- }
-
- block = Hex.decode("08639D838C627C897323A2F8C436F541");
- testChecksum(kek, iv, block, wrapper);
-
- block = Hex.decode("08736D838C627C897323A2F8C436F541");
- testChecksum(kek, iv, block, wrapper);
-
- block = Hex.decode("08739D638C627C897323A2F8C436F541");
- testChecksum(kek, iv, block, wrapper);
- }
-
- private void testChecksum(byte[] kek, byte[] iv, byte[] block, Wrapper wrapper)
- {
- encryptBlock(kek, iv, block);
-
- try
- {
- wrapper.unwrap(block, 0, block.length);
-
- fail("bad checksum not detected");
- }
- catch (InvalidCipherTextException e)
- {
- if (!e.getMessage().equals("wrapped key fails checksum"))
- {
- fail("wrong exception");
- }
- }
- }
-
- private void encryptBlock(byte[] key, byte[] iv, byte[] cekBlock)
- {
- BlockCipher engine = new CBCBlockCipher(new DESEngine());
-
- engine.init(true, new ParametersWithIV(new KeyParameter(key), iv));
-
- for (int i = 0; i < cekBlock.length; i += 8)
- {
- engine.processBlock(cekBlock, i, cekBlock, i);
- }
-
- for (int i = 0; i < cekBlock.length; i += 8)
- {
- engine.processBlock(cekBlock, i, cekBlock, i);
- }
- }
-
- public void performTest()
- throws Exception
- {
- wrapTest(1, new DESEngine(), Hex.decode("D1DAA78615F287E6"), Hex.decode("EFE598EF21B33D6D"), r1, Hex.decode("8C627C897323A2F8"), Hex.decode("B81B2565EE373CA6DEDCA26A178B0C10"));
- wrapTest(2, new DESedeEngine(), Hex.decode("6A8970BF68C92CAEA84A8DF28510858607126380CC47AB2D"), Hex.decode("BAF1CA7931213C4E"), r2,
- Hex.decode("8C637D887223A2F965B566EB014B0FA5D52300A3F7EA40FFFC577203C71BAF3B"),
- Hex.decode("C03C514ABDB9E2C5AAC038572B5E24553876B377AAFB82ECA5A9D73F8AB143D9EC74E6CAD7DB260C"));
-
- testCorruption();
-
- Wrapper wrapper = new RFC3211WrapEngine(new DESEngine());
- ParametersWithIV params = new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]);
- byte[] buf = new byte[16];
-
- try
- {
- wrapper.init(true, params);
-
- wrapper.unwrap(buf, 0, buf.length);
-
- fail("failed unwrap state test.");
- }
- catch (IllegalStateException e)
- {
- // expected
- }
- catch (InvalidCipherTextException e)
- {
- fail("unexpected exception: " + e, e);
- }
-
- try
- {
- wrapper.init(false, params);
-
- wrapper.wrap(buf, 0, buf.length);
-
- fail("failed unwrap state test.");
- }
- catch (IllegalStateException e)
- {
- // expected
- }
-
- //
- // short test
- //
- try
- {
- wrapper.init(false, params);
-
- wrapper.unwrap(buf, 0, buf.length / 2);
-
- fail("failed unwrap short test.");
- }
- catch (InvalidCipherTextException e)
- {
- // expected
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new RFC3211WrapTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/RIPEMD128DigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/RIPEMD128DigestTest.java
deleted file mode 100644
index bdd622ca..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/RIPEMD128DigestTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.RIPEMD128Digest;
-
-/**
- * RIPEMD128 Digest Test
- */
-public class RIPEMD128DigestTest
- extends DigestTest
-{
- final static String[] messages = {
- "",
- "a",
- "abc",
- "message digest",
- "abcdefghijklmnopqrstuvwxyz",
- "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
- "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
- };
-
- final static String[] digests = {
- "cdf26213a150dc3ecb610f18f6b38b46",
- "86be7afa339d0fc7cfc785e72f578d33",
- "c14a12199c66e4ba84636b0f69144c77",
- "9e327b3d6e523062afc1132d7df9d1b8",
- "fd2aa607f71dc8f510714922b371834e",
- "a1aa0689d0fafa2ddc22e88b49133a06",
- "d1e959eb179c911faea4624c60c5c702",
- "3f45ef194732c2dbb2c4a2c769795fa3"
- };
-
- final static String million_a_digest = "4a7f5723f954eba1216c9d8f6320431f";
-
- RIPEMD128DigestTest()
- {
- super(new RIPEMD128Digest(), messages, digests);
- }
-
- public void performTest()
- {
- super.performTest();
-
- millionATest(million_a_digest);
- }
-
- protected Digest cloneDigest(Digest digest)
- {
- return new RIPEMD128Digest((RIPEMD128Digest)digest);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new RIPEMD128DigestTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/RIPEMD128HMacTest.java b/core/src/test/java/org/bouncycastle/crypto/test/RIPEMD128HMacTest.java
deleted file mode 100644
index cc042c91..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/RIPEMD128HMacTest.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.digests.RIPEMD128Digest;
-import org.bouncycastle.crypto.macs.HMac;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-/**
- * RIPEMD128 HMac Test, test vectors from RFC 2286
- */
-public class RIPEMD128HMacTest
- implements Test
-{
- final static String[] keys = {
- "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
- "4a656665",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
- "0102030405060708090a0b0c0d0e0f10111213141516171819",
- "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- };
-
- final static String[] digests = {
- "fbf61f9492aa4bbf81c172e84e0734db",
- "875f828862b6b334b427c55f9f7ff09b",
- "09f0b2846d2f543da363cbec8d62a38d",
- "bdbbd7cf03e44b5aa60af815be4d2294",
- "e79808f24b25fd031c155f0d551d9a3a",
- "dc732928de98104a1f59d373c150acbb",
- "5c6bec96793e16d40690c237635f30c5"
- };
-
- final static String[] messages = {
- "Hi There",
- "what do ya want for nothing?",
- "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
- "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
- "Test With Truncation",
- "Test Using Larger Than Block-Size Key - Hash Key First",
- "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
- };
-
- public String getName()
- {
- return "RIPEMD128HMac";
- }
-
- public TestResult perform()
- {
- HMac hmac = new HMac(new RIPEMD128Digest());
- byte[] resBuf = new byte[hmac.getMacSize()];
-
- for (int i = 0; i < messages.length; i++)
- {
- byte[] m = messages[i].getBytes();
- if (messages[i].startsWith("0x"))
- {
- m = Hex.decode(messages[i].substring(2));
- }
- hmac.init(new KeyParameter(Hex.decode(keys[i])));
- hmac.update(m, 0, m.length);
- hmac.doFinal(resBuf, 0);
-
- if (!Arrays.areEqual(resBuf, Hex.decode(digests[i])))
- {
- return new SimpleTestResult(false, getName() + ": Vector " + i + " failed");
- }
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
-
- public static void main(
- String[] args)
- {
- RIPEMD128HMacTest test = new RIPEMD128HMacTest();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/RIPEMD160DigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/RIPEMD160DigestTest.java
deleted file mode 100644
index e92693d2..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/RIPEMD160DigestTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.RIPEMD160Digest;
-
-/**
- * RIPEMD160 Digest Test
- */
-public class RIPEMD160DigestTest
- extends DigestTest
-{
- final static String[] messages = {
- "",
- "a",
- "abc",
- "message digest",
- "abcdefghijklmnopqrstuvwxyz",
- "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
- "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
- };
-
- final static String[] digests = {
- "9c1185a5c5e9fc54612808977ee8f548b2258d31",
- "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe",
- "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc",
- "5d0689ef49d2fae572b881b123a85ffa21595f36",
- "f71c27109c692c1b56bbdceb5b9d2865b3708dbc",
- "12a053384a9c0c88e405a06c27dcf49ada62eb2b",
- "b0e20b6e3116640286ed3a87a5713079b21f5189",
- "9b752e45573d4b39f4dbd3323cab82bf63326bfb"
- };
-
- final static String million_a_digest = "52783243c1697bdbe16d37f97f68f08325dc1528";
-
- RIPEMD160DigestTest()
- {
- super(new RIPEMD160Digest(), messages, digests);
- }
-
- public void performTest()
- {
- super.performTest();
-
- millionATest(million_a_digest);
- }
-
- protected Digest cloneDigest(Digest digest)
- {
- return new RIPEMD160Digest((RIPEMD160Digest)digest);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new RIPEMD160DigestTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/RIPEMD160HMacTest.java b/core/src/test/java/org/bouncycastle/crypto/test/RIPEMD160HMacTest.java
deleted file mode 100644
index 7e6e8132..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/RIPEMD160HMacTest.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.digests.RIPEMD160Digest;
-import org.bouncycastle.crypto.macs.HMac;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-/**
- * RIPEMD160 HMac Test, test vectors from RFC 2286
- */
-public class RIPEMD160HMacTest
- implements Test
-{
- final static String[] keys = {
- "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
- "4a656665",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
- "0102030405060708090a0b0c0d0e0f10111213141516171819",
- "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- };
-
- final static String[] digests = {
- "24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668",
- "dda6c0213a485a9e24f4742064a7f033b43c4069",
- "b0b105360de759960ab4f35298e116e295d8e7c1",
- "d5ca862f4d21d5e610e18b4cf1beb97a4365ecf4",
- "7619693978f91d90539ae786500ff3d8e0518e39",
- "6466ca07ac5eac29e1bd523e5ada7605b791fd8b",
- "69ea60798d71616cce5fd0871e23754cd75d5a0a"
- };
-
- final static String[] messages = {
- "Hi There",
- "what do ya want for nothing?",
- "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
- "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
- "Test With Truncation",
- "Test Using Larger Than Block-Size Key - Hash Key First",
- "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
- };
-
- public String getName()
- {
- return "RIPEMD160HMac";
- }
-
- public TestResult perform()
- {
- HMac hmac = new HMac(new RIPEMD160Digest());
- byte[] resBuf = new byte[hmac.getMacSize()];
-
- for (int i = 0; i < messages.length; i++)
- {
- byte[] m = messages[i].getBytes();
- if (messages[i].startsWith("0x"))
- {
- m = Hex.decode(messages[i].substring(2));
- }
- hmac.init(new KeyParameter(Hex.decode(keys[i])));
- hmac.update(m, 0, m.length);
- hmac.doFinal(resBuf, 0);
-
- if (!Arrays.areEqual(resBuf, Hex.decode(digests[i])))
- {
- return new SimpleTestResult(false, getName() + ": Vector " + i + " failed");
- }
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
-
- public static void main(
- String[] args)
- {
- RIPEMD160HMacTest test = new RIPEMD160HMacTest();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/RIPEMD256DigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/RIPEMD256DigestTest.java
deleted file mode 100644
index 4de70d8e..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/RIPEMD256DigestTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.RIPEMD256Digest;
-
-/**
- * RIPEMD128 Digest Test
- */
-public class RIPEMD256DigestTest
- extends DigestTest
-{
- final static String[] messages = {
- "",
- "a",
- "abc",
- "message digest",
- "abcdefghijklmnopqrstuvwxyz",
- "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
- "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
- };
-
- final static String[] digests = {
- "02ba4c4e5f8ecd1877fc52d64d30e37a2d9774fb1e5d026380ae0168e3c5522d",
- "f9333e45d857f5d90a91bab70a1eba0cfb1be4b0783c9acfcd883a9134692925",
- "afbd6e228b9d8cbbcef5ca2d03e6dba10ac0bc7dcbe4680e1e42d2e975459b65",
- "87e971759a1ce47a514d5c914c392c9018c7c46bc14465554afcdf54a5070c0e",
- "649d3034751ea216776bf9a18acc81bc7896118a5197968782dd1fd97d8d5133",
- "3843045583aac6c8c8d9128573e7a9809afb2a0f34ccc36ea9e72f16f6368e3f",
- "5740a408ac16b720b84424ae931cbb1fe363d1d0bf4017f1a89f7ea6de77a0b8",
- "06fdcc7a409548aaf91368c06a6275b553e3f099bf0ea4edfd6778df89a890dd"
- };
-
- final static String million_a_digest = "ac953744e10e31514c150d4d8d7b677342e33399788296e43ae4850ce4f97978";
-
- RIPEMD256DigestTest()
- {
- super(new RIPEMD256Digest(), messages, digests);
- }
-
- public void performTest()
- {
- super.performTest();
-
- millionATest(million_a_digest);
- }
-
- protected Digest cloneDigest(Digest digest)
- {
- return new RIPEMD256Digest((RIPEMD256Digest)digest);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new RIPEMD256DigestTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/RIPEMD320DigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/RIPEMD320DigestTest.java
deleted file mode 100644
index 351b1b74..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/RIPEMD320DigestTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.RIPEMD320Digest;
-
-/**
- * RIPEMD320 Digest Test
- */
-public class RIPEMD320DigestTest
- extends DigestTest
-{
- final static String[] messages = {
- "",
- "a",
- "abc",
- "message digest",
- "abcdefghijklmnopqrstuvwxyz",
- "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
- "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
- };
-
- final static String[] digests = {
- "22d65d5661536cdc75c1fdf5c6de7b41b9f27325ebc61e8557177d705a0ec880151c3a32a00899b8",
- "ce78850638f92658a5a585097579926dda667a5716562cfcf6fbe77f63542f99b04705d6970dff5d",
- "de4c01b3054f8930a79d09ae738e92301e5a17085beffdc1b8d116713e74f82fa942d64cdbc4682d",
- "3a8e28502ed45d422f68844f9dd316e7b98533fa3f2a91d29f84d425c88d6b4eff727df66a7c0197",
- "cabdb1810b92470a2093aa6bce05952c28348cf43ff60841975166bb40ed234004b8824463e6b009",
- "d034a7950cf722021ba4b84df769a5de2060e259df4c9bb4a4268c0e935bbc7470a969c9d072a1ac",
- "ed544940c86d67f250d232c30b7b3e5770e0c60c8cb9a4cafe3b11388af9920e1b99230b843c86a4",
- "557888af5f6d8ed62ab66945c6d2a0a47ecd5341e915eb8fea1d0524955f825dc717e4a008ab2d42"
- };
-
- final static String million_a_digest = "bdee37f4371e20646b8b0d862dda16292ae36f40965e8c8509e63d1dbddecc503e2b63eb9245bb66";
-
- RIPEMD320DigestTest()
- {
- super(new RIPEMD320Digest(), messages, digests);
- }
-
- public void performTest()
- {
- super.performTest();
-
- millionATest(million_a_digest);
- }
-
- protected Digest cloneDigest(Digest digest)
- {
- return new RIPEMD320Digest((RIPEMD320Digest)digest);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new RIPEMD320DigestTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/RSABlindedTest.java b/core/src/test/java/org/bouncycastle/crypto/test/RSABlindedTest.java
deleted file mode 100644
index 7cb6e98a..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/RSABlindedTest.java
+++ /dev/null
@@ -1,437 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.encodings.OAEPEncoding;
-import org.bouncycastle.crypto.encodings.PKCS1Encoding;
-import org.bouncycastle.crypto.engines.RSABlindedEngine;
-import org.bouncycastle.crypto.generators.RSAKeyPairGenerator;
-import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-public class RSABlindedTest
- extends SimpleTest
-{
- static BigInteger mod = new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16);
- static BigInteger pubExp = new BigInteger("11", 16);
- static BigInteger privExp = new BigInteger("92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619", 16);
- static BigInteger p = new BigInteger("f75e80839b9b9379f1cf1128f321639757dba514642c206bbbd99f9a4846208b3e93fbbe5e0527cc59b1d4b929d9555853004c7c8b30ee6a213c3d1bb7415d03", 16);
- static BigInteger q = new BigInteger("b892d9ebdbfc37e397256dd8a5d3123534d1f03726284743ddc6be3a709edb696fc40c7d902ed804c6eee730eee3d5b20bf6bd8d87a296813c87d3b3cc9d7947", 16);
- static BigInteger pExp = new BigInteger("1d1a2d3ca8e52068b3094d501c9a842fec37f54db16e9a67070a8b3f53cc03d4257ad252a1a640eadd603724d7bf3737914b544ae332eedf4f34436cac25ceb5", 16);
- static BigInteger qExp = new BigInteger("6c929e4e81672fef49d9c825163fec97c4b7ba7acb26c0824638ac22605d7201c94625770984f78a56e6e25904fe7db407099cad9b14588841b94f5ab498dded", 16);
- static BigInteger crtCoef = new BigInteger("dae7651ee69ad1d081ec5e7188ae126f6004ff39556bde90e0b870962fa7b926d070686d8244fe5a9aa709a95686a104614834b0ada4b10f53197a5cb4c97339", 16);
-
- static String input = "4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
-
- //
- // to check that we handling byte extension by big number correctly.
- //
- static String edgeInput = "ff6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
-
- static byte[] oversizedSig = Hex.decode("01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
- static byte[] dudBlock = Hex.decode("000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
- static byte[] truncatedDataBlock = Hex.decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
- static byte[] incorrectPadding = Hex.decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
- static byte[] missingDataBlock = Hex.decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
-
- public String getName()
- {
- return "RSABlinded";
- }
-
- private void testStrictPKCS1Length(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
- {
- AsymmetricBlockCipher eng = new RSABlindedEngine();
-
- eng.init(true, privParameters);
-
- byte[] data = null;
-
- try
- {
- data = eng.processBlock(oversizedSig, 0, oversizedSig.length);
- }
- catch (Exception e)
- {
- fail("RSA: failed - exception " + e.toString(), e);
- }
-
- eng = new PKCS1Encoding(eng);
-
- eng.init(false, pubParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
-
- fail("oversized signature block not recognised");
- }
- catch (InvalidCipherTextException e)
- {
- if (!e.getMessage().equals("block incorrect size"))
- {
- fail("RSA: failed - exception " + e.toString(), e);
- }
- }
-
- //System.setProperty(PKCS1Encoding.STRICT_LENGTH_ENABLED_PROPERTY, "false");
-
- System.getProperties().put(PKCS1Encoding.STRICT_LENGTH_ENABLED_PROPERTY, "false");
- eng = new PKCS1Encoding(new RSABlindedEngine());
-
- eng.init(false, pubParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (InvalidCipherTextException e)
- {
- fail("RSA: failed - exception " + e.toString(), e);
- }
-
- System.getProperties().remove(PKCS1Encoding.STRICT_LENGTH_ENABLED_PROPERTY);
- }
-
- private void testTruncatedPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
- {
- checkForPKCS1Exception(pubParameters, privParameters, truncatedDataBlock, "block truncated");
- }
-
- private void testDudPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
- {
- checkForPKCS1Exception(pubParameters, privParameters, dudBlock, "unknown block type");
- }
-
- private void testWrongPaddingPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
- {
- checkForPKCS1Exception(pubParameters, privParameters, incorrectPadding, "block padding incorrect");
- }
-
- private void testMissingDataPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
- {
- checkForPKCS1Exception(pubParameters, privParameters, missingDataBlock, "no data in block");
- }
-
- private void checkForPKCS1Exception(RSAKeyParameters pubParameters, RSAKeyParameters privParameters, byte[] inputData, String expectedMessage)
- {
- AsymmetricBlockCipher eng = new RSABlindedEngine();
-
- eng.init(true, privParameters);
-
- byte[] data = null;
-
- try
- {
- data = eng.processBlock(inputData, 0, inputData.length);
- }
- catch (Exception e)
- {
- fail("RSA: failed - exception " + e.toString(), e);
- }
-
- eng = new PKCS1Encoding(eng);
-
- eng.init(false, pubParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
-
- fail("missing data block not recognised");
- }
- catch (InvalidCipherTextException e)
- {
- if (!e.getMessage().equals(expectedMessage))
- {
- fail("RSA: failed - exception " + e.toString(), e);
- }
- }
- }
-
- private void testOAEP(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
- {
- //
- // OAEP - public encrypt, private decrypt
- //
- AsymmetricBlockCipher eng = new OAEPEncoding(new RSABlindedEngine());
- byte[] data = Hex.decode(input);
-
- eng.init(true, pubParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- eng.init(false, privParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- if (!input.equals(new String(Hex.encode(data))))
- {
- fail("failed OAEP Test");
- }
- }
-
- public void performTest()
- {
- RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod, pubExp);
- RSAKeyParameters privParameters = new RSAPrivateCrtKeyParameters(mod, pubExp, privExp, p, q, pExp, qExp, crtCoef);
- byte[] data = Hex.decode(edgeInput);
-
- //
- // RAW
- //
- AsymmetricBlockCipher eng = new RSABlindedEngine();
-
- eng.init(true, pubParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("RSA: failed - exception " + e.toString(), e);
- }
-
- eng.init(false, privParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- if (!edgeInput.equals(new String(Hex.encode(data))))
- {
- fail("failed RAW edge Test");
- }
-
- data = Hex.decode(input);
-
- eng.init(true, pubParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- eng.init(false, privParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- if (!input.equals(new String(Hex.encode(data))))
- {
- fail("failed RAW Test");
- }
-
- //
- // PKCS1 - public encrypt, private decrypt
- //
- eng = new PKCS1Encoding(eng);
-
- eng.init(true, pubParameters);
-
- if (eng.getOutputBlockSize() != ((PKCS1Encoding)eng).getUnderlyingCipher().getOutputBlockSize())
- {
- fail("PKCS1 output block size incorrect");
- }
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- eng.init(false, privParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- if (!input.equals(new String(Hex.encode(data))))
- {
- fail("failed PKCS1 public/private Test");
- }
-
- //
- // PKCS1 - private encrypt, public decrypt
- //
- eng = new PKCS1Encoding(((PKCS1Encoding)eng).getUnderlyingCipher());
-
- eng.init(true, privParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- eng.init(false, pubParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- if (!input.equals(new String(Hex.encode(data))))
- {
- fail("failed PKCS1 private/public Test");
- }
-
- //
- // key generation test
- //
- RSAKeyPairGenerator pGen = new RSAKeyPairGenerator();
- RSAKeyGenerationParameters genParam = new RSAKeyGenerationParameters(
- BigInteger.valueOf(0x11), new SecureRandom(), 768, 25);
-
- pGen.init(genParam);
-
- AsymmetricCipherKeyPair pair = pGen.generateKeyPair();
-
- eng = new RSABlindedEngine();
-
- if (((RSAKeyParameters)pair.getPublic()).getModulus().bitLength() < 768)
- {
- fail("failed key generation (768) length test");
- }
-
- eng.init(true, pair.getPublic());
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- eng.init(false, pair.getPrivate());
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- if (!input.equals(new String(Hex.encode(data))))
- {
- fail("failed key generation (768) Test");
- }
-
- genParam = new RSAKeyGenerationParameters(BigInteger.valueOf(0x11), new SecureRandom(), 1024, 25);
-
- pGen.init(genParam);
- pair = pGen.generateKeyPair();
-
- eng.init(true, pair.getPublic());
-
- if (((RSAKeyParameters)pair.getPublic()).getModulus().bitLength() < 1024)
- {
- fail("failed key generation (1024) length test");
- }
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- eng.init(false, pair.getPrivate());
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- if (!input.equals(new String(Hex.encode(data))))
- {
- fail("failed key generation (1024) test");
- }
-
- testOAEP(pubParameters, privParameters);
- testStrictPKCS1Length(pubParameters, privParameters);
- testDudPKCS1Block(pubParameters, privParameters);
- testMissingDataPKCS1Block(pubParameters, privParameters);
- testTruncatedPKCS1Block(pubParameters, privParameters);
- testWrongPaddingPKCS1Block(pubParameters, privParameters);
-
- try
- {
- new RSABlindedEngine().processBlock(new byte[]{ 1 }, 0, 1);
- fail("failed initialisation check");
- }
- catch (IllegalStateException e)
- {
- // expected
- }
- }
-
-
- public static void main(
- String[] args)
- {
- runTest(new RSABlindedTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/RSADigestSignerTest.java b/core/src/test/java/org/bouncycastle/crypto/test/RSADigestSignerTest.java
deleted file mode 100644
index 605a2cac..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/RSADigestSignerTest.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
-import org.bouncycastle.crypto.signers.RSADigestSigner;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.test.SimpleTest;
-
-import java.math.BigInteger;
-
-public class RSADigestSignerTest
- extends SimpleTest
-{
- public String getName()
- {
- return "RSADigestSigner";
- }
-
- public void performTest() throws Exception
- {
- BigInteger rsaPubMod = new BigInteger(Base64.decode("AIASoe2PQb1IP7bTyC9usjHP7FvnUMVpKW49iuFtrw/dMpYlsMMoIU2jupfifDpdFxIktSB4P+6Ymg5WjvHKTIrvQ7SR4zV4jaPTu56Ys0pZ9EDA6gb3HLjtU+8Bb1mfWM+yjKxcPDuFjwEtjGlPHg1Vq+CA9HNcMSKNn2+tW6qt"));
- BigInteger rsaPubExp = new BigInteger(Base64.decode("EQ=="));
- BigInteger rsaPrivMod = new BigInteger(Base64.decode("AIASoe2PQb1IP7bTyC9usjHP7FvnUMVpKW49iuFtrw/dMpYlsMMoIU2jupfifDpdFxIktSB4P+6Ymg5WjvHKTIrvQ7SR4zV4jaPTu56Ys0pZ9EDA6gb3HLjtU+8Bb1mfWM+yjKxcPDuFjwEtjGlPHg1Vq+CA9HNcMSKNn2+tW6qt"));
- BigInteger rsaPrivDP = new BigInteger(Base64.decode("JXzfzG5v+HtLJIZqYMUefJfFLu8DPuJGaLD6lI3cZ0babWZ/oPGoJa5iHpX4Ul/7l3s1PFsuy1GhzCdOdlfRcQ=="));
- BigInteger rsaPrivDQ = new BigInteger(Base64.decode("YNdJhw3cn0gBoVmMIFRZzflPDNthBiWy/dUMSRfJCxoZjSnr1gysZHK01HteV1YYNGcwPdr3j4FbOfri5c6DUQ=="));
- BigInteger rsaPrivExp = new BigInteger(Base64.decode("DxFAOhDajr00rBjqX+7nyZ/9sHWRCCp9WEN5wCsFiWVRPtdB+NeLcou7mWXwf1Y+8xNgmmh//fPV45G2dsyBeZbXeJwB7bzx9NMEAfedchyOwjR8PYdjK3NpTLKtZlEJ6Jkh4QihrXpZMO4fKZWUm9bid3+lmiq43FwW+Hof8/E="));
- BigInteger rsaPrivP = new BigInteger(Base64.decode("AJ9StyTVW+AL/1s7RBtFwZGFBgd3zctBqzzwKPda6LbtIFDznmwDCqAlIQH9X14X7UPLokCDhuAa76OnDXb1OiE="));
- BigInteger rsaPrivQ = new BigInteger(Base64.decode("AM3JfD79dNJ5A3beScSzPtWxx/tSLi0QHFtkuhtSizeXdkv5FSba7lVzwEOGKHmW829bRoNxThDy4ds1IihW1w0="));
- BigInteger rsaPrivQinv = new BigInteger(Base64.decode("Lt0g7wrsNsQxuDdB8q/rH8fSFeBXMGLtCIqfOec1j7FEIuYA/ACiRDgXkHa0WgN7nLXSjHoy630wC5Toq8vvUg=="));
- RSAKeyParameters rsaPublic = new RSAKeyParameters(false, rsaPubMod, rsaPubExp);
- RSAPrivateCrtKeyParameters rsaPrivate = new RSAPrivateCrtKeyParameters(rsaPrivMod, rsaPubExp, rsaPrivExp, rsaPrivP, rsaPrivQ, rsaPrivDP, rsaPrivDQ, rsaPrivQinv);
-
- byte[] msg = new byte[] { 1, 6, 3, 32, 7, 43, 2, 5, 7, 78, 4, 23 };
-
- RSADigestSigner signer = new RSADigestSigner(new SHA1Digest());
- signer.init(true, rsaPrivate);
- signer.update(msg, 0, msg.length);
- byte[] sig = signer.generateSignature();
-
- signer = new RSADigestSigner(new SHA1Digest(), X509ObjectIdentifiers.id_SHA1);
- signer.init(false, rsaPublic);
- signer.update(msg, 0, msg.length);
- if (!signer.verifySignature(sig))
- {
- fail("RSA Digest Signer failed.");
- }
- }
-
- public static void main(String[] args)
- {
- runTest(new RSADigestSignerTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/RSAKeyEncapsulationTest.java b/core/src/test/java/org/bouncycastle/crypto/test/RSAKeyEncapsulationTest.java
deleted file mode 100755
index 058f4682..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/RSAKeyEncapsulationTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.generators.KDF2BytesGenerator;
-import org.bouncycastle.crypto.generators.RSAKeyPairGenerator;
-import org.bouncycastle.crypto.kems.RSAKeyEncapsulation;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * Tests for the RSA Key Encapsulation Mechanism
- */
-public class RSAKeyEncapsulationTest
- extends SimpleTest
-{
- public String getName()
- {
- return "RSAKeyEncapsulation";
- }
-
- public void performTest()
- throws Exception
- {
- // Generate RSA key pair
- RSAKeyPairGenerator rsaGen = new RSAKeyPairGenerator();
- rsaGen.init(new RSAKeyGenerationParameters(BigInteger.valueOf(65537), new SecureRandom(), 1024, 5));
- AsymmetricCipherKeyPair keys = rsaGen.generateKeyPair();
-
- // Set RSA-KEM parameters
- RSAKeyEncapsulation kem;
- KDF2BytesGenerator kdf = new KDF2BytesGenerator(new SHA1Digest());
- SecureRandom rnd = new SecureRandom();
- byte[] out = new byte[128];
- KeyParameter key1, key2;
-
- // Test RSA-KEM
- kem = new RSAKeyEncapsulation(kdf, rnd);
-
- kem.init(keys.getPublic());
- key1 = (KeyParameter)kem.encrypt(out, 128);
-
- kem.init(keys.getPrivate());
- key2 = (KeyParameter)kem.decrypt(out, 128);
-
- if (!areEqual(key1.getKey(), key2.getKey()))
- {
- fail("failed test");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new RSAKeyEncapsulationTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/RSATest.java b/core/src/test/java/org/bouncycastle/crypto/test/RSATest.java
deleted file mode 100644
index a1ea3996..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/RSATest.java
+++ /dev/null
@@ -1,498 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.encodings.OAEPEncoding;
-import org.bouncycastle.crypto.encodings.PKCS1Encoding;
-import org.bouncycastle.crypto.engines.RSAEngine;
-import org.bouncycastle.crypto.generators.RSAKeyPairGenerator;
-import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class RSATest
- extends SimpleTest
-{
- static BigInteger mod = new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16);
- static BigInteger pubExp = new BigInteger("11", 16);
- static BigInteger privExp = new BigInteger("92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619", 16);
- static BigInteger p = new BigInteger("f75e80839b9b9379f1cf1128f321639757dba514642c206bbbd99f9a4846208b3e93fbbe5e0527cc59b1d4b929d9555853004c7c8b30ee6a213c3d1bb7415d03", 16);
- static BigInteger q = new BigInteger("b892d9ebdbfc37e397256dd8a5d3123534d1f03726284743ddc6be3a709edb696fc40c7d902ed804c6eee730eee3d5b20bf6bd8d87a296813c87d3b3cc9d7947", 16);
- static BigInteger pExp = new BigInteger("1d1a2d3ca8e52068b3094d501c9a842fec37f54db16e9a67070a8b3f53cc03d4257ad252a1a640eadd603724d7bf3737914b544ae332eedf4f34436cac25ceb5", 16);
- static BigInteger qExp = new BigInteger("6c929e4e81672fef49d9c825163fec97c4b7ba7acb26c0824638ac22605d7201c94625770984f78a56e6e25904fe7db407099cad9b14588841b94f5ab498dded", 16);
- static BigInteger crtCoef = new BigInteger("dae7651ee69ad1d081ec5e7188ae126f6004ff39556bde90e0b870962fa7b926d070686d8244fe5a9aa709a95686a104614834b0ada4b10f53197a5cb4c97339", 16);
-
- static String input = "4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
-
- //
- // to check that we handling byte extension by big number correctly.
- //
- static String edgeInput = "ff6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
-
- static byte[] oversizedSig = Hex.decode("01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
- static byte[] dudBlock = Hex.decode("000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
- static byte[] truncatedDataBlock = Hex.decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
- static byte[] incorrectPadding = Hex.decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
- static byte[] missingDataBlock = Hex.decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
-
- public String getName()
- {
- return "RSA";
- }
-
- private void testStrictPKCS1Length(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
- {
- AsymmetricBlockCipher eng = new RSAEngine();
-
- eng.init(true, privParameters);
-
- byte[] data = null;
-
- try
- {
- data = eng.processBlock(oversizedSig, 0, oversizedSig.length);
- }
- catch (Exception e)
- {
- fail("RSA: failed - exception " + e.toString(), e);
- }
-
- eng = new PKCS1Encoding(eng);
-
- eng.init(false, pubParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
-
- fail("oversized signature block not recognised");
- }
- catch (InvalidCipherTextException e)
- {
- if (!e.getMessage().equals("block incorrect size"))
- {
- fail("RSA: failed - exception " + e.toString(), e);
- }
- }
-
- //System.setProperty(PKCS1Encoding.STRICT_LENGTH_ENABLED_PROPERTY, "false");
-
- System.getProperties().put(PKCS1Encoding.STRICT_LENGTH_ENABLED_PROPERTY, "false");
- eng = new PKCS1Encoding(new RSAEngine());
-
- eng.init(false, pubParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (InvalidCipherTextException e)
- {
- fail("RSA: failed - exception " + e.toString(), e);
- }
-
- System.getProperties().remove(PKCS1Encoding.STRICT_LENGTH_ENABLED_PROPERTY);
- }
-
- private void testTruncatedPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
- {
- checkForPKCS1Exception(pubParameters, privParameters, truncatedDataBlock, "block truncated");
- }
-
- private void testDudPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
- {
- checkForPKCS1Exception(pubParameters, privParameters, dudBlock, "unknown block type");
- }
-
- private void testWrongPaddingPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
- {
- checkForPKCS1Exception(pubParameters, privParameters, incorrectPadding, "block padding incorrect");
- }
-
- private void testMissingDataPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
- {
- checkForPKCS1Exception(pubParameters, privParameters, missingDataBlock, "no data in block");
- }
-
- private void checkForPKCS1Exception(RSAKeyParameters pubParameters, RSAKeyParameters privParameters, byte[] inputData, String expectedMessage)
- {
- AsymmetricBlockCipher eng = new RSAEngine();
-
- eng.init(true, privParameters);
-
- byte[] data = null;
-
- try
- {
- data = eng.processBlock(inputData, 0, inputData.length);
- }
- catch (Exception e)
- {
- fail("RSA: failed - exception " + e.toString(), e);
- }
-
- eng = new PKCS1Encoding(eng);
-
- eng.init(false, pubParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
-
- fail("missing data block not recognised");
- }
- catch (InvalidCipherTextException e)
- {
- if (!e.getMessage().equals(expectedMessage))
- {
- fail("RSA: failed - exception " + e.toString(), e);
- }
- }
- }
-
- private void testOAEP(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
- {
- //
- // OAEP - public encrypt, private decrypt
- //
- AsymmetricBlockCipher eng = new OAEPEncoding(new RSAEngine());
- byte[] data = Hex.decode(input);
-
- eng.init(true, pubParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- eng.init(false, privParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- if (!input.equals(new String(Hex.encode(data))))
- {
- fail("failed OAEP Test");
- }
- }
-
- private void zeroBlockTest(CipherParameters encParameters, CipherParameters decParameters)
- {
- AsymmetricBlockCipher eng = new PKCS1Encoding(new RSAEngine());
-
- eng.init(true, encParameters);
-
- if (eng.getOutputBlockSize() != ((PKCS1Encoding)eng).getUnderlyingCipher().getOutputBlockSize())
- {
- fail("PKCS1 output block size incorrect");
- }
-
- byte[] zero = new byte[0];
- byte[] data = null;
-
- try
- {
- data = eng.processBlock(zero, 0, zero.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- eng.init(false, decParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- if (!Arrays.areEqual(zero, data))
- {
- fail("failed PKCS1 zero Test");
- }
- }
-
- public void performTest()
- {
- RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod, pubExp);
- RSAKeyParameters privParameters = new RSAPrivateCrtKeyParameters(mod, pubExp, privExp, p, q, pExp, qExp, crtCoef);
- byte[] data = Hex.decode(edgeInput);
-
- //
- // RAW
- //
- AsymmetricBlockCipher eng = new RSAEngine();
-
- eng.init(true, pubParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("RSA: failed - exception " + e.toString(), e);
- }
-
- eng.init(false, privParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- if (!edgeInput.equals(new String(Hex.encode(data))))
- {
- fail("failed RAW edge Test");
- }
-
- data = Hex.decode(input);
-
- eng.init(true, pubParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- eng.init(false, privParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- if (!input.equals(new String(Hex.encode(data))))
- {
- fail("failed RAW Test");
- }
-
- //
- // PKCS1 - public encrypt, private decrypt
- //
- eng = new PKCS1Encoding(eng);
-
- eng.init(true, pubParameters);
-
- if (eng.getOutputBlockSize() != ((PKCS1Encoding)eng).getUnderlyingCipher().getOutputBlockSize())
- {
- fail("PKCS1 output block size incorrect");
- }
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- eng.init(false, privParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- if (!input.equals(new String(Hex.encode(data))))
- {
- fail("failed PKCS1 public/private Test");
- }
-
- //
- // PKCS1 - private encrypt, public decrypt
- //
- eng = new PKCS1Encoding(((PKCS1Encoding)eng).getUnderlyingCipher());
-
- eng.init(true, privParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- eng.init(false, pubParameters);
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- if (!input.equals(new String(Hex.encode(data))))
- {
- fail("failed PKCS1 private/public Test");
- }
-
- zeroBlockTest(pubParameters, privParameters);
- zeroBlockTest(privParameters, pubParameters);
-
- //
- // key generation test
- //
- RSAKeyPairGenerator pGen = new RSAKeyPairGenerator();
- RSAKeyGenerationParameters genParam = new RSAKeyGenerationParameters(
- BigInteger.valueOf(0x11), new SecureRandom(), 768, 25);
-
- pGen.init(genParam);
-
- AsymmetricCipherKeyPair pair = pGen.generateKeyPair();
-
- eng = new RSAEngine();
-
- if (((RSAKeyParameters)pair.getPublic()).getModulus().bitLength() < 768)
- {
- fail("failed key generation (768) length test");
- }
-
- eng.init(true, pair.getPublic());
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- eng.init(false, pair.getPrivate());
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- if (!input.equals(new String(Hex.encode(data))))
- {
- fail("failed key generation (768) Test");
- }
-
- genParam = new RSAKeyGenerationParameters(BigInteger.valueOf(0x11), new SecureRandom(), 1024, 25);
-
- pGen.init(genParam);
- pair = pGen.generateKeyPair();
-
- eng.init(true, pair.getPublic());
-
- if (((RSAKeyParameters)pair.getPublic()).getModulus().bitLength() < 1024)
- {
- fail("failed key generation (1024) length test");
- }
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- eng.init(false, pair.getPrivate());
-
- try
- {
- data = eng.processBlock(data, 0, data.length);
- }
- catch (Exception e)
- {
- fail("failed - exception " + e.toString(), e);
- }
-
- if (!input.equals(new String(Hex.encode(data))))
- {
- fail("failed key generation (1024) test");
- }
-
- genParam = new RSAKeyGenerationParameters(
- BigInteger.valueOf(0x11), new SecureRandom(), 16, 25);
- pGen.init(genParam);
-
- for (int i = 0; i < 100; ++i)
- {
- pair = pGen.generateKeyPair();
- RSAPrivateCrtKeyParameters privKey = (RSAPrivateCrtKeyParameters) pair.getPrivate();
- BigInteger pqDiff = privKey.getP().subtract(privKey.getQ()).abs();
-
- if (pqDiff.bitLength() < 5)
- {
- fail("P and Q too close in RSA key pair");
- }
- }
-
- testOAEP(pubParameters, privParameters);
- testStrictPKCS1Length(pubParameters, privParameters);
- testDudPKCS1Block(pubParameters, privParameters);
- testMissingDataPKCS1Block(pubParameters, privParameters);
- testTruncatedPKCS1Block(pubParameters, privParameters);
- testWrongPaddingPKCS1Block(pubParameters, privParameters);
-
- try
- {
- new RSAEngine().processBlock(new byte[]{ 1 }, 0, 1);
- fail("failed initialisation check");
- }
- catch (IllegalStateException e)
- {
- // expected
- }
- }
-
-
- public static void main(
- String[] args)
- {
- runTest(new RSATest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/RegressionTest.java b/core/src/test/java/org/bouncycastle/crypto/test/RegressionTest.java
deleted file mode 100644
index 4913081c..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/RegressionTest.java
+++ /dev/null
@@ -1,157 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-public class RegressionTest
-{
- public static Test[] tests =
- {
- new AESTest(),
- new AESLightTest(),
- new AESFastTest(),
- new AESWrapTest(),
- new AESWrapPadTest(),
- new DESTest(),
- new DESedeTest(),
- new ModeTest(),
- new PaddingTest(),
- new DHTest(),
- new ElGamalTest(),
- new DSATest(),
- new ECTest(),
- new DeterministicDSATest(),
- new GOST3410Test(),
- new ECGOST3410Test(),
- new ECIESTest(),
- new ECNRTest(),
- new MacTest(),
- new GOST28147MacTest(),
- new RC2Test(),
- new RC2WrapTest(),
- new RC4Test(),
- new RC5Test(),
- new RC6Test(),
- new RijndaelTest(),
- new SerpentTest(),
- new CamelliaTest(),
- new CamelliaLightTest(),
- new DigestRandomNumberTest(),
- new SkipjackTest(),
- new BlowfishTest(),
- new TwofishTest(),
- new Threefish256Test(),
- new Threefish512Test(),
- new Threefish1024Test(),
- new SkeinDigestTest(),
- new SkeinMacTest(),
- new CAST5Test(),
- new CAST6Test(),
- new GOST28147Test(),
- new IDEATest(),
- new RSATest(),
- new RSABlindedTest(),
- new RSADigestSignerTest(),
- new PSSBlindTest(),
- new ISO9796Test(),
- new ISO9797Alg3MacTest(),
- new MD2DigestTest(),
- new MD4DigestTest(),
- new MD5DigestTest(),
- new SHA1DigestTest(),
- new SHA224DigestTest(),
- new SHA256DigestTest(),
- new SHA384DigestTest(),
- new SHA512DigestTest(),
- new SHA512t224DigestTest(),
- new SHA512t256DigestTest(),
- new SHA3DigestTest(),
- new RIPEMD128DigestTest(),
- new RIPEMD160DigestTest(),
- new RIPEMD256DigestTest(),
- new RIPEMD320DigestTest(),
- new TigerDigestTest(),
- new GOST3411DigestTest(),
- new WhirlpoolDigestTest(),
- new MD5HMacTest(),
- new SHA1HMacTest(),
- new SHA224HMacTest(),
- new SHA256HMacTest(),
- new SHA384HMacTest(),
- new SHA512HMacTest(),
- new RIPEMD128HMacTest(),
- new RIPEMD160HMacTest(),
- new OAEPTest(),
- new PSSTest(),
- new CTSTest(),
- new CCMTest(),
- new PKCS5Test(),
- new PKCS12Test(),
- new KDF1GeneratorTest(),
- new KDF2GeneratorTest(),
- new MGF1GeneratorTest(),
- new HKDFGeneratorTest(),
- new DHKEKGeneratorTest(),
- new ECDHKEKGeneratorTest(),
- new ShortenedDigestTest(),
- new EqualsHashCodeTest(),
- new TEATest(),
- new XTEATest(),
- new RFC3211WrapTest(),
- new SEEDTest(),
- new Salsa20Test(),
- new XSalsa20Test(),
- new ChaChaTest(),
- new CMacTest(),
- new EAXTest(),
- new GCMTest(),
- new GMacTest(),
- new HCFamilyTest(),
- new HCFamilyVecTest(),
- new ISAACTest(),
- new NoekeonTest(),
- new VMPCKSA3Test(),
- new VMPCMacTest(),
- new VMPCTest(),
- new Grainv1Test(),
- new Grain128Test(),
- //new NaccacheSternTest(),
- new SRP6Test(),
- new SCryptTest(),
- new ResetTest(),
- new NullTest(),
- new DSTU4145Test(),
- new SipHashTest(),
- new Poly1305Test(),
- new OCBTest(),
- new NonMemoableDigestTest(),
- new RSAKeyEncapsulationTest(),
- new ECIESKeyEncapsulationTest(),
- new HashCommitmentTest(),
- new CipherStreamTest(),
- new BlockCipherResetTest(),
- new StreamCipherResetTest(),
- new SM3DigestTest(),
- new Shacal2Test(),
- new KDFCounterGeneratorTest(),
- new KDFDoublePipelineIteratorGeneratorTest(),
- new KDFFeedbackGeneratorTest(),
- new CramerShoupTest()
- };
-
- public static void main(
- String[] args)
- {
- for (int i = 0; i != tests.length; i++)
- {
- TestResult result = tests[i].perform();
-
- if (result.getException() != null)
- {
- result.getException().printStackTrace();
- }
-
- System.out.println(result);
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/ResetTest.java b/core/src/test/java/org/bouncycastle/crypto/test/ResetTest.java
deleted file mode 100644
index efd0e06c..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/ResetTest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.BufferedBlockCipher;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.engines.DESEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class ResetTest
- extends SimpleTest
-{
- private static final byte[] input = Hex.decode("4e6f77206973207468652074696d6520666f7220616c6c20");
- private static final byte[] output = Hex.decode("3fa40e8a984d48156a271787ab8883f9893d51ec4b563b53");
- public String getName()
- {
- return "Reset";
- }
-
- public void performTest()
- throws Exception
- {
- BufferedBlockCipher cipher = new BufferedBlockCipher(new DESEngine());
-
- KeyParameter param = new KeyParameter(Hex.decode("0123456789abcdef"));
-
- basicTrial(cipher, param);
-
- cipher.init(false, param);
-
- byte[] out = new byte[input.length];
-
- int len2 = cipher.processBytes(output, 0, output.length - 1, out, 0);
-
- try
- {
- cipher.doFinal(out, len2);
- fail("no DataLengthException - short input");
- }
- catch (DataLengthException e)
- {
- // ignore
- }
-
- len2 = cipher.processBytes(output, 0, output.length, out, 0);
-
- cipher.doFinal(out, len2);
-
- if (!areEqual(input, out))
- {
- fail("failed reversal one got " + new String(Hex.encode(out)));
- }
-
- len2 = cipher.processBytes(output, 0, output.length - 1, out, 0);
-
- try
- {
- cipher.doFinal(out, len2);
- fail("no DataLengthException - short output");
- }
- catch (DataLengthException e)
- {
- // ignore
- }
-
- len2 = cipher.processBytes(output, 0, output.length, out, 0);
-
- cipher.doFinal(out, len2);
-
- if (!areEqual(input, out))
- {
- fail("failed reversal two got " + new String(Hex.encode(out)));
- }
- }
-
- private void basicTrial(BufferedBlockCipher cipher, KeyParameter param)
- throws InvalidCipherTextException
- {
- cipher.init(true, param);
-
- byte[] out = new byte[input.length];
-
- int len1 = cipher.processBytes(input, 0, input.length, out, 0);
-
- cipher.doFinal(out, len1);
-
- if (!areEqual(out, output))
- {
- fail("failed - " + "expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new ResetTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/RijndaelTest.java b/core/src/test/java/org/bouncycastle/crypto/test/RijndaelTest.java
deleted file mode 100644
index ca81dfb1..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/RijndaelTest.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.engines.RijndaelEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * Test vectors from the NIST standard tests and Brian Gladman's vector set
- * <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">
- * http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
- */
-public class RijndaelTest
- extends CipherTest
-{
- static SimpleTest[] tests =
- {
- new BlockCipherVectorTest(0, new RijndaelEngine(128),
- new KeyParameter(Hex.decode("80000000000000000000000000000000")),
- "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
- new BlockCipherVectorTest(1, new RijndaelEngine(128),
- new KeyParameter(Hex.decode("00000000000000000000000000000080")),
- "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
- new BlockCipherMonteCarloTest(2, 10000, new RijndaelEngine(128),
- new KeyParameter(Hex.decode("00000000000000000000000000000000")),
- "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
- new BlockCipherMonteCarloTest(3, 10000, new RijndaelEngine(128),
- new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")),
- "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
- new BlockCipherVectorTest(4, new RijndaelEngine(128),
- new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
- "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
- new BlockCipherMonteCarloTest(5, 10000, new RijndaelEngine(128),
- new KeyParameter(Hex.decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
- "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
- new BlockCipherVectorTest(6, new RijndaelEngine(128),
- new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
- "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
- new BlockCipherMonteCarloTest(7, 10000, new RijndaelEngine(128),
- new KeyParameter(Hex.decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
- "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168"),
- new BlockCipherVectorTest(8, new RijndaelEngine(160),
- new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c")),
- "3243f6a8885a308d313198a2e03707344a409382", "16e73aec921314c29df905432bc8968ab64b1f51"),
- new BlockCipherVectorTest(8, new RijndaelEngine(160),
- new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160")),
- "3243f6a8885a308d313198a2e03707344a409382", "0553eb691670dd8a5a5b5addf1aa7450f7a0e587"),
- new BlockCipherVectorTest(8, new RijndaelEngine(160),
- new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da5")),
- "3243f6a8885a308d313198a2e03707344a409382", "73cd6f3423036790463aa9e19cfcde894ea16623"),
- new BlockCipherVectorTest(8, new RijndaelEngine(160),
- new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d90")),
- "3243f6a8885a308d313198a2e03707344a409382", "601b5dcd1cf4ece954c740445340bf0afdc048df"),
- new BlockCipherVectorTest(8, new RijndaelEngine(160),
- new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d9045190cfe")),
- "3243f6a8885a308d313198a2e03707344a409382", "579e930b36c1529aa3e86628bacfe146942882cf"),
- new BlockCipherVectorTest(8, new RijndaelEngine(192),
- new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c")),
- "3243f6a8885a308d313198a2e03707344a4093822299f31d", "b24d275489e82bb8f7375e0d5fcdb1f481757c538b65148a"),
- new BlockCipherVectorTest(9, new RijndaelEngine(192),
- new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da5")),
- "3243f6a8885a308d313198a2e03707344a4093822299f31d", "725ae43b5f3161de806a7c93e0bca93c967ec1ae1b71e1cf"),
- new BlockCipherVectorTest(10, new RijndaelEngine(192),
- new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d90")),
- "3243f6a8885a308d313198a2e03707344a4093822299f31d", "bbfc14180afbf6a36382a061843f0b63e769acdc98769130"),
- new BlockCipherVectorTest(11, new RijndaelEngine(192),
- new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d9045190cfe")),
- "3243f6a8885a308d313198a2e03707344a4093822299f31d", "0ebacf199e3315c2e34b24fcc7c46ef4388aa475d66c194c"),
- new BlockCipherVectorTest(12, new RijndaelEngine(224),
- new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c")),
- "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa9", "b0a8f78f6b3c66213f792ffd2a61631f79331407a5e5c8d3793aceb1"),
- new BlockCipherVectorTest(13, new RijndaelEngine(224),
- new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160")),
- "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa9", "08b99944edfce33a2acb131183ab0168446b2d15e958480010f545e3"),
- new BlockCipherVectorTest(14, new RijndaelEngine(224),
- new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da5")),
- "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa9", "be4c597d8f7efe22a2f7e5b1938e2564d452a5bfe72399c7af1101e2"),
- new BlockCipherVectorTest(15, new RijndaelEngine(224),
- new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d90")),
- "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa9", "ef529598ecbce297811b49bbed2c33bbe1241d6e1a833dbe119569e8"),
- new BlockCipherVectorTest(16, new RijndaelEngine(224),
- new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d9045190cfe")),
- "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa9", "02fafc200176ed05deb8edb82a3555b0b10d47a388dfd59cab2f6c11"),
- new BlockCipherVectorTest(17, new RijndaelEngine(256),
- new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c")),
- "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c8", "7d15479076b69a46ffb3b3beae97ad8313f622f67fedb487de9f06b9ed9c8f19"),
- new BlockCipherVectorTest(18, new RijndaelEngine(256),
- new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160")),
- "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c8", "514f93fb296b5ad16aa7df8b577abcbd484decacccc7fb1f18dc567309ceeffd"),
- new BlockCipherVectorTest(19, new RijndaelEngine(256),
- new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da5")),
- "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c8", "5d7101727bb25781bf6715b0e6955282b9610e23a43c2eb062699f0ebf5887b2"),
- new BlockCipherVectorTest(20, new RijndaelEngine(256),
- new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d90")),
- "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c8", "d56c5a63627432579e1dd308b2c8f157b40a4bfb56fea1377b25d3ed3d6dbf80"),
- new BlockCipherVectorTest(21, new RijndaelEngine(256),
- new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d9045190cfe")),
- "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c8", "a49406115dfb30a40418aafa4869b7c6a886ff31602a7dd19c889dc64f7e4e7a")
- };
-
- RijndaelTest()
- {
- super(tests, new RijndaelEngine(128), new KeyParameter(new byte[16]));
- }
-
- public String getName()
- {
- return "Rijndael";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new RijndaelTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/SCryptTest.java b/core/src/test/java/org/bouncycastle/crypto/test/SCryptTest.java
deleted file mode 100644
index b017a1da..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/SCryptTest.java
+++ /dev/null
@@ -1,144 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-
-import org.bouncycastle.crypto.generators.SCrypt;
-import org.bouncycastle.util.Strings;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/*
- * scrypt test vectors from "Stronger Key Derivation Via Sequential Memory-hard Functions" Appendix B.
- * (http://www.tarsnap.com/scrypt/scrypt.pdf)
- */
-public class SCryptTest extends SimpleTest
-{
- public String getName()
- {
- return "SCrypt";
- }
-
- public void performTest() throws Exception
- {
- testParameters();
- testVectors();
- }
-
- public void testParameters()
- {
- checkOK("Minimal values", new byte[0], new byte[0], 2, 1, 1, 1);
- checkIllegal("Cost parameter must be > 1", new byte[0], new byte[0], 1, 1, 1, 1);
- checkOK("Cost parameter 65536 OK for r == 1", new byte[0], new byte[0], 65536, 1, 1, 1);
- checkIllegal("Cost parameter must <= 65536 for r == 1", new byte[0], new byte[0], 65537, 1, 1, 1);
- checkIllegal("Block size must be >= 1", new byte[0], new byte[0], 2, 0, 2, 1);
- checkIllegal("Parallelisation parameter must be >= 1", new byte[0], new byte[0], 2, 1, 0, 1);
- // checkOK("Parallelisation parameter 65535 OK for r = 4", new byte[0], new byte[0], 2, 32,
- // 65535, 1);
- checkIllegal("Parallelisation parameter must be < 65535 for r = 4", new byte[0], new byte[0], 2, 32, 65536, 1);
-
- checkIllegal("Len parameter must be > 1", new byte[0], new byte[0], 2, 1, 1, 0);
- }
-
- private void checkOK(String msg, byte[] pass, byte[] salt, int N, int r, int p, int len)
- {
- try
- {
- SCrypt.generate(pass, salt, N, r, p, len);
- }
- catch (IllegalArgumentException e)
- {
- e.printStackTrace();
- fail(msg);
- }
- }
-
- private void checkIllegal(String msg, byte[] pass, byte[] salt, int N, int r, int p, int len)
- {
- try
- {
- SCrypt.generate(pass, salt, N, r, p, len);
- fail(msg);
- }
- catch (IllegalArgumentException e)
- {
- // e.printStackTrace();
- }
- }
-
- public void testVectors()
- throws Exception
- {
- BufferedReader br = new BufferedReader(new InputStreamReader(
- getClass().getResourceAsStream("SCryptTestVectors.txt")));
-
- int count = 0;
- String line = br.readLine();
-
- while (line != null)
- {
- ++count;
- String header = line;
- StringBuffer data = new StringBuffer();
-
- while (!isEndData(line = br.readLine()))
- {
- for (int i = 0; i != line.length(); i++)
- {
- if (line.charAt(i) != ' ')
- {
- data.append(line.charAt(i));
- }
- }
- }
-
- int start = header.indexOf('(') + 1;
- int limit = header.lastIndexOf(')');
- String argStr = header.substring(start, limit);
- String[] args = Strings.split(argStr, ',');
-
- byte[] P = extractQuotedString(args[0]);
- byte[] S = extractQuotedString(args[1]);
- int N = extractInteger(args[2]);
- int r = extractInteger(args[3]);
- int p = extractInteger(args[4]);
- int dkLen = extractInteger(args[5]);
- byte[] expected = Hex.decode(data.toString());
-
- // This skips very expensive test case(s), remove check to re-enable
- if (N <= 16384)
- {
- byte[] result = SCrypt.generate(P, S, N, r, p, dkLen);
-
- if (!areEqual(expected, result))
- {
- fail("Result does not match expected value in test case " + count);
- }
- }
- }
-
- br.close();
- }
-
- private static boolean isEndData(String line)
- {
- return line == null || line.startsWith("scrypt");
- }
-
- private static byte[] extractQuotedString(String arg)
- {
- arg = arg.trim();
- arg = arg.substring(1, arg.length() - 1);
- return Strings.toByteArray(arg);
- }
-
- private static int extractInteger(String arg)
- {
- return Integer.parseInt(arg.trim());
- }
-
- public static void main(String[] args)
- {
- runTest(new SCryptTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/SEEDTest.java b/core/src/test/java/org/bouncycastle/crypto/test/SEEDTest.java
deleted file mode 100644
index 4aa955b2..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/SEEDTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.engines.SEEDEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * SEED tester - vectors http://www.ietf.org/rfc/rfc4009.txt
- */
-public class SEEDTest
- extends CipherTest
-{
- static SimpleTest[] tests =
- {
- new BlockCipherVectorTest(0, new SEEDEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000")),
- "000102030405060708090a0b0c0d0e0f",
- "5EBAC6E0054E166819AFF1CC6D346CDB"),
- new BlockCipherVectorTest(0, new SEEDEngine(),
- new KeyParameter(Hex.decode("000102030405060708090a0b0c0d0e0f")),
- "00000000000000000000000000000000",
- "c11f22f20140505084483597e4370f43"),
- new BlockCipherVectorTest(0, new SEEDEngine(),
- new KeyParameter(Hex.decode("4706480851E61BE85D74BFB3FD956185")),
- "83A2F8A288641FB9A4E9A5CC2F131C7D",
- "EE54D13EBCAE706D226BC3142CD40D4A"),
- new BlockCipherVectorTest(0, new SEEDEngine(),
- new KeyParameter(Hex.decode("28DBC3BC49FFD87DCFA509B11D422BE7")),
- "B41E6BE2EBA84A148E2EED84593C5EC7",
- "9B9B7BFCD1813CB95D0B3618F40F5122"),
- new BlockCipherVectorTest(0, new SEEDEngine(),
- new KeyParameter(Hex.decode("0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E")),
- "0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E",
- "8296F2F1B007AB9D533FDEE35A9AD850"),
- };
-
- SEEDTest()
- {
- super(tests, new SEEDEngine(), new KeyParameter(new byte[16]));
- }
-
- public String getName()
- {
- return "SEED";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new SEEDTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/SHA1DigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/SHA1DigestTest.java
deleted file mode 100644
index 38b9b807..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/SHA1DigestTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-
-/**
- * standard vector test for SHA-1 from "Handbook of Applied Cryptography", page 345.
- */
-public class SHA1DigestTest
- extends DigestTest
-{
- private static String[] messages =
- {
- "",
- "a",
- "abc",
- "abcdefghijklmnopqrstuvwxyz"
- };
-
- private static String[] digests =
- {
- "da39a3ee5e6b4b0d3255bfef95601890afd80709",
- "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8",
- "a9993e364706816aba3e25717850c26c9cd0d89d",
- "32d10c7b8cf96570ca04ce37f2a19d84240d3a89"
- };
-
- SHA1DigestTest()
- {
- super(new SHA1Digest(), messages, digests);
- }
-
- protected Digest cloneDigest(Digest digest)
- {
- return new SHA1Digest((SHA1Digest)digest);
- }
-
- protected Digest cloneDigest(byte[] encodedState)
- {
- return new SHA1Digest(encodedState);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new SHA1DigestTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/SHA1HMacTest.java b/core/src/test/java/org/bouncycastle/crypto/test/SHA1HMacTest.java
deleted file mode 100644
index 72a5fdc9..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/SHA1HMacTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.macs.HMac;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-/**
- * SHA1 HMac Test, test vectors from RFC 2202
- */
-public class SHA1HMacTest
- implements Test
-{
- final static String[] keys = {
- "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
- "4a656665",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
- "0102030405060708090a0b0c0d0e0f10111213141516171819",
- "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
- "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F"
- };
-
- final static String[] digests = {
- "b617318655057264e28bc0b6fb378c8ef146be00",
- "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79",
- "125d7342b9ac11cd91a39af48aa17b4f63f175d3",
- "4c9007f4026250c6bc8414f9bf50c86c2d7235da",
- "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04",
- "aa4ae5e15272d00e95705637ce8a3b55ed402112",
- "e8e99d0f45237d786d6bbaa7965c7808bbff1a91",
- "5FD596EE78D5553C8FF4E72D266DFD192366DA29"
- };
-
- final static String[] messages = {
- "Hi There",
- "what do ya want for nothing?",
- "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
- "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
- "Test With Truncation",
- "Test Using Larger Than Block-Size Key - Hash Key First",
- "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
- "Sample message for keylen=blocklen"
- };
-
- public String getName()
- {
- return "SHA1HMac";
- }
-
- public TestResult perform()
- {
- HMac hmac = new HMac(new SHA1Digest());
- byte[] resBuf = new byte[hmac.getMacSize()];
-
- for (int i = 0; i < messages.length; i++)
- {
- byte[] m = messages[i].getBytes();
- if (messages[i].startsWith("0x"))
- {
- m = Hex.decode(messages[i].substring(2));
- }
- hmac.init(new KeyParameter(Hex.decode(keys[i])));
- hmac.update(m, 0, m.length);
- hmac.doFinal(resBuf, 0);
-
- if (!Arrays.areEqual(resBuf, Hex.decode(digests[i])))
- {
- return new SimpleTestResult(false, getName() + ": Vector " + i + " failed");
- }
- }
-
- //
- // test reset
- //
- int vector = 0; // vector used for test
- byte[] m = messages[vector].getBytes();
- if (messages[vector].startsWith("0x"))
- {
- m = Hex.decode(messages[vector].substring(2));
- }
- hmac.init(new KeyParameter(Hex.decode(keys[vector])));
- hmac.update(m, 0, m.length);
- hmac.doFinal(resBuf, 0);
- hmac.reset();
- hmac.update(m, 0, m.length);
- hmac.doFinal(resBuf, 0);
-
- if (!Arrays.areEqual(resBuf, Hex.decode(digests[vector])))
- {
- return new SimpleTestResult(false, getName() +
- "Reset with vector " + vector + " failed");
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
-
- public static void main(
- String[] args)
- {
- SHA1HMacTest test = new SHA1HMacTest();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/SHA224DigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/SHA224DigestTest.java
deleted file mode 100644
index d14f87d9..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/SHA224DigestTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA224Digest;
-
-/**
- * standard vector test for SHA-224 from RFC 3874 - only the last three are in
- * the RFC.
- */
-public class SHA224DigestTest
- extends DigestTest
-{
- private static String[] messages =
- {
- "",
- "a",
- "abc",
- "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
- };
-
- private static String[] digests =
- {
- "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f",
- "abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5",
- "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7",
- "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525"
- };
-
- // 1 million 'a'
- static private String million_a_digest = "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67";
-
- SHA224DigestTest()
- {
- super(new SHA224Digest(), messages, digests);
- }
-
- public void performTest()
- {
- super.performTest();
-
- millionATest(million_a_digest);
- }
-
- protected Digest cloneDigest(Digest digest)
- {
- return new SHA224Digest((SHA224Digest)digest);
- }
-
- protected Digest cloneDigest(byte[] encodedState)
- {
- return new SHA224Digest(encodedState);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new SHA224DigestTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/SHA224HMacTest.java b/core/src/test/java/org/bouncycastle/crypto/test/SHA224HMacTest.java
deleted file mode 100644
index 52abb16f..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/SHA224HMacTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.digests.SHA224Digest;
-import org.bouncycastle.crypto.macs.HMac;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-/**
- * SHA224 HMac Test
- */
-public class SHA224HMacTest
- implements Test
-{
- final static String[] keys = {
- "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
- "4a656665",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
- "0102030405060708090a0b0c0d0e0f10111213141516171819",
- "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- };
-
- final static String[] digests = {
- "896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22",
- "a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44",
- "7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea",
- "6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a",
- "0e2aea68a90c8d37c988bcdb9fca6fa8099cd857c7ec4a1815cac54c",
- "95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e",
- "3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1"
- };
-
- final static String[] messages = {
- "Hi There",
- "what do ya want for nothing?",
- "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
- "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
- "Test With Truncation",
- "Test Using Larger Than Block-Size Key - Hash Key First",
- "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."
- };
-
- public String getName()
- {
- return "SHA224HMac";
- }
-
- public TestResult perform()
- {
- HMac hmac = new HMac(new SHA224Digest());
- byte[] resBuf = new byte[hmac.getMacSize()];
-
- for (int i = 0; i < messages.length; i++)
- {
- byte[] m = messages[i].getBytes();
- if (messages[i].startsWith("0x"))
- {
- m = Hex.decode(messages[i].substring(2));
- }
- hmac.init(new KeyParameter(Hex.decode(keys[i])));
- hmac.update(m, 0, m.length);
- hmac.doFinal(resBuf, 0);
-
- if (!Arrays.areEqual(resBuf, Hex.decode(digests[i])))
- {
- return new SimpleTestResult(false, getName() + ": Vector " + i + " failed got -" + new String(Hex.encode(resBuf)));
- }
- }
-
- //
- // test reset
- //
- int vector = 0; // vector used for test
- byte[] m = messages[vector].getBytes();
- if (messages[vector].startsWith("0x"))
- {
- m = Hex.decode(messages[vector].substring(2));
- }
- hmac.init(new KeyParameter(Hex.decode(keys[vector])));
- hmac.update(m, 0, m.length);
- hmac.doFinal(resBuf, 0);
- hmac.reset();
- hmac.update(m, 0, m.length);
- hmac.doFinal(resBuf, 0);
-
- if (!Arrays.areEqual(resBuf, Hex.decode(digests[vector])))
- {
- return new SimpleTestResult(false, getName() +
- "Reset with vector " + vector + " failed");
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
-
- public static void main(
- String[] args)
- {
- SHA224HMacTest test = new SHA224HMacTest();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/SHA256DigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/SHA256DigestTest.java
deleted file mode 100644
index 8a35ce42..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/SHA256DigestTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-
-/**
- * standard vector test for SHA-256 from FIPS Draft 180-2.
- *
- * Note, the first two vectors are _not_ from the draft, the last three are.
- */
-public class SHA256DigestTest
- extends DigestTest
-{
- private static String[] messages =
- {
- "",
- "a",
- "abc",
- "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
- };
-
- private static String[] digests =
- {
- "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
- "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb",
- "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
- "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
- };
-
- // 1 million 'a'
- static private String million_a_digest = "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0";
-
- SHA256DigestTest()
- {
- super(new SHA256Digest(), messages, digests);
- }
-
- public void performTest()
- {
- super.performTest();
-
- millionATest(million_a_digest);
- }
-
- protected Digest cloneDigest(Digest digest)
- {
- return new SHA256Digest((SHA256Digest)digest);
- }
-
- protected Digest cloneDigest(byte[] encodedState)
- {
- return new SHA256Digest(encodedState);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new SHA256DigestTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/SHA256HMacTest.java b/core/src/test/java/org/bouncycastle/crypto/test/SHA256HMacTest.java
deleted file mode 100644
index 82ab1dc7..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/SHA256HMacTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.macs.HMac;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-/**
- * SHA256 HMac Test
- */
-public class SHA256HMacTest
- implements Test
-{
- final static String[] keys = {
- "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
- "4a656665",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
- "0102030405060708090a0b0c0d0e0f10111213141516171819",
- "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- };
-
- final static String[] digests = {
- "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7",
- "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843",
- "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe",
- "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b",
- "a3b6167473100ee06e0c796c2955552bfa6f7c0a6a8aef8b93f860aab0cd20c5",
- "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54",
- "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2"
- };
-
- final static String[] messages = {
- "Hi There",
- "what do ya want for nothing?",
- "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
- "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
- "Test With Truncation",
- "Test Using Larger Than Block-Size Key - Hash Key First",
- "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."
- };
-
- public String getName()
- {
- return "SHA256HMac";
- }
-
- public TestResult perform()
- {
- HMac hmac = new HMac(new SHA256Digest());
- byte[] resBuf = new byte[hmac.getMacSize()];
-
- for (int i = 0; i < messages.length; i++)
- {
- byte[] m = messages[i].getBytes();
- if (messages[i].startsWith("0x"))
- {
- m = Hex.decode(messages[i].substring(2));
- }
- hmac.init(new KeyParameter(Hex.decode(keys[i])));
- hmac.update(m, 0, m.length);
- hmac.doFinal(resBuf, 0);
-
- if (!Arrays.areEqual(resBuf, Hex.decode(digests[i])))
- {
- return new SimpleTestResult(false, getName() + ": Vector " + i + " failed got -" + new String(Hex.encode(resBuf)));
- }
- }
-
- //
- // test reset
- //
- int vector = 0; // vector used for test
- byte[] m = messages[vector].getBytes();
- if (messages[vector].startsWith("0x"))
- {
- m = Hex.decode(messages[vector].substring(2));
- }
- hmac.init(new KeyParameter(Hex.decode(keys[vector])));
- hmac.update(m, 0, m.length);
- hmac.doFinal(resBuf, 0);
- hmac.reset();
- hmac.update(m, 0, m.length);
- hmac.doFinal(resBuf, 0);
-
- if (!Arrays.areEqual(resBuf, Hex.decode(digests[vector])))
- {
- return new SimpleTestResult(false, getName() +
- "Reset with vector " + vector + " failed");
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
-
- public static void main(
- String[] args)
- {
- SHA256HMacTest test = new SHA256HMacTest();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/SHA384DigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/SHA384DigestTest.java
deleted file mode 100644
index 7b5f149f..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/SHA384DigestTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA384Digest;
-
-/**
- * standard vector test for SHA-384 from FIPS Draft 180-2.
- *
- * Note, the first two vectors are _not_ from the draft, the last three are.
- */
-public class SHA384DigestTest
- extends DigestTest
-{
- private static String[] messages =
- {
- "",
- "a",
- "abc",
- "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
- };
-
- private static String[] digests =
- {
- "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b",
- "54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31",
- "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7",
- "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039"
- };
-
- static private String million_a_digest = "9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985";
-
- SHA384DigestTest()
- {
- super(new SHA384Digest(), messages, digests);
- }
-
- public void performTest()
- {
- super.performTest();
-
- millionATest(million_a_digest);
- }
-
- protected Digest cloneDigest(Digest digest)
- {
- return new SHA384Digest((SHA384Digest)digest);
- }
-
- protected Digest cloneDigest(byte[] encodedState)
- {
- return new SHA384Digest(encodedState);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new SHA384DigestTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/SHA384HMacTest.java b/core/src/test/java/org/bouncycastle/crypto/test/SHA384HMacTest.java
deleted file mode 100644
index fe903a39..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/SHA384HMacTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.digests.SHA384Digest;
-import org.bouncycastle.crypto.macs.HMac;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-/**
- * SHA384 HMac Test
- */
-public class SHA384HMacTest
- implements Test
-{
- final static String[] keys = {
- "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
- "4a656665",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
- "0102030405060708090a0b0c0d0e0f10111213141516171819",
- "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- };
-
- final static String[] digests = {
- "afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6",
- "af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649",
- "88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b2a5ab39dc13814b94e3ab6e101a34f27",
- "3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e6801dd23c4a7d679ccf8a386c674cffb",
- "3abf34c3503b2a23a46efc619baef897f4c8e42c934ce55ccbae9740fcbc1af4ca62269e2a37cd88ba926341efe4aeea",
- "4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c60c2ef6ab4030fe8296248df163f44952",
- "6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5a678cc31e799176d3860e6110c46523e"
- };
-
- final static String[] messages = {
- "Hi There",
- "what do ya want for nothing?",
- "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
- "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
- "Test With Truncation",
- "Test Using Larger Than Block-Size Key - Hash Key First",
- "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."
- };
-
- public String getName()
- {
- return "SHA384HMac";
- }
-
- public TestResult perform()
- {
- HMac hmac = new HMac(new SHA384Digest());
- byte[] resBuf = new byte[hmac.getMacSize()];
-
- for (int i = 0; i < messages.length; i++)
- {
- byte[] m = messages[i].getBytes();
- if (messages[i].startsWith("0x"))
- {
- m = Hex.decode(messages[i].substring(2));
- }
- hmac.init(new KeyParameter(Hex.decode(keys[i])));
- hmac.update(m, 0, m.length);
- hmac.doFinal(resBuf, 0);
-
- if (!Arrays.areEqual(resBuf, Hex.decode(digests[i])))
- {
- return new SimpleTestResult(false, getName() + ": Vector " + i + " failed got -" + new String(Hex.encode(resBuf)));
- }
- }
-
- //
- // test reset
- //
- int vector = 0; // vector used for test
- byte[] m = messages[vector].getBytes();
- if (messages[vector].startsWith("0x"))
- {
- m = Hex.decode(messages[vector].substring(2));
- }
- hmac.init(new KeyParameter(Hex.decode(keys[vector])));
- hmac.update(m, 0, m.length);
- hmac.doFinal(resBuf, 0);
- hmac.reset();
- hmac.update(m, 0, m.length);
- hmac.doFinal(resBuf, 0);
-
- if (!Arrays.areEqual(resBuf, Hex.decode(digests[vector])))
- {
- return new SimpleTestResult(false, getName() +
- "Reset with vector " + vector + " failed");
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
-
- public static void main(
- String[] args)
- {
- SHA384HMacTest test = new SHA384HMacTest();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/SHA3DigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/SHA3DigestTest.java
deleted file mode 100644
index 260d457a..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/SHA3DigestTest.java
+++ /dev/null
@@ -1,363 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.digests.SHA3Digest;
-import org.bouncycastle.crypto.macs.HMac;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * SHA3 Digest Test
- */
-public class SHA3DigestTest
- extends SimpleTest
-{
- final static String[] messages = {
- "",
- "54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67",
- "54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f672e"
- };
-
- final static String[] digests288 = { // the default settings
- "6753e3380c09e385d0339eb6b050a68f66cfd60a73476e6fd6adeb72f5edd7c6f04a5d01", // message[0]
- "0bbe6afae0d7e89054085c1cc47b1689772c89a41796891e197d1ca1b76f288154933ded", // message[1]
- "82558a209b960ddeb531e6dcb281885b2400ca160472462486e79f071e88a3330a8a303d", // message[2]
- "94049e1ad7ef5d5b0df2b880489e7ab09ec937c3bfc1b04470e503e1ac7b1133c18f86da", // 64k a-test
- "a9cb5a75b5b81b7528301e72553ed6770214fa963956e790528afe420de33c074e6f4220", // random alphabet test
- "eadaf5ba2ad6a2f6f338fce0e1efdad2a61bb38f6be6068b01093977acf99e97a5d5827c" // extremely long data test
- };
-
- final static String[] digests224 = {
- "f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd",
- "310aee6b30c47350576ac2873fa89fd190cdc488442f3ef654cf23fe",
- "c59d4eaeac728671c635ff645014e2afa935bebffdb5fbd207ffdeab",
- "f621e11c142fbf35fa8c22841c3a812ba1e0151be4f38d80b9f1ff53",
- "68b5fc8c87193155bba68a2485377e809ee4f81a85ef023b9e64add0",
- "c42e4aee858e1a8ad2976896b9d23dd187f64436ee15969afdbc68c5"
- };
-
- final static String[] digests256 = {
- "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
- "4d741b6f1eb29cb2a9b9911c82f56fa8d73b04959d3d9d222895df6c0b28aa15",
- "578951e24efd62a3d63a86f7cd19aaa53c898fe287d2552133220370240b572d",
- "0047a916daa1f92130d870b542e22d3108444f5a7e4429f05762fb647e6ed9ed",
- "db368762253ede6d4f1db87e0b799b96e554eae005747a2ea687456ca8bcbd03",
- "5f313c39963dcf792b5470d4ade9f3a356a3e4021748690a958372e2b06f82a4"
- };
-
- final static String[] digests384 = {
- "2c23146a63a29acf99e73b88f8c24eaa7dc60aa771780ccc006afbfa8fe2479b2dd2b21362337441ac12b515911957ff",
- "283990fa9d5fb731d786c5bbee94ea4db4910f18c62c03d173fc0a5e494422e8a0b3da7574dae7fa0baf005e504063b3",
- "9ad8e17325408eddb6edee6147f13856ad819bb7532668b605a24a2d958f88bd5c169e56dc4b2f89ffd325f6006d820b",
- "c704cfe7a1a53208ca9526cd24251e0acdc252ecd978eee05acd16425cfb404ea81f5a9e2e5e97784d63ee6a0618a398",
- "d4fe8586fd8f858dd2e4dee0bafc19b4c12b4e2a856054abc4b14927354931675cdcaf942267f204ea706c19f7beefc4",
- "9b7168b4494a80a86408e6b9dc4e5a1837c85dd8ff452ed410f2832959c08c8c0d040a892eb9a755776372d4a8732315"
- };
-
- final static String[] digests512 = {
- "0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e",
- "d135bb84d0439dbac432247ee573a23ea7d3c9deb2a968eb31d47c4fb45f1ef4422d6c531b5b9bd6f449ebcc449ea94d0a8f05f62130fda612da53c79659f609",
- "ab7192d2b11f51c7dd744e7b3441febf397ca07bf812cceae122ca4ded6387889064f8db9230f173f6d1ab6e24b6e50f065b039f799f5592360a6558eb52d760",
- "34341ead153aa1d1fdcf6cf624c2b4f6894b6fd16dc38bd4ec971ac0385ad54fafcb2e0ed86a1e509456f4246fdcb02c3172824cd649d9ad54c51f7fb49ea67c",
- "dc44d4f4d36b07ab5fc04016cbe53548e5a7778671c58a43cb379fd00c06719b8073141fc22191ffc3db5f8b8983ae8341fa37f18c1c969664393aa5ceade64e",
- "3e122edaf37398231cfaca4c7c216c9d66d5b899ec1d7ac617c40c7261906a45fc01617a021e5da3bd8d4182695b5cb785a28237cbb167590e34718e56d8aab8"
- };
-
- // test vectors from http://www.di-mgt.com.au/hmac_sha3_testvectors.html
- final static byte[][] macKeys =
- {
- Hex.decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
- Hex.decode("4a656665"),
- Hex.decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
- Hex.decode("0102030405060708090a0b0c0d0e0f10111213141516171819"),
- Hex.decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaa"),
- Hex.decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaa"),
- Hex.decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
- };
-
- final static String[] macData =
- {
- "4869205468657265",
- "7768617420646f2079612077616e7420666f72206e6f7468696e673f",
- "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" +
- "dddddddddddddddddddddddddddddddddddd",
- "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" +
- "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
- "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a" +
- "65204b6579202d2048617368204b6579204669727374",
- "5468697320697320612074657374207573696e672061206c6172676572207468" +
- "616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074" +
- "68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565" +
- "647320746f20626520686173686564206265666f7265206265696e6720757365" +
- "642062792074686520484d414320616c676f726974686d2e",
- "5468697320697320612074657374207573696e672061206c6172676572207468" +
- "616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074" +
- "68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565" +
- "647320746f20626520686173686564206265666f7265206265696e6720757365\n" +
- "642062792074686520484d414320616c676f726974686d2e"
- };
-
- final static String[] mac224 =
- {
- "b73d595a2ba9af815e9f2b4e53e78581ebd34a80b3bbaac4e702c4cc",
- "e824fec96c074f22f99235bb942da1982664ab692ca8501053cbd414",
- "770df38c99d6e2bacd68056dcfe07d4c89ae20b2686a6185e1faa449",
- "305a8f2dfb94bad28861a03cbc4d590febe775c58cb4961c28428a0b",
- "e7a52dfa45f95a217c100066b239aa8ad519be9b35d667268b1b57ff",
- "ba13009405a929f398b348885caa5419191bb948ada32194afc84104",
- "92649468be236c3c72c189909c063b13f994be05749dc91310db639e"
- };
-
- final static String[] mac256 =
- {
- "9663d10c73ee294054dc9faf95647cb99731d12210ff7075fb3d3395abfb9821",
- "aa9aed448c7abc8b5e326ffa6a01cdedf7b4b831881468c044ba8dd4566369a1",
- "95f43e50f8df80a21977d51a8db3ba572dcd71db24687e6f86f47c1139b26260",
- "6331ba9b4af5804a68725b3663eb74814494b63c6093e35fb320a85d507936fd",
- "b4d0cdee7ec2ba81a88b86918958312300a15622377929a054a9ce3ae1fac2b6",
- "1fdc8cb4e27d07c10d897dec39c217792a6e64fa9c63a77ce42ad106ef284e02",
- "fdaa10a0299aecff9bb411cf2d7748a4022e4a26be3fb5b11b33d8c2b7ef5484"
- };
-
- final static String[] mac384 =
- {
- "892dfdf5d51e4679bf320cd16d4c9dc6f749744608e003add7fba894acff87361efa4e5799be06b6461f43b60ae97048",
- "5af5c9a77a23a6a93d80649e562ab77f4f3552e3c5caffd93bdf8b3cfc6920e3023fc26775d9df1f3c94613146ad2c9d",
- "4243c29f2201992ff96441e3b91ff81d8c601d706fbc83252684a4bc51101ca9b2c06ddd03677303c502ac5331752a3c",
- "b730724d3d4090cda1be799f63acbbe389fef7792fc18676fa5453aab398664650ed029c3498bbe8056f06c658e1e693",
- "d62482ef601d7847439b55236e9679388ffcd53c62cd126f39be6ea63de762e26cd5974cb9a8de401b786b5555040f6f",
- "4860ea191ac34994cf88957afe5a836ef36e4cc1a66d75bf77defb7576122d75f60660e4cf731c6effac06402787e2b9",
- "fe9357e3cfa538eb0373a2ce8f1e26ad6590afdaf266f1300522e8896d27e73f654d0631c8fa598d4bb82af6b744f4f5"
- };
-
- final static String[] mac512 =
- {
- "8852c63be8cfc21541a4ee5e5a9a852fc2f7a9adec2ff3a13718ab4ed81aaea0b87b7eb397323548e261a64e7fc75198f6663a11b22cd957f7c8ec858a1c7755",
- "c2962e5bbe1238007852f79d814dbbecd4682e6f097d37a363587c03bfa2eb0859d8d9c701e04cececfd3dd7bfd438f20b8b648e01bf8c11d26824b96cebbdcb",
- "eb0ed9580e0ec11fc66cbb646b1be904eaff6da4556d9334f65ee4b2c85739157bae9027c51505e49d1bb81cfa55e6822db55262d5a252c088a29a5e95b84a66",
- "b46193bb59f4f696bf702597616da91e2a4558a593f4b015e69141ba81e1e50ea580834c2b87f87baa25a3a03bfc9bb389847f2dc820beae69d30c4bb75369cb",
- "d05888a6ebf8460423ea7bc85ea4ffda847b32df32291d2ce115fd187707325c7ce4f71880d91008084ce24a38795d20e6a28328a0f0712dc38253370da3ebb5",
- "2c6b9748d35c4c8db0b4407dd2ed2381f133bdbd1dfaa69e30051eb6badfcca64299b88ae05fdbd3dd3dd7fe627e42e39e48b0fe8c7f1e85f2dbd52c2d753572",
- "6adc502f14e27812402fc81a807b28bf8a53c87bea7a1df6256bf66f5de1a4cb741407ad15ab8abc136846057f881969fbb159c321c904bfb557b77afb7778c8"
- };
-
- final static KeyParameter truncKey = new KeyParameter(Hex.decode("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c"));
- final static byte[] truncData = Hex.decode("546573742057697468205472756e636174696f6e");
-
- final static byte[] trunc224 = Hex.decode("f52bbcfd654264e7133085c5e69b72c3");
- final static byte[] trunc256 = Hex.decode("745e7e687f8335280d54202ef13cecc6");
- final static byte[] trunc384 = Hex.decode("fa9aea2bc1e181e47cbb8c3df243814d");
- final static byte[] trunc512 = Hex.decode("04c929fead434bba190dacfa554ce3f5");
-
- final static byte[] xtremeData = Hex.decode("61626364656667686263646566676869636465666768696a6465666768696a6b65666768696a6b6c666768696a6b6c6d6768696a6b6c6d6e68696a6b6c6d6e6f");
-
- SHA3DigestTest()
- {
- }
-
- public String getName()
- {
- return "SHA3";
- }
-
- private void testDigest(Digest digest, String[] expected)
- {
- byte[] hash = new byte[digest.getDigestSize()];
-
- for (int i = 0; i != messages.length; i++)
- {
- if (messages.length != 0)
- {
- byte[] data = Hex.decode(messages[i]);
-
- digest.update(data, 0, data.length);
- }
-
- digest.doFinal(hash, 0);
-
- if (!Arrays.areEqual(Hex.decode(expected[i]), hash))
- {
- fail("sha3 mismatch on " + digest.getAlgorithmName() + " index " + i);
- }
- }
-
- byte[] k64 = new byte[1024 * 64];
-
- for (int i = 0; i != k64.length; i++)
- {
- k64[i] = (byte)'a';
- }
-
- digest.update(k64, 0, k64.length);
-
- digest.doFinal(hash, 0);
-
- if (!Arrays.areEqual(Hex.decode(expected[messages.length]), hash))
- {
- fail("sha3 mismatch on " + digest.getAlgorithmName() + " 64k a");
- }
-
- for (int i = 0; i != k64.length; i++)
- {
- digest.update((byte)'a');
- }
-
- digest.doFinal(hash, 0);
-
- if (!Arrays.areEqual(Hex.decode(expected[messages.length]), hash))
- {
- fail("sha3 mismatch on " + digest.getAlgorithmName() + " 64k a single");
- }
-
-
- for (int i = 0; i != k64.length; i++)
- {
- k64[i] = (byte)('a' + (i % 26));
- }
-
- digest.update(k64, 0, k64.length);
-
- digest.doFinal(hash, 0);
-
- if (!Arrays.areEqual(Hex.decode(expected[messages.length + 1]), hash))
- {
- fail("sha3 mismatch on " + digest.getAlgorithmName() + " 64k alpha");
- }
-
- for (int i = 0; i != 64; i++)
- {
- digest.update(k64[i * 1024]);
- digest.update(k64, i * 1024 + 1, 1023);
- }
-
- digest.doFinal(hash, 0);
-
- if (!Arrays.areEqual(Hex.decode(expected[messages.length + 1]), hash))
- {
- fail("sha3 mismatch on " + digest.getAlgorithmName() + " 64k chunked alpha");
- }
-
- testDigestDoFinal(digest);
-
- //
- // extremely long data test
- //
-// System.out.println("Starting very long");
-// for (int i = 0; i != 16384; i++)
-// {
-// for (int j = 0; j != 1024; j++)
-// {
-// digest.update(xtremeData, 0, xtremeData.length);
-// }
-// }
-//
-// digest.doFinal(hash, 0);
-//
-// if (!Arrays.areEqual(Hex.decode(expected[messages.length + 2]), hash))
-// {
-// fail("sha3 mismatch on " + digest.getAlgorithmName() + " extreme data test");
-// }
-// System.out.println("Done");
- }
-
- private void testDigestDoFinal(Digest digest)
- {
- byte[] hash = new byte[digest.getDigestSize()];
- digest.doFinal(hash, 0);
-
- for (int i = 0; i <= digest.getDigestSize(); ++i)
- {
- byte[] cmp = new byte[2 * digest.getDigestSize()];
- System.arraycopy(hash, 0, cmp, i, hash.length);
-
- byte[] buf = new byte[2 * digest.getDigestSize()];
- digest.doFinal(buf, i);
-
- if (!Arrays.areEqual(cmp, buf))
- {
- fail("sha3 offset doFinal on " + digest.getAlgorithmName());
- }
- }
- }
-
- private void testMac(Digest digest, byte[][] keys, String[] data, String[] expected, byte[] truncExpected)
- {
- Mac mac = new HMac(digest);
-
- for (int i = 0; i != keys.length; i++)
- {
- mac.init(new KeyParameter(keys[i]));
-
- byte[] mData = Hex.decode(data[i]);
-
- mac.update(mData, 0, mData.length);
-
- byte[] macV = new byte[mac.getMacSize()];
-
- mac.doFinal(macV, 0);
-
- if (!Arrays.areEqual(Hex.decode(expected[i]), macV))
- {
- fail("sha3 HMAC mismatch on " + digest.getAlgorithmName());
- }
- }
-
- mac = new HMac(digest);
-
- mac.init(truncKey);
-
- mac.update(truncData, 0, truncData.length);
-
- byte[] macV = new byte[mac.getMacSize()];
-
- mac.doFinal(macV, 0);
-
- for (int i = 0; i != truncExpected.length; i++)
- {
- if (macV[i] != truncExpected[i])
- {
- fail("mismatch on truncated HMAC for " + digest.getAlgorithmName());
- }
- }
- }
-
- public void performTest()
- {
- testDigest(new SHA3Digest(), digests288);
- testDigest(new SHA3Digest(224), digests224);
- testDigest(new SHA3Digest(256), digests256);
- testDigest(new SHA3Digest(384), digests384);
- testDigest(new SHA3Digest(512), digests512);
-
- testMac(new SHA3Digest(224), macKeys, macData, mac224, trunc224);
- testMac(new SHA3Digest(256), macKeys, macData, mac256, trunc256);
- testMac(new SHA3Digest(384), macKeys, macData, mac384, trunc384);
- testMac(new SHA3Digest(512), macKeys, macData, mac512, trunc512);
- }
-
- protected Digest cloneDigest(Digest digest)
- {
- return new SHA3Digest((SHA3Digest)digest);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new SHA3DigestTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/SHA512DigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/SHA512DigestTest.java
deleted file mode 100644
index ffebaee4..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/SHA512DigestTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA512Digest;
-
-/**
- * standard vector test for SHA-512 from FIPS Draft 180-2.
- *
- * Note, the first two vectors are _not_ from the draft, the last three are.
- */
-public class SHA512DigestTest
- extends DigestTest
-{
- private static String[] messages =
- {
- "",
- "a",
- "abc",
- "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
- };
-
- private static String[] digests =
- {
- "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e",
- "1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75",
- "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
- "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"
- };
-
- // 1 million 'a'
- static private String million_a_digest = "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b";
-
- SHA512DigestTest()
- {
- super(new SHA512Digest(), messages, digests);
- }
-
- public void performTest()
- {
- super.performTest();
-
- millionATest(million_a_digest);
- }
-
- protected Digest cloneDigest(Digest digest)
- {
- return new SHA512Digest((SHA512Digest)digest);
- }
-
- protected Digest cloneDigest(byte[] encodedState)
- {
- return new SHA512Digest(encodedState);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new SHA512DigestTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/SHA512HMacTest.java b/core/src/test/java/org/bouncycastle/crypto/test/SHA512HMacTest.java
deleted file mode 100644
index ee163eb5..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/SHA512HMacTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.digests.SHA512Digest;
-import org.bouncycastle.crypto.macs.HMac;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-/**
- * SHA512 HMac Test
- */
-public class SHA512HMacTest
- implements Test
-{
- final static String[] keys = {
- "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
- "4a656665",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
- "0102030405060708090a0b0c0d0e0f10111213141516171819",
- "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- };
-
- final static String[] digests = {
- "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854",
- "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737",
- "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb",
- "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd",
- "415fad6271580a531d4179bc891d87a650188707922a4fbb36663a1eb16da008711c5b50ddd0fc235084eb9d3364a1454fb2ef67cd1d29fe6773068ea266e96b",
- "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598",
- "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58"
- };
-
- final static String[] messages = {
- "Hi There",
- "what do ya want for nothing?",
- "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
- "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
- "Test With Truncation",
- "Test Using Larger Than Block-Size Key - Hash Key First",
- "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."
- };
-
- public String getName()
- {
- return "SHA512HMac";
- }
-
- public TestResult perform()
- {
- HMac hmac = new HMac(new SHA512Digest());
- byte[] resBuf = new byte[hmac.getMacSize()];
-
- for (int i = 0; i < messages.length; i++)
- {
- byte[] m = messages[i].getBytes();
- if (messages[i].startsWith("0x"))
- {
- m = Hex.decode(messages[i].substring(2));
- }
- hmac.init(new KeyParameter(Hex.decode(keys[i])));
- hmac.update(m, 0, m.length);
- hmac.doFinal(resBuf, 0);
-
- if (!Arrays.areEqual(resBuf, Hex.decode(digests[i])))
- {
- return new SimpleTestResult(false, getName() + ": Vector " + i + " failed got -" + new String(Hex.encode(resBuf)));
- }
- }
-
- //
- // test reset
- //
- int vector = 0; // vector used for test
- byte[] m = messages[vector].getBytes();
- if (messages[vector].startsWith("0x"))
- {
- m = Hex.decode(messages[vector].substring(2));
- }
- hmac.init(new KeyParameter(Hex.decode(keys[vector])));
- hmac.update(m, 0, m.length);
- hmac.doFinal(resBuf, 0);
- hmac.reset();
- hmac.update(m, 0, m.length);
- hmac.doFinal(resBuf, 0);
-
- if (!Arrays.areEqual(resBuf, Hex.decode(digests[vector])))
- {
- return new SimpleTestResult(false, getName() +
- "Reset with vector " + vector + " failed");
- }
-
- return new SimpleTestResult(true, getName() + ": Okay");
- }
-
- public static void main(
- String[] args)
- {
- SHA512HMacTest test = new SHA512HMacTest();
- TestResult result = test.perform();
-
- System.out.println(result);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/SHA512t224DigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/SHA512t224DigestTest.java
deleted file mode 100644
index 0c7bc954..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/SHA512t224DigestTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA512tDigest;
-
-/**
- * standard vector test for SHA-512/224 from FIPS 180-4.
- *
- * Note, only the last 2 message entries are FIPS originated..
- */
-public class SHA512t224DigestTest
- extends DigestTest
-{
- private static String[] messages =
- {
- "",
- "a",
- "abc",
- "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
- };
-
- private static String[] digests =
- {
- "6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4",
- "d5cdb9ccc769a5121d4175f2bfdd13d6310e0d3d361ea75d82108327",
- "4634270F707B6A54DAAE7530460842E20E37ED265CEEE9A43E8924AA",
- "23FEC5BB94D60B23308192640B0C453335D664734FE40E7268674AF9"
- };
-
- // 1 million 'a'
- static private String million_a_digest = "37ab331d76f0d36de422bd0edeb22a28accd487b7a8453ae965dd287";
-
- SHA512t224DigestTest()
- {
- super(new SHA512tDigest(224), messages, digests);
- }
-
- public void performTest()
- {
- super.performTest();
-
- millionATest(million_a_digest);
- }
-
- protected Digest cloneDigest(Digest digest)
- {
- return new SHA512tDigest((SHA512tDigest)digest);
- }
-
- protected Digest cloneDigest(byte[] encodedState)
- {
- return new SHA512tDigest(encodedState);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new SHA512t224DigestTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/SHA512t256DigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/SHA512t256DigestTest.java
deleted file mode 100644
index db019ae6..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/SHA512t256DigestTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA512tDigest;
-
-/**
- * standard vector test for SHA-512/256 from FIPS 180-4.
- *
- * Note, only the last 2 message entries are FIPS originated..
- */
-public class SHA512t256DigestTest
- extends DigestTest
-{
- private static String[] messages =
- {
- "",
- "a",
- "abc",
- "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
- };
-
- private static String[] digests =
- {
- "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a",
- "455e518824bc0601f9fb858ff5c37d417d67c2f8e0df2babe4808858aea830f8",
- "53048E2681941EF99B2E29B76B4C7DABE4C2D0C634FC6D46E0E2F13107E7AF23",
- "3928E184FB8690F840DA3988121D31BE65CB9D3EF83EE6146FEAC861E19B563A"
- };
-
- // 1 million 'a'
- static private String million_a_digest = "9a59a052930187a97038cae692f30708aa6491923ef5194394dc68d56c74fb21";
-
- SHA512t256DigestTest()
- {
- super(new SHA512tDigest(256), messages, digests);
- }
-
- public void performTest()
- {
- super.performTest();
-
- millionATest(million_a_digest);
- }
-
- protected Digest cloneDigest(Digest digest)
- {
- return new SHA512tDigest((SHA512tDigest)digest);
- }
-
- protected Digest cloneDigest(byte[] encodedState)
- {
- return new SHA512tDigest(encodedState);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new SHA512t256DigestTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/SM3DigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/SM3DigestTest.java
deleted file mode 100644
index 2d418cb5..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/SM3DigestTest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SM3Digest;
-
-/**
- * standard vector test for SM3 digest from chinese specification
- */
-public class SM3DigestTest
- extends DigestTest
-{
- private static String[] messages = {
- // Standard test vectors
- "abc",
- "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd",
- // Non-standard test vectors
- "",
- "a",
- "abcdefghijklmnopqrstuvwxyz",
- };
-
- private static String[] digests = {
- // Standard test vectors
- "66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0",
- "debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c5732",
- // Non-standard test vectors
- "1ab21d8355cfa17f8e61194831e81a8f22bec8c728fefb747ed035eb5082aa2b",
- "623476ac18f65a2909e43c7fec61b49c7e764a91a18ccb82f1917a29c86c5e88",
- "b80fe97a4da24afc277564f66a359ef440462ad28dcc6d63adb24d5c20a61595",
- };
-
- final static String sixtyFourKdigest = "97049bdc8f0736bc7300eafa9980aeb9cf00f24f7ec3a8f1f8884954d7655c1d";
- final static String million_a_digest = "c8aaf89429554029e231941a2acc0ad61ff2a5acd8fadd25847a3a732b3b02c3";
-
- SM3DigestTest()
- {
- super(new SM3Digest(), messages, digests);
- }
-
- public void performTest()
- {
- super.performTest();
-
- sixtyFourKTest(sixtyFourKdigest);
- millionATest(million_a_digest);
- }
-
- protected Digest cloneDigest(Digest digest)
- {
- return new SM3Digest((SM3Digest)digest);
- }
-
- public static void main(String[] args)
- {
- runTest(new SM3DigestTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/SRP6Test.java b/core/src/test/java/org/bouncycastle/crypto/test/SRP6Test.java
deleted file mode 100644
index 349c2197..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/SRP6Test.java
+++ /dev/null
@@ -1,276 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.agreement.srp.SRP6Client;
-import org.bouncycastle.crypto.agreement.srp.SRP6Server;
-import org.bouncycastle.crypto.agreement.srp.SRP6Util;
-import org.bouncycastle.crypto.agreement.srp.SRP6VerifierGenerator;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.generators.DHParametersGenerator;
-import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class SRP6Test extends SimpleTest
-{
- private static final BigInteger ZERO = BigInteger.valueOf(0);
-
- private static BigInteger fromHex(String hex)
- {
- return new BigInteger(1, Hex.decode(hex));
- }
-
- // 1024 bit example prime from RFC5054 and corresponding generator
- private static final BigInteger N_1024 = fromHex("EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C"
- + "9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE4"
- + "8E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B29"
- + "7BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9A"
- + "FD5138FE8376435B9FC61D2FC0EB06E3");
- private static final BigInteger g_1024 = BigInteger.valueOf(2);
-
- private final SecureRandom random = new SecureRandom();
-
- public String getName()
- {
- return "SRP6";
- }
-
- public void performTest() throws Exception
- {
- rfc5054AppendixBTestVectors();
-
- testMutualVerification(N_1024, g_1024);
- testClientCatchesBadB(N_1024, g_1024);
- testServerCatchesBadA(N_1024, g_1024);
-
- testWithRandomParams(256);
- testWithRandomParams(384);
- testWithRandomParams(512);
- }
-
- private void rfc5054AppendixBTestVectors() throws Exception
- {
- byte[] I = "alice".getBytes("UTF8");
- byte[] P = "password123".getBytes("UTF8");
- byte[] s = Hex.decode("BEB25379D1A8581EB5A727673A2441EE");
- BigInteger N = N_1024;
- BigInteger g = g_1024;
- BigInteger a = fromHex("60975527035CF2AD1989806F0407210BC81EDC04E2762A56AFD529DDDA2D4393");
- BigInteger b = fromHex("E487CB59D31AC550471E81F00F6928E01DDA08E974A004F49E61F5D105284D20");
-
- BigInteger expect_k = fromHex("7556AA045AEF2CDD07ABAF0F665C3E818913186F");
- BigInteger expect_x = fromHex("94B7555AABE9127CC58CCF4993DB6CF84D16C124");
- BigInteger expect_v = fromHex("7E273DE8696FFC4F4E337D05B4B375BEB0DDE1569E8FA00A9886D812"
- + "9BADA1F1822223CA1A605B530E379BA4729FDC59F105B4787E5186F5"
- + "C671085A1447B52A48CF1970B4FB6F8400BBF4CEBFBB168152E08AB5"
- + "EA53D15C1AFF87B2B9DA6E04E058AD51CC72BFC9033B564E26480D78"
- + "E955A5E29E7AB245DB2BE315E2099AFB");
- BigInteger expect_A = fromHex("61D5E490F6F1B79547B0704C436F523DD0E560F0C64115BB72557EC4"
- + "4352E8903211C04692272D8B2D1A5358A2CF1B6E0BFCF99F921530EC"
- + "8E39356179EAE45E42BA92AEACED825171E1E8B9AF6D9C03E1327F44"
- + "BE087EF06530E69F66615261EEF54073CA11CF5858F0EDFDFE15EFEA"
- + "B349EF5D76988A3672FAC47B0769447B");
- BigInteger expect_B = fromHex("BD0C61512C692C0CB6D041FA01BB152D4916A1E77AF46AE105393011"
- + "BAF38964DC46A0670DD125B95A981652236F99D9B681CBF87837EC99"
- + "6C6DA04453728610D0C6DDB58B318885D7D82C7F8DEB75CE7BD4FBAA"
- + "37089E6F9C6059F388838E7A00030B331EB76840910440B1B27AAEAE"
- + "EB4012B7D7665238A8E3FB004B117B58");
- BigInteger expect_u = fromHex("CE38B9593487DA98554ED47D70A7AE5F462EF019");
- BigInteger expect_S = fromHex("B0DC82BABCF30674AE450C0287745E7990A3381F63B387AAF271A10D"
- + "233861E359B48220F7C4693C9AE12B0A6F67809F0876E2D013800D6C"
- + "41BB59B6D5979B5C00A172B4A2A5903A0BDCAF8A709585EB2AFAFA8F"
- + "3499B200210DCC1F10EB33943CD67FC88A2F39A4BE5BEC4EC0A3212D"
- + "C346D7E474B29EDE8A469FFECA686E5A");
-
- BigInteger k = SRP6Util.calculateK(new SHA1Digest(), N, g);
- if (!k.equals(expect_k))
- {
- fail("wrong value of 'k'");
- }
-
- BigInteger x = SRP6Util.calculateX(new SHA1Digest(), N, s, I, P);
- if (!x.equals(expect_x))
- {
- fail("wrong value of 'x'");
- }
-
- SRP6VerifierGenerator gen = new SRP6VerifierGenerator();
- gen.init(N, g, new SHA1Digest());
- BigInteger v = gen.generateVerifier(s, I, P);
- if (!v.equals(expect_v))
- {
- fail("wrong value of 'v'");
- }
-
- final BigInteger aVal = a;
- SRP6Client client = new SRP6Client()
- {
- protected BigInteger selectPrivateValue()
- {
- return aVal;
- }
- };
- client.init(N, g, new SHA1Digest(), random);
-
- BigInteger A = client.generateClientCredentials(s, I, P);
- if (!A.equals(expect_A))
- {
- fail("wrong value of 'A'");
- }
-
- final BigInteger bVal = b;
- SRP6Server server = new SRP6Server()
- {
- protected BigInteger selectPrivateValue()
- {
- return bVal;
- }
- };
- server.init(N, g, v, new SHA1Digest(), random);
-
- BigInteger B = server.generateServerCredentials();
- if (!B.equals(expect_B))
- {
- fail("wrong value of 'B'");
- }
-
- BigInteger u = SRP6Util.calculateU(new SHA1Digest(), N, A, B);
- if (!u.equals(expect_u))
- {
- fail("wrong value of 'u'");
- }
-
- BigInteger clientS = client.calculateSecret(B);
- if (!clientS.equals(expect_S))
- {
- fail("wrong value of 'S' (client)");
- }
-
- BigInteger serverS = server.calculateSecret(A);
- if (!serverS.equals(expect_S))
- {
- fail("wrong value of 'S' (server)");
- }
- }
-
- private void testWithRandomParams(int bits) throws CryptoException
- {
- DHParametersGenerator paramGen = new DHParametersGenerator();
- paramGen.init(bits, 25, random);
- DHParameters parameters = paramGen.generateParameters();
-
- BigInteger g = parameters.getG();
- BigInteger p = parameters.getP();
-
- testMutualVerification(p, g);
- }
-
- private void testMutualVerification(BigInteger N, BigInteger g) throws CryptoException
- {
- byte[] I = "username".getBytes();
- byte[] P = "password".getBytes();
- byte[] s = new byte[16];
- random.nextBytes(s);
-
- SRP6VerifierGenerator gen = new SRP6VerifierGenerator();
- gen.init(N, g, new SHA256Digest());
- BigInteger v = gen.generateVerifier(s, I, P);
-
- SRP6Client client = new SRP6Client();
- client.init(N, g, new SHA256Digest(), random);
-
- SRP6Server server = new SRP6Server();
- server.init(N, g, v, new SHA256Digest(), random);
-
- BigInteger A = client.generateClientCredentials(s, I, P);
- BigInteger B = server.generateServerCredentials();
-
- BigInteger clientS = client.calculateSecret(B);
- BigInteger serverS = server.calculateSecret(A);
-
- if (!clientS.equals(serverS))
- {
- fail("SRP agreement failed - client/server calculated different secrets");
- }
- }
-
- private void testClientCatchesBadB(BigInteger N, BigInteger g)
- {
- byte[] I = "username".getBytes();
- byte[] P = "password".getBytes();
- byte[] s = new byte[16];
- random.nextBytes(s);
-
- SRP6Client client = new SRP6Client();
- client.init(N, g, new SHA256Digest(), random);
-
- client.generateClientCredentials(s, I, P);
-
- try
- {
- client.calculateSecret(ZERO);
- fail("Client failed to detect invalid value for 'B'");
- }
- catch (CryptoException e)
- {
- // Expected
- }
-
- try
- {
- client.calculateSecret(N);
- fail("Client failed to detect invalid value for 'B'");
- }
- catch (CryptoException e)
- {
- // Expected
- }
- }
-
- private void testServerCatchesBadA(BigInteger N, BigInteger g)
- {
- byte[] I = "username".getBytes();
- byte[] P = "password".getBytes();
- byte[] s = new byte[16];
- random.nextBytes(s);
-
- SRP6VerifierGenerator gen = new SRP6VerifierGenerator();
- gen.init(N, g, new SHA256Digest());
- BigInteger v = gen.generateVerifier(s, I, P);
-
- SRP6Server server = new SRP6Server();
- server.init(N, g, v, new SHA256Digest(), random);
-
- server.generateServerCredentials();
-
- try
- {
- server.calculateSecret(ZERO);
- fail("Client failed to detect invalid value for 'A'");
- }
- catch (CryptoException e)
- {
- // Expected
- }
-
- try
- {
- server.calculateSecret(N);
- fail("Client failed to detect invalid value for 'A'");
- }
- catch (CryptoException e)
- {
- // Expected
- }
- }
-
- public static void main(String[] args)
- {
- runTest(new SRP6Test());
- }
-}
-
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/Salsa20Test.java b/core/src/test/java/org/bouncycastle/crypto/test/Salsa20Test.java
deleted file mode 100644
index 940fb573..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/Salsa20Test.java
+++ /dev/null
@@ -1,400 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.StreamCipher;
-import org.bouncycastle.crypto.engines.Salsa20Engine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * Salsa20 Test
- */
-public class Salsa20Test
- extends SimpleTest
-{
- byte[] zeroes = Hex.decode(
- "00000000000000000000000000000000"
- + "00000000000000000000000000000000"
- + "00000000000000000000000000000000"
- + "00000000000000000000000000000000");
-
- String set1v0_0 = "4DFA5E481DA23EA09A31022050859936"
- + "DA52FCEE218005164F267CB65F5CFD7F"
- + "2B4F97E0FF16924A52DF269515110A07"
- + "F9E460BC65EF95DA58F740B7D1DBB0AA";
-
- String set1v0_192 = "DA9C1581F429E0A00F7D67E23B730676"
- + "783B262E8EB43A25F55FB90B3E753AEF"
- + "8C6713EC66C51881111593CCB3E8CB8F"
- + "8DE124080501EEEB389C4BCB6977CF95";
-
- String set1v0_256 = "7D5789631EB4554400E1E025935DFA7B"
- + "3E9039D61BDC58A8697D36815BF1985C"
- + "EFDF7AE112E5BB81E37ECF0616CE7147"
- + "FC08A93A367E08631F23C03B00A8DA2F";
-
- String set1v0_448 = "B375703739DACED4DD4059FD71C3C47F"
- + "C2F9939670FAD4A46066ADCC6A564578"
- + "3308B90FFB72BE04A6B147CBE38CC0C3"
- + "B9267C296A92A7C69873F9F263BE9703";
-
- String set1v9_0 = "0471076057830FB99202291177FBFE5D"
- + "38C888944DF8917CAB82788B91B53D1C"
- + "FB06D07A304B18BB763F888A61BB6B75"
- + "5CD58BEC9C4CFB7569CB91862E79C459";
-
- String set1v9_192 = "D1D7E97556426E6CFC21312AE3811425"
- + "9E5A6FB10DACBD88E4354B0472556935"
- + "2B6DA5ACAFACD5E266F9575C2ED8E6F2"
- + "EFE4B4D36114C3A623DD49F4794F865B";
-
- String set1v9_256 = "AF06FAA82C73291231E1BD916A773DE1"
- + "52FD2126C40A10C3A6EB40F22834B8CC"
- + "68BD5C6DBD7FC1EC8F34165C517C0B63"
- + "9DB0C60506D3606906B8463AA0D0EC2F";
-
- String set1v9_448 = "AB3216F1216379EFD5EC589510B8FD35"
- + "014D0AA0B613040BAE63ECAB90A9AF79"
- + "661F8DA2F853A5204B0F8E72E9D9EB4D"
- + "BA5A4690E73A4D25F61EE7295215140C";
-
- String set6v0_0 = "F5FAD53F79F9DF58C4AEA0D0ED9A9601"
- + "F278112CA7180D565B420A48019670EA"
- + "F24CE493A86263F677B46ACE1924773D"
- + "2BB25571E1AA8593758FC382B1280B71";
-
- String set6v0_65472 = "B70C50139C63332EF6E77AC54338A407"
- + "9B82BEC9F9A403DFEA821B83F7860791"
- + "650EF1B2489D0590B1DE772EEDA4E3BC"
- + "D60FA7CE9CD623D9D2FD5758B8653E70";
-
- String set6v0_65536 = "81582C65D7562B80AEC2F1A673A9D01C"
- + "9F892A23D4919F6AB47B9154E08E699B"
- + "4117D7C666477B60F8391481682F5D95"
- + "D96623DBC489D88DAA6956B9F0646B6E";
-
- String set6v1_0 = "3944F6DC9F85B128083879FDF190F7DE"
- + "E4053A07BC09896D51D0690BD4DA4AC1"
- + "062F1E47D3D0716F80A9B4D85E6D6085"
- + "EE06947601C85F1A27A2F76E45A6AA87";
-
- String set6v1_65472 = "36E03B4B54B0B2E04D069E690082C8C5"
- + "92DF56E633F5D8C7682A02A65ECD1371"
- + "8CA4352AACCB0DA20ED6BBBA62E177F2"
- + "10E3560E63BB822C4158CAA806A88C82";
-
- String set6v1_65536 = "1B779E7A917C8C26039FFB23CF0EF8E0"
- + "8A1A13B43ACDD9402CF5DF38501098DF"
- + "C945A6CC69A6A17367BC03431A86B3ED"
- + "04B0245B56379BF997E25800AD837D7D";
-
- // Salsa20/12
- String salsa12_set1v0_0 = "FC207DBFC76C5E1774961E7A5AAD0906"
- + "9B2225AC1CE0FE7A0CE77003E7E5BDF8"
- + "B31AF821000813E6C56B8C1771D6EE70"
- + "39B2FBD0A68E8AD70A3944B677937897";
-
- String salsa12_set1v0_192 = "4B62A4881FA1AF9560586510D5527ED4"
- + "8A51ECAFA4DECEEBBDDC10E9918D44AB"
- + "26B10C0A31ED242F146C72940C6E9C37"
- + "53F641DA84E9F68B4F9E76B6C48CA5AC";
-
- String salsa12_set1v0_256 = "F52383D9DEFB20810325F7AEC9EADE34"
- + "D9D883FEE37E05F74BF40875B2D0BE79"
- + "ED8886E5BFF556CEA8D1D9E86B1F68A9"
- + "64598C34F177F8163E271B8D2FEB5996";
-
- String salsa12_set1v0_448 = "A52ED8C37014B10EC0AA8E05B5CEEE12"
- + "3A1017557FB3B15C53E6C5EA8300BF74"
- + "264A73B5315DC821AD2CAB0F3BB2F152"
- + "BDAEA3AEE97BA04B8E72A7B40DCC6BA4";
-
- // Salsa20/8
- String salsa8_set1v0_0 = "A9C9F888AB552A2D1BBFF9F36BEBEB33"
- + "7A8B4B107C75B63BAE26CB9A235BBA9D"
- + "784F38BEFC3ADF4CD3E266687EA7B9F0"
- + "9BA650AE81EAC6063AE31FF12218DDC5";
-
- String salsa8_set1v0_192 = "BB5B6BB2CC8B8A0222DCCC1753ED4AEB"
- + "23377ACCBD5D4C0B69A8A03BB115EF71"
- + "871BC10559080ACA7C68F0DEF32A80DD"
- + "BAF497259BB76A3853A7183B51CC4B9F";
-
- String salsa8_set1v0_256 = "4436CDC0BE39559F5E5A6B79FBDB2CAE"
- + "4782910F27FFC2391E05CFC78D601AD8"
- + "CD7D87B074169361D997D1BED9729C0D"
- + "EB23418E0646B7997C06AA84E7640CE3";
-
- String salsa8_set1v0_448 = "BEE85903BEA506B05FC04795836FAAAC"
- + "7F93F785D473EB762576D96B4A65FFE4"
- + "63B34AAE696777FC6351B67C3753B89B"
- + "A6B197BD655D1D9CA86E067F4D770220";
-
-
- public String getName()
- {
- return "Salsa20";
- }
-
- public void performTest()
- {
- salsa20Test1(20, new ParametersWithIV(new KeyParameter(Hex.decode("80000000000000000000000000000000")), Hex.decode("0000000000000000")),
- set1v0_0, set1v0_192, set1v0_256, set1v0_448);
- salsa20Test1(20, new ParametersWithIV(new KeyParameter(Hex.decode("00400000000000000000000000000000")), Hex.decode("0000000000000000")),
- set1v9_0, set1v9_192, set1v9_256, set1v9_448);
- salsa20Test1(12, new ParametersWithIV(new KeyParameter(Hex.decode("80000000000000000000000000000000")), Hex.decode("0000000000000000")),
- salsa12_set1v0_0, salsa12_set1v0_192, salsa12_set1v0_256, salsa12_set1v0_448);
- salsa20Test1(8, new ParametersWithIV(new KeyParameter(Hex.decode("80000000000000000000000000000000")), Hex.decode("0000000000000000")),
- salsa8_set1v0_0, salsa8_set1v0_192, salsa8_set1v0_256, salsa8_set1v0_448);
- salsa20Test2(new ParametersWithIV(new KeyParameter(Hex.decode("0053A6F94C9FF24598EB3E91E4378ADD3083D6297CCF2275C81B6EC11467BA0D")), Hex.decode("0D74DB42A91077DE")),
- set6v0_0, set6v0_65472, set6v0_65536);
- salsa20Test2(new ParametersWithIV(new KeyParameter(Hex.decode("0558ABFE51A4F74A9DF04396E93C8FE23588DB2E81D4277ACD2073C6196CBF12")), Hex.decode("167DE44BB21980E7")),
- set6v1_0, set6v1_65472, set6v1_65536);
- reinitBug();
- skipTest();
- }
-
- private void salsa20Test1(int rounds, CipherParameters params, String v0, String v192, String v256, String v448)
- {
- StreamCipher salsa = new Salsa20Engine(rounds);
- byte[] buf = new byte[64];
-
- salsa.init(true, params);
-
- for (int i = 0; i != 7; i++)
- {
- salsa.processBytes(zeroes, 0, 64, buf, 0);
- switch (i)
- {
- case 0:
- if (!areEqual(buf, Hex.decode(v0)))
- {
- mismatch("v0/" + rounds, v0, buf);
- }
- break;
- case 3:
- if (!areEqual(buf, Hex.decode(v192)))
- {
- mismatch("v192/" + rounds, v192, buf);
- }
- break;
- case 4:
- if (!areEqual(buf, Hex.decode(v256)))
- {
- mismatch("v256/" + rounds, v256, buf);
- }
- break;
- default:
- // ignore
- }
- }
-
- for (int i = 0; i != 64; i++)
- {
- buf[i] = salsa.returnByte(zeroes[i]);
- }
-
- if (!areEqual(buf, Hex.decode(v448)))
- {
- mismatch("v448", v448, buf);
- }
- }
-
- private void salsa20Test2(CipherParameters params, String v0, String v65472, String v65536)
- {
- StreamCipher salsa = new Salsa20Engine();
- byte[] buf = new byte[64];
-
- salsa.init(true, params);
-
- for (int i = 0; i != 1025; i++)
- {
- salsa.processBytes(zeroes, 0, 64, buf, 0);
- switch (i)
- {
- case 0:
- if (!areEqual(buf, Hex.decode(v0)))
- {
- mismatch("v0", v0, buf);
- }
- break;
- case 1023:
- if (!areEqual(buf, Hex.decode(v65472)))
- {
- mismatch("v65472", v65472, buf);
- }
- break;
- case 1024:
- if (!areEqual(buf, Hex.decode(v65536)))
- {
- mismatch("v65536", v65536, buf);
- }
- break;
- default:
- // ignore
- }
- }
- }
-
- private void mismatch(String name, String expected, byte[] found)
- {
- fail("mismatch on " + name, expected, new String(Hex.encode(found)));
- }
-
-
- private void reinitBug()
- {
- KeyParameter key = new KeyParameter(Hex.decode("80000000000000000000000000000000"));
- ParametersWithIV parameters = new ParametersWithIV(key, Hex.decode("0000000000000000"));
-
- StreamCipher salsa = new Salsa20Engine();
-
- salsa.init(true, parameters);
-
- try
- {
- salsa.init(true, key);
- fail("Salsa20 should throw exception if no IV in Init");
- }
- catch (IllegalArgumentException e)
- {
- }
- }
-
- private boolean areEqual(byte[] a, int aOff, byte[] b, int bOff)
- {
- for (int i = bOff; i != b.length; i++)
- {
- if (a[aOff + i - bOff] != b[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- private void skipTest()
- {
- SecureRandom rand = new SecureRandom();
- byte[] plain = new byte[5000];
- byte[] cipher = new byte[5000];
-
- rand.nextBytes(plain);
-
- CipherParameters params = new ParametersWithIV(new KeyParameter(Hex.decode("0053A6F94C9FF24598EB3E91E4378ADD3083D6297CCF2275C81B6EC11467BA0D")), Hex.decode("0D74DB42A91077DE"));
- Salsa20Engine engine = new Salsa20Engine();
-
- engine.init(true, params);
-
- engine.processBytes(plain, 0, plain.length, cipher, 0);
-
- byte[] fragment = new byte[20];
-
- engine.init(true, params);
-
- engine.skip(10);
-
- engine.processBytes(plain, 10, fragment.length, fragment, 0);
-
- if (!areEqual(cipher, 10, fragment, 0))
- {
- fail("skip forward 10 failed");
- }
-
- engine.skip(1000);
-
- engine.processBytes(plain, 1010 + fragment.length, fragment.length, fragment, 0);
-
- if (!areEqual(cipher, 1010 + fragment.length, fragment, 0))
- {
- fail("skip forward 1000 failed");
- }
-
- engine.skip(-10);
-
- engine.processBytes(plain, 1010 + 2 * fragment.length - 10, fragment.length, fragment, 0);
-
- if (!areEqual(cipher, 1010 + 2 * fragment.length - 10, fragment, 0))
- {
- fail("skip back 10 failed");
- }
-
- engine.skip(-1000);
-
- if (engine.getPosition() != 60)
- {
- fail("skip position incorrect - " + 60 + " got " + engine.getPosition());
- }
-
- engine.processBytes(plain, 60, fragment.length, fragment, 0);
-
- if (!areEqual(cipher, 60, fragment, 0))
- {
- fail("skip back 1000 failed");
- }
-
- long pos = engine.seekTo(1010);
- if (pos != 1010)
- {
- fail("position wrong");
- }
-
- engine.processBytes(plain, 1010, fragment.length, fragment, 0);
-
- if (!areEqual(cipher, 1010, fragment, 0))
- {
- fail("seek to 1010 failed");
- }
-
- engine.reset();
-
- for (int i = 0; i != 1000; i++)
- {
- engine.skip(i);
-
- if (engine.getPosition() != i)
- {
- fail("skip forward at wrong position");
- }
-
- engine.processBytes(plain, i, fragment.length, fragment, 0);
-
- if (!areEqual(cipher, i, fragment, 0))
- {
- fail("skip forward i failed: " + i);
- }
-
- if (engine.getPosition() != i + fragment.length)
- {
- fail("cipher at wrong position: " + engine.getPosition() + " [" + i + "]");
- }
-
- engine.skip(-fragment.length);
-
- if (engine.getPosition() != i)
- {
- fail("skip back at wrong position");
- }
-
- engine.processBytes(plain, i, fragment.length, fragment, 0);
-
- if (!areEqual(cipher, i, fragment, 0))
- {
- fail("skip back i failed: " + i);
- }
-
- engine.reset();
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new Salsa20Test());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/SerpentTest.java b/core/src/test/java/org/bouncycastle/crypto/test/SerpentTest.java
deleted file mode 100644
index 3eac33a7..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/SerpentTest.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.engines.SerpentEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- */
-public class SerpentTest
- extends CipherTest
-{
- static SimpleTest[] tests =
- {
- new BlockCipherVectorTest(0, new SerpentEngine(),
- new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
- "00000000000000000000000000000000", "8910494504181950f98dd998a82b6749"),
- new BlockCipherVectorTest(1, new SerpentEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000")),
- "80000000000000000000000000000000", "10b5ffb720b8cb9002a1142b0ba2e94a"),
- new BlockCipherVectorTest(2, new SerpentEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000")),
- "00000000008000000000000000000000", "4f057a42d8d5bd9746e434680ddcd5e5"),
- new BlockCipherVectorTest(3, new SerpentEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000")),
- "00000000000000000000400000000000", "99407bf8582ef12550886ef5b6f169b9"),
- new BlockCipherVectorTest(4, new SerpentEngine(),
- new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
- "40000000000000000000000000000000", "d522a3b8d6d89d4d2a124fdd88f36896"),
- new BlockCipherVectorTest(5, new SerpentEngine(),
- new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
- "00000000000200000000000000000000", "189b8ec3470085b3da97e82ca8964e32"),
- new BlockCipherVectorTest(6, new SerpentEngine(),
- new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
- "00000000000000000000008000000000", "f77d868cf760b9143a89809510ccb099"),
- new BlockCipherVectorTest(7, new SerpentEngine(),
- new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
- "08000000000000000000000000000000", "d43b7b981b829342fce0e3ec6f5f4c82"),
- new BlockCipherVectorTest(8, new SerpentEngine(),
- new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
- "00000000000000000100000000000000", "0bf30e1a0c33ccf6d5293177886912a7"),
- new BlockCipherVectorTest(9, new SerpentEngine(),
- new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
- "00000000000000000000000000000001", "6a7f3b805d2ddcba49b89770ade5e507"),
- new BlockCipherVectorTest(10, new SerpentEngine(),
- new KeyParameter(Hex.decode("80000000000000000000000000000000")),
- "00000000000000000000000000000000", "49afbfad9d5a34052cd8ffa5986bd2dd"),
- new BlockCipherVectorTest(11, new SerpentEngine(),
- new KeyParameter(Hex.decode("000000000000000000000000004000000000000000000000")),
- "00000000000000000000000000000000", "ba8829b1de058c4b48615d851fc74f17"),
- new BlockCipherVectorTest(12, new SerpentEngine(),
- new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000100000000")),
- "00000000000000000000000000000000", "89f64377bf1e8a46c8247044e8056a98"),
-/*
- new BlockCipherMonteCarloTest(13, 10000, new SerpentEngine(),
- new KeyParameter(Hex.decode("47f5f881daab9b67b43bd1342e339c19")),
- "7a4f7db38c52a8b711b778a38d203b6b", "003380e19f10065740394f48e2fe80b7"),
-*/
- new BlockCipherMonteCarloTest(13, 100, new SerpentEngine(),
- new KeyParameter(Hex.decode("47f5f881daab9b67b43bd1342e339c19")),
- "7a4f7db38c52a8b711b778a38d203b6b", "4db75303d815c2f7cc6ca935d1c5a046"),
-/*
- new BlockCipherMonteCarloTest(14, 10000, new SerpentEngine(),
- new KeyParameter(Hex.decode("31fba879ebc5e80df35e6fa33eaf92d6")),
- "70a05e12f74589009692a337f53ff614", "afb5425426906db26b70bdf842ac5400"),
-*/
- new BlockCipherMonteCarloTest(14, 100, new SerpentEngine(),
- new KeyParameter(Hex.decode("31fba879ebc5e80df35e6fa33eaf92d6")),
- "70a05e12f74589009692a337f53ff614", "fc53a50f4d3bc9836001893d2f41742d"),
-/*
- new BlockCipherMonteCarloTest(15, 10000, new SerpentEngine(),
- new KeyParameter(Hex.decode("bde6dd392307984695aee80e574f9977caae9aa78eda53e8")),
- "9cc523d034a93740a0aa4e2054bb34d8", "1949d506ada7de1f1344986e8ea049b2"),
-*/
- new BlockCipherMonteCarloTest(15, 100, new SerpentEngine(),
- new KeyParameter(Hex.decode("bde6dd392307984695aee80e574f9977caae9aa78eda53e8")),
- "9cc523d034a93740a0aa4e2054bb34d8", "77117e6a9e80f40b2a36b7d755573c2d"),
-/*
- new BlockCipherMonteCarloTest(16, 10000, new SerpentEngine(),
- new KeyParameter(Hex.decode("60f6f8ad4290699dc50921a1bbcca92da914e7d9cf01a9317c79c0af8f2487a1")),
- "ee1a61106fae2d381d686cbf854bab65", "e57f45559027cb1f2ed9603d814e1c34"),
-*/
- new BlockCipherMonteCarloTest(16, 100, new SerpentEngine(),
- new KeyParameter(Hex.decode("60f6f8ad4290699dc50921a1bbcca92da914e7d9cf01a9317c79c0af8f2487a1")),
- "ee1a61106fae2d381d686cbf854bab65", "dcd7f13ea0dcdfd0139d1a42e2ffb84b")
- };
-
- SerpentTest()
- {
- super(tests, new SerpentEngine(), new KeyParameter(new byte[32]));
- }
-
- public String getName()
- {
- return "Serpent";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new SerpentTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/Shacal2Test.java b/core/src/test/java/org/bouncycastle/crypto/test/Shacal2Test.java
deleted file mode 100644
index bd7a8154..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/Shacal2Test.java
+++ /dev/null
@@ -1,200 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.engines.Shacal2Engine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * Shacal2 tester - vectors from https://www.cosic.esat.kuleuven.be/nessie/testvectors/
- */
-public class Shacal2Test
- extends CipherTest
-{
- static SimpleTest[] tests =
- {
- // set 8.0
- new BlockCipherVectorTest(0, new Shacal2Engine(),
- new KeyParameter(Hex.decode("000102030405060708090A0B0C0D0E0F" +
- "101112131415161718191A1B1C1D1E1F" +
- "202122232425262728292A2B2C2D2E2F" +
- "303132333435363738393A3B3C3D3E3F")),
- "98BCC10405AB0BFC686BECECAAD01AC1" +
- "9B452511BCEB9CB094F905C51CA45430",
- "00112233445566778899AABBCCDDEEFF" +
- "102132435465768798A9BACBDCEDFE0F"),
- // set 8.1
- new BlockCipherVectorTest(1, new Shacal2Engine(),
- new KeyParameter(Hex.decode("2BD6459F82C5B300952C49104881FF48" +
- "2BD6459F82C5B300952C49104881FF48" +
- "2BD6459F82C5B300952C49104881FF48" +
- "2BD6459F82C5B300952C49104881FF48")),
- "481F122A75F2C4C3395140B5A951EBBA" +
- "06D96BDFD9D8FF4FB59CBD1287808D5A",
- "EA024714AD5C4D84EA024714AD5C4D84" +
- "EA024714AD5C4D84EA024714AD5C4D84"),
- // 7.255
- new BlockCipherVectorTest(2, new Shacal2Engine(),
- new KeyParameter(Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")),
- "94FEDFF2A0CFE3C983D340C88D73F8CF" +
- "4B79FC581797EC10B27D4DA1B51E1BC7",
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"),
- // 7.100
- new BlockCipherVectorTest(3, new Shacal2Engine(),
- new KeyParameter(Hex.decode("64646464646464646464646464646464" +
- "64646464646464646464646464646464" +
- "64646464646464646464646464646464" +
- "64646464646464646464646464646464")),
- "6643CB84B3B3F126F5E50959EF4CE73D" +
- "B8500918ABE1056368DB06CA8C1C0D45",
- "64646464646464646464646464646464" +
- "64646464646464646464646464646464"),
- // 7.50
- new BlockCipherVectorTest(4, new Shacal2Engine(),
- new KeyParameter(Hex.decode("32323232323232323232323232323232" +
- "32323232323232323232323232323232" +
- "32323232323232323232323232323232" +
- "32323232323232323232323232323232")),
- "92E937285AB11FE3561542C43C918966" +
- "971DE722E9B9D38BD69EAC77899DCF81",
- "32323232323232323232323232323232" +
- "32323232323232323232323232323232"),
- // 7.0
- new BlockCipherVectorTest(5, new Shacal2Engine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000" +
- "00000000000000000000000000000000" +
- "00000000000000000000000000000000" +
- "00000000000000000000000000000000")),
- "F8C9259FA4F5D787B570AFA9219166A6" +
- "3636FC5C30AC289155D0CC4FFCB4B03D",
- "00000000000000000000000000000000" +
- "00000000000000000000000000000000"),
- // 6.255
- new BlockCipherVectorTest(6, new Shacal2Engine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000" +
- "00000000000000000000000000000000" +
- "00000000000000000000000000000000" +
- "00000000000000000000000000000000")),
- "F4E976DF0172CD961D4C8D466A12F676" +
- "5B9089046E747CD2A41BF43C18A8328E",
- "00000000000000000000000000000000" +
- "00000000000000000000000000000001"),
- // 6.100
- new BlockCipherVectorTest(7, new Shacal2Engine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000" +
- "00000000000000000000000000000000" +
- "00000000000000000000000000000000" +
- "00000000000000000000000000000000")),
- "3B929F0597E21D0076EC399D21B67713" +
- "B40E3AD559704219A26A3380212D5AD6",
- "00000000000000000000000008000000" +
- "00000000000000000000000000000000"),
-
- // 6.0
- new BlockCipherVectorTest(8, new Shacal2Engine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000" +
- "00000000000000000000000000000000" +
- "00000000000000000000000000000000" +
- "00000000000000000000000000000000")),
- "43A0DAD8307F19FBBCF166FE20BAC075" +
- "C56FF14042550E472094B042BE5963EE",
- "80000000000000000000000000000000" +
- "00000000000000000000000000000000"),
- };
-
- Shacal2Test()
- {
- super(tests, new Shacal2Engine(), new KeyParameter(new byte[16]));
- }
-
- public void performTest()
- throws Exception
- {
- super.performTest();
-
- // 1.0
- iteratedTest(0,
- Hex.decode("80000000000000000000000000000000" +
- "00000000000000000000000000000000" +
- "00000000000000000000000000000000" +
- "00000000000000000000000000000000"),
- Hex.decode("00000000000000000000000000000000" +
- "00000000000000000000000000000000"),
- Hex.decode("361AB6322FA9E7A7BB23818D839E01BD" +
- "DAFDF47305426EDD297AEDB9F6202BAE"),
- Hex.decode("226A582DE04383D0F3E7DE655DD848AC" +
- "3E14CCFB4E76F7B7069879F67C4D5420"),
- Hex.decode("B05D5A18C0712082CFF5BA9DBBCD7269" +
- "114FC3DF83B42DAC306D95BBC473D839"));
-
- // 1.100
- iteratedTest(1,
- Hex.decode("00000000000000000000000008000000" +
- "00000000000000000000000000000000" +
- "00000000000000000000000000000000" +
- "00000000000000000000000000000000"),
- Hex.decode("00000000000000000000000000000000" +
- "00000000000000000000000000000000"),
- Hex.decode("F703282E54592A5617E10618027BB67F" +
- "639E43A90767150D8B7F5E83054B3CBD"),
- Hex.decode("3B442692B579485B8BA2F92CE3B90DE7" +
- "D2EA03D8B3C8E7BE7BF6415F798EED90"),
- Hex.decode("331B9B65F06230380BBEECFBFBA94BCF" +
- "92AF6341F815D7651F996144A5377263"));
- }
-
- private void iteratedTest(int index, byte[] key, byte[] plain, byte[] cipher, byte[] cipher100, byte[] cipher1000)
- {
- BlockCipher engine = new Shacal2Engine();
-
- engine.init(true, new KeyParameter(key));
-
- byte[] buf = new byte[plain.length];
-
- System.arraycopy(plain, 0, buf, 0, plain.length);
-
- engine.processBlock(buf, 0, buf, 0);
-
- if (!Arrays.areEqual(cipher, buf))
- {
- fail(index + " single count failed");
- }
-
- for (int i = 1; i != 100; i++)
- {
- engine.processBlock(buf, 0, buf, 0);
- }
-
- if (!Arrays.areEqual(cipher100, buf))
- {
- fail(index + " 100 count failed");
- }
-
- for (int i = 100; i != 1000; i++)
- {
- engine.processBlock(buf, 0, buf, 0);
- }
-
- if (!Arrays.areEqual(cipher1000, buf))
- {
- fail(index + " 1000 count failed");
- }
- }
-
- public String getName()
- {
- return "Shacal2";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new Shacal2Test());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/ShortenedDigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/ShortenedDigestTest.java
deleted file mode 100644
index 20510c94..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/ShortenedDigestTest.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Created on 6/05/2006
- *
- * To change the template for this generated file go to
- * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
- */
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.ExtendedDigest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.SHA512Digest;
-import org.bouncycastle.crypto.digests.ShortenedDigest;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class ShortenedDigestTest
- extends SimpleTest
-{
- public void performTest()
- {
- ExtendedDigest d = new SHA1Digest();
- ShortenedDigest sd = new ShortenedDigest(new SHA1Digest(), 10);
-
- if (sd.getDigestSize() != 10)
- {
- fail("size check wrong for SHA-1");
- }
-
- if (sd.getByteLength() != d.getByteLength())
- {
- fail("byte length check wrong for SHA-1");
- }
-
- //
- // check output fits
- //
- sd.doFinal(new byte[10], 0);
-
- d = new SHA512Digest();
- sd = new ShortenedDigest(new SHA512Digest(), 20);
-
- if (sd.getDigestSize() != 20)
- {
- fail("size check wrong for SHA-512");
- }
-
- if (sd.getByteLength() != d.getByteLength())
- {
- fail("byte length check wrong for SHA-512");
- }
-
- //
- // check output fits
- //
- sd.doFinal(new byte[20], 0);
-
- try
- {
- new ShortenedDigest(null, 20);
-
- fail("null parameter not caught");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
-
- try
- {
- new ShortenedDigest(new SHA1Digest(), 50);
-
- fail("short digest not caught");
- }
- catch (IllegalArgumentException e)
- {
- // expected
- }
- }
-
- public String getName()
- {
- return "ShortenedDigest";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new ShortenedDigestTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/SipHashTest.java b/core/src/test/java/org/bouncycastle/crypto/test/SipHashTest.java
deleted file mode 100644
index 1c55411d..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/SipHashTest.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.macs.SipHash;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Pack;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/*
- * SipHash test values from "SipHash: a fast short-input PRF", by Jean-Philippe
- * Aumasson and Daniel J. Bernstein (https://131002.net/siphash/siphash.pdf), Appendix A.
- */
-public class SipHashTest
- extends SimpleTest
-{
- private static final int UPDATE_BYTES = 0;
- private static final int UPDATE_FULL = 1;
- private static final int UPDATE_MIX = 2;
-
- public String getName()
- {
- return "SipHash";
- }
-
- public void performTest()
- throws Exception
- {
- byte[] key = Hex.decode("000102030405060708090a0b0c0d0e0f");
- byte[] input = Hex.decode("000102030405060708090a0b0c0d0e");
-
- runMAC(key, input, UPDATE_BYTES);
- runMAC(key, input, UPDATE_FULL);
- runMAC(key, input, UPDATE_MIX);
-
- SecureRandom random = new SecureRandom();
- for (int i = 0; i < 100; ++i)
- {
- randomTest(random);
- }
- }
-
- private void runMAC(byte[] key, byte[] input, int updateType)
- throws Exception
- {
- long expected = 0xa129ca6149be45e5L;
-
- SipHash mac = new SipHash();
- mac.init(new KeyParameter(key));
-
- updateMAC(mac, input, updateType);
-
- long result = mac.doFinal();
- if (expected != result)
- {
- fail("Result does not match expected value for doFinal()");
- }
-
- byte[] expectedBytes = new byte[8];
- Pack.longToLittleEndian(expected, expectedBytes, 0);
-
- updateMAC(mac, input, updateType);
-
- byte[] output = new byte[mac.getMacSize()];
- int len = mac.doFinal(output, 0);
- if (len != output.length)
- {
- fail("Result length does not equal getMacSize() for doFinal(byte[],int)");
- }
- if (!areEqual(expectedBytes, output))
- {
- fail("Result does not match expected value for doFinal(byte[],int)");
- }
- }
-
- private void randomTest(SecureRandom random)
- {
- byte[] key = new byte[16];
- random.nextBytes(key);
-
- int length = 1 + random.nextInt(1024);
- byte[] input = new byte[length];
- random.nextBytes(input);
-
- SipHash mac = new SipHash();
- mac.init(new KeyParameter(key));
-
- updateMAC(mac, input, UPDATE_BYTES);
- long result1 = mac.doFinal();
-
- updateMAC(mac, input, UPDATE_FULL);
- long result2 = mac.doFinal();
-
- updateMAC(mac, input, UPDATE_MIX);
- long result3 = mac.doFinal();
-
- if (result1 != result2 || result1 != result3)
- {
- fail("Inconsistent results in random test");
- }
- }
-
- private void updateMAC(SipHash mac, byte[] input, int updateType)
- {
- switch (updateType)
- {
- case UPDATE_BYTES:
- {
- for (int i = 0; i < input.length; ++i)
- {
- mac.update(input[i]);
- }
- break;
- }
- case UPDATE_FULL:
- {
- mac.update(input, 0, input.length);
- break;
- }
- case UPDATE_MIX:
- {
- int step = Math.max(1, input.length / 3);
- int pos = 0;
- while (pos < input.length)
- {
- mac.update(input[pos++]);
- int len = Math.min(input.length - pos, step);
- mac.update(input, pos, len);
- pos += len;
- }
- break;
- }
- default:
- throw new IllegalStateException();
- }
- }
-
- public static void main(String[] args)
- {
- runTest(new SipHashTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/SkeinDigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/SkeinDigestTest.java
deleted file mode 100644
index 1a7dff6f..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/SkeinDigestTest.java
+++ /dev/null
@@ -1,294 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SkeinDigest;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Memoable;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class SkeinDigestTest
- extends SimpleTest
-{
- private static class Case
- {
- private byte[] message;
- private byte[] digest;
- private int blockSize;
- private int outputSize;
-
- public Case(int blockSize, int outputSize, String message, String digest)
- {
- this.blockSize = blockSize;
- this.outputSize = outputSize;
- this.message = Hex.decode(message);
- this.digest = Hex.decode(digest);
- }
-
- public int getOutputSize()
- {
- return outputSize;
- }
-
- public int getBlockSize()
- {
- return blockSize;
- }
-
- public byte[] getMessage()
- {
- return message;
- }
-
- public byte[] getDigest()
- {
- return digest;
- }
-
- }
-
- // Test cases from skein_golden_kat.txt and skein_golden_kat_short.txt in Skein 1.3 NIST CD
- private static final Case[] TEST_CASES = {
- new Case(256, 256, "", "c8877087da56e072870daa843f176e9453115929094c3a40c463a196c29bf7ba"),
- new Case(256, 256, "fb", "088eb23cc2bccfb8171aa64e966d4af937325167dfcd170700ffd21f8a4cbdac"),
- new Case(256, 256, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8",
- "5c3002ff57a627089ea2f97a5000d5678416389019e80e45a3bbcab118315d26"),
- new Case(256, 256, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
- + "78bb393a1a5f79bef30995a85a129233",
- "640c894a4bba6574c83e920ddf7dd2982fc634881bbbcb9d774eae0a285e89ce"),
- new Case(256, 160, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
- + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
- + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
- + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
- "0cd491b7715704c3a15a45a1ca8d93f8f646d3a1"),
- new Case(256, 224, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
- + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
- + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
- + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
- "afd1e2d0f5b6cd4e1f8b3935fa2497d27ee97e72060adac099543487"),
- new Case(256, 256, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
- + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
- + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
- + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
- "4de6fe2bfdaa3717a4261030ef0e044ced9225d066354610842a24a3eafd1dcf"),
- new Case(256, 384, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
- + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
- + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
- + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
- "954620fb31e8b782a2794c6542827026fe069d715df04261629fcbe81d7d529b"
- + "95ba021fa4239fb00afaa75f5fd8e78b"),
- new Case(256, 512, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
- + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
- + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
- + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
- "51347e27c7eabba514959f899a6715ef6ad5cf01c23170590e6a8af399470bf9"
- + "0ea7409960a708c1dbaa90e86389df254abc763639bb8cdf7fb663b29d9557c3"),
- new Case(256, 1024, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
- + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
- + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
- + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
- "6c9b6facbaf116b538aa655e0be0168084aa9f1be445f7e06714585e5999a6c9"
- + "84fffa9d41a316028692d4aad18f573fbf27cf78e84de26da1928382b023987d"
- + "cfe002b6201ea33713c54a8a5d9eb346f0365e04330d2faaf7bc8aba92a5d7fb"
- + "6345c6fb26750bce65ab2045c233627679ac6e9acb33602e26fe3526063ecc8b"),
-
- new Case(512, 512, "", "bc5b4c50925519c290cc634277ae3d6257212395cba733bbad37a4af0fa06af4"
- + "1fca7903d06564fea7a2d3730dbdb80c1f85562dfcc070334ea4d1d9e72cba7a"),
- new Case(512, 512, "fb", "c49e03d50b4b2cc46bd3b7ef7014c8a45b016399fd1714467b7596c86de98240"
- + "e35bf7f9772b7d65465cd4cffab14e6bc154c54fc67b8bc340abf08eff572b9e"),
- new Case(512, 512, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8",
- "abefb179d52f68f86941acbbe014cc67ec66ad78b7ba9508eb1400ee2cbdb06f"
- + "9fe7c2a260a0272d0d80e8ef5e8737c0c6a5f1c02ceb00fb2746f664b85fcef5"),
- new Case(512, 512, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
- + "78bb393a1a5f79bef30995a85a129233",
- "5c5b7956f9d973c0989aa40a71aa9c48a65af2757590e9a758343c7e23ea2df4"
- + "057ce0b49f9514987feff97f648e1dd065926e2c371a0211ca977c213f14149f"),
- new Case(512, 160, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
- + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
- + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
- + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
- "ef03079d61b57c6047e15fa2b35b46fa24279539"),
- new Case(512, 224, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
- + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
- + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
- + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
- "d9e3219b214e15246a2038f76a573e018ef69b385b3bd0576b558231"),
- new Case(512, 256, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
- + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
- + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
- + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
- "809dd3f763a11af90912bbb92bc0d94361cbadab10142992000c88b4ceb88648"),
- new Case(512, 384, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
- + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
- + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
- + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
- "825f5cbd5da8807a7b4d3e7bd9cd089ca3a256bcc064cd73a9355bf3ae67f2bf"
- + "93ac7074b3b19907a0665ba3a878b262"),
- new Case(512, 512, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
- + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
- + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
- + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
- "1a0d5abf4432e7c612d658f8dcfa35b0d1ab68b8d6bd4dd115c23cc57b5c5bcd"
- + "de9bff0ece4208596e499f211bc07594d0cb6f3c12b0e110174b2a9b4b2cb6a9"),
-
- new Case(1024, 1024, "", "0fff9563bb3279289227ac77d319b6fff8d7e9f09da1247b72a0a265cd6d2a62"
- + "645ad547ed8193db48cff847c06494a03f55666d3b47eb4c20456c9373c86297"
- + "d630d5578ebd34cb40991578f9f52b18003efa35d3da6553ff35db91b81ab890"
- + "bec1b189b7f52cb2a783ebb7d823d725b0b4a71f6824e88f68f982eefc6d19c6"),
- new Case(1024, 1024, "fb", "6426bdc57b2771a6ef1b0dd39f8096a9a07554565743ac3de851d28258fcff22"
- + "9993e11c4e6bebc8b6ecb0ad1b140276081aa390ec3875960336119427827473"
- + "4770671b79f076771e2cfdaaf5adc9b10cbae43d8e6cd2b1c1f5d6c82dc96618"
- + "00ddc476f25865b8748253173187d81da971c027d91d32fb390301c2110d2db2"),
- new Case(1024, 1024, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8",
- "140e93726ab0b0467c0b8a834ad8cda4d1769d273661902b70db0dcb5ee692ac"
- + "b3f852d03b11f857850f2428432811309c1dcbe5724f00267ea3667e89fadb4e"
- + "4911da6b0ba8a7eddf87c1c67152ef0f07b7fead3557318478bdef5ad1e5926d"
- + "7071fdd4bfa5076d4b3253f8de479ebdf5357676f1641b2f097e9b785e9e528e"),
- new Case(1024, 1024, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
- + "78bb393a1a5f79bef30995a85a129233",
- "31105e1ef042c30b95b16e0f6e6a1a19172bb7d54a0597dd0c711194888efe1d"
- + "bce82d47416df9577ca387219f06e45cd10964ff36f6711edbbea0e9595b0f66"
- + "f72b755d70a46857e0aec98561a743d49370d8e572e212811273125f66cc30bf"
- + "117d3221894c48012bf6e2219de91e064b01523517420a1e00f71c4cc04bab62"),
- new Case(1024, 160, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
- + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
- + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
- + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
- "2e6a4cbf2ef05ea9c24b93e8d1de732ddf2739eb"),
- new Case(1024, 224, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
- + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
- + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
- + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
- "1d6de19f37f7a3c265440eecb4b9fbd3300bb5ac60895cfc0d4d3c72"),
- new Case(1024, 256, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
- + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
- + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
- + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
- "986a4d472b123e8148731a8eac9db23325f0058c4ccbc44a5bb6fe3a8db672d7"),
- new Case(1024, 384, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
- + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
- + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
- + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
- "9c3d0648c11f31c18395d5e6c8ebd73f43d189843fc45235e2c35e345e12d62b"
- + "c21a41f65896ddc6a04969654c2e2ce9"),
- new Case(1024, 512, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
- + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
- + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
- + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
- "5d0416f49c2d08dfd40a1446169dc6a1d516e23b8b853be4933513051de8d5c2"
- + "6baccffb08d3b16516ba3c6ccf3e9a6c78fff6ef955f2dbc56e1459a7cdba9a5"),
- new Case(1024, 1024, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
- + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
- + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
- + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
- "96ca81f586c825d0360aef5acaec49ad55289e1797072eee198b64f349ce65b6"
- + "e6ed804fe38f05135fe769cc56240ddda5098f620865ce4a4278c77fa2ec6bc3"
- + "1c0f354ca78c7ca81665bfcc5dc54258c3b8310ed421d9157f36c093814d9b25"
- + "103d83e0ddd89c52d0050e13a64c6140e6388431961685734b1f138fe2243086"),
-
- };
-
- public String getName()
- {
- return "SkeinDigest";
- }
-
- public void performTest()
- throws Exception
- {
- runTest(TEST_CASES[7]);
- for (int i = 0; i < TEST_CASES.length; i++)
- {
- Case test = TEST_CASES[i];
- runTest(test);
- }
- }
-
- private void runTest(Case dc)
- {
- SkeinDigest digest = new SkeinDigest(dc.getBlockSize(), dc.getOutputSize());
-
- byte[] message = dc.getMessage();
- digest.update(message, 0, message.length);
-
- byte[] output = new byte[digest.getDigestSize()];
- digest.doFinal(output, 0);
-
- if (!Arrays.areEqual(output, dc.getDigest()))
- {
- fail(digest.getAlgorithmName() + " message mismatch.\n Message " + new String(Hex.encode(dc.getMessage())),
- new String(Hex.encode(dc.getDigest())), new String(Hex.encode(output)));
- }
-
- // Clone test
- digest.update(message, 0, message.length / 2);
-
- // clone the Digest
- Digest d = new SkeinDigest(digest);
-
- digest.update(message, message.length / 2, message.length - message.length / 2);
- digest.doFinal(output, 0);
-
- if (!areEqual(dc.getDigest(), output))
- {
- fail("failing clone vector test", new String(Hex.encode(dc.getDigest())), new String(Hex.encode(output)));
- }
-
- d.update(message, message.length / 2, message.length - message.length / 2);
- d.doFinal(output, 0);
-
- if (!areEqual(dc.getDigest(), output))
- {
- fail("failing second clone vector test", new String(Hex.encode(dc.getDigest())), new String(Hex.encode(output)));
- }
-
- //
- // memo test
- //
- Memoable m = (Memoable)digest;
-
- digest.update(message, 0, message.length / 2);
-
- // copy the Digest
- Memoable copy1 = m.copy();
- Memoable copy2 = copy1.copy();
-
- digest.update(message, message.length / 2, message.length - message.length / 2);
- digest.doFinal(output, 0);
-
- if (!areEqual(dc.getDigest(), output))
- {
- fail("failing memo vector test", new String(Hex.encode(dc.getDigest())), new String(Hex.encode(output)));
- }
-
- m.reset(copy1);
-
- digest.update(message, message.length / 2, message.length - message.length / 2);
- digest.doFinal(output, 0);
-
- if (!areEqual(dc.getDigest(), output))
- {
- fail("failing memo reset vector test", new String(Hex.encode(dc.getDigest())), new String(Hex.encode(output)));
- }
-
- Digest md = (Digest)copy2;
-
- md.update(message, message.length / 2, message.length - message.length / 2);
- md.doFinal(output, 0);
-
- if (!areEqual(dc.getDigest(), output))
- {
- fail("failing memo copy vector test", new String(Hex.encode(dc.getDigest())), new String(Hex.encode(output)));
- }
- }
-
- public static void main(String[] args)
- throws IOException
- {
- // generateTests();
- runTest(new SkeinDigestTest());
- }
-
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/SkeinMacTest.java b/core/src/test/java/org/bouncycastle/crypto/test/SkeinMacTest.java
deleted file mode 100644
index 68008b7a..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/SkeinMacTest.java
+++ /dev/null
@@ -1,162 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.macs.SkeinMac;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class SkeinMacTest
- extends SimpleTest
-{
- private static class Case
- {
- private byte[] message;
- private byte[] digest;
- private byte[] key;
- private int blockSize;
- private int outputSize;
-
- public Case(int blockSize, int outputSize, String message, String key, String digest)
- {
- this.blockSize = blockSize;
- this.outputSize = outputSize;
- this.message = Hex.decode(message);
- this.key = Hex.decode(key);
- this.digest = Hex.decode(digest);
- }
-
- public int getOutputSize()
- {
- return outputSize;
- }
-
- public int getBlockSize()
- {
- return blockSize;
- }
-
- public byte[] getMessage()
- {
- return message;
- }
-
- public byte[] getKey()
- {
- return key;
- }
-
- public byte[] getDigest()
- {
- return digest;
- }
-
- public String toString()
- {
- return "new Case(" + blockSize + ", " + outputSize + ", \"" + new String(Hex.encode(message)) + "\", \""
- + new String(Hex.encode(key)) + "\", \"" + new String(Hex.encode(digest)) + "\"";
- }
-
- }
-
- // Test cases from skein_golden_kat.txt in Skein 1.3 NIST CD
- // Excludes empty '(none)' key 'random+MAC' tests, which are in effect digest
- private static final Case[] TEST_CASES = {
- new Case(256, 256, "", "cb41f1706cde09651203c2d0efbaddf8", "886e4efefc15f06aa298963971d7a25398fffe5681c84db39bd00851f64ae29d"),
- new Case(256, 256, "d3", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "979422a94e3afaa46664124d4e5e8b9422b1d8baf11c6ae6725992ac72a112ca"),
- new Case(256, 256, "d3090c72", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "1d658372cbea2f9928493cc47599d6f4ad8ce33536bedfa20b739f07516519d5"),
- new Case(256, 256, "d3090c72167517f7", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e92", "41ef6b0f0fad81c040284f3b1a91e9c44e4c26a6d7207f3aac4362856ef12aca"),
- new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "ca8208119b9e4e4057631ab31015cfd256f6763a0a34381633d97f640899b84f"),
- new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "9e9980fcc16ee082cf164a5147d0e0692aeffe3dcb8d620e2bb542091162e2e9"),
- new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc235", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "c353a316558ec34f8245dd2f9c2c4961fbc7decc3b69053c103e4b8aaaf20394"),
- new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdf", "cb41f1706cde09651203c2d0efbaddf8", "b1b8c18188e69a6ecae0b6018e6b638c6a91e6de6881e32a60858468c17b520d"),
- new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e92", "1dfd2515a412e78852cd81a7f2167711b4ca19b2891c2ea36ba94f8451944793"),
- new Case(256, 224, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf8", "a097340709b443ed2c0a921f5dcefef3ead65c4f0bcd5f13da54d7ed"),
- new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "ac1b4fab6561c92d0c487e082daec53e0db4f505e08bf51cae4fd5375e37fc04"),
- new Case(256, 384, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e92", "96e6cebb23573d0a70ce36a67aa05d2403148093f25c695e1254887cc97f9771d2518413af4286bf2a06b61a53f7fcec"),
- new Case(256, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "0e95e597e71d6350f20b99c4179f54f43a4722705c06ba765a82cb0a314fe2fe87ef8090063b757e53182706ed18737dadc0da1e1c66518f08334052702c5ed7"),
- new Case(256, 264, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf8", "064abd4896f460b1953f5a357e7f7c5256e29cdb62b8740d0b52295cfa2ef4c7a2"),
- new Case(256, 520, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "edf220e43e048603bd16197d59b673b9974de5b8bcf7cb1558a4799f6fd3743eb5fb400cd6129afc0c60e7b741b7e5806f0e0b93eb8429fbc7efa222175a9c80fd"),
- new Case(256, 1032, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e92", "f3f59fb07399c7b73aae02a8590883cb2fdfde75c55654e71846522301bde48d267169adcc559e038e8c2f28faa552b550d51874055384adea93c036c71a1f0af0c7bcc3bc923738d5307b9da7cb423d4e615c629c4aba71f70d4c9d1fa008176825e51bfa0203445a4083947ec19f6a0fbd082b5b970f2396fb67420639410447"),
- new Case(256, 2056, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "80eb80d9b8836b32fa576fc84ba08edfbdfd6979123d61914e610a70a372b37f560a10909484f9f4a377c93e29ba681dfe522c41dc83b5ee0567e5370007c7bbe4df0b2b4a25e088f80d72fc30734cdcd76d817b42fbd44dca881019afb25306f19d4e91848778af306517d2072cef72caa327e877c5b6554f83cec3d00877131b47c4d3b557f5a13541c4d5080ee3ce7a658993d083efd0db3496a8752060c3c8552f44b290cabdcc867f691ad605836c08dbd59c9528d885b600b85fdfc8a9d0e636ac3ad8b4295bcb0169e78dc358e77eacc8c4b61bddfa9e5f32d2268a006cfe05c57150fe8e68cabd21cf6cf6035aa1fe4db36c922b765aad0b64e82a2c37"),
- new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed696e6c9db1e6abea026288954a9c2d5758d7c5db7c9e48aa3d21cae3d977a7c3926066aa393dbd538dd0c30da8916c8757f24c18488014668a2627163a37b261833dc2f8c3c56b1b2e0be21fd3fbdb507b2950b77a6cc02efb393e57419383a920767bca2c972107aa61384542d47cbfb82cfe5c415389d1b0a2d74e2c5da851", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "8f88de68f03cd2f396ccdd49c3a0f4ff15bcda7eb357da9753f6116b124de91d"),
- new Case(512, 512, "", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "9bd43d2a2fcfa92becb9f69faab3936978f1b865b7e44338fc9c8f16aba949ba340291082834a1fc5aa81649e13d50cd98641a1d0883062bfe2c16d1faa7e3aa"),
- new Case(512, 512, "d3", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "f0c0a10f031c8fc69cfabcd54154c318b5d6cd95d06b12cf20264402492211ee010d5cecc2dc37fd772afac0596b2bf71e6020ef2dee7c860628b6e643ed9ff6"),
- new Case(512, 512, "d3090c72167517f7", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "0c1f1921253dd8e5c2d4c5f4099f851042d91147892705829161f5fc64d89785226eb6e187068493ee4c78a4b7c0f55a8cbbb1a5982c2daf638fc6a74b16b0d7"),
- new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "478d7b6c0cc6e35d9ebbdedf39128e5a36585db6222891692d1747d401de34ce3db6fcbab6c968b7f2620f4a844a2903b547775579993736d2493a75ff6752a1"),
- new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e59", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "13c170bac1de35e5fb843f65fabecf214a54a6e0458a4ff6ea5df91915468f4efcd371effa8965a9e82c5388d84730490dcf3976af157b8baf550655a5a6ab78"),
- new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc235", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "a947812529a72fd3b8967ec391b298bee891babc8487a1ec4ea3d88f6b2b5be09ac6a780f30f8e8c3bbb4f18bc302a28f3e87d170ba0f858a8fefe3487478cca"),
- new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdf", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "7690ba61f10e0bba312980b0212e6a9a51b0e9aadfde7ca535754a706e042335b29172aae29d8bad18efaf92d43e6406f3098e253f41f2931eda5911dc740352"),
- new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "d10e3ba81855ac087fbf5a3bc1f99b27d05f98ba22441138026225d34a418b93fd9e8dfaf5120757451adabe050d0eb59d271b0fe1bbf04badbcf9ba25a8791b"),
- new Case(512, 160, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "5670b226156570dff3efe16661ab86eb24982cdf"),
- new Case(512, 224, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "c41b9ff9753e6c0f8ed88866e320535e927fe4da552c289841a920db"),
- new Case(512, 384, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "dfbf5c1319a1d9d70efb2f1600fbcf694f935907f31d24a16d6cd2fb2d7855a769681766c0a29da778eed346cd1d740f"),
- new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "04d8cddb0ad931d54d195899a094684344e902286037272890bce98a41813edc37a3cee190a693fcca613ee30049ce7ec2bdff9613f56778a13f8c28a21d167a"),
- new Case(512, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "08fca368b3b14ac406676adf37ac9be2dbb8704e694055a0c6331184d4f0070098f23f0963ee29002495771bf56fb4d3d9ff3506abcd80be927379f7880d5d7703919fbf92184f498ac44f47f015ce676eded9165d47d53733f5a27abbc05f45acd98b97cc15ffdced641defd1a5119ef841b452a1b8f94ee69004466ccdc143"),
- new Case(512, 264, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "669e770ebe7eacc2b64caaf049923ad297a5b37cfa61c283392d81ccfcb9bbbc09"),
- new Case(512, 1032, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "acc2e03f07f33e9820a6038421089429adcd6a7a83f733beec048c05bf37531a170a5537fcb565c348a70a83217f8be768ff6f95fd2b3d89cb7d8a3dc849505e3710eb4e65a8e7134bbf580d92fe18c9aa987563669b1f014aa5e092519089355534eaa9f0bdc99f6839f54080ffe74623254c906ecb8896b4346c3178a0bc2898"),
- new Case(512, 2056, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "9f3e082223c43090a4a3ffbdcd469cbabfe0c1399d1edf45a5dfc18f4db5428928a76e979b8d0d5dffec0e6a59ada448c1ffbc06cc80a2006f002adc0c6dbf458563762228dce4381944e460ebebfe06f1237093634625107469a22a189a47f8b025899265d8890a1b39df64552394377e88ba2ad44a8c8d174f884ac8c3ae24ddb0affca5fceb6aa76e09706881e8371774b9b050a69b96ef5e97e81043f8b7e9479e287ab441bacd62caf768a82c8c3e3107be70eb8799a39856fe29842a04e25de0ef9de1b7e65bd0f1f7306835287fc957388e2035b7d22d3aa9c06a9fefbca16f3f60e1c4def89038d918942152a069aa2e0be8ae7475d859031adec84583"),
- new Case(1024, 1024, "", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc81463134", "bcf37b3459c88959d6b6b58b2bfe142cef60c6f4ec56b0702480d7893a2b0595aa354e87102a788b61996b9cbc1eade7dafbf6581135572c09666d844c90f066b800fc4f5fd1737644894ef7d588afc5c38f5d920bdbd3b738aea3a3267d161ed65284d1f57da73b68817e17e381ca169115152b869c66b812bb9a84275303f0"),
- new Case(1024, 1024, "d3090c72", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "df0596e5808835a3e304aa27923db05f61dac57c0696a1d19abf188e70aa9dbcc659e9510f7c9a37fbc025bd4e5ea293e78ed7838dd0b08864e8ad40ddb3a88031ebefc21572a89960d1916107a7da7ac0c067e34ec46a86a29ca63fa250bd398eb32ec1ed0f8ac8329f26da018b029e41e2e58d1dfc44de81615e6c987ed9c9"),
- new Case(1024, 1024, "d3090c72167517f7", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c042eb4187aa1c015a4767032c0bb28f076b66485f51531c12e948f47dbc2cb904a4b75d1e8a6d931dab4a07e0a54d1bb5b55e602141746bd09fb15e8f01a8d74e9e63959cb37336bc1b896ec78da734c15e362db04368fbba280f20a043e0d0941e9f5193e1b360a33c43b266524880125222e648f05f28be34ba3cabfc9c544", "3cfbb79cd88af8ee09c7670bcbab6907a31f80fa31d9d7c9d50826c9568f307a78bd254961398c76b6e338fd9ca5f351059350d30963c3320659b223b991fc46d1307686fe2b4763d9f593c57ad5adbc45caf2ea3dc6090f5a74fa5fa6d9e9838964ea0a2aa216831ab069b00629a1a9b037083403bdb25d3d06a21c430c87dd"),
- new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e59", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "0a1b960099fc9d653b0fd1f5b6b972fb366907b772cbce5a59b6171d7935506f70c212bd169d68c5cfd8618343611b7eb2e686ff1dc7c03a57e1a55ed10726848161eea903d53b58459be42d95df989c66c2eea4e51cde272c2d8be67bf3bca2aee633777eb8486781eaa060d0f538abd6c93dbd2d1bf66e6f50bfdcac3725a4"),
- new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "3e0cd7938d71c39ffbb08a6ba7995ade3ad140e2c0c45cdbafb099247e08e4c20b61c1f885ced5ed2f816680925034918236e5807f0eecf3f27e9cfca36675eb75873efa1fb41f17541dc2f7c2469eaecb35cc7ca58e489804caf56f09fb97c9f689c64ad49c6888f86c483e901bd3d25798b394ef93faf9154900f92f31f433"),
- new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdf", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc81463134", "7266752f7e9aa04bd7d8a1b16030677de6021301f6a62473c76bae2b98bbf8aad73bd00a4b5035f741caf2317ab80e4e97f5c5bbe8acc0e8b424bcb13c7c6740a985801fba54addde8d4f13f69d2bfc98ae104d46a211145217e51d510ea846cec9581d14fda079f775c8b18d66cb31bf7060996ee8a69eee7f107909ce59a97"),
- new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c042eb4187aa1c015a4767032c0bb28f076b66485f51531c12e948f47dbc2cb904a4b75d1e8a6d931dab4a07e0a54d1bb5b55e602141746bd09fb15e8f01a8d74e9e63959cb37336bc1b896ec78da734c15e362db04368fbba280f20a043e0d0941e9f5193e1b360a33c43b266524880125222e648f05f28be34ba3cabfc9c544", "71f40bf2aa635125ef83c8df0d4e9ea18b73b56be4f45e89b910a7c68d396b65b09d18abc7d1b6de3f53fd5de583e6f22e612dd17b292068af6027daaf8b4cd60acf5bc85044741e9f7a1f423f5827f5e360930a2e71912239af9fc6343604fdcf3f3569854f2bb8d25a81e3b3f5261a02fe8292aaaa50c324101ab2c7a2f349"),
- new Case(1024, 160, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "17c3c533b27d666da556ae586e641b7a3a0bcc45"),
- new Case(1024, 224, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc81463134", "6625df9801581009125ea4e5c94ad6f1a2d692c278822ccb6eb67235"),
- new Case(1024, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "6c5b671c1766f6eecea6d24b641d4a6bf84bba13a1976f8f80b3f30ee2f93de6"),
- new Case(1024, 384, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c042eb4187aa1c015a4767032c0bb28f076b66485f51531c12e948f47dbc2cb904a4b75d1e8a6d931dab4a07e0a54d1bb5b55e602141746bd09fb15e8f01a8d74e9e63959cb37336bc1b896ec78da734c15e362db04368fbba280f20a043e0d0941e9f5193e1b360a33c43b266524880125222e648f05f28be34ba3cabfc9c544", "98af454d7fa3706dfaafbf58c3f9944868b57f68f493987347a69fce19865febba0407a16b4e82065035651f0b1e0327"),
- new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "211ac479e9961141da3aac19d320a1dbbbfad55d2dce87e6a345fcd58e36827597378432b482d89bad44dddb13e6ad86e0ee1e0882b4eb0cd6a181e9685e18dd302ebb3aa74502c06254dcadfb2bd45d288f82366b7afc3bc0f6b1a3c2e8f84d37fbedd07a3f8fcff84faf24c53c11da600aaa118e76cfdcb366d0b3f7729dce"),
- new Case(1024, 264, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc81463134", "dc1d253b7cadbdaef18503b1809a7f1d4f8c323b7f6f8ca50b76d3864649ce1c7d"),
- new Case(1024, 520, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "decd79578d12bf6806530c382230a2c7836429c70cac941179e1dd982938bab91fb6f3638df1cc1ef615ecfc4249e5aca8a73c4c1eebef662a836d0be903b00146"),
- new Case(1024, 1032, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c042eb4187aa1c015a4767032c0bb28f076b66485f51531c12e948f47dbc2cb904a4b75d1e8a6d931dab4a07e0a54d1bb5b55e602141746bd09fb15e8f01a8d74e9e63959cb37336bc1b896ec78da734c15e362db04368fbba280f20a043e0d0941e9f5193e1b360a33c43b266524880125222e648f05f28be34ba3cabfc9c544", "440fe691e04f1fed8c253d6c4670646156f33fffaea702de9445df5739eb960cecf85d56e2e6860a610211a5c909932ab774b978aa0b0d5bbce82775172ab12dceddd51d1eb030057ce61bea6c18f6bb368d26ae76a9e44a962eb132e6c42c25d9fecc4f13348300ca55c78e0990de96c1ae24eb3ee3324782c93dd628260a2c8d"),
- new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed696e6c9db1e6abea026288954a9c2d5758d7c5db7c9e48aa3d21cae3d977a7c3926066aa393dbd538dd0c30da8916c8757f24c18488014668a2627163a37b261833dc2f8c3c56b1b2e0be21fd3fbdb507b2950b77a6cc02efb393e57419383a920767bca2c972107aa61384542d47cbfb82cfe5c415389d1b0a2d74e2c5da851", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "46a42b0d7b8679f8fcea156c072cf9833c468a7d59ac5e5d326957d60dfe1cdfb27eb54c760b9e049fda47f0b847ac68d6b340c02c39d4a18c1bdfece3f405fae8aa848bdbefe3a4c277a095e921228618d3be8bd1999a071682810de748440ad416a97742cc9e8a9b85455b1d76472cf562f525116698d5cd0a35ddf86e7f8a"),
-
- };
-
- public String getName()
- {
- return "SkeinMac";
- }
-
- public void performTest()
- throws Exception
- {
- for (int i = 0; i < TEST_CASES.length; i++)
- {
- Case test = TEST_CASES[i];
- runTest(test);
- }
- }
-
- private void runTest(Case dc)
- {
- Mac digest = new SkeinMac(dc.getBlockSize(), dc.getOutputSize());
- digest.init(new KeyParameter(dc.getKey()));
-
- byte[] message = dc.getMessage();
- digest.update(message, 0, message.length);
-
- byte[] output = new byte[digest.getMacSize()];
- digest.doFinal(output, 0);
-
- if (!Arrays.areEqual(output, dc.getDigest()))
- {
- fail(digest.getAlgorithmName() + " message " + (dc.getMessage().length * 8) + " mismatch.\n Message " + new String(Hex.encode(dc.getMessage()))
- + "\n Key " + new String(Hex.encode(dc.getKey())) + "\n Expected "
- + new String(Hex.encode(dc.getDigest())) + "\n Actual " + new String(Hex.encode(output)));
- }
-
- }
-
- public static void main(String[] args)
- throws IOException
- {
- runTest(new SkeinMacTest());
- }
-
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/SkipjackTest.java b/core/src/test/java/org/bouncycastle/crypto/test/SkipjackTest.java
deleted file mode 100644
index 455e10bd..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/SkipjackTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.engines.SkipjackEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- */
-public class SkipjackTest
- extends CipherTest
-{
- static SimpleTest[] tests =
- {
- new BlockCipherVectorTest(0, new SkipjackEngine(),
- new KeyParameter(Hex.decode("00998877665544332211")),
- "33221100ddccbbaa", "2587cae27a12d300")
- };
-
- SkipjackTest()
- {
- super(tests, new SkipjackEngine(), new KeyParameter(Hex.decode("00998877665544332211")));
- }
-
- public String getName()
- {
- return "SKIPJACK";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new SkipjackTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/StreamCipherResetTest.java b/core/src/test/java/org/bouncycastle/crypto/test/StreamCipherResetTest.java
deleted file mode 100644
index 092de5fb..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/StreamCipherResetTest.java
+++ /dev/null
@@ -1,133 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.StreamCipher;
-import org.bouncycastle.crypto.engines.ChaChaEngine;
-import org.bouncycastle.crypto.engines.Grain128Engine;
-import org.bouncycastle.crypto.engines.Grainv1Engine;
-import org.bouncycastle.crypto.engines.HC128Engine;
-import org.bouncycastle.crypto.engines.HC256Engine;
-import org.bouncycastle.crypto.engines.ISAACEngine;
-import org.bouncycastle.crypto.engines.RC4Engine;
-import org.bouncycastle.crypto.engines.Salsa20Engine;
-import org.bouncycastle.crypto.engines.XSalsa20Engine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * Test whether block ciphers implement reset contract on init, encrypt/decrypt and reset.
- */
-public class StreamCipherResetTest
- extends SimpleTest
-{
- public String getName()
- {
- return "Stream Cipher Reset";
- }
-
- public void performTest()
- throws Exception
- {
- testReset(new Salsa20Engine(), new Salsa20Engine(), new ParametersWithIV(new KeyParameter(random(32)),
- random(8)));
- testReset(new Salsa20Engine(), new Salsa20Engine(), new ParametersWithIV(new KeyParameter(random(16)),
- random(8)));
- testReset(new XSalsa20Engine(), new XSalsa20Engine(), new ParametersWithIV(new KeyParameter(random(32)),
- random(24)));
- testReset(new ChaChaEngine(), new ChaChaEngine(), new ParametersWithIV(new KeyParameter(random(32)), random(8)));
- testReset(new ChaChaEngine(), new ChaChaEngine(), new ParametersWithIV(new KeyParameter(random(16)), random(8)));
- testReset(new RC4Engine(), new RC4Engine(), new KeyParameter(random(16)));
- testReset(new ISAACEngine(), new ISAACEngine(), new KeyParameter(random(16)));
- testReset(new HC128Engine(), new HC128Engine(), new ParametersWithIV(new KeyParameter(random(16)), random(16)));
- testReset(new HC256Engine(), new HC256Engine(), new ParametersWithIV(new KeyParameter(random(16)), random(16)));
- testReset(new Grainv1Engine(), new Grainv1Engine(), new ParametersWithIV(new KeyParameter(random(16)),
- random(8)));
- testReset(new Grain128Engine(), new Grain128Engine(), new ParametersWithIV(new KeyParameter(random(16)),
- random(12)));
- }
-
- private static final SecureRandom RAND = new SecureRandom();
-
- private byte[] random(int size)
- {
- final byte[] data = new byte[size];
- RAND.nextBytes(data);
- return data;
- }
-
- private void testReset(StreamCipher cipher1, StreamCipher cipher2, CipherParameters params)
- throws InvalidCipherTextException
- {
- cipher1.init(true, params);
-
- byte[] plaintext = new byte[1023];
- byte[] ciphertext = new byte[plaintext.length];
-
- // Establish baseline answer
- cipher1.processBytes(plaintext, 0, plaintext.length, ciphertext, 0);
-
- // Test encryption resets
- checkReset(cipher1, params, true, plaintext, ciphertext);
-
- // Test decryption resets with fresh instance
- cipher2.init(false, params);
- checkReset(cipher2, params, false, ciphertext, plaintext);
- }
-
- private void checkReset(StreamCipher cipher,
- CipherParameters params,
- boolean encrypt,
- byte[] pretext,
- byte[] posttext)
- throws InvalidCipherTextException
- {
- // Do initial run
- byte[] output = new byte[posttext.length];
- cipher.processBytes(pretext, 0, pretext.length, output, 0);
-
- // Check encrypt resets cipher
- cipher.init(encrypt, params);
-
- try
- {
- cipher.processBytes(pretext, 0, pretext.length, output, 0);
- }
- catch (Exception e)
- {
- fail(cipher.getAlgorithmName() + " init did not reset: " + e.getMessage());
- }
- if (!Arrays.areEqual(output, posttext))
- {
- fail(cipher.getAlgorithmName() + " init did not reset.", new String(Hex.encode(posttext)),
- new String(Hex.encode(output)));
- }
-
- // Check reset resets data
- cipher.reset();
-
- try
- {
- cipher.processBytes(pretext, 0, pretext.length, output, 0);
- }
- catch (Exception e)
- {
- fail(cipher.getAlgorithmName() + " reset did not reset: " + e.getMessage());
- }
- if (!Arrays.areEqual(output, posttext))
- {
- fail(cipher.getAlgorithmName() + " reset did not reset.");
- }
- }
-
- public static void main(String[] args)
- {
- runTest(new StreamCipherResetTest());
- }
-
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/StreamCipherVectorTest.java b/core/src/test/java/org/bouncycastle/crypto/test/StreamCipherVectorTest.java
deleted file mode 100644
index 7b788280..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/StreamCipherVectorTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.StreamCipher;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * a basic test that takes a stream cipher, key parameter, and an input
- * and output string.
- */
-public class StreamCipherVectorTest
- extends SimpleTest
-{
- int id;
- StreamCipher cipher;
- CipherParameters param;
- byte[] input;
- byte[] output;
-
- public StreamCipherVectorTest(
- int id,
- StreamCipher cipher,
- CipherParameters param,
- String input,
- String output)
- {
- this.id = id;
- this.cipher = cipher;
- this.param = param;
- this.input = Hex.decode(input);
- this.output = Hex.decode(output);
- }
-
- public String getName()
- {
- return cipher.getAlgorithmName() + " Vector Test " + id;
- }
-
- public void performTest()
- {
- cipher.init(true, param);
-
- byte[] out = new byte[input.length];
-
- cipher.processBytes(input, 0, input.length, out, 0);
-
- if (!areEqual(out, output))
- {
- fail("failed.", new String(Hex.encode(output)) , new String(Hex.encode(out)));
- }
-
- cipher.init(false, param);
-
- cipher.processBytes(output, 0, output.length, out, 0);
-
- if (!areEqual(input, out))
- {
- fail("failed reversal");
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/TEATest.java b/core/src/test/java/org/bouncycastle/crypto/test/TEATest.java
deleted file mode 100644
index 98b0ec9a..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/TEATest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.engines.TEAEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * TEA tester - based on C implementation results from http://www.simonshepherd.supanet.com/tea.htm
- */
-public class TEATest
- extends CipherTest
-{
- static SimpleTest[] tests = {
- new BlockCipherVectorTest(0, new TEAEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000")),
- "0000000000000000",
- "41ea3a0a94baa940"),
- new BlockCipherVectorTest(1, new TEAEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000")),
- "0102030405060708",
- "6a2f9cf3fccf3c55"),
- new BlockCipherVectorTest(2, new TEAEngine(),
- new KeyParameter(Hex.decode("0123456712345678234567893456789A")),
- "0000000000000000",
- "34e943b0900f5dcb"),
- new BlockCipherVectorTest(3, new TEAEngine(),
- new KeyParameter(Hex.decode("0123456712345678234567893456789A")),
- "0102030405060708",
- "773dc179878a81c0"),
- };
-
- TEATest()
- {
- super(tests, new TEAEngine(), new KeyParameter(new byte[16]));
- }
-
- public String getName()
- {
- return "TEA";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new TEATest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/Threefish1024Test.java b/core/src/test/java/org/bouncycastle/crypto/test/Threefish1024Test.java
deleted file mode 100644
index a580a156..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/Threefish1024Test.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.engines.ThreefishEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.TweakableBlockCipherParameters;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class Threefish1024Test
- extends CipherTest
-{
- // Test cases from skein_golden_kat_internals.txt in Skein 1.3 NIST CD
- static SimpleTest[] tests =
- {
- new BlockCipherVectorTest(0, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024),
- new TweakableBlockCipherParameters(
- new KeyParameter(new byte[128]),
- new byte[16]),
- "0000000000000000000000000000000000000000000000000000000000000000" +
- "0000000000000000000000000000000000000000000000000000000000000000" +
- "0000000000000000000000000000000000000000000000000000000000000000" +
- "0000000000000000000000000000000000000000000000000000000000000000",
- "f05c3d0a3d05b304f785ddc7d1e036015c8aa76e2f217b06c6e1544c0bc1a90d" +
- "f0accb9473c24e0fd54fea68057f43329cb454761d6df5cf7b2e9b3614fbd5a2" +
- "0b2e4760b40603540d82eabc5482c171c832afbe68406bc39500367a592943fa" +
- "9a5b4a43286ca3c4cf46104b443143d560a4b230488311df4feef7e1dfe8391e"),
- new BlockCipherVectorTest(1, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024),
- new TweakableBlockCipherParameters(
- new KeyParameter(Hex.decode(
- "101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f" +
- "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" +
- "505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f" +
- "707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f")),
- Hex.decode("000102030405060708090a0b0c0d0e0f")),
- "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0" +
- "dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0" +
- "bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0afaeadacabaaa9a8a7a6a5a4a3a2a1a0" +
- "9f9e9d9c9b9a999897969594939291908f8e8d8c8b8a89888786858483828180",
- "a6654ddbd73cc3b05dd777105aa849bce49372eaaffc5568d254771bab85531c" +
- "94f780e7ffaae430d5d8af8c70eebbe1760f3b42b737a89cb363490d670314bd" +
- "8aa41ee63c2e1f45fbd477922f8360b388d6125ea6c7af0ad7056d01796e90c8" +
- "3313f4150a5716b30ed5f569288ae974ce2b4347926fce57de44512177dd7cde")
- };
-
- Threefish1024Test()
- {
- super(tests, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024), new KeyParameter(new byte[128]));
- }
-
- public String getName()
- {
- return "Threefish-1024";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new Threefish1024Test());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/Threefish256Test.java b/core/src/test/java/org/bouncycastle/crypto/test/Threefish256Test.java
deleted file mode 100644
index 10bd6080..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/Threefish256Test.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.engines.ThreefishEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.TweakableBlockCipherParameters;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class Threefish256Test
- extends CipherTest
-{
- // Test cases from skein_golden_kat_internals.txt in Skein 1.3 NIST CD
- static SimpleTest[] tests =
- {
- new BlockCipherVectorTest(0, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_256),
- new TweakableBlockCipherParameters(
- new KeyParameter(new byte[32]),
- new byte[16]),
- "0000000000000000000000000000000000000000000000000000000000000000",
- "84da2a1f8beaee947066ae3e3103f1ad536db1f4a1192495116b9f3ce6133fd8"),
- new BlockCipherVectorTest(1, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_256),
- new TweakableBlockCipherParameters(
- new KeyParameter(Hex.decode(
- "101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f")),
- Hex.decode("000102030405060708090a0b0c0d0e0f")),
- "FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0",
- "e0d091ff0eea8fdfc98192e62ed80ad59d865d08588df476657056b5955e97df")
- };
-
- Threefish256Test()
- {
- super(tests, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_256), new KeyParameter(new byte[32]));
- }
-
- public String getName()
- {
- return "Threefish-256";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new Threefish256Test());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/Threefish512Test.java b/core/src/test/java/org/bouncycastle/crypto/test/Threefish512Test.java
deleted file mode 100644
index 1eb4e85c..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/Threefish512Test.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.engines.ThreefishEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.TweakableBlockCipherParameters;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class Threefish512Test
- extends CipherTest
-{
- // Test cases from skein_golden_kat_internals.txt in Skein 1.3 NIST CD
- static SimpleTest[] tests =
- {
- new BlockCipherVectorTest(0, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512),
- new TweakableBlockCipherParameters(
- new KeyParameter(new byte[64]),
- new byte[16]),
- "0000000000000000000000000000000000000000000000000000000000000000" +
- "0000000000000000000000000000000000000000000000000000000000000000",
- "b1a2bbc6ef6025bc40eb3822161f36e375d1bb0aee3186fbd19e47c5d479947b" +
- "7bc2f8586e35f0cff7e7f03084b0b7b1f1ab3961a580a3e97eb41ea14a6d7bbe"),
- new BlockCipherVectorTest(1, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512),
- new TweakableBlockCipherParameters(
- new KeyParameter(Hex.decode(
- "101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f" +
- "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f")),
- Hex.decode("000102030405060708090a0b0c0d0e0f")),
- "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0" +
- "dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0",
- "e304439626d45a2cb401cad8d636249a6338330eb06d45dd8b36b90e97254779" +
- "272a0a8d99463504784420ea18c9a725af11dffea10162348927673d5c1caf3d")
- };
-
- Threefish512Test()
- {
- super(tests, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512), new KeyParameter(new byte[64]));
- }
-
- public String getName()
- {
- return "Threefish-512";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new Threefish512Test());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/TigerDigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/TigerDigestTest.java
deleted file mode 100644
index deb838f0..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/TigerDigestTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.TigerDigest;
-
-/**
- * Tiger Digest Test
- */
-public class TigerDigestTest
- extends DigestTest
-{
- final static String[] messages = {
- "",
- "abc",
- "Tiger",
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvw",
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789",
- "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge, 1996.",
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"
- };
-
- final static String[] digests = {
- "3293AC630C13F0245F92BBB1766E16167A4E58492DDE73F3",
- "2AAB1484E8C158F2BFB8C5FF41B57A525129131C957B5F93",
- "DD00230799F5009FEC6DEBC838BB6A27DF2B9D6F110C7937",
- "F71C8583902AFB879EDFE610F82C0D4786A3A534504486B5",
- "38F41D9D9A710A10C3727AC0DEEAA270727D9F926EC10139",
- "48CEEB6308B87D46E95D656112CDF18D97915F9765658957",
- "631ABDD103EB9A3D245B6DFD4D77B257FC7439501D1568DD",
- "C54034E5B43EB8005848A7E0AE6AAC76E4FF590AE715FD25",
- "C54034E5B43EB8005848A7E0AE6AAC76E4FF590AE715FD25"
- };
-
- final static String hash64k = "FDF4F5B35139F48E710E421BE5AF411DE1A8AAC333F26204";
-
- TigerDigestTest()
- {
- super(new TigerDigest(), messages, digests);
- }
-
- public void performTest()
- {
- super.performTest();
-
- sixtyFourKTest(hash64k);
- }
-
- protected Digest cloneDigest(Digest digest)
- {
- return new TigerDigest((TigerDigest)digest);
- }
-
- public static void main(
- String[] args)
- {
- runTest(new TigerDigestTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/TwofishTest.java b/core/src/test/java/org/bouncycastle/crypto/test/TwofishTest.java
deleted file mode 100644
index 50a41c81..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/TwofishTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.engines.TwofishEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class TwofishTest
- extends CipherTest
-{
- static String key1 = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
- static String key2 = "000102030405060708090a0b0c0d0e0f1011121314151617";
- static String key3 = "000102030405060708090a0b0c0d0e0f";
-
- static String input = "000102030405060708090A0B0C0D0E0F";
-
- static SimpleTest[] tests =
- {
- new BlockCipherVectorTest(0, new TwofishEngine(),
- new KeyParameter(Hex.decode(key1)),
- input, "8ef0272c42db838bcf7b07af0ec30f38"),
- new BlockCipherVectorTest(1, new TwofishEngine(),
- new KeyParameter(Hex.decode(key2)),
- input, "95accc625366547617f8be4373d10cd7"),
- new BlockCipherVectorTest(2, new TwofishEngine(),
- new KeyParameter(Hex.decode(key3)),
- input, "9fb63337151be9c71306d159ea7afaa4")
- };
-
- TwofishTest()
- {
- super(tests, new TwofishEngine(), new KeyParameter(new byte[32]));
- }
-
- public String getName()
- {
- return "Twofish";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new TwofishTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/VMPCKSA3Test.java b/core/src/test/java/org/bouncycastle/crypto/test/VMPCKSA3Test.java
deleted file mode 100644
index 65fdfc22..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/VMPCKSA3Test.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.engines.VMPCKSA3Engine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * VMPC Test
- */
-public class VMPCKSA3Test extends SimpleTest
-{
- private static final byte[] input = new byte[1000000];
-
- public String getName()
- {
- return "VMPC-KSA3";
- }
-
- private void checkByte(byte[] array, int position, byte b)
- {
- if (array[position] != b)
- {
- fail("Fail on position " + position,
- new String(Hex.encode(new byte[] { b })),
- new String(Hex.encode(new byte[] { array[position] })));
- }
- }
-
- public void performTest()
- {
- byte[] key = Hex.decode("9661410AB797D8A9EB767C21172DF6C7");
- byte[] iv = Hex.decode("4B5C2F003E67F39557A8D26F3DA2B155");
- CipherParameters kp = new KeyParameter(key);
- CipherParameters kpwiv = new ParametersWithIV(kp, iv);
-
- VMPCKSA3Engine engine = new VMPCKSA3Engine();
-
- try
- {
- engine.init(true, kp);
- fail("init failed to throw expected exception");
- }
- catch (IllegalArgumentException e)
- {
- // Expected
- }
-
- engine.init(true, kpwiv);
- checkEngine(engine);
-
- engine.reset();
- byte[] output = checkEngine(engine);
-
- engine.init(false, kpwiv);
- byte[] recovered = new byte[output.length];
- engine.processBytes(output, 0, output.length, recovered, 0);
-
- if (!Arrays.areEqual(input, recovered))
- {
- fail("decrypted bytes differ from original bytes");
- }
- }
-
- private byte[] checkEngine(VMPCKSA3Engine engine)
- {
- byte[] output = new byte[input.length];
- engine.processBytes(input, 0, output.length, output, 0);
-
- checkByte(output, 0, (byte) 0xB6);
- checkByte(output, 1, (byte) 0xEB);
- checkByte(output, 2, (byte) 0xAE);
- checkByte(output, 3, (byte) 0xFE);
- checkByte(output, 252, (byte) 0x48);
- checkByte(output, 253, (byte) 0x17);
- checkByte(output, 254, (byte) 0x24);
- checkByte(output, 255, (byte) 0x73);
- checkByte(output, 1020, (byte) 0x1D);
- checkByte(output, 1021, (byte) 0xAE);
- checkByte(output, 1022, (byte) 0xC3);
- checkByte(output, 1023, (byte) 0x5A);
- checkByte(output, 102396, (byte) 0x1D);
- checkByte(output, 102397, (byte) 0xA7);
- checkByte(output, 102398, (byte) 0xE1);
- checkByte(output, 102399, (byte) 0xDC);
-
- return output;
- }
-
- public static void main(String[] args)
- {
- runTest(new VMPCKSA3Test());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/VMPCMacTest.java b/core/src/test/java/org/bouncycastle/crypto/test/VMPCMacTest.java
deleted file mode 100644
index 50a0410b..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/VMPCMacTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.macs.VMPCMac;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class VMPCMacTest extends SimpleTest
-{
- public String getName()
- {
- return "VMPC-MAC";
- }
-
- public static void main(String[] args)
- {
- runTest(new VMPCMacTest());
- }
-
- static byte[] output1 = Hex.decode("9BDA16E2AD0E284774A3ACBC8835A8326C11FAAD");
-
- public void performTest() throws Exception
- {
- CipherParameters kp = new KeyParameter(
- Hex.decode("9661410AB797D8A9EB767C21172DF6C7"));
- CipherParameters kpwiv = new ParametersWithIV(kp,
- Hex.decode("4B5C2F003E67F39557A8D26F3DA2B155"));
-
- byte[] m = new byte[256];
- for (int i = 0; i < 256; i++)
- {
- m[i] = (byte) i;
- }
-
- VMPCMac mac = new VMPCMac();
- mac.init(kpwiv);
-
- mac.update(m, 0, m.length);
-
- byte[] out = new byte[20];
- mac.doFinal(out, 0);
-
- if (!Arrays.areEqual(out, output1))
- {
- fail("Fail", new String(Hex.encode(output1)), new String(Hex.encode(out)));
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/VMPCTest.java b/core/src/test/java/org/bouncycastle/crypto/test/VMPCTest.java
deleted file mode 100644
index cedffa46..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/VMPCTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.engines.VMPCEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * VMPC Test
- */
-public class VMPCTest extends SimpleTest
-{
- private static final byte[] input = new byte[1000000];
-
- public String getName()
- {
- return "VMPC";
- }
-
- private void checkByte(byte[] array, int position, byte b)
- {
- if (array[position] != b)
- {
- fail("Fail on position " + position,
- new String(Hex.encode(new byte[] { b })),
- new String(Hex.encode(new byte[] { array[position] })));
- }
- }
-
- public void performTest()
- {
- byte[] key = Hex.decode("9661410AB797D8A9EB767C21172DF6C7");
- byte[] iv = Hex.decode("4B5C2F003E67F39557A8D26F3DA2B155");
- CipherParameters kp = new KeyParameter(key);
- CipherParameters kpwiv = new ParametersWithIV(kp, iv);
-
- VMPCEngine engine = new VMPCEngine();
-
- try
- {
- engine.init(true, kp);
- fail("init failed to throw expected exception");
- }
- catch (IllegalArgumentException e)
- {
- // Expected
- }
-
- engine.init(true, kpwiv);
- checkEngine(engine);
-
- engine.reset();
- byte[] output = checkEngine(engine);
-
- engine.init(false, kpwiv);
- byte[] recovered = new byte[output.length];
- engine.processBytes(output, 0, output.length, recovered, 0);
-
- if (!Arrays.areEqual(input, recovered))
- {
- fail("decrypted bytes differ from original bytes");
- }
- }
-
- private byte[] checkEngine(VMPCEngine engine)
- {
- byte[] output = new byte[input.length];
- engine.processBytes(input, 0, output.length, output, 0);
-
- checkByte(output, 0, (byte) 0xA8);
- checkByte(output, 1, (byte) 0x24);
- checkByte(output, 2, (byte) 0x79);
- checkByte(output, 3, (byte) 0xF5);
- checkByte(output, 252, (byte) 0xB8);
- checkByte(output, 253, (byte) 0xFC);
- checkByte(output, 254, (byte) 0x66);
- checkByte(output, 255, (byte) 0xA4);
- checkByte(output, 1020, (byte) 0xE0);
- checkByte(output, 1021, (byte) 0x56);
- checkByte(output, 1022, (byte) 0x40);
- checkByte(output, 1023, (byte) 0xA5);
- checkByte(output, 102396, (byte) 0x81);
- checkByte(output, 102397, (byte) 0xCA);
- checkByte(output, 102398, (byte) 0x49);
- checkByte(output, 102399, (byte) 0x9A);
-
- return output;
- }
-
- public static void main(String[] args)
- {
- runTest(new VMPCTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/WhirlpoolDigestTest.java b/core/src/test/java/org/bouncycastle/crypto/test/WhirlpoolDigestTest.java
deleted file mode 100644
index 542e6e6b..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/WhirlpoolDigestTest.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.WhirlpoolDigest;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * ISO vector test for Whirlpool
- *
- */
-public class WhirlpoolDigestTest
- extends DigestTest
-{
- private static String[] messages =
- {
- "",
- "a",
- "abc",
- "message digest",
- "abcdefghijklmnopqrstuvwxyz",
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
- "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
- "abcdbcdecdefdefgefghfghighijhijk"
- };
-
- private static String[] digests =
- {
- "19FA61D75522A4669B44E39C1D2E1726C530232130D407F89AFEE0964997F7A73E83BE698B288FEBCF88E3E03C4F0757EA8964E59B63D93708B138CC42A66EB3",
- "8ACA2602792AEC6F11A67206531FB7D7F0DFF59413145E6973C45001D0087B42D11BC645413AEFF63A42391A39145A591A92200D560195E53B478584FDAE231A",
- "4E2448A4C6F486BB16B6562C73B4020BF3043E3A731BCE721AE1B303D97E6D4C7181EEBDB6C57E277D0E34957114CBD6C797FC9D95D8B582D225292076D4EEF5",
- "378C84A4126E2DC6E56DCC7458377AAC838D00032230F53CE1F5700C0FFB4D3B8421557659EF55C106B4B52AC5A4AAA692ED920052838F3362E86DBD37A8903E",
- "F1D754662636FFE92C82EBB9212A484A8D38631EAD4238F5442EE13B8054E41B08BF2A9251C30B6A0B8AAE86177AB4A6F68F673E7207865D5D9819A3DBA4EB3B",
- "DC37E008CF9EE69BF11F00ED9ABA26901DD7C28CDEC066CC6AF42E40F82F3A1E08EBA26629129D8FB7CB57211B9281A65517CC879D7B962142C65F5A7AF01467",
- "466EF18BABB0154D25B9D38A6414F5C08784372BCCB204D6549C4AFADB6014294D5BD8DF2A6C44E538CD047B2681A51A2C60481E88C5A20B2C2A80CF3A9A083B",
- "2A987EA40F917061F5D6F0A0E4644F488A7A5A52DEEE656207C562F988E95C6916BDC8031BC5BE1B7B947639FE050B56939BAAA0ADFF9AE6745B7B181C3BE3FD"
- };
-
- WhirlpoolDigestTest()
- {
- super(new WhirlpoolDigest(), messages, digests);
- }
-
- protected Digest cloneDigest(Digest digest)
- {
- return new WhirlpoolDigest((WhirlpoolDigest)digest);
- }
-
- private static String _millionAResultVector = "0C99005BEB57EFF50A7CF005560DDF5D29057FD86B20BFD62DECA0F1CCEA4AF51FC15490EDDC47AF32BB2B66C34FF9AD8C6008AD677F77126953B226E4ED8B01";
-
- private static String _thirtyOneZeros = "3E3F188F8FEBBEB17A933FEAF7FE53A4858D80C915AD6A1418F0318E68D49B4E459223CD414E0FBC8A57578FD755D86E827ABEF4070FC1503E25D99E382F72BA";
-
- public String getName()
- {
- return "Whirlpool";
- }
-
- public void performTest()
- {
- super.performTest();
-
- byte[] thirtyOneZeros = new byte[31];
- performStandardVectorTest("31 zeroes test",
- thirtyOneZeros, _thirtyOneZeros);
-
- byte[] millionAInByteArray = new byte[1000000];
- Arrays.fill(millionAInByteArray, (byte)'a');
-
- performStandardVectorTest("Million 'a' test",
- millionAInByteArray, _millionAResultVector);
- }
-
- private void performStandardVectorTest(String testTitle, byte[] inputBytes,
- String resultsAsHex)
- {
- doPerformTest(testTitle, inputBytes, resultsAsHex);
- }
-
- private void doPerformTest(String testTitle, byte[] inputBytes, String resultsAsHex)
- {
- String resStr = createHexOutputFromDigest(inputBytes);
- if (!resultsAsHex.equals(resStr.toUpperCase()))
- {
- fail(testTitle, resultsAsHex, resStr);
- }
- }
-
- private String createHexOutputFromDigest(byte[] digestBytes)
- {
- String resStr;
- Digest digest = new WhirlpoolDigest();
- byte[] resBuf = new byte[digest.getDigestSize()];
- digest.update(digestBytes, 0, digestBytes.length);
- digest.doFinal(resBuf, 0);
- resStr = new String(Hex.encode(resBuf));
- return resStr;
- }
-
- public static void main(String[] args)
- {
- runTest(new WhirlpoolDigestTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/XSalsa20Test.java b/core/src/test/java/org/bouncycastle/crypto/test/XSalsa20Test.java
deleted file mode 100644
index efbd5ec0..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/XSalsa20Test.java
+++ /dev/null
@@ -1,166 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.engines.XSalsa20Engine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class XSalsa20Test extends SimpleTest
-{
- private static class TestCase
- {
-
- private byte[] key;
- private byte[] iv;
- private byte[] plaintext;
- private byte[] ciphertext;
-
- public TestCase(String key, String iv, String plaintext, String ciphertext)
- {
- this.key = Hex.decode(key);
- this.iv = Hex.decode(iv);
- this.plaintext = Hex.decode(plaintext);
- this.ciphertext = Hex.decode(ciphertext);
- }
-
- public byte[] getKey()
- {
- return key;
- }
-
- public byte[] getIv()
- {
- return iv;
- }
-
- public byte[] getPlaintext()
- {
- return plaintext;
- }
-
- public byte[] getCiphertext()
- {
- return ciphertext;
- }
- }
-
- // Test cases generated by naclcrypto-20090308, as used by cryptopp
- private static final TestCase[] TEST_CASES = new TestCase[] {
- new TestCase(
- "a6a7251c1e72916d11c2cb214d3c252539121d8e234e652d651fa4c8cff88030",
- "9e645a74e9e0a60d8243acd9177ab51a1beb8d5a2f5d700c",
- "093c5e5585579625337bd3ab619d615760d8c5b224a85b1d0efe0eb8a7ee163abb0376529fcc09bab506c618e13ce777d82c3ae9d1a6f972d4160287cbfe60bf2130fc0a6ff6049d0a5c8a82f429231f008082e845d7e189d37f9ed2b464e6b919e6523a8c1210bd52a02a4c3fe406d3085f5068d1909eeeca6369abc981a42e87fe665583f0ab85ae71f6f84f528e6b397af86f6917d9754b7320dbdc2fea81496f2732f532ac78c4e9c6cfb18f8e9bdf74622eb126141416776971a84f94d156beaf67aecbf2ad412e76e66e8fad7633f5b6d7f3d64b5c6c69ce29003c6024465ae3b89be78e915d88b4b5621d",
- "b2af688e7d8fc4b508c05cc39dd583d6714322c64d7f3e63147aede2d9534934b04ff6f337b031815cd094bdbc6d7a92077dce709412286822ef0737ee47f6b7ffa22f9d53f11dd2b0a3bb9fc01d9a88f9d53c26e9365c2c3c063bc4840bfc812e4b80463e69d179530b25c158f543191cff993106511aa036043bbc75866ab7e34afc57e2cce4934a5faae6eabe4f221770183dd060467827c27a354159a081275a291f69d946d6fe28ed0b9ce08206cf484925a51b9498dbde178ddd3ae91a8581b91682d860f840782f6eea49dbb9bd721501d2c67122dea3b7283848c5f13e0c0de876bd227a856e4de593a3"),
- new TestCase(
- "9e1da239d155f52ad37f75c7368a536668b051952923ad44f57e75ab588e475a",
- "af06f17859dffa799891c4288f6635b5c5a45eee9017fd72",
- "feac9d54fc8c115ae247d9a7e919dd76cfcbc72d32cae4944860817cbdfb8c04e6b1df76a16517cd33ccf1acda9206389e9e318f5966c093cfb3ec2d9ee2de856437ed581f552f26ac2907609df8c613b9e33d44bfc21ff79153e9ef81a9d66cc317857f752cc175fd8891fefebb7d041e6517c3162d197e2112837d3bc4104312ad35b75ea686e7c70d4ec04746b52ff09c421451459fb59f",
- "2c261a2f4e61a62e1b27689916bf03453fcbc97bb2af6f329391ef063b5a219bf984d07d70f602d85f6db61474e9d9f5a2deecb4fcd90184d16f3b5b5e168ee03ea8c93f3933a22bc3d1a5ae8c2d8b02757c87c073409052a2a8a41e7f487e041f9a49a0997b540e18621cad3a24f0a56d9b19227929057ab3ba950f6274b121f193e32e06e5388781a1cb57317c0ba6305e910961d01002f0"),
- new TestCase("d5c7f6797b7e7e9c1d7fd2610b2abf2bc5a7885fb3ff78092fb3abe8986d35e2",
- "744e17312b27969d826444640e9c4a378ae334f185369c95",
- "7758298c628eb3a4b6963c5445ef66971222be5d1a4ad839715d1188071739b77cc6e05d5410f963a64167629757",
- "27b8cfe81416a76301fd1eec6a4d99675069b2da2776c360db1bdfea7c0aa613913e10f7a60fec04d11e65f2d64e"),
- new TestCase(
- "737d7811ce96472efed12258b78122f11deaec8759ccbd71eac6bbefa627785c",
- "6fb2ee3dda6dbd12f1274f126701ec75c35c86607adb3edd",
- "501325fb2645264864df11faa17bbd58312b77cad3d94ac8fb8542f0eb653ad73d7fce932bb874cb89ac39fc47f8267cf0f0c209f204b2d8578a3bdf461cb6a271a468bebaccd9685014ccbc9a73618c6a5e778a21cc8416c60ad24ddc417a130d53eda6dfbfe47d09170a7be1a708b7b5f3ad464310be36d9a2a95dc39e83d38667e842eb6411e8a23712297b165f690c2d7ca1b1346e3c1fccf5cafd4f8be0",
- "6724c372d2e9074da5e27a6c54b2d703dc1d4c9b1f8d90f00c122e692ace7700eadca942544507f1375b6581d5a8fb39981c1c0e6e1ff2140b082e9ec016fce141d5199647d43b0b68bfd0fea5e00f468962c7384dd6129aea6a3fdfe75abb210ed5607cef8fa0e152833d5ac37d52e557b91098a322e76a45bbbcf4899e790618aa3f4c2e5e0fc3de93269a577d77a5502e8ea02f717b1dd2df1ec69d8b61ca"),
- new TestCase(
- "760158da09f89bbab2c99e6997f9523a95fcef10239bcca2573b7105f6898d34",
- "43636b2cc346fc8b7c85a19bf507bdc3dafe953b88c69dba",
- "d30a6d42dff49f0ed039a306bae9dec8d9e88366cc19e8c3642fd58fa0794ebf8029d949730339b0823a51f0f49f0d2c71f1051c1e0e2c86941f172789cdb1b0107413e70f982ff9761877bb526ef1c3eb1106a948d60ef21bd35d32cfd64f89b79ed63ecc5cca56246af736766f285d8e6b0da9cb1cd21020223ffacc5a32",
- "c815b6b79b64f9369aec8dce8c753df8a50f2bc97c70ce2f014db33a65ac5816bac9e30ac08bdded308c65cb87e28e2e71b677dc25c5a6499c1553555daf1f55270a56959dffa0c66f24e0af00951ec4bb59ccc3a6c5f52e0981647e53e439313a52c40fa7004c855b6e6eb25b212a138e843a9ba46edb2a039ee82a263abe"),
- new TestCase(
- "27ba7e81e7edd4e71be53c07ce8e633138f287e155c7fa9e84c4ad804b7fa1b9",
- "ea05f4ebcd2fb6b000da0612861ba54ff5c176fb601391aa",
- "e09ff5d2cb050d69b2d42494bde5825238c756d6991d99d7a20d1ef0b83c371c89872690b2fc11d5369f4fc4971b6d3d6c078aef9b0f05c0e61ab89c025168054defeb03fef633858700c58b1262ce011300012673e893e44901dc18eee3105699c44c805897bdaf776af1833162a21a",
- "a23e7ef93c5d0667c96d9e404dcbe6be62026fa98f7a3ff9ba5d458643a16a1cef7272dc6097a9b52f35983557c77a11b314b4f7d5dc2cca15ee47616f861873cbfed1d32372171a61e38e447f3cf362b3abbb2ed4170d89dcb28187b7bfd206a3e026f084a7e0ed63d319de6bc9afc0"),
- new TestCase("6799d76e5ffb5b4920bc2768bafd3f8c16554e65efcf9a16f4683a7a06927c11",
- "61ab951921e54ff06d9b77f313a4e49df7a057d5fd627989", "472766", "8fd7df"),
- new TestCase(
- "f68238c08365bb293d26980a606488d09c2f109edafa0bbae9937b5cc219a49c",
- "5190b51e9b708624820b5abdf4e40fad1fb950ad1adc2d26",
- "47ec6b1f73c4b7ff5274a0bfd7f45f864812c85a12fbcb3c2cf8a3e90cf66ccf2eacb521e748363c77f52eb426ae57a0c6c78f75af71284569e79d1a92f949a9d69c4efc0b69902f1e36d7562765543e2d3942d9f6ff5948d8a312cff72c1afd9ea3088aff7640bfd265f7a9946e606abc77bcedae6bddc75a0dba0bd917d73e3bd1268f727e0096345da1ed25cf553ea7a98fea6b6f285732de37431561ee1b3064887fbcbd71935e02",
- "36160e88d3500529ba4edba17bc24d8cfaca9a0680b3b1fc97cf03f3675b7ac301c883a68c071bc54acdd3b63af4a2d72f985e51f9d60a4c7fd481af10b2fc75e252fdee7ea6b6453190617dcc6e2fe1cd56585fc2f0b0e97c5c3f8ad7eb4f31bc4890c03882aac24cc53acc1982296526690a220271c2f6e326750d3fbda5d5b63512c831f67830f59ac49aae330b3e0e02c9ea0091d19841f1b0e13d69c9fbfe8a12d6f30bb734d9d2"),
- new TestCase(
- "45b2bd0de4ed9293ec3e26c4840faaf64b7d619d51e9d7a2c7e36c83d584c3df",
- "546c8c5d6be8f90952cab3f36d7c1957baaa7a59abe3d7e5",
- "5007c8cd5b3c40e17d7fe423a87ae0ced86bec1c39dc07a25772f3e96dabd56cd3fd7319f6c9654925f2d87087a700e1b130da796895d1c9b9acd62b266144067d373ed51e787498b03c52faad16bb3826fa511b0ed2a19a8663f5ba2d6ea7c38e7212e9697d91486c49d8a000b9a1935d6a7ff7ef23e720a45855481440463b4ac8c4f6e7062adc1f1e1e25d3d65a31812f58a71160",
- "8eacfba568898b10c0957a7d44100685e8763a71a69a8d16bc7b3f88085bb9a2f09642e4d09a9f0ad09d0aad66b22610c8bd02ff6679bb92c2c026a216bf425c6be35fb8dae7ff0c72b0efd6a18037c70eed0ca90062a49a3c97fdc90a8f9c2ea536bfdc41918a7582c9927fae47efaa3dc87967b7887dee1bf071734c7665901d9105dae2fdf66b4918e51d8f4a48c60d19fbfbbcba"),
- new TestCase(
- "fe559c9a282beb40814d016d6bfcb2c0c0d8bf077b1110b8703a3ce39d70e0e1",
- "b076200cc7011259805e18b304092754002723ebec5d6200",
- "6db65b9ec8b114a944137c821fd606be75478d928366d5284096cdef782fcff7e8f59cb8ffcda979757902c5ffa6bc477ceaa4cb5d5ea76f94d91e833f823a6bc78f1055dfa6a97bea8965c1cde67a668e001257334a585727d9e0f7c1a06e88d3d25a4e6d9096c968bf138e116a3ebeffd4bb4808adb1fd698164ba0a35c709a47f16f1f4435a2345a9194a00b95abd51851d505809a6077da9baca5831afff31578c487ee68f2767974a98a7e803aac788da98319c4ea8eaa3d394855651f484cef543f537e35158ee29",
- "4dce9c8f97a028051b0727f34e1b9ef21f06f0760f36e71713204027902090ba2bb6b13436ee778d9f50530efbd7a32b0d41443f58ccaee781c7b716d3a96fdec0e3764ed7959f34c3941278591ea033b5cbadc0f1916032e9bebbd1a8395b83fb63b1454bd775bd20b3a2a96f951246ac14daf68166ba62f6cbff8bd121ac9498ff8852fd2be975df52b5daef3829d18eda42e715022dcbf930d0a789ee6a146c2c7088c35773c63c06b4af4559856ac199ced86863e4294707825337c5857970eb7fddeb263781309011"),
- new TestCase(
- "0ae10012d7e56614b03dcc89b14bae9242ffe630f3d7e35ce8bbb97bbc2c92c3",
- "f96b025d6cf46a8a12ac2af1e2aef1fb83590adadaa5c5ea",
- "ea0f354e96f12bc72bbaa3d12b4a8ed879b042f0689878f46b651cc4116d6f78409b11430b3aaa30b2076891e8e1fa528f2fd169ed93dc9f84e24409eec2101daf4d057be2492d11de640cbd7b355ad29fb70400fffd7cd6d425abeeb732a0eaa4330af4c656252c4173deab653eb85c58462d7ab0f35fd12b613d29d473d330310dc323d3c66348bbdbb68a326324657cae7b77a9e34358f2cec50c85609e73056856796e3be8d62b6e2fe9f953",
- "e8abd48924b54e5b80866be7d4ebe5cf4274cafff08b39cb2d40a8f0b472398aedc776e0793812fbf1f60078635d2ed86b15efcdba60411ee23b07233592a44ec31b1013ce8964236675f8f183aef885e864f2a72edf4215b5338fa2b54653dfa1a8c55ce5d95cc605b9b311527f2e3463ffbec78a9d1d65dabad2f338769c9f43f133a791a11c7eca9af0b771a4ac32963dc8f631a2c11217ac6e1b9430c1aae1ceebe22703f429998a8fb8c641"),
- new TestCase(
- "082c539bc5b20f97d767cd3f229eda80b2adc4fe49c86329b5cd6250a9877450",
- "845543502e8b64912d8f2c8d9fffb3c69365686587c08d0c",
- "a96bb7e910281a6dfad7c8a9c370674f0ceec1ad8d4f0de32f9ae4a23ed329e3d6bc708f876640a229153ac0e7281a8188dd77695138f01cda5f41d5215fd5c6bdd46d982cb73b1efe2997970a9fdbdb1e768d7e5db712068d8ba1af6067b5753495e23e6e1963af012f9c7ce450bf2de619d3d59542fb55f3",
- "835da74fc6de08cbda277a7966a07c8dcd627e7b17adde6d930b6581e3124b8baad096f693991fedb1572930601fc7709541839b8e3ffd5f033d2060d999c6c6e3048276613e648000acb5212cc632a916afce290e20ebdf612d08a6aa4c79a74b070d3f872a861f8dc6bb07614db515d363349d3a8e3336a3"),
- new TestCase("3d02bff3375d403027356b94f514203737ee9a85d2052db3e4e5a217c259d18a",
- "74216c95031895f48c1dba651555ebfa3ca326a755237025",
- "0d4b0f54fd09ae39baa5fa4baccf2e6682e61b257e01f42b8f",
- "16c4006c28365190411eb1593814cf15e74c22238f210afc3d"),
- new TestCase(
- "ad1a5c47688874e6663a0f3fa16fa7efb7ecadc175c468e5432914bdb480ffc6",
- "e489eed440f1aae1fac8fb7a9825635454f8f8f1f52e2fcc",
- "aa6c1e53580f03a9abb73bfdadedfecada4c6b0ebe020ef10db745e54ba861caf65f0e40dfc520203bb54d29e0a8f78f16b3f1aa525d6bfa33c54726e59988cfbec78056",
- "02fe84ce81e178e7aabdd3ba925a766c3c24756eefae33942af75e8b464556b5997e616f3f2dfc7fce91848afd79912d9fb55201b5813a5a074d2c0d4292c1fd441807c5"),
- new TestCase(
- "053a02bedd6368c1fb8afc7a1b199f7f7ea2220c9a4b642a6850091c9d20ab9c",
- "c713eea5c26dad75ad3f52451e003a9cb0d649f917c89dde",
- "8f0a8a164760426567e388840276de3f95cb5e3fadc6ed3f3e4fe8bc169d9388804dcb94b6587dbb66cb0bd5f87b8e98b52af37ba290629b858e0e2aa7378047a26602",
- "516710e59843e6fbd4f25d0d8ca0ec0d47d39d125e9dad987e0518d49107014cb0ae405e30c2eb3794750bca142ce95e290cf95abe15e822823e2e7d3ab21bc8fbd445"),
- new TestCase(
- "5b14ab0fbed4c58952548a6cb1e0000cf4481421f41288ea0aa84add9f7deb96",
- "54bf52b911231b952ba1a6af8e45b1c5a29d97e2abad7c83",
- "37fb44a675978b560ff9a4a87011d6f3ad2d37a2c3815b45a3c0e6d1b1d8b1784cd468927c2ee39e1dccd4765e1c3d676a335be1ccd6900a45f5d41a317648315d8a8c24adc64eb285f6aeba05b9029586353d303f17a807658b9ff790474e1737bd5fdc604aeff8dfcaf1427dcc3aacbb0256badcd183ed75a2dc52452f87d3c1ed2aa583472b0ab91cda20614e9b6fdbda3b49b098c95823cc72d8e5b717f2314b0324e9ce",
- "ae6deb5d6ce43d4b09d0e6b1c0e9f46157bcd8ab50eaa3197ff9fa2bf7af649eb52c68544fd3adfe6b1eb316f1f23538d470c30dbfec7e57b60cbcd096c782e7736b669199c8253e70214cf2a098fda8eac5da79a9496a3aae754d03b17c6d70d1027f42bf7f95ce3d1d9c338854e158fcc803e4d6262fb639521e47116ef78a7a437ca9427ba645cd646832feab822a208278e45e93e118d780b988d65397eddfd7a819526e"),
- new TestCase(
- "d74636e3413a88d85f322ca80fb0bd650bd0bf0134e2329160b69609cd58a4b0",
- "efb606aa1d9d9f0f465eaa7f8165f1ac09f5cb46fecf2a57",
- "f85471b75f6ec81abac2799ec09e98e280b2ffd64ca285e5a0109cfb31ffab2d617b2c2952a2a8a788fc0da2af7f530758f74f1ab56391ab5ff2adbcc5be2d6c7f49fbe8118104c6ff9a23c6dfe52f57954e6a69dcee5db06f514f4a0a572a9a8525d961dae72269b987189d465df6107119c7fa790853e063cba0fab7800ca932e258880fd74c33c784675bedad0e7c09e9cc4d63dd5e9713d5d4a0196e6b562226ac31b4f57c04f90a181973737ddc7e80f364112a9fbb435ebdbcabf7d490ce52",
- "b2b795fe6c1d4c83c1327e015a67d4465fd8e32813575cbab263e20ef05864d2dc17e0e4eb81436adfe9f638dcc1c8d78f6b0306baf938e5d2ab0b3e05e735cc6fff2d6e02e3d60484bea7c7a8e13e23197fea7b04d47d48f4a4e5944174539492800d3ef51e2ee5e4c8a0bdf050c2dd3dd74fce5e7e5c37364f7547a11480a3063b9a0a157b15b10a5a954de2731ced055aa2e2767f0891d4329c426f3808ee867bed0dc75b5922b7cfb895700fda016105a4c7b7f0bb90f029f6bbcb04ac36ac16") };
-
- public String getName()
- {
- return "XSalsa20";
- }
-
- public void performTest() throws Exception
- {
- for (int i = 0; i < TEST_CASES.length; i++)
- {
- performTest(i, TEST_CASES[i]);
- }
- }
-
- private void performTest(int number, TestCase testCase)
- {
- final byte[] plaintext = testCase.getPlaintext();
- byte[] output = new byte[plaintext.length];
-
- XSalsa20Engine engine = new XSalsa20Engine();
- engine.init(false, new ParametersWithIV(new KeyParameter(testCase.getKey()), testCase.getIv()));
-
- engine.processBytes(testCase.getPlaintext(), 0, testCase.getPlaintext().length, output, 0);
-
- if (!Arrays.areEqual(testCase.getCiphertext(), output))
- {
- fail("mismatch on " + number, new String(Hex.encode(testCase.getCiphertext())),
- new String(Hex.encode(output)));
- }
- }
-
- public static void main(String[] args)
- {
- runTest(new XSalsa20Test());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/XTEATest.java b/core/src/test/java/org/bouncycastle/crypto/test/XTEATest.java
deleted file mode 100644
index 2b5279e9..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/XTEATest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.crypto.engines.XTEAEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * TEA tester - based on C implementation results from http://www.simonshepherd.supanet.com/tea.htm
- */
-public class XTEATest
- extends CipherTest
-{
- static SimpleTest[] tests = {
- new BlockCipherVectorTest(0, new XTEAEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000")),
- "0000000000000000",
- "dee9d4d8f7131ed9"),
- new BlockCipherVectorTest(1, new XTEAEngine(),
- new KeyParameter(Hex.decode("00000000000000000000000000000000")),
- "0102030405060708",
- "065c1b8975c6a816"),
- new BlockCipherVectorTest(2, new XTEAEngine(),
- new KeyParameter(Hex.decode("0123456712345678234567893456789A")),
- "0000000000000000",
- "1ff9a0261ac64264"),
- new BlockCipherVectorTest(3, new XTEAEngine(),
- new KeyParameter(Hex.decode("0123456712345678234567893456789A")),
- "0102030405060708",
- "8c67155b2ef91ead"),
- };
-
- XTEATest()
- {
- super(tests, new XTEAEngine(), new KeyParameter(new byte[16]));
- }
-
- public String getName()
- {
- return "XTEA";
- }
-
- public static void main(
- String[] args)
- {
- runTest(new XTEATest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/cavp/CAVPListener.java b/core/src/test/java/org/bouncycastle/crypto/test/cavp/CAVPListener.java
deleted file mode 100644
index 81f86e57..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/cavp/CAVPListener.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.bouncycastle.crypto.test.cavp;
-
-import java.util.Properties;
-
-public interface CAVPListener
-{
- public void setup();
-
- public void receiveStart(String name);
-
- public void receiveCAVPVectors(String name, Properties config, Properties vectors);
-
- public void receiveCommentLine(String commentLine);
-
- public void receiveEnd();
-
- public void tearDown();
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/cavp/CAVPReader.java b/core/src/test/java/org/bouncycastle/crypto/test/cavp/CAVPReader.java
deleted file mode 100644
index 9cd33afc..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/cavp/CAVPReader.java
+++ /dev/null
@@ -1,152 +0,0 @@
-package org.bouncycastle.crypto.test.cavp;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.util.Properties;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.SHA224Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.digests.SHA384Digest;
-import org.bouncycastle.crypto.digests.SHA512Digest;
-import org.bouncycastle.crypto.engines.AESFastEngine;
-import org.bouncycastle.crypto.engines.DESedeEngine;
-import org.bouncycastle.crypto.macs.CMac;
-import org.bouncycastle.crypto.macs.HMac;
-
-public class CAVPReader
-{
-
- private static final Pattern COMMENT_PATTERN = Pattern.compile("^\\s*\\#\\s*(.*)$");
- private static final Pattern CONFIG_PATTERN = Pattern.compile("^\\s*+\\[\\s*+(.*?)\\s*+=\\s*+(.*?)\\s*+\\]\\s*+$");
- private static final Pattern VECTOR_PATTERN = Pattern.compile("^\\s*+(.*?)\\s*+=\\s*+(.*?)\\s*+$");
- private static final Pattern EMPTY_PATTERN = Pattern.compile("^\\s*+$");
- static final Pattern PATTERN_FOR_R = Pattern.compile("(\\d+)_BITS");
- private final CAVPListener listener;
- private String name;
- private BufferedReader lineReader;
-
-
- public CAVPReader(CAVPListener listener)
- {
- this.listener = listener;
- }
-
- public void setInput(String name, Reader reader)
- {
- this.name = name;
- this.lineReader = new BufferedReader(reader);
- }
-
- public void readAll()
- throws IOException
- {
-
- listener.setup();
-
- Properties config = new Properties();
-
- boolean startNewVector = true;
-
- Properties vectors = new Properties();
-
- while (true)
- {
- final String line = lineReader.readLine();
- if (line == null)
- {
- listener.receiveEnd();
- break;
- }
-
- final Matcher commentMatcher = COMMENT_PATTERN.matcher(line);
- if (commentMatcher.matches())
- {
- listener.receiveCommentLine(commentMatcher.group(1));
- continue;
- }
-
- final Matcher configMatcher = CONFIG_PATTERN.matcher(line);
- if (configMatcher.matches())
- {
- config.put(configMatcher.group(1), configMatcher.group(2));
- continue;
- }
-
- final Matcher vectorMatcher = VECTOR_PATTERN.matcher(line);
- if (vectorMatcher.matches())
- {
- vectors.put(vectorMatcher.group(1), vectorMatcher.group(2));
- startNewVector = false;
- continue;
- }
-
- final Matcher emptyMatcher = EMPTY_PATTERN.matcher(line);
- if (emptyMatcher.matches())
- {
- if (startNewVector)
- {
- continue;
- }
-
- listener.receiveCAVPVectors(name, config, vectors);
- vectors = new Properties();
- startNewVector = true;
- }
- }
-
- listener.tearDown();
- }
-
- static Mac createPRF(Properties config)
- {
- final Mac prf;
- if (config.getProperty("PRF").matches("CMAC_AES\\d\\d\\d"))
- {
- BlockCipher blockCipher = new AESFastEngine();
- prf = new CMac(blockCipher);
- }
- else if (config.getProperty("PRF").matches("CMAC_TDES\\d"))
- {
- BlockCipher blockCipher = new DESedeEngine();
- prf = new CMac(blockCipher);
- }
- else if (config.getProperty("PRF").matches("HMAC_SHA1"))
- {
- Digest digest = new SHA1Digest();
- prf = new HMac(digest);
- }
- else if (config.getProperty("PRF").matches("HMAC_SHA224"))
- {
- Digest digest = new SHA224Digest();
- prf = new HMac(digest);
- }
- else if (config.getProperty("PRF").matches("HMAC_SHA256"))
- {
- Digest digest = new SHA256Digest();
- prf = new HMac(digest);
- }
- else if (config.getProperty("PRF").matches("HMAC_SHA384"))
- {
- Digest digest = new SHA384Digest();
- prf = new HMac(digest);
- }
- else if (config.getProperty("PRF").matches("HMAC_SHA512"))
- {
- Digest digest = new SHA512Digest();
- prf = new HMac(digest);
- }
- else
- {
- throw new IllegalStateException("Unknown Mac for PRF");
- }
- return prf;
- }
-
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/cavp/KDFCounterTests.java b/core/src/test/java/org/bouncycastle/crypto/test/cavp/KDFCounterTests.java
deleted file mode 100644
index 81f10824..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/cavp/KDFCounterTests.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package org.bouncycastle.crypto.test.cavp;
-
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.Properties;
-import java.util.regex.Matcher;
-
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.generators.KDFCounterBytesGenerator;
-import org.bouncycastle.crypto.params.KDFCounterParameters;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.TestFailedException;
-
-public final class KDFCounterTests
- implements CAVPListener
-{
- private PrintWriter out;
-
- public void receiveCAVPVectors(String name, Properties config,
- Properties vectors)
- {
-
- // create Mac based PRF from PRF property, create the KDF
- final Mac prf = CAVPReader.createPRF(config);
- final KDFCounterBytesGenerator gen = new KDFCounterBytesGenerator(prf);
-
-
- Matcher matcherForR = CAVPReader.PATTERN_FOR_R.matcher(config.getProperty("RLEN"));
- if (!matcherForR.matches())
- {
- throw new IllegalStateException("RLEN value should always match");
- }
- final int r = Integer.parseInt(matcherForR.group(1));
-
- final int count = Integer.parseInt(vectors.getProperty("COUNT"));
- final int l = Integer.parseInt(vectors.getProperty("L"));
- final byte[] ki = Hex.decode(vectors.getProperty("KI"));
-
- //Three variants of this KDF are possible, with the counter before the fixed data, after the fixed data, or in the middle of the fixed data.
- if (config.getProperty("CTRLOCATION").matches("BEFORE_FIXED"))
- {
- final byte[] fixedInputData = Hex.decode(vectors.getProperty("FixedInputData"));
- final KDFCounterParameters params = new KDFCounterParameters(ki, null, fixedInputData, r);
- gen.init(params);
- }
- else if (config.getProperty("CTRLOCATION").matches("AFTER_FIXED"))
- {
- final byte[] fixedInputData = Hex.decode(vectors.getProperty("FixedInputData"));
- final KDFCounterParameters params = new KDFCounterParameters(ki, fixedInputData, null, r);
- gen.init(params);
- }
- else if (config.getProperty("CTRLOCATION").matches("MIDDLE_FIXED"))
- {
- final byte[] DataBeforeCtrData = Hex.decode(vectors.getProperty("DataBeforeCtrData"));
- final byte[] DataAfterCtrData = Hex.decode(vectors.getProperty("DataAfterCtrData"));
- final KDFCounterParameters params = new KDFCounterParameters(ki, DataBeforeCtrData, DataAfterCtrData, r);
- gen.init(params);
- }
- else
- {
- return; // Unknown CTRLOCATION
- }
-
-
- final byte[] koGenerated = new byte[l / 8];
- gen.generateBytes(koGenerated, 0, koGenerated.length);
-
- final byte[] koVectors = Hex.decode(vectors.getProperty("KO"));
-
- compareKO(name, config, count, koGenerated, koVectors);
- }
-
- private static void compareKO(
- String name, Properties config, int test, byte[] calculatedOKM, byte[] testOKM)
- {
-
- if (!Arrays.areEqual(calculatedOKM, testOKM))
- {
- throw new TestFailedException(new SimpleTestResult(
- false, name + " using " + config + " test " + test + " failed"));
-
- }
- }
-
- public void receiveCommentLine(String commentLine)
- {
- // out.println("# " + commentLine);
- }
-
- public void receiveStart(String name)
- {
- // do nothing
- }
-
- public void receiveEnd()
- {
- out.println(" *** *** *** ");
- }
-
- public void setup()
- {
- try
- {
- out = new PrintWriter(new FileWriter("KDFCTR.gen"));
- }
- catch (IOException e)
- {
- throw new IllegalStateException(e);
- }
- }
-
- public void tearDown()
- {
- out.close();
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/cavp/KDFDoublePipelineCounterTests.java b/core/src/test/java/org/bouncycastle/crypto/test/cavp/KDFDoublePipelineCounterTests.java
deleted file mode 100644
index 5b3df023..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/cavp/KDFDoublePipelineCounterTests.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package org.bouncycastle.crypto.test.cavp;
-
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.Properties;
-import java.util.regex.Matcher;
-
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.generators.KDFDoublePipelineIterationBytesGenerator;
-import org.bouncycastle.crypto.params.KDFDoublePipelineIterationParameters;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.TestFailedException;
-
-public final class KDFDoublePipelineCounterTests
- implements CAVPListener
-{
- private PrintWriter out;
-
- public void receiveCAVPVectors(String name, Properties config,
- Properties vectors)
- {
- // out.println(" === " + name + " === ");
- // out.println(" --- config --- ");
- // out.println(config);
- // out.println(" --- vectors --- ");
- // out.println(vectors);
-
- // always skip AFTER_FIXED
- if (!config.getProperty("CTRLOCATION").matches("AFTER_ITER"))
- {
- return;
- }
-
- // create Mac based PRF from PRF property, create the KDF
- final Mac prf = CAVPReader.createPRF(config);
- final KDFDoublePipelineIterationBytesGenerator gen = new KDFDoublePipelineIterationBytesGenerator(prf);
-
-
- Matcher matcherForR = CAVPReader.PATTERN_FOR_R.matcher(config.getProperty("RLEN"));
- if (!matcherForR.matches())
- {
- throw new IllegalStateException("RLEN value should always match");
- }
- final int r = Integer.parseInt(matcherForR.group(1));
-
- final int count = Integer.parseInt(vectors.getProperty("COUNT"));
- final int l = Integer.parseInt(vectors.getProperty("L"));
- final byte[] ki = Hex.decode(vectors.getProperty("KI"));
- final byte[] fixedInputData = Hex.decode(vectors.getProperty("FixedInputData"));
- final KDFDoublePipelineIterationParameters params = KDFDoublePipelineIterationParameters.createWithCounter(ki, fixedInputData, r);
- gen.init(params);
-
- final byte[] koGenerated = new byte[l / 8];
- gen.generateBytes(koGenerated, 0, koGenerated.length);
-
- final byte[] koVectors = Hex.decode(vectors.getProperty("KO"));
-
- compareKO(name, config, count, koGenerated, koVectors);
- }
-
- private static void compareKO(
- String name, Properties config, int test, byte[] calculatedOKM, byte[] testOKM)
- {
-
- if (!Arrays.areEqual(calculatedOKM, testOKM))
- {
- throw new TestFailedException(new SimpleTestResult(
- false, name + " using " + config + " test " + test + " failed"));
-
- }
- }
-
- public void receiveCommentLine(String commentLine)
- {
- // out.println("# " + commentLine);
- }
-
- public void receiveStart(String name)
- {
- // do nothing
- }
-
- public void receiveEnd()
- {
- out.println(" *** *** *** ");
- }
-
- public void setup()
- {
- try
- {
- out = new PrintWriter(new FileWriter("KDFDblPipelineCounter.gen"));
- }
- catch (IOException e)
- {
- throw new IllegalStateException(e);
- }
- }
-
- public void tearDown()
- {
- out.close();
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/cavp/KDFDoublePipelineIterationNoCounterTests.java b/core/src/test/java/org/bouncycastle/crypto/test/cavp/KDFDoublePipelineIterationNoCounterTests.java
deleted file mode 100644
index 3923f9a1..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/cavp/KDFDoublePipelineIterationNoCounterTests.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package org.bouncycastle.crypto.test.cavp;
-
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.Properties;
-
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.generators.KDFDoublePipelineIterationBytesGenerator;
-import org.bouncycastle.crypto.params.KDFDoublePipelineIterationParameters;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.TestFailedException;
-
-public final class KDFDoublePipelineIterationNoCounterTests
- implements CAVPListener
-{
- private PrintWriter out;
-
- public void receiveCAVPVectors(String name, Properties config,
- Properties vectors)
- {
-
-
- // create Mac based PRF from PRF property, create the KDF
- final Mac prf = CAVPReader.createPRF(config);
- final KDFDoublePipelineIterationBytesGenerator gen = new KDFDoublePipelineIterationBytesGenerator(prf);
-
- final int count = Integer.parseInt(vectors.getProperty("COUNT"));
- final int l = Integer.parseInt(vectors.getProperty("L"));
- final byte[] ki = Hex.decode(vectors.getProperty("KI"));
- final byte[] fixedInputData = Hex.decode(vectors.getProperty("FixedInputData"));
- final KDFDoublePipelineIterationParameters params = KDFDoublePipelineIterationParameters.createWithoutCounter(ki, fixedInputData);
- gen.init(params);
-
- final byte[] koGenerated = new byte[l / 8];
- gen.generateBytes(koGenerated, 0, koGenerated.length);
-
- final byte[] koVectors = Hex.decode(vectors.getProperty("KO"));
-
- compareKO(name, config, count, koGenerated, koVectors);
- }
-
- private static void compareKO(
- String name, Properties config, int test, byte[] calculatedOKM, byte[] testOKM)
- {
-
- if (!Arrays.areEqual(calculatedOKM, testOKM))
- {
- throw new TestFailedException(new SimpleTestResult(
- false, name + " using " + config + " test " + test + " failed"));
-
- }
- }
-
- public void receiveCommentLine(String commentLine)
- {
- // out.println("# " + commentLine);
- }
-
- public void receiveStart(String name)
- {
- // do nothing
- }
-
- public void receiveEnd()
- {
- out.println(" *** *** *** ");
- }
-
- public void setup()
- {
- try
- {
- out = new PrintWriter(new FileWriter("KDFDblPipelineNoCounter.gen"));
- }
- catch (IOException e)
- {
- throw new IllegalStateException(e);
- }
- }
-
- public void tearDown()
- {
- out.close();
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/cavp/KDFFeedbackCounterTests.java b/core/src/test/java/org/bouncycastle/crypto/test/cavp/KDFFeedbackCounterTests.java
deleted file mode 100644
index 6f8a0fde..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/cavp/KDFFeedbackCounterTests.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package org.bouncycastle.crypto.test.cavp;
-
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.Properties;
-import java.util.regex.Matcher;
-
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.generators.KDFFeedbackBytesGenerator;
-import org.bouncycastle.crypto.params.KDFFeedbackParameters;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.TestFailedException;
-
-public final class KDFFeedbackCounterTests
- implements CAVPListener
-{
- private PrintWriter out;
-
- public void receiveCAVPVectors(String name, Properties config,
- Properties vectors)
- {
- // out.println(" === " + name + " === ");
- // out.println(" --- config --- ");
- // out.println(config);
- // out.println(" --- vectors --- ");
- // out.println(vectors);
-
- // always skip AFTER_FIXED
- if (!config.getProperty("CTRLOCATION").matches("AFTER_ITER"))
- {
- return;
- }
-
- // create Mac based PRF from PRF property, create the KDF
- final Mac prf = CAVPReader.createPRF(config);
- final KDFFeedbackBytesGenerator gen = new KDFFeedbackBytesGenerator(prf);
-
-
- Matcher matcherForR = CAVPReader.PATTERN_FOR_R.matcher(config.getProperty("RLEN"));
- if (!matcherForR.matches())
- {
- throw new IllegalStateException("RLEN value should always match");
- }
- final int r = Integer.parseInt(matcherForR.group(1));
-
- final int count = Integer.parseInt(vectors.getProperty("COUNT"));
- final int l = Integer.parseInt(vectors.getProperty("L"));
- final byte[] ki = Hex.decode(vectors.getProperty("KI"));
- final byte[] iv = Hex.decode(vectors.getProperty("IV"));
- final byte[] fixedInputData = Hex.decode(vectors.getProperty("FixedInputData"));
- final KDFFeedbackParameters params = KDFFeedbackParameters.createWithCounter(ki, iv, fixedInputData, r);
- gen.init(params);
-
- final byte[] koGenerated = new byte[l / 8];
- gen.generateBytes(koGenerated, 0, koGenerated.length);
-
- final byte[] koVectors = Hex.decode(vectors.getProperty("KO"));
-
- compareKO(name, config, count, koGenerated, koVectors);
- }
-
- private static void compareKO(
- String name, Properties config, int test, byte[] calculatedOKM, byte[] testOKM)
- {
-
- if (!Arrays.areEqual(calculatedOKM, testOKM))
- {
- throw new TestFailedException(new SimpleTestResult(
- false, name + " using " + config + " test " + test + " failed"));
-
- }
- }
-
- public void receiveCommentLine(String commentLine)
- {
- // out.println("# " + commentLine);
- }
-
- public void receiveStart(String name)
- {
- // do nothing
- }
-
- public void receiveEnd()
- {
- out.println(" *** *** *** ");
- }
-
- public void setup()
- {
- try
- {
- out = new PrintWriter(new FileWriter("KDFFeedbackCounter.gen"));
- }
- catch (IOException e)
- {
- throw new IllegalStateException(e);
- }
- }
-
- public void tearDown()
- {
- out.close();
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/cavp/KDFFeedbackNoCounterTests.java b/core/src/test/java/org/bouncycastle/crypto/test/cavp/KDFFeedbackNoCounterTests.java
deleted file mode 100644
index cd7d8b80..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/cavp/KDFFeedbackNoCounterTests.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package org.bouncycastle.crypto.test.cavp;
-
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.Properties;
-
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.generators.KDFFeedbackBytesGenerator;
-import org.bouncycastle.crypto.params.KDFFeedbackParameters;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTestResult;
-import org.bouncycastle.util.test.TestFailedException;
-
-public final class KDFFeedbackNoCounterTests
- implements CAVPListener
-{
- private PrintWriter out;
-
- public void receiveCAVPVectors(String name, Properties config,
- Properties vectors)
- {
-
-
- // create Mac based PRF from PRF property, create the KDF
- final Mac prf = CAVPReader.createPRF(config);
- final KDFFeedbackBytesGenerator gen = new KDFFeedbackBytesGenerator(prf);
-
- final int count = Integer.parseInt(vectors.getProperty("COUNT"));
- final int l = Integer.parseInt(vectors.getProperty("L"));
- final byte[] ki = Hex.decode(vectors.getProperty("KI"));
- final byte[] iv = Hex.decode(vectors.getProperty("IV"));
- final byte[] fixedInputData = Hex.decode(vectors.getProperty("FixedInputData"));
- final KDFFeedbackParameters params = KDFFeedbackParameters.createWithoutCounter(ki, iv, fixedInputData);
- gen.init(params);
-
- final byte[] koGenerated = new byte[l / 8];
- gen.generateBytes(koGenerated, 0, koGenerated.length);
-
- final byte[] koVectors = Hex.decode(vectors.getProperty("KO"));
-
- compareKO(name, config, count, koGenerated, koVectors);
- }
-
- private static void compareKO(
- String name, Properties config, int test, byte[] calculatedOKM, byte[] testOKM)
- {
-
- if (!Arrays.areEqual(calculatedOKM, testOKM))
- {
- throw new TestFailedException(new SimpleTestResult(
- false, name + " using " + config + " test " + test + " failed"));
-
- }
- }
-
- public void receiveCommentLine(String commentLine)
- {
-// out.println("# " + commentLine);
- }
-
- public void receiveStart(String name)
- {
- // do nothing
- }
-
- public void receiveEnd()
- {
- out.println(" *** *** *** ");
- }
-
- public void setup()
- {
- try
- {
- out = new PrintWriter(new FileWriter("KDFFeedbackNoCounter.gen"));
- }
- catch (IOException e)
- {
- throw new IllegalStateException(e);
- }
- }
-
- public void tearDown()
- {
- out.close();
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/speedy/MacThroughputTest.java b/core/src/test/java/org/bouncycastle/crypto/test/speedy/MacThroughputTest.java
deleted file mode 100644
index 8249fd18..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/speedy/MacThroughputTest.java
+++ /dev/null
@@ -1,156 +0,0 @@
-package org.bouncycastle.crypto.test.speedy;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.engines.AESFastEngine;
-import org.bouncycastle.crypto.engines.NullEngine;
-import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
-import org.bouncycastle.crypto.macs.CMac;
-import org.bouncycastle.crypto.macs.GMac;
-import org.bouncycastle.crypto.macs.HMac;
-import org.bouncycastle.crypto.macs.Poly1305;
-import org.bouncycastle.crypto.macs.SipHash;
-import org.bouncycastle.crypto.macs.SkeinMac;
-import org.bouncycastle.crypto.modes.GCMBlockCipher;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-/**
- * Microbenchmark of MACs on short, medium, long messages, with optional object creation cost.
- */
-public class MacThroughputTest
-{
-
- private static final long CLOCK_SPEED = 2400000000L;
-
- private static final SecureRandom RANDOM = new SecureRandom();
- private static Poly1305KeyGenerator kg = new Poly1305KeyGenerator();;
-
- private static final byte[] SHORT_MESSAGE = new byte[16];
- private static final byte[] MEDIUM_MESSAGE = new byte[256];
- private static final byte[] LONG_MESSAGE = new byte[8192];
- static
- {
- RANDOM.nextBytes(SHORT_MESSAGE);
- RANDOM.nextBytes(MEDIUM_MESSAGE);
- RANDOM.nextBytes(LONG_MESSAGE);
- }
-
- private static final int SHORT_MESSAGE_COUNT = 20000000;
- private static final int MEDIUM_MESSAGE_COUNT = 2200000;
- private static final int LONG_MESSAGE_COUNT = 80000;
-
- static
- {
- kg.init(new KeyGenerationParameters(RANDOM, 256));
- }
-
- private static KeyParameter generatePoly1305Key()
- {
- return new KeyParameter(kg.generateKey());
- }
-
- public static void main(String[] args)
- {
- testMac(new HMac(new SHA1Digest()), new KeyParameter(generateNonce(20)), 3);
- testMac(new SkeinMac(SkeinMac.SKEIN_512, 128), new KeyParameter(generateNonce(64)), 2);
- testMac(new SipHash(), new KeyParameter(generateNonce(16)), 1);
- testMac(new CMac(new AESFastEngine()), new KeyParameter(generateNonce(16)), 3);
- testMac(new GMac(new GCMBlockCipher(new AESFastEngine())), new ParametersWithIV(new KeyParameter(
- generateNonce(16)), generateNonce(16)), 5);
- testMac(new Poly1305(new NullEngine(16)), new ParametersWithIV(generatePoly1305Key(), generateNonce(16)), 1);
- testMac(new Poly1305(new AESFastEngine()), new ParametersWithIV(generatePoly1305Key(), generateNonce(16)), 1);
- testMac(new Poly1305Reference(new NullEngine(16)), new ParametersWithIV(generatePoly1305Key(),
- generateNonce(16)), 1);
- }
-
- private static byte[] generateNonce(int sizeBytes)
- {
- byte[] nonce = new byte[16];
- RANDOM.nextBytes(nonce);
- return nonce;
- }
-
- private static void testMac(Mac mac, CipherParameters params, int rateFactor)
- {
- System.out.println("=========================");
-
- long total = testRun(mac, params, false, MEDIUM_MESSAGE, adjust(MEDIUM_MESSAGE_COUNT, rateFactor));
- System.out.printf("%s Warmup 1 run time: %,d ms\n", mac.getAlgorithmName(), total / 1000000);
- total = testRun(mac, params, false, MEDIUM_MESSAGE, adjust(MEDIUM_MESSAGE_COUNT, rateFactor));
- System.out.printf("%s Warmup 2 run time: %,d ms\n", mac.getAlgorithmName(), total / 1000000);
- System.gc();
- try
- {
- Thread.sleep(1000);
- } catch (InterruptedException e)
- {
- }
-
- test("Short", mac, params, false, SHORT_MESSAGE, adjust(SHORT_MESSAGE_COUNT, rateFactor));
- // test("Short", mac, params, true, SHORT_MESSAGE, adjust(SHORT_MESSAGE_COUNT, rateFactor));
- test("Medium", mac, params, false, MEDIUM_MESSAGE, adjust(MEDIUM_MESSAGE_COUNT, rateFactor));
- // test("Medium", mac, params, true, MEDIUM_MESSAGE, adjust(MEDIUM_MESSAGE_COUNT,
- // rateFactor));
- test("Long", mac, params, false, LONG_MESSAGE, adjust(LONG_MESSAGE_COUNT, rateFactor));
- // test("Long", mac, params, true, LONG_MESSAGE, adjust(LONG_MESSAGE_COUNT, rateFactor));
- }
-
- private static int adjust(int iterationCount, int rateFactor)
- {
- return (int)(iterationCount * (1.0f / rateFactor));
- }
-
- private static void test(String name,
- Mac mac,
- CipherParameters params,
- boolean initPerMessage,
- byte[] message,
- int adjustedCount)
- {
- System.out.println("=========================");
- long total = testRun(mac, params, initPerMessage, message, adjustedCount);
-
- long averageRuntime = total / adjustedCount;
- System.out.printf("%s %-7s%s Total run time: %,d ms\n", mac.getAlgorithmName(), name, initPerMessage ? "*"
- : " ", total / 1000000);
- System.out.printf("%s %-7s%s Average run time: %,d ns\n", mac.getAlgorithmName(), name, initPerMessage ? "*"
- : " ", averageRuntime);
- final long mbPerSecond = (long)((double)message.length / averageRuntime * 1000000000 / (1024 * 1024));
- System.out.printf("%s %-7s%s Average speed: %,d MB/s\n", mac.getAlgorithmName(), name, initPerMessage ? "*"
- : " ", mbPerSecond);
- System.out.printf("%s %-7s%s Average speed: %,f c/b\n", mac.getAlgorithmName(), name, initPerMessage ? "*"
- : " ", CLOCK_SPEED / (double)(mbPerSecond * (1024 * 1024)));
- }
-
- private static long testRun(Mac mac,
- CipherParameters params,
- boolean initPerMessage,
- byte[] message,
- int adjustedCount)
- {
- byte[] out = new byte[mac.getMacSize()];
-
- if (!initPerMessage)
- {
- mac.init(params);
- }
- long start = System.nanoTime();
-
- for (int i = 0; i < adjustedCount; i++)
- {
- if (initPerMessage)
- {
- mac.init(params);
- }
- mac.update(message, 0, message.length);
- mac.doFinal(out, 0);
- }
- long total = System.nanoTime() - start;
- return total;
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/speedy/Poly1305Reference.java b/core/src/test/java/org/bouncycastle/crypto/test/speedy/Poly1305Reference.java
deleted file mode 100644
index c8db287a..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/speedy/Poly1305Reference.java
+++ /dev/null
@@ -1,292 +0,0 @@
-package org.bouncycastle.crypto.test.speedy;
-
-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;
-
-/**
- * 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>
- * This implementation is adapted from the public domain <a href="http://nacl.cr.yp.to/">nacl</a>
- * <code>ref</code> implementation, and is probably too slow for real usage.
- *
- * @see Poly1305KeyGenerator
- */
-public class Poly1305Reference
- implements Mac
-{
- private static final int BLOCK_SIZE = 16;
- private static final int STATE_SIZE = BLOCK_SIZE + 1;
- private static int[] minusp = {5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252};
-
- private final BlockCipher cipher;
-
- /** Encrypted nonce */
- private final byte[] encryptedNonce = new byte[BLOCK_SIZE];
-
- /** Private integer r *, expanded to 17 bytes */
- private final int[] r = new int[STATE_SIZE];
-
- /** Accumulated authenticator value */
- private final int[] h = new int[STATE_SIZE];
-
- /** Temp buffer for incorporating into authenticator */
- private final int[] c = new int[STATE_SIZE];
-
- private final byte[] singleByte = new byte[1];
-
- /** Current block of buffered input */
- private final byte[] currentBlock = new byte[BLOCK_SIZE];
-
- /** Current offset in input buffer */
- private int currentBlockOffset = 0;
-
- public Poly1305Reference(BlockCipher cipher)
- {
- if (cipher.getBlockSize() != BLOCK_SIZE)
- {
- throw new IllegalArgumentException("Poly1305 requires a 128 bit block cipher.");
- }
- this.cipher = cipher;
- }
-
- public void init(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(byte[] key, byte[] nonce)
- {
- if (nonce.length != BLOCK_SIZE)
- {
- throw new IllegalArgumentException("Poly1305 requires a 128 bit IV.");
- }
- Poly1305KeyGenerator.checkKey(key);
-
- // Expand private integer r
- for (int i = 0; i < BLOCK_SIZE; i++)
- {
- r[i] = key[BLOCK_SIZE + i] & 0xFF;
- }
- r[BLOCK_SIZE] = 0;
-
- // Calculate 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, this.encryptedNonce, 0);
- }
-
- public String getAlgorithmName()
- {
- return "Poly1305-Ref-" + cipher.getAlgorithmName();
- }
-
- public int getMacSize()
- {
- return BLOCK_SIZE;
- }
-
- public void update(byte in)
- throws IllegalStateException
- {
- singleByte[0] = in;
- update(singleByte, 0, 1);
- }
-
- public void update(byte[] in, int inOff, int len)
- throws DataLengthException,
- IllegalStateException
- {
- int copied = 0;
- while (len > copied)
- {
- if (currentBlockOffset == currentBlock.length)
- {
- processBlock();
- currentBlockOffset = 0;
- }
-
- int toCopy = Math.min((len - copied), currentBlock.length - currentBlockOffset);
- System.arraycopy(in, copied + inOff, currentBlock, currentBlockOffset, toCopy);
- copied += toCopy;
- currentBlockOffset += toCopy;
- }
-
- }
-
- /**
- * Add a full block of 16 bytes of data, padded to 17 bytes, to the MAC
- */
- private void processBlock()
- {
- for (int i = 0; i < currentBlockOffset; i++)
- {
- c[i] = currentBlock[i] & 0xFF;
- }
- c[currentBlockOffset] = 1;
- for (int i = currentBlockOffset + 1; i < c.length; i++)
- {
- c[i] = 0;
- }
- add(h, c);
- mulmod(h, r);
- }
-
- public int doFinal(byte[] out, 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();
- }
-
- freeze(h);
-
- // Add encrypted nonce to result
- for (int i = 0; i < BLOCK_SIZE; i++)
- {
- c[i] = encryptedNonce[i] & 0xFF;
- }
- c[BLOCK_SIZE] = 0;
- add(h, c);
-
- for (int i = 0; i < BLOCK_SIZE; i++)
- {
- out[outOff + i] = (byte)h[i];
- }
-
- reset();
- return BLOCK_SIZE;
- }
-
- public void reset()
- {
- currentBlockOffset = 0;
- for (int i = 0; i < h.length; i++)
- {
- h[i] = 0;
- }
- }
-
- // 130 bit math adapted from nacl ref implementation
-
- /**
- * 130 bit add with carry.
- */
- private static void add(int[] h, int[] c)
- {
- int u = 0;
- for (int j = 0; j < 17; ++j)
- {
- u += h[j] + c[j];
- h[j] = u & 255;
- u >>= 8;
- }
- }
-
- /**
- * 130 bit multiplication mod 2^130-5
- */
- private void mulmod(int[] h, int[] r)
- {
- final int[] hr = c;
-
- for (int i = 0; i < 17; ++i)
- {
- int u = 0;
- /* Basic multiply to compute term i */
- for (int j = 0; j <= i; ++j)
- {
- u += h[j] * r[i - j];
- }
-
- /*
- * Modular reduction
- *
- * Shift overflow >> 130 bits == (>> 17 bytes = 136 bits) + (<< 6 bits = * 64)
- *
- * Reduction mod 2^130-5 leaves 5x remainder, so 64 * 5 = 320.
- */
- for (int j = i + 1; j < 17; ++j)
- {
- u += 320 * h[j] * r[i + 17 - j];
- }
- hr[i] = u;
- }
- System.arraycopy(hr, 0, h, 0, h.length);
- squeeze(h);
- }
-
- /**
- * Propagate carries following a modular multiplication.
- */
- private static void squeeze(int[] h)
- {
- int u = 0;
- for (int j = 0; j < 16; ++j)
- {
- u += h[j];
- h[j] = u & 255;
- u >>= 8;
- }
- u += h[16];
- h[16] = u & 3;
- u = 5 * (u >> 2);
- for (int j = 0; j < 16; ++j)
- {
- u += h[j];
- h[j] = u & 255;
- u >>= 8;
- }
- u += h[16];
- h[16] = u;
- }
-
- /**
- * Constant time correction of h to be &lt; p (2^130 - 5).
- */
- private void freeze(int[] h)
- {
- final int[] horig = c;
- System.arraycopy(h, 0, horig, 0, h.length);
-
- add(h, minusp);
- final int negative = -(h[16] >> 7);
- for (int j = 0; j < 17; ++j)
- {
- h[j] ^= negative & (horig[j] ^ h[j]);
- }
- }
-
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/speedy/ThreefishReferenceEngine.java b/core/src/test/java/org/bouncycastle/crypto/test/speedy/ThreefishReferenceEngine.java
deleted file mode 100644
index 7dabbde0..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/speedy/ThreefishReferenceEngine.java
+++ /dev/null
@@ -1,395 +0,0 @@
-package org.bouncycastle.crypto.test.speedy;
-
-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;
-
-public class ThreefishReferenceEngine
- implements BlockCipher
-{
-
- /**
- * The tweak input is always 128 bits
- */
- private static final int TWEAK_SIZE = 16;
-
- private static long C_240 = 0x1BD11BDAA9FC1A22L;
-
- private final int blocksize = 64;
- private final int rounds = 72;
- private final int words = 8;
-
- private boolean forEncryption;
-
- private long[] block = new long[words];
-
- private int[][] rotations = R8;
-
- /**
- * Rotation constants Rd,j for Nw = 8.
- */
- private static final int[][] R8 = {
- {46, 36, 19, 37},
- {33, 27, 14, 42},
- {17, 49, 36, 39},
- {44, 9, 54, 56},
- {39, 30, 34, 24},
- {13, 50, 10, 17},
- {25, 29, 39, 43},
- {8, 35, 56, 22}};
-
- private long[] t;
-
- private long kw[];
-
- public void init(boolean forEncryption, CipherParameters params)
- throws IllegalArgumentException
- {
- if (params instanceof TweakableBlockCipherParameters)
- {
- init(forEncryption, (TweakableBlockCipherParameters)params);
- }
- else if (params instanceof KeyParameter)
- {
- init(forEncryption, new TweakableBlockCipherParameters((KeyParameter)params, new byte[TWEAK_SIZE]));
- }
- else
- {
- throw new IllegalArgumentException("Invalid parameter passed to Threefish init - "
- + params.getClass().getName());
- }
- }
-
- public void init(boolean forEncryption, TweakableBlockCipherParameters params)
- throws IllegalArgumentException
- {
- // TODO: Remove some of the NPEs that can be avoided in the Params
- // classes
- if ((params.getKey() == null) || (params.getKey().getKey() == null)
- || (params.getKey().getKey().length != blocksize))
- {
- throw new IllegalArgumentException("Threefish key must be same size as block (%d bytes)" + blocksize);
- }
-
- if ((params.getTweak() == null) || (params.getTweak().length != TWEAK_SIZE))
- {
- throw new IllegalArgumentException("Threefish tweak must be %d bytes" + TWEAK_SIZE);
- }
-
- this.forEncryption = forEncryption;
-
- generateKeySchedule(params.getKey().getKey(), params.getTweak());
- }
-
- private void generateKeySchedule(byte[] key, byte[] tweak)
- {
- // TODO: This key schedule can/should be generated incrementally/on demand during encrypt/decrypt
- // to reduce memory overhead (currently 1.2MB = (rounds/4+1)=19 * words=8 * 8 bytes/word)
-
- t = new long[3];
- t[0] = BytesToWord(tweak, 0);
- t[1] = BytesToWord(tweak, 8);
- t[2] = t[0] ^ t[1];
-
- kw = new long[words + 1];
-
- long knw = C_240;
- for (int i = 0; i < words; i++)
- {
- kw[i] = BytesToWord(key, i * 8);
- knw = knw ^ kw[i];
- }
- kw[kw.length - 1] = knw;
- }
-
- private static long BytesToWord(byte[] bytes, int off)
- {
- 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;
- }
-
- private static void WordToBytes(long word, byte[] bytes, int off)
- {
- 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);
- }
-
- public String getAlgorithmName()
- {
- return "Threefish";
- }
-
- public int getBlockSize()
- {
- return blocksize;
- }
-
- public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
- throws DataLengthException,
- IllegalStateException
- {
- // TODO: Check init state
- if (kw == null)
- {
- throw new IllegalStateException("Threefish engine not initialised");
- }
-
- if ((inOff + blocksize) > in.length)
- {
- throw new DataLengthException("Input buffer too short");
- }
-
- if ((outOff + blocksize) > out.length)
- {
- throw new DataLengthException("Output buffer too short");
- }
-
- if (forEncryption)
- {
- unpackBlock(in, inOff);
- encryptBlock();
- packBlock(out, outOff);
- }
- else
- {
- unpackBlock(in, inOff);
- decryptBlock();
- packBlock(out, outOff);
- }
-
- return blocksize;
- }
-
- private void decryptBlock()
- {
- for (int d = rounds; d > 0; d--)
- {
- // Add subkey every 4 rounds
- if ((d % 4) == 0)
- {
- uninjectSubkey(d / 4);
- }
-
- // Permute
- unpermute();
-
- // Mix
- for (int j = 0; j < words / 2; j++)
- {
- unmix(j, d - 1);
- }
- }
-
- // Remove first subkey
- uninjectSubkey(0);
- }
-
- private void injectSubkey(int s)
- {
- for (int i = 0; i < (words - 3); i++)
- {
- block[i] += kw[(s + i) % (words + 1)];
- }
- block[words - 3] += kw[(s + words - 3) % (words + 1)] + t[s % 3];
- block[words - 2] += kw[(s + words - 2) % (words + 1)] + t[(s + 1) % 3];
- block[words - 1] += kw[(s + words - 1) % (words + 1)] + s;
- }
-
- private void uninjectSubkey(int s)
- {
- for (int i = 0; i < (words - 3); i++)
- {
- block[i] -= kw[(s + i) % (words + 1)];
- }
- block[words - 3] -= kw[(s + words - 3) % (words + 1)] + t[s % 3];
- block[words - 2] -= kw[(s + words - 2) % (words + 1)] + t[(s + 1) % 3];
- block[words - 1] -= kw[(s + words - 1) % (words + 1)] + s;
- }
-
- private void encryptBlock()
- {
- for (int d = 0; d < rounds; d++)
- {
- // Add subkey every 4 rounds
- if ((d % 4) == 0)
- {
- injectSubkey(d / 4);
- }
-
- // Mix
- for (int j = 0; j < words / 2; j++)
- {
- mix(j, d);
- }
-
- // Permute
- permute();
- }
-
- // Final key addition
- injectSubkey(rounds / 4);
- }
-
- private void permute()
- {
- // Permute in place for Nw = 8
- long f0 = block[0];
- long f3 = block[3];
-
- block[0] = block[2];
- block[1] = block[1];
- block[2] = block[4];
- block[3] = block[7];
- block[4] = block[6];
- block[5] = block[5];
- block[6] = f0;
- block[7] = f3;
- }
-
- private void unpermute()
- {
- // TODO: Change these to tables
- // Permute in place for Nw = 8
- long f6 = block[6];
- long f7 = block[7];
-
- block[7] = block[3];
- block[6] = block[4];
- block[5] = block[5];
- block[4] = block[2];
- block[3] = f7;
- block[2] = block[0];
- block[1] = block[1];
- block[0] = f6;
- }
-
- private void mix(int j, int d)
- {
- // ed,2j and ed,2j+1
- int b0 = 2 * j;
- int b1 = b0 + 1;
-
- // y0 = x0 + x1
- block[b0] = block[b0] + block[b1];
-
- // y1 = (x1 <<< R(d mod 8,j)) xor y0
- block[b1] = Long.rotateLeft(block[b1], rotations[d % 8][j]) ^ block[b0];
- }
-
- private void unmix(int j, int d)
- {
- // ed,2j and ed,2j+1
- int b0 = 2 * j;
- int b1 = b0 + 1;
-
- // x1 = (y1 ^ y0) >>> R(d mod 8, j))
- block[b1] = Long.rotateRight(block[b1] ^ block[b0], rotations[d % 8][j]);
-
- // x0 = y0 - x1
- block[b0] = block[b0] - block[b1];
-
- }
-
- public static void main(String[] args)
- {
- ThreefishReferenceEngine engine = new ThreefishReferenceEngine();
- engine.fu();
- }
-
- private void fu()
- {
- block[0] = 0x12;
- block[1] = 0x34;
- block[2] = 0x56;
- block[3] = 0x78;
- block[4] = 0x90;
- block[5] = 0xAB;
- block[6] = 0xCD;
- block[7] = 0xEF;
-
- for (int i = 0; i < block.length; i++)
- {
- System.err.println(i + " : " + Long.toHexString(block[i]));
- }
- mix(0, 4);
- System.err.println("=========");
- for (int i = 0; i < block.length; i++)
- {
- System.err.println(i + " : " + Long.toHexString(block[i]));
- }
- unmix(0, 4);
- System.err.println("=========");
- for (int i = 0; i < block.length; i++)
- {
- System.err.println(i + " : " + Long.toHexString(block[i]));
- }
- permute();
- System.err.println("=========");
- for (int i = 0; i < block.length; i++)
- {
- System.err.println(i + " : " + Long.toHexString(block[i]));
- }
- unpermute();
- System.err.println("=========");
- for (int i = 0; i < block.length; i++)
- {
- System.err.println(i + " : " + Long.toHexString(block[i]));
- }
- generateKeySchedule(new byte[blocksize], new byte[TWEAK_SIZE]);
- injectSubkey(5);
- System.err.println("=========");
- for (int i = 0; i < block.length; i++)
- {
- System.err.println(i + " : " + Long.toHexString(block[i]));
- }
- uninjectSubkey(5);
- System.err.println("=========");
- for (int i = 0; i < block.length; i++)
- {
- System.err.println(i + " : " + Long.toHexString(block[i]));
- }
- }
-
- private void packBlock(byte[] out, int outOff)
- {
- for (int i = 0; i < block.length; i++)
- {
- WordToBytes(block[i], out, outOff + (i * 8));
- }
- }
-
- private long[] unpackBlock(byte[] bytes, int index)
- {
- for (int i = 0; i < block.length; i++)
- {
- block[i] = BytesToWord(bytes, index + (i * 8));
- }
- return block;
- }
-
- public void reset()
- {
- }
-
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/test/speedy/ThroughputTest.java b/core/src/test/java/org/bouncycastle/crypto/test/speedy/ThroughputTest.java
deleted file mode 100644
index 7c090f8a..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/test/speedy/ThroughputTest.java
+++ /dev/null
@@ -1,203 +0,0 @@
-package org.bouncycastle.crypto.test.speedy;
-
-import java.io.IOException;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.engines.AESFastEngine;
-import org.bouncycastle.crypto.engines.ThreefishEngine;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.TweakableBlockCipherParameters;
-import org.bouncycastle.util.encoders.Hex;
-
-public class ThroughputTest
-{
-
- private static final int DATA_SIZE = 100 * 1024 * 1024;
- private static final int RUNS = 1;
- private static final long CLOCK_SPEED = 2400000000L;
-
- private static SecureRandom rand = new SecureRandom();
-
- public static void main(String[] args)
- throws InterruptedException, IOException
- {
-// testTF_1024_1();
-// testTF_1024_2();
- testTF_512_1();
- testTF_512_2();
-// testTF_256_1();
-// testTF_256_2();
- System.out.println("Initialising test data.");
- byte[] input = new byte[DATA_SIZE];
- rand.nextBytes(input);
-
- System.out.println("Init complete.");
-// speedTestCipher(new ThreefishEngine(ThreefishEngine.BLOCKSIZE_256), input);
- speedTestCipher(new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512), input);
-// speedTestCipher(new Skein3FishEngine(), input);
-// speedTestCipher(new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024), input);
-// speedTestCipher(new ThreefishReferenceEngine(), input);
- speedTestCipher(new AESFastEngine(), input);
-// speedTestCipher(new TwofishEngine(), input);
-// speedTestCipher(new BlowfishEngine(), input);
- }
-
- private static void testTF_512_1()
- throws IOException
- {
- byte[] key = new byte[64];
- byte[] tweak = new byte[16];
- byte[] plaintext = new byte[64];
- byte[] expected = Hex.decode("b1a2bbc6ef6025bc40eb3822161f36e375d1bb0aee3186fbd19e47c5d479947b7bc2f8586e35f0cff7e7f03084b0b7b1f1ab3961a580a3e97eb41ea14a6d7bbe");
-
- runTestVector("Threefish-512-1: Fast", key, tweak, plaintext, expected, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512));
- runTestVector("Threefish-512-1: Reference", key, tweak, plaintext, expected, new ThreefishReferenceEngine());
- }
-
- private static void testTF_256_1()
- throws IOException
- {
- byte[] key = new byte[32];
- byte[] tweak = new byte[16];
- byte[] plaintext = new byte[32];
- byte[] expected = Hex.decode("84da2a1f8beaee947066ae3e3103f1ad536db1f4a1192495116b9f3ce6133fd8");
-
- runTestVector("Threefish-256-1: ", key, tweak, plaintext, expected, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_256));
- }
-
- private static void testTF_1024_1()
- throws IOException
- {
- byte[] key = new byte[128];
- byte[] tweak = new byte[16];
- byte[] plaintext = new byte[128];
- byte[] expected = Hex.decode("f05c3d0a3d05b304f785ddc7d1e036015c8aa76e2f217b06c6e1544c0bc1a90df0accb9473c24e0fd54fea68057f43329cb454761d6df5cf7b2e9b3614fbd5a20b2e4760b40603540d82eabc5482c171c832afbe68406bc39500367a592943fa9a5b4a43286ca3c4cf46104b443143d560a4b230488311df4feef7e1dfe8391e");
-
- runTestVector("Threefish-1024-1: ", key, tweak, plaintext, expected, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024));
- }
-
- private static void runTestVector(String name, byte[] key, byte[] tweak, byte[] plaintext, byte[] expected, BlockCipher cipher)
- {
- System.out.println("====");
- System.out.println(name + ": ");
- cipher.init(true, new TweakableBlockCipherParameters(new KeyParameter(key), tweak));
-
- byte[] ciphertext = new byte[key.length];
- cipher.processBlock(plaintext, 0, ciphertext, 0);
-
- System.out.println("Plaintext : " + new String(Hex.encode(plaintext)));
- System.out.println("Expected : " + new String(Hex.encode(expected)));
- System.out.println("Ciphertext : " + new String(Hex.encode(ciphertext)));
- System.out.println(" Encrypt : " + org.bouncycastle.util.Arrays.areEqual(expected, ciphertext));
-
- cipher.init(false, new TweakableBlockCipherParameters(new KeyParameter(key), tweak));
- byte[] replain = new byte[plaintext.length];
- cipher.processBlock(ciphertext, 0, replain, 0);
-
- System.out.println("Replain : " + new String(Hex.encode(replain)));
- System.out.println(" Decrypt : " + org.bouncycastle.util.Arrays.areEqual(plaintext, replain));
- }
-
- private static void testTF_512_2()
- throws IOException
- {
- byte[] key = Hex.decode("101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f");
- byte[] tweak = Hex.decode("000102030405060708090a0b0c0d0e0f");
- byte[] plaintext = Hex.decode("fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0");
- byte[] expected = Hex.decode("e304439626d45a2cb401cad8d636249a6338330eb06d45dd8b36b90e97254779272a0a8d99463504784420ea18c9a725af11dffea10162348927673d5c1caf3d");
-
- runTestVector("Threefish-512-2: Fast", key, tweak, plaintext, expected, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512));
- runTestVector("Threefish-512-2: Reference", key, tweak, plaintext, expected, new ThreefishReferenceEngine());
- }
-
- private static void testTF_256_2()
- throws IOException
- {
- byte[] key = Hex.decode("101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f");
- byte[] tweak = Hex.decode("000102030405060708090a0b0c0d0e0f");
- byte[] plaintext = Hex.decode("FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0");
- byte[] expected = Hex.decode("e0d091ff0eea8fdfc98192e62ed80ad59d865d08588df476657056b5955e97df");
-
- runTestVector("Threefish-256-2: ", key, tweak, plaintext, expected, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_256));
- }
-
- private static void testTF_1024_2()
- throws IOException
- {
- byte[] key = Hex.decode("101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f");
- byte[] tweak = Hex.decode("000102030405060708090a0b0c0d0e0f");
- byte[] plaintext = Hex.decode("fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0afaeadacabaaa9a8a7a6a5a4a3a2a1a09f9e9d9c9b9a999897969594939291908f8e8d8c8b8a89888786858483828180");
- byte[] expected = Hex.decode("a6654ddbd73cc3b05dd777105aa849bce49372eaaffc5568d254771bab85531c94f780e7ffaae430d5d8af8c70eebbe1760f3b42b737a89cb363490d670314bd8aa41ee63c2e1f45fbd477922f8360b388d6125ea6c7af0ad7056d01796e90c83313f4150a5716b30ed5f569288ae974ce2b4347926fce57de44512177dd7cde");
-
- runTestVector("Threefish-1024-2: ", key, tweak, plaintext, expected, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024));
- }
-
- private static void speedTestCipher(BlockCipher cipher, byte[] input)
- throws InterruptedException
- {
- byte[] key = new byte[cipher.getBlockSize()];
- rand.nextBytes(key);
-
- cipher.init(true, new KeyParameter(key));
- speedTestCipherForMode("encrypt", cipher, input);
- cipher.init(false, new KeyParameter(key));
- speedTestCipherForMode("decrypt", cipher, input);
- }
-
- private static void speedTestCipherForMode(String mode, BlockCipher cipher, byte[] input)
- throws InterruptedException
- {
- System.out.println("======");
- System.out.println("Testing " + cipher.getAlgorithmName() + " " + cipher.getBlockSize() * 8 + " " + mode);
- System.out.println("Beginning warmup run.");
-
- long warmup = testCipher(cipher, input);
- System.out.println("Warmup run 1 in " + (warmup / 1000000) + "ms");
- Thread.sleep(100);
- warmup = testCipher(cipher, input);
- System.out.println("Warmup run 2 in " + (warmup / 1000000) + "ms");
-
- System.gc();
- Thread.sleep(500);
- System.gc();
- Thread.sleep(500);
-
- System.out.println("Beginning " + RUNS + " hot runs.");
-
- long[] runtimes = new long[RUNS];
- long total = 0;
- for (int i = 0; i < RUNS; i++)
- {
- runtimes[i] = testCipher(cipher, input);
- total += runtimes[i];
- System.out.println("Run " + (i + 1) + ": " + runtimes[i] / 100000 + "ms");
- }
- long averageRuntime = total / RUNS;
- System.out.println(cipher.getAlgorithmName() + " Average run time: " + averageRuntime / 1000000 + "ms");
- final long mbPerSecond = (long)((double)DATA_SIZE / averageRuntime * 1000000000 / (1024 * 1024));
- System.out.println(cipher.getAlgorithmName() + " Average speed: " + mbPerSecond + " MB/s");
- System.out.println(cipher.getAlgorithmName() + " Average speed: " + CLOCK_SPEED / (double)(mbPerSecond * (1024 * 1024)) + " c/b");
- }
-
- private static long testCipher(BlockCipher cipher, byte[] input)
- {
- long start = System.nanoTime();
- int blockSize = cipher.getBlockSize();
- byte[] out = new byte[blockSize];
-
- for (int i = 0; i < (input.length - blockSize); i += blockSize)
- {
- cipher.processBlock(input, i, out, 0);
-// byte[] test = new byte[blockSize];
-// System.arraycopy(input, i, test, 0, test.length);
-// if (!Arrays.equals(out, test)) {
-// System.err.println(":(");
-// }
- }
-
- long end = System.nanoTime();
- long delta = end - start;
- return delta;
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/AllTests.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/AllTests.java
deleted file mode 100644
index ef5b29bc..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/AllTests.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-public class AllTests
-{
- public static void main(String[] args)
- throws Exception
- {
- junit.textui.TestRunner.run(suite());
- }
-
- public static Test suite()
- throws Exception
- {
- TestSuite suite = new TestSuite("TLS tests");
-
- suite.addTest(BasicTlsTest.suite());
-
- return suite;
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/BasicTlsTest.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/BasicTlsTest.java
deleted file mode 100644
index 7be21ed4..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/BasicTlsTest.java
+++ /dev/null
@@ -1,200 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.net.Socket;
-
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-import org.bouncycastle.crypto.tls.AlertDescription;
-import org.bouncycastle.crypto.tls.AlertLevel;
-import org.bouncycastle.crypto.tls.AlwaysValidVerifyer;
-import org.bouncycastle.crypto.tls.Certificate;
-import org.bouncycastle.crypto.tls.CipherSuite;
-import org.bouncycastle.crypto.tls.DefaultTlsClient;
-import org.bouncycastle.crypto.tls.LegacyTlsClient;
-import org.bouncycastle.crypto.tls.TlsAuthentication;
-import org.bouncycastle.crypto.tls.TlsClient;
-import org.bouncycastle.crypto.tls.TlsClientProtocol;
-import org.bouncycastle.crypto.tls.TlsFatalAlert;
-import org.bouncycastle.crypto.tls.TlsKeyExchange;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-
-public class BasicTlsTest
- extends TestCase
-{
- private static final int PORT_NO = 8003;
-
- // private static final String CLIENT = "client";
- // private static final char[] CLIENT_PASSWORD = "clientPassword".toCharArray();
- // private static final char[] SERVER_PASSWORD = "serverPassword".toCharArray();
- // private static final char[] TRUST_STORE_PASSWORD = "trustPassword".toCharArray();
-
- public void testConnection()
- throws Exception
- {
- String vmVersion = System.getProperty("java.specification.version");
-
- if (vmVersion == null || !vmVersion.equals("1.7"))
- {
- return; // only works on later VMs.
- }
-
- Thread server = new HTTPSServerThread();
-
- server.start();
-
- Thread.yield();
-
- AlwaysValidVerifyer verifyer = new AlwaysValidVerifyer();
- Socket s = null;
-
- for (int i = 0; s == null && i != 3; i++)
- {
- Thread.sleep(1000);
-
- try
- {
- s = new Socket("localhost", PORT_NO);
- }
- catch (IOException e)
- {
- // ignore
- }
- }
-
- if (s == null)
- {
- throw new IOException("unable to connect");
- }
-
- // long time = System.currentTimeMillis();
- TlsClientProtocol protocol = new TlsClientProtocol(s.getInputStream(), s.getOutputStream());
- protocol.connect(new LegacyTlsClient(verifyer));
- InputStream is = protocol.getInputStream();
- OutputStream os = protocol.getOutputStream();
-
- os.write("GET / HTTP/1.1\r\n\r\n".getBytes());
-
- // time = System.currentTimeMillis();
- byte[] buf = new byte[4096];
- int read = 0;
- int total = 0;
-
- while ((read = is.read(buf, total, buf.length - total)) > 0)
- {
- total += read;
- }
-
- is.close();
-
- byte[] expected = Hex.decode("485454502f312e3120323030204f4b0d0a436f6e74656e742d547970653a20746578742f68"
- + "746d6c0d0a0d0a3c68746d6c3e0d0a3c626f64793e0d0a48656c6c6f20576f726c64210d0a3c2f626f64793e0d0a3c2f"
- + "68746d6c3e0d0a");
- assertEquals(total, expected.length);
-
- byte[] tmp = new byte[expected.length];
- System.arraycopy(buf, 0, tmp, 0, total);
- assertTrue(Arrays.areEqual(expected, tmp));
- }
-
- public void testRSAConnectionClient()
- throws Exception
- {
- MyTlsClient client = new MyTlsClient(null);
-
- checkConnectionClient(client, CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA, TlsTestUtils.rsaCertData);
- checkConnectionClient(client, CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, TlsTestUtils.rsaCertData);
- checkConnectionClient(client, CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA, TlsTestUtils.rsaCertData);
- checkConnectionClient(client, CipherSuite.TLS_RSA_WITH_RC4_128_SHA, TlsTestUtils.rsaCertData);
-
- try
- {
- checkConnectionClient(client, CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA, TlsTestUtils.dudRsaCertData);
-
- fail("dud certificate not caught");
- }
- catch (TlsFatalAlert e)
- {
- assertEquals(AlertDescription.certificate_unknown, e.getAlertDescription());
- }
-
- try
- {
- checkConnectionClient(client, CipherSuite.TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA, TlsTestUtils.rsaCertData);
-
- fail("wrong certificate not caught");
- }
- catch (TlsFatalAlert e)
- {
- assertEquals(AlertDescription.internal_error, e.getAlertDescription());
- }
- }
-
- private void checkConnectionClient(TlsClient client, int cipherSuite, byte[] encCert)
- throws Exception
- {
- client.notifySelectedCipherSuite(cipherSuite);
-
- TlsKeyExchange keyExchange = client.getKeyExchange();
-
- keyExchange
- .processServerCertificate(new Certificate(
- new org.bouncycastle.asn1.x509.Certificate[]{org.bouncycastle.asn1.x509.Certificate
- .getInstance(encCert)}));
- }
-
- public static TestSuite suite()
- {
- return new TestSuite(BasicTlsTest.class);
- }
-
- public static void main(String[] args)
- throws Exception
- {
- junit.textui.TestRunner.run(suite());
- }
-
- static class MyTlsClient
- extends DefaultTlsClient
- {
-
- public void notifyAlertRaised(short alertLevel, short alertDescription, String message, Exception cause)
- {
- PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
- out.println("TLS client raised alert (AlertLevel." + alertLevel + ", AlertDescription." + alertDescription
- + ")");
- if (message != null)
- {
- out.println(message);
- }
- if (cause != null)
- {
- cause.printStackTrace(out);
- }
- }
-
- public void notifyAlertReceived(short alertLevel, short alertDescription)
- {
- PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
- out.println("TLS client received alert (AlertLevel." + alertLevel + ", AlertDescription."
- + alertDescription + ")");
- }
-
- private final TlsAuthentication authentication;
-
- MyTlsClient(TlsAuthentication authentication)
- {
- this.authentication = authentication;
- }
-
- public TlsAuthentication getAuthentication()
- throws IOException
- {
- return authentication;
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/DTLSClientTest.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/DTLSClientTest.java
deleted file mode 100644
index ada1a2e5..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/DTLSClientTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import java.io.IOException;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.tls.DTLSClientProtocol;
-import org.bouncycastle.crypto.tls.DTLSTransport;
-import org.bouncycastle.crypto.tls.DatagramTransport;
-import org.bouncycastle.crypto.tls.TlsClient;
-import org.bouncycastle.crypto.tls.TlsSession;
-import org.bouncycastle.crypto.tls.UDPTransport;
-
-/**
- * A simple test designed to conduct a DTLS handshake with an external DTLS server.
- * <p/>
- * Please refer to GnuTLSSetup.txt or OpenSSLSetup.txt, and x509-*.pem files in this package for
- * help configuring an external DTLS server.
- */
-public class DTLSClientTest
-{
- private static final SecureRandom secureRandom = new SecureRandom();
-
- public static void main(String[] args)
- throws Exception
- {
- InetAddress address = InetAddress.getLocalHost();
- int port = 5556;
-
- TlsSession session = createSession(address, port);
-
- MockDTLSClient client = new MockDTLSClient(session);
-
- DTLSTransport dtls = openDTLSConnection(address, port, client);
-
- System.out.println("Receive limit: " + dtls.getReceiveLimit());
- System.out.println("Send limit: " + dtls.getSendLimit());
-
- // Send and hopefully receive a packet back
-
- byte[] request = "Hello World!\n".getBytes("UTF-8");
- dtls.send(request, 0, request.length);
-
- byte[] response = new byte[dtls.getReceiveLimit()];
- int received = dtls.receive(response, 0, response.length, 30000);
- if (received >= 0)
- {
- System.out.println(new String(response, 0, received, "UTF-8"));
- }
-
- dtls.close();
- }
-
- private static TlsSession createSession(InetAddress address, int port)
- throws IOException
- {
- MockDTLSClient client = new MockDTLSClient(null);
- DTLSTransport dtls = openDTLSConnection(address, port, client);
- TlsSession session = client.getSessionToResume();
- dtls.close();
- return session;
- }
-
- private static DTLSTransport openDTLSConnection(InetAddress address, int port, TlsClient client)
- throws IOException
- {
- DatagramSocket socket = new DatagramSocket();
- socket.connect(address, port);
-
- int mtu = 1500;
- DatagramTransport transport = new UDPTransport(socket, mtu);
- transport = new UnreliableDatagramTransport(transport, secureRandom, 0, 0);
- transport = new LoggingDatagramTransport(transport, System.out);
-
- DTLSClientProtocol protocol = new DTLSClientProtocol(secureRandom);
-
- return protocol.connect(client, transport);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/DTLSProtocolTest.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/DTLSProtocolTest.java
deleted file mode 100644
index df5a3f87..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/DTLSProtocolTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import java.security.SecureRandom;
-
-import junit.framework.TestCase;
-
-import org.bouncycastle.crypto.tls.DTLSClientProtocol;
-import org.bouncycastle.crypto.tls.DTLSServerProtocol;
-import org.bouncycastle.crypto.tls.DTLSTransport;
-import org.bouncycastle.crypto.tls.DatagramTransport;
-import org.bouncycastle.util.Arrays;
-
-public class DTLSProtocolTest
- extends TestCase
-{
- public void testClientServer()
- throws Exception
- {
- SecureRandom secureRandom = new SecureRandom();
-
- DTLSClientProtocol clientProtocol = new DTLSClientProtocol(secureRandom);
- DTLSServerProtocol serverProtocol = new DTLSServerProtocol(secureRandom);
-
- MockDatagramAssociation network = new MockDatagramAssociation(1500);
-
- ServerThread serverThread = new ServerThread(serverProtocol, network.getServer());
- serverThread.start();
-
- DatagramTransport clientTransport = network.getClient();
-
- clientTransport = new UnreliableDatagramTransport(clientTransport, secureRandom, 0, 0);
-
- clientTransport = new LoggingDatagramTransport(clientTransport, System.out);
-
- MockDTLSClient client = new MockDTLSClient(null);
-
- DTLSTransport dtlsClient = clientProtocol.connect(client, clientTransport);
-
- for (int i = 1; i <= 10; ++i)
- {
- byte[] data = new byte[i];
- Arrays.fill(data, (byte)i);
- dtlsClient.send(data, 0, data.length);
- }
-
- byte[] buf = new byte[dtlsClient.getReceiveLimit()];
- while (dtlsClient.receive(buf, 0, buf.length, 100) >= 0)
- {
- }
-
- dtlsClient.close();
-
- serverThread.shutdown();
- }
-
- static class ServerThread
- extends Thread
- {
- private final DTLSServerProtocol serverProtocol;
- private final DatagramTransport serverTransport;
- private volatile boolean isShutdown = false;
-
- ServerThread(DTLSServerProtocol serverProtocol, DatagramTransport serverTransport)
- {
- this.serverProtocol = serverProtocol;
- this.serverTransport = serverTransport;
- }
-
- public void run()
- {
- try
- {
- MockDTLSServer server = new MockDTLSServer();
- DTLSTransport dtlsServer = serverProtocol.accept(server, serverTransport);
- byte[] buf = new byte[dtlsServer.getReceiveLimit()];
- while (!isShutdown)
- {
- int length = dtlsServer.receive(buf, 0, buf.length, 1000);
- if (length >= 0)
- {
- dtlsServer.send(buf, 0, length);
- }
- }
- dtlsServer.close();
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- }
-
- void shutdown()
- throws InterruptedException
- {
- if (!isShutdown)
- {
- isShutdown = true;
- this.join();
- }
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/DTLSServerTest.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/DTLSServerTest.java
deleted file mode 100644
index 5f6c09b0..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/DTLSServerTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import java.net.DatagramPacket;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.net.SocketTimeoutException;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.tls.DTLSServerProtocol;
-import org.bouncycastle.crypto.tls.DTLSTransport;
-import org.bouncycastle.crypto.tls.DatagramTransport;
-import org.bouncycastle.crypto.tls.UDPTransport;
-
-/**
- * A simple test designed to conduct a DTLS handshake with an external DTLS client.
- * <p/>
- * Please refer to GnuTLSSetup.txt or OpenSSLSetup.txt, and x509-*.pem files in this package for
- * help configuring an external DTLS client.
- */
-public class DTLSServerTest
-{
- public static void main(String[] args)
- throws Exception
- {
- InetAddress address = InetAddress.getLocalHost();
- int port = 5556;
-
- int mtu = 1500;
-
- SecureRandom secureRandom = new SecureRandom();
-
- DTLSServerProtocol serverProtocol = new DTLSServerProtocol(secureRandom);
-
- byte[] data = new byte[mtu];
- DatagramPacket packet = new DatagramPacket(data, mtu);
-
- DatagramSocket socket = new DatagramSocket(port, address);
- socket.receive(packet);
-
- System.out.println("Accepting connection from " + packet.getAddress().getHostAddress() + ":" + port);
- socket.connect(packet.getAddress(), packet.getPort());
-
- /*
- * NOTE: For simplicity, and since we don't yet have HelloVerifyRequest support, we just
- * discard the initial packet, which the client should re-send anyway.
- */
-
- DatagramTransport transport = new UDPTransport(socket, mtu);
-
- // Uncomment to see packets
-// transport = new LoggingDatagramTransport(transport, System.out);
-
- MockDTLSServer server = new MockDTLSServer();
- DTLSTransport dtlsServer = serverProtocol.accept(server, transport);
-
- byte[] buf = new byte[dtlsServer.getReceiveLimit()];
-
- while (!socket.isClosed())
- {
- try
- {
- int length = dtlsServer.receive(buf, 0, buf.length, 60000);
- if (length >= 0)
- {
- System.out.write(buf, 0, length);
- dtlsServer.send(buf, 0, length);
- }
- }
- catch (SocketTimeoutException ste)
- {
- }
- }
-
- dtlsServer.close();
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/DTLSTestCase.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/DTLSTestCase.java
deleted file mode 100644
index 65482a77..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/DTLSTestCase.java
+++ /dev/null
@@ -1,248 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import java.security.SecureRandom;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import org.bouncycastle.crypto.tls.DTLSClientProtocol;
-import org.bouncycastle.crypto.tls.DTLSServerProtocol;
-import org.bouncycastle.crypto.tls.DTLSTransport;
-import org.bouncycastle.crypto.tls.DatagramTransport;
-import org.bouncycastle.crypto.tls.ProtocolVersion;
-import org.bouncycastle.util.Arrays;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-
-import static org.junit.Assert.*;
-
-@RunWith(Parameterized.class)
-public class DTLSTestCase
-{
- // Make the access to constants less verbose
- static abstract class C extends TlsTestConfig {}
-
- @Parameterized.Parameters(name = "{index}: {1}")
- public static Collection<Object[]> data() {
- List<Object[]> params = new ArrayList<Object[]>();
- addVersionTests(params, ProtocolVersion.DTLSv10);
- addVersionTests(params, ProtocolVersion.DTLSv12);
- return params;
- }
-
- private static void addVersionTests(List<Object[]> params, ProtocolVersion version)
- {
- String prefix = version.toString().replaceAll("[ \\.]", "") + "_";
-
- /*
- * NOTE: Temporarily disabled automatic test runs because of problems getting a clean exit
- * of the DTLS server after a fatal alert. As of writing, manual runs show the correct
- * alerts being raised
- */
-
-// {
-// TlsTestConfig c = createDTLSTestConfig(version);
-// c.clientAuth = C.CLIENT_AUTH_INVALID_VERIFY;
-// c.expectServerFatalAlert(AlertDescription.decrypt_error);
-//
-// testSuite.addTest(new DTLSTestCase(c, prefix + "BadCertificateVerify"));
-// }
-//
-// {
-// TlsTestConfig c = createDTLSTestConfig(version);
-// c.clientAuth = C.CLIENT_AUTH_INVALID_CERT;
-// c.expectServerFatalAlert(AlertDescription.bad_certificate);
-//
-// testSuite.addTest(new DTLSTestCase(c, prefix + "BadClientCertificate"));
-// }
-//
-// {
-// TlsTestConfig c = createDTLSTestConfig(version);
-// c.clientAuth = C.CLIENT_AUTH_NONE;
-// c.serverCertReq = C.SERVER_CERT_REQ_MANDATORY;
-// c.expectServerFatalAlert(AlertDescription.handshake_failure);
-//
-// testSuite.addTest(new DTLSTestCase(c, prefix + "BadMandatoryCertReqDeclined"));
-// }
-
- {
- TlsTestConfig c = createDTLSTestConfig(version);
-
- params.add(new Object[] { c, prefix + "GoodDefault" });
- }
-
- {
- TlsTestConfig c = createDTLSTestConfig(version);
- c.serverCertReq = C.SERVER_CERT_REQ_NONE;
-
- params.add(new Object[]{ c, prefix + "GoodNoCertReq"});
- }
-
- {
- TlsTestConfig c = createDTLSTestConfig(version);
- c.clientAuth = C.CLIENT_AUTH_NONE;
-
- params.add(new Object[]{ c, prefix + "GoodOptionalCertReqDeclined"});
- }
- }
-
- private static TlsTestConfig createDTLSTestConfig(ProtocolVersion version)
- {
- TlsTestConfig c = new TlsTestConfig();
- c.clientMinimumVersion = ProtocolVersion.DTLSv10;
- /*
- * TODO We'd like to just set the offer version to DTLSv12, but there is a known issue with
- * overly-restrictive version checks b/w BC DTLS 1.2 client, BC DTLS 1.0 server
- */
- c.clientOfferVersion = version;
- c.serverMaximumVersion = version;
- c.serverMinimumVersion = ProtocolVersion.DTLSv10;
- return c;
- }
-
- private static void checkDTLSVersion(ProtocolVersion version)
- {
- if (version != null && !version.isDTLS())
- {
- throw new IllegalStateException("Non-DTLS version");
- }
- }
-
- protected final TlsTestConfig config;
-
- public DTLSTestCase(TlsTestConfig config, String name)
- {
- checkDTLSVersion(config.clientMinimumVersion);
- checkDTLSVersion(config.clientOfferVersion);
- checkDTLSVersion(config.serverMaximumVersion);
- checkDTLSVersion(config.serverMinimumVersion);
-
- this.config = config;
- }
-
- @Test
- public void runTest() throws Throwable
- {
- SecureRandom secureRandom = new SecureRandom();
-
- DTLSClientProtocol clientProtocol = new DTLSClientProtocol(secureRandom);
- DTLSServerProtocol serverProtocol = new DTLSServerProtocol(secureRandom);
-
- MockDatagramAssociation network = new MockDatagramAssociation(1500);
-
- TlsTestClientImpl clientImpl = new TlsTestClientImpl(config);
- TlsTestServerImpl serverImpl = new TlsTestServerImpl(config);
-
- ServerThread serverThread = new ServerThread(serverProtocol, network.getServer(), serverImpl);
- serverThread.start();
-
- Exception caught = null;
- try
- {
- DatagramTransport clientTransport = network.getClient();
-
- if (TlsTestConfig.DEBUG)
- {
- clientTransport = new LoggingDatagramTransport(clientTransport, System.out);
- }
-
- DTLSTransport dtlsClient = clientProtocol.connect(clientImpl, clientTransport);
-
- for (int i = 1; i <= 10; ++i)
- {
- byte[] data = new byte[i];
- Arrays.fill(data, (byte)i);
- dtlsClient.send(data, 0, data.length);
- }
-
- byte[] buf = new byte[dtlsClient.getReceiveLimit()];
- while (dtlsClient.receive(buf, 0, buf.length, 100) >= 0)
- {
- }
-
- dtlsClient.close();
- }
- catch (Exception e)
- {
- caught = e;
- logException(caught);
- }
-
- serverThread.shutdown();
-
- // TODO Add checks that the various streams were closed
-
- assertEquals("Client fatal alert connection end", config.expectFatalAlertConnectionEnd, clientImpl.firstFatalAlertConnectionEnd);
- assertEquals("Server fatal alert connection end", config.expectFatalAlertConnectionEnd, serverImpl.firstFatalAlertConnectionEnd);
-
- assertEquals("Client fatal alert description", config.expectFatalAlertDescription, clientImpl.firstFatalAlertDescription);
- assertEquals("Server fatal alert description", config.expectFatalAlertDescription, serverImpl.firstFatalAlertDescription);
-
- if (config.expectFatalAlertConnectionEnd == -1)
- {
- assertNull("Unexpected client exception", caught);
- assertNull("Unexpected server exception", serverThread.caught);
- }
- }
-
- protected void logException(Exception e)
- {
- if (TlsTestConfig.DEBUG)
- {
- e.printStackTrace();
- }
- }
-
- class ServerThread
- extends Thread
- {
- private final DTLSServerProtocol serverProtocol;
- private final DatagramTransport serverTransport;
- private final TlsTestServerImpl serverImpl;
-
- private volatile boolean isShutdown = false;
- Exception caught = null;
-
- ServerThread(DTLSServerProtocol serverProtocol, DatagramTransport serverTransport, TlsTestServerImpl serverImpl)
- {
- this.serverProtocol = serverProtocol;
- this.serverTransport = serverTransport;
- this.serverImpl = serverImpl;
- }
-
- public void run()
- {
- try
- {
- DTLSTransport dtlsServer = serverProtocol.accept(serverImpl, serverTransport);
- byte[] buf = new byte[dtlsServer.getReceiveLimit()];
- while (!isShutdown)
- {
- int length = dtlsServer.receive(buf, 0, buf.length, 100);
- if (length >= 0)
- {
- dtlsServer.send(buf, 0, length);
- }
- }
- dtlsServer.close();
- }
- catch (Exception e)
- {
- caught = e;
- logException(caught);
- }
- }
-
- void shutdown()
- throws InterruptedException
- {
- if (!isShutdown)
- {
- isShutdown = true;
- this.interrupt();
- this.join();
- }
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/HTTPSServerThread.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/HTTPSServerThread.java
deleted file mode 100644
index d55bc737..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/HTTPSServerThread.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.security.KeyStore;
-
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLServerSocket;
-import javax.net.ssl.SSLServerSocketFactory;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.TrustManagerFactory;
-
-public class HTTPSServerThread
- extends Thread
-{
- private static final int PORT_NO = 8003;
- private static final char[] SERVER_PASSWORD = "serverPassword".toCharArray();
- private static final char[] TRUST_STORE_PASSWORD = "trustPassword".toCharArray();
-
- /**
- * Read a HTTP request
- */
- private void readRequest(
- InputStream in)
- throws IOException
- {
- int ch = 0;
- int lastCh = 0;
- while ((ch = in.read()) >= 0 && (ch != '\n' && lastCh != '\n'))
- {
- if (ch != '\r')
- {
- lastCh = ch;
- }
- }
- }
-
- /**
- * Send a response
- */
- private void sendResponse(
- OutputStream out)
- {
- PrintWriter pWrt = new PrintWriter(new OutputStreamWriter(out));
- pWrt.print("HTTP/1.1 200 OK\r\n");
- pWrt.print("Content-Type: text/html\r\n");
- pWrt.print("\r\n");
- pWrt.print("<html>\r\n");
- pWrt.print("<body>\r\n");
- pWrt.print("Hello World!\r\n");
- pWrt.print("</body>\r\n");
- pWrt.print("</html>\r\n");
- pWrt.flush();
- }
-
- SSLContext createSSLContext()
- throws Exception
- {
- KeyManagerFactory mgrFact = KeyManagerFactory.getInstance("SunX509");
- KeyStore serverStore = KeyStore.getInstance("JKS");
-
- serverStore.load(new ByteArrayInputStream(KeyStores.server), SERVER_PASSWORD);
-
- mgrFact.init(serverStore, SERVER_PASSWORD);
-
- // set up a trust manager so we can recognize the server
- TrustManagerFactory trustFact = TrustManagerFactory.getInstance("SunX509");
- KeyStore trustStore = KeyStore.getInstance("JKS");
-
- trustStore.load(new ByteArrayInputStream(KeyStores.trustStore), TRUST_STORE_PASSWORD);
-
- trustFact.init(trustStore);
-
- // create a context and set up a socket factory
- SSLContext sslContext = SSLContext.getInstance("TLS");
-
- sslContext.init(mgrFact.getKeyManagers(), trustFact.getTrustManagers(), null);
-
- return sslContext;
- }
-
- public void run()
- {
- try
- {
- SSLContext sslContext = createSSLContext();
- SSLServerSocketFactory fact = sslContext.getServerSocketFactory();
-
- SSLServerSocket sSock = (SSLServerSocket)fact.createServerSocket(PORT_NO);
- SSLSocket sslSock = (SSLSocket)sSock.accept();
-
- sslSock.startHandshake();
-
- readRequest(sslSock.getInputStream());
-
- SSLSession session = sslSock.getSession();
-
- sendResponse(sslSock.getOutputStream());
-
- sslSock.close();
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/KeyStores.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/KeyStores.java
deleted file mode 100644
index bf71f965..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/KeyStores.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import org.bouncycastle.util.encoders.Base64;
-
-public class KeyStores
-{
- static final byte[] trustStore = Base64.decode(
- "/u3+7QAAAAIAAAABAAAAAgAGc2VydmVyAAABD34zDJEABVguNTA5AAABrzCC"
- + "AaswggEUAgEBMA0GCSqGSIb3DQEBBQUAMB4xHDAaBgNVBAMTE1Rlc3QgQ0Eg"
- + "Q2VydGlmaWNhdGUwHhcNMDYxMjEzMjM0MzI5WhcNMDYxMjIwMjM0MzI5WjAe"
- + "MRwwGgYDVQQDExNUZXN0IENBIENlcnRpZmljYXRlMIGfMA0GCSqGSIb3DQEB"
- + "AQUAA4GNADCBiQKBgQCmOumCM46ehsdcrZMw6tj0hMl5D0xf21gcyBj/ByIv"
- + "pe008ukaN3zCXIUUUlAu0GkbI1sCbTD1V4qVZuaHqtfa/FINJjyZJy5w7KEx"
- + "93OOF2/gyPlnEPGs6RPdThAPliSBsWKBKqtOdmKpwYn/NKuUNFRkFXVLLUPn"
- + "jyEKjIcNywIDAQABMA0GCSqGSIb3DQEBBQUAA4GBACi8J7raYqDFjXqAXXPJ"
- + "ljZHqvzJNVaSWvBtK/oY7g0+sdGIjPR526fhSCxOZRr7G157ERqMnPjuFjcm"
- + "cRlUOPsQtTl6KbUnxmKxa04UzDuNXzSx2oyGx5GCWx9u62hpO6vSpK69L9gH"
- + "OUtM5dQXcoK4i3olScKaU8qaYb0mBAy8fnx5pen8B0bIg+pz47l5VxQ5NO8=");
-
- static final byte[] server = Base64.decode(
- "/u3+7QAAAAIAAAABAAAAAQAGc2VydmVyAAABD34zDJIAAAK8MIICuDAOBgor"
- + "BgEEASoCEQEBBQAEggKk9OXWj3aBr6rV9Grcsm2YL+/2ShVsxbJVGMSWll1f"
- + "U8z/mjhv5K/skgleTIMoyE5FzDDxJIGEmSMCkcHsnseXzxyhLpKBaz3N1Tk7"
- + "KVPzXfrNh0FJwzw3lPWyC2ayT+ObQfAtzuI9SUWNLBzzpWeolUJ8gkXnLshX"
- + "5RqmR735NRZdjgQOtNYBBErX/NOhTyi009/CZDNxgJQzywFmQcXBLhNSA+0i"
- + "cE+LwZ4sZV0NXshPZiyNnsfqN/XNOyhpKr8a3VyVtee2nhO9+FY5IDEviHmR"
- + "WDvH5TmB6Os3L6xvwE1ZQCPElk/cK2G1q9+zDBe4JDeo8o7lPhiNpVfcivnr"
- + "+tyK9m7PqlssR0+ohuZGwrFMyzLugkOWh+qZ3pk8/7AwJosMvvTvIg36nN7R"
- + "pdnouQNKqTm1Sr/UUnKyWqfG7zqKIuF72IkDwwafwuQ9YRX5PAOuRfo6bCyb"
- + "D4w1OWdfGFciKMc1BrT+8JzhiTkzNe+jWEA5Tw1zeazPGpp1RHPz2np50G2s"
- + "v025uiOSUilBe13Qpx0mAyx7z8Gl6eOxai6rQ/eB/Fu++BMx0OX8vO/K4//Q"
- + "w43IPVPklGlb/3Qt7eoNf4tichuxrYJjHu4XbwnzB29Vmsan0XZFER7epvFj"
- + "cAZCSG+O6G/f6Ib+7d7xYjLdUaPI60tJ4/C+AuYwZn4jJwTnMnMmwIypz4Z8"
- + "XPXW5SbHlV5OkkFC+eAuuN4b2YXZmifeWv4fx65Ioir921LMJrorMizH41RJ"
- + "/rAO5wGSwjeDJ784QhhLGbEUMygraRtdaz6MRx26InnoHY7V58ET3Z5YGV39"
- + "p+9AtVhYw/QQmTZiF7hqnEMf9AMVFfac9qFF2+IN3g9HAMC6QLxJ1VuPn5oo"
- + "lS//axPfjckO7iZx9x59/gAAAAEABVguNTA5AAABrzCCAaswggEUAgEBMA0G"
- + "CSqGSIb3DQEBBQUAMB4xHDAaBgNVBAMTE1Rlc3QgQ0EgQ2VydGlmaWNhdGUw"
- + "HhcNMDYxMjEzMjM0MzI5WhcNMDYxMjIwMjM0MzI5WjAeMRwwGgYDVQQDExNU"
- + "ZXN0IENBIENlcnRpZmljYXRlMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB"
- + "gQCmOumCM46ehsdcrZMw6tj0hMl5D0xf21gcyBj/ByIvpe008ukaN3zCXIUU"
- + "UlAu0GkbI1sCbTD1V4qVZuaHqtfa/FINJjyZJy5w7KEx93OOF2/gyPlnEPGs"
- + "6RPdThAPliSBsWKBKqtOdmKpwYn/NKuUNFRkFXVLLUPnjyEKjIcNywIDAQAB"
- + "MA0GCSqGSIb3DQEBBQUAA4GBACi8J7raYqDFjXqAXXPJljZHqvzJNVaSWvBt"
- + "K/oY7g0+sdGIjPR526fhSCxOZRr7G157ERqMnPjuFjcmcRlUOPsQtTl6KbUn"
- + "xmKxa04UzDuNXzSx2oyGx5GCWx9u62hpO6vSpK69L9gHOUtM5dQXcoK4i3ol"
- + "ScKaU8qaYb0mBAy87VQaPfaiQqqxSgqifbSowlg+0fg=");
-
- static final byte[] client = Base64.decode(
- "MIACAQMwgAYJKoZIhvcNAQcBoIAkgASCA+gwgDCABgkqhkiG9w0BBwGggCSA"
- + "BIIDDzCCAwswggMHBgsqhkiG9w0BDAoBAqCCArIwggKuMCgGCiqGSIb3DQEM"
- + "AQMwGgQUyeN8U+ViAJCk1WGo8wTnRVOaE1oCAgQABIICgH3yMWB+dfMBNa07"
- + "hn3smUSBTF+LUauM+kx+12nZt0QazBYg09yM+aVcTznettlDwE/PTpKZnrFT"
- + "22DSQf5GwABwiL6KW+xyM8wV5vZx1xtqrQoNf2oNHnF0lB7ddSYM8jHqennb"
- + "bzcVOdrrCqewqAfUU/CDugpwwI8c8Iy9ECri6vBMbfeIIZQTug+1952TCCiA"
- + "E1bEDFGqgAoDsqYi6uNtpjmL/DPX/qmkbHAXUKxOtjTtxacfat2HgN97Gb7z"
- + "+ZBNI5aaCSRoYwl+K9biWGID3EqsNmg0+2ELmFhE4mQZ78i7vNLTG7e5mj6v"
- + "Qt+QuqN+daCbVqVTKxsFpODRRweobUTRxwEun6p0p3w3SUhR6p7ug1Jttgyu"
- + "vfZug3PIk2j9fb26wAs2ZreVYut8hXpp/09ulCUudtlsYb/FD+H11v/JyopG"
- + "2vYy0hL/gkMr41sGoVdyvzXeZUa7A1wYask+g7torad9sT8CPb3zXBd0kU2r"
- + "lbSJIXQ8wTpheeUKe47YF9JVCF8WRc1dokD7fgfn6197pwyZpDEVrVyz1pUq"
- + "jyum3ctONU4BSkAUVr9pTyeRFUeOE7SLuVu+c67PzNWXEc/HMVD4Hgs/idVc"
- + "mrONk3xe385wFJK1iPe1kfRX5OXk9UWr2/yjgrahbkonWhJHnIlvs+b5rRKN"
- + "qauwUZ+agMJV98Eyc2Lz0Lp/pNDRNjmGXeJLzAaAy46STov8sxwAgj3bQ7xu"
- + "uEzdhJPDynAY5sWd3WnBY2ZhpawnToEKnD4u+eiH2MjUL2q/R2IPSmoyg9i2"
- + "Ictgh4/ylrhm+lJDzcDrLDhC0m/t9EdhytH4erk/uCPcmAK/jpzFn6ltxcsx"
- + "QjAbBgkqhkiG9w0BCRQxDh4MAGMAbABpAGUAbgB0MCMGCSqGSIb3DQEJFTEW"
- + "BBS2wDxw7yH2OhKIgkDoQrTlavLvxQAAAAAAADCABgkqhkiG9w0BBwaggDCA"
- + "AgEAMIAGCSqGSIb3DQEHATAoBgoqhkiG9w0BDAEGMBoEFORdyeTIG2oXDQBl"
- + "I3aFNozDAkC2AgIEAKCABIIHICsc3D8rxLiDlegyXFfIejto66RW4u6b+d0C"
- + "uAAz0G+dIvhQ9g3s++vUsX7x+icO/vjpgdo09aqtIg7T3suzfcHtU8CGSgtQ"
- + "Tvml25LDC3IK3qI6cRqO+sCdvg18aS04IDKvDPYH4ca5btwPBIID6CStk/jY"
- + "QFpnSI6VNz9IERi/nwuvuBYk+A0Z7+nQdhF+QkW1rzN+uz0dkNJt6ZbG5lEK"
- + "GayV+FDTQcREMihYa716RN9sq3cm0jXXdttj998oS/QrpZDEcPqd4AM6EIL+"
- + "PTA1tEQYxXa8msAPp+tLvXOtiD6v/4FO77EA7E5oR36a9en+M1QQasFU3VBf"
- + "V9os92QlbtVUTkspJV9gXL6s4CGNptc7lUH+nIw65j9MOoyOU9w1qjPRlN/Z"
- + "MTuhFooglE6TPd29Udwufqp+hHkW/7z5tBKkhGlZEClzD3IWhcF9NVraE/IV"
- + "S5qVmx2Up7SeLZAXJ+AAznq5IXwE1dOUTkwYLcIrH1FuVA5rtOkB8Xt1LJq0"
- + "ERkjJ5MfpxTxbKXp5PejzD98v54+s4INekcrI0jzz4pLsann7ex0r6CPsQsH"
- + "+F3rBVaT3oHSKqoIm2Nw57oDjLLp5lP2qcCqps3y2dcVzu5NIzCSkVlxUaBK"
- + "IT3xv0gvVJI7wnP0QM35MCywKkToJX5ajQKrDc4iCAAzmxaQzdBycxJPYByq"
- + "VHvH7BJldJlMw5NHbTHlNoYKndMdAsHp7sUqERkDEGl80R86TlB4nJaDrfsx"
- + "vL+KluiCY9AD7o+MEYZ9VYoNDUzVGH4pTr4wnv1UFoRWix5IZuDnnYkyijKD"
- + "VtU5+mc0YtsPQIpKCBJOYt05bgpX5aPQ3s2lviYw3bvP0TrclYs/rx4wKVgW"
- + "2GYLzPh0OVMBduCbzW1E58ieBsgRyQ7+2MTl9Nj+nznjCAfLSvrVEcwxVUQA"
- + "ofcEbiECEJss2JNQq8erwgo8dP3atwQ1KeqMc8acICcOrI2rNxwVOLzPuCsl"
- + "l8gwZOoxLZXuKMQbQu4as1HNS309dfWIWppvc3K4nDWg51HUCPbsIo3wm3rR"
- + "igc/W3bf4Ppg0pLAS5c1s0Xau43u9GmIjGiDqYaasfcXnCKy2LNuUpbhoOC1"
- + "o/wMC9gT45aJQ5vsVGe5XvfhLV7Y815EdI756s9PIEOnG8HbAtCAjOIVpQfP"
- + "eF8+cnZyGGdsbmu7lYzg3whCpZ/L2RrTI86nEn5eePs4m2hDV0Oi9r6e2CIf"
- + "nGUa0TB9jf1OMhOSBD+h4jx7b6uT+XLmG8qUxvkoItMDZLrJ0f8czO5MyOZa"
- + "nEJoG42Fy2p7zD/qO72OUQISNmt8C1rQFsg9dBDib4DMu69vBsVrIV028sal"
- + "+tq1UH3vFMbEYyVfPH3WDgxyHwUQK2qrz3WBdD/BMyuAV4DPI3SPTweROh8n"
- + "yWJN1ppY9qybmTyHFCs6TRjPB9cVcdKSc0qYxgzblJiXXb3s9ANOb89aA3Ah"
- + "anWnAhcEggLZN2yFCtrRuvJXvDQhj8qmye9UkjB2fEpWXV7H0natE3hSoB+C"
- + "2krt3eBV0xJ1tLEco7T4zsbQQJRmeu/essOsfwpRfE5ZPoIeThf+UmWTsfsw"
- + "r4fxeePMTy6iCnkF5/ro8k5WKnOsaV+HWy/ulwW2r/DMT3aDBWfHX5Hk8DpU"
- + "+PlQhbyGTSTIJ/OFmbcWjMPt469o7+KrrF9IBrzJ42KzMw6xtKwtVb0232AM"
- + "pIwnLzCHIiNO2qDBZAIDdF68+GU3RsEkHfR6d5myZVxnH4mhSCFFtHxgqTOz"
- + "Ouo/uvgu72miZ0OFAy1zcMtfGMS3Md54MJkhSZq4ZgUo/EyJCeEDLGn8pMF1"
- + "jX1WsUj96qMRyc+p2KnKs6ZL95BVa76SdIFz6ts6uoIem3drTXYJHNbw29OW"
- + "Y0am+FmXTWFZFnin8Qu5Xct5l7FYIGA9VLOHL9Vtp+SXomcFEZpjMaxvtf4R"
- + "xoAI2Bc9Ka+MNiz35O0JXhI9/t5uOdiN6ZOJlfpEWOK7ou5lDkZuDcrHvLvQ"
- + "PocP2Yemd36xEgjFssR/tFITlhRBXHDeHwpvmXM4iiwD1wOGMqybXx/1g1m1"
- + "0UBbKqDsgSLQC7c0TaRFJjj71T74PBMiapiQgijv9WINfmTgxNUukbK3Kqp/"
- + "G3BmThoIDCB8WD1kxXBpaG62dSsih7yhPQJVEV3Y0tdkdChOk+Y3Wf8crV/Q"
- + "P08pQH7H9yCi04S5fSJtIDtYARWhr1yl8EQMnu2X8J6r/DWcDmXUK4Bv1vqe"
- + "tcnT5EAYFPeOMz21nonM3kJgUMNsxCQjKaEMEcUu8ZRnGUAFdG4lULPJn5NQ"
- + "LTvWg8Y3GrHRLjpnd9k+8gWWzRIbBiwCwEbClMZffRd6kcA5ZoOhVngdyvvj"
- + "BhkgadB5jC+ZRzExHxoEhzPJx3mxIVTqLuw7QxHz9OTcysvY/cGKCvmgzgk/"
- + "TjTJsqcEAAAAAAAAAAAAAAAAAAAAAAAAMD0wITAJBgUrDgMCGgUABBQWfGA6"
- + "lI+TXQiuXaa1V+LlHodhXAQUAwMIAAUvBYY+a7sXNlQeVEPAGkMCAgQAAAA=");
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/LoggingDatagramTransport.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/LoggingDatagramTransport.java
deleted file mode 100644
index 41816193..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/LoggingDatagramTransport.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import java.io.IOException;
-import java.io.PrintStream;
-
-import org.bouncycastle.crypto.tls.DatagramTransport;
-
-public class LoggingDatagramTransport
- implements DatagramTransport
-{
-
- private static final String HEX_CHARS = "0123456789ABCDEF";
-
- private final DatagramTransport transport;
- private final PrintStream output;
- private final long launchTimestamp;
-
- public LoggingDatagramTransport(DatagramTransport transport, PrintStream output)
- {
- this.transport = transport;
- this.output = output;
- this.launchTimestamp = System.currentTimeMillis();
- }
-
- public int getReceiveLimit()
- throws IOException
- {
- return transport.getReceiveLimit();
- }
-
- public int getSendLimit()
- throws IOException
- {
- return transport.getSendLimit();
- }
-
- public int receive(byte[] buf, int off, int len, int waitMillis)
- throws IOException
- {
- int length = transport.receive(buf, off, len, waitMillis);
- if (length >= 0)
- {
- dumpDatagram("Received", buf, off, length);
- }
- return length;
- }
-
- public void send(byte[] buf, int off, int len)
- throws IOException
- {
- dumpDatagram("Sending", buf, off, len);
- transport.send(buf, off, len);
- }
-
- public void close()
- throws IOException
- {
- }
-
- private void dumpDatagram(String verb, byte[] buf, int off, int len)
- throws IOException
- {
- long timestamp = System.currentTimeMillis() - launchTimestamp;
- StringBuffer sb = new StringBuffer("(+" + timestamp + "ms) " + verb + " " + len + " byte datagram:");
- for (int pos = 0; pos < len; ++pos)
- {
- if (pos % 16 == 0)
- {
- sb.append(System.getProperty("line.separator"));
- sb.append(" ");
- }
- else if (pos % 16 == 8)
- {
- sb.append('-');
- }
- else
- {
- sb.append(' ');
- }
- int val = buf[off + pos] & 0xFF;
- sb.append(HEX_CHARS.charAt(val >> 4));
- sb.append(HEX_CHARS.charAt(val & 0xF));
- }
- dump(sb.toString());
- }
-
- private synchronized void dump(String s)
- {
- output.println(s);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/MockDTLSClient.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/MockDTLSClient.java
deleted file mode 100644
index 5aba7f89..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/MockDTLSClient.java
+++ /dev/null
@@ -1,177 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.x509.Certificate;
-import org.bouncycastle.crypto.tls.AlertLevel;
-import org.bouncycastle.crypto.tls.CertificateRequest;
-import org.bouncycastle.crypto.tls.ClientCertificateType;
-import org.bouncycastle.crypto.tls.DefaultTlsClient;
-import org.bouncycastle.crypto.tls.MaxFragmentLength;
-import org.bouncycastle.crypto.tls.ProtocolVersion;
-import org.bouncycastle.crypto.tls.SignatureAlgorithm;
-import org.bouncycastle.crypto.tls.SignatureAndHashAlgorithm;
-import org.bouncycastle.crypto.tls.TlsAuthentication;
-import org.bouncycastle.crypto.tls.TlsCredentials;
-import org.bouncycastle.crypto.tls.TlsExtensionsUtils;
-import org.bouncycastle.crypto.tls.TlsSession;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-
-public class MockDTLSClient
- extends DefaultTlsClient
-{
- protected TlsSession session;
-
- public MockDTLSClient(TlsSession session)
- {
- this.session = session;
- }
-
- public TlsSession getSessionToResume()
- {
- return this.session;
- }
-
- public void notifyAlertRaised(short alertLevel, short alertDescription, String message, Exception cause)
- {
- PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
- out.println("DTLS client raised alert (AlertLevel." + alertLevel + ", AlertDescription." + alertDescription
- + ")");
- if (message != null)
- {
- out.println(message);
- }
- if (cause != null)
- {
- cause.printStackTrace(out);
- }
- }
-
- public void notifyAlertReceived(short alertLevel, short alertDescription)
- {
- PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
- out.println("DTLS client received alert (AlertLevel." + alertLevel + ", AlertDescription." + alertDescription
- + ")");
- }
-
- public ProtocolVersion getClientVersion()
- {
- return ProtocolVersion.DTLSv12;
- }
-
- public ProtocolVersion getMinimumVersion()
- {
- return ProtocolVersion.DTLSv10;
- }
-
-// public int[] getCipherSuites()
-// {
-// return Arrays.concatenate(super.getCipherSuites(),
-// new int[]
-// {
-// CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
-// CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1,
-// CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1,
-// CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1,
-// CipherSuite.TLS_RSA_WITH_SALSA20_SHA1,
-// });
-// }
-
- public Hashtable getClientExtensions() throws IOException
- {
- Hashtable clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(super.getClientExtensions());
- TlsExtensionsUtils.addEncryptThenMACExtension(clientExtensions);
- TlsExtensionsUtils.addMaxFragmentLengthExtension(clientExtensions, MaxFragmentLength.pow2_9);
- TlsExtensionsUtils.addTruncatedHMacExtension(clientExtensions);
- return clientExtensions;
- }
-
- public void notifyServerVersion(ProtocolVersion serverVersion) throws IOException
- {
- super.notifyServerVersion(serverVersion);
-
- System.out.println("Negotiated " + serverVersion);
- }
-
- public TlsAuthentication getAuthentication()
- throws IOException
- {
- return new TlsAuthentication()
- {
- public void notifyServerCertificate(org.bouncycastle.crypto.tls.Certificate serverCertificate)
- throws IOException
- {
- Certificate[] chain = serverCertificate.getCertificateList();
- System.out.println("Received server certificate chain of length " + chain.length);
- for (int i = 0; i != chain.length; i++)
- {
- Certificate entry = chain[i];
- // TODO Create fingerprint based on certificate signature algorithm digest
- System.out.println(" fingerprint:SHA-256 " + TlsTestUtils.fingerprint(entry) + " ("
- + entry.getSubject() + ")");
- }
- }
-
- public TlsCredentials getClientCredentials(CertificateRequest certificateRequest)
- throws IOException
- {
- short[] certificateTypes = certificateRequest.getCertificateTypes();
- if (certificateTypes == null || !Arrays.contains(certificateTypes, ClientCertificateType.rsa_sign))
- {
- return null;
- }
-
- SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
- Vector sigAlgs = certificateRequest.getSupportedSignatureAlgorithms();
- if (sigAlgs != null)
- {
- for (int i = 0; i < sigAlgs.size(); ++i)
- {
- SignatureAndHashAlgorithm sigAlg = (SignatureAndHashAlgorithm)
- sigAlgs.elementAt(i);
- if (sigAlg.getSignature() == SignatureAlgorithm.rsa)
- {
- signatureAndHashAlgorithm = sigAlg;
- break;
- }
- }
-
- if (signatureAndHashAlgorithm == null)
- {
- return null;
- }
- }
-
- return TlsTestUtils.loadSignerCredentials(context, new String[] { "x509-client.pem", "x509-ca.pem" },
- "x509-client-key.pem", signatureAndHashAlgorithm);
- }
- };
- }
-
- public void notifyHandshakeComplete() throws IOException
- {
- super.notifyHandshakeComplete();
-
- TlsSession newSession = context.getResumableSession();
- if (newSession != null)
- {
- byte[] newSessionID = newSession.getSessionID();
- String hex = Hex.toHexString(newSessionID);
-
- if (this.session != null && Arrays.areEqual(this.session.getSessionID(), newSessionID))
- {
- System.out.println("Resumed session: " + hex);
- }
- else
- {
- System.out.println("Established session: " + hex);
- }
-
- this.session = newSession;
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/MockDTLSServer.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/MockDTLSServer.java
deleted file mode 100644
index abd5d731..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/MockDTLSServer.java
+++ /dev/null
@@ -1,148 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.x509.Certificate;
-import org.bouncycastle.crypto.tls.AlertLevel;
-import org.bouncycastle.crypto.tls.CertificateRequest;
-import org.bouncycastle.crypto.tls.CipherSuite;
-import org.bouncycastle.crypto.tls.ClientCertificateType;
-import org.bouncycastle.crypto.tls.DefaultTlsServer;
-import org.bouncycastle.crypto.tls.HashAlgorithm;
-import org.bouncycastle.crypto.tls.ProtocolVersion;
-import org.bouncycastle.crypto.tls.SignatureAlgorithm;
-import org.bouncycastle.crypto.tls.SignatureAndHashAlgorithm;
-import org.bouncycastle.crypto.tls.TlsEncryptionCredentials;
-import org.bouncycastle.crypto.tls.TlsSignerCredentials;
-import org.bouncycastle.crypto.tls.TlsUtils;
-import org.bouncycastle.util.Arrays;
-
-public class MockDTLSServer
- extends DefaultTlsServer
-{
- public void notifyAlertRaised(short alertLevel, short alertDescription, String message, Exception cause)
- {
- PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
- out.println("DTLS server raised alert (AlertLevel." + alertLevel + ", AlertDescription." + alertDescription
- + ")");
- if (message != null)
- {
- out.println(message);
- }
- if (cause != null)
- {
- cause.printStackTrace(out);
- }
- }
-
- public void notifyAlertReceived(short alertLevel, short alertDescription)
- {
- PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
- out.println("DTLS server received alert (AlertLevel." + alertLevel + ", AlertDescription." + alertDescription
- + ")");
- }
-
- protected int[] getCipherSuites()
- {
- return Arrays.concatenate(super.getCipherSuites(),
- new int[]
- {
- CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
- CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1,
- CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1,
- CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1,
- CipherSuite.TLS_RSA_WITH_SALSA20_SHA1,
- });
- }
-
- public CertificateRequest getCertificateRequest() throws IOException
- {
- Vector serverSigAlgs = null;
-
- if (TlsUtils.isSignatureAlgorithmsExtensionAllowed(serverVersion))
- {
- short[] hashAlgorithms = new short[]{ HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256,
- HashAlgorithm.sha224, HashAlgorithm.sha1 };
- short[] signatureAlgorithms = new short[]{ SignatureAlgorithm.rsa };
-
- serverSigAlgs = new Vector();
- for (int i = 0; i < hashAlgorithms.length; ++i)
- {
- for (int j = 0; j < signatureAlgorithms.length; ++j)
- {
- serverSigAlgs.addElement(new SignatureAndHashAlgorithm(hashAlgorithms[i],
- signatureAlgorithms[j]));
- }
- }
- }
-
- Vector certificateAuthorities = new Vector();
- certificateAuthorities.add(TlsTestUtils.loadCertificateResource("x509-ca.pem").getSubject());
-
- return new CertificateRequest(new short[]{ ClientCertificateType.rsa_sign }, serverSigAlgs, certificateAuthorities);
- }
-
- public void notifyClientCertificate(org.bouncycastle.crypto.tls.Certificate clientCertificate)
- throws IOException
- {
- Certificate[] chain = clientCertificate.getCertificateList();
- System.out.println("Received client certificate chain of length " + chain.length);
- for (int i = 0; i != chain.length; i++)
- {
- Certificate entry = chain[i];
- // TODO Create fingerprint based on certificate signature algorithm digest
- System.out.println(" fingerprint:SHA-256 " + TlsTestUtils.fingerprint(entry) + " (" + entry.getSubject()
- + ")");
- }
- }
-
- protected ProtocolVersion getMaximumVersion()
- {
- return ProtocolVersion.DTLSv12;
- }
-
- protected ProtocolVersion getMinimumVersion()
- {
- return ProtocolVersion.DTLSv10;
- }
-
- protected TlsEncryptionCredentials getRSAEncryptionCredentials()
- throws IOException
- {
- return TlsTestUtils.loadEncryptionCredentials(context, new String[]{"x509-server.pem", "x509-ca.pem"},
- "x509-server-key.pem");
- }
-
- protected TlsSignerCredentials getRSASignerCredentials()
- throws IOException
- {
- /*
- * TODO Note that this code fails to provide default value for the client supported
- * algorithms if it wasn't sent.
- */
- SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
- Vector sigAlgs = supportedSignatureAlgorithms;
- if (sigAlgs != null)
- {
- for (int i = 0; i < sigAlgs.size(); ++i)
- {
- SignatureAndHashAlgorithm sigAlg = (SignatureAndHashAlgorithm)
- sigAlgs.elementAt(i);
- if (sigAlg.getSignature() == SignatureAlgorithm.rsa)
- {
- signatureAndHashAlgorithm = sigAlg;
- break;
- }
- }
-
- if (signatureAndHashAlgorithm == null)
- {
- return null;
- }
- }
- return TlsTestUtils.loadSignerCredentials(context, new String[]{"x509-server.pem", "x509-ca.pem"},
- "x509-server-key.pem", signatureAndHashAlgorithm);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/MockDatagramAssociation.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/MockDatagramAssociation.java
deleted file mode 100644
index b8b7c069..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/MockDatagramAssociation.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import java.io.IOException;
-import java.net.DatagramPacket;
-import java.util.Vector;
-
-import org.bouncycastle.crypto.tls.DatagramTransport;
-
-public class MockDatagramAssociation
-{
- private int mtu;
- private MockDatagramTransport client, server;
-
- public MockDatagramAssociation(int mtu)
- {
- this.mtu = mtu;
-
- Vector clientQueue = new Vector();
- Vector serverQueue = new Vector();
-
- this.client = new MockDatagramTransport(clientQueue, serverQueue);
- this.server = new MockDatagramTransport(serverQueue, clientQueue);
- }
-
- public DatagramTransport getClient()
- {
- return client;
- }
-
- public DatagramTransport getServer()
- {
- return server;
- }
-
- private class MockDatagramTransport
- implements DatagramTransport
- {
- private Vector receiveQueue, sendQueue;
-
- MockDatagramTransport(Vector receiveQueue, Vector sendQueue)
- {
- this.receiveQueue = receiveQueue;
- this.sendQueue = sendQueue;
- }
-
- public int getReceiveLimit()
- throws IOException
- {
- return mtu;
- }
-
- public int getSendLimit()
- throws IOException
- {
- return mtu;
- }
-
- public int receive(byte[] buf, int off, int len, int waitMillis)
- throws IOException
- {
- synchronized (receiveQueue)
- {
- if (receiveQueue.isEmpty())
- {
- try
- {
- receiveQueue.wait(waitMillis);
- }
- catch (InterruptedException e)
- {
- // TODO Keep waiting until full wait expired?
- }
- if (receiveQueue.isEmpty())
- {
- return -1;
- }
- }
- DatagramPacket packet = (DatagramPacket)receiveQueue.remove(0);
- int copyLength = Math.min(len, packet.getLength());
- System.arraycopy(packet.getData(), packet.getOffset(), buf, off, copyLength);
- return copyLength;
- }
- }
-
- public void send(byte[] buf, int off, int len)
- throws IOException
- {
- if (len > mtu)
- {
- // TODO Simulate rejection?
- }
-
- byte[] copy = new byte[len];
- System.arraycopy(buf, off, copy, 0, len);
- DatagramPacket packet = new DatagramPacket(copy, len);
-
- synchronized (sendQueue)
- {
- sendQueue.addElement(packet);
- sendQueue.notify();
- }
- }
-
- public void close()
- throws IOException
- {
- // TODO?
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/MockTlsClient.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/MockTlsClient.java
deleted file mode 100644
index bc17db8c..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/MockTlsClient.java
+++ /dev/null
@@ -1,167 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.x509.Certificate;
-import org.bouncycastle.crypto.tls.AlertLevel;
-import org.bouncycastle.crypto.tls.CertificateRequest;
-import org.bouncycastle.crypto.tls.ClientCertificateType;
-import org.bouncycastle.crypto.tls.DefaultTlsClient;
-import org.bouncycastle.crypto.tls.MaxFragmentLength;
-import org.bouncycastle.crypto.tls.ProtocolVersion;
-import org.bouncycastle.crypto.tls.SignatureAlgorithm;
-import org.bouncycastle.crypto.tls.SignatureAndHashAlgorithm;
-import org.bouncycastle.crypto.tls.TlsAuthentication;
-import org.bouncycastle.crypto.tls.TlsCredentials;
-import org.bouncycastle.crypto.tls.TlsExtensionsUtils;
-import org.bouncycastle.crypto.tls.TlsSession;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.encoders.Hex;
-
-class MockTlsClient
- extends DefaultTlsClient
-{
- TlsSession session;
-
- MockTlsClient(TlsSession session)
- {
- this.session = session;
- }
-
- public TlsSession getSessionToResume()
- {
- return this.session;
- }
-
- public void notifyAlertRaised(short alertLevel, short alertDescription, String message, Exception cause)
- {
- PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
- out.println("TLS client raised alert (AlertLevel." + alertLevel + ", AlertDescription." + alertDescription
- + ")");
- if (message != null)
- {
- out.println("> " + message);
- }
- if (cause != null)
- {
- cause.printStackTrace(out);
- }
- }
-
- public void notifyAlertReceived(short alertLevel, short alertDescription)
- {
- PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
- out.println("TLS client received alert (AlertLevel." + alertLevel + ", AlertDescription."
- + alertDescription + ")");
- }
-
-// public int[] getCipherSuites()
-// {
-// return Arrays.concatenate(super.getCipherSuites(),
-// new int[]
-// {
-// CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
-// CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1,
-// CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1,
-// CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1,
-// CipherSuite.TLS_RSA_WITH_SALSA20_SHA1,
-// });
-// }
-
- public Hashtable getClientExtensions() throws IOException
- {
- Hashtable clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(super.getClientExtensions());
- TlsExtensionsUtils.addEncryptThenMACExtension(clientExtensions);
- TlsExtensionsUtils.addMaxFragmentLengthExtension(clientExtensions, MaxFragmentLength.pow2_9);
- TlsExtensionsUtils.addTruncatedHMacExtension(clientExtensions);
- return clientExtensions;
- }
-
- public void notifyServerVersion(ProtocolVersion serverVersion) throws IOException
- {
- super.notifyServerVersion(serverVersion);
-
- System.out.println("TLS client negotiated " + serverVersion);
- }
-
- public TlsAuthentication getAuthentication()
- throws IOException
- {
- return new TlsAuthentication()
- {
- public void notifyServerCertificate(org.bouncycastle.crypto.tls.Certificate serverCertificate)
- throws IOException
- {
- Certificate[] chain = serverCertificate.getCertificateList();
- System.out.println("TLS client received server certificate chain of length " + chain.length);
- for (int i = 0; i != chain.length; i++)
- {
- Certificate entry = chain[i];
- // TODO Create fingerprint based on certificate signature algorithm digest
- System.out.println(" fingerprint:SHA-256 " + TlsTestUtils.fingerprint(entry) + " ("
- + entry.getSubject() + ")");
- }
- }
-
- public TlsCredentials getClientCredentials(CertificateRequest certificateRequest)
- throws IOException
- {
- short[] certificateTypes = certificateRequest.getCertificateTypes();
- if (certificateTypes == null || !Arrays.contains(certificateTypes, ClientCertificateType.rsa_sign))
- {
- return null;
- }
-
- SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
- Vector sigAlgs = certificateRequest.getSupportedSignatureAlgorithms();
- if (sigAlgs != null)
- {
- for (int i = 0; i < sigAlgs.size(); ++i)
- {
- SignatureAndHashAlgorithm sigAlg = (SignatureAndHashAlgorithm)
- sigAlgs.elementAt(i);
- if (sigAlg.getSignature() == SignatureAlgorithm.rsa)
- {
- signatureAndHashAlgorithm = sigAlg;
- break;
- }
- }
-
- if (signatureAndHashAlgorithm == null)
- {
- return null;
- }
- }
-
- return TlsTestUtils.loadSignerCredentials(context, new String[] { "x509-client.pem", "x509-ca.pem" },
- "x509-client-key.pem", signatureAndHashAlgorithm);
- }
- };
- }
-
- public void notifyHandshakeComplete() throws IOException
- {
- super.notifyHandshakeComplete();
-
- TlsSession newSession = context.getResumableSession();
- if (newSession != null)
- {
- byte[] newSessionID = newSession.getSessionID();
- String hex = Hex.toHexString(newSessionID);
-
- if (this.session != null && Arrays.areEqual(this.session.getSessionID(), newSessionID))
- {
- System.out.println("Resumed session: " + hex);
- }
- else
- {
- System.out.println("Established session: " + hex);
- }
-
- this.session = newSession;
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/MockTlsServer.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/MockTlsServer.java
deleted file mode 100644
index 0f3c4631..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/MockTlsServer.java
+++ /dev/null
@@ -1,153 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.x509.Certificate;
-import org.bouncycastle.crypto.tls.AlertLevel;
-import org.bouncycastle.crypto.tls.CertificateRequest;
-import org.bouncycastle.crypto.tls.CipherSuite;
-import org.bouncycastle.crypto.tls.ClientCertificateType;
-import org.bouncycastle.crypto.tls.DefaultTlsServer;
-import org.bouncycastle.crypto.tls.HashAlgorithm;
-import org.bouncycastle.crypto.tls.ProtocolVersion;
-import org.bouncycastle.crypto.tls.SignatureAlgorithm;
-import org.bouncycastle.crypto.tls.SignatureAndHashAlgorithm;
-import org.bouncycastle.crypto.tls.TlsEncryptionCredentials;
-import org.bouncycastle.crypto.tls.TlsSignerCredentials;
-import org.bouncycastle.crypto.tls.TlsUtils;
-import org.bouncycastle.util.Arrays;
-
-class MockTlsServer
- extends DefaultTlsServer
-{
- public void notifyAlertRaised(short alertLevel, short alertDescription, String message, Exception cause)
- {
- PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
- out.println("TLS server raised alert (AlertLevel." + alertLevel + ", AlertDescription." + alertDescription
- + ")");
- if (message != null)
- {
- out.println("> " + message);
- }
- if (cause != null)
- {
- cause.printStackTrace(out);
- }
- }
-
- public void notifyAlertReceived(short alertLevel, short alertDescription)
- {
- PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
- out.println("TLS server received alert (AlertLevel." + alertLevel + ", AlertDescription."
- + alertDescription + ")");
- }
-
- protected int[] getCipherSuites()
- {
- return Arrays.concatenate(super.getCipherSuites(),
- new int[]
- {
- CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
- CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1,
- CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1,
- CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1,
- CipherSuite.TLS_RSA_WITH_SALSA20_SHA1,
- });
- }
-
- protected ProtocolVersion getMaximumVersion()
- {
- return ProtocolVersion.TLSv12;
- }
-
- public ProtocolVersion getServerVersion() throws IOException
- {
- ProtocolVersion serverVersion = super.getServerVersion();
-
- System.out.println("TLS server negotiated " + serverVersion);
-
- return serverVersion;
- }
-
- public CertificateRequest getCertificateRequest() throws IOException
- {
- Vector serverSigAlgs = null;
-
- if (TlsUtils.isSignatureAlgorithmsExtensionAllowed(serverVersion))
- {
- short[] hashAlgorithms = new short[]{ HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256,
- HashAlgorithm.sha224, HashAlgorithm.sha1 };
- short[] signatureAlgorithms = new short[]{ SignatureAlgorithm.rsa };
-
- serverSigAlgs = new Vector();
- for (int i = 0; i < hashAlgorithms.length; ++i)
- {
- for (int j = 0; j < signatureAlgorithms.length; ++j)
- {
- serverSigAlgs.addElement(new SignatureAndHashAlgorithm(hashAlgorithms[i],
- signatureAlgorithms[j]));
- }
- }
- }
-
- Vector certificateAuthorities = new Vector();
- certificateAuthorities.add(TlsTestUtils.loadCertificateResource("x509-ca.pem").getSubject());
-
- return new CertificateRequest(new short[]{ ClientCertificateType.rsa_sign }, serverSigAlgs, certificateAuthorities);
- }
-
- public void notifyClientCertificate(org.bouncycastle.crypto.tls.Certificate clientCertificate)
- throws IOException
- {
- Certificate[] chain = clientCertificate.getCertificateList();
- System.out.println("TLS server received client certificate chain of length " + chain.length);
- for (int i = 0; i != chain.length; i++)
- {
- Certificate entry = chain[i];
- // TODO Create fingerprint based on certificate signature algorithm digest
- System.out.println(" fingerprint:SHA-256 " + TlsTestUtils.fingerprint(entry) + " ("
- + entry.getSubject() + ")");
- }
- }
-
- protected TlsEncryptionCredentials getRSAEncryptionCredentials()
- throws IOException
- {
- return TlsTestUtils.loadEncryptionCredentials(context, new String[]{"x509-server.pem", "x509-ca.pem"},
- "x509-server-key.pem");
- }
-
- protected TlsSignerCredentials getRSASignerCredentials()
- throws IOException
- {
- /*
- * TODO Note that this code fails to provide default value for the client supported
- * algorithms if it wasn't sent.
- */
- SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
- Vector sigAlgs = supportedSignatureAlgorithms;
- if (sigAlgs != null)
- {
- for (int i = 0; i < sigAlgs.size(); ++i)
- {
- SignatureAndHashAlgorithm sigAlg = (SignatureAndHashAlgorithm)
- sigAlgs.elementAt(i);
- if (sigAlg.getSignature() == SignatureAlgorithm.rsa)
- {
- signatureAndHashAlgorithm = sigAlg;
- break;
- }
- }
-
- if (signatureAndHashAlgorithm == null)
- {
- return null;
- }
- }
-
- return TlsTestUtils.loadSignerCredentials(context, new String[]{"x509-server.pem", "x509-ca.pem"},
- "x509-server-key.pem", signatureAndHashAlgorithm);
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/NetworkInputStream.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/NetworkInputStream.java
deleted file mode 100644
index e5f47706..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/NetworkInputStream.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * Tracks and enforces close() calls, without closing the underlying InputStream
- */
-class NetworkInputStream extends FilterInputStream
-{
- boolean closed = false;
-
- public NetworkInputStream(InputStream input)
- {
- super(input);
- }
-
- synchronized boolean isClosed()
- {
- return closed;
- }
-
- public int available() throws IOException
- {
- checkNotClosed();
- return in.available();
- }
-
- public synchronized void close() throws IOException
- {
- closed = true;
- }
-
- public int read() throws IOException
- {
- checkNotClosed();
- return in.read();
- }
-
- public int read(byte[] b) throws IOException
- {
- checkNotClosed();
- return in.read(b);
- }
-
- public int read(byte[] b, int off, int len) throws IOException
- {
- checkNotClosed();
- return in.read(b, off, len);
- }
-
- protected synchronized void checkNotClosed() throws IOException
- {
- if (closed)
- {
- throw new IOException("NetworkInputStream closed");
- }
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/NetworkOutputStream.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/NetworkOutputStream.java
deleted file mode 100644
index a11694b7..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/NetworkOutputStream.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * Tracks and enforces close() calls, without closing the underlying OutputStream
- */
-class NetworkOutputStream extends FilterOutputStream
-{
- boolean closed = false;
-
- public NetworkOutputStream(OutputStream output)
- {
- super(output);
- }
-
- synchronized boolean isClosed()
- {
- return closed;
- }
-
- public synchronized void close() throws IOException
- {
- closed = true;
- }
-
- public void write(int b) throws IOException
- {
- checkNotClosed();
- out.write(b);
- }
-
- public void write(byte[] b) throws IOException
- {
- checkNotClosed();
- out.write(b);
- }
-
- public void write(byte[] b, int off, int len) throws IOException
- {
- checkNotClosed();
- out.write(b, off, len);
- }
-
- protected synchronized void checkNotClosed() throws IOException
- {
- if (closed)
- {
- throw new IOException("NetworkOutputStream closed");
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsClientTest.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsClientTest.java
deleted file mode 100644
index 10485ccd..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsClientTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.net.InetAddress;
-import java.net.Socket;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.tls.TlsClient;
-import org.bouncycastle.crypto.tls.TlsClientProtocol;
-
-/**
- * A simple test designed to conduct a TLS handshake with an external TLS server.
- * <p/>
- * Please refer to GnuTLSSetup.txt or OpenSSLSetup.txt, and x509-*.pem files in this package for
- * help configuring an external TLS server.
- */
-public class TlsClientTest
-{
- private static final SecureRandom secureRandom = new SecureRandom();
-
- public static void main(String[] args)
- throws Exception
- {
- InetAddress address = InetAddress.getLocalHost();
- int port = 5556;
-
- long time1 = System.currentTimeMillis();
-
- MockTlsClient client = new MockTlsClient(null);
- TlsClientProtocol protocol = openTlsConnection(address, port, client);
- protocol.close();
-
- long time2 = System.currentTimeMillis();
- System.out.println("Elapsed 1: " + (time2 - time1) + "ms");
-
- client = new MockTlsClient(client.getSessionToResume());
- protocol = openTlsConnection(address, port, client);
-
- long time3 = System.currentTimeMillis();
- System.out.println("Elapsed 2: " + (time3 - time2) + "ms");
-
- OutputStream output = protocol.getOutputStream();
- output.write("GET / HTTP/1.1\r\n\r\n".getBytes("UTF-8"));
- output.flush();
-
- InputStream input = protocol.getInputStream();
- BufferedReader reader = new BufferedReader(new InputStreamReader(input));
-
- String line;
- while ((line = reader.readLine()) != null)
- {
- System.out.println(">>> " + line);
- }
-
- protocol.close();
- }
-
- static TlsClientProtocol openTlsConnection(InetAddress address, int port, TlsClient client) throws IOException
- {
- Socket s = new Socket(address, port);
- TlsClientProtocol protocol = new TlsClientProtocol(s.getInputStream(), s.getOutputStream(), secureRandom);
- protocol.connect(client);
- return protocol;
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsProtocolTest.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsProtocolTest.java
deleted file mode 100644
index a817c47a..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsProtocolTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import java.io.OutputStream;
-import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
-import java.security.SecureRandom;
-
-import junit.framework.TestCase;
-
-import org.bouncycastle.crypto.tls.TlsClientProtocol;
-import org.bouncycastle.crypto.tls.TlsServerProtocol;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.io.Streams;
-
-public class TlsProtocolTest
- extends TestCase
-{
- public void testClientServer()
- throws Exception
- {
- SecureRandom secureRandom = new SecureRandom();
-
- PipedInputStream clientRead = new PipedInputStream();
- PipedInputStream serverRead = new PipedInputStream();
- PipedOutputStream clientWrite = new PipedOutputStream(serverRead);
- PipedOutputStream serverWrite = new PipedOutputStream(clientRead);
-
- TlsClientProtocol clientProtocol = new TlsClientProtocol(clientRead, clientWrite, secureRandom);
- TlsServerProtocol serverProtocol = new TlsServerProtocol(serverRead, serverWrite, secureRandom);
-
- ServerThread serverThread = new ServerThread(serverProtocol);
- serverThread.start();
-
- MockTlsClient client = new MockTlsClient(null);
- clientProtocol.connect(client);
-
- // NOTE: Because we write-all before we read-any, this length can't be more than the pipe capacity
- int length = 1000;
-
- byte[] data = new byte[length];
- secureRandom.nextBytes(data);
-
- OutputStream output = clientProtocol.getOutputStream();
- output.write(data);
-
- byte[] echo = new byte[data.length];
- int count = Streams.readFully(clientProtocol.getInputStream(), echo);
-
- assertEquals(count, data.length);
- assertTrue(Arrays.areEqual(data, echo));
-
- output.close();
-
- serverThread.join();
- }
-
- static class ServerThread
- extends Thread
- {
- private final TlsServerProtocol serverProtocol;
-
- ServerThread(TlsServerProtocol serverProtocol)
- {
- this.serverProtocol = serverProtocol;
- }
-
- public void run()
- {
- try
- {
- MockTlsServer server = new MockTlsServer();
- serverProtocol.accept(server);
- Streams.pipeAll(serverProtocol.getInputStream(), serverProtocol.getOutputStream());
- serverProtocol.close();
- }
- catch (Exception e)
- {
-// throw new RuntimeException(e);
- }
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsServerTest.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsServerTest.java
deleted file mode 100644
index e590cf5e..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsServerTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.tls.TlsServerProtocol;
-import org.bouncycastle.util.io.Streams;
-import org.bouncycastle.util.io.TeeOutputStream;
-
-/**
- * A simple test designed to conduct a TLS handshake with an external TLS client.
- * <p/>
- * Please refer to GnuTLSSetup.txt or OpenSSLSetup.txt, and x509-*.pem files in this package for
- * help configuring an external TLS client.
- */
-public class TlsServerTest
-{
- private static final SecureRandom secureRandom = new SecureRandom();
-
- public static void main(String[] args)
- throws Exception
- {
- InetAddress address = InetAddress.getLocalHost();
- int port = 5556;
-
- ServerSocket ss = new ServerSocket(port, 16, address);
- while (true)
- {
- Socket s = ss.accept();
- System.out.println("--------------------------------------------------------------------------------");
- System.out.println("Accepted " + s);
- ServerThread t = new ServerThread(s);
- t.start();
- }
- }
-
- static class ServerThread
- extends Thread
- {
- private final Socket s;
-
- ServerThread(Socket s)
- {
- this.s = s;
- }
-
- public void run()
- {
- try
- {
- MockTlsServer server = new MockTlsServer();
- TlsServerProtocol serverProtocol = new TlsServerProtocol(s.getInputStream(), s.getOutputStream(), secureRandom);
- serverProtocol.accept(server);
- OutputStream log = new TeeOutputStream(serverProtocol.getOutputStream(), System.out);
- Streams.pipeAll(serverProtocol.getInputStream(), log);
- serverProtocol.close();
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
- finally
- {
- try
- {
- s.close();
- }
- catch (IOException e)
- {
- }
- finally
- {
- }
- }
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsTestCase.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsTestCase.java
deleted file mode 100644
index 8e7f13a6..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsTestCase.java
+++ /dev/null
@@ -1,252 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import java.io.OutputStream;
-import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
-import java.security.SecureRandom;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import org.bouncycastle.crypto.tls.AlertDescription;
-import org.bouncycastle.crypto.tls.ProtocolVersion;
-import org.bouncycastle.crypto.tls.TlsClientProtocol;
-import org.bouncycastle.crypto.tls.TlsServerProtocol;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.io.Streams;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-
-import static org.junit.Assert.*;
-
-@RunWith(Parameterized.class)
-public class TlsTestCase
-{
-
- // Make the access to constants less verbose
- static abstract class C extends TlsTestConfig {}
-
- @Parameterized.Parameters(name = "{index}: {1}")
- public static Collection<Object[]> data() {
- List<Object[]> params = new ArrayList<Object[]>();
- addVersionTests(params, ProtocolVersion.TLSv10);
- addVersionTests(params, ProtocolVersion.TLSv11);
- addVersionTests(params, ProtocolVersion.TLSv12);
- return params;
- }
-
- private static void addVersionTests(List<Object[]> params, ProtocolVersion version)
- {
- String prefix = version.toString().replaceAll("[ \\.]", "") + "_";
-
- {
- TlsTestConfig c = createTlsTestConfig(version);
-
- params.add(new Object[] { c, prefix + "GoodDefault" });
- }
-
- {
- TlsTestConfig c = createTlsTestConfig(version);
- c.clientAuth = C.CLIENT_AUTH_INVALID_VERIFY;
- c.expectServerFatalAlert(AlertDescription.decrypt_error);
-
- params.add(new Object[] { c, prefix + "BadCertificateVerify" });
- }
-
- {
- TlsTestConfig c = createTlsTestConfig(version);
- c.clientAuth = C.CLIENT_AUTH_INVALID_CERT;
- c.expectServerFatalAlert(AlertDescription.bad_certificate);
-
- params.add(new Object[] { c, prefix + "BadClientCertificate" });
- }
-
- {
- TlsTestConfig c = createTlsTestConfig(version);
- c.clientAuth = C.CLIENT_AUTH_NONE;
- c.serverCertReq = C.SERVER_CERT_REQ_MANDATORY;
- c.expectServerFatalAlert(AlertDescription.handshake_failure);
-
- params.add(new Object[] { c, prefix + "BadMandatoryCertReqDeclined" });
- }
-
- {
- TlsTestConfig c = createTlsTestConfig(version);
- c.serverCertReq = C.SERVER_CERT_REQ_NONE;
-
- params.add(new Object[] { c, prefix + "GoodNoCertReq" });
- }
-
- {
- TlsTestConfig c = createTlsTestConfig(version);
- c.clientAuth = C.CLIENT_AUTH_NONE;
-
- params.add(new Object[] { c, prefix + "GoodOptionalCertReqDeclined" });
- }
- }
-
- private static TlsTestConfig createTlsTestConfig(ProtocolVersion version)
- {
- TlsTestConfig c = new TlsTestConfig();
- c.clientMinimumVersion = ProtocolVersion.TLSv10;
- c.clientOfferVersion = ProtocolVersion.TLSv12;
- c.serverMaximumVersion = version;
- c.serverMinimumVersion = ProtocolVersion.TLSv10;
- return c;
- }
-
-
- private static void checkTLSVersion(ProtocolVersion version)
- {
- if (version != null && !version.isTLS())
- {
- throw new IllegalStateException("Non-TLS version");
- }
- }
-
- protected final TlsTestConfig config;
-
- public TlsTestCase(TlsTestConfig config, String name)
- {
- checkTLSVersion(config.clientMinimumVersion);
- checkTLSVersion(config.clientOfferVersion);
- checkTLSVersion(config.serverMaximumVersion);
- checkTLSVersion(config.serverMinimumVersion);
-
- this.config = config;
- }
-
- @Test
- public void runTest() throws Throwable
- {
- SecureRandom secureRandom = new SecureRandom();
-
- PipedInputStream clientRead = new PipedInputStream();
- PipedInputStream serverRead = new PipedInputStream();
- PipedOutputStream clientWrite = new PipedOutputStream(serverRead);
- PipedOutputStream serverWrite = new PipedOutputStream(clientRead);
-
- NetworkInputStream clientNetIn = new NetworkInputStream(clientRead);
- NetworkInputStream serverNetIn = new NetworkInputStream(serverRead);
- NetworkOutputStream clientNetOut = new NetworkOutputStream(clientWrite);
- NetworkOutputStream serverNetOut = new NetworkOutputStream(serverWrite);
-
- TlsClientProtocol clientProtocol = new TlsClientProtocol(clientNetIn, clientNetOut, secureRandom);
- TlsServerProtocol serverProtocol = new TlsServerProtocol(serverNetIn, serverNetOut, secureRandom);
-
- TlsTestClientImpl clientImpl = new TlsTestClientImpl(config);
- TlsTestServerImpl serverImpl = new TlsTestServerImpl(config);
-
- ServerThread serverThread = new ServerThread(serverProtocol, serverImpl);
- serverThread.start();
-
- Exception caught = null;
- try
- {
- clientProtocol.connect(clientImpl);
-
- // NOTE: Because we write-all before we read-any, this length can't be more than the pipe capacity
- int length = 1000;
-
- byte[] data = new byte[length];
- secureRandom.nextBytes(data);
-
- OutputStream output = clientProtocol.getOutputStream();
- output.write(data);
-
- byte[] echo = new byte[data.length];
- int count = Streams.readFully(clientProtocol.getInputStream(), echo);
-
- assertEquals(count, data.length);
- assertTrue(Arrays.areEqual(data, echo));
-
- output.close();
- }
- catch (Exception e)
- {
- caught = e;
- logException(caught);
- }
-
- serverThread.allowExit();
- serverThread.join();
-
- assertTrue("Client InputStream not closed", clientNetIn.isClosed());
- assertTrue("Client OutputStream not closed", clientNetOut.isClosed());
- assertTrue("Server InputStream not closed", serverNetIn.isClosed());
- assertTrue("Server OutputStream not closed", serverNetOut.isClosed());
-
- assertEquals("Client fatal alert connection end", config.expectFatalAlertConnectionEnd, clientImpl.firstFatalAlertConnectionEnd);
- assertEquals("Server fatal alert connection end", config.expectFatalAlertConnectionEnd, serverImpl.firstFatalAlertConnectionEnd);
-
- assertEquals("Client fatal alert description", config.expectFatalAlertDescription, clientImpl.firstFatalAlertDescription);
- assertEquals("Server fatal alert description", config.expectFatalAlertDescription, serverImpl.firstFatalAlertDescription);
-
- if (config.expectFatalAlertConnectionEnd == -1)
- {
- assertNull("Unexpected client exception", caught);
- assertNull("Unexpected server exception", serverThread.caught);
- }
- }
-
- protected void logException(Exception e)
- {
- if (TlsTestConfig.DEBUG)
- {
- e.printStackTrace();
- }
- }
-
- class ServerThread extends Thread
- {
- protected final TlsServerProtocol serverProtocol;
- protected final TlsTestServerImpl serverImpl;
-
- boolean canExit = false;
- Exception caught = null;
-
- ServerThread(TlsServerProtocol serverProtocol, TlsTestServerImpl serverImpl)
- {
- this.serverProtocol = serverProtocol;
- this.serverImpl = serverImpl;
- }
-
- synchronized void allowExit()
- {
- canExit = true;
- this.notifyAll();
- }
-
- public void run()
- {
- try
- {
- serverProtocol.accept(serverImpl);
- Streams.pipeAll(serverProtocol.getInputStream(), serverProtocol.getOutputStream());
- serverProtocol.close();
- }
- catch (Exception e)
- {
- caught = e;
- logException(caught);
- }
-
- waitExit();
- }
-
- protected synchronized void waitExit()
- {
- while (!canExit)
- {
- try
- {
- this.wait();
- }
- catch (InterruptedException e)
- {
- }
- }
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsTestClientImpl.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsTestClientImpl.java
deleted file mode 100644
index 4bc76e68..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsTestClientImpl.java
+++ /dev/null
@@ -1,263 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.Certificate;
-import org.bouncycastle.crypto.tls.AlertDescription;
-import org.bouncycastle.crypto.tls.AlertLevel;
-import org.bouncycastle.crypto.tls.CertificateRequest;
-import org.bouncycastle.crypto.tls.ClientCertificateType;
-import org.bouncycastle.crypto.tls.ConnectionEnd;
-import org.bouncycastle.crypto.tls.DefaultTlsClient;
-import org.bouncycastle.crypto.tls.ProtocolVersion;
-import org.bouncycastle.crypto.tls.SignatureAlgorithm;
-import org.bouncycastle.crypto.tls.SignatureAndHashAlgorithm;
-import org.bouncycastle.crypto.tls.TlsAuthentication;
-import org.bouncycastle.crypto.tls.TlsCredentials;
-import org.bouncycastle.crypto.tls.TlsFatalAlert;
-import org.bouncycastle.crypto.tls.TlsSignerCredentials;
-import org.bouncycastle.util.Arrays;
-
-class TlsTestClientImpl
- extends DefaultTlsClient
-{
- protected final TlsTestConfig config;
-
- protected int firstFatalAlertConnectionEnd = -1;
- protected short firstFatalAlertDescription = -1;
-
- TlsTestClientImpl(TlsTestConfig config)
- {
- this.config = config;
- }
-
- int getFirstFatalAlertConnectionEnd()
- {
- return firstFatalAlertConnectionEnd;
- }
-
- short getFirstFatalAlertDescription()
- {
- return firstFatalAlertDescription;
- }
-
- public ProtocolVersion getClientVersion()
- {
- if (config.clientOfferVersion != null)
- {
- return config.clientOfferVersion;
- }
-
- return super.getClientVersion();
- }
-
- public ProtocolVersion getMinimumVersion()
- {
- if (config.clientMinimumVersion != null)
- {
- return config.clientMinimumVersion;
- }
-
- return super.getMinimumVersion();
- }
-
- public void notifyAlertRaised(short alertLevel, short alertDescription, String message, Exception cause)
- {
- if (alertLevel == AlertLevel.fatal && firstFatalAlertConnectionEnd == -1)
- {
- firstFatalAlertConnectionEnd = ConnectionEnd.client;
- firstFatalAlertDescription = alertDescription;
- }
-
- if (TlsTestConfig.DEBUG)
- {
- PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
- out.println("TLS client raised alert (AlertLevel." + alertLevel + ", AlertDescription." + alertDescription
- + ")");
- if (message != null)
- {
- out.println("> " + message);
- }
- if (cause != null)
- {
- cause.printStackTrace(out);
- }
- }
- }
-
- public void notifyAlertReceived(short alertLevel, short alertDescription)
- {
- if (alertLevel == AlertLevel.fatal && firstFatalAlertConnectionEnd == -1)
- {
- firstFatalAlertConnectionEnd = ConnectionEnd.server;
- firstFatalAlertDescription = alertDescription;
- }
-
- if (TlsTestConfig.DEBUG)
- {
- PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
- out.println("TLS client received alert (AlertLevel." + alertLevel + ", AlertDescription."
- + alertDescription + ")");
- }
- }
-
- public void notifyServerVersion(ProtocolVersion serverVersion) throws IOException
- {
- super.notifyServerVersion(serverVersion);
-
- if (TlsTestConfig.DEBUG)
- {
- System.out.println("TLS client negotiated " + serverVersion);
- }
- }
-
- public TlsAuthentication getAuthentication()
- throws IOException
- {
- return new TlsAuthentication()
- {
- public void notifyServerCertificate(org.bouncycastle.crypto.tls.Certificate serverCertificate)
- throws IOException
- {
- boolean isEmpty = serverCertificate == null || serverCertificate.isEmpty();
-
- Certificate[] chain = serverCertificate.getCertificateList();
-
- if (isEmpty || !chain[0].equals(TlsTestUtils.loadCertificateResource("x509-server.pem")))
- {
- throw new TlsFatalAlert(AlertDescription.bad_certificate);
- }
-
- if (TlsTestConfig.DEBUG)
- {
- System.out.println("TLS client received server certificate chain of length " + chain.length);
- for (int i = 0; i != chain.length; i++)
- {
- Certificate entry = chain[i];
- // TODO Create fingerprint based on certificate signature algorithm digest
- System.out.println(" fingerprint:SHA-256 " + TlsTestUtils.fingerprint(entry) + " ("
- + entry.getSubject() + ")");
- }
- }
- }
-
- public TlsCredentials getClientCredentials(CertificateRequest certificateRequest)
- throws IOException
- {
- if (config.serverCertReq == TlsTestConfig.SERVER_CERT_REQ_NONE)
- {
- throw new IllegalStateException();
- }
- if (config.clientAuth == TlsTestConfig.CLIENT_AUTH_NONE)
- {
- return null;
- }
-
- short[] certificateTypes = certificateRequest.getCertificateTypes();
- if (certificateTypes == null || !Arrays.contains(certificateTypes, ClientCertificateType.rsa_sign))
- {
- return null;
- }
-
- SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
- Vector sigAlgs = certificateRequest.getSupportedSignatureAlgorithms();
- if (sigAlgs != null)
- {
- for (int i = 0; i < sigAlgs.size(); ++i)
- {
- SignatureAndHashAlgorithm sigAlg = (SignatureAndHashAlgorithm)
- sigAlgs.elementAt(i);
- if (sigAlg.getSignature() == SignatureAlgorithm.rsa)
- {
- signatureAndHashAlgorithm = sigAlg;
- break;
- }
- }
-
- if (signatureAndHashAlgorithm == null)
- {
- return null;
- }
- }
-
- final TlsSignerCredentials signerCredentials = TlsTestUtils.loadSignerCredentials(context, new String[]{
- "x509-client.pem", "x509-ca.pem" }, "x509-client-key.pem", signatureAndHashAlgorithm);
-
- if (config.clientAuth == TlsTestConfig.CLIENT_AUTH_VALID)
- {
- return signerCredentials;
- }
-
- return new TlsSignerCredentials()
- {
- public byte[] generateCertificateSignature(byte[] hash) throws IOException
- {
- byte[] sig = signerCredentials.generateCertificateSignature(hash);
-
- if (config.clientAuth == TlsTestConfig.CLIENT_AUTH_INVALID_VERIFY)
- {
- sig = corruptBit(sig);
- }
-
- return sig;
- }
-
- public org.bouncycastle.crypto.tls.Certificate getCertificate()
- {
- org.bouncycastle.crypto.tls.Certificate cert = signerCredentials.getCertificate();
-
- if (config.clientAuth == TlsTestConfig.CLIENT_AUTH_INVALID_CERT)
- {
- cert = corruptCertificate(cert);
- }
-
- return cert;
- }
-
- public SignatureAndHashAlgorithm getSignatureAndHashAlgorithm()
- {
- return signerCredentials.getSignatureAndHashAlgorithm();
- }
- };
- }
- };
- }
-
- protected org.bouncycastle.crypto.tls.Certificate corruptCertificate(org.bouncycastle.crypto.tls.Certificate cert)
- {
- Certificate[] certList = cert.getCertificateList();
- certList[0] = corruptCertificateSignature(certList[0]);
- return new org.bouncycastle.crypto.tls.Certificate(certList);
- }
-
- protected Certificate corruptCertificateSignature(Certificate cert)
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- v.add(cert.getTBSCertificate());
- v.add(cert.getSignatureAlgorithm());
- v.add(corruptBitString(cert.getSignature()));
-
- return Certificate.getInstance(new DERSequence(v));
- }
-
- protected DERBitString corruptBitString(DERBitString bs)
- {
- return new DERBitString(corruptBit(bs.getBytes()));
- }
-
- protected byte[] corruptBit(byte[] bs)
- {
- bs = Arrays.clone(bs);
-
- // Flip a random bit
- int bit = context.getSecureRandom().nextInt(bs.length << 3);
- bs[bit >>> 3] ^= (1 << (bit & 7));
-
- return bs;
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsTestConfig.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsTestConfig.java
deleted file mode 100644
index 6110458e..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsTestConfig.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import org.bouncycastle.crypto.tls.ConnectionEnd;
-import org.bouncycastle.crypto.tls.ProtocolVersion;
-
-public class TlsTestConfig
-{
- public static final boolean DEBUG = false;
-
- /**
- * Client does not authenticate, ignores any certificate request
- */
- public static final int CLIENT_AUTH_NONE = 0;
-
- /**
- * Client will authenticate if it receives a certificate request
- */
- public static final int CLIENT_AUTH_VALID = 1;
-
- /**
- * Client will authenticate if it receives a certificate request, with an invalid certificate
- */
- public static final int CLIENT_AUTH_INVALID_CERT = 2;
-
- /**
- * Client will authenticate if it receives a certificate request, with an invalid CertificateVerify signature
- */
- public static final int CLIENT_AUTH_INVALID_VERIFY = 3;
-
- /**
- * Server will not request a client certificate
- */
- public static final int SERVER_CERT_REQ_NONE = 0;
-
- /**
- * Server will request a client certificate but receiving one is optional
- */
- public static final int SERVER_CERT_REQ_OPTIONAL = 1;
-
- /**
- * Server will request a client certificate and receiving one is mandatory
- */
- public static final int SERVER_CERT_REQ_MANDATORY = 2;
-
- /**
- * Configures the client authentication behaviour of the test client. Use CLIENT_AUTH_* constants.
- */
- public int clientAuth = CLIENT_AUTH_VALID;
-
- /**
- * Configures the minimum protocol version the client will accept. If null, uses the library's default.
- */
- public ProtocolVersion clientMinimumVersion = null;
-
- /**
- * Configures the protocol version the client will offer. If null, uses the library's default.
- */
- public ProtocolVersion clientOfferVersion = null;
-
- /**
- * Configures whether the test server will send a certificate request.
- */
- public int serverCertReq = SERVER_CERT_REQ_OPTIONAL;
-
- /**
- * Configures the maximum protocol version the server will accept. If null, uses the library's default.
- */
- public ProtocolVersion serverMaximumVersion = null;
-
- /**
- * Configures the minimum protocol version the server will accept. If null, uses the library's default.
- */
- public ProtocolVersion serverMinimumVersion = null;
-
- /**
- * Configures the connection end that a fatal alert is expected to be raised. Use ConnectionEnd.* constants.
- */
- public int expectFatalAlertConnectionEnd = -1;
-
- /**
- * Configures the type of fatal alert expected to be raised. Use AlertDescription.* constants.
- */
- public short expectFatalAlertDescription = -1;
-
- public void expectClientFatalAlert(short alertDescription)
- {
- this.expectFatalAlertConnectionEnd = ConnectionEnd.client;
- this.expectFatalAlertDescription = alertDescription;
- }
-
- public void expectServerFatalAlert(short alertDescription)
- {
- this.expectFatalAlertConnectionEnd = ConnectionEnd.server;
- this.expectFatalAlertDescription = alertDescription;
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsTestServerImpl.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsTestServerImpl.java
deleted file mode 100644
index 835db459..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsTestServerImpl.java
+++ /dev/null
@@ -1,222 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.x509.Certificate;
-import org.bouncycastle.crypto.tls.AlertDescription;
-import org.bouncycastle.crypto.tls.AlertLevel;
-import org.bouncycastle.crypto.tls.CertificateRequest;
-import org.bouncycastle.crypto.tls.ClientCertificateType;
-import org.bouncycastle.crypto.tls.ConnectionEnd;
-import org.bouncycastle.crypto.tls.DefaultTlsServer;
-import org.bouncycastle.crypto.tls.HashAlgorithm;
-import org.bouncycastle.crypto.tls.ProtocolVersion;
-import org.bouncycastle.crypto.tls.SignatureAlgorithm;
-import org.bouncycastle.crypto.tls.SignatureAndHashAlgorithm;
-import org.bouncycastle.crypto.tls.TlsEncryptionCredentials;
-import org.bouncycastle.crypto.tls.TlsFatalAlert;
-import org.bouncycastle.crypto.tls.TlsSignerCredentials;
-import org.bouncycastle.crypto.tls.TlsUtils;
-
-class TlsTestServerImpl
- extends DefaultTlsServer
-{
- protected final TlsTestConfig config;
-
- protected int firstFatalAlertConnectionEnd = -1;
- protected short firstFatalAlertDescription = -1;
-
- TlsTestServerImpl(TlsTestConfig config)
- {
- this.config = config;
- }
-
- int getFirstFatalAlertConnectionEnd()
- {
- return firstFatalAlertConnectionEnd;
- }
-
- short getFirstFatalAlertDescription()
- {
- return firstFatalAlertDescription;
- }
-
- protected ProtocolVersion getMaximumVersion()
- {
- if (config.serverMaximumVersion != null)
- {
- return config.serverMaximumVersion;
- }
-
- return super.getMaximumVersion();
- }
-
- protected ProtocolVersion getMinimumVersion()
- {
- if (config.serverMinimumVersion != null)
- {
- return config.serverMinimumVersion;
- }
-
- return super.getMinimumVersion();
- }
-
- public void notifyAlertRaised(short alertLevel, short alertDescription, String message, Exception cause)
- {
- if (alertLevel == AlertLevel.fatal && firstFatalAlertConnectionEnd == -1)
- {
- firstFatalAlertConnectionEnd = ConnectionEnd.server;
- firstFatalAlertDescription = alertDescription;
- }
-
- if (TlsTestConfig.DEBUG)
- {
- PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
- out.println("TLS server raised alert (AlertLevel." + alertLevel + ", AlertDescription." + alertDescription
- + ")");
- if (message != null)
- {
- out.println("> " + message);
- }
- if (cause != null)
- {
- cause.printStackTrace(out);
- }
- }
- }
-
- public void notifyAlertReceived(short alertLevel, short alertDescription)
- {
- if (alertLevel == AlertLevel.fatal && firstFatalAlertConnectionEnd == -1)
- {
- firstFatalAlertConnectionEnd = ConnectionEnd.client;
- firstFatalAlertDescription = alertDescription;
- }
-
- if (TlsTestConfig.DEBUG)
- {
- PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
- out.println("TLS server received alert (AlertLevel." + alertLevel + ", AlertDescription."
- + alertDescription + ")");
- }
- }
-
- public ProtocolVersion getServerVersion() throws IOException
- {
- ProtocolVersion serverVersion = super.getServerVersion();
-
- if (TlsTestConfig.DEBUG)
- {
- System.out.println("TLS server negotiated " + serverVersion);
- }
-
- return serverVersion;
- }
-
- public CertificateRequest getCertificateRequest() throws IOException
- {
- if (config.serverCertReq == TlsTestConfig.SERVER_CERT_REQ_NONE)
- {
- return null;
- }
-
- Vector serverSigAlgs = null;
-
- if (TlsUtils.isSignatureAlgorithmsExtensionAllowed(serverVersion))
- {
- short[] hashAlgorithms = new short[]{ HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256,
- HashAlgorithm.sha224, HashAlgorithm.sha1 };
- short[] signatureAlgorithms = new short[]{ SignatureAlgorithm.rsa };
-
- serverSigAlgs = new Vector();
- for (int i = 0; i < hashAlgorithms.length; ++i)
- {
- for (int j = 0; j < signatureAlgorithms.length; ++j)
- {
- serverSigAlgs.addElement(new SignatureAndHashAlgorithm(hashAlgorithms[i],
- signatureAlgorithms[j]));
- }
- }
- }
-
- Vector certificateAuthorities = new Vector();
- certificateAuthorities.add(TlsTestUtils.loadCertificateResource("x509-ca.pem").getSubject());
-
- return new CertificateRequest(new short[]{ ClientCertificateType.rsa_sign }, serverSigAlgs, certificateAuthorities);
- }
-
- public void notifyClientCertificate(org.bouncycastle.crypto.tls.Certificate clientCertificate)
- throws IOException
- {
- boolean isEmpty = (clientCertificate == null || clientCertificate.isEmpty());
-
- if (isEmpty != (config.clientAuth == TlsTestConfig.CLIENT_AUTH_NONE))
- {
- throw new IllegalStateException();
- }
- if (isEmpty && (config.serverCertReq == TlsTestConfig.SERVER_CERT_REQ_MANDATORY))
- {
- throw new TlsFatalAlert(AlertDescription.handshake_failure);
- }
-
- Certificate[] chain = clientCertificate.getCertificateList();
-
- if (!isEmpty && !chain[0].equals(TlsTestUtils.loadCertificateResource("x509-client.pem")))
- {
- throw new TlsFatalAlert(AlertDescription.bad_certificate);
- }
-
- if (TlsTestConfig.DEBUG)
- {
- System.out.println("TLS server received client certificate chain of length " + chain.length);
- for (int i = 0; i != chain.length; i++)
- {
- Certificate entry = chain[i];
- // TODO Create fingerprint based on certificate signature algorithm digest
- System.out.println(" fingerprint:SHA-256 " + TlsTestUtils.fingerprint(entry) + " ("
- + entry.getSubject() + ")");
- }
- }
- }
-
- protected TlsEncryptionCredentials getRSAEncryptionCredentials()
- throws IOException
- {
- return TlsTestUtils.loadEncryptionCredentials(context, new String[]{"x509-server.pem", "x509-ca.pem"},
- "x509-server-key.pem");
- }
-
- protected TlsSignerCredentials getRSASignerCredentials()
- throws IOException
- {
- /*
- * TODO Note that this code fails to provide default value for the client supported
- * algorithms if it wasn't sent.
- */
- SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
- Vector sigAlgs = supportedSignatureAlgorithms;
- if (sigAlgs != null)
- {
- for (int i = 0; i < sigAlgs.size(); ++i)
- {
- SignatureAndHashAlgorithm sigAlg = (SignatureAndHashAlgorithm)
- sigAlgs.elementAt(i);
- if (sigAlg.getSignature() == SignatureAlgorithm.rsa)
- {
- signatureAndHashAlgorithm = sigAlg;
- break;
- }
- }
-
- if (signatureAndHashAlgorithm == null)
- {
- return null;
- }
- }
-
- return TlsTestUtils.loadSignerCredentials(context, new String[]{"x509-server.pem", "x509-ca.pem"},
- "x509-server-key.pem", signatureAndHashAlgorithm);
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsTestUtils.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsTestUtils.java
deleted file mode 100644
index cf0bdb16..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsTestUtils.java
+++ /dev/null
@@ -1,157 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-
-import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
-import org.bouncycastle.crypto.tls.Certificate;
-import org.bouncycastle.crypto.tls.DefaultTlsAgreementCredentials;
-import org.bouncycastle.crypto.tls.DefaultTlsEncryptionCredentials;
-import org.bouncycastle.crypto.tls.DefaultTlsSignerCredentials;
-import org.bouncycastle.crypto.tls.SignatureAndHashAlgorithm;
-import org.bouncycastle.crypto.tls.TlsAgreementCredentials;
-import org.bouncycastle.crypto.tls.TlsContext;
-import org.bouncycastle.crypto.tls.TlsEncryptionCredentials;
-import org.bouncycastle.crypto.tls.TlsSignerCredentials;
-import org.bouncycastle.crypto.util.PrivateKeyFactory;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.io.pem.PemObject;
-import org.bouncycastle.util.io.pem.PemReader;
-
-public class TlsTestUtils
-{
- static final byte[] rsaCertData = Base64
- .decode("MIICUzCCAf2gAwIBAgIBATANBgkqhkiG9w0BAQQFADCBjzELMAkGA1UEBhMCQVUxKDAmBgNVBAoMH1RoZSBMZWdpb2"
- + "4gb2YgdGhlIEJvdW5jeSBDYXN0bGUxEjAQBgNVBAcMCU1lbGJvdXJuZTERMA8GA1UECAwIVmljdG9yaWExLzAtBgkq"
- + "hkiG9w0BCQEWIGZlZWRiYWNrLWNyeXB0b0Bib3VuY3ljYXN0bGUub3JnMB4XDTEzMDIyNTA2MDIwNVoXDTEzMDIyNT"
- + "A2MDM0NVowgY8xCzAJBgNVBAYTAkFVMSgwJgYDVQQKDB9UaGUgTGVnaW9uIG9mIHRoZSBCb3VuY3kgQ2FzdGxlMRIw"
- + "EAYDVQQHDAlNZWxib3VybmUxETAPBgNVBAgMCFZpY3RvcmlhMS8wLQYJKoZIhvcNAQkBFiBmZWVkYmFjay1jcnlwdG"
- + "9AYm91bmN5Y2FzdGxlLm9yZzBaMA0GCSqGSIb3DQEBAQUAA0kAMEYCQQC0p+RhcFdPFqlwgrIr5YtqKmKXmEGb4Shy"
- + "pL26Ymz66ZAPdqv7EhOdzl3lZWT6srZUMWWgQMYGiHQg4z2R7X7XAgERo0QwQjAOBgNVHQ8BAf8EBAMCBSAwEgYDVR"
- + "0lAQH/BAgwBgYEVR0lADAcBgNVHREBAf8EEjAQgQ50ZXN0QHRlc3QudGVzdDANBgkqhkiG9w0BAQQFAANBAHU55Ncz"
- + "eglREcTg54YLUlGWu2WOYWhit/iM1eeq8Kivro7q98eW52jTuMI3CI5ulqd0hYzshQKQaZ5GDzErMyM=");
-
- static final byte[] dudRsaCertData = Base64
- .decode("MIICUzCCAf2gAwIBAgIBATANBgkqhkiG9w0BAQQFADCBjzELMAkGA1UEBhMCQVUxKDAmBgNVBAoMH1RoZSBMZWdpb2"
- + "4gb2YgdGhlIEJvdW5jeSBDYXN0bGUxEjAQBgNVBAcMCU1lbGJvdXJuZTERMA8GA1UECAwIVmljdG9yaWExLzAtBgkq"
- + "hkiG9w0BCQEWIGZlZWRiYWNrLWNyeXB0b0Bib3VuY3ljYXN0bGUub3JnMB4XDTEzMDIyNTA1NDcyOFoXDTEzMDIyNT"
- + "A1NDkwOFowgY8xCzAJBgNVBAYTAkFVMSgwJgYDVQQKDB9UaGUgTGVnaW9uIG9mIHRoZSBCb3VuY3kgQ2FzdGxlMRIw"
- + "EAYDVQQHDAlNZWxib3VybmUxETAPBgNVBAgMCFZpY3RvcmlhMS8wLQYJKoZIhvcNAQkBFiBmZWVkYmFjay1jcnlwdG"
- + "9AYm91bmN5Y2FzdGxlLm9yZzBaMA0GCSqGSIb3DQEBAQUAA0kAMEYCQQC0p+RhcFdPFqlwgrIr5YtqKmKXmEGb4Shy"
- + "pL26Ymz66ZAPdqv7EhOdzl3lZWT6srZUMWWgQMYGiHQg4z2R7X7XAgERo0QwQjAOBgNVHQ8BAf8EBAMCAAEwEgYDVR"
- + "0lAQH/BAgwBgYEVR0lADAcBgNVHREBAf8EEjAQgQ50ZXN0QHRlc3QudGVzdDANBgkqhkiG9w0BAQQFAANBAJg55PBS"
- + "weg6obRUKF4FF6fCrWFi6oCYSQ99LWcAeupc5BofW5MstFMhCOaEucuGVqunwT5G7/DweazzCIrSzB0=");
-
- static String fingerprint(org.bouncycastle.asn1.x509.Certificate c)
- throws IOException
- {
- byte[] der = c.getEncoded();
- byte[] sha1 = sha256DigestOf(der);
- byte[] hexBytes = Hex.encode(sha1);
- String hex = new String(hexBytes, "ASCII").toUpperCase();
-
- StringBuffer fp = new StringBuffer();
- int i = 0;
- fp.append(hex.substring(i, i + 2));
- while ((i += 2) < hex.length())
- {
- fp.append(':');
- fp.append(hex.substring(i, i + 2));
- }
- return fp.toString();
- }
-
- static byte[] sha256DigestOf(byte[] input)
- {
- SHA256Digest d = new SHA256Digest();
- d.update(input, 0, input.length);
- byte[] result = new byte[d.getDigestSize()];
- d.doFinal(result, 0);
- return result;
- }
-
- static TlsAgreementCredentials loadAgreementCredentials(TlsContext context,
- String[] certResources, String keyResource)
- throws IOException
- {
- Certificate certificate = loadCertificateChain(certResources);
- AsymmetricKeyParameter privateKey = loadPrivateKeyResource(keyResource);
-
- return new DefaultTlsAgreementCredentials(certificate, privateKey);
- }
-
- static TlsEncryptionCredentials loadEncryptionCredentials(TlsContext context,
- String[] certResources, String keyResource)
- throws IOException
- {
- Certificate certificate = loadCertificateChain(certResources);
- AsymmetricKeyParameter privateKey = loadPrivateKeyResource(keyResource);
-
- return new DefaultTlsEncryptionCredentials(context, certificate, privateKey);
- }
-
- static TlsSignerCredentials loadSignerCredentials(TlsContext context, String[] certResources,
- String keyResource, SignatureAndHashAlgorithm signatureAndHashAlgorithm)
- throws IOException
- {
- Certificate certificate = loadCertificateChain(certResources);
- AsymmetricKeyParameter privateKey = loadPrivateKeyResource(keyResource);
-
- return new DefaultTlsSignerCredentials(context, certificate, privateKey, signatureAndHashAlgorithm);
- }
-
- static Certificate loadCertificateChain(String[] resources)
- throws IOException
- {
- org.bouncycastle.asn1.x509.Certificate[] chain = new org.bouncycastle.asn1.x509.Certificate[resources.length];
- for (int i = 0; i < resources.length; ++i)
- {
- chain[i] = loadCertificateResource(resources[i]);
- }
- return new Certificate(chain);
- }
-
- static org.bouncycastle.asn1.x509.Certificate loadCertificateResource(String resource)
- throws IOException
- {
- PemObject pem = loadPemResource(resource);
- if (pem.getType().endsWith("CERTIFICATE"))
- {
- return org.bouncycastle.asn1.x509.Certificate.getInstance(pem.getContent());
- }
- throw new IllegalArgumentException("'resource' doesn't specify a valid certificate");
- }
-
- static AsymmetricKeyParameter loadPrivateKeyResource(String resource)
- throws IOException
- {
- PemObject pem = loadPemResource(resource);
- if (pem.getType().endsWith("RSA PRIVATE KEY"))
- {
- RSAPrivateKey rsa = RSAPrivateKey.getInstance(pem.getContent());
- return new RSAPrivateCrtKeyParameters(rsa.getModulus(), rsa.getPublicExponent(),
- rsa.getPrivateExponent(), rsa.getPrime1(), rsa.getPrime2(), rsa.getExponent1(),
- rsa.getExponent2(), rsa.getCoefficient());
- }
- if (pem.getType().endsWith("PRIVATE KEY"))
- {
- return PrivateKeyFactory.createKey(pem.getContent());
- }
- throw new IllegalArgumentException("'resource' doesn't specify a valid private key");
- }
-
- static PemObject loadPemResource(String resource)
- throws IOException
- {
- InputStream s = TlsTestUtils.class.getResourceAsStream(resource);
- PemReader p = new PemReader(new InputStreamReader(s));
- PemObject o = p.readPemObject();
- p.close();
- return o;
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/UnreliableDatagramTransport.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/UnreliableDatagramTransport.java
deleted file mode 100644
index bdc205ae..00000000
--- a/core/src/test/java/org/bouncycastle/crypto/tls/test/UnreliableDatagramTransport.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package org.bouncycastle.crypto.tls.test;
-
-import java.io.IOException;
-import java.util.Random;
-
-import org.bouncycastle.crypto.tls.DatagramTransport;
-
-public class UnreliableDatagramTransport
- implements DatagramTransport
-{
-
- private final DatagramTransport transport;
- private final Random random;
- private final int percentPacketLossReceiving, percentPacketLossSending;
-
- public UnreliableDatagramTransport(DatagramTransport transport, Random random,
- int percentPacketLossReceiving, int percentPacketLossSending)
- {
- if (percentPacketLossReceiving < 0 || percentPacketLossReceiving > 100)
- {
- throw new IllegalArgumentException("'percentPacketLossReceiving' out of range");
- }
- if (percentPacketLossSending < 0 || percentPacketLossSending > 100)
- {
- throw new IllegalArgumentException("'percentPacketLossSending' out of range");
- }
-
- this.transport = transport;
- this.random = random;
- this.percentPacketLossReceiving = percentPacketLossReceiving;
- this.percentPacketLossSending = percentPacketLossSending;
- }
-
- public int getReceiveLimit()
- throws IOException
- {
- return transport.getReceiveLimit();
- }
-
- public int getSendLimit()
- throws IOException
- {
- return transport.getSendLimit();
- }
-
- public int receive(byte[] buf, int off, int len, int waitMillis)
- throws IOException
- {
- long endMillis = System.currentTimeMillis() + waitMillis;
- for (; ; )
- {
- int length = transport.receive(buf, off, len, waitMillis);
- if (length < 0 || !lostPacket(percentPacketLossReceiving))
- {
- return length;
- }
-
- System.out.println("PACKET LOSS (" + length + " byte packet not received)");
-
- long now = System.currentTimeMillis();
- if (now >= endMillis)
- {
- return -1;
- }
-
- waitMillis = (int)(endMillis - now);
- }
- }
-
- public void send(byte[] buf, int off, int len)
- throws IOException
- {
- if (lostPacket(percentPacketLossSending))
- {
- System.out.println("PACKET LOSS (" + len + " byte packet not sent)");
- }
- else
- {
- transport.send(buf, off, len);
- }
- }
-
- public void close()
- throws IOException
- {
- transport.close();
- }
-
- private boolean lostPacket(int percentPacketLoss)
- {
- return percentPacketLoss > 0 && random.nextInt(100) < percentPacketLoss;
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/i18n/filter/test/HTMLFilterTest.java b/core/src/test/java/org/bouncycastle/i18n/filter/test/HTMLFilterTest.java
deleted file mode 100644
index e1dfb733..00000000
--- a/core/src/test/java/org/bouncycastle/i18n/filter/test/HTMLFilterTest.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.bouncycastle.i18n.filter.test;
-
-import org.bouncycastle.i18n.filter.Filter;
-import org.bouncycastle.i18n.filter.HTMLFilter;
-
-import junit.framework.TestCase;
-
-public class HTMLFilterTest extends TestCase
-{
-
- private static final String test1 = "hello world";
-
- private static final String test2 = "<script></script>";
-
- private static final String test3 = "javascript:attack()";
-
- private static final String test4 = "\"hello\"";
-
- public void testDoFilter()
- {
- Filter dummy = new HTMLFilter();
-
- assertEquals("No filtering", "hello world", dummy.doFilter(test1));
- assertEquals("script tags", "&#60script&#62&#60/script&#62", dummy.doFilter(test2));
- assertEquals("javascript link", "javascript:attack&#40&#41", dummy.doFilter(test3));
- assertEquals("", "&#34hello&#34", dummy.doFilter(test4));
- }
-
-}
diff --git a/core/src/test/java/org/bouncycastle/i18n/filter/test/SQLFilterTest.java b/core/src/test/java/org/bouncycastle/i18n/filter/test/SQLFilterTest.java
deleted file mode 100644
index 5c1cc363..00000000
--- a/core/src/test/java/org/bouncycastle/i18n/filter/test/SQLFilterTest.java
+++ /dev/null
@@ -1,20 +0,0 @@
-
-package org.bouncycastle.i18n.filter.test;
-
-import org.bouncycastle.i18n.filter.Filter;
-import org.bouncycastle.i18n.filter.SQLFilter;
-
-import junit.framework.TestCase;
-
-public class SQLFilterTest extends TestCase
-{
-
- private static final String test1 = "\'\"=-/\\;\r\n";
-
- public void testDoFilter()
- {
- Filter filter = new SQLFilter();
- assertEquals("encode special charaters","\\\'\\\"\\=\\-\\/\\\\\\;\\r\\n",filter.doFilter(test1));
- }
-
-}
diff --git a/core/src/test/java/org/bouncycastle/i18n/test/AllTests.java b/core/src/test/java/org/bouncycastle/i18n/test/AllTests.java
deleted file mode 100644
index ee490e1d..00000000
--- a/core/src/test/java/org/bouncycastle/i18n/test/AllTests.java
+++ /dev/null
@@ -1,28 +0,0 @@
-
-package org.bouncycastle.i18n.test;
-
-import org.bouncycastle.i18n.filter.test.HTMLFilterTest;
-import org.bouncycastle.i18n.filter.test.SQLFilterTest;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-public class AllTests extends TestCase
-{
-
- public static void main (String[] args)
- {
- junit.textui.TestRunner.run (suite());
- }
-
- public static Test suite()
- {
- TestSuite suite = new TestSuite("i18n tests");
- suite.addTestSuite(LocalizedMessageTest.class);
- suite.addTestSuite(HTMLFilterTest.class);
- suite.addTestSuite(SQLFilterTest.class);
- return suite;
- }
-
-}
diff --git a/core/src/test/java/org/bouncycastle/i18n/test/LocalizedMessageTest.java b/core/src/test/java/org/bouncycastle/i18n/test/LocalizedMessageTest.java
deleted file mode 100644
index f7c5a420..00000000
--- a/core/src/test/java/org/bouncycastle/i18n/test/LocalizedMessageTest.java
+++ /dev/null
@@ -1,185 +0,0 @@
-package org.bouncycastle.i18n.test;
-
-import junit.framework.TestCase;
-import org.bouncycastle.i18n.LocaleString;
-import org.bouncycastle.i18n.LocalizedMessage;
-import org.bouncycastle.i18n.MissingEntryException;
-import org.bouncycastle.i18n.filter.HTMLFilter;
-import org.bouncycastle.i18n.filter.TrustedInput;
-import org.bouncycastle.util.encoders.Hex;
-
-import java.io.UnsupportedEncodingException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.Date;
-import java.util.Locale;
-import java.util.TimeZone;
-
-public class LocalizedMessageTest extends TestCase
-{
-
- private static final String TEST_RESOURCE = "org.bouncycastle.i18n.test.I18nTestMessages";
- private static final String UTF8_TEST_RESOURCE = "org.bouncycastle.i18n.test.I18nUTF8TestMessages";
-
- /*
- * test message id's
- */
- private static final String timeTestId = "time";
- private static final String argsTestId = "arguments";
- private static final String localeTestId = "hello";
- private static final String missingTestId = "missing";
- private static final String filterTestId = "filter";
- private static final String utf8TestId = "utf8";
-
- /*
- * Test method for 'org.bouncycastle.i18n.LocalizedMessage.getEntry(String,
- * Locale, TimeZone)'
- */
- public void testGetEntry()
- {
- LocalizedMessage msg;
-
- // test different locales
- msg = new LocalizedMessage(TEST_RESOURCE, localeTestId);
- assertEquals("Hello world.", msg.getEntry("text", Locale.ENGLISH,
- TimeZone.getDefault()));
- assertEquals("Hallo Welt.", msg.getEntry("text", Locale.GERMAN,
- TimeZone.getDefault()));
-
- // test arguments
- Object[] args = new Object[] { "Nobody" };
- msg = new LocalizedMessage(TEST_RESOURCE, argsTestId, args);
- assertEquals("My name is Nobody.", msg.getEntry("text", Locale.ENGLISH,
- TimeZone.getDefault()));
- assertEquals("Mein Name ist Nobody.", msg.getEntry("text",
- Locale.GERMAN, TimeZone.getDefault()));
-
- // test timezones
- // test date 17. Aug. 13:12:00 GMT
- Date testDate = new Date(1155820320000l);
- args = new Object[] { new TrustedInput(testDate) };
- msg = new LocalizedMessage(TEST_RESOURCE, timeTestId, args);
- assertEquals("It's 1:12:00 PM GMT at Aug 17, 2006.", msg.getEntry(
- "text", Locale.ENGLISH, TimeZone.getTimeZone("GMT")));
- // NOTE: Older JDKs appear to use '.' as the time separator for German locale
- assertEquals("Es ist 13:12 Uhr GMT am 17.08.2006.", msg.getEntry(
- "text", Locale.GERMAN, TimeZone.getTimeZone("GMT")).replace("13.12", "13:12"));
-
- // test time with filter
- args = new Object[] { new TrustedInput(testDate) };
- msg = new LocalizedMessage(TEST_RESOURCE, timeTestId, args);
- msg.setFilter(new HTMLFilter());
- assertEquals("It's 1:12:00 PM GMT at Aug 17, 2006.", msg.getEntry(
- "text", Locale.ENGLISH, TimeZone.getTimeZone("GMT")));
- // NOTE: Older JDKs appear to use '.' as the time separator for German locale
- assertEquals("Es ist 13:12 Uhr GMT am 17.08.2006.", msg.getEntry(
- "text", Locale.GERMAN, TimeZone.getTimeZone("GMT")).replace("13.12", "13:12"));
-
- // test number
- args = new Object[] { new TrustedInput(new Float(0.2)) };
- msg = new LocalizedMessage(TEST_RESOURCE, "number", args);
- assertEquals("20%", msg.getEntry("text", Locale.ENGLISH, TimeZone.getDefault()));
-
- // test filters
- String untrusted = "<script>doBadThings()</script>";
- args = new Object[] { untrusted };
- msg = new LocalizedMessage(TEST_RESOURCE,filterTestId,args);
- msg.setFilter(new HTMLFilter());
- assertEquals("The following part should contain no HTML tags: "
- + "&#60script&#62doBadThings&#40&#41&#60/script&#62",
- msg.getEntry("text",Locale.ENGLISH, TimeZone.getDefault()));
-
- // test missing entry
- msg = new LocalizedMessage(TEST_RESOURCE, missingTestId);
- try
- {
- String text = msg.getEntry("text", Locale.UK, TimeZone
- .getDefault());
- fail();
- }
- catch (MissingEntryException e)
- {
-// System.out.println(e.getDebugMsg());
- }
-
- // test missing entry
- try
- {
- URLClassLoader cl = URLClassLoader.newInstance(new URL[] {new URL("file:///nonexistent/")});
- msg = new LocalizedMessage(TEST_RESOURCE, missingTestId);
- msg.setClassLoader(cl);
- try
- {
- String text = msg.getEntry("text", Locale.UK, TimeZone
- .getDefault());
- fail();
- }
- catch (MissingEntryException e)
- {
-// System.out.println(e.getDebugMsg());
- }
- }
- catch (MalformedURLException e)
- {
-
- }
-
- // test utf8
- try
- {
-// String expectedUtf8 = "some umlauts äöüèéà";
- String expectedUtf8 = new String(Hex.decode("736f6d6520756d6c6175747320c3a4c3b6c3bcc3a8c3a9c3a0"), "UTF-8");
- msg = new LocalizedMessage(UTF8_TEST_RESOURCE, utf8TestId, "UTF-8");
- assertEquals(expectedUtf8, msg.getEntry("text", Locale.GERMAN, TimeZone.getDefault()));
- }
- catch (UnsupportedEncodingException e)
- {
-
- }
-
- }
-
- public void testLocalizedArgs()
- {
- LocaleString ls = new LocaleString(TEST_RESOURCE, "name");
-
- // without filter
- Object[] args = new Object[] { ls };
- LocalizedMessage msg = new LocalizedMessage(TEST_RESOURCE, argsTestId, args);
- assertEquals("My name is John.", msg.getEntry("text", Locale.ENGLISH,
- TimeZone.getDefault()));
- assertEquals("Mein Name ist Hans.", msg.getEntry("text",
- Locale.GERMAN, TimeZone.getDefault()));
-
- // with filter
- msg.setFilter(new HTMLFilter());
- assertEquals("My name is John.", msg.getEntry("text", Locale.ENGLISH,
- TimeZone.getDefault()));
- assertEquals("Mein Name ist Hans.", msg.getEntry("text",
- Locale.GERMAN, TimeZone.getDefault()));
-
- // add extra args
- LocaleString lsExtra = new LocaleString(TEST_RESOURCE, "hello.text");
- msg.setExtraArguments(new Object[] {" ", lsExtra});
- assertEquals("My name is John. Hello world.", msg.getEntry("text", Locale.ENGLISH,
- TimeZone.getDefault()));
- assertEquals("Mein Name ist Hans. Hallo Welt.", msg.getEntry("text",
- Locale.GERMAN, TimeZone.getDefault()));
-
- // missing localized arg
- try
- {
- ls = new LocaleString(TEST_RESOURCE, "noname");
- args = new Object[] { ls };
- msg = new LocalizedMessage(TEST_RESOURCE, argsTestId, args);
- msg.getEntry("text", Locale.ENGLISH, TimeZone.getDefault());
- fail();
- }
- catch (MissingEntryException e)
- {
- assertEquals("Can't find entry noname in resource file org.bouncycastle.i18n.test.I18nTestMessages.", e.getMessage());
- }
- }
-
-}
diff --git a/core/src/test/java/org/bouncycastle/math/ec/test/AllTests.java b/core/src/test/java/org/bouncycastle/math/ec/test/AllTests.java
deleted file mode 100644
index dcba332a..00000000
--- a/core/src/test/java/org/bouncycastle/math/ec/test/AllTests.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package org.bouncycastle.math.ec.test;
-
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-public class AllTests
-{
- public static void main (String[] args)
- throws Exception
- {
- junit.textui.TestRunner.run(suite());
- }
-
- public static Test suite()
- throws Exception
- {
- TestSuite suite = new TestSuite("EC Math tests");
-
- suite.addTest(ECAlgorithmsTest.suite());
- suite.addTest(ECPointTest.suite());
-
- return suite;
- }
-
- static List enumToList(Enumeration en)
- {
- List rv = new ArrayList();
-
- while (en.hasMoreElements())
- {
- rv.add(en.nextElement());
- }
-
- return rv;
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/math/ec/test/ECAlgorithmsTest.java b/core/src/test/java/org/bouncycastle/math/ec/test/ECAlgorithmsTest.java
deleted file mode 100644
index 6e293bf6..00000000
--- a/core/src/test/java/org/bouncycastle/math/ec/test/ECAlgorithmsTest.java
+++ /dev/null
@@ -1,168 +0,0 @@
-package org.bouncycastle.math.ec.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-import org.bouncycastle.asn1.x9.ECNamedCurveTable;
-import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.crypto.ec.CustomNamedCurves;
-import org.bouncycastle.math.ec.ECAlgorithms;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECPoint;
-
-public class ECAlgorithmsTest extends TestCase
-{
- private static final int SCALE = 4;
- private static final SecureRandom RND = new SecureRandom();
-
- public void testSumOfMultiplies()
- {
- ArrayList x9s = getTestCurves();
- Iterator it = x9s.iterator();
- while (it.hasNext())
- {
- X9ECParameters x9 = (X9ECParameters)it.next();
-
- ECPoint[] points = new ECPoint[SCALE];
- BigInteger[] scalars = new BigInteger[SCALE];
- for (int i = 0; i < SCALE; ++i)
- {
- points[i] = getRandomPoint(x9);
- scalars[i] = getRandomScalar(x9);
- }
-
- ECPoint u = x9.getCurve().getInfinity();
- for (int i = 0; i < SCALE; ++i)
- {
- u = u.add(points[i].multiply(scalars[i]));
-
- ECPoint v = ECAlgorithms.sumOfMultiplies(copyPoints(points, i + 1), copyScalars(scalars, i + 1));
-
- ECPoint[] results = new ECPoint[]{ u, v };
- x9.getCurve().normalizeAll(results);
-
- assertPointsEqual("ECAlgorithms.sumOfMultiplies is incorrect", results[0], results[1]);
- }
- }
- }
-
- public void testSumOfTwoMultiplies()
- {
- ArrayList x9s = getTestCurves();
- Iterator it = x9s.iterator();
- while (it.hasNext())
- {
- X9ECParameters x9 = (X9ECParameters)it.next();
-
- ECPoint p = getRandomPoint(x9);
- BigInteger a = getRandomScalar(x9);
-
- for (int i = 0; i < SCALE; ++i)
- {
- ECPoint q = getRandomPoint(x9);
- BigInteger b = getRandomScalar(x9);
-
- ECPoint u = p.multiply(a).add(q.multiply(b));
- ECPoint v = ECAlgorithms.shamirsTrick(p, a, q, b);
- ECPoint w = ECAlgorithms.sumOfTwoMultiplies(p, a, q, b);
-
- ECPoint[] results = new ECPoint[]{ u, v, w };
- x9.getCurve().normalizeAll(results);
-
- assertPointsEqual("ECAlgorithms.shamirsTrick is incorrect", results[0], results[1]);
- assertPointsEqual("ECAlgorithms.sumOfTwoMultiplies is incorrect", results[0], results[2]);
-
- p = q;
- a = b;
- }
- }
- }
-
- private void assertPointsEqual(String message, ECPoint a, ECPoint b)
- {
- assertEquals(message, a, b);
- }
-
- private ECPoint[] copyPoints(ECPoint[] ps, int len)
- {
- ECPoint[] result = new ECPoint[len];
- System.arraycopy(ps, 0, result, 0, len);
- return result;
- }
-
- private BigInteger[] copyScalars(BigInteger[] ks, int len)
- {
- BigInteger[] result = new BigInteger[len];
- System.arraycopy(ks, 0, result, 0, len);
- return result;
- }
-
- private ECPoint getRandomPoint(X9ECParameters x9)
- {
- return x9.getG().multiply(getRandomScalar(x9));
- }
-
- private BigInteger getRandomScalar(X9ECParameters x9)
- {
- return new BigInteger(x9.getN().bitLength(), RND);
- }
-
- private ArrayList getTestCurves()
- {
- ArrayList x9s = new ArrayList();
- Set names = new HashSet(AllTests.enumToList(ECNamedCurveTable.getNames()));
- names.addAll(AllTests.enumToList(CustomNamedCurves.getNames()));
-
- Iterator it = names.iterator();
- while (it.hasNext())
- {
- String name = (String)it.next();
-
- X9ECParameters x9 = ECNamedCurveTable.getByName(name);
- if (x9 != null)
- {
- addTestCurves(x9s, x9);
- }
-
- x9 = CustomNamedCurves.getByName(name);
- if (x9 != null)
- {
- addTestCurves(x9s, x9);
- }
- }
- return x9s;
- }
-
- private void addTestCurves(ArrayList x9s, X9ECParameters x9)
- {
- ECCurve curve = x9.getCurve();
-
- int[] coords = ECCurve.getAllCoordinateSystems();
- for (int i = 0; i < coords.length; ++i)
- {
- int coord = coords[i];
- if (curve.getCoordinateSystem() == coord)
- {
- x9s.add(x9);
- }
- else if (curve.supportsCoordinateSystem(coord))
- {
- ECCurve c = curve.configure().setCoordinateSystem(coord).create();
- x9s.add(new X9ECParameters(c, c.importPoint(x9.getG()), x9.getN(), x9.getH()));
- }
- }
- }
-
- public static Test suite()
- {
- return new TestSuite(ECAlgorithmsTest.class);
- }
-
-}
diff --git a/core/src/test/java/org/bouncycastle/math/ec/test/ECPointPerformanceTest.java b/core/src/test/java/org/bouncycastle/math/ec/test/ECPointPerformanceTest.java
deleted file mode 100644
index 9be8d3ea..00000000
--- a/core/src/test/java/org/bouncycastle/math/ec/test/ECPointPerformanceTest.java
+++ /dev/null
@@ -1,198 +0,0 @@
-package org.bouncycastle.math.ec.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-import junit.framework.TestCase;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.x9.ECNamedCurveTable;
-import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.crypto.ec.CustomNamedCurves;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.util.Times;
-
-/**
- * Compares the performance of the the window NAF point multiplication against conventional point
- * multiplication.
- */
-public class ECPointPerformanceTest extends TestCase
-{
- static final int MILLIS_PER_ROUND = 200;
- static final int MILLIS_WARMUP = 1000;
-
- static final int MULTS_PER_CHECK = 16;
- static final int NUM_ROUNDS = 10;
-
- private static String[] COORD_NAMES = new String[]{ "AFFINE", "HOMOGENEOUS", "JACOBIAN", "JACOBIAN-CHUDNOVSKY",
- "JACOBIAN-MODIFIED", "LAMBDA-AFFINE", "LAMBDA-PROJECTIVE", "SKEWED" };
-
- private void randMult(String curveName) throws Exception
- {
- X9ECParameters spec = ECNamedCurveTable.getByName(curveName);
- if (spec != null)
- {
- randMult(curveName, spec);
- }
-
- spec = CustomNamedCurves.getByName(curveName);
- if (spec != null)
- {
- randMult(curveName + " (custom)", spec);
- }
- }
-
- private void randMult(String label, X9ECParameters spec) throws Exception
- {
- ECCurve C = spec.getCurve();
- ECPoint G = (ECPoint)spec.getG();
- BigInteger n = spec.getN();
-
- SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
- random.setSeed(System.currentTimeMillis());
-
- System.out.println(label);
-
- int[] coords = ECCurve.getAllCoordinateSystems();
- for (int i = 0; i < coords.length; ++i)
- {
- int coord = coords[i];
- if (C.supportsCoordinateSystem(coord))
- {
- ECCurve c = C;
- ECPoint g = G;
-
- boolean defaultCoord = (c.getCoordinateSystem() == coord);
- if (!defaultCoord)
- {
- c = C.configure().setCoordinateSystem(coord).create();
- g = c.importPoint(G);
- }
-
- double avgRate = randMult(random, g, n);
- String coordName = COORD_NAMES[coord];
- StringBuffer sb = new StringBuffer();
- sb.append(" ");
- sb.append(defaultCoord ? '*' : ' ');
- sb.append(coordName);
- for (int j = sb.length(); j < 30; ++j)
- {
- sb.append(' ');
- }
- sb.append(": ");
- sb.append(avgRate);
- sb.append(" mults/sec");
- for (int j = sb.length(); j < 64; ++j)
- {
- sb.append(' ');
- }
- sb.append('(');
- sb.append(1000.0 / avgRate);
- sb.append(" millis/mult)");
- System.out.println(sb.toString());
- }
- }
- }
-
- private double randMult(SecureRandom random, ECPoint g, BigInteger n) throws Exception
- {
- BigInteger[] ks = new BigInteger[128];
- for (int i = 0; i < ks.length; ++i)
- {
- ks[i] = new BigInteger(n.bitLength() - 1, random);
- }
-
- int ki = 0;
- ECPoint p = g;
-
- {
- long startTime = Times.nanoTime();
- long goalTime = startTime + 1000000L * MILLIS_WARMUP;
-
- do
- {
- BigInteger k = ks[ki];
- p = g.multiply(k);
- if ((ki & 1) != 0)
- {
- g = p;
- }
- if (++ki == ks.length)
- {
- ki = 0;
- }
- }
- while (Times.nanoTime() < goalTime);
- }
-
- double minRate = Double.MAX_VALUE, maxRate = Double.MIN_VALUE, totalRate = 0.0;
-
- for (int i = 1; i <= NUM_ROUNDS; i++)
- {
- long startTime = Times.nanoTime();
- long goalTime = startTime + 1000000L * MILLIS_PER_ROUND;
- long count = 0, endTime;
-
- do
- {
- ++count;
-
- for (int j = 0; j < MULTS_PER_CHECK; ++j)
- {
- BigInteger k = ks[ki];
- p = g.multiply(k);
- if ((ki & 1) != 0)
- {
- g = p;
- }
- if (++ki == ks.length)
- {
- ki = 0;
- }
- }
-
- endTime = Times.nanoTime();
- }
- while (endTime < goalTime);
-
- double roundElapsed = (double)(endTime - startTime);
- double roundRate = count * MULTS_PER_CHECK * 1000000000L / roundElapsed;
-
- minRate = Math.min(minRate, roundRate);
- maxRate = Math.max(maxRate, roundRate);
- totalRate += roundRate;
- }
-
- return (totalRate - minRate - maxRate) / (NUM_ROUNDS - 2);
- }
-
- public void testMultiply() throws Exception
- {
- SortedSet names = new TreeSet(AllTests.enumToList(ECNamedCurveTable.getNames()));
- names.addAll(AllTests.enumToList(CustomNamedCurves.getNames()));
-
- Set oids = new HashSet();
-
- Iterator it = names.iterator();
- while (it.hasNext())
- {
- String name = (String)it.next();
- ASN1ObjectIdentifier oid = ECNamedCurveTable.getOID(name);
- if (oid == null)
- {
- oid = CustomNamedCurves.getOID(name);
- }
- if (oid != null && !oids.add(oid))
- {
- continue;
- }
-
- randMult(name);
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/math/ec/test/ECPointTest.java b/core/src/test/java/org/bouncycastle/math/ec/test/ECPointTest.java
deleted file mode 100644
index efd6aca0..00000000
--- a/core/src/test/java/org/bouncycastle/math/ec/test/ECPointTest.java
+++ /dev/null
@@ -1,521 +0,0 @@
-package org.bouncycastle.math.ec.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-import org.bouncycastle.asn1.x9.ECNamedCurveTable;
-import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.crypto.ec.CustomNamedCurves;
-import org.bouncycastle.math.ec.ECAlgorithms;
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.util.BigIntegers;
-
-/**
- * Test class for {@link org.bouncycastle.math.ec.ECPoint ECPoint}. All
- * literature values are taken from "Guide to elliptic curve cryptography",
- * Darrel Hankerson, Alfred J. Menezes, Scott Vanstone, 2004, Springer-Verlag
- * New York, Inc.
- */
-public class ECPointTest extends TestCase
-{
- /**
- * Random source used to generate random points
- */
- private SecureRandom secRand = new SecureRandom();
-
- private ECPointTest.Fp fp = null;
-
- private ECPointTest.F2m f2m = null;
-
- /**
- * Nested class containing sample literature values for <code>Fp</code>.
- */
- public static class Fp
- {
- private final BigInteger q = new BigInteger("29");
-
- private final BigInteger a = new BigInteger("4");
-
- private final BigInteger b = new BigInteger("20");
-
- private final BigInteger n = new BigInteger("38");
-
- private final BigInteger h = new BigInteger("1");
-
- private final ECCurve curve = new ECCurve.Fp(q, a, b, n, h);
-
- private final ECPoint infinity = curve.getInfinity();
-
- private final int[] pointSource = { 5, 22, 16, 27, 13, 6, 14, 6 };
-
- private ECPoint[] p = new ECPoint[pointSource.length / 2];
-
- /**
- * Creates the points on the curve with literature values.
- */
- private void createPoints()
- {
- for (int i = 0; i < pointSource.length / 2; i++)
- {
- p[i] = curve.createPoint(
- new BigInteger(Integer.toString(pointSource[2 * i])),
- new BigInteger(Integer.toString(pointSource[2 * i + 1])));
- }
- }
- }
-
- /**
- * Nested class containing sample literature values for <code>F2m</code>.
- */
- public static class F2m
- {
- // Irreducible polynomial for TPB z^4 + z + 1
- private final int m = 4;
-
- private final int k1 = 1;
-
- // a = z^3
- private final BigInteger aTpb = new BigInteger("1000", 2);
-
- // b = z^3 + 1
- private final BigInteger bTpb = new BigInteger("1001", 2);
-
- private final BigInteger n = new BigInteger("23");
-
- private final BigInteger h = new BigInteger("1");
-
- private final ECCurve.F2m curve = new ECCurve.F2m(m, k1, aTpb, bTpb, n, h);
-
- private final ECPoint.F2m infinity = (ECPoint.F2m) curve.getInfinity();
-
- private final String[] pointSource = { "0010", "1111", "1100", "1100",
- "0001", "0001", "1011", "0010" };
-
- private ECPoint[] p = new ECPoint[pointSource.length / 2];
-
- /**
- * Creates the points on the curve with literature values.
- */
- private void createPoints()
- {
- for (int i = 0; i < pointSource.length / 2; i++)
- {
- p[i] = curve.createPoint(
- new BigInteger(pointSource[2 * i], 2),
- new BigInteger(pointSource[2 * i + 1], 2));
- }
- }
- }
-
- public void setUp()
- {
- fp = new ECPointTest.Fp();
- fp.createPoints();
-
- f2m = new ECPointTest.F2m();
- f2m.createPoints();
- }
-
- /**
- * Tests, if inconsistent points can be created, i.e. points with exactly
- * one null coordinate (not permitted).
- */
- public void testPointCreationConsistency()
- {
- try
- {
- ECPoint bad = fp.curve.createPoint(new BigInteger("12"), null);
- fail();
- }
- catch (IllegalArgumentException expected)
- {
- }
-
- try
- {
- ECPoint bad = fp.curve.createPoint(null, new BigInteger("12"));
- fail();
- }
- catch (IllegalArgumentException expected)
- {
- }
-
- try
- {
- ECPoint bad = f2m.curve.createPoint(new BigInteger("1011"), null);
- fail();
- }
- catch (IllegalArgumentException expected)
- {
- }
-
- try
- {
- ECPoint bad = f2m.curve.createPoint(null, new BigInteger("1011"));
- fail();
- }
- catch (IllegalArgumentException expected)
- {
- }
- }
-
- /**
- * Tests <code>ECPoint.add()</code> against literature values.
- *
- * @param p
- * The array of literature values.
- * @param infinity
- * The point at infinity on the respective curve.
- */
- private void implTestAdd(ECPoint[] p, ECPoint infinity)
- {
- assertPointsEqual("p0 plus p1 does not equal p2", p[2], p[0].add(p[1]));
- assertPointsEqual("p1 plus p0 does not equal p2", p[2], p[1].add(p[0]));
- for (int i = 0; i < p.length; i++)
- {
- assertPointsEqual("Adding infinity failed", p[i], p[i].add(infinity));
- assertPointsEqual("Adding to infinity failed", p[i], infinity.add(p[i]));
- }
- }
-
- /**
- * Calls <code>implTestAdd()</code> for <code>Fp</code> and
- * <code>F2m</code>.
- */
- public void testAdd()
- {
- implTestAdd(fp.p, fp.infinity);
- implTestAdd(f2m.p, f2m.infinity);
- }
-
- /**
- * Tests <code>ECPoint.twice()</code> against literature values.
- *
- * @param p
- * The array of literature values.
- */
- private void implTestTwice(ECPoint[] p)
- {
- assertPointsEqual("Twice incorrect", p[3], p[0].twice());
- assertPointsEqual("Add same point incorrect", p[3], p[0].add(p[0]));
- }
-
- /**
- * Calls <code>implTestTwice()</code> for <code>Fp</code> and
- * <code>F2m</code>.
- */
- public void testTwice()
- {
- implTestTwice(fp.p);
- implTestTwice(f2m.p);
- }
-
- private void implTestThreeTimes(ECPoint[] p)
- {
- ECPoint P = p[0];
- ECPoint _3P = P.add(P).add(P);
- assertPointsEqual("ThreeTimes incorrect", _3P, P.threeTimes());
- assertPointsEqual("TwicePlus incorrect", _3P, P.twicePlus(P));
- }
-
- /**
- * Calls <code>implTestThreeTimes()</code> for <code>Fp</code> and
- * <code>F2m</code>.
- */
- public void testThreeTimes()
- {
- implTestThreeTimes(fp.p);
- implTestThreeTimes(f2m.p);
- }
-
- /**
- * Goes through all points on an elliptic curve and checks, if adding a
- * point <code>k</code>-times is the same as multiplying the point by
- * <code>k</code>, for all <code>k</code>. Should be called for points
- * on very small elliptic curves only.
- *
- * @param p
- * The base point on the elliptic curve.
- * @param infinity
- * The point at infinity on the elliptic curve.
- */
- private void implTestAllPoints(ECPoint p, ECPoint infinity)
- {
- ECPoint adder = infinity;
- ECPoint multiplier = infinity;
-
- BigInteger i = BigInteger.valueOf(1);
- do
- {
- adder = adder.add(p);
- multiplier = p.multiply(i);
- assertPointsEqual("Results of add() and multiply() are inconsistent "
- + i, adder, multiplier);
- i = i.add(BigInteger.ONE);
- }
- while (!(adder.equals(infinity)));
- }
-
- /**
- * Calls <code>implTestAllPoints()</code> for the small literature curves,
- * both for <code>Fp</code> and <code>F2m</code>.
- */
- public void testAllPoints()
- {
- for (int i = 0; i < fp.p.length; i++)
- {
- implTestAllPoints(fp.p[0], fp.infinity);
- }
-
- for (int i = 0; i < f2m.p.length; i++)
- {
- implTestAllPoints(f2m.p[0], f2m.infinity);
- }
- }
-
- /**
- * Checks, if the point multiplication algorithm of the given point yields
- * the same result as point multiplication done by the reference
- * implementation given in <code>multiply()</code>. This method chooses a
- * random number by which the given point <code>p</code> is multiplied.
- *
- * @param p
- * The point to be multiplied.
- * @param numBits
- * The bitlength of the random number by which <code>p</code>
- * is multiplied.
- */
- private void implTestMultiply(ECPoint p, int numBits)
- {
- BigInteger k = new BigInteger(numBits, secRand);
- ECPoint ref = ECAlgorithms.referenceMultiply(p, k);
- ECPoint q = p.multiply(k);
- assertPointsEqual("ECPoint.multiply is incorrect", ref, q);
- }
-
- /**
- * Checks, if the point multiplication algorithm of the given point yields
- * the same result as point multiplication done by the reference
- * implementation given in <code>multiply()</code>. This method tests
- * multiplication of <code>p</code> by every number of bitlength
- * <code>numBits</code> or less.
- *
- * @param p
- * The point to be multiplied.
- * @param numBits
- * Try every multiplier up to this bitlength
- */
- private void implTestMultiplyAll(ECPoint p, int numBits)
- {
- BigInteger bound = BigInteger.ONE.shiftLeft(numBits);
- BigInteger k = BigInteger.ZERO;
-
- do
- {
- ECPoint ref = ECAlgorithms.referenceMultiply(p, k);
- ECPoint q = p.multiply(k);
- assertPointsEqual("ECPoint.multiply is incorrect", ref, q);
- k = k.add(BigInteger.ONE);
- }
- while (k.compareTo(bound) < 0);
- }
-
- /**
- * Tests <code>ECPoint.add()</code> and <code>ECPoint.subtract()</code>
- * for the given point and the given point at infinity.
- *
- * @param p
- * The point on which the tests are performed.
- * @param infinity
- * The point at infinity on the same curve as <code>p</code>.
- */
- private void implTestAddSubtract(ECPoint p, ECPoint infinity)
- {
- assertPointsEqual("Twice and Add inconsistent", p.twice(), p.add(p));
- assertPointsEqual("Twice p - p is not p", p, p.twice().subtract(p));
- assertPointsEqual("TwicePlus(p, -p) is not p", p, p.twicePlus(p.negate()));
- assertPointsEqual("p - p is not infinity", infinity, p.subtract(p));
- assertPointsEqual("p plus infinity is not p", p, p.add(infinity));
- assertPointsEqual("infinity plus p is not p", p, infinity.add(p));
- assertPointsEqual("infinity plus infinity is not infinity ", infinity, infinity.add(infinity));
- assertPointsEqual("Twice infinity is not infinity ", infinity, infinity.twice());
- }
-
- /**
- * Calls <code>implTestAddSubtract()</code> for literature values, both
- * for <code>Fp</code> and <code>F2m</code>.
- */
- public void testAddSubtractMultiplySimple()
- {
- int fpBits = fp.curve.getOrder().bitLength();
- for (int iFp = 0; iFp < fp.pointSource.length / 2; iFp++)
- {
- implTestAddSubtract(fp.p[iFp], fp.infinity);
-
- implTestMultiplyAll(fp.p[iFp], fpBits);
- implTestMultiplyAll(fp.infinity, fpBits);
- }
-
- int f2mBits = f2m.curve.getOrder().bitLength();
- for (int iF2m = 0; iF2m < f2m.pointSource.length / 2; iF2m++)
- {
- implTestAddSubtract(f2m.p[iF2m], f2m.infinity);
-
- implTestMultiplyAll(f2m.p[iF2m], f2mBits);
- implTestMultiplyAll(f2m.infinity, f2mBits);
- }
- }
-
- /**
- * Test encoding with and without point compression.
- *
- * @param p
- * The point to be encoded and decoded.
- */
- private void implTestEncoding(ECPoint p)
- {
- // Not Point Compression
- byte[] unCompBarr = p.getEncoded(false);
- ECPoint decUnComp = p.getCurve().decodePoint(unCompBarr);
- assertPointsEqual("Error decoding uncompressed point", p, decUnComp);
-
- // Point compression
- byte[] compBarr = p.getEncoded(true);
- ECPoint decComp = p.getCurve().decodePoint(compBarr);
- assertPointsEqual("Error decoding compressed point", p, decComp);
- }
-
- private void implAddSubtractMultiplyTwiceEncodingTest(ECCurve curve, ECPoint q, BigInteger n)
- {
- // Get point at infinity on the curve
- ECPoint infinity = curve.getInfinity();
-
- implTestAddSubtract(q, infinity);
- implTestMultiply(q, n.bitLength());
- implTestMultiply(infinity, n.bitLength());
-
- ECPoint p = q;
- for (int i = 0; i < 10; ++i)
- {
- implTestEncoding(p);
- p = p.twice();
- }
- }
-
- private void implSqrtTest(ECCurve c)
- {
- if (ECAlgorithms.isFpCurve(c))
- {
- BigInteger p = c.getField().getCharacteristic();
- BigInteger pMinusOne = p.subtract(ECConstants.ONE);
- BigInteger legendreExponent = p.shiftRight(1);
-
- int count = 0;
- while (count < 10)
- {
- BigInteger nonSquare = BigIntegers.createRandomInRange(ECConstants.TWO, pMinusOne, secRand);
- if (!nonSquare.modPow(legendreExponent, p).equals(ECConstants.ONE))
- {
- ECFieldElement root = c.fromBigInteger(nonSquare).sqrt();
- assertNull(root);
- ++count;
- }
- }
- }
- }
-
- private void implAddSubtractMultiplyTwiceEncodingTestAllCoords(X9ECParameters x9ECParameters)
- {
- BigInteger n = x9ECParameters.getN();
- ECPoint G = x9ECParameters.getG();
- ECCurve C = x9ECParameters.getCurve();
-
- int[] coords = ECCurve.getAllCoordinateSystems();
- for (int i = 0; i < coords.length; ++i)
- {
- int coord = coords[i];
- if (C.supportsCoordinateSystem(coord))
- {
- ECCurve c = C;
- ECPoint g = G;
-
- if (c.getCoordinateSystem() != coord)
- {
- c = C.configure().setCoordinateSystem(coord).create();
- g = c.importPoint(G);
- }
-
- // The generator is multiplied by random b to get random q
- BigInteger b = new BigInteger(n.bitLength(), secRand);
- ECPoint q = g.multiply(b).normalize();
-
- implAddSubtractMultiplyTwiceEncodingTest(c, q, n);
-
- implSqrtTest(c);
- }
- }
- }
-
- /**
- * Calls <code>implTestAddSubtract()</code>,
- * <code>implTestMultiply</code> and <code>implTestEncoding</code> for
- * the standard elliptic curves as given in <code>SECNamedCurves</code>.
- */
- public void testAddSubtractMultiplyTwiceEncoding()
- {
- Set names = new HashSet(enumToList(ECNamedCurveTable.getNames()));
- names.addAll(enumToList(CustomNamedCurves.getNames()));
-
- Iterator it = names.iterator();
- while (it.hasNext())
- {
- String name = (String)it.next();
-
- X9ECParameters x9ECParameters = ECNamedCurveTable.getByName(name);
- if (x9ECParameters != null)
- {
- implAddSubtractMultiplyTwiceEncodingTestAllCoords(x9ECParameters);
- }
-
- x9ECParameters = CustomNamedCurves.getByName(name);
- if (x9ECParameters != null)
- {
- implAddSubtractMultiplyTwiceEncodingTestAllCoords(x9ECParameters);
- }
- }
- }
-
- private List enumToList(Enumeration en)
- {
- List rv = new ArrayList();
-
- while (en.hasMoreElements())
- {
- rv.add(en.nextElement());
- }
-
- return rv;
- }
-
- private void assertPointsEqual(String message, ECPoint a, ECPoint b)
- {
- assertEquals(message, a, b);
- }
-
- public static Test suite()
- {
- return new TestSuite(ECPointTest.class);
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/math/ec/test/F2mProofer.java b/core/src/test/java/org/bouncycastle/math/ec/test/F2mProofer.java
deleted file mode 100644
index f113482e..00000000
--- a/core/src/test/java/org/bouncycastle/math/ec/test/F2mProofer.java
+++ /dev/null
@@ -1,203 +0,0 @@
-package org.bouncycastle.math.ec.test;
-
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.util.Iterator;
-import java.util.Properties;
-import java.util.Set;
-
-import org.bouncycastle.asn1.sec.SECNamedCurves;
-import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECPoint;
-
-public class F2mProofer
-{
- private static final int NUM_SAMPLES = 1000;
-
- private static final String PATH = "crypto/test/src/org/bouncycastle/math/ec/test/samples/";
-
- private static final String INPUT_FILE_NAME_PREFIX = "Input_";
-
- private static final String RESULT_FILE_NAME_PREFIX = "Output_";
-
- /**
- * The standard curves on which the tests are done
- */
- public static final String[] CURVES = { "sect163r2", "sect233r1",
- "sect283r1", "sect409r1", "sect571r1" };
-
- private String pointToString(ECPoint.F2m p)
- {
- ECFieldElement.F2m x = (ECFieldElement.F2m) p.getAffineXCoord();
- ECFieldElement.F2m y = (ECFieldElement.F2m) p.getAffineYCoord();
-
- int m = x.getM();
- int len = m / 2 + 5;
-
- StringBuffer sb = new StringBuffer(len);
- sb.append('(');
- sb.append(x.toBigInteger().toString(16));
- sb.append(", ");
- sb.append(y.toBigInteger().toString(16));
- sb.append(')');
-
- return sb.toString();
- }
-
- private void generateRandomInput(X9ECParameters x9ECParameters)
- throws NoSuchAlgorithmException, IOException
- {
- ECPoint.F2m g = (ECPoint.F2m) x9ECParameters.getG();
- int m = ((ECFieldElement.F2m) (g.getAffineXCoord())).getM();
-
- SecureRandom secRand = SecureRandom.getInstance("SHA1PRNG");
- Properties inputProps = new Properties();
- for (int i = 0; i < NUM_SAMPLES; i++)
- {
- BigInteger rand = new BigInteger(m, secRand);
- inputProps.put(Integer.toString(i), rand.toString(16));
- }
- String bits = Integer.toString(m);
- FileOutputStream fos = new FileOutputStream(PATH
- + INPUT_FILE_NAME_PREFIX + bits + ".properties");
- inputProps.store(fos, "Input Samples of length" + bits);
- }
-
- private void multiplyPoints(X9ECParameters x9ECParameters,
- String classPrefix) throws IOException
- {
- ECPoint.F2m g = (ECPoint.F2m) x9ECParameters.getG();
- int m = ((ECFieldElement.F2m) (g.getAffineXCoord())).getM();
-
- String inputFileName = PATH + INPUT_FILE_NAME_PREFIX + m
- + ".properties";
- Properties inputProps = new Properties();
- inputProps.load(new FileInputStream(inputFileName));
-
- Properties outputProps = new Properties();
-
- for (int i = 0; i < NUM_SAMPLES; i++)
- {
- BigInteger rand = new BigInteger(inputProps.getProperty(Integer
- .toString(i)), 16);
- ECPoint.F2m result = (ECPoint.F2m) g.multiply(rand).normalize();
- String resultStr = pointToString(result);
- outputProps.setProperty(Integer.toString(i), resultStr);
- }
-
- String outputFileName = PATH + RESULT_FILE_NAME_PREFIX + classPrefix
- + "_" + m + ".properties";
- FileOutputStream fos = new FileOutputStream(outputFileName);
- outputProps.store(fos, "Output Samples of length" + m);
- }
-
- private Properties loadResults(String classPrefix, int m)
- throws IOException
- {
- FileInputStream fis = new FileInputStream(PATH
- + RESULT_FILE_NAME_PREFIX + classPrefix + "_" + m + ".properties");
- Properties res = new Properties();
- res.load(fis);
- return res;
-
- }
-
- private void compareResult(X9ECParameters x9ECParameters,
- String classPrefix1, String classPrefix2) throws IOException
- {
- ECPoint.F2m g = (ECPoint.F2m) x9ECParameters.getG();
- int m = ((ECFieldElement.F2m) (g.getAffineXCoord())).getM();
-
- Properties res1 = loadResults(classPrefix1, m);
- Properties res2 = loadResults(classPrefix2, m);
-
- Set keys = res1.keySet();
- Iterator iter = keys.iterator();
- while (iter.hasNext())
- {
- String key = (String) iter.next();
- String result1 = res1.getProperty(key);
- String result2 = res2.getProperty(key);
- if (!(result1.equals(result2)))
- {
- System.err.println("Difference found: m = " + m + ", "
- + result1 + " does not equal " + result2);
- }
- }
-
- }
-
- private static void usage()
- {
- System.err.println("Usage: F2mProofer [-init | -multiply <className> "
- + "| -compare <className1> <className2>]");
- }
-
- public static void main(String[] args) throws Exception
- {
- if (args.length == 0)
- {
- usage();
- return;
- }
- F2mProofer proofer = new F2mProofer();
- if (args[0].equals("-init"))
- {
- System.out.println("Generating random input...");
- for (int i = 0; i < CURVES.length; i++)
- {
- X9ECParameters x9ECParameters = SECNamedCurves
- .getByName(CURVES[i]);
- proofer.generateRandomInput(x9ECParameters);
- }
- System.out
- .println("Successfully generated random input in " + PATH);
- }
- else if (args[0].equals("-compare"))
- {
- if (args.length < 3)
- {
- usage();
- return;
- }
- String classPrefix1 = args[1];
- String classPrefix2 = args[2];
- System.out.println("Comparing results...");
- for (int i = 0; i < CURVES.length; i++)
- {
- X9ECParameters x9ECParameters = SECNamedCurves
- .getByName(CURVES[i]);
- proofer.compareResult(x9ECParameters, classPrefix1,
- classPrefix2);
- }
- System.out.println("Successfully compared results in " + PATH);
- }
- else if (args[0].equals("-multiply"))
- {
- if (args.length < 2)
- {
- usage();
- return;
- }
- String classPrefix = args[1];
- System.out.println("Multiplying points...");
- for (int i = 0; i < CURVES.length; i++)
- {
- X9ECParameters x9ECParameters = SECNamedCurves
- .getByName(CURVES[i]);
- proofer.multiplyPoints(x9ECParameters, classPrefix);
- }
- System.out.println("Successfully generated multiplied points in "
- + PATH);
- }
- else
- {
- usage();
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/math/ec/test/TnafTest.java b/core/src/test/java/org/bouncycastle/math/ec/test/TnafTest.java
deleted file mode 100644
index 9400f6c5..00000000
--- a/core/src/test/java/org/bouncycastle/math/ec/test/TnafTest.java
+++ /dev/null
@@ -1,152 +0,0 @@
-//package org.bouncycastle.math.ec.test;
-//
-//import java.math.BigInteger;
-//import java.util.Random;
-//
-//import junit.framework.TestCase;
-//
-//import org.bouncycastle.asn1.sec.SECNamedCurves;
-//import org.bouncycastle.asn1.x9.X9ECParameters;
-//import org.bouncycastle.math.ec.ECCurve;
-//import org.bouncycastle.math.ec.ECPoint;
-//import org.bouncycastle.math.ec.NafL2RMultiplier;
-//import org.bouncycastle.math.ec.ReferenceMultiplier;
-//import org.bouncycastle.math.ec.WNafL2RMultiplier;
-//import org.bouncycastle.math.ec.WTauNafMultiplier;
-//
-//public class TnafTest extends TestCase
-//{
-// private Random m_rand = new Random();
-//
-// private String ecPointToString(ECPoint p) {
-// StringBuffer sb = new StringBuffer("x = ");
-// sb.append(p.getX().toBigInteger().toString());
-// sb.append("; y = ");
-// sb.append(p.getY().toBigInteger().toString());
-// return sb.toString();
-// }
-//
-// private ECPoint repeatedMultiply(ECPoint p, BigInteger k)
-// {
-// ECPoint result = p.multiply(k);
-// for (int i = 1; i < 10; ++i)
-// {
-// ECPoint check = p.multiply(k);
-// assertEquals(result, check);
-// }
-// return result;
-// }
-//
-// private void implTestMultiplyTnaf(String curveName) {
-// X9ECParameters x9ECParameters = SECNamedCurves.getByName(curveName);
-//
-// ECCurve.F2m curve = (ECCurve.F2m)x9ECParameters.getCurve();
-// BigInteger n = curve.getN();
-//
-// // The generator is multiplied by random b to get random q
-// BigInteger b = new BigInteger(n.bitLength(), m_rand);
-// ECPoint g = x9ECParameters.getG();
-// ECPoint.F2m p = (ECPoint.F2m)g.multiply(b);
-//
-// BigInteger k = new BigInteger(n.bitLength(), m_rand);
-// long now1 = System.currentTimeMillis();
-// p.setECMultiplier(new WTauNafMultiplier());
-// ECPoint refRWTnaf = repeatedMultiply(p, k);
-// long now2 = System.currentTimeMillis();
-// p.setECMultiplier(new WNafL2RMultiplier());
-// ECPoint refWnaf = repeatedMultiply(p, k);
-// long now3 = System.currentTimeMillis();
-// p.setECMultiplier(new NafL2RMultiplier());
-// ECPoint refFpNaf = repeatedMultiply(p, k);
-// long now4 = System.currentTimeMillis();
-// p.setECMultiplier(new ReferenceMultiplier());
-// ECPoint reference = repeatedMultiply(p, k);
-// long now5 = System.currentTimeMillis();
-//
-// assertEquals("WTNAF multiplication is incorrect", refRWTnaf, reference);
-// assertEquals("FPNAF multiplication is incorrect", refFpNaf, reference);
-// assertEquals("WNAF multiplication is incorrect", refWnaf, reference);
-//
-// System.out.println(curveName + ": Multiply WTNAF took millis: " + (now2 - now1));
-// System.out.println(curveName + ": Multiply WNAF took millis: " + (now3 - now2));
-// System.out.println(curveName + ": Multiply FPNAF took millis: " + (now4 - now3));
-// System.out.println(curveName + ": Multiply REFE took millis: " + (now5 - now4));
-//
-//// System.out.println(curveName + ": refRWTnaf = " + ecPointToString(refRWTnaf));
-//// System.out.println(curveName + ": refWnaf = " + ecPointToString(refWnaf));
-//// System.out.println(curveName + ": refFpNaf = " + ecPointToString(refFpNaf));
-//// System.out.println(curveName + ": reference = " + ecPointToString(reference) + "\n");
-// System.out.println();
-// }
-//
-// public void testMultiplyTnaf() {
-// System.out.println("\n\n\n***** Start test multiplications on F2m (Koblitz) *****");
-// implTestMultiplyTnaf("sect163k1");
-// implTestMultiplyTnaf("sect233k1");
-// implTestMultiplyTnaf("sect239k1");
-// implTestMultiplyTnaf("sect283k1");
-// implTestMultiplyTnaf("sect409k1");
-// implTestMultiplyTnaf("sect571k1");
-// }
-//
-// private void implTestMultiplyWnaf(String curveName) {
-// X9ECParameters x9ECParameters = SECNamedCurves.getByName(curveName);
-//
-// BigInteger r = x9ECParameters.getN();
-//
-// // The generator is multiplied by random b to get random q
-// BigInteger b = new BigInteger(r.bitLength(), m_rand);
-// ECPoint g = x9ECParameters.getG();
-// ECPoint p = g.multiply(b);
-//
-// BigInteger k = new BigInteger(r.bitLength(), m_rand);
-// long now1 = System.currentTimeMillis();
-// p.setECMultiplier(new WNafL2RMultiplier());
-// ECPoint refWnaf = repeatedMultiply(p, k);
-// long now2 = System.currentTimeMillis();
-// p.setECMultiplier(new NafL2RMultiplier());
-// ECPoint refFpNaf = repeatedMultiply(p, k);
-// long now3 = System.currentTimeMillis();
-// p.setECMultiplier(new ReferenceMultiplier());
-// ECPoint reference = repeatedMultiply(p, k);
-// long now4 = System.currentTimeMillis();
-//
-// assertEquals("WNAF multiplication is incorrect", refWnaf, reference);
-// assertEquals("FPNAF multiplication is incorrect", refFpNaf, reference);
-//
-// System.out.println(curveName + ": Multiply WNAF took millis: " + (now2 - now1));
-// System.out.println(curveName + ": Multiply FPNAF took millis: " + (now3 - now2));
-// System.out.println(curveName + ": Multiply REFE took millis: " + (now4 - now3));
-//
-//// System.out.println(curveName + ": refWnaf = " + ecPointToString(refWnaf));
-//// System.out.println(curveName + ": refFpNaf = " + ecPointToString(refFpNaf));
-//// System.out.println(curveName + ": reference = " + ecPointToString(reference));
-// System.out.println();
-// }
-//
-// public void testMultiplyWnaf() {
-// System.out.println("\n\n\n***** Start test multiplications on F2m *****");
-// implTestMultiplyWnaf("sect113r1");
-// implTestMultiplyWnaf("sect113r2");
-// implTestMultiplyWnaf("sect131r1");
-// implTestMultiplyWnaf("sect131r2");
-// implTestMultiplyWnaf("sect163r1");
-// implTestMultiplyWnaf("sect163r2");
-// implTestMultiplyWnaf("sect193r1");
-// implTestMultiplyWnaf("sect193r2");
-// implTestMultiplyWnaf("sect233r1");
-// implTestMultiplyWnaf("sect283r1");
-// implTestMultiplyWnaf("sect409r1");
-// implTestMultiplyWnaf("sect571r1");
-//
-// System.out.println("\n\n\n***** Start test multiplications on Fp *****");
-// implTestMultiplyWnaf("secp112r1");
-// implTestMultiplyWnaf("secp128r1");
-// implTestMultiplyWnaf("secp160r1");
-// implTestMultiplyWnaf("secp192r1");
-// implTestMultiplyWnaf("secp224r1");
-// implTestMultiplyWnaf("secp256r1");
-// implTestMultiplyWnaf("secp384r1");
-// implTestMultiplyWnaf("secp521r1");
-// }
-//}
diff --git a/core/src/test/java/org/bouncycastle/pqc/crypto/test/AllTests.java b/core/src/test/java/org/bouncycastle/pqc/crypto/test/AllTests.java
deleted file mode 100644
index 4559fdb9..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/crypto/test/AllTests.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.bouncycastle.pqc.crypto.test;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-import org.bouncycastle.util.test.SimpleTestResult;
-
-public class AllTests
- extends TestCase
-{
- public void testCrypto()
- {
- org.bouncycastle.util.test.Test[] tests = RegressionTest.tests;
-
- for (int i = 0; i != tests.length; i++)
- {
- SimpleTestResult result = (SimpleTestResult)tests[i].perform();
-
- if (!result.isSuccessful())
- {
- fail(result.toString());
- }
- }
- }
-
- public static void main (String[] args)
- {
- junit.textui.TestRunner.run(suite());
- }
-
- public static Test suite()
- {
- TestSuite suite = new TestSuite("Lightweight PQ Crypto Tests");
-
- suite.addTestSuite(AllTests.class);
- suite.addTestSuite(BitStringTest.class);
- suite.addTestSuite(EncryptionKeyTest.class);
- suite.addTestSuite(NTRUEncryptionParametersTest.class);
- suite.addTestSuite(NTRUEncryptTest.class);
- suite.addTestSuite(NTRUSignatureParametersTest.class);
- suite.addTestSuite(NTRUSignatureKeyTest.class);
- suite.addTestSuite(NTRUSignerTest.class);
- suite.addTestSuite(NTRUSigningParametersTest.class);
-
- return suite;
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/pqc/crypto/test/BitStringTest.java b/core/src/test/java/org/bouncycastle/pqc/crypto/test/BitStringTest.java
deleted file mode 100644
index 85e1ffaa..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/crypto/test/BitStringTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package org.bouncycastle.pqc.crypto.test;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.crypto.ntru.IndexGenerator.BitString;
-import org.bouncycastle.util.Arrays;
-
-public class BitStringTest
- extends TestCase
-{
- public void testAppendBitsByteArray()
- {
- BitString bs = new BitString();
- bs.appendBits((byte)78);
- assertBitStringEquals(bs, new byte[]{78});
- bs.appendBits((byte)-5);
- assertBitStringEquals(bs, new byte[]{78, -5});
- bs.appendBits((byte)127);
- assertBitStringEquals(bs, new byte[]{78, -5, 127});
- bs.appendBits((byte)0);
- assertBitStringEquals(bs, new byte[]{78, -5, 127, 0});
- bs.appendBits((byte)100);
- assertBitStringEquals(bs, new byte[]{78, -5, 127, 0, 100});
- }
-
- private void assertBitStringEquals(BitString bs, byte[] arr)
- {
- byte[] bsBytes = bs.getBytes();
-
- assertTrue(bsBytes.length >= arr.length);
- arr = copyOf(arr, bsBytes.length);
- assertTrue(Arrays.areEqual(arr, bsBytes));
- }
-
- public void testGetTrailing()
- {
- BitString bs = new BitString();
- bs.appendBits((byte)78);
- BitString bs2 = bs.getTrailing(3);
- assertBitStringEquals(bs2, new byte[]{6});
-
- bs = new BitString();
- bs.appendBits((byte)78);
- bs.appendBits((byte)-5);
- bs2 = bs.getTrailing(9);
- assertBitStringEquals(bs2, new byte[]{78, 1});
-
- bs2.appendBits((byte)100);
- assertBitStringEquals(bs2, new byte[]{78, -55});
- bs = bs2.getTrailing(13);
- assertBitStringEquals(bs, new byte[]{78, 9});
- bs2 = bs2.getTrailing(11);
- assertBitStringEquals(bs2, new byte[]{78, 1});
-
- bs2.appendBits((byte)100);
- assertBitStringEquals(bs2, new byte[]{78, 33, 3});
- bs2 = bs2.getTrailing(16);
- assertBitStringEquals(bs2, new byte[]{78, 33});
- }
-
- public void testGetLeadingAsInt()
- {
- BitString bs = new BitString();
- bs.appendBits((byte)78);
- bs.appendBits((byte)42);
- assertEquals(1, bs.getLeadingAsInt(3));
- assertEquals(84, bs.getLeadingAsInt(9));
- assertEquals(338, bs.getLeadingAsInt(11));
-
- BitString bs2 = bs.getTrailing(11);
- assertBitStringEquals(bs2, new byte[]{78, 2});
- assertEquals(590, bs2.getLeadingAsInt(11));
- assertEquals(9, bs2.getLeadingAsInt(5));
-
- bs2.appendBits((byte)115);
- assertEquals(230, bs2.getLeadingAsInt(9));
- assertEquals(922, bs2.getLeadingAsInt(11));
-
- bs2.appendBits((byte)-36);
- assertEquals(55, bs2.getLeadingAsInt(6));
- }
-
- private byte[] copyOf(byte[] src, int length)
- {
- byte[] tmp = new byte[length];
- System.arraycopy(src, 0, tmp, 0, tmp.length > src.length ? src.length : tmp.length);
- return tmp;
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/pqc/crypto/test/EncryptionKeyTest.java b/core/src/test/java/org/bouncycastle/pqc/crypto/test/EncryptionKeyTest.java
deleted file mode 100644
index f0234063..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/crypto/test/EncryptionKeyTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package org.bouncycastle.pqc.crypto.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-import junit.framework.TestCase;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.pqc.crypto.ntru.NTRUEncryptionKeyPairGenerator;
-import org.bouncycastle.pqc.crypto.ntru.NTRUEncryptionKeyGenerationParameters;
-import org.bouncycastle.pqc.crypto.ntru.NTRUEncryptionPrivateKeyParameters;
-import org.bouncycastle.pqc.crypto.ntru.NTRUEncryptionPublicKeyParameters;
-
-public class EncryptionKeyTest
- extends TestCase
-{
- public void testEncode()
- throws IOException
- {
- for (NTRUEncryptionKeyGenerationParameters params : new NTRUEncryptionKeyGenerationParameters[]{NTRUEncryptionKeyGenerationParameters.APR2011_743, NTRUEncryptionKeyGenerationParameters.APR2011_743_FAST, NTRUEncryptionKeyGenerationParameters.EES1499EP1})
- {
- testEncode(params);
- }
- }
-
- private void testEncode(NTRUEncryptionKeyGenerationParameters params)
- throws IOException
- {
- NTRUEncryptionKeyPairGenerator kpGen = new NTRUEncryptionKeyPairGenerator();
-
- kpGen.init(params);
-
- AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();
- byte[] priv = ((NTRUEncryptionPrivateKeyParameters)kp.getPrivate()).getEncoded();
- byte[] pub = ((NTRUEncryptionPublicKeyParameters)kp.getPublic()).getEncoded();
-
- AsymmetricCipherKeyPair kp2 = new AsymmetricCipherKeyPair(new NTRUEncryptionPublicKeyParameters(pub, params.getEncryptionParameters()), new NTRUEncryptionPrivateKeyParameters(priv, params.getEncryptionParameters()));
- assertEquals(kp.getPublic(), kp2.getPublic());
- assertEquals(kp.getPrivate(), kp2.getPrivate());
-
- ByteArrayOutputStream bos1 = new ByteArrayOutputStream();
- ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
- ((NTRUEncryptionPrivateKeyParameters)kp.getPrivate()).writeTo(bos1);
- ((NTRUEncryptionPublicKeyParameters)kp.getPublic()).writeTo(bos2);
- ByteArrayInputStream bis1 = new ByteArrayInputStream(bos1.toByteArray());
- ByteArrayInputStream bis2 = new ByteArrayInputStream(bos2.toByteArray());
- AsymmetricCipherKeyPair kp3 = new AsymmetricCipherKeyPair(new NTRUEncryptionPublicKeyParameters(bis2, params.getEncryptionParameters()), new NTRUEncryptionPrivateKeyParameters(bis1, params.getEncryptionParameters()));
- assertEquals(kp.getPublic(), kp3.getPublic());
- assertEquals(kp.getPrivate(), kp3.getPrivate());
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/pqc/crypto/test/GMSSSignerTest.java b/core/src/test/java/org/bouncycastle/pqc/crypto/test/GMSSSignerTest.java
deleted file mode 100644
index 69b28428..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/crypto/test/GMSSSignerTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package org.bouncycastle.pqc.crypto.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.Signer;
-import org.bouncycastle.crypto.digests.SHA224Digest;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.pqc.crypto.DigestingMessageSigner;
-import org.bouncycastle.pqc.crypto.gmss.GMSSDigestProvider;
-import org.bouncycastle.pqc.crypto.gmss.GMSSKeyGenerationParameters;
-import org.bouncycastle.pqc.crypto.gmss.GMSSKeyPairGenerator;
-import org.bouncycastle.pqc.crypto.gmss.GMSSParameters;
-import org.bouncycastle.pqc.crypto.gmss.GMSSPrivateKeyParameters;
-import org.bouncycastle.pqc.crypto.gmss.GMSSSigner;
-import org.bouncycastle.util.BigIntegers;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.FixedSecureRandom;
-import org.bouncycastle.util.test.SimpleTest;
-
-
-public class GMSSSignerTest
- extends SimpleTest
-{
- byte[] keyData = Hex.decode("b5014e4b60ef2ba8b6211b4062ba3224e0427dd3");
-
- SecureRandom keyRandom = new FixedSecureRandom(new byte[][]{keyData, keyData});
-
- public String getName()
- {
- return "GMSS";
- }
-
- public void performTest()
- throws Exception
- {
-
- GMSSParameters params = new GMSSParameters(3,
- new int[]{15, 15, 10}, new int[]{5, 5, 4}, new int[]{3, 3, 2});
-
- GMSSDigestProvider digProvider = new GMSSDigestProvider()
- {
- public Digest get()
- {
- return new SHA224Digest();
- }
- };
-
- GMSSKeyPairGenerator gmssKeyGen = new GMSSKeyPairGenerator(digProvider);
-
- GMSSKeyGenerationParameters genParam = new GMSSKeyGenerationParameters(keyRandom, params);
-
- gmssKeyGen.init(genParam);
-
- AsymmetricCipherKeyPair pair = gmssKeyGen.generateKeyPair();
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), keyRandom);
-
- // TODO
- Signer gmssSigner = new DigestingMessageSigner(new GMSSSigner(digProvider), new SHA224Digest());
- gmssSigner.init(true, param);
-
- byte[] message = BigIntegers.asUnsignedByteArray(new BigInteger("968236873715988614170569073515315707566766479517"));
- gmssSigner.update(message, 0, message.length);
- byte[] sig = gmssSigner.generateSignature();
-
-
- gmssSigner.init(false, pair.getPublic());
- gmssSigner.update(message, 0, message.length);
- if (!gmssSigner.verifySignature(sig))
- {
- fail("verification fails");
- }
-
- if (!((GMSSPrivateKeyParameters)pair.getPrivate()).isUsed())
- {
- fail("private key not marked as used");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new GMSSSignerTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/pqc/crypto/test/McElieceFujisakiCipherTest.java b/core/src/test/java/org/bouncycastle/pqc/crypto/test/McElieceFujisakiCipherTest.java
deleted file mode 100644
index dfc44b65..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/crypto/test/McElieceFujisakiCipherTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package org.bouncycastle.pqc.crypto.test;
-
-import java.security.SecureRandom;
-import java.util.Random;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.pqc.crypto.mceliece.McElieceCCA2KeyGenerationParameters;
-import org.bouncycastle.pqc.crypto.mceliece.McElieceCCA2KeyPairGenerator;
-import org.bouncycastle.pqc.crypto.mceliece.McElieceCCA2Parameters;
-import org.bouncycastle.pqc.crypto.mceliece.McElieceFujisakiCipher;
-import org.bouncycastle.pqc.crypto.mceliece.McElieceFujisakiDigestCipher;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class McElieceFujisakiCipherTest
- extends SimpleTest
-{
-
- SecureRandom keyRandom = new SecureRandom();
-
- public String getName()
- {
- return "McElieceFujisaki";
-
- }
-
-
- public void performTest()
- {
- int numPassesKPG = 1;
- int numPassesEncDec = 10;
- Random rand = new Random();
- byte[] mBytes;
- for (int j = 0; j < numPassesKPG; j++)
- {
-
- McElieceCCA2Parameters params = new McElieceCCA2Parameters();
- McElieceCCA2KeyPairGenerator mcElieceCCA2KeyGen = new McElieceCCA2KeyPairGenerator();
- McElieceCCA2KeyGenerationParameters genParam = new McElieceCCA2KeyGenerationParameters(keyRandom, params);
-
- mcElieceCCA2KeyGen.init(genParam);
- AsymmetricCipherKeyPair pair = mcElieceCCA2KeyGen.generateKeyPair();
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPublic(), keyRandom);
- Digest msgDigest = new SHA256Digest();
- McElieceFujisakiDigestCipher mcElieceFujisakiDigestCipher = new McElieceFujisakiDigestCipher(new McElieceFujisakiCipher(), msgDigest);
-
-
- for (int k = 1; k <= numPassesEncDec; k++)
- {
- System.out.println("############### test: " + k);
- // initialize for encryption
- mcElieceFujisakiDigestCipher.init(true, param);
-
- // generate random message
- int mLength = (rand.nextInt() & 0x1f) + 1;;
- mBytes = new byte[mLength];
- rand.nextBytes(mBytes);
-
- // encrypt
- mcElieceFujisakiDigestCipher.update(mBytes, 0, mBytes.length);
- byte[] enc = mcElieceFujisakiDigestCipher.messageEncrypt();
-
- // initialize for decryption
- mcElieceFujisakiDigestCipher.init(false, pair.getPrivate());
- byte[] constructedmessage = mcElieceFujisakiDigestCipher.messageDecrypt(enc);
-
- // XXX write in McElieceFujisakiDigestCipher?
- msgDigest.update(mBytes, 0, mBytes.length);
- byte[] hash = new byte[msgDigest.getDigestSize()];
- msgDigest.doFinal(hash, 0);
-
- boolean verified = true;
- for (int i = 0; i < hash.length; i++)
- {
- verified = verified && hash[i] == constructedmessage[i];
- }
-
- if (!verified)
- {
- fail("en/decryption fails");
- }
- else
- {
- System.out.println("test okay");
- System.out.println();
- }
-
- }
- }
-
- }
-
- public static void main(
- String[] args)
- {
- runTest(new McElieceFujisakiCipherTest());
- }
-
-}
diff --git a/core/src/test/java/org/bouncycastle/pqc/crypto/test/McElieceKobaraImaiCipherTest.java b/core/src/test/java/org/bouncycastle/pqc/crypto/test/McElieceKobaraImaiCipherTest.java
deleted file mode 100644
index 849e656a..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/crypto/test/McElieceKobaraImaiCipherTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package org.bouncycastle.pqc.crypto.test;
-
-import java.security.SecureRandom;
-import java.util.Random;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.pqc.crypto.mceliece.McElieceCCA2KeyGenerationParameters;
-import org.bouncycastle.pqc.crypto.mceliece.McElieceCCA2KeyPairGenerator;
-import org.bouncycastle.pqc.crypto.mceliece.McElieceCCA2Parameters;
-import org.bouncycastle.pqc.crypto.mceliece.McElieceKobaraImaiCipher;
-import org.bouncycastle.pqc.crypto.mceliece.McElieceKobaraImaiDigestCipher;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class McElieceKobaraImaiCipherTest
- extends SimpleTest
-{
-
- SecureRandom keyRandom = new SecureRandom();
-
- public String getName()
- {
- return "McElieceKobaraImai";
-
- }
-
-
- public void performTest()
- {
- int numPassesKPG = 1;
- int numPassesEncDec = 10;
- Random rand = new Random();
- byte[] mBytes;
- for (int j = 0; j < numPassesKPG; j++)
- {
-
- McElieceCCA2Parameters params = new McElieceCCA2Parameters();
- McElieceCCA2KeyPairGenerator mcElieceCCA2KeyGen = new McElieceCCA2KeyPairGenerator();
- McElieceCCA2KeyGenerationParameters genParam = new McElieceCCA2KeyGenerationParameters(keyRandom, params);
-
- mcElieceCCA2KeyGen.init(genParam);
- AsymmetricCipherKeyPair pair = mcElieceCCA2KeyGen.generateKeyPair();
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPublic(), keyRandom);
- Digest msgDigest = new SHA256Digest();
- McElieceKobaraImaiDigestCipher mcElieceKobaraImaiDigestCipher = new McElieceKobaraImaiDigestCipher(new McElieceKobaraImaiCipher(), msgDigest);
-
-
- for (int k = 1; k <= numPassesEncDec; k++)
- {
- System.out.println("############### test: " + k);
- // initialize for encryption
- mcElieceKobaraImaiDigestCipher.init(true, param);
-
- // generate random message
- int mLength = (rand.nextInt() & 0x1f) + 1;
- mBytes = new byte[mLength];
- rand.nextBytes(mBytes);
-
- // encrypt
- mcElieceKobaraImaiDigestCipher.update(mBytes, 0, mBytes.length);
- byte[] enc = mcElieceKobaraImaiDigestCipher.messageEncrypt();
-
- // initialize for decryption
- mcElieceKobaraImaiDigestCipher.init(false, pair.getPrivate());
- byte[] constructedmessage = mcElieceKobaraImaiDigestCipher.messageDecrypt(enc);
-
- // XXX write in McElieceFujisakiDigestCipher?
- msgDigest.update(mBytes, 0, mBytes.length);
- byte[] hash = new byte[msgDigest.getDigestSize()];
- msgDigest.doFinal(hash, 0);
-
- boolean verified = true;
- for (int i = 0; i < hash.length; i++)
- {
- verified = verified && hash[i] == constructedmessage[i];
- }
-
- if (!verified)
- {
- fail("en/decryption fails");
- }
- else
- {
- System.out.println("test okay");
- System.out.println();
- }
-
- }
- }
-
- }
-
- public static void main(
- String[] args)
- {
- runTest(new McElieceKobaraImaiCipherTest());
- }
-
-}
diff --git a/core/src/test/java/org/bouncycastle/pqc/crypto/test/McEliecePKCSCipherTest.java b/core/src/test/java/org/bouncycastle/pqc/crypto/test/McEliecePKCSCipherTest.java
deleted file mode 100644
index edb1d607..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/crypto/test/McEliecePKCSCipherTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package org.bouncycastle.pqc.crypto.test;
-
-import java.security.SecureRandom;
-import java.util.Random;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.pqc.crypto.mceliece.McElieceKeyGenerationParameters;
-import org.bouncycastle.pqc.crypto.mceliece.McElieceKeyPairGenerator;
-import org.bouncycastle.pqc.crypto.mceliece.McEliecePKCSCipher;
-import org.bouncycastle.pqc.crypto.mceliece.McEliecePKCSDigestCipher;
-import org.bouncycastle.pqc.crypto.mceliece.McElieceParameters;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class McEliecePKCSCipherTest
- extends SimpleTest
-{
-
- SecureRandom keyRandom = new SecureRandom();
-
- public String getName()
- {
- return "McEliecePKCS";
-
- }
-
-
- public void performTest()
- {
- int numPassesKPG = 1;
- int numPassesEncDec = 10;
- Random rand = new Random();
- byte[] mBytes;
- for (int j = 0; j < numPassesKPG; j++)
- {
-
- McElieceParameters params = new McElieceParameters();
- McElieceKeyPairGenerator mcElieceKeyGen = new McElieceKeyPairGenerator();
- McElieceKeyGenerationParameters genParam = new McElieceKeyGenerationParameters(keyRandom, params);
-
- mcElieceKeyGen.init(genParam);
- AsymmetricCipherKeyPair pair = mcElieceKeyGen.generateKeyPair();
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPublic(), keyRandom);
- Digest msgDigest = new SHA256Digest();
- McEliecePKCSDigestCipher mcEliecePKCSDigestCipher = new McEliecePKCSDigestCipher(new McEliecePKCSCipher(), msgDigest);
-
-
- for (int k = 1; k <= numPassesEncDec; k++)
- {
- System.out.println("############### test: " + k);
- // initialize for encryption
- mcEliecePKCSDigestCipher.init(true, param);
-
- // generate random message
- int mLength = (rand.nextInt() & 0x1f) + 1;
- mBytes = new byte[mLength];
- rand.nextBytes(mBytes);
-
- // encrypt
- mcEliecePKCSDigestCipher.update(mBytes, 0, mBytes.length);
- byte[] enc = mcEliecePKCSDigestCipher.messageEncrypt();
-
- // initialize for decryption
- mcEliecePKCSDigestCipher.init(false, pair.getPrivate());
- byte[] constructedmessage = mcEliecePKCSDigestCipher.messageDecrypt(enc);
-
- // XXX write in McElieceFujisakiDigestCipher?
- msgDigest.update(mBytes, 0, mBytes.length);
- byte[] hash = new byte[msgDigest.getDigestSize()];
- msgDigest.doFinal(hash, 0);
-
- boolean verified = true;
- for (int i = 0; i < hash.length; i++)
- {
- verified = verified && hash[i] == constructedmessage[i];
- }
-
- if (!verified)
- {
- fail("en/decryption fails");
- }
- else
- {
- System.out.println("test okay");
- System.out.println();
- }
-
- }
- }
-
- }
-
- public static void main(
- String[] args)
- {
- runTest(new McEliecePKCSCipherTest());
- }
-
-}
diff --git a/core/src/test/java/org/bouncycastle/pqc/crypto/test/McEliecePointchevalCipherTest.java b/core/src/test/java/org/bouncycastle/pqc/crypto/test/McEliecePointchevalCipherTest.java
deleted file mode 100644
index 23ba3f9d..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/crypto/test/McEliecePointchevalCipherTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package org.bouncycastle.pqc.crypto.test;
-
-import java.security.SecureRandom;
-import java.util.Random;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.pqc.crypto.mceliece.McElieceCCA2KeyGenerationParameters;
-import org.bouncycastle.pqc.crypto.mceliece.McElieceCCA2KeyPairGenerator;
-import org.bouncycastle.pqc.crypto.mceliece.McElieceCCA2Parameters;
-import org.bouncycastle.pqc.crypto.mceliece.McEliecePointchevalCipher;
-import org.bouncycastle.pqc.crypto.mceliece.McEliecePointchevalDigestCipher;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class McEliecePointchevalCipherTest
- extends SimpleTest
-{
-
- SecureRandom keyRandom = new SecureRandom();
-
- public String getName()
- {
- return "McElieceFujisaki";
-
- }
-
-
- public void performTest()
- {
- int numPassesKPG = 1;
- int numPassesEncDec = 10;
- Random rand = new Random();
- byte[] mBytes;
- for (int j = 0; j < numPassesKPG; j++)
- {
-
- McElieceCCA2Parameters params = new McElieceCCA2Parameters();
- McElieceCCA2KeyPairGenerator mcElieceCCA2KeyGen = new McElieceCCA2KeyPairGenerator();
- McElieceCCA2KeyGenerationParameters genParam = new McElieceCCA2KeyGenerationParameters(keyRandom, params);
-
- mcElieceCCA2KeyGen.init(genParam);
- AsymmetricCipherKeyPair pair = mcElieceCCA2KeyGen.generateKeyPair();
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPublic(), keyRandom);
- Digest msgDigest = new SHA256Digest();
- McEliecePointchevalDigestCipher mcEliecePointchevalDigestCipher = new McEliecePointchevalDigestCipher(new McEliecePointchevalCipher(), msgDigest);
-
-
- for (int k = 1; k <= numPassesEncDec; k++)
- {
- System.out.println("############### test: " + k);
- // initialize for encryption
- mcEliecePointchevalDigestCipher.init(true, param);
-
- // generate random message
- int mLength = (rand.nextInt() & 0x1f) + 1;
- mBytes = new byte[mLength];
- rand.nextBytes(mBytes);
-
- // encrypt
- mcEliecePointchevalDigestCipher.update(mBytes, 0, mBytes.length);
- byte[] enc = mcEliecePointchevalDigestCipher.messageEncrypt();
-
- // initialize for decryption
- mcEliecePointchevalDigestCipher.init(false, pair.getPrivate());
- byte[] constructedmessage = mcEliecePointchevalDigestCipher.messageDecrypt(enc);
-
- // XXX write in McElieceFujisakiDigestCipher?
- msgDigest.update(mBytes, 0, mBytes.length);
- byte[] hash = new byte[msgDigest.getDigestSize()];
- msgDigest.doFinal(hash, 0);
-
- boolean verified = true;
- for (int i = 0; i < hash.length; i++)
- {
- verified = verified && hash[i] == constructedmessage[i];
- }
-
- if (!verified)
- {
- fail("en/decryption fails");
- }
- else
- {
- System.out.println("test okay");
- System.out.println();
- }
-
- }
- }
-
- }
-
- public static void main(
- String[] args)
- {
- runTest(new McEliecePointchevalCipherTest());
- }
-
-}
diff --git a/core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUEncryptTest.java b/core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUEncryptTest.java
deleted file mode 100644
index df63a103..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUEncryptTest.java
+++ /dev/null
@@ -1,298 +0,0 @@
-package org.bouncycastle.pqc.crypto.test;
-
-import java.io.IOException;
-import java.security.SecureRandom;
-
-import junit.framework.TestCase;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.pqc.crypto.ntru.NTRUEngine;
-import org.bouncycastle.pqc.crypto.ntru.NTRUEncryptionKeyPairGenerator;
-import org.bouncycastle.pqc.crypto.ntru.NTRUEncryptionKeyGenerationParameters;
-import org.bouncycastle.pqc.crypto.ntru.NTRUEncryptionPrivateKeyParameters;
-import org.bouncycastle.pqc.crypto.ntru.NTRUEncryptionPublicKeyParameters;
-import org.bouncycastle.pqc.crypto.ntru.NTRUParameters;
-import org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.Polynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.TernaryPolynomial;
-import org.bouncycastle.util.Arrays;
-
-public class NTRUEncryptTest
- extends TestCase
-{
- public void testEncryptDecrypt()
- throws InvalidCipherTextException
- {
- NTRUEncryptionKeyGenerationParameters params = NTRUEncryptionKeyGenerationParameters.APR2011_743.clone();
- // set df1..df3 and dr1..dr3 so params can be used for SIMPLE as well as PRODUCT
- params.df1 = NTRUEncryptionKeyGenerationParameters.APR2011_743_FAST.df1;
- params.df2 = NTRUEncryptionKeyGenerationParameters.APR2011_743_FAST.df2;
- params.df3 = NTRUEncryptionKeyGenerationParameters.APR2011_743_FAST.df3;
- params.dr1 = NTRUEncryptionKeyGenerationParameters.APR2011_743_FAST.dr1;
- params.dr2 = NTRUEncryptionKeyGenerationParameters.APR2011_743_FAST.dr2;
- params.dr3 = NTRUEncryptionKeyGenerationParameters.APR2011_743_FAST.dr3;
-
- int[] values = new int[] { NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE, NTRUParameters.TERNARY_POLYNOMIAL_TYPE_PRODUCT };
-
- for (int i = 0; i != values.length; i++)
- {
- int polyType = values[i];
-
- boolean[] booleans = {true, false};
- for (int j = 0; j != booleans.length; j++)
- {
- params.polyType = polyType;
- params.fastFp = booleans[j];
-
- VisibleNTRUEngine ntru = new VisibleNTRUEngine();
- NTRUEncryptionKeyPairGenerator ntruGen = new NTRUEncryptionKeyPairGenerator();
-
- ntruGen.init(params);
-
- AsymmetricCipherKeyPair kp = ntruGen.generateKeyPair();
-
- testPolynomial(ntru, kp, params);
-
- testText(ntru, kp, params);
- // sparse/dense
- params.sparse = !params.sparse;
- testText(ntru, kp, params);
- params.sparse = !params.sparse;
-
- testEmpty(ntru, kp, params);
- testMaxLength(ntru, kp, params);
- testTooLong(ntru, kp, params);
- testInvalidEncoding(ntru, kp, params);
- }
- }
- }
-
- // encrypts and decrypts a polynomial
- private void testPolynomial(VisibleNTRUEngine ntru, AsymmetricCipherKeyPair kp, NTRUEncryptionKeyGenerationParameters params)
- {
- SecureRandom random = new SecureRandom();
- IntegerPolynomial m = DenseTernaryPolynomial.generateRandom(params.N, random);
- SparseTernaryPolynomial r = SparseTernaryPolynomial.generateRandom(params.N, params.dr, params.dr, random);
-
- ntru.init(true, kp.getPublic()); // just to set params
-
- IntegerPolynomial e = ntru.encrypt(m, r, ((NTRUEncryptionPublicKeyParameters)kp.getPublic()).h);
- IntegerPolynomial c = ntru.decrypt(e, ((NTRUEncryptionPrivateKeyParameters)kp.getPrivate()).t, ((NTRUEncryptionPrivateKeyParameters)kp.getPrivate()).fp);
-
- assertTrue(Arrays.areEqual(m.coeffs, c.coeffs));
- }
-
- // encrypts and decrypts text
- private void testText(NTRUEngine ntru, AsymmetricCipherKeyPair kp, NTRUEncryptionKeyGenerationParameters params)
- throws InvalidCipherTextException
- {
- byte[] plainText = "text to encrypt".getBytes();
-
- ntru.init(true, kp.getPublic());
-
- byte[] encrypted = ntru.processBlock(plainText, 0, plainText.length);
-
- ntru.init(false, kp.getPrivate());
-
- byte[] decrypted = ntru.processBlock(encrypted, 0, encrypted.length);
-
- assertTrue(Arrays.areEqual(plainText, decrypted));
- }
-
- // tests an empty message
- private void testEmpty(NTRUEngine ntru, AsymmetricCipherKeyPair kp, NTRUEncryptionKeyGenerationParameters params)
- throws InvalidCipherTextException
- {
- byte[] plainText = "".getBytes();
-
- ntru.init(true, kp.getPublic());
-
- byte[] encrypted = ntru.processBlock(plainText, 0, plainText.length);
-
- ntru.init(false, kp.getPrivate());
-
- byte[] decrypted = ntru.processBlock(encrypted, 0, encrypted.length);
-
- assertTrue(Arrays.areEqual(plainText, decrypted));
- }
-
- // tests a message of the maximum allowed length
- private void testMaxLength(NTRUEngine ntru, AsymmetricCipherKeyPair kp, NTRUEncryptionKeyGenerationParameters params)
- throws InvalidCipherTextException
- {
- byte[] plainText = new byte[params.maxMsgLenBytes];
- System.arraycopy("secret encrypted text".getBytes(), 0, plainText, 0, 21);
- ntru.init(true, kp.getPublic());
-
- byte[] encrypted = ntru.processBlock(plainText, 0, plainText.length);
-
- ntru.init(false, kp.getPrivate());
-
- byte[] decrypted = ntru.processBlock(encrypted, 0, encrypted.length);
-
- assertTrue(Arrays.areEqual(plainText, decrypted));
- }
-
- // tests a message that is too long
- private void testTooLong(NTRUEngine ntru, AsymmetricCipherKeyPair kp, NTRUEncryptionKeyGenerationParameters params)
- {
- byte[] plainText = new byte[params.maxMsgLenBytes + 1];
- try
- {
- System.arraycopy("secret encrypted text".getBytes(), 0, plainText, 0, 21);
-
- ntru.init(true, kp.getPublic());
-
- byte[] encrypted = ntru.processBlock(plainText, 0, plainText.length);
-
- ntru.init(false, kp.getPrivate());
-
- byte[] decrypted = ntru.processBlock(encrypted, 0, encrypted.length);
-
- assertTrue(Arrays.areEqual(plainText, decrypted));
- fail("An exception should have been thrown!");
- }
- catch (DataLengthException ex)
- {
- assertEquals("Message too long: " + plainText.length + ">" + params.maxMsgLenBytes, ex.getMessage());
- }
- catch (InvalidCipherTextException e)
- {
- e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
- }
- }
-
- // tests that altering the public key *AFTER* encryption causes the decrypted message to be rejected
- private void testInvalidEncoding(NTRUEngine ntru, AsymmetricCipherKeyPair kp, NTRUEncryptionKeyGenerationParameters params)
- {
- try
- {
- byte[] plainText = "secret encrypted text".getBytes();
- ntru.init(true, kp.getPublic());
-
- byte[] encrypted = ntru.processBlock(plainText, 0, plainText.length);
-
- NTRUEncryptionPrivateKeyParameters orig = (NTRUEncryptionPrivateKeyParameters)kp.getPrivate();
- IntegerPolynomial h = (IntegerPolynomial)((NTRUEncryptionPublicKeyParameters)kp.getPublic()).h.clone();
- h.coeffs[0] = (h.coeffs[0] + 111) % params.q; // alter h
- NTRUEncryptionPrivateKeyParameters privKey = new NTRUEncryptionPrivateKeyParameters(h, orig.t, orig.fp, params.getEncryptionParameters());
-
- ntru.init(false, privKey);
-
- ntru.processBlock(encrypted, 0, encrypted.length);
-
- fail("An exception should have been thrown!");
- }
- catch (InvalidCipherTextException ex)
- {
- assertEquals("Invalid message encoding", ex.getMessage());
- }
- }
-
- // encrypts and decrypts text using an encoded key pair (fastFp=false, simple ternary polynomials)
- public void testEncodedKeysSlow()
- throws IOException, InvalidCipherTextException
- {
- byte[] plainText = "secret encrypted text".getBytes();
-
- // dense polynomials
- NTRUEncryptionKeyGenerationParameters params = NTRUEncryptionKeyGenerationParameters.APR2011_743;
- NTRUEngine ntru = new NTRUEngine();
-
- byte[] privBytes = {2, -94, 95, 65, -107, 27, 98, 62, -15, -62, 21, -4, 119, -117, 7, 68, 100, 113, -36, -82, 87, -87, -82, 24, -45, -75, -74, -108, 105, 24, 123, 117, 124, 74, -27, 42, -106, -78, 114, 27, 18, 77, -41, 105, -113, 39, 49, 46, 109, -69, 61, 77, 49, 117, 14, -29, 42, 3, 120, -121, -120, -37, 95, 84, 60, -9, -31, -64, 31, 72, 115, -15, 21, -6, 27, -60, -73, -29, -33, -81, -43, 106, 65, 114, 102, -14, -115, -96, 9, 54, 23, -18, -24, -76, 84, -41, -79, 35, 88, 11, 41, 67, 44, -63, -28, 76, 84, -41, -103, 106, -22, 35, -2, -40, -48, -121, -128, 76, 63, 123, -11, 103, -35, -32, 21, -51, -99, -40, -103, -12, 64, -80, 57, -56, 1, -51, 103, 83, 50, 111, -87, -98, 7, -109, 25, -51, 23, -92};
- byte[] pubBytes = {91, -66, -25, -81, -66, -33, 25, -31, 48, 23, -38, 20, -30, -120, -17, 1, 21, 51, -11, 102, -50, 62, 71, 79, 32, -49, -57, 105, 21, -34, -45, -67, 113, -46, -103, 57, 28, -54, -21, 94, -112, -63, 105, -100, -95, 21, -52, 50, 11, -22, -63, -35, -42, 50, 93, -40, 23, 0, 121, 23, -93, 111, -98, -14, 92, -24, -117, -8, -109, -118, -4, -107, -60, 100, -128, -47, -92, -117, -108, 39, -113, 43, 48, 68, 95, 123, -112, 41, -27, -99, 59, 33, -57, -120, -44, 72, -98, -105, -91, -52, -89, 107, 119, 87, -36, -102, -83, 67, -8, 30, -54, 74, 93, 119, -3, 126, 69, -104, -44, -24, 124, 108, -125, 73, 98, 121, -49, -37, -24, 87, -71, 91, 8, -31, -50, 95, 112, 27, 97, -93, 3, -73, -54, -16, -92, -108, -74, 88, -5, 23, 70, 69, -49, -46, -50, 65, 69, -54, -41, 109, 8, -80, -23, -84, 120, -77, 26, 99, -104, -33, 82, 91, 22, -17, 113, -29, 66, -7, -114, -101, -111, -47, -1, -3, -57, 62, 79, -70, -58, 45, 76, 28, -117, 59, -117, 113, 84, -55, 48, 119, 58, -105, -20, 80, 102, 14, -69, -69, 5, 11, -87, 107, 15, 105, -69, -27, -24, 47, -18, -54, -45, -67, 27, -52, -20, -94, 64, -26, -58, 98, 33, -61, 71, -101, 120, 28, 113, 72, 127, 50, 123, 36, -97, 78, 32, -74, 105, 62, 92, 84, -17, 21, -75, 24, -90, -78, -4, -121, 47, -82, 119, 27, -61, 17, -66, 43, 96, -49, -6, 66, -13, -75, -95, 64, -12, -39, 111, 46, -3, -123, 82, 12, -26, -30, -29, 71, -108, -79, -112, 13, 16, -70, 7, 100, 84, 89, -100, 114, 47, 56, 71, 83, 63, -61, -39, -53, -100, 23, -31, -52, -46, 36, -13, 62, 107, 28, -28, 92, 116, -59, 28, -111, -23, -44, 21, -2, 127, -112, 54, -126, 13, -104, 47, -43, -109, -19, 107, -94, -126, 50, 92, -69, 1, 115, -121, -52, -100, 25, 126, -7, 86, 77, 72, -2, -104, -42, 98, -16, 54, -67, 117, 14, -73, 4, 58, 121, 35, 1, 99, -127, -9, -60, 32, -37, -106, 6, -108, -13, -62, 23, -20, -9, 21, 15, 4, 126, -112, 123, 34, -67, -51, 43, -30, -75, 119, -112, -58, -55, -90, 2, -5, -46, -12, 119, 87, 24, -52, 2, -29, 113, 61, -82, -101, 57, -11, -107, -11, 67, -42, -43, -13, 112, -49, 82, 60, 13, -50, 108, 64, -64, 53, -107, -9, 102, -33, 75, -100, -115, 102, -113, -48, 19, -119, -72, -65, 22, -65, -93, 34, -71, 75, 101, 54, 126, 75, 34, -21, -53, -36, 127, -21, 70, 24, 89, -88, 63, -43, -4, 68, 97, -45, -101, -125, -38, 98, -118, -34, -63, 23, 78, 15, 17, 101, -107, 119, -41, 107, 117, 17, 108, 43, -93, -6, -23, -30, 49, -61, 27, 61, -125, -68, 51, 40, -106, -61, 51, 127, 2, 123, 7, -50, -115, -32, -95, -96, 67, 4, 5, 59, -45, 61, 95, 14, 2, -76, -121, 8, 125, 16, -126, 58, 118, -32, 19, -113, -113, 120, -101, 86, 76, -90, 50, -92, 51, -92, 1, 121, -74, -101, -33, 53, -53, -83, 46, 20, -87, -112, -61, -87, 106, -126, 64, 99, -60, 70, 120, 47, -53, 36, 20, -90, 110, 61, -93, 55, -10, 85, 45, 52, 79, 87, 100, -81, -85, 34, 55, -91, 27, 116, -18, -71, -11, 87, -11, 76, 48, 97, -78, 64, -100, -59, -12, 19, -90, 121, 48, -19, 64, 113, -70, -14, -70, 92, 124, 42, 95, 7, -115, 36, 127, 73, 33, 30, 121, 88, 16, -90, 99, 120, -68, 64, -125, -78, 76, 112, 68, 8, 105, 10, -47, -124, 39, -107, -101, 46, -61, 118, -74, 102, -62, -6, -128, 17, -45, 61, 76, 63, -10, -41, 50, -113, 75, -83, -59, -51, -23, -61, 47, 7, -80, 126, -2, 79, -53, 110, -93, -38, -91, -22, 20, -84, -113, -124, -73, 124, 0, 33, -58, 63, -26, 52, 7, 74, 65, 38, -33, 21, -9, -1, 120, -16, 47, -96, 59, -64, 74, 6, 48, -67, -32, -26, 35, 68, 47, 82, 36, 52, 41, 112, -28, -22, -51, -6, -49, 105, 16, -34, 99, -41, 75, 7, 79, -22, -125, -30, -126, 35, 119, -43, -30, 32, 8, 44, -42, -98, 78, -92, -95, -10, -94, -1, -91, -122, 77, 0, 40, -23, 36, 85, 123, -57, -74, -69, -90, 89, 111, -120, 22, 5, -48, 114, 59, 31, 31, -25, -3, 24, 110, -110, 73, -40, 92, -26, -12, 52, 83, -98, -119, -6, -117, -89, 95, 83, -25, 122, -26, 114, 81, 25, 110, 79, -49, -39, 10, -78, -65, 57, -90, -46, -126, 15, -124, -104, -89, -66, -87, 24, -45, 39, -34, -40, -13, 106, 12, -25, -116, -47, 79, -81, 64, -17, -31, -70, 87, 36, 46, 102, 107, 48, 88, 34, 46, 24, 63, -100, 106, 27, 58, -71, 38, 60, -66, 45, -89, 39, -60, -116, -14, -119, 118, 0, -24, -9, 38, -71, -79, 124, -119, -64, -9, 71, -56, -82, -73, -69, 127, -1, -20, 123, 32, -43, 49, 5, 49, 105, -5, -2, 5, -105, -111, 89, -30, -41, -49, 61, 80, 69, 44, -33, -116, -45, -96, 63, 28, -17, -106, -94, 90, -40, -88, 122, 116, 116, 113, -65, 104, 119, -3, 96, -45, 18, -120, -111, 83, 43, -5, 101, 71, 48, 104, -112, -95, -46, 53, -96, -93, -126, 96, 56, 104, -111, 114, -1, -44, -120, -112, -19, 100, 41, -122, 23, -78, 33, -35, 11, 57, -18, 106, -40, 74, 61, 66, 54, -77, 96, 70, 108, -128, 91, -97, -36, -23, -86, -91, 44, 58, 117, 2, 26, 44, 95, 79, -101, -81, -92, 110, -81, -12, -88, -21, -83, 60, 93, -121, -114, -48, -34, -119, -1, 127, -121, 54, -128, -106, -39, -108, 81, 17, -3, -13, -57, 74, 41, -122, -65, -107, -118, -65, -61, 103, -69, 19};
-
- byte[] fullBytes = new byte[pubBytes.length + privBytes.length];
-
- System.arraycopy(pubBytes, 0, fullBytes, 0, pubBytes.length);
- System.arraycopy(privBytes, 0, fullBytes, pubBytes.length, privBytes.length);
-
- NTRUEncryptionPrivateKeyParameters priv = new NTRUEncryptionPrivateKeyParameters(fullBytes, params.getEncryptionParameters());
- NTRUEncryptionPublicKeyParameters pub = new NTRUEncryptionPublicKeyParameters(pubBytes, params.getEncryptionParameters());
- AsymmetricCipherKeyPair kp = new AsymmetricCipherKeyPair(pub, priv);
-
- ntru.init(true, kp.getPublic());
-
- byte[] encrypted = ntru.processBlock(plainText, 0, plainText.length);
-
- ntru.init(false, kp.getPrivate());
-
- byte[] decrypted = ntru.processBlock(encrypted, 0, encrypted.length);
- assertTrue(Arrays.areEqual(plainText, decrypted));
-
- // sparse polynomials
- params = NTRUEncryptionKeyGenerationParameters.EES1499EP1;
- ntru = new NTRUEngine();
- privBytes = new byte[] {116, 7, 118, 121, 6, 77, -36, 60, 65, 108, 10, -106, 12, 9, -22, -113, 122, -31, -31, 18, 120, 81, -33, 5, 122, -76, 109, -30, -101, -45, 21, 13, -11, -49, -111, 46, 91, 4, -28, -109, 121, -119, -121, -58, -113, -9, -10, -25, -53, 40, -86, -22, -50, 42, 52, 107, 119, 17, 33, 125, -26, 33, 55, 25, -77, -65, -106, 116, -67, 91, 105, -7, 42, -107, -54, 101, 12, -12, 57, -116, 45, -107, -17, 110, 35, -64, 19, -38, -122, 115, -93, 53, 69, 66, -106, 17, 20, -71, 121, 23, -21, -45, 108, 97, 23, -98, -12, -41, -31, -53, 30, -42, 15, 85, -21, -89, 118, 42, -117, -39, 69, 0, -63, 83, 48, -80, -14, -123, -4, -116, -90, -107, -89, 119, 29, -30, 69, 22, -84, 47, 117, -123, 102, -116, 35, 93, -13, 84, -9, -122, 58, 101, 93, -106, -119, -35, -75, 76, 27, -125, -22, 68, 101, 49, 103, -13, -98, 93, -56, -110, -19, -12, 74, 104, 7, 6, -11, 47, 57, 90, 75, -30, 47, 66, -58, 14, 14, 70, 11, -119, -36, -118, -55, -53, 101, -73, -77, 33, -29, 96, -86, 38, 47, 103, 19, -37, -17, -50, -82, -87, -119, 37, -54, 77, -69, -16, -48, -52, 110, -26, 111, 35, 26, -53, -10, 9, -108, -34, 102, 7, -18, -72, -26, 24, -50, -43, 92, 56, -94, 23, -36, 60, 28, -121, 27, 127, -93, -79, -45, -60, 105, -6, -88, 72, -41, 47, -51, 3, 91, 116, 75, 122, -94, -113, 28, -96, -62, -29, -74, -85, -93, 51, 58, 72, 44, 9, 18, -48, -24, 73, 122, 60, -23, 83, -110, -7, -111, -69, 106, 51, 118, -83, -18, 109, -32, 40, 22};
-
- pubBytes = new byte[] {-62, 56, 59, -46, 30, -19, 22, -115, -20, 117, -14, 3, 2, -57, 85, -24, 27, 57, 49, -93, -52, 87, 49, 96, 15, 95, -95, -86, -61, 50, -18, 3, 109, -55, -110, -57, 82, 124, -5, -57, 68, -18, 126, 114, 6, -22, 8, 121, 125, 29, -16, 112, -81, 27, -7, 109, -44, -123, -15, -14, 74, -126, 95, -94, -91, 119, 80, -48, 41, 49, 6, 104, 93, -97, -108, -82, 93, 70, -127, -113, -22, -103, 35, -115, 20, -115, 63, 57, -84, -18, -107, 81, 44, -16, 83, 71, -27, -2, -125, 87, 26, 100, -116, 110, 94, -46, -56, -82, 119, -110, -127, -99, -8, -118, 90, 64, -29, 102, 99, 92, 86, -117, 26, -89, 32, 17, 55, -65, -10, -5, -74, 19, 13, 113, -15, -103, 17, 10, -127, -95, -79, 19, 11, -24, 59, 28, -70, -55, -69, -105, -20, -117, 66, 4, 77, 116, -124, -62, 19, 109, 49, -120, 10, -15, 108, 84, 126, 122, -46, -37, 114, -78, -72, 34, -12, 25, -104, -3, 114, -94, 16, 31, 31, -124, -109, -64, 57, -47, -113, -26, 97, -58, 112, -40, 49, 80, -54, -115, -98, -60, -123, 91, 14, 75, -86, 77, -93, 68, 112, 82, 79, 28, -25, 49, -27, -112, 103, 60, -128, 95, -63, 2, -51, 2, -107, 80, 113, 18, 123, 24, 70, 77, -56, -48, 33, 89, 88, 29, 112, -102, -15, 52, -96, 17, -9, 6, -11, -119, 29, -107, -84, -19, 84, 124, 19, 90, -60, -41, 123, -81, 96, -119, 17, -61, 62, 55, 95, -73, -13, -60, 56, 77, 24, -39, -107, -78, 47, -91, 88, 90, 34, 112, -80, 83, -58, 127, 76, -97, -40, 78, -20, -1, -62, 19, 6, -43, -46, -36, -53, -22, -28, -119, 8, 19, 79, -9, -54, -126, -3, -20, -110, -82, 51, 3, 1, -123, -41, -40, -11, 91, -52, 48, 104, -11, -2, 49, 45, 52, -33, 109, -44, -30, -44, -83, -108, -10, 77, 106, 82, 3, 14, -48, -18, -79, -64, -34, -63, -18, 122, 33, 25, 44, 82, -112, 111, 68, 97, -58, -38, 25, 62, 78, 97, -36, 57, -19, 122, -18, -74, 67, -127, -24, 32, -45, 67, -106, 90, 0, 1, 91, 30, -80, 95, 9, 78, -4, -14, 16, 111, -56, -102, -90, 52, -1, 116, 19, -127, -23, -87, 103, -94, -111, 118, 53, -69, 77, 17, -3, 31, -53, -21, -78, 124, -88, 52, 117, 34, -52, -77, -107, -38, -102, 23, 73, -76, -88, 95, 64, -85, 12, 36, -86, 86, -17, 77, 121, 90, 24, -49, -107, 33, -116, 65, 13, 91, 118, -107, -21, 65, -59, 18, 125, 61, -65, -68, -19, 23, 88, 60, -6, 78, -8, 69, -62, -118, -93, 97, -64, -67, 28, 28, -87, -97, 72, -125, -119, 4, -43, 7, 22, -15, 52, 52, -82, -5, -51, 99, 20, -59, -2, -54, -67, 40, -128, -20, -37, 50, 123, 32, 8, -39, -105, 93, 73, 77, 84, 43, 89, 88, -6, 7, -108, 81, 27, 1, 50, 16, -101, 67, 95, 119, 105, 70, 99, -127, 22, 127, -33, -19, -113, -55, -100, 122, -86, 98, 53, 27, -95, 4, -121, -96, 87, 67, -98, -37, -10, 92, 29, -3, -115, -23, 37, 8, -30, 99, -117, 62, 101, 83, 49, 60, -83, -47, -33, 41, -118, 76, -7, 111, -15, 123, -59, 53, 2, -20, -57, 24, 57, 62, 84, -26, -11, 93, -118, 54, -13, 56, 77, -66, 18, -62, -76, 80, 98, 26, 120, -93, 55, 103, -1, 78, -92, 120, -23, -60, -75, 11, 53, -62, -94, -80, 120, 113, 33, -24, -64, -5, 23, 120, -14, 61, 26, -1, 56, 79, 34, 116, -16, -95, -71, 40, -89, -50, 71, -117, -109, 2, -2, -34, 94, -78, -88, -27, 70, 94, -86, 123, -49, 107, -65, -67, 84, 90, 123, -61, -2, 43, -119, -93, 75, -4, -81, 98, -36, 125, -23, -37, 81, 104, 90, -63, -52, 88, -96, -44, 25, 3, -37, -123, -48, 113, -76, -94, -109, -115, 37, -39, 104, -124, 82, -73, 100, 48, -54, -40, -65, 81, 16, -85, -41, 60, 42, 117, 65, 77, 14, -8, -56, 52, -118, -109, 125, 13, 64, -20, 125, -37, -74, -28, 118, 112, -126, 18, -101, 11, 75, 30, -4, -121, -13, -65, -13, -122, -53, -52, 20, -2, 67, 18, -106, 67, 83, -111, 15, 106, 10, 113, 53, -112, -3, 118, 8, -56, 40, 53, 23, -123, 96, 87, -118, -97, -116, -47, 85, -73, -85, -82, 124, -55, 55, 61, 46, 12, -6, 34, 22, -22, 3, 115, -49, 102, 23, 46, 39, 0, 118, 3, -45, 48, -73, -38, 29, -36, 11, -127, -86, 30, 29, -2, -108, -114, 64, 110, 86, -46, -91, -64, 95, -40, -65, 49, -79, -126, -37, -103, -71, 53, -85, 45, -51, 33, -28, -126, 36, -77, -120, 55, -54, 72, -21, 58, -87, -73, 18, -12, 20, -100, 30, 118, -83, -22, -90, 71, -64, 108, 101, -46, 36, 105, -46, -91, 60, -113, 72, 100, 82, -90, 106, -127, 65, -94, 17, 77, -10, -112, 46, 118, 72, -84, 57, -86, -114, 88, 91, 79, 30, 107, -35, 61, 81, 71, 40, -29, -6, -107, 61, -62, -6, 65, -68, 118, 61, 110, -115, -119, -73, 104, 59, -66, -89, -127, -8, -67, 122, -38, 79, -13, 93, 1, -32, -47, -3, 62, 88, -112, 105, 73, 96, 73, -104, -126, -69, 21, -22, 16, -85, 116, 9, 82, 54, -15, -55, -67, 68, -23, 16, -89, 48, -17, -107, 60, -43, -34, 66, -114, 63, -3, -26, 68, 68, -86, 120, -111, 99, 61, 101, 27, 93, 31, 90, -33, -94, 29, -89, 41, -80, 26, -23, -80, 27, 107, 69, -45, -123, 62, 63, 80, 1, -28, 52, -8, 35, -86, -127, 76, 102, 83, -104, -79, -98, 77, -28, 118, 18, -15, -98, -39, 2, -58, 95, 64, 105, -82, -7, 96, 110, 104, 127, 126, -124, 26, 36, 33, -42, 59, 82, 127, 42, -24, -61, -50, -18, -87, 22, -32, -125, -70, 103, -121, -112, -94, 58, -95, -97, 53, 95, -61, -83, 42, 37, 80, 51, -118, 125, 15, 67, 41, -97, 41, -121, 29, -88, 100, -113, 39, 101, 47, 91, -36, 48, -56, -13, 12, 37, 0, 81, 3, -40, 8, 36, -65, -11, -32, 108, 62, 79, 70, 91, -83, 2, -47, 0, 91, 10, 87, -19, -40, 96, 106, 41, 120, -53, 40, -114, 90, 64, 59, -115, 39, 2, 53, -49, -72, -114, 94, 5, 49, 74, 13, 50, -14, 76, -123, -11, -81, 100, 120, 16, -41, -72, -118, 28, 41, 98, 122, 27, 18, -108, -43, 51, -71, 93, -13, -42, -64, -118, -106, 45, 108, 72, -128, 58, -123, -29, -114, 15, 52, -72, 108, -62, 75, -15, 105, -89, 25, 37, 13, -21, -109, 68, 5, -89, 69, 10, -46, 18, -57, 77, -103, -74, 57, -43, -110, 1, -80, 82, 5, -9, -49, -53, 83, 4, 44, 64, -117, -67, -11, 1, -65, -81, 34, -23, -71, 14, 105, -93, 2, -120, 90, 92, -6, -128, -16, -51, 27, 123, 71, -117, -72, -81, 26, 28, 5, -117, -30, 22, -72, -76, -32, -14, 82, 90, 69, 74, -94, -72, -30, -17, 12, -37, -3, -80, 72, 2, -40, 41, 0, -53, 48, -37, -117, -128, -120, -80, 28, 49, -52, 114, -119, 92, -42, -105, 125, -95, 78, 76, 123, -56, 32, -66, 69, -58, 57, -77, -100, -70, 125, 53, -115, 8, 116, 88, -34, 86, -75, 55, 64, 79, -113, -124, -91, 50, -82, -119, 50, 11, 87, -14, -25, 15, -1, -49, -127, -5, -50, 72, -29, -78, 101, -119, -21, -15, 97, -63, 57, -123, -94, -24, -8, 104, 86, 79, 49, 102, -8, -76, 8, 69, 99, -64, -108, 70, 36, 71, -127, 56, 39, 78, 109, 42, -42, -2, 126, 17, -88, -65, -23, -64, 78, 87, 7, 6, -82, -98, 41, -46, -10, -25, 90, -73, 24, 127, -27, 118, -9, 81, -3, 115, -4, 47, 86, -30, -9, -50, 32, 86, 114, 58, -5, 78, 74, 36, 29, -126, 116, 117, -114, -92, -121, -36, -86, -18, 55, 49, 112, 43, 111, -99, -116, 70, 60, -63, 87, -4, -35, 15, 28, -27, -65, 66, 115, -33, 112, 94, 74, -22, 104, -56, -27, 39, -8, -53, -120, 8, -109, 73, -68, 67, 40, -59, 59, 121, -76, -41, -80, -54, -88, -120, -121, -118, -58, 74, -120, 82, -88, -113, 30, -8, 54, -126, -106, 37, -43, -74, -56, 40, -76, 93, 91, 28, -59, -30, -2, 107, 6, -89, -69, -121, -125, -109, 5, -94, -7, -2, -5, -67, 54, -90, 39, 5, -80, 93, -99, 82, -100, -128, -8, -39, -109, 66, -11, 99, -41, 18, -32, -122, 69, 6, -95, -21, 9, 19, -117, -34, -42, 11, 20, 84, 89, 91, -61, -13, -7, 55, 90, -15, 62, 59, -4, 125, -127, -24, -124, -99, -63, -23, 52, 111, -52, -60, -113, -65, -26, 127, 57, 21, 102, 101, -77, 66, -116, 117, 80, 7, 1, -96, -29, -99, 75, -73, 44, -99, 61, -73, 15, -18, 89, 95, 104, -12, 94, 33, 13, -49, 118, -84, -122, -2, -121, 62, -32, -80, 11, -10, 102, -67, 20, -3, 25, -6, 51, -17, -123, -76, 103, 3, 127, -107, -5, 122, 65, 22, 113, 120, 6, -19, -110, 86, 55, -88, -124, 0, -54, 17, 112, 15, 105, -28, 111, -93, 85, -59, -88, 28, 123, 55, 117, 10, 76, 54, -98, 116, 40, -65, -53, -80, 46, 66, -8, -114, 102, 66, 67, -117, 46, 21, -116, -38, 58, -105, 101, 37, -16, 5, 55, -33, -87, 72, 122, -114, -91, 41, -114, 77, 50, 109, 35, -61, 9, -55, -118, 126, -35, -108, 5, 62, 125, -109, -115, -55, 32, -71, 69, 110, 87, -82, 119, 26, 103, -77, -38, -13, 113, 74, 69, 116, 94, -21, 5, 35, 73, -80, -87, 80, 13, 108, 1, 82, -56, -35, -21, -78, -98, 121, 112, -117, 72, 47, 76, -97, -84, -110, -35, -19, -120, -13, 127, 5, 56, 72, -22, 110, -8, -71, 0, -57, -125, -101, 60, -64, -32, 1, 126, -109, 9, 84, 117, 62, -68, -106, 28, -118, -52, -81, 112, 11, 55, 68, -86, -65, 123, 83, 55, -72, 110, 63, -90, 31, 11, 90, -60, 20, 14, -36, 5, -92, 11, -100, 64, -57, -72, -105, 7, 103, 125, 99, -88, 32, -5, 41, -115, -11, 89, 81, 77, -33, -7, -123, -17, 109, 59, 40, -12, -61, 98, -91, 19, -36, 108, 118, -124, -82, -40, -124, -66, 19, 127, -73, -39, 99, 43, -16, -44, -83, -77, -34, 68, -118, -71, -116, 114, 120, -34, -105, -32, -46, 102, 73, -79, 7, 42, 35, -66, 125, 34, 113, 66, 78, 71, 6, 44, -17, 4, -80, 38, -59, 12, -8, -78, 103, 8, 80, 18, -74, 20, 3, 56, -20, 106, -1, -12, 83, 4, 68, -119, 84, -87, 97, -53, 102, 119, 34, -85, 22, -26, 55, -107, 96, -70, 77, -68, -96, -15, -22, -77, -55, 5, 103, -42, -87, 122, -80, -103, -37, -120, -56, -16, -51, -7, -19, -104, 120, 9, 54, -85, 48, -76, -38, 58, -68, 116, -20, -44, 22, -32, 75, -46, -41, 13, -100, 16, -59, -93, -115, 54, 22, -110, -46, -119, 44, -98, -48, 4, -58, -115, -57, 103, -56, 36, -63, 104, -114, -125, 92, 65, 117, -21, -59, -31, 56, -98, -126, 56, 47, -116, 100, 122, -98, 4, 26, -29, -127, -113, 73, 48, 106, 125, -69, -127, 62, 56, -79, 76, 84, -46, -31, -17, 94, -98, 62, 63, 118, -24, 63, 123, -93, -46, 103, 117, -120, -35, 19, 25, 15, -110, -125, 12, -75, -50, 103, 49, 47, 98, 92, 10, -88, 54, -53, 19, 25, -90, 93, -49, 64, 126, -106, -30, -52, 58, 37, 68, -18, -60, 15, -27, 93, -124, 88, 110, -80, -106, 88, 55, 108, -58, -43, -70, 76, 85, 98, 27, -66, 18, 75, 69, 114, 90, -26, -10, -12, -126, 84, -109, 108, 15, -115, 90, 11, -127, 63, -7, 47, 92, -72, 38, -58, -35, 18, 25, 12, -103, 0};
-
- fullBytes = new byte[pubBytes.length + privBytes.length];
-
- System.arraycopy(pubBytes, 0, fullBytes, 0, pubBytes.length);
- System.arraycopy(privBytes, 0, fullBytes, pubBytes.length, privBytes.length);
-
- priv = new NTRUEncryptionPrivateKeyParameters(fullBytes, params.getEncryptionParameters());
- pub = new NTRUEncryptionPublicKeyParameters(pubBytes, params.getEncryptionParameters());
- kp = new AsymmetricCipherKeyPair(pub, priv);
- ntru.init(true, kp.getPublic());
-
- encrypted = ntru.processBlock(plainText, 0, plainText.length);
-
- ntru.init(false, kp.getPrivate());
-
- decrypted = ntru.processBlock(encrypted, 0, encrypted.length);
-
- assertTrue(Arrays.areEqual(plainText, decrypted));
- }
-
- // encrypts and decrypts text using an encoded key pair (fastFp=true)
- public void testEncodedKeysFast()
- throws IOException, InvalidCipherTextException
- {
- byte[] plainText = "secret encrypted text".getBytes();
-
- NTRUEncryptionKeyGenerationParameters params = NTRUEncryptionKeyGenerationParameters.APR2011_743_FAST;
- NTRUEngine ntru = new NTRUEngine();
- byte[] privBytes = {10, 16, 2, 30, -40, -63, -109, -77, -72, -122, 66, 23, -30, -44, -82, 0, 95, 64, 68, 48, -62, -14, 26, -19, -72, -25, 72, 123, 98, 84, -83, 0, 7, 40, 65, 35, 68, 113, 12, -112, 32, -123, 58, 85, -30, -109, -74, 0, 34, -8, -126, 57, 30, 98, -107, -45, -88, 102, 68, 42, -30, -108, -89, 0, 38, -40, -61, 37, 82, 113, -115, 123, -100, 5, 46, 125, -23, 78, -111, -76, 36, -90, 67, -31, 10, 2, 96, -127, 21, 50, -79, 13, -125, -124, 38, 55, -67, -95, 81, -107, 12, 117, -86, 99, -127, 11};
- byte[] pubBytes = {108, -76, -104, -75, -87, -65, -18, -5, 45, -57, -100, -83, 51, 99, 94, 15, -73, 89, -100, 40, -114, 91, -107, 104, 127, 22, 13, 5, -16, 69, -104, -126, -44, 119, 47, -48, 75, 66, 83, -37, -66, -84, 73, 52, 23, -27, 53, 63, 56, 14, -2, 43, -59, -85, -80, 46, 38, -126, 75, -8, -63, 88, 104, 13, 72, -25, -10, -58, -51, 117, -84, 115, -24, -53, 83, -103, -97, 46, 90, -82, -61, 113, -49, -24, -72, 24, -124, -42, -36, 7, 41, 8, 14, -71, -75, -84, -24, -39, 56, 67, 88, 67, 66, -13, 70, -119, -64, 74, -100, -58, 35, 105, -20, 93, 80, -116, -55, 37, -52, 64, 0, -36, -71, 8, 77, -10, -41, -22, -73, 4, -115, -74, -74, -73, 23, -10, -26, 48, 125, -114, -32, -116, 74, 19, -104, 59, 43, 4, 97, -84, 112, 45, 16, 3, -110, -13, 119, -6, 29, -80, 109, 82, -31, 82, 30, 76, -111, -122, -50, -69, -41, -123, 107, 78, -35, 24, -121, -87, -108, 13, 70, 32, -74, 112, 104, -40, -61, 86, -125, 60, -94, -5, -18, 55, 54, -128, 83, -88, 71, 71, -66, 29, -113, 120, 30, 16, -38, 37, 96, -90, 38, -85, 88, 59, 15, -69, 6, -8, 1, 1, 71, 12, 60, -26, -110, 97, 77, 33, 58, 63, 104, 108, 83, 72, -21, -99, 115, -125, -16, 12, 99, 68, 39, -97, -6, 17, 26, -59, 123, -110, -37, -71, 47, 50, 5, 110, -34, 89, -74, 20, 79, -108, -7, 42, 106, -112, 44, 107, 106, -50, 55, 127, -124, 53, 123, -119, -46, -114, -52, -85, 75, 34, -39, -125, 58, -5, -31, -81, -37, -94, -123, 113, 11, -104, -124, 96, -103, 9, 108, 115, 97, -6, 98, -43, 26, -89, -23, 83, 60, 34, -86, -54, 107, 78, -48, 118, -31, -19, 29, -106, 108, 117, 83, 119, 51, -45, 115, 108, -13, -89, -29, 29, -120, 108, 20, 22, -3, 22, 78, -109, 95, 3, -68, -10, -53, -117, -96, -49, 9, 7, 38, 116, 33, -65, 31, 9, -5, -73, 127, 52, 113, 87, -39, 119, -96, 74, -105, 75, -89, 63, 69, -109, -127, 92, -54, 17, -98, -23, -69, 123, -125, 23, -93, 44, -11, -25, -101, 120, -29, 113, -33, 0, -117, -100, -114, 22, 41, -46, 29, -109, 107, 37, -94, 125, 46, 17, 16, -65, -14, 105, -118, 51, -21, 121, -5, 56, 29, 30, -69, -38, -10, -77, -74, 6, -105, 83, 110, 23, 114, -11, -123, -14, 30, -11, -9, 84, -90, -20, -29, 72, -85, 97, -74, -59, -112, -15, -51, -105, 117, 123, -17, -64, -127, 127, -33, -102, 88, 77, 122, -127, -15, 121, -125, -32, 53, 113, 45, -22, 84, -87, 20, 36, 65, 83, -84, -66, -22, 4, 15, -108, -92, 109, -128, -48, 4, -27, -13, 25, 51, -10, 34, 87, 88, 38, -87, 89, -64, -62, 20, 78, 35, -26, -2, 55, 3, -72, -64, 30, 28, -105, 6, -37, -38, -8, 26, -118, 105, -37, -30, 85, -66, 105, -46, -37, -11, -72, 71, 43, -65, -44, 17, -79, 98, 79, -77, -111, 95, 74, 101, -40, -106, 14, -108, -112, 86, 108, 49, 72, -38, -103, -31, 65, -119, 8, 78, -89, 100, -28, 116, 94, 15, -18, 108, 101, 85, 8, -6, 111, -82, -49, -66, -89, 28, -84, -85, -119, 111, 45, 83, -60, -40, -45, -101, -105, -35, 123, -1, 13, -112, 79, -80, -85, -109, -71, 69, 104, 95, -93, 121, -17, 83, 117, -73, -63, -65, -107, -72, 118, -102, -56, 38, 79, 121, -25, -86, -81, -38, 8, 122, 97, 37, 82, -40, 53, 11, 124, -94, -76, -107, -125, -9, -119, 63, 52, -34, -72, -21, 59, 3, -100, -127, 47, -102, 19, -37, -45, -114, -65, 39, -106, 6, -127, -110, -38, 96, -38, -51, 110, -3, 28, 8, 102, -102, 96, -127, 109, -56, -53, -13, 59, -98, 92, 80, 1, 55, -91, -122, -105, 28, 69, -85, 109, -38, 105, 87, -5, 3, -102, 62, -92, 60, 43, -20, -7, -23, -84, 106, 121, -48, 123, -112, 56, -17, -52, 14, -123, -122, 64, 14, -23, -71, 60, 70, -121, 6, 37, -15, 77, 96, 104, -34, 58, -125, -61, 1, -26, 118, -78, -35, -1, 0, 5, 33, -98, -86, -127, 25, 56, -91, 82, -33, 60, -64, -86, 27, 31, -80, -79, 118, -12, -18, 40, -72, 32, 119, -28, -62, 100, -121, -71, -79, -9, 38, -37, 25, 65, -46, 8, -112, 37, 9, -56, 123, -40, -44, -90, -21, -54, -2, -7, 107, -93, 24, -126, 69, 42, -111, -84, 57, 69, -119, 21, 60, 57, -122, 111, -99, 49, -46, -119, 100, 98, 24, -62, 112, 122, 46, 18, -35, -67, 89, 104, 82, 12, 125, 57, -70, -112, -109, 96, 51, -68, 1, -101, -59, -92, 54, 85, -41, 17, 31, 94, 75, -128, 53, 84, 0, -83, -94, -123, 49, -30, -24, 18, 46, 48, -33, 120, 66, -69, 70, 23, -124, -117, 81, 96, 46, 47, -33, 83, -13, -14, -94, 49, 66, -46, 84, -27, -77, 6, 0, -75, -18, 86, -119, -88, 82, -50, 55, -20, 63, 55, -57, 22, -108, -103, -17, -22, 64, 65, 90, -34, -96, -117, 51, 119, -103, -35, 95, -15, -118, 2, -31, 31, -9, -58, 84, -75, 80, 39, -101, -56, 16, -75, 59, 48, -63, -24, -95, 119, 73, -110, -115, 49, -18, 54, -124, 112, -61, -40, -105, -118, -66, 15, -107, 75, 82, -70, -87, -11, -11, 48, 41, 119, -42, -34, -33, 57, 23, -14, -45, -125, -108, -75, 3, 44, 44, 58, 126, -126, -20, -123, 58, 114, 79, -102, -115, 115, 12, 66, 108, 84, 43, -46, -80, -41, -70, 111, -114, 123, 21, 1, 34, -72, 23, 105, -52, -39, -54, -119, 45, 77, -16, -66, -105, -11, 91, -46, 77, -104, -93, 52, -3, 17, 55, -10, 67, -33, 43, 75, -103, 106, 7, -35, -65, -21, 68, 118, -38, 59, -115, 31};
-
- byte[] fullBytes = new byte[pubBytes.length + privBytes.length];
-
- System.arraycopy(pubBytes, 0, fullBytes, 0, pubBytes.length);
- System.arraycopy(privBytes, 0, fullBytes, pubBytes.length, privBytes.length);
-
- NTRUEncryptionPrivateKeyParameters priv = new NTRUEncryptionPrivateKeyParameters(fullBytes, params.getEncryptionParameters());
- NTRUEncryptionPublicKeyParameters pub = new NTRUEncryptionPublicKeyParameters(pubBytes, params.getEncryptionParameters());
- AsymmetricCipherKeyPair kp = new AsymmetricCipherKeyPair(pub, priv);
-
- ntru.init(true, kp.getPublic());
-
- byte[] encrypted = ntru.processBlock(plainText, 0, plainText.length);
-
- assertEquals(encrypted.length, ntru.getOutputBlockSize());
-
- ntru.init(false, kp.getPrivate());
-
- byte[] decrypted = ntru.processBlock(encrypted, 0, encrypted.length);
-
- assertTrue(Arrays.areEqual(plainText, decrypted));
- }
-
- private class VisibleNTRUEngine
- extends NTRUEngine
- {
- public IntegerPolynomial encrypt(IntegerPolynomial m, TernaryPolynomial r, IntegerPolynomial pubKey)
- {
- return super.encrypt(m, r, pubKey);
- }
-
- public IntegerPolynomial decrypt(IntegerPolynomial e, Polynomial priv_t, IntegerPolynomial priv_fp)
- {
- return super.decrypt(e, priv_t, priv_fp);
- }
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUEncryptionParametersTest.java b/core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUEncryptionParametersTest.java
deleted file mode 100644
index 54f53ad3..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUEncryptionParametersTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.bouncycastle.pqc.crypto.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.crypto.ntru.NTRUEncryptionKeyGenerationParameters;
-
-public class NTRUEncryptionParametersTest
- extends TestCase
-{
- public void testLoadSave()
- throws IOException
- {
- NTRUEncryptionKeyGenerationParameters params = NTRUEncryptionKeyGenerationParameters.EES1499EP1;
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- params.writeTo(os);
- ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
- assertEquals(params, new NTRUEncryptionKeyGenerationParameters(is));
- }
-
- public void testEqualsHashCode()
- throws IOException
- {
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- NTRUEncryptionKeyGenerationParameters.EES1499EP1.writeTo(os);
- ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
- NTRUEncryptionKeyGenerationParameters params = new NTRUEncryptionKeyGenerationParameters(is);
-
- assertEquals(params, NTRUEncryptionKeyGenerationParameters.EES1499EP1);
- assertEquals(params.hashCode(), NTRUEncryptionKeyGenerationParameters.EES1499EP1.hashCode());
-
- params.N += 1;
- assertFalse(params.equals(NTRUEncryptionKeyGenerationParameters.EES1499EP1));
- assertFalse(NTRUEncryptionKeyGenerationParameters.EES1499EP1.equals(params));
- assertFalse(params.hashCode() == NTRUEncryptionKeyGenerationParameters.EES1499EP1.hashCode());
- }
-
- public void testClone()
- {
- NTRUEncryptionKeyGenerationParameters params = NTRUEncryptionKeyGenerationParameters.APR2011_439;
- assertEquals(params, params.clone());
-
- params = NTRUEncryptionKeyGenerationParameters.APR2011_439_FAST;
- assertEquals(params, params.clone());
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSignatureKeyTest.java b/core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSignatureKeyTest.java
deleted file mode 100644
index 509839a0..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSignatureKeyTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.bouncycastle.pqc.crypto.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-import junit.framework.TestCase;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.pqc.crypto.ntru.NTRUSigner;
-import org.bouncycastle.pqc.crypto.ntru.NTRUSigningKeyGenerationParameters;
-import org.bouncycastle.pqc.crypto.ntru.NTRUSigningKeyPairGenerator;
-import org.bouncycastle.pqc.crypto.ntru.NTRUSigningPrivateKeyParameters;
-import org.bouncycastle.pqc.crypto.ntru.NTRUSigningPublicKeyParameters;
-
-public class NTRUSignatureKeyTest
- extends TestCase
-{
- public void testEncode()
- throws IOException
- {
- for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157, NTRUSigningKeyGenerationParameters.TEST157_PROD})
- {
- testEncode(params);
- }
- }
-
- private void testEncode(NTRUSigningKeyGenerationParameters params)
- throws IOException
- {
- NTRUSigner ntru = new NTRUSigner(params.getSigningParameters());
- NTRUSigningKeyPairGenerator kGen = new NTRUSigningKeyPairGenerator();
-
- kGen.init(params);
-
- AsymmetricCipherKeyPair kp = kGen.generateKeyPair();
-
- NTRUSigningPrivateKeyParameters kPriv = (NTRUSigningPrivateKeyParameters)kp.getPrivate();
- NTRUSigningPublicKeyParameters kPub = (NTRUSigningPublicKeyParameters)kp.getPublic();
-
- // encode to byte[] and reconstruct
- byte[] priv = kPriv.getEncoded();
- byte[] pub = kPub.getEncoded();
- AsymmetricCipherKeyPair kp2 = new AsymmetricCipherKeyPair(new NTRUSigningPublicKeyParameters(pub, params.getSigningParameters()), new NTRUSigningPrivateKeyParameters(priv, params));
- assertEquals(kPub, kp2.getPublic());
- assertEquals(kPriv, kp2.getPrivate());
-
- // encode to OutputStream and reconstruct
- ByteArrayOutputStream bos1 = new ByteArrayOutputStream();
- ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
- kPriv.writeTo(bos1);
- kPub.writeTo(bos2);
- ByteArrayInputStream bis1 = new ByteArrayInputStream(bos1.toByteArray());
- ByteArrayInputStream bis2 = new ByteArrayInputStream(bos2.toByteArray());
- AsymmetricCipherKeyPair kp3 = new AsymmetricCipherKeyPair(new NTRUSigningPublicKeyParameters(bis2, params.getSigningParameters()), new NTRUSigningPrivateKeyParameters(bis1, params));
- assertEquals(kPub, kp3.getPublic());
- assertEquals(kPriv, kp3.getPrivate());
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSignatureParametersTest.java b/core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSignatureParametersTest.java
deleted file mode 100644
index 4c5751ed..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSignatureParametersTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.bouncycastle.pqc.crypto.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.crypto.ntru.NTRUSigningKeyGenerationParameters;
-
-public class NTRUSignatureParametersTest
- extends TestCase
-{
- public void testLoadSave()
- throws IOException
- {
- for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157, NTRUSigningKeyGenerationParameters.TEST157_PROD, NTRUSigningKeyGenerationParameters.APR2011_743, NTRUSigningKeyGenerationParameters.APR2011_743_PROD})
- {
- testLoadSave(params);
- }
- }
-
- private void testLoadSave(NTRUSigningKeyGenerationParameters params)
- throws IOException
- {
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- params.writeTo(os);
- ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
- assertEquals(params, new NTRUSigningKeyGenerationParameters(is));
- }
-
- public void testEqualsHashCode()
- throws IOException
- {
- for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157, NTRUSigningKeyGenerationParameters.TEST157_PROD, NTRUSigningKeyGenerationParameters.APR2011_743, NTRUSigningKeyGenerationParameters.APR2011_743_PROD})
- {
- testEqualsHashCode(params);
- }
- }
-
- private void testEqualsHashCode(NTRUSigningKeyGenerationParameters params)
- throws IOException
- {
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- params.writeTo(os);
- ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
- NTRUSigningKeyGenerationParameters params2 = new NTRUSigningKeyGenerationParameters(is);
-
- assertEquals(params, params2);
- assertEquals(params.hashCode(), params2.hashCode());
-
- params.N += 1;
- assertFalse(params.equals(params2));
- assertFalse(params.equals(params2));
- assertFalse(params.hashCode() == params2.hashCode());
- }
-
- public void testClone()
- {
- for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157, NTRUSigningKeyGenerationParameters.TEST157_PROD, NTRUSigningKeyGenerationParameters.APR2011_743, NTRUSigningKeyGenerationParameters.APR2011_743_PROD})
- {
- assertEquals(params, params.clone());
- }
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSignerTest.java b/core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSignerTest.java
deleted file mode 100644
index 3a765af4..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSignerTest.java
+++ /dev/null
@@ -1,317 +0,0 @@
-package org.bouncycastle.pqc.crypto.test;
-
-
-import junit.framework.TestCase;
-
-/**
- * @deprecated algorithm no longer safe.
- */
-public class NTRUSignerTest
- extends TestCase
-{
- public void testStub()
- {
-
- }
- /*
- public void testCreateBasis()
- {
- for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157.clone(), NTRUSigningKeyGenerationParameters.TEST157_PROD.clone()})
- {
- testCreateBasis(params);
- }
- }
-
- private void testCreateBasis(NTRUSigningKeyGenerationParameters params)
- {
- NTRUSigningKeyPairGenerator ntru = new NTRUSigningKeyPairGenerator();
-
- ntru.init(params);
-
- NTRUSigningKeyPairGenerator.FGBasis basis = (NTRUSigningKeyPairGenerator.FGBasis)ntru.generateBoundedBasis();
- assertTrue(equalsQ(basis.f, basis.fPrime, basis.F, basis.G, params.q, params.N));
-
- // test KeyGenAlg.FLOAT (default=RESULTANT)
- params.keyGenAlg = NTRUSigningKeyGenerationParameters.KEY_GEN_ALG_FLOAT;
- ntru.init(params);
- basis = (NTRUSigningKeyPairGenerator.FGBasis)ntru.generateBoundedBasis();
- assertTrue(equalsQ(basis.f, basis.fPrime, basis.F, basis.G, params.q, params.N));
- }
-
- // verifies that f*G-g*F=q
- private boolean equalsQ(Polynomial f, Polynomial g, IntegerPolynomial F, IntegerPolynomial G, int q, int N)
- {
- IntegerPolynomial x = f.mult(G);
- x.sub(g.mult(F));
- boolean equalsQ = true;
- for (int i = 1; i < x.coeffs.length; i++)
- {
- equalsQ &= x.coeffs[i] == 0;
- }
- equalsQ &= x.coeffs[0] == q;
- return equalsQ;
- }
-
- /**
- * a test for the one-method-call variants: sign(byte, SignatureKeyPair) and verify(byte[], byte[], SignatureKeyPair)
- *
- public void testSignVerify157()
- throws IOException
- {
- for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157.clone(), NTRUSigningKeyGenerationParameters.TEST157_PROD.clone(), NTRUSigningKeyGenerationParameters.APR2011_439.clone(), NTRUSigningKeyGenerationParameters.APR2011_439_PROD.clone(), NTRUSigningKeyGenerationParameters.APR2011_743.clone(), NTRUSigningKeyGenerationParameters.APR2011_743_PROD.clone()})
- {
- testSignVerify(params);
- }
- }
-
- public void testSignVerify439()
- throws IOException
- {
- for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.APR2011_439.clone(), NTRUSigningKeyGenerationParameters.APR2011_439_PROD.clone()})
- {
- testSignVerify(params);
- }
- }
-//
-// public void testSignVerify743()
-// throws IOException
-// {
-// for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.APR2011_743.clone(), NTRUSigningKeyGenerationParameters.APR2011_743_PROD.clone()})
-// {
-// testSignVerify(params);
-// }
-// }
-
- private void testSignVerify(NTRUSigningKeyGenerationParameters params)
- throws IOException
- {
- NTRUSigner ntru = new NTRUSigner(params.getSigningParameters());
- NTRUSigningKeyPairGenerator kGen = new NTRUSigningKeyPairGenerator();
-
- kGen.init(params);
-
- AsymmetricCipherKeyPair kp = kGen.generateKeyPair();
-
- Random rng = new Random();
- byte[] msg = new byte[10 + rng.nextInt(1000)];
- rng.nextBytes(msg);
-
- // sign and verify
- ntru.init(true, kp.getPrivate());
-
- ntru.update(msg, 0, msg.length);
-
- byte[] s = ntru.generateSignature();
-
- ntru.init(false, kp.getPublic());
-
- ntru.update(msg, 0, msg.length);
-
- boolean valid = ntru.verifySignature(s);
-
- assertTrue(valid);
-
- // altering the signature should make it invalid
- s[rng.nextInt(params.N)] += 1;
- ntru.init(false, kp.getPublic());
-
- ntru.update(msg, 0, msg.length);
-
- valid = ntru.verifySignature(s);
- assertFalse(valid);
-
- // test that a random signature fails
- rng.nextBytes(s);
-
- ntru.init(false, kp.getPublic());
-
- ntru.update(msg, 0, msg.length);
-
- valid = ntru.verifySignature(s);
- assertFalse(valid);
-
- // encode, decode keypair, test
- NTRUSigningPrivateKeyParameters priv = new NTRUSigningPrivateKeyParameters(((NTRUSigningPrivateKeyParameters)kp.getPrivate()).getEncoded(), params);
- NTRUSigningPublicKeyParameters pub = new NTRUSigningPublicKeyParameters(((NTRUSigningPublicKeyParameters)kp.getPublic()).getEncoded(), params.getSigningParameters());
- kp = new AsymmetricCipherKeyPair(pub, priv);
-
- ntru.init(true, kp.getPrivate());
- ntru.update(msg, 0, msg.length);
-
- s = ntru.generateSignature();
-
- ntru.init(false, kp.getPublic());
- ntru.update(msg, 0, msg.length);
-
- valid = ntru.verifySignature(s);
- assertTrue(valid);
-
- // altering the signature should make it invalid
- s[rng.nextInt(s.length)] += 1;
- ntru.init(false, kp.getPublic());
- ntru.update(msg, 0, msg.length);
- valid = ntru.verifySignature(s);
- assertFalse(valid);
-
- // sparse/dense
- params.sparse = !params.sparse;
-
- ntru.init(true, kp.getPrivate());
- ntru.update(msg, 0, msg.length);
-
- s = ntru.generateSignature();
-
- ntru.init(false, kp.getPublic());
- ntru.update(msg, 0, msg.length);
- valid = ntru.verifySignature(s);
- assertTrue(valid);
-
- s[rng.nextInt(s.length)] += 1;
- ntru.init(false, kp.getPublic());
- ntru.update(msg, 0, msg.length);
- valid = ntru.verifySignature(s);
- assertFalse(valid);
- params.sparse = !params.sparse;
-
- // decrease NormBound to force multiple signing attempts
- NTRUSigningKeyGenerationParameters params2 = params.clone();
- params2.normBoundSq *= 4.0 / 9;
- params2.signFailTolerance = 10000;
- ntru = new NTRUSigner(params2.getSigningParameters());
-
- ntru.init(true, kp.getPrivate());
- ntru.update(msg, 0, msg.length);
-
- s = ntru.generateSignature();
-
- ntru.init(false, kp.getPublic());
- ntru.update(msg, 0, msg.length);
- valid = ntru.verifySignature(s);
-
- assertTrue(valid);
-
- // test KeyGenAlg.FLOAT (default=RESULTANT)
- params2 = params.clone();
- params.keyGenAlg = NTRUSigningKeyGenerationParameters.KEY_GEN_ALG_FLOAT;
- ntru = new NTRUSigner(params.getSigningParameters());
-
- kGen.init(params);
-
- kp = kGen.generateKeyPair();
- ntru.init(true, kp.getPrivate());
- ntru.update(msg, 0, msg.length);
-
- s = ntru.generateSignature();
- ntru.init(false, kp.getPublic());
- ntru.update(msg, 0, msg.length);
- valid = ntru.verifySignature(s);
- assertTrue(valid);
- s[rng.nextInt(s.length)] += 1;
- ntru.init(false, kp.getPublic());
- ntru.update(msg, 0, msg.length);
- valid = ntru.verifySignature(s);
- assertFalse(valid);
- }
-
- /**
- * test for the initSign/update/sign and initVerify/update/verify variant
- *
- public void testInitUpdateSign()
- {
- for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157.clone(), NTRUSigningKeyGenerationParameters.TEST157_PROD.clone()})
- {
- testInitUpdateSign(params);
- }
- }
-
- private void testInitUpdateSign(NTRUSigningKeyGenerationParameters params)
- {
- NTRUSigner ntru = new NTRUSigner(params.getSigningParameters());
- NTRUSigningKeyPairGenerator kGen = new NTRUSigningKeyPairGenerator();
-
- kGen.init(params);
-
- AsymmetricCipherKeyPair kp = kGen.generateKeyPair();
-
- Random rng = new Random();
- byte[] msg = new byte[10 + rng.nextInt(1000)];
- rng.nextBytes(msg);
-
- // sign and verify a message in two pieces each
- ntru.init(true, kp.getPrivate());
- int splitIdx = rng.nextInt(msg.length);
- ntru.update(msg[0]); // first byte
- ntru.update(msg, 1, splitIdx - 1); // part 1 of msg
- ntru.update(msg, splitIdx, msg.length - splitIdx);
- byte[] s = ntru.generateSignature(); // part 2 of msg
- ntru.init(false, kp.getPublic());
- splitIdx = rng.nextInt(msg.length);
- ntru.update(msg, 0, splitIdx); // part 1 of msg
- ntru.update(msg, splitIdx, msg.length - splitIdx); // part 2 of msg
- boolean valid = ntru.verifySignature(s);
- assertTrue(valid);
- // verify the same signature with the one-step method
- ntru.init(false, (NTRUSigningPublicKeyParameters)kp.getPublic());
- ntru.update(msg, 0, msg.length); // part 1 of msg
- valid = ntru.verifySignature(s);
- assertTrue(valid);
-
- // sign using the one-step method and verify using the multi-step method
- ntru.init(true, kp.getPrivate());
- ntru.update(msg, 0, msg.length);
- s = ntru.generateSignature();
- ntru.init(false, (NTRUSigningPublicKeyParameters)kp.getPublic());
- splitIdx = rng.nextInt(msg.length);
- ntru.update(msg, 0, splitIdx); // part 1 of msg
- ntru.update(msg, splitIdx, msg.length - splitIdx); // part 2 of msg
- valid = ntru.verifySignature(s);
- assertTrue(valid);
- }
-
- public void testCreateMsgRep()
- {
- for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157.clone(), NTRUSigningKeyGenerationParameters.TEST157_PROD.clone()})
- {
- testCreateMsgRep(params);
- }
- }
-
- private void testCreateMsgRep(NTRUSigningKeyGenerationParameters params)
- {
- VisibleNTRUSigner ntru = new VisibleNTRUSigner(params.getSigningParameters());
- byte[] msgHash = "adfsadfsdfs23234234".getBytes();
-
- // verify that the message representative is reproducible
- IntegerPolynomial i1 = ntru.createMsgRep(msgHash, 1);
- IntegerPolynomial i2 = ntru.createMsgRep(msgHash, 1);
- assertTrue(Arrays.areEqual(i1.coeffs, i2.coeffs));
- i1 = ntru.createMsgRep(msgHash, 5);
- i2 = ntru.createMsgRep(msgHash, 5);
- assertTrue(Arrays.areEqual(i1.coeffs, i2.coeffs));
-
- i1 = ntru.createMsgRep(msgHash, 2);
- i2 = ntru.createMsgRep(msgHash, 3);
- assertFalse(Arrays.areEqual(i1.coeffs, i2.coeffs));
- }
-
- private class VisibleNTRUSigner
- extends NTRUSigner
- {
-
- /**
- * Constructs a new instance with a set of signature parameters.
- *
- * @param params signature parameters
- *
- public VisibleNTRUSigner(NTRUSigningParameters params)
- {
- super(params);
- }
-
- public IntegerPolynomial createMsgRep(byte[] hash, int i)
- {
- return super.createMsgRep(hash, i);
- }
- }
- */
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSigningParametersTest.java b/core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSigningParametersTest.java
deleted file mode 100644
index 7cf7de83..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSigningParametersTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package org.bouncycastle.pqc.crypto.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.crypto.ntru.NTRUSigningKeyGenerationParameters;
-
-public class NTRUSigningParametersTest
- extends TestCase
-{
-
- public void testLoadSave()
- throws IOException
- {
- for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157, NTRUSigningKeyGenerationParameters.TEST157_PROD})
- {
- testLoadSave(params);
- }
- }
-
- private void testLoadSave(NTRUSigningKeyGenerationParameters params)
- throws IOException
- {
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- params.writeTo(os);
- ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
- assertEquals(params, new NTRUSigningKeyGenerationParameters(is));
- }
-
- public void testEqualsHashCode()
- throws IOException
- {
- for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157, NTRUSigningKeyGenerationParameters.TEST157_PROD})
- {
- testEqualsHashCode(params);
- }
- }
-
- private void testEqualsHashCode(NTRUSigningKeyGenerationParameters params)
- throws IOException
- {
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- params.writeTo(os);
- ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
- NTRUSigningKeyGenerationParameters params2 = new NTRUSigningKeyGenerationParameters(is);
-
- assertEquals(params, params2);
- assertEquals(params.hashCode(), params2.hashCode());
-
- params.N += 1;
- assertFalse(params.equals(params2));
- assertFalse(params.equals(params2));
- assertFalse(params.hashCode() == params2.hashCode());
- }
-
- public void testClone()
- {
- for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157, NTRUSigningKeyGenerationParameters.TEST157_PROD})
- {
- assertEquals(params, params.clone());
- }
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/pqc/crypto/test/RainbowSignerTest.java b/core/src/test/java/org/bouncycastle/pqc/crypto/test/RainbowSignerTest.java
deleted file mode 100644
index ae6774b6..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/crypto/test/RainbowSignerTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package org.bouncycastle.pqc.crypto.test;
-
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.digests.SHA224Digest;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.pqc.crypto.DigestingMessageSigner;
-import org.bouncycastle.pqc.crypto.rainbow.RainbowKeyGenerationParameters;
-import org.bouncycastle.pqc.crypto.rainbow.RainbowKeyPairGenerator;
-import org.bouncycastle.pqc.crypto.rainbow.RainbowParameters;
-import org.bouncycastle.pqc.crypto.rainbow.RainbowSigner;
-import org.bouncycastle.util.BigIntegers;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.FixedSecureRandom;
-import org.bouncycastle.util.test.SimpleTest;
-
-
-public class RainbowSignerTest
-extends SimpleTest
-{
- byte[] keyData = Hex.decode("b5014e4b60ef2ba8b6211b4062ba3224e0427dd3");
-
- SecureRandom keyRandom = new FixedSecureRandom(new byte[][] { keyData, keyData });
-
-
- public String getName()
- {
- return "Rainbow";
- }
-
- public void performTest()
- {
- RainbowParameters params = new RainbowParameters();
-
- RainbowKeyPairGenerator rainbowKeyGen = new RainbowKeyPairGenerator();
- RainbowKeyGenerationParameters genParam = new RainbowKeyGenerationParameters(keyRandom, params);
-
- rainbowKeyGen.init(genParam);
-
- AsymmetricCipherKeyPair pair = rainbowKeyGen.generateKeyPair();
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), keyRandom);
-
- DigestingMessageSigner rainbowSigner = new DigestingMessageSigner(new RainbowSigner() , new SHA224Digest());
- rainbowSigner.init(true, param);
-
- byte[] message = BigIntegers.asUnsignedByteArray(new BigInteger("968236873715988614170569073515315707566766479517"));
- rainbowSigner.update(message, 0, message.length);
- byte[] sig = rainbowSigner.generateSignature();
-
- rainbowSigner.init(false, pair.getPublic());
- rainbowSigner.update(message, 0, message.length);
- if (!rainbowSigner.verify(sig))
- {
- fail("verification fails");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new RainbowSignerTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/pqc/crypto/test/RegressionTest.java b/core/src/test/java/org/bouncycastle/pqc/crypto/test/RegressionTest.java
deleted file mode 100644
index bc5a9794..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/crypto/test/RegressionTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.bouncycastle.pqc.crypto.test;
-
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-public class RegressionTest
-{
- public static Test[] tests = {
- new GMSSSignerTest(),
- new McElieceFujisakiCipherTest(),
- new McElieceKobaraImaiCipherTest(),
- new McEliecePKCSCipherTest(),
- new McEliecePointchevalCipherTest(),
- new RainbowSignerTest()
- };
-
- public static void main(
- String[] args)
- {
- for (int i = 0; i != tests.length; i++)
- {
- TestResult result = tests[i].perform();
-
- if (result.getException() != null)
- {
- result.getException().printStackTrace();
- }
-
- System.out.println(result);
- }
- }
-}
-
diff --git a/core/src/test/java/org/bouncycastle/pqc/math/ntru/euclid/test/AllTests.java b/core/src/test/java/org/bouncycastle/pqc/math/ntru/euclid/test/AllTests.java
deleted file mode 100644
index 6302e053..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/math/ntru/euclid/test/AllTests.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.euclid.test;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-public class AllTests
- extends TestCase
-{
- public static void main (String[] args)
- {
- junit.textui.TestRunner.run(suite());
- }
-
- public static Test suite()
- {
- TestSuite suite = new TestSuite("NTRU Euclid Tests");
-
- suite.addTestSuite(BigIntEuclideanTest.class);
- suite.addTestSuite(IntEuclideanTest.class);
-
- return suite;
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/pqc/math/ntru/euclid/test/BigIntEuclideanTest.java b/core/src/test/java/org/bouncycastle/pqc/math/ntru/euclid/test/BigIntEuclideanTest.java
deleted file mode 100644
index 2cb94675..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/math/ntru/euclid/test/BigIntEuclideanTest.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.euclid.test;
-
-import java.math.BigInteger;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.math.ntru.euclid.BigIntEuclidean;
-
-public class BigIntEuclideanTest
- extends TestCase
-{
- public void testCalculate()
- {
- BigIntEuclidean r = BigIntEuclidean.calculate(BigInteger.valueOf(120), BigInteger.valueOf(23));
- assertEquals(BigInteger.valueOf(-9), r.x);
- assertEquals(BigInteger.valueOf(47), r.y);
- assertEquals(BigInteger.valueOf(1), r.gcd);
-
- r = BigIntEuclidean.calculate(BigInteger.valueOf(126), BigInteger.valueOf(231));
- assertEquals(BigInteger.valueOf(2), r.x);
- assertEquals(BigInteger.valueOf(-1), r.y);
- assertEquals(BigInteger.valueOf(21), r.gcd);
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/pqc/math/ntru/euclid/test/IntEuclideanTest.java b/core/src/test/java/org/bouncycastle/pqc/math/ntru/euclid/test/IntEuclideanTest.java
deleted file mode 100644
index ab2ba259..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/math/ntru/euclid/test/IntEuclideanTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * Copyright (c) 2011 Tim Buktu (tbuktu@hotmail.com)
- *
- * 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, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-package org.bouncycastle.pqc.math.ntru.euclid.test;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.math.ntru.euclid.IntEuclidean;
-
-public class IntEuclideanTest
- extends TestCase
-{
- public void testCalculate()
- {
- IntEuclidean r = IntEuclidean.calculate(120, 23);
- assertEquals(-9, r.x);
- assertEquals(47, r.y);
- assertEquals(1, r.gcd);
-
- r = IntEuclidean.calculate(126, 231);
- assertEquals(2, r.x);
- assertEquals(-1, r.y);
- assertEquals(21, r.gcd);
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/AllTests.java b/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/AllTests.java
deleted file mode 100644
index 296a66ed..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/AllTests.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial.test;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-public class AllTests
- extends TestCase
-{
- public static void main (String[] args)
- {
- junit.textui.TestRunner.run(suite());
- }
-
- public static Test suite()
- {
- TestSuite suite = new TestSuite("NTRU Polynomial Tests");
-
- suite.addTestSuite(BigDecimalPolynomialTest.class);
- suite.addTestSuite(BigIntPolynomialTest.class);
- suite.addTestSuite(IntegerPolynomialTest.class);
- suite.addTestSuite(LongPolynomial2Test.class);
- suite.addTestSuite(LongPolynomial5Test.class);
- suite.addTestSuite(ProductFormPolynomialTest.class);
- suite.addTestSuite(SparseTernaryPolynomialTest.class);
-
- return suite;
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/BigDecimalPolynomialTest.java b/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/BigDecimalPolynomialTest.java
deleted file mode 100644
index 06e9e043..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/BigDecimalPolynomialTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial.test;
-
-import java.math.BigDecimal;
-import java.security.SecureRandom;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.math.ntru.polynomial.BigDecimalPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.BigIntPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-
-public class BigDecimalPolynomialTest
- extends TestCase
-{
- public void testMult()
- {
- BigDecimalPolynomial a = new BigDecimalPolynomial(new BigIntPolynomial(new IntegerPolynomial(new int[]{4, -1, 9, 2, 1, -5, 12, -7, 0, -9, 5})));
- BigDecimalPolynomial b = new BigDecimalPolynomial(new BigIntPolynomial(new IntegerPolynomial(new int[]{-6, 0, 0, 13, 3, -2, -4, 10, 11, 2, -1})));
- BigDecimalPolynomial c = a.mult(b);
- BigDecimal[] expectedCoeffs = new BigDecimalPolynomial(new BigIntPolynomial(new IntegerPolynomial(new int[]{2, -189, 77, 124, -29, 0, -75, 124, -49, 267, 34}))).getCoeffs();
-
- BigDecimal[] cCoeffs = c.getCoeffs();
-
- assertEquals(expectedCoeffs.length, cCoeffs.length);
- for (int i = 0; i != cCoeffs.length; i++)
- {
- assertEquals(expectedCoeffs[i], cCoeffs[i]);
- }
-
- // multiply a polynomial by its inverse modulo 2048 and check that the result is 1
- SecureRandom random = new SecureRandom();
- IntegerPolynomial d, dInv;
- do
- {
- d = DenseTernaryPolynomial.generateRandom(1001, 333, 334, random);
- dInv = d.invertFq(2048);
- }
- while (dInv == null);
-
- d.mod(2048);
- BigDecimalPolynomial e = new BigDecimalPolynomial(new BigIntPolynomial(d));
- BigIntPolynomial f = new BigIntPolynomial(dInv);
- IntegerPolynomial g = new IntegerPolynomial(e.mult(f).round());
- g.modPositive(2048);
- assertTrue(g.equalsOne());
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/BigIntPolynomialTest.java b/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/BigIntPolynomialTest.java
deleted file mode 100644
index a6ad36e5..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/BigIntPolynomialTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial.test;
-
-import java.math.BigInteger;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.math.ntru.polynomial.BigIntPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-
-public class BigIntPolynomialTest
- extends TestCase
-{
- public void testMult()
- {
- BigIntPolynomial a = new BigIntPolynomial(new IntegerPolynomial(new int[]{4, -1, 9, 2, 1, -5, 12, -7, 0, -9, 5}));
- BigIntPolynomial b = new BigIntPolynomial(new IntegerPolynomial(new int[]{-6, 0, 0, 13, 3, -2, -4, 10, 11, 2, -1}));
- BigIntPolynomial c = a.mult(b);
- BigInteger[] expectedCoeffs = new BigIntPolynomial(new IntegerPolynomial(new int[]{2, -189, 77, 124, -29, 0, -75, 124, -49, 267, 34})).getCoeffs();
- BigInteger[] cCoeffs = c.getCoeffs();
-
- assertEquals(expectedCoeffs.length, cCoeffs.length);
- for (int i = 0; i != cCoeffs.length; i++)
- {
- assertEquals(expectedCoeffs[i], cCoeffs[i]);
- }
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/IntegerPolynomialTest.java b/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/IntegerPolynomialTest.java
deleted file mode 100644
index 8f6e489e..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/IntegerPolynomialTest.java
+++ /dev/null
@@ -1,230 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.crypto.ntru.NTRUSigningKeyGenerationParameters;
-import org.bouncycastle.pqc.math.ntru.polynomial.BigIntPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.Resultant;
-import org.bouncycastle.util.Arrays;
-
-
-public class IntegerPolynomialTest
- extends TestCase
-{
- public void testMult()
- {
- // multiplication modulo q
- IntegerPolynomial a = new IntegerPolynomial(new int[]{-1, 1, 1, 0, -1, 0, 1, 0, 0, 1, -1});
- IntegerPolynomial b = new IntegerPolynomial(new int[]{14, 11, 26, 24, 14, 16, 30, 7, 25, 6, 19});
- IntegerPolynomial c = a.mult(b, 32);
- assertEqualsMod(new int[]{3, -7, -10, -11, 10, 7, 6, 7, 5, -3, -7}, c.coeffs, 32);
-
- a = new IntegerPolynomial(new int[]{15, 27, 18, 16, 12, 13, 16, 2, 28, 22, 26});
- b = new IntegerPolynomial(new int[]{-1, 0, 1, 1, 0, 1, 0, 0, -1, 0, -1});
- c = a.mult(b, 32);
- assertEqualsMod(new int[]{8, 25, 22, 20, 12, 24, 15, 19, 12, 19, 16}, c.coeffs, 32);
-
- // multiplication without a modulus
- a = new IntegerPolynomial(new int[]{1, 1, 0, 0, -1, -1, 0, 0, -1, 0, 1});
- b = new IntegerPolynomial(new int[]{704, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
- c = a.mult(b);
-
- // mult(p, modulus) should give the same result as mult(p) followed by modulus
- a = new IntegerPolynomial(new int[]{1, 0, -1, 1, 0, 1, 1, 1, -1, 1, -1});
- b = new IntegerPolynomial(new int[]{0, 1, 1, 0, 0, -1, -1, 1, 1, -1, 1});
- c = a.mult(b);
- c.modPositive(20);
- IntegerPolynomial d = a.mult(b, 20);
- d.modPositive(20);
- assertTrue(Arrays.areEqual(c.coeffs, d.coeffs));
- }
-
- void assertEqualsMod(int[] arr1, int[] arr2, int m)
- {
- assertEquals(arr1.length, arr2.length);
- for (int i = 0; i < arr1.length; i++)
- {
- assertEquals((arr1[i] + m) % m, (arr2[i] + m) % m);
- }
- }
-
- public void testInvertFq()
- {
- SecureRandom random = new SecureRandom();
- // Verify an example from the NTRU tutorial
- IntegerPolynomial a = new IntegerPolynomial(new int[]{-1, 1, 1, 0, -1, 0, 1, 0, 0, 1, -1});
- IntegerPolynomial b = a.invertFq(32);
- assertEqualsMod(new int[]{5, 9, 6, 16, 4, 15, 16, 22, 20, 18, 30}, b.coeffs, 32);
- verifyInverse(a, b, 32);
-
- // test 3 random polynomials
- int numInvertible = 0;
- while (numInvertible < 3)
- {
- a = DenseTernaryPolynomial.generateRandom(853, random);
- b = a.invertFq(2048);
- if (b != null)
- {
- numInvertible++;
- verifyInverse(a, b, 2048);
- }
- }
-
- // test a non-invertible polynomial
- a = new IntegerPolynomial(new int[]{-1, 0, 1, 1, 0, 0, -1, 0, -1, 0, 1});
- b = a.invertFq(32);
- assertNull(b);
- }
-
- public void testInvertF3()
- {
- IntegerPolynomial a = new IntegerPolynomial(new int[]{-1, 1, 1, 0, -1, 0, 1, 0, 0, 1, -1});
- IntegerPolynomial b = a.invertF3();
- assertEqualsMod(new int[]{1, 2, 0, 2, 2, 1, 0, 2, 1, 2, 0}, b.coeffs, 3);
- verifyInverse(a, b, 3);
-
- // test a non-invertible polynomial
- a = new IntegerPolynomial(new int[]{0, 1, -1, 1, 0, 0, 0, 0, -1, 0, 0});
- b = a.invertF3();
- assertNull(b);
- }
-
- // tests if a*b=1 (mod modulus)
- private void verifyInverse(IntegerPolynomial a, IntegerPolynomial b, int modulus)
- {
- IntegerPolynomial c = a.mult(b, modulus);
- for (int i = 1; i < c.coeffs.length; i++)
- {
- c.coeffs[i] %= modulus;
- }
- c.ensurePositive(modulus);
- assertTrue(c.equalsOne());
- }
-
- public void testFromToBinary()
- {
- byte[] a = new byte[]{-44, -33, 30, -109, 101, -28, -6, -105, -45, 113, -72, 99, 101, 15, 9, 49, -80, -76, 58, 42, -57, -113, -89, -14, -125, 24, 125, -16, 37, -58, 10, -49, -77, -31, 120, 103, -29, 105, -56, -126, -92, 36, 125, 127, -90, 38, 9, 4, 104, 10, -78, -106, -88, -1, -1, -43, -19, 90, 41, 0, -43, 102, 118, -72, -122, 19, -76, 57, -59, -2, 35, 47, 83, 114, 86, -115, -125, 58, 75, 115, -29, -6, 108, 6, -77, -51, 127, -8, -8, -58, -30, -126, 110, -5, -35, -41, -37, 69, 22, -48, 26, 4, -120, -19, -32, -81, -77, 124, -7, -2, -46, -96, 38, -35, 88, 4, -5, 16, 101, 29, 7, 2, 88, 35, -64, 31, -66, -70, 120, -97, 76, -74, -97, -61, 52, -56, 87, -35, 5, 95, -93, -30, 10, 38, 17, -102, -25, 86, 7, -43, 44, -52, -108, 33, -18, -110, -9, -115, 66, -71, 66, 1, -90, -72, 90, -88, -38, 75, 47, -124, -120, -15, -49, -8, 85, 5, 17, -88, 76, 99, -4, 83, 16, -91, 82, 116, 112, -83, 56, -45, -26, 125, 13, -75, -115, 92, -12, -59, 3, -12, 14, -6, 43, -17, 121, 122, 22, 92, -74, 99, -59, -103, 113, 8, -103, 114, 99, -48, 92, -88, 77, 81, 5, 31, -4, -69, -24, 23, 94, 126, 71, 93, 20, 77, 82, -54, -14, 86, 45, -81, 0, 52, -63, -66, 48, 104, -54, 15, -73, -2, -52, 115, 76, 28, -5, -94, -63, 117, -69, 0, 61, 22, -1, 71, -115, 9, -73, -100, -128, -31, 106, -74, -61, -37, 98, -6, 11, -5, 6, -18, -53, -6, 11, -49, 62, 23, 6, -128, 38, -91, 89, -34, 18, -38, -110, -101, 43, 36, 62, 101, 112, 59, -91, 78, -81, 61, 126, -21, -42, -110, -38, -27, 69, 57, 9, 24, -50, -118, 31, -17, 42, 87, -54, 122, -16, 42, -47, -19, -80, 16, 54, -97, -89, 81, -22, -35, 45, 54, -46, 22, -122, -95, -17, 7, -127, 105, -100, -56, -98, -105, 101, -81, 104, 121, -7, 33, 126, 110, -125, -85, 111, -52, 123, -98, 41, -42, 88, -68, -17, 39, -19, -96, -10, -117, 13, -88, -75, -101, -16, -7, 73, 23, -12, 41, -116, -105, -64, -4, 103, 49, -15, -49, 60, 88, -25, -21, 42, 26, 95, -90, -83, -69, 64, -2, 50, -116, -64, 26, -29, -93, -120, -70, 32, -38, 39, -126, -19, 103, 127, 65, 54, 110, 94, 126, -82, -80, -18, 43, 45, 56, -118, 109, 36, -8, 10, 113, 69, 53, -122, -127, 92, -127, -73, 70, -19, -105, -80, -15, -5, 99, -109, -27, 119, -76, -57, -48, 42, -35, 23, 39, -126, 44, -107, -100, -125, 117, -50, 115, -79, -16, 104, 8, -102, 83, -73, 21, -85, 113, -87, -54, 93, 63, -108, -64, 109, -74, 15, 14, -119, -6, -68, 45, 37, -15, -97, -95, -55, 89, 25, -63, -92, -80, -27, -8, 55, 50, 96, -91, 40, -74, 110, -96, 94, 6, 85, 92, 0, 34, -122, 5, -126, 123, 37, -90, -94, 60, 14, 36, 49, -98, -23, 57, 75, 63, 106, -7, -36, -89, 84, 71, 60, -21, 104, -47, 90, -52, -66, 88, -91, -81, -3, 116, 23, 62, -47, -84, -118, 65, 31, 7, -103, 37, -29, 115, -114, 73, 12, -121, 96, -91, -7, 56, 10, -72, 27, -45, 122, -27, -38, 74, 64, 30, -60, 64, -21, 48, 101, 113, 126, -60, -103, 71, 100, -117, 124, -125, 116, 78, 114, -74, 42, -81, -54, 34, 33, -10, 19, 23, 24, 40, 0, -8, 78, 100, 73, -88, -95, -62, -115, -18, 47, 10, -14, -39, 82, 27, -9, -115, -70, 92, -6, 39, 45, -71, -109, -41, 94, -88, -63, 19, -58, -37, -31, 1, 127, -42, 125, -120, -57, 120, -86, -6, 17, -27, -37, 47, 55, -22, -11, -31, 38, -1, 29, 56, -34, -104, -66, -62, 72, -11, -30, -30, 61, -31, 10, -63, 116, -84, 118, -127, 6, 17, -36, 91, 123, 77, 35, 22, 110, 114, 107, -3, 52, 11, 86, 68, -56, 0, 119, -43, -73, 112, 89, -4, -122, -71, -26, 103, -118, -61, -112, -108, -44, -25, -22, 4, 24, 53, -5, -71, 9, -41, 84, -28, 22, 99, 39, -26, -2, -51, 68, 63, -15, 99, 66, -78, 46, -89, 21, -38, -114, -51, 100, -59, 84, -76, -105, 51, 28, 19, 74, 42, 91, -73, 12, -89, -128, 34, 38, -100, 121, -78, 114, -28, 127, -29, 50, 105, -6, 36, 98, -35, 79, -58, 5, -13, -86, -101, -108, -99, -70, 25, 103, 63, 57, 79, -12, -63, 125, -54, 61, 15, 6, -79, 90, 76, 103, -45, 7, 39, 93, 107, 58, 76, 80, 56, -108, 55, -22, 36, 125, -91, -65, 11, 69, 10, -19, -14, -4, -26, -36, 114, 124, 63, -31, 88, 92, 108, 33, -52, -22, 80, -65, 57, 126, 43, -13, 122, -8, 68, 72, 92, -50, 100, -91, 1, -81, 75, 95, -11, -99, 38, 121, -20, -70, 82, -125, -94, -18, 16, 59, 89, 18, -96, 91, -97, 62, -96, 127, 45, 70, 16, 84, -43, -75, -118, 81, 58, 84, -115, -120, -3, 41, -103, -70, 123, 26, 101, 33, 58, 13, -11, -73, -84, -47, -7, 81, -63, 60, -45, 30, 100, -51, -15, 73, 58, -119, -3, 62, -63, -17, -69, -44, 60, -54, -115, -59, 23, -59, 98, -89, -72, 20, -96, 27, 53, -89, 59, -85, -29, 120, 23, 62, 8, -86, 113, 87, -15, 102, 106, -104, 57, -57, 37, 110, 118, 109, 25, 64, 26, -20, -86, -2, 60, -70, -33, 67, 13, -28, -29, -63, -37, 67, 99, 84, 121, -126, -38, 45, 24, 122, 51, 11, -19, -80, 26, -106, -95, 82, 69, -2, -75, 62, 106, -120, 87, -107, 87, 17, 102, -52, -16, 22, 12, -86, -48, -95, -61, 109, 64, -29, 111, 40, -90, -35, 49, 88, -15, 122, 127, 87, 113, 116, 93, 100, 28, -70, -87, -40, -1, -126, -114, 7, 79, 16, 2, -47, -98, -102, 49, 58, 61, -32, 44, 18, -26, 37, 27, -123, -76, 56, 91, 51, -21, -48, -122, -33, 40, -8, -62, -56, -126, 91, -51, 76, -29, 127, -22, -18, -110, 27, 13, -111, 81, 51, -104, 70, 98, 12, 120, -7, 15, 104, -43, -104, 124, 46, 116, 7, -26, 21, 33, 105, 17, -99, -42, -106, 8, -85, 39, 8, 79, -54, -81, 109, 40, 25, 29, -18, -90, 22, 85, -12, -16, 61, 49, -31, 127, 64, 5, 25, 39, -65, -42, 13, -97, -92, 36, -126, -18, -4, -22, -14, 109, -93, -76, -5, 13, 74, 44, 103, 79, 110, 85, 58, 39, -24, 119, 120, 122, 120, 43, 110, 67, 21, 47, 39, -48, 7, 91, -51, 126, 100, -38, -124, 0, -97, 99, -123, 118, -27, 8, 102, -106, -23, -53, -4, -56, -9, -126, -85, 93, -4, -5, 4, 49, 29, 2, 63, 78, -32, -106, 118, 111, 52, 54, 74, 53, 106, 39, -95, -38, -18, 118, -5, 94, -83, -97, -27, 62, -56, -90, -36, 43, 43, -113, 119, -89, 44, -108, -46, 66, 28, 66, -38, 3, -62, -83, -35, -127, -2, 51, 104, 105, 40, 76, -10, -124, -95, 52, 11, 101, -32, -122, -73, -17, 37, -126, 68, -126, 55, 112, -126, 38, 99, -63, 123, -74, -31, 58, 8, 93, -68, 111, -22, -24, -23, 9, -87, -25, -115, 81, -116, -91, 60, 96, -102, -1, -7, 73, 99, 46, -78, 62, 48, -116, -52, -44, -5, 82, -45, 5, -55, -101, 101, 65, -109, -108, 26, 98, -55, 11, -86, 57, 30, 92, -58, 20, 82, 65, 103, 27, -64, 76, 123, -56, -16, -111, -83, 125, 65, 111, 9, 123, 14, 119, 126, -80, 79, 94, -19, 66, -25, 35, 112, -64, 10, -66, -86, 51, 56, -78, 103, 92, -116, 8, 75, 41, -49, -79, -53, 125, -32, -76, -27, 59, -8, -4, -94, -104, -15, 79, -7, -124, 32, -87, -104, 85, -118, -36, 125, 65, 111, -105, 5, -105, 40, -50, 2, 118, 123, -54, 59, -22, 94, 20, 99, -87, -27, 28, -30, -109, 72, -19, 92, 60, 19, 115, 47, 96, -96, 10, -74, 60, 96, -86, 101, 101, 68, -44, -72, 9, -36, 126, 96, -45, -12, 9, 14, -15, 79, -79, -48, 8, -107, -81, 47, 35, -36, -107, -120, -36, -124, 37, 103, -60, -35, -74, 100, -38, -88, -99, -99, -94, -107, 79, 115, 108, 54, 119, 73, 84, 110, -74, 92, 57, 108, 80, 47, -36, -119, -115, 58, -62, -4, -97, 43, -98, 5, 112, 47, 59, -89, 82, -69, -103, 39, -29, 75, -9, -94, -72, 99, -64, 22, -10, 21, 89, 101, 21, 94, -30, -17, 73, -36, -68, -89, -91, -94, 99, -106, 119, -116, 123, -19, 54, -99, 64, -119, 82, 120, -106, -99, 80, 69, 29, -48, 77, 28, 13, 92, -107, -77, 94, -116, 108, 89, -115, 96, -41, 25, 99, -65, 118, -5, -16, 48, -122, 5, 50, -123, -115, 13, 24, 7, 15, -103, -62, -71, 92, -82, -5, -70, 49, -6, -51, -17, -47, 12, 46, -86, 30, 93, 84, -101, 43, -92, -87, -118, -110, -32, 52, 115, -4, 36, -2, -79, -69, -46, -110, 70, -82, 6, 21, -27, -11, 94, 42, -81, -96, 116, -102, -38, 36, 32, 91, 28, 80, -45, 116, -94, -33, -5, -102, 64, -96, 27, -2, 100, -126, 59, -71, 33, -36, -124, 123, 99, -76, 108, 127, -11, -24, -19, 84, -6, 19, 105, -19, -18, 120, -14, 23, 39, 54, 87, 105, 58, -95, -15, 127, -65, 114, 49, 4, -66, 32, -7, 84, 43, -103, 76, 11, 36, -68, -3, -98, -5, -43, 35, -48, 20, -40, -33, -123, 1, -54, -44, 99, -68, 8, -100, 97, -49, -10, 110, 49, 84, 46, -85, 98, -103, -58, -4, 104, -100, -40, -79, 67, -20, -95, 85, 51, 73, 10, -25, 102, 68, -97, -83, -39, 35, 2, -111, 71, 62, -89, 20, 25, -126, 17, -81, -29, 39, -27, -55, 55, -122, 97, 23, -99, 55, 86, 33, -9, 8, 55, -40, -84, 39, 38, 37, -29, 87, 113, -118, -26, 123, -95, 24, -126, 119, -94, 17, 83, -43, 10, 63, -98, 72, 8, 16, -95, -96, 119, -91, 6, 71, -60, 1, -77, 4, 53, -121, 55, 7, 36, -86, -49, -118, -121, 56, 84, -49, -57, -99, 3, -68, 37, -108, -72, 114, -74, 120, 3, 121, -28, -106, 54, -20, 63, -121, -85, -59, -111, 32, 13, -69, 122, 90, 5, 40, 88, 15, -90, 125, -28, 89, 95, 73, 96, 60, -60, -51, 102, 7, 57, 91, 59, 15, 92, -76, -34, -23, -77, 90, 45, 91, 77, -63, 94, -127, 74, -97, -44, 50, -87, -94, -25, -71, 112, 127, -117, 6, 32, -113, 54, 83, -31, 111, -73, 53, 34, -32, -98, 125, -39, 63, 15, 72, -69, 87, -118, 108, 17, 84, 15, 61, -47, 54, -24, -79, 91, 28, -28, 66, 53, 22, 9, -28, -12, 38, 64, 75, -122, 96, -59, -45, 4, -19, 47, -30, 75, -94, 62, -64, 76, -49, 19, -66, -34, 3, 84, -2, -54, 13, -84, 86, -117, 94, -27, 89, 16, 96, 52, -77, -36, -116, 27, -52, -33, -50, 14, -59, 77, 93, -109, 8, -89, 81, -114, -29, -94, 73, -119, -56, -19, 88, -17, -33, 125, -18, -68, 113, 40, -128, -112, -119, -106, -106, -30, 23, -77, 49, 3, 98, -101, 99, -107, -121, -12, -112, 24, -74, -74, 79, -17, 96, 65, -52, 86, -63, 45, 84, 119, -42, 61, -91, 29, -87, 65, -85, 99, -14, 71, 33, -41, -48, -2, -121, 78, -38, 41, -7, -37, 48, 122, 61, -124, 42, -22, 24, 2, -49, 74, -81, -88, -89, -107, 109, 53, -68, 90, -117, 123, -109, -28, 12, 80, 120, 26, -104, 73, 70, -36, 34, -80, -104, 23, 16, 14, -96, -5, 27, 71, 25, -8, -125, 58, 88, -52, -97, -97, -93, 11, -44, 116, 42, -102, -100, -31, -86, 71, 84, 70, 27, 117, -67, 92, -84, -13, 54, -102, 34, 5, 19, -76, 71, 89, 22, -49, -34, -29};
- IntegerPolynomial poly = IntegerPolynomial.fromBinary(a, 1499, 2048);
- byte[] b = poly.toBinary(2048);
- // verify that bytes 0..2047 match, ignore non-relevant bits of byte 2048
- assertTrue(Arrays.areEqual(copyOf(a, 2047), copyOf(b, 2047)));
- assertEquals((a[a.length - 1] & 1) >> (7 - (1499 * 11) % 8), (b[b.length - 1] & 1) >> (7 - (1499 * 11) % 8));
- }
-
- public void testFromToBinary3Sves()
- {
- byte[] a = new byte[]{-112, -78, 19, 15, 99, -65, -56, -90, 44, -93, -109, 104, 40, 90, -84, -21, -124, 51, -33, 4, -51, -106, 33, 86, -76, 42, 41, -17, 47, 79, 81, -29, 15, 116, 101, 120, 116, 32, 116, 111, 32, 101, 110, 99, 114, 121, 112, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- IntegerPolynomial poly = IntegerPolynomial.fromBinary3Sves(a, 1499);
- byte[] b = poly.toBinary3Sves();
- assertTrue(Arrays.areEqual(a, b));
- }
-
- public void testFromToBinary3Tight()
- {
- int[] c = new int[]{0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 1, 0, 1, 0, -1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0};
- IntegerPolynomial poly1 = new IntegerPolynomial(c);
- IntegerPolynomial poly2 = IntegerPolynomial.fromBinary3Tight(poly1.toBinary3Tight(), c.length);
- assertTrue(Arrays.areEqual(poly1.coeffs, poly2.coeffs));
-
- IntegerPolynomial poly3 = new IntegerPolynomial(new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, -1, -1, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0});
- byte[] arr = poly3.toBinary3Tight();
- IntegerPolynomial poly4 = IntegerPolynomial.fromBinary3Tight(arr, 1499);
- assertTrue(Arrays.areEqual(poly3.coeffs, poly4.coeffs));
-
- IntegerPolynomial poly5 = new IntegerPolynomial(new int[]{0, 0, 0, 1, -1, -1, -1});
- arr = poly5.toBinary3Tight();
- IntegerPolynomial poly6 = IntegerPolynomial.fromBinary3Tight(arr, 7);
- assertTrue(Arrays.areEqual(poly5.coeffs, poly6.coeffs));
-
- SecureRandom random = new SecureRandom();
-
- for (int i = 0; i < 100; i++)
- {
- IntegerPolynomial poly7 = DenseTernaryPolynomial.generateRandom(157, random);
- arr = poly7.toBinary3Tight();
- IntegerPolynomial poly8 = IntegerPolynomial.fromBinary3Tight(arr, 157);
- assertTrue(Arrays.areEqual(poly7.coeffs, poly8.coeffs));
- }
- }
-
- public void testResultant()
- {
- SecureRandom random = new SecureRandom();
- NTRUSigningKeyGenerationParameters params = NTRUSigningKeyGenerationParameters.APR2011_439;
- IntegerPolynomial a = DenseTernaryPolynomial.generateRandom(params.N, params.d, params.d, random);
- verifyResultant(a, a.resultant());
-
- a = new IntegerPolynomial(new int[]{0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 1, -1, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, -1, -1, 0, -1, 1, -1, 0, -1, 0, -1, -1, -1, 0, 0, 0, 1, 1, -1, -1, -1, 0, -1, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 1, 1, -1, 0, 1, -1, 0, 1, 0, 1, 0, -1, -1, 0, 1, 0, -1, 1, 1, 1, 1, 0, 0, -1, -1, 1, 0, 0, -1, -1, 0, -1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 1, 0, 1, -1, 0, 0, 1, 1, 1, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0, -1, -1, 0, -1, -1, -1, 0, -1, -1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, -1, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, -1, -1, 0, -1, -1, 1, 1, 0, 0, -1, 1, 0, 0, 0, -1, 1, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 1, 1, 0, 0, -1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, -1, 0, 1, 0, -1, -1, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 1, -1, 1, -1, -1, 1, -1, 0, 1, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, -1, 0, 1, -1, 0, 0, 1, 1, 0, 0, 1, 1, 0, -1, 0, -1, 1, -1, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 1, -1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, -1, -1, 0, 0, -1, 0, 1, 1, -1, 1, -1, 0, 0, 0, 1});
- verifyResultant(a, a.resultant());
- }
-
- // verifies that res=rho*a mod x^n-1
- private void verifyResultant(IntegerPolynomial a, Resultant r)
- {
- BigIntPolynomial b = new BigIntPolynomial(a).mult(r.rho);
- BigInteger[] bCoeffs = b.getCoeffs();
-
- for (int j = 1; j < bCoeffs.length - 1; j++)
- {
- assertEquals(BigInteger.ZERO, bCoeffs[j]);
- }
- if (r.res.equals(BigInteger.ZERO))
- {
- assertEquals(BigInteger.ZERO, bCoeffs[0].subtract(bCoeffs[bCoeffs.length - 1]));
- }
- else
- {
- assertEquals(BigInteger.ZERO, (bCoeffs[0].subtract(bCoeffs[bCoeffs.length - 1]).mod(r.res)));
- }
- assertEquals(bCoeffs[0].subtract(r.res), bCoeffs[bCoeffs.length - 1].negate());
- }
-
- public void testResultantMod()
- {
- int p = 46337; // prime; must be less than sqrt(2^31) or integer overflows will occur
-
- IntegerPolynomial a = new IntegerPolynomial(new int[]{0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 1, -1, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, -1, -1, 0, -1, 1, -1, 0, -1, 0, -1, -1, -1, 0, 0, 0, 1, 1, -1, -1, -1, 0, -1, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 1, 1, -1, 0, 1, -1, 0, 1, 0, 1, 0, -1, -1, 0, 1, 0, -1, 1, 1, 1, 1, 0, 0, -1, -1, 1, 0, 0, -1, -1, 0, -1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 1, 0, 1, -1, 0, 0, 1, 1, 1, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0, -1, -1, 0, -1, -1, -1, 0, -1, -1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, -1, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, -1, -1, 0, -1, -1, 1, 1, 0, 0, -1, 1, 0, 0, 0, -1, 1, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 1, 1, 0, 0, -1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, -1, 0, 1, 0, -1, -1, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 1, -1, 1, -1, -1, 1, -1, 0, 1, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, -1, 0, 1, -1, 0, 0, 1, 1, 0, 0, 1, 1, 0, -1, 0, -1, 1, -1, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 1, -1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, -1, -1, 0, 0, -1, 0, 1, 1, -1, 1, -1, 0, 0, 0, 1});
- verifyResultant(a, a.resultant(p), p);
-
- SecureRandom random = new SecureRandom();
-
- for (int i = 0; i < 10; i++)
- {
- a = DenseTernaryPolynomial.generateRandom(853, random);
- verifyResultant(a, a.resultant(p), p);
- }
- }
-
- // verifies that res=rho*a mod x^n-1 mod p
- private void verifyResultant(IntegerPolynomial a, Resultant r, int p)
- {
- BigIntPolynomial b = new BigIntPolynomial(a).mult(r.rho);
- b.mod(BigInteger.valueOf(p));
- BigInteger[] bCoeffs = b.getCoeffs();
-
- for (int j = 1; j < bCoeffs.length - 1; j++)
- {
- assertEquals(BigInteger.ZERO, bCoeffs[j]);
- }
- if (r.res.equals(BigInteger.ZERO))
- {
- assertEquals(BigInteger.ZERO, bCoeffs[0].subtract(bCoeffs[bCoeffs.length - 1]));
- }
- else
- {
- assertEquals(BigInteger.ZERO, (bCoeffs[0].subtract(bCoeffs[bCoeffs.length - 1]).subtract(r.res).mod(BigInteger.valueOf(p))));
- }
- assertEquals(BigInteger.ZERO, bCoeffs[0].subtract(r.res).subtract(bCoeffs[bCoeffs.length - 1].negate()).mod(BigInteger.valueOf(p)));
- }
-
- private byte[] copyOf(byte[] src, int length)
- {
- byte[] tmp = new byte[length];
- System.arraycopy(src, 0, tmp, 0, tmp.length);
- return tmp;
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/LongPolynomial2Test.java b/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/LongPolynomial2Test.java
deleted file mode 100644
index c8420646..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/LongPolynomial2Test.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial.test;
-
-import java.util.Random;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.LongPolynomial2;
-import org.bouncycastle.util.Arrays;
-
-public class LongPolynomial2Test
- extends TestCase
-{
- public void testMult()
- {
- IntegerPolynomial i1 = new IntegerPolynomial(new int[]{1368, 2047, 672, 871, 1662, 1352, 1099, 1608});
- IntegerPolynomial i2 = new IntegerPolynomial(new int[]{1729, 1924, 806, 179, 1530, 1381, 1695, 60});
- LongPolynomial2 a = new LongPolynomial2(i1);
- LongPolynomial2 b = new LongPolynomial2(i2);
- IntegerPolynomial c1 = i1.mult(i2, 2048);
- IntegerPolynomial c2 = a.mult(b).toIntegerPolynomial();
- assertTrue(Arrays.areEqual(c1.coeffs, c2.coeffs));
-
- // test 10 random polynomials
- Random rng = new Random();
- for (int i = 0; i < 10; i++)
- {
- int N = 2 + rng.nextInt(2000);
- i1 = PolynomialGenerator.generateRandom(N, 2048);
- i2 = PolynomialGenerator.generateRandom(N, 2048);
- a = new LongPolynomial2(i1);
- b = new LongPolynomial2(i2);
- c1 = i1.mult(i2);
- c1.modPositive(2048);
- c2 = a.mult(b).toIntegerPolynomial();
- assertTrue(Arrays.areEqual(c1.coeffs, c2.coeffs));
- }
- }
-
- public void testSubAnd()
- {
- IntegerPolynomial i1 = new IntegerPolynomial(new int[]{1368, 2047, 672, 871, 1662, 1352, 1099, 1608});
- IntegerPolynomial i2 = new IntegerPolynomial(new int[]{1729, 1924, 806, 179, 1530, 1381, 1695, 60});
- LongPolynomial2 a = new LongPolynomial2(i1);
- LongPolynomial2 b = new LongPolynomial2(i2);
- a.subAnd(b, 2047);
- i1.sub(i2);
- i1.modPositive(2048);
- assertTrue(Arrays.areEqual(a.toIntegerPolynomial().coeffs, i1.coeffs));
- }
-
- public void testMult2And()
- {
- IntegerPolynomial i1 = new IntegerPolynomial(new int[]{1368, 2047, 672, 871, 1662, 1352, 1099, 1608});
- LongPolynomial2 i2 = new LongPolynomial2(i1);
- i2.mult2And(2047);
- i1.mult(2);
- i1.modPositive(2048);
- assertTrue(Arrays.areEqual(i1.coeffs, i2.toIntegerPolynomial().coeffs));
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/LongPolynomial5Test.java b/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/LongPolynomial5Test.java
deleted file mode 100644
index cf91ac27..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/LongPolynomial5Test.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial.test;
-
-import java.security.SecureRandom;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.LongPolynomial5;
-import org.bouncycastle.util.Arrays;
-
-public class LongPolynomial5Test
- extends TestCase
-{
- public void testMult()
- {
- testMult(new int[]{2}, new int[]{-1});
- testMult(new int[]{2, 0}, new int[]{-1, 0});
- testMult(new int[]{2, 0, 3}, new int[]{-1, 0, 1});
- testMult(new int[]{2, 0, 3, 1}, new int[]{-1, 0, 1, 1});
- testMult(new int[]{2, 0, 3, 1, 2}, new int[]{-1, 0, 1, 1, 0});
- testMult(new int[]{2, 0, 3, 1, 1, 5}, new int[]{1, -1, 1, 1, 0, 1});
- testMult(new int[]{2, 0, 3, 1, 1, 5, 1, 4}, new int[]{1, 0, 1, 1, -1, 1, 0, -1});
- testMult(new int[]{1368, 2047, 672, 871, 1662, 1352, 1099, 1608}, new int[]{1, 0, 1, 1, -1, 1, 0, -1});
-
- // test random polynomials
- SecureRandom rng = new SecureRandom();
- for (int i = 0; i < 10; i++)
- {
- int[] coeffs1 = new int[rng.nextInt(2000) + 1];
- int[] coeffs2 = DenseTernaryPolynomial.generateRandom(coeffs1.length, rng).coeffs;
- testMult(coeffs1, coeffs2);
- }
- }
-
- private void testMult(int[] coeffs1, int[] coeffs2)
- {
- IntegerPolynomial i1 = new IntegerPolynomial(coeffs1);
- IntegerPolynomial i2 = new IntegerPolynomial(coeffs2);
-
- LongPolynomial5 a = new LongPolynomial5(i1);
- DenseTernaryPolynomial b = new DenseTernaryPolynomial(i2);
- IntegerPolynomial c1 = i1.mult(i2, 2048);
- IntegerPolynomial c2 = a.mult(b).toIntegerPolynomial();
- assertEqualsMod(c1.coeffs, c2.coeffs, 2048);
- }
-
- private void assertEqualsMod(int[] arr1, int[] arr2, int m)
- {
- assertEquals(arr1.length, arr2.length);
- for (int i = 0; i < arr1.length; i++)
- {
- assertEquals((arr1[i] + m) % m, (arr2[i] + m) % m);
- }
- }
-
- public void testToIntegerPolynomial()
- {
- int[] coeffs = new int[]{2, 0, 3, 1, 1, 5, 1, 4};
- LongPolynomial5 p = new LongPolynomial5(new IntegerPolynomial(coeffs));
- assertTrue(Arrays.areEqual(coeffs, p.toIntegerPolynomial().coeffs));
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/PolynomialGenerator.java b/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/PolynomialGenerator.java
deleted file mode 100644
index 8f931d7a..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/PolynomialGenerator.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial.test;
-
-import java.util.Random;
-
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-
-public class PolynomialGenerator
-{
- /**
- * Creates a random polynomial with <code>N</code> coefficients
- * between <code>0</code> and <code>q-1</code>.
- *
- * @param N length of the polynomial
- * @param q coefficients will all be below this number
- * @return a random polynomial
- */
- public static IntegerPolynomial generateRandom(int N, int q)
- {
- Random rng = new Random();
- int[] coeffs = new int[N];
- for (int i = 0; i < N; i++)
- {
- coeffs[i] = rng.nextInt(q);
- }
- return new IntegerPolynomial(coeffs);
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/ProductFormPolynomialTest.java b/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/ProductFormPolynomialTest.java
deleted file mode 100644
index 9fbbb981..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/ProductFormPolynomialTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial.test;
-
-import java.security.SecureRandom;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.crypto.ntru.NTRUEncryptionKeyGenerationParameters;
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.ProductFormPolynomial;
-
-public class ProductFormPolynomialTest
- extends TestCase
-{
- private NTRUEncryptionKeyGenerationParameters params;
- private int N;
- private int df1;
- private int df2;
- private int df3;
- private int q;
-
- public void setUp()
- {
- params = NTRUEncryptionKeyGenerationParameters.APR2011_439_FAST;
- N = params.N;
- df1 = params.df1;
- df2 = params.df2;
- df3 = params.df3;
- q = params.q;
- }
-
- public void testFromToBinary()
- throws Exception
- {
- ProductFormPolynomial p1 = ProductFormPolynomial.generateRandom(N, df1, df2, df3, df3 - 1, new SecureRandom());
- byte[] bin1 = p1.toBinary();
- ProductFormPolynomial p2 = ProductFormPolynomial.fromBinary(bin1, N, df1, df2, df3, df3 - 1);
- assertEquals(p1, p2);
- }
-
- public void testMult()
- {
- ProductFormPolynomial p1 = ProductFormPolynomial.generateRandom(N, df1, df2, df3, df3 - 1, new SecureRandom());
- IntegerPolynomial p2 = PolynomialGenerator.generateRandom(N, q);
- IntegerPolynomial p3 = p1.mult(p2);
- IntegerPolynomial p4 = p1.toIntegerPolynomial().mult(p2);
- assertEquals(p3, p4);
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/SparseTernaryPolynomialTest.java b/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/SparseTernaryPolynomialTest.java
deleted file mode 100644
index 3d434c68..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/math/ntru/polynomial/test/SparseTernaryPolynomialTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.security.SecureRandom;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.math.ntru.polynomial.BigIntPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial;
-
-public class SparseTernaryPolynomialTest
- extends TestCase
-{
-
- /**
- * tests mult(IntegerPolynomial) and mult(BigIntPolynomial)
- */
- public void testMult()
- {
- SecureRandom random = new SecureRandom();
- SparseTernaryPolynomial p1 = SparseTernaryPolynomial.generateRandom(1000, 500, 500, random);
- IntegerPolynomial p2 = DenseTernaryPolynomial.generateRandom(1000, random);
-
- IntegerPolynomial prod1 = p1.mult(p2);
- IntegerPolynomial prod2 = p1.mult(p2);
- assertEquals(prod1, prod2);
-
- BigIntPolynomial p3 = new BigIntPolynomial(p2);
- BigIntPolynomial prod3 = p1.mult(p3);
-
- assertEquals(new BigIntPolynomial(prod1), prod3);
- }
-
- public void testFromToBinary()
- throws IOException
- {
- SecureRandom random = new SecureRandom();
- SparseTernaryPolynomial poly1 = SparseTernaryPolynomial.generateRandom(1000, 100, 101, random);
- ByteArrayInputStream poly1Stream = new ByteArrayInputStream(poly1.toBinary());
- SparseTernaryPolynomial poly2 = SparseTernaryPolynomial.fromBinary(poly1Stream, 1000, 100, 101);
- assertEquals(poly1, poly2);
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/pqc/math/ntru/util/test/AllTests.java b/core/src/test/java/org/bouncycastle/pqc/math/ntru/util/test/AllTests.java
deleted file mode 100644
index 55fc973e..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/math/ntru/util/test/AllTests.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.util.test;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-public class AllTests
- extends TestCase
-{
- public static void main (String[] args)
- {
- junit.textui.TestRunner.run(suite());
- }
-
- public static Test suite()
- {
- TestSuite suite = new TestSuite("NTRU ArrayEncoder Tests");
-
- suite.addTestSuite(ArrayEncoderTest.class);
-
- return suite;
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/pqc/math/ntru/util/test/ArrayEncoderTest.java b/core/src/test/java/org/bouncycastle/pqc/math/ntru/util/test/ArrayEncoderTest.java
deleted file mode 100644
index 6dbdea34..00000000
--- a/core/src/test/java/org/bouncycastle/pqc/math/ntru/util/test/ArrayEncoderTest.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.util.test;
-
-import java.security.SecureRandom;
-import java.util.Random;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.test.PolynomialGenerator;
-import org.bouncycastle.pqc.math.ntru.util.ArrayEncoder;
-import org.bouncycastle.util.Arrays;
-
-public class ArrayEncoderTest
- extends TestCase
-{
- public void testEncodeDecodeModQ()
- {
- int[] coeffs = PolynomialGenerator.generateRandom(1000, 2048).coeffs;
- byte[] data = ArrayEncoder.encodeModQ(coeffs, 2048);
- int[] coeffs2 = ArrayEncoder.decodeModQ(data, 1000, 2048);
- assertTrue(Arrays.areEqual(coeffs, coeffs2));
- }
-
- public void testEncodeDecodeMod3Sves()
- {
- Random rng = new Random();
- byte[] data = new byte[180];
- rng.nextBytes(data);
- int[] coeffs = ArrayEncoder.decodeMod3Sves(data, 960);
- byte[] data2 = ArrayEncoder.encodeMod3Sves(coeffs);
- assertTrue(Arrays.areEqual(data, data2));
- }
-
- public void testEncodeDecodeMod3Tight()
- {
- SecureRandom random = new SecureRandom();
-
- int[] coeffs = DenseTernaryPolynomial.generateRandom(1000, random).coeffs;
- byte[] data = ArrayEncoder.encodeMod3Tight(coeffs);
- int[] coeffs2 = ArrayEncoder.decodeMod3Tight(data, 1000);
- assertTrue(Arrays.areEqual(coeffs, coeffs2));
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/util/encoders/test/AbstractCoderTest.java b/core/src/test/java/org/bouncycastle/util/encoders/test/AbstractCoderTest.java
deleted file mode 100644
index d103869d..00000000
--- a/core/src/test/java/org/bouncycastle/util/encoders/test/AbstractCoderTest.java
+++ /dev/null
@@ -1,211 +0,0 @@
-package org.bouncycastle.util.encoders.test;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Random;
-
-import junit.framework.TestCase;
-
-import org.bouncycastle.util.encoders.Encoder;
-
-public abstract class AbstractCoderTest extends TestCase
-{
-
- private static final int[] SIZES_TO_CHECK = {64, 128, 1024, 1025, 1026, 2048,
- 2049, 2050, 4096, 4097, 4098, 8192, 8193, 8194};
-
- protected Encoder enc;
- private Random r;
-
- AbstractCoderTest(
- String name)
- {
- super(name);
- }
-
- protected void setUp()
- {
- r = new Random();
- }
-
- private void checkArrayOfSize(int size)
- throws IOException
- {
- byte[] original = new byte[size];
- r.nextBytes(original);
-
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- enc.encode(original, 0, original.length, bOut);
-
- byte[] encoded = bOut.toByteArray();
-
- assertTrue(encoded.length > original.length);
- assertTrue(encoded.length <= (original.length * 2));
- checkEncoding(encoded);
- checkSimpleDecode(original, encoded);
- checkStringDecode(original, encoded);
- checkOutputStreamDecode(original, encoded);
-
- int offset = r.nextInt(20);
- byte[] offsetEncoded = new byte[offset + encoded.length];
- System.arraycopy(encoded, 0, offsetEncoded, offset, encoded.length);
- checkOffsetDecode(original, offsetEncoded, offset, encoded.length);
-
- offset = r.nextInt(20);
- byte[] offsetOriginal = new byte[offset + original.length];
- System.arraycopy(original, 0, offsetOriginal, offset, original.length);
- checkOffsetEncode(original, offsetOriginal, offset, original.length);
-
- byte[] encodedWithSpace = addWhitespace(encoded);
- checkSimpleDecode(original, encodedWithSpace);
- checkStringDecode(original, encodedWithSpace);
- checkOutputStreamDecode(original, encodedWithSpace);
- }
-
- public void testEncode()
- throws IOException
- {
- for (int i = 0; i < SIZES_TO_CHECK.length; i++)
- {
- checkArrayOfSize(SIZES_TO_CHECK[i]);
- }
- }
-
- private void checkEncoding(byte[] encoded)
- {
- String encString = convertBytesToString(encoded);
- for (int i = 0; i < encString.length(); i++)
- {
- char c = encString.charAt(i);
- if (c == paddingChar())
- {
- // should only be padding at end of string
- assertTrue(i > encString.length() - 3);
- continue;
- }
- else if (isEncodedChar(c))
- {
- continue;
- }
- fail("Unexpected encoded character " + c);
- }
- }
-
- private void checkOutputStreamDecode(byte[] original, byte[] encoded)
- {
- String encString = convertBytesToString(encoded);
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- try
- {
- assertEquals(original.length, enc.decode(encString, out));
- assertTrue(Arrays.equals(original, out.toByteArray()));
- }
- catch (IOException e)
- {
- fail("This shouldn't happen");
- }
- }
-
- private void checkSimpleDecode(byte[] original, byte[] encoded)
- throws IOException
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- enc.decode(encoded, 0, encoded.length, bOut);
-
- assertTrue(Arrays.equals(original, bOut.toByteArray()));
- }
-
- private void checkOffsetEncode(byte[] original, byte[] offsetOriginal, int off, int length)
- throws IOException
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- enc.encode(offsetOriginal, off, length, bOut);
-
- byte[] encoded = bOut.toByteArray();
-
- bOut.reset();
-
- enc.decode(encoded, 0, encoded.length, bOut);
-
- assertTrue(Arrays.equals(original, bOut.toByteArray()));
- }
-
- private void checkOffsetDecode(byte[] original, byte[] encoded, int off, int length)
- throws IOException
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- enc.decode(encoded, off, length, bOut);
-
- assertTrue(Arrays.equals(original, bOut.toByteArray()));
- }
-
- private void checkStringDecode(byte[] original, byte[] encoded)
- throws IOException
- {
- String encString = convertBytesToString(encoded);
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- enc.decode(encString, bOut);
- assertTrue(Arrays.equals(original, bOut.toByteArray()));
- }
-
- private byte[] addWhitespace(byte[] encoded)
- {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- addSpace(out);
- for (int i = 0; i < encoded.length - 5; i++)
- {
- out.write(encoded, i, 1);
- if (r.nextInt(100) < 5)
- {
- addSpace(out);
- }
- }
- for (int i = encoded.length - 5; i < encoded.length; i++)
- {
- out.write(encoded, i, 1);
- }
- addSpace(out);
- return out.toByteArray();
- }
-
- private void addSpace(ByteArrayOutputStream out)
- {
- do
- {
- switch (r.nextInt(3))
- {
- case 0 :
- out.write((int) '\n');
- break;
- case 1 :
- out.write((int) '\r');
- break;
- case 2 :
- out.write((int) '\t');
- break;
- case 3 :
- out.write((int) ' ');
- break;
- }
- } while (r.nextBoolean());
- }
-
- private String convertBytesToString(byte[] encoded)
- {
- StringBuffer b = new StringBuffer();
-
- for (int i = 0; i != encoded.length; i++)
- {
- b.append((char)(encoded[i] & 0xff));
- }
-
- return b.toString();
- }
-
- abstract protected char paddingChar();
-
- abstract protected boolean isEncodedChar(char c);
-
-}
diff --git a/core/src/test/java/org/bouncycastle/util/encoders/test/AllTests.java b/core/src/test/java/org/bouncycastle/util/encoders/test/AllTests.java
deleted file mode 100644
index 4691a0b0..00000000
--- a/core/src/test/java/org/bouncycastle/util/encoders/test/AllTests.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.bouncycastle.util.encoders.test;
-
-import junit.framework.*;
-
-public class AllTests
-{
- public static void main (String[] args)
- {
- junit.textui.TestRunner.run (suite());
- }
-
- public static Test suite()
- {
- TestSuite suite = new TestSuite("encoder tests");
- suite.addTestSuite(Base64Test.class);
- suite.addTestSuite(UrlBase64Test.class);
- suite.addTestSuite(HexTest.class);
- return suite;
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/util/encoders/test/Base64Test.java b/core/src/test/java/org/bouncycastle/util/encoders/test/Base64Test.java
deleted file mode 100644
index 3c053999..00000000
--- a/core/src/test/java/org/bouncycastle/util/encoders/test/Base64Test.java
+++ /dev/null
@@ -1,121 +0,0 @@
-package org.bouncycastle.util.encoders.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Strings;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.encoders.Base64Encoder;
-import org.bouncycastle.util.encoders.DecoderException;
-import org.bouncycastle.util.encoders.Hex;
-
-public class Base64Test extends AbstractCoderTest
-{
- private static final String sample1 = "mO4TyLWG7vjFWdKT8IJcVbZ/jwc=";
- private static final byte[] sample1Bytes = Hex.decode("98ee13c8b586eef8c559d293f0825c55b67f8f07");
- private static final String sample2 = "F4I4p8Vf/mS+Kxvri3FPoMcqmJ1f";
- private static final byte[] sample2Bytes = Hex.decode("178238a7c55ffe64be2b1beb8b714fa0c72a989d5f");
- private static final String sample3 = "UJmEdJYodqHJmd7Rtv6/OP29/jUEFw==";
- private static final byte[] sample3Bytes = Hex.decode("50998474962876a1c999ded1b6febf38fdbdfe350417");
-
- private static final String invalid1 = "%O4TyLWG7vjFWdKT8IJcVbZ/jwc=";
- private static final String invalid2 = "F%I4p8Vf/mS+Kxvri3FPoMcqmJ1f";
- private static final String invalid3 = "UJ%EdJYodqHJmd7Rtv6/OP29/jUEFw==";
- private static final String invalid4 = "mO4%yLWG7vjFWdKT8IJcVbZ/jwc=";
- private static final String invalid5 = "UJmEdJYodqHJmd7Rtv6/OP29/jUEF%==";
- private static final String invalid6 = "mO4TyLWG7vjFWdKT8IJcVbZ/jw%=";
- private static final String invalid7 = "F4I4p8Vf/mS+Kxvri3FPoMcqmJ1%";
- private static final String invalid8 = "UJmEdJYodqHJmd7Rtv6/OP29/jUE%c==";
- private static final String invalid9 = "mO4TyLWG7vjFWdKT8IJcVbZ/j%c=";
- private static final String invalida = "F4I4p8Vf/mS+Kxvri3FPoMcqmJ%1";
- private static final String invalidb = "UJmEdJYodqHJmd7Rtv6/OP29/jU%Fc==";
- private static final String invalidc = "mO4TyLWG7vjFWdKT8IJcVbZ/%wc=";
- private static final String invalidd = "F4I4p8Vf/mS+Kxvri3FPoMcqm%1c";
-
-
- public Base64Test(
- String name)
- {
- super(name);
- }
-
- protected void setUp()
- {
- super.setUp();
- enc = new Base64Encoder();
- }
-
- public void testSamples()
- throws IOException
- {
- assertTrue(Arrays.areEqual(sample1Bytes, Base64.decode(sample1)));
- assertTrue(Arrays.areEqual(sample1Bytes, Base64.decode(Strings.toByteArray(sample1))));
- assertTrue(Arrays.areEqual(sample2Bytes, Base64.decode(sample2)));
- assertTrue(Arrays.areEqual(sample2Bytes, Base64.decode(Strings.toByteArray(sample2))));
- assertTrue(Arrays.areEqual(sample3Bytes, Base64.decode(sample3)));
- assertTrue(Arrays.areEqual(sample3Bytes, Base64.decode(Strings.toByteArray(sample3))));
- }
-
- public void testInvalidInput()
- throws IOException
- {
- String[] invalid = new String[] { invalid1, invalid2, invalid3, invalid4, invalid5, invalid6, invalid7, invalid8, invalid9, invalida, invalidb, invalidc, invalidd };
-
- for (int i = 0; i != invalid.length; i++)
- {
- invalidTest(invalid[i]);
- invalidTest(Strings.toByteArray(invalid[i]));
- }
- }
-
- private void invalidTest(String data)
- {
- try
- {
- Base64.decode(data);
- }
- catch (DecoderException e)
- {
- return;
- }
-
- fail("invalid String data parsed");
- }
-
- private void invalidTest(byte[] data)
- {
- try
- {
- Base64.decode(data);
- }
- catch (DecoderException e)
- {
- return;
- }
-
- fail("invalid byte data parsed");
- }
-
- protected char paddingChar()
- {
- return '=';
- }
-
- protected boolean isEncodedChar(char c)
- {
- if (Character.isLetterOrDigit(c))
- {
- return true;
- }
- else if (c == '+')
- {
- return true;
- }
- else if (c == '/')
- {
- return true;
- }
- return false;
- }
-
-}
diff --git a/core/src/test/java/org/bouncycastle/util/encoders/test/EncoderTest.java b/core/src/test/java/org/bouncycastle/util/encoders/test/EncoderTest.java
deleted file mode 100644
index c28b9328..00000000
--- a/core/src/test/java/org/bouncycastle/util/encoders/test/EncoderTest.java
+++ /dev/null
@@ -1,250 +0,0 @@
-package org.bouncycastle.util.encoders.test;
-
-import java.util.Arrays;
-import java.util.Random;
-
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class EncoderTest
- extends SimpleTest
-{
- public static final boolean DEBUG = true;
-
-
- public static void main(
- String[] args)
- {
- runTest(new EncoderTest());
- }
-
- public String getName()
- {
- return "Encoder";
- }
-
- /*
- *
- * TESTS
- *
- */
-
- public void performTest()
- {
- testHex();
- testBase64();
- testBase64WithNL();
- }
-
-
- public void testBase64()
- {
- try
- {
- Random _r = new Random();
-
- byte[] _orig1024 = new byte[1024];
- _r.nextBytes(_orig1024);
-
- byte[] _orig2048 = new byte[2048];
- _r.nextBytes(_orig2048);
-
- byte[] _orig4096 = new byte[4096];
- _r.nextBytes(_orig4096);
-
- byte[] _orig8192 = new byte[8192];
- _r.nextBytes(_orig8192);
-
- byte[] _enc1024 = Base64.encode(_orig1024);
- byte[] _enc2048 = Base64.encode(_orig2048);
- byte[] _enc4096 = Base64.encode(_orig4096);
- byte[] _enc8192 = Base64.encode(_orig8192);
-
- byte[] _dec1024 = Base64.decode(_enc1024);
- byte[] _dec2048 = Base64.decode(_enc2048);
- byte[] _dec4096 = Base64.decode(_enc4096);
- byte[] _dec8192 = Base64.decode(_enc8192);
-
- if(!Arrays.equals(_orig1024, _dec1024))
- {
- fail("Failed Base64 test");
- }
-
- if(!Arrays.equals(_orig2048, _dec2048))
- {
- fail("Failed Base64 test");
- }
-
- if(!Arrays.equals(_orig4096, _dec4096))
- {
- fail("Failed Base64 test");
- }
-
- if(!Arrays.equals(_orig8192, _dec8192))
- {
- fail("Failed Base64 test");
- }
-
-
-
- byte[] _orig1025 = new byte[1025];
- _r.nextBytes(_orig1025);
-
- byte[] _orig2049 = new byte[2049];
- _r.nextBytes(_orig2049);
-
- byte[] _orig4097 = new byte[4097];
- _r.nextBytes(_orig4097);
-
- byte[] _orig8193 = new byte[8193];
- _r.nextBytes(_orig8193);
-
- byte[] _enc1025 = Base64.encode(_orig1025);
- byte[] _enc2049 = Base64.encode(_orig2049);
- byte[] _enc4097 = Base64.encode(_orig4097);
- byte[] _enc8193 = Base64.encode(_orig8193);
-
- byte[] _dec1025 = Base64.decode(_enc1025);
- byte[] _dec2049 = Base64.decode(_enc2049);
- byte[] _dec4097 = Base64.decode(_enc4097);
- byte[] _dec8193 = Base64.decode(_enc8193);
-
- if(!Arrays.equals(_orig1025, _dec1025))
- {
- fail("Failed Base64 test");
- }
-
- if(!Arrays.equals(_orig2049, _dec2049))
- {
- fail("Failed Base64 test");
- }
-
- if(!Arrays.equals(_orig4097, _dec4097))
- {
- fail("Failed Base64 test");
- }
-
- if(!Arrays.equals(_orig8193, _dec8193))
- {
- fail("Failed Base64 test");
- }
- }
- catch(Exception ex)
- {
- fail("Failed Base64 test");
- }
- }
-
- public void testBase64WithNL()
- {
- byte[] dec = Base64.decode("SVNC" + "\n" + "QUQ=\n");
-
- if (dec.length != 5)
- {
- fail("got length " + dec.length + " when expecting 10");
- }
-
- if (!areEqual(dec, Base64.decode("SVNCQUQ=")))
- {
- fail("decodings are not equal");
- }
- }
-
- public void testHex()
- {
- try
- {
- Random _r = new Random();
-
- byte[] _orig1024 = new byte[1024];
- _r.nextBytes(_orig1024);
-
- byte[] _orig2048 = new byte[2048];
- _r.nextBytes(_orig2048);
-
- byte[] _orig4096 = new byte[4096];
- _r.nextBytes(_orig4096);
-
- byte[] _orig8192 = new byte[8192];
- _r.nextBytes(_orig8192);
-
- byte[] _enc1024 = Hex.encode(_orig1024);
- byte[] _enc2048 = Hex.encode(_orig2048);
- byte[] _enc4096 = Hex.encode(_orig4096);
- byte[] _enc8192 = Hex.encode(_orig8192);
-
- byte[] _dec1024 = Hex.decode(_enc1024);
- byte[] _dec2048 = Hex.decode(_enc2048);
- byte[] _dec4096 = Hex.decode(_enc4096);
- byte[] _dec8192 = Hex.decode(_enc8192);
-
- if(!Arrays.equals(_orig1024, _dec1024))
- {
- fail("Failed Hex test");
- }
-
- if(!Arrays.equals(_orig2048, _dec2048))
- {
- fail("Failed Hex test");
- }
-
- if(!Arrays.equals(_orig4096, _dec4096))
- {
- fail("Failed Hex test");
- }
-
- if(!Arrays.equals(_orig8192, _dec8192))
- {
- fail("Failed Hex test");
- }
-
-
- byte[] _orig1025 = new byte[1025];
- _r.nextBytes(_orig1025);
-
- byte[] _orig2049 = new byte[2049];
- _r.nextBytes(_orig2049);
-
- byte[] _orig4097 = new byte[4097];
- _r.nextBytes(_orig4097);
-
- byte[] _orig8193 = new byte[8193];
- _r.nextBytes(_orig8193);
-
- byte[] _enc1025 = Hex.encode(_orig1025);
- byte[] _enc2049 = Hex.encode(_orig2049);
- byte[] _enc4097 = Hex.encode(_orig4097);
- byte[] _enc8193 = Hex.encode(_orig8193);
-
- byte[] _dec1025 = Hex.decode(_enc1025);
- byte[] _dec2049 = Hex.decode(_enc2049);
- byte[] _dec4097 = Hex.decode(_enc4097);
- byte[] _dec8193 = Hex.decode(_enc8193);
-
- if(!Arrays.equals(_orig1025, _dec1025))
- {
- fail("Failed Hex test");
- }
-
- if(!Arrays.equals(_orig2049, _dec2049))
- {
- fail("Failed Hex test");
- }
-
- if(!Arrays.equals(_orig4097, _dec4097))
- {
- fail("Failed Hex test");
- }
-
- if(!Arrays.equals(_orig8193, _dec8193))
- {
- fail("Failed Hex test");
- }
- }
- catch(Exception ex)
- {
- fail("Failed Hex test");
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/util/encoders/test/HexTest.java b/core/src/test/java/org/bouncycastle/util/encoders/test/HexTest.java
deleted file mode 100644
index 34af71f0..00000000
--- a/core/src/test/java/org/bouncycastle/util/encoders/test/HexTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package org.bouncycastle.util.encoders.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.util.Strings;
-import org.bouncycastle.util.encoders.DecoderException;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.encoders.HexEncoder;
-
-public class HexTest extends AbstractCoderTest
-{
- private static final String invalid1 = "%O4T";
- private static final String invalid2 = "FZI4";
- private static final String invalid3 = "ae%E";
- private static final String invalid4 = "fO4%";
- private static final String invalid5 = "beefe";
- private static final String invalid6 = "beefs";
-
- public HexTest(
- String name)
- {
- super(name);
- }
-
- protected void setUp()
- {
- super.setUp();
- enc = new HexEncoder();
- }
-
- protected char paddingChar()
- {
- return 0;
- }
-
- protected boolean isEncodedChar(char c)
- {
- if ('A' <= c && c <= 'F')
- {
- return true;
- }
- if ('a' <= c && c <= 'f')
- {
- return true;
- }
- if ('0' <= c && c <= '9')
- {
- return true;
- }
- return false;
- }
-
- public void testInvalidInput()
- throws IOException
- {
- String[] invalid = new String[] { invalid1, invalid2, invalid3, invalid4, invalid5, invalid6 };
-
- for (int i = 0; i != invalid.length; i++)
- {
- invalidTest(invalid[i]);
- invalidTest(Strings.toByteArray(invalid[i]));
- }
- }
-
- private void invalidTest(String data)
- {
- try
- {
- Hex.decode(data);
- }
- catch (DecoderException e)
- {
- return;
- }
-
- fail("invalid String data parsed");
- }
-
- private void invalidTest(byte[] data)
- {
- try
- {
- Hex.decode(data);
- }
- catch (DecoderException e)
- {
- return;
- }
-
- fail("invalid byte data parsed");
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/util/encoders/test/UrlBase64Test.java b/core/src/test/java/org/bouncycastle/util/encoders/test/UrlBase64Test.java
deleted file mode 100644
index fbe1fc17..00000000
--- a/core/src/test/java/org/bouncycastle/util/encoders/test/UrlBase64Test.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package org.bouncycastle.util.encoders.test;
-
-import java.io.IOException;
-
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Strings;
-import org.bouncycastle.util.encoders.DecoderException;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.encoders.UrlBase64;
-import org.bouncycastle.util.encoders.UrlBase64Encoder;
-
-public class UrlBase64Test extends AbstractCoderTest
-{
- private static final String sample1 = "mO4TyLWG7vjFWdKT8IJcVbZ_jwc.";
- private static final byte[] sample1Bytes = Hex.decode("98ee13c8b586eef8c559d293f0825c55b67f8f07");
- private static final String sample2 = "F4I4p8Vf_mS-Kxvri3FPoMcqmJ1f";
- private static final byte[] sample2Bytes = Hex.decode("178238a7c55ffe64be2b1beb8b714fa0c72a989d5f");
- private static final String sample3 = "UJmEdJYodqHJmd7Rtv6_OP29_jUEFw..";
- private static final byte[] sample3Bytes = Hex.decode("50998474962876a1c999ded1b6febf38fdbdfe350417");
-
- private static final String invalid1 = "%O4TyLWG7vjFWdKT8IJcVbZ_jwc.";
- private static final String invalid2 = "F%I4p8Vf_mS-Kxvri3FPoMcqmJ1f";
- private static final String invalid3 = "UJ%EdJYodqHJmd7Rtv6_OP29_jUEFw..";
- private static final String invalid4 = "mO4%yLWG7vjFWdKT8IJcVbZ_jwc.";
- private static final String invalid5 = "UJmEdJYodqHJmd7Rtv6_OP29_jUEF%..";
- private static final String invalid6 = "mO4TyLWG7vjFWdKT8IJcVbZ_jw%.";
- private static final String invalid7 = "F4I4p8Vf_mS-Kxvri3FPoMcqmJ1%";
- private static final String invalid8 = "UJmEdJYodqHJmd7Rtv6_OP29_jUE%c..";
- private static final String invalid9 = "mO4TyLWG7vjFWdKT8IJcVbZ_j%c.";
- private static final String invalida = "F4I4p8Vf_mS-Kxvri3FPoMcqmJ%1";
- private static final String invalidb = "UJmEdJYodqHJmd7Rtv6_OP29_jU%Fc..";
- private static final String invalidc = "mO4TyLWG7vjFWdKT8IJcVbZ_%wc.";
- private static final String invalidd = "F4I4p8Vf_mS-Kxvri3FPoMcqm%1c";
-
- public UrlBase64Test(
- String name)
- {
- super(name);
- }
-
- protected void setUp()
- {
- super.setUp();
- enc = new UrlBase64Encoder();
- }
-
- public void testSamples()
- throws IOException
- {
- assertTrue(Arrays.areEqual(sample1Bytes, UrlBase64.decode(sample1)));
- assertTrue(Arrays.areEqual(sample1Bytes, UrlBase64.decode(Strings.toByteArray(sample1))));
- assertTrue(Arrays.areEqual(sample2Bytes, UrlBase64.decode(sample2)));
- assertTrue(Arrays.areEqual(sample2Bytes, UrlBase64.decode(Strings.toByteArray(sample2))));
- assertTrue(Arrays.areEqual(sample3Bytes, UrlBase64.decode(sample3)));
- assertTrue(Arrays.areEqual(sample3Bytes, UrlBase64.decode(Strings.toByteArray(sample3))));
- }
-
- public void testInvalidInput()
- throws IOException
- {
- String[] invalid = new String[] { invalid1, invalid2, invalid3, invalid4, invalid5, invalid6, invalid7, invalid8, invalid9, invalida, invalidb, invalidc, invalidd };
-
- for (int i = 0; i != invalid.length; i++)
- {
- invalidTest(invalid[i]);
- invalidTest(Strings.toByteArray(invalid[i]));
- }
- }
-
- private void invalidTest(String data)
- {
- try
- {
- UrlBase64.decode(data);
- }
- catch (DecoderException e)
- {
- return;
- }
-
- fail("invalid String data parsed");
- }
-
- private void invalidTest(byte[] data)
- {
- try
- {
- UrlBase64.decode(data);
- }
- catch (DecoderException e)
- {
- return;
- }
-
- fail("invalid byte data parsed");
- }
-
- protected char paddingChar()
- {
- return '.';
- }
-
- protected boolean isEncodedChar(char c)
- {
- if (Character.isLetterOrDigit(c))
- {
- return true;
- }
- else if (c == '-')
- {
- return true;
- }
- else if (c == '_')
- {
- return true;
- }
- return false;
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/util/io/pem/test/AllTests.java b/core/src/test/java/org/bouncycastle/util/io/pem/test/AllTests.java
deleted file mode 100644
index c3460833..00000000
--- a/core/src/test/java/org/bouncycastle/util/io/pem/test/AllTests.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.bouncycastle.util.io.pem.test;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-import org.bouncycastle.util.io.pem.PemHeader;
-import org.bouncycastle.util.io.pem.PemObject;
-import org.bouncycastle.util.io.pem.PemWriter;
-
-public class AllTests
- extends TestCase
-{
- public void testPemLength()
- throws IOException
- {
- for (int i = 1; i != 60; i++)
- {
- lengthTest("CERTIFICATE", Collections.EMPTY_LIST, new byte[i]);
- }
-
- lengthTest("CERTIFICATE", Collections.EMPTY_LIST, new byte[100]);
- lengthTest("CERTIFICATE", Collections.EMPTY_LIST, new byte[101]);
- lengthTest("CERTIFICATE", Collections.EMPTY_LIST, new byte[102]);
- lengthTest("CERTIFICATE", Collections.EMPTY_LIST, new byte[103]);
-
- lengthTest("CERTIFICATE", Collections.EMPTY_LIST, new byte[1000]);
- lengthTest("CERTIFICATE", Collections.EMPTY_LIST, new byte[1001]);
- lengthTest("CERTIFICATE", Collections.EMPTY_LIST, new byte[1002]);
- lengthTest("CERTIFICATE", Collections.EMPTY_LIST, new byte[1003]);
-
- List headers = new ArrayList();
-
- headers.add(new PemHeader("Proc-Type", "4,ENCRYPTED"));
- headers.add(new PemHeader("DEK-Info", "DES3,0001020304050607"));
-
- lengthTest("RSA PRIVATE KEY", headers, new byte[103]);
- }
-
- private void lengthTest(String type, List headers, byte[] data)
- throws IOException
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- PemWriter pWrt = new PemWriter(new OutputStreamWriter(bOut));
-
- PemObject pemObj = new PemObject(type, headers, data);
- pWrt.writeObject(pemObj);
-
- pWrt.close();
-
- assertEquals(bOut.toByteArray().length, pWrt.getOutputSize(pemObj));
- }
-
- public static void main (String[] args)
- {
- junit.textui.TestRunner.run (suite());
- }
-
- public static Test suite()
- {
- TestSuite suite = new TestSuite("util tests");
- suite.addTestSuite(AllTests.class);
- return suite;
- }
-} \ No newline at end of file
diff --git a/core/src/test/java/org/bouncycastle/util/io/test/BufferingOutputStreamTest.java b/core/src/test/java/org/bouncycastle/util/io/test/BufferingOutputStreamTest.java
deleted file mode 100644
index 0fb6546d..00000000
--- a/core/src/test/java/org/bouncycastle/util/io/test/BufferingOutputStreamTest.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.bouncycastle.util.io.test;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.security.SecureRandom;
-
-import org.bouncycastle.util.io.BufferingOutputStream;
-import org.bouncycastle.util.test.SimpleTest;
-
-public class BufferingOutputStreamTest
- extends SimpleTest
-{
- public String getName()
- {
- return "BufferingStreamTest";
- }
-
- public void performTest()
- throws Exception
- {
- SecureRandom random = new SecureRandom();
-
- for (int i = 1; i != 256; i++)
- {
- byte[] data = new byte[i];
-
- random.nextBytes(data);
-
- checkStream(data, 16);
- checkStream(data, 33);
- checkStream(data, 128);
- }
- }
-
- private void checkStream(byte[] data, int bufsize)
- throws IOException
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- BufferingOutputStream bfOut = new BufferingOutputStream(bOut, bufsize);
-
- for (int i = 0; i != 10; i++)
- {
- bfOut.write(data[0]);
- bfOut.write(data, 1, data.length - 1);
- }
-
- bfOut.close();
-
- byte[] output = bOut.toByteArray();
-
- for (int i = 0; i != 10; i++)
- {
- for (int j = 0; j != data.length; j++)
- {
- if (output[i * data.length + j] != data[j])
- {
- fail("data mismatch!");
- }
- }
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new BufferingOutputStreamTest());
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/util/utiltest/AllTests.java b/core/src/test/java/org/bouncycastle/util/utiltest/AllTests.java
deleted file mode 100644
index a1ff2ae7..00000000
--- a/core/src/test/java/org/bouncycastle/util/utiltest/AllTests.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.bouncycastle.util.utiltest;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-public class AllTests
-{
- public static void main (String[] args)
- {
- junit.textui.TestRunner.run (suite());
- }
-
- public static Test suite()
- {
- TestSuite suite = new TestSuite("util tests");
- suite.addTestSuite(IPTest.class);
- suite.addTestSuite(BigIntegersTest.class);
- return suite;
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/util/utiltest/BigIntegersTest.java b/core/src/test/java/org/bouncycastle/util/utiltest/BigIntegersTest.java
deleted file mode 100644
index d3eef271..00000000
--- a/core/src/test/java/org/bouncycastle/util/utiltest/BigIntegersTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package org.bouncycastle.util.utiltest;
-
-import java.math.BigInteger;
-
-import junit.framework.Assert;
-import junit.framework.TestCase;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.BigIntegers;
-import org.bouncycastle.util.IPAddress;
-import org.bouncycastle.util.encoders.Hex;
-
-public class BigIntegersTest
- extends TestCase
-{
- public String getName()
- {
- return "BigIntegers";
- }
-
- public void testAsUnsignedByteArray()
- {
- BigInteger a = new BigInteger(1, Hex.decode("ff12345678"));
-
- byte[] a5 = BigIntegers.asUnsignedByteArray(a);
-
- Assert.assertEquals(5, a5.length);
- Assert.assertTrue(Arrays.areEqual(a5, Hex.decode("ff12345678")));
-
- BigInteger b = new BigInteger(1, Hex.decode("0f12345678"));
-
- byte[] b5 = BigIntegers.asUnsignedByteArray(b);
-
- Assert.assertEquals(5, b5.length);
- Assert.assertTrue(Arrays.areEqual(b5, Hex.decode("0f12345678")));
- }
-
- public void testFixedLengthUnsignedByteArray()
- {
- BigInteger a = new BigInteger(1, Hex.decode("ff12345678"));
-
- byte[] a5 = BigIntegers.asUnsignedByteArray(5, a);
-
- Assert.assertEquals(5, a5.length);
- Assert.assertTrue(Arrays.areEqual(a5, Hex.decode("ff12345678")));
-
- byte[] a6 = BigIntegers.asUnsignedByteArray(6, a);
-
- Assert.assertEquals(6, a6.length);
- Assert.assertEquals(0, a6[0]);
- Assert.assertTrue(Arrays.areEqual(a6, Hex.decode("00ff12345678")));
-
- BigInteger b = new BigInteger(1, Hex.decode("0f12345678"));
-
- byte[] b5 = BigIntegers.asUnsignedByteArray(5, b);
-
- Assert.assertEquals(5, b5.length);
- Assert.assertTrue(Arrays.areEqual(b5, Hex.decode("0f12345678")));
-
- byte[] b6 = BigIntegers.asUnsignedByteArray(6, b);
-
- Assert.assertEquals(6, b6.length);
- Assert.assertEquals(0, b6[0]);
- Assert.assertTrue(Arrays.areEqual(b6, Hex.decode("000f12345678")));
-
- BigInteger c = new BigInteger(1, Hex.decode("ff123456789a"));
-
- try
- {
- byte[] c5 = BigIntegers.asUnsignedByteArray(5, c);
-
- fail("no exception thrown");
- }
- catch (IllegalArgumentException e)
- {
- // ignore
- }
-
- BigInteger d = new BigInteger(1, Hex.decode("0f123456789a"));
- try
- {
- byte[] c5 = BigIntegers.asUnsignedByteArray(5, d);
-
- fail("no exception thrown");
- }
- catch (IllegalArgumentException e)
- {
- // ignore
- }
- }
-}
diff --git a/core/src/test/java/org/bouncycastle/util/utiltest/IPTest.java b/core/src/test/java/org/bouncycastle/util/utiltest/IPTest.java
deleted file mode 100644
index 107b3384..00000000
--- a/core/src/test/java/org/bouncycastle/util/utiltest/IPTest.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package org.bouncycastle.util.utiltest;
-
-import junit.framework.TestCase;
-import org.bouncycastle.util.IPAddress;
-
-public class IPTest
- extends TestCase
-{
-
- private static final String validIP4v[] = new String[]
- { "0.0.0.0", "255.255.255.255", "192.168.0.0" };
-
- private static final String invalidIP4v[] = new String[]
- { "0.0.0.0.1", "256.255.255.255", "1", "A.B.C", "1:.4.6.5" };
-
- private static final String validIP6v[] = new String[]
- { "0:0:0:0:0:0:0:0", "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF",
- "0:1:2:3:FFFF:5:FFFF:1" };
-
- private static final String invalidIP6v[] = new String[]
- { "0.0.0.0:1", "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFFF" };
-
- private void testIP(String[] valid, String[] invalid)
- {
- for (int i = 0; i < valid.length; i++)
- {
- if (!IPAddress.isValid(valid[i]))
- {
- fail("Valid input string not accepted: " + valid[i] + ".");
- }
- }
- for (int i = 0; i < invalid.length; i++)
- {
- if (IPAddress.isValid(invalid[i]))
- {
- fail("Invalid input string accepted: " + invalid[i] + ".");
- }
- }
- }
-
- public String getName()
- {
- return "IPTest";
- }
-
- public void testIPv4()
- {
- testIP(validIP4v, invalidIP4v);
- }
-
- public void testIPv6()
- {
- testIP(validIP6v, invalidIP6v);
- }
-}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/ASN1SequenceParserTest.java b/core/src/test/java/org/spongycastle/asn1/test/ASN1SequenceParserTest.java
new file mode 100644
index 00000000..4c93a888
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/ASN1SequenceParserTest.java
@@ -0,0 +1,372 @@
+package org.spongycastle.asn1.test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Arrays;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Null;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1SequenceParser;
+import org.spongycastle.asn1.ASN1StreamParser;
+import org.spongycastle.asn1.BERSequenceGenerator;
+import org.spongycastle.asn1.DERSequenceGenerator;
+import org.spongycastle.util.encoders.Hex;
+
+public class ASN1SequenceParserTest
+ extends TestCase
+{
+ private static final byte[] seqData = Hex.decode("3006020100060129");
+ private static final byte[] nestedSeqData = Hex.decode("300b0201000601293003020101");
+ private static final byte[] expTagSeqData = Hex.decode("a1083006020100060129");
+ private static final byte[] implTagSeqData = Hex.decode("a106020100060129");
+ private static final byte[] nestedSeqExpTagData = Hex.decode("300d020100060129a1053003020101");
+ private static final byte[] nestedSeqImpTagData = Hex.decode("300b020100060129a103020101");
+
+ private static final byte[] berSeqData = Hex.decode("30800201000601290000");
+ private static final byte[] berDERNestedSeqData = Hex.decode("308002010006012930030201010000");
+ private static final byte[] berNestedSeqData = Hex.decode("3080020100060129308002010100000000");
+ private static final byte[] berExpTagSeqData = Hex.decode("a180308002010006012900000000");
+
+ private static final byte[] berSeqWithDERNullData = Hex.decode("308005000201000601290000");
+
+ public void testDERWriting()
+ throws Exception
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ DERSequenceGenerator seqGen = new DERSequenceGenerator(bOut);
+
+ seqGen.addObject(new ASN1Integer(BigInteger.valueOf(0)));
+
+ seqGen.addObject(new ASN1ObjectIdentifier("1.1"));
+
+ seqGen.close();
+
+ assertTrue("basic DER writing test failed.", Arrays.equals(seqData, bOut.toByteArray()));
+ }
+
+ public void testNestedDERWriting()
+ throws Exception
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ DERSequenceGenerator seqGen1 = new DERSequenceGenerator(bOut);
+
+ seqGen1.addObject(new ASN1Integer(BigInteger.valueOf(0)));
+
+ seqGen1.addObject(new ASN1ObjectIdentifier("1.1"));
+
+ DERSequenceGenerator seqGen2 = new DERSequenceGenerator(seqGen1.getRawOutputStream());
+
+ seqGen2.addObject(new ASN1Integer(BigInteger.valueOf(1)));
+
+ seqGen2.close();
+
+ seqGen1.close();
+
+ assertTrue("nested DER writing test failed.", Arrays.equals(nestedSeqData, bOut.toByteArray()));
+ }
+
+ public void testDERExplicitTaggedSequenceWriting()
+ throws Exception
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ DERSequenceGenerator seqGen = new DERSequenceGenerator(bOut, 1, true);
+
+ seqGen.addObject(new ASN1Integer(BigInteger.valueOf(0)));
+
+ seqGen.addObject(new ASN1ObjectIdentifier("1.1"));
+
+ seqGen.close();
+
+ assertTrue("explicit tag writing test failed.", Arrays.equals(expTagSeqData, bOut.toByteArray()));
+ }
+
+ public void testDERImplicitTaggedSequenceWriting()
+ throws Exception
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ DERSequenceGenerator seqGen = new DERSequenceGenerator(bOut, 1, false);
+
+ seqGen.addObject(new ASN1Integer(BigInteger.valueOf(0)));
+
+ seqGen.addObject(new ASN1ObjectIdentifier("1.1"));
+
+ seqGen.close();
+
+ assertTrue("implicit tag writing test failed.", Arrays.equals(implTagSeqData, bOut.toByteArray()));
+ }
+
+ public void testNestedExplicitTagDERWriting()
+ throws Exception
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ DERSequenceGenerator seqGen1 = new DERSequenceGenerator(bOut);
+
+ seqGen1.addObject(new ASN1Integer(BigInteger.valueOf(0)));
+
+ seqGen1.addObject(new ASN1ObjectIdentifier("1.1"));
+
+ DERSequenceGenerator seqGen2 = new DERSequenceGenerator(seqGen1.getRawOutputStream(), 1, true);
+
+ seqGen2.addObject(new ASN1Integer(BigInteger.valueOf(1)));
+
+ seqGen2.close();
+
+ seqGen1.close();
+
+ assertTrue("nested explicit tagged DER writing test failed.", Arrays.equals(nestedSeqExpTagData, bOut.toByteArray()));
+ }
+
+ public void testNestedImplicitTagDERWriting()
+ throws Exception
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ DERSequenceGenerator seqGen1 = new DERSequenceGenerator(bOut);
+
+ seqGen1.addObject(new ASN1Integer(BigInteger.valueOf(0)));
+
+ seqGen1.addObject(new ASN1ObjectIdentifier("1.1"));
+
+ DERSequenceGenerator seqGen2 = new DERSequenceGenerator(seqGen1.getRawOutputStream(), 1, false);
+
+ seqGen2.addObject(new ASN1Integer(BigInteger.valueOf(1)));
+
+ seqGen2.close();
+
+ seqGen1.close();
+
+ assertTrue("nested implicit tagged DER writing test failed.", Arrays.equals(nestedSeqImpTagData, bOut.toByteArray()));
+ }
+
+ public void testBERWriting()
+ throws Exception
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ BERSequenceGenerator seqGen = new BERSequenceGenerator(bOut);
+
+ seqGen.addObject(new ASN1Integer(BigInteger.valueOf(0)));
+
+ seqGen.addObject(new ASN1ObjectIdentifier("1.1"));
+
+ seqGen.close();
+
+ assertTrue("basic BER writing test failed.", Arrays.equals(berSeqData, bOut.toByteArray()));
+ }
+
+ public void testNestedBERDERWriting()
+ throws Exception
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ BERSequenceGenerator seqGen1 = new BERSequenceGenerator(bOut);
+
+ seqGen1.addObject(new ASN1Integer(BigInteger.valueOf(0)));
+
+ seqGen1.addObject(new ASN1ObjectIdentifier("1.1"));
+
+ DERSequenceGenerator seqGen2 = new DERSequenceGenerator(seqGen1.getRawOutputStream());
+
+ seqGen2.addObject(new ASN1Integer(BigInteger.valueOf(1)));
+
+ seqGen2.close();
+
+ seqGen1.close();
+
+ assertTrue("nested BER/DER writing test failed.", Arrays.equals(berDERNestedSeqData, bOut.toByteArray()));
+ }
+
+ public void testNestedBERWriting()
+ throws Exception
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ BERSequenceGenerator seqGen1 = new BERSequenceGenerator(bOut);
+
+ seqGen1.addObject(new ASN1Integer(BigInteger.valueOf(0)));
+
+ seqGen1.addObject(new ASN1ObjectIdentifier("1.1"));
+
+ BERSequenceGenerator seqGen2 = new BERSequenceGenerator(seqGen1.getRawOutputStream());
+
+ seqGen2.addObject(new ASN1Integer(BigInteger.valueOf(1)));
+
+ seqGen2.close();
+
+ seqGen1.close();
+
+ assertTrue("nested BER writing test failed.", Arrays.equals(berNestedSeqData, bOut.toByteArray()));
+ }
+
+ public void testDERReading()
+ throws Exception
+ {
+ ASN1StreamParser aIn = new ASN1StreamParser(seqData);
+
+ ASN1SequenceParser seq = (ASN1SequenceParser)aIn.readObject();
+ Object o;
+ int count = 0;
+
+ assertNotNull("null sequence returned", seq);
+
+ while ((o = seq.readObject()) != null)
+ {
+ switch (count)
+ {
+ case 0:
+ assertTrue(o instanceof ASN1Integer);
+ break;
+ case 1:
+ assertTrue(o instanceof ASN1ObjectIdentifier);
+ break;
+ }
+ count++;
+ }
+
+ assertEquals("wrong number of objects in sequence", 2, count);
+ }
+
+ private void testNestedReading(
+ byte[] data)
+ throws Exception
+ {
+ ASN1StreamParser aIn = new ASN1StreamParser(data);
+
+ ASN1SequenceParser seq = (ASN1SequenceParser)aIn.readObject();
+ Object o;
+ int count = 0;
+
+ assertNotNull("null sequence returned", seq);
+
+ while ((o = seq.readObject()) != null)
+ {
+ switch (count)
+ {
+ case 0:
+ assertTrue(o instanceof ASN1Integer);
+ break;
+ case 1:
+ assertTrue(o instanceof ASN1ObjectIdentifier);
+ break;
+ case 2:
+ assertTrue(o instanceof ASN1SequenceParser);
+
+ ASN1SequenceParser s = (ASN1SequenceParser)o;
+
+ // NB: Must exhaust the nested parser
+ while (s.readObject() != null)
+ {
+ // Nothing
+ }
+
+ break;
+ }
+ count++;
+ }
+
+ assertEquals("wrong number of objects in sequence", 3, count);
+ }
+
+ public void testNestedDERReading()
+ throws Exception
+ {
+ testNestedReading(nestedSeqData);
+ }
+
+ public void testBERReading()
+ throws Exception
+ {
+ ASN1StreamParser aIn = new ASN1StreamParser(berSeqData);
+
+ ASN1SequenceParser seq = (ASN1SequenceParser)aIn.readObject();
+ Object o;
+ int count = 0;
+
+ assertNotNull("null sequence returned", seq);
+
+ while ((o = seq.readObject()) != null)
+ {
+ switch (count)
+ {
+ case 0:
+ assertTrue(o instanceof ASN1Integer);
+ break;
+ case 1:
+ assertTrue(o instanceof ASN1ObjectIdentifier);
+ break;
+ }
+ count++;
+ }
+
+ assertEquals("wrong number of objects in sequence", 2, count);
+ }
+
+ public void testNestedBERDERReading()
+ throws Exception
+ {
+ testNestedReading(berDERNestedSeqData);
+ }
+
+ public void testNestedBERReading()
+ throws Exception
+ {
+ testNestedReading(berNestedSeqData);
+ }
+
+ public void testBERExplicitTaggedSequenceWriting()
+ throws Exception
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ BERSequenceGenerator seqGen = new BERSequenceGenerator(bOut, 1, true);
+
+ seqGen.addObject(new ASN1Integer(BigInteger.valueOf(0)));
+
+ seqGen.addObject(new ASN1ObjectIdentifier("1.1"));
+
+ seqGen.close();
+
+ assertTrue("explicit BER tag writing test failed.", Arrays.equals(berExpTagSeqData, bOut.toByteArray()));
+ }
+
+ public void testSequenceWithDERNullReading()
+ throws Exception
+ {
+ testParseWithNull(berSeqWithDERNullData);
+ }
+
+ private void testParseWithNull(byte[] data)
+ throws IOException
+ {
+ ASN1StreamParser aIn = new ASN1StreamParser(data);
+ ASN1SequenceParser seq = (ASN1SequenceParser)aIn.readObject();
+ Object o;
+ int count = 0;
+
+ assertNotNull("null sequence returned", seq);
+
+ while ((o = seq.readObject()) != null)
+ {
+ switch (count)
+ {
+ case 0:
+ assertTrue(o instanceof ASN1Null);
+ break;
+ case 1:
+ assertTrue(o instanceof ASN1Integer);
+ break;
+ case 2:
+ assertTrue(o instanceof ASN1ObjectIdentifier);
+ break;
+ }
+ count++;
+ }
+
+ assertEquals("wrong number of objects in sequence", 3, count);
+ }
+
+ public static Test suite()
+ {
+ return new TestSuite(ASN1SequenceParserTest.class);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/ASN1UnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/ASN1UnitTest.java
new file mode 100644
index 00000000..e71aedc1
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/ASN1UnitTest.java
@@ -0,0 +1,89 @@
+package org.spongycastle.asn1.test;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.util.test.SimpleTest;
+
+import java.math.BigInteger;
+
+public abstract class ASN1UnitTest
+ extends SimpleTest
+{
+ protected void checkMandatoryField(String name, ASN1Encodable expected, ASN1Encodable present)
+ {
+ if (!expected.equals(present))
+ {
+ fail(name + " field doesn't match.");
+ }
+ }
+
+ protected void checkMandatoryField(String name, String expected, String present)
+ {
+ if (!expected.equals(present))
+ {
+ fail(name + " field doesn't match.");
+ }
+ }
+
+ protected void checkMandatoryField(String name, byte[] expected, byte[] present)
+ {
+ if (!areEqual(expected, present))
+ {
+ fail(name + " field doesn't match.");
+ }
+ }
+
+ protected void checkMandatoryField(String name, int expected, int present)
+ {
+ if (expected != present)
+ {
+ fail(name + " field doesn't match.");
+ }
+ }
+
+ protected void checkOptionalField(String name, ASN1Encodable expected, ASN1Encodable present)
+ {
+ if (expected != null)
+ {
+ if (!expected.equals(present))
+ {
+ fail(name + " field doesn't match.");
+ }
+ }
+ else if (present != null)
+ {
+ fail(name + " field found when none expected.");
+ }
+ }
+
+ protected void checkOptionalField(String name, String expected, String present)
+ {
+ if (expected != null)
+ {
+ if (!expected.equals(present))
+ {
+ fail(name + " field doesn't match.");
+ }
+ }
+ else if (present != null)
+ {
+ fail(name + " field found when none expected.");
+ }
+ }
+
+ protected void checkOptionalField(String name, BigInteger expected, BigInteger present)
+ {
+ if (expected != null)
+ {
+ if (!expected.equals(present))
+ {
+ fail(name + " field doesn't match.");
+ }
+ }
+ else if (present != null)
+ {
+ fail(name + " field found when none expected.");
+ }
+ }
+
+
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/AdditionalInformationSyntaxUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/AdditionalInformationSyntaxUnitTest.java
new file mode 100644
index 00000000..b1aa29bb
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/AdditionalInformationSyntaxUnitTest.java
@@ -0,0 +1,69 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1String;
+import org.spongycastle.asn1.isismtt.x509.AdditionalInformationSyntax;
+import org.spongycastle.asn1.x500.DirectoryString;
+
+public class AdditionalInformationSyntaxUnitTest
+ extends ASN1UnitTest
+{
+ public String getName()
+ {
+ return "AdditionalInformationSyntax";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ AdditionalInformationSyntax syntax = new AdditionalInformationSyntax("hello world");
+
+ checkConstruction(syntax, new DirectoryString("hello world"));
+
+ try
+ {
+ AdditionalInformationSyntax.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ AdditionalInformationSyntax syntax,
+ DirectoryString information)
+ throws IOException
+ {
+ checkValues(syntax, information);
+
+ syntax = AdditionalInformationSyntax.getInstance(syntax);
+
+ checkValues(syntax, information);
+
+ ASN1InputStream aIn = new ASN1InputStream(syntax.toASN1Object().getEncoded());
+
+ ASN1String info = (ASN1String)aIn.readObject();
+
+ syntax = AdditionalInformationSyntax.getInstance(info);
+
+ checkValues(syntax, information);
+ }
+
+ private void checkValues(
+ AdditionalInformationSyntax syntax,
+ DirectoryString information)
+ {
+ checkMandatoryField("information", information, syntax.getInformation());
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new AdditionalInformationSyntaxUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/AdmissionSyntaxUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/AdmissionSyntaxUnitTest.java
new file mode 100644
index 00000000..b87cb83d
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/AdmissionSyntaxUnitTest.java
@@ -0,0 +1,97 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.isismtt.x509.AdmissionSyntax;
+import org.spongycastle.asn1.isismtt.x509.Admissions;
+import org.spongycastle.asn1.isismtt.x509.NamingAuthority;
+import org.spongycastle.asn1.isismtt.x509.ProfessionInfo;
+import org.spongycastle.asn1.x500.DirectoryString;
+import org.spongycastle.asn1.x509.GeneralName;
+import org.spongycastle.asn1.x509.X509Name;
+
+public class AdmissionSyntaxUnitTest
+ extends ASN1UnitTest
+{
+ public String getName()
+ {
+ return "AdmissionSyntax";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ GeneralName name = new GeneralName(new X509Name("CN=hello world"));
+ ASN1Sequence admissions = new DERSequence(
+ new Admissions(name,
+ new NamingAuthority(new ASN1ObjectIdentifier("1.2.3"), "url", new DirectoryString("fred")),
+ new ProfessionInfo[0]));
+ AdmissionSyntax syntax = new AdmissionSyntax(name, admissions);
+
+ checkConstruction(syntax, name, admissions);
+
+ syntax = AdmissionSyntax.getInstance(null);
+
+ if (syntax != null)
+ {
+ fail("null getInstance() failed.");
+ }
+
+ try
+ {
+ AdmissionSyntax.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ AdmissionSyntax syntax,
+ GeneralName authority,
+ ASN1Sequence admissions)
+ throws IOException
+ {
+ checkValues(syntax, authority, admissions);
+
+ syntax = AdmissionSyntax.getInstance(syntax);
+
+ checkValues(syntax, authority, admissions);
+
+ ASN1InputStream aIn = new ASN1InputStream(syntax.toASN1Object().getEncoded());
+
+ ASN1Sequence info = (ASN1Sequence)aIn.readObject();
+
+ syntax = AdmissionSyntax.getInstance(info);
+
+ checkValues(syntax, authority, admissions);
+ }
+
+ private void checkValues(
+ AdmissionSyntax syntax,
+ GeneralName authority,
+ ASN1Sequence admissions)
+ {
+ checkMandatoryField("admissionAuthority", authority, syntax.getAdmissionAuthority());
+
+ Admissions[] adm = syntax.getContentsOfAdmissions();
+
+ if (adm.length != 1 || !adm[0].equals(admissions.getObjectAt(0)))
+ {
+ fail("admissions check failed");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new AdmissionSyntaxUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/AdmissionsUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/AdmissionsUnitTest.java
new file mode 100644
index 00000000..e9bf4906
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/AdmissionsUnitTest.java
@@ -0,0 +1,86 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.isismtt.x509.Admissions;
+import org.spongycastle.asn1.isismtt.x509.NamingAuthority;
+import org.spongycastle.asn1.isismtt.x509.ProfessionInfo;
+import org.spongycastle.asn1.x500.DirectoryString;
+import org.spongycastle.asn1.x509.GeneralName;
+import org.spongycastle.asn1.x509.X509Name;
+
+public class AdmissionsUnitTest
+ extends ASN1UnitTest
+{
+ public String getName()
+ {
+ return "Admissions";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ GeneralName name = new GeneralName(new X509Name("CN=hello world"));
+ NamingAuthority auth = new NamingAuthority(new ASN1ObjectIdentifier("1.2.3"), "url", new DirectoryString("fred"));
+ Admissions admissions = new Admissions(name, auth, new ProfessionInfo[0]);
+
+ checkConstruction(admissions, name, auth);
+
+ admissions = Admissions.getInstance(null);
+
+ if (admissions != null)
+ {
+ fail("null getInstance() failed.");
+ }
+
+ try
+ {
+ Admissions.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ Admissions admissions,
+ GeneralName name,
+ NamingAuthority auth)
+ throws IOException
+ {
+ checkValues(admissions, name, auth);
+
+ admissions = Admissions.getInstance(admissions);
+
+ checkValues(admissions, name, auth);
+
+ ASN1InputStream aIn = new ASN1InputStream(admissions.toASN1Object().getEncoded());
+
+ ASN1Sequence info = (ASN1Sequence)aIn.readObject();
+
+ admissions = Admissions.getInstance(info);
+
+ checkValues(admissions, name, auth);
+ }
+
+ private void checkValues(
+ Admissions admissions,
+ GeneralName name,
+ NamingAuthority auth)
+ {
+ checkMandatoryField("admissionAuthority", name, admissions.getAdmissionAuthority());
+ checkMandatoryField("namingAuthority", auth, admissions.getNamingAuthority());
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new AdmissionsUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/AllTests.java b/core/src/test/java/org/spongycastle/asn1/test/AllTests.java
new file mode 100644
index 00000000..6e1c6dde
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/AllTests.java
@@ -0,0 +1,43 @@
+package org.spongycastle.asn1.test;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.spongycastle.util.test.SimpleTestResult;
+
+public class AllTests
+ extends TestCase
+{
+ public void testASN1()
+ {
+ org.spongycastle.util.test.Test[] tests = RegressionTest.tests;
+
+ for (int i = 0; i != tests.length; i++)
+ {
+ SimpleTestResult result = (SimpleTestResult)tests[i].perform();
+
+ if (!result.isSuccessful())
+ {
+ fail(result.toString());
+ }
+ }
+ }
+
+ public static void main (String[] args)
+ {
+ junit.textui.TestRunner.run(suite());
+ }
+
+ public static Test suite()
+ {
+ TestSuite suite = new TestSuite("ASN.1 Tests");
+
+ suite.addTestSuite(AllTests.class);
+ suite.addTestSuite(GetInstanceTest.class);
+ suite.addTestSuite(ASN1SequenceParserTest.class);
+ suite.addTestSuite(OctetStringTest.class);
+ suite.addTestSuite(ParseTest.class);
+
+ return suite;
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/AttributeTableUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/AttributeTableUnitTest.java
new file mode 100644
index 00000000..ec541032
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/AttributeTableUnitTest.java
@@ -0,0 +1,144 @@
+package org.spongycastle.asn1.test;
+
+import java.util.Hashtable;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.DERSet;
+import org.spongycastle.asn1.cms.Attribute;
+import org.spongycastle.asn1.cms.AttributeTable;
+import org.spongycastle.util.test.SimpleTest;
+
+public class AttributeTableUnitTest
+ extends SimpleTest
+{
+ private static final ASN1ObjectIdentifier type1 = new ASN1ObjectIdentifier("1.1.1");
+ private static final ASN1ObjectIdentifier type2 = new ASN1ObjectIdentifier("1.1.2");
+ private static final ASN1ObjectIdentifier type3 = new ASN1ObjectIdentifier("1.1.3");
+
+ public String getName()
+ {
+ return "AttributeTable";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new Attribute(type1, new DERSet(type1)));
+ v.add(new Attribute(type2, new DERSet(type2)));
+
+ AttributeTable table = new AttributeTable(v);
+
+ Attribute a = table.get(type1);
+ if (a == null)
+ {
+ fail("type1 attribute not found.");
+ }
+ if (!a.getAttrValues().equals(new DERSet(type1)))
+ {
+ fail("wrong value retrieved for type1!");
+ }
+
+ a = table.get(type2);
+ if (a == null)
+ {
+ fail("type2 attribute not found.");
+ }
+ if (!a.getAttrValues().equals(new DERSet(type2)))
+ {
+ fail("wrong value retrieved for type2!");
+ }
+
+ a = table.get(type3);
+ if (a != null)
+ {
+ fail("type3 attribute found when none expected.");
+ }
+
+ ASN1EncodableVector vec = table.getAll(type1);
+ if (vec.size() != 1)
+ {
+ fail("wrong vector size for type1.");
+ }
+
+ vec = table.getAll(type3);
+ if (vec.size() != 0)
+ {
+ fail("wrong vector size for type3.");
+ }
+
+ vec = table.toASN1EncodableVector();
+ if (vec.size() != 2)
+ {
+ fail("wrong vector size for single.");
+ }
+
+ Hashtable t = table.toHashtable();
+
+ if (t.size() != 2)
+ {
+ fail("hashtable wrong size.");
+ }
+
+ // multiple
+
+ v = new ASN1EncodableVector();
+
+ v.add(new Attribute(type1, new DERSet(type1)));
+ v.add(new Attribute(type1, new DERSet(type2)));
+ v.add(new Attribute(type1, new DERSet(type3)));
+ v.add(new Attribute(type2, new DERSet(type2)));
+
+ table = new AttributeTable(v);
+
+ a = table.get(type1);
+ if (!a.getAttrValues().equals(new DERSet(type1)))
+ {
+ fail("wrong value retrieved for type1 multi get!");
+ }
+
+ vec = table.getAll(type1);
+ if (vec.size() != 3)
+ {
+ fail("wrong vector size for multiple type1.");
+ }
+
+ a = (Attribute)vec.get(0);
+ if (!a.getAttrValues().equals(new DERSet(type1)))
+ {
+ fail("wrong value retrieved for type1(0)!");
+ }
+
+ a = (Attribute)vec.get(1);
+ if (!a.getAttrValues().equals(new DERSet(type2)))
+ {
+ fail("wrong value retrieved for type1(1)!");
+ }
+
+ a = (Attribute)vec.get(2);
+ if (!a.getAttrValues().equals(new DERSet(type3)))
+ {
+ fail("wrong value retrieved for type1(2)!");
+ }
+
+ vec = table.getAll(type2);
+ if (vec.size() != 1)
+ {
+ fail("wrong vector size for multiple type2.");
+ }
+
+ vec = table.toASN1EncodableVector();
+ if (vec.size() != 4)
+ {
+ fail("wrong vector size for multiple.");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new AttributeTableUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/BiometricDataUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/BiometricDataUnitTest.java
new file mode 100644
index 00000000..97058495
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/BiometricDataUnitTest.java
@@ -0,0 +1,133 @@
+package org.spongycastle.asn1.test;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.DERNull;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.oiw.OIWObjectIdentifiers;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.qualified.BiometricData;
+import org.spongycastle.asn1.x509.qualified.TypeOfBiometricData;
+import org.spongycastle.util.test.SimpleTest;
+
+public class BiometricDataUnitTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "BiometricData";
+ }
+
+ private byte[] generateHash()
+ {
+ SecureRandom rand = new SecureRandom();
+ byte[] bytes = new byte[20];
+
+ rand.nextBytes(bytes);
+
+ return bytes;
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ TypeOfBiometricData dataType = new TypeOfBiometricData(TypeOfBiometricData.HANDWRITTEN_SIGNATURE);
+ AlgorithmIdentifier hashAlgorithm = new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE);
+ ASN1OctetString dataHash = new DEROctetString(generateHash());
+ BiometricData bd = new BiometricData(dataType, hashAlgorithm, dataHash);
+
+ checkConstruction(bd, dataType, hashAlgorithm, dataHash, null);
+
+ DERIA5String dataUri = new DERIA5String("http://test");
+
+ bd = new BiometricData(dataType, hashAlgorithm, dataHash, dataUri);
+
+ checkConstruction(bd, dataType, hashAlgorithm, dataHash, dataUri);
+
+ bd = BiometricData.getInstance(null);
+
+ if (bd != null)
+ {
+ fail("null getInstance() failed.");
+ }
+
+ try
+ {
+ BiometricData.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ BiometricData bd,
+ TypeOfBiometricData dataType,
+ AlgorithmIdentifier hashAlgorithm,
+ ASN1OctetString dataHash,
+ DERIA5String dataUri)
+ throws Exception
+ {
+ checkValues(bd, dataType, hashAlgorithm, dataHash, dataUri);
+
+ bd = BiometricData.getInstance(bd);
+
+ checkValues(bd, dataType, hashAlgorithm, dataHash, dataUri);
+
+ ASN1InputStream aIn = new ASN1InputStream(bd.toASN1Object().getEncoded());
+
+ ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
+
+ bd = BiometricData.getInstance(seq);
+
+ checkValues(bd, dataType, hashAlgorithm, dataHash, dataUri);
+ }
+
+ private void checkValues(
+ BiometricData bd,
+ TypeOfBiometricData dataType,
+ AlgorithmIdentifier algID,
+ ASN1OctetString dataHash,
+ DERIA5String sourceDataURI)
+ {
+ if (!bd.getTypeOfBiometricData().equals(dataType))
+ {
+ fail("types don't match.");
+ }
+
+ if (!bd.getHashAlgorithm().equals(algID))
+ {
+ fail("hash algorithms don't match.");
+ }
+
+ if (!bd.getBiometricDataHash().equals(dataHash))
+ {
+ fail("hash algorithms don't match.");
+ }
+
+ if (sourceDataURI != null)
+ {
+ if (!bd.getSourceDataUri().equals(sourceDataURI))
+ {
+ fail("data uris don't match.");
+ }
+ }
+ else if (bd.getSourceDataUri() != null)
+ {
+ fail("data uri found when none expected.");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new BiometricDataUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/BitStringConstantTester.java b/core/src/test/java/org/spongycastle/asn1/test/BitStringConstantTester.java
new file mode 100644
index 00000000..ad036d9e
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/BitStringConstantTester.java
@@ -0,0 +1,22 @@
+package org.spongycastle.asn1.test;
+
+public class BitStringConstantTester
+{
+ private static final int[] bits =
+ {
+ 1 << 7, 1 << 6, 1 << 5, 1 << 4, 1 << 3, 1 << 2, 1 << 1, 1 << 0,
+ 1 << 15, 1 << 14, 1 << 13, 1 << 12, 1 << 11, 1 << 10, 1 << 9, 1 << 8,
+ 1 << 23, 1 << 22, 1 << 21, 1 << 20, 1 << 19, 1 << 18, 1 << 17, 1 << 16,
+ 1 << 31, 1 << 30, 1 << 29, 1 << 28, 1 << 27, 1 << 26, 1 << 25, 1 << 24
+ };
+
+ public static void testFlagValueCorrect(
+ int bitNo,
+ int value)
+ {
+ if (bits[bitNo] != value)
+ {
+ throw new IllegalArgumentException("bit value " + bitNo + " wrong");
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/BitStringTest.java b/core/src/test/java/org/spongycastle/asn1/test/BitStringTest.java
new file mode 100644
index 00000000..ff7cd387
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/BitStringTest.java
@@ -0,0 +1,73 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.x509.KeyUsage;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+public class BitStringTest
+ implements Test
+{
+ public TestResult perform()
+ {
+ KeyUsage k = new KeyUsage(KeyUsage.digitalSignature);
+ if ((k.getBytes()[0] != (byte)KeyUsage.digitalSignature) || (k.getPadBits() != 7))
+ {
+ return new SimpleTestResult(false, getName() + ": failed digitalSignature");
+ }
+
+ k = new KeyUsage(KeyUsage.nonRepudiation);
+ if ((k.getBytes()[0] != (byte)KeyUsage.nonRepudiation) || (k.getPadBits() != 6))
+ {
+ return new SimpleTestResult(false, getName() + ": failed nonRepudiation");
+ }
+
+ k = new KeyUsage(KeyUsage.keyEncipherment);
+ if ((k.getBytes()[0] != (byte)KeyUsage.keyEncipherment) || (k.getPadBits() != 5))
+ {
+ return new SimpleTestResult(false, getName() + ": failed keyEncipherment");
+ }
+
+ k = new KeyUsage(KeyUsage.cRLSign);
+ if ((k.getBytes()[0] != (byte)KeyUsage.cRLSign) || (k.getPadBits() != 1))
+ {
+ return new SimpleTestResult(false, getName() + ": failed cRLSign");
+ }
+
+ k = new KeyUsage(KeyUsage.decipherOnly);
+ if ((k.getBytes()[1] != (byte)(KeyUsage.decipherOnly >> 8)) || (k.getPadBits() != 7))
+ {
+ return new SimpleTestResult(false, getName() + ": failed decipherOnly");
+ }
+
+ // test for zero length bit string
+ try
+ {
+ ASN1Primitive.fromByteArray(new DERBitString(new byte[0], 0).getEncoded());
+ }
+ catch (IOException e)
+ {
+ return new SimpleTestResult(false, getName() + ": " + e);
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+
+ public String getName()
+ {
+ return "BitString";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ BitStringTest test = new BitStringTest();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/CMSTest.java b/core/src/test/java/org/spongycastle/asn1/test/CMSTest.java
new file mode 100644
index 00000000..8fb342c8
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/CMSTest.java
@@ -0,0 +1,358 @@
+package org.spongycastle.asn1.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1OctetStringParser;
+import org.spongycastle.asn1.ASN1OutputStream;
+import org.spongycastle.asn1.ASN1SequenceParser;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.ASN1SetParser;
+import org.spongycastle.asn1.ASN1StreamParser;
+import org.spongycastle.asn1.BERTags;
+import org.spongycastle.asn1.DERSet;
+import org.spongycastle.asn1.cms.CMSObjectIdentifiers;
+import org.spongycastle.asn1.cms.CompressedData;
+import org.spongycastle.asn1.cms.ContentInfo;
+import org.spongycastle.asn1.cms.ContentInfoParser;
+import org.spongycastle.asn1.cms.EncryptedContentInfoParser;
+import org.spongycastle.asn1.cms.EnvelopedData;
+import org.spongycastle.asn1.cms.EnvelopedDataParser;
+import org.spongycastle.asn1.cms.KEKRecipientInfo;
+import org.spongycastle.asn1.cms.KeyTransRecipientInfo;
+import org.spongycastle.asn1.cms.RecipientInfo;
+import org.spongycastle.asn1.cms.SignedData;
+import org.spongycastle.util.encoders.Base64;
+import org.spongycastle.util.io.Streams;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+public class CMSTest
+ implements Test
+{
+ //
+ // compressed data object
+ //
+ 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");
+
+ //
+ // enveloped data
+ //
+ byte[] envDataKeyTrns = Base64.decode(
+ "MIAGCSqGSIb3DQEHA6CAMIACAQAxgcQwgcECAQAwKjAlMRYwFAYDVQQKEw1Cb3Vu"
+ + "Y3kgQ2FzdGxlMQswCQYDVQQGEwJBVQIBCjANBgkqhkiG9w0BAQEFAASBgC5vdGrB"
+ + "itQSGwifLf3KwPILjaB4WEXgT/IIO1KDzrsbItCJsMA0Smq2y0zptxT0pSRL6JRg"
+ + "NMxLk1ySnrIrvGiEPLMR1zjxlT8yQ6VLX+kEoK43ztd1aaLw0oBfrcXcLN7BEpZ1"
+ + "TIdjlBfXIOx1S88WY1MiYqJJFc3LMwRUaTEDMIAGCSqGSIb3DQEHATAdBglghkgB"
+ + "ZQMEARYEEAfxLMWeaBOTTZQwUq0Y5FuggAQgwOJhL04rjSZCBCSOv5i5XpFfGsOd"
+ + "YSHSqwntGpFqCx4AAAAAAAAAAAAA");
+
+ byte[] envDataKEK = Base64.decode(
+ "MIAGCSqGSIb3DQEHA6CAMIACAQIxUqJQAgEEMAcEBQECAwQFMBAGCyqGSIb3DQEJE"
+ + "AMHAgE6BDC7G/HyUPilIrin2Yeajqmj795VoLWETRnZAAFcAiQdoQWyz+oCh6WY/H"
+ + "jHHi+0y+cwgAYJKoZIhvcNAQcBMBQGCCqGSIb3DQMHBAiY3eDBBbF6naCABBiNdzJb"
+ + "/v6+UZB3XXKipxFDUpz9GyjzB+gAAAAAAAAAAAAA");
+
+ byte[] envDataNestedNDEF = Base64.decode(
+ "MIAGCSqGSIb3DQEHA6CAMIACAQAxge8wgewCAQAwgZUwgY8xKDAmBgNVBAoMH1RoZSBMZWdpb24g"
+ + "b2YgdGhlIEJvdW5jeSBDYXN0bGUxLzAtBgkqhkiG9w0BCQEWIGZlZWRiYWNrLWNyeXB0b0Bib3Vu"
+ + "Y3ljYXN0bGUub3JnMREwDwYDVQQIDAhWaWN0b3JpYTESMBAGA1UEBwwJTWVsYm91cm5lMQswCQYD"
+ + "VQQGEwJBVQIBATANBgkqhkiG9w0BAQEFAARABIXMd8xiTyWDKO/LQfvdGYTPW3I9oSQWwtm4OIaN"
+ + "VINpfY2lfwTvbmE6VXiLKeALC0dMBV8z7DEM9hE0HVmvLDCABgkqhkiG9w0BBwEwHQYJYIZIAWUD"
+ + "BAECBBB32ko6WrVxDTqwUYEpV6IUoIAEggKgS6RowrhNlmWWI13zxD/lryxkZ5oWXPUfNiUxYX/P"
+ + "r5iscW3s8VKJKUpJ4W5SNA7JGL4l/5LmSnJ4Qu/xzxcoH4r4vmt75EDE9p2Ob2Xi1NuSFAZubJFc"
+ + "Zlnp4e05UHKikmoaz0PbiAi277sLQlK2FcVsntTYVT00y8+IwuuQu0ATVqkXC+VhfjV/sK6vQZnw"
+ + "2rQKedZhLB7B4dUkmxCujb/UAq4lgSpLMXg2P6wMimTczXyQxRiZxPeI4ByCENjkafXbfcJft2eD"
+ + "gv1DEDdYM5WrW9Z75b4lmJiOJ/xxDniHCvum7KGXzpK1d1mqTlpzPC2xoz08/MO4lRf5Mb0bYdq6"
+ + "CjMaYqVwGsYryp/2ayX+d8H+JphEG+V9Eg8uPcDoibwhDI4KkoyGHstPw5bxcy7vVFt7LXUdNjJc"
+ + "K1wxaUKEXDGKt9Vj93FnBTLMX0Pc9HpueV5o1ipX34dn/P3HZB9XK8ScbrE38B1VnIgylStnhVFO"
+ + "Cj9s7qSVqI2L+xYHJRHsxaMumIRnmRuOqdXDfIo28EZAnFtQ/b9BziMGVvAW5+A8h8s2oazhSmK2"
+ + "23ftV7uv98ScgE8fCd3PwT1kKJM83ThTYyBzokvMfPYCCvsonMV+kTWXhWcwjYTS4ukrpR452ZdW"
+ + "l3aJqDnzobt5FK4T8OGciOj+1PxYFZyRmCuafm2Dx6o7Et2Tu/T5HYvhdY9jHyqtDl2PXH4CTnVi"
+ + "gA1YOAArjPVmsZVwAM3Ml46uyXXhcsXwQ1X0Tv4D+PSa/id4UQ2cObOw8Cj1eW2GB8iJIZVqkZaU"
+ + "XBexqgWYOIoxjqODSeoZKiBsTK3c+oOUBqBDueY1i55swE2o6dDt95FluX6iyr/q4w2wLt3upY1J"
+ + "YL+TuvZxAKviuAczMS1bAAAAAAAAAAAAAA==");
+
+ //
+ // signed data
+ //
+ byte[] signedData = Base64.decode(
+ "MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAaCA"
+ + "JIAEDEhlbGxvIFdvcmxkIQAAAAAAAKCCBGIwggINMIIBdqADAgECAgEBMA0GCSqG"
+ + "SIb3DQEBBAUAMCUxFjAUBgNVBAoTDUJvdW5jeSBDYXN0bGUxCzAJBgNVBAYTAkFV"
+ + "MB4XDTA0MTAyNDA0MzA1OFoXDTA1MDIwMTA0MzA1OFowJTEWMBQGA1UEChMNQm91"
+ + "bmN5IENhc3RsZTELMAkGA1UEBhMCQVUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ"
+ + "AoGBAJj3OAshAOgDmPcYZ1jdNSuhOHRH9VhC/PG17FdiInVGc2ulJhEifEQga/uq"
+ + "ZCpSd1nHsJUZKm9k1bVneWzC0941i9Znfxgb2jnXXsa5kwB2KEVESrOWsRjSRtnY"
+ + "iLgqBG0rzpaMn5A5ntu7N0406EesBhe19cjZAageEHGZDbufAgMBAAGjTTBLMB0G"
+ + "A1UdDgQWBBR/iHNKOo6f4ByWFFywRNZ65XSr1jAfBgNVHSMEGDAWgBR/iHNKOo6f"
+ + "4ByWFFywRNZ65XSr1jAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBBAUAA4GBAFMJJ7QO"
+ + "pHo30bnlQ4Ny3PCnK+Se+Gw3TpaYGp84+a8fGD9Dme78G6NEsgvpFGTyoLxvJ4CB"
+ + "84Kzys+1p2HdXzoZiyXAer5S4IwptE3TxxFwKyj28cRrM6dK47DDyXUkV0qwBAMN"
+ + "luwnk/no4K7ilzN2MZk5l7wXyNa9yJ6CHW6dMIICTTCCAbagAwIBAgIBAjANBgkq"
+ + "hkiG9w0BAQQFADAlMRYwFAYDVQQKEw1Cb3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJB"
+ + "VTAeFw0wNDEwMjQwNDMwNTlaFw0wNTAyMDEwNDMwNTlaMGUxGDAWBgNVBAMTD0Vy"
+ + "aWMgSC4gRWNoaWRuYTEkMCIGCSqGSIb3DQEJARYVZXJpY0Bib3VuY3ljYXN0bGUu"
+ + "b3JnMRYwFAYDVQQKEw1Cb3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJBVTCBnzANBgkq"
+ + "hkiG9w0BAQEFAAOBjQAwgYkCgYEAm+5CnGU6W45iUpCsaGkn5gDruZv3j/o7N6ag"
+ + "mRZhikaLG2JF6ECaX13iioVJfmzBsPKxAACWwuTXCoSSXG8viK/qpSHwJpfQHYEh"
+ + "tcC0CxIqlnltv3KQAGwh/PdwpSPvSNnkQBGvtFq++9gnXDBbynfP8b2L2Eis0X9U"
+ + "2y6gFiMCAwEAAaNNMEswHQYDVR0OBBYEFEAmOksnF66FoQm6IQBVN66vJo1TMB8G"
+ + "A1UdIwQYMBaAFH+Ic0o6jp/gHJYUXLBE1nrldKvWMAkGA1UdEwQCMAAwDQYJKoZI"
+ + "hvcNAQEEBQADgYEAEeIjvNkKMPU/ZYCu1TqjGZPEqi+glntg2hC/CF0oGyHFpMuG"
+ + "tMepF3puW+uzKM1s61ar3ahidp3XFhr/GEU/XxK24AolI3yFgxP8PRgUWmQizTQX"
+ + "pWUmhlsBe1uIKVEfNAzCgtYfJQ8HJIKsUCcdWeCKVKs4jRionsek1rozkPExggEv"
+ + "MIIBKwIBATAqMCUxFjAUBgNVBAoTDUJvdW5jeSBDYXN0bGUxCzAJBgNVBAYTAkFV"
+ + "AgECMAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqG"
+ + "SIb3DQEJBTEPFw0wNDEwMjQwNDMwNTlaMCMGCSqGSIb3DQEJBDEWBBQu973mCM5U"
+ + "BOl9XwQvlfifHCMocTANBgkqhkiG9w0BAQEFAASBgGHbe3/jcZu6b/erRhc3PEji"
+ + "MUO8mEIRiNYBr5/vFNhkry8TrGfOpI45m7gu1MS0/vdas7ykvidl/sNZfO0GphEI"
+ + "UaIjMRT3U6yuTWF4aLpatJbbRsIepJO/B2kdIAbV5SCbZgVDJIPOR2qnruHN2wLF"
+ + "a+fEv4J8wQ8Xwvk0C8iMAAAAAAAA");
+
+ private boolean isSameAs(
+ byte[] a,
+ byte[] b)
+ {
+ if (a.length != b.length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i != a.length; i++)
+ {
+ if (a[i] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private TestResult compressionTest()
+ {
+ try
+ {
+ ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(compData));
+
+ ContentInfo info = ContentInfo.getInstance(aIn.readObject());
+ CompressedData data = CompressedData.getInstance(info.getContent());
+
+ data = new CompressedData(data.getCompressionAlgorithmIdentifier(), data.getEncapContentInfo());
+ info = new ContentInfo(CMSObjectIdentifiers.compressedData, data);
+
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ aOut.writeObject(info);
+
+ if (!isSameAs(bOut.toByteArray(), compData))
+ {
+ return new SimpleTestResult(false, getName() + ": CMS compression failed to re-encode");
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+ catch (Exception e)
+ {
+ return new SimpleTestResult(false, getName() + ": CMS compression failed - " + e.toString(), e);
+ }
+ }
+
+ private TestResult envelopedTest()
+ {
+ try
+ {
+ //
+ // Key trans
+ //
+ ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(envDataKeyTrns));
+
+ ContentInfo info = ContentInfo.getInstance(aIn.readObject());
+ EnvelopedData envData = EnvelopedData.getInstance(info.getContent());
+ ASN1Set s = envData.getRecipientInfos();
+
+ if (s.size() != 1)
+ {
+ return new SimpleTestResult(false, getName() + ": CMS KeyTrans enveloped, wrong number of recipients");
+ }
+
+ RecipientInfo recip = RecipientInfo.getInstance(s.getObjectAt(0));
+
+ if (recip.getInfo() instanceof KeyTransRecipientInfo)
+ {
+ KeyTransRecipientInfo inf = KeyTransRecipientInfo.getInstance(recip.getInfo());
+
+ inf = new KeyTransRecipientInfo(inf.getRecipientIdentifier(), inf.getKeyEncryptionAlgorithm(), inf.getEncryptedKey());
+
+ s = new DERSet(new RecipientInfo(inf));
+ }
+ else
+ {
+ return new SimpleTestResult(false, getName() + ": CMS KeyTrans enveloped, wrong recipient type");
+ }
+
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ envData = new EnvelopedData(envData.getOriginatorInfo(), s, envData.getEncryptedContentInfo(), envData.getUnprotectedAttrs());
+ info = new ContentInfo(CMSObjectIdentifiers.envelopedData, envData);
+
+ aOut.writeObject(info);
+
+ if (!isSameAs(bOut.toByteArray(), envDataKeyTrns))
+ {
+ return new SimpleTestResult(false, getName() + ": CMS KeyTrans enveloped failed to re-encode");
+ }
+
+ //
+ // KEK
+ //
+ aIn = new ASN1InputStream(new ByteArrayInputStream(envDataKEK));
+
+ info = ContentInfo.getInstance(aIn.readObject());
+ envData = EnvelopedData.getInstance(info.getContent());
+ s = envData.getRecipientInfos();
+
+ if (s.size() != 1)
+ {
+ return new SimpleTestResult(false, getName() + ": CMS KEK enveloped, wrong number of recipients");
+ }
+
+ recip = RecipientInfo.getInstance(s.getObjectAt(0));
+
+ if (recip.getInfo() instanceof KEKRecipientInfo)
+ {
+ KEKRecipientInfo inf = KEKRecipientInfo.getInstance(recip.getInfo());
+
+ inf = new KEKRecipientInfo(inf.getKekid(), inf.getKeyEncryptionAlgorithm(), inf.getEncryptedKey());
+
+ s = new DERSet(new RecipientInfo(inf));
+ }
+ else
+ {
+ return new SimpleTestResult(false, getName() + ": CMS KEK enveloped, wrong recipient type");
+ }
+
+ bOut = new ByteArrayOutputStream();
+ aOut = new ASN1OutputStream(bOut);
+
+ envData = new EnvelopedData(envData.getOriginatorInfo(), s, envData.getEncryptedContentInfo(), envData.getUnprotectedAttrs());
+ info = new ContentInfo(CMSObjectIdentifiers.envelopedData, envData);
+
+ aOut.writeObject(info);
+
+ if (!isSameAs(bOut.toByteArray(), envDataKEK))
+ { System.out.println(new String(Base64.encode(bOut.toByteArray())));
+ return new SimpleTestResult(false, getName() + ": CMS KEK enveloped failed to re-encode");
+ }
+
+ // Nested NDEF problem
+ ASN1StreamParser asn1In = new ASN1StreamParser(new ByteArrayInputStream(envDataNestedNDEF));
+ ContentInfoParser ci = new ContentInfoParser((ASN1SequenceParser)asn1In.readObject());
+ EnvelopedDataParser ed = new EnvelopedDataParser((ASN1SequenceParser)ci
+ .getContent(BERTags.SEQUENCE));
+ ed.getVersion();
+ ed.getOriginatorInfo();
+ ed.getRecipientInfos().toASN1Primitive();
+ EncryptedContentInfoParser eci = ed.getEncryptedContentInfo();
+ eci.getContentType();
+ eci.getContentEncryptionAlgorithm();
+
+ InputStream dataIn = ((ASN1OctetStringParser)eci.getEncryptedContent(BERTags.OCTET_STRING))
+ .getOctetStream();
+ Streams.drain(dataIn);
+ dataIn.close();
+
+ // Test data doesn't have unprotected attrs, bug was being thrown by this call
+ ASN1SetParser upa = ed.getUnprotectedAttrs();
+ if (upa != null)
+ {
+ upa.toASN1Primitive();
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+ catch (Exception e)
+ {
+ return new SimpleTestResult(false, getName() + ": CMS enveloped failed - " + e.toString(), e);
+ }
+ }
+
+ private TestResult signedTest()
+ {
+ try
+ {
+ ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(signedData));
+
+ ContentInfo info = ContentInfo.getInstance(aIn.readObject());
+ SignedData sData = SignedData.getInstance(info.getContent());
+
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ sData = new SignedData(sData.getDigestAlgorithms(), sData.getEncapContentInfo(), sData.getCertificates(), sData.getCRLs(), sData.getSignerInfos());
+ info = new ContentInfo(CMSObjectIdentifiers.signedData, sData);
+
+ aOut.writeObject(info);
+
+ if (!isSameAs(bOut.toByteArray(), signedData))
+ {
+ return new SimpleTestResult(false, getName() + ": CMS signed failed to re-encode");
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+ catch (Exception e)
+ {
+ return new SimpleTestResult(false, getName() + ": CMS signed failed - " + e.toString(), e);
+ }
+ }
+
+ public TestResult perform()
+ {
+ TestResult res = compressionTest();
+
+ if (!res.isSuccessful())
+ {
+ return res;
+ }
+
+ res = envelopedTest();
+ if (!res.isSuccessful())
+ {
+ return res;
+ }
+
+ return signedTest();
+ }
+
+ public String getName()
+ {
+ return "CMS";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ CMSTest test = new CMSTest();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/CertHashUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/CertHashUnitTest.java
new file mode 100644
index 00000000..283d64f2
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/CertHashUnitTest.java
@@ -0,0 +1,84 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.isismtt.ocsp.CertHash;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+public class CertHashUnitTest
+ extends ASN1UnitTest
+{
+ public String getName()
+ {
+ return "CertHash";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ AlgorithmIdentifier algId = new AlgorithmIdentifier(new ASN1ObjectIdentifier("1.2.2.3"));
+ byte[] digest = new byte[20];
+
+ CertHash certID = new CertHash(algId, digest);
+
+ checkConstruction(certID, algId, digest);
+
+ certID = CertHash.getInstance(null);
+
+ if (certID != null)
+ {
+ fail("null getInstance() failed.");
+ }
+
+ try
+ {
+ CertHash.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ CertHash certHash,
+ AlgorithmIdentifier algId,
+ byte[] digest)
+ throws IOException
+ {
+ checkValues(certHash, algId, digest);
+
+ certHash = CertHash.getInstance(certHash);
+
+ checkValues(certHash, algId, digest);
+
+ ASN1InputStream aIn = new ASN1InputStream(certHash.toASN1Object().getEncoded());
+
+ ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
+
+ certHash = CertHash.getInstance(seq);
+
+ checkValues(certHash, algId, digest);
+ }
+
+ private void checkValues(
+ CertHash certHash,
+ AlgorithmIdentifier algId,
+ byte[] digest)
+ {
+ checkMandatoryField("algorithmHash", algId, certHash.getHashAlgorithm());
+
+ checkMandatoryField("certificateHash", digest, certHash.getCertificateHash());
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new CertHashUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/CertificateTest.java b/core/src/test/java/org/spongycastle/asn1/test/CertificateTest.java
new file mode 100644
index 00000000..bfdba438
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/CertificateTest.java
@@ -0,0 +1,574 @@
+package org.spongycastle.asn1.test;
+
+import java.io.ByteArrayInputStream;
+import java.util.Enumeration;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.AttCertIssuer;
+import org.spongycastle.asn1.x509.AttCertValidityPeriod;
+import org.spongycastle.asn1.x509.Attribute;
+import org.spongycastle.asn1.x509.AttributeCertificate;
+import org.spongycastle.asn1.x509.AttributeCertificateInfo;
+import org.spongycastle.asn1.x509.AuthorityKeyIdentifier;
+import org.spongycastle.asn1.x509.BasicConstraints;
+import org.spongycastle.asn1.x509.CRLDistPoint;
+import org.spongycastle.asn1.x509.Certificate;
+import org.spongycastle.asn1.x509.DistributionPoint;
+import org.spongycastle.asn1.x509.ExtendedKeyUsage;
+import org.spongycastle.asn1.x509.Extension;
+import org.spongycastle.asn1.x509.Extensions;
+import org.spongycastle.asn1.x509.GeneralName;
+import org.spongycastle.asn1.x509.GeneralNames;
+import org.spongycastle.asn1.x509.Holder;
+import org.spongycastle.asn1.x509.KeyPurposeId;
+import org.spongycastle.asn1.x509.KeyUsage;
+import org.spongycastle.asn1.x509.PolicyInformation;
+import org.spongycastle.asn1.x509.SubjectKeyIdentifier;
+import org.spongycastle.asn1.x509.TBSCertificate;
+import org.spongycastle.util.encoders.Base64;
+import org.spongycastle.util.test.SimpleTest;
+
+public class CertificateTest
+ extends SimpleTest
+{
+ //
+ // server.crt
+ //
+ byte[] cert1 = Base64.decode(
+ "MIIDXjCCAsegAwIBAgIBBzANBgkqhkiG9w0BAQQFADCBtzELMAkGA1UEBhMCQVUx"
+ + "ETAPBgNVBAgTCFZpY3RvcmlhMRgwFgYDVQQHEw9Tb3V0aCBNZWxib3VybmUxGjAY"
+ + "BgNVBAoTEUNvbm5lY3QgNCBQdHkgTHRkMR4wHAYDVQQLExVDZXJ0aWZpY2F0ZSBB"
+ + "dXRob3JpdHkxFTATBgNVBAMTDENvbm5lY3QgNCBDQTEoMCYGCSqGSIb3DQEJARYZ"
+ + "d2VibWFzdGVyQGNvbm5lY3Q0LmNvbS5hdTAeFw0wMDA2MDIwNzU2MjFaFw0wMTA2"
+ + "MDIwNzU2MjFaMIG4MQswCQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExGDAW"
+ + "BgNVBAcTD1NvdXRoIE1lbGJvdXJuZTEaMBgGA1UEChMRQ29ubmVjdCA0IFB0eSBM"
+ + "dGQxFzAVBgNVBAsTDldlYnNlcnZlciBUZWFtMR0wGwYDVQQDExR3d3cyLmNvbm5l"
+ + "Y3Q0LmNvbS5hdTEoMCYGCSqGSIb3DQEJARYZd2VibWFzdGVyQGNvbm5lY3Q0LmNv"
+ + "bS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArvDxclKAhyv7Q/Wmr2re"
+ + "Gw4XL9Cnh9e+6VgWy2AWNy/MVeXdlxzd7QAuc1eOWQkGQEiLPy5XQtTY+sBUJ3AO"
+ + "Rvd2fEVJIcjf29ey7bYua9J/vz5MG2KYo9/WCHIwqD9mmG9g0xLcfwq/s8ZJBswE"
+ + "7sb85VU+h94PTvsWOsWuKaECAwEAAaN3MHUwJAYDVR0RBB0wG4EZd2VibWFzdGVy"
+ + "QGNvbm5lY3Q0LmNvbS5hdTA6BglghkgBhvhCAQ0ELRYrbW9kX3NzbCBnZW5lcmF0"
+ + "ZWQgY3VzdG9tIHNlcnZlciBjZXJ0aWZpY2F0ZTARBglghkgBhvhCAQEEBAMCBkAw"
+ + "DQYJKoZIhvcNAQEEBQADgYEAotccfKpwSsIxM1Hae8DR7M/Rw8dg/RqOWx45HNVL"
+ + "iBS4/3N/TO195yeQKbfmzbAA2jbPVvIvGgTxPgO1MP4ZgvgRhasaa0qCJCkWvpM4"
+ + "yQf33vOiYQbpv4rTwzU8AmRlBG45WdjyNIigGV+oRc61aKCTnLq7zB8N3z1TF/bF"
+ + "5/8=");
+
+ //
+ // ca.crt
+ //
+ byte[] cert2 = Base64.decode(
+ "MIIDbDCCAtWgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBtzELMAkGA1UEBhMCQVUx"
+ + "ETAPBgNVBAgTCFZpY3RvcmlhMRgwFgYDVQQHEw9Tb3V0aCBNZWxib3VybmUxGjAY"
+ + "BgNVBAoTEUNvbm5lY3QgNCBQdHkgTHRkMR4wHAYDVQQLExVDZXJ0aWZpY2F0ZSBB"
+ + "dXRob3JpdHkxFTATBgNVBAMTDENvbm5lY3QgNCBDQTEoMCYGCSqGSIb3DQEJARYZ"
+ + "d2VibWFzdGVyQGNvbm5lY3Q0LmNvbS5hdTAeFw0wMDA2MDIwNzU1MzNaFw0wMTA2"
+ + "MDIwNzU1MzNaMIG3MQswCQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExGDAW"
+ + "BgNVBAcTD1NvdXRoIE1lbGJvdXJuZTEaMBgGA1UEChMRQ29ubmVjdCA0IFB0eSBM"
+ + "dGQxHjAcBgNVBAsTFUNlcnRpZmljYXRlIEF1dGhvcml0eTEVMBMGA1UEAxMMQ29u"
+ + "bmVjdCA0IENBMSgwJgYJKoZIhvcNAQkBFhl3ZWJtYXN0ZXJAY29ubmVjdDQuY29t"
+ + "LmF1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgs5ptNG6Qv1ZpCDuUNGmv"
+ + "rhjqMDPd3ri8JzZNRiiFlBA4e6/ReaO1U8ASewDeQMH6i9R6degFdQRLngbuJP0s"
+ + "xcEE+SksEWNvygfzLwV9J/q+TQDyJYK52utb++lS0b48A1KPLwEsyL6kOAgelbur"
+ + "ukwxowprKUIV7Knf1ajetQIDAQABo4GFMIGCMCQGA1UdEQQdMBuBGXdlYm1hc3Rl"
+ + "ckBjb25uZWN0NC5jb20uYXUwDwYDVR0TBAgwBgEB/wIBADA2BglghkgBhvhCAQ0E"
+ + "KRYnbW9kX3NzbCBnZW5lcmF0ZWQgY3VzdG9tIENBIGNlcnRpZmljYXRlMBEGCWCG"
+ + "SAGG+EIBAQQEAwICBDANBgkqhkiG9w0BAQQFAAOBgQCsGvfdghH8pPhlwm1r3pQk"
+ + "msnLAVIBb01EhbXm2861iXZfWqGQjrGAaA0ZpXNk9oo110yxoqEoSJSzniZa7Xtz"
+ + "soTwNUpE0SLHvWf/SlKdFWlzXA+vOZbzEv4UmjeelekTm7lc01EEa5QRVzOxHFtQ"
+ + "DhkaJ8VqOMajkQFma2r9iA==");
+
+ //
+ // testx509.pem
+ //
+ byte[] cert3 = Base64.decode(
+ "MIIBWzCCAQYCARgwDQYJKoZIhvcNAQEEBQAwODELMAkGA1UEBhMCQVUxDDAKBgNV"
+ + "BAgTA1FMRDEbMBkGA1UEAxMSU1NMZWF5L3JzYSB0ZXN0IENBMB4XDTk1MDYxOTIz"
+ + "MzMxMloXDTk1MDcxNzIzMzMxMlowOjELMAkGA1UEBhMCQVUxDDAKBgNVBAgTA1FM"
+ + "RDEdMBsGA1UEAxMUU1NMZWF5L3JzYSB0ZXN0IGNlcnQwXDANBgkqhkiG9w0BAQEF"
+ + "AANLADBIAkEAqtt6qS5GTxVxGZYWa0/4u+IwHf7p2LNZbcPBp9/OfIcYAXBQn8hO"
+ + "/Re1uwLKXdCjIoaGs4DLdG88rkzfyK5dPQIDAQABMAwGCCqGSIb3DQIFBQADQQAE"
+ + "Wc7EcF8po2/ZO6kNCwK/ICH6DobgLekA5lSLr5EvuioZniZp5lFzAw4+YzPQ7XKJ"
+ + "zl9HYIMxATFyqSiD9jsx");
+
+ //
+ // v3-cert1.pem
+ //
+ byte[] cert4 = Base64.decode(
+ "MIICjTCCAfigAwIBAgIEMaYgRzALBgkqhkiG9w0BAQQwRTELMAkGA1UEBhMCVVMx"
+ + "NjA0BgNVBAoTLU5hdGlvbmFsIEFlcm9uYXV0aWNzIGFuZCBTcGFjZSBBZG1pbmlz"
+ + "dHJhdGlvbjAmFxE5NjA1MjgxMzQ5MDUrMDgwMBcROTgwNTI4MTM0OTA1KzA4MDAw"
+ + "ZzELMAkGA1UEBhMCVVMxNjA0BgNVBAoTLU5hdGlvbmFsIEFlcm9uYXV0aWNzIGFu"
+ + "ZCBTcGFjZSBBZG1pbmlzdHJhdGlvbjEgMAkGA1UEBRMCMTYwEwYDVQQDEwxTdGV2"
+ + "ZSBTY2hvY2gwWDALBgkqhkiG9w0BAQEDSQAwRgJBALrAwyYdgxmzNP/ts0Uyf6Bp"
+ + "miJYktU/w4NG67ULaN4B5CnEz7k57s9o3YY3LecETgQ5iQHmkwlYDTL2fTgVfw0C"
+ + "AQOjgaswgagwZAYDVR0ZAQH/BFowWDBWMFQxCzAJBgNVBAYTAlVTMTYwNAYDVQQK"
+ + "Ey1OYXRpb25hbCBBZXJvbmF1dGljcyBhbmQgU3BhY2UgQWRtaW5pc3RyYXRpb24x"
+ + "DTALBgNVBAMTBENSTDEwFwYDVR0BAQH/BA0wC4AJODMyOTcwODEwMBgGA1UdAgQR"
+ + "MA8ECTgzMjk3MDgyM4ACBSAwDQYDVR0KBAYwBAMCBkAwCwYJKoZIhvcNAQEEA4GB"
+ + "AH2y1VCEw/A4zaXzSYZJTTUi3uawbbFiS2yxHvgf28+8Js0OHXk1H1w2d6qOHH21"
+ + "X82tZXd/0JtG0g1T9usFFBDvYK8O0ebgz/P5ELJnBL2+atObEuJy1ZZ0pBDWINR3"
+ + "WkDNLCGiTkCKp0F5EWIrVDwh54NNevkCQRZita+z4IBO");
+
+ //
+ // v3-cert2.pem
+ //
+ byte[] cert5 = Base64.decode(
+ "MIICiTCCAfKgAwIBAgIEMeZfHzANBgkqhkiG9w0BAQQFADB9MQswCQYDVQQGEwJD"
+ + "YTEPMA0GA1UEBxMGTmVwZWFuMR4wHAYDVQQLExVObyBMaWFiaWxpdHkgQWNjZXB0"
+ + "ZWQxHzAdBgNVBAoTFkZvciBEZW1vIFB1cnBvc2VzIE9ubHkxHDAaBgNVBAMTE0Vu"
+ + "dHJ1c3QgRGVtbyBXZWIgQ0EwHhcNOTYwNzEyMTQyMDE1WhcNOTYxMDEyMTQyMDE1"
+ + "WjB0MSQwIgYJKoZIhvcNAQkBExVjb29rZUBpc3NsLmF0bC5ocC5jb20xCzAJBgNV"
+ + "BAYTAlVTMScwJQYDVQQLEx5IZXdsZXR0IFBhY2thcmQgQ29tcGFueSAoSVNTTCkx"
+ + "FjAUBgNVBAMTDVBhdWwgQS4gQ29va2UwXDANBgkqhkiG9w0BAQEFAANLADBIAkEA"
+ + "6ceSq9a9AU6g+zBwaL/yVmW1/9EE8s5you1mgjHnj0wAILuoB3L6rm6jmFRy7QZT"
+ + "G43IhVZdDua4e+5/n1ZslwIDAQABo2MwYTARBglghkgBhvhCAQEEBAMCB4AwTAYJ"
+ + "YIZIAYb4QgENBD8WPVRoaXMgY2VydGlmaWNhdGUgaXMgb25seSBpbnRlbmRlZCBm"
+ + "b3IgZGVtb25zdHJhdGlvbiBwdXJwb3Nlcy4wDQYJKoZIhvcNAQEEBQADgYEAi8qc"
+ + "F3zfFqy1sV8NhjwLVwOKuSfhR/Z8mbIEUeSTlnH3QbYt3HWZQ+vXI8mvtZoBc2Fz"
+ + "lexKeIkAZXCesqGbs6z6nCt16P6tmdfbZF3I3AWzLquPcOXjPf4HgstkyvVBn0Ap"
+ + "jAFN418KF/Cx4qyHB4cjdvLrRjjQLnb2+ibo7QU=");
+
+ byte[] cert6 = Base64.decode(
+ "MIIEDjCCAvagAwIBAgIEFAAq2jANBgkqhkiG9w0BAQUFADBLMSowKAYDVQQDEyFT"
+ + "dW4gTWljcm9zeXN0ZW1zIEluYyBDQSAoQ2xhc3MgQikxHTAbBgNVBAoTFFN1biBN"
+ + "aWNyb3N5c3RlbXMgSW5jMB4XDTA0MDIyOTAwNDMzNFoXDTA5MDMwMTAwNDMzNFow"
+ + "NzEdMBsGA1UEChMUU3VuIE1pY3Jvc3lzdGVtcyBJbmMxFjAUBgNVBAMTDXN0b3Jl"
+ + "LnN1bi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAP9ErzFT7MPg2bVV"
+ + "LNmHTgN4kmiRNlPpuLGWS7EDIXYBbLeSSOCp/e1ANcOGnsuf0WIq9ejd/CPyEfh4"
+ + "sWoVvQzpOfHZ/Jyei29PEuxzWT+4kQmCx3+sLK25lAnDFsz1KiFmB6Y3GJ/JSjpp"
+ + "L0Yy1R9YlIc82I8gSw44y5JDABW5AgMBAAGjggGQMIIBjDAOBgNVHQ8BAf8EBAMC"
+ + "BaAwHQYDVR0OBBYEFG1WB3PApZM7OPPVWJ31UrERaoKWMEcGA1UdIARAMD4wPAYL"
+ + "YIZIAYb3AIN9k18wLTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5zdW4uY29tL3Br"
+ + "aS9jcHMuaHRtbDCBhQYDVR0fBH4wfDB6oCegJYYjaHR0cDovL3d3dy5zdW4uY29t"
+ + "L3BraS9wa2lzbWljYS5jcmyiT6RNMEsxKjAoBgNVBAMTIVN1biBNaWNyb3N5c3Rl"
+ + "bXMgSW5jIENBIChDbGFzcyBCKTEdMBsGA1UEChMUU3VuIE1pY3Jvc3lzdGVtcyBJ"
+ + "bmMwHwYDVR0jBBgwFoAUT7ZnqR/EEBSgG6h1wdYMI5RiiWswVAYIKwYBBQUHAQEE"
+ + "SDBGMB0GCCsGAQUFBzABhhFodHRwOi8vdmEuc3VuLmNvbTAlBggrBgEFBQcwAYYZ"
+ + "aHR0cDovL3ZhLmNlbnRyYWwuc3VuLmNvbTATBgNVHSUEDDAKBggrBgEFBQcDATAN"
+ + "BgkqhkiG9w0BAQUFAAOCAQEAq3byQgyU24tBpR07iQK7agm1zQyzDQ6itdbji0ln"
+ + "T7fOd5Pnp99iig8ovwWliNtXKAmgtJY60jWz7nEuk38AioZJhS+RPWIWX/+2PRV7"
+ + "s2aWTzM3n43BypD+jU2qF9c9kDWP/NW9K9IcrS7SfU/2MZVmiCMD/9FEL+CWndwE"
+ + "JJQ/oenXm44BFISI/NjV7fMckN8EayPvgtzQkD5KnEiggOD6HOrwTDFR+tmAEJ0K"
+ + "ZttQNwOzCOcEdxXTg6qBHUbONdL7bjTT5NzV+JR/bnfiCqHzdnGwfbHzhmrnXw8j"
+ + "QCVXcfBfL9++nmpNNRlnJMRdYGeCY6OAfh/PRo8/fXak1Q==");
+
+ byte[] cert7 = Base64.decode(
+ "MIIFJDCCBAygAwIBAgIKEcJZuwAAAAAABzANBgkqhkiG9w0BAQUFADAPMQ0wCwYD"
+ + "VQQDEwRNU0NBMB4XDTA0MDUyMjE2MTM1OFoXDTA1MDUyMjE2MjM1OFowaTEbMBkG"
+ + "CSqGSIb3DQEJCBMMMTkyLjE2OC4xLjMzMScwJQYJKoZIhvcNAQkCExhwaXhmaXJl"
+ + "d2FsbC5jaXNjb3BpeC5jb20xITAfBgNVBAMTGHBpeGZpcmV3YWxsLmNpc2NvcGl4"
+ + "LmNvbTB8MA0GCSqGSIb3DQEBAQUAA2sAMGgCYQCbcsY7vrjweXZiFQdhUafEjJV+"
+ + "HRy5UKmuCy0237ffmYrN+XNLw0h90cdCSK6KPZebd2E2Bc2UmTikc/FY8meBT3/E"
+ + "O/Osmywzi++Ur8/IrDvtuR1zd0c/xEPnV1ZRezkCAwEAAaOCAs4wggLKMAsGA1Ud"
+ + "DwQEAwIFoDAdBgNVHQ4EFgQUzJBSxkQiN9TKvhTMQ1/Aq4gZnHswHwYDVR0jBBgw"
+ + "FoAUMsxzXVh+5UKMNpwNHmqSfcRYfJ4wgfcGA1UdHwSB7zCB7DCB6aCB5qCB44aB"
+ + "r2xkYXA6Ly8vQ049TVNDQSxDTj1NQVVELENOPUNEUCxDTj1QdWJsaWMlMjBLZXkl"
+ + "MjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25maWd1cmF0aW9uLERDPWludCxE"
+ + "Qz1wcmltZWtleSxEQz1zZT9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0P2Jhc2U/"
+ + "b2JqZWN0Q2xhc3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnSGL2h0dHA6Ly9tYXVkLmlu"
+ + "dC5wcmltZWtleS5zZS9DZXJ0RW5yb2xsL01TQ0EuY3JsMIIBEAYIKwYBBQUHAQEE"
+ + "ggECMIH/MIGqBggrBgEFBQcwAoaBnWxkYXA6Ly8vQ049TVNDQSxDTj1BSUEsQ049"
+ + "UHVibGljJTIwS2V5JTIwU2VydmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJh"
+ + "dGlvbixEQz1pbnQsREM9cHJpbWVrZXksREM9c2U/Y0FDZXJ0aWZpY2F0ZT9iYXNl"
+ + "P29iamVjdENsYXNzPWNlcnRpZmljYXRpb25BdXRob3JpdHkwUAYIKwYBBQUHMAKG"
+ + "RGh0dHA6Ly9tYXVkLmludC5wcmltZWtleS5zZS9DZXJ0RW5yb2xsL01BVUQuaW50"
+ + "LnByaW1la2V5LnNlX01TQ0EuY3J0MCwGA1UdEQEB/wQiMCCCGHBpeGZpcmV3YWxs"
+ + "LmNpc2NvcGl4LmNvbYcEwKgBITA/BgkrBgEEAYI3FAIEMh4wAEkAUABTAEUAQwBJ"
+ + "AG4AdABlAHIAbQBlAGQAaQBhAHQAZQBPAGYAZgBsAGkAbgBlMA0GCSqGSIb3DQEB"
+ + "BQUAA4IBAQCa0asiPbObLJjpSz6ndJ7y4KOWMiuuBc/VQBnLr7RBCF3ZlZ6z1+e6"
+ + "dmv8se/z11NgateKfxw69IhLCriA960HEgX9Z61MiVG+DrCFpbQyp8+hPFHoqCZN"
+ + "b7upc8k2OtJW6KPaP9k0DW52YQDIky4Vb2rZeC4AMCorWN+KlndHhr1HFA14HxwA"
+ + "4Mka0FM6HNWnBV2UmTjBZMDr/OrGH1jLYIceAaZK0X2R+/DWXeeqIga8jwP5empq"
+ + "JetYnkXdtTbEh3xL0BX+mZl8vDI+/PGcwox/7YjFmyFWphRMxk9CZ3rF2/FQWMJP"
+ + "YqQpKiQOmQg5NAhcwffLAuVjVVibPYqi");
+
+ byte[] cert8 = Base64.decode(
+ "MIIB0zCCATwCAQEwbqBsMGekZTBjMQswCQYDVQQGEwJERTELMAkGA1UECBMCQlkx"
+ + "EzARBgNVBAcTClJlZ2Vuc2J1cmcxEDAOBgNVBAoTB0FDIFRlc3QxCzAJBgNVBAsT"
+ + "AkNBMRMwEQYDVQQDEwpBQyBUZXN0IENBAgEBoHYwdKRyMHAxCzAJBgNVBAYTAkRF"
+ + "MQswCQYDVQQIEwJCWTETMBEGA1UEBxMKUmVnZW5zYnVyZzESMBAGA1UEChMJQUMg"
+ + "SXNzdWVyMRowGAYDVQQLExFBQyBJc3N1ZXIgc2VjdGlvbjEPMA0GA1UEAxMGQUMg"
+ + "TWFuMA0GCSqGSIb3DQEBBQUAAgEBMCIYDzIwMDQxMTI2MTI1MjUxWhgPMjAwNDEy"
+ + "MzEyMzAwMDBaMBkwFwYDVRhIMRAwDoEMREFVMTIzNDU2Nzg5MA0GCSqGSIb3DQEB"
+ + "BQUAA4GBABd4Odx3yEMGL/BvItuT1RafNR2uuWuZbajg0pD6bshUsl+WCIfRiEkq"
+ + "lHMkpI7WqAZikdnAEQ5jQsVWEuVejWxR6gjejKxc0fb9qpIui7/GoI5Eh6dmG20e"
+ + "xbwJL3+6YYFrZwxR8cC5rPvWrblUR5XKJy+Zp/H5+t9iANnL1L8J");
+
+ // V1 attribute certificate
+ private static final byte[] attrCertv1 = Base64.decode(
+ "MIIFdDCCBFygXTBbMFOkUTBPMQswCQYDVQQGEwJERTEcMBoGA1UECgwTRGV1"
+ + "dHNjaGUgVGVsZWtvbSBBRzEiMCAGA1UEAwwZVGVsZVNlYyBQS1MgU2lnRyBD"
+ + "QSAxNzpQTgIEG1toDjBTpFEwTzELMAkGA1UEBhMCREUxHDAaBgNVBAoME0Rl"
+ + "dXRzY2hlIFRlbGVrb20gQUcxIjAgBgNVBAMMGVRlbGVTZWMgUEtTIFNpZ0cg"
+ + "Q0EgMjU6UE4wDQYJKoZIhvcNAQELBQACBCep3f0wIhgPMjAxMDA0MTIxMTI5"
+ + "MTJaGA8yMDEyMDQxMjEwNTkyOFowggGmMIIBogYFKyQIAwgxggGXDIIBk1Ro"
+ + "ZSBxdWFsaWZpZWQgc2lnbmF0dXJlIGF0IGhhbmQgaXMgcmVzdHJpY3RlZCB0"
+ + "byBwcmVzZW50aW5nIGludm9pY2VzIG9yIGNyZWRpdHMgdG8gY3VzdG9tZXJz"
+ + "IGFjY29yZGluZyB0byBFVSBDb3VuY2lsIGRpcmVjdGl2ZSAyMDAxLzExNS9F"
+ + "QyAoMjB0aCBEZWNlbWJlciAyMDAxKSBhbmQgR2VybWFuIFZBVCB0YXggKMKn"
+ + "MTQgVVN0RykuICBEaWUgdm9ybGllZ2VuZGUgcXVhbGlmaXppZXJ0ZSBTaWdu"
+ + "YXR1ciBpc3QgYXVmIGRpZSAgUHJhZXNlbnRhdGlvbiB2b24gUmVjaG51bmdl"
+ + "biBvZGVyIEd1dHNjaHJpZnRlbiBnZW1hZXNzIEVVIERpcmVrdGl2ZSAyMDAx"
+ + "LzExNS9FQyAoMjAuIERlemVtYmVyIDIwMDEpIHVuZCBkZXV0c2NoZW0gVW1z"
+ + "YXR6c3RldWVyZ2VzZXR6ICAowqcxNCBVU3RHKSBiZXNjaHJhZW5rdC4wggHB"
+ + "MB8GA1UdIwQYMBaAFM6i1yR/z8IikpxpU/Fdh8BPxhq8MEMGA1UdIAQ8MDow"
+ + "OAYFKyQIAQEwLzAtBggrBgEFBQcCARYhaHR0cDovL3Brcy50ZWxlc2VjLmRl"
+ + "L2Nwcy9jcHMucGRmMIIBBAYDVR0fBIH8MIH5MIH2oG2ga4Y1bGRhcDovL3Br"
+ + "cy1sZGFwLnRlbGVzZWMuZGUvbz1EZXV0c2NoZSBUZWxla29tIEFHLGM9ZGWG"
+ + "Mmh0dHA6Ly9wa3MudGVsZXNlYy5kZS90ZWxlc2VjL3NlcnZsZXQvZG93bmxv"
+ + "YWRfY3JsooGEpIGBMH8xCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2No"
+ + "ZSBUZWxla29tIEFHMR8wHQYDVQQLFBZQcm9kdWt0emVudHJ1bSBUZWxlU2Vj"
+ + "MTEwDAYHAoIGAQoHFBMBMTAhBgNVBAMUGlRlbGVTZWMgUEtTIFNpZ0cgRElS"
+ + "IDM1OlBOMDcGCCsGAQUFBwEBBCswKTAnBggrBgEFBQcwAYYbaHR0cDovL3Br"
+ + "cy50ZWxlc2VjLmRlL29jc3ByMBgGCCsGAQUFBwEDBAwwCjAIBgYEAI5GAQEw"
+ + "DQYJKoZIhvcNAQELBQADggEBAEz2OvU9YytJUKHMDQcND5njIyUXTkSrlWjV"
+ + "F28uwxVlveO4JPTAY7PvXy69HUuTPwlvqCfJIUF2RLPZFQx0wFto8ajC9v5X"
+ + "SqwQcINXRakpE6FPAdQFnH44TaIQWXW1hy9xr8GuD0uhQLTJGYqVzHfLoM8e"
+ + "llPNHUVhC7CEOxDb1PTHCUlQFNkFRmeeqzEVoj1F0pM6wI5zf8+w2WwrFPCD"
+ + "jrjEr/VoBRoEi/tKnsLq6oOkizUKT0KJEnSyYxoOa7euT1yX+Co94SPnMZi5"
+ + "qukHSj8Kiio6Jecl//qDPG/mHo1ro+8rH+rbze7EEfKMp5yeWCwXGthL9oYo"
+ + "RYl+UuI=");
+
+ String[] subjects =
+ {
+ "C=AU,ST=Victoria,L=South Melbourne,O=Connect 4 Pty Ltd,OU=Webserver Team,CN=www2.connect4.com.au,E=webmaster@connect4.com.au",
+ "C=AU,ST=Victoria,L=South Melbourne,O=Connect 4 Pty Ltd,OU=Certificate Authority,CN=Connect 4 CA,E=webmaster@connect4.com.au",
+ "C=AU,ST=QLD,CN=SSLeay/rsa test cert",
+ "C=US,O=National Aeronautics and Space Administration,SERIALNUMBER=16+CN=Steve Schoch",
+ "E=cooke@issl.atl.hp.com,C=US,OU=Hewlett Packard Company (ISSL),CN=Paul A. Cooke",
+ "O=Sun Microsystems Inc,CN=store.sun.com",
+ "unstructuredAddress=192.168.1.33,unstructuredName=pixfirewall.ciscopix.com,CN=pixfirewall.ciscopix.com"
+ };
+
+ public String getName()
+ {
+ return "Certificate";
+ }
+
+ public void checkCertificate(
+ int id,
+ byte[] cert)
+ throws Exception
+ {
+ ByteArrayInputStream bIn = new ByteArrayInputStream(cert);
+ ASN1InputStream aIn = new ASN1InputStream(bIn);
+
+ ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
+// String dump = ASN1Dump.dumpAsString(seq);
+
+ Certificate obj = Certificate.getInstance(seq);
+ TBSCertificate tbsCert = obj.getTBSCertificate();
+
+ if (!tbsCert.getSubject().toString().equals(subjects[id - 1]))
+ {
+ fail("failed subject test for certificate id " + id + " got " + tbsCert.getSubject().toString());
+ }
+
+ if (tbsCert.getVersionNumber() == 3)
+ {
+ Extensions ext = tbsCert.getExtensions();
+ if (ext != null)
+ {
+ Enumeration en = ext.oids();
+ while (en.hasMoreElements())
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)en.nextElement();
+ Extension extVal = ext.getExtension(oid);
+
+ ASN1OctetString oct = extVal.getExtnValue();
+ ASN1InputStream extIn = new ASN1InputStream(new ByteArrayInputStream(oct.getOctets()));
+
+ if (oid.equals(Extension.subjectKeyIdentifier))
+ {
+ SubjectKeyIdentifier si = SubjectKeyIdentifier.getInstance(extIn.readObject());
+
+ if (!si.equals(SubjectKeyIdentifier.fromExtensions(ext)))
+ {
+ fail("SubjectKeyIdentifier not matched");
+ }
+ }
+ else if (oid.equals(Extension.keyUsage))
+ {
+ KeyUsage ku = KeyUsage.getInstance(extIn.readObject());
+
+ if (!ku.equals(KeyUsage.fromExtensions(ext)))
+ {
+ fail("KeyUsage not matched");
+ }
+ }
+ else if (oid.equals(Extension.extendedKeyUsage))
+ {
+ ExtendedKeyUsage ku = ExtendedKeyUsage.getInstance(extIn.readObject());
+
+ ASN1Sequence sq = (ASN1Sequence)ku.toASN1Primitive();
+ for (int i = 0; i != sq.size(); i++)
+ {
+ ASN1ObjectIdentifier p = ASN1ObjectIdentifier.getInstance(KeyPurposeId.getInstance(sq.getObjectAt(i)));
+ }
+
+ if (!ku.equals(ExtendedKeyUsage.fromExtensions(ext)))
+ {
+ fail("ExtendedKeyUsage not matched");
+ }
+ }
+ else if (oid.equals(Extension.subjectAlternativeName))
+ {
+ GeneralNames gn = GeneralNames.getInstance(extIn.readObject());
+
+ ASN1Sequence sq = (ASN1Sequence)gn.toASN1Primitive();
+ for (int i = 0; i != sq.size(); i++)
+ {
+ GeneralName n = GeneralName.getInstance(sq.getObjectAt(i));
+ }
+ }
+ else if (oid.equals(Extension.issuerAlternativeName))
+ {
+ GeneralNames gn = GeneralNames.getInstance(extIn.readObject());
+
+ ASN1Sequence sq = (ASN1Sequence)gn.toASN1Primitive();
+ for (int i = 0; i != sq.size(); i++)
+ {
+ GeneralName n = GeneralName.getInstance(sq.getObjectAt(i));
+ }
+ }
+ else if (oid.equals(Extension.cRLDistributionPoints))
+ {
+ CRLDistPoint p = CRLDistPoint.getInstance(extIn.readObject());
+
+ DistributionPoint[] points = p.getDistributionPoints();
+ for (int i = 0; i != points.length; i++)
+ {
+ // do nothing
+ }
+ }
+ else if (oid.equals(Extension.certificatePolicies))
+ {
+ ASN1Sequence cp = (ASN1Sequence)extIn.readObject();
+
+ for (int i = 0; i != cp.size(); i++)
+ {
+ PolicyInformation.getInstance(cp.getObjectAt(i));
+ }
+ }
+ else if (oid.equals(Extension.authorityKeyIdentifier))
+ {
+ AuthorityKeyIdentifier auth = AuthorityKeyIdentifier.getInstance(extIn.readObject());
+
+ if (!auth.equals(AuthorityKeyIdentifier.fromExtensions(ext)))
+ {
+ fail("AuthorityKeyIdentifier not matched");
+ }
+ }
+ else if (oid.equals(Extension.basicConstraints))
+ {
+ BasicConstraints bc = BasicConstraints.getInstance(extIn.readObject());
+
+ if (!bc.equals(BasicConstraints.fromExtensions(ext)))
+ {
+ fail("BasicConstraints not matched");
+ }
+ }
+ else
+ {
+ //System.out.println(oid.getId());
+ }
+ }
+ }
+ }
+ }
+
+
+ public void checkAttributeCertificate(
+ int id,
+ byte[] cert)
+ throws Exception
+ {
+ ByteArrayInputStream bIn;
+ ASN1InputStream aIn;
+
+ bIn = new ByteArrayInputStream(cert);
+ aIn = new ASN1InputStream(bIn);
+
+ ASN1Sequence seq = (ASN1Sequence) aIn.readObject();
+// String dump = ASN1Dump.dumpAsString(seq);
+
+ AttributeCertificate obj = AttributeCertificate.getInstance(seq);
+ AttributeCertificateInfo acInfo = obj.getAcinfo();
+
+ // Version
+ if (!(acInfo.getVersion().equals(new ASN1Integer(1)))
+ && (!(acInfo.getVersion().equals(new ASN1Integer(2)))))
+ {
+ fail(
+ "failed AC Version test for id " + id);
+ }
+
+ // Holder
+ Holder h = acInfo.getHolder();
+ if (h == null)
+ {
+ fail(
+ "failed AC Holder test, it's null, for id " + id);
+ }
+
+ // Issuer
+ AttCertIssuer aci = acInfo.getIssuer();
+ if (aci == null)
+ {
+ fail(
+ "failed AC Issuer test, it's null, for id " + id);
+ }
+
+ // Signature
+ AlgorithmIdentifier sig = acInfo.getSignature();
+ if (sig == null)
+ {
+ fail(
+ "failed AC Signature test for id " + id);
+ }
+
+ // Serial
+ ASN1Integer serial = acInfo.getSerialNumber();
+
+ // Validity
+ AttCertValidityPeriod validity = acInfo.getAttrCertValidityPeriod();
+ if (validity == null)
+ {
+ fail("failed AC AttCertValidityPeriod test for id " + id);
+ }
+
+ // Attributes
+ ASN1Sequence attribSeq = acInfo.getAttributes();
+ Attribute att[] = new Attribute[attribSeq.size()];
+ for (int i = 0; i < attribSeq.size(); i++)
+ {
+ att[i] = Attribute.getInstance(attribSeq.getObjectAt(i));
+ }
+
+ // IssuerUniqueId
+ // TODO, how to best test?
+
+ // X509 Extensions
+ Extensions ext = acInfo.getExtensions();
+ if (ext != null)
+ {
+ Enumeration en = ext.oids();
+ while (en.hasMoreElements())
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier) en
+ .nextElement();
+ Extension extVal = ext.getExtension(oid);
+ }
+ }
+ }
+
+ public void checkV1AttributeCertificate(
+ int id,
+ byte[] cert)
+ throws Exception
+ {
+ ByteArrayInputStream bIn;
+ ASN1InputStream aIn;
+
+ bIn = new ByteArrayInputStream(cert);
+ aIn = new ASN1InputStream(bIn);
+
+ ASN1Sequence seq = (ASN1Sequence) aIn.readObject();
+ //String dump = ASN1Dump.dumpAsString(seq);
+
+ AttributeCertificate obj = AttributeCertificate.getInstance(seq);
+ AttributeCertificateInfo acInfo = obj.getAcinfo();
+
+ // Version
+ if (!(acInfo.getVersion().equals(new ASN1Integer(0))))
+ {
+ fail(
+ "failed AC Version test for id " + id);
+ }
+
+ // Holder
+ Holder h = acInfo.getHolder();
+ if (h == null)
+ {
+ fail(
+ "failed AC Holder test, it's null, for id " + id);
+ }
+
+ // Issuer
+ AttCertIssuer aci = acInfo.getIssuer();
+ if (aci == null)
+ {
+ fail(
+ "failed AC Issuer test, it's null, for id " + id);
+ }
+
+ // Signature
+ AlgorithmIdentifier sig = acInfo.getSignature();
+ if (sig == null)
+ {
+ fail(
+ "failed AC Signature test for id " + id);
+ }
+
+ // Serial
+ ASN1Integer serial = acInfo.getSerialNumber();
+
+ // Validity
+ AttCertValidityPeriod validity = acInfo.getAttrCertValidityPeriod();
+ if (validity == null)
+ {
+ fail("failed AC AttCertValidityPeriod test for id " + id);
+ }
+
+ // Attributes
+ ASN1Sequence attribSeq = acInfo.getAttributes();
+ Attribute att[] = new Attribute[attribSeq.size()];
+ for (int i = 0; i < attribSeq.size(); i++)
+ {
+ att[i] = Attribute.getInstance(attribSeq.getObjectAt(i));
+ }
+
+ // IssuerUniqueId
+ // TODO, how to best test?
+
+ // X509 Extensions
+ Extensions ext = acInfo.getExtensions();
+ if (ext != null)
+ {
+ Enumeration en = ext.oids();
+ while (en.hasMoreElements())
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier) en
+ .nextElement();
+ Extension extVal = ext.getExtension(oid);
+ }
+ }
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ checkCertificate(1, cert1);
+ checkCertificate(2, cert2);
+ checkCertificate(3, cert3);
+ checkCertificate(4, cert4);
+ checkCertificate(5, cert5);
+ checkCertificate(6, cert6);
+ checkCertificate(7, cert7);
+ checkAttributeCertificate(8,cert8);
+ checkV1AttributeCertificate(9, attrCertv1);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new CertificateTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/CommitmentTypeIndicationUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/CommitmentTypeIndicationUnitTest.java
new file mode 100644
index 00000000..321e1f72
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/CommitmentTypeIndicationUnitTest.java
@@ -0,0 +1,103 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.esf.CommitmentTypeIdentifier;
+import org.spongycastle.asn1.esf.CommitmentTypeIndication;
+import org.spongycastle.util.test.SimpleTest;
+
+public class CommitmentTypeIndicationUnitTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "CommitmentTypeIndication";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ CommitmentTypeIndication cti = new CommitmentTypeIndication(CommitmentTypeIdentifier.proofOfOrigin);
+
+ checkConstruction(cti, CommitmentTypeIdentifier.proofOfOrigin, null);
+
+ ASN1Sequence qualifier = new DERSequence(new ASN1ObjectIdentifier("1.2"));
+
+ cti = new CommitmentTypeIndication(CommitmentTypeIdentifier.proofOfOrigin, qualifier);
+
+ checkConstruction(cti, CommitmentTypeIdentifier.proofOfOrigin, qualifier);
+
+ cti = CommitmentTypeIndication.getInstance(null);
+
+ if (cti != null)
+ {
+ fail("null getInstance() failed.");
+ }
+
+ try
+ {
+ CommitmentTypeIndication.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ CommitmentTypeIndication mv,
+ ASN1ObjectIdentifier commitmenttTypeId,
+ ASN1Encodable qualifier)
+ throws IOException
+ {
+ checkStatement(mv, commitmenttTypeId, qualifier);
+
+ mv = CommitmentTypeIndication.getInstance(mv);
+
+ checkStatement(mv, commitmenttTypeId, qualifier);
+
+ ASN1InputStream aIn = new ASN1InputStream(mv.toASN1Object().getEncoded());
+
+ ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
+
+ mv = CommitmentTypeIndication.getInstance(seq);
+
+ checkStatement(mv, commitmenttTypeId, qualifier);
+ }
+
+ private void checkStatement(
+ CommitmentTypeIndication cti,
+ ASN1ObjectIdentifier commitmentTypeId,
+ ASN1Encodable qualifier)
+ {
+ if (!cti.getCommitmentTypeId().equals(commitmentTypeId))
+ {
+ fail("commitmentTypeIds don't match.");
+ }
+
+ if (qualifier != null)
+ {
+ if (!cti.getCommitmentTypeQualifier().equals(qualifier))
+ {
+ fail("qualifiers don't match.");
+ }
+ }
+ else if (cti.getCommitmentTypeQualifier() != null)
+ {
+ fail("qualifier found when none expected.");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new CommitmentTypeIndicationUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/CommitmentTypeQualifierUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/CommitmentTypeQualifierUnitTest.java
new file mode 100644
index 00000000..9e3a0abf
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/CommitmentTypeQualifierUnitTest.java
@@ -0,0 +1,102 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.esf.CommitmentTypeIdentifier;
+import org.spongycastle.asn1.esf.CommitmentTypeQualifier;
+import org.spongycastle.util.test.SimpleTest;
+
+public class CommitmentTypeQualifierUnitTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "CommitmentTypeQualifier";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ CommitmentTypeQualifier ctq = new CommitmentTypeQualifier(CommitmentTypeIdentifier.proofOfOrigin);
+
+ checkConstruction(ctq, CommitmentTypeIdentifier.proofOfOrigin, null);
+
+ ASN1Encodable info = new ASN1ObjectIdentifier("1.2");
+
+ ctq = new CommitmentTypeQualifier(CommitmentTypeIdentifier.proofOfOrigin, info);
+
+ checkConstruction(ctq, CommitmentTypeIdentifier.proofOfOrigin, info);
+
+ ctq = CommitmentTypeQualifier.getInstance(null);
+
+ if (ctq != null)
+ {
+ fail("null getInstance() failed.");
+ }
+
+ try
+ {
+ CommitmentTypeQualifier.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ CommitmentTypeQualifier mv,
+ ASN1ObjectIdentifier commitmenttTypeId,
+ ASN1Encodable qualifier)
+ throws IOException
+ {
+ checkStatement(mv, commitmenttTypeId, qualifier);
+
+ mv = CommitmentTypeQualifier.getInstance(mv);
+
+ checkStatement(mv, commitmenttTypeId, qualifier);
+
+ ASN1InputStream aIn = new ASN1InputStream(mv.toASN1Object().getEncoded());
+
+ ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
+
+ mv = CommitmentTypeQualifier.getInstance(seq);
+
+ checkStatement(mv, commitmenttTypeId, qualifier);
+ }
+
+ private void checkStatement(
+ CommitmentTypeQualifier ctq,
+ ASN1ObjectIdentifier commitmentTypeId,
+ ASN1Encodable qualifier)
+ {
+ if (!ctq.getCommitmentTypeIdentifier().equals(commitmentTypeId))
+ {
+ fail("commitmentTypeIds don't match.");
+ }
+
+ if (qualifier != null)
+ {
+ if (!ctq.getQualifier().equals(qualifier))
+ {
+ fail("qualifiers don't match.");
+ }
+ }
+ else if (ctq.getQualifier() != null)
+ {
+ fail("qualifier found when none expected.");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new CommitmentTypeQualifierUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/ContentHintsUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/ContentHintsUnitTest.java
new file mode 100644
index 00000000..b0610f64
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/ContentHintsUnitTest.java
@@ -0,0 +1,87 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERUTF8String;
+import org.spongycastle.asn1.ess.ContentHints;
+
+public class ContentHintsUnitTest
+ extends ASN1UnitTest
+{
+ public String getName()
+ {
+ return "ContentHints";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ DERUTF8String contentDescription = new DERUTF8String("Description");
+ ASN1ObjectIdentifier contentType = new ASN1ObjectIdentifier("1.2.2.3");
+
+ ContentHints hints = new ContentHints(contentType);
+
+ checkConstruction(hints, contentType, null);
+
+ hints = new ContentHints(contentType, contentDescription);
+
+ checkConstruction(hints, contentType, contentDescription);
+
+ hints = ContentHints.getInstance(null);
+
+ if (hints != null)
+ {
+ fail("null getInstance() failed.");
+ }
+
+ try
+ {
+ ContentHints.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ ContentHints hints,
+ ASN1ObjectIdentifier contentType,
+ DERUTF8String description)
+ throws IOException
+ {
+ checkValues(hints, contentType, description);
+
+ hints = ContentHints.getInstance(hints);
+
+ checkValues(hints, contentType, description);
+
+ ASN1InputStream aIn = new ASN1InputStream(hints.toASN1Primitive().getEncoded());
+
+ ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
+
+ hints = ContentHints.getInstance(seq);
+
+ checkValues(hints, contentType, description);
+ }
+
+ private void checkValues(
+ ContentHints hints,
+ ASN1ObjectIdentifier contentType,
+ DERUTF8String description)
+ {
+ checkMandatoryField("contentType", contentType, hints.getContentType());
+ checkOptionalField("description", description, hints.getContentDescription());
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new ContentHintsUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/CscaMasterListTest.java b/core/src/test/java/org/spongycastle/asn1/test/CscaMasterListTest.java
new file mode 100644
index 00000000..30c82cdf
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/CscaMasterListTest.java
@@ -0,0 +1,49 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.icao.CscaMasterList;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.io.Streams;
+import org.spongycastle.util.test.SimpleTest;
+
+public class CscaMasterListTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "CscaMasterList";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ byte[] input = getInput("masterlist-content.data");
+ CscaMasterList parsedList
+ = CscaMasterList.getInstance(ASN1Primitive.fromByteArray(input));
+
+ if (parsedList.getCertStructs().length != 3)
+ {
+ fail("Cert structure parsing failed: incorrect length");
+ }
+
+ byte[] output = parsedList.getEncoded();
+ if (!Arrays.areEqual(input, output))
+ {
+ fail("Encoding failed after parse");
+ }
+ }
+
+ private byte[] getInput(String name)
+ throws IOException
+ {
+ return Streams.readAll(getClass().getResourceAsStream(name));
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new CscaMasterListTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/DERApplicationSpecificTest.java b/core/src/test/java/org/spongycastle/asn1/test/DERApplicationSpecificTest.java
new file mode 100644
index 00000000..f17179ee
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/DERApplicationSpecificTest.java
@@ -0,0 +1,77 @@
+package org.spongycastle.asn1.test;
+
+import org.spongycastle.asn1.ASN1Encoding;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.BERTags;
+import org.spongycastle.asn1.DERApplicationSpecific;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class DERApplicationSpecificTest
+ extends SimpleTest
+{
+ private static final byte[] impData = Hex.decode("430109");
+
+ private static final byte[] certData = Hex.decode(
+ "7F218201897F4E8201495F290100420E44454356434145504153533030317F49"
+ + "81FD060A04007F00070202020202811CD7C134AA264366862A18302575D1D787"
+ + "B09F075797DA89F57EC8C0FF821C68A5E62CA9CE6C1C299803A6C1530B514E18"
+ + "2AD8B0042A59CAD29F43831C2580F63CCFE44138870713B1A92369E33E2135D2"
+ + "66DBB372386C400B8439040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C"
+ + "1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D376"
+ + "1402CD851CD7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A793"
+ + "9F863904393EE8E06DB6C7F528F8B4260B49AA93309824D92CDB1807E5437EE2"
+ + "E26E29B73A7111530FA86B350037CB9415E153704394463797139E148701015F"
+ + "200E44454356434145504153533030317F4C0E060904007F0007030102015301"
+ + "C15F25060007000400015F24060009000400015F37384CCF25C59F3612EEE188"
+ + "75F6C5F2E2D21F0395683B532A26E4C189B71EFE659C3F26E0EB9AEAE9986310"
+ + "7F9B0DADA16414FFA204516AEE2B");
+
+ public String getName()
+ {
+ return "DERApplicationSpecific";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ ASN1Integer value = new ASN1Integer(9);
+
+ DERApplicationSpecific tagged = new DERApplicationSpecific(false, 3, value);
+
+ if (!areEqual(impData, tagged.getEncoded()))
+ {
+ fail("implicit encoding failed");
+ }
+
+ ASN1Integer recVal = (ASN1Integer)tagged.getObject(BERTags.INTEGER);
+
+ if (!value.equals(recVal))
+ {
+ fail("implicit read back failed");
+ }
+
+ DERApplicationSpecific certObj = (DERApplicationSpecific)
+ ASN1Primitive.fromByteArray(certData);
+
+ if (!certObj.isConstructed() || certObj.getApplicationTag() != 33)
+ {
+ fail("parsing of certificate data failed");
+ }
+
+ byte[] encoded = certObj.getEncoded(ASN1Encoding.DER);
+
+ if (!Arrays.areEqual(certData, encoded))
+ {
+ fail("re-encoding of certificate data failed");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new DERApplicationSpecificTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/DERUTF8StringTest.java b/core/src/test/java/org/spongycastle/asn1/test/DERUTF8StringTest.java
new file mode 100644
index 00000000..bd284b66
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/DERUTF8StringTest.java
@@ -0,0 +1,101 @@
+package org.spongycastle.asn1.test;
+
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERUTF8String;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Strings;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+public class DERUTF8StringTest
+ implements Test
+{
+
+ /**
+ * Unicode code point U+10400 coded as surrogate in two native Java UTF-16
+ * code units
+ */
+ private final static char[] glyph1_utf16 = { 0xd801, 0xdc00 };
+
+ /**
+ * U+10400 coded in UTF-8
+ */
+ private final static byte[] glyph1_utf8 = { (byte)0xF0, (byte)0x90, (byte)0x90, (byte)0x80 };
+
+ /**
+ * Unicode code point U+6771 in native Java UTF-16
+ */
+ private final static char[] glyph2_utf16 = { 0x6771 };
+
+ /**
+ * U+6771 coded in UTF-8
+ */
+ private final static byte[] glyph2_utf8 = { (byte)0xE6, (byte)0x9D, (byte)0xB1 };
+
+ /**
+ * Unicode code point U+00DF in native Java UTF-16
+ */
+ private final static char[] glyph3_utf16 = { 0x00DF };
+
+ /**
+ * U+00DF coded in UTF-8
+ */
+ private final static byte[] glyph3_utf8 = { (byte)0xC3, (byte)0x9f };
+
+ /**
+ * Unicode code point U+0041 in native Java UTF-16
+ */
+ private final static char[] glyph4_utf16 = { 0x0041 };
+
+ /**
+ * U+0041 coded in UTF-8
+ */
+ private final static byte[] glyph4_utf8 = { 0x41 };
+
+ private final static byte[][] glyphs_utf8 = { glyph1_utf8, glyph2_utf8, glyph3_utf8, glyph4_utf8 };
+
+ private final static char[][] glyphs_utf16 = { glyph1_utf16, glyph2_utf16, glyph3_utf16, glyph4_utf16 };
+
+ public TestResult perform()
+ {
+ try
+ {
+ for (int i = 0; i < glyphs_utf16.length; i++)
+ {
+ String s = new String(glyphs_utf16[i]);
+ byte[] b1 = new DERUTF8String(s).getEncoded();
+ byte temp[] = new byte[b1.length - 2];
+ System.arraycopy(b1, 2, temp, 0, b1.length - 2);
+ byte[] b2 = new DERUTF8String(Strings.fromUTF8ByteArray(new DEROctetString(temp).getOctets())).getEncoded();
+ if (!Arrays.areEqual(b1, b2))
+ {
+ return new SimpleTestResult(false, getName() + ": failed UTF-8 encoding and decoding");
+ }
+ if (!Arrays.areEqual(temp, glyphs_utf8[i]))
+ {
+ return new SimpleTestResult(false, getName() + ": failed UTF-8 encoding and decoding");
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ return new SimpleTestResult(false, getName() + ": failed with Exception " + e.getMessage());
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+
+ public String getName()
+ {
+ return "DERUTF8String";
+ }
+
+ public static void main(String[] args)
+ {
+ DERUTF8StringTest test = new DERUTF8StringTest();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/DataGroupHashUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/DataGroupHashUnitTest.java
new file mode 100644
index 00000000..86d0c4c8
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/DataGroupHashUnitTest.java
@@ -0,0 +1,106 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+import java.util.Random;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.icao.DataGroupHash;
+import org.spongycastle.util.test.SimpleTest;
+
+public class DataGroupHashUnitTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "DataGroupHash";
+ }
+
+ private byte[] generateHash()
+ {
+ Random rand = new Random();
+ byte[] bytes = new byte[20];
+
+ for (int i = 0; i != bytes.length; i++)
+ {
+ bytes[i] = (byte)rand.nextInt();
+ }
+
+ return bytes;
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ int dataGroupNumber = 1;
+ ASN1OctetString dataHash = new DEROctetString(generateHash());
+ DataGroupHash dg = new DataGroupHash(dataGroupNumber, dataHash);
+
+ checkConstruction(dg, dataGroupNumber, dataHash);
+
+ try
+ {
+ DataGroupHash.getInstance(null);
+ }
+ catch (Exception e)
+ {
+ fail("getInstance() failed to handle null.");
+ }
+
+ try
+ {
+ DataGroupHash.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ DataGroupHash dg,
+ int dataGroupNumber,
+ ASN1OctetString dataGroupHashValue)
+ throws IOException
+ {
+ checkValues(dg, dataGroupNumber, dataGroupHashValue);
+
+ dg = DataGroupHash.getInstance(dg);
+
+ checkValues(dg, dataGroupNumber, dataGroupHashValue);
+
+ ASN1InputStream aIn = new ASN1InputStream(dg.toASN1Object().getEncoded());
+
+ ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
+
+ dg = DataGroupHash.getInstance(seq);
+
+ checkValues(dg, dataGroupNumber, dataGroupHashValue);
+ }
+
+ private void checkValues(
+ DataGroupHash dg,
+ int dataGroupNumber,
+ ASN1OctetString dataGroupHashValue)
+ {
+ if (dg.getDataGroupNumber() != dataGroupNumber)
+ {
+ fail("group number don't match.");
+ }
+
+ if (!dg.getDataGroupHashValue().equals(dataGroupHashValue))
+ {
+ fail("hash value don't match.");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new DataGroupHashUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/DeclarationOfMajorityUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/DeclarationOfMajorityUnitTest.java
new file mode 100644
index 00000000..ec0d3974
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/DeclarationOfMajorityUnitTest.java
@@ -0,0 +1,90 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.isismtt.x509.DeclarationOfMajority;
+
+public class DeclarationOfMajorityUnitTest
+ extends ASN1UnitTest
+{
+ public String getName()
+ {
+ return "DeclarationOfMajority";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ ASN1GeneralizedTime dateOfBirth = new ASN1GeneralizedTime("20070315173729Z");
+ DeclarationOfMajority decl = new DeclarationOfMajority(dateOfBirth);
+
+ checkConstruction(decl, DeclarationOfMajority.dateOfBirth, dateOfBirth, -1);
+
+ decl = new DeclarationOfMajority(6);
+
+ checkConstruction(decl, DeclarationOfMajority.notYoungerThan, null, 6);
+
+ decl = DeclarationOfMajority.getInstance(null);
+
+ if (decl != null)
+ {
+ fail("null getInstance() failed.");
+ }
+
+ try
+ {
+ DeclarationOfMajority.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ DeclarationOfMajority decl,
+ int type,
+ ASN1GeneralizedTime dateOfBirth,
+ int notYoungerThan)
+ throws IOException
+ {
+ checkValues(decl, type, dateOfBirth, notYoungerThan);
+
+ decl = DeclarationOfMajority.getInstance(decl);
+
+ checkValues(decl, type, dateOfBirth, notYoungerThan);
+
+ ASN1InputStream aIn = new ASN1InputStream(decl.toASN1Object().getEncoded());
+
+ DERTaggedObject info = (DERTaggedObject)aIn.readObject();
+
+ decl = DeclarationOfMajority.getInstance(info);
+
+ checkValues(decl, type, dateOfBirth, notYoungerThan);
+ }
+
+ private void checkValues(
+ DeclarationOfMajority decl,
+ int type,
+ ASN1GeneralizedTime dateOfBirth,
+ int notYoungerThan)
+ {
+ checkMandatoryField("type", type, decl.getType());
+ checkOptionalField("dateOfBirth", dateOfBirth, decl.getDateOfBirth());
+ if (notYoungerThan != -1 && notYoungerThan != decl.notYoungerThan())
+ {
+ fail("notYoungerThan mismatch");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new DeclarationOfMajorityUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/ESSCertIDv2UnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/ESSCertIDv2UnitTest.java
new file mode 100644
index 00000000..a9f6e344
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/ESSCertIDv2UnitTest.java
@@ -0,0 +1,33 @@
+package org.spongycastle.asn1.test;
+
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ess.ESSCertIDv2;
+import org.spongycastle.asn1.nist.NISTObjectIdentifiers;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+public class ESSCertIDv2UnitTest
+ extends ASN1UnitTest
+{
+ public String getName()
+ {
+ return "ESSCertIDv2";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ // check getInstance on default algorithm.
+ byte[] digest = new byte [256];
+ ESSCertIDv2 essCertIdv2 = new ESSCertIDv2(new AlgorithmIdentifier(
+ NISTObjectIdentifiers.id_sha256), digest);
+ ASN1Primitive asn1Object = essCertIdv2.toASN1Primitive();
+
+ ESSCertIDv2.getInstance(asn1Object);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new ESSCertIDv2UnitTest());
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/asn1/test/EncryptedPrivateKeyInfoTest.java b/core/src/test/java/org/spongycastle/asn1/test/EncryptedPrivateKeyInfoTest.java
new file mode 100644
index 00000000..a02a166e
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/EncryptedPrivateKeyInfoTest.java
@@ -0,0 +1,135 @@
+package org.spongycastle.asn1.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DEROutputStream;
+import org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo;
+import org.spongycastle.asn1.util.ASN1Dump;
+import org.spongycastle.util.encoders.Base64;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * Test the reading and writing of EncryptedPrivateKeyInfo objects using
+ * the test vectors provided at
+ * <a href=http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html>
+ * RSA's PKCS5 Page</a>.
+ * <br>
+ * The vectors are Base 64 encoded and encrypted using the password "password"
+ * (without quotes). They should all yield the same PrivateKeyInfo object.
+ */
+public class EncryptedPrivateKeyInfoTest
+ extends SimpleTest
+{
+ static byte[] sample1 = Base64.decode(
+ "MIIBozA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQIfWBDXwLp4K4CAggA"
+ + "MBEGBSsOAwIHBAiaCF/AvOgQ6QSCAWDWX4BdAzCRNSQSANSuNsT5X8mWYO27mr3Y"
+ + "9c9LoBVXGNmYWKA77MI4967f7SmjNcgXj3xNE/jmnVz6hhsjS8E5VPT3kfyVkpdZ"
+ + "0lr5e9Yk2m3JWpPU7++v5zBkZmC4V/MwV/XuIs6U+vykgzMgpxQg0oZKS9zgmiZo"
+ + "f/4dOCL0UtCDnyOSvqT7mCVIcMDIEKu8QbVlgZYBop08l60EuEU3gARUo8WsYQmO"
+ + "Dz/ldx0Z+znIT0SXVuOwc+RVItC5T/Qx+aijmmpt+9l14nmaGBrEkmuhmtdvU/4v"
+ + "aptewGRgmjOfD6cqK+zs0O5NrrJ3P/6ZSxXj91CQgrThGfOv72bUncXEMNtc8pks"
+ + "2jpHFjGMdKufnadAD7XuMgzkkaklEXZ4f5tU6heIIwr51g0GBEGF96gYPFnjnSQM"
+ + "75JE02Clo+DfcfXpcybPTwwFg2jd6JTTOfkdf6OdSlA/1XNK43FA");
+
+ static byte[] sample2 = Base64.decode(
+ "MIIBpjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIeFeOWl1jywYCAggA"
+ + "MBQGCCqGSIb3DQMHBAjUJ5eGBhQGtQSCAWBrHrRgqO8UUMLcWzZEtpk1l3mjxiF/"
+ + "koCMkHsFwowgyWhEbgIkTgbSViK54LVK8PskekcGNLph+rB6bGZ7pPbL5pbXASJ8"
+ + "+MkQcG3FZdlS4Ek9tTJDApj3O1UubZGFG4uvTlJJFbF1BOJ3MkY3XQ9Gl1qwv7j5"
+ + "6e103Da7Cq9+oIDKmznza78XXQYrUsPo8mJGjUxPskEYlzwvHjKubRnYm/K6RKhi"
+ + "5f4zX4BQ/Dt3H812ZjRXrsjAJP0KrD/jyD/jCT7zNBVPH1izBds+RwizyQAHwfNJ"
+ + "BFR78TH4cgzB619X47FDVOnT0LqQNVd0O3cSwnPrXE9XR3tPayE+iOB15llFSmi8"
+ + "z0ByOXldEpkezCn92Umk++suzIVj1qfsK+bv2phZWJPbLEIWPDRHUbYf76q5ArAr"
+ + "u4xtxT/hoK3krEs/IN3d70qjlUJ36SEw1UaZ82PWhakQbdtu39ZraMJB");
+
+ static byte[] sample3 = Base64.decode(
+ "MIIBrjBIBgkqhkiG9w0BBQ0wOzAeBgkqhkiG9w0BBQwwEQQIrHyQPBZqWLUCAggA"
+ + "AgEQMBkGCCqGSIb3DQMCMA0CAToECEhbh7YZKiPSBIIBYCT1zp6o5jpFlIkgwPop"
+ + "7bW1+8ACr4exqzkeb3WflQ8cWJ4cURxzVdvxUnXeW1VJdaQZtjS/QHs5GhPTG/0f"
+ + "wtvnaPfwrIJ3FeGaZfcg2CrYhalOFmEb4xrE4KyoEQmUN8tb/Cg94uzd16BOPw21"
+ + "RDnE8bnPdIGY7TyL95kbkqH23mK53pi7h+xWIgduW+atIqDyyt55f7WMZcvDvlj6"
+ + "VpN/V0h+qxBHL274WA4dj6GYgeyUFpi60HdGCK7By2TBy8h1ZvKGjmB9h8jZvkx1"
+ + "MkbRumXxyFsowTZawyYvO8Um6lbfEDP9zIEUq0IV8RqH2MRyblsPNSikyYhxX/cz"
+ + "tdDxRKhilySbSBg5Kr8OfcwKp9bpinN96nmG4xr3Tch1bnVvqJzOQ5+Vva2WwVvH"
+ + "2JkWvYm5WaANg4Q6bRxu9vz7DuhbJjQdZbxFezIAgrJdSe92B00jO/0Kny1WjiVO"
+ + "6DA=");
+
+ public String getName()
+ {
+ return "EncryptedPrivateKeyInfoTest";
+ }
+
+ private void test(
+ int id,
+ byte[] sample)
+ {
+ ByteArrayInputStream bIn = new ByteArrayInputStream(sample);
+ ASN1InputStream aIn = new ASN1InputStream(bIn);
+ EncryptedPrivateKeyInfo info = null;
+
+ try
+ {
+ info = EncryptedPrivateKeyInfo.getInstance(aIn.readObject());
+ }
+ catch (Exception e)
+ {
+ fail("test " + id + " failed construction - exception " + e.toString(), e);
+ }
+
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ DEROutputStream dOut = new DEROutputStream(bOut);
+
+ try
+ {
+ dOut.writeObject(info);
+ }
+ catch (Exception e)
+ {
+ fail("test " + id + " failed writing - exception " + e.toString(), e);
+ }
+
+ byte[] bytes = bOut.toByteArray();
+
+ if (bytes.length != sample.length)
+ {
+ try
+ {
+ bIn = new ByteArrayInputStream(bytes);
+ aIn = new ASN1InputStream(bIn);
+
+ ASN1Primitive obj = aIn.readObject();
+
+ fail("test " + id + " length mismatch - expected " + sample.length + System.getProperty("line.separator") + ASN1Dump.dumpAsString(info) + " got " + bytes.length + System.getProperty("line.separator") + ASN1Dump.dumpAsString(obj));
+ }
+ catch (Exception e)
+ {
+ fail("test " + id + " length mismatch - exception " + e.toString());
+ }
+ }
+
+ for (int i = 0; i != bytes.length; i++)
+ {
+ if (bytes[i] != sample[i])
+ {
+ fail("test " + id + " data mismatch");
+ }
+ }
+ }
+
+ public void performTest()
+ {
+ test(0, sample1);
+ test(1, sample2);
+ test(2, sample3);
+ }
+
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new EncryptedPrivateKeyInfoTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/EnumeratedTest.java b/core/src/test/java/org/spongycastle/asn1/test/EnumeratedTest.java
new file mode 100644
index 00000000..90391ef5
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/EnumeratedTest.java
@@ -0,0 +1,115 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import junit.framework.TestCase;
+
+import org.spongycastle.asn1.ASN1Boolean;
+import org.spongycastle.asn1.ASN1Enumerated;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.util.encoders.Hex;
+
+/**
+ * Tests used to verify correct decoding of the ENUMERATED type.
+ */
+public class EnumeratedTest
+ extends TestCase
+{
+ /**
+ * Test vector used to test decoding of multiple items. This sample uses an ENUMERATED and a BOOLEAN.
+ */
+ private static final byte[] MultipleSingleByteItems = Hex.decode("30060a01010101ff");
+
+ /**
+ * Test vector used to test decoding of multiple items. This sample uses two ENUMERATEDs.
+ */
+ private static final byte[] MultipleDoubleByteItems = Hex.decode("30080a0201010a020202");
+
+ /**
+ * Test vector used to test decoding of multiple items. This sample uses an ENUMERATED and an OBJECT IDENTIFIER.
+ */
+ private static final byte[] MultipleTripleByteItems = Hex.decode("300a0a0301010106032b0601");
+
+ /**
+ * Makes sure multiple identically sized values are parsed correctly.
+ */
+ public void testReadingMultipleSingleByteItems()
+ throws IOException
+ {
+ ASN1Primitive obj = ASN1Primitive.fromByteArray(MultipleSingleByteItems);
+
+ assertTrue("Null ASN.1 SEQUENCE", obj instanceof ASN1Sequence);
+
+ ASN1Sequence sequence = (ASN1Sequence)obj;
+
+ assertEquals("2 items expected", 2, sequence.size());
+
+ ASN1Enumerated enumerated = ASN1Enumerated.getInstance(sequence.getObjectAt(0));
+
+ assertNotNull("ENUMERATED expected", enumerated);
+
+ assertEquals("Unexpected ENUMERATED value", 1, enumerated.getValue().intValue());
+
+ ASN1Boolean b = ASN1Boolean.getInstance(sequence.getObjectAt(1));
+
+ assertNotNull("BOOLEAN expected", b);
+
+ assertTrue("Unexpected BOOLEAN value", b.isTrue());
+ }
+
+ /**
+ * Makes sure multiple identically sized values are parsed correctly.
+ */
+ public void testReadingMultipleDoubleByteItems()
+ throws IOException
+ {
+ ASN1Primitive obj = ASN1Primitive.fromByteArray(MultipleDoubleByteItems);
+
+ assertTrue("Null ASN.1 SEQUENCE", obj instanceof ASN1Sequence);
+
+ ASN1Sequence sequence = (ASN1Sequence)obj;
+
+ assertEquals("2 items expected", 2, sequence.size());
+
+ ASN1Enumerated enumerated1 = ASN1Enumerated.getInstance(sequence.getObjectAt(0));
+
+ assertNotNull("ENUMERATED expected", enumerated1);
+
+ assertEquals("Unexpected ENUMERATED value", 257, enumerated1.getValue().intValue());
+
+ ASN1Enumerated enumerated2 = ASN1Enumerated.getInstance(sequence.getObjectAt(1));
+
+ assertNotNull("ENUMERATED expected", enumerated2);
+
+ assertEquals("Unexpected ENUMERATED value", 514, enumerated2.getValue().intValue());
+ }
+
+ /**
+ * Makes sure multiple identically sized values are parsed correctly.
+ */
+ public void testReadingMultipleTripleByteItems()
+ throws IOException
+ {
+ ASN1Primitive obj = ASN1Primitive.fromByteArray(MultipleTripleByteItems);
+
+ assertTrue("Null ASN.1 SEQUENCE", obj instanceof ASN1Sequence);
+
+ ASN1Sequence sequence = (ASN1Sequence)obj;
+
+ assertEquals("2 items expected", 2, sequence.size());
+
+ ASN1Enumerated enumerated = ASN1Enumerated.getInstance(sequence.getObjectAt(0));
+
+ assertNotNull("ENUMERATED expected", enumerated);
+
+ assertEquals("Unexpected ENUMERATED value", 65793, enumerated.getValue().intValue());
+
+ ASN1ObjectIdentifier objectId = ASN1ObjectIdentifier.getInstance(sequence.getObjectAt(1));
+
+ assertNotNull("OBJECT IDENTIFIER expected", objectId);
+
+ assertEquals("Unexpected OBJECT IDENTIFIER value", "1.3.6.1", objectId.getId());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/EqualsAndHashCodeTest.java b/core/src/test/java/org/spongycastle/asn1/test/EqualsAndHashCodeTest.java
new file mode 100644
index 00000000..1993d016
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/EqualsAndHashCodeTest.java
@@ -0,0 +1,127 @@
+package org.spongycastle.asn1.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.Date;
+
+import org.spongycastle.asn1.ASN1Boolean;
+import org.spongycastle.asn1.ASN1Enumerated;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OutputStream;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.BERConstructedOctetString;
+import org.spongycastle.asn1.BERSequence;
+import org.spongycastle.asn1.BERSet;
+import org.spongycastle.asn1.BERTaggedObject;
+import org.spongycastle.asn1.DERApplicationSpecific;
+import org.spongycastle.asn1.DERBMPString;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERGeneralString;
+import org.spongycastle.asn1.DERGeneralizedTime;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.DERNull;
+import org.spongycastle.asn1.DERNumericString;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERPrintableString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERSet;
+import org.spongycastle.asn1.DERT61String;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.DERUTCTime;
+import org.spongycastle.asn1.DERUTF8String;
+import org.spongycastle.asn1.DERUniversalString;
+import org.spongycastle.asn1.DERVisibleString;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+public class EqualsAndHashCodeTest
+ implements Test
+{
+ public TestResult perform()
+ {
+ byte[] data = { 0, 1, 0, 1, 0, 0, 1 };
+
+ ASN1Primitive values[] = {
+ new BERConstructedOctetString(data),
+ new BERSequence(new DERPrintableString("hello world")),
+ new BERSet(new DERPrintableString("hello world")),
+ new BERTaggedObject(0, new DERPrintableString("hello world")),
+ new DERApplicationSpecific(0, data),
+ new DERBitString(data),
+ new DERBMPString("hello world"),
+ new ASN1Boolean(true),
+ new ASN1Boolean(false),
+ new ASN1Enumerated(100),
+ new DERGeneralizedTime("20070315173729Z"),
+ new DERGeneralString("hello world"),
+ new DERIA5String("hello"),
+ new ASN1Integer(1000),
+ new DERNull(),
+ new DERNumericString("123456"),
+ new ASN1ObjectIdentifier("1.1.1.10000.1"),
+ new DEROctetString(data),
+ new DERPrintableString("hello world"),
+ new DERSequence(new DERPrintableString("hello world")),
+ new DERSet(new DERPrintableString("hello world")),
+ new DERT61String("hello world"),
+ new DERTaggedObject(0, new DERPrintableString("hello world")),
+ new DERUniversalString(data),
+ new DERUTCTime(new Date()),
+ new DERUTF8String("hello world"),
+ new DERVisibleString("hello world")
+ };
+
+ try
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ for (int i = 0; i != values.length; i++)
+ {
+ aOut.writeObject(values[i]);
+ }
+
+ ASN1Primitive[] readValues = new ASN1Primitive[values.length];
+
+ ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
+ ASN1InputStream aIn = new ASN1InputStream(bIn);
+
+ for (int i = 0; i != values.length; i++)
+ {
+ ASN1Primitive o = aIn.readObject();
+ if (!o.equals(values[i]))
+ {
+ return new SimpleTestResult(false, getName() + ": Failed equality test for " + o.getClass());
+ }
+
+ if (o.hashCode() != values[i].hashCode())
+ {
+ return new SimpleTestResult(false, getName() + ": Failed hashCode test for " + o.getClass());
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ return new SimpleTestResult(false, getName() + ": Failed - exception " + e.toString(), e);
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+
+ public String getName()
+ {
+ return "EqualsAndHashCode";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ EqualsAndHashCodeTest test = new EqualsAndHashCodeTest();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/GeneralNameTest.java b/core/src/test/java/org/spongycastle/asn1/test/GeneralNameTest.java
new file mode 100644
index 00000000..dcc2e8b7
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/GeneralNameTest.java
@@ -0,0 +1,143 @@
+package org.spongycastle.asn1.test;
+
+import org.spongycastle.asn1.x509.GeneralName;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class GeneralNameTest
+ extends SimpleTest
+{
+ private static final byte[] ipv4 = Hex.decode("87040a090800");
+ private static final byte[] ipv4WithMask1 = Hex.decode("87080a090800ffffff00");
+ private static final byte[] ipv4WithMask2 = Hex.decode("87080a090800ffff8000");
+ private static final byte[] ipv4WithMask3 = Hex.decode("87080a090800ffffc000");
+
+ private static final byte[] ipv6a = Hex.decode("871020010db885a308d313198a2e03707334");
+ private static final byte[] ipv6b = Hex.decode("871020010db885a3000013198a2e03707334");
+ private static final byte[] ipv6c = Hex.decode("871000000000000000000000000000000001");
+ private static final byte[] ipv6d = Hex.decode("871020010db885a3000000008a2e03707334");
+ private static final byte[] ipv6e = Hex.decode("871020010db885a3000000008a2e0a090800");
+ private static final byte[] ipv6f = Hex.decode("872020010db885a3000000008a2e0a090800ffffffffffff00000000000000000000");
+ private static final byte[] ipv6g = Hex.decode("872020010db885a3000000008a2e0a090800ffffffffffffffffffffffffffffffff");
+ private static final byte[] ipv6h = Hex.decode("872020010db885a300000000000000000000ffffffffffff00000000000000000000");
+ private static final byte[] ipv6i = Hex.decode("872020010db885a300000000000000000000fffffffffffe00000000000000000000");
+ private static final byte[] ipv6j = Hex.decode("872020010db885a300000000000000000000ffffffffffff80000000000000000000");
+
+ public String getName()
+ {
+ return "GeneralName";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ GeneralName nm = new GeneralName(GeneralName.iPAddress, "10.9.8.0");
+ if (!Arrays.areEqual(nm.getEncoded(), ipv4))
+ {
+ fail("ipv4 encoding failed");
+ }
+
+ nm = new GeneralName(GeneralName.iPAddress, "10.9.8.0/255.255.255.0");
+ if (!Arrays.areEqual(nm.getEncoded(), ipv4WithMask1))
+ {
+ fail("ipv4 with netmask 1 encoding failed");
+ }
+
+ nm = new GeneralName(GeneralName.iPAddress, "10.9.8.0/24");
+ if (!Arrays.areEqual(nm.getEncoded(), ipv4WithMask1))
+ {
+ fail("ipv4 with netmask 2 encoding failed");
+ }
+
+ nm = new GeneralName(GeneralName.iPAddress, "10.9.8.0/255.255.128.0");
+ if (!Arrays.areEqual(nm.getEncoded(), ipv4WithMask2))
+ {
+ fail("ipv4 with netmask 3a encoding failed");
+ }
+
+ nm = new GeneralName(GeneralName.iPAddress, "10.9.8.0/17");
+ if (!Arrays.areEqual(nm.getEncoded(), ipv4WithMask2))
+ {
+ fail("ipv4 with netmask 3b encoding failed");
+ }
+
+ nm = new GeneralName(GeneralName.iPAddress, "10.9.8.0/255.255.192.0");
+ if (!Arrays.areEqual(nm.getEncoded(), ipv4WithMask3))
+ {
+ fail("ipv4 with netmask 3a encoding failed");
+ }
+
+ nm = new GeneralName(GeneralName.iPAddress, "10.9.8.0/18");
+ if (!Arrays.areEqual(nm.getEncoded(), ipv4WithMask3))
+ {
+ fail("ipv4 with netmask 3b encoding failed");
+ }
+
+ nm = new GeneralName(GeneralName.iPAddress, "2001:0db8:85a3:08d3:1319:8a2e:0370:7334");
+ if (!Arrays.areEqual(nm.getEncoded(), ipv6a))
+ {
+ fail("ipv6 with netmask encoding failed");
+ }
+
+ nm = new GeneralName(GeneralName.iPAddress, "2001:0db8:85a3::1319:8a2e:0370:7334");
+ if (!Arrays.areEqual(nm.getEncoded(), ipv6b))
+ {
+ fail("ipv6b encoding failed");
+ }
+
+ nm = new GeneralName(GeneralName.iPAddress, "::1");
+ if (!Arrays.areEqual(nm.getEncoded(), ipv6c))
+ {
+ fail("ipv6c failed");
+ }
+
+ nm = new GeneralName(GeneralName.iPAddress, "2001:0db8:85a3::8a2e:0370:7334");
+ if (!Arrays.areEqual(nm.getEncoded(), ipv6d))
+ {
+ fail("ipv6d failed");
+ }
+
+ nm = new GeneralName(GeneralName.iPAddress, "2001:0db8:85a3::8a2e:10.9.8.0");
+ if (!Arrays.areEqual(nm.getEncoded(), ipv6e))
+ {
+ fail("ipv6e failed");
+ }
+
+ nm = new GeneralName(GeneralName.iPAddress, "2001:0db8:85a3::8a2e:10.9.8.0/ffff:ffff:ffff::0000");
+ if (!Arrays.areEqual(nm.getEncoded(), ipv6f))
+ {
+ fail("ipv6f failed");
+ }
+
+ nm = new GeneralName(GeneralName.iPAddress, "2001:0db8:85a3::8a2e:10.9.8.0/128");
+ if (!Arrays.areEqual(nm.getEncoded(), ipv6g))
+ {
+ fail("ipv6g failed");
+ }
+
+ nm = new GeneralName(GeneralName.iPAddress, "2001:0db8:85a3::/48");
+ if (!Arrays.areEqual(nm.getEncoded(), ipv6h))
+ {
+ fail("ipv6h failed");
+ }
+
+ nm = new GeneralName(GeneralName.iPAddress, "2001:0db8:85a3::/47");
+ if (!Arrays.areEqual(nm.getEncoded(), ipv6i))
+ {
+ fail("ipv6i failed");
+ }
+
+ nm = new GeneralName(GeneralName.iPAddress, "2001:0db8:85a3::/49");
+ if (!Arrays.areEqual(nm.getEncoded(), ipv6j))
+ {
+ fail("ipv6j failed");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new GeneralNameTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/GeneralizedTimeTest.java b/core/src/test/java/org/spongycastle/asn1/test/GeneralizedTimeTest.java
new file mode 100644
index 00000000..3dce5b3c
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/GeneralizedTimeTest.java
@@ -0,0 +1,201 @@
+package org.spongycastle.asn1.test;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.SimpleTimeZone;
+import java.util.TimeZone;
+
+import org.spongycastle.asn1.DERGeneralizedTime;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * X.690 test example
+ */
+public class GeneralizedTimeTest
+ extends SimpleTest
+{
+ String[] input =
+ {
+ "20020122122220",
+ "20020122122220Z",
+ "20020122122220-1000",
+ "20020122122220+00",
+ "20020122122220.1",
+ "20020122122220.1Z",
+ "20020122122220.1-1000",
+ "20020122122220.1+00",
+ "20020122122220.01",
+ "20020122122220.01Z",
+ "20020122122220.01-1000",
+ "20020122122220.01+00",
+ "20020122122220.001",
+ "20020122122220.001Z",
+ "20020122122220.001-1000",
+ "20020122122220.001+00",
+ "20020122122220.0001",
+ "20020122122220.0001Z",
+ "20020122122220.0001-1000",
+ "20020122122220.0001+00",
+ "20020122122220.0001+1000"
+ };
+
+ String[] output = {
+ "20020122122220",
+ "20020122122220GMT+00:00",
+ "20020122122220GMT-10:00",
+ "20020122122220GMT+00:00",
+ "20020122122220.1",
+ "20020122122220.1GMT+00:00",
+ "20020122122220.1GMT-10:00",
+ "20020122122220.1GMT+00:00",
+ "20020122122220.01",
+ "20020122122220.01GMT+00:00",
+ "20020122122220.01GMT-10:00",
+ "20020122122220.01GMT+00:00",
+ "20020122122220.001",
+ "20020122122220.001GMT+00:00",
+ "20020122122220.001GMT-10:00",
+ "20020122122220.001GMT+00:00",
+ "20020122122220.0001",
+ "20020122122220.0001GMT+00:00",
+ "20020122122220.0001GMT-10:00",
+ "20020122122220.0001GMT+00:00",
+ "20020122122220.0001GMT+10:00" };
+
+ String[] zOutput = {
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122222220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122222220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122222220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122222220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122222220Z",
+ "20020122122220Z",
+ "20020122022220Z"
+ };
+
+ String[] mzOutput = {
+ "20020122122220.000Z",
+ "20020122122220.000Z",
+ "20020122222220.000Z",
+ "20020122122220.000Z",
+ "20020122122220.100Z",
+ "20020122122220.100Z",
+ "20020122222220.100Z",
+ "20020122122220.100Z",
+ "20020122122220.010Z",
+ "20020122122220.010Z",
+ "20020122222220.010Z",
+ "20020122122220.010Z",
+ "20020122122220.001Z",
+ "20020122122220.001Z",
+ "20020122222220.001Z",
+ "20020122122220.001Z",
+ "20020122122220.000Z",
+ "20020122122220.000Z",
+ "20020122222220.000Z",
+ "20020122122220.000Z",
+ "20020122022220.000Z"
+ };
+
+ public String getName()
+ {
+ return "GeneralizedTime";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
+
+ dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
+
+ for (int i = 0; i != input.length; i++)
+ {
+ DERGeneralizedTime t = new DERGeneralizedTime(input[i]);
+
+ if (output[i].indexOf('G') > 0) // don't check local time the same way
+ {
+ if (!t.getTime().equals(output[i]))
+ {
+ fail("failed conversion test");
+ }
+ if (!dateF.format(t.getDate()).equals(zOutput[i]))
+ {
+ fail("failed date conversion test");
+ }
+ }
+ else
+ {
+ String offset = calculateGMTOffset(t.getDate());
+ if (!t.getTime().equals(output[i] + offset))
+ {
+ fail("failed conversion test");
+ }
+ }
+ }
+
+ dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS'Z'");
+
+ dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
+
+ for (int i = 0; i != input.length; i++)
+ {
+ DERGeneralizedTime t = new DERGeneralizedTime(input[i]);
+
+ if (!dateF.format(t.getDate()).equals(mzOutput[i]))
+ {
+ fail("failed long date conversion test");
+ }
+ }
+ }
+
+ private String calculateGMTOffset(Date date)
+ {
+ String sign = "+";
+ TimeZone timeZone = TimeZone.getDefault();
+ int offset = timeZone.getRawOffset();
+ if (offset < 0)
+ {
+ sign = "-";
+ offset = -offset;
+ }
+ int hours = offset / (60 * 60 * 1000);
+ int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000);
+
+ if (timeZone.useDaylightTime() && timeZone.inDaylightTime(date))
+ {
+ hours += sign.equals("+") ? 1 : -1;
+ }
+
+ return "GMT" + sign + convert(hours) + ":" + convert(minutes);
+ }
+
+ private String convert(int time)
+ {
+ if (time < 10)
+ {
+ return "0" + time;
+ }
+
+ return Integer.toString(time);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new GeneralizedTimeTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/GenerationTest.java b/core/src/test/java/org/spongycastle/asn1/test/GenerationTest.java
new file mode 100644
index 00000000..3502c8a1
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/GenerationTest.java
@@ -0,0 +1,441 @@
+package org.spongycastle.asn1.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1OutputStream;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DERNull;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.oiw.ElGamalParameter;
+import org.spongycastle.asn1.oiw.OIWObjectIdentifiers;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.x500.X500Name;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.AuthorityKeyIdentifier;
+import org.spongycastle.asn1.x509.CRLReason;
+import org.spongycastle.asn1.x509.Extension;
+import org.spongycastle.asn1.x509.Extensions;
+import org.spongycastle.asn1.x509.ExtensionsGenerator;
+import org.spongycastle.asn1.x509.GeneralName;
+import org.spongycastle.asn1.x509.GeneralNames;
+import org.spongycastle.asn1.x509.IssuingDistributionPoint;
+import org.spongycastle.asn1.x509.KeyUsage;
+import org.spongycastle.asn1.x509.RSAPublicKeyStructure;
+import org.spongycastle.asn1.x509.SubjectKeyIdentifier;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.spongycastle.asn1.x509.TBSCertList;
+import org.spongycastle.asn1.x509.TBSCertificate;
+import org.spongycastle.asn1.x509.Time;
+import org.spongycastle.asn1.x509.V1TBSCertificateGenerator;
+import org.spongycastle.asn1.x509.V2TBSCertListGenerator;
+import org.spongycastle.asn1.x509.V3TBSCertificateGenerator;
+import org.spongycastle.asn1.x509.X509Extension;
+import org.spongycastle.asn1.x509.X509Extensions;
+import org.spongycastle.asn1.x509.X509Name;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Base64;
+import org.spongycastle.util.test.SimpleTest;
+
+public class GenerationTest
+ extends SimpleTest
+{
+ private byte[] v1Cert = Base64.decode(
+ "MIGtAgEBMA0GCSqGSIb3DQEBBAUAMCUxCzAJBgNVBAMMAkFVMRYwFAYDVQQKDA1Cb"
+ + "3VuY3kgQ2FzdGxlMB4XDTcwMDEwMTAwMDAwMVoXDTcwMDEwMTAwMDAxMlowNjELMA"
+ + "kGA1UEAwwCQVUxFjAUBgNVBAoMDUJvdW5jeSBDYXN0bGUxDzANBgNVBAsMBlRlc3Q"
+ + "gMTAaMA0GCSqGSIb3DQEBAQUAAwkAMAYCAQECAQI=");
+
+ private byte[] v3Cert = Base64.decode(
+ "MIIBSKADAgECAgECMA0GCSqGSIb3DQEBBAUAMCUxCzAJBgNVBAMMAkFVMRYwFAYD"
+ + "VQQKDA1Cb3VuY3kgQ2FzdGxlMB4XDTcwMDEwMTAwMDAwMVoXDTcwMDEwMTAwMDAw"
+ + "MlowNjELMAkGA1UEAwwCQVUxFjAUBgNVBAoMDUJvdW5jeSBDYXN0bGUxDzANBgNV"
+ + "BAsMBlRlc3QgMjAYMBAGBisOBwIBATAGAgEBAgECAwQAAgEDo4GVMIGSMGEGA1Ud"
+ + "IwEB/wRXMFWAFDZPdpHPzKi7o8EJokkQU2uqCHRRoTqkODA2MQswCQYDVQQDDAJB"
+ + "VTEWMBQGA1UECgwNQm91bmN5IENhc3RsZTEPMA0GA1UECwwGVGVzdCAyggECMCAG"
+ + "A1UdDgEB/wQWBBQ2T3aRz8you6PBCaJJEFNrqgh0UTALBgNVHQ8EBAMCBBA=");
+
+ private byte[] v3CertNullSubject = Base64.decode(
+ "MIHGoAMCAQICAQIwDQYJKoZIhvcNAQEEBQAwJTELMAkGA1UEAwwCQVUxFjAUBgNVB"
+ + "AoMDUJvdW5jeSBDYXN0bGUwHhcNNzAwMTAxMDAwMDAxWhcNNzAwMTAxMDAwMDAyWj"
+ + "AAMBgwEAYGKw4HAgEBMAYCAQECAQIDBAACAQOjSjBIMEYGA1UdEQEB/wQ8MDqkODA"
+ + "2MQswCQYDVQQDDAJBVTEWMBQGA1UECgwNQm91bmN5IENhc3RsZTEPMA0GA1UECwwG"
+ + "VGVzdCAy");
+
+ private byte[] v2CertList = Base64.decode(
+ "MIIBQwIBATANBgkqhkiG9w0BAQUFADAlMQswCQYDVQQDDAJBVTEWMBQGA1UECgwN" +
+ "Qm91bmN5IENhc3RsZRcNNzAwMTAxMDAwMDAwWhcNNzAwMTAxMDAwMDAyWjAiMCAC" +
+ "AQEXDTcwMDEwMTAwMDAwMVowDDAKBgNVHRUEAwoBCqCBxTCBwjBhBgNVHSMBAf8E" +
+ "VzBVgBQ2T3aRz8you6PBCaJJEFNrqgh0UaE6pDgwNjELMAkGA1UEAwwCQVUxFjAU" +
+ "BgNVBAoMDUJvdW5jeSBDYXN0bGUxDzANBgNVBAsMBlRlc3QgMoIBAjBDBgNVHRIE" +
+ "PDA6pDgwNjELMAkGA1UEAwwCQVUxFjAUBgNVBAoMDUJvdW5jeSBDYXN0bGUxDzAN" +
+ "BgNVBAsMBlRlc3QgMzAKBgNVHRQEAwIBATAMBgNVHRwBAf8EAjAA");
+
+ private void tbsV1CertGen()
+ throws IOException
+ {
+ V1TBSCertificateGenerator gen = new V1TBSCertificateGenerator();
+ Date startDate = new Date(1000);
+ Date endDate = new Date(12000);
+
+ gen.setSerialNumber(new ASN1Integer(1));
+
+ gen.setStartDate(new Time(startDate));
+ gen.setEndDate(new Time(endDate));
+
+ gen.setIssuer(new X500Name("CN=AU,O=Bouncy Castle"));
+ gen.setSubject(new X500Name("CN=AU,O=Bouncy Castle,OU=Test 1"));
+
+ gen.setSignature(new AlgorithmIdentifier(PKCSObjectIdentifiers.md5WithRSAEncryption, DERNull.INSTANCE));
+
+ SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE),
+ new RSAPublicKeyStructure(BigInteger.valueOf(1), BigInteger.valueOf(2)));
+
+ gen.setSubjectPublicKeyInfo(info);
+
+ TBSCertificate tbs = gen.generateTBSCertificate();
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ aOut.writeObject(tbs);
+
+ if (!Arrays.areEqual(bOut.toByteArray(), v1Cert))
+ {
+ fail("failed v1 cert generation");
+ }
+
+ //
+ // read back test
+ //
+ ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(v1Cert));
+ ASN1Primitive o = aIn.readObject();
+
+ bOut = new ByteArrayOutputStream();
+ aOut = new ASN1OutputStream(bOut);
+
+ aOut.writeObject(o);
+
+ if (!Arrays.areEqual(bOut.toByteArray(), v1Cert))
+ {
+ fail("failed v1 cert read back test");
+ }
+ }
+
+ private AuthorityKeyIdentifier createAuthorityKeyId(
+ SubjectPublicKeyInfo info,
+ X500Name name,
+ int sNumber)
+ {
+ GeneralName genName = new GeneralName(name);
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(genName);
+
+ return new AuthorityKeyIdentifier(
+ info, GeneralNames.getInstance(new DERSequence(v)), BigInteger.valueOf(sNumber));
+ }
+
+ private void tbsV3CertGen()
+ throws IOException
+ {
+ V3TBSCertificateGenerator gen = new V3TBSCertificateGenerator();
+ Date startDate = new Date(1000);
+ Date endDate = new Date(2000);
+
+ gen.setSerialNumber(new ASN1Integer(2));
+
+ gen.setStartDate(new Time(startDate));
+ gen.setEndDate(new Time(endDate));
+
+ gen.setIssuer(new X500Name("CN=AU,O=Bouncy Castle"));
+ gen.setSubject(new X500Name("CN=AU,O=Bouncy Castle,OU=Test 2"));
+
+ gen.setSignature(new AlgorithmIdentifier(PKCSObjectIdentifiers.md5WithRSAEncryption, DERNull.INSTANCE));
+
+ SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(OIWObjectIdentifiers.elGamalAlgorithm, new ElGamalParameter(BigInteger.valueOf(1), BigInteger.valueOf(2))), new ASN1Integer(3));
+
+ gen.setSubjectPublicKeyInfo(info);
+
+ //
+ // add extensions
+ //
+ Vector order = new Vector();
+ Hashtable extensions = new Hashtable();
+
+ order.addElement(X509Extension.authorityKeyIdentifier);
+ order.addElement(X509Extension.subjectKeyIdentifier);
+ order.addElement(X509Extension.keyUsage);
+
+ extensions.put(X509Extension.authorityKeyIdentifier, new X509Extension(true, new DEROctetString(createAuthorityKeyId(info, new X500Name("CN=AU,O=Bouncy Castle,OU=Test 2"), 2))));
+ extensions.put(X509Extension.subjectKeyIdentifier, new X509Extension(true, new DEROctetString(new SubjectKeyIdentifier(getDigest(info)))));
+ extensions.put(X509Extension.keyUsage, new X509Extension(false, new DEROctetString(new KeyUsage(KeyUsage.dataEncipherment))));
+
+ X509Extensions ex = new X509Extensions(order, extensions);
+
+ gen.setExtensions(ex);
+
+ TBSCertificate tbs = gen.generateTBSCertificate();
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ aOut.writeObject(tbs);
+
+ if (!Arrays.areEqual(bOut.toByteArray(), v3Cert))
+ {
+ fail("failed v3 cert generation");
+ }
+
+ //
+ // read back test
+ //
+ ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(v3Cert));
+ ASN1Primitive o = aIn.readObject();
+
+ bOut = new ByteArrayOutputStream();
+ aOut = new ASN1OutputStream(bOut);
+
+ aOut.writeObject(o);
+
+ if (!Arrays.areEqual(bOut.toByteArray(), v3Cert))
+ {
+ fail("failed v3 cert read back test");
+ }
+ }
+
+ private void tbsV3CertGenWithNullSubject()
+ throws IOException
+ {
+ V3TBSCertificateGenerator gen = new V3TBSCertificateGenerator();
+ Date startDate = new Date(1000);
+ Date endDate = new Date(2000);
+
+ gen.setSerialNumber(new ASN1Integer(2));
+
+ gen.setStartDate(new Time(startDate));
+ gen.setEndDate(new Time(endDate));
+
+ gen.setIssuer(new X500Name("CN=AU,O=Bouncy Castle"));
+
+ gen.setSignature(new AlgorithmIdentifier(PKCSObjectIdentifiers.md5WithRSAEncryption, DERNull.INSTANCE));
+
+ SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(OIWObjectIdentifiers.elGamalAlgorithm, new ElGamalParameter(BigInteger.valueOf(1), BigInteger.valueOf(2))), new ASN1Integer(3));
+
+ gen.setSubjectPublicKeyInfo(info);
+
+ try
+ {
+ gen.generateTBSCertificate();
+ fail("null subject not caught!");
+ }
+ catch (IllegalStateException e)
+ {
+ if (!e.getMessage().equals("not all mandatory fields set in V3 TBScertificate generator"))
+ {
+ fail("unexpected exception", e);
+ }
+ }
+
+ //
+ // add extensions
+ //
+ Vector order = new Vector();
+ Hashtable extensions = new Hashtable();
+
+ order.addElement(X509Extension.subjectAlternativeName);
+
+ extensions.put(X509Extension.subjectAlternativeName, new X509Extension(true, new DEROctetString(new GeneralNames(new GeneralName(new X509Name("CN=AU,O=Bouncy Castle,OU=Test 2"))))));
+
+ X509Extensions ex = new X509Extensions(order, extensions);
+
+ gen.setExtensions(ex);
+
+ TBSCertificate tbs = gen.generateTBSCertificate();
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ aOut.writeObject(tbs);
+
+ if (!Arrays.areEqual(bOut.toByteArray(), v3CertNullSubject))
+ {
+ fail("failed v3 null sub cert generation");
+ }
+
+ //
+ // read back test
+ //
+ ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(v3CertNullSubject));
+ ASN1Primitive o = aIn.readObject();
+
+ bOut = new ByteArrayOutputStream();
+ aOut = new ASN1OutputStream(bOut);
+
+ aOut.writeObject(o);
+
+ if (!Arrays.areEqual(bOut.toByteArray(), v3CertNullSubject))
+ {
+ fail("failed v3 null sub cert read back test");
+ }
+ }
+
+ private void tbsV2CertListGen()
+ throws IOException
+ {
+ V2TBSCertListGenerator gen = new V2TBSCertListGenerator();
+
+ gen.setIssuer(new X500Name("CN=AU,O=Bouncy Castle"));
+
+ gen.addCRLEntry(new ASN1Integer(1), new Time(new Date(1000)), CRLReason.aACompromise);
+
+ gen.setNextUpdate(new Time(new Date(2000)));
+
+ gen.setThisUpdate(new Time(new Date(500)));
+
+ gen.setSignature(new AlgorithmIdentifier(PKCSObjectIdentifiers.sha1WithRSAEncryption, DERNull.INSTANCE));
+
+ //
+ // extensions
+ //
+ SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(OIWObjectIdentifiers.elGamalAlgorithm, new ElGamalParameter(BigInteger.valueOf(1), BigInteger.valueOf(2))), new ASN1Integer(3));
+
+ ExtensionsGenerator extGen = new ExtensionsGenerator();
+
+ extGen.addExtension(Extension.authorityKeyIdentifier, true, createAuthorityKeyId(info, new X500Name("CN=AU,O=Bouncy Castle,OU=Test 2"), 2));
+ extGen.addExtension(Extension.issuerAlternativeName, false, new GeneralNames(new GeneralName(new X500Name("CN=AU,O=Bouncy Castle,OU=Test 3"))));
+ extGen.addExtension(Extension.cRLNumber, false, new ASN1Integer(1));
+ extGen.addExtension(Extension.issuingDistributionPoint, true, IssuingDistributionPoint.getInstance(new DERSequence()));
+
+ Extensions ex = extGen.generate();
+
+ gen.setExtensions(ex);
+
+ TBSCertList tbs = gen.generateTBSCertList();
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ aOut.writeObject(tbs);
+
+ if (!Arrays.areEqual(bOut.toByteArray(), v2CertList))
+ {
+ System.out.println(new String(Base64.encode(bOut.toByteArray())));
+ fail("failed v2 cert list generation");
+ }
+
+ //
+ // read back test
+ //
+ ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(v2CertList));
+ ASN1Primitive o = aIn.readObject();
+
+ bOut = new ByteArrayOutputStream();
+ aOut = new ASN1OutputStream(bOut);
+
+ aOut.writeObject(o);
+
+ if (!Arrays.areEqual(bOut.toByteArray(), v2CertList))
+ {
+ fail("failed v2 cert list read back test");
+ }
+
+ //
+ // check we can add a custom reason
+ //
+ gen.addCRLEntry(new ASN1Integer(1), new Time(new Date(1000)), CRLReason.aACompromise);
+
+ //
+ // check invalidity date
+ gen.addCRLEntry(new ASN1Integer(2), new Time(new Date(1000)), CRLReason.affiliationChanged, new ASN1GeneralizedTime(new Date(2000)));
+
+ TBSCertList crl = gen.generateTBSCertList();
+
+ TBSCertList.CRLEntry[] entries = crl.getRevokedCertificates();
+ for (int i = 0; i != entries.length; i++)
+ {
+ TBSCertList.CRLEntry entry = entries[i];
+
+ if (entry.getUserCertificate().equals(new ASN1Integer(1)))
+ {
+ Extensions extensions = entry.getExtensions();
+ Extension ext = extensions.getExtension(Extension.reasonCode);
+
+ CRLReason r = CRLReason.getInstance(ext.getParsedValue());
+
+ if (r.getValue().intValue() != CRLReason.aACompromise)
+ {
+ fail("reason code mismatch");
+ }
+ }
+ else if (entry.getUserCertificate().equals(new ASN1Integer(2)))
+ {
+ Extensions extensions = entry.getExtensions();
+ Extension ext = extensions.getExtension(Extension.reasonCode);
+
+ CRLReason r = CRLReason.getInstance(ext.getParsedValue());
+
+ if (r.getValue().intValue() != CRLReason.affiliationChanged)
+ {
+ fail("reason code mismatch");
+ }
+
+ ext = extensions.getExtension(Extension.invalidityDate);
+
+ ASN1GeneralizedTime t = ASN1GeneralizedTime.getInstance(ext.getParsedValue());
+
+ try
+ {
+ if (!t.getDate().equals(new Date(2000)))
+ {
+ fail("invalidity date mismatch");
+ }
+ }
+ catch (ParseException e)
+ {
+ fail("can't parse date", e);
+ }
+ }
+ }
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ tbsV1CertGen();
+ tbsV3CertGen();
+ tbsV3CertGenWithNullSubject();
+ tbsV2CertListGen();
+ }
+
+ public String getName()
+ {
+ return "Generation";
+ }
+
+ private static byte[] getDigest(SubjectPublicKeyInfo spki)
+ {
+ Digest digest = new SHA1Digest();
+ byte[] resBuf = new byte[digest.getDigestSize()];
+
+ byte[] bytes = spki.getPublicKeyData().getBytes();
+ digest.update(bytes, 0, bytes.length);
+ digest.doFinal(resBuf, 0);
+ return resBuf;
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new GenerationTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/GetInstanceTest.java b/core/src/test/java/org/spongycastle/asn1/test/GetInstanceTest.java
new file mode 100644
index 00000000..05652173
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/GetInstanceTest.java
@@ -0,0 +1,888 @@
+package org.spongycastle.asn1.test;
+
+import java.lang.reflect.Method;
+import java.math.BigInteger;
+import java.util.Date;
+import java.util.Vector;
+
+import junit.framework.TestCase;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Enumerated;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Object;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.ASN1UTCTime;
+import org.spongycastle.asn1.DERBMPString;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERGeneralString;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.DERNull;
+import org.spongycastle.asn1.DERNumericString;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERPrintableString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERSet;
+import org.spongycastle.asn1.DERT61String;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.DERUTF8String;
+import org.spongycastle.asn1.DERUniversalString;
+import org.spongycastle.asn1.DERVisibleString;
+import org.spongycastle.asn1.cmp.CAKeyUpdAnnContent;
+import org.spongycastle.asn1.cmp.CMPCertificate;
+import org.spongycastle.asn1.cmp.CRLAnnContent;
+import org.spongycastle.asn1.cmp.CertConfirmContent;
+import org.spongycastle.asn1.cmp.CertOrEncCert;
+import org.spongycastle.asn1.cmp.CertRepMessage;
+import org.spongycastle.asn1.cmp.CertResponse;
+import org.spongycastle.asn1.cmp.CertifiedKeyPair;
+import org.spongycastle.asn1.cmp.Challenge;
+import org.spongycastle.asn1.cmp.ErrorMsgContent;
+import org.spongycastle.asn1.cmp.GenMsgContent;
+import org.spongycastle.asn1.cmp.GenRepContent;
+import org.spongycastle.asn1.cmp.InfoTypeAndValue;
+import org.spongycastle.asn1.cmp.KeyRecRepContent;
+import org.spongycastle.asn1.cmp.OOBCertHash;
+import org.spongycastle.asn1.cmp.PBMParameter;
+import org.spongycastle.asn1.cmp.PKIBody;
+import org.spongycastle.asn1.cmp.PKIConfirmContent;
+import org.spongycastle.asn1.cmp.PKIFailureInfo;
+import org.spongycastle.asn1.cmp.PKIFreeText;
+import org.spongycastle.asn1.cmp.PKIHeader;
+import org.spongycastle.asn1.cmp.PKIMessage;
+import org.spongycastle.asn1.cmp.PKIMessages;
+import org.spongycastle.asn1.cmp.PKIStatus;
+import org.spongycastle.asn1.cmp.PKIStatusInfo;
+import org.spongycastle.asn1.cmp.POPODecKeyChallContent;
+import org.spongycastle.asn1.cmp.POPODecKeyRespContent;
+import org.spongycastle.asn1.cmp.PollRepContent;
+import org.spongycastle.asn1.cmp.PollReqContent;
+import org.spongycastle.asn1.cmp.ProtectedPart;
+import org.spongycastle.asn1.cmp.RevAnnContent;
+import org.spongycastle.asn1.cmp.RevDetails;
+import org.spongycastle.asn1.cmp.RevRepContent;
+import org.spongycastle.asn1.cmp.RevReqContent;
+import org.spongycastle.asn1.cms.Attribute;
+import org.spongycastle.asn1.cms.Attributes;
+import org.spongycastle.asn1.cms.AuthEnvelopedData;
+import org.spongycastle.asn1.cms.AuthenticatedData;
+import org.spongycastle.asn1.cms.CompressedData;
+import org.spongycastle.asn1.cms.ContentInfo;
+import org.spongycastle.asn1.cms.EncryptedContentInfo;
+import org.spongycastle.asn1.cms.EncryptedData;
+import org.spongycastle.asn1.cms.EnvelopedData;
+import org.spongycastle.asn1.cms.Evidence;
+import org.spongycastle.asn1.cms.IssuerAndSerialNumber;
+import org.spongycastle.asn1.cms.KEKIdentifier;
+import org.spongycastle.asn1.cms.KEKRecipientInfo;
+import org.spongycastle.asn1.cms.KeyAgreeRecipientIdentifier;
+import org.spongycastle.asn1.cms.KeyAgreeRecipientInfo;
+import org.spongycastle.asn1.cms.KeyTransRecipientInfo;
+import org.spongycastle.asn1.cms.MetaData;
+import org.spongycastle.asn1.cms.OriginatorIdentifierOrKey;
+import org.spongycastle.asn1.cms.OriginatorInfo;
+import org.spongycastle.asn1.cms.OriginatorPublicKey;
+import org.spongycastle.asn1.cms.OtherKeyAttribute;
+import org.spongycastle.asn1.cms.OtherRecipientInfo;
+import org.spongycastle.asn1.cms.PasswordRecipientInfo;
+import org.spongycastle.asn1.cms.RecipientEncryptedKey;
+import org.spongycastle.asn1.cms.RecipientIdentifier;
+import org.spongycastle.asn1.cms.RecipientInfo;
+import org.spongycastle.asn1.cms.RecipientKeyIdentifier;
+import org.spongycastle.asn1.cms.SignerIdentifier;
+import org.spongycastle.asn1.cms.SignerInfo;
+import org.spongycastle.asn1.cms.TimeStampAndCRL;
+import org.spongycastle.asn1.cms.TimeStampTokenEvidence;
+import org.spongycastle.asn1.cms.TimeStampedData;
+import org.spongycastle.asn1.cms.ecc.MQVuserKeyingMaterial;
+import org.spongycastle.asn1.crmf.AttributeTypeAndValue;
+import org.spongycastle.asn1.crmf.CertId;
+import org.spongycastle.asn1.crmf.CertReqMessages;
+import org.spongycastle.asn1.crmf.CertReqMsg;
+import org.spongycastle.asn1.crmf.CertRequest;
+import org.spongycastle.asn1.crmf.CertTemplate;
+import org.spongycastle.asn1.crmf.Controls;
+import org.spongycastle.asn1.crmf.EncKeyWithID;
+import org.spongycastle.asn1.crmf.EncryptedKey;
+import org.spongycastle.asn1.crmf.EncryptedValue;
+import org.spongycastle.asn1.crmf.OptionalValidity;
+import org.spongycastle.asn1.crmf.PKIArchiveOptions;
+import org.spongycastle.asn1.crmf.PKIPublicationInfo;
+import org.spongycastle.asn1.crmf.PKMACValue;
+import org.spongycastle.asn1.crmf.POPOPrivKey;
+import org.spongycastle.asn1.crmf.POPOSigningKey;
+import org.spongycastle.asn1.crmf.POPOSigningKeyInput;
+import org.spongycastle.asn1.crmf.ProofOfPossession;
+import org.spongycastle.asn1.crmf.SinglePubInfo;
+import org.spongycastle.asn1.cryptopro.ECGOST3410ParamSetParameters;
+import org.spongycastle.asn1.cryptopro.GOST28147Parameters;
+import org.spongycastle.asn1.cryptopro.GOST3410ParamSetParameters;
+import org.spongycastle.asn1.cryptopro.GOST3410PublicKeyAlgParameters;
+import org.spongycastle.asn1.eac.CVCertificate;
+import org.spongycastle.asn1.eac.CVCertificateRequest;
+import org.spongycastle.asn1.eac.CertificateBody;
+import org.spongycastle.asn1.eac.PublicKeyDataObject;
+import org.spongycastle.asn1.eac.RSAPublicKey;
+import org.spongycastle.asn1.eac.UnsignedInteger;
+import org.spongycastle.asn1.esf.CommitmentTypeIndication;
+import org.spongycastle.asn1.esf.CommitmentTypeQualifier;
+import org.spongycastle.asn1.esf.CompleteRevocationRefs;
+import org.spongycastle.asn1.esf.CrlIdentifier;
+import org.spongycastle.asn1.esf.CrlListID;
+import org.spongycastle.asn1.esf.CrlOcspRef;
+import org.spongycastle.asn1.esf.CrlValidatedID;
+import org.spongycastle.asn1.esf.OcspIdentifier;
+import org.spongycastle.asn1.esf.OcspListID;
+import org.spongycastle.asn1.esf.OcspResponsesID;
+import org.spongycastle.asn1.esf.OtherHash;
+import org.spongycastle.asn1.esf.OtherHashAlgAndValue;
+import org.spongycastle.asn1.esf.OtherRevRefs;
+import org.spongycastle.asn1.esf.OtherRevVals;
+import org.spongycastle.asn1.esf.RevocationValues;
+import org.spongycastle.asn1.esf.SPUserNotice;
+import org.spongycastle.asn1.esf.SPuri;
+import org.spongycastle.asn1.esf.SigPolicyQualifierInfo;
+import org.spongycastle.asn1.esf.SigPolicyQualifiers;
+import org.spongycastle.asn1.esf.SignaturePolicyId;
+import org.spongycastle.asn1.esf.SignaturePolicyIdentifier;
+import org.spongycastle.asn1.esf.SignerAttribute;
+import org.spongycastle.asn1.esf.SignerLocation;
+import org.spongycastle.asn1.ess.ContentHints;
+import org.spongycastle.asn1.ess.ContentIdentifier;
+import org.spongycastle.asn1.ess.ESSCertID;
+import org.spongycastle.asn1.ess.ESSCertIDv2;
+import org.spongycastle.asn1.ess.OtherCertID;
+import org.spongycastle.asn1.ess.OtherSigningCertificate;
+import org.spongycastle.asn1.ess.SigningCertificate;
+import org.spongycastle.asn1.ess.SigningCertificateV2;
+import org.spongycastle.asn1.icao.CscaMasterList;
+import org.spongycastle.asn1.icao.DataGroupHash;
+import org.spongycastle.asn1.icao.LDSSecurityObject;
+import org.spongycastle.asn1.icao.LDSVersionInfo;
+import org.spongycastle.asn1.isismtt.ocsp.CertHash;
+import org.spongycastle.asn1.isismtt.ocsp.RequestedCertificate;
+import org.spongycastle.asn1.isismtt.x509.AdditionalInformationSyntax;
+import org.spongycastle.asn1.isismtt.x509.AdmissionSyntax;
+import org.spongycastle.asn1.isismtt.x509.Admissions;
+import org.spongycastle.asn1.isismtt.x509.DeclarationOfMajority;
+import org.spongycastle.asn1.isismtt.x509.MonetaryLimit;
+import org.spongycastle.asn1.isismtt.x509.NamingAuthority;
+import org.spongycastle.asn1.isismtt.x509.ProcurationSyntax;
+import org.spongycastle.asn1.isismtt.x509.ProfessionInfo;
+import org.spongycastle.asn1.isismtt.x509.Restriction;
+import org.spongycastle.asn1.misc.CAST5CBCParameters;
+import org.spongycastle.asn1.misc.IDEACBCPar;
+import org.spongycastle.asn1.mozilla.PublicKeyAndChallenge;
+import org.spongycastle.asn1.ocsp.BasicOCSPResponse;
+import org.spongycastle.asn1.ocsp.CertID;
+import org.spongycastle.asn1.ocsp.CertStatus;
+import org.spongycastle.asn1.ocsp.CrlID;
+import org.spongycastle.asn1.ocsp.OCSPRequest;
+import org.spongycastle.asn1.ocsp.OCSPResponse;
+import org.spongycastle.asn1.ocsp.OCSPResponseStatus;
+import org.spongycastle.asn1.ocsp.Request;
+import org.spongycastle.asn1.ocsp.ResponderID;
+import org.spongycastle.asn1.ocsp.ResponseBytes;
+import org.spongycastle.asn1.ocsp.ResponseData;
+import org.spongycastle.asn1.ocsp.RevokedInfo;
+import org.spongycastle.asn1.ocsp.Signature;
+import org.spongycastle.asn1.ocsp.SingleResponse;
+import org.spongycastle.asn1.ocsp.TBSRequest;
+import org.spongycastle.asn1.oiw.OIWObjectIdentifiers;
+import org.spongycastle.asn1.pkcs.AuthenticatedSafe;
+import org.spongycastle.asn1.pkcs.CertificationRequest;
+import org.spongycastle.asn1.pkcs.CertificationRequestInfo;
+import org.spongycastle.asn1.pkcs.DHParameter;
+import org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo;
+import org.spongycastle.asn1.pkcs.MacData;
+import org.spongycastle.asn1.pkcs.PBEParameter;
+import org.spongycastle.asn1.pkcs.PBES2Parameters;
+import org.spongycastle.asn1.pkcs.PBKDF2Params;
+import org.spongycastle.asn1.pkcs.PKCS12PBEParams;
+import org.spongycastle.asn1.pkcs.Pfx;
+import org.spongycastle.asn1.pkcs.PrivateKeyInfo;
+import org.spongycastle.asn1.pkcs.RC2CBCParameter;
+import org.spongycastle.asn1.pkcs.RSAESOAEPparams;
+import org.spongycastle.asn1.pkcs.RSAPrivateKey;
+import org.spongycastle.asn1.pkcs.RSASSAPSSparams;
+import org.spongycastle.asn1.pkcs.SafeBag;
+import org.spongycastle.asn1.pkcs.SignedData;
+import org.spongycastle.asn1.sec.ECPrivateKey;
+import org.spongycastle.asn1.smime.SMIMECapabilities;
+import org.spongycastle.asn1.smime.SMIMECapability;
+import org.spongycastle.asn1.tsp.Accuracy;
+import org.spongycastle.asn1.tsp.MessageImprint;
+import org.spongycastle.asn1.tsp.TSTInfo;
+import org.spongycastle.asn1.tsp.TimeStampReq;
+import org.spongycastle.asn1.tsp.TimeStampResp;
+import org.spongycastle.asn1.x500.DirectoryString;
+import org.spongycastle.asn1.x500.RDN;
+import org.spongycastle.asn1.x500.X500Name;
+import org.spongycastle.asn1.x509.AccessDescription;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.AttCertIssuer;
+import org.spongycastle.asn1.x509.AttCertValidityPeriod;
+import org.spongycastle.asn1.x509.AttributeCertificate;
+import org.spongycastle.asn1.x509.AttributeCertificateInfo;
+import org.spongycastle.asn1.x509.AuthorityInformationAccess;
+import org.spongycastle.asn1.x509.AuthorityKeyIdentifier;
+import org.spongycastle.asn1.x509.BasicConstraints;
+import org.spongycastle.asn1.x509.CRLDistPoint;
+import org.spongycastle.asn1.x509.CRLNumber;
+import org.spongycastle.asn1.x509.CRLReason;
+import org.spongycastle.asn1.x509.Certificate;
+import org.spongycastle.asn1.x509.CertificateList;
+import org.spongycastle.asn1.x509.CertificatePair;
+import org.spongycastle.asn1.x509.CertificatePolicies;
+import org.spongycastle.asn1.x509.DSAParameter;
+import org.spongycastle.asn1.x509.DigestInfo;
+import org.spongycastle.asn1.x509.DisplayText;
+import org.spongycastle.asn1.x509.DistributionPoint;
+import org.spongycastle.asn1.x509.DistributionPointName;
+import org.spongycastle.asn1.x509.ExtendedKeyUsage;
+import org.spongycastle.asn1.x509.Extensions;
+import org.spongycastle.asn1.x509.GeneralName;
+import org.spongycastle.asn1.x509.GeneralNames;
+import org.spongycastle.asn1.x509.GeneralSubtree;
+import org.spongycastle.asn1.x509.Holder;
+import org.spongycastle.asn1.x509.IetfAttrSyntax;
+import org.spongycastle.asn1.x509.IssuerSerial;
+import org.spongycastle.asn1.x509.IssuingDistributionPoint;
+import org.spongycastle.asn1.x509.NameConstraints;
+import org.spongycastle.asn1.x509.NoticeReference;
+import org.spongycastle.asn1.x509.ObjectDigestInfo;
+import org.spongycastle.asn1.x509.PolicyInformation;
+import org.spongycastle.asn1.x509.PolicyMappings;
+import org.spongycastle.asn1.x509.PolicyQualifierInfo;
+import org.spongycastle.asn1.x509.PrivateKeyUsagePeriod;
+import org.spongycastle.asn1.x509.RSAPublicKeyStructure;
+import org.spongycastle.asn1.x509.RoleSyntax;
+import org.spongycastle.asn1.x509.SubjectDirectoryAttributes;
+import org.spongycastle.asn1.x509.SubjectKeyIdentifier;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.spongycastle.asn1.x509.TBSCertList;
+import org.spongycastle.asn1.x509.TBSCertificate;
+import org.spongycastle.asn1.x509.TBSCertificateStructure;
+import org.spongycastle.asn1.x509.Target;
+import org.spongycastle.asn1.x509.TargetInformation;
+import org.spongycastle.asn1.x509.Targets;
+import org.spongycastle.asn1.x509.Time;
+import org.spongycastle.asn1.x509.UserNotice;
+import org.spongycastle.asn1.x509.V2Form;
+import org.spongycastle.asn1.x509.X509CertificateStructure;
+import org.spongycastle.asn1.x509.X509Extensions;
+import org.spongycastle.asn1.x509.X509Name;
+import org.spongycastle.asn1.x509.qualified.BiometricData;
+import org.spongycastle.asn1.x509.qualified.Iso4217CurrencyCode;
+import org.spongycastle.asn1.x509.qualified.MonetaryValue;
+import org.spongycastle.asn1.x509.qualified.QCStatement;
+import org.spongycastle.asn1.x509.qualified.SemanticsInformation;
+import org.spongycastle.asn1.x509.qualified.TypeOfBiometricData;
+import org.spongycastle.asn1.x509.sigi.NameOrPseudonym;
+import org.spongycastle.asn1.x509.sigi.PersonalData;
+import org.spongycastle.asn1.x9.DHDomainParameters;
+import org.spongycastle.asn1.x9.DHPublicKey;
+import org.spongycastle.asn1.x9.DHValidationParms;
+import org.spongycastle.asn1.x9.X962Parameters;
+import org.spongycastle.asn1.x9.X9ECParameters;
+import org.spongycastle.util.Integers;
+import org.spongycastle.util.encoders.Base64;
+
+public class GetInstanceTest
+ extends TestCase
+{
+ public static byte[] attrCert = Base64.decode(
+ "MIIHQDCCBqkCAQEwgZChgY2kgYowgYcxHDAaBgkqhkiG9w0BCQEWDW1sb3JjaEB2"
+ + "dC5lZHUxHjAcBgNVBAMTFU1hcmt1cyBMb3JjaCAobWxvcmNoKTEbMBkGA1UECxMS"
+ + "VmlyZ2luaWEgVGVjaCBVc2VyMRAwDgYDVQQLEwdDbGFzcyAyMQswCQYDVQQKEwJ2"
+ + "dDELMAkGA1UEBhMCVVMwgYmkgYYwgYMxGzAZBgkqhkiG9w0BCQEWDHNzaGFoQHZ0"
+ + "LmVkdTEbMBkGA1UEAxMSU3VtaXQgU2hhaCAoc3NoYWgpMRswGQYDVQQLExJWaXJn"
+ + "aW5pYSBUZWNoIFVzZXIxEDAOBgNVBAsTB0NsYXNzIDExCzAJBgNVBAoTAnZ0MQsw"
+ + "CQYDVQQGEwJVUzANBgkqhkiG9w0BAQQFAAIBBTAiGA8yMDAzMDcxODE2MDgwMloY"
+ + "DzIwMDMwNzI1MTYwODAyWjCCBU0wggVJBgorBgEEAbRoCAEBMYIFORaCBTU8UnVs"
+ + "ZSBSdWxlSWQ9IkZpbGUtUHJpdmlsZWdlLVJ1bGUiIEVmZmVjdD0iUGVybWl0Ij4K"
+ + "IDxUYXJnZXQ+CiAgPFN1YmplY3RzPgogICA8U3ViamVjdD4KICAgIDxTdWJqZWN0"
+ + "TWF0Y2ggTWF0Y2hJZD0idXJuOm9hc2lzOm5hbWVzOnRjOnhhY21sOjEuMDpmdW5j"
+ + "dGlvbjpzdHJpbmctZXF1YWwiPgogICAgIDxBdHRyaWJ1dGVWYWx1ZSBEYXRhVHlw"
+ + "ZT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEjc3RyaW5nIj4KICAg"
+ + "ICAgIENOPU1hcmt1cyBMb3JjaDwvQXR0cmlidXRlVmFsdWU+CiAgICAgPFN1Ympl"
+ + "Y3RBdHRyaWJ1dGVEZXNpZ25hdG9yIEF0dHJpYnV0ZUlkPSJ1cm46b2FzaXM6bmFt"
+ + "ZXM6dGM6eGFjbWw6MS4wOnN1YmplY3Q6c3ViamVjdC1pZCIgRGF0YVR5cGU9Imh0"
+ + "dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hI3N0cmluZyIgLz4gCiAgICA8"
+ + "L1N1YmplY3RNYXRjaD4KICAgPC9TdWJqZWN0PgogIDwvU3ViamVjdHM+CiAgPFJl"
+ + "c291cmNlcz4KICAgPFJlc291cmNlPgogICAgPFJlc291cmNlTWF0Y2ggTWF0Y2hJ"
+ + "ZD0idXJuOm9hc2lzOm5hbWVzOnRjOnhhY21sOjEuMDpmdW5jdGlvbjpzdHJpbmct"
+ + "ZXF1YWwiPgogICAgIDxBdHRyaWJ1dGVWYWx1ZSBEYXRhVHlwZT0iaHR0cDovL3d3"
+ + "dy53My5vcmcvMjAwMS9YTUxTY2hlbWEjYW55VVJJIj4KICAgICAgaHR0cDovL3p1"
+ + "bmkuY3MudnQuZWR1PC9BdHRyaWJ1dGVWYWx1ZT4KICAgICA8UmVzb3VyY2VBdHRy"
+ + "aWJ1dGVEZXNpZ25hdG9yIEF0dHJpYnV0ZUlkPSJ1cm46b2FzaXM6bmFtZXM6dGM6"
+ + "eGFjbWw6MS4wOnJlc291cmNlOnJlc291cmNlLWlkIiBEYXRhVHlwZT0iaHR0cDov"
+ + "L3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEjYW55VVJJIiAvPiAKICAgIDwvUmVz"
+ + "b3VyY2VNYXRjaD4KICAgPC9SZXNvdXJjZT4KICA8L1Jlc291cmNlcz4KICA8QWN0"
+ + "aW9ucz4KICAgPEFjdGlvbj4KICAgIDxBY3Rpb25NYXRjaCBNYXRjaElkPSJ1cm46"
+ + "b2FzaXM6bmFtZXM6dGM6eGFjbWw6MS4wOmZ1bmN0aW9uOnN0cmluZy1lcXVhbCI+"
+ + "CiAgICAgPEF0dHJpYnV0ZVZhbHVlIERhdGFUeXBlPSJodHRwOi8vd3d3LnczLm9y"
+ + "Zy8yMDAxL1hNTFNjaGVtYSNzdHJpbmciPgpEZWxlZ2F0ZSBBY2Nlc3MgICAgIDwv"
+ + "QXR0cmlidXRlVmFsdWU+CgkgIDxBY3Rpb25BdHRyaWJ1dGVEZXNpZ25hdG9yIEF0"
+ + "dHJpYnV0ZUlkPSJ1cm46b2FzaXM6bmFtZXM6dGM6eGFjbWw6MS4wOmFjdGlvbjph"
+ + "Y3Rpb24taWQiIERhdGFUeXBlPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNj"
+ + "aGVtYSNzdHJpbmciIC8+IAogICAgPC9BY3Rpb25NYXRjaD4KICAgPC9BY3Rpb24+"
+ + "CiAgPC9BY3Rpb25zPgogPC9UYXJnZXQ+CjwvUnVsZT4KMA0GCSqGSIb3DQEBBAUA"
+ + "A4GBAGiJSM48XsY90HlYxGmGVSmNR6ZW2As+bot3KAfiCIkUIOAqhcphBS23egTr"
+ + "6asYwy151HshbPNYz+Cgeqs45KkVzh7bL/0e1r8sDVIaaGIkjHK3CqBABnfSayr3"
+ + "Rd1yBoDdEv8Qb+3eEPH6ab9021AsLEnJ6LWTmybbOpMNZ3tv");
+
+ byte[] cert1 = Base64.decode(
+ "MIIDXjCCAsegAwIBAgIBBzANBgkqhkiG9w0BAQQFADCBtzELMAkGA1UEBhMCQVUx"
+ + "ETAPBgNVBAgTCFZpY3RvcmlhMRgwFgYDVQQHEw9Tb3V0aCBNZWxib3VybmUxGjAY"
+ + "BgNVBAoTEUNvbm5lY3QgNCBQdHkgTHRkMR4wHAYDVQQLExVDZXJ0aWZpY2F0ZSBB"
+ + "dXRob3JpdHkxFTATBgNVBAMTDENvbm5lY3QgNCBDQTEoMCYGCSqGSIb3DQEJARYZ"
+ + "d2VibWFzdGVyQGNvbm5lY3Q0LmNvbS5hdTAeFw0wMDA2MDIwNzU2MjFaFw0wMTA2"
+ + "MDIwNzU2MjFaMIG4MQswCQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExGDAW"
+ + "BgNVBAcTD1NvdXRoIE1lbGJvdXJuZTEaMBgGA1UEChMRQ29ubmVjdCA0IFB0eSBM"
+ + "dGQxFzAVBgNVBAsTDldlYnNlcnZlciBUZWFtMR0wGwYDVQQDExR3d3cyLmNvbm5l"
+ + "Y3Q0LmNvbS5hdTEoMCYGCSqGSIb3DQEJARYZd2VibWFzdGVyQGNvbm5lY3Q0LmNv"
+ + "bS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArvDxclKAhyv7Q/Wmr2re"
+ + "Gw4XL9Cnh9e+6VgWy2AWNy/MVeXdlxzd7QAuc1eOWQkGQEiLPy5XQtTY+sBUJ3AO"
+ + "Rvd2fEVJIcjf29ey7bYua9J/vz5MG2KYo9/WCHIwqD9mmG9g0xLcfwq/s8ZJBswE"
+ + "7sb85VU+h94PTvsWOsWuKaECAwEAAaN3MHUwJAYDVR0RBB0wG4EZd2VibWFzdGVy"
+ + "QGNvbm5lY3Q0LmNvbS5hdTA6BglghkgBhvhCAQ0ELRYrbW9kX3NzbCBnZW5lcmF0"
+ + "ZWQgY3VzdG9tIHNlcnZlciBjZXJ0aWZpY2F0ZTARBglghkgBhvhCAQEEBAMCBkAw"
+ + "DQYJKoZIhvcNAQEEBQADgYEAotccfKpwSsIxM1Hae8DR7M/Rw8dg/RqOWx45HNVL"
+ + "iBS4/3N/TO195yeQKbfmzbAA2jbPVvIvGgTxPgO1MP4ZgvgRhasaa0qCJCkWvpM4"
+ + "yQf33vOiYQbpv4rTwzU8AmRlBG45WdjyNIigGV+oRc61aKCTnLq7zB8N3z1TF/bF"
+ + "5/8=");
+
+ private byte[] v2CertList = Base64.decode(
+ "MIICjTCCAfowDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMxIDAeBgNVBAoT"
+ + "F1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2VydmVy"
+ + "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5Fw05NTA1MDIwMjEyMjZaFw05NTA2MDEw"
+ + "MDAxNDlaMIIBaDAWAgUCQQAABBcNOTUwMjAxMTcyNDI2WjAWAgUCQQAACRcNOTUw"
+ + "MjEwMDIxNjM5WjAWAgUCQQAADxcNOTUwMjI0MDAxMjQ5WjAWAgUCQQAADBcNOTUw"
+ + "MjI1MDA0NjQ0WjAWAgUCQQAAGxcNOTUwMzEzMTg0MDQ5WjAWAgUCQQAAFhcNOTUw"
+ + "MzE1MTkxNjU0WjAWAgUCQQAAGhcNOTUwMzE1MTk0MDQxWjAWAgUCQQAAHxcNOTUw"
+ + "MzI0MTk0NDMzWjAWAgUCcgAABRcNOTUwMzI5MjAwNzExWjAWAgUCcgAAERcNOTUw"
+ + "MzMwMDIzNDI2WjAWAgUCQQAAIBcNOTUwNDA3MDExMzIxWjAWAgUCcgAAHhcNOTUw"
+ + "NDA4MDAwMjU5WjAWAgUCcgAAQRcNOTUwNDI4MTcxNzI0WjAWAgUCcgAAOBcNOTUw"
+ + "NDI4MTcyNzIxWjAWAgUCcgAATBcNOTUwNTAyMDIxMjI2WjANBgkqhkiG9w0BAQIF"
+ + "AAN+AHqOEJXSDejYy0UwxxrH/9+N2z5xu/if0J6qQmK92W0hW158wpJg+ovV3+wQ"
+ + "wvIEPRL2rocL0tKfAsVq1IawSJzSNgxG0lrcla3MrJBnZ4GaZDu4FutZh72MR3Gt"
+ + "JaAL3iTJHJD55kK2D/VoyY1djlsPuNh6AEgdVwFAyp0v");
+
+ private static final Object[] NULL_ARGS = new Object[] { null };
+
+ private void doFullGetInstanceTest(Class clazz, ASN1Object o1)
+ throws Exception
+ {
+ Method m;
+
+ try
+ {
+ m = clazz.getMethod("getInstance", Object.class);
+ }
+ catch (NoSuchMethodException e)
+ {
+ fail("no getInstance method found");
+ return;
+ }
+
+ ASN1Object o2 = (ASN1Object)m.invoke(clazz, NULL_ARGS);
+ if (o2 != null)
+ {
+ fail(clazz.getName() + " null failed");
+ }
+
+ o2 = (ASN1Object)m.invoke(clazz, o1);
+
+ if (!o1.equals(o2) || !clazz.isInstance(o2))
+ {
+ fail(clazz.getName() + " equality failed");
+ }
+
+ o2 = (ASN1Object)m.invoke(clazz, o1.getEncoded());
+ if (!o1.equals(o2) || !clazz.isInstance(o2))
+ {
+ fail(clazz.getName() + " encoded equality failed");
+ }
+
+ o2 = (ASN1Object)m.invoke(clazz, o1.toASN1Primitive());
+ if (!o1.equals(o2) || !clazz.isInstance(o2))
+ {
+ fail(clazz.getName() + " sequence equality failed");
+ }
+
+ try
+ {
+ m = clazz.getMethod("getInstance", ASN1TaggedObject.class, Boolean.TYPE);
+ }
+ catch (NoSuchMethodException e)
+ {
+ return;
+ }
+
+ ASN1TaggedObject t = new DERTaggedObject(true, 0, o1);
+ o2 = (ASN1Object)m.invoke(clazz, t, true);
+ if (!o1.equals(o2) || !clazz.isInstance(o2))
+ {
+ fail(clazz.getName() + " tag equality failed");
+ }
+
+ t = new DERTaggedObject(true, 0, o1.toASN1Primitive());
+ o2 = (ASN1Object)m.invoke(clazz, t, true);
+ if (!o1.equals(o2) || !clazz.isInstance(o2))
+ {
+ fail(clazz.getName() + " tag equality failed");
+ }
+
+ t = ASN1TaggedObject.getInstance(t.getEncoded());
+ o2 = (ASN1Object)m.invoke(clazz, t, true);
+ if (!o1.equals(o2) || !clazz.isInstance(o2))
+ {
+ fail(clazz.getName() + " tag equality failed");
+ }
+
+ t = new DERTaggedObject(false, 0, o1);
+ o2 = (ASN1Object)m.invoke(clazz, t, false);
+ if (!o1.equals(o2) || !clazz.isInstance(o2))
+ {
+ fail(clazz.getName() + " tag equality failed");
+ }
+
+ t = new DERTaggedObject(false, 0, o1.toASN1Primitive());
+ o2 = (ASN1Object)m.invoke(clazz, t, false);
+ if (!o1.equals(o2) || !clazz.isInstance(o2))
+ {
+ fail(clazz.getName() + " tag equality failed");
+ }
+
+ t = ASN1TaggedObject.getInstance(t.getEncoded());
+ o2 = (ASN1Object)m.invoke(clazz, t, false);
+ if (!o1.equals(o2) || !clazz.isInstance(o2))
+ {
+ fail(clazz.getName() + " tag equality failed");
+ }
+ }
+
+ public void testGetInstance()
+ throws Exception
+ {
+ doFullGetInstanceTest(DERPrintableString.class, new DERPrintableString("hello world"));
+ doFullGetInstanceTest(DERBMPString.class, new DERBMPString("hello world"));
+ doFullGetInstanceTest(DERUTF8String.class, new DERUTF8String("hello world"));
+ doFullGetInstanceTest(DERUniversalString.class, new DERUniversalString(new byte[20]));
+ doFullGetInstanceTest(DERIA5String.class, new DERIA5String("hello world"));
+ doFullGetInstanceTest(DERGeneralString.class, new DERGeneralString("hello world"));
+ doFullGetInstanceTest(DERNumericString.class, new DERNumericString("hello world"));
+ doFullGetInstanceTest(DERNumericString.class, new DERNumericString("99999", true));
+ doFullGetInstanceTest(DERT61String.class, new DERT61String("hello world"));
+ doFullGetInstanceTest(DERVisibleString.class, new DERVisibleString("hello world"));
+
+ doFullGetInstanceTest(ASN1Integer.class, new ASN1Integer(1));
+ doFullGetInstanceTest(ASN1GeneralizedTime.class, new ASN1GeneralizedTime(new Date()));
+ doFullGetInstanceTest(ASN1UTCTime.class, new ASN1UTCTime(new Date()));
+ doFullGetInstanceTest(ASN1Enumerated.class, new ASN1Enumerated(1));
+
+ CMPCertificate cmpCert = new CMPCertificate(Certificate.getInstance(cert1));
+ CertificateList crl = CertificateList.getInstance(v2CertList);
+ AttributeCertificate attributeCert = AttributeCertificate.getInstance(attrCert);
+
+ doFullGetInstanceTest(CAKeyUpdAnnContent.class, new CAKeyUpdAnnContent(cmpCert, cmpCert, cmpCert));
+
+ CertConfirmContent.getInstance(null);
+ CertifiedKeyPair.getInstance(null);
+ CertOrEncCert.getInstance(null);
+ CertRepMessage.getInstance(null);
+ doFullGetInstanceTest(CertResponse.class, new CertResponse(new ASN1Integer(1), new PKIStatusInfo(PKIStatus.granted)));
+ doFullGetInstanceTest(org.spongycastle.asn1.cmp.CertStatus.class, new org.spongycastle.asn1.cmp.CertStatus(new byte[10], BigInteger.valueOf(1), new PKIStatusInfo(PKIStatus.granted)));
+ doFullGetInstanceTest(Challenge.class, new Challenge(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE), new byte[10], new byte[10]));
+
+ doFullGetInstanceTest(CMPCertificate.class, cmpCert);
+ doFullGetInstanceTest(CRLAnnContent.class, new CRLAnnContent(crl));
+ doFullGetInstanceTest(ErrorMsgContent.class, new ErrorMsgContent(new PKIStatusInfo(PKIStatus.granted), new ASN1Integer(1), new PKIFreeText("fred")));
+ GenMsgContent.getInstance(null);
+ GenRepContent.getInstance(null);
+ InfoTypeAndValue.getInstance(null);
+ KeyRecRepContent.getInstance(null);
+ OOBCertHash.getInstance(null);
+ PBMParameter.getInstance(null);
+ PKIBody.getInstance(null);
+ PKIConfirmContent.getInstance(null);
+ PKIFreeText.getInstance(null);
+ doFullGetInstanceTest(PKIFreeText.class, new PKIFreeText("hello world"));
+ doFullGetInstanceTest(PKIFreeText.class, new PKIFreeText(new String[]{"hello", "world"}));
+ doFullGetInstanceTest(PKIFreeText.class, new PKIFreeText(new DERUTF8String[]{new DERUTF8String("hello"), new DERUTF8String("world")}));
+ PKIHeader.getInstance(null);
+ PKIMessage.getInstance(null);
+ PKIMessages.getInstance(null);
+ doFullGetInstanceTest(PKIStatusInfo.class, new PKIStatusInfo(PKIStatus.rejection, new PKIFreeText("hello world"), new PKIFailureInfo(PKIFailureInfo.badAlg)));
+ doFullGetInstanceTest(PKIStatusInfo.class, new PKIStatusInfo(PKIStatus.granted, new PKIFreeText("hello world")));
+ PKIStatus.getInstance(null);
+ PollRepContent.getInstance(null);
+ PollReqContent.getInstance(null);
+ POPODecKeyChallContent.getInstance(null);
+ POPODecKeyRespContent.getInstance(null);
+ ProtectedPart.getInstance(null);
+ RevAnnContent.getInstance(null);
+ RevDetails.getInstance(null);
+ RevRepContent.getInstance(null);
+ RevReqContent.getInstance(null);
+ Attribute.getInstance(null);
+ Attributes.getInstance(null);
+ AuthenticatedData.getInstance(null);
+ AuthenticatedData.getInstance(null);
+ AuthEnvelopedData.getInstance(null);
+ AuthEnvelopedData.getInstance(null);
+ CompressedData.getInstance(null);
+ CompressedData.getInstance(null);
+ ContentInfo.getInstance(null);
+ EncryptedContentInfo.getInstance(null);
+ EncryptedData.getInstance(null);
+ EnvelopedData.getInstance(null);
+ EnvelopedData.getInstance(null);
+ Evidence.getInstance(null);
+ IssuerAndSerialNumber.getInstance(null);
+ KEKIdentifier.getInstance(null);
+ KEKIdentifier.getInstance(null);
+ KEKRecipientInfo.getInstance(null);
+ KEKRecipientInfo.getInstance(null);
+ KeyAgreeRecipientIdentifier.getInstance(null);
+ KeyAgreeRecipientIdentifier.getInstance(null);
+ KeyAgreeRecipientInfo.getInstance(null);
+ KeyAgreeRecipientInfo.getInstance(null);
+ KeyTransRecipientInfo.getInstance(null);
+ MetaData.getInstance(null);
+ OriginatorIdentifierOrKey.getInstance(null);
+ OriginatorIdentifierOrKey.getInstance(null);
+ OriginatorInfo.getInstance(null);
+ OriginatorInfo.getInstance(null);
+ OriginatorPublicKey.getInstance(null);
+ OriginatorPublicKey.getInstance(null);
+ OtherKeyAttribute.getInstance(null);
+ OtherRecipientInfo.getInstance(null);
+ OtherRecipientInfo.getInstance(null);
+ PasswordRecipientInfo.getInstance(null);
+ PasswordRecipientInfo.getInstance(null);
+ RecipientEncryptedKey.getInstance(null);
+ RecipientIdentifier.getInstance(null);
+ RecipientInfo.getInstance(null);
+ RecipientKeyIdentifier.getInstance(null);
+ RecipientKeyIdentifier.getInstance(null);
+ SignedData.getInstance(null);
+ SignerIdentifier.getInstance(null);
+ SignerInfo.getInstance(null);
+ Time.getInstance(null);
+ Time.getInstance(null);
+ TimeStampAndCRL.getInstance(null);
+ TimeStampedData.getInstance(null);
+ TimeStampTokenEvidence.getInstance(null);
+ AttributeTypeAndValue.getInstance(null);
+
+ doFullGetInstanceTest(CertId.class, new CertId(new GeneralName(new X500Name("CN=Test")), BigInteger.valueOf(1)));
+
+
+ CertReqMessages.getInstance(null);
+ CertReqMsg.getInstance(null);
+ CertRequest.getInstance(null);
+ CertTemplate.getInstance(null);
+ Controls.getInstance(null);
+ EncKeyWithID.getInstance(null);
+ EncryptedKey.getInstance(null);
+ EncryptedValue.getInstance(null);
+ OptionalValidity.getInstance(null);
+ PKIArchiveOptions.getInstance(null);
+ PKIPublicationInfo.getInstance(null);
+ PKMACValue.getInstance(null);
+ PKMACValue.getInstance(null);
+ POPOPrivKey.getInstance(null);
+ POPOSigningKeyInput.getInstance(null);
+ POPOSigningKey.getInstance(null);
+ POPOSigningKey.getInstance(null);
+ ProofOfPossession.getInstance(null);
+ SinglePubInfo.getInstance(null);
+ ECGOST3410ParamSetParameters.getInstance(null);
+ ECGOST3410ParamSetParameters.getInstance(null);
+ GOST28147Parameters.getInstance(null);
+ GOST28147Parameters.getInstance(null);
+ GOST3410ParamSetParameters.getInstance(null);
+ GOST3410ParamSetParameters.getInstance(null);
+ GOST3410PublicKeyAlgParameters.getInstance(null);
+ GOST3410PublicKeyAlgParameters.getInstance(null);
+ CertificateBody.getInstance(null);
+ CVCertificate.getInstance(null);
+ CVCertificateRequest.getInstance(null);
+ PublicKeyDataObject.getInstance(null);
+ UnsignedInteger.getInstance(null);
+ CommitmentTypeIndication.getInstance(null);
+ CommitmentTypeQualifier.getInstance(null);
+
+ OcspIdentifier ocspIdentifier = new OcspIdentifier(new ResponderID(new X500Name("CN=Test")), new ASN1GeneralizedTime(new Date()));
+ CrlListID crlListID = new CrlListID(new CrlValidatedID[]{new CrlValidatedID(new OtherHash(new byte[20]))});
+ OcspListID ocspListID = new OcspListID(new OcspResponsesID[] { new OcspResponsesID(ocspIdentifier) });
+ OtherRevRefs otherRevRefs = new OtherRevRefs(new ASN1ObjectIdentifier("1.2.1"), new DERSequence());
+ OtherRevVals otherRevVals = new OtherRevVals(new ASN1ObjectIdentifier("1.2.1"), new DERSequence());
+ CrlOcspRef crlOcspRef = new CrlOcspRef(crlListID, ocspListID, otherRevRefs);
+ doFullGetInstanceTest(CompleteRevocationRefs.class, new CompleteRevocationRefs(new CrlOcspRef[]{crlOcspRef, crlOcspRef}));
+
+ doFullGetInstanceTest(CrlIdentifier.class, new CrlIdentifier(new X500Name("CN=Test"), new ASN1UTCTime(new Date()), BigInteger.valueOf(1)));
+
+
+ doFullGetInstanceTest(CrlListID.class, crlListID);
+ doFullGetInstanceTest(CrlOcspRef.class, crlOcspRef);
+ doFullGetInstanceTest(CrlValidatedID.class, new CrlValidatedID(new OtherHash(new byte[20])));
+ doFullGetInstanceTest(OcspIdentifier.class, ocspIdentifier);
+ doFullGetInstanceTest(OcspListID.class, ocspListID);
+ doFullGetInstanceTest(OcspResponsesID.class, new OcspResponsesID(ocspIdentifier));
+
+ OtherHashAlgAndValue otherHashAlgAndValue = new OtherHashAlgAndValue(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE), new DEROctetString(new byte[10]));
+ doFullGetInstanceTest(OtherHashAlgAndValue.class, otherHashAlgAndValue);
+ OtherHash.getInstance(null);
+ doFullGetInstanceTest(OtherRevRefs.class, otherRevRefs);
+ doFullGetInstanceTest(OtherRevVals.class, otherRevVals);
+ doFullGetInstanceTest(RevocationValues.class, new RevocationValues(new CertificateList[]{crl}, null, otherRevVals));
+
+ SignaturePolicyId signaturePolicyId = new SignaturePolicyId(new ASN1ObjectIdentifier("1.2.1"), otherHashAlgAndValue);
+ doFullGetInstanceTest(SignaturePolicyIdentifier.class, new SignaturePolicyIdentifier());
+ doFullGetInstanceTest(SignaturePolicyIdentifier.class, new SignaturePolicyIdentifier(signaturePolicyId));
+ doFullGetInstanceTest(SignaturePolicyId.class, signaturePolicyId);
+ doFullGetInstanceTest(SignerAttribute.class, new SignerAttribute(new org.spongycastle.asn1.x509.Attribute[]{new org.spongycastle.asn1.x509.Attribute(new ASN1ObjectIdentifier("1.2.1"), new DERSet())}));
+ doFullGetInstanceTest(SignerAttribute.class, new SignerAttribute(attributeCert));
+
+ ASN1EncodableVector postalAddr = new ASN1EncodableVector();
+
+ postalAddr.add(new DERUTF8String("line 1"));
+ postalAddr.add(new DERUTF8String("line 2"));
+
+ doFullGetInstanceTest(SignerLocation.class, new SignerLocation(new DERUTF8String("AU"), new DERUTF8String("Melbourne"), new DERSequence(postalAddr)));
+ doFullGetInstanceTest(SigPolicyQualifierInfo.class, new SigPolicyQualifierInfo(new ASN1ObjectIdentifier("1.2.1"), new DERSequence()));
+ SigPolicyQualifiers.getInstance(null);
+ SPuri.getInstance(null);
+ Vector v = new Vector();
+
+ v.add(Integers.valueOf(1));
+ v.add(BigInteger.valueOf(2));
+ NoticeReference noticeReference = new NoticeReference("SC", v);
+ doFullGetInstanceTest(SPUserNotice.class, new SPUserNotice(noticeReference, new DisplayText("hello world")));
+ ContentHints.getInstance(null);
+ ContentIdentifier.getInstance(null);
+ ESSCertID.getInstance(null);
+ ESSCertIDv2.getInstance(null);
+ OtherCertID.getInstance(null);
+ OtherSigningCertificate.getInstance(null);
+ SigningCertificate.getInstance(null);
+ SigningCertificateV2.getInstance(null);
+ CscaMasterList.getInstance(null);
+ DataGroupHash.getInstance(null);
+ LDSSecurityObject.getInstance(null);
+ LDSVersionInfo.getInstance(null);
+ CAST5CBCParameters.getInstance(null);
+ IDEACBCPar.getInstance(null);
+ PublicKeyAndChallenge.getInstance(null);
+ BasicOCSPResponse.getInstance(null);
+ BasicOCSPResponse.getInstance(null);
+
+ doFullGetInstanceTest(CertID.class, new CertID(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE), new DEROctetString(new byte[1]), new DEROctetString(new byte[1]), new ASN1Integer(1)));
+
+ CertStatus.getInstance(null);
+ CertStatus.getInstance(null);
+ CrlID.getInstance(null);
+ OCSPRequest.getInstance(null);
+ OCSPRequest.getInstance(null);
+ OCSPResponse.getInstance(null);
+ OCSPResponse.getInstance(null);
+ OCSPResponseStatus.getInstance(null);
+ Request.getInstance(null);
+ Request.getInstance(null);
+ ResponderID.getInstance(null);
+ ResponderID.getInstance(null);
+ ResponseBytes.getInstance(null);
+ ResponseBytes.getInstance(null);
+ ResponseData.getInstance(null);
+ ResponseData.getInstance(null);
+ RevokedInfo.getInstance(null);
+ RevokedInfo.getInstance(null);
+ Signature.getInstance(null);
+ Signature.getInstance(null);
+ SingleResponse.getInstance(null);
+ SingleResponse.getInstance(null);
+ TBSRequest.getInstance(null);
+ TBSRequest.getInstance(null);
+ Attribute.getInstance(null);
+ AuthenticatedSafe.getInstance(null);
+ CertificationRequestInfo.getInstance(null);
+ CertificationRequest.getInstance(null);
+ ContentInfo.getInstance(null);
+ DHParameter.getInstance(null);
+ EncryptedData.getInstance(null);
+ EncryptedPrivateKeyInfo.getInstance(null);
+ AlgorithmIdentifier.getInstance(null);
+ IssuerAndSerialNumber.getInstance(null);
+ MacData.getInstance(null);
+ PBEParameter.getInstance(null);
+ PBES2Parameters.getInstance(null);
+ PBKDF2Params.getInstance(null);
+ Pfx.getInstance(null);
+ PKCS12PBEParams.getInstance(null);
+ PrivateKeyInfo.getInstance(null);
+ PrivateKeyInfo.getInstance(null);
+ RC2CBCParameter.getInstance(null);
+ RSAESOAEPparams.getInstance(null);
+ RSAPrivateKey.getInstance(null);
+ RSAPrivateKey.getInstance(null);
+ RSAPublicKey.getInstance(null);
+ RSAPublicKey.getInstance(null);
+ RSASSAPSSparams.getInstance(null);
+ SafeBag.getInstance(null);
+ SignedData.getInstance(null);
+ SignerInfo.getInstance(null);
+ ECPrivateKey.getInstance(null);
+ SMIMECapabilities.getInstance(null);
+ SMIMECapability.getInstance(null);
+ Accuracy.getInstance(null);
+ MessageImprint.getInstance(null);
+ TimeStampReq.getInstance(null);
+ TimeStampResp.getInstance(null);
+ TSTInfo.getInstance(null);
+ AttributeTypeAndValue.getInstance(null);
+ DirectoryString.getInstance(null);
+ DirectoryString.getInstance(null);
+ RDN.getInstance(null);
+ X500Name.getInstance(null);
+ X500Name.getInstance(null);
+ AccessDescription.getInstance(null);
+ AlgorithmIdentifier.getInstance(null);
+ AlgorithmIdentifier.getInstance(null);
+ AttCertIssuer.getInstance(null);
+ AttCertIssuer.getInstance(null);
+ AttCertValidityPeriod.getInstance(null);
+ AttributeCertificateInfo.getInstance(null);
+ AttributeCertificateInfo.getInstance(null);
+ AttributeCertificate.getInstance(null);
+ Attribute.getInstance(null);
+ AuthorityInformationAccess.getInstance(null);
+ AuthorityKeyIdentifier.getInstance(null);
+ AuthorityKeyIdentifier.getInstance(null);
+ BasicConstraints.getInstance(null);
+ BasicConstraints.getInstance(null);
+ Certificate.getInstance(null);
+ Certificate.getInstance(null);
+ CertificateList.getInstance(null);
+ CertificateList.getInstance(null);
+ CertificatePair.getInstance(null);
+ CertificatePolicies.getInstance(null);
+ CertificatePolicies.getInstance(null);
+ CRLDistPoint.getInstance(null);
+ CRLDistPoint.getInstance(null);
+ CRLNumber.getInstance(null);
+ CRLReason.getInstance(null);
+ DigestInfo.getInstance(null);
+ DigestInfo.getInstance(null);
+ DisplayText.getInstance(null);
+ DisplayText.getInstance(null);
+ DistributionPoint.getInstance(null);
+ DistributionPoint.getInstance(null);
+ DistributionPointName.getInstance(null);
+ DistributionPointName.getInstance(null);
+ DSAParameter.getInstance(null);
+ DSAParameter.getInstance(null);
+ ExtendedKeyUsage.getInstance(null);
+ ExtendedKeyUsage.getInstance(null);
+ Extensions.getInstance(null);
+ Extensions.getInstance(null);
+ GeneralName.getInstance(null);
+ GeneralName.getInstance(null);
+ GeneralNames.getInstance(null);
+ GeneralNames.getInstance(null);
+
+ GeneralSubtree generalSubtree = new GeneralSubtree(new GeneralName(new X500Name("CN=Test")));
+ ASN1ObjectIdentifier algOid = new ASN1ObjectIdentifier("1.2.1");
+ ObjectDigestInfo objectDigestInfo = new ObjectDigestInfo(ObjectDigestInfo.otherObjectDigest, algOid, new AlgorithmIdentifier(algOid), new byte[20]);
+
+ doFullGetInstanceTest(GeneralSubtree.class, generalSubtree);
+ doFullGetInstanceTest(Holder.class, new Holder(objectDigestInfo));
+ IetfAttrSyntax.getInstance(null);
+ IssuerSerial.getInstance(null);
+ IssuerSerial.getInstance(null);
+ IssuingDistributionPoint.getInstance(null);
+ IssuingDistributionPoint.getInstance(null);
+ DERBitString.getInstance(null);
+
+ v.clear();
+ v.add(generalSubtree);
+
+ doFullGetInstanceTest(NameConstraints.class, new NameConstraints(null, null));
+ doFullGetInstanceTest(NoticeReference.class, noticeReference);
+ doFullGetInstanceTest(ObjectDigestInfo.class, objectDigestInfo);
+
+ PolicyInformation.getInstance(null);
+ PolicyMappings.getInstance(null);
+ PolicyQualifierInfo.getInstance(null);
+ PrivateKeyUsagePeriod.getInstance(null);
+ doFullGetInstanceTest(RoleSyntax.class, new RoleSyntax(new GeneralNames(new GeneralName(new X500Name("CN=Test"))), new GeneralName(GeneralName.uniformResourceIdentifier, "http://bc")));
+ RSAPublicKeyStructure.getInstance(null);
+ RSAPublicKeyStructure.getInstance(null);
+ SubjectDirectoryAttributes.getInstance(null);
+ SubjectKeyIdentifier.getInstance(null);
+ SubjectKeyIdentifier.getInstance(null);
+ SubjectPublicKeyInfo.getInstance(null);
+ SubjectPublicKeyInfo.getInstance(null);
+ TargetInformation.getInstance(null);
+ Target.getInstance(null);
+ Targets.getInstance(null);
+ TBSCertificate.getInstance(null);
+ TBSCertificate.getInstance(null);
+ TBSCertificateStructure.getInstance(null);
+ TBSCertificateStructure.getInstance(null);
+ TBSCertList.CRLEntry.getInstance(null);
+ TBSCertList.getInstance(null);
+ TBSCertList.getInstance(null);
+ Time.getInstance(null);
+ Time.getInstance(null);
+ doFullGetInstanceTest(UserNotice.class, new UserNotice(noticeReference, "hello world"));
+ V2Form.getInstance(null);
+ V2Form.getInstance(null);
+ X509CertificateStructure.getInstance(null);
+ X509CertificateStructure.getInstance(null);
+ X509Extensions.getInstance(null);
+ X509Extensions.getInstance(null);
+ X509Name.getInstance(null);
+ X509Name.getInstance(null);
+ DHDomainParameters.getInstance(null);
+ DHDomainParameters.getInstance(null);
+ DHPublicKey.getInstance(null);
+ DHPublicKey.getInstance(null);
+ DHValidationParms.getInstance(null);
+ DHValidationParms.getInstance(null);
+ X962Parameters.getInstance(null);
+ X962Parameters.getInstance(null);
+ X9ECParameters.getInstance(null);
+ MQVuserKeyingMaterial.getInstance(null);
+ MQVuserKeyingMaterial.getInstance(null);
+ CertHash.getInstance(null);
+ RequestedCertificate.getInstance(null);
+ RequestedCertificate.getInstance(null);
+ AdditionalInformationSyntax.getInstance(null);
+ Admissions.getInstance(null);
+ AdmissionSyntax.getInstance(null);
+ DeclarationOfMajority.getInstance(null);
+ MonetaryLimit.getInstance(null);
+ NamingAuthority.getInstance(null);
+ NamingAuthority.getInstance(null);
+ ProcurationSyntax.getInstance(null);
+ ProfessionInfo.getInstance(null);
+ Restriction.getInstance(null);
+ BiometricData.getInstance(null);
+ Iso4217CurrencyCode.getInstance(null);
+ MonetaryValue.getInstance(null);
+ QCStatement.getInstance(null);
+ SemanticsInformation.getInstance(null);
+ TypeOfBiometricData.getInstance(null);
+ NameOrPseudonym.getInstance(null);
+ PersonalData.getInstance(null);
+ }
+
+ public String getName()
+ {
+ return "GetInstanceNullTest";
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/InputStreamTest.java b/core/src/test/java/org/spongycastle/asn1/test/InputStreamTest.java
new file mode 100644
index 00000000..000455d8
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/InputStreamTest.java
@@ -0,0 +1,75 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.util.test.SimpleTest;
+
+public class InputStreamTest
+ extends SimpleTest
+{
+ private static final byte[] outOfBoundsLength = new byte[] { (byte)0x30, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff };
+ private static final byte[] negativeLength = new byte[] { (byte)0x30, (byte)0x84, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff };
+ private static final byte[] outsideLimitLength = new byte[] { (byte)0x30, (byte)0x83, (byte)0x0f, (byte)0xff, (byte)0xff };
+
+
+ public String getName()
+ {
+ return "InputStream";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ ASN1InputStream aIn = new ASN1InputStream(outOfBoundsLength);
+
+ try
+ {
+ aIn.readObject();
+ fail("out of bounds length not detected.");
+ }
+ catch (IOException e)
+ {
+ if (!e.getMessage().startsWith("DER length more than 4 bytes"))
+ {
+ fail("wrong exception: " + e.getMessage());
+ }
+ }
+
+ aIn = new ASN1InputStream(negativeLength);
+
+ try
+ {
+ aIn.readObject();
+ fail("negative length not detected.");
+ }
+ catch (IOException e)
+ {
+ if (!e.getMessage().equals("corrupted stream - negative length found"))
+ {
+ fail("wrong exception: " + e.getMessage());
+ }
+ }
+
+ aIn = new ASN1InputStream(outsideLimitLength);
+
+ try
+ {
+ aIn.readObject();
+ fail("outside limit length not detected.");
+ }
+ catch (IOException e)
+ {
+ if (!e.getMessage().equals("corrupted stream - out of bounds length found"))
+ {
+ fail("wrong exception: " + e.getMessage());
+ }
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new InputStreamTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/Iso4217CurrencyCodeUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/Iso4217CurrencyCodeUnitTest.java
new file mode 100644
index 00000000..1c197804
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/Iso4217CurrencyCodeUnitTest.java
@@ -0,0 +1,142 @@
+package org.spongycastle.asn1.test;
+
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.x509.qualified.Iso4217CurrencyCode;
+import org.spongycastle.util.test.SimpleTest;
+
+public class Iso4217CurrencyCodeUnitTest
+ extends SimpleTest
+{
+ private static final String ALPHABETIC_CURRENCY_CODE = "AUD";
+ private static final int NUMERIC_CURRENCY_CODE = 1;
+
+ public String getName()
+ {
+ return "Iso4217CurrencyCode";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ //
+ // alphabetic
+ //
+ Iso4217CurrencyCode cc = new Iso4217CurrencyCode(ALPHABETIC_CURRENCY_CODE);
+
+ checkNumeric(cc, ALPHABETIC_CURRENCY_CODE);
+
+ cc = Iso4217CurrencyCode.getInstance(cc);
+
+ checkNumeric(cc, ALPHABETIC_CURRENCY_CODE);
+
+ ASN1Primitive obj = cc.toASN1Object();
+
+ cc = Iso4217CurrencyCode.getInstance(obj);
+
+ checkNumeric(cc, ALPHABETIC_CURRENCY_CODE);
+
+ //
+ // numeric
+ //
+ cc = new Iso4217CurrencyCode(NUMERIC_CURRENCY_CODE);
+
+ checkNumeric(cc, NUMERIC_CURRENCY_CODE);
+
+ cc = Iso4217CurrencyCode.getInstance(cc);
+
+ checkNumeric(cc, NUMERIC_CURRENCY_CODE);
+
+ obj = cc.toASN1Object();
+
+ cc = Iso4217CurrencyCode.getInstance(obj);
+
+ checkNumeric(cc, NUMERIC_CURRENCY_CODE);
+
+ cc = Iso4217CurrencyCode.getInstance(null);
+
+ if (cc != null)
+ {
+ fail("null getInstance() failed.");
+ }
+
+ try
+ {
+ Iso4217CurrencyCode.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ new Iso4217CurrencyCode("ABCD");
+
+ fail("constructor failed to detect out of range currencycode.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ new Iso4217CurrencyCode(0);
+
+ fail("constructor failed to detect out of range small numeric code.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ new Iso4217CurrencyCode(1000);
+
+ fail("constructor failed to detect out of range large numeric code.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkNumeric(
+ Iso4217CurrencyCode cc,
+ String code)
+ {
+ if (!cc.isAlphabetic())
+ {
+ fail("non-alphabetic code found when one expected.");
+ }
+
+ if (!cc.getAlphabetic().equals(code))
+ {
+ fail("string codes don't match.");
+ }
+ }
+
+ private void checkNumeric(
+ Iso4217CurrencyCode cc,
+ int code)
+ {
+ if (cc.isAlphabetic())
+ {
+ fail("alphabetic code found when one not expected.");
+ }
+
+ if (cc.getNumeric() != code)
+ {
+ fail("numeric codes don't match.");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new Iso4217CurrencyCodeUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/IssuingDistributionPointUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/IssuingDistributionPointUnitTest.java
new file mode 100644
index 00000000..6453d707
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/IssuingDistributionPointUnitTest.java
@@ -0,0 +1,122 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.x509.DistributionPointName;
+import org.spongycastle.asn1.x509.GeneralName;
+import org.spongycastle.asn1.x509.GeneralNames;
+import org.spongycastle.asn1.x509.IssuingDistributionPoint;
+import org.spongycastle.asn1.x509.ReasonFlags;
+import org.spongycastle.asn1.x509.X509Name;
+import org.spongycastle.util.test.SimpleTest;
+
+public class IssuingDistributionPointUnitTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "IssuingDistributionPoint";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ DistributionPointName name = new DistributionPointName(
+ new GeneralNames(new GeneralName(new X509Name("cn=test"))));
+ ReasonFlags reasonFlags = new ReasonFlags(ReasonFlags.cACompromise);
+
+ checkPoint(6, name, true, true, reasonFlags, true, true);
+
+ checkPoint(2, name, false, false, reasonFlags, false, false);
+
+ checkPoint(0, null, false, false, null, false, false);
+
+ try
+ {
+ IssuingDistributionPoint.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkPoint(
+ int size,
+ DistributionPointName distributionPoint,
+ boolean onlyContainsUserCerts,
+ boolean onlyContainsCACerts,
+ ReasonFlags onlySomeReasons,
+ boolean indirectCRL,
+ boolean onlyContainsAttributeCerts)
+ throws IOException
+ {
+ IssuingDistributionPoint point = new IssuingDistributionPoint(distributionPoint, onlyContainsUserCerts, onlyContainsCACerts, onlySomeReasons, indirectCRL, onlyContainsAttributeCerts);
+
+ checkValues(point, distributionPoint, onlyContainsUserCerts, onlyContainsCACerts, onlySomeReasons, indirectCRL, onlyContainsAttributeCerts);
+
+ ASN1Sequence seq = ASN1Sequence.getInstance(ASN1Primitive.fromByteArray(point.getEncoded()));
+
+ if (seq.size() != size)
+ {
+ fail("size mismatch");
+ }
+
+ point = IssuingDistributionPoint.getInstance(seq);
+
+ checkValues(point, distributionPoint, onlyContainsUserCerts, onlyContainsCACerts, onlySomeReasons, indirectCRL, onlyContainsAttributeCerts);
+ }
+
+ private void checkValues(IssuingDistributionPoint point, DistributionPointName distributionPoint, boolean onlyContainsUserCerts, boolean onlyContainsCACerts, ReasonFlags onlySomeReasons, boolean indirectCRL, boolean onlyContainsAttributeCerts)
+ {
+ if (point.onlyContainsUserCerts() != onlyContainsUserCerts)
+ {
+ fail("mismatch on onlyContainsUserCerts");
+ }
+
+ if (point.onlyContainsCACerts() != onlyContainsCACerts)
+ {
+ fail("mismatch on onlyContainsCACerts");
+ }
+
+ if (point.isIndirectCRL() != indirectCRL)
+ {
+ fail("mismatch on indirectCRL");
+ }
+
+ if (point.onlyContainsAttributeCerts() != onlyContainsAttributeCerts)
+ {
+ fail("mismatch on onlyContainsAttributeCerts");
+ }
+
+ if (!isEquiv(onlySomeReasons, point.getOnlySomeReasons()))
+ {
+ fail("mismatch on onlySomeReasons");
+ }
+
+ if (!isEquiv(distributionPoint, point.getDistributionPoint()))
+ {
+ fail("mismatch on distributionPoint");
+ }
+ }
+
+ private boolean isEquiv(Object o1, Object o2)
+ {
+ if (o1 == null)
+ {
+ return o2 == null;
+ }
+
+ return o1.equals(o2);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new IssuingDistributionPointUnitTest());
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/asn1/test/KeyUsageTest.java b/core/src/test/java/org/spongycastle/asn1/test/KeyUsageTest.java
new file mode 100644
index 00000000..2de2f3d5
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/KeyUsageTest.java
@@ -0,0 +1,55 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.x509.KeyUsage;
+import org.spongycastle.util.test.SimpleTest;
+
+public class KeyUsageTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "KeyUsage";
+ }
+
+ public void performTest()
+ throws IOException
+ {
+ BitStringConstantTester.testFlagValueCorrect(0, KeyUsage.digitalSignature);
+ BitStringConstantTester.testFlagValueCorrect(1, KeyUsage.nonRepudiation);
+ BitStringConstantTester.testFlagValueCorrect(2, KeyUsage.keyEncipherment);
+ BitStringConstantTester.testFlagValueCorrect(3, KeyUsage.dataEncipherment);
+ BitStringConstantTester.testFlagValueCorrect(4, KeyUsage.keyAgreement);
+ BitStringConstantTester.testFlagValueCorrect(5, KeyUsage.keyCertSign);
+ BitStringConstantTester.testFlagValueCorrect(6, KeyUsage.cRLSign);
+ BitStringConstantTester.testFlagValueCorrect(7, KeyUsage.encipherOnly);
+ BitStringConstantTester.testFlagValueCorrect(8, KeyUsage.decipherOnly);
+
+ if (!new KeyUsage(KeyUsage.keyCertSign).hasUsages(KeyUsage.keyCertSign))
+ {
+ fail("usages bit test failed 1");
+ }
+
+ if (new KeyUsage(KeyUsage.cRLSign).hasUsages(KeyUsage.keyCertSign))
+ {
+ fail("usages bit test failed 2");
+ }
+
+ if (!new KeyUsage(KeyUsage.cRLSign | KeyUsage.decipherOnly).hasUsages(KeyUsage.cRLSign | KeyUsage.decipherOnly))
+ {
+ fail("usages bit test failed 3");
+ }
+
+ if (new KeyUsage(KeyUsage.cRLSign | KeyUsage.decipherOnly).hasUsages(KeyUsage.cRLSign | KeyUsage.decipherOnly | KeyUsage.keyCertSign))
+ {
+ fail("usages bit test failed 4");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new KeyUsageTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/LDSSecurityObjectUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/LDSSecurityObjectUnitTest.java
new file mode 100644
index 00000000..0cbb4476
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/LDSSecurityObjectUnitTest.java
@@ -0,0 +1,214 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+import java.util.Random;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.icao.DataGroupHash;
+import org.spongycastle.asn1.icao.LDSSecurityObject;
+import org.spongycastle.asn1.icao.LDSVersionInfo;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.util.test.SimpleTest;
+
+public class LDSSecurityObjectUnitTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "LDSSecurityObject";
+ }
+
+ private byte[] generateHash()
+ {
+ Random rand = new Random();
+ byte[] bytes = new byte[20];
+
+ for (int i = 0; i != bytes.length; i++)
+ {
+ bytes[i] = (byte)rand.nextInt();
+ }
+
+ return bytes;
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ AlgorithmIdentifier algoId = new AlgorithmIdentifier("1.3.14.3.2.26");
+ DataGroupHash[] datas = new DataGroupHash[2];
+
+ datas[0] = new DataGroupHash(1, new DEROctetString(generateHash()));
+ datas[1] = new DataGroupHash(2, new DEROctetString(generateHash()));
+
+ LDSSecurityObject so = new LDSSecurityObject(algoId, datas);
+
+ checkConstruction(so, algoId, datas);
+
+ LDSVersionInfo versionInfo = new LDSVersionInfo("Hello", "world");
+
+ so = new LDSSecurityObject(algoId, datas, versionInfo);
+
+ checkConstruction(so, algoId, datas, versionInfo);
+
+ try
+ {
+ LDSSecurityObject.getInstance(null);
+ }
+ catch (Exception e)
+ {
+ fail("getInstance() failed to handle null.");
+ }
+
+ try
+ {
+ LDSSecurityObject.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ LDSSecurityObject.getInstance(new DERSequence(v));
+
+ fail("constructor failed to detect empty sequence.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ new LDSSecurityObject(algoId, new DataGroupHash[1]);
+
+ fail("constructor failed to detect small DataGroupHash array.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ new LDSSecurityObject(algoId, new DataGroupHash[LDSSecurityObject.ub_DataGroups + 1]);
+
+ fail("constructor failed to out of bounds DataGroupHash array.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ LDSSecurityObject so,
+ AlgorithmIdentifier digestAlgorithmIdentifier,
+ DataGroupHash[] datagroupHash)
+ throws IOException
+ {
+ checkStatement(so, digestAlgorithmIdentifier, datagroupHash, null);
+
+ so = LDSSecurityObject.getInstance(so);
+
+ checkStatement(so, digestAlgorithmIdentifier, datagroupHash, null);
+
+ ASN1InputStream aIn = new ASN1InputStream(so.toASN1Object().getEncoded());
+
+ ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
+
+ so = LDSSecurityObject.getInstance(seq);
+
+ checkStatement(so, digestAlgorithmIdentifier, datagroupHash, null);
+ }
+
+ private void checkConstruction(
+ LDSSecurityObject so,
+ AlgorithmIdentifier digestAlgorithmIdentifier,
+ DataGroupHash[] datagroupHash,
+ LDSVersionInfo versionInfo)
+ throws IOException
+ {
+ if (so.getVersion() != 1)
+ {
+ fail("version number not 1");
+ }
+
+ checkStatement(so, digestAlgorithmIdentifier, datagroupHash, versionInfo);
+
+ so = LDSSecurityObject.getInstance(so);
+
+ checkStatement(so, digestAlgorithmIdentifier, datagroupHash, versionInfo);
+
+ ASN1InputStream aIn = new ASN1InputStream(so.toASN1Object().getEncoded());
+
+ ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
+
+ so = LDSSecurityObject.getInstance(seq);
+
+ checkStatement(so, digestAlgorithmIdentifier, datagroupHash, versionInfo);
+ }
+
+ private void checkStatement(
+ LDSSecurityObject so,
+ AlgorithmIdentifier digestAlgorithmIdentifier,
+ DataGroupHash[] datagroupHash,
+ LDSVersionInfo versionInfo)
+ {
+ if (digestAlgorithmIdentifier != null)
+ {
+ if (!so.getDigestAlgorithmIdentifier().equals(digestAlgorithmIdentifier))
+ {
+ fail("ids don't match.");
+ }
+ }
+ else if (so.getDigestAlgorithmIdentifier() != null)
+ {
+ fail("digest algorithm Id found when none expected.");
+ }
+
+ if (datagroupHash != null)
+ {
+ DataGroupHash[] datas = so.getDatagroupHash();
+
+ for (int i = 0; i != datas.length; i++)
+ {
+ if (!datagroupHash[i].equals(datas[i]))
+ {
+ fail("name registration authorities don't match.");
+ }
+ }
+ }
+ else if (so.getDatagroupHash() != null)
+ {
+ fail("data hash groups found when none expected.");
+ }
+
+ if (versionInfo != null)
+ {
+ if (!versionInfo.equals(so.getVersionInfo()))
+ {
+ fail("versionInfo doesn't match");
+ }
+ }
+ else if (so.getVersionInfo() != null)
+ {
+ fail("version info found when none expected.");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new LDSSecurityObjectUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/MiscTest.java b/core/src/test/java/org/spongycastle/asn1/test/MiscTest.java
new file mode 100644
index 00000000..3f127479
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/MiscTest.java
@@ -0,0 +1,113 @@
+package org.spongycastle.asn1.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1OutputStream;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.misc.CAST5CBCParameters;
+import org.spongycastle.asn1.misc.IDEACBCPar;
+import org.spongycastle.asn1.misc.NetscapeCertType;
+import org.spongycastle.asn1.misc.NetscapeRevocationURL;
+import org.spongycastle.asn1.misc.VerisignCzagExtension;
+import org.spongycastle.util.encoders.Base64;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+public class MiscTest
+ implements Test
+{
+ private boolean isSameAs(
+ byte[] a,
+ byte[] b)
+ {
+ if (a.length != b.length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i != a.length; i++)
+ {
+ if (a[i] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public TestResult perform()
+ {
+ byte[] testIv = { 1, 2, 3, 4, 5, 6, 7, 8 };
+
+ ASN1Encodable[] values = {
+ new CAST5CBCParameters(testIv, 128),
+ new NetscapeCertType(NetscapeCertType.smime),
+ new VerisignCzagExtension(new DERIA5String("hello")),
+ new IDEACBCPar(testIv),
+ new NetscapeRevocationURL(new DERIA5String("http://test"))
+ };
+
+ byte[] data = Base64.decode("MA4ECAECAwQFBgcIAgIAgAMCBSAWBWhlbGxvMAoECAECAwQFBgcIFgtodHRwOi8vdGVzdA==");
+
+ try
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ for (int i = 0; i != values.length; i++)
+ {
+ aOut.writeObject(values[i]);
+ }
+
+ ASN1Primitive[] readValues = new ASN1Primitive[values.length];
+
+ if (!isSameAs(bOut.toByteArray(), data))
+ {
+ return new SimpleTestResult(false, getName() + ": Failed data check");
+ }
+
+ ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
+ ASN1InputStream aIn = new ASN1InputStream(bIn);
+
+ for (int i = 0; i != values.length; i++)
+ {
+ ASN1Primitive o = aIn.readObject();
+ if (!values[i].equals(o))
+ {
+ return new SimpleTestResult(false, getName() + ": Failed equality test for " + o);
+ }
+
+ if (o.hashCode() != values[i].hashCode())
+ {
+ return new SimpleTestResult(false, getName() + ": Failed hashCode test for " + o);
+ }
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+ catch (Exception e)
+ {
+ return new SimpleTestResult(false, getName() + ": Failed - exception " + e.toString(), e);
+ }
+ }
+
+ public String getName()
+ {
+ return "Misc";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ MiscTest test = new MiscTest();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/MonetaryLimitUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/MonetaryLimitUnitTest.java
new file mode 100644
index 00000000..02a59b4b
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/MonetaryLimitUnitTest.java
@@ -0,0 +1,85 @@
+package org.spongycastle.asn1.test;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.isismtt.x509.MonetaryLimit;
+
+import java.io.IOException;
+
+public class MonetaryLimitUnitTest
+ extends ASN1UnitTest
+{
+ public String getName()
+ {
+ return "MonetaryLimit";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ String currency = "AUD";
+ int amount = 1;
+ int exponent = 2;
+
+ MonetaryLimit limit = new MonetaryLimit(currency, amount, exponent);
+
+ checkConstruction(limit, currency, amount, exponent);
+
+ limit = MonetaryLimit.getInstance(null);
+
+ if (limit != null)
+ {
+ fail("null getInstance() failed.");
+ }
+
+ try
+ {
+ MonetaryLimit.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ MonetaryLimit limit,
+ String currency,
+ int amount,
+ int exponent)
+ throws IOException
+ {
+ checkValues(limit, currency, amount, exponent);
+
+ limit = MonetaryLimit.getInstance(limit);
+
+ checkValues(limit, currency, amount, exponent);
+
+ ASN1InputStream aIn = new ASN1InputStream(limit.toASN1Object().getEncoded());
+
+ ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
+
+ limit = MonetaryLimit.getInstance(seq);
+
+ checkValues(limit, currency, amount, exponent);
+ }
+
+ private void checkValues(
+ MonetaryLimit limit,
+ String currency,
+ int amount,
+ int exponent)
+ {
+ checkMandatoryField("currency", currency, limit.getCurrency());
+ checkMandatoryField("amount", amount, limit.getAmount().intValue());
+ checkMandatoryField("exponent", exponent, limit.getExponent().intValue());
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new MonetaryLimitUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/MonetaryValueUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/MonetaryValueUnitTest.java
new file mode 100644
index 00000000..541dc497
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/MonetaryValueUnitTest.java
@@ -0,0 +1,88 @@
+package org.spongycastle.asn1.test;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.x509.qualified.Iso4217CurrencyCode;
+import org.spongycastle.asn1.x509.qualified.MonetaryValue;
+import org.spongycastle.util.test.SimpleTest;
+
+public class MonetaryValueUnitTest
+ extends SimpleTest
+{
+ private static final int TEST_AMOUNT = 100;
+ private static final int ZERO_EXPONENT = 0;
+
+ private static final String CURRENCY_CODE = "AUD";
+
+ public String getName()
+ {
+ return "MonetaryValue";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ MonetaryValue mv = new MonetaryValue(new Iso4217CurrencyCode(CURRENCY_CODE), TEST_AMOUNT, ZERO_EXPONENT);
+
+ checkValues(mv, TEST_AMOUNT, ZERO_EXPONENT);
+
+ mv = MonetaryValue.getInstance(mv);
+
+ checkValues(mv, TEST_AMOUNT, ZERO_EXPONENT);
+
+ ASN1InputStream aIn = new ASN1InputStream(mv.toASN1Object().getEncoded());
+
+ ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
+
+ mv = MonetaryValue.getInstance(seq);
+
+ checkValues(mv, TEST_AMOUNT, ZERO_EXPONENT);
+
+ mv = MonetaryValue.getInstance(null);
+
+ if (mv != null)
+ {
+ fail("null getInstance() failed.");
+ }
+
+ try
+ {
+ MonetaryValue.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkValues(
+ MonetaryValue mv,
+ int amount,
+ int exponent)
+ {
+ if (mv.getAmount().intValue() != amount)
+ {
+ fail("amounts don't match.");
+ }
+
+ if (mv.getExponent().intValue() != exponent)
+ {
+ fail("exponents don't match.");
+ }
+
+ Iso4217CurrencyCode cc = mv.getCurrency();
+
+ if (!cc.getAlphabetic().equals(CURRENCY_CODE))
+ {
+ fail("currency code wrong");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new MonetaryValueUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/NameOrPseudonymUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/NameOrPseudonymUnitTest.java
new file mode 100644
index 00000000..fdab08f6
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/NameOrPseudonymUnitTest.java
@@ -0,0 +1,108 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1String;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x500.DirectoryString;
+import org.spongycastle.asn1.x509.sigi.NameOrPseudonym;
+
+public class NameOrPseudonymUnitTest
+ extends ASN1UnitTest
+{
+ public String getName()
+ {
+ return "NameOrPseudonym";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ String pseudonym = "pseudonym";
+ DirectoryString surname = new DirectoryString("surname");
+ ASN1Sequence givenName = new DERSequence(new DirectoryString("givenName"));
+
+ NameOrPseudonym id = new NameOrPseudonym(pseudonym);
+
+ checkConstruction(id, pseudonym, null, null);
+
+ id = new NameOrPseudonym(surname, givenName);
+
+ checkConstruction(id, null, surname, givenName);
+
+ id = NameOrPseudonym.getInstance(null);
+
+ if (id != null)
+ {
+ fail("null getInstance() failed.");
+ }
+
+ try
+ {
+ NameOrPseudonym.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ NameOrPseudonym id,
+ String pseudonym,
+ DirectoryString surname,
+ ASN1Sequence givenName)
+ throws IOException
+ {
+ checkValues(id, pseudonym, surname, givenName);
+
+ id = NameOrPseudonym.getInstance(id);
+
+ checkValues(id, pseudonym, surname, givenName);
+
+ ASN1InputStream aIn = new ASN1InputStream(id.toASN1Object().getEncoded());
+
+ if (surname != null)
+ {
+ ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
+
+ id = NameOrPseudonym.getInstance(seq);
+ }
+ else
+ {
+ ASN1String s = (ASN1String)aIn.readObject();
+
+ id = NameOrPseudonym.getInstance(s);
+ }
+
+ checkValues(id, pseudonym, surname, givenName);
+ }
+
+ private void checkValues(
+ NameOrPseudonym id,
+ String pseudonym,
+ DirectoryString surname,
+ ASN1Sequence givenName)
+ {
+
+ if (surname != null)
+ {
+ checkMandatoryField("surname", surname, id.getSurname());
+ checkMandatoryField("givenName", givenName, new DERSequence(id.getGivenName()[0]));
+ }
+ else
+ {
+ checkOptionalField("pseudonym", new DirectoryString(pseudonym), id.getPseudonym());
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new NameOrPseudonymUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/NamingAuthorityUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/NamingAuthorityUnitTest.java
new file mode 100644
index 00000000..cf6d5a37
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/NamingAuthorityUnitTest.java
@@ -0,0 +1,99 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.isismtt.x509.NamingAuthority;
+import org.spongycastle.asn1.x500.DirectoryString;
+
+public class NamingAuthorityUnitTest
+ extends ASN1UnitTest
+{
+ public String getName()
+ {
+ return "NamingAuthority";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ ASN1ObjectIdentifier namingAuthorityID = new ASN1ObjectIdentifier("1.2.3");
+ String namingAuthorityURL = "url";
+ DirectoryString namingAuthorityText = new DirectoryString("text");
+
+ NamingAuthority auth = new NamingAuthority(namingAuthorityID, namingAuthorityURL, namingAuthorityText);
+
+ checkConstruction(auth, namingAuthorityID, namingAuthorityURL, namingAuthorityText);
+
+ auth = new NamingAuthority(null, namingAuthorityURL, namingAuthorityText);
+
+ checkConstruction(auth, null, namingAuthorityURL, namingAuthorityText);
+
+ auth = new NamingAuthority(namingAuthorityID, null, namingAuthorityText);
+
+ checkConstruction(auth, namingAuthorityID, null, namingAuthorityText);
+
+ auth = new NamingAuthority(namingAuthorityID, namingAuthorityURL, null);
+
+ checkConstruction(auth, namingAuthorityID, namingAuthorityURL, null);
+
+ auth = NamingAuthority.getInstance(null);
+
+ if (auth != null)
+ {
+ fail("null getInstance() failed.");
+ }
+
+ try
+ {
+ NamingAuthority.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ NamingAuthority auth,
+ ASN1ObjectIdentifier namingAuthorityID,
+ String namingAuthorityURL,
+ DirectoryString namingAuthorityText)
+ throws IOException
+ {
+ checkValues(auth, namingAuthorityID, namingAuthorityURL, namingAuthorityText);
+
+ auth = NamingAuthority.getInstance(auth);
+
+ checkValues(auth, namingAuthorityID, namingAuthorityURL, namingAuthorityText);
+
+ ASN1InputStream aIn = new ASN1InputStream(auth.toASN1Object().getEncoded());
+
+ ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
+
+ auth = NamingAuthority.getInstance(seq);
+
+ checkValues(auth, namingAuthorityID, namingAuthorityURL, namingAuthorityText);
+ }
+
+ private void checkValues(
+ NamingAuthority auth,
+ ASN1ObjectIdentifier namingAuthorityId,
+ String namingAuthorityURL,
+ DirectoryString namingAuthorityText)
+ {
+ checkOptionalField("namingAuthorityId", namingAuthorityId, auth.getNamingAuthorityId());
+ checkOptionalField("namingAuthorityURL", namingAuthorityURL, auth.getNamingAuthorityUrl());
+ checkOptionalField("namingAuthorityText", namingAuthorityText, auth.getNamingAuthorityText());
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new NamingAuthorityUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/NetscapeCertTypeTest.java b/core/src/test/java/org/spongycastle/asn1/test/NetscapeCertTypeTest.java
new file mode 100644
index 00000000..9d3b0993
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/NetscapeCertTypeTest.java
@@ -0,0 +1,34 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.misc.NetscapeCertType;
+import org.spongycastle.util.test.SimpleTest;
+
+public class NetscapeCertTypeTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "NetscapeCertType";
+ }
+
+ public void performTest()
+ throws IOException
+ {
+ BitStringConstantTester.testFlagValueCorrect(0, NetscapeCertType.sslClient);
+ BitStringConstantTester.testFlagValueCorrect(1, NetscapeCertType.sslServer);
+ BitStringConstantTester.testFlagValueCorrect(2, NetscapeCertType.smime);
+ BitStringConstantTester.testFlagValueCorrect(3, NetscapeCertType.objectSigning);
+ BitStringConstantTester.testFlagValueCorrect(4, NetscapeCertType.reserved);
+ BitStringConstantTester.testFlagValueCorrect(5, NetscapeCertType.sslCA);
+ BitStringConstantTester.testFlagValueCorrect(6, NetscapeCertType.smimeCA);
+ BitStringConstantTester.testFlagValueCorrect(7, NetscapeCertType.objectSigningCA);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new NetscapeCertTypeTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/OCSPTest.java b/core/src/test/java/org/spongycastle/asn1/test/OCSPTest.java
new file mode 100644
index 00000000..15b330ce
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/OCSPTest.java
@@ -0,0 +1,193 @@
+package org.spongycastle.asn1.test;
+
+import java.io.ByteArrayInputStream;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.ocsp.BasicOCSPResponse;
+import org.spongycastle.asn1.ocsp.OCSPRequest;
+import org.spongycastle.asn1.ocsp.OCSPResponse;
+import org.spongycastle.asn1.ocsp.ResponseBytes;
+import org.spongycastle.util.encoders.Base64;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+import org.spongycastle.util.test.SimpleTestResult;
+
+public class OCSPTest
+ implements Test
+{
+ private byte[] unsignedReq = Base64.decode(
+ "MEIwQDA+MDwwOjAJBgUrDgMCGgUABBRDb9GODnq7lRhSkEqw4XX24huERwQUkY4j"
+ + "a6eKuDlkVP9hRgkEvIWqHPECAQE=");
+
+ private byte[] signedReq = Base64.decode(
+ "MIIC9jBAMD4wPDA6MAkGBSsOAwIaBQAEFENv0Y4OeruVGFKQSrDhdfbiG4RHBBTc"
+ + "Mr1fP+mZAxbF2ZdehWxn6mtAngIBAaCCArAwggKsMA0GCSqGSIb3DQEBBQUAA4GB"
+ + "AAzHBm4nL5AcRQB3Jkz7ScNeZF+GbRZ0p4kBDTnqi3IeESuso12yJhpqqyijdnj5"
+ + "gd4/GsSAgdluLHyYZ6wgozV7G9MDXCnFnG4PBUW05HaVX81JYAp+amVyU0NOgNrG"
+ + "90npVBsHb0o+UlkxNgMiEbSkp/TeGb6YURsYKhmwp7BgoIICFTCCAhEwggINMIIB"
+ + "dqADAgECAgEBMA0GCSqGSIb3DQEBBAUAMCUxFjAUBgNVBAoTDUJvdW5jeSBDYXN0"
+ + "bGUxCzAJBgNVBAYTAkFVMB4XDTA0MTAyNDEzNDc0M1oXDTA1MDIwMTEzNDc0M1ow"
+ + "JTEWMBQGA1UEChMNQm91bmN5IENhc3RsZTELMAkGA1UEBhMCQVUwgZ8wDQYJKoZI"
+ + "hvcNAQEBBQADgY0AMIGJAoGBAJBmLeIzthMHUeTkOeJ76iBxcMHY31o/i3a9VT12"
+ + "y2FcS/ejJmeUCMTdtwl5alOwXY66vF4DyT1VU/nJG3mHpSoqq7qrMXOIFGcXg1Wf"
+ + "oJRrQgTOLdQ6bod7i9ME/EjEJy70orh0nVS7NGcu0R5TjcbLde2J5zxjb/W9wqfy"
+ + "RovJAgMBAAGjTTBLMB0GA1UdDgQWBBTcMr1fP+mZAxbF2ZdehWxn6mtAnjAfBgNV"
+ + "HSMEGDAWgBTcMr1fP+mZAxbF2ZdehWxn6mtAnjAJBgNVHRMEAjAAMA0GCSqGSIb3"
+ + "DQEBBAUAA4GBAF/4EH1KkNrNxocJPIp7lThmG1KIVYESIadowMowrbok46ESofRF"
+ + "OIPku07W+e1Y1Y1KXLIiPMG3IGwrBrn04iLsbbBUiN37BcC/VyT4xKJ2MYscGjKL"
+ + "ua/9bU0lOyeTRAwqb8towWRd5lLYAI3RQ7dhStUTFp3Vqd803PJ/cpR6");
+
+ private byte[] response = Base64.decode(
+ "MIIFnAoBAKCCBZUwggWRBgkrBgEFBQcwAQEEggWCMIIFfjCCARehgZ8wgZwx"
+ + "CzAJBgNVBAYTAklOMRcwFQYDVQQIEw5BbmRocmEgcHJhZGVzaDESMBAGA1UE"
+ + "BxMJSHlkZXJhYmFkMQwwCgYDVQQKEwNUQ1MxDDAKBgNVBAsTA0FUQzEeMBwG"
+ + "A1UEAxMVVENTLUNBIE9DU1AgUmVzcG9uZGVyMSQwIgYJKoZIhvcNAQkBFhVv"
+ + "Y3NwQHRjcy1jYS50Y3MuY28uaW4YDzIwMDMwNDAyMTIzNDU4WjBiMGAwOjAJ"
+ + "BgUrDgMCGgUABBRs07IuoCWNmcEl1oHwIak1BPnX8QQUtGyl/iL9WJ1VxjxF"
+ + "j0hAwJ/s1AcCAQKhERgPMjAwMjA4MjkwNzA5MjZaGA8yMDAzMDQwMjEyMzQ1"
+ + "OFowDQYJKoZIhvcNAQEFBQADgYEAfbN0TCRFKdhsmvOdUoiJ+qvygGBzDxD/"
+ + "VWhXYA+16AphHLIWNABR3CgHB3zWtdy2j7DJmQ/R7qKj7dUhWLSqclAiPgFt"
+ + "QQ1YvSJAYfEIdyHkxv4NP0LSogxrumANcDyC9yt/W9yHjD2ICPBIqCsZLuLk"
+ + "OHYi5DlwWe9Zm9VFwCGgggPMMIIDyDCCA8QwggKsoAMCAQICAQYwDQYJKoZI"
+ + "hvcNAQEFBQAwgZQxFDASBgNVBAMTC1RDUy1DQSBPQ1NQMSYwJAYJKoZIhvcN"
+ + "AQkBFhd0Y3MtY2FAdGNzLWNhLnRjcy5jby5pbjEMMAoGA1UEChMDVENTMQww"
+ + "CgYDVQQLEwNBVEMxEjAQBgNVBAcTCUh5ZGVyYWJhZDEXMBUGA1UECBMOQW5k"
+ + "aHJhIHByYWRlc2gxCzAJBgNVBAYTAklOMB4XDTAyMDgyOTA3MTE0M1oXDTAz"
+ + "MDgyOTA3MTE0M1owgZwxCzAJBgNVBAYTAklOMRcwFQYDVQQIEw5BbmRocmEg"
+ + "cHJhZGVzaDESMBAGA1UEBxMJSHlkZXJhYmFkMQwwCgYDVQQKEwNUQ1MxDDAK"
+ + "BgNVBAsTA0FUQzEeMBwGA1UEAxMVVENTLUNBIE9DU1AgUmVzcG9uZGVyMSQw"
+ + "IgYJKoZIhvcNAQkBFhVvY3NwQHRjcy1jYS50Y3MuY28uaW4wgZ8wDQYJKoZI"
+ + "hvcNAQEBBQADgY0AMIGJAoGBAM+XWW4caMRv46D7L6Bv8iwtKgmQu0SAybmF"
+ + "RJiz12qXzdvTLt8C75OdgmUomxp0+gW/4XlTPUqOMQWv463aZRv9Ust4f8MH"
+ + "EJh4ekP/NS9+d8vEO3P40ntQkmSMcFmtA9E1koUtQ3MSJlcs441JjbgUaVnm"
+ + "jDmmniQnZY4bU3tVAgMBAAGjgZowgZcwDAYDVR0TAQH/BAIwADALBgNVHQ8E"
+ + "BAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwkwNgYIKwYBBQUHAQEEKjAoMCYG"
+ + "CCsGAQUFBzABhhpodHRwOi8vMTcyLjE5LjQwLjExMDo3NzAwLzAtBgNVHR8E"
+ + "JjAkMCKgIKAehhxodHRwOi8vMTcyLjE5LjQwLjExMC9jcmwuY3JsMA0GCSqG"
+ + "SIb3DQEBBQUAA4IBAQB6FovM3B4VDDZ15o12gnADZsIk9fTAczLlcrmXLNN4"
+ + "PgmqgnwF0Ymj3bD5SavDOXxbA65AZJ7rBNAguLUo+xVkgxmoBH7R2sBxjTCc"
+ + "r07NEadxM3HQkt0aX5XYEl8eRoifwqYAI9h0ziZfTNes8elNfb3DoPPjqq6V"
+ + "mMg0f0iMS4W8LjNPorjRB+kIosa1deAGPhq0eJ8yr0/s2QR2/WFD5P4aXc8I"
+ + "KWleklnIImS3zqiPrq6tl2Bm8DZj7vXlTOwmraSQxUwzCKwYob1yGvNOUQTq"
+ + "pG6jxn7jgDawHU1+WjWQe4Q34/pWeGLysxTraMa+Ug9kPe+jy/qRX2xwvKBZ");
+
+ private boolean isSameAs(
+ byte[] a,
+ byte[] b)
+ {
+ if (a.length != b.length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i != a.length; i++)
+ {
+ if (a[i] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private TestResult unsignedRequest()
+ {
+ try
+ {
+ ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(unsignedReq));
+ OCSPRequest req = OCSPRequest.getInstance(aIn.readObject());
+
+ if (!isSameAs(req.getEncoded(), unsignedReq))
+ {
+ return new SimpleTestResult(false, getName() + ": OCSP unsigned request failed to re-encode");
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+ catch (Exception e)
+ {
+ return new SimpleTestResult(false, getName() + ": failed unsigned exception - " + e.toString(), e);
+ }
+ }
+
+ private TestResult signedRequest()
+ {
+ try
+ {
+ ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(signedReq));
+ OCSPRequest req = OCSPRequest.getInstance(aIn.readObject());
+
+ if (!isSameAs(req.getEncoded(), signedReq))
+ {
+ return new SimpleTestResult(false, getName() + ": OCSP signed request failed to re-encode");
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+ catch (Exception e)
+ {
+ return new SimpleTestResult(false, getName() + ": failed signed exception - " + e.toString(), e);
+ }
+ }
+
+ private TestResult response()
+ {
+ try
+ {
+ ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(response));
+ OCSPResponse resp = OCSPResponse.getInstance(aIn.readObject());
+ ResponseBytes rBytes = ResponseBytes.getInstance(resp.getResponseBytes());
+
+ aIn = new ASN1InputStream(new ByteArrayInputStream(rBytes.getResponse().getOctets()));
+
+ BasicOCSPResponse bResp = BasicOCSPResponse.getInstance(aIn.readObject());
+
+ resp = new OCSPResponse(resp.getResponseStatus(), new ResponseBytes(rBytes.getResponseType(), new DEROctetString(bResp.getEncoded())));
+
+ if (!isSameAs(resp.getEncoded(), response))
+ {
+ return new SimpleTestResult(false, getName() + ": OCSP response failed to re-encode");
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+ catch (Exception e)
+ {
+ return new SimpleTestResult(false, getName() + ": failed response exception - " + e.toString(), e);
+ }
+ }
+
+ public TestResult perform()
+ {
+ TestResult res = unsignedRequest();
+
+ if (!res.isSuccessful())
+ {
+ return res;
+ }
+
+ res = signedRequest();
+ if (!res.isSuccessful())
+ {
+ return res;
+ }
+
+ return response();
+ }
+
+ public String getName()
+ {
+ return "OCSP";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ OCSPTest test = new OCSPTest();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/OIDTest.java b/core/src/test/java/org/spongycastle/asn1/test/OIDTest.java
new file mode 100644
index 00000000..bc5a287c
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/OIDTest.java
@@ -0,0 +1,165 @@
+package org.spongycastle.asn1.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OutputStream;
+import org.spongycastle.asn1.DEROutputStream;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+
+/**
+ * X.690 test example
+ */
+public class OIDTest
+ extends SimpleTest
+{
+ byte[] req1 = Hex.decode("0603813403");
+ byte[] req2 = Hex.decode("06082A36FFFFFFDD6311");
+
+ public String getName()
+ {
+ return "OID";
+ }
+
+ private void recodeCheck(
+ String oid,
+ byte[] enc)
+ throws IOException
+ {
+ ByteArrayInputStream bIn = new ByteArrayInputStream(enc);
+ ASN1InputStream aIn = new ASN1InputStream(bIn);
+
+ ASN1ObjectIdentifier o = new ASN1ObjectIdentifier(oid);
+ ASN1ObjectIdentifier encO = (ASN1ObjectIdentifier)aIn.readObject();
+
+ if (!o.equals(encO))
+ {
+ fail("oid ID didn't match", o, encO);
+ }
+
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ DEROutputStream dOut = new DEROutputStream(bOut);
+
+ dOut.writeObject(o);
+
+ byte[] bytes = bOut.toByteArray();
+
+ if (bytes.length != enc.length)
+ {
+ fail("failed length test");
+ }
+
+ for (int i = 0; i != enc.length; i++)
+ {
+ if (bytes[i] != enc[i])
+ {
+ fail("failed comparison test", new String(Hex.encode(enc)), new String(Hex.encode(bytes)));
+ }
+ }
+ }
+
+ private void validOidCheck(
+ String oid)
+ throws IOException
+ {
+ ASN1ObjectIdentifier o = new ASN1ObjectIdentifier(oid);
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ aOut.writeObject(o);
+
+ ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
+ ASN1InputStream aIn = new ASN1InputStream(bIn);
+
+ o = (ASN1ObjectIdentifier)aIn.readObject();
+
+ if (!o.getId().equals(oid))
+ {
+ fail("failed oid check for " + oid);
+ }
+ }
+
+ private void invalidOidCheck(
+ String oid)
+ {
+ try
+ {
+ new ASN1ObjectIdentifier(oid);
+ fail("failed to catch bad oid: " + oid);
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void branchCheck(String stem, String branch)
+ {
+ String expected = stem + "." + branch;
+ String actual = new ASN1ObjectIdentifier(stem).branch(branch).getId();
+
+ if (!expected.equals(actual))
+ {
+ fail("failed 'branch' check for " + stem + "/" + branch);
+ }
+ }
+
+ private void onCheck(String stem, String test, boolean expected)
+ {
+ if (expected != new ASN1ObjectIdentifier(test).on(new ASN1ObjectIdentifier(stem)))
+ {
+ fail("failed 'on' check for " + stem + "/" + test);
+ }
+ }
+
+ public void performTest()
+ throws IOException
+ {
+ recodeCheck("2.100.3", req1);
+ recodeCheck("1.2.54.34359733987.17", req2);
+
+ validOidCheck(PKCSObjectIdentifiers.pkcs_9_at_contentType.getId());
+ validOidCheck("0.1");
+ validOidCheck("1.1.127.32512.8323072.2130706432.545460846592.139637976727552.35747322042253312.9151314442816847872");
+ validOidCheck("1.2.123.12345678901.1.1.1");
+ validOidCheck("2.25.196556539987194312349856245628873852187.1");
+
+ invalidOidCheck("0");
+ invalidOidCheck("1");
+ invalidOidCheck("2");
+ invalidOidCheck("3.1");
+ invalidOidCheck("..1");
+ invalidOidCheck("192.168.1.1");
+ invalidOidCheck(".123452");
+ invalidOidCheck("1.");
+ invalidOidCheck("1.345.23.34..234");
+ invalidOidCheck("1.345.23.34.234.");
+ invalidOidCheck(".12.345.77.234");
+ invalidOidCheck(".12.345.77.234.");
+ invalidOidCheck("1.2.3.4.A.5");
+ invalidOidCheck("1,2");
+
+ branchCheck("1.1", "2.2");
+
+ onCheck("1.1", "1.1", false);
+ onCheck("1.1", "1.2", false);
+ onCheck("1.1", "1.2.1", false);
+ onCheck("1.1", "2.1", false);
+ onCheck("1.1", "1.11", false);
+ onCheck("1.12", "1.1.2", false);
+ onCheck("1.1", "1.1.1", true);
+ onCheck("1.1", "1.1.2", true);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new OIDTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/ObjectIdentifierTest.java b/core/src/test/java/org/spongycastle/asn1/test/ObjectIdentifierTest.java
new file mode 100644
index 00000000..ed0a6023
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/ObjectIdentifierTest.java
@@ -0,0 +1,38 @@
+package org.spongycastle.asn1.test;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.util.test.SimpleTest;
+import org.spongycastle.util.test.TestResult;
+
+public class ObjectIdentifierTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "ObjectIdentifier";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ // exercise the object cache
+ for (int i = 0; i < 1024; i++)
+ {
+ for (int j = 0; j != 17000; j++)
+ {
+ byte[] encoded = new ASN1ObjectIdentifier("1.1." + i + "." + j).getEncoded();
+
+ ASN1ObjectIdentifier.getInstance(encoded);
+ }
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ ObjectIdentifierTest test = new ObjectIdentifierTest();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/OctetStringTest.java b/core/src/test/java/org/spongycastle/asn1/test/OctetStringTest.java
new file mode 100644
index 00000000..ea20d91c
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/OctetStringTest.java
@@ -0,0 +1,203 @@
+package org.spongycastle.asn1.test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetStringParser;
+import org.spongycastle.asn1.ASN1SequenceParser;
+import org.spongycastle.asn1.ASN1StreamParser;
+import org.spongycastle.asn1.BEROctetStringGenerator;
+import org.spongycastle.asn1.BERSequenceGenerator;
+import org.spongycastle.asn1.BERTags;
+import org.spongycastle.asn1.DERSequenceGenerator;
+import org.spongycastle.asn1.cms.CMSObjectIdentifiers;
+import org.spongycastle.asn1.cms.CompressedDataParser;
+import org.spongycastle.asn1.cms.ContentInfoParser;
+
+public class OctetStringTest
+ extends TestCase
+{
+ public void testReadingWriting()
+ throws Exception
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ BEROctetStringGenerator octGen = new BEROctetStringGenerator(bOut);
+
+ OutputStream out = octGen.getOctetOutputStream();
+
+ out.write(new byte[] { 1, 2, 3, 4 });
+ out.write(new byte[4]);
+
+ out.close();
+
+ ASN1StreamParser aIn = new ASN1StreamParser(bOut.toByteArray());
+
+ ASN1OctetStringParser s = (ASN1OctetStringParser)aIn.readObject();
+
+ InputStream in = s.getOctetStream();
+ int count = 0;
+
+ while (in.read() >= 0)
+ {
+ count++;
+ }
+
+ assertEquals(8, count);
+ }
+
+ public void testReadingWritingZeroInLength()
+ throws Exception
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ BEROctetStringGenerator octGen = new BEROctetStringGenerator(bOut);
+
+ OutputStream out = octGen.getOctetOutputStream();
+
+ out.write(new byte[] { 1, 2, 3, 4 });
+ out.write(new byte[512]); // forces a zero to appear in length
+
+ out.close();
+
+ ASN1StreamParser aIn = new ASN1StreamParser(bOut.toByteArray());
+
+ ASN1OctetStringParser s = (ASN1OctetStringParser)aIn.readObject();
+
+ InputStream in = s.getOctetStream();
+ int count = 0;
+
+ while (in.read() >= 0)
+ {
+ count++;
+ }
+
+ assertEquals(516, count);
+ }
+
+ public void testReadingWritingNested()
+ throws Exception
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ BERSequenceGenerator sGen = new BERSequenceGenerator(bOut);
+ BEROctetStringGenerator octGen = new BEROctetStringGenerator(sGen.getRawOutputStream());
+
+ OutputStream out = octGen.getOctetOutputStream();
+
+ BERSequenceGenerator inSGen = new BERSequenceGenerator(out);
+
+ BEROctetStringGenerator inOctGen = new BEROctetStringGenerator(inSGen.getRawOutputStream());
+
+ OutputStream inOut = inOctGen.getOctetOutputStream();
+
+ inOut.write(new byte[] { 1, 2, 3, 4 });
+ inOut.write(new byte[10]);
+
+ inOut.close();
+
+ inSGen.close();
+
+ out.close();
+
+ sGen.close();
+
+ ASN1StreamParser aIn = new ASN1StreamParser(bOut.toByteArray());
+
+ ASN1SequenceParser sq = (ASN1SequenceParser)aIn.readObject();
+
+ ASN1OctetStringParser s = (ASN1OctetStringParser)sq.readObject();
+
+ ASN1StreamParser aIn2 = new ASN1StreamParser(s.getOctetStream());
+
+ ASN1SequenceParser sq2 = (ASN1SequenceParser)aIn2.readObject();
+
+ ASN1OctetStringParser inS = (ASN1OctetStringParser)sq2.readObject();
+
+ InputStream in = inS.getOctetStream();
+ int count = 0;
+
+ while (in.read() >= 0)
+ {
+ count++;
+ }
+
+ assertEquals(14, count);
+ }
+
+ public void testNestedStructure()
+ throws Exception
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ BERSequenceGenerator sGen = new BERSequenceGenerator(bOut);
+
+ sGen.addObject(new ASN1ObjectIdentifier(CMSObjectIdentifiers.compressedData.getId()));
+
+ BERSequenceGenerator cGen = new BERSequenceGenerator(sGen.getRawOutputStream(), 0, true);
+
+ cGen.addObject(new ASN1Integer(0));
+
+ //
+ // AlgorithmIdentifier
+ //
+ DERSequenceGenerator algGen = new DERSequenceGenerator(cGen.getRawOutputStream());
+
+ algGen.addObject(new ASN1ObjectIdentifier("1.2"));
+
+ algGen.close();
+
+ //
+ // Encapsulated ContentInfo
+ //
+ BERSequenceGenerator eiGen = new BERSequenceGenerator(cGen.getRawOutputStream());
+
+ eiGen.addObject(new ASN1ObjectIdentifier("1.1"));
+
+ BEROctetStringGenerator octGen = new BEROctetStringGenerator(eiGen.getRawOutputStream(), 0, true);
+
+ //
+ // output containing zeroes
+ //
+ OutputStream out = octGen.getOctetOutputStream();
+
+ out.write(new byte[] { 1, 2, 3, 4 });
+ out.write(new byte[4]);
+ out.write(new byte[20]);
+
+ out.close();
+ eiGen.close();
+ cGen.close();
+ sGen.close();
+
+ //
+ // reading back
+ //
+ ASN1StreamParser aIn = new ASN1StreamParser(bOut.toByteArray());
+
+ ContentInfoParser cp = new ContentInfoParser((ASN1SequenceParser)aIn.readObject());
+
+ CompressedDataParser comData = new CompressedDataParser((ASN1SequenceParser)cp.getContent(BERTags.SEQUENCE));
+ ContentInfoParser content = comData.getEncapContentInfo();
+
+ ASN1OctetStringParser bytes = (ASN1OctetStringParser)content.getContent(BERTags.OCTET_STRING);
+
+ InputStream in = bytes.getOctetStream();
+ int count = 0;
+
+ while (in.read() >= 0)
+ {
+ count++;
+ }
+
+ assertEquals(28, count);
+ }
+
+ public static Test suite()
+ {
+ return new TestSuite(OctetStringTest.class);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/OtherCertIDUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/OtherCertIDUnitTest.java
new file mode 100644
index 00000000..2e6a3b23
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/OtherCertIDUnitTest.java
@@ -0,0 +1,97 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ess.OtherCertID;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.GeneralName;
+import org.spongycastle.asn1.x509.GeneralNames;
+import org.spongycastle.asn1.x509.IssuerSerial;
+import org.spongycastle.asn1.x509.X509Name;
+
+public class OtherCertIDUnitTest
+ extends ASN1UnitTest
+{
+ public String getName()
+ {
+ return "OtherCertID";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ AlgorithmIdentifier algId = new AlgorithmIdentifier(new ASN1ObjectIdentifier("1.2.2.3"));
+ byte[] digest = new byte[20];
+ IssuerSerial issuerSerial = new IssuerSerial(new GeneralNames(new GeneralName(new X509Name("CN=test"))), new ASN1Integer(1));
+
+ OtherCertID certID = new OtherCertID(algId, digest);
+
+ checkConstruction(certID, algId, digest, null);
+
+ certID = new OtherCertID(algId, digest, issuerSerial);
+
+ checkConstruction(certID, algId, digest, issuerSerial);
+
+ certID = OtherCertID.getInstance(null);
+
+ if (certID != null)
+ {
+ fail("null getInstance() failed.");
+ }
+
+ try
+ {
+ OtherCertID.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ OtherCertID certID,
+ AlgorithmIdentifier algId,
+ byte[] digest,
+ IssuerSerial issuerSerial)
+ throws IOException
+ {
+ checkValues(certID, algId, digest, issuerSerial);
+
+ certID = OtherCertID.getInstance(certID);
+
+ checkValues(certID, algId, digest, issuerSerial);
+
+ ASN1InputStream aIn = new ASN1InputStream(certID.toASN1Object().getEncoded());
+
+ ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
+
+ certID = OtherCertID.getInstance(seq);
+
+ checkValues(certID, algId, digest, issuerSerial);
+ }
+
+ private void checkValues(
+ OtherCertID certID,
+ AlgorithmIdentifier algId,
+ byte[] digest,
+ IssuerSerial issuerSerial)
+ {
+ checkMandatoryField("algorithmHash", algId, certID.getAlgorithmHash());
+ checkMandatoryField("certHash", digest, certID.getCertHash());
+
+ checkOptionalField("issuerSerial", issuerSerial, certID.getIssuerSerial());
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new OtherCertIDUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/OtherSigningCertificateUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/OtherSigningCertificateUnitTest.java
new file mode 100644
index 00000000..96c67256
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/OtherSigningCertificateUnitTest.java
@@ -0,0 +1,86 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ess.OtherCertID;
+import org.spongycastle.asn1.ess.OtherSigningCertificate;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+
+public class OtherSigningCertificateUnitTest
+ extends ASN1UnitTest
+{
+ public String getName()
+ {
+ return "OtherSigningCertificate";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ AlgorithmIdentifier algId = new AlgorithmIdentifier(new ASN1ObjectIdentifier("1.2.2.3"));
+ byte[] digest = new byte[20];
+ OtherCertID otherCertID = new OtherCertID(algId, digest);
+
+ OtherSigningCertificate otherCert = new OtherSigningCertificate(otherCertID);
+
+ checkConstruction(otherCert, otherCertID);
+
+ otherCert = OtherSigningCertificate.getInstance(null);
+
+ if (otherCert != null)
+ {
+ fail("null getInstance() failed.");
+ }
+
+ try
+ {
+ OtherCertID.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ OtherSigningCertificate otherCert,
+ OtherCertID otherCertID)
+ throws IOException
+ {
+ checkValues(otherCert, otherCertID);
+
+ otherCert = OtherSigningCertificate.getInstance(otherCert);
+
+ checkValues(otherCert, otherCertID);
+
+ ASN1InputStream aIn = new ASN1InputStream(otherCert.toASN1Object().getEncoded());
+
+ ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
+
+ otherCert = OtherSigningCertificate.getInstance(seq);
+
+ checkValues(otherCert, otherCertID);
+ }
+
+ private void checkValues(
+ OtherSigningCertificate otherCert,
+ OtherCertID otherCertID)
+ {
+ if (otherCert.getCerts().length != 1)
+ {
+ fail("getCerts() length wrong");
+ }
+ checkMandatoryField("getCerts()[0]", otherCertID, otherCert.getCerts()[0]);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new OtherSigningCertificateUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/PKCS10Test.java b/core/src/test/java/org/spongycastle/asn1/test/PKCS10Test.java
new file mode 100644
index 00000000..5aaff0bb
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/PKCS10Test.java
@@ -0,0 +1,101 @@
+package org.spongycastle.asn1.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROutputStream;
+import org.spongycastle.asn1.pkcs.CertificationRequest;
+import org.spongycastle.util.encoders.Base64;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+public class PKCS10Test
+ implements Test
+{
+ byte[] req1 = Base64.decode(
+ "MIHoMIGTAgEAMC4xDjAMBgNVBAMTBVRlc3QyMQ8wDQYDVQQKEwZBbmFUb20xCzAJBgNVBAYTAlNF"
+ + "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALlEt31Tzt2MlcOljvacJgzQVhmlMoqAOgqJ9Pgd3Gux"
+ + "Z7/WcIlgW4QCB7WZT21O1YoghwBhPDMcNGrHei9kHQkCAwEAAaAAMA0GCSqGSIb3DQEBBQUAA0EA"
+ + "NDEI4ecNtJ3uHwGGlitNFq9WxcoZ0djbQJ5hABMotav6gtqlrwKXY2evaIrsNwkJtNdwwH18aQDU"
+ + "KCjOuBL38Q==");
+
+ byte[] req2 = Base64.decode(
+ "MIIB6TCCAVICAQAwgagxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRQwEgYDVQQH"
+ + "EwtTYW50YSBDbGFyYTEMMAoGA1UEChMDQUJCMVEwTwYDVQQLHEhQAAAAAAAAAG8AAAAAAAAAdwAA"
+ + "AAAAAABlAAAAAAAAAHIAAAAAAAAAIAAAAAAAAABUAAAAAAAAABxIAAAAAAAARAAAAAAAAAAxDTAL"
+ + "BgNVBAMTBGJsdWUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANETRZ+6occCOrFxNhfKIp4C"
+ + "mMkxwhBNb7TnnahpbM9O0r4hrBPcfYuL7u9YX/jN0YNUP+/CiT39HhSe/bikaBPDEyNsl988I8vX"
+ + "piEdgxYq/+LTgGHbjRsRYCkPtmzwBbuBldNF8bV7pu0v4UScSsExmGqqDlX1TbPU8KkPU1iTAgMB"
+ + "AAGgADANBgkqhkiG9w0BAQQFAAOBgQAFbrs9qUwh93CtETk7DeUD5HcdCnxauo1bck44snSV6MZV"
+ + "OCIGaYu1501kmhEvAtVVRr6SEHwimfQDDIjnrWwYsEr/DT6tkTZAbfRd3qUu3iKjT0H0vlUZp0hJ"
+ + "66mINtBM84uZFBfoXiWY8M3FuAnGmvy6ah/dYtJorTxLKiGkew==");
+
+ public String getName()
+ {
+ return "PKCS10";
+ }
+
+ public TestResult pkcs10Test(
+ String testName,
+ byte[] req)
+ {
+ try
+ {
+ ByteArrayInputStream bIn = new ByteArrayInputStream(req);
+ ASN1InputStream aIn = new ASN1InputStream(bIn);
+
+ CertificationRequest r = new CertificationRequest((ASN1Sequence)aIn.readObject());
+
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ DEROutputStream dOut = new DEROutputStream(bOut);
+
+ dOut.writeObject(r.toASN1Primitive());
+
+ byte[] bytes = bOut.toByteArray();
+
+ if (bytes.length != req.length)
+ {
+ return new SimpleTestResult(false, getName() + ": " + testName + " failed length test");
+ }
+
+ for (int i = 0; i != req.length; i++)
+ {
+ if (bytes[i] != req[i])
+ {
+ return new SimpleTestResult(false, getName() + ": " + testName + " failed comparison test");
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ return new SimpleTestResult(false, getName() + ": Exception - " + testName + " " + e.toString());
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+
+ public TestResult perform()
+ {
+ TestResult res = pkcs10Test("basic CR", req1);
+
+ if (!res.isSuccessful())
+ {
+ return res;
+ }
+
+ return pkcs10Test("Universal CR", req2);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ Test test = new PKCS10Test();
+
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/PKCS12Test.java b/core/src/test/java/org/spongycastle/asn1/test/PKCS12Test.java
new file mode 100644
index 00000000..0ad0a26e
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/PKCS12Test.java
@@ -0,0 +1,227 @@
+package org.spongycastle.asn1.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1OutputStream;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.BEROctetString;
+import org.spongycastle.asn1.DLSequence;
+import org.spongycastle.asn1.pkcs.AuthenticatedSafe;
+import org.spongycastle.asn1.pkcs.ContentInfo;
+import org.spongycastle.asn1.pkcs.EncryptedData;
+import org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo;
+import org.spongycastle.asn1.pkcs.MacData;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.pkcs.Pfx;
+import org.spongycastle.asn1.pkcs.SafeBag;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.DigestInfo;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Base64;
+import org.spongycastle.util.test.SimpleTest;
+
+public class PKCS12Test
+ extends SimpleTest
+{
+ byte[] pkcs12 = Base64.decode(
+ "MIACAQMwgAYJKoZIhvcNAQcBoIAkgASCA+gwgDCABgkqhkiG9w0BBwGggCSA"
+ + "BIIDRDCCA0AwggM8BgsqhkiG9w0BDAoBAqCCArEwggKtMCcGCiqGSIb3DQEM"
+ + "AQMwGQQUFlnNVpQoEHc+J3UEGxARipkHu5kCAWQEggKAAH9tmy40lly6QDoc"
+ + "1TfmY9y2qysD+lrgk+dnxP04RfoJfycTRDeaz2sPLImZtio9nsqCFqtzU/sl"
+ + "eWigbH34BpKU1sC0Gq1cyik0GO65sW95S6YjKtGcGOBfQCPk1oQjfiqnfU3G"
+ + "oeOaG3COQJukMFj8unv55u0xbX1hwO8SsZmr9RjPzLrVaeY6BP5+CCzOKBaj"
+ + "GxneIDqnQW7/kBIVWK7M+JXGdgQyiKhD6NvXL/zD8oKEne0nIX7IokQuWEn6"
+ + "8Sglv5OSclsSdvHTk57bCuV5lVzoIzczA4J/LZWdrtITeVefBLQSalBzpRde"
+ + "rSTMj485z2x5ChizhjE627/KQ5vkKQkQVqXYYXVyeTvKZRpL7vz13C4DUCwN"
+ + "im1XvNSCNebXS1yHJRtcONDhGJN3UsrVjHr+2kCfE5SCEeSU/dqgNLuLa1tk"
+ + "5+jwZFNj/HjO88wlOwPCol1uuJjDpaEW7dxu5qsVSfZhEXWHs8rZAMttFMzi"
+ + "yxsEkZe8kqngRbNJOY6KpppYedsMWDusUJGfIHo+8zymiw3gv/z+lmFOlDGt"
+ + "CKMk9Es/MgfjpbfhbTVYHOBKS6Qyrz7LdTuBMI8XdsZMuN+Uf73690ggLmKW"
+ + "IELUg8h1RX0ra2n6jOc/1rnebAifMhiMkL1ABQvqOobfOrG/9h9XcXoi64Qr"
+ + "htc3T7yMAHafBX5KUcNkbcn6kssYhpvd8bPADoLBnbx3GxGh/uziB0zKQEI0"
+ + "GnaY4SL7aR4C5xNNi41lYtsR6ohKyfPEGslhrhd4axx0cKxC2sHgVl0k+r8B"
+ + "8Vu44XHbW8LqdspjOHN9qg2erES1Dvgj05SfHDup+V6a3ogJo2YKXOiu3DF4"
+ + "MFEGCSqGSIb3DQEJFDFEHkIARABhAHYAaQBkACAARwAuACAASABvAG8AawAn"
+ + "AHMAIABWAGUAcgBpAFMAaQBnAG4ALAAgAEkAbgBjAC4AIABJAEQwIwYJKoZI"
+ + "hvcNAQkVMRYEFKEcMJ798oZLFkH0OnpbUBnrTLgWAAAAAAAAMIAGCSqGSIb3"
+ + "DQEHBqCAMIACAQAwgAYJKoZIhvcNAQcBMCcGCiqGSIb3DQEMAQYwGQQUTErH"
+ + "kWZ8nBXZYWO53FH4yqRZZsECAWSggASCDGCreuCr6/azcOv5w04bN3jkg4G2"
+ + "dsvTPAjL8bichaEOQCykhuNPt1dv3FsjUsdFC550K0+Y48RyBIID6JTiN9Gj"
+ + "K+a5aLPaXgTRdY74Toof1hYtZ4DIcVyq25LezVQHoe/++pAgEpWjqHTxVDIv"
+ + "YFAgT2oDB+2vkeXM61XnNWOjwCY3pXpk/VGjyN4USkD7Q/Y6tPjQOywvQE7c"
+ + "Ab1z62k9iMia7Yk/qmh+zJu4SSneo0/RLLdMZOlGZv89MResVG038TC8MTA9"
+ + "Uf+wDRcS20d7XDbTaBAgju8TpFIw5/lbDi0feUVlk6L+jkT1ktaTc1Pwtxn7"
+ + "psXMFW6HAWB4exOi09297R9BCOQX6vcetK/iA/3jIC6NuTdizYof0DWetdGy"
+ + "haIkMiEnERYE3unJocH4fq585Rw6mE+BYssPVPkVWZZInF3l69bKduuxsQt+"
+ + "pcApgBVsTjsU+1FOiUxuW2wWKi70RcQprPv5Ef1A5FRNxPFp+7IzLNlE4qCo"
+ + "wvC6NTpeuRw3aGsXSfqHmSddrHugNPmghNgG5lv1Ef7A8MUuyp8fyjAgxCDk"
+ + "4Hpb8PCHGj5t//Fr6Cd0MygJMIFQmv4kUd2LVHxQ9A9WFNCqTz/nBe+ZRLJL"
+ + "NghTv6gGpjGJiBnXYv6Sod2fs+5J2GIvex4qbdh6gzZIU2YTAwpj6Aca3SjA"
+ + "X8+m8AXt2SC3Z6T5+m8SxyiNp2P511paV/TZKtLWXQGKeEX1JXhQkaM6Q5W/"
+ + "IhSgC8/gppk1gbIraBqrW8bEnGBnC03wi0OnMz3ohM4CVHyaW3dQquT2+u6F"
+ + "8VeGXAYHU022NkrpPl/VlfNNEAyisU2+oJqpPZkqL6FsDWF3k6Fq2jXBLL+/"
+ + "a0WA82jIpgjNeXze/cgoHtU023V9E9Qcu+5nPBYdCTR4sRxvHLANii0W8lPv"
+ + "tvU5XO1UsEjHDfKL4E1bhGzGpb/OU5yg/98EN95r/xdFL5G+XVyHeR0UtkcB"
+ + "IuvyBdhkwoprCjkcgLZe8FPIBNw84HRe7Ye6f2gDW/F5uej6rBehJS1VFvCh"
+ + "DXzkajGmK40Gc2APS1/1vZqPu68polgw9dT84rem36PLEOq4KuU7n4QE0g7T"
+ + "YR2G8+4FNgQTjjg/qw3lX+sj6yLn1lYt1dOVvkiM8i8tdZg/3pCKKAW1uV7a"
+ + "astlBxVSkFfn1BrFTc2oFGkTrlUg90a+parOfGHTfDiaHX8ouEg63fk0+Xdi"
+ + "FCarXsqHNPDbpmWLKw8TAmdeneGipyScntJJk4ajy+jROQBgGew3ofOmfkqm"
+ + "oJFNwUvKOXN2ucViLZgsdK/7YgV1OR7oiTh8knQNPk3d5fRYSMFf9GJTjQRV"
+ + "y2CLdICAVzvrUXf9k7miWYkjIp2/HGD7pOH018sX9MrpfJKqvdPFOssZiFd0"
+ + "I2FUbgcEggPotvnT0XoabEiurTm8EPPpw66NKmK/H1kQL0hEtdIazPxfLmm/"
+ + "ZUDokwa7d4bE3BwFh0weQfEvMzJu6Y5E7ir2MqD33XaGMOGys1nst1SPPyDB"
+ + "WpOWD9w7Ng3yU1JVzqFWuVXaXDYbfnlG7AGevKF5PYNZj/RIQBBf5Xle9hTd"
+ + "c9CtxPkrsJwA8DeAwKl2WIfbXGzAYLSnXoYUcoTkWn/O81BlUFgAXv80gLe8"
+ + "NUrH7bhsnyGaPY953NyDk8IWUYrsn/sXvxTy5B0/7/WGMh3CSZrLX3p7TcFY"
+ + "yBrL6SRas4q9rrcwuhBq0tUUbbgWi92nhZl4bOGmx7ehHnwuUId2HWXyVGoB"
+ + "qToee/2E4PZFxSZwKCY6dahswFq5QGDrQKN2/qpOLZcJib6SvSGyEZl2pqr0"
+ + "lqk7tVPzBkN/4uP0qrcbZCDbGW6IXwu3RGMRehqj/HEJcs92lZKfVrk/U07X"
+ + "MBAiQHqV+kLw7kStECR/MGJG1c0xhqqBrf0W74+LpJiv/Q9iFNdWbXvE/cAk"
+ + "G7+OTUABd2kI88uA43T0UoRuPOi5KnLuD3AG+7IuyGyP69Xncd4u0srMg2fn"
+ + "DiLLZUy6vWmxwRFsSMCEfQNLtZaggukoPIihQvbX3mQS9izwLs6D89WtEcZ5"
+ + "6DVbIlUqUinnNKsT8vW1DZo5FMJkUxB666YIPVmkQbbJOEUU89dZg5Gw0og6"
+ + "rn4irEr4xHFdx+S7iqJXhzs9THg/9e4/k8KQ136z7LALOqDookcSdBzW6H8c"
+ + "STjs4qKQyNimsLB90mEuIEApzhseAaLFl+kgORGJv/2a+uoukZchMsJ98MVo"
+ + "sEPS1oBXJl2m9AshkWfON2GDeJatgcw6CyC1mSx++Gg602ZKUZZUaWxkz1Sw"
+ + "zTj3nhiJe+SZsdfxhsojNq7zfxqgY/Rq7BwvphU3StjnxvkB4rTkbmbiGOBO"
+ + "cvTFg4yOtQGRcifk2/XH/bgYiPqQrYSXpO3WRASV005RaSGufcpTtj3YlHGe"
+ + "8FUgZfDtfiGezhNET9KO3/Q0i34bGEpoIb/9uOWH4ZHULIlfdSm1ynV50nE4"
+ + "mJTXccrF6BE80KZI5GWGhqXdfPFaHTK1S20+XCw7bRJCGeiwVxvGfB+C0SZ4"
+ + "ndtqx165dKG5JwFukcygiIZN6foh0/PhwzmFxmPtZuPQt9dtuIQ35Y7PSDsy"
+ + "IH2Ot0Hh0YIN99lHJ6n9HomSjpwcgDXGssEuevbpz27u/MI/Uhq4Gfx0k5RF"
+ + "0pcRYtk1dYSx44a+8WgqZLF8DUNtyjSE/H8P5iGa6tqOl7kNyeeEkfoTtKst"
+ + "asGFwL4Qxxus4GC7repyVi7IJgSCA+iopiqKQJ2IqUHvoIEuD//sZooDx0Je"
+ + "oFRO5VakkTO6WHd8JpOOEU2f6Zjg++HdIl0QK7xcUaRH075LzEfqgn1vyw6J"
+ + "N6ex8D76sf/nAy01NvDPij48Z50XDwXu4kJGJvv0AJwId8BpjziBF0j3K/DI"
+ + "YOOpd6nW4EvdivCgaCnxqlIU/u1OP4BwpO+AUjJh6RKlKviGihQpi103DFhR"
+ + "yXNDhh55pqgCCCuNeEB+ovRt7UxzlGAVRSxJh1Zbjp/+iQun0E32RlSR4Diz"
+ + "p5vDk8NBZpIiKRqI+8GWZc3G1igp7dvViTLw4OdWMKwhccV5+3Ll/W72aNVm"
+ + "azYUoYOVn+OYS1NJkER0tjFOCozRGm5hfkxGlP+02wbH5uu/AQoJMqWIxT6l"
+ + "46IWC24lmAnDCXuM+gWmwUvyXLwuBdejVK8iG1Lnfg1qztoLpYRbBROgRdpt"
+ + "2cbPRm+9seqrth3eJbtmxCvuh3bZ3pR2e0/r5Tob/fDcOc5Kp+j4ndXWkwpa"
+ + "OuH1yxam7zNJR+mcYp1Wiujia5qIeY1QCAEY5QgAWaSHtjlEprwUuootA2Xm"
+ + "V7D8Vsr9BValhm9zMKj6IzsPmM+HZJWlhHcoucuAmPK6Lnys3Kv/mbkSgNOq"
+ + "fJDY901veFfKeqiCbAm6hZjNWoQDNJKFhjXUALrcOv9VCFPA3bMW3Xul/sB4"
+ + "Mq595e+x/1HkNOgZorBv97C6X7ENVDaAFcyZvrRU/ZeDnvFhisfxS4EJhzxl"
+ + "cWWnQhzD+ur1FTTlkmUFzgoB/rW+i3XigiHOuRRnkcoMy1uV17rwH8eELHJu"
+ + "Yni5vu2QUaD4jNEhliE2XCsn8Sm6bcXnfzBa7FXC39QvAcdJHzqcD6iIwjIz"
+ + "hKLu+/XoWFMFFNsgV78AwzPAn6TRya8LLCYPoIZkEP4qBoeZtUZ8PIS/Y7M9"
+ + "QStMwa/NI9SPswb3iScTGvor/obUEQS4QM6mVxFMpQWfwJfyU6jingX4EHRE"
+ + "mqvZ3ehzU8ZLOdKzRKuk022YDT7hwEQ+VL0Fg0Ld9oexqT96nQpUTHZtDRMV"
+ + "iTuJoUYTneDs2c9tsY4mWBqamZQSfTegj4sLMZagkuSUp/SpPM2zSGuD3nY6"
+ + "u3553gIM9jYhvLBEXwjGudVCwMd3bqo/4EhnKb2PcwUzdaMkipQlNteHZjBT"
+ + "1ici63xjJva+di0qTV+W9cyYyHwg1927X2qcMh06BhbHlcXQKbgmbL18KJEt"
+ + "K+GGhGNkP7mtPyHHgBb6vref/z8p7oxT2CG+oBuN/z+xQoYfe9c4IC3e/kNN"
+ + "DIoyYvPyEzAdfMS2aL8qDxzc5GH9UE9kcusJ/2dNEFTzBH2GK1CItL3IACv/"
+ + "LwX1SkI0w7oIQTL127CSnuTrUUkvJ/+rOYScQTMD/ntZPdLdu2ffszg3SzhN"
+ + "ELgojK8ss1OBlruWRHw/fP736Nx8MNsuOvXMnO8lruz+uyuEhF3BLv96oTcg"
+ + "XVHdWhPmOoqNdBQdRgAAAAAAAAAAAAAAAAAAAAAAADA8MCEwCQYFKw4DAhoF"
+ + "AAQUJMZn7MEKv4vW/+voCVyHBa6B0EMEFJOzH/BEjRtNNsZWlo/4L840aE5r"
+ + "AgFkAAA=");
+
+ public void performTest()
+ throws Exception
+ {
+ ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(pkcs12));
+ ASN1Sequence obj = (ASN1Sequence)aIn.readObject();
+ Pfx bag = Pfx.getInstance(obj);
+ ContentInfo info = bag.getAuthSafe();
+ MacData mData = bag.getMacData();
+ DigestInfo dInfo = mData.getMac();
+ AlgorithmIdentifier algId = dInfo.getAlgorithmId();
+ byte[] salt = mData.getSalt();
+ int itCount = mData.getIterationCount().intValue();
+
+ aIn = new ASN1InputStream(new ByteArrayInputStream(((ASN1OctetString)info.getContent()).getOctets()));
+
+ AuthenticatedSafe authSafe = AuthenticatedSafe.getInstance(aIn.readObject());
+ ContentInfo[] c = authSafe.getContentInfo();
+
+ //
+ // private key section
+ //
+ if (!c[0].getContentType().equals(PKCSObjectIdentifiers.data))
+ {
+ fail("failed comparison data test");
+ }
+
+ aIn = new ASN1InputStream(new ByteArrayInputStream(((ASN1OctetString)c[0].getContent()).getOctets()));
+ ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
+
+ SafeBag b = SafeBag.getInstance(seq.getObjectAt(0));
+ if (!b.getBagId().equals(PKCSObjectIdentifiers.pkcs8ShroudedKeyBag))
+ {
+ fail("failed comparison shroudedKeyBag test");
+ }
+
+ EncryptedPrivateKeyInfo encInfo = EncryptedPrivateKeyInfo.getInstance(b.getBagValue());
+
+ encInfo = new EncryptedPrivateKeyInfo(encInfo.getEncryptionAlgorithm(), encInfo.getEncryptedData());
+
+ b = new SafeBag(PKCSObjectIdentifiers.pkcs8ShroudedKeyBag, encInfo.toASN1Primitive(), b.getBagAttributes());
+
+ ByteArrayOutputStream abOut = new ByteArrayOutputStream();
+ ASN1OutputStream berOut = new ASN1OutputStream(abOut);
+
+ berOut.writeObject(new DLSequence(b));
+
+ c[0] = new ContentInfo(PKCSObjectIdentifiers.data, new BEROctetString(abOut.toByteArray()));
+
+ //
+ // certificates
+ //
+ if (!c[1].getContentType().equals(PKCSObjectIdentifiers.encryptedData))
+ {
+ fail("failed comparison encryptedData test");
+ }
+
+ EncryptedData eData = EncryptedData.getInstance(c[1].getContent());
+
+ c[1] = new ContentInfo(PKCSObjectIdentifiers.encryptedData, eData);
+
+ //
+ // create an octet stream represent the BER encoding of authSafe
+ //
+ authSafe = new AuthenticatedSafe(c);
+
+ abOut = new ByteArrayOutputStream();
+ berOut = new ASN1OutputStream(abOut);
+
+ berOut.writeObject(authSafe);
+
+ info = new ContentInfo(PKCSObjectIdentifiers.data, new BEROctetString(abOut.toByteArray()));
+
+ mData = new MacData(new DigestInfo(algId, dInfo.getDigest()), salt, itCount);
+
+ bag = new Pfx(info, mData);
+
+ //
+ // comparison test
+ //
+
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ aOut.writeObject(bag);
+
+ if (!Arrays.areEqual(bOut.toByteArray(), pkcs12))
+ {
+ fail("failed comparison test");
+ }
+ }
+
+ public String getName()
+ {
+ return "PKCS12";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new PKCS12Test());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/PKIFailureInfoTest.java b/core/src/test/java/org/spongycastle/asn1/test/PKIFailureInfoTest.java
new file mode 100644
index 00000000..b4b52744
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/PKIFailureInfoTest.java
@@ -0,0 +1,68 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Encoding;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.cmp.PKIFailureInfo;
+import org.spongycastle.util.encoders.Base64;
+import org.spongycastle.util.test.SimpleTest;
+
+
+/**
+ * PKIFailureInfoTest
+ */
+public class PKIFailureInfoTest
+ extends SimpleTest
+{
+ // A correct hex encoded BAD_DATA_FORMAT PKIFailureInfo
+ private static final byte[] CORRECT_FAILURE_INFO = Base64.decode("AwIANQ==");
+
+ public String getName()
+ {
+ return "PKIFailureInfo";
+ }
+
+ private void testEncoding()
+ throws IOException
+ {
+ DERBitString bitString = (DERBitString)new ASN1InputStream(CORRECT_FAILURE_INFO).readObject();
+ PKIFailureInfo correct = new PKIFailureInfo(bitString);
+
+ PKIFailureInfo bug = new PKIFailureInfo(PKIFailureInfo.badRequest | PKIFailureInfo.badTime |PKIFailureInfo.badDataFormat | PKIFailureInfo.incorrectData);
+
+ if (!areEqual(correct.getEncoded(ASN1Encoding.DER),bug.getEncoded(ASN1Encoding.DER)))
+ {
+ fail("encoding doesn't match");
+ }
+ }
+
+ public void performTest()
+ throws IOException
+ {
+ BitStringConstantTester.testFlagValueCorrect(0, PKIFailureInfo.badAlg);
+ BitStringConstantTester.testFlagValueCorrect(1, PKIFailureInfo.badMessageCheck);
+ BitStringConstantTester.testFlagValueCorrect(2, PKIFailureInfo.badRequest);
+ BitStringConstantTester.testFlagValueCorrect(3, PKIFailureInfo.badTime);
+ BitStringConstantTester.testFlagValueCorrect(4, PKIFailureInfo.badCertId);
+ BitStringConstantTester.testFlagValueCorrect(5, PKIFailureInfo.badDataFormat);
+ BitStringConstantTester.testFlagValueCorrect(6, PKIFailureInfo.wrongAuthority);
+ BitStringConstantTester.testFlagValueCorrect(7, PKIFailureInfo.incorrectData);
+ BitStringConstantTester.testFlagValueCorrect(8, PKIFailureInfo.missingTimeStamp);
+ BitStringConstantTester.testFlagValueCorrect(9, PKIFailureInfo.badPOP);
+ BitStringConstantTester.testFlagValueCorrect(14, PKIFailureInfo.timeNotAvailable);
+ BitStringConstantTester.testFlagValueCorrect(15, PKIFailureInfo.unacceptedPolicy);
+ BitStringConstantTester.testFlagValueCorrect(16, PKIFailureInfo.unacceptedExtension);
+ BitStringConstantTester.testFlagValueCorrect(17, PKIFailureInfo.addInfoNotAvailable);
+ BitStringConstantTester.testFlagValueCorrect(25, PKIFailureInfo.systemFailure);
+
+ testEncoding();
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new PKIFailureInfoTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/ParseTest.java b/core/src/test/java/org/spongycastle/asn1/test/ParseTest.java
new file mode 100644
index 00000000..f2ba1770
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/ParseTest.java
@@ -0,0 +1,308 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import junit.framework.TestCase;
+import org.spongycastle.asn1.ASN1OctetStringParser;
+import org.spongycastle.asn1.ASN1SequenceParser;
+import org.spongycastle.asn1.ASN1StreamParser;
+import org.spongycastle.asn1.ASN1TaggedObjectParser;
+import org.spongycastle.asn1.BERTags;
+import org.spongycastle.asn1.cms.ContentInfoParser;
+import org.spongycastle.asn1.cms.EncryptedContentInfoParser;
+import org.spongycastle.asn1.cms.EnvelopedDataParser;
+import org.spongycastle.util.encoders.Base64;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.io.Streams;
+
+public class ParseTest
+ extends TestCase
+{
+ private static byte[] classCastTest = Base64.decode(
+ "MIIXqAYJKoZIhvcNAQcDoIIXmTCCF5UCAQAxggG1MIIBsQIBADCBmDCBkDEL"
+ + "MAkGA1UEBhMCVVMxETAPBgNVBAgTCE1pY2hpZ2FuMQ0wCwYDVQQHEwRUcm95"
+ + "MQwwCgYDVQQKEwNFRFMxGTAXBgNVBAsTEEVMSVQgRW5naW5lZXJpbmcxJDAi"
+ + "BgkqhkiG9w0BCQEWFUVsaXQuU2VydmljZXNAZWRzLmNvbTEQMA4GA1UEAxMH"
+ + "RURTRUxJVAIDD6FBMA0GCSqGSIb3DQEBAQUABIIBAGh04C2SyEnH9J2Va18w"
+ + "3vdp5L7immD5h5CDZFgdgHln5QBzT7hodXMVHmyGnycsWnAjYqpsil96H3xQ"
+ + "A6+9a7yB6TYSLTNv8zhL2qU3IrfdmUJyxxfsFJlWFO1MlRmu9xEAW5CeauXs"
+ + "RurQCT+C5tLc5uytbvw0Jqbz+Qp1+eaRbfvyhWFGkO/BYZ89hVL9Yl1sg/Ls"
+ + "mA5jwTj2AvHkAwis+F33ZhYlto2QDvbPsUa0cldnX8+1Pz4QzKMHmfUbFD2D"
+ + "ngaYN1tDlmezCsYFQmNx1th1SaQtTefvPr+qaqRsm8KEXlWbJQXmIfdyi0zY"
+ + "qiwztEtO81hXZYkKqc5fKMMwghXVBgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcE"
+ + "CEq3cLLWVds9gIIVsAAik3al6Nn5pr7r0mSy9Ki3vEeCBcV9EzEG44BvNHNA"
+ + "WyEsqQsdSxuF7h1/DJAMuZFwCbGflaRGx/1L94zrmtpeuH501lzPMvvZCmpj"
+ + "KrOF8e1B4MVQ5TfQTdUVyRnbcDa6E4V1ZZIdAI7BgDeJttS4+L6btquXfxUg"
+ + "ttPYQkevF7MdShYNnfLkY4vUMDOp3+iVzrOlq0elM95dfSA7OdBavgDJbz/7"
+ + "mro3AFTytnWjGz8TUos+oUujTk9/kHOn4cEAIm0hHrNhPS5qoj3QnNduNrad"
+ + "rLpGtcYyNlHIsYCsvPMxwoHmIw+r9xQQRjjzmVYzidn+cNOt0FmLs6YE8ds4"
+ + "wvHRO9S69TgKPHRgk2bihgHqII9lF9qIzfG40YwJLHzGoEwVO1O0+wn8j2EP"
+ + "O9I/Q3vreCH+5VbpUD2NGTwsMwZ3YlUesurLwse/YICxmgdN5Ro4DeQJSa9M"
+ + "iJnRFYWRq+58cKgr+L11mNc9nApZBShlpPP7pdNqWOafStIEjo+dsY/J+iyS"
+ + "6WLlUvNt/12qF4NAgZMb3FvRQ9PrMe87lqSRnHcpLWHcFjuKbMKCBvcdWGWI"
+ + "R7JR8UNzUvoLGGAUI9Ck+yTq4QtfgtL5MLmdBGxSKzgs44Mmek+LnrFx+e9n"
+ + "pkrdDf2gM/m7E50FnLYqzUjctKYGLNYpXQorq9MJx6TB20CHXcqOOoQqesXa"
+ + "9jL9PIOtBQy1Ow5Bh4SP07nTFWFSMI/Wt4ZvNvWJj3ecA9KjMOA9EXWUDS/H"
+ + "k9iCb2EEMo7fe5mhoyxMxPO+EIa1sEC9A1+rDACKPQCHOLI0uPmsdo0AEECC"
+ + "QLgOQkcwQlkHexOyHiOOtBxehtGZ1eBQQZ+31DF+RRU6WvS6grg58eS4gGOQ"
+ + "bd7CS9yYebvAQkz61J8KprWdtZuG1gBGma12wKMuQuC6RuWlKsj+rPMvaQCt"
+ + "8mucGbkElPGZVhdyD8/BvpSCNbgRwb6iSiw4EECovu4P4GFJaMGUYEuCA711"
+ + "itEieYc1QqS6ULjb3LFL/RcwSw0fGdjnt6B2nHckC2VsYKU1NwU7j0R1Omb4"
+ + "y5AvSgpuWjTXWnHnE9Ey0B+KP5ERZA+jJGiwYz48ynYlvQFSbBm4I6nh/DuI"
+ + "dWB2dLNxWuhdfzafBGtEHhLHzjW3WQwwRZsKesgHLrrj9hBUObodl1uvqvZN"
+ + "AjMOj8DrqbGOhAClj1t4S1Zk1ZekuMjsuoxEL+/lgtbT+056ES0k3A/LnpRb"
+ + "uxA1ZBr26Im+GVFzEcsV0hB4vNujSwStTTZH5jX5rMyi085yJfnikcLYUn9N"
+ + "apl+srhpIZlDJPw7IHaw8tsqXKDxF7MozIXo8B45CKv5Am+BMrIemCMX/ehu"
+ + "PODICl98Ur8tNAn1L+m0nj7H3c8HW2vNuBLEI3SEHHgm2Ij3IY5pyyeVUaWC"
+ + "pumhy8Ru5dj3fZcfKgYuJBQxWMf+UqPsf4iUK3923pouJ1cQ8XU8gOXIRrtX"
+ + "e41d/yR+UAZXSig6SITLw+wLtvitSvtxvjcUSUOI9CYTovKyuz1PQKiaLsV5"
+ + "4CoJhMQ5uRlVFS3H829I2d2gLRpSp6pNWeIZO2NMBxPYf2qcSHyHqQjR7xP2"
+ + "ZTg7U3OO6dZHORfXxzAnW2ExavBIYQmZh1gLn5jSS4wXFPXyvnJAsF4s5wed"
+ + "YHsyAqM/ek0n2Oo/zAh7UcP2vcb9FOoeRK8qC9HjTciS6WbjskRN0ft4T69G"
+ + "+1RsH8/edBxo2LZeA48BSCXDXOlBZJBsOptzYJD8HSZONPnef0jn23lk0fkU"
+ + "C3BjJu2ubFChctRvJniTko4klpidkHwuJgrTnL4er8rG3RfiiEHn/d5era15"
+ + "E1cekdVYWqwQOObOd4v+0gZSJgI48TBc5Qdy8F6wIU38DR2pn/5uNthNDgXk"
+ + "NcV9a2gOE3DoLe8CEIPMihqYMPY8NuSp97eHB2YhKpjP7qX9TUMoOdE2Iat2"
+ + "klNxadJt6JTFeiBPL6R9RHAD5sVBrkrl0S+oYtgF92f9WHVwAXU7zP6IgM4x"
+ + "hhzeJT07yyIp44mKd//F+7ntbgQjZ/iLbHh0mtOlUmzkFsDR0UNSXEQoourZ"
+ + "EY4A62HXj0DMqEQbik6QwEF7FKuwZX2opdOyVKH9MzJxNfDLd5dc8wAc8bCX"
+ + "jcCx5/GzHx2S5DndWQEVhp2hOQYuoJS3r6QCYFaHtDPKnFHS2PBFyFWL+2UK"
+ + "c0WsvVaHYqYKnksmxse9I9oU75kx5O05DZCThPX6h8J8MHRuxU9tcuuleIUQ"
+ + "XY8On+JeEtLSUZgp+Z7ITLuagf6yuKQpaR396MlDii/449/dvBiXAXeduyO1"
+ + "QzSkQCh37fdasqGL3mP0ssMcxM/qpOwQsx3gMtwiHQRi1oQE1QHb8qZHDE4m"
+ + "I5afQJ9O/H/m/EVlGUSn2yYOsPlZrWuI3BBZKoRzRq1lZOQDtOh18BE3tWmX"
+ + "viGIAxajam0i2Ce3h2U7vNwtiePRNEgPmQ7RwTTv0U6X8qqkjeYskiF4Cv9G"
+ + "nrB0WreC19ih5psEWLIkCYKTr+OhQuRrtv7RcyUi9QSneh7BjcvRjlGB6joA"
+ + "F6J4Y6ENAA/nzOZJ699VkljTi59bbNJYlONpQhOeRTu8M/wExkIJz7yR9DTY"
+ + "bY4/JdbdHNFf5DSDmYAHaFLmdnnfuRy+tC9CGGJvlcLVv5LMFJQGt2Wi15p8"
+ + "lctx7sL6yNCi7OakWbEOCvGPOxY7ejnvOjVK/Krx1T+dAXNUqrsDZmvmakOP"
+ + "We+P4Di1GqcyLVOTP8wNCkuAUoN0JFoBHy336/Xnae91KlY4DciPMpEOIpPN"
+ + "oB+3h6CozV7IWX5Wh3rhfC25nyGJshIBUS6cMXAsswQI8rOylMlGaekNcSU4"
+ + "gNKNDZAK5jNkS0Z/ziIrElSvMNTfYbnx3gCkY0pV18uadmchXihVT11Bt77O"
+ + "8KCKHycR39WYFIRO09wvGv6P42CRBFTdQbWFtkSwRiH8l6x39Z7pIkDFxokT"
+ + "Dp6Htkj3ywfQXNbFgRXZUXqgD1gZVFDFx920hcJnuu65CKz6pEL6X0XUwNPg"
+ + "vtraA2nj4wjVB/y+Cxc+1FgzeELB4CAmWO1OfRVLjYe7WEe/X5DPT6p8HBkB"
+ + "5mWuv+iQ3e37e1Lrsjt2frRYQWoOSP5Lv7c8tZiNfuIp07IYnJKBWZLTqNf9"
+ + "60uiY93ssE0gr3mfYOj+fSbbjy6NgAenT7NRZmFCjFwAfmapIV0hJoqnquaN"
+ + "jj5KKOP72hp+Zr9l8cEcvIhG/BbkY3kYbx3JJ9lnujBVr69PphHQTdw67CNB"
+ + "mDkH7y3bvZ+YaDY0vdKOJif9YwW2qoALXKgVBu1T2BONbCTIUTOzrKhWEvW8"
+ + "D6x03JsWrMMqOKeoyomf1iMt4dIOjp7yGl/lQ3iserzzLsAzR699W2+PWrAT"
+ + "5vLgklJPX/Fb3Tojbsc074lBq669WZe3xzlj85hFcBmoLPPyBE91BLhEwlGC"
+ + "+lWmwFOENLFGZE0mGoRN+KYxwqfA2N6H8TWoz6m0oPUW4uQvy9sGtYTSyQO9"
+ + "6ZwVNT3ndlFrP5p2atdEFVc5aO5FsK8/Fenwez06B2wv9cE9QTVpFrnJkKtF"
+ + "SaPCZkignj64XN7cHbk7Ys6nC3WIrTCcj1UOyp5ihuMS9eL9vosYADsmrR6M"
+ + "uqqeqHsf2+6U1sO1JBkDYtLzoaILTJoqg9/eH7cTA0T0mEfxVos9kAzk5nVN"
+ + "nVOKFrCGVIbOStpYlWP6wyykIKVkssfO6D42D5Im0zmgUwgNEkB+Vxvs8bEs"
+ + "l1wPuB2YPRDCEvwM3A5d5vTKhPtKMECIcDxpdwkD5RmLt+iaYN6oSFzyeeU0"
+ + "YvXBQzq8gfpqJu/lP8cFsjEJ0qCKdDHVTAAeWE6s5XpIzXt5cEWa5JK7Us+I"
+ + "VbSmri4z0sVwSpuopXmhLqLlNWLGXRDyTjZSGGJbguczXCq5XJ2E3E4WGYd6"
+ + "mUWhnP5H7gfW7ILOUN8HLbwOWon8A6xZlMQssL/1PaP3nL8ukvOqzbIBCZQY"
+ + "nrIYGowGKDU83zhO6IOgO8RIVQBJsdjXbN0FyV/sFCs5Sf5WyPlXw/dUAXIA"
+ + "cQiVKM3GiVeAg/q8f5nfrr8+OD4TGMVtUVYujfJocDEtdjxBuyFz3aUaKj0F"
+ + "r9DM3ozAxgWcEvl2CUqJLPHH+AWn5kM7bDyQ2sTIUf5M6hdeick09hwrmXRF"
+ + "NdIoUpn7rZORh0h2VX3XytLj2ERmvv/jPVC97VKU916n1QeMJLprjIsp7GsH"
+ + "KieC1RCKEfg4i9uHoIyHo/VgnKrnTOGX/ksj2ArMhviUJ0yjDDx5jo/k5wLn"
+ + "Rew2+bhiQdghRSriUMkubFh7TN901yl1kF2BBP5PHbpgfTP6R7qfl8ZEwzzO"
+ + "elHe7t7SvI7ff5LkwDvUXSEIrHPGajYvBNZsgro+4Sx5rmaE0QSXACG228OQ"
+ + "Qaju8qWqA2UaPhcHSPHO/u7ad/r8kHceu0dYnSFNe1p5v9Tjux0Yn6y1c+xf"
+ + "V1cu3plCwzW3Byw14PH9ATmi8KJpZQaJOqTxn+zD9TvOa93blK/9b5KDY1QM"
+ + "1s70+VOq0lEMI6Ch3QhFbXaslpgMUJLgvEa5fz3GhmD6+BRHkqjjwlLdwmyR"
+ + "qbr4v6o+vnJKucoUmzvDT8ZH9nH2WCtiiEtQaLNU2vsJ4kZvEy0CEajOrqUF"
+ + "d8qgEAHgh9it5oiyGBB2X/52notXWOi6OMKgWlxxKHPTJDvEVcQ4zZUverII"
+ + "4vYrveRXdiDodggfrafziDrA/0eEKWpcZj7fDBYjUBazwjrsn5VIWfwP2AUE"
+ + "wNn+xR81/so8Nl7EDBeoRXttyH7stbZYdRnkPK025CQug9RLzfhEAgjdgQYw"
+ + "uG+z0IuyctJW1Q1E8YSOpWEFcOK5okQkLFUfB63sO1M2LS0dDHzmdZriCfIE"
+ + "F+9aPMzojaHg3OQmZD7MiIjioV6w43bzVmtMRG22weZIYH/Sh3lDRZn13AS9"
+ + "YV6L7hbFtKKYrie79SldtYazYT8FTSNml/+Qv2TvYTjVwYwHpm7t479u+MLh"
+ + "LxMRVsVeJeSxjgufHmiLk7yYJajNyS2j9Kx/fmXmJbWZNcerrfLP+q+b594Y"
+ + "1TGWr8E6ZTh9I1gU2JR7WYl/hB2/eT6sgSYHTPyGSxTEvEHP242lmjkiHY94"
+ + "CfiTMDu281gIsnAskl05aeCBkj2M5S0BWCxy7bpVAVFf5nhf74EFIBOtHaJl"
+ + "/8psz1kGVF3TzgYHkZXpUjVX/mJX8FG0R8HN7g/xK73HSvqeamr4qVz3Kmm/"
+ + "kMtYRbZre7E1D10qh/ksNYnOkYBcG4P2JyjZ5q+8CQNungz2/b0Glg5LztNz"
+ + "hUgG27xDOUraJXjkkZl/GOh0eTqhfLHXC/TfyoEAQOPcA59MKqvroFC5Js0Q"
+ + "sTgqm2lWzaLNz+PEXpJHuSifHFXaYIkLUJs+8X5711+0M03y8iP4jZeEOrjI"
+ + "l9t3ZYbazwsI3hBIke2hGprw4m3ZmSvQ22g+N6+hnitnDALMsZThesjb6aJd"
+ + "XOwhjLkWRD4nQN594o6ZRrfv4bFEPTp4ev8l6diouKlXSFFnVqz7AZw3Pe53"
+ + "BvIsoh66zHBpZhauPV/s/uLb5x6Z8sU2OK6AoJ7b8R9V/AT7zvonBi/XQNw3"
+ + "nwkwGnTS9Mh7PFnGHLJWTKKlYXrSpNviR1vPxqHMO6b+Lki10d/YMY0vHQrY"
+ + "P6oSVkA6RIKsepHWo11+rV838+2NRrdedCe91foUmOs+eoWQnwmTy2CTZmQ5"
+ + "b7/TTcau9ewimZAqI+MtDWcmWoZfgibZmnIITGcduNOJDRn+aLt9dz+zr1qA"
+ + "HxlLXCOyBPdtfx6eo4Jon+fVte37i3HmxHk+8ZGMMSS9hJbLQEkA59b4E+7L"
+ + "GI3JZjvEkhizB4n/aFeG7KT7K3x072DMbHLZ7VgsXQ1VDDmcZmizFwgyNqKy"
+ + "hKCKxU+I2O10IMtiZUpEzV1Pw7hD5Kv/eFCsJFPXOJ2j3KP6qPtX5IYki1qH"
+ + "Juo5C5uGKtqNc6OzkXsvNUfBz5sJkEYl0WfitSSo4ARyshFUNh2hGxNxUVKM"
+ + "2opOcuHSxBgwUSmVprym50C305zdHulBXv3mLzGjvRstE9qfkQ8qVJYLQEkL"
+ + "1Yn7E92ex71YsC8JhNNMy0/YZwMkiFrqyaFd/LrblWpBbGumhe4reCJ4K3mk"
+ + "lFGEsICcMoe+zU1+QuLlz/bQ+UtvClHUe8hTyIjfY04Fwo2vbdSc1U/SHho5"
+ + "thQy+lOZ/HijzCmfWK3aTqYMdwCUTCsoxri2N8vyD/K2kbMLQWUfUlBQfDOK"
+ + "VrksBoSfcluNVaO56uEUw3enPhhJghfNlJnpr5gUcrAMES53DfkjNr0dCsfM"
+ + "JOY2ZfQEwwYey1c4W1MNNMoegSTg4aXzjVc0xDgKa7RGbtRmVNbOxIhUNAVi"
+ + "thQV3Qujoz1ehDt2GyLpjGjHSpQo3WlIU4OUqJaQfF6EH+3khFqUmp1LT7Iq"
+ + "zH3ydYsoCDjvdXSSEY3hLcZVijUJqoaNWBLb/LF8OG5qTjsM2gLgy2vgO/lM"
+ + "NsqkHnWTtDimoaRRjZBlYLhdzf6QlfLi7RPmmRriiAOM0nXmylF5xBPHQLoz"
+ + "LO9lXYIfNbVJVqQsV43z52MvEQCqPNpGqjB+Au/PZalYHbosiVOQLgTB9hTI"
+ + "sGutSXXeLnf5rftCFvWyL3n5DgURzDFLibrbyVGGKAk166bK1RyVP9XZJonr"
+ + "hPYELk4KawCysJJSmC0E8sSsuXpfd6PPDru6nCV1EdXKR7DybS7NVHCktiPR"
+ + "4B4y8O/AgfJX8sb6LuxmjaINtUKEJ1+O88Gb69uy6b/Kpu2ri/SUBaNNw4Sn"
+ + "/tuaD+jxroL7RlZmt9ME/saNKn9OmLuggd6IUKAL4Ifsx9i7+JKcYuP8Cjdf"
+ + "Rx6U6H4qkEwwYGXnZYqF3jxplyOfqA2Vpvp4rnf8mST6dRLKk49IhKGTzwZr"
+ + "4za/RZhyl6lyoRAFDrVs1b+tj6RYZk0QnK3dLiN1MFYojLyz5Uvi5KlSyFw9"
+ + "trsvXyfyWdyRmJqo1fT7OUe0ImJW2RN3v/qs1k+EXizgb7DW4Rc2goDsCGrZ"
+ + "ZdMwuAdpRnyg9WNtmWwp4XXeb66u3hJHr4RwMd5oyKFB1GsmzZF7aOhSIb2B"
+ + "t3coNXo/Y+WpEj9fD7/snq7I1lS2+3Jrnna1048O7N4b5S4b5TtEcCBILP1C"
+ + "SRvaHyZhBtJpoH6UyimKfabXi08ksrcHmbs1+HRvn+3pl0bHcdeBIQS/wjk1"
+ + "TVEDtaP+K9zkJxaExtoa45QvqowxtcKtMftNoznF45LvwriXEDV9jCXvKMcO"
+ + "nxG5aQ//fbnn4j4q1wsKXxn61wuLUW5Nrg9fIhX7nTNAAooETO7bMUeOWjig"
+ + "2S1nscmtwaV+Sumyz/XUhvWynwE0AXveLrA8Gxfx");
+
+ private static byte[] derExpTest = Base64.decode(
+ "MIIS6AYJKoZIhvcNAQcDoIIS2TCCEtUCAQAxggG1MIIBsQIBADCBmDCBkDEL"
+ + "MAkGA1UEBhMCVVMxETAPBgNVBAgTCE1pY2hpZ2FuMQ0wCwYDVQQHEwRUcm95"
+ + "MQwwCgYDVQQKEwNFRFMxGTAXBgNVBAsTEEVMSVQgRW5naW5lZXJpbmcxJDAi"
+ + "BgkqhkiG9w0BCQEWFUVsaXQuU2VydmljZXNAZWRzLmNvbTEQMA4GA1UEAxMH"
+ + "RURTRUxJVAIDD6FBMA0GCSqGSIb3DQEBAQUABIIBAGsRYK/jP1YujirddAMl"
+ + "ATysfLCwd0eZhENohVqLiMleH25Dnwf+tBaH4a9hyW+7VrWw/LC6ILPVbKpo"
+ + "oLBAOical40cw6C3zulajc4gM3AlE2KEeAWtI+bgPMXhumqiWDb4byX/APYk"
+ + "53Gk7WXF6Xs4hj3tmrHSJxCUOsTdHKUJYvOqjwKGARPQDjP0EUbVJezeAwBA"
+ + "RMlJ/qBVLBj2UW28n5oJZm3oaSaU93Uc6GPVIk43IWrmEUcWVPiMfUtUCwcX"
+ + "tRNtHuQ9os++rmdNBiuB5p+vtUeA45KWnTUtkwJXvrzE6Sf9AUH/p8uOvvZJ"
+ + "3yt9LhPxcZukGIVvcQnBxLswghEVBgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcE"
+ + "CGObmTycubs2gIIQ8AKUC8ciGPxa3sFJ1EPeX/nRwYGNAarlpVnG+07NITL2"
+ + "pUzqZSgsYh5JiKd8TptQBZNdebzNmCvjrVv5s9PaescGcypL7FNVPEubh0w/"
+ + "8h9rTACqUpF5yRgfcgpAGeK29F1hyZ1WaIH43avUCaDnrZcOKB7wc1ats1aQ"
+ + "TSDLImyFn4KjSo5k0Ec/xSoWnfg391vebp8eOsyHZhFMffFtKQMaayZNHJ7Q"
+ + "BzG3r/ysUbkgI5x+0bX0QfZjEIs7yuV5Wt8DxMTueCm3RQ+HkR4lNdTBkM4V"
+ + "qozCqC1SjcAF5YHB0WFkGouEPGgTlmyvLqR2xerEXVZn9YwSnT48kOde3oGt"
+ + "EAYyg0yHbNbL0sp6LDM7upRmrgWwxf0BR6lP4wyWdv/XSLatEB7twSNiPBJ4"
+ + "PJ+QagK08yQJ84UB7YpMTudKsaUs7zW76eA7KkW3TndfDYGdhbmZ5wxNl+5x"
+ + "yPZc/jcQHW7vplMfWglUVxnzibNW12th0QXSB57Mzk8v1Rvc/HLGvAOJZG/S"
+ + "N12FZOxbUrMIHGi3kXsmfWznVyq92X4P9tuDDD7sxkSGsyUAm/UJIZ3KsXhV"
+ + "QeaRHVTVDxtJtnbYxBupy1FDBO6AhVrp16Blvnip9cPn/aLfxDoFHzmsZmEg"
+ + "IcOFqpT1fW+KN6i/JxLD3mn3gKzzdL1/8F36A2GxhCbefQFp0MfIovlnMLFv"
+ + "mrINwMP8a9VnP8gIV5oW5CxmmMUPHuGkXrfg+69iVACaC2sTq6KGebhtg9OC"
+ + "8vZhmu7+Eescst694pYa3b8Sbr5bTFXV68mMMjuRnhvF2NZgF+O0jzU+sFps"
+ + "o7s1rUloCBk1clJUJ/r+j9vbhVahCeJQw62JAqjZu4R1JYAzON3S7jWU5zJ7"
+ + "pWYPSAQkLYUz3FmRRS2Yv65mXDNHqR9vqkHTIphwA9CLMKC2rIONxSVB57q1"
+ + "Npa/TFkVdXnw+cmYjyFWiWeDP7Mw0Kwy7tO008UrBY0rKQU466RI5ezDqYPc"
+ + "Lm73dUH2EjUYmKUi8zCtXpzgfTYVa/DmkbVUL9ThHMVRq1OpT2nctE7kpXZk"
+ + "OsZjEZHZX4MCrSOlc10ZW7MJIRreWMs70n7JX7MISU+8fK6JKOuaQNG8XcQp"
+ + "5IrCTIH8vmN2rVt4UT8zgm640FtO3jWUxScvxCtUJJ49hGCwK+HwDDpO6fLw"
+ + "LFuybey+6hnAbtaDyqgsgDh2KN8GSkQT9wixqwQPWsMQ4h0xQixf4IMdFOjP"
+ + "ciwp3ul8KAp/q70i0xldWGqcDjUasx6WHKc++rFjVJjoVvijKgEhlod5wJIw"
+ + "BqQVMKRsXle07NS1MOB+CRTVW6mwBEhDDERL+ym2GT2Q4uSDzoolmLq2y5vL"
+ + "+RfDHuh3W0UeC3Q5D2bJclgMsVjgfQUN19iD+lPFp2xvLTaNWi5fYDn4uuJL"
+ + "lgVDXIMmM8I+Z2hlTXTM1Pldz2/UFe3QXTbYnjP6kfd7Bo2Webhhgs/YmSR2"
+ + "XPuA42tWNAAjlK77lETWodxi3UC7XELjZ9xoGPRbxjOklXXvev9v5Vo+vcmN"
+ + "0KrLXhLdkyHRSm81SRsWoadCTSyT8ibv66P00GOt+OlIUOt0YKSUkULQfPvC"
+ + "EgMpeTm1/9l8n9bJ6td5fpJFDqLDm+FpJX6T2sWevV/Tyt6aoDPuET5iHBHW"
+ + "PoHxKl8YPRHBf+nRWoh45QMGQWNSrJRDlO8oYOhdznh4wxLn3DXEfDr0Z7Kd"
+ + "gEg6xr1XCobBn6Gi7wWXp5FDTaRF41t7fH8VxPwwDa8Yfu3vsgB6q426kjAj"
+ + "Q77wx1QFIg8gOYopTOgqze1i4h1U8ehP9btznDD6OR8+hPsVKoXYGp8Ukkc7"
+ + "JBA0o8l9O2DSGh0StsD94UhdYzn+ri7ozkXFy2SHFT2/saC34NHLoIF0v/aw"
+ + "L9G506Dtz6xXOACZ4brCG+NNnPLIcGblXIrYTy4+sm0KSdsl6BGzYh9uc8tu"
+ + "tfCh+iDuhT0n+nfnvdCmPwonONFb53Is1+dz5sisILfjB7OPRW4ngyfjgfHm"
+ + "oxxHDC/N01uoJIdmQRIisLi2nLhG+si8+Puz0SyPaB820VuV2mp77Y2osTAB"
+ + "0hTDv/sU0DQjqcuepYPUMvMs3SlkEmaEzNSiu7xOOBQYB8FoK4PeOXDIW6n2"
+ + "0hv6iS17hcZ+8GdhwC4x2Swkxt99ikRM0AxWrh1lCk5BagVN5xG79c/ZQ1M7"
+ + "a0k3WTzYF1Y4d6QPNOYeOBP9+G7/a2o3hGXDRRXnFpO7gQtlXy9A15RfvsWH"
+ + "O+UuFsOTtuiiZk1qRgWW5nkSCPCl2rP1Z7bwr3VD7o6VYhNCSdjuFfxwgNbW"
+ + "x8t35dBn6xLkc6QcBs2SZaRxvPTSAfjON++Ke0iK5w3mec0Br4QSNB1B0Aza"
+ + "w3t3AleqPyJC6IP1OQl5bi+PA+h3YZthwQmcwgXgW9bWxNDqUjUPZfsnNNDX"
+ + "MU9ANDLjITxvwr3F3ZSfJyeeDdbhr3EJUTtnzzWC6157EL9dt0jdPO35V0w4"
+ + "iUyZIW1FcYlCJp6t6Sy9n3TmxeLbq2xML4hncJBClaDMOp2QfabJ0XEYrD8F"
+ + "jq+aDM0NEUHng+Gt9WNqnjc8GzNlhxTNm3eQ6gyM/9Ip154GhH6c9hsmkMy5"
+ + "DlMjGFpFnsSTNFka2+DOzumWUiXLGbe4M3RePl1N4MLwXrkR2llguQynyoqF"
+ + "Ptat2Ky5yW2q9+IQHY49NJTlsCpunE5HFkAK9rY/4lM4/Q7hVunP6U4a0Kbu"
+ + "beFuOQMKQlBZvcplnYBefXD79uarY/q7ui6nFHlqND5mlXMknMrsQk3papfp"
+ + "OpMS4T07rCTLek0ODtb5KsHdIF76NZXevko4+d/xbv7HLCUYd8xuOuqf+y4I"
+ + "VJiT1FmYtZd9w+ubfHrOfHxY+SBtN6fs02WAccZqBXUYzZEijRbN2YUv1OnG"
+ + "rfYe4EcfOu/Sa+wLbB7msYpLfvUfEO3iseKf4LXZkgtF5P610PBZR8edeSgr"
+ + "YZW+J0K78PRAl5nEi1mvzBxi9DyNf6iQ9mWLyyCmr9p9HGE+aCMKVCn9jfZH"
+ + "WeBDAJNYDcUh5NEckqJtbEc2S1FJM7yZBWLQUt3NCQvj+nvQT45osZ3BJvFg"
+ + "IcGJ0CysoblVz4fCLybrYxby9HP89WMLHqdqsIeVX8IJ3x84SqLPuzrqf9FT"
+ + "ZVYLo0F2oBjAzjT7obt9+NJc/psOMCg+OGQkAfwj3VNvaqkkQsVxSiozgxrC"
+ + "7KaTXuAL6eKKspman96kz4QVk9P0usUPii+LFnW4XYc0RNfgJVO6BgJT7pLX"
+ + "NWwv/izMIMNAqSiWfzHHRVkhq4f1TMSF91auXOSICpJb3QQ4XFh52Mgl8+zs"
+ + "fobsb0geyb49WqFrZhUu+X+8LfQztppGmiUpFL+8EW0aPHbfaf4y9J1/Wthy"
+ + "c28Yqu62j/ljXq4Qa21uaEkoxzH1wPKCoKM9TXJtZJ39Yl9cf119Qy4M6QsB"
+ + "6oMXExlMjqIMCCWaLXLRiqbc2Y7rZHgEr08msibdoYHbSkEl8U+Kii2p6Vdx"
+ + "zyiEIz4CadrFbrAzxmrR/+3u8JuBdq0K3KNR0WWx73BU+G0rgBX56GnP7Ixy"
+ + "fuvkRb4YfJUF4PkDa50BGVhybPrIhoFteT6bSh6LQtBm9c4Kop8Svx3ZbqOT"
+ + "kgQDa0n+O0iR7x3fvNZ0Wz4YJrKGnVOPCqJSlSsnX6v2JScmaNdrSwkMTnUf"
+ + "F9450Hasd88+skC4jVAv3WAB03Gz1MtiGDhdUKFnHnU9HeHUnh38peCFEfnK"
+ + "WihakVQNfc72YoFVZHeJI5fJAW8P7xGTZ95ysyirtirxt2zkRVJa5p7semOw"
+ + "bL/lBC1bp4J6xHF/NHY8NQjvuhqkDyNlh3dRpIBVBu6Z04hRhLFW6IBxcCCv"
+ + "pjfoxJoox9yxKQKpr3J6MiZKBlndZRbSogO/wYwFeh7HhUzMNM1xIy3jWVVC"
+ + "CrzWp+Q1uxnL74SwrMP/EcZh+jZO4CYWk6guUMhTo1kbW03BZfyAqbPM+X+e"
+ + "ZqMZljydH8AWgl0MZd2IAfajDxI03/6XZSgzq24n+J7wKMYWS3WzB98OIwr+"
+ + "oKoQ7aKwaaT/KtR8ggUVYsCLs4ScFY24MnjUvMm+gQcVyeX74UlqR30Aipnf"
+ + "qzDRVcAUMMNcs0fuqePcrZ/yxPo+P135YClPDo9J8bwNpioUY8g+BQxjEQTj"
+ + "py3i2rAoX+Z5fcGjnZQVPMog0niIvLPRJ1Xl7yzPW0SevhlnMo6uDYDjWgQ2"
+ + "TLeTehRCiSd3z7ZunYR3kvJIw1Kzo4YjdO3l3WNf3RQvxPmJcSKzeqKVxWxU"
+ + "QBMIC/dIzmRDcY787qjAlKDZOdDp7qBKIqnfodWolxBA0KhvE61eYabZqUCT"
+ + "G2HJaQE1SvOdL9KM4ORFlxE3/dqv8ttBJ6N1qKk423CJjajZHYTwf1dCfj8T"
+ + "VAE/A3INTc6vg02tfkig+7ebmbeXJRH93KveEo2Wi1xQDsWNA+3DVzsMyTqV"
+ + "+AgfSjjwKouXAznhpgNc5QjmD2I6RyTf+hngftve18ZmVhtlW5+K6qi62M7o"
+ + "aM83KweH1QgCS12/p2tMEAfz//pPbod2NrFDxnmozhp2ZnD04wC+6HGz6bX/"
+ + "h8x2PDaXrpuqnZREFEYzUDKQqxdglXj5oE/chBR8+eBfYSS4JW3TBkW6RfwM"
+ + "KOBBOOv8pe3Sfq/bg7OLq5bn0jKwulqP50bysZJNlQUG/KqJagKRx60fnTqB"
+ + "7gZRebvtqgn3JQU3fRCm8ikmGz9XHruoPlrUQJitWIt4AWFxjyl3oj+suLJn"
+ + "7sK62KwsqAztLV7ztoC9dxldJF34ykok1XQ2cMT+uSrD6ghYZrmrG5QDkiKW"
+ + "tOQCUvVh/CorZNlON2rt67UvueMoW+ua25K4pLKDW316c2hGZRf/jmCpRSdb"
+ + "Xr3RDaRFIK6JpmEiFMMOEnk9yf4rChnS6MHrun7vPkf82w6Q0VxoR8NRdFyW"
+ + "3mETtm2mmG5zPFMMD8uM0BYJ/mlJ2zUcD4P3hWZ8NRiU5y1kazvrC6v7NijV"
+ + "o459AKOasZUj1rDMlXDLPloTHT2ViURHh/8GKqFHi2PDhIjPYUlLR5IrPRAl"
+ + "3m6DLZ7/tvZ1hHEu9lUMMcjrt7EJ3ujS/RRkuxhrM9BFlwzpa2VK8eckuCHm"
+ + "j89UH5Nn7TvH964K67hp3TeV5DKV6WTJmtIoZKCxSi6FFzMlky73gHZM4Vur"
+ + "eccwycFHu+8o+tQqbIAVXaJvdDstHpluUCMtb2SzVmI0bxABXp5XrkOOCg8g"
+ + "EDZz1I7rKLFcyERSifhsnXaC5E99BY0DJ/7v668ZR3bE5cU7Pmo/YmJctK3n"
+ + "m8cThrYDXJNbUi0c5vrAs36ZQECn7BY/bdDDk2NPgi36UfePI8XsbezcyrUR"
+ + "ZZwT+uQ5LOB931NjD5GOMEb96cjmECONcRjB0uD7DoTiVeS3QoWmf7Yz4g0p"
+ + "v9894YWQgOl+CvmTERO4dxd7X5wJsM3Y0acGPwneDF+HtQrIpJlslm2DivEv"
+ + "sikc6DtAQrnVRSNDr67HPPeIpgzThbxH3bm5UjvnP/zcGV1W8Nzk/OBQWi0l"
+ + "fQM9DccS6P/DW3XPSD1+fDtUK5dfH8DFf8wwgnxeVwi/1hCBq9+33XPwiVpz"
+ + "489DnjGhHqq7BdHjTIqAZvNm8UPQfXRpeexbkFZx1mJvS7so54Cs58/hHgQN"
+ + "GHJh4AUCLEt0v7Hc3CMy38ovLr3Q8eZsyNGKO5GvGNa7EffGjzOKxgqtMwT2"
+ + "yv8TOTFCWnZEUTtVA9+2CpwfmuEjD2UQ4vxoM+o=");
+
+ byte[] longTagged = Hex.decode("9f1f023330");
+
+ public void testClassCast()
+ throws IOException
+ {
+ parseEnveloped(classCastTest);
+ }
+
+ public void testDerExp()
+ throws IOException
+ {
+ parseEnveloped(derExpTest);
+ }
+
+ public void testLongTag()
+ throws IOException
+ {
+ ASN1StreamParser aIn = new ASN1StreamParser(longTagged);
+
+ ASN1TaggedObjectParser tagged = (ASN1TaggedObjectParser)aIn.readObject();
+
+ assertEquals(31, tagged.getTagNo());
+ }
+
+ private void parseEnveloped(byte[] data) throws IOException
+ {
+ ASN1StreamParser aIn = new ASN1StreamParser(data);
+
+ ContentInfoParser cP = new ContentInfoParser((ASN1SequenceParser)aIn.readObject());
+
+ EnvelopedDataParser eP = new EnvelopedDataParser((ASN1SequenceParser)cP.getContent(BERTags.SEQUENCE));
+
+ eP.getRecipientInfos().toASN1Primitive(); // Must drain the parser!
+
+ EncryptedContentInfoParser ecP = eP.getEncryptedContentInfo();
+
+ ASN1OctetStringParser content = (ASN1OctetStringParser)ecP.getEncryptedContent(BERTags.OCTET_STRING);
+
+ Streams.drain(content.getOctetStream());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/ParsingTest.java b/core/src/test/java/org/spongycastle/asn1/test/ParsingTest.java
new file mode 100644
index 00000000..65424e22
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/ParsingTest.java
@@ -0,0 +1,99 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1StreamParser;
+import org.spongycastle.util.encoders.Base64;
+import org.spongycastle.util.test.SimpleTest;
+
+public class ParsingTest
+ extends SimpleTest
+{
+ String[] streams = {
+ "oRNphCO0F+jcMQKC1uMO8qFBPikDDYmtfVGeB45xvbfj1qu696YGjdW2igRnePYM/KkQtADG7gMHIhqBRcl7dBtkejNeolOklPNA3NgsACTiVN9JFUsYq0a5842+TU+U2/6Kt/D0kvz0WmwWFRPHWEWVM9PYOWabGsh28Iucc6s7eEqmr8NEzWUx/jM3dmjpFYVpSpxt2KbbT+yUO0EqFQyy8hQ7JvKRgv1AoWQfPjMsfjkKgxnA8DjenmwXaZnDaKEvQIKQl46L1Yyu3boN082SQliSJMJVgNuNNLFIt5QSUdG1ant5O6f9Yr0niAkAoqGzmqz+LZE1S7RrGHWiQ3DowE9NzviBuaAoI4WdCn1ClMwb9fdEmBMU4C7DJSgs3qaJzPUuaAT9vU3GhZqZ0wcTV5DHxSRzGLqg9JEJRi4qyeuG3Qkg3YBtathl+FiLJ7mVoO3dFIccRuuqp2MpMhfuP1DxHLNLNiUZEhLMQ0CLTGabUISBuyQudVFlKBZIpcLD0k7fKpMPuywrYiDrTinMc2ZP3fOGevoR5fnZ6kZAE5oMTtMNokzBuctGqVapblXNrVMLYbriT538oYz5",
+ "KEKVhHxtyUR9D3v5K4IJbVQLAMiVKoK9z7wFWUjzvLFNLg9C/r8zKfBa3YgZrt0Nq64+MxBePMbiNLCnfditc2qUcQZUHnvNnhwT6uGK37JmXg7MvQiKwvi31EIYt6ghqBZVs1iaqc0ep7wuQ16uwSQMlaDdXc9Qf1L0dGO/6eLyREz+p4UR4NOXK+GooQLfMxYL40zJlYcwNyR0rigvIr84WP2IMS2hZjqXtyS6HMM4yUv70hkIorjr7+JC4GtU1MyWuPuNSAGen0AZTaEEXd5sMbqXMqWg3jeM4mzRH1Kb3WdAChO5vMJZPBj9jZZKgXzmxkUh5GlIhUdYgztoNceBzQ3PIc7slCDUw9I2PjB87xsfy7jA5tFtFADs2EUyxUTMCuhilP664jSHgwbrr80k9Xc4sU+MCwCq2nQmcZYcPgKb4M31VJMlKwnZF3JUU2Jtqgg4gbErw58YoBwSkEcMJ2Juhiyx9U36MzxHs9OcTURfpsilMy+mDL8arCDx1knM1KkAHCLjWuJI+p1PvuIypgCwVc+MtGfd7wW8iR1JPJLBiuoZyNJ+xx9htd/HVB+rLtB57H8Gz8W+R00f",
+ "Ol9I/rXMwbLpxTY97v70B+HCl2+cojz2574x/cC56A7KGVF13La8RdzOOvSkl338ct9T/blEFa6QwNz3GmF+MoPdH9lncwz+tqixIqGU02Bp5swH0qjbp/Yjaeq91eR6B+9fl+KKrpglBr8S1BrI4Ey5v3AxxJdCWP8Gd+6Sp15/HMYanwlHBpCsW4+Kq8sGJoJXUXpQ/GBUJKs+WjX1zE6PsvF7/B8cByuqE3NJt7x4Oa+qZtF8qNc0CFDNj31Yhdt7JkAoD30IAd+ue9OhImQMCWwFwySRIRJXU3865K2dBR+VhLuI2aKzLh7MlgVKJk6b2P/ZIkc86ksR1sOUiHrs9EdoYuIssAgMc8QGzn4VN8lxopdzQYVG6pbXGS/VQlHkGdyLd+OHt4srz/NTUWiOquVTRxa6GgtlBFfIXikPTb+iT2pZKyKUlBvpgo0BY9vVUadsteHAI5qrFZBrL5ecK/Qtl9hf/M8qEjyjt2aCXe9B96Hg2QR5A53qW2PJW5VzS0AeB3g+zJSPCTpygrBs20q5Xrna0ux2l17r6HT9Q/AXIOkwPZUXXn0d02igS4D6Hxrg3Fhdp+OTXL8G",
+ "o3eXWpwAGmUkxHEKm/pGkDb1ZQQctCQ06lltZjeMXDp9AkowmA0KXjPQCQwyWE/nqEvk2g/58AxNU0TWSujo5uU0h4/hdMZ7Mrj33NSskWvDpKe7lE5tUjPi74Rmc5RRS+1T/EQobpNxoic3+tTO7NBbZfJtcUYeZ3jqxL+3YQL3PrGe/Zpno9TnQW8mWbbhKhDRtKY4p3Pgk9hPSpJCM9xYo3EMAOAIiH2P6RKH6uX/gSaUY2b6DE/TT0V6v/jdSmYM4+cnYiTyJCi5txI35jfCqIlVCXJd7klirvUMg9SXBhGR25AgQ5Z8yjd7lbB8FvD8JQAXZrp6xiHxbLIW7G11fWEo7RGLFtALI6H38Ud0vKjsEN7N5AibJcxS2A/CWk9R00sTHRBHFUP8o5mz8nE7FeCiwJPs/+tCt04nGb9wxBFMsmWcPEDfIzphCaO6U/D/tQHlA846gbKoikv/6LI0ussSR/i85XBclNcvzTctxylSbCR02lZ+go6fe5rmMouiel/0Tndz8t1YpQGilVeOQ3mqAFyAJk3dgfTNKZuOhNzVIZ5GWScKQ5ZtNcWrg6siR+6YwKvLiRb/TJZk",
+ "PwRUnW4yU8PI7ggbI1BIO9fcTup8optkqCirodyHCiqsPOMZ4g28bJ2+kpfQRujWGlKFYQzA1ZT32s9hdci+fvXPX0KAjcUgcxsGzMABFbEm04BwDF2WLgg9s4/x71r5JrgME1S08I3mCo4N0eFHWDeLJL1b5YNNo6tfO5V2WpIE867N9zdAgvp1gijVjUNWqEB3A/NLb3reLMu2hYgqRFTCVBfcFclD46k0XEfUJqwWdQhOz92WNl/3g53bjKX1hDZgjLIzK6m+SU6+J/h4NidrS7E0gOBevZW8gRYdKMVqNWxzUfxv6kgG+kIeF9JqMcO6jdh/Zu/0tpZoHFeCweZ1jT1eEtltFu1FcTTPc1UT0pT+ZNVgefrBONoGnvn8+dBjPese6F2TmRCExJq9taKlIh/kHdkbpaa7vwrBpYRgVGfARPyM9SSCaE7pVBDuwkFeYiGU4tamm5Gq10ojRQgetJ3UOg/PGTJcxo97GBiG5zAST9NdHdgK3eI4FAbWpGwmWxNpPWOst0a7zuGKAzYU+1IQh8XA3IgJ2vy3+w0JihU6G+12LUzsL2aQtpG7d1PqLhwOqHq3Qqv3SDsB",
+ "ZIAKizvGzbvqvqOlxOeVgHGHV9TfKNjjqyzbCj8tggv2yp7kkq1D3yRlC349tuul3zN9g4u83Ctio9Gg3HiLzMULxoOImF/hKRDhJpPLbLm0jSq1fyF+N7/YvyLeFhGoPhYEBUihDcxo1NIcWy66aBt3EuOlTyDQWrDe0Za3mrTrrl10uLHVKcQMgeD+UMgjQqmHzQJR8wdNjHPKHWVvZEdiwI031nV2giHJHXv08Jvf4vmw4dAlH2drCl6cBgg33jy7ohK8IiXz6eCw6iY9Ri8YaMzxOhgE2BOHzEz5ZC2hilL4xO/ambTER4bhb4+9VTUIehHP18FcXm8TKPQRMqyKP2fMlzWW3/uelYfPP5SHlyLAULa1KjDCkLIDunEKZDpv2ljGB6JPrTlNwFsvlZcihfOAwjbr2jW3MwP704OA8xzd/dynBU47unIZEu0LAvQ3TUz3PLga0GGO1LZGtg0Foo9zFG2wuVCdgYHmozOQ+8I3gRguW1CjGy7ZCTBuN1GZ510ERhae+bRQtldHsLeiHTghnkU1xEX1+W0iEf3csDYrgpuq3NaBYRGirovDiPBYFHmru0AMclhFnpcX",
+ "uG0wQ55kMlfZtJFAqTl0bnYW/oy9NFOi0e4FqAYwsvMxGO4JtGzXgkVwEUAC0AUDItRUjxBl+TkoPTYaprgn0M/NQvKPpXJ+yzI7Ssi+F2alLR0T6eF/4rQ32AVjnANJaghXZm0ZKduckbhSxk5lilJVJRuzXKchZRtlPluvlj448bq+iThktsEQoNP8NMpi7n/EVxovp+dow4Q6t7msSRP4cGXtyYoWKbf/7e5XzBKOZZ1/f3s86uJke4dcKIaljpJfBrtuFxZC6NYXzX6PkoDoBgqQ8RBrxsX54S9cBDAPxxmkq8zviAOW3oqPMULGGmQzHBiRwE8oeDFoMnzF5aR/lkbNuTLOxhbIkosgLWlDNVEFYx9bVhdLzO7VwaAK829dimlPOo5loKB7Pd2G7ekRKXwu7wNvJBq8KRkhtLKbKoS8D6TaRWUMb9VBJ1CMy4mrw+YwTmAKURQ6Dko9J/RgzRg5Y/sUlwdMYS9HOnvKiTVu5I/ha35wwkhIPVm+FCn05tstntZaXXXu4xExHeugAKNBhkcc/SQt+GFdxXDd+R4C2LfKxGDSyZKVTFYojHTdZUo8Gx6SZLY6b2SZ",
+ "sH0kIwIq1THAfTLfqUKJfG1YauCQKPc9/mk3l39yK6zgxSpCH2IjZIwhhJtGm3F+8PTneT725OuyR617nxqrgqMGkkZkyY4DA5CjsikpBo5mo8TspX1g+vtXXtxymJMTMo8JwX3nSH4gSb3vPia+gwOW2TcJmxVdp3ITPA4gJpMfqoMBqRM+eDWO6QXW5ijVL4+wnp40u5bU4fQLVzpg25+QGLqBHD6PZTQaN6F9Vy5XpsAGDlncCklVuX3Lkp3Xb9cTiNa/4ii04uwZqx0juszjwFAMPPb6u56crvN1x4FXfXzabWECHbdQLlKazowvU9bEnqG2i4H44Ae+v8Iw8HK5mbZ6ercLTD9oPgs7Ogal037l2WwLApUz/fmD5fV8SxHh+vKDpfOzv6xcQxynS82jAJw9AdUwE/4ndGzzHPIu2M81gbAgZQ02EurMMU62hYgiXeridrtyh+H5R+CiwQdEyX7/op6WVihsYj2O3O/1hgjhGQRFD6sGwnko50jgWRxaMMfJGNlyGoT8WT5k931jU7547u7Ovr7XP/t8r3G7ceCiCcYjQgdwXdvIStzPvvV7Yy02isZjiJF8TLJQ",
+ "tycxf1mOz1yLE6cT/ZlCxMeTxlEEHFeIdw0+nF/40Tsw4vLco+4kR2A6cVml611CSpN6l/RMKk2LnAkprrbJ/Uam902WBnQ+I6Vsl6GkFFq7362bdixojqMFVKYytXLCT8I78f6s8M6a3jSALQloD6Ftvn+cc+cctO3weaaaPgAlrz+f2MFs8bqpnLQYbbY/JS9IAYJFH+yVtLz7eKcedEp9JMlJ3/43szU2fDN9ZMxBoQnxEmF3WZv6GF0WRc8VhTblXRgk4mlz6Fu3IXvwW/rbn+VCYYIk/XaVLrxFAnnw6mBozAF7vmV0OrIYBlSDU8rMb+F7AvE7pwErO9TJtCE8IUvQf8TsJYRoYv21/X57pzcBedtqVeU3DnTlmESHxG6H1uJbadSFLWSxKS4svfp8T9FWqX5815yD/UplAKEIeorLTAlPIC2ASKDU6SQW260biNAfY8FYQCWa8btaTwFuY8NMwSHzyqgU0aoPKnagi/4hOIWNO5rZ8Xcnzx+ELtEl33hQnzc4OUlT5eeVYQWkz2IWVQ6Re4JWF3L4OXzNZWgefKGMzZU6IHoBeCgfi+popLRJpaOx0dcvwGjk",
+ "oDsoFvUA+sGOoMyZY6w1UhY3NBkeoozzjEkDSRN1golyXJ1dC5CtYNEjvAJYKj+sqNwg9mBlYyybYpnI3GSP125zMeBHPCoy5CoNOkJW4OH/oLyjVeQbFNic/b2Jcz6lTguYhep8hq9EM2XuFV8T1rm5+4ucI7fH1UiOqRZyuHBAJ0Cna5kv6D3efsa9rd+swybiMIUjmPWpyxzNOOihCYuf4JqRh/D5eZKm6x0Zj2uRhTAYYxI7Q3czd0R9490ufG8VbF8ASBMireMONNNAA/OZCpxJh6xnIANBqV6YDeysws3NBWY2QuNumvg5Kr3/g+VMzJHi4wGuJjraKWi9+ylMfelHF5h/h+pAQVxCotq8JU3OTnMUW4rQp2a8BR5S+mZqPSPlb87tDG9r0+yqb1uO4UIo71C7Xxwoq4M0tXjk6mSmtP/sm+Lh14qfUzKRhTHVdz91TK104mbTJNXbK+jGPD/2BJO9fiaXY8IYanpfDLBfJo06VYbm6HehRZTwnDHnN50j7ki4aMS3COZvffjRInXD8dS5h9zmtKNpoqg//lPg4gpS+4Th2sJ3SGtBV0Ne89r7AfZMAVa26PMK",
+ "MIDLuZTrtZnEBOB6l14iSEyokAg5Wf5JviumhfPeL7WSFTHfOodU2hrvhyvM6oAlRHY1blTj7mw+Tcf9Tmc+/FHT6PGu0NT5UAqaqChX0gS9jizgAE2Yfhd4X/DoeQySMAixKuhu8TbvDxb54jeW9+7LVkmlntJ/0SkMgsT+WQ31OfpwDmEGDczYc+Ol14aJS+EW+rnGv9d38bo/cy+EnpNh8iV2rGGoC8fDzFHKU4gqGFSZF/tnD2OfCne0Vjr/GD6kyp2MVcHig19DBg2toGRkHnuY5kLkwOanztXA80IaAmv8e6s62U8CE8ozUZeDBcvBigEkSGx79Vsyiks8+9Kq9xLHLeS5kRT6zSl8whe8U1fIfrgic34KPlozcQVahwCru1XWyQ+9uevih8x4zMftkJ3JBZhPrnlgtx9McntH/Ss9fdUEkNwWpDnq8Xby8/5gMMMwQ13XDB73vqqteDiltMq8i7LRez4iIHfSBBfIkZIzMZAblQXaSm029iBcAAUes7wcGHUl7KOpRy18jNtI3+h7e1Ri6sT2vJYQaove0nzZ5xAjpBKnbJX+lpGVlI00fC2YSTfyNqFA0jkL",
+ "MG4QbKLbQR3enPn6Z/kEUtHrzWBIqYKR7Gvs5QHLPF6417p1O58suZq38Bb8dO5udtgOqNEVAPGmOuidYygWWfWOP5ReggTUk5XlrkvRxCU0MHWbkSKkJ+T4nLjozreqTJ0io41sFVrpxuOugAvXJ6QtMmixSABUaNgU9SkkWf9pOEiJI8dfND51HxJCbXHwsMCMBp5FbaMZmlWPwirRdAox4wbLk9ZLmoWUcorUjdaWhKvT/LnjMgPmwnwwKpN/4MOnRDdAPdzXX3aWHdkzpfsQnqt3UJsTsSaJlzeUja5C5L4CXGyt99qmfcwB8OB9TL4EYTIl3maD/gUWBfckOsji8x2E2c2iuKKrcmMmcChYr4wCjtTjEeVKOAZ2m9mU2MKc2z2hDw3AuZxsY6aOtdAjnrwl5QXGRg9I5LVl5SI5RwnLwk90pJzDGuSSCtSmzh9DUZ4WpfN+1393aTGRqCMOsB4KxbXjspUbVMFJbnXXlsSNWaoFTpHjK6b6Ghi2/re7KJpoKElM3nGs3qvxdvGTKu7LKr/sgKDL6uQLRKoyk8AHSIGX9c8ZUTk7Sq9jV9p4QfV1WFVpaBxSsEmw",
+ "MR0BACgWKis9/AKwG9/ARgGWJn1aM3nU8YXzWG+b7aeRUkVCjl4WxeL38E3FAMLW4UcyLzxeb+CskOqhPPTglmxhK7jQcrNILsWcZvdZfApYIvk5uKqA5FKuUuL48uvD0aKGRENe/VEUFlkQru5YX4Xnp+ZThrJJlgn7ANat/qAdP6ULEcLaOQlLYcGRh5ttsJTRT4+cZQggTJjWt+9idUQ66HfC6zQ1qHcMuochy7GHiUmNXAs0AgwOF9Jwet/Qh74KGMtmppJ9gkEqiYECFQA2gVgKc1AufHJS6S6Re72FfH/UkL41L2hvlwktkD5/hZrUZ1R+RG12Eip2zKgus4g/aGl0V8B/JvkcnFUsZJ6uxs24arOBDJOuzzxky5F5B/hwVGPEdcfHunqndUcx26/KCK72hOljlqTXl8yEbXlcMqVFNByZLr7TnGzGGUlO7kuHPW/ItZUJvrHokpsLLrb3ZhEZ8pTQd75gFcf0Ve8CYzEtk2ISHtNJQV6Iz4AZHWssU6F6YWM/OlJz5JGTtPHfGMJXgl4oxbBjeenS3JQ0X7vWXYMwPe3U1dat6m5hrRC1KzI6e6w+gPDtF8GQ",
+ "DH2WX6XoIseX6lHIey3seUr3DAz82fyk0jL7xc5IDTrDfqS64QBhHDpqHETF/81MrPXsM3IANBfjDOl9g/gua8wWPpPNxuWZMNh0GLcAr6PJ939TCbjE3soZHF2wiA82nZEO8jIZosDVRWFUfJS6Y3nrJz63SExqB6OUdBfvSfz1Y1M/90ofBxkfeuS85deMdn+1rZdsnZJYwz2Z6lCDvYjUTfrSwfVFJBP8Y2BXr8WClUYkfGG4eNG7IPNBRuMmhrhHj5y9z+5Jor+EbbTi5F5Jvdu2/bDM7s32XsaMNLYuVtNYONrbQ+3QZ746/yKZM4hDREvxyGLgDx3Apz7pyvwKm0//iTCY3yJLxZifGLh2uc28cFBln7IH1x8oui4Xq9vF+Z2EH4Ow48Ln5pzggBKMGy4dsfW6266TNYd/Z3SZUi28sxondqhGCSGUo7ZVPAOoYDcYKvjdI/cJ688PHliyZSYBYVmR5HBxZ57sqWwgZQ7zVvwv4CHHysvb92sPrXijHxBIkwpNuK56UMyQCcywlTRLDCMAMNAEGi4fWbDQIoPfn+NixMhEieg3Zh7GXPwHxW8morlgBW5aF76P",
+ "AwClK6Tq9R2DYGf8RAHu9dEttLeOfUVmS4WPwX0NehsnyM7y7n2sgGnXsiva3yFqK1hKZICkVukvHF7/bpgEEm/jRwcAhQUoG+c1qVde38eHJXj58YOBGTveruc+021or9/tHBtenmYPO6+arLQtONi43NKm7+I6ugkgQlp6iBr4haa0XMDTzMX9c8Qm/O+MrVo3qESYKkVtoSSK7SGZTBaRWNF/dOM0NQxeMP+XTVOuroqE23ZNsubBTEZnd4vUilFb/iKnhyT9XnIo7gM/Yz7HLVU5yc3yIj2sFUE+DcwpvcNO5EnPhj3bHsJvf3N4r72+5my2KjoR3KAJE1Imabd54o4xZ/9UaR93qLkVuXMkLRCCU/zlZDtfbJDsRR0C5rSYd2k6IPlNcl7PgmUpsNPUyoDYqvhuRUZxgoUAfKbogzJX8FU/QpllsKVtt68ucBi0bqC5pVKu23j79nDvYQsSlYY3JwJQaM5M558J5qpP1yEF2p4kSRphnB9UR29wWgch5eWZ4a02LlHVM5Msl6W5PdmHt+eFARBRv6edIyYDFzxm4WZroH5F/GxBhM0KObgawkxa5VWsYm0VhhXb",
+ "KACwq8rZuOLHuNnZJA07WzI7kppCwptbcYU2B7t86QcZrnadCtxoM5QNcl9rsbMA26iWCPV3VlDAmLSWcxtMoSKWuo4edJpk8K915xkFU5U6I/901vx5hqAECQDy/Q+QDWmWTXDoVHqFV9wvIj3wCJPpJL/Ewpl0NZd+68jjOjUhjIdNebLrWNK2nhTPiIjFjkcVqEgashpOmnbHT+2MV/CHoixmUEiuRI1B0dvSf7FHGRgbXGBubisuu60g8XTens5zyRo4Qn/LTxIu2aj4LTtyLonV3sXr+y35A1zq5mCrE1f1nOINVzwYYY76iJGIaBkZuMU3366FPIbYkmXwla6RQU1FA0Y7n05qczw7Ie5TveRTByKFtUqW8OAb9vH+H2ezJ4CXE3AGbu/nTj64KClO/zL499GA+97g+X6tTN6xOJdNknlqw6ZnFNtCL8+A3hL4OyOgWD0IGC+xFvcKjDUaaJenCtQvprCJaFrvoOS+yYmixnFqglnPYL/64/Lca8NmDVpPzlHI8HNwUDzKiXTw3q7GnQZWmUYzu1vLIEi6/hyqrULRN1vLdd/8HCMNQFj4ot61UftHtOG8MCKa",
+ "rUABPQ3SEWE5rY16pM+o+7EObLNM1jEa5YCMQM/aen0PWajWNax3Pyo6TZL8aGDXZF0yWqDM3b2m6UHOr6yqsUSrD+0jXPT48QN1VdBmh+AFRK+UcaYO383a0nvtv0c9uHt4yfceXLPGWrNjW+uTnS/lKpCdpE4GfLF1SFHIUcMxT+3At7hwDHNkLXllEXqbgDP8LyQSlYwT5jQUDCOzwc8CSxAryUOj6fN+iLKAiw4haPV/WZDG+JOmDMG2azo8SoBMi3y6Z2Le2fz2dMuvn5DUvCUvazrUmWYx4NEdSzc9GfBc6cXkduMqCs+lT2Ik2GHO0WjhrEB6j5NULOaCtbrislM85P6QutN4Pj9l18pcD6vZCcDTOwMj/BznclH342jeMn7rBgpW1YSzbNGP6KC4NeNW1H2xqNtuyhcJvasx4dwhzO18A36H6HtkiQyJNnfnVHh1oviO6mi3atmnh9B/55ugXM1Wf/6Kv8kJyaKtK8cWo+jCAR0/P/EsPtzToJM9Yk2+qxaPFd3k7T2KXvCQ9D1jLeECxL59L+WDvdBtxOEBD7W0a/Mn/9LuQPOiwARKJSTU+blJ6ezTeo83",
+ "poA1hF4zRh7HF0xVglYoLFqkUR7Pru/qYFnfMKBPuEOOGdgO3MMcAvIZ+w+Ug4THr/6+Vux0TN3wdOB+beObOboLgNE2zaD65lyMFbaulzrEnWjUgIg63CdpQJ2ESaimHGg/GmsipUCndRJ37TbUtn8W112SehsAgrsjiBcuJhw61i4bVfAZEcycq4Y/FlEDxtzoH8WzDoESNbl+r5agLcHGr37BFi81IXS8TLihC1T8b7d6tLb6lpXT+9IR4xAyZTw1IFMDZZEzVmHgYE/Et20/WhkX/oGghkWSpCxR0kynDplk+BEK2oyGKnl+rf4vymhsse2iQ/C99PhaodZjDfuGVSwPLoU0AYyAKaEwmgHPOFbDlrAmNk4iBp+IZYm9guZM2hcQ4GeA5WQyZzw4C1yMywWbdjtL9ZhpClmmPZ28nmwNORAat7tXPJoBBdXFB0gNT/wU7UYIKU5GnAiDIFJ0o8ijnuAMat3AsBki2vxwdypuBq5M6OF9DVA0HRUjOA0l4JHjK8Y282mz3U34PDPQvwCT342uD9cO3uXoSr3T2FnDmsVHz4Q9zYpSjioLmZk9ZTnQWgN5V5Oyat6m"
+ };
+
+ public String getName()
+ {
+ return "ParsingTest";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ inputStreamTest();
+ parserTest();
+ }
+
+ private void parserTest()
+ {
+ for (int i = 0; i != streams.length; i++)
+ {
+ ASN1StreamParser aIn = new ASN1StreamParser(Base64.decode(streams[i]));
+
+ try
+ {
+ Object obj;
+
+ while ((obj = aIn.readObject()) != null)
+ {
+
+ }
+
+ fail("bad stream parsed successfully!");
+ }
+ catch (IOException e)
+ {
+ // ignore
+ }
+ }
+ }
+
+ private void inputStreamTest()
+ {
+ for (int i = 0; i != streams.length; i++)
+ {
+ ASN1InputStream aIn = new ASN1InputStream(Base64.decode(streams[i]));
+
+ try
+ {
+ Object obj;
+
+ while ((obj = aIn.readObject()) != null)
+ {
+
+ }
+
+ fail("bad stream parsed successfully!");
+ }
+ catch (IOException e)
+ {
+ // ignore
+ }
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new ParsingTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/PersonalDataUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/PersonalDataUnitTest.java
new file mode 100644
index 00000000..90cdcccd
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/PersonalDataUnitTest.java
@@ -0,0 +1,121 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.x500.DirectoryString;
+import org.spongycastle.asn1.x509.sigi.NameOrPseudonym;
+import org.spongycastle.asn1.x509.sigi.PersonalData;
+
+public class PersonalDataUnitTest
+ extends ASN1UnitTest
+{
+ public String getName()
+ {
+ return "PersonalData";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ NameOrPseudonym nameOrPseudonym = new NameOrPseudonym("pseudonym");
+ BigInteger nameDistinguisher = BigInteger.valueOf(10);
+ ASN1GeneralizedTime dateOfBirth= new ASN1GeneralizedTime("20070315173729Z");
+ DirectoryString placeOfBirth = new DirectoryString("placeOfBirth");
+ String gender = "M";
+ DirectoryString postalAddress = new DirectoryString("address");
+
+ PersonalData data = new PersonalData(nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, gender, postalAddress);
+
+ checkConstruction(data, nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, gender, postalAddress);
+
+ data = new PersonalData(nameOrPseudonym, null, dateOfBirth, placeOfBirth, gender, postalAddress);
+
+ checkConstruction(data, nameOrPseudonym, null, dateOfBirth, placeOfBirth, gender, postalAddress);
+
+ data = new PersonalData(nameOrPseudonym, nameDistinguisher, null, placeOfBirth, gender, postalAddress);
+
+ checkConstruction(data, nameOrPseudonym, nameDistinguisher, null, placeOfBirth, gender, postalAddress);
+
+ data = new PersonalData(nameOrPseudonym, nameDistinguisher, dateOfBirth, null, gender, postalAddress);
+
+ checkConstruction(data, nameOrPseudonym, nameDistinguisher, dateOfBirth, null, gender, postalAddress);
+
+ data = new PersonalData(nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, null, postalAddress);
+
+ checkConstruction(data, nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, null, postalAddress);
+
+ data = new PersonalData(nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, gender, null);
+
+ checkConstruction(data, nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, gender, null);
+
+ data = PersonalData.getInstance(null);
+
+ if (data != null)
+ {
+ fail("null getInstance() failed.");
+ }
+
+ try
+ {
+ PersonalData.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ PersonalData data,
+ NameOrPseudonym nameOrPseudonym,
+ BigInteger nameDistinguisher,
+ ASN1GeneralizedTime dateOfBirth,
+ DirectoryString placeOfBirth,
+ String gender,
+ DirectoryString postalAddress)
+ throws IOException
+ {
+ checkValues(data, nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, gender, postalAddress);
+
+ data = PersonalData.getInstance(data);
+
+ checkValues(data, nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, gender, postalAddress);
+
+ ASN1InputStream aIn = new ASN1InputStream(data.toASN1Object().getEncoded());
+
+ ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
+
+ data = PersonalData.getInstance(seq);
+
+ checkValues(data, nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, gender, postalAddress);
+ }
+
+ private void checkValues(
+ PersonalData data,
+ NameOrPseudonym nameOrPseudonym,
+ BigInteger nameDistinguisher,
+ ASN1GeneralizedTime dateOfBirth,
+ DirectoryString placeOfBirth,
+ String gender,
+ DirectoryString postalAddress)
+ {
+ checkMandatoryField("nameOrPseudonym", nameOrPseudonym, data.getNameOrPseudonym());
+ checkOptionalField("nameDistinguisher", nameDistinguisher, data.getNameDistinguisher());
+ checkOptionalField("dateOfBirth", dateOfBirth, data.getDateOfBirth());
+ checkOptionalField("placeOfBirth", placeOfBirth, data.getPlaceOfBirth());
+ checkOptionalField("gender", gender, data.getGender());
+ checkOptionalField("postalAddress", postalAddress, data.getPostalAddress());
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new PersonalDataUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/ProcurationSyntaxUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/ProcurationSyntaxUnitTest.java
new file mode 100644
index 00000000..8064bc65
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/ProcurationSyntaxUnitTest.java
@@ -0,0 +1,107 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.isismtt.x509.ProcurationSyntax;
+import org.spongycastle.asn1.x500.DirectoryString;
+import org.spongycastle.asn1.x509.GeneralName;
+import org.spongycastle.asn1.x509.GeneralNames;
+import org.spongycastle.asn1.x509.IssuerSerial;
+import org.spongycastle.asn1.x509.X509Name;
+
+public class ProcurationSyntaxUnitTest
+ extends ASN1UnitTest
+{
+ public String getName()
+ {
+ return "ProcurationSyntax";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ String country = "AU";
+ DirectoryString typeOfSubstitution = new DirectoryString("substitution");
+ GeneralName thirdPerson = new GeneralName(new X509Name("CN=thirdPerson"));
+ IssuerSerial certRef = new IssuerSerial(new GeneralNames(new GeneralName(new X509Name("CN=test"))), new ASN1Integer(1));
+
+ ProcurationSyntax procuration = new ProcurationSyntax(country, typeOfSubstitution, thirdPerson);
+
+ checkConstruction(procuration, country, typeOfSubstitution, thirdPerson, null);
+
+ procuration = new ProcurationSyntax(country, typeOfSubstitution, certRef);
+
+ checkConstruction(procuration, country, typeOfSubstitution, null, certRef);
+
+ procuration = new ProcurationSyntax(null, typeOfSubstitution, certRef);
+
+ checkConstruction(procuration, null, typeOfSubstitution, null, certRef);
+
+ procuration = new ProcurationSyntax(country, null, certRef);
+
+ checkConstruction(procuration, country, null, null, certRef);
+
+ procuration = ProcurationSyntax.getInstance(null);
+
+ if (procuration != null)
+ {
+ fail("null getInstance() failed.");
+ }
+
+ try
+ {
+ ProcurationSyntax.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ ProcurationSyntax procuration,
+ String country,
+ DirectoryString typeOfSubstitution,
+ GeneralName thirdPerson,
+ IssuerSerial certRef)
+ throws IOException
+ {
+ checkValues(procuration, country, typeOfSubstitution, thirdPerson, certRef);
+
+ procuration = ProcurationSyntax.getInstance(procuration);
+
+ checkValues(procuration, country, typeOfSubstitution, thirdPerson, certRef);
+
+ ASN1InputStream aIn = new ASN1InputStream(procuration.toASN1Object().getEncoded());
+
+ ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
+
+ procuration = ProcurationSyntax.getInstance(seq);
+
+ checkValues(procuration, country, typeOfSubstitution, thirdPerson, certRef);
+ }
+
+ private void checkValues(
+ ProcurationSyntax procuration,
+ String country,
+ DirectoryString typeOfSubstitution,
+ GeneralName thirdPerson,
+ IssuerSerial certRef)
+ {
+ checkOptionalField("country", country, procuration.getCountry());
+ checkOptionalField("typeOfSubstitution", typeOfSubstitution, procuration.getTypeOfSubstitution());
+ checkOptionalField("thirdPerson", thirdPerson, procuration.getThirdPerson());
+ checkOptionalField("certRef", certRef, procuration.getCertRef());
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new ProcurationSyntaxUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/ProfessionInfoUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/ProfessionInfoUnitTest.java
new file mode 100644
index 00000000..e0bb5dda
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/ProfessionInfoUnitTest.java
@@ -0,0 +1,117 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.isismtt.x509.NamingAuthority;
+import org.spongycastle.asn1.isismtt.x509.ProcurationSyntax;
+import org.spongycastle.asn1.isismtt.x509.ProfessionInfo;
+import org.spongycastle.asn1.x500.DirectoryString;
+
+public class ProfessionInfoUnitTest
+ extends ASN1UnitTest
+{
+ public String getName()
+ {
+ return "ProfessionInfo";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ NamingAuthority auth = new NamingAuthority(new ASN1ObjectIdentifier("1.2.3"), "url", new DirectoryString("fred"));
+ DirectoryString[] professionItems = { new DirectoryString("substitution") };
+ ASN1ObjectIdentifier[] professionOids = { new ASN1ObjectIdentifier("1.2.3") };
+ String registrationNumber = "12345";
+ DEROctetString addProfInfo = new DEROctetString(new byte[20]);
+
+ ProfessionInfo info = new ProfessionInfo(auth, professionItems, professionOids, registrationNumber, addProfInfo);
+
+ checkConstruction(info, auth, professionItems, professionOids, registrationNumber, addProfInfo);
+
+ info = new ProfessionInfo(null, professionItems, professionOids, registrationNumber, addProfInfo);
+
+ checkConstruction(info, null, professionItems, professionOids, registrationNumber, addProfInfo);
+
+ info = new ProfessionInfo(auth, professionItems, null, registrationNumber, addProfInfo);
+
+ checkConstruction(info, auth, professionItems, null, registrationNumber, addProfInfo);
+
+ info = new ProfessionInfo(auth, professionItems, professionOids, null, addProfInfo);
+
+ checkConstruction(info, auth, professionItems, professionOids, null, addProfInfo);
+
+ info = new ProfessionInfo(auth, professionItems, professionOids, registrationNumber, null);
+
+ checkConstruction(info, auth, professionItems, professionOids, registrationNumber, null);
+
+ info = ProfessionInfo.getInstance(null);
+
+ if (info != null)
+ {
+ fail("null getInstance() failed.");
+ }
+
+ try
+ {
+ ProcurationSyntax.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ ProfessionInfo profInfo,
+ NamingAuthority auth,
+ DirectoryString[] professionItems,
+ ASN1ObjectIdentifier[] professionOids,
+ String registrationNumber,
+ DEROctetString addProfInfo)
+ throws IOException
+ {
+ checkValues(profInfo, auth, professionItems, professionOids, registrationNumber, addProfInfo);
+
+ profInfo = ProfessionInfo.getInstance(profInfo);
+
+ checkValues(profInfo, auth, professionItems, professionOids, registrationNumber, addProfInfo);
+
+ ASN1InputStream aIn = new ASN1InputStream(profInfo.toASN1Object().getEncoded());
+
+ ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
+
+ profInfo = ProfessionInfo.getInstance(seq);
+
+ checkValues(profInfo, auth, professionItems, professionOids, registrationNumber, addProfInfo);
+ }
+
+ private void checkValues(
+ ProfessionInfo profInfo,
+ NamingAuthority auth,
+ DirectoryString[] professionItems,
+ ASN1ObjectIdentifier[] professionOids,
+ String registrationNumber,
+ DEROctetString addProfInfo)
+ {
+ checkOptionalField("auth", auth, profInfo.getNamingAuthority());
+ checkMandatoryField("professionItems", professionItems[0], profInfo.getProfessionItems()[0]);
+ if (professionOids != null)
+ {
+ checkOptionalField("professionOids", professionOids[0], profInfo.getProfessionOIDs()[0]);
+ }
+ checkOptionalField("registrationNumber", registrationNumber, profInfo.getRegistrationNumber());
+ checkOptionalField("addProfessionInfo", addProfInfo, profInfo.getAddProfessionInfo());
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new ProfessionInfoUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/QCStatementUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/QCStatementUnitTest.java
new file mode 100644
index 00000000..9f820e2f
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/QCStatementUnitTest.java
@@ -0,0 +1,104 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.x509.qualified.QCStatement;
+import org.spongycastle.asn1.x509.qualified.RFC3739QCObjectIdentifiers;
+import org.spongycastle.asn1.x509.qualified.SemanticsInformation;
+import org.spongycastle.util.test.SimpleTest;
+
+public class QCStatementUnitTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "QCStatement";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ QCStatement mv = new QCStatement(RFC3739QCObjectIdentifiers.id_qcs_pkixQCSyntax_v1);
+
+ checkConstruction(mv, RFC3739QCObjectIdentifiers.id_qcs_pkixQCSyntax_v1, null);
+
+ ASN1Encodable info = new SemanticsInformation(new ASN1ObjectIdentifier("1.2"));
+
+ mv = new QCStatement(RFC3739QCObjectIdentifiers.id_qcs_pkixQCSyntax_v1, info);
+
+ checkConstruction(mv, RFC3739QCObjectIdentifiers.id_qcs_pkixQCSyntax_v1, info);
+
+ mv = QCStatement.getInstance(null);
+
+ if (mv != null)
+ {
+ fail("null getInstance() failed.");
+ }
+
+ try
+ {
+ QCStatement.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ QCStatement mv,
+ ASN1ObjectIdentifier statementId,
+ ASN1Encodable statementInfo)
+ throws IOException
+ {
+ checkStatement(mv, statementId, statementInfo);
+
+ mv = QCStatement.getInstance(mv);
+
+ checkStatement(mv, statementId, statementInfo);
+
+ ASN1InputStream aIn = new ASN1InputStream(mv.toASN1Object().getEncoded());
+
+ ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
+
+ mv = QCStatement.getInstance(seq);
+
+ checkStatement(mv, statementId, statementInfo);
+ }
+
+ private void checkStatement(
+ QCStatement qcs,
+ ASN1ObjectIdentifier statementId,
+ ASN1Encodable statementInfo)
+ throws IOException
+ {
+ if (!qcs.getStatementId().equals(statementId))
+ {
+ fail("statementIds don't match.");
+ }
+
+ if (statementInfo != null)
+ {
+ if (!qcs.getStatementInfo().equals(statementInfo))
+ {
+ fail("statementInfos don't match.");
+ }
+ }
+ else if (qcs.getStatementInfo() != null)
+ {
+ fail("statementInfo found when none expected.");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new QCStatementUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/RFC4519Test.java b/core/src/test/java/org/spongycastle/asn1/test/RFC4519Test.java
new file mode 100644
index 00000000..52e5b573
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/RFC4519Test.java
@@ -0,0 +1,149 @@
+package org.spongycastle.asn1.test;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.x500.X500Name;
+import org.spongycastle.asn1.x500.X500NameStyle;
+import org.spongycastle.asn1.x500.style.RFC4519Style;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class RFC4519Test
+ extends SimpleTest
+{
+ static String[] attributeTypes =
+ {
+ "businessCategory",
+ "c",
+ "cn",
+ "dc",
+ "description",
+ "destinationIndicator",
+ "distinguishedName",
+ "dnQualifier",
+ "enhancedSearchGuide",
+ "facsimileTelephoneNumber",
+ "generationQualifier",
+ "givenName",
+ "houseIdentifier",
+ "initials",
+ "internationalISDNNumber",
+ "l",
+ "member",
+ "name",
+ "o",
+ "ou",
+ "owner",
+ "physicalDeliveryOfficeName",
+ "postalAddress",
+ "postalCode",
+ "postOfficeBox",
+ "preferredDeliveryMethod",
+ "registeredAddress",
+ "roleOccupant",
+ "searchGuide",
+ "seeAlso",
+ "serialNumber",
+ "sn",
+ "st",
+ "street",
+ "telephoneNumber",
+ "teletexTerminalIdentifier",
+ "telexNumber",
+ "title",
+ "uid",
+ "uniqueMember",
+ "userPassword",
+ "x121Address",
+ "x500UniqueIdentifier"
+ };
+
+ static ASN1ObjectIdentifier[] attributeTypeOIDs =
+ {
+ new ASN1ObjectIdentifier("2.5.4.15"),
+ new ASN1ObjectIdentifier("2.5.4.6"),
+ new ASN1ObjectIdentifier("2.5.4.3"),
+ new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.25"),
+ new ASN1ObjectIdentifier("2.5.4.13"),
+ new ASN1ObjectIdentifier("2.5.4.27"),
+ new ASN1ObjectIdentifier("2.5.4.49"),
+ new ASN1ObjectIdentifier("2.5.4.46"),
+ new ASN1ObjectIdentifier("2.5.4.47"),
+ new ASN1ObjectIdentifier("2.5.4.23"),
+ new ASN1ObjectIdentifier("2.5.4.44"),
+ new ASN1ObjectIdentifier("2.5.4.42"),
+ new ASN1ObjectIdentifier("2.5.4.51"),
+ new ASN1ObjectIdentifier("2.5.4.43"),
+ new ASN1ObjectIdentifier("2.5.4.25"),
+ new ASN1ObjectIdentifier("2.5.4.7"),
+ new ASN1ObjectIdentifier("2.5.4.31"),
+ new ASN1ObjectIdentifier("2.5.4.41"),
+ new ASN1ObjectIdentifier("2.5.4.10"),
+ new ASN1ObjectIdentifier("2.5.4.11"),
+ new ASN1ObjectIdentifier("2.5.4.32"),
+ new ASN1ObjectIdentifier("2.5.4.19"),
+ new ASN1ObjectIdentifier("2.5.4.16"),
+ new ASN1ObjectIdentifier("2.5.4.17"),
+ new ASN1ObjectIdentifier("2.5.4.18"),
+ new ASN1ObjectIdentifier("2.5.4.28"),
+ new ASN1ObjectIdentifier("2.5.4.26"),
+ new ASN1ObjectIdentifier("2.5.4.33"),
+ new ASN1ObjectIdentifier("2.5.4.14"),
+ new ASN1ObjectIdentifier("2.5.4.34"),
+ new ASN1ObjectIdentifier("2.5.4.5"),
+ new ASN1ObjectIdentifier("2.5.4.4"),
+ new ASN1ObjectIdentifier("2.5.4.8"),
+ new ASN1ObjectIdentifier("2.5.4.9"),
+ new ASN1ObjectIdentifier("2.5.4.20"),
+ new ASN1ObjectIdentifier("2.5.4.22"),
+ new ASN1ObjectIdentifier("2.5.4.21"),
+ new ASN1ObjectIdentifier("2.5.4.12"),
+ new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.1"),
+ new ASN1ObjectIdentifier("2.5.4.50"),
+ new ASN1ObjectIdentifier("2.5.4.35"),
+ new ASN1ObjectIdentifier("2.5.4.24"),
+ new ASN1ObjectIdentifier("2.5.4.45")
+ };
+
+ public String getName()
+ {
+ return "RFC4519Test";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ X500NameStyle style = RFC4519Style.INSTANCE;
+
+ for (int i = 0; i != attributeTypes.length; i++)
+ {
+ if (!attributeTypeOIDs[i].equals(style.attrNameToOID(attributeTypes[i])))
+ {
+ fail("mismatch for " + attributeTypes[i]);
+ }
+ }
+
+ byte[] enc = Hex.decode("305e310b300906035504061302415531283026060355040a0c1f546865204c6567696f6e206f662074686520426f756e637920436173746c653125301006035504070c094d656c626f75726e653011060355040b0c0a4173636f742056616c65");
+
+ X500Name n = new X500Name(style, X500Name.getInstance(enc));
+
+ if (!n.toString().equals("l=Melbourne+ou=Ascot Vale,o=The Legion of the Bouncy Castle,c=AU"))
+ {
+ fail("Failed composite to string test got: " + n.toString());
+ }
+
+ n = new X500Name(style, "l=Melbourne+ou=Ascot Vale,o=The Legion of the Bouncy Castle,c=AU");
+
+ if (!Arrays.areEqual(n.getEncoded(), enc))
+ {
+ fail("re-encoding test after parse failed");
+ }
+ }
+
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new RFC4519Test());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/ReasonFlagsTest.java b/core/src/test/java/org/spongycastle/asn1/test/ReasonFlagsTest.java
new file mode 100644
index 00000000..34347914
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/ReasonFlagsTest.java
@@ -0,0 +1,35 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.x509.ReasonFlags;
+import org.spongycastle.util.test.SimpleTest;
+
+public class ReasonFlagsTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "ReasonFlags";
+ }
+
+ public void performTest()
+ throws IOException
+ {
+ BitStringConstantTester.testFlagValueCorrect(0, ReasonFlags.unused);
+ BitStringConstantTester.testFlagValueCorrect(1, ReasonFlags.keyCompromise);
+ BitStringConstantTester.testFlagValueCorrect(2, ReasonFlags.cACompromise);
+ BitStringConstantTester.testFlagValueCorrect(3, ReasonFlags.affiliationChanged);
+ BitStringConstantTester.testFlagValueCorrect(4, ReasonFlags.superseded);
+ BitStringConstantTester.testFlagValueCorrect(5, ReasonFlags.cessationOfOperation);
+ BitStringConstantTester.testFlagValueCorrect(6, ReasonFlags.certificateHold);
+ BitStringConstantTester.testFlagValueCorrect(7, ReasonFlags.privilegeWithdrawn);
+ BitStringConstantTester.testFlagValueCorrect(8, ReasonFlags.aACompromise);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new ReasonFlagsTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/RegressionTest.java b/core/src/test/java/org/spongycastle/asn1/test/RegressionTest.java
new file mode 100644
index 00000000..5fa57fa9
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/RegressionTest.java
@@ -0,0 +1,92 @@
+package org.spongycastle.asn1.test;
+
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+public class RegressionTest
+{
+ public static Test[] tests = {
+ new InputStreamTest(),
+ new EqualsAndHashCodeTest(),
+ new TagTest(),
+ new SetTest(),
+ new DERUTF8StringTest(),
+ new CertificateTest(),
+ new GenerationTest(),
+ new CMSTest(),
+ new OCSPTest(),
+ new OIDTest(),
+ new PKCS10Test(),
+ new PKCS12Test(),
+ new X509NameTest(),
+ new X500NameTest(),
+ new X509ExtensionsTest(),
+ new GeneralizedTimeTest(),
+ new BitStringTest(),
+ new MiscTest(),
+ new SMIMETest(),
+ new X9Test(),
+ new MonetaryValueUnitTest(),
+ new BiometricDataUnitTest(),
+ new Iso4217CurrencyCodeUnitTest(),
+ new SemanticsInformationUnitTest(),
+ new QCStatementUnitTest(),
+ new TypeOfBiometricDataUnitTest(),
+ new SignerLocationUnitTest(),
+ new CommitmentTypeQualifierUnitTest(),
+ new CommitmentTypeIndicationUnitTest(),
+ new EncryptedPrivateKeyInfoTest(),
+ new DataGroupHashUnitTest(),
+ new LDSSecurityObjectUnitTest(),
+ new CscaMasterListTest(),
+ new AttributeTableUnitTest(),
+ new ReasonFlagsTest(),
+ new NetscapeCertTypeTest(),
+ new PKIFailureInfoTest(),
+ new KeyUsageTest(),
+ new StringTest(),
+ new UTCTimeTest(),
+ new RequestedCertificateUnitTest(),
+ new OtherCertIDUnitTest(),
+ new OtherSigningCertificateUnitTest(),
+ new ContentHintsUnitTest(),
+ new CertHashUnitTest(),
+ new AdditionalInformationSyntaxUnitTest(),
+ new AdmissionSyntaxUnitTest(),
+ new AdmissionsUnitTest(),
+ new DeclarationOfMajorityUnitTest(),
+ new ProcurationSyntaxUnitTest(),
+ new ProfessionInfoUnitTest(),
+ new RestrictionUnitTest(),
+ new NamingAuthorityUnitTest(),
+ new MonetaryLimitUnitTest(),
+ new NameOrPseudonymUnitTest(),
+ new PersonalDataUnitTest(),
+ new DERApplicationSpecificTest(),
+ new IssuingDistributionPointUnitTest(),
+ new TargetInformationTest(),
+ new SubjectKeyIdentifierTest(),
+ new ESSCertIDv2UnitTest(),
+ new ParsingTest(),
+ new GeneralNameTest(),
+ new ObjectIdentifierTest(),
+ new RFC4519Test()
+ };
+
+ public static void main(
+ String[] args)
+ {
+ for (int i = 0; i != tests.length; i++)
+ {
+ TestResult result = tests[i].perform();
+
+ if (result.getException() != null)
+ {
+ result.getException().printStackTrace();
+ }
+
+ System.out.println(result);
+ }
+ }
+}
+
diff --git a/core/src/test/java/org/spongycastle/asn1/test/RequestedCertificateUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/RequestedCertificateUnitTest.java
new file mode 100644
index 00000000..389f07d3
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/RequestedCertificateUnitTest.java
@@ -0,0 +1,108 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.isismtt.ocsp.RequestedCertificate;
+import org.spongycastle.asn1.x509.Certificate;
+import org.spongycastle.util.encoders.Base64;
+
+public class RequestedCertificateUnitTest
+ extends ASN1UnitTest
+{
+ byte[] certBytes = Base64.decode(
+ "MIIBWzCCAQYCARgwDQYJKoZIhvcNAQEEBQAwODELMAkGA1UEBhMCQVUxDDAKBgNV"
+ + "BAgTA1FMRDEbMBkGA1UEAxMSU1NMZWF5L3JzYSB0ZXN0IENBMB4XDTk1MDYxOTIz"
+ + "MzMxMloXDTk1MDcxNzIzMzMxMlowOjELMAkGA1UEBhMCQVUxDDAKBgNVBAgTA1FM"
+ + "RDEdMBsGA1UEAxMUU1NMZWF5L3JzYSB0ZXN0IGNlcnQwXDANBgkqhkiG9w0BAQEF"
+ + "AANLADBIAkEAqtt6qS5GTxVxGZYWa0/4u+IwHf7p2LNZbcPBp9/OfIcYAXBQn8hO"
+ + "/Re1uwLKXdCjIoaGs4DLdG88rkzfyK5dPQIDAQABMAwGCCqGSIb3DQIFBQADQQAE"
+ + "Wc7EcF8po2/ZO6kNCwK/ICH6DobgLekA5lSLr5EvuioZniZp5lFzAw4+YzPQ7XKJ"
+ + "zl9HYIMxATFyqSiD9jsx");
+
+ public String getName()
+ {
+ return "RequestedCertificate";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ int type = 1;
+ byte[] certOctets = new byte[20];
+ Certificate cert = Certificate.getInstance(certBytes);
+
+ RequestedCertificate requested = new RequestedCertificate(type, certOctets);
+
+ checkConstruction(requested, type, certOctets, null);
+
+ requested = new RequestedCertificate(cert);
+
+ checkConstruction(requested, RequestedCertificate.certificate, null, cert);
+
+ requested = RequestedCertificate.getInstance(null);
+
+ if (requested != null)
+ {
+ fail("null getInstance() failed.");
+ }
+
+ try
+ {
+ RequestedCertificate.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ RequestedCertificate requested,
+ int type,
+ byte[] certOctets,
+ Certificate cert)
+ throws IOException
+ {
+ checkValues(requested, type, certOctets, cert);
+
+ requested = RequestedCertificate.getInstance(requested);
+
+ checkValues(requested, type, certOctets, cert);
+
+ ASN1InputStream aIn = new ASN1InputStream(requested.toASN1Object().getEncoded());
+
+ Object obj = aIn.readObject();
+
+ requested = RequestedCertificate.getInstance(obj);
+
+ checkValues(requested, type, certOctets, cert);
+ }
+
+ private void checkValues(
+ RequestedCertificate requested,
+ int type,
+ byte[] certOctets,
+ Certificate cert)
+ throws IOException
+ {
+ checkMandatoryField("certType", type, requested.getType());
+
+ if (requested.getType() == RequestedCertificate.certificate)
+ {
+ checkMandatoryField("certificate", cert.getEncoded(), requested.getCertificateBytes());
+ }
+ else
+ {
+ checkMandatoryField("certificateOctets", certOctets, requested.getCertificateBytes());
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new RequestedCertificateUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/RestrictionUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/RestrictionUnitTest.java
new file mode 100644
index 00000000..582d6851
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/RestrictionUnitTest.java
@@ -0,0 +1,70 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1String;
+import org.spongycastle.asn1.isismtt.x509.Restriction;
+import org.spongycastle.asn1.x500.DirectoryString;
+
+public class RestrictionUnitTest
+ extends ASN1UnitTest
+{
+ public String getName()
+ {
+ return "Restriction";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ DirectoryString res = new DirectoryString("test");
+ Restriction restriction = new Restriction(res.getString());
+
+ checkConstruction(restriction, res);
+
+ try
+ {
+ Restriction.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ Restriction restriction,
+ DirectoryString res)
+ throws IOException
+ {
+ checkValues(restriction, res);
+
+ restriction = Restriction.getInstance(restriction);
+
+ checkValues(restriction, res);
+
+ ASN1InputStream aIn = new ASN1InputStream(restriction.toASN1Object().getEncoded());
+
+ ASN1String str = (ASN1String)aIn.readObject();
+
+ restriction = Restriction.getInstance(str);
+
+ checkValues(restriction, res);
+ }
+
+ private void checkValues(
+ Restriction restriction,
+ DirectoryString res)
+ {
+ checkMandatoryField("restriction", res, restriction.getRestriction());
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new RestrictionUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/SMIMETest.java b/core/src/test/java/org/spongycastle/asn1/test/SMIMETest.java
new file mode 100644
index 00000000..e6330386
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/SMIMETest.java
@@ -0,0 +1,109 @@
+package org.spongycastle.asn1.test;
+
+import java.io.ByteArrayInputStream;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DERGeneralizedTime;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.cms.RecipientKeyIdentifier;
+import org.spongycastle.asn1.smime.SMIMECapabilitiesAttribute;
+import org.spongycastle.asn1.smime.SMIMECapability;
+import org.spongycastle.asn1.smime.SMIMECapabilityVector;
+import org.spongycastle.asn1.smime.SMIMEEncryptionKeyPreferenceAttribute;
+import org.spongycastle.util.encoders.Base64;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+public class SMIMETest
+ implements Test
+{
+ byte[] attrBytes = Base64.decode("MDQGCSqGSIb3DQEJDzEnMCUwCgYIKoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMAcGBSsOAwIH");
+ byte[] prefBytes = Base64.decode("MCwGCyqGSIb3DQEJEAILMR2hGwQIAAAAAAAAAAAYDzIwMDcwMzE1MTczNzI5Wg==");
+
+ private boolean isSameAs(
+ byte[] a,
+ byte[] b)
+ {
+ if (a.length != b.length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i != a.length; i++)
+ {
+ if (a[i] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public TestResult perform()
+ {
+ SMIMECapabilityVector caps = new SMIMECapabilityVector();
+
+ caps.addCapability(SMIMECapability.dES_EDE3_CBC);
+ caps.addCapability(SMIMECapability.rC2_CBC, 128);
+ caps.addCapability(SMIMECapability.dES_CBC);
+
+ SMIMECapabilitiesAttribute attr = new SMIMECapabilitiesAttribute(caps);
+
+ SMIMEEncryptionKeyPreferenceAttribute pref = new SMIMEEncryptionKeyPreferenceAttribute(
+ new RecipientKeyIdentifier(new DEROctetString(new byte[8]), new DERGeneralizedTime("20070315173729Z"), null));
+
+ try
+ {
+ if (!isSameAs(attr.getEncoded(), attrBytes))
+ {
+ return new SimpleTestResult(false, getName() + ": Failed attr data check");
+ }
+
+ ByteArrayInputStream bIn = new ByteArrayInputStream(attrBytes);
+ ASN1InputStream aIn = new ASN1InputStream(bIn);
+
+ ASN1Primitive o = aIn.readObject();
+ if (!attr.equals(o))
+ {
+ return new SimpleTestResult(false, getName() + ": Failed equality test for attr");
+ }
+
+ if (!isSameAs(pref.getEncoded(), prefBytes))
+ {
+ return new SimpleTestResult(false, getName() + ": Failed attr data check");
+ }
+
+ bIn = new ByteArrayInputStream(prefBytes);
+ aIn = new ASN1InputStream(bIn);
+
+ o = aIn.readObject();
+ if (!pref.equals(o))
+ {
+ return new SimpleTestResult(false, getName() + ": Failed equality test for pref");
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+ catch (Exception e)
+ {
+ return new SimpleTestResult(false, getName() + ": Failed - exception " + e.toString(), e);
+ }
+ }
+
+ public String getName()
+ {
+ return "SMIME";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ SMIMETest test = new SMIMETest();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/SemanticsInformationUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/SemanticsInformationUnitTest.java
new file mode 100644
index 00000000..400d9003
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/SemanticsInformationUnitTest.java
@@ -0,0 +1,135 @@
+package org.spongycastle.asn1.test;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.GeneralName;
+import org.spongycastle.asn1.x509.X509Name;
+import org.spongycastle.asn1.x509.qualified.SemanticsInformation;
+import org.spongycastle.util.test.SimpleTest;
+
+public class SemanticsInformationUnitTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "SemanticsInformation";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ ASN1ObjectIdentifier statementId = new ASN1ObjectIdentifier("1.1");
+ SemanticsInformation mv = new SemanticsInformation(statementId);
+
+ checkConstruction(mv, statementId, null);
+
+ GeneralName[] names = new GeneralName[2];
+
+ names[0] = new GeneralName(GeneralName.rfc822Name, "test@test.org");
+ names[1] = new GeneralName(new X509Name("cn=test"));
+
+ mv = new SemanticsInformation(statementId, names);
+
+ checkConstruction(mv, statementId, names);
+
+ mv = new SemanticsInformation(names);
+
+ checkConstruction(mv, null, names);
+
+ mv = SemanticsInformation.getInstance(null);
+
+ if (mv != null)
+ {
+ fail("null getInstance() failed.");
+ }
+
+ try
+ {
+ SemanticsInformation.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ SemanticsInformation.getInstance(new DERSequence(v));
+
+ fail("constructor failed to detect empty sequence.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ SemanticsInformation mv,
+ ASN1ObjectIdentifier semanticsIdentifier,
+ GeneralName[] names)
+ throws Exception
+ {
+ checkStatement(mv, semanticsIdentifier, names);
+
+ mv = SemanticsInformation.getInstance(mv);
+
+ checkStatement(mv, semanticsIdentifier, names);
+
+ ASN1InputStream aIn = new ASN1InputStream(mv.toASN1Object().getEncoded());
+
+ ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
+
+ mv = SemanticsInformation.getInstance(seq);
+
+ checkStatement(mv, semanticsIdentifier, names);
+ }
+
+ private void checkStatement(
+ SemanticsInformation si,
+ ASN1ObjectIdentifier id,
+ GeneralName[] names)
+ {
+ if (id != null)
+ {
+ if (!si.getSemanticsIdentifier().equals(id))
+ {
+ fail("ids don't match.");
+ }
+ }
+ else if (si.getSemanticsIdentifier() != null)
+ {
+ fail("statementId found when none expected.");
+ }
+
+ if (names != null)
+ {
+ GeneralName[] siNames = si.getNameRegistrationAuthorities();
+
+ for (int i = 0; i != siNames.length; i++)
+ {
+ if (!names[i].equals(siNames[i]))
+ {
+ fail("name registration authorities don't match.");
+ }
+ }
+ }
+ else if (si.getNameRegistrationAuthorities() != null)
+ {
+ fail("name registration authorities found when none expected.");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new SemanticsInformationUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/SetTest.java b/core/src/test/java/org/spongycastle/asn1/test/SetTest.java
new file mode 100644
index 00000000..51ad4b3f
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/SetTest.java
@@ -0,0 +1,115 @@
+package org.spongycastle.asn1.test;
+
+import org.spongycastle.asn1.ASN1Boolean;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.BERSet;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERSet;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * Set sorting test example
+ */
+public class SetTest
+ extends SimpleTest
+{
+
+ public String getName()
+ {
+ return "Set";
+ }
+
+ private void checkedSortedSet(int attempt, ASN1Set s)
+ {
+ if (s.getObjectAt(0) instanceof ASN1Boolean
+ && s.getObjectAt(1) instanceof ASN1Integer
+ && s.getObjectAt(2) instanceof DERBitString
+ && s.getObjectAt(3) instanceof DEROctetString)
+ {
+ return;
+ }
+
+ fail("sorting failed on attempt: " + attempt);
+ }
+
+ public void performTest()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ byte[] data = new byte[10];
+
+ v.add(new DEROctetString(data));
+ v.add(new DERBitString(data));
+ v.add(new ASN1Integer(100));
+ v.add(new ASN1Boolean(true));
+
+ checkedSortedSet(0, new DERSet(v));
+
+ v = new ASN1EncodableVector();
+ v.add(new ASN1Integer(100));
+ v.add(new ASN1Boolean(true));
+ v.add(new DEROctetString(data));
+ v.add(new DERBitString(data));
+
+ checkedSortedSet(1, new DERSet(v));
+
+ v = new ASN1EncodableVector();
+ v.add(new ASN1Boolean(true));
+ v.add(new DEROctetString(data));
+ v.add(new DERBitString(data));
+ v.add(new ASN1Integer(100));
+
+
+ checkedSortedSet(2, new DERSet(v));
+
+ v = new ASN1EncodableVector();
+ v.add(new DERBitString(data));
+ v.add(new DEROctetString(data));
+ v.add(new ASN1Integer(100));
+ v.add(new ASN1Boolean(true));
+
+ checkedSortedSet(3, new DERSet(v));
+
+ v = new ASN1EncodableVector();
+ v.add(new DEROctetString(data));
+ v.add(new DERBitString(data));
+ v.add(new ASN1Integer(100));
+ v.add(new ASN1Boolean(true));
+
+ ASN1Set s = new BERSet(v);
+
+ if (!(s.getObjectAt(0) instanceof DEROctetString))
+ {
+ fail("BER set sort order changed.");
+ }
+
+ // create an implicitly tagged "set" without sorting
+ ASN1TaggedObject tag = new DERTaggedObject(false, 1, new DERSequence(v));
+ s = ASN1Set.getInstance(tag, false);
+
+ if (s.getObjectAt(0) instanceof ASN1Boolean)
+ {
+ fail("sorted when shouldn't be.");
+ }
+
+ // equality test
+ v = new ASN1EncodableVector();
+
+ v.add(new ASN1Boolean(true));
+ v.add(new ASN1Boolean(true));
+ v.add(new ASN1Boolean(true));
+
+ s = new DERSet(v);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new SetTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/SignerLocationUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/SignerLocationUnitTest.java
new file mode 100644
index 00000000..44b1f66e
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/SignerLocationUnitTest.java
@@ -0,0 +1,197 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.DERUTF8String;
+import org.spongycastle.asn1.esf.SignerLocation;
+import org.spongycastle.util.test.SimpleTest;
+
+public class SignerLocationUnitTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "SignerLocation";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ DERUTF8String countryName = new DERUTF8String("Australia");
+
+ SignerLocation sl = new SignerLocation(countryName, null, null);
+
+ checkConstruction(sl, countryName, null, null);
+
+ DERUTF8String localityName = new DERUTF8String("Melbourne");
+
+ sl = new SignerLocation(null, localityName, null);
+
+ checkConstruction(sl, null, localityName, null);
+
+ sl = new SignerLocation(countryName, localityName, null);
+
+ checkConstruction(sl, countryName, localityName, null);
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new DERUTF8String("line 1"));
+ v.add(new DERUTF8String("line 2"));
+
+ ASN1Sequence postalAddress = new DERSequence(v);
+
+ sl = new SignerLocation(null, null, postalAddress);
+
+ checkConstruction(sl, null, null, postalAddress);
+
+ sl = new SignerLocation(countryName, null, postalAddress);
+
+ checkConstruction(sl, countryName, null, postalAddress);
+
+ sl = new SignerLocation(countryName, localityName, postalAddress);
+
+ checkConstruction(sl, countryName, localityName, postalAddress);
+
+ sl = SignerLocation.getInstance(null);
+
+ if (sl != null)
+ {
+ fail("null getInstance() failed.");
+ }
+
+ try
+ {
+ SignerLocation.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ //
+ // out of range postal address
+ //
+ v = new ASN1EncodableVector();
+
+ v.add(new DERUTF8String("line 1"));
+ v.add(new DERUTF8String("line 2"));
+ v.add(new DERUTF8String("line 3"));
+ v.add(new DERUTF8String("line 4"));
+ v.add(new DERUTF8String("line 5"));
+ v.add(new DERUTF8String("line 6"));
+ v.add(new DERUTF8String("line 7"));
+
+ postalAddress = new DERSequence(v);
+
+ try
+ {
+ new SignerLocation(null, null, postalAddress);
+
+ fail("constructor failed to detect bad postalAddress.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ SignerLocation.getInstance(new DERSequence(new DERTaggedObject(2, postalAddress)));
+
+ fail("sequence constructor failed to detect bad postalAddress.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ SignerLocation.getInstance(new DERSequence(new DERTaggedObject(5, postalAddress)));
+
+ fail("sequence constructor failed to detect bad tag.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkConstruction(
+ SignerLocation sl,
+ DERUTF8String countryName,
+ DERUTF8String localityName,
+ ASN1Sequence postalAddress)
+ throws IOException
+ {
+ checkValues(sl, countryName, localityName, postalAddress);
+
+ sl = SignerLocation.getInstance(sl);
+
+ checkValues(sl, countryName, localityName, postalAddress);
+
+ ASN1InputStream aIn = new ASN1InputStream(sl.toASN1Object().getEncoded());
+
+ ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
+
+ sl = SignerLocation.getInstance(seq);
+
+ checkValues(sl, countryName, localityName, postalAddress);
+ }
+
+ private void checkValues(
+ SignerLocation sl,
+ DERUTF8String countryName,
+ DERUTF8String localityName,
+ ASN1Sequence postalAddress)
+ {
+ if (countryName != null)
+ {
+ if (!countryName.equals(sl.getCountryName()))
+ {
+ fail("countryNames don't match.");
+ }
+ }
+ else if (sl.getCountryName() != null)
+ {
+ fail("countryName found when none expected.");
+ }
+
+ if (localityName != null)
+ {
+ if (!localityName.equals(sl.getLocalityName()))
+ {
+ fail("localityNames don't match.");
+ }
+ }
+ else if (sl.getLocalityName() != null)
+ {
+ fail("localityName found when none expected.");
+ }
+
+ if (postalAddress != null)
+ {
+ if (!postalAddress.equals(sl.getPostalAddress()))
+ {
+ fail("postalAddresses don't match.");
+ }
+ }
+ else if (sl.getPostalAddress() != null)
+ {
+ fail("postalAddress found when none expected.");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new SignerLocationUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/StringTest.java b/core/src/test/java/org/spongycastle/asn1/test/StringTest.java
new file mode 100644
index 00000000..acf29cf5
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/StringTest.java
@@ -0,0 +1,161 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1String;
+import org.spongycastle.asn1.DERBMPString;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERGeneralString;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.DERNumericString;
+import org.spongycastle.asn1.DERPrintableString;
+import org.spongycastle.asn1.DERT61String;
+import org.spongycastle.asn1.DERUTF8String;
+import org.spongycastle.asn1.DERUniversalString;
+import org.spongycastle.asn1.DERVisibleString;
+import org.spongycastle.util.Strings;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * X.690 test example
+ */
+public class StringTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "String";
+ }
+
+ public void performTest()
+ throws IOException
+ {
+ DERBitString bs = new DERBitString(
+ new byte[] { (byte)0x01,(byte)0x23,(byte)0x45,(byte)0x67,(byte)0x89,(byte)0xab,(byte)0xcd,(byte)0xef });
+
+ if (!bs.getString().equals("#0309000123456789ABCDEF"))
+ {
+ fail("DERBitString.getString() result incorrect");
+ }
+
+ if (!bs.toString().equals("#0309000123456789ABCDEF"))
+ {
+ fail("DERBitString.toString() result incorrect");
+ }
+
+ bs = new DERBitString(
+ new byte[] { (byte)0xfe,(byte)0xdc,(byte)0xba,(byte)0x98,(byte)0x76,(byte)0x54,(byte)0x32,(byte)0x10 });
+
+ if (!bs.getString().equals("#030900FEDCBA9876543210"))
+ {
+ fail("DERBitString.getString() result incorrect");
+ }
+
+ if (!bs.toString().equals("#030900FEDCBA9876543210"))
+ {
+ fail("DERBitString.toString() result incorrect");
+ }
+
+ DERUniversalString us = new DERUniversalString(
+ new byte[] { (byte)0x01,(byte)0x23,(byte)0x45,(byte)0x67,(byte)0x89,(byte)0xab,(byte)0xcd,(byte)0xef });
+
+ if (!us.getString().equals("#1C080123456789ABCDEF"))
+ {
+ fail("DERUniversalString.getString() result incorrect");
+ }
+
+ if (!us.toString().equals("#1C080123456789ABCDEF"))
+ {
+ fail("DERUniversalString.toString() result incorrect");
+ }
+
+ us = new DERUniversalString(
+ new byte[] { (byte)0xfe,(byte)0xdc,(byte)0xba,(byte)0x98,(byte)0x76,(byte)0x54,(byte)0x32,(byte)0x10 });
+
+ if (!us.getString().equals("#1C08FEDCBA9876543210"))
+ {
+ fail("DERUniversalString.getString() result incorrect");
+ }
+
+ if (!us.toString().equals("#1C08FEDCBA9876543210"))
+ {
+ fail("DERUniversalString.toString() result incorrect");
+ }
+
+ byte[] t61Bytes = new byte[] { -1, -2, -3, -4, -5, -6, -7, -8 };
+ String t61String = new String(t61Bytes, "iso-8859-1");
+ DERT61String t61 = new DERT61String(Strings.fromByteArray(t61Bytes));
+
+ if (!t61.getString().equals(t61String))
+ {
+ fail("DERT61String.getString() result incorrect");
+ }
+
+ if (!t61.toString().equals(t61String))
+ {
+ fail("DERT61String.toString() result incorrect");
+ }
+
+ char[] shortChars = new char[] { 'a', 'b', 'c', 'd', 'e'};
+ char[] longChars = new char[1000];
+
+ for (int i = 0; i != longChars.length; i++)
+ {
+ longChars[i] = 'X';
+ }
+
+ checkString(new DERBMPString(new String(shortChars)), new DERBMPString(new String(longChars)));
+ checkString(new DERUTF8String(new String(shortChars)), new DERUTF8String(new String(longChars)));
+ checkString(new DERIA5String(new String(shortChars)), new DERIA5String(new String(longChars)));
+ checkString(new DERPrintableString(new String(shortChars)), new DERPrintableString(new String(longChars)));
+ checkString(new DERVisibleString(new String(shortChars)), new DERVisibleString(new String(longChars)));
+ checkString(new DERGeneralString(new String(shortChars)), new DERGeneralString(new String(longChars)));
+ checkString(new DERT61String(new String(shortChars)), new DERT61String(new String(longChars)));
+
+ shortChars = new char[] { '1', '2', '3', '4', '5'};
+ longChars = new char[1000];
+
+ for (int i = 0; i != longChars.length; i++)
+ {
+ longChars[i] = '1';
+ }
+
+ checkString(new DERNumericString(new String(shortChars)), new DERNumericString(new String(longChars)));
+
+ byte[] shortBytes = new byte[] { (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e'};
+ byte[] longBytes = new byte[1000];
+
+ for (int i = 0; i != longChars.length; i++)
+ {
+ longBytes[i] = (byte)'X';
+ }
+
+ checkString(new DERUniversalString(shortBytes), new DERUniversalString(longBytes));
+
+ }
+
+ private void checkString(ASN1String shortString, ASN1String longString)
+ throws IOException
+ {
+ ASN1String short2 = (ASN1String)ASN1Primitive.fromByteArray(((ASN1Primitive)shortString).getEncoded());
+
+ if (!shortString.toString().equals(short2.toString()))
+ {
+ fail(short2.getClass().getName() + " shortBytes result incorrect");
+ }
+
+ ASN1String long2 = (ASN1String)ASN1Primitive.fromByteArray(((ASN1Primitive)longString).getEncoded());
+
+ if (!longString.toString().equals(long2.toString()))
+ {
+ fail(long2.getClass().getName() + " longBytes result incorrect");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new StringTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/SubjectKeyIdentifierTest.java b/core/src/test/java/org/spongycastle/asn1/test/SubjectKeyIdentifierTest.java
new file mode 100644
index 00000000..3aba390b
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/SubjectKeyIdentifierTest.java
@@ -0,0 +1,48 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.util.encoders.Base64;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class SubjectKeyIdentifierTest
+ extends SimpleTest
+{
+ private static byte[] pubKeyInfo = Base64.decode(
+ "MFgwCwYJKoZIhvcNAQEBA0kAMEYCQQC6wMMmHYMZszT/7bNFMn+gaZoiWJLVP8ODRuu1C2jeAe" +
+ "QpxM+5Oe7PaN2GNy3nBE4EOYkB5pMJWA0y9n04FX8NAgED");
+
+ private static byte[] shaID = Hex.decode("d8128a06d6c2feb0865994a2936e7b75b836a021");
+ private static byte[] shaTruncID = Hex.decode("436e7b75b836a021");
+
+ public String getName()
+ {
+ return "SubjectKeyIdentifier";
+ }
+
+ public void performTest()
+ throws IOException
+ {
+// SubjectPublicKeyInfo pubInfo = SubjectPublicKeyInfo.getInstance(ASN1Primitive.fromByteArray(pubKeyInfo));
+// SubjectKeyIdentifier ski = SubjectKeyIdentifier.createSHA1KeyIdentifier(pubInfo);
+//
+// if (!Arrays.areEqual(shaID, ski.getKeyIdentifier()))
+// {
+// fail("SHA-1 ID does not match");
+// }
+//
+// ski = SubjectKeyIdentifier.createTruncatedSHA1KeyIdentifier(pubInfo);
+//
+// if (!Arrays.areEqual(shaTruncID, ski.getKeyIdentifier()))
+// {
+// fail("truncated SHA-1 ID does not match");
+// }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new SubjectKeyIdentifierTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/TagTest.java b/core/src/test/java/org/spongycastle/asn1/test/TagTest.java
new file mode 100644
index 00000000..cd497de3
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/TagTest.java
@@ -0,0 +1,113 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+import java.security.SecureRandom;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERApplicationSpecific;
+import org.spongycastle.util.encoders.Base64;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+
+/**
+ * X.690 test example
+ */
+public class TagTest
+ extends SimpleTest
+{
+ byte[] longTagged = Base64.decode(
+ "ZSRzIp8gEEZFRENCQTk4NzY1NDMyMTCfIQwyMDA2MDQwMTEyMzSUCCAFERVz"
+ + "A4kCAHEXGBkalAggBRcYGRqUCCAFZS6QAkRFkQlURUNITklLRVKSBQECAwQF"
+ + "kxAREhMUFRYXGBkalAggBREVcwOJAgBxFxgZGpQIIAUXGBkalAggBWUukAJE"
+ + "RZEJVEVDSE5JS0VSkgUBAgMEBZMQERITFBUWFxgZGpQIIAURFXMDiQIAcRcY"
+ + "GRqUCCAFFxgZGpQIIAVlLpACREWRCVRFQ0hOSUtFUpIFAQIDBAWTEBESExQV"
+ + "FhcYGRqUCCAFERVzA4kCAHEXGBkalAggBRcYGRqUCCAFFxgZGpQIIAUXGBka"
+ + "lAg=");
+
+ byte[] longAppSpecificTag = Hex.decode("5F610101");
+
+ public String getName()
+ {
+ return "Tag";
+ }
+
+ public void performTest()
+ throws IOException
+ {
+ ASN1InputStream aIn = new ASN1InputStream(longTagged);
+
+ DERApplicationSpecific app = (DERApplicationSpecific)aIn.readObject();
+
+ aIn = new ASN1InputStream(app.getContents());
+
+ app = (DERApplicationSpecific)aIn.readObject();
+
+ aIn = new ASN1InputStream(app.getContents());
+
+ ASN1TaggedObject tagged = (ASN1TaggedObject)aIn.readObject();
+
+ if (tagged.getTagNo() != 32)
+ {
+ fail("unexpected tag value found - not 32");
+ }
+
+ tagged = (ASN1TaggedObject)ASN1Primitive.fromByteArray(tagged.getEncoded());
+
+ if (tagged.getTagNo() != 32)
+ {
+ fail("unexpected tag value found on recode - not 32");
+ }
+
+ tagged = (ASN1TaggedObject)aIn.readObject();
+
+ if (tagged.getTagNo() != 33)
+ {
+ fail("unexpected tag value found - not 33");
+ }
+
+ tagged = (ASN1TaggedObject)ASN1Primitive.fromByteArray(tagged.getEncoded());
+
+ if (tagged.getTagNo() != 33)
+ {
+ fail("unexpected tag value found on recode - not 33");
+ }
+
+ aIn = new ASN1InputStream(longAppSpecificTag);
+
+ app = (DERApplicationSpecific)aIn.readObject();
+
+ if (app.getApplicationTag() != 97)
+ {
+ fail("incorrect tag number read");
+ }
+
+ app = (DERApplicationSpecific)ASN1Primitive.fromByteArray(app.getEncoded());
+
+ if (app.getApplicationTag() != 97)
+ {
+ fail("incorrect tag number read on recode");
+ }
+
+ SecureRandom sr = new SecureRandom();
+ for (int i = 0; i < 100; ++i)
+ {
+ int testTag = sr.nextInt() >>> (1 + (sr.nextInt() >>> 1) % 26);
+ app = new DERApplicationSpecific(testTag, new byte[]{ 1 });
+ app = (DERApplicationSpecific)ASN1Primitive.fromByteArray(app.getEncoded());
+
+ if (app.getApplicationTag() != testTag)
+ {
+ fail("incorrect tag number read on recode (random test value: " + testTag + ")");
+ }
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new TagTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/TargetInformationTest.java b/core/src/test/java/org/spongycastle/asn1/test/TargetInformationTest.java
new file mode 100644
index 00000000..225cb4b8
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/TargetInformationTest.java
@@ -0,0 +1,48 @@
+package org.spongycastle.asn1.test;
+
+import org.spongycastle.asn1.x509.GeneralName;
+import org.spongycastle.asn1.x509.Target;
+import org.spongycastle.asn1.x509.TargetInformation;
+import org.spongycastle.asn1.x509.Targets;
+import org.spongycastle.util.test.SimpleTest;
+
+public class TargetInformationTest
+ extends SimpleTest
+{
+
+ public String getName()
+ {
+ return "TargetInformation";
+ }
+
+ public void performTest() throws Exception
+ {
+ Target[] targets = new Target[2];
+ Target targetName = new Target(Target.targetName, new GeneralName(GeneralName.dNSName, "www.test.com"));
+ Target targetGroup = new Target(Target.targetGroup, new GeneralName(GeneralName.directoryName, "o=Test, ou=Test"));
+ targets[0] = targetName;
+ targets[1] = targetGroup;
+ Targets targetss = new Targets(targets);
+ TargetInformation targetInformation1 = new TargetInformation(targetss);
+ // use an Target array
+ TargetInformation targetInformation2 = new TargetInformation(targets);
+ // targetInformation1 and targetInformation2 must have same
+ // encoding.
+ if (!targetInformation1.equals(targetInformation2))
+ {
+ fail("targetInformation1 and targetInformation2 should have the same encoding.");
+ }
+ TargetInformation targetInformation3 = TargetInformation.getInstance(targetInformation1);
+ TargetInformation targetInformation4 = TargetInformation.getInstance(targetInformation2);
+ if (!targetInformation3.equals(targetInformation4))
+ {
+ fail("targetInformation3 and targetInformation4 should have the same encoding.");
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new TargetInformationTest());
+ }
+}
+
diff --git a/core/src/test/java/org/spongycastle/asn1/test/TypeOfBiometricDataUnitTest.java b/core/src/test/java/org/spongycastle/asn1/test/TypeOfBiometricDataUnitTest.java
new file mode 100644
index 00000000..bb971d7a
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/TypeOfBiometricDataUnitTest.java
@@ -0,0 +1,144 @@
+package org.spongycastle.asn1.test;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.x509.qualified.TypeOfBiometricData;
+import org.spongycastle.util.test.SimpleTest;
+
+public class TypeOfBiometricDataUnitTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "TypeOfBiometricData";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ //
+ // predefined
+ //
+ checkPredefinedType(TypeOfBiometricData.PICTURE);
+
+ checkPredefinedType(TypeOfBiometricData.HANDWRITTEN_SIGNATURE);
+
+ //
+ // non-predefined
+ //
+ ASN1ObjectIdentifier localType = new ASN1ObjectIdentifier("1.1");
+
+ TypeOfBiometricData type = new TypeOfBiometricData(localType);
+
+ checkNonPredefined(type, localType);
+
+ type = TypeOfBiometricData.getInstance(type);
+
+ checkNonPredefined(type, localType);
+
+ ASN1Primitive obj = type.toASN1Primitive();
+
+ type = TypeOfBiometricData.getInstance(obj);
+
+ checkNonPredefined(type, localType);
+
+ type = TypeOfBiometricData.getInstance(null);
+
+ if (type != null)
+ {
+ fail("null getInstance() failed.");
+ }
+
+ try
+ {
+ TypeOfBiometricData.getInstance(new Object());
+
+ fail("getInstance() failed to detect bad object.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ new TypeOfBiometricData(100);
+
+ fail("constructor failed to detect bad predefined type.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ if (TypeOfBiometricData.PICTURE != 0)
+ {
+ fail("predefined picture should be 0");
+ }
+
+ if (TypeOfBiometricData.HANDWRITTEN_SIGNATURE != 1)
+ {
+ fail("predefined handwritten signature should be 1");
+ }
+ }
+
+ private void checkPredefinedType(
+ int predefinedType)
+ throws IOException
+ {
+ TypeOfBiometricData type = new TypeOfBiometricData(predefinedType);
+
+ checkPredefined(type, predefinedType);
+
+ type = TypeOfBiometricData.getInstance(type);
+
+ checkPredefined(type, predefinedType);
+
+ ASN1InputStream aIn = new ASN1InputStream(type.toASN1Object().getEncoded());
+
+ ASN1Primitive obj = aIn.readObject();
+
+ type = TypeOfBiometricData.getInstance(obj);
+
+ checkPredefined(type, predefinedType);
+ }
+
+ private void checkPredefined(
+ TypeOfBiometricData type,
+ int value)
+ {
+ if (!type.isPredefined())
+ {
+ fail("predefined type expected but not found.");
+ }
+
+ if (type.getPredefinedBiometricType() != value)
+ {
+ fail("predefined type does not match.");
+ }
+ }
+
+ private void checkNonPredefined(
+ TypeOfBiometricData type,
+ ASN1ObjectIdentifier value)
+ {
+ if (type.isPredefined())
+ {
+ fail("predefined type found when not expected.");
+ }
+
+ if (!type.getBiometricDataOid().equals(value))
+ {
+ fail("data oid does not match.");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new TypeOfBiometricDataUnitTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/UTCTimeTest.java b/core/src/test/java/org/spongycastle/asn1/test/UTCTimeTest.java
new file mode 100644
index 00000000..b28fb0e3
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/UTCTimeTest.java
@@ -0,0 +1,108 @@
+package org.spongycastle.asn1.test;
+
+import org.spongycastle.asn1.DERUTCTime;
+import org.spongycastle.util.test.SimpleTest;
+
+import java.text.SimpleDateFormat;
+import java.util.SimpleTimeZone;
+
+/**
+ * X.690 test example
+ */
+public class UTCTimeTest
+ extends SimpleTest
+{
+ String[] input =
+ {
+ "020122122220Z",
+ "020122122220-1000",
+ "020122122220+1000",
+ "020122122220+00",
+ "0201221222Z",
+ "0201221222-1000",
+ "0201221222+1000",
+ "0201221222+00",
+ "550122122220Z",
+ "5501221222Z"
+ };
+
+ String[] output = {
+ "20020122122220GMT+00:00",
+ "20020122122220GMT-10:00",
+ "20020122122220GMT+10:00",
+ "20020122122220GMT+00:00",
+ "20020122122200GMT+00:00",
+ "20020122122200GMT-10:00",
+ "20020122122200GMT+10:00",
+ "20020122122200GMT+00:00",
+ "19550122122220GMT+00:00",
+ "19550122122200GMT+00:00"
+ };
+
+ String[] zOutput1 = {
+ "20020122122220Z",
+ "20020122222220Z",
+ "20020122022220Z",
+ "20020122122220Z",
+ "20020122122200Z",
+ "20020122222200Z",
+ "20020122022200Z",
+ "20020122122200Z",
+ "19550122122220Z",
+ "19550122122200Z"
+ };
+
+ String[] zOutput2 = {
+ "20020122122220Z",
+ "20020122222220Z",
+ "20020122022220Z",
+ "20020122122220Z",
+ "20020122122200Z",
+ "20020122222200Z",
+ "20020122022200Z",
+ "20020122122200Z",
+ "19550122122220Z",
+ "19550122122200Z"
+ };
+
+ public String getName()
+ {
+ return "UTCTime";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ SimpleDateFormat yyyyF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
+ SimpleDateFormat yyF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
+
+ yyyyF.setTimeZone(new SimpleTimeZone(0,"Z"));
+ yyF.setTimeZone(new SimpleTimeZone(0,"Z"));
+
+ for (int i = 0; i != input.length; i++)
+ {
+ DERUTCTime t = new DERUTCTime(input[i]);
+
+ if (!t.getAdjustedTime().equals(output[i]))
+ {
+ fail("failed conversion test " + i);
+ }
+
+ if (!yyyyF.format(t.getAdjustedDate()).equals(zOutput1[i]))
+ {
+ fail("failed date conversion test " + i);
+ }
+
+ if (!yyF.format(t.getDate()).equals(zOutput2[i]))
+ {
+ fail("failed date shortened conversion test " + i);
+ }
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new UTCTimeTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/X500NameTest.java b/core/src/test/java/org/spongycastle/asn1/test/X500NameTest.java
new file mode 100644
index 00000000..09a597d3
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/X500NameTest.java
@@ -0,0 +1,771 @@
+package org.spongycastle.asn1.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OutputStream;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.ASN1String;
+import org.spongycastle.asn1.ASN1TaggedObject;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.DERPrintableString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERSet;
+import org.spongycastle.asn1.DERTaggedObject;
+import org.spongycastle.asn1.DERUTF8String;
+import org.spongycastle.asn1.x500.RDN;
+import org.spongycastle.asn1.x500.X500Name;
+import org.spongycastle.asn1.x500.X500NameBuilder;
+import org.spongycastle.asn1.x500.style.BCStrictStyle;
+import org.spongycastle.asn1.x500.style.BCStyle;
+import org.spongycastle.asn1.x500.style.IETFUtils;
+import org.spongycastle.asn1.x509.X509DefaultEntryConverter;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class X500NameTest
+ extends SimpleTest
+{
+ String[] subjects =
+ {
+ "C=AU,ST=Victoria,L=South Melbourne,O=Connect 4 Pty Ltd,OU=Webserver Team,CN=www2.connect4.com.au,E=webmaster@connect4.com.au",
+ "C=AU,ST=Victoria,L=South Melbourne,O=Connect 4 Pty Ltd,OU=Certificate Authority,CN=Connect 4 CA,E=webmaster@connect4.com.au",
+ "C=AU,ST=QLD,CN=SSLeay/rsa test cert",
+ "C=US,O=National Aeronautics and Space Administration,SERIALNUMBER=16+CN=Steve Schoch",
+ "E=cooke@issl.atl.hp.com,C=US,OU=Hewlett Packard Company (ISSL),CN=Paul A. Cooke",
+ "O=Sun Microsystems Inc,CN=store.sun.com",
+ "unstructuredAddress=192.168.1.33,unstructuredName=pixfirewall.ciscopix.com,CN=pixfirewall.ciscopix.com",
+ "CN=*.canal-plus.com,OU=Provided by TBS INTERNET http://www.tbs-certificats.com/,OU=\\ CANAL \\+,O=CANAL\\+DISTRIBUTION,L=issy les moulineaux,ST=Hauts de Seine,C=FR",
+ "O=Bouncy Castle,CN=www.bouncycastle.org\\ ",
+ "O=Bouncy Castle,CN=c:\\\\fred\\\\bob",
+ };
+
+ String[] hexSubjects =
+ {
+ "CN=\\20Test\\20X,O=\\20Test,C=GB", // input
+ "CN=\\ Test X,O=\\ Test,C=GB", // expected
+ "CN=\\20Test\\20X\\20,O=\\20Test,C=GB", // input
+ "CN=\\ Test X\\ ,O=\\ Test,C=GB" // expected
+ };
+
+ public String getName()
+ {
+ return "X500Name";
+ }
+
+ private static X500Name fromBytes(
+ byte[] bytes)
+ throws IOException
+ {
+ return X500Name.getInstance(new ASN1InputStream(new ByteArrayInputStream(bytes)).readObject());
+ }
+
+ private ASN1Encodable createEntryValue(ASN1ObjectIdentifier oid, String value)
+ {
+ X500NameBuilder builder = new X500NameBuilder(BCStyle.INSTANCE);
+
+ builder.addRDN(oid, value);
+
+ X500Name name = builder.build();
+
+ ASN1Sequence seq = (ASN1Sequence)name.toASN1Primitive();
+ ASN1Set set = ASN1Set.getInstance(seq.getObjectAt(0).toASN1Primitive());
+ seq = (ASN1Sequence)set.getObjectAt(0);
+
+ return seq.getObjectAt(1);
+ }
+
+ private ASN1Encodable createEntryValueFromString(ASN1ObjectIdentifier oid, String value)
+ {
+ X500NameBuilder builder = new X500NameBuilder(BCStyle.INSTANCE);
+
+ builder.addRDN(oid, value);
+
+ X500Name name = new X500Name(builder.build().toString());
+
+ ASN1Sequence seq = (ASN1Sequence)name.toASN1Primitive();
+ ASN1Set set = ASN1Set.getInstance(seq.getObjectAt(0).toASN1Primitive());
+ seq = (ASN1Sequence)set.getObjectAt(0);
+
+ return seq.getObjectAt(1);
+ }
+
+ private void testEncodingPrintableString(ASN1ObjectIdentifier oid, String value)
+ {
+ ASN1Encodable converted = createEntryValue(oid, value);
+ if (!(converted instanceof DERPrintableString))
+ {
+ fail("encoding for " + oid + " not printable string");
+ }
+ }
+
+ private void testEncodingIA5String(ASN1ObjectIdentifier oid, String value)
+ {
+ ASN1Encodable converted = createEntryValue(oid, value);
+ if (!(converted instanceof DERIA5String))
+ {
+ fail("encoding for " + oid + " not IA5String");
+ }
+ }
+
+ private void testEncodingUTF8String(ASN1ObjectIdentifier oid, String value)
+ throws IOException
+ {
+ ASN1Encodable converted = createEntryValue(oid, value);
+ if (!(converted instanceof DERUTF8String))
+ {
+ fail("encoding for " + oid + " not IA5String");
+ }
+ if (!value.equals((DERUTF8String.getInstance(converted.toASN1Primitive().getEncoded()).getString())))
+ {
+ fail("decoding not correct");
+ }
+ }
+
+ private void testEncodingGeneralizedTime(ASN1ObjectIdentifier oid, String value)
+ {
+ ASN1Encodable converted = createEntryValue(oid, value);
+ if (!(converted instanceof ASN1GeneralizedTime))
+ {
+ fail("encoding for " + oid + " not GeneralizedTime");
+ }
+ converted = createEntryValueFromString(oid, value);
+ if (!(converted instanceof ASN1GeneralizedTime))
+ {
+ fail("encoding for " + oid + " not GeneralizedTime");
+ }
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ ietfUtilsTest();
+
+ testEncodingPrintableString(BCStyle.C, "AU");
+ testEncodingPrintableString(BCStyle.SERIALNUMBER, "123456");
+ testEncodingPrintableString(BCStyle.DN_QUALIFIER, "123456");
+ testEncodingIA5String(BCStyle.EmailAddress, "test@test.com");
+ testEncodingIA5String(BCStyle.DC, "test");
+ // correct encoding
+ testEncodingGeneralizedTime(BCStyle.DATE_OF_BIRTH, "#180F32303032303132323132323232305A");
+ // compatibility encoding
+ testEncodingGeneralizedTime(BCStyle.DATE_OF_BIRTH, "20020122122220Z");
+ testEncodingUTF8String(BCStyle.CN, "Mörsky");
+
+ //
+ // composite
+ //
+ X500NameBuilder builder = new X500NameBuilder(BCStyle.INSTANCE);
+
+ builder.addRDN(BCStyle.C, "AU");
+ builder.addRDN(BCStyle.O, "The Legion of the Bouncy Castle");
+ builder.addRDN(BCStyle.L, "Melbourne");
+ builder.addRDN(BCStyle.ST, "Victoria");
+ builder.addRDN(BCStyle.E, "feedback-crypto@bouncycastle.org");
+
+ X500Name name1 = builder.build();
+
+ if (!name1.equals(name1))
+ {
+ fail("Failed same object test");
+ }
+
+// if (!name1.equals(name1, true))
+// {
+// fail("Failed same object test - in Order");
+// }
+
+ builder = new X500NameBuilder(BCStyle.INSTANCE);
+
+ builder.addRDN(BCStyle.C, "AU");
+ builder.addRDN(BCStyle.O, "The Legion of the Bouncy Castle");
+ builder.addRDN(BCStyle.L, "Melbourne");
+ builder.addRDN(BCStyle.ST, "Victoria");
+ builder.addRDN(BCStyle.E, "feedback-crypto@bouncycastle.org");
+
+ X500Name name2 = builder.build();
+
+ if (!name1.equals(name2))
+ {
+ fail("Failed same name test");
+ }
+
+// if (!name1.equals(name2, true))
+// {
+// fail("Failed same name test - in Order");
+// }
+
+ if (name1.hashCode() != name2.hashCode())
+ {
+ fail("Failed same name test - in Order");
+ }
+
+ X500NameBuilder builder1 = new X500NameBuilder(BCStyle.INSTANCE);
+
+ builder.addRDN(BCStyle.C, "AU");
+ builder.addRDN(BCStyle.O, "The Legion of the Bouncy Castle");
+ builder.addRDN(BCStyle.L, "Melbourne");
+ builder.addRDN(BCStyle.ST, "Victoria");
+ builder.addRDN(BCStyle.E, "feedback-crypto@bouncycastle.org");
+
+ X500NameBuilder builder2 = new X500NameBuilder(BCStyle.INSTANCE);
+
+ builder.addRDN(BCStyle.E, "feedback-crypto@bouncycastle.org");
+ builder.addRDN(BCStyle.C, "AU");
+ builder.addRDN(BCStyle.O, "The Legion of the Bouncy Castle");
+ builder.addRDN(BCStyle.L, "Melbourne");
+ builder.addRDN(BCStyle.ST, "Victoria");
+
+ name1 = builder1.build();
+ name2 = builder2.build();
+
+ if (!name1.equals(name2))
+ {
+ fail("Failed reverse name test");
+ }
+
+ if (name1.hashCode() != name2.hashCode())
+ {
+ fail("Failed reverse name test hashCode");
+ }
+
+// if (name1.equals(name2, true))
+// {
+// fail("Failed reverse name test - in Order");
+// }
+//
+// if (!name1.equals(name2, false))
+// {
+// fail("Failed reverse name test - in Order false");
+// }
+
+// Vector oids = name1.getOIDs();
+// if (!compareVectors(oids, ord1))
+// {
+// fail("oid comparison test");
+// }
+ /*
+ Vector val1 = new Vector();
+
+ val1.addElement("AU");
+ val1.addElement("The Legion of the Bouncy Castle");
+ val1.addElement("Melbourne");
+ val1.addElement("Victoria");
+ val1.addElement("feedback-crypto@bouncycastle.org");
+
+ name1 = new X500Name(ord1, val1);
+
+ Vector values = name1.getValues();
+ if (!compareVectors(values, val1))
+ {
+ fail("value comparison test");
+ }
+
+ ord2 = new Vector();
+
+ ord2.addElement(X500Name.ST);
+ ord2.addElement(X500Name.ST);
+ ord2.addElement(X500Name.L);
+ ord2.addElement(X500Name.O);
+ ord2.addElement(X500Name.C);
+
+ name1 = new X500Name(ord1, attrs);
+ name2 = new X500Name(ord2, attrs);
+
+ if (name1.equals(name2))
+ {
+ fail("Failed different name test");
+ }
+
+ ord2 = new Vector();
+
+ ord2.addElement(X500Name.ST);
+ ord2.addElement(X500Name.L);
+ ord2.addElement(X500Name.O);
+ ord2.addElement(X500Name.C);
+
+ name1 = new X500Name(ord1, attrs);
+ name2 = new X500Name(ord2, attrs);
+
+ if (name1.equals(name2))
+ {
+ fail("Failed subset name test");
+ }
+
+ compositeTest();
+ */
+ ByteArrayOutputStream bOut;
+ ASN1OutputStream aOut;
+ ASN1InputStream aIn;
+ /*
+ //
+ // getValues test
+ //
+ Vector v1 = name1.getValues(X500Name.O);
+
+ if (v1.size() != 1 || !v1.elementAt(0).equals("The Legion of the Bouncy Castle"))
+ {
+ fail("O test failed");
+ }
+
+ Vector v2 = name1.getValues(X500Name.L);
+
+ if (v2.size() != 1 || !v2.elementAt(0).equals("Melbourne"))
+ {
+ fail("L test failed");
+ }
+ */
+ //
+ // general subjects test
+ //
+ for (int i = 0; i != subjects.length; i++)
+ {
+ X500Name name = new X500Name(subjects[i]);
+
+ bOut = new ByteArrayOutputStream();
+ aOut = new ASN1OutputStream(bOut);
+
+ aOut.writeObject(name);
+
+ aIn = new ASN1InputStream(new ByteArrayInputStream(bOut.toByteArray()));
+
+ name = X500Name.getInstance(aIn.readObject());
+ if (!name.toString().equals(subjects[i]))
+ {
+ fail("failed regeneration test " + i + " got: " + name.toString() + " expected " + subjects[i]);
+ }
+ }
+
+ for (int i = 0; i < hexSubjects.length; i += 2)
+ {
+ X500Name name = new X500Name(hexSubjects[i]);
+
+ bOut = new ByteArrayOutputStream();
+ aOut = new ASN1OutputStream(bOut);
+
+ aOut.writeObject(name);
+
+ aIn = new ASN1InputStream(new ByteArrayInputStream(bOut.toByteArray()));
+
+ name = X500Name.getInstance(aIn.readObject());
+ if (!name.toString().equals(hexSubjects[i + 1]))
+ {
+ fail("failed hex regeneration test " + i + " got: " + name.toString() + " expected " + subjects[i]);
+ }
+ }
+
+ //
+ // sort test
+ //
+ X500Name unsorted = new X500Name("SERIALNUMBER=BBB + CN=AA");
+
+ if (!fromBytes(unsorted.getEncoded()).toString().equals("CN=AA+SERIALNUMBER=BBB"))
+ {
+ fail("failed sort test 1");
+ }
+
+ unsorted = new X500Name("CN=AA + SERIALNUMBER=BBB");
+
+ if (!fromBytes(unsorted.getEncoded()).toString().equals("CN=AA+SERIALNUMBER=BBB"))
+ {
+ fail("failed sort test 2");
+ }
+
+ unsorted = new X500Name("SERIALNUMBER=B + CN=AA");
+
+ if (!fromBytes(unsorted.getEncoded()).toString().equals("SERIALNUMBER=B+CN=AA"))
+ {
+ fail("failed sort test 3");
+ }
+
+ unsorted = new X500Name("CN=AA + SERIALNUMBER=B");
+
+ if (!fromBytes(unsorted.getEncoded()).toString().equals("SERIALNUMBER=B+CN=AA"))
+ {
+ fail("failed sort test 4");
+ }
+
+ //
+ // equality tests
+ //
+ equalityTest(new X500Name("CN=The Legion"), new X500Name("CN=The Legion"));
+ equalityTest(new X500Name("CN= The Legion"), new X500Name("CN=The Legion"));
+ equalityTest(new X500Name("CN=The Legion "), new X500Name("CN=The Legion"));
+ equalityTest(new X500Name("CN= The Legion "), new X500Name("CN=The Legion"));
+ equalityTest(new X500Name("CN= the legion "), new X500Name("CN=The Legion"));
+
+ equalityTest(new X500Name("CN= the legion+C=AU, O=Legion "), new X500Name("CN=The Legion+C=AU, O=Legion"));
+ // # test
+
+ X500Name n1 = new X500Name("SERIALNUMBER=8,O=ABC,CN=ABC Class 3 CA,C=LT");
+ X500Name n2 = new X500Name("2.5.4.5=8,O=ABC,CN=ABC Class 3 CA,C=LT");
+ X500Name n3 = new X500Name("2.5.4.5=#130138,O=ABC,CN=ABC Class 3 CA,C=LT");
+
+ equalityTest(n1, n2);
+ equalityTest(n2, n3);
+ equalityTest(n3, n1);
+
+ n1 = new X500Name("2.5.4.5=#130138,CN=SSC Class 3 CA,O=UAB Skaitmeninio sertifikavimo centras,C=LT");
+ n2 = new X500Name("SERIALNUMBER=#130138,CN=SSC Class 3 CA,O=UAB Skaitmeninio sertifikavimo centras,C=LT");
+ n3 = X500Name.getInstance(ASN1Primitive.fromByteArray(Hex.decode("3063310b3009060355040613024c54312f302d060355040a1326"
+ + "55414220536b6169746d656e696e696f20736572746966696b6176696d6f2063656e74726173311730150603550403130e53534320436c6173732033204341310a30080603550405130138")));
+
+ equalityTest(n1, n2);
+ equalityTest(n2, n3);
+ equalityTest(n3, n1);
+
+ n1 = new X500Name("SERIALNUMBER=8,O=XX,CN=ABC Class 3 CA,C=LT");
+ n2 = new X500Name("2.5.4.5=8,O=,CN=ABC Class 3 CA,C=LT");
+
+// if (n1.equals(n2))
+// {
+// fail("empty inequality check failed");
+// }
+
+ n1 = new X500Name("SERIALNUMBER=8,O=,CN=ABC Class 3 CA,C=LT");
+ n2 = new X500Name("2.5.4.5=8,O=,CN=ABC Class 3 CA,C=LT");
+
+ equalityTest(n1, n2);
+
+ equalityTest(X500Name.getInstance(BCStrictStyle.INSTANCE, n1), X500Name.getInstance(BCStrictStyle.INSTANCE, n2));
+
+ n2 = new X500Name("C=LT,2.5.4.5=8,O=,CN=ABC Class 3 CA");
+
+ equalityTest(n1, n2);
+
+ if (X500Name.getInstance(BCStrictStyle.INSTANCE, n1).equals(X500Name.getInstance(BCStrictStyle.INSTANCE, n2)))
+ {
+ fail("strict comparison failed");
+ }
+
+ //
+ // inequality to sequences
+ //
+ name1 = new X500Name("CN=The Legion");
+
+ if (name1.equals(new DERSequence()))
+ {
+ fail("inequality test with sequence");
+ }
+
+ if (name1.equals(new DERSequence(new DERSet())))
+ {
+ fail("inequality test with sequence and set");
+ }
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1ObjectIdentifier("1.1"));
+ v.add(new ASN1ObjectIdentifier("1.1"));
+ if (name1.equals(new DERSequence(new DERSet(new DERSet(v)))))
+ {
+ fail("inequality test with sequence and bad set");
+ }
+
+ if (name1.equals(new DERSequence(new DERSet(new DERSet(v)))))
+ {
+ fail("inequality test with sequence and bad set");
+ }
+
+ if (name1.equals(new DERSequence(new DERSet(new DERSequence()))))
+ {
+ fail("inequality test with sequence and short sequence");
+ }
+
+ if (name1.equals(new DERSequence(new DERSet(new DERSequence()))))
+ {
+ fail("inequality test with sequence and short sequence");
+ }
+
+ v = new ASN1EncodableVector();
+
+ v.add(new ASN1ObjectIdentifier("1.1"));
+ v.add(new DERSequence());
+
+ if (name1.equals(new DERSequence(new DERSet(new DERSequence(v)))))
+ {
+ fail("inequality test with sequence and bad sequence");
+ }
+
+ if (name1.equals(null))
+ {
+ fail("inequality test with null");
+ }
+
+// if (name1.equals(null, true))
+// {
+// fail("inequality test with null");
+// }
+
+ //
+ // this is contrived but it checks sorting of sets with equal elements
+ //
+ unsorted = new X500Name("CN=AA + CN=AA + CN=AA");
+
+ ASN1ObjectIdentifier[] types = unsorted.getAttributeTypes();
+ if (types.length != 3 || !types[0].equals(BCStyle.CN) || !types[1].equals(BCStyle.CN) || !types[2].equals(BCStyle.CN))
+ {
+ fail("types not matched correctly");
+ }
+
+ // general type test
+ X500Name nested = new X500Name("CN=AA + CN=AA, C=AU");
+
+ types = nested.getAttributeTypes();
+ if (types.length != 3 || !types[0].equals(BCStyle.CN) || !types[1].equals(BCStyle.CN) || !types[2].equals(BCStyle.C))
+ {
+ fail("nested types not matched correctly");
+ }
+ //
+ // tagging test - only works if CHOICE implemented
+ //
+ ASN1TaggedObject tag = new DERTaggedObject(false, 1, new X500Name("CN=AA"));
+
+ if (!tag.isExplicit())
+ {
+ fail("failed to explicitly tag CHOICE object");
+ }
+
+ X500Name name = X500Name.getInstance(tag, false);
+
+ if (!name.equals(new X500Name("CN=AA")))
+ {
+ fail("failed to recover tagged name");
+ }
+
+ DERUTF8String testString = new DERUTF8String("The Legion of the Bouncy Castle");
+ byte[] encodedBytes = testString.getEncoded();
+ byte[] hexEncodedBytes = Hex.encode(encodedBytes);
+ String hexEncodedString = "#" + new String(hexEncodedBytes);
+
+ DERUTF8String converted = (DERUTF8String)
+ new X509DefaultEntryConverter().getConvertedValue(
+ BCStyle.L , hexEncodedString);
+
+ if (!converted.equals(testString))
+ {
+ fail("failed X509DefaultEntryConverter test");
+ }
+
+ //
+ // try escaped.
+ //
+ converted = (DERUTF8String)
+ new X509DefaultEntryConverter().getConvertedValue(
+ BCStyle.L , "\\" + hexEncodedString);
+
+ if (!converted.equals(new DERUTF8String(hexEncodedString)))
+ {
+ fail("failed X509DefaultEntryConverter test got " + converted + " expected: " + hexEncodedString);
+ }
+
+ //
+ // try a weird value
+ //
+ X500Name n = new X500Name("CN=\\#nothex#string");
+
+ if (!n.toString().equals("CN=\\#nothex#string"))
+ {
+ fail("# string not properly escaped.");
+ }
+
+ RDN[] vls = n.getRDNs(BCStyle.CN);
+ if (vls.length != 1 || !getValue(vls[0]).equals("#nothex#string"))
+ {
+ fail("escaped # not reduced properly");
+ }
+
+ types = n.getAttributeTypes();
+ if (types.length != 1 || !types[0].equals(BCStyle.CN))
+ {
+ fail("type not matched correctly");
+ }
+
+ n = new X500Name("CN=\"a+b\"");
+
+ vls = n.getRDNs(BCStyle.CN);
+ if (vls.length != 1 || !getValue(vls[0]).equals("a+b"))
+ {
+ fail("escaped + not reduced properly");
+ }
+
+ n = new X500Name("CN=a\\+b");
+
+ vls = n.getRDNs(BCStyle.CN);
+ if (vls.length != 1 || !getValue(vls[0]).equals("a+b"))
+ {
+ fail("escaped + not reduced properly");
+ }
+
+ if (!n.toString().equals("CN=a\\+b"))
+ {
+ fail("+ in string not properly escaped.");
+ }
+
+ n = new X500Name("CN=a\\=b");
+
+ vls = n.getRDNs(BCStyle.CN);
+ if (vls.length != 1 || !getValue(vls[0]).equals("a=b"))
+ {
+ fail("escaped = not reduced properly");
+ }
+
+ if (!n.toString().equals("CN=a\\=b"))
+ {
+ fail("= in string not properly escaped.");
+ }
+
+ n = new X500Name("TELEPHONENUMBER=\"+61999999999\"");
+
+ vls = n.getRDNs(BCStyle.TELEPHONE_NUMBER);
+ if (vls.length != 1 || !getValue(vls[0]).equals("+61999999999"))
+ {
+ fail("telephonenumber escaped + not reduced properly");
+ }
+
+ n = new X500Name("TELEPHONENUMBER=\\+61999999999");
+
+ vls = n.getRDNs(BCStyle.TELEPHONE_NUMBER);
+ if (vls.length != 1 || !getValue(vls[0]).equals("+61999999999"))
+ {
+ fail("telephonenumber escaped + not reduced properly");
+ }
+
+ // test query methods
+ if (!"E".equals(BCStyle.INSTANCE.oidToDisplayName(BCStyle.EmailAddress)))
+ {
+ fail("display name for E incorrect");
+ }
+
+ String[] aliases = BCStyle.INSTANCE.oidToAttrNames(BCStyle.EmailAddress);
+ if (aliases.length != 2)
+ {
+ fail("no aliases found");
+ }
+ if (!("e".equals(aliases[0]) || "e".equals(aliases[1])))
+ {
+ fail("first alias name for E incorrect");
+ }
+ if (!("emailaddress".equals(aliases[0]) || "emailaddress".equals(aliases[1])))
+ {
+ fail("second alias name for E incorrect");
+ }
+
+ if (BCStyle.INSTANCE.oidToDisplayName(new ASN1ObjectIdentifier("1.2.1")) != null)
+ {
+ fail("unknown oid matched!");
+ }
+
+ if (BCStyle.INSTANCE.oidToAttrNames(new ASN1ObjectIdentifier("1.2.1")).length != 0)
+ {
+ fail("unknown oid matched aliases!");
+ }
+ }
+
+ private String getValue(RDN vl)
+ {
+ return ((ASN1String)vl.getFirst().getValue()).getString();
+ }
+
+ private void ietfUtilsTest()
+ throws Exception
+ {
+ IETFUtils.valueToString(new DERUTF8String(" "));
+ }
+
+ /*
+ private boolean compareVectors(Vector a, Vector b) // for compatibility with early JDKs
+ {
+ if (a.size() != b.size())
+ {
+ return false;
+ }
+
+ for (int i = 0; i != a.size(); i++)
+ {
+ if (!a.elementAt(i).equals(b.elementAt(i)))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private void compositeTest()
+ throws IOException
+ {
+ //
+ // composite test
+ //
+ byte[] enc = Hex.decode("305e310b300906035504061302415531283026060355040a0c1f546865204c6567696f6e206f662074686520426f756e637920436173746c653125301006035504070c094d656c626f75726e653011060355040b0c0a4173636f742056616c65");
+ ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(enc));
+
+ X500Name n = X500Name.getInstance(aIn.readObject());
+
+ if (!n.toString().equals("C=AU,O=The Legion of the Bouncy Castle,L=Melbourne+OU=Ascot Vale"))
+ {
+ fail("Failed composite to string test got: " + n.toString());
+ }
+
+ if (!n.toString(true, X500Name.DefaultSymbols).equals("L=Melbourne+OU=Ascot Vale,O=The Legion of the Bouncy Castle,C=AU"))
+ {
+ fail("Failed composite to string test got: " + n.toString(true, X500Name.DefaultSymbols));
+ }
+
+ n = new X500Name(true, "L=Melbourne+OU=Ascot Vale,O=The Legion of the Bouncy Castle,C=AU");
+ if (!n.toString().equals("C=AU,O=The Legion of the Bouncy Castle,L=Melbourne+OU=Ascot Vale"))
+ {
+ fail("Failed composite to string reversal test got: " + n.toString());
+ }
+
+ n = new X500Name("C=AU, O=The Legion of the Bouncy Castle, L=Melbourne + OU=Ascot Vale");
+
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ aOut.writeObject(n);
+
+ byte[] enc2 = bOut.toByteArray();
+
+ if (!Arrays.areEqual(enc, enc2))
+ {
+ fail("Failed composite string to encoding test");
+ }
+
+ //
+ // dud name test - handle empty DN without barfing.
+ //
+ n = new X500Name("C=CH,O=,OU=dummy,CN=mail@dummy.com");
+
+ n = X500Name.getInstance(ASN1Object.fromByteArray(n.getEncoded()));
+ }
+ */
+ private void equalityTest(X500Name name1, X500Name name2)
+ {
+ if (!name1.equals(name2))
+ {
+ fail("equality test failed for " + name1 + " : " + name2);
+ }
+
+ if (name1.hashCode() != name2.hashCode())
+ {
+ fail("hashCodeTest test failed for " + name1 + " : " + name2);
+ }
+ }
+
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new X500NameTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/X509ExtensionsTest.java b/core/src/test/java/org/spongycastle/asn1/test/X509ExtensionsTest.java
new file mode 100644
index 00000000..af99668f
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/X509ExtensionsTest.java
@@ -0,0 +1,105 @@
+package org.spongycastle.asn1.test;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.x509.X509Extensions;
+import org.spongycastle.asn1.x509.X509ExtensionsGenerator;
+import org.spongycastle.util.test.SimpleTest;
+
+public class X509ExtensionsTest
+ extends SimpleTest
+{
+ private static final ASN1ObjectIdentifier OID_2 = new ASN1ObjectIdentifier("1.2.2");
+ private static final ASN1ObjectIdentifier OID_3 = new ASN1ObjectIdentifier("1.2.3");
+ private static final ASN1ObjectIdentifier OID_1 = new ASN1ObjectIdentifier("1.2.1");
+
+ public String getName()
+ {
+ return "X509Extensions";
+ }
+
+ public void performTest() throws Exception
+ {
+ X509ExtensionsGenerator gen = new X509ExtensionsGenerator();
+
+ gen.addExtension(OID_1, true, new byte[20]);
+ gen.addExtension(OID_2, true, new byte[20]);
+
+ X509Extensions ext1 = gen.generate();
+ X509Extensions ext2 = gen.generate();
+
+ if (!ext1.equals(ext2))
+ {
+ fail("equals test failed");
+ }
+
+ gen.reset();
+
+ gen.addExtension(OID_2, true, new byte[20]);
+ gen.addExtension(OID_1, true, new byte[20]);
+
+ ext2 = gen.generate();
+
+ if (ext1.equals(ext2))
+ {
+ fail("inequality test failed");
+ }
+
+ if (!ext1.equivalent(ext2))
+ {
+ fail("equivalence true failed");
+ }
+
+ gen.reset();
+
+ gen.addExtension(OID_1, true, new byte[22]);
+ gen.addExtension(OID_2, true, new byte[20]);
+
+ ext2 = gen.generate();
+
+ if (ext1.equals(ext2))
+ {
+ fail("inequality 1 failed");
+ }
+
+ if (ext1.equivalent(ext2))
+ {
+ fail("non-equivalence 1 failed");
+ }
+
+ gen.reset();
+
+ gen.addExtension(OID_3, true, new byte[20]);
+ gen.addExtension(OID_2, true, new byte[20]);
+
+ ext2 = gen.generate();
+
+ if (ext1.equals(ext2))
+ {
+ fail("inequality 2 failed");
+ }
+
+ if (ext1.equivalent(ext2))
+ {
+ fail("non-equivalence 2 failed");
+ }
+
+ try
+ {
+ gen.addExtension(OID_2, true, new byte[20]);
+ fail("repeated oid");
+ }
+ catch (IllegalArgumentException e)
+ {
+ if (!e.getMessage().equals("extension 1.2.2 already added"))
+ {
+ fail("wrong exception on repeated oid: " + e.getMessage());
+ }
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new X509ExtensionsTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/X509NameTest.java b/core/src/test/java/org/spongycastle/asn1/test/X509NameTest.java
new file mode 100644
index 00000000..e67d47a0
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/X509NameTest.java
@@ -0,0 +1,693 @@
+package org.spongycastle.asn1.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OutputStream;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.ASN1Set;
+import org.spongycastle.asn1.DERIA5String;
+import org.spongycastle.asn1.DERPrintableString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.DERSet;
+import org.spongycastle.asn1.DERUTF8String;
+import org.spongycastle.asn1.x500.X500Name;
+import org.spongycastle.asn1.x500.X500NameBuilder;
+import org.spongycastle.asn1.x500.style.BCStyle;
+import org.spongycastle.asn1.x509.X509DefaultEntryConverter;
+import org.spongycastle.asn1.x509.X509Name;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class X509NameTest
+ extends SimpleTest
+{
+ String[] subjects =
+ {
+ "C=AU,ST=Victoria,L=South Melbourne,O=Connect 4 Pty Ltd,OU=Webserver Team,CN=www2.connect4.com.au,E=webmaster@connect4.com.au",
+ "C=AU,ST=Victoria,L=South Melbourne,O=Connect 4 Pty Ltd,OU=Certificate Authority,CN=Connect 4 CA,E=webmaster@connect4.com.au",
+ "C=AU,ST=QLD,CN=SSLeay/rsa test cert",
+ "C=US,O=National Aeronautics and Space Administration,SERIALNUMBER=16+CN=Steve Schoch",
+ "E=cooke@issl.atl.hp.com,C=US,OU=Hewlett Packard Company (ISSL),CN=Paul A. Cooke",
+ "O=Sun Microsystems Inc,CN=store.sun.com",
+ "unstructuredAddress=192.168.1.33,unstructuredName=pixfirewall.ciscopix.com,CN=pixfirewall.ciscopix.com",
+ "CN=*.canal-plus.com,OU=Provided by TBS INTERNET http://www.tbs-certificats.com/,OU=\\ CANAL \\+,O=CANAL\\+DISTRIBUTION,L=issy les moulineaux,ST=Hauts de Seine,C=FR",
+ "O=Bouncy Castle,CN=www.bouncycastle.org\\ ",
+ "O=Bouncy Castle,CN=c:\\\\fred\\\\bob"
+ };
+
+ public String getName()
+ {
+ return "X509Name";
+ }
+
+ private static X509Name fromBytes(
+ byte[] bytes)
+ throws IOException
+ {
+ return X509Name.getInstance(new ASN1InputStream(new ByteArrayInputStream(bytes)).readObject());
+ }
+
+ private ASN1Encodable createEntryValue(ASN1ObjectIdentifier oid, String value)
+ {
+ Hashtable attrs = new Hashtable();
+
+ attrs.put(oid, value);
+
+ Vector order = new Vector();
+
+ order.addElement(oid);
+
+ X509Name name = new X509Name(order, attrs);
+
+ ASN1Sequence seq = (ASN1Sequence)name.toASN1Primitive();
+ ASN1Set set = (ASN1Set)seq.getObjectAt(0);
+ seq = (ASN1Sequence)set.getObjectAt(0);
+
+ return seq.getObjectAt(1);
+ }
+
+ private ASN1Encodable createEntryValueFromString(ASN1ObjectIdentifier oid, String value)
+ {
+ Hashtable attrs = new Hashtable();
+
+ attrs.put(oid, value);
+
+ Vector order = new Vector();
+
+ order.addElement(oid);
+
+ X509Name name = new X509Name(new X509Name(order, attrs).toString());
+
+ ASN1Sequence seq = (ASN1Sequence)name.toASN1Primitive();
+ ASN1Set set = (ASN1Set)seq.getObjectAt(0);
+ seq = (ASN1Sequence)set.getObjectAt(0);
+
+ return seq.getObjectAt(1);
+ }
+
+ private void testEncodingPrintableString(ASN1ObjectIdentifier oid, String value)
+ {
+ ASN1Encodable converted = createEntryValue(oid, value);
+ if (!(converted instanceof DERPrintableString))
+ {
+ fail("encoding for " + oid + " not printable string");
+ }
+ }
+
+ private void testEncodingIA5String(ASN1ObjectIdentifier oid, String value)
+ {
+ ASN1Encodable converted = createEntryValue(oid, value);
+ if (!(converted instanceof DERIA5String))
+ {
+ fail("encoding for " + oid + " not IA5String");
+ }
+ }
+
+
+ private void testEncodingUTF8String(ASN1ObjectIdentifier oid, String value)
+ throws IOException
+ {
+ ASN1Encodable converted = createEntryValue(oid, value);
+ if (!(converted instanceof DERUTF8String))
+ {
+ fail("encoding for " + oid + " not IA5String");
+ }
+ if (!value.equals((DERUTF8String.getInstance(converted.toASN1Primitive().getEncoded()).getString())))
+ {
+ fail("decoding not correct");
+ }
+ }
+
+ private void testEncodingGeneralizedTime(ASN1ObjectIdentifier oid, String value)
+ {
+ ASN1Encodable converted = createEntryValue(oid, value);
+ if (!(converted instanceof ASN1GeneralizedTime))
+ {
+ fail("encoding for " + oid + " not GeneralizedTime");
+ }
+ converted = createEntryValueFromString(oid, value);
+ if (!(converted instanceof ASN1GeneralizedTime))
+ {
+ fail("encoding for " + oid + " not GeneralizedTime");
+ }
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ testEncodingPrintableString(X509Name.C, "AU");
+ testEncodingPrintableString(X509Name.SERIALNUMBER, "123456");
+ testEncodingPrintableString(X509Name.DN_QUALIFIER, "123456");
+ testEncodingIA5String(X509Name.EmailAddress, "test@test.com");
+ testEncodingIA5String(X509Name.DC, "test");
+ // correct encoding
+ testEncodingGeneralizedTime(X509Name.DATE_OF_BIRTH, "#180F32303032303132323132323232305A");
+ // compatibility encoding
+ testEncodingGeneralizedTime(X509Name.DATE_OF_BIRTH, "20020122122220Z");
+ testEncodingUTF8String(X509Name.CN, "Mörsky");
+ //
+ // composite
+ //
+ Hashtable attrs = new Hashtable();
+
+ attrs.put(X509Name.C, "AU");
+ attrs.put(X509Name.O, "The Legion of the Bouncy Castle");
+ attrs.put(X509Name.L, "Melbourne");
+ attrs.put(X509Name.ST, "Victoria");
+ attrs.put(X509Name.E, "feedback-crypto@bouncycastle.org");
+
+ Vector order = new Vector();
+
+ order.addElement(X509Name.C);
+ order.addElement(X509Name.O);
+ order.addElement(X509Name.L);
+ order.addElement(X509Name.ST);
+ order.addElement(X509Name.E);
+
+ X509Name name1 = new X509Name(order, attrs);
+
+ if (!name1.equals(name1))
+ {
+ fail("Failed same object test");
+ }
+
+ if (!name1.equals(name1, true))
+ {
+ fail("Failed same object test - in Order");
+ }
+
+ X509Name name2 = new X509Name(order, attrs);
+
+ if (!name1.equals(name2))
+ {
+ fail("Failed same name test");
+ }
+
+ if (!name1.equals(name2, true))
+ {
+ fail("Failed same name test - in Order");
+ }
+
+ if (name1.hashCode() != name2.hashCode())
+ {
+ fail("Failed same name test - in Order");
+ }
+
+ Vector ord1 = new Vector();
+
+ ord1.addElement(X509Name.C);
+ ord1.addElement(X509Name.O);
+ ord1.addElement(X509Name.L);
+ ord1.addElement(X509Name.ST);
+ ord1.addElement(X509Name.E);
+
+ Vector ord2 = new Vector();
+
+ ord2.addElement(X509Name.E);
+ ord2.addElement(X509Name.ST);
+ ord2.addElement(X509Name.L);
+ ord2.addElement(X509Name.O);
+ ord2.addElement(X509Name.C);
+
+ name1 = new X509Name(ord1, attrs);
+ name2 = new X509Name(ord2, attrs);
+
+ if (!name1.equals(name2))
+ {
+ fail("Failed reverse name test");
+ }
+
+ if (name1.hashCode() != name2.hashCode())
+ {
+ fail("Failed reverse name test hashCode");
+ }
+
+ if (name1.equals(name2, true))
+ {
+ fail("Failed reverse name test - in Order");
+ }
+
+ if (!name1.equals(name2, false))
+ {
+ fail("Failed reverse name test - in Order false");
+ }
+
+ Vector oids = name1.getOIDs();
+ if (!compareVectors(oids, ord1))
+ {
+ fail("oid comparison test");
+ }
+
+ Vector val1 = new Vector();
+
+ val1.addElement("AU");
+ val1.addElement("The Legion of the Bouncy Castle");
+ val1.addElement("Melbourne");
+ val1.addElement("Victoria");
+ val1.addElement("feedback-crypto@bouncycastle.org");
+
+ name1 = new X509Name(ord1, val1);
+
+ Vector values = name1.getValues();
+ if (!compareVectors(values, val1))
+ {
+ fail("value comparison test");
+ }
+
+ ord2 = new Vector();
+
+ ord2.addElement(X509Name.ST);
+ ord2.addElement(X509Name.ST);
+ ord2.addElement(X509Name.L);
+ ord2.addElement(X509Name.O);
+ ord2.addElement(X509Name.C);
+
+ name1 = new X509Name(ord1, attrs);
+ name2 = new X509Name(ord2, attrs);
+
+ if (name1.equals(name2))
+ {
+ fail("Failed different name test");
+ }
+
+ ord2 = new Vector();
+
+ ord2.addElement(X509Name.ST);
+ ord2.addElement(X509Name.L);
+ ord2.addElement(X509Name.O);
+ ord2.addElement(X509Name.C);
+
+ name1 = new X509Name(ord1, attrs);
+ name2 = new X509Name(ord2, attrs);
+
+ if (name1.equals(name2))
+ {
+ fail("Failed subset name test");
+ }
+
+ compositeTest();
+
+ ByteArrayOutputStream bOut;
+ ASN1OutputStream aOut;
+ ASN1InputStream aIn;
+
+ //
+ // getValues test
+ //
+ Vector v1 = name1.getValues(X509Name.O);
+
+ if (v1.size() != 1 || !v1.elementAt(0).equals("The Legion of the Bouncy Castle"))
+ {
+ fail("O test failed");
+ }
+
+ Vector v2 = name1.getValues(X509Name.L);
+
+ if (v2.size() != 1 || !v2.elementAt(0).equals("Melbourne"))
+ {
+ fail("L test failed");
+ }
+
+ //
+ // general subjects test
+ //
+ for (int i = 0; i != subjects.length; i++)
+ {
+ X509Name name = new X509Name(subjects[i]);
+
+ bOut = new ByteArrayOutputStream();
+ aOut = new ASN1OutputStream(bOut);
+
+ aOut.writeObject(name);
+
+ aIn = new ASN1InputStream(new ByteArrayInputStream(bOut.toByteArray()));
+
+ name = X509Name.getInstance(aIn.readObject());
+
+ if (!name.toString().equals(subjects[i]))
+ {
+ fail("failed regeneration test " + i + " got " + name.toString());
+ }
+ }
+
+ //
+ // sort test
+ //
+ X509Name unsorted = new X509Name("SERIALNUMBER=BBB + CN=AA");
+
+ if (!fromBytes(unsorted.getEncoded()).toString().equals("CN=AA+SERIALNUMBER=BBB"))
+ {
+ fail("failed sort test 1");
+ }
+
+ unsorted = new X509Name("CN=AA + SERIALNUMBER=BBB");
+
+ if (!fromBytes(unsorted.getEncoded()).toString().equals("CN=AA+SERIALNUMBER=BBB"))
+ {
+ fail("failed sort test 2");
+ }
+
+ unsorted = new X509Name("SERIALNUMBER=B + CN=AA");
+
+ if (!fromBytes(unsorted.getEncoded()).toString().equals("SERIALNUMBER=B+CN=AA"))
+ {
+ fail("failed sort test 3");
+ }
+
+ unsorted = new X509Name("CN=AA + SERIALNUMBER=B");
+
+ if (!fromBytes(unsorted.getEncoded()).toString().equals("SERIALNUMBER=B+CN=AA"))
+ {
+ fail("failed sort test 4");
+ }
+
+ //
+ // equality tests
+ //
+ equalityTest(new X509Name("CN=The Legion"), new X509Name("CN=The Legion"));
+ equalityTest(new X509Name("CN= The Legion"), new X509Name("CN=The Legion"));
+ equalityTest(new X509Name("CN=The Legion "), new X509Name("CN=The Legion"));
+ equalityTest(new X509Name("CN= The Legion "), new X509Name("CN=The Legion"));
+ equalityTest(new X509Name("CN= the legion "), new X509Name("CN=The Legion"));
+
+ // # test
+
+ X509Name n1 = new X509Name("SERIALNUMBER=8,O=ABC,CN=ABC Class 3 CA,C=LT");
+ X509Name n2 = new X509Name("2.5.4.5=8,O=ABC,CN=ABC Class 3 CA,C=LT");
+ X509Name n3 = new X509Name("2.5.4.5=#130138,O=ABC,CN=ABC Class 3 CA,C=LT");
+
+ equalityTest(n1, n2);
+ equalityTest(n2, n3);
+ equalityTest(n3, n1);
+
+ n1 = new X509Name(true, "2.5.4.5=#130138,CN=SSC Class 3 CA,O=UAB Skaitmeninio sertifikavimo centras,C=LT");
+ n2 = new X509Name(true, "SERIALNUMBER=#130138,CN=SSC Class 3 CA,O=UAB Skaitmeninio sertifikavimo centras,C=LT");
+ n3 = X509Name.getInstance(ASN1Primitive.fromByteArray(Hex.decode("3063310b3009060355040613024c54312f302d060355040a1326"
+ + "55414220536b6169746d656e696e696f20736572746966696b6176696d6f2063656e74726173311730150603550403130e53534320436c6173732033204341310a30080603550405130138")));
+
+ equalityTest(n1, n2);
+ equalityTest(n2, n3);
+ equalityTest(n3, n1);
+
+ n1 = new X509Name("SERIALNUMBER=8,O=XX,CN=ABC Class 3 CA,C=LT");
+ n2 = new X509Name("2.5.4.5=8,O=,CN=ABC Class 3 CA,C=LT");
+
+ if (n1.equals(n2))
+ {
+ fail("empty inequality check failed");
+ }
+
+ n1 = new X509Name("SERIALNUMBER=8,O=,CN=ABC Class 3 CA,C=LT");
+ n2 = new X509Name("2.5.4.5=8,O=,CN=ABC Class 3 CA,C=LT");
+
+ equalityTest(n1, n2);
+
+ //
+ // inequality to sequences
+ //
+ name1 = new X509Name("CN=The Legion");
+
+ if (name1.equals(new DERSequence()))
+ {
+ fail("inequality test with sequence");
+ }
+
+ if (name1.equals(new DERSequence(new DERSet())))
+ {
+ fail("inequality test with sequence and set");
+ }
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1ObjectIdentifier("1.1"));
+ v.add(new ASN1ObjectIdentifier("1.1"));
+ if (name1.equals(new DERSequence(new DERSet(new DERSet(v)))))
+ {
+ fail("inequality test with sequence and bad set");
+ }
+
+ if (name1.equals(new DERSequence(new DERSet(new DERSet(v))), true))
+ {
+ fail("inequality test with sequence and bad set");
+ }
+
+ if (name1.equals(new DERSequence(new DERSet(new DERSequence()))))
+ {
+ fail("inequality test with sequence and short sequence");
+ }
+
+ if (name1.equals(new DERSequence(new DERSet(new DERSequence())), true))
+ {
+ fail("inequality test with sequence and short sequence");
+ }
+
+ v = new ASN1EncodableVector();
+
+ v.add(new ASN1ObjectIdentifier("1.1"));
+ v.add(new DERSequence());
+
+ if (name1.equals(new DERSequence(new DERSet(new DERSequence(v)))))
+ {
+ fail("inequality test with sequence and bad sequence");
+ }
+
+ if (name1.equals(null))
+ {
+ fail("inequality test with null");
+ }
+
+ if (name1.equals(null, true))
+ {
+ fail("inequality test with null");
+ }
+
+ //
+ // this is contrived but it checks sorting of sets with equal elements
+ //
+ unsorted = new X509Name("CN=AA + CN=AA + CN=AA");
+
+ //
+ // tagging test - only works if CHOICE implemented
+ //
+ /*
+ ASN1TaggedObject tag = new DERTaggedObject(false, 1, new X509Name("CN=AA"));
+
+ if (!tag.isExplicit())
+ {
+ fail("failed to explicitly tag CHOICE object");
+ }
+
+ X509Name name = X509Name.getInstance(tag, false);
+
+ if (!name.equals(new X509Name("CN=AA")))
+ {
+ fail("failed to recover tagged name");
+ }
+ */
+
+ DERUTF8String testString = new DERUTF8String("The Legion of the Bouncy Castle");
+ byte[] encodedBytes = testString.getEncoded();
+ byte[] hexEncodedBytes = Hex.encode(encodedBytes);
+ String hexEncodedString = "#" + new String(hexEncodedBytes);
+
+ DERUTF8String converted = (DERUTF8String)
+ new X509DefaultEntryConverter().getConvertedValue(
+ X509Name.L , hexEncodedString);
+
+ if (!converted.equals(testString))
+ {
+ fail("failed X509DefaultEntryConverter test");
+ }
+
+ //
+ // try escaped.
+ //
+ converted = (DERUTF8String)
+ new X509DefaultEntryConverter().getConvertedValue(
+ X509Name.L , "\\" + hexEncodedString);
+
+ if (!converted.equals(new DERUTF8String(hexEncodedString)))
+ {
+ fail("failed X509DefaultEntryConverter test got " + converted + " expected: " + hexEncodedString);
+ }
+
+ //
+ // try a weird value
+ //
+ X509Name n = new X509Name("CN=\\#nothex#string");
+
+ if (!n.toString().equals("CN=\\#nothex#string"))
+ {
+ fail("# string not properly escaped.");
+ }
+
+ Vector vls = n.getValues(X509Name.CN);
+ if (vls.size() != 1 || !vls.elementAt(0).equals("#nothex#string"))
+ {
+ fail("escaped # not reduced properly");
+ }
+
+ n = new X509Name("CN=\"a+b\"");
+
+ vls = n.getValues(X509Name.CN);
+ if (vls.size() != 1 || !vls.elementAt(0).equals("a+b"))
+ {
+ fail("escaped + not reduced properly");
+ }
+
+ n = new X509Name("CN=a\\+b");
+
+ vls = n.getValues(X509Name.CN);
+ if (vls.size() != 1 || !vls.elementAt(0).equals("a+b"))
+ {
+ fail("escaped + not reduced properly");
+ }
+
+ if (!n.toString().equals("CN=a\\+b"))
+ {
+ fail("+ in string not properly escaped.");
+ }
+
+ n = new X509Name("CN=a\\=b");
+
+ vls = n.getValues(X509Name.CN);
+ if (vls.size() != 1 || !vls.elementAt(0).equals("a=b"))
+ {
+ fail("escaped = not reduced properly");
+ }
+
+ if (!n.toString().equals("CN=a\\=b"))
+ {
+ fail("= in string not properly escaped.");
+ }
+
+ n = new X509Name("TELEPHONENUMBER=\"+61999999999\"");
+
+ vls = n.getValues(X509Name.TELEPHONE_NUMBER);
+ if (vls.size() != 1 || !vls.elementAt(0).equals("+61999999999"))
+ {
+ fail("telephonenumber escaped + not reduced properly");
+ }
+
+ n = new X509Name("TELEPHONENUMBER=\\+61999999999");
+
+ vls = n.getValues(X509Name.TELEPHONE_NUMBER);
+ if (vls.size() != 1 || !vls.elementAt(0).equals("+61999999999"))
+ {
+ fail("telephonenumber escaped + not reduced properly");
+ }
+
+ // migration
+ X500NameBuilder builder = new X500NameBuilder(BCStyle.INSTANCE);
+ builder.addMultiValuedRDN(new ASN1ObjectIdentifier[] { BCStyle.CN, BCStyle.SN }, new String[] { "Thomas", "CVR:12341233-UID:1111" });
+ builder.addRDN(BCStyle.O, "Test");
+ builder.addRDN(BCStyle.C, "DK");
+
+ X500Name subject = builder.build();
+ ASN1Primitive derObject = subject.toASN1Primitive();
+ X509Name instance = X509Name.getInstance(derObject);
+ }
+
+ private boolean compareVectors(Vector a, Vector b) // for compatibility with early JDKs
+ {
+ if (a.size() != b.size())
+ {
+ return false;
+ }
+
+ for (int i = 0; i != a.size(); i++)
+ {
+ if (!a.elementAt(i).equals(b.elementAt(i)))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private void compositeTest()
+ throws IOException
+ {
+ //
+ // composite test
+ //
+ byte[] enc = Hex.decode("305e310b300906035504061302415531283026060355040a0c1f546865204c6567696f6e206f662074686520426f756e637920436173746c653125301006035504070c094d656c626f75726e653011060355040b0c0a4173636f742056616c65");
+ ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(enc));
+
+ X509Name n = X509Name.getInstance(aIn.readObject());
+
+ if (!n.toString().equals("C=AU,O=The Legion of the Bouncy Castle,L=Melbourne+OU=Ascot Vale"))
+ {
+ fail("Failed composite to string test got: " + n.toString());
+ }
+
+ if (!n.toString(true, X509Name.DefaultSymbols).equals("L=Melbourne+OU=Ascot Vale,O=The Legion of the Bouncy Castle,C=AU"))
+ {
+ fail("Failed composite to string test got: " + n.toString(true, X509Name.DefaultSymbols));
+ }
+
+ n = new X509Name(true, "L=Melbourne+OU=Ascot Vale,O=The Legion of the Bouncy Castle,C=AU");
+ if (!n.toString().equals("C=AU,O=The Legion of the Bouncy Castle,L=Melbourne+OU=Ascot Vale"))
+ {
+ fail("Failed composite to string reversal test got: " + n.toString());
+ }
+
+ n = new X509Name("C=AU, O=The Legion of the Bouncy Castle, L=Melbourne + OU=Ascot Vale");
+
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ aOut.writeObject(n);
+
+ byte[] enc2 = bOut.toByteArray();
+
+ if (!Arrays.areEqual(enc, enc2))
+ {
+ //fail("Failed composite string to encoding test");
+ }
+
+ //
+ // dud name test - handle empty DN without barfing.
+ //
+ n = new X509Name("C=CH,O=,OU=dummy,CN=mail@dummy.com");
+
+ n = X509Name.getInstance(ASN1Primitive.fromByteArray(n.getEncoded()));
+ }
+
+ private void equalityTest(X509Name x509Name, X509Name x509Name1)
+ {
+ if (!x509Name.equals(x509Name1))
+ {
+ fail("equality test failed for " + x509Name + " : " + x509Name1);
+ }
+
+ if (x509Name.hashCode() != x509Name1.hashCode())
+ {
+ fail("hashCodeTest test failed for " + x509Name + " : " + x509Name1);
+ }
+
+ if (!x509Name.equals(x509Name1, true))
+ {
+ fail("equality test failed for " + x509Name + " : " + x509Name1);
+ }
+ }
+
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new X509NameTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/asn1/test/X9Test.java b/core/src/test/java/org/spongycastle/asn1/test/X9Test.java
new file mode 100644
index 00000000..8c90e7ba
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/asn1/test/X9Test.java
@@ -0,0 +1,168 @@
+package org.spongycastle.asn1.test;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DEROctetString;
+import org.spongycastle.asn1.pkcs.PrivateKeyInfo;
+import org.spongycastle.asn1.sec.ECPrivateKey;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.spongycastle.asn1.x9.X962NamedCurves;
+import org.spongycastle.asn1.x9.X962Parameters;
+import org.spongycastle.asn1.x9.X9ECParameters;
+import org.spongycastle.asn1.x9.X9ECPoint;
+import org.spongycastle.asn1.x9.X9IntegerConverter;
+import org.spongycastle.asn1.x9.X9ObjectIdentifiers;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Base64;
+import org.spongycastle.util.test.SimpleTest;
+
+public class X9Test
+ extends SimpleTest
+{
+ private byte[] namedPub = Base64.decode("MDcwEwYHKoZIzj0CAQYIKoZIzj0DAQEDIAADG5xRI+Iki/JrvL20hoDUa7Cggzorv5B9yyqSMjYu");
+ private byte[] expPub = Base64.decode(
+ "MIH8MIHXBgcqhkjOPQIBMIHLAgEBMCkGByqGSM49AQECHn///////////////3///////4AAAA" +
+ "AAAH///////zBXBB5///////////////9///////+AAAAAAAB///////wEHiVXBfoqMGZUsfTL" +
+ "A9anUKMMJQEC1JiHF9m6FattPgMVAH1zdBaP/jRxtgqFdoahlHXTv6L/BB8DZ2iujhi7ks/PAF" +
+ "yUmqLG2UhT0OZgu/hUsclQX+laAh5///////////////9///+XXetBs6YFfDxDIUZSZVECAQED" +
+ "IAADG5xRI+Iki/JrvL20hoDUa7Cggzorv5B9yyqSMjYu");
+
+ private byte[] namedPriv = Base64.decode("MCICAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQEECDAGAgEBBAEK");
+ private byte[] expPriv = Base64.decode(
+ "MIHnAgEAMIHXBgcqhkjOPQIBMIHLAgEBMCkGByqGSM49AQECHn///////////////3///////4"
+ + "AAAAAAAH///////zBXBB5///////////////9///////+AAAAAAAB///////wEHiVXBfoqMGZU"
+ + "sfTLA9anUKMMJQEC1JiHF9m6FattPgMVAH1zdBaP/jRxtgqFdoahlHXTv6L/BB8DZ2iujhi7ks"
+ + "/PAFyUmqLG2UhT0OZgu/hUsclQX+laAh5///////////////9///+XXetBs6YFfDxDIUZSZVEC"
+ + "AQEECDAGAgEBBAEU");
+
+ private void encodePublicKey()
+ throws Exception
+ {
+ X9ECParameters ecP = X962NamedCurves.getByOID(X9ObjectIdentifiers.prime239v3);
+
+ X9IntegerConverter conv = new X9IntegerConverter();
+
+ if (conv.getByteLength(ecP.getCurve()) != 30)
+ {
+ fail("wrong byte length reported for curve");
+ }
+
+ if (ecP.getCurve().getFieldSize() != 239)
+ {
+ fail("wrong field size reported for curve");
+ }
+
+ //
+ // named curve
+ //
+ X962Parameters params = new X962Parameters(X9ObjectIdentifiers.prime192v1);
+ ECPoint point = ecP.getG().multiply(BigInteger.valueOf(100));
+
+ ASN1OctetString p = new DEROctetString(point.getEncoded(true));
+
+ SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), p.getOctets());
+ if (!areEqual(info.getEncoded(), namedPub))
+ {
+ fail("failed public named generation");
+ }
+
+ X9ECPoint x9P = new X9ECPoint(ecP.getCurve(), p);
+
+ if (!Arrays.areEqual(p.getOctets(), x9P.getPoint().getEncoded()))
+ {
+ fail("point encoding not preserved");
+ }
+
+ ASN1Primitive o = ASN1Primitive.fromByteArray(namedPub);
+
+ if (!info.equals(o))
+ {
+ fail("failed public named equality");
+ }
+
+ //
+ // explicit curve parameters
+ //
+ params = new X962Parameters(ecP);
+
+ info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), p.getOctets());
+
+ if (!areEqual(info.getEncoded(), expPub))
+ {
+ fail("failed public explicit generation");
+ }
+
+ o = ASN1Primitive.fromByteArray(expPub);
+
+ if (!info.equals(o))
+ {
+ fail("failed public explicit equality");
+ }
+ }
+
+ private void encodePrivateKey()
+ throws Exception
+ {
+ X9ECParameters ecP = X962NamedCurves.getByOID(X9ObjectIdentifiers.prime239v3);
+
+ //
+ // named curve
+ //
+ X962Parameters params = new X962Parameters(X9ObjectIdentifiers.prime192v1);
+
+ PrivateKeyInfo info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), new ECPrivateKey(BigInteger.valueOf(10)));
+
+ if (!areEqual(info.getEncoded(), namedPriv))
+ {
+ fail("failed private named generation");
+ }
+
+ ASN1Primitive o = ASN1Primitive.fromByteArray(namedPriv);
+
+ if (!info.equals(o))
+ {
+ fail("failed private named equality");
+ }
+
+ //
+ // explicit curve parameters
+ //
+ params = new X962Parameters(ecP);
+
+ info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), new ECPrivateKey(BigInteger.valueOf(20)));
+
+ if (!areEqual(info.getEncoded(), expPriv))
+ {
+ fail("failed private explicit generation");
+ }
+
+ o = ASN1Primitive.fromByteArray(expPriv);
+
+ if (!info.equals(o))
+ {
+ fail("failed private explicit equality");
+ }
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ encodePublicKey();
+ encodePrivateKey();
+ }
+
+ public String getName()
+ {
+ return "X9";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new X9Test());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/agreement/test/AllTests.java b/core/src/test/java/org/spongycastle/crypto/agreement/test/AllTests.java
new file mode 100644
index 00000000..25c42874
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/agreement/test/AllTests.java
@@ -0,0 +1,25 @@
+package org.spongycastle.crypto.agreement.test;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class AllTests
+ extends TestCase
+{
+ public static void main(String[] args)
+ {
+ junit.textui.TestRunner.run(suite());
+ }
+
+ public static Test suite()
+ {
+ TestSuite suite = new TestSuite("JPKAE Engine Tests");
+
+ suite.addTestSuite(JPAKEParticipantTest.class);
+ suite.addTestSuite(JPAKEPrimeOrderGroupTest.class);
+ suite.addTestSuite(JPAKEUtilTest.class);
+
+ return suite;
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/agreement/test/JPAKEParticipantTest.java b/core/src/test/java/org/spongycastle/crypto/agreement/test/JPAKEParticipantTest.java
new file mode 100644
index 00000000..223057fc
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/agreement/test/JPAKEParticipantTest.java
@@ -0,0 +1,561 @@
+package org.spongycastle.crypto.agreement.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import junit.framework.TestCase;
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.agreement.jpake.JPAKEParticipant;
+import org.spongycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroup;
+import org.spongycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroups;
+import org.spongycastle.crypto.agreement.jpake.JPAKERound1Payload;
+import org.spongycastle.crypto.agreement.jpake.JPAKERound2Payload;
+import org.spongycastle.crypto.agreement.jpake.JPAKERound3Payload;
+import org.spongycastle.crypto.agreement.jpake.JPAKEUtil;
+import org.spongycastle.crypto.digests.SHA256Digest;
+
+public class JPAKEParticipantTest
+ extends TestCase
+{
+
+ public void testConstruction()
+ throws CryptoException
+ {
+ JPAKEPrimeOrderGroup group = JPAKEPrimeOrderGroups.SUN_JCE_1024;
+ SecureRandom random = new SecureRandom();
+ Digest digest = new SHA256Digest();
+ String participantId = "participantId";
+ char[] password = "password".toCharArray();
+
+ // should succeed
+ new JPAKEParticipant(participantId, password, group, digest, random);
+
+ // null participantId
+ try
+ {
+ new JPAKEParticipant(null, password, group, digest, random);
+ fail();
+ }
+ catch (NullPointerException e)
+ {
+ // pass
+ }
+
+ // null password
+ try
+ {
+ new JPAKEParticipant(participantId, null, group, digest, random);
+ fail();
+ }
+ catch (NullPointerException e)
+ {
+ // pass
+ }
+
+ // empty password
+ try
+ {
+ new JPAKEParticipant(participantId, "".toCharArray(), group, digest, random);
+ fail();
+ }
+ catch (IllegalArgumentException e)
+ {
+ // pass
+ }
+
+ // null group
+ try
+ {
+ new JPAKEParticipant(participantId, password, null, digest, random);
+ fail();
+ }
+ catch (NullPointerException e)
+ {
+ // pass
+ }
+
+ // null digest
+ try
+ {
+ new JPAKEParticipant(participantId, password, group, null, random);
+ fail();
+ }
+ catch (NullPointerException e)
+ {
+ // pass
+ }
+
+ // null random
+ try
+ {
+ new JPAKEParticipant(participantId, password, group, digest, null);
+ fail();
+ }
+ catch (NullPointerException e)
+ {
+ // pass
+ }
+ }
+
+ public void testSuccessfulExchange()
+ throws CryptoException
+ {
+
+ JPAKEParticipant alice = createAlice();
+ JPAKEParticipant bob = createBob();
+
+ ExchangeAfterRound2Creation exchange = runExchangeUntilRound2Creation(alice, bob);
+
+ alice.validateRound2PayloadReceived(exchange.bobRound2Payload);
+ bob.validateRound2PayloadReceived(exchange.aliceRound2Payload);
+
+ BigInteger aliceKeyingMaterial = alice.calculateKeyingMaterial();
+ BigInteger bobKeyingMaterial = bob.calculateKeyingMaterial();
+
+ JPAKERound3Payload aliceRound3Payload = alice.createRound3PayloadToSend(aliceKeyingMaterial);
+ JPAKERound3Payload bobRound3Payload = bob.createRound3PayloadToSend(bobKeyingMaterial);
+
+ alice.validateRound3PayloadReceived(bobRound3Payload, aliceKeyingMaterial);
+ bob.validateRound3PayloadReceived(aliceRound3Payload, bobKeyingMaterial);
+
+ assertEquals(aliceKeyingMaterial, bobKeyingMaterial);
+
+ }
+
+ public void testIncorrectPassword()
+ throws CryptoException
+ {
+
+ JPAKEParticipant alice = createAlice();
+ JPAKEParticipant bob = createBobWithWrongPassword();
+
+ ExchangeAfterRound2Creation exchange = runExchangeUntilRound2Creation(alice, bob);
+
+ alice.validateRound2PayloadReceived(exchange.bobRound2Payload);
+ bob.validateRound2PayloadReceived(exchange.aliceRound2Payload);
+
+ BigInteger aliceKeyingMaterial = alice.calculateKeyingMaterial();
+ BigInteger bobKeyingMaterial = bob.calculateKeyingMaterial();
+
+ JPAKERound3Payload aliceRound3Payload = alice.createRound3PayloadToSend(aliceKeyingMaterial);
+ JPAKERound3Payload bobRound3Payload = bob.createRound3PayloadToSend(bobKeyingMaterial);
+
+ try
+ {
+ alice.validateRound3PayloadReceived(bobRound3Payload, aliceKeyingMaterial);
+ fail();
+ }
+ catch (CryptoException e)
+ {
+ // pass
+ }
+
+ try
+ {
+ bob.validateRound3PayloadReceived(aliceRound3Payload, bobKeyingMaterial);
+ fail();
+ }
+ catch (CryptoException e)
+ {
+ // pass
+ }
+
+ }
+
+ /**
+ * Tests that {@link JPAKEParticipant} throws appropriate {@link IllegalStateException}s
+ * when the methods are called in the wrong order.
+ */
+ public void testStateValidation()
+ throws CryptoException
+ {
+
+ JPAKEParticipant alice = createAlice();
+ JPAKEParticipant bob = createBob();
+
+ // We're testing alice here. Bob is just used for help.
+
+ // START ROUND 1 CHECKS
+
+ assertEquals(JPAKEParticipant.STATE_INITIALIZED, alice.getState());
+
+ // create round 2 before round 1
+ try
+ {
+ alice.createRound2PayloadToSend();
+ fail();
+ }
+ catch (IllegalStateException e)
+ {
+ // pass
+ }
+
+ JPAKERound1Payload aliceRound1Payload = alice.createRound1PayloadToSend();
+
+ assertEquals(JPAKEParticipant.STATE_ROUND_1_CREATED, alice.getState());
+
+ // create round 1 payload twice
+ try
+ {
+ alice.createRound1PayloadToSend();
+ fail();
+ }
+ catch (IllegalStateException e)
+ {
+ // pass
+ }
+
+ // create round 2 before validating round 1
+ try
+ {
+ alice.createRound2PayloadToSend();
+ fail();
+ }
+ catch (IllegalStateException e)
+ {
+ // pass
+ }
+
+ // validate round 2 before validating round 1
+ try
+ {
+ alice.validateRound2PayloadReceived(null);
+ fail();
+ }
+ catch (IllegalStateException e)
+ {
+ // pass
+ }
+
+ JPAKERound1Payload bobRound1Payload = bob.createRound1PayloadToSend();
+
+ alice.validateRound1PayloadReceived(bobRound1Payload);
+
+ assertEquals(JPAKEParticipant.STATE_ROUND_1_VALIDATED, alice.getState());
+
+ // validate round 1 payload twice
+ try
+ {
+ alice.validateRound1PayloadReceived(bobRound1Payload);
+ fail();
+ }
+ catch (IllegalStateException e)
+ {
+ // pass
+ }
+
+ bob.validateRound1PayloadReceived(aliceRound1Payload);
+
+ // START ROUND 2 CHECKS
+
+ JPAKERound2Payload aliceRound2Payload = alice.createRound2PayloadToSend();
+
+ assertEquals(JPAKEParticipant.STATE_ROUND_2_CREATED, alice.getState());
+
+ // create round 2 payload twice
+ try
+ {
+ alice.createRound2PayloadToSend();
+ fail();
+ }
+ catch (IllegalStateException e)
+ {
+ // pass
+ }
+
+ // create key before validating round 2
+ try
+ {
+ alice.calculateKeyingMaterial();
+ fail();
+ }
+ catch (IllegalStateException e)
+ {
+ // pass
+ }
+
+ // validate round 3 before validating round 2
+ try
+ {
+ alice.validateRound3PayloadReceived(null, null);
+ fail();
+ }
+ catch (IllegalStateException e)
+ {
+ // pass
+ }
+
+ JPAKERound2Payload bobRound2Payload = bob.createRound2PayloadToSend();
+
+ alice.validateRound2PayloadReceived(bobRound2Payload);
+
+ assertEquals(JPAKEParticipant.STATE_ROUND_2_VALIDATED, alice.getState());
+
+ // validate round 2 payload twice
+ try
+ {
+ alice.validateRound2PayloadReceived(bobRound2Payload);
+ fail();
+ }
+ catch (IllegalStateException e)
+ {
+ // pass
+ }
+
+ bob.validateRound2PayloadReceived(aliceRound2Payload);
+
+ // create round 3 before calculating key
+ try
+ {
+ alice.createRound3PayloadToSend(BigInteger.ONE);
+ fail();
+ }
+ catch (IllegalStateException e)
+ {
+ // pass
+ }
+
+ // START KEY CALCULATION CHECKS
+
+ BigInteger aliceKeyingMaterial = alice.calculateKeyingMaterial();
+
+ assertEquals(JPAKEParticipant.STATE_KEY_CALCULATED, alice.getState());
+
+ // calculate key twice
+ try
+ {
+ alice.calculateKeyingMaterial();
+ fail();
+ }
+ catch (IllegalStateException e)
+ {
+ // pass
+ }
+
+ BigInteger bobKeyingMaterial = bob.calculateKeyingMaterial();
+
+ // START ROUND 3 CHECKS
+
+ JPAKERound3Payload aliceRound3Payload = alice.createRound3PayloadToSend(aliceKeyingMaterial);
+
+ assertEquals(JPAKEParticipant.STATE_ROUND_3_CREATED, alice.getState());
+
+ // create round 3 payload twice
+ try
+ {
+ alice.createRound3PayloadToSend(aliceKeyingMaterial);
+ fail();
+ }
+ catch (IllegalStateException e)
+ {
+ // pass
+ }
+
+ JPAKERound3Payload bobRound3Payload = bob.createRound3PayloadToSend(bobKeyingMaterial);
+
+ alice.validateRound3PayloadReceived(bobRound3Payload, aliceKeyingMaterial);
+
+ assertEquals(JPAKEParticipant.STATE_ROUND_3_VALIDATED, alice.getState());
+
+ // validate round 3 payload twice
+ try
+ {
+ alice.validateRound3PayloadReceived(bobRound3Payload, aliceKeyingMaterial);
+ fail();
+ }
+ catch (IllegalStateException e)
+ {
+ // pass
+ }
+
+ bob.validateRound3PayloadReceived(aliceRound3Payload, bobKeyingMaterial);
+
+
+ }
+
+ /**
+ * Tests that {@link JPAKEParticipant#validateRound1PayloadReceived(JPAKERound1Payload)}
+ * calls the appropriate validate methods in {@link JPAKEUtil}.
+ * Note that {@link JPAKEUtilTest} tests the individual validate methods
+ * called by {@link JPAKEParticipant} more extensively.
+ */
+ public void testValidateRound1PayloadReceived()
+ throws CryptoException
+ {
+
+ // We're testing alice here. Bob is just used for help.
+
+ JPAKERound1Payload bobRound1Payload = createBob().createRound1PayloadToSend();
+
+ // should succeed
+ createAlice().validateRound1PayloadReceived(bobRound1Payload);
+
+ // alice verifies alice's payload
+ try
+ {
+ JPAKEParticipant alice = createAlice();
+ alice.validateRound1PayloadReceived(alice.createRound1PayloadToSend());
+ fail();
+ }
+ catch (CryptoException e)
+ {
+ // pass
+ }
+
+ // g^x4 == 1
+ try
+ {
+ createAlice().validateRound1PayloadReceived(new JPAKERound1Payload(
+ bobRound1Payload.getParticipantId(),
+ bobRound1Payload.getGx1(),
+ BigInteger.ONE,
+ bobRound1Payload.getKnowledgeProofForX1(),
+ bobRound1Payload.getKnowledgeProofForX2()));
+ fail();
+ }
+ catch (CryptoException e)
+ {
+ // pass
+ }
+
+ // zero knowledge proof for x3 fails
+ try
+ {
+ JPAKERound1Payload bobRound1Payload2 = createBob().createRound1PayloadToSend();
+ createAlice().validateRound1PayloadReceived(new JPAKERound1Payload(
+ bobRound1Payload.getParticipantId(),
+ bobRound1Payload.getGx1(),
+ bobRound1Payload.getGx2(),
+ bobRound1Payload2.getKnowledgeProofForX1(),
+ bobRound1Payload.getKnowledgeProofForX2()));
+ fail();
+ }
+ catch (CryptoException e)
+ {
+ // pass
+ }
+
+ // zero knowledge proof for x4 fails
+ try
+ {
+ JPAKERound1Payload bobRound1Payload2 = createBob().createRound1PayloadToSend();
+ createAlice().validateRound1PayloadReceived(new JPAKERound1Payload(
+ bobRound1Payload.getParticipantId(),
+ bobRound1Payload.getGx1(),
+ bobRound1Payload.getGx2(),
+ bobRound1Payload.getKnowledgeProofForX1(),
+ bobRound1Payload2.getKnowledgeProofForX2()));
+ fail();
+ }
+ catch (CryptoException e)
+ {
+ // pass
+ }
+
+ }
+
+ /**
+ * Tests that {@link JPAKEParticipant#validateRound2PayloadReceived(JPAKERound2Payload)}
+ * calls the appropriate validate methods in {@link JPAKEUtil}.
+ * Note that {@link JPAKEUtilTest} tests the individual validate methods
+ * called by {@link JPAKEParticipant} more extensively.
+ */
+ public void testValidateRound2PayloadReceived()
+ throws CryptoException
+ {
+
+ // We're testing alice here. Bob is just used for help.
+
+ // should succeed
+ ExchangeAfterRound2Creation exchange1 = runExchangeUntilRound2Creation(createAlice(), createBob());
+ exchange1.alice.validateRound2PayloadReceived(exchange1.bobRound2Payload);
+
+ // alice verifies alice's payload
+ ExchangeAfterRound2Creation exchange2 = runExchangeUntilRound2Creation(createAlice(), createBob());
+ try
+ {
+ exchange2.alice.validateRound2PayloadReceived(exchange2.aliceRound2Payload);
+ fail();
+ }
+ catch (CryptoException e)
+ {
+ // pass
+ }
+
+ // wrong z
+ ExchangeAfterRound2Creation exchange3 = runExchangeUntilRound2Creation(createAlice(), createBob());
+ ExchangeAfterRound2Creation exchange4 = runExchangeUntilRound2Creation(createAlice(), createBob());
+ try
+ {
+ exchange3.alice.validateRound2PayloadReceived(exchange4.bobRound2Payload);
+ fail();
+ }
+ catch (CryptoException e)
+ {
+ // pass
+ }
+
+ }
+
+ private static class ExchangeAfterRound2Creation
+ {
+
+ public JPAKEParticipant alice;
+ public JPAKERound2Payload aliceRound2Payload;
+ public JPAKERound2Payload bobRound2Payload;
+
+ public ExchangeAfterRound2Creation(
+ JPAKEParticipant alice,
+ JPAKERound2Payload aliceRound2Payload,
+ JPAKERound2Payload bobRound2Payload)
+ {
+ this.alice = alice;
+ this.aliceRound2Payload = aliceRound2Payload;
+ this.bobRound2Payload = bobRound2Payload;
+ }
+
+ }
+
+ private ExchangeAfterRound2Creation runExchangeUntilRound2Creation(JPAKEParticipant alice, JPAKEParticipant bob)
+ throws CryptoException
+ {
+ JPAKERound1Payload aliceRound1Payload = alice.createRound1PayloadToSend();
+ JPAKERound1Payload bobRound1Payload = bob.createRound1PayloadToSend();
+
+ alice.validateRound1PayloadReceived(bobRound1Payload);
+ bob.validateRound1PayloadReceived(aliceRound1Payload);
+
+ JPAKERound2Payload aliceRound2Payload = alice.createRound2PayloadToSend();
+ JPAKERound2Payload bobRound2Payload = bob.createRound2PayloadToSend();
+
+ return new ExchangeAfterRound2Creation(
+ alice,
+ aliceRound2Payload,
+ bobRound2Payload);
+ }
+
+ private JPAKEParticipant createAlice()
+ {
+ return createParticipant("alice", "password");
+ }
+
+ private JPAKEParticipant createBob()
+ {
+ return createParticipant("bob", "password");
+ }
+
+ private JPAKEParticipant createBobWithWrongPassword()
+ {
+ return createParticipant("bob", "wrong");
+ }
+
+ private JPAKEParticipant createParticipant(String participantId, String password)
+ {
+ return new JPAKEParticipant(
+ participantId,
+ password.toCharArray(),
+ JPAKEPrimeOrderGroups.SUN_JCE_1024);
+ }
+
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/agreement/test/JPAKEPrimeOrderGroupTest.java b/core/src/test/java/org/spongycastle/crypto/agreement/test/JPAKEPrimeOrderGroupTest.java
new file mode 100644
index 00000000..b02a8f6c
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/agreement/test/JPAKEPrimeOrderGroupTest.java
@@ -0,0 +1,85 @@
+package org.spongycastle.crypto.agreement.test;
+
+import java.math.BigInteger;
+
+import junit.framework.TestCase;
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroup;
+
+public class JPAKEPrimeOrderGroupTest
+ extends TestCase
+{
+
+ public void testConstruction()
+ throws CryptoException
+ {
+ // p-1 not evenly divisible by q
+ try
+ {
+ new JPAKEPrimeOrderGroup(BigInteger.valueOf(7), BigInteger.valueOf(5), BigInteger.valueOf(6));
+ fail();
+ }
+ catch (IllegalArgumentException e)
+ {
+ // pass
+ }
+
+ // g < 2
+ try
+ {
+ new JPAKEPrimeOrderGroup(BigInteger.valueOf(11), BigInteger.valueOf(5), BigInteger.valueOf(1));
+ fail();
+ }
+ catch (IllegalArgumentException e)
+ {
+ // pass
+ }
+
+ // g > p-1
+ try
+ {
+ new JPAKEPrimeOrderGroup(BigInteger.valueOf(11), BigInteger.valueOf(5), BigInteger.valueOf(11));
+ fail();
+ }
+ catch (IllegalArgumentException e)
+ {
+ // pass
+ }
+
+ // g^q mod p not equal 1
+ try
+ {
+ new JPAKEPrimeOrderGroup(BigInteger.valueOf(11), BigInteger.valueOf(5), BigInteger.valueOf(6));
+ fail();
+ }
+ catch (IllegalArgumentException e)
+ {
+ // pass
+ }
+
+ // p not prime
+ try
+ {
+ new JPAKEPrimeOrderGroup(BigInteger.valueOf(15), BigInteger.valueOf(2), BigInteger.valueOf(4));
+ fail();
+ }
+ catch (IllegalArgumentException e)
+ {
+ // pass
+ }
+
+ // q not prime
+ try
+ {
+ new JPAKEPrimeOrderGroup(BigInteger.valueOf(7), BigInteger.valueOf(6), BigInteger.valueOf(3));
+ fail();
+ }
+ catch (IllegalArgumentException e)
+ {
+ // pass
+ }
+
+ // should succeed
+ new JPAKEPrimeOrderGroup(BigInteger.valueOf(7), BigInteger.valueOf(3), BigInteger.valueOf(4));
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/agreement/test/JPAKEUtilTest.java b/core/src/test/java/org/spongycastle/crypto/agreement/test/JPAKEUtilTest.java
new file mode 100644
index 00000000..beaa2be0
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/agreement/test/JPAKEUtilTest.java
@@ -0,0 +1,267 @@
+package org.spongycastle.crypto.agreement.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import junit.framework.TestCase;
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroup;
+import org.spongycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroups;
+import org.spongycastle.crypto.agreement.jpake.JPAKEUtil;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+
+public class JPAKEUtilTest
+ extends TestCase
+{
+ private static final BigInteger TEN = BigInteger.valueOf(10);
+
+ public void testValidateGx4()
+ throws CryptoException
+ {
+ JPAKEUtil.validateGx4(TEN);
+
+ try
+ {
+ JPAKEUtil.validateGx4(BigInteger.ONE);
+ fail();
+ }
+ catch (CryptoException e)
+ {
+ // pass
+ }
+ }
+
+ public void testValidateGa()
+ throws CryptoException
+ {
+ JPAKEUtil.validateGa(TEN);
+
+ try
+ {
+ JPAKEUtil.validateGa(BigInteger.ONE);
+ fail();
+ }
+ catch (CryptoException e)
+ {
+ // pass
+ }
+ }
+
+ public void testValidateParticipantIdsDiffer()
+ throws CryptoException
+ {
+ JPAKEUtil.validateParticipantIdsDiffer("a", "b");
+ JPAKEUtil.validateParticipantIdsDiffer("a", "A");
+
+ try
+ {
+ JPAKEUtil.validateParticipantIdsDiffer("a", "a");
+ fail();
+ }
+ catch (CryptoException e)
+ {
+ // pass
+ }
+ }
+
+ public void testValidateParticipantIdsEqual()
+ throws CryptoException
+ {
+ JPAKEUtil.validateParticipantIdsEqual("a", "a");
+
+ try
+ {
+ JPAKEUtil.validateParticipantIdsEqual("a", "b");
+ fail();
+ }
+ catch (CryptoException e)
+ {
+ // pass
+ }
+ }
+
+ public void testValidateMacTag()
+ throws CryptoException
+ {
+ JPAKEPrimeOrderGroup pg1 = JPAKEPrimeOrderGroups.SUN_JCE_1024;
+
+ SecureRandom random = new SecureRandom();
+ Digest digest = new SHA256Digest();
+
+ BigInteger x1 = JPAKEUtil.generateX1(pg1.getQ(), random);
+ BigInteger x2 = JPAKEUtil.generateX2(pg1.getQ(), random);
+ BigInteger x3 = JPAKEUtil.generateX1(pg1.getQ(), random);
+ BigInteger x4 = JPAKEUtil.generateX2(pg1.getQ(), random);
+
+ BigInteger gx1 = JPAKEUtil.calculateGx(pg1.getP(), pg1.getG(), x1);
+ BigInteger gx2 = JPAKEUtil.calculateGx(pg1.getP(), pg1.getG(), x2);
+ BigInteger gx3 = JPAKEUtil.calculateGx(pg1.getP(), pg1.getG(), x3);
+ BigInteger gx4 = JPAKEUtil.calculateGx(pg1.getP(), pg1.getG(), x4);
+
+ BigInteger gB = JPAKEUtil.calculateGA(pg1.getP(), gx3, gx1, gx2);
+
+ BigInteger s = JPAKEUtil.calculateS("password".toCharArray());
+
+ BigInteger xs = JPAKEUtil.calculateX2s(pg1.getQ(), x4, s);
+
+ BigInteger B = JPAKEUtil.calculateA(pg1.getP(), pg1.getQ(), gB, xs);
+
+ BigInteger keyingMaterial = JPAKEUtil.calculateKeyingMaterial(pg1.getP(), pg1.getQ(), gx4, x2, s, B);
+
+ BigInteger macTag = JPAKEUtil.calculateMacTag("participantId", "partnerParticipantId", gx1, gx2, gx3, gx4, keyingMaterial, digest);
+
+ // should succed
+ JPAKEUtil.validateMacTag("partnerParticipantId", "participantId", gx3, gx4, gx1, gx2, keyingMaterial, digest, macTag);
+
+ // validating own macTag (as opposed to the other party's mactag)
+ try
+ {
+ JPAKEUtil.validateMacTag("participantId", "partnerParticipantId", gx1, gx2, gx3, gx4, keyingMaterial, digest, macTag);
+ fail();
+ }
+ catch (CryptoException e)
+ {
+ // pass
+ }
+
+ // participant ids switched
+ try
+ {
+ JPAKEUtil.validateMacTag("participantId", "partnerParticipantId", gx3, gx4, gx1, gx2, keyingMaterial, digest, macTag);
+ fail();
+ }
+ catch (CryptoException e)
+ {
+ // pass
+ }
+ }
+
+ public void testValidateNotNull()
+ {
+ JPAKEUtil.validateNotNull("a", "description");
+
+ try
+ {
+ JPAKEUtil.validateNotNull(null, "description");
+ fail();
+ }
+ catch (NullPointerException e)
+ {
+ // pass
+ }
+ }
+
+ public void testValidateZeroKnowledgeProof()
+ throws CryptoException
+ {
+ JPAKEPrimeOrderGroup pg1 = JPAKEPrimeOrderGroups.SUN_JCE_1024;
+
+ SecureRandom random = new SecureRandom();
+ Digest digest1 = new SHA256Digest();
+
+ BigInteger x1 = JPAKEUtil.generateX1(pg1.getQ(), random);
+ BigInteger gx1 = JPAKEUtil.calculateGx(pg1.getP(), pg1.getG(), x1);
+ String participantId1 = "participant1";
+
+ BigInteger[] zkp1 = JPAKEUtil.calculateZeroKnowledgeProof(pg1.getP(), pg1.getQ(), pg1.getG(), gx1, x1, participantId1, digest1, random);
+
+ // should succeed
+ JPAKEUtil.validateZeroKnowledgeProof(pg1.getP(), pg1.getQ(), pg1.getG(), gx1, zkp1, participantId1, digest1);
+
+ // wrong group
+ JPAKEPrimeOrderGroup pg2 = JPAKEPrimeOrderGroups.NIST_3072;
+ try
+ {
+ JPAKEUtil.validateZeroKnowledgeProof(pg2.getP(), pg2.getQ(), pg2.getG(), gx1, zkp1, participantId1, digest1);
+ fail();
+ }
+ catch (CryptoException e)
+ {
+ // pass
+ }
+
+ // wrong digest
+ Digest digest2 = new SHA1Digest();
+ try
+ {
+ JPAKEUtil.validateZeroKnowledgeProof(pg1.getP(), pg1.getQ(), pg1.getG(), gx1, zkp1, participantId1, digest2);
+ fail();
+ }
+ catch (CryptoException e)
+ {
+ // pass
+ }
+
+ // wrong participant
+ String participantId2 = "participant2";
+ try
+ {
+ JPAKEUtil.validateZeroKnowledgeProof(pg1.getP(), pg1.getQ(), pg1.getG(), gx1, zkp1, participantId2, digest1);
+ fail();
+ }
+ catch (CryptoException e)
+ {
+ // pass
+ }
+
+ // wrong gx
+ BigInteger x2 = JPAKEUtil.generateX1(pg1.getQ(), random);
+ BigInteger gx2 = JPAKEUtil.calculateGx(pg1.getP(), pg1.getG(), x2);
+ try
+ {
+ JPAKEUtil.validateZeroKnowledgeProof(pg1.getP(), pg1.getQ(), pg1.getG(), gx2, zkp1, participantId1, digest1);
+ fail();
+ }
+ catch (CryptoException e)
+ {
+ // pass
+ }
+
+ // wrong zkp
+ BigInteger[] zkp2 = JPAKEUtil.calculateZeroKnowledgeProof(pg1.getP(), pg1.getQ(), pg1.getG(), gx2, x2, participantId1, digest1, random);
+ try
+ {
+ JPAKEUtil.validateZeroKnowledgeProof(pg1.getP(), pg1.getQ(), pg1.getG(), gx1, zkp2, participantId1, digest1);
+ fail();
+ }
+ catch (CryptoException e)
+ {
+ // pass
+ }
+
+ // gx <= 0
+ try
+ {
+ JPAKEUtil.validateZeroKnowledgeProof(pg1.getP(), pg1.getQ(), pg1.getG(), BigInteger.ZERO, zkp1, participantId1, digest1);
+ fail();
+ }
+ catch (CryptoException e)
+ {
+ // pass
+ }
+
+ // gx >= p
+ try
+ {
+ JPAKEUtil.validateZeroKnowledgeProof(pg1.getP(), pg1.getQ(), pg1.getG(), pg1.getP(), zkp1, participantId1, digest1);
+ fail();
+ }
+ catch (CryptoException e)
+ {
+ // pass
+ }
+
+ // gx mod q == 1
+ try
+ {
+ JPAKEUtil.validateZeroKnowledgeProof(pg1.getP(), pg1.getQ(), pg1.getG(), pg1.getQ().add(BigInteger.ONE), zkp1, participantId1, digest1);
+ fail();
+ }
+ catch (CryptoException e)
+ {
+ // pass
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/ec/test/AllTests.java b/core/src/test/java/org/spongycastle/crypto/ec/test/AllTests.java
new file mode 100644
index 00000000..5186f4b2
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/ec/test/AllTests.java
@@ -0,0 +1,39 @@
+package org.spongycastle.crypto.ec.test;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.spongycastle.util.test.SimpleTestResult;
+
+public class AllTests
+ extends TestCase
+{
+ public void testCrypto()
+ {
+ org.spongycastle.util.test.Test[] tests = { new ECElGamalTest(), new ECTransformationTest() };
+
+ for (int i = 0; i != tests.length; i++)
+ {
+ SimpleTestResult result = (SimpleTestResult)tests[i].perform();
+
+ if (!result.isSuccessful())
+ {
+ fail(result.toString());
+ }
+ }
+ }
+
+ public static void main (String[] args)
+ {
+ junit.textui.TestRunner.run(suite());
+ }
+
+ public static Test suite()
+ {
+ TestSuite suite = new TestSuite("Lightweight EC ElGamal Tests");
+
+ suite.addTestSuite(AllTests.class);
+
+ return suite;
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/ec/test/ECElGamalTest.java b/core/src/test/java/org/spongycastle/crypto/ec/test/ECElGamalTest.java
new file mode 100644
index 00000000..2b8341c9
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/ec/test/ECElGamalTest.java
@@ -0,0 +1,88 @@
+package org.spongycastle.crypto.ec.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.ec.ECDecryptor;
+import org.spongycastle.crypto.ec.ECElGamalDecryptor;
+import org.spongycastle.crypto.ec.ECElGamalEncryptor;
+import org.spongycastle.crypto.ec.ECEncryptor;
+import org.spongycastle.crypto.ec.ECPair;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.math.ec.ECConstants;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class ECElGamalTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "ECElGamal";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ BigInteger n = new BigInteger("6277101735386680763835789423176059013767194773182842284081");
+
+ ECCurve.Fp curve = new ECCurve.Fp(
+ new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q
+ new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a
+ new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16), // b
+ n, ECConstants.ONE);
+
+ ECDomainParameters params = new ECDomainParameters(
+ curve,
+ curve.decodePoint(Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), // G
+ n);
+
+ ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+ curve.decodePoint(Hex.decode("0262b12d60690cdcf330babab6e69763b471f994dd702d16a5")), // Q
+ params);
+
+ ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+ new BigInteger("651056770906015076056810763456358567190100156695615665659"), // d
+ params);
+
+ ParametersWithRandom pRandom = new ParametersWithRandom(pubKey, new SecureRandom());
+
+ doTest(priKey, pRandom, BigInteger.valueOf(20));
+
+ BigInteger rand = new BigInteger(pubKey.getParameters().getN().bitLength() - 1, new SecureRandom());
+
+ doTest(priKey, pRandom, rand);
+ }
+
+ private void doTest(ECPrivateKeyParameters priKey, ParametersWithRandom pRandom, BigInteger value)
+ {
+ ECPoint data = priKey.getParameters().getG().multiply(value);
+
+ ECEncryptor encryptor = new ECElGamalEncryptor();
+
+ encryptor.init(pRandom);
+
+ ECPair pair = encryptor.encrypt(data);
+
+ ECDecryptor decryptor = new ECElGamalDecryptor();
+
+ decryptor.init(priKey);
+
+ ECPoint result = decryptor.decrypt(pair);
+
+ if (!data.equals(result))
+ {
+ fail("point pair failed to decrypt back to original");
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new ECElGamalTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/ec/test/ECTransformationTest.java b/core/src/test/java/org/spongycastle/crypto/ec/test/ECTransformationTest.java
new file mode 100644
index 00000000..3b6e64e1
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/ec/test/ECTransformationTest.java
@@ -0,0 +1,149 @@
+package org.spongycastle.crypto.ec.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.ec.ECDecryptor;
+import org.spongycastle.crypto.ec.ECElGamalDecryptor;
+import org.spongycastle.crypto.ec.ECElGamalEncryptor;
+import org.spongycastle.crypto.ec.ECEncryptor;
+import org.spongycastle.crypto.ec.ECNewPublicKeyTransform;
+import org.spongycastle.crypto.ec.ECNewRandomnessTransform;
+import org.spongycastle.crypto.ec.ECPair;
+import org.spongycastle.crypto.ec.ECPairTransform;
+import org.spongycastle.crypto.generators.ECKeyPairGenerator;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECKeyGenerationParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.math.ec.ECConstants;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class ECTransformationTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "ECTransformationTest";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ BigInteger n = new BigInteger("6277101735386680763835789423176059013767194773182842284081");
+
+ ECCurve.Fp curve = new ECCurve.Fp(
+ new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q
+ new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a
+ new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16), // b
+ n, ECConstants.ONE);
+
+ ECDomainParameters params = new ECDomainParameters(
+ curve,
+ curve.decodePoint(Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), // G
+ n);
+
+ ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+ curve.decodePoint(Hex.decode("0262b12d60690cdcf330babab6e69763b471f994dd702d16a5")), // Q
+ params);
+
+ ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+ new BigInteger("651056770906015076056810763456358567190100156695615665659"), // d
+ params);
+
+
+ ParametersWithRandom pRandom = new ParametersWithRandom(pubKey, new SecureRandom());
+
+ doTest(priKey, pRandom, BigInteger.valueOf(20));
+
+ BigInteger rand = new BigInteger(pubKey.getParameters().getN().bitLength() - 1, new SecureRandom());
+
+ doTest(priKey, pRandom, rand);
+ doSameKeyTest(priKey, pRandom, rand);
+ }
+
+ private void doTest(ECPrivateKeyParameters priKey, ParametersWithRandom pRandom, BigInteger value)
+ {
+ ECPoint data = priKey.getParameters().getG().multiply(value);
+
+ ECEncryptor encryptor = new ECElGamalEncryptor();
+
+ encryptor.init(pRandom);
+
+ ECPair pair = encryptor.encrypt(data);
+
+ ECKeyPairGenerator ecGen = new ECKeyPairGenerator();
+
+ ecGen.init(new ECKeyGenerationParameters(priKey.getParameters(), new SecureRandom()));
+
+ AsymmetricCipherKeyPair reEncKP = ecGen.generateKeyPair();
+
+ ECPairTransform ecr = new ECNewPublicKeyTransform();
+
+ ecr.init(reEncKP.getPublic());
+
+ ECPair srcPair = pair;
+
+ // re-encrypt the message portion
+ pair = ecr.transform(srcPair);
+
+ ECDecryptor decryptor = new ECElGamalDecryptor();
+
+ decryptor.init(priKey);
+
+ // decrypt out the original private key
+ ECPoint p = decryptor.decrypt(new ECPair(srcPair.getX(), pair.getY()));
+
+ decryptor.init(reEncKP.getPrivate());
+
+ // decrypt the fully transformed point.
+ ECPoint result = decryptor.decrypt(new ECPair(pair.getX(), p));
+
+ if (!data.equals(result))
+ {
+ fail("point pair failed to decrypt back to original");
+ }
+ }
+
+ private void doSameKeyTest(ECPrivateKeyParameters priKey, ParametersWithRandom pRandom, BigInteger value)
+ {
+ ECPoint data = priKey.getParameters().getG().multiply(value);
+
+ ECEncryptor encryptor = new ECElGamalEncryptor();
+
+ encryptor.init(pRandom);
+
+ ECPair pair = encryptor.encrypt(data);
+
+ ECPairTransform ecr = new ECNewRandomnessTransform();
+
+ ecr.init(pRandom);
+
+ ECPair srcPair = pair;
+
+ // re-encrypt the message portion
+ pair = ecr.transform(srcPair);
+
+ ECDecryptor decryptor = new ECElGamalDecryptor();
+
+ decryptor.init(priKey);
+
+ // decrypt the fully transformed point.
+ ECPoint result = decryptor.decrypt(pair);
+
+ if (!data.equals(result))
+ {
+ fail("point pair failed to decrypt back to original");
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new ECTransformationTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/prng/test/AllTests.java b/core/src/test/java/org/spongycastle/crypto/prng/test/AllTests.java
new file mode 100644
index 00000000..61a17dd4
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/prng/test/AllTests.java
@@ -0,0 +1,39 @@
+package org.spongycastle.crypto.prng.test;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.spongycastle.util.test.SimpleTestResult;
+
+public class AllTests
+ extends TestCase
+{
+ public void testCrypto()
+ {
+ org.spongycastle.util.test.Test[] tests = RegressionTest.tests;
+
+ for (int i = 0; i != tests.length; i++)
+ {
+ SimpleTestResult result = (SimpleTestResult)tests[i].perform();
+
+ if (!result.isSuccessful())
+ {
+ fail(result.toString());
+ }
+ }
+ }
+
+ public static void main (String[] args)
+ {
+ junit.textui.TestRunner.run(suite());
+ }
+
+ public static Test suite()
+ {
+ TestSuite suite = new TestSuite("Lightweight Crypto PRNG Tests");
+
+ suite.addTestSuite(AllTests.class);
+
+ return suite;
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/prng/test/CTRDRBGTest.java b/core/src/test/java/org/spongycastle/crypto/prng/test/CTRDRBGTest.java
new file mode 100644
index 00000000..0a4d09db
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/prng/test/CTRDRBGTest.java
@@ -0,0 +1,513 @@
+package org.spongycastle.crypto.prng.test;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.engines.AESEngine;
+import org.spongycastle.crypto.engines.AESFastEngine;
+import org.spongycastle.crypto.engines.DESedeEngine;
+import org.spongycastle.crypto.params.DESedeParameters;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.prng.drbg.CTRSP800DRBG;
+import org.spongycastle.crypto.prng.drbg.SP80090DRBG;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * CTR DRBG Test
+ */
+public class CTRDRBGTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "CTRDRBGTest";
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new CTRDRBGTest());
+ }
+
+ private DRBGTestVector[] createTestVectorData()
+ {
+ return new DRBGTestVector[]
+ {
+ new DRBGTestVector(
+ new DESedeEngine(), 168,
+ new Bit232EntropyProvider().get(232),
+ false,
+ "20212223242526",
+ 112,
+ new String[]
+ {
+ "ABC88224514D0316EA3D48AEE3C9A2B4",
+ "D3D3F372E43E7ABDC4FA293743EED076"
+ }
+ ),
+ new DRBGTestVector(
+ new DESedeEngine(), 168,
+ new Bit232EntropyProvider().get(232),
+ false,
+ "20212223242526",
+ 112,
+ new String[]
+ {
+ "D4564EE072ACA5BD279536E14F94CB12",
+ "1CCD9AFEF15A9679BA75E35225585DEA"
+ }
+ )
+ .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C")
+ .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBC"),
+ new DRBGTestVector(
+ new DESedeEngine(), 168,
+ new Bit232EntropyProvider().get(232),
+ false,
+ "20212223242526",
+ 112,
+ new String[]
+ {
+ "760BED7D92B083B10AF31CF0656081EB",
+ "FD1AC41482384D823CF3FD6F0E6C88B3"
+ }
+ )
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C"),
+ new DRBGTestVector(
+ new DESedeEngine(), 168,
+ new Bit232EntropyProvider().get(232),
+ false,
+ "20212223242526",
+ 112,
+ new String[]
+ {
+ "7A4C1D7ADC8A67FDB50100ED23583A2C",
+ "43044D311C0E07541CA5C8B0916976B2"
+ }
+ )
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C")
+ .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C")
+ .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBC"),
+ new DRBGTestVector(
+ new DESedeEngine(), 168,
+ new Bit232EntropyProvider().get(232),
+ true,
+ "20212223242526",
+ 112,
+ new String[]
+ {
+ "8FB78ABCA75C9F284E974E36141866BC",
+ "9D9745FF31C42A4488CBB771B13B5D86"
+ }
+ ),
+ new DRBGTestVector(
+ new DESedeEngine(), 168,
+ new Bit232EntropyProvider().get(232),
+ true,
+ "20212223242526",
+ 112,
+ new String[]
+ {
+ "0E389920A09B485AA4ABD0CA7E60D89C",
+ "F4478EC6659A0D3577625B0C73A211DD"
+ }
+ )
+ .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C")
+ .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBC"),
+ new DRBGTestVector(
+ new DESedeEngine(), 168,
+ new Bit232EntropyProvider().get(232),
+ true,
+ "20212223242526",
+ 112,
+ new String[]
+ {
+ "64983055D014550B39DE699E43130B64",
+ "035FDDA8582A2214EC722C410A8D95D3"
+ }
+ )
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C"),
+ new DRBGTestVector(
+ new DESedeEngine(), 168,
+ new Bit232EntropyProvider().get(232),
+ true,
+ "20212223242526",
+ 112,
+ new String[]
+ {
+ "A29C1A8C42FBC562D7D1DBA7DC541FFE",
+ "0BDA66B049429061C013E4228C2F44C6"
+ }
+ )
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C")
+ .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C")
+ .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBC"),
+ new DRBGTestVector(
+ new AESFastEngine(), 128,
+ new Bit256EntropyProvider().get(256),
+ false,
+ "2021222324252627",
+ 128,
+ new String[]
+ {
+ "8CF59C8CF6888B96EB1C1E3E79D82387AF08A9E5FF75E23F1FBCD4559B6B997E",
+ "69CDEF912C692D61B1DA4C05146B52EB7B8849BD87937835328254EC25A9180E"
+ }
+ ),
+ new DRBGTestVector(
+ new AESFastEngine(), 128,
+ new Bit256EntropyProvider().get(256),
+ false,
+ "2021222324252627",
+ 128,
+ new String[]
+ {
+ "E8C74A4B7BFFB53BEB80E78CA86BB6DF70E2032AEB473E0DD54D2339CEFCE9D0",
+ "26B3F823B4DBAFC23B141375E10B3AEB7A0B5DEF1C7D760B6F827D01ECD17AC7"
+ }
+ )
+ .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F")
+ .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"),
+ new DRBGTestVector(
+ new AESFastEngine(), 128,
+ new Bit256EntropyProvider().get(256),
+ false,
+ "2021222324252627",
+ 128,
+ new String[]
+ {
+ "18FDEFBDC43D7A36D5D6D862205765D1D701C9F237007030DF1B8E70EE4EEE29",
+ "9888F1D38BB1CCE31B363AA1BD9B39616876C30DEE1FF0B7BD8C4C441715C833"
+ }
+ )
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F"),
+ new DRBGTestVector(
+ new AESFastEngine(), 128,
+ new Bit256EntropyProvider().get(256),
+ true,
+ "2021222324252627",
+ 128,
+ new String[]
+ {
+ "BFF4B85D68C84529F24F69F9ACF1756E29BA648DDEB825C225FA32BA490EF4A9",
+ "9BD2635137A52AF7D0FCBEFEFB97EA93A0F4C438BD98956C0DACB04F15EE25B3"
+ }
+ ),
+ new DRBGTestVector(
+ new AESFastEngine(), 128,
+ new Bit256EntropyProvider().get(256),
+ true,
+ "2021222324252627",
+ 128,
+ new String[]
+ {
+ "4573AC8BBB33D7CC4DBEF3EEDF6EAE748B536C3A1082CEE4948CDB51C83A7F9C",
+ "99C628CDD87BD8C2F1FE443AA7F761DA16886436326323354DA6311FFF5BC678"
+ }
+ )
+ .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F")
+ .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"),
+ new DRBGTestVector(
+ new AESFastEngine(), 128,
+ new Bit256EntropyProvider().get(256),
+ true,
+ "2021222324252627",
+ 128,
+ new String[]
+ {
+ "F324104E2FA14F79D8AA60DF06B93B3BC157324958F0A7EE1E193677A70E0250",
+ "78F4C840134F40DC001BFAD3A90B5EF4DEBDBFAC3CFDF0CD69A89DC4FD34713F"
+ }
+ )
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F"),
+ new DRBGTestVector(
+ new AESFastEngine(), 192,
+ new Bit320EntropyProvider().get(320),
+ false,
+ "202122232425262728292A2B",
+ 192,
+ new String[]
+ {
+ "E231244B3235B085C81604424357E85201E3828B5C45568679A5555F867AAC8C",
+ "DDD0F7BCCADADAA31A67652259CE569A271DD85CF66C3D6A7E9FAED61F38D219"
+ }
+ )
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F6061626364656667"),
+ new DRBGTestVector(
+ new AESFastEngine(), 192,
+ new Bit320EntropyProvider().get(320),
+ true,
+ "202122232425262728292A2B",
+ 192,
+ new String[]
+ {
+ "F780D4A2C25CF8EE7407D948EC0B724A4235D8B20E65081392755CA7912AD7C0",
+ "BA14617F915BA964CB79276BDADC840C14B631BBD1A59097054FA6DFF863B238"
+ }
+ )
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F6061626364656667"),
+ new DRBGTestVector(
+ new AESFastEngine(), 256,
+ new Bit384EntropyProvider().get(384),
+ false,
+ "202122232425262728292A2B2C2D2E2F",
+ 256,
+ new String[]
+ {
+ "47111E146562E9AA2FB2A1B095D37A8165AF8FC7CA611D632BE7D4C145C83900",
+ "98A28E3B1BA363C9DAF0F6887A1CF52B833D3354D77A7C10837DD63DD2E645F8"
+ }
+ )
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F")
+ .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F")
+ .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"),
+ new DRBGTestVector(
+ new AESFastEngine(), 256,
+ new Bit384EntropyProvider().get(384),
+ true,
+ "202122232425262728292A2B2C2D2E2F",
+ 256,
+ new String[]
+ {
+ "71BB3F9C9CEAF4E6C92A83EB4C7225010EE150AC75E23F5F77AD5073EF24D88A",
+ "386DEBBBF091BBF0502957B0329938FB836B82E594A2F5FDD5EB28D4E35528F4"
+ }
+ )
+ .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F")
+ .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"),
+ new DRBGTestVector(
+ new AESFastEngine(), 256,
+ new Bit384EntropyProvider().get(384),
+ true,
+ "202122232425262728292A2B2C2D2E2F",
+ 256,
+ new String[]
+ {
+ "1A2E3FEE9056E98D375525FDC2B63B95B47CE51FCF594D804BD5A17F2E01139B",
+ "601F95384F0D85946301D1EACE8F645A825CE38F1E2565B0C0C439448E9CA8AC"
+ }
+ )
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F"),
+ new DRBGTestVector(
+ new AESFastEngine(), 256,
+ new Bit384EntropyProvider().get(384),
+ true,
+ "202122232425262728292A2B2C2D2E2F",
+ 256,
+ new String[]
+ {
+ "EAE6BCE781807E524D26605EA198077932D01EEB445B9AC6C5D99C101D29F46E",
+ "738E99C95AF59519AAD37FF3D5180986ADEBAB6E95836725097E50A8D1D0BD28"
+ }
+ )
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F")
+ .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F")
+ .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF")
+ };
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ DRBGTestVector[] tests = createTestVectorData();
+
+ for (int i = 0; i != tests.length; i++)
+ {
+ DRBGTestVector tv = tests[i];
+
+ byte[] nonce = tv.nonce();
+ byte[] personalisationString = tv.personalizationString();
+
+ SP80090DRBG d = new CTRSP800DRBG(tv.getCipher(), tv.keySizeInBits(), tv.securityStrength(), tv.entropySource(), personalisationString, nonce);
+
+ byte[] output = new byte[tv.expectedValue(0).length];
+
+ d.generate(output, tv.additionalInput(0), tv.predictionResistance());
+
+ byte[] expected = tv.expectedValue(0);
+
+ if (!areEqual(expected, output))
+ {
+ fail("Test #" + (i + 1) + ".1 failed, expected " + new String(Hex.encode(tv.expectedValue(0))) + " got " + new String(Hex.encode(output)));
+ }
+
+ output = new byte[tv.expectedValue(0).length];
+
+ d.generate(output, tv.additionalInput(1), tv.predictionResistance());
+
+ expected = tv.expectedValue(1);
+ if (!areEqual(expected, output))
+ {
+ fail("Test #" + (i + 1) + ".2 failed, expected " + new String(Hex.encode(tv.expectedValue(1))) + " got " + new String(Hex.encode(output)));
+ }
+ }
+
+ // DESede/TDEA key parity test
+ DRBGTestVector tv = tests[0];
+
+ SP80090DRBG drbg = new CTRSP800DRBG(new KeyParityCipher(tv.getCipher()), tv.keySizeInBits(), tv.securityStrength(), tv.entropySource(), tv.personalizationString(), tv.nonce());
+
+ byte[] output = new byte[tv.expectedValue(0).length];
+
+ drbg.generate(output, tv.additionalInput(0), tv.predictionResistance());
+
+ // Exception tests
+ SP80090DRBG d;
+ try
+ {
+ d = new CTRSP800DRBG(new AESEngine(), 256, 256, new Bit232EntropyProvider().get(128), null, null);
+ fail("no exception thrown");
+ }
+ catch (IllegalArgumentException e)
+ {
+ if (!e.getMessage().equals("Not enough entropy for security strength required"))
+ {
+ fail("Wrong exception", e);
+ }
+ }
+
+ try
+ {
+ d = new CTRSP800DRBG(new DESedeEngine(), 256, 256, new Bit232EntropyProvider().get(232), null, null);
+ fail("no exception thrown");
+ }
+ catch (IllegalArgumentException e)
+ {
+ if (!e.getMessage().equals("Requested security strength is not supported by block cipher and key size"))
+ {
+ fail("Wrong exception", e);
+ }
+ }
+
+ try
+ {
+ d = new CTRSP800DRBG(new DESedeEngine(), 168, 256, new Bit232EntropyProvider().get(232), null, null);
+ fail("no exception thrown");
+ }
+ catch (IllegalArgumentException e)
+ {
+ if (!e.getMessage().equals("Requested security strength is not supported by block cipher and key size"))
+ {
+ fail("Wrong exception", e);
+ }
+ }
+
+ try
+ {
+ d = new CTRSP800DRBG(new AESEngine(), 192, 256, new Bit232EntropyProvider().get(232), null, null);
+ fail("no exception thrown");
+ }
+ catch (IllegalArgumentException e)
+ {
+ if (!e.getMessage().equals("Requested security strength is not supported by block cipher and key size"))
+ {
+ fail("Wrong exception", e);
+ }
+ }
+ }
+
+ private class Bit232EntropyProvider
+ extends TestEntropySourceProvider
+ {
+ Bit232EntropyProvider()
+ {
+ super(Hex.decode(
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C" +
+ "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C" +
+ "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDC"), true);
+ }
+ }
+
+ private class Bit256EntropyProvider
+ extends TestEntropySourceProvider
+ {
+ Bit256EntropyProvider()
+ {
+ super(Hex.decode(
+ "0001020304050607"+
+ "08090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"+
+ "8081828384858687"+
+ "88898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F"+
+ "C0C1C2C3C4C5C6C7"+
+ "C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"), true);
+ }
+ }
+
+ private class Bit320EntropyProvider
+ extends TestEntropySourceProvider
+ {
+ Bit320EntropyProvider()
+ {
+ super(Hex.decode(
+ "000102030405060708090A0B0C0D0E0F"+
+ "101112131415161718191A1B1C1D1E1F2021222324252627"+
+ "808182838485868788898A8B8C8D8E8F"+
+ "909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7"+
+ "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"+
+ "D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7"), true);
+ }
+ }
+
+ private class Bit384EntropyProvider
+ extends TestEntropySourceProvider
+ {
+ Bit384EntropyProvider()
+ {
+ super(Hex.decode(
+ "000102030405060708090A0B0C0D0E0F1011121314151617" +
+ "18191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F" +
+ "808182838485868788898A8B8C8D8E8F9091929394959697" +
+ "98999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAF" +
+ "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7" +
+ "D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF"), true);
+ }
+ }
+
+ private class KeyParityCipher
+ implements BlockCipher
+ {
+ private BlockCipher cipher;
+
+ KeyParityCipher(BlockCipher cipher)
+ {
+ this.cipher = cipher;
+ }
+
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ byte[] k = Arrays.clone(((KeyParameter)params).getKey());
+
+ DESedeParameters.setOddParity(k);
+
+ if (!Arrays.areEqual(((KeyParameter)params).getKey(), k))
+ {
+ fail("key not odd parity");
+ }
+
+ cipher.init(forEncryption, params);
+ }
+
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName();
+ }
+
+ public int getBlockSize()
+ {
+ return cipher.getBlockSize();
+ }
+
+ public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ return cipher.processBlock(in, inOff, out, outOff);
+ }
+
+ public void reset()
+ {
+ cipher.reset();
+ }
+ }
+
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/prng/test/DRBGTestVector.java b/core/src/test/java/org/spongycastle/crypto/prng/test/DRBGTestVector.java
new file mode 100644
index 00000000..b0dd3b72
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/prng/test/DRBGTestVector.java
@@ -0,0 +1,131 @@
+package org.spongycastle.crypto.prng.test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.prng.EntropySource;
+import org.spongycastle.util.encoders.Hex;
+
+public class DRBGTestVector
+{
+ private Digest _digest;
+ private BlockCipher _cipher;
+ private int _keySizeInBits;
+ private EntropySource _eSource;
+ private boolean _pr;
+ private String _nonce;
+ private String _personalisation;
+ private int _ss;
+ private String[] _ev;
+ private List _ai = new ArrayList();
+
+ public DRBGTestVector(Digest digest, EntropySource eSource, boolean predictionResistance, String nonce, int securityStrength, String[] expected)
+ {
+ _digest = digest;
+ _eSource = eSource;
+ _pr = predictionResistance;
+ _nonce = nonce;
+ _ss = securityStrength;
+ _ev = expected;
+ _personalisation = null;
+ }
+
+ public DRBGTestVector(BlockCipher cipher, int keySizeInBits, EntropySource eSource, boolean predictionResistance, String nonce, int securityStrength, String[] expected)
+ {
+ _cipher = cipher;
+ _keySizeInBits = keySizeInBits;
+ _eSource = eSource;
+ _pr = predictionResistance;
+ _nonce = nonce;
+ _ss = securityStrength;
+ _ev = expected;
+ _personalisation = null;
+ }
+
+ public Digest getDigest()
+ {
+ return _digest;
+ }
+
+ public BlockCipher getCipher()
+ {
+ return _cipher;
+ }
+
+ public int keySizeInBits()
+ {
+ return _keySizeInBits;
+ }
+
+ public DRBGTestVector addAdditionalInput(String input)
+ {
+ _ai.add(input);
+
+ return this;
+ }
+
+ public DRBGTestVector setPersonalizationString(String p)
+ {
+ _personalisation = p;
+
+ return this;
+ }
+
+ public EntropySource entropySource()
+ {
+ return _eSource;
+ }
+
+ public boolean predictionResistance()
+ {
+ return _pr;
+ }
+
+ public byte[] nonce()
+ {
+ if (_nonce == null)
+ {
+ return null;
+ }
+
+ return Hex.decode(_nonce);
+ }
+
+ public byte[] personalizationString()
+ {
+ if (_personalisation == null)
+ {
+ return null;
+ }
+
+ return Hex.decode(_personalisation);
+ }
+
+ public int securityStrength()
+ {
+ return _ss;
+ }
+
+ public byte[] expectedValue(int index)
+ {
+ return Hex.decode(_ev[index]);
+ }
+
+ public byte[] additionalInput(int position)
+ {
+ int len = _ai.size();
+ byte[] rv;
+ if (position >= len)
+ {
+ rv = null;
+ }
+ else
+ {
+ rv = Hex.decode((String)(_ai.get(position)));
+ }
+ return rv;
+ }
+
+ }
diff --git a/core/src/test/java/org/spongycastle/crypto/prng/test/DualECDRBGTest.java b/core/src/test/java/org/spongycastle/crypto/prng/test/DualECDRBGTest.java
new file mode 100644
index 00000000..4aa85708
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/prng/test/DualECDRBGTest.java
@@ -0,0 +1,415 @@
+package org.spongycastle.crypto.prng.test;
+
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.digests.SHA384Digest;
+import org.spongycastle.crypto.digests.SHA512Digest;
+import org.spongycastle.crypto.prng.drbg.DualECSP800DRBG;
+import org.spongycastle.crypto.prng.drbg.SP80090DRBG;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * Dual EC SP800-90 DRBG test
+ */
+public class DualECDRBGTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "DualECDRBG";
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new DualECDRBGTest());
+ }
+
+ private DRBGTestVector[] createTestVectorData()
+ {
+ return new DRBGTestVector[]
+ {
+ new DRBGTestVector(
+ new SHA256Digest(),
+ new SHA256EntropyProvider().get(128),
+ false,
+ "2021222324252627",
+ 128,
+ new String[]
+ {
+ "FF5163C388F791E96F1052D5C8F0BD6FBF7144839C4890FF85487C5C12702E4C9849AF518AE68DEB14D3A62702BBDE4B98AB211765FD87ACA12FC2A6",
+ "9A0A11F2DFB88F7260559DD8DA6134EB2B34CC0415FA8FD0474DB6B85E1A08385F41B435DF81296B1B4EDF66E0107C0844E3D28A89B05046B89177F2"
+ }),
+ new DRBGTestVector(
+ new SHA256Digest(),
+ new SHA256EntropyProvider().get(128),
+ false,
+ "2021222324252627",
+ 128,
+ new String[]
+ {
+ "C08E954FCD486D0B0934A0236692AC705A835D1A3C94D2ACD4684AB26E978D7D42E73CC06D6EC1472C63E51BED7F71518395836E2052BBD73A20CABB",
+ "1D76DEE36FCC5F9478C112EAFA1C4CCD0635435A6F3A247A3BA3849790B5245070E95C1A67BE7A39BFB213F2C0EFCC171A3253DA6D54DA4362EA2099"
+ })
+ .addAdditionalInput("606162636465666768696A6B6C6D6E6F")
+ .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAF"),
+ new DRBGTestVector(
+ new SHA256Digest(),
+ new SHA256EntropyProvider().get(128),
+ false,
+ "2021222324252627",
+ 128,
+ new String[]
+ {
+ "3AB095CC493A8730D70DE923108B2E4710799044FFC27D0A1156250DDF97E8B05ACE055E49F3E3F5B928CCD18317A3E68FCB0B6F0459ADF9ECF79C87",
+ "7B902FC35B0AF50F57F8822936D08A96E41B16967C6B1AA0BC05032F0D53919DC587B664C883E2FE8F3948002FCD8BCBFC4706BCAA2075EF6BF41167"
+ })
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F"),
+ new DRBGTestVector(
+ new SHA256Digest(),
+ new SHA256EntropyProvider().get(128),
+ false,
+ "2021222324252627",
+ 128,
+ new String[]
+ {
+ "3B68A1D95ED0312150AC1991189780F37EC50E75249F915CD806BBA0C44F9E3A919B2390805E1E90C1D2D1C823B17B96DB44535B72E0CFB62723529D",
+ "250B933475E3BD4FC85D97FD797834B599DEDEDF8B6F15474E1F31B4AF215CFA7A8C0A0296A2E374B3886BB0CC7E49DBB19324564B451E64F12864F9"
+ })
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F")
+ .addAdditionalInput("606162636465666768696A6B6C6D6E6F")
+ .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAF"),
+ new DRBGTestVector(
+ new SHA256Digest(),
+ new SHA256EntropyProvider().get(128),
+ true,
+ "2021222324252627",
+ 128,
+ new String[]
+ {
+ "8C77288EDBEA9A742464F78D55E33593C1BF5F9D8CD8609D6D53BAC4E4B42252A227A99BAD0F2358B05955CD35723B549401C71C9C1F32F8A2018E24",
+ "56ECA61C64F69C1C232E992623C71418BD0B96D783118FAAD94A09E3A9DB74D15E805BA7F14625995CA77612B2EF7A05863699ECBABF70D3D422C014"
+ }),
+ new DRBGTestVector(
+ new SHA256Digest(),
+ new SHA256EntropyProvider().get(128),
+ true,
+ "2021222324252627",
+ 128,
+ new String[]
+ {
+ "A5C397DFEB540E86F0470E9625D5C5AC2D50016FB201E8DF574F2201DFBB42A799FEB9E238AAD301A493382250EEE60D2E2927E500E848E57535ABD1",
+ "BF9894630BEBAF0A0EDFE726285EB055FD2ED678B76673803DD327F49DBEDE87D3E447A6EB73B5D5C52A40078132677F412E9E7DE32B9B1CB32421B9"
+ })
+ .addAdditionalInput("606162636465666768696A6B6C6D6E6F")
+ .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAF"),
+ new DRBGTestVector(
+ new SHA384Digest(),
+ new SHA384EntropyProvider().get(192),
+ false,
+ "202122232425262728292A2B",
+ 192,
+ new String[]
+ {
+ "1F858858B65357D6360E1ED8F8475767B08DAB30718CCA01C6FAE77A4BDCE2702C76D0FB4758EA1ED6AA587CFD26B9011DC8A75D0B4154193BB2C1798FFA52BCAB208310" +
+ "3CD2AAD44BEED56D042FC2B8915D7D9BED6437EFEB1582EE",
+ "6E4AAB63938212C870F24BB067A32CA9E7FC2343" +
+ "5D411729268C8BA6F90E87074D04888CE2CC5A916B7AC93F" +
+ "EDE85E2995645DFCC4CE44B9FB41F1BFCC5E9F59EE3A8E1B" +
+ "8F85247F741B7C480521EE6BF8BA319B59048E65F08FAA76"
+ }),
+ new DRBGTestVector(
+ new SHA384Digest(),
+ new SHA384EntropyProvider().get(192),
+ false,
+ "202122232425262728292A2B",
+ 192,
+ new String[]
+ {
+ "E6A30AB0C9AFCBA673E4F1C94B3DB1F0C7D78B3D" +
+ "87B967281BE1E7B3CAF5200AED502C26B84FC169FE8336BD" +
+ "23271CB299812F2CF1955AA63FC362044ABA246EF1610F9E" +
+ "DC613924A84A00F8DB3FC65C13373F3171EB20848FA9A70E",
+ "8585764DF1C86EA12ACCB882525BF6217B447486" +
+ "5EBFDA367B8657FA80471139BAC626172B9F219DF2CE9099" +
+ "F65833E07CD1A8DD80468779EA3C26620A2C9C9F5C7EFCDD" +
+ "C036E6F6C8BF70316D3C37FC246A4CC79B3F1DB971D72ED0"
+ })
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F5051525354555657"),
+ new DRBGTestVector(
+ new SHA384Digest(),
+ new SHA384EntropyProvider().get(192),
+ false,
+ "202122232425262728292A2B",
+ 192,
+ new String[]
+ {
+ "13F6EA9BBA7BABDC2A52A3B9FD73D65ECAA638A0" +
+ "4C74BCCA2ACDE6FD29FEA4B5D884E095E87D1B7C0DEB9D37" +
+ "7AD81FBFEEA2D5EF82C0F6F52B9FCC359E769AC9DF2A876C" +
+ "58BAF21657814F3E66D1680B1D4EBD65581E42534F85197D",
+ "FC0A36F4D20F8F83BE3430AA3C36A49191821A82" +
+ "072BBC3D5AFF8D7EC39484D646277CE87599B6FE8CCA9862" +
+ "559703A10F4DE1066BFD30B80C325E774B512525BC6D3734" +
+ "4C93906368243D31F89E99C4D2A6E9BEB24D5F7267360DCA"
+ })
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F5051525354555657")
+ .addAdditionalInput("606162636465666768696A6B6C6D6E6F7071727374757677")
+ .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7"),
+ new DRBGTestVector(
+ new SHA384Digest(),
+ new SHA384EntropyProvider().get(192),
+ true,
+ "202122232425262728292A2B",
+ 192,
+ new String[]
+ {
+ "FE55601BF734493013705CCEB76E44AAD48373F7" +
+ "42E72B83D4701FA6549255F1CDE6217953522FF973BA4F6E" +
+ "C96D2BDCF14A76BE7DEB61781E34B99335BD714F17C91739" +
+ "B4E2AB57E36E9C3116E215D3D94FCFAD532636874875CAC7",
+ "F5E59D0ABADE81F62FFAB9D4A6A26FF200016608" +
+ "A7215E389858FFED83FBC75CFD33DBA6688C89AA32AD22E4" +
+ "80EA3D04EADFB35567B67564207E64B77844E8E4A87502D5" +
+ "02DBBB6D8277F1CACDB7CF8D293D09DB7DD59A950821507A"
+ })
+ .addAdditionalInput("606162636465666768696A6B6C6D6E6F7071727374757677")
+ .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7"),
+ new DRBGTestVector(
+ new SHA384Digest(),
+ new SHA384EntropyProvider().get(192),
+ true,
+ "202122232425262728292A2B",
+ 192,
+ new String[]
+ {
+ "CC788F70FB08F256D9604333630D85936D400F45" +
+ "718DC3F939A8B9F6F75D3E4EC17D68FBB924AEACB7021295" +
+ "48FA63CE9BCB82176639B64DE890A47025B5582312FE934E" +
+ "F0D0A12697C0F05D2DA108CCADB511BA0EB62F4051BB2354",
+ "2C922EA620D76E4137B315EBC29E518F80951B3F" +
+ "0E6173FA2BFD94A230EE513EE2E4EB330D802F620DD24911" +
+ "534EC0F95A1F1D44A2125F5D57476A666FC372092B55D0D6" +
+ "8B49738F5BC466EC206AB3CF6A972B38BCFAE5FCD53C7E21 "
+ }),
+ new DRBGTestVector(
+ new SHA512Digest(),
+ new SHA512EntropyProvider().get(256),
+ false,
+ "202122232425262728292A2B2C2D2E2F",
+ 256,
+ new String[]
+ {
+ "7A8313798EE1" +
+ "D1898712683F2D0B0DEE5804146ABA64FDA8DB4E539CC8D1" +
+ "E59C74EE5AA48E73E958C8EC85DD529D42E68B4F7E02FFAF" +
+ "3E3EF8312AEA68BC08A414885E60A7DF0B55F9D90210B319" +
+ "E9B8FD23E078A4153636F29AA3CAC8198CB1D5D846151653" +
+ "ECE275A591089261238014E5058410065AB8229EB9115E8E",
+ "918B5D79E646" +
+ "64966D954BC5E2946BF48F061BF0C2701C3C2D1F75EA821E" +
+ "1DA05D5B3C2C4EEA246E806B53BF6BDB3F3D53A3AE756C2A" +
+ "45C72603973A3DE1BC367C283CA124A5589CEAB30E5D2D74" +
+ "8A40DD874FF15B032CF4F4B2AAD590B0DB91A0D38FCE93C5" +
+ "AAD4E55AC482F86FF06FAE66B7C7CCA7E45557E1A5A3B85D"
+ }),
+ new DRBGTestVector(
+ new SHA512Digest(),
+ new SHA512EntropyProvider().get(256),
+ true,
+ "202122232425262728292A2B2C2D2E2F",
+ 256,
+ new String[]
+ {
+ "C7ED88A2C690" +
+ "1C04802BA2BB04262921B19664835A4A3C002CB9F13E35E3" +
+ "DEB3698A436BF1C85B070E9E6977CA78A5130905AA0C01A9" +
+ "4130F5133DF904A4ACF59A7DD01227E8FCA1C8D51F093839" +
+ "46ECD950113104760D7E216CAF581FE9D3AACE6FC4CDDC4C" +
+ "CD736D26A60BE8BE2A6A78CD752D1EC7CCC802638B177307",
+ "83B78B206785" +
+ "4412EEB24AEA86064D510C68FD96DBF94EAC1BC2022752D7" +
+ "558AEB9F97B9CBC1B9648FE4D88E2C82A6F530675E1DB92D" +
+ "396D6D85BDAD2A23CBD10AD808ECCCFBFC811EB68AE835E4" +
+ "912E011DD10A4399C8DE2D9D88F81B6168B05D282B9DAC1E" +
+ "65E0A45F61043E1FA047870DD582295E6C50DD1185B13594 "
+ })
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F")
+ .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F")
+ .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"),
+ new DRBGTestVector(
+ new SHA512Digest(),
+ new SHA512EntropyProvider().get(256),
+ true,
+ "202122232425262728292A2B2C2D2E2F",
+ 256,
+ new String[]
+ {
+ "CC7035C73040" +
+ "5CF5DF7137ED9E10744B75B540AFFC68EB564B71C0F737E8" +
+ "F656B6171940497FA90D8F383EFB6FC6717BA14AAA164EF5" +
+ "6641C0F513312551DCD21D0A5B0DBDCD97F627E968DFD752" +
+ "56C11CF2BCCA5822EAACE796A34CB7D2F8CD8CC6DBE76274" +
+ "498289BBC4C2F1CADA6185D82605CF992EC285BC4945EE9E",
+ "0E6C329AD1BE" +
+ "681EB1E6F5E03A89E3D80153D6CCDD5A3ECF865003EE4A2D" +
+ "E5A23B7F43681361CFAFC3A3FEF17777E75CF9D6685573C8" +
+ "87A3962CB955076D45D6F1E45EE4B8CB31A4731CDA031FA2" +
+ "815B6D34E29F2603526CE186576F4CCA3FEDF7F8ACDB37C9" +
+ "9D762706ABE4967D44739C8CFCFCC76C58B1ED243AC394C0"
+ }),
+ // From http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip
+ // modified to test partial block processing.
+ new DRBGTestVector(
+ new SHA256Digest(),
+ new TestEntropySourceProvider(Hex.decode("a826f1cd3fa24b9e71c316e5bf2bafff"), false).get(128),
+ false,
+ "82bc3bf050614b34",
+ 128,
+ new String[]
+ {
+ "14949b876e30f832331f59f2e687350bea9ba22b78549521a70748ca916c74ebff0b638266aa" +
+ "d81e089545eb60bfe332f7d134d91ed3c104f975fae0f71391add71e3380a725251ed5552a84" +
+ "650637eddfc88b5ab26311277cbc429aa152b2cfac61c67846512d7564114177a622f25e870a" +
+ "acec37c0977d",
+ "7050bf74a887809673ecd295071f7a457d1e2e227f68ef4b4445e34f3904b95d4833180ee522" +
+ "104bfc996234063e2c76173937b883c66b0e64a56643877228cad5212cddbf839270ef80889b" +
+ "c83424c141c2419f2231004c8860f8fd95435e2c9f8ac7409fcbfb6a74851fadc7d99bf5d68b" +
+ "591892f0e3a1"
+ }),
+ new DRBGTestVector(
+ new SHA256Digest(),
+ new TestEntropySourceProvider(Hex.decode("a826f1cd3fa24b9e71c316e5bf2bafff"), false).get(128),
+ false,
+ "82bc3bf050614b34",
+ 128,
+ new String[]
+ {
+ "14949b876e30f832331f59f2e687350bea9ba22b78549521a70748ca916c74ebff0b638266aa" +
+ "d81e089545eb60bfe332f7d134d91ed3c104f975fae0f71391add71e3380a725251ed5552a84" +
+ "650637eddfc88b5ab26311277cbc429aa152b2cfac61c67846512d7564114177a622f25e870a" +
+ "acec37c0977d",
+ "7050bf74a887809673ecd295071f7a457d1e2e227f68ef4b4445e34f3904b95d4833180ee522" +
+ "104bfc996234063e2c76173937b883c66b0e64a56643877228cad5212cddbf839270ef80889b" +
+ "c83424c141c2419f2231004c8860f8fd95435e2c9f8ac7409fcbfb6a74851fadc7d99bf5d68b" +
+ "591892f0e3"
+ })
+ };
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ DRBGTestVector[] tests = createTestVectorData();
+
+ for (int i = 0; i != tests.length; i++)
+ {
+ DRBGTestVector tv = tests[i];
+
+ byte[] nonce = tv.nonce();
+ byte[] personalisationString = tv.personalizationString();
+
+ SP80090DRBG d = new DualECSP800DRBG(tv.getDigest(), tv.securityStrength(), tv.entropySource(), personalisationString, nonce);
+
+ byte[] output = new byte[tv.expectedValue(0).length];
+
+ d.generate(output, tv.additionalInput(0), tv.predictionResistance());
+
+ byte[] expected = tv.expectedValue(0);
+
+ if (!areEqual(expected, output))
+ {
+ fail("Test #" + (i + 1) + ".1 failed, expected " + new String(Hex.encode(tv.expectedValue(0))) + " got " + new String(Hex.encode(output)));
+ }
+
+ output = new byte[tv.expectedValue(1).length];
+
+ d.generate(output, tv.additionalInput(1), tv.predictionResistance());
+
+ expected = tv.expectedValue(1);
+ if (!areEqual(expected, output))
+ {
+ fail("Test #" + (i + 1) + ".2 failed, expected " + new String(Hex.encode(tv.expectedValue(1))) + " got " + new String(Hex.encode(output)));
+ }
+ }
+
+ // Exception tests
+ //
+ SP80090DRBG d;
+
+ try
+ {
+ d = new DualECSP800DRBG(new SHA256Digest(), 256, new SHA256EntropyProvider().get(128), null, null);
+ fail("no exception thrown");
+ }
+ catch (IllegalArgumentException e)
+ {
+ if (!e.getMessage().equals("EntropySource must provide between 256 and 4096 bits"))
+ {
+ fail("Wrong exception", e);
+ }
+ }
+
+ try
+ {
+ d = new DualECSP800DRBG(new SHA256Digest(), 256, new SHA256EntropyProvider().get(1 << (13 - 1) + 1), null, null);
+ fail("no exception thrown");
+ }
+ catch (IllegalArgumentException e)
+ {
+ if (!e.getMessage().equals("EntropySource must provide between 256 and 4096 bits"))
+ {
+ fail("Wrong exception", e);
+ }
+ }
+
+ try
+ {
+ d = new DualECSP800DRBG(new SHA1Digest(), 256, new SHA256EntropyProvider().get(256), null, null);
+ fail("no exception thrown");
+ }
+ catch (IllegalArgumentException e)
+ {
+ if (!e.getMessage().equals("Requested security strength is not supported by digest"))
+ {
+ fail("Wrong exception", e);
+ }
+ }
+ }
+
+ private class SHA256EntropyProvider
+ extends TestEntropySourceProvider
+ {
+ SHA256EntropyProvider()
+ {
+ super(Hex.decode(
+ "000102030405060708090A0B0C0D0E0F " +
+ "808182838485868788898A8B8C8D8E8F" +
+ "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"), true);
+ }
+ }
+
+ private class SHA384EntropyProvider
+ extends TestEntropySourceProvider
+ {
+ SHA384EntropyProvider()
+ {
+ super(Hex.decode(
+ "000102030405060708090A0B0C0D0E0F1011121314151617" +
+ "808182838485868788898A8B8C8D8E8F9091929394959697" +
+ "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7"), true);
+ }
+ }
+
+ private class SHA512EntropyProvider
+ extends TestEntropySourceProvider
+ {
+ SHA512EntropyProvider()
+ {
+ super(Hex.decode(
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F" +
+ "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F" +
+ "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"), true);
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/prng/test/FixedSecureRandomTest.java b/core/src/test/java/org/spongycastle/crypto/prng/test/FixedSecureRandomTest.java
new file mode 100644
index 00000000..b10ad367
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/prng/test/FixedSecureRandomTest.java
@@ -0,0 +1,68 @@
+package org.spongycastle.crypto.prng.test;
+
+import org.spongycastle.crypto.prng.FixedSecureRandom;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class FixedSecureRandomTest
+ extends SimpleTest
+{
+ byte[] base = Hex.decode("deadbeefdeadbeef");
+ byte[] r1 = Hex.decode("cafebabecafebabe");
+ byte[] r2 = Hex.decode("ffffffffcafebabedeadbeef");
+
+ public String getName()
+ {
+ return "FixedSecureRandom";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ FixedSecureRandom fixed = new FixedSecureRandom(base);
+ byte[] buf = new byte[8];
+
+ fixed.nextBytes(buf);
+
+ if (!Arrays.areEqual(buf, base))
+ {
+ fail("wrong data returned");
+ }
+
+ fixed = new FixedSecureRandom(base);
+
+ byte[] seed = fixed.generateSeed(8);
+
+ if (!Arrays.areEqual(seed, base))
+ {
+ fail("wrong seed data returned");
+ }
+
+ if (!fixed.isExhausted())
+ {
+ fail("not exhausted");
+ }
+
+ fixed = new FixedSecureRandom(new byte[][] { r1, r2 });
+
+ seed = fixed.generateSeed(12);
+
+ if (!Arrays.areEqual(seed, Hex.decode("cafebabecafebabeffffffff")))
+ {
+ fail("wrong seed data returned - composite");
+ }
+
+ fixed.nextBytes(buf);
+
+ if (!Arrays.areEqual(buf, Hex.decode("cafebabedeadbeef")))
+ {
+ fail("wrong data returned");
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new FixedSecureRandomTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/prng/test/HMacDRBGTest.java b/core/src/test/java/org/spongycastle/crypto/prng/test/HMacDRBGTest.java
new file mode 100644
index 00000000..cfbd386d
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/prng/test/HMacDRBGTest.java
@@ -0,0 +1,508 @@
+package org.spongycastle.crypto.prng.test;
+
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.digests.SHA384Digest;
+import org.spongycastle.crypto.digests.SHA512Digest;
+import org.spongycastle.crypto.macs.HMac;
+import org.spongycastle.crypto.prng.drbg.HMacSP800DRBG;
+import org.spongycastle.crypto.prng.drbg.SP80090DRBG;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * HMAC SP800-90 DRBG
+ */
+public class HMacDRBGTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "HMacDRBG";
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new HMacDRBGTest());
+ }
+
+ private DRBGTestVector[] createTestVectorData()
+ {
+ return new DRBGTestVector[]
+ {
+ new DRBGTestVector(
+ new SHA1Digest(),
+ new SHA1EntropyProvider().get(440),
+ false,
+ "2021222324",
+ 80,
+ new String[]
+ {
+ "5A7D3B449F481CB38DF79AD2B1FCC01E57F8135E8C0B22CD0630BFB0127FB5408C8EFC17A929896E",
+ "82cf772ec3e84b00fc74f5df104efbfb2428554e9ce367d03aeade37827fa8e9cb6a08196115d948"
+ }),
+ new DRBGTestVector(
+ new SHA1Digest(),
+ new SHA1EntropyProvider().get(440),
+ false,
+ "2021222324",
+ 80,
+ new String[]
+ {
+ "B3BD05246CBA12A64735A4E3FDE599BC1BE30F439BD060208EEA7D71F9D123DF47B3CE069D98EDE6",
+ "B5DADA380E2872DF935BCA55B882C8C9376902AB639765472B71ACEBE2EA8B1B6B49629CB67317E0"
+ })
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576"),
+ new DRBGTestVector(
+ new SHA1Digest(),
+ new SHA1EntropyProvider().get(440),
+ false,
+ "2021222324",
+ 80,
+ new String[]
+ {
+ "C7AAAC583C6EF6300714C2CC5D06C148CFFB40449AD0BB26FAC0497B5C57E161E36681BCC930CE80",
+ "6EBD2B7B5E0A2AD7A24B1BF9A1DBA47D43271719B9C37B7FE81BA94045A14A7CB514B446666EA5A7"
+ })
+ .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90919293949596")
+ .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6"),
+ new DRBGTestVector(
+ new SHA1Digest(),
+ new SHA1EntropyProvider().get(440),
+ true,
+ "2021222324",
+ 80,
+ new String[]
+ {
+ "FEC4597F06A3A8CC8529D59557B9E661053809C0BC0EFC282ABD87605CC90CBA9B8633DCB1DAE02E",
+ "84ADD5E2D2041C01723A4DE4335B13EFDF16B0E51A0AD39BD15E862E644F31E4A2D7D843E57C5968"
+ }),
+ new DRBGTestVector(
+ new SHA1Digest(),
+ new SHA1EntropyProvider().get(440),
+ true,
+ "2021222324",
+ 80,
+ new String[]
+ {
+ "6C37FDD729AA40F80BC6AB08CA7CC649794F6998B57081E4220F22C5C283E2C91B8E305AB869C625",
+ "CAF57DCFEA393B9236BF691FA456FEA7FDF1DF8361482CA54D5FA723F4C88B4FA504BF03277FA783"
+ })
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576"),
+ new DRBGTestVector(
+ new SHA1Digest(),
+ new SHA1EntropyProvider().get(440),
+ true,
+ "2021222324",
+ 80,
+ new String[]
+ {
+ "A1BA8FA58BB5013F43F7B6ED52B4539FA16DC77957AEE815B9C07004C7E992EB8C7E591964AFEEA2",
+ "84264A73A818C95C2F424B37D3CC990B046FB50C2DC64A164211889A010F2471A0912FFEA1BF0195"
+ })
+ .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90919293949596")
+ .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6"),
+ new DRBGTestVector(
+ new SHA256Digest(),
+ new SHA256EntropyProvider().get(440),
+ false,
+ "2021222324252627",
+ 128,
+ new String[]
+ {
+ "D67B8C1734F46FA3F763CF57C6F9F4F2" +
+ "DC1089BD8BC1F6F023950BFC5617635208C8501238AD7A44" +
+ "00DEFEE46C640B61AF77C2D1A3BFAA90EDE5D207406E5403",
+ "8FDAEC20F8B421407059E3588920DA7E" +
+ "DA9DCE3CF8274DFA1C59C108C1D0AA9B0FA38DA5C792037C" +
+ "4D33CD070CA7CD0C5608DBA8B885654639DE2187B74CB263"
+ }),
+ new DRBGTestVector(
+ new SHA256Digest(),
+ new SHA256EntropyProvider().get(440),
+ true,
+ "2021222324252627",
+ 128,
+ new String[]
+ {
+ "FABD0AE25C69DC2EFDEFB7F20C5A31B5" +
+ "7AC938AB771AA19BF8F5F1468F665C938C9A1A5DF0628A56" +
+ "90F15A1AD8A613F31BBD65EEAD5457D5D26947F29FE91AA7",
+ "6BD925B0E1C232EFD67CCD84F722E927" +
+ "ECB46AB2B740014777AF14BA0BBF53A45BDBB62B3F7D0B9C" +
+ "8EEAD057C0EC754EF8B53E60A1F434F05946A8B686AFBC7A"
+ }),
+ new DRBGTestVector(
+ new SHA384Digest(),
+ new SHA384EntropyProvider().get(888),
+ false,
+ "202122232425262728292A2B",
+ 192,
+ new String[]{
+ "03AB8BCE4D1DBBB636C5C5B7E1C58499FEB1C619CDD11D35" +
+ "CD6CF6BB8F20EF27B6F5F9054FF900DB9EBF7BF30ED4DCBB" +
+ "BC8D5B51C965EA226FFEE2CA5AB2EFD00754DC32F357BF7A" +
+ "E42275E0F7704DC44E50A5220AD05AB698A22640AC634829",
+ "B907E77144FD55A54E9BA1A6A0EED0AAC780020C41A15DD8" +
+ "9A6C163830BA1D094E6A17100FF71EE30A96E1EE04D2A966" +
+ "03832A4E404F1966C2B5F4CB61B9927E8D12AC1E1A24CF23" +
+ "88C14E8EC96C35181EAEE32AAA46330DEAAFE5E7CE783C74"})
+ .setPersonalizationString(
+ "404142434445464748494A4B4C4D4E" +
+ "4F505152535455565758595A5B5C5D5E5F60616263646566" +
+ "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" +
+ "7F808182838485868788898A8B8C8D8E8F90919293949596" +
+ "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"),
+ new DRBGTestVector(
+ new SHA384Digest(),
+ new SHA384EntropyProvider().get(888),
+ true,
+ "202122232425262728292A2B",
+ 192,
+ new String[]{
+ "804A3AD720F4FCE8738D0632514FEF16430CB7D63A8DF1A5" +
+ "F02A3CE3BD7ED6A668B69E63E2BB93F096EE753D6194A0F1" +
+ "A32711063653009636337D22167CC4402D019AC216FA574F" +
+ "091CF6EA283568D737A77BE38E8F09382C69E76B142ABC3A",
+ "73B8E55C753202176A17B9B9754A9FE6F23B01861FCD4059" +
+ "6AEAA301AF1AEF8AF0EAF22FBF34541EFFAB1431666ACACC" +
+ "759338C7E28672819D53CFEF10A3E19DAFBD53295F1980A9" +
+ "F491504A2725506784B7AC826D92C838A8668171CAAA86E7"})
+ .setPersonalizationString(
+ "404142434445464748494A4B4C4D4E" +
+ "4F505152535455565758595A5B5C5D5E5F60616263646566" +
+ "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" +
+ "7F808182838485868788898A8B8C8D8E8F90919293949596" +
+ "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"),
+ new DRBGTestVector(
+ new SHA512Digest(),
+ new SHA512EntropyProvider().get(888),
+ false,
+ "202122232425262728292A2B2C2D2E2F",
+ 256,
+ new String[]{
+ "2A5FF6520C20F66E" +
+ "D5EA431BD4AEAC58F975EEC9A015137D5C94B73AA09CB8B5" +
+ "9D611DDEECEB34A52BB999424009EB9EAC5353F92A6699D2" +
+ "0A02164EEBBC6492941E10426323898465DFD731C7E04730" +
+ "60A5AA8973841FDF3446FB6E72A58DA8BDA2A57A36F3DD98" +
+ "6DF85C8A5C6FF31CDE660BF8A841B21DD6AA9D3AC356B87B",
+ "0EDC8D7D7CEEC7FE" +
+ "36333FB30C0A9A4B27AA0BECBF075568B006C1C3693B1C29" +
+ "0F84769C213F98EB5880909EDF068FDA6BFC43503987BBBD" +
+ "4FC23AFBE982FE4B4B007910CC4874EEC217405421C8D8A1" +
+ "BA87EC684D0AF9A6101D9DB787AE82C3A6A25ED478DF1B12" +
+ "212CEC325466F3AC7C48A56166DD0B119C8673A1A9D54F67"})
+ .setPersonalizationString(
+ "404142434445464748494A4B4C4D4E" +
+ "4F505152535455565758595A5B5C5D5E5F60616263646566" +
+ "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" +
+ "7F808182838485868788898A8B8C8D8E8F90919293949596" +
+ "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"),
+ new DRBGTestVector(
+ new SHA512Digest(),
+ new SHA512EntropyProvider().get(888),
+ true,
+ "202122232425262728292A2B2C2D2E2F",
+ 256,
+ new String[]{
+ "AAE4DC3C9ECC74D9" +
+ "061DD527117EF3D29E1E52B26853C539D6CA797E8DA3D0BB" +
+ "171D8E30B8B194D8C28F7F6BE3B986B88506DC6A01B294A7" +
+ "165DD1C3470F7BE7B396AA0DB7D50C4051E7C7E1C8A7D21A" +
+ "2B5878C0BCB163CAA79366E7A1162FDC88429616CD3E6977" +
+ "8D327520A6BBBF71D8AA2E03EC4A9DAA0E77CF93E1EE30D2 ",
+ "129FF6D31A23FFBC" +
+ "870632B35EE477C2280DDD2ECDABEDB900C78418BE2D243B" +
+ "B9D8E5093ECE7B6BF48638D8F704D134ADDEB7F4E9D5C142" +
+ "CD05683E72B516486AF24AEC15D61E81E270DD4EBED91B62" +
+ "12EB8896A6250D5C8BC3A4A12F7E3068FBDF856F47EB23D3" +
+ "79F82C1EBCD1585FB260B9C0C42625FBCEE68CAD773CD5B1"})
+ .setPersonalizationString(
+ "404142434445464748494A4B4C4D4E" +
+ "4F505152535455565758595A5B5C5D5E5F60616263646566" +
+ "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" +
+ "7F808182838485868788898A8B8C8D8E8F90919293949596" +
+ "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"),
+ new DRBGTestVector(
+ new SHA512Digest(),
+ new SHA512EntropyProvider().get(888),
+ false,
+ "202122232425262728292A2B2C2D2E2F",
+ 256,
+ new String[]{
+ "7AE31A2DEC31075F" +
+ "E5972660C16D22ECC0D415C5693001BE5A468B590BC1AE2C" +
+ "43F647F8D681AEEA0D87B79B0B4E5D089CA2C9D327534234" +
+ "0254E6B04690D77A71A294DA9568479EEF8BB2A2110F18B6" +
+ "22F60F35235DE0E8F9D7E98105D84AA24AF0757AF005DFD5" +
+ "2FA51DE3F44FCE0C5F3A27FCE8B0F6E4A3F7C7B53CE34A3D",
+ "D83A8084630F286D" +
+ "A4DB49B9F6F608C8993F7F1397EA0D6F4A72CF3EF2733A11" +
+ "AB823C29F2EBDEC3EDE962F93D920A1DB59C84E1E879C29F" +
+ "5F9995FC3A6A3AF9B587CA7C13EA197D423E81E1D6469942" +
+ "B6E2CA83A97E91F6B298266AC148A1809776C26AF5E239A5" +
+ "5A2BEB9E752203A694E1F3FE2B3E6A0C9C314421CDB55FBD "})
+ .setPersonalizationString(
+ "404142434445464748494A4B4C4D4E" +
+ "4F505152535455565758595A5B5C5D5E5F60616263646566" +
+ "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" +
+ "7F808182838485868788898A8B8C8D8E8F90919293949596" +
+ "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE")
+ .addAdditionalInput(
+ "606162636465666768696A6B6C6D6E" +
+ "6F707172737475767778797A7B7C7D7E7F80818283848586" +
+ "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" +
+ "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" +
+ "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE")
+ .addAdditionalInput(
+ "A0A1A2A3A4A5A6A7A8A9AAABACADAE" +
+ "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" +
+ "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" +
+ "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" +
+ "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E"),
+ new DRBGTestVector(
+ new SHA512Digest(),
+ new SHA512EntropyProvider().get(888),
+ true,
+ "202122232425262728292A2B2C2D2E2F",
+ 256,
+ new String[]{
+ "28FD6060C4F35F4D" +
+ "317AB2060EE32019E0DAA330F3F5650BBCA57CB67EE6AF1C" +
+ "6F25D1B01F3601EDA85DC2ED29A9B2BA4C85CF491CE7185F" +
+ "1A2BD9378AE3C655BD1CEC2EE108AE7FC382989F6D4FEA8A" +
+ "B01499697C2F07945CE02C5ED617D04287FEAF3BA638A4CE" +
+ "F3BB6B827E40AF16279580FCF1FDAD830930F7FDE341E2AF",
+ "C0B1601AFE39338B" +
+ "58DC2BE7C256AEBE3C21C5A939BEEC7E97B3528AC420F0C6" +
+ "341847187666E0FF578A8EB0A37809F877365A28DF2FA0F0" +
+ "6354A6F02496747369375B9A9D6B756FDC4A8FB308E08256" +
+ "9D79A85BB960F747256626389A3B45B0ABE7ECBC39D5CD7B" +
+ "2C18DF2E5FDE8C9B8D43474C54B6F9839468445929B438C7"}),
+ new DRBGTestVector(
+ new SHA512Digest(),
+ new SHA512EntropyProvider().get(888),
+ true,
+ "202122232425262728292A2B2C2D2E2F",
+ 256,
+ new String[]{
+ "72691D2103FB567C" +
+ "CD30370715B36666F63430087B1C688281CA0974DB456BDB" +
+ "A7EB5C48CFF62EA05F9508F3B530CE995A272B11EC079C13" +
+ "923EEF8E011A93C19B58CC6716BC7CB8BD886CAA60C14D85" +
+ "C023348BD77738C475D6C7E1D9BFF4B12C43D8CC73F838DC" +
+ "4F8BD476CF8328EEB71B3D873D6B7B859C9B21065638FF95",
+ "8570DA3D47E1E160" +
+ "5CF3E44B8D328B995EFC64107B6292D1B1036B5F88CE3160" +
+ "2F12BEB71D801C0942E7C0864B3DB67A9356DB203490D881" +
+ "24FE86BCE38AC2269B4FDA6ABAA884039DF80A0336A24D79" +
+ "1EB3067C8F5F0CF0F18DD73B66A7B316FB19E02835CC6293" +
+ "65FCD1D3BE640178ED9093B91B36E1D68135F2785BFF505C"})
+ .addAdditionalInput(
+ "606162636465666768696A6B6C6D6E" +
+ "6F707172737475767778797A7B7C7D7E7F80818283848586" +
+ "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" +
+ "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" +
+ "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE")
+ .addAdditionalInput(
+ "A0A1A2A3A4A5A6A7A8A9AAABACADAE" +
+ "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" +
+ "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" +
+ "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" +
+ "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E"),
+ new DRBGTestVector(
+ new SHA512Digest(),
+ new SHA512EntropyProvider().get(888),
+ true,
+ "202122232425262728292A2B2C2D2E2F",
+ 256,
+ new String[]{
+ "AAE4DC3C9ECC74D9" +
+ "061DD527117EF3D29E1E52B26853C539D6CA797E8DA3D0BB" +
+ "171D8E30B8B194D8C28F7F6BE3B986B88506DC6A01B294A7" +
+ "165DD1C3470F7BE7B396AA0DB7D50C4051E7C7E1C8A7D21A" +
+ "2B5878C0BCB163CAA79366E7A1162FDC88429616CD3E6977" +
+ "8D327520A6BBBF71D8AA2E03EC4A9DAA0E77CF93E1EE30D2 ",
+ "129FF6D31A23FFBC" +
+ "870632B35EE477C2280DDD2ECDABEDB900C78418BE2D243B" +
+ "B9D8E5093ECE7B6BF48638D8F704D134ADDEB7F4E9D5C142" +
+ "CD05683E72B516486AF24AEC15D61E81E270DD4EBED91B62" +
+ "12EB8896A6250D5C8BC3A4A12F7E3068FBDF856F47EB23D3" +
+ "79F82C1EBCD1585FB260B9C0C42625FBCEE68CAD773CD5B1"})
+ .setPersonalizationString(
+ "404142434445464748494A4B4C4D4E" +
+ "4F505152535455565758595A5B5C5D5E5F60616263646566" +
+ "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" +
+ "7F808182838485868788898A8B8C8D8E8F90919293949596" +
+ "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"),
+ new DRBGTestVector(
+ new SHA512Digest(),
+ new SHA512EntropyProvider().get(888),
+ true,
+ "202122232425262728292A2B2C2D2E2F",
+ 256,
+ new String[]{
+ "B8E827652175E6E0" +
+ "6E513C7BE94B5810C14ED94AD903647940CAEB7EE014C848" +
+ "8DCBBE6D4D6616D06656A3DC707CDAC4F02EE6D8408C065F" +
+ "CB068C0760DA47C5D60E5D70D09DC3929B6979615D117F7B" +
+ "EDCC661A98514B3A1F55B2CBABDCA59F11823E4838065F1F" +
+ "8431CBF28A577738234AF3F188C7190CC19739E72E9BBFFF",
+ "7ED41B9CFDC8C256" +
+ "83BBB4C553CC2DC61F690E62ABC9F038A16B8C519690CABE" +
+ "BD1B5C196C57CF759BB9871BE0C163A57315EA96F615136D" +
+ "064572F09F26D659D24211F9610FFCDFFDA8CE23FFA96735" +
+ "7595182660877766035EED800B05364CE324A75EB63FD9B3" +
+ "EED956D147480B1D0A42DF8AA990BB628666F6F61D60CBE2"})
+ .setPersonalizationString(
+ "404142434445464748494A4B4C4D4E" +
+ "4F505152535455565758595A5B5C5D5E5F60616263646566" +
+ "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" +
+ "7F808182838485868788898A8B8C8D8E8F90919293949596" +
+ "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE")
+ .addAdditionalInput(
+ "606162636465666768696A6B6C6D6E" +
+ "6F707172737475767778797A7B7C7D7E7F80818283848586" +
+ "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" +
+ "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" +
+ "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE")
+ .addAdditionalInput(
+ "A0A1A2A3A4A5A6A7A8A9AAABACADAE" +
+ "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" +
+ "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" +
+ "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" +
+ "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E")
+ };
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ DRBGTestVector[] tests = createTestVectorData();
+
+ for (int i = 0; i != tests.length; i++)
+ {
+ DRBGTestVector tv = tests[i];
+
+ byte[] nonce = tv.nonce();
+ byte[] personalisationString = tv.personalizationString();
+
+ SP80090DRBG d = new HMacSP800DRBG(new HMac(tv.getDigest()), tv.securityStrength(), tv.entropySource(), personalisationString, nonce);
+
+ byte[] output = new byte[tv.expectedValue(0).length];
+
+ d.generate(output, tv.additionalInput(0), tv.predictionResistance());
+
+ byte[] expected = tv.expectedValue(0);
+
+ if (!areEqual(expected, output))
+ {
+ fail("Test #" + (i + 1) + ".1 failed, expected " + new String(Hex.encode(tv.expectedValue(0))) + " got " + new String(Hex.encode(output)));
+ }
+
+ output = new byte[tv.expectedValue(0).length];
+
+ d.generate(output, tv.additionalInput(1), tv.predictionResistance());
+
+ expected = tv.expectedValue(1);
+ if (!areEqual(expected, output))
+ {
+ fail("Test #" + (i + 1) + ".2 failed, expected " + new String(Hex.encode(tv.expectedValue(1))) + " got " + new String(Hex.encode(output)));
+ }
+ }
+
+ // Exception tests
+ //
+ SP80090DRBG d;
+ try
+ {
+ d = new HMacSP800DRBG(new HMac(new SHA256Digest()), 256, new SHA256EntropyProvider().get(128), null, null);
+ fail("no exception thrown");
+ }
+ catch (IllegalArgumentException e)
+ {
+ if (!e.getMessage().equals("Not enough entropy for security strength required"))
+ {
+ fail("Wrong exception", e);
+ }
+ }
+ }
+
+ private class SHA1EntropyProvider
+ extends TestEntropySourceProvider
+ {
+ SHA1EntropyProvider()
+ {
+ super(
+ Hex.decode(
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233343536"
+ + "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6"
+ + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6"), true);
+ }
+ }
+
+ private class SHA256EntropyProvider
+ extends TestEntropySourceProvider
+ {
+ SHA256EntropyProvider()
+ {
+ super(Hex.decode(
+ "00010203040506" +
+ "0708090A0B0C0D0E0F101112131415161718191A1B1C1D1E" +
+ "1F202122232425262728292A2B2C2D2E2F30313233343536" +
+ "80818283848586" +
+ "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" +
+ "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" +
+ "C0C1C2C3C4C5C6" +
+ "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" +
+ "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6"), true);
+ }
+ }
+
+ private class SHA384EntropyProvider
+ extends TestEntropySourceProvider
+ {
+ SHA384EntropyProvider()
+ {
+ super(Hex.decode(
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223242526"
+ + "2728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F50515253545556"
+ + "5758595A5B5C5D5E5F606162636465666768696A6B6C6D6E" +
+ "808182838485868788898A8B8C8D8E" +
+ "8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6" +
+ "A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBE" +
+ "BFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6" +
+ "D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE" +
+ "C0C1C2C3C4C5C6C7C8C9CACBCCCDCE" +
+ "CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6" +
+ "E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" +
+ "FF000102030405060708090A0B0C0D0E0F10111213141516" +
+ "1718191A1B1C1D1E1F202122232425262728292A2B2C2D2E"), true);
+ }
+ }
+
+ private class SHA512EntropyProvider
+ extends TestEntropySourceProvider
+ {
+ SHA512EntropyProvider()
+ {
+ super(Hex.decode(
+ "000102030405060708090A0B0C0D0E" +
+ "0F101112131415161718191A1B1C1D1E1F20212223242526" +
+ "2728292A2B2C2D2E2F303132333435363738393A3B3C3D3E" +
+ "3F404142434445464748494A4B4C4D4E4F50515253545556" +
+ "5758595A5B5C5D5E5F606162636465666768696A6B6C6D6E" +
+ "808182838485868788898A8B8C8D8E" +
+ "8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6" +
+ "A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBE" +
+ "BFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6" +
+ "D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE" +
+ "C0C1C2C3C4C5C6C7C8C9CACBCCCDCE" +
+ "CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6" +
+ "E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" +
+ "FF000102030405060708090A0B0C0D0E0F10111213141516" +
+ "1718191A1B1C1D1E1F202122232425262728292A2B2C2D2E"), true);
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/prng/test/HashDRBGTest.java b/core/src/test/java/org/spongycastle/crypto/prng/test/HashDRBGTest.java
new file mode 100644
index 00000000..294ae72c
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/prng/test/HashDRBGTest.java
@@ -0,0 +1,481 @@
+package org.spongycastle.crypto.prng.test;
+
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.digests.SHA384Digest;
+import org.spongycastle.crypto.digests.SHA512Digest;
+import org.spongycastle.crypto.prng.drbg.HashSP800DRBG;
+import org.spongycastle.crypto.prng.drbg.SP80090DRBG;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * DRBG Test
+ */
+public class HashDRBGTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "HashDRBG";
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new HashDRBGTest());
+ }
+
+ private DRBGTestVector[] createTestVectorData()
+ {
+ return new DRBGTestVector[]
+ {
+ new DRBGTestVector(
+ new SHA1Digest(),
+ new SHA1EntropyProvider().get(440),
+ false,
+ "2021222324",
+ 80,
+ new String[]
+ {
+ "9F7CFF1ECA23E750F66326969F11800F12088BA68E441D15D888B3FE12BF66FE057494F4546DE2F1",
+ "B77AA5C0CD55BBCEED7574AF223AFD988C7EEC8EFF4A94E5E89D26A04F58FA79F5E0D3702D7A9A6A"
+ }
+ ),
+ new DRBGTestVector(
+ new SHA1Digest(),
+ new SHA1EntropyProvider().get(440),
+ false,
+ "2021222324",
+ 80,
+ new String[]
+ {
+ "AB438BD3B01A0AF85CFEE29F7D7B71621C4908B909124D430E7B406FB1086EA994C582E0D656D989",
+ "29D9098F987E7005314A0F51B3DD2B8122F4AED706735DE6AD5DDBF223177C1E5F3AEBC52FAB90B9"
+ })
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576"),
+ new DRBGTestVector(
+ new SHA1Digest(),
+ new SHA1EntropyProvider().get(440),
+ false,
+ "2021222324",
+ 80,
+ new String[]
+ {
+ "E76B4EDD5C865BC8AFD809A59B69B429AC7F4352A579BCF3F75E56249A3491F87C3CA6848B0FAB25",
+ "6577B6B4F87A93240B199FE51A3B335313683103DECE171E3256FB7E803586CA4E45DD242EB01F70"
+ })
+ .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90919293949596")
+ .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6"),
+ new DRBGTestVector(
+ new SHA1Digest(),
+ new SHA1EntropyProvider().get(440),
+ true,
+ "2021222324",
+ 80,
+ new String[]
+ {
+ "56EF4913373994D5539F4D7D17AFE7448CDF5E72416CC6A71A340059FA0D5AE526B23250C46C0944",
+ "575B37A2739814F966C63B60A2C4F149CA9ACC84FC4B25493289B085C67B2E30F5F0B99A2C349E2A"
+ }),
+ new DRBGTestVector(
+ new SHA1Digest(),
+ new SHA1EntropyProvider().get(440),
+ true,
+ "2021222324",
+ 80,
+ new String[]
+ {
+ "532CA1165DCFF21C55592687639884AF4BC4B057DF8F41DE653AB44E2ADEC7C9303E75ABE277EDBF",
+ "73C2C67C696D686D0C4DBCEB5C2AF7DDF6F020B6874FAE4390F102117ECAAFF54418529A367005A0"
+ })
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576"),
+ new DRBGTestVector(
+ new SHA1Digest(),
+ new SHA1EntropyProvider().get(440),
+ true,
+ "2021222324",
+ 80,
+ new String[]
+ {
+ "183C242A1430E46C4ED70B4DBE1BF9AB0AB8721CDCA2A2D1820AD6F6C956858543B2AA191D8D1287",
+ "F196F9BD021C745CBD5AC7BFCE48EAAF0D0E7C091FBF436940E63A198EE770D9A4F0718669AF2BC9"
+ })
+ .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90919293949596")
+ .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6"),
+ new DRBGTestVector(
+ new SHA256Digest(),
+ new SHA256EntropyProvider().get(440),
+ false,
+ "2021222324252627",
+ 128,
+ new String[]
+ {
+ "77E05A0E7DC78AB5D8934D5E93E82C06" +
+ "A07C04CEE6C9C53045EEB485872777CF3B3E35C474F976B8" +
+ "94BF301A86FA651F463970E89D4A0534B2ECAD29EC044E7E",
+ "5FF4BA493C40CFFF3B01E472C575668C" +
+ "CE3880B9290B05BFEDE5EC96ED5E9B2898508B09BC800EEE" +
+ "099A3C90602ABD4B1D4F343D497C6055C87BB956D53BF351"
+ }
+ ),
+ new DRBGTestVector(
+ new SHA256Digest(),
+ new SHA256EntropyProvider().get(440),
+ true,
+ "2021222324252627",
+ 128,
+ new String[]
+ {
+ "92275523C70E567BCF9B35EC50B933F8" +
+ "12616DF586B7F72EE1BC7735A5C2654373CBBC72316DFF84" +
+ "20A33BF02B97AC8D1952583F270ACD7005CC027F4CF1187E",
+ "681A46B2AA8694A0FE4DEEA720927A84" +
+ "EAAA985E59C19F8BE0984D8CBEF8C69B754167641946E040" +
+ "EE2043E1CCB29DCF063C0A50830E428E6DCA262ECD77C542"
+ }),
+ new DRBGTestVector(
+ new SHA384Digest(),
+ new SHA384EntropyProvider().get(888),
+ false,
+ "202122232425262728292A2B",
+ 192,
+ new String[]
+ {
+ "04FF23AD15E78790ADD36B438BBC097C7A11747CC2CCEEDE" +
+ "2C978B23B3DC63B732C953061D7764990ABFEFC47A581B92" +
+ "1BC0428C4F12212460E406A0F0651E7F0CB9A90ABFDB07B5" +
+ "25565C74F0AA085082F6CF213AAFAD0C0646895078F1E1FE",
+ "4F35B85F95DEE3E873054905CFD02341653E18F529930CBE" +
+ "14D909F37FEAF2C790D22FAE7516B4590BE35D53E2FE1A35" +
+ "AFE4B6607CB358589C3B4D094A1D81FE0717F1DF5BDDEB3E" +
+ "114F130BB781E66C22B5B770E8AE115FF39F8ADAF66DEEDF"
+ }
+ ),
+ new DRBGTestVector(
+ new SHA384Digest(),
+ new SHA384EntropyProvider().get(888),
+ true,
+ "202122232425262728292A2B",
+ 192,
+ new String[]
+ {
+ "97993B78F7C31C0E876DC92EB7D6C408E09D608AD6B99D0E" +
+ "A2229B05A578C426334FCC8A1C7E676ED2D89A5B4CDF5B3F" +
+ "4ADF11936BF14F4E10909DBA9C24F4FDFFDE72351DA8E2CC" +
+ "3B135A395373899E5F1A5955B880CA9B9E9DD4C9CA7FA4D4",
+ "F5983946320E36C64EF283CA1F65D197CF81624EC6778E77" +
+ "0E78949D84EF21A45CDD62D1DB76920D4C2836FC6AE5299F" +
+ "AF1357D9701FAD10FBD88D1E2832239436D76EB271BDC3CA" +
+ "04425EC88BC0E89A4D5C37FFCE7C6C3ABDE9C413AE6D3FEA"
+ }
+ ),
+ new DRBGTestVector(
+ new SHA512Digest(),
+ new SHA512EntropyProvider().get(888),
+ false,
+ "202122232425262728292A2B2C2D2E2F",
+ 256,
+ new String[]
+ {
+ "DA126CF95C6BF97E" +
+ "2F731F2137A907ACC70FD7AC9EBACD1C6E31C74029B052E3" +
+ "AABC48F3B00993F2B2381F7650A55322A968C86E05DE88E6" +
+ "367F6EF89A601DB4342E9086C7AC13B5E56C32E9E668040B" +
+ "73847893C5BFD38A1CF44F348B4EEE4CD68ADB7E7B8C837F" +
+ "19BC4F902761F7CFF24AB1D704FD11C4E929D8553753B55D",
+ "400B977CE8A2BB6A" +
+ "84C6FD1CF901459685ABF5408CFF4588CEDF52E2D2DC300A" +
+ "A9B4FAED8CD0161C2172B1FD269253195883D6EBF21020F2" +
+ "C20E5F2C81AE60C8595B834A229B1F5B726C1125717E6207" +
+ "8886EF38E61E32707AD5F8116C6393DFB6E7C7AE0E8E92BB" +
+ "D7E0C3D04BBA02F5169F2F569A58158915FEE4C9D28D45DB"
+ }
+ )
+ .setPersonalizationString(
+ "404142434445464748494A4B4C4D4E" +
+ "4F505152535455565758595A5B5C5D5E5F60616263646566" +
+ "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" +
+ "7F808182838485868788898A8B8C8D8E8F90919293949596" +
+ "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE")
+ .addAdditionalInput(
+ "606162636465666768696A6B6C6D6E" +
+ "6F707172737475767778797A7B7C7D7E7F80818283848586" +
+ "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" +
+ "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" +
+ "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE")
+ .addAdditionalInput(
+ "A0A1A2A3A4A5A6A7A8A9AAABACADAE" +
+ "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" +
+ "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" +
+ "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" +
+ "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E"),
+ new DRBGTestVector(
+ new SHA512Digest(),
+ new SHA512EntropyProvider().get(888),
+ true,
+ "202122232425262728292A2B2C2D2E2F",
+ 256,
+ new String[]
+ {
+ "F93CA6855590A77F" +
+ "07354097E90E026648B6115DF008FFEDBD9D9811F54E8286" +
+ "EF00FDD6BA1E58DF2535E3FBDD9A9BA3754A97F36EE83322" +
+ "1582060A1F37FCE4EE8826636B28EAD589593F4CA8B64738" +
+ "8F24EB3F0A34796968D21BDEE6F81FD5DF93536F935937B8" +
+ "025EC8CBF57DDB0C61F2E41463CC1516D657DA2829C6BF90",
+ "4817618F48C60FB1" +
+ "CE5BFBDA0CAF4591882A31F6EE3FE0F78779992A06EC60F3" +
+ "7FB9A8D6108C231F0A927754B0599FA4FA27A4E25E065EF0" +
+ "3085B892979DC0E7A1080883CAEBFDFD3665A8F2D061C521" +
+ "F7D6E3DA2AF8B97B6B43B6EC831AF515070A83BBB9AC95ED" +
+ "4EF49B756A2377A5F0833D847E27A88DDB0C2CE4AD782E7B "
+ }
+ ),
+ new DRBGTestVector(
+ new SHA512Digest(),
+ new SHA512EntropyProvider().get(888),
+ true,
+ "202122232425262728292A2B2C2D2E2F",
+ 256,
+ new String[]
+ {
+ "0455DD4AD7DBACB2" +
+ "410BE58DF7248D765A4547ABAEE1743B0BCAD37EBD06DA7C" +
+ "F7CE5E2216E525327E9E2005EBEF2CE53BD733B18128627D" +
+ "3FD6153089373AF2606A1584646A0EA488BFEF45228699A0" +
+ "89CEA8AEC44502D86D9591F3552C688B7F7B45FCB0C3C2B9" +
+ "43C1CD8A6FC63DF4D81C3DA543C9CF2843855EA84E4F959C",
+ "C047D46D7F614E4E" +
+ "4A7952C79A451F8F7ACA379967E2977C401C626A2ED70D74" +
+ "A63660579A354115BC8C8C8CC3AEA3050686A0CFCDB6FA9C" +
+ "F78D4C2165BAF851C6F9B1CD16A2E14C15C6DAAC56C16E75" +
+ "FC84A14D58B41622E88B0F1B1995587FD8BAA999CBA98025" +
+ "4C8AB9A9691DF7B84D88B639A9A3106DEABEB63748B99C09"
+ }
+ )
+ .addAdditionalInput(
+ "606162636465666768696A6B6C6D6E" +
+ "6F707172737475767778797A7B7C7D7E7F80818283848586" +
+ "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" +
+ "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" +
+ "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE")
+ .addAdditionalInput(
+ "A0A1A2A3A4A5A6A7A8A9AAABACADAE" +
+ "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" +
+ "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" +
+ "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" +
+ "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E"),
+ new DRBGTestVector(
+ new SHA512Digest(),
+ new SHA512EntropyProvider().get(888),
+ true,
+ "202122232425262728292A2B2C2D2E2F",
+ 256,
+ new String[]
+ {
+ "22EB93A67911DA73" +
+ "85D9180C78127DE1A04FF713114C07C9C615F7CC5EF72744" +
+ "A2DDCD7C3CB85E65DED8EF5F240FBDCBEBBDE2BAAC8ECF7D" +
+ "CBC8AC333E54607AD41DC495D83DF72A05EF55B127C1441C" +
+ "9A0EFFDA2C7954DB6C2D04342EB812E5E0B11D6C395F41ED" +
+ "A2702ECE5BA479E2DFA18F953097492636C12FE30CE5C968",
+ "E66698CFBF1B3F2E" +
+ "919C03036E584EAA81CF1C6666240AF05F70637043733954" +
+ "D8A1E5A66A04C53C6900FDC145D4A3A80A31F5868ACE9AC9" +
+ "4E14E2051F624A05EEA1F8B684AA5410BCE315E76EA07C71" +
+ "5D6F34731320FF0DCF78D795E6EFA2DF92B98BE636CDFBA2" +
+ "9008DD392112AEC202F2E481CB9D83F987FEA69CD1B368BB"
+ }
+ )
+ .setPersonalizationString(
+ "404142434445464748494A4B4C4D4E" +
+ "4F505152535455565758595A5B5C5D5E5F60616263646566" +
+ "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" +
+ "7F808182838485868788898A8B8C8D8E8F90919293949596" +
+ "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"),
+ new DRBGTestVector(
+ new SHA512Digest(),
+ new SHA512EntropyProvider().get(888),
+ true,
+ "202122232425262728292A2B2C2D2E2F",
+ 256,
+ new String[]
+ {
+ "7596A76372308BD5" +
+ "A5613439934678B35521A94D81ABFE63A21ACF61ABB88B61" +
+ "E86A12C37F308F2BBBE32BE4B38D03AE808386494D70EF52" +
+ "E9E1365DD18B7784CAB826F31D47579E4D57F69D8BF3152B" +
+ "95741946CEBE58571DF58ED39980D9AF44E69F01E8989759" +
+ "8E40171101A0E3302838E0AD9E849C01988993CF9F6E5263",
+ "DBE5EE36FCD85301" +
+ "303E1C3617C1AC5E23C08885D0BEFAAD0C85A0D89F85B9F1" +
+ "6ECE3D88A24EB96504F2F13EFA7049621782F5DE2C416A0D" +
+ "294CCFE53545C4E309C48E1E285A2B829A574B72B3C2FBE1" +
+ "34D01E3706B486F2401B9820E17298A342666918E15B8462" +
+ "87F8C5AF2D96B20FAF3D0BB392E15F4A06CDB0DECD1B6AD7"
+ }
+ )
+ .setPersonalizationString(
+ "404142434445464748494A4B4C4D4E" +
+ "4F505152535455565758595A5B5C5D5E5F60616263646566" +
+ "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" +
+ "7F808182838485868788898A8B8C8D8E8F90919293949596" +
+ "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE")
+ .addAdditionalInput(
+ "606162636465666768696A6B6C6D6E" +
+ "6F707172737475767778797A7B7C7D7E7F80818283848586" +
+ "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" +
+ "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" +
+ "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE")
+ .addAdditionalInput(
+ "A0A1A2A3A4A5A6A7A8A9AAABACADAE" +
+ "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" +
+ "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" +
+ "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" +
+ "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E")
+ };
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ DRBGTestVector[] tests = createTestVectorData();
+
+ for (int i = 0; i != tests.length; i++)
+ {
+ DRBGTestVector tv = tests[i];
+
+ byte[] nonce = tv.nonce();
+ byte[] personalisationString = tv.personalizationString();
+
+ SP80090DRBG d = new HashSP800DRBG(tv.getDigest(), tv.securityStrength(), tv.entropySource(), personalisationString, nonce);
+
+ byte[] output = new byte[tv.expectedValue(0).length];
+
+ d.generate(output, tv.additionalInput(0), tv.predictionResistance());
+
+ byte[] expected = tv.expectedValue(0);
+
+ if (!areEqual(expected, output))
+ {
+ fail("Test #" + (i + 1) + ".1 failed, expected " + new String(Hex.encode(tv.expectedValue(0))) + " got " + new String(Hex.encode(output)));
+ }
+
+ output = new byte[tv.expectedValue(0).length];
+
+ d.generate(output, tv.additionalInput(1), tv.predictionResistance());
+
+ expected = tv.expectedValue(1);
+ if (!areEqual(expected, output))
+ {
+ fail("Test #" + (i + 1) + ".2 failed, expected " + new String(Hex.encode(tv.expectedValue(1))) + " got " + new String(Hex.encode(output)));
+ }
+ }
+
+ // Exception tests
+ //
+ SP80090DRBG d;
+ try
+ {
+ d = new HashSP800DRBG(new SHA256Digest(), 256, new SHA256EntropyProvider().get(128), null, null);
+ fail("no exception thrown");
+ }
+ catch (IllegalArgumentException e)
+ {
+ if (!e.getMessage().equals("Not enough entropy for security strength required"))
+ {
+ fail("Wrong exception", e);
+ }
+ }
+
+ try
+ {
+ d = new HashSP800DRBG(new SHA1Digest(), 256, new SHA256EntropyProvider().get(256), null, null);
+ fail("no exception thrown");
+ }
+ catch (IllegalArgumentException e)
+ {
+ if (!e.getMessage().equals("Requested security strength is not supported by the derivation function"))
+ {
+ fail("Wrong exception", e);
+ }
+ }
+ }
+
+ private class SHA1EntropyProvider
+ extends TestEntropySourceProvider
+ {
+ SHA1EntropyProvider()
+ {
+ super(
+ Hex.decode(
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233343536"
+ + "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6"
+ + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6"), true);
+ }
+ }
+
+ private class SHA256EntropyProvider
+ extends TestEntropySourceProvider
+ {
+ SHA256EntropyProvider()
+ {
+ super(Hex.decode(
+ "00010203040506" +
+ "0708090A0B0C0D0E0F101112131415161718191A1B1C1D1E" +
+ "1F202122232425262728292A2B2C2D2E2F30313233343536" +
+ "80818283848586" +
+ "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" +
+ "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" +
+ "C0C1C2C3C4C5C6" +
+ "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" +
+ "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6"), true);
+ }
+ }
+
+ private class SHA384EntropyProvider
+ extends TestEntropySourceProvider
+ {
+ SHA384EntropyProvider()
+ {
+ super(Hex.decode(
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223242526"
+ + "2728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F50515253545556"
+ + "5758595A5B5C5D5E5F606162636465666768696A6B6C6D6E" +
+ "808182838485868788898A8B8C8D8E" +
+ "8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6" +
+ "A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBE" +
+ "BFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6" +
+ "D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE" +
+ "C0C1C2C3C4C5C6C7C8C9CACBCCCDCE" +
+ "CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6" +
+ "E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" +
+ "FF000102030405060708090A0B0C0D0E0F10111213141516" +
+ "1718191A1B1C1D1E1F202122232425262728292A2B2C2D2E"), true);
+ }
+ }
+
+ private class SHA512EntropyProvider
+ extends TestEntropySourceProvider
+ {
+ SHA512EntropyProvider()
+ {
+ super(Hex.decode(
+ "000102030405060708090A0B0C0D0E" +
+ "0F101112131415161718191A1B1C1D1E1F20212223242526" +
+ "2728292A2B2C2D2E2F303132333435363738393A3B3C3D3E" +
+ "3F404142434445464748494A4B4C4D4E4F50515253545556" +
+ "5758595A5B5C5D5E5F606162636465666768696A6B6C6D6E" +
+ "808182838485868788898A8B8C8D8E" +
+ "8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6" +
+ "A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBE" +
+ "BFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6" +
+ "D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE" +
+ "C0C1C2C3C4C5C6C7C8C9CACBCCCDCE" +
+ "CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6" +
+ "E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" +
+ "FF000102030405060708090A0B0C0D0E0F10111213141516" +
+ "1718191A1B1C1D1E1F202122232425262728292A2B2C2D2E"), true);
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/prng/test/RegressionTest.java b/core/src/test/java/org/spongycastle/crypto/prng/test/RegressionTest.java
new file mode 100644
index 00000000..4c16e89d
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/prng/test/RegressionTest.java
@@ -0,0 +1,33 @@
+package org.spongycastle.crypto.prng.test;
+
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+public class RegressionTest
+{
+ public static Test[] tests = {
+ new CTRDRBGTest(),
+ new DualECDRBGTest(),
+ new HashDRBGTest(),
+ new HMacDRBGTest(),
+ new SP800RandomTest(),
+ new FixedSecureRandomTest()
+ };
+
+ public static void main(
+ String[] args)
+ {
+ for (int i = 0; i != tests.length; i++)
+ {
+ TestResult result = tests[i].perform();
+
+ if (result.getException() != null)
+ {
+ result.getException().printStackTrace();
+ }
+
+ System.out.println(result);
+ }
+ }
+}
+
diff --git a/core/src/test/java/org/spongycastle/crypto/prng/test/SP800RandomTest.java b/core/src/test/java/org/spongycastle/crypto/prng/test/SP800RandomTest.java
new file mode 100644
index 00000000..ce37d5b6
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/prng/test/SP800RandomTest.java
@@ -0,0 +1,319 @@
+package org.spongycastle.crypto.prng.test;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.engines.DESedeEngine;
+import org.spongycastle.crypto.macs.HMac;
+import org.spongycastle.crypto.prng.SP800SecureRandomBuilder;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class SP800RandomTest
+ extends SimpleTest
+{
+
+ public String getName()
+ {
+ return "SP800RandomTest";
+ }
+
+ private void testHashRandom()
+ {
+ DRBGTestVector tv = new DRBGTestVector(
+ new SHA1Digest(),
+ new SHA1EntropyProvider().get(440),
+ true,
+ "2021222324",
+ 80,
+ new String[]
+ {
+ "532CA1165DCFF21C55592687639884AF4BC4B057DF8F41DE653AB44E2ADEC7C9303E75ABE277EDBF",
+ "73C2C67C696D686D0C4DBCEB5C2AF7DDF6F020B6874FAE4390F102117ECAAFF54418529A367005A0"
+ })
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576");
+
+ doHashTest(0, tv);
+
+ tv = new DRBGTestVector(
+ new SHA1Digest(),
+ new SHA1EntropyProvider().get(440),
+ false,
+ "2021222324",
+ 80,
+ new String[]
+ {
+ "AB438BD3B01A0AF85CFEE29F7D7B71621C4908B909124D430E7B406FB1086EA994C582E0D656D989",
+ "29D9098F987E7005314A0F51B3DD2B8122F4AED706735DE6AD5DDBF223177C1E5F3AEBC52FAB90B9"
+ })
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576");
+
+ doHashTest(1, tv);
+ }
+
+ private void doHashTest(int index, DRBGTestVector tv)
+ {
+ SP800SecureRandomBuilder rBuild = new SP800SecureRandomBuilder(new SHA1EntropyProvider());
+
+ rBuild.setPersonalizationString(tv.personalizationString());
+ rBuild.setSecurityStrength(tv.securityStrength());
+ rBuild.setEntropyBitsRequired(tv.entropySource().getEntropy().length * 8);
+
+ SecureRandom random = rBuild.buildHash(tv.getDigest(), tv.nonce(), tv.predictionResistance());
+
+ byte[] expected = tv.expectedValue(0);
+ byte[] produced = new byte[expected.length];
+
+ random.nextBytes(produced);
+
+ if (!Arrays.areEqual(expected, produced))
+ {
+ fail(index + " SP800 Hash SecureRandom produced incorrect result (1)");
+ }
+
+ random.nextBytes(produced);
+ expected = tv.expectedValue(1);
+
+ if (!Arrays.areEqual(expected, produced))
+ {
+ fail(index + " SP800 Hash SecureRandom produced incorrect result (2)");
+ }
+ }
+
+ private void testHMACRandom()
+ {
+ DRBGTestVector tv = new DRBGTestVector(
+ new SHA1Digest(),
+ new SHA1EntropyProvider().get(440),
+ true,
+ "2021222324",
+ 80,
+ new String[]
+ {
+ "6C37FDD729AA40F80BC6AB08CA7CC649794F6998B57081E4220F22C5C283E2C91B8E305AB869C625",
+ "CAF57DCFEA393B9236BF691FA456FEA7FDF1DF8361482CA54D5FA723F4C88B4FA504BF03277FA783"
+ })
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576");
+
+ doHMACTest(tv);
+
+ tv = new DRBGTestVector(
+ new SHA1Digest(),
+ new SHA1EntropyProvider().get(440),
+ false,
+ "2021222324",
+ 80,
+ new String[]
+ {
+ "5A7D3B449F481CB38DF79AD2B1FCC01E57F8135E8C0B22CD0630BFB0127FB5408C8EFC17A929896E",
+ "82cf772ec3e84b00fc74f5df104efbfb2428554e9ce367d03aeade37827fa8e9cb6a08196115d948"
+ });
+
+ doHMACTest(tv);
+ }
+
+ private void doHMACTest(DRBGTestVector tv)
+ {
+ SP800SecureRandomBuilder rBuild = new SP800SecureRandomBuilder(new SHA1EntropyProvider());
+
+ rBuild.setPersonalizationString(tv.personalizationString());
+ rBuild.setSecurityStrength(tv.securityStrength());
+ rBuild.setEntropyBitsRequired(tv.entropySource().getEntropy().length * 8);
+
+ SecureRandom random = rBuild.buildHMAC(new HMac(tv.getDigest()), tv.nonce(), tv.predictionResistance());
+
+ byte[] expected = tv.expectedValue(0);
+ byte[] produced = new byte[expected.length];
+
+ random.nextBytes(produced);
+ if (!Arrays.areEqual(expected, produced))
+ {
+ fail("SP800 HMAC SecureRandom produced incorrect result (1)");
+ }
+
+ random.nextBytes(produced);
+ expected = tv.expectedValue(1);
+
+ if (!Arrays.areEqual(expected, produced))
+ {
+ fail("SP800 HMAC SecureRandom produced incorrect result (2)");
+ }
+ }
+
+ private void testDualECRandom()
+ {
+ DRBGTestVector tv = new DRBGTestVector(
+ new SHA256Digest(),
+ new SHA256EntropyProvider().get(128),
+ false,
+ "2021222324252627",
+ 128,
+ new String[]
+ {
+ "3AB095CC493A8730D70DE923108B2E4710799044FFC27D0A1156250DDF97E8B05ACE055E49F3E3F5B928CCD18317A3E68FCB0B6F0459ADF9ECF79C87",
+ "7B902FC35B0AF50F57F8822936D08A96E41B16967C6B1AA0BC05032F0D53919DC587B664C883E2FE8F3948002FCD8BCBFC4706BCAA2075EF6BF41167"
+ })
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F");
+
+ doDualECTest(1, tv);
+
+ tv = new DRBGTestVector(
+ new SHA256Digest(),
+ new SHA256EntropyProvider().get(128),
+ true,
+ "2021222324252627",
+ 128,
+ new String[]
+ {
+ "8C77288EDBEA9A742464F78D55E33593C1BF5F9D8CD8609D6D53BAC4E4B42252A227A99BAD0F2358B05955CD35723B549401C71C9C1F32F8A2018E24",
+ "56ECA61C64F69C1C232E992623C71418BD0B96D783118FAAD94A09E3A9DB74D15E805BA7F14625995CA77612B2EF7A05863699ECBABF70D3D422C014"
+ });
+
+ doDualECTest(2, tv);
+ }
+
+ private void doDualECTest(int index, DRBGTestVector tv)
+ {
+ SP800SecureRandomBuilder rBuild = new SP800SecureRandomBuilder(new SHA256EntropyProvider());
+
+ rBuild.setPersonalizationString(tv.personalizationString());
+ rBuild.setSecurityStrength(tv.securityStrength());
+ rBuild.setEntropyBitsRequired(tv.securityStrength());
+
+ SecureRandom random = rBuild.buildDualEC(tv.getDigest(), tv.nonce(), tv.predictionResistance());
+
+ byte[] expected = tv.expectedValue(0);
+ byte[] produced = new byte[expected.length];
+
+ random.nextBytes(produced);
+ if (!Arrays.areEqual(expected, produced))
+ {
+ fail(index + " SP800 Dual EC SecureRandom produced incorrect result (1)");
+ }
+
+ random.nextBytes(produced);
+ expected = tv.expectedValue(1);
+
+ if (!Arrays.areEqual(expected, produced))
+ {
+ fail(index + " SP800 Dual EC SecureRandom produced incorrect result (2)");
+ }
+ }
+
+ private void testCTRRandom()
+ {
+ DRBGTestVector tv = new DRBGTestVector(
+ new DESedeEngine(), 168,
+ new Bit232EntropyProvider().get(232),
+ false,
+ "20212223242526",
+ 112,
+ new String[]
+ {
+ "ABC88224514D0316EA3D48AEE3C9A2B4",
+ "D3D3F372E43E7ABDC4FA293743EED076"
+ }
+ );
+
+ doCTRTest(tv);
+
+ tv = new DRBGTestVector(
+ new DESedeEngine(), 168,
+ new Bit232EntropyProvider().get(232),
+ true,
+ "20212223242526",
+ 112,
+ new String[]
+ {
+ "64983055D014550B39DE699E43130B64",
+ "035FDDA8582A2214EC722C410A8D95D3"
+ }
+ )
+ .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C");
+
+ doCTRTest(tv);
+ }
+
+ private void doCTRTest(DRBGTestVector tv)
+ {
+ SP800SecureRandomBuilder rBuild = new SP800SecureRandomBuilder(new Bit232EntropyProvider());
+
+ rBuild.setPersonalizationString(tv.personalizationString());
+ rBuild.setSecurityStrength(tv.securityStrength());
+ rBuild.setEntropyBitsRequired(tv.entropySource().getEntropy().length * 8);
+
+ SecureRandom random = rBuild.buildCTR(tv.getCipher(), tv.keySizeInBits(), tv.nonce(), tv.predictionResistance());
+
+ byte[] expected = tv.expectedValue(0);
+ byte[] produced = new byte[expected.length];
+
+ random.nextBytes(produced);
+ if (!Arrays.areEqual(expected, produced))
+ {
+ fail("SP800 CTR SecureRandom produced incorrect result (1)");
+ }
+
+ random.nextBytes(produced);
+ expected = tv.expectedValue(1);
+
+ if (!Arrays.areEqual(expected, produced))
+ {
+ fail("SP800 CTR SecureRandom produced incorrect result (2)");
+ }
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ testHashRandom();
+ testHMACRandom();
+ testCTRRandom();
+ testDualECRandom();
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new SP800RandomTest());
+ }
+
+ // for HMAC/Hash
+ private class SHA1EntropyProvider
+ extends TestEntropySourceProvider
+ {
+ SHA1EntropyProvider()
+ {
+ super(
+ Hex.decode(
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233343536"
+ + "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6"
+ + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6"), true);
+ }
+ }
+
+ // for Dual EC
+ private class SHA256EntropyProvider
+ extends TestEntropySourceProvider
+ {
+ SHA256EntropyProvider()
+ {
+ super(Hex.decode(
+ "000102030405060708090A0B0C0D0E0F " +
+ "808182838485868788898A8B8C8D8E8F" +
+ "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"), true);
+ }
+ }
+
+ private class Bit232EntropyProvider
+ extends TestEntropySourceProvider
+ {
+ Bit232EntropyProvider()
+ {
+ super(Hex.decode(
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C" +
+ "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C" +
+ "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDC"), true);
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/prng/test/TestEntropySourceProvider.java b/core/src/test/java/org/spongycastle/crypto/prng/test/TestEntropySourceProvider.java
new file mode 100644
index 00000000..d630f4c9
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/prng/test/TestEntropySourceProvider.java
@@ -0,0 +1,46 @@
+package org.spongycastle.crypto.prng.test;
+
+import org.spongycastle.crypto.prng.EntropySource;
+import org.spongycastle.crypto.prng.EntropySourceProvider;
+
+public class TestEntropySourceProvider
+ implements EntropySourceProvider
+{
+ private final byte[] data;
+ private final boolean isPredictionResistant;
+
+ protected TestEntropySourceProvider(byte[] data, boolean isPredictionResistant)
+ {
+ this.data = data;
+ this.isPredictionResistant = isPredictionResistant;
+ }
+
+ public EntropySource get(final int bitsRequired)
+ {
+ return new EntropySource()
+ {
+ int index = 0;
+
+ public boolean isPredictionResistant()
+ {
+ return isPredictionResistant;
+ }
+
+ public byte[] getEntropy()
+ {
+ byte[] rv = new byte[bitsRequired / 8];
+
+ System.arraycopy(data, index, rv, 0, rv.length);
+
+ index += bitsRequired / 8;
+
+ return rv;
+ }
+
+ public int entropySize()
+ {
+ return bitsRequired;
+ }
+ };
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/AEADTestUtil.java b/core/src/test/java/org/spongycastle/crypto/test/AEADTestUtil.java
new file mode 100644
index 00000000..e2ff7e4c
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/AEADTestUtil.java
@@ -0,0 +1,474 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.modes.AEADBlockCipher;
+import org.spongycastle.crypto.params.AEADParameters;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestFailedException;
+
+public class AEADTestUtil
+{
+ public static void testTampering(Test test, AEADBlockCipher cipher, CipherParameters params)
+ throws InvalidCipherTextException
+ {
+ byte[] plaintext = new byte[1000];
+ for (int i = 0; i < plaintext.length; i++)
+ {
+ plaintext[i] = (byte)i;
+ }
+ cipher.init(true, params);
+
+ byte[] ciphertext = new byte[cipher.getOutputSize(plaintext.length)];
+ int len = cipher.processBytes(plaintext, 0, plaintext.length, ciphertext, 0);
+ cipher.doFinal(ciphertext, len);
+
+ int macLength = cipher.getMac().length;
+
+ // Test tampering with a single byte
+ cipher.init(false, params);
+ byte[] tampered = new byte[ciphertext.length];
+ byte[] output = new byte[plaintext.length];
+ System.arraycopy(ciphertext, 0, tampered, 0, tampered.length);
+ tampered[0] += 1;
+
+ cipher.processBytes(tampered, 0, tampered.length, output, 0);
+ try
+ {
+ cipher.doFinal(output, 0);
+ throw new TestFailedException(
+ new SimpleTestResult(false, test + " : tampering of ciphertext not detected."));
+ }
+ catch (InvalidCipherTextException e)
+ {
+ // Expected
+ }
+
+ // Test truncation of ciphertext to < tag length
+ cipher.init(false, params);
+ byte[] truncated = new byte[macLength - 1];
+ System.arraycopy(ciphertext, 0, truncated, 0, truncated.length);
+
+ cipher.processBytes(truncated, 0, truncated.length, output, 0);
+ try
+ {
+ cipher.doFinal(output, 0);
+ fail(test, "tampering of ciphertext not detected.");
+ }
+ catch (InvalidCipherTextException e)
+ {
+ // Expected
+ }
+ }
+
+ private static void fail(Test test, String message)
+ {
+ throw new TestFailedException(SimpleTestResult.failed(test, message));
+ }
+
+ private static void fail(Test test, String message, String expected, String result)
+ {
+ throw new TestFailedException(SimpleTestResult.failed(test, message, expected, result));
+ }
+
+ public static void testReset(Test test, AEADBlockCipher cipher1, AEADBlockCipher cipher2, CipherParameters params)
+ throws InvalidCipherTextException
+ {
+ cipher1.init(true, params);
+
+ byte[] plaintext = new byte[1000];
+ byte[] ciphertext = new byte[cipher1.getOutputSize(plaintext.length)];
+
+ // Establish baseline answer
+ crypt(cipher1, plaintext, ciphertext);
+
+ // Test encryption resets
+ checkReset(test, cipher1, params, true, plaintext, ciphertext);
+
+ // Test decryption resets with fresh instance
+ cipher2.init(false, params);
+ checkReset(test, cipher2, params, false, ciphertext, plaintext);
+ }
+
+ private static void checkReset(Test test,
+ AEADBlockCipher cipher,
+ CipherParameters params,
+ boolean encrypt,
+ byte[] pretext,
+ byte[] posttext)
+ throws InvalidCipherTextException
+ {
+ // Do initial run
+ byte[] output = new byte[posttext.length];
+ crypt(cipher, pretext, output);
+
+ // Check encrypt resets cipher
+ crypt(cipher, pretext, output);
+ if (!Arrays.areEqual(output, posttext))
+ {
+ fail(test, (encrypt ? "Encrypt" : "Decrypt") + " did not reset cipher.");
+ }
+
+ // Check init resets data
+ cipher.processBytes(pretext, 0, 100, output, 0);
+ cipher.init(encrypt, params);
+
+ try
+ {
+ crypt(cipher, pretext, output);
+ }
+ catch (DataLengthException e)
+ {
+ fail(test, "Init did not reset data.");
+ }
+ if (!Arrays.areEqual(output, posttext))
+ {
+ fail(test, "Init did not reset data.", new String(Hex.encode(posttext)), new String(Hex.encode(output)));
+ }
+
+ // Check init resets AD
+ cipher.processAADBytes(pretext, 0, 100);
+ cipher.init(encrypt, params);
+
+ try
+ {
+ crypt(cipher, pretext, output);
+ }
+ catch (DataLengthException e)
+ {
+ fail(test, "Init did not reset additional data.");
+ }
+ if (!Arrays.areEqual(output, posttext))
+ {
+ fail(test, "Init did not reset additional data.");
+ }
+
+ // Check reset resets data
+ cipher.processBytes(pretext, 0, 100, output, 0);
+ cipher.reset();
+
+ try
+ {
+ crypt(cipher, pretext, output);
+ }
+ catch (DataLengthException e)
+ {
+ fail(test, "Init did not reset data.");
+ }
+ if (!Arrays.areEqual(output, posttext))
+ {
+ fail(test, "Reset did not reset data.");
+ }
+
+ // Check reset resets AD
+ cipher.processAADBytes(pretext, 0, 100);
+ cipher.reset();
+
+ try
+ {
+ crypt(cipher, pretext, output);
+ }
+ catch (DataLengthException e)
+ {
+ fail(test, "Init did not reset data.");
+ }
+ if (!Arrays.areEqual(output, posttext))
+ {
+ fail(test, "Reset did not reset additional data.");
+ }
+ }
+
+ private static void crypt(AEADBlockCipher cipher, byte[] plaintext, byte[] output)
+ throws InvalidCipherTextException
+ {
+ int len = cipher.processBytes(plaintext, 0, plaintext.length, output, 0);
+ cipher.doFinal(output, len);
+ }
+
+ public static void testOutputSizes(Test test, AEADBlockCipher cipher, AEADParameters params)
+ throws IllegalStateException,
+ InvalidCipherTextException
+ {
+ int maxPlaintext = cipher.getUnderlyingCipher().getBlockSize() * 10;
+ byte[] plaintext = new byte[maxPlaintext];
+ byte[] ciphertext = new byte[maxPlaintext * 2];
+
+ // Check output size calculations for truncated ciphertext lengths
+ cipher.init(true, params);
+ cipher.doFinal(ciphertext, 0);
+ int macLength = cipher.getMac().length;
+
+ cipher.init(false, params);
+ for (int i = 0; i < macLength; i++)
+ {
+ cipher.reset();
+ if (cipher.getUpdateOutputSize(i) != 0)
+ {
+ fail(test, "AE cipher should not produce update output with ciphertext length <= macSize");
+ }
+ if (cipher.getOutputSize(i) != 0)
+ {
+ fail(test, "AE cipher should not produce output with ciphertext length <= macSize");
+ }
+ }
+
+ for (int i = 0; i < plaintext.length; i++)
+ {
+ cipher.init(true, params);
+ int expectedCTUpdateSize = cipher.getUpdateOutputSize(i);
+ int expectedCTOutputSize = cipher.getOutputSize(i);
+
+ if (expectedCTUpdateSize < 0)
+ {
+ fail(test, "Encryption update output size should not be < 0 for size " + i);
+ }
+
+ if (expectedCTOutputSize < 0)
+ {
+ fail(test, "Encryption update output size should not be < 0 for size " + i);
+ }
+
+ int actualCTSize = cipher.processBytes(plaintext, 0, i, ciphertext, 0);
+
+ if (expectedCTUpdateSize != actualCTSize)
+ {
+ fail(test, "Encryption update output size did not match calculated for plaintext length " + i,
+ String.valueOf(expectedCTUpdateSize), String.valueOf(actualCTSize));
+ }
+
+ actualCTSize += cipher.doFinal(ciphertext, actualCTSize);
+
+ if (expectedCTOutputSize != actualCTSize)
+ {
+ fail(test, "Encryption actual final output size did not match calculated for plaintext length " + i,
+ String.valueOf(expectedCTOutputSize), String.valueOf(actualCTSize));
+ }
+
+ cipher.init(false, params);
+ int expectedPTUpdateSize = cipher.getUpdateOutputSize(actualCTSize);
+ int expectedPTOutputSize = cipher.getOutputSize(actualCTSize);
+
+ if (expectedPTOutputSize != i)
+ {
+ fail(test, "Decryption update output size did not original plaintext length " + i,
+ String.valueOf(expectedPTUpdateSize), String.valueOf(i));
+ }
+
+ int actualPTSize = cipher.processBytes(ciphertext, 0, actualCTSize, plaintext, 0);
+
+ if (expectedPTUpdateSize != actualPTSize)
+ {
+ fail(test, "Decryption update output size did not match calculated for plaintext length " + i,
+ String.valueOf(expectedPTUpdateSize), String.valueOf(actualPTSize));
+ }
+
+ actualPTSize += cipher.doFinal(plaintext, actualPTSize);
+
+ if (expectedPTOutputSize != actualPTSize)
+ {
+ fail(test, "Decryption update output size did not match calculated for plaintext length " + i,
+ String.valueOf(expectedPTOutputSize), String.valueOf(actualPTSize));
+ }
+
+ }
+ }
+
+ public static void testBufferSizeChecks(Test test, AEADBlockCipher cipher, AEADParameters params)
+ throws IllegalStateException,
+ InvalidCipherTextException
+ {
+ int blockSize = cipher.getUnderlyingCipher().getBlockSize();
+ int maxPlaintext = (blockSize * 10);
+ byte[] plaintext = new byte[maxPlaintext];
+
+
+ cipher.init(true, params);
+
+ int expectedUpdateOutputSize = cipher.getUpdateOutputSize(plaintext.length);
+ byte[] ciphertext = new byte[cipher.getOutputSize(plaintext.length)];
+
+ try
+ {
+ cipher.processBytes(new byte[maxPlaintext - 1], 0, maxPlaintext, new byte[expectedUpdateOutputSize], 0);
+ fail(test, "processBytes should validate input buffer length");
+ }
+ catch (DataLengthException e)
+ {
+ // Expected
+ }
+ cipher.reset();
+
+ if (expectedUpdateOutputSize > 0)
+ {
+ int outputTrigger = 0;
+ // Process bytes until output would be produced
+ for(int i = 0; i < plaintext.length; i++) {
+ if (cipher.getUpdateOutputSize(1) != 0)
+ {
+ outputTrigger = i + 1;
+ break;
+ }
+ cipher.processByte(plaintext[i], ciphertext, 0);
+ }
+ if (outputTrigger == 0)
+ {
+ fail(test, "Failed to find output trigger size");
+ }
+ try
+ {
+ cipher.processByte(plaintext[0], new byte[cipher.getUpdateOutputSize(1) - 1], 0);
+ fail(test, "Encrypt processByte should validate output buffer length");
+ }
+ catch (OutputLengthException e)
+ {
+ // Expected
+ }
+ cipher.reset();
+
+ // Repeat checking with entire input at once
+ try
+ {
+ cipher.processBytes(plaintext, 0, outputTrigger,
+ new byte[cipher.getUpdateOutputSize(outputTrigger) - 1], 0);
+ fail(test, "Encrypt processBytes should validate output buffer length");
+ }
+ catch (OutputLengthException e)
+ {
+ // Expected
+ }
+ cipher.reset();
+
+ }
+
+ // Remember the actual ciphertext for later
+ int actualOutputSize = cipher.processBytes(plaintext, 0, plaintext.length, ciphertext, 0);
+ actualOutputSize += cipher.doFinal(ciphertext, actualOutputSize);
+ int macSize = cipher.getMac().length;
+
+ cipher.reset();
+ try
+ {
+ cipher.processBytes(plaintext, 0, plaintext.length, ciphertext, 0);
+ cipher.doFinal(new byte[cipher.getOutputSize(0) - 1], 0);
+ fail(test, "Encrypt doFinal should validate output buffer length");
+ }
+ catch (OutputLengthException e)
+ {
+ // Expected
+ }
+
+ // Decryption tests
+
+ cipher.init(false, params);
+ expectedUpdateOutputSize = cipher.getUpdateOutputSize(actualOutputSize);
+
+ if (expectedUpdateOutputSize > 0)
+ {
+ // Process bytes until output would be produced
+ int outputTrigger = 0;
+ for (int i = 0; i < plaintext.length; i++)
+ {
+ if (cipher.getUpdateOutputSize(1) != 0)
+ {
+ outputTrigger = i + 1;
+ break;
+ }
+ cipher.processByte(ciphertext[i], plaintext, 0);
+ }
+ if (outputTrigger == 0)
+ {
+ fail(test, "Failed to find output trigger size");
+ }
+
+ try
+ {
+ cipher.processByte(ciphertext[0], new byte[cipher.getUpdateOutputSize(1) - 1], 0);
+ fail(test, "Decrypt processByte should validate output buffer length");
+ }
+ catch (OutputLengthException e)
+ {
+ // Expected
+ }
+ cipher.reset();
+
+ // Repeat test with processBytes
+ try
+ {
+ cipher.processBytes(ciphertext, 0, outputTrigger,
+ new byte[cipher.getUpdateOutputSize(outputTrigger) - 1], 0);
+ fail(test, "Decrypt processBytes should validate output buffer length");
+ }
+ catch (OutputLengthException e)
+ {
+ // Expected
+ }
+ }
+
+ cipher.reset();
+ // Data less than mac length should fail before output length check
+ try
+ {
+ // Assumes AE cipher on decrypt can't return any data until macSize bytes are received
+ if (cipher.processBytes(ciphertext, 0, macSize - 1, plaintext, 0) != 0)
+ {
+ fail(test, "AE cipher unexpectedly produced output");
+ }
+ cipher.doFinal(new byte[0], 0);
+ fail(test, "Decrypt doFinal should check ciphertext length");
+ }
+ catch (InvalidCipherTextException e)
+ {
+ // Expected
+ }
+
+ try
+ {
+ // Search through plaintext lengths until one is found that creates >= 1 buffered byte
+ // during decryption of ciphertext for doFinal to handle
+ for (int i = 2; i < plaintext.length; i++)
+ {
+ cipher.init(true, params);
+ int encrypted = cipher.processBytes(plaintext, 0, i, ciphertext, 0);
+ encrypted += cipher.doFinal(ciphertext, encrypted);
+
+ cipher.init(false, params);
+ cipher.processBytes(ciphertext, 0, encrypted - 1, plaintext, 0);
+ if (cipher.processByte(ciphertext[encrypted - 1], plaintext, 0) == 0)
+ {
+ cipher.doFinal(new byte[cipher.getOutputSize(0) - 1], 0);
+ fail(test, "Decrypt doFinal should check output length");
+ cipher.reset();
+
+ // Truncated Mac should be reported in preference to inability to output
+ // buffered plaintext byte
+ try
+ {
+ cipher.processBytes(ciphertext, 0, actualOutputSize - 1, plaintext, 0);
+ cipher.doFinal(new byte[cipher.getOutputSize(0) - 1], 0);
+ fail(test, "Decrypt doFinal should check ciphertext length");
+ }
+ catch (InvalidCipherTextException e)
+ {
+ // Expected
+ }
+ cipher.reset();
+ }
+ }
+ fail(test, "Decrypt doFinal test couldn't find a ciphertext length that buffered for doFinal");
+ }
+ catch (OutputLengthException e)
+ {
+ // Expected
+ }
+ }
+
+ static AEADParameters reuseKey(AEADParameters p)
+ {
+ return new AEADParameters(null, p.getMacSize(), p.getNonce(), p.getAssociatedText());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/AESFastTest.java b/core/src/test/java/org/spongycastle/crypto/test/AESFastTest.java
new file mode 100644
index 00000000..6892ed77
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/AESFastTest.java
@@ -0,0 +1,150 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.engines.AESFastEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * Test vectors from the NIST standard tests and Brian Gladman's vector set
+ * <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">
+ * http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
+ */
+public class AESFastTest
+ extends CipherTest
+{
+ static SimpleTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new AESFastEngine(),
+ new KeyParameter(Hex.decode("80000000000000000000000000000000")),
+ "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
+ new BlockCipherVectorTest(1, new AESFastEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000080")),
+ "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
+ new BlockCipherMonteCarloTest(2, 10000, new AESFastEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000")),
+ "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
+ new BlockCipherMonteCarloTest(3, 10000, new AESFastEngine(),
+ new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")),
+ "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
+ new BlockCipherVectorTest(4, new AESFastEngine(),
+ new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
+ "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
+ new BlockCipherMonteCarloTest(5, 10000, new AESFastEngine(),
+ new KeyParameter(Hex.decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
+ "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
+ new BlockCipherVectorTest(6, new AESFastEngine(),
+ new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
+ "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
+ new BlockCipherMonteCarloTest(7, 10000, new AESFastEngine(),
+ new KeyParameter(Hex.decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
+ "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168"),
+ new BlockCipherVectorTest(8, new AESFastEngine(),
+ new KeyParameter(Hex.decode("80000000000000000000000000000000")),
+ "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
+ new BlockCipherVectorTest(9, new AESFastEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000080")),
+ "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
+ new BlockCipherMonteCarloTest(10, 10000, new AESFastEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000")),
+ "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
+ new BlockCipherMonteCarloTest(11, 10000, new AESFastEngine(),
+ new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")),
+ "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
+ new BlockCipherVectorTest(12, new AESFastEngine(),
+ new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
+ "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
+ new BlockCipherMonteCarloTest(13, 10000, new AESFastEngine(),
+ new KeyParameter(Hex.decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
+ "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
+ new BlockCipherVectorTest(14, new AESFastEngine(),
+ new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
+ "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
+ new BlockCipherMonteCarloTest(15, 10000, new AESFastEngine(),
+ new KeyParameter(Hex.decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
+ "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168"),
+ new BlockCipherVectorTest(16, new AESFastEngine(),
+ new KeyParameter(Hex.decode("80000000000000000000000000000000")),
+ "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
+ new BlockCipherVectorTest(17, new AESFastEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000080")),
+ "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
+ new BlockCipherMonteCarloTest(18, 10000, new AESFastEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000")),
+ "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
+ new BlockCipherMonteCarloTest(19, 10000, new AESFastEngine(),
+ new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")),
+ "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
+ new BlockCipherVectorTest(20, new AESFastEngine(),
+ new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
+ "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
+ new BlockCipherMonteCarloTest(21, 10000, new AESFastEngine(),
+ new KeyParameter(Hex.decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
+ "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
+ new BlockCipherVectorTest(22, new AESFastEngine(),
+ new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
+ "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
+ new BlockCipherMonteCarloTest(23, 10000, new AESFastEngine(),
+ new KeyParameter(Hex.decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
+ "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168")
+ };
+
+ private BlockCipher _engine = new AESFastEngine();
+
+ AESFastTest()
+ {
+ super(tests, new AESFastEngine(), new KeyParameter(new byte[16]));
+ }
+
+ public String getName()
+ {
+ return "AESFast";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ super.performTest();
+
+ byte[] keyBytes = new byte[16];
+
+ _engine.init(true, new KeyParameter(keyBytes));
+
+ //
+ // init tests
+ //
+ try
+ {
+ byte[] dudKey = new byte[6];
+
+ _engine.init(true, new KeyParameter(dudKey));
+
+ fail("failed key length check");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ byte[] iv = new byte[16];
+
+ _engine.init(true, new ParametersWithIV(null, iv));
+
+ fail("failed parameter check");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new AESFastTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/AESLightTest.java b/core/src/test/java/org/spongycastle/crypto/test/AESLightTest.java
new file mode 100644
index 00000000..a3c4ca53
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/AESLightTest.java
@@ -0,0 +1,150 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.engines.AESLightEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * Test vectors from the NIST standard tests and Brian Gladman's vector set
+ * <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">
+ * http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
+ */
+public class AESLightTest
+ extends CipherTest
+{
+ static SimpleTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new AESLightEngine(),
+ new KeyParameter(Hex.decode("80000000000000000000000000000000")),
+ "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
+ new BlockCipherVectorTest(1, new AESLightEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000080")),
+ "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
+ new BlockCipherMonteCarloTest(2, 10000, new AESLightEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000")),
+ "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
+ new BlockCipherMonteCarloTest(3, 10000, new AESLightEngine(),
+ new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")),
+ "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
+ new BlockCipherVectorTest(4, new AESLightEngine(),
+ new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
+ "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
+ new BlockCipherMonteCarloTest(5, 10000, new AESLightEngine(),
+ new KeyParameter(Hex.decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
+ "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
+ new BlockCipherVectorTest(6, new AESLightEngine(),
+ new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
+ "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
+ new BlockCipherMonteCarloTest(7, 10000, new AESLightEngine(),
+ new KeyParameter(Hex.decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
+ "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168"),
+ new BlockCipherVectorTest(8, new AESLightEngine(),
+ new KeyParameter(Hex.decode("80000000000000000000000000000000")),
+ "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
+ new BlockCipherVectorTest(9, new AESLightEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000080")),
+ "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
+ new BlockCipherMonteCarloTest(10, 10000, new AESLightEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000")),
+ "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
+ new BlockCipherMonteCarloTest(11, 10000, new AESLightEngine(),
+ new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")),
+ "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
+ new BlockCipherVectorTest(12, new AESLightEngine(),
+ new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
+ "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
+ new BlockCipherMonteCarloTest(13, 10000, new AESLightEngine(),
+ new KeyParameter(Hex.decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
+ "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
+ new BlockCipherVectorTest(14, new AESLightEngine(),
+ new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
+ "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
+ new BlockCipherMonteCarloTest(15, 10000, new AESLightEngine(),
+ new KeyParameter(Hex.decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
+ "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168"),
+ new BlockCipherVectorTest(16, new AESLightEngine(),
+ new KeyParameter(Hex.decode("80000000000000000000000000000000")),
+ "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
+ new BlockCipherVectorTest(17, new AESLightEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000080")),
+ "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
+ new BlockCipherMonteCarloTest(18, 10000, new AESLightEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000")),
+ "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
+ new BlockCipherMonteCarloTest(19, 10000, new AESLightEngine(),
+ new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")),
+ "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
+ new BlockCipherVectorTest(20, new AESLightEngine(),
+ new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
+ "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
+ new BlockCipherMonteCarloTest(21, 10000, new AESLightEngine(),
+ new KeyParameter(Hex.decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
+ "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
+ new BlockCipherVectorTest(22, new AESLightEngine(),
+ new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
+ "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
+ new BlockCipherMonteCarloTest(23, 10000, new AESLightEngine(),
+ new KeyParameter(Hex.decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
+ "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168")
+ };
+
+ private BlockCipher _engine = new AESLightEngine();
+
+ AESLightTest()
+ {
+ super(tests, new AESLightEngine(), new KeyParameter(new byte[16]));
+ }
+
+ public String getName()
+ {
+ return "AESLight";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ super.performTest();
+
+ byte[] keyBytes = new byte[16];
+
+ _engine.init(true, new KeyParameter(keyBytes));
+
+ //
+ // init tests
+ //
+ try
+ {
+ byte[] dudKey = new byte[6];
+
+ _engine.init(true, new KeyParameter(dudKey));
+
+ fail("failed key length check");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ byte[] iv = new byte[16];
+
+ _engine.init(true, new ParametersWithIV(null, iv));
+
+ fail("failed parameter check");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new AESLightTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/AESTest.java b/core/src/test/java/org/spongycastle/crypto/test/AESTest.java
new file mode 100644
index 00000000..243d9e8b
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/AESTest.java
@@ -0,0 +1,442 @@
+package org.spongycastle.crypto.test;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.BufferedBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.engines.AESEngine;
+import org.spongycastle.crypto.modes.CBCBlockCipher;
+import org.spongycastle.crypto.modes.CFBBlockCipher;
+import org.spongycastle.crypto.modes.OFBBlockCipher;
+import org.spongycastle.crypto.modes.SICBlockCipher;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * Test vectors from the NIST standard tests and Brian Gladman's vector set
+ * <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">
+ * http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
+ */
+public class AESTest
+ extends CipherTest
+{
+ private static final byte[] tData = Hex.decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114F3F6752AE8D7831138F041560631B1145A01020304050607");
+ private static final byte[] outCBC1 = Hex.decode("a444a9a4d46eb30cb7ed34d62873a89f8fdf2bf8a54e1aeadd06fd85c9cb46f021ee7cd4f418fa0bb72e9d07c70d5d20");
+ private static final byte[] outCBC2 = Hex.decode("585681354f0e01a86b32f94ebb6a675045d923cf201263c2aaecca2b4de82da0edd74ca5efd654c688f8a58e61955b11");
+ private static final byte[] outSIC1 = Hex.decode("82a1744e8ebbd053ca72362d5e570326e0b6fdaf824ab673fbf029042886b23c75129a015852913790f81f94447475a0");
+ private static final byte[] outSIC2 = Hex.decode("146cbb581d9e12c3333dd9c736fbb93043c92019f78580da48f81f80b3f551d58ea836fed480fc6912fefa9c5c89cc24");
+ private static final byte[] outCFB1 = Hex.decode("82a1744e8ebbd053ca72362d5e5703264b4182de3208c374b8ac4fa36af9c5e5f4f87d1e3b67963d06acf5eb13914c90");
+ private static final byte[] outCFB2 = Hex.decode("146cbb581d9e12c3333dd9c736fbb9303c8a3eb5185e2809e9d3c28e25cc2d2b6f5c11ee28d6530f72c412b1438a816a");
+ private static final byte[] outOFB1 = Hex.decode("82a1744e8ebbd053ca72362d5e5703261ebf1fdbec05e57b3465b583132f84b43bf95b2c89040ad1677b22d42db69a7a");
+ private static final byte[] outOFB2 = Hex.decode("146cbb581d9e12c3333dd9c736fbb9309ea4c2a7696c84959a2dada49f2f1c5905db1f0cec3a31acbc4701e74ab05e1f");
+
+ static SimpleTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new AESEngine(),
+ new KeyParameter(Hex.decode("80000000000000000000000000000000")),
+ "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
+ new BlockCipherVectorTest(1, new AESEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000080")),
+ "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
+ new BlockCipherMonteCarloTest(2, 10000, new AESEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000")),
+ "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
+ new BlockCipherMonteCarloTest(3, 10000, new AESEngine(),
+ new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")),
+ "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
+ new BlockCipherVectorTest(4, new AESEngine(),
+ new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
+ "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
+ new BlockCipherMonteCarloTest(5, 10000, new AESEngine(),
+ new KeyParameter(Hex.decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
+ "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
+ new BlockCipherVectorTest(6, new AESEngine(),
+ new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
+ "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
+ new BlockCipherMonteCarloTest(7, 10000, new AESEngine(),
+ new KeyParameter(Hex.decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
+ "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168"),
+ new BlockCipherVectorTest(8, new AESEngine(),
+ new KeyParameter(Hex.decode("80000000000000000000000000000000")),
+ "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
+ new BlockCipherVectorTest(9, new AESEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000080")),
+ "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
+ new BlockCipherMonteCarloTest(10, 10000, new AESEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000")),
+ "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
+ new BlockCipherMonteCarloTest(11, 10000, new AESEngine(),
+ new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")),
+ "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
+ new BlockCipherVectorTest(12, new AESEngine(),
+ new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
+ "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
+ new BlockCipherMonteCarloTest(13, 10000, new AESEngine(),
+ new KeyParameter(Hex.decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
+ "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
+ new BlockCipherVectorTest(14, new AESEngine(),
+ new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
+ "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
+ new BlockCipherMonteCarloTest(15, 10000, new AESEngine(),
+ new KeyParameter(Hex.decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
+ "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168"),
+ new BlockCipherVectorTest(16, new AESEngine(),
+ new KeyParameter(Hex.decode("80000000000000000000000000000000")),
+ "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
+ new BlockCipherVectorTest(17, new AESEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000080")),
+ "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
+ new BlockCipherMonteCarloTest(18, 10000, new AESEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000")),
+ "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
+ new BlockCipherMonteCarloTest(19, 10000, new AESEngine(),
+ new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")),
+ "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
+ new BlockCipherVectorTest(20, new AESEngine(),
+ new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
+ "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
+ new BlockCipherMonteCarloTest(21, 10000, new AESEngine(),
+ new KeyParameter(Hex.decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
+ "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
+ new BlockCipherVectorTest(22, new AESEngine(),
+ new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
+ "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
+ new BlockCipherMonteCarloTest(23, 10000, new AESEngine(),
+ new KeyParameter(Hex.decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
+ "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168")
+ };
+
+ private BlockCipher _engine = new AESEngine();
+
+ public AESTest()
+ {
+ super(tests, new AESEngine(), new KeyParameter(new byte[16]));
+ }
+
+ public String getName()
+ {
+ return "AES";
+ }
+
+ private void testNullSIC()
+ throws InvalidCipherTextException
+ {
+ BufferedBlockCipher b = new BufferedBlockCipher(new SICBlockCipher(new AESEngine()));
+ KeyParameter kp = new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917"));
+
+ b.init(true, new ParametersWithIV(kp, new byte[16]));
+
+ byte[] out = new byte[b.getOutputSize(tData.length)];
+
+ int len = b.processBytes(tData, 0, tData.length, out, 0);
+
+ len += b.doFinal(out, len);
+
+ if (!areEqual(outSIC1, out))
+ {
+ fail("no match on first nullSIC check");
+ }
+
+ b.init(true, new ParametersWithIV(null, Hex.decode("000102030405060708090a0b0c0d0e0f")));
+
+ len = b.processBytes(tData, 0, tData.length, out, 0);
+
+ len += b.doFinal(out, len);
+
+ if (!areEqual(outSIC2, out))
+ {
+ fail("no match on second nullSIC check");
+ }
+ }
+
+ private void testNullCBC()
+ throws InvalidCipherTextException
+ {
+ BufferedBlockCipher b = new BufferedBlockCipher(new CBCBlockCipher(new AESEngine()));
+ KeyParameter kp = new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917"));
+
+ b.init(true, new ParametersWithIV(kp, new byte[16]));
+
+ byte[] out = new byte[b.getOutputSize(tData.length)];
+
+ int len = b.processBytes(tData, 0, tData.length, out, 0);
+
+ len += b.doFinal(out, len);
+
+ if (!areEqual(outCBC1, out))
+ {
+ fail("no match on first nullCBC check");
+ }
+
+ b.init(true, new ParametersWithIV(null, Hex.decode("000102030405060708090a0b0c0d0e0f")));
+
+ len = b.processBytes(tData, 0, tData.length, out, 0);
+
+ len += b.doFinal(out, len);
+
+ if (!areEqual(outCBC2, out))
+ {
+ fail("no match on second nullCBC check");
+ }
+ }
+
+ private void testNullOFB()
+ throws InvalidCipherTextException
+ {
+ BufferedBlockCipher b = new BufferedBlockCipher(new OFBBlockCipher(new AESEngine(), 128));
+ KeyParameter kp = new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917"));
+
+ b.init(true, new ParametersWithIV(kp, new byte[16]));
+
+ byte[] out = new byte[b.getOutputSize(tData.length)];
+
+ int len = b.processBytes(tData, 0, tData.length, out, 0);
+
+ len += b.doFinal(out, len);
+
+ if (!areEqual(outOFB1, out))
+ {
+ fail("no match on first nullOFB check");
+ }
+
+ b.init(true, new ParametersWithIV(null, Hex.decode("000102030405060708090a0b0c0d0e0f")));
+
+ len = b.processBytes(tData, 0, tData.length, out, 0);
+
+ len += b.doFinal(out, len);
+
+ if (!areEqual(outOFB2, out))
+ {
+ fail("no match on second nullOFB check");
+ }
+ }
+
+ private void testNullCFB()
+ throws InvalidCipherTextException
+ {
+ BufferedBlockCipher b = new BufferedBlockCipher(new CFBBlockCipher(new AESEngine(), 128));
+ KeyParameter kp = new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917"));
+
+ b.init(true, new ParametersWithIV(kp, new byte[16]));
+
+ byte[] out = new byte[b.getOutputSize(tData.length)];
+
+ int len = b.processBytes(tData, 0, tData.length, out, 0);
+
+ len += b.doFinal(out, len);
+
+ if (!areEqual(outCFB1, out))
+ {
+ fail("no match on first nullCFB check");
+ }
+
+ b.init(true, new ParametersWithIV(null, Hex.decode("000102030405060708090a0b0c0d0e0f")));
+
+ len = b.processBytes(tData, 0, tData.length, out, 0);
+
+ len += b.doFinal(out, len);
+
+ if (!areEqual(outCFB2, out))
+ {
+ fail("no match on second nullCFB check");
+ }
+ }
+
+ private boolean areEqual(byte[] a, int aOff, byte[] b, int bOff)
+ {
+ for (int i = bOff; i != b.length; i++)
+ {
+ if (a[aOff + i - bOff] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private void skipTest()
+ {
+ CipherParameters params = new ParametersWithIV(new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")), Hex.decode("00000000000000000000000000000000"));
+ SICBlockCipher engine = new SICBlockCipher(new AESEngine());
+
+ engine.init(true, params);
+
+ SecureRandom rand = new SecureRandom();
+ byte[] plain = new byte[5000];
+ byte[] cipher = new byte[5000];
+
+ rand.nextBytes(plain);
+ engine.processBytes(plain, 0, plain.length, cipher, 0);
+
+ byte[] fragment = new byte[20];
+
+ engine.init(true, params);
+
+ engine.skip(10);
+
+ if (engine.getPosition() != 10)
+ {
+ fail("skip position incorrect - 10 got " + engine.getPosition());
+ }
+
+ engine.processBytes(plain, 10, fragment.length, fragment, 0);
+
+ if (!areEqual(cipher, 10, fragment, 0))
+ {
+ fail("skip forward 10 failed");
+ }
+
+ engine.skip(1000);
+
+ if (engine.getPosition() != 1010 + fragment.length)
+ {
+ fail("skip position incorrect - " + (1010 + fragment.length) + " got " + engine.getPosition());
+ }
+
+ engine.processBytes(plain, 1010 + fragment.length, fragment.length, fragment, 0);
+
+ if (!areEqual(cipher, 1010 + fragment.length, fragment, 0))
+ {
+ fail("skip forward 1000 failed");
+ }
+
+ engine.skip(-10);
+
+ if (engine.getPosition() != 1010 + 2 * fragment.length - 10)
+ {
+ fail("skip position incorrect - " + (1010 + 2 * fragment.length - 10) + " got " + engine.getPosition());
+ }
+
+ engine.processBytes(plain, 1010 + 2 * fragment.length - 10, fragment.length, fragment, 0);
+
+ if (!areEqual(cipher, 1010 + 2 * fragment.length - 10, fragment, 0))
+ {
+ fail("skip back 10 failed");
+ }
+
+ engine.skip(-1000);
+
+ if (engine.getPosition() != 60)
+ {
+ fail("skip position incorrect - " + 60 + " got " + engine.getPosition());
+ }
+
+ engine.processBytes(plain, 60, fragment.length, fragment, 0);
+
+ if (!areEqual(cipher, 60, fragment, 0))
+ {
+ fail("skip back 1000 failed");
+ }
+
+ long pos = engine.seekTo(1010);
+
+ if (pos != 1010)
+ {
+ fail("position incorrect - " + 1010 + " got " + pos);
+ }
+
+ engine.processBytes(plain, 1010, fragment.length, fragment, 0);
+
+ if (!areEqual(cipher, 1010, fragment, 0))
+ {
+ fail("seek to 1010 failed");
+ }
+
+ engine.reset();
+
+ for (int i = 0; i != 1000; i++)
+ {
+ engine.skip(i);
+
+ if (engine.getPosition() != i)
+ {
+ fail("skip forward at wrong position");
+ }
+
+ engine.processBytes(plain, i, fragment.length, fragment, 0);
+
+ if (!areEqual(cipher, i, fragment, 0))
+ {
+ fail("skip forward i failed: " + i);
+ }
+
+ if (engine.getPosition() != i + fragment.length)
+ {
+ fail("cipher at wrong position: " + engine.getPosition() + " [" + i + "]");
+ }
+
+ engine.skip(-fragment.length);
+
+ if (engine.getPosition() != i)
+ {
+ fail("skip back at wrong position");
+ }
+
+ engine.processBytes(plain, i, fragment.length, fragment, 0);
+
+ if (!areEqual(cipher, i, fragment, 0))
+ {
+ fail("skip back i failed: " + i);
+ }
+
+ engine.reset();
+ }
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ super.performTest();
+
+ byte[] keyBytes = new byte[16];
+
+ _engine.init(true, new KeyParameter(keyBytes));
+
+ //
+ // init tests
+ //
+ try
+ {
+ byte[] dudKey = new byte[6];
+
+ _engine.init(true, new KeyParameter(dudKey));
+
+ fail("failed key length check");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ byte[] iv = new byte[16];
+
+ _engine.init(true, new ParametersWithIV(null, iv));
+
+ fail("failed parameter check");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ testNullCBC();
+ testNullSIC();
+ testNullOFB();
+ testNullCFB();
+
+ skipTest();
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new AESTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/AESVectorFileTest.java b/core/src/test/java/org/spongycastle/crypto/test/AESVectorFileTest.java
new file mode 100644
index 00000000..504b4bd4
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/AESVectorFileTest.java
@@ -0,0 +1,258 @@
+package org.spongycastle.crypto.test;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.engines.AESEngine;
+import org.spongycastle.crypto.engines.AESFastEngine;
+import org.spongycastle.crypto.engines.AESLightEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+/**
+ * Test vectors from the NIST standard tests and Brian Gladman's vector set
+ * <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">
+ * http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
+ */
+public class AESVectorFileTest
+ implements Test
+{
+
+ private int countOfTests = 0;
+ private int testNum = 0;
+
+ protected BlockCipher createNewEngineForTest()
+ {
+ return new AESEngine();
+ }
+
+ private Test[] readTestVectors(InputStream inStream)
+ {
+ // initialize key, plaintext, ciphertext = null
+ // read until find BLOCKSIZE=
+ // return if not 128
+ // read KEYSIZE= or ignore
+ // loop
+ // read a line
+ // if starts with BLOCKSIZE=
+ // parse the rest. return if not 128
+ // if starts with KEY=
+ // parse the rest and set KEY
+ // if starts with PT=
+ // parse the rest and set plaintext
+ // if starts with CT=
+ // parse the rest and set ciphertext
+ // if starts with TEST= or end of file
+ // if key, plaintext, ciphertext are all not null
+ // save away their values as the next test
+ // until end of file
+ List tests = new ArrayList();
+ String key = null;
+ String plaintext = null;
+ String ciphertext = null;
+
+ BufferedReader in = new BufferedReader(new InputStreamReader(inStream));
+
+ try
+ {
+ String line = in.readLine();
+
+ while (line != null)
+ {
+ line = line.trim().toLowerCase();
+ if (line.startsWith("blocksize="))
+ {
+ int i = 0;
+ try
+ {
+ i = Integer.parseInt(line.substring(10).trim());
+ }
+ catch (Exception e)
+ {
+ }
+ if (i != 128)
+ {
+ return null;
+ }
+ }
+ else if (line.startsWith("keysize="))
+ {
+ int i = 0;
+ try
+ {
+ i = Integer.parseInt(line.substring(10).trim());
+ }
+ catch (Exception e)
+ {
+ }
+ if ((i != 128) && (i != 192) && (i != 256))
+ {
+ return null;
+ }
+ }
+ else if (line.startsWith("key="))
+ {
+ key = line.substring(4).trim();
+ }
+ else if (line.startsWith("pt="))
+ {
+ plaintext = line.substring(3).trim();
+ }
+ else if (line.startsWith("ct="))
+ {
+ ciphertext = line.substring(3).trim();
+ }
+ else if (line.startsWith("test="))
+ {
+ if ((key != null) && (plaintext != null)
+ && (ciphertext != null))
+ {
+ tests.add(new BlockCipherVectorTest(testNum++,
+ createNewEngineForTest(), new KeyParameter(Hex
+ .decode(key)), plaintext, ciphertext));
+ }
+ }
+
+ line = in.readLine();
+ }
+ try
+ {
+ in.close();
+ }
+ catch (IOException e)
+ {
+ }
+ }
+ catch (IOException e)
+ {
+ }
+ if ((key != null) && (plaintext != null) && (ciphertext != null))
+ {
+ tests.add(new BlockCipherVectorTest(testNum++,
+ createNewEngineForTest(),
+ new KeyParameter(Hex.decode(key)), plaintext, ciphertext));
+ }
+ return (Test[])(tests.toArray(new Test[tests.size()]));
+ }
+
+ public String getName()
+ {
+ return "AES";
+ }
+
+ private TestResult performTestsFromZipFile(File zfile)
+ {
+ try
+ {
+ ZipFile inZip = new ZipFile(zfile);
+ for (Enumeration files = inZip.entries(); files.hasMoreElements();)
+ {
+ Test[] tests = null;
+ try
+ {
+ tests = readTestVectors(inZip
+ .getInputStream((ZipEntry)(files.nextElement())));
+ }
+ catch (Exception e)
+ {
+ return new SimpleTestResult(false, getName() + ": threw "
+ + e);
+ }
+ if (tests != null)
+ {
+ for (int i = 0; i != tests.length; i++)
+ {
+ TestResult res = tests[i].perform();
+ countOfTests++;
+
+ if (!res.isSuccessful())
+ {
+ return res;
+ }
+ }
+ }
+ }
+ inZip.close();
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+ catch (Exception e)
+ {
+ return new SimpleTestResult(false, getName() + ": threw " + e);
+ }
+ }
+
+ private static final String[] zipFileNames = { "rijn.tv.ecbnk.zip",
+ "rijn.tv.ecbnt.zip", "rijn.tv.ecbvk.zip", "rijn.tv.ecbvt.zip" };
+
+ public TestResult perform()
+ {
+ countOfTests = 0;
+ for (int i = 0; i < zipFileNames.length; i++)
+ {
+ File inf = new File(zipFileNames[i]);
+ TestResult res = performTestsFromZipFile(inf);
+ if (!res.isSuccessful())
+ {
+ return res;
+ }
+ }
+ return new SimpleTestResult(true, getName() + ": " + countOfTests
+ + " performed Okay");
+ }
+
+ public static void main(String[] args)
+ {
+ AESVectorFileTest test = new AESVectorFileTest();
+ TestResult result = test.perform();
+ System.out.println(result);
+
+ test = new AESLightVectorFileTest();
+ result = test.perform();
+ System.out.println(result);
+
+ test = new AESFastVectorFileTest();
+ result = test.perform();
+ System.out.println(result);
+
+ }
+
+ private static class AESLightVectorFileTest extends AESVectorFileTest
+ {
+ protected BlockCipher createNewEngineForTest()
+ {
+ return new AESLightEngine();
+ }
+
+ public String getName()
+ {
+ return "AESLight";
+ }
+
+ }
+
+ private static class AESFastVectorFileTest extends AESVectorFileTest
+ {
+ protected BlockCipher createNewEngineForTest()
+ {
+ return new AESFastEngine();
+ }
+
+ public String getName()
+ {
+ return "AESFast";
+ }
+
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/AESWrapPadTest.java b/core/src/test/java/org/spongycastle/crypto/test/AESWrapPadTest.java
new file mode 100644
index 00000000..992c4468
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/AESWrapPadTest.java
@@ -0,0 +1,146 @@
+package org.spongycastle.crypto.test;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.Wrapper;
+import org.spongycastle.crypto.engines.AESWrapPadEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * This is a test harness I use because I cannot modify the BC test harness without
+ * invalidating the signature on their signed provider library. The code here is not
+ * high quality but it does test the RFC vectors as well as randomly generated values.
+ * The RFC test vectors are tested by making sure both the ciphertext and decrypted
+ * values match the expected values whereas the random values are just checked to make
+ * sure that:
+ * <p>unwrap(wrap(random_value, random_kek), random_kek) == random_value.</p>
+ */
+
+public class AESWrapPadTest
+ extends SimpleTest
+{
+
+ private final int numOfRandomIterations = 100;
+
+ public AESWrapPadTest()
+ {
+
+ }
+
+ private void wrapAndUnwrap(byte[] kek, byte[] key, byte[] expected)
+ throws Exception
+ {
+ Wrapper wrapper = new AESWrapPadEngine();
+
+ wrapper.init(true, new KeyParameter(kek));
+
+ byte[] cipherText = wrapper.wrap(key, 0, key.length);
+ if (!areEqual(cipherText, expected))
+ {
+ fail("Wrapped value does not match expected.");
+ }
+ wrapper.init(false, new KeyParameter(kek));
+ byte[] plainText = wrapper.unwrap(cipherText, 0, cipherText.length);
+
+ if (!areEqual(key, plainText))
+ {
+ fail("Unwrapped value does not match original.");
+ }
+ }
+
+ private void wrapAndUnwrap(byte[] kek, byte[] key)
+ throws Exception
+ {
+ Wrapper wrapper = new AESWrapPadEngine();
+
+ wrapper.init(true, new KeyParameter(kek));
+
+ byte[] cipherText = wrapper.wrap(key, 0, key.length);
+
+ wrapper.init(false, new KeyParameter(kek));
+ byte[] plainText = wrapper.unwrap(cipherText, 0, cipherText.length);
+
+ if (!areEqual(key, plainText))
+ {
+ fail("Unwrapped value does not match original.");
+ }
+ }
+
+ public String getName()
+ {
+ return "AESWrapPad";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ // test RFC 5649 test vectors
+ byte[] kek = Hex.decode("5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8");
+ byte[] key = Hex.decode("c37b7e6492584340bed12207808941155068f738");
+ byte[] wrap = Hex.decode("138bdeaa9b8fa7fc61f97742e72248ee5ae6ae5360d1ae6a5f54f373fa543b6a");
+
+ wrapAndUnwrap(kek, key, wrap);
+
+ wrap = Hex.decode("afbeb0f07dfbf5419200f2ccb50bb24f");
+ key = Hex.decode("466f7250617369");
+ wrapAndUnwrap(kek, key, wrap);
+
+
+ //
+ // offset test
+ //
+ Wrapper wrapper = new AESWrapPadEngine();
+
+ byte[] pText = new byte[5 + key.length];
+ byte[] cText;
+
+ System.arraycopy(key, 0, pText, 5, key.length);
+
+ wrapper.init(true, new KeyParameter(kek));
+
+ cText = wrapper.wrap(pText, 5, key.length);
+ if (!Arrays.areEqual(cText, wrap))
+ {
+ fail("failed offset wrap test expected " + new String(Hex.encode(wrap)) + " got " + new String(Hex.encode(cText)));
+ }
+
+ wrapper.init(false, new KeyParameter(kek));
+
+ cText = new byte[6 + wrap.length];
+ System.arraycopy(wrap, 0, cText, 6, wrap.length);
+
+ pText = wrapper.unwrap(cText, 6, wrap.length);
+ if (!Arrays.areEqual(pText, key))
+ {
+ fail("failed offset unwrap test expected " + new String(Hex.encode(key)) + " got " + new String(Hex.encode(pText)));
+ }
+
+ // test random values
+ SecureRandom rnd = new SecureRandom();
+ for (int i = 0; i < numOfRandomIterations; i++)
+ {
+ int kekLength = 128;
+ boolean shouldIncrease = (rnd.nextInt() & 0x01) != 0;
+ if (shouldIncrease)
+ {
+ kekLength = 256;
+ }
+ kek = new byte[kekLength / 8];
+ rnd.nextBytes(kek);
+ int keyToWrapSize = rnd.nextInt(256 / 8 - 8) + 8;
+ byte[] keyToWrap = new byte[keyToWrapSize];
+ rnd.nextBytes(keyToWrap);
+ wrapAndUnwrap(kek, keyToWrap);
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new AESWrapPadTest());
+ }
+}
+
diff --git a/core/src/test/java/org/spongycastle/crypto/test/AESWrapTest.java b/core/src/test/java/org/spongycastle/crypto/test/AESWrapTest.java
new file mode 100644
index 00000000..38f4af70
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/AESWrapTest.java
@@ -0,0 +1,238 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.Wrapper;
+import org.spongycastle.crypto.engines.AESWrapEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+/**
+ * Wrap Test
+ */
+public class AESWrapTest
+ implements Test
+{
+ public String getName()
+ {
+ return "AESWrap";
+ }
+
+ private TestResult wrapTest(
+ int id,
+ byte[] kek,
+ byte[] in,
+ byte[] out)
+ {
+ Wrapper wrapper = new AESWrapEngine();
+
+ wrapper.init(true, new KeyParameter(kek));
+
+ try
+ {
+ byte[] cText = wrapper.wrap(in, 0, in.length);
+ if (!Arrays.areEqual(cText, out))
+ {
+ return new SimpleTestResult(false, getName() + ": failed wrap test " + id + " expected " + new String(Hex.encode(out)) + " got " + new String(Hex.encode(cText)));
+ }
+ }
+ catch (Exception e)
+ {
+ return new SimpleTestResult(false, getName() + ": failed wrap test exception " + e.toString());
+ }
+
+ wrapper.init(false, new KeyParameter(kek));
+
+ try
+ {
+ byte[] pText = wrapper.unwrap(out, 0, out.length);
+ if (!Arrays.areEqual(pText, in))
+ {
+ return new SimpleTestResult(false, getName() + ": failed unwrap test " + id + " expected " + new String(Hex.encode(in)) + " got " + new String(Hex.encode(pText)));
+ }
+ }
+ catch (Exception e)
+ {
+ return new SimpleTestResult(false, getName() + ": failed unwrap test exception.", e);
+ }
+
+ //
+ // offset test
+ //
+ byte[] pText = new byte[5 + in.length];
+ byte[] cText;
+
+ System.arraycopy(in, 0, pText, 5, in.length);
+
+ wrapper.init(true, new KeyParameter(kek));
+
+ try
+ {
+ cText = wrapper.wrap(pText, 5, in.length);
+ if (!Arrays.areEqual(cText, out))
+ {
+ return new SimpleTestResult(false, getName() + ": failed wrap test " + id + " expected " + new String(Hex.encode(out)) + " got " + new String(Hex.encode(cText)));
+ }
+ }
+ catch (Exception e)
+ {
+ return new SimpleTestResult(false, getName() + ": failed wrap test exception " + e.toString());
+ }
+
+ wrapper.init(false, new KeyParameter(kek));
+
+ cText = new byte[6 + out.length];
+ System.arraycopy(out, 0, cText, 6, out.length);
+
+ try
+ {
+ pText = wrapper.unwrap(cText, 6, out.length);
+ if (!Arrays.areEqual(pText, in))
+ {
+ return new SimpleTestResult(false, getName() + ": failed unwrap test " + id + " expected " + new String(Hex.encode(in)) + " got " + new String(Hex.encode(pText)));
+ }
+ }
+ catch (Exception e)
+ {
+ return new SimpleTestResult(false, getName() + ": failed unwrap test exception.", e);
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+
+ public TestResult perform()
+ {
+ byte[] kek1 = Hex.decode("000102030405060708090a0b0c0d0e0f");
+ byte[] in1 = Hex.decode("00112233445566778899aabbccddeeff");
+ byte[] out1 = Hex.decode("1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5");
+ TestResult result = wrapTest(1, kek1, in1, out1);
+
+ if (!result.isSuccessful())
+ {
+ return result;
+ }
+
+ byte[] kek2 = Hex.decode("000102030405060708090a0b0c0d0e0f1011121314151617");
+ byte[] in2 = Hex.decode("00112233445566778899aabbccddeeff");
+ byte[] out2 = Hex.decode("96778b25ae6ca435f92b5b97c050aed2468ab8a17ad84e5d");
+ result = wrapTest(2, kek2, in2, out2);
+ if (!result.isSuccessful())
+ {
+ return result;
+ }
+
+ byte[] kek3 = Hex.decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
+ byte[] in3 = Hex.decode("00112233445566778899aabbccddeeff");
+ byte[] out3 = Hex.decode("64e8c3f9ce0f5ba263e9777905818a2a93c8191e7d6e8ae7");
+ result = wrapTest(3, kek3, in3, out3);
+ if (!result.isSuccessful())
+ {
+ return result;
+ }
+
+ byte[] kek4 = Hex.decode("000102030405060708090a0b0c0d0e0f1011121314151617");
+ byte[] in4 = Hex.decode("00112233445566778899aabbccddeeff0001020304050607");
+ byte[] out4 = Hex.decode("031d33264e15d33268f24ec260743edce1c6c7ddee725a936ba814915c6762d2");
+ result = wrapTest(4, kek4, in4, out4);
+ if (!result.isSuccessful())
+ {
+ return result;
+ }
+
+ byte[] kek5 = Hex.decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
+ byte[] in5 = Hex.decode("00112233445566778899aabbccddeeff0001020304050607");
+ byte[] out5 = Hex.decode("a8f9bc1612c68b3ff6e6f4fbe30e71e4769c8b80a32cb8958cd5d17d6b254da1");
+ result = wrapTest(5, kek5, in5, out5);
+ if (!result.isSuccessful())
+ {
+ return result;
+ }
+
+ byte[] kek6 = Hex.decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
+ byte[] in6 = Hex.decode("00112233445566778899aabbccddeeff000102030405060708090a0b0c0d0e0f");
+ byte[] out6 = Hex.decode("28c9f404c4b810f4cbccb35cfb87f8263f5786e2d80ed326cbc7f0e71a99f43bfb988b9b7a02dd21");
+ result = wrapTest(6, kek6, in6, out6);
+ if (!result.isSuccessful())
+ {
+ return result;
+ }
+
+ Wrapper wrapper = new AESWrapEngine();
+ KeyParameter key = new KeyParameter(new byte[16]);
+ byte[] buf = new byte[16];
+
+ try
+ {
+ wrapper.init(true, key);
+
+ wrapper.unwrap(buf, 0, buf.length);
+
+ return new SimpleTestResult(false, getName() + ": failed unwrap state test.");
+ }
+ catch (IllegalStateException e)
+ {
+ // expected
+ }
+ catch (InvalidCipherTextException e)
+ {
+ return new SimpleTestResult(false, getName() + ": unexpected exception: " + e, e);
+ }
+
+ try
+ {
+ wrapper.init(false, key);
+
+ wrapper.wrap(buf, 0, buf.length);
+
+ return new SimpleTestResult(false, getName() + ": failed unwrap state test.");
+ }
+ catch (IllegalStateException e)
+ {
+ // expected
+ }
+
+ //
+ // short test
+ //
+ try
+ {
+ wrapper.init(false, key);
+
+ wrapper.unwrap(buf, 0, buf.length / 2);
+
+ return new SimpleTestResult(false, getName() + ": failed unwrap short test.");
+ }
+ catch (InvalidCipherTextException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ wrapper.init(true, key);
+
+ wrapper.wrap(buf, 0, 15);
+
+ return new SimpleTestResult(false, getName() + ": failed wrap length test.");
+ }
+ catch (DataLengthException e)
+ {
+ // expected
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+
+ public static void main(
+ String[] args)
+ {
+ AESWrapTest test = new AESWrapTest();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/AllTests.java b/core/src/test/java/org/spongycastle/crypto/test/AllTests.java
new file mode 100644
index 00000000..edc7b1b2
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/AllTests.java
@@ -0,0 +1,41 @@
+package org.spongycastle.crypto.test;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.spongycastle.util.test.SimpleTestResult;
+
+public class AllTests
+ extends TestCase
+{
+ public void testCrypto()
+ {
+ org.spongycastle.util.test.Test[] tests = RegressionTest.tests;
+
+ for (int i = 0; i != tests.length; i++)
+ {
+ SimpleTestResult result = (SimpleTestResult)tests[i].perform();
+
+ if (!result.isSuccessful())
+ {
+ fail(result.toString());
+ }
+ }
+ }
+
+ public static void main (String[] args)
+ {
+ junit.textui.TestRunner.run(suite());
+ }
+
+ public static Test suite()
+ {
+ TestSuite suite = new TestSuite("Lightweight Crypto Tests");
+
+ suite.addTestSuite(AllTests.class);
+ suite.addTestSuite(GCMReorderTest.class);
+
+ return suite;
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/BlockCipherMonteCarloTest.java b/core/src/test/java/org/spongycastle/crypto/test/BlockCipherMonteCarloTest.java
new file mode 100644
index 00000000..0b08d461
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/BlockCipherMonteCarloTest.java
@@ -0,0 +1,82 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.BufferedBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * a basic test that takes a cipher, key parameter, and an input
+ * and output string. This test wraps the engine in a buffered block
+ * cipher with padding disabled.
+ */
+public class BlockCipherMonteCarloTest
+ extends SimpleTest
+{
+ int id;
+ int iterations;
+ BlockCipher engine;
+ CipherParameters param;
+ byte[] input;
+ byte[] output;
+
+ public BlockCipherMonteCarloTest(
+ int id,
+ int iterations,
+ BlockCipher engine,
+ CipherParameters param,
+ String input,
+ String output)
+ {
+ this.id = id;
+ this.iterations = iterations;
+ this.engine = engine;
+ this.param = param;
+ this.input = Hex.decode(input);
+ this.output = Hex.decode(output);
+ }
+
+ public String getName()
+ {
+ return engine.getAlgorithmName() + " Monte Carlo Test " + id;
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ BufferedBlockCipher cipher = new BufferedBlockCipher(engine);
+
+ cipher.init(true, param);
+
+ byte[] out = new byte[input.length];
+
+ System.arraycopy(input, 0, out, 0, out.length);
+
+ for (int i = 0; i != iterations; i++)
+ {
+ int len1 = cipher.processBytes(out, 0, out.length, out, 0);
+
+ cipher.doFinal(out, len1);
+ }
+
+ if (!areEqual(out, output))
+ {
+ fail("failed - " + "expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
+ }
+
+ cipher.init(false, param);
+
+ for (int i = 0; i != iterations; i++)
+ {
+ int len1 = cipher.processBytes(out, 0, out.length, out, 0);
+
+ cipher.doFinal(out, len1);
+ }
+
+ if (!areEqual(input, out))
+ {
+ fail("failed reversal");
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/BlockCipherResetTest.java b/core/src/test/java/org/spongycastle/crypto/test/BlockCipherResetTest.java
new file mode 100644
index 00000000..9e95cfd8
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/BlockCipherResetTest.java
@@ -0,0 +1,206 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.engines.AESEngine;
+import org.spongycastle.crypto.engines.AESFastEngine;
+import org.spongycastle.crypto.engines.AESLightEngine;
+import org.spongycastle.crypto.engines.BlowfishEngine;
+import org.spongycastle.crypto.engines.CAST5Engine;
+import org.spongycastle.crypto.engines.CAST6Engine;
+import org.spongycastle.crypto.engines.DESEngine;
+import org.spongycastle.crypto.engines.DESedeEngine;
+import org.spongycastle.crypto.engines.NoekeonEngine;
+import org.spongycastle.crypto.engines.RC6Engine;
+import org.spongycastle.crypto.engines.SEEDEngine;
+import org.spongycastle.crypto.engines.SerpentEngine;
+import org.spongycastle.crypto.engines.TEAEngine;
+import org.spongycastle.crypto.engines.TwofishEngine;
+import org.spongycastle.crypto.engines.XTEAEngine;
+import org.spongycastle.crypto.modes.CBCBlockCipher;
+import org.spongycastle.crypto.modes.CFBBlockCipher;
+import org.spongycastle.crypto.modes.GOFBBlockCipher;
+import org.spongycastle.crypto.modes.OFBBlockCipher;
+import org.spongycastle.crypto.modes.OpenPGPCFBBlockCipher;
+import org.spongycastle.crypto.modes.PGPCFBBlockCipher;
+import org.spongycastle.crypto.modes.SICBlockCipher;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * Test whether block ciphers implement reset contract on init, encrypt/decrypt and reset.
+ */
+public class BlockCipherResetTest
+ extends SimpleTest
+{
+
+ public String getName()
+ {
+ return "Block Cipher Reset";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ // 128 bit block ciphers
+ testReset("AESFastEngine", new AESFastEngine(), new AESFastEngine(), new KeyParameter(new byte[16]));
+ testReset("AESEngine", new AESEngine(), new AESEngine(), new KeyParameter(new byte[16]));
+ testReset("AESLightEngine", new AESLightEngine(), new AESLightEngine(), new KeyParameter(new byte[16]));
+ testReset("Twofish", new TwofishEngine(), new TwofishEngine(), new KeyParameter(new byte[16]));
+ testReset("NoekeonEngine", new NoekeonEngine(), new NoekeonEngine(), new KeyParameter(new byte[16]));
+ testReset("SerpentEngine", new SerpentEngine(), new SerpentEngine(), new KeyParameter(new byte[16]));
+ testReset("SEEDEngine", new SEEDEngine(), new SEEDEngine(), new KeyParameter(new byte[16]));
+ testReset("CAST6Engine", new CAST6Engine(), new CAST6Engine(), new KeyParameter(new byte[16]));
+ testReset("RC6Engine", new RC6Engine(), new RC6Engine(), new KeyParameter(new byte[16]));
+
+ // 64 bit block ciphers
+ testReset("DESEngine", new DESEngine(), new DESEngine(), new KeyParameter(new byte[8]));
+ testReset("BlowfishEngine", new BlowfishEngine(), new BlowfishEngine(), new KeyParameter(new byte[8]));
+ testReset("CAST5Engine", new CAST5Engine(), new CAST5Engine(), new KeyParameter(new byte[8]));
+ testReset("DESedeEngine", new DESedeEngine(), new DESedeEngine(), new KeyParameter(new byte[24]));
+ testReset("TEAEngine", new TEAEngine(), new TEAEngine(), new KeyParameter(new byte[16]));
+ testReset("XTEAEngine", new XTEAEngine(), new XTEAEngine(), new KeyParameter(new byte[16]));
+
+ // primitive block cipher modes (don't reset on processBlock)
+ testModeReset("AES/CBC", new CBCBlockCipher(new AESEngine()), new CBCBlockCipher(new AESEngine()),
+ new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]));
+ testModeReset("AES/SIC", new SICBlockCipher(new AESEngine()), new SICBlockCipher(new AESEngine()),
+ new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]));
+ testModeReset("AES/CFB", new CFBBlockCipher(new AESEngine(), 128), new CFBBlockCipher(new AESEngine(), 128),
+ new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]));
+ testModeReset("AES/OFB", new OFBBlockCipher(new AESEngine(), 128), new OFBBlockCipher(new AESEngine(), 128),
+ new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]));
+ testModeReset("AES/GCTR", new GOFBBlockCipher(new DESEngine()), new GOFBBlockCipher(new DESEngine()),
+ new ParametersWithIV(new KeyParameter(new byte[8]), new byte[8]));
+ testModeReset("AES/OpenPGPCFB", new OpenPGPCFBBlockCipher(new AESEngine()), new OpenPGPCFBBlockCipher(
+ new AESEngine()), new KeyParameter(new byte[16]));
+ testModeReset("AES/PGPCFB", new PGPCFBBlockCipher(new AESEngine(), false), new PGPCFBBlockCipher(
+ new AESEngine(), false), new KeyParameter(new byte[16]));
+
+ // PGPCFB with IV is broken (it's also not a PRP, so probably shouldn't be a BlockCipher)
+ // testModeReset("AES/PGPCFBwithIV", new PGPCFBBlockCipher(new AESEngine(), true), new
+ // PGPCFBBlockCipher(
+ // new AESEngine(), true), new ParametersWithIV(new KeyParameter(new byte[16]), new
+ // byte[16]));
+ // testModeReset("AES/PGPCFBwithIV_NoIV", new PGPCFBBlockCipher(new AESEngine(), true), new
+ // PGPCFBBlockCipher(
+ // new AESEngine(), true), new KeyParameter(new byte[16]));
+
+ }
+
+ private void testModeReset(String test, BlockCipher cipher1, BlockCipher cipher2, CipherParameters params)
+ throws InvalidCipherTextException
+ {
+ testReset(test, false, cipher1, cipher2, params);
+ }
+
+ private void testReset(String test, BlockCipher cipher1, BlockCipher cipher2, CipherParameters params)
+ throws InvalidCipherTextException
+ {
+ testReset(test, true, cipher1, cipher2, params);
+ }
+
+ private void testReset(String test,
+ boolean testCryptReset,
+ BlockCipher cipher1,
+ BlockCipher cipher2,
+ CipherParameters params)
+ throws InvalidCipherTextException
+ {
+ cipher1.init(true, params);
+
+ byte[] plaintext = new byte[cipher1.getBlockSize()];
+ byte[] ciphertext = new byte[(cipher1.getAlgorithmName().indexOf("PGPCFBwithIV")) > -1 ? 2 * cipher1.getBlockSize() + 2
+ : cipher1.getBlockSize()];
+
+ // Establish baseline answer
+ crypt(cipher1, true, plaintext, ciphertext);
+
+ // Test encryption resets
+ checkReset(test, testCryptReset, cipher1, params, true, plaintext, ciphertext);
+
+ // Test decryption resets with fresh instance
+ cipher2.init(false, params);
+ checkReset(test, testCryptReset, cipher2, params, false, ciphertext, plaintext);
+ }
+
+ private void checkReset(String test,
+ boolean testCryptReset,
+ BlockCipher cipher,
+ CipherParameters params,
+ boolean encrypt,
+ byte[] pretext,
+ byte[] posttext)
+ throws InvalidCipherTextException
+ {
+ // Do initial run
+ byte[] output = new byte[posttext.length];
+ crypt(cipher, encrypt, pretext, output);
+
+ // Check encrypt resets cipher
+ if (testCryptReset)
+ {
+ crypt(cipher, encrypt, pretext, output);
+ if (!Arrays.areEqual(output, posttext))
+ {
+ fail(test + (encrypt ? " encrypt" : " decrypt") + " did not reset cipher.");
+ }
+ }
+
+ // Check init resets data
+ cipher.processBlock(pretext, 0, output, 0);
+ cipher.init(encrypt, params);
+
+ try
+ {
+ crypt(cipher, encrypt, pretext, output);
+ }
+ catch (DataLengthException e)
+ {
+ fail(test + " init did not reset data.");
+ }
+ if (!Arrays.areEqual(output, posttext))
+ {
+ fail(test + " init did not reset data.", new String(Hex.encode(posttext)), new String(Hex.encode(output)));
+ }
+
+ // Check reset resets data
+ cipher.processBlock(pretext, 0, output, 0);
+ cipher.reset();
+
+ try
+ {
+ crypt(cipher, encrypt, pretext, output);
+ }
+ catch (DataLengthException e)
+ {
+ fail(test + " reset did not reset data.");
+ }
+ if (!Arrays.areEqual(output, posttext))
+ {
+ fail(test + " reset did not reset data.");
+ }
+ }
+
+ private static void crypt(BlockCipher cipher1, boolean encrypt, byte[] plaintext, byte[] output)
+ throws InvalidCipherTextException
+ {
+ cipher1.processBlock(plaintext, 0, output, 0);
+ if ((cipher1.getAlgorithmName().indexOf("PGPCFBwithIV") > -1) && !encrypt)
+ {
+ // Process past IV in first block
+ cipher1.processBlock(plaintext, cipher1.getBlockSize(), output, 0);
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new BlockCipherResetTest());
+ }
+
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/BlockCipherVectorTest.java b/core/src/test/java/org/spongycastle/crypto/test/BlockCipherVectorTest.java
new file mode 100644
index 00000000..322a580d
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/BlockCipherVectorTest.java
@@ -0,0 +1,71 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.BufferedBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * a basic test that takes a cipher, key parameter, and an input
+ * and output string. This test wraps the engine in a buffered block
+ * cipher with padding disabled.
+ */
+public class BlockCipherVectorTest
+ extends SimpleTest
+{
+ int id;
+ BlockCipher engine;
+ CipherParameters param;
+ byte[] input;
+ byte[] output;
+
+ public BlockCipherVectorTest(
+ int id,
+ BlockCipher engine,
+ CipherParameters param,
+ String input,
+ String output)
+ {
+ this.id = id;
+ this.engine = engine;
+ this.param = param;
+ this.input = Hex.decode(input);
+ this.output = Hex.decode(output);
+ }
+
+ public String getName()
+ {
+ return engine.getAlgorithmName() + " Vector Test " + id;
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ BufferedBlockCipher cipher = new BufferedBlockCipher(engine);
+
+ cipher.init(true, param);
+
+ byte[] out = new byte[input.length];
+
+ int len1 = cipher.processBytes(input, 0, input.length, out, 0);
+
+ cipher.doFinal(out, len1);
+
+ if (!areEqual(out, output))
+ {
+ fail("failed - " + "expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
+ }
+
+ cipher.init(false, param);
+
+ int len2 = cipher.processBytes(output, 0, output.length, out, 0);
+
+ cipher.doFinal(out, len2);
+
+ if (!areEqual(input, out))
+ {
+ fail("failed reversal got " + new String(Hex.encode(out)));
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/BlowfishTest.java b/core/src/test/java/org/spongycastle/crypto/test/BlowfishTest.java
new file mode 100644
index 00000000..57e38a3e
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/BlowfishTest.java
@@ -0,0 +1,57 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.engines.BlowfishEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * blowfish tester - vectors from http://www.counterpane.com/vectors.txt
+ */
+public class BlowfishTest
+ extends CipherTest
+{
+ static SimpleTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new BlowfishEngine(),
+ new KeyParameter(Hex.decode("0000000000000000")),
+ "0000000000000000", "4EF997456198DD78"),
+ new BlockCipherVectorTest(1, new BlowfishEngine(),
+ new KeyParameter(Hex.decode("FFFFFFFFFFFFFFFF")),
+ "FFFFFFFFFFFFFFFF", "51866FD5B85ECB8A"),
+ new BlockCipherVectorTest(2, new BlowfishEngine(),
+ new KeyParameter(Hex.decode("3000000000000000")),
+ "1000000000000001", "7D856F9A613063F2"),
+ new BlockCipherVectorTest(3, new BlowfishEngine(),
+ new KeyParameter(Hex.decode("1111111111111111")),
+ "1111111111111111", "2466DD878B963C9D"),
+ new BlockCipherVectorTest(4, new BlowfishEngine(),
+ new KeyParameter(Hex.decode("0123456789ABCDEF")),
+ "1111111111111111", "61F9C3802281B096"),
+ new BlockCipherVectorTest(5, new BlowfishEngine(),
+ new KeyParameter(Hex.decode("FEDCBA9876543210")),
+ "0123456789ABCDEF", "0ACEAB0FC6A0A28D"),
+ new BlockCipherVectorTest(6, new BlowfishEngine(),
+ new KeyParameter(Hex.decode("7CA110454A1A6E57")),
+ "01A1D6D039776742", "59C68245EB05282B"),
+ new BlockCipherVectorTest(7, new BlowfishEngine(),
+ new KeyParameter(Hex.decode("0131D9619DC1376E")),
+ "5CD54CA83DEF57DA", "B1B8CC0B250F09A0"),
+ };
+
+ BlowfishTest()
+ {
+ super(tests, new BlowfishEngine(), new KeyParameter(new byte[16]));
+ }
+
+ public String getName()
+ {
+ return "Blowfish";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new BlowfishTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/CAST5Test.java b/core/src/test/java/org/spongycastle/crypto/test/CAST5Test.java
new file mode 100644
index 00000000..339edd48
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/CAST5Test.java
@@ -0,0 +1,44 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.engines.CAST5Engine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * cast tester - vectors from http://www.ietf.org/rfc/rfc2144.txt
+ */
+public class CAST5Test
+ extends CipherTest
+{
+ static SimpleTest[] tests = {
+ new BlockCipherVectorTest(0, new CAST5Engine(),
+ new KeyParameter(Hex.decode("0123456712345678234567893456789A")),
+ "0123456789ABCDEF",
+ "238B4FE5847E44B2"),
+ new BlockCipherVectorTest(0, new CAST5Engine(),
+ new KeyParameter(Hex.decode("01234567123456782345")),
+ "0123456789ABCDEF",
+ "EB6A711A2C02271B"),
+ new BlockCipherVectorTest(0, new CAST5Engine(),
+ new KeyParameter(Hex.decode("0123456712")),
+ "0123456789ABCDEF",
+ "7Ac816d16E9B302E"),
+ };
+
+ CAST5Test()
+ {
+ super(tests, new CAST5Engine(), new KeyParameter(new byte[16]));
+ }
+
+ public String getName()
+ {
+ return "CAST5";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new CAST5Test());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/CAST6Test.java b/core/src/test/java/org/spongycastle/crypto/test/CAST6Test.java
new file mode 100644
index 00000000..bd62fd2b
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/CAST6Test.java
@@ -0,0 +1,44 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.engines.CAST6Engine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * cast6 tester - vectors from http://www.ietf.org/rfc/rfc2612.txt
+ */
+public class CAST6Test
+ extends CipherTest
+{
+ static SimpleTest[] tests = {
+ new BlockCipherVectorTest(0, new CAST6Engine(),
+ new KeyParameter(Hex.decode("2342bb9efa38542c0af75647f29f615d")),
+ "00000000000000000000000000000000",
+ "c842a08972b43d20836c91d1b7530f6b"),
+ new BlockCipherVectorTest(0, new CAST6Engine(),
+ new KeyParameter(Hex.decode("2342bb9efa38542cbed0ac83940ac298bac77a7717942863")),
+ "00000000000000000000000000000000",
+ "1b386c0210dcadcbdd0e41aa08a7a7e8"),
+ new BlockCipherVectorTest(0, new CAST6Engine(),
+ new KeyParameter(Hex.decode("2342bb9efa38542cbed0ac83940ac2988d7c47ce264908461cc1b5137ae6b604")),
+ "00000000000000000000000000000000",
+ "4f6a2038286897b9c9870136553317fa")
+ };
+
+ CAST6Test()
+ {
+ super(tests, new CAST6Engine(), new KeyParameter(new byte[16]));
+ }
+
+ public String getName()
+ {
+ return "CAST6";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new CAST6Test());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/CCMTest.java b/core/src/test/java/org/spongycastle/crypto/test/CCMTest.java
new file mode 100644
index 00000000..92c22cd1
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/CCMTest.java
@@ -0,0 +1,305 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.engines.AESEngine;
+import org.spongycastle.crypto.engines.DESEngine;
+import org.spongycastle.crypto.modes.CCMBlockCipher;
+import org.spongycastle.crypto.params.AEADParameters;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Strings;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * First four test vectors from
+ * NIST Special Publication 800-38C.
+ */
+public class CCMTest
+ extends SimpleTest
+{
+ private byte[] K1 = Hex.decode("404142434445464748494a4b4c4d4e4f");
+ private byte[] N1 = Hex.decode("10111213141516");
+ private byte[] A1 = Hex.decode("0001020304050607");
+ private byte[] P1 = Hex.decode("20212223");
+ private byte[] C1 = Hex.decode("7162015b4dac255d");
+ private byte[] T1 = Hex.decode("6084341b");
+
+ private byte[] K2 = Hex.decode("404142434445464748494a4b4c4d4e4f");
+ private byte[] N2 = Hex.decode("1011121314151617");
+ private byte[] A2 = Hex.decode("000102030405060708090a0b0c0d0e0f");
+ private byte[] P2 = Hex.decode("202122232425262728292a2b2c2d2e2f");
+ private byte[] C2 = Hex.decode("d2a1f0e051ea5f62081a7792073d593d1fc64fbfaccd");
+ private byte[] T2 = Hex.decode("7f479ffca464");
+
+ private byte[] K3 = Hex.decode("404142434445464748494a4b4c4d4e4f");
+ private byte[] N3 = Hex.decode("101112131415161718191a1b");
+ private byte[] A3 = Hex.decode("000102030405060708090a0b0c0d0e0f10111213");
+ private byte[] P3 = Hex.decode("202122232425262728292a2b2c2d2e2f3031323334353637");
+ private byte[] C3 = Hex.decode("e3b201a9f5b71a7a9b1ceaeccd97e70b6176aad9a4428aa5484392fbc1b09951");
+ private byte[] T3 = Hex.decode("67c99240c7d51048");
+
+ private byte[] K4 = Hex.decode("404142434445464748494a4b4c4d4e4f");
+ private byte[] N4 = Hex.decode("101112131415161718191a1b1c");
+ private byte[] A4 = Hex.decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
+ private byte[] P4 = Hex.decode("202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f");
+ private byte[] C4 = Hex.decode("69915dad1e84c6376a68c2967e4dab615ae0fd1faec44cc484828529463ccf72b4ac6bec93e8598e7f0dadbcea5b");
+ private byte[] T4 = Hex.decode("f4dd5d0ee404617225ffe34fce91");
+
+ //
+ // long data vector
+ //
+ private byte[] C5 = Hex.decode("49b17d8d3ea4e6174a48e2b65e6d8b417ac0dd3f8ee46ce4a4a2a509661cef52528c1cd9805333a5cfd482fa3f095a3c2fdd1cc47771c5e55fddd60b5c8d6d3fa5c8dd79d08b16242b6642106e7c0c28bd1064b31e6d7c9800c8397dbc3fa8071e6a38278b386c18d65d39c6ad1ef9501a5c8f68d38eb6474799f3cc898b4b9b97e87f9c95ce5c51bc9d758f17119586663a5684e0a0daf6520ec572b87473eb141d10471e4799ded9e607655402eca5176bbf792ef39dd135ac8d710da8e9e854fd3b95c681023f36b5ebe2fb213d0b62dd6e9e3cfe190b792ccb20c53423b2dca128f861a61d306910e1af418839467e466f0ec361d2539eedd99d4724f1b51c07beb40e875a87491ec8b27cd1");
+ private byte[] T5 = Hex.decode("5c768856796b627b13ec8641581b");
+
+ public void performTest()
+ throws Exception
+ {
+ CCMBlockCipher ccm = new CCMBlockCipher(new AESEngine());
+
+ checkVectors(0, ccm, K1, 32, N1, A1, P1, T1, C1);
+ checkVectors(1, ccm, K2, 48, N2, A2, P2, T2, C2);
+ checkVectors(2, ccm, K3, 64, N3, A3, P3, T3, C3);
+
+ ivParamTest(0, ccm, K1, N1);
+
+ //
+ // 4 has a reduced associated text which needs to be replicated
+ //
+ byte[] a4 = new byte[65536]; // 524288 / 8
+
+ for (int i = 0; i < a4.length; i += A4.length)
+ {
+ System.arraycopy(A4, 0, a4, i, A4.length);
+ }
+
+ checkVectors(3, ccm, K4, 112, N4, a4, P4, T4, C4);
+
+ //
+ // long data test
+ //
+ checkVectors(4, ccm, K4, 112, N4, A4, A4, T5, C5);
+
+ // decryption with output specified, non-zero offset.
+ ccm.init(false, new AEADParameters(new KeyParameter(K2), 48, N2, A2));
+
+ byte[] inBuf = new byte[C2.length + 10];
+ byte[] outBuf = new byte[ccm.getOutputSize(C2.length) + 10];
+
+ System.arraycopy(C2, 0, inBuf, 10, C2.length);
+
+ int len = ccm.processPacket(inBuf, 10, C2.length, outBuf, 10);
+ byte[] out = ccm.processPacket(C2, 0, C2.length);
+
+ if (len != out.length || !isEqual(out, outBuf, 10))
+ {
+ fail("decryption output incorrect");
+ }
+
+ // encryption with output specified, non-zero offset.
+ ccm.init(true, new AEADParameters(new KeyParameter(K2), 48, N2, A2));
+
+ int inLen = len;
+ inBuf = outBuf;
+ outBuf = new byte[ccm.getOutputSize(inLen) + 10];
+
+ len = ccm.processPacket(inBuf, 10, inLen, outBuf, 10);
+ out = ccm.processPacket(inBuf, 10, inLen);
+
+ if (len != out.length || !isEqual(out, outBuf, 10))
+ {
+ fail("encryption output incorrect");
+ }
+
+ //
+ // exception tests
+ //
+
+ try
+ {
+ ccm.init(false, new AEADParameters(new KeyParameter(K1), 32, N2, A2));
+
+ ccm.processPacket(C2, 0, C2.length);
+
+ fail("invalid cipher text not picked up");
+ }
+ catch (InvalidCipherTextException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ ccm = new CCMBlockCipher(new DESEngine());
+
+ fail("incorrect block size not picked up");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ ccm.init(false, new KeyParameter(K1));
+
+ fail("illegal argument not picked up");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ AEADTestUtil.testReset(this, new CCMBlockCipher(new AESEngine()), new CCMBlockCipher(new AESEngine()), new AEADParameters(new KeyParameter(K1), 32, N2));
+ AEADTestUtil.testTampering(this, ccm, new AEADParameters(new KeyParameter(K1), 32, N2));
+ AEADTestUtil.testOutputSizes(this, new CCMBlockCipher(new AESEngine()), new AEADParameters(
+ new KeyParameter(K1), 32, N2));
+ AEADTestUtil.testBufferSizeChecks(this, new CCMBlockCipher(new AESEngine()), new AEADParameters(
+ new KeyParameter(K1), 32, N2));
+ }
+
+ private boolean isEqual(byte[] exp, byte[] other, int off)
+ {
+ for (int i = 0; i != exp.length; i++)
+ {
+ if (exp[i] != other[off + i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private void checkVectors(
+ int count,
+ CCMBlockCipher ccm,
+ byte[] k,
+ int macSize,
+ byte[] n,
+ byte[] a,
+ byte[] p,
+ byte[] t,
+ byte[] c)
+ throws InvalidCipherTextException
+ {
+ byte[] fa = new byte[a.length / 2];
+ byte[] la = new byte[a.length - (a.length / 2)];
+ System.arraycopy(a, 0, fa, 0, fa.length);
+ System.arraycopy(a, fa.length, la, 0, la.length);
+
+ checkVectors(count, ccm, "all initial associated data", k, macSize, n, a, null, p, t, c);
+ checkVectors(count, ccm, "subsequent associated data", k, macSize, n, null, a, p, t, c);
+ checkVectors(count, ccm, "split associated data", k, macSize, n, fa, la, p, t, c);
+ checkVectors(count, ccm, "reuse key", null, macSize, n, fa, la, p, t, c);
+ }
+
+ private void checkVectors(
+ int count,
+ CCMBlockCipher ccm,
+ String additionalDataType,
+ byte[] k,
+ int macSize,
+ byte[] n,
+ byte[] a,
+ byte[] sa,
+ byte[] p,
+ byte[] t,
+ byte[] c)
+ throws InvalidCipherTextException
+ {
+ KeyParameter keyParam = (k == null) ? null : new KeyParameter(k);
+
+ ccm.init(true, new AEADParameters(keyParam, macSize, n, a));
+
+ byte[] enc = new byte[c.length];
+
+ if (sa != null)
+ {
+ ccm.processAADBytes(sa, 0, sa.length);
+ }
+
+ int len = ccm.processBytes(p, 0, p.length, enc, 0);
+
+ len += ccm.doFinal(enc, len);
+
+ if (!areEqual(c, enc))
+ {
+ fail("encrypted stream fails to match in test " + count + " with " + additionalDataType);
+ }
+
+ ccm.init(false, new AEADParameters(keyParam, macSize, n, a));
+
+ byte[] tmp = new byte[enc.length];
+
+ if (sa != null)
+ {
+ ccm.processAADBytes(sa, 0, sa.length);
+ }
+
+ len = ccm.processBytes(enc, 0, enc.length, tmp, 0);
+
+ len += ccm.doFinal(tmp, len);
+
+ byte[] dec = new byte[len];
+
+ System.arraycopy(tmp, 0, dec, 0, len);
+
+ if (!areEqual(p, dec))
+ {
+ fail("decrypted stream fails to match in test " + count + " with " + additionalDataType,
+ new String(Hex.encode(p)), new String(Hex.encode(dec)));
+ }
+
+ if (!areEqual(t, ccm.getMac()))
+ {
+ fail("MAC fails to match in test " + count + " with " + additionalDataType);
+ }
+ }
+
+ private void ivParamTest(
+ int count,
+ CCMBlockCipher ccm,
+ byte[] k,
+ byte[] n)
+ throws InvalidCipherTextException
+ {
+ byte[] p = Strings.toByteArray("hello world!!");
+
+ ccm.init(true, new ParametersWithIV(new KeyParameter(k), n));
+
+ byte[] enc = new byte[p.length + 8];
+
+ int len = ccm.processBytes(p, 0, p.length, enc, 0);
+
+ len += ccm.doFinal(enc, len);
+
+ ccm.init(false, new ParametersWithIV(new KeyParameter(k), n));
+
+ byte[] tmp = new byte[enc.length];
+
+ len = ccm.processBytes(enc, 0, enc.length, tmp, 0);
+
+ len += ccm.doFinal(tmp, len);
+
+ byte[] dec = new byte[len];
+
+ System.arraycopy(tmp, 0, dec, 0, len);
+
+ if (!areEqual(p, dec))
+ {
+ fail("decrypted stream fails to match in test " + count);
+ }
+ }
+
+ public String getName()
+ {
+ return "CCM";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new CCMTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/CMacTest.java b/core/src/test/java/org/spongycastle/crypto/test/CMacTest.java
new file mode 100644
index 00000000..a55ad1d2
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/CMacTest.java
@@ -0,0 +1,321 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.engines.AESEngine;
+import org.spongycastle.crypto.engines.AESFastEngine;
+import org.spongycastle.crypto.macs.CMac;
+import org.spongycastle.crypto.macs.CMacWithIV;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * CMAC tester - <a href="http://www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/tv/omac1-tv.txt">Official Test Vectors</a>.
+ */
+public class CMacTest
+ extends SimpleTest
+{
+ private static final byte[] keyBytes128 = Hex.decode("2b7e151628aed2a6abf7158809cf4f3c");
+ private static final byte[] keyBytes192 = Hex.decode(
+ "8e73b0f7da0e6452c810f32b809079e5"
+ + "62f8ead2522c6b7b");
+ private static final byte[] keyBytes256 = Hex.decode(
+ "603deb1015ca71be2b73aef0857d7781"
+ + "1f352c073b6108d72d9810a30914dff4");
+
+ private static final byte[] input0 = Hex.decode("");
+ private static final byte[] input16 = Hex.decode("6bc1bee22e409f96e93d7e117393172a");
+ private static final byte[] input40 = Hex.decode(
+ "6bc1bee22e409f96e93d7e117393172a"
+ + "ae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411");
+ private static final byte[] input64 = Hex.decode(
+ "6bc1bee22e409f96e93d7e117393172a"
+ + "ae2d8a571e03ac9c9eb76fac45af8e51"
+ + "30c81c46a35ce411e5fbc1191a0a52ef"
+ + "f69f2445df4f9b17ad2b417be66c3710");
+
+ private static final byte[] output_k128_m0 = Hex.decode("bb1d6929e95937287fa37d129b756746");
+ private static final byte[] output_k128_m16 = Hex.decode("070a16b46b4d4144f79bdd9dd04a287c");
+ private static final byte[] output_k128_m40 = Hex.decode("dfa66747de9ae63030ca32611497c827");
+ private static final byte[] output_k128_m64 = Hex.decode("51f0bebf7e3b9d92fc49741779363cfe");
+
+ private static final byte[] output_k192_m0 = Hex.decode("d17ddf46adaacde531cac483de7a9367");
+ private static final byte[] output_k192_m16 = Hex.decode("9e99a7bf31e710900662f65e617c5184");
+ private static final byte[] output_k192_m40 = Hex.decode("8a1de5be2eb31aad089a82e6ee908b0e");
+ private static final byte[] output_k192_m64 = Hex.decode("a1d5df0eed790f794d77589659f39a11");
+
+ private static final byte[] output_k256_m0 = Hex.decode("028962f61b7bf89efc6b551f4667d983");
+ private static final byte[] output_k256_m16 = Hex.decode("28a7023f452e8f82bd4bf28d8c37c35c");
+ private static final byte[] output_k256_m40 = Hex.decode("aaf3d8f1de5640c232f5b169b9c911e6");
+ private static final byte[] output_k256_m64 = Hex.decode("e1992190549f6ed5696a2c056c315410");
+
+ public CMacTest()
+ {
+ }
+
+ public void performTest()
+ {
+ BlockCipher cipher = new AESFastEngine();
+ Mac mac = new CMac(cipher, 128);
+
+ //128 bytes key
+
+ KeyParameter key = new KeyParameter(keyBytes128);
+
+ // 0 bytes message - 128 bytes key
+ mac.init(key);
+
+ mac.update(input0, 0, input0.length);
+
+ byte[] out = new byte[16];
+
+ mac.doFinal(out, 0);
+
+ if (!areEqual(out, output_k128_m0))
+ {
+ fail("Failed - expected " + new String(Hex.encode(output_k128_m0))
+ + " got " + new String(Hex.encode(out)));
+ }
+
+ // 16 bytes message - 128 bytes key
+ mac.init(key);
+
+ mac.update(input16, 0, input16.length);
+
+ out = new byte[16];
+
+ mac.doFinal(out, 0);
+
+ if (!areEqual(out, output_k128_m16))
+ {
+ fail("Failed - expected " + new String(Hex.encode(output_k128_m16))
+ + " got " + new String(Hex.encode(out)));
+ }
+
+ // 40 bytes message - 128 bytes key
+ mac.init(key);
+
+ mac.update(input40, 0, input40.length);
+
+ out = new byte[16];
+
+ mac.doFinal(out, 0);
+
+ if (!areEqual(out, output_k128_m40))
+ {
+ fail("Failed - expected " + new String(Hex.encode(output_k128_m40))
+ + " got " + new String(Hex.encode(out)));
+ }
+
+ // 64 bytes message - 128 bytes key
+ mac.init(key);
+
+ mac.update(input64, 0, input64.length);
+
+ out = new byte[16];
+
+ mac.doFinal(out, 0);
+
+ if (!areEqual(out, output_k128_m64))
+ {
+ fail("Failed - expected " + new String(Hex.encode(output_k128_m64))
+ + " got " + new String(Hex.encode(out)));
+ }
+
+ //192 bytes key
+
+ key = new KeyParameter(keyBytes192);
+
+ // 0 bytes message - 192 bytes key
+ mac.init(key);
+
+ mac.update(input0, 0, input0.length);
+
+ out = new byte[16];
+
+ mac.doFinal(out, 0);
+
+ if (!areEqual(out, output_k192_m0))
+ {
+ fail("Failed - expected " + new String(Hex.encode(output_k192_m0))
+ + " got " + new String(Hex.encode(out)));
+ }
+
+ // 16 bytes message - 192 bytes key
+ mac.init(key);
+
+ mac.update(input16, 0, input16.length);
+
+ out = new byte[16];
+
+ mac.doFinal(out, 0);
+
+ if (!areEqual(out, output_k192_m16))
+ {
+ fail("Failed - expected " + new String(Hex.encode(output_k192_m16))
+ + " got " + new String(Hex.encode(out)));
+ }
+
+ // 40 bytes message - 192 bytes key
+ mac.init(key);
+
+ mac.update(input40, 0, input40.length);
+
+ out = new byte[16];
+
+ mac.doFinal(out, 0);
+
+ if (!areEqual(out, output_k192_m40))
+ {
+ fail("Failed - expected " + new String(Hex.encode(output_k192_m40))
+ + " got " + new String(Hex.encode(out)));
+ }
+
+ // 64 bytes message - 192 bytes key
+ mac.init(key);
+
+ mac.update(input64, 0, input64.length);
+
+ out = new byte[16];
+
+ mac.doFinal(out, 0);
+
+ if (!areEqual(out, output_k192_m64))
+ {
+ fail("Failed - expected " + new String(Hex.encode(output_k192_m64))
+ + " got " + new String(Hex.encode(out)));
+ }
+
+ //256 bytes key
+
+ key = new KeyParameter(keyBytes256);
+
+ // 0 bytes message - 256 bytes key
+ mac.init(key);
+
+ mac.update(input0, 0, input0.length);
+
+ out = new byte[16];
+
+ mac.doFinal(out, 0);
+
+ if (!areEqual(out, output_k256_m0))
+ {
+ fail("Failed - expected " + new String(Hex.encode(output_k256_m0))
+ + " got " + new String(Hex.encode(out)));
+ }
+
+ // 16 bytes message - 256 bytes key
+ mac.init(key);
+
+ mac.update(input16, 0, input16.length);
+
+ out = new byte[16];
+
+ mac.doFinal(out, 0);
+
+ if (!areEqual(out, output_k256_m16))
+ {
+ fail("Failed - expected " + new String(Hex.encode(output_k256_m16))
+ + " got " + new String(Hex.encode(out)));
+ }
+
+ // 40 bytes message - 256 bytes key
+ mac.init(key);
+
+ mac.update(input40, 0, input40.length);
+
+ out = new byte[16];
+
+ mac.doFinal(out, 0);
+
+ if (!areEqual(out, output_k256_m40))
+ {
+ fail("Failed - expected " + new String(Hex.encode(output_k256_m40))
+ + " got " + new String(Hex.encode(out)));
+ }
+
+ // 64 bytes message - 256 bytes key
+ mac.init(key);
+
+ mac.update(input64, 0, input64.length);
+
+ out = new byte[16];
+
+ mac.doFinal(out, 0);
+
+ if (!areEqual(out, output_k256_m64))
+ {
+ fail("Failed - expected " + new String(Hex.encode(output_k256_m64))
+ + " got " + new String(Hex.encode(out)));
+ }
+
+ // CMAC with IV
+ // 16 bytes message - 256 bytes key
+ mac = new CMacWithIV(new AESFastEngine());
+
+ mac.init(key);
+
+ mac.update(input16, 0, input16.length);
+
+ out = new byte[16];
+
+ mac.doFinal(out, 0);
+
+ if (!areEqual(out, output_k256_m16))
+ {
+ fail("Failed - expected " + new String(Hex.encode(output_k256_m16))
+ + " got " + new String(Hex.encode(out)));
+ }
+
+ // CMAC with IV
+ // 16 bytes message - 256 bytes key
+ mac = new CMacWithIV(new AESFastEngine());
+
+ mac.init(new ParametersWithIV(key, Hex.decode("000102030405060708090a0b0c0d0e0f")));
+
+ mac.update(input16, 0, input16.length);
+
+ out = new byte[16];
+
+ mac.doFinal(out, 0);
+
+ if (areEqual(out, output_k256_m16))
+ {
+ fail("Failed - got " + new String(Hex.encode(output_k256_m16)));
+ }
+
+ if (!areEqual(out, Hex.decode("9347a60c64061b9ff2a92522ca8e08fc")))
+ {
+ fail("Failed - expected " + "9347a60c64061b9ff2a92522ca8e08fc"
+ + " got " + new String(Hex.encode(out)));
+ }
+
+ testExceptions();
+ }
+
+ private void testExceptions()
+ {
+ try
+ {
+ CMac mac = new CMac(new AESEngine());
+ mac.init(new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]));
+ fail("CMac does not accept IV");
+ } catch(IllegalArgumentException e)
+ {
+ // Expected
+ }
+ }
+
+ public String getName()
+ {
+ return "CMac";
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new CMacTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/CTSTest.java b/core/src/test/java/org/spongycastle/crypto/test/CTSTest.java
new file mode 100644
index 00000000..76846193
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/CTSTest.java
@@ -0,0 +1,212 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.BufferedBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.engines.AESEngine;
+import org.spongycastle.crypto.engines.DESEngine;
+import org.spongycastle.crypto.engines.SkipjackEngine;
+import org.spongycastle.crypto.modes.CBCBlockCipher;
+import org.spongycastle.crypto.modes.CTSBlockCipher;
+import org.spongycastle.crypto.modes.OldCTSBlockCipher;
+import org.spongycastle.crypto.modes.SICBlockCipher;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * CTS tester
+ */
+public class CTSTest
+ extends SimpleTest
+{
+ static byte[] in1 = Hex.decode("4e6f7720697320746865207420");
+ static byte[] in2 = Hex.decode("000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f0aaa");
+ static byte[] out1 = Hex.decode("9952f131588465033fa40e8a98");
+ static byte[] out2 = Hex.decode("358f84d01eb42988dc34efb994");
+ static byte[] out3 = Hex.decode("170171cfad3f04530c509b0c1f0be0aefbd45a8e3755a873bff5ea198504b71683c6");
+
+ private void testCTS(
+ int id,
+ BlockCipher cipher,
+ CipherParameters params,
+ byte[] input,
+ byte[] output)
+ throws Exception
+ {
+ byte[] out = new byte[input.length];
+ BufferedBlockCipher engine = new CTSBlockCipher(cipher);
+
+ engine.init(true, params);
+
+ int len = engine.processBytes(input, 0, input.length, out, 0);
+
+ engine.doFinal(out, len);
+
+ if (!areEqual(output, out))
+ {
+ fail("failed encryption expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
+ }
+
+ engine.init(false, params);
+
+ len = engine.processBytes(output, 0, output.length, out, 0);
+
+ engine.doFinal(out, len);
+
+ if (!areEqual(input, out))
+ {
+ fail("failed decryption expected " + new String(Hex.encode(input)) + " got " + new String(Hex.encode(out)));
+ }
+ }
+
+ private void testOldCTS(
+ int id,
+ BlockCipher cipher,
+ CipherParameters params,
+ byte[] input,
+ byte[] output)
+ throws Exception
+ {
+ byte[] out = new byte[input.length];
+ BufferedBlockCipher engine = new OldCTSBlockCipher(cipher);
+
+ engine.init(true, params);
+
+ int len = engine.processBytes(input, 0, input.length, out, 0);
+
+ engine.doFinal(out, len);
+
+ if (!areEqual(output, out))
+ {
+ fail("failed encryption expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
+ }
+
+ engine.init(false, params);
+
+ len = engine.processBytes(output, 0, output.length, out, 0);
+
+ engine.doFinal(out, len);
+
+ if (!areEqual(input, out))
+ {
+ fail("failed decryption expected " + new String(Hex.encode(input)) + " got " + new String(Hex.encode(out)));
+ }
+ }
+
+ private void testExceptions() throws InvalidCipherTextException
+ {
+ BufferedBlockCipher engine = new CTSBlockCipher(new DESEngine());
+ CipherParameters params = new KeyParameter(new byte[engine.getBlockSize()]);
+ engine.init(true, params);
+
+ byte[] out = new byte[engine.getOutputSize(engine.getBlockSize())];
+
+ engine.processBytes(new byte[engine.getBlockSize() - 1], 0, engine.getBlockSize() - 1, out, 0);
+ try
+ {
+ engine.doFinal(out, 0);
+ fail("Expected CTS encrypt error on < 1 block input");
+ } catch(DataLengthException e)
+ {
+ // Expected
+ }
+
+ engine.init(true, params);
+ engine.processBytes(new byte[engine.getBlockSize()], 0, engine.getBlockSize(), out, 0);
+ try
+ {
+ engine.doFinal(out, 0);
+ } catch(DataLengthException e)
+ {
+ fail("Unexpected CTS encrypt error on == 1 block input");
+ }
+
+ engine.init(false, params);
+ engine.processBytes(new byte[engine.getBlockSize() - 1], 0, engine.getBlockSize() - 1, out, 0);
+ try
+ {
+ engine.doFinal(out, 0);
+ fail("Expected CTS decrypt error on < 1 block input");
+ } catch(DataLengthException e)
+ {
+ // Expected
+ }
+
+ engine.init(false, params);
+ engine.processBytes(new byte[engine.getBlockSize()], 0, engine.getBlockSize(), out, 0);
+ try
+ {
+ engine.doFinal(out, 0);
+ } catch(DataLengthException e)
+ {
+ fail("Unexpected CTS decrypt error on == 1 block input");
+ }
+
+ try
+ {
+ new CTSBlockCipher(new SICBlockCipher(new AESEngine()));
+ fail("Expected CTS construction error - only ECB/CBC supported.");
+ } catch(IllegalArgumentException e)
+ {
+ // Expected
+ }
+
+ }
+
+ public String getName()
+ {
+ return "CTS";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ byte[] key1 = { (byte)0x01, (byte)0x23, (byte)0x45, (byte)0x67, (byte)0x89, (byte)0xAB, (byte)0xCD, (byte)0xEF };
+ byte[] key2 = { (byte)0x01, (byte)0x23, (byte)0x45, (byte)0x67, (byte)0x89, (byte)0xAB, (byte)0xCD, (byte)0xEF, (byte)0xee, (byte)0xff };
+ byte[] iv = { 1, 2, 3, 4, 5, 6, 7, 8 };
+
+ testCTS(1, new DESEngine(), new KeyParameter(key1), in1, out1);
+ testCTS(2, new CBCBlockCipher(new DESEngine()), new ParametersWithIV(new KeyParameter(key1), iv), in1, out2);
+ testCTS(3, new CBCBlockCipher(new SkipjackEngine()), new ParametersWithIV(new KeyParameter(key2), iv), in2, out3);
+
+ //
+ // test vectors from rfc3962
+ //
+ byte[] aes128 = Hex.decode("636869636b656e207465726979616b69");
+ byte[] aesIn1 = Hex.decode("4920776f756c64206c696b652074686520");
+ byte[] aesOut1 = Hex.decode("c6353568f2bf8cb4d8a580362da7ff7f97");
+ byte[] aesIn2 = Hex.decode("4920776f756c64206c696b65207468652047656e6572616c20476175277320");
+ byte[] aesOut2 = Hex.decode("fc00783e0efdb2c1d445d4c8eff7ed2297687268d6ecccc0c07b25e25ecfe5");
+ byte[] aesIn3 = Hex.decode("4920776f756c64206c696b65207468652047656e6572616c2047617527732043");
+ byte[] aesOut3 = Hex.decode("39312523a78662d5be7fcbcc98ebf5a897687268d6ecccc0c07b25e25ecfe584");
+
+ testCTS(4, new CBCBlockCipher(new AESEngine()), new ParametersWithIV(new KeyParameter(aes128), new byte[16]), aesIn1, aesOut1);
+ testCTS(5, new CBCBlockCipher(new AESEngine()), new ParametersWithIV(new KeyParameter(aes128), new byte[16]), aesIn2, aesOut2);
+ testCTS(6, new CBCBlockCipher(new AESEngine()), new ParametersWithIV(new KeyParameter(aes128), new byte[16]), aesIn3, aesOut3);
+
+ testOldCTS(4, new CBCBlockCipher(new AESEngine()), new ParametersWithIV(new KeyParameter(aes128), new byte[16]), aesIn1, aesOut1);
+ testOldCTS(5, new CBCBlockCipher(new AESEngine()), new ParametersWithIV(new KeyParameter(aes128), new byte[16]), aesIn2, aesOut2);
+ testOldCTS(6, new CBCBlockCipher(new AESEngine()), new ParametersWithIV(new KeyParameter(aes128), new byte[16]), aesIn3, aesOut3);
+
+ byte[] aes1Block = Hex.decode("4920776f756c64206c696b6520746865");
+ byte[] preErrata = Hex.decode("e7664c13ff28c965b0d2a0e7ec353706"); // CTS style one block
+ byte[] pstErrata = Hex.decode("97687268d6ecccc0c07b25e25ecfe584"); // CBC style one block
+ byte[] pstErrataNonZeroIV = Hex.decode("571f5108c53fe95ab52df783df933fa3");
+
+ testCTS(7, new CBCBlockCipher(new AESEngine()), new ParametersWithIV(new KeyParameter(aes128), new byte[16]), aes1Block, pstErrata);
+ testCTS(8, new CBCBlockCipher(new AESEngine()), new ParametersWithIV(new KeyParameter(aes128), aes1Block), aes1Block, pstErrataNonZeroIV);
+ testOldCTS(7, new CBCBlockCipher(new AESEngine()), new ParametersWithIV(new KeyParameter(aes128), new byte[16]), aes1Block, preErrata);
+
+ testExceptions();
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new CTSTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/CamelliaLightTest.java b/core/src/test/java/org/spongycastle/crypto/test/CamelliaLightTest.java
new file mode 100644
index 00000000..71a89fba
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/CamelliaLightTest.java
@@ -0,0 +1,66 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.engines.CamelliaLightEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * Camellia tester - vectors from https://www.cosic.esat.kuleuven.be/nessie/testvectors/ and RFC 3713
+ */
+public class CamelliaLightTest
+ extends CipherTest
+{
+ static SimpleTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new CamelliaLightEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000")),
+ "80000000000000000000000000000000", "07923A39EB0A817D1C4D87BDB82D1F1C"),
+ new BlockCipherVectorTest(1, new CamelliaLightEngine(),
+ new KeyParameter(Hex.decode("80000000000000000000000000000000")),
+ "00000000000000000000000000000000", "6C227F749319A3AA7DA235A9BBA05A2C"),
+ new BlockCipherVectorTest(2, new CamelliaLightEngine(),
+ new KeyParameter(Hex.decode("0123456789abcdeffedcba9876543210")),
+ "0123456789abcdeffedcba9876543210", "67673138549669730857065648eabe43"),
+ //
+ // 192 bit
+ //
+ new BlockCipherVectorTest(3, new CamelliaLightEngine(),
+ new KeyParameter(Hex.decode("0123456789abcdeffedcba98765432100011223344556677")),
+ "0123456789abcdeffedcba9876543210", "b4993401b3e996f84ee5cee7d79b09b9"),
+ new BlockCipherVectorTest(4, new CamelliaLightEngine(),
+ new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
+ "00040000000000000000000000000000", "9BCA6C88B928C1B0F57F99866583A9BC"),
+ new BlockCipherVectorTest(5, new CamelliaLightEngine(),
+ new KeyParameter(Hex.decode("949494949494949494949494949494949494949494949494")),
+ "636EB22D84B006381235641BCF0308D2", "94949494949494949494949494949494"),
+ //
+ // 256 bit
+ //
+ new BlockCipherVectorTest(6, new CamelliaLightEngine(),
+ new KeyParameter(Hex.decode("0123456789abcdeffedcba987654321000112233445566778899aabbccddeeff")),
+ "0123456789abcdeffedcba9876543210", "9acc237dff16d76c20ef7c919e3a7509"),
+ new BlockCipherVectorTest(7, new CamelliaLightEngine(),
+ new KeyParameter(Hex.decode("4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A")),
+ "057764FE3A500EDBD988C5C3B56CBA9A", "4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A"),
+ new BlockCipherVectorTest(8, new CamelliaLightEngine(),
+ new KeyParameter(Hex.decode("0303030303030303030303030303030303030303030303030303030303030303")),
+ "7968B08ABA92193F2295121EF8D75C8A", "03030303030303030303030303030303"),
+ };
+
+ CamelliaLightTest()
+ {
+ super(tests, new CamelliaLightEngine(), new KeyParameter(new byte[32]));
+ }
+
+ public String getName()
+ {
+ return "CamelliaLight";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new CamelliaLightTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/CamelliaTest.java b/core/src/test/java/org/spongycastle/crypto/test/CamelliaTest.java
new file mode 100644
index 00000000..a3d48193
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/CamelliaTest.java
@@ -0,0 +1,70 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.engines.CamelliaEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+import org.spongycastle.util.test.TestResult;
+
+/**
+ * Camellia tester - vectors from https://www.cosic.esat.kuleuven.be/nessie/testvectors/ and RFC 3713
+ */
+public class CamelliaTest
+ extends CipherTest
+{
+ static SimpleTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new CamelliaEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000")),
+ "80000000000000000000000000000000", "07923A39EB0A817D1C4D87BDB82D1F1C"),
+ new BlockCipherVectorTest(1, new CamelliaEngine(),
+ new KeyParameter(Hex.decode("80000000000000000000000000000000")),
+ "00000000000000000000000000000000", "6C227F749319A3AA7DA235A9BBA05A2C"),
+ new BlockCipherVectorTest(2, new CamelliaEngine(),
+ new KeyParameter(Hex.decode("0123456789abcdeffedcba9876543210")),
+ "0123456789abcdeffedcba9876543210", "67673138549669730857065648eabe43"),
+ //
+ // 192 bit
+ //
+ new BlockCipherVectorTest(3, new CamelliaEngine(),
+ new KeyParameter(Hex.decode("0123456789abcdeffedcba98765432100011223344556677")),
+ "0123456789abcdeffedcba9876543210", "b4993401b3e996f84ee5cee7d79b09b9"),
+ new BlockCipherVectorTest(4, new CamelliaEngine(),
+ new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
+ "00040000000000000000000000000000", "9BCA6C88B928C1B0F57F99866583A9BC"),
+ new BlockCipherVectorTest(5, new CamelliaEngine(),
+ new KeyParameter(Hex.decode("949494949494949494949494949494949494949494949494")),
+ "636EB22D84B006381235641BCF0308D2", "94949494949494949494949494949494"),
+ //
+ // 256 bit
+ //
+ new BlockCipherVectorTest(6, new CamelliaEngine(),
+ new KeyParameter(Hex.decode("0123456789abcdeffedcba987654321000112233445566778899aabbccddeeff")),
+ "0123456789abcdeffedcba9876543210", "9acc237dff16d76c20ef7c919e3a7509"),
+ new BlockCipherVectorTest(7, new CamelliaEngine(),
+ new KeyParameter(Hex.decode("4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A")),
+ "057764FE3A500EDBD988C5C3B56CBA9A", "4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A"),
+ new BlockCipherVectorTest(8, new CamelliaEngine(),
+ new KeyParameter(Hex.decode("0303030303030303030303030303030303030303030303030303030303030303")),
+ "7968B08ABA92193F2295121EF8D75C8A", "03030303030303030303030303030303"),
+ };
+
+ CamelliaTest()
+ {
+ super(tests, new CamelliaEngine(), new KeyParameter(new byte[32]));
+ }
+
+ public String getName()
+ {
+ return "Camellia";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ CamelliaTest test = new CamelliaTest();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/ChaChaTest.java b/core/src/test/java/org/spongycastle/crypto/test/ChaChaTest.java
new file mode 100644
index 00000000..21f24bf9
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/ChaChaTest.java
@@ -0,0 +1,403 @@
+package org.spongycastle.crypto.test;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.StreamCipher;
+import org.spongycastle.crypto.engines.ChaChaEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * ChaCha Test
+ * <p>
+ * Test cases generated using ref version of ChaCha20 in estreambench-20080905.
+ */
+public class ChaChaTest
+ extends SimpleTest
+{
+ byte[] zeroes = Hex.decode(
+ "00000000000000000000000000000000"
+ + "00000000000000000000000000000000"
+ + "00000000000000000000000000000000"
+ + "00000000000000000000000000000000");
+
+ String set1v0_0 = "FBB87FBB8395E05DAA3B1D683C422046"
+ + "F913985C2AD9B23CFC06C1D8D04FF213"
+ + "D44A7A7CDB84929F915420A8A3DC58BF"
+ + "0F7ECB4B1F167BB1A5E6153FDAF4493D";
+
+ String set1v0_192 = "D9485D55B8B82D792ED1EEA8E93E9BC1"
+ + "E2834AD0D9B11F3477F6E106A2F6A5F2"
+ + "EA8244D5B925B8050EAB038F58D4DF57"
+ + "7FAFD1B89359DAE508B2B10CBD6B488E";
+
+ String set1v0_256 = "08661A35D6F02D3D9ACA8087F421F7C8"
+ + "A42579047D6955D937925BA21396DDD4"
+ + "74B1FC4ACCDCAA33025B4BCE817A4FBF"
+ + "3E5D07D151D7E6FE04934ED466BA4779";
+
+ String set1v0_448 = "A7E16DD38BA48CCB130E5BE9740CE359"
+ + "D631E91600F85C8A5D0785A612D1D987"
+ + "90780ACDDC26B69AB106CCF6D866411D"
+ + "10637483DBF08CC5591FD8B3C87A3AE0";
+
+ String set1v9_0 = "A276339F99316A913885A0A4BE870F06"
+ + "91E72B00F1B3F2239F714FE81E88E00C"
+ + "BBE52B4EBBE1EA15894E29658C4CB145"
+ + "E6F89EE4ABB045A78514482CE75AFB7C";
+
+ String set1v9_192 = "0DFB9BD4F87F68DE54FBC1C6428FDEB0"
+ + "63E997BE8490C9B7A4694025D6EBA2B1"
+ + "5FE429DB82A7CAE6AAB22918E8D00449"
+ + "6FB6291467B5AE81D4E85E81D8795EBB";
+
+ String set1v9_256 = "546F5BB315E7F71A46E56D4580F90889"
+ + "639A2BA528F757CF3B048738BA141AF3"
+ + "B31607CB21561BAD94721048930364F4"
+ + "B1227CFEB7CDECBA881FB44903550E68";
+
+ String set1v9_448 = "6F813586E76691305A0CF048C0D8586D"
+ + "C89460207D8B230CD172398AA33D19E9"
+ + "2D24883C3A9B0BB7CD8C6B2668DB142E"
+ + "37A97948A7A01498A21110297984CD20";
+
+ String set6v0_0 = "57459975BC46799394788DE80B928387"
+ + "862985A269B9E8E77801DE9D874B3F51"
+ + "AC4610B9F9BEE8CF8CACD8B5AD0BF17D"
+ + "3DDF23FD7424887EB3F81405BD498CC3";
+
+ String set6v0_65472 = "EF9AEC58ACE7DB427DF012B2B91A0C1E"
+ + "8E4759DCE9CDB00A2BD59207357BA06C"
+ + "E02D327C7719E83D6348A6104B081DB0"
+ + "3908E5186986AE41E3AE95298BB7B713";
+
+ String set6v0_65536 = "17EF5FF454D85ABBBA280F3A94F1D26E"
+ + "950C7D5B05C4BB3A78326E0DC5731F83"
+ + "84205C32DB867D1B476CE121A0D7074B"
+ + "AA7EE90525D15300F48EC0A6624BD0AF";
+
+ String set6v1_0 = "92A2508E2C4084567195F2A1005E552B"
+ + "4874EC0504A9CD5E4DAF739AB553D2E7"
+ + "83D79C5BA11E0653BEBB5C116651302E"
+ + "8D381CB728CA627B0B246E83942A2B99";
+
+ String set6v1_65472 = "E1974EC3063F7BD0CBA58B1CE34BC874"
+ + "67AAF5759B05EA46682A5D4306E5A76B"
+ + "D99A448DB8DE73AF97A73F5FBAE2C776"
+ + "35040464524CF14D7F08D4CE1220FD84";
+
+ String set6v1_65536 = "BE3436141CFD62D12FF7D852F80C1344"
+ + "81F152AD0235ECF8CA172C55CA8C031B"
+ + "2E785D773A988CA8D4BDA6FAE0E493AA"
+ + "71DCCC4C894D1F106CAC62A9FC0A9607";
+
+ // ChaCha12
+ String chacha12_set1v0_0 = "36CF0D56E9F7FBF287BC5460D95FBA94"
+ + "AA6CBF17D74E7C784DDCF7E0E882DDAE"
+ + "3B5A58243EF32B79A04575A8E2C2B73D"
+ + "C64A52AA15B9F88305A8F0CA0B5A1A25";
+
+ String chacha12_set1v0_192 = "83496792AB68FEC75ADB16D3044420A4"
+ + "A00A6E9ADC41C3A63DBBF317A8258C85"
+ + "A9BC08B4F76B413A4837324AEDF8BC2A"
+ + "67D53C9AB9E1C5BC5F379D48DF9AF730";
+
+ String chacha12_set1v0_256 = "BAA28ED593690FD760ADA07C95E3B888"
+ + "4B4B64E488CA7A2D9BDC262243AB9251"
+ + "394C5037E255F8BCCDCD31306C508FFB"
+ + "C9E0161380F7911FCB137D46D9269250";
+
+ String chacha12_set1v0_448 = "B7ECFB6AE0B51915762FE1FD03A14D0C"
+ + "9E54DA5DC76EB16EBA5313BC535DE63D"
+ + "C72D7F9F1874E301E99C8531819F4E37"
+ + "75793F6A5D19C717FA5C78A39EB804A6";
+
+ // ChaCha8
+ String chacha8_set1v0_0 = "BEB1E81E0F747E43EE51922B3E87FB38"
+ + "D0163907B4ED49336032AB78B67C2457"
+ + "9FE28F751BD3703E51D876C017FAA435"
+ + "89E63593E03355A7D57B2366F30047C5";
+
+ String chacha8_set1v0_192 = "33B8B7CA8F8E89F0095ACE75A379C651"
+ + "FD6BDD55703C90672E44C6BAB6AACDD8"
+ + "7C976A87FD264B906E749429284134C2"
+ + "38E3B88CF74A68245B860D119A8BDF43";
+
+ String chacha8_set1v0_256 = "F7CA95BF08688BD3BE8A27724210F9DC"
+ + "16F32AF974FBFB09E9F757C577A245AB"
+ + "F35F824B70A4C02CB4A8D7191FA8A5AD"
+ + "6A84568743844703D353B7F00A8601F4";
+
+ String chacha8_set1v0_448 = "7B4117E8BFFD595CD8482270B08920FB"
+ + "C9B97794E1809E07BB271BF07C861003"
+ + "4C38DBA6ECA04E5474F399A284CBF6E2"
+ + "7F70142E604D0977797DE5B58B6B25E0";
+
+
+
+ public String getName()
+ {
+ return "ChaCha";
+ }
+
+ public void performTest()
+ {
+ chachaTest1(20, new ParametersWithIV(new KeyParameter(Hex.decode("80000000000000000000000000000000")), Hex.decode("0000000000000000")),
+ set1v0_0, set1v0_192, set1v0_256, set1v0_448);
+ chachaTest1(20, new ParametersWithIV(new KeyParameter(Hex.decode("00400000000000000000000000000000")), Hex.decode("0000000000000000")),
+ set1v9_0, set1v9_192, set1v9_256, set1v9_448);
+ chachaTest1(12, new ParametersWithIV(new KeyParameter(Hex.decode("80000000000000000000000000000000")), Hex.decode("0000000000000000")),
+ chacha12_set1v0_0, chacha12_set1v0_192, chacha12_set1v0_256, chacha12_set1v0_448);
+ chachaTest1(8, new ParametersWithIV(new KeyParameter(Hex.decode("80000000000000000000000000000000")), Hex.decode("0000000000000000")),
+ chacha8_set1v0_0, chacha8_set1v0_192, chacha8_set1v0_256, chacha8_set1v0_448);
+ chachaTest2(new ParametersWithIV(new KeyParameter(Hex.decode("0053A6F94C9FF24598EB3E91E4378ADD3083D6297CCF2275C81B6EC11467BA0D")), Hex.decode("0D74DB42A91077DE")),
+ set6v0_0, set6v0_65472, set6v0_65536);
+ chachaTest2(new ParametersWithIV(new KeyParameter(Hex.decode("0558ABFE51A4F74A9DF04396E93C8FE23588DB2E81D4277ACD2073C6196CBF12")), Hex.decode("167DE44BB21980E7")),
+ set6v1_0, set6v1_65472, set6v1_65536);
+ reinitBug();
+ skipTest();
+ }
+
+ private void chachaTest1(int rounds, CipherParameters params, String v0, String v192, String v256, String v448)
+ {
+ StreamCipher chaCha = new ChaChaEngine(rounds);
+ byte[] buf = new byte[64];
+
+ chaCha.init(true, params);
+
+ for (int i = 0; i != 7; i++)
+ {
+ chaCha.processBytes(zeroes, 0, 64, buf, 0);
+ switch (i)
+ {
+ case 0:
+ if (!areEqual(buf, Hex.decode(v0)))
+ {
+ mismatch("v0/" + rounds, v0, buf);
+ }
+ break;
+ case 3:
+ if (!areEqual(buf, Hex.decode(v192)))
+ {
+ mismatch("v192/" + rounds, v192, buf);
+ }
+ break;
+ case 4:
+ if (!areEqual(buf, Hex.decode(v256)))
+ {
+ mismatch("v256/" + rounds, v256, buf);
+ }
+ break;
+ default:
+ // ignore
+ }
+ }
+
+ for (int i = 0; i != 64; i++)
+ {
+ buf[i] = chaCha.returnByte(zeroes[i]);
+ }
+
+ if (!areEqual(buf, Hex.decode(v448)))
+ {
+ mismatch("v448", v448, buf);
+ }
+ }
+
+ private void chachaTest2(CipherParameters params, String v0, String v65472, String v65536)
+ {
+ StreamCipher chaCha = new ChaChaEngine();
+ byte[] buf = new byte[64];
+
+ chaCha.init(true, params);
+
+ for (int i = 0; i != 1025; i++)
+ {
+ chaCha.processBytes(zeroes, 0, 64, buf, 0);
+ switch (i)
+ {
+ case 0:
+ if (!areEqual(buf, Hex.decode(v0)))
+ {
+ mismatch("v0", v0, buf);
+ }
+ break;
+ case 1023:
+ if (!areEqual(buf, Hex.decode(v65472)))
+ {
+ mismatch("v65472", v65472, buf);
+ }
+ break;
+ case 1024:
+ if (!areEqual(buf, Hex.decode(v65536)))
+ {
+ mismatch("v65536", v65536, buf);
+ }
+ break;
+ default:
+ // ignore
+ }
+ }
+ }
+
+ private void mismatch(String name, String expected, byte[] found)
+ {
+ fail("mismatch on " + name, expected, new String(Hex.encode(found)));
+ }
+
+
+ private void reinitBug()
+ {
+ KeyParameter key = new KeyParameter(Hex.decode("80000000000000000000000000000000"));
+ ParametersWithIV parameters = new ParametersWithIV(key, Hex.decode("0000000000000000"));
+
+ StreamCipher salsa = new ChaChaEngine();
+
+ salsa.init(true, parameters);
+
+ try
+ {
+ salsa.init(true, key);
+ fail("Salsa20 should throw exception if no IV in Init");
+ }
+ catch (IllegalArgumentException e)
+ {
+ }
+ }
+
+ private boolean areEqual(byte[] a, int aOff, byte[] b, int bOff)
+ {
+ for (int i = bOff; i != b.length; i++)
+ {
+ if (a[aOff + i - bOff] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private void skipTest()
+ {
+ SecureRandom rand = new SecureRandom();
+ byte[] plain = new byte[5000];
+ byte[] cipher = new byte[5000];
+
+ rand.nextBytes(plain);
+
+ CipherParameters params = new ParametersWithIV(new KeyParameter(Hex.decode("0053A6F94C9FF24598EB3E91E4378ADD3083D6297CCF2275C81B6EC11467BA0D")), Hex.decode("0D74DB42A91077DE"));
+ ChaChaEngine engine = new ChaChaEngine();
+
+ engine.init(true, params);
+
+ engine.processBytes(plain, 0, plain.length, cipher, 0);
+
+ byte[] fragment = new byte[20];
+
+ engine.init(true, params);
+
+ engine.skip(10);
+
+ engine.processBytes(plain, 10, fragment.length, fragment, 0);
+
+ if (!areEqual(cipher, 10, fragment, 0))
+ {
+ fail("skip forward 10 failed");
+ }
+
+ engine.skip(1000);
+
+ engine.processBytes(plain, 1010 + fragment.length, fragment.length, fragment, 0);
+
+ if (!areEqual(cipher, 1010 + fragment.length, fragment, 0))
+ {
+ fail("skip forward 1000 failed");
+ }
+
+ engine.skip(-10);
+
+ engine.processBytes(plain, 1010 + 2 * fragment.length - 10, fragment.length, fragment, 0);
+
+ if (!areEqual(cipher, 1010 + 2 * fragment.length - 10, fragment, 0))
+ {
+ fail("skip back 10 failed");
+ }
+
+ engine.skip(-1000);
+
+ if (engine.getPosition() != 60)
+ {
+ fail("skip position incorrect - " + 60 + " got " + engine.getPosition());
+ }
+
+ engine.processBytes(plain, 60, fragment.length, fragment, 0);
+
+ if (!areEqual(cipher, 60, fragment, 0))
+ {
+ fail("skip back 1000 failed");
+ }
+
+ long pos = engine.seekTo(1010);
+ if (pos != 1010)
+ {
+ fail("position wrong");
+ }
+
+ engine.processBytes(plain, 1010, fragment.length, fragment, 0);
+
+ if (!areEqual(cipher, 1010, fragment, 0))
+ {
+ fail("seek to 1010 failed");
+ }
+
+ engine.reset();
+
+ for (int i = 0; i != 1000; i++)
+ {
+ engine.skip(i);
+
+ if (engine.getPosition() != i)
+ {
+ fail("skip forward at wrong position");
+ }
+
+ engine.processBytes(plain, i, fragment.length, fragment, 0);
+
+ if (!areEqual(cipher, i, fragment, 0))
+ {
+ fail("skip forward i failed: " + i);
+ }
+
+ if (engine.getPosition() != i + fragment.length)
+ {
+ fail("cipher at wrong position: " + engine.getPosition() + " [" + i + "]");
+ }
+
+ engine.skip(-fragment.length);
+
+ if (engine.getPosition() != i)
+ {
+ fail("skip back at wrong position");
+ }
+
+ engine.processBytes(plain, i, fragment.length, fragment, 0);
+
+ if (!areEqual(cipher, i, fragment, 0))
+ {
+ fail("skip back i failed: " + i);
+ }
+
+ engine.reset();
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new ChaChaTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/CipherStreamTest.java b/core/src/test/java/org/spongycastle/crypto/test/CipherStreamTest.java
new file mode 100644
index 00000000..bc049fa2
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/CipherStreamTest.java
@@ -0,0 +1,699 @@
+package org.spongycastle.crypto.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.BufferedBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.StreamCipher;
+import org.spongycastle.crypto.engines.AESEngine;
+import org.spongycastle.crypto.engines.BlowfishEngine;
+import org.spongycastle.crypto.engines.CAST5Engine;
+import org.spongycastle.crypto.engines.CAST6Engine;
+import org.spongycastle.crypto.engines.CamelliaEngine;
+import org.spongycastle.crypto.engines.ChaChaEngine;
+import org.spongycastle.crypto.engines.DESEngine;
+import org.spongycastle.crypto.engines.DESedeEngine;
+import org.spongycastle.crypto.engines.Grain128Engine;
+import org.spongycastle.crypto.engines.Grainv1Engine;
+import org.spongycastle.crypto.engines.HC128Engine;
+import org.spongycastle.crypto.engines.HC256Engine;
+import org.spongycastle.crypto.engines.NoekeonEngine;
+import org.spongycastle.crypto.engines.RC2Engine;
+import org.spongycastle.crypto.engines.RC4Engine;
+import org.spongycastle.crypto.engines.RC6Engine;
+import org.spongycastle.crypto.engines.SEEDEngine;
+import org.spongycastle.crypto.engines.Salsa20Engine;
+import org.spongycastle.crypto.engines.SerpentEngine;
+import org.spongycastle.crypto.engines.TEAEngine;
+import org.spongycastle.crypto.engines.ThreefishEngine;
+import org.spongycastle.crypto.engines.TwofishEngine;
+import org.spongycastle.crypto.engines.XSalsa20Engine;
+import org.spongycastle.crypto.engines.XTEAEngine;
+import org.spongycastle.crypto.io.CipherInputStream;
+import org.spongycastle.crypto.io.CipherOutputStream;
+import org.spongycastle.crypto.io.InvalidCipherTextIOException;
+import org.spongycastle.crypto.modes.AEADBlockCipher;
+import org.spongycastle.crypto.modes.CBCBlockCipher;
+import org.spongycastle.crypto.modes.CCMBlockCipher;
+import org.spongycastle.crypto.modes.CFBBlockCipher;
+import org.spongycastle.crypto.modes.CTSBlockCipher;
+import org.spongycastle.crypto.modes.EAXBlockCipher;
+import org.spongycastle.crypto.modes.GCMBlockCipher;
+import org.spongycastle.crypto.modes.OCBBlockCipher;
+import org.spongycastle.crypto.modes.OFBBlockCipher;
+import org.spongycastle.crypto.modes.SICBlockCipher;
+import org.spongycastle.crypto.paddings.PKCS7Padding;
+import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.test.SimpleTest;
+
+public class CipherStreamTest
+ extends SimpleTest
+{
+ private int streamSize;
+
+ public String getName()
+ {
+ return "CipherStreamTest";
+ }
+
+ private void testMode(Object cipher, CipherParameters params)
+ throws Exception
+ {
+ testWriteRead(cipher, params, false);
+ testWriteRead(cipher, params, true);
+ testReadWrite(cipher, params, false);
+ testReadWrite(cipher, params, true);
+
+ if (!(cipher instanceof CTSBlockCipher))
+ {
+ testWriteReadEmpty(cipher, params, false);
+ testWriteReadEmpty(cipher, params, true);
+ }
+
+ if (cipher instanceof AEADBlockCipher)
+ {
+ testTamperedRead((AEADBlockCipher)cipher, params);
+ testTruncatedRead((AEADBlockCipher)cipher, params);
+ testTamperedWrite((AEADBlockCipher)cipher, params);
+ }
+ }
+
+ private OutputStream createCipherOutputStream(OutputStream output, Object cipher)
+ {
+ if (cipher instanceof BufferedBlockCipher)
+ {
+ return new CipherOutputStream(output, (BufferedBlockCipher)cipher);
+ }
+ else if (cipher instanceof AEADBlockCipher)
+ {
+ return new CipherOutputStream(output, (AEADBlockCipher)cipher);
+ }
+ else
+ {
+ return new CipherOutputStream(output, (StreamCipher)cipher);
+ }
+ }
+
+ private InputStream createCipherInputStream(byte[] data, Object cipher)
+ {
+ ByteArrayInputStream input = new ByteArrayInputStream(data);
+ if (cipher instanceof BufferedBlockCipher)
+ {
+ return new CipherInputStream(input, (BufferedBlockCipher)cipher);
+ }
+ else if (cipher instanceof AEADBlockCipher)
+ {
+ return new CipherInputStream(input, (AEADBlockCipher)cipher);
+ }
+ else
+ {
+ return new CipherInputStream(input, (StreamCipher)cipher);
+ }
+ }
+
+ /**
+ * Test tampering of ciphertext followed by read from decrypting CipherInputStream
+ */
+ private void testTamperedRead(AEADBlockCipher cipher, CipherParameters params)
+ throws Exception
+ {
+ cipher.init(true, params);
+
+ byte[] ciphertext = new byte[cipher.getOutputSize(streamSize)];
+ cipher.doFinal(ciphertext, cipher.processBytes(new byte[streamSize], 0, streamSize, ciphertext, 0));
+
+ // Tamper
+ ciphertext[0] += 1;
+
+ cipher.init(false, params);
+ InputStream input = createCipherInputStream(ciphertext, cipher);
+ try
+ {
+ while (input.read() >= 0)
+ {
+ }
+ fail("Expected invalid ciphertext after tamper and read : " + cipher.getAlgorithmName());
+ }
+ catch (InvalidCipherTextIOException e)
+ {
+ // Expected
+ }
+ try
+ {
+ input.close();
+ }
+ catch (Exception e)
+ {
+ fail("Unexpected exception after tamper and read : " + cipher.getAlgorithmName());
+ }
+ }
+
+ /**
+ * Test truncation of ciphertext to make tag calculation impossible, followed by read from
+ * decrypting CipherInputStream
+ */
+ private void testTruncatedRead(AEADBlockCipher cipher, CipherParameters params)
+ throws Exception
+ {
+ cipher.init(true, params);
+
+ byte[] ciphertext = new byte[cipher.getOutputSize(streamSize)];
+ cipher.doFinal(ciphertext, cipher.processBytes(new byte[streamSize], 0, streamSize, ciphertext, 0));
+
+ // Truncate to just smaller than complete tag
+ byte[] truncated = new byte[ciphertext.length - streamSize - 1];
+ System.arraycopy(ciphertext, 0, truncated, 0, truncated.length);
+
+ cipher.init(false, params);
+ InputStream input = createCipherInputStream(truncated, cipher);
+ while (true)
+ {
+ int read = 0;
+ try
+ {
+ read = input.read();
+ }
+ catch (InvalidCipherTextIOException e)
+ {
+ // Expected
+ break;
+ }
+ catch (Exception e)
+ {
+ fail("Unexpected exception on truncated read : " + cipher.getAlgorithmName());
+ break;
+ }
+ if (read < 0)
+ {
+ fail("Expected invalid ciphertext after truncate and read : " + cipher.getAlgorithmName());
+ break;
+ }
+ }
+ try
+ {
+ input.close();
+ }
+ catch (Exception e)
+ {
+ fail("Unexpected exception after truncate and read : " + cipher.getAlgorithmName());
+ }
+ }
+
+ /**
+ * Test tampering of ciphertext followed by write to decrypting CipherOutputStream
+ */
+ private void testTamperedWrite(AEADBlockCipher cipher, CipherParameters params)
+ throws Exception
+ {
+ cipher.init(true, params);
+
+ byte[] ciphertext = new byte[cipher.getOutputSize(streamSize)];
+ cipher.doFinal(ciphertext, cipher.processBytes(new byte[streamSize], 0, streamSize, ciphertext, 0));
+
+ // Tamper
+ ciphertext[0] += 1;
+
+ cipher.init(false, params);
+ ByteArrayOutputStream plaintext = new ByteArrayOutputStream();
+ OutputStream output = createCipherOutputStream(plaintext, cipher);
+
+ for (int i = 0; i < ciphertext.length; i++)
+ {
+ output.write(ciphertext[i]);
+ }
+ try
+ {
+ output.close();
+ fail("Expected invalid ciphertext after tamper and write : " + cipher.getAlgorithmName());
+ }
+ catch (InvalidCipherTextIOException e)
+ {
+ // Expected
+ }
+ }
+
+ /**
+ * Test CipherOutputStream in ENCRYPT_MODE, CipherInputStream in DECRYPT_MODE
+ */
+ private void testWriteRead(Object cipher, CipherParameters params, boolean blocks)
+ throws Exception
+ {
+ byte[] data = new byte[streamSize];
+ for (int i = 0; i < data.length; i++)
+ {
+ data[i] = (byte)(i % 255);
+ }
+
+ testWriteRead(cipher, params, blocks, data);
+ }
+
+ /**
+ * Test CipherOutputStream in ENCRYPT_MODE, CipherInputStream in DECRYPT_MODE
+ */
+ private void testWriteReadEmpty(Object cipher, CipherParameters params, boolean blocks)
+ throws Exception
+ {
+ byte[] data = new byte[0];
+
+ testWriteRead(cipher, params, blocks, data);
+ }
+
+ private void testWriteRead(Object cipher, CipherParameters params, boolean blocks, byte[] data)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ init(cipher, true, params);
+
+ OutputStream cOut = createCipherOutputStream(bOut, cipher);
+ if (blocks)
+ {
+ int chunkSize = Math.max(1, data.length / 8);
+ for (int i = 0; i < data.length; i += chunkSize)
+ {
+ cOut.write(data, i, Math.min(chunkSize, data.length - i));
+ }
+ }
+ else
+ {
+ for (int i = 0; i < data.length; i++)
+ {
+ cOut.write(data[i]);
+ }
+ }
+ cOut.close();
+
+ byte[] cipherText = bOut.toByteArray();
+ bOut.reset();
+ init(cipher, false, params);
+ InputStream cIn = createCipherInputStream(cipherText, cipher);
+
+ if (blocks)
+ {
+ byte[] block = new byte[getBlockSize(cipher) + 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 " + getName(cipher), e);
+ }
+
+ byte[] decrypted = bOut.toByteArray();
+ if (!Arrays.areEqual(data, decrypted))
+ {
+ fail("Failed - decrypted data doesn't match: " + getName(cipher));
+ }
+ }
+
+ private String getName(Object cipher)
+ {
+ if (cipher instanceof BufferedBlockCipher)
+ {
+ return ((BufferedBlockCipher)cipher).getUnderlyingCipher().getAlgorithmName();
+ }
+ else if (cipher instanceof AEADBlockCipher)
+ {
+ return ((AEADBlockCipher)cipher).getUnderlyingCipher().getAlgorithmName();
+ }
+ else if (cipher instanceof StreamCipher)
+ {
+ return ((StreamCipher)cipher).getAlgorithmName();
+ }
+ return null;
+ }
+
+ private int getBlockSize(Object cipher)
+ {
+ if (cipher instanceof BlockCipher)
+ {
+ return ((BlockCipher)cipher).getBlockSize();
+ }
+ else if (cipher instanceof BufferedBlockCipher)
+ {
+ return ((BufferedBlockCipher)cipher).getBlockSize();
+ }
+ else if (cipher instanceof AEADBlockCipher)
+ {
+ return ((AEADBlockCipher)cipher).getUnderlyingCipher().getBlockSize();
+ }
+ else if (cipher instanceof StreamCipher)
+ {
+ return 1;
+ }
+ return 0;
+ }
+
+ private void init(Object cipher, boolean forEncrypt, CipherParameters params)
+ {
+ if (cipher instanceof BufferedBlockCipher)
+ {
+ ((BufferedBlockCipher)cipher).init(forEncrypt, params);
+ }
+ else if (cipher instanceof AEADBlockCipher)
+ {
+ ((AEADBlockCipher)cipher).init(forEncrypt, params);
+ }
+ else if (cipher instanceof StreamCipher)
+ {
+ ((StreamCipher)cipher).init(forEncrypt, params);
+ }
+ }
+
+ 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);
+ }
+ }
+
+ /**
+ * Test CipherInputStream in ENCRYPT_MODE, CipherOutputStream in DECRYPT_MODE
+ */
+ private void testReadWrite(Object cipher, CipherParameters params, boolean blocks)
+ throws Exception
+ {
+ String lCode = "ABCDEFGHIJKLMNOPQRSTU";
+
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ init(cipher, true, params);
+
+ InputStream cIn = createCipherInputStream(lCode.getBytes(), cipher);
+ ByteArrayOutputStream ct = new ByteArrayOutputStream();
+
+ if (blocks)
+ {
+ byte[] block = new byte[getBlockSize(cipher) + 1];
+ int c;
+ while ((c = cIn.read(block)) >= 0)
+ {
+ ct.write(block, 0, c);
+ }
+ }
+ else
+ {
+ int c;
+ while ((c = cIn.read()) >= 0)
+ {
+ ct.write(c);
+ }
+ }
+ cIn.close();
+
+ init(cipher, false, params);
+ ByteArrayInputStream dataIn = new ByteArrayInputStream(ct.toByteArray());
+ OutputStream cOut = createCipherOutputStream(bOut, cipher);
+
+ if (blocks)
+ {
+ byte[] block = new byte[getBlockSize(cipher) + 1];
+ int c;
+ while ((c = dataIn.read(block)) >= 0)
+ {
+ cOut.write(block, 0, c);
+ }
+ }
+ else
+ {
+ int c;
+ while ((c = dataIn.read()) >= 0)
+ {
+ cOut.write(c);
+ }
+ }
+ cOut.flush();
+ cOut.close();
+
+ }
+ catch (Exception e)
+ {
+ fail("Unexpected exception " + getName(cipher), e);
+ }
+
+ String res = new String(bOut.toByteArray());
+ if (!res.equals(lCode))
+ {
+ fail("Failed read/write - decrypted data doesn't match: " + getName(cipher), lCode, res);
+ }
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ int[] testSizes = new int[]{0, 1, 7, 8, 9, 15, 16, 17, 1023, 1024, 1025, 2047, 2048, 2049, 4095, 4096, 4097};
+ for (int i = 0; i < testSizes.length; i++)
+ {
+ this.streamSize = testSizes[i];
+ performTests();
+ }
+ }
+
+ private void performTests()
+ throws Exception
+ {
+ testModes(new BlowfishEngine(), new BlowfishEngine(), 16);
+ testModes(new DESEngine(), new DESEngine(), 8);
+ testModes(new DESedeEngine(), new DESedeEngine(), 24);
+ testModes(new TEAEngine(), new TEAEngine(), 16);
+ testModes(new CAST5Engine(), new CAST5Engine(), 16);
+ testModes(new RC2Engine(), new RC2Engine(), 16);
+ testModes(new XTEAEngine(), new XTEAEngine(), 16);
+
+ testModes(new AESEngine(), new AESEngine(), 16);
+ testModes(new NoekeonEngine(), new NoekeonEngine(), 16);
+ testModes(new TwofishEngine(), new TwofishEngine(), 16);
+ testModes(new CAST6Engine(), new CAST6Engine(), 16);
+ testModes(new SEEDEngine(), new SEEDEngine(), 16);
+ testModes(new SerpentEngine(), new SerpentEngine(), 16);
+ testModes(new RC6Engine(), new RC6Engine(), 16);
+ testModes(new CamelliaEngine(), new CamelliaEngine(), 16);
+ testModes(new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512),
+ new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512), 64);
+
+ testMode(new RC4Engine(), new KeyParameter(new byte[16]));
+ testMode(new Salsa20Engine(), new ParametersWithIV(new KeyParameter(new byte[16]), new byte[8]));
+ testMode(new XSalsa20Engine(), new ParametersWithIV(new KeyParameter(new byte[32]), new byte[24]));
+ testMode(new ChaChaEngine(), new ParametersWithIV(new KeyParameter(new byte[16]), new byte[8]));
+ testMode(new Grainv1Engine(), new ParametersWithIV(new KeyParameter(new byte[16]), new byte[8]));
+ testMode(new Grain128Engine(), new ParametersWithIV(new KeyParameter(new byte[16]), new byte[12]));
+ testMode(new HC128Engine(), new KeyParameter(new byte[16]));
+ testMode(new HC256Engine(), new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]));
+
+ testSkipping(new Salsa20Engine(), new ParametersWithIV(new KeyParameter(new byte[16]), new byte[8]));
+ testSkipping(new SICBlockCipher(new AESEngine()), new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]));
+ }
+
+ private void testModes(BlockCipher cipher1, BlockCipher cipher2, int keySize)
+ throws Exception
+ {
+ final KeyParameter key = new KeyParameter(new byte[keySize]);
+ final int blockSize = getBlockSize(cipher1);
+ final CipherParameters withIv = new ParametersWithIV(key, new byte[blockSize]);
+
+ if (blockSize > 1)
+ {
+ testMode(new PaddedBufferedBlockCipher(cipher1, new PKCS7Padding()), key);
+
+ testMode(new PaddedBufferedBlockCipher(new CBCBlockCipher(cipher1), new PKCS7Padding()), withIv);
+
+ testMode(new BufferedBlockCipher(new OFBBlockCipher(cipher1, blockSize)), withIv);
+ testMode(new BufferedBlockCipher(new CFBBlockCipher(cipher1, blockSize)), withIv);
+ testMode(new BufferedBlockCipher(new SICBlockCipher(cipher1)), withIv);
+ }
+ // CTS requires at least one block
+ if (blockSize <= 16 && streamSize >= blockSize)
+ {
+ testMode(new CTSBlockCipher(cipher1), key);
+ }
+ if (blockSize == 8 || blockSize == 16)
+ {
+ testMode(new EAXBlockCipher(cipher1), withIv);
+ }
+ if (blockSize == 16)
+ {
+ testMode(new CCMBlockCipher(cipher1), new ParametersWithIV(key, new byte[7]));
+ testMode(new GCMBlockCipher(cipher1), withIv);
+ testMode(new OCBBlockCipher(cipher1, cipher2), new ParametersWithIV(key, new byte[15]));
+ }
+ }
+
+ private void testSkipping(StreamCipher cipher, CipherParameters params)
+ throws Exception
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ init(cipher, true, params);
+
+ OutputStream cOut = createCipherOutputStream(bOut, cipher);
+ byte[] data = new byte[5000];
+
+ new SecureRandom().nextBytes(data);
+
+ cOut.write(data);
+
+ cOut.close();
+
+ init(cipher, false, params);
+
+ InputStream cIn = createCipherInputStream(bOut.toByteArray(), cipher);
+
+ long skip = cIn.skip(50);
+ if (skip != 50)
+ {
+ fail("wrong number of bytes skipped: " + skip);
+ }
+
+ byte[] block = new byte[50];
+
+ cIn.read(block);
+
+ if (!areEqual(data, 50, block, 0))
+ {
+ fail("initial skip mismatch");
+ }
+
+ skip = cIn.skip(3000);
+ if (skip != 3000)
+ {
+ fail("wrong number of bytes skipped: " + skip);
+ }
+
+ cIn.read(block);
+
+ if (!areEqual(data, 3100, block, 0))
+ {
+ fail("second skip mismatch");
+ }
+
+ cipher.reset();
+
+ cIn = createCipherInputStream(bOut.toByteArray(), cipher);
+ if (!cIn.markSupported())
+ {
+ fail("marking not supported");
+ }
+
+ cIn.mark(100);
+
+ cIn.read(block);
+
+ if (!areEqual(data, 0, block, 0))
+ {
+ fail("initial mark read failed");
+ }
+
+ cIn.reset();
+
+ cIn.read(block);
+
+ if (!areEqual(data, 0, block, 0))
+ {
+ fail(cipher.getAlgorithmName() + " initial reset read failed");
+ }
+
+ cIn.reset();
+
+ cIn.read(block);
+
+ cIn.mark(100);
+
+ cIn.read(block);
+
+ if (!areEqual(data, 50, block, 0))
+ {
+ fail("second mark read failed");
+ }
+
+ cIn.reset();
+
+ cIn.read(block);
+
+ if (!areEqual(data, 50, block, 0))
+ {
+ fail(cipher.getAlgorithmName() + " second reset read failed");
+ }
+
+ cIn.mark(3000);
+
+ skip = cIn.skip(2050);
+ if (skip != 2050)
+ {
+ fail("wrong number of bytes skipped: " + skip);
+ }
+
+ cIn.reset();
+
+ cIn.read(block);
+
+ if (!areEqual(data, 100, block, 0))
+ {
+ fail(cipher.getAlgorithmName() + " third reset read failed");
+ }
+
+ cIn.read(new byte[2150]);
+
+ cIn.reset();
+
+ cIn.read(block);
+
+ if (!areEqual(data, 100, block, 0))
+ {
+ fail(cipher.getAlgorithmName() + " fourth reset read failed");
+ }
+
+ cIn.close();
+ }
+
+ private boolean areEqual(byte[] a, int aOff, byte[] b, int bOff)
+ {
+ for (int i = bOff; i != b.length; i++)
+ {
+ if (a[aOff + i - bOff] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new CipherStreamTest());
+ }
+
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/CipherTest.java b/core/src/test/java/org/spongycastle/crypto/test/CipherTest.java
new file mode 100644
index 00000000..6bd4c21f
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/CipherTest.java
@@ -0,0 +1,117 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.test.SimpleTest;
+
+public abstract class CipherTest
+ extends SimpleTest
+{
+ private SimpleTest[] _tests;
+ private BlockCipher _engine;
+ private KeyParameter _validKey;
+
+// protected CipherTest(
+// SimpleTest[] tests)
+// {
+// _tests = tests;
+// }
+
+ protected CipherTest(
+ SimpleTest[] tests,
+ BlockCipher engine,
+ KeyParameter validKey)
+ {
+ _tests = tests;
+ _engine = engine;
+ _validKey = validKey;
+ }
+
+ public abstract String getName();
+
+ public void performTest()
+ throws Exception
+ {
+ for (int i = 0; i != _tests.length; i++)
+ {
+ _tests[i].performTest();
+ }
+
+ if (_engine != null)
+ {
+ //
+ // state tests
+ //
+ byte[] buf = new byte[128];
+
+ try
+ {
+ _engine.processBlock(buf, 0, buf, 0);
+
+ fail("failed initialisation check");
+ }
+ catch (IllegalStateException e)
+ {
+ // expected
+ }
+
+ bufferSizeCheck((_engine));
+ }
+ }
+
+ private void bufferSizeCheck(
+ BlockCipher engine)
+ {
+ byte[] correctBuf = new byte[engine.getBlockSize()];
+ byte[] shortBuf = new byte[correctBuf.length / 2];
+
+ engine.init(true, _validKey);
+
+ try
+ {
+ engine.processBlock(shortBuf, 0, correctBuf, 0);
+
+ fail("failed short input check");
+ }
+ catch (DataLengthException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ engine.processBlock(correctBuf, 0, shortBuf, 0);
+
+ fail("failed short output check");
+ }
+ catch (DataLengthException e)
+ {
+ // expected
+ }
+
+ engine.init(false, _validKey);
+
+ try
+ {
+ engine.processBlock(shortBuf, 0, correctBuf, 0);
+
+ fail("failed short input check");
+ }
+ catch (DataLengthException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ engine.processBlock(correctBuf, 0, shortBuf, 0);
+
+ fail("failed short output check");
+ }
+ catch (DataLengthException e)
+ {
+ // expected
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/CramerShoupTest.java b/core/src/test/java/org/spongycastle/crypto/test/CramerShoupTest.java
new file mode 100644
index 00000000..584fe9e1
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/CramerShoupTest.java
@@ -0,0 +1,147 @@
+package org.spongycastle.crypto.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.agreement.DHStandardGroups;
+import org.spongycastle.crypto.engines.CramerShoupCiphertext;
+import org.spongycastle.crypto.engines.CramerShoupCoreEngine;
+import org.spongycastle.crypto.engines.CramerShoupCoreEngine.CramerShoupCiphertextException;
+import org.spongycastle.crypto.generators.CramerShoupKeyPairGenerator;
+import org.spongycastle.crypto.generators.CramerShoupParametersGenerator;
+import org.spongycastle.crypto.params.CramerShoupKeyGenerationParameters;
+import org.spongycastle.crypto.params.CramerShoupParameters;
+import org.spongycastle.util.BigIntegers;
+import org.spongycastle.util.test.SimpleTest;
+
+public class CramerShoupTest
+ extends SimpleTest
+{
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ private static final SecureRandom RND = new SecureRandom();
+
+ private AsymmetricCipherKeyPair keyPair;
+
+ public static void main(String[] args)
+ {
+ runTest(new CramerShoupTest());
+ }
+
+ public String getName()
+ {
+ return "CramerShoup";
+ }
+
+
+ public void performTest()
+ throws Exception
+ {
+ BigInteger pSubOne = DHStandardGroups.rfc3526_2048.getP().subtract(ONE);
+ for (int i = 0; i < 10; ++i)
+ {
+ BigInteger message = BigIntegers.createRandomInRange(ONE, pSubOne, RND);
+
+ BigInteger m1 = encDecTest(message);
+ BigInteger m2 = labelledEncDecTest(message, "myRandomLabel");
+ BigInteger m3 = encDecEncodingTest(message);
+ BigInteger m4 = labelledEncDecEncodingTest(message, "myOtherCoolLabel");
+
+ if (!message.equals(m1) || !message.equals(m2) || !message.equals(m3) || !message.equals(m4))
+ {
+ fail("decrypted message != original message");
+ }
+ }
+ }
+
+ private BigInteger encDecEncodingTest(BigInteger m)
+ {
+ CramerShoupCiphertext ciphertext = encrypt(m);
+ byte[] c = ciphertext.toByteArray();
+ CramerShoupCiphertext decC = new CramerShoupCiphertext(c);
+ return decrypt(decC);
+ }
+
+ private BigInteger labelledEncDecEncodingTest(BigInteger m, String l)
+ {
+ byte[] c = encrypt(m, l).toByteArray();
+ return decrypt(new CramerShoupCiphertext(c), l);
+ }
+
+ private BigInteger encDecTest(BigInteger m)
+ {
+ CramerShoupCiphertext c = encrypt(m);
+ return decrypt(c);
+ }
+
+ private BigInteger labelledEncDecTest(BigInteger m, String l)
+ {
+ CramerShoupCiphertext c = encrypt(m, l);
+ return decrypt(c, l);
+ }
+
+
+ private BigInteger decrypt(CramerShoupCiphertext ciphertext)
+ {
+ return decrypt(ciphertext, null);
+ }
+
+ private BigInteger decrypt(CramerShoupCiphertext ciphertext, String label)
+ {
+
+ CramerShoupCoreEngine engine = new CramerShoupCoreEngine();
+ if (label != null)
+ {
+ engine.init(false, keyPair.getPrivate(), label);
+ }
+ else
+ {
+ engine.init(false, keyPair.getPrivate());
+ }
+ try
+ {
+ BigInteger m = engine.decryptBlock(ciphertext);
+
+ return m;
+ }
+ catch (CramerShoupCiphertextException e)
+ {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ private CramerShoupCiphertext encrypt(BigInteger message)
+ {
+ return encrypt(message, null);
+ }
+
+ private CramerShoupCiphertext encrypt(BigInteger message, String label)
+ {
+ CramerShoupKeyPairGenerator kpGen = new CramerShoupKeyPairGenerator();
+ CramerShoupParametersGenerator pGen = new CramerShoupParametersGenerator();
+
+ pGen.init(2048, 1, RND);
+ CramerShoupParameters params = pGen.generateParameters(DHStandardGroups.rfc3526_2048);
+ CramerShoupKeyGenerationParameters param = new CramerShoupKeyGenerationParameters(RND, params);
+
+ kpGen.init(param);
+ keyPair = kpGen.generateKeyPair();
+
+ CramerShoupCoreEngine engine = new CramerShoupCoreEngine();
+ if (label != null)
+ {
+ engine.init(true, keyPair.getPublic(), label);
+ }
+ else
+ {
+ engine.init(true, keyPair.getPublic());
+ }
+
+ CramerShoupCiphertext ciphertext = engine.encryptBlock(message);
+
+ return ciphertext;
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/DESTest.java b/core/src/test/java/org/spongycastle/crypto/test/DESTest.java
new file mode 100644
index 00000000..aec63ef2
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/DESTest.java
@@ -0,0 +1,206 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.crypto.engines.DESEngine;
+import org.spongycastle.crypto.generators.DESKeyGenerator;
+import org.spongycastle.crypto.modes.CBCBlockCipher;
+import org.spongycastle.crypto.modes.CFBBlockCipher;
+import org.spongycastle.crypto.modes.OFBBlockCipher;
+import org.spongycastle.crypto.params.DESParameters;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+import java.security.SecureRandom;
+
+class DESParityTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "DESParityTest";
+ }
+
+ public void performTest()
+ {
+ byte[] k1In = { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff,
+ (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff };
+ byte[] k1Out = { (byte)0xfe, (byte)0xfe, (byte)0xfe, (byte)0xfe,
+ (byte)0xfe, (byte)0xfe, (byte)0xfe, (byte)0xfe };
+
+ byte[] k2In = { (byte)0xef, (byte)0xcb, (byte)0xda, (byte)0x4f,
+ (byte)0xaa, (byte)0x99, (byte)0x7f, (byte)0x63 };
+ byte[] k2Out = { (byte)0xef, (byte)0xcb, (byte)0xda, (byte)0x4f,
+ (byte)0xab, (byte)0x98, (byte)0x7f, (byte)0x62 };
+
+ DESParameters.setOddParity(k1In);
+
+ for (int i = 0; i != k1In.length; i++)
+ {
+ if (k1In[i] != k1Out[i])
+ {
+ fail("Failed "
+ + "got " + new String(Hex.encode(k1In))
+ + " expected " + new String(Hex.encode(k1Out)));
+ }
+ }
+
+ DESParameters.setOddParity(k2In);
+
+ for (int i = 0; i != k2In.length; i++)
+ {
+ if (k2In[i] != k2Out[i])
+ {
+ fail("Failed "
+ + "got " + new String(Hex.encode(k2In))
+ + " expected " + new String(Hex.encode(k2Out)));
+ }
+ }
+ }
+}
+
+class KeyGenTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "KeyGenTest";
+ }
+
+ public void performTest()
+ {
+ DESKeyGenerator keyGen = new DESKeyGenerator();
+
+ keyGen.init(new KeyGenerationParameters(new SecureRandom(), 56));
+
+ byte[] kB = keyGen.generateKey();
+
+ if (kB.length != 8)
+ {
+ fail("DES bit key wrong length.");
+ }
+ }
+}
+
+class DESParametersTest
+ extends SimpleTest
+{
+ static private byte[] weakKeys =
+ {
+ (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01, (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01,
+ (byte)0x1f,(byte)0x1f,(byte)0x1f,(byte)0x1f, (byte)0x0e,(byte)0x0e,(byte)0x0e,(byte)0x0e,
+ (byte)0xe0,(byte)0xe0,(byte)0xe0,(byte)0xe0, (byte)0xf1,(byte)0xf1,(byte)0xf1,(byte)0xf1,
+ (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe, (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe,
+ /* semi-weak keys */
+ (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe, (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe,
+ (byte)0x1f,(byte)0xe0,(byte)0x1f,(byte)0xe0, (byte)0x0e,(byte)0xf1,(byte)0x0e,(byte)0xf1,
+ (byte)0x01,(byte)0xe0,(byte)0x01,(byte)0xe0, (byte)0x01,(byte)0xf1,(byte)0x01,(byte)0xf1,
+ (byte)0x1f,(byte)0xfe,(byte)0x1f,(byte)0xfe, (byte)0x0e,(byte)0xfe,(byte)0x0e,(byte)0xfe,
+ (byte)0x01,(byte)0x1f,(byte)0x01,(byte)0x1f, (byte)0x01,(byte)0x0e,(byte)0x01,(byte)0x0e,
+ (byte)0xe0,(byte)0xfe,(byte)0xe0,(byte)0xfe, (byte)0xf1,(byte)0xfe,(byte)0xf1,(byte)0xfe,
+ (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01, (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01,
+ (byte)0xe0,(byte)0x1f,(byte)0xe0,(byte)0x1f, (byte)0xf1,(byte)0x0e,(byte)0xf1,(byte)0x0e,
+ (byte)0xe0,(byte)0x01,(byte)0xe0,(byte)0x01, (byte)0xf1,(byte)0x01,(byte)0xf1,(byte)0x01,
+ (byte)0xfe,(byte)0x1f,(byte)0xfe,(byte)0x1f, (byte)0xfe,(byte)0x0e,(byte)0xfe,(byte)0x0e,
+ (byte)0x1f,(byte)0x01,(byte)0x1f,(byte)0x01, (byte)0x0e,(byte)0x01,(byte)0x0e,(byte)0x01,
+ (byte)0xfe,(byte)0xe0,(byte)0xfe,(byte)0xe0, (byte)0xfe,(byte)0xf1,(byte)0xfe,(byte)0xf1
+ };
+
+ public String getName()
+ {
+ return "DESParameters";
+ }
+
+ public void performTest() throws Exception
+ {
+ try
+ {
+ DESParameters.isWeakKey(new byte[4], 0);
+ fail("no exception on small key");
+ }
+ catch (IllegalArgumentException e)
+ {
+ if (!e.getMessage().equals("key material too short."))
+ {
+ fail("wrong exception");
+ }
+ }
+
+ try
+ {
+ new DESParameters(weakKeys);
+ fail("no exception on weak key");
+ }
+ catch (IllegalArgumentException e)
+ {
+ if (!e.getMessage().equals("attempt to create weak DES key"))
+ {
+ fail("wrong exception");
+ }
+ }
+
+ for (int i = 0; i != weakKeys.length; i += 8)
+ {
+ if (!DESParameters.isWeakKey(weakKeys, i))
+ {
+ fail("weakKey test failed");
+ }
+ }
+ }
+}
+
+/**
+ * DES tester - vectors from <a href=http://www.itl.nist.gov/fipspubs/fip81.htm>FIPS 81</a>
+ */
+public class DESTest
+ extends CipherTest
+{
+ static String input1 = "4e6f77206973207468652074696d6520666f7220616c6c20";
+ static String input2 = "4e6f7720697320746865";
+ static String input3 = "4e6f7720697320746865aabbcc";
+
+ static SimpleTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new DESEngine(),
+ new KeyParameter(Hex.decode("0123456789abcdef")),
+ input1, "3fa40e8a984d48156a271787ab8883f9893d51ec4b563b53"),
+ new BlockCipherVectorTest(1, new CBCBlockCipher(new DESEngine()),
+ new ParametersWithIV(new KeyParameter(Hex.decode("0123456789abcdef")), Hex.decode("1234567890abcdef")),
+ input1, "e5c7cdde872bf27c43e934008c389c0f683788499a7c05f6"),
+ new BlockCipherVectorTest(2, new CFBBlockCipher(new DESEngine(), 8),
+ new ParametersWithIV(new KeyParameter(Hex.decode("0123456789abcdef")), Hex.decode("1234567890abcdef")),
+ input2, "f31fda07011462ee187f"),
+ new BlockCipherVectorTest(3, new CFBBlockCipher(new DESEngine(), 64),
+ new ParametersWithIV(new KeyParameter(Hex.decode("0123456789abcdef")), Hex.decode("1234567890abcdef")),
+ input1, "f3096249c7f46e51a69e839b1a92f78403467133898ea622"),
+ new BlockCipherVectorTest(4, new OFBBlockCipher(new DESEngine(), 8),
+ new ParametersWithIV(new KeyParameter(Hex.decode("0123456789abcdef")), Hex.decode("1234567890abcdef")),
+ input2, "f34a2850c9c64985d684"),
+ new BlockCipherVectorTest(5, new CFBBlockCipher(new DESEngine(), 64),
+ new ParametersWithIV(new KeyParameter(Hex.decode("0123456789abcdef")), Hex.decode("1234567890abcdef")),
+ input3, "f3096249c7f46e51a69e0954bf"),
+ new BlockCipherVectorTest(6, new OFBBlockCipher(new DESEngine(), 64),
+ new ParametersWithIV(new KeyParameter(Hex.decode("0123456789abcdef")), Hex.decode("1234567890abcdef")),
+ input3, "f3096249c7f46e5135f2c0eb8b"),
+ new DESParityTest(),
+ new DESParametersTest(),
+ new KeyGenTest()
+ };
+
+ public DESTest()
+ {
+ super(tests, new DESEngine(), new KeyParameter(new byte[8]));
+ }
+
+ public String getName()
+ {
+ return "DES";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new DESTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/DESedeTest.java b/core/src/test/java/org/spongycastle/crypto/test/DESedeTest.java
new file mode 100644
index 00000000..6fc4d0d0
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/DESedeTest.java
@@ -0,0 +1,177 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.crypto.Wrapper;
+import org.spongycastle.crypto.engines.DESedeEngine;
+import org.spongycastle.crypto.engines.DESedeWrapEngine;
+import org.spongycastle.crypto.generators.DESedeKeyGenerator;
+import org.spongycastle.crypto.params.DESedeParameters;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+import java.security.SecureRandom;
+
+/**
+ * DESede tester
+ */
+public class DESedeTest
+ extends CipherTest
+{
+ static private byte[] weakKey = // first 8 bytes non-weak
+ {
+ (byte)0x06,(byte)0x01,(byte)0x01,(byte)0x01, (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01,
+ (byte)0x1f,(byte)0x1f,(byte)0x1f,(byte)0x1f, (byte)0x0e,(byte)0x0e,(byte)0x0e,(byte)0x0e,
+ (byte)0xe0,(byte)0xe0,(byte)0xe0,(byte)0xe0, (byte)0xf1,(byte)0xf1,(byte)0xf1,(byte)0xf1,
+ };
+
+ static String input1 = "4e6f77206973207468652074696d6520666f7220616c6c20";
+ static String input2 = "4e6f7720697320746865";
+
+ static SimpleTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new DESedeEngine(),
+ new DESedeParameters(Hex.decode("0123456789abcdef0123456789abcdef")),
+ input1, "3fa40e8a984d48156a271787ab8883f9893d51ec4b563b53"),
+ new BlockCipherVectorTest(1, new DESedeEngine(),
+ new DESedeParameters(Hex.decode("0123456789abcdeffedcba9876543210")),
+ input1, "d80a0d8b2bae5e4e6a0094171abcfc2775d2235a706e232c"),
+ new BlockCipherVectorTest(2, new DESedeEngine(),
+ new DESedeParameters(Hex.decode("0123456789abcdef0123456789abcdef0123456789abcdef")),
+ input1, "3fa40e8a984d48156a271787ab8883f9893d51ec4b563b53"),
+ new BlockCipherVectorTest(3, new DESedeEngine(),
+ new DESedeParameters(Hex.decode("0123456789abcdeffedcba98765432100123456789abcdef")),
+ input1, "d80a0d8b2bae5e4e6a0094171abcfc2775d2235a706e232c")
+ };
+
+ DESedeTest()
+ {
+ super(tests, new DESedeEngine(), new KeyParameter(new byte[16]));
+ }
+
+ private void wrapTest(
+ int id,
+ byte[] kek,
+ byte[] iv,
+ byte[] in,
+ byte[] out)
+ {
+ Wrapper wrapper = new DESedeWrapEngine();
+
+ wrapper.init(true, new ParametersWithIV(new KeyParameter(kek), iv));
+
+ try
+ {
+ byte[] cText = wrapper.wrap(in, 0, in.length);
+ if (!areEqual(cText, out))
+ {
+ fail(": failed wrap test " + id + " expected " + new String(Hex.encode(out)) + " got " + new String(Hex.encode(cText)));
+ }
+ }
+ catch (Exception e)
+ {
+ fail("failed wrap test exception: " + e.toString(), e);
+ }
+
+ wrapper.init(false, new KeyParameter(kek));
+
+ try
+ {
+ byte[] pText = wrapper.unwrap(out, 0, out.length);
+ if (!areEqual(pText, in))
+ {
+ fail("failed unwrap test " + id + " expected " + new String(Hex.encode(in)) + " got " + new String(Hex.encode(pText)));
+ }
+ }
+ catch (Exception e)
+ {
+ fail("failed unwrap test exception: " + e.toString(), e);
+ }
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ super.performTest();
+
+ byte[] kek1 = Hex.decode("255e0d1c07b646dfb3134cc843ba8aa71f025b7c0838251f");
+ byte[] iv1 = Hex.decode("5dd4cbfc96f5453b");
+ byte[] in1 = Hex.decode("2923bf85e06dd6ae529149f1f1bae9eab3a7da3d860d3e98");
+ byte[] out1 = Hex.decode("690107618ef092b3b48ca1796b234ae9fa33ebb4159604037db5d6a84eb3aac2768c632775a467d4");
+
+ wrapTest(1, kek1, iv1, in1, out1);
+
+ //
+ // key generation
+ //
+ SecureRandom random = new SecureRandom();
+ DESedeKeyGenerator keyGen = new DESedeKeyGenerator();
+
+ keyGen.init(new KeyGenerationParameters(random, 112));
+
+ byte[] kB = keyGen.generateKey();
+
+ if (kB.length != 16)
+ {
+ fail("112 bit key wrong length.");
+ }
+
+ keyGen.init(new KeyGenerationParameters(random, 168));
+
+ kB = keyGen.generateKey();
+
+ if (kB.length != 24)
+ {
+ fail("168 bit key wrong length.");
+ }
+
+ try
+ {
+ keyGen.init(new KeyGenerationParameters(random, 200));
+
+ fail("invalid key length not detected.");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ DESedeParameters.isWeakKey(new byte[4], 0);
+ fail("no exception on small key");
+ }
+ catch (IllegalArgumentException e)
+ {
+ if (!e.getMessage().equals("key material too short."))
+ {
+ fail("wrong exception");
+ }
+ }
+
+ try
+ {
+ new DESedeParameters(weakKey);
+ fail("no exception on weak key");
+ }
+ catch (IllegalArgumentException e)
+ {
+ if (!e.getMessage().equals("attempt to create weak DESede key"))
+ {
+ fail("wrong exception");
+ }
+ }
+ }
+
+ public String getName()
+ {
+ return "DESede";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new DESedeTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/DHKEKGeneratorTest.java b/core/src/test/java/org/spongycastle/crypto/test/DHKEKGeneratorTest.java
new file mode 100644
index 00000000..7a675739
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/DHKEKGeneratorTest.java
@@ -0,0 +1,70 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.crypto.DerivationFunction;
+import org.spongycastle.crypto.DerivationParameters;
+import org.spongycastle.crypto.agreement.kdf.DHKDFParameters;
+import org.spongycastle.crypto.agreement.kdf.DHKEKGenerator;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * DHKEK Generator tests - from RFC 2631.
+ */
+public class DHKEKGeneratorTest
+ extends SimpleTest
+{
+ private byte[] seed1 = Hex.decode("000102030405060708090a0b0c0d0e0f10111213");
+ private ASN1ObjectIdentifier alg1 = PKCSObjectIdentifiers.id_alg_CMS3DESwrap;
+ private byte[] result1 = Hex.decode("a09661392376f7044d9052a397883246b67f5f1ef63eb5fb");
+
+ private byte[] seed2 = Hex.decode("000102030405060708090a0b0c0d0e0f10111213");
+ private ASN1ObjectIdentifier alg2 = PKCSObjectIdentifiers.id_alg_CMSRC2wrap;
+ private byte[] partyAInfo = Hex.decode(
+ "0123456789abcdeffedcba9876543201"
+ + "0123456789abcdeffedcba9876543201"
+ + "0123456789abcdeffedcba9876543201"
+ + "0123456789abcdeffedcba9876543201");
+ private byte[] result2 = Hex.decode("48950c46e0530075403cce72889604e0");
+
+ public DHKEKGeneratorTest()
+ {
+ }
+
+ public void performTest()
+ {
+ checkMask(1, new DHKEKGenerator(new SHA1Digest()), new DHKDFParameters(alg1, 192, seed1), result1);
+ checkMask(2, new DHKEKGenerator(new SHA1Digest()), new DHKDFParameters(alg2, 128, seed2, partyAInfo), result2);
+ }
+
+ private void checkMask(
+ int count,
+ DerivationFunction kdf,
+ DerivationParameters params,
+ byte[] result)
+ {
+ byte[] data = new byte[result.length];
+
+ kdf.init(params);
+
+ kdf.generateBytes(data, 0, data.length);
+
+ if (!areEqual(result, data))
+ {
+ fail("DHKEKGenerator failed generator test " + count);
+ }
+ }
+
+ public String getName()
+ {
+ return "DHKEKGenerator";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new DHKEKGeneratorTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/DHTest.java b/core/src/test/java/org/spongycastle/crypto/test/DHTest.java
new file mode 100644
index 00000000..ce78961f
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/DHTest.java
@@ -0,0 +1,414 @@
+package org.spongycastle.crypto.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.agreement.DHAgreement;
+import org.spongycastle.crypto.agreement.DHBasicAgreement;
+import org.spongycastle.crypto.generators.DHBasicKeyPairGenerator;
+import org.spongycastle.crypto.generators.DHKeyPairGenerator;
+import org.spongycastle.crypto.generators.DHParametersGenerator;
+import org.spongycastle.crypto.params.DHKeyGenerationParameters;
+import org.spongycastle.crypto.params.DHParameters;
+import org.spongycastle.crypto.params.DHPrivateKeyParameters;
+import org.spongycastle.crypto.params.DHPublicKeyParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.util.test.SimpleTest;
+
+public class DHTest
+ extends SimpleTest
+{
+ private BigInteger g512 = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16);
+ private BigInteger p512 = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16);
+
+ private BigInteger g768 = new BigInteger("7c240073c1316c621df461b71ebb0cdcc90a6e5527e5e126633d131f87461c4dc4afc60c2cb0f053b6758871489a69613e2a8b4c8acde23954c08c81cbd36132cfd64d69e4ed9f8e51ed6e516297206672d5c0a69135df0a5dcf010d289a9ca1", 16);
+ private BigInteger p768 = new BigInteger("8c9dd223debed1b80103b8b309715be009d48860ed5ae9b9d5d8159508efd802e3ad4501a7f7e1cfec78844489148cd72da24b21eddd01aa624291c48393e277cfc529e37075eccef957f3616f962d15b44aeab4039d01b817fde9eaa12fd73f", 16);
+
+ private BigInteger g1024 = new BigInteger("1db17639cdf96bc4eabba19454f0b7e5bd4e14862889a725c96eb61048dcd676ceb303d586e30f060dbafd8a571a39c4d823982117da5cc4e0f89c77388b7a08896362429b94a18a327604eb7ff227bffbc83459ade299e57b5f77b50fb045250934938efa145511166e3197373e1b5b1e52de713eb49792bedde722c6717abf", 16);
+ private BigInteger p1024 = new BigInteger("a00e283b3c624e5b2b4d9fbc2653b5185d99499b00fd1bf244c6f0bb817b4d1c451b2958d62a0f8a38caef059fb5ecd25d75ed9af403f5b5bdab97a642902f824e3c13789fed95fa106ddfe0ff4a707c85e2eb77d49e68f2808bcea18ce128b178cd287c6bc00efa9a1ad2a673fe0dceace53166f75b81d6709d5f8af7c66bb7", 16);
+
+ public String getName()
+ {
+ return "DH";
+ }
+
+ private void testDH(
+ int size,
+ BigInteger g,
+ BigInteger p)
+ {
+ DHKeyPairGenerator kpGen = getDHKeyPairGenerator(g, p);
+
+ //
+ // generate first pair
+ //
+ AsymmetricCipherKeyPair pair = kpGen.generateKeyPair();
+
+ DHPublicKeyParameters pu1 = (DHPublicKeyParameters)pair.getPublic();
+ DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.getPrivate();
+ //
+ // generate second pair
+ //
+ pair = kpGen.generateKeyPair();
+
+ DHPublicKeyParameters pu2 = (DHPublicKeyParameters)pair.getPublic();
+ DHPrivateKeyParameters pv2 = (DHPrivateKeyParameters)pair.getPrivate();
+
+ //
+ // two way
+ //
+ DHAgreement e1 = new DHAgreement();
+ DHAgreement e2 = new DHAgreement();
+
+ e1.init(pv1);
+ e2.init(pv2);
+
+ BigInteger m1 = e1.calculateMessage();
+ BigInteger m2 = e2.calculateMessage();
+
+ BigInteger k1 = e1.calculateAgreement(pu2, m2);
+ BigInteger k2 = e2.calculateAgreement(pu1, m1);
+
+ if (!k1.equals(k2))
+ {
+ fail(size + " bit 2-way test failed");
+ }
+ }
+
+ private void testDHBasic(
+ int size,
+ int privateValueSize,
+ BigInteger g,
+ BigInteger p)
+ {
+ DHBasicKeyPairGenerator kpGen = getDHBasicKeyPairGenerator(g, p, privateValueSize);
+
+ //
+ // generate first pair
+ //
+ AsymmetricCipherKeyPair pair = kpGen.generateKeyPair();
+
+ DHPublicKeyParameters pu1 = (DHPublicKeyParameters)pair.getPublic();
+ DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.getPrivate();
+
+ checkKeySize(privateValueSize, pv1);
+ //
+ // generate second pair
+ //
+ pair = kpGen.generateKeyPair();
+
+ DHPublicKeyParameters pu2 = (DHPublicKeyParameters)pair.getPublic();
+ DHPrivateKeyParameters pv2 = (DHPrivateKeyParameters)pair.getPrivate();
+
+ checkKeySize(privateValueSize, pv2);
+ //
+ // two way
+ //
+ DHBasicAgreement e1 = new DHBasicAgreement();
+ DHBasicAgreement e2 = new DHBasicAgreement();
+
+ e1.init(pv1);
+ e2.init(pv2);
+
+ BigInteger k1 = e1.calculateAgreement(pu2);
+ BigInteger k2 = e2.calculateAgreement(pu1);
+
+ if (!k1.equals(k2))
+ {
+ fail("basic " + size + " bit 2-way test failed");
+ }
+ }
+
+ private void checkKeySize(
+ int privateValueSize,
+ DHPrivateKeyParameters priv)
+ {
+ if (privateValueSize != 0)
+ {
+ if (priv.getX().bitLength() != privateValueSize)
+ {
+ fail("limited key check failed for key size " + privateValueSize);
+ }
+ }
+ }
+
+ private void testGPWithRandom(
+ DHKeyPairGenerator kpGen)
+ {
+ //
+ // generate first pair
+ //
+ AsymmetricCipherKeyPair pair = kpGen.generateKeyPair();
+
+ DHPublicKeyParameters pu1 = (DHPublicKeyParameters)pair.getPublic();
+ DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.getPrivate();
+ //
+ // generate second pair
+ //
+ pair = kpGen.generateKeyPair();
+
+ DHPublicKeyParameters pu2 = (DHPublicKeyParameters)pair.getPublic();
+ DHPrivateKeyParameters pv2 = (DHPrivateKeyParameters)pair.getPrivate();
+
+ //
+ // two way
+ //
+ DHAgreement e1 = new DHAgreement();
+ DHAgreement e2 = new DHAgreement();
+
+ e1.init(new ParametersWithRandom(pv1, new SecureRandom()));
+ e2.init(new ParametersWithRandom(pv2, new SecureRandom()));
+
+ BigInteger m1 = e1.calculateMessage();
+ BigInteger m2 = e2.calculateMessage();
+
+ BigInteger k1 = e1.calculateAgreement(pu2, m2);
+ BigInteger k2 = e2.calculateAgreement(pu1, m1);
+
+ if (!k1.equals(k2))
+ {
+ fail("basic with random 2-way test failed");
+ }
+ }
+
+ private void testSimpleWithRandom(
+ DHBasicKeyPairGenerator kpGen)
+ {
+ //
+ // generate first pair
+ //
+ AsymmetricCipherKeyPair pair = kpGen.generateKeyPair();
+
+ DHPublicKeyParameters pu1 = (DHPublicKeyParameters)pair.getPublic();
+ DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.getPrivate();
+ //
+ // generate second pair
+ //
+ pair = kpGen.generateKeyPair();
+
+ DHPublicKeyParameters pu2 = (DHPublicKeyParameters)pair.getPublic();
+ DHPrivateKeyParameters pv2 = (DHPrivateKeyParameters)pair.getPrivate();
+
+ //
+ // two way
+ //
+ DHBasicAgreement e1 = new DHBasicAgreement();
+ DHBasicAgreement e2 = new DHBasicAgreement();
+
+ e1.init(new ParametersWithRandom(pv1, new SecureRandom()));
+ e2.init(new ParametersWithRandom(pv2, new SecureRandom()));
+
+ BigInteger k1 = e1.calculateAgreement(pu2);
+ BigInteger k2 = e2.calculateAgreement(pu1);
+
+ if (!k1.equals(k2))
+ {
+ fail("basic with random 2-way test failed");
+ }
+ }
+
+ private DHBasicKeyPairGenerator getDHBasicKeyPairGenerator(
+ BigInteger g,
+ BigInteger p,
+ int privateValueSize)
+ {
+ DHParameters dhParams = new DHParameters(p, g, null, privateValueSize);
+ DHKeyGenerationParameters params = new DHKeyGenerationParameters(new SecureRandom(), dhParams);
+ DHBasicKeyPairGenerator kpGen = new DHBasicKeyPairGenerator();
+
+ kpGen.init(params);
+
+ return kpGen;
+ }
+
+ private DHKeyPairGenerator getDHKeyPairGenerator(
+ BigInteger g,
+ BigInteger p)
+ {
+ DHParameters dhParams = new DHParameters(p, g);
+ DHKeyGenerationParameters params = new DHKeyGenerationParameters(new SecureRandom(), dhParams);
+ DHKeyPairGenerator kpGen = new DHKeyPairGenerator();
+
+ kpGen.init(params);
+
+ return kpGen;
+ }
+
+ /**
+ * this test is can take quiet a while
+ */
+ private void testGeneration(
+ int size)
+ {
+ DHParametersGenerator pGen = new DHParametersGenerator();
+
+ pGen.init(size, 10, new SecureRandom());
+
+ DHParameters dhParams = pGen.generateParameters();
+
+ if (dhParams.getL() != 0)
+ {
+ fail("DHParametersGenerator failed to set J to 0 in generated DHParameters");
+ }
+
+ DHKeyGenerationParameters params = new DHKeyGenerationParameters(new SecureRandom(), dhParams);
+
+ DHBasicKeyPairGenerator kpGen = new DHBasicKeyPairGenerator();
+
+ kpGen.init(params);
+
+ //
+ // generate first pair
+ //
+ AsymmetricCipherKeyPair pair = kpGen.generateKeyPair();
+
+ DHPublicKeyParameters pu1 = (DHPublicKeyParameters)pair.getPublic();
+ DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.getPrivate();
+
+ //
+ // generate second pair
+ //
+ params = new DHKeyGenerationParameters(new SecureRandom(), pu1.getParameters());
+
+ kpGen.init(params);
+
+ pair = kpGen.generateKeyPair();
+
+ DHPublicKeyParameters pu2 = (DHPublicKeyParameters)pair.getPublic();
+ DHPrivateKeyParameters pv2 = (DHPrivateKeyParameters)pair.getPrivate();
+
+ //
+ // two way
+ //
+ DHBasicAgreement e1 = new DHBasicAgreement();
+ DHBasicAgreement e2 = new DHBasicAgreement();
+
+ e1.init(new ParametersWithRandom(pv1, new SecureRandom()));
+ e2.init(new ParametersWithRandom(pv2, new SecureRandom()));
+
+ BigInteger k1 = e1.calculateAgreement(pu2);
+ BigInteger k2 = e2.calculateAgreement(pu1);
+
+ if (!k1.equals(k2))
+ {
+ fail("basic with " + size + " bit 2-way test failed");
+ }
+ }
+ private void testBounds()
+ {
+ BigInteger p1 = new BigInteger("00C8028E9151C6B51BCDB35C1F6B2527986A72D8546AE7A4BF41DC4289FF9837EE01592D36C324A0F066149B8B940C86C87D194206A39038AE3396F8E12435BB74449B70222D117B8A2BB77CB0D67A5D664DDE7B75E0FEC13CE0CAF258DAF3ADA0773F6FF0F2051D1859929AAA53B07809E496B582A89C3D7DA8B6E38305626621", 16);
+ BigInteger g1 = new BigInteger("1F869713181464577FE4026B47102FA0D7675503A4FCDA810881FAEC3524E6DBAEA9B96561EF7F8BEA76466DF11C2F3EB1A90CC5851735BF860606481257EECE6418C0204E61004E85D7131CE54BCBC7AD67E53C79DCB715E7C8D083DCD85D728283EC8F96839B4C9FA7C0727C472BEB94E4613CAFA8D580119C0AF4BF8AF252", 16);
+ int l1 = 1023;
+
+ BigInteger p2 = new BigInteger("00B333C98720220CC3946F494E25231B3E19F9AD5F6B19F4E7ABF80D8826C491C3224D4F7415A14A7C11D1BE584405FED12C3554F103E56A72D986CA5E325BB9DE07AC37D1EAE5E5AC724D32EF638F0E4462D4C1FC7A45B9FD3A5DF5EC36A1FA4DAA3FBB66AA42B1B71DF416AB547E987513426C7BB8634F5F4D37705514FDC1E1", 16);
+ BigInteger g2 = new BigInteger("2592F5A99FE46313650CCE66C94C15DBED9F4A45BD05C329986CF5D3E12139F0405A47C6385FEA27BFFEDC4CBABC5BB151F3BEE7CC3D51567F1E2B12A975AA9F48A70BDAAE7F5B87E70ADCF902490A3CBEFEDA41EBA8E12E02B56120B5FDEFBED07F5EAD3AE020DF3C8233216F8F0D35E13A7AE4DA5CBCC0D91EADBF20C281C6", 16);
+ int l2 = 1024;
+
+ DHKeyGenerationParameters params1 = new DHKeyGenerationParameters(new SecureRandom(), new DHParameters(p1, g1, null, l1));
+ DHKeyGenerationParameters params2 = new DHKeyGenerationParameters(new SecureRandom(), new DHParameters(p2, g2, null, l2));
+
+ DHBasicKeyPairGenerator kpGen = new DHBasicKeyPairGenerator();
+
+ kpGen.init(params1);
+ kpGen.init(params2);
+ }
+
+ public void performTest()
+ {
+ testDHBasic(512, 0, g512, p512);
+ testDHBasic(768, 0, g768, p768);
+ testDHBasic(1024, 0, g1024, p1024);
+
+ testDHBasic(512, 64, g512, p512);
+ testDHBasic(768, 128, g768, p768);
+ testDHBasic(1024, 256, g1024, p1024);
+
+ testDH(512, g512, p512);
+ testDH(768, g768, p768);
+ testDH(1024, g1024, p1024);
+
+ testBounds();
+
+ //
+ // generation test.
+ //
+ testGeneration(256);
+
+ //
+ // with random test
+ //
+ DHBasicKeyPairGenerator kpBasicGen = getDHBasicKeyPairGenerator(g512, p512, 0);
+
+ testSimpleWithRandom(kpBasicGen);
+
+ DHKeyPairGenerator kpGen = getDHKeyPairGenerator(g512, p512);
+
+ testGPWithRandom(kpGen);
+
+ //
+ // parameter tests
+ //
+ DHAgreement dh = new DHAgreement();
+ AsymmetricCipherKeyPair dhPair = kpGen.generateKeyPair();
+
+ try
+ {
+ dh.init(dhPair.getPublic());
+ fail("DHAgreement key check failed");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // ignore
+ }
+
+ DHKeyPairGenerator kpGen768 = getDHKeyPairGenerator(g768, p768);
+
+ try
+ {
+ dh.init(dhPair.getPrivate());
+
+ dh.calculateAgreement((DHPublicKeyParameters)kpGen768.generateKeyPair().getPublic(), BigInteger.valueOf(100));
+
+ fail("DHAgreement agreement check failed");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // ignore
+ }
+
+ DHBasicAgreement dhBasic = new DHBasicAgreement();
+ AsymmetricCipherKeyPair dhBasicPair = kpBasicGen.generateKeyPair();
+
+ try
+ {
+ dhBasic.init(dhBasicPair.getPublic());
+ fail("DHBasicAgreement key check failed");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ DHBasicKeyPairGenerator kpBasicGen768 = getDHBasicKeyPairGenerator(g768, p768, 0);
+
+ try
+ {
+ dhBasic.init(dhPair.getPrivate());
+
+ dhBasic.calculateAgreement((DHPublicKeyParameters)kpBasicGen768.generateKeyPair().getPublic());
+
+ fail("DHBasicAgreement agreement check failed");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new DHTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/DSATest.java b/core/src/test/java/org/spongycastle/crypto/test/DSATest.java
new file mode 100644
index 00000000..3d91dee9
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/DSATest.java
@@ -0,0 +1,602 @@
+package org.spongycastle.crypto.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.digests.SHA224Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.generators.DSAKeyPairGenerator;
+import org.spongycastle.crypto.generators.DSAParametersGenerator;
+import org.spongycastle.crypto.params.DSAKeyGenerationParameters;
+import org.spongycastle.crypto.params.DSAParameterGenerationParameters;
+import org.spongycastle.crypto.params.DSAParameters;
+import org.spongycastle.crypto.params.DSAPrivateKeyParameters;
+import org.spongycastle.crypto.params.DSAPublicKeyParameters;
+import org.spongycastle.crypto.params.DSAValidationParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.signers.DSASigner;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.BigIntegers;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.FixedSecureRandom;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * Test based on FIPS 186-2, Appendix 5, an example of DSA, and FIPS 168-3 test vectors.
+ */
+public class DSATest
+ extends SimpleTest
+{
+ byte[] k1 = Hex.decode("d5014e4b60ef2ba8b6211b4062ba3224e0427dd3");
+ byte[] k2 = Hex.decode("345e8d05c075c3a508df729a1685690e68fcfb8c8117847e89063bca1f85d968fd281540b6e13bd1af989a1fbf17e06462bf511f9d0b140fb48ac1b1baa5bded");
+
+ SecureRandom random = new FixedSecureRandom(new byte[][] { k1, k2});
+
+ byte[] keyData = Hex.decode("b5014e4b60ef2ba8b6211b4062ba3224e0427dd3");
+
+ SecureRandom keyRandom = new FixedSecureRandom(new byte[][] { keyData, keyData });
+
+ BigInteger pValue = new BigInteger("8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291", 16);
+ BigInteger qValue = new BigInteger("c773218c737ec8ee993b4f2ded30f48edace915f", 16);
+
+ public String getName()
+ {
+ return "DSA";
+ }
+
+ public void performTest()
+ {
+ BigInteger r = new BigInteger("68076202252361894315274692543577577550894681403");
+ BigInteger s = new BigInteger("1089214853334067536215539335472893651470583479365");
+ DSAParametersGenerator pGen = new DSAParametersGenerator();
+
+ pGen.init(512, 80, random);
+
+ DSAParameters params = pGen.generateParameters();
+ DSAValidationParameters pValid = params.getValidationParameters();
+
+ if (pValid.getCounter() != 105)
+ {
+ fail("Counter wrong");
+ }
+
+ if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
+ {
+ fail("p or q wrong");
+ }
+
+ DSAKeyPairGenerator dsaKeyGen = new DSAKeyPairGenerator();
+ DSAKeyGenerationParameters genParam = new DSAKeyGenerationParameters(keyRandom, params);
+
+ dsaKeyGen.init(genParam);
+
+ AsymmetricCipherKeyPair pair = dsaKeyGen.generateKeyPair();
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), keyRandom);
+
+ DSASigner dsa = new DSASigner();
+
+ dsa.init(true, param);
+
+ byte[] message = BigIntegers.asUnsignedByteArray(new BigInteger("968236873715988614170569073515315707566766479517"));
+ BigInteger[] sig = dsa.generateSignature(message);
+
+ if (!r.equals(sig[0]))
+ {
+ fail("r component wrong.", r, sig[0]);
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ fail("s component wrong.", s, sig[1]);
+ }
+
+ dsa.init(false, pair.getPublic());
+
+ if (!dsa.verifySignature(message, sig[0], sig[1]))
+ {
+ fail("verification fails");
+ }
+
+ dsa2Test1();
+ dsa2Test2();
+ dsa2Test3();
+ dsa2Test4();
+ }
+
+ private void dsa2Test1()
+ {
+ byte[] seed = Hex.decode("ED8BEE8D1CB89229D2903CBF0E51EE7377F48698");
+
+ DSAParametersGenerator pGen = new DSAParametersGenerator();
+
+ pGen.init(new DSAParameterGenerationParameters(1024, 160, 80, new DSATestSecureRandom(seed)));
+
+ DSAParameters params = pGen.generateParameters();
+
+ DSAValidationParameters pv = params.getValidationParameters();
+
+ if (pv.getCounter() != 5)
+ {
+ fail("counter incorrect");
+ }
+
+ if (!Arrays.areEqual(seed, pv.getSeed()))
+ {
+ fail("seed incorrect");
+ }
+
+ if (!params.getQ().equals(new BigInteger("E950511EAB424B9A19A2AEB4E159B7844C589C4F", 16)))
+ {
+ fail("Q incorrect");
+ }
+
+ if (!params.getP().equals(new BigInteger(
+ "E0A67598CD1B763B" +
+ "C98C8ABB333E5DDA0CD3AA0E5E1FB5BA8A7B4EABC10BA338" +
+ "FAE06DD4B90FDA70D7CF0CB0C638BE3341BEC0AF8A7330A3" +
+ "307DED2299A0EE606DF035177A239C34A912C202AA5F83B9" +
+ "C4A7CF0235B5316BFC6EFB9A248411258B30B839AF172440" +
+ "F32563056CB67A861158DDD90E6A894C72A5BBEF9E286C6B", 16)))
+ {
+ fail("P incorrect");
+ }
+
+ if (!params.getG().equals(new BigInteger(
+ "D29D5121B0423C27" +
+ "69AB21843E5A3240FF19CACC792264E3BB6BE4F78EDD1B15" +
+ "C4DFF7F1D905431F0AB16790E1F773B5CE01C804E509066A" +
+ "9919F5195F4ABC58189FD9FF987389CB5BEDF21B4DAB4F8B" +
+ "76A055FFE2770988FE2EC2DE11AD92219F0B351869AC24DA" +
+ "3D7BA87011A701CE8EE7BFE49486ED4527B7186CA4610A75", 16)))
+ {
+ fail("G incorrect");
+ }
+
+ DSAKeyPairGenerator kpGen = new DSAKeyPairGenerator();
+
+ kpGen.init(new DSAKeyGenerationParameters(new FixedSecureRandom(Hex.decode("D0EC4E50BB290A42E9E355C73D8809345DE2E139")), params));
+
+ AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();
+
+ DSAPublicKeyParameters pub = (DSAPublicKeyParameters)kp.getPublic();
+ DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)kp.getPrivate();
+
+ if (!pub.getY().equals(new BigInteger(
+ "25282217F5730501" +
+ "DD8DBA3EDFCF349AAFFEC20921128D70FAC44110332201BB" +
+ "A3F10986140CBB97C726938060473C8EC97B4731DB004293" +
+ "B5E730363609DF9780F8D883D8C4D41DED6A2F1E1BBBDC97" +
+ "9E1B9D6D3C940301F4E978D65B19041FCF1E8B518F5C0576" +
+ "C770FE5A7A485D8329EE2914A2DE1B5DA4A6128CEAB70F79", 16)))
+ {
+ fail("Y value incorrect");
+ }
+
+ if (!priv.getX().equals(
+ new BigInteger("D0EC4E50BB290A42E9E355C73D8809345DE2E139", 16)))
+ {
+ fail("X value incorrect");
+ }
+
+ DSASigner signer = new DSASigner();
+
+ signer.init(true, new ParametersWithRandom(kp.getPrivate(), new FixedSecureRandom(Hex.decode("349C55648DCF992F3F33E8026CFAC87C1D2BA075"))));
+
+ byte[] msg = Hex.decode("A9993E364706816ABA3E25717850C26C9CD0D89D");
+
+ BigInteger[] sig = signer.generateSignature(msg);
+
+ if (!sig[0].equals(new BigInteger("636155AC9A4633B4665D179F9E4117DF68601F34", 16)))
+ {
+ fail("R value incorrect");
+ }
+
+ if (!sig[1].equals(new BigInteger("6C540B02D9D4852F89DF8CFC99963204F4347704", 16)))
+ {
+ fail("S value incorrect");
+ }
+
+ signer.init(false, kp.getPublic());
+
+ if (!signer.verifySignature(msg, sig[0], sig[1]))
+ {
+ fail("signature not verified");
+ }
+
+ }
+
+ private void dsa2Test2()
+ {
+ byte[] seed = Hex.decode("5AFCC1EFFC079A9CCA6ECA86D6E3CC3B18642D9BE1CC6207C84002A9");
+
+ DSAParametersGenerator pGen = new DSAParametersGenerator(new SHA224Digest());
+
+ pGen.init(new DSAParameterGenerationParameters(2048, 224, 80, new DSATestSecureRandom(seed)));
+
+ DSAParameters params = pGen.generateParameters();
+
+ DSAValidationParameters pv = params.getValidationParameters();
+
+ if (pv.getCounter() != 21)
+ {
+ fail("counter incorrect");
+ }
+
+ if (!Arrays.areEqual(seed, pv.getSeed()))
+ {
+ fail("seed incorrect");
+ }
+
+ if (!params.getQ().equals(new BigInteger("90EAF4D1AF0708B1B612FF35E0A2997EB9E9D263C9CE659528945C0D", 16)))
+ {
+ fail("Q incorrect");
+ }
+
+ if (!params.getP().equals(new BigInteger(
+ "C196BA05AC29E1F9C3C72D56DFFC6154" +
+ "A033F1477AC88EC37F09BE6C5BB95F51C296DD20D1A28A06" +
+ "7CCC4D4316A4BD1DCA55ED1066D438C35AEBAABF57E7DAE4" +
+ "28782A95ECA1C143DB701FD48533A3C18F0FE23557EA7AE6" +
+ "19ECACC7E0B51652A8776D02A425567DED36EABD90CA33A1" +
+ "E8D988F0BBB92D02D1D20290113BB562CE1FC856EEB7CDD9" +
+ "2D33EEA6F410859B179E7E789A8F75F645FAE2E136D252BF" +
+ "FAFF89528945C1ABE705A38DBC2D364AADE99BE0D0AAD82E" +
+ "5320121496DC65B3930E38047294FF877831A16D5228418D" +
+ "E8AB275D7D75651CEFED65F78AFC3EA7FE4D79B35F62A040" +
+ "2A1117599ADAC7B269A59F353CF450E6982D3B1702D9CA83", 16)))
+ {
+ fail("P incorrect");
+ }
+
+ if (!params.getG().equals(new BigInteger(
+ "A59A749A11242C58C894E9E5A91804E8"+
+ "FA0AC64B56288F8D47D51B1EDC4D65444FECA0111D78F35F"+
+ "C9FDD4CB1F1B79A3BA9CBEE83A3F811012503C8117F98E50"+
+ "48B089E387AF6949BF8784EBD9EF45876F2E6A5A495BE64B"+
+ "6E770409494B7FEE1DBB1E4B2BC2A53D4F893D418B715959"+
+ "2E4FFFDF6969E91D770DAEBD0B5CB14C00AD68EC7DC1E574"+
+ "5EA55C706C4A1C5C88964E34D09DEB753AD418C1AD0F4FDF"+
+ "D049A955E5D78491C0B7A2F1575A008CCD727AB376DB6E69"+
+ "5515B05BD412F5B8C2F4C77EE10DA48ABD53F5DD498927EE"+
+ "7B692BBBCDA2FB23A516C5B4533D73980B2A3B60E384ED20"+
+ "0AE21B40D273651AD6060C13D97FD69AA13C5611A51B9085", 16)))
+ {
+ fail("G incorrect");
+ }
+
+ DSAKeyPairGenerator kpGen = new DSAKeyPairGenerator();
+
+ kpGen.init(new DSAKeyGenerationParameters(new FixedSecureRandom(Hex.decode("00D0F09ED3E2568F6CADF9224117DA2AEC5A4300E009DE1366023E17")), params));
+
+ AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();
+
+ DSAPublicKeyParameters pub = (DSAPublicKeyParameters)kp.getPublic();
+ DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)kp.getPrivate();
+
+ if (!pub.getY().equals(new BigInteger(
+ "70035C9A3B225B258F16741F3941FBF0" +
+ "6F3D056CD7BD864604CBB5EE9DD85304EE8E8E4ABD5E9032" +
+ "11DDF25CE149075510ACE166970AFDC7DF552B7244F342FA" +
+ "02F7A621405B754909D757F97290E1FE5036E904CF593446" +
+ "0C046D95659821E1597ED9F2B1F0E20863A6BBD0CE74DACB" +
+ "A5D8C68A90B29C2157CDEDB82EC12B81EE3068F9BF5F7F34" +
+ "6ECA41ED174CCCD7D154FA4F42F80FFE1BF46AE9D8125DEB" +
+ "5B4BA08A72BDD86596DBEDDC9550FDD650C58F5AE5133509" +
+ "A702F79A31ECB490F7A3C5581631F7C5BE4FF7F9E9F27FA3" +
+ "90E47347AD1183509FED6FCF198BA9A71AB3335B4F38BE8D" +
+ "15496A00B6DC2263E20A5F6B662320A3A1EC033AA61E3B68", 16)))
+ {
+ fail("Y value incorrect");
+ }
+
+ if (!priv.getX().equals(
+ new BigInteger("00D0F09ED3E2568F6CADF9224117DA2AEC5A4300E009DE1366023E17", 16)))
+ {
+ fail("X value incorrect");
+ }
+
+ DSASigner signer = new DSASigner();
+
+ signer.init(true, new ParametersWithRandom(kp.getPrivate(), new FixedSecureRandom(Hex.decode("735959CC4463B8B440E407EECA8A473BF6A6D1FE657546F67D401F05"))));
+
+ byte[] msg = Hex.decode("23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7");
+
+ BigInteger[] sig = signer.generateSignature(msg);
+
+ if (!sig[0].equals(new BigInteger("4400138D05F9639CAF54A583CAAF25D2B76D0C3EAD752CE17DBC85FE", 16)))
+ {
+ fail("R value incorrect");
+ }
+
+ if (!sig[1].equals(new BigInteger("874D4F12CB13B61732D398445698CFA9D92381D938AA57EE2C9327B3", 16)))
+ {
+ fail("S value incorrect");
+ }
+
+ signer.init(false, kp.getPublic());
+
+ if (!signer.verifySignature(msg, sig[0], sig[1]))
+ {
+ fail("signature not verified");
+ }
+ }
+
+ private void dsa2Test3()
+ {
+ byte[] seed = Hex.decode("4783081972865EA95D43318AB2EAF9C61A2FC7BBF1B772A09017BDF5A58F4FF0");
+
+ DSAParametersGenerator pGen = new DSAParametersGenerator(new SHA256Digest());
+
+ pGen.init(new DSAParameterGenerationParameters(2048, 256, 80, new DSATestSecureRandom(seed)));
+
+ DSAParameters params = pGen.generateParameters();
+
+ DSAValidationParameters pv = params.getValidationParameters();
+
+ if (pv.getCounter() != 12)
+ {
+ fail("counter incorrect");
+ }
+
+ if (!Arrays.areEqual(seed, pv.getSeed()))
+ {
+ fail("seed incorrect");
+ }
+
+ if (!params.getQ().equals(new BigInteger("C24ED361870B61E0D367F008F99F8A1F75525889C89DB1B673C45AF5867CB467", 16)))
+ {
+ fail("Q incorrect");
+ }
+
+ if (!params.getP().equals(new BigInteger(
+ "F56C2A7D366E3EBDEAA1891FD2A0D099" +
+ "436438A673FED4D75F594959CFFEBCA7BE0FC72E4FE67D91" +
+ "D801CBA0693AC4ED9E411B41D19E2FD1699C4390AD27D94C" +
+ "69C0B143F1DC88932CFE2310C886412047BD9B1C7A67F8A2" +
+ "5909132627F51A0C866877E672E555342BDF9355347DBD43" +
+ "B47156B2C20BAD9D2B071BC2FDCF9757F75C168C5D9FC431" +
+ "31BE162A0756D1BDEC2CA0EB0E3B018A8B38D3EF2487782A" +
+ "EB9FBF99D8B30499C55E4F61E5C7DCEE2A2BB55BD7F75FCD" +
+ "F00E48F2E8356BDB59D86114028F67B8E07B127744778AFF" +
+ "1CF1399A4D679D92FDE7D941C5C85C5D7BFF91BA69F9489D" +
+ "531D1EBFA727CFDA651390F8021719FA9F7216CEB177BD75", 16)))
+ {
+ fail("P incorrect");
+ }
+
+ if (!params.getG().equals(new BigInteger(
+ "8DC6CC814CAE4A1C05A3E186A6FE27EA" +
+ "BA8CDB133FDCE14A963A92E809790CBA096EAA26140550C1" +
+ "29FA2B98C16E84236AA33BF919CD6F587E048C52666576DB" +
+ "6E925C6CBE9B9EC5C16020F9A44C9F1C8F7A8E611C1F6EC2" +
+ "513EA6AA0B8D0F72FED73CA37DF240DB57BBB27431D61869" +
+ "7B9E771B0B301D5DF05955425061A30DC6D33BB6D2A32BD0" +
+ "A75A0A71D2184F506372ABF84A56AEEEA8EB693BF29A6403" +
+ "45FA1298A16E85421B2208D00068A5A42915F82CF0B858C8" +
+ "FA39D43D704B6927E0B2F916304E86FB6A1B487F07D8139E" +
+ "428BB096C6D67A76EC0B8D4EF274B8A2CF556D279AD267CC" +
+ "EF5AF477AFED029F485B5597739F5D0240F67C2D948A6279", 16)))
+ {
+ fail("G incorrect");
+ }
+
+ DSAKeyPairGenerator kpGen = new DSAKeyPairGenerator();
+
+ kpGen.init(new DSAKeyGenerationParameters(new FixedSecureRandom(Hex.decode("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C")), params));
+
+ AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();
+
+ DSAPublicKeyParameters pub = (DSAPublicKeyParameters)kp.getPublic();
+ DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)kp.getPrivate();
+
+ if (!pub.getY().equals(new BigInteger(
+ "2828003D7C747199143C370FDD07A286" +
+ "1524514ACC57F63F80C38C2087C6B795B62DE1C224BF8D1D" +
+ "1424E60CE3F5AE3F76C754A2464AF292286D873A7A30B7EA" +
+ "CBBC75AAFDE7191D9157598CDB0B60E0C5AA3F6EBE425500" +
+ "C611957DBF5ED35490714A42811FDCDEB19AF2AB30BEADFF" +
+ "2907931CEE7F3B55532CFFAEB371F84F01347630EB227A41" +
+ "9B1F3F558BC8A509D64A765D8987D493B007C4412C297CAF" +
+ "41566E26FAEE475137EC781A0DC088A26C8804A98C23140E" +
+ "7C936281864B99571EE95C416AA38CEEBB41FDBFF1EB1D1D" +
+ "C97B63CE1355257627C8B0FD840DDB20ED35BE92F08C49AE" +
+ "A5613957D7E5C7A6D5A5834B4CB069E0831753ECF65BA02B", 16)))
+ {
+ fail("Y value incorrect");
+ }
+
+ if (!priv.getX().equals(
+ new BigInteger("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C", 16)))
+ {
+ fail("X value incorrect");
+ }
+
+ DSASigner signer = new DSASigner();
+
+ signer.init(true, new ParametersWithRandom(kp.getPrivate(), new FixedSecureRandom(Hex.decode("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C"))));
+
+ byte[] msg = Hex.decode("BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD");
+
+ BigInteger[] sig = signer.generateSignature(msg);
+
+ if (!sig[0].equals(new BigInteger("315C875DCD4850E948B8AC42824E9483A32D5BA5ABE0681B9B9448D444F2BE3C", 16)))
+ {
+ fail("R value incorrect");
+ }
+
+ if (!sig[1].equals(new BigInteger("89718D12E54A8D9ED066E4A55F7ED5A2229CD23B9A3CEE78F83ED6AA61F6BCB9", 16)))
+ {
+ fail("S value incorrect");
+ }
+
+ signer.init(false, kp.getPublic());
+
+ if (!signer.verifySignature(msg, sig[0], sig[1]))
+ {
+ fail("signature not verified");
+ }
+ }
+
+ private void dsa2Test4()
+ {
+ byte[] seed = Hex.decode("193AFCA7C1E77B3C1ECC618C81322E47B8B8B997C9C83515C59CC446C2D9BD47");
+
+ DSAParametersGenerator pGen = new DSAParametersGenerator(new SHA256Digest());
+
+ pGen.init(new DSAParameterGenerationParameters(3072, 256, 80, new DSATestSecureRandom(seed)));
+
+ DSAParameters params = pGen.generateParameters();
+
+ DSAValidationParameters pv = params.getValidationParameters();
+
+ if (pv.getCounter() != 20)
+ {
+ fail("counter incorrect");
+ }
+
+ if (!Arrays.areEqual(seed, pv.getSeed()))
+ {
+ fail("seed incorrect");
+ }
+
+ if (!params.getQ().equals(new BigInteger("CFA0478A54717B08CE64805B76E5B14249A77A4838469DF7F7DC987EFCCFB11D", 16)))
+ {
+ fail("Q incorrect");
+ }
+
+ if (!params.getP().equals(new BigInteger(
+ "90066455B5CFC38F9CAA4A48B4281F292C260FEEF01FD610" +
+ "37E56258A7795A1C7AD46076982CE6BB956936C6AB4DCFE0" +
+ "5E6784586940CA544B9B2140E1EB523F009D20A7E7880E4E" +
+ "5BFA690F1B9004A27811CD9904AF70420EEFD6EA11EF7DA1" +
+ "29F58835FF56B89FAA637BC9AC2EFAAB903402229F491D8D" +
+ "3485261CD068699B6BA58A1DDBBEF6DB51E8FE34E8A78E54" +
+ "2D7BA351C21EA8D8F1D29F5D5D15939487E27F4416B0CA63" +
+ "2C59EFD1B1EB66511A5A0FBF615B766C5862D0BD8A3FE7A0" +
+ "E0DA0FB2FE1FCB19E8F9996A8EA0FCCDE538175238FC8B0E" +
+ "E6F29AF7F642773EBE8CD5402415A01451A840476B2FCEB0" +
+ "E388D30D4B376C37FE401C2A2C2F941DAD179C540C1C8CE0" +
+ "30D460C4D983BE9AB0B20F69144C1AE13F9383EA1C08504F" +
+ "B0BF321503EFE43488310DD8DC77EC5B8349B8BFE97C2C56" +
+ "0EA878DE87C11E3D597F1FEA742D73EEC7F37BE43949EF1A" +
+ "0D15C3F3E3FC0A8335617055AC91328EC22B50FC15B941D3" +
+ "D1624CD88BC25F3E941FDDC6200689581BFEC416B4B2CB73", 16)))
+ {
+ fail("P incorrect");
+ }
+
+ if (!params.getG().equals(new BigInteger(
+ "5E5CBA992E0A680D885EB903AEA78E4A45A469103D448EDE" +
+ "3B7ACCC54D521E37F84A4BDD5B06B0970CC2D2BBB715F7B8" +
+ "2846F9A0C393914C792E6A923E2117AB805276A975AADB52" +
+ "61D91673EA9AAFFEECBFA6183DFCB5D3B7332AA19275AFA1" +
+ "F8EC0B60FB6F66CC23AE4870791D5982AAD1AA9485FD8F4A" +
+ "60126FEB2CF05DB8A7F0F09B3397F3937F2E90B9E5B9C9B6" +
+ "EFEF642BC48351C46FB171B9BFA9EF17A961CE96C7E7A7CC" +
+ "3D3D03DFAD1078BA21DA425198F07D2481622BCE45969D9C" +
+ "4D6063D72AB7A0F08B2F49A7CC6AF335E08C4720E31476B6" +
+ "7299E231F8BD90B39AC3AE3BE0C6B6CACEF8289A2E2873D5" +
+ "8E51E029CAFBD55E6841489AB66B5B4B9BA6E2F784660896" +
+ "AFF387D92844CCB8B69475496DE19DA2E58259B090489AC8" +
+ "E62363CDF82CFD8EF2A427ABCD65750B506F56DDE3B98856" +
+ "7A88126B914D7828E2B63A6D7ED0747EC59E0E0A23CE7D8A" +
+ "74C1D2C2A7AFB6A29799620F00E11C33787F7DED3B30E1A2" +
+ "2D09F1FBDA1ABBBFBF25CAE05A13F812E34563F99410E73B", 16)))
+ {
+ fail("G incorrect");
+ }
+
+ DSAKeyPairGenerator kpGen = new DSAKeyPairGenerator();
+
+ kpGen.init(new DSAKeyGenerationParameters(new FixedSecureRandom(Hex.decode("3ABC1587297CE7B9EA1AD6651CF2BC4D7F92ED25CABC8553F567D1B40EBB8764")), params));
+
+ AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();
+
+ DSAPublicKeyParameters pub = (DSAPublicKeyParameters)kp.getPublic();
+ DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)kp.getPrivate();
+
+ if (!pub.getY().equals(new BigInteger(
+ "8B891C8692D3DE875879390F2698B26FBECCA6B075535DCE" +
+ "6B0C862577F9FA0DEF6074E7A7624121224A595896ABD4CD" +
+ "A56B2CEFB942E025D2A4282FFAA98A48CDB47E1A6FCB5CFB" +
+ "393EF35AF9DF913102BB303C2B5C36C3F8FC04ED7B8B69FE" +
+ "FE0CF3E1FC05CFA713B3435B2656E913BA8874AEA9F93600" +
+ "6AEB448BCD005D18EC3562A33D04CF25C8D3D69844343442" +
+ "FA3DB7DE618C5E2DA064573E61E6D5581BFB694A23AC87FD" +
+ "5B52D62E954E1376DB8DDB524FFC0D469DF978792EE44173" +
+ "8E5DB05A7DC43E94C11A2E7A4FBE383071FA36D2A7EC8A93" +
+ "88FE1C4F79888A99D3B6105697C2556B79BB4D7E781CEBB3" +
+ "D4866AD825A5E830846072289FDBC941FA679CA82F5F78B7" +
+ "461B2404DB883D215F4E0676CF5493950AC5591697BFEA8D" +
+ "1EE6EC016B89BA51CAFB5F9C84C989FA117375E94578F28B" +
+ "E0B34CE0545DA46266FD77F62D8F2CEE92AB77012AFEBC11" +
+ "008985A821CD2D978C7E6FE7499D1AAF8DE632C21BB48CA5" +
+ "CBF9F31098FD3FD3854C49A65D9201744AACE540354974F9", 16)))
+ {
+ fail("Y value incorrect");
+ }
+
+ if (!priv.getX().equals(
+ new BigInteger("3ABC1587297CE7B9EA1AD6651CF2BC4D7F92ED25CABC8553F567D1B40EBB8764", 16)))
+ {
+ fail("X value incorrect");
+ }
+
+ DSASigner signer = new DSASigner();
+
+ signer.init(true, new ParametersWithRandom(kp.getPrivate(), new FixedSecureRandom(Hex.decode("A6902C1E6E3943C5628061588A8B007BCCEA91DBF12915483F04B24AB0678BEE"))));
+
+ byte[] msg = Hex.decode("BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD");
+
+ BigInteger[] sig = signer.generateSignature(msg);
+
+ if (!sig[0].equals(new BigInteger("5F184E645A38BE8FB4A6871B6503A9D12924C7ABE04B71410066C2ECA6E3BE3E", 16)))
+ {
+ fail("R value incorrect");
+ }
+
+ if (!sig[1].equals(new BigInteger("91EB0C7BA3D4B9B60B825C3D9F2CADA8A2C9D7723267B033CBCDCF8803DB9C18", 16)))
+ {
+ fail("S value incorrect");
+ }
+
+ signer.init(false, kp.getPublic());
+
+ if (!signer.verifySignature(msg, sig[0], sig[1]))
+ {
+ fail("signature not verified");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new DSATest());
+ }
+
+ private class DSATestSecureRandom
+ extends FixedSecureRandom
+ {
+ private boolean first = true;
+
+ public DSATestSecureRandom(byte[] value)
+ {
+ super(value);
+ }
+
+ public void nextBytes(byte[] bytes)
+ {
+ if (first)
+ {
+ super.nextBytes(bytes);
+ first = false;
+ }
+ else
+ {
+ bytes[bytes.length - 1] = 2;
+ }
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/DSTU4145Test.java b/core/src/test/java/org/spongycastle/crypto/test/DSTU4145Test.java
new file mode 100644
index 00000000..43d27f09
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/DSTU4145Test.java
@@ -0,0 +1,278 @@
+package org.spongycastle.crypto.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.signers.DSTU4145Signer;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.FixedSecureRandom;
+import org.spongycastle.util.test.SimpleTest;
+
+public class DSTU4145Test
+ extends SimpleTest
+{
+ private static final BigInteger ZERO = BigInteger.valueOf(0);
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ public static void main(String[] args)
+ {
+ runTest(new DSTU4145Test());
+ }
+
+ public String getName()
+ {
+ return "DSTU4145";
+ }
+
+ private void test163()
+ throws Exception
+ {
+ SecureRandom random = new FixedSecureRandom(Hex.decode("01025e40bd97db012b7a1d79de8e12932d247f61c6"));
+
+ byte[] hash = Hex.decode("09c9c44277910c9aaee486883a2eb95b7180166ddf73532eeb76edaef52247ff");
+ for (int i = 0; i < hash.length / 2; i++)
+ {
+ byte tmp = hash[i];
+ hash[i] = hash[hash.length - 1 - i];
+ hash[hash.length - 1 - i] = tmp;
+ }
+
+ BigInteger r = new BigInteger("274ea2c0caa014a0d80a424f59ade7a93068d08a7", 16);
+ BigInteger s = new BigInteger("2100d86957331832b8e8c230f5bd6a332b3615aca", 16);
+
+ ECCurve.F2m curve = new ECCurve.F2m(163, 3, 6, 7, ONE, new BigInteger("5FF6108462A2DC8210AB403925E638A19C1455D21", 16));
+ ECPoint P = curve.createPoint(new BigInteger("72d867f93a93ac27df9ff01affe74885c8c540420", 16), new BigInteger("0224a9c3947852b97c5599d5f4ab81122adc3fd9b", 16));
+ BigInteger n = new BigInteger("400000000000000000002BEC12BE2262D39BCF14D", 16);
+
+ BigInteger d = new BigInteger("183f60fdf7951ff47d67193f8d073790c1c9b5a3e", 16);
+ ECPoint Q = P.multiply(d).negate();
+
+ ECDomainParameters domain = new ECDomainParameters(curve, P, n);
+ CipherParameters privKey = new ParametersWithRandom(new ECPrivateKeyParameters(d, domain), random);
+ ECPublicKeyParameters pubKey = new ECPublicKeyParameters(Q, domain);
+
+ DSTU4145Signer dstuSigner = new DSTU4145Signer();
+ dstuSigner.init(true, privKey);
+ BigInteger[] rs = dstuSigner.generateSignature(hash);
+
+ if (rs[0].compareTo(r) != 0)
+ {
+ fail("r component wrong");
+ }
+
+ if (rs[1].compareTo(s) != 0)
+ {
+ fail("s component wrong");
+ }
+
+ dstuSigner.init(false, pubKey);
+ if (!dstuSigner.verifySignature(hash, r, s))
+ {
+ fail("verification fails");
+ }
+ }
+
+ private void test173()
+ throws Exception
+ {
+ SecureRandom random = new FixedSecureRandom(Hex.decode("0000137449348C1249971759D99C252FFE1E14D8B31F"));
+
+ byte[] hash = Hex.decode("0137187EA862117EF1484289470ECAC802C5A651FDA8");
+ for (int i = 0; i < hash.length / 2; i++)
+ {
+ byte tmp = hash[i];
+ hash[i] = hash[hash.length - 1 - i];
+ hash[hash.length - 1 - i] = tmp;
+ }
+
+ BigInteger r = new BigInteger("13ae89746386709cdbd237cc5ec20ca30004a82ead8", 16);
+ BigInteger s = new BigInteger("3597912cdd093b3e711ccb74a79d3c4ab4c7cccdc60", 16);
+
+ ECCurve.F2m curve = new ECCurve.F2m(173, 1, 2, 10, ZERO, new BigInteger("108576C80499DB2FC16EDDF6853BBB278F6B6FB437D9", 16));
+ ECPoint P = curve.createPoint(new BigInteger("BE6628EC3E67A91A4E470894FBA72B52C515F8AEE9", 16), new BigInteger("D9DEEDF655CF5412313C11CA566CDC71F4DA57DB45C", 16));
+ BigInteger n = new BigInteger("800000000000000000000189B4E67606E3825BB2831", 16);
+
+ BigInteger d = new BigInteger("955CD7E344303D1034E66933DC21C8044D42ADB8", 16);
+ ECPoint Q = P.multiply(d).negate();
+
+ ECDomainParameters domain = new ECDomainParameters(curve, P, n);
+ CipherParameters privKey = new ParametersWithRandom(new ECPrivateKeyParameters(d, domain), random);
+ ECPublicKeyParameters pubKey = new ECPublicKeyParameters(Q, domain);
+
+ DSTU4145Signer dstuSigner = new DSTU4145Signer();
+ dstuSigner.init(true, privKey);
+ BigInteger[] rs = dstuSigner.generateSignature(hash);
+
+ if (rs[0].compareTo(r) != 0)
+ {
+ fail("r component wrong");
+ }
+
+ if (rs[1].compareTo(s) != 0)
+ {
+ fail("s component wrong");
+ }
+
+ dstuSigner.init(false, pubKey);
+ if (!dstuSigner.verifySignature(hash, r, s))
+ {
+ fail("verification fails");
+ }
+ }
+
+ private void test283()
+ throws Exception
+ {
+ SecureRandom random = new FixedSecureRandom(Hex.decode("00000000245383CB3AD41BF30F5F7E8FBA858509B2D5558C92D539A6D994BFA98BC6940E"));
+
+ byte[] hash = Hex.decode("0137187EA862117EF1484289470ECAC802C5A651FDA8");
+ for (int i = 0; i < hash.length / 2; i++)
+ {
+ byte tmp = hash[i];
+ hash[i] = hash[hash.length - 1 - i];
+ hash[hash.length - 1 - i] = tmp;
+ }
+
+ BigInteger r = new BigInteger("12a5edcc38d92208ff23036d75b000c7e4bc0f9af2d40b35f15d6fd15e01234e67781a8", 16);
+ BigInteger s = new BigInteger("2de0775577f75b643cf5afc80d4fe10b21100690f17e2cab7bdc9b50ec87c5727aeb515", 16);
+
+ ECCurve.F2m curve = new ECCurve.F2m(283, 5, 7, 12, ONE, new BigInteger("27B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5", 16));
+ ECPoint P = curve.createPoint(new BigInteger("4D95820ACE761110824CE425C8089129487389B7F0E0A9D043DDC0BB0A4CC9EB25", 16), new BigInteger("954C9C4029B2C62DE35C2B9C2A164984BF1101951E3A68ED03DF234DDE5BB2013152F2", 16));
+ BigInteger n = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307", 16);
+
+ BigInteger d = new BigInteger("B844EEAF15213E4BAD4FB84796D68F2448DB8EB7B4621EC0D51929874892C43E", 16);
+ ECPoint Q = P.multiply(d).negate();
+
+ ECDomainParameters domain = new ECDomainParameters(curve, P, n);
+ CipherParameters privKey = new ParametersWithRandom(new ECPrivateKeyParameters(d, domain), random);
+ ECPublicKeyParameters pubKey = new ECPublicKeyParameters(Q, domain);
+
+ DSTU4145Signer dstuSigner = new DSTU4145Signer();
+ dstuSigner.init(true, privKey);
+ BigInteger[] rs = dstuSigner.generateSignature(hash);
+
+ if (rs[0].compareTo(r) != 0)
+ {
+ fail("r component wrong");
+ }
+
+ if (rs[1].compareTo(s) != 0)
+ {
+ fail("s component wrong");
+ }
+
+ dstuSigner.init(false, pubKey);
+ if (!dstuSigner.verifySignature(hash, r, s))
+ {
+ fail("verification fails");
+ }
+ }
+
+ private void test431()
+ throws Exception
+ {
+ SecureRandom random = new FixedSecureRandom(Hex.decode("0000C4224DBBD800988DBAA39DE838294C345CDA5F5929D1174AA8D9340A5E79D10ACADE6B53CF873E7301A3871C2073AD75AB530457"));
+
+ byte[] hash = Hex.decode("0137187EA862117EF1484289470ECAC802C5A651FDA8");
+ for (int i = 0; i < hash.length / 2; i++)
+ {
+ byte tmp = hash[i];
+ hash[i] = hash[hash.length - 1 - i];
+ hash[hash.length - 1 - i] = tmp;
+ }
+
+ BigInteger r = new BigInteger("1911fefb1f494bebcf8dffdf5276946ff9c9f662192ee18c718db47310a439c784fe07577b16e1edbe16179876e0792a634f1c9c3a2e", 16);
+ BigInteger s = new BigInteger("3852170ee801c2083c52f1ea77b987a5432acecd9c654f064e87bf179e0a397151edbca430082e43bd38a67b55424b5bbc7f2713f620", 16);
+
+ ECCurve.F2m curve = new ECCurve.F2m(431, 1, 3, 5, ONE, new BigInteger("3CE10490F6A708FC26DFE8C3D27C4F94E690134D5BFF988D8D28AAEAEDE975936C66BAC536B18AE2DC312CA493117DAA469C640CAF3", 16));
+ ECPoint P = curve.createPoint(new BigInteger("9548BCDF314CEEEAF099C780FFEFBF93F9FE5B5F55547603C9C8FC1A2774170882B3BE35E892C6D4296B8DEA282EC30FB344272791", 16), new BigInteger("4C6CBD7C62A8EEEFDE17A8B5E196E49A22CE6DE128ABD9FBD81FA4411AD5A38E2A810BEDE09A7C6226BCDCB4A4A5DA37B4725E00AA74", 16));
+ BigInteger n = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBA3175458009A8C0A724F02F81AA8A1FCBAF80D90C7A95110504CF", 16);
+
+ BigInteger d = new BigInteger("D0F97354E314191FD773E2404F478C8AEE0FF5109F39E6F37D1FEEC8B2ED1691D84C9882CC729E716A71CC013F66CAC60E29E22C", 16);
+ ECPoint Q = P.multiply(d).negate();
+
+ ECDomainParameters domain = new ECDomainParameters(curve, P, n);
+ CipherParameters privKey = new ParametersWithRandom(new ECPrivateKeyParameters(d, domain), random);
+ ECPublicKeyParameters pubKey = new ECPublicKeyParameters(Q, domain);
+
+ DSTU4145Signer dstuSigner = new DSTU4145Signer();
+ dstuSigner.init(true, privKey);
+ BigInteger[] rs = dstuSigner.generateSignature(hash);
+
+ if (rs[0].compareTo(r) != 0)
+ {
+ fail("r component wrong");
+ }
+
+ if (rs[1].compareTo(s) != 0)
+ {
+ fail("s component wrong");
+ }
+
+ dstuSigner.init(false, pubKey);
+ if (!dstuSigner.verifySignature(hash, r, s))
+ {
+ fail("verification fails");
+ }
+ }
+
+ private void testTruncation()
+ {
+ SecureRandom random = new FixedSecureRandom(Hex.decode("0000C4224DBBD800988DBAA39DE838294C345CDA5F5929D1174AA8D9340A5E79D10ACADE6B53CF873E7301A3871C2073AD75AB530457"));
+
+ // use extra long "hash" with set bits...
+ byte[] hash = Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
+
+ ECCurve.F2m curve = new ECCurve.F2m(173, 1, 2, 10, ZERO, new BigInteger("108576C80499DB2FC16EDDF6853BBB278F6B6FB437D9", 16));
+ ECPoint P = curve.createPoint(new BigInteger("BE6628EC3E67A91A4E470894FBA72B52C515F8AEE9", 16), new BigInteger("D9DEEDF655CF5412313C11CA566CDC71F4DA57DB45C", 16));
+ BigInteger n = new BigInteger("800000000000000000000189B4E67606E3825BB2831", 16);
+
+ BigInteger d = new BigInteger("955CD7E344303D1034E66933DC21C8044D42ADB8", 16);
+ ECPoint Q = P.multiply(d).negate();
+
+ ECDomainParameters domain = new ECDomainParameters(curve, P, n);
+ CipherParameters privKey = new ParametersWithRandom(new ECPrivateKeyParameters(d, domain), random);
+ ECPublicKeyParameters pubKey = new ECPublicKeyParameters(Q, domain);
+
+ DSTU4145Signer dstuSigner = new DSTU4145Signer();
+ dstuSigner.init(true, privKey);
+ BigInteger[] rs = dstuSigner.generateSignature(hash);
+
+ BigInteger r = new BigInteger("6bb5c0cb82e5067485458ebfe81025f03b687c63a27", 16);
+ BigInteger s = new BigInteger("34d6b1868969b86ecf934167c8fe352c63d1074bd", 16);
+
+ if (rs[0].compareTo(r) != 0)
+ {
+ fail("r component wrong");
+ }
+
+ if (rs[1].compareTo(s) != 0)
+ {
+ fail("s component wrong");
+ }
+
+ dstuSigner.init(false, pubKey);
+ if (!dstuSigner.verifySignature(hash, rs[0], rs[1]))
+ {
+ fail("verification fails");
+ }
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ test163();
+ test173();
+ test283();
+ test431();
+ testTruncation();
+ }
+
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/DeterministicDSATest.java b/core/src/test/java/org/spongycastle/crypto/test/DeterministicDSATest.java
new file mode 100644
index 00000000..e5f61ec2
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/DeterministicDSATest.java
@@ -0,0 +1,513 @@
+package org.spongycastle.crypto.test;
+
+import java.math.BigInteger;
+
+import org.spongycastle.asn1.nist.NISTNamedCurves;
+import org.spongycastle.asn1.x9.X9ECParameters;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DSA;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA224Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.digests.SHA384Digest;
+import org.spongycastle.crypto.digests.SHA512Digest;
+import org.spongycastle.crypto.params.DSAParameters;
+import org.spongycastle.crypto.params.DSAPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.signers.DSASigner;
+import org.spongycastle.crypto.signers.ECDSASigner;
+import org.spongycastle.crypto.signers.HMacDSAKCalculator;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.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 DeterministicDSATest
+ 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()
+ {
+ DSAParameters dsaParameters = new DSAParameters(
+ new BigInteger("86F5CA03DCFEB225063FF830A0C769B9DD9D6153AD91D7CE27F787C43278B447" +
+ "E6533B86B18BED6E8A48B784A14C252C5BE0DBF60B86D6385BD2F12FB763ED88" +
+ "73ABFD3F5BA2E0A8C0A59082EAC056935E529DAF7C610467899C77ADEDFC846C" +
+ "881870B7B19B2B58F9BE0521A17002E3BDD6B86685EE90B3D9A1B02B782B1779", 16),
+ new BigInteger("996F967F6C8E388D9E28D01E205FBA957A5698B1", 16),
+ new BigInteger("07B0F92546150B62514BB771E2A0C0CE387F03BDA6C56B505209FF25FD3C133D" +
+ "89BBCD97E904E09114D9A7DEFDEADFC9078EA544D2E401AEECC40BB9FBBF78FD" +
+ "87995A10A1C27CB7789B594BA7EFB5C4326A9FE59A070E136DB77175464ADCA4" +
+ "17BE5DCE2F40D10A46A3A3943F26AB7FD9C0398FF8C76EE0A56826A8A88F1DBD", 16));
+
+ DSAPrivateKeyParameters privKey = new DSAPrivateKeyParameters(new BigInteger("411602CB19A6CCC34494D79D98EF1E7ED5AF25F7", 16), dsaParameters);
+
+ doTestHMACDetDSASample(new SHA1Digest(), privKey, new BigInteger("2E1A0C2562B2912CAAF89186FB0F42001585DA55", 16), new BigInteger("29EFB6B0AFF2D7A68EB70CA313022253B9A88DF5", 16));
+ doTestHMACDetDSASample(new SHA224Digest(), privKey, new BigInteger("4BC3B686AEA70145856814A6F1BB53346F02101E", 16), new BigInteger("410697B92295D994D21EDD2F4ADA85566F6F94C1", 16));
+ doTestHMACDetDSASample(new SHA256Digest(), privKey, new BigInteger("81F2F5850BE5BC123C43F71A3033E9384611C545", 16), new BigInteger("4CDD914B65EB6C66A8AAAD27299BEE6B035F5E89", 16));
+ doTestHMACDetDSASample(new SHA384Digest(), privKey, new BigInteger("07F2108557EE0E3921BC1774F1CA9B410B4CE65A", 16), new BigInteger("54DF70456C86FAC10FAB47C1949AB83F2C6F7595", 16));
+ doTestHMACDetDSASample(new SHA512Digest(), privKey, new BigInteger("16C3491F9B8C3FBBDD5E7A7B667057F0D8EE8E1B", 16), new BigInteger("02C36A127A7B89EDBB72E4FFBC71DABC7D4FC69C", 16));
+
+ doTestHMACDetDSATest(new SHA1Digest(), privKey, new BigInteger("42AB2052FD43E123F0607F115052A67DCD9C5C77", 16), new BigInteger("183916B0230D45B9931491D4C6B0BD2FB4AAF088", 16));
+ doTestHMACDetDSATest(new SHA224Digest(), privKey, new BigInteger("6868E9964E36C1689F6037F91F28D5F2C30610F2", 16), new BigInteger("49CEC3ACDC83018C5BD2674ECAAD35B8CD22940F", 16));
+ doTestHMACDetDSATest(new SHA256Digest(), privKey, new BigInteger("22518C127299B0F6FDC9872B282B9E70D0790812", 16), new BigInteger("6837EC18F150D55DE95B5E29BE7AF5D01E4FE160", 16));
+ doTestHMACDetDSATest(new SHA384Digest(), privKey, new BigInteger("854CF929B58D73C3CBFDC421E8D5430CD6DB5E66", 16), new BigInteger("91D0E0F53E22F898D158380676A871A157CDA622", 16));
+ doTestHMACDetDSATest(new SHA512Digest(), privKey, new BigInteger("8EA47E475BA8AC6F2D821DA3BD212D11A3DEB9A0", 16), new BigInteger("7C670C7AD72B6C050C109E1790008097125433E8", 16));
+
+ dsaParameters = new DSAParameters(
+ new BigInteger("9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48" +
+ "C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44F" +
+ "FE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5" +
+ "B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51743BF33050C38DE2" +
+ "35567E1B34C3D6A5C0CEAA1A0F368213C3D19843D0B4B09DCB9FC72D39C8DE41" +
+ "F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE" +
+ "92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA15" +
+ "3E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B", 16),
+ new BigInteger("F2C3119374CE76C9356990B465374A17F23F9ED35089BD969F61C6DDE9998C1F", 16),
+ new BigInteger("5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613" +
+ "D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C4" +
+ "6A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472" +
+ "085057F3494309FFA73C611F78B32ADBB5740C361C9F35BE90997DB2014E2EF5" +
+ "AA61782F52ABEB8BD6432C4DD097BC5423B285DAFB60DC364E8161F4A2A35ACA" +
+ "3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71" +
+ "BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0" +
+ "DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7", 16));
+
+ privKey = new DSAPrivateKeyParameters(new BigInteger("69C7548C21D0DFEA6B9A51C9EAD4E27C33D3B3F180316E5BCAB92C933F0E4DBC", 16), dsaParameters);
+
+ doTestHMACDetDSASample(new SHA1Digest(), privKey, new BigInteger("3A1B2DBD7489D6ED7E608FD036C83AF396E290DBD602408E8677DAABD6E7445A", 16), new BigInteger("D26FCBA19FA3E3058FFC02CA1596CDBB6E0D20CB37B06054F7E36DED0CDBBCCF", 16));
+ doTestHMACDetDSASample(new SHA224Digest(), privKey, new BigInteger("DC9F4DEADA8D8FF588E98FED0AB690FFCE858DC8C79376450EB6B76C24537E2C", 16), new BigInteger("A65A9C3BC7BABE286B195D5DA68616DA8D47FA0097F36DD19F517327DC848CEC", 16));
+ doTestHMACDetDSASample(new SHA256Digest(), privKey, new BigInteger("EACE8BDBBE353C432A795D9EC556C6D021F7A03F42C36E9BC87E4AC7932CC809", 16), new BigInteger("7081E175455F9247B812B74583E9E94F9EA79BD640DC962533B0680793A38D53", 16));
+ doTestHMACDetDSASample(new SHA384Digest(), privKey, new BigInteger("B2DA945E91858834FD9BF616EBAC151EDBC4B45D27D0DD4A7F6A22739F45C00B", 16), new BigInteger("19048B63D9FD6BCA1D9BAE3664E1BCB97F7276C306130969F63F38FA8319021B", 16));
+ doTestHMACDetDSASample(new SHA512Digest(), privKey, new BigInteger("2016ED092DC5FB669B8EFB3D1F31A91EECB199879BE0CF78F02BA062CB4C942E", 16), new BigInteger("D0C76F84B5F091E141572A639A4FB8C230807EEA7D55C8A154A224400AFF2351", 16));
+
+ doTestHMACDetDSATest(new SHA1Digest(), privKey, new BigInteger("C18270A93CFC6063F57A4DFA86024F700D980E4CF4E2CB65A504397273D98EA0", 16), new BigInteger("414F22E5F31A8B6D33295C7539C1C1BA3A6160D7D68D50AC0D3A5BEAC2884FAA", 16));
+ doTestHMACDetDSATest(new SHA224Digest(), privKey, new BigInteger("272ABA31572F6CC55E30BF616B7A265312018DD325BE031BE0CC82AA17870EA3", 16), new BigInteger("E9CC286A52CCE201586722D36D1E917EB96A4EBDB47932F9576AC645B3A60806", 16));
+ doTestHMACDetDSATest(new SHA256Digest(), privKey, new BigInteger("8190012A1969F9957D56FCCAAD223186F423398D58EF5B3CEFD5A4146A4476F0", 16), new BigInteger("7452A53F7075D417B4B013B278D1BB8BBD21863F5E7B1CEE679CF2188E1AB19E", 16));
+ doTestHMACDetDSATest(new SHA384Digest(), privKey, new BigInteger("239E66DDBE8F8C230A3D071D601B6FFBDFB5901F94D444C6AF56F732BEB954BE", 16), new BigInteger("6BD737513D5E72FE85D1C750E0F73921FE299B945AAD1C802F15C26A43D34961", 16));
+ doTestHMACDetDSATest(new SHA512Digest(), privKey, new BigInteger("89EC4BB1400ECCFF8E7D9AA515CD1DE7803F2DAFF09693EE7FD1353E90A68307", 16), new BigInteger("C9F0BDABCC0D880BB137A994CC7F3980CE91CC10FAF529FC46565B15CEA854E1", 16));
+ }
+
+ private void doTestHMACDetDSASample(Digest digest, DSAPrivateKeyParameters privKey, BigInteger r, BigInteger s)
+ {
+ doTestHMACDetECDSA(new DSASigner(new HMacDSAKCalculator(digest)), digest, SAMPLE, privKey, r, s);
+ }
+
+ private void doTestHMACDetDSATest(Digest digest, DSAPrivateKeyParameters privKey, BigInteger r, BigInteger s)
+ {
+ doTestHMACDetECDSA(new DSASigner(new HMacDSAKCalculator(digest)), digest, TEST, privKey, r, s);
+ }
+
+ // test vectors from appendix in RFC 6979
+ private void testECHMacDeterministic()
+ {
+ X9ECParameters x9ECParameters = NISTNamedCurves.getByName("P-192");
+ ECDomainParameters ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
+
+ ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(new BigInteger("6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4", 16), ecDomainParameters);
+
+ doTestHMACDetECDSASample(new SHA1Digest(), privKey, new BigInteger("98C6BD12B23EAF5E2A2045132086BE3EB8EBD62ABF6698FF", 16), new BigInteger("57A22B07DEA9530F8DE9471B1DC6624472E8E2844BC25B64", 16));
+ doTestHMACDetECDSASample(new SHA224Digest(), privKey, new BigInteger("A1F00DAD97AEEC91C95585F36200C65F3C01812AA60378F5", 16), new BigInteger("E07EC1304C7C6C9DEBBE980B9692668F81D4DE7922A0F97A", 16));
+ doTestHMACDetECDSASample(new SHA256Digest(), privKey, new BigInteger("4B0B8CE98A92866A2820E20AA6B75B56382E0F9BFD5ECB55", 16), new BigInteger("CCDB006926EA9565CBADC840829D8C384E06DE1F1E381B85", 16));
+ doTestHMACDetECDSASample(new SHA384Digest(), privKey, new BigInteger("DA63BF0B9ABCF948FBB1E9167F136145F7A20426DCC287D5", 16), new BigInteger("C3AA2C960972BD7A2003A57E1C4C77F0578F8AE95E31EC5E", 16));
+ doTestHMACDetECDSASample(new SHA512Digest(), privKey, new BigInteger("4D60C5AB1996BD848343B31C00850205E2EA6922DAC2E4B8", 16), new BigInteger("3F6E837448F027A1BF4B34E796E32A811CBB4050908D8F67", 16));
+
+ doTestHMACDetECDSATest(new SHA1Digest(), privKey, new BigInteger("0F2141A0EBBC44D2E1AF90A50EBCFCE5E197B3B7D4DE036D", 16), new BigInteger("EB18BC9E1F3D7387500CB99CF5F7C157070A8961E38700B7", 16));
+ doTestHMACDetECDSATest(new SHA224Digest(), privKey, new BigInteger("6945A1C1D1B2206B8145548F633BB61CEF04891BAF26ED34", 16), new BigInteger("B7FB7FDFC339C0B9BD61A9F5A8EAF9BE58FC5CBA2CB15293", 16));
+ doTestHMACDetECDSATest(new SHA256Digest(), privKey, new BigInteger("3A718BD8B4926C3B52EE6BBE67EF79B18CB6EB62B1AD97AE", 16), new BigInteger("5662E6848A4A19B1F1AE2F72ACD4B8BBE50F1EAC65D9124F", 16));
+ doTestHMACDetECDSATest(new SHA384Digest(), privKey, new BigInteger("B234B60B4DB75A733E19280A7A6034BD6B1EE88AF5332367", 16), new BigInteger("7994090B2D59BB782BE57E74A44C9A1C700413F8ABEFE77A", 16));
+ doTestHMACDetECDSATest(new SHA512Digest(), privKey, new BigInteger("FE4F4AE86A58B6507946715934FE2D8FF9D95B6B098FE739", 16), new BigInteger("74CF5605C98FBA0E1EF34D4B5A1577A7DCF59457CAE52290", 16));
+
+ x9ECParameters = NISTNamedCurves.getByName("P-224");
+ ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
+
+ privKey = new ECPrivateKeyParameters(new BigInteger("F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1", 16), ecDomainParameters);
+
+ doTestHMACDetECDSASample(new SHA1Digest(), privKey, new BigInteger("22226F9D40A96E19C4A301CE5B74B115303C0F3A4FD30FC257FB57AC", 16), new BigInteger("66D1CDD83E3AF75605DD6E2FEFF196D30AA7ED7A2EDF7AF475403D69", 16));
+ doTestHMACDetECDSASample(new SHA224Digest(), privKey, new BigInteger("1CDFE6662DDE1E4A1EC4CDEDF6A1F5A2FB7FBD9145C12113E6ABFD3E", 16), new BigInteger("A6694FD7718A21053F225D3F46197CA699D45006C06F871808F43EBC", 16));
+ doTestHMACDetECDSASample(new SHA256Digest(), privKey, new BigInteger("61AA3DA010E8E8406C656BC477A7A7189895E7E840CDFE8FF42307BA", 16), new BigInteger("BC814050DAB5D23770879494F9E0A680DC1AF7161991BDE692B10101", 16));
+ doTestHMACDetECDSASample(new SHA384Digest(), privKey, new BigInteger("0B115E5E36F0F9EC81F1325A5952878D745E19D7BB3EABFABA77E953", 16), new BigInteger("830F34CCDFE826CCFDC81EB4129772E20E122348A2BBD889A1B1AF1D", 16));
+ doTestHMACDetECDSASample(new SHA512Digest(), privKey, new BigInteger("074BD1D979D5F32BF958DDC61E4FB4872ADCAFEB2256497CDAC30397", 16), new BigInteger("A4CECA196C3D5A1FF31027B33185DC8EE43F288B21AB342E5D8EB084", 16));
+
+ doTestHMACDetECDSATest(new SHA1Digest(), privKey, new BigInteger("DEAA646EC2AF2EA8AD53ED66B2E2DDAA49A12EFD8356561451F3E21C", 16), new BigInteger("95987796F6CF2062AB8135271DE56AE55366C045F6D9593F53787BD2", 16));
+ doTestHMACDetECDSATest(new SHA224Digest(), privKey, new BigInteger("C441CE8E261DED634E4CF84910E4C5D1D22C5CF3B732BB204DBEF019", 16), new BigInteger("902F42847A63BDC5F6046ADA114953120F99442D76510150F372A3F4", 16));
+ doTestHMACDetECDSATest(new SHA256Digest(), privKey, new BigInteger("AD04DDE87B84747A243A631EA47A1BA6D1FAA059149AD2440DE6FBA6", 16), new BigInteger("178D49B1AE90E3D8B629BE3DB5683915F4E8C99FDF6E666CF37ADCFD", 16));
+ doTestHMACDetECDSATest(new SHA384Digest(), privKey, new BigInteger("389B92682E399B26518A95506B52C03BC9379A9DADF3391A21FB0EA4", 16), new BigInteger("414A718ED3249FF6DBC5B50C27F71F01F070944DA22AB1F78F559AAB", 16));
+ doTestHMACDetECDSATest(new SHA512Digest(), privKey, new BigInteger("049F050477C5ADD858CAC56208394B5A55BAEBBE887FDF765047C17C", 16), new BigInteger("077EB13E7005929CEFA3CD0403C7CDCC077ADF4E44F3C41B2F60ECFF", 16));
+
+ x9ECParameters = NISTNamedCurves.getByName("P-256");
+ ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
+
+ privKey = new ECPrivateKeyParameters(new BigInteger("C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721", 16), ecDomainParameters);
+
+ doTestHMACDetECDSASample(new SHA1Digest(), privKey, new BigInteger("61340C88C3AAEBEB4F6D667F672CA9759A6CCAA9FA8811313039EE4A35471D32", 16), new BigInteger("6D7F147DAC089441BB2E2FE8F7A3FA264B9C475098FDCF6E00D7C996E1B8B7EB", 16));
+ doTestHMACDetECDSASample(new SHA224Digest(), privKey, new BigInteger("53B2FFF5D1752B2C689DF257C04C40A587FABABB3F6FC2702F1343AF7CA9AA3F", 16), new BigInteger("B9AFB64FDC03DC1A131C7D2386D11E349F070AA432A4ACC918BEA988BF75C74C", 16));
+ doTestHMACDetECDSASample(new SHA256Digest(), privKey, new BigInteger("EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716", 16), new BigInteger("F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8", 16));
+ doTestHMACDetECDSASample(new SHA384Digest(), privKey, new BigInteger("0EAFEA039B20E9B42309FB1D89E213057CBF973DC0CFC8F129EDDDC800EF7719", 16), new BigInteger("4861F0491E6998B9455193E34E7B0D284DDD7149A74B95B9261F13ABDE940954", 16));
+ doTestHMACDetECDSASample(new SHA512Digest(), privKey, new BigInteger("8496A60B5E9B47C825488827E0495B0E3FA109EC4568FD3F8D1097678EB97F00", 16), new BigInteger("2362AB1ADBE2B8ADF9CB9EDAB740EA6049C028114F2460F96554F61FAE3302FE", 16));
+
+ doTestHMACDetECDSATest(new SHA1Digest(), privKey, new BigInteger("0CBCC86FD6ABD1D99E703E1EC50069EE5C0B4BA4B9AC60E409E8EC5910D81A89", 16), new BigInteger("01B9D7B73DFAA60D5651EC4591A0136F87653E0FD780C3B1BC872FFDEAE479B1", 16));
+ doTestHMACDetECDSATest(new SHA224Digest(), privKey, new BigInteger("C37EDB6F0AE79D47C3C27E962FA269BB4F441770357E114EE511F662EC34A692", 16), new BigInteger("C820053A05791E521FCAAD6042D40AEA1D6B1A540138558F47D0719800E18F2D", 16));
+ doTestHMACDetECDSATest(new SHA256Digest(), privKey, new BigInteger("F1ABB023518351CD71D881567B1EA663ED3EFCF6C5132B354F28D3B0B7D38367", 16), new BigInteger("019F4113742A2B14BD25926B49C649155F267E60D3814B4C0CC84250E46F0083", 16));
+ doTestHMACDetECDSATest(new SHA384Digest(), privKey, new BigInteger("83910E8B48BB0C74244EBDF7F07A1C5413D61472BD941EF3920E623FBCCEBEB6", 16), new BigInteger("8DDBEC54CF8CD5874883841D712142A56A8D0F218F5003CB0296B6B509619F2C", 16));
+ doTestHMACDetECDSATest(new SHA512Digest(), privKey, new BigInteger("461D93F31B6540894788FD206C07CFA0CC35F46FA3C91816FFF1040AD1581A04", 16), new BigInteger("39AF9F15DE0DB8D97E72719C74820D304CE5226E32DEDAE67519E840D1194E55", 16));
+
+ x9ECParameters = NISTNamedCurves.getByName("P-384");
+ ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
+
+ privKey = new ECPrivateKeyParameters(new BigInteger("6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D8" +
+ "96D5724E4C70A825F872C9EA60D2EDF5", 16), ecDomainParameters);
+
+ doTestHMACDetECDSASample(new SHA1Digest(), privKey, new BigInteger("EC748D839243D6FBEF4FC5C4859A7DFFD7F3ABDDF72014540C16D73309834FA3" +
+ "7B9BA002899F6FDA3A4A9386790D4EB2", 16),
+ new BigInteger("A3BCFA947BEEF4732BF247AC17F71676CB31A847B9FF0CBC9C9ED4C1A5B3FACF" +
+ "26F49CA031D4857570CCB5CA4424A443", 16));
+ doTestHMACDetECDSASample(new SHA224Digest(), privKey, new BigInteger("42356E76B55A6D9B4631C865445DBE54E056D3B3431766D0509244793C3F9366" +
+ "450F76EE3DE43F5A125333A6BE060122", 16),
+ new BigInteger("9DA0C81787064021E78DF658F2FBB0B042BF304665DB721F077A4298B095E483" +
+ "4C082C03D83028EFBF93A3C23940CA8D", 16));
+ doTestHMACDetECDSASample(new SHA256Digest(), privKey, new BigInteger("21B13D1E013C7FA1392D03C5F99AF8B30C570C6F98D4EA8E354B63A21D3DAA33" +
+ "BDE1E888E63355D92FA2B3C36D8FB2CD", 16),
+ new BigInteger("F3AA443FB107745BF4BD77CB3891674632068A10CA67E3D45DB2266FA7D1FEEB" +
+ "EFDC63ECCD1AC42EC0CB8668A4FA0AB0", 16));
+ doTestHMACDetECDSASample(new SHA384Digest(), privKey, new BigInteger("94EDBB92A5ECB8AAD4736E56C691916B3F88140666CE9FA73D64C4EA95AD133C" +
+ "81A648152E44ACF96E36DD1E80FABE46", 16),
+ new BigInteger("99EF4AEB15F178CEA1FE40DB2603138F130E740A19624526203B6351D0A3A94F" +
+ "A329C145786E679E7B82C71A38628AC8", 16));
+ doTestHMACDetECDSASample(new SHA512Digest(), privKey, new BigInteger("ED0959D5880AB2D869AE7F6C2915C6D60F96507F9CB3E047C0046861DA4A799C" +
+ "FE30F35CC900056D7C99CD7882433709", 16),
+ new BigInteger("512C8CCEEE3890A84058CE1E22DBC2198F42323CE8ACA9135329F03C068E5112" +
+ "DC7CC3EF3446DEFCEB01A45C2667FDD5", 16));
+
+ doTestHMACDetECDSATest(new SHA1Digest(), privKey, new BigInteger("4BC35D3A50EF4E30576F58CD96CE6BF638025EE624004A1F7789A8B8E43D0678" +
+ "ACD9D29876DAF46638645F7F404B11C7", 16),
+ new BigInteger("D5A6326C494ED3FF614703878961C0FDE7B2C278F9A65FD8C4B7186201A29916" +
+ "95BA1C84541327E966FA7B50F7382282", 16));
+ doTestHMACDetECDSATest(new SHA224Digest(), privKey, new BigInteger("E8C9D0B6EA72A0E7837FEA1D14A1A9557F29FAA45D3E7EE888FC5BF954B5E624" +
+ "64A9A817C47FF78B8C11066B24080E72", 16),
+ new BigInteger("07041D4A7A0379AC7232FF72E6F77B6DDB8F09B16CCE0EC3286B2BD43FA8C614" +
+ "1C53EA5ABEF0D8231077A04540A96B66", 16));
+ doTestHMACDetECDSATest(new SHA256Digest(), privKey, new BigInteger("6D6DEFAC9AB64DABAFE36C6BF510352A4CC27001263638E5B16D9BB51D451559" +
+ "F918EEDAF2293BE5B475CC8F0188636B", 16),
+ new BigInteger("2D46F3BECBCC523D5F1A1256BF0C9B024D879BA9E838144C8BA6BAEB4B53B47D" +
+ "51AB373F9845C0514EEFB14024787265", 16));
+ doTestHMACDetECDSATest(new SHA384Digest(), privKey, new BigInteger("8203B63D3C853E8D77227FB377BCF7B7B772E97892A80F36AB775D509D7A5FEB" +
+ "0542A7F0812998DA8F1DD3CA3CF023DB", 16),
+ new BigInteger("DDD0760448D42D8A43AF45AF836FCE4DE8BE06B485E9B61B827C2F13173923E0" +
+ "6A739F040649A667BF3B828246BAA5A5", 16));
+ doTestHMACDetECDSATest(new SHA512Digest(), privKey, new BigInteger("A0D5D090C9980FAF3C2CE57B7AE951D31977DD11C775D314AF55F76C676447D0" +
+ "6FB6495CD21B4B6E340FC236584FB277", 16),
+ new BigInteger("976984E59B4C77B0E8E4460DCA3D9F20E07B9BB1F63BEEFAF576F6B2E8B22463" +
+ "4A2092CD3792E0159AD9CEE37659C736", 16));
+
+ x9ECParameters = NISTNamedCurves.getByName("P-521");
+ ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
+
+ privKey = new ECPrivateKeyParameters(new BigInteger("0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75C" +
+ "AA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83" +
+ "538", 16), ecDomainParameters);
+
+ doTestHMACDetECDSASample(new SHA1Digest(), privKey, new BigInteger("0343B6EC45728975EA5CBA6659BBB6062A5FF89EEA58BE3C80B619F322C87910" +
+ "FE092F7D45BB0F8EEE01ED3F20BABEC079D202AE677B243AB40B5431D497C55D" +
+ "75D", 16),
+ new BigInteger("0E7B0E675A9B24413D448B8CC119D2BF7B2D2DF032741C096634D6D65D0DBE3D" +
+ "5694625FB9E8104D3B842C1B0E2D0B98BEA19341E8676AEF66AE4EBA3D5475D5" +
+ "D16", 16));
+ doTestHMACDetECDSASample(new SHA224Digest(), privKey, new BigInteger("1776331CFCDF927D666E032E00CF776187BC9FDD8E69D0DABB4109FFE1B5E2A3" +
+ "0715F4CC923A4A5E94D2503E9ACFED92857B7F31D7152E0F8C00C15FF3D87E2E" +
+ "D2E", 16),
+ new BigInteger("050CB5265417FE2320BBB5A122B8E1A32BD699089851128E360E620A30C7E17B" +
+ "A41A666AF126CE100E5799B153B60528D5300D08489CA9178FB610A2006C254B" +
+ "41F", 16));
+ doTestHMACDetECDSASample(new SHA256Digest(), privKey, new BigInteger("1511BB4D675114FE266FC4372B87682BAECC01D3CC62CF2303C92B3526012659" +
+ "D16876E25C7C1E57648F23B73564D67F61C6F14D527D54972810421E7D87589E" +
+ "1A7", 16),
+ new BigInteger("04A171143A83163D6DF460AAF61522695F207A58B95C0644D87E52AA1A347916" +
+ "E4F7A72930B1BC06DBE22CE3F58264AFD23704CBB63B29B931F7DE6C9D949A7E" +
+ "CFC", 16));
+ doTestHMACDetECDSASample(new SHA384Digest(), privKey, new BigInteger("1EA842A0E17D2DE4F92C15315C63DDF72685C18195C2BB95E572B9C5136CA4B4" +
+ "B576AD712A52BE9730627D16054BA40CC0B8D3FF035B12AE75168397F5D50C67" +
+ "451", 16),
+ new BigInteger("1F21A3CEE066E1961025FB048BD5FE2B7924D0CD797BABE0A83B66F1E35EEAF5" +
+ "FDE143FA85DC394A7DEE766523393784484BDF3E00114A1C857CDE1AA203DB65" +
+ "D61", 16));
+ doTestHMACDetECDSASample(new SHA512Digest(), privKey, new BigInteger("0C328FAFCBD79DD77850370C46325D987CB525569FB63C5D3BC53950E6D4C5F1" +
+ "74E25A1EE9017B5D450606ADD152B534931D7D4E8455CC91F9B15BF05EC36E37" +
+ "7FA", 16),
+ new BigInteger("0617CCE7CF5064806C467F678D3B4080D6F1CC50AF26CA209417308281B68AF2" +
+ "82623EAA63E5B5C0723D8B8C37FF0777B1A20F8CCB1DCCC43997F1EE0E44DA4A" +
+ "67A", 16));
+
+ doTestHMACDetECDSATest(new SHA1Digest(), privKey, new BigInteger("13BAD9F29ABE20DE37EBEB823C252CA0F63361284015A3BF430A46AAA80B87B0" +
+ "693F0694BD88AFE4E661FC33B094CD3B7963BED5A727ED8BD6A3A202ABE009D0" +
+ "367", 16),
+ new BigInteger("1E9BB81FF7944CA409AD138DBBEE228E1AFCC0C890FC78EC8604639CB0DBDC90" +
+ "F717A99EAD9D272855D00162EE9527567DD6A92CBD629805C0445282BBC91679" +
+ "7FF", 16));
+ doTestHMACDetECDSATest(new SHA224Digest(), privKey, new BigInteger("1C7ED902E123E6815546065A2C4AF977B22AA8EADDB68B2C1110E7EA44D42086" +
+ "BFE4A34B67DDC0E17E96536E358219B23A706C6A6E16BA77B65E1C595D43CAE1" +
+ "7FB", 16),
+ new BigInteger("177336676304FCB343CE028B38E7B4FBA76C1C1B277DA18CAD2A8478B2A9A9F5" +
+ "BEC0F3BA04F35DB3E4263569EC6AADE8C92746E4C82F8299AE1B8F1739F8FD51" +
+ "9A4", 16));
+ doTestHMACDetECDSATest(new SHA256Digest(), privKey, new BigInteger("00E871C4A14F993C6C7369501900C4BC1E9C7B0B4BA44E04868B30B41D807104" +
+ "2EB28C4C250411D0CE08CD197E4188EA4876F279F90B3D8D74A3C76E6F1E4656" +
+ "AA8", 16),
+ new BigInteger("0CD52DBAA33B063C3A6CD8058A1FB0A46A4754B034FCC644766CA14DA8CA5CA9" +
+ "FDE00E88C1AD60CCBA759025299079D7A427EC3CC5B619BFBC828E7769BCD694" +
+ "E86", 16));
+ doTestHMACDetECDSATest(new SHA384Digest(), privKey, new BigInteger("14BEE21A18B6D8B3C93FAB08D43E739707953244FDBE924FA926D76669E7AC8C" +
+ "89DF62ED8975C2D8397A65A49DCC09F6B0AC62272741924D479354D74FF60755" +
+ "78C", 16),
+ new BigInteger("133330865C067A0EAF72362A65E2D7BC4E461E8C8995C3B6226A21BD1AA78F0E" +
+ "D94FE536A0DCA35534F0CD1510C41525D163FE9D74D134881E35141ED5E8E95B" +
+ "979", 16));
+ doTestHMACDetECDSATest(new SHA512Digest(), privKey, new BigInteger("13E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10" +
+ "CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47E" +
+ "E6D", 16),
+ new BigInteger("1FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78" +
+ "A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4D" +
+ "CE3", 16));
+
+ x9ECParameters = NISTNamedCurves.getByName("B-163");
+ ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
+
+ privKey = new ECPrivateKeyParameters(new BigInteger("35318FC447D48D7E6BC93B48617DDDEDF26AA658F", 16), ecDomainParameters);
+
+ doTestHMACDetECDSASample(new SHA1Digest(), privKey, new BigInteger("153FEBD179A69B6122DEBF5BC61EB947B24C93526", 16), new BigInteger("37AC9C670F8CF18045049BAE7DD35553545C19E49", 16));
+ doTestHMACDetECDSASample(new SHA224Digest(), privKey, new BigInteger("0A379E69C44F9C16EA3215EA39EB1A9B5D58CC955", 16), new BigInteger("04BAFF5308DA2A7FE2C1742769265AD3ED1D24E74", 16));
+ doTestHMACDetECDSASample(new SHA256Digest(), privKey, new BigInteger("134E00F78FC1CB9501675D91C401DE20DDF228CDC", 16), new BigInteger("373273AEC6C36CB7BAFBB1903A5F5EA6A1D50B624", 16));
+ doTestHMACDetECDSASample(new SHA384Digest(), privKey, new BigInteger("29430B935AF8E77519B0CA4F6903B0B82E6A21A66", 16), new BigInteger("1EA1415306E9353FA5AA54BC7C2581DFBB888440D", 16));
+ doTestHMACDetECDSASample(new SHA512Digest(), privKey, new BigInteger("0B2F177A99F9DF2D51CCAF55F015F326E4B65E7A0", 16), new BigInteger("0DF1FB4487E9B120C5E970EFE48F55E406306C3A1", 16));
+
+ doTestHMACDetECDSATest(new SHA1Digest(), privKey, new BigInteger("256D4079C6C7169B8BC92529D701776A269D56308", 16), new BigInteger("341D3FFEC9F1EB6A6ACBE88E3C86A1C8FDEB8B8E1", 16));
+ doTestHMACDetECDSATest(new SHA224Digest(), privKey, new BigInteger("28ECC6F1272CE80EA59DCF32F7AC2D861BA803393", 16), new BigInteger("0AD4AE2C06E60183C1567D2B82F19421FE3053CE2", 16));
+ doTestHMACDetECDSATest(new SHA256Digest(), privKey, new BigInteger("227DF377B3FA50F90C1CB3CDCBBDBA552C1D35104", 16), new BigInteger("1F7BEAD92583FE920D353F368C1960D0E88B46A56", 16));
+ doTestHMACDetECDSATest(new SHA384Digest(), privKey, new BigInteger("11811DAFEEA441845B6118A0DFEE8A0061231337D", 16), new BigInteger("36258301865EE48C5C6F91D63F62695002AB55B57", 16));
+ doTestHMACDetECDSATest(new SHA512Digest(), privKey, new BigInteger("3B6BB95CA823BE2ED8E3972FF516EB8972D765571", 16), new BigInteger("13DC6F420628969DF900C3FCC48220B38BE24A541", 16));
+
+ x9ECParameters = NISTNamedCurves.getByName("B-233");
+ ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
+
+ privKey = new ECPrivateKeyParameters(new BigInteger("07ADC13DD5BF34D1DDEEB50B2CE23B5F5E6D18067306D60C5F6FF11E5D3", 16), ecDomainParameters);
+
+ doTestHMACDetECDSASample(new SHA1Digest(), privKey, new BigInteger("015CC6FD78BB06E0878E71465515EA5A21A2C18E6FC77B4B158DBEB3944", 16), new BigInteger("0822A4A6C2EB2DF213A5E90BF40377956365EE8C4B4A5A4E2EB9270CB6A", 16));
+ doTestHMACDetECDSASample(new SHA224Digest(), privKey, new BigInteger("05D9920B53471148E10502AB49AB7A3F11084820A074FD89883CF51BC1A", 16), new BigInteger("04D3938900C0A9AAA7080D1DFEB56CFB0FADABE4214536C7ED5117ED13A", 16));
+ doTestHMACDetECDSASample(new SHA256Digest(), privKey, new BigInteger("0A797F3B8AEFCE7456202DF1E46CCC291EA5A49DA3D4BDDA9A4B62D5E0D", 16), new BigInteger("01F6F81DA55C22DA4152134C661588F4BD6F82FDBAF0C5877096B070DC2", 16));
+ doTestHMACDetECDSASample(new SHA384Digest(), privKey, new BigInteger("015E85A8D46225DD7E314A1C4289731FC14DECE949349FE535D11043B85", 16), new BigInteger("03F189D37F50493EFD5111A129443A662AB3C6B289129AD8C0CAC85119C", 16));
+ doTestHMACDetECDSASample(new SHA512Digest(), privKey, new BigInteger("03B62A4BF783919098B1E42F496E65F7621F01D1D466C46940F0F132A95", 16), new BigInteger("0F4BE031C6E5239E7DAA014CBBF1ED19425E49DAEB426EC9DF4C28A2E30", 16));
+
+ doTestHMACDetECDSATest(new SHA1Digest(), privKey, new BigInteger("02F1FEDC57BE203E4C8C6B8C1CEB35E13C1FCD956AB41E3BD4C8A6EFB1F", 16), new BigInteger("05738EC8A8EDEA8E435EE7266AD3EDE1EEFC2CEBE2BE1D614008D5D2951", 16));
+ doTestHMACDetECDSATest(new SHA224Digest(), privKey, new BigInteger("0CCE175124D3586BA7486F7146894C65C2A4A5A1904658E5C7F9DF5FA5D", 16), new BigInteger("08804B456D847ACE5CA86D97BF79FD6335E5B17F6C0D964B5D0036C867E", 16));
+ doTestHMACDetECDSATest(new SHA256Digest(), privKey, new BigInteger("035C3D6DFEEA1CFB29B93BE3FDB91A7B130951770C2690C16833A159677", 16), new BigInteger("0600F7301D12AB376B56D4459774159ADB51F97E282FF384406AFD53A02", 16));
+ doTestHMACDetECDSATest(new SHA384Digest(), privKey, new BigInteger("061602FC8068BFD5FB86027B97455D200EC603057446CCE4D76DB8EF42C", 16), new BigInteger("03396DD0D59C067BB999B422D9883736CF9311DFD6951F91033BD03CA8D", 16));
+ doTestHMACDetECDSATest(new SHA512Digest(), privKey, new BigInteger("07E12CB60FDD614958E8E34B3C12DDFF35D85A9C5800E31EA2CC2EF63B1", 16), new BigInteger("0E8970FD99D836F3CC1C807A2C58760DE6EDAA23705A82B9CB1CE93FECC", 16));
+
+ x9ECParameters = NISTNamedCurves.getByName("B-283");
+ ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
+
+ privKey = new ECPrivateKeyParameters(new BigInteger("14510D4BC44F2D26F4553942C98073C1BD35545CEABB5CC138853C5158D2729EA408836", 16), ecDomainParameters);
+
+ doTestHMACDetECDSASample(new SHA1Digest(), privKey, new BigInteger("201E18D48C6DB3D5D097C4DCE1E25587E1501FC3CF47BDB5B4289D79E273D6A9" +
+ "ACB8285", 16), new BigInteger("151AE05712B024CE617358260774C8CA8B0E7A7E72EF8229BF2ACE7609560CB3" +
+ "0322C4F", 16));
+ doTestHMACDetECDSASample(new SHA224Digest(), privKey, new BigInteger("143E878DDFD4DF40D97B8CD638B3C4706501C2201CF7108F2FB91478C11D6947" +
+ "3246925", 16), new BigInteger("0CBF1B9717FEEA3AABB09D9654110144267098E0E1E8D0289A6211BE0EEDFDD8" +
+ "6A3DB79", 16));
+ doTestHMACDetECDSASample(new SHA256Digest(), privKey, new BigInteger("29FD82497FB3E5CEF65579272138DE59E2B666B8689466572B3B69A172CEE83B" +
+ "E145659", 16), new BigInteger("05A89D9166B40795AF0FE5958201B9C0523E500013CA12B4840EA2BC53F25F9B" +
+ "3CE87C0", 16));
+ doTestHMACDetECDSASample(new SHA384Digest(), privKey, new BigInteger("2F00689C1BFCD2A8C7A41E0DE55AE182E6463A152828EF89FE3525139B660329" +
+ "4E69353", 16), new BigInteger("1744514FE0A37447250C8A329EAAADA81572226CABA16F39270EE5DD03F27B1F" +
+ "665EB5D", 16));
+ doTestHMACDetECDSASample(new SHA512Digest(), privKey, new BigInteger("0DA43A9ADFAA6AD767998A054C6A8F1CF77A562924628D73C62761847AD8286E" +
+ "0D91B47", 16), new BigInteger("1D118733AE2C88357827CAFC6F68ABC25C80C640532925E95CFE66D40F8792F3" +
+ "AC44C42", 16));
+
+ doTestHMACDetECDSATest(new SHA1Digest(), privKey, new BigInteger("05A408133919F2CDCDBE5E4C14FBC706C1F71BADAFEF41F5DE4EC27272FC1CA9" +
+ "366FBB2", 16), new BigInteger("012966272872C097FEA7BCE64FAB1A81982A773E26F6E4EF7C99969846E67CA9" +
+ "CBE1692", 16));
+ doTestHMACDetECDSATest(new SHA224Digest(), privKey, new BigInteger("08F3824E40C16FF1DDA8DC992776D26F4A5981AB5092956C4FDBB4F1AE0A711E" +
+ "EAA10E5", 16), new BigInteger("0A64B91EFADB213E11483FB61C73E3EF63D3B44EEFC56EA401B99DCC60CC28E9" +
+ "9F0F1FA", 16));
+ doTestHMACDetECDSATest(new SHA256Digest(), privKey, new BigInteger("3597B406F5329D11A79E887847E5EC60861CCBB19EC61F252DB7BD549C699951" +
+ "C182796", 16), new BigInteger("0A6A100B997BC622D91701D9F5C6F6D3815517E577622DA69D3A0E8917C1CBE6" +
+ "3ACD345", 16));
+ doTestHMACDetECDSATest(new SHA384Digest(), privKey, new BigInteger("1BB490926E5A1FDC7C5AA86D0835F9B994EDA315CA408002AF54A298728D422E" +
+ "BF59E4C", 16), new BigInteger("36C682CFC9E2C89A782BFD3A191609D1F0C1910D5FD6981442070393159D65FB" +
+ "CC0A8BA", 16));
+ doTestHMACDetECDSATest(new SHA512Digest(), privKey, new BigInteger("19944AA68F9778C2E3D6E240947613E6DA60EFCE9B9B2C063FF5466D72745B5A" +
+ "0B25BA2", 16), new BigInteger("03F1567B3C5B02DF15C874F0EE22850824693D5ADC4663BAA19E384E550B1DD4" +
+ "1F31EE6", 16));
+
+ x9ECParameters = NISTNamedCurves.getByName("B-409");
+ ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
+
+ privKey = new ECPrivateKeyParameters(new BigInteger("0494994CC325B08E7B4CE038BD9436F90B5E59A2C13C3140CD3AE07C04A01FC489F572CE0569A6DB7B8060393DE76330C624177", 16), ecDomainParameters);
+
+ doTestHMACDetECDSASample(new SHA1Digest(), privKey, new BigInteger("0D8783188E1A540E2022D389E1D35B32F56F8C2BB5636B8ABF7718806B27A713" +
+ "EBAE37F63ECD4B61445CEF5801B62594EF3E982", 16), new BigInteger("03A6B4A80E204DB0DE12E7415C13C9EC091C52935658316B4A0C591216A38791" +
+ "54BEB1712560E346E7EF26517707435B55C3141", 16));
+ doTestHMACDetECDSASample(new SHA224Digest(), privKey, new BigInteger("0EE4F39ACC2E03CE96C3D9FCBAFA5C22C89053662F8D4117752A9B10F09ADFDA" +
+ "59DB061E247FE5321D6B170EE758ACE1BE4D157", 16), new BigInteger("00A2B83265B456A430A8BF27DCC8A9488B3F126C10F0D6D64BF7B8A218FAAF20" +
+ "E51A295A3AE78F205E5A4A6AE224C3639F1BB34", 16));
+ doTestHMACDetECDSASample(new SHA256Digest(), privKey, new BigInteger("02D8B1B31E33E74D7EB46C30FDE5AD2CA04EC8FE08FBA0E73BA5E568953AC5EA" +
+ "307C072942238DFC07F4A4D7C7C6A9F86436D17", 16), new BigInteger("079F7D471E6CB73234AF7F7C381D2CE15DE35BAF8BB68393B73235B3A26EC2DF" +
+ "4842CE433FB492D6E074E604D4870024D42189A", 16));
+ doTestHMACDetECDSASample(new SHA384Digest(), privKey, new BigInteger("07BC638B7E7CE6FEE5E9C64A0F966D722D01BB4BC3F3A35F30D4CDDA92DFC5F7" +
+ "F0B4BBFE8065D9AD452FD77A1914BE3A2440C18", 16), new BigInteger("06D904429850521B28A32CBF55C7C0FDF35DC4E0BDA2552C7BF68A171E970E67" +
+ "88ACC0B9521EACB4796E057C70DD9B95FED5BFB", 16));
+ doTestHMACDetECDSASample(new SHA512Digest(), privKey, new BigInteger("05D178DECAFD2D02A3DA0D8BA1C4C1D95EE083C760DF782193A9F7B4A8BE6FC5" +
+ "C21FD60613BCA65C063A61226E050A680B3ABD4", 16), new BigInteger("013B7581E98F6A63FBBCB3E49BCDA60F816DB230B888506D105DC229600497C3" +
+ "B46588C784BE3AA9343BEF82F7C9C80AEB63C3B", 16));
+
+ doTestHMACDetECDSATest(new SHA1Digest(), privKey, new BigInteger("049F54E7C10D2732B4638473053782C6919218BBEFCEC8B51640FC193E832291" +
+ "F05FA12371E9B448417B3290193F08EE9319195", 16), new BigInteger("0499E267DEC84E02F6F108B10E82172C414F15B1B7364BE8BFD66ADC0C5DE23F" +
+ "EE3DF0D811134C25AFE0E05A6672F98889F28F1", 16));
+ doTestHMACDetECDSATest(new SHA224Digest(), privKey, new BigInteger("0B1527FFAA7DD7C7E46B628587A5BEC0539A2D04D3CF27C54841C2544E1BBDB4" +
+ "2FDBDAAF8671A4CA86DFD619B1E3732D7BB56F2", 16), new BigInteger("0442C68C044868DF4832C807F1EDDEBF7F5052A64B826FD03451440794063F52" +
+ "B022DF304F47403D4069234CA9EB4C964B37C02", 16));
+ doTestHMACDetECDSATest(new SHA256Digest(), privKey, new BigInteger("0BB27755B991D6D31757BCBF68CB01225A38E1CFA20F775E861055DD108ED7EA" +
+ "455E4B96B2F6F7CD6C6EC2B3C70C3EDDEB9743B", 16), new BigInteger("0C5BE90980E7F444B5F7A12C9E9AC7A04CA81412822DD5AD1BE7C45D5032555E" +
+ "A070864245CF69266871FEB8CD1B7EDC30EF6D5", 16));
+ doTestHMACDetECDSATest(new SHA384Digest(), privKey, new BigInteger("04EFEB7098772187907C87B33E0FBBA4584226C50C11E98CA7AAC6986F8D3BE0" +
+ "44E5B52D201A410B852536527724CA5F8CE6549", 16), new BigInteger("09574102FEB3EF87E6D66B94119F5A6062950FF4F902EA1E6BD9E2037F33FF99" +
+ "1E31F5956C23AFE48FCDC557FD6F088C7C9B2B3", 16));
+ doTestHMACDetECDSATest(new SHA512Digest(), privKey, new BigInteger("07E0249C68536AE2AEC2EC30090340DA49E6DC9E9EEC8F85E5AABFB234B6DA7D" +
+ "2E9524028CF821F21C6019770474CC40B01FAF6", 16), new BigInteger("08125B5A03FB44AE81EA46D446130C2A415ECCA265910CA69D55F2453E16CD7B" +
+ "2DFA4E28C50FA8137F9C0C6CEE4CD37ABCCF6D8", 16));
+
+ x9ECParameters = NISTNamedCurves.getByName("B-571");
+ ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
+
+ privKey = new ECPrivateKeyParameters(new BigInteger("028A04857F24C1C082DF0D909C0E72F453F2E2340CCB071F0E389BCA2575DA19" +
+ "124198C57174929AD26E348CF63F78D28021EF5A9BF2D5CBEAF6B7CCB6C4DA82" +
+ "4DD5C82CFB24E11", 16), ecDomainParameters);
+
+ doTestHMACDetECDSASample(new SHA1Digest(), privKey, new BigInteger("147D3EB0EDA9F2152DFD014363D6A9CE816D7A1467D326A625FC4AB0C786E1B7" +
+ "4DDF7CD4D0E99541391B266C704BB6B6E8DCCD27B460802E0867143727AA4155" +
+ "55454321EFE5CB6", 16),
+ new BigInteger("17319571CAF533D90D2E78A64060B9C53169AB7FC908947B3EDADC54C79CCF0A" +
+ "7920B4C64A4EAB6282AFE9A459677CDA37FD6DD50BEF18709590FE18B923BDF7" +
+ "4A66B189A850819", 16));
+
+ doTestHMACDetECDSASample(new SHA224Digest(), privKey, new BigInteger("10F4B63E79B2E54E4F4F6A2DBC786D8F4A143ECA7B2AD97810F6472AC6AE2085" +
+ "3222854553BE1D44A7974599DB7061AE8560DF57F2675BE5F9DD94ABAF3D47F1" +
+ "582B318E459748B", 16),
+ new BigInteger("3BBEA07C6B269C2B7FE9AE4DDB118338D0C2F0022920A7F9DCFCB7489594C03B" +
+ "536A9900C4EA6A10410007222D3DAE1A96F291C4C9275D75D98EB290DC0EEF17" +
+ "6037B2C7A7A39A3", 16));
+
+ doTestHMACDetECDSASample(new SHA256Digest(), privKey, new BigInteger("213EF9F3B0CFC4BF996B8AF3A7E1F6CACD2B87C8C63820000800AC787F17EC99" +
+ "C04BCEDF29A8413CFF83142BB88A50EF8D9A086AF4EB03E97C567500C21D8657" +
+ "14D832E03C6D054", 16),
+ new BigInteger("3D32322559B094E20D8935E250B6EC139AC4AAB77920812C119AF419FB62B332" +
+ "C8D226C6C9362AE3C1E4AABE19359B8428EA74EC8FBE83C8618C2BCCB6B43FBA" +
+ "A0F2CCB7D303945", 16));
+
+ doTestHMACDetECDSASample(new SHA384Digest(), privKey, new BigInteger("375D8F49C656A0BBD21D3F54CDA287D853C4BB1849983CD891EF6CD6BB56A62B" +
+ "687807C16685C2C9BCA2663C33696ACCE344C45F3910B1DF806204FF731ECB28" +
+ "9C100EF4D1805EC", 16),
+ new BigInteger("1CDEC6F46DFEEE44BCE71D41C60550DC67CF98D6C91363625AC2553E4368D2DF" +
+ "B734A8E8C72E118A76ACDB0E58697940A0F3DF49E72894BD799450FC9E550CC0" +
+ "4B9FF9B0380021C", 16));
+ doTestHMACDetECDSASample(new SHA512Digest(), privKey, new BigInteger("1C26F40D940A7EAA0EB1E62991028057D91FEDA0366B606F6C434C361F04E545" +
+ "A6A51A435E26416F6838FFA260C617E798E946B57215284182BE55F29A355E60" +
+ "24FE32A47289CF0", 16),
+ new BigInteger("3691DE4369D921FE94EDDA67CB71FBBEC9A436787478063EB1CC778B3DCDC1C4" +
+ "162662752D28DEEDF6F32A269C82D1DB80C87CE4D3B662E03AC347806E3F19D1" +
+ "8D6D4DE7358DF7E", 16));
+
+ doTestHMACDetECDSATest(new SHA1Digest(), privKey, new BigInteger("133F5414F2A9BC41466D339B79376038A64D045E5B0F792A98E5A7AA87E0AD01" +
+ "6419E5F8D176007D5C9C10B5FD9E2E0AB8331B195797C0358BA05ECBF24ACE59" +
+ "C5F368A6C0997CC", 16),
+ new BigInteger("3D16743AE9F00F0B1A500F738719C5582550FEB64689DA241665C4CE4F328BA0" +
+ "E34A7EF527ED13BFA5889FD2D1D214C11EB17D6BC338E05A56F41CAFF1AF7B8D" +
+ "574DB62EF0D0F21", 16));
+
+ doTestHMACDetECDSATest(new SHA224Digest(), privKey, new BigInteger("3048E76506C5C43D92B2E33F62B33E3111CEEB87F6C7DF7C7C01E3CDA28FA5E8" +
+ "BE04B5B23AA03C0C70FEF8F723CBCEBFF0B7A52A3F5C8B84B741B4F6157E69A5" +
+ "FB0524B48F31828", 16),
+ new BigInteger("2C99078CCFE5C82102B8D006E3703E020C46C87C75163A2CD839C885550BA5CB" +
+ "501AC282D29A1C26D26773B60FBE05AAB62BFA0BA32127563D42F7669C97784C" +
+ "8897C22CFB4B8FA", 16));
+
+ doTestHMACDetECDSATest(new SHA256Digest(), privKey, new BigInteger("184BC808506E11A65D628B457FDA60952803C604CC7181B59BD25AEE1411A66D" +
+ "12A777F3A0DC99E1190C58D0037807A95E5080FA1B2E5CCAA37B50D401CFFC34" +
+ "17C005AEE963469", 16),
+ new BigInteger("27280D45F81B19334DBDB07B7E63FE8F39AC7E9AE14DE1D2A6884D2101850289" +
+ "D70EE400F26ACA5E7D73F534A14568478E59D00594981ABE6A1BA18554C13EB5" +
+ "E03921E4DC98333", 16));
+
+ doTestHMACDetECDSATest(new SHA384Digest(), privKey, new BigInteger("319EE57912E7B0FAA1FBB145B0505849A89C6DB1EC06EA20A6A7EDE072A6268A" +
+ "F6FD9C809C7E422A5F33C6C3326EAD7402467DF3272A1B2726C1C20975950F0F" +
+ "50D8324578F13EC", 16),
+ new BigInteger("2CF3EA27EADD0612DD2F96F46E89AB894B01A10DF985C5FC099CFFE0EA083EB4" +
+ "4BE682B08BFE405DAD5F37D0A2C59015BA41027E24B99F8F75A70B6B7385BF39" +
+ "BBEA02513EB880C", 16));
+ doTestHMACDetECDSATest(new SHA512Digest(), privKey, new BigInteger("2AA1888EAB05F7B00B6A784C4F7081D2C833D50794D9FEAF6E22B8BE728A2A90" +
+ "BFCABDC803162020AA629718295A1489EE7ED0ECB8AAA197B9BDFC49D18DDD78" +
+ "FC85A48F9715544", 16),
+ new BigInteger("0AA5371FE5CA671D6ED9665849C37F394FED85D51FEF72DA2B5F28EDFB2C6479" +
+ "CA63320C19596F5E1101988E2C619E302DD05112F47E8823040CE540CD3E90DC" +
+ "F41DBC461744EE9", 16));
+
+ }
+
+ private void doTestHMACDetECDSASample(Digest digest, ECPrivateKeyParameters privKey, BigInteger r, BigInteger s)
+ {
+ doTestHMACDetECDSA(new ECDSASigner(new HMacDSAKCalculator(digest)), digest, SAMPLE, privKey, r, s);
+ }
+
+ private void doTestHMACDetECDSATest(Digest digest, ECPrivateKeyParameters privKey, BigInteger r, BigInteger s)
+ {
+ doTestHMACDetECDSA(new ECDSASigner(new HMacDSAKCalculator(digest)), digest, TEST, privKey, r, s);
+ }
+
+ private void doTestHMACDetECDSA(DSA detSigner, Digest digest, byte[] data, CipherParameters privKey, BigInteger r, BigInteger s)
+ {
+ byte[] m = new byte[digest.getDigestSize()];
+
+ digest.update(data, 0, data.length);
+
+ digest.doFinal(m, 0);
+
+ detSigner.init(true, privKey);
+
+ BigInteger[] rs = detSigner.generateSignature(m);
+
+ if (!r.equals(rs[0]))
+ {
+ fail("r value wrong");
+ }
+ if (!s.equals(rs[1]))
+ {
+ fail("s value wrong");
+ }
+ }
+
+ public String getName()
+ {
+ return "DeterministicDSA";
+ }
+
+ public void performTest()
+ {
+ testHMacDeterministic();
+ testECHMacDeterministic();
+ }
+
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new DeterministicDSATest());
+ }
+}
+
diff --git a/core/src/test/java/org/spongycastle/crypto/test/DigestRandomNumberTest.java b/core/src/test/java/org/spongycastle/crypto/test/DigestRandomNumberTest.java
new file mode 100644
index 00000000..b79eadd3
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/DigestRandomNumberTest.java
@@ -0,0 +1,152 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.util.test.SimpleTest;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.crypto.prng.DigestRandomGenerator;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.Digest;
+
+public class DigestRandomNumberTest
+ extends SimpleTest
+{
+ private static final byte[] ZERO_SEED = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ private static final byte[] TEST_SEED = Hex.decode("81dcfafc885914057876");
+
+ private static final byte[] expected0SHA1 = Hex.decode("95bca677b3d4ff793213c00892d2356ec729ee02");
+ private static final byte[] noCycle0SHA1 = Hex.decode("d57ccd0eb12c3938d59226412bc1268037b6b846");
+ private static final byte[] expected0SHA256 = Hex.decode("587e2dfd597d086e47ddcd343eac983a5c913bef8c6a1a560a5c1bc3a74b0991");
+ private static final byte[] noCycle0SHA256 = Hex.decode("e5776c4483486ba7be081f4e1b9dafbab25c8fae290fd5474c1ceda2c16f9509");
+ private static final byte[] expected100SHA1 = Hex.decode("b9d924092546e0876cafd4937d7364ebf9efa4be");
+ private static final byte[] expected100SHA256 = Hex.decode("fbc4aa54b948b99de104c44563a552899d718bb75d1941cc62a2444b0506abaf");
+ private static final byte[] expectedTestSHA1 = Hex.decode("e9ecef9f5306daf1ac51a89a211a64cb24415649");
+ private static final byte[] expectedTestSHA256 = Hex.decode("bdab3ca831b472a2fa09bd1bade541ef16c96640a91fcec553679a136061de98");
+
+ private static final byte[] sha1Xors = Hex.decode("7edcc1216934f3891b03ffa65821611a3e2b1f79");
+ private static final byte[] sha256Xors = Hex.decode("5ec48189cc0aa71e79c707bc3c33ffd47bbba368a83d6cfebf3cd3969d7f3eed");
+
+ public String getName()
+ {
+ return "DigestRandomNumber";
+ }
+
+ private void doExpectedTest(Digest digest, int seed, byte[] expected)
+ {
+ doExpectedTest(digest, seed, expected, null);
+ }
+
+ private void doExpectedTest(Digest digest, int seed, byte[] expected, byte[] noCycle)
+ {
+ DigestRandomGenerator rGen = new DigestRandomGenerator(digest);
+ byte[] output = new byte[digest.getDigestSize()];
+
+ rGen.addSeedMaterial(seed);
+
+ for (int i = 0; i != 1024; i++)
+ {
+ rGen.nextBytes(output);
+ }
+
+ if (noCycle != null)
+ {
+ if (Arrays.areEqual(noCycle, output))
+ {
+ fail("seed not being cycled!");
+ }
+ }
+
+ if (!Arrays.areEqual(expected, output))
+ {
+ fail("expected output doesn't match");
+ }
+ }
+
+ private void doExpectedTest(Digest digest, byte[] seed, byte[] expected)
+ {
+ DigestRandomGenerator rGen = new DigestRandomGenerator(digest);
+ byte[] output = new byte[digest.getDigestSize()];
+
+ rGen.addSeedMaterial(seed);
+
+ for (int i = 0; i != 1024; i++)
+ {
+ rGen.nextBytes(output);
+ }
+
+ if (!Arrays.areEqual(expected, output))
+ {
+ fail("expected output doesn't match");
+ }
+ }
+
+ private void doCountTest(Digest digest, byte[] seed, byte[] expectedXors)
+ {
+ DigestRandomGenerator rGen = new DigestRandomGenerator(digest);
+ byte[] output = new byte[digest.getDigestSize()];
+ int[] averages = new int[digest.getDigestSize()];
+ byte[] ands = new byte[digest.getDigestSize()];
+ byte[] xors = new byte[digest.getDigestSize()];
+ byte[] ors = new byte[digest.getDigestSize()];
+
+ rGen.addSeedMaterial(seed);
+
+ for (int i = 0; i != 1000000; i++)
+ {
+ rGen.nextBytes(output);
+ for (int j = 0; j != output.length; j++)
+ {
+ averages[j] += output[j] & 0xff;
+ ands[j] &= output[j];
+ xors[j] ^= output[j];
+ ors[j] |= output[j];
+ }
+ }
+
+ for (int i = 0; i != output.length; i++)
+ {
+ if ((averages[i] / 1000000) != 127)
+ {
+ fail("average test failed for " + digest.getAlgorithmName());
+ }
+ if (ands[i] != 0)
+ {
+ fail("and test failed for " + digest.getAlgorithmName());
+ }
+ if ((ors[i] & 0xff) != 0xff)
+ {
+ fail("or test failed for " + digest.getAlgorithmName());
+ }
+ if (xors[i] != expectedXors[i])
+ {
+ fail("xor test failed for " + digest.getAlgorithmName());
+ }
+ }
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ doExpectedTest(new SHA1Digest(), 0, expected0SHA1, noCycle0SHA1);
+ doExpectedTest(new SHA256Digest(), 0, expected0SHA256, noCycle0SHA256);
+
+ doExpectedTest(new SHA1Digest(), 100, expected100SHA1);
+ doExpectedTest(new SHA256Digest(), 100, expected100SHA256);
+
+ doExpectedTest(new SHA1Digest(), ZERO_SEED, expected0SHA1);
+ doExpectedTest(new SHA256Digest(), ZERO_SEED, expected0SHA256);
+
+ doExpectedTest(new SHA1Digest(), TEST_SEED, expectedTestSHA1);
+ doExpectedTest(new SHA256Digest(), TEST_SEED, expectedTestSHA256);
+
+ doCountTest(new SHA1Digest(), TEST_SEED, sha1Xors);
+ doCountTest(new SHA256Digest(), TEST_SEED, sha256Xors);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new DigestRandomNumberTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/DigestTest.java b/core/src/test/java/org/spongycastle/crypto/test/DigestTest.java
new file mode 100644
index 00000000..b293ba77
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/DigestTest.java
@@ -0,0 +1,226 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.EncodableDigest;
+import org.spongycastle.util.Memoable;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public abstract class DigestTest
+ extends SimpleTest
+{
+ private Digest digest;
+ private String[] input;
+ private String[] results;
+
+ DigestTest(
+ Digest digest,
+ String[] input,
+ String[] results)
+ {
+ this.digest = digest;
+ this.input = input;
+ this.results = results;
+ }
+
+ public String getName()
+ {
+ return digest.getAlgorithmName();
+ }
+
+ public void performTest()
+ {
+ byte[] resBuf = new byte[digest.getDigestSize()];
+
+ for (int i = 0; i < input.length - 1; i++)
+ {
+ byte[] m = toByteArray(input[i]);
+
+ vectorTest(digest, i, resBuf, m, Hex.decode(results[i]));
+ }
+
+ byte[] lastV = toByteArray(input[input.length - 1]);
+ byte[] lastDigest = Hex.decode(results[input.length - 1]);
+
+ vectorTest(digest, input.length - 1, resBuf, lastV, Hex.decode(results[input.length - 1]));
+
+ testClone(resBuf, lastV, lastDigest);
+ testMemo(resBuf, lastV, lastDigest);
+ if (digest instanceof EncodableDigest)
+ {
+ testEncodedState(resBuf, lastV, lastDigest);
+ }
+ }
+
+ private void testEncodedState(byte[] resBuf, byte[] input, byte[] expected)
+ {
+ // test state encoding;
+ digest.update(input, 0, input.length / 2);
+
+ // copy the Digest
+ Digest copy1 = cloneDigest(((EncodableDigest)digest).getEncodedState());
+ Digest copy2 = cloneDigest(((EncodableDigest)copy1).getEncodedState());
+
+ digest.update(input, input.length / 2, input.length - input.length / 2);
+
+ digest.doFinal(resBuf, 0);
+
+ if (!areEqual(expected, resBuf))
+ {
+ fail("failing state vector test", expected, new String(Hex.encode(resBuf)));
+ }
+
+ copy1.update(input, input.length / 2, input.length - input.length / 2);
+ copy1.doFinal(resBuf, 0);
+
+ if (!areEqual(expected, resBuf))
+ {
+ fail("failing state copy1 vector test", expected, new String(Hex.encode(resBuf)));
+ }
+
+ copy2.update(input, input.length / 2, input.length - input.length / 2);
+ copy2.doFinal(resBuf, 0);
+
+ if (!areEqual(expected, resBuf))
+ {
+ fail("failing state copy2 vector test", expected, new String(Hex.encode(resBuf)));
+ }
+ }
+
+ private void testMemo(byte[] resBuf, byte[] input, byte[] expected)
+ {
+ Memoable m = (Memoable)digest;
+
+ digest.update(input, 0, input.length/2);
+
+ // copy the Digest
+ Memoable copy1 = m.copy();
+ Memoable copy2 = copy1.copy();
+
+ digest.update(input, input.length/2, input.length - input.length/2);
+ digest.doFinal(resBuf, 0);
+
+ if (!areEqual(expected, resBuf))
+ {
+ fail("failing memo vector test", results[results.length - 1], new String(Hex.encode(resBuf)));
+ }
+
+ m.reset(copy1);
+
+ digest.update(input, input.length/2, input.length - input.length/2);
+ digest.doFinal(resBuf, 0);
+
+ if (!areEqual(expected, resBuf))
+ {
+ fail("failing memo reset vector test", results[results.length - 1], new String(Hex.encode(resBuf)));
+ }
+
+ Digest md = (Digest)copy2;
+
+ md.update(input, input.length/2, input.length - input.length/2);
+ md.doFinal(resBuf, 0);
+
+ if (!areEqual(expected, resBuf))
+ {
+ fail("failing memo copy vector test", results[results.length - 1], new String(Hex.encode(resBuf)));
+ }
+ }
+
+ private void testClone(byte[] resBuf, byte[] input, byte[] expected)
+ {
+ digest.update(input, 0, input.length/2);
+
+ // clone the Digest
+ Digest d = cloneDigest(digest);
+
+ digest.update(input, input.length/2, input.length - input.length/2);
+ digest.doFinal(resBuf, 0);
+
+ if (!areEqual(expected, resBuf))
+ {
+ fail("failing clone vector test", results[results.length - 1], new String(Hex.encode(resBuf)));
+ }
+
+ d.update(input, input.length/2, input.length - input.length/2);
+ d.doFinal(resBuf, 0);
+
+ if (!areEqual(expected, resBuf))
+ {
+ fail("failing second clone vector test", results[results.length - 1], new String(Hex.encode(resBuf)));
+ }
+ }
+
+ protected byte[] toByteArray(String input)
+ {
+ byte[] bytes = new byte[input.length()];
+
+ for (int i = 0; i != bytes.length; i++)
+ {
+ bytes[i] = (byte)input.charAt(i);
+ }
+
+ return bytes;
+ }
+
+ private void vectorTest(
+ Digest digest,
+ int count,
+ byte[] resBuf,
+ byte[] input,
+ byte[] expected)
+ {
+ digest.update(input, 0, input.length);
+ digest.doFinal(resBuf, 0);
+
+ if (!areEqual(resBuf, expected))
+ {
+ fail("Vector " + count + " failed got " + new String(Hex.encode(resBuf)));
+ }
+ }
+
+ protected abstract Digest cloneDigest(Digest digest);
+
+ protected Digest cloneDigest(byte[] encodedState)
+ {
+ throw new IllegalStateException("Unsupported");
+ }
+
+ //
+ // optional tests
+ //
+ protected void millionATest(
+ String expected)
+ {
+ byte[] resBuf = new byte[digest.getDigestSize()];
+
+ for (int i = 0; i < 1000000; i++)
+ {
+ digest.update((byte)'a');
+ }
+
+ digest.doFinal(resBuf, 0);
+
+ if (!areEqual(resBuf, Hex.decode(expected)))
+ {
+ fail("Million a's failed", expected, new String(Hex.encode(resBuf)));
+ }
+ }
+
+ protected void sixtyFourKTest(
+ String expected)
+ {
+ byte[] resBuf = new byte[digest.getDigestSize()];
+
+ for (int i = 0; i < 65536; i++)
+ {
+ digest.update((byte)(i & 0xff));
+ }
+
+ digest.doFinal(resBuf, 0);
+
+ if (!areEqual(resBuf, Hex.decode(expected)))
+ {
+ fail("64k test failed", expected, new String(Hex.encode(resBuf)));
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/EAXTest.java b/core/src/test/java/org/spongycastle/crypto/test/EAXTest.java
new file mode 100644
index 00000000..38c0a685
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/EAXTest.java
@@ -0,0 +1,355 @@
+package org.spongycastle.crypto.test;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.engines.AESEngine;
+import org.spongycastle.crypto.engines.AESFastEngine;
+import org.spongycastle.crypto.modes.AEADBlockCipher;
+import org.spongycastle.crypto.modes.EAXBlockCipher;
+import org.spongycastle.crypto.params.AEADParameters;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Strings;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class EAXTest
+ extends SimpleTest
+{
+ private byte[] K1 = Hex.decode("233952DEE4D5ED5F9B9C6D6FF80FF478");
+ private byte[] N1 = Hex.decode("62EC67F9C3A4A407FCB2A8C49031A8B3");
+ private byte[] A1 = Hex.decode("6BFB914FD07EAE6B");
+ private byte[] P1 = Hex.decode("");
+ private byte[] C1 = Hex.decode("E037830E8389F27B025A2D6527E79D01");
+ private byte[] T1 = Hex.decode("E037830E8389F27B025A2D6527E79D01");
+
+ 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");
+ private byte[] T2 = Hex.decode("5C4C9331049D0BDAB0277408F67967E5");
+
+ private byte[] K3 = Hex.decode("01F74AD64077F2E704C0F60ADA3DD523");
+ private byte[] N3 = Hex.decode("70C3DB4F0D26368400A10ED05D2BFF5E");
+ private byte[] A3 = Hex.decode("234A3463C1264AC6");
+ private byte[] P3 = Hex.decode("1A47CB4933");
+ private byte[] C3 = Hex.decode("D851D5BAE03A59F238A23E39199DC9266626C40F80");
+ private byte[] T3 = Hex.decode("3A59F238A23E39199DC9266626C40F80");
+
+ private byte[] K4 = Hex.decode("D07CF6CBB7F313BDDE66B727AFD3C5E8");
+ private byte[] N4 = Hex.decode("8408DFFF3C1A2B1292DC199E46B7D617");
+ private byte[] A4 = Hex.decode("33CCE2EABFF5A79D");
+ private byte[] P4 = Hex.decode("481C9E39B1");
+ private byte[] C4 = Hex.decode("632A9D131AD4C168A4225D8E1FF755939974A7BEDE");
+ private byte[] T4 = Hex.decode("D4C168A4225D8E1FF755939974A7BEDE");
+
+ private byte[] K5 = Hex.decode("35B6D0580005BBC12B0587124557D2C2");
+ private byte[] N5 = Hex.decode("FDB6B06676EEDC5C61D74276E1F8E816");
+ private byte[] A5 = Hex.decode("AEB96EAEBE2970E9");
+ private byte[] P5 = Hex.decode("40D0C07DA5E4");
+ private byte[] C5 = Hex.decode("071DFE16C675CB0677E536F73AFE6A14B74EE49844DD");
+ private byte[] T5 = Hex.decode("CB0677E536F73AFE6A14B74EE49844DD");
+
+ private byte[] K6 = Hex.decode("BD8E6E11475E60B268784C38C62FEB22");
+ private byte[] N6 = Hex.decode("6EAC5C93072D8E8513F750935E46DA1B");
+ private byte[] A6 = Hex.decode("D4482D1CA78DCE0F");
+ private byte[] P6 = Hex.decode("4DE3B35C3FC039245BD1FB7D");
+ private byte[] C6 = Hex.decode("835BB4F15D743E350E728414ABB8644FD6CCB86947C5E10590210A4F");
+ private byte[] T6 = Hex.decode("ABB8644FD6CCB86947C5E10590210A4F");
+
+ private byte[] K7 = Hex.decode("7C77D6E813BED5AC98BAA417477A2E7D");
+ private byte[] N7 = Hex.decode("1A8C98DCD73D38393B2BF1569DEEFC19");
+ private byte[] A7 = Hex.decode("65D2017990D62528");
+ private byte[] P7 = Hex.decode("8B0A79306C9CE7ED99DAE4F87F8DD61636");
+ private byte[] C7 = Hex.decode("02083E3979DA014812F59F11D52630DA30137327D10649B0AA6E1C181DB617D7F2");
+ private byte[] T7 = Hex.decode("137327D10649B0AA6E1C181DB617D7F2");
+
+ private byte[] K8 = Hex.decode("5FFF20CAFAB119CA2FC73549E20F5B0D");
+ private byte[] N8 = Hex.decode("DDE59B97D722156D4D9AFF2BC7559826");
+ private byte[] A8 = Hex.decode("54B9F04E6A09189A");
+ private byte[] P8 = Hex.decode("1BDA122BCE8A8DBAF1877D962B8592DD2D56");
+ private byte[] C8 = Hex.decode("2EC47B2C4954A489AFC7BA4897EDCDAE8CC33B60450599BD02C96382902AEF7F832A");
+ private byte[] T8 = Hex.decode("3B60450599BD02C96382902AEF7F832A");
+
+ private byte[] K9 = Hex.decode("A4A4782BCFFD3EC5E7EF6D8C34A56123");
+ private byte[] N9 = Hex.decode("B781FCF2F75FA5A8DE97A9CA48E522EC");
+ private byte[] A9 = Hex.decode("899A175897561D7E");
+ private byte[] P9 = Hex.decode("6CF36720872B8513F6EAB1A8A44438D5EF11");
+ private byte[] C9 = Hex.decode("0DE18FD0FDD91E7AF19F1D8EE8733938B1E8E7F6D2231618102FDB7FE55FF1991700");
+ private byte[] T9 = Hex.decode("E7F6D2231618102FDB7FE55FF1991700");
+
+ private byte[] K10 = Hex.decode("8395FCF1E95BEBD697BD010BC766AAC3");
+ private byte[] N10 = Hex.decode("22E7ADD93CFC6393C57EC0B3C17D6B44");
+ private byte[] A10 = Hex.decode("126735FCC320D25A");
+ private byte[] P10 = Hex.decode("CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7");
+ private byte[] C10 = Hex.decode("CB8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC253B4652B1AF3795B124AB6E");
+ private byte[] T10 = Hex.decode("CFC46AFC253B4652B1AF3795B124AB6E");
+
+ private byte[] K11 = Hex.decode("8395FCF1E95BEBD697BD010BC766AAC3");
+ private byte[] N11 = Hex.decode("22E7ADD93CFC6393C57EC0B3C17D6B44");
+ private byte[] A11 = Hex.decode("126735FCC320D25A");
+ private byte[] P11 = Hex.decode("CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7");
+ private byte[] C11 = Hex.decode("CB8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC");
+ private byte[] T11 = Hex.decode("CFC46AFC");
+
+ private static final int NONCE_LEN = 8;
+ private static final int MAC_LEN = 8;
+ private static final int AUTHEN_LEN = 20;
+
+ public String getName()
+ {
+ return "EAX";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ checkVectors(1, K1, 128, N1, A1, P1, T1, C1);
+ checkVectors(2, K2, 128, N2, A2, P2, T2, C2);
+ checkVectors(3, K3, 128, N3, A3, P3, T3, C3);
+ checkVectors(4, K4, 128, N4, A4, P4, T4, C4);
+ checkVectors(5, K5, 128, N5, A5, P5, T5, C5);
+ checkVectors(6, K6, 128, N6, A6, P6, T6, C6);
+ checkVectors(7, K7, 128, N7, A7, P7, T7, C7);
+ checkVectors(8, K8, 128, N8, A8, P8, T8, C8);
+ checkVectors(9, K9, 128, N9, A9, P9, T9, C9);
+ checkVectors(10, K10, 128, N10, A10, P10, T10, C10);
+ checkVectors(11, K11, 32, N11, A11, P11, T11, C11);
+
+ EAXBlockCipher eax = new EAXBlockCipher(new AESFastEngine());
+ ivParamTest(1, eax, K1, N1);
+
+ //
+ // exception tests
+ //
+
+ try
+ {
+ eax.init(false, new AEADParameters(new KeyParameter(K1), 32, N2, A2));
+
+ byte[] enc = new byte[C2.length];
+ int len = eax.processBytes(C2, 0, C2.length, enc, 0);
+
+ len += eax.doFinal(enc, len);
+
+ fail("invalid cipher text not picked up");
+ }
+ catch (InvalidCipherTextException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ eax.init(false, new KeyParameter(K1));
+
+ fail("illegal argument not picked up");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ randomTests();
+ AEADTestUtil.testReset(this, new EAXBlockCipher(new AESEngine()), new EAXBlockCipher(new AESEngine()), new AEADParameters(new KeyParameter(K1), 32, N2));
+ AEADTestUtil.testTampering(this, eax, new AEADParameters(new KeyParameter(K1), 32, N2));
+ AEADTestUtil.testOutputSizes(this, new EAXBlockCipher(new AESEngine()), new AEADParameters(
+ new KeyParameter(K1), 32, N2));
+ AEADTestUtil.testBufferSizeChecks(this, new EAXBlockCipher(new AESEngine()), new AEADParameters(
+ new KeyParameter(K1), 32, N2));
+ }
+
+ private void checkVectors(
+ int count,
+ byte[] k,
+ int macSize,
+ byte[] n,
+ byte[] a,
+ byte[] p,
+ byte[] t,
+ byte[] c)
+ throws InvalidCipherTextException
+ {
+ byte[] fa = new byte[a.length / 2];
+ byte[] la = new byte[a.length - (a.length / 2)];
+ System.arraycopy(a, 0, fa, 0, fa.length);
+ System.arraycopy(a, fa.length, la, 0, la.length);
+
+ checkVectors(count, "all initial associated data", k, macSize, n, a, null, p, t, c);
+ checkVectors(count, "subsequent associated data", k, macSize, n, null, a, p, t, c);
+ checkVectors(count, "split associated data", k, macSize, n, fa, la, p, t, c);
+ }
+
+ private void checkVectors(
+ int count,
+ String additionalDataType,
+ byte[] k,
+ int macSize,
+ byte[] n,
+ byte[] a,
+ byte[] sa,
+ byte[] p,
+ byte[] t,
+ byte[] c)
+ throws InvalidCipherTextException
+ {
+ EAXBlockCipher encEax = new EAXBlockCipher(new AESFastEngine());
+ EAXBlockCipher decEax = new EAXBlockCipher(new AESFastEngine());
+
+ AEADParameters parameters = new AEADParameters(new KeyParameter(k), macSize, n, a);
+ encEax.init(true, parameters);
+ decEax.init(false, parameters);
+
+ runCheckVectors(count, encEax, decEax, additionalDataType, sa, p, t, c);
+ runCheckVectors(count, encEax, decEax, additionalDataType, sa, p, t, c);
+
+ // key reuse test
+ parameters = new AEADParameters(null, macSize, n, a);
+ encEax.init(true, parameters);
+ decEax.init(false, parameters);
+
+ runCheckVectors(count, encEax, decEax, additionalDataType, sa, p, t, c);
+ runCheckVectors(count, encEax, decEax, additionalDataType, sa, p, t, c);
+ }
+
+ private void runCheckVectors(
+ int count,
+ EAXBlockCipher encEax,
+ EAXBlockCipher decEax,
+ String additionalDataType,
+ byte[] sa,
+ byte[] p,
+ byte[] t,
+ byte[] c)
+ throws InvalidCipherTextException
+ {
+ byte[] enc = new byte[c.length];
+
+ if (sa != null)
+ {
+ encEax.processAADBytes(sa, 0, sa.length);
+ }
+
+ int len = encEax.processBytes(p, 0, p.length, enc, 0);
+
+ len += encEax.doFinal(enc, len);
+
+ if (!areEqual(c, enc))
+ {
+ fail("encrypted stream fails to match in test " + count + " with " + additionalDataType);
+ }
+
+ byte[] tmp = new byte[enc.length];
+
+ if (sa != null)
+ {
+ decEax.processAADBytes(sa, 0, sa.length);
+ }
+
+ len = decEax.processBytes(enc, 0, enc.length, tmp, 0);
+
+ len += decEax.doFinal(tmp, len);
+
+ byte[] dec = new byte[len];
+
+ System.arraycopy(tmp, 0, dec, 0, len);
+
+ if (!areEqual(p, dec))
+ {
+ fail("decrypted stream fails to match in test " + count + " with " + additionalDataType);
+ }
+
+ if (!areEqual(t, decEax.getMac()))
+ {
+ fail("MAC fails to match in test " + count + " with " + additionalDataType);
+ }
+ }
+
+ private void ivParamTest(
+ int count,
+ AEADBlockCipher eax,
+ byte[] k,
+ byte[] n)
+ throws InvalidCipherTextException
+ {
+ byte[] p = Strings.toByteArray("hello world!!");
+
+ eax.init(true, new ParametersWithIV(new KeyParameter(k), n));
+
+ byte[] enc = new byte[p.length + 8];
+
+ int len = eax.processBytes(p, 0, p.length, enc, 0);
+
+ len += eax.doFinal(enc, len);
+
+ eax.init(false, new ParametersWithIV(new KeyParameter(k), n));
+
+ byte[] tmp = new byte[enc.length];
+
+ len = eax.processBytes(enc, 0, enc.length, tmp, 0);
+
+ len += eax.doFinal(tmp, len);
+
+ byte[] dec = new byte[len];
+
+ System.arraycopy(tmp, 0, dec, 0, len);
+
+ if (!areEqual(p, dec))
+ {
+ fail("decrypted stream fails to match in test " + count);
+ }
+ }
+
+ private void randomTests()
+ throws InvalidCipherTextException
+ {
+ SecureRandom srng = new SecureRandom();
+ for (int i = 0; i < 10; ++i)
+ {
+ randomTest(srng);
+ }
+ }
+
+ private void randomTest(
+ SecureRandom srng)
+ throws InvalidCipherTextException
+ {
+ int DAT_LEN = srng.nextInt() >>> 22; // Note: JDK1.0 compatibility
+ byte[] nonce = new byte[NONCE_LEN];
+ byte[] authen = new byte[AUTHEN_LEN];
+ byte[] datIn = new byte[DAT_LEN];
+ byte[] key = new byte[16];
+ srng.nextBytes(nonce);
+ srng.nextBytes(authen);
+ srng.nextBytes(datIn);
+ srng.nextBytes(key);
+
+ AESFastEngine engine = new AESFastEngine();
+ KeyParameter sessKey = new KeyParameter(key);
+ EAXBlockCipher eaxCipher = new EAXBlockCipher(engine);
+
+ AEADParameters params = new AEADParameters(sessKey, MAC_LEN * 8, nonce, authen);
+ eaxCipher.init(true, params);
+
+ byte[] intrDat = new byte[eaxCipher.getOutputSize(datIn.length)];
+ int outOff = eaxCipher.processBytes(datIn, 0, DAT_LEN, intrDat, 0);
+ outOff += eaxCipher.doFinal(intrDat, outOff);
+
+ eaxCipher.init(false, params);
+ byte[] datOut = new byte[eaxCipher.getOutputSize(outOff)];
+ int resultLen = eaxCipher.processBytes(intrDat, 0, outOff, datOut, 0);
+ eaxCipher.doFinal(datOut, resultLen);
+
+ if (!areEqual(datIn, datOut))
+ {
+ fail("EAX roundtrip failed to match");
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new EAXTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/ECDHKEKGeneratorTest.java b/core/src/test/java/org/spongycastle/crypto/test/ECDHKEKGeneratorTest.java
new file mode 100644
index 00000000..46e9dca8
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/ECDHKEKGeneratorTest.java
@@ -0,0 +1,71 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.nist.NISTObjectIdentifiers;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.crypto.DerivationFunction;
+import org.spongycastle.crypto.DerivationParameters;
+import org.spongycastle.crypto.agreement.kdf.DHKDFParameters;
+import org.spongycastle.crypto.agreement.kdf.ECDHKEKGenerator;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * ECDHKEK Generator tests.
+ */
+public class ECDHKEKGeneratorTest
+ extends SimpleTest
+{
+ private byte[] seed1 = Hex.decode("db4a8daba1f98791d54e940175dd1a5f3a0826a1066aa9b668d4dc1e1e0790158dcad1533c03b44214d1b61fefa8b579");
+ private ASN1ObjectIdentifier alg1 = NISTObjectIdentifiers.id_aes256_wrap;
+ private byte[] result1 = Hex.decode("8ecc6d85caf25eaba823a7d620d4ab0d33e4c645f2");
+
+ private byte[] seed2 = Hex.decode("75d7487b5d3d2bfb3c69ce0365fe64e3bfab5d0d63731628a9f47eb8fddfa28c65decaf228a0b38f0c51c6a3356d7c56");
+ private ASN1ObjectIdentifier alg2 = NISTObjectIdentifiers.id_aes128_wrap;
+ private byte[] result2 = Hex.decode("042be1faca3a4a8fc859241bfb87ba35");
+
+ private byte[] seed3 = Hex.decode("fdeb6d809f997e8ac174d638734dc36d37aaf7e876e39967cd82b1cada3de772449788461ee7f856bad9305627f8e48b");
+ private ASN1ObjectIdentifier alg3 = PKCSObjectIdentifiers.id_alg_CMS3DESwrap;
+ private byte[] result3 = Hex.decode("bcd701fc92109b1b9d6f3b6497ad5ca9627fa8a597010305");
+
+ public ECDHKEKGeneratorTest()
+ {
+ }
+
+ public void performTest()
+ {
+ checkMask(1, new ECDHKEKGenerator(new SHA1Digest()), new DHKDFParameters(alg1, 256, seed1), result1);
+ checkMask(2, new ECDHKEKGenerator(new SHA1Digest()), new DHKDFParameters(alg2, 128, seed2), result2);
+ checkMask(3, new ECDHKEKGenerator(new SHA1Digest()), new DHKDFParameters(alg3, 192, seed3), result3);
+ }
+
+ private void checkMask(
+ int count,
+ DerivationFunction kdf,
+ DerivationParameters params,
+ byte[] result)
+ {
+ byte[] data = new byte[result.length];
+
+ kdf.init(params);
+
+ kdf.generateBytes(data, 0, data.length);
+
+ if (!areEqual(result, data))
+ {
+ fail("ECDHKEKGenerator failed generator test " + count);
+ }
+ }
+
+ public String getName()
+ {
+ return "ECDHKEKGenerator";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new ECDHKEKGeneratorTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/ECGOST3410Test.java b/core/src/test/java/org/spongycastle/crypto/test/ECGOST3410Test.java
new file mode 100644
index 00000000..2d7900d9
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/ECGOST3410Test.java
@@ -0,0 +1,327 @@
+package org.spongycastle.crypto.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.digests.GOST3411Digest;
+import org.spongycastle.crypto.generators.ECKeyPairGenerator;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECKeyGenerationParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.signers.ECGOST3410Signer;
+import org.spongycastle.math.ec.ECConstants;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.FixedSecureRandom;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * ECGOST3410 tests are taken from GOST R 34.10-2001.
+ */
+public class ECGOST3410Test
+ extends SimpleTest
+ {
+ byte[] hashmessage = Hex.decode("3042453136414534424341374533364339313734453431443642453241453435");
+
+ /**
+ * ECGOST3410 over the field Fp<br>
+ */
+ BigInteger r = new BigInteger("29700980915817952874371204983938256990422752107994319651632687982059210933395");
+ BigInteger s = new BigInteger("574973400270084654178925310019147038455227042649098563933718999175515839552");
+
+ byte[] kData = new BigInteger("53854137677348463731403841147996619241504003434302020712960838528893196233395").toByteArray();
+
+ SecureRandom k = new FixedSecureRandom(kData);
+
+ private void ecGOST3410_TEST()
+ {
+ BigInteger mod_p = new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564821041"); //p
+ BigInteger mod_q = new BigInteger("57896044618658097711785492504343953927082934583725450622380973592137631069619");
+
+ ECCurve.Fp curve = new ECCurve.Fp(
+ mod_p, // p
+ new BigInteger("7"), // a
+ new BigInteger("43308876546767276905765904595650931995942111794451039583252968842033849580414"), // b
+ mod_q, ECConstants.ONE);
+
+ ECDomainParameters params = new ECDomainParameters(
+ curve,
+ curve.createPoint(
+ new BigInteger("2"), // x
+ new BigInteger("4018974056539037503335449422937059775635739389905545080690979365213431566280")), // y
+ mod_q);
+
+ ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+ new BigInteger("55441196065363246126355624130324183196576709222340016572108097750006097525544"), // d
+ params);
+
+ ParametersWithRandom param = new ParametersWithRandom(priKey, k);
+
+ ECGOST3410Signer ecgost3410 = new ECGOST3410Signer();
+
+ ecgost3410.init(true, param);
+
+ byte[] mVal = new BigInteger("20798893674476452017134061561508270130637142515379653289952617252661468872421").toByteArray();
+ byte[] message = new byte[mVal.length];
+
+ for (int i = 0; i != mVal.length; i++)
+ {
+ message[i] = mVal[mVal.length - 1 - i];
+ }
+
+ BigInteger[] sig = ecgost3410.generateSignature(message);
+
+ if (!r.equals(sig[0]))
+ {
+ fail("r component wrong.", r, sig[0]);
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ fail("s component wrong.", s, sig[1]);
+ }
+
+ // Verify the signature
+ ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+ curve.createPoint(
+ new BigInteger("57520216126176808443631405023338071176630104906313632182896741342206604859403"), // x
+ new BigInteger("17614944419213781543809391949654080031942662045363639260709847859438286763994")), // y
+ params);
+
+ ecgost3410.init(false, pubKey);
+ if (!ecgost3410.verifySignature(message, sig[0], sig[1]))
+ {
+ fail("verification fails");
+ }
+ }
+
+ /**
+ * Test Sign & Verify with test parameters
+ * see: http://www.ietf.org/internet-drafts/draft-popov-cryptopro-cpalgs-01.txt
+ * gostR3410-2001-TestParamSet P.46
+ */
+ private void ecGOST3410_TestParam()
+ {
+ SecureRandom random = new SecureRandom();
+
+ BigInteger mod_p = new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564821041"); //p
+ BigInteger mod_q = new BigInteger("57896044618658097711785492504343953927082934583725450622380973592137631069619");
+
+ ECCurve.Fp curve = new ECCurve.Fp(
+ mod_p, // p
+ new BigInteger("7"), // a
+ new BigInteger("43308876546767276905765904595650931995942111794451039583252968842033849580414"), // b
+ mod_q, ECConstants.ONE);
+
+ ECDomainParameters params = new ECDomainParameters(
+ curve,
+ curve.createPoint(
+ new BigInteger("2"), // x
+ new BigInteger("4018974056539037503335449422937059775635739389905545080690979365213431566280")), // y
+ mod_q);
+
+ ECKeyPairGenerator pGen = new ECKeyPairGenerator();
+ ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(
+ params,
+ random);
+
+ pGen.init(genParam);
+
+ AsymmetricCipherKeyPair pair = pGen.generateKeyPair();
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
+
+ ECGOST3410Signer ecgost3410 = new ECGOST3410Signer();
+
+ ecgost3410.init(true, param);
+
+ //get hash message using the digest GOST3411.
+ byte[] message = "Message for sign".getBytes();
+ GOST3411Digest gost3411 = new GOST3411Digest();
+ gost3411.update(message, 0, message.length);
+ byte[] hashmessage = new byte[gost3411.getDigestSize()];
+ gost3411.doFinal(hashmessage, 0);
+
+ BigInteger[] sig = ecgost3410.generateSignature(hashmessage);
+
+ ecgost3410.init(false, pair.getPublic());
+
+ if (!ecgost3410.verifySignature(hashmessage, sig[0], sig[1]))
+ {
+ fail("signature fails");
+ }
+ }
+
+ /**
+ * Test Sign & Verify with A parameters
+ * see: http://www.ietf.org/internet-drafts/draft-popov-cryptopro-cpalgs-01.txt
+ * gostR3410-2001-CryptoPro-A-ParamSet P.47
+ */
+ public void ecGOST3410_AParam()
+ {
+ SecureRandom random = new SecureRandom();
+
+ BigInteger mod_p = new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639319"); //p
+ BigInteger mod_q = new BigInteger("115792089237316195423570985008687907853073762908499243225378155805079068850323");
+
+ ECCurve.Fp curve = new ECCurve.Fp(
+ mod_p, // p
+ new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639316"), // a
+ new BigInteger("166"), // b
+ mod_q, ECConstants.ONE);
+
+ ECDomainParameters params = new ECDomainParameters(
+ curve,
+ curve.createPoint(
+ new BigInteger("1"), // x
+ new BigInteger("64033881142927202683649881450433473985931760268884941288852745803908878638612")), // y
+ mod_q);
+
+ ECKeyPairGenerator pGen = new ECKeyPairGenerator();
+ ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(
+ params,
+ random);
+
+ pGen.init(genParam);
+
+ AsymmetricCipherKeyPair pair = pGen.generateKeyPair();
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
+
+ ECGOST3410Signer ecgost3410 = new ECGOST3410Signer();
+
+ ecgost3410.init(true, param);
+
+ BigInteger[] sig = ecgost3410.generateSignature(hashmessage);
+
+ ecgost3410.init(false, pair.getPublic());
+
+ if (!ecgost3410.verifySignature(hashmessage, sig[0], sig[1]))
+ {
+ fail("signature fails");
+ }
+ }
+
+ /**
+ * Test Sign & Verify with B parameters
+ * see: http://www.ietf.org/internet-drafts/draft-popov-cryptopro-cpalgs-01.txt
+ * gostR3410-2001-CryptoPro-B-ParamSet P.47-48
+ */
+ private void ecGOST3410_BParam()
+ {
+ SecureRandom random = new SecureRandom();
+
+ BigInteger mod_p = new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564823193"); //p
+ BigInteger mod_q = new BigInteger("57896044618658097711785492504343953927102133160255826820068844496087732066703");
+
+ ECCurve.Fp curve = new ECCurve.Fp(
+ mod_p, // p
+ new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564823190"), // a
+ new BigInteger("28091019353058090096996979000309560759124368558014865957655842872397301267595"), // b
+ mod_q, ECConstants.ONE);
+
+ ECDomainParameters params = new ECDomainParameters(
+ curve,
+ curve.createPoint(
+ new BigInteger("1"), // x
+ new BigInteger("28792665814854611296992347458380284135028636778229113005756334730996303888124")), // y
+ mod_q);
+
+ ECKeyPairGenerator pGen = new ECKeyPairGenerator();
+ ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(
+ params,
+ random);
+
+ pGen.init(genParam);
+
+ AsymmetricCipherKeyPair pair = pGen.generateKeyPair();
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
+
+ ECGOST3410Signer ecgost3410 = new ECGOST3410Signer();
+
+ ecgost3410.init(true, param);
+
+ BigInteger[] sig = ecgost3410.generateSignature(hashmessage);
+
+ ecgost3410.init(false, pair.getPublic());
+
+ if (!ecgost3410.verifySignature(hashmessage, sig[0], sig[1]))
+ {
+ fail("signature fails");
+ }
+ }
+
+ /**
+ * Test Sign & Verify with C parameters
+ * see: http://www.ietf.org/internet-drafts/draft-popov-cryptopro-cpalgs-01.txt
+ * gostR3410-2001-CryptoPro-C-ParamSet P.48
+ */
+ private void ecGOST3410_CParam()
+ {
+ SecureRandom random = new SecureRandom();
+
+ BigInteger mod_p = new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502619"); //p
+ BigInteger mod_q = new BigInteger("70390085352083305199547718019018437840920882647164081035322601458352298396601");
+
+ ECCurve.Fp curve = new ECCurve.Fp(
+ mod_p, // p
+ new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502616"), // a
+ new BigInteger("32858"), // b
+ mod_q, ECConstants.ONE);
+
+ ECDomainParameters params = new ECDomainParameters(
+ curve,
+ curve.createPoint(
+ new BigInteger("0"), // x
+ new BigInteger("29818893917731240733471273240314769927240550812383695689146495261604565990247")), // y
+ mod_q);
+
+ ECKeyPairGenerator pGen = new ECKeyPairGenerator();
+ ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(
+ params,
+ random);
+
+ pGen.init(genParam);
+
+ AsymmetricCipherKeyPair pair = pGen.generateKeyPair();
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
+
+ ECGOST3410Signer ecgost3410 = new ECGOST3410Signer();
+
+ ecgost3410.init(true, param);
+
+ BigInteger[] sig = ecgost3410.generateSignature(hashmessage);
+
+ ecgost3410.init(false, pair.getPublic());
+
+ if (!ecgost3410.verifySignature(hashmessage, sig[0], sig[1]))
+ {
+ fail("signature fails");
+ }
+ }
+
+ public String getName()
+ {
+ return "ECGOST3410";
+ }
+
+ public void performTest()
+ {
+ ecGOST3410_TEST();
+ ecGOST3410_TestParam();
+ ecGOST3410_AParam();
+ ecGOST3410_BParam();
+ ecGOST3410_CParam();
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new ECGOST3410Test());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/ECIESKeyEncapsulationTest.java b/core/src/test/java/org/spongycastle/crypto/test/ECIESKeyEncapsulationTest.java
new file mode 100755
index 00000000..10a73411
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/ECIESKeyEncapsulationTest.java
@@ -0,0 +1,138 @@
+package org.spongycastle.crypto.test;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.asn1.sec.SECNamedCurves;
+import org.spongycastle.asn1.x9.X9ECParameters;
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.generators.ECKeyPairGenerator;
+import org.spongycastle.crypto.generators.KDF2BytesGenerator;
+import org.spongycastle.crypto.kems.ECIESKeyEncapsulation;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECKeyGenerationParameters;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * Tests for the ECIES Key Encapsulation Mechanism
+ */
+public class ECIESKeyEncapsulationTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "ECIESKeyEncapsulation";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+
+ // Set EC domain parameters and generate key pair
+ X9ECParameters spec = SECNamedCurves.getByName("secp224r1");
+ ECDomainParameters ecDomain = new ECDomainParameters(spec.getCurve(), spec.getG(), spec.getN());
+ ECKeyPairGenerator ecGen = new ECKeyPairGenerator();
+
+ ecGen.init(new ECKeyGenerationParameters(ecDomain, new SecureRandom()));
+
+ AsymmetricCipherKeyPair keys = ecGen.generateKeyPair();
+
+ // Set ECIES-KEM parameters
+ ECIESKeyEncapsulation kem;
+ KDF2BytesGenerator kdf = new KDF2BytesGenerator(new SHA1Digest());
+ SecureRandom rnd = new SecureRandom();
+ byte[] out = new byte[57];
+ KeyParameter key1, key2;
+
+ // Test basic ECIES-KEM
+ kem = new ECIESKeyEncapsulation(kdf, rnd);
+
+ kem.init(keys.getPublic());
+ key1 = (KeyParameter)kem.encrypt(out, 128);
+
+ kem.init(keys.getPrivate());
+ key2 = (KeyParameter)kem.decrypt(out, 128);
+
+ if (!areEqual(key1.getKey(), key2.getKey()))
+ {
+ fail("failed basic test");
+ }
+
+ // Test ECIES-KEM using new cofactor mode
+ kem = new ECIESKeyEncapsulation(kdf, rnd, true, false, false);
+
+ kem.init(keys.getPublic());
+ key1 = (KeyParameter)kem.encrypt(out, 128);
+
+ kem.init(keys.getPrivate());
+ key2 = (KeyParameter)kem.decrypt(out, 128);
+
+ if (!areEqual(key1.getKey(), key2.getKey()))
+ {
+ fail("failed cofactor test");
+ }
+
+ // Test ECIES-KEM using old cofactor mode
+ kem = new ECIESKeyEncapsulation(kdf, rnd, false, true, false);
+
+ kem.init(keys.getPublic());
+ key1 = (KeyParameter)kem.encrypt(out, 128);
+
+ kem.init(keys.getPrivate());
+ key2 = (KeyParameter)kem.decrypt(out, 128);
+
+ if (!areEqual(key1.getKey(), key2.getKey()))
+ {
+ fail("failed old cofactor test");
+ }
+
+ // Test ECIES-KEM using single hash mode
+ kem = new ECIESKeyEncapsulation(kdf, rnd, false, false, true);
+
+ kem.init(keys.getPublic());
+ key1 = (KeyParameter)kem.encrypt(out, 128);
+
+ kem.init(keys.getPrivate());
+ key2 = (KeyParameter)kem.decrypt(out, 128);
+
+ if (!areEqual(key1.getKey(), key2.getKey()))
+ {
+ fail("failed single hash test");
+ }
+
+ // Test ECIES-KEM using new cofactor mode and single hash mode
+ kem = new ECIESKeyEncapsulation(kdf, rnd, true, false, true);
+
+ kem.init(keys.getPublic());
+ key1 = (KeyParameter)kem.encrypt(out, 128);
+
+ kem.init(keys.getPrivate());
+ key2 = (KeyParameter)kem.decrypt(out, 128);
+
+ if (!areEqual(key1.getKey(), key2.getKey()))
+ {
+ fail("failed cofactor and single hash test");
+ }
+
+ // Test ECIES-KEM using old cofactor mode and single hash mode
+ kem = new ECIESKeyEncapsulation(kdf, rnd, false, true, true);
+
+ kem.init(keys.getPublic());
+ key1 = (KeyParameter)kem.encrypt(out, 128);
+
+ kem.init(keys.getPrivate());
+ key2 = (KeyParameter)kem.decrypt(out, 128);
+
+ if (!areEqual(key1.getKey(), key2.getKey()))
+ {
+ fail("failed old cofactor and single hash test");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new ECIESKeyEncapsulationTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/ECIESTest.java b/core/src/test/java/org/spongycastle/crypto/test/ECIESTest.java
new file mode 100644
index 00000000..98593ae6
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/ECIESTest.java
@@ -0,0 +1,377 @@
+package org.spongycastle.crypto.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.BufferedBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.KeyEncoder;
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.crypto.agreement.ECDHBasicAgreement;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.engines.IESEngine;
+import org.spongycastle.crypto.engines.TwofishEngine;
+import org.spongycastle.crypto.generators.ECKeyPairGenerator;
+import org.spongycastle.crypto.generators.EphemeralKeyPairGenerator;
+import org.spongycastle.crypto.generators.KDF2BytesGenerator;
+import org.spongycastle.crypto.macs.HMac;
+import org.spongycastle.crypto.modes.CBCBlockCipher;
+import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECKeyGenerationParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.crypto.params.IESParameters;
+import org.spongycastle.crypto.params.IESWithCipherParameters;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.crypto.parsers.ECIESPublicKeyParser;
+import org.spongycastle.math.ec.ECConstants;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * test for ECIES - Elliptic Curve Integrated Encryption Scheme
+ */
+public class ECIESTest
+ extends SimpleTest
+{
+ private static byte[] TWOFISH_IV = Hex.decode("000102030405060708090a0b0c0d0e0f");
+
+ ECIESTest()
+ {
+ }
+
+ public String getName()
+ {
+ return "ECIES";
+ }
+
+ private void doStaticTest(byte[] iv)
+ throws Exception
+ {
+ BigInteger n = new BigInteger("6277101735386680763835789423176059013767194773182842284081");
+
+ ECCurve.Fp curve = new ECCurve.Fp(
+ new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q
+ new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a
+ new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16), // b
+ n, ECConstants.ONE);
+
+ ECDomainParameters params = new ECDomainParameters(
+ curve,
+ curve.decodePoint(Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), // G
+ n);
+
+ ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+ new BigInteger("651056770906015076056810763456358567190100156695615665659"), // d
+ params);
+
+ ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+ curve.decodePoint(Hex.decode("0262b12d60690cdcf330babab6e69763b471f994dd702d16a5")), // Q
+ params);
+
+ AsymmetricCipherKeyPair p1 = new AsymmetricCipherKeyPair(pubKey, priKey);
+ AsymmetricCipherKeyPair p2 = new AsymmetricCipherKeyPair(pubKey, priKey);
+
+ //
+ // stream test
+ //
+ IESEngine i1 = new IESEngine(
+ new ECDHBasicAgreement(),
+ new KDF2BytesGenerator(new SHA1Digest()),
+ new HMac(new SHA1Digest()));
+ IESEngine i2 = new IESEngine(
+ new ECDHBasicAgreement(),
+ new KDF2BytesGenerator(new SHA1Digest()),
+ new HMac(new SHA1Digest()));
+ byte[] d = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
+ byte[] e = new byte[] { 8, 7, 6, 5, 4, 3, 2, 1 };
+ CipherParameters p = new IESParameters(d, e, 64);
+
+ i1.init(true, p1.getPrivate(), p2.getPublic(), p);
+ i2.init(false, p2.getPrivate(), p1.getPublic(), p);
+
+ byte[] message = Hex.decode("1234567890abcdef");
+
+ byte[] out1 = i1.processBlock(message, 0, message.length);
+
+ if (!areEqual(out1, Hex.decode("468d89877e8238802403ec4cb6b329faeccfa6f3a730f2cdb3c0a8e8")))
+ {
+ fail("stream cipher test failed on enc");
+ }
+
+ byte[] out2 = i2.processBlock(out1, 0, out1.length);
+
+ if (!areEqual(out2, message))
+ {
+ fail("stream cipher test failed");
+ }
+
+ //
+ // twofish with CBC
+ //
+ BufferedBlockCipher c1 = new PaddedBufferedBlockCipher(
+ new CBCBlockCipher(new TwofishEngine()));
+ BufferedBlockCipher c2 = new PaddedBufferedBlockCipher(
+ new CBCBlockCipher(new TwofishEngine()));
+ i1 = new IESEngine(
+ new ECDHBasicAgreement(),
+ new KDF2BytesGenerator(new SHA1Digest()),
+ new HMac(new SHA1Digest()),
+ c1);
+ i2 = new IESEngine(
+ new ECDHBasicAgreement(),
+ new KDF2BytesGenerator(new SHA1Digest()),
+ new HMac(new SHA1Digest()),
+ c2);
+ d = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
+ e = new byte[] { 8, 7, 6, 5, 4, 3, 2, 1 };
+ p = new IESWithCipherParameters(d, e, 64, 128);
+
+ if (iv != null)
+ {
+ p = new ParametersWithIV(p, iv);
+ }
+
+ i1.init(true, p1.getPrivate(), p2.getPublic(), p);
+ i2.init(false, p2.getPrivate(), p1.getPublic(), p);
+
+ message = Hex.decode("1234567890abcdef");
+
+ out1 = i1.processBlock(message, 0, message.length);
+
+ if (!areEqual(out1, (iv == null) ?
+ Hex.decode("b8a06ea5c2b9df28b58a0a90a734cde8c9c02903e5c220021fe4417410d1e53a32a71696")
+ : Hex.decode("f246b0e26a2711992cac9c590d08e45c5e730b7c0f4218bb064e27b7dd7c8a3bd8bf01c3")))
+ {
+ fail("twofish cipher test failed on enc");
+ }
+
+ out2 = i2.processBlock(out1, 0, out1.length);
+
+ if (!areEqual(out2, message))
+ {
+ fail("twofish cipher test failed");
+ }
+ }
+
+ private void doEphemeralTest(byte[] iv)
+ throws Exception
+ {
+ BigInteger n = new BigInteger("6277101735386680763835789423176059013767194773182842284081");
+
+ ECCurve.Fp curve = new ECCurve.Fp(
+ new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q
+ new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a
+ new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16), // b
+ n, ECConstants.ONE);
+
+ ECDomainParameters params = new ECDomainParameters(
+ curve,
+ curve.decodePoint(Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), // G
+ n);
+
+ ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+ new BigInteger("651056770906015076056810763456358567190100156695615665659"), // d
+ params);
+
+ ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+ curve.decodePoint(Hex.decode("0262b12d60690cdcf330babab6e69763b471f994dd702d16a5")), // Q
+ params);
+
+ AsymmetricCipherKeyPair p1 = new AsymmetricCipherKeyPair(pubKey, priKey);
+ AsymmetricCipherKeyPair p2 = new AsymmetricCipherKeyPair(pubKey, priKey);
+
+ // Generate the ephemeral key pair
+ ECKeyPairGenerator gen = new ECKeyPairGenerator();
+ gen.init(new ECKeyGenerationParameters(params, new SecureRandom()));
+
+ EphemeralKeyPairGenerator ephKeyGen = new EphemeralKeyPairGenerator(gen, new KeyEncoder()
+ {
+ public byte[] getEncoded(AsymmetricKeyParameter keyParameter)
+ {
+ return ((ECPublicKeyParameters)keyParameter).getQ().getEncoded();
+ }
+ });
+
+ //
+ // stream test
+ //
+ IESEngine i1 = new IESEngine(
+ new ECDHBasicAgreement(),
+ new KDF2BytesGenerator(new SHA1Digest()),
+ new HMac(new SHA1Digest()));
+ IESEngine i2 = new IESEngine(
+ new ECDHBasicAgreement(),
+ new KDF2BytesGenerator(new SHA1Digest()),
+ new HMac(new SHA1Digest()));
+
+ byte[] d = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
+ byte[] e = new byte[] { 8, 7, 6, 5, 4, 3, 2, 1 };
+ CipherParameters p = new IESParameters(d, e, 64);
+
+ i1.init(p2.getPublic(), p, ephKeyGen);
+ i2.init(p2.getPrivate(), p, new ECIESPublicKeyParser(params));
+
+ byte[] message = Hex.decode("1234567890abcdef");
+
+ byte[] out1 = i1.processBlock(message, 0, message.length);
+
+ byte[] out2 = i2.processBlock(out1, 0, out1.length);
+
+ if (!areEqual(out2, message))
+ {
+ fail("stream cipher test failed");
+ }
+
+ //
+ // twofish with CBC
+ //
+ BufferedBlockCipher c1 = new PaddedBufferedBlockCipher(
+ new CBCBlockCipher(new TwofishEngine()));
+ BufferedBlockCipher c2 = new PaddedBufferedBlockCipher(
+ new CBCBlockCipher(new TwofishEngine()));
+ i1 = new IESEngine(
+ new ECDHBasicAgreement(),
+ new KDF2BytesGenerator(new SHA1Digest()),
+ new HMac(new SHA1Digest()),
+ c1);
+ i2 = new IESEngine(
+ new ECDHBasicAgreement(),
+ new KDF2BytesGenerator(new SHA1Digest()),
+ new HMac(new SHA1Digest()),
+ c2);
+ d = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
+ e = new byte[] { 8, 7, 6, 5, 4, 3, 2, 1 };
+ p = new IESWithCipherParameters(d, e, 64, 128);
+
+ if (iv != null)
+ {
+ p = new ParametersWithIV(p, iv);
+ }
+
+ i1.init(p2.getPublic(), p, ephKeyGen);
+ i2.init(p2.getPrivate(), p, new ECIESPublicKeyParser(params));
+
+ message = Hex.decode("1234567890abcdef");
+
+ out1 = i1.processBlock(message, 0, message.length);
+
+ out2 = i2.processBlock(out1, 0, out1.length);
+
+ if (!areEqual(out2, message))
+ {
+ fail("twofish cipher test failed");
+ }
+ }
+
+ private void doTest(AsymmetricCipherKeyPair p1, AsymmetricCipherKeyPair p2)
+ throws Exception
+ {
+ //
+ // stream test
+ //
+ IESEngine i1 = new IESEngine(
+ new ECDHBasicAgreement(),
+ new KDF2BytesGenerator(new SHA1Digest()),
+ new HMac(new SHA1Digest()));
+ IESEngine i2 = new IESEngine(
+ new ECDHBasicAgreement(),
+ new KDF2BytesGenerator(new SHA1Digest()),
+ new HMac(new SHA1Digest()));
+ byte[] d = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
+ byte[] e = new byte[] { 8, 7, 6, 5, 4, 3, 2, 1 };
+ IESParameters p = new IESParameters(d, e, 64);
+
+ i1.init(true, p1.getPrivate(), p2.getPublic(), p);
+ i2.init(false, p2.getPrivate(), p1.getPublic(), p);
+
+ byte[] message = Hex.decode("1234567890abcdef");
+
+ byte[] out1 = i1.processBlock(message, 0, message.length);
+
+ byte[] out2 = i2.processBlock(out1, 0, out1.length);
+
+ if (!areEqual(out2, message))
+ {
+ fail("stream cipher test failed");
+ }
+
+ //
+ // twofish with CBC
+ //
+ BufferedBlockCipher c1 = new PaddedBufferedBlockCipher(
+ new CBCBlockCipher(new TwofishEngine()));
+ BufferedBlockCipher c2 = new PaddedBufferedBlockCipher(
+ new CBCBlockCipher(new TwofishEngine()));
+ i1 = new IESEngine(
+ new ECDHBasicAgreement(),
+ new KDF2BytesGenerator(new SHA1Digest()),
+ new HMac(new SHA1Digest()),
+ c1);
+ i2 = new IESEngine(
+ new ECDHBasicAgreement(),
+ new KDF2BytesGenerator(new SHA1Digest()),
+ new HMac(new SHA1Digest()),
+ c2);
+ d = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
+ e = new byte[] { 8, 7, 6, 5, 4, 3, 2, 1 };
+ p = new IESWithCipherParameters(d, e, 64, 128);
+
+ i1.init(true, p1.getPrivate(), p2.getPublic(), p);
+ i2.init(false, p2.getPrivate(), p1.getPublic(), p);
+
+ message = Hex.decode("1234567890abcdef");
+
+ out1 = i1.processBlock(message, 0, message.length);
+
+ out2 = i2.processBlock(out1, 0, out1.length);
+
+ if (!areEqual(out2, message))
+ {
+ fail("twofish cipher test failed");
+ }
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ doStaticTest(null);
+ doStaticTest(TWOFISH_IV);
+
+ BigInteger n = new BigInteger("6277101735386680763835789423176059013767194773182842284081");
+
+ ECCurve.Fp curve = new ECCurve.Fp(
+ new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q
+ new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a
+ new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16), // b
+ n, ECConstants.ONE);
+
+ ECDomainParameters params = new ECDomainParameters(
+ curve,
+ curve.decodePoint(Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), // G
+ n);
+
+ ECKeyPairGenerator eGen = new ECKeyPairGenerator();
+ KeyGenerationParameters gParam = new ECKeyGenerationParameters(params, new SecureRandom());
+
+ eGen.init(gParam);
+
+ AsymmetricCipherKeyPair p1 = eGen.generateKeyPair();
+ AsymmetricCipherKeyPair p2 = eGen.generateKeyPair();
+
+ doTest(p1, p2);
+
+ doEphemeralTest(null);
+ doEphemeralTest(TWOFISH_IV);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new ECIESTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/ECNRTest.java b/core/src/test/java/org/spongycastle/crypto/test/ECNRTest.java
new file mode 100644
index 00000000..5a91f05a
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/ECNRTest.java
@@ -0,0 +1,99 @@
+package org.spongycastle.crypto.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.signers.ECNRSigner;
+import org.spongycastle.math.ec.ECConstants;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.util.BigIntegers;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.FixedSecureRandom;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * ECNR tests.
+ */
+public class ECNRTest
+ extends SimpleTest
+{
+ /**
+ * a basic regression test with 239 bit prime
+ */
+ BigInteger r = new BigInteger("308636143175167811492623515537541734843573549327605293463169625072911693");
+ BigInteger s = new BigInteger("852401710738814635664888632022555967400445256405412579597015412971797143");
+
+ byte[] kData = BigIntegers.asUnsignedByteArray(new BigInteger("700000017569056646655505781757157107570501575775705779575555657156756655"));
+
+ SecureRandom k = new FixedSecureRandom(true, kData);
+
+ private void ecNR239bitPrime()
+ {
+ BigInteger n = new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307");
+
+ ECCurve.Fp curve = new ECCurve.Fp(
+ new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
+ new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+ new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16), // b
+ n, ECConstants.ONE);
+
+ ECDomainParameters params = new ECDomainParameters(
+ curve,
+ curve.decodePoint(Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
+ n);
+
+ ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+ new BigInteger("876300101507107567501066130761671078357010671067781776716671676178726717"), // d
+ params);
+
+ ECNRSigner ecnr = new ECNRSigner();
+ ParametersWithRandom param = new ParametersWithRandom(priKey, k);
+
+ ecnr.init(true, param);
+
+ byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").toByteArray();
+ BigInteger[] sig = ecnr.generateSignature(message);
+
+ if (!r.equals(sig[0]))
+ {
+ fail("r component wrong.", r, sig[0]);
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ fail("s component wrong.", s, sig[1]);
+ }
+
+ // Verify the signature
+ ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+ curve.decodePoint(Hex.decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q
+ params);
+
+ ecnr.init(false, pubKey);
+ if (!ecnr.verifySignature(message, sig[0], sig[1]))
+ {
+ fail("signature fails");
+ }
+ }
+
+ public String getName()
+ {
+ return "ECNR";
+ }
+
+ public void performTest()
+ {
+ ecNR239bitPrime();
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new ECNRTest());
+ }
+}
+
diff --git a/core/src/test/java/org/spongycastle/crypto/test/ECTest.java b/core/src/test/java/org/spongycastle/crypto/test/ECTest.java
new file mode 100644
index 00000000..01fb3304
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/ECTest.java
@@ -0,0 +1,926 @@
+package org.spongycastle.crypto.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.asn1.nist.NISTNamedCurves;
+import org.spongycastle.asn1.sec.SECNamedCurves;
+import org.spongycastle.asn1.x9.X9ECParameters;
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.BasicAgreement;
+import org.spongycastle.crypto.agreement.ECDHBasicAgreement;
+import org.spongycastle.crypto.agreement.ECDHCBasicAgreement;
+import org.spongycastle.crypto.agreement.ECMQVBasicAgreement;
+import org.spongycastle.crypto.generators.ECKeyPairGenerator;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECKeyGenerationParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.crypto.params.MQVPrivateParameters;
+import org.spongycastle.crypto.params.MQVPublicParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.signers.ECDSASigner;
+import org.spongycastle.math.ec.ECConstants;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.util.BigIntegers;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.FixedSecureRandom;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * ECDSA tests are taken from X9.62.
+ */
+public class ECTest
+ extends SimpleTest
+{
+ /**
+ * X9.62 - 1998,<br>
+ * J.3.1, Page 152, ECDSA over the field Fp<br>
+ * an example with 192 bit prime
+ */
+ private void testECDSA192bitPrime()
+ {
+ BigInteger r = new BigInteger("3342403536405981729393488334694600415596881826869351677613");
+ BigInteger s = new BigInteger("5735822328888155254683894997897571951568553642892029982342");
+
+ byte[] kData = BigIntegers.asUnsignedByteArray(new BigInteger("6140507067065001063065065565667405560006161556565665656654"));
+
+ SecureRandom k = new FixedSecureRandom(kData);
+
+ BigInteger n = new BigInteger("6277101735386680763835789423176059013767194773182842284081");
+
+ ECCurve.Fp curve = new ECCurve.Fp(
+ new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q
+ new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a
+ new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16), // b
+ n, ECConstants.ONE);
+
+ ECDomainParameters params = new ECDomainParameters(
+ curve,
+ curve.decodePoint(Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), // G
+ n);
+
+ ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+ new BigInteger("651056770906015076056810763456358567190100156695615665659"), // d
+ params);
+
+ ParametersWithRandom param = new ParametersWithRandom(priKey, k);
+
+ ECDSASigner ecdsa = new ECDSASigner();
+
+ ecdsa.init(true, param);
+
+ byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").toByteArray();
+ BigInteger[] sig = ecdsa.generateSignature(message);
+
+ if (!r.equals(sig[0]))
+ {
+ fail("r component wrong." + System.getProperty("line.separator")
+ + " expecting: " + r + System.getProperty("line.separator")
+ + " got : " + sig[0]);
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ fail("s component wrong." + System.getProperty("line.separator")
+ + " expecting: " + s + System.getProperty("line.separator")
+ + " got : " + sig[1]);
+ }
+
+ // Verify the signature
+ ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+ curve.decodePoint(Hex.decode("0262b12d60690cdcf330babab6e69763b471f994dd702d16a5")), // Q
+ params);
+
+ ecdsa.init(false, pubKey);
+ if (!ecdsa.verifySignature(message, sig[0], sig[1]))
+ {
+ fail("verification fails");
+ }
+ }
+
+ private void decodeTest()
+ {
+ ECCurve.Fp curve = new ECCurve.Fp(
+ new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q
+ new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a
+ new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16)); // b
+
+ ECPoint p = curve.decodePoint(Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")).normalize();
+
+ if (!p.getAffineXCoord().toBigInteger().equals(new BigInteger("188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 16)))
+ {
+ fail("x uncompressed incorrectly");
+ }
+
+ if (!p.getAffineYCoord().toBigInteger().equals(new BigInteger("7192b95ffc8da78631011ed6b24cdd573f977a11e794811", 16)))
+ {
+ fail("y uncompressed incorrectly");
+ }
+
+ byte[] encoding = p.getEncoded();
+
+ if (!areEqual(encoding, Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")))
+ {
+ fail("point compressed incorrectly");
+ }
+ }
+
+ /**
+ * X9.62 - 1998,<br>
+ * J.3.2, Page 155, ECDSA over the field Fp<br>
+ * an example with 239 bit prime
+ */
+ private void testECDSA239bitPrime()
+ {
+ BigInteger r = new BigInteger("308636143175167811492622547300668018854959378758531778147462058306432176");
+ BigInteger s = new BigInteger("323813553209797357708078776831250505931891051755007842781978505179448783");
+
+ byte[] kData = BigIntegers.asUnsignedByteArray(new BigInteger("700000017569056646655505781757157107570501575775705779575555657156756655"));
+
+ SecureRandom k = new FixedSecureRandom(true, kData);
+
+ BigInteger n = new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307");
+
+ ECCurve.Fp curve = new ECCurve.Fp(
+ new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
+ new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+ new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16), // b
+ n, ECConstants.ONE);
+
+ ECDomainParameters params = new ECDomainParameters(
+ curve,
+ curve.decodePoint(Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
+ n);
+
+ ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+ new BigInteger("876300101507107567501066130761671078357010671067781776716671676178726717"), // d
+ params);
+
+ ECDSASigner ecdsa = new ECDSASigner();
+ ParametersWithRandom param = new ParametersWithRandom(priKey, k);
+
+ ecdsa.init(true, param);
+
+ byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").toByteArray();
+ BigInteger[] sig = ecdsa.generateSignature(message);
+
+ if (!r.equals(sig[0]))
+ {
+ fail("r component wrong." + System.getProperty("line.separator")
+ + " expecting: " + r + System.getProperty("line.separator")
+ + " got : " + sig[0]);
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ fail("s component wrong." + System.getProperty("line.separator")
+ + " expecting: " + s + System.getProperty("line.separator")
+ + " got : " + sig[1]);
+ }
+
+ // Verify the signature
+ ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+ curve.decodePoint(Hex.decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q
+ params);
+
+ ecdsa.init(false, pubKey);
+ if (!ecdsa.verifySignature(message, sig[0], sig[1]))
+ {
+ fail("signature fails");
+ }
+ }
+
+
+ /**
+ * X9.62 - 1998,<br>
+ * J.2.1, Page 100, ECDSA over the field F2m<br>
+ * an example with 191 bit binary field
+ */
+ private void testECDSA191bitBinary()
+ {
+ BigInteger r = new BigInteger("87194383164871543355722284926904419997237591535066528048");
+ BigInteger s = new BigInteger("308992691965804947361541664549085895292153777025772063598");
+
+ byte[] kData = BigIntegers.asUnsignedByteArray(new BigInteger("1542725565216523985789236956265265265235675811949404040041"));
+
+ SecureRandom k = new FixedSecureRandom(kData);
+
+ BigInteger n = new BigInteger("1569275433846670190958947355803350458831205595451630533029");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve.F2m curve = new ECCurve.F2m(
+ 191, // m
+ 9, //k
+ new BigInteger("2866537B676752636A68F56554E12640276B649EF7526267", 16), // a
+ new BigInteger("2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC", 16), // b
+ n, h);
+
+ ECDomainParameters params = new ECDomainParameters(
+ curve,
+ curve.decodePoint(Hex.decode("0436B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D765BE73433B3F95E332932E70EA245CA2418EA0EF98018FB")), // G
+ n, h);
+
+ ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+ new BigInteger("1275552191113212300012030439187146164646146646466749494799"), // d
+ params);
+
+ ECDSASigner ecdsa = new ECDSASigner();
+ ParametersWithRandom param = new ParametersWithRandom(priKey, k);
+
+ ecdsa.init(true, param);
+
+ byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").toByteArray();
+ BigInteger[] sig = ecdsa.generateSignature(message);
+
+ if (!r.equals(sig[0]))
+ {
+ fail("r component wrong." + System.getProperty("line.separator")
+ + " expecting: " + r + System.getProperty("line.separator")
+ + " got : " + sig[0]);
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ fail("s component wrong." + System.getProperty("line.separator")
+ + " expecting: " + s + System.getProperty("line.separator")
+ + " got : " + sig[1]);
+ }
+
+ // Verify the signature
+ ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+ curve.decodePoint(Hex.decode("045DE37E756BD55D72E3768CB396FFEB962614DEA4CE28A2E755C0E0E02F5FB132CAF416EF85B229BBB8E1352003125BA1")), // Q
+ params);
+
+ ecdsa.init(false, pubKey);
+ if (!ecdsa.verifySignature(message, sig[0], sig[1]))
+ {
+ fail("signature fails");
+ }
+ }
+
+
+ /**
+ * X9.62 - 1998,<br>
+ * J.2.1, Page 100, ECDSA over the field F2m<br>
+ * an example with 191 bit binary field
+ */
+ private void testECDSA239bitBinary()
+ {
+ BigInteger r = new BigInteger("21596333210419611985018340039034612628818151486841789642455876922391552");
+ BigInteger s = new BigInteger("197030374000731686738334997654997227052849804072198819102649413465737174");
+
+ byte[] kData = BigIntegers.asUnsignedByteArray(new BigInteger("171278725565216523967285789236956265265265235675811949404040041670216363"));
+
+ SecureRandom k = new FixedSecureRandom(kData);
+
+ BigInteger n = new BigInteger("220855883097298041197912187592864814557886993776713230936715041207411783");
+ BigInteger h = BigInteger.valueOf(4);
+
+ ECCurve.F2m curve = new ECCurve.F2m(
+ 239, // m
+ 36, //k
+ new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), // a
+ new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16), // b
+ n, h);
+
+ ECDomainParameters params = new ECDomainParameters(
+ curve,
+ curve.decodePoint(Hex.decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G
+ n, h);
+
+ ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+ new BigInteger("145642755521911534651321230007534120304391871461646461466464667494947990"), // d
+ params);
+
+ ECDSASigner ecdsa = new ECDSASigner();
+ ParametersWithRandom param = new ParametersWithRandom(priKey, k);
+
+ ecdsa.init(true, param);
+
+ byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").toByteArray();
+ BigInteger[] sig = ecdsa.generateSignature(message);
+
+ if (!r.equals(sig[0]))
+ {
+ fail("r component wrong." + System.getProperty("line.separator")
+ + " expecting: " + r + System.getProperty("line.separator")
+ + " got : " + sig[0]);
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ fail("s component wrong." + System.getProperty("line.separator")
+ + " expecting: " + s + System.getProperty("line.separator")
+ + " got : " + sig[1]);
+ }
+
+ // Verify the signature
+ ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+ curve.decodePoint(Hex.decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q
+ params);
+
+ ecdsa.init(false, pubKey);
+ if (!ecdsa.verifySignature(message, sig[0], sig[1]))
+ {
+ fail("signature fails");
+ }
+ }
+
+ // L 4.1 X9.62 2005
+ private void testECDSAP224sha224()
+ {
+ X9ECParameters p = NISTNamedCurves.getByName("P-224");
+ ECDomainParameters params = new ECDomainParameters(p.getCurve(), p.getG(), p.getN(), p.getH());
+ ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+ new BigInteger("6081831502424510080126737029209236539191290354021104541805484120491"), // d
+ params);
+ SecureRandom k = new FixedSecureRandom(BigIntegers.asUnsignedByteArray(new BigInteger("15456715103636396133226117016818339719732885723579037388121116732601")));
+
+ byte[] M = Hex.decode("8797A3C693CC292441039A4E6BAB7387F3B4F2A63D00ED384B378C79");
+
+ ECDSASigner dsa = new ECDSASigner();
+
+ dsa.init(true, new ParametersWithRandom(priKey, k));
+
+ BigInteger[] sig = dsa.generateSignature(M);
+
+ BigInteger r = new BigInteger("26477406756127720855365980332052585411804331993436302005017227573742");
+ BigInteger s = new BigInteger("17694958233103667059888193972742186995283044672015112738919822429978");
+
+ if (!r.equals(sig[0]))
+ {
+ fail("r component wrong." + System.getProperty("line.separator")
+ + " expecting: " + r + System.getProperty("line.separator")
+ + " got : " + sig[0]);
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ fail("s component wrong." + System.getProperty("line.separator")
+ + " expecting: " + s + System.getProperty("line.separator")
+ + " got : " + sig[1]);
+ }
+
+ // Verify the signature
+ ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+ params.getCurve().decodePoint(Hex.decode("03FD44EC11F9D43D9D23B1E1D1C9ED6519B40ECF0C79F48CF476CC43F1")), // Q
+ params);
+
+ dsa.init(false, pubKey);
+ if (!dsa.verifySignature(M, sig[0], sig[1]))
+ {
+ fail("signature fails");
+ }
+ }
+
+ private void testECDSASecP224k1sha256()
+ {
+ X9ECParameters p = SECNamedCurves.getByName("secp224k1");
+ ECDomainParameters params = new ECDomainParameters(p.getCurve(), p.getG(), p.getN(), p.getH());
+ ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+ new BigInteger("BE6F6E91FE96840A6518B56F3FE21689903A64FA729057AB872A9F51", 16), // d
+ params);
+ SecureRandom k = new FixedSecureRandom(Hex.decode("00c39beac93db21c3266084429eb9b846b787c094f23a4de66447efbb3"));
+
+ byte[] M = Hex.decode("E5D5A7ADF73C5476FAEE93A2C76CE94DC0557DB04CDC189504779117920B896D");
+
+ ECDSASigner dsa = new ECDSASigner();
+
+ dsa.init(true, new ParametersWithRandom(priKey, k));
+
+ BigInteger[] sig = dsa.generateSignature(M);
+
+ BigInteger r = new BigInteger("8163E5941BED41DA441B33E653C632A55A110893133351E20CE7CB75", 16);
+ BigInteger s = new BigInteger("D12C3FC289DDD5F6890DCE26B65792C8C50E68BF551D617D47DF15A8", 16);
+
+ if (!r.equals(sig[0]))
+ {
+ fail("r component wrong." + System.getProperty("line.separator")
+ + " expecting: " + r + System.getProperty("line.separator")
+ + " got : " + sig[0]);
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ fail("s component wrong." + System.getProperty("line.separator")
+ + " expecting: " + s + System.getProperty("line.separator")
+ + " got : " + sig[1]);
+ }
+
+ // Verify the signature
+ ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+ params.getCurve().decodePoint(Hex.decode("04C5C9B38D3603FCCD6994CBB9594E152B658721E483669BB42728520F484B537647EC816E58A8284D3B89DFEDB173AFDC214ECA95A836FA7C")), // Q
+ params);
+
+ dsa.init(false, pubKey);
+ if (!dsa.verifySignature(M, sig[0], sig[1]))
+ {
+ fail("signature fails");
+ }
+ }
+
+ // L4.2 X9.62 2005
+ private void testECDSAP256sha256()
+ {
+ X9ECParameters p = NISTNamedCurves.getByName("P-256");
+ ECDomainParameters params = new ECDomainParameters(p.getCurve(), p.getG(), p.getN(), p.getH());
+ ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+ new BigInteger("20186677036482506117540275567393538695075300175221296989956723148347484984008"), // d
+ params);
+ SecureRandom k = new FixedSecureRandom(BigIntegers.asUnsignedByteArray(new BigInteger("72546832179840998877302529996971396893172522460793442785601695562409154906335")));
+
+ byte[] M = Hex.decode("1BD4ED430B0F384B4E8D458EFF1A8A553286D7AC21CB2F6806172EF5F94A06AD");
+
+ ECDSASigner dsa = new ECDSASigner();
+
+ dsa.init(true, new ParametersWithRandom(priKey, k));
+
+ BigInteger[] sig = dsa.generateSignature(M);
+
+ BigInteger r = new BigInteger("97354732615802252173078420023658453040116611318111190383344590814578738210384");
+ BigInteger s = new BigInteger("98506158880355671805367324764306888225238061309262649376965428126566081727535");
+
+ if (!r.equals(sig[0]))
+ {
+ fail("r component wrong." + System.getProperty("line.separator")
+ + " expecting: " + r + System.getProperty("line.separator")
+ + " got : " + sig[0]);
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ fail("s component wrong." + System.getProperty("line.separator")
+ + " expecting: " + s + System.getProperty("line.separator")
+ + " got : " + sig[1]);
+ }
+
+ // Verify the signature
+ ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+ params.getCurve().decodePoint(Hex.decode("03596375E6CE57E0F20294FC46BDFCFD19A39F8161B58695B3EC5B3D16427C274D")), // Q
+ params);
+
+ dsa.init(false, pubKey);
+ if (!dsa.verifySignature(M, sig[0], sig[1]))
+ {
+ fail("signature fails");
+ }
+ }
+
+ private void testECDSAP224OneByteOver()
+ {
+ X9ECParameters p = NISTNamedCurves.getByName("P-224");
+ ECDomainParameters params = new ECDomainParameters(p.getCurve(), p.getG(), p.getN(), p.getH());
+ ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+ new BigInteger("6081831502424510080126737029209236539191290354021104541805484120491"), // d
+ params);
+ SecureRandom k = new FixedSecureRandom(BigIntegers.asUnsignedByteArray(new BigInteger("15456715103636396133226117016818339719732885723579037388121116732601")));
+
+ byte[] M = Hex.decode("8797A3C693CC292441039A4E6BAB7387F3B4F2A63D00ED384B378C79FF");
+
+ ECDSASigner dsa = new ECDSASigner();
+
+ dsa.init(true, new ParametersWithRandom(priKey, k));
+
+ BigInteger[] sig = dsa.generateSignature(M);
+
+ BigInteger r = new BigInteger("26477406756127720855365980332052585411804331993436302005017227573742");
+ BigInteger s = new BigInteger("17694958233103667059888193972742186995283044672015112738919822429978");
+
+ if (!r.equals(sig[0]))
+ {
+ fail("r component wrong." + System.getProperty("line.separator")
+ + " expecting: " + r + System.getProperty("line.separator")
+ + " got : " + sig[0]);
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ fail("s component wrong." + System.getProperty("line.separator")
+ + " expecting: " + s + System.getProperty("line.separator")
+ + " got : " + sig[1]);
+ }
+
+ // Verify the signature
+ ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+ params.getCurve().decodePoint(Hex.decode("03FD44EC11F9D43D9D23B1E1D1C9ED6519B40ECF0C79F48CF476CC43F1")), // Q
+ params);
+
+ dsa.init(false, pubKey);
+ if (!dsa.verifySignature(M, sig[0], sig[1]))
+ {
+ fail("signature fails");
+ }
+ }
+
+ // L4.3 X9.62 2005
+ private void testECDSAP521sha512()
+ {
+ X9ECParameters p = NISTNamedCurves.getByName("P-521");
+ ECDomainParameters params = new ECDomainParameters(p.getCurve(), p.getG(), p.getN(), p.getH());
+ ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+ new BigInteger("617573726813476282316253885608633222275541026607493641741273231656161177732180358888434629562647985511298272498852936680947729040673640492310550142822667389"), // d
+ params);
+ SecureRandom k = new FixedSecureRandom(BigIntegers.asUnsignedByteArray(new BigInteger("6806532878215503520845109818432174847616958675335397773700324097584974639728725689481598054743894544060040710846048585856076812050552869216017728862957612913")));
+
+ byte[] M = Hex.decode("6893B64BD3A9615C39C3E62DDD269C2BAAF1D85915526083183CE14C2E883B48B193607C1ED871852C9DF9C3147B574DC1526C55DE1FE263A676346A20028A66");
+
+ ECDSASigner dsa = new ECDSASigner();
+
+ dsa.init(true, new ParametersWithRandom(priKey, k));
+
+ BigInteger[] sig = dsa.generateSignature(M);
+
+ BigInteger r = new BigInteger("1368926195812127407956140744722257403535864168182534321188553460365652865686040549247096155740756318290773648848859639978618869784291633651685766829574104630");
+ BigInteger s = new BigInteger("1624754720348883715608122151214003032398685415003935734485445999065609979304811509538477657407457976246218976767156629169821116579317401249024208611945405790");
+
+ if (!r.equals(sig[0]))
+ {
+ fail("r component wrong." + System.getProperty("line.separator")
+ + " expecting: " + r + System.getProperty("line.separator")
+ + " got : " + sig[0]);
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ fail("s component wrong." + System.getProperty("line.separator")
+ + " expecting: " + s + System.getProperty("line.separator")
+ + " got : " + sig[1]);
+ }
+
+ // Verify the signature
+ ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+ params.getCurve().decodePoint(Hex.decode("020145E221AB9F71C5FE740D8D2B94939A09E2816E2167A7D058125A06A80C014F553E8D6764B048FB6F2B687CEC72F39738F223D4CE6AFCBFF2E34774AA5D3C342CB3")), // Q
+ params);
+
+ dsa.init(false, pubKey);
+ if (!dsa.verifySignature(M, sig[0], sig[1]))
+ {
+ fail("signature fails");
+ }
+ }
+
+ /**
+ * General test for long digest.
+ */
+ private void testECDSA239bitBinaryAndLargeDigest()
+ {
+ BigInteger r = new BigInteger("21596333210419611985018340039034612628818151486841789642455876922391552");
+ BigInteger s = new BigInteger("144940322424411242416373536877786566515839911620497068645600824084578597");
+
+ byte[] kData = BigIntegers.asUnsignedByteArray(new BigInteger("171278725565216523967285789236956265265265235675811949404040041670216363"));
+
+ SecureRandom k = new FixedSecureRandom(kData);
+
+ BigInteger n = new BigInteger("220855883097298041197912187592864814557886993776713230936715041207411783");
+ BigInteger h = BigInteger.valueOf(4);
+
+ ECCurve.F2m curve = new ECCurve.F2m(
+ 239, // m
+ 36, //k
+ new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), // a
+ new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16), // b
+ n, h);
+
+ ECDomainParameters params = new ECDomainParameters(
+ curve,
+ curve.decodePoint(Hex.decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G
+ n, h);
+
+ ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+ new BigInteger("145642755521911534651321230007534120304391871461646461466464667494947990"), // d
+ params);
+
+ ECDSASigner ecdsa = new ECDSASigner();
+ ParametersWithRandom param = new ParametersWithRandom(priKey, k);
+
+ ecdsa.init(true, param);
+
+ byte[] message = new BigInteger("968236873715988614170569073515315707566766479517968236873715988614170569073515315707566766479517968236873715988614170569073515315707566766479517").toByteArray();
+ BigInteger[] sig = ecdsa.generateSignature(message);
+
+ if (!r.equals(sig[0]))
+ {
+ fail("r component wrong." + System.getProperty("line.separator")
+ + " expecting: " + r + System.getProperty("line.separator")
+ + " got : " + sig[0]);
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ fail("s component wrong." + System.getProperty("line.separator")
+ + " expecting: " + s + System.getProperty("line.separator")
+ + " got : " + sig[1]);
+ }
+
+ // Verify the signature
+ ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+ curve.decodePoint(Hex.decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q
+ params);
+
+ ecdsa.init(false, pubKey);
+ if (!ecdsa.verifySignature(message, sig[0], sig[1]))
+ {
+ fail("signature fails");
+ }
+ }
+
+ /**
+ * key generation test
+ */
+ private void testECDSAKeyGenTest()
+ {
+ SecureRandom random = new SecureRandom();
+
+ BigInteger n = new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307");
+
+ ECCurve.Fp curve = new ECCurve.Fp(
+ new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
+ new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+ new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16), // b
+ n, ECConstants.ONE);
+
+ ECDomainParameters params = new ECDomainParameters(
+ curve,
+ curve.decodePoint(Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
+ n);
+
+ ECKeyPairGenerator pGen = new ECKeyPairGenerator();
+ ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(
+ params,
+ random);
+
+ pGen.init(genParam);
+
+ AsymmetricCipherKeyPair pair = pGen.generateKeyPair();
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
+
+ ECDSASigner ecdsa = new ECDSASigner();
+
+ ecdsa.init(true, param);
+
+ byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").toByteArray();
+ BigInteger[] sig = ecdsa.generateSignature(message);
+
+ ecdsa.init(false, pair.getPublic());
+
+ if (!ecdsa.verifySignature(message, sig[0], sig[1]))
+ {
+ fail("signature fails");
+ }
+ }
+
+ /**
+ * Basic Key Agreement Test
+ */
+ private void testECBasicAgreementTest()
+ {
+ SecureRandom random = new SecureRandom();
+
+ BigInteger n = new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307");
+
+ ECCurve.Fp curve = new ECCurve.Fp(
+ new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
+ new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+ new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16), // b
+ n, ECConstants.ONE);
+
+ ECDomainParameters params = new ECDomainParameters(
+ curve,
+ curve.decodePoint(Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
+ n);
+
+ ECKeyPairGenerator pGen = new ECKeyPairGenerator();
+ ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(
+ params,
+ random);
+
+ pGen.init(genParam);
+
+ AsymmetricCipherKeyPair p1 = pGen.generateKeyPair();
+ AsymmetricCipherKeyPair p2 = pGen.generateKeyPair();
+
+ //
+ // two way
+ //
+ BasicAgreement e1 = new ECDHBasicAgreement();
+ BasicAgreement e2 = new ECDHBasicAgreement();
+
+ e1.init(p1.getPrivate());
+ e2.init(p2.getPrivate());
+
+ BigInteger k1 = e1.calculateAgreement(p2.getPublic());
+ BigInteger k2 = e2.calculateAgreement(p1.getPublic());
+
+ if (!k1.equals(k2))
+ {
+ fail("calculated agreement test failed");
+ }
+
+ //
+ // two way
+ //
+ e1 = new ECDHCBasicAgreement();
+ e2 = new ECDHCBasicAgreement();
+
+ e1.init(p1.getPrivate());
+ e2.init(p2.getPrivate());
+
+ k1 = e1.calculateAgreement(p2.getPublic());
+ k2 = e2.calculateAgreement(p1.getPublic());
+
+ if (!k1.equals(k2))
+ {
+ fail("calculated agreement test failed");
+ }
+ }
+
+ private void testECMQVTestVector1()
+ {
+ // Test Vector from GEC-2
+
+ X9ECParameters x9 = SECNamedCurves.getByName("secp160r1");
+ ECDomainParameters p = new ECDomainParameters(
+ x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
+
+ AsymmetricCipherKeyPair U1 = new AsymmetricCipherKeyPair(
+ new ECPublicKeyParameters(
+ p.getCurve().decodePoint(Hex.decode("0251B4496FECC406ED0E75A24A3C03206251419DC0")), p),
+ new ECPrivateKeyParameters(
+ new BigInteger("AA374FFC3CE144E6B073307972CB6D57B2A4E982", 16), p));
+
+ AsymmetricCipherKeyPair U2 = new AsymmetricCipherKeyPair(
+ new ECPublicKeyParameters(
+ p.getCurve().decodePoint(Hex.decode("03D99CE4D8BF52FA20BD21A962C6556B0F71F4CA1F")), p),
+ new ECPrivateKeyParameters(
+ new BigInteger("149EC7EA3A220A887619B3F9E5B4CA51C7D1779C", 16), p));
+
+ AsymmetricCipherKeyPair V1 = new AsymmetricCipherKeyPair(
+ new ECPublicKeyParameters(
+ p.getCurve().decodePoint(Hex.decode("0349B41E0E9C0369C2328739D90F63D56707C6E5BC")), p),
+ new ECPrivateKeyParameters(
+ new BigInteger("45FB58A92A17AD4B15101C66E74F277E2B460866", 16), p));
+
+ AsymmetricCipherKeyPair V2 = new AsymmetricCipherKeyPair(
+ new ECPublicKeyParameters(
+ p.getCurve().decodePoint(Hex.decode("02706E5D6E1F640C6E9C804E75DBC14521B1E5F3B5")), p),
+ new ECPrivateKeyParameters(
+ new BigInteger("18C13FCED9EADF884F7C595C8CB565DEFD0CB41E", 16), p));
+
+ BigInteger x = calculateAgreement(U1, U2, V1, V2);
+
+ if (x == null
+ || !x.equals(new BigInteger("5A6955CEFDB4E43255FB7FCF718611E4DF8E05AC", 16)))
+ {
+ fail("MQV Test Vector #1 agreement failed");
+ }
+ }
+
+ private void testECMQVTestVector2()
+ {
+ // Test Vector from GEC-2
+
+ X9ECParameters x9 = SECNamedCurves.getByName("sect163k1");
+ ECDomainParameters p = new ECDomainParameters(
+ x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
+
+ AsymmetricCipherKeyPair U1 = new AsymmetricCipherKeyPair(
+ new ECPublicKeyParameters(
+ p.getCurve().decodePoint(Hex.decode("03037D529FA37E42195F10111127FFB2BB38644806BC")), p),
+ new ECPrivateKeyParameters(
+ new BigInteger("03A41434AA99C2EF40C8495B2ED9739CB2155A1E0D", 16), p));
+
+ AsymmetricCipherKeyPair U2 = new AsymmetricCipherKeyPair(
+ new ECPublicKeyParameters(
+ p.getCurve().decodePoint(Hex.decode("02015198E74BC2F1E5C9A62B80248DF0D62B9ADF8429")), p),
+ new ECPrivateKeyParameters(
+ new BigInteger("032FC4C61A8211E6A7C4B8B0C03CF35F7CF20DBD52", 16), p));
+
+ AsymmetricCipherKeyPair V1 = new AsymmetricCipherKeyPair(
+ new ECPublicKeyParameters(
+ p.getCurve().decodePoint(Hex.decode("03072783FAAB9549002B4F13140B88132D1C75B3886C")), p),
+ new ECPrivateKeyParameters(
+ new BigInteger("57E8A78E842BF4ACD5C315AA0569DB1703541D96", 16), p));
+
+ AsymmetricCipherKeyPair V2 = new AsymmetricCipherKeyPair(
+ new ECPublicKeyParameters(
+ p.getCurve().decodePoint(Hex.decode("03067E3AEA3510D69E8EDD19CB2A703DDC6CF5E56E32")), p),
+ new ECPrivateKeyParameters(
+ new BigInteger("02BD198B83A667A8D908EA1E6F90FD5C6D695DE94F", 16), p));
+
+ BigInteger x = calculateAgreement(U1, U2, V1, V2);
+
+ if (x == null
+ || !x.equals(new BigInteger("038359FFD30C0D5FC1E6154F483B73D43E5CF2B503", 16)))
+ {
+ fail("MQV Test Vector #2 agreement failed");
+ }
+ }
+
+ private void testECMQVRandom()
+ {
+ SecureRandom random = new SecureRandom();
+
+ BigInteger n = new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307");
+
+ ECCurve.Fp curve = new ECCurve.Fp(
+ new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
+ new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+ new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16), // b
+ n, ECConstants.ONE);
+
+ ECDomainParameters parameters = new ECDomainParameters(
+ curve,
+ curve.decodePoint(Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
+ n);
+
+ ECKeyPairGenerator pGen = new ECKeyPairGenerator();
+
+ pGen.init(new ECKeyGenerationParameters(parameters, random));
+
+
+ // Pre-established key pairs
+ AsymmetricCipherKeyPair U1 = pGen.generateKeyPair();
+ AsymmetricCipherKeyPair V1 = pGen.generateKeyPair();
+
+ // Ephemeral key pairs
+ AsymmetricCipherKeyPair U2 = pGen.generateKeyPair();
+ AsymmetricCipherKeyPair V2 = pGen.generateKeyPair();
+
+ BigInteger x = calculateAgreement(U1, U2, V1, V2);
+
+ if (x == null)
+ {
+ fail("MQV Test Vector (random) agreement failed");
+ }
+ }
+
+ private static BigInteger calculateAgreement(
+ AsymmetricCipherKeyPair U1,
+ AsymmetricCipherKeyPair U2,
+ AsymmetricCipherKeyPair V1,
+ AsymmetricCipherKeyPair V2)
+ {
+ ECMQVBasicAgreement u = new ECMQVBasicAgreement();
+ u.init(new MQVPrivateParameters(
+ (ECPrivateKeyParameters)U1.getPrivate(),
+ (ECPrivateKeyParameters)U2.getPrivate(),
+ (ECPublicKeyParameters)U2.getPublic()));
+ BigInteger ux = u.calculateAgreement(new MQVPublicParameters(
+ (ECPublicKeyParameters)V1.getPublic(),
+ (ECPublicKeyParameters)V2.getPublic()));
+
+ ECMQVBasicAgreement v = new ECMQVBasicAgreement();
+ v.init(new MQVPrivateParameters(
+ (ECPrivateKeyParameters)V1.getPrivate(),
+ (ECPrivateKeyParameters)V2.getPrivate(),
+ (ECPublicKeyParameters)V2.getPublic()));
+ BigInteger vx = v.calculateAgreement(new MQVPublicParameters(
+ (ECPublicKeyParameters)U1.getPublic(),
+ (ECPublicKeyParameters)U2.getPublic()));
+
+ if (ux.equals(vx))
+ {
+ return ux;
+ }
+
+ return null;
+ }
+
+ public String getName()
+ {
+ return "EC";
+ }
+
+ public void performTest()
+ {
+ decodeTest();
+ testECDSA192bitPrime();
+ testECDSA239bitPrime();
+ testECDSA191bitBinary();
+ testECDSA239bitBinary();
+ testECDSAKeyGenTest();
+ testECBasicAgreementTest();
+
+ testECDSAP224sha224();
+ testECDSAP224OneByteOver();
+ testECDSAP256sha256();
+ testECDSAP521sha512();
+ testECDSASecP224k1sha256();
+ testECDSA239bitBinaryAndLargeDigest();
+
+ testECMQVTestVector1();
+ testECMQVTestVector2();
+ testECMQVRandom();
+ }
+
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new ECTest());
+ }
+}
+
diff --git a/core/src/test/java/org/spongycastle/crypto/test/ElGamalTest.java b/core/src/test/java/org/spongycastle/crypto/test/ElGamalTest.java
new file mode 100644
index 00000000..08c029af
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/ElGamalTest.java
@@ -0,0 +1,285 @@
+package org.spongycastle.crypto.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.engines.ElGamalEngine;
+import org.spongycastle.crypto.generators.ElGamalKeyPairGenerator;
+import org.spongycastle.crypto.generators.ElGamalParametersGenerator;
+import org.spongycastle.crypto.params.ElGamalKeyGenerationParameters;
+import org.spongycastle.crypto.params.ElGamalParameters;
+import org.spongycastle.crypto.params.ElGamalPrivateKeyParameters;
+import org.spongycastle.crypto.params.ElGamalPublicKeyParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.BigIntegers;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class ElGamalTest
+ extends SimpleTest
+{
+ private BigInteger g512 = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16);
+ private BigInteger p512 = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16);
+
+ private BigInteger g768 = new BigInteger("7c240073c1316c621df461b71ebb0cdcc90a6e5527e5e126633d131f87461c4dc4afc60c2cb0f053b6758871489a69613e2a8b4c8acde23954c08c81cbd36132cfd64d69e4ed9f8e51ed6e516297206672d5c0a69135df0a5dcf010d289a9ca1", 16);
+ private BigInteger p768 = new BigInteger("8c9dd223debed1b80103b8b309715be009d48860ed5ae9b9d5d8159508efd802e3ad4501a7f7e1cfec78844489148cd72da24b21eddd01aa624291c48393e277cfc529e37075eccef957f3616f962d15b44aeab4039d01b817fde9eaa12fd73f", 16);
+
+ private BigInteger g1024 = new BigInteger("1db17639cdf96bc4eabba19454f0b7e5bd4e14862889a725c96eb61048dcd676ceb303d586e30f060dbafd8a571a39c4d823982117da5cc4e0f89c77388b7a08896362429b94a18a327604eb7ff227bffbc83459ade299e57b5f77b50fb045250934938efa145511166e3197373e1b5b1e52de713eb49792bedde722c6717abf", 16);
+ private BigInteger p1024 = new BigInteger("a00e283b3c624e5b2b4d9fbc2653b5185d99499b00fd1bf244c6f0bb817b4d1c451b2958d62a0f8a38caef059fb5ecd25d75ed9af403f5b5bdab97a642902f824e3c13789fed95fa106ddfe0ff4a707c85e2eb77d49e68f2808bcea18ce128b178cd287c6bc00efa9a1ad2a673fe0dceace53166f75b81d6709d5f8af7c66bb7", 16);
+
+ private BigInteger yPgpBogusPSamp = new BigInteger("de4688497cc05b45fe8559bc9918c45afcad69b74123a7236eba409fd9de8ea34c7869839ee9df35e3d97576145d089841aa65b5b4e061fae52c37e430354269a02496b8ed8456f2d0d7c9b0db985fbcb21ae9f78507ed6e3a29db595b201b1a4f931c7d791eede65ccf918e8a61cf146859151c78c41ad48853694623467d78", 16);
+ private BigInteger xPgpBogusPSamp = new BigInteger("cbaf780f2cfe4f987bbc5fcb0738bbd7912060ccfdf37cbfeea65c0fd857e74a8df6cc359375f28cf5725d081813c614410a78cbe4b06d677beea9ff0fa10b1dbc47a6ed8c5b8466d6a95d6574029dbdf72596392e1b6b230faf9916dc8455821c10527a375a4d1c8a54947d1fe714d321aca25ad486b4b456506999fd2fd11a", 16);
+ private BigInteger gPgpBogusPSamp = new BigInteger("153ffe9522076d1cbd6e75f0816a0fc2ebd8b0e0091406587387a1763022088a03b411eed07ff50efb82b21f1608c352d10f63ba7e7e981a2f3387cec8af2915953d00493857663ae8919f517fe90f1d2abe7af4305a344b10d1a25d75f65902cd7fd775853d3ac43d7c5253ad666e1e63ee98cdcb10af81273d4ff053ff07d51", 16);
+ private BigInteger pPgpBogusPSamp = new BigInteger("15061b26cdab4e865098a01c86f13b03220104c5443e950658b36b85245aa0c616a0c0d8d99c454bea087c172315e45b3bc9b925443948a2b6ba47608a6035b9a79a4ef34a78d7274a12ede8364f02d5030db864988643d7e92753df603bd69fbd2682ab0af64d1a866d1131a2cb13333cedb0a9e6eefddd9fff8154d34c2daab", 16);
+ private int lPgpBogusPSamp = 0;
+
+ public String getName()
+ {
+ return "ElGamal";
+ }
+
+ private void testEnc(
+ int size,
+ int privateValueSize,
+ BigInteger g,
+ BigInteger p)
+ {
+ ElGamalParameters dhParams = new ElGamalParameters(p, g, privateValueSize);
+ ElGamalKeyGenerationParameters params = new ElGamalKeyGenerationParameters(new SecureRandom(), dhParams);
+ ElGamalKeyPairGenerator kpGen = new ElGamalKeyPairGenerator();
+
+ kpGen.init(params);
+
+ //
+ // generate pair
+ //
+ AsymmetricCipherKeyPair pair = kpGen.generateKeyPair();
+
+ ElGamalPublicKeyParameters pu = (ElGamalPublicKeyParameters)pair.getPublic();
+ ElGamalPrivateKeyParameters pv = (ElGamalPrivateKeyParameters)pair.getPrivate();
+
+ checkKeySize(privateValueSize, pv);
+
+ ElGamalEngine e = new ElGamalEngine();
+
+ e.init(true, pu);
+
+ if (e.getOutputBlockSize() != size / 4)
+ {
+ fail(size + " getOutputBlockSize() on encryption failed.");
+ }
+
+ byte[] message = Hex.decode("5468697320697320612074657374");
+
+ byte[] pText = message;
+ byte[] cText = e.processBlock(pText, 0, pText.length);
+
+ e.init(false, pv);
+
+ if (e.getOutputBlockSize() != (size / 8) - 1)
+ {
+ fail(size + " getOutputBlockSize() on decryption failed.");
+ }
+
+ pText = e.processBlock(cText, 0, cText.length);
+
+ if (!Arrays.areEqual(message, pText))
+ {
+ fail(size + " bit test failed");
+ }
+
+ e.init(true, pu);
+
+ byte[] bytes = new byte[e.getInputBlockSize() + 2];
+
+ try
+ {
+ e.processBlock(bytes, 0, bytes.length);
+
+ fail("out of range block not detected");
+ }
+ catch (DataLengthException ex)
+ {
+ // expected
+ }
+
+ try
+ {
+ bytes[0] = (byte)0xff;
+
+ e.processBlock(bytes, 0, bytes.length - 1);
+
+ fail("out of range block not detected");
+ }
+ catch (DataLengthException ex)
+ {
+ // expected
+ }
+
+ try
+ {
+ bytes[0] = (byte)0x7f;
+
+ e.processBlock(bytes, 0, bytes.length - 1);
+ }
+ catch (DataLengthException ex)
+ {
+ fail("in range block failed");
+ }
+
+ try
+ {
+ bytes = BigIntegers.asUnsignedByteArray(p);
+
+ e.processBlock(bytes, 0, bytes.length);
+
+ fail("out of range block not detected");
+ }
+ catch (DataLengthException ex)
+ {
+ // expected
+ }
+
+ try
+ {
+ bytes = BigIntegers.asUnsignedByteArray(p.subtract(BigInteger.valueOf(1)));
+
+ e.processBlock(bytes, 0, bytes.length);
+ }
+ catch (DataLengthException ex)
+ {
+ fail("boundary block rejected");
+ }
+ }
+
+ private void checkKeySize(
+ int privateValueSize,
+ ElGamalPrivateKeyParameters priv)
+ {
+ if (privateValueSize != 0)
+ {
+ if (priv.getX().bitLength() != privateValueSize)
+ {
+ fail("limited key check failed for key size " + privateValueSize);
+ }
+ }
+ }
+
+ /**
+ * this test is can take quiet a while
+ *
+ * @param size size of key in bits.
+ */
+ private void testGeneration(
+ int size)
+ {
+ ElGamalParametersGenerator pGen = new ElGamalParametersGenerator();
+
+ pGen.init(size, 10, new SecureRandom());
+
+ ElGamalParameters elParams = pGen.generateParameters();
+
+ if (elParams.getL() != 0)
+ {
+ fail("ElGamalParametersGenerator failed to set L to 0 in generated ElGamalParameters");
+ }
+
+ ElGamalKeyGenerationParameters params = new ElGamalKeyGenerationParameters(new SecureRandom(), elParams);
+
+ ElGamalKeyPairGenerator kpGen = new ElGamalKeyPairGenerator();
+
+ kpGen.init(params);
+
+ //
+ // generate first pair
+ //
+ AsymmetricCipherKeyPair pair = kpGen.generateKeyPair();
+
+ ElGamalPublicKeyParameters pu = (ElGamalPublicKeyParameters)pair.getPublic();
+ ElGamalPrivateKeyParameters pv = (ElGamalPrivateKeyParameters)pair.getPrivate();
+
+ ElGamalEngine e = new ElGamalEngine();
+
+ e.init(true, new ParametersWithRandom(pu, new SecureRandom()));
+
+ byte[] message = Hex.decode("5468697320697320612074657374");
+
+ byte[] pText = message;
+ byte[] cText = e.processBlock(pText, 0, pText.length);
+
+ e.init(false, pv);
+
+ pText = e.processBlock(cText, 0, cText.length);
+
+ if (!Arrays.areEqual(message, pText))
+ {
+ fail("generation test failed");
+ }
+ }
+
+ private void testInitCheck()
+ {
+ try
+ {
+ new ElGamalEngine().processBlock(new byte[]{ 1 }, 0, 1);
+ fail("failed initialisation check");
+ }
+ catch (IllegalStateException e)
+ {
+ // expected
+ }
+ }
+
+ private void testInvalidP()
+ {
+ ElGamalParameters dhParams = new ElGamalParameters(pPgpBogusPSamp, gPgpBogusPSamp, lPgpBogusPSamp);
+ ElGamalPublicKeyParameters pu = new ElGamalPublicKeyParameters(yPgpBogusPSamp, dhParams);
+ ElGamalPrivateKeyParameters pv = new ElGamalPrivateKeyParameters(xPgpBogusPSamp, dhParams);
+
+ ElGamalEngine e = new ElGamalEngine();
+
+ e.init(true, pu);
+
+ byte[] message = Hex.decode("5468697320697320612074657374");
+
+ byte[] pText = message;
+ byte[] cText = e.processBlock(pText, 0, pText.length);
+
+ e.init(false, pv);
+
+ pText = e.processBlock(cText, 0, cText.length);
+
+ if (Arrays.areEqual(message, pText))
+ {
+ fail("invalid test failed");
+ }
+ }
+
+ public void performTest()
+ {
+ testInvalidP();
+
+ testEnc(512, 0, g512, p512);
+ testEnc(768, 0, g768, p768);
+ testEnc(1024, 0, g1024, p1024);
+
+ testEnc(512, 64, g512, p512);
+ testEnc(768, 128, g768, p768);
+
+ //
+ // generation test.
+ //
+ testGeneration(258);
+
+ testInitCheck();
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new ElGamalTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/EqualsHashCodeTest.java b/core/src/test/java/org/spongycastle/crypto/test/EqualsHashCodeTest.java
new file mode 100644
index 00000000..3966f8e8
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/EqualsHashCodeTest.java
@@ -0,0 +1,261 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.generators.DHKeyPairGenerator;
+import org.spongycastle.crypto.generators.ElGamalKeyPairGenerator;
+import org.spongycastle.crypto.params.DHKeyGenerationParameters;
+import org.spongycastle.crypto.params.DHKeyParameters;
+import org.spongycastle.crypto.params.DHParameters;
+import org.spongycastle.crypto.params.DHPrivateKeyParameters;
+import org.spongycastle.crypto.params.DHPublicKeyParameters;
+import org.spongycastle.crypto.params.DHValidationParameters;
+import org.spongycastle.crypto.params.DSAParameters;
+import org.spongycastle.crypto.params.DSAValidationParameters;
+import org.spongycastle.crypto.params.ElGamalKeyGenerationParameters;
+import org.spongycastle.crypto.params.ElGamalKeyParameters;
+import org.spongycastle.crypto.params.ElGamalParameters;
+import org.spongycastle.crypto.params.ElGamalPrivateKeyParameters;
+import org.spongycastle.crypto.params.ElGamalPublicKeyParameters;
+import org.spongycastle.crypto.params.GOST3410Parameters;
+import org.spongycastle.crypto.params.GOST3410ValidationParameters;
+import org.spongycastle.util.test.SimpleTest;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+class DHTestKeyParameters
+ extends DHKeyParameters
+{
+ protected DHTestKeyParameters(boolean isPrivate, DHParameters params)
+ {
+ super(isPrivate, params);
+ }
+}
+
+class ElGamalTestKeyParameters
+ extends ElGamalKeyParameters
+{
+ protected ElGamalTestKeyParameters(boolean isPrivate, ElGamalParameters params)
+ {
+ super(isPrivate, params);
+ }
+}
+
+public class EqualsHashCodeTest
+ extends SimpleTest
+{
+ private static Object OTHER = new Object();
+
+ public String getName()
+ {
+ return "EqualsHashCode";
+ }
+
+ private void doTest(Object a, Object equalsA, Object notEqualsA)
+ {
+ if (a.equals(null))
+ {
+ fail("a equaled null");
+ }
+
+ if (!a.equals(equalsA) || !equalsA.equals(a))
+ {
+ fail("equality failed");
+ }
+
+ if (a.equals(OTHER))
+ {
+ fail("other inequality failed");
+ }
+
+ if (a.equals(notEqualsA) || notEqualsA.equals(a))
+ {
+ fail("inequality failed");
+ }
+
+ if (a.hashCode() != equalsA.hashCode())
+ {
+ fail("hashCode equality failed");
+ }
+ }
+
+ private void dhTest()
+ {
+ BigInteger g512 = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16);
+ BigInteger p512 = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16);
+
+ DHParameters dhParams = new DHParameters(p512, g512);
+ DHKeyGenerationParameters params = new DHKeyGenerationParameters(new SecureRandom(), dhParams); DHKeyPairGenerator kpGen = new DHKeyPairGenerator();
+
+ kpGen.init(params);
+
+ AsymmetricCipherKeyPair pair = kpGen.generateKeyPair();
+ DHPublicKeyParameters pu1 = (DHPublicKeyParameters)pair.getPublic();
+ DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.getPrivate();
+
+ DHPublicKeyParameters pu2 = new DHPublicKeyParameters(pu1.getY(), pu1.getParameters());
+ DHPrivateKeyParameters pv2 = new DHPrivateKeyParameters(pv1.getX(), pv1.getParameters());
+ DHPublicKeyParameters pu3 = new DHPublicKeyParameters(pv1.getX(), pu1.getParameters());
+ DHPrivateKeyParameters pv3 = new DHPrivateKeyParameters(pu1.getY(), pu1.getParameters());
+
+ doTest(pu1, pu2, pu3);
+ doTest(pv1, pv2, pv3);
+
+ DHParameters pr1 = pu1.getParameters();
+ DHParameters pr2 = new DHParameters(pr1.getP(), pr1.getG(), pr1.getQ(), pr1.getM(), pr1.getL(), pr1.getJ(), pr1.getValidationParameters());
+ DHParameters pr3 = new DHParameters(pr1.getG(), pr1.getP(), pr1.getQ(), pr1.getM(), pr1.getL(), pr1.getJ(), pr1.getValidationParameters());
+
+ doTest(pr1, pr2, pr3);
+
+ pr3 = new DHParameters(pr1.getG(), pr1.getP(), null, pr1.getM(), pr1.getL(), pr1.getJ(), pr1.getValidationParameters());
+
+ doTest(pr1, pr2, pr3);
+
+ pu2 = new DHPublicKeyParameters(pu1.getY(), pr2);
+ pv2 = new DHPrivateKeyParameters(pv1.getX(), pr2);
+
+ doTest(pu1, pu2, pu3);
+ doTest(pv1, pv2, pv3);
+
+ DHValidationParameters vp1 = new DHValidationParameters(new byte[20], 1024);
+ DHValidationParameters vp2 = new DHValidationParameters(new byte[20], 1024);
+ DHValidationParameters vp3 = new DHValidationParameters(new byte[24], 1024);
+
+ doTest(vp1, vp1, vp3);
+ doTest(vp1, vp2, vp3);
+
+ byte[] bytes = new byte[20];
+ bytes[0] = 1;
+
+ vp3 = new DHValidationParameters(bytes, 1024);
+
+ doTest(vp1, vp2, vp3);
+
+ vp3 = new DHValidationParameters(new byte[20], 2048);
+
+ doTest(vp1, vp2, vp3);
+
+ DHTestKeyParameters k1 = new DHTestKeyParameters(false, null);
+ DHTestKeyParameters k2 = new DHTestKeyParameters(false, null);
+ DHTestKeyParameters k3 = new DHTestKeyParameters(false, pu1.getParameters());
+
+ doTest(k1, k2, k3);
+ }
+
+ private void elGamalTest()
+ {
+ BigInteger g512 = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16);
+ BigInteger p512 = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16);
+
+ ElGamalParameters dhParams = new ElGamalParameters(p512, g512);
+ ElGamalKeyGenerationParameters params = new ElGamalKeyGenerationParameters(new SecureRandom(), dhParams); ElGamalKeyPairGenerator kpGen = new ElGamalKeyPairGenerator();
+
+ kpGen.init(params);
+
+ AsymmetricCipherKeyPair pair = kpGen.generateKeyPair();
+ ElGamalPublicKeyParameters pu1 = (ElGamalPublicKeyParameters)pair.getPublic();
+ ElGamalPrivateKeyParameters pv1 = (ElGamalPrivateKeyParameters)pair.getPrivate();
+
+ ElGamalPublicKeyParameters pu2 = new ElGamalPublicKeyParameters(pu1.getY(), pu1.getParameters());
+ ElGamalPrivateKeyParameters pv2 = new ElGamalPrivateKeyParameters(pv1.getX(), pv1.getParameters());
+ ElGamalPublicKeyParameters pu3 = new ElGamalPublicKeyParameters(pv1.getX(), pu1.getParameters());
+ ElGamalPrivateKeyParameters pv3 = new ElGamalPrivateKeyParameters(pu1.getY(), pu1.getParameters());
+
+ doTest(pu1, pu2, pu3);
+ doTest(pv1, pv2, pv3);
+
+ ElGamalParameters pr1 = pu1.getParameters();
+ ElGamalParameters pr2 = new ElGamalParameters(pr1.getP(), pr1.getG());
+ ElGamalParameters pr3 = new ElGamalParameters(pr1.getG(), pr1.getP());
+
+ doTest(pr1, pr2, pr3);
+
+ pu2 = new ElGamalPublicKeyParameters(pu1.getY(), pr2);
+ pv2 = new ElGamalPrivateKeyParameters(pv1.getX(), pr2);
+
+ doTest(pu1, pu2, pu3);
+ doTest(pv1, pv2, pv3);
+
+ ElGamalTestKeyParameters k1 = new ElGamalTestKeyParameters(false, null);
+ ElGamalTestKeyParameters k2 = new ElGamalTestKeyParameters(false, null);
+ ElGamalTestKeyParameters k3 = new ElGamalTestKeyParameters(false, pu1.getParameters());
+
+ doTest(k1, k2, k3);
+ }
+
+ private void dsaTest()
+ {
+ BigInteger a = BigInteger.valueOf(1), b = BigInteger.valueOf(2), c = BigInteger.valueOf(3);
+
+ DSAParameters dsaP1 = new DSAParameters(a, b, c);
+ DSAParameters dsaP2 = new DSAParameters(a, b, c);
+ DSAParameters dsaP3 = new DSAParameters(b, c, a);
+
+ doTest(dsaP1, dsaP2, dsaP3);
+
+ DSAValidationParameters vp1 = new DSAValidationParameters(new byte[20], 1024);
+ DSAValidationParameters vp2 = new DSAValidationParameters(new byte[20], 1024);
+ DSAValidationParameters vp3 = new DSAValidationParameters(new byte[24], 1024);
+
+ doTest(vp1, vp1, vp3);
+ doTest(vp1, vp2, vp3);
+
+ byte[] bytes = new byte[20];
+ bytes[0] = 1;
+
+ vp3 = new DSAValidationParameters(bytes, 1024);
+
+ doTest(vp1, vp2, vp3);
+
+ vp3 = new DSAValidationParameters(new byte[20], 2048);
+
+ doTest(vp1, vp2, vp3);
+ }
+
+ private void gost3410Test()
+ {
+ BigInteger a = BigInteger.valueOf(1), b = BigInteger.valueOf(2), c = BigInteger.valueOf(3);
+
+ GOST3410Parameters g1 = new GOST3410Parameters(a, b, c);
+ GOST3410Parameters g2 = new GOST3410Parameters(a, b, c);
+ GOST3410Parameters g3 = new GOST3410Parameters(a, c, c);
+
+ doTest(g1, g2, g3);
+
+ GOST3410ValidationParameters v1 = new GOST3410ValidationParameters(100, 1);
+ GOST3410ValidationParameters v2 = new GOST3410ValidationParameters(100, 1);
+ GOST3410ValidationParameters v3 = new GOST3410ValidationParameters(101, 1);
+
+ doTest(v1, v2, v3);
+
+ v3 = new GOST3410ValidationParameters(100, 2);
+
+ doTest(v1, v2, v3);
+
+ v1 = new GOST3410ValidationParameters(100L, 1L);
+ v2 = new GOST3410ValidationParameters(100L, 1L);
+ v3 = new GOST3410ValidationParameters(101L, 1L);
+
+ doTest(v1, v2, v3);
+
+ v3 = new GOST3410ValidationParameters(100L, 2L);
+
+ doTest(v1, v2, v3);
+
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ dhTest();
+ elGamalTest();
+ gost3410Test();
+ dsaTest();
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new EqualsHashCodeTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/GCMReorderTest.java b/core/src/test/java/org/spongycastle/crypto/test/GCMReorderTest.java
new file mode 100644
index 00000000..adddcf61
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/GCMReorderTest.java
@@ -0,0 +1,347 @@
+package org.spongycastle.crypto.test;
+
+import java.io.IOException;
+import java.security.SecureRandom;
+
+import junit.framework.TestCase;
+import org.spongycastle.crypto.modes.gcm.GCMExponentiator;
+import org.spongycastle.crypto.modes.gcm.GCMMultiplier;
+import org.spongycastle.crypto.modes.gcm.Tables1kGCMExponentiator;
+import org.spongycastle.crypto.modes.gcm.Tables64kGCMMultiplier;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Pack;
+import org.spongycastle.util.encoders.Hex;
+
+public class GCMReorderTest
+ extends TestCase
+{
+ private static final byte[] H;
+ private static final SecureRandom random = new SecureRandom();
+ private static final GCMMultiplier mul = new Tables64kGCMMultiplier();
+ private static final GCMExponentiator exp = new Tables1kGCMExponentiator();
+ private static final byte[] EMPTY = new byte[0];
+
+ static
+ {
+ H = new byte[16];
+ random.nextBytes(H);
+ mul.init(Arrays.clone(H));
+ exp.init(Arrays.clone(H));
+ }
+
+ public void testCombine() throws Exception
+ {
+ for (int count = 0; count < 10; ++count)
+ {
+ byte[] A = randomBytes(1000);
+ byte[] C = randomBytes(1000);
+
+ byte[] ghashA_ = GHASH(A, EMPTY);
+ byte[] ghash_C = GHASH(EMPTY, C);
+ byte[] ghashAC = GHASH(A, C);
+
+ byte[] ghashCombine = combine_GHASH(ghashA_, (long)A.length * 8, ghash_C, (long)C.length * 8);
+
+ assertTrue(Arrays.areEqual(ghashAC, ghashCombine));
+ }
+ }
+
+ public void testConcatAuth() throws Exception
+ {
+ for (int count = 0; count < 10; ++count)
+ {
+ byte[] P = randomBlocks(100);
+ byte[] A = randomBytes(1000);
+ byte[] PA = concatArrays(P, A);
+
+ byte[] ghashP_ = GHASH(P, EMPTY);
+ byte[] ghashA_ = GHASH(A, EMPTY);
+ byte[] ghashPA_ = GHASH(PA, EMPTY);
+ byte[] ghashConcat = concatAuth_GHASH(ghashP_, (long)P.length * 8, ghashA_, (long)A.length * 8);
+
+ assertTrue(Arrays.areEqual(ghashPA_, ghashConcat));
+ }
+ }
+
+ public void testConcatCrypt() throws Exception
+ {
+ for (int count = 0; count < 10; ++count)
+ {
+ byte[] P = randomBlocks(100);
+ byte[] A = randomBytes(1000);
+ byte[] PA = concatArrays(P, A);
+
+ byte[] ghash_P = GHASH(EMPTY, P);
+ byte[] ghash_A = GHASH(EMPTY, A);
+ byte[] ghash_PA = GHASH(EMPTY, PA);
+ byte[] ghashConcat = concatCrypt_GHASH(ghash_P, (long)P.length * 8, ghash_A, (long)A.length * 8);
+
+ assertTrue(Arrays.areEqual(ghash_PA, ghashConcat));
+ }
+ }
+
+ public void testExp()
+ {
+ {
+ byte[] buf1 = new byte[16];
+ buf1[0] = (byte)0x80;
+
+ byte[] buf2 = new byte[16];
+
+ for (int pow = 0; pow != 100; ++pow)
+ {
+ exp.exponentiateX(pow, buf2);
+
+ assertTrue(Arrays.areEqual(buf1, buf2));
+
+ mul.multiplyH(buf1);
+ }
+ }
+
+ long[] testPow = new long[]{ 10, 1, 8, 17, 24, 13, 2, 13, 2, 3 };
+ byte[][] testData = new byte[][]{
+ Hex.decode("9185848a877bd87ba071e281f476e8e7"),
+ Hex.decode("697ce3052137d80745d524474fb6b290"),
+ Hex.decode("2696fc47198bb23b11296e4f88720a17"),
+ Hex.decode("01f2f0ead011a4ae0cf3572f1b76dd8e"),
+ Hex.decode("a53060694a044e4b7fa1e661c5a7bb6b"),
+ Hex.decode("39c0392e8b6b0e04a7565c85394c2c4c"),
+ Hex.decode("519c362d502e07f2d8b7597a359a5214"),
+ Hex.decode("5a527a393675705e19b2117f67695af4"),
+ Hex.decode("27fc0901d1d332a53ba4d4386c2109d2"),
+ Hex.decode("93ca9b57174aabedf8220e83366d7df6"),
+ };
+
+ for (int i = 0; i != 10; ++i)
+ {
+ long pow = testPow[i];
+ byte[] data = Arrays.clone(testData[i]);
+
+ byte[] expected = Arrays.clone(data);
+ for (int j = 0; j < pow; ++j)
+ {
+ mul.multiplyH(expected);
+ }
+
+ byte[] H_a = new byte[16];
+ exp.exponentiateX(pow, H_a);
+ byte[] actual = multiply(data, H_a);
+
+ assertTrue(Arrays.areEqual(expected, actual));
+ }
+ }
+
+ public void testMultiply()
+ {
+ byte[] expected = Arrays.clone(H);
+ mul.multiplyH(expected);
+
+ assertTrue(Arrays.areEqual(expected, multiply(H, H)));
+
+ for (int count = 0; count < 10; ++count)
+ {
+ byte[] a = new byte[16];
+ random.nextBytes(a);
+
+ byte[] b = new byte[16];
+ random.nextBytes(b);
+
+ expected = Arrays.clone(a);
+ mul.multiplyH(expected);
+ assertTrue(Arrays.areEqual(expected, multiply(a, H)));
+ assertTrue(Arrays.areEqual(expected, multiply(H, a)));
+
+ expected = Arrays.clone(b);
+ mul.multiplyH(expected);
+ assertTrue(Arrays.areEqual(expected, multiply(b, H)));
+ assertTrue(Arrays.areEqual(expected, multiply(H, b)));
+
+ assertTrue(Arrays.areEqual(multiply(a, b), multiply(b, a)));
+ }
+ }
+
+ private byte[] randomBlocks(int upper)
+ {
+ byte[] bs = new byte[16 * random.nextInt(upper)];
+ random.nextBytes(bs);
+ return bs;
+ }
+
+ private byte[] randomBytes(int upper)
+ {
+ byte[] bs = new byte[random.nextInt(upper)];
+ random.nextBytes(bs);
+ return bs;
+ }
+
+ private byte[] concatArrays(byte[] a, byte[] b) throws IOException
+ {
+ byte[] ab = new byte[a.length + b.length];
+ System.arraycopy(a, 0, ab, 0, a.length);
+ System.arraycopy(b, 0, ab, a.length, b.length);
+ return ab;
+ }
+
+ private byte[] combine_GHASH(byte[] ghashA_, long bitlenA, byte[] ghash_C, long bitlenC)
+ {
+ // Note: bitlenA must be aligned to the block size
+
+ long c = (bitlenC + 127) >>> 7;
+
+ byte[] H_c = new byte[16];
+ exp.exponentiateX(c, H_c);
+
+ byte[] tmp1 = lengthBlock(bitlenA, 0);
+ mul.multiplyH(tmp1);
+
+ byte[] ghashAC = Arrays.clone(ghashA_);
+ xor(ghashAC, tmp1);
+ ghashAC = multiply(ghashAC, H_c);
+ // No need to touch the len(C) part (second 8 bytes)
+ xor(ghashAC, tmp1);
+ xor(ghashAC, ghash_C);
+
+ return ghashAC;
+ }
+
+ private byte[] concatAuth_GHASH(byte[] ghashP, long bitlenP, byte[] ghashA, long bitlenA)
+ {
+ // Note: bitlenP must be aligned to the block size
+
+ long a = (bitlenA + 127) >>> 7;
+
+ byte[] tmp1 = lengthBlock(bitlenP, 0);
+ mul.multiplyH(tmp1);
+
+ byte[] tmp2 = lengthBlock(bitlenA ^ (bitlenP + bitlenA), 0);
+ mul.multiplyH(tmp2);
+
+ byte[] H_a = new byte[16];
+ exp.exponentiateX(a, H_a);
+
+ byte[] ghashC = Arrays.clone(ghashP);
+ xor(ghashC, tmp1);
+ ghashC = multiply(ghashC, H_a);
+ xor(ghashC, tmp2);
+ xor(ghashC, ghashA);
+ return ghashC;
+ }
+
+ private byte[] concatCrypt_GHASH(byte[] ghashP, long bitlenP, byte[] ghashA, long bitlenA)
+ {
+ // Note: bitlenP must be aligned to the block size
+
+ long a = (bitlenA + 127) >>> 7;
+
+ byte[] tmp1 = lengthBlock(0, bitlenP);
+ mul.multiplyH(tmp1);
+
+ byte[] tmp2 = lengthBlock(0, bitlenA ^ (bitlenP + bitlenA));
+ mul.multiplyH(tmp2);
+
+ byte[] H_a = new byte[16];
+ exp.exponentiateX(a, H_a);
+
+ byte[] ghashC = Arrays.clone(ghashP);
+ xor(ghashC, tmp1);
+ ghashC = multiply(ghashC, H_a);
+ xor(ghashC, tmp2);
+ xor(ghashC, ghashA);
+ return ghashC;
+ }
+
+ private byte[] GHASH(byte[] A, byte[] C)
+ {
+ byte[] X = new byte[16];
+
+ {
+ for (int pos = 0; pos < A.length; pos += 16)
+ {
+ byte[] tmp = new byte[16];
+ int num = Math.min(A.length - pos, 16);
+ System.arraycopy(A, pos, tmp, 0, num);
+ xor(X, tmp);
+ mul.multiplyH(X);
+ }
+ }
+
+ {
+ for (int pos = 0; pos < C.length; pos += 16)
+ {
+ byte[] tmp = new byte[16];
+ int num = Math.min(C.length - pos, 16);
+ System.arraycopy(C, pos, tmp, 0, num);
+ xor(X, tmp);
+ mul.multiplyH(X);
+ }
+ }
+
+ {
+ xor(X, lengthBlock((long)A.length * 8, (long)C.length * 8));
+ mul.multiplyH(X);
+ }
+
+ return X;
+ }
+
+ private static byte[] lengthBlock(long bitlenA, long bitlenC)
+ {
+ byte[] tmp = new byte[16];
+ Pack.longToBigEndian(bitlenA, tmp, 0);
+ Pack.longToBigEndian(bitlenC, tmp, 8);
+ return tmp;
+ }
+
+ private static void xor(byte[] block, byte[] val)
+ {
+ for (int i = 15; i >= 0; --i)
+ {
+ block[i] ^= val[i];
+ }
+ }
+
+ private static byte[] multiply(byte[] a, byte[] b)
+ {
+ byte[] c = new byte[16];
+ byte[] tmp = Arrays.clone(b);
+
+ for (int i = 0; i < 16; ++i)
+ {
+ byte bits = a[i];
+ for (int j = 7; j >= 0; --j)
+ {
+ if ((bits & (1 << j)) != 0)
+ {
+ xor(c, tmp);
+ }
+
+ boolean lsb = (tmp[15] & 1) != 0;
+ shiftRight(tmp);
+ if (lsb)
+ {
+ // R = new byte[]{ 0xe1, ... };
+// GCMUtil.xor(v, R);
+ tmp[0] ^= (byte)0xe1;
+ }
+ }
+ }
+
+ return c;
+ }
+
+ private static void shiftRight(byte[] block)
+ {
+ int i = 0;
+ int bit = 0;
+ for (;;)
+ {
+ int b = block[i] & 0xff;
+ block[i] = (byte) ((b >>> 1) | bit);
+ if (++i == 16)
+ {
+ break;
+ }
+ bit = (b & 1) << 7;
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/GCMTest.java b/core/src/test/java/org/spongycastle/crypto/test/GCMTest.java
new file mode 100644
index 00000000..0a28dd18
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/GCMTest.java
@@ -0,0 +1,687 @@
+package org.spongycastle.crypto.test;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.engines.AESFastEngine;
+import org.spongycastle.crypto.engines.DESEngine;
+import org.spongycastle.crypto.modes.GCMBlockCipher;
+import org.spongycastle.crypto.modes.gcm.BasicGCMMultiplier;
+import org.spongycastle.crypto.modes.gcm.GCMMultiplier;
+import org.spongycastle.crypto.modes.gcm.Tables64kGCMMultiplier;
+import org.spongycastle.crypto.modes.gcm.Tables8kGCMMultiplier;
+import org.spongycastle.crypto.params.AEADParameters;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Times;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * Test vectors from "The Galois/Counter Mode of Operation (GCM)", McGrew/Viega, Appendix B
+ */
+public class GCMTest
+ extends SimpleTest
+{
+ private static final String[][] TEST_VECTORS = new String[][] {
+ {
+ "Test Case 1",
+ "00000000000000000000000000000000",
+ "",
+ "",
+ "000000000000000000000000",
+ "",
+ "58e2fccefa7e3061367f1d57a4e7455a",
+ },
+ {
+ "Test Case 2",
+ "00000000000000000000000000000000",
+ "00000000000000000000000000000000",
+ "",
+ "000000000000000000000000",
+ "0388dace60b6a392f328c2b971b2fe78",
+ "ab6e47d42cec13bdf53a67b21257bddf",
+ },
+ {
+ "Test Case 3",
+ "feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a"
+ + "86a7a9531534f7da2e4c303d8a318a72"
+ + "1c3c0c95956809532fcf0e2449a6b525"
+ + "b16aedf5aa0de657ba637b391aafd255",
+ "",
+ "cafebabefacedbaddecaf888",
+ "42831ec2217774244b7221b784d0d49c"
+ + "e3aa212f2c02a4e035c17e2329aca12e"
+ + "21d514b25466931c7d8f6a5aac84aa05"
+ + "1ba30b396a0aac973d58e091473f5985",
+ "4d5c2af327cd64a62cf35abd2ba6fab4",
+ },
+ {
+ "Test Case 4",
+ "feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a"
+ + "86a7a9531534f7da2e4c303d8a318a72"
+ + "1c3c0c95956809532fcf0e2449a6b525"
+ + "b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeef"
+ + "abaddad2",
+ "cafebabefacedbaddecaf888",
+ "42831ec2217774244b7221b784d0d49c"
+ + "e3aa212f2c02a4e035c17e2329aca12e"
+ + "21d514b25466931c7d8f6a5aac84aa05"
+ + "1ba30b396a0aac973d58e091",
+ "5bc94fbc3221a5db94fae95ae7121a47",
+ },
+ {
+ "Test Case 5",
+ "feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a"
+ + "86a7a9531534f7da2e4c303d8a318a72"
+ + "1c3c0c95956809532fcf0e2449a6b525"
+ + "b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeef"
+ + "abaddad2",
+ "cafebabefacedbad",
+ "61353b4c2806934a777ff51fa22a4755"
+ + "699b2a714fcdc6f83766e5f97b6c7423"
+ + "73806900e49f24b22b097544d4896b42"
+ + "4989b5e1ebac0f07c23f4598",
+ "3612d2e79e3b0785561be14aaca2fccb",
+ },
+ {
+ "Test Case 6",
+ "feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a"
+ + "86a7a9531534f7da2e4c303d8a318a72"
+ + "1c3c0c95956809532fcf0e2449a6b525"
+ + "b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeef"
+ + "abaddad2",
+ "9313225df88406e555909c5aff5269aa"
+ + "6a7a9538534f7da1e4c303d2a318a728"
+ + "c3c0c95156809539fcf0e2429a6b5254"
+ + "16aedbf5a0de6a57a637b39b",
+ "8ce24998625615b603a033aca13fb894"
+ + "be9112a5c3a211a8ba262a3cca7e2ca7"
+ + "01e4a9a4fba43c90ccdcb281d48c7c6f"
+ + "d62875d2aca417034c34aee5",
+ "619cc5aefffe0bfa462af43c1699d050",
+ },
+ {
+ "Test Case 7",
+ "00000000000000000000000000000000"
+ + "0000000000000000",
+ "",
+ "",
+ "000000000000000000000000",
+ "",
+ "cd33b28ac773f74ba00ed1f312572435",
+ },
+ {
+ "Test Case 8",
+ "00000000000000000000000000000000"
+ + "0000000000000000",
+ "00000000000000000000000000000000",
+ "",
+ "000000000000000000000000",
+ "98e7247c07f0fe411c267e4384b0f600",
+ "2ff58d80033927ab8ef4d4587514f0fb",
+ },
+ {
+ "Test Case 9",
+ "feffe9928665731c6d6a8f9467308308"
+ + "feffe9928665731c",
+ "d9313225f88406e5a55909c5aff5269a"
+ + "86a7a9531534f7da2e4c303d8a318a72"
+ + "1c3c0c95956809532fcf0e2449a6b525"
+ + "b16aedf5aa0de657ba637b391aafd255",
+ "",
+ "cafebabefacedbaddecaf888",
+ "3980ca0b3c00e841eb06fac4872a2757"
+ + "859e1ceaa6efd984628593b40ca1e19c"
+ + "7d773d00c144c525ac619d18c84a3f47"
+ + "18e2448b2fe324d9ccda2710acade256",
+ "9924a7c8587336bfb118024db8674a14",
+ },
+ {
+ "Test Case 10",
+ "feffe9928665731c6d6a8f9467308308"
+ + "feffe9928665731c",
+ "d9313225f88406e5a55909c5aff5269a"
+ + "86a7a9531534f7da2e4c303d8a318a72"
+ + "1c3c0c95956809532fcf0e2449a6b525"
+ + "b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeef"
+ + "abaddad2",
+ "cafebabefacedbaddecaf888",
+ "3980ca0b3c00e841eb06fac4872a2757"
+ + "859e1ceaa6efd984628593b40ca1e19c"
+ + "7d773d00c144c525ac619d18c84a3f47"
+ + "18e2448b2fe324d9ccda2710",
+ "2519498e80f1478f37ba55bd6d27618c",
+ },
+ {
+ "Test Case 11",
+ "feffe9928665731c6d6a8f9467308308"
+ + "feffe9928665731c",
+ "d9313225f88406e5a55909c5aff5269a"
+ + "86a7a9531534f7da2e4c303d8a318a72"
+ + "1c3c0c95956809532fcf0e2449a6b525"
+ + "b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeef"
+ + "abaddad2",
+ "cafebabefacedbad",
+ "0f10f599ae14a154ed24b36e25324db8"
+ + "c566632ef2bbb34f8347280fc4507057"
+ + "fddc29df9a471f75c66541d4d4dad1c9"
+ + "e93a19a58e8b473fa0f062f7",
+ "65dcc57fcf623a24094fcca40d3533f8",
+ },
+ {
+ "Test Case 12",
+ "feffe9928665731c6d6a8f9467308308"
+ + "feffe9928665731c",
+ "d9313225f88406e5a55909c5aff5269a"
+ + "86a7a9531534f7da2e4c303d8a318a72"
+ + "1c3c0c95956809532fcf0e2449a6b525"
+ + "b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeef"
+ + "abaddad2",
+ "9313225df88406e555909c5aff5269aa"
+ + "6a7a9538534f7da1e4c303d2a318a728"
+ + "c3c0c95156809539fcf0e2429a6b5254"
+ + "16aedbf5a0de6a57a637b39b",
+ "d27e88681ce3243c4830165a8fdcf9ff"
+ + "1de9a1d8e6b447ef6ef7b79828666e45"
+ + "81e79012af34ddd9e2f037589b292db3"
+ + "e67c036745fa22e7e9b7373b",
+ "dcf566ff291c25bbb8568fc3d376a6d9",
+ },
+ {
+ "Test Case 13",
+ "00000000000000000000000000000000"
+ + "00000000000000000000000000000000",
+ "",
+ "",
+ "000000000000000000000000",
+ "",
+ "530f8afbc74536b9a963b4f1c4cb738b",
+ },
+ {
+ "Test Case 14",
+ "00000000000000000000000000000000"
+ + "00000000000000000000000000000000",
+ "00000000000000000000000000000000",
+ "",
+ "000000000000000000000000",
+ "cea7403d4d606b6e074ec5d3baf39d18",
+ "d0d1c8a799996bf0265b98b5d48ab919",
+ },
+ {
+ "Test Case 15",
+ "feffe9928665731c6d6a8f9467308308"
+ + "feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a"
+ + "86a7a9531534f7da2e4c303d8a318a72"
+ + "1c3c0c95956809532fcf0e2449a6b525"
+ + "b16aedf5aa0de657ba637b391aafd255",
+ "",
+ "cafebabefacedbaddecaf888",
+ "522dc1f099567d07f47f37a32a84427d"
+ + "643a8cdcbfe5c0c97598a2bd2555d1aa"
+ + "8cb08e48590dbb3da7b08b1056828838"
+ + "c5f61e6393ba7a0abcc9f662898015ad",
+ "b094dac5d93471bdec1a502270e3cc6c",
+ },
+ {
+ "Test Case 16",
+ "feffe9928665731c6d6a8f9467308308"
+ + "feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a"
+ + "86a7a9531534f7da2e4c303d8a318a72"
+ + "1c3c0c95956809532fcf0e2449a6b525"
+ + "b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeef"
+ + "abaddad2",
+ "cafebabefacedbaddecaf888",
+ "522dc1f099567d07f47f37a32a84427d"
+ + "643a8cdcbfe5c0c97598a2bd2555d1aa"
+ + "8cb08e48590dbb3da7b08b1056828838"
+ + "c5f61e6393ba7a0abcc9f662",
+ "76fc6ece0f4e1768cddf8853bb2d551b",
+ },
+ {
+ "Test Case 17",
+ "feffe9928665731c6d6a8f9467308308"
+ + "feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a"
+ + "86a7a9531534f7da2e4c303d8a318a72"
+ + "1c3c0c95956809532fcf0e2449a6b525"
+ + "b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeef"
+ + "abaddad2",
+ "cafebabefacedbad",
+ "c3762df1ca787d32ae47c13bf19844cb"
+ + "af1ae14d0b976afac52ff7d79bba9de0"
+ + "feb582d33934a4f0954cc2363bc73f78"
+ + "62ac430e64abe499f47c9b1f",
+ "3a337dbf46a792c45e454913fe2ea8f2",
+ },
+ {
+ "Test Case 18",
+ "feffe9928665731c6d6a8f9467308308"
+ + "feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a"
+ + "86a7a9531534f7da2e4c303d8a318a72"
+ + "1c3c0c95956809532fcf0e2449a6b525"
+ + "b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeef"
+ + "abaddad2",
+ "9313225df88406e555909c5aff5269aa"
+ + "6a7a9538534f7da1e4c303d2a318a728"
+ + "c3c0c95156809539fcf0e2429a6b5254"
+ + "16aedbf5a0de6a57a637b39b",
+ "5a8def2f0c9e53f1f75d7853659e2a20"
+ + "eeb2b22aafde6419a058ab4f6f746bf4"
+ + "0fc0c3b780f244452da3ebf1c5d82cde"
+ + "a2418997200ef82e44ae7e3f",
+ "a44a8266ee1c8eb0c8b5d4cf5ae9f19a",
+ },
+ };
+
+ public String getName()
+ {
+ return "GCM";
+ }
+
+ public void performTest() throws Exception
+ {
+ for (int i = 0; i < TEST_VECTORS.length; ++i)
+ {
+ runTestCase(TEST_VECTORS[i]);
+ }
+
+ randomTests();
+ outputSizeTests();
+ testExceptions();
+ }
+
+ protected BlockCipher createAESEngine()
+ {
+ return new AESFastEngine();
+ }
+
+ private void testExceptions() throws InvalidCipherTextException
+ {
+ GCMBlockCipher gcm = new GCMBlockCipher(createAESEngine());
+
+ try
+ {
+ gcm = new GCMBlockCipher(new DESEngine());
+
+ fail("incorrect block size not picked up");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ gcm.init(false, new KeyParameter(new byte[16]));
+
+ fail("illegal argument not picked up");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ AEADTestUtil.testReset(this, new GCMBlockCipher(createAESEngine()), new GCMBlockCipher(createAESEngine()), new AEADParameters(new KeyParameter(new byte[16]), 128, new byte[16]));
+ AEADTestUtil.testTampering(this, gcm, new AEADParameters(new KeyParameter(new byte[16]), 128, new byte[16]));
+ AEADTestUtil.testOutputSizes(this, new GCMBlockCipher(createAESEngine()), new AEADParameters(new KeyParameter(
+ new byte[16]), 128, new byte[16]));
+ AEADTestUtil.testBufferSizeChecks(this, new GCMBlockCipher(createAESEngine()), new AEADParameters(
+ new KeyParameter(new byte[16]), 128, new byte[16]));
+ }
+
+ private void runTestCase(String[] testVector)
+ throws InvalidCipherTextException
+ {
+ for (int macLength = 12; macLength <= 16; ++macLength)
+ {
+ runTestCase(testVector, macLength);
+ }
+ }
+
+ private void runTestCase(String[] testVector, int macLength)
+ throws InvalidCipherTextException
+ {
+ int pos = 0;
+ String testName = testVector[pos++];
+ byte[] K = Hex.decode(testVector[pos++]);
+ byte[] P = Hex.decode(testVector[pos++]);
+ byte[] A = Hex.decode(testVector[pos++]);
+ byte[] IV = Hex.decode(testVector[pos++]);
+ byte[] C = Hex.decode(testVector[pos++]);
+
+ // For short MAC, take leading bytes
+ byte[] t = Hex.decode(testVector[pos++]);
+ byte[] T = new byte[macLength];
+ System.arraycopy(t, 0, T, 0, T.length);
+
+ // Default multiplier
+ runTestCase(null, null, testName, K, IV, A, P, C, T);
+
+ runTestCase(new BasicGCMMultiplier(), new BasicGCMMultiplier(), testName, K, IV, A, P, C, T);
+ runTestCase(new Tables8kGCMMultiplier(), new Tables8kGCMMultiplier(), testName, K, IV, A, P, C, T);
+ runTestCase(new Tables64kGCMMultiplier(), new Tables64kGCMMultiplier(), testName, K, IV, A, P, C, T);
+ }
+
+ private void runTestCase(
+ GCMMultiplier encM,
+ GCMMultiplier decM,
+ String testName,
+ byte[] K,
+ byte[] IV,
+ byte[] A,
+ byte[] P,
+ byte[] C,
+ byte[] T)
+ throws InvalidCipherTextException
+ {
+ byte[] fa = new byte[A.length / 2];
+ byte[] la = new byte[A.length - (A.length / 2)];
+ System.arraycopy(A, 0, fa, 0, fa.length);
+ System.arraycopy(A, fa.length, la, 0, la.length);
+
+ runTestCase(encM, decM, testName + " all initial associated data", K, IV, A, null, P, C, T);
+ runTestCase(encM, decM, testName + " all subsequent associated data", K, IV, null, A, P, C, T);
+ runTestCase(encM, decM, testName + " split associated data", K, IV, fa, la, P, C, T);
+ }
+
+ private void runTestCase(
+ GCMMultiplier encM,
+ GCMMultiplier decM,
+ String testName,
+ byte[] K,
+ byte[] IV,
+ byte[] A,
+ byte[] SA,
+ byte[] P,
+ byte[] C,
+ byte[] T)
+ throws InvalidCipherTextException
+ {
+ AEADParameters parameters = new AEADParameters(new KeyParameter(K), T.length * 8, IV, A);
+ GCMBlockCipher encCipher = initCipher(encM, true, parameters);
+ GCMBlockCipher decCipher = initCipher(decM, false, parameters);
+ checkTestCase(encCipher, decCipher, testName, SA, P, C, T);
+ checkTestCase(encCipher, decCipher, testName + " (reused)", SA, P, C, T);
+
+ // Key reuse
+ AEADParameters keyReuseParams = AEADTestUtil.reuseKey(parameters);
+ encCipher.init(true, keyReuseParams);
+ decCipher.init(false, keyReuseParams);
+ checkTestCase(encCipher, decCipher, testName + " (key reuse)", SA, P, C, T);
+ }
+
+ private GCMBlockCipher initCipher(GCMMultiplier m, boolean forEncryption, AEADParameters parameters)
+ {
+ GCMBlockCipher c = new GCMBlockCipher(createAESEngine(), m);
+ c.init(forEncryption, parameters);
+ return c;
+ }
+
+ private void checkTestCase(
+ GCMBlockCipher encCipher,
+ GCMBlockCipher decCipher,
+ String testName,
+ byte[] SA,
+ byte[] P,
+ byte[] C,
+ byte[] T)
+ throws InvalidCipherTextException
+ {
+ byte[] enc = new byte[encCipher.getOutputSize(P.length)];
+ if (SA != null)
+ {
+ encCipher.processAADBytes(SA, 0, SA.length);
+ }
+ int len = encCipher.processBytes(P, 0, P.length, enc, 0);
+ len += encCipher.doFinal(enc, len);
+
+ if (enc.length != len)
+ {
+// System.out.println("" + enc.length + "/" + len);
+ fail("encryption reported incorrect length: " + testName);
+ }
+
+ byte[] mac = encCipher.getMac();
+
+ byte[] data = new byte[P.length];
+ System.arraycopy(enc, 0, data, 0, data.length);
+ byte[] tail = new byte[enc.length - P.length];
+ System.arraycopy(enc, P.length, tail, 0, tail.length);
+
+ if (!areEqual(C, data))
+ {
+ fail("incorrect encrypt in: " + testName);
+ }
+
+ if (!areEqual(T, mac))
+ {
+ fail("getMac() returned wrong mac in: " + testName);
+ }
+
+ if (!areEqual(T, tail))
+ {
+ fail("stream contained wrong mac in: " + testName);
+ }
+
+ byte[] dec = new byte[decCipher.getOutputSize(enc.length)];
+ if (SA != null)
+ {
+ decCipher.processAADBytes(SA, 0, SA.length);
+ }
+ len = decCipher.processBytes(enc, 0, enc.length, dec, 0);
+ len += decCipher.doFinal(dec, len);
+ mac = decCipher.getMac();
+
+ data = new byte[C.length];
+ System.arraycopy(dec, 0, data, 0, data.length);
+
+ if (!areEqual(P, data))
+ {
+ fail("incorrect decrypt in: " + testName);
+ }
+ }
+
+ private void randomTests()
+ throws InvalidCipherTextException
+ {
+ SecureRandom srng = new SecureRandom();
+ srng.setSeed(Times.nanoTime());
+ randomTests(srng, null);
+ randomTests(srng, new BasicGCMMultiplier());
+ randomTests(srng, new Tables8kGCMMultiplier());
+ randomTests(srng, new Tables64kGCMMultiplier());
+ }
+
+ private void randomTests(SecureRandom srng, GCMMultiplier m)
+ throws InvalidCipherTextException
+ {
+ for (int i = 0; i < 10; ++i)
+ {
+ randomTest(srng, m);
+ }
+ }
+
+ private void randomTest(SecureRandom srng, GCMMultiplier m)
+ throws InvalidCipherTextException
+ {
+ int kLength = 16 + 8 * (Math.abs(srng.nextInt()) % 3);
+ byte[] K = new byte[kLength];
+ srng.nextBytes(K);
+
+ int pLength = srng.nextInt() >>> 16;
+ byte[] P = new byte[pLength];
+ srng.nextBytes(P);
+
+ int aLength = srng.nextInt() >>> 24;
+ byte[] A = new byte[aLength];
+ srng.nextBytes(A);
+
+ int saLength = srng.nextInt() >>> 24;
+ byte[] SA = new byte[saLength];
+ srng.nextBytes(SA);
+
+ int ivLength = 1 + (srng.nextInt() >>> 24);
+ byte[] IV = new byte[ivLength];
+ srng.nextBytes(IV);
+
+ AEADParameters parameters = new AEADParameters(new KeyParameter(K), 16 * 8, IV, A);
+ GCMBlockCipher cipher = initCipher(m, true, parameters);
+ byte[] C = new byte[cipher.getOutputSize(P.length)];
+ int predicted = cipher.getUpdateOutputSize(P.length);
+
+ int split = nextInt(srng, SA.length + 1);
+ cipher.processAADBytes(SA, 0, split);
+ int len = cipher.processBytes(P, 0, P.length, C, 0);
+ cipher.processAADBytes(SA, split, SA.length - split);
+
+ if (predicted != len)
+ {
+ fail("encryption reported incorrect update length in randomised test");
+ }
+
+ len += cipher.doFinal(C, len);
+
+ if (C.length != len)
+ {
+ fail("encryption reported incorrect length in randomised test");
+ }
+
+ byte[] encT = cipher.getMac();
+ byte[] tail = new byte[C.length - P.length];
+ System.arraycopy(C, P.length, tail, 0, tail.length);
+
+ if (!areEqual(encT, tail))
+ {
+ fail("stream contained wrong mac in randomised test");
+ }
+
+ cipher.init(false, parameters);
+ byte[] decP = new byte[cipher.getOutputSize(C.length)];
+ predicted = cipher.getUpdateOutputSize(C.length);
+
+ split = nextInt(srng, SA.length + 1);
+ cipher.processAADBytes(SA, 0, split);
+ len = cipher.processBytes(C, 0, C.length, decP, 0);
+ cipher.processAADBytes(SA, split, SA.length - split);
+
+ if (predicted != len)
+ {
+ fail("decryption reported incorrect update length in randomised test");
+ }
+
+ len += cipher.doFinal(decP, len);
+
+ if (!areEqual(P, decP))
+ {
+ fail("incorrect decrypt in randomised test");
+ }
+
+ byte[] decT = cipher.getMac();
+ if (!areEqual(encT, decT))
+ {
+ fail("decryption produced different mac from encryption");
+ }
+
+ //
+ // key reuse test
+ //
+ cipher.init(false, AEADTestUtil.reuseKey(parameters));
+ decP = new byte[cipher.getOutputSize(C.length)];
+
+ split = nextInt(srng, SA.length + 1);
+ cipher.processAADBytes(SA, 0, split);
+ len = cipher.processBytes(C, 0, C.length, decP, 0);
+ cipher.processAADBytes(SA, split, SA.length - split);
+
+ len += cipher.doFinal(decP, len);
+
+ if (!areEqual(P, decP))
+ {
+ fail("incorrect decrypt in randomised test");
+ }
+
+ decT = cipher.getMac();
+ if (!areEqual(encT, decT))
+ {
+ fail("decryption produced different mac from encryption");
+ }
+ }
+
+ private void outputSizeTests()
+ {
+ byte[] K = new byte[16];
+ byte[] A = null;
+ byte[] IV = new byte[16];
+
+ AEADParameters parameters = new AEADParameters(new KeyParameter(K), 16 * 8, IV, A);
+ GCMBlockCipher cipher = initCipher(null, true, parameters);
+
+ if (cipher.getUpdateOutputSize(0) != 0)
+ {
+ fail("incorrect getUpdateOutputSize for initial 0 bytes encryption");
+ }
+
+ if (cipher.getOutputSize(0) != 16)
+ {
+ fail("incorrect getOutputSize for initial 0 bytes encryption");
+ }
+
+ cipher.init(false, parameters);
+
+ if (cipher.getUpdateOutputSize(0) != 0)
+ {
+ fail("incorrect getUpdateOutputSize for initial 0 bytes decryption");
+ }
+
+ // NOTE: 0 bytes would be truncated data, but we want it to fail in the doFinal, not here
+ if (cipher.getOutputSize(0) != 0)
+ {
+ fail("fragile getOutputSize for initial 0 bytes decryption");
+ }
+
+ if (cipher.getOutputSize(16) != 0)
+ {
+ fail("incorrect getOutputSize for initial MAC-size bytes decryption");
+ }
+ }
+
+ private static int nextInt(SecureRandom rand, int n)
+ {
+ if ((n & -n) == n) // i.e., n is a power of 2
+ {
+ return (int)((n * (long)(rand.nextInt() >>> 1)) >> 31);
+ }
+
+ int bits, value;
+ do
+ {
+ bits = rand.nextInt() >>> 1;
+ value = bits % n;
+ }
+ while (bits - value + (n - 1) < 0);
+
+ return value;
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new GCMTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/GMacTest.java b/core/src/test/java/org/spongycastle/crypto/test/GMacTest.java
new file mode 100644
index 00000000..6d766e3d
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/GMacTest.java
@@ -0,0 +1,174 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.engines.AESFastEngine;
+import org.spongycastle.crypto.macs.GMac;
+import org.spongycastle.crypto.modes.GCMBlockCipher;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * Test vectors for AES-GMAC, extracted from <a
+ * href="http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip">NIST CAVP GCM test
+ * vectors</a>.
+ *
+ */
+public class GMacTest extends SimpleTest
+{
+ private static class TestCase
+ {
+ private byte[] key;
+ private byte[] iv;
+ private byte[] ad;
+ private byte[] tag;
+ private String name;
+
+ private TestCase(final String name, final String key, final String iv, final String ad, final String tag)
+ {
+ this.name = name;
+ this.key = Hex.decode(key);
+ this.iv = Hex.decode(iv);
+ this.ad = Hex.decode(ad);
+ this.tag = Hex.decode(tag);
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public byte[] getKey()
+ {
+ return key;
+ }
+
+ public byte[] getIv()
+ {
+ return iv;
+ }
+
+ public byte[] getAd()
+ {
+ return ad;
+ }
+
+ public byte[] getTag()
+ {
+ return tag;
+ }
+ }
+
+ private static TestCase[] TEST_VECTORS = new TestCase[] {
+ // Count = 0, from each of the PTlen = 0 test vector sequences
+ new TestCase("128/96/0/128", "11754cd72aec309bf52f7687212e8957", "3c819d9a9bed087615030b65", "",
+ "250327c674aaf477aef2675748cf6971"),
+ new TestCase("128/96/0/120", "272f16edb81a7abbea887357a58c1917", "794ec588176c703d3d2a7a07", "",
+ "b6e6f197168f5049aeda32dafbdaeb"),
+ new TestCase("128/96/0/112", "81b6844aab6a568c4556a2eb7eae752f", "ce600f59618315a6829bef4d", "",
+ "89b43e9dbc1b4f597dbbc7655bb5"),
+ new TestCase("128/96/0/104", "cde2f9a9b1a004165ef9dc981f18651b", "29512c29566c7322e1e33e8e", "",
+ "2e58ce7dabd107c82759c66a75"),
+ new TestCase("128/96/0/96", "b01e45cc3088aaba9fa43d81d481823f", "5a2c4a66468713456a4bd5e1", "",
+ "014280f944f53c681164b2ff"),
+
+ new TestCase("128/96/128/128", "77be63708971c4e240d1cb79e8d77feb", "e0e00f19fed7ba0136a797f3",
+ "7a43ec1d9c0a5a78a0b16533a6213cab", "209fcc8d3675ed938e9c7166709dd946"),
+ new TestCase("128/96/128/96", "bea48ae4980d27f357611014d4486625", "32bddb5c3aa998a08556454c",
+ "8a50b0b8c7654bced884f7f3afda2ead", "8e0f6d8bf05ffebe6f500eb1"),
+
+ new TestCase("128/96/384/128", "99e3e8793e686e571d8285c564f75e2b", "c2dd0ab868da6aa8ad9c0d23",
+ "b668e42d4e444ca8b23cfdd95a9fedd5178aa521144890b093733cf5cf22526c5917ee476541809ac6867a8c399309fc",
+ "3f4fba100eaf1f34b0baadaae9995d85"),
+ new TestCase("128/96/384/96", "c77acd1b0918e87053cb3e51651e7013", "39ff857a81745d10f718ac00",
+ "407992f82ea23b56875d9a3cb843ceb83fd27cb954f7c5534d58539fe96fb534502a1b38ea4fac134db0a42de4be1137",
+ "2a5dc173285375dc82835876"),
+
+ new TestCase(
+ "128/1024/0/128",
+ "d0f1f4defa1e8c08b4b26d576392027c",
+ "42b4f01eb9f5a1ea5b1eb73b0fb0baed54f387ecaa0393c7d7dffc6af50146ecc021abf7eb9038d4303d91f8d741a11743166c0860208bcc02c6258fd9511a2fa626f96d60b72fcff773af4e88e7a923506e4916ecbd814651e9f445adef4ad6a6b6c7290cc13b956130eef5b837c939fcac0cbbcc9656cd75b13823ee5acdac",
+ "", "7ab49b57ddf5f62c427950111c5c4f0d"),
+ new TestCase(
+ "128/1024/384/96",
+ "3cce72d37933394a8cac8a82deada8f0",
+ "aa2f0d676d705d9733c434e481972d4888129cf7ea55c66511b9c0d25a92a174b1e28aa072f27d4de82302828955aadcb817c4907361869bd657b45ff4a6f323871987fcf9413b0702d46667380cd493ed24331a28b9ce5bbfa82d3a6e7679fcce81254ba64abcad14fd18b22c560a9d2c1cd1d3c42dac44c683edf92aced894",
+ "5686b458e9c176f4de8428d9ebd8e12f569d1c7595cf49a4b0654ab194409f86c0dd3fdb8eb18033bb4338c70f0b97d1",
+ "a3a9444b21f330c3df64c8b6"), };
+
+ public void performTest()
+ {
+ for (int i = 0; i < TEST_VECTORS.length; i++)
+ {
+ TestCase testCase = TEST_VECTORS[i];
+
+ Mac mac = new GMac(new GCMBlockCipher(new AESFastEngine()), testCase.getTag().length * 8);
+ CipherParameters key = new KeyParameter(testCase.getKey());
+ mac.init(new ParametersWithIV(key, testCase.getIv()));
+
+ testSingleByte(mac, testCase);
+ testMultibyte(mac, testCase);
+ }
+
+ // Invalid mac size
+ testInvalidMacSize(97);
+ testInvalidMacSize(136);
+ testInvalidMacSize(24);
+ }
+
+ private void testInvalidMacSize(int size)
+ {
+ try
+ {
+ GMac mac = new GMac(new GCMBlockCipher(new AESFastEngine()), size);
+ mac.init(new ParametersWithIV(null, new byte[16]));
+ fail("Expected failure for illegal mac size " + size);
+ }
+ catch (IllegalArgumentException e)
+ {
+ if (!e.getMessage().startsWith("Invalid value for MAC size"))
+ {
+ fail("Illegal mac size failed with unexpected message");
+ }
+ }
+ }
+
+ private void testMultibyte(Mac mac, TestCase testCase)
+ {
+ mac.update(testCase.getAd(), 0, testCase.getAd().length);
+ checkMac(mac, testCase);
+ }
+
+ private void testSingleByte(Mac mac, TestCase testCase)
+ {
+ final byte[] ad = testCase.getAd();
+ for (int i = 0; i < ad.length; i++)
+ {
+ mac.update(ad[i]);
+ }
+ checkMac(mac, testCase);
+ }
+
+ private void checkMac(Mac mac, TestCase testCase)
+ {
+ final byte[] generatedMac = new byte[mac.getMacSize()];
+ mac.doFinal(generatedMac, 0);
+ if (!areEqual(testCase.getTag(), generatedMac))
+ {
+ fail("Failed " + testCase.getName() + " - expected " + new String(Hex.encode(testCase.getTag())) + " got "
+ + new String(Hex.encode(generatedMac)));
+ }
+ }
+
+ public String getName()
+ {
+ return "GMac";
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new GMacTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/GOST28147MacTest.java b/core/src/test/java/org/spongycastle/crypto/test/GOST28147MacTest.java
new file mode 100644
index 00000000..4ed50783
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/GOST28147MacTest.java
@@ -0,0 +1,89 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.engines.GOST28147Engine;
+import org.spongycastle.crypto.macs.GOST28147Mac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithSBox;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+/**
+ * GOST 28147 MAC tester
+ */
+public class GOST28147MacTest
+ implements Test
+{
+ //
+ // these GOSTMac for testing.
+ //
+ static byte[] gkeyBytes1 = Hex.decode("6d145dc993f4019e104280df6fcd8cd8e01e101e4c113d7ec4f469ce6dcd9e49");
+ static byte[] gkeyBytes2 = Hex.decode("6d145dc993f4019e104280df6fcd8cd8e01e101e4c113d7ec4f469ce6dcd9e49");
+
+ static byte[] input3 = Hex.decode("7768617420646f2079612077616e7420666f72206e6f7468696e673f");
+ static byte[] input4 = Hex.decode("7768617420646f2079612077616e7420666f72206e6f7468696e673f");
+
+ static byte[] output7 = Hex.decode("93468a46");
+ static byte[] output8 = Hex.decode("93468a46");
+
+ public GOST28147MacTest()
+ {
+ }
+
+ public TestResult perform()
+ {
+ // test1
+ Mac mac = new GOST28147Mac();
+ KeyParameter key = new KeyParameter(gkeyBytes1);
+
+ mac.init(key);
+
+ mac.update(input3, 0, input3.length);
+
+ byte[] out = new byte[4];
+
+ mac.doFinal(out, 0);
+
+ if (!Arrays.areEqual(out, output7))
+ {
+ return new SimpleTestResult(false, getName() + ": Failed test 1 - expected " + new String(Hex.encode(output7)) + " got " + new String(Hex.encode(out)));
+ }
+
+ // test2
+ key = new KeyParameter(gkeyBytes2);
+
+ ParametersWithSBox gparam = new ParametersWithSBox(key, GOST28147Engine.getSBox("E-A"));
+
+ mac.init(gparam);
+
+ mac.update(input4, 0, input4.length);
+
+ out = new byte[4];
+
+ mac.doFinal(out, 0);
+
+ if (!Arrays.areEqual(out, output8))
+ {
+ return new SimpleTestResult(false, getName() + ": Failed test 2 - expected " + new String(Hex.encode(output8)) + " got " + new String(Hex.encode(out)));
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+
+ public String getName()
+ {
+ return "GOST28147Mac";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ GOST28147MacTest test = new GOST28147MacTest();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/GOST28147Test.java b/core/src/test/java/org/spongycastle/crypto/test/GOST28147Test.java
new file mode 100644
index 00000000..a89f2e63
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/GOST28147Test.java
@@ -0,0 +1,328 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.BufferedBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.digests.GOST3411Digest;
+import org.spongycastle.crypto.engines.GOST28147Engine;
+import org.spongycastle.crypto.modes.CBCBlockCipher;
+import org.spongycastle.crypto.modes.CFBBlockCipher;
+import org.spongycastle.crypto.modes.GOFBBlockCipher;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.crypto.params.ParametersWithSBox;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class GOST28147Test
+ extends CipherTest
+{
+ static String input1 = "0000000000000000";
+ static String output1 = "1b0bbc32cebcab42";
+ static String input2 = "bc350e71aac5f5c2";
+ static String output2 = "d35ab653493b49f5";
+ static String input3 = "bc350e71aa11345709acde";
+ static String output3 = "8824c124c4fd14301fb1e8";
+ static String input4 = "000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f";
+ static String output4 = "29b7083e0a6d955ca0ec5b04fdb4ea41949f1dd2efdf17baffc1780b031f3934";
+
+ static byte TestSBox[] = {
+ 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF,
+ 0xF,0xE,0xD,0xC,0xB,0xA,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0,
+ 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF,
+ 0xF,0xE,0xD,0xC,0xB,0xA,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0,
+ 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF,
+ 0xF,0xE,0xD,0xC,0xB,0xA,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0,
+ 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF,
+ 0xF,0xE,0xD,0xC,0xB,0xA,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0
+ };
+
+ static SimpleTest[] tests =
+ { new BlockCipherVectorTest(1, new GOST28147Engine(),
+ new KeyParameter(Hex.decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")),
+ input1, output1),
+ new BlockCipherVectorTest(2, new CBCBlockCipher(new GOST28147Engine()),
+ new ParametersWithIV(new KeyParameter(Hex.decode("00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF")),
+ Hex.decode("1234567890abcdef")), input2, output2),
+ new BlockCipherVectorTest(3, new GOFBBlockCipher(new GOST28147Engine()),
+ new ParametersWithIV(new KeyParameter(Hex.decode("0011223344556677889900112233445566778899001122334455667788990011")),
+ Hex.decode("1234567890abcdef")), //IV
+ input3, output3),
+ new BlockCipherVectorTest(4, new CFBBlockCipher(new GOST28147Engine(), 64),
+ new ParametersWithIV(new KeyParameter(Hex.decode("aafd12f659cae63489b479e5076ddec2f06cb58faafd12f659cae63489b479e5")),
+ Hex.decode("aafd12f659cae634")), input4, output4),
+
+ //tests with parameters, set S-box.
+ new BlockCipherVectorTest(5, new GOST28147Engine(),
+ new KeyParameter(Hex.decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")),//key , default parameter S-box set to D-Test
+ input1, output1),
+ new BlockCipherVectorTest(6, new CFBBlockCipher(new GOST28147Engine(), 64),
+ new ParametersWithIV(
+ new ParametersWithSBox(
+ new KeyParameter(Hex.decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
+ GOST28147Engine.getSBox("D-Test")), //type S-box
+ Hex.decode("1234567890abcdef")), //IV
+ "0000000000000000", //input message
+ "b587f7a0814c911d"), //encrypt message
+ new BlockCipherVectorTest(7, new CFBBlockCipher(new GOST28147Engine(), 64),
+ new ParametersWithIV(
+ new ParametersWithSBox(
+ new KeyParameter(Hex.decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
+ GOST28147Engine.getSBox("E-Test")), //type S-box
+ Hex.decode("1234567890abcdef")), //IV
+ "0000000000000000", //input message
+ "e8287f53f991d52b"), //encrypt message
+ new BlockCipherVectorTest(8, new CFBBlockCipher(new GOST28147Engine(), 64),
+ new ParametersWithIV(
+ new ParametersWithSBox(
+ new KeyParameter(Hex.decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
+ GOST28147Engine.getSBox("E-A")), //type S-box
+ Hex.decode("1234567890abcdef")), //IV
+ "0000000000000000", //input message
+ "c41009dba22ebe35"), //encrypt message
+ new BlockCipherVectorTest(9, new CFBBlockCipher(new GOST28147Engine(), 8),
+ new ParametersWithIV(
+ new ParametersWithSBox(
+ new KeyParameter(Hex.decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
+ GOST28147Engine.getSBox("E-B")), //type S-box
+ Hex.decode("1234567890abcdef")), //IV
+ "0000000000000000", //input message
+ "80d8723fcd3aba28"), //encrypt message
+ new BlockCipherVectorTest(10, new CFBBlockCipher(new GOST28147Engine(), 8),
+ new ParametersWithIV(
+ new ParametersWithSBox(
+ new KeyParameter(Hex.decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
+ GOST28147Engine.getSBox("E-C")), //type S-box
+ Hex.decode("1234567890abcdef")), //IV
+ "0000000000000000", //input message
+ "739f6f95068499b5"), //encrypt message
+ new BlockCipherVectorTest(11, new CFBBlockCipher(new GOST28147Engine(), 8),
+ new ParametersWithIV(
+ new ParametersWithSBox(
+ new KeyParameter(Hex.decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
+ GOST28147Engine.getSBox("E-D")), //type S-box
+ Hex.decode("1234567890abcdef")), //IV
+ "0000000000000000", //input message
+ "4663f720f4340f57"), //encrypt message
+ new BlockCipherVectorTest(12, new CFBBlockCipher(new GOST28147Engine(), 8),
+ new ParametersWithIV(
+ new ParametersWithSBox(
+ new KeyParameter(Hex.decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
+ GOST28147Engine.getSBox("D-A")), //type S-box
+ Hex.decode("1234567890abcdef")), //IV
+ "0000000000000000", //input message
+ "5bb0a31d218ed564"), //encrypt message
+ new BlockCipherVectorTest(13, new CFBBlockCipher(new GOST28147Engine(), 8),
+ new ParametersWithIV(
+ new ParametersWithSBox(
+ new KeyParameter(Hex.decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
+ TestSBox), //set own S-box
+ Hex.decode("1234567890abcdef")), //IV
+ "0000000000000000", //input message
+ "c3af96ef788667c5"), //encrypt message
+ new BlockCipherVectorTest(14, new GOFBBlockCipher(new GOST28147Engine()),
+ new ParametersWithIV(
+ new ParametersWithSBox(
+ new KeyParameter(Hex.decode("4ef72b778f0b0bebeef4f077551cb74a927b470ad7d7f2513454569a247e989d")), //key
+ GOST28147Engine.getSBox("E-A")), //type S-box
+ Hex.decode("1234567890abcdef")), //IV
+ "bc350e71aa11345709acde", //input message
+ "1bcc2282707c676fb656dc"), //encrypt message
+
+ };
+
+ static private final int GOST28147_KEY_LENGTH = 32;
+
+ private byte[] generateKey(byte[] startkey)
+ {
+ byte[] newKey = new byte[GOST28147_KEY_LENGTH];
+
+ GOST3411Digest digest = new GOST3411Digest();
+
+ digest.update(startkey, 0, startkey.length);
+ digest.doFinal(newKey, 0);
+
+ return newKey;
+ }
+
+ GOST28147Test()
+ {
+ super(tests, new GOST28147Engine(), new KeyParameter(new byte[32]));
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ super.performTest();
+
+ //advanced tests with GOST28147KeyGenerator:
+ //encrypt on hesh message; ECB mode:
+ byte[] in = Hex.decode("4e6f77206973207468652074696d6520666f7220616c6c20");
+ byte[] output = Hex.decode("8ad3c8f56b27ff1fbd46409359bdc796bc350e71aac5f5c0");
+ byte[] out = new byte[in.length];
+
+ byte[] key = generateKey(Hex.decode("0123456789abcdef")); //!!! heshing start_key - get 256 bits !!!
+// System.out.println(new String(Hex.encode(key)));
+ CipherParameters param = new ParametersWithSBox(new KeyParameter(key), GOST28147Engine.getSBox("E-A"));
+ //CipherParameters param = new GOST28147Parameters(key,"D-Test");
+ BufferedBlockCipher cipher = new BufferedBlockCipher(new GOST28147Engine());
+
+ cipher.init(true, param);
+ int len1 = cipher.processBytes(in, 0, in.length, out, 0);
+ try
+ {
+ cipher.doFinal(out, len1);
+ }
+ catch (CryptoException e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+ if (out.length != output.length)
+ {
+ fail("failed - "
+ + "expected " + new String(Hex.encode(output)) + " got "
+ + new String(Hex.encode(out)));
+ }
+ for (int i = 0; i != out.length; i++)
+ {
+ if (out[i] != output[i])
+ {
+ fail("failed - " + "expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
+ }
+ }
+
+
+ //encrypt on hesh message; CFB mode:
+ in = Hex.decode("bc350e71aac5f5c2");
+ output = Hex.decode("0ebbbafcf38f14a5");
+ out = new byte[in.length];
+
+ key = generateKey(Hex.decode("0123456789abcdef")); //!!! heshing start_key - get 256 bits !!!
+ param = new ParametersWithIV(new ParametersWithSBox(
+ new KeyParameter(key), //key
+ GOST28147Engine.getSBox("E-A")), //type S-box
+ Hex.decode("1234567890abcdef")); //IV
+
+ cipher = new BufferedBlockCipher(new CFBBlockCipher(new GOST28147Engine(), 64));
+
+ cipher.init(true, param);
+ len1 = cipher.processBytes(in, 0, in.length, out, 0);
+ try
+ {
+ cipher.doFinal(out, len1);
+ }
+ catch (CryptoException e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+ if (out.length != output.length)
+ {
+ fail("failed - " + "expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
+ }
+ for (int i = 0; i != out.length; i++)
+ {
+ if (out[i] != output[i])
+ {
+ fail("failed - " + "expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
+ }
+ }
+
+
+ //encrypt on hesh message; CFB mode:
+ in = Hex.decode("000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f");
+ output = Hex.decode("64988982819f0a1655e226e19ecad79d10cc73bac95c5d7da034786c12294225");
+ out = new byte[in.length];
+
+ key = generateKey(Hex.decode("aafd12f659cae63489b479e5076ddec2f06cb58faafd12f659cae63489b479e5")); //!!! heshing start_key - get 256 bits !!!
+ param = new ParametersWithIV(new ParametersWithSBox(
+ new KeyParameter(key), //key
+ GOST28147Engine.getSBox("E-A")), //type S-box
+ Hex.decode("aafd12f659cae634")); //IV
+
+ cipher = new BufferedBlockCipher(new CFBBlockCipher(new GOST28147Engine(), 64));
+
+ cipher.init(true, param);
+ len1 = cipher.processBytes(in, 0, in.length, out, 0);
+
+ cipher.doFinal(out, len1);
+
+ if (out.length != output.length)
+ {
+ fail("failed - " + "expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
+ }
+
+ for (int i = 0; i != out.length; i++)
+ {
+ if (out[i] != output[i])
+ {
+ fail("failed - " + "expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
+ }
+ }
+
+ //encrypt on hesh message; OFB mode:
+ in = Hex.decode("bc350e71aa11345709acde");
+ output = Hex.decode("1bcc2282707c676fb656dc");
+ out = new byte[in.length];
+
+ key = generateKey(Hex.decode("0123456789abcdef")); //!!! heshing start_key - get 256 bits !!!
+ param = new ParametersWithIV(new ParametersWithSBox(
+ new KeyParameter(key), //key
+ GOST28147Engine.getSBox("E-A")), //type S-box
+ Hex.decode("1234567890abcdef")); //IV
+
+ cipher = new BufferedBlockCipher(new GOFBBlockCipher(new GOST28147Engine()));
+
+ cipher.init(true, param);
+ len1 = cipher.processBytes(in, 0, in.length, out, 0);
+
+ cipher.doFinal(out, len1);
+
+ if (out.length != output.length)
+ {
+ fail("failed - " + "expected "
+ + new String(Hex.encode(output)) + " got "
+ + new String(Hex.encode(out)));
+ }
+ for (int i = 0; i != out.length; i++)
+ {
+ if (out[i] != output[i])
+ {
+ fail("failed - " + "expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
+ }
+ }
+
+ // key reuse test
+ param = new ParametersWithIV(null, // key and sbox reused
+ Hex.decode("1234567890abcdef")); //IV
+
+ cipher.init(true, param);
+ len1 = cipher.processBytes(in, 0, in.length, out, 0);
+
+ cipher.doFinal(out, len1);
+
+ if (out.length != output.length)
+ {
+ fail("failed - " + "expected "
+ + new String(Hex.encode(output)) + " got "
+ + new String(Hex.encode(out)));
+ }
+ for (int i = 0; i != out.length; i++)
+ {
+ if (out[i] != output[i])
+ {
+ fail("failed - " + "expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
+ }
+ }
+ }
+
+ public String getName()
+ {
+ return "GOST28147";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new GOST28147Test());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/GOST3410Test.java b/core/src/test/java/org/spongycastle/crypto/test/GOST3410Test.java
new file mode 100644
index 00000000..08ce0b01
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/GOST3410Test.java
@@ -0,0 +1,1570 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.generators.GOST3410KeyPairGenerator;
+import org.spongycastle.crypto.generators.GOST3410ParametersGenerator;
+import org.spongycastle.crypto.params.GOST3410KeyGenerationParameters;
+import org.spongycastle.crypto.params.GOST3410Parameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.signers.GOST3410Signer;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.FixedSecureRandom;
+import org.spongycastle.util.test.NumberParsing;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+public class GOST3410Test
+ implements Test
+{
+ byte[] hashmessage = Hex.decode("3042453136414534424341374533364339313734453431443642453241453435");
+
+ private byte[] zeroTwo(int length)
+ {
+ byte[] data = new byte[length];
+ data[data.length - 1] = 0x02;
+ return data;
+ }
+
+ private class GOST3410_TEST1_512
+ implements Test
+ {
+ public String getName()
+ {
+ return "GOST3410-TEST1-512";
+ }
+
+ FixedSecureRandom init_random = new FixedSecureRandom(new byte[][] { Hex.decode("00005EC900007341"), zeroTwo(64) });
+ FixedSecureRandom random = new FixedSecureRandom(Hex.decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A"));
+ FixedSecureRandom keyRandom = new FixedSecureRandom(Hex.decode("3036314538303830343630454235324435324234314132373832433138443046"));
+
+ BigInteger pValue = new BigInteger("EE8172AE8996608FB69359B89EB82A69854510E2977A4D63BC97322CE5DC3386EA0A12B343E9190F23177539845839786BB0C345D165976EF2195EC9B1C379E3", 16);
+ BigInteger qValue = new BigInteger("98915E7EC8265EDFCDA31E88F24809DDB064BDC7285DD50D7289F0AC6F49DD2D", 16);
+
+ public TestResult perform()
+ {
+ BigInteger r = new BigInteger("3e5f895e276d81d2d52c0763270a458157b784c57abdbd807bc44fd43a32ac06",16);
+ BigInteger s = new BigInteger("3f0dd5d4400d47c08e4ce505ff7434b6dbf729592e37c74856dab85115a60955",16);
+ GOST3410ParametersGenerator pGen = new GOST3410ParametersGenerator();
+
+ pGen.init(512, 1, init_random);
+
+ GOST3410Parameters params = pGen.generateParameters();
+
+ if (params.getValidationParameters() == null)
+ {
+ return new SimpleTestResult(false, getName() + "validation parameters wrong");
+ }
+ if (params.getValidationParameters().getC() != 29505
+ || params.getValidationParameters().getX0() != 24265)
+ {
+ return new SimpleTestResult(false, getName() + "validation parameters values wrong");
+ }
+ if (!init_random.isExhausted())
+ {
+ return new SimpleTestResult(false, getName()
+ + ": unexpected number of bytes used from 'init_random'.");
+ }
+
+ if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
+ {
+ return new SimpleTestResult(false, getName() + ": p or q wrong");
+ }
+
+ GOST3410KeyPairGenerator GOST3410KeyGen = new GOST3410KeyPairGenerator();
+ GOST3410KeyGenerationParameters genParam = new GOST3410KeyGenerationParameters(keyRandom, params);
+
+ GOST3410KeyGen.init(genParam);
+
+ AsymmetricCipherKeyPair pair = GOST3410KeyGen.generateKeyPair();
+
+ if (!keyRandom.isExhausted())
+ {
+ return new SimpleTestResult(false, getName()
+ + ": unexpected number of bytes used from 'keyRandom'.");
+ }
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
+
+ GOST3410Signer gost3410 = new GOST3410Signer();
+
+ gost3410.init(true, param);
+
+ BigInteger[] sig = gost3410.generateSignature(hashmessage);
+
+ if (!random.isExhausted())
+ {
+ return new SimpleTestResult(false, getName()
+ + ": unexpected number of bytes used from 'random'.");
+ }
+
+ if (!r.equals(sig[0]))
+ {
+ return new SimpleTestResult(false, getName()
+ + ": r component wrong." + System.getProperty("line.separator")
+ + " expecting: " + r.toString(16) + System.getProperty("line.separator")
+ + " got : " + sig[0].toString(16));
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ return new SimpleTestResult(false, getName()
+ + ": s component wrong." + System.getProperty("line.separator")
+ + " expecting: " + s.toString(16) + System.getProperty("line.separator")
+ + " got : " + sig[1].toString(16));
+ }
+
+ gost3410.init(false, pair.getPublic());
+
+ if (gost3410.verifySignature(hashmessage, sig[0], sig[1]))
+ {
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+ else
+ {
+ return new SimpleTestResult(false, getName() + ": verification fails");
+ }
+ }
+ }
+
+ private class GOST3410_TEST2_512
+ implements Test
+ {
+ public String getName()
+ {
+ return "GOST3410-TEST2-512";
+ }
+
+ FixedSecureRandom init_random = new FixedSecureRandom(new byte[][] { Hex.decode("000000003DFC46F1000000000000000D"), zeroTwo(64) });
+ FixedSecureRandom random = new FixedSecureRandom(Hex.decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A"));
+ FixedSecureRandom keyRandom = new FixedSecureRandom(Hex.decode("3036314538303830343630454235324435324234314132373832433138443046"));
+
+ BigInteger pValue = new BigInteger("8b08eb135af966aab39df294538580c7da26765d6d38d30cf1c06aae0d1228c3316a0e29198460fad2b19dc381c15c888c6dfd0fc2c565abb0bf1faff9518f85", 16);
+ BigInteger qValue = new BigInteger("931a58fb6f0dcdf2fe7549bc3f19f4724b56898f7f921a076601edb18c93dc75", 16);
+
+ public TestResult perform()
+ {
+ BigInteger r = new BigInteger("7c07c8cf035c2a1cb2b7fae5807ac7cd623dfca7a1a68f6d858317822f1ea00d",16);
+ BigInteger s = new BigInteger("7e9e036a6ff87dbf9b004818252b1f6fc310bdd4d17cb8c37d9c36c7884de60c",16);
+ GOST3410ParametersGenerator pGen = new GOST3410ParametersGenerator();
+
+ pGen.init(512, 2, init_random);
+
+ GOST3410Parameters params = pGen.generateParameters();
+
+ if (!init_random.isExhausted())
+ {
+ return new SimpleTestResult(false, getName()
+ + ": unexpected number of bytes used from 'init_random'.");
+ }
+
+ if (params.getValidationParameters() == null)
+ {
+ return new SimpleTestResult(false, getName() + ": validation parameters wrong");
+ }
+
+ if (params.getValidationParameters().getCL() != 13
+ || params.getValidationParameters().getX0L() != 1039943409)
+ {
+ return new SimpleTestResult(false, getName() + ": validation parameters values wrong");
+ }
+
+ if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
+ {
+ return new SimpleTestResult(false, getName() + ": p or q wrong");
+ }
+
+ GOST3410KeyPairGenerator GOST3410KeyGen = new GOST3410KeyPairGenerator();
+ GOST3410KeyGenerationParameters genParam = new GOST3410KeyGenerationParameters(keyRandom, params);
+
+ GOST3410KeyGen.init(genParam);
+
+ AsymmetricCipherKeyPair pair = GOST3410KeyGen.generateKeyPair();
+
+ if (!keyRandom.isExhausted())
+ {
+ return new SimpleTestResult(false, getName()
+ + ": unexpected number of bytes used from 'keyRandom'.");
+ }
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
+
+ GOST3410Signer GOST3410 = new GOST3410Signer();
+
+ GOST3410.init(true, param);
+
+ BigInteger[] sig = GOST3410.generateSignature(hashmessage);
+
+ if (!random.isExhausted())
+ {
+ return new SimpleTestResult(false, getName()
+ + ": unexpected number of bytes used from 'random'.");
+ }
+
+ if (!r.equals(sig[0]))
+ {
+ return new SimpleTestResult(false, getName()
+ + ": r component wrong." + System.getProperty("line.separator")
+ + " expecting: " + r.toString(16) + System.getProperty("line.separator")
+ + " got : " + sig[0].toString(16));
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ return new SimpleTestResult(false, getName()
+ + ": s component wrong." + System.getProperty("line.separator")
+ + " expecting: " + s.toString(16) + System.getProperty("line.separator")
+ + " got : " + sig[1].toString(16));
+ }
+
+ GOST3410.init(false, pair.getPublic());
+
+ if (GOST3410.verifySignature(hashmessage, sig[0], sig[1]))
+ {
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+ else
+ {
+ return new SimpleTestResult(false, getName() + ": verification fails");
+ }
+ }
+ }
+
+ private class GOST3410_TEST1_1024
+ implements Test
+ {
+ public String getName()
+ {
+ return "GOST3410-TEST1-1024";
+ }
+
+ SecureRandom init_random = new SecureRandom()
+ {
+ boolean firstInt = true;
+
+ public int nextInt()
+ {
+ String x0 = "0xA565";
+ String c = "0x538B";
+
+ if (firstInt)
+ {
+ firstInt = false;
+ return NumberParsing.decodeIntFromHex(x0);
+ }
+ return NumberParsing.decodeIntFromHex(c);
+ }
+
+ public void nextBytes(byte[] bytes)
+ {
+
+ byte[] d = Hex.decode("02");
+
+ System.arraycopy(d, 0, bytes, bytes.length-d.length, d.length);
+ }
+ };
+
+ SecureRandom random = new SecureRandom()
+ {
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] k = Hex.decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
+
+ int i;
+
+ for (i = 0; i < (bytes.length - k.length); i += k.length)
+ {
+ System.arraycopy(k, 0, bytes, i, k.length);
+ }
+
+ if (i > bytes.length)
+ {
+ System.arraycopy(k, 0, bytes, i - k.length, bytes.length - (i - k.length));
+ }
+ else
+ {
+ System.arraycopy(k, 0, bytes, i, bytes.length - i);
+ }
+ }
+ };
+
+ SecureRandom keyRandom = new SecureRandom()
+ {
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] x = Hex.decode("3036314538303830343630454235324435324234314132373832433138443046");
+
+ int i;
+
+ for (i = 0; i < (bytes.length - x.length); i += x.length)
+ {
+ System.arraycopy(x, 0, bytes, i, x.length);
+ }
+
+ if (i > bytes.length)
+ {
+ System.arraycopy(x, 0, bytes, i - x.length, bytes.length - (i - x.length));
+ }
+ else
+ {
+ System.arraycopy(x, 0, bytes, i, bytes.length - i);
+ }
+ }
+ };
+
+ BigInteger pValue = new BigInteger("ab8f37938356529e871514c1f48c5cbce77b2f4fc9a2673ac2c1653da8984090c0ac73775159a26bef59909d4c9846631270e16653a6234668f2a52a01a39b921490e694c0f104b58d2e14970fccb478f98d01e975a1028b9536d912de5236d2dd2fc396b77153594d4178780e5f16f718471e2111c8ce64a7d7e196fa57142d", 16);
+ BigInteger qValue = new BigInteger("bcc02ca0ce4f0753ec16105ee5d530aa00d39f3171842ab2c334a26b5f576e0f", 16);
+
+ public TestResult perform()
+ {
+ BigInteger r = new BigInteger("a8790aabbd5a998ff524bad048ac69cd1faff2dab048265c8d60d1471c44a9ee",16);
+ BigInteger s = new BigInteger("30df5ba32ac77170b9632559bef7d37620017756dff3fea1088b4267db0944b8",16);
+ GOST3410ParametersGenerator pGen = new GOST3410ParametersGenerator();
+
+ pGen.init(1024, 1, init_random);
+
+ GOST3410Parameters params = pGen.generateParameters();
+
+ if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
+ {
+ return new SimpleTestResult(false, getName() + ": p or q wrong");
+ }
+
+ GOST3410KeyPairGenerator GOST3410KeyGen = new GOST3410KeyPairGenerator();
+ GOST3410KeyGenerationParameters genParam = new GOST3410KeyGenerationParameters(keyRandom, params);
+
+ GOST3410KeyGen.init(genParam);
+
+ AsymmetricCipherKeyPair pair = GOST3410KeyGen.generateKeyPair();
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
+
+ GOST3410Signer GOST3410 = new GOST3410Signer();
+
+ GOST3410.init(true, param);
+
+ BigInteger[] sig = GOST3410.generateSignature(hashmessage);
+
+ if (!r.equals(sig[0]))
+ {
+ return new SimpleTestResult(false, getName()
+ + ": r component wrong." + System.getProperty("line.separator")
+ + " expecting: " + r.toString(16) + System.getProperty("line.separator")
+ + " got : " + sig[0].toString(16));
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ return new SimpleTestResult(false, getName()
+ + ": s component wrong." + System.getProperty("line.separator")
+ + " expecting: " + s.toString(16) + System.getProperty("line.separator")
+ + " got : " + sig[1].toString(16));
+ }
+
+ GOST3410.init(false, pair.getPublic());
+
+ if (GOST3410.verifySignature(hashmessage, sig[0], sig[1]))
+ {
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+ else
+ {
+ return new SimpleTestResult(false, getName() + ": verification fails");
+ }
+ }
+ }
+
+ private class GOST3410_TEST2_1024
+ implements Test
+ {
+ public String getName()
+ {
+ return "GOST3410-TEST2-1024";
+ }
+
+ SecureRandom init_random = new SecureRandom()
+ {
+ boolean firstLong = true;
+
+ public long nextLong()
+ {
+ String x0 = "0x3DFC46F1";
+ String c = "0xD";
+
+ if (firstLong)
+ {
+ firstLong = false;
+ return NumberParsing.decodeLongFromHex(x0);
+ }
+ return NumberParsing.decodeLongFromHex(c);
+ }
+
+ public void nextBytes(byte[] bytes)
+ {
+
+ byte[] d = Hex.decode("02");
+
+ System.arraycopy(d, 0, bytes, bytes.length-d.length, d.length);
+ }
+ };
+
+ SecureRandom random = new SecureRandom()
+ {
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] k = Hex.decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
+
+ int i;
+
+ for (i = 0; i < (bytes.length - k.length); i += k.length)
+ {
+ System.arraycopy(k, 0, bytes, i, k.length);
+ }
+
+ if (i > bytes.length)
+ {
+ System.arraycopy(k, 0, bytes, i - k.length, bytes.length - (i - k.length));
+ }
+ else
+ {
+ System.arraycopy(k, 0, bytes, i, bytes.length - i);
+ }
+ }
+ };
+
+ SecureRandom keyRandom = new SecureRandom()
+ {
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] x = Hex.decode("3036314538303830343630454235324435324234314132373832433138443046");
+
+ int i;
+
+ for (i = 0; i < (bytes.length - x.length); i += x.length)
+ {
+ System.arraycopy(x, 0, bytes, i, x.length);
+ }
+
+ if (i > bytes.length)
+ {
+ System.arraycopy(x, 0, bytes, i - x.length, bytes.length - (i - x.length));
+ }
+ else
+ {
+ System.arraycopy(x, 0, bytes, i, bytes.length - i);
+ }
+ }
+ };
+
+ BigInteger pValue = new BigInteger("e2c4191c4b5f222f9ac2732562f6d9b4f18e7fb67a290ea1e03d750f0b9806755fc730d975bf3faa606d05c218b35a6c3706919aab92e0c58b1de4531c8fa8e7af43c2bff016251e21b2870897f6a27ac4450bca235a5b748ad386e4a0e4dfcb09152435abcfe48bd0b126a8122c7382f285a9864615c66decddf6afd355dfb7", 16);
+ BigInteger qValue = new BigInteger("931a58fb6f0dcdf2fe7549bc3f19f4724b56898f7f921a076601edb18c93dc75", 16);
+
+ public TestResult perform()
+ {
+ BigInteger r = new BigInteger("81d69a192e9c7ac21fc07da41bd07e230ba6a94eb9f3c1fd104c7bd976733ca5",16);
+ BigInteger s = new BigInteger("315c879c8414f35feb4deb15e7cc0278c48e6ca1596325d6959338d860b0c47a",16);
+ GOST3410ParametersGenerator pGen = new GOST3410ParametersGenerator();
+
+ pGen.init(1024, 2, init_random);
+
+ GOST3410Parameters params = pGen.generateParameters();
+
+ if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
+ {
+ return new SimpleTestResult(false, getName() + ": p or q wrong");
+ }
+
+ GOST3410KeyPairGenerator GOST3410KeyGen = new GOST3410KeyPairGenerator();
+ GOST3410KeyGenerationParameters genParam = new GOST3410KeyGenerationParameters(keyRandom, params);
+
+ GOST3410KeyGen.init(genParam);
+
+ AsymmetricCipherKeyPair pair = GOST3410KeyGen.generateKeyPair();
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
+
+ GOST3410Signer GOST3410 = new GOST3410Signer();
+
+ GOST3410.init(true, param);
+
+ BigInteger[] sig = GOST3410.generateSignature(hashmessage);
+
+ if (!r.equals(sig[0]))
+ {
+ return new SimpleTestResult(false, getName()
+ + ": r component wrong." + System.getProperty("line.separator")
+ + " expecting: " + r.toString(16) + System.getProperty("line.separator")
+ + " got : " + sig[0].toString(16));
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ return new SimpleTestResult(false, getName()
+ + ": s component wrong." + System.getProperty("line.separator")
+ + " expecting: " + s.toString(16) + System.getProperty("line.separator")
+ + " got : " + sig[1].toString(16));
+ }
+
+ GOST3410.init(false, pair.getPublic());
+
+ if (GOST3410.verifySignature(hashmessage, sig[0], sig[1]))
+ {
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+ else
+ {
+ return new SimpleTestResult(false, getName() + ": verification fails");
+ }
+ }
+ }
+
+ private class GOST3410_AParam
+ implements Test
+ {
+ public String getName()
+ {
+ return "GOST3410-AParam";
+ }
+
+ SecureRandom init_random = new SecureRandom()
+ {
+ boolean firstLong = true;
+
+ public long nextLong()
+ {
+ String x0 = "0x520874F5";
+ String c = "0xEE39ADB3";
+
+ if (firstLong)
+ {
+ firstLong = false;
+ return NumberParsing.decodeLongFromHex(x0);
+ }
+ return NumberParsing.decodeLongFromHex(c);
+ }
+
+ public void nextBytes(byte[] bytes)
+ {
+
+ byte[] d = Hex.decode("02");
+
+ System.arraycopy(d, 0, bytes, bytes.length-d.length, d.length);
+ }
+ };
+
+ SecureRandom random = new SecureRandom()
+ {
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] k = Hex.decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
+
+ int i;
+
+ for (i = 0; i < (bytes.length - k.length); i += k.length)
+ {
+ System.arraycopy(k, 0, bytes, i, k.length);
+ }
+
+ if (i > bytes.length)
+ {
+ System.arraycopy(k, 0, bytes, i - k.length, bytes.length - (i - k.length));
+ }
+ else
+ {
+ System.arraycopy(k, 0, bytes, i, bytes.length - i);
+ }
+ }
+ };
+
+ SecureRandom keyRandom = new SecureRandom()
+ {
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] x = Hex.decode("3036314538303830343630454235324435324234314132373832433138443046");
+
+ int i;
+
+ for (i = 0; i < (bytes.length - x.length); i += x.length)
+ {
+ System.arraycopy(x, 0, bytes, i, x.length);
+ }
+
+ if (i > bytes.length)
+ {
+ System.arraycopy(x, 0, bytes, i - x.length, bytes.length - (i - x.length));
+ }
+ else
+ {
+ System.arraycopy(x, 0, bytes, i, bytes.length - i);
+ }
+ }
+ };
+
+ BigInteger pValue = new BigInteger("b4e25efb018e3c8b87505e2a67553c5edc56c2914b7e4f89d23f03f03377e70a2903489dd60e78418d3d851edb5317c4871e40b04228c3b7902963c4b7d85d52b9aa88f2afdbeb28da8869d6df846a1d98924e925561bd69300b9ddd05d247b5922d967cbb02671881c57d10e5ef72d3e6dad4223dc82aa1f7d0294651a480df", 16);
+ BigInteger qValue = new BigInteger("972432a437178b30bd96195b773789ab2fff15594b176dd175b63256ee5af2cf", 16);
+
+ public TestResult perform()
+ {
+ BigInteger r = new BigInteger("64a8856628e5669d85f62cd763dd4a99bc56d33dc0e1859122855d141e9e4774",16);
+ BigInteger s = new BigInteger("319ebac97092b288d469a4b988248794f60c865bc97858d9a3135c6d1a1bf2dd",16);
+ GOST3410ParametersGenerator pGen = new GOST3410ParametersGenerator();
+
+ pGen.init(1024, 2, init_random);
+
+ GOST3410Parameters params = pGen.generateParameters();
+
+ if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
+ {
+ return new SimpleTestResult(false, getName() + ": p or q wrong");
+ }
+
+ GOST3410KeyPairGenerator GOST3410KeyGen = new GOST3410KeyPairGenerator();
+ GOST3410KeyGenerationParameters genParam = new GOST3410KeyGenerationParameters(keyRandom, params);
+
+ GOST3410KeyGen.init(genParam);
+
+ AsymmetricCipherKeyPair pair = GOST3410KeyGen.generateKeyPair();
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
+
+ GOST3410Signer GOST3410 = new GOST3410Signer();
+
+ GOST3410.init(true, param);
+
+ BigInteger[] sig = GOST3410.generateSignature(hashmessage);
+
+ if (!r.equals(sig[0]))
+ {
+ return new SimpleTestResult(false, getName()
+ + ": r component wrong." + System.getProperty("line.separator")
+ + " expecting: " + r.toString(16) + System.getProperty("line.separator")
+ + " got : " + sig[0].toString(16));
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ return new SimpleTestResult(false, getName()
+ + ": s component wrong." + System.getProperty("line.separator")
+ + " expecting: " + s.toString(16) + System.getProperty("line.separator")
+ + " got : " + sig[1].toString(16));
+ }
+
+ GOST3410.init(false, pair.getPublic());
+
+ if (GOST3410.verifySignature(hashmessage, sig[0], sig[1]))
+ {
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+ else
+ {
+ return new SimpleTestResult(false, getName() + ": verification fails");
+ }
+ }
+ }
+
+ private class GOST3410_BParam
+ implements Test
+ {
+ public String getName()
+ {
+ return "GOST3410-BParam";
+ }
+
+ SecureRandom init_random = new SecureRandom()
+ {
+ boolean firstLong = true;
+
+ public long nextLong()
+ {
+ String x0 = "0x5B977CDB";
+ String c = "0x6E9692DD";
+
+ if (firstLong)
+ {
+ firstLong = false;
+ return NumberParsing.decodeLongFromHex(x0);
+ }
+ return NumberParsing.decodeLongFromHex(c);
+ }
+
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] d = Hex.decode("bc3cbbdb7e6f848286e19ad9a27a8e297e5b71c53dd974cdf60f937356df69cbc97a300ccc71685c553046147f11568c4fddf363d9d886438345a62c3b75963d6546adfabf31b31290d12cae65ecb8309ef66782");
+
+ System.arraycopy(d, 0, bytes, bytes.length-d.length, d.length);
+ }
+ };
+
+ SecureRandom random = new SecureRandom()
+ {
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] k = Hex.decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
+
+ int i;
+
+ for (i = 0; i < (bytes.length - k.length); i += k.length)
+ {
+ System.arraycopy(k, 0, bytes, i, k.length);
+ }
+
+ if (i > bytes.length)
+ {
+ System.arraycopy(k, 0, bytes, i - k.length, bytes.length - (i - k.length));
+ }
+ else
+ {
+ System.arraycopy(k, 0, bytes, i, bytes.length - i);
+ }
+ }
+ };
+
+ SecureRandom keyRandom = new SecureRandom()
+ {
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] x = Hex.decode("3036314538303830343630454235324435324234314132373832433138443046");
+
+ int i;
+
+ for (i = 0; i < (bytes.length - x.length); i += x.length)
+ {
+ System.arraycopy(x, 0, bytes, i, x.length);
+ }
+
+ if (i > bytes.length)
+ {
+ System.arraycopy(x, 0, bytes, i - x.length, bytes.length - (i - x.length));
+ }
+ else
+ {
+ System.arraycopy(x, 0, bytes, i, bytes.length - i);
+ }
+ }
+ };
+
+ BigInteger pValue = new BigInteger("c6971fc57524b30c9018c5e621de15499736854f56a6f8aee65a7a404632b3540f09020f67f04dc2e6783b141dceffd21a703035b7d0187c6e12cb4229922bafdb2225b73e6b23a0de36e20047065aea000c1a374283d0ad8dc1981e3995f0bb8c72526041fcb98ae6163e1e71a669d8364e9c4c3188f673c5f8ee6fadb41abf", 16);
+ BigInteger qValue = new BigInteger("b09d634c10899cd7d4c3a7657403e05810b07c61a688bab2c37f475e308b0607", 16);
+
+ public TestResult perform()
+ {
+ BigInteger r = new BigInteger("860d82c60e9502cd00c0e9e1f6563feafec304801974d745c5e02079946f729e",16);
+ BigInteger s = new BigInteger("7ef49264ef022801aaa03033cd97915235fbab4c823ed936b0f360c22114688a",16);
+ GOST3410ParametersGenerator pGen = new GOST3410ParametersGenerator();
+
+ pGen.init(1024, 2, init_random);
+
+ GOST3410Parameters params = pGen.generateParameters();
+
+ if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
+ {
+ return new SimpleTestResult(false, getName() + ": p or q wrong");
+ }
+
+ GOST3410KeyPairGenerator GOST3410KeyGen = new GOST3410KeyPairGenerator();
+ GOST3410KeyGenerationParameters genParam = new GOST3410KeyGenerationParameters(keyRandom, params);
+
+ GOST3410KeyGen.init(genParam);
+
+ AsymmetricCipherKeyPair pair = GOST3410KeyGen.generateKeyPair();
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
+
+ GOST3410Signer GOST3410 = new GOST3410Signer();
+
+ GOST3410.init(true, param);
+
+ BigInteger[] sig = GOST3410.generateSignature(hashmessage);
+
+ if (!r.equals(sig[0]))
+ {
+ return new SimpleTestResult(false, getName()
+ + ": r component wrong." + System.getProperty("line.separator")
+ + " expecting: " + r.toString(16) + System.getProperty("line.separator")
+ + " got : " + sig[0].toString(16));
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ return new SimpleTestResult(false, getName()
+ + ": s component wrong." + System.getProperty("line.separator")
+ + " expecting: " + s.toString(16) + System.getProperty("line.separator")
+ + " got : " + sig[1].toString(16));
+ }
+
+ GOST3410.init(false, pair.getPublic());
+
+ if (GOST3410.verifySignature(hashmessage, sig[0], sig[1]))
+ {
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+ else
+ {
+ return new SimpleTestResult(false, getName() + ": verification fails");
+ }
+ }
+ }
+
+ private class GOST3410_CParam
+ implements Test
+ {
+ public String getName()
+ {
+ return "GOST3410-CParam";
+ }
+
+ SecureRandom init_random = new SecureRandom()
+ {
+ boolean firstLong = true;
+
+ public long nextLong()
+ {
+ String x0 = "0x43848744";
+ String c = "0xB50A826D";
+
+ if (firstLong)
+ {
+ firstLong = false;
+ return NumberParsing.decodeLongFromHex(x0);
+ }
+ return NumberParsing.decodeLongFromHex(c);
+ }
+
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] d = Hex.decode("7F575E8194BC5BDF");
+
+ System.arraycopy(d, 0, bytes, bytes.length-d.length, d.length);
+ }
+ };
+
+ SecureRandom random = new SecureRandom()
+ {
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] k = Hex.decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
+
+ int i;
+
+ for (i = 0; i < (bytes.length - k.length); i += k.length)
+ {
+ System.arraycopy(k, 0, bytes, i, k.length);
+ }
+
+ if (i > bytes.length)
+ {
+ System.arraycopy(k, 0, bytes, i - k.length, bytes.length - (i - k.length));
+ }
+ else
+ {
+ System.arraycopy(k, 0, bytes, i, bytes.length - i);
+ }
+ }
+ };
+
+ SecureRandom keyRandom = new SecureRandom()
+ {
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] x = Hex.decode("3036314538303830343630454235324435324234314132373832433138443046");
+
+ int i;
+
+ for (i = 0; i < (bytes.length - x.length); i += x.length)
+ {
+ System.arraycopy(x, 0, bytes, i, x.length);
+ }
+
+ if (i > bytes.length)
+ {
+ System.arraycopy(x, 0, bytes, i - x.length, bytes.length - (i - x.length));
+ }
+ else
+ {
+ System.arraycopy(x, 0, bytes, i, bytes.length - i);
+ }
+ }
+ };
+
+ BigInteger pValue = new BigInteger("9d88e6d7fe3313bd2e745c7cdd2ab9ee4af3c8899e847de74a33783ea68bc30588ba1f738c6aaf8ab350531f1854c3837cc3c860ffd7e2e106c3f63b3d8a4c034ce73942a6c3d585b599cf695ed7a3c4a93b2b947b7157bb1a1c043ab41ec8566c6145e938a611906de0d32e562494569d7e999a0dda5c879bdd91fe124df1e9", 16);
+ BigInteger qValue = new BigInteger("fadd197abd19a1b4653eecf7eca4d6a22b1f7f893b641f901641fbb555354faf", 16);
+
+ public TestResult perform()
+ {
+ BigInteger r = new BigInteger("4deb95a0b35e7ed7edebe9bef5a0f93739e16b7ff27fe794d989d0c13159cfbc",16);
+ BigInteger s = new BigInteger("e1d0d30345c24cfeb33efde3deee5fbbda78ddc822b719d860cd0ba1fb6bd43b",16);
+ GOST3410ParametersGenerator pGen = new GOST3410ParametersGenerator();
+
+ pGen.init(1024, 2, init_random);
+
+ GOST3410Parameters params = pGen.generateParameters();
+
+ if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
+ {
+ return new SimpleTestResult(false, getName() + ": p or q wrong");
+ }
+
+ GOST3410KeyPairGenerator GOST3410KeyGen = new GOST3410KeyPairGenerator();
+ GOST3410KeyGenerationParameters genParam = new GOST3410KeyGenerationParameters(keyRandom, params);
+
+ GOST3410KeyGen.init(genParam);
+
+ AsymmetricCipherKeyPair pair = GOST3410KeyGen.generateKeyPair();
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
+
+ GOST3410Signer GOST3410 = new GOST3410Signer();
+
+ GOST3410.init(true, param);
+
+ BigInteger[] sig = GOST3410.generateSignature(hashmessage);
+
+ if (!r.equals(sig[0]))
+ {
+ return new SimpleTestResult(false, getName()
+ + ": r component wrong." + System.getProperty("line.separator")
+ + " expecting: " + r.toString(16) + System.getProperty("line.separator")
+ + " got : " + sig[0].toString(16));
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ return new SimpleTestResult(false, getName()
+ + ": s component wrong." + System.getProperty("line.separator")
+ + " expecting: " + s.toString(16) + System.getProperty("line.separator")
+ + " got : " + sig[1].toString(16));
+ }
+
+ GOST3410.init(false, pair.getPublic());
+
+ if (GOST3410.verifySignature(hashmessage, sig[0], sig[1]))
+ {
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+ else
+ {
+ return new SimpleTestResult(false, getName() + ": verification fails");
+ }
+ }
+ }
+
+ private class GOST3410_DParam
+ implements Test
+ {
+ public String getName()
+ {
+ return "GOST3410-DParam";
+ }
+
+ SecureRandom init_random = new SecureRandom()
+ {
+ boolean firstLong = true;
+
+ public long nextLong()
+ {
+ String x0 = "0x13DA8B9D";
+ String c = "0xA0E9DE4B";
+
+ if (firstLong)
+ {
+ firstLong = false;
+ return NumberParsing.decodeLongFromHex(x0);
+ }
+ return NumberParsing.decodeLongFromHex(c);
+ }
+
+ public void nextBytes(byte[] bytes)
+ {
+
+ byte[] d = Hex.decode("41ab97857f42614355d32db0b1069f109a4da283676c7c53a68185b4");
+
+ System.arraycopy(d, 0, bytes, bytes.length-d.length, d.length);
+ }
+ };
+
+ SecureRandom random = new SecureRandom()
+ {
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] k = Hex.decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
+
+ int i;
+
+ for (i = 0; i < (bytes.length - k.length); i += k.length)
+ {
+ System.arraycopy(k, 0, bytes, i, k.length);
+ }
+
+ if (i > bytes.length)
+ {
+ System.arraycopy(k, 0, bytes, i - k.length, bytes.length - (i - k.length));
+ }
+ else
+ {
+ System.arraycopy(k, 0, bytes, i, bytes.length - i);
+ }
+ }
+ };
+
+ SecureRandom keyRandom = new SecureRandom()
+ {
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] x = Hex.decode("3036314538303830343630454235324435324234314132373832433138443046");
+
+ int i;
+
+ for (i = 0; i < (bytes.length - x.length); i += x.length)
+ {
+ System.arraycopy(x, 0, bytes, i, x.length);
+ }
+
+ if (i > bytes.length)
+ {
+ System.arraycopy(x, 0, bytes, i - x.length, bytes.length - (i - x.length));
+ }
+ else
+ {
+ System.arraycopy(x, 0, bytes, i, bytes.length - i);
+ }
+ }
+ };
+
+ BigInteger pValue = new BigInteger("80f102d32b0fd167d069c27a307adad2c466091904dbaa55d5b8cc7026f2f7a1919b890cb652c40e054e1e9306735b43d7b279eddf9102001cd9e1a831fe8a163eed89ab07cf2abe8242ac9dedddbf98d62cddd1ea4f5f15d3a42a6677bdd293b24260c0f27c0f1d15948614d567b66fa902baa11a69ae3bceadbb83e399c9b5", 16);
+ BigInteger qValue = new BigInteger("f0f544c418aac234f683f033511b65c21651a6078bda2d69bb9f732867502149", 16);
+
+ public TestResult perform()
+ {
+ BigInteger r = new BigInteger("712592d285b792e33b8a9a11e8e6c4f512ddf0042972bbfd1abb0a93e8fc6f54",16);
+ BigInteger s = new BigInteger("2cf26758321258b130d5612111339f09ceb8668241f3482e38baa56529963f07",16);
+ GOST3410ParametersGenerator pGen = new GOST3410ParametersGenerator();
+
+ pGen.init(1024, 2, init_random);
+
+ GOST3410Parameters params = pGen.generateParameters();
+
+ if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
+ {
+ return new SimpleTestResult(false, getName() + ": p or q wrong");
+ }
+
+ GOST3410KeyPairGenerator GOST3410KeyGen = new GOST3410KeyPairGenerator();
+ GOST3410KeyGenerationParameters genParam = new GOST3410KeyGenerationParameters(keyRandom, params);
+
+ GOST3410KeyGen.init(genParam);
+
+ AsymmetricCipherKeyPair pair = GOST3410KeyGen.generateKeyPair();
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
+
+ GOST3410Signer GOST3410 = new GOST3410Signer();
+
+ GOST3410.init(true, param);
+
+ BigInteger[] sig = GOST3410.generateSignature(hashmessage);
+
+ if (!r.equals(sig[0]))
+ {
+ return new SimpleTestResult(false, getName()
+ + ": r component wrong." + System.getProperty("line.separator")
+ + " expecting: " + r.toString(16) + System.getProperty("line.separator")
+ + " got : " + sig[0].toString(16));
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ return new SimpleTestResult(false, getName()
+ + ": s component wrong." + System.getProperty("line.separator")
+ + " expecting: " + s.toString(16) + System.getProperty("line.separator")
+ + " got : " + sig[1].toString(16));
+ }
+
+ GOST3410.init(false, pair.getPublic());
+
+ if (GOST3410.verifySignature(hashmessage, sig[0], sig[1]))
+ {
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+ else
+ {
+ return new SimpleTestResult(false, getName() + ": verification fails");
+ }
+ }
+ }
+
+ private class GOST3410_AExParam
+ implements Test
+ {
+ public String getName()
+ {
+ return "GOST3410-AExParam";
+ }
+
+ SecureRandom init_random = new SecureRandom()
+ {
+ boolean firstLong = true;
+
+ public long nextLong()
+ {
+ String x0 = "0xD05E9F14";
+ String c = "0x46304C5F";
+
+ if (firstLong)
+ {
+ firstLong = false;
+ return NumberParsing.decodeLongFromHex(x0);
+ }
+ return NumberParsing.decodeLongFromHex(c);
+ }
+
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] d = Hex.decode("35ab875399cda33c146ca629660e5a5e5c07714ca326db032dd6751995cdb90a612b9228932d8302704ec24a5def7739c5813d83");
+
+ System.arraycopy(d, 0, bytes, bytes.length-d.length, d.length);
+ }
+ };
+
+ SecureRandom random = new SecureRandom()
+ {
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] k = Hex.decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
+
+ int i;
+
+ for (i = 0; i < (bytes.length - k.length); i += k.length)
+ {
+ System.arraycopy(k, 0, bytes, i, k.length);
+ }
+
+ if (i > bytes.length)
+ {
+ System.arraycopy(k, 0, bytes, i - k.length, bytes.length - (i - k.length));
+ }
+ else
+ {
+ System.arraycopy(k, 0, bytes, i, bytes.length - i);
+ }
+ }
+ };
+
+ SecureRandom keyRandom = new SecureRandom()
+ {
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] x = Hex.decode("3036314538303830343630454235324435324234314132373832433138443046");
+
+ int i;
+
+ for (i = 0; i < (bytes.length - x.length); i += x.length)
+ {
+ System.arraycopy(x, 0, bytes, i, x.length);
+ }
+
+ if (i > bytes.length)
+ {
+ System.arraycopy(x, 0, bytes, i - x.length, bytes.length - (i - x.length));
+ }
+ else
+ {
+ System.arraycopy(x, 0, bytes, i, bytes.length - i);
+ }
+ }
+ };
+
+ BigInteger pValue = new BigInteger("ca3b3f2eee9fd46317d49595a9e7518e6c63d8f4eb4d22d10d28af0b8839f079f8289e603b03530784b9bb5a1e76859e4850c670c7b71c0df84ca3e0d6c177fe9f78a9d8433230a883cd82a2b2b5c7a3306980278570cdb79bf01074a69c9623348824b0c53791d53c6a78cab69e1cfb28368611a397f50f541e16db348dbe5f", 16);
+ BigInteger qValue = new BigInteger("cae4d85f80c147704b0ca48e85fb00a9057aa4acc44668e17f1996d7152690d9", 16);
+
+ public TestResult perform()
+ {
+ BigInteger r = new BigInteger("90892707282f433398488f19d31ac48523a8e2ded68944e0da91c6895ee7045e",16);
+ BigInteger s = new BigInteger("3be4620ee88f1ee8f9dd63c7d145b7e554839feeca125049118262ea4651e9de",16);
+ GOST3410ParametersGenerator pGen = new GOST3410ParametersGenerator();
+
+ pGen.init(1024, 2, init_random);
+
+ GOST3410Parameters params = pGen.generateParameters();
+
+ if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
+ {
+ return new SimpleTestResult(false, getName() + ": p or q wrong");
+ }
+
+ GOST3410KeyPairGenerator GOST3410KeyGen = new GOST3410KeyPairGenerator();
+ GOST3410KeyGenerationParameters genParam = new GOST3410KeyGenerationParameters(keyRandom, params);
+
+ GOST3410KeyGen.init(genParam);
+
+ AsymmetricCipherKeyPair pair = GOST3410KeyGen.generateKeyPair();
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
+
+ GOST3410Signer GOST3410 = new GOST3410Signer();
+
+ GOST3410.init(true, param);
+
+ BigInteger[] sig = GOST3410.generateSignature(hashmessage);
+
+ if (!r.equals(sig[0]))
+ {
+ return new SimpleTestResult(false, getName()
+ + ": r component wrong." + System.getProperty("line.separator")
+ + " expecting: " + r.toString(16) + System.getProperty("line.separator")
+ + " got : " + sig[0].toString(16));
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ return new SimpleTestResult(false, getName()
+ + ": s component wrong." + System.getProperty("line.separator")
+ + " expecting: " + s.toString(16) + System.getProperty("line.separator")
+ + " got : " + sig[1].toString(16));
+ }
+
+ GOST3410.init(false, pair.getPublic());
+
+ if (GOST3410.verifySignature(hashmessage, sig[0], sig[1]))
+ {
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+ else
+ {
+ return new SimpleTestResult(false, getName() + ": verification fails");
+ }
+ }
+ }
+
+ private class GOST3410_BExParam
+ implements Test
+ {
+ public String getName()
+ {
+ return "GOST3410-BExParam";
+ }
+
+ SecureRandom init_random = new SecureRandom()
+ {
+ boolean firstLong = true;
+
+ public long nextLong()
+ {
+ String x0 = "0x7A007804";
+ String c = "0xD31A4FF7";
+
+ if (firstLong)
+ {
+ firstLong = false;
+ return NumberParsing.decodeLongFromHex(x0);
+ }
+ return NumberParsing.decodeLongFromHex(c);
+ }
+
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] d = Hex.decode("7ec123d161477762838c2bea9dbdf33074af6d41d108a066a1e7a07ab3048de2");
+
+ System.arraycopy(d, 0, bytes, bytes.length-d.length, d.length);
+ }
+ };
+
+ SecureRandom random = new SecureRandom()
+ {
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] k = Hex.decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
+
+ int i;
+
+ for (i = 0; i < (bytes.length - k.length); i += k.length)
+ {
+ System.arraycopy(k, 0, bytes, i, k.length);
+ }
+
+ if (i > bytes.length)
+ {
+ System.arraycopy(k, 0, bytes, i - k.length, bytes.length - (i - k.length));
+ }
+ else
+ {
+ System.arraycopy(k, 0, bytes, i, bytes.length - i);
+ }
+ }
+ };
+
+ SecureRandom keyRandom = new SecureRandom()
+ {
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] x = Hex.decode("3036314538303830343630454235324435324234314132373832433138443046");
+
+ int i;
+
+ for (i = 0; i < (bytes.length - x.length); i += x.length)
+ {
+ System.arraycopy(x, 0, bytes, i, x.length);
+ }
+
+ if (i > bytes.length)
+ {
+ System.arraycopy(x, 0, bytes, i - x.length, bytes.length - (i - x.length));
+ }
+ else
+ {
+ System.arraycopy(x, 0, bytes, i, bytes.length - i);
+ }
+ }
+ };
+
+ BigInteger pValue = new BigInteger("9286dbda91eccfc3060aa5598318e2a639f5ba90a4ca656157b2673fb191cd0589ee05f4cef1bd13508408271458c30851ce7a4ef534742bfb11f4743c8f787b11193ba304c0e6bca25701bf88af1cb9b8fd4711d89f88e32b37d95316541bf1e5dbb4989b3df13659b88c0f97a3c1087b9f2d5317d557dcd4afc6d0a754e279", 16);
+ BigInteger qValue = new BigInteger("c966e9b3b8b7cdd82ff0f83af87036c38f42238ec50a876cd390e43d67b6013f", 16);
+
+ public TestResult perform()
+ {
+ BigInteger r = new BigInteger("8f79a582513df84dc247bcb624340cc0e5a34c4324a20ce7fe3ab8ff38a9db71",16);
+ BigInteger s = new BigInteger("7508d22fd6cbb45efd438cb875e43f137247088d0f54b29a7c91f68a65b5fa85",16);
+ GOST3410ParametersGenerator pGen = new GOST3410ParametersGenerator();
+
+ pGen.init(1024, 2, init_random);
+
+ GOST3410Parameters params = pGen.generateParameters();
+
+ if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
+ {
+ return new SimpleTestResult(false, getName() + ": p or q wrong");
+ }
+
+ GOST3410KeyPairGenerator GOST3410KeyGen = new GOST3410KeyPairGenerator();
+ GOST3410KeyGenerationParameters genParam = new GOST3410KeyGenerationParameters(keyRandom, params);
+
+ GOST3410KeyGen.init(genParam);
+
+ AsymmetricCipherKeyPair pair = GOST3410KeyGen.generateKeyPair();
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
+
+ GOST3410Signer GOST3410 = new GOST3410Signer();
+
+ GOST3410.init(true, param);
+
+ BigInteger[] sig = GOST3410.generateSignature(hashmessage);
+
+ if (!r.equals(sig[0]))
+ {
+ return new SimpleTestResult(false, getName()
+ + ": r component wrong." + System.getProperty("line.separator")
+ + " expecting: " + r.toString(16) + System.getProperty("line.separator")
+ + " got : " + sig[0].toString(16));
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ return new SimpleTestResult(false, getName()
+ + ": s component wrong." + System.getProperty("line.separator")
+ + " expecting: " + s.toString(16) + System.getProperty("line.separator")
+ + " got : " + sig[1].toString(16));
+ }
+
+ GOST3410.init(false, pair.getPublic());
+
+ if (GOST3410.verifySignature(hashmessage, sig[0], sig[1]))
+ {
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+ else
+ {
+ return new SimpleTestResult(false, getName() + ": verification fails");
+ }
+ }
+ }
+
+ private class GOST3410_CExParam
+ implements Test
+ {
+ public String getName()
+ {
+ return "GOST3410-CExParam";
+ }
+
+ SecureRandom init_random = new SecureRandom()
+ {
+ boolean firstLong = true;
+
+ public long nextLong()
+ {
+ String x0 = "0x162AB910";
+ String c = "0x93F828D3";
+
+ if (firstLong)
+ {
+ firstLong = false;
+ return NumberParsing.decodeLongFromHex(x0);
+ }
+ return NumberParsing.decodeLongFromHex(c);
+ }
+
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] d = Hex.decode("ca82cce78a738bc46f103d53b9bf809745ec845e4f6da462606c51f60ecf302e31204b81");
+
+ System.arraycopy(d, 0, bytes, bytes.length-d.length, d.length);
+ }
+ };
+
+ SecureRandom random = new SecureRandom()
+ {
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] k = Hex.decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
+
+ int i;
+
+ for (i = 0; i < (bytes.length - k.length); i += k.length)
+ {
+ System.arraycopy(k, 0, bytes, i, k.length);
+ }
+
+ if (i > bytes.length)
+ {
+ System.arraycopy(k, 0, bytes, i - k.length, bytes.length - (i - k.length));
+ }
+ else
+ {
+ System.arraycopy(k, 0, bytes, i, bytes.length - i);
+ }
+ }
+ };
+
+ SecureRandom keyRandom = new SecureRandom()
+ {
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] x = Hex.decode("3036314538303830343630454235324435324234314132373832433138443046");
+
+ int i;
+
+ for (i = 0; i < (bytes.length - x.length); i += x.length)
+ {
+ System.arraycopy(x, 0, bytes, i, x.length);
+ }
+
+ if (i > bytes.length)
+ {
+ System.arraycopy(x, 0, bytes, i - x.length, bytes.length - (i - x.length));
+ }
+ else
+ {
+ System.arraycopy(x, 0, bytes, i, bytes.length - i);
+ }
+ }
+ };
+
+ BigInteger pValue = new BigInteger("b194036ace14139d36d64295ae6c50fc4b7d65d8b340711366ca93f383653908ee637be428051d86612670ad7b402c09b820fa77d9da29c8111a8496da6c261a53ed252e4d8a69a20376e6addb3bdcd331749a491a184b8fda6d84c31cf05f9119b5ed35246ea4562d85928ba1136a8d0e5a7e5c764ba8902029a1336c631a1d", 16);
+ BigInteger qValue = new BigInteger("96120477df0f3896628e6f4a88d83c93204c210ff262bccb7dae450355125259", 16);
+
+ public TestResult perform()
+ {
+ BigInteger r = new BigInteger("169fdb2dc09f690b71332432bfec806042e258fa9a21dafe73c6abfbc71407d9",16);
+ BigInteger s = new BigInteger("9002551808ae40d19f6f31fb67e4563101243cf07cffd5f2f8ff4c537b0c9866",16);
+ GOST3410ParametersGenerator pGen = new GOST3410ParametersGenerator();
+
+ pGen.init(1024, 2, init_random);
+
+ GOST3410Parameters params = pGen.generateParameters();
+
+ if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
+ {
+ return new SimpleTestResult(false, getName() + ": p or q wrong");
+ }
+
+ GOST3410KeyPairGenerator GOST3410KeyGen = new GOST3410KeyPairGenerator();
+ GOST3410KeyGenerationParameters genParam = new GOST3410KeyGenerationParameters(keyRandom, params);
+
+ GOST3410KeyGen.init(genParam);
+
+ AsymmetricCipherKeyPair pair = GOST3410KeyGen.generateKeyPair();
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
+
+ GOST3410Signer GOST3410 = new GOST3410Signer();
+
+ GOST3410.init(true, param);
+
+ BigInteger[] sig = GOST3410.generateSignature(hashmessage);
+
+ if (!r.equals(sig[0]))
+ {
+ return new SimpleTestResult(false, getName()
+ + ": r component wrong." + System.getProperty("line.separator")
+ + " expecting: " + r.toString(16) + System.getProperty("line.separator")
+ + " got : " + sig[0].toString(16));
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ return new SimpleTestResult(false, getName()
+ + ": s component wrong." + System.getProperty("line.separator")
+ + " expecting: " + s.toString(16) + System.getProperty("line.separator")
+ + " got : " + sig[1].toString(16));
+ }
+
+ GOST3410.init(false, pair.getPublic());
+
+ if (GOST3410.verifySignature(hashmessage, sig[0], sig[1]))
+ {
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+ else
+ {
+ return new SimpleTestResult(false, getName() + ": verification fails");
+ }
+ }
+ }
+
+ Test tests[] =
+ {
+ new GOST3410_TEST1_512(),
+ new GOST3410_TEST2_512(),
+// new GOST3410_TEST1_1024(),
+// new GOST3410_TEST2_1024(),
+// new GOST3410_AParam(),
+// new GOST3410_BParam(),
+// new GOST3410_CParam(),
+// new GOST3410_DParam(),
+// new GOST3410_AExParam(),
+// new GOST3410_BExParam(),
+// new GOST3410_CExParam()
+ };
+
+ public String getName()
+ {
+ return "GOST3410";
+ }
+
+ public TestResult perform()
+ {
+ for (int i = 0; i != tests.length; i++)
+ {
+ TestResult result = tests[i].perform();
+
+ if (!result.isSuccessful())
+ {
+ return result;
+ }
+ }
+
+ return new SimpleTestResult(true, "GOST3410: Okay");
+ }
+
+ public static void main(
+ String[] args)
+ {
+ GOST3410Test test = new GOST3410Test();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/GOST3411DigestTest.java b/core/src/test/java/org/spongycastle/crypto/test/GOST3411DigestTest.java
new file mode 100644
index 00000000..b3121e82
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/GOST3411DigestTest.java
@@ -0,0 +1,74 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.GOST3411Digest;
+import org.spongycastle.crypto.generators.PKCS5S1ParametersGenerator;
+import org.spongycastle.crypto.macs.HMac;
+import org.spongycastle.crypto.params.KeyParameter;
+
+public class GOST3411DigestTest
+ extends DigestTest
+{
+ private static final String[] messages =
+ {
+ "",
+ "This is message, length=32 bytes",
+ "Suppose the original message has length = 50 bytes",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+ };
+
+// If S-box = D-A (see: digest/GOST3411Digest.java; function: E(byte[] in, byte[] key); string: CipherParameters param = new GOST28147Parameters(key,"D-A");)
+ private static final String[] digests =
+ {
+ "981e5f3ca30c841487830f84fb433e13ac1101569b9c13584ac483234cd656c0",
+ "2cefc2f7b7bdc514e18ea57fa74ff357e7fa17d652c75f69cb1be7893ede48eb",
+ "c3730c5cbccacf915ac292676f21e8bd4ef75331d9405e5f1a61dc3130a65011",
+ "73b70a39497de53a6e08c67b6d4db853540f03e9389299d9b0156ef7e85d0f61"
+ };
+
+// If S-box = D-Test (see: digest/GOST3411Digest.java; function:E(byte[] in, byte[] key); string: CipherParameters param = new GOST28147Parameters(key,"D-Test");)
+// private static final String[] digests =
+// {
+// "ce85b99cc46752fffee35cab9a7b0278abb4c2d2055cff685af4912c49490f8d",
+// "b1c466d37519b82e8319819ff32595e047a28cb6f83eff1c6916a815a637fffa",
+// "471aba57a60a770d3a76130635c1fbea4ef14de51f78b4ae57dd893b62f55208",
+// "95c1af627c356496d80274330b2cff6a10c67b5f597087202f94d06d2338cf8e"
+// };
+
+ // 1 million 'a'
+ static private String million_a_digest = "8693287aa62f9478f7cb312ec0866b6c4e4a0f11160441e8f4ffcd2715dd554f";
+
+ GOST3411DigestTest()
+ {
+ super(new GOST3411Digest(), messages, digests);
+ }
+
+ public void performTest()
+ {
+ super.performTest();
+
+ millionATest(million_a_digest);
+
+ HMac gMac = new HMac(new GOST3411Digest());
+
+ gMac.init(new KeyParameter(PKCS5S1ParametersGenerator.PKCS5PasswordToUTF8Bytes("1".toCharArray())));
+
+ byte[] data = "fred".getBytes();
+
+ gMac.update(data, 0, data.length);
+ byte[] mac = new byte[gMac.getMacSize()];
+
+ gMac.doFinal(mac, 0);
+ }
+
+ protected Digest cloneDigest(Digest digest)
+ {
+ return new GOST3411Digest((GOST3411Digest)digest);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new GOST3411DigestTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/Grain128Test.java b/core/src/test/java/org/spongycastle/crypto/test/Grain128Test.java
new file mode 100644
index 00000000..7ac877c1
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/Grain128Test.java
@@ -0,0 +1,117 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.StreamCipher;
+import org.spongycastle.crypto.engines.Grain128Engine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * Grain-128 Test
+ */
+public class Grain128Test
+ extends SimpleTest
+{
+
+ String keyStream1 = "f09b7bf7d7f6b5c2de2ffc73ac21397f";
+ String keyStream2 = "afb5babfa8de896b4b9c6acaf7c4fbfd";
+
+ public String getName()
+ {
+ return "Grain-128";
+ }
+
+ public void performTest()
+ {
+ Grain128Test1(new ParametersWithIV(new KeyParameter(Hex
+ .decode("00000000000000000000000000000000")), Hex
+ .decode("000000000000000000000000")));
+ Grain128Test2(new ParametersWithIV(new KeyParameter(Hex
+ .decode("0123456789abcdef123456789abcdef0")), Hex
+ .decode("0123456789abcdef12345678")));
+ Grain128Test3(new ParametersWithIV(new KeyParameter(Hex
+ .decode("0123456789abcdef123456789abcdef0")), Hex
+ .decode("0123456789abcdef12345678")));
+ }
+
+ private void Grain128Test1(CipherParameters params)
+ {
+ StreamCipher grain = new Grain128Engine();
+ byte[] in = new byte[16];
+ byte[] out = new byte[16];
+
+ grain.init(true, params);
+
+ grain.processBytes(in, 0, in.length, out, 0);
+
+ if (!areEqual(out, Hex.decode(keyStream1)))
+ {
+ mismatch("Keystream 1", keyStream1, out);
+ }
+
+ grain.reset();
+
+ grain.processBytes(in, 0, in.length, out, 0);
+
+ if (!areEqual(out, Hex.decode(keyStream1)))
+ {
+ mismatch("Keystream 1", keyStream1, out);
+ }
+ }
+
+ private void Grain128Test2(CipherParameters params)
+ {
+ StreamCipher grain = new Grain128Engine();
+ byte[] in = new byte[16];
+ byte[] out = new byte[16];
+
+ grain.init(true, params);
+
+ grain.processBytes(in, 0, in.length, out, 0);
+
+ if (!areEqual(out, Hex.decode(keyStream2)))
+ {
+ mismatch("Keystream 2", keyStream2, out);
+ }
+
+ grain.reset();
+
+ grain.processBytes(in, 0, in.length, out, 0);
+
+ if (!areEqual(out, Hex.decode(keyStream2)))
+ {
+ mismatch("Keystream 2", keyStream2, out);
+ }
+ }
+
+ private void Grain128Test3(CipherParameters params)
+ {
+ StreamCipher grain = new Grain128Engine();
+ byte[] in = "Encrypt me!".getBytes();
+ byte[] cipher = new byte[in.length];
+ byte[] clear = new byte[in.length];
+
+ grain.init(true, params);
+
+ grain.processBytes(in, 0, in.length, cipher, 0);
+ grain.reset();
+ grain.processBytes(cipher, 0, cipher.length, clear, 0);
+
+ if (!areEqual(in, clear))
+ {
+ mismatch("Test 3", new String(Hex.encode(in)), clear);
+ }
+ }
+
+ private void mismatch(String name, String expected, byte[] found)
+ {
+ fail("mismatch on " + name, expected, new String(Hex.encode(found)));
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new Grain128Test());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/Grainv1Test.java b/core/src/test/java/org/spongycastle/crypto/test/Grainv1Test.java
new file mode 100644
index 00000000..a9847d0e
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/Grainv1Test.java
@@ -0,0 +1,140 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.StreamCipher;
+import org.spongycastle.crypto.engines.Grainv1Engine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * Grain v1 Test
+ */
+public class Grainv1Test
+ extends SimpleTest
+{
+
+ String keyStream1 = "dee931cf1662a72f77d0";
+ String keyStream2 = "7f362bd3f7abae203664";
+ String keyStream4 = "017D13ECB20AE0C9ACF784CB06525F72"
+ + "CE6D52BEBB948F124668C35064559024"
+ + "49EEA505C19F3EE4D052C3D19DA9C4D1"
+ + "B92DBC7F07AFEA6A3D845DE60D8471FD";
+
+ public String getName()
+ {
+ return "Grain v1";
+ }
+
+ public void performTest()
+ {
+ Grainv1Test1(new ParametersWithIV(new KeyParameter(Hex
+ .decode("00000000000000000000")), Hex
+ .decode("0000000000000000")));
+ Grainv1Test2(new ParametersWithIV(new KeyParameter(Hex
+ .decode("0123456789abcdef1234")), Hex
+ .decode("0123456789abcdef")));
+ Grainv1Test3(new ParametersWithIV(new KeyParameter(Hex
+ .decode("0123456789abcdef1234")), Hex
+ .decode("0123456789abcdef")));
+ Grainv1Test4(new ParametersWithIV(new KeyParameter(Hex
+ .decode("0F62B5085BAE0154A7FA")), Hex
+ .decode("288FF65DC42B92F9")));
+ }
+
+ private void Grainv1Test1(CipherParameters params)
+ {
+ StreamCipher grain = new Grainv1Engine();
+ byte[] in = new byte[10];
+ byte[] out = new byte[10];
+
+ grain.init(true, params);
+
+ grain.processBytes(in, 0, in.length, out, 0);
+
+ if (!areEqual(out, Hex.decode(keyStream1)))
+ {
+ mismatch("Keystream 1", keyStream1, out);
+ }
+
+ grain.reset();
+
+ grain.processBytes(in, 0, in.length, out, 0);
+
+ if (!areEqual(out, Hex.decode(keyStream1)))
+ {
+ mismatch("Keystream 1", keyStream1, out);
+ }
+ }
+
+ private void Grainv1Test2(CipherParameters params)
+ {
+ StreamCipher grain = new Grainv1Engine();
+ byte[] in = new byte[10];
+ byte[] out = new byte[10];
+
+ grain.init(true, params);
+
+ grain.processBytes(in, 0, in.length, out, 0);
+
+ if (!areEqual(out, Hex.decode(keyStream2)))
+ {
+ mismatch("Keystream 2", keyStream2, out);
+ }
+
+ grain.reset();
+
+ grain.processBytes(in, 0, in.length, out, 0);
+
+ if (!areEqual(out, Hex.decode(keyStream2)))
+ {
+ mismatch("Keystream 2", keyStream2, out);
+ }
+ }
+
+ private void Grainv1Test3(CipherParameters params)
+ {
+ StreamCipher grain = new Grainv1Engine();
+ byte[] in = "Encrypt me!".getBytes();
+ byte[] cipher = new byte[in.length];
+ byte[] clear = new byte[in.length];
+
+ grain.init(true, params);
+
+ grain.processBytes(in, 0, in.length, cipher, 0);
+ grain.reset();
+ grain.processBytes(cipher, 0, cipher.length, clear, 0);
+
+ if (!areEqual(in, clear))
+ {
+ mismatch("Test 3", new String(Hex.encode(in)), clear);
+ }
+ }
+
+ private void Grainv1Test4(CipherParameters params)
+ {
+ StreamCipher grain = new Grainv1Engine();
+ byte[] in = new byte[keyStream4.length() / 2];
+ byte[] out = new byte[in.length];
+
+ grain.init(true, params);
+
+ grain.processBytes(in, 0, in.length, out, 0);
+
+ if (!areEqual(out, Hex.decode(keyStream4)))
+ {
+ mismatch("Keystream 4", keyStream4, out);
+ }
+ }
+
+ private void mismatch(String name, String expected, byte[] found)
+ {
+ fail("mismatch on " + name, expected, new String(Hex.encode(found)));
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new Grainv1Test());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/HCFamilyTest.java b/core/src/test/java/org/spongycastle/crypto/test/HCFamilyTest.java
new file mode 100644
index 00000000..1032c443
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/HCFamilyTest.java
@@ -0,0 +1,192 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.StreamCipher;
+import org.spongycastle.crypto.engines.HC128Engine;
+import org.spongycastle.crypto.engines.HC256Engine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * HC-128 and HC-256 Tests. Based on the test vectors in the official reference
+ * papers, respectively:
+ * <pre>
+ * http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc128_p3.pdf
+ * http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc256_p3.pdf
+ * </pre>
+ * See HCFamilyVecTest for a more exhaustive test based on the ecrypt vectors.
+ */
+public class HCFamilyTest
+ extends SimpleTest
+{
+ private static final byte[] MSG = new byte[64];
+
+ private static String[][] HC128_VerifiedTest =
+ {
+ {
+ "Set 2, vector# 0",
+ "00000000000000000000000000000000",
+ "00000000000000000000000000000000",
+ "82001573A003FD3B7FD72FFB0EAF63AA" +
+ "C62F12DEB629DCA72785A66268EC758B" +
+ "1EDB36900560898178E0AD009ABF1F49" +
+ "1330DC1C246E3D6CB264F6900271D59C"
+ },
+ {
+ "Set 6, vector# 0",
+ "0053A6F94C9FF24598EB3E91E4378ADD",
+ "0D74DB42A91077DE45AC137AE148AF16",
+ "2E1ED12A8551C05AF41FF39D8F9DF933" +
+ "122B5235D48FC2A6F20037E69BDBBCE8" +
+ "05782EFC16C455A4B3FF06142317535E" +
+ "F876104C32445138CB26EBC2F88A684C"
+ },
+ {
+ "Set 6, vector# 1",
+ "0558ABFE51A4F74A9DF04396E93C8FE2",
+ "167DE44BB21980E74EB51C83EA51B81F",
+ "4F864BF3C96D0363B1903F0739189138" +
+ "F6ED2BC0AF583FEEA0CEA66BA7E06E63" +
+ "FB28BF8B3CA0031D24ABB511C57DD17B" +
+ "FC2861C32400072CB680DF2E58A5CECC"
+ },
+ {
+ "Set 6, vector# 2",
+ "0A5DB00356A9FC4FA2F5489BEE4194E7",
+ "1F86ED54BB2289F057BE258CF35AC128",
+ "82168AB0023B79AAF1E6B4D823855E14" +
+ "A7084378036A951B1CFEF35173875ED8" +
+ "6CB66AB8410491A08582BE40080C3102" +
+ "193BA567F9E95D096C3CC60927DD7901"
+ },
+ {
+ "Set 6, vector# 3",
+ "0F62B5085BAE0154A7FA4DA0F34699EC",
+ "288FF65DC42B92F960C72E95FC63CA31",
+ "1CD8AEDDFE52E217E835D0B7E84E2922" +
+ "D04B1ADBCA53C4522B1AA604C42856A9" +
+ "0AF83E2614BCE65C0AECABDD8975B557" +
+ "00D6A26D52FFF0888DA38F1DE20B77B7"
+ }
+ };
+
+ private static String[][] HC256_VerifiedTest =
+ {
+ {
+ "Set 2, vector# 0",
+ "00000000000000000000000000000000",
+ "00000000000000000000000000000000",
+ "5B078985D8F6F30D42C5C02FA6B67951" +
+ "53F06534801F89F24E74248B720B4818" +
+ "CD9227ECEBCF4DBF8DBF6977E4AE14FA" +
+ "E8504C7BC8A9F3EA6C0106F5327E6981"
+ },
+ {
+ "Set 2, vector# 9",
+ "09090909090909090909090909090909",
+ "00000000000000000000000000000000",
+ "F5C2926651AEED9AF1A9C2F04C03D081" +
+ "2145B56AEA46EB283A25A4C9E3D8BEB4" +
+ "821B418F06F2B9DCDF1A85AB8C02CD14" +
+ "62E1BBCAEC9AB0E99AA6AFF918BA627C"
+ },
+ {
+ "Set 2, vector#135",
+ "87878787878787878787878787878787",
+ "00000000000000000000000000000000",
+ "CEC0C3852E3B98233EBCB975C10B1191" +
+ "3C69F2275EB97A1402EDF16C6FBE19BE" +
+ "79D65360445BCB63676E6553B609A065" +
+ "0155C3B22DD1975AC0F3F65063A2E16E"
+ },
+ {
+ "Set 6, vector# 0",
+ "0053A6F94C9FF24598EB3E91E4378ADD" +
+ "3083D6297CCF2275C81B6EC11467BA0D",
+ "0D74DB42A91077DE45AC137AE148AF16" +
+ "7DE44BB21980E74EB51C83EA51B81F86",
+ "23D9E70A45EB0127884D66D9F6F23C01" +
+ "D1F88AFD629270127247256C1FFF91E9" +
+ "1A797BD98ADD23AE15BEE6EEA3CEFDBF" +
+ "A3ED6D22D9C4F459DB10C40CDF4F4DFF"
+ },
+ {
+ "Set 6, vector# 1",
+ "0558ABFE51A4F74A9DF04396E93C8FE2" +
+ "3588DB2E81D4277ACD2073C6196CBF12",
+ "167DE44BB21980E74EB51C83EA51B81F" +
+ "86ED54BB2289F057BE258CF35AC1288F",
+ "C44B5262F2EAD9C018213127686DB742" +
+ "A72D3F2D61D18F0F4E7DE5B4F7ADABE0" +
+ "7E0C82033B139F02BAACB4E2F2D0BE30" +
+ "110C3A8A2B621523756692877C905DD0"
+ },
+ {
+ "Set 6, vector# 2",
+ "0A5DB00356A9FC4FA2F5489BEE4194E7" +
+ "3A8DE03386D92C7FD22578CB1E71C417",
+ "1F86ED54BB2289F057BE258CF35AC128" +
+ "8FF65DC42B92F960C72E95FC63CA3198",
+ "9D13AA06122F4F03AE60D507701F1ED0" +
+ "63D7530FF35EE76CAEDCBFB01D8A239E" +
+ "FA4A44B272DE9B4092E2AD56E87C3A60" +
+ "89F5A074D1F6E5B8FC6FABEE0C936F06"
+ },
+ {
+ "Set 6, vector# 3",
+ "0F62B5085BAE0154A7FA4DA0F34699EC" +
+ "3F92E5388BDE3184D72A7DD02376C91C",
+ "288FF65DC42B92F960C72E95FC63CA31" +
+ "98FF66CD349B0269D0379E056CD33AA1",
+ "C8632038DA61679C4685288B37D3E232" +
+ "7BC2D28C266B041FE0CA0D3CFEED8FD5" +
+ "753259BAB757168F85EA96ADABD823CA" +
+ "4684E918423E091565713FEDDE2CCFE0"
+ }
+ };
+
+ public String getName()
+ {
+ return "HC-128 and HC-256";
+ }
+
+ public void performTest()
+ {
+ StreamCipher hc = new HC256Engine();
+
+ for (int i = 0; i != HC256_VerifiedTest.length; i++)
+ {
+ String[] test = HC256_VerifiedTest[i];
+ HCTest(hc, "HC-256 - " + test[0], Hex.decode(test[1]), Hex.decode(test[2]), Hex.decode(test[3]));
+ }
+
+ hc = new HC128Engine();
+
+ for (int i = 0; i != HC128_VerifiedTest.length; i++)
+ {
+ String[] test = HC128_VerifiedTest[i];
+ HCTest(hc, "HC-128 - " + test[0], Hex.decode(test[1]), Hex.decode(test[2]), Hex.decode(test[3]));
+ }
+ }
+
+ private void HCTest(StreamCipher hc, String test, byte[] key, byte[] IV, byte[] expected)
+ {
+ KeyParameter kp = new KeyParameter(key);
+ ParametersWithIV ivp = new ParametersWithIV(kp, IV);
+
+ hc.init(true, ivp);
+ for (int i = 0; i < 64; i++)
+ {
+ if (hc.returnByte(MSG[i]) != expected[i])
+ {
+ fail(test + " failure at byte " + i);
+ }
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new HCFamilyTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/HCFamilyVecTest.java b/core/src/test/java/org/spongycastle/crypto/test/HCFamilyVecTest.java
new file mode 100644
index 00000000..a3c954f8
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/HCFamilyVecTest.java
@@ -0,0 +1,199 @@
+package org.spongycastle.crypto.test;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.StreamCipher;
+import org.spongycastle.crypto.engines.HC128Engine;
+import org.spongycastle.crypto.engines.HC256Engine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * HC-128 and HC-256 Tests. Based on the test vectors in the official reference
+ * papers, respectively:
+ *
+ * http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc128_p3.pdf
+ * http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc256_p3.pdf
+ */
+public class HCFamilyVecTest
+ extends SimpleTest
+{
+ private static class PeekableLineReader extends BufferedReader
+ {
+ public PeekableLineReader(Reader r) throws IOException
+ {
+ super(r);
+
+ peek = super.readLine();
+ }
+
+ public String peekLine()
+ {
+ return peek;
+ }
+
+ public String readLine() throws IOException
+ {
+ String tmp = peek;
+ peek = super.readLine();
+ return tmp;
+ }
+
+ private String peek;
+ }
+
+ public String getName()
+ {
+ return "HC-128 and HC-256 (ecrypt)";
+ }
+
+ public void performTest() throws Exception
+ {
+ runTests(new HC128Engine(), "ecrypt_HC-128.txt");
+ runTests(new HC256Engine(), "ecrypt_HC-256_128K_128IV.txt");
+ runTests(new HC256Engine(), "ecrypt_HC-256_256K_128IV.txt");
+ runTests(new HC256Engine(), "ecrypt_HC-256_128K_256IV.txt");
+ runTests(new HC256Engine(), "ecrypt_HC-256_256K_256IV.txt");
+ }
+
+ private void runTests(StreamCipher hc, String fileName) throws IOException
+ {
+ Reader resource = new InputStreamReader(getClass().getResourceAsStream(fileName));
+ PeekableLineReader r = new PeekableLineReader(resource);
+ runAllVectors(hc, fileName, r);
+ }
+
+ private void runAllVectors(StreamCipher hc, String fileName, PeekableLineReader r)
+ throws IOException
+ {
+ for (;;)
+ {
+ String line = r.readLine();
+ if (line == null)
+ {
+ break;
+ }
+
+ line = line.trim();
+
+ if (line.startsWith("Set "))
+ {
+ runVector(hc, fileName, r, dellChar(line, ':'));
+ }
+ }
+ }
+
+ private String dellChar(String s, char c)
+ {
+ StringBuffer b = new StringBuffer();
+
+ for (int i = 0; i != s.length(); i++)
+ {
+ if (s.charAt(i) != c)
+ {
+ b.append(s.charAt(i));
+ }
+ }
+
+ return b.toString();
+ }
+
+ private void runVector(StreamCipher hc, String fileName, PeekableLineReader r, String vectorName)
+ throws IOException
+ {
+// System.out.println(fileName + " => " + vectorName);
+ String hexKey = readBlock(r);
+ String hexIV = readBlock(r);
+
+ CipherParameters cp = new KeyParameter(Hex.decode(hexKey));
+ cp = new ParametersWithIV(cp, Hex.decode(hexIV));
+ hc.init(true, cp);
+
+ byte[] input = new byte[64];
+ byte[] output = new byte[64];
+ byte[] digest = new byte[64];
+ int pos = 0;
+
+ for (;;)
+ {
+ String line1 = r.peekLine().trim();
+ int equalsPos = line1.indexOf('=');
+ String lead = line1.substring(0, equalsPos - 1);
+
+ String hexData = readBlock(r);
+ byte[] data = Hex.decode(hexData);
+
+ if (lead.equals("xor-digest"))
+ {
+ if (!Arrays.areEqual(data, digest))
+ {
+ fail("Failed in " + fileName + " for test vector: " + vectorName + " at " + lead);
+// System.out.println(fileName + " => " + vectorName + " failed at " + lead); return;
+ }
+ break;
+ }
+
+ int posA = lead.indexOf('[');
+ int posB = lead.indexOf("..");
+ int posC = lead.indexOf(']');
+ int start = Integer.parseInt(lead.substring(posA + 1, posB));
+ int end = Integer.parseInt(lead.substring(posB + 2, posC));
+
+ if (start % 64 != 0 || (end - start != 63))
+ {
+ throw new IllegalStateException(vectorName + ": " + lead + " not on 64 byte boundaries");
+ }
+
+ while (pos < end)
+ {
+ hc.processBytes(input, 0, input.length, output, 0);
+ xor(digest, output);
+ pos += 64;
+ }
+
+ if (!Arrays.areEqual(data, output))
+ {
+ fail("Failed in " + fileName + " for test vector: " + vectorName + " at " + lead);
+// System.out.println(fileName + " => " + vectorName + " failed at " + lead); return;
+ }
+ }
+ }
+
+ private static String readBlock(PeekableLineReader r) throws IOException
+ {
+ String first = r.readLine().trim();
+ String result = first.substring(first.lastIndexOf(' ') + 1);
+
+ for (;;)
+ {
+ String peek = r.peekLine().trim();
+ if (peek.length() < 1 || peek.indexOf('=') >= 0)
+ {
+ break;
+ }
+ result += r.readLine().trim();
+ }
+
+ return result;
+ }
+
+ private static void xor(byte[] digest, byte[] block)
+ {
+ for (int i = 0; i < digest.length; ++i)
+ {
+ digest[i] ^= block[i];
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new HCFamilyVecTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/HKDFGeneratorTest.java b/core/src/test/java/org/spongycastle/crypto/test/HKDFGeneratorTest.java
new file mode 100644
index 00000000..00564eb6
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/HKDFGeneratorTest.java
@@ -0,0 +1,304 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.generators.HKDFBytesGenerator;
+import org.spongycastle.crypto.params.HKDFParameters;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * HKDF tests - vectors from RFC 5869, + 2 more, 101 and 102
+ */
+public class HKDFGeneratorTest
+ extends SimpleTest
+{
+
+ public HKDFGeneratorTest()
+ {
+ }
+
+ private void compareOKM(int test, byte[] calculatedOKM, byte[] testOKM)
+ {
+
+ if (!areEqual(calculatedOKM, testOKM))
+ {
+ fail("HKDF failed generator test " + test);
+ }
+ }
+
+ public void performTest()
+ {
+ {
+ // === A.1. Test Case 1 - Basic test case with SHA-256 ===
+
+ Digest hash = new SHA256Digest();
+ byte[] ikm = Hex
+ .decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
+ byte[] salt = Hex.decode("000102030405060708090a0b0c");
+ byte[] info = Hex.decode("f0f1f2f3f4f5f6f7f8f9");
+ int l = 42;
+ byte[] okm = new byte[l];
+
+ HKDFParameters params = new HKDFParameters(ikm, salt, info);
+
+ HKDFBytesGenerator hkdf = new HKDFBytesGenerator(hash);
+ hkdf.init(params);
+ hkdf.generateBytes(okm, 0, l);
+
+ compareOKM(1, okm, Hex.decode(
+ "3cb25f25faacd57a90434f64d0362f2a" +
+ "2d2d0a90cf1a5a4c5db02d56ecc4c5bf" +
+ "34007208d5b887185865"));
+ }
+
+ // === A.2. Test Case 2 - Test with SHA-256 and longer inputs/outputs
+ // ===
+ {
+ Digest hash = new SHA256Digest();
+ byte[] ikm = Hex.decode("000102030405060708090a0b0c0d0e0f"
+ + "101112131415161718191a1b1c1d1e1f"
+ + "202122232425262728292a2b2c2d2e2f"
+ + "303132333435363738393a3b3c3d3e3f"
+ + "404142434445464748494a4b4c4d4e4f");
+ byte[] salt = Hex.decode("606162636465666768696a6b6c6d6e6f"
+ + "707172737475767778797a7b7c7d7e7f"
+ + "808182838485868788898a8b8c8d8e8f"
+ + "909192939495969798999a9b9c9d9e9f"
+ + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf");
+ byte[] info = Hex.decode("b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
+ + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
+ + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
+ + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
+ + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
+ int l = 82;
+ byte[] okm = new byte[l];
+
+ HKDFParameters params = new HKDFParameters(ikm, salt, info);
+
+ HKDFBytesGenerator hkdf = new HKDFBytesGenerator(hash);
+ hkdf.init(params);
+ hkdf.generateBytes(okm, 0, l);
+
+ compareOKM(2, okm, Hex.decode(
+ "b11e398dc80327a1c8e7f78c596a4934" +
+ "4f012eda2d4efad8a050cc4c19afa97c" +
+ "59045a99cac7827271cb41c65e590e09" +
+ "da3275600c2f09b8367793a9aca3db71" +
+ "cc30c58179ec3e87c14c01d5c1f3434f" +
+ "1d87"));
+ }
+
+ {
+ // === A.3. Test Case 3 - Test with SHA-256 and zero-length
+ // salt/info ===
+
+ // setting salt to an empty byte array means that the salt is set to
+ // HashLen zero valued bytes
+ // setting info to null generates an empty byte array as info
+ // structure
+
+ Digest hash = new SHA256Digest();
+ byte[] ikm = Hex
+ .decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
+ byte[] salt = new byte[0];
+ byte[] info = null;
+ int l = 42;
+ byte[] okm = new byte[l];
+
+ HKDFParameters params = new HKDFParameters(ikm, salt, info);
+
+ HKDFBytesGenerator hkdf = new HKDFBytesGenerator(hash);
+ hkdf.init(params);
+ hkdf.generateBytes(okm, 0, l);
+
+ compareOKM(3, okm, Hex.decode(
+ "8da4e775a563c18f715f802a063c5a31" +
+ "b8a11f5c5ee1879ec3454e5f3c738d2d" +
+ "9d201395faa4b61a96c8"));
+ }
+
+ {
+ // === A.4. Test Case 4 - Basic test case with SHA-1 ===
+
+ Digest hash = new SHA1Digest();
+ byte[] ikm = Hex.decode("0b0b0b0b0b0b0b0b0b0b0b");
+ byte[] salt = Hex.decode("000102030405060708090a0b0c");
+ byte[] info = Hex.decode("f0f1f2f3f4f5f6f7f8f9");
+ int l = 42;
+ byte[] okm = new byte[l];
+
+ HKDFParameters params = new HKDFParameters(ikm, salt, info);
+
+ HKDFBytesGenerator hkdf = new HKDFBytesGenerator(hash);
+ hkdf.init(params);
+ hkdf.generateBytes(okm, 0, l);
+
+ compareOKM(4, okm, Hex.decode(
+ "085a01ea1b10f36933068b56efa5ad81" +
+ "a4f14b822f5b091568a9cdd4f155fda2" +
+ "c22e422478d305f3f896"));
+ }
+
+ // === A.5. Test Case 5 - Test with SHA-1 and longer inputs/outputs ===
+ {
+ Digest hash = new SHA1Digest();
+ byte[] ikm = Hex.decode("000102030405060708090a0b0c0d0e0f"
+ + "101112131415161718191a1b1c1d1e1f"
+ + "202122232425262728292a2b2c2d2e2f"
+ + "303132333435363738393a3b3c3d3e3f"
+ + "404142434445464748494a4b4c4d4e4f");
+ byte[] salt = Hex.decode("606162636465666768696a6b6c6d6e6f"
+ + "707172737475767778797a7b7c7d7e7f"
+ + "808182838485868788898a8b8c8d8e8f"
+ + "909192939495969798999a9b9c9d9e9f"
+ + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf");
+ byte[] info = Hex.decode("b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
+ + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
+ + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
+ + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
+ + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
+ int l = 82;
+ byte[] okm = new byte[l];
+
+ HKDFParameters params = new HKDFParameters(ikm, salt, info);
+
+ HKDFBytesGenerator hkdf = new HKDFBytesGenerator(hash);
+ hkdf.init(params);
+ hkdf.generateBytes(okm, 0, l);
+
+ compareOKM(5, okm, Hex.decode(
+ "0bd770a74d1160f7c9f12cd5912a06eb" +
+ "ff6adcae899d92191fe4305673ba2ffe" +
+ "8fa3f1a4e5ad79f3f334b3b202b2173c" +
+ "486ea37ce3d397ed034c7f9dfeb15c5e" +
+ "927336d0441f4c4300e2cff0d0900b52" +
+ "d3b4"));
+ }
+
+ {
+ // === A.6. Test Case 6 - Test with SHA-1 and zero-length salt/info
+ // ===
+
+ // setting salt to null should generate a new salt of HashLen zero
+ // valued bytes
+
+ Digest hash = new SHA1Digest();
+ byte[] ikm = Hex
+ .decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
+ byte[] salt = null;
+ byte[] info = new byte[0];
+ int l = 42;
+ byte[] okm = new byte[l];
+
+ HKDFParameters params = new HKDFParameters(ikm, salt, info);
+
+ HKDFBytesGenerator hkdf = new HKDFBytesGenerator(hash);
+ hkdf.init(params);
+ hkdf.generateBytes(okm, 0, l);
+
+ compareOKM(6, okm, Hex.decode(
+ "0ac1af7002b3d761d1e55298da9d0506" +
+ "b9ae52057220a306e07b6b87e8df21d0" +
+ "ea00033de03984d34918"));
+ }
+
+ {
+ // === A.7. Test Case 7 - Test with SHA-1, salt not provided,
+ // zero-length info ===
+ // (salt defaults to HashLen zero octets)
+
+ // this test is identical to test 6 in all ways bar the IKM value
+
+ Digest hash = new SHA1Digest();
+ byte[] ikm = Hex
+ .decode("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c");
+ byte[] salt = null;
+ byte[] info = new byte[0];
+ int l = 42;
+ byte[] okm = new byte[l];
+
+ HKDFParameters params = new HKDFParameters(ikm, salt, info);
+
+ HKDFBytesGenerator hkdf = new HKDFBytesGenerator(hash);
+ hkdf.init(params);
+ hkdf.generateBytes(okm, 0, l);
+
+ compareOKM(7, okm, Hex.decode(
+ "2c91117204d745f3500d636a62f64f0a" +
+ "b3bae548aa53d423b0d1f27ebba6f5e5" +
+ "673a081d70cce7acfc48"));
+ }
+
+ {
+ // === A.101. Additional Test Case - Test with SHA-1, skipping extract
+ // zero-length info ===
+ // (salt defaults to HashLen zero octets)
+
+ // this test is identical to test 7 in all ways bar the IKM value
+ // which is set to the PRK value
+
+ Digest hash = new SHA1Digest();
+ byte[] ikm = Hex
+ .decode("2adccada18779e7c2077ad2eb19d3f3e731385dd");
+ byte[] info = new byte[0];
+ int l = 42;
+ byte[] okm = new byte[l];
+
+ HKDFParameters params = HKDFParameters.skipExtractParameters(ikm, info);
+
+ HKDFBytesGenerator hkdf = new HKDFBytesGenerator(hash);
+ hkdf.init(params);
+ hkdf.generateBytes(okm, 0, l);
+
+ compareOKM(101, okm, Hex.decode(
+ "2c91117204d745f3500d636a62f64f0a" +
+ "b3bae548aa53d423b0d1f27ebba6f5e5" +
+ "673a081d70cce7acfc48"));
+ }
+
+ // === A.102. Additional Test Case - Test with SHA-1, maximum output ===
+ // (salt defaults to HashLen zero octets)
+
+ // this test is identical to test 7 in all ways bar the IKM value
+
+ Digest hash = new SHA1Digest();
+ byte[] ikm = Hex
+ .decode("2adccada18779e7c2077ad2eb19d3f3e731385dd");
+ byte[] info = new byte[0];
+ int l = 255 * hash.getDigestSize();
+ byte[] okm = new byte[l];
+
+ HKDFParameters params = HKDFParameters.skipExtractParameters(ikm, info);
+
+ HKDFBytesGenerator hkdf = new HKDFBytesGenerator(hash);
+ hkdf.init(params);
+ hkdf.generateBytes(okm, 0, l);
+
+ int zeros = 0;
+ for (int i = 0; i < hash.getDigestSize(); i++)
+ {
+ if (okm[i] == 0)
+ {
+ zeros++;
+ }
+ }
+
+ if (zeros == hash.getDigestSize())
+ {
+ fail("HKDF failed generator test " + 102);
+ }
+ }
+
+ public String getName()
+ {
+ return "HKDF";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new HKDFGeneratorTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/HashCommitmentTest.java b/core/src/test/java/org/spongycastle/crypto/test/HashCommitmentTest.java
new file mode 100644
index 00000000..d4c1c076
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/HashCommitmentTest.java
@@ -0,0 +1,152 @@
+package org.spongycastle.crypto.test;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.Commitment;
+import org.spongycastle.crypto.Committer;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.commitments.GeneralHashCommitter;
+import org.spongycastle.crypto.commitments.HashCommitter;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class HashCommitmentTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "HashCommitmentTest";
+ }
+
+ public void performBasicTest()
+ throws Exception
+ {
+ byte[] data = Hex.decode("4e6f77206973207468652074696d6520666f7220616c6c20");
+
+ Committer committer = new HashCommitter(new SHA256Digest(), new SecureRandom());
+
+ Commitment c = committer.commit(data);
+
+ committer = new HashCommitter(new SHA256Digest(), new SecureRandom());
+
+ if (!committer.isRevealed(c, data))
+ {
+ fail("commitment failed to validate");
+ }
+
+ committer = new HashCommitter(new SHA1Digest(), new SecureRandom());
+
+ if (committer.isRevealed(c, data))
+ {
+ fail("commitment validated!!");
+ }
+
+ try
+ {
+ committer.isRevealed(c, new byte[data.length + 1]);
+ }
+ catch (Exception e)
+ {
+ if (!e.getMessage().equals("Message and witness secret lengths do not match."))
+ {
+ fail("exception thrown but wrong message");
+ }
+ }
+
+ // SHA1 has a block size of 512 bits, try a message that's too big
+
+ try
+ {
+ c = committer.commit(new byte[33]);
+ }
+ catch (DataLengthException e)
+ {
+ if (!e.getMessage().equals("Message to be committed to too large for digest."))
+ {
+ fail("exception thrown but wrong message");
+ }
+ }
+ }
+
+ public void performGeneralTest()
+ throws Exception
+ {
+ byte[] data = Hex.decode("4e6f77206973207468652074696d6520666f7220616c6c20");
+
+ Committer committer = new GeneralHashCommitter(new SHA256Digest(), new SecureRandom());
+
+ Commitment c = committer.commit(data);
+
+ committer = new GeneralHashCommitter(new SHA256Digest(), new SecureRandom());
+
+ if (!committer.isRevealed(c, data))
+ {
+ fail("general commitment failed to validate");
+ }
+
+ committer = new GeneralHashCommitter(new SHA1Digest(), new SecureRandom());
+
+ if (committer.isRevealed(c, data))
+ {
+ fail("general commitment validated!!");
+ }
+
+ c = committer.commit(data);
+
+ // try and fool it.
+ byte[] s = c.getSecret();
+ byte[] newS = Arrays.copyOfRange(s, 0, s.length - 1);
+ byte[] newData = new byte[data.length + 1];
+
+ newData[0] = s[s.length - 1];
+ System.arraycopy(data, 0, newData, 1, data.length);
+
+ c = new Commitment(newS, c.getCommitment());
+
+ if (committer.isRevealed(c, newData))
+ {
+ fail("general commitment validated!!");
+ }
+
+ try
+ {
+ committer.isRevealed(c, new byte[data.length + 1]);
+ }
+ catch (Exception e)
+ {
+ if (!e.getMessage().equals("Message and witness secret lengths do not match."))
+ {
+ fail("exception thrown but wrong message");
+ }
+ }
+
+ // SHA1 has a block size of 512 bits, try a message that's too big
+
+ try
+ {
+ c = committer.commit(new byte[33]);
+ }
+ catch (DataLengthException e)
+ {
+ if (!e.getMessage().equals("Message to be committed to too large for digest."))
+ {
+ fail("exception thrown but wrong message");
+ }
+ }
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ performBasicTest();
+ performGeneralTest();
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new HashCommitmentTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/IDEATest.java b/core/src/test/java/org/spongycastle/crypto/test/IDEATest.java
new file mode 100644
index 00000000..beb0e489
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/IDEATest.java
@@ -0,0 +1,38 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.engines.IDEAEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ */
+public class IDEATest
+ extends CipherTest
+{
+ static SimpleTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new IDEAEngine(),
+ new KeyParameter(Hex.decode("00112233445566778899AABBCCDDEEFF")),
+ "000102030405060708090a0b0c0d0e0f", "ed732271a7b39f475b4b2b6719f194bf"),
+ new BlockCipherVectorTest(0, new IDEAEngine(),
+ new KeyParameter(Hex.decode("00112233445566778899AABBCCDDEEFF")),
+ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", "b8bc6ed5c899265d2bcfad1fc6d4287d")
+ };
+
+ IDEATest()
+ {
+ super(tests, new IDEAEngine(), new KeyParameter(new byte[32]));
+ }
+
+ public String getName()
+ {
+ return "IDEA";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new IDEATest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/ISAACTest.java b/core/src/test/java/org/spongycastle/crypto/test/ISAACTest.java
new file mode 100644
index 00000000..e2f9f124
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/ISAACTest.java
@@ -0,0 +1,180 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.engines.ISAACEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * ISAAC Test - see http://www.burtleburtle.net/bob/rand/isaacafa.html
+ */
+public class ISAACTest
+ extends SimpleTest
+{
+ byte[] out = Hex.decode(
+ "f650e4c8e448e96d98db2fb4f5fad54f433f1afbedec154ad837048746ca4f9a" +
+ "5de3743e88381097f1d444eb823cedb66a83e1e04a5f6355c744243325890e2e" +
+ "7452e31957161df638a824f3002ed71329f5544951c08d83d78cb99ea0cc74f3" +
+ "8f651659cbc8b7c2f5f71c6912ad6419e5792e1b860536b809b3ce98d45d6d81" +
+ "f3b2612917e38f8529cf72ce349947b0c998f9ffb5e13dae32ae2a2bf7cf814c" +
+ "8ebfa303cf22e0640b923200eca4d58aef53cec4d0f7b37d9c411a2affdf8a80" +
+ "b40e27bcb4d2f97644b89b08f37c71d51a70e7e90bdb9c3060dc5207b3c3f24b" +
+ "d7386806229749b54e232cd091dabc65a70e11018b87437e5781414fcdbc62e2" +
+ "8107c9ff69d2e4ae3b18e752b143b6886f4e077295138769943c3c74afc17a97" +
+ "0fd439636a529b0bd8c58a6aa8bcc22d2db35dfea7a2f4026cb167db538e1f4e" +
+ "7275e2771d3b8e97ecc5dc9115e3a5b90369661430ab93ecac9fe69d7bc76811" +
+ "60eda8da28833522d5295ebc5adb60e7f7e1cdd097166d14b67ec13a210f3925" +
+ "64af0fef0d0286843aea3decb058bafbb8b0ccfcf2b5cc05e3a662d9814bc24c" +
+ "2364a1aa37c0ed052b36505c451e7ec85d2a542fe43d0fbb91c8d92560d4d5f8" +
+ "12a0594b9e8a51dacd49ebdb1b0dcdc1cd57c7f7e63444517ded386f2f36fa86" +
+ "a6d1210133bc405db388d96cdb6dbe96fe29661c13edc0cbcb0eee4a70cc94ae" +
+ "de11ed340606cf9f3a6ce38923d74f4ea37f63ff917bdec2d73f72d40e7e0e67" +
+ "3d77d9a213add9228891b3db01a9bd7056a001e3d51f093dcc033ce35ad0d3b0" +
+ "34105a8c6a123f57bd2e50247364944be89b1a3b21835c4d9f39e2d9d405ded8" +
+ "294d37e5bccaaeed35a124b56708a2bcb00960ba2a98121a4d8fae820bb3263f" +
+ "12595a196a1075890809e49421c171ec884d682514c8009bb0b84e7b03fb88f4" +
+ "28e7cb789388b13bdd2dc1d5848f520a07c28cd168a3935872c9137d127dd430" +
+ "c613f1578c2f0d55f7d3f39f309bfb788406b13746c0a6f53718d59708607f04" +
+ "76904b6d04db4e13cd7411a7b510ce0ebfc7f7ccb83f957afdfef62dc35e4580" +
+ "3ff1e5244112d96c02c9b944d5990dfbe7e265810d9c7e7e826dfa8966f1e0ab" +
+ "30bcc764eadebeaced35e5ee0c571a7de4f3a26af7f58f7badf6bc235d023e65" +
+ "1ed3ff4eec46b0b6d2a93b51e75b41c97e315aeb61119a5a53245b7933f6d7b1" +
+ "cae8deba50fc8194afa92a6dc87c80064188bfcd8bace62e78ffa5685597ec0f" +
+ "b4415f7d08294766ad56764309c36f903dde9f394a0a283c18080c8e080c79ec" +
+ "79ae4c10cb9e15637cdd662f62d31911a4ca0cf15cf824cd3b708f991e16614c" +
+ "b6b9d7665de87abb7229ea81d5b2d75056e6cd21fe1e42d596da2655c2b9aa36" +
+ "b8f6fd4a6a158d1001913fd3af7d1fb80b5e435f90c107576554abda7a68710f" +
+ "82ac484fd7e1c7be95c85eaa94a302f44d3cfbda786b29081010b27582d53d12" +
+ "21e2a51c3d1e9150b059261dd0638e1a31860f0581f2864dff4cfc350451516d" +
+ "bd086f26bc5654c165dfa427a82427f5582e3014b8d2486dc79a17499a1d7745" +
+ "8766bb541e04a7f73d3dff8ad5ec6bf4dbef7d9f36ec0ea31feb2e4f15cfcc5c" +
+ "d8c423fbd0ef3cc9eb244925ba5590c8a5f48ac433c5321c613b67b2479c3a22" +
+ "e21339cc10d210aa931dd7e2ef05ee06b82f2703a385cb2c5d67133c877eb7b4" +
+ "1e3437f75afb43ae53c078f394d904811d96458908063a85e13222281956b1e5" +
+ "31860f132e7b022f21182ca396f703ac46819e2e0d28fe523724d4dca0eabe6b" +
+ "c66699fdc6112fdd19c1e69c04d3658a4b55dd9931907d62f854b5224d678f26" +
+ "22ae0582eafed133e4a51d2184bd6dd6c1a513753f28ee63fb737b1a70a1660e" +
+ "8a8dfaa31be79937f7476978513c1764531ac6bf12c06908001cdb951a4b6a53" +
+ "d067fce512b2cfb69ddb477f740e006639ddf25acc8bfa2df1b20eaf64f2632c" +
+ "9783cdee63bfd4d80084cfe575f4e9e219b48fd06c48ddd87a36af9371865c4c" +
+ "9ce0199d867027d72cb7b77f84ef01da72f5972f040f7074df9afa29c921f94e" +
+ "75c08a3618c1ef9ad649a428c5b719378a30738ad97cd348858129a6239e3b0a" +
+ "bbb8abc480fac4c2ecfcf20bd9d711f9e2a4ef71b5fe87c0be8b06b2aafef5a7" +
+ "9c15db3b0aeb81654389a84a253b1d7a19047c797cdc78a2d20adf0356f55a71" +
+ "3e730fa8fd8650d8959e234eb7546681dad1b22a142a6e858ef4bce668235b9d" +
+ "85a13f8574096ae7a949bea229322d0dd568385882846526403dae086dd1943a" +
+ "e1279bff9e7e4f041c3a4524484525e481d4cc5fe24124c0037464c0bf1bd691" +
+ "26ceb003275ead3ac5bde90826414ff3a30519add7b43abe2ce5d3d588412761" +
+ "97ca2070e5fbb9c7276df0b4308f751f37a97df6c9cd808cfe4cb3803d469303" +
+ "aee19096c0d5d42a4e823ad3f5f9cc3b4286619c9ca45e1c66c97340891aec49" +
+ "45bae606c798f04752649d6cce86fdfc80c6e402d6ec2f2b27c822821fe26ce0" +
+ "92f57ea7de462f4d07497cae5a48755c721502dd6cbe7935836d80039ead7f70" +
+ "9ab3a42f4c8652d632e39273e8fa38601da4f25a0cd6ef8102503f7d8854a0a1" +
+ "9a30c4e88815715305efe29457c4c9252887d96fc1a71e3ce9f841632d0985de" +
+ "d21e796c6fb5ce5602614abfc3c7be2cb54fed6fa617a083c3142d8f6079e4ce" +
+ "ceffc1471d0cb81bdc153e5fe36ef5bbd531161a165b10157aa114ed3f7579b3" +
+ "f7f395f1bc6172c7a86f875e0e6c51b3cdfec2af73c0e762824c2009c5a87748" +
+ "94d401258aba3ffbd32be0608c17eff021e2547e07cffad905340e15f3310c92" +
+ "9d8d190886ba527ff943f672ef73fbf046d95ca5c54cd95b9d855e894bb5af29");
+
+ byte[] outFFFFFFFF = Hex.decode(
+ "de3b3f3c19e0629c1fc8b7836695d523e7804edd86ff7ce9b106f52caebae9d9" +
+ "72f845d49ce17d7da44e49bae954aac0d0b1284b98a88eec1524fb6bc91a16b5" +
+ "1192ac5334131446ac2442de9ff3d5867b9b9148881ee30a6e87dd88e5d1f7cd" +
+ "98db31ff36f70d9850cfefaef42abb00ecc39ed308bf4b8030cdc2b6b7e42f0e" +
+ "908030dd282f96edacc888b3a986e109c129998f89baa1b5da8970b07a6ab012" +
+ "f10264f23c315c9c8e0c164955c68517b6a4f982b2626db70787f869ac6d551b" +
+ "e34931627c7058e965c502e18d2cd370e6db3b70d947d61aa9717cf8394f48c6" +
+ "3c796f3a154950846badb28b70d982f29bc670254e3e5e0f8e36b0a5f6da0a04" +
+ "6b235ed6a42988c012bde74d879fa8eb5d59f5f40ed5e76601c9847b3edb2690");
+
+ byte[] outFFFF0000 = Hex.decode(
+ "26c54b1f8c4e3fc582e9e8180f7aba5380463dcf58b03cbeda0ecc8ba90ccff8" +
+ "5bd50896313d7efed44015faeac6964b241a7fb8a2e37127a7cbea0fd7c020f2" +
+ "406371b87ef5185089504751e5e44352eff63e00e5c28f5dff0616a9a3a00f1f" +
+ "4a1350e3a17be9abddfc2c94571450a0dc4c3c0c7c7f98e80c95f607d50c676a" +
+ "9a3006f9d279a79a4d66b2ab0c52930c9ee84bc09895e70fa041b1a3a2966f11" +
+ "6a47fd09705124b1f5c7ae055e54536e66584b1608f3612d81b72f109a385831" +
+ "121945b207b90ac72437a248f27a121c2801f4153a8699fb047e193f7ba69e1b" +
+ "b117869675d4c963e6070c2ca3d332ce830cb5e3d9ed2eee7faf0acc20fbe154" +
+ "188ae789e95bd5c1f459dbd150aab6eb833170257084bc5d44e9df09f5624f9d" +
+ "afecd0c9340ac8587f8625d343f7efd1cc8abcf7a6f90eabd4e8e2d906278d6e" +
+ "431fcade165c8c467887fbf5c26d341557b064b98c60dd40ab262dc046d69647" +
+ "56f3ddc1a07ae5f87be878b9334fcde40add68d2ca1dc05fb1670f998c7c4607" +
+ "9a6e48bdb330ad8d30b61b5cc8dc156f5733905931949783f89ac396b65aa4b8" +
+ "51f746b53ed8ea66130e1d75e8eab136e60450e3e600226bc8e17d03744ce94c" +
+ "0eec9234fea5f18eef65d81f2f10cfbc0b112b8cde17c32eb33ed81d7356eac3" +
+ "eb1cb9cefa6604c2d707949b6e5a83e60705bf6aae76dcc7d35d68ff149c1ac5" +
+ "424bb4a39e2f496f886637fce3db4ba4ad12c1a32d25e1606f6635ff636486f6" +
+ "714997b45477f38813c02afce4bebf196b813332f0decd567c745f441e736364");
+
+ byte[] out0000FFFF = Hex.decode(
+ "bc31712f2a2f467a5abc737c57ce0f8d49d2f775eb850fc8f856daf19310fee2"+
+ "5bab40e78403c9ef4ccd971418992faf4e85ca643fa6b482f30c4659066158a6"+
+ "5bc3e620ba7ea5c34dd0eac5aabb2cf078d915fd1f8c437ed00423076c10f701"+
+ "eefa7fc7c461aca5db8a87be29d925c4212d4adcfa71ff5b06af15c048aa0dfd"+
+ "f0e645bc09fea200c430a88eb38c466ff358b836f1159656a078f6fc752f6db1"+
+ "6680bb30fc771a6a785bbb2298e947d7b3500e557775962248bedf4e82c16e66"+
+ "f39283ccb95e5399061056a11c4a280f00f7487888199487905273c7aa13012b"+
+ "4849eca626cbf071c782e084f9fded57de92313e5f61a6e81117fb1115eff275"+
+ "66fd5c755bb3b01bba69aeb8f1b1b1cc9709734be31b35bc707d372ba6fe70d1"+
+ "e2c3b0e5e74a7058faff6b11d3a168f19fecc9fcb36b3e6a5f828c01c22ac0c2"+
+ "5da2a3a9eec7e0ebbbf51472e430ed4cf1c7ab57ef9aea511e40250846d260b6"+
+ "17a3fdeba16cf4afaf700144d3296b58b22a3c79ed96f3e2fc8d9e3c660ae153"+
+ "8e0c285ccdc48b59117e80413bd0ad24c6a8d4f133fe1496f14351bb89904fa5"+
+ "e10c4b8d50e0604578389c336a9ab3d292beb90ce640fc028e697cf54e021e2f"+
+ "c0ca3fe0471fde5e5462f221739a74f5a13ae0621fe2a82e752bc294f63de48d"+
+ "e85430af71307a30441b861ab5380e6a6dbe1251c9baa567da14e38e5a0ccddf"+
+ "0127205c38fc3b77065e98101d219246103438d223ec7f8f533d4bb3a3d3407a"+
+ "944910f11e8e5492e86de7a0471250eca32f0838b3db02fffe71898712af3261");
+
+ public String getName()
+ {
+ return "ISAAC";
+ }
+
+ public void performTest()
+ {
+ ISAACEngine engine = new ISAACEngine();
+
+ doTest(engine, Hex.decode("00000000"), out);
+ doTest(engine, Hex.decode("ffffffff"), outFFFFFFFF);
+
+ byte[] k = new byte[256 * 4];
+ for (int i = 0; i != k.length; i++)
+ {
+ k[i] = (byte)((i % 4 == 0 || i % 4 == 1) ? 0xff : 0x00);
+ }
+ doTest(engine, k, outFFFF0000);
+ k = new byte[256 * 4];
+ for (int i = 0; i != k.length; i++)
+ {
+ k[i] = (byte)((i % 4 == 2 || i % 4 == 3) ? 0xff : 0x00);
+ }
+ doTest(engine, k, out0000FFFF);
+ }
+
+ private void doTest(ISAACEngine engine, byte[] key, byte[] output)
+ {
+ byte[] in = new byte[output.length];
+ byte[] enc = new byte[output.length];
+ engine.init(true, new KeyParameter(key));
+ engine.processBytes(in, 0, in.length, enc, 0);
+ if (!areEqual(enc, output))
+ {
+ fail("ciphertext mismatch");
+ }
+ engine.init(false, new KeyParameter(key));
+ engine.processBytes(enc, 0, enc.length, enc, 0);
+ if (!areEqual(enc, in))
+ {
+ fail("plaintext mismatch");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new ISAACTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/ISO9796Test.java b/core/src/test/java/org/spongycastle/crypto/test/ISO9796Test.java
new file mode 100644
index 00000000..109696bc
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/ISO9796Test.java
@@ -0,0 +1,972 @@
+package org.spongycastle.crypto.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.RIPEMD128Digest;
+import org.spongycastle.crypto.digests.RIPEMD160Digest;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.encodings.ISO9796d1Encoding;
+import org.spongycastle.crypto.engines.RSABlindedEngine;
+import org.spongycastle.crypto.engines.RSAEngine;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.ParametersWithSalt;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+import org.spongycastle.crypto.signers.ISO9796d2PSSSigner;
+import org.spongycastle.crypto.signers.ISO9796d2Signer;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Base64;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * test vectors from ISO 9796-1 and ISO 9796-2 edition 1.
+ */
+public class ISO9796Test
+ extends SimpleTest
+{
+ static BigInteger mod1 = new BigInteger("0100000000000000000000000000000000bba2d15dbb303c8a21c5ebbcbae52b7125087920dd7cdf358ea119fd66fb064012ec8ce692f0a0b8e8321b041acd40b7", 16);
+
+ static BigInteger pub1 = new BigInteger("03", 16);
+
+ static BigInteger pri1 = new BigInteger("2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac9f0783a49dd5f6c5af651f4c9d0dc9281c96a3f16a85f9572d7cc3f2d0f25a9dbf1149e4cdc32273faadd3fda5dcda7", 16);
+
+ static BigInteger mod2 = new BigInteger("ffffff7fa27087c35ebead78412d2bdffe0301edd494df13458974ea89b364708f7d0f5a00a50779ddf9f7d4cb80b8891324da251a860c4ec9ef288104b3858d", 16);
+
+ static BigInteger pub2 = new BigInteger("03", 16);
+
+ static BigInteger pri2 = new BigInteger("2aaaaa9545bd6bf5e51fc7940adcdca5550080524e18cfd88b96e8d1c19de6121b13fac0eb0495d47928e047724d91d1740f6968457ce53ec8e24c9362ce84b5", 16);
+
+ static byte msg1[] = Hex.decode("0cbbaa99887766554433221100");
+
+ //
+ // you'll need to see the ISO 9796 to make sense of this
+ //
+ static byte sig1[] = mod1.subtract(new BigInteger("309f873d8ded8379490f6097eaafdabc137d3ebfd8f25ab5f138d56a719cdc526bdd022ea65dabab920a81013a85d092e04d3e421caab717c90d89ea45a8d23a", 16)).toByteArray();
+
+ static byte msg2[] = Hex.decode("fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210");
+
+ static byte sig2[] = new BigInteger("319bb9becb49f3ed1bca26d0fcf09b0b0a508e4d0bd43b350f959b72cd25b3af47d608fdcd248eada74fbe19990dbeb9bf0da4b4e1200243a14e5cab3f7e610c", 16).toByteArray();
+
+ static byte msg3[] = Hex.decode("0112233445566778899aabbccd");
+
+ static byte sig3[] = mod2.subtract(new BigInteger("58e59ffb4b1fb1bcdbf8d1fe9afa3730c78a318a1134f5791b7313d480ff07ac319b068edf8f212945cb09cf33df30ace54f4a063fcca0b732f4b662dc4e2454", 16)).toByteArray();
+
+ //
+ // ISO 9796-2
+ //
+ static BigInteger mod3 = new BigInteger("ffffffff78f6c55506c59785e871211ee120b0b5dd644aa796d82413a47b24573f1be5745b5cd9950f6b389b52350d4e01e90009669a8720bf265a2865994190a661dea3c7828e2e7ca1b19651adc2d5", 16);
+
+ static BigInteger pub3 = new BigInteger("03", 16);
+
+ static BigInteger pri3 = new BigInteger("2aaaaaaa942920e38120ee965168302fd0301d73a4e60c7143ceb0adf0bf30b9352f50e8b9e4ceedd65343b2179005b2f099915e4b0c37e41314bb0821ad8330d23cba7f589e0f129b04c46b67dfce9d", 16);
+
+ static BigInteger mod4 = new BigInteger("FFFFFFFF45f1903ebb83d4d363f70dc647b839f2a84e119b8830b2dec424a1ce0c9fd667966b81407e89278283f27ca8857d40979407fc6da4cc8a20ecb4b8913b5813332409bc1f391a94c9c328dfe46695daf922259174544e2bfbe45cc5cd", 16);
+ static BigInteger pub4 = new BigInteger("02", 16);
+ static BigInteger pri4 = new BigInteger("1fffffffe8be3207d7707a9a6c7ee1b8c8f7073e5509c2337106165bd8849439c193faccf2cd70280fd124f0507e4f94cb66447680c6b87b6599d1b61c8f3600854a618262e9c1cb1438e485e47437be036d94b906087a61ee74ab0d9a1accd8", 16);
+
+ static byte msg4[] = Hex.decode("6162636462636465636465666465666765666768666768696768696a68696a6b696a6b6c6a6b6c6d6b6c6d6e6c6d6e6f6d6e6f706e6f7071");
+ static byte sig4[] = Hex.decode("374695b7ee8b273925b4656cc2e008d41463996534aa5aa5afe72a52ffd84e118085f8558f36631471d043ad342de268b94b080bee18a068c10965f581e7f32899ad378835477064abed8ef3bd530fce");
+
+ static byte msg5[] = Hex.decode("fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210");
+ static byte sig5[] = Hex.decode("5cf9a01854dbacaec83aae8efc563d74538192e95466babacd361d7c86000fe42dcb4581e48e4feb862d04698da9203b1803b262105104d510b365ee9c660857ba1c001aa57abfd1c8de92e47c275cae");
+
+ //
+ // scheme 2 data
+ //
+ static BigInteger mod6 = new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16);
+ static BigInteger pub6 = new BigInteger("11", 16);
+ static BigInteger pri6 = new BigInteger("92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619", 16);
+
+ static byte sig6[] = new BigInteger("0073FEAF13EB12914A43FE635022BB4AB8188A8F3ABD8D8A9E4AD6C355EE920359C7F237AE36B1212FE947F676C68FE362247D27D1F298CA9302EB21F4A64C26CE44471EF8C0DFE1A54606F0BA8E63E87CDACA993BFA62973B567473B4D38FAE73AB228600934A9CC1D3263E632E21FD52D2B95C5F7023DA63DE9509C01F6C7BBC", 16).modPow(pri6, mod6).toByteArray();
+
+ static byte msg7[] = Hex.decode("6162636462636465636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F70716F70717270717273");
+ static byte sig7[] = new BigInteger("296B06224010E1EC230D4560A5F88F03550AAFCE31C805CE81E811E5E53E5F71AE64FC2A2A486B193E87972D90C54B807A862F21A21919A43ECF067240A8C8C641DE8DCDF1942CF790D136728FFC0D98FB906E7939C1EC0E64C0E067F0A7443D6170E411DF91F797D1FFD74009C4638462E69D5923E7433AEC028B9A90E633CC", 16).modPow(pri6, mod6).toByteArray();
+
+ static byte msg8[] = Hex.decode("FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA98");
+ static byte sig8[] = new BigInteger("01402B29ABA104079677CE7FC3D5A84DB24494D6F9508B4596484F5B3CC7E8AFCC4DDE7081F21CAE9D4F94D6D2CCCB43FCEDA0988FFD4EF2EAE72CFDEB4A2638F0A34A0C49664CD9DB723315759D758836C8BA26AC4348B66958AC94AE0B5A75195B57ABFB9971E21337A4B517F2E820B81F26BCE7C66F48A2DB12A8F3D731CC", 16).modPow(pri6, mod6).toByteArray();
+
+ static byte msg9[] = Hex.decode("6162636462636465636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F70716F707172707172737172737472737475737475767475767775767778767778797778797A78797A61797A61627A6162636162636462636465");
+ static byte sig9[] = new BigInteger("6F2BB97571FE2EF205B66000E9DD06656655C1977F374E8666D636556A5FEEEEAF645555B25F45567C4EE5341F96FED86508C90A9E3F11B26E8D496139ED3E55ECE42860A6FB3A0817DAFBF13019D93E1D382DA07264FE99D9797D2F0B7779357CA7E74EE440D8855B7DDF15F000AC58EE3FFF144845E771907C0C83324A6FBC", 16).modPow(pri6, mod6).toByteArray();
+
+ public String getName()
+ {
+ return "ISO9796";
+ }
+
+ private boolean isSameAs(
+ byte[] a,
+ int off,
+ byte[] b)
+ {
+ if ((a.length - off) != b.length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i != b.length; i++)
+ {
+ if (a[i + off] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private boolean startsWith(
+ byte[] a,
+ byte[] b)
+ {
+ if (a.length < b.length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i != b.length; i++)
+ {
+ if (a[i] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private void doTest1()
+ throws Exception
+ {
+ RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod1, pub1);
+ RSAKeyParameters privParameters = new RSAKeyParameters(true, mod1, pri1);
+ RSAEngine rsa = new RSAEngine();
+ byte[] data;
+
+ //
+ // ISO 9796-1 - public encrypt, private decrypt
+ //
+ ISO9796d1Encoding eng = new ISO9796d1Encoding(rsa);
+
+ eng.init(true, privParameters);
+
+ eng.setPadBits(4);
+
+ data = eng.processBlock(msg1, 0, msg1.length);
+
+ eng.init(false, pubParameters);
+
+ if (!areEqual(sig1, data))
+ {
+ fail("failed ISO9796-1 generation Test 1");
+ }
+
+ data = eng.processBlock(data, 0, data.length);
+
+ if (!areEqual(msg1, data))
+ {
+ fail("failed ISO9796-1 retrieve Test 1");
+ }
+ }
+
+ private void doTest2()
+ throws Exception
+ {
+ RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod1, pub1);
+ RSAKeyParameters privParameters = new RSAKeyParameters(true, mod1, pri1);
+ RSAEngine rsa = new RSAEngine();
+ byte[] data;
+
+ //
+ // ISO 9796-1 - public encrypt, private decrypt
+ //
+ ISO9796d1Encoding eng = new ISO9796d1Encoding(rsa);
+
+ eng.init(true, privParameters);
+
+ data = eng.processBlock(msg2, 0, msg2.length);
+
+ eng.init(false, pubParameters);
+
+ if (!isSameAs(data, 1, sig2))
+ {
+ fail("failed ISO9796-1 generation Test 2");
+ }
+
+ data = eng.processBlock(data, 0, data.length);
+
+
+ if (!areEqual(msg2, data))
+ {
+ fail("failed ISO9796-1 retrieve Test 2");
+ }
+ }
+
+ public void doTest3()
+ throws Exception
+ {
+ RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod2, pub2);
+ RSAKeyParameters privParameters = new RSAKeyParameters(true, mod2, pri2);
+ RSAEngine rsa = new RSAEngine();
+ byte[] data;
+
+ //
+ // ISO 9796-1 - public encrypt, private decrypt
+ //
+ ISO9796d1Encoding eng = new ISO9796d1Encoding(rsa);
+
+ eng.init(true, privParameters);
+
+ eng.setPadBits(4);
+
+ data = eng.processBlock(msg3, 0, msg3.length);
+
+ eng.init(false, pubParameters);
+
+ if (!isSameAs(sig3, 1, data))
+ {
+ fail("failed ISO9796-1 generation Test 3");
+ }
+
+ data = eng.processBlock(data, 0, data.length);
+
+ if (!isSameAs(msg3, 0, data))
+ {
+ fail("failed ISO9796-1 retrieve Test 3");
+ }
+ }
+
+ public void doTest4()
+ throws Exception
+ {
+ RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod3, pub3);
+ RSAKeyParameters privParameters = new RSAKeyParameters(true, mod3, pri3);
+ RSAEngine rsa = new RSAEngine();
+ byte[] data;
+
+ //
+ // ISO 9796-2 - Signing
+ //
+ ISO9796d2Signer eng = new ISO9796d2Signer(rsa, new RIPEMD128Digest());
+
+ eng.init(true, privParameters);
+
+ eng.update(msg4[0]);
+ eng.update(msg4, 1, msg4.length - 1);
+
+ data = eng.generateSignature();
+
+ eng.init(false, pubParameters);
+
+ if (!isSameAs(sig4, 0, data))
+ {
+ fail("failed ISO9796-2 generation Test 4");
+ }
+
+ eng.update(msg4[0]);
+ eng.update(msg4, 1, msg4.length - 1);
+
+ if (!eng.verifySignature(sig4))
+ {
+ fail("failed ISO9796-2 verify Test 4");
+ }
+
+ if (eng.hasFullMessage())
+ {
+ eng = new ISO9796d2Signer(rsa, new RIPEMD128Digest());
+
+ eng.init(false, pubParameters);
+
+ if (!eng.verifySignature(sig4))
+ {
+ fail("failed ISO9796-2 verify and recover Test 4");
+ }
+
+ if (!isSameAs(eng.getRecoveredMessage(), 0, msg4))
+ {
+ fail("failed ISO9796-2 recovered message Test 4");
+ }
+
+ // try update with recovered
+ eng.updateWithRecoveredMessage(sig4);
+
+ if (!isSameAs(eng.getRecoveredMessage(), 0, msg4))
+ {
+ fail("failed ISO9796-2 updateWithRecovered recovered message Test 4");
+ }
+
+ if (!eng.verifySignature(sig4))
+ {
+ fail("failed ISO9796-2 updateWithRecovered verify and recover Test 4");
+ }
+
+ if (!isSameAs(eng.getRecoveredMessage(), 0, msg4))
+ {
+ fail("failed ISO9796-2 updateWithRecovered recovered verify message Test 4");
+ }
+
+ // should fail
+ eng.updateWithRecoveredMessage(sig4);
+
+ eng.update(msg4, 0, msg4.length);
+
+ if (eng.verifySignature(sig4))
+ {
+ fail("failed ISO9796-2 updateWithRecovered verify and recover Test 4");
+ }
+ }
+ else
+ {
+ fail("full message flag false - Test 4");
+ }
+ }
+
+ public void doTest5()
+ throws Exception
+ {
+ RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod3, pub3);
+ RSAKeyParameters privParameters = new RSAKeyParameters(true, mod3, pri3);
+ RSAEngine rsa = new RSAEngine();
+ byte[] data;
+
+ //
+ // ISO 9796-2 - Signing
+ //
+ ISO9796d2Signer eng = new ISO9796d2Signer(rsa, new RIPEMD160Digest(), true);
+
+ eng.init(true, privParameters);
+
+ eng.update(msg5[0]);
+ eng.update(msg5, 1, msg5.length - 1);
+
+ data = eng.generateSignature();
+
+ eng.init(false, pubParameters);
+
+ if (!isSameAs(sig5, 0, data))
+ {
+ fail("failed ISO9796-2 generation Test 5");
+ }
+
+ eng.update(msg5[0]);
+ eng.update(msg5, 1, msg5.length - 1);
+
+ if (!eng.verifySignature(sig5))
+ {
+ fail("failed ISO9796-2 verify Test 5");
+ }
+
+ if (eng.hasFullMessage())
+ {
+ fail("fullMessage true - Test 5");
+ }
+
+ if (!startsWith(msg5, eng.getRecoveredMessage()))
+ {
+ fail("failed ISO9796-2 partial recovered message Test 5");
+ }
+
+ int length = eng.getRecoveredMessage().length;
+
+ if (length >= msg5.length)
+ {
+ fail("Test 5 recovered message too long");
+ }
+
+ eng = new ISO9796d2Signer(rsa, new RIPEMD160Digest(), true);
+
+ eng.init(false, pubParameters);
+
+ eng.updateWithRecoveredMessage(sig5);
+
+ if (!startsWith(msg5, eng.getRecoveredMessage()))
+ {
+ fail("failed ISO9796-2 updateWithRecovered partial recovered message Test 5");
+ }
+
+ if (eng.hasFullMessage())
+ {
+ fail("fullMessage updateWithRecovered true - Test 5");
+ }
+
+ for (int i = length; i != msg5.length; i++)
+ {
+ eng.update(msg5[i]);
+ }
+
+ if (!eng.verifySignature(sig5))
+ {
+ fail("failed ISO9796-2 verify Test 5");
+ }
+
+ if (eng.hasFullMessage())
+ {
+ fail("fullMessage updateWithRecovered true - Test 5");
+ }
+
+ // should fail
+ eng.updateWithRecoveredMessage(sig5);
+
+ eng.update(msg5, 0, msg5.length);
+
+ if (eng.verifySignature(sig5))
+ {
+ fail("failed ISO9796-2 updateWithRecovered verify fail Test 5");
+ }
+ }
+
+ //
+ // against a zero length string
+ //
+
+ public void doTest6()
+ throws Exception
+ {
+ byte[] salt = Hex.decode("61DF870C4890FE85D6E3DD87C3DCE3723F91DB49");
+ RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod6, pub6);
+ RSAKeyParameters privParameters = new RSAKeyParameters(true, mod6, pri6);
+ ParametersWithSalt sigParameters = new ParametersWithSalt(privParameters, salt);
+ RSAEngine rsa = new RSAEngine();
+ byte[] data;
+
+ //
+ // ISO 9796-2 - PSS Signing
+ //
+ ISO9796d2PSSSigner eng = new ISO9796d2PSSSigner(rsa, new RIPEMD160Digest(), 20, true);
+
+ eng.init(true, sigParameters);
+
+ data = eng.generateSignature();
+
+ eng.init(false, pubParameters);
+
+ if (!isSameAs(sig6, 1, data))
+ {
+ fail("failed ISO9796-2 generation Test 6");
+ }
+
+ if (!eng.verifySignature(data))
+ {
+ fail("failed ISO9796-2 verify Test 6");
+ }
+ }
+
+ public void doTest7()
+ throws Exception
+ {
+ byte[] salt = new byte[0];
+ RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod6, pub6);
+ RSAKeyParameters privParameters = new RSAKeyParameters(true, mod6, pri6);
+ ParametersWithSalt sigParameters = new ParametersWithSalt(privParameters, salt);
+ RSAEngine rsa = new RSAEngine();
+ byte[] data;
+
+ //
+ // ISO 9796-2 - PSS Signing
+ //
+ ISO9796d2PSSSigner eng = new ISO9796d2PSSSigner(rsa, new SHA1Digest(), 0, false);
+
+ eng.init(true, sigParameters);
+
+ eng.update(msg7[0]);
+ eng.update(msg7, 1, msg7.length - 1);
+
+ data = eng.generateSignature();
+
+ eng.init(false, pubParameters);
+
+ if (!isSameAs(sig7, 0, data))
+ {
+ fail("failed ISO9796-2 generation Test 7");
+ }
+
+ eng.update(msg7[0]);
+ eng.update(msg7, 1, msg7.length - 1);
+
+ if (!eng.verifySignature(sig7))
+ {
+ fail("failed ISO9796-2 verify Test 7");
+ }
+
+ if (!isSameAs(msg7, 0, eng.getRecoveredMessage()))
+ {
+ fail("failed ISO9796-2 recovery Test 7");
+ }
+ }
+
+ public void doTest8()
+ throws Exception
+ {
+ byte[] salt = Hex.decode("78E293203CBA1B7F92F05F4D171FF8CA3E738FF8");
+ RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod6, pub6);
+ RSAKeyParameters privParameters = new RSAKeyParameters(true, mod6, pri6);
+ ParametersWithSalt sigParameters = new ParametersWithSalt(privParameters, salt);
+ RSAEngine rsa = new RSAEngine();
+ byte[] data;
+
+ //
+ // ISO 9796-2 - PSS Signing
+ //
+ ISO9796d2PSSSigner eng = new ISO9796d2PSSSigner(rsa, new RIPEMD160Digest(), 20, false);
+
+ eng.init(true, sigParameters);
+
+ eng.update(msg8[0]);
+ eng.update(msg8, 1, msg8.length - 1);
+
+ data = eng.generateSignature();
+
+ eng.init(false, pubParameters);
+
+ if (!isSameAs(sig8, 0, data))
+ {
+ fail("failed ISO9796-2 generation Test 8");
+ }
+
+ eng.update(msg8[0]);
+ eng.update(msg8, 1, msg8.length - 1);
+
+ if (!eng.verifySignature(sig8))
+ {
+ fail("failed ISO9796-2 verify Test 8");
+ }
+ }
+
+ public void doTest9()
+ throws Exception
+ {
+ RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod6, pub6);
+ RSAKeyParameters privParameters = new RSAKeyParameters(true, mod6, pri6);
+ RSAEngine rsa = new RSAEngine();
+ byte[] data;
+
+ //
+ // ISO 9796-2 - PSS Signing
+ //
+ ISO9796d2PSSSigner eng = new ISO9796d2PSSSigner(rsa, new RIPEMD160Digest(), 0, true);
+
+ eng.init(true, privParameters);
+
+ eng.update(msg9[0]);
+ eng.update(msg9, 1, msg9.length - 1);
+
+ data = eng.generateSignature();
+
+ eng.init(false, pubParameters);
+
+ if (!isSameAs(sig9, 0, data))
+ {
+ fail("failed ISO9796-2 generation Test 9");
+ }
+
+ eng.update(msg9[0]);
+ eng.update(msg9, 1, msg9.length - 1);
+
+ if (!eng.verifySignature(sig9))
+ {
+ fail("failed ISO9796-2 verify Test 9");
+ }
+ }
+
+ public void doTest10()
+ throws Exception
+ {
+ BigInteger mod = new BigInteger("B3ABE6D91A4020920F8B3847764ECB34C4EB64151A96FDE7B614DC986C810FF2FD73575BDF8532C06004C8B4C8B64F700A50AEC68C0701ED10E8D211A4EA554D", 16);
+ BigInteger pubExp = new BigInteger("65537", 10);
+ BigInteger priExp = new BigInteger("AEE76AE4716F77C5782838F328327012C097BD67E5E892E75C1356E372CCF8EE1AA2D2CBDFB4DA19F703743F7C0BA42B2D69202BA7338C294D1F8B6A5771FF41", 16);
+ RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod, pubExp);
+ RSAKeyParameters privParameters = new RSAKeyParameters(true, mod, priExp);
+ RSAEngine rsa = new RSAEngine();
+ byte[] data;
+
+ //
+ // ISO 9796-2 - PSS Signing
+ //
+ Digest dig = new SHA1Digest();
+ ISO9796d2PSSSigner eng = new ISO9796d2PSSSigner(rsa, dig, dig.getDigestSize());
+
+ //
+ // as the padding is random this test needs to repeat a few times to
+ // make sure
+ //
+ for (int i = 0; i != 500; i++)
+ {
+ eng.init(true, privParameters);
+
+ eng.update(msg9[0]);
+ eng.update(msg9, 1, msg9.length - 1);
+
+ data = eng.generateSignature();
+
+ eng.init(false, pubParameters);
+
+ eng.update(msg9[0]);
+ eng.update(msg9, 1, msg9.length - 1);
+
+ if (!eng.verifySignature(data))
+ {
+ fail("failed ISO9796-2 verify Test 10");
+ }
+ }
+ }
+
+ public void doTest11()
+ throws Exception
+ {
+ BigInteger mod = new BigInteger("B3ABE6D91A4020920F8B3847764ECB34C4EB64151A96FDE7B614DC986C810FF2FD73575BDF8532C06004C8B4C8B64F700A50AEC68C0701ED10E8D211A4EA554D", 16);
+ BigInteger pubExp = new BigInteger("65537", 10);
+ BigInteger priExp = new BigInteger("AEE76AE4716F77C5782838F328327012C097BD67E5E892E75C1356E372CCF8EE1AA2D2CBDFB4DA19F703743F7C0BA42B2D69202BA7338C294D1F8B6A5771FF41", 16);
+ RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod, pubExp);
+ RSAKeyParameters privParameters = new RSAKeyParameters(true, mod, priExp);
+ RSAEngine rsa = new RSAEngine();
+ byte[] data;
+ byte[] m1 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+ byte[] m2 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
+ byte[] m3 = {1, 2, 3, 4, 5, 6, 7, 8};
+
+ //
+ // ISO 9796-2 - PSS Signing
+ //
+ Digest dig = new SHA1Digest();
+ ISO9796d2PSSSigner eng = new ISO9796d2PSSSigner(rsa, dig, dig.getDigestSize());
+
+ //
+ // check message bounds
+ //
+ eng.init(true, privParameters);
+
+ eng.update(m1, 0, m1.length);
+
+ data = eng.generateSignature();
+
+ eng.init(false, pubParameters);
+
+ eng.update(m2, 0, m2.length);
+
+ if (eng.verifySignature(data))
+ {
+ fail("failed ISO9796-2 m2 verify Test 11");
+ }
+
+ eng.init(false, pubParameters);
+
+ eng.update(m3, 0, m3.length);
+
+ if (eng.verifySignature(data))
+ {
+ fail("failed ISO9796-2 m3 verify Test 11");
+ }
+
+ eng.init(false, pubParameters);
+
+ eng.update(m1, 0, m1.length);
+
+ if (!eng.verifySignature(data))
+ {
+ fail("failed ISO9796-2 verify Test 11");
+ }
+ }
+
+ public void doTest12()
+ throws Exception
+ {
+ BigInteger mod = new BigInteger("B3ABE6D91A4020920F8B3847764ECB34C4EB64151A96FDE7B614DC986C810FF2FD73575BDF8532C06004C8B4C8B64F700A50AEC68C0701ED10E8D211A4EA554D", 16);
+ BigInteger pubExp = new BigInteger("65537", 10);
+ BigInteger priExp = new BigInteger("AEE76AE4716F77C5782838F328327012C097BD67E5E892E75C1356E372CCF8EE1AA2D2CBDFB4DA19F703743F7C0BA42B2D69202BA7338C294D1F8B6A5771FF41", 16);
+ RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod, pubExp);
+ RSAKeyParameters privParameters = new RSAKeyParameters(true, mod, priExp);
+ RSAEngine rsa = new RSAEngine();
+ byte[] data;
+ byte[] m1 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+ byte[] m2 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
+ byte[] m3 = {1, 2, 3, 4, 5, 6, 7, 8};
+
+ //
+ // ISO 9796-2 - Signing
+ //
+ Digest dig = new SHA1Digest();
+ ISO9796d2Signer eng = new ISO9796d2Signer(rsa, dig);
+
+ //
+ // check message bounds
+ //
+ eng.init(true, privParameters);
+
+ eng.update(m1, 0, m1.length);
+
+ data = eng.generateSignature();
+
+ eng.init(false, pubParameters);
+
+ eng.update(m2, 0, m2.length);
+
+ if (eng.verifySignature(data))
+ {
+ fail("failed ISO9796-2 m2 verify Test 12");
+ }
+
+ eng.init(false, pubParameters);
+
+ eng.update(m3, 0, m3.length);
+
+ if (eng.verifySignature(data))
+ {
+ fail("failed ISO9796-2 m3 verify Test 12");
+ }
+
+ eng.init(false, pubParameters);
+
+ eng.update(m1, 0, m1.length);
+
+ if (!eng.verifySignature(data))
+ {
+ fail("failed ISO9796-2 verify Test 12");
+ }
+ }
+
+ private void doTest13()
+ throws Exception
+ {
+ BigInteger modulus = new BigInteger(1, Hex.decode("CDCBDABBF93BE8E8294E32B055256BBD0397735189BF75816341BB0D488D05D627991221DF7D59835C76A4BB4808ADEEB779E7794504E956ADC2A661B46904CDC71337DD29DDDD454124EF79CFDD7BC2C21952573CEFBA485CC38C6BD2428809B5A31A898A6B5648CAA4ED678D9743B589134B7187478996300EDBA16271A861"));
+ BigInteger pubExp = new BigInteger(1, Hex.decode("010001"));
+ BigInteger privExp = new BigInteger(1, Hex.decode("4BA6432AD42C74AA5AFCB6DF60FD57846CBC909489994ABD9C59FE439CC6D23D6DE2F3EA65B8335E796FD7904CA37C248367997257AFBD82B26F1A30525C447A236C65E6ADE43ECAAF7283584B2570FA07B340D9C9380D88EAACFFAEEFE7F472DBC9735C3FF3A3211E8A6BBFD94456B6A33C17A2C4EC18CE6335150548ED126D"));
+
+ RSAKeyParameters pubParams = new RSAKeyParameters(false, modulus, pubExp);
+ RSAKeyParameters privParams = new RSAKeyParameters(true, modulus, privExp);
+
+ AsymmetricBlockCipher rsaEngine = new RSABlindedEngine();
+ Digest digest = new SHA256Digest();
+
+ // set challenge to all zero's for verification
+ byte[] challenge = new byte[8];
+
+ // DOES NOT USE FINAL BOOLEAN TO INDICATE RECOVERY
+ ISO9796d2Signer signer = new ISO9796d2Signer(rsaEngine, digest, false);
+
+ // sign
+ signer.init(true, privParams);
+ signer.update(challenge, 0, challenge.length);
+
+ byte[] sig = signer.generateSignature();
+
+ // verify
+ signer.init(false, pubParams);
+ signer.update(challenge, 0, challenge.length);
+
+ if (!signer.verifySignature(sig))
+ {
+ fail("basic verification failed");
+ }
+
+ // === LETS ACTUALLY DO SOME RECOVERY, USING INPUT FROM INTERNAL AUTHENTICATE ===
+
+ signer.reset();
+
+ final String args0 = "482E20D1EDDED34359C38F5E7C01203F9D6B2641CDCA5C404D49ADAEDE034C7481D781D043722587761C90468DE69C6585A1E8B9C322F90E1B580EEDAB3F6007D0C366CF92B4DB8B41C8314929DCE2BE889C0129123484D2FD3D12763D2EBFD12AC8E51D7061AFCA1A53DEDEC7B9A617472A78C952CCC72467AE008E5F132994";
+
+ digest = new SHA1Digest();
+
+ signer = new ISO9796d2Signer(rsaEngine, digest, true);
+
+
+ signer.init(false, pubParams);
+ final byte[] signature = Hex.decode(args0);
+ signer.updateWithRecoveredMessage(signature);
+ signer.update(challenge, 0, challenge.length);
+
+ if (!signer.verifySignature(signature))
+ {
+ fail("recovered + challenge signature failed");
+ }
+
+ // === FINALLY, USING SHA-256 ===
+
+ signer.reset();
+
+ digest = new SHA256Digest();
+
+ // NOTE setting implit to false does not actually do anything for verification !!!
+ signer = new ISO9796d2Signer(rsaEngine, digest, false);
+
+
+ signer.init(true, privParams);
+ // generate NONCE of correct length using some inner knowledge
+ int nonceLength = modulus.bitLength() / 8 - 1 - digest.getDigestSize() - 2;
+ final byte[] nonce = new byte[nonceLength];
+ SecureRandom rnd = new SecureRandom();
+
+ rnd.nextBytes(nonce);
+
+ signer.update(nonce, 0, nonce.length);
+ signer.update(challenge, 0, challenge.length);
+ byte[] sig3 = signer.generateSignature();
+
+ signer.init(false, pubParams);
+ signer.updateWithRecoveredMessage(sig3);
+ signer.update(challenge, 0, challenge.length);
+ if (signer.verifySignature(sig3))
+ {
+ if (signer.hasFullMessage())
+ {
+ fail("signer indicates full message");
+ }
+ byte[] recoverableMessage = signer.getRecoveredMessage();
+
+ // sanity check, normally the nonce is ignored in eMRTD specs (PKI Technical Report)
+ if (!Arrays.areEqual(nonce, recoverableMessage))
+ {
+ fail("Nonce compare with recoverable part of message failed");
+ }
+ }
+ else
+ {
+ fail("recoverable + nonce failed.");
+ }
+ }
+
+ private static final byte[] longMessage = Base64.decode(
+ "VVNIKzErU0U2ODAxNTMyOTcxOSsyKzErNisyKzErMTo6OTk5OTk5OTk5OTk5"
+ + "OTo6OSsyOjo3Nzc3Nzc3Nzc3Nzc3Ojo5Kys1OjIwMTMwNDA1OjExMzUyMCdV"
+ + "U0ErMTo6OjE2OjEnVVNDKzRmYjk3YzFhNDI5ZGIyZDYnVVNBKzY6MTY6MTox"
+ + "MDoxKzE0OjIwNDgrMTI6/vn3S0h96eNhfmPN6OZUxXhd815h0tP871Hl+V1r"
+ + "fHHUXvrPXmjHV0vdb8fYY1zxwvnQUcFBWXT43PFi7Xbow0/9e9l6/mhs1UJq"
+ + "VPvp+ELbeXfn4Nj02ttk0e3H5Hfa69NYRuHv1WBO6lfizNnM9m9XYmh9TOrg"
+ + "f9rDRtd+ZNbf4lz9fPTt9OXyxOJWRPr/0FLzxUVsddplfHxM3ndETFD7ffjI"
+ + "/mhRYuL8WXZ733LeWFRCeOzKzmDz/HvT3GZx/XJMbFpqyOZjedzh6vZr1vrD"
+ + "615TQfN7wtJJ29bN2Hvzb2f1xGHaXl7af0/w9dpR2dr7/HzuZEJKYc7JSkv4"
+ + "/k37yERIbcrfbVTeVtR+dcVoeeRT41fmzMfzf8RnWOX4YMNifl0rMTM68EFA"
+ + "QSdCR00rMzgwKzk5OTk5OTk5J0RUTSsxMzc6MjAxMzA0MDU6MTAyJ0ZUWCtB"
+ + "QUkrKytJTlZPSUNFIFRFU1QnUkZGK09OOjEyMzQ1NidSRkYrRFE6MjIyMjIy"
+ + "MjIyJ0RUTSsxNzE6MjAxMzA0MDE6MTAyJ05BRCtTVSs5OTk5OTk5OTk5OTk5"
+ + "Ojo5KytURVNUIFNVUFBMSUVSOjpUcmFzZSByZWdpc3RlciBYWFhYWFhYK1Rl"
+ + "c3QgYWRkcmVzcyBzdXBwbGllcitDaXR5KysxMjM0NStERSdSRkYrVkE6QTEy"
+ + "MzQ1Njc4J05BRCtTQ08rOTk5OTk5OTk5OTk5OTo6OSsrVEVTVCBTVVBQTElF"
+ + "Ujo6VHJhc2UgcmVnaXN0ZXIgWFhYWFhYWCtUZXN0IGFkZHJlc3Mgc3VwcGxp"
+ + "ZXIrQ2l0eSsrMTIzNDUrREUnUkZGK1ZBOkExMjM0NTY3OCdOQUQrQlkrODg4"
+ + "ODg4ODg4ODg4ODo6OSdOQUQrSVYrNzc3Nzc3Nzc3Nzc3Nzo6OSsrVEVTVCBC"
+ + "VVlFUitUZXN0IGFkZHJlc3MgYnV5ZXIrQ2l0eTIrKzU0MzIxK0RFJ1JGRitW"
+ + "QTpKODc2NTQzMjEnTkFEK0JDTys3Nzc3Nzc3Nzc3Nzc3Ojo5KytURVNUIEJV"
+ + "WUVSK1Rlc3QgYWRkcmVzcyBidXllcitDaXR5MisrNTQzMjErREUnUkZGK1ZB"
+ + "Oko4NzY1NDMyMSdOQUQrRFArODg4ODg4ODg4ODg4ODo6OSdOQUQrUFIrNzc3"
+ + "Nzc3Nzc3Nzc3Nzo6OSdDVVgrMjpFVVI6NCdQQVQrMzUnRFRNKzEzOjIwMTMw"
+ + "NjI0OjEwMidMSU4rMSsrMTExMTExMTExMTExMTpFTidQSUErMStBQUFBQUFB"
+ + "OlNBJ0lNRCtGK00rOjo6UFJPRFVDVCBURVNUIDEnUVRZKzQ3OjEwLjAwMCdN"
+ + "T0ErNjY6Ny4wMCdQUkkrQUFCOjEuMDAnUFJJK0FBQTowLjcwJ1JGRitPTjox"
+ + "MjM0NTYnUkZGK0RROjIyMjIyMjIyMidUQVgrNytWQVQrKys6OjoyMS4wMDAn"
+ + "QUxDK0ErKysxK1REJ1BDRCsxOjMwLjAwMCdNT0ErMjA0OjMuMDAnTElOKzIr"
+ + "KzIyMjIyMjIyMjIyMjI6RU4nUElBKzErQkJCQkJCQjpTQSdJTUQrRitNKzo6"
+ + "OlBST0RVQ1QgVEVTVCAyJ1FUWSs0NzoyMC4wMDAnTU9BKzY2OjgwLjAwJ1BS"
+ + "SStBQUI6NS4wMCdQUkkrQUFBOjQuMDAnUkZGK09OOjEyMzQ1NidSRkYrRFE6"
+ + "MjIyMjIyMjIyJ1RBWCs3K1ZBVCsrKzo6OjIxLjAwMCdBTEMrQSsrKzErVEQn"
+ + "UENEKzE6MjAuMDAwJ01PQSsyMDQ6MjAuMDAnVU5TK1MnQ05UKzI6MidNT0Er"
+ + "Nzk6ODcuMDAnTU9BKzEzOToxMDUuMjcnTU9BKzEyNTo4Ny4wMCdNT0ErMjYw"
+ + "OjAuMDAnTU9BKzI1OTowLjAwJ01PQSsxNzY6MTguMjcnVEFYKzcrVkFUKysr"
+ + "Ojo6MjEuMDAwJ01PQSsxNzY6MTguMjcnTU9BKzEyNTo4Ny4wMCc=");
+
+ private static final byte[] shortPartialSig = Base64.decode(
+ "sb8yyKk6HM1cJhICScMx7QRQunRyrZ1fbI42+T+TBGNjOknvzKuvG7aftGX7"
+ + "O/RXuYgk6LTxpXv7+O5noUhMBsR2PKaHveuylU1WSPmDxDCui3kp4frqVH0w"
+ + "8Vjpl5CsKqBsmKkbGCKE+smM0xFXhYxV8QUTB2XsWNCQiFiHPgwbpfWzZUNY"
+ + "QPWd0A99P64EuUIYz1tkkDnLFmwQ19/PJu1a8orIQInmkVYWSsBsZ/7Ks6lx"
+ + "nDHpAvgiRe+OXmJ/yuQy1O3FJYdyoqvjYRPBu3qYeBK9+9L3lExLilImH5aD"
+ + "nJznaXcO8QFOxVPbrF2s4GdPIMDonEyAHdrnzoghlg==");
+
+ private void doShortPartialTest()
+ throws Exception
+ {
+ byte[] recovered = Hex.decode("5553482b312b534536383031353332393731392b322b312b362b322b312b313a3a393939393939393939393939393a3a392b323a3a373737373737373737373737373a3a392b2b353a32303133303430353a313133");
+ BigInteger exp = new BigInteger("10001", 16);
+ BigInteger mod = new BigInteger("b9b70b083da9e37e23cde8e654855db31e21d2d3fc11a5f91d2b3c311efa8f5e28c757dd6fc798631cb1b9d051c14119749cb122ad76e8c3fd7bd93abe282c026a14fba9f8023977a7a0d8b49a24d1ad87e4379a931846a1ef9520ea57e28c998cf65722683d0caaa0da8306973e2496a25cbd3cb4adb4b284e25604fabf12f385456c75da7c3c4cde37440cfb7db8c8fe6851e2bc59767b9f7218540238ac8acef3bc7bd3dc6671320c2c1a2ac8a6799ce1eaf62b9683ab1e1341b37b9249dbd6cd987b2f27b5c4619a1eda7f0fb0b59a519afbbc3cee640261cec90a4bb8fefbc844082dca9f549e56943e758579a453a357e6ccb37fc46718a5b8c3227e5d", 16);
+
+ AsymmetricKeyParameter pubKey = new RSAKeyParameters(false, mod, exp);
+
+ ISO9796d2PSSSigner pssSign = new ISO9796d2PSSSigner(new RSAEngine(), new SHA1Digest(), 20);
+
+ pssSign.init(false, pubKey);
+
+ pssSign.updateWithRecoveredMessage(shortPartialSig);
+
+ pssSign.update(longMessage, pssSign.getRecoveredMessage().length, longMessage.length - pssSign.getRecoveredMessage().length);
+
+ if (!pssSign.verifySignature(shortPartialSig))
+ {
+ fail("short partial PSS sig verification failed.");
+ }
+
+ byte[] mm = pssSign.getRecoveredMessage();
+
+ if (!Arrays.areEqual(recovered, mm))
+ {
+ fail("short partial PSS recovery failed");
+ }
+ }
+
+ private void doFullMessageTest()
+ throws Exception
+ {
+ BigInteger modulus = new BigInteger(1, Hex.decode("CDCBDABBF93BE8E8294E32B055256BBD0397735189BF75816341BB0D488D05D627991221DF7D59835C76A4BB4808ADEEB779E7794504E956ADC2A661B46904CDC71337DD29DDDD454124EF79CFDD7BC2C21952573CEFBA485CC38C6BD2428809B5A31A898A6B5648CAA4ED678D9743B589134B7187478996300EDBA16271A861"));
+ BigInteger pubExp = new BigInteger(1, Hex.decode("010001"));
+ BigInteger privExp = new BigInteger(1, Hex.decode("4BA6432AD42C74AA5AFCB6DF60FD57846CBC909489994ABD9C59FE439CC6D23D6DE2F3EA65B8335E796FD7904CA37C248367997257AFBD82B26F1A30525C447A236C65E6ADE43ECAAF7283584B2570FA07B340D9C9380D88EAACFFAEEFE7F472DBC9735C3FF3A3211E8A6BBFD94456B6A33C17A2C4EC18CE6335150548ED126D"));
+
+ RSAKeyParameters pubParams = new RSAKeyParameters(false, modulus, pubExp);
+ RSAKeyParameters privParams = new RSAKeyParameters(true, modulus, privExp);
+
+ AsymmetricBlockCipher rsaEngine = new RSABlindedEngine();
+
+ // set challenge to all zero's for verification
+ byte[] challenge = new byte[8];
+
+ ISO9796d2PSSSigner pssSign = new ISO9796d2PSSSigner(new RSAEngine(), new SHA256Digest(), 20, true);
+
+ pssSign.init(true, privParams);
+
+ pssSign.update(challenge, 0, challenge.length);
+
+ byte[] sig = pssSign.generateSignature();
+
+ pssSign.init(false, pubParams);
+
+ pssSign.updateWithRecoveredMessage(sig);
+
+ if (!pssSign.verifySignature(sig))
+ {
+ fail("challenge PSS sig verification failed.");
+ }
+
+ byte[] mm = pssSign.getRecoveredMessage();
+
+ if (!Arrays.areEqual(challenge, mm))
+ {
+ fail("challenge partial PSS recovery failed");
+ }
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ doTest1();
+ doTest2();
+ doTest3();
+ doTest4();
+ doTest5();
+ doTest6();
+ doTest7();
+ doTest8();
+ doTest9();
+ doTest10();
+ doTest11();
+ doTest12();
+ doTest13();
+ doShortPartialTest();
+ doFullMessageTest();
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new ISO9796Test());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/ISO9797Alg3MacTest.java b/core/src/test/java/org/spongycastle/crypto/test/ISO9797Alg3MacTest.java
new file mode 100644
index 00000000..1a2aee97
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/ISO9797Alg3MacTest.java
@@ -0,0 +1,126 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.engines.DESEngine;
+import org.spongycastle.crypto.macs.ISO9797Alg3Mac;
+import org.spongycastle.crypto.paddings.ISO7816d4Padding;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class ISO9797Alg3MacTest
+ extends SimpleTest
+{
+ static byte[] keyBytes = Hex.decode("7CA110454A1A6E570131D9619DC1376E");
+
+ static byte[] input1 = "Hello World !!!!".getBytes();
+
+ static byte[] output1 = Hex.decode("F09B856213BAB83B");
+
+ public ISO9797Alg3MacTest()
+ {
+ }
+
+ public void performTest()
+ {
+ KeyParameter key = new KeyParameter(keyBytes);
+ BlockCipher cipher = new DESEngine();
+ Mac mac = new ISO9797Alg3Mac(cipher);
+
+ //
+ // standard DAC - zero IV
+ //
+ mac.init(key);
+
+ mac.update(input1, 0, input1.length);
+
+ byte[] out = new byte[8];
+
+ mac.doFinal(out, 0);
+
+ if (!areEqual(out, output1))
+ {
+ fail("Failed - expected " + new String(Hex.encode(output1)) + " got " + new String(Hex.encode(out)));
+ }
+
+ //
+ // reset
+ //
+ mac.reset();
+
+ mac.init(key);
+
+ for (int i = 0; i != input1.length / 2; i++)
+ {
+ mac.update(input1[i]);
+ }
+
+ mac.update(input1, input1.length / 2, input1.length - (input1.length / 2));
+
+ mac.doFinal(out, 0);
+
+ if (!areEqual(out, output1))
+ {
+ fail("Reset failed - expected " + new String(Hex.encode(output1)) + " got " + new String(Hex.encode(out)));
+ }
+
+ testMacWithIv();
+ }
+
+ private void testMacWithIv()
+ {
+ byte[] inputData = new byte[]{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8};
+ byte[] key = new byte[]{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8};
+ byte[] zeroIv = new byte[8];
+ byte[] nonZeroIv = new byte[]{0x5, 0x6, 0x7, 0x8, 0x1, 0x2, 0x3, 0x4};
+
+ KeyParameter simpleParameter = new KeyParameter(key);
+ ParametersWithIV zeroIvParameter = new ParametersWithIV(new KeyParameter(key), zeroIv);
+
+ ISO9797Alg3Mac mac1 = new ISO9797Alg3Mac(new DESEngine(), new ISO7816d4Padding());
+
+ // we calculate a reference MAC with a null IV
+ mac1.init(simpleParameter);
+ mac1.update(inputData, 0, inputData.length);
+ byte[] output1 = new byte[mac1.getMacSize()];
+ mac1.doFinal(output1, 0);
+
+ // we then check that passing a vector of 0s is the same as not using any IV
+ ISO9797Alg3Mac mac2 = new ISO9797Alg3Mac(new DESEngine(), new ISO7816d4Padding());
+ mac2.init(zeroIvParameter);
+ mac2.update(inputData, 0, inputData.length);
+ byte[] output2 = new byte[mac2.getMacSize()];
+ mac2.doFinal(output2, 0);
+ if (!Arrays.areEqual(output1, output2))
+ {
+ fail("zero IV test failed");
+ }
+
+ // and then check that a non zero IV parameter produces a different results.
+ ParametersWithIV nonZeroIvParameter = new ParametersWithIV(new KeyParameter(key), nonZeroIv);
+ mac2 = new ISO9797Alg3Mac(new DESEngine(), new ISO7816d4Padding());
+ mac2.init(nonZeroIvParameter);
+ mac2.update(inputData, 0, inputData.length);
+ output2 = new byte[mac2.getMacSize()];
+ mac2.doFinal(output2, 0);
+ if (Arrays.areEqual(output1, output2))
+ {
+ fail("non-zero IV test failed");
+ }
+ }
+
+ public String getName()
+ {
+ return "ISO9797Alg3Mac";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new ISO9797Alg3MacTest());
+ }
+}
+
diff --git a/core/src/test/java/org/spongycastle/crypto/test/KDF1GeneratorTest.java b/core/src/test/java/org/spongycastle/crypto/test/KDF1GeneratorTest.java
new file mode 100644
index 00000000..0671ef8b
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/KDF1GeneratorTest.java
@@ -0,0 +1,93 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.DerivationFunction;
+import org.spongycastle.crypto.digests.ShortenedDigest;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.generators.KDF1BytesGenerator;
+import org.spongycastle.crypto.params.ISO18033KDFParameters;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * KDF1 tests - vectors from ISO 18033.
+ */
+public class KDF1GeneratorTest
+ extends SimpleTest
+{
+ private byte[] seed1 = Hex.decode("d6e168c5f256a2dcff7ef12facd390f393c7a88d");
+ private byte[] mask1 = Hex.decode(
+ "0742ba966813af75536bb6149cc44fc256fd6406df79665bc31dc5"
+ + "a62f70535e52c53015b9d37d412ff3c1193439599e1b628774c50d9c"
+ + "cb78d82c425e4521ee47b8c36a4bcffe8b8112a89312fc04420a39de"
+ + "99223890e74ce10378bc515a212b97b8a6447ba6a8870278");
+
+ private byte[] seed2 = Hex.decode(
+ "032e45326fa859a72ec235acff929b15d1372e30b207255f0611b8f785d7643741"
+ + "52e0ac009e509e7ba30cd2f1778e113b64e135cf4e2292c75efe5288edfda4");
+ private byte[] mask2 = Hex.decode(
+ "5f8de105b5e96b2e490ddecbd147dd1def7e3b8e0e6a26eb7b956ccb8b3bdc1ca9"
+ + "75bc57c3989e8fbad31a224655d800c46954840ff32052cdf0d640562bdfadfa263c"
+ + "fccf3c52b29f2af4a1869959bc77f854cf15bd7a25192985a842dbff8e13efee5b7e"
+ + "7e55bbe4d389647c686a9a9ab3fb889b2d7767d3837eea4e0a2f04");
+
+ private byte[] seed3 = seed2;
+ private byte[] mask3= Hex.decode(
+ "09e2decf2a6e1666c2f6071ff4298305e2643fd510a2403db42a8743cb989de86e"
+ + "668d168cbe604611ac179f819a3d18412e9eb45668f2923c087c12fee0c5a0d2a8aa"
+ + "70185401fbbd99379ec76c663e875a60b4aacb1319fa11c3365a8b79a44669f26fb5"
+ + "55c80391847b05eca1cb5cf8c2d531448d33fbaca19f6410ee1fcb");
+
+
+ public KDF1GeneratorTest()
+ {
+ }
+
+ public void performTest()
+ {
+ checkMask(1, new KDF1BytesGenerator(new ShortenedDigest(new SHA256Digest(), 20)), seed1, mask1);
+ checkMask(2, new KDF1BytesGenerator(new SHA1Digest()), seed2, mask2);
+ checkMask(3, new KDF1BytesGenerator(new ShortenedDigest(new SHA256Digest(), 20)), seed3, mask3);
+
+ try
+ {
+ new KDF1BytesGenerator(new SHA1Digest()).generateBytes(new byte[10], 0, 20);
+
+ fail("short input array not caught");
+ }
+ catch (DataLengthException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkMask(
+ int count,
+ DerivationFunction kdf,
+ byte[] seed,
+ byte[] result)
+ {
+ byte[] data = new byte[result.length];
+
+ kdf.init(new ISO18033KDFParameters(seed));
+
+ kdf.generateBytes(data, 0, data.length);
+
+ if (!areEqual(result, data))
+ {
+ fail("KDF1 failed generator test " + count);
+ }
+ }
+
+ public String getName()
+ {
+ return "KDF1";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new KDF1GeneratorTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/KDF2GeneratorTest.java b/core/src/test/java/org/spongycastle/crypto/test/KDF2GeneratorTest.java
new file mode 100644
index 00000000..676f22b1
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/KDF2GeneratorTest.java
@@ -0,0 +1,105 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.DerivationFunction;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.digests.ShortenedDigest;
+import org.spongycastle.crypto.generators.KDF2BytesGenerator;
+import org.spongycastle.crypto.params.KDFParameters;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * KDF2 tests - vectors from ISO 18033.
+ */
+public class KDF2GeneratorTest
+ extends SimpleTest
+{
+ private byte[] seed1 = Hex.decode("d6e168c5f256a2dcff7ef12facd390f393c7a88d");
+ private byte[] mask1 = Hex.decode(
+ "df79665bc31dc5a62f70535e52c53015b9d37d412ff3c119343959"
+ + "9e1b628774c50d9ccb78d82c425e4521ee47b8c36a4bcffe8b8112a8"
+ + "9312fc04420a39de99223890e74ce10378bc515a212b97b8a6447ba6"
+ + "a8870278f0262727ca041fa1aa9f7b5d1cf7f308232fe861");
+
+ private byte[] seed2 = Hex.decode(
+ "032e45326fa859a72ec235acff929b15d1372e30b207255f0611b8f785d7643741"
+ + "52e0ac009e509e7ba30cd2f1778e113b64e135cf4e2292c75efe5288edfda4");
+ private byte[] mask2 = Hex.decode(
+ "10a2403db42a8743cb989de86e668d168cbe604611ac179f819a3d18412e9eb456"
+ + "68f2923c087c12fee0c5a0d2a8aa70185401fbbd99379ec76c663e875a60b4aacb13"
+ + "19fa11c3365a8b79a44669f26fb555c80391847b05eca1cb5cf8c2d531448d33fbac"
+ + "a19f6410ee1fcb260892670e0814c348664f6a7248aaf998a3acc6");
+ private byte[] adjustedMask2 = Hex.decode(
+ "10a2403db42a8743cb989de86e668d168cbe6046e23ff26f741e87949a3bba1311ac1"
+ + "79f819a3d18412e9eb45668f2923c087c1299005f8d5fd42ca257bc93e8fee0c5a0d2"
+ + "a8aa70185401fbbd99379ec76c663e9a29d0b70f3fe261a59cdc24875a60b4aacb131"
+ + "9fa11c3365a8b79a44669f26fba933d012db213d7e3b16349");
+
+ private byte[] sha1Mask = Hex.decode(
+ "0e6a26eb7b956ccb8b3bdc1ca975bc57c3989e8fbad31a224655d800c46954840ff32"
+ + "052cdf0d640562bdfadfa263cfccf3c52b29f2af4a1869959bc77f854cf15bd7a2519"
+ + "2985a842dbff8e13efee5b7e7e55bbe4d389647c686a9a9ab3fb889b2d7767d3837ee"
+ + "a4e0a2f04b53ca8f50fb31225c1be2d0126c8c7a4753b0807");
+
+ private byte[] seed3 = Hex.decode("CA7C0F8C3FFA87A96E1B74AC8E6AF594347BB40A");
+ private byte[] mask3 = Hex.decode("744AB703F5BC082E59185F6D049D2D367DB245C2");
+
+ private byte[] seed4 = Hex.decode("0499B502FC8B5BAFB0F4047E731D1F9FD8CD0D8881");
+ private byte[] mask4 = Hex.decode("03C62280C894E103C680B13CD4B4AE740A5EF0C72547292F82DC6B1777F47D63BA9D1EA732DBF386");
+
+ public KDF2GeneratorTest()
+ {
+ }
+
+ public void performTest()
+ {
+ checkMask(1, new KDF2BytesGenerator(new ShortenedDigest(new SHA256Digest(), 20)), seed1, mask1);
+ checkMask(2, new KDF2BytesGenerator(new ShortenedDigest(new SHA256Digest(), 20)), seed2, mask2);
+ checkMask(3, new KDF2BytesGenerator(new SHA256Digest()), seed2, adjustedMask2);
+ checkMask(4, new KDF2BytesGenerator(new SHA1Digest()), seed2, sha1Mask);
+ checkMask(5, new KDF2BytesGenerator(new SHA1Digest()), seed3, mask3);
+ checkMask(6, new KDF2BytesGenerator(new SHA1Digest()), seed4, mask4);
+
+ try
+ {
+ new KDF2BytesGenerator(new SHA1Digest()).generateBytes(new byte[10], 0, 20);
+
+ fail("short input array not caught");
+ }
+ catch (DataLengthException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkMask(
+ int count,
+ DerivationFunction kdf,
+ byte[] seed,
+ byte[] result)
+ {
+ byte[] data = new byte[result.length];
+
+ kdf.init(new KDFParameters(seed, new byte[0]));
+
+ kdf.generateBytes(data, 0, data.length);
+
+ if (!areEqual(result, data))
+ {
+ fail("KDF2 failed generator test " + count);
+ }
+ }
+
+ public String getName()
+ {
+ return "KDF2";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new KDF2GeneratorTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/KDFCounterGeneratorTest.java b/core/src/test/java/org/spongycastle/crypto/test/KDFCounterGeneratorTest.java
new file mode 100644
index 00000000..3b58db2a
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/KDFCounterGeneratorTest.java
@@ -0,0 +1,51 @@
+package org.spongycastle.crypto.test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+
+import org.spongycastle.crypto.test.cavp.CAVPReader;
+import org.spongycastle.crypto.test.cavp.KDFCounterTests;
+import org.spongycastle.util.test.SimpleTest;
+
+public class KDFCounterGeneratorTest
+ extends SimpleTest
+{
+
+ private static void testCounter()
+ {
+
+ CAVPReader cavpReader = new CAVPReader(new KDFCounterTests());
+
+ final InputStream stream = CAVPReader.class.getResourceAsStream("KDFCTR_gen.rsp");
+ final Reader reader = new InputStreamReader(stream, Charset.forName("UTF-8"));
+ cavpReader.setInput("KDFCounter", reader);
+
+ try
+ {
+ cavpReader.readAll();
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("Something is rotten in the state of Denmark", e);
+ }
+ }
+
+ public String getName()
+ {
+ return this.getClass().getSimpleName();
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ testCounter();
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new KDFCounterGeneratorTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/KDFDoublePipelineIteratorGeneratorTest.java b/core/src/test/java/org/spongycastle/crypto/test/KDFDoublePipelineIteratorGeneratorTest.java
new file mode 100644
index 00000000..d44d1cab
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/KDFDoublePipelineIteratorGeneratorTest.java
@@ -0,0 +1,72 @@
+package org.spongycastle.crypto.test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+
+import org.spongycastle.crypto.test.cavp.CAVPReader;
+import org.spongycastle.crypto.test.cavp.KDFDoublePipelineCounterTests;
+import org.spongycastle.crypto.test.cavp.KDFDoublePipelineIterationNoCounterTests;
+import org.spongycastle.util.test.SimpleTest;
+
+public class KDFDoublePipelineIteratorGeneratorTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return this.getClass().getSimpleName();
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ testDoublePipelineIterationCounter();
+ testDoublePipelineIterationNoCounter();
+ }
+
+ private static void testDoublePipelineIterationCounter()
+ {
+
+ CAVPReader cavpReader = new CAVPReader(new KDFDoublePipelineCounterTests());
+
+ final InputStream stream = CAVPReader.class.getResourceAsStream("KDFDblPipelineCounter_gen.rsp");
+ final Reader reader = new InputStreamReader(stream, Charset.forName("UTF-8"));
+ cavpReader.setInput("KDFDoublePipelineIterationCounter", reader);
+
+ try
+ {
+ cavpReader.readAll();
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("Something is rotten in the state of Denmark", e);
+ }
+ }
+
+ private static void testDoublePipelineIterationNoCounter()
+ {
+
+ CAVPReader cavpReader = new CAVPReader(new KDFDoublePipelineIterationNoCounterTests());
+
+ final InputStream stream = CAVPReader.class.getResourceAsStream("KDFDblPipelineNoCounter_gen.rsp");
+ final Reader reader = new InputStreamReader(stream, Charset.forName("UTF-8"));
+ cavpReader.setInput("KDFDblPipelineIterationNoCounter", reader);
+
+ try
+ {
+ cavpReader.readAll();
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("Something is rotten in the state of Denmark", e);
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new KDFDoublePipelineIteratorGeneratorTest());
+ }
+
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/KDFFeedbackGeneratorTest.java b/core/src/test/java/org/spongycastle/crypto/test/KDFFeedbackGeneratorTest.java
new file mode 100644
index 00000000..fa850985
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/KDFFeedbackGeneratorTest.java
@@ -0,0 +1,71 @@
+package org.spongycastle.crypto.test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+
+import org.spongycastle.crypto.test.cavp.CAVPReader;
+import org.spongycastle.crypto.test.cavp.KDFFeedbackCounterTests;
+import org.spongycastle.crypto.test.cavp.KDFFeedbackNoCounterTests;
+import org.spongycastle.util.test.SimpleTest;
+
+public class KDFFeedbackGeneratorTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return this.getClass().getSimpleName();
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ testFeedbackCounter();
+ testFeedbackNoCounter();
+ }
+
+ private static void testFeedbackCounter()
+ {
+
+ CAVPReader cavpReader = new CAVPReader(new KDFFeedbackCounterTests());
+
+ final InputStream stream = CAVPReader.class.getResourceAsStream("KDFFeedbackCounter_gen.rsp");
+ final Reader reader = new InputStreamReader(stream, Charset.forName("UTF-8"));
+ cavpReader.setInput("KDFFeedbackCounter", reader);
+
+ try
+ {
+ cavpReader.readAll();
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("Something is rotten in the state of Denmark ", e);
+ }
+ }
+
+ private static void testFeedbackNoCounter()
+ {
+
+ CAVPReader cavpReader = new CAVPReader(new KDFFeedbackNoCounterTests());
+
+ final InputStream stream = CAVPReader.class.getResourceAsStream("KDFFeedbackNoCounter_gen.rsp");
+ final Reader reader = new InputStreamReader(stream, Charset.forName("UTF-8"));
+ cavpReader.setInput("KDFFeedbackNoCounter", reader);
+
+ try
+ {
+ cavpReader.readAll();
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("Something is rotten in the state of Denmark", e);
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new KDFDoublePipelineIteratorGeneratorTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/MD2DigestTest.java b/core/src/test/java/org/spongycastle/crypto/test/MD2DigestTest.java
new file mode 100644
index 00000000..e393f799
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/MD2DigestTest.java
@@ -0,0 +1,52 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.MD2Digest;
+
+/**
+ * standard vector test for MD2
+ * from RFC1319 by B.Kaliski of RSA Laboratories April 1992
+ *
+ */
+public class MD2DigestTest
+ extends DigestTest
+{
+ static final String messages[] =
+ {
+ "",
+ "a",
+ "abc",
+ "message digest",
+ "abcdefghijklmnopqrstuvwxyz",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ };
+
+ static final String digests[] =
+ {
+ "8350e5a3e24c153df2275c9f80692773",
+ "32ec01ec4a6dac72c0ab96fb34c0b5d1",
+ "da853b0d3f88d99b30283a69e6ded6bb",
+ "ab4f496bfb2a530b219ff33031fe06b0",
+ "4e8ddff3650292ab5a4108c3aa47940b",
+ "da33def2a42df13975352846c30338cd",
+ "d5976f79d83d3a0dc9806c3c66f3efd8"
+ };
+
+ MD2DigestTest()
+ {
+ super(new MD2Digest(), messages, digests);
+ }
+
+ protected Digest cloneDigest(
+ Digest digest)
+ {
+ return new MD2Digest((MD2Digest)digest);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new MD2DigestTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/MD4DigestTest.java b/core/src/test/java/org/spongycastle/crypto/test/MD4DigestTest.java
new file mode 100644
index 00000000..9175e2fe
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/MD4DigestTest.java
@@ -0,0 +1,43 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.MD4Digest;
+
+/**
+ * standard vector test for MD4 from RFC 1320.
+ */
+public class MD4DigestTest
+ extends DigestTest
+{
+ static private String[] messages =
+ {
+ "",
+ "a",
+ "abc",
+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ };
+
+ static private String[] digests =
+ {
+ "31d6cfe0d16ae931b73c59d7e0c089c0",
+ "bde52cb31de33e46245e05fbdbd6fb24",
+ "a448017aaf21d8525fc10ae87aa6729d",
+ "e33b4ddc9c38f2199c3e7b164fcc0536"
+ };
+
+ MD4DigestTest()
+ {
+ super(new MD4Digest(), messages, digests);
+ }
+
+ protected Digest cloneDigest(Digest digest)
+ {
+ return new MD4Digest((MD4Digest)digest);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new MD4DigestTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/MD5DigestTest.java b/core/src/test/java/org/spongycastle/crypto/test/MD5DigestTest.java
new file mode 100644
index 00000000..f39944d1
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/MD5DigestTest.java
@@ -0,0 +1,43 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.MD5Digest;
+
+/**
+ * standard vector test for MD5 from "Handbook of Applied Cryptography", page 345.
+ */
+public class MD5DigestTest
+ extends DigestTest
+{
+ static final String[] messages =
+ {
+ "",
+ "a",
+ "abc",
+ "abcdefghijklmnopqrstuvwxyz"
+ };
+
+ static final String[] digests =
+ {
+ "d41d8cd98f00b204e9800998ecf8427e",
+ "0cc175b9c0f1b6a831c399e269772661",
+ "900150983cd24fb0d6963f7d28e17f72",
+ "c3fcd3d76192e4007dfb496cca67e13b"
+ };
+
+ MD5DigestTest()
+ {
+ super(new MD5Digest(), messages, digests);
+ }
+
+ protected Digest cloneDigest(Digest digest)
+ {
+ return new MD5Digest((MD5Digest)digest);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new MD5DigestTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/MD5HMacTest.java b/core/src/test/java/org/spongycastle/crypto/test/MD5HMacTest.java
new file mode 100644
index 00000000..76d8e214
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/MD5HMacTest.java
@@ -0,0 +1,98 @@
+
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.digests.MD5Digest;
+import org.spongycastle.crypto.macs.HMac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * MD5 HMac Test, test vectors from RFC 2202
+ */
+public class MD5HMacTest
+ extends SimpleTest
+{
+ final static String[] keys = {
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "4a656665",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "0102030405060708090a0b0c0d0e0f10111213141516171819",
+ "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ };
+
+ final static String[] digests = {
+ "9294727a3638bb1c13f48ef8158bfc9d",
+ "750c783e6ab0b503eaa86e310a5db738",
+ "56be34521d144c88dbb8c733f0e8b3f6",
+ "697eaf0aca3a3aea3a75164746ffaa79",
+ "56461ef2342edc00f9bab995690efd4c",
+ "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd",
+ "6f630fad67cda0ee1fb1f562db3aa53e"
+ };
+
+ final static String[] messages = {
+ "Hi There",
+ "what do ya want for nothing?",
+ "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
+ "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+ "Test With Truncation",
+ "Test Using Larger Than Block-Size Key - Hash Key First",
+ "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+ };
+
+ public String getName()
+ {
+ return "MD5HMac";
+ }
+
+ public void performTest()
+ {
+ HMac hmac = new HMac(new MD5Digest());
+ byte[] resBuf = new byte[hmac.getMacSize()];
+
+ for (int i = 0; i < messages.length; i++)
+ {
+ byte[] m = messages[i].getBytes();
+ if (messages[i].startsWith("0x"))
+ {
+ m = Hex.decode(messages[i].substring(2));
+ }
+ hmac.init(new KeyParameter(Hex.decode(keys[i])));
+ hmac.update(m, 0, m.length);
+ hmac.doFinal(resBuf, 0);
+
+ if (!areEqual(resBuf, Hex.decode(digests[i])))
+ {
+ fail("Vector " + i + " failed");
+ }
+ }
+
+ // test reset
+ int vector = 0; // vector used for test
+ byte[] m = messages[vector].getBytes();
+ if (messages[vector].startsWith("0x"))
+ {
+ m = Hex.decode(messages[vector].substring(2));
+ }
+ hmac.init(new KeyParameter(Hex.decode(keys[vector])));
+ hmac.update(m, 0, m.length);
+ hmac.doFinal(resBuf, 0);
+ hmac.reset();
+ hmac.update(m, 0, m.length);
+ hmac.doFinal(resBuf, 0);
+
+ if (!areEqual(resBuf, Hex.decode(digests[vector])))
+ {
+ fail("Reset with vector " + vector + " failed");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new MD5HMacTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/MGF1GeneratorTest.java b/core/src/test/java/org/spongycastle/crypto/test/MGF1GeneratorTest.java
new file mode 100644
index 00000000..0c7a2fec
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/MGF1GeneratorTest.java
@@ -0,0 +1,88 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.DerivationFunction;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.digests.ShortenedDigest;
+import org.spongycastle.crypto.generators.MGF1BytesGenerator;
+import org.spongycastle.crypto.params.MGFParameters;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * MGF1 tests - vectors from ISO 18033 for KDF1 (equivalent).
+ */
+public class MGF1GeneratorTest
+ extends SimpleTest
+{
+ private byte[] seed1 = Hex.decode("d6e168c5f256a2dcff7ef12facd390f393c7a88d");
+ private byte[] mask1 = Hex.decode(
+ "0742ba966813af75536bb6149cc44fc256fd6406df79665bc31dc5"
+ + "a62f70535e52c53015b9d37d412ff3c1193439599e1b628774c50d9c"
+ + "cb78d82c425e4521ee47b8c36a4bcffe8b8112a89312fc04420a39de"
+ + "99223890e74ce10378bc515a212b97b8a6447ba6a8870278");
+
+ private byte[] seed2 = Hex.decode(
+ "032e45326fa859a72ec235acff929b15d1372e30b207255f0611b8f785d7643741"
+ + "52e0ac009e509e7ba30cd2f1778e113b64e135cf4e2292c75efe5288edfda4");
+ private byte[] mask2 = Hex.decode(
+ "5f8de105b5e96b2e490ddecbd147dd1def7e3b8e0e6a26eb7b956ccb8b3bdc1ca9"
+ + "75bc57c3989e8fbad31a224655d800c46954840ff32052cdf0d640562bdfadfa263c"
+ + "fccf3c52b29f2af4a1869959bc77f854cf15bd7a25192985a842dbff8e13efee5b7e"
+ + "7e55bbe4d389647c686a9a9ab3fb889b2d7767d3837eea4e0a2f04");
+
+ private byte[] seed3 = seed2;
+ private byte[] mask3= Hex.decode(
+ "09e2decf2a6e1666c2f6071ff4298305e2643fd510a2403db42a8743cb989de86e"
+ + "668d168cbe604611ac179f819a3d18412e9eb45668f2923c087c12fee0c5a0d2a8aa"
+ + "70185401fbbd99379ec76c663e875a60b4aacb1319fa11c3365a8b79a44669f26fb5"
+ + "55c80391847b05eca1cb5cf8c2d531448d33fbaca19f6410ee1fcb");
+
+ public void performTest()
+ {
+ checkMask(1, new MGF1BytesGenerator(new ShortenedDigest(new SHA256Digest(), 20)), seed1, mask1);
+ checkMask(2, new MGF1BytesGenerator(new SHA1Digest()), seed2, mask2);
+ checkMask(3, new MGF1BytesGenerator(new ShortenedDigest(new SHA256Digest(), 20)), seed3, mask3);
+
+ try
+ {
+ new MGF1BytesGenerator(new SHA1Digest()).generateBytes(new byte[10], 0, 20);
+
+ fail("short input array not caught");
+ }
+ catch (DataLengthException e)
+ {
+ // expected
+ }
+ }
+
+ private void checkMask(
+ int count,
+ DerivationFunction kdf,
+ byte[] seed,
+ byte[] result)
+ {
+ byte[] data = new byte[result.length];
+
+ kdf.init(new MGFParameters(seed));
+
+ kdf.generateBytes(data, 0, data.length);
+
+ if (!areEqual(result, data))
+ {
+ fail("MGF1 failed generator test " + count);
+ }
+ }
+
+ public String getName()
+ {
+ return "MGF1";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new MGF1GeneratorTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/MacTest.java b/core/src/test/java/org/spongycastle/crypto/test/MacTest.java
new file mode 100644
index 00000000..1ae2bca1
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/MacTest.java
@@ -0,0 +1,181 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.engines.DESEngine;
+import org.spongycastle.crypto.macs.CBCBlockCipherMac;
+import org.spongycastle.crypto.macs.CFBBlockCipherMac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.crypto.paddings.PKCS7Padding;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * MAC tester - vectors from
+ * <a href=http://www.itl.nist.gov/fipspubs/fip81.htm>FIP 81</a> and
+ * <a href=http://www.itl.nist.gov/fipspubs/fip113.htm>FIP 113</a>.
+ */
+public class MacTest
+ extends SimpleTest
+{
+ static byte[] keyBytes = Hex.decode("0123456789abcdef");
+ static byte[] ivBytes = Hex.decode("1234567890abcdef");
+
+ static byte[] input1 = Hex.decode("37363534333231204e6f77206973207468652074696d6520666f7220");
+
+ static byte[] output1 = Hex.decode("f1d30f68");
+ static byte[] output2 = Hex.decode("58d2e77e");
+ static byte[] output3 = Hex.decode("cd647403");
+
+ //
+ // these aren't NIST vectors, just for regression testing.
+ //
+ static byte[] input2 = Hex.decode("3736353433323120");
+
+ static byte[] output4 = Hex.decode("3af549c9");
+ static byte[] output5 = Hex.decode("188fbdd5");
+ static byte[] output6 = Hex.decode("7045eecd");
+
+ public MacTest()
+ {
+ }
+
+ public void performTest()
+ {
+ KeyParameter key = new KeyParameter(keyBytes);
+ BlockCipher cipher = new DESEngine();
+ Mac mac = new CBCBlockCipherMac(cipher);
+
+ //
+ // standard DAC - zero IV
+ //
+ mac.init(key);
+
+ mac.update(input1, 0, input1.length);
+
+ byte[] out = new byte[4];
+
+ mac.doFinal(out, 0);
+
+ if (!areEqual(out, output1))
+ {
+ fail("Failed - expected " + new String(Hex.encode(output1)) + " got " + new String(Hex.encode(out)));
+ }
+
+ //
+ // mac with IV.
+ //
+ ParametersWithIV param = new ParametersWithIV(key, ivBytes);
+
+ mac.init(param);
+
+ mac.update(input1, 0, input1.length);
+
+ out = new byte[4];
+
+ mac.doFinal(out, 0);
+
+ if (!areEqual(out, output2))
+ {
+ fail("Failed - expected " + new String(Hex.encode(output2)) + " got " + new String(Hex.encode(out)));
+ }
+
+ //
+ // CFB mac with IV - 8 bit CFB mode
+ //
+ param = new ParametersWithIV(key, ivBytes);
+
+ mac = new CFBBlockCipherMac(cipher);
+
+ mac.init(param);
+
+ mac.update(input1, 0, input1.length);
+
+ out = new byte[4];
+
+ mac.doFinal(out, 0);
+
+ if (!areEqual(out, output3))
+ {
+ fail("Failed - expected " + new String(Hex.encode(output3)) + " got " + new String(Hex.encode(out)));
+ }
+
+ //
+ // word aligned data - zero IV
+ //
+ mac.init(key);
+
+ mac.update(input2, 0, input2.length);
+
+ out = new byte[4];
+
+ mac.doFinal(out, 0);
+
+ if (!areEqual(out, output4))
+ {
+ fail("Failed - expected " + new String(Hex.encode(output4)) + " got " + new String(Hex.encode(out)));
+ }
+
+ //
+ // word aligned data - zero IV - CBC padding
+ //
+ mac = new CBCBlockCipherMac(cipher, new PKCS7Padding());
+
+ mac.init(key);
+
+ mac.update(input2, 0, input2.length);
+
+ out = new byte[4];
+
+ mac.doFinal(out, 0);
+
+ if (!areEqual(out, output5))
+ {
+ fail("Failed - expected " + new String(Hex.encode(output5)) + " got " + new String(Hex.encode(out)));
+ }
+
+ //
+ // non-word aligned data - zero IV - CBC padding
+ //
+ mac.reset();
+
+ mac.update(input1, 0, input1.length);
+
+ out = new byte[4];
+
+ mac.doFinal(out, 0);
+
+ if (!areEqual(out, output6))
+ {
+ fail("Failed - expected " + new String(Hex.encode(output6)) + " got " + new String(Hex.encode(out)));
+ }
+
+ //
+ // non-word aligned data - zero IV - CBC padding
+ //
+ mac.init(key);
+
+ mac.update(input1, 0, input1.length);
+
+ out = new byte[4];
+
+ mac.doFinal(out, 0);
+
+ if (!areEqual(out, output6))
+ {
+ fail("Failed - expected " + new String(Hex.encode(output6)) + " got " + new String(Hex.encode(out)));
+ }
+ }
+
+ public String getName()
+ {
+ return "Mac";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new MacTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/ModeTest.java b/core/src/test/java/org/spongycastle/crypto/test/ModeTest.java
new file mode 100644
index 00000000..19fe1932
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/ModeTest.java
@@ -0,0 +1,115 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.engines.DESEngine;
+import org.spongycastle.crypto.modes.CFBBlockCipher;
+import org.spongycastle.crypto.modes.OFBBlockCipher;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+/**
+ * CFB/OFB Mode test of IV padding.
+ */
+public class ModeTest
+ implements Test
+{
+ public ModeTest()
+ {
+ }
+
+ private boolean isEqualTo(
+ byte[] a,
+ byte[] b)
+ {
+ for (int i = 0; i != a.length; i++)
+ {
+ if (a[i] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public TestResult perform()
+ {
+ KeyParameter key = new KeyParameter(Hex.decode("0011223344556677"));
+ byte[] input = Hex.decode("4e6f7720");
+ byte[] out1 = new byte[4];
+ byte[] out2 = new byte[4];
+
+
+ BlockCipher ofb = new OFBBlockCipher(new DESEngine(), 32);
+
+ ofb.init(true, new ParametersWithIV(key, Hex.decode("1122334455667788")));
+
+ ofb.processBlock(input, 0, out1, 0);
+
+ ofb.init(false, new ParametersWithIV(key, Hex.decode("1122334455667788")));
+ ofb.processBlock(out1, 0, out2, 0);
+
+ if (!isEqualTo(out2, input))
+ {
+ return new SimpleTestResult(false, getName() + ": test 1 - in != out");
+ }
+
+ ofb.init(true, new ParametersWithIV(key, Hex.decode("11223344")));
+
+ ofb.processBlock(input, 0, out1, 0);
+
+ ofb.init(false, new ParametersWithIV(key, Hex.decode("0000000011223344")));
+ ofb.processBlock(out1, 0, out2, 0);
+
+ if (!isEqualTo(out2, input))
+ {
+ return new SimpleTestResult(false, getName() + ": test 2 - in != out");
+ }
+
+ BlockCipher cfb = new CFBBlockCipher(new DESEngine(), 32);
+
+ cfb.init(true, new ParametersWithIV(key, Hex.decode("1122334455667788")));
+
+ cfb.processBlock(input, 0, out1, 0);
+
+ cfb.init(false, new ParametersWithIV(key, Hex.decode("1122334455667788")));
+ cfb.processBlock(out1, 0, out2, 0);
+
+ if (!isEqualTo(out2, input))
+ {
+ return new SimpleTestResult(false, getName() + ": test 3 - in != out");
+ }
+
+ cfb.init(true, new ParametersWithIV(key, Hex.decode("11223344")));
+
+ cfb.processBlock(input, 0, out1, 0);
+
+ cfb.init(false, new ParametersWithIV(key, Hex.decode("0000000011223344")));
+ cfb.processBlock(out1, 0, out2, 0);
+
+ if (!isEqualTo(out2, input))
+ {
+ return new SimpleTestResult(false, getName() + ": test 4 - in != out");
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+
+ public String getName()
+ {
+ return "ModeTest";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ ModeTest test = new ModeTest();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/NaccacheSternTest.java b/core/src/test/java/org/spongycastle/crypto/test/NaccacheSternTest.java
new file mode 100644
index 00000000..1bde2f45
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/NaccacheSternTest.java
@@ -0,0 +1,354 @@
+package org.spongycastle.crypto.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.Vector;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.engines.NaccacheSternEngine;
+import org.spongycastle.crypto.generators.NaccacheSternKeyPairGenerator;
+import org.spongycastle.crypto.params.NaccacheSternKeyGenerationParameters;
+import org.spongycastle.crypto.params.NaccacheSternKeyParameters;
+import org.spongycastle.crypto.params.NaccacheSternPrivateKeyParameters;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * Test case for NaccacheStern cipher. For details on this cipher, please see
+ *
+ * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+ *
+ * Performs the following tests:
+ * <ul>
+ * <li> Toy example from the NaccacheSternPaper </li>
+ * <li> 768 bit test with text "Now is the time for all good men." (ripped from RSA test) and
+ * the same test with the first byte replaced by 0xFF </li>
+ * <li> 1024 bit test analog to 768 bit test </li>
+ * </ul>
+ */
+public class NaccacheSternTest
+ extends SimpleTest
+{
+ static final boolean debug = false;
+
+ static final NaccacheSternEngine cryptEng = new NaccacheSternEngine();
+
+ static final NaccacheSternEngine decryptEng = new NaccacheSternEngine();
+
+ static
+ {
+ cryptEng.setDebug(debug);
+ decryptEng.setDebug(debug);
+ }
+
+ // Values from NaccacheStern paper
+ static final BigInteger a = BigInteger.valueOf(101);
+
+ static final BigInteger u1 = BigInteger.valueOf(3);
+
+ static final BigInteger u2 = BigInteger.valueOf(5);
+
+ static final BigInteger u3 = BigInteger.valueOf(7);
+
+ static final BigInteger b = BigInteger.valueOf(191);
+
+ static final BigInteger v1 = BigInteger.valueOf(11);
+
+ static final BigInteger v2 = BigInteger.valueOf(13);
+
+ static final BigInteger v3 = BigInteger.valueOf(17);
+
+ static final BigInteger ONE = BigInteger.valueOf(1);
+
+ static final BigInteger TWO = BigInteger.valueOf(2);
+
+ static final BigInteger sigma = u1.multiply(u2).multiply(u3).multiply(v1)
+ .multiply(v2).multiply(v3);
+
+ static final BigInteger p = TWO.multiply(a).multiply(u1).multiply(u2)
+ .multiply(u3).add(ONE);
+
+ static final BigInteger q = TWO.multiply(b).multiply(v1).multiply(v2)
+ .multiply(v3).add(ONE);
+
+ static final BigInteger n = p.multiply(q);
+
+ static final BigInteger phi_n = p.subtract(ONE).multiply(q.subtract(ONE));
+
+ static final BigInteger g = BigInteger.valueOf(131);
+
+ static final Vector smallPrimes = new Vector();
+
+ // static final BigInteger paperTest = BigInteger.valueOf(202);
+
+ static final String input = "4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
+
+ static final BigInteger paperTest = BigInteger.valueOf(202);
+
+ //
+ // to check that we handling byte extension by big number correctly.
+ //
+ static final String edgeInput = "ff6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
+
+ public String getName()
+ {
+ return "NaccacheStern";
+ }
+
+ public void performTest()
+ {
+ // Test with given key from NaccacheSternPaper (totally insecure)
+
+ // First the Parameters from the NaccacheStern Paper
+ // (see http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf )
+
+ smallPrimes.addElement(u1);
+ smallPrimes.addElement(u2);
+ smallPrimes.addElement(u3);
+ smallPrimes.addElement(v1);
+ smallPrimes.addElement(v2);
+ smallPrimes.addElement(v3);
+
+ NaccacheSternKeyParameters pubParameters = new NaccacheSternKeyParameters(false, g, n, sigma.bitLength());
+
+ NaccacheSternPrivateKeyParameters privParameters = new NaccacheSternPrivateKeyParameters(g, n, sigma.bitLength(), smallPrimes, phi_n);
+
+ AsymmetricCipherKeyPair pair = new AsymmetricCipherKeyPair(pubParameters, privParameters);
+
+ // Initialize Engines with KeyPair
+
+ if (debug)
+ {
+ System.out.println("initializing encryption engine");
+ }
+ cryptEng.init(true, pair.getPublic());
+
+ if (debug)
+ {
+ System.out.println("initializing decryption engine");
+ }
+ decryptEng.init(false, pair.getPrivate());
+
+ byte[] data = paperTest.toByteArray();
+
+ if (!new BigInteger(data).equals(new BigInteger(enDeCrypt(data))))
+ {
+ fail("failed NaccacheStern paper test");
+ }
+
+ //
+ // key generation test
+ //
+
+ //
+ // 768 Bit test
+ //
+
+ if (debug)
+ {
+ System.out.println();
+ System.out.println("768 Bit TEST");
+ }
+
+ // specify key generation parameters
+ NaccacheSternKeyGenerationParameters genParam
+ = new NaccacheSternKeyGenerationParameters(new SecureRandom(), 768, 8, 30, debug);
+
+ // Initialize Key generator and generate key pair
+ NaccacheSternKeyPairGenerator pGen = new NaccacheSternKeyPairGenerator();
+ pGen.init(genParam);
+
+ pair = pGen.generateKeyPair();
+
+ if (((NaccacheSternKeyParameters)pair.getPublic()).getModulus().bitLength() < 768)
+ {
+ System.out.println("FAILED: key size is <786 bit, exactly "
+ + ((NaccacheSternKeyParameters)pair.getPublic()).getModulus().bitLength() + " bit");
+ fail("failed key generation (768) length test");
+ }
+
+ // Initialize Engines with KeyPair
+
+ if (debug)
+ {
+ System.out.println("initializing " + genParam.getStrength() + " bit encryption engine");
+ }
+ cryptEng.init(true, pair.getPublic());
+
+ if (debug)
+ {
+ System.out.println("initializing " + genParam.getStrength() + " bit decryption engine");
+ }
+ decryptEng.init(false, pair.getPrivate());
+
+ // Basic data input
+ data = Hex.decode(input);
+
+ if (!new BigInteger(1, data).equals(new BigInteger(1, enDeCrypt(data))))
+ {
+ fail("failed encryption decryption (" + genParam.getStrength() + ") basic test");
+ }
+
+ // Data starting with FF byte (would be interpreted as negative
+ // BigInteger)
+
+ data = Hex.decode(edgeInput);
+
+ if (!new BigInteger(1, data).equals(new BigInteger(1, enDeCrypt(data))))
+ {
+ fail("failed encryption decryption (" + genParam.getStrength() + ") edgeInput test");
+ }
+
+ //
+ // 1024 Bit Test
+ //
+/*
+ if (debug)
+ {
+ System.out.println();
+ System.out.println("1024 Bit TEST");
+ }
+
+ // specify key generation parameters
+ genParam = new NaccacheSternKeyGenerationParameters(new SecureRandom(), 1024, 8, 40);
+
+ pGen.init(genParam);
+ pair = pGen.generateKeyPair();
+
+ if (((NaccacheSternKeyParameters)pair.getPublic()).getModulus().bitLength() < 1024)
+ {
+ if (debug)
+ {
+ System.out.println("FAILED: key size is <1024 bit, exactly "
+ + ((NaccacheSternKeyParameters)pair.getPublic()).getModulus().bitLength() + " bit");
+ }
+ fail("failed key generation (1024) length test");
+ }
+
+ // Initialize Engines with KeyPair
+
+ if (debug)
+ {
+ System.out.println("initializing " + genParam.getStrength() + " bit encryption engine");
+ }
+ cryptEng.init(true, pair.getPublic());
+
+ if (debug)
+ {
+ System.out.println("initializing " + genParam.getStrength() + " bit decryption engine");
+ }
+ decryptEng.init(false, pair.getPrivate());
+
+ if (debug)
+ {
+ System.out.println("Data is " + new BigInteger(1, data));
+ }
+
+ // Basic data input
+ data = Hex.decode(input);
+
+ if (!new BigInteger(1, data).equals(new BigInteger(1, enDeCrypt(data))))
+ {
+ fail("failed encryption decryption (" + genParam.getStrength() + ") basic test");
+ }
+
+ // Data starting with FF byte (would be interpreted as negative
+ // BigInteger)
+
+ data = Hex.decode(edgeInput);
+
+ if (!new BigInteger(1, data).equals(new BigInteger(1, enDeCrypt(data))))
+ {
+ fail("failed encryption decryption (" + genParam.getStrength() + ") edgeInput test");
+ }
+*/
+ // END OF TEST CASE
+
+ try
+ {
+ new NaccacheSternEngine().processBlock(new byte[]{ 1 }, 0, 1);
+ fail("failed initialisation check");
+ }
+ catch (IllegalStateException e)
+ {
+ // expected
+ }
+ catch (InvalidCipherTextException e)
+ {
+ fail("failed initialisation check");
+ }
+
+ if (debug)
+ {
+ System.out.println("All tests successful");
+ }
+ }
+
+ private byte[] enDeCrypt(byte[] input)
+ {
+
+ // create work array
+ byte[] data = new byte[input.length];
+ System.arraycopy(input, 0, data, 0, data.length);
+
+ // Perform encryption like in the paper from Naccache-Stern
+ if (debug)
+ {
+ System.out.println("encrypting data. Data representation\n"
+ // + "As String:.... " + new String(data) + "\n"
+ + "As BigInteger: " + new BigInteger(1, data));
+ System.out.println("data length is " + data.length);
+ }
+
+ try
+ {
+ data = cryptEng.processData(data);
+ }
+ catch (InvalidCipherTextException e)
+ {
+ if (debug)
+ {
+ System.out.println("failed - exception " + e.toString() + "\n" + e.getMessage());
+ }
+ fail("failed - exception " + e.toString() + "\n" + e.getMessage());
+ }
+
+ if (debug)
+ {
+ System.out.println("enrypted data representation\n"
+ // + "As String:.... " + new String(data) + "\n"
+ + "As BigInteger: " + new BigInteger(1, data));
+ System.out.println("data length is " + data.length);
+ }
+
+ try
+ {
+ data = decryptEng.processData(data);
+ }
+ catch (InvalidCipherTextException e)
+ {
+ if (debug)
+ {
+ System.out.println("failed - exception " + e.toString() + "\n" + e.getMessage());
+ }
+ fail("failed - exception " + e.toString() + "\n" + e.getMessage());
+ }
+
+ if (debug)
+ {
+ System.out.println("decrypted data representation\n"
+ // + "As String:.... " + new String(data) + "\n"
+ + "As BigInteger: " + new BigInteger(1, data));
+ System.out.println("data length is " + data.length);
+ }
+
+ return data;
+
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new NaccacheSternTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/NoekeonTest.java b/core/src/test/java/org/spongycastle/crypto/test/NoekeonTest.java
new file mode 100644
index 00000000..f17ff0ff
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/NoekeonTest.java
@@ -0,0 +1,45 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.engines.NoekeonEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * Noekeon tester
+ */
+public class NoekeonTest
+ extends CipherTest
+{
+ static SimpleTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new NoekeonEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000")),
+ "00000000000000000000000000000000",
+ "b1656851699e29fa24b70148503d2dfc"),
+ new BlockCipherVectorTest(1, new NoekeonEngine(),
+ new KeyParameter(Hex.decode("ffffffffffffffffffffffffffffffff")),
+ "ffffffffffffffffffffffffffffffff",
+ "2a78421b87c7d0924f26113f1d1349b2"),
+ new BlockCipherVectorTest(2, new NoekeonEngine(),
+ new KeyParameter(Hex.decode("b1656851699e29fa24b70148503d2dfc")),
+ "2a78421b87c7d0924f26113f1d1349b2",
+ "e2f687e07b75660ffc372233bc47532c")
+ };
+
+ NoekeonTest()
+ {
+ super(tests, new NoekeonEngine(), new KeyParameter(new byte[16]));
+ }
+
+ public String getName()
+ {
+ return "Noekeon";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new NoekeonTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/NonMemoableDigestTest.java b/core/src/test/java/org/spongycastle/crypto/test/NonMemoableDigestTest.java
new file mode 100644
index 00000000..8abb0229
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/NonMemoableDigestTest.java
@@ -0,0 +1,112 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.digests.NonMemoableDigest;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.macs.HMac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+/**
+ * SHA1 HMac Test, test vectors from RFC 2202
+ */
+public class NonMemoableDigestTest
+ implements Test
+{
+ final static String[] keys = {
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "4a656665",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "0102030405060708090a0b0c0d0e0f10111213141516171819",
+ "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ };
+
+ final static String[] digests = {
+ "b617318655057264e28bc0b6fb378c8ef146be00",
+ "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79",
+ "125d7342b9ac11cd91a39af48aa17b4f63f175d3",
+ "4c9007f4026250c6bc8414f9bf50c86c2d7235da",
+ "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04",
+ "aa4ae5e15272d00e95705637ce8a3b55ed402112",
+ "e8e99d0f45237d786d6bbaa7965c7808bbff1a91",
+ "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04",
+ "aa4ae5e15272d00e95705637ce8a3b55ed402112",
+ "e8e99d0f45237d786d6bbaa7965c7808bbff1a91"
+ };
+
+ final static String[] messages = {
+ "Hi There",
+ "what do ya want for nothing?",
+ "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
+ "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+ "Test With Truncation",
+ "Test Using Larger Than Block-Size Key - Hash Key First",
+ "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+ };
+
+ public String getName()
+ {
+ return "NonMemoableDigest";
+ }
+
+ public TestResult perform()
+ {
+ HMac hmac = new HMac(new NonMemoableDigest(new SHA1Digest()));
+ byte[] resBuf = new byte[hmac.getMacSize()];
+
+ for (int i = 0; i < messages.length; i++)
+ {
+ byte[] m = messages[i].getBytes();
+ if (messages[i].startsWith("0x"))
+ {
+ m = Hex.decode(messages[i].substring(2));
+ }
+ hmac.init(new KeyParameter(Hex.decode(keys[i])));
+ hmac.update(m, 0, m.length);
+ hmac.doFinal(resBuf, 0);
+
+ if (!Arrays.areEqual(resBuf, Hex.decode(digests[i])))
+ {
+ return new SimpleTestResult(false, getName() + ": Vector " + i + " failed");
+ }
+ }
+
+ //
+ // test reset
+ //
+ int vector = 0; // vector used for test
+ byte[] m = messages[vector].getBytes();
+ if (messages[vector].startsWith("0x"))
+ {
+ m = Hex.decode(messages[vector].substring(2));
+ }
+ hmac.init(new KeyParameter(Hex.decode(keys[vector])));
+ hmac.update(m, 0, m.length);
+ hmac.doFinal(resBuf, 0);
+ hmac.reset();
+ hmac.update(m, 0, m.length);
+ hmac.doFinal(resBuf, 0);
+
+ if (!Arrays.areEqual(resBuf, Hex.decode(digests[vector])))
+ {
+ return new SimpleTestResult(false, getName() +
+ "Reset with vector " + vector + " failed");
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+
+ public static void main(
+ String[] args)
+ {
+ NonMemoableDigestTest test = new NonMemoableDigestTest();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/NullTest.java b/core/src/test/java/org/spongycastle/crypto/test/NullTest.java
new file mode 100644
index 00000000..f384cfc4
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/NullTest.java
@@ -0,0 +1,77 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.engines.NullEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class NullTest
+ extends CipherTest
+{
+ static SimpleTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new NullEngine(),
+ new KeyParameter(Hex.decode("00")), "00", "00")
+ };
+
+ NullTest()
+ {
+ super(tests, new NullEngine(), new KeyParameter(new byte[2]));
+ }
+
+ public String getName()
+ {
+ return "Null";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ super.performTest();
+
+ BlockCipher engine = new NullEngine();
+
+ engine.init(true, null);
+
+ byte[] buf = new byte[1];
+
+ engine.processBlock(buf, 0, buf, 0);
+
+ if (buf[0] != 0)
+ {
+ fail("NullCipher changed data!");
+ }
+
+ byte[] shortBuf = new byte[0];
+
+ try
+ {
+ engine.processBlock(shortBuf, 0, buf, 0);
+
+ fail("failed short input check");
+ }
+ catch (DataLengthException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ engine.processBlock(buf, 0, shortBuf, 0);
+
+ fail("failed short output check");
+ }
+ catch (DataLengthException e)
+ {
+ // expected
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new NullTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/OAEPTest.java b/core/src/test/java/org/spongycastle/crypto/test/OAEPTest.java
new file mode 100644
index 00000000..30c575de
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/OAEPTest.java
@@ -0,0 +1,830 @@
+package org.spongycastle.crypto.test;
+
+import java.io.ByteArrayInputStream;
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.pkcs.PrivateKeyInfo;
+import org.spongycastle.asn1.pkcs.RSAPrivateKey;
+import org.spongycastle.asn1.pkcs.RSAPublicKey;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.encodings.OAEPEncoding;
+import org.spongycastle.crypto.engines.RSAEngine;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+import org.spongycastle.crypto.params.RSAPrivateCrtKeyParameters;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class OAEPTest
+ extends SimpleTest
+{
+ static byte[] pubKeyEnc1 =
+ {
+ (byte)0x30, (byte)0x5a, (byte)0x30, (byte)0x0d, (byte)0x06, (byte)0x09, (byte)0x2a, (byte)0x86,
+ (byte)0x48, (byte)0x86, (byte)0xf7, (byte)0x0d, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x05,
+ (byte)0x00, (byte)0x03, (byte)0x49, (byte)0x00, (byte)0x30, (byte)0x46, (byte)0x02, (byte)0x41,
+ (byte)0x00, (byte)0xaa, (byte)0x36, (byte)0xab, (byte)0xce, (byte)0x88, (byte)0xac, (byte)0xfd,
+ (byte)0xff, (byte)0x55, (byte)0x52, (byte)0x3c, (byte)0x7f, (byte)0xc4, (byte)0x52, (byte)0x3f,
+ (byte)0x90, (byte)0xef, (byte)0xa0, (byte)0x0d, (byte)0xf3, (byte)0x77, (byte)0x4a, (byte)0x25,
+ (byte)0x9f, (byte)0x2e, (byte)0x62, (byte)0xb4, (byte)0xc5, (byte)0xd9, (byte)0x9c, (byte)0xb5,
+ (byte)0xad, (byte)0xb3, (byte)0x00, (byte)0xa0, (byte)0x28, (byte)0x5e, (byte)0x53, (byte)0x01,
+ (byte)0x93, (byte)0x0e, (byte)0x0c, (byte)0x70, (byte)0xfb, (byte)0x68, (byte)0x76, (byte)0x93,
+ (byte)0x9c, (byte)0xe6, (byte)0x16, (byte)0xce, (byte)0x62, (byte)0x4a, (byte)0x11, (byte)0xe0,
+ (byte)0x08, (byte)0x6d, (byte)0x34, (byte)0x1e, (byte)0xbc, (byte)0xac, (byte)0xa0, (byte)0xa1,
+ (byte)0xf5, (byte)0x02, (byte)0x01, (byte)0x11
+ };
+
+ static byte[] privKeyEnc1 =
+ {
+ (byte)0x30, (byte)0x82, (byte)0x01, (byte)0x52, (byte)0x02, (byte)0x01, (byte)0x00, (byte)0x30,
+ (byte)0x0d, (byte)0x06, (byte)0x09, (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0x86, (byte)0xf7,
+ (byte)0x0d, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x05, (byte)0x00, (byte)0x04, (byte)0x82,
+ (byte)0x01, (byte)0x3c, (byte)0x30, (byte)0x82, (byte)0x01, (byte)0x38, (byte)0x02, (byte)0x01,
+ (byte)0x00, (byte)0x02, (byte)0x41, (byte)0x00, (byte)0xaa, (byte)0x36, (byte)0xab, (byte)0xce,
+ (byte)0x88, (byte)0xac, (byte)0xfd, (byte)0xff, (byte)0x55, (byte)0x52, (byte)0x3c, (byte)0x7f,
+ (byte)0xc4, (byte)0x52, (byte)0x3f, (byte)0x90, (byte)0xef, (byte)0xa0, (byte)0x0d, (byte)0xf3,
+ (byte)0x77, (byte)0x4a, (byte)0x25, (byte)0x9f, (byte)0x2e, (byte)0x62, (byte)0xb4, (byte)0xc5,
+ (byte)0xd9, (byte)0x9c, (byte)0xb5, (byte)0xad, (byte)0xb3, (byte)0x00, (byte)0xa0, (byte)0x28,
+ (byte)0x5e, (byte)0x53, (byte)0x01, (byte)0x93, (byte)0x0e, (byte)0x0c, (byte)0x70, (byte)0xfb,
+ (byte)0x68, (byte)0x76, (byte)0x93, (byte)0x9c, (byte)0xe6, (byte)0x16, (byte)0xce, (byte)0x62,
+ (byte)0x4a, (byte)0x11, (byte)0xe0, (byte)0x08, (byte)0x6d, (byte)0x34, (byte)0x1e, (byte)0xbc,
+ (byte)0xac, (byte)0xa0, (byte)0xa1, (byte)0xf5, (byte)0x02, (byte)0x01, (byte)0x11, (byte)0x02,
+ (byte)0x40, (byte)0x0a, (byte)0x03, (byte)0x37, (byte)0x48, (byte)0x62, (byte)0x64, (byte)0x87,
+ (byte)0x69, (byte)0x5f, (byte)0x5f, (byte)0x30, (byte)0xbc, (byte)0x38, (byte)0xb9, (byte)0x8b,
+ (byte)0x44, (byte)0xc2, (byte)0xcd, (byte)0x2d, (byte)0xff, (byte)0x43, (byte)0x40, (byte)0x98,
+ (byte)0xcd, (byte)0x20, (byte)0xd8, (byte)0xa1, (byte)0x38, (byte)0xd0, (byte)0x90, (byte)0xbf,
+ (byte)0x64, (byte)0x79, (byte)0x7c, (byte)0x3f, (byte)0xa7, (byte)0xa2, (byte)0xcd, (byte)0xcb,
+ (byte)0x3c, (byte)0xd1, (byte)0xe0, (byte)0xbd, (byte)0xba, (byte)0x26, (byte)0x54, (byte)0xb4,
+ (byte)0xf9, (byte)0xdf, (byte)0x8e, (byte)0x8a, (byte)0xe5, (byte)0x9d, (byte)0x73, (byte)0x3d,
+ (byte)0x9f, (byte)0x33, (byte)0xb3, (byte)0x01, (byte)0x62, (byte)0x4a, (byte)0xfd, (byte)0x1d,
+ (byte)0x51, (byte)0x02, (byte)0x21, (byte)0x00, (byte)0xd8, (byte)0x40, (byte)0xb4, (byte)0x16,
+ (byte)0x66, (byte)0xb4, (byte)0x2e, (byte)0x92, (byte)0xea, (byte)0x0d, (byte)0xa3, (byte)0xb4,
+ (byte)0x32, (byte)0x04, (byte)0xb5, (byte)0xcf, (byte)0xce, (byte)0x33, (byte)0x52, (byte)0x52,
+ (byte)0x4d, (byte)0x04, (byte)0x16, (byte)0xa5, (byte)0xa4, (byte)0x41, (byte)0xe7, (byte)0x00,
+ (byte)0xaf, (byte)0x46, (byte)0x12, (byte)0x0d, (byte)0x02, (byte)0x21, (byte)0x00, (byte)0xc9,
+ (byte)0x7f, (byte)0xb1, (byte)0xf0, (byte)0x27, (byte)0xf4, (byte)0x53, (byte)0xf6, (byte)0x34,
+ (byte)0x12, (byte)0x33, (byte)0xea, (byte)0xaa, (byte)0xd1, (byte)0xd9, (byte)0x35, (byte)0x3f,
+ (byte)0x6c, (byte)0x42, (byte)0xd0, (byte)0x88, (byte)0x66, (byte)0xb1, (byte)0xd0, (byte)0x5a,
+ (byte)0x0f, (byte)0x20, (byte)0x35, (byte)0x02, (byte)0x8b, (byte)0x9d, (byte)0x89, (byte)0x02,
+ (byte)0x20, (byte)0x59, (byte)0x0b, (byte)0x95, (byte)0x72, (byte)0xa2, (byte)0xc2, (byte)0xa9,
+ (byte)0xc4, (byte)0x06, (byte)0x05, (byte)0x9d, (byte)0xc2, (byte)0xab, (byte)0x2f, (byte)0x1d,
+ (byte)0xaf, (byte)0xeb, (byte)0x7e, (byte)0x8b, (byte)0x4f, (byte)0x10, (byte)0xa7, (byte)0x54,
+ (byte)0x9e, (byte)0x8e, (byte)0xed, (byte)0xf5, (byte)0xb4, (byte)0xfc, (byte)0xe0, (byte)0x9e,
+ (byte)0x05, (byte)0x02, (byte)0x21, (byte)0x00, (byte)0x8e, (byte)0x3c, (byte)0x05, (byte)0x21,
+ (byte)0xfe, (byte)0x15, (byte)0xe0, (byte)0xea, (byte)0x06, (byte)0xa3, (byte)0x6f, (byte)0xf0,
+ (byte)0xf1, (byte)0x0c, (byte)0x99, (byte)0x52, (byte)0xc3, (byte)0x5b, (byte)0x7a, (byte)0x75,
+ (byte)0x14, (byte)0xfd, (byte)0x32, (byte)0x38, (byte)0xb8, (byte)0x0a, (byte)0xad, (byte)0x52,
+ (byte)0x98, (byte)0x62, (byte)0x8d, (byte)0x51, (byte)0x02, (byte)0x20, (byte)0x36, (byte)0x3f,
+ (byte)0xf7, (byte)0x18, (byte)0x9d, (byte)0xa8, (byte)0xe9, (byte)0x0b, (byte)0x1d, (byte)0x34,
+ (byte)0x1f, (byte)0x71, (byte)0xd0, (byte)0x9b, (byte)0x76, (byte)0xa8, (byte)0xa9, (byte)0x43,
+ (byte)0xe1, (byte)0x1d, (byte)0x10, (byte)0xb2, (byte)0x4d, (byte)0x24, (byte)0x9f, (byte)0x2d,
+ (byte)0xea, (byte)0xfe, (byte)0xf8, (byte)0x0c, (byte)0x18, (byte)0x26
+ };
+
+ static byte[] output1 =
+ {
+ (byte)0x1b, (byte)0x8f, (byte)0x05, (byte)0xf9, (byte)0xca, (byte)0x1a, (byte)0x79, (byte)0x52,
+ (byte)0x6e, (byte)0x53, (byte)0xf3, (byte)0xcc, (byte)0x51, (byte)0x4f, (byte)0xdb, (byte)0x89,
+ (byte)0x2b, (byte)0xfb, (byte)0x91, (byte)0x93, (byte)0x23, (byte)0x1e, (byte)0x78, (byte)0xb9,
+ (byte)0x92, (byte)0xe6, (byte)0x8d, (byte)0x50, (byte)0xa4, (byte)0x80, (byte)0xcb, (byte)0x52,
+ (byte)0x33, (byte)0x89, (byte)0x5c, (byte)0x74, (byte)0x95, (byte)0x8d, (byte)0x5d, (byte)0x02,
+ (byte)0xab, (byte)0x8c, (byte)0x0f, (byte)0xd0, (byte)0x40, (byte)0xeb, (byte)0x58, (byte)0x44,
+ (byte)0xb0, (byte)0x05, (byte)0xc3, (byte)0x9e, (byte)0xd8, (byte)0x27, (byte)0x4a, (byte)0x9d,
+ (byte)0xbf, (byte)0xa8, (byte)0x06, (byte)0x71, (byte)0x40, (byte)0x94, (byte)0x39, (byte)0xd2
+ };
+
+ static byte[] pubKeyEnc2 =
+ {
+ (byte)0x30, (byte)0x4c, (byte)0x30, (byte)0x0d, (byte)0x06, (byte)0x09, (byte)0x2a, (byte)0x86,
+ (byte)0x48, (byte)0x86, (byte)0xf7, (byte)0x0d, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x05,
+ (byte)0x00, (byte)0x03, (byte)0x3b, (byte)0x00, (byte)0x30, (byte)0x38, (byte)0x02, (byte)0x33,
+ (byte)0x00, (byte)0xa3, (byte)0x07, (byte)0x9a, (byte)0x90, (byte)0xdf, (byte)0x0d, (byte)0xfd,
+ (byte)0x72, (byte)0xac, (byte)0x09, (byte)0x0c, (byte)0xcc, (byte)0x2a, (byte)0x78, (byte)0xb8,
+ (byte)0x74, (byte)0x13, (byte)0x13, (byte)0x3e, (byte)0x40, (byte)0x75, (byte)0x9c, (byte)0x98,
+ (byte)0xfa, (byte)0xf8, (byte)0x20, (byte)0x4f, (byte)0x35, (byte)0x8a, (byte)0x0b, (byte)0x26,
+ (byte)0x3c, (byte)0x67, (byte)0x70, (byte)0xe7, (byte)0x83, (byte)0xa9, (byte)0x3b, (byte)0x69,
+ (byte)0x71, (byte)0xb7, (byte)0x37, (byte)0x79, (byte)0xd2, (byte)0x71, (byte)0x7b, (byte)0xe8,
+ (byte)0x34, (byte)0x77, (byte)0xcf, (byte)0x02, (byte)0x01, (byte)0x03
+ };
+
+ static byte[] privKeyEnc2 =
+ {
+ (byte)0x30, (byte)0x82, (byte)0x01, (byte)0x13, (byte)0x02, (byte)0x01, (byte)0x00, (byte)0x30,
+ (byte)0x0d, (byte)0x06, (byte)0x09, (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0x86, (byte)0xf7,
+ (byte)0x0d, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x05, (byte)0x00, (byte)0x04, (byte)0x81,
+ (byte)0xfe, (byte)0x30, (byte)0x81, (byte)0xfb, (byte)0x02, (byte)0x01, (byte)0x00, (byte)0x02,
+ (byte)0x33, (byte)0x00, (byte)0xa3, (byte)0x07, (byte)0x9a, (byte)0x90, (byte)0xdf, (byte)0x0d,
+ (byte)0xfd, (byte)0x72, (byte)0xac, (byte)0x09, (byte)0x0c, (byte)0xcc, (byte)0x2a, (byte)0x78,
+ (byte)0xb8, (byte)0x74, (byte)0x13, (byte)0x13, (byte)0x3e, (byte)0x40, (byte)0x75, (byte)0x9c,
+ (byte)0x98, (byte)0xfa, (byte)0xf8, (byte)0x20, (byte)0x4f, (byte)0x35, (byte)0x8a, (byte)0x0b,
+ (byte)0x26, (byte)0x3c, (byte)0x67, (byte)0x70, (byte)0xe7, (byte)0x83, (byte)0xa9, (byte)0x3b,
+ (byte)0x69, (byte)0x71, (byte)0xb7, (byte)0x37, (byte)0x79, (byte)0xd2, (byte)0x71, (byte)0x7b,
+ (byte)0xe8, (byte)0x34, (byte)0x77, (byte)0xcf, (byte)0x02, (byte)0x01, (byte)0x03, (byte)0x02,
+ (byte)0x32, (byte)0x6c, (byte)0xaf, (byte)0xbc, (byte)0x60, (byte)0x94, (byte)0xb3, (byte)0xfe,
+ (byte)0x4c, (byte)0x72, (byte)0xb0, (byte)0xb3, (byte)0x32, (byte)0xc6, (byte)0xfb, (byte)0x25,
+ (byte)0xa2, (byte)0xb7, (byte)0x62, (byte)0x29, (byte)0x80, (byte)0x4e, (byte)0x68, (byte)0x65,
+ (byte)0xfc, (byte)0xa4, (byte)0x5a, (byte)0x74, (byte)0xdf, (byte)0x0f, (byte)0x8f, (byte)0xb8,
+ (byte)0x41, (byte)0x3b, (byte)0x52, (byte)0xc0, (byte)0xd0, (byte)0xe5, (byte)0x3d, (byte)0x9b,
+ (byte)0x59, (byte)0x0f, (byte)0xf1, (byte)0x9b, (byte)0xe7, (byte)0x9f, (byte)0x49, (byte)0xdd,
+ (byte)0x21, (byte)0xe5, (byte)0xeb, (byte)0x02, (byte)0x1a, (byte)0x00, (byte)0xcf, (byte)0x20,
+ (byte)0x35, (byte)0x02, (byte)0x8b, (byte)0x9d, (byte)0x86, (byte)0x98, (byte)0x40, (byte)0xb4,
+ (byte)0x16, (byte)0x66, (byte)0xb4, (byte)0x2e, (byte)0x92, (byte)0xea, (byte)0x0d, (byte)0xa3,
+ (byte)0xb4, (byte)0x32, (byte)0x04, (byte)0xb5, (byte)0xcf, (byte)0xce, (byte)0x91, (byte)0x02,
+ (byte)0x1a, (byte)0x00, (byte)0xc9, (byte)0x7f, (byte)0xb1, (byte)0xf0, (byte)0x27, (byte)0xf4,
+ (byte)0x53, (byte)0xf6, (byte)0x34, (byte)0x12, (byte)0x33, (byte)0xea, (byte)0xaa, (byte)0xd1,
+ (byte)0xd9, (byte)0x35, (byte)0x3f, (byte)0x6c, (byte)0x42, (byte)0xd0, (byte)0x88, (byte)0x66,
+ (byte)0xb1, (byte)0xd0, (byte)0x5f, (byte)0x02, (byte)0x1a, (byte)0x00, (byte)0x8a, (byte)0x15,
+ (byte)0x78, (byte)0xac, (byte)0x5d, (byte)0x13, (byte)0xaf, (byte)0x10, (byte)0x2b, (byte)0x22,
+ (byte)0xb9, (byte)0x99, (byte)0xcd, (byte)0x74, (byte)0x61, (byte)0xf1, (byte)0x5e, (byte)0x6d,
+ (byte)0x22, (byte)0xcc, (byte)0x03, (byte)0x23, (byte)0xdf, (byte)0xdf, (byte)0x0b, (byte)0x02,
+ (byte)0x1a, (byte)0x00, (byte)0x86, (byte)0x55, (byte)0x21, (byte)0x4a, (byte)0xc5, (byte)0x4d,
+ (byte)0x8d, (byte)0x4e, (byte)0xcd, (byte)0x61, (byte)0x77, (byte)0xf1, (byte)0xc7, (byte)0x36,
+ (byte)0x90, (byte)0xce, (byte)0x2a, (byte)0x48, (byte)0x2c, (byte)0x8b, (byte)0x05, (byte)0x99,
+ (byte)0xcb, (byte)0xe0, (byte)0x3f, (byte)0x02, (byte)0x1a, (byte)0x00, (byte)0x83, (byte)0xef,
+ (byte)0xef, (byte)0xb8, (byte)0xa9, (byte)0xa4, (byte)0x0d, (byte)0x1d, (byte)0xb6, (byte)0xed,
+ (byte)0x98, (byte)0xad, (byte)0x84, (byte)0xed, (byte)0x13, (byte)0x35, (byte)0xdc, (byte)0xc1,
+ (byte)0x08, (byte)0xf3, (byte)0x22, (byte)0xd0, (byte)0x57, (byte)0xcf, (byte)0x8d
+ };
+
+ static byte[] output2 =
+ {
+ (byte)0x14, (byte)0xbd, (byte)0xdd, (byte)0x28, (byte)0xc9, (byte)0x83, (byte)0x35, (byte)0x19,
+ (byte)0x23, (byte)0x80, (byte)0xe8, (byte)0xe5, (byte)0x49, (byte)0xb1, (byte)0x58, (byte)0x2a,
+ (byte)0x8b, (byte)0x40, (byte)0xb4, (byte)0x48, (byte)0x6d, (byte)0x03, (byte)0xa6, (byte)0xa5,
+ (byte)0x31, (byte)0x1f, (byte)0x1f, (byte)0xd5, (byte)0xf0, (byte)0xa1, (byte)0x80, (byte)0xe4,
+ (byte)0x17, (byte)0x53, (byte)0x03, (byte)0x29, (byte)0xa9, (byte)0x34, (byte)0x90, (byte)0x74,
+ (byte)0xb1, (byte)0x52, (byte)0x13, (byte)0x54, (byte)0x29, (byte)0x08, (byte)0x24, (byte)0x52,
+ (byte)0x62, (byte)0x51
+ };
+
+ static byte[] pubKeyEnc3 =
+ {
+ (byte)0x30, (byte)0x81, (byte)0x9d, (byte)0x30, (byte)0x0d, (byte)0x06, (byte)0x09, (byte)0x2a,
+ (byte)0x86, (byte)0x48, (byte)0x86, (byte)0xf7, (byte)0x0d, (byte)0x01, (byte)0x01, (byte)0x01,
+ (byte)0x05, (byte)0x00, (byte)0x03, (byte)0x81, (byte)0x8b, (byte)0x00, (byte)0x30, (byte)0x81,
+ (byte)0x87, (byte)0x02, (byte)0x81, (byte)0x81, (byte)0x00, (byte)0xbb, (byte)0xf8, (byte)0x2f,
+ (byte)0x09, (byte)0x06, (byte)0x82, (byte)0xce, (byte)0x9c, (byte)0x23, (byte)0x38, (byte)0xac,
+ (byte)0x2b, (byte)0x9d, (byte)0xa8, (byte)0x71, (byte)0xf7, (byte)0x36, (byte)0x8d, (byte)0x07,
+ (byte)0xee, (byte)0xd4, (byte)0x10, (byte)0x43, (byte)0xa4, (byte)0x40, (byte)0xd6, (byte)0xb6,
+ (byte)0xf0, (byte)0x74, (byte)0x54, (byte)0xf5, (byte)0x1f, (byte)0xb8, (byte)0xdf, (byte)0xba,
+ (byte)0xaf, (byte)0x03, (byte)0x5c, (byte)0x02, (byte)0xab, (byte)0x61, (byte)0xea, (byte)0x48,
+ (byte)0xce, (byte)0xeb, (byte)0x6f, (byte)0xcd, (byte)0x48, (byte)0x76, (byte)0xed, (byte)0x52,
+ (byte)0x0d, (byte)0x60, (byte)0xe1, (byte)0xec, (byte)0x46, (byte)0x19, (byte)0x71, (byte)0x9d,
+ (byte)0x8a, (byte)0x5b, (byte)0x8b, (byte)0x80, (byte)0x7f, (byte)0xaf, (byte)0xb8, (byte)0xe0,
+ (byte)0xa3, (byte)0xdf, (byte)0xc7, (byte)0x37, (byte)0x72, (byte)0x3e, (byte)0xe6, (byte)0xb4,
+ (byte)0xb7, (byte)0xd9, (byte)0x3a, (byte)0x25, (byte)0x84, (byte)0xee, (byte)0x6a, (byte)0x64,
+ (byte)0x9d, (byte)0x06, (byte)0x09, (byte)0x53, (byte)0x74, (byte)0x88, (byte)0x34, (byte)0xb2,
+ (byte)0x45, (byte)0x45, (byte)0x98, (byte)0x39, (byte)0x4e, (byte)0xe0, (byte)0xaa, (byte)0xb1,
+ (byte)0x2d, (byte)0x7b, (byte)0x61, (byte)0xa5, (byte)0x1f, (byte)0x52, (byte)0x7a, (byte)0x9a,
+ (byte)0x41, (byte)0xf6, (byte)0xc1, (byte)0x68, (byte)0x7f, (byte)0xe2, (byte)0x53, (byte)0x72,
+ (byte)0x98, (byte)0xca, (byte)0x2a, (byte)0x8f, (byte)0x59, (byte)0x46, (byte)0xf8, (byte)0xe5,
+ (byte)0xfd, (byte)0x09, (byte)0x1d, (byte)0xbd, (byte)0xcb, (byte)0x02, (byte)0x01, (byte)0x11
+ };
+
+ static byte[] privKeyEnc3 =
+ {
+ (byte)0x30, (byte)0x82, (byte)0x02, (byte)0x75, (byte)0x02, (byte)0x01, (byte)0x00, (byte)0x30,
+ (byte)0x0d, (byte)0x06, (byte)0x09, (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0x86, (byte)0xf7,
+ (byte)0x0d, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x05, (byte)0x00, (byte)0x04, (byte)0x82,
+ (byte)0x02, (byte)0x5f, (byte)0x30, (byte)0x82, (byte)0x02, (byte)0x5b, (byte)0x02, (byte)0x01,
+ (byte)0x00, (byte)0x02, (byte)0x81, (byte)0x81, (byte)0x00, (byte)0xbb, (byte)0xf8, (byte)0x2f,
+ (byte)0x09, (byte)0x06, (byte)0x82, (byte)0xce, (byte)0x9c, (byte)0x23, (byte)0x38, (byte)0xac,
+ (byte)0x2b, (byte)0x9d, (byte)0xa8, (byte)0x71, (byte)0xf7, (byte)0x36, (byte)0x8d, (byte)0x07,
+ (byte)0xee, (byte)0xd4, (byte)0x10, (byte)0x43, (byte)0xa4, (byte)0x40, (byte)0xd6, (byte)0xb6,
+ (byte)0xf0, (byte)0x74, (byte)0x54, (byte)0xf5, (byte)0x1f, (byte)0xb8, (byte)0xdf, (byte)0xba,
+ (byte)0xaf, (byte)0x03, (byte)0x5c, (byte)0x02, (byte)0xab, (byte)0x61, (byte)0xea, (byte)0x48,
+ (byte)0xce, (byte)0xeb, (byte)0x6f, (byte)0xcd, (byte)0x48, (byte)0x76, (byte)0xed, (byte)0x52,
+ (byte)0x0d, (byte)0x60, (byte)0xe1, (byte)0xec, (byte)0x46, (byte)0x19, (byte)0x71, (byte)0x9d,
+ (byte)0x8a, (byte)0x5b, (byte)0x8b, (byte)0x80, (byte)0x7f, (byte)0xaf, (byte)0xb8, (byte)0xe0,
+ (byte)0xa3, (byte)0xdf, (byte)0xc7, (byte)0x37, (byte)0x72, (byte)0x3e, (byte)0xe6, (byte)0xb4,
+ (byte)0xb7, (byte)0xd9, (byte)0x3a, (byte)0x25, (byte)0x84, (byte)0xee, (byte)0x6a, (byte)0x64,
+ (byte)0x9d, (byte)0x06, (byte)0x09, (byte)0x53, (byte)0x74, (byte)0x88, (byte)0x34, (byte)0xb2,
+ (byte)0x45, (byte)0x45, (byte)0x98, (byte)0x39, (byte)0x4e, (byte)0xe0, (byte)0xaa, (byte)0xb1,
+ (byte)0x2d, (byte)0x7b, (byte)0x61, (byte)0xa5, (byte)0x1f, (byte)0x52, (byte)0x7a, (byte)0x9a,
+ (byte)0x41, (byte)0xf6, (byte)0xc1, (byte)0x68, (byte)0x7f, (byte)0xe2, (byte)0x53, (byte)0x72,
+ (byte)0x98, (byte)0xca, (byte)0x2a, (byte)0x8f, (byte)0x59, (byte)0x46, (byte)0xf8, (byte)0xe5,
+ (byte)0xfd, (byte)0x09, (byte)0x1d, (byte)0xbd, (byte)0xcb, (byte)0x02, (byte)0x01, (byte)0x11,
+ (byte)0x02, (byte)0x81, (byte)0x81, (byte)0x00, (byte)0xa5, (byte)0xda, (byte)0xfc, (byte)0x53,
+ (byte)0x41, (byte)0xfa, (byte)0xf2, (byte)0x89, (byte)0xc4, (byte)0xb9, (byte)0x88, (byte)0xdb,
+ (byte)0x30, (byte)0xc1, (byte)0xcd, (byte)0xf8, (byte)0x3f, (byte)0x31, (byte)0x25, (byte)0x1e,
+ (byte)0x06, (byte)0x68, (byte)0xb4, (byte)0x27, (byte)0x84, (byte)0x81, (byte)0x38, (byte)0x01,
+ (byte)0x57, (byte)0x96, (byte)0x41, (byte)0xb2, (byte)0x94, (byte)0x10, (byte)0xb3, (byte)0xc7,
+ (byte)0x99, (byte)0x8d, (byte)0x6b, (byte)0xc4, (byte)0x65, (byte)0x74, (byte)0x5e, (byte)0x5c,
+ (byte)0x39, (byte)0x26, (byte)0x69, (byte)0xd6, (byte)0x87, (byte)0x0d, (byte)0xa2, (byte)0xc0,
+ (byte)0x82, (byte)0xa9, (byte)0x39, (byte)0xe3, (byte)0x7f, (byte)0xdc, (byte)0xb8, (byte)0x2e,
+ (byte)0xc9, (byte)0x3e, (byte)0xda, (byte)0xc9, (byte)0x7f, (byte)0xf3, (byte)0xad, (byte)0x59,
+ (byte)0x50, (byte)0xac, (byte)0xcf, (byte)0xbc, (byte)0x11, (byte)0x1c, (byte)0x76, (byte)0xf1,
+ (byte)0xa9, (byte)0x52, (byte)0x94, (byte)0x44, (byte)0xe5, (byte)0x6a, (byte)0xaf, (byte)0x68,
+ (byte)0xc5, (byte)0x6c, (byte)0x09, (byte)0x2c, (byte)0xd3, (byte)0x8d, (byte)0xc3, (byte)0xbe,
+ (byte)0xf5, (byte)0xd2, (byte)0x0a, (byte)0x93, (byte)0x99, (byte)0x26, (byte)0xed, (byte)0x4f,
+ (byte)0x74, (byte)0xa1, (byte)0x3e, (byte)0xdd, (byte)0xfb, (byte)0xe1, (byte)0xa1, (byte)0xce,
+ (byte)0xcc, (byte)0x48, (byte)0x94, (byte)0xaf, (byte)0x94, (byte)0x28, (byte)0xc2, (byte)0xb7,
+ (byte)0xb8, (byte)0x88, (byte)0x3f, (byte)0xe4, (byte)0x46, (byte)0x3a, (byte)0x4b, (byte)0xc8,
+ (byte)0x5b, (byte)0x1c, (byte)0xb3, (byte)0xc1, (byte)0x02, (byte)0x41, (byte)0x00, (byte)0xee,
+ (byte)0xcf, (byte)0xae, (byte)0x81, (byte)0xb1, (byte)0xb9, (byte)0xb3, (byte)0xc9, (byte)0x08,
+ (byte)0x81, (byte)0x0b, (byte)0x10, (byte)0xa1, (byte)0xb5, (byte)0x60, (byte)0x01, (byte)0x99,
+ (byte)0xeb, (byte)0x9f, (byte)0x44, (byte)0xae, (byte)0xf4, (byte)0xfd, (byte)0xa4, (byte)0x93,
+ (byte)0xb8, (byte)0x1a, (byte)0x9e, (byte)0x3d, (byte)0x84, (byte)0xf6, (byte)0x32, (byte)0x12,
+ (byte)0x4e, (byte)0xf0, (byte)0x23, (byte)0x6e, (byte)0x5d, (byte)0x1e, (byte)0x3b, (byte)0x7e,
+ (byte)0x28, (byte)0xfa, (byte)0xe7, (byte)0xaa, (byte)0x04, (byte)0x0a, (byte)0x2d, (byte)0x5b,
+ (byte)0x25, (byte)0x21, (byte)0x76, (byte)0x45, (byte)0x9d, (byte)0x1f, (byte)0x39, (byte)0x75,
+ (byte)0x41, (byte)0xba, (byte)0x2a, (byte)0x58, (byte)0xfb, (byte)0x65, (byte)0x99, (byte)0x02,
+ (byte)0x41, (byte)0x00, (byte)0xc9, (byte)0x7f, (byte)0xb1, (byte)0xf0, (byte)0x27, (byte)0xf4,
+ (byte)0x53, (byte)0xf6, (byte)0x34, (byte)0x12, (byte)0x33, (byte)0xea, (byte)0xaa, (byte)0xd1,
+ (byte)0xd9, (byte)0x35, (byte)0x3f, (byte)0x6c, (byte)0x42, (byte)0xd0, (byte)0x88, (byte)0x66,
+ (byte)0xb1, (byte)0xd0, (byte)0x5a, (byte)0x0f, (byte)0x20, (byte)0x35, (byte)0x02, (byte)0x8b,
+ (byte)0x9d, (byte)0x86, (byte)0x98, (byte)0x40, (byte)0xb4, (byte)0x16, (byte)0x66, (byte)0xb4,
+ (byte)0x2e, (byte)0x92, (byte)0xea, (byte)0x0d, (byte)0xa3, (byte)0xb4, (byte)0x32, (byte)0x04,
+ (byte)0xb5, (byte)0xcf, (byte)0xce, (byte)0x33, (byte)0x52, (byte)0x52, (byte)0x4d, (byte)0x04,
+ (byte)0x16, (byte)0xa5, (byte)0xa4, (byte)0x41, (byte)0xe7, (byte)0x00, (byte)0xaf, (byte)0x46,
+ (byte)0x15, (byte)0x03, (byte)0x02, (byte)0x40, (byte)0x54, (byte)0x49, (byte)0x4c, (byte)0xa6,
+ (byte)0x3e, (byte)0xba, (byte)0x03, (byte)0x37, (byte)0xe4, (byte)0xe2, (byte)0x40, (byte)0x23,
+ (byte)0xfc, (byte)0xd6, (byte)0x9a, (byte)0x5a, (byte)0xeb, (byte)0x07, (byte)0xdd, (byte)0xdc,
+ (byte)0x01, (byte)0x83, (byte)0xa4, (byte)0xd0, (byte)0xac, (byte)0x9b, (byte)0x54, (byte)0xb0,
+ (byte)0x51, (byte)0xf2, (byte)0xb1, (byte)0x3e, (byte)0xd9, (byte)0x49, (byte)0x09, (byte)0x75,
+ (byte)0xea, (byte)0xb7, (byte)0x74, (byte)0x14, (byte)0xff, (byte)0x59, (byte)0xc1, (byte)0xf7,
+ (byte)0x69, (byte)0x2e, (byte)0x9a, (byte)0x2e, (byte)0x20, (byte)0x2b, (byte)0x38, (byte)0xfc,
+ (byte)0x91, (byte)0x0a, (byte)0x47, (byte)0x41, (byte)0x74, (byte)0xad, (byte)0xc9, (byte)0x3c,
+ (byte)0x1f, (byte)0x67, (byte)0xc9, (byte)0x81, (byte)0x02, (byte)0x40, (byte)0x47, (byte)0x1e,
+ (byte)0x02, (byte)0x90, (byte)0xff, (byte)0x0a, (byte)0xf0, (byte)0x75, (byte)0x03, (byte)0x51,
+ (byte)0xb7, (byte)0xf8, (byte)0x78, (byte)0x86, (byte)0x4c, (byte)0xa9, (byte)0x61, (byte)0xad,
+ (byte)0xbd, (byte)0x3a, (byte)0x8a, (byte)0x7e, (byte)0x99, (byte)0x1c, (byte)0x5c, (byte)0x05,
+ (byte)0x56, (byte)0xa9, (byte)0x4c, (byte)0x31, (byte)0x46, (byte)0xa7, (byte)0xf9, (byte)0x80,
+ (byte)0x3f, (byte)0x8f, (byte)0x6f, (byte)0x8a, (byte)0xe3, (byte)0x42, (byte)0xe9, (byte)0x31,
+ (byte)0xfd, (byte)0x8a, (byte)0xe4, (byte)0x7a, (byte)0x22, (byte)0x0d, (byte)0x1b, (byte)0x99,
+ (byte)0xa4, (byte)0x95, (byte)0x84, (byte)0x98, (byte)0x07, (byte)0xfe, (byte)0x39, (byte)0xf9,
+ (byte)0x24, (byte)0x5a, (byte)0x98, (byte)0x36, (byte)0xda, (byte)0x3d, (byte)0x02, (byte)0x41,
+ (byte)0x00, (byte)0xb0, (byte)0x6c, (byte)0x4f, (byte)0xda, (byte)0xbb, (byte)0x63, (byte)0x01,
+ (byte)0x19, (byte)0x8d, (byte)0x26, (byte)0x5b, (byte)0xdb, (byte)0xae, (byte)0x94, (byte)0x23,
+ (byte)0xb3, (byte)0x80, (byte)0xf2, (byte)0x71, (byte)0xf7, (byte)0x34, (byte)0x53, (byte)0x88,
+ (byte)0x50, (byte)0x93, (byte)0x07, (byte)0x7f, (byte)0xcd, (byte)0x39, (byte)0xe2, (byte)0x11,
+ (byte)0x9f, (byte)0xc9, (byte)0x86, (byte)0x32, (byte)0x15, (byte)0x4f, (byte)0x58, (byte)0x83,
+ (byte)0xb1, (byte)0x67, (byte)0xa9, (byte)0x67, (byte)0xbf, (byte)0x40, (byte)0x2b, (byte)0x4e,
+ (byte)0x9e, (byte)0x2e, (byte)0x0f, (byte)0x96, (byte)0x56, (byte)0xe6, (byte)0x98, (byte)0xea,
+ (byte)0x36, (byte)0x66, (byte)0xed, (byte)0xfb, (byte)0x25, (byte)0x79, (byte)0x80, (byte)0x39,
+ (byte)0xf7
+ };
+
+ static byte[] output3 = Hex.decode(
+ "b8246b56a6ed5881aeb585d9a25b2ad790c417e080681bf1ac2bc3deb69d8bce"
+ + "f0c4366fec400af052a72e9b0effb5b3f2f192dbeaca03c12740057113bf1f06"
+ + "69ac22e9f3a7852e3c15d913cab0b8863a95c99294ce8674214954610346f4d4"
+ + "74b26f7c48b42ee68e1f572a1fc4026ac456b4f59f7b621ea1b9d88f64202fb1");
+
+ byte[] seed = {
+ (byte)0xaa, (byte)0xfd, (byte)0x12, (byte)0xf6, (byte)0x59,
+ (byte)0xca, (byte)0xe6, (byte)0x34, (byte)0x89, (byte)0xb4,
+ (byte)0x79, (byte)0xe5, (byte)0x07, (byte)0x6d, (byte)0xde,
+ (byte)0xc2, (byte)0xf0, (byte)0x6c, (byte)0xb5, (byte)0x8f
+ };
+
+ private class VecRand extends SecureRandom
+ {
+ byte[] seed;
+
+ VecRand(byte[] seed)
+ {
+ this.seed = seed;
+ }
+
+ public void nextBytes(
+ byte[] bytes)
+ {
+ System.arraycopy(seed, 0, bytes, 0, bytes.length);
+ }
+ }
+
+ private void baseOaepTest(
+ int id,
+ byte[] pubKeyEnc,
+ byte[] privKeyEnc,
+ byte[] output)
+ throws Exception
+ {
+ ByteArrayInputStream bIn = new ByteArrayInputStream(pubKeyEnc);
+ ASN1InputStream dIn = new ASN1InputStream(bIn);
+
+ //
+ // extract the public key info.
+ //
+ RSAPublicKey pubStruct;
+
+ pubStruct = RSAPublicKey.getInstance(new SubjectPublicKeyInfo((ASN1Sequence)dIn.readObject()).parsePublicKey());
+
+
+ bIn = new ByteArrayInputStream(privKeyEnc);
+ dIn = new ASN1InputStream(bIn);
+
+ //
+ // extract the private key info.
+ //
+ RSAPrivateKey privStruct;
+
+ privStruct = RSAPrivateKey.getInstance(new PrivateKeyInfo((ASN1Sequence)dIn.readObject()).parsePrivateKey());
+
+ RSAKeyParameters pubParameters = new RSAKeyParameters(
+ false,
+ pubStruct.getModulus(),
+ pubStruct.getPublicExponent());
+
+ RSAKeyParameters privParameters = new RSAPrivateCrtKeyParameters(
+ privStruct.getModulus(),
+ privStruct.getPublicExponent(),
+ privStruct.getPrivateExponent(),
+ privStruct.getPrime1(),
+ privStruct.getPrime2(),
+ privStruct.getExponent1(),
+ privStruct.getExponent2(),
+ privStruct.getCoefficient());
+
+ byte[] input = new byte[]
+ { (byte)0x54, (byte)0x85, (byte)0x9b, (byte)0x34, (byte)0x2c, (byte)0x49, (byte)0xea, (byte)0x2a };
+
+ encDec("id(" + id + ")", pubParameters, privParameters, seed, input, output);
+
+ }
+
+ private void encDec(
+ String label,
+ RSAKeyParameters pubParameters,
+ RSAKeyParameters privParameters,
+ byte[] seed,
+ byte[] input,
+ byte[] output)
+ throws InvalidCipherTextException
+ {
+ AsymmetricBlockCipher cipher = new OAEPEncoding(new RSAEngine());
+
+ cipher.init(true, new ParametersWithRandom(pubParameters, new VecRand(seed)));
+
+ byte[] out;
+
+ out = cipher.processBlock(input, 0, input.length);
+
+ for (int i = 0; i != output.length; i++)
+ {
+ if (out[i] != output[i])
+ {
+ fail(label + " failed encryption");
+ }
+ }
+
+ cipher.init(false, privParameters);
+
+ out = cipher.processBlock(output, 0, output.length);
+
+ for (int i = 0; i != input.length; i++)
+ {
+ if (out[i] != input[i])
+ {
+ fail(label + " failed decoding");
+ }
+ }
+ }
+
+ /*
+ * RSA vector tests from PKCS#1 page
+ */
+ byte[] modulus_1024 = Hex.decode(
+ "a8b3b284af8eb50b387034a860f146c4"
+ + "919f318763cd6c5598c8ae4811a1e0ab"
+ + "c4c7e0b082d693a5e7fced675cf46685"
+ + "12772c0cbc64a742c6c630f533c8cc72"
+ + "f62ae833c40bf25842e984bb78bdbf97"
+ + "c0107d55bdb662f5c4e0fab9845cb514"
+ + "8ef7392dd3aaff93ae1e6b667bb3d424"
+ + "7616d4f5ba10d4cfd226de88d39f16fb");
+
+ byte[] pubExp_1024 = Hex.decode(
+ "010001");
+
+ byte[] privExp_1024 = Hex.decode(
+ "53339cfdb79fc8466a655c7316aca85c"
+ + "55fd8f6dd898fdaf119517ef4f52e8fd"
+ + "8e258df93fee180fa0e4ab29693cd83b"
+ + "152a553d4ac4d1812b8b9fa5af0e7f55"
+ + "fe7304df41570926f3311f15c4d65a73"
+ + "2c483116ee3d3d2d0af3549ad9bf7cbf"
+ + "b78ad884f84d5beb04724dc7369b31de"
+ + "f37d0cf539e9cfcdd3de653729ead5d1");
+
+ byte[] prime1_1024 = Hex.decode(
+ "d32737e7267ffe1341b2d5c0d150a81b"
+ + "586fb3132bed2f8d5262864a9cb9f30a"
+ + "f38be448598d413a172efb802c21acf1"
+ + "c11c520c2f26a471dcad212eac7ca39d");
+
+ byte[] prime2_1024 = Hex.decode(
+ "cc8853d1d54da630fac004f471f281c7"
+ + "b8982d8224a490edbeb33d3e3d5cc93c"
+ + "4765703d1dd791642f1f116a0dd852be"
+ + "2419b2af72bfe9a030e860b0288b5d77");
+
+ byte[] primeExp1_1024 = Hex.decode(
+ "0e12bf1718e9cef5599ba1c3882fe804"
+ + "6a90874eefce8f2ccc20e4f2741fb0a3"
+ + "3a3848aec9c9305fbecbd2d76819967d"
+ + "4671acc6431e4037968db37878e695c1");
+
+ byte[] primeExp2_1024 = Hex.decode(
+ "95297b0f95a2fa67d00707d609dfd4fc"
+ + "05c89dafc2ef6d6ea55bec771ea33373"
+ + "4d9251e79082ecda866efef13c459e1a"
+ + "631386b7e354c899f5f112ca85d71583");
+
+ byte[] crtCoef_1024 = Hex.decode(
+ "4f456c502493bdc0ed2ab756a3a6ed4d"
+ + "67352a697d4216e93212b127a63d5411"
+ + "ce6fa98d5dbefd73263e372814274381"
+ + "8166ed7dd63687dd2a8ca1d2f4fbd8e1");
+
+ byte[] input_1024_1 = Hex.decode(
+ "6628194e12073db03ba94cda9ef95323"
+ + "97d50dba79b987004afefe34");
+
+ byte[] seed_1024_1 = Hex.decode(
+ "18b776ea21069d69776a33e96bad48e1"
+ + "dda0a5ef");
+
+ byte[] output_1024_1 = Hex.decode(
+ "354fe67b4a126d5d35fe36c777791a3f"
+ + "7ba13def484e2d3908aff722fad468fb"
+ + "21696de95d0be911c2d3174f8afcc201"
+ + "035f7b6d8e69402de5451618c21a535f"
+ + "a9d7bfc5b8dd9fc243f8cf927db31322"
+ + "d6e881eaa91a996170e657a05a266426"
+ + "d98c88003f8477c1227094a0d9fa1e8c"
+ + "4024309ce1ecccb5210035d47ac72e8a");
+
+ byte[] input_1024_2 = Hex.decode(
+ "750c4047f547e8e41411856523298ac9"
+ + "bae245efaf1397fbe56f9dd5");
+
+ byte[] seed_1024_2 = Hex.decode(
+ "0cc742ce4a9b7f32f951bcb251efd925"
+ + "fe4fe35f");
+
+ byte[] output_1024_2 = Hex.decode(
+ "640db1acc58e0568fe5407e5f9b701df"
+ + "f8c3c91e716c536fc7fcec6cb5b71c11"
+ + "65988d4a279e1577d730fc7a29932e3f"
+ + "00c81515236d8d8e31017a7a09df4352"
+ + "d904cdeb79aa583adcc31ea698a4c052"
+ + "83daba9089be5491f67c1a4ee48dc74b"
+ + "bbe6643aef846679b4cb395a352d5ed1"
+ + "15912df696ffe0702932946d71492b44");
+
+ byte[] input_1024_3 = Hex.decode(
+ "d94ae0832e6445ce42331cb06d531a82"
+ + "b1db4baad30f746dc916df24d4e3c245"
+ + "1fff59a6423eb0e1d02d4fe646cf699d"
+ + "fd818c6e97b051");
+
+ byte[] seed_1024_3 = Hex.decode(
+ "2514df4695755a67b288eaf4905c36ee"
+ + "c66fd2fd");
+
+ byte[] output_1024_3 = Hex.decode(
+ "423736ed035f6026af276c35c0b3741b"
+ + "365e5f76ca091b4e8c29e2f0befee603"
+ + "595aa8322d602d2e625e95eb81b2f1c9"
+ + "724e822eca76db8618cf09c5343503a4"
+ + "360835b5903bc637e3879fb05e0ef326"
+ + "85d5aec5067cd7cc96fe4b2670b6eac3"
+ + "066b1fcf5686b68589aafb7d629b02d8"
+ + "f8625ca3833624d4800fb081b1cf94eb");
+
+ byte[] input_1024_4 = Hex.decode(
+ "52e650d98e7f2a048b4f86852153b97e"
+ + "01dd316f346a19f67a85");
+
+ byte[] seed_1024_4 = Hex.decode(
+ "c4435a3e1a18a68b6820436290a37cef"
+ + "b85db3fb");
+
+ byte[] output_1024_4 = Hex.decode(
+ "45ead4ca551e662c9800f1aca8283b05"
+ + "25e6abae30be4b4aba762fa40fd3d38e"
+ + "22abefc69794f6ebbbc05ddbb1121624"
+ + "7d2f412fd0fba87c6e3acd888813646f"
+ + "d0e48e785204f9c3f73d6d8239562722"
+ + "dddd8771fec48b83a31ee6f592c4cfd4"
+ + "bc88174f3b13a112aae3b9f7b80e0fc6"
+ + "f7255ba880dc7d8021e22ad6a85f0755");
+
+ byte[] input_1024_5 = Hex.decode(
+ "8da89fd9e5f974a29feffb462b49180f"
+ + "6cf9e802");
+
+ byte[] seed_1024_5 = Hex.decode(
+ "b318c42df3be0f83fea823f5a7b47ed5"
+ + "e425a3b5");
+
+ byte[] output_1024_5 = Hex.decode(
+ "36f6e34d94a8d34daacba33a2139d00a"
+ + "d85a9345a86051e73071620056b920e2"
+ + "19005855a213a0f23897cdcd731b4525"
+ + "7c777fe908202befdd0b58386b1244ea"
+ + "0cf539a05d5d10329da44e13030fd760"
+ + "dcd644cfef2094d1910d3f433e1c7c6d"
+ + "d18bc1f2df7f643d662fb9dd37ead905"
+ + "9190f4fa66ca39e869c4eb449cbdc439");
+
+ byte[] input_1024_6 = Hex.decode(
+ "26521050844271");
+
+ byte[] seed_1024_6 = Hex.decode(
+ "e4ec0982c2336f3a677f6a356174eb0c"
+ + "e887abc2");
+
+ byte[] output_1024_6 = Hex.decode(
+ "42cee2617b1ecea4db3f4829386fbd61"
+ + "dafbf038e180d837c96366df24c097b4"
+ + "ab0fac6bdf590d821c9f10642e681ad0"
+ + "5b8d78b378c0f46ce2fad63f74e0ad3d"
+ + "f06b075d7eb5f5636f8d403b9059ca76"
+ + "1b5c62bb52aa45002ea70baace08ded2"
+ + "43b9d8cbd62a68ade265832b56564e43"
+ + "a6fa42ed199a099769742df1539e8255");
+
+ byte[] modulus_1027 = Hex.decode(
+ "051240b6cc0004fa48d0134671c078c7"
+ + "c8dec3b3e2f25bc2564467339db38853"
+ + "d06b85eea5b2de353bff42ac2e46bc97"
+ + "fae6ac9618da9537a5c8f553c1e35762"
+ + "5991d6108dcd7885fb3a25413f53efca"
+ + "d948cb35cd9b9ae9c1c67626d113d57d"
+ + "de4c5bea76bb5bb7de96c00d07372e96"
+ + "85a6d75cf9d239fa148d70931b5f3fb0"
+ + "39");
+
+ byte[] pubExp_1027 = Hex.decode(
+ "010001");
+
+ byte[] privExp_1027 = Hex.decode(
+ "0411ffca3b7ca5e9e9be7fe38a85105e"
+ + "353896db05c5796aecd2a725161eb365"
+ + "1c8629a9b862b904d7b0c7b37f8cb5a1"
+ + "c2b54001018a00a1eb2cafe4ee4e9492"
+ + "c348bc2bedab4b9ebbf064e8eff322b9"
+ + "009f8eec653905f40df88a3cdc49d456"
+ + "7f75627d41aca624129b46a0b7c698e5"
+ + "e65f2b7ba102c749a10135b6540d0401");
+
+ byte[] prime1_1027 = Hex.decode(
+ "027458c19ec1636919e736c9af25d609"
+ + "a51b8f561d19c6bf6943dd1ee1ab8a4a"
+ + "3f232100bd40b88decc6ba235548b6ef"
+ + "792a11c9de823d0a7922c7095b6eba57"
+ + "01");
+
+ byte[] prime2_1027 = Hex.decode(
+ "0210ee9b33ab61716e27d251bd465f4b"
+ + "35a1a232e2da00901c294bf22350ce49"
+ + "0d099f642b5375612db63ba1f2038649"
+ + "2bf04d34b3c22bceb909d13441b53b51"
+ + "39");
+
+ byte[] primeExp1_1027 = Hex.decode(
+ "39fa028b826e88c1121b750a8b242fa9"
+ + "a35c5b66bdfd1fa637d3cc48a84a4f45"
+ + "7a194e7727e49f7bcc6e5a5a412657fc"
+ + "470c7322ebc37416ef458c307a8c0901");
+
+ byte[] primeExp2_1027 = Hex.decode(
+ "015d99a84195943979fa9e1be2c3c1b6"
+ + "9f432f46fd03e47d5befbbbfd6b1d137"
+ + "1d83efb330a3e020942b2fed115e5d02"
+ + "be24fd92c9019d1cecd6dd4cf1e54cc8"
+ + "99");
+
+ byte[] crtCoef_1027 = Hex.decode(
+ "01f0b7015170b3f5e42223ba30301c41"
+ + "a6d87cbb70e30cb7d3c67d25473db1f6"
+ + "cbf03e3f9126e3e97968279a865b2c2b"
+ + "426524cfc52a683d31ed30eb984be412"
+ + "ba");
+
+ byte[] input_1027_1 = Hex.decode(
+ "4a86609534ee434a6cbca3f7e962e76d"
+ + "455e3264c19f605f6e5ff6137c65c56d"
+ + "7fb344cd52bc93374f3d166c9f0c6f9c"
+ + "506bad19330972d2");
+
+ byte[] seed_1027_1 = Hex.decode(
+ "1cac19ce993def55f98203f6852896c9"
+ + "5ccca1f3");
+
+ byte[] output_1027_1 = Hex.decode(
+ "04cce19614845e094152a3fe18e54e33"
+ + "30c44e5efbc64ae16886cb1869014cc5"
+ + "781b1f8f9e045384d0112a135ca0d12e"
+ + "9c88a8e4063416deaae3844f60d6e96f"
+ + "e155145f4525b9a34431ca3766180f70"
+ + "e15a5e5d8e8b1a516ff870609f13f896"
+ + "935ced188279a58ed13d07114277d75c"
+ + "6568607e0ab092fd803a223e4a8ee0b1"
+ + "a8");
+
+ byte[] input_1027_2 = Hex.decode(
+ "b0adc4f3fe11da59ce992773d9059943"
+ + "c03046497ee9d9f9a06df1166db46d98"
+ + "f58d27ec074c02eee6cbe2449c8b9fc5"
+ + "080c5c3f4433092512ec46aa793743c8");
+
+ byte[] seed_1027_2 = Hex.decode(
+ "f545d5897585e3db71aa0cb8da76c51d"
+ + "032ae963");
+
+ byte[] output_1027_2 = Hex.decode(
+ "0097b698c6165645b303486fbf5a2a44"
+ + "79c0ee85889b541a6f0b858d6b6597b1"
+ + "3b854eb4f839af03399a80d79bda6578"
+ + "c841f90d645715b280d37143992dd186"
+ + "c80b949b775cae97370e4ec97443136c"
+ + "6da484e970ffdb1323a20847821d3b18"
+ + "381de13bb49aaea66530c4a4b8271f3e"
+ + "ae172cd366e07e6636f1019d2a28aed1"
+ + "5e");
+
+ byte[] input_1027_3 = Hex.decode(
+ "bf6d42e701707b1d0206b0c8b45a1c72"
+ + "641ff12889219a82bdea965b5e79a96b"
+ + "0d0163ed9d578ec9ada20f2fbcf1ea3c"
+ + "4089d83419ba81b0c60f3606da99");
+
+ byte[] seed_1027_3 = Hex.decode(
+ "ad997feef730d6ea7be60d0dc52e72ea"
+ + "cbfdd275");
+
+ byte[] output_1027_3 = Hex.decode(
+ "0301f935e9c47abcb48acbbe09895d9f"
+ + "5971af14839da4ff95417ee453d1fd77"
+ + "319072bb7297e1b55d7561cd9d1bb24c"
+ + "1a9a37c619864308242804879d86ebd0"
+ + "01dce5183975e1506989b70e5a834341"
+ + "54d5cbfd6a24787e60eb0c658d2ac193"
+ + "302d1192c6e622d4a12ad4b53923bca2"
+ + "46df31c6395e37702c6a78ae081fb9d0"
+ + "65");
+
+ byte[] input_1027_4 = Hex.decode(
+ "fb2ef112f5e766eb94019297934794f7"
+ + "be2f6fc1c58e");
+
+ byte[] seed_1027_4 = Hex.decode(
+ "136454df5730f73c807a7e40d8c1a312"
+ + "ac5b9dd3");
+
+ byte[] output_1027_4 = Hex.decode(
+ "02d110ad30afb727beb691dd0cf17d0a"
+ + "f1a1e7fa0cc040ec1a4ba26a42c59d0a"
+ + "796a2e22c8f357ccc98b6519aceb682e"
+ + "945e62cb734614a529407cd452bee3e4"
+ + "4fece8423cc19e55548b8b994b849c7e"
+ + "cde4933e76037e1d0ce44275b08710c6"
+ + "8e430130b929730ed77e09b015642c55"
+ + "93f04e4ffb9410798102a8e96ffdfe11"
+ + "e4");
+
+ byte[] input_1027_5 = Hex.decode(
+ "28ccd447bb9e85166dabb9e5b7d1adad"
+ + "c4b9d39f204e96d5e440ce9ad928bc1c"
+ + "2284");
+
+ byte[] seed_1027_5 = Hex.decode(
+ "bca8057f824b2ea257f2861407eef63d"
+ + "33208681");
+
+ byte[] output_1027_5 = Hex.decode(
+ "00dbb8a7439d90efd919a377c54fae8f"
+ + "e11ec58c3b858362e23ad1b8a4431079"
+ + "9066b99347aa525691d2adc58d9b06e3"
+ + "4f288c170390c5f0e11c0aa3645959f1"
+ + "8ee79e8f2be8d7ac5c23d061f18dd74b"
+ + "8c5f2a58fcb5eb0c54f99f01a8324756"
+ + "8292536583340948d7a8c97c4acd1e98"
+ + "d1e29dc320e97a260532a8aa7a758a1e"
+ + "c2");
+
+ byte[] input_1027_6 = Hex.decode(
+ "f22242751ec6b1");
+
+ byte[] seed_1027_6 = Hex.decode(
+ "2e7e1e17f647b5ddd033e15472f90f68"
+ + "12f3ac4e");
+
+ byte[] output_1027_6 = Hex.decode(
+ "00a5ffa4768c8bbecaee2db77e8f2eec"
+ + "99595933545520835e5ba7db9493d3e1"
+ + "7cddefe6a5f567624471908db4e2d83a"
+ + "0fbee60608fc84049503b2234a07dc83"
+ + "b27b22847ad8920ff42f674ef79b7628"
+ + "0b00233d2b51b8cb2703a9d42bfbc825"
+ + "0c96ec32c051e57f1b4ba528db89c37e"
+ + "4c54e27e6e64ac69635ae887d9541619"
+ + "a9");
+
+ private void oaepVecTest(
+ int keySize,
+ int no,
+ RSAKeyParameters pubParam,
+ RSAKeyParameters privParam,
+ byte[] seed,
+ byte[] input,
+ byte[] output)
+ throws Exception
+ {
+ encDec(keySize + " " + no, pubParam, privParam, seed, input, output);
+ }
+
+ public OAEPTest()
+ {
+ }
+
+ public String getName()
+ {
+ return "OAEP";
+ }
+
+ public void performTest() throws Exception
+ {
+ baseOaepTest(1, pubKeyEnc1, privKeyEnc1, output1);
+ baseOaepTest(2, pubKeyEnc2, privKeyEnc2, output2);
+ baseOaepTest(3, pubKeyEnc3, privKeyEnc3, output3);
+
+ RSAKeyParameters pubParam = new RSAKeyParameters(false, new BigInteger(1, modulus_1024), new BigInteger(1, pubExp_1024));
+ RSAKeyParameters privParam = new RSAPrivateCrtKeyParameters(pubParam.getModulus(), pubParam.getExponent(), new BigInteger(1, privExp_1024), new BigInteger(1, prime1_1024), new BigInteger(1, prime2_1024), new BigInteger(1, primeExp1_1024), new BigInteger(1, primeExp2_1024), new BigInteger(1, crtCoef_1024));
+
+ oaepVecTest(1024, 1, pubParam, privParam, seed_1024_1, input_1024_1, output_1024_1);
+ oaepVecTest(1024, 2, pubParam, privParam, seed_1024_2, input_1024_2, output_1024_2);
+ oaepVecTest(1024, 3, pubParam, privParam, seed_1024_3, input_1024_3, output_1024_3);
+ oaepVecTest(1024, 4, pubParam, privParam, seed_1024_4, input_1024_4, output_1024_4);
+ oaepVecTest(1024, 5, pubParam, privParam, seed_1024_5, input_1024_5, output_1024_5);
+ oaepVecTest(1024, 6, pubParam, privParam, seed_1024_6, input_1024_6, output_1024_6);
+
+ pubParam = new RSAKeyParameters(false, new BigInteger(1, modulus_1027), new BigInteger(1, pubExp_1027));
+ privParam = new RSAPrivateCrtKeyParameters(pubParam.getModulus(), pubParam.getExponent(), new BigInteger(1, privExp_1027), new BigInteger(1, prime1_1027), new BigInteger(1, prime2_1027), new BigInteger(1, primeExp1_1027), new BigInteger(1, primeExp2_1027), new BigInteger(1, crtCoef_1027));
+
+ oaepVecTest(1027, 1, pubParam, privParam, seed_1027_1, input_1027_1, output_1027_1);
+ oaepVecTest(1027, 2, pubParam, privParam, seed_1027_2, input_1027_2, output_1027_2);
+ oaepVecTest(1027, 3, pubParam, privParam, seed_1027_3, input_1027_3, output_1027_3);
+ oaepVecTest(1027, 4, pubParam, privParam, seed_1027_4, input_1027_4, output_1027_4);
+ oaepVecTest(1027, 5, pubParam, privParam, seed_1027_5, input_1027_5, output_1027_5);
+ oaepVecTest(1027, 6, pubParam, privParam, seed_1027_6, input_1027_6, output_1027_6);
+
+ //
+ // OAEP - public encrypt, private decrypt differring hashes
+ //
+ AsymmetricBlockCipher cipher = new OAEPEncoding(new RSAEngine(), new SHA256Digest(), new SHA1Digest(), new byte[10]);
+
+ cipher.init(true, new ParametersWithRandom(pubParam, new SecureRandom()));
+
+ byte[] input = new byte[10];
+
+ byte[] out = cipher.processBlock(input, 0, input.length);
+
+ cipher.init(false, privParam);
+
+ out = cipher.processBlock(out, 0, out.length);
+
+ for (int i = 0; i != input.length; i++)
+ {
+ if (out[i] != input[i])
+ {
+ fail("mixed digest failed decoding");
+ }
+ }
+
+ cipher = new OAEPEncoding(new RSAEngine(), new SHA1Digest(), new SHA256Digest(), new byte[10]);
+
+ cipher.init(true, new ParametersWithRandom(pubParam, new SecureRandom()));
+
+ out = cipher.processBlock(input, 0, input.length);
+
+ cipher.init(false, privParam);
+
+ out = cipher.processBlock(out, 0, out.length);
+
+ for (int i = 0; i != input.length; i++)
+ {
+ if (out[i] != input[i])
+ {
+ fail("mixed digest failed decoding");
+ }
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new OAEPTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/OCBTest.java b/core/src/test/java/org/spongycastle/crypto/test/OCBTest.java
new file mode 100644
index 00000000..8596e304
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/OCBTest.java
@@ -0,0 +1,520 @@
+package org.spongycastle.crypto.test;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.engines.AESEngine;
+import org.spongycastle.crypto.engines.DESEngine;
+import org.spongycastle.crypto.modes.AEADBlockCipher;
+import org.spongycastle.crypto.modes.OCBBlockCipher;
+import org.spongycastle.crypto.params.AEADParameters;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Times;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * Test vectors from <a href="http://tools.ietf.org/html/rfc7253">RFC 7253 on The OCB
+ * Authenticated-Encryption Algorithm</a>
+ */
+public class OCBTest
+ extends SimpleTest
+{
+ private static final String KEY_128 = "000102030405060708090A0B0C0D0E0F";
+ private static final String KEY_96 = "0F0E0D0C0B0A09080706050403020100";
+
+ /*
+ * Test vectors from Appendix A of the specification, containing the strings N, A, P, C in order
+ */
+
+ private static final String[][] TEST_VECTORS_128 = new String[][]{
+ { "BBAA99887766554433221100",
+ "",
+ "",
+ "785407BFFFC8AD9EDCC5520AC9111EE6" },
+ { "BBAA99887766554433221101",
+ "0001020304050607",
+ "0001020304050607",
+ "6820B3657B6F615A5725BDA0D3B4EB3A257C9AF1F8F03009" },
+ { "BBAA99887766554433221102",
+ "0001020304050607",
+ "",
+ "81017F8203F081277152FADE694A0A00" },
+ { "BBAA99887766554433221103",
+ "",
+ "0001020304050607",
+ "45DD69F8F5AAE72414054CD1F35D82760B2CD00D2F99BFA9" },
+ { "BBAA99887766554433221104",
+ "000102030405060708090A0B0C0D0E0F",
+ "000102030405060708090A0B0C0D0E0F",
+ "571D535B60B277188BE5147170A9A22C3AD7A4FF3835B8C5701C1CCEC8FC3358" },
+ { "BBAA99887766554433221105",
+ "000102030405060708090A0B0C0D0E0F",
+ "",
+ "8CF761B6902EF764462AD86498CA6B97" },
+ { "BBAA99887766554433221106",
+ "",
+ "000102030405060708090A0B0C0D0E0F",
+ "5CE88EC2E0692706A915C00AEB8B2396F40E1C743F52436BDF06D8FA1ECA343D" },
+ { "BBAA99887766554433221107",
+ "000102030405060708090A0B0C0D0E0F1011121314151617",
+ "000102030405060708090A0B0C0D0E0F1011121314151617",
+ "1CA2207308C87C010756104D8840CE1952F09673A448A122C92C62241051F57356D7F3C90BB0E07F" },
+ { "BBAA99887766554433221108",
+ "000102030405060708090A0B0C0D0E0F1011121314151617",
+ "",
+ "6DC225A071FC1B9F7C69F93B0F1E10DE" },
+ { "BBAA99887766554433221109",
+ "",
+ "000102030405060708090A0B0C0D0E0F1011121314151617",
+ "221BD0DE7FA6FE993ECCD769460A0AF2D6CDED0C395B1C3CE725F32494B9F914D85C0B1EB38357FF" },
+ { "BBAA9988776655443322110A",
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
+ "BD6F6C496201C69296C11EFD138A467ABD3C707924B964DEAFFC40319AF5A48540FBBA186C5553C68AD9F592A79A4240" },
+ { "BBAA9988776655443322110B",
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
+ "",
+ "FE80690BEE8A485D11F32965BC9D2A32" },
+ { "BBAA9988776655443322110C",
+ "",
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
+ "2942BFC773BDA23CABC6ACFD9BFD5835BD300F0973792EF46040C53F1432BCDFB5E1DDE3BC18A5F840B52E653444D5DF" },
+ { "BBAA9988776655443322110D",
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
+ "D5CA91748410C1751FF8A2F618255B68A0A12E093FF454606E59F9C1D0DDC54B65E8628E568BAD7AED07BA06A4A69483A7035490C5769E60" },
+ { "BBAA9988776655443322110E",
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
+ "",
+ "C5CD9D1850C141E358649994EE701B68" },
+ { "BBAA9988776655443322110F",
+ "",
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
+ "4412923493C57D5DE0D700F753CCE0D1D2D95060122E9F15A5DDBFC5787E50B5CC55EE507BCB084E479AD363AC366B95A98CA5F3000B1479" },
+ };
+
+ private static final String[][] TEST_VECTORS_96 = new String[][]{
+ { "BBAA9988776655443322110D",
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
+ "1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FDAC4F02AA" },
+ };
+
+ public String getName()
+ {
+ return "OCB";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ byte[] K128 = Hex.decode(KEY_128);
+ for (int i = 0; i < TEST_VECTORS_128.length; ++i)
+ {
+ runTestCase("Test Case " + i, TEST_VECTORS_128[i], 128, K128);
+ }
+
+ byte[] K96 = Hex.decode(KEY_96);
+ for (int i = 0; i < TEST_VECTORS_96.length; ++i)
+ {
+ runTestCase("Test Case " + i, TEST_VECTORS_96[i], 96, K96);
+ }
+
+ runLongerTestCase(128, 128, "67E944D23256C5E0B6C61FA22FDF1EA2");
+ runLongerTestCase(192, 128, "F673F2C3E7174AAE7BAE986CA9F29E17");
+ runLongerTestCase(256, 128, "D90EB8E9C977C88B79DD793D7FFA161C");
+ runLongerTestCase(128, 96, "77A3D8E73589158D25D01209");
+ runLongerTestCase(192, 96, "05D56EAD2752C86BE6932C5E");
+ runLongerTestCase(256, 96, "5458359AC23B0CBA9E6330DD");
+ runLongerTestCase(128, 64, "192C9B7BD90BA06A");
+ runLongerTestCase(192, 64, "0066BC6E0EF34E24");
+ runLongerTestCase(256, 64, "7D4EA5D445501CBE");
+
+ randomTests();
+ outputSizeTests();
+ testExceptions();
+ }
+
+ private void testExceptions() throws InvalidCipherTextException
+ {
+ AEADBlockCipher ocb = createOCBCipher();
+
+ try
+ {
+ ocb = new OCBBlockCipher(new DESEngine(), new DESEngine());
+
+ fail("incorrect block size not picked up");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ ocb.init(false, new KeyParameter(new byte[16]));
+
+ fail("illegal argument not picked up");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ AEADTestUtil.testReset(this, createOCBCipher(), createOCBCipher(), new AEADParameters(new KeyParameter(new byte[16]), 128, new byte[15]));
+ AEADTestUtil.testTampering(this, ocb, new AEADParameters(new KeyParameter(new byte[16]), 128, new byte[15]));
+ AEADTestUtil.testOutputSizes(this, createOCBCipher(), new AEADParameters(new KeyParameter(new byte[16]), 128,
+ new byte[15]));
+ AEADTestUtil.testBufferSizeChecks(this, createOCBCipher(), new AEADParameters(new KeyParameter(new byte[16]),
+ 128, new byte[15]));
+ }
+
+ private void runTestCase(String testName, String[] testVector, int macLengthBits, byte[] K)
+ throws InvalidCipherTextException
+ {
+ int pos = 0;
+ byte[] N = Hex.decode(testVector[pos++]);
+ byte[] A = Hex.decode(testVector[pos++]);
+ byte[] P = Hex.decode(testVector[pos++]);
+ byte[] C = Hex.decode(testVector[pos++]);
+
+ int macLengthBytes = macLengthBits / 8;
+
+ KeyParameter keyParameter = new KeyParameter(K);
+ AEADParameters parameters = new AEADParameters(keyParameter, macLengthBits, N, A);
+
+ AEADBlockCipher encCipher = initOCBCipher(true, parameters);
+ AEADBlockCipher decCipher = initOCBCipher(false, parameters);
+
+ checkTestCase(encCipher, decCipher, testName, macLengthBytes, P, C);
+ checkTestCase(encCipher, decCipher, testName + " (reused)", macLengthBytes, P, C);
+
+ // Key reuse
+ AEADParameters keyReuseParams = AEADTestUtil.reuseKey(parameters);
+ encCipher.init(true, keyReuseParams);
+ decCipher.init(false, keyReuseParams);
+ checkTestCase(encCipher, decCipher, testName + " (key reuse)", macLengthBytes, P, C);
+ }
+
+ private BlockCipher createUnderlyingCipher()
+ {
+ return new AESEngine();
+ }
+
+ private AEADBlockCipher createOCBCipher()
+ {
+ return new OCBBlockCipher(createUnderlyingCipher(), createUnderlyingCipher());
+ }
+
+ private AEADBlockCipher initOCBCipher(boolean forEncryption, AEADParameters parameters)
+ {
+ AEADBlockCipher c = createOCBCipher();
+ c.init(forEncryption, parameters);
+ return c;
+ }
+
+ private void checkTestCase(AEADBlockCipher encCipher, AEADBlockCipher decCipher, String testName,
+ int macLengthBytes, byte[] P, byte[] C)
+ throws InvalidCipherTextException
+ {
+ byte[] tag = Arrays.copyOfRange(C, C.length - macLengthBytes, C.length);
+
+ {
+ byte[] enc = new byte[encCipher.getOutputSize(P.length)];
+ int len = encCipher.processBytes(P, 0, P.length, enc, 0);
+ len += encCipher.doFinal(enc, len);
+
+ if (enc.length != len)
+ {
+ fail("encryption reported incorrect length: " + testName);
+ }
+
+ if (!areEqual(C, enc))
+ {
+ fail("incorrect encrypt in: " + testName);
+ }
+
+ if (!areEqual(tag, encCipher.getMac()))
+ {
+ fail("getMac() not the same as the appended tag: " + testName);
+ }
+ }
+
+ {
+ byte[] dec = new byte[decCipher.getOutputSize(C.length)];
+ int len = decCipher.processBytes(C, 0, C.length, dec, 0);
+ len += decCipher.doFinal(dec, len);
+
+ if (dec.length != len)
+ {
+ fail("decryption reported incorrect length: " + testName);
+ }
+
+ if (!areEqual(P, dec))
+ {
+ fail("incorrect decrypt in: " + testName);
+ }
+
+ if (!areEqual(tag, decCipher.getMac()))
+ {
+ fail("getMac() not the same as the appended tag: " + testName);
+ }
+ }
+ }
+
+ private void runLongerTestCase(int keyLen, int tagLen, String expectedOutputHex)
+ throws InvalidCipherTextException
+ {
+ byte[] expectedOutput = Hex.decode(expectedOutputHex);
+ byte[] keyBytes = new byte[keyLen / 8];
+ keyBytes[keyBytes.length - 1] = (byte)tagLen;
+ KeyParameter key = new KeyParameter(keyBytes);
+
+ AEADBlockCipher c1 = initOCBCipher(true, new AEADParameters(key, tagLen, createNonce(385)));
+ AEADBlockCipher c2 = createOCBCipher();
+
+ long total = 0;
+
+ byte[] S = new byte[128];
+
+ int n = 0;
+ for (int i = 0; i < 128; ++i)
+ {
+ c2.init(true, new AEADParameters(key, tagLen, createNonce(++n)));
+ total += updateCiphers(c1, c2, S, i, true, true);
+ c2.init(true, new AEADParameters(key, tagLen, createNonce(++n)));
+ total += updateCiphers(c1, c2, S, i, false, true);
+ c2.init(true, new AEADParameters(key, tagLen, createNonce(++n)));
+ total += updateCiphers(c1, c2, S, i, true, false);
+ }
+
+ long expectedTotal = 16256 + (48 * tagLen);
+
+ if (total != expectedTotal)
+ {
+ fail("test generated the wrong amount of input: " + total);
+ }
+
+ byte[] output = new byte[c1.getOutputSize(0)];
+ c1.doFinal(output, 0);
+
+ if (!areEqual(expectedOutput, output))
+ {
+ fail("incorrect encrypt in long-form test");
+ }
+ }
+
+ private byte[] createNonce(int n)
+ {
+ return new byte[]{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte)(n >>> 8), (byte)n };
+ }
+
+ private int updateCiphers(AEADBlockCipher c1, AEADBlockCipher c2, byte[] S, int i,
+ boolean includeAAD, boolean includePlaintext)
+ throws InvalidCipherTextException
+ {
+ int inputLen = includePlaintext ? i : 0;
+ int outputLen = c2.getOutputSize(inputLen);
+
+ byte[] output = new byte[outputLen];
+
+ int len = 0;
+
+ if (includeAAD)
+ {
+ c2.processAADBytes(S, 0, i);
+ }
+
+ if (includePlaintext)
+ {
+ len += c2.processBytes(S, 0, i, output, len);
+ }
+
+ len += c2.doFinal(output, len);
+
+ c1.processAADBytes(output, 0, len);
+
+ return len;
+ }
+
+ private void randomTests()
+ throws InvalidCipherTextException
+ {
+ SecureRandom srng = new SecureRandom();
+ srng.setSeed(Times.nanoTime());
+ for (int i = 0; i < 10; ++i)
+ {
+ randomTest(srng);
+ }
+ }
+
+ private void randomTest(SecureRandom srng)
+ throws InvalidCipherTextException
+ {
+ int kLength = 16 + 8 * (Math.abs(srng.nextInt()) % 3);
+ byte[] K = new byte[kLength];
+ srng.nextBytes(K);
+
+ int pLength = srng.nextInt() >>> 16;
+ byte[] P = new byte[pLength];
+ srng.nextBytes(P);
+
+ int aLength = srng.nextInt() >>> 24;
+ byte[] A = new byte[aLength];
+ srng.nextBytes(A);
+
+ int saLength = srng.nextInt() >>> 24;
+ byte[] SA = new byte[saLength];
+ srng.nextBytes(SA);
+
+ int ivLength = 1 + nextInt(srng, 15);
+ byte[] IV = new byte[ivLength];
+ srng.nextBytes(IV);
+
+ AEADParameters parameters = new AEADParameters(new KeyParameter(K), 16 * 8, IV, A);
+ AEADBlockCipher cipher = initOCBCipher(true, parameters);
+ byte[] C = new byte[cipher.getOutputSize(P.length)];
+ int predicted = cipher.getUpdateOutputSize(P.length);
+
+ int split = nextInt(srng, SA.length + 1);
+ cipher.processAADBytes(SA, 0, split);
+ int len = cipher.processBytes(P, 0, P.length, C, 0);
+ cipher.processAADBytes(SA, split, SA.length - split);
+
+ if (predicted != len)
+ {
+ fail("encryption reported incorrect update length in randomised test");
+ }
+
+ len += cipher.doFinal(C, len);
+
+ if (C.length != len)
+ {
+ fail("encryption reported incorrect length in randomised test");
+ }
+
+ byte[] encT = cipher.getMac();
+ byte[] tail = new byte[C.length - P.length];
+ System.arraycopy(C, P.length, tail, 0, tail.length);
+
+ if (!areEqual(encT, tail))
+ {
+ fail("stream contained wrong mac in randomised test");
+ }
+
+ cipher.init(false, parameters);
+ byte[] decP = new byte[cipher.getOutputSize(C.length)];
+ predicted = cipher.getUpdateOutputSize(C.length);
+
+ split = nextInt(srng, SA.length + 1);
+ cipher.processAADBytes(SA, 0, split);
+ len = cipher.processBytes(C, 0, C.length, decP, 0);
+ cipher.processAADBytes(SA, split, SA.length - split);
+
+ if (predicted != len)
+ {
+ fail("decryption reported incorrect update length in randomised test");
+ }
+
+ len += cipher.doFinal(decP, len);
+
+ if (!areEqual(P, decP))
+ {
+ fail("incorrect decrypt in randomised test");
+ }
+
+ byte[] decT = cipher.getMac();
+ if (!areEqual(encT, decT))
+ {
+ fail("decryption produced different mac from encryption");
+ }
+
+ //
+ // key reuse test
+ //
+ cipher.init(false, AEADTestUtil.reuseKey(parameters));
+ decP = new byte[cipher.getOutputSize(C.length)];
+
+ split = nextInt(srng, SA.length + 1);
+ cipher.processAADBytes(SA, 0, split);
+ len = cipher.processBytes(C, 0, C.length, decP, 0);
+ cipher.processAADBytes(SA, split, SA.length - split);
+
+ len += cipher.doFinal(decP, len);
+
+ if (!areEqual(P, decP))
+ {
+ fail("incorrect decrypt in randomised test");
+ }
+
+ decT = cipher.getMac();
+ if (!areEqual(encT, decT))
+ {
+ fail("decryption produced different mac from encryption");
+ }
+ }
+
+ private void outputSizeTests()
+ {
+ byte[] K = new byte[16];
+ byte[] A = null;
+ byte[] IV = new byte[15];
+
+ AEADParameters parameters = new AEADParameters(new KeyParameter(K), 16 * 8, IV, A);
+ AEADBlockCipher cipher = initOCBCipher(true, parameters);
+
+ if (cipher.getUpdateOutputSize(0) != 0)
+ {
+ fail("incorrect getUpdateOutputSize for initial 0 bytes encryption");
+ }
+
+ if (cipher.getOutputSize(0) != 16)
+ {
+ fail("incorrect getOutputSize for initial 0 bytes encryption");
+ }
+
+ cipher.init(false, parameters);
+
+ if (cipher.getUpdateOutputSize(0) != 0)
+ {
+ fail("incorrect getUpdateOutputSize for initial 0 bytes decryption");
+ }
+
+ // NOTE: 0 bytes would be truncated data, but we want it to fail in the doFinal, not here
+ if (cipher.getOutputSize(0) != 0)
+ {
+ fail("fragile getOutputSize for initial 0 bytes decryption");
+ }
+
+ if (cipher.getOutputSize(16) != 0)
+ {
+ fail("incorrect getOutputSize for initial MAC-size bytes decryption");
+ }
+ }
+
+ private static int nextInt(SecureRandom rand, int n)
+ {
+ if ((n & -n) == n) // i.e., n is a power of 2
+ {
+ return (int)((n * (long)(rand.nextInt() >>> 1)) >> 31);
+ }
+
+ int bits, value;
+ do
+ {
+ bits = rand.nextInt() >>> 1;
+ value = bits % n;
+ }
+ while (bits - value + (n - 1) < 0);
+
+ return value;
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new OCBTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/PKCS12Test.java b/core/src/test/java/org/spongycastle/crypto/test/PKCS12Test.java
new file mode 100644
index 00000000..5374116a
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/PKCS12Test.java
@@ -0,0 +1,206 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.PBEParametersGenerator;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.generators.PKCS12ParametersGenerator;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+/**
+ * test for PKCS12 key generation - vectors from
+ * <a href=http://www.drh-consultancy.demon.co.uk/test.txt>
+ * http://www.drh-consultancy.demon.co.uk/test.txt</a>
+ */
+public class PKCS12Test
+ implements Test
+{
+ char[] password1 = { 's', 'm', 'e', 'g' };
+ char[] password2 = { 'q', 'u', 'e', 'e', 'g' };
+
+ private boolean isEqual(
+ byte[] a,
+ byte[] b)
+ {
+ if (a.length != b.length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i != a.length; i++)
+ {
+ if (a[i] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private TestResult run1(
+ int id,
+ char[] password,
+ byte[] salt,
+ int iCount,
+ byte[] result)
+ {
+ PBEParametersGenerator generator = new PKCS12ParametersGenerator(
+ new SHA1Digest());
+
+ generator.init(
+ PBEParametersGenerator.PKCS12PasswordToBytes(password),
+ salt,
+ iCount);
+
+ CipherParameters key = generator.generateDerivedParameters(24 * 8);
+
+ if (isEqual(result, ((KeyParameter)key).getKey()))
+ {
+ return new SimpleTestResult(true, "PKCS12Test: Okay");
+ }
+ else
+ {
+ return new SimpleTestResult(false, "PKCS12Test: id "
+ + id + " Failed");
+ }
+ }
+
+ private TestResult run2(
+ int id,
+ char[] password,
+ byte[] salt,
+ int iCount,
+ byte[] result)
+ {
+ PBEParametersGenerator generator = new PKCS12ParametersGenerator(
+ new SHA1Digest());
+
+ generator.init(
+ PBEParametersGenerator.PKCS12PasswordToBytes(password),
+ salt,
+ iCount);
+
+ ParametersWithIV params = (ParametersWithIV)generator.generateDerivedParameters(64, 64);
+
+ if (isEqual(result, params.getIV()))
+ {
+ return new SimpleTestResult(true, "PKCS12Test: Okay");
+ }
+ else
+ {
+ return new SimpleTestResult(false, "PKCS12Test: id "
+ + id + " Failed");
+ }
+ }
+
+ private TestResult run3(
+ int id,
+ char[] password,
+ byte[] salt,
+ int iCount,
+ byte[] result)
+ {
+ PBEParametersGenerator generator = new PKCS12ParametersGenerator(
+ new SHA1Digest());
+
+ generator.init(
+ PBEParametersGenerator.PKCS12PasswordToBytes(password),
+ salt,
+ iCount);
+
+ CipherParameters key = generator.generateDerivedMacParameters(160);
+
+ if (isEqual(result, ((KeyParameter)key).getKey()))
+ {
+ return new SimpleTestResult(true, "PKCS12Test: Okay");
+ }
+ else
+ {
+ return new SimpleTestResult(false, "PKCS12Test: id "
+ + id + " Failed");
+ }
+ }
+
+ public String getName()
+ {
+ return "PKCS12Test";
+ }
+
+ public TestResult perform()
+ {
+ TestResult result;
+
+ result = run1(1, password1, Hex.decode("0A58CF64530D823F"), 1,
+ Hex.decode("8AAAE6297B6CB04642AB5B077851284EB7128F1A2A7FBCA3"));
+
+ if (result.isSuccessful())
+ {
+ result = run2(2, password1, Hex.decode("0A58CF64530D823F"), 1,
+ Hex.decode("79993DFE048D3B76"));
+ }
+
+ if (result.isSuccessful())
+ {
+ result = run1(3, password1, Hex.decode("642B99AB44FB4B1F"), 1,
+ Hex.decode("F3A95FEC48D7711E985CFE67908C5AB79FA3D7C5CAA5D966"));
+ }
+
+ if (result.isSuccessful())
+ {
+ result = run2(4, password1, Hex.decode("642B99AB44FB4B1F"), 1,
+ Hex.decode("C0A38D64A79BEA1D"));
+ }
+
+ if (result.isSuccessful())
+ {
+ result = run3(5, password1, Hex.decode("3D83C0E4546AC140"), 1,
+ Hex.decode("8D967D88F6CAA9D714800AB3D48051D63F73A312"));
+ }
+
+ if (result.isSuccessful())
+ {
+ result = run1(6, password2, Hex.decode("05DEC959ACFF72F7"), 1000,
+ Hex.decode("ED2034E36328830FF09DF1E1A07DD357185DAC0D4F9EB3D4"));
+ }
+
+ if (result.isSuccessful())
+ {
+ result = run2(7, password2, Hex.decode("05DEC959ACFF72F7"), 1000,
+ Hex.decode("11DEDAD7758D4860"));
+ }
+
+ if (result.isSuccessful())
+ {
+ result = run1(8, password2, Hex.decode("1682C0FC5B3F7EC5"), 1000,
+ Hex.decode("483DD6E919D7DE2E8E648BA8F862F3FBFBDC2BCB2C02957F"));
+ }
+
+ if (result.isSuccessful())
+ {
+ result = run2(9, password2, Hex.decode("1682C0FC5B3F7EC5"), 1000,
+ Hex.decode("9D461D1B00355C50"));
+ }
+
+ if (result.isSuccessful())
+ {
+ result = run3(10, password2, Hex.decode("263216FCC2FAB31C"), 1000,
+ Hex.decode("5EC4C7A80DF652294C3925B6489A7AB857C83476"));
+ }
+
+ return result;
+ }
+
+ public static void main(
+ String[] args)
+ {
+ PKCS12Test test = new PKCS12Test();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/PKCS5Test.java b/core/src/test/java/org/spongycastle/crypto/test/PKCS5Test.java
new file mode 100644
index 00000000..66aef5eb
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/PKCS5Test.java
@@ -0,0 +1,265 @@
+package org.spongycastle.crypto.test;
+
+import java.io.ByteArrayInputStream;
+
+import org.spongycastle.asn1.ASN1InputStream;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo;
+import org.spongycastle.asn1.pkcs.EncryptionScheme;
+import org.spongycastle.asn1.pkcs.KeyDerivationFunc;
+import org.spongycastle.asn1.pkcs.PBES2Parameters;
+import org.spongycastle.asn1.pkcs.PBKDF2Params;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.pkcs.RC2CBCParameter;
+import org.spongycastle.crypto.BufferedBlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.PBEParametersGenerator;
+import org.spongycastle.crypto.engines.DESEngine;
+import org.spongycastle.crypto.engines.DESedeEngine;
+import org.spongycastle.crypto.engines.RC2Engine;
+import org.spongycastle.crypto.generators.PKCS5S2ParametersGenerator;
+import org.spongycastle.crypto.modes.CBCBlockCipher;
+import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.encoders.Base64;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * A test class for PKCS5 PBES2 with PBKDF2 (PKCS5 v2.0) using
+ * test vectors provider at
+ * <a href=http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html>
+ * RSA's PKCS5 Page</a>
+ * <br>
+ * The vectors are Base 64 encoded and encrypted using the password "password"
+ * (without quotes). They should all yield the same PrivateKeyInfo object.
+ */
+public class PKCS5Test
+ extends SimpleTest
+{
+ /**
+ * encrypted using des-cbc.
+ */
+ static byte[] sample1 = Base64.decode(
+ "MIIBozA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQIfWBDXwLp4K4CAggA"
+ + "MBEGBSsOAwIHBAiaCF/AvOgQ6QSCAWDWX4BdAzCRNSQSANSuNsT5X8mWYO27mr3Y"
+ + "9c9LoBVXGNmYWKA77MI4967f7SmjNcgXj3xNE/jmnVz6hhsjS8E5VPT3kfyVkpdZ"
+ + "0lr5e9Yk2m3JWpPU7++v5zBkZmC4V/MwV/XuIs6U+vykgzMgpxQg0oZKS9zgmiZo"
+ + "f/4dOCL0UtCDnyOSvqT7mCVIcMDIEKu8QbVlgZYBop08l60EuEU3gARUo8WsYQmO"
+ + "Dz/ldx0Z+znIT0SXVuOwc+RVItC5T/Qx+aijmmpt+9l14nmaGBrEkmuhmtdvU/4v"
+ + "aptewGRgmjOfD6cqK+zs0O5NrrJ3P/6ZSxXj91CQgrThGfOv72bUncXEMNtc8pks"
+ + "2jpHFjGMdKufnadAD7XuMgzkkaklEXZ4f5tU6heIIwr51g0GBEGF96gYPFnjnSQM"
+ + "75JE02Clo+DfcfXpcybPTwwFg2jd6JTTOfkdf6OdSlA/1XNK43FA");
+
+ /**
+ * encrypted using des-ede3-cbc.
+ */
+ static byte[] sample2 = Base64.decode(
+ "MIIBpjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIeFeOWl1jywYCAggA"
+ + "MBQGCCqGSIb3DQMHBAjUJ5eGBhQGtQSCAWBrHrRgqO8UUMLcWzZEtpk1l3mjxiF/"
+ + "koCMkHsFwowgyWhEbgIkTgbSViK54LVK8PskekcGNLph+rB6bGZ7pPbL5pbXASJ8"
+ + "+MkQcG3FZdlS4Ek9tTJDApj3O1UubZGFG4uvTlJJFbF1BOJ3MkY3XQ9Gl1qwv7j5"
+ + "6e103Da7Cq9+oIDKmznza78XXQYrUsPo8mJGjUxPskEYlzwvHjKubRnYm/K6RKhi"
+ + "5f4zX4BQ/Dt3H812ZjRXrsjAJP0KrD/jyD/jCT7zNBVPH1izBds+RwizyQAHwfNJ"
+ + "BFR78TH4cgzB619X47FDVOnT0LqQNVd0O3cSwnPrXE9XR3tPayE+iOB15llFSmi8"
+ + "z0ByOXldEpkezCn92Umk++suzIVj1qfsK+bv2phZWJPbLEIWPDRHUbYf76q5ArAr"
+ + "u4xtxT/hoK3krEs/IN3d70qjlUJ36SEw1UaZ82PWhakQbdtu39ZraMJB");
+
+ /**
+ * encrypted using rc2-cbc.
+ */
+ static byte[] sample3 = Base64.decode(
+ "MIIBrjBIBgkqhkiG9w0BBQ0wOzAeBgkqhkiG9w0BBQwwEQQIrHyQPBZqWLUCAggA"
+ + "AgEQMBkGCCqGSIb3DQMCMA0CAToECEhbh7YZKiPSBIIBYCT1zp6o5jpFlIkgwPop"
+ + "7bW1+8ACr4exqzkeb3WflQ8cWJ4cURxzVdvxUnXeW1VJdaQZtjS/QHs5GhPTG/0f"
+ + "wtvnaPfwrIJ3FeGaZfcg2CrYhalOFmEb4xrE4KyoEQmUN8tb/Cg94uzd16BOPw21"
+ + "RDnE8bnPdIGY7TyL95kbkqH23mK53pi7h+xWIgduW+atIqDyyt55f7WMZcvDvlj6"
+ + "VpN/V0h+qxBHL274WA4dj6GYgeyUFpi60HdGCK7By2TBy8h1ZvKGjmB9h8jZvkx1"
+ + "MkbRumXxyFsowTZawyYvO8Um6lbfEDP9zIEUq0IV8RqH2MRyblsPNSikyYhxX/cz"
+ + "tdDxRKhilySbSBg5Kr8OfcwKp9bpinN96nmG4xr3Tch1bnVvqJzOQ5+Vva2WwVvH"
+ + "2JkWvYm5WaANg4Q6bRxu9vz7DuhbJjQdZbxFezIAgrJdSe92B00jO/0Kny1WjiVO"
+ + "6DA=");
+
+ static byte[] result = Hex.decode(
+ "30820155020100300d06092a864886f70d01010105000482013f3082013b020100024100"
+ + "debbfc2c09d61bada2a9462f24224e54cc6b3cc0755f15ce318ef57e79df17026b6a85cc"
+ + "a12428027245045df2052a329a2f9ad3d17b78a10572ad9b22bf343b020301000102402d"
+ + "90a96adcec472743527bc023153d8f0d6e96b40c8ed228276d467d843306429f8670559b"
+ + "f376dd41857f6397c2fc8d95e0e53ed62de420b855430ee4a1b8a1022100ffcaf0838239"
+ + "31e073ff534f06a5d415b3d414bc614a4544a3dff7ed271817eb022100deea30242117db"
+ + "2d3b8837f58f1da530ff83cf9283680da33683ec4e583610f1022100e6026381adb0a683"
+ + "f16a8f4c096b462979b9e4277cc89f3ed8a905b46fa9ff9f02210097c146d4d1d2b3dbaf"
+ + "53a504ff51674c5c271800de84d003f4f10ac6ab36e38102202bfa141f10bda874e1017d"
+ + "845e82767c1c38e82745daf421f0c8cd09d7652387");
+
+ private class PBETest
+ extends SimpleTest
+ {
+ int id;
+ BufferedBlockCipher cipher;
+ byte[] sample;
+ int keySize;
+
+ PBETest(
+ int id,
+ BufferedBlockCipher cipher,
+ byte[] sample,
+ int keySize)
+ {
+ this.id = id;
+ this.cipher = cipher;
+ this.sample = sample;
+ this.keySize = keySize;
+ }
+
+ public String getName()
+ {
+ return cipher.getUnderlyingCipher().getAlgorithmName() + " PKCS5S2 Test " + id;
+ }
+
+ public void performTest()
+ {
+ char[] password = { 'p', 'a', 's', 's', 'w', 'o', 'r', 'd' };
+ PBEParametersGenerator generator = new PKCS5S2ParametersGenerator();
+ ByteArrayInputStream bIn = new ByteArrayInputStream(sample);
+ ASN1InputStream dIn = new ASN1InputStream(bIn);
+ EncryptedPrivateKeyInfo info = null;
+
+ try
+ {
+ info = EncryptedPrivateKeyInfo.getInstance(dIn.readObject());
+ }
+ catch (Exception e)
+ {
+ fail("failed construction - exception " + e.toString(), e);
+ }
+
+ PBES2Parameters alg = PBES2Parameters.getInstance(info.getEncryptionAlgorithm().getParameters());
+ PBKDF2Params func = PBKDF2Params.getInstance(alg.getKeyDerivationFunc().getParameters());
+ EncryptionScheme scheme = alg.getEncryptionScheme();
+
+ if (func.getKeyLength() != null)
+ {
+ keySize = func.getKeyLength().intValue() * 8;
+ }
+
+ int iterationCount = func.getIterationCount().intValue();
+ byte[] salt = func.getSalt();
+
+ generator.init(
+ PBEParametersGenerator.PKCS5PasswordToBytes(password),
+ salt,
+ iterationCount);
+
+ CipherParameters param;
+
+ if (scheme.getAlgorithm().equals(PKCSObjectIdentifiers.RC2_CBC))
+ {
+ RC2CBCParameter rc2Params = RC2CBCParameter.getInstance(scheme.getParameters());
+ byte[] iv = rc2Params.getIV();
+
+ param = new ParametersWithIV(generator.generateDerivedParameters(keySize), iv);
+ }
+ else
+ {
+ byte[] iv = ASN1OctetString.getInstance(scheme.getParameters()).getOctets();
+
+ param = new ParametersWithIV(generator.generateDerivedParameters(keySize), iv);
+ }
+
+ cipher.init(false, param);
+
+ byte[] data = info.getEncryptedData();
+ byte[] out = new byte[cipher.getOutputSize(data.length)];
+ int len = cipher.processBytes(data, 0, data.length, out, 0);
+
+ try
+ {
+ len += cipher.doFinal(out, len);
+ }
+ catch (Exception e)
+ {
+ fail("failed doFinal - exception " + e.toString());
+ }
+
+ if (result.length != len)
+ {
+ fail("failed length");
+ }
+
+ for (int i = 0; i != len; i++)
+ {
+ if (out[i] != result[i])
+ {
+ fail("failed comparison");
+ }
+ }
+ }
+ }
+
+ public String getName()
+ {
+ return "PKCS5S2";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new DESEngine()));
+ SimpleTest test = new PBETest(0, cipher, sample1, 64);
+
+ test.performTest();
+
+ cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new DESedeEngine()));
+ test = new PBETest(1, cipher, sample2, 192);
+
+ test.performTest();
+
+ cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new RC2Engine()));
+ test = new PBETest(2, cipher, sample3, 0);
+ test.performTest();
+
+ //
+ // RFC 3211 tests
+ //
+ char[] password = { 'p', 'a', 's', 's', 'w', 'o', 'r', 'd' };
+ PBEParametersGenerator generator = new PKCS5S2ParametersGenerator();
+
+ byte[] salt = Hex.decode("1234567878563412");
+
+ generator.init(
+ PBEParametersGenerator.PKCS5PasswordToBytes(password),
+ salt,
+ 5);
+
+ if (!areEqual(((KeyParameter)generator.generateDerivedParameters(64)).getKey(), Hex.decode("d1daa78615f287e6")))
+ {
+ fail("64 test failed");
+ }
+
+ password = "All n-entities must communicate with other n-entities via n-1 entiteeheehees".toCharArray();
+
+ generator.init(
+ PBEParametersGenerator.PKCS5PasswordToBytes(password),
+ salt,
+ 500);
+
+ if (!areEqual(((KeyParameter)generator.generateDerivedParameters(192)).getKey(), Hex.decode("6a8970bf68c92caea84a8df28510858607126380cc47ab2d")))
+ {
+ fail("192 test failed");
+ }
+
+ generator.init(PBEParametersGenerator.PKCS5PasswordToBytes(password), salt, 60000);
+ if (!areEqual(((KeyParameter)generator.generateDerivedParameters(192)).getKey(), Hex.decode("29aaef810c12ecd2236bbcfb55407f9852b5573dc1c095bb")))
+ {
+ fail("192 (60000) test failed");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new PKCS5Test());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/PSSBlindTest.java b/core/src/test/java/org/spongycastle/crypto/test/PSSBlindTest.java
new file mode 100644
index 00000000..36362bca
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/PSSBlindTest.java
@@ -0,0 +1,398 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.engines.RSABlindingEngine;
+import org.spongycastle.crypto.engines.RSAEngine;
+import org.spongycastle.crypto.generators.RSABlindingFactorGenerator;
+import org.spongycastle.crypto.generators.RSAKeyPairGenerator;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.params.RSABlindingParameters;
+import org.spongycastle.crypto.params.RSAKeyGenerationParameters;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+import org.spongycastle.crypto.params.RSAPrivateCrtKeyParameters;
+import org.spongycastle.crypto.signers.PSSSigner;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/*
+ * RSA PSS test vectors for PKCS#1 V2.1 with blinding
+ */
+public class PSSBlindTest
+ extends SimpleTest
+{
+ private final int DATA_LENGTH = 1000;
+ private final int NUM_TESTS = 50;
+ private final int NUM_TESTS_WITH_KEY_GENERATION = 10;
+
+ private class FixedRandom
+ extends SecureRandom
+ {
+ byte[] vals;
+
+ FixedRandom(
+ byte[] vals)
+ {
+ this.vals = vals;
+ }
+
+ public void nextBytes(
+ byte[] bytes)
+ {
+ System.arraycopy(vals, 0, bytes, 0, vals.length);
+ }
+ }
+
+ //
+ // Example 1: A 1024-bit RSA keypair
+ //
+ private RSAKeyParameters pub1 = new RSAKeyParameters(false,
+ new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",16),
+ new BigInteger("010001",16));
+
+ private RSAKeyParameters prv1 = new RSAPrivateCrtKeyParameters(
+ new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",16),
+ new BigInteger("010001",16),
+ new BigInteger("33a5042a90b27d4f5451ca9bbbd0b44771a101af884340aef9885f2a4bbe92e894a724ac3c568c8f97853ad07c0266c8c6a3ca0929f1e8f11231884429fc4d9ae55fee896a10ce707c3ed7e734e44727a39574501a532683109c2abacaba283c31b4bd2f53c3ee37e352cee34f9e503bd80c0622ad79c6dcee883547c6a3b325",16),
+ new BigInteger("e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443",16),
+ new BigInteger("b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd",16),
+ new BigInteger("28fa13938655be1f8a159cbaca5a72ea190c30089e19cd274a556f36c4f6e19f554b34c077790427bbdd8dd3ede2448328f385d81b30e8e43b2fffa027861979",16),
+ new BigInteger("1a8b38f398fa712049898d7fb79ee0a77668791299cdfa09efc0e507acb21ed74301ef5bfd48be455eaeb6e1678255827580a8e4e8e14151d1510a82a3f2e729",16),
+ new BigInteger("27156aba4126d24a81f3a528cbfb27f56886f840a9f6e86e17a44b94fe9319584b8e22fdde1e5a2e3bd8aa5ba8d8584194eb2190acf832b847f13a3d24a79f4d",16));
+
+ // PSSExample1.1
+
+ private byte[] msg1a = Hex.decode("cdc87da223d786df3b45e0bbbc721326d1ee2af806cc315475cc6f0d9c66e1b62371d45ce2392e1ac92844c310102f156a0d8d52c1f4c40ba3aa65095786cb769757a6563ba958fed0bcc984e8b517a3d5f515b23b8a41e74aa867693f90dfb061a6e86dfaaee64472c00e5f20945729cbebe77f06ce78e08f4098fba41f9d6193c0317e8b60d4b6084acb42d29e3808a3bc372d85e331170fcbf7cc72d0b71c296648b3a4d10f416295d0807aa625cab2744fd9ea8fd223c42537029828bd16be02546f130fd2e33b936d2676e08aed1b73318b750a0167d0");
+
+ private byte[] slt1a = Hex.decode("dee959c7e06411361420ff80185ed57f3e6776af");
+
+ private byte[] sig1a = Hex.decode("9074308fb598e9701b2294388e52f971faac2b60a5145af185df5287b5ed2887e57ce7fd44dc8634e407c8e0e4360bc226f3ec227f9d9e54638e8d31f5051215df6ebb9c2f9579aa77598a38f914b5b9c1bd83c4e2f9f382a0d0aa3542ffee65984a601bc69eb28deb27dca12c82c2d4c3f66cd500f1ff2b994d8a4e30cbb33c");
+
+ // PSSExample1.2
+
+ private byte[] msg1b = Hex.decode("851384cdfe819c22ed6c4ccb30daeb5cf059bc8e1166b7e3530c4c233e2b5f8f71a1cca582d43ecc72b1bca16dfc7013226b9e");
+
+ private byte[] slt1b = Hex.decode("ef2869fa40c346cb183dab3d7bffc98fd56df42d");
+
+ private byte[] sig1b = Hex.decode("3ef7f46e831bf92b32274142a585ffcefbdca7b32ae90d10fb0f0c729984f04ef29a9df0780775ce43739b97838390db0a5505e63de927028d9d29b219ca2c4517832558a55d694a6d25b9dab66003c4cccd907802193be5170d26147d37b93590241be51c25055f47ef62752cfbe21418fafe98c22c4d4d47724fdb5669e843");
+
+ //
+ // Example 2: A 1025-bit RSA keypair
+ //
+
+ private RSAKeyParameters pub2 = new RSAKeyParameters(false,
+ new BigInteger("01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9", 16),
+ new BigInteger("010001", 16));
+
+ private RSAKeyParameters prv2 = new RSAPrivateCrtKeyParameters(
+ new BigInteger("01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9", 16),
+ new BigInteger("010001", 16),
+ new BigInteger("027d147e4673057377fd1ea201565772176a7dc38358d376045685a2e787c23c15576bc16b9f444402d6bfc5d98a3e88ea13ef67c353eca0c0ddba9255bd7b8bb50a644afdfd1dd51695b252d22e7318d1b6687a1c10ff75545f3db0fe602d5f2b7f294e3601eab7b9d1cecd767f64692e3e536ca2846cb0c2dd486a39fa75b1", 16),
+ new BigInteger("016601e926a0f8c9e26ecab769ea65a5e7c52cc9e080ef519457c644da6891c5a104d3ea7955929a22e7c68a7af9fcad777c3ccc2b9e3d3650bce404399b7e59d1", 16),
+ new BigInteger("014eafa1d4d0184da7e31f877d1281ddda625664869e8379e67ad3b75eae74a580e9827abd6eb7a002cb5411f5266797768fb8e95ae40e3e8a01f35ff89e56c079", 16),
+ new BigInteger("e247cce504939b8f0a36090de200938755e2444b29539a7da7a902f6056835c0db7b52559497cfe2c61a8086d0213c472c78851800b171f6401de2e9c2756f31", 16),
+ new BigInteger("b12fba757855e586e46f64c38a70c68b3f548d93d787b399999d4c8f0bbd2581c21e19ed0018a6d5d3df86424b3abcad40199d31495b61309f27c1bf55d487c1", 16),
+ new BigInteger("564b1e1fa003bda91e89090425aac05b91da9ee25061e7628d5f51304a84992fdc33762bd378a59f030a334d532bd0dae8f298ea9ed844636ad5fb8cbdc03cad", 16));
+
+ // PSS Example 2.1
+
+ private byte[] msg2a = Hex.decode("daba032066263faedb659848115278a52c44faa3a76f37515ed336321072c40a9d9b53bc05014078adf520875146aae70ff060226dcb7b1f1fc27e9360");
+ private byte[] slt2a = Hex.decode("57bf160bcb02bb1dc7280cf0458530b7d2832ff7");
+ private byte[] sig2a = Hex.decode("014c5ba5338328ccc6e7a90bf1c0ab3fd606ff4796d3c12e4b639ed9136a5fec6c16d8884bdd99cfdc521456b0742b736868cf90de099adb8d5ffd1deff39ba4007ab746cefdb22d7df0e225f54627dc65466131721b90af445363a8358b9f607642f78fab0ab0f43b7168d64bae70d8827848d8ef1e421c5754ddf42c2589b5b3");
+
+ // PSS Example 2.2
+
+ private byte[] msg2b = Hex.decode("e4f8601a8a6da1be34447c0959c058570c3668cfd51dd5f9ccd6ad4411fe8213486d78a6c49f93efc2ca2288cebc2b9b60bd04b1e220d86e3d4848d709d032d1e8c6a070c6af9a499fcf95354b14ba6127c739de1bb0fd16431e46938aec0cf8ad9eb72e832a7035de9b7807bdc0ed8b68eb0f5ac2216be40ce920c0db0eddd3860ed788efaccaca502d8f2bd6d1a7c1f41ff46f1681c8f1f818e9c4f6d91a0c7803ccc63d76a6544d843e084e363b8acc55aa531733edb5dee5b5196e9f03e8b731b3776428d9e457fe3fbcb3db7274442d785890e9cb0854b6444dace791d7273de1889719338a77fe");
+ private byte[] slt2b = Hex.decode("7f6dd359e604e60870e898e47b19bf2e5a7b2a90");
+ private byte[] sig2b = Hex.decode("010991656cca182b7f29d2dbc007e7ae0fec158eb6759cb9c45c5ff87c7635dd46d150882f4de1e9ae65e7f7d9018f6836954a47c0a81a8a6b6f83f2944d6081b1aa7c759b254b2c34b691da67cc0226e20b2f18b42212761dcd4b908a62b371b5918c5742af4b537e296917674fb914194761621cc19a41f6fb953fbcbb649dea");
+
+ //
+ // Example 4: A 1027-bit RSA key pair
+ //
+
+ private RSAKeyParameters pub4 = new RSAKeyParameters(false,
+ new BigInteger("054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705", 16),
+ new BigInteger("010001", 16));
+
+ private RSAKeyParameters prv4 = new RSAPrivateCrtKeyParameters(
+ new BigInteger("054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705", 16),
+ new BigInteger("010001", 16),
+ new BigInteger("fa041f8cd9697ceed38ec8caa275523b4dd72b09a301d3541d72f5d31c05cbce2d6983b36183af10690bd46c46131e35789431a556771dd0049b57461bf060c1f68472e8a67c25f357e5b6b4738fa541a730346b4a07649a2dfa806a69c975b6aba64678acc7f5913e89c622f2d8abb1e3e32554e39df94ba60c002e387d9011", 16),
+ new BigInteger("029232336d2838945dba9dd7723f4e624a05f7375b927a87abe6a893a1658fd49f47f6c7b0fa596c65fa68a23f0ab432962d18d4343bd6fd671a5ea8d148413995", 16),
+ new BigInteger("020ef5efe7c5394aed2272f7e81a74f4c02d145894cb1b3cab23a9a0710a2afc7e3329acbb743d01f680c4d02afb4c8fde7e20930811bb2b995788b5e872c20bb1", 16),
+ new BigInteger("026e7e28010ecf2412d9523ad704647fb4fe9b66b1a681581b0e15553a89b1542828898f27243ebab45ff5e1acb9d4df1b051fbc62824dbc6f6c93261a78b9a759", 16),
+ new BigInteger("012ddcc86ef655998c39ddae11718669e5e46cf1495b07e13b1014cd69b3af68304ad2a6b64321e78bf3bbca9bb494e91d451717e2d97564c6549465d0205cf421", 16),
+ new BigInteger("010600c4c21847459fe576703e2ebecae8a5094ee63f536bf4ac68d3c13e5e4f12ac5cc10ab6a2d05a199214d1824747d551909636b774c22cac0b837599abcc75", 16));
+
+ // PSS Example 4.1
+
+ private byte[] msg4a = Hex.decode("9fb03b827c8217d9");
+
+ private byte[] slt4a = Hex.decode("ed7c98c95f30974fbe4fbddcf0f28d6021c0e91d");
+
+ private byte[] sig4a = Hex.decode("0323d5b7bf20ba4539289ae452ae4297080feff4518423ff4811a817837e7d82f1836cdfab54514ff0887bddeebf40bf99b047abc3ecfa6a37a3ef00f4a0c4a88aae0904b745c846c4107e8797723e8ac810d9e3d95dfa30ff4966f4d75d13768d20857f2b1406f264cfe75e27d7652f4b5ed3575f28a702f8c4ed9cf9b2d44948");
+
+ // PSS Example 4.2
+
+ private byte[] msg4b = Hex.decode("0ca2ad77797ece86de5bf768750ddb5ed6a3116ad99bbd17edf7f782f0db1cd05b0f677468c5ea420dc116b10e80d110de2b0461ea14a38be68620392e7e893cb4ea9393fb886c20ff790642305bf302003892e54df9f667509dc53920df583f50a3dd61abb6fab75d600377e383e6aca6710eeea27156e06752c94ce25ae99fcbf8592dbe2d7e27453cb44de07100ebb1a2a19811a478adbeab270f94e8fe369d90b3ca612f9f");
+
+ private byte[] slt4b = Hex.decode("22d71d54363a4217aa55113f059b3384e3e57e44");
+
+ private byte[] sig4b = Hex.decode("049d0185845a264d28feb1e69edaec090609e8e46d93abb38371ce51f4aa65a599bdaaa81d24fba66a08a116cb644f3f1e653d95c89db8bbd5daac2709c8984000178410a7c6aa8667ddc38c741f710ec8665aa9052be929d4e3b16782c1662114c5414bb0353455c392fc28f3db59054b5f365c49e1d156f876ee10cb4fd70598");
+
+
+ //
+ // Example 8: A 1031-bit RSA key pair
+ //
+
+ private RSAKeyParameters pub8 = new RSAKeyParameters(false,
+ new BigInteger("495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f", 16),
+ new BigInteger("010001", 16));
+
+ private RSAKeyParameters prv8 = new RSAPrivateCrtKeyParameters(
+ new BigInteger("495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f", 16),
+ new BigInteger("010001", 16),
+ new BigInteger("6c66ffe98980c38fcdeab5159898836165f4b4b817c4f6a8d486ee4ea9130fe9b9092bd136d184f95f504a607eac565846d2fdd6597a8967c7396ef95a6eeebb4578a643966dca4d8ee3de842de63279c618159c1ab54a89437b6a6120e4930afb52a4ba6ced8a4947ac64b30a3497cbe701c2d6266d517219ad0ec6d347dbe9", 16),
+ new BigInteger("08dad7f11363faa623d5d6d5e8a319328d82190d7127d2846c439b0ab72619b0a43a95320e4ec34fc3a9cea876422305bd76c5ba7be9e2f410c8060645a1d29edb", 16),
+ new BigInteger("0847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca4174825b48f49706d", 16),
+ new BigInteger("05c2a83c124b3621a2aa57ea2c3efe035eff4560f33ddebb7adab81fce69a0c8c2edc16520dda83d59a23be867963ac65f2cc710bbcfb96ee103deb771d105fd85", 16),
+ new BigInteger("04cae8aa0d9faa165c87b682ec140b8ed3b50b24594b7a3b2c220b3669bb819f984f55310a1ae7823651d4a02e99447972595139363434e5e30a7e7d241551e1b9", 16),
+ new BigInteger("07d3e47bf686600b11ac283ce88dbb3f6051e8efd04680e44c171ef531b80b2b7c39fc766320e2cf15d8d99820e96ff30dc69691839c4b40d7b06e45307dc91f3f", 16));
+
+ // PSS Example 8.1
+
+ private byte[] msg8a = Hex.decode("81332f4be62948415ea1d899792eeacf6c6e1db1da8be13b5cea41db2fed467092e1ff398914c714259775f595f8547f735692a575e6923af78f22c6997ddb90fb6f72d7bb0dd5744a31decd3dc3685849836ed34aec596304ad11843c4f88489f209735f5fb7fdaf7cec8addc5818168f880acbf490d51005b7a8e84e43e54287977571dd99eea4b161eb2df1f5108f12a4142a83322edb05a75487a3435c9a78ce53ed93bc550857d7a9fb");
+
+ private byte[] slt8a = Hex.decode("1d65491d79c864b373009be6f6f2467bac4c78fa");
+
+ private byte[] sig8a = Hex.decode("0262ac254bfa77f3c1aca22c5179f8f040422b3c5bafd40a8f21cf0fa5a667ccd5993d42dbafb409c520e25fce2b1ee1e716577f1efa17f3da28052f40f0419b23106d7845aaf01125b698e7a4dfe92d3967bb00c4d0d35ba3552ab9a8b3eef07c7fecdbc5424ac4db1e20cb37d0b2744769940ea907e17fbbca673b20522380c5");
+
+ // PSS Example 8.2
+
+ private byte[] msg8b = Hex.decode("e2f96eaf0e05e7ba326ecca0ba7fd2f7c02356f3cede9d0faabf4fcc8e60a973e5595fd9ea08");
+
+ private byte[] slt8b = Hex.decode("435c098aa9909eb2377f1248b091b68987ff1838");
+
+ private byte[] sig8b = Hex.decode("2707b9ad5115c58c94e932e8ec0a280f56339e44a1b58d4ddcff2f312e5f34dcfe39e89c6a94dcee86dbbdae5b79ba4e0819a9e7bfd9d982e7ee6c86ee68396e8b3a14c9c8f34b178eb741f9d3f121109bf5c8172fada2e768f9ea1433032c004a8aa07eb990000a48dc94c8bac8aabe2b09b1aa46c0a2aa0e12f63fbba775ba7e");
+
+ //
+ // Example 9: A 1536-bit RSA key pair
+ //
+
+ private RSAKeyParameters pub9 = new RSAKeyParameters(false,
+ new BigInteger("e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b", 16),
+ new BigInteger("010001", 16));
+
+ private RSAKeyParameters prv9 = new RSAPrivateCrtKeyParameters(
+ new BigInteger("e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b", 16),
+ new BigInteger("010001", 16),
+ new BigInteger("6a7fd84fb85fad073b34406db74f8d61a6abc12196a961dd79565e9da6e5187bce2d980250f7359575359270d91590bb0e427c71460b55d51410b191bcf309fea131a92c8e702738fa719f1e0041f52e40e91f229f4d96a1e6f172e15596b4510a6daec26105f2bebc53316b87bdf21311666070e8dfee69d52c71a976caae79c72b68d28580dc686d9f5129d225f82b3d615513a882b3db91416b48ce08888213e37eeb9af800d81cab328ce420689903c00c7b5fd31b75503a6d419684d629", 16),
+ new BigInteger("f8eb97e98df12664eefdb761596a69ddcd0e76daece6ed4bf5a1b50ac086f7928a4d2f8726a77e515b74da41988f220b1cc87aa1fc810ce99a82f2d1ce821edced794c6941f42c7a1a0b8c4d28c75ec60b652279f6154a762aed165d47dee367", 16),
+ new BigInteger("ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e4728cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b489c176128092d629e49d3d", 16),
+ new BigInteger("2bb68bddfb0c4f56c8558bffaf892d8043037841e7fa81cfa61a38c5e39b901c8ee71122a5da2227bd6cdeeb481452c12ad3d61d5e4f776a0ab556591befe3e59e5a7fddb8345e1f2f35b9f4cee57c32414c086aec993e9353e480d9eec6289f", 16),
+ new BigInteger("4ff897709fad079746494578e70fd8546130eeab5627c49b080f05ee4ad9f3e4b7cba9d6a5dff113a41c3409336833f190816d8a6bc42e9bec56b7567d0f3c9c696db619b245d901dd856db7c8092e77e9a1cccd56ee4dba42c5fdb61aec2669", 16),
+ new BigInteger("77b9d1137b50404a982729316efafc7dfe66d34e5a182600d5f30a0a8512051c560d081d4d0a1835ec3d25a60f4e4d6aa948b2bf3dbb5b124cbbc3489255a3a948372f6978496745f943e1db4f18382ceaa505dfc65757bb3f857a58dce52156", 16));
+
+ // PSS Example 9.1
+
+ private byte[] msg9a = Hex.decode("a88e265855e9d7ca36c68795f0b31b591cd6587c71d060a0b3f7f3eaef43795922028bc2b6ad467cfc2d7f659c5385aa70ba3672cdde4cfe4970cc7904601b278872bf51321c4a972f3c95570f3445d4f57980e0f20df54846e6a52c668f1288c03f95006ea32f562d40d52af9feb32f0fa06db65b588a237b34e592d55cf979f903a642ef64d2ed542aa8c77dc1dd762f45a59303ed75e541ca271e2b60ca709e44fa0661131e8d5d4163fd8d398566ce26de8730e72f9cca737641c244159420637028df0a18079d6208ea8b4711a2c750f5");
+
+ private byte[] slt9a = Hex.decode("c0a425313df8d7564bd2434d311523d5257eed80");
+
+ private byte[] sig9a = Hex.decode("586107226c3ce013a7c8f04d1a6a2959bb4b8e205ba43a27b50f124111bc35ef589b039f5932187cb696d7d9a32c0c38300a5cdda4834b62d2eb240af33f79d13dfbf095bf599e0d9686948c1964747b67e89c9aba5cd85016236f566cc5802cb13ead51bc7ca6bef3b94dcbdbb1d570469771df0e00b1a8a06777472d2316279edae86474668d4e1efff95f1de61c6020da32ae92bbf16520fef3cf4d88f61121f24bbd9fe91b59caf1235b2a93ff81fc403addf4ebdea84934a9cdaf8e1a9e");
+
+ // PSS Example 9.2
+
+ private byte[] msg9b = Hex.decode("c8c9c6af04acda414d227ef23e0820c3732c500dc87275e95b0d095413993c2658bc1d988581ba879c2d201f14cb88ced153a01969a7bf0a7be79c84c1486bc12b3fa6c59871b6827c8ce253ca5fefa8a8c690bf326e8e37cdb96d90a82ebab69f86350e1822e8bd536a2e");
+
+ private byte[] slt9b = Hex.decode("b307c43b4850a8dac2f15f32e37839ef8c5c0e91");
+
+ private byte[] sig9b = Hex.decode("80b6d643255209f0a456763897ac9ed259d459b49c2887e5882ecb4434cfd66dd7e1699375381e51cd7f554f2c271704b399d42b4be2540a0eca61951f55267f7c2878c122842dadb28b01bd5f8c025f7e228418a673c03d6bc0c736d0a29546bd67f786d9d692ccea778d71d98c2063b7a71092187a4d35af108111d83e83eae46c46aa34277e06044589903788f1d5e7cee25fb485e92949118814d6f2c3ee361489016f327fb5bc517eb50470bffa1afa5f4ce9aa0ce5b8ee19bf5501b958");
+
+
+ public String getName()
+ {
+ return "PSSBlindTest";
+ }
+
+ private void testSig(
+ int id,
+ RSAKeyParameters pub,
+ RSAKeyParameters prv,
+ byte[] slt,
+ byte[] msg,
+ byte[] sig)
+ throws Exception
+ {
+ RSABlindingFactorGenerator blindFactorGen = new RSABlindingFactorGenerator();
+ RSABlindingEngine blindingEngine = new RSABlindingEngine();
+ PSSSigner blindSigner = new PSSSigner(blindingEngine, new SHA1Digest(), 20);
+ PSSSigner signer = new PSSSigner(new RSAEngine(), new SHA1Digest(), 20);
+
+ blindFactorGen.init(pub);
+
+ BigInteger blindFactor = blindFactorGen.generateBlindingFactor();
+ RSABlindingParameters params = new RSABlindingParameters(pub, blindFactor);
+
+ // generate a blind signature
+ blindSigner.init(true, new ParametersWithRandom(params, new FixedRandom(slt)));
+
+ blindSigner.update(msg, 0, msg.length);
+
+ byte[] blindedData = blindSigner.generateSignature();
+
+ RSAEngine signerEngine = new RSAEngine();
+
+ signerEngine.init(true, prv);
+
+ byte[] blindedSig = signerEngine.processBlock(blindedData, 0, blindedData.length);
+
+ // unblind the signature
+ blindingEngine.init(false, params);
+
+ byte[] s = blindingEngine.processBlock(blindedSig, 0, blindedSig.length);
+
+ //signature verification
+ if (!areEqual(s, sig))
+ {
+ fail("test " + id + " failed generation");
+ }
+
+ //verify signature with PSSSigner
+ signer.init(false, pub);
+ signer.update(msg, 0, msg.length);
+
+ if (!signer.verifySignature(s))
+ {
+ fail("test " + id + " failed PSSSigner verification");
+ }
+ }
+
+ private boolean isProcessingOkay(
+ RSAKeyParameters pub,
+ RSAKeyParameters prv,
+ byte[] data,
+ SecureRandom random)
+ throws Exception
+ {
+ RSABlindingFactorGenerator blindFactorGen = new RSABlindingFactorGenerator();
+ RSABlindingEngine blindingEngine = new RSABlindingEngine();
+ PSSSigner blindSigner = new PSSSigner(blindingEngine, new SHA1Digest(), 20);
+ PSSSigner pssEng = new PSSSigner(new RSAEngine(), new SHA1Digest(), 20);
+
+ random.nextBytes(data);
+
+ blindFactorGen.init(pub);
+
+ BigInteger blindFactor = blindFactorGen.generateBlindingFactor();
+ RSABlindingParameters params = new RSABlindingParameters(pub, blindFactor);
+
+ // generate a blind signature
+ blindSigner.init(true, new ParametersWithRandom(params, random));
+
+ blindSigner.update(data, 0, data.length);
+
+ byte[] blindedData = blindSigner.generateSignature();
+
+ RSAEngine signerEngine = new RSAEngine();
+
+ signerEngine.init(true, prv);
+
+ byte[] blindedSig = signerEngine.processBlock(blindedData, 0, blindedData.length);
+
+ // unblind the signature
+ blindingEngine.init(false, params);
+
+ byte[] s = blindingEngine.processBlock(blindedSig, 0, blindedSig.length);
+
+ //verify signature with PSSSigner
+ pssEng.init(false, pub);
+ pssEng.update(data, 0, data.length);
+
+ return pssEng.verifySignature(s);
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ testSig(1, pub1, prv1, slt1a, msg1a, sig1a);
+ testSig(2, pub1, prv1, slt1b, msg1b, sig1b);
+ testSig(3, pub2, prv2, slt2a, msg2a, sig2a);
+ testSig(4, pub2, prv2, slt2b, msg2b, sig2b);
+ testSig(5, pub4, prv4, slt4a, msg4a, sig4a);
+ testSig(6, pub4, prv4, slt4b, msg4b, sig4b);
+ testSig(7, pub8, prv8, slt8a, msg8a, sig8a);
+ testSig(8, pub8, prv8, slt8b, msg8b, sig8b);
+ testSig(9, pub9, prv9, slt9a, msg9a, sig9a);
+ testSig(10, pub9, prv9, slt9b, msg9b, sig9b);
+
+ //
+ // loop test
+ //
+ int failed = 0;
+ byte[] data = new byte[DATA_LENGTH];
+
+ SecureRandom random = new SecureRandom();
+
+
+ RSAKeyParameters[] kprv ={prv1, prv2, prv4, prv8, prv9};
+ RSAKeyParameters[] kpub ={pub1, pub2, pub4, pub8, pub9};
+
+ int i = 0;
+ for (int j = 0; j < NUM_TESTS; j++, i++)
+ {
+ if (i == kprv.length)
+ {
+ i = 0;
+ }
+
+ if (!isProcessingOkay(kpub[i], kprv[i], data, random))
+ {
+ failed++;
+ }
+ }
+
+ if (failed != 0)
+ {
+ fail("loop test failed - failures: " + failed);
+ }
+
+ //
+ // key generation test
+ //
+ RSAKeyPairGenerator pGen = new RSAKeyPairGenerator();
+ RSAKeyGenerationParameters genParam = new RSAKeyGenerationParameters(
+ BigInteger.valueOf(0x11), new SecureRandom(), 1024, 25);
+
+ pGen.init(genParam);
+ failed = 0;
+
+ for (int k = 0; k < NUM_TESTS_WITH_KEY_GENERATION; k++)
+ {
+ AsymmetricCipherKeyPair pair = pGen.generateKeyPair();
+
+ for (int j = 0; j < NUM_TESTS; j++)
+ {
+ if (!isProcessingOkay((RSAKeyParameters)pair.getPublic(), (RSAKeyParameters)pair.getPrivate(), data, random))
+ {
+ failed++;
+ }
+ }
+
+ }
+
+ if (failed != 0)
+ {
+ fail("loop test with key generation failed - failures: " + failed);
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new PSSBlindTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/PSSTest.java b/core/src/test/java/org/spongycastle/crypto/test/PSSTest.java
new file mode 100644
index 00000000..517433a6
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/PSSTest.java
@@ -0,0 +1,332 @@
+package org.spongycastle.crypto.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.engines.RSAEngine;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+import org.spongycastle.crypto.params.RSAPrivateCrtKeyParameters;
+import org.spongycastle.crypto.signers.PSSSigner;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/*
+ * RSA PSS test vectors for PKCS#1 V2.1
+ */
+public class PSSTest
+ extends SimpleTest
+{
+ private final int DATA_LENGTH = 1000;
+ private final int NUM_TESTS = 500;
+
+ private class FixedRandom
+ extends SecureRandom
+ {
+ byte[] vals;
+
+ FixedRandom(
+ byte[] vals)
+ {
+ this.vals = vals;
+ }
+
+ public void nextBytes(
+ byte[] bytes)
+ {
+ System.arraycopy(vals, 0, bytes, 0, vals.length);
+ }
+ }
+
+ //
+ // Example 1: A 1024-bit RSA keypair
+ //
+ private RSAKeyParameters pub1 = new RSAKeyParameters(false,
+ new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",16),
+ new BigInteger("010001",16));
+
+ private RSAKeyParameters prv1 = new RSAPrivateCrtKeyParameters(
+ new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",16),
+ new BigInteger("010001",16),
+ new BigInteger("33a5042a90b27d4f5451ca9bbbd0b44771a101af884340aef9885f2a4bbe92e894a724ac3c568c8f97853ad07c0266c8c6a3ca0929f1e8f11231884429fc4d9ae55fee896a10ce707c3ed7e734e44727a39574501a532683109c2abacaba283c31b4bd2f53c3ee37e352cee34f9e503bd80c0622ad79c6dcee883547c6a3b325",16),
+ new BigInteger("e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443",16),
+ new BigInteger("b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd",16),
+ new BigInteger("28fa13938655be1f8a159cbaca5a72ea190c30089e19cd274a556f36c4f6e19f554b34c077790427bbdd8dd3ede2448328f385d81b30e8e43b2fffa027861979",16),
+ new BigInteger("1a8b38f398fa712049898d7fb79ee0a77668791299cdfa09efc0e507acb21ed74301ef5bfd48be455eaeb6e1678255827580a8e4e8e14151d1510a82a3f2e729",16),
+ new BigInteger("27156aba4126d24a81f3a528cbfb27f56886f840a9f6e86e17a44b94fe9319584b8e22fdde1e5a2e3bd8aa5ba8d8584194eb2190acf832b847f13a3d24a79f4d",16));
+
+ // PSSExample1.1
+
+ private byte[] msg1a = Hex.decode("cdc87da223d786df3b45e0bbbc721326d1ee2af806cc315475cc6f0d9c66e1b62371d45ce2392e1ac92844c310102f156a0d8d52c1f4c40ba3aa65095786cb769757a6563ba958fed0bcc984e8b517a3d5f515b23b8a41e74aa867693f90dfb061a6e86dfaaee64472c00e5f20945729cbebe77f06ce78e08f4098fba41f9d6193c0317e8b60d4b6084acb42d29e3808a3bc372d85e331170fcbf7cc72d0b71c296648b3a4d10f416295d0807aa625cab2744fd9ea8fd223c42537029828bd16be02546f130fd2e33b936d2676e08aed1b73318b750a0167d0");
+
+ private byte[] slt1a = Hex.decode("dee959c7e06411361420ff80185ed57f3e6776af");
+
+ private byte[] sig1a = Hex.decode("9074308fb598e9701b2294388e52f971faac2b60a5145af185df5287b5ed2887e57ce7fd44dc8634e407c8e0e4360bc226f3ec227f9d9e54638e8d31f5051215df6ebb9c2f9579aa77598a38f914b5b9c1bd83c4e2f9f382a0d0aa3542ffee65984a601bc69eb28deb27dca12c82c2d4c3f66cd500f1ff2b994d8a4e30cbb33c");
+
+ // PSSExample1.2
+
+ private byte[] msg1b = Hex.decode("851384cdfe819c22ed6c4ccb30daeb5cf059bc8e1166b7e3530c4c233e2b5f8f71a1cca582d43ecc72b1bca16dfc7013226b9e");
+
+ private byte[] slt1b = Hex.decode("ef2869fa40c346cb183dab3d7bffc98fd56df42d");
+
+ private byte[] sig1b = Hex.decode("3ef7f46e831bf92b32274142a585ffcefbdca7b32ae90d10fb0f0c729984f04ef29a9df0780775ce43739b97838390db0a5505e63de927028d9d29b219ca2c4517832558a55d694a6d25b9dab66003c4cccd907802193be5170d26147d37b93590241be51c25055f47ef62752cfbe21418fafe98c22c4d4d47724fdb5669e843");
+
+ //
+ // Example 2: A 1025-bit RSA keypair
+ //
+
+ private RSAKeyParameters pub2 = new RSAKeyParameters(false,
+ new BigInteger("01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9", 16),
+ new BigInteger("010001", 16));
+
+ private RSAKeyParameters prv2 = new RSAPrivateCrtKeyParameters(
+ new BigInteger("01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9", 16),
+ new BigInteger("010001", 16),
+ new BigInteger("027d147e4673057377fd1ea201565772176a7dc38358d376045685a2e787c23c15576bc16b9f444402d6bfc5d98a3e88ea13ef67c353eca0c0ddba9255bd7b8bb50a644afdfd1dd51695b252d22e7318d1b6687a1c10ff75545f3db0fe602d5f2b7f294e3601eab7b9d1cecd767f64692e3e536ca2846cb0c2dd486a39fa75b1", 16),
+ new BigInteger("016601e926a0f8c9e26ecab769ea65a5e7c52cc9e080ef519457c644da6891c5a104d3ea7955929a22e7c68a7af9fcad777c3ccc2b9e3d3650bce404399b7e59d1", 16),
+ new BigInteger("014eafa1d4d0184da7e31f877d1281ddda625664869e8379e67ad3b75eae74a580e9827abd6eb7a002cb5411f5266797768fb8e95ae40e3e8a01f35ff89e56c079", 16),
+ new BigInteger("e247cce504939b8f0a36090de200938755e2444b29539a7da7a902f6056835c0db7b52559497cfe2c61a8086d0213c472c78851800b171f6401de2e9c2756f31", 16),
+ new BigInteger("b12fba757855e586e46f64c38a70c68b3f548d93d787b399999d4c8f0bbd2581c21e19ed0018a6d5d3df86424b3abcad40199d31495b61309f27c1bf55d487c1", 16),
+ new BigInteger("564b1e1fa003bda91e89090425aac05b91da9ee25061e7628d5f51304a84992fdc33762bd378a59f030a334d532bd0dae8f298ea9ed844636ad5fb8cbdc03cad", 16));
+
+ // PSS Example 2.1
+
+ private byte[] msg2a = Hex.decode("daba032066263faedb659848115278a52c44faa3a76f37515ed336321072c40a9d9b53bc05014078adf520875146aae70ff060226dcb7b1f1fc27e9360");
+ private byte[] slt2a = Hex.decode("57bf160bcb02bb1dc7280cf0458530b7d2832ff7");
+ private byte[] sig2a = Hex.decode("014c5ba5338328ccc6e7a90bf1c0ab3fd606ff4796d3c12e4b639ed9136a5fec6c16d8884bdd99cfdc521456b0742b736868cf90de099adb8d5ffd1deff39ba4007ab746cefdb22d7df0e225f54627dc65466131721b90af445363a8358b9f607642f78fab0ab0f43b7168d64bae70d8827848d8ef1e421c5754ddf42c2589b5b3");
+
+ // PSS Example 2.2
+
+ private byte[] msg2b = Hex.decode("e4f8601a8a6da1be34447c0959c058570c3668cfd51dd5f9ccd6ad4411fe8213486d78a6c49f93efc2ca2288cebc2b9b60bd04b1e220d86e3d4848d709d032d1e8c6a070c6af9a499fcf95354b14ba6127c739de1bb0fd16431e46938aec0cf8ad9eb72e832a7035de9b7807bdc0ed8b68eb0f5ac2216be40ce920c0db0eddd3860ed788efaccaca502d8f2bd6d1a7c1f41ff46f1681c8f1f818e9c4f6d91a0c7803ccc63d76a6544d843e084e363b8acc55aa531733edb5dee5b5196e9f03e8b731b3776428d9e457fe3fbcb3db7274442d785890e9cb0854b6444dace791d7273de1889719338a77fe");
+ private byte[] slt2b = Hex.decode("7f6dd359e604e60870e898e47b19bf2e5a7b2a90");
+ private byte[] sig2b = Hex.decode("010991656cca182b7f29d2dbc007e7ae0fec158eb6759cb9c45c5ff87c7635dd46d150882f4de1e9ae65e7f7d9018f6836954a47c0a81a8a6b6f83f2944d6081b1aa7c759b254b2c34b691da67cc0226e20b2f18b42212761dcd4b908a62b371b5918c5742af4b537e296917674fb914194761621cc19a41f6fb953fbcbb649dea");
+
+ //
+ // Example 4: A 1027-bit RSA key pair
+ //
+
+ private RSAKeyParameters pub4 = new RSAKeyParameters(false,
+ new BigInteger("054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705", 16),
+ new BigInteger("010001", 16));
+
+ private RSAKeyParameters prv4 = new RSAPrivateCrtKeyParameters(
+ new BigInteger("054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705", 16),
+ new BigInteger("010001", 16),
+ new BigInteger("fa041f8cd9697ceed38ec8caa275523b4dd72b09a301d3541d72f5d31c05cbce2d6983b36183af10690bd46c46131e35789431a556771dd0049b57461bf060c1f68472e8a67c25f357e5b6b4738fa541a730346b4a07649a2dfa806a69c975b6aba64678acc7f5913e89c622f2d8abb1e3e32554e39df94ba60c002e387d9011", 16),
+ new BigInteger("029232336d2838945dba9dd7723f4e624a05f7375b927a87abe6a893a1658fd49f47f6c7b0fa596c65fa68a23f0ab432962d18d4343bd6fd671a5ea8d148413995", 16),
+ new BigInteger("020ef5efe7c5394aed2272f7e81a74f4c02d145894cb1b3cab23a9a0710a2afc7e3329acbb743d01f680c4d02afb4c8fde7e20930811bb2b995788b5e872c20bb1", 16),
+ new BigInteger("026e7e28010ecf2412d9523ad704647fb4fe9b66b1a681581b0e15553a89b1542828898f27243ebab45ff5e1acb9d4df1b051fbc62824dbc6f6c93261a78b9a759", 16),
+ new BigInteger("012ddcc86ef655998c39ddae11718669e5e46cf1495b07e13b1014cd69b3af68304ad2a6b64321e78bf3bbca9bb494e91d451717e2d97564c6549465d0205cf421", 16),
+ new BigInteger("010600c4c21847459fe576703e2ebecae8a5094ee63f536bf4ac68d3c13e5e4f12ac5cc10ab6a2d05a199214d1824747d551909636b774c22cac0b837599abcc75", 16));
+
+ // PSS Example 4.1
+
+ private byte[] msg4a = Hex.decode("9fb03b827c8217d9");
+
+ private byte[] slt4a = Hex.decode("ed7c98c95f30974fbe4fbddcf0f28d6021c0e91d");
+
+ private byte[] sig4a = Hex.decode("0323d5b7bf20ba4539289ae452ae4297080feff4518423ff4811a817837e7d82f1836cdfab54514ff0887bddeebf40bf99b047abc3ecfa6a37a3ef00f4a0c4a88aae0904b745c846c4107e8797723e8ac810d9e3d95dfa30ff4966f4d75d13768d20857f2b1406f264cfe75e27d7652f4b5ed3575f28a702f8c4ed9cf9b2d44948");
+
+ // PSS Example 4.2
+
+ private byte[] msg4b = Hex.decode("0ca2ad77797ece86de5bf768750ddb5ed6a3116ad99bbd17edf7f782f0db1cd05b0f677468c5ea420dc116b10e80d110de2b0461ea14a38be68620392e7e893cb4ea9393fb886c20ff790642305bf302003892e54df9f667509dc53920df583f50a3dd61abb6fab75d600377e383e6aca6710eeea27156e06752c94ce25ae99fcbf8592dbe2d7e27453cb44de07100ebb1a2a19811a478adbeab270f94e8fe369d90b3ca612f9f");
+
+ private byte[] slt4b = Hex.decode("22d71d54363a4217aa55113f059b3384e3e57e44");
+
+ private byte[] sig4b = Hex.decode("049d0185845a264d28feb1e69edaec090609e8e46d93abb38371ce51f4aa65a599bdaaa81d24fba66a08a116cb644f3f1e653d95c89db8bbd5daac2709c8984000178410a7c6aa8667ddc38c741f710ec8665aa9052be929d4e3b16782c1662114c5414bb0353455c392fc28f3db59054b5f365c49e1d156f876ee10cb4fd70598");
+
+
+ //
+ // Example 8: A 1031-bit RSA key pair
+ //
+
+ private RSAKeyParameters pub8 = new RSAKeyParameters(false,
+ new BigInteger("495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f", 16),
+ new BigInteger("010001", 16));
+
+ private RSAKeyParameters prv8 = new RSAPrivateCrtKeyParameters(
+ new BigInteger("495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f", 16),
+ new BigInteger("010001", 16),
+ new BigInteger("6c66ffe98980c38fcdeab5159898836165f4b4b817c4f6a8d486ee4ea9130fe9b9092bd136d184f95f504a607eac565846d2fdd6597a8967c7396ef95a6eeebb4578a643966dca4d8ee3de842de63279c618159c1ab54a89437b6a6120e4930afb52a4ba6ced8a4947ac64b30a3497cbe701c2d6266d517219ad0ec6d347dbe9", 16),
+ new BigInteger("08dad7f11363faa623d5d6d5e8a319328d82190d7127d2846c439b0ab72619b0a43a95320e4ec34fc3a9cea876422305bd76c5ba7be9e2f410c8060645a1d29edb", 16),
+ new BigInteger("0847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca4174825b48f49706d", 16),
+ new BigInteger("05c2a83c124b3621a2aa57ea2c3efe035eff4560f33ddebb7adab81fce69a0c8c2edc16520dda83d59a23be867963ac65f2cc710bbcfb96ee103deb771d105fd85", 16),
+ new BigInteger("04cae8aa0d9faa165c87b682ec140b8ed3b50b24594b7a3b2c220b3669bb819f984f55310a1ae7823651d4a02e99447972595139363434e5e30a7e7d241551e1b9", 16),
+ new BigInteger("07d3e47bf686600b11ac283ce88dbb3f6051e8efd04680e44c171ef531b80b2b7c39fc766320e2cf15d8d99820e96ff30dc69691839c4b40d7b06e45307dc91f3f", 16));
+
+ // PSS Example 8.1
+
+ private byte[] msg8a = Hex.decode("81332f4be62948415ea1d899792eeacf6c6e1db1da8be13b5cea41db2fed467092e1ff398914c714259775f595f8547f735692a575e6923af78f22c6997ddb90fb6f72d7bb0dd5744a31decd3dc3685849836ed34aec596304ad11843c4f88489f209735f5fb7fdaf7cec8addc5818168f880acbf490d51005b7a8e84e43e54287977571dd99eea4b161eb2df1f5108f12a4142a83322edb05a75487a3435c9a78ce53ed93bc550857d7a9fb");
+
+ private byte[] slt8a = Hex.decode("1d65491d79c864b373009be6f6f2467bac4c78fa");
+
+ private byte[] sig8a = Hex.decode("0262ac254bfa77f3c1aca22c5179f8f040422b3c5bafd40a8f21cf0fa5a667ccd5993d42dbafb409c520e25fce2b1ee1e716577f1efa17f3da28052f40f0419b23106d7845aaf01125b698e7a4dfe92d3967bb00c4d0d35ba3552ab9a8b3eef07c7fecdbc5424ac4db1e20cb37d0b2744769940ea907e17fbbca673b20522380c5");
+
+ // PSS Example 8.2
+
+ private byte[] msg8b = Hex.decode("e2f96eaf0e05e7ba326ecca0ba7fd2f7c02356f3cede9d0faabf4fcc8e60a973e5595fd9ea08");
+
+ private byte[] slt8b = Hex.decode("435c098aa9909eb2377f1248b091b68987ff1838");
+
+ private byte[] sig8b = Hex.decode("2707b9ad5115c58c94e932e8ec0a280f56339e44a1b58d4ddcff2f312e5f34dcfe39e89c6a94dcee86dbbdae5b79ba4e0819a9e7bfd9d982e7ee6c86ee68396e8b3a14c9c8f34b178eb741f9d3f121109bf5c8172fada2e768f9ea1433032c004a8aa07eb990000a48dc94c8bac8aabe2b09b1aa46c0a2aa0e12f63fbba775ba7e");
+
+ //
+ // Example 9: A 1536-bit RSA key pair
+ //
+
+ private RSAKeyParameters pub9 = new RSAKeyParameters(false,
+ new BigInteger("e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b", 16),
+ new BigInteger("010001", 16));
+
+ private RSAKeyParameters prv9 = new RSAPrivateCrtKeyParameters(
+ new BigInteger("e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b", 16),
+ new BigInteger("010001", 16),
+ new BigInteger("6a7fd84fb85fad073b34406db74f8d61a6abc12196a961dd79565e9da6e5187bce2d980250f7359575359270d91590bb0e427c71460b55d51410b191bcf309fea131a92c8e702738fa719f1e0041f52e40e91f229f4d96a1e6f172e15596b4510a6daec26105f2bebc53316b87bdf21311666070e8dfee69d52c71a976caae79c72b68d28580dc686d9f5129d225f82b3d615513a882b3db91416b48ce08888213e37eeb9af800d81cab328ce420689903c00c7b5fd31b75503a6d419684d629", 16),
+ new BigInteger("f8eb97e98df12664eefdb761596a69ddcd0e76daece6ed4bf5a1b50ac086f7928a4d2f8726a77e515b74da41988f220b1cc87aa1fc810ce99a82f2d1ce821edced794c6941f42c7a1a0b8c4d28c75ec60b652279f6154a762aed165d47dee367", 16),
+ new BigInteger("ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e4728cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b489c176128092d629e49d3d", 16),
+ new BigInteger("2bb68bddfb0c4f56c8558bffaf892d8043037841e7fa81cfa61a38c5e39b901c8ee71122a5da2227bd6cdeeb481452c12ad3d61d5e4f776a0ab556591befe3e59e5a7fddb8345e1f2f35b9f4cee57c32414c086aec993e9353e480d9eec6289f", 16),
+ new BigInteger("4ff897709fad079746494578e70fd8546130eeab5627c49b080f05ee4ad9f3e4b7cba9d6a5dff113a41c3409336833f190816d8a6bc42e9bec56b7567d0f3c9c696db619b245d901dd856db7c8092e77e9a1cccd56ee4dba42c5fdb61aec2669", 16),
+ new BigInteger("77b9d1137b50404a982729316efafc7dfe66d34e5a182600d5f30a0a8512051c560d081d4d0a1835ec3d25a60f4e4d6aa948b2bf3dbb5b124cbbc3489255a3a948372f6978496745f943e1db4f18382ceaa505dfc65757bb3f857a58dce52156", 16));
+
+ // PSS Example 9.1
+
+ private byte[] msg9a = Hex.decode("a88e265855e9d7ca36c68795f0b31b591cd6587c71d060a0b3f7f3eaef43795922028bc2b6ad467cfc2d7f659c5385aa70ba3672cdde4cfe4970cc7904601b278872bf51321c4a972f3c95570f3445d4f57980e0f20df54846e6a52c668f1288c03f95006ea32f562d40d52af9feb32f0fa06db65b588a237b34e592d55cf979f903a642ef64d2ed542aa8c77dc1dd762f45a59303ed75e541ca271e2b60ca709e44fa0661131e8d5d4163fd8d398566ce26de8730e72f9cca737641c244159420637028df0a18079d6208ea8b4711a2c750f5");
+
+ private byte[] slt9a = Hex.decode("c0a425313df8d7564bd2434d311523d5257eed80");
+
+ private byte[] sig9a = Hex.decode("586107226c3ce013a7c8f04d1a6a2959bb4b8e205ba43a27b50f124111bc35ef589b039f5932187cb696d7d9a32c0c38300a5cdda4834b62d2eb240af33f79d13dfbf095bf599e0d9686948c1964747b67e89c9aba5cd85016236f566cc5802cb13ead51bc7ca6bef3b94dcbdbb1d570469771df0e00b1a8a06777472d2316279edae86474668d4e1efff95f1de61c6020da32ae92bbf16520fef3cf4d88f61121f24bbd9fe91b59caf1235b2a93ff81fc403addf4ebdea84934a9cdaf8e1a9e");
+
+ // PSS Example 9.2
+
+ private byte[] msg9b = Hex.decode("c8c9c6af04acda414d227ef23e0820c3732c500dc87275e95b0d095413993c2658bc1d988581ba879c2d201f14cb88ced153a01969a7bf0a7be79c84c1486bc12b3fa6c59871b6827c8ce253ca5fefa8a8c690bf326e8e37cdb96d90a82ebab69f86350e1822e8bd536a2e");
+
+ private byte[] slt9b = Hex.decode("b307c43b4850a8dac2f15f32e37839ef8c5c0e91");
+
+ private byte[] sig9b = Hex.decode("80b6d643255209f0a456763897ac9ed259d459b49c2887e5882ecb4434cfd66dd7e1699375381e51cd7f554f2c271704b399d42b4be2540a0eca61951f55267f7c2878c122842dadb28b01bd5f8c025f7e228418a673c03d6bc0c736d0a29546bd67f786d9d692ccea778d71d98c2063b7a71092187a4d35af108111d83e83eae46c46aa34277e06044589903788f1d5e7cee25fb485e92949118814d6f2c3ee361489016f327fb5bc517eb50470bffa1afa5f4ce9aa0ce5b8ee19bf5501b958");
+
+
+ public String getName()
+ {
+ return "PSSTest";
+ }
+
+ private void testSig(
+ int id,
+ RSAKeyParameters pub,
+ RSAKeyParameters prv,
+ byte[] slt,
+ byte[] msg,
+ byte[] sig)
+ throws Exception
+ {
+ PSSSigner eng = new PSSSigner(new RSAEngine(), new SHA1Digest(), 20);
+
+ eng.init(true, new ParametersWithRandom(prv, new FixedRandom(slt)));
+
+ eng.update(msg, 0, msg.length);
+
+ byte[] s = eng.generateSignature();
+
+ if (!areEqual(s, sig))
+ {
+ fail("test " + id + " failed generation");
+ }
+
+ eng.init(false, pub);
+
+ eng.update(msg, 0, msg.length);
+
+ if (!eng.verifySignature(s))
+ {
+ fail("test " + id + " failed verification");
+ }
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ testSig(1, pub1, prv1, slt1a, msg1a, sig1a);
+ testSig(2, pub1, prv1, slt1b, msg1b, sig1b);
+ testSig(3, pub2, prv2, slt2a, msg2a, sig2a);
+ testSig(4, pub2, prv2, slt2b, msg2b, sig2b);
+ testSig(5, pub4, prv4, slt4a, msg4a, sig4a);
+ testSig(6, pub4, prv4, slt4b, msg4b, sig4b);
+ testSig(7, pub8, prv8, slt8a, msg8a, sig8a);
+ testSig(8, pub8, prv8, slt8b, msg8b, sig8b);
+ testSig(9, pub9, prv9, slt9a, msg9a, sig9a);
+ testSig(10, pub9, prv9, slt9b, msg9b, sig9b);
+
+ //
+ // loop test - sha-1 only
+ //
+ PSSSigner eng = new PSSSigner(new RSAEngine(), new SHA1Digest(), 20);
+ int failed = 0;
+ byte[] data = new byte[DATA_LENGTH];
+
+ SecureRandom random = new SecureRandom();
+ random.nextBytes(data);
+
+ for (int j = 0; j < NUM_TESTS; j++)
+ {
+ eng.init(true, new ParametersWithRandom(prv8, random));
+
+ eng.update(data, 0, data.length);
+
+ byte[] s = eng.generateSignature();
+
+ eng.init(false, pub8);
+
+ eng.update(data, 0, data.length);
+
+ if (!eng.verifySignature(s))
+ {
+ failed++;
+ }
+ }
+
+ if (failed != 0)
+ {
+ fail("loop test failed - failures: " + failed);
+ }
+
+ //
+ // loop test - sha-256 and sha-1
+ //
+ eng = new PSSSigner(new RSAEngine(), new SHA256Digest(), new SHA1Digest(), 20);
+ failed = 0;
+ data = new byte[DATA_LENGTH];
+
+ random.nextBytes(data);
+
+ for (int j = 0; j < NUM_TESTS; j++)
+ {
+ eng.init(true, new ParametersWithRandom(prv8, random));
+
+ eng.update(data, 0, data.length);
+
+ byte[] s = eng.generateSignature();
+
+ eng.init(false, pub8);
+
+ eng.update(data, 0, data.length);
+
+ if (!eng.verifySignature(s))
+ {
+ failed++;
+ }
+ }
+
+ if (failed != 0)
+ {
+ fail("loop test failed - failures: " + failed);
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new PSSTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/PaddingTest.java b/core/src/test/java/org/spongycastle/crypto/test/PaddingTest.java
new file mode 100644
index 00000000..2e905377
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/PaddingTest.java
@@ -0,0 +1,200 @@
+package org.spongycastle.crypto.test;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.engines.DESEngine;
+import org.spongycastle.crypto.paddings.BlockCipherPadding;
+import org.spongycastle.crypto.paddings.ISO10126d2Padding;
+import org.spongycastle.crypto.paddings.ISO7816d4Padding;
+import org.spongycastle.crypto.paddings.PKCS7Padding;
+import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
+import org.spongycastle.crypto.paddings.TBCPadding;
+import org.spongycastle.crypto.paddings.X923Padding;
+import org.spongycastle.crypto.paddings.ZeroBytePadding;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * General Padding tests.
+ */
+public class PaddingTest
+ extends SimpleTest
+{
+ public PaddingTest()
+ {
+ }
+
+ private void blockCheck(
+ PaddedBufferedBlockCipher cipher,
+ BlockCipherPadding padding,
+ KeyParameter key,
+ byte[] data)
+ {
+ byte[] out = new byte[data.length + 8];
+ byte[] dec = new byte[data.length];
+
+ try
+ {
+ cipher.init(true, key);
+
+ int len = cipher.processBytes(data, 0, data.length, out, 0);
+
+ len += cipher.doFinal(out, len);
+
+ cipher.init(false, key);
+
+ int decLen = cipher.processBytes(out, 0, len, dec, 0);
+
+ decLen += cipher.doFinal(dec, decLen);
+
+ if (!areEqual(data, dec))
+ {
+ fail("failed to decrypt - i = " + data.length + ", padding = " + padding.getPaddingName());
+ }
+ }
+ catch (Exception e)
+ {
+ fail("Exception - " + e.toString(), e);
+ }
+ }
+
+ public void testPadding(
+ BlockCipherPadding padding,
+ SecureRandom rand,
+ byte[] ffVector,
+ byte[] ZeroVector)
+ {
+ PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new DESEngine(), padding);
+ KeyParameter key = new KeyParameter(Hex.decode("0011223344556677"));
+
+ //
+ // ff test
+ //
+ byte[] data = { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0 };
+
+ if (ffVector != null)
+ {
+ padding.addPadding(data, 3);
+
+ if (!areEqual(data, ffVector))
+ {
+ fail("failed ff test for " + padding.getPaddingName());
+ }
+ }
+
+ //
+ // zero test
+ //
+ if (ZeroVector != null)
+ {
+ data = new byte[8];
+ padding.addPadding(data, 4);
+
+ if (!areEqual(data, ZeroVector))
+ {
+ fail("failed zero test for " + padding.getPaddingName());
+ }
+ }
+
+ for (int i = 1; i != 200; i++)
+ {
+ data = new byte[i];
+
+ rand.nextBytes(data);
+
+ blockCheck(cipher, padding, key, data);
+ }
+ }
+
+ private void testOutputSizes()
+ {
+ PaddedBufferedBlockCipher bc = new PaddedBufferedBlockCipher(new DESEngine(), new PKCS7Padding());
+ KeyParameter key = new KeyParameter(Hex.decode("0011223344556677"));
+
+ for (int i = 0; i < bc.getBlockSize() * 2; i++)
+ {
+ bc.init(true, key);
+ if (bc.getUpdateOutputSize(i) < 0)
+ {
+ fail("Padded cipher encrypt negative update output size for input size " + i);
+ }
+ if (bc.getOutputSize(i) < 0)
+ {
+ fail("Padded cipher encrypt negative output size for input size " + i);
+ }
+
+ bc.init(false, key);
+ if (bc.getUpdateOutputSize(i) < 0)
+ {
+ fail("Padded cipher decrypt negative update output size for input size " + i);
+ }
+ if (bc.getOutputSize(i) < 0)
+ {
+ fail("Padded cipher decrypt negative output size for input size " + i);
+ }
+
+ }
+ }
+
+ public void performTest()
+ {
+ SecureRandom rand = new SecureRandom(new byte[20]);
+
+ rand.setSeed(System.currentTimeMillis());
+
+ testPadding(new PKCS7Padding(), rand,
+ Hex.decode("ffffff0505050505"),
+ Hex.decode("0000000004040404"));
+
+ PKCS7Padding padder = new PKCS7Padding();
+ try
+ {
+ padder.padCount(new byte[8]);
+
+ fail("invalid padding not detected");
+ }
+ catch (InvalidCipherTextException e)
+ {
+ if (!"pad block corrupted".equals(e.getMessage()))
+ {
+ fail("wrong exception for corrupt padding: " + e);
+ }
+ }
+
+ testPadding(new ISO10126d2Padding(), rand,
+ null,
+ null);
+
+ testPadding(new X923Padding(), rand,
+ null,
+ null);
+
+ testPadding(new TBCPadding(), rand,
+ Hex.decode("ffffff0000000000"),
+ Hex.decode("00000000ffffffff"));
+
+ testPadding(new ZeroBytePadding(), rand,
+ Hex.decode("ffffff0000000000"),
+ null);
+
+ testPadding(new ISO7816d4Padding(), rand,
+ Hex.decode("ffffff8000000000"),
+ Hex.decode("0000000080000000"));
+
+ testOutputSizes();
+
+ }
+
+ public String getName()
+ {
+ return "PaddingTest";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new PaddingTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/Poly1305Test.java b/core/src/test/java/org/spongycastle/crypto/test/Poly1305Test.java
new file mode 100644
index 00000000..2410f249
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/Poly1305Test.java
@@ -0,0 +1,388 @@
+package org.spongycastle.crypto.test;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherKeyGenerator;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.engines.AESFastEngine;
+import org.spongycastle.crypto.generators.Poly1305KeyGenerator;
+import org.spongycastle.crypto.macs.Poly1305;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/*
+ */
+public class Poly1305Test
+ extends SimpleTest
+{
+ private static final int MAXLEN = 1000;
+
+ private static class KeyEngine
+ implements BlockCipher
+ {
+
+ private byte[] key;
+ private final int blockSize;
+
+ public KeyEngine(int blockSize)
+ {
+ this.blockSize = blockSize;
+ }
+
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ if (params instanceof KeyParameter)
+ {
+ this.key = ((KeyParameter)params).getKey();
+ }
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Key";
+ }
+
+ public int getBlockSize()
+ {
+ return blockSize;
+ }
+
+ public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
+ throws DataLengthException,
+ IllegalStateException
+ {
+ System.arraycopy(key, 0, out, outOff, key.length);
+ return key.length;
+ }
+
+ public void reset()
+ {
+ }
+
+ }
+
+ private static class TestCase
+ {
+ private final byte[] key;
+ private final byte[] nonce;
+ private final byte[] message;
+ private final byte[] expectedMac;
+
+ public TestCase(String key, String nonce, String message, String expectedMac)
+ {
+ this.key = Hex.decode(key);
+ // nacl test case keys are not pre-clamped
+ Poly1305KeyGenerator.clamp(this.key);
+ this.nonce = (nonce == null) ? null : Hex.decode(nonce);
+ this.message = Hex.decode(message);
+ this.expectedMac = Hex.decode(expectedMac);
+ }
+ }
+
+ private static TestCase[] CASES = {
+ // Raw Poly1305
+ // onetimeauth.c from nacl-20110221
+ new TestCase("2539121d8e234e652d651fa4c8cff880eea6a7251c1e72916d11c2cb214d3c25", null,
+ "8e993b9f48681273c29650ba32fc76ce48332ea7164d96a4476fb8c531a1186a"
+ + "c0dfc17c98dce87b4da7f011ec48c97271d2c20f9b928fe2270d6fb863d51738"
+ + "b48eeee314a7cc8ab932164548e526ae90224368517acfeabd6bb3732bc0e9da"
+ + "99832b61ca01b6de56244a9e88d5f9b37973f622a43d14a6599b1f654cb45a74e355a5",
+ "f3ffc7703f9400e52a7dfb4b3d3305d9"),
+
+ // Poly1305-AES
+ // Loop 1 of test-poly1305aes from poly1305aes-20050218
+ new TestCase("0000000000000000000000000000000000000000000000000000000000000000",
+ "00000000000000000000000000000000", "", "66e94bd4ef8a2c3b884cfa59ca342b2e"),
+ new TestCase("f795bd4a52e29ed713d313fa20e98dbcf795bd0a50e29e0710d3130a20e98d0c",
+ "917cf69ebd68b2ec9b9fe9a3eadda692", "66f7", "5ca585c75e8f8f025e710cabc9a1508b"),
+ new TestCase("e69dae0aab9f91c03a325dcc9436fa903ef49901c8e11c000430d90ad45e7603",
+ "166450152e2394835606a9d1dd2cdc8b", "66f75c0e0c7a406586", "2924f51b9c2eff5df09db61dd03a9ca1"),
+ new TestCase("85a4ea91a7de0b0d96eed0d4bf6ecf1cda4afc035087d90e503f8f0ea08c3e0d",
+ "0b6ef7a0b8f8c738b0f8d5995415271f",
+ "66f75c0e0c7a40658629e3392f7f8e3349a02191ffd49f39879a8d9d1d0e23ea",
+ "3c5a13adb18d31c64cc29972030c917d"),
+ new TestCase(
+ "25eb69bac5cdf7d6bfcee4d9d5507b82ca3c6a0da0a864024ca3090628c28e0d",
+ "046772a4f0a8de92e4f0d628cdb04484",
+ "66f75c0e0c7a40658629e3392f7f8e3349a02191ffd49f39879a8d9d1d0e23ea3caa4d240bd2ab8a8c4a6bb8d3288d9de4b793f05e97646dd4d98055de",
+ "fc5fb58dc65daf19b14d1d05da1064e8"),
+
+ // Specific test cases generated from test-poly1305aes from poly1305aes-20050218 that
+ // expose Java unsigned integer problems
+ new TestCase(
+ "95cc0e44d0b79a8856afcae1bec4fe3c" + "01bcb20bfc8b6e03609ddd09f44b060f",
+ null,
+ "66f75c0e0c7a40658629e3392f7f8e3349a02191ffd49f39879a8d9d1d0e23ea3caa4d240bd2ab8a8c4a6bb8d3288d9de4b793f05e97646dd4d98055de"
+ + "fc3e0677d956b4c62664bac15962ab15d93ccbbc03aafdbde779162ed93b55361f0f8acaa41d50ef5175927fe79ea316186516eef15001cd04d3524a55"
+ + "e4fa3c5ca479d3aaa8a897c21807f721b6270ffc68b6889d81a116799f6aaa35d8e04c7a7dd5e6da2519e8759f54e906696f5772fee093283bcef7b930"
+ + "aed50323bcbc8c820c67422c1e16bdc022a9c0277c9d95fef0ea4ee11e2b27276da811523c5acb80154989f8a67ee9e3fa30b73b0c1c34bf46e3464d97"
+ + "7cd7fcd0ac3b82721080bb0d9b982ee2c77feee983d7ba35da88ce86955002940652ab63bc56fb16f994da2b01d74356509d7d1b6d7956b0e5a557757b"
+ + "d1ced2eef8650bc5b6d426108c1518abcbd0befb6a0d5fd57a3e2dbf31458eab63df66613653d4beae73f5c40eb438fbcfdcf4a4ba46320184b9ca0da4"
+ + "dfae77de7ccc910356caea3243f33a3c81b064b3b7cedc7435c223f664227215715980e6e0bb570d459ba80d7512dbe458c8f0f3f52d659b6e8eef19ee"
+ + "71aea2ced85c7a42ffca6522a62db49a2a46eff72bd7f7e0883acd087183f0627f3537a4d558754ed63358e8182bee196735b361dc9bd64d5e34e1074a"
+ + "855655d2974cc6fa1653754cf40f561d8c7dc526aab2908ec2d2b977cde1a1fb1071e32f40e049ea20f30368ba1592b4fe57fb51595d23acbdace324cd"
+ + "d78060a17187c662368854e915402d9b52fb21e984663e41c26a109437e162cfaf071b53f77e50000a5388ff183b82ce7a1af476c416d7d204157b3633"
+ + "b2f4ec077b699b032816997e37bceded8d4a04976fd7d0c0b029f290794c3be504c5242287ea2f831f11ed5690d92775cd6e863d7731fd4da687ebfb13"
+ + "df4c41dc0fb8", "ae345d555eb04d6947bb95c0965237e2"),
+ new TestCase(
+ "76fb3635a2dc92a1f768163ab12f2187" + "cd07fd0ef8c0be0afcbdb30af4af0009",
+ null,
+ "f05204a74f0f88a7fa1a95b84ec3d8ffb36fcdc7723ea65dfe7cd464e86e0abf6b9d51db3220cfd8496ad6e6d36ebee8d990f9ce0d3bb7f72b7ab5b3ab0a73240d11efe772c857021ae859db4933cdde4387b471d2ce700fef4b81087f8f47c307881fd83017afcd15b8d21edf9b704677f46df97b07e5b83f87c8abd90af9b1d0f9e2710e8ebd0d4d1c6a055abea861f42368bed94d9373e909c1d3715b221c16bc524c55c31ec3eab204850bb2474a84f9917038eff9d921130951391b5c54f09b5e1de833ea2cd7d3b306740abb7096d1e173da83427da2adddd3631eda30b54dbf487f2b082e8646f07d6e0a87e97522ca38d4ace4954bf3db6dd3a93b06fa18eb56856627ed6cffcd7ae26374554ca18ab8905f26331d323fe10e6e70624c7bc07a70f06ecd804b48f8f7e75e910165e1beb554f1f0ec7949c9c8d429a206b4d5c0653102249b6098e6b45fac2a07ff0220b0b8ae8f4c6bcc0c813a7cd141fa8b398b42575fc395747c5a0257ac41d6c1f434cfbf5dfe8349f5347ef6b60e611f5d6c3cbc20ca2555274d1934325824cef4809da293ea13f181929e2af025bbd1c9abdc3af93afd4c50a2854ade3887f4d2c8c225168052c16e74d76d2dd3e9467a2c5b8e15c06ffbffa42b8536384139f07e195a8c9f70f514f31dca4eb2cf262c0dcbde53654b6250a29efe21d54e83c80e005a1cad36d5934ff01c32e4bc5fe06d03064ff4a268517df4a94c759289f323734318cfa5d859d4ce9c16e63d02dff0896976f521607638535d2ee8dd3312e1ddc80a55d34fe829ab954c1ebd54d929954770f1be9d32b4c05003c5c9e97943b6431e2afe820b1e967b19843e5985a131b1100517cdc363799104af91e2cf3f53cb8fd003653a6dd8a31a3f9d566a7124b0ffe9695bcb87c482eb60106f88198f766a40bc0f4873c23653c5f9e7a8e446f770beb8034cf01d21028ba15ccee21a8db918c4829d61c88bfa927bc5def831501796c5b401a60a6b1b433c9fb905c8cd40412fffee81ab",
+ "045be28cc52009f506bdbfabedacf0b4"),
+
+ };
+
+ public String getName()
+ {
+ return "Poly1305";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ testKeyGenerator();
+ testInit();
+ for (int i = 0; i < CASES.length; i++)
+ {
+ testCase(i);
+ }
+ testSequential();
+ testReset();
+ }
+
+ private void testCase(int i)
+ {
+ byte[] out = new byte[16];
+ TestCase tc = CASES[i];
+
+ final Mac mac;
+ if (tc.nonce == null)
+ {
+ // Raw Poly1305 test - don't do any transform on AES key part
+ mac = new Poly1305(new KeyEngine(16));
+ mac.init(new ParametersWithIV(new KeyParameter(tc.key), new byte[16]));
+ }
+ else
+ {
+ mac = new Poly1305(new AESFastEngine());
+ mac.init(new ParametersWithIV(new KeyParameter(tc.key), tc.nonce));
+ }
+ mac.update(tc.message, 0, tc.message.length);
+ mac.doFinal(out, 0);
+
+ if (!Arrays.areEqual(out, tc.expectedMac))
+ {
+ fail("Mismatched output " + i, new String(Hex.encode(tc.expectedMac)), new String(Hex.encode(out)));
+ }
+ }
+
+ private void testSequential()
+ {
+ // Sequential test, adapted from test-poly1305aes
+ int len;
+ byte[] kr = new byte[32];
+ byte[] m = new byte[MAXLEN];
+ byte[] n = new byte[16];
+ byte[] out = new byte[16];
+
+ int c = 0;
+ final Mac mac = new Poly1305(new AESFastEngine());
+ for (int loop = 0; loop < 13; loop++)
+ {
+ len = 0;
+ for (;;)
+ {
+ c++;
+ mac.init(new ParametersWithIV(new KeyParameter(kr), n));
+ mac.update(m, 0, len);
+ mac.doFinal(out, 0);
+
+ // if (c == 678)
+ // {
+ // TestCase tc = CASES[0];
+ //
+ // if (!Arrays.areEqual(tc.key, kr))
+ // {
+ // System.err.println("Key bad");
+ // System.err.println(new String(Hex.encode(tc.key)));
+ // System.err.println(new String(Hex.encode(kr)));
+ // System.exit(1);
+ // }
+ // if (!Arrays.areEqual(tc.nonce, n))
+ // {
+ // System.err.println("Nonce bad");
+ // System.exit(1);
+ // }
+ // System.out.printf("[%d] m: %s\n", c, new String(Hex.encode(m, 0, len)));
+ // System.out.printf("[%d] K: %s\n", c, new String(Hex.encodje(kr)));
+ // System.out.printf("[%d] N: %s\n", c, new String(Hex.encode(n)));
+ // System.out.printf("[%d] M: ", c);
+ // }
+ // System.out.printf("%d/%s\n", c, new String(Hex.encode(out)));
+
+ if (len >= MAXLEN)
+ break;
+ n[0] ^= loop;
+ for (int i = 0; i < 16; ++i)
+ n[i] ^= out[i];
+ if (len % 2 != 0)
+ for (int i = 0; i < 16; ++i)
+ kr[i] ^= out[i];
+ if (len % 3 != 0)
+ for (int i = 0; i < 16; ++i)
+ kr[i + 16] ^= out[i];
+ Poly1305KeyGenerator.clamp(kr);
+ m[len++] ^= out[0];
+ }
+ }
+ // Output after 13 loops as generated by poly1305 ref
+ if (c != 13013 || !Arrays.areEqual(out, Hex.decode("c96f60a23701a5b0fd2016f58cbe4f7e")))
+ {
+ fail("Sequential Poly1305 " + c, "c96f60a23701a5b0fd2016f58cbe4f7e", new String(Hex.encode(out)));
+ }
+ }
+
+ private void testReset()
+ {
+ CipherKeyGenerator gen = new Poly1305KeyGenerator();
+ gen.init(new KeyGenerationParameters(new SecureRandom(), 256));
+ byte[] k = gen.generateKey();
+
+ byte[] m = new byte[10000];
+ byte[] check = new byte[16];
+ byte[] out = new byte[16];
+
+ // Generate baseline
+ Mac poly = new Poly1305(new AESFastEngine());
+ poly.init(new ParametersWithIV(new KeyParameter(k), new byte[16]));
+
+ poly.update(m, 0, m.length);
+ poly.doFinal(check, 0);
+
+ // Check reset after doFinal
+ poly.update(m, 0, m.length);
+ poly.doFinal(out, 0);
+
+ if (!Arrays.areEqual(check, out))
+ {
+ fail("Mac not reset after doFinal");
+ }
+
+ // Check reset
+ poly.update((byte)1);
+ poly.update((byte)2);
+ poly.reset();
+ poly.update(m, 0, m.length);
+ poly.doFinal(out, 0);
+
+ if (!Arrays.areEqual(check, out))
+ {
+ fail("Mac not reset after doFinal");
+ }
+
+ // Check init resets
+ poly.update((byte)1);
+ poly.update((byte)2);
+ poly.init(new ParametersWithIV(new KeyParameter(k), new byte[16]));
+ poly.update(m, 0, m.length);
+ poly.doFinal(out, 0);
+
+ if (!Arrays.areEqual(check, out))
+ {
+ fail("Mac not reset after doFinal");
+ }
+ }
+
+ private void testInit()
+ {
+ CipherKeyGenerator gen = new Poly1305KeyGenerator();
+ gen.init(new KeyGenerationParameters(new SecureRandom(), 256));
+ byte[] k = gen.generateKey();
+
+ Mac poly = new Poly1305(new AESFastEngine());
+ poly.init(new ParametersWithIV(new KeyParameter(k), new byte[16]));
+
+ try
+ {
+ poly.init(new ParametersWithIV(new KeyParameter(k), new byte[15]));
+ fail("16 byte nonce required");
+ } catch (IllegalArgumentException e)
+ {
+ // Expected
+ }
+
+ try
+ {
+ byte[] k2 = new byte[k.length - 1];
+ System.arraycopy(k, 0, k2, 0, k2.length);
+ poly.init(new ParametersWithIV(new KeyParameter(k2), new byte[16]));
+ fail("32 byte key required");
+ } catch (IllegalArgumentException e)
+ {
+ // Expected
+ }
+
+ try
+ {
+ k[19] = (byte)0xFF;
+ poly.init(new ParametersWithIV(new KeyParameter(k), new byte[16]));
+ fail("Unclamped key should not be accepted.");
+ } catch (IllegalArgumentException e)
+ {
+ // Expected
+ }
+
+ }
+
+ private void testKeyGenerator()
+ {
+ CipherKeyGenerator gen = new Poly1305KeyGenerator();
+ gen.init(new KeyGenerationParameters(new SecureRandom(), 256));
+ byte[] k = gen.generateKey();
+
+ if (k.length != 32)
+ {
+ fail("Poly1305 key should be 256 bits.");
+ }
+
+ try
+ {
+ Poly1305KeyGenerator.checkKey(k);
+ } catch (IllegalArgumentException e)
+ {
+ fail("Poly1305 key should be clamped on generation.");
+ }
+
+ byte[] k2 = new byte[k.length];
+ System.arraycopy(k, 0, k2, 0, k2.length);
+ Poly1305KeyGenerator.clamp(k);
+ if (!Arrays.areEqual(k, k2))
+ {
+ fail("Poly1305 key should be clamped on generation.");
+ }
+
+ try
+ {
+ k2[19] = (byte)0xff;
+ Poly1305KeyGenerator.checkKey(k2);
+ fail("Unclamped key should fail check.");
+ } catch (IllegalArgumentException e)
+ {
+ // Expected
+ }
+ }
+
+ public static void main(String[] args)
+ throws Exception
+ {
+ runTest(new Poly1305Test());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/RC2Test.java b/core/src/test/java/org/spongycastle/crypto/test/RC2Test.java
new file mode 100644
index 00000000..fde13347
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/RC2Test.java
@@ -0,0 +1,66 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.engines.RC2Engine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.RC2Parameters;
+import org.spongycastle.util.encoders.Hex;
+
+/**
+ * RC2 tester - vectors from ftp://ftp.isi.edu/in-notes/rfc2268.txt
+ *
+ * RFC 2268 "A Description of the RC2(r) Encryption Algorithm"
+ */
+public class RC2Test
+ extends CipherTest
+{
+ static BlockCipherVectorTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new RC2Engine(),
+ new RC2Parameters(Hex.decode("0000000000000000"), 63),
+ "0000000000000000", "ebb773f993278eff"),
+
+ new BlockCipherVectorTest(1, new RC2Engine(),
+ new RC2Parameters(Hex.decode("ffffffffffffffff"), 64),
+ "ffffffffffffffff", "278b27e42e2f0d49"),
+
+ new BlockCipherVectorTest(2, new RC2Engine(),
+ new RC2Parameters(Hex.decode("3000000000000000"), 64),
+ "1000000000000001", "30649edf9be7d2c2"),
+
+ new BlockCipherVectorTest(3, new RC2Engine(),
+ new RC2Parameters(Hex.decode("88"), 64),
+ "0000000000000000", "61a8a244adacccf0"),
+
+ new BlockCipherVectorTest(4, new RC2Engine(),
+ new RC2Parameters(Hex.decode("88bca90e90875a"), 64),
+ "0000000000000000", "6ccf4308974c267f"),
+
+ new BlockCipherVectorTest(5, new RC2Engine(),
+ new RC2Parameters(Hex.decode("88bca90e90875a7f0f79c384627bafb2"), 64),
+ "0000000000000000", "1a807d272bbe5db1"),
+
+ new BlockCipherVectorTest(6, new RC2Engine(),
+ new RC2Parameters(Hex.decode("88bca90e90875a7f0f79c384627bafb2"), 128),
+ "0000000000000000", "2269552ab0f85ca6"),
+
+ new BlockCipherVectorTest(7, new RC2Engine(),
+ new RC2Parameters(Hex.decode("88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e"), 129),
+ "0000000000000000", "5b78d3a43dfff1f1")
+ };
+
+ RC2Test()
+ {
+ super(tests, new RC2Engine(), new KeyParameter(new byte[16]));
+ }
+
+ public String getName()
+ {
+ return "RC2";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new RC2Test());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/RC2WrapTest.java b/core/src/test/java/org/spongycastle/crypto/test/RC2WrapTest.java
new file mode 100644
index 00000000..27cca204
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/RC2WrapTest.java
@@ -0,0 +1,111 @@
+package org.spongycastle.crypto.test;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Wrapper;
+import org.spongycastle.crypto.engines.RC2WrapEngine;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.params.RC2Parameters;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+/**
+ * RC2 wrap tester
+ */
+public class RC2WrapTest
+ implements Test
+{
+ private class RFCRandom
+ extends SecureRandom
+ {
+ public void nextBytes(
+ byte[] nextBytes)
+ {
+ System.arraycopy(Hex.decode("4845cce7fd1250"), 0, nextBytes, 0, nextBytes.length);
+ }
+ }
+
+ private TestResult wrapTest(
+ int id,
+ CipherParameters paramsWrap,
+ CipherParameters paramsUnwrap,
+ byte[] in,
+ byte[] out)
+ {
+ Wrapper wrapper = new RC2WrapEngine();
+
+ wrapper.init(true, paramsWrap);
+
+ try
+ {
+ byte[] cText = wrapper.wrap(in, 0, in.length);
+ if (!Arrays.areEqual(cText, out))
+ {
+ return new SimpleTestResult(false, getName() + ": failed wrap test " + id + " expected " + new String(Hex.encode(out)) + " got " + new String(Hex.encode(cText)));
+ }
+ }
+ catch (Exception e)
+ {
+ return new SimpleTestResult(false, getName() + ": failed wrap test exception " + e.toString(), e);
+ }
+
+ wrapper.init(false, paramsUnwrap);
+
+ try
+ {
+ byte[] pText = wrapper.unwrap(out, 0, out.length);
+ if (!Arrays.areEqual(pText, in))
+ {
+ return new SimpleTestResult(false, getName() + ": failed unwrap test " + id + " expected " + new String(Hex.encode(in)) + " got " + new String(Hex.encode(pText)));
+ }
+ }
+ catch (Exception e)
+ {
+ return new SimpleTestResult(false, getName() + ": failed unwrap test exception " + e.toString(), e);
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+
+ public TestResult perform()
+ {
+ byte[] kek1 = Hex.decode("fd04fd08060707fb0003fefffd02fe05");
+ byte[] iv1 = Hex.decode("c7d90059b29e97f7");
+ byte[] in1 = Hex.decode("b70a25fbc9d86a86050ce0d711ead4d9");
+ byte[] out1 = Hex.decode("70e699fb5701f7833330fb71e87c85a420bdc99af05d22af5a0e48d35f3138986cbaafb4b28d4f35");
+ //
+ // note the RFC 3217 test specifies a key to be used with an effective key size of
+ // 40 bits which is why it is done here - in practice nothing less than 128 bits should be used.
+ //
+ CipherParameters paramWrap = new ParametersWithRandom(new ParametersWithIV(new RC2Parameters(kek1, 40), iv1), new RFCRandom());
+ CipherParameters paramUnwrap = new RC2Parameters(kek1, 40);
+
+ TestResult result = wrapTest(1, paramWrap, paramUnwrap, in1, out1);
+
+ if (!result.isSuccessful())
+ {
+ return result;
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+
+ public String getName()
+ {
+ return "RC2Wrap";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ RC2WrapTest test = new RC2WrapTest();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/RC4Test.java b/core/src/test/java/org/spongycastle/crypto/test/RC4Test.java
new file mode 100644
index 00000000..c03b4e51
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/RC4Test.java
@@ -0,0 +1,45 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.engines.RC4Engine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * RC4 Test
+ */
+public class RC4Test
+ extends SimpleTest
+{
+ StreamCipherVectorTest[] tests =
+ {
+ new StreamCipherVectorTest(0, new RC4Engine(),
+ new KeyParameter(Hex.decode("0123456789ABCDEF")),
+ "4e6f772069732074", "3afbb5c77938280d"),
+ new StreamCipherVectorTest(0, new RC4Engine(),
+ new KeyParameter(Hex.decode("0123456789ABCDEF")),
+ "68652074696d6520", "1cf1e29379266d59"),
+ new StreamCipherVectorTest(0, new RC4Engine(),
+ new KeyParameter(Hex.decode("0123456789ABCDEF")),
+ "666f7220616c6c20", "12fbb0c771276459")
+ };
+
+ public String getName()
+ {
+ return "RC4";
+ }
+
+ public void performTest()
+ {
+ for (int i = 0; i != tests.length; i++)
+ {
+ tests[i].performTest();
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new RC4Test());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/RC5Test.java b/core/src/test/java/org/spongycastle/crypto/test/RC5Test.java
new file mode 100644
index 00000000..29686ee0
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/RC5Test.java
@@ -0,0 +1,188 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.engines.RC532Engine;
+import org.spongycastle.crypto.engines.RC564Engine;
+import org.spongycastle.crypto.modes.CBCBlockCipher;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.crypto.params.RC5Parameters;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+/**
+ * RC5 tester - vectors from ftp://ftp.nordu.net/rfc/rfc2040.txt
+ *
+ * RFC 2040 "The RC5, RC5-CBC, RC5-CBC-Pad, and RC5-CTS Algorithms"
+ */
+public class RC5Test
+ implements Test
+{
+ BlockCipherVectorTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("00"), 0),
+ Hex.decode("0000000000000000")),
+ "0000000000000000", "7a7bba4d79111d1e"),
+ new BlockCipherVectorTest(1, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("00"), 0),
+ Hex.decode("0000000000000000")),
+ "ffffffffffffffff", "797bba4d78111d1e"),
+ new BlockCipherVectorTest(2, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("00"), 0),
+ Hex.decode("0000000000000001")),
+ "0000000000000000", "7a7bba4d79111d1f"),
+ new BlockCipherVectorTest(3, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("00"), 0),
+ Hex.decode("0000000000000000")),
+ "0000000000000001", "7a7bba4d79111d1f"),
+ new BlockCipherVectorTest(4, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("00"), 0),
+ Hex.decode("0102030405060708")),
+ "1020304050607080", "8b9ded91ce7794a6"),
+ new BlockCipherVectorTest(5, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("11"), 1),
+ Hex.decode("0000000000000000")),
+ "0000000000000000", "2f759fe7ad86a378"),
+ new BlockCipherVectorTest(6, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("00"), 2),
+ Hex.decode("0000000000000000")),
+ "0000000000000000", "dca2694bf40e0788"),
+ new BlockCipherVectorTest(7, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("00000000"), 2),
+ Hex.decode("0000000000000000")),
+ "0000000000000000", "dca2694bf40e0788"),
+ new BlockCipherVectorTest(8, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("00000000"), 8),
+ Hex.decode("0000000000000000")),
+ "0000000000000000", "dcfe098577eca5ff"),
+ new BlockCipherVectorTest(9, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("00"), 8),
+ Hex.decode("0102030405060708")),
+ "1020304050607080", "9646fb77638f9ca8"),
+ new BlockCipherVectorTest(10, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("00"), 12),
+ Hex.decode("0102030405060708")),
+ "1020304050607080", "b2b3209db6594da4"),
+ new BlockCipherVectorTest(11, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("00"), 16),
+ Hex.decode("0102030405060708")),
+ "1020304050607080", "545f7f32a5fc3836"),
+ new BlockCipherVectorTest(12, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("01020304"), 8),
+ Hex.decode("0000000000000000")),
+ "ffffffffffffffff", "8285e7c1b5bc7402"),
+ new BlockCipherVectorTest(13, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("01020304"), 12),
+ Hex.decode("0000000000000000")),
+ "ffffffffffffffff", "fc586f92f7080934"),
+ new BlockCipherVectorTest(14, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("01020304"), 16),
+ Hex.decode("0000000000000000")),
+ "ffffffffffffffff", "cf270ef9717ff7c4"),
+ new BlockCipherVectorTest(15, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("0102030405060708"), 12),
+ Hex.decode("0000000000000000")),
+ "ffffffffffffffff", "e493f1c1bb4d6e8c"),
+ new BlockCipherVectorTest(16, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("0102030405060708"), 8),
+ Hex.decode("0102030405060708")),
+ "1020304050607080", "5c4c041e0f217ac3"),
+ new BlockCipherVectorTest(17, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("0102030405060708"), 12),
+ Hex.decode("0102030405060708")),
+ "1020304050607080", "921f12485373b4f7"),
+ new BlockCipherVectorTest(18, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("0102030405060708"), 16),
+ Hex.decode("0102030405060708")),
+ "1020304050607080", "5ba0ca6bbe7f5fad"),
+ new BlockCipherVectorTest(19, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("01020304050607081020304050607080"), 8),
+ Hex.decode("0102030405060708")),
+ "1020304050607080", "c533771cd0110e63"),
+ new BlockCipherVectorTest(20, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("01020304050607081020304050607080"), 12),
+ Hex.decode("0102030405060708")),
+ "1020304050607080", "294ddb46b3278d60"),
+ new BlockCipherVectorTest(21, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("01020304050607081020304050607080"), 16),
+ Hex.decode("0102030405060708")),
+ "1020304050607080", "dad6bda9dfe8f7e8"),
+ new BlockCipherVectorTest(22, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("0102030405"), 12),
+ Hex.decode("0000000000000000")),
+ "ffffffffffffffff", "97e0787837ed317f"),
+ new BlockCipherVectorTest(23, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("0102030405"), 8),
+ Hex.decode("0000000000000000")),
+ "ffffffffffffffff", "7875dbf6738c6478"),
+ new BlockCipherVectorTest(23, new CBCBlockCipher(new RC532Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("0102030405"), 8),
+ Hex.decode("7875dbf6738c6478")),
+ "0808080808080808", "8f34c3c681c99695"),
+ new BlockCipherVectorTest(640, new CBCBlockCipher(new RC564Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("00"), 0),
+ Hex.decode("00000000000000000000000000000000")),
+ "00000000000000000000000000000000", "9f09b98d3f6062d9d4d59973d00e0e63"),
+ new BlockCipherVectorTest(641, new CBCBlockCipher(new RC564Engine()),
+ new ParametersWithIV(
+ new RC5Parameters(Hex.decode("00"), 0),
+ Hex.decode("00000000000000000000000000000000")),
+ "ffffffffffffffffffffffffffffffff", "9e09b98d3f6062d9d3d59973d00e0e63")
+ };
+
+ public String getName()
+ {
+ return "RC5";
+ }
+
+ public TestResult perform()
+ {
+ for (int i = 0; i != tests.length; i++)
+ {
+ TestResult res = tests[i].perform();
+
+ if (!res.isSuccessful())
+ {
+ return res;
+ }
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+
+ public static void main(
+ String[] args)
+ {
+ RC5Test test = new RC5Test();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/RC6Test.java b/core/src/test/java/org/spongycastle/crypto/test/RC6Test.java
new file mode 100644
index 00000000..9d91547b
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/RC6Test.java
@@ -0,0 +1,64 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.engines.RC6Engine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * RC6 Test - test vectors from AES Submitted RSA Reference implementation.
+ * ftp://ftp.funet.fi/pub/crypt/cryptography/symmetric/aes/rc6-unix-refc.tar
+ */
+public class RC6Test
+ extends CipherTest
+{
+ static SimpleTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new RC6Engine(),
+ new KeyParameter(
+ Hex.decode("00000000000000000000000000000000")),
+ "80000000000000000000000000000000",
+ "f71f65e7b80c0c6966fee607984b5cdf"),
+ new BlockCipherVectorTest(1, new RC6Engine(),
+ new KeyParameter(
+ Hex.decode("000000000000000000000000000000008000000000000000")),
+ "00000000000000000000000000000000",
+ "dd04c176440bbc6686c90aee775bd368"),
+ new BlockCipherVectorTest(2, new RC6Engine(),
+ new KeyParameter(
+ Hex.decode("000000000000000000000000000000000000001000000000")),
+ "00000000000000000000000000000000",
+ "937fe02d20fcb72f0f57201012b88ba4"),
+ new BlockCipherVectorTest(3, new RC6Engine(),
+ new KeyParameter(
+ Hex.decode("00000001000000000000000000000000")),
+ "00000000000000000000000000000000",
+ "8a380594d7396453771a1dfbe2914c8e"),
+ new BlockCipherVectorTest(4, new RC6Engine(),
+ new KeyParameter(
+ Hex.decode("1000000000000000000000000000000000000000000000000000000000000000")),
+ "00000000000000000000000000000000",
+ "11395d4bfe4c8258979ee2bf2d24dff4"),
+ new BlockCipherVectorTest(5, new RC6Engine(),
+ new KeyParameter(
+ Hex.decode("0000000000000000000000000000000000080000000000000000000000000000")),
+ "00000000000000000000000000000000",
+ "3d6f7e99f6512553bb983e8f75672b97")
+ };
+
+ RC6Test()
+ {
+ super(tests, new RC6Engine(), new KeyParameter(new byte[32]));
+ }
+
+ public String getName()
+ {
+ return "RC6";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new RC6Test());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/RFC3211WrapTest.java b/core/src/test/java/org/spongycastle/crypto/test/RFC3211WrapTest.java
new file mode 100644
index 00000000..8568e590
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/RFC3211WrapTest.java
@@ -0,0 +1,220 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.Wrapper;
+import org.spongycastle.crypto.engines.DESEngine;
+import org.spongycastle.crypto.engines.DESedeEngine;
+import org.spongycastle.crypto.engines.RFC3211WrapEngine;
+import org.spongycastle.crypto.modes.CBCBlockCipher;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+import java.security.SecureRandom;
+
+/**
+ * Wrap Test based on RFC3211 test vectors
+ */
+public class RFC3211WrapTest
+ extends SimpleTest
+{
+ SecureRandom r1 = new SecureRandom()
+ {
+ int[] ints = { 0xC4, 0x36, 0xF5, 0x41 };
+ int count = 0;
+
+ public int nextInt()
+ {
+ return ints[count++];
+ }
+ };
+
+ SecureRandom r2 = new SecureRandom()
+ {
+ int[] ints = { 0xFA, 0x06, 0x0A, 0x45 };
+ int count = 0;
+
+ public int nextInt()
+ {
+ return ints[count++];
+ }
+ };
+
+ public String getName()
+ {
+ return "RFC3211Wrap";
+ }
+
+ private void wrapTest(
+ int id,
+ BlockCipher engine,
+ byte[] kek,
+ byte[] iv,
+ SecureRandom rand,
+ byte[] in,
+ byte[] out)
+ throws Exception
+ {
+ Wrapper wrapper = new RFC3211WrapEngine(engine);
+
+ wrapper.init(true, new ParametersWithRandom(new ParametersWithIV(new KeyParameter(kek), iv), rand));
+
+ byte[] cText = wrapper.wrap(in, 0, in.length);
+ if (!Arrays.areEqual(cText, out))
+ {
+ fail("failed wrap test " + id + " expected " + new String(Hex.encode(out)) + " got " + new String(Hex.encode(cText)));
+ }
+
+ wrapper.init(false, new ParametersWithIV(new KeyParameter(kek), iv));
+
+ byte[] pText = wrapper.unwrap(out, 0, out.length);
+ if (!Arrays.areEqual(pText, in))
+ {
+ fail("rfailed unwrap test " + id + " expected " + new String(Hex.encode(in)) + " got " + new String(Hex.encode(pText)));
+ }
+ }
+
+ private void testCorruption()
+ throws InvalidCipherTextException
+ {
+ byte[] kek = Hex.decode("D1DAA78615F287E6");
+ byte[] iv = Hex.decode("EFE598EF21B33D6D");
+
+ Wrapper wrapper = new RFC3211WrapEngine(new DESEngine());
+
+ wrapper.init(false, new ParametersWithIV(new KeyParameter(kek), iv));
+
+ byte[] block = Hex.decode("ff739D838C627C897323A2F8C436F541");
+ encryptBlock(kek, iv, block);
+
+ try
+ {
+ wrapper.unwrap(block, 0, block.length);
+
+ fail("bad length not detected");
+ }
+ catch (InvalidCipherTextException e)
+ {
+ if (!e.getMessage().equals("wrapped key corrupted"))
+ {
+ fail("wrong exception on length");
+ }
+ }
+
+ block = Hex.decode("08639D838C627C897323A2F8C436F541");
+ testChecksum(kek, iv, block, wrapper);
+
+ block = Hex.decode("08736D838C627C897323A2F8C436F541");
+ testChecksum(kek, iv, block, wrapper);
+
+ block = Hex.decode("08739D638C627C897323A2F8C436F541");
+ testChecksum(kek, iv, block, wrapper);
+ }
+
+ private void testChecksum(byte[] kek, byte[] iv, byte[] block, Wrapper wrapper)
+ {
+ encryptBlock(kek, iv, block);
+
+ try
+ {
+ wrapper.unwrap(block, 0, block.length);
+
+ fail("bad checksum not detected");
+ }
+ catch (InvalidCipherTextException e)
+ {
+ if (!e.getMessage().equals("wrapped key fails checksum"))
+ {
+ fail("wrong exception");
+ }
+ }
+ }
+
+ private void encryptBlock(byte[] key, byte[] iv, byte[] cekBlock)
+ {
+ BlockCipher engine = new CBCBlockCipher(new DESEngine());
+
+ engine.init(true, new ParametersWithIV(new KeyParameter(key), iv));
+
+ for (int i = 0; i < cekBlock.length; i += 8)
+ {
+ engine.processBlock(cekBlock, i, cekBlock, i);
+ }
+
+ for (int i = 0; i < cekBlock.length; i += 8)
+ {
+ engine.processBlock(cekBlock, i, cekBlock, i);
+ }
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ wrapTest(1, new DESEngine(), Hex.decode("D1DAA78615F287E6"), Hex.decode("EFE598EF21B33D6D"), r1, Hex.decode("8C627C897323A2F8"), Hex.decode("B81B2565EE373CA6DEDCA26A178B0C10"));
+ wrapTest(2, new DESedeEngine(), Hex.decode("6A8970BF68C92CAEA84A8DF28510858607126380CC47AB2D"), Hex.decode("BAF1CA7931213C4E"), r2,
+ Hex.decode("8C637D887223A2F965B566EB014B0FA5D52300A3F7EA40FFFC577203C71BAF3B"),
+ Hex.decode("C03C514ABDB9E2C5AAC038572B5E24553876B377AAFB82ECA5A9D73F8AB143D9EC74E6CAD7DB260C"));
+
+ testCorruption();
+
+ Wrapper wrapper = new RFC3211WrapEngine(new DESEngine());
+ ParametersWithIV params = new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]);
+ byte[] buf = new byte[16];
+
+ try
+ {
+ wrapper.init(true, params);
+
+ wrapper.unwrap(buf, 0, buf.length);
+
+ fail("failed unwrap state test.");
+ }
+ catch (IllegalStateException e)
+ {
+ // expected
+ }
+ catch (InvalidCipherTextException e)
+ {
+ fail("unexpected exception: " + e, e);
+ }
+
+ try
+ {
+ wrapper.init(false, params);
+
+ wrapper.wrap(buf, 0, buf.length);
+
+ fail("failed unwrap state test.");
+ }
+ catch (IllegalStateException e)
+ {
+ // expected
+ }
+
+ //
+ // short test
+ //
+ try
+ {
+ wrapper.init(false, params);
+
+ wrapper.unwrap(buf, 0, buf.length / 2);
+
+ fail("failed unwrap short test.");
+ }
+ catch (InvalidCipherTextException e)
+ {
+ // expected
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new RFC3211WrapTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/RIPEMD128DigestTest.java b/core/src/test/java/org/spongycastle/crypto/test/RIPEMD128DigestTest.java
new file mode 100644
index 00000000..04c1c2b2
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/RIPEMD128DigestTest.java
@@ -0,0 +1,58 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.RIPEMD128Digest;
+
+/**
+ * RIPEMD128 Digest Test
+ */
+public class RIPEMD128DigestTest
+ extends DigestTest
+{
+ final static String[] messages = {
+ "",
+ "a",
+ "abc",
+ "message digest",
+ "abcdefghijklmnopqrstuvwxyz",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ };
+
+ final static String[] digests = {
+ "cdf26213a150dc3ecb610f18f6b38b46",
+ "86be7afa339d0fc7cfc785e72f578d33",
+ "c14a12199c66e4ba84636b0f69144c77",
+ "9e327b3d6e523062afc1132d7df9d1b8",
+ "fd2aa607f71dc8f510714922b371834e",
+ "a1aa0689d0fafa2ddc22e88b49133a06",
+ "d1e959eb179c911faea4624c60c5c702",
+ "3f45ef194732c2dbb2c4a2c769795fa3"
+ };
+
+ final static String million_a_digest = "4a7f5723f954eba1216c9d8f6320431f";
+
+ RIPEMD128DigestTest()
+ {
+ super(new RIPEMD128Digest(), messages, digests);
+ }
+
+ public void performTest()
+ {
+ super.performTest();
+
+ millionATest(million_a_digest);
+ }
+
+ protected Digest cloneDigest(Digest digest)
+ {
+ return new RIPEMD128Digest((RIPEMD128Digest)digest);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new RIPEMD128DigestTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/RIPEMD128HMacTest.java b/core/src/test/java/org/spongycastle/crypto/test/RIPEMD128HMacTest.java
new file mode 100644
index 00000000..8a0a07c2
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/RIPEMD128HMacTest.java
@@ -0,0 +1,86 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.digests.RIPEMD128Digest;
+import org.spongycastle.crypto.macs.HMac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+/**
+ * RIPEMD128 HMac Test, test vectors from RFC 2286
+ */
+public class RIPEMD128HMacTest
+ implements Test
+{
+ final static String[] keys = {
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "4a656665",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "0102030405060708090a0b0c0d0e0f10111213141516171819",
+ "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ };
+
+ final static String[] digests = {
+ "fbf61f9492aa4bbf81c172e84e0734db",
+ "875f828862b6b334b427c55f9f7ff09b",
+ "09f0b2846d2f543da363cbec8d62a38d",
+ "bdbbd7cf03e44b5aa60af815be4d2294",
+ "e79808f24b25fd031c155f0d551d9a3a",
+ "dc732928de98104a1f59d373c150acbb",
+ "5c6bec96793e16d40690c237635f30c5"
+ };
+
+ final static String[] messages = {
+ "Hi There",
+ "what do ya want for nothing?",
+ "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
+ "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+ "Test With Truncation",
+ "Test Using Larger Than Block-Size Key - Hash Key First",
+ "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+ };
+
+ public String getName()
+ {
+ return "RIPEMD128HMac";
+ }
+
+ public TestResult perform()
+ {
+ HMac hmac = new HMac(new RIPEMD128Digest());
+ byte[] resBuf = new byte[hmac.getMacSize()];
+
+ for (int i = 0; i < messages.length; i++)
+ {
+ byte[] m = messages[i].getBytes();
+ if (messages[i].startsWith("0x"))
+ {
+ m = Hex.decode(messages[i].substring(2));
+ }
+ hmac.init(new KeyParameter(Hex.decode(keys[i])));
+ hmac.update(m, 0, m.length);
+ hmac.doFinal(resBuf, 0);
+
+ if (!Arrays.areEqual(resBuf, Hex.decode(digests[i])))
+ {
+ return new SimpleTestResult(false, getName() + ": Vector " + i + " failed");
+ }
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+
+ public static void main(
+ String[] args)
+ {
+ RIPEMD128HMacTest test = new RIPEMD128HMacTest();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/RIPEMD160DigestTest.java b/core/src/test/java/org/spongycastle/crypto/test/RIPEMD160DigestTest.java
new file mode 100644
index 00000000..9af98c92
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/RIPEMD160DigestTest.java
@@ -0,0 +1,58 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.RIPEMD160Digest;
+
+/**
+ * RIPEMD160 Digest Test
+ */
+public class RIPEMD160DigestTest
+ extends DigestTest
+{
+ final static String[] messages = {
+ "",
+ "a",
+ "abc",
+ "message digest",
+ "abcdefghijklmnopqrstuvwxyz",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ };
+
+ final static String[] digests = {
+ "9c1185a5c5e9fc54612808977ee8f548b2258d31",
+ "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe",
+ "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc",
+ "5d0689ef49d2fae572b881b123a85ffa21595f36",
+ "f71c27109c692c1b56bbdceb5b9d2865b3708dbc",
+ "12a053384a9c0c88e405a06c27dcf49ada62eb2b",
+ "b0e20b6e3116640286ed3a87a5713079b21f5189",
+ "9b752e45573d4b39f4dbd3323cab82bf63326bfb"
+ };
+
+ final static String million_a_digest = "52783243c1697bdbe16d37f97f68f08325dc1528";
+
+ RIPEMD160DigestTest()
+ {
+ super(new RIPEMD160Digest(), messages, digests);
+ }
+
+ public void performTest()
+ {
+ super.performTest();
+
+ millionATest(million_a_digest);
+ }
+
+ protected Digest cloneDigest(Digest digest)
+ {
+ return new RIPEMD160Digest((RIPEMD160Digest)digest);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new RIPEMD160DigestTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/RIPEMD160HMacTest.java b/core/src/test/java/org/spongycastle/crypto/test/RIPEMD160HMacTest.java
new file mode 100644
index 00000000..1676fef3
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/RIPEMD160HMacTest.java
@@ -0,0 +1,86 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.digests.RIPEMD160Digest;
+import org.spongycastle.crypto.macs.HMac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+/**
+ * RIPEMD160 HMac Test, test vectors from RFC 2286
+ */
+public class RIPEMD160HMacTest
+ implements Test
+{
+ final static String[] keys = {
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "4a656665",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "0102030405060708090a0b0c0d0e0f10111213141516171819",
+ "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ };
+
+ final static String[] digests = {
+ "24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668",
+ "dda6c0213a485a9e24f4742064a7f033b43c4069",
+ "b0b105360de759960ab4f35298e116e295d8e7c1",
+ "d5ca862f4d21d5e610e18b4cf1beb97a4365ecf4",
+ "7619693978f91d90539ae786500ff3d8e0518e39",
+ "6466ca07ac5eac29e1bd523e5ada7605b791fd8b",
+ "69ea60798d71616cce5fd0871e23754cd75d5a0a"
+ };
+
+ final static String[] messages = {
+ "Hi There",
+ "what do ya want for nothing?",
+ "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
+ "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+ "Test With Truncation",
+ "Test Using Larger Than Block-Size Key - Hash Key First",
+ "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+ };
+
+ public String getName()
+ {
+ return "RIPEMD160HMac";
+ }
+
+ public TestResult perform()
+ {
+ HMac hmac = new HMac(new RIPEMD160Digest());
+ byte[] resBuf = new byte[hmac.getMacSize()];
+
+ for (int i = 0; i < messages.length; i++)
+ {
+ byte[] m = messages[i].getBytes();
+ if (messages[i].startsWith("0x"))
+ {
+ m = Hex.decode(messages[i].substring(2));
+ }
+ hmac.init(new KeyParameter(Hex.decode(keys[i])));
+ hmac.update(m, 0, m.length);
+ hmac.doFinal(resBuf, 0);
+
+ if (!Arrays.areEqual(resBuf, Hex.decode(digests[i])))
+ {
+ return new SimpleTestResult(false, getName() + ": Vector " + i + " failed");
+ }
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+
+ public static void main(
+ String[] args)
+ {
+ RIPEMD160HMacTest test = new RIPEMD160HMacTest();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/RIPEMD256DigestTest.java b/core/src/test/java/org/spongycastle/crypto/test/RIPEMD256DigestTest.java
new file mode 100644
index 00000000..dd8a1b9c
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/RIPEMD256DigestTest.java
@@ -0,0 +1,58 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.RIPEMD256Digest;
+
+/**
+ * RIPEMD128 Digest Test
+ */
+public class RIPEMD256DigestTest
+ extends DigestTest
+{
+ final static String[] messages = {
+ "",
+ "a",
+ "abc",
+ "message digest",
+ "abcdefghijklmnopqrstuvwxyz",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ };
+
+ final static String[] digests = {
+ "02ba4c4e5f8ecd1877fc52d64d30e37a2d9774fb1e5d026380ae0168e3c5522d",
+ "f9333e45d857f5d90a91bab70a1eba0cfb1be4b0783c9acfcd883a9134692925",
+ "afbd6e228b9d8cbbcef5ca2d03e6dba10ac0bc7dcbe4680e1e42d2e975459b65",
+ "87e971759a1ce47a514d5c914c392c9018c7c46bc14465554afcdf54a5070c0e",
+ "649d3034751ea216776bf9a18acc81bc7896118a5197968782dd1fd97d8d5133",
+ "3843045583aac6c8c8d9128573e7a9809afb2a0f34ccc36ea9e72f16f6368e3f",
+ "5740a408ac16b720b84424ae931cbb1fe363d1d0bf4017f1a89f7ea6de77a0b8",
+ "06fdcc7a409548aaf91368c06a6275b553e3f099bf0ea4edfd6778df89a890dd"
+ };
+
+ final static String million_a_digest = "ac953744e10e31514c150d4d8d7b677342e33399788296e43ae4850ce4f97978";
+
+ RIPEMD256DigestTest()
+ {
+ super(new RIPEMD256Digest(), messages, digests);
+ }
+
+ public void performTest()
+ {
+ super.performTest();
+
+ millionATest(million_a_digest);
+ }
+
+ protected Digest cloneDigest(Digest digest)
+ {
+ return new RIPEMD256Digest((RIPEMD256Digest)digest);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new RIPEMD256DigestTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/RIPEMD320DigestTest.java b/core/src/test/java/org/spongycastle/crypto/test/RIPEMD320DigestTest.java
new file mode 100644
index 00000000..c64616ba
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/RIPEMD320DigestTest.java
@@ -0,0 +1,58 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.RIPEMD320Digest;
+
+/**
+ * RIPEMD320 Digest Test
+ */
+public class RIPEMD320DigestTest
+ extends DigestTest
+{
+ final static String[] messages = {
+ "",
+ "a",
+ "abc",
+ "message digest",
+ "abcdefghijklmnopqrstuvwxyz",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ };
+
+ final static String[] digests = {
+ "22d65d5661536cdc75c1fdf5c6de7b41b9f27325ebc61e8557177d705a0ec880151c3a32a00899b8",
+ "ce78850638f92658a5a585097579926dda667a5716562cfcf6fbe77f63542f99b04705d6970dff5d",
+ "de4c01b3054f8930a79d09ae738e92301e5a17085beffdc1b8d116713e74f82fa942d64cdbc4682d",
+ "3a8e28502ed45d422f68844f9dd316e7b98533fa3f2a91d29f84d425c88d6b4eff727df66a7c0197",
+ "cabdb1810b92470a2093aa6bce05952c28348cf43ff60841975166bb40ed234004b8824463e6b009",
+ "d034a7950cf722021ba4b84df769a5de2060e259df4c9bb4a4268c0e935bbc7470a969c9d072a1ac",
+ "ed544940c86d67f250d232c30b7b3e5770e0c60c8cb9a4cafe3b11388af9920e1b99230b843c86a4",
+ "557888af5f6d8ed62ab66945c6d2a0a47ecd5341e915eb8fea1d0524955f825dc717e4a008ab2d42"
+ };
+
+ final static String million_a_digest = "bdee37f4371e20646b8b0d862dda16292ae36f40965e8c8509e63d1dbddecc503e2b63eb9245bb66";
+
+ RIPEMD320DigestTest()
+ {
+ super(new RIPEMD320Digest(), messages, digests);
+ }
+
+ public void performTest()
+ {
+ super.performTest();
+
+ millionATest(million_a_digest);
+ }
+
+ protected Digest cloneDigest(Digest digest)
+ {
+ return new RIPEMD320Digest((RIPEMD320Digest)digest);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new RIPEMD320DigestTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/RSABlindedTest.java b/core/src/test/java/org/spongycastle/crypto/test/RSABlindedTest.java
new file mode 100644
index 00000000..749e6ba1
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/RSABlindedTest.java
@@ -0,0 +1,437 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.encodings.OAEPEncoding;
+import org.spongycastle.crypto.encodings.PKCS1Encoding;
+import org.spongycastle.crypto.engines.RSABlindedEngine;
+import org.spongycastle.crypto.generators.RSAKeyPairGenerator;
+import org.spongycastle.crypto.params.RSAKeyGenerationParameters;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+import org.spongycastle.crypto.params.RSAPrivateCrtKeyParameters;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+public class RSABlindedTest
+ extends SimpleTest
+{
+ static BigInteger mod = new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16);
+ static BigInteger pubExp = new BigInteger("11", 16);
+ static BigInteger privExp = new BigInteger("92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619", 16);
+ static BigInteger p = new BigInteger("f75e80839b9b9379f1cf1128f321639757dba514642c206bbbd99f9a4846208b3e93fbbe5e0527cc59b1d4b929d9555853004c7c8b30ee6a213c3d1bb7415d03", 16);
+ static BigInteger q = new BigInteger("b892d9ebdbfc37e397256dd8a5d3123534d1f03726284743ddc6be3a709edb696fc40c7d902ed804c6eee730eee3d5b20bf6bd8d87a296813c87d3b3cc9d7947", 16);
+ static BigInteger pExp = new BigInteger("1d1a2d3ca8e52068b3094d501c9a842fec37f54db16e9a67070a8b3f53cc03d4257ad252a1a640eadd603724d7bf3737914b544ae332eedf4f34436cac25ceb5", 16);
+ static BigInteger qExp = new BigInteger("6c929e4e81672fef49d9c825163fec97c4b7ba7acb26c0824638ac22605d7201c94625770984f78a56e6e25904fe7db407099cad9b14588841b94f5ab498dded", 16);
+ static BigInteger crtCoef = new BigInteger("dae7651ee69ad1d081ec5e7188ae126f6004ff39556bde90e0b870962fa7b926d070686d8244fe5a9aa709a95686a104614834b0ada4b10f53197a5cb4c97339", 16);
+
+ static String input = "4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
+
+ //
+ // to check that we handling byte extension by big number correctly.
+ //
+ static String edgeInput = "ff6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
+
+ static byte[] oversizedSig = Hex.decode("01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+ static byte[] dudBlock = Hex.decode("000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+ static byte[] truncatedDataBlock = Hex.decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+ static byte[] incorrectPadding = Hex.decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+ static byte[] missingDataBlock = Hex.decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
+
+ public String getName()
+ {
+ return "RSABlinded";
+ }
+
+ private void testStrictPKCS1Length(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
+ {
+ AsymmetricBlockCipher eng = new RSABlindedEngine();
+
+ eng.init(true, privParameters);
+
+ byte[] data = null;
+
+ try
+ {
+ data = eng.processBlock(oversizedSig, 0, oversizedSig.length);
+ }
+ catch (Exception e)
+ {
+ fail("RSA: failed - exception " + e.toString(), e);
+ }
+
+ eng = new PKCS1Encoding(eng);
+
+ eng.init(false, pubParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+
+ fail("oversized signature block not recognised");
+ }
+ catch (InvalidCipherTextException e)
+ {
+ if (!e.getMessage().equals("block incorrect size"))
+ {
+ fail("RSA: failed - exception " + e.toString(), e);
+ }
+ }
+
+ //System.setProperty(PKCS1Encoding.STRICT_LENGTH_ENABLED_PROPERTY, "false");
+
+ System.getProperties().put(PKCS1Encoding.STRICT_LENGTH_ENABLED_PROPERTY, "false");
+ eng = new PKCS1Encoding(new RSABlindedEngine());
+
+ eng.init(false, pubParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (InvalidCipherTextException e)
+ {
+ fail("RSA: failed - exception " + e.toString(), e);
+ }
+
+ System.getProperties().remove(PKCS1Encoding.STRICT_LENGTH_ENABLED_PROPERTY);
+ }
+
+ private void testTruncatedPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
+ {
+ checkForPKCS1Exception(pubParameters, privParameters, truncatedDataBlock, "block truncated");
+ }
+
+ private void testDudPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
+ {
+ checkForPKCS1Exception(pubParameters, privParameters, dudBlock, "unknown block type");
+ }
+
+ private void testWrongPaddingPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
+ {
+ checkForPKCS1Exception(pubParameters, privParameters, incorrectPadding, "block padding incorrect");
+ }
+
+ private void testMissingDataPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
+ {
+ checkForPKCS1Exception(pubParameters, privParameters, missingDataBlock, "no data in block");
+ }
+
+ private void checkForPKCS1Exception(RSAKeyParameters pubParameters, RSAKeyParameters privParameters, byte[] inputData, String expectedMessage)
+ {
+ AsymmetricBlockCipher eng = new RSABlindedEngine();
+
+ eng.init(true, privParameters);
+
+ byte[] data = null;
+
+ try
+ {
+ data = eng.processBlock(inputData, 0, inputData.length);
+ }
+ catch (Exception e)
+ {
+ fail("RSA: failed - exception " + e.toString(), e);
+ }
+
+ eng = new PKCS1Encoding(eng);
+
+ eng.init(false, pubParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+
+ fail("missing data block not recognised");
+ }
+ catch (InvalidCipherTextException e)
+ {
+ if (!e.getMessage().equals(expectedMessage))
+ {
+ fail("RSA: failed - exception " + e.toString(), e);
+ }
+ }
+ }
+
+ private void testOAEP(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
+ {
+ //
+ // OAEP - public encrypt, private decrypt
+ //
+ AsymmetricBlockCipher eng = new OAEPEncoding(new RSABlindedEngine());
+ byte[] data = Hex.decode(input);
+
+ eng.init(true, pubParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, privParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!input.equals(new String(Hex.encode(data))))
+ {
+ fail("failed OAEP Test");
+ }
+ }
+
+ public void performTest()
+ {
+ RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod, pubExp);
+ RSAKeyParameters privParameters = new RSAPrivateCrtKeyParameters(mod, pubExp, privExp, p, q, pExp, qExp, crtCoef);
+ byte[] data = Hex.decode(edgeInput);
+
+ //
+ // RAW
+ //
+ AsymmetricBlockCipher eng = new RSABlindedEngine();
+
+ eng.init(true, pubParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("RSA: failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, privParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!edgeInput.equals(new String(Hex.encode(data))))
+ {
+ fail("failed RAW edge Test");
+ }
+
+ data = Hex.decode(input);
+
+ eng.init(true, pubParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, privParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!input.equals(new String(Hex.encode(data))))
+ {
+ fail("failed RAW Test");
+ }
+
+ //
+ // PKCS1 - public encrypt, private decrypt
+ //
+ eng = new PKCS1Encoding(eng);
+
+ eng.init(true, pubParameters);
+
+ if (eng.getOutputBlockSize() != ((PKCS1Encoding)eng).getUnderlyingCipher().getOutputBlockSize())
+ {
+ fail("PKCS1 output block size incorrect");
+ }
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, privParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!input.equals(new String(Hex.encode(data))))
+ {
+ fail("failed PKCS1 public/private Test");
+ }
+
+ //
+ // PKCS1 - private encrypt, public decrypt
+ //
+ eng = new PKCS1Encoding(((PKCS1Encoding)eng).getUnderlyingCipher());
+
+ eng.init(true, privParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, pubParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!input.equals(new String(Hex.encode(data))))
+ {
+ fail("failed PKCS1 private/public Test");
+ }
+
+ //
+ // key generation test
+ //
+ RSAKeyPairGenerator pGen = new RSAKeyPairGenerator();
+ RSAKeyGenerationParameters genParam = new RSAKeyGenerationParameters(
+ BigInteger.valueOf(0x11), new SecureRandom(), 768, 25);
+
+ pGen.init(genParam);
+
+ AsymmetricCipherKeyPair pair = pGen.generateKeyPair();
+
+ eng = new RSABlindedEngine();
+
+ if (((RSAKeyParameters)pair.getPublic()).getModulus().bitLength() < 768)
+ {
+ fail("failed key generation (768) length test");
+ }
+
+ eng.init(true, pair.getPublic());
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, pair.getPrivate());
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!input.equals(new String(Hex.encode(data))))
+ {
+ fail("failed key generation (768) Test");
+ }
+
+ genParam = new RSAKeyGenerationParameters(BigInteger.valueOf(0x11), new SecureRandom(), 1024, 25);
+
+ pGen.init(genParam);
+ pair = pGen.generateKeyPair();
+
+ eng.init(true, pair.getPublic());
+
+ if (((RSAKeyParameters)pair.getPublic()).getModulus().bitLength() < 1024)
+ {
+ fail("failed key generation (1024) length test");
+ }
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, pair.getPrivate());
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!input.equals(new String(Hex.encode(data))))
+ {
+ fail("failed key generation (1024) test");
+ }
+
+ testOAEP(pubParameters, privParameters);
+ testStrictPKCS1Length(pubParameters, privParameters);
+ testDudPKCS1Block(pubParameters, privParameters);
+ testMissingDataPKCS1Block(pubParameters, privParameters);
+ testTruncatedPKCS1Block(pubParameters, privParameters);
+ testWrongPaddingPKCS1Block(pubParameters, privParameters);
+
+ try
+ {
+ new RSABlindedEngine().processBlock(new byte[]{ 1 }, 0, 1);
+ fail("failed initialisation check");
+ }
+ catch (IllegalStateException e)
+ {
+ // expected
+ }
+ }
+
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new RSABlindedTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/RSADigestSignerTest.java b/core/src/test/java/org/spongycastle/crypto/test/RSADigestSignerTest.java
new file mode 100644
index 00000000..5587dcf8
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/RSADigestSignerTest.java
@@ -0,0 +1,55 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.asn1.x509.X509ObjectIdentifiers;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+import org.spongycastle.crypto.params.RSAPrivateCrtKeyParameters;
+import org.spongycastle.crypto.signers.RSADigestSigner;
+import org.spongycastle.util.encoders.Base64;
+import org.spongycastle.util.test.SimpleTest;
+
+import java.math.BigInteger;
+
+public class RSADigestSignerTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "RSADigestSigner";
+ }
+
+ public void performTest() throws Exception
+ {
+ BigInteger rsaPubMod = new BigInteger(Base64.decode("AIASoe2PQb1IP7bTyC9usjHP7FvnUMVpKW49iuFtrw/dMpYlsMMoIU2jupfifDpdFxIktSB4P+6Ymg5WjvHKTIrvQ7SR4zV4jaPTu56Ys0pZ9EDA6gb3HLjtU+8Bb1mfWM+yjKxcPDuFjwEtjGlPHg1Vq+CA9HNcMSKNn2+tW6qt"));
+ BigInteger rsaPubExp = new BigInteger(Base64.decode("EQ=="));
+ BigInteger rsaPrivMod = new BigInteger(Base64.decode("AIASoe2PQb1IP7bTyC9usjHP7FvnUMVpKW49iuFtrw/dMpYlsMMoIU2jupfifDpdFxIktSB4P+6Ymg5WjvHKTIrvQ7SR4zV4jaPTu56Ys0pZ9EDA6gb3HLjtU+8Bb1mfWM+yjKxcPDuFjwEtjGlPHg1Vq+CA9HNcMSKNn2+tW6qt"));
+ BigInteger rsaPrivDP = new BigInteger(Base64.decode("JXzfzG5v+HtLJIZqYMUefJfFLu8DPuJGaLD6lI3cZ0babWZ/oPGoJa5iHpX4Ul/7l3s1PFsuy1GhzCdOdlfRcQ=="));
+ BigInteger rsaPrivDQ = new BigInteger(Base64.decode("YNdJhw3cn0gBoVmMIFRZzflPDNthBiWy/dUMSRfJCxoZjSnr1gysZHK01HteV1YYNGcwPdr3j4FbOfri5c6DUQ=="));
+ BigInteger rsaPrivExp = new BigInteger(Base64.decode("DxFAOhDajr00rBjqX+7nyZ/9sHWRCCp9WEN5wCsFiWVRPtdB+NeLcou7mWXwf1Y+8xNgmmh//fPV45G2dsyBeZbXeJwB7bzx9NMEAfedchyOwjR8PYdjK3NpTLKtZlEJ6Jkh4QihrXpZMO4fKZWUm9bid3+lmiq43FwW+Hof8/E="));
+ BigInteger rsaPrivP = new BigInteger(Base64.decode("AJ9StyTVW+AL/1s7RBtFwZGFBgd3zctBqzzwKPda6LbtIFDznmwDCqAlIQH9X14X7UPLokCDhuAa76OnDXb1OiE="));
+ BigInteger rsaPrivQ = new BigInteger(Base64.decode("AM3JfD79dNJ5A3beScSzPtWxx/tSLi0QHFtkuhtSizeXdkv5FSba7lVzwEOGKHmW829bRoNxThDy4ds1IihW1w0="));
+ BigInteger rsaPrivQinv = new BigInteger(Base64.decode("Lt0g7wrsNsQxuDdB8q/rH8fSFeBXMGLtCIqfOec1j7FEIuYA/ACiRDgXkHa0WgN7nLXSjHoy630wC5Toq8vvUg=="));
+ RSAKeyParameters rsaPublic = new RSAKeyParameters(false, rsaPubMod, rsaPubExp);
+ RSAPrivateCrtKeyParameters rsaPrivate = new RSAPrivateCrtKeyParameters(rsaPrivMod, rsaPubExp, rsaPrivExp, rsaPrivP, rsaPrivQ, rsaPrivDP, rsaPrivDQ, rsaPrivQinv);
+
+ byte[] msg = new byte[] { 1, 6, 3, 32, 7, 43, 2, 5, 7, 78, 4, 23 };
+
+ RSADigestSigner signer = new RSADigestSigner(new SHA1Digest());
+ signer.init(true, rsaPrivate);
+ signer.update(msg, 0, msg.length);
+ byte[] sig = signer.generateSignature();
+
+ signer = new RSADigestSigner(new SHA1Digest(), X509ObjectIdentifiers.id_SHA1);
+ signer.init(false, rsaPublic);
+ signer.update(msg, 0, msg.length);
+ if (!signer.verifySignature(sig))
+ {
+ fail("RSA Digest Signer failed.");
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new RSADigestSignerTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/RSAKeyEncapsulationTest.java b/core/src/test/java/org/spongycastle/crypto/test/RSAKeyEncapsulationTest.java
new file mode 100755
index 00000000..b2f0f8fd
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/RSAKeyEncapsulationTest.java
@@ -0,0 +1,61 @@
+package org.spongycastle.crypto.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.generators.KDF2BytesGenerator;
+import org.spongycastle.crypto.generators.RSAKeyPairGenerator;
+import org.spongycastle.crypto.kems.RSAKeyEncapsulation;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.RSAKeyGenerationParameters;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * Tests for the RSA Key Encapsulation Mechanism
+ */
+public class RSAKeyEncapsulationTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "RSAKeyEncapsulation";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ // Generate RSA key pair
+ RSAKeyPairGenerator rsaGen = new RSAKeyPairGenerator();
+ rsaGen.init(new RSAKeyGenerationParameters(BigInteger.valueOf(65537), new SecureRandom(), 1024, 5));
+ AsymmetricCipherKeyPair keys = rsaGen.generateKeyPair();
+
+ // Set RSA-KEM parameters
+ RSAKeyEncapsulation kem;
+ KDF2BytesGenerator kdf = new KDF2BytesGenerator(new SHA1Digest());
+ SecureRandom rnd = new SecureRandom();
+ byte[] out = new byte[128];
+ KeyParameter key1, key2;
+
+ // Test RSA-KEM
+ kem = new RSAKeyEncapsulation(kdf, rnd);
+
+ kem.init(keys.getPublic());
+ key1 = (KeyParameter)kem.encrypt(out, 128);
+
+ kem.init(keys.getPrivate());
+ key2 = (KeyParameter)kem.decrypt(out, 128);
+
+ if (!areEqual(key1.getKey(), key2.getKey()))
+ {
+ fail("failed test");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new RSAKeyEncapsulationTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/RSATest.java b/core/src/test/java/org/spongycastle/crypto/test/RSATest.java
new file mode 100644
index 00000000..bf115003
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/RSATest.java
@@ -0,0 +1,498 @@
+package org.spongycastle.crypto.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricBlockCipher;
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.encodings.OAEPEncoding;
+import org.spongycastle.crypto.encodings.PKCS1Encoding;
+import org.spongycastle.crypto.engines.RSAEngine;
+import org.spongycastle.crypto.generators.RSAKeyPairGenerator;
+import org.spongycastle.crypto.params.RSAKeyGenerationParameters;
+import org.spongycastle.crypto.params.RSAKeyParameters;
+import org.spongycastle.crypto.params.RSAPrivateCrtKeyParameters;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class RSATest
+ extends SimpleTest
+{
+ static BigInteger mod = new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16);
+ static BigInteger pubExp = new BigInteger("11", 16);
+ static BigInteger privExp = new BigInteger("92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619", 16);
+ static BigInteger p = new BigInteger("f75e80839b9b9379f1cf1128f321639757dba514642c206bbbd99f9a4846208b3e93fbbe5e0527cc59b1d4b929d9555853004c7c8b30ee6a213c3d1bb7415d03", 16);
+ static BigInteger q = new BigInteger("b892d9ebdbfc37e397256dd8a5d3123534d1f03726284743ddc6be3a709edb696fc40c7d902ed804c6eee730eee3d5b20bf6bd8d87a296813c87d3b3cc9d7947", 16);
+ static BigInteger pExp = new BigInteger("1d1a2d3ca8e52068b3094d501c9a842fec37f54db16e9a67070a8b3f53cc03d4257ad252a1a640eadd603724d7bf3737914b544ae332eedf4f34436cac25ceb5", 16);
+ static BigInteger qExp = new BigInteger("6c929e4e81672fef49d9c825163fec97c4b7ba7acb26c0824638ac22605d7201c94625770984f78a56e6e25904fe7db407099cad9b14588841b94f5ab498dded", 16);
+ static BigInteger crtCoef = new BigInteger("dae7651ee69ad1d081ec5e7188ae126f6004ff39556bde90e0b870962fa7b926d070686d8244fe5a9aa709a95686a104614834b0ada4b10f53197a5cb4c97339", 16);
+
+ static String input = "4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
+
+ //
+ // to check that we handling byte extension by big number correctly.
+ //
+ static String edgeInput = "ff6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
+
+ static byte[] oversizedSig = Hex.decode("01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+ static byte[] dudBlock = Hex.decode("000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+ static byte[] truncatedDataBlock = Hex.decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+ static byte[] incorrectPadding = Hex.decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+ static byte[] missingDataBlock = Hex.decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
+
+ public String getName()
+ {
+ return "RSA";
+ }
+
+ private void testStrictPKCS1Length(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
+ {
+ AsymmetricBlockCipher eng = new RSAEngine();
+
+ eng.init(true, privParameters);
+
+ byte[] data = null;
+
+ try
+ {
+ data = eng.processBlock(oversizedSig, 0, oversizedSig.length);
+ }
+ catch (Exception e)
+ {
+ fail("RSA: failed - exception " + e.toString(), e);
+ }
+
+ eng = new PKCS1Encoding(eng);
+
+ eng.init(false, pubParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+
+ fail("oversized signature block not recognised");
+ }
+ catch (InvalidCipherTextException e)
+ {
+ if (!e.getMessage().equals("block incorrect size"))
+ {
+ fail("RSA: failed - exception " + e.toString(), e);
+ }
+ }
+
+ //System.setProperty(PKCS1Encoding.STRICT_LENGTH_ENABLED_PROPERTY, "false");
+
+ System.getProperties().put(PKCS1Encoding.STRICT_LENGTH_ENABLED_PROPERTY, "false");
+ eng = new PKCS1Encoding(new RSAEngine());
+
+ eng.init(false, pubParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (InvalidCipherTextException e)
+ {
+ fail("RSA: failed - exception " + e.toString(), e);
+ }
+
+ System.getProperties().remove(PKCS1Encoding.STRICT_LENGTH_ENABLED_PROPERTY);
+ }
+
+ private void testTruncatedPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
+ {
+ checkForPKCS1Exception(pubParameters, privParameters, truncatedDataBlock, "block truncated");
+ }
+
+ private void testDudPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
+ {
+ checkForPKCS1Exception(pubParameters, privParameters, dudBlock, "unknown block type");
+ }
+
+ private void testWrongPaddingPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
+ {
+ checkForPKCS1Exception(pubParameters, privParameters, incorrectPadding, "block padding incorrect");
+ }
+
+ private void testMissingDataPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
+ {
+ checkForPKCS1Exception(pubParameters, privParameters, missingDataBlock, "no data in block");
+ }
+
+ private void checkForPKCS1Exception(RSAKeyParameters pubParameters, RSAKeyParameters privParameters, byte[] inputData, String expectedMessage)
+ {
+ AsymmetricBlockCipher eng = new RSAEngine();
+
+ eng.init(true, privParameters);
+
+ byte[] data = null;
+
+ try
+ {
+ data = eng.processBlock(inputData, 0, inputData.length);
+ }
+ catch (Exception e)
+ {
+ fail("RSA: failed - exception " + e.toString(), e);
+ }
+
+ eng = new PKCS1Encoding(eng);
+
+ eng.init(false, pubParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+
+ fail("missing data block not recognised");
+ }
+ catch (InvalidCipherTextException e)
+ {
+ if (!e.getMessage().equals(expectedMessage))
+ {
+ fail("RSA: failed - exception " + e.toString(), e);
+ }
+ }
+ }
+
+ private void testOAEP(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
+ {
+ //
+ // OAEP - public encrypt, private decrypt
+ //
+ AsymmetricBlockCipher eng = new OAEPEncoding(new RSAEngine());
+ byte[] data = Hex.decode(input);
+
+ eng.init(true, pubParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, privParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!input.equals(new String(Hex.encode(data))))
+ {
+ fail("failed OAEP Test");
+ }
+ }
+
+ private void zeroBlockTest(CipherParameters encParameters, CipherParameters decParameters)
+ {
+ AsymmetricBlockCipher eng = new PKCS1Encoding(new RSAEngine());
+
+ eng.init(true, encParameters);
+
+ if (eng.getOutputBlockSize() != ((PKCS1Encoding)eng).getUnderlyingCipher().getOutputBlockSize())
+ {
+ fail("PKCS1 output block size incorrect");
+ }
+
+ byte[] zero = new byte[0];
+ byte[] data = null;
+
+ try
+ {
+ data = eng.processBlock(zero, 0, zero.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, decParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!Arrays.areEqual(zero, data))
+ {
+ fail("failed PKCS1 zero Test");
+ }
+ }
+
+ public void performTest()
+ {
+ RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod, pubExp);
+ RSAKeyParameters privParameters = new RSAPrivateCrtKeyParameters(mod, pubExp, privExp, p, q, pExp, qExp, crtCoef);
+ byte[] data = Hex.decode(edgeInput);
+
+ //
+ // RAW
+ //
+ AsymmetricBlockCipher eng = new RSAEngine();
+
+ eng.init(true, pubParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("RSA: failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, privParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!edgeInput.equals(new String(Hex.encode(data))))
+ {
+ fail("failed RAW edge Test");
+ }
+
+ data = Hex.decode(input);
+
+ eng.init(true, pubParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, privParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!input.equals(new String(Hex.encode(data))))
+ {
+ fail("failed RAW Test");
+ }
+
+ //
+ // PKCS1 - public encrypt, private decrypt
+ //
+ eng = new PKCS1Encoding(eng);
+
+ eng.init(true, pubParameters);
+
+ if (eng.getOutputBlockSize() != ((PKCS1Encoding)eng).getUnderlyingCipher().getOutputBlockSize())
+ {
+ fail("PKCS1 output block size incorrect");
+ }
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, privParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!input.equals(new String(Hex.encode(data))))
+ {
+ fail("failed PKCS1 public/private Test");
+ }
+
+ //
+ // PKCS1 - private encrypt, public decrypt
+ //
+ eng = new PKCS1Encoding(((PKCS1Encoding)eng).getUnderlyingCipher());
+
+ eng.init(true, privParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, pubParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!input.equals(new String(Hex.encode(data))))
+ {
+ fail("failed PKCS1 private/public Test");
+ }
+
+ zeroBlockTest(pubParameters, privParameters);
+ zeroBlockTest(privParameters, pubParameters);
+
+ //
+ // key generation test
+ //
+ RSAKeyPairGenerator pGen = new RSAKeyPairGenerator();
+ RSAKeyGenerationParameters genParam = new RSAKeyGenerationParameters(
+ BigInteger.valueOf(0x11), new SecureRandom(), 768, 25);
+
+ pGen.init(genParam);
+
+ AsymmetricCipherKeyPair pair = pGen.generateKeyPair();
+
+ eng = new RSAEngine();
+
+ if (((RSAKeyParameters)pair.getPublic()).getModulus().bitLength() < 768)
+ {
+ fail("failed key generation (768) length test");
+ }
+
+ eng.init(true, pair.getPublic());
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, pair.getPrivate());
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!input.equals(new String(Hex.encode(data))))
+ {
+ fail("failed key generation (768) Test");
+ }
+
+ genParam = new RSAKeyGenerationParameters(BigInteger.valueOf(0x11), new SecureRandom(), 1024, 25);
+
+ pGen.init(genParam);
+ pair = pGen.generateKeyPair();
+
+ eng.init(true, pair.getPublic());
+
+ if (((RSAKeyParameters)pair.getPublic()).getModulus().bitLength() < 1024)
+ {
+ fail("failed key generation (1024) length test");
+ }
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, pair.getPrivate());
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!input.equals(new String(Hex.encode(data))))
+ {
+ fail("failed key generation (1024) test");
+ }
+
+ genParam = new RSAKeyGenerationParameters(
+ BigInteger.valueOf(0x11), new SecureRandom(), 16, 25);
+ pGen.init(genParam);
+
+ for (int i = 0; i < 100; ++i)
+ {
+ pair = pGen.generateKeyPair();
+ RSAPrivateCrtKeyParameters privKey = (RSAPrivateCrtKeyParameters) pair.getPrivate();
+ BigInteger pqDiff = privKey.getP().subtract(privKey.getQ()).abs();
+
+ if (pqDiff.bitLength() < 5)
+ {
+ fail("P and Q too close in RSA key pair");
+ }
+ }
+
+ testOAEP(pubParameters, privParameters);
+ testStrictPKCS1Length(pubParameters, privParameters);
+ testDudPKCS1Block(pubParameters, privParameters);
+ testMissingDataPKCS1Block(pubParameters, privParameters);
+ testTruncatedPKCS1Block(pubParameters, privParameters);
+ testWrongPaddingPKCS1Block(pubParameters, privParameters);
+
+ try
+ {
+ new RSAEngine().processBlock(new byte[]{ 1 }, 0, 1);
+ fail("failed initialisation check");
+ }
+ catch (IllegalStateException e)
+ {
+ // expected
+ }
+ }
+
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new RSATest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/RegressionTest.java b/core/src/test/java/org/spongycastle/crypto/test/RegressionTest.java
new file mode 100644
index 00000000..0c89e979
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/RegressionTest.java
@@ -0,0 +1,157 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+public class RegressionTest
+{
+ public static Test[] tests =
+ {
+ new AESTest(),
+ new AESLightTest(),
+ new AESFastTest(),
+ new AESWrapTest(),
+ new AESWrapPadTest(),
+ new DESTest(),
+ new DESedeTest(),
+ new ModeTest(),
+ new PaddingTest(),
+ new DHTest(),
+ new ElGamalTest(),
+ new DSATest(),
+ new ECTest(),
+ new DeterministicDSATest(),
+ new GOST3410Test(),
+ new ECGOST3410Test(),
+ new ECIESTest(),
+ new ECNRTest(),
+ new MacTest(),
+ new GOST28147MacTest(),
+ new RC2Test(),
+ new RC2WrapTest(),
+ new RC4Test(),
+ new RC5Test(),
+ new RC6Test(),
+ new RijndaelTest(),
+ new SerpentTest(),
+ new CamelliaTest(),
+ new CamelliaLightTest(),
+ new DigestRandomNumberTest(),
+ new SkipjackTest(),
+ new BlowfishTest(),
+ new TwofishTest(),
+ new Threefish256Test(),
+ new Threefish512Test(),
+ new Threefish1024Test(),
+ new SkeinDigestTest(),
+ new SkeinMacTest(),
+ new CAST5Test(),
+ new CAST6Test(),
+ new GOST28147Test(),
+ new IDEATest(),
+ new RSATest(),
+ new RSABlindedTest(),
+ new RSADigestSignerTest(),
+ new PSSBlindTest(),
+ new ISO9796Test(),
+ new ISO9797Alg3MacTest(),
+ new MD2DigestTest(),
+ new MD4DigestTest(),
+ new MD5DigestTest(),
+ new SHA1DigestTest(),
+ new SHA224DigestTest(),
+ new SHA256DigestTest(),
+ new SHA384DigestTest(),
+ new SHA512DigestTest(),
+ new SHA512t224DigestTest(),
+ new SHA512t256DigestTest(),
+ new SHA3DigestTest(),
+ new RIPEMD128DigestTest(),
+ new RIPEMD160DigestTest(),
+ new RIPEMD256DigestTest(),
+ new RIPEMD320DigestTest(),
+ new TigerDigestTest(),
+ new GOST3411DigestTest(),
+ new WhirlpoolDigestTest(),
+ new MD5HMacTest(),
+ new SHA1HMacTest(),
+ new SHA224HMacTest(),
+ new SHA256HMacTest(),
+ new SHA384HMacTest(),
+ new SHA512HMacTest(),
+ new RIPEMD128HMacTest(),
+ new RIPEMD160HMacTest(),
+ new OAEPTest(),
+ new PSSTest(),
+ new CTSTest(),
+ new CCMTest(),
+ new PKCS5Test(),
+ new PKCS12Test(),
+ new KDF1GeneratorTest(),
+ new KDF2GeneratorTest(),
+ new MGF1GeneratorTest(),
+ new HKDFGeneratorTest(),
+ new DHKEKGeneratorTest(),
+ new ECDHKEKGeneratorTest(),
+ new ShortenedDigestTest(),
+ new EqualsHashCodeTest(),
+ new TEATest(),
+ new XTEATest(),
+ new RFC3211WrapTest(),
+ new SEEDTest(),
+ new Salsa20Test(),
+ new XSalsa20Test(),
+ new ChaChaTest(),
+ new CMacTest(),
+ new EAXTest(),
+ new GCMTest(),
+ new GMacTest(),
+ new HCFamilyTest(),
+ new HCFamilyVecTest(),
+ new ISAACTest(),
+ new NoekeonTest(),
+ new VMPCKSA3Test(),
+ new VMPCMacTest(),
+ new VMPCTest(),
+ new Grainv1Test(),
+ new Grain128Test(),
+ //new NaccacheSternTest(),
+ new SRP6Test(),
+ new SCryptTest(),
+ new ResetTest(),
+ new NullTest(),
+ new DSTU4145Test(),
+ new SipHashTest(),
+ new Poly1305Test(),
+ new OCBTest(),
+ new NonMemoableDigestTest(),
+ new RSAKeyEncapsulationTest(),
+ new ECIESKeyEncapsulationTest(),
+ new HashCommitmentTest(),
+ new CipherStreamTest(),
+ new BlockCipherResetTest(),
+ new StreamCipherResetTest(),
+ new SM3DigestTest(),
+ new Shacal2Test(),
+ new KDFCounterGeneratorTest(),
+ new KDFDoublePipelineIteratorGeneratorTest(),
+ new KDFFeedbackGeneratorTest(),
+ new CramerShoupTest()
+ };
+
+ public static void main(
+ String[] args)
+ {
+ for (int i = 0; i != tests.length; i++)
+ {
+ TestResult result = tests[i].perform();
+
+ if (result.getException() != null)
+ {
+ result.getException().printStackTrace();
+ }
+
+ System.out.println(result);
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/ResetTest.java b/core/src/test/java/org/spongycastle/crypto/test/ResetTest.java
new file mode 100644
index 00000000..dd323d7d
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/ResetTest.java
@@ -0,0 +1,99 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.BufferedBlockCipher;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.engines.DESEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class ResetTest
+ extends SimpleTest
+{
+ private static final byte[] input = Hex.decode("4e6f77206973207468652074696d6520666f7220616c6c20");
+ private static final byte[] output = Hex.decode("3fa40e8a984d48156a271787ab8883f9893d51ec4b563b53");
+ public String getName()
+ {
+ return "Reset";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ BufferedBlockCipher cipher = new BufferedBlockCipher(new DESEngine());
+
+ KeyParameter param = new KeyParameter(Hex.decode("0123456789abcdef"));
+
+ basicTrial(cipher, param);
+
+ cipher.init(false, param);
+
+ byte[] out = new byte[input.length];
+
+ int len2 = cipher.processBytes(output, 0, output.length - 1, out, 0);
+
+ try
+ {
+ cipher.doFinal(out, len2);
+ fail("no DataLengthException - short input");
+ }
+ catch (DataLengthException e)
+ {
+ // ignore
+ }
+
+ len2 = cipher.processBytes(output, 0, output.length, out, 0);
+
+ cipher.doFinal(out, len2);
+
+ if (!areEqual(input, out))
+ {
+ fail("failed reversal one got " + new String(Hex.encode(out)));
+ }
+
+ len2 = cipher.processBytes(output, 0, output.length - 1, out, 0);
+
+ try
+ {
+ cipher.doFinal(out, len2);
+ fail("no DataLengthException - short output");
+ }
+ catch (DataLengthException e)
+ {
+ // ignore
+ }
+
+ len2 = cipher.processBytes(output, 0, output.length, out, 0);
+
+ cipher.doFinal(out, len2);
+
+ if (!areEqual(input, out))
+ {
+ fail("failed reversal two got " + new String(Hex.encode(out)));
+ }
+ }
+
+ private void basicTrial(BufferedBlockCipher cipher, KeyParameter param)
+ throws InvalidCipherTextException
+ {
+ cipher.init(true, param);
+
+ byte[] out = new byte[input.length];
+
+ int len1 = cipher.processBytes(input, 0, input.length, out, 0);
+
+ cipher.doFinal(out, len1);
+
+ if (!areEqual(out, output))
+ {
+ fail("failed - " + "expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out)));
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new ResetTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/RijndaelTest.java b/core/src/test/java/org/spongycastle/crypto/test/RijndaelTest.java
new file mode 100644
index 00000000..6c5d742b
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/RijndaelTest.java
@@ -0,0 +1,116 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.engines.RijndaelEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * Test vectors from the NIST standard tests and Brian Gladman's vector set
+ * <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">
+ * http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
+ */
+public class RijndaelTest
+ extends CipherTest
+{
+ static SimpleTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new RijndaelEngine(128),
+ new KeyParameter(Hex.decode("80000000000000000000000000000000")),
+ "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
+ new BlockCipherVectorTest(1, new RijndaelEngine(128),
+ new KeyParameter(Hex.decode("00000000000000000000000000000080")),
+ "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
+ new BlockCipherMonteCarloTest(2, 10000, new RijndaelEngine(128),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000")),
+ "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
+ new BlockCipherMonteCarloTest(3, 10000, new RijndaelEngine(128),
+ new KeyParameter(Hex.decode("5F060D3716B345C253F6749ABAC10917")),
+ "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
+ new BlockCipherVectorTest(4, new RijndaelEngine(128),
+ new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
+ "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
+ new BlockCipherMonteCarloTest(5, 10000, new RijndaelEngine(128),
+ new KeyParameter(Hex.decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
+ "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
+ new BlockCipherVectorTest(6, new RijndaelEngine(128),
+ new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
+ "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
+ new BlockCipherMonteCarloTest(7, 10000, new RijndaelEngine(128),
+ new KeyParameter(Hex.decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
+ "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168"),
+ new BlockCipherVectorTest(8, new RijndaelEngine(160),
+ new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c")),
+ "3243f6a8885a308d313198a2e03707344a409382", "16e73aec921314c29df905432bc8968ab64b1f51"),
+ new BlockCipherVectorTest(8, new RijndaelEngine(160),
+ new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160")),
+ "3243f6a8885a308d313198a2e03707344a409382", "0553eb691670dd8a5a5b5addf1aa7450f7a0e587"),
+ new BlockCipherVectorTest(8, new RijndaelEngine(160),
+ new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da5")),
+ "3243f6a8885a308d313198a2e03707344a409382", "73cd6f3423036790463aa9e19cfcde894ea16623"),
+ new BlockCipherVectorTest(8, new RijndaelEngine(160),
+ new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d90")),
+ "3243f6a8885a308d313198a2e03707344a409382", "601b5dcd1cf4ece954c740445340bf0afdc048df"),
+ new BlockCipherVectorTest(8, new RijndaelEngine(160),
+ new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d9045190cfe")),
+ "3243f6a8885a308d313198a2e03707344a409382", "579e930b36c1529aa3e86628bacfe146942882cf"),
+ new BlockCipherVectorTest(8, new RijndaelEngine(192),
+ new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c")),
+ "3243f6a8885a308d313198a2e03707344a4093822299f31d", "b24d275489e82bb8f7375e0d5fcdb1f481757c538b65148a"),
+ new BlockCipherVectorTest(9, new RijndaelEngine(192),
+ new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da5")),
+ "3243f6a8885a308d313198a2e03707344a4093822299f31d", "725ae43b5f3161de806a7c93e0bca93c967ec1ae1b71e1cf"),
+ new BlockCipherVectorTest(10, new RijndaelEngine(192),
+ new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d90")),
+ "3243f6a8885a308d313198a2e03707344a4093822299f31d", "bbfc14180afbf6a36382a061843f0b63e769acdc98769130"),
+ new BlockCipherVectorTest(11, new RijndaelEngine(192),
+ new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d9045190cfe")),
+ "3243f6a8885a308d313198a2e03707344a4093822299f31d", "0ebacf199e3315c2e34b24fcc7c46ef4388aa475d66c194c"),
+ new BlockCipherVectorTest(12, new RijndaelEngine(224),
+ new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c")),
+ "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa9", "b0a8f78f6b3c66213f792ffd2a61631f79331407a5e5c8d3793aceb1"),
+ new BlockCipherVectorTest(13, new RijndaelEngine(224),
+ new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160")),
+ "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa9", "08b99944edfce33a2acb131183ab0168446b2d15e958480010f545e3"),
+ new BlockCipherVectorTest(14, new RijndaelEngine(224),
+ new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da5")),
+ "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa9", "be4c597d8f7efe22a2f7e5b1938e2564d452a5bfe72399c7af1101e2"),
+ new BlockCipherVectorTest(15, new RijndaelEngine(224),
+ new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d90")),
+ "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa9", "ef529598ecbce297811b49bbed2c33bbe1241d6e1a833dbe119569e8"),
+ new BlockCipherVectorTest(16, new RijndaelEngine(224),
+ new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d9045190cfe")),
+ "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa9", "02fafc200176ed05deb8edb82a3555b0b10d47a388dfd59cab2f6c11"),
+ new BlockCipherVectorTest(17, new RijndaelEngine(256),
+ new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c")),
+ "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c8", "7d15479076b69a46ffb3b3beae97ad8313f622f67fedb487de9f06b9ed9c8f19"),
+ new BlockCipherVectorTest(18, new RijndaelEngine(256),
+ new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160")),
+ "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c8", "514f93fb296b5ad16aa7df8b577abcbd484decacccc7fb1f18dc567309ceeffd"),
+ new BlockCipherVectorTest(19, new RijndaelEngine(256),
+ new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da5")),
+ "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c8", "5d7101727bb25781bf6715b0e6955282b9610e23a43c2eb062699f0ebf5887b2"),
+ new BlockCipherVectorTest(20, new RijndaelEngine(256),
+ new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d90")),
+ "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c8", "d56c5a63627432579e1dd308b2c8f157b40a4bfb56fea1377b25d3ed3d6dbf80"),
+ new BlockCipherVectorTest(21, new RijndaelEngine(256),
+ new KeyParameter(Hex.decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d9045190cfe")),
+ "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c8", "a49406115dfb30a40418aafa4869b7c6a886ff31602a7dd19c889dc64f7e4e7a")
+ };
+
+ RijndaelTest()
+ {
+ super(tests, new RijndaelEngine(128), new KeyParameter(new byte[16]));
+ }
+
+ public String getName()
+ {
+ return "Rijndael";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new RijndaelTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/SCryptTest.java b/core/src/test/java/org/spongycastle/crypto/test/SCryptTest.java
new file mode 100644
index 00000000..f64a6a76
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/SCryptTest.java
@@ -0,0 +1,144 @@
+package org.spongycastle.crypto.test;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+import org.spongycastle.crypto.generators.SCrypt;
+import org.spongycastle.util.Strings;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/*
+ * scrypt test vectors from "Stronger Key Derivation Via Sequential Memory-hard Functions" Appendix B.
+ * (http://www.tarsnap.com/scrypt/scrypt.pdf)
+ */
+public class SCryptTest extends SimpleTest
+{
+ public String getName()
+ {
+ return "SCrypt";
+ }
+
+ public void performTest() throws Exception
+ {
+ testParameters();
+ testVectors();
+ }
+
+ public void testParameters()
+ {
+ checkOK("Minimal values", new byte[0], new byte[0], 2, 1, 1, 1);
+ checkIllegal("Cost parameter must be > 1", new byte[0], new byte[0], 1, 1, 1, 1);
+ checkOK("Cost parameter 65536 OK for r == 1", new byte[0], new byte[0], 65536, 1, 1, 1);
+ checkIllegal("Cost parameter must <= 65536 for r == 1", new byte[0], new byte[0], 65537, 1, 1, 1);
+ checkIllegal("Block size must be >= 1", new byte[0], new byte[0], 2, 0, 2, 1);
+ checkIllegal("Parallelisation parameter must be >= 1", new byte[0], new byte[0], 2, 1, 0, 1);
+ // checkOK("Parallelisation parameter 65535 OK for r = 4", new byte[0], new byte[0], 2, 32,
+ // 65535, 1);
+ checkIllegal("Parallelisation parameter must be < 65535 for r = 4", new byte[0], new byte[0], 2, 32, 65536, 1);
+
+ checkIllegal("Len parameter must be > 1", new byte[0], new byte[0], 2, 1, 1, 0);
+ }
+
+ private void checkOK(String msg, byte[] pass, byte[] salt, int N, int r, int p, int len)
+ {
+ try
+ {
+ SCrypt.generate(pass, salt, N, r, p, len);
+ }
+ catch (IllegalArgumentException e)
+ {
+ e.printStackTrace();
+ fail(msg);
+ }
+ }
+
+ private void checkIllegal(String msg, byte[] pass, byte[] salt, int N, int r, int p, int len)
+ {
+ try
+ {
+ SCrypt.generate(pass, salt, N, r, p, len);
+ fail(msg);
+ }
+ catch (IllegalArgumentException e)
+ {
+ // e.printStackTrace();
+ }
+ }
+
+ public void testVectors()
+ throws Exception
+ {
+ BufferedReader br = new BufferedReader(new InputStreamReader(
+ getClass().getResourceAsStream("SCryptTestVectors.txt")));
+
+ int count = 0;
+ String line = br.readLine();
+
+ while (line != null)
+ {
+ ++count;
+ String header = line;
+ StringBuffer data = new StringBuffer();
+
+ while (!isEndData(line = br.readLine()))
+ {
+ for (int i = 0; i != line.length(); i++)
+ {
+ if (line.charAt(i) != ' ')
+ {
+ data.append(line.charAt(i));
+ }
+ }
+ }
+
+ int start = header.indexOf('(') + 1;
+ int limit = header.lastIndexOf(')');
+ String argStr = header.substring(start, limit);
+ String[] args = Strings.split(argStr, ',');
+
+ byte[] P = extractQuotedString(args[0]);
+ byte[] S = extractQuotedString(args[1]);
+ int N = extractInteger(args[2]);
+ int r = extractInteger(args[3]);
+ int p = extractInteger(args[4]);
+ int dkLen = extractInteger(args[5]);
+ byte[] expected = Hex.decode(data.toString());
+
+ // This skips very expensive test case(s), remove check to re-enable
+ if (N <= 16384)
+ {
+ byte[] result = SCrypt.generate(P, S, N, r, p, dkLen);
+
+ if (!areEqual(expected, result))
+ {
+ fail("Result does not match expected value in test case " + count);
+ }
+ }
+ }
+
+ br.close();
+ }
+
+ private static boolean isEndData(String line)
+ {
+ return line == null || line.startsWith("scrypt");
+ }
+
+ private static byte[] extractQuotedString(String arg)
+ {
+ arg = arg.trim();
+ arg = arg.substring(1, arg.length() - 1);
+ return Strings.toByteArray(arg);
+ }
+
+ private static int extractInteger(String arg)
+ {
+ return Integer.parseInt(arg.trim());
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new SCryptTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/SEEDTest.java b/core/src/test/java/org/spongycastle/crypto/test/SEEDTest.java
new file mode 100644
index 00000000..a38c59c1
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/SEEDTest.java
@@ -0,0 +1,53 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.engines.SEEDEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * SEED tester - vectors http://www.ietf.org/rfc/rfc4009.txt
+ */
+public class SEEDTest
+ extends CipherTest
+{
+ static SimpleTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new SEEDEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000")),
+ "000102030405060708090a0b0c0d0e0f",
+ "5EBAC6E0054E166819AFF1CC6D346CDB"),
+ new BlockCipherVectorTest(0, new SEEDEngine(),
+ new KeyParameter(Hex.decode("000102030405060708090a0b0c0d0e0f")),
+ "00000000000000000000000000000000",
+ "c11f22f20140505084483597e4370f43"),
+ new BlockCipherVectorTest(0, new SEEDEngine(),
+ new KeyParameter(Hex.decode("4706480851E61BE85D74BFB3FD956185")),
+ "83A2F8A288641FB9A4E9A5CC2F131C7D",
+ "EE54D13EBCAE706D226BC3142CD40D4A"),
+ new BlockCipherVectorTest(0, new SEEDEngine(),
+ new KeyParameter(Hex.decode("28DBC3BC49FFD87DCFA509B11D422BE7")),
+ "B41E6BE2EBA84A148E2EED84593C5EC7",
+ "9B9B7BFCD1813CB95D0B3618F40F5122"),
+ new BlockCipherVectorTest(0, new SEEDEngine(),
+ new KeyParameter(Hex.decode("0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E")),
+ "0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E",
+ "8296F2F1B007AB9D533FDEE35A9AD850"),
+ };
+
+ SEEDTest()
+ {
+ super(tests, new SEEDEngine(), new KeyParameter(new byte[16]));
+ }
+
+ public String getName()
+ {
+ return "SEED";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new SEEDTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/SHA1DigestTest.java b/core/src/test/java/org/spongycastle/crypto/test/SHA1DigestTest.java
new file mode 100644
index 00000000..ab0adae2
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/SHA1DigestTest.java
@@ -0,0 +1,48 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA1Digest;
+
+/**
+ * standard vector test for SHA-1 from "Handbook of Applied Cryptography", page 345.
+ */
+public class SHA1DigestTest
+ extends DigestTest
+{
+ private static String[] messages =
+ {
+ "",
+ "a",
+ "abc",
+ "abcdefghijklmnopqrstuvwxyz"
+ };
+
+ private static String[] digests =
+ {
+ "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+ "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8",
+ "a9993e364706816aba3e25717850c26c9cd0d89d",
+ "32d10c7b8cf96570ca04ce37f2a19d84240d3a89"
+ };
+
+ SHA1DigestTest()
+ {
+ super(new SHA1Digest(), messages, digests);
+ }
+
+ protected Digest cloneDigest(Digest digest)
+ {
+ return new SHA1Digest((SHA1Digest)digest);
+ }
+
+ protected Digest cloneDigest(byte[] encodedState)
+ {
+ return new SHA1Digest(encodedState);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new SHA1DigestTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/SHA1HMacTest.java b/core/src/test/java/org/spongycastle/crypto/test/SHA1HMacTest.java
new file mode 100644
index 00000000..4740988c
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/SHA1HMacTest.java
@@ -0,0 +1,111 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.macs.HMac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+/**
+ * SHA1 HMac Test, test vectors from RFC 2202
+ */
+public class SHA1HMacTest
+ implements Test
+{
+ final static String[] keys = {
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "4a656665",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "0102030405060708090a0b0c0d0e0f10111213141516171819",
+ "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F"
+ };
+
+ final static String[] digests = {
+ "b617318655057264e28bc0b6fb378c8ef146be00",
+ "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79",
+ "125d7342b9ac11cd91a39af48aa17b4f63f175d3",
+ "4c9007f4026250c6bc8414f9bf50c86c2d7235da",
+ "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04",
+ "aa4ae5e15272d00e95705637ce8a3b55ed402112",
+ "e8e99d0f45237d786d6bbaa7965c7808bbff1a91",
+ "5FD596EE78D5553C8FF4E72D266DFD192366DA29"
+ };
+
+ final static String[] messages = {
+ "Hi There",
+ "what do ya want for nothing?",
+ "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
+ "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+ "Test With Truncation",
+ "Test Using Larger Than Block-Size Key - Hash Key First",
+ "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
+ "Sample message for keylen=blocklen"
+ };
+
+ public String getName()
+ {
+ return "SHA1HMac";
+ }
+
+ public TestResult perform()
+ {
+ HMac hmac = new HMac(new SHA1Digest());
+ byte[] resBuf = new byte[hmac.getMacSize()];
+
+ for (int i = 0; i < messages.length; i++)
+ {
+ byte[] m = messages[i].getBytes();
+ if (messages[i].startsWith("0x"))
+ {
+ m = Hex.decode(messages[i].substring(2));
+ }
+ hmac.init(new KeyParameter(Hex.decode(keys[i])));
+ hmac.update(m, 0, m.length);
+ hmac.doFinal(resBuf, 0);
+
+ if (!Arrays.areEqual(resBuf, Hex.decode(digests[i])))
+ {
+ return new SimpleTestResult(false, getName() + ": Vector " + i + " failed");
+ }
+ }
+
+ //
+ // test reset
+ //
+ int vector = 0; // vector used for test
+ byte[] m = messages[vector].getBytes();
+ if (messages[vector].startsWith("0x"))
+ {
+ m = Hex.decode(messages[vector].substring(2));
+ }
+ hmac.init(new KeyParameter(Hex.decode(keys[vector])));
+ hmac.update(m, 0, m.length);
+ hmac.doFinal(resBuf, 0);
+ hmac.reset();
+ hmac.update(m, 0, m.length);
+ hmac.doFinal(resBuf, 0);
+
+ if (!Arrays.areEqual(resBuf, Hex.decode(digests[vector])))
+ {
+ return new SimpleTestResult(false, getName() +
+ "Reset with vector " + vector + " failed");
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+
+ public static void main(
+ String[] args)
+ {
+ SHA1HMacTest test = new SHA1HMacTest();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/SHA224DigestTest.java b/core/src/test/java/org/spongycastle/crypto/test/SHA224DigestTest.java
new file mode 100644
index 00000000..abe5b316
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/SHA224DigestTest.java
@@ -0,0 +1,59 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA224Digest;
+
+/**
+ * standard vector test for SHA-224 from RFC 3874 - only the last three are in
+ * the RFC.
+ */
+public class SHA224DigestTest
+ extends DigestTest
+{
+ private static String[] messages =
+ {
+ "",
+ "a",
+ "abc",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ };
+
+ private static String[] digests =
+ {
+ "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f",
+ "abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5",
+ "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7",
+ "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525"
+ };
+
+ // 1 million 'a'
+ static private String million_a_digest = "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67";
+
+ SHA224DigestTest()
+ {
+ super(new SHA224Digest(), messages, digests);
+ }
+
+ public void performTest()
+ {
+ super.performTest();
+
+ millionATest(million_a_digest);
+ }
+
+ protected Digest cloneDigest(Digest digest)
+ {
+ return new SHA224Digest((SHA224Digest)digest);
+ }
+
+ protected Digest cloneDigest(byte[] encodedState)
+ {
+ return new SHA224Digest(encodedState);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new SHA224DigestTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/SHA224HMacTest.java b/core/src/test/java/org/spongycastle/crypto/test/SHA224HMacTest.java
new file mode 100644
index 00000000..5f4c73ed
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/SHA224HMacTest.java
@@ -0,0 +1,108 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.digests.SHA224Digest;
+import org.spongycastle.crypto.macs.HMac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+/**
+ * SHA224 HMac Test
+ */
+public class SHA224HMacTest
+ implements Test
+{
+ final static String[] keys = {
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "4a656665",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "0102030405060708090a0b0c0d0e0f10111213141516171819",
+ "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ };
+
+ final static String[] digests = {
+ "896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22",
+ "a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44",
+ "7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea",
+ "6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a",
+ "0e2aea68a90c8d37c988bcdb9fca6fa8099cd857c7ec4a1815cac54c",
+ "95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e",
+ "3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1"
+ };
+
+ final static String[] messages = {
+ "Hi There",
+ "what do ya want for nothing?",
+ "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
+ "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+ "Test With Truncation",
+ "Test Using Larger Than Block-Size Key - Hash Key First",
+ "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."
+ };
+
+ public String getName()
+ {
+ return "SHA224HMac";
+ }
+
+ public TestResult perform()
+ {
+ HMac hmac = new HMac(new SHA224Digest());
+ byte[] resBuf = new byte[hmac.getMacSize()];
+
+ for (int i = 0; i < messages.length; i++)
+ {
+ byte[] m = messages[i].getBytes();
+ if (messages[i].startsWith("0x"))
+ {
+ m = Hex.decode(messages[i].substring(2));
+ }
+ hmac.init(new KeyParameter(Hex.decode(keys[i])));
+ hmac.update(m, 0, m.length);
+ hmac.doFinal(resBuf, 0);
+
+ if (!Arrays.areEqual(resBuf, Hex.decode(digests[i])))
+ {
+ return new SimpleTestResult(false, getName() + ": Vector " + i + " failed got -" + new String(Hex.encode(resBuf)));
+ }
+ }
+
+ //
+ // test reset
+ //
+ int vector = 0; // vector used for test
+ byte[] m = messages[vector].getBytes();
+ if (messages[vector].startsWith("0x"))
+ {
+ m = Hex.decode(messages[vector].substring(2));
+ }
+ hmac.init(new KeyParameter(Hex.decode(keys[vector])));
+ hmac.update(m, 0, m.length);
+ hmac.doFinal(resBuf, 0);
+ hmac.reset();
+ hmac.update(m, 0, m.length);
+ hmac.doFinal(resBuf, 0);
+
+ if (!Arrays.areEqual(resBuf, Hex.decode(digests[vector])))
+ {
+ return new SimpleTestResult(false, getName() +
+ "Reset with vector " + vector + " failed");
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+
+ public static void main(
+ String[] args)
+ {
+ SHA224HMacTest test = new SHA224HMacTest();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/SHA256DigestTest.java b/core/src/test/java/org/spongycastle/crypto/test/SHA256DigestTest.java
new file mode 100644
index 00000000..548ca1fb
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/SHA256DigestTest.java
@@ -0,0 +1,60 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+
+/**
+ * standard vector test for SHA-256 from FIPS Draft 180-2.
+ *
+ * Note, the first two vectors are _not_ from the draft, the last three are.
+ */
+public class SHA256DigestTest
+ extends DigestTest
+{
+ private static String[] messages =
+ {
+ "",
+ "a",
+ "abc",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ };
+
+ private static String[] digests =
+ {
+ "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb",
+ "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
+ "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
+ };
+
+ // 1 million 'a'
+ static private String million_a_digest = "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0";
+
+ SHA256DigestTest()
+ {
+ super(new SHA256Digest(), messages, digests);
+ }
+
+ public void performTest()
+ {
+ super.performTest();
+
+ millionATest(million_a_digest);
+ }
+
+ protected Digest cloneDigest(Digest digest)
+ {
+ return new SHA256Digest((SHA256Digest)digest);
+ }
+
+ protected Digest cloneDigest(byte[] encodedState)
+ {
+ return new SHA256Digest(encodedState);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new SHA256DigestTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/SHA256HMacTest.java b/core/src/test/java/org/spongycastle/crypto/test/SHA256HMacTest.java
new file mode 100644
index 00000000..f29a81d1
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/SHA256HMacTest.java
@@ -0,0 +1,108 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.macs.HMac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+/**
+ * SHA256 HMac Test
+ */
+public class SHA256HMacTest
+ implements Test
+{
+ final static String[] keys = {
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "4a656665",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "0102030405060708090a0b0c0d0e0f10111213141516171819",
+ "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ };
+
+ final static String[] digests = {
+ "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7",
+ "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843",
+ "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe",
+ "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b",
+ "a3b6167473100ee06e0c796c2955552bfa6f7c0a6a8aef8b93f860aab0cd20c5",
+ "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54",
+ "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2"
+ };
+
+ final static String[] messages = {
+ "Hi There",
+ "what do ya want for nothing?",
+ "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
+ "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+ "Test With Truncation",
+ "Test Using Larger Than Block-Size Key - Hash Key First",
+ "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."
+ };
+
+ public String getName()
+ {
+ return "SHA256HMac";
+ }
+
+ public TestResult perform()
+ {
+ HMac hmac = new HMac(new SHA256Digest());
+ byte[] resBuf = new byte[hmac.getMacSize()];
+
+ for (int i = 0; i < messages.length; i++)
+ {
+ byte[] m = messages[i].getBytes();
+ if (messages[i].startsWith("0x"))
+ {
+ m = Hex.decode(messages[i].substring(2));
+ }
+ hmac.init(new KeyParameter(Hex.decode(keys[i])));
+ hmac.update(m, 0, m.length);
+ hmac.doFinal(resBuf, 0);
+
+ if (!Arrays.areEqual(resBuf, Hex.decode(digests[i])))
+ {
+ return new SimpleTestResult(false, getName() + ": Vector " + i + " failed got -" + new String(Hex.encode(resBuf)));
+ }
+ }
+
+ //
+ // test reset
+ //
+ int vector = 0; // vector used for test
+ byte[] m = messages[vector].getBytes();
+ if (messages[vector].startsWith("0x"))
+ {
+ m = Hex.decode(messages[vector].substring(2));
+ }
+ hmac.init(new KeyParameter(Hex.decode(keys[vector])));
+ hmac.update(m, 0, m.length);
+ hmac.doFinal(resBuf, 0);
+ hmac.reset();
+ hmac.update(m, 0, m.length);
+ hmac.doFinal(resBuf, 0);
+
+ if (!Arrays.areEqual(resBuf, Hex.decode(digests[vector])))
+ {
+ return new SimpleTestResult(false, getName() +
+ "Reset with vector " + vector + " failed");
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+
+ public static void main(
+ String[] args)
+ {
+ SHA256HMacTest test = new SHA256HMacTest();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/SHA384DigestTest.java b/core/src/test/java/org/spongycastle/crypto/test/SHA384DigestTest.java
new file mode 100644
index 00000000..7e1afbf3
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/SHA384DigestTest.java
@@ -0,0 +1,59 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA384Digest;
+
+/**
+ * standard vector test for SHA-384 from FIPS Draft 180-2.
+ *
+ * Note, the first two vectors are _not_ from the draft, the last three are.
+ */
+public class SHA384DigestTest
+ extends DigestTest
+{
+ private static String[] messages =
+ {
+ "",
+ "a",
+ "abc",
+ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
+ };
+
+ private static String[] digests =
+ {
+ "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b",
+ "54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31",
+ "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7",
+ "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039"
+ };
+
+ static private String million_a_digest = "9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985";
+
+ SHA384DigestTest()
+ {
+ super(new SHA384Digest(), messages, digests);
+ }
+
+ public void performTest()
+ {
+ super.performTest();
+
+ millionATest(million_a_digest);
+ }
+
+ protected Digest cloneDigest(Digest digest)
+ {
+ return new SHA384Digest((SHA384Digest)digest);
+ }
+
+ protected Digest cloneDigest(byte[] encodedState)
+ {
+ return new SHA384Digest(encodedState);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new SHA384DigestTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/SHA384HMacTest.java b/core/src/test/java/org/spongycastle/crypto/test/SHA384HMacTest.java
new file mode 100644
index 00000000..77152471
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/SHA384HMacTest.java
@@ -0,0 +1,108 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.digests.SHA384Digest;
+import org.spongycastle.crypto.macs.HMac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+/**
+ * SHA384 HMac Test
+ */
+public class SHA384HMacTest
+ implements Test
+{
+ final static String[] keys = {
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "4a656665",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "0102030405060708090a0b0c0d0e0f10111213141516171819",
+ "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ };
+
+ final static String[] digests = {
+ "afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6",
+ "af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649",
+ "88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b2a5ab39dc13814b94e3ab6e101a34f27",
+ "3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e6801dd23c4a7d679ccf8a386c674cffb",
+ "3abf34c3503b2a23a46efc619baef897f4c8e42c934ce55ccbae9740fcbc1af4ca62269e2a37cd88ba926341efe4aeea",
+ "4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c60c2ef6ab4030fe8296248df163f44952",
+ "6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5a678cc31e799176d3860e6110c46523e"
+ };
+
+ final static String[] messages = {
+ "Hi There",
+ "what do ya want for nothing?",
+ "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
+ "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+ "Test With Truncation",
+ "Test Using Larger Than Block-Size Key - Hash Key First",
+ "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."
+ };
+
+ public String getName()
+ {
+ return "SHA384HMac";
+ }
+
+ public TestResult perform()
+ {
+ HMac hmac = new HMac(new SHA384Digest());
+ byte[] resBuf = new byte[hmac.getMacSize()];
+
+ for (int i = 0; i < messages.length; i++)
+ {
+ byte[] m = messages[i].getBytes();
+ if (messages[i].startsWith("0x"))
+ {
+ m = Hex.decode(messages[i].substring(2));
+ }
+ hmac.init(new KeyParameter(Hex.decode(keys[i])));
+ hmac.update(m, 0, m.length);
+ hmac.doFinal(resBuf, 0);
+
+ if (!Arrays.areEqual(resBuf, Hex.decode(digests[i])))
+ {
+ return new SimpleTestResult(false, getName() + ": Vector " + i + " failed got -" + new String(Hex.encode(resBuf)));
+ }
+ }
+
+ //
+ // test reset
+ //
+ int vector = 0; // vector used for test
+ byte[] m = messages[vector].getBytes();
+ if (messages[vector].startsWith("0x"))
+ {
+ m = Hex.decode(messages[vector].substring(2));
+ }
+ hmac.init(new KeyParameter(Hex.decode(keys[vector])));
+ hmac.update(m, 0, m.length);
+ hmac.doFinal(resBuf, 0);
+ hmac.reset();
+ hmac.update(m, 0, m.length);
+ hmac.doFinal(resBuf, 0);
+
+ if (!Arrays.areEqual(resBuf, Hex.decode(digests[vector])))
+ {
+ return new SimpleTestResult(false, getName() +
+ "Reset with vector " + vector + " failed");
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+
+ public static void main(
+ String[] args)
+ {
+ SHA384HMacTest test = new SHA384HMacTest();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/SHA3DigestTest.java b/core/src/test/java/org/spongycastle/crypto/test/SHA3DigestTest.java
new file mode 100644
index 00000000..eb636e2a
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/SHA3DigestTest.java
@@ -0,0 +1,363 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.digests.SHA3Digest;
+import org.spongycastle.crypto.macs.HMac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * SHA3 Digest Test
+ */
+public class SHA3DigestTest
+ extends SimpleTest
+{
+ final static String[] messages = {
+ "",
+ "54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67",
+ "54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f672e"
+ };
+
+ final static String[] digests288 = { // the default settings
+ "6753e3380c09e385d0339eb6b050a68f66cfd60a73476e6fd6adeb72f5edd7c6f04a5d01", // message[0]
+ "0bbe6afae0d7e89054085c1cc47b1689772c89a41796891e197d1ca1b76f288154933ded", // message[1]
+ "82558a209b960ddeb531e6dcb281885b2400ca160472462486e79f071e88a3330a8a303d", // message[2]
+ "94049e1ad7ef5d5b0df2b880489e7ab09ec937c3bfc1b04470e503e1ac7b1133c18f86da", // 64k a-test
+ "a9cb5a75b5b81b7528301e72553ed6770214fa963956e790528afe420de33c074e6f4220", // random alphabet test
+ "eadaf5ba2ad6a2f6f338fce0e1efdad2a61bb38f6be6068b01093977acf99e97a5d5827c" // extremely long data test
+ };
+
+ final static String[] digests224 = {
+ "f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd",
+ "310aee6b30c47350576ac2873fa89fd190cdc488442f3ef654cf23fe",
+ "c59d4eaeac728671c635ff645014e2afa935bebffdb5fbd207ffdeab",
+ "f621e11c142fbf35fa8c22841c3a812ba1e0151be4f38d80b9f1ff53",
+ "68b5fc8c87193155bba68a2485377e809ee4f81a85ef023b9e64add0",
+ "c42e4aee858e1a8ad2976896b9d23dd187f64436ee15969afdbc68c5"
+ };
+
+ final static String[] digests256 = {
+ "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "4d741b6f1eb29cb2a9b9911c82f56fa8d73b04959d3d9d222895df6c0b28aa15",
+ "578951e24efd62a3d63a86f7cd19aaa53c898fe287d2552133220370240b572d",
+ "0047a916daa1f92130d870b542e22d3108444f5a7e4429f05762fb647e6ed9ed",
+ "db368762253ede6d4f1db87e0b799b96e554eae005747a2ea687456ca8bcbd03",
+ "5f313c39963dcf792b5470d4ade9f3a356a3e4021748690a958372e2b06f82a4"
+ };
+
+ final static String[] digests384 = {
+ "2c23146a63a29acf99e73b88f8c24eaa7dc60aa771780ccc006afbfa8fe2479b2dd2b21362337441ac12b515911957ff",
+ "283990fa9d5fb731d786c5bbee94ea4db4910f18c62c03d173fc0a5e494422e8a0b3da7574dae7fa0baf005e504063b3",
+ "9ad8e17325408eddb6edee6147f13856ad819bb7532668b605a24a2d958f88bd5c169e56dc4b2f89ffd325f6006d820b",
+ "c704cfe7a1a53208ca9526cd24251e0acdc252ecd978eee05acd16425cfb404ea81f5a9e2e5e97784d63ee6a0618a398",
+ "d4fe8586fd8f858dd2e4dee0bafc19b4c12b4e2a856054abc4b14927354931675cdcaf942267f204ea706c19f7beefc4",
+ "9b7168b4494a80a86408e6b9dc4e5a1837c85dd8ff452ed410f2832959c08c8c0d040a892eb9a755776372d4a8732315"
+ };
+
+ final static String[] digests512 = {
+ "0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e",
+ "d135bb84d0439dbac432247ee573a23ea7d3c9deb2a968eb31d47c4fb45f1ef4422d6c531b5b9bd6f449ebcc449ea94d0a8f05f62130fda612da53c79659f609",
+ "ab7192d2b11f51c7dd744e7b3441febf397ca07bf812cceae122ca4ded6387889064f8db9230f173f6d1ab6e24b6e50f065b039f799f5592360a6558eb52d760",
+ "34341ead153aa1d1fdcf6cf624c2b4f6894b6fd16dc38bd4ec971ac0385ad54fafcb2e0ed86a1e509456f4246fdcb02c3172824cd649d9ad54c51f7fb49ea67c",
+ "dc44d4f4d36b07ab5fc04016cbe53548e5a7778671c58a43cb379fd00c06719b8073141fc22191ffc3db5f8b8983ae8341fa37f18c1c969664393aa5ceade64e",
+ "3e122edaf37398231cfaca4c7c216c9d66d5b899ec1d7ac617c40c7261906a45fc01617a021e5da3bd8d4182695b5cb785a28237cbb167590e34718e56d8aab8"
+ };
+
+ // test vectors from http://www.di-mgt.com.au/hmac_sha3_testvectors.html
+ final static byte[][] macKeys =
+ {
+ Hex.decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
+ Hex.decode("4a656665"),
+ Hex.decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
+ Hex.decode("0102030405060708090a0b0c0d0e0f10111213141516171819"),
+ Hex.decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+ "aaaaaa"),
+ Hex.decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+ "aaaaaa"),
+ Hex.decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
+ };
+
+ final static String[] macData =
+ {
+ "4869205468657265",
+ "7768617420646f2079612077616e7420666f72206e6f7468696e673f",
+ "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" +
+ "dddddddddddddddddddddddddddddddddddd",
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" +
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+ "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a" +
+ "65204b6579202d2048617368204b6579204669727374",
+ "5468697320697320612074657374207573696e672061206c6172676572207468" +
+ "616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074" +
+ "68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565" +
+ "647320746f20626520686173686564206265666f7265206265696e6720757365" +
+ "642062792074686520484d414320616c676f726974686d2e",
+ "5468697320697320612074657374207573696e672061206c6172676572207468" +
+ "616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074" +
+ "68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565" +
+ "647320746f20626520686173686564206265666f7265206265696e6720757365\n" +
+ "642062792074686520484d414320616c676f726974686d2e"
+ };
+
+ final static String[] mac224 =
+ {
+ "b73d595a2ba9af815e9f2b4e53e78581ebd34a80b3bbaac4e702c4cc",
+ "e824fec96c074f22f99235bb942da1982664ab692ca8501053cbd414",
+ "770df38c99d6e2bacd68056dcfe07d4c89ae20b2686a6185e1faa449",
+ "305a8f2dfb94bad28861a03cbc4d590febe775c58cb4961c28428a0b",
+ "e7a52dfa45f95a217c100066b239aa8ad519be9b35d667268b1b57ff",
+ "ba13009405a929f398b348885caa5419191bb948ada32194afc84104",
+ "92649468be236c3c72c189909c063b13f994be05749dc91310db639e"
+ };
+
+ final static String[] mac256 =
+ {
+ "9663d10c73ee294054dc9faf95647cb99731d12210ff7075fb3d3395abfb9821",
+ "aa9aed448c7abc8b5e326ffa6a01cdedf7b4b831881468c044ba8dd4566369a1",
+ "95f43e50f8df80a21977d51a8db3ba572dcd71db24687e6f86f47c1139b26260",
+ "6331ba9b4af5804a68725b3663eb74814494b63c6093e35fb320a85d507936fd",
+ "b4d0cdee7ec2ba81a88b86918958312300a15622377929a054a9ce3ae1fac2b6",
+ "1fdc8cb4e27d07c10d897dec39c217792a6e64fa9c63a77ce42ad106ef284e02",
+ "fdaa10a0299aecff9bb411cf2d7748a4022e4a26be3fb5b11b33d8c2b7ef5484"
+ };
+
+ final static String[] mac384 =
+ {
+ "892dfdf5d51e4679bf320cd16d4c9dc6f749744608e003add7fba894acff87361efa4e5799be06b6461f43b60ae97048",
+ "5af5c9a77a23a6a93d80649e562ab77f4f3552e3c5caffd93bdf8b3cfc6920e3023fc26775d9df1f3c94613146ad2c9d",
+ "4243c29f2201992ff96441e3b91ff81d8c601d706fbc83252684a4bc51101ca9b2c06ddd03677303c502ac5331752a3c",
+ "b730724d3d4090cda1be799f63acbbe389fef7792fc18676fa5453aab398664650ed029c3498bbe8056f06c658e1e693",
+ "d62482ef601d7847439b55236e9679388ffcd53c62cd126f39be6ea63de762e26cd5974cb9a8de401b786b5555040f6f",
+ "4860ea191ac34994cf88957afe5a836ef36e4cc1a66d75bf77defb7576122d75f60660e4cf731c6effac06402787e2b9",
+ "fe9357e3cfa538eb0373a2ce8f1e26ad6590afdaf266f1300522e8896d27e73f654d0631c8fa598d4bb82af6b744f4f5"
+ };
+
+ final static String[] mac512 =
+ {
+ "8852c63be8cfc21541a4ee5e5a9a852fc2f7a9adec2ff3a13718ab4ed81aaea0b87b7eb397323548e261a64e7fc75198f6663a11b22cd957f7c8ec858a1c7755",
+ "c2962e5bbe1238007852f79d814dbbecd4682e6f097d37a363587c03bfa2eb0859d8d9c701e04cececfd3dd7bfd438f20b8b648e01bf8c11d26824b96cebbdcb",
+ "eb0ed9580e0ec11fc66cbb646b1be904eaff6da4556d9334f65ee4b2c85739157bae9027c51505e49d1bb81cfa55e6822db55262d5a252c088a29a5e95b84a66",
+ "b46193bb59f4f696bf702597616da91e2a4558a593f4b015e69141ba81e1e50ea580834c2b87f87baa25a3a03bfc9bb389847f2dc820beae69d30c4bb75369cb",
+ "d05888a6ebf8460423ea7bc85ea4ffda847b32df32291d2ce115fd187707325c7ce4f71880d91008084ce24a38795d20e6a28328a0f0712dc38253370da3ebb5",
+ "2c6b9748d35c4c8db0b4407dd2ed2381f133bdbd1dfaa69e30051eb6badfcca64299b88ae05fdbd3dd3dd7fe627e42e39e48b0fe8c7f1e85f2dbd52c2d753572",
+ "6adc502f14e27812402fc81a807b28bf8a53c87bea7a1df6256bf66f5de1a4cb741407ad15ab8abc136846057f881969fbb159c321c904bfb557b77afb7778c8"
+ };
+
+ final static KeyParameter truncKey = new KeyParameter(Hex.decode("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c"));
+ final static byte[] truncData = Hex.decode("546573742057697468205472756e636174696f6e");
+
+ final static byte[] trunc224 = Hex.decode("f52bbcfd654264e7133085c5e69b72c3");
+ final static byte[] trunc256 = Hex.decode("745e7e687f8335280d54202ef13cecc6");
+ final static byte[] trunc384 = Hex.decode("fa9aea2bc1e181e47cbb8c3df243814d");
+ final static byte[] trunc512 = Hex.decode("04c929fead434bba190dacfa554ce3f5");
+
+ final static byte[] xtremeData = Hex.decode("61626364656667686263646566676869636465666768696a6465666768696a6b65666768696a6b6c666768696a6b6c6d6768696a6b6c6d6e68696a6b6c6d6e6f");
+
+ SHA3DigestTest()
+ {
+ }
+
+ public String getName()
+ {
+ return "SHA3";
+ }
+
+ private void testDigest(Digest digest, String[] expected)
+ {
+ byte[] hash = new byte[digest.getDigestSize()];
+
+ for (int i = 0; i != messages.length; i++)
+ {
+ if (messages.length != 0)
+ {
+ byte[] data = Hex.decode(messages[i]);
+
+ digest.update(data, 0, data.length);
+ }
+
+ digest.doFinal(hash, 0);
+
+ if (!Arrays.areEqual(Hex.decode(expected[i]), hash))
+ {
+ fail("sha3 mismatch on " + digest.getAlgorithmName() + " index " + i);
+ }
+ }
+
+ byte[] k64 = new byte[1024 * 64];
+
+ for (int i = 0; i != k64.length; i++)
+ {
+ k64[i] = (byte)'a';
+ }
+
+ digest.update(k64, 0, k64.length);
+
+ digest.doFinal(hash, 0);
+
+ if (!Arrays.areEqual(Hex.decode(expected[messages.length]), hash))
+ {
+ fail("sha3 mismatch on " + digest.getAlgorithmName() + " 64k a");
+ }
+
+ for (int i = 0; i != k64.length; i++)
+ {
+ digest.update((byte)'a');
+ }
+
+ digest.doFinal(hash, 0);
+
+ if (!Arrays.areEqual(Hex.decode(expected[messages.length]), hash))
+ {
+ fail("sha3 mismatch on " + digest.getAlgorithmName() + " 64k a single");
+ }
+
+
+ for (int i = 0; i != k64.length; i++)
+ {
+ k64[i] = (byte)('a' + (i % 26));
+ }
+
+ digest.update(k64, 0, k64.length);
+
+ digest.doFinal(hash, 0);
+
+ if (!Arrays.areEqual(Hex.decode(expected[messages.length + 1]), hash))
+ {
+ fail("sha3 mismatch on " + digest.getAlgorithmName() + " 64k alpha");
+ }
+
+ for (int i = 0; i != 64; i++)
+ {
+ digest.update(k64[i * 1024]);
+ digest.update(k64, i * 1024 + 1, 1023);
+ }
+
+ digest.doFinal(hash, 0);
+
+ if (!Arrays.areEqual(Hex.decode(expected[messages.length + 1]), hash))
+ {
+ fail("sha3 mismatch on " + digest.getAlgorithmName() + " 64k chunked alpha");
+ }
+
+ testDigestDoFinal(digest);
+
+ //
+ // extremely long data test
+ //
+// System.out.println("Starting very long");
+// for (int i = 0; i != 16384; i++)
+// {
+// for (int j = 0; j != 1024; j++)
+// {
+// digest.update(xtremeData, 0, xtremeData.length);
+// }
+// }
+//
+// digest.doFinal(hash, 0);
+//
+// if (!Arrays.areEqual(Hex.decode(expected[messages.length + 2]), hash))
+// {
+// fail("sha3 mismatch on " + digest.getAlgorithmName() + " extreme data test");
+// }
+// System.out.println("Done");
+ }
+
+ private void testDigestDoFinal(Digest digest)
+ {
+ byte[] hash = new byte[digest.getDigestSize()];
+ digest.doFinal(hash, 0);
+
+ for (int i = 0; i <= digest.getDigestSize(); ++i)
+ {
+ byte[] cmp = new byte[2 * digest.getDigestSize()];
+ System.arraycopy(hash, 0, cmp, i, hash.length);
+
+ byte[] buf = new byte[2 * digest.getDigestSize()];
+ digest.doFinal(buf, i);
+
+ if (!Arrays.areEqual(cmp, buf))
+ {
+ fail("sha3 offset doFinal on " + digest.getAlgorithmName());
+ }
+ }
+ }
+
+ private void testMac(Digest digest, byte[][] keys, String[] data, String[] expected, byte[] truncExpected)
+ {
+ Mac mac = new HMac(digest);
+
+ for (int i = 0; i != keys.length; i++)
+ {
+ mac.init(new KeyParameter(keys[i]));
+
+ byte[] mData = Hex.decode(data[i]);
+
+ mac.update(mData, 0, mData.length);
+
+ byte[] macV = new byte[mac.getMacSize()];
+
+ mac.doFinal(macV, 0);
+
+ if (!Arrays.areEqual(Hex.decode(expected[i]), macV))
+ {
+ fail("sha3 HMAC mismatch on " + digest.getAlgorithmName());
+ }
+ }
+
+ mac = new HMac(digest);
+
+ mac.init(truncKey);
+
+ mac.update(truncData, 0, truncData.length);
+
+ byte[] macV = new byte[mac.getMacSize()];
+
+ mac.doFinal(macV, 0);
+
+ for (int i = 0; i != truncExpected.length; i++)
+ {
+ if (macV[i] != truncExpected[i])
+ {
+ fail("mismatch on truncated HMAC for " + digest.getAlgorithmName());
+ }
+ }
+ }
+
+ public void performTest()
+ {
+ testDigest(new SHA3Digest(), digests288);
+ testDigest(new SHA3Digest(224), digests224);
+ testDigest(new SHA3Digest(256), digests256);
+ testDigest(new SHA3Digest(384), digests384);
+ testDigest(new SHA3Digest(512), digests512);
+
+ testMac(new SHA3Digest(224), macKeys, macData, mac224, trunc224);
+ testMac(new SHA3Digest(256), macKeys, macData, mac256, trunc256);
+ testMac(new SHA3Digest(384), macKeys, macData, mac384, trunc384);
+ testMac(new SHA3Digest(512), macKeys, macData, mac512, trunc512);
+ }
+
+ protected Digest cloneDigest(Digest digest)
+ {
+ return new SHA3Digest((SHA3Digest)digest);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new SHA3DigestTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/SHA512DigestTest.java b/core/src/test/java/org/spongycastle/crypto/test/SHA512DigestTest.java
new file mode 100644
index 00000000..e1ccc9e2
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/SHA512DigestTest.java
@@ -0,0 +1,60 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA512Digest;
+
+/**
+ * standard vector test for SHA-512 from FIPS Draft 180-2.
+ *
+ * Note, the first two vectors are _not_ from the draft, the last three are.
+ */
+public class SHA512DigestTest
+ extends DigestTest
+{
+ private static String[] messages =
+ {
+ "",
+ "a",
+ "abc",
+ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
+ };
+
+ private static String[] digests =
+ {
+ "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e",
+ "1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75",
+ "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
+ "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"
+ };
+
+ // 1 million 'a'
+ static private String million_a_digest = "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b";
+
+ SHA512DigestTest()
+ {
+ super(new SHA512Digest(), messages, digests);
+ }
+
+ public void performTest()
+ {
+ super.performTest();
+
+ millionATest(million_a_digest);
+ }
+
+ protected Digest cloneDigest(Digest digest)
+ {
+ return new SHA512Digest((SHA512Digest)digest);
+ }
+
+ protected Digest cloneDigest(byte[] encodedState)
+ {
+ return new SHA512Digest(encodedState);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new SHA512DigestTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/SHA512HMacTest.java b/core/src/test/java/org/spongycastle/crypto/test/SHA512HMacTest.java
new file mode 100644
index 00000000..c4b4d66a
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/SHA512HMacTest.java
@@ -0,0 +1,108 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.digests.SHA512Digest;
+import org.spongycastle.crypto.macs.HMac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+/**
+ * SHA512 HMac Test
+ */
+public class SHA512HMacTest
+ implements Test
+{
+ final static String[] keys = {
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "4a656665",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "0102030405060708090a0b0c0d0e0f10111213141516171819",
+ "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ };
+
+ final static String[] digests = {
+ "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854",
+ "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737",
+ "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb",
+ "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd",
+ "415fad6271580a531d4179bc891d87a650188707922a4fbb36663a1eb16da008711c5b50ddd0fc235084eb9d3364a1454fb2ef67cd1d29fe6773068ea266e96b",
+ "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598",
+ "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58"
+ };
+
+ final static String[] messages = {
+ "Hi There",
+ "what do ya want for nothing?",
+ "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
+ "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+ "Test With Truncation",
+ "Test Using Larger Than Block-Size Key - Hash Key First",
+ "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."
+ };
+
+ public String getName()
+ {
+ return "SHA512HMac";
+ }
+
+ public TestResult perform()
+ {
+ HMac hmac = new HMac(new SHA512Digest());
+ byte[] resBuf = new byte[hmac.getMacSize()];
+
+ for (int i = 0; i < messages.length; i++)
+ {
+ byte[] m = messages[i].getBytes();
+ if (messages[i].startsWith("0x"))
+ {
+ m = Hex.decode(messages[i].substring(2));
+ }
+ hmac.init(new KeyParameter(Hex.decode(keys[i])));
+ hmac.update(m, 0, m.length);
+ hmac.doFinal(resBuf, 0);
+
+ if (!Arrays.areEqual(resBuf, Hex.decode(digests[i])))
+ {
+ return new SimpleTestResult(false, getName() + ": Vector " + i + " failed got -" + new String(Hex.encode(resBuf)));
+ }
+ }
+
+ //
+ // test reset
+ //
+ int vector = 0; // vector used for test
+ byte[] m = messages[vector].getBytes();
+ if (messages[vector].startsWith("0x"))
+ {
+ m = Hex.decode(messages[vector].substring(2));
+ }
+ hmac.init(new KeyParameter(Hex.decode(keys[vector])));
+ hmac.update(m, 0, m.length);
+ hmac.doFinal(resBuf, 0);
+ hmac.reset();
+ hmac.update(m, 0, m.length);
+ hmac.doFinal(resBuf, 0);
+
+ if (!Arrays.areEqual(resBuf, Hex.decode(digests[vector])))
+ {
+ return new SimpleTestResult(false, getName() +
+ "Reset with vector " + vector + " failed");
+ }
+
+ return new SimpleTestResult(true, getName() + ": Okay");
+ }
+
+ public static void main(
+ String[] args)
+ {
+ SHA512HMacTest test = new SHA512HMacTest();
+ TestResult result = test.perform();
+
+ System.out.println(result);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/SHA512t224DigestTest.java b/core/src/test/java/org/spongycastle/crypto/test/SHA512t224DigestTest.java
new file mode 100644
index 00000000..443aa0b9
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/SHA512t224DigestTest.java
@@ -0,0 +1,60 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA512tDigest;
+
+/**
+ * standard vector test for SHA-512/224 from FIPS 180-4.
+ *
+ * Note, only the last 2 message entries are FIPS originated..
+ */
+public class SHA512t224DigestTest
+ extends DigestTest
+{
+ private static String[] messages =
+ {
+ "",
+ "a",
+ "abc",
+ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
+ };
+
+ private static String[] digests =
+ {
+ "6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4",
+ "d5cdb9ccc769a5121d4175f2bfdd13d6310e0d3d361ea75d82108327",
+ "4634270F707B6A54DAAE7530460842E20E37ED265CEEE9A43E8924AA",
+ "23FEC5BB94D60B23308192640B0C453335D664734FE40E7268674AF9"
+ };
+
+ // 1 million 'a'
+ static private String million_a_digest = "37ab331d76f0d36de422bd0edeb22a28accd487b7a8453ae965dd287";
+
+ SHA512t224DigestTest()
+ {
+ super(new SHA512tDigest(224), messages, digests);
+ }
+
+ public void performTest()
+ {
+ super.performTest();
+
+ millionATest(million_a_digest);
+ }
+
+ protected Digest cloneDigest(Digest digest)
+ {
+ return new SHA512tDigest((SHA512tDigest)digest);
+ }
+
+ protected Digest cloneDigest(byte[] encodedState)
+ {
+ return new SHA512tDigest(encodedState);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new SHA512t224DigestTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/SHA512t256DigestTest.java b/core/src/test/java/org/spongycastle/crypto/test/SHA512t256DigestTest.java
new file mode 100644
index 00000000..3e44cf5f
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/SHA512t256DigestTest.java
@@ -0,0 +1,60 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA512tDigest;
+
+/**
+ * standard vector test for SHA-512/256 from FIPS 180-4.
+ *
+ * Note, only the last 2 message entries are FIPS originated..
+ */
+public class SHA512t256DigestTest
+ extends DigestTest
+{
+ private static String[] messages =
+ {
+ "",
+ "a",
+ "abc",
+ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
+ };
+
+ private static String[] digests =
+ {
+ "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a",
+ "455e518824bc0601f9fb858ff5c37d417d67c2f8e0df2babe4808858aea830f8",
+ "53048E2681941EF99B2E29B76B4C7DABE4C2D0C634FC6D46E0E2F13107E7AF23",
+ "3928E184FB8690F840DA3988121D31BE65CB9D3EF83EE6146FEAC861E19B563A"
+ };
+
+ // 1 million 'a'
+ static private String million_a_digest = "9a59a052930187a97038cae692f30708aa6491923ef5194394dc68d56c74fb21";
+
+ SHA512t256DigestTest()
+ {
+ super(new SHA512tDigest(256), messages, digests);
+ }
+
+ public void performTest()
+ {
+ super.performTest();
+
+ millionATest(million_a_digest);
+ }
+
+ protected Digest cloneDigest(Digest digest)
+ {
+ return new SHA512tDigest((SHA512tDigest)digest);
+ }
+
+ protected Digest cloneDigest(byte[] encodedState)
+ {
+ return new SHA512tDigest(encodedState);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new SHA512t256DigestTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/SM3DigestTest.java b/core/src/test/java/org/spongycastle/crypto/test/SM3DigestTest.java
new file mode 100644
index 00000000..df0bec32
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/SM3DigestTest.java
@@ -0,0 +1,57 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SM3Digest;
+
+/**
+ * standard vector test for SM3 digest from chinese specification
+ */
+public class SM3DigestTest
+ extends DigestTest
+{
+ private static String[] messages = {
+ // Standard test vectors
+ "abc",
+ "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd",
+ // Non-standard test vectors
+ "",
+ "a",
+ "abcdefghijklmnopqrstuvwxyz",
+ };
+
+ private static String[] digests = {
+ // Standard test vectors
+ "66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0",
+ "debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c5732",
+ // Non-standard test vectors
+ "1ab21d8355cfa17f8e61194831e81a8f22bec8c728fefb747ed035eb5082aa2b",
+ "623476ac18f65a2909e43c7fec61b49c7e764a91a18ccb82f1917a29c86c5e88",
+ "b80fe97a4da24afc277564f66a359ef440462ad28dcc6d63adb24d5c20a61595",
+ };
+
+ final static String sixtyFourKdigest = "97049bdc8f0736bc7300eafa9980aeb9cf00f24f7ec3a8f1f8884954d7655c1d";
+ final static String million_a_digest = "c8aaf89429554029e231941a2acc0ad61ff2a5acd8fadd25847a3a732b3b02c3";
+
+ SM3DigestTest()
+ {
+ super(new SM3Digest(), messages, digests);
+ }
+
+ public void performTest()
+ {
+ super.performTest();
+
+ sixtyFourKTest(sixtyFourKdigest);
+ millionATest(million_a_digest);
+ }
+
+ protected Digest cloneDigest(Digest digest)
+ {
+ return new SM3Digest((SM3Digest)digest);
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new SM3DigestTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/SRP6Test.java b/core/src/test/java/org/spongycastle/crypto/test/SRP6Test.java
new file mode 100644
index 00000000..c2ab0ad8
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/SRP6Test.java
@@ -0,0 +1,276 @@
+package org.spongycastle.crypto.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CryptoException;
+import org.spongycastle.crypto.agreement.srp.SRP6Client;
+import org.spongycastle.crypto.agreement.srp.SRP6Server;
+import org.spongycastle.crypto.agreement.srp.SRP6Util;
+import org.spongycastle.crypto.agreement.srp.SRP6VerifierGenerator;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.generators.DHParametersGenerator;
+import org.spongycastle.crypto.params.DHParameters;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class SRP6Test extends SimpleTest
+{
+ private static final BigInteger ZERO = BigInteger.valueOf(0);
+
+ private static BigInteger fromHex(String hex)
+ {
+ return new BigInteger(1, Hex.decode(hex));
+ }
+
+ // 1024 bit example prime from RFC5054 and corresponding generator
+ private static final BigInteger N_1024 = fromHex("EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C"
+ + "9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE4"
+ + "8E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B29"
+ + "7BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9A"
+ + "FD5138FE8376435B9FC61D2FC0EB06E3");
+ private static final BigInteger g_1024 = BigInteger.valueOf(2);
+
+ private final SecureRandom random = new SecureRandom();
+
+ public String getName()
+ {
+ return "SRP6";
+ }
+
+ public void performTest() throws Exception
+ {
+ rfc5054AppendixBTestVectors();
+
+ testMutualVerification(N_1024, g_1024);
+ testClientCatchesBadB(N_1024, g_1024);
+ testServerCatchesBadA(N_1024, g_1024);
+
+ testWithRandomParams(256);
+ testWithRandomParams(384);
+ testWithRandomParams(512);
+ }
+
+ private void rfc5054AppendixBTestVectors() throws Exception
+ {
+ byte[] I = "alice".getBytes("UTF8");
+ byte[] P = "password123".getBytes("UTF8");
+ byte[] s = Hex.decode("BEB25379D1A8581EB5A727673A2441EE");
+ BigInteger N = N_1024;
+ BigInteger g = g_1024;
+ BigInteger a = fromHex("60975527035CF2AD1989806F0407210BC81EDC04E2762A56AFD529DDDA2D4393");
+ BigInteger b = fromHex("E487CB59D31AC550471E81F00F6928E01DDA08E974A004F49E61F5D105284D20");
+
+ BigInteger expect_k = fromHex("7556AA045AEF2CDD07ABAF0F665C3E818913186F");
+ BigInteger expect_x = fromHex("94B7555AABE9127CC58CCF4993DB6CF84D16C124");
+ BigInteger expect_v = fromHex("7E273DE8696FFC4F4E337D05B4B375BEB0DDE1569E8FA00A9886D812"
+ + "9BADA1F1822223CA1A605B530E379BA4729FDC59F105B4787E5186F5"
+ + "C671085A1447B52A48CF1970B4FB6F8400BBF4CEBFBB168152E08AB5"
+ + "EA53D15C1AFF87B2B9DA6E04E058AD51CC72BFC9033B564E26480D78"
+ + "E955A5E29E7AB245DB2BE315E2099AFB");
+ BigInteger expect_A = fromHex("61D5E490F6F1B79547B0704C436F523DD0E560F0C64115BB72557EC4"
+ + "4352E8903211C04692272D8B2D1A5358A2CF1B6E0BFCF99F921530EC"
+ + "8E39356179EAE45E42BA92AEACED825171E1E8B9AF6D9C03E1327F44"
+ + "BE087EF06530E69F66615261EEF54073CA11CF5858F0EDFDFE15EFEA"
+ + "B349EF5D76988A3672FAC47B0769447B");
+ BigInteger expect_B = fromHex("BD0C61512C692C0CB6D041FA01BB152D4916A1E77AF46AE105393011"
+ + "BAF38964DC46A0670DD125B95A981652236F99D9B681CBF87837EC99"
+ + "6C6DA04453728610D0C6DDB58B318885D7D82C7F8DEB75CE7BD4FBAA"
+ + "37089E6F9C6059F388838E7A00030B331EB76840910440B1B27AAEAE"
+ + "EB4012B7D7665238A8E3FB004B117B58");
+ BigInteger expect_u = fromHex("CE38B9593487DA98554ED47D70A7AE5F462EF019");
+ BigInteger expect_S = fromHex("B0DC82BABCF30674AE450C0287745E7990A3381F63B387AAF271A10D"
+ + "233861E359B48220F7C4693C9AE12B0A6F67809F0876E2D013800D6C"
+ + "41BB59B6D5979B5C00A172B4A2A5903A0BDCAF8A709585EB2AFAFA8F"
+ + "3499B200210DCC1F10EB33943CD67FC88A2F39A4BE5BEC4EC0A3212D"
+ + "C346D7E474B29EDE8A469FFECA686E5A");
+
+ BigInteger k = SRP6Util.calculateK(new SHA1Digest(), N, g);
+ if (!k.equals(expect_k))
+ {
+ fail("wrong value of 'k'");
+ }
+
+ BigInteger x = SRP6Util.calculateX(new SHA1Digest(), N, s, I, P);
+ if (!x.equals(expect_x))
+ {
+ fail("wrong value of 'x'");
+ }
+
+ SRP6VerifierGenerator gen = new SRP6VerifierGenerator();
+ gen.init(N, g, new SHA1Digest());
+ BigInteger v = gen.generateVerifier(s, I, P);
+ if (!v.equals(expect_v))
+ {
+ fail("wrong value of 'v'");
+ }
+
+ final BigInteger aVal = a;
+ SRP6Client client = new SRP6Client()
+ {
+ protected BigInteger selectPrivateValue()
+ {
+ return aVal;
+ }
+ };
+ client.init(N, g, new SHA1Digest(), random);
+
+ BigInteger A = client.generateClientCredentials(s, I, P);
+ if (!A.equals(expect_A))
+ {
+ fail("wrong value of 'A'");
+ }
+
+ final BigInteger bVal = b;
+ SRP6Server server = new SRP6Server()
+ {
+ protected BigInteger selectPrivateValue()
+ {
+ return bVal;
+ }
+ };
+ server.init(N, g, v, new SHA1Digest(), random);
+
+ BigInteger B = server.generateServerCredentials();
+ if (!B.equals(expect_B))
+ {
+ fail("wrong value of 'B'");
+ }
+
+ BigInteger u = SRP6Util.calculateU(new SHA1Digest(), N, A, B);
+ if (!u.equals(expect_u))
+ {
+ fail("wrong value of 'u'");
+ }
+
+ BigInteger clientS = client.calculateSecret(B);
+ if (!clientS.equals(expect_S))
+ {
+ fail("wrong value of 'S' (client)");
+ }
+
+ BigInteger serverS = server.calculateSecret(A);
+ if (!serverS.equals(expect_S))
+ {
+ fail("wrong value of 'S' (server)");
+ }
+ }
+
+ private void testWithRandomParams(int bits) throws CryptoException
+ {
+ DHParametersGenerator paramGen = new DHParametersGenerator();
+ paramGen.init(bits, 25, random);
+ DHParameters parameters = paramGen.generateParameters();
+
+ BigInteger g = parameters.getG();
+ BigInteger p = parameters.getP();
+
+ testMutualVerification(p, g);
+ }
+
+ private void testMutualVerification(BigInteger N, BigInteger g) throws CryptoException
+ {
+ byte[] I = "username".getBytes();
+ byte[] P = "password".getBytes();
+ byte[] s = new byte[16];
+ random.nextBytes(s);
+
+ SRP6VerifierGenerator gen = new SRP6VerifierGenerator();
+ gen.init(N, g, new SHA256Digest());
+ BigInteger v = gen.generateVerifier(s, I, P);
+
+ SRP6Client client = new SRP6Client();
+ client.init(N, g, new SHA256Digest(), random);
+
+ SRP6Server server = new SRP6Server();
+ server.init(N, g, v, new SHA256Digest(), random);
+
+ BigInteger A = client.generateClientCredentials(s, I, P);
+ BigInteger B = server.generateServerCredentials();
+
+ BigInteger clientS = client.calculateSecret(B);
+ BigInteger serverS = server.calculateSecret(A);
+
+ if (!clientS.equals(serverS))
+ {
+ fail("SRP agreement failed - client/server calculated different secrets");
+ }
+ }
+
+ private void testClientCatchesBadB(BigInteger N, BigInteger g)
+ {
+ byte[] I = "username".getBytes();
+ byte[] P = "password".getBytes();
+ byte[] s = new byte[16];
+ random.nextBytes(s);
+
+ SRP6Client client = new SRP6Client();
+ client.init(N, g, new SHA256Digest(), random);
+
+ client.generateClientCredentials(s, I, P);
+
+ try
+ {
+ client.calculateSecret(ZERO);
+ fail("Client failed to detect invalid value for 'B'");
+ }
+ catch (CryptoException e)
+ {
+ // Expected
+ }
+
+ try
+ {
+ client.calculateSecret(N);
+ fail("Client failed to detect invalid value for 'B'");
+ }
+ catch (CryptoException e)
+ {
+ // Expected
+ }
+ }
+
+ private void testServerCatchesBadA(BigInteger N, BigInteger g)
+ {
+ byte[] I = "username".getBytes();
+ byte[] P = "password".getBytes();
+ byte[] s = new byte[16];
+ random.nextBytes(s);
+
+ SRP6VerifierGenerator gen = new SRP6VerifierGenerator();
+ gen.init(N, g, new SHA256Digest());
+ BigInteger v = gen.generateVerifier(s, I, P);
+
+ SRP6Server server = new SRP6Server();
+ server.init(N, g, v, new SHA256Digest(), random);
+
+ server.generateServerCredentials();
+
+ try
+ {
+ server.calculateSecret(ZERO);
+ fail("Client failed to detect invalid value for 'A'");
+ }
+ catch (CryptoException e)
+ {
+ // Expected
+ }
+
+ try
+ {
+ server.calculateSecret(N);
+ fail("Client failed to detect invalid value for 'A'");
+ }
+ catch (CryptoException e)
+ {
+ // Expected
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new SRP6Test());
+ }
+}
+
diff --git a/core/src/test/java/org/spongycastle/crypto/test/Salsa20Test.java b/core/src/test/java/org/spongycastle/crypto/test/Salsa20Test.java
new file mode 100644
index 00000000..1cdf10cf
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/Salsa20Test.java
@@ -0,0 +1,400 @@
+package org.spongycastle.crypto.test;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.StreamCipher;
+import org.spongycastle.crypto.engines.Salsa20Engine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * Salsa20 Test
+ */
+public class Salsa20Test
+ extends SimpleTest
+{
+ byte[] zeroes = Hex.decode(
+ "00000000000000000000000000000000"
+ + "00000000000000000000000000000000"
+ + "00000000000000000000000000000000"
+ + "00000000000000000000000000000000");
+
+ String set1v0_0 = "4DFA5E481DA23EA09A31022050859936"
+ + "DA52FCEE218005164F267CB65F5CFD7F"
+ + "2B4F97E0FF16924A52DF269515110A07"
+ + "F9E460BC65EF95DA58F740B7D1DBB0AA";
+
+ String set1v0_192 = "DA9C1581F429E0A00F7D67E23B730676"
+ + "783B262E8EB43A25F55FB90B3E753AEF"
+ + "8C6713EC66C51881111593CCB3E8CB8F"
+ + "8DE124080501EEEB389C4BCB6977CF95";
+
+ String set1v0_256 = "7D5789631EB4554400E1E025935DFA7B"
+ + "3E9039D61BDC58A8697D36815BF1985C"
+ + "EFDF7AE112E5BB81E37ECF0616CE7147"
+ + "FC08A93A367E08631F23C03B00A8DA2F";
+
+ String set1v0_448 = "B375703739DACED4DD4059FD71C3C47F"
+ + "C2F9939670FAD4A46066ADCC6A564578"
+ + "3308B90FFB72BE04A6B147CBE38CC0C3"
+ + "B9267C296A92A7C69873F9F263BE9703";
+
+ String set1v9_0 = "0471076057830FB99202291177FBFE5D"
+ + "38C888944DF8917CAB82788B91B53D1C"
+ + "FB06D07A304B18BB763F888A61BB6B75"
+ + "5CD58BEC9C4CFB7569CB91862E79C459";
+
+ String set1v9_192 = "D1D7E97556426E6CFC21312AE3811425"
+ + "9E5A6FB10DACBD88E4354B0472556935"
+ + "2B6DA5ACAFACD5E266F9575C2ED8E6F2"
+ + "EFE4B4D36114C3A623DD49F4794F865B";
+
+ String set1v9_256 = "AF06FAA82C73291231E1BD916A773DE1"
+ + "52FD2126C40A10C3A6EB40F22834B8CC"
+ + "68BD5C6DBD7FC1EC8F34165C517C0B63"
+ + "9DB0C60506D3606906B8463AA0D0EC2F";
+
+ String set1v9_448 = "AB3216F1216379EFD5EC589510B8FD35"
+ + "014D0AA0B613040BAE63ECAB90A9AF79"
+ + "661F8DA2F853A5204B0F8E72E9D9EB4D"
+ + "BA5A4690E73A4D25F61EE7295215140C";
+
+ String set6v0_0 = "F5FAD53F79F9DF58C4AEA0D0ED9A9601"
+ + "F278112CA7180D565B420A48019670EA"
+ + "F24CE493A86263F677B46ACE1924773D"
+ + "2BB25571E1AA8593758FC382B1280B71";
+
+ String set6v0_65472 = "B70C50139C63332EF6E77AC54338A407"
+ + "9B82BEC9F9A403DFEA821B83F7860791"
+ + "650EF1B2489D0590B1DE772EEDA4E3BC"
+ + "D60FA7CE9CD623D9D2FD5758B8653E70";
+
+ String set6v0_65536 = "81582C65D7562B80AEC2F1A673A9D01C"
+ + "9F892A23D4919F6AB47B9154E08E699B"
+ + "4117D7C666477B60F8391481682F5D95"
+ + "D96623DBC489D88DAA6956B9F0646B6E";
+
+ String set6v1_0 = "3944F6DC9F85B128083879FDF190F7DE"
+ + "E4053A07BC09896D51D0690BD4DA4AC1"
+ + "062F1E47D3D0716F80A9B4D85E6D6085"
+ + "EE06947601C85F1A27A2F76E45A6AA87";
+
+ String set6v1_65472 = "36E03B4B54B0B2E04D069E690082C8C5"
+ + "92DF56E633F5D8C7682A02A65ECD1371"
+ + "8CA4352AACCB0DA20ED6BBBA62E177F2"
+ + "10E3560E63BB822C4158CAA806A88C82";
+
+ String set6v1_65536 = "1B779E7A917C8C26039FFB23CF0EF8E0"
+ + "8A1A13B43ACDD9402CF5DF38501098DF"
+ + "C945A6CC69A6A17367BC03431A86B3ED"
+ + "04B0245B56379BF997E25800AD837D7D";
+
+ // Salsa20/12
+ String salsa12_set1v0_0 = "FC207DBFC76C5E1774961E7A5AAD0906"
+ + "9B2225AC1CE0FE7A0CE77003E7E5BDF8"
+ + "B31AF821000813E6C56B8C1771D6EE70"
+ + "39B2FBD0A68E8AD70A3944B677937897";
+
+ String salsa12_set1v0_192 = "4B62A4881FA1AF9560586510D5527ED4"
+ + "8A51ECAFA4DECEEBBDDC10E9918D44AB"
+ + "26B10C0A31ED242F146C72940C6E9C37"
+ + "53F641DA84E9F68B4F9E76B6C48CA5AC";
+
+ String salsa12_set1v0_256 = "F52383D9DEFB20810325F7AEC9EADE34"
+ + "D9D883FEE37E05F74BF40875B2D0BE79"
+ + "ED8886E5BFF556CEA8D1D9E86B1F68A9"
+ + "64598C34F177F8163E271B8D2FEB5996";
+
+ String salsa12_set1v0_448 = "A52ED8C37014B10EC0AA8E05B5CEEE12"
+ + "3A1017557FB3B15C53E6C5EA8300BF74"
+ + "264A73B5315DC821AD2CAB0F3BB2F152"
+ + "BDAEA3AEE97BA04B8E72A7B40DCC6BA4";
+
+ // Salsa20/8
+ String salsa8_set1v0_0 = "A9C9F888AB552A2D1BBFF9F36BEBEB33"
+ + "7A8B4B107C75B63BAE26CB9A235BBA9D"
+ + "784F38BEFC3ADF4CD3E266687EA7B9F0"
+ + "9BA650AE81EAC6063AE31FF12218DDC5";
+
+ String salsa8_set1v0_192 = "BB5B6BB2CC8B8A0222DCCC1753ED4AEB"
+ + "23377ACCBD5D4C0B69A8A03BB115EF71"
+ + "871BC10559080ACA7C68F0DEF32A80DD"
+ + "BAF497259BB76A3853A7183B51CC4B9F";
+
+ String salsa8_set1v0_256 = "4436CDC0BE39559F5E5A6B79FBDB2CAE"
+ + "4782910F27FFC2391E05CFC78D601AD8"
+ + "CD7D87B074169361D997D1BED9729C0D"
+ + "EB23418E0646B7997C06AA84E7640CE3";
+
+ String salsa8_set1v0_448 = "BEE85903BEA506B05FC04795836FAAAC"
+ + "7F93F785D473EB762576D96B4A65FFE4"
+ + "63B34AAE696777FC6351B67C3753B89B"
+ + "A6B197BD655D1D9CA86E067F4D770220";
+
+
+ public String getName()
+ {
+ return "Salsa20";
+ }
+
+ public void performTest()
+ {
+ salsa20Test1(20, new ParametersWithIV(new KeyParameter(Hex.decode("80000000000000000000000000000000")), Hex.decode("0000000000000000")),
+ set1v0_0, set1v0_192, set1v0_256, set1v0_448);
+ salsa20Test1(20, new ParametersWithIV(new KeyParameter(Hex.decode("00400000000000000000000000000000")), Hex.decode("0000000000000000")),
+ set1v9_0, set1v9_192, set1v9_256, set1v9_448);
+ salsa20Test1(12, new ParametersWithIV(new KeyParameter(Hex.decode("80000000000000000000000000000000")), Hex.decode("0000000000000000")),
+ salsa12_set1v0_0, salsa12_set1v0_192, salsa12_set1v0_256, salsa12_set1v0_448);
+ salsa20Test1(8, new ParametersWithIV(new KeyParameter(Hex.decode("80000000000000000000000000000000")), Hex.decode("0000000000000000")),
+ salsa8_set1v0_0, salsa8_set1v0_192, salsa8_set1v0_256, salsa8_set1v0_448);
+ salsa20Test2(new ParametersWithIV(new KeyParameter(Hex.decode("0053A6F94C9FF24598EB3E91E4378ADD3083D6297CCF2275C81B6EC11467BA0D")), Hex.decode("0D74DB42A91077DE")),
+ set6v0_0, set6v0_65472, set6v0_65536);
+ salsa20Test2(new ParametersWithIV(new KeyParameter(Hex.decode("0558ABFE51A4F74A9DF04396E93C8FE23588DB2E81D4277ACD2073C6196CBF12")), Hex.decode("167DE44BB21980E7")),
+ set6v1_0, set6v1_65472, set6v1_65536);
+ reinitBug();
+ skipTest();
+ }
+
+ private void salsa20Test1(int rounds, CipherParameters params, String v0, String v192, String v256, String v448)
+ {
+ StreamCipher salsa = new Salsa20Engine(rounds);
+ byte[] buf = new byte[64];
+
+ salsa.init(true, params);
+
+ for (int i = 0; i != 7; i++)
+ {
+ salsa.processBytes(zeroes, 0, 64, buf, 0);
+ switch (i)
+ {
+ case 0:
+ if (!areEqual(buf, Hex.decode(v0)))
+ {
+ mismatch("v0/" + rounds, v0, buf);
+ }
+ break;
+ case 3:
+ if (!areEqual(buf, Hex.decode(v192)))
+ {
+ mismatch("v192/" + rounds, v192, buf);
+ }
+ break;
+ case 4:
+ if (!areEqual(buf, Hex.decode(v256)))
+ {
+ mismatch("v256/" + rounds, v256, buf);
+ }
+ break;
+ default:
+ // ignore
+ }
+ }
+
+ for (int i = 0; i != 64; i++)
+ {
+ buf[i] = salsa.returnByte(zeroes[i]);
+ }
+
+ if (!areEqual(buf, Hex.decode(v448)))
+ {
+ mismatch("v448", v448, buf);
+ }
+ }
+
+ private void salsa20Test2(CipherParameters params, String v0, String v65472, String v65536)
+ {
+ StreamCipher salsa = new Salsa20Engine();
+ byte[] buf = new byte[64];
+
+ salsa.init(true, params);
+
+ for (int i = 0; i != 1025; i++)
+ {
+ salsa.processBytes(zeroes, 0, 64, buf, 0);
+ switch (i)
+ {
+ case 0:
+ if (!areEqual(buf, Hex.decode(v0)))
+ {
+ mismatch("v0", v0, buf);
+ }
+ break;
+ case 1023:
+ if (!areEqual(buf, Hex.decode(v65472)))
+ {
+ mismatch("v65472", v65472, buf);
+ }
+ break;
+ case 1024:
+ if (!areEqual(buf, Hex.decode(v65536)))
+ {
+ mismatch("v65536", v65536, buf);
+ }
+ break;
+ default:
+ // ignore
+ }
+ }
+ }
+
+ private void mismatch(String name, String expected, byte[] found)
+ {
+ fail("mismatch on " + name, expected, new String(Hex.encode(found)));
+ }
+
+
+ private void reinitBug()
+ {
+ KeyParameter key = new KeyParameter(Hex.decode("80000000000000000000000000000000"));
+ ParametersWithIV parameters = new ParametersWithIV(key, Hex.decode("0000000000000000"));
+
+ StreamCipher salsa = new Salsa20Engine();
+
+ salsa.init(true, parameters);
+
+ try
+ {
+ salsa.init(true, key);
+ fail("Salsa20 should throw exception if no IV in Init");
+ }
+ catch (IllegalArgumentException e)
+ {
+ }
+ }
+
+ private boolean areEqual(byte[] a, int aOff, byte[] b, int bOff)
+ {
+ for (int i = bOff; i != b.length; i++)
+ {
+ if (a[aOff + i - bOff] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private void skipTest()
+ {
+ SecureRandom rand = new SecureRandom();
+ byte[] plain = new byte[5000];
+ byte[] cipher = new byte[5000];
+
+ rand.nextBytes(plain);
+
+ CipherParameters params = new ParametersWithIV(new KeyParameter(Hex.decode("0053A6F94C9FF24598EB3E91E4378ADD3083D6297CCF2275C81B6EC11467BA0D")), Hex.decode("0D74DB42A91077DE"));
+ Salsa20Engine engine = new Salsa20Engine();
+
+ engine.init(true, params);
+
+ engine.processBytes(plain, 0, plain.length, cipher, 0);
+
+ byte[] fragment = new byte[20];
+
+ engine.init(true, params);
+
+ engine.skip(10);
+
+ engine.processBytes(plain, 10, fragment.length, fragment, 0);
+
+ if (!areEqual(cipher, 10, fragment, 0))
+ {
+ fail("skip forward 10 failed");
+ }
+
+ engine.skip(1000);
+
+ engine.processBytes(plain, 1010 + fragment.length, fragment.length, fragment, 0);
+
+ if (!areEqual(cipher, 1010 + fragment.length, fragment, 0))
+ {
+ fail("skip forward 1000 failed");
+ }
+
+ engine.skip(-10);
+
+ engine.processBytes(plain, 1010 + 2 * fragment.length - 10, fragment.length, fragment, 0);
+
+ if (!areEqual(cipher, 1010 + 2 * fragment.length - 10, fragment, 0))
+ {
+ fail("skip back 10 failed");
+ }
+
+ engine.skip(-1000);
+
+ if (engine.getPosition() != 60)
+ {
+ fail("skip position incorrect - " + 60 + " got " + engine.getPosition());
+ }
+
+ engine.processBytes(plain, 60, fragment.length, fragment, 0);
+
+ if (!areEqual(cipher, 60, fragment, 0))
+ {
+ fail("skip back 1000 failed");
+ }
+
+ long pos = engine.seekTo(1010);
+ if (pos != 1010)
+ {
+ fail("position wrong");
+ }
+
+ engine.processBytes(plain, 1010, fragment.length, fragment, 0);
+
+ if (!areEqual(cipher, 1010, fragment, 0))
+ {
+ fail("seek to 1010 failed");
+ }
+
+ engine.reset();
+
+ for (int i = 0; i != 1000; i++)
+ {
+ engine.skip(i);
+
+ if (engine.getPosition() != i)
+ {
+ fail("skip forward at wrong position");
+ }
+
+ engine.processBytes(plain, i, fragment.length, fragment, 0);
+
+ if (!areEqual(cipher, i, fragment, 0))
+ {
+ fail("skip forward i failed: " + i);
+ }
+
+ if (engine.getPosition() != i + fragment.length)
+ {
+ fail("cipher at wrong position: " + engine.getPosition() + " [" + i + "]");
+ }
+
+ engine.skip(-fragment.length);
+
+ if (engine.getPosition() != i)
+ {
+ fail("skip back at wrong position");
+ }
+
+ engine.processBytes(plain, i, fragment.length, fragment, 0);
+
+ if (!areEqual(cipher, i, fragment, 0))
+ {
+ fail("skip back i failed: " + i);
+ }
+
+ engine.reset();
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new Salsa20Test());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/SerpentTest.java b/core/src/test/java/org/spongycastle/crypto/test/SerpentTest.java
new file mode 100644
index 00000000..bf687980
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/SerpentTest.java
@@ -0,0 +1,103 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.engines.SerpentEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ */
+public class SerpentTest
+ extends CipherTest
+{
+ static SimpleTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new SerpentEngine(),
+ new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
+ "00000000000000000000000000000000", "8910494504181950f98dd998a82b6749"),
+ new BlockCipherVectorTest(1, new SerpentEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000")),
+ "80000000000000000000000000000000", "10b5ffb720b8cb9002a1142b0ba2e94a"),
+ new BlockCipherVectorTest(2, new SerpentEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000")),
+ "00000000008000000000000000000000", "4f057a42d8d5bd9746e434680ddcd5e5"),
+ new BlockCipherVectorTest(3, new SerpentEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000")),
+ "00000000000000000000400000000000", "99407bf8582ef12550886ef5b6f169b9"),
+ new BlockCipherVectorTest(4, new SerpentEngine(),
+ new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
+ "40000000000000000000000000000000", "d522a3b8d6d89d4d2a124fdd88f36896"),
+ new BlockCipherVectorTest(5, new SerpentEngine(),
+ new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
+ "00000000000200000000000000000000", "189b8ec3470085b3da97e82ca8964e32"),
+ new BlockCipherVectorTest(6, new SerpentEngine(),
+ new KeyParameter(Hex.decode("000000000000000000000000000000000000000000000000")),
+ "00000000000000000000008000000000", "f77d868cf760b9143a89809510ccb099"),
+ new BlockCipherVectorTest(7, new SerpentEngine(),
+ new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
+ "08000000000000000000000000000000", "d43b7b981b829342fce0e3ec6f5f4c82"),
+ new BlockCipherVectorTest(8, new SerpentEngine(),
+ new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
+ "00000000000000000100000000000000", "0bf30e1a0c33ccf6d5293177886912a7"),
+ new BlockCipherVectorTest(9, new SerpentEngine(),
+ new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000000000000")),
+ "00000000000000000000000000000001", "6a7f3b805d2ddcba49b89770ade5e507"),
+ new BlockCipherVectorTest(10, new SerpentEngine(),
+ new KeyParameter(Hex.decode("80000000000000000000000000000000")),
+ "00000000000000000000000000000000", "49afbfad9d5a34052cd8ffa5986bd2dd"),
+ new BlockCipherVectorTest(11, new SerpentEngine(),
+ new KeyParameter(Hex.decode("000000000000000000000000004000000000000000000000")),
+ "00000000000000000000000000000000", "ba8829b1de058c4b48615d851fc74f17"),
+ new BlockCipherVectorTest(12, new SerpentEngine(),
+ new KeyParameter(Hex.decode("0000000000000000000000000000000000000000000000000000000100000000")),
+ "00000000000000000000000000000000", "89f64377bf1e8a46c8247044e8056a98"),
+/*
+ new BlockCipherMonteCarloTest(13, 10000, new SerpentEngine(),
+ new KeyParameter(Hex.decode("47f5f881daab9b67b43bd1342e339c19")),
+ "7a4f7db38c52a8b711b778a38d203b6b", "003380e19f10065740394f48e2fe80b7"),
+*/
+ new BlockCipherMonteCarloTest(13, 100, new SerpentEngine(),
+ new KeyParameter(Hex.decode("47f5f881daab9b67b43bd1342e339c19")),
+ "7a4f7db38c52a8b711b778a38d203b6b", "4db75303d815c2f7cc6ca935d1c5a046"),
+/*
+ new BlockCipherMonteCarloTest(14, 10000, new SerpentEngine(),
+ new KeyParameter(Hex.decode("31fba879ebc5e80df35e6fa33eaf92d6")),
+ "70a05e12f74589009692a337f53ff614", "afb5425426906db26b70bdf842ac5400"),
+*/
+ new BlockCipherMonteCarloTest(14, 100, new SerpentEngine(),
+ new KeyParameter(Hex.decode("31fba879ebc5e80df35e6fa33eaf92d6")),
+ "70a05e12f74589009692a337f53ff614", "fc53a50f4d3bc9836001893d2f41742d"),
+/*
+ new BlockCipherMonteCarloTest(15, 10000, new SerpentEngine(),
+ new KeyParameter(Hex.decode("bde6dd392307984695aee80e574f9977caae9aa78eda53e8")),
+ "9cc523d034a93740a0aa4e2054bb34d8", "1949d506ada7de1f1344986e8ea049b2"),
+*/
+ new BlockCipherMonteCarloTest(15, 100, new SerpentEngine(),
+ new KeyParameter(Hex.decode("bde6dd392307984695aee80e574f9977caae9aa78eda53e8")),
+ "9cc523d034a93740a0aa4e2054bb34d8", "77117e6a9e80f40b2a36b7d755573c2d"),
+/*
+ new BlockCipherMonteCarloTest(16, 10000, new SerpentEngine(),
+ new KeyParameter(Hex.decode("60f6f8ad4290699dc50921a1bbcca92da914e7d9cf01a9317c79c0af8f2487a1")),
+ "ee1a61106fae2d381d686cbf854bab65", "e57f45559027cb1f2ed9603d814e1c34"),
+*/
+ new BlockCipherMonteCarloTest(16, 100, new SerpentEngine(),
+ new KeyParameter(Hex.decode("60f6f8ad4290699dc50921a1bbcca92da914e7d9cf01a9317c79c0af8f2487a1")),
+ "ee1a61106fae2d381d686cbf854bab65", "dcd7f13ea0dcdfd0139d1a42e2ffb84b")
+ };
+
+ SerpentTest()
+ {
+ super(tests, new SerpentEngine(), new KeyParameter(new byte[32]));
+ }
+
+ public String getName()
+ {
+ return "Serpent";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new SerpentTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/Shacal2Test.java b/core/src/test/java/org/spongycastle/crypto/test/Shacal2Test.java
new file mode 100644
index 00000000..5ffd9473
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/Shacal2Test.java
@@ -0,0 +1,200 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.engines.Shacal2Engine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * Shacal2 tester - vectors from https://www.cosic.esat.kuleuven.be/nessie/testvectors/
+ */
+public class Shacal2Test
+ extends CipherTest
+{
+ static SimpleTest[] tests =
+ {
+ // set 8.0
+ new BlockCipherVectorTest(0, new Shacal2Engine(),
+ new KeyParameter(Hex.decode("000102030405060708090A0B0C0D0E0F" +
+ "101112131415161718191A1B1C1D1E1F" +
+ "202122232425262728292A2B2C2D2E2F" +
+ "303132333435363738393A3B3C3D3E3F")),
+ "98BCC10405AB0BFC686BECECAAD01AC1" +
+ "9B452511BCEB9CB094F905C51CA45430",
+ "00112233445566778899AABBCCDDEEFF" +
+ "102132435465768798A9BACBDCEDFE0F"),
+ // set 8.1
+ new BlockCipherVectorTest(1, new Shacal2Engine(),
+ new KeyParameter(Hex.decode("2BD6459F82C5B300952C49104881FF48" +
+ "2BD6459F82C5B300952C49104881FF48" +
+ "2BD6459F82C5B300952C49104881FF48" +
+ "2BD6459F82C5B300952C49104881FF48")),
+ "481F122A75F2C4C3395140B5A951EBBA" +
+ "06D96BDFD9D8FF4FB59CBD1287808D5A",
+ "EA024714AD5C4D84EA024714AD5C4D84" +
+ "EA024714AD5C4D84EA024714AD5C4D84"),
+ // 7.255
+ new BlockCipherVectorTest(2, new Shacal2Engine(),
+ new KeyParameter(Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")),
+ "94FEDFF2A0CFE3C983D340C88D73F8CF" +
+ "4B79FC581797EC10B27D4DA1B51E1BC7",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"),
+ // 7.100
+ new BlockCipherVectorTest(3, new Shacal2Engine(),
+ new KeyParameter(Hex.decode("64646464646464646464646464646464" +
+ "64646464646464646464646464646464" +
+ "64646464646464646464646464646464" +
+ "64646464646464646464646464646464")),
+ "6643CB84B3B3F126F5E50959EF4CE73D" +
+ "B8500918ABE1056368DB06CA8C1C0D45",
+ "64646464646464646464646464646464" +
+ "64646464646464646464646464646464"),
+ // 7.50
+ new BlockCipherVectorTest(4, new Shacal2Engine(),
+ new KeyParameter(Hex.decode("32323232323232323232323232323232" +
+ "32323232323232323232323232323232" +
+ "32323232323232323232323232323232" +
+ "32323232323232323232323232323232")),
+ "92E937285AB11FE3561542C43C918966" +
+ "971DE722E9B9D38BD69EAC77899DCF81",
+ "32323232323232323232323232323232" +
+ "32323232323232323232323232323232"),
+ // 7.0
+ new BlockCipherVectorTest(5, new Shacal2Engine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000" +
+ "00000000000000000000000000000000" +
+ "00000000000000000000000000000000" +
+ "00000000000000000000000000000000")),
+ "F8C9259FA4F5D787B570AFA9219166A6" +
+ "3636FC5C30AC289155D0CC4FFCB4B03D",
+ "00000000000000000000000000000000" +
+ "00000000000000000000000000000000"),
+ // 6.255
+ new BlockCipherVectorTest(6, new Shacal2Engine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000" +
+ "00000000000000000000000000000000" +
+ "00000000000000000000000000000000" +
+ "00000000000000000000000000000000")),
+ "F4E976DF0172CD961D4C8D466A12F676" +
+ "5B9089046E747CD2A41BF43C18A8328E",
+ "00000000000000000000000000000000" +
+ "00000000000000000000000000000001"),
+ // 6.100
+ new BlockCipherVectorTest(7, new Shacal2Engine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000" +
+ "00000000000000000000000000000000" +
+ "00000000000000000000000000000000" +
+ "00000000000000000000000000000000")),
+ "3B929F0597E21D0076EC399D21B67713" +
+ "B40E3AD559704219A26A3380212D5AD6",
+ "00000000000000000000000008000000" +
+ "00000000000000000000000000000000"),
+
+ // 6.0
+ new BlockCipherVectorTest(8, new Shacal2Engine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000" +
+ "00000000000000000000000000000000" +
+ "00000000000000000000000000000000" +
+ "00000000000000000000000000000000")),
+ "43A0DAD8307F19FBBCF166FE20BAC075" +
+ "C56FF14042550E472094B042BE5963EE",
+ "80000000000000000000000000000000" +
+ "00000000000000000000000000000000"),
+ };
+
+ Shacal2Test()
+ {
+ super(tests, new Shacal2Engine(), new KeyParameter(new byte[16]));
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ super.performTest();
+
+ // 1.0
+ iteratedTest(0,
+ Hex.decode("80000000000000000000000000000000" +
+ "00000000000000000000000000000000" +
+ "00000000000000000000000000000000" +
+ "00000000000000000000000000000000"),
+ Hex.decode("00000000000000000000000000000000" +
+ "00000000000000000000000000000000"),
+ Hex.decode("361AB6322FA9E7A7BB23818D839E01BD" +
+ "DAFDF47305426EDD297AEDB9F6202BAE"),
+ Hex.decode("226A582DE04383D0F3E7DE655DD848AC" +
+ "3E14CCFB4E76F7B7069879F67C4D5420"),
+ Hex.decode("B05D5A18C0712082CFF5BA9DBBCD7269" +
+ "114FC3DF83B42DAC306D95BBC473D839"));
+
+ // 1.100
+ iteratedTest(1,
+ Hex.decode("00000000000000000000000008000000" +
+ "00000000000000000000000000000000" +
+ "00000000000000000000000000000000" +
+ "00000000000000000000000000000000"),
+ Hex.decode("00000000000000000000000000000000" +
+ "00000000000000000000000000000000"),
+ Hex.decode("F703282E54592A5617E10618027BB67F" +
+ "639E43A90767150D8B7F5E83054B3CBD"),
+ Hex.decode("3B442692B579485B8BA2F92CE3B90DE7" +
+ "D2EA03D8B3C8E7BE7BF6415F798EED90"),
+ Hex.decode("331B9B65F06230380BBEECFBFBA94BCF" +
+ "92AF6341F815D7651F996144A5377263"));
+ }
+
+ private void iteratedTest(int index, byte[] key, byte[] plain, byte[] cipher, byte[] cipher100, byte[] cipher1000)
+ {
+ BlockCipher engine = new Shacal2Engine();
+
+ engine.init(true, new KeyParameter(key));
+
+ byte[] buf = new byte[plain.length];
+
+ System.arraycopy(plain, 0, buf, 0, plain.length);
+
+ engine.processBlock(buf, 0, buf, 0);
+
+ if (!Arrays.areEqual(cipher, buf))
+ {
+ fail(index + " single count failed");
+ }
+
+ for (int i = 1; i != 100; i++)
+ {
+ engine.processBlock(buf, 0, buf, 0);
+ }
+
+ if (!Arrays.areEqual(cipher100, buf))
+ {
+ fail(index + " 100 count failed");
+ }
+
+ for (int i = 100; i != 1000; i++)
+ {
+ engine.processBlock(buf, 0, buf, 0);
+ }
+
+ if (!Arrays.areEqual(cipher1000, buf))
+ {
+ fail(index + " 1000 count failed");
+ }
+ }
+
+ public String getName()
+ {
+ return "Shacal2";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new Shacal2Test());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/ShortenedDigestTest.java b/core/src/test/java/org/spongycastle/crypto/test/ShortenedDigestTest.java
new file mode 100644
index 00000000..58b70149
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/ShortenedDigestTest.java
@@ -0,0 +1,89 @@
+/*
+ * Created on 6/05/2006
+ *
+ * To change the template for this generated file go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+ */
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.ExtendedDigest;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA512Digest;
+import org.spongycastle.crypto.digests.ShortenedDigest;
+import org.spongycastle.util.test.SimpleTest;
+
+public class ShortenedDigestTest
+ extends SimpleTest
+{
+ public void performTest()
+ {
+ ExtendedDigest d = new SHA1Digest();
+ ShortenedDigest sd = new ShortenedDigest(new SHA1Digest(), 10);
+
+ if (sd.getDigestSize() != 10)
+ {
+ fail("size check wrong for SHA-1");
+ }
+
+ if (sd.getByteLength() != d.getByteLength())
+ {
+ fail("byte length check wrong for SHA-1");
+ }
+
+ //
+ // check output fits
+ //
+ sd.doFinal(new byte[10], 0);
+
+ d = new SHA512Digest();
+ sd = new ShortenedDigest(new SHA512Digest(), 20);
+
+ if (sd.getDigestSize() != 20)
+ {
+ fail("size check wrong for SHA-512");
+ }
+
+ if (sd.getByteLength() != d.getByteLength())
+ {
+ fail("byte length check wrong for SHA-512");
+ }
+
+ //
+ // check output fits
+ //
+ sd.doFinal(new byte[20], 0);
+
+ try
+ {
+ new ShortenedDigest(null, 20);
+
+ fail("null parameter not caught");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+
+ try
+ {
+ new ShortenedDigest(new SHA1Digest(), 50);
+
+ fail("short digest not caught");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ public String getName()
+ {
+ return "ShortenedDigest";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new ShortenedDigestTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/SipHashTest.java b/core/src/test/java/org/spongycastle/crypto/test/SipHashTest.java
new file mode 100644
index 00000000..6c6b28e2
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/SipHashTest.java
@@ -0,0 +1,143 @@
+package org.spongycastle.crypto.test;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.macs.SipHash;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Pack;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/*
+ * SipHash test values from "SipHash: a fast short-input PRF", by Jean-Philippe
+ * Aumasson and Daniel J. Bernstein (https://131002.net/siphash/siphash.pdf), Appendix A.
+ */
+public class SipHashTest
+ extends SimpleTest
+{
+ private static final int UPDATE_BYTES = 0;
+ private static final int UPDATE_FULL = 1;
+ private static final int UPDATE_MIX = 2;
+
+ public String getName()
+ {
+ return "SipHash";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ byte[] key = Hex.decode("000102030405060708090a0b0c0d0e0f");
+ byte[] input = Hex.decode("000102030405060708090a0b0c0d0e");
+
+ runMAC(key, input, UPDATE_BYTES);
+ runMAC(key, input, UPDATE_FULL);
+ runMAC(key, input, UPDATE_MIX);
+
+ SecureRandom random = new SecureRandom();
+ for (int i = 0; i < 100; ++i)
+ {
+ randomTest(random);
+ }
+ }
+
+ private void runMAC(byte[] key, byte[] input, int updateType)
+ throws Exception
+ {
+ long expected = 0xa129ca6149be45e5L;
+
+ SipHash mac = new SipHash();
+ mac.init(new KeyParameter(key));
+
+ updateMAC(mac, input, updateType);
+
+ long result = mac.doFinal();
+ if (expected != result)
+ {
+ fail("Result does not match expected value for doFinal()");
+ }
+
+ byte[] expectedBytes = new byte[8];
+ Pack.longToLittleEndian(expected, expectedBytes, 0);
+
+ updateMAC(mac, input, updateType);
+
+ byte[] output = new byte[mac.getMacSize()];
+ int len = mac.doFinal(output, 0);
+ if (len != output.length)
+ {
+ fail("Result length does not equal getMacSize() for doFinal(byte[],int)");
+ }
+ if (!areEqual(expectedBytes, output))
+ {
+ fail("Result does not match expected value for doFinal(byte[],int)");
+ }
+ }
+
+ private void randomTest(SecureRandom random)
+ {
+ byte[] key = new byte[16];
+ random.nextBytes(key);
+
+ int length = 1 + random.nextInt(1024);
+ byte[] input = new byte[length];
+ random.nextBytes(input);
+
+ SipHash mac = new SipHash();
+ mac.init(new KeyParameter(key));
+
+ updateMAC(mac, input, UPDATE_BYTES);
+ long result1 = mac.doFinal();
+
+ updateMAC(mac, input, UPDATE_FULL);
+ long result2 = mac.doFinal();
+
+ updateMAC(mac, input, UPDATE_MIX);
+ long result3 = mac.doFinal();
+
+ if (result1 != result2 || result1 != result3)
+ {
+ fail("Inconsistent results in random test");
+ }
+ }
+
+ private void updateMAC(SipHash mac, byte[] input, int updateType)
+ {
+ switch (updateType)
+ {
+ case UPDATE_BYTES:
+ {
+ for (int i = 0; i < input.length; ++i)
+ {
+ mac.update(input[i]);
+ }
+ break;
+ }
+ case UPDATE_FULL:
+ {
+ mac.update(input, 0, input.length);
+ break;
+ }
+ case UPDATE_MIX:
+ {
+ int step = Math.max(1, input.length / 3);
+ int pos = 0;
+ while (pos < input.length)
+ {
+ mac.update(input[pos++]);
+ int len = Math.min(input.length - pos, step);
+ mac.update(input, pos, len);
+ pos += len;
+ }
+ break;
+ }
+ default:
+ throw new IllegalStateException();
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new SipHashTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/SkeinDigestTest.java b/core/src/test/java/org/spongycastle/crypto/test/SkeinDigestTest.java
new file mode 100644
index 00000000..cb5c8648
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/SkeinDigestTest.java
@@ -0,0 +1,294 @@
+package org.spongycastle.crypto.test;
+
+import java.io.IOException;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SkeinDigest;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Memoable;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class SkeinDigestTest
+ extends SimpleTest
+{
+ private static class Case
+ {
+ private byte[] message;
+ private byte[] digest;
+ private int blockSize;
+ private int outputSize;
+
+ public Case(int blockSize, int outputSize, String message, String digest)
+ {
+ this.blockSize = blockSize;
+ this.outputSize = outputSize;
+ this.message = Hex.decode(message);
+ this.digest = Hex.decode(digest);
+ }
+
+ public int getOutputSize()
+ {
+ return outputSize;
+ }
+
+ public int getBlockSize()
+ {
+ return blockSize;
+ }
+
+ public byte[] getMessage()
+ {
+ return message;
+ }
+
+ public byte[] getDigest()
+ {
+ return digest;
+ }
+
+ }
+
+ // Test cases from skein_golden_kat.txt and skein_golden_kat_short.txt in Skein 1.3 NIST CD
+ private static final Case[] TEST_CASES = {
+ new Case(256, 256, "", "c8877087da56e072870daa843f176e9453115929094c3a40c463a196c29bf7ba"),
+ new Case(256, 256, "fb", "088eb23cc2bccfb8171aa64e966d4af937325167dfcd170700ffd21f8a4cbdac"),
+ new Case(256, 256, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8",
+ "5c3002ff57a627089ea2f97a5000d5678416389019e80e45a3bbcab118315d26"),
+ new Case(256, 256, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a129233",
+ "640c894a4bba6574c83e920ddf7dd2982fc634881bbbcb9d774eae0a285e89ce"),
+ new Case(256, 160, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "0cd491b7715704c3a15a45a1ca8d93f8f646d3a1"),
+ new Case(256, 224, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "afd1e2d0f5b6cd4e1f8b3935fa2497d27ee97e72060adac099543487"),
+ new Case(256, 256, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "4de6fe2bfdaa3717a4261030ef0e044ced9225d066354610842a24a3eafd1dcf"),
+ new Case(256, 384, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "954620fb31e8b782a2794c6542827026fe069d715df04261629fcbe81d7d529b"
+ + "95ba021fa4239fb00afaa75f5fd8e78b"),
+ new Case(256, 512, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "51347e27c7eabba514959f899a6715ef6ad5cf01c23170590e6a8af399470bf9"
+ + "0ea7409960a708c1dbaa90e86389df254abc763639bb8cdf7fb663b29d9557c3"),
+ new Case(256, 1024, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "6c9b6facbaf116b538aa655e0be0168084aa9f1be445f7e06714585e5999a6c9"
+ + "84fffa9d41a316028692d4aad18f573fbf27cf78e84de26da1928382b023987d"
+ + "cfe002b6201ea33713c54a8a5d9eb346f0365e04330d2faaf7bc8aba92a5d7fb"
+ + "6345c6fb26750bce65ab2045c233627679ac6e9acb33602e26fe3526063ecc8b"),
+
+ new Case(512, 512, "", "bc5b4c50925519c290cc634277ae3d6257212395cba733bbad37a4af0fa06af4"
+ + "1fca7903d06564fea7a2d3730dbdb80c1f85562dfcc070334ea4d1d9e72cba7a"),
+ new Case(512, 512, "fb", "c49e03d50b4b2cc46bd3b7ef7014c8a45b016399fd1714467b7596c86de98240"
+ + "e35bf7f9772b7d65465cd4cffab14e6bc154c54fc67b8bc340abf08eff572b9e"),
+ new Case(512, 512, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8",
+ "abefb179d52f68f86941acbbe014cc67ec66ad78b7ba9508eb1400ee2cbdb06f"
+ + "9fe7c2a260a0272d0d80e8ef5e8737c0c6a5f1c02ceb00fb2746f664b85fcef5"),
+ new Case(512, 512, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a129233",
+ "5c5b7956f9d973c0989aa40a71aa9c48a65af2757590e9a758343c7e23ea2df4"
+ + "057ce0b49f9514987feff97f648e1dd065926e2c371a0211ca977c213f14149f"),
+ new Case(512, 160, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "ef03079d61b57c6047e15fa2b35b46fa24279539"),
+ new Case(512, 224, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "d9e3219b214e15246a2038f76a573e018ef69b385b3bd0576b558231"),
+ new Case(512, 256, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "809dd3f763a11af90912bbb92bc0d94361cbadab10142992000c88b4ceb88648"),
+ new Case(512, 384, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "825f5cbd5da8807a7b4d3e7bd9cd089ca3a256bcc064cd73a9355bf3ae67f2bf"
+ + "93ac7074b3b19907a0665ba3a878b262"),
+ new Case(512, 512, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "1a0d5abf4432e7c612d658f8dcfa35b0d1ab68b8d6bd4dd115c23cc57b5c5bcd"
+ + "de9bff0ece4208596e499f211bc07594d0cb6f3c12b0e110174b2a9b4b2cb6a9"),
+
+ new Case(1024, 1024, "", "0fff9563bb3279289227ac77d319b6fff8d7e9f09da1247b72a0a265cd6d2a62"
+ + "645ad547ed8193db48cff847c06494a03f55666d3b47eb4c20456c9373c86297"
+ + "d630d5578ebd34cb40991578f9f52b18003efa35d3da6553ff35db91b81ab890"
+ + "bec1b189b7f52cb2a783ebb7d823d725b0b4a71f6824e88f68f982eefc6d19c6"),
+ new Case(1024, 1024, "fb", "6426bdc57b2771a6ef1b0dd39f8096a9a07554565743ac3de851d28258fcff22"
+ + "9993e11c4e6bebc8b6ecb0ad1b140276081aa390ec3875960336119427827473"
+ + "4770671b79f076771e2cfdaaf5adc9b10cbae43d8e6cd2b1c1f5d6c82dc96618"
+ + "00ddc476f25865b8748253173187d81da971c027d91d32fb390301c2110d2db2"),
+ new Case(1024, 1024, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8",
+ "140e93726ab0b0467c0b8a834ad8cda4d1769d273661902b70db0dcb5ee692ac"
+ + "b3f852d03b11f857850f2428432811309c1dcbe5724f00267ea3667e89fadb4e"
+ + "4911da6b0ba8a7eddf87c1c67152ef0f07b7fead3557318478bdef5ad1e5926d"
+ + "7071fdd4bfa5076d4b3253f8de479ebdf5357676f1641b2f097e9b785e9e528e"),
+ new Case(1024, 1024, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a129233",
+ "31105e1ef042c30b95b16e0f6e6a1a19172bb7d54a0597dd0c711194888efe1d"
+ + "bce82d47416df9577ca387219f06e45cd10964ff36f6711edbbea0e9595b0f66"
+ + "f72b755d70a46857e0aec98561a743d49370d8e572e212811273125f66cc30bf"
+ + "117d3221894c48012bf6e2219de91e064b01523517420a1e00f71c4cc04bab62"),
+ new Case(1024, 160, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "2e6a4cbf2ef05ea9c24b93e8d1de732ddf2739eb"),
+ new Case(1024, 224, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "1d6de19f37f7a3c265440eecb4b9fbd3300bb5ac60895cfc0d4d3c72"),
+ new Case(1024, 256, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "986a4d472b123e8148731a8eac9db23325f0058c4ccbc44a5bb6fe3a8db672d7"),
+ new Case(1024, 384, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "9c3d0648c11f31c18395d5e6c8ebd73f43d189843fc45235e2c35e345e12d62b"
+ + "c21a41f65896ddc6a04969654c2e2ce9"),
+ new Case(1024, 512, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "5d0416f49c2d08dfd40a1446169dc6a1d516e23b8b853be4933513051de8d5c2"
+ + "6baccffb08d3b16516ba3c6ccf3e9a6c78fff6ef955f2dbc56e1459a7cdba9a5"),
+ new Case(1024, 1024, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "96ca81f586c825d0360aef5acaec49ad55289e1797072eee198b64f349ce65b6"
+ + "e6ed804fe38f05135fe769cc56240ddda5098f620865ce4a4278c77fa2ec6bc3"
+ + "1c0f354ca78c7ca81665bfcc5dc54258c3b8310ed421d9157f36c093814d9b25"
+ + "103d83e0ddd89c52d0050e13a64c6140e6388431961685734b1f138fe2243086"),
+
+ };
+
+ public String getName()
+ {
+ return "SkeinDigest";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ runTest(TEST_CASES[7]);
+ for (int i = 0; i < TEST_CASES.length; i++)
+ {
+ Case test = TEST_CASES[i];
+ runTest(test);
+ }
+ }
+
+ private void runTest(Case dc)
+ {
+ SkeinDigest digest = new SkeinDigest(dc.getBlockSize(), dc.getOutputSize());
+
+ byte[] message = dc.getMessage();
+ digest.update(message, 0, message.length);
+
+ byte[] output = new byte[digest.getDigestSize()];
+ digest.doFinal(output, 0);
+
+ if (!Arrays.areEqual(output, dc.getDigest()))
+ {
+ fail(digest.getAlgorithmName() + " message mismatch.\n Message " + new String(Hex.encode(dc.getMessage())),
+ new String(Hex.encode(dc.getDigest())), new String(Hex.encode(output)));
+ }
+
+ // Clone test
+ digest.update(message, 0, message.length / 2);
+
+ // clone the Digest
+ Digest d = new SkeinDigest(digest);
+
+ digest.update(message, message.length / 2, message.length - message.length / 2);
+ digest.doFinal(output, 0);
+
+ if (!areEqual(dc.getDigest(), output))
+ {
+ fail("failing clone vector test", new String(Hex.encode(dc.getDigest())), new String(Hex.encode(output)));
+ }
+
+ d.update(message, message.length / 2, message.length - message.length / 2);
+ d.doFinal(output, 0);
+
+ if (!areEqual(dc.getDigest(), output))
+ {
+ fail("failing second clone vector test", new String(Hex.encode(dc.getDigest())), new String(Hex.encode(output)));
+ }
+
+ //
+ // memo test
+ //
+ Memoable m = (Memoable)digest;
+
+ digest.update(message, 0, message.length / 2);
+
+ // copy the Digest
+ Memoable copy1 = m.copy();
+ Memoable copy2 = copy1.copy();
+
+ digest.update(message, message.length / 2, message.length - message.length / 2);
+ digest.doFinal(output, 0);
+
+ if (!areEqual(dc.getDigest(), output))
+ {
+ fail("failing memo vector test", new String(Hex.encode(dc.getDigest())), new String(Hex.encode(output)));
+ }
+
+ m.reset(copy1);
+
+ digest.update(message, message.length / 2, message.length - message.length / 2);
+ digest.doFinal(output, 0);
+
+ if (!areEqual(dc.getDigest(), output))
+ {
+ fail("failing memo reset vector test", new String(Hex.encode(dc.getDigest())), new String(Hex.encode(output)));
+ }
+
+ Digest md = (Digest)copy2;
+
+ md.update(message, message.length / 2, message.length - message.length / 2);
+ md.doFinal(output, 0);
+
+ if (!areEqual(dc.getDigest(), output))
+ {
+ fail("failing memo copy vector test", new String(Hex.encode(dc.getDigest())), new String(Hex.encode(output)));
+ }
+ }
+
+ public static void main(String[] args)
+ throws IOException
+ {
+ // generateTests();
+ runTest(new SkeinDigestTest());
+ }
+
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/SkeinMacTest.java b/core/src/test/java/org/spongycastle/crypto/test/SkeinMacTest.java
new file mode 100644
index 00000000..3f1c616f
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/SkeinMacTest.java
@@ -0,0 +1,162 @@
+package org.spongycastle.crypto.test;
+
+import java.io.IOException;
+
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.macs.SkeinMac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class SkeinMacTest
+ extends SimpleTest
+{
+ private static class Case
+ {
+ private byte[] message;
+ private byte[] digest;
+ private byte[] key;
+ private int blockSize;
+ private int outputSize;
+
+ public Case(int blockSize, int outputSize, String message, String key, String digest)
+ {
+ this.blockSize = blockSize;
+ this.outputSize = outputSize;
+ this.message = Hex.decode(message);
+ this.key = Hex.decode(key);
+ this.digest = Hex.decode(digest);
+ }
+
+ public int getOutputSize()
+ {
+ return outputSize;
+ }
+
+ public int getBlockSize()
+ {
+ return blockSize;
+ }
+
+ public byte[] getMessage()
+ {
+ return message;
+ }
+
+ public byte[] getKey()
+ {
+ return key;
+ }
+
+ public byte[] getDigest()
+ {
+ return digest;
+ }
+
+ public String toString()
+ {
+ return "new Case(" + blockSize + ", " + outputSize + ", \"" + new String(Hex.encode(message)) + "\", \""
+ + new String(Hex.encode(key)) + "\", \"" + new String(Hex.encode(digest)) + "\"";
+ }
+
+ }
+
+ // Test cases from skein_golden_kat.txt in Skein 1.3 NIST CD
+ // Excludes empty '(none)' key 'random+MAC' tests, which are in effect digest
+ private static final Case[] TEST_CASES = {
+ new Case(256, 256, "", "cb41f1706cde09651203c2d0efbaddf8", "886e4efefc15f06aa298963971d7a25398fffe5681c84db39bd00851f64ae29d"),
+ new Case(256, 256, "d3", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "979422a94e3afaa46664124d4e5e8b9422b1d8baf11c6ae6725992ac72a112ca"),
+ new Case(256, 256, "d3090c72", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "1d658372cbea2f9928493cc47599d6f4ad8ce33536bedfa20b739f07516519d5"),
+ new Case(256, 256, "d3090c72167517f7", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e92", "41ef6b0f0fad81c040284f3b1a91e9c44e4c26a6d7207f3aac4362856ef12aca"),
+ new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "ca8208119b9e4e4057631ab31015cfd256f6763a0a34381633d97f640899b84f"),
+ new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "9e9980fcc16ee082cf164a5147d0e0692aeffe3dcb8d620e2bb542091162e2e9"),
+ new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc235", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "c353a316558ec34f8245dd2f9c2c4961fbc7decc3b69053c103e4b8aaaf20394"),
+ new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdf", "cb41f1706cde09651203c2d0efbaddf8", "b1b8c18188e69a6ecae0b6018e6b638c6a91e6de6881e32a60858468c17b520d"),
+ new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e92", "1dfd2515a412e78852cd81a7f2167711b4ca19b2891c2ea36ba94f8451944793"),
+ new Case(256, 224, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf8", "a097340709b443ed2c0a921f5dcefef3ead65c4f0bcd5f13da54d7ed"),
+ new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "ac1b4fab6561c92d0c487e082daec53e0db4f505e08bf51cae4fd5375e37fc04"),
+ new Case(256, 384, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e92", "96e6cebb23573d0a70ce36a67aa05d2403148093f25c695e1254887cc97f9771d2518413af4286bf2a06b61a53f7fcec"),
+ new Case(256, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "0e95e597e71d6350f20b99c4179f54f43a4722705c06ba765a82cb0a314fe2fe87ef8090063b757e53182706ed18737dadc0da1e1c66518f08334052702c5ed7"),
+ new Case(256, 264, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf8", "064abd4896f460b1953f5a357e7f7c5256e29cdb62b8740d0b52295cfa2ef4c7a2"),
+ new Case(256, 520, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "edf220e43e048603bd16197d59b673b9974de5b8bcf7cb1558a4799f6fd3743eb5fb400cd6129afc0c60e7b741b7e5806f0e0b93eb8429fbc7efa222175a9c80fd"),
+ new Case(256, 1032, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e92", "f3f59fb07399c7b73aae02a8590883cb2fdfde75c55654e71846522301bde48d267169adcc559e038e8c2f28faa552b550d51874055384adea93c036c71a1f0af0c7bcc3bc923738d5307b9da7cb423d4e615c629c4aba71f70d4c9d1fa008176825e51bfa0203445a4083947ec19f6a0fbd082b5b970f2396fb67420639410447"),
+ new Case(256, 2056, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "80eb80d9b8836b32fa576fc84ba08edfbdfd6979123d61914e610a70a372b37f560a10909484f9f4a377c93e29ba681dfe522c41dc83b5ee0567e5370007c7bbe4df0b2b4a25e088f80d72fc30734cdcd76d817b42fbd44dca881019afb25306f19d4e91848778af306517d2072cef72caa327e877c5b6554f83cec3d00877131b47c4d3b557f5a13541c4d5080ee3ce7a658993d083efd0db3496a8752060c3c8552f44b290cabdcc867f691ad605836c08dbd59c9528d885b600b85fdfc8a9d0e636ac3ad8b4295bcb0169e78dc358e77eacc8c4b61bddfa9e5f32d2268a006cfe05c57150fe8e68cabd21cf6cf6035aa1fe4db36c922b765aad0b64e82a2c37"),
+ new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed696e6c9db1e6abea026288954a9c2d5758d7c5db7c9e48aa3d21cae3d977a7c3926066aa393dbd538dd0c30da8916c8757f24c18488014668a2627163a37b261833dc2f8c3c56b1b2e0be21fd3fbdb507b2950b77a6cc02efb393e57419383a920767bca2c972107aa61384542d47cbfb82cfe5c415389d1b0a2d74e2c5da851", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "8f88de68f03cd2f396ccdd49c3a0f4ff15bcda7eb357da9753f6116b124de91d"),
+ new Case(512, 512, "", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "9bd43d2a2fcfa92becb9f69faab3936978f1b865b7e44338fc9c8f16aba949ba340291082834a1fc5aa81649e13d50cd98641a1d0883062bfe2c16d1faa7e3aa"),
+ new Case(512, 512, "d3", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "f0c0a10f031c8fc69cfabcd54154c318b5d6cd95d06b12cf20264402492211ee010d5cecc2dc37fd772afac0596b2bf71e6020ef2dee7c860628b6e643ed9ff6"),
+ new Case(512, 512, "d3090c72167517f7", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "0c1f1921253dd8e5c2d4c5f4099f851042d91147892705829161f5fc64d89785226eb6e187068493ee4c78a4b7c0f55a8cbbb1a5982c2daf638fc6a74b16b0d7"),
+ new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "478d7b6c0cc6e35d9ebbdedf39128e5a36585db6222891692d1747d401de34ce3db6fcbab6c968b7f2620f4a844a2903b547775579993736d2493a75ff6752a1"),
+ new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e59", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "13c170bac1de35e5fb843f65fabecf214a54a6e0458a4ff6ea5df91915468f4efcd371effa8965a9e82c5388d84730490dcf3976af157b8baf550655a5a6ab78"),
+ new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc235", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "a947812529a72fd3b8967ec391b298bee891babc8487a1ec4ea3d88f6b2b5be09ac6a780f30f8e8c3bbb4f18bc302a28f3e87d170ba0f858a8fefe3487478cca"),
+ new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdf", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "7690ba61f10e0bba312980b0212e6a9a51b0e9aadfde7ca535754a706e042335b29172aae29d8bad18efaf92d43e6406f3098e253f41f2931eda5911dc740352"),
+ new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "d10e3ba81855ac087fbf5a3bc1f99b27d05f98ba22441138026225d34a418b93fd9e8dfaf5120757451adabe050d0eb59d271b0fe1bbf04badbcf9ba25a8791b"),
+ new Case(512, 160, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "5670b226156570dff3efe16661ab86eb24982cdf"),
+ new Case(512, 224, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "c41b9ff9753e6c0f8ed88866e320535e927fe4da552c289841a920db"),
+ new Case(512, 384, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "dfbf5c1319a1d9d70efb2f1600fbcf694f935907f31d24a16d6cd2fb2d7855a769681766c0a29da778eed346cd1d740f"),
+ new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "04d8cddb0ad931d54d195899a094684344e902286037272890bce98a41813edc37a3cee190a693fcca613ee30049ce7ec2bdff9613f56778a13f8c28a21d167a"),
+ new Case(512, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "08fca368b3b14ac406676adf37ac9be2dbb8704e694055a0c6331184d4f0070098f23f0963ee29002495771bf56fb4d3d9ff3506abcd80be927379f7880d5d7703919fbf92184f498ac44f47f015ce676eded9165d47d53733f5a27abbc05f45acd98b97cc15ffdced641defd1a5119ef841b452a1b8f94ee69004466ccdc143"),
+ new Case(512, 264, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "669e770ebe7eacc2b64caaf049923ad297a5b37cfa61c283392d81ccfcb9bbbc09"),
+ new Case(512, 1032, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "acc2e03f07f33e9820a6038421089429adcd6a7a83f733beec048c05bf37531a170a5537fcb565c348a70a83217f8be768ff6f95fd2b3d89cb7d8a3dc849505e3710eb4e65a8e7134bbf580d92fe18c9aa987563669b1f014aa5e092519089355534eaa9f0bdc99f6839f54080ffe74623254c906ecb8896b4346c3178a0bc2898"),
+ new Case(512, 2056, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "9f3e082223c43090a4a3ffbdcd469cbabfe0c1399d1edf45a5dfc18f4db5428928a76e979b8d0d5dffec0e6a59ada448c1ffbc06cc80a2006f002adc0c6dbf458563762228dce4381944e460ebebfe06f1237093634625107469a22a189a47f8b025899265d8890a1b39df64552394377e88ba2ad44a8c8d174f884ac8c3ae24ddb0affca5fceb6aa76e09706881e8371774b9b050a69b96ef5e97e81043f8b7e9479e287ab441bacd62caf768a82c8c3e3107be70eb8799a39856fe29842a04e25de0ef9de1b7e65bd0f1f7306835287fc957388e2035b7d22d3aa9c06a9fefbca16f3f60e1c4def89038d918942152a069aa2e0be8ae7475d859031adec84583"),
+ new Case(1024, 1024, "", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc81463134", "bcf37b3459c88959d6b6b58b2bfe142cef60c6f4ec56b0702480d7893a2b0595aa354e87102a788b61996b9cbc1eade7dafbf6581135572c09666d844c90f066b800fc4f5fd1737644894ef7d588afc5c38f5d920bdbd3b738aea3a3267d161ed65284d1f57da73b68817e17e381ca169115152b869c66b812bb9a84275303f0"),
+ new Case(1024, 1024, "d3090c72", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "df0596e5808835a3e304aa27923db05f61dac57c0696a1d19abf188e70aa9dbcc659e9510f7c9a37fbc025bd4e5ea293e78ed7838dd0b08864e8ad40ddb3a88031ebefc21572a89960d1916107a7da7ac0c067e34ec46a86a29ca63fa250bd398eb32ec1ed0f8ac8329f26da018b029e41e2e58d1dfc44de81615e6c987ed9c9"),
+ new Case(1024, 1024, "d3090c72167517f7", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c042eb4187aa1c015a4767032c0bb28f076b66485f51531c12e948f47dbc2cb904a4b75d1e8a6d931dab4a07e0a54d1bb5b55e602141746bd09fb15e8f01a8d74e9e63959cb37336bc1b896ec78da734c15e362db04368fbba280f20a043e0d0941e9f5193e1b360a33c43b266524880125222e648f05f28be34ba3cabfc9c544", "3cfbb79cd88af8ee09c7670bcbab6907a31f80fa31d9d7c9d50826c9568f307a78bd254961398c76b6e338fd9ca5f351059350d30963c3320659b223b991fc46d1307686fe2b4763d9f593c57ad5adbc45caf2ea3dc6090f5a74fa5fa6d9e9838964ea0a2aa216831ab069b00629a1a9b037083403bdb25d3d06a21c430c87dd"),
+ new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e59", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "0a1b960099fc9d653b0fd1f5b6b972fb366907b772cbce5a59b6171d7935506f70c212bd169d68c5cfd8618343611b7eb2e686ff1dc7c03a57e1a55ed10726848161eea903d53b58459be42d95df989c66c2eea4e51cde272c2d8be67bf3bca2aee633777eb8486781eaa060d0f538abd6c93dbd2d1bf66e6f50bfdcac3725a4"),
+ new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "3e0cd7938d71c39ffbb08a6ba7995ade3ad140e2c0c45cdbafb099247e08e4c20b61c1f885ced5ed2f816680925034918236e5807f0eecf3f27e9cfca36675eb75873efa1fb41f17541dc2f7c2469eaecb35cc7ca58e489804caf56f09fb97c9f689c64ad49c6888f86c483e901bd3d25798b394ef93faf9154900f92f31f433"),
+ new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdf", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc81463134", "7266752f7e9aa04bd7d8a1b16030677de6021301f6a62473c76bae2b98bbf8aad73bd00a4b5035f741caf2317ab80e4e97f5c5bbe8acc0e8b424bcb13c7c6740a985801fba54addde8d4f13f69d2bfc98ae104d46a211145217e51d510ea846cec9581d14fda079f775c8b18d66cb31bf7060996ee8a69eee7f107909ce59a97"),
+ new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c042eb4187aa1c015a4767032c0bb28f076b66485f51531c12e948f47dbc2cb904a4b75d1e8a6d931dab4a07e0a54d1bb5b55e602141746bd09fb15e8f01a8d74e9e63959cb37336bc1b896ec78da734c15e362db04368fbba280f20a043e0d0941e9f5193e1b360a33c43b266524880125222e648f05f28be34ba3cabfc9c544", "71f40bf2aa635125ef83c8df0d4e9ea18b73b56be4f45e89b910a7c68d396b65b09d18abc7d1b6de3f53fd5de583e6f22e612dd17b292068af6027daaf8b4cd60acf5bc85044741e9f7a1f423f5827f5e360930a2e71912239af9fc6343604fdcf3f3569854f2bb8d25a81e3b3f5261a02fe8292aaaa50c324101ab2c7a2f349"),
+ new Case(1024, 160, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "17c3c533b27d666da556ae586e641b7a3a0bcc45"),
+ new Case(1024, 224, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc81463134", "6625df9801581009125ea4e5c94ad6f1a2d692c278822ccb6eb67235"),
+ new Case(1024, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "6c5b671c1766f6eecea6d24b641d4a6bf84bba13a1976f8f80b3f30ee2f93de6"),
+ new Case(1024, 384, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c042eb4187aa1c015a4767032c0bb28f076b66485f51531c12e948f47dbc2cb904a4b75d1e8a6d931dab4a07e0a54d1bb5b55e602141746bd09fb15e8f01a8d74e9e63959cb37336bc1b896ec78da734c15e362db04368fbba280f20a043e0d0941e9f5193e1b360a33c43b266524880125222e648f05f28be34ba3cabfc9c544", "98af454d7fa3706dfaafbf58c3f9944868b57f68f493987347a69fce19865febba0407a16b4e82065035651f0b1e0327"),
+ new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "211ac479e9961141da3aac19d320a1dbbbfad55d2dce87e6a345fcd58e36827597378432b482d89bad44dddb13e6ad86e0ee1e0882b4eb0cd6a181e9685e18dd302ebb3aa74502c06254dcadfb2bd45d288f82366b7afc3bc0f6b1a3c2e8f84d37fbedd07a3f8fcff84faf24c53c11da600aaa118e76cfdcb366d0b3f7729dce"),
+ new Case(1024, 264, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc81463134", "dc1d253b7cadbdaef18503b1809a7f1d4f8c323b7f6f8ca50b76d3864649ce1c7d"),
+ new Case(1024, 520, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "decd79578d12bf6806530c382230a2c7836429c70cac941179e1dd982938bab91fb6f3638df1cc1ef615ecfc4249e5aca8a73c4c1eebef662a836d0be903b00146"),
+ new Case(1024, 1032, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c042eb4187aa1c015a4767032c0bb28f076b66485f51531c12e948f47dbc2cb904a4b75d1e8a6d931dab4a07e0a54d1bb5b55e602141746bd09fb15e8f01a8d74e9e63959cb37336bc1b896ec78da734c15e362db04368fbba280f20a043e0d0941e9f5193e1b360a33c43b266524880125222e648f05f28be34ba3cabfc9c544", "440fe691e04f1fed8c253d6c4670646156f33fffaea702de9445df5739eb960cecf85d56e2e6860a610211a5c909932ab774b978aa0b0d5bbce82775172ab12dceddd51d1eb030057ce61bea6c18f6bb368d26ae76a9e44a962eb132e6c42c25d9fecc4f13348300ca55c78e0990de96c1ae24eb3ee3324782c93dd628260a2c8d"),
+ new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed696e6c9db1e6abea026288954a9c2d5758d7c5db7c9e48aa3d21cae3d977a7c3926066aa393dbd538dd0c30da8916c8757f24c18488014668a2627163a37b261833dc2f8c3c56b1b2e0be21fd3fbdb507b2950b77a6cc02efb393e57419383a920767bca2c972107aa61384542d47cbfb82cfe5c415389d1b0a2d74e2c5da851", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "46a42b0d7b8679f8fcea156c072cf9833c468a7d59ac5e5d326957d60dfe1cdfb27eb54c760b9e049fda47f0b847ac68d6b340c02c39d4a18c1bdfece3f405fae8aa848bdbefe3a4c277a095e921228618d3be8bd1999a071682810de748440ad416a97742cc9e8a9b85455b1d76472cf562f525116698d5cd0a35ddf86e7f8a"),
+
+ };
+
+ public String getName()
+ {
+ return "SkeinMac";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ for (int i = 0; i < TEST_CASES.length; i++)
+ {
+ Case test = TEST_CASES[i];
+ runTest(test);
+ }
+ }
+
+ private void runTest(Case dc)
+ {
+ Mac digest = new SkeinMac(dc.getBlockSize(), dc.getOutputSize());
+ digest.init(new KeyParameter(dc.getKey()));
+
+ byte[] message = dc.getMessage();
+ digest.update(message, 0, message.length);
+
+ byte[] output = new byte[digest.getMacSize()];
+ digest.doFinal(output, 0);
+
+ if (!Arrays.areEqual(output, dc.getDigest()))
+ {
+ fail(digest.getAlgorithmName() + " message " + (dc.getMessage().length * 8) + " mismatch.\n Message " + new String(Hex.encode(dc.getMessage()))
+ + "\n Key " + new String(Hex.encode(dc.getKey())) + "\n Expected "
+ + new String(Hex.encode(dc.getDigest())) + "\n Actual " + new String(Hex.encode(output)));
+ }
+
+ }
+
+ public static void main(String[] args)
+ throws IOException
+ {
+ runTest(new SkeinMacTest());
+ }
+
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/SkipjackTest.java b/core/src/test/java/org/spongycastle/crypto/test/SkipjackTest.java
new file mode 100644
index 00000000..e7b2d867
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/SkipjackTest.java
@@ -0,0 +1,35 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.engines.SkipjackEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ */
+public class SkipjackTest
+ extends CipherTest
+{
+ static SimpleTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new SkipjackEngine(),
+ new KeyParameter(Hex.decode("00998877665544332211")),
+ "33221100ddccbbaa", "2587cae27a12d300")
+ };
+
+ SkipjackTest()
+ {
+ super(tests, new SkipjackEngine(), new KeyParameter(Hex.decode("00998877665544332211")));
+ }
+
+ public String getName()
+ {
+ return "SKIPJACK";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new SkipjackTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/StreamCipherResetTest.java b/core/src/test/java/org/spongycastle/crypto/test/StreamCipherResetTest.java
new file mode 100644
index 00000000..7c166ada
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/StreamCipherResetTest.java
@@ -0,0 +1,133 @@
+package org.spongycastle.crypto.test;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.crypto.StreamCipher;
+import org.spongycastle.crypto.engines.ChaChaEngine;
+import org.spongycastle.crypto.engines.Grain128Engine;
+import org.spongycastle.crypto.engines.Grainv1Engine;
+import org.spongycastle.crypto.engines.HC128Engine;
+import org.spongycastle.crypto.engines.HC256Engine;
+import org.spongycastle.crypto.engines.ISAACEngine;
+import org.spongycastle.crypto.engines.RC4Engine;
+import org.spongycastle.crypto.engines.Salsa20Engine;
+import org.spongycastle.crypto.engines.XSalsa20Engine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * Test whether block ciphers implement reset contract on init, encrypt/decrypt and reset.
+ */
+public class StreamCipherResetTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "Stream Cipher Reset";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ testReset(new Salsa20Engine(), new Salsa20Engine(), new ParametersWithIV(new KeyParameter(random(32)),
+ random(8)));
+ testReset(new Salsa20Engine(), new Salsa20Engine(), new ParametersWithIV(new KeyParameter(random(16)),
+ random(8)));
+ testReset(new XSalsa20Engine(), new XSalsa20Engine(), new ParametersWithIV(new KeyParameter(random(32)),
+ random(24)));
+ testReset(new ChaChaEngine(), new ChaChaEngine(), new ParametersWithIV(new KeyParameter(random(32)), random(8)));
+ testReset(new ChaChaEngine(), new ChaChaEngine(), new ParametersWithIV(new KeyParameter(random(16)), random(8)));
+ testReset(new RC4Engine(), new RC4Engine(), new KeyParameter(random(16)));
+ testReset(new ISAACEngine(), new ISAACEngine(), new KeyParameter(random(16)));
+ testReset(new HC128Engine(), new HC128Engine(), new ParametersWithIV(new KeyParameter(random(16)), random(16)));
+ testReset(new HC256Engine(), new HC256Engine(), new ParametersWithIV(new KeyParameter(random(16)), random(16)));
+ testReset(new Grainv1Engine(), new Grainv1Engine(), new ParametersWithIV(new KeyParameter(random(16)),
+ random(8)));
+ testReset(new Grain128Engine(), new Grain128Engine(), new ParametersWithIV(new KeyParameter(random(16)),
+ random(12)));
+ }
+
+ private static final SecureRandom RAND = new SecureRandom();
+
+ private byte[] random(int size)
+ {
+ final byte[] data = new byte[size];
+ RAND.nextBytes(data);
+ return data;
+ }
+
+ private void testReset(StreamCipher cipher1, StreamCipher cipher2, CipherParameters params)
+ throws InvalidCipherTextException
+ {
+ cipher1.init(true, params);
+
+ byte[] plaintext = new byte[1023];
+ byte[] ciphertext = new byte[plaintext.length];
+
+ // Establish baseline answer
+ cipher1.processBytes(plaintext, 0, plaintext.length, ciphertext, 0);
+
+ // Test encryption resets
+ checkReset(cipher1, params, true, plaintext, ciphertext);
+
+ // Test decryption resets with fresh instance
+ cipher2.init(false, params);
+ checkReset(cipher2, params, false, ciphertext, plaintext);
+ }
+
+ private void checkReset(StreamCipher cipher,
+ CipherParameters params,
+ boolean encrypt,
+ byte[] pretext,
+ byte[] posttext)
+ throws InvalidCipherTextException
+ {
+ // Do initial run
+ byte[] output = new byte[posttext.length];
+ cipher.processBytes(pretext, 0, pretext.length, output, 0);
+
+ // Check encrypt resets cipher
+ cipher.init(encrypt, params);
+
+ try
+ {
+ cipher.processBytes(pretext, 0, pretext.length, output, 0);
+ }
+ catch (Exception e)
+ {
+ fail(cipher.getAlgorithmName() + " init did not reset: " + e.getMessage());
+ }
+ if (!Arrays.areEqual(output, posttext))
+ {
+ fail(cipher.getAlgorithmName() + " init did not reset.", new String(Hex.encode(posttext)),
+ new String(Hex.encode(output)));
+ }
+
+ // Check reset resets data
+ cipher.reset();
+
+ try
+ {
+ cipher.processBytes(pretext, 0, pretext.length, output, 0);
+ }
+ catch (Exception e)
+ {
+ fail(cipher.getAlgorithmName() + " reset did not reset: " + e.getMessage());
+ }
+ if (!Arrays.areEqual(output, posttext))
+ {
+ fail(cipher.getAlgorithmName() + " reset did not reset.");
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new StreamCipherResetTest());
+ }
+
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/StreamCipherVectorTest.java b/core/src/test/java/org/spongycastle/crypto/test/StreamCipherVectorTest.java
new file mode 100644
index 00000000..2d3b197d
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/StreamCipherVectorTest.java
@@ -0,0 +1,62 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.StreamCipher;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * a basic test that takes a stream cipher, key parameter, and an input
+ * and output string.
+ */
+public class StreamCipherVectorTest
+ extends SimpleTest
+{
+ int id;
+ StreamCipher cipher;
+ CipherParameters param;
+ byte[] input;
+ byte[] output;
+
+ public StreamCipherVectorTest(
+ int id,
+ StreamCipher cipher,
+ CipherParameters param,
+ String input,
+ String output)
+ {
+ this.id = id;
+ this.cipher = cipher;
+ this.param = param;
+ this.input = Hex.decode(input);
+ this.output = Hex.decode(output);
+ }
+
+ public String getName()
+ {
+ return cipher.getAlgorithmName() + " Vector Test " + id;
+ }
+
+ public void performTest()
+ {
+ cipher.init(true, param);
+
+ byte[] out = new byte[input.length];
+
+ cipher.processBytes(input, 0, input.length, out, 0);
+
+ if (!areEqual(out, output))
+ {
+ fail("failed.", new String(Hex.encode(output)) , new String(Hex.encode(out)));
+ }
+
+ cipher.init(false, param);
+
+ cipher.processBytes(output, 0, output.length, out, 0);
+
+ if (!areEqual(input, out))
+ {
+ fail("failed reversal");
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/TEATest.java b/core/src/test/java/org/spongycastle/crypto/test/TEATest.java
new file mode 100644
index 00000000..a2740600
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/TEATest.java
@@ -0,0 +1,48 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.engines.TEAEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * TEA tester - based on C implementation results from http://www.simonshepherd.supanet.com/tea.htm
+ */
+public class TEATest
+ extends CipherTest
+{
+ static SimpleTest[] tests = {
+ new BlockCipherVectorTest(0, new TEAEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000")),
+ "0000000000000000",
+ "41ea3a0a94baa940"),
+ new BlockCipherVectorTest(1, new TEAEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000")),
+ "0102030405060708",
+ "6a2f9cf3fccf3c55"),
+ new BlockCipherVectorTest(2, new TEAEngine(),
+ new KeyParameter(Hex.decode("0123456712345678234567893456789A")),
+ "0000000000000000",
+ "34e943b0900f5dcb"),
+ new BlockCipherVectorTest(3, new TEAEngine(),
+ new KeyParameter(Hex.decode("0123456712345678234567893456789A")),
+ "0102030405060708",
+ "773dc179878a81c0"),
+ };
+
+ TEATest()
+ {
+ super(tests, new TEAEngine(), new KeyParameter(new byte[16]));
+ }
+
+ public String getName()
+ {
+ return "TEA";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new TEATest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/Threefish1024Test.java b/core/src/test/java/org/spongycastle/crypto/test/Threefish1024Test.java
new file mode 100644
index 00000000..9e087187
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/Threefish1024Test.java
@@ -0,0 +1,60 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.engines.ThreefishEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.TweakableBlockCipherParameters;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class Threefish1024Test
+ extends CipherTest
+{
+ // Test cases from skein_golden_kat_internals.txt in Skein 1.3 NIST CD
+ static SimpleTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024),
+ new TweakableBlockCipherParameters(
+ new KeyParameter(new byte[128]),
+ new byte[16]),
+ "0000000000000000000000000000000000000000000000000000000000000000" +
+ "0000000000000000000000000000000000000000000000000000000000000000" +
+ "0000000000000000000000000000000000000000000000000000000000000000" +
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "f05c3d0a3d05b304f785ddc7d1e036015c8aa76e2f217b06c6e1544c0bc1a90d" +
+ "f0accb9473c24e0fd54fea68057f43329cb454761d6df5cf7b2e9b3614fbd5a2" +
+ "0b2e4760b40603540d82eabc5482c171c832afbe68406bc39500367a592943fa" +
+ "9a5b4a43286ca3c4cf46104b443143d560a4b230488311df4feef7e1dfe8391e"),
+ new BlockCipherVectorTest(1, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024),
+ new TweakableBlockCipherParameters(
+ new KeyParameter(Hex.decode(
+ "101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f" +
+ "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" +
+ "505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f" +
+ "707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f")),
+ Hex.decode("000102030405060708090a0b0c0d0e0f")),
+ "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0" +
+ "dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0" +
+ "bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0afaeadacabaaa9a8a7a6a5a4a3a2a1a0" +
+ "9f9e9d9c9b9a999897969594939291908f8e8d8c8b8a89888786858483828180",
+ "a6654ddbd73cc3b05dd777105aa849bce49372eaaffc5568d254771bab85531c" +
+ "94f780e7ffaae430d5d8af8c70eebbe1760f3b42b737a89cb363490d670314bd" +
+ "8aa41ee63c2e1f45fbd477922f8360b388d6125ea6c7af0ad7056d01796e90c8" +
+ "3313f4150a5716b30ed5f569288ae974ce2b4347926fce57de44512177dd7cde")
+ };
+
+ Threefish1024Test()
+ {
+ super(tests, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024), new KeyParameter(new byte[128]));
+ }
+
+ public String getName()
+ {
+ return "Threefish-1024";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new Threefish1024Test());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/Threefish256Test.java b/core/src/test/java/org/spongycastle/crypto/test/Threefish256Test.java
new file mode 100644
index 00000000..6753c245
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/Threefish256Test.java
@@ -0,0 +1,45 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.engines.ThreefishEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.TweakableBlockCipherParameters;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class Threefish256Test
+ extends CipherTest
+{
+ // Test cases from skein_golden_kat_internals.txt in Skein 1.3 NIST CD
+ static SimpleTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_256),
+ new TweakableBlockCipherParameters(
+ new KeyParameter(new byte[32]),
+ new byte[16]),
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "84da2a1f8beaee947066ae3e3103f1ad536db1f4a1192495116b9f3ce6133fd8"),
+ new BlockCipherVectorTest(1, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_256),
+ new TweakableBlockCipherParameters(
+ new KeyParameter(Hex.decode(
+ "101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f")),
+ Hex.decode("000102030405060708090a0b0c0d0e0f")),
+ "FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0",
+ "e0d091ff0eea8fdfc98192e62ed80ad59d865d08588df476657056b5955e97df")
+ };
+
+ Threefish256Test()
+ {
+ super(tests, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_256), new KeyParameter(new byte[32]));
+ }
+
+ public String getName()
+ {
+ return "Threefish-256";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new Threefish256Test());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/Threefish512Test.java b/core/src/test/java/org/spongycastle/crypto/test/Threefish512Test.java
new file mode 100644
index 00000000..ba5447f4
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/Threefish512Test.java
@@ -0,0 +1,50 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.engines.ThreefishEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.TweakableBlockCipherParameters;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class Threefish512Test
+ extends CipherTest
+{
+ // Test cases from skein_golden_kat_internals.txt in Skein 1.3 NIST CD
+ static SimpleTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512),
+ new TweakableBlockCipherParameters(
+ new KeyParameter(new byte[64]),
+ new byte[16]),
+ "0000000000000000000000000000000000000000000000000000000000000000" +
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "b1a2bbc6ef6025bc40eb3822161f36e375d1bb0aee3186fbd19e47c5d479947b" +
+ "7bc2f8586e35f0cff7e7f03084b0b7b1f1ab3961a580a3e97eb41ea14a6d7bbe"),
+ new BlockCipherVectorTest(1, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512),
+ new TweakableBlockCipherParameters(
+ new KeyParameter(Hex.decode(
+ "101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f" +
+ "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f")),
+ Hex.decode("000102030405060708090a0b0c0d0e0f")),
+ "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0" +
+ "dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0",
+ "e304439626d45a2cb401cad8d636249a6338330eb06d45dd8b36b90e97254779" +
+ "272a0a8d99463504784420ea18c9a725af11dffea10162348927673d5c1caf3d")
+ };
+
+ Threefish512Test()
+ {
+ super(tests, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512), new KeyParameter(new byte[64]));
+ }
+
+ public String getName()
+ {
+ return "Threefish-512";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new Threefish512Test());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/TigerDigestTest.java b/core/src/test/java/org/spongycastle/crypto/test/TigerDigestTest.java
new file mode 100644
index 00000000..b9a40655
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/TigerDigestTest.java
@@ -0,0 +1,59 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.TigerDigest;
+
+/**
+ * Tiger Digest Test
+ */
+public class TigerDigestTest
+ extends DigestTest
+{
+ final static String[] messages = {
+ "",
+ "abc",
+ "Tiger",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvw",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789",
+ "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge, 1996.",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"
+ };
+
+ final static String[] digests = {
+ "3293AC630C13F0245F92BBB1766E16167A4E58492DDE73F3",
+ "2AAB1484E8C158F2BFB8C5FF41B57A525129131C957B5F93",
+ "DD00230799F5009FEC6DEBC838BB6A27DF2B9D6F110C7937",
+ "F71C8583902AFB879EDFE610F82C0D4786A3A534504486B5",
+ "38F41D9D9A710A10C3727AC0DEEAA270727D9F926EC10139",
+ "48CEEB6308B87D46E95D656112CDF18D97915F9765658957",
+ "631ABDD103EB9A3D245B6DFD4D77B257FC7439501D1568DD",
+ "C54034E5B43EB8005848A7E0AE6AAC76E4FF590AE715FD25",
+ "C54034E5B43EB8005848A7E0AE6AAC76E4FF590AE715FD25"
+ };
+
+ final static String hash64k = "FDF4F5B35139F48E710E421BE5AF411DE1A8AAC333F26204";
+
+ TigerDigestTest()
+ {
+ super(new TigerDigest(), messages, digests);
+ }
+
+ public void performTest()
+ {
+ super.performTest();
+
+ sixtyFourKTest(hash64k);
+ }
+
+ protected Digest cloneDigest(Digest digest)
+ {
+ return new TigerDigest((TigerDigest)digest);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new TigerDigestTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/TwofishTest.java b/core/src/test/java/org/spongycastle/crypto/test/TwofishTest.java
new file mode 100644
index 00000000..84f3e7fc
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/TwofishTest.java
@@ -0,0 +1,45 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.engines.TwofishEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class TwofishTest
+ extends CipherTest
+{
+ static String key1 = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
+ static String key2 = "000102030405060708090a0b0c0d0e0f1011121314151617";
+ static String key3 = "000102030405060708090a0b0c0d0e0f";
+
+ static String input = "000102030405060708090A0B0C0D0E0F";
+
+ static SimpleTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new TwofishEngine(),
+ new KeyParameter(Hex.decode(key1)),
+ input, "8ef0272c42db838bcf7b07af0ec30f38"),
+ new BlockCipherVectorTest(1, new TwofishEngine(),
+ new KeyParameter(Hex.decode(key2)),
+ input, "95accc625366547617f8be4373d10cd7"),
+ new BlockCipherVectorTest(2, new TwofishEngine(),
+ new KeyParameter(Hex.decode(key3)),
+ input, "9fb63337151be9c71306d159ea7afaa4")
+ };
+
+ TwofishTest()
+ {
+ super(tests, new TwofishEngine(), new KeyParameter(new byte[32]));
+ }
+
+ public String getName()
+ {
+ return "Twofish";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new TwofishTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/VMPCKSA3Test.java b/core/src/test/java/org/spongycastle/crypto/test/VMPCKSA3Test.java
new file mode 100644
index 00000000..21000db9
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/VMPCKSA3Test.java
@@ -0,0 +1,97 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.engines.VMPCKSA3Engine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * VMPC Test
+ */
+public class VMPCKSA3Test extends SimpleTest
+{
+ private static final byte[] input = new byte[1000000];
+
+ public String getName()
+ {
+ return "VMPC-KSA3";
+ }
+
+ private void checkByte(byte[] array, int position, byte b)
+ {
+ if (array[position] != b)
+ {
+ fail("Fail on position " + position,
+ new String(Hex.encode(new byte[] { b })),
+ new String(Hex.encode(new byte[] { array[position] })));
+ }
+ }
+
+ public void performTest()
+ {
+ byte[] key = Hex.decode("9661410AB797D8A9EB767C21172DF6C7");
+ byte[] iv = Hex.decode("4B5C2F003E67F39557A8D26F3DA2B155");
+ CipherParameters kp = new KeyParameter(key);
+ CipherParameters kpwiv = new ParametersWithIV(kp, iv);
+
+ VMPCKSA3Engine engine = new VMPCKSA3Engine();
+
+ try
+ {
+ engine.init(true, kp);
+ fail("init failed to throw expected exception");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // Expected
+ }
+
+ engine.init(true, kpwiv);
+ checkEngine(engine);
+
+ engine.reset();
+ byte[] output = checkEngine(engine);
+
+ engine.init(false, kpwiv);
+ byte[] recovered = new byte[output.length];
+ engine.processBytes(output, 0, output.length, recovered, 0);
+
+ if (!Arrays.areEqual(input, recovered))
+ {
+ fail("decrypted bytes differ from original bytes");
+ }
+ }
+
+ private byte[] checkEngine(VMPCKSA3Engine engine)
+ {
+ byte[] output = new byte[input.length];
+ engine.processBytes(input, 0, output.length, output, 0);
+
+ checkByte(output, 0, (byte) 0xB6);
+ checkByte(output, 1, (byte) 0xEB);
+ checkByte(output, 2, (byte) 0xAE);
+ checkByte(output, 3, (byte) 0xFE);
+ checkByte(output, 252, (byte) 0x48);
+ checkByte(output, 253, (byte) 0x17);
+ checkByte(output, 254, (byte) 0x24);
+ checkByte(output, 255, (byte) 0x73);
+ checkByte(output, 1020, (byte) 0x1D);
+ checkByte(output, 1021, (byte) 0xAE);
+ checkByte(output, 1022, (byte) 0xC3);
+ checkByte(output, 1023, (byte) 0x5A);
+ checkByte(output, 102396, (byte) 0x1D);
+ checkByte(output, 102397, (byte) 0xA7);
+ checkByte(output, 102398, (byte) 0xE1);
+ checkByte(output, 102399, (byte) 0xDC);
+
+ return output;
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new VMPCKSA3Test());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/VMPCMacTest.java b/core/src/test/java/org/spongycastle/crypto/test/VMPCMacTest.java
new file mode 100644
index 00000000..a8d84029
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/VMPCMacTest.java
@@ -0,0 +1,51 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.macs.VMPCMac;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class VMPCMacTest extends SimpleTest
+{
+ public String getName()
+ {
+ return "VMPC-MAC";
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new VMPCMacTest());
+ }
+
+ static byte[] output1 = Hex.decode("9BDA16E2AD0E284774A3ACBC8835A8326C11FAAD");
+
+ public void performTest() throws Exception
+ {
+ CipherParameters kp = new KeyParameter(
+ Hex.decode("9661410AB797D8A9EB767C21172DF6C7"));
+ CipherParameters kpwiv = new ParametersWithIV(kp,
+ Hex.decode("4B5C2F003E67F39557A8D26F3DA2B155"));
+
+ byte[] m = new byte[256];
+ for (int i = 0; i < 256; i++)
+ {
+ m[i] = (byte) i;
+ }
+
+ VMPCMac mac = new VMPCMac();
+ mac.init(kpwiv);
+
+ mac.update(m, 0, m.length);
+
+ byte[] out = new byte[20];
+ mac.doFinal(out, 0);
+
+ if (!Arrays.areEqual(out, output1))
+ {
+ fail("Fail", new String(Hex.encode(output1)), new String(Hex.encode(out)));
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/VMPCTest.java b/core/src/test/java/org/spongycastle/crypto/test/VMPCTest.java
new file mode 100644
index 00000000..8155ddcc
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/VMPCTest.java
@@ -0,0 +1,97 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.engines.VMPCEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * VMPC Test
+ */
+public class VMPCTest extends SimpleTest
+{
+ private static final byte[] input = new byte[1000000];
+
+ public String getName()
+ {
+ return "VMPC";
+ }
+
+ private void checkByte(byte[] array, int position, byte b)
+ {
+ if (array[position] != b)
+ {
+ fail("Fail on position " + position,
+ new String(Hex.encode(new byte[] { b })),
+ new String(Hex.encode(new byte[] { array[position] })));
+ }
+ }
+
+ public void performTest()
+ {
+ byte[] key = Hex.decode("9661410AB797D8A9EB767C21172DF6C7");
+ byte[] iv = Hex.decode("4B5C2F003E67F39557A8D26F3DA2B155");
+ CipherParameters kp = new KeyParameter(key);
+ CipherParameters kpwiv = new ParametersWithIV(kp, iv);
+
+ VMPCEngine engine = new VMPCEngine();
+
+ try
+ {
+ engine.init(true, kp);
+ fail("init failed to throw expected exception");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // Expected
+ }
+
+ engine.init(true, kpwiv);
+ checkEngine(engine);
+
+ engine.reset();
+ byte[] output = checkEngine(engine);
+
+ engine.init(false, kpwiv);
+ byte[] recovered = new byte[output.length];
+ engine.processBytes(output, 0, output.length, recovered, 0);
+
+ if (!Arrays.areEqual(input, recovered))
+ {
+ fail("decrypted bytes differ from original bytes");
+ }
+ }
+
+ private byte[] checkEngine(VMPCEngine engine)
+ {
+ byte[] output = new byte[input.length];
+ engine.processBytes(input, 0, output.length, output, 0);
+
+ checkByte(output, 0, (byte) 0xA8);
+ checkByte(output, 1, (byte) 0x24);
+ checkByte(output, 2, (byte) 0x79);
+ checkByte(output, 3, (byte) 0xF5);
+ checkByte(output, 252, (byte) 0xB8);
+ checkByte(output, 253, (byte) 0xFC);
+ checkByte(output, 254, (byte) 0x66);
+ checkByte(output, 255, (byte) 0xA4);
+ checkByte(output, 1020, (byte) 0xE0);
+ checkByte(output, 1021, (byte) 0x56);
+ checkByte(output, 1022, (byte) 0x40);
+ checkByte(output, 1023, (byte) 0xA5);
+ checkByte(output, 102396, (byte) 0x81);
+ checkByte(output, 102397, (byte) 0xCA);
+ checkByte(output, 102398, (byte) 0x49);
+ checkByte(output, 102399, (byte) 0x9A);
+
+ return output;
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new VMPCTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/WhirlpoolDigestTest.java b/core/src/test/java/org/spongycastle/crypto/test/WhirlpoolDigestTest.java
new file mode 100644
index 00000000..806f5cc2
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/WhirlpoolDigestTest.java
@@ -0,0 +1,105 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.WhirlpoolDigest;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * ISO vector test for Whirlpool
+ *
+ */
+public class WhirlpoolDigestTest
+ extends DigestTest
+{
+ private static String[] messages =
+ {
+ "",
+ "a",
+ "abc",
+ "message digest",
+ "abcdefghijklmnopqrstuvwxyz",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
+ "abcdbcdecdefdefgefghfghighijhijk"
+ };
+
+ private static String[] digests =
+ {
+ "19FA61D75522A4669B44E39C1D2E1726C530232130D407F89AFEE0964997F7A73E83BE698B288FEBCF88E3E03C4F0757EA8964E59B63D93708B138CC42A66EB3",
+ "8ACA2602792AEC6F11A67206531FB7D7F0DFF59413145E6973C45001D0087B42D11BC645413AEFF63A42391A39145A591A92200D560195E53B478584FDAE231A",
+ "4E2448A4C6F486BB16B6562C73B4020BF3043E3A731BCE721AE1B303D97E6D4C7181EEBDB6C57E277D0E34957114CBD6C797FC9D95D8B582D225292076D4EEF5",
+ "378C84A4126E2DC6E56DCC7458377AAC838D00032230F53CE1F5700C0FFB4D3B8421557659EF55C106B4B52AC5A4AAA692ED920052838F3362E86DBD37A8903E",
+ "F1D754662636FFE92C82EBB9212A484A8D38631EAD4238F5442EE13B8054E41B08BF2A9251C30B6A0B8AAE86177AB4A6F68F673E7207865D5D9819A3DBA4EB3B",
+ "DC37E008CF9EE69BF11F00ED9ABA26901DD7C28CDEC066CC6AF42E40F82F3A1E08EBA26629129D8FB7CB57211B9281A65517CC879D7B962142C65F5A7AF01467",
+ "466EF18BABB0154D25B9D38A6414F5C08784372BCCB204D6549C4AFADB6014294D5BD8DF2A6C44E538CD047B2681A51A2C60481E88C5A20B2C2A80CF3A9A083B",
+ "2A987EA40F917061F5D6F0A0E4644F488A7A5A52DEEE656207C562F988E95C6916BDC8031BC5BE1B7B947639FE050B56939BAAA0ADFF9AE6745B7B181C3BE3FD"
+ };
+
+ WhirlpoolDigestTest()
+ {
+ super(new WhirlpoolDigest(), messages, digests);
+ }
+
+ protected Digest cloneDigest(Digest digest)
+ {
+ return new WhirlpoolDigest((WhirlpoolDigest)digest);
+ }
+
+ private static String _millionAResultVector = "0C99005BEB57EFF50A7CF005560DDF5D29057FD86B20BFD62DECA0F1CCEA4AF51FC15490EDDC47AF32BB2B66C34FF9AD8C6008AD677F77126953B226E4ED8B01";
+
+ private static String _thirtyOneZeros = "3E3F188F8FEBBEB17A933FEAF7FE53A4858D80C915AD6A1418F0318E68D49B4E459223CD414E0FBC8A57578FD755D86E827ABEF4070FC1503E25D99E382F72BA";
+
+ public String getName()
+ {
+ return "Whirlpool";
+ }
+
+ public void performTest()
+ {
+ super.performTest();
+
+ byte[] thirtyOneZeros = new byte[31];
+ performStandardVectorTest("31 zeroes test",
+ thirtyOneZeros, _thirtyOneZeros);
+
+ byte[] millionAInByteArray = new byte[1000000];
+ Arrays.fill(millionAInByteArray, (byte)'a');
+
+ performStandardVectorTest("Million 'a' test",
+ millionAInByteArray, _millionAResultVector);
+ }
+
+ private void performStandardVectorTest(String testTitle, byte[] inputBytes,
+ String resultsAsHex)
+ {
+ doPerformTest(testTitle, inputBytes, resultsAsHex);
+ }
+
+ private void doPerformTest(String testTitle, byte[] inputBytes, String resultsAsHex)
+ {
+ String resStr = createHexOutputFromDigest(inputBytes);
+ if (!resultsAsHex.equals(resStr.toUpperCase()))
+ {
+ fail(testTitle, resultsAsHex, resStr);
+ }
+ }
+
+ private String createHexOutputFromDigest(byte[] digestBytes)
+ {
+ String resStr;
+ Digest digest = new WhirlpoolDigest();
+ byte[] resBuf = new byte[digest.getDigestSize()];
+ digest.update(digestBytes, 0, digestBytes.length);
+ digest.doFinal(resBuf, 0);
+ resStr = new String(Hex.encode(resBuf));
+ return resStr;
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new WhirlpoolDigestTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/XSalsa20Test.java b/core/src/test/java/org/spongycastle/crypto/test/XSalsa20Test.java
new file mode 100644
index 00000000..6c0ab486
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/XSalsa20Test.java
@@ -0,0 +1,166 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.engines.XSalsa20Engine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class XSalsa20Test extends SimpleTest
+{
+ private static class TestCase
+ {
+
+ private byte[] key;
+ private byte[] iv;
+ private byte[] plaintext;
+ private byte[] ciphertext;
+
+ public TestCase(String key, String iv, String plaintext, String ciphertext)
+ {
+ this.key = Hex.decode(key);
+ this.iv = Hex.decode(iv);
+ this.plaintext = Hex.decode(plaintext);
+ this.ciphertext = Hex.decode(ciphertext);
+ }
+
+ public byte[] getKey()
+ {
+ return key;
+ }
+
+ public byte[] getIv()
+ {
+ return iv;
+ }
+
+ public byte[] getPlaintext()
+ {
+ return plaintext;
+ }
+
+ public byte[] getCiphertext()
+ {
+ return ciphertext;
+ }
+ }
+
+ // Test cases generated by naclcrypto-20090308, as used by cryptopp
+ private static final TestCase[] TEST_CASES = new TestCase[] {
+ new TestCase(
+ "a6a7251c1e72916d11c2cb214d3c252539121d8e234e652d651fa4c8cff88030",
+ "9e645a74e9e0a60d8243acd9177ab51a1beb8d5a2f5d700c",
+ "093c5e5585579625337bd3ab619d615760d8c5b224a85b1d0efe0eb8a7ee163abb0376529fcc09bab506c618e13ce777d82c3ae9d1a6f972d4160287cbfe60bf2130fc0a6ff6049d0a5c8a82f429231f008082e845d7e189d37f9ed2b464e6b919e6523a8c1210bd52a02a4c3fe406d3085f5068d1909eeeca6369abc981a42e87fe665583f0ab85ae71f6f84f528e6b397af86f6917d9754b7320dbdc2fea81496f2732f532ac78c4e9c6cfb18f8e9bdf74622eb126141416776971a84f94d156beaf67aecbf2ad412e76e66e8fad7633f5b6d7f3d64b5c6c69ce29003c6024465ae3b89be78e915d88b4b5621d",
+ "b2af688e7d8fc4b508c05cc39dd583d6714322c64d7f3e63147aede2d9534934b04ff6f337b031815cd094bdbc6d7a92077dce709412286822ef0737ee47f6b7ffa22f9d53f11dd2b0a3bb9fc01d9a88f9d53c26e9365c2c3c063bc4840bfc812e4b80463e69d179530b25c158f543191cff993106511aa036043bbc75866ab7e34afc57e2cce4934a5faae6eabe4f221770183dd060467827c27a354159a081275a291f69d946d6fe28ed0b9ce08206cf484925a51b9498dbde178ddd3ae91a8581b91682d860f840782f6eea49dbb9bd721501d2c67122dea3b7283848c5f13e0c0de876bd227a856e4de593a3"),
+ new TestCase(
+ "9e1da239d155f52ad37f75c7368a536668b051952923ad44f57e75ab588e475a",
+ "af06f17859dffa799891c4288f6635b5c5a45eee9017fd72",
+ "feac9d54fc8c115ae247d9a7e919dd76cfcbc72d32cae4944860817cbdfb8c04e6b1df76a16517cd33ccf1acda9206389e9e318f5966c093cfb3ec2d9ee2de856437ed581f552f26ac2907609df8c613b9e33d44bfc21ff79153e9ef81a9d66cc317857f752cc175fd8891fefebb7d041e6517c3162d197e2112837d3bc4104312ad35b75ea686e7c70d4ec04746b52ff09c421451459fb59f",
+ "2c261a2f4e61a62e1b27689916bf03453fcbc97bb2af6f329391ef063b5a219bf984d07d70f602d85f6db61474e9d9f5a2deecb4fcd90184d16f3b5b5e168ee03ea8c93f3933a22bc3d1a5ae8c2d8b02757c87c073409052a2a8a41e7f487e041f9a49a0997b540e18621cad3a24f0a56d9b19227929057ab3ba950f6274b121f193e32e06e5388781a1cb57317c0ba6305e910961d01002f0"),
+ new TestCase("d5c7f6797b7e7e9c1d7fd2610b2abf2bc5a7885fb3ff78092fb3abe8986d35e2",
+ "744e17312b27969d826444640e9c4a378ae334f185369c95",
+ "7758298c628eb3a4b6963c5445ef66971222be5d1a4ad839715d1188071739b77cc6e05d5410f963a64167629757",
+ "27b8cfe81416a76301fd1eec6a4d99675069b2da2776c360db1bdfea7c0aa613913e10f7a60fec04d11e65f2d64e"),
+ new TestCase(
+ "737d7811ce96472efed12258b78122f11deaec8759ccbd71eac6bbefa627785c",
+ "6fb2ee3dda6dbd12f1274f126701ec75c35c86607adb3edd",
+ "501325fb2645264864df11faa17bbd58312b77cad3d94ac8fb8542f0eb653ad73d7fce932bb874cb89ac39fc47f8267cf0f0c209f204b2d8578a3bdf461cb6a271a468bebaccd9685014ccbc9a73618c6a5e778a21cc8416c60ad24ddc417a130d53eda6dfbfe47d09170a7be1a708b7b5f3ad464310be36d9a2a95dc39e83d38667e842eb6411e8a23712297b165f690c2d7ca1b1346e3c1fccf5cafd4f8be0",
+ "6724c372d2e9074da5e27a6c54b2d703dc1d4c9b1f8d90f00c122e692ace7700eadca942544507f1375b6581d5a8fb39981c1c0e6e1ff2140b082e9ec016fce141d5199647d43b0b68bfd0fea5e00f468962c7384dd6129aea6a3fdfe75abb210ed5607cef8fa0e152833d5ac37d52e557b91098a322e76a45bbbcf4899e790618aa3f4c2e5e0fc3de93269a577d77a5502e8ea02f717b1dd2df1ec69d8b61ca"),
+ new TestCase(
+ "760158da09f89bbab2c99e6997f9523a95fcef10239bcca2573b7105f6898d34",
+ "43636b2cc346fc8b7c85a19bf507bdc3dafe953b88c69dba",
+ "d30a6d42dff49f0ed039a306bae9dec8d9e88366cc19e8c3642fd58fa0794ebf8029d949730339b0823a51f0f49f0d2c71f1051c1e0e2c86941f172789cdb1b0107413e70f982ff9761877bb526ef1c3eb1106a948d60ef21bd35d32cfd64f89b79ed63ecc5cca56246af736766f285d8e6b0da9cb1cd21020223ffacc5a32",
+ "c815b6b79b64f9369aec8dce8c753df8a50f2bc97c70ce2f014db33a65ac5816bac9e30ac08bdded308c65cb87e28e2e71b677dc25c5a6499c1553555daf1f55270a56959dffa0c66f24e0af00951ec4bb59ccc3a6c5f52e0981647e53e439313a52c40fa7004c855b6e6eb25b212a138e843a9ba46edb2a039ee82a263abe"),
+ new TestCase(
+ "27ba7e81e7edd4e71be53c07ce8e633138f287e155c7fa9e84c4ad804b7fa1b9",
+ "ea05f4ebcd2fb6b000da0612861ba54ff5c176fb601391aa",
+ "e09ff5d2cb050d69b2d42494bde5825238c756d6991d99d7a20d1ef0b83c371c89872690b2fc11d5369f4fc4971b6d3d6c078aef9b0f05c0e61ab89c025168054defeb03fef633858700c58b1262ce011300012673e893e44901dc18eee3105699c44c805897bdaf776af1833162a21a",
+ "a23e7ef93c5d0667c96d9e404dcbe6be62026fa98f7a3ff9ba5d458643a16a1cef7272dc6097a9b52f35983557c77a11b314b4f7d5dc2cca15ee47616f861873cbfed1d32372171a61e38e447f3cf362b3abbb2ed4170d89dcb28187b7bfd206a3e026f084a7e0ed63d319de6bc9afc0"),
+ new TestCase("6799d76e5ffb5b4920bc2768bafd3f8c16554e65efcf9a16f4683a7a06927c11",
+ "61ab951921e54ff06d9b77f313a4e49df7a057d5fd627989", "472766", "8fd7df"),
+ new TestCase(
+ "f68238c08365bb293d26980a606488d09c2f109edafa0bbae9937b5cc219a49c",
+ "5190b51e9b708624820b5abdf4e40fad1fb950ad1adc2d26",
+ "47ec6b1f73c4b7ff5274a0bfd7f45f864812c85a12fbcb3c2cf8a3e90cf66ccf2eacb521e748363c77f52eb426ae57a0c6c78f75af71284569e79d1a92f949a9d69c4efc0b69902f1e36d7562765543e2d3942d9f6ff5948d8a312cff72c1afd9ea3088aff7640bfd265f7a9946e606abc77bcedae6bddc75a0dba0bd917d73e3bd1268f727e0096345da1ed25cf553ea7a98fea6b6f285732de37431561ee1b3064887fbcbd71935e02",
+ "36160e88d3500529ba4edba17bc24d8cfaca9a0680b3b1fc97cf03f3675b7ac301c883a68c071bc54acdd3b63af4a2d72f985e51f9d60a4c7fd481af10b2fc75e252fdee7ea6b6453190617dcc6e2fe1cd56585fc2f0b0e97c5c3f8ad7eb4f31bc4890c03882aac24cc53acc1982296526690a220271c2f6e326750d3fbda5d5b63512c831f67830f59ac49aae330b3e0e02c9ea0091d19841f1b0e13d69c9fbfe8a12d6f30bb734d9d2"),
+ new TestCase(
+ "45b2bd0de4ed9293ec3e26c4840faaf64b7d619d51e9d7a2c7e36c83d584c3df",
+ "546c8c5d6be8f90952cab3f36d7c1957baaa7a59abe3d7e5",
+ "5007c8cd5b3c40e17d7fe423a87ae0ced86bec1c39dc07a25772f3e96dabd56cd3fd7319f6c9654925f2d87087a700e1b130da796895d1c9b9acd62b266144067d373ed51e787498b03c52faad16bb3826fa511b0ed2a19a8663f5ba2d6ea7c38e7212e9697d91486c49d8a000b9a1935d6a7ff7ef23e720a45855481440463b4ac8c4f6e7062adc1f1e1e25d3d65a31812f58a71160",
+ "8eacfba568898b10c0957a7d44100685e8763a71a69a8d16bc7b3f88085bb9a2f09642e4d09a9f0ad09d0aad66b22610c8bd02ff6679bb92c2c026a216bf425c6be35fb8dae7ff0c72b0efd6a18037c70eed0ca90062a49a3c97fdc90a8f9c2ea536bfdc41918a7582c9927fae47efaa3dc87967b7887dee1bf071734c7665901d9105dae2fdf66b4918e51d8f4a48c60d19fbfbbcba"),
+ new TestCase(
+ "fe559c9a282beb40814d016d6bfcb2c0c0d8bf077b1110b8703a3ce39d70e0e1",
+ "b076200cc7011259805e18b304092754002723ebec5d6200",
+ "6db65b9ec8b114a944137c821fd606be75478d928366d5284096cdef782fcff7e8f59cb8ffcda979757902c5ffa6bc477ceaa4cb5d5ea76f94d91e833f823a6bc78f1055dfa6a97bea8965c1cde67a668e001257334a585727d9e0f7c1a06e88d3d25a4e6d9096c968bf138e116a3ebeffd4bb4808adb1fd698164ba0a35c709a47f16f1f4435a2345a9194a00b95abd51851d505809a6077da9baca5831afff31578c487ee68f2767974a98a7e803aac788da98319c4ea8eaa3d394855651f484cef543f537e35158ee29",
+ "4dce9c8f97a028051b0727f34e1b9ef21f06f0760f36e71713204027902090ba2bb6b13436ee778d9f50530efbd7a32b0d41443f58ccaee781c7b716d3a96fdec0e3764ed7959f34c3941278591ea033b5cbadc0f1916032e9bebbd1a8395b83fb63b1454bd775bd20b3a2a96f951246ac14daf68166ba62f6cbff8bd121ac9498ff8852fd2be975df52b5daef3829d18eda42e715022dcbf930d0a789ee6a146c2c7088c35773c63c06b4af4559856ac199ced86863e4294707825337c5857970eb7fddeb263781309011"),
+ new TestCase(
+ "0ae10012d7e56614b03dcc89b14bae9242ffe630f3d7e35ce8bbb97bbc2c92c3",
+ "f96b025d6cf46a8a12ac2af1e2aef1fb83590adadaa5c5ea",
+ "ea0f354e96f12bc72bbaa3d12b4a8ed879b042f0689878f46b651cc4116d6f78409b11430b3aaa30b2076891e8e1fa528f2fd169ed93dc9f84e24409eec2101daf4d057be2492d11de640cbd7b355ad29fb70400fffd7cd6d425abeeb732a0eaa4330af4c656252c4173deab653eb85c58462d7ab0f35fd12b613d29d473d330310dc323d3c66348bbdbb68a326324657cae7b77a9e34358f2cec50c85609e73056856796e3be8d62b6e2fe9f953",
+ "e8abd48924b54e5b80866be7d4ebe5cf4274cafff08b39cb2d40a8f0b472398aedc776e0793812fbf1f60078635d2ed86b15efcdba60411ee23b07233592a44ec31b1013ce8964236675f8f183aef885e864f2a72edf4215b5338fa2b54653dfa1a8c55ce5d95cc605b9b311527f2e3463ffbec78a9d1d65dabad2f338769c9f43f133a791a11c7eca9af0b771a4ac32963dc8f631a2c11217ac6e1b9430c1aae1ceebe22703f429998a8fb8c641"),
+ new TestCase(
+ "082c539bc5b20f97d767cd3f229eda80b2adc4fe49c86329b5cd6250a9877450",
+ "845543502e8b64912d8f2c8d9fffb3c69365686587c08d0c",
+ "a96bb7e910281a6dfad7c8a9c370674f0ceec1ad8d4f0de32f9ae4a23ed329e3d6bc708f876640a229153ac0e7281a8188dd77695138f01cda5f41d5215fd5c6bdd46d982cb73b1efe2997970a9fdbdb1e768d7e5db712068d8ba1af6067b5753495e23e6e1963af012f9c7ce450bf2de619d3d59542fb55f3",
+ "835da74fc6de08cbda277a7966a07c8dcd627e7b17adde6d930b6581e3124b8baad096f693991fedb1572930601fc7709541839b8e3ffd5f033d2060d999c6c6e3048276613e648000acb5212cc632a916afce290e20ebdf612d08a6aa4c79a74b070d3f872a861f8dc6bb07614db515d363349d3a8e3336a3"),
+ new TestCase("3d02bff3375d403027356b94f514203737ee9a85d2052db3e4e5a217c259d18a",
+ "74216c95031895f48c1dba651555ebfa3ca326a755237025",
+ "0d4b0f54fd09ae39baa5fa4baccf2e6682e61b257e01f42b8f",
+ "16c4006c28365190411eb1593814cf15e74c22238f210afc3d"),
+ new TestCase(
+ "ad1a5c47688874e6663a0f3fa16fa7efb7ecadc175c468e5432914bdb480ffc6",
+ "e489eed440f1aae1fac8fb7a9825635454f8f8f1f52e2fcc",
+ "aa6c1e53580f03a9abb73bfdadedfecada4c6b0ebe020ef10db745e54ba861caf65f0e40dfc520203bb54d29e0a8f78f16b3f1aa525d6bfa33c54726e59988cfbec78056",
+ "02fe84ce81e178e7aabdd3ba925a766c3c24756eefae33942af75e8b464556b5997e616f3f2dfc7fce91848afd79912d9fb55201b5813a5a074d2c0d4292c1fd441807c5"),
+ new TestCase(
+ "053a02bedd6368c1fb8afc7a1b199f7f7ea2220c9a4b642a6850091c9d20ab9c",
+ "c713eea5c26dad75ad3f52451e003a9cb0d649f917c89dde",
+ "8f0a8a164760426567e388840276de3f95cb5e3fadc6ed3f3e4fe8bc169d9388804dcb94b6587dbb66cb0bd5f87b8e98b52af37ba290629b858e0e2aa7378047a26602",
+ "516710e59843e6fbd4f25d0d8ca0ec0d47d39d125e9dad987e0518d49107014cb0ae405e30c2eb3794750bca142ce95e290cf95abe15e822823e2e7d3ab21bc8fbd445"),
+ new TestCase(
+ "5b14ab0fbed4c58952548a6cb1e0000cf4481421f41288ea0aa84add9f7deb96",
+ "54bf52b911231b952ba1a6af8e45b1c5a29d97e2abad7c83",
+ "37fb44a675978b560ff9a4a87011d6f3ad2d37a2c3815b45a3c0e6d1b1d8b1784cd468927c2ee39e1dccd4765e1c3d676a335be1ccd6900a45f5d41a317648315d8a8c24adc64eb285f6aeba05b9029586353d303f17a807658b9ff790474e1737bd5fdc604aeff8dfcaf1427dcc3aacbb0256badcd183ed75a2dc52452f87d3c1ed2aa583472b0ab91cda20614e9b6fdbda3b49b098c95823cc72d8e5b717f2314b0324e9ce",
+ "ae6deb5d6ce43d4b09d0e6b1c0e9f46157bcd8ab50eaa3197ff9fa2bf7af649eb52c68544fd3adfe6b1eb316f1f23538d470c30dbfec7e57b60cbcd096c782e7736b669199c8253e70214cf2a098fda8eac5da79a9496a3aae754d03b17c6d70d1027f42bf7f95ce3d1d9c338854e158fcc803e4d6262fb639521e47116ef78a7a437ca9427ba645cd646832feab822a208278e45e93e118d780b988d65397eddfd7a819526e"),
+ new TestCase(
+ "d74636e3413a88d85f322ca80fb0bd650bd0bf0134e2329160b69609cd58a4b0",
+ "efb606aa1d9d9f0f465eaa7f8165f1ac09f5cb46fecf2a57",
+ "f85471b75f6ec81abac2799ec09e98e280b2ffd64ca285e5a0109cfb31ffab2d617b2c2952a2a8a788fc0da2af7f530758f74f1ab56391ab5ff2adbcc5be2d6c7f49fbe8118104c6ff9a23c6dfe52f57954e6a69dcee5db06f514f4a0a572a9a8525d961dae72269b987189d465df6107119c7fa790853e063cba0fab7800ca932e258880fd74c33c784675bedad0e7c09e9cc4d63dd5e9713d5d4a0196e6b562226ac31b4f57c04f90a181973737ddc7e80f364112a9fbb435ebdbcabf7d490ce52",
+ "b2b795fe6c1d4c83c1327e015a67d4465fd8e32813575cbab263e20ef05864d2dc17e0e4eb81436adfe9f638dcc1c8d78f6b0306baf938e5d2ab0b3e05e735cc6fff2d6e02e3d60484bea7c7a8e13e23197fea7b04d47d48f4a4e5944174539492800d3ef51e2ee5e4c8a0bdf050c2dd3dd74fce5e7e5c37364f7547a11480a3063b9a0a157b15b10a5a954de2731ced055aa2e2767f0891d4329c426f3808ee867bed0dc75b5922b7cfb895700fda016105a4c7b7f0bb90f029f6bbcb04ac36ac16") };
+
+ public String getName()
+ {
+ return "XSalsa20";
+ }
+
+ public void performTest() throws Exception
+ {
+ for (int i = 0; i < TEST_CASES.length; i++)
+ {
+ performTest(i, TEST_CASES[i]);
+ }
+ }
+
+ private void performTest(int number, TestCase testCase)
+ {
+ final byte[] plaintext = testCase.getPlaintext();
+ byte[] output = new byte[plaintext.length];
+
+ XSalsa20Engine engine = new XSalsa20Engine();
+ engine.init(false, new ParametersWithIV(new KeyParameter(testCase.getKey()), testCase.getIv()));
+
+ engine.processBytes(testCase.getPlaintext(), 0, testCase.getPlaintext().length, output, 0);
+
+ if (!Arrays.areEqual(testCase.getCiphertext(), output))
+ {
+ fail("mismatch on " + number, new String(Hex.encode(testCase.getCiphertext())),
+ new String(Hex.encode(output)));
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new XSalsa20Test());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/XTEATest.java b/core/src/test/java/org/spongycastle/crypto/test/XTEATest.java
new file mode 100644
index 00000000..74da43be
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/XTEATest.java
@@ -0,0 +1,48 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.crypto.engines.XTEAEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * TEA tester - based on C implementation results from http://www.simonshepherd.supanet.com/tea.htm
+ */
+public class XTEATest
+ extends CipherTest
+{
+ static SimpleTest[] tests = {
+ new BlockCipherVectorTest(0, new XTEAEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000")),
+ "0000000000000000",
+ "dee9d4d8f7131ed9"),
+ new BlockCipherVectorTest(1, new XTEAEngine(),
+ new KeyParameter(Hex.decode("00000000000000000000000000000000")),
+ "0102030405060708",
+ "065c1b8975c6a816"),
+ new BlockCipherVectorTest(2, new XTEAEngine(),
+ new KeyParameter(Hex.decode("0123456712345678234567893456789A")),
+ "0000000000000000",
+ "1ff9a0261ac64264"),
+ new BlockCipherVectorTest(3, new XTEAEngine(),
+ new KeyParameter(Hex.decode("0123456712345678234567893456789A")),
+ "0102030405060708",
+ "8c67155b2ef91ead"),
+ };
+
+ XTEATest()
+ {
+ super(tests, new XTEAEngine(), new KeyParameter(new byte[16]));
+ }
+
+ public String getName()
+ {
+ return "XTEA";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new XTEATest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/cavp/CAVPListener.java b/core/src/test/java/org/spongycastle/crypto/test/cavp/CAVPListener.java
new file mode 100644
index 00000000..71011614
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/cavp/CAVPListener.java
@@ -0,0 +1,18 @@
+package org.spongycastle.crypto.test.cavp;
+
+import java.util.Properties;
+
+public interface CAVPListener
+{
+ public void setup();
+
+ public void receiveStart(String name);
+
+ public void receiveCAVPVectors(String name, Properties config, Properties vectors);
+
+ public void receiveCommentLine(String commentLine);
+
+ public void receiveEnd();
+
+ public void tearDown();
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/cavp/CAVPReader.java b/core/src/test/java/org/spongycastle/crypto/test/cavp/CAVPReader.java
new file mode 100644
index 00000000..2cee4559
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/cavp/CAVPReader.java
@@ -0,0 +1,152 @@
+package org.spongycastle.crypto.test.cavp;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA224Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.digests.SHA384Digest;
+import org.spongycastle.crypto.digests.SHA512Digest;
+import org.spongycastle.crypto.engines.AESFastEngine;
+import org.spongycastle.crypto.engines.DESedeEngine;
+import org.spongycastle.crypto.macs.CMac;
+import org.spongycastle.crypto.macs.HMac;
+
+public class CAVPReader
+{
+
+ private static final Pattern COMMENT_PATTERN = Pattern.compile("^\\s*\\#\\s*(.*)$");
+ private static final Pattern CONFIG_PATTERN = Pattern.compile("^\\s*+\\[\\s*+(.*?)\\s*+=\\s*+(.*?)\\s*+\\]\\s*+$");
+ private static final Pattern VECTOR_PATTERN = Pattern.compile("^\\s*+(.*?)\\s*+=\\s*+(.*?)\\s*+$");
+ private static final Pattern EMPTY_PATTERN = Pattern.compile("^\\s*+$");
+ static final Pattern PATTERN_FOR_R = Pattern.compile("(\\d+)_BITS");
+ private final CAVPListener listener;
+ private String name;
+ private BufferedReader lineReader;
+
+
+ public CAVPReader(CAVPListener listener)
+ {
+ this.listener = listener;
+ }
+
+ public void setInput(String name, Reader reader)
+ {
+ this.name = name;
+ this.lineReader = new BufferedReader(reader);
+ }
+
+ public void readAll()
+ throws IOException
+ {
+
+ listener.setup();
+
+ Properties config = new Properties();
+
+ boolean startNewVector = true;
+
+ Properties vectors = new Properties();
+
+ while (true)
+ {
+ final String line = lineReader.readLine();
+ if (line == null)
+ {
+ listener.receiveEnd();
+ break;
+ }
+
+ final Matcher commentMatcher = COMMENT_PATTERN.matcher(line);
+ if (commentMatcher.matches())
+ {
+ listener.receiveCommentLine(commentMatcher.group(1));
+ continue;
+ }
+
+ final Matcher configMatcher = CONFIG_PATTERN.matcher(line);
+ if (configMatcher.matches())
+ {
+ config.put(configMatcher.group(1), configMatcher.group(2));
+ continue;
+ }
+
+ final Matcher vectorMatcher = VECTOR_PATTERN.matcher(line);
+ if (vectorMatcher.matches())
+ {
+ vectors.put(vectorMatcher.group(1), vectorMatcher.group(2));
+ startNewVector = false;
+ continue;
+ }
+
+ final Matcher emptyMatcher = EMPTY_PATTERN.matcher(line);
+ if (emptyMatcher.matches())
+ {
+ if (startNewVector)
+ {
+ continue;
+ }
+
+ listener.receiveCAVPVectors(name, config, vectors);
+ vectors = new Properties();
+ startNewVector = true;
+ }
+ }
+
+ listener.tearDown();
+ }
+
+ static Mac createPRF(Properties config)
+ {
+ final Mac prf;
+ if (config.getProperty("PRF").matches("CMAC_AES\\d\\d\\d"))
+ {
+ BlockCipher blockCipher = new AESFastEngine();
+ prf = new CMac(blockCipher);
+ }
+ else if (config.getProperty("PRF").matches("CMAC_TDES\\d"))
+ {
+ BlockCipher blockCipher = new DESedeEngine();
+ prf = new CMac(blockCipher);
+ }
+ else if (config.getProperty("PRF").matches("HMAC_SHA1"))
+ {
+ Digest digest = new SHA1Digest();
+ prf = new HMac(digest);
+ }
+ else if (config.getProperty("PRF").matches("HMAC_SHA224"))
+ {
+ Digest digest = new SHA224Digest();
+ prf = new HMac(digest);
+ }
+ else if (config.getProperty("PRF").matches("HMAC_SHA256"))
+ {
+ Digest digest = new SHA256Digest();
+ prf = new HMac(digest);
+ }
+ else if (config.getProperty("PRF").matches("HMAC_SHA384"))
+ {
+ Digest digest = new SHA384Digest();
+ prf = new HMac(digest);
+ }
+ else if (config.getProperty("PRF").matches("HMAC_SHA512"))
+ {
+ Digest digest = new SHA512Digest();
+ prf = new HMac(digest);
+ }
+ else
+ {
+ throw new IllegalStateException("Unknown Mac for PRF");
+ }
+ return prf;
+ }
+
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/cavp/KDFCounterTests.java b/core/src/test/java/org/spongycastle/crypto/test/cavp/KDFCounterTests.java
new file mode 100644
index 00000000..ee53d475
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/cavp/KDFCounterTests.java
@@ -0,0 +1,119 @@
+package org.spongycastle.crypto.test.cavp;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Properties;
+import java.util.regex.Matcher;
+
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.generators.KDFCounterBytesGenerator;
+import org.spongycastle.crypto.params.KDFCounterParameters;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.TestFailedException;
+
+public final class KDFCounterTests
+ implements CAVPListener
+{
+ private PrintWriter out;
+
+ public void receiveCAVPVectors(String name, Properties config,
+ Properties vectors)
+ {
+
+ // create Mac based PRF from PRF property, create the KDF
+ final Mac prf = CAVPReader.createPRF(config);
+ final KDFCounterBytesGenerator gen = new KDFCounterBytesGenerator(prf);
+
+
+ Matcher matcherForR = CAVPReader.PATTERN_FOR_R.matcher(config.getProperty("RLEN"));
+ if (!matcherForR.matches())
+ {
+ throw new IllegalStateException("RLEN value should always match");
+ }
+ final int r = Integer.parseInt(matcherForR.group(1));
+
+ final int count = Integer.parseInt(vectors.getProperty("COUNT"));
+ final int l = Integer.parseInt(vectors.getProperty("L"));
+ final byte[] ki = Hex.decode(vectors.getProperty("KI"));
+
+ //Three variants of this KDF are possible, with the counter before the fixed data, after the fixed data, or in the middle of the fixed data.
+ if (config.getProperty("CTRLOCATION").matches("BEFORE_FIXED"))
+ {
+ final byte[] fixedInputData = Hex.decode(vectors.getProperty("FixedInputData"));
+ final KDFCounterParameters params = new KDFCounterParameters(ki, null, fixedInputData, r);
+ gen.init(params);
+ }
+ else if (config.getProperty("CTRLOCATION").matches("AFTER_FIXED"))
+ {
+ final byte[] fixedInputData = Hex.decode(vectors.getProperty("FixedInputData"));
+ final KDFCounterParameters params = new KDFCounterParameters(ki, fixedInputData, null, r);
+ gen.init(params);
+ }
+ else if (config.getProperty("CTRLOCATION").matches("MIDDLE_FIXED"))
+ {
+ final byte[] DataBeforeCtrData = Hex.decode(vectors.getProperty("DataBeforeCtrData"));
+ final byte[] DataAfterCtrData = Hex.decode(vectors.getProperty("DataAfterCtrData"));
+ final KDFCounterParameters params = new KDFCounterParameters(ki, DataBeforeCtrData, DataAfterCtrData, r);
+ gen.init(params);
+ }
+ else
+ {
+ return; // Unknown CTRLOCATION
+ }
+
+
+ final byte[] koGenerated = new byte[l / 8];
+ gen.generateBytes(koGenerated, 0, koGenerated.length);
+
+ final byte[] koVectors = Hex.decode(vectors.getProperty("KO"));
+
+ compareKO(name, config, count, koGenerated, koVectors);
+ }
+
+ private static void compareKO(
+ String name, Properties config, int test, byte[] calculatedOKM, byte[] testOKM)
+ {
+
+ if (!Arrays.areEqual(calculatedOKM, testOKM))
+ {
+ throw new TestFailedException(new SimpleTestResult(
+ false, name + " using " + config + " test " + test + " failed"));
+
+ }
+ }
+
+ public void receiveCommentLine(String commentLine)
+ {
+ // out.println("# " + commentLine);
+ }
+
+ public void receiveStart(String name)
+ {
+ // do nothing
+ }
+
+ public void receiveEnd()
+ {
+ out.println(" *** *** *** ");
+ }
+
+ public void setup()
+ {
+ try
+ {
+ out = new PrintWriter(new FileWriter("KDFCTR.gen"));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public void tearDown()
+ {
+ out.close();
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/crypto/test/cavp/KDFDoublePipelineCounterTests.java b/core/src/test/java/org/spongycastle/crypto/test/cavp/KDFDoublePipelineCounterTests.java
new file mode 100644
index 00000000..8f58be49
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/cavp/KDFDoublePipelineCounterTests.java
@@ -0,0 +1,107 @@
+package org.spongycastle.crypto.test.cavp;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Properties;
+import java.util.regex.Matcher;
+
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.generators.KDFDoublePipelineIterationBytesGenerator;
+import org.spongycastle.crypto.params.KDFDoublePipelineIterationParameters;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.TestFailedException;
+
+public final class KDFDoublePipelineCounterTests
+ implements CAVPListener
+{
+ private PrintWriter out;
+
+ public void receiveCAVPVectors(String name, Properties config,
+ Properties vectors)
+ {
+ // out.println(" === " + name + " === ");
+ // out.println(" --- config --- ");
+ // out.println(config);
+ // out.println(" --- vectors --- ");
+ // out.println(vectors);
+
+ // always skip AFTER_FIXED
+ if (!config.getProperty("CTRLOCATION").matches("AFTER_ITER"))
+ {
+ return;
+ }
+
+ // create Mac based PRF from PRF property, create the KDF
+ final Mac prf = CAVPReader.createPRF(config);
+ final KDFDoublePipelineIterationBytesGenerator gen = new KDFDoublePipelineIterationBytesGenerator(prf);
+
+
+ Matcher matcherForR = CAVPReader.PATTERN_FOR_R.matcher(config.getProperty("RLEN"));
+ if (!matcherForR.matches())
+ {
+ throw new IllegalStateException("RLEN value should always match");
+ }
+ final int r = Integer.parseInt(matcherForR.group(1));
+
+ final int count = Integer.parseInt(vectors.getProperty("COUNT"));
+ final int l = Integer.parseInt(vectors.getProperty("L"));
+ final byte[] ki = Hex.decode(vectors.getProperty("KI"));
+ final byte[] fixedInputData = Hex.decode(vectors.getProperty("FixedInputData"));
+ final KDFDoublePipelineIterationParameters params = KDFDoublePipelineIterationParameters.createWithCounter(ki, fixedInputData, r);
+ gen.init(params);
+
+ final byte[] koGenerated = new byte[l / 8];
+ gen.generateBytes(koGenerated, 0, koGenerated.length);
+
+ final byte[] koVectors = Hex.decode(vectors.getProperty("KO"));
+
+ compareKO(name, config, count, koGenerated, koVectors);
+ }
+
+ private static void compareKO(
+ String name, Properties config, int test, byte[] calculatedOKM, byte[] testOKM)
+ {
+
+ if (!Arrays.areEqual(calculatedOKM, testOKM))
+ {
+ throw new TestFailedException(new SimpleTestResult(
+ false, name + " using " + config + " test " + test + " failed"));
+
+ }
+ }
+
+ public void receiveCommentLine(String commentLine)
+ {
+ // out.println("# " + commentLine);
+ }
+
+ public void receiveStart(String name)
+ {
+ // do nothing
+ }
+
+ public void receiveEnd()
+ {
+ out.println(" *** *** *** ");
+ }
+
+ public void setup()
+ {
+ try
+ {
+ out = new PrintWriter(new FileWriter("KDFDblPipelineCounter.gen"));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public void tearDown()
+ {
+ out.close();
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/crypto/test/cavp/KDFDoublePipelineIterationNoCounterTests.java b/core/src/test/java/org/spongycastle/crypto/test/cavp/KDFDoublePipelineIterationNoCounterTests.java
new file mode 100644
index 00000000..512568f5
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/cavp/KDFDoublePipelineIterationNoCounterTests.java
@@ -0,0 +1,88 @@
+package org.spongycastle.crypto.test.cavp;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Properties;
+
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.generators.KDFDoublePipelineIterationBytesGenerator;
+import org.spongycastle.crypto.params.KDFDoublePipelineIterationParameters;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.TestFailedException;
+
+public final class KDFDoublePipelineIterationNoCounterTests
+ implements CAVPListener
+{
+ private PrintWriter out;
+
+ public void receiveCAVPVectors(String name, Properties config,
+ Properties vectors)
+ {
+
+
+ // create Mac based PRF from PRF property, create the KDF
+ final Mac prf = CAVPReader.createPRF(config);
+ final KDFDoublePipelineIterationBytesGenerator gen = new KDFDoublePipelineIterationBytesGenerator(prf);
+
+ final int count = Integer.parseInt(vectors.getProperty("COUNT"));
+ final int l = Integer.parseInt(vectors.getProperty("L"));
+ final byte[] ki = Hex.decode(vectors.getProperty("KI"));
+ final byte[] fixedInputData = Hex.decode(vectors.getProperty("FixedInputData"));
+ final KDFDoublePipelineIterationParameters params = KDFDoublePipelineIterationParameters.createWithoutCounter(ki, fixedInputData);
+ gen.init(params);
+
+ final byte[] koGenerated = new byte[l / 8];
+ gen.generateBytes(koGenerated, 0, koGenerated.length);
+
+ final byte[] koVectors = Hex.decode(vectors.getProperty("KO"));
+
+ compareKO(name, config, count, koGenerated, koVectors);
+ }
+
+ private static void compareKO(
+ String name, Properties config, int test, byte[] calculatedOKM, byte[] testOKM)
+ {
+
+ if (!Arrays.areEqual(calculatedOKM, testOKM))
+ {
+ throw new TestFailedException(new SimpleTestResult(
+ false, name + " using " + config + " test " + test + " failed"));
+
+ }
+ }
+
+ public void receiveCommentLine(String commentLine)
+ {
+ // out.println("# " + commentLine);
+ }
+
+ public void receiveStart(String name)
+ {
+ // do nothing
+ }
+
+ public void receiveEnd()
+ {
+ out.println(" *** *** *** ");
+ }
+
+ public void setup()
+ {
+ try
+ {
+ out = new PrintWriter(new FileWriter("KDFDblPipelineNoCounter.gen"));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public void tearDown()
+ {
+ out.close();
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/crypto/test/cavp/KDFFeedbackCounterTests.java b/core/src/test/java/org/spongycastle/crypto/test/cavp/KDFFeedbackCounterTests.java
new file mode 100644
index 00000000..84cd4dd8
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/cavp/KDFFeedbackCounterTests.java
@@ -0,0 +1,108 @@
+package org.spongycastle.crypto.test.cavp;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Properties;
+import java.util.regex.Matcher;
+
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.generators.KDFFeedbackBytesGenerator;
+import org.spongycastle.crypto.params.KDFFeedbackParameters;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.TestFailedException;
+
+public final class KDFFeedbackCounterTests
+ implements CAVPListener
+{
+ private PrintWriter out;
+
+ public void receiveCAVPVectors(String name, Properties config,
+ Properties vectors)
+ {
+ // out.println(" === " + name + " === ");
+ // out.println(" --- config --- ");
+ // out.println(config);
+ // out.println(" --- vectors --- ");
+ // out.println(vectors);
+
+ // always skip AFTER_FIXED
+ if (!config.getProperty("CTRLOCATION").matches("AFTER_ITER"))
+ {
+ return;
+ }
+
+ // create Mac based PRF from PRF property, create the KDF
+ final Mac prf = CAVPReader.createPRF(config);
+ final KDFFeedbackBytesGenerator gen = new KDFFeedbackBytesGenerator(prf);
+
+
+ Matcher matcherForR = CAVPReader.PATTERN_FOR_R.matcher(config.getProperty("RLEN"));
+ if (!matcherForR.matches())
+ {
+ throw new IllegalStateException("RLEN value should always match");
+ }
+ final int r = Integer.parseInt(matcherForR.group(1));
+
+ final int count = Integer.parseInt(vectors.getProperty("COUNT"));
+ final int l = Integer.parseInt(vectors.getProperty("L"));
+ final byte[] ki = Hex.decode(vectors.getProperty("KI"));
+ final byte[] iv = Hex.decode(vectors.getProperty("IV"));
+ final byte[] fixedInputData = Hex.decode(vectors.getProperty("FixedInputData"));
+ final KDFFeedbackParameters params = KDFFeedbackParameters.createWithCounter(ki, iv, fixedInputData, r);
+ gen.init(params);
+
+ final byte[] koGenerated = new byte[l / 8];
+ gen.generateBytes(koGenerated, 0, koGenerated.length);
+
+ final byte[] koVectors = Hex.decode(vectors.getProperty("KO"));
+
+ compareKO(name, config, count, koGenerated, koVectors);
+ }
+
+ private static void compareKO(
+ String name, Properties config, int test, byte[] calculatedOKM, byte[] testOKM)
+ {
+
+ if (!Arrays.areEqual(calculatedOKM, testOKM))
+ {
+ throw new TestFailedException(new SimpleTestResult(
+ false, name + " using " + config + " test " + test + " failed"));
+
+ }
+ }
+
+ public void receiveCommentLine(String commentLine)
+ {
+ // out.println("# " + commentLine);
+ }
+
+ public void receiveStart(String name)
+ {
+ // do nothing
+ }
+
+ public void receiveEnd()
+ {
+ out.println(" *** *** *** ");
+ }
+
+ public void setup()
+ {
+ try
+ {
+ out = new PrintWriter(new FileWriter("KDFFeedbackCounter.gen"));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public void tearDown()
+ {
+ out.close();
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/crypto/test/cavp/KDFFeedbackNoCounterTests.java b/core/src/test/java/org/spongycastle/crypto/test/cavp/KDFFeedbackNoCounterTests.java
new file mode 100644
index 00000000..4c6fa942
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/cavp/KDFFeedbackNoCounterTests.java
@@ -0,0 +1,89 @@
+package org.spongycastle.crypto.test.cavp;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Properties;
+
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.generators.KDFFeedbackBytesGenerator;
+import org.spongycastle.crypto.params.KDFFeedbackParameters;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTestResult;
+import org.spongycastle.util.test.TestFailedException;
+
+public final class KDFFeedbackNoCounterTests
+ implements CAVPListener
+{
+ private PrintWriter out;
+
+ public void receiveCAVPVectors(String name, Properties config,
+ Properties vectors)
+ {
+
+
+ // create Mac based PRF from PRF property, create the KDF
+ final Mac prf = CAVPReader.createPRF(config);
+ final KDFFeedbackBytesGenerator gen = new KDFFeedbackBytesGenerator(prf);
+
+ final int count = Integer.parseInt(vectors.getProperty("COUNT"));
+ final int l = Integer.parseInt(vectors.getProperty("L"));
+ final byte[] ki = Hex.decode(vectors.getProperty("KI"));
+ final byte[] iv = Hex.decode(vectors.getProperty("IV"));
+ final byte[] fixedInputData = Hex.decode(vectors.getProperty("FixedInputData"));
+ final KDFFeedbackParameters params = KDFFeedbackParameters.createWithoutCounter(ki, iv, fixedInputData);
+ gen.init(params);
+
+ final byte[] koGenerated = new byte[l / 8];
+ gen.generateBytes(koGenerated, 0, koGenerated.length);
+
+ final byte[] koVectors = Hex.decode(vectors.getProperty("KO"));
+
+ compareKO(name, config, count, koGenerated, koVectors);
+ }
+
+ private static void compareKO(
+ String name, Properties config, int test, byte[] calculatedOKM, byte[] testOKM)
+ {
+
+ if (!Arrays.areEqual(calculatedOKM, testOKM))
+ {
+ throw new TestFailedException(new SimpleTestResult(
+ false, name + " using " + config + " test " + test + " failed"));
+
+ }
+ }
+
+ public void receiveCommentLine(String commentLine)
+ {
+// out.println("# " + commentLine);
+ }
+
+ public void receiveStart(String name)
+ {
+ // do nothing
+ }
+
+ public void receiveEnd()
+ {
+ out.println(" *** *** *** ");
+ }
+
+ public void setup()
+ {
+ try
+ {
+ out = new PrintWriter(new FileWriter("KDFFeedbackNoCounter.gen"));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public void tearDown()
+ {
+ out.close();
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/crypto/test/speedy/MacThroughputTest.java b/core/src/test/java/org/spongycastle/crypto/test/speedy/MacThroughputTest.java
new file mode 100644
index 00000000..ffbc673f
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/speedy/MacThroughputTest.java
@@ -0,0 +1,156 @@
+package org.spongycastle.crypto.test.speedy;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.KeyGenerationParameters;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.engines.AESFastEngine;
+import org.spongycastle.crypto.engines.NullEngine;
+import org.spongycastle.crypto.generators.Poly1305KeyGenerator;
+import org.spongycastle.crypto.macs.CMac;
+import org.spongycastle.crypto.macs.GMac;
+import org.spongycastle.crypto.macs.HMac;
+import org.spongycastle.crypto.macs.Poly1305;
+import org.spongycastle.crypto.macs.SipHash;
+import org.spongycastle.crypto.macs.SkeinMac;
+import org.spongycastle.crypto.modes.GCMBlockCipher;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+
+/**
+ * Microbenchmark of MACs on short, medium, long messages, with optional object creation cost.
+ */
+public class MacThroughputTest
+{
+
+ private static final long CLOCK_SPEED = 2400000000L;
+
+ private static final SecureRandom RANDOM = new SecureRandom();
+ private static Poly1305KeyGenerator kg = new Poly1305KeyGenerator();;
+
+ private static final byte[] SHORT_MESSAGE = new byte[16];
+ private static final byte[] MEDIUM_MESSAGE = new byte[256];
+ private static final byte[] LONG_MESSAGE = new byte[8192];
+ static
+ {
+ RANDOM.nextBytes(SHORT_MESSAGE);
+ RANDOM.nextBytes(MEDIUM_MESSAGE);
+ RANDOM.nextBytes(LONG_MESSAGE);
+ }
+
+ private static final int SHORT_MESSAGE_COUNT = 20000000;
+ private static final int MEDIUM_MESSAGE_COUNT = 2200000;
+ private static final int LONG_MESSAGE_COUNT = 80000;
+
+ static
+ {
+ kg.init(new KeyGenerationParameters(RANDOM, 256));
+ }
+
+ private static KeyParameter generatePoly1305Key()
+ {
+ return new KeyParameter(kg.generateKey());
+ }
+
+ public static void main(String[] args)
+ {
+ testMac(new HMac(new SHA1Digest()), new KeyParameter(generateNonce(20)), 3);
+ testMac(new SkeinMac(SkeinMac.SKEIN_512, 128), new KeyParameter(generateNonce(64)), 2);
+ testMac(new SipHash(), new KeyParameter(generateNonce(16)), 1);
+ testMac(new CMac(new AESFastEngine()), new KeyParameter(generateNonce(16)), 3);
+ testMac(new GMac(new GCMBlockCipher(new AESFastEngine())), new ParametersWithIV(new KeyParameter(
+ generateNonce(16)), generateNonce(16)), 5);
+ testMac(new Poly1305(new NullEngine(16)), new ParametersWithIV(generatePoly1305Key(), generateNonce(16)), 1);
+ testMac(new Poly1305(new AESFastEngine()), new ParametersWithIV(generatePoly1305Key(), generateNonce(16)), 1);
+ testMac(new Poly1305Reference(new NullEngine(16)), new ParametersWithIV(generatePoly1305Key(),
+ generateNonce(16)), 1);
+ }
+
+ private static byte[] generateNonce(int sizeBytes)
+ {
+ byte[] nonce = new byte[16];
+ RANDOM.nextBytes(nonce);
+ return nonce;
+ }
+
+ private static void testMac(Mac mac, CipherParameters params, int rateFactor)
+ {
+ System.out.println("=========================");
+
+ long total = testRun(mac, params, false, MEDIUM_MESSAGE, adjust(MEDIUM_MESSAGE_COUNT, rateFactor));
+ System.out.printf("%s Warmup 1 run time: %,d ms\n", mac.getAlgorithmName(), total / 1000000);
+ total = testRun(mac, params, false, MEDIUM_MESSAGE, adjust(MEDIUM_MESSAGE_COUNT, rateFactor));
+ System.out.printf("%s Warmup 2 run time: %,d ms\n", mac.getAlgorithmName(), total / 1000000);
+ System.gc();
+ try
+ {
+ Thread.sleep(1000);
+ } catch (InterruptedException e)
+ {
+ }
+
+ test("Short", mac, params, false, SHORT_MESSAGE, adjust(SHORT_MESSAGE_COUNT, rateFactor));
+ // test("Short", mac, params, true, SHORT_MESSAGE, adjust(SHORT_MESSAGE_COUNT, rateFactor));
+ test("Medium", mac, params, false, MEDIUM_MESSAGE, adjust(MEDIUM_MESSAGE_COUNT, rateFactor));
+ // test("Medium", mac, params, true, MEDIUM_MESSAGE, adjust(MEDIUM_MESSAGE_COUNT,
+ // rateFactor));
+ test("Long", mac, params, false, LONG_MESSAGE, adjust(LONG_MESSAGE_COUNT, rateFactor));
+ // test("Long", mac, params, true, LONG_MESSAGE, adjust(LONG_MESSAGE_COUNT, rateFactor));
+ }
+
+ private static int adjust(int iterationCount, int rateFactor)
+ {
+ return (int)(iterationCount * (1.0f / rateFactor));
+ }
+
+ private static void test(String name,
+ Mac mac,
+ CipherParameters params,
+ boolean initPerMessage,
+ byte[] message,
+ int adjustedCount)
+ {
+ System.out.println("=========================");
+ long total = testRun(mac, params, initPerMessage, message, adjustedCount);
+
+ long averageRuntime = total / adjustedCount;
+ System.out.printf("%s %-7s%s Total run time: %,d ms\n", mac.getAlgorithmName(), name, initPerMessage ? "*"
+ : " ", total / 1000000);
+ System.out.printf("%s %-7s%s Average run time: %,d ns\n", mac.getAlgorithmName(), name, initPerMessage ? "*"
+ : " ", averageRuntime);
+ final long mbPerSecond = (long)((double)message.length / averageRuntime * 1000000000 / (1024 * 1024));
+ System.out.printf("%s %-7s%s Average speed: %,d MB/s\n", mac.getAlgorithmName(), name, initPerMessage ? "*"
+ : " ", mbPerSecond);
+ System.out.printf("%s %-7s%s Average speed: %,f c/b\n", mac.getAlgorithmName(), name, initPerMessage ? "*"
+ : " ", CLOCK_SPEED / (double)(mbPerSecond * (1024 * 1024)));
+ }
+
+ private static long testRun(Mac mac,
+ CipherParameters params,
+ boolean initPerMessage,
+ byte[] message,
+ int adjustedCount)
+ {
+ byte[] out = new byte[mac.getMacSize()];
+
+ if (!initPerMessage)
+ {
+ mac.init(params);
+ }
+ long start = System.nanoTime();
+
+ for (int i = 0; i < adjustedCount; i++)
+ {
+ if (initPerMessage)
+ {
+ mac.init(params);
+ }
+ mac.update(message, 0, message.length);
+ mac.doFinal(out, 0);
+ }
+ long total = System.nanoTime() - start;
+ return total;
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/speedy/Poly1305Reference.java b/core/src/test/java/org/spongycastle/crypto/test/speedy/Poly1305Reference.java
new file mode 100644
index 00000000..a30c1116
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/speedy/Poly1305Reference.java
@@ -0,0 +1,292 @@
+package org.spongycastle.crypto.test.speedy;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.Mac;
+import org.spongycastle.crypto.generators.Poly1305KeyGenerator;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.ParametersWithIV;
+
+/**
+ * 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>
+ * This implementation is adapted from the public domain <a href="http://nacl.cr.yp.to/">nacl</a>
+ * <code>ref</code> implementation, and is probably too slow for real usage.
+ *
+ * @see Poly1305KeyGenerator
+ */
+public class Poly1305Reference
+ implements Mac
+{
+ private static final int BLOCK_SIZE = 16;
+ private static final int STATE_SIZE = BLOCK_SIZE + 1;
+ private static int[] minusp = {5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252};
+
+ private final BlockCipher cipher;
+
+ /** Encrypted nonce */
+ private final byte[] encryptedNonce = new byte[BLOCK_SIZE];
+
+ /** Private integer r *, expanded to 17 bytes */
+ private final int[] r = new int[STATE_SIZE];
+
+ /** Accumulated authenticator value */
+ private final int[] h = new int[STATE_SIZE];
+
+ /** Temp buffer for incorporating into authenticator */
+ private final int[] c = new int[STATE_SIZE];
+
+ private final byte[] singleByte = new byte[1];
+
+ /** Current block of buffered input */
+ private final byte[] currentBlock = new byte[BLOCK_SIZE];
+
+ /** Current offset in input buffer */
+ private int currentBlockOffset = 0;
+
+ public Poly1305Reference(BlockCipher cipher)
+ {
+ if (cipher.getBlockSize() != BLOCK_SIZE)
+ {
+ throw new IllegalArgumentException("Poly1305 requires a 128 bit block cipher.");
+ }
+ this.cipher = cipher;
+ }
+
+ public void init(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(byte[] key, byte[] nonce)
+ {
+ if (nonce.length != BLOCK_SIZE)
+ {
+ throw new IllegalArgumentException("Poly1305 requires a 128 bit IV.");
+ }
+ Poly1305KeyGenerator.checkKey(key);
+
+ // Expand private integer r
+ for (int i = 0; i < BLOCK_SIZE; i++)
+ {
+ r[i] = key[BLOCK_SIZE + i] & 0xFF;
+ }
+ r[BLOCK_SIZE] = 0;
+
+ // Calculate 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, this.encryptedNonce, 0);
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Poly1305-Ref-" + cipher.getAlgorithmName();
+ }
+
+ public int getMacSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public void update(byte in)
+ throws IllegalStateException
+ {
+ singleByte[0] = in;
+ update(singleByte, 0, 1);
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ throws DataLengthException,
+ IllegalStateException
+ {
+ int copied = 0;
+ while (len > copied)
+ {
+ if (currentBlockOffset == currentBlock.length)
+ {
+ processBlock();
+ currentBlockOffset = 0;
+ }
+
+ int toCopy = Math.min((len - copied), currentBlock.length - currentBlockOffset);
+ System.arraycopy(in, copied + inOff, currentBlock, currentBlockOffset, toCopy);
+ copied += toCopy;
+ currentBlockOffset += toCopy;
+ }
+
+ }
+
+ /**
+ * Add a full block of 16 bytes of data, padded to 17 bytes, to the MAC
+ */
+ private void processBlock()
+ {
+ for (int i = 0; i < currentBlockOffset; i++)
+ {
+ c[i] = currentBlock[i] & 0xFF;
+ }
+ c[currentBlockOffset] = 1;
+ for (int i = currentBlockOffset + 1; i < c.length; i++)
+ {
+ c[i] = 0;
+ }
+ add(h, c);
+ mulmod(h, r);
+ }
+
+ public int doFinal(byte[] out, 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();
+ }
+
+ freeze(h);
+
+ // Add encrypted nonce to result
+ for (int i = 0; i < BLOCK_SIZE; i++)
+ {
+ c[i] = encryptedNonce[i] & 0xFF;
+ }
+ c[BLOCK_SIZE] = 0;
+ add(h, c);
+
+ for (int i = 0; i < BLOCK_SIZE; i++)
+ {
+ out[outOff + i] = (byte)h[i];
+ }
+
+ reset();
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ currentBlockOffset = 0;
+ for (int i = 0; i < h.length; i++)
+ {
+ h[i] = 0;
+ }
+ }
+
+ // 130 bit math adapted from nacl ref implementation
+
+ /**
+ * 130 bit add with carry.
+ */
+ private static void add(int[] h, int[] c)
+ {
+ int u = 0;
+ for (int j = 0; j < 17; ++j)
+ {
+ u += h[j] + c[j];
+ h[j] = u & 255;
+ u >>= 8;
+ }
+ }
+
+ /**
+ * 130 bit multiplication mod 2^130-5
+ */
+ private void mulmod(int[] h, int[] r)
+ {
+ final int[] hr = c;
+
+ for (int i = 0; i < 17; ++i)
+ {
+ int u = 0;
+ /* Basic multiply to compute term i */
+ for (int j = 0; j <= i; ++j)
+ {
+ u += h[j] * r[i - j];
+ }
+
+ /*
+ * Modular reduction
+ *
+ * Shift overflow >> 130 bits == (>> 17 bytes = 136 bits) + (<< 6 bits = * 64)
+ *
+ * Reduction mod 2^130-5 leaves 5x remainder, so 64 * 5 = 320.
+ */
+ for (int j = i + 1; j < 17; ++j)
+ {
+ u += 320 * h[j] * r[i + 17 - j];
+ }
+ hr[i] = u;
+ }
+ System.arraycopy(hr, 0, h, 0, h.length);
+ squeeze(h);
+ }
+
+ /**
+ * Propagate carries following a modular multiplication.
+ */
+ private static void squeeze(int[] h)
+ {
+ int u = 0;
+ for (int j = 0; j < 16; ++j)
+ {
+ u += h[j];
+ h[j] = u & 255;
+ u >>= 8;
+ }
+ u += h[16];
+ h[16] = u & 3;
+ u = 5 * (u >> 2);
+ for (int j = 0; j < 16; ++j)
+ {
+ u += h[j];
+ h[j] = u & 255;
+ u >>= 8;
+ }
+ u += h[16];
+ h[16] = u;
+ }
+
+ /**
+ * Constant time correction of h to be &lt; p (2^130 - 5).
+ */
+ private void freeze(int[] h)
+ {
+ final int[] horig = c;
+ System.arraycopy(h, 0, horig, 0, h.length);
+
+ add(h, minusp);
+ final int negative = -(h[16] >> 7);
+ for (int j = 0; j < 17; ++j)
+ {
+ h[j] ^= negative & (horig[j] ^ h[j]);
+ }
+ }
+
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/speedy/ThreefishReferenceEngine.java b/core/src/test/java/org/spongycastle/crypto/test/speedy/ThreefishReferenceEngine.java
new file mode 100644
index 00000000..768bb954
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/speedy/ThreefishReferenceEngine.java
@@ -0,0 +1,395 @@
+package org.spongycastle.crypto.test.speedy;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.TweakableBlockCipherParameters;
+
+public class ThreefishReferenceEngine
+ implements BlockCipher
+{
+
+ /**
+ * The tweak input is always 128 bits
+ */
+ private static final int TWEAK_SIZE = 16;
+
+ private static long C_240 = 0x1BD11BDAA9FC1A22L;
+
+ private final int blocksize = 64;
+ private final int rounds = 72;
+ private final int words = 8;
+
+ private boolean forEncryption;
+
+ private long[] block = new long[words];
+
+ private int[][] rotations = R8;
+
+ /**
+ * Rotation constants Rd,j for Nw = 8.
+ */
+ private static final int[][] R8 = {
+ {46, 36, 19, 37},
+ {33, 27, 14, 42},
+ {17, 49, 36, 39},
+ {44, 9, 54, 56},
+ {39, 30, 34, 24},
+ {13, 50, 10, 17},
+ {25, 29, 39, 43},
+ {8, 35, 56, 22}};
+
+ private long[] t;
+
+ private long kw[];
+
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ if (params instanceof TweakableBlockCipherParameters)
+ {
+ init(forEncryption, (TweakableBlockCipherParameters)params);
+ }
+ else if (params instanceof KeyParameter)
+ {
+ init(forEncryption, new TweakableBlockCipherParameters((KeyParameter)params, new byte[TWEAK_SIZE]));
+ }
+ else
+ {
+ throw new IllegalArgumentException("Invalid parameter passed to Threefish init - "
+ + params.getClass().getName());
+ }
+ }
+
+ public void init(boolean forEncryption, TweakableBlockCipherParameters params)
+ throws IllegalArgumentException
+ {
+ // TODO: Remove some of the NPEs that can be avoided in the Params
+ // classes
+ if ((params.getKey() == null) || (params.getKey().getKey() == null)
+ || (params.getKey().getKey().length != blocksize))
+ {
+ throw new IllegalArgumentException("Threefish key must be same size as block (%d bytes)" + blocksize);
+ }
+
+ if ((params.getTweak() == null) || (params.getTweak().length != TWEAK_SIZE))
+ {
+ throw new IllegalArgumentException("Threefish tweak must be %d bytes" + TWEAK_SIZE);
+ }
+
+ this.forEncryption = forEncryption;
+
+ generateKeySchedule(params.getKey().getKey(), params.getTweak());
+ }
+
+ private void generateKeySchedule(byte[] key, byte[] tweak)
+ {
+ // TODO: This key schedule can/should be generated incrementally/on demand during encrypt/decrypt
+ // to reduce memory overhead (currently 1.2MB = (rounds/4+1)=19 * words=8 * 8 bytes/word)
+
+ t = new long[3];
+ t[0] = BytesToWord(tweak, 0);
+ t[1] = BytesToWord(tweak, 8);
+ t[2] = t[0] ^ t[1];
+
+ kw = new long[words + 1];
+
+ long knw = C_240;
+ for (int i = 0; i < words; i++)
+ {
+ kw[i] = BytesToWord(key, i * 8);
+ knw = knw ^ kw[i];
+ }
+ kw[kw.length - 1] = knw;
+ }
+
+ private static long BytesToWord(byte[] bytes, int off)
+ {
+ 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;
+ }
+
+ private static void WordToBytes(long word, byte[] bytes, int off)
+ {
+ 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);
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Threefish";
+ }
+
+ public int getBlockSize()
+ {
+ return blocksize;
+ }
+
+ public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
+ throws DataLengthException,
+ IllegalStateException
+ {
+ // TODO: Check init state
+ if (kw == null)
+ {
+ throw new IllegalStateException("Threefish engine not initialised");
+ }
+
+ if ((inOff + blocksize) > in.length)
+ {
+ throw new DataLengthException("Input buffer too short");
+ }
+
+ if ((outOff + blocksize) > out.length)
+ {
+ throw new DataLengthException("Output buffer too short");
+ }
+
+ if (forEncryption)
+ {
+ unpackBlock(in, inOff);
+ encryptBlock();
+ packBlock(out, outOff);
+ }
+ else
+ {
+ unpackBlock(in, inOff);
+ decryptBlock();
+ packBlock(out, outOff);
+ }
+
+ return blocksize;
+ }
+
+ private void decryptBlock()
+ {
+ for (int d = rounds; d > 0; d--)
+ {
+ // Add subkey every 4 rounds
+ if ((d % 4) == 0)
+ {
+ uninjectSubkey(d / 4);
+ }
+
+ // Permute
+ unpermute();
+
+ // Mix
+ for (int j = 0; j < words / 2; j++)
+ {
+ unmix(j, d - 1);
+ }
+ }
+
+ // Remove first subkey
+ uninjectSubkey(0);
+ }
+
+ private void injectSubkey(int s)
+ {
+ for (int i = 0; i < (words - 3); i++)
+ {
+ block[i] += kw[(s + i) % (words + 1)];
+ }
+ block[words - 3] += kw[(s + words - 3) % (words + 1)] + t[s % 3];
+ block[words - 2] += kw[(s + words - 2) % (words + 1)] + t[(s + 1) % 3];
+ block[words - 1] += kw[(s + words - 1) % (words + 1)] + s;
+ }
+
+ private void uninjectSubkey(int s)
+ {
+ for (int i = 0; i < (words - 3); i++)
+ {
+ block[i] -= kw[(s + i) % (words + 1)];
+ }
+ block[words - 3] -= kw[(s + words - 3) % (words + 1)] + t[s % 3];
+ block[words - 2] -= kw[(s + words - 2) % (words + 1)] + t[(s + 1) % 3];
+ block[words - 1] -= kw[(s + words - 1) % (words + 1)] + s;
+ }
+
+ private void encryptBlock()
+ {
+ for (int d = 0; d < rounds; d++)
+ {
+ // Add subkey every 4 rounds
+ if ((d % 4) == 0)
+ {
+ injectSubkey(d / 4);
+ }
+
+ // Mix
+ for (int j = 0; j < words / 2; j++)
+ {
+ mix(j, d);
+ }
+
+ // Permute
+ permute();
+ }
+
+ // Final key addition
+ injectSubkey(rounds / 4);
+ }
+
+ private void permute()
+ {
+ // Permute in place for Nw = 8
+ long f0 = block[0];
+ long f3 = block[3];
+
+ block[0] = block[2];
+ block[1] = block[1];
+ block[2] = block[4];
+ block[3] = block[7];
+ block[4] = block[6];
+ block[5] = block[5];
+ block[6] = f0;
+ block[7] = f3;
+ }
+
+ private void unpermute()
+ {
+ // TODO: Change these to tables
+ // Permute in place for Nw = 8
+ long f6 = block[6];
+ long f7 = block[7];
+
+ block[7] = block[3];
+ block[6] = block[4];
+ block[5] = block[5];
+ block[4] = block[2];
+ block[3] = f7;
+ block[2] = block[0];
+ block[1] = block[1];
+ block[0] = f6;
+ }
+
+ private void mix(int j, int d)
+ {
+ // ed,2j and ed,2j+1
+ int b0 = 2 * j;
+ int b1 = b0 + 1;
+
+ // y0 = x0 + x1
+ block[b0] = block[b0] + block[b1];
+
+ // y1 = (x1 <<< R(d mod 8,j)) xor y0
+ block[b1] = Long.rotateLeft(block[b1], rotations[d % 8][j]) ^ block[b0];
+ }
+
+ private void unmix(int j, int d)
+ {
+ // ed,2j and ed,2j+1
+ int b0 = 2 * j;
+ int b1 = b0 + 1;
+
+ // x1 = (y1 ^ y0) >>> R(d mod 8, j))
+ block[b1] = Long.rotateRight(block[b1] ^ block[b0], rotations[d % 8][j]);
+
+ // x0 = y0 - x1
+ block[b0] = block[b0] - block[b1];
+
+ }
+
+ public static void main(String[] args)
+ {
+ ThreefishReferenceEngine engine = new ThreefishReferenceEngine();
+ engine.fu();
+ }
+
+ private void fu()
+ {
+ block[0] = 0x12;
+ block[1] = 0x34;
+ block[2] = 0x56;
+ block[3] = 0x78;
+ block[4] = 0x90;
+ block[5] = 0xAB;
+ block[6] = 0xCD;
+ block[7] = 0xEF;
+
+ for (int i = 0; i < block.length; i++)
+ {
+ System.err.println(i + " : " + Long.toHexString(block[i]));
+ }
+ mix(0, 4);
+ System.err.println("=========");
+ for (int i = 0; i < block.length; i++)
+ {
+ System.err.println(i + " : " + Long.toHexString(block[i]));
+ }
+ unmix(0, 4);
+ System.err.println("=========");
+ for (int i = 0; i < block.length; i++)
+ {
+ System.err.println(i + " : " + Long.toHexString(block[i]));
+ }
+ permute();
+ System.err.println("=========");
+ for (int i = 0; i < block.length; i++)
+ {
+ System.err.println(i + " : " + Long.toHexString(block[i]));
+ }
+ unpermute();
+ System.err.println("=========");
+ for (int i = 0; i < block.length; i++)
+ {
+ System.err.println(i + " : " + Long.toHexString(block[i]));
+ }
+ generateKeySchedule(new byte[blocksize], new byte[TWEAK_SIZE]);
+ injectSubkey(5);
+ System.err.println("=========");
+ for (int i = 0; i < block.length; i++)
+ {
+ System.err.println(i + " : " + Long.toHexString(block[i]));
+ }
+ uninjectSubkey(5);
+ System.err.println("=========");
+ for (int i = 0; i < block.length; i++)
+ {
+ System.err.println(i + " : " + Long.toHexString(block[i]));
+ }
+ }
+
+ private void packBlock(byte[] out, int outOff)
+ {
+ for (int i = 0; i < block.length; i++)
+ {
+ WordToBytes(block[i], out, outOff + (i * 8));
+ }
+ }
+
+ private long[] unpackBlock(byte[] bytes, int index)
+ {
+ for (int i = 0; i < block.length; i++)
+ {
+ block[i] = BytesToWord(bytes, index + (i * 8));
+ }
+ return block;
+ }
+
+ public void reset()
+ {
+ }
+
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/test/speedy/ThroughputTest.java b/core/src/test/java/org/spongycastle/crypto/test/speedy/ThroughputTest.java
new file mode 100644
index 00000000..69b942fc
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/test/speedy/ThroughputTest.java
@@ -0,0 +1,203 @@
+package org.spongycastle.crypto.test.speedy;
+
+import java.io.IOException;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.engines.AESFastEngine;
+import org.spongycastle.crypto.engines.ThreefishEngine;
+import org.spongycastle.crypto.params.KeyParameter;
+import org.spongycastle.crypto.params.TweakableBlockCipherParameters;
+import org.spongycastle.util.encoders.Hex;
+
+public class ThroughputTest
+{
+
+ private static final int DATA_SIZE = 100 * 1024 * 1024;
+ private static final int RUNS = 1;
+ private static final long CLOCK_SPEED = 2400000000L;
+
+ private static SecureRandom rand = new SecureRandom();
+
+ public static void main(String[] args)
+ throws InterruptedException, IOException
+ {
+// testTF_1024_1();
+// testTF_1024_2();
+ testTF_512_1();
+ testTF_512_2();
+// testTF_256_1();
+// testTF_256_2();
+ System.out.println("Initialising test data.");
+ byte[] input = new byte[DATA_SIZE];
+ rand.nextBytes(input);
+
+ System.out.println("Init complete.");
+// speedTestCipher(new ThreefishEngine(ThreefishEngine.BLOCKSIZE_256), input);
+ speedTestCipher(new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512), input);
+// speedTestCipher(new Skein3FishEngine(), input);
+// speedTestCipher(new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024), input);
+// speedTestCipher(new ThreefishReferenceEngine(), input);
+ speedTestCipher(new AESFastEngine(), input);
+// speedTestCipher(new TwofishEngine(), input);
+// speedTestCipher(new BlowfishEngine(), input);
+ }
+
+ private static void testTF_512_1()
+ throws IOException
+ {
+ byte[] key = new byte[64];
+ byte[] tweak = new byte[16];
+ byte[] plaintext = new byte[64];
+ byte[] expected = Hex.decode("b1a2bbc6ef6025bc40eb3822161f36e375d1bb0aee3186fbd19e47c5d479947b7bc2f8586e35f0cff7e7f03084b0b7b1f1ab3961a580a3e97eb41ea14a6d7bbe");
+
+ runTestVector("Threefish-512-1: Fast", key, tweak, plaintext, expected, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512));
+ runTestVector("Threefish-512-1: Reference", key, tweak, plaintext, expected, new ThreefishReferenceEngine());
+ }
+
+ private static void testTF_256_1()
+ throws IOException
+ {
+ byte[] key = new byte[32];
+ byte[] tweak = new byte[16];
+ byte[] plaintext = new byte[32];
+ byte[] expected = Hex.decode("84da2a1f8beaee947066ae3e3103f1ad536db1f4a1192495116b9f3ce6133fd8");
+
+ runTestVector("Threefish-256-1: ", key, tweak, plaintext, expected, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_256));
+ }
+
+ private static void testTF_1024_1()
+ throws IOException
+ {
+ byte[] key = new byte[128];
+ byte[] tweak = new byte[16];
+ byte[] plaintext = new byte[128];
+ byte[] expected = Hex.decode("f05c3d0a3d05b304f785ddc7d1e036015c8aa76e2f217b06c6e1544c0bc1a90df0accb9473c24e0fd54fea68057f43329cb454761d6df5cf7b2e9b3614fbd5a20b2e4760b40603540d82eabc5482c171c832afbe68406bc39500367a592943fa9a5b4a43286ca3c4cf46104b443143d560a4b230488311df4feef7e1dfe8391e");
+
+ runTestVector("Threefish-1024-1: ", key, tweak, plaintext, expected, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024));
+ }
+
+ private static void runTestVector(String name, byte[] key, byte[] tweak, byte[] plaintext, byte[] expected, BlockCipher cipher)
+ {
+ System.out.println("====");
+ System.out.println(name + ": ");
+ cipher.init(true, new TweakableBlockCipherParameters(new KeyParameter(key), tweak));
+
+ byte[] ciphertext = new byte[key.length];
+ cipher.processBlock(plaintext, 0, ciphertext, 0);
+
+ System.out.println("Plaintext : " + new String(Hex.encode(plaintext)));
+ System.out.println("Expected : " + new String(Hex.encode(expected)));
+ System.out.println("Ciphertext : " + new String(Hex.encode(ciphertext)));
+ System.out.println(" Encrypt : " + org.spongycastle.util.Arrays.areEqual(expected, ciphertext));
+
+ cipher.init(false, new TweakableBlockCipherParameters(new KeyParameter(key), tweak));
+ byte[] replain = new byte[plaintext.length];
+ cipher.processBlock(ciphertext, 0, replain, 0);
+
+ System.out.println("Replain : " + new String(Hex.encode(replain)));
+ System.out.println(" Decrypt : " + org.spongycastle.util.Arrays.areEqual(plaintext, replain));
+ }
+
+ private static void testTF_512_2()
+ throws IOException
+ {
+ byte[] key = Hex.decode("101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f");
+ byte[] tweak = Hex.decode("000102030405060708090a0b0c0d0e0f");
+ byte[] plaintext = Hex.decode("fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0");
+ byte[] expected = Hex.decode("e304439626d45a2cb401cad8d636249a6338330eb06d45dd8b36b90e97254779272a0a8d99463504784420ea18c9a725af11dffea10162348927673d5c1caf3d");
+
+ runTestVector("Threefish-512-2: Fast", key, tweak, plaintext, expected, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512));
+ runTestVector("Threefish-512-2: Reference", key, tweak, plaintext, expected, new ThreefishReferenceEngine());
+ }
+
+ private static void testTF_256_2()
+ throws IOException
+ {
+ byte[] key = Hex.decode("101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f");
+ byte[] tweak = Hex.decode("000102030405060708090a0b0c0d0e0f");
+ byte[] plaintext = Hex.decode("FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0");
+ byte[] expected = Hex.decode("e0d091ff0eea8fdfc98192e62ed80ad59d865d08588df476657056b5955e97df");
+
+ runTestVector("Threefish-256-2: ", key, tweak, plaintext, expected, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_256));
+ }
+
+ private static void testTF_1024_2()
+ throws IOException
+ {
+ byte[] key = Hex.decode("101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f");
+ byte[] tweak = Hex.decode("000102030405060708090a0b0c0d0e0f");
+ byte[] plaintext = Hex.decode("fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0afaeadacabaaa9a8a7a6a5a4a3a2a1a09f9e9d9c9b9a999897969594939291908f8e8d8c8b8a89888786858483828180");
+ byte[] expected = Hex.decode("a6654ddbd73cc3b05dd777105aa849bce49372eaaffc5568d254771bab85531c94f780e7ffaae430d5d8af8c70eebbe1760f3b42b737a89cb363490d670314bd8aa41ee63c2e1f45fbd477922f8360b388d6125ea6c7af0ad7056d01796e90c83313f4150a5716b30ed5f569288ae974ce2b4347926fce57de44512177dd7cde");
+
+ runTestVector("Threefish-1024-2: ", key, tweak, plaintext, expected, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024));
+ }
+
+ private static void speedTestCipher(BlockCipher cipher, byte[] input)
+ throws InterruptedException
+ {
+ byte[] key = new byte[cipher.getBlockSize()];
+ rand.nextBytes(key);
+
+ cipher.init(true, new KeyParameter(key));
+ speedTestCipherForMode("encrypt", cipher, input);
+ cipher.init(false, new KeyParameter(key));
+ speedTestCipherForMode("decrypt", cipher, input);
+ }
+
+ private static void speedTestCipherForMode(String mode, BlockCipher cipher, byte[] input)
+ throws InterruptedException
+ {
+ System.out.println("======");
+ System.out.println("Testing " + cipher.getAlgorithmName() + " " + cipher.getBlockSize() * 8 + " " + mode);
+ System.out.println("Beginning warmup run.");
+
+ long warmup = testCipher(cipher, input);
+ System.out.println("Warmup run 1 in " + (warmup / 1000000) + "ms");
+ Thread.sleep(100);
+ warmup = testCipher(cipher, input);
+ System.out.println("Warmup run 2 in " + (warmup / 1000000) + "ms");
+
+ System.gc();
+ Thread.sleep(500);
+ System.gc();
+ Thread.sleep(500);
+
+ System.out.println("Beginning " + RUNS + " hot runs.");
+
+ long[] runtimes = new long[RUNS];
+ long total = 0;
+ for (int i = 0; i < RUNS; i++)
+ {
+ runtimes[i] = testCipher(cipher, input);
+ total += runtimes[i];
+ System.out.println("Run " + (i + 1) + ": " + runtimes[i] / 100000 + "ms");
+ }
+ long averageRuntime = total / RUNS;
+ System.out.println(cipher.getAlgorithmName() + " Average run time: " + averageRuntime / 1000000 + "ms");
+ final long mbPerSecond = (long)((double)DATA_SIZE / averageRuntime * 1000000000 / (1024 * 1024));
+ System.out.println(cipher.getAlgorithmName() + " Average speed: " + mbPerSecond + " MB/s");
+ System.out.println(cipher.getAlgorithmName() + " Average speed: " + CLOCK_SPEED / (double)(mbPerSecond * (1024 * 1024)) + " c/b");
+ }
+
+ private static long testCipher(BlockCipher cipher, byte[] input)
+ {
+ long start = System.nanoTime();
+ int blockSize = cipher.getBlockSize();
+ byte[] out = new byte[blockSize];
+
+ for (int i = 0; i < (input.length - blockSize); i += blockSize)
+ {
+ cipher.processBlock(input, i, out, 0);
+// byte[] test = new byte[blockSize];
+// System.arraycopy(input, i, test, 0, test.length);
+// if (!Arrays.equals(out, test)) {
+// System.err.println(":(");
+// }
+ }
+
+ long end = System.nanoTime();
+ long delta = end - start;
+ return delta;
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/AllTests.java b/core/src/test/java/org/spongycastle/crypto/tls/test/AllTests.java
new file mode 100644
index 00000000..6970aa1d
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/AllTests.java
@@ -0,0 +1,23 @@
+package org.spongycastle.crypto.tls.test;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests
+{
+ public static void main(String[] args)
+ throws Exception
+ {
+ junit.textui.TestRunner.run(suite());
+ }
+
+ public static Test suite()
+ throws Exception
+ {
+ TestSuite suite = new TestSuite("TLS tests");
+
+ suite.addTest(BasicTlsTest.suite());
+
+ return suite;
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/BasicTlsTest.java b/core/src/test/java/org/spongycastle/crypto/tls/test/BasicTlsTest.java
new file mode 100644
index 00000000..91194992
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/BasicTlsTest.java
@@ -0,0 +1,200 @@
+package org.spongycastle.crypto.tls.test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.net.Socket;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.spongycastle.crypto.tls.AlertDescription;
+import org.spongycastle.crypto.tls.AlertLevel;
+import org.spongycastle.crypto.tls.AlwaysValidVerifyer;
+import org.spongycastle.crypto.tls.Certificate;
+import org.spongycastle.crypto.tls.CipherSuite;
+import org.spongycastle.crypto.tls.DefaultTlsClient;
+import org.spongycastle.crypto.tls.LegacyTlsClient;
+import org.spongycastle.crypto.tls.TlsAuthentication;
+import org.spongycastle.crypto.tls.TlsClient;
+import org.spongycastle.crypto.tls.TlsClientProtocol;
+import org.spongycastle.crypto.tls.TlsFatalAlert;
+import org.spongycastle.crypto.tls.TlsKeyExchange;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+
+public class BasicTlsTest
+ extends TestCase
+{
+ private static final int PORT_NO = 8003;
+
+ // private static final String CLIENT = "client";
+ // private static final char[] CLIENT_PASSWORD = "clientPassword".toCharArray();
+ // private static final char[] SERVER_PASSWORD = "serverPassword".toCharArray();
+ // private static final char[] TRUST_STORE_PASSWORD = "trustPassword".toCharArray();
+
+ public void testConnection()
+ throws Exception
+ {
+ String vmVersion = System.getProperty("java.specification.version");
+
+ if (vmVersion == null || !vmVersion.equals("1.7"))
+ {
+ return; // only works on later VMs.
+ }
+
+ Thread server = new HTTPSServerThread();
+
+ server.start();
+
+ Thread.yield();
+
+ AlwaysValidVerifyer verifyer = new AlwaysValidVerifyer();
+ Socket s = null;
+
+ for (int i = 0; s == null && i != 3; i++)
+ {
+ Thread.sleep(1000);
+
+ try
+ {
+ s = new Socket("localhost", PORT_NO);
+ }
+ catch (IOException e)
+ {
+ // ignore
+ }
+ }
+
+ if (s == null)
+ {
+ throw new IOException("unable to connect");
+ }
+
+ // long time = System.currentTimeMillis();
+ TlsClientProtocol protocol = new TlsClientProtocol(s.getInputStream(), s.getOutputStream());
+ protocol.connect(new LegacyTlsClient(verifyer));
+ InputStream is = protocol.getInputStream();
+ OutputStream os = protocol.getOutputStream();
+
+ os.write("GET / HTTP/1.1\r\n\r\n".getBytes());
+
+ // time = System.currentTimeMillis();
+ byte[] buf = new byte[4096];
+ int read = 0;
+ int total = 0;
+
+ while ((read = is.read(buf, total, buf.length - total)) > 0)
+ {
+ total += read;
+ }
+
+ is.close();
+
+ byte[] expected = Hex.decode("485454502f312e3120323030204f4b0d0a436f6e74656e742d547970653a20746578742f68"
+ + "746d6c0d0a0d0a3c68746d6c3e0d0a3c626f64793e0d0a48656c6c6f20576f726c64210d0a3c2f626f64793e0d0a3c2f"
+ + "68746d6c3e0d0a");
+ assertEquals(total, expected.length);
+
+ byte[] tmp = new byte[expected.length];
+ System.arraycopy(buf, 0, tmp, 0, total);
+ assertTrue(Arrays.areEqual(expected, tmp));
+ }
+
+ public void testRSAConnectionClient()
+ throws Exception
+ {
+ MyTlsClient client = new MyTlsClient(null);
+
+ checkConnectionClient(client, CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA, TlsTestUtils.rsaCertData);
+ checkConnectionClient(client, CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, TlsTestUtils.rsaCertData);
+ checkConnectionClient(client, CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA, TlsTestUtils.rsaCertData);
+ checkConnectionClient(client, CipherSuite.TLS_RSA_WITH_RC4_128_SHA, TlsTestUtils.rsaCertData);
+
+ try
+ {
+ checkConnectionClient(client, CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA, TlsTestUtils.dudRsaCertData);
+
+ fail("dud certificate not caught");
+ }
+ catch (TlsFatalAlert e)
+ {
+ assertEquals(AlertDescription.certificate_unknown, e.getAlertDescription());
+ }
+
+ try
+ {
+ checkConnectionClient(client, CipherSuite.TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA, TlsTestUtils.rsaCertData);
+
+ fail("wrong certificate not caught");
+ }
+ catch (TlsFatalAlert e)
+ {
+ assertEquals(AlertDescription.internal_error, e.getAlertDescription());
+ }
+ }
+
+ private void checkConnectionClient(TlsClient client, int cipherSuite, byte[] encCert)
+ throws Exception
+ {
+ client.notifySelectedCipherSuite(cipherSuite);
+
+ TlsKeyExchange keyExchange = client.getKeyExchange();
+
+ keyExchange
+ .processServerCertificate(new Certificate(
+ new org.spongycastle.asn1.x509.Certificate[]{org.spongycastle.asn1.x509.Certificate
+ .getInstance(encCert)}));
+ }
+
+ public static TestSuite suite()
+ {
+ return new TestSuite(BasicTlsTest.class);
+ }
+
+ public static void main(String[] args)
+ throws Exception
+ {
+ junit.textui.TestRunner.run(suite());
+ }
+
+ static class MyTlsClient
+ extends DefaultTlsClient
+ {
+
+ public void notifyAlertRaised(short alertLevel, short alertDescription, String message, Exception cause)
+ {
+ PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
+ out.println("TLS client raised alert (AlertLevel." + alertLevel + ", AlertDescription." + alertDescription
+ + ")");
+ if (message != null)
+ {
+ out.println(message);
+ }
+ if (cause != null)
+ {
+ cause.printStackTrace(out);
+ }
+ }
+
+ public void notifyAlertReceived(short alertLevel, short alertDescription)
+ {
+ PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
+ out.println("TLS client received alert (AlertLevel." + alertLevel + ", AlertDescription."
+ + alertDescription + ")");
+ }
+
+ private final TlsAuthentication authentication;
+
+ MyTlsClient(TlsAuthentication authentication)
+ {
+ this.authentication = authentication;
+ }
+
+ public TlsAuthentication getAuthentication()
+ throws IOException
+ {
+ return authentication;
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/DTLSClientTest.java b/core/src/test/java/org/spongycastle/crypto/tls/test/DTLSClientTest.java
new file mode 100644
index 00000000..d091a132
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/DTLSClientTest.java
@@ -0,0 +1,80 @@
+package org.spongycastle.crypto.tls.test;
+
+import java.io.IOException;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.tls.DTLSClientProtocol;
+import org.spongycastle.crypto.tls.DTLSTransport;
+import org.spongycastle.crypto.tls.DatagramTransport;
+import org.spongycastle.crypto.tls.TlsClient;
+import org.spongycastle.crypto.tls.TlsSession;
+import org.spongycastle.crypto.tls.UDPTransport;
+
+/**
+ * A simple test designed to conduct a DTLS handshake with an external DTLS server.
+ * <p/>
+ * Please refer to GnuTLSSetup.txt or OpenSSLSetup.txt, and x509-*.pem files in this package for
+ * help configuring an external DTLS server.
+ */
+public class DTLSClientTest
+{
+ private static final SecureRandom secureRandom = new SecureRandom();
+
+ public static void main(String[] args)
+ throws Exception
+ {
+ InetAddress address = InetAddress.getLocalHost();
+ int port = 5556;
+
+ TlsSession session = createSession(address, port);
+
+ MockDTLSClient client = new MockDTLSClient(session);
+
+ DTLSTransport dtls = openDTLSConnection(address, port, client);
+
+ System.out.println("Receive limit: " + dtls.getReceiveLimit());
+ System.out.println("Send limit: " + dtls.getSendLimit());
+
+ // Send and hopefully receive a packet back
+
+ byte[] request = "Hello World!\n".getBytes("UTF-8");
+ dtls.send(request, 0, request.length);
+
+ byte[] response = new byte[dtls.getReceiveLimit()];
+ int received = dtls.receive(response, 0, response.length, 30000);
+ if (received >= 0)
+ {
+ System.out.println(new String(response, 0, received, "UTF-8"));
+ }
+
+ dtls.close();
+ }
+
+ private static TlsSession createSession(InetAddress address, int port)
+ throws IOException
+ {
+ MockDTLSClient client = new MockDTLSClient(null);
+ DTLSTransport dtls = openDTLSConnection(address, port, client);
+ TlsSession session = client.getSessionToResume();
+ dtls.close();
+ return session;
+ }
+
+ private static DTLSTransport openDTLSConnection(InetAddress address, int port, TlsClient client)
+ throws IOException
+ {
+ DatagramSocket socket = new DatagramSocket();
+ socket.connect(address, port);
+
+ int mtu = 1500;
+ DatagramTransport transport = new UDPTransport(socket, mtu);
+ transport = new UnreliableDatagramTransport(transport, secureRandom, 0, 0);
+ transport = new LoggingDatagramTransport(transport, System.out);
+
+ DTLSClientProtocol protocol = new DTLSClientProtocol(secureRandom);
+
+ return protocol.connect(client, transport);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/DTLSProtocolTest.java b/core/src/test/java/org/spongycastle/crypto/tls/test/DTLSProtocolTest.java
new file mode 100644
index 00000000..838e65cd
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/DTLSProtocolTest.java
@@ -0,0 +1,102 @@
+package org.spongycastle.crypto.tls.test;
+
+import java.security.SecureRandom;
+
+import junit.framework.TestCase;
+
+import org.spongycastle.crypto.tls.DTLSClientProtocol;
+import org.spongycastle.crypto.tls.DTLSServerProtocol;
+import org.spongycastle.crypto.tls.DTLSTransport;
+import org.spongycastle.crypto.tls.DatagramTransport;
+import org.spongycastle.util.Arrays;
+
+public class DTLSProtocolTest
+ extends TestCase
+{
+ public void testClientServer()
+ throws Exception
+ {
+ SecureRandom secureRandom = new SecureRandom();
+
+ DTLSClientProtocol clientProtocol = new DTLSClientProtocol(secureRandom);
+ DTLSServerProtocol serverProtocol = new DTLSServerProtocol(secureRandom);
+
+ MockDatagramAssociation network = new MockDatagramAssociation(1500);
+
+ ServerThread serverThread = new ServerThread(serverProtocol, network.getServer());
+ serverThread.start();
+
+ DatagramTransport clientTransport = network.getClient();
+
+ clientTransport = new UnreliableDatagramTransport(clientTransport, secureRandom, 0, 0);
+
+ clientTransport = new LoggingDatagramTransport(clientTransport, System.out);
+
+ MockDTLSClient client = new MockDTLSClient(null);
+
+ DTLSTransport dtlsClient = clientProtocol.connect(client, clientTransport);
+
+ for (int i = 1; i <= 10; ++i)
+ {
+ byte[] data = new byte[i];
+ Arrays.fill(data, (byte)i);
+ dtlsClient.send(data, 0, data.length);
+ }
+
+ byte[] buf = new byte[dtlsClient.getReceiveLimit()];
+ while (dtlsClient.receive(buf, 0, buf.length, 100) >= 0)
+ {
+ }
+
+ dtlsClient.close();
+
+ serverThread.shutdown();
+ }
+
+ static class ServerThread
+ extends Thread
+ {
+ private final DTLSServerProtocol serverProtocol;
+ private final DatagramTransport serverTransport;
+ private volatile boolean isShutdown = false;
+
+ ServerThread(DTLSServerProtocol serverProtocol, DatagramTransport serverTransport)
+ {
+ this.serverProtocol = serverProtocol;
+ this.serverTransport = serverTransport;
+ }
+
+ public void run()
+ {
+ try
+ {
+ MockDTLSServer server = new MockDTLSServer();
+ DTLSTransport dtlsServer = serverProtocol.accept(server, serverTransport);
+ byte[] buf = new byte[dtlsServer.getReceiveLimit()];
+ while (!isShutdown)
+ {
+ int length = dtlsServer.receive(buf, 0, buf.length, 1000);
+ if (length >= 0)
+ {
+ dtlsServer.send(buf, 0, length);
+ }
+ }
+ dtlsServer.close();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ void shutdown()
+ throws InterruptedException
+ {
+ if (!isShutdown)
+ {
+ isShutdown = true;
+ this.join();
+ }
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/DTLSServerTest.java b/core/src/test/java/org/spongycastle/crypto/tls/test/DTLSServerTest.java
new file mode 100644
index 00000000..5296ce52
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/DTLSServerTest.java
@@ -0,0 +1,76 @@
+package org.spongycastle.crypto.tls.test;
+
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.SocketTimeoutException;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.tls.DTLSServerProtocol;
+import org.spongycastle.crypto.tls.DTLSTransport;
+import org.spongycastle.crypto.tls.DatagramTransport;
+import org.spongycastle.crypto.tls.UDPTransport;
+
+/**
+ * A simple test designed to conduct a DTLS handshake with an external DTLS client.
+ * <p/>
+ * Please refer to GnuTLSSetup.txt or OpenSSLSetup.txt, and x509-*.pem files in this package for
+ * help configuring an external DTLS client.
+ */
+public class DTLSServerTest
+{
+ public static void main(String[] args)
+ throws Exception
+ {
+ InetAddress address = InetAddress.getLocalHost();
+ int port = 5556;
+
+ int mtu = 1500;
+
+ SecureRandom secureRandom = new SecureRandom();
+
+ DTLSServerProtocol serverProtocol = new DTLSServerProtocol(secureRandom);
+
+ byte[] data = new byte[mtu];
+ DatagramPacket packet = new DatagramPacket(data, mtu);
+
+ DatagramSocket socket = new DatagramSocket(port, address);
+ socket.receive(packet);
+
+ System.out.println("Accepting connection from " + packet.getAddress().getHostAddress() + ":" + port);
+ socket.connect(packet.getAddress(), packet.getPort());
+
+ /*
+ * NOTE: For simplicity, and since we don't yet have HelloVerifyRequest support, we just
+ * discard the initial packet, which the client should re-send anyway.
+ */
+
+ DatagramTransport transport = new UDPTransport(socket, mtu);
+
+ // Uncomment to see packets
+// transport = new LoggingDatagramTransport(transport, System.out);
+
+ MockDTLSServer server = new MockDTLSServer();
+ DTLSTransport dtlsServer = serverProtocol.accept(server, transport);
+
+ byte[] buf = new byte[dtlsServer.getReceiveLimit()];
+
+ while (!socket.isClosed())
+ {
+ try
+ {
+ int length = dtlsServer.receive(buf, 0, buf.length, 60000);
+ if (length >= 0)
+ {
+ System.out.write(buf, 0, length);
+ dtlsServer.send(buf, 0, length);
+ }
+ }
+ catch (SocketTimeoutException ste)
+ {
+ }
+ }
+
+ dtlsServer.close();
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/DTLSTestCase.java b/core/src/test/java/org/spongycastle/crypto/tls/test/DTLSTestCase.java
new file mode 100644
index 00000000..ebb9c30b
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/DTLSTestCase.java
@@ -0,0 +1,248 @@
+package org.spongycastle.crypto.tls.test;
+
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.spongycastle.crypto.tls.DTLSClientProtocol;
+import org.spongycastle.crypto.tls.DTLSServerProtocol;
+import org.spongycastle.crypto.tls.DTLSTransport;
+import org.spongycastle.crypto.tls.DatagramTransport;
+import org.spongycastle.crypto.tls.ProtocolVersion;
+import org.spongycastle.util.Arrays;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.junit.Assert.*;
+
+@RunWith(Parameterized.class)
+public class DTLSTestCase
+{
+ // Make the access to constants less verbose
+ static abstract class C extends TlsTestConfig {}
+
+ @Parameterized.Parameters(name = "{index}: {1}")
+ public static Collection<Object[]> data() {
+ List<Object[]> params = new ArrayList<Object[]>();
+ addVersionTests(params, ProtocolVersion.DTLSv10);
+ addVersionTests(params, ProtocolVersion.DTLSv12);
+ return params;
+ }
+
+ private static void addVersionTests(List<Object[]> params, ProtocolVersion version)
+ {
+ String prefix = version.toString().replaceAll("[ \\.]", "") + "_";
+
+ /*
+ * NOTE: Temporarily disabled automatic test runs because of problems getting a clean exit
+ * of the DTLS server after a fatal alert. As of writing, manual runs show the correct
+ * alerts being raised
+ */
+
+// {
+// TlsTestConfig c = createDTLSTestConfig(version);
+// c.clientAuth = C.CLIENT_AUTH_INVALID_VERIFY;
+// c.expectServerFatalAlert(AlertDescription.decrypt_error);
+//
+// testSuite.addTest(new DTLSTestCase(c, prefix + "BadCertificateVerify"));
+// }
+//
+// {
+// TlsTestConfig c = createDTLSTestConfig(version);
+// c.clientAuth = C.CLIENT_AUTH_INVALID_CERT;
+// c.expectServerFatalAlert(AlertDescription.bad_certificate);
+//
+// testSuite.addTest(new DTLSTestCase(c, prefix + "BadClientCertificate"));
+// }
+//
+// {
+// TlsTestConfig c = createDTLSTestConfig(version);
+// c.clientAuth = C.CLIENT_AUTH_NONE;
+// c.serverCertReq = C.SERVER_CERT_REQ_MANDATORY;
+// c.expectServerFatalAlert(AlertDescription.handshake_failure);
+//
+// testSuite.addTest(new DTLSTestCase(c, prefix + "BadMandatoryCertReqDeclined"));
+// }
+
+ {
+ TlsTestConfig c = createDTLSTestConfig(version);
+
+ params.add(new Object[] { c, prefix + "GoodDefault" });
+ }
+
+ {
+ TlsTestConfig c = createDTLSTestConfig(version);
+ c.serverCertReq = C.SERVER_CERT_REQ_NONE;
+
+ params.add(new Object[]{ c, prefix + "GoodNoCertReq"});
+ }
+
+ {
+ TlsTestConfig c = createDTLSTestConfig(version);
+ c.clientAuth = C.CLIENT_AUTH_NONE;
+
+ params.add(new Object[]{ c, prefix + "GoodOptionalCertReqDeclined"});
+ }
+ }
+
+ private static TlsTestConfig createDTLSTestConfig(ProtocolVersion version)
+ {
+ TlsTestConfig c = new TlsTestConfig();
+ c.clientMinimumVersion = ProtocolVersion.DTLSv10;
+ /*
+ * TODO We'd like to just set the offer version to DTLSv12, but there is a known issue with
+ * overly-restrictive version checks b/w BC DTLS 1.2 client, BC DTLS 1.0 server
+ */
+ c.clientOfferVersion = version;
+ c.serverMaximumVersion = version;
+ c.serverMinimumVersion = ProtocolVersion.DTLSv10;
+ return c;
+ }
+
+ private static void checkDTLSVersion(ProtocolVersion version)
+ {
+ if (version != null && !version.isDTLS())
+ {
+ throw new IllegalStateException("Non-DTLS version");
+ }
+ }
+
+ protected final TlsTestConfig config;
+
+ public DTLSTestCase(TlsTestConfig config, String name)
+ {
+ checkDTLSVersion(config.clientMinimumVersion);
+ checkDTLSVersion(config.clientOfferVersion);
+ checkDTLSVersion(config.serverMaximumVersion);
+ checkDTLSVersion(config.serverMinimumVersion);
+
+ this.config = config;
+ }
+
+ @Test
+ public void runTest() throws Throwable
+ {
+ SecureRandom secureRandom = new SecureRandom();
+
+ DTLSClientProtocol clientProtocol = new DTLSClientProtocol(secureRandom);
+ DTLSServerProtocol serverProtocol = new DTLSServerProtocol(secureRandom);
+
+ MockDatagramAssociation network = new MockDatagramAssociation(1500);
+
+ TlsTestClientImpl clientImpl = new TlsTestClientImpl(config);
+ TlsTestServerImpl serverImpl = new TlsTestServerImpl(config);
+
+ ServerThread serverThread = new ServerThread(serverProtocol, network.getServer(), serverImpl);
+ serverThread.start();
+
+ Exception caught = null;
+ try
+ {
+ DatagramTransport clientTransport = network.getClient();
+
+ if (TlsTestConfig.DEBUG)
+ {
+ clientTransport = new LoggingDatagramTransport(clientTransport, System.out);
+ }
+
+ DTLSTransport dtlsClient = clientProtocol.connect(clientImpl, clientTransport);
+
+ for (int i = 1; i <= 10; ++i)
+ {
+ byte[] data = new byte[i];
+ Arrays.fill(data, (byte)i);
+ dtlsClient.send(data, 0, data.length);
+ }
+
+ byte[] buf = new byte[dtlsClient.getReceiveLimit()];
+ while (dtlsClient.receive(buf, 0, buf.length, 100) >= 0)
+ {
+ }
+
+ dtlsClient.close();
+ }
+ catch (Exception e)
+ {
+ caught = e;
+ logException(caught);
+ }
+
+ serverThread.shutdown();
+
+ // TODO Add checks that the various streams were closed
+
+ assertEquals("Client fatal alert connection end", config.expectFatalAlertConnectionEnd, clientImpl.firstFatalAlertConnectionEnd);
+ assertEquals("Server fatal alert connection end", config.expectFatalAlertConnectionEnd, serverImpl.firstFatalAlertConnectionEnd);
+
+ assertEquals("Client fatal alert description", config.expectFatalAlertDescription, clientImpl.firstFatalAlertDescription);
+ assertEquals("Server fatal alert description", config.expectFatalAlertDescription, serverImpl.firstFatalAlertDescription);
+
+ if (config.expectFatalAlertConnectionEnd == -1)
+ {
+ assertNull("Unexpected client exception", caught);
+ assertNull("Unexpected server exception", serverThread.caught);
+ }
+ }
+
+ protected void logException(Exception e)
+ {
+ if (TlsTestConfig.DEBUG)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ class ServerThread
+ extends Thread
+ {
+ private final DTLSServerProtocol serverProtocol;
+ private final DatagramTransport serverTransport;
+ private final TlsTestServerImpl serverImpl;
+
+ private volatile boolean isShutdown = false;
+ Exception caught = null;
+
+ ServerThread(DTLSServerProtocol serverProtocol, DatagramTransport serverTransport, TlsTestServerImpl serverImpl)
+ {
+ this.serverProtocol = serverProtocol;
+ this.serverTransport = serverTransport;
+ this.serverImpl = serverImpl;
+ }
+
+ public void run()
+ {
+ try
+ {
+ DTLSTransport dtlsServer = serverProtocol.accept(serverImpl, serverTransport);
+ byte[] buf = new byte[dtlsServer.getReceiveLimit()];
+ while (!isShutdown)
+ {
+ int length = dtlsServer.receive(buf, 0, buf.length, 100);
+ if (length >= 0)
+ {
+ dtlsServer.send(buf, 0, length);
+ }
+ }
+ dtlsServer.close();
+ }
+ catch (Exception e)
+ {
+ caught = e;
+ logException(caught);
+ }
+ }
+
+ void shutdown()
+ throws InterruptedException
+ {
+ if (!isShutdown)
+ {
+ isShutdown = true;
+ this.interrupt();
+ this.join();
+ }
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/HTTPSServerThread.java b/core/src/test/java/org/spongycastle/crypto/tls/test/HTTPSServerThread.java
new file mode 100644
index 00000000..07eb86e0
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/HTTPSServerThread.java
@@ -0,0 +1,113 @@
+package org.spongycastle.crypto.tls.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.security.KeyStore;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.TrustManagerFactory;
+
+public class HTTPSServerThread
+ extends Thread
+{
+ private static final int PORT_NO = 8003;
+ private static final char[] SERVER_PASSWORD = "serverPassword".toCharArray();
+ private static final char[] TRUST_STORE_PASSWORD = "trustPassword".toCharArray();
+
+ /**
+ * Read a HTTP request
+ */
+ private void readRequest(
+ InputStream in)
+ throws IOException
+ {
+ int ch = 0;
+ int lastCh = 0;
+ while ((ch = in.read()) >= 0 && (ch != '\n' && lastCh != '\n'))
+ {
+ if (ch != '\r')
+ {
+ lastCh = ch;
+ }
+ }
+ }
+
+ /**
+ * Send a response
+ */
+ private void sendResponse(
+ OutputStream out)
+ {
+ PrintWriter pWrt = new PrintWriter(new OutputStreamWriter(out));
+ pWrt.print("HTTP/1.1 200 OK\r\n");
+ pWrt.print("Content-Type: text/html\r\n");
+ pWrt.print("\r\n");
+ pWrt.print("<html>\r\n");
+ pWrt.print("<body>\r\n");
+ pWrt.print("Hello World!\r\n");
+ pWrt.print("</body>\r\n");
+ pWrt.print("</html>\r\n");
+ pWrt.flush();
+ }
+
+ SSLContext createSSLContext()
+ throws Exception
+ {
+ KeyManagerFactory mgrFact = KeyManagerFactory.getInstance("SunX509");
+ KeyStore serverStore = KeyStore.getInstance("JKS");
+
+ serverStore.load(new ByteArrayInputStream(KeyStores.server), SERVER_PASSWORD);
+
+ mgrFact.init(serverStore, SERVER_PASSWORD);
+
+ // set up a trust manager so we can recognize the server
+ TrustManagerFactory trustFact = TrustManagerFactory.getInstance("SunX509");
+ KeyStore trustStore = KeyStore.getInstance("JKS");
+
+ trustStore.load(new ByteArrayInputStream(KeyStores.trustStore), TRUST_STORE_PASSWORD);
+
+ trustFact.init(trustStore);
+
+ // create a context and set up a socket factory
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+
+ sslContext.init(mgrFact.getKeyManagers(), trustFact.getTrustManagers(), null);
+
+ return sslContext;
+ }
+
+ public void run()
+ {
+ try
+ {
+ SSLContext sslContext = createSSLContext();
+ SSLServerSocketFactory fact = sslContext.getServerSocketFactory();
+
+ SSLServerSocket sSock = (SSLServerSocket)fact.createServerSocket(PORT_NO);
+ SSLSocket sslSock = (SSLSocket)sSock.accept();
+
+ sslSock.startHandshake();
+
+ readRequest(sslSock.getInputStream());
+
+ SSLSession session = sslSock.getSession();
+
+ sendResponse(sslSock.getOutputStream());
+
+ sslSock.close();
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/KeyStores.java b/core/src/test/java/org/spongycastle/crypto/tls/test/KeyStores.java
new file mode 100644
index 00000000..5aa0b396
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/KeyStores.java
@@ -0,0 +1,113 @@
+package org.spongycastle.crypto.tls.test;
+
+import org.spongycastle.util.encoders.Base64;
+
+public class KeyStores
+{
+ static final byte[] trustStore = Base64.decode(
+ "/u3+7QAAAAIAAAABAAAAAgAGc2VydmVyAAABD34zDJEABVguNTA5AAABrzCC"
+ + "AaswggEUAgEBMA0GCSqGSIb3DQEBBQUAMB4xHDAaBgNVBAMTE1Rlc3QgQ0Eg"
+ + "Q2VydGlmaWNhdGUwHhcNMDYxMjEzMjM0MzI5WhcNMDYxMjIwMjM0MzI5WjAe"
+ + "MRwwGgYDVQQDExNUZXN0IENBIENlcnRpZmljYXRlMIGfMA0GCSqGSIb3DQEB"
+ + "AQUAA4GNADCBiQKBgQCmOumCM46ehsdcrZMw6tj0hMl5D0xf21gcyBj/ByIv"
+ + "pe008ukaN3zCXIUUUlAu0GkbI1sCbTD1V4qVZuaHqtfa/FINJjyZJy5w7KEx"
+ + "93OOF2/gyPlnEPGs6RPdThAPliSBsWKBKqtOdmKpwYn/NKuUNFRkFXVLLUPn"
+ + "jyEKjIcNywIDAQABMA0GCSqGSIb3DQEBBQUAA4GBACi8J7raYqDFjXqAXXPJ"
+ + "ljZHqvzJNVaSWvBtK/oY7g0+sdGIjPR526fhSCxOZRr7G157ERqMnPjuFjcm"
+ + "cRlUOPsQtTl6KbUnxmKxa04UzDuNXzSx2oyGx5GCWx9u62hpO6vSpK69L9gH"
+ + "OUtM5dQXcoK4i3olScKaU8qaYb0mBAy8fnx5pen8B0bIg+pz47l5VxQ5NO8=");
+
+ static final byte[] server = Base64.decode(
+ "/u3+7QAAAAIAAAABAAAAAQAGc2VydmVyAAABD34zDJIAAAK8MIICuDAOBgor"
+ + "BgEEASoCEQEBBQAEggKk9OXWj3aBr6rV9Grcsm2YL+/2ShVsxbJVGMSWll1f"
+ + "U8z/mjhv5K/skgleTIMoyE5FzDDxJIGEmSMCkcHsnseXzxyhLpKBaz3N1Tk7"
+ + "KVPzXfrNh0FJwzw3lPWyC2ayT+ObQfAtzuI9SUWNLBzzpWeolUJ8gkXnLshX"
+ + "5RqmR735NRZdjgQOtNYBBErX/NOhTyi009/CZDNxgJQzywFmQcXBLhNSA+0i"
+ + "cE+LwZ4sZV0NXshPZiyNnsfqN/XNOyhpKr8a3VyVtee2nhO9+FY5IDEviHmR"
+ + "WDvH5TmB6Os3L6xvwE1ZQCPElk/cK2G1q9+zDBe4JDeo8o7lPhiNpVfcivnr"
+ + "+tyK9m7PqlssR0+ohuZGwrFMyzLugkOWh+qZ3pk8/7AwJosMvvTvIg36nN7R"
+ + "pdnouQNKqTm1Sr/UUnKyWqfG7zqKIuF72IkDwwafwuQ9YRX5PAOuRfo6bCyb"
+ + "D4w1OWdfGFciKMc1BrT+8JzhiTkzNe+jWEA5Tw1zeazPGpp1RHPz2np50G2s"
+ + "v025uiOSUilBe13Qpx0mAyx7z8Gl6eOxai6rQ/eB/Fu++BMx0OX8vO/K4//Q"
+ + "w43IPVPklGlb/3Qt7eoNf4tichuxrYJjHu4XbwnzB29Vmsan0XZFER7epvFj"
+ + "cAZCSG+O6G/f6Ib+7d7xYjLdUaPI60tJ4/C+AuYwZn4jJwTnMnMmwIypz4Z8"
+ + "XPXW5SbHlV5OkkFC+eAuuN4b2YXZmifeWv4fx65Ioir921LMJrorMizH41RJ"
+ + "/rAO5wGSwjeDJ784QhhLGbEUMygraRtdaz6MRx26InnoHY7V58ET3Z5YGV39"
+ + "p+9AtVhYw/QQmTZiF7hqnEMf9AMVFfac9qFF2+IN3g9HAMC6QLxJ1VuPn5oo"
+ + "lS//axPfjckO7iZx9x59/gAAAAEABVguNTA5AAABrzCCAaswggEUAgEBMA0G"
+ + "CSqGSIb3DQEBBQUAMB4xHDAaBgNVBAMTE1Rlc3QgQ0EgQ2VydGlmaWNhdGUw"
+ + "HhcNMDYxMjEzMjM0MzI5WhcNMDYxMjIwMjM0MzI5WjAeMRwwGgYDVQQDExNU"
+ + "ZXN0IENBIENlcnRpZmljYXRlMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB"
+ + "gQCmOumCM46ehsdcrZMw6tj0hMl5D0xf21gcyBj/ByIvpe008ukaN3zCXIUU"
+ + "UlAu0GkbI1sCbTD1V4qVZuaHqtfa/FINJjyZJy5w7KEx93OOF2/gyPlnEPGs"
+ + "6RPdThAPliSBsWKBKqtOdmKpwYn/NKuUNFRkFXVLLUPnjyEKjIcNywIDAQAB"
+ + "MA0GCSqGSIb3DQEBBQUAA4GBACi8J7raYqDFjXqAXXPJljZHqvzJNVaSWvBt"
+ + "K/oY7g0+sdGIjPR526fhSCxOZRr7G157ERqMnPjuFjcmcRlUOPsQtTl6KbUn"
+ + "xmKxa04UzDuNXzSx2oyGx5GCWx9u62hpO6vSpK69L9gHOUtM5dQXcoK4i3ol"
+ + "ScKaU8qaYb0mBAy87VQaPfaiQqqxSgqifbSowlg+0fg=");
+
+ static final byte[] client = Base64.decode(
+ "MIACAQMwgAYJKoZIhvcNAQcBoIAkgASCA+gwgDCABgkqhkiG9w0BBwGggCSA"
+ + "BIIDDzCCAwswggMHBgsqhkiG9w0BDAoBAqCCArIwggKuMCgGCiqGSIb3DQEM"
+ + "AQMwGgQUyeN8U+ViAJCk1WGo8wTnRVOaE1oCAgQABIICgH3yMWB+dfMBNa07"
+ + "hn3smUSBTF+LUauM+kx+12nZt0QazBYg09yM+aVcTznettlDwE/PTpKZnrFT"
+ + "22DSQf5GwABwiL6KW+xyM8wV5vZx1xtqrQoNf2oNHnF0lB7ddSYM8jHqennb"
+ + "bzcVOdrrCqewqAfUU/CDugpwwI8c8Iy9ECri6vBMbfeIIZQTug+1952TCCiA"
+ + "E1bEDFGqgAoDsqYi6uNtpjmL/DPX/qmkbHAXUKxOtjTtxacfat2HgN97Gb7z"
+ + "+ZBNI5aaCSRoYwl+K9biWGID3EqsNmg0+2ELmFhE4mQZ78i7vNLTG7e5mj6v"
+ + "Qt+QuqN+daCbVqVTKxsFpODRRweobUTRxwEun6p0p3w3SUhR6p7ug1Jttgyu"
+ + "vfZug3PIk2j9fb26wAs2ZreVYut8hXpp/09ulCUudtlsYb/FD+H11v/JyopG"
+ + "2vYy0hL/gkMr41sGoVdyvzXeZUa7A1wYask+g7torad9sT8CPb3zXBd0kU2r"
+ + "lbSJIXQ8wTpheeUKe47YF9JVCF8WRc1dokD7fgfn6197pwyZpDEVrVyz1pUq"
+ + "jyum3ctONU4BSkAUVr9pTyeRFUeOE7SLuVu+c67PzNWXEc/HMVD4Hgs/idVc"
+ + "mrONk3xe385wFJK1iPe1kfRX5OXk9UWr2/yjgrahbkonWhJHnIlvs+b5rRKN"
+ + "qauwUZ+agMJV98Eyc2Lz0Lp/pNDRNjmGXeJLzAaAy46STov8sxwAgj3bQ7xu"
+ + "uEzdhJPDynAY5sWd3WnBY2ZhpawnToEKnD4u+eiH2MjUL2q/R2IPSmoyg9i2"
+ + "Ictgh4/ylrhm+lJDzcDrLDhC0m/t9EdhytH4erk/uCPcmAK/jpzFn6ltxcsx"
+ + "QjAbBgkqhkiG9w0BCRQxDh4MAGMAbABpAGUAbgB0MCMGCSqGSIb3DQEJFTEW"
+ + "BBS2wDxw7yH2OhKIgkDoQrTlavLvxQAAAAAAADCABgkqhkiG9w0BBwaggDCA"
+ + "AgEAMIAGCSqGSIb3DQEHATAoBgoqhkiG9w0BDAEGMBoEFORdyeTIG2oXDQBl"
+ + "I3aFNozDAkC2AgIEAKCABIIHICsc3D8rxLiDlegyXFfIejto66RW4u6b+d0C"
+ + "uAAz0G+dIvhQ9g3s++vUsX7x+icO/vjpgdo09aqtIg7T3suzfcHtU8CGSgtQ"
+ + "Tvml25LDC3IK3qI6cRqO+sCdvg18aS04IDKvDPYH4ca5btwPBIID6CStk/jY"
+ + "QFpnSI6VNz9IERi/nwuvuBYk+A0Z7+nQdhF+QkW1rzN+uz0dkNJt6ZbG5lEK"
+ + "GayV+FDTQcREMihYa716RN9sq3cm0jXXdttj998oS/QrpZDEcPqd4AM6EIL+"
+ + "PTA1tEQYxXa8msAPp+tLvXOtiD6v/4FO77EA7E5oR36a9en+M1QQasFU3VBf"
+ + "V9os92QlbtVUTkspJV9gXL6s4CGNptc7lUH+nIw65j9MOoyOU9w1qjPRlN/Z"
+ + "MTuhFooglE6TPd29Udwufqp+hHkW/7z5tBKkhGlZEClzD3IWhcF9NVraE/IV"
+ + "S5qVmx2Up7SeLZAXJ+AAznq5IXwE1dOUTkwYLcIrH1FuVA5rtOkB8Xt1LJq0"
+ + "ERkjJ5MfpxTxbKXp5PejzD98v54+s4INekcrI0jzz4pLsann7ex0r6CPsQsH"
+ + "+F3rBVaT3oHSKqoIm2Nw57oDjLLp5lP2qcCqps3y2dcVzu5NIzCSkVlxUaBK"
+ + "IT3xv0gvVJI7wnP0QM35MCywKkToJX5ajQKrDc4iCAAzmxaQzdBycxJPYByq"
+ + "VHvH7BJldJlMw5NHbTHlNoYKndMdAsHp7sUqERkDEGl80R86TlB4nJaDrfsx"
+ + "vL+KluiCY9AD7o+MEYZ9VYoNDUzVGH4pTr4wnv1UFoRWix5IZuDnnYkyijKD"
+ + "VtU5+mc0YtsPQIpKCBJOYt05bgpX5aPQ3s2lviYw3bvP0TrclYs/rx4wKVgW"
+ + "2GYLzPh0OVMBduCbzW1E58ieBsgRyQ7+2MTl9Nj+nznjCAfLSvrVEcwxVUQA"
+ + "ofcEbiECEJss2JNQq8erwgo8dP3atwQ1KeqMc8acICcOrI2rNxwVOLzPuCsl"
+ + "l8gwZOoxLZXuKMQbQu4as1HNS309dfWIWppvc3K4nDWg51HUCPbsIo3wm3rR"
+ + "igc/W3bf4Ppg0pLAS5c1s0Xau43u9GmIjGiDqYaasfcXnCKy2LNuUpbhoOC1"
+ + "o/wMC9gT45aJQ5vsVGe5XvfhLV7Y815EdI756s9PIEOnG8HbAtCAjOIVpQfP"
+ + "eF8+cnZyGGdsbmu7lYzg3whCpZ/L2RrTI86nEn5eePs4m2hDV0Oi9r6e2CIf"
+ + "nGUa0TB9jf1OMhOSBD+h4jx7b6uT+XLmG8qUxvkoItMDZLrJ0f8czO5MyOZa"
+ + "nEJoG42Fy2p7zD/qO72OUQISNmt8C1rQFsg9dBDib4DMu69vBsVrIV028sal"
+ + "+tq1UH3vFMbEYyVfPH3WDgxyHwUQK2qrz3WBdD/BMyuAV4DPI3SPTweROh8n"
+ + "yWJN1ppY9qybmTyHFCs6TRjPB9cVcdKSc0qYxgzblJiXXb3s9ANOb89aA3Ah"
+ + "anWnAhcEggLZN2yFCtrRuvJXvDQhj8qmye9UkjB2fEpWXV7H0natE3hSoB+C"
+ + "2krt3eBV0xJ1tLEco7T4zsbQQJRmeu/essOsfwpRfE5ZPoIeThf+UmWTsfsw"
+ + "r4fxeePMTy6iCnkF5/ro8k5WKnOsaV+HWy/ulwW2r/DMT3aDBWfHX5Hk8DpU"
+ + "+PlQhbyGTSTIJ/OFmbcWjMPt469o7+KrrF9IBrzJ42KzMw6xtKwtVb0232AM"
+ + "pIwnLzCHIiNO2qDBZAIDdF68+GU3RsEkHfR6d5myZVxnH4mhSCFFtHxgqTOz"
+ + "Ouo/uvgu72miZ0OFAy1zcMtfGMS3Md54MJkhSZq4ZgUo/EyJCeEDLGn8pMF1"
+ + "jX1WsUj96qMRyc+p2KnKs6ZL95BVa76SdIFz6ts6uoIem3drTXYJHNbw29OW"
+ + "Y0am+FmXTWFZFnin8Qu5Xct5l7FYIGA9VLOHL9Vtp+SXomcFEZpjMaxvtf4R"
+ + "xoAI2Bc9Ka+MNiz35O0JXhI9/t5uOdiN6ZOJlfpEWOK7ou5lDkZuDcrHvLvQ"
+ + "PocP2Yemd36xEgjFssR/tFITlhRBXHDeHwpvmXM4iiwD1wOGMqybXx/1g1m1"
+ + "0UBbKqDsgSLQC7c0TaRFJjj71T74PBMiapiQgijv9WINfmTgxNUukbK3Kqp/"
+ + "G3BmThoIDCB8WD1kxXBpaG62dSsih7yhPQJVEV3Y0tdkdChOk+Y3Wf8crV/Q"
+ + "P08pQH7H9yCi04S5fSJtIDtYARWhr1yl8EQMnu2X8J6r/DWcDmXUK4Bv1vqe"
+ + "tcnT5EAYFPeOMz21nonM3kJgUMNsxCQjKaEMEcUu8ZRnGUAFdG4lULPJn5NQ"
+ + "LTvWg8Y3GrHRLjpnd9k+8gWWzRIbBiwCwEbClMZffRd6kcA5ZoOhVngdyvvj"
+ + "BhkgadB5jC+ZRzExHxoEhzPJx3mxIVTqLuw7QxHz9OTcysvY/cGKCvmgzgk/"
+ + "TjTJsqcEAAAAAAAAAAAAAAAAAAAAAAAAMD0wITAJBgUrDgMCGgUABBQWfGA6"
+ + "lI+TXQiuXaa1V+LlHodhXAQUAwMIAAUvBYY+a7sXNlQeVEPAGkMCAgQAAAA=");
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/LoggingDatagramTransport.java b/core/src/test/java/org/spongycastle/crypto/tls/test/LoggingDatagramTransport.java
new file mode 100644
index 00000000..ff9bdc04
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/LoggingDatagramTransport.java
@@ -0,0 +1,91 @@
+package org.spongycastle.crypto.tls.test;
+
+import java.io.IOException;
+import java.io.PrintStream;
+
+import org.spongycastle.crypto.tls.DatagramTransport;
+
+public class LoggingDatagramTransport
+ implements DatagramTransport
+{
+
+ private static final String HEX_CHARS = "0123456789ABCDEF";
+
+ private final DatagramTransport transport;
+ private final PrintStream output;
+ private final long launchTimestamp;
+
+ public LoggingDatagramTransport(DatagramTransport transport, PrintStream output)
+ {
+ this.transport = transport;
+ this.output = output;
+ this.launchTimestamp = System.currentTimeMillis();
+ }
+
+ public int getReceiveLimit()
+ throws IOException
+ {
+ return transport.getReceiveLimit();
+ }
+
+ public int getSendLimit()
+ throws IOException
+ {
+ return transport.getSendLimit();
+ }
+
+ public int receive(byte[] buf, int off, int len, int waitMillis)
+ throws IOException
+ {
+ int length = transport.receive(buf, off, len, waitMillis);
+ if (length >= 0)
+ {
+ dumpDatagram("Received", buf, off, length);
+ }
+ return length;
+ }
+
+ public void send(byte[] buf, int off, int len)
+ throws IOException
+ {
+ dumpDatagram("Sending", buf, off, len);
+ transport.send(buf, off, len);
+ }
+
+ public void close()
+ throws IOException
+ {
+ }
+
+ private void dumpDatagram(String verb, byte[] buf, int off, int len)
+ throws IOException
+ {
+ long timestamp = System.currentTimeMillis() - launchTimestamp;
+ StringBuffer sb = new StringBuffer("(+" + timestamp + "ms) " + verb + " " + len + " byte datagram:");
+ for (int pos = 0; pos < len; ++pos)
+ {
+ if (pos % 16 == 0)
+ {
+ sb.append(System.getProperty("line.separator"));
+ sb.append(" ");
+ }
+ else if (pos % 16 == 8)
+ {
+ sb.append('-');
+ }
+ else
+ {
+ sb.append(' ');
+ }
+ int val = buf[off + pos] & 0xFF;
+ sb.append(HEX_CHARS.charAt(val >> 4));
+ sb.append(HEX_CHARS.charAt(val & 0xF));
+ }
+ dump(sb.toString());
+ }
+
+ private synchronized void dump(String s)
+ {
+ output.println(s);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/MockDTLSClient.java b/core/src/test/java/org/spongycastle/crypto/tls/test/MockDTLSClient.java
new file mode 100644
index 00000000..4a728714
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/MockDTLSClient.java
@@ -0,0 +1,177 @@
+package org.spongycastle.crypto.tls.test;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.spongycastle.asn1.x509.Certificate;
+import org.spongycastle.crypto.tls.AlertLevel;
+import org.spongycastle.crypto.tls.CertificateRequest;
+import org.spongycastle.crypto.tls.ClientCertificateType;
+import org.spongycastle.crypto.tls.DefaultTlsClient;
+import org.spongycastle.crypto.tls.MaxFragmentLength;
+import org.spongycastle.crypto.tls.ProtocolVersion;
+import org.spongycastle.crypto.tls.SignatureAlgorithm;
+import org.spongycastle.crypto.tls.SignatureAndHashAlgorithm;
+import org.spongycastle.crypto.tls.TlsAuthentication;
+import org.spongycastle.crypto.tls.TlsCredentials;
+import org.spongycastle.crypto.tls.TlsExtensionsUtils;
+import org.spongycastle.crypto.tls.TlsSession;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+
+public class MockDTLSClient
+ extends DefaultTlsClient
+{
+ protected TlsSession session;
+
+ public MockDTLSClient(TlsSession session)
+ {
+ this.session = session;
+ }
+
+ public TlsSession getSessionToResume()
+ {
+ return this.session;
+ }
+
+ public void notifyAlertRaised(short alertLevel, short alertDescription, String message, Exception cause)
+ {
+ PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
+ out.println("DTLS client raised alert (AlertLevel." + alertLevel + ", AlertDescription." + alertDescription
+ + ")");
+ if (message != null)
+ {
+ out.println(message);
+ }
+ if (cause != null)
+ {
+ cause.printStackTrace(out);
+ }
+ }
+
+ public void notifyAlertReceived(short alertLevel, short alertDescription)
+ {
+ PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
+ out.println("DTLS client received alert (AlertLevel." + alertLevel + ", AlertDescription." + alertDescription
+ + ")");
+ }
+
+ public ProtocolVersion getClientVersion()
+ {
+ return ProtocolVersion.DTLSv12;
+ }
+
+ public ProtocolVersion getMinimumVersion()
+ {
+ return ProtocolVersion.DTLSv10;
+ }
+
+// public int[] getCipherSuites()
+// {
+// return Arrays.concatenate(super.getCipherSuites(),
+// new int[]
+// {
+// CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+// CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1,
+// CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1,
+// CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1,
+// CipherSuite.TLS_RSA_WITH_SALSA20_SHA1,
+// });
+// }
+
+ public Hashtable getClientExtensions() throws IOException
+ {
+ Hashtable clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(super.getClientExtensions());
+ TlsExtensionsUtils.addEncryptThenMACExtension(clientExtensions);
+ TlsExtensionsUtils.addMaxFragmentLengthExtension(clientExtensions, MaxFragmentLength.pow2_9);
+ TlsExtensionsUtils.addTruncatedHMacExtension(clientExtensions);
+ return clientExtensions;
+ }
+
+ public void notifyServerVersion(ProtocolVersion serverVersion) throws IOException
+ {
+ super.notifyServerVersion(serverVersion);
+
+ System.out.println("Negotiated " + serverVersion);
+ }
+
+ public TlsAuthentication getAuthentication()
+ throws IOException
+ {
+ return new TlsAuthentication()
+ {
+ public void notifyServerCertificate(org.spongycastle.crypto.tls.Certificate serverCertificate)
+ throws IOException
+ {
+ Certificate[] chain = serverCertificate.getCertificateList();
+ System.out.println("Received server certificate chain of length " + chain.length);
+ for (int i = 0; i != chain.length; i++)
+ {
+ Certificate entry = chain[i];
+ // TODO Create fingerprint based on certificate signature algorithm digest
+ System.out.println(" fingerprint:SHA-256 " + TlsTestUtils.fingerprint(entry) + " ("
+ + entry.getSubject() + ")");
+ }
+ }
+
+ public TlsCredentials getClientCredentials(CertificateRequest certificateRequest)
+ throws IOException
+ {
+ short[] certificateTypes = certificateRequest.getCertificateTypes();
+ if (certificateTypes == null || !Arrays.contains(certificateTypes, ClientCertificateType.rsa_sign))
+ {
+ return null;
+ }
+
+ SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
+ Vector sigAlgs = certificateRequest.getSupportedSignatureAlgorithms();
+ if (sigAlgs != null)
+ {
+ for (int i = 0; i < sigAlgs.size(); ++i)
+ {
+ SignatureAndHashAlgorithm sigAlg = (SignatureAndHashAlgorithm)
+ sigAlgs.elementAt(i);
+ if (sigAlg.getSignature() == SignatureAlgorithm.rsa)
+ {
+ signatureAndHashAlgorithm = sigAlg;
+ break;
+ }
+ }
+
+ if (signatureAndHashAlgorithm == null)
+ {
+ return null;
+ }
+ }
+
+ return TlsTestUtils.loadSignerCredentials(context, new String[] { "x509-client.pem", "x509-ca.pem" },
+ "x509-client-key.pem", signatureAndHashAlgorithm);
+ }
+ };
+ }
+
+ public void notifyHandshakeComplete() throws IOException
+ {
+ super.notifyHandshakeComplete();
+
+ TlsSession newSession = context.getResumableSession();
+ if (newSession != null)
+ {
+ byte[] newSessionID = newSession.getSessionID();
+ String hex = Hex.toHexString(newSessionID);
+
+ if (this.session != null && Arrays.areEqual(this.session.getSessionID(), newSessionID))
+ {
+ System.out.println("Resumed session: " + hex);
+ }
+ else
+ {
+ System.out.println("Established session: " + hex);
+ }
+
+ this.session = newSession;
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/MockDTLSServer.java b/core/src/test/java/org/spongycastle/crypto/tls/test/MockDTLSServer.java
new file mode 100644
index 00000000..8c41ba74
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/MockDTLSServer.java
@@ -0,0 +1,148 @@
+package org.spongycastle.crypto.tls.test;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Vector;
+
+import org.spongycastle.asn1.x509.Certificate;
+import org.spongycastle.crypto.tls.AlertLevel;
+import org.spongycastle.crypto.tls.CertificateRequest;
+import org.spongycastle.crypto.tls.CipherSuite;
+import org.spongycastle.crypto.tls.ClientCertificateType;
+import org.spongycastle.crypto.tls.DefaultTlsServer;
+import org.spongycastle.crypto.tls.HashAlgorithm;
+import org.spongycastle.crypto.tls.ProtocolVersion;
+import org.spongycastle.crypto.tls.SignatureAlgorithm;
+import org.spongycastle.crypto.tls.SignatureAndHashAlgorithm;
+import org.spongycastle.crypto.tls.TlsEncryptionCredentials;
+import org.spongycastle.crypto.tls.TlsSignerCredentials;
+import org.spongycastle.crypto.tls.TlsUtils;
+import org.spongycastle.util.Arrays;
+
+public class MockDTLSServer
+ extends DefaultTlsServer
+{
+ public void notifyAlertRaised(short alertLevel, short alertDescription, String message, Exception cause)
+ {
+ PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
+ out.println("DTLS server raised alert (AlertLevel." + alertLevel + ", AlertDescription." + alertDescription
+ + ")");
+ if (message != null)
+ {
+ out.println(message);
+ }
+ if (cause != null)
+ {
+ cause.printStackTrace(out);
+ }
+ }
+
+ public void notifyAlertReceived(short alertLevel, short alertDescription)
+ {
+ PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
+ out.println("DTLS server received alert (AlertLevel." + alertLevel + ", AlertDescription." + alertDescription
+ + ")");
+ }
+
+ protected int[] getCipherSuites()
+ {
+ return Arrays.concatenate(super.getCipherSuites(),
+ new int[]
+ {
+ CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+ CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1,
+ CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1,
+ CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1,
+ CipherSuite.TLS_RSA_WITH_SALSA20_SHA1,
+ });
+ }
+
+ public CertificateRequest getCertificateRequest() throws IOException
+ {
+ Vector serverSigAlgs = null;
+
+ if (TlsUtils.isSignatureAlgorithmsExtensionAllowed(serverVersion))
+ {
+ short[] hashAlgorithms = new short[]{ HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256,
+ HashAlgorithm.sha224, HashAlgorithm.sha1 };
+ short[] signatureAlgorithms = new short[]{ SignatureAlgorithm.rsa };
+
+ serverSigAlgs = new Vector();
+ for (int i = 0; i < hashAlgorithms.length; ++i)
+ {
+ for (int j = 0; j < signatureAlgorithms.length; ++j)
+ {
+ serverSigAlgs.addElement(new SignatureAndHashAlgorithm(hashAlgorithms[i],
+ signatureAlgorithms[j]));
+ }
+ }
+ }
+
+ Vector certificateAuthorities = new Vector();
+ certificateAuthorities.add(TlsTestUtils.loadCertificateResource("x509-ca.pem").getSubject());
+
+ return new CertificateRequest(new short[]{ ClientCertificateType.rsa_sign }, serverSigAlgs, certificateAuthorities);
+ }
+
+ public void notifyClientCertificate(org.spongycastle.crypto.tls.Certificate clientCertificate)
+ throws IOException
+ {
+ Certificate[] chain = clientCertificate.getCertificateList();
+ System.out.println("Received client certificate chain of length " + chain.length);
+ for (int i = 0; i != chain.length; i++)
+ {
+ Certificate entry = chain[i];
+ // TODO Create fingerprint based on certificate signature algorithm digest
+ System.out.println(" fingerprint:SHA-256 " + TlsTestUtils.fingerprint(entry) + " (" + entry.getSubject()
+ + ")");
+ }
+ }
+
+ protected ProtocolVersion getMaximumVersion()
+ {
+ return ProtocolVersion.DTLSv12;
+ }
+
+ protected ProtocolVersion getMinimumVersion()
+ {
+ return ProtocolVersion.DTLSv10;
+ }
+
+ protected TlsEncryptionCredentials getRSAEncryptionCredentials()
+ throws IOException
+ {
+ return TlsTestUtils.loadEncryptionCredentials(context, new String[]{"x509-server.pem", "x509-ca.pem"},
+ "x509-server-key.pem");
+ }
+
+ protected TlsSignerCredentials getRSASignerCredentials()
+ throws IOException
+ {
+ /*
+ * TODO Note that this code fails to provide default value for the client supported
+ * algorithms if it wasn't sent.
+ */
+ SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
+ Vector sigAlgs = supportedSignatureAlgorithms;
+ if (sigAlgs != null)
+ {
+ for (int i = 0; i < sigAlgs.size(); ++i)
+ {
+ SignatureAndHashAlgorithm sigAlg = (SignatureAndHashAlgorithm)
+ sigAlgs.elementAt(i);
+ if (sigAlg.getSignature() == SignatureAlgorithm.rsa)
+ {
+ signatureAndHashAlgorithm = sigAlg;
+ break;
+ }
+ }
+
+ if (signatureAndHashAlgorithm == null)
+ {
+ return null;
+ }
+ }
+ return TlsTestUtils.loadSignerCredentials(context, new String[]{"x509-server.pem", "x509-ca.pem"},
+ "x509-server-key.pem", signatureAndHashAlgorithm);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/MockDatagramAssociation.java b/core/src/test/java/org/spongycastle/crypto/tls/test/MockDatagramAssociation.java
new file mode 100644
index 00000000..92bc6c1c
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/MockDatagramAssociation.java
@@ -0,0 +1,110 @@
+package org.spongycastle.crypto.tls.test;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.util.Vector;
+
+import org.spongycastle.crypto.tls.DatagramTransport;
+
+public class MockDatagramAssociation
+{
+ private int mtu;
+ private MockDatagramTransport client, server;
+
+ public MockDatagramAssociation(int mtu)
+ {
+ this.mtu = mtu;
+
+ Vector clientQueue = new Vector();
+ Vector serverQueue = new Vector();
+
+ this.client = new MockDatagramTransport(clientQueue, serverQueue);
+ this.server = new MockDatagramTransport(serverQueue, clientQueue);
+ }
+
+ public DatagramTransport getClient()
+ {
+ return client;
+ }
+
+ public DatagramTransport getServer()
+ {
+ return server;
+ }
+
+ private class MockDatagramTransport
+ implements DatagramTransport
+ {
+ private Vector receiveQueue, sendQueue;
+
+ MockDatagramTransport(Vector receiveQueue, Vector sendQueue)
+ {
+ this.receiveQueue = receiveQueue;
+ this.sendQueue = sendQueue;
+ }
+
+ public int getReceiveLimit()
+ throws IOException
+ {
+ return mtu;
+ }
+
+ public int getSendLimit()
+ throws IOException
+ {
+ return mtu;
+ }
+
+ public int receive(byte[] buf, int off, int len, int waitMillis)
+ throws IOException
+ {
+ synchronized (receiveQueue)
+ {
+ if (receiveQueue.isEmpty())
+ {
+ try
+ {
+ receiveQueue.wait(waitMillis);
+ }
+ catch (InterruptedException e)
+ {
+ // TODO Keep waiting until full wait expired?
+ }
+ if (receiveQueue.isEmpty())
+ {
+ return -1;
+ }
+ }
+ DatagramPacket packet = (DatagramPacket)receiveQueue.remove(0);
+ int copyLength = Math.min(len, packet.getLength());
+ System.arraycopy(packet.getData(), packet.getOffset(), buf, off, copyLength);
+ return copyLength;
+ }
+ }
+
+ public void send(byte[] buf, int off, int len)
+ throws IOException
+ {
+ if (len > mtu)
+ {
+ // TODO Simulate rejection?
+ }
+
+ byte[] copy = new byte[len];
+ System.arraycopy(buf, off, copy, 0, len);
+ DatagramPacket packet = new DatagramPacket(copy, len);
+
+ synchronized (sendQueue)
+ {
+ sendQueue.addElement(packet);
+ sendQueue.notify();
+ }
+ }
+
+ public void close()
+ throws IOException
+ {
+ // TODO?
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/MockTlsClient.java b/core/src/test/java/org/spongycastle/crypto/tls/test/MockTlsClient.java
new file mode 100644
index 00000000..db62c5e3
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/MockTlsClient.java
@@ -0,0 +1,167 @@
+package org.spongycastle.crypto.tls.test;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.spongycastle.asn1.x509.Certificate;
+import org.spongycastle.crypto.tls.AlertLevel;
+import org.spongycastle.crypto.tls.CertificateRequest;
+import org.spongycastle.crypto.tls.ClientCertificateType;
+import org.spongycastle.crypto.tls.DefaultTlsClient;
+import org.spongycastle.crypto.tls.MaxFragmentLength;
+import org.spongycastle.crypto.tls.ProtocolVersion;
+import org.spongycastle.crypto.tls.SignatureAlgorithm;
+import org.spongycastle.crypto.tls.SignatureAndHashAlgorithm;
+import org.spongycastle.crypto.tls.TlsAuthentication;
+import org.spongycastle.crypto.tls.TlsCredentials;
+import org.spongycastle.crypto.tls.TlsExtensionsUtils;
+import org.spongycastle.crypto.tls.TlsSession;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.encoders.Hex;
+
+class MockTlsClient
+ extends DefaultTlsClient
+{
+ TlsSession session;
+
+ MockTlsClient(TlsSession session)
+ {
+ this.session = session;
+ }
+
+ public TlsSession getSessionToResume()
+ {
+ return this.session;
+ }
+
+ public void notifyAlertRaised(short alertLevel, short alertDescription, String message, Exception cause)
+ {
+ PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
+ out.println("TLS client raised alert (AlertLevel." + alertLevel + ", AlertDescription." + alertDescription
+ + ")");
+ if (message != null)
+ {
+ out.println("> " + message);
+ }
+ if (cause != null)
+ {
+ cause.printStackTrace(out);
+ }
+ }
+
+ public void notifyAlertReceived(short alertLevel, short alertDescription)
+ {
+ PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
+ out.println("TLS client received alert (AlertLevel." + alertLevel + ", AlertDescription."
+ + alertDescription + ")");
+ }
+
+// public int[] getCipherSuites()
+// {
+// return Arrays.concatenate(super.getCipherSuites(),
+// new int[]
+// {
+// CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+// CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1,
+// CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1,
+// CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1,
+// CipherSuite.TLS_RSA_WITH_SALSA20_SHA1,
+// });
+// }
+
+ public Hashtable getClientExtensions() throws IOException
+ {
+ Hashtable clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(super.getClientExtensions());
+ TlsExtensionsUtils.addEncryptThenMACExtension(clientExtensions);
+ TlsExtensionsUtils.addMaxFragmentLengthExtension(clientExtensions, MaxFragmentLength.pow2_9);
+ TlsExtensionsUtils.addTruncatedHMacExtension(clientExtensions);
+ return clientExtensions;
+ }
+
+ public void notifyServerVersion(ProtocolVersion serverVersion) throws IOException
+ {
+ super.notifyServerVersion(serverVersion);
+
+ System.out.println("TLS client negotiated " + serverVersion);
+ }
+
+ public TlsAuthentication getAuthentication()
+ throws IOException
+ {
+ return new TlsAuthentication()
+ {
+ public void notifyServerCertificate(org.spongycastle.crypto.tls.Certificate serverCertificate)
+ throws IOException
+ {
+ Certificate[] chain = serverCertificate.getCertificateList();
+ System.out.println("TLS client received server certificate chain of length " + chain.length);
+ for (int i = 0; i != chain.length; i++)
+ {
+ Certificate entry = chain[i];
+ // TODO Create fingerprint based on certificate signature algorithm digest
+ System.out.println(" fingerprint:SHA-256 " + TlsTestUtils.fingerprint(entry) + " ("
+ + entry.getSubject() + ")");
+ }
+ }
+
+ public TlsCredentials getClientCredentials(CertificateRequest certificateRequest)
+ throws IOException
+ {
+ short[] certificateTypes = certificateRequest.getCertificateTypes();
+ if (certificateTypes == null || !Arrays.contains(certificateTypes, ClientCertificateType.rsa_sign))
+ {
+ return null;
+ }
+
+ SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
+ Vector sigAlgs = certificateRequest.getSupportedSignatureAlgorithms();
+ if (sigAlgs != null)
+ {
+ for (int i = 0; i < sigAlgs.size(); ++i)
+ {
+ SignatureAndHashAlgorithm sigAlg = (SignatureAndHashAlgorithm)
+ sigAlgs.elementAt(i);
+ if (sigAlg.getSignature() == SignatureAlgorithm.rsa)
+ {
+ signatureAndHashAlgorithm = sigAlg;
+ break;
+ }
+ }
+
+ if (signatureAndHashAlgorithm == null)
+ {
+ return null;
+ }
+ }
+
+ return TlsTestUtils.loadSignerCredentials(context, new String[] { "x509-client.pem", "x509-ca.pem" },
+ "x509-client-key.pem", signatureAndHashAlgorithm);
+ }
+ };
+ }
+
+ public void notifyHandshakeComplete() throws IOException
+ {
+ super.notifyHandshakeComplete();
+
+ TlsSession newSession = context.getResumableSession();
+ if (newSession != null)
+ {
+ byte[] newSessionID = newSession.getSessionID();
+ String hex = Hex.toHexString(newSessionID);
+
+ if (this.session != null && Arrays.areEqual(this.session.getSessionID(), newSessionID))
+ {
+ System.out.println("Resumed session: " + hex);
+ }
+ else
+ {
+ System.out.println("Established session: " + hex);
+ }
+
+ this.session = newSession;
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/MockTlsServer.java b/core/src/test/java/org/spongycastle/crypto/tls/test/MockTlsServer.java
new file mode 100644
index 00000000..a0340ff8
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/MockTlsServer.java
@@ -0,0 +1,153 @@
+package org.spongycastle.crypto.tls.test;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Vector;
+
+import org.spongycastle.asn1.x509.Certificate;
+import org.spongycastle.crypto.tls.AlertLevel;
+import org.spongycastle.crypto.tls.CertificateRequest;
+import org.spongycastle.crypto.tls.CipherSuite;
+import org.spongycastle.crypto.tls.ClientCertificateType;
+import org.spongycastle.crypto.tls.DefaultTlsServer;
+import org.spongycastle.crypto.tls.HashAlgorithm;
+import org.spongycastle.crypto.tls.ProtocolVersion;
+import org.spongycastle.crypto.tls.SignatureAlgorithm;
+import org.spongycastle.crypto.tls.SignatureAndHashAlgorithm;
+import org.spongycastle.crypto.tls.TlsEncryptionCredentials;
+import org.spongycastle.crypto.tls.TlsSignerCredentials;
+import org.spongycastle.crypto.tls.TlsUtils;
+import org.spongycastle.util.Arrays;
+
+class MockTlsServer
+ extends DefaultTlsServer
+{
+ public void notifyAlertRaised(short alertLevel, short alertDescription, String message, Exception cause)
+ {
+ PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
+ out.println("TLS server raised alert (AlertLevel." + alertLevel + ", AlertDescription." + alertDescription
+ + ")");
+ if (message != null)
+ {
+ out.println("> " + message);
+ }
+ if (cause != null)
+ {
+ cause.printStackTrace(out);
+ }
+ }
+
+ public void notifyAlertReceived(short alertLevel, short alertDescription)
+ {
+ PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
+ out.println("TLS server received alert (AlertLevel." + alertLevel + ", AlertDescription."
+ + alertDescription + ")");
+ }
+
+ protected int[] getCipherSuites()
+ {
+ return Arrays.concatenate(super.getCipherSuites(),
+ new int[]
+ {
+ CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+ CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1,
+ CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1,
+ CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1,
+ CipherSuite.TLS_RSA_WITH_SALSA20_SHA1,
+ });
+ }
+
+ protected ProtocolVersion getMaximumVersion()
+ {
+ return ProtocolVersion.TLSv12;
+ }
+
+ public ProtocolVersion getServerVersion() throws IOException
+ {
+ ProtocolVersion serverVersion = super.getServerVersion();
+
+ System.out.println("TLS server negotiated " + serverVersion);
+
+ return serverVersion;
+ }
+
+ public CertificateRequest getCertificateRequest() throws IOException
+ {
+ Vector serverSigAlgs = null;
+
+ if (TlsUtils.isSignatureAlgorithmsExtensionAllowed(serverVersion))
+ {
+ short[] hashAlgorithms = new short[]{ HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256,
+ HashAlgorithm.sha224, HashAlgorithm.sha1 };
+ short[] signatureAlgorithms = new short[]{ SignatureAlgorithm.rsa };
+
+ serverSigAlgs = new Vector();
+ for (int i = 0; i < hashAlgorithms.length; ++i)
+ {
+ for (int j = 0; j < signatureAlgorithms.length; ++j)
+ {
+ serverSigAlgs.addElement(new SignatureAndHashAlgorithm(hashAlgorithms[i],
+ signatureAlgorithms[j]));
+ }
+ }
+ }
+
+ Vector certificateAuthorities = new Vector();
+ certificateAuthorities.add(TlsTestUtils.loadCertificateResource("x509-ca.pem").getSubject());
+
+ return new CertificateRequest(new short[]{ ClientCertificateType.rsa_sign }, serverSigAlgs, certificateAuthorities);
+ }
+
+ public void notifyClientCertificate(org.spongycastle.crypto.tls.Certificate clientCertificate)
+ throws IOException
+ {
+ Certificate[] chain = clientCertificate.getCertificateList();
+ System.out.println("TLS server received client certificate chain of length " + chain.length);
+ for (int i = 0; i != chain.length; i++)
+ {
+ Certificate entry = chain[i];
+ // TODO Create fingerprint based on certificate signature algorithm digest
+ System.out.println(" fingerprint:SHA-256 " + TlsTestUtils.fingerprint(entry) + " ("
+ + entry.getSubject() + ")");
+ }
+ }
+
+ protected TlsEncryptionCredentials getRSAEncryptionCredentials()
+ throws IOException
+ {
+ return TlsTestUtils.loadEncryptionCredentials(context, new String[]{"x509-server.pem", "x509-ca.pem"},
+ "x509-server-key.pem");
+ }
+
+ protected TlsSignerCredentials getRSASignerCredentials()
+ throws IOException
+ {
+ /*
+ * TODO Note that this code fails to provide default value for the client supported
+ * algorithms if it wasn't sent.
+ */
+ SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
+ Vector sigAlgs = supportedSignatureAlgorithms;
+ if (sigAlgs != null)
+ {
+ for (int i = 0; i < sigAlgs.size(); ++i)
+ {
+ SignatureAndHashAlgorithm sigAlg = (SignatureAndHashAlgorithm)
+ sigAlgs.elementAt(i);
+ if (sigAlg.getSignature() == SignatureAlgorithm.rsa)
+ {
+ signatureAndHashAlgorithm = sigAlg;
+ break;
+ }
+ }
+
+ if (signatureAndHashAlgorithm == null)
+ {
+ return null;
+ }
+ }
+
+ return TlsTestUtils.loadSignerCredentials(context, new String[]{"x509-server.pem", "x509-ca.pem"},
+ "x509-server-key.pem", signatureAndHashAlgorithm);
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/NetworkInputStream.java b/core/src/test/java/org/spongycastle/crypto/tls/test/NetworkInputStream.java
new file mode 100644
index 00000000..4764805a
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/NetworkInputStream.java
@@ -0,0 +1,60 @@
+package org.spongycastle.crypto.tls.test;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Tracks and enforces close() calls, without closing the underlying InputStream
+ */
+class NetworkInputStream extends FilterInputStream
+{
+ boolean closed = false;
+
+ public NetworkInputStream(InputStream input)
+ {
+ super(input);
+ }
+
+ synchronized boolean isClosed()
+ {
+ return closed;
+ }
+
+ public int available() throws IOException
+ {
+ checkNotClosed();
+ return in.available();
+ }
+
+ public synchronized void close() throws IOException
+ {
+ closed = true;
+ }
+
+ public int read() throws IOException
+ {
+ checkNotClosed();
+ return in.read();
+ }
+
+ public int read(byte[] b) throws IOException
+ {
+ checkNotClosed();
+ return in.read(b);
+ }
+
+ public int read(byte[] b, int off, int len) throws IOException
+ {
+ checkNotClosed();
+ return in.read(b, off, len);
+ }
+
+ protected synchronized void checkNotClosed() throws IOException
+ {
+ if (closed)
+ {
+ throw new IOException("NetworkInputStream closed");
+ }
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/NetworkOutputStream.java b/core/src/test/java/org/spongycastle/crypto/tls/test/NetworkOutputStream.java
new file mode 100644
index 00000000..5e619958
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/NetworkOutputStream.java
@@ -0,0 +1,54 @@
+package org.spongycastle.crypto.tls.test;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Tracks and enforces close() calls, without closing the underlying OutputStream
+ */
+class NetworkOutputStream extends FilterOutputStream
+{
+ boolean closed = false;
+
+ public NetworkOutputStream(OutputStream output)
+ {
+ super(output);
+ }
+
+ synchronized boolean isClosed()
+ {
+ return closed;
+ }
+
+ public synchronized void close() throws IOException
+ {
+ closed = true;
+ }
+
+ public void write(int b) throws IOException
+ {
+ checkNotClosed();
+ out.write(b);
+ }
+
+ public void write(byte[] b) throws IOException
+ {
+ checkNotClosed();
+ out.write(b);
+ }
+
+ public void write(byte[] b, int off, int len) throws IOException
+ {
+ checkNotClosed();
+ out.write(b, off, len);
+ }
+
+ protected synchronized void checkNotClosed() throws IOException
+ {
+ if (closed)
+ {
+ throw new IOException("NetworkOutputStream closed");
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/TlsClientTest.java b/core/src/test/java/org/spongycastle/crypto/tls/test/TlsClientTest.java
new file mode 100644
index 00000000..96634fe8
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/TlsClientTest.java
@@ -0,0 +1,69 @@
+package org.spongycastle.crypto.tls.test;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.tls.TlsClient;
+import org.spongycastle.crypto.tls.TlsClientProtocol;
+
+/**
+ * A simple test designed to conduct a TLS handshake with an external TLS server.
+ * <p/>
+ * Please refer to GnuTLSSetup.txt or OpenSSLSetup.txt, and x509-*.pem files in this package for
+ * help configuring an external TLS server.
+ */
+public class TlsClientTest
+{
+ private static final SecureRandom secureRandom = new SecureRandom();
+
+ public static void main(String[] args)
+ throws Exception
+ {
+ InetAddress address = InetAddress.getLocalHost();
+ int port = 5556;
+
+ long time1 = System.currentTimeMillis();
+
+ MockTlsClient client = new MockTlsClient(null);
+ TlsClientProtocol protocol = openTlsConnection(address, port, client);
+ protocol.close();
+
+ long time2 = System.currentTimeMillis();
+ System.out.println("Elapsed 1: " + (time2 - time1) + "ms");
+
+ client = new MockTlsClient(client.getSessionToResume());
+ protocol = openTlsConnection(address, port, client);
+
+ long time3 = System.currentTimeMillis();
+ System.out.println("Elapsed 2: " + (time3 - time2) + "ms");
+
+ OutputStream output = protocol.getOutputStream();
+ output.write("GET / HTTP/1.1\r\n\r\n".getBytes("UTF-8"));
+ output.flush();
+
+ InputStream input = protocol.getInputStream();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(input));
+
+ String line;
+ while ((line = reader.readLine()) != null)
+ {
+ System.out.println(">>> " + line);
+ }
+
+ protocol.close();
+ }
+
+ static TlsClientProtocol openTlsConnection(InetAddress address, int port, TlsClient client) throws IOException
+ {
+ Socket s = new Socket(address, port);
+ TlsClientProtocol protocol = new TlsClientProtocol(s.getInputStream(), s.getOutputStream(), secureRandom);
+ protocol.connect(client);
+ return protocol;
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/TlsProtocolTest.java b/core/src/test/java/org/spongycastle/crypto/tls/test/TlsProtocolTest.java
new file mode 100644
index 00000000..06754648
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/TlsProtocolTest.java
@@ -0,0 +1,82 @@
+package org.spongycastle.crypto.tls.test;
+
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.security.SecureRandom;
+
+import junit.framework.TestCase;
+
+import org.spongycastle.crypto.tls.TlsClientProtocol;
+import org.spongycastle.crypto.tls.TlsServerProtocol;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.io.Streams;
+
+public class TlsProtocolTest
+ extends TestCase
+{
+ public void testClientServer()
+ throws Exception
+ {
+ SecureRandom secureRandom = new SecureRandom();
+
+ PipedInputStream clientRead = new PipedInputStream();
+ PipedInputStream serverRead = new PipedInputStream();
+ PipedOutputStream clientWrite = new PipedOutputStream(serverRead);
+ PipedOutputStream serverWrite = new PipedOutputStream(clientRead);
+
+ TlsClientProtocol clientProtocol = new TlsClientProtocol(clientRead, clientWrite, secureRandom);
+ TlsServerProtocol serverProtocol = new TlsServerProtocol(serverRead, serverWrite, secureRandom);
+
+ ServerThread serverThread = new ServerThread(serverProtocol);
+ serverThread.start();
+
+ MockTlsClient client = new MockTlsClient(null);
+ clientProtocol.connect(client);
+
+ // NOTE: Because we write-all before we read-any, this length can't be more than the pipe capacity
+ int length = 1000;
+
+ byte[] data = new byte[length];
+ secureRandom.nextBytes(data);
+
+ OutputStream output = clientProtocol.getOutputStream();
+ output.write(data);
+
+ byte[] echo = new byte[data.length];
+ int count = Streams.readFully(clientProtocol.getInputStream(), echo);
+
+ assertEquals(count, data.length);
+ assertTrue(Arrays.areEqual(data, echo));
+
+ output.close();
+
+ serverThread.join();
+ }
+
+ static class ServerThread
+ extends Thread
+ {
+ private final TlsServerProtocol serverProtocol;
+
+ ServerThread(TlsServerProtocol serverProtocol)
+ {
+ this.serverProtocol = serverProtocol;
+ }
+
+ public void run()
+ {
+ try
+ {
+ MockTlsServer server = new MockTlsServer();
+ serverProtocol.accept(server);
+ Streams.pipeAll(serverProtocol.getInputStream(), serverProtocol.getOutputStream());
+ serverProtocol.close();
+ }
+ catch (Exception e)
+ {
+// throw new RuntimeException(e);
+ }
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/TlsServerTest.java b/core/src/test/java/org/spongycastle/crypto/tls/test/TlsServerTest.java
new file mode 100644
index 00000000..af74ec77
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/TlsServerTest.java
@@ -0,0 +1,81 @@
+package org.spongycastle.crypto.tls.test;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.tls.TlsServerProtocol;
+import org.spongycastle.util.io.Streams;
+import org.spongycastle.util.io.TeeOutputStream;
+
+/**
+ * A simple test designed to conduct a TLS handshake with an external TLS client.
+ * <p/>
+ * Please refer to GnuTLSSetup.txt or OpenSSLSetup.txt, and x509-*.pem files in this package for
+ * help configuring an external TLS client.
+ */
+public class TlsServerTest
+{
+ private static final SecureRandom secureRandom = new SecureRandom();
+
+ public static void main(String[] args)
+ throws Exception
+ {
+ InetAddress address = InetAddress.getLocalHost();
+ int port = 5556;
+
+ ServerSocket ss = new ServerSocket(port, 16, address);
+ while (true)
+ {
+ Socket s = ss.accept();
+ System.out.println("--------------------------------------------------------------------------------");
+ System.out.println("Accepted " + s);
+ ServerThread t = new ServerThread(s);
+ t.start();
+ }
+ }
+
+ static class ServerThread
+ extends Thread
+ {
+ private final Socket s;
+
+ ServerThread(Socket s)
+ {
+ this.s = s;
+ }
+
+ public void run()
+ {
+ try
+ {
+ MockTlsServer server = new MockTlsServer();
+ TlsServerProtocol serverProtocol = new TlsServerProtocol(s.getInputStream(), s.getOutputStream(), secureRandom);
+ serverProtocol.accept(server);
+ OutputStream log = new TeeOutputStream(serverProtocol.getOutputStream(), System.out);
+ Streams.pipeAll(serverProtocol.getInputStream(), log);
+ serverProtocol.close();
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ finally
+ {
+ try
+ {
+ s.close();
+ }
+ catch (IOException e)
+ {
+ }
+ finally
+ {
+ }
+ }
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/TlsTestCase.java b/core/src/test/java/org/spongycastle/crypto/tls/test/TlsTestCase.java
new file mode 100644
index 00000000..bfcf7cba
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/TlsTestCase.java
@@ -0,0 +1,252 @@
+package org.spongycastle.crypto.tls.test;
+
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.spongycastle.crypto.tls.AlertDescription;
+import org.spongycastle.crypto.tls.ProtocolVersion;
+import org.spongycastle.crypto.tls.TlsClientProtocol;
+import org.spongycastle.crypto.tls.TlsServerProtocol;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.io.Streams;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.junit.Assert.*;
+
+@RunWith(Parameterized.class)
+public class TlsTestCase
+{
+
+ // Make the access to constants less verbose
+ static abstract class C extends TlsTestConfig {}
+
+ @Parameterized.Parameters(name = "{index}: {1}")
+ public static Collection<Object[]> data() {
+ List<Object[]> params = new ArrayList<Object[]>();
+ addVersionTests(params, ProtocolVersion.TLSv10);
+ addVersionTests(params, ProtocolVersion.TLSv11);
+ addVersionTests(params, ProtocolVersion.TLSv12);
+ return params;
+ }
+
+ private static void addVersionTests(List<Object[]> params, ProtocolVersion version)
+ {
+ String prefix = version.toString().replaceAll("[ \\.]", "") + "_";
+
+ {
+ TlsTestConfig c = createTlsTestConfig(version);
+
+ params.add(new Object[] { c, prefix + "GoodDefault" });
+ }
+
+ {
+ TlsTestConfig c = createTlsTestConfig(version);
+ c.clientAuth = C.CLIENT_AUTH_INVALID_VERIFY;
+ c.expectServerFatalAlert(AlertDescription.decrypt_error);
+
+ params.add(new Object[] { c, prefix + "BadCertificateVerify" });
+ }
+
+ {
+ TlsTestConfig c = createTlsTestConfig(version);
+ c.clientAuth = C.CLIENT_AUTH_INVALID_CERT;
+ c.expectServerFatalAlert(AlertDescription.bad_certificate);
+
+ params.add(new Object[] { c, prefix + "BadClientCertificate" });
+ }
+
+ {
+ TlsTestConfig c = createTlsTestConfig(version);
+ c.clientAuth = C.CLIENT_AUTH_NONE;
+ c.serverCertReq = C.SERVER_CERT_REQ_MANDATORY;
+ c.expectServerFatalAlert(AlertDescription.handshake_failure);
+
+ params.add(new Object[] { c, prefix + "BadMandatoryCertReqDeclined" });
+ }
+
+ {
+ TlsTestConfig c = createTlsTestConfig(version);
+ c.serverCertReq = C.SERVER_CERT_REQ_NONE;
+
+ params.add(new Object[] { c, prefix + "GoodNoCertReq" });
+ }
+
+ {
+ TlsTestConfig c = createTlsTestConfig(version);
+ c.clientAuth = C.CLIENT_AUTH_NONE;
+
+ params.add(new Object[] { c, prefix + "GoodOptionalCertReqDeclined" });
+ }
+ }
+
+ private static TlsTestConfig createTlsTestConfig(ProtocolVersion version)
+ {
+ TlsTestConfig c = new TlsTestConfig();
+ c.clientMinimumVersion = ProtocolVersion.TLSv10;
+ c.clientOfferVersion = ProtocolVersion.TLSv12;
+ c.serverMaximumVersion = version;
+ c.serverMinimumVersion = ProtocolVersion.TLSv10;
+ return c;
+ }
+
+
+ private static void checkTLSVersion(ProtocolVersion version)
+ {
+ if (version != null && !version.isTLS())
+ {
+ throw new IllegalStateException("Non-TLS version");
+ }
+ }
+
+ protected final TlsTestConfig config;
+
+ public TlsTestCase(TlsTestConfig config, String name)
+ {
+ checkTLSVersion(config.clientMinimumVersion);
+ checkTLSVersion(config.clientOfferVersion);
+ checkTLSVersion(config.serverMaximumVersion);
+ checkTLSVersion(config.serverMinimumVersion);
+
+ this.config = config;
+ }
+
+ @Test
+ public void runTest() throws Throwable
+ {
+ SecureRandom secureRandom = new SecureRandom();
+
+ PipedInputStream clientRead = new PipedInputStream();
+ PipedInputStream serverRead = new PipedInputStream();
+ PipedOutputStream clientWrite = new PipedOutputStream(serverRead);
+ PipedOutputStream serverWrite = new PipedOutputStream(clientRead);
+
+ NetworkInputStream clientNetIn = new NetworkInputStream(clientRead);
+ NetworkInputStream serverNetIn = new NetworkInputStream(serverRead);
+ NetworkOutputStream clientNetOut = new NetworkOutputStream(clientWrite);
+ NetworkOutputStream serverNetOut = new NetworkOutputStream(serverWrite);
+
+ TlsClientProtocol clientProtocol = new TlsClientProtocol(clientNetIn, clientNetOut, secureRandom);
+ TlsServerProtocol serverProtocol = new TlsServerProtocol(serverNetIn, serverNetOut, secureRandom);
+
+ TlsTestClientImpl clientImpl = new TlsTestClientImpl(config);
+ TlsTestServerImpl serverImpl = new TlsTestServerImpl(config);
+
+ ServerThread serverThread = new ServerThread(serverProtocol, serverImpl);
+ serverThread.start();
+
+ Exception caught = null;
+ try
+ {
+ clientProtocol.connect(clientImpl);
+
+ // NOTE: Because we write-all before we read-any, this length can't be more than the pipe capacity
+ int length = 1000;
+
+ byte[] data = new byte[length];
+ secureRandom.nextBytes(data);
+
+ OutputStream output = clientProtocol.getOutputStream();
+ output.write(data);
+
+ byte[] echo = new byte[data.length];
+ int count = Streams.readFully(clientProtocol.getInputStream(), echo);
+
+ assertEquals(count, data.length);
+ assertTrue(Arrays.areEqual(data, echo));
+
+ output.close();
+ }
+ catch (Exception e)
+ {
+ caught = e;
+ logException(caught);
+ }
+
+ serverThread.allowExit();
+ serverThread.join();
+
+ assertTrue("Client InputStream not closed", clientNetIn.isClosed());
+ assertTrue("Client OutputStream not closed", clientNetOut.isClosed());
+ assertTrue("Server InputStream not closed", serverNetIn.isClosed());
+ assertTrue("Server OutputStream not closed", serverNetOut.isClosed());
+
+ assertEquals("Client fatal alert connection end", config.expectFatalAlertConnectionEnd, clientImpl.firstFatalAlertConnectionEnd);
+ assertEquals("Server fatal alert connection end", config.expectFatalAlertConnectionEnd, serverImpl.firstFatalAlertConnectionEnd);
+
+ assertEquals("Client fatal alert description", config.expectFatalAlertDescription, clientImpl.firstFatalAlertDescription);
+ assertEquals("Server fatal alert description", config.expectFatalAlertDescription, serverImpl.firstFatalAlertDescription);
+
+ if (config.expectFatalAlertConnectionEnd == -1)
+ {
+ assertNull("Unexpected client exception", caught);
+ assertNull("Unexpected server exception", serverThread.caught);
+ }
+ }
+
+ protected void logException(Exception e)
+ {
+ if (TlsTestConfig.DEBUG)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ class ServerThread extends Thread
+ {
+ protected final TlsServerProtocol serverProtocol;
+ protected final TlsTestServerImpl serverImpl;
+
+ boolean canExit = false;
+ Exception caught = null;
+
+ ServerThread(TlsServerProtocol serverProtocol, TlsTestServerImpl serverImpl)
+ {
+ this.serverProtocol = serverProtocol;
+ this.serverImpl = serverImpl;
+ }
+
+ synchronized void allowExit()
+ {
+ canExit = true;
+ this.notifyAll();
+ }
+
+ public void run()
+ {
+ try
+ {
+ serverProtocol.accept(serverImpl);
+ Streams.pipeAll(serverProtocol.getInputStream(), serverProtocol.getOutputStream());
+ serverProtocol.close();
+ }
+ catch (Exception e)
+ {
+ caught = e;
+ logException(caught);
+ }
+
+ waitExit();
+ }
+
+ protected synchronized void waitExit()
+ {
+ while (!canExit)
+ {
+ try
+ {
+ this.wait();
+ }
+ catch (InterruptedException e)
+ {
+ }
+ }
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/TlsTestClientImpl.java b/core/src/test/java/org/spongycastle/crypto/tls/test/TlsTestClientImpl.java
new file mode 100644
index 00000000..cb4c4d15
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/TlsTestClientImpl.java
@@ -0,0 +1,263 @@
+package org.spongycastle.crypto.tls.test;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Vector;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.x509.Certificate;
+import org.spongycastle.crypto.tls.AlertDescription;
+import org.spongycastle.crypto.tls.AlertLevel;
+import org.spongycastle.crypto.tls.CertificateRequest;
+import org.spongycastle.crypto.tls.ClientCertificateType;
+import org.spongycastle.crypto.tls.ConnectionEnd;
+import org.spongycastle.crypto.tls.DefaultTlsClient;
+import org.spongycastle.crypto.tls.ProtocolVersion;
+import org.spongycastle.crypto.tls.SignatureAlgorithm;
+import org.spongycastle.crypto.tls.SignatureAndHashAlgorithm;
+import org.spongycastle.crypto.tls.TlsAuthentication;
+import org.spongycastle.crypto.tls.TlsCredentials;
+import org.spongycastle.crypto.tls.TlsFatalAlert;
+import org.spongycastle.crypto.tls.TlsSignerCredentials;
+import org.spongycastle.util.Arrays;
+
+class TlsTestClientImpl
+ extends DefaultTlsClient
+{
+ protected final TlsTestConfig config;
+
+ protected int firstFatalAlertConnectionEnd = -1;
+ protected short firstFatalAlertDescription = -1;
+
+ TlsTestClientImpl(TlsTestConfig config)
+ {
+ this.config = config;
+ }
+
+ int getFirstFatalAlertConnectionEnd()
+ {
+ return firstFatalAlertConnectionEnd;
+ }
+
+ short getFirstFatalAlertDescription()
+ {
+ return firstFatalAlertDescription;
+ }
+
+ public ProtocolVersion getClientVersion()
+ {
+ if (config.clientOfferVersion != null)
+ {
+ return config.clientOfferVersion;
+ }
+
+ return super.getClientVersion();
+ }
+
+ public ProtocolVersion getMinimumVersion()
+ {
+ if (config.clientMinimumVersion != null)
+ {
+ return config.clientMinimumVersion;
+ }
+
+ return super.getMinimumVersion();
+ }
+
+ public void notifyAlertRaised(short alertLevel, short alertDescription, String message, Exception cause)
+ {
+ if (alertLevel == AlertLevel.fatal && firstFatalAlertConnectionEnd == -1)
+ {
+ firstFatalAlertConnectionEnd = ConnectionEnd.client;
+ firstFatalAlertDescription = alertDescription;
+ }
+
+ if (TlsTestConfig.DEBUG)
+ {
+ PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
+ out.println("TLS client raised alert (AlertLevel." + alertLevel + ", AlertDescription." + alertDescription
+ + ")");
+ if (message != null)
+ {
+ out.println("> " + message);
+ }
+ if (cause != null)
+ {
+ cause.printStackTrace(out);
+ }
+ }
+ }
+
+ public void notifyAlertReceived(short alertLevel, short alertDescription)
+ {
+ if (alertLevel == AlertLevel.fatal && firstFatalAlertConnectionEnd == -1)
+ {
+ firstFatalAlertConnectionEnd = ConnectionEnd.server;
+ firstFatalAlertDescription = alertDescription;
+ }
+
+ if (TlsTestConfig.DEBUG)
+ {
+ PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
+ out.println("TLS client received alert (AlertLevel." + alertLevel + ", AlertDescription."
+ + alertDescription + ")");
+ }
+ }
+
+ public void notifyServerVersion(ProtocolVersion serverVersion) throws IOException
+ {
+ super.notifyServerVersion(serverVersion);
+
+ if (TlsTestConfig.DEBUG)
+ {
+ System.out.println("TLS client negotiated " + serverVersion);
+ }
+ }
+
+ public TlsAuthentication getAuthentication()
+ throws IOException
+ {
+ return new TlsAuthentication()
+ {
+ public void notifyServerCertificate(org.spongycastle.crypto.tls.Certificate serverCertificate)
+ throws IOException
+ {
+ boolean isEmpty = serverCertificate == null || serverCertificate.isEmpty();
+
+ Certificate[] chain = serverCertificate.getCertificateList();
+
+ if (isEmpty || !chain[0].equals(TlsTestUtils.loadCertificateResource("x509-server.pem")))
+ {
+ throw new TlsFatalAlert(AlertDescription.bad_certificate);
+ }
+
+ if (TlsTestConfig.DEBUG)
+ {
+ System.out.println("TLS client received server certificate chain of length " + chain.length);
+ for (int i = 0; i != chain.length; i++)
+ {
+ Certificate entry = chain[i];
+ // TODO Create fingerprint based on certificate signature algorithm digest
+ System.out.println(" fingerprint:SHA-256 " + TlsTestUtils.fingerprint(entry) + " ("
+ + entry.getSubject() + ")");
+ }
+ }
+ }
+
+ public TlsCredentials getClientCredentials(CertificateRequest certificateRequest)
+ throws IOException
+ {
+ if (config.serverCertReq == TlsTestConfig.SERVER_CERT_REQ_NONE)
+ {
+ throw new IllegalStateException();
+ }
+ if (config.clientAuth == TlsTestConfig.CLIENT_AUTH_NONE)
+ {
+ return null;
+ }
+
+ short[] certificateTypes = certificateRequest.getCertificateTypes();
+ if (certificateTypes == null || !Arrays.contains(certificateTypes, ClientCertificateType.rsa_sign))
+ {
+ return null;
+ }
+
+ SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
+ Vector sigAlgs = certificateRequest.getSupportedSignatureAlgorithms();
+ if (sigAlgs != null)
+ {
+ for (int i = 0; i < sigAlgs.size(); ++i)
+ {
+ SignatureAndHashAlgorithm sigAlg = (SignatureAndHashAlgorithm)
+ sigAlgs.elementAt(i);
+ if (sigAlg.getSignature() == SignatureAlgorithm.rsa)
+ {
+ signatureAndHashAlgorithm = sigAlg;
+ break;
+ }
+ }
+
+ if (signatureAndHashAlgorithm == null)
+ {
+ return null;
+ }
+ }
+
+ final TlsSignerCredentials signerCredentials = TlsTestUtils.loadSignerCredentials(context, new String[]{
+ "x509-client.pem", "x509-ca.pem" }, "x509-client-key.pem", signatureAndHashAlgorithm);
+
+ if (config.clientAuth == TlsTestConfig.CLIENT_AUTH_VALID)
+ {
+ return signerCredentials;
+ }
+
+ return new TlsSignerCredentials()
+ {
+ public byte[] generateCertificateSignature(byte[] hash) throws IOException
+ {
+ byte[] sig = signerCredentials.generateCertificateSignature(hash);
+
+ if (config.clientAuth == TlsTestConfig.CLIENT_AUTH_INVALID_VERIFY)
+ {
+ sig = corruptBit(sig);
+ }
+
+ return sig;
+ }
+
+ public org.spongycastle.crypto.tls.Certificate getCertificate()
+ {
+ org.spongycastle.crypto.tls.Certificate cert = signerCredentials.getCertificate();
+
+ if (config.clientAuth == TlsTestConfig.CLIENT_AUTH_INVALID_CERT)
+ {
+ cert = corruptCertificate(cert);
+ }
+
+ return cert;
+ }
+
+ public SignatureAndHashAlgorithm getSignatureAndHashAlgorithm()
+ {
+ return signerCredentials.getSignatureAndHashAlgorithm();
+ }
+ };
+ }
+ };
+ }
+
+ protected org.spongycastle.crypto.tls.Certificate corruptCertificate(org.spongycastle.crypto.tls.Certificate cert)
+ {
+ Certificate[] certList = cert.getCertificateList();
+ certList[0] = corruptCertificateSignature(certList[0]);
+ return new org.spongycastle.crypto.tls.Certificate(certList);
+ }
+
+ protected Certificate corruptCertificateSignature(Certificate cert)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(cert.getTBSCertificate());
+ v.add(cert.getSignatureAlgorithm());
+ v.add(corruptBitString(cert.getSignature()));
+
+ return Certificate.getInstance(new DERSequence(v));
+ }
+
+ protected DERBitString corruptBitString(DERBitString bs)
+ {
+ return new DERBitString(corruptBit(bs.getBytes()));
+ }
+
+ protected byte[] corruptBit(byte[] bs)
+ {
+ bs = Arrays.clone(bs);
+
+ // Flip a random bit
+ int bit = context.getSecureRandom().nextInt(bs.length << 3);
+ bs[bit >>> 3] ^= (1 << (bit & 7));
+
+ return bs;
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/TlsTestConfig.java b/core/src/test/java/org/spongycastle/crypto/tls/test/TlsTestConfig.java
new file mode 100644
index 00000000..5eaeaff2
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/TlsTestConfig.java
@@ -0,0 +1,96 @@
+package org.spongycastle.crypto.tls.test;
+
+import org.spongycastle.crypto.tls.ConnectionEnd;
+import org.spongycastle.crypto.tls.ProtocolVersion;
+
+public class TlsTestConfig
+{
+ public static final boolean DEBUG = false;
+
+ /**
+ * Client does not authenticate, ignores any certificate request
+ */
+ public static final int CLIENT_AUTH_NONE = 0;
+
+ /**
+ * Client will authenticate if it receives a certificate request
+ */
+ public static final int CLIENT_AUTH_VALID = 1;
+
+ /**
+ * Client will authenticate if it receives a certificate request, with an invalid certificate
+ */
+ public static final int CLIENT_AUTH_INVALID_CERT = 2;
+
+ /**
+ * Client will authenticate if it receives a certificate request, with an invalid CertificateVerify signature
+ */
+ public static final int CLIENT_AUTH_INVALID_VERIFY = 3;
+
+ /**
+ * Server will not request a client certificate
+ */
+ public static final int SERVER_CERT_REQ_NONE = 0;
+
+ /**
+ * Server will request a client certificate but receiving one is optional
+ */
+ public static final int SERVER_CERT_REQ_OPTIONAL = 1;
+
+ /**
+ * Server will request a client certificate and receiving one is mandatory
+ */
+ public static final int SERVER_CERT_REQ_MANDATORY = 2;
+
+ /**
+ * Configures the client authentication behaviour of the test client. Use CLIENT_AUTH_* constants.
+ */
+ public int clientAuth = CLIENT_AUTH_VALID;
+
+ /**
+ * Configures the minimum protocol version the client will accept. If null, uses the library's default.
+ */
+ public ProtocolVersion clientMinimumVersion = null;
+
+ /**
+ * Configures the protocol version the client will offer. If null, uses the library's default.
+ */
+ public ProtocolVersion clientOfferVersion = null;
+
+ /**
+ * Configures whether the test server will send a certificate request.
+ */
+ public int serverCertReq = SERVER_CERT_REQ_OPTIONAL;
+
+ /**
+ * Configures the maximum protocol version the server will accept. If null, uses the library's default.
+ */
+ public ProtocolVersion serverMaximumVersion = null;
+
+ /**
+ * Configures the minimum protocol version the server will accept. If null, uses the library's default.
+ */
+ public ProtocolVersion serverMinimumVersion = null;
+
+ /**
+ * Configures the connection end that a fatal alert is expected to be raised. Use ConnectionEnd.* constants.
+ */
+ public int expectFatalAlertConnectionEnd = -1;
+
+ /**
+ * Configures the type of fatal alert expected to be raised. Use AlertDescription.* constants.
+ */
+ public short expectFatalAlertDescription = -1;
+
+ public void expectClientFatalAlert(short alertDescription)
+ {
+ this.expectFatalAlertConnectionEnd = ConnectionEnd.client;
+ this.expectFatalAlertDescription = alertDescription;
+ }
+
+ public void expectServerFatalAlert(short alertDescription)
+ {
+ this.expectFatalAlertConnectionEnd = ConnectionEnd.server;
+ this.expectFatalAlertDescription = alertDescription;
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/TlsTestServerImpl.java b/core/src/test/java/org/spongycastle/crypto/tls/test/TlsTestServerImpl.java
new file mode 100644
index 00000000..5dc9f278
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/TlsTestServerImpl.java
@@ -0,0 +1,222 @@
+package org.spongycastle.crypto.tls.test;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Vector;
+
+import org.spongycastle.asn1.x509.Certificate;
+import org.spongycastle.crypto.tls.AlertDescription;
+import org.spongycastle.crypto.tls.AlertLevel;
+import org.spongycastle.crypto.tls.CertificateRequest;
+import org.spongycastle.crypto.tls.ClientCertificateType;
+import org.spongycastle.crypto.tls.ConnectionEnd;
+import org.spongycastle.crypto.tls.DefaultTlsServer;
+import org.spongycastle.crypto.tls.HashAlgorithm;
+import org.spongycastle.crypto.tls.ProtocolVersion;
+import org.spongycastle.crypto.tls.SignatureAlgorithm;
+import org.spongycastle.crypto.tls.SignatureAndHashAlgorithm;
+import org.spongycastle.crypto.tls.TlsEncryptionCredentials;
+import org.spongycastle.crypto.tls.TlsFatalAlert;
+import org.spongycastle.crypto.tls.TlsSignerCredentials;
+import org.spongycastle.crypto.tls.TlsUtils;
+
+class TlsTestServerImpl
+ extends DefaultTlsServer
+{
+ protected final TlsTestConfig config;
+
+ protected int firstFatalAlertConnectionEnd = -1;
+ protected short firstFatalAlertDescription = -1;
+
+ TlsTestServerImpl(TlsTestConfig config)
+ {
+ this.config = config;
+ }
+
+ int getFirstFatalAlertConnectionEnd()
+ {
+ return firstFatalAlertConnectionEnd;
+ }
+
+ short getFirstFatalAlertDescription()
+ {
+ return firstFatalAlertDescription;
+ }
+
+ protected ProtocolVersion getMaximumVersion()
+ {
+ if (config.serverMaximumVersion != null)
+ {
+ return config.serverMaximumVersion;
+ }
+
+ return super.getMaximumVersion();
+ }
+
+ protected ProtocolVersion getMinimumVersion()
+ {
+ if (config.serverMinimumVersion != null)
+ {
+ return config.serverMinimumVersion;
+ }
+
+ return super.getMinimumVersion();
+ }
+
+ public void notifyAlertRaised(short alertLevel, short alertDescription, String message, Exception cause)
+ {
+ if (alertLevel == AlertLevel.fatal && firstFatalAlertConnectionEnd == -1)
+ {
+ firstFatalAlertConnectionEnd = ConnectionEnd.server;
+ firstFatalAlertDescription = alertDescription;
+ }
+
+ if (TlsTestConfig.DEBUG)
+ {
+ PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
+ out.println("TLS server raised alert (AlertLevel." + alertLevel + ", AlertDescription." + alertDescription
+ + ")");
+ if (message != null)
+ {
+ out.println("> " + message);
+ }
+ if (cause != null)
+ {
+ cause.printStackTrace(out);
+ }
+ }
+ }
+
+ public void notifyAlertReceived(short alertLevel, short alertDescription)
+ {
+ if (alertLevel == AlertLevel.fatal && firstFatalAlertConnectionEnd == -1)
+ {
+ firstFatalAlertConnectionEnd = ConnectionEnd.client;
+ firstFatalAlertDescription = alertDescription;
+ }
+
+ if (TlsTestConfig.DEBUG)
+ {
+ PrintStream out = (alertLevel == AlertLevel.fatal) ? System.err : System.out;
+ out.println("TLS server received alert (AlertLevel." + alertLevel + ", AlertDescription."
+ + alertDescription + ")");
+ }
+ }
+
+ public ProtocolVersion getServerVersion() throws IOException
+ {
+ ProtocolVersion serverVersion = super.getServerVersion();
+
+ if (TlsTestConfig.DEBUG)
+ {
+ System.out.println("TLS server negotiated " + serverVersion);
+ }
+
+ return serverVersion;
+ }
+
+ public CertificateRequest getCertificateRequest() throws IOException
+ {
+ if (config.serverCertReq == TlsTestConfig.SERVER_CERT_REQ_NONE)
+ {
+ return null;
+ }
+
+ Vector serverSigAlgs = null;
+
+ if (TlsUtils.isSignatureAlgorithmsExtensionAllowed(serverVersion))
+ {
+ short[] hashAlgorithms = new short[]{ HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256,
+ HashAlgorithm.sha224, HashAlgorithm.sha1 };
+ short[] signatureAlgorithms = new short[]{ SignatureAlgorithm.rsa };
+
+ serverSigAlgs = new Vector();
+ for (int i = 0; i < hashAlgorithms.length; ++i)
+ {
+ for (int j = 0; j < signatureAlgorithms.length; ++j)
+ {
+ serverSigAlgs.addElement(new SignatureAndHashAlgorithm(hashAlgorithms[i],
+ signatureAlgorithms[j]));
+ }
+ }
+ }
+
+ Vector certificateAuthorities = new Vector();
+ certificateAuthorities.add(TlsTestUtils.loadCertificateResource("x509-ca.pem").getSubject());
+
+ return new CertificateRequest(new short[]{ ClientCertificateType.rsa_sign }, serverSigAlgs, certificateAuthorities);
+ }
+
+ public void notifyClientCertificate(org.spongycastle.crypto.tls.Certificate clientCertificate)
+ throws IOException
+ {
+ boolean isEmpty = (clientCertificate == null || clientCertificate.isEmpty());
+
+ if (isEmpty != (config.clientAuth == TlsTestConfig.CLIENT_AUTH_NONE))
+ {
+ throw new IllegalStateException();
+ }
+ if (isEmpty && (config.serverCertReq == TlsTestConfig.SERVER_CERT_REQ_MANDATORY))
+ {
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
+ }
+
+ Certificate[] chain = clientCertificate.getCertificateList();
+
+ if (!isEmpty && !chain[0].equals(TlsTestUtils.loadCertificateResource("x509-client.pem")))
+ {
+ throw new TlsFatalAlert(AlertDescription.bad_certificate);
+ }
+
+ if (TlsTestConfig.DEBUG)
+ {
+ System.out.println("TLS server received client certificate chain of length " + chain.length);
+ for (int i = 0; i != chain.length; i++)
+ {
+ Certificate entry = chain[i];
+ // TODO Create fingerprint based on certificate signature algorithm digest
+ System.out.println(" fingerprint:SHA-256 " + TlsTestUtils.fingerprint(entry) + " ("
+ + entry.getSubject() + ")");
+ }
+ }
+ }
+
+ protected TlsEncryptionCredentials getRSAEncryptionCredentials()
+ throws IOException
+ {
+ return TlsTestUtils.loadEncryptionCredentials(context, new String[]{"x509-server.pem", "x509-ca.pem"},
+ "x509-server-key.pem");
+ }
+
+ protected TlsSignerCredentials getRSASignerCredentials()
+ throws IOException
+ {
+ /*
+ * TODO Note that this code fails to provide default value for the client supported
+ * algorithms if it wasn't sent.
+ */
+ SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
+ Vector sigAlgs = supportedSignatureAlgorithms;
+ if (sigAlgs != null)
+ {
+ for (int i = 0; i < sigAlgs.size(); ++i)
+ {
+ SignatureAndHashAlgorithm sigAlg = (SignatureAndHashAlgorithm)
+ sigAlgs.elementAt(i);
+ if (sigAlg.getSignature() == SignatureAlgorithm.rsa)
+ {
+ signatureAndHashAlgorithm = sigAlg;
+ break;
+ }
+ }
+
+ if (signatureAndHashAlgorithm == null)
+ {
+ return null;
+ }
+ }
+
+ return TlsTestUtils.loadSignerCredentials(context, new String[]{"x509-server.pem", "x509-ca.pem"},
+ "x509-server-key.pem", signatureAndHashAlgorithm);
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/TlsTestUtils.java b/core/src/test/java/org/spongycastle/crypto/tls/test/TlsTestUtils.java
new file mode 100644
index 00000000..4bdf154a
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/TlsTestUtils.java
@@ -0,0 +1,157 @@
+package org.spongycastle.crypto.tls.test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import org.spongycastle.asn1.pkcs.RSAPrivateKey;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.crypto.params.RSAPrivateCrtKeyParameters;
+import org.spongycastle.crypto.tls.Certificate;
+import org.spongycastle.crypto.tls.DefaultTlsAgreementCredentials;
+import org.spongycastle.crypto.tls.DefaultTlsEncryptionCredentials;
+import org.spongycastle.crypto.tls.DefaultTlsSignerCredentials;
+import org.spongycastle.crypto.tls.SignatureAndHashAlgorithm;
+import org.spongycastle.crypto.tls.TlsAgreementCredentials;
+import org.spongycastle.crypto.tls.TlsContext;
+import org.spongycastle.crypto.tls.TlsEncryptionCredentials;
+import org.spongycastle.crypto.tls.TlsSignerCredentials;
+import org.spongycastle.crypto.util.PrivateKeyFactory;
+import org.spongycastle.util.encoders.Base64;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.io.pem.PemObject;
+import org.spongycastle.util.io.pem.PemReader;
+
+public class TlsTestUtils
+{
+ static final byte[] rsaCertData = Base64
+ .decode("MIICUzCCAf2gAwIBAgIBATANBgkqhkiG9w0BAQQFADCBjzELMAkGA1UEBhMCQVUxKDAmBgNVBAoMH1RoZSBMZWdpb2"
+ + "4gb2YgdGhlIEJvdW5jeSBDYXN0bGUxEjAQBgNVBAcMCU1lbGJvdXJuZTERMA8GA1UECAwIVmljdG9yaWExLzAtBgkq"
+ + "hkiG9w0BCQEWIGZlZWRiYWNrLWNyeXB0b0Bib3VuY3ljYXN0bGUub3JnMB4XDTEzMDIyNTA2MDIwNVoXDTEzMDIyNT"
+ + "A2MDM0NVowgY8xCzAJBgNVBAYTAkFVMSgwJgYDVQQKDB9UaGUgTGVnaW9uIG9mIHRoZSBCb3VuY3kgQ2FzdGxlMRIw"
+ + "EAYDVQQHDAlNZWxib3VybmUxETAPBgNVBAgMCFZpY3RvcmlhMS8wLQYJKoZIhvcNAQkBFiBmZWVkYmFjay1jcnlwdG"
+ + "9AYm91bmN5Y2FzdGxlLm9yZzBaMA0GCSqGSIb3DQEBAQUAA0kAMEYCQQC0p+RhcFdPFqlwgrIr5YtqKmKXmEGb4Shy"
+ + "pL26Ymz66ZAPdqv7EhOdzl3lZWT6srZUMWWgQMYGiHQg4z2R7X7XAgERo0QwQjAOBgNVHQ8BAf8EBAMCBSAwEgYDVR"
+ + "0lAQH/BAgwBgYEVR0lADAcBgNVHREBAf8EEjAQgQ50ZXN0QHRlc3QudGVzdDANBgkqhkiG9w0BAQQFAANBAHU55Ncz"
+ + "eglREcTg54YLUlGWu2WOYWhit/iM1eeq8Kivro7q98eW52jTuMI3CI5ulqd0hYzshQKQaZ5GDzErMyM=");
+
+ static final byte[] dudRsaCertData = Base64
+ .decode("MIICUzCCAf2gAwIBAgIBATANBgkqhkiG9w0BAQQFADCBjzELMAkGA1UEBhMCQVUxKDAmBgNVBAoMH1RoZSBMZWdpb2"
+ + "4gb2YgdGhlIEJvdW5jeSBDYXN0bGUxEjAQBgNVBAcMCU1lbGJvdXJuZTERMA8GA1UECAwIVmljdG9yaWExLzAtBgkq"
+ + "hkiG9w0BCQEWIGZlZWRiYWNrLWNyeXB0b0Bib3VuY3ljYXN0bGUub3JnMB4XDTEzMDIyNTA1NDcyOFoXDTEzMDIyNT"
+ + "A1NDkwOFowgY8xCzAJBgNVBAYTAkFVMSgwJgYDVQQKDB9UaGUgTGVnaW9uIG9mIHRoZSBCb3VuY3kgQ2FzdGxlMRIw"
+ + "EAYDVQQHDAlNZWxib3VybmUxETAPBgNVBAgMCFZpY3RvcmlhMS8wLQYJKoZIhvcNAQkBFiBmZWVkYmFjay1jcnlwdG"
+ + "9AYm91bmN5Y2FzdGxlLm9yZzBaMA0GCSqGSIb3DQEBAQUAA0kAMEYCQQC0p+RhcFdPFqlwgrIr5YtqKmKXmEGb4Shy"
+ + "pL26Ymz66ZAPdqv7EhOdzl3lZWT6srZUMWWgQMYGiHQg4z2R7X7XAgERo0QwQjAOBgNVHQ8BAf8EBAMCAAEwEgYDVR"
+ + "0lAQH/BAgwBgYEVR0lADAcBgNVHREBAf8EEjAQgQ50ZXN0QHRlc3QudGVzdDANBgkqhkiG9w0BAQQFAANBAJg55PBS"
+ + "weg6obRUKF4FF6fCrWFi6oCYSQ99LWcAeupc5BofW5MstFMhCOaEucuGVqunwT5G7/DweazzCIrSzB0=");
+
+ static String fingerprint(org.spongycastle.asn1.x509.Certificate c)
+ throws IOException
+ {
+ byte[] der = c.getEncoded();
+ byte[] sha1 = sha256DigestOf(der);
+ byte[] hexBytes = Hex.encode(sha1);
+ String hex = new String(hexBytes, "ASCII").toUpperCase();
+
+ StringBuffer fp = new StringBuffer();
+ int i = 0;
+ fp.append(hex.substring(i, i + 2));
+ while ((i += 2) < hex.length())
+ {
+ fp.append(':');
+ fp.append(hex.substring(i, i + 2));
+ }
+ return fp.toString();
+ }
+
+ static byte[] sha256DigestOf(byte[] input)
+ {
+ SHA256Digest d = new SHA256Digest();
+ d.update(input, 0, input.length);
+ byte[] result = new byte[d.getDigestSize()];
+ d.doFinal(result, 0);
+ return result;
+ }
+
+ static TlsAgreementCredentials loadAgreementCredentials(TlsContext context,
+ String[] certResources, String keyResource)
+ throws IOException
+ {
+ Certificate certificate = loadCertificateChain(certResources);
+ AsymmetricKeyParameter privateKey = loadPrivateKeyResource(keyResource);
+
+ return new DefaultTlsAgreementCredentials(certificate, privateKey);
+ }
+
+ static TlsEncryptionCredentials loadEncryptionCredentials(TlsContext context,
+ String[] certResources, String keyResource)
+ throws IOException
+ {
+ Certificate certificate = loadCertificateChain(certResources);
+ AsymmetricKeyParameter privateKey = loadPrivateKeyResource(keyResource);
+
+ return new DefaultTlsEncryptionCredentials(context, certificate, privateKey);
+ }
+
+ static TlsSignerCredentials loadSignerCredentials(TlsContext context, String[] certResources,
+ String keyResource, SignatureAndHashAlgorithm signatureAndHashAlgorithm)
+ throws IOException
+ {
+ Certificate certificate = loadCertificateChain(certResources);
+ AsymmetricKeyParameter privateKey = loadPrivateKeyResource(keyResource);
+
+ return new DefaultTlsSignerCredentials(context, certificate, privateKey, signatureAndHashAlgorithm);
+ }
+
+ static Certificate loadCertificateChain(String[] resources)
+ throws IOException
+ {
+ org.spongycastle.asn1.x509.Certificate[] chain = new org.spongycastle.asn1.x509.Certificate[resources.length];
+ for (int i = 0; i < resources.length; ++i)
+ {
+ chain[i] = loadCertificateResource(resources[i]);
+ }
+ return new Certificate(chain);
+ }
+
+ static org.spongycastle.asn1.x509.Certificate loadCertificateResource(String resource)
+ throws IOException
+ {
+ PemObject pem = loadPemResource(resource);
+ if (pem.getType().endsWith("CERTIFICATE"))
+ {
+ return org.spongycastle.asn1.x509.Certificate.getInstance(pem.getContent());
+ }
+ throw new IllegalArgumentException("'resource' doesn't specify a valid certificate");
+ }
+
+ static AsymmetricKeyParameter loadPrivateKeyResource(String resource)
+ throws IOException
+ {
+ PemObject pem = loadPemResource(resource);
+ if (pem.getType().endsWith("RSA PRIVATE KEY"))
+ {
+ RSAPrivateKey rsa = RSAPrivateKey.getInstance(pem.getContent());
+ return new RSAPrivateCrtKeyParameters(rsa.getModulus(), rsa.getPublicExponent(),
+ rsa.getPrivateExponent(), rsa.getPrime1(), rsa.getPrime2(), rsa.getExponent1(),
+ rsa.getExponent2(), rsa.getCoefficient());
+ }
+ if (pem.getType().endsWith("PRIVATE KEY"))
+ {
+ return PrivateKeyFactory.createKey(pem.getContent());
+ }
+ throw new IllegalArgumentException("'resource' doesn't specify a valid private key");
+ }
+
+ static PemObject loadPemResource(String resource)
+ throws IOException
+ {
+ InputStream s = TlsTestUtils.class.getResourceAsStream(resource);
+ PemReader p = new PemReader(new InputStreamReader(s));
+ PemObject o = p.readPemObject();
+ p.close();
+ return o;
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/crypto/tls/test/UnreliableDatagramTransport.java b/core/src/test/java/org/spongycastle/crypto/tls/test/UnreliableDatagramTransport.java
new file mode 100644
index 00000000..b1b38817
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/crypto/tls/test/UnreliableDatagramTransport.java
@@ -0,0 +1,93 @@
+package org.spongycastle.crypto.tls.test;
+
+import java.io.IOException;
+import java.util.Random;
+
+import org.spongycastle.crypto.tls.DatagramTransport;
+
+public class UnreliableDatagramTransport
+ implements DatagramTransport
+{
+
+ private final DatagramTransport transport;
+ private final Random random;
+ private final int percentPacketLossReceiving, percentPacketLossSending;
+
+ public UnreliableDatagramTransport(DatagramTransport transport, Random random,
+ int percentPacketLossReceiving, int percentPacketLossSending)
+ {
+ if (percentPacketLossReceiving < 0 || percentPacketLossReceiving > 100)
+ {
+ throw new IllegalArgumentException("'percentPacketLossReceiving' out of range");
+ }
+ if (percentPacketLossSending < 0 || percentPacketLossSending > 100)
+ {
+ throw new IllegalArgumentException("'percentPacketLossSending' out of range");
+ }
+
+ this.transport = transport;
+ this.random = random;
+ this.percentPacketLossReceiving = percentPacketLossReceiving;
+ this.percentPacketLossSending = percentPacketLossSending;
+ }
+
+ public int getReceiveLimit()
+ throws IOException
+ {
+ return transport.getReceiveLimit();
+ }
+
+ public int getSendLimit()
+ throws IOException
+ {
+ return transport.getSendLimit();
+ }
+
+ public int receive(byte[] buf, int off, int len, int waitMillis)
+ throws IOException
+ {
+ long endMillis = System.currentTimeMillis() + waitMillis;
+ for (; ; )
+ {
+ int length = transport.receive(buf, off, len, waitMillis);
+ if (length < 0 || !lostPacket(percentPacketLossReceiving))
+ {
+ return length;
+ }
+
+ System.out.println("PACKET LOSS (" + length + " byte packet not received)");
+
+ long now = System.currentTimeMillis();
+ if (now >= endMillis)
+ {
+ return -1;
+ }
+
+ waitMillis = (int)(endMillis - now);
+ }
+ }
+
+ public void send(byte[] buf, int off, int len)
+ throws IOException
+ {
+ if (lostPacket(percentPacketLossSending))
+ {
+ System.out.println("PACKET LOSS (" + len + " byte packet not sent)");
+ }
+ else
+ {
+ transport.send(buf, off, len);
+ }
+ }
+
+ public void close()
+ throws IOException
+ {
+ transport.close();
+ }
+
+ private boolean lostPacket(int percentPacketLoss)
+ {
+ return percentPacketLoss > 0 && random.nextInt(100) < percentPacketLoss;
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/i18n/filter/test/HTMLFilterTest.java b/core/src/test/java/org/spongycastle/i18n/filter/test/HTMLFilterTest.java
new file mode 100644
index 00000000..bd6716b0
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/i18n/filter/test/HTMLFilterTest.java
@@ -0,0 +1,29 @@
+package org.spongycastle.i18n.filter.test;
+
+import org.spongycastle.i18n.filter.Filter;
+import org.spongycastle.i18n.filter.HTMLFilter;
+
+import junit.framework.TestCase;
+
+public class HTMLFilterTest extends TestCase
+{
+
+ private static final String test1 = "hello world";
+
+ private static final String test2 = "<script></script>";
+
+ private static final String test3 = "javascript:attack()";
+
+ private static final String test4 = "\"hello\"";
+
+ public void testDoFilter()
+ {
+ Filter dummy = new HTMLFilter();
+
+ assertEquals("No filtering", "hello world", dummy.doFilter(test1));
+ assertEquals("script tags", "&#60script&#62&#60/script&#62", dummy.doFilter(test2));
+ assertEquals("javascript link", "javascript:attack&#40&#41", dummy.doFilter(test3));
+ assertEquals("", "&#34hello&#34", dummy.doFilter(test4));
+ }
+
+}
diff --git a/core/src/test/java/org/spongycastle/i18n/filter/test/SQLFilterTest.java b/core/src/test/java/org/spongycastle/i18n/filter/test/SQLFilterTest.java
new file mode 100644
index 00000000..a8340c02
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/i18n/filter/test/SQLFilterTest.java
@@ -0,0 +1,20 @@
+
+package org.spongycastle.i18n.filter.test;
+
+import org.spongycastle.i18n.filter.Filter;
+import org.spongycastle.i18n.filter.SQLFilter;
+
+import junit.framework.TestCase;
+
+public class SQLFilterTest extends TestCase
+{
+
+ private static final String test1 = "\'\"=-/\\;\r\n";
+
+ public void testDoFilter()
+ {
+ Filter filter = new SQLFilter();
+ assertEquals("encode special charaters","\\\'\\\"\\=\\-\\/\\\\\\;\\r\\n",filter.doFilter(test1));
+ }
+
+}
diff --git a/core/src/test/java/org/spongycastle/i18n/test/AllTests.java b/core/src/test/java/org/spongycastle/i18n/test/AllTests.java
new file mode 100644
index 00000000..d9872801
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/i18n/test/AllTests.java
@@ -0,0 +1,28 @@
+
+package org.spongycastle.i18n.test;
+
+import org.spongycastle.i18n.filter.test.HTMLFilterTest;
+import org.spongycastle.i18n.filter.test.SQLFilterTest;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class AllTests extends TestCase
+{
+
+ public static void main (String[] args)
+ {
+ junit.textui.TestRunner.run (suite());
+ }
+
+ public static Test suite()
+ {
+ TestSuite suite = new TestSuite("i18n tests");
+ suite.addTestSuite(LocalizedMessageTest.class);
+ suite.addTestSuite(HTMLFilterTest.class);
+ suite.addTestSuite(SQLFilterTest.class);
+ return suite;
+ }
+
+}
diff --git a/core/src/test/java/org/spongycastle/i18n/test/LocalizedMessageTest.java b/core/src/test/java/org/spongycastle/i18n/test/LocalizedMessageTest.java
new file mode 100644
index 00000000..65e03f54
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/i18n/test/LocalizedMessageTest.java
@@ -0,0 +1,185 @@
+package org.spongycastle.i18n.test;
+
+import junit.framework.TestCase;
+import org.spongycastle.i18n.LocaleString;
+import org.spongycastle.i18n.LocalizedMessage;
+import org.spongycastle.i18n.MissingEntryException;
+import org.spongycastle.i18n.filter.HTMLFilter;
+import org.spongycastle.i18n.filter.TrustedInput;
+import org.spongycastle.util.encoders.Hex;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+public class LocalizedMessageTest extends TestCase
+{
+
+ private static final String TEST_RESOURCE = "org.spongycastle.i18n.test.I18nTestMessages";
+ private static final String UTF8_TEST_RESOURCE = "org.spongycastle.i18n.test.I18nUTF8TestMessages";
+
+ /*
+ * test message id's
+ */
+ private static final String timeTestId = "time";
+ private static final String argsTestId = "arguments";
+ private static final String localeTestId = "hello";
+ private static final String missingTestId = "missing";
+ private static final String filterTestId = "filter";
+ private static final String utf8TestId = "utf8";
+
+ /*
+ * Test method for 'org.spongycastle.i18n.LocalizedMessage.getEntry(String,
+ * Locale, TimeZone)'
+ */
+ public void testGetEntry()
+ {
+ LocalizedMessage msg;
+
+ // test different locales
+ msg = new LocalizedMessage(TEST_RESOURCE, localeTestId);
+ assertEquals("Hello world.", msg.getEntry("text", Locale.ENGLISH,
+ TimeZone.getDefault()));
+ assertEquals("Hallo Welt.", msg.getEntry("text", Locale.GERMAN,
+ TimeZone.getDefault()));
+
+ // test arguments
+ Object[] args = new Object[] { "Nobody" };
+ msg = new LocalizedMessage(TEST_RESOURCE, argsTestId, args);
+ assertEquals("My name is Nobody.", msg.getEntry("text", Locale.ENGLISH,
+ TimeZone.getDefault()));
+ assertEquals("Mein Name ist Nobody.", msg.getEntry("text",
+ Locale.GERMAN, TimeZone.getDefault()));
+
+ // test timezones
+ // test date 17. Aug. 13:12:00 GMT
+ Date testDate = new Date(1155820320000l);
+ args = new Object[] { new TrustedInput(testDate) };
+ msg = new LocalizedMessage(TEST_RESOURCE, timeTestId, args);
+ assertEquals("It's 1:12:00 PM GMT at Aug 17, 2006.", msg.getEntry(
+ "text", Locale.ENGLISH, TimeZone.getTimeZone("GMT")));
+ // NOTE: Older JDKs appear to use '.' as the time separator for German locale
+ assertEquals("Es ist 13:12 Uhr GMT am 17.08.2006.", msg.getEntry(
+ "text", Locale.GERMAN, TimeZone.getTimeZone("GMT")).replace("13.12", "13:12"));
+
+ // test time with filter
+ args = new Object[] { new TrustedInput(testDate) };
+ msg = new LocalizedMessage(TEST_RESOURCE, timeTestId, args);
+ msg.setFilter(new HTMLFilter());
+ assertEquals("It's 1:12:00 PM GMT at Aug 17, 2006.", msg.getEntry(
+ "text", Locale.ENGLISH, TimeZone.getTimeZone("GMT")));
+ // NOTE: Older JDKs appear to use '.' as the time separator for German locale
+ assertEquals("Es ist 13:12 Uhr GMT am 17.08.2006.", msg.getEntry(
+ "text", Locale.GERMAN, TimeZone.getTimeZone("GMT")).replace("13.12", "13:12"));
+
+ // test number
+ args = new Object[] { new TrustedInput(new Float(0.2)) };
+ msg = new LocalizedMessage(TEST_RESOURCE, "number", args);
+ assertEquals("20%", msg.getEntry("text", Locale.ENGLISH, TimeZone.getDefault()));
+
+ // test filters
+ String untrusted = "<script>doBadThings()</script>";
+ args = new Object[] { untrusted };
+ msg = new LocalizedMessage(TEST_RESOURCE,filterTestId,args);
+ msg.setFilter(new HTMLFilter());
+ assertEquals("The following part should contain no HTML tags: "
+ + "&#60script&#62doBadThings&#40&#41&#60/script&#62",
+ msg.getEntry("text",Locale.ENGLISH, TimeZone.getDefault()));
+
+ // test missing entry
+ msg = new LocalizedMessage(TEST_RESOURCE, missingTestId);
+ try
+ {
+ String text = msg.getEntry("text", Locale.UK, TimeZone
+ .getDefault());
+ fail();
+ }
+ catch (MissingEntryException e)
+ {
+// System.out.println(e.getDebugMsg());
+ }
+
+ // test missing entry
+ try
+ {
+ URLClassLoader cl = URLClassLoader.newInstance(new URL[] {new URL("file:///nonexistent/")});
+ msg = new LocalizedMessage(TEST_RESOURCE, missingTestId);
+ msg.setClassLoader(cl);
+ try
+ {
+ String text = msg.getEntry("text", Locale.UK, TimeZone
+ .getDefault());
+ fail();
+ }
+ catch (MissingEntryException e)
+ {
+// System.out.println(e.getDebugMsg());
+ }
+ }
+ catch (MalformedURLException e)
+ {
+
+ }
+
+ // test utf8
+ try
+ {
+// String expectedUtf8 = "some umlauts äöüèéà";
+ String expectedUtf8 = new String(Hex.decode("736f6d6520756d6c6175747320c3a4c3b6c3bcc3a8c3a9c3a0"), "UTF-8");
+ msg = new LocalizedMessage(UTF8_TEST_RESOURCE, utf8TestId, "UTF-8");
+ assertEquals(expectedUtf8, msg.getEntry("text", Locale.GERMAN, TimeZone.getDefault()));
+ }
+ catch (UnsupportedEncodingException e)
+ {
+
+ }
+
+ }
+
+ public void testLocalizedArgs()
+ {
+ LocaleString ls = new LocaleString(TEST_RESOURCE, "name");
+
+ // without filter
+ Object[] args = new Object[] { ls };
+ LocalizedMessage msg = new LocalizedMessage(TEST_RESOURCE, argsTestId, args);
+ assertEquals("My name is John.", msg.getEntry("text", Locale.ENGLISH,
+ TimeZone.getDefault()));
+ assertEquals("Mein Name ist Hans.", msg.getEntry("text",
+ Locale.GERMAN, TimeZone.getDefault()));
+
+ // with filter
+ msg.setFilter(new HTMLFilter());
+ assertEquals("My name is John.", msg.getEntry("text", Locale.ENGLISH,
+ TimeZone.getDefault()));
+ assertEquals("Mein Name ist Hans.", msg.getEntry("text",
+ Locale.GERMAN, TimeZone.getDefault()));
+
+ // add extra args
+ LocaleString lsExtra = new LocaleString(TEST_RESOURCE, "hello.text");
+ msg.setExtraArguments(new Object[] {" ", lsExtra});
+ assertEquals("My name is John. Hello world.", msg.getEntry("text", Locale.ENGLISH,
+ TimeZone.getDefault()));
+ assertEquals("Mein Name ist Hans. Hallo Welt.", msg.getEntry("text",
+ Locale.GERMAN, TimeZone.getDefault()));
+
+ // missing localized arg
+ try
+ {
+ ls = new LocaleString(TEST_RESOURCE, "noname");
+ args = new Object[] { ls };
+ msg = new LocalizedMessage(TEST_RESOURCE, argsTestId, args);
+ msg.getEntry("text", Locale.ENGLISH, TimeZone.getDefault());
+ fail();
+ }
+ catch (MissingEntryException e)
+ {
+ assertEquals("Can't find entry noname in resource file org.spongycastle.i18n.test.I18nTestMessages.", e.getMessage());
+ }
+ }
+
+}
diff --git a/core/src/test/java/org/spongycastle/math/ec/test/AllTests.java b/core/src/test/java/org/spongycastle/math/ec/test/AllTests.java
new file mode 100644
index 00000000..5388c743
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/math/ec/test/AllTests.java
@@ -0,0 +1,40 @@
+package org.spongycastle.math.ec.test;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests
+{
+ public static void main (String[] args)
+ throws Exception
+ {
+ junit.textui.TestRunner.run(suite());
+ }
+
+ public static Test suite()
+ throws Exception
+ {
+ TestSuite suite = new TestSuite("EC Math tests");
+
+ suite.addTest(ECAlgorithmsTest.suite());
+ suite.addTest(ECPointTest.suite());
+
+ return suite;
+ }
+
+ static List enumToList(Enumeration en)
+ {
+ List rv = new ArrayList();
+
+ while (en.hasMoreElements())
+ {
+ rv.add(en.nextElement());
+ }
+
+ return rv;
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/math/ec/test/ECAlgorithmsTest.java b/core/src/test/java/org/spongycastle/math/ec/test/ECAlgorithmsTest.java
new file mode 100644
index 00000000..153738b5
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/math/ec/test/ECAlgorithmsTest.java
@@ -0,0 +1,168 @@
+package org.spongycastle.math.ec.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.spongycastle.asn1.x9.ECNamedCurveTable;
+import org.spongycastle.asn1.x9.X9ECParameters;
+import org.spongycastle.crypto.ec.CustomNamedCurves;
+import org.spongycastle.math.ec.ECAlgorithms;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECPoint;
+
+public class ECAlgorithmsTest extends TestCase
+{
+ private static final int SCALE = 4;
+ private static final SecureRandom RND = new SecureRandom();
+
+ public void testSumOfMultiplies()
+ {
+ ArrayList x9s = getTestCurves();
+ Iterator it = x9s.iterator();
+ while (it.hasNext())
+ {
+ X9ECParameters x9 = (X9ECParameters)it.next();
+
+ ECPoint[] points = new ECPoint[SCALE];
+ BigInteger[] scalars = new BigInteger[SCALE];
+ for (int i = 0; i < SCALE; ++i)
+ {
+ points[i] = getRandomPoint(x9);
+ scalars[i] = getRandomScalar(x9);
+ }
+
+ ECPoint u = x9.getCurve().getInfinity();
+ for (int i = 0; i < SCALE; ++i)
+ {
+ u = u.add(points[i].multiply(scalars[i]));
+
+ ECPoint v = ECAlgorithms.sumOfMultiplies(copyPoints(points, i + 1), copyScalars(scalars, i + 1));
+
+ ECPoint[] results = new ECPoint[]{ u, v };
+ x9.getCurve().normalizeAll(results);
+
+ assertPointsEqual("ECAlgorithms.sumOfMultiplies is incorrect", results[0], results[1]);
+ }
+ }
+ }
+
+ public void testSumOfTwoMultiplies()
+ {
+ ArrayList x9s = getTestCurves();
+ Iterator it = x9s.iterator();
+ while (it.hasNext())
+ {
+ X9ECParameters x9 = (X9ECParameters)it.next();
+
+ ECPoint p = getRandomPoint(x9);
+ BigInteger a = getRandomScalar(x9);
+
+ for (int i = 0; i < SCALE; ++i)
+ {
+ ECPoint q = getRandomPoint(x9);
+ BigInteger b = getRandomScalar(x9);
+
+ ECPoint u = p.multiply(a).add(q.multiply(b));
+ ECPoint v = ECAlgorithms.shamirsTrick(p, a, q, b);
+ ECPoint w = ECAlgorithms.sumOfTwoMultiplies(p, a, q, b);
+
+ ECPoint[] results = new ECPoint[]{ u, v, w };
+ x9.getCurve().normalizeAll(results);
+
+ assertPointsEqual("ECAlgorithms.shamirsTrick is incorrect", results[0], results[1]);
+ assertPointsEqual("ECAlgorithms.sumOfTwoMultiplies is incorrect", results[0], results[2]);
+
+ p = q;
+ a = b;
+ }
+ }
+ }
+
+ private void assertPointsEqual(String message, ECPoint a, ECPoint b)
+ {
+ assertEquals(message, a, b);
+ }
+
+ private ECPoint[] copyPoints(ECPoint[] ps, int len)
+ {
+ ECPoint[] result = new ECPoint[len];
+ System.arraycopy(ps, 0, result, 0, len);
+ return result;
+ }
+
+ private BigInteger[] copyScalars(BigInteger[] ks, int len)
+ {
+ BigInteger[] result = new BigInteger[len];
+ System.arraycopy(ks, 0, result, 0, len);
+ return result;
+ }
+
+ private ECPoint getRandomPoint(X9ECParameters x9)
+ {
+ return x9.getG().multiply(getRandomScalar(x9));
+ }
+
+ private BigInteger getRandomScalar(X9ECParameters x9)
+ {
+ return new BigInteger(x9.getN().bitLength(), RND);
+ }
+
+ private ArrayList getTestCurves()
+ {
+ ArrayList x9s = new ArrayList();
+ Set names = new HashSet(AllTests.enumToList(ECNamedCurveTable.getNames()));
+ names.addAll(AllTests.enumToList(CustomNamedCurves.getNames()));
+
+ Iterator it = names.iterator();
+ while (it.hasNext())
+ {
+ String name = (String)it.next();
+
+ X9ECParameters x9 = ECNamedCurveTable.getByName(name);
+ if (x9 != null)
+ {
+ addTestCurves(x9s, x9);
+ }
+
+ x9 = CustomNamedCurves.getByName(name);
+ if (x9 != null)
+ {
+ addTestCurves(x9s, x9);
+ }
+ }
+ return x9s;
+ }
+
+ private void addTestCurves(ArrayList x9s, X9ECParameters x9)
+ {
+ ECCurve curve = x9.getCurve();
+
+ int[] coords = ECCurve.getAllCoordinateSystems();
+ for (int i = 0; i < coords.length; ++i)
+ {
+ int coord = coords[i];
+ if (curve.getCoordinateSystem() == coord)
+ {
+ x9s.add(x9);
+ }
+ else if (curve.supportsCoordinateSystem(coord))
+ {
+ ECCurve c = curve.configure().setCoordinateSystem(coord).create();
+ x9s.add(new X9ECParameters(c, c.importPoint(x9.getG()), x9.getN(), x9.getH()));
+ }
+ }
+ }
+
+ public static Test suite()
+ {
+ return new TestSuite(ECAlgorithmsTest.class);
+ }
+
+}
diff --git a/core/src/test/java/org/spongycastle/math/ec/test/ECPointPerformanceTest.java b/core/src/test/java/org/spongycastle/math/ec/test/ECPointPerformanceTest.java
new file mode 100644
index 00000000..6be0c00b
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/math/ec/test/ECPointPerformanceTest.java
@@ -0,0 +1,198 @@
+package org.spongycastle.math.ec.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import junit.framework.TestCase;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.x9.ECNamedCurveTable;
+import org.spongycastle.asn1.x9.X9ECParameters;
+import org.spongycastle.crypto.ec.CustomNamedCurves;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.util.Times;
+
+/**
+ * Compares the performance of the the window NAF point multiplication against conventional point
+ * multiplication.
+ */
+public class ECPointPerformanceTest extends TestCase
+{
+ static final int MILLIS_PER_ROUND = 200;
+ static final int MILLIS_WARMUP = 1000;
+
+ static final int MULTS_PER_CHECK = 16;
+ static final int NUM_ROUNDS = 10;
+
+ private static String[] COORD_NAMES = new String[]{ "AFFINE", "HOMOGENEOUS", "JACOBIAN", "JACOBIAN-CHUDNOVSKY",
+ "JACOBIAN-MODIFIED", "LAMBDA-AFFINE", "LAMBDA-PROJECTIVE", "SKEWED" };
+
+ private void randMult(String curveName) throws Exception
+ {
+ X9ECParameters spec = ECNamedCurveTable.getByName(curveName);
+ if (spec != null)
+ {
+ randMult(curveName, spec);
+ }
+
+ spec = CustomNamedCurves.getByName(curveName);
+ if (spec != null)
+ {
+ randMult(curveName + " (custom)", spec);
+ }
+ }
+
+ private void randMult(String label, X9ECParameters spec) throws Exception
+ {
+ ECCurve C = spec.getCurve();
+ ECPoint G = (ECPoint)spec.getG();
+ BigInteger n = spec.getN();
+
+ SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
+ random.setSeed(System.currentTimeMillis());
+
+ System.out.println(label);
+
+ int[] coords = ECCurve.getAllCoordinateSystems();
+ for (int i = 0; i < coords.length; ++i)
+ {
+ int coord = coords[i];
+ if (C.supportsCoordinateSystem(coord))
+ {
+ ECCurve c = C;
+ ECPoint g = G;
+
+ boolean defaultCoord = (c.getCoordinateSystem() == coord);
+ if (!defaultCoord)
+ {
+ c = C.configure().setCoordinateSystem(coord).create();
+ g = c.importPoint(G);
+ }
+
+ double avgRate = randMult(random, g, n);
+ String coordName = COORD_NAMES[coord];
+ StringBuffer sb = new StringBuffer();
+ sb.append(" ");
+ sb.append(defaultCoord ? '*' : ' ');
+ sb.append(coordName);
+ for (int j = sb.length(); j < 30; ++j)
+ {
+ sb.append(' ');
+ }
+ sb.append(": ");
+ sb.append(avgRate);
+ sb.append(" mults/sec");
+ for (int j = sb.length(); j < 64; ++j)
+ {
+ sb.append(' ');
+ }
+ sb.append('(');
+ sb.append(1000.0 / avgRate);
+ sb.append(" millis/mult)");
+ System.out.println(sb.toString());
+ }
+ }
+ }
+
+ private double randMult(SecureRandom random, ECPoint g, BigInteger n) throws Exception
+ {
+ BigInteger[] ks = new BigInteger[128];
+ for (int i = 0; i < ks.length; ++i)
+ {
+ ks[i] = new BigInteger(n.bitLength() - 1, random);
+ }
+
+ int ki = 0;
+ ECPoint p = g;
+
+ {
+ long startTime = Times.nanoTime();
+ long goalTime = startTime + 1000000L * MILLIS_WARMUP;
+
+ do
+ {
+ BigInteger k = ks[ki];
+ p = g.multiply(k);
+ if ((ki & 1) != 0)
+ {
+ g = p;
+ }
+ if (++ki == ks.length)
+ {
+ ki = 0;
+ }
+ }
+ while (Times.nanoTime() < goalTime);
+ }
+
+ double minRate = Double.MAX_VALUE, maxRate = Double.MIN_VALUE, totalRate = 0.0;
+
+ for (int i = 1; i <= NUM_ROUNDS; i++)
+ {
+ long startTime = Times.nanoTime();
+ long goalTime = startTime + 1000000L * MILLIS_PER_ROUND;
+ long count = 0, endTime;
+
+ do
+ {
+ ++count;
+
+ for (int j = 0; j < MULTS_PER_CHECK; ++j)
+ {
+ BigInteger k = ks[ki];
+ p = g.multiply(k);
+ if ((ki & 1) != 0)
+ {
+ g = p;
+ }
+ if (++ki == ks.length)
+ {
+ ki = 0;
+ }
+ }
+
+ endTime = Times.nanoTime();
+ }
+ while (endTime < goalTime);
+
+ double roundElapsed = (double)(endTime - startTime);
+ double roundRate = count * MULTS_PER_CHECK * 1000000000L / roundElapsed;
+
+ minRate = Math.min(minRate, roundRate);
+ maxRate = Math.max(maxRate, roundRate);
+ totalRate += roundRate;
+ }
+
+ return (totalRate - minRate - maxRate) / (NUM_ROUNDS - 2);
+ }
+
+ public void testMultiply() throws Exception
+ {
+ SortedSet names = new TreeSet(AllTests.enumToList(ECNamedCurveTable.getNames()));
+ names.addAll(AllTests.enumToList(CustomNamedCurves.getNames()));
+
+ Set oids = new HashSet();
+
+ Iterator it = names.iterator();
+ while (it.hasNext())
+ {
+ String name = (String)it.next();
+ ASN1ObjectIdentifier oid = ECNamedCurveTable.getOID(name);
+ if (oid == null)
+ {
+ oid = CustomNamedCurves.getOID(name);
+ }
+ if (oid != null && !oids.add(oid))
+ {
+ continue;
+ }
+
+ randMult(name);
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/math/ec/test/ECPointTest.java b/core/src/test/java/org/spongycastle/math/ec/test/ECPointTest.java
new file mode 100644
index 00000000..5987e22f
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/math/ec/test/ECPointTest.java
@@ -0,0 +1,521 @@
+package org.spongycastle.math.ec.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.spongycastle.asn1.x9.ECNamedCurveTable;
+import org.spongycastle.asn1.x9.X9ECParameters;
+import org.spongycastle.crypto.ec.CustomNamedCurves;
+import org.spongycastle.math.ec.ECAlgorithms;
+import org.spongycastle.math.ec.ECConstants;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+import org.spongycastle.util.BigIntegers;
+
+/**
+ * Test class for {@link org.spongycastle.math.ec.ECPoint ECPoint}. All
+ * literature values are taken from "Guide to elliptic curve cryptography",
+ * Darrel Hankerson, Alfred J. Menezes, Scott Vanstone, 2004, Springer-Verlag
+ * New York, Inc.
+ */
+public class ECPointTest extends TestCase
+{
+ /**
+ * Random source used to generate random points
+ */
+ private SecureRandom secRand = new SecureRandom();
+
+ private ECPointTest.Fp fp = null;
+
+ private ECPointTest.F2m f2m = null;
+
+ /**
+ * Nested class containing sample literature values for <code>Fp</code>.
+ */
+ public static class Fp
+ {
+ private final BigInteger q = new BigInteger("29");
+
+ private final BigInteger a = new BigInteger("4");
+
+ private final BigInteger b = new BigInteger("20");
+
+ private final BigInteger n = new BigInteger("38");
+
+ private final BigInteger h = new BigInteger("1");
+
+ private final ECCurve curve = new ECCurve.Fp(q, a, b, n, h);
+
+ private final ECPoint infinity = curve.getInfinity();
+
+ private final int[] pointSource = { 5, 22, 16, 27, 13, 6, 14, 6 };
+
+ private ECPoint[] p = new ECPoint[pointSource.length / 2];
+
+ /**
+ * Creates the points on the curve with literature values.
+ */
+ private void createPoints()
+ {
+ for (int i = 0; i < pointSource.length / 2; i++)
+ {
+ p[i] = curve.createPoint(
+ new BigInteger(Integer.toString(pointSource[2 * i])),
+ new BigInteger(Integer.toString(pointSource[2 * i + 1])));
+ }
+ }
+ }
+
+ /**
+ * Nested class containing sample literature values for <code>F2m</code>.
+ */
+ public static class F2m
+ {
+ // Irreducible polynomial for TPB z^4 + z + 1
+ private final int m = 4;
+
+ private final int k1 = 1;
+
+ // a = z^3
+ private final BigInteger aTpb = new BigInteger("1000", 2);
+
+ // b = z^3 + 1
+ private final BigInteger bTpb = new BigInteger("1001", 2);
+
+ private final BigInteger n = new BigInteger("23");
+
+ private final BigInteger h = new BigInteger("1");
+
+ private final ECCurve.F2m curve = new ECCurve.F2m(m, k1, aTpb, bTpb, n, h);
+
+ private final ECPoint.F2m infinity = (ECPoint.F2m) curve.getInfinity();
+
+ private final String[] pointSource = { "0010", "1111", "1100", "1100",
+ "0001", "0001", "1011", "0010" };
+
+ private ECPoint[] p = new ECPoint[pointSource.length / 2];
+
+ /**
+ * Creates the points on the curve with literature values.
+ */
+ private void createPoints()
+ {
+ for (int i = 0; i < pointSource.length / 2; i++)
+ {
+ p[i] = curve.createPoint(
+ new BigInteger(pointSource[2 * i], 2),
+ new BigInteger(pointSource[2 * i + 1], 2));
+ }
+ }
+ }
+
+ public void setUp()
+ {
+ fp = new ECPointTest.Fp();
+ fp.createPoints();
+
+ f2m = new ECPointTest.F2m();
+ f2m.createPoints();
+ }
+
+ /**
+ * Tests, if inconsistent points can be created, i.e. points with exactly
+ * one null coordinate (not permitted).
+ */
+ public void testPointCreationConsistency()
+ {
+ try
+ {
+ ECPoint bad = fp.curve.createPoint(new BigInteger("12"), null);
+ fail();
+ }
+ catch (IllegalArgumentException expected)
+ {
+ }
+
+ try
+ {
+ ECPoint bad = fp.curve.createPoint(null, new BigInteger("12"));
+ fail();
+ }
+ catch (IllegalArgumentException expected)
+ {
+ }
+
+ try
+ {
+ ECPoint bad = f2m.curve.createPoint(new BigInteger("1011"), null);
+ fail();
+ }
+ catch (IllegalArgumentException expected)
+ {
+ }
+
+ try
+ {
+ ECPoint bad = f2m.curve.createPoint(null, new BigInteger("1011"));
+ fail();
+ }
+ catch (IllegalArgumentException expected)
+ {
+ }
+ }
+
+ /**
+ * Tests <code>ECPoint.add()</code> against literature values.
+ *
+ * @param p
+ * The array of literature values.
+ * @param infinity
+ * The point at infinity on the respective curve.
+ */
+ private void implTestAdd(ECPoint[] p, ECPoint infinity)
+ {
+ assertPointsEqual("p0 plus p1 does not equal p2", p[2], p[0].add(p[1]));
+ assertPointsEqual("p1 plus p0 does not equal p2", p[2], p[1].add(p[0]));
+ for (int i = 0; i < p.length; i++)
+ {
+ assertPointsEqual("Adding infinity failed", p[i], p[i].add(infinity));
+ assertPointsEqual("Adding to infinity failed", p[i], infinity.add(p[i]));
+ }
+ }
+
+ /**
+ * Calls <code>implTestAdd()</code> for <code>Fp</code> and
+ * <code>F2m</code>.
+ */
+ public void testAdd()
+ {
+ implTestAdd(fp.p, fp.infinity);
+ implTestAdd(f2m.p, f2m.infinity);
+ }
+
+ /**
+ * Tests <code>ECPoint.twice()</code> against literature values.
+ *
+ * @param p
+ * The array of literature values.
+ */
+ private void implTestTwice(ECPoint[] p)
+ {
+ assertPointsEqual("Twice incorrect", p[3], p[0].twice());
+ assertPointsEqual("Add same point incorrect", p[3], p[0].add(p[0]));
+ }
+
+ /**
+ * Calls <code>implTestTwice()</code> for <code>Fp</code> and
+ * <code>F2m</code>.
+ */
+ public void testTwice()
+ {
+ implTestTwice(fp.p);
+ implTestTwice(f2m.p);
+ }
+
+ private void implTestThreeTimes(ECPoint[] p)
+ {
+ ECPoint P = p[0];
+ ECPoint _3P = P.add(P).add(P);
+ assertPointsEqual("ThreeTimes incorrect", _3P, P.threeTimes());
+ assertPointsEqual("TwicePlus incorrect", _3P, P.twicePlus(P));
+ }
+
+ /**
+ * Calls <code>implTestThreeTimes()</code> for <code>Fp</code> and
+ * <code>F2m</code>.
+ */
+ public void testThreeTimes()
+ {
+ implTestThreeTimes(fp.p);
+ implTestThreeTimes(f2m.p);
+ }
+
+ /**
+ * Goes through all points on an elliptic curve and checks, if adding a
+ * point <code>k</code>-times is the same as multiplying the point by
+ * <code>k</code>, for all <code>k</code>. Should be called for points
+ * on very small elliptic curves only.
+ *
+ * @param p
+ * The base point on the elliptic curve.
+ * @param infinity
+ * The point at infinity on the elliptic curve.
+ */
+ private void implTestAllPoints(ECPoint p, ECPoint infinity)
+ {
+ ECPoint adder = infinity;
+ ECPoint multiplier = infinity;
+
+ BigInteger i = BigInteger.valueOf(1);
+ do
+ {
+ adder = adder.add(p);
+ multiplier = p.multiply(i);
+ assertPointsEqual("Results of add() and multiply() are inconsistent "
+ + i, adder, multiplier);
+ i = i.add(BigInteger.ONE);
+ }
+ while (!(adder.equals(infinity)));
+ }
+
+ /**
+ * Calls <code>implTestAllPoints()</code> for the small literature curves,
+ * both for <code>Fp</code> and <code>F2m</code>.
+ */
+ public void testAllPoints()
+ {
+ for (int i = 0; i < fp.p.length; i++)
+ {
+ implTestAllPoints(fp.p[0], fp.infinity);
+ }
+
+ for (int i = 0; i < f2m.p.length; i++)
+ {
+ implTestAllPoints(f2m.p[0], f2m.infinity);
+ }
+ }
+
+ /**
+ * Checks, if the point multiplication algorithm of the given point yields
+ * the same result as point multiplication done by the reference
+ * implementation given in <code>multiply()</code>. This method chooses a
+ * random number by which the given point <code>p</code> is multiplied.
+ *
+ * @param p
+ * The point to be multiplied.
+ * @param numBits
+ * The bitlength of the random number by which <code>p</code>
+ * is multiplied.
+ */
+ private void implTestMultiply(ECPoint p, int numBits)
+ {
+ BigInteger k = new BigInteger(numBits, secRand);
+ ECPoint ref = ECAlgorithms.referenceMultiply(p, k);
+ ECPoint q = p.multiply(k);
+ assertPointsEqual("ECPoint.multiply is incorrect", ref, q);
+ }
+
+ /**
+ * Checks, if the point multiplication algorithm of the given point yields
+ * the same result as point multiplication done by the reference
+ * implementation given in <code>multiply()</code>. This method tests
+ * multiplication of <code>p</code> by every number of bitlength
+ * <code>numBits</code> or less.
+ *
+ * @param p
+ * The point to be multiplied.
+ * @param numBits
+ * Try every multiplier up to this bitlength
+ */
+ private void implTestMultiplyAll(ECPoint p, int numBits)
+ {
+ BigInteger bound = BigInteger.ONE.shiftLeft(numBits);
+ BigInteger k = BigInteger.ZERO;
+
+ do
+ {
+ ECPoint ref = ECAlgorithms.referenceMultiply(p, k);
+ ECPoint q = p.multiply(k);
+ assertPointsEqual("ECPoint.multiply is incorrect", ref, q);
+ k = k.add(BigInteger.ONE);
+ }
+ while (k.compareTo(bound) < 0);
+ }
+
+ /**
+ * Tests <code>ECPoint.add()</code> and <code>ECPoint.subtract()</code>
+ * for the given point and the given point at infinity.
+ *
+ * @param p
+ * The point on which the tests are performed.
+ * @param infinity
+ * The point at infinity on the same curve as <code>p</code>.
+ */
+ private void implTestAddSubtract(ECPoint p, ECPoint infinity)
+ {
+ assertPointsEqual("Twice and Add inconsistent", p.twice(), p.add(p));
+ assertPointsEqual("Twice p - p is not p", p, p.twice().subtract(p));
+ assertPointsEqual("TwicePlus(p, -p) is not p", p, p.twicePlus(p.negate()));
+ assertPointsEqual("p - p is not infinity", infinity, p.subtract(p));
+ assertPointsEqual("p plus infinity is not p", p, p.add(infinity));
+ assertPointsEqual("infinity plus p is not p", p, infinity.add(p));
+ assertPointsEqual("infinity plus infinity is not infinity ", infinity, infinity.add(infinity));
+ assertPointsEqual("Twice infinity is not infinity ", infinity, infinity.twice());
+ }
+
+ /**
+ * Calls <code>implTestAddSubtract()</code> for literature values, both
+ * for <code>Fp</code> and <code>F2m</code>.
+ */
+ public void testAddSubtractMultiplySimple()
+ {
+ int fpBits = fp.curve.getOrder().bitLength();
+ for (int iFp = 0; iFp < fp.pointSource.length / 2; iFp++)
+ {
+ implTestAddSubtract(fp.p[iFp], fp.infinity);
+
+ implTestMultiplyAll(fp.p[iFp], fpBits);
+ implTestMultiplyAll(fp.infinity, fpBits);
+ }
+
+ int f2mBits = f2m.curve.getOrder().bitLength();
+ for (int iF2m = 0; iF2m < f2m.pointSource.length / 2; iF2m++)
+ {
+ implTestAddSubtract(f2m.p[iF2m], f2m.infinity);
+
+ implTestMultiplyAll(f2m.p[iF2m], f2mBits);
+ implTestMultiplyAll(f2m.infinity, f2mBits);
+ }
+ }
+
+ /**
+ * Test encoding with and without point compression.
+ *
+ * @param p
+ * The point to be encoded and decoded.
+ */
+ private void implTestEncoding(ECPoint p)
+ {
+ // Not Point Compression
+ byte[] unCompBarr = p.getEncoded(false);
+ ECPoint decUnComp = p.getCurve().decodePoint(unCompBarr);
+ assertPointsEqual("Error decoding uncompressed point", p, decUnComp);
+
+ // Point compression
+ byte[] compBarr = p.getEncoded(true);
+ ECPoint decComp = p.getCurve().decodePoint(compBarr);
+ assertPointsEqual("Error decoding compressed point", p, decComp);
+ }
+
+ private void implAddSubtractMultiplyTwiceEncodingTest(ECCurve curve, ECPoint q, BigInteger n)
+ {
+ // Get point at infinity on the curve
+ ECPoint infinity = curve.getInfinity();
+
+ implTestAddSubtract(q, infinity);
+ implTestMultiply(q, n.bitLength());
+ implTestMultiply(infinity, n.bitLength());
+
+ ECPoint p = q;
+ for (int i = 0; i < 10; ++i)
+ {
+ implTestEncoding(p);
+ p = p.twice();
+ }
+ }
+
+ private void implSqrtTest(ECCurve c)
+ {
+ if (ECAlgorithms.isFpCurve(c))
+ {
+ BigInteger p = c.getField().getCharacteristic();
+ BigInteger pMinusOne = p.subtract(ECConstants.ONE);
+ BigInteger legendreExponent = p.shiftRight(1);
+
+ int count = 0;
+ while (count < 10)
+ {
+ BigInteger nonSquare = BigIntegers.createRandomInRange(ECConstants.TWO, pMinusOne, secRand);
+ if (!nonSquare.modPow(legendreExponent, p).equals(ECConstants.ONE))
+ {
+ ECFieldElement root = c.fromBigInteger(nonSquare).sqrt();
+ assertNull(root);
+ ++count;
+ }
+ }
+ }
+ }
+
+ private void implAddSubtractMultiplyTwiceEncodingTestAllCoords(X9ECParameters x9ECParameters)
+ {
+ BigInteger n = x9ECParameters.getN();
+ ECPoint G = x9ECParameters.getG();
+ ECCurve C = x9ECParameters.getCurve();
+
+ int[] coords = ECCurve.getAllCoordinateSystems();
+ for (int i = 0; i < coords.length; ++i)
+ {
+ int coord = coords[i];
+ if (C.supportsCoordinateSystem(coord))
+ {
+ ECCurve c = C;
+ ECPoint g = G;
+
+ if (c.getCoordinateSystem() != coord)
+ {
+ c = C.configure().setCoordinateSystem(coord).create();
+ g = c.importPoint(G);
+ }
+
+ // The generator is multiplied by random b to get random q
+ BigInteger b = new BigInteger(n.bitLength(), secRand);
+ ECPoint q = g.multiply(b).normalize();
+
+ implAddSubtractMultiplyTwiceEncodingTest(c, q, n);
+
+ implSqrtTest(c);
+ }
+ }
+ }
+
+ /**
+ * Calls <code>implTestAddSubtract()</code>,
+ * <code>implTestMultiply</code> and <code>implTestEncoding</code> for
+ * the standard elliptic curves as given in <code>SECNamedCurves</code>.
+ */
+ public void testAddSubtractMultiplyTwiceEncoding()
+ {
+ Set names = new HashSet(enumToList(ECNamedCurveTable.getNames()));
+ names.addAll(enumToList(CustomNamedCurves.getNames()));
+
+ Iterator it = names.iterator();
+ while (it.hasNext())
+ {
+ String name = (String)it.next();
+
+ X9ECParameters x9ECParameters = ECNamedCurveTable.getByName(name);
+ if (x9ECParameters != null)
+ {
+ implAddSubtractMultiplyTwiceEncodingTestAllCoords(x9ECParameters);
+ }
+
+ x9ECParameters = CustomNamedCurves.getByName(name);
+ if (x9ECParameters != null)
+ {
+ implAddSubtractMultiplyTwiceEncodingTestAllCoords(x9ECParameters);
+ }
+ }
+ }
+
+ private List enumToList(Enumeration en)
+ {
+ List rv = new ArrayList();
+
+ while (en.hasMoreElements())
+ {
+ rv.add(en.nextElement());
+ }
+
+ return rv;
+ }
+
+ private void assertPointsEqual(String message, ECPoint a, ECPoint b)
+ {
+ assertEquals(message, a, b);
+ }
+
+ public static Test suite()
+ {
+ return new TestSuite(ECPointTest.class);
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/math/ec/test/F2mProofer.java b/core/src/test/java/org/spongycastle/math/ec/test/F2mProofer.java
new file mode 100644
index 00000000..9d7e5195
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/math/ec/test/F2mProofer.java
@@ -0,0 +1,203 @@
+package org.spongycastle.math.ec.test;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+
+import org.spongycastle.asn1.sec.SECNamedCurves;
+import org.spongycastle.asn1.x9.X9ECParameters;
+import org.spongycastle.math.ec.ECFieldElement;
+import org.spongycastle.math.ec.ECPoint;
+
+public class F2mProofer
+{
+ private static final int NUM_SAMPLES = 1000;
+
+ private static final String PATH = "crypto/test/src/org/spongycastle/math/ec/test/samples/";
+
+ private static final String INPUT_FILE_NAME_PREFIX = "Input_";
+
+ private static final String RESULT_FILE_NAME_PREFIX = "Output_";
+
+ /**
+ * The standard curves on which the tests are done
+ */
+ public static final String[] CURVES = { "sect163r2", "sect233r1",
+ "sect283r1", "sect409r1", "sect571r1" };
+
+ private String pointToString(ECPoint.F2m p)
+ {
+ ECFieldElement.F2m x = (ECFieldElement.F2m) p.getAffineXCoord();
+ ECFieldElement.F2m y = (ECFieldElement.F2m) p.getAffineYCoord();
+
+ int m = x.getM();
+ int len = m / 2 + 5;
+
+ StringBuffer sb = new StringBuffer(len);
+ sb.append('(');
+ sb.append(x.toBigInteger().toString(16));
+ sb.append(", ");
+ sb.append(y.toBigInteger().toString(16));
+ sb.append(')');
+
+ return sb.toString();
+ }
+
+ private void generateRandomInput(X9ECParameters x9ECParameters)
+ throws NoSuchAlgorithmException, IOException
+ {
+ ECPoint.F2m g = (ECPoint.F2m) x9ECParameters.getG();
+ int m = ((ECFieldElement.F2m) (g.getAffineXCoord())).getM();
+
+ SecureRandom secRand = SecureRandom.getInstance("SHA1PRNG");
+ Properties inputProps = new Properties();
+ for (int i = 0; i < NUM_SAMPLES; i++)
+ {
+ BigInteger rand = new BigInteger(m, secRand);
+ inputProps.put(Integer.toString(i), rand.toString(16));
+ }
+ String bits = Integer.toString(m);
+ FileOutputStream fos = new FileOutputStream(PATH
+ + INPUT_FILE_NAME_PREFIX + bits + ".properties");
+ inputProps.store(fos, "Input Samples of length" + bits);
+ }
+
+ private void multiplyPoints(X9ECParameters x9ECParameters,
+ String classPrefix) throws IOException
+ {
+ ECPoint.F2m g = (ECPoint.F2m) x9ECParameters.getG();
+ int m = ((ECFieldElement.F2m) (g.getAffineXCoord())).getM();
+
+ String inputFileName = PATH + INPUT_FILE_NAME_PREFIX + m
+ + ".properties";
+ Properties inputProps = new Properties();
+ inputProps.load(new FileInputStream(inputFileName));
+
+ Properties outputProps = new Properties();
+
+ for (int i = 0; i < NUM_SAMPLES; i++)
+ {
+ BigInteger rand = new BigInteger(inputProps.getProperty(Integer
+ .toString(i)), 16);
+ ECPoint.F2m result = (ECPoint.F2m) g.multiply(rand).normalize();
+ String resultStr = pointToString(result);
+ outputProps.setProperty(Integer.toString(i), resultStr);
+ }
+
+ String outputFileName = PATH + RESULT_FILE_NAME_PREFIX + classPrefix
+ + "_" + m + ".properties";
+ FileOutputStream fos = new FileOutputStream(outputFileName);
+ outputProps.store(fos, "Output Samples of length" + m);
+ }
+
+ private Properties loadResults(String classPrefix, int m)
+ throws IOException
+ {
+ FileInputStream fis = new FileInputStream(PATH
+ + RESULT_FILE_NAME_PREFIX + classPrefix + "_" + m + ".properties");
+ Properties res = new Properties();
+ res.load(fis);
+ return res;
+
+ }
+
+ private void compareResult(X9ECParameters x9ECParameters,
+ String classPrefix1, String classPrefix2) throws IOException
+ {
+ ECPoint.F2m g = (ECPoint.F2m) x9ECParameters.getG();
+ int m = ((ECFieldElement.F2m) (g.getAffineXCoord())).getM();
+
+ Properties res1 = loadResults(classPrefix1, m);
+ Properties res2 = loadResults(classPrefix2, m);
+
+ Set keys = res1.keySet();
+ Iterator iter = keys.iterator();
+ while (iter.hasNext())
+ {
+ String key = (String) iter.next();
+ String result1 = res1.getProperty(key);
+ String result2 = res2.getProperty(key);
+ if (!(result1.equals(result2)))
+ {
+ System.err.println("Difference found: m = " + m + ", "
+ + result1 + " does not equal " + result2);
+ }
+ }
+
+ }
+
+ private static void usage()
+ {
+ System.err.println("Usage: F2mProofer [-init | -multiply <className> "
+ + "| -compare <className1> <className2>]");
+ }
+
+ public static void main(String[] args) throws Exception
+ {
+ if (args.length == 0)
+ {
+ usage();
+ return;
+ }
+ F2mProofer proofer = new F2mProofer();
+ if (args[0].equals("-init"))
+ {
+ System.out.println("Generating random input...");
+ for (int i = 0; i < CURVES.length; i++)
+ {
+ X9ECParameters x9ECParameters = SECNamedCurves
+ .getByName(CURVES[i]);
+ proofer.generateRandomInput(x9ECParameters);
+ }
+ System.out
+ .println("Successfully generated random input in " + PATH);
+ }
+ else if (args[0].equals("-compare"))
+ {
+ if (args.length < 3)
+ {
+ usage();
+ return;
+ }
+ String classPrefix1 = args[1];
+ String classPrefix2 = args[2];
+ System.out.println("Comparing results...");
+ for (int i = 0; i < CURVES.length; i++)
+ {
+ X9ECParameters x9ECParameters = SECNamedCurves
+ .getByName(CURVES[i]);
+ proofer.compareResult(x9ECParameters, classPrefix1,
+ classPrefix2);
+ }
+ System.out.println("Successfully compared results in " + PATH);
+ }
+ else if (args[0].equals("-multiply"))
+ {
+ if (args.length < 2)
+ {
+ usage();
+ return;
+ }
+ String classPrefix = args[1];
+ System.out.println("Multiplying points...");
+ for (int i = 0; i < CURVES.length; i++)
+ {
+ X9ECParameters x9ECParameters = SECNamedCurves
+ .getByName(CURVES[i]);
+ proofer.multiplyPoints(x9ECParameters, classPrefix);
+ }
+ System.out.println("Successfully generated multiplied points in "
+ + PATH);
+ }
+ else
+ {
+ usage();
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/math/ec/test/TnafTest.java b/core/src/test/java/org/spongycastle/math/ec/test/TnafTest.java
new file mode 100644
index 00000000..bd527c6f
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/math/ec/test/TnafTest.java
@@ -0,0 +1,152 @@
+//package org.spongycastle.math.ec.test;
+//
+//import java.math.BigInteger;
+//import java.util.Random;
+//
+//import junit.framework.TestCase;
+//
+//import org.spongycastle.asn1.sec.SECNamedCurves;
+//import org.spongycastle.asn1.x9.X9ECParameters;
+//import org.spongycastle.math.ec.ECCurve;
+//import org.spongycastle.math.ec.ECPoint;
+//import org.spongycastle.math.ec.NafL2RMultiplier;
+//import org.spongycastle.math.ec.ReferenceMultiplier;
+//import org.spongycastle.math.ec.WNafL2RMultiplier;
+//import org.spongycastle.math.ec.WTauNafMultiplier;
+//
+//public class TnafTest extends TestCase
+//{
+// private Random m_rand = new Random();
+//
+// private String ecPointToString(ECPoint p) {
+// StringBuffer sb = new StringBuffer("x = ");
+// sb.append(p.getX().toBigInteger().toString());
+// sb.append("; y = ");
+// sb.append(p.getY().toBigInteger().toString());
+// return sb.toString();
+// }
+//
+// private ECPoint repeatedMultiply(ECPoint p, BigInteger k)
+// {
+// ECPoint result = p.multiply(k);
+// for (int i = 1; i < 10; ++i)
+// {
+// ECPoint check = p.multiply(k);
+// assertEquals(result, check);
+// }
+// return result;
+// }
+//
+// private void implTestMultiplyTnaf(String curveName) {
+// X9ECParameters x9ECParameters = SECNamedCurves.getByName(curveName);
+//
+// ECCurve.F2m curve = (ECCurve.F2m)x9ECParameters.getCurve();
+// BigInteger n = curve.getN();
+//
+// // The generator is multiplied by random b to get random q
+// BigInteger b = new BigInteger(n.bitLength(), m_rand);
+// ECPoint g = x9ECParameters.getG();
+// ECPoint.F2m p = (ECPoint.F2m)g.multiply(b);
+//
+// BigInteger k = new BigInteger(n.bitLength(), m_rand);
+// long now1 = System.currentTimeMillis();
+// p.setECMultiplier(new WTauNafMultiplier());
+// ECPoint refRWTnaf = repeatedMultiply(p, k);
+// long now2 = System.currentTimeMillis();
+// p.setECMultiplier(new WNafL2RMultiplier());
+// ECPoint refWnaf = repeatedMultiply(p, k);
+// long now3 = System.currentTimeMillis();
+// p.setECMultiplier(new NafL2RMultiplier());
+// ECPoint refFpNaf = repeatedMultiply(p, k);
+// long now4 = System.currentTimeMillis();
+// p.setECMultiplier(new ReferenceMultiplier());
+// ECPoint reference = repeatedMultiply(p, k);
+// long now5 = System.currentTimeMillis();
+//
+// assertEquals("WTNAF multiplication is incorrect", refRWTnaf, reference);
+// assertEquals("FPNAF multiplication is incorrect", refFpNaf, reference);
+// assertEquals("WNAF multiplication is incorrect", refWnaf, reference);
+//
+// System.out.println(curveName + ": Multiply WTNAF took millis: " + (now2 - now1));
+// System.out.println(curveName + ": Multiply WNAF took millis: " + (now3 - now2));
+// System.out.println(curveName + ": Multiply FPNAF took millis: " + (now4 - now3));
+// System.out.println(curveName + ": Multiply REFE took millis: " + (now5 - now4));
+//
+//// System.out.println(curveName + ": refRWTnaf = " + ecPointToString(refRWTnaf));
+//// System.out.println(curveName + ": refWnaf = " + ecPointToString(refWnaf));
+//// System.out.println(curveName + ": refFpNaf = " + ecPointToString(refFpNaf));
+//// System.out.println(curveName + ": reference = " + ecPointToString(reference) + "\n");
+// System.out.println();
+// }
+//
+// public void testMultiplyTnaf() {
+// System.out.println("\n\n\n***** Start test multiplications on F2m (Koblitz) *****");
+// implTestMultiplyTnaf("sect163k1");
+// implTestMultiplyTnaf("sect233k1");
+// implTestMultiplyTnaf("sect239k1");
+// implTestMultiplyTnaf("sect283k1");
+// implTestMultiplyTnaf("sect409k1");
+// implTestMultiplyTnaf("sect571k1");
+// }
+//
+// private void implTestMultiplyWnaf(String curveName) {
+// X9ECParameters x9ECParameters = SECNamedCurves.getByName(curveName);
+//
+// BigInteger r = x9ECParameters.getN();
+//
+// // The generator is multiplied by random b to get random q
+// BigInteger b = new BigInteger(r.bitLength(), m_rand);
+// ECPoint g = x9ECParameters.getG();
+// ECPoint p = g.multiply(b);
+//
+// BigInteger k = new BigInteger(r.bitLength(), m_rand);
+// long now1 = System.currentTimeMillis();
+// p.setECMultiplier(new WNafL2RMultiplier());
+// ECPoint refWnaf = repeatedMultiply(p, k);
+// long now2 = System.currentTimeMillis();
+// p.setECMultiplier(new NafL2RMultiplier());
+// ECPoint refFpNaf = repeatedMultiply(p, k);
+// long now3 = System.currentTimeMillis();
+// p.setECMultiplier(new ReferenceMultiplier());
+// ECPoint reference = repeatedMultiply(p, k);
+// long now4 = System.currentTimeMillis();
+//
+// assertEquals("WNAF multiplication is incorrect", refWnaf, reference);
+// assertEquals("FPNAF multiplication is incorrect", refFpNaf, reference);
+//
+// System.out.println(curveName + ": Multiply WNAF took millis: " + (now2 - now1));
+// System.out.println(curveName + ": Multiply FPNAF took millis: " + (now3 - now2));
+// System.out.println(curveName + ": Multiply REFE took millis: " + (now4 - now3));
+//
+//// System.out.println(curveName + ": refWnaf = " + ecPointToString(refWnaf));
+//// System.out.println(curveName + ": refFpNaf = " + ecPointToString(refFpNaf));
+//// System.out.println(curveName + ": reference = " + ecPointToString(reference));
+// System.out.println();
+// }
+//
+// public void testMultiplyWnaf() {
+// System.out.println("\n\n\n***** Start test multiplications on F2m *****");
+// implTestMultiplyWnaf("sect113r1");
+// implTestMultiplyWnaf("sect113r2");
+// implTestMultiplyWnaf("sect131r1");
+// implTestMultiplyWnaf("sect131r2");
+// implTestMultiplyWnaf("sect163r1");
+// implTestMultiplyWnaf("sect163r2");
+// implTestMultiplyWnaf("sect193r1");
+// implTestMultiplyWnaf("sect193r2");
+// implTestMultiplyWnaf("sect233r1");
+// implTestMultiplyWnaf("sect283r1");
+// implTestMultiplyWnaf("sect409r1");
+// implTestMultiplyWnaf("sect571r1");
+//
+// System.out.println("\n\n\n***** Start test multiplications on Fp *****");
+// implTestMultiplyWnaf("secp112r1");
+// implTestMultiplyWnaf("secp128r1");
+// implTestMultiplyWnaf("secp160r1");
+// implTestMultiplyWnaf("secp192r1");
+// implTestMultiplyWnaf("secp224r1");
+// implTestMultiplyWnaf("secp256r1");
+// implTestMultiplyWnaf("secp384r1");
+// implTestMultiplyWnaf("secp521r1");
+// }
+//}
diff --git a/core/src/test/java/org/spongycastle/pqc/crypto/test/AllTests.java b/core/src/test/java/org/spongycastle/pqc/crypto/test/AllTests.java
new file mode 100644
index 00000000..20c8a154
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/crypto/test/AllTests.java
@@ -0,0 +1,47 @@
+package org.spongycastle.pqc.crypto.test;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.spongycastle.util.test.SimpleTestResult;
+
+public class AllTests
+ extends TestCase
+{
+ public void testCrypto()
+ {
+ org.spongycastle.util.test.Test[] tests = RegressionTest.tests;
+
+ for (int i = 0; i != tests.length; i++)
+ {
+ SimpleTestResult result = (SimpleTestResult)tests[i].perform();
+
+ if (!result.isSuccessful())
+ {
+ fail(result.toString());
+ }
+ }
+ }
+
+ public static void main (String[] args)
+ {
+ junit.textui.TestRunner.run(suite());
+ }
+
+ public static Test suite()
+ {
+ TestSuite suite = new TestSuite("Lightweight PQ Crypto Tests");
+
+ suite.addTestSuite(AllTests.class);
+ suite.addTestSuite(BitStringTest.class);
+ suite.addTestSuite(EncryptionKeyTest.class);
+ suite.addTestSuite(NTRUEncryptionParametersTest.class);
+ suite.addTestSuite(NTRUEncryptTest.class);
+ suite.addTestSuite(NTRUSignatureParametersTest.class);
+ suite.addTestSuite(NTRUSignatureKeyTest.class);
+ suite.addTestSuite(NTRUSignerTest.class);
+ suite.addTestSuite(NTRUSigningParametersTest.class);
+
+ return suite;
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/pqc/crypto/test/BitStringTest.java b/core/src/test/java/org/spongycastle/pqc/crypto/test/BitStringTest.java
new file mode 100644
index 00000000..449c83eb
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/crypto/test/BitStringTest.java
@@ -0,0 +1,88 @@
+package org.spongycastle.pqc.crypto.test;
+
+import junit.framework.TestCase;
+import org.spongycastle.pqc.crypto.ntru.IndexGenerator.BitString;
+import org.spongycastle.util.Arrays;
+
+public class BitStringTest
+ extends TestCase
+{
+ public void testAppendBitsByteArray()
+ {
+ BitString bs = new BitString();
+ bs.appendBits((byte)78);
+ assertBitStringEquals(bs, new byte[]{78});
+ bs.appendBits((byte)-5);
+ assertBitStringEquals(bs, new byte[]{78, -5});
+ bs.appendBits((byte)127);
+ assertBitStringEquals(bs, new byte[]{78, -5, 127});
+ bs.appendBits((byte)0);
+ assertBitStringEquals(bs, new byte[]{78, -5, 127, 0});
+ bs.appendBits((byte)100);
+ assertBitStringEquals(bs, new byte[]{78, -5, 127, 0, 100});
+ }
+
+ private void assertBitStringEquals(BitString bs, byte[] arr)
+ {
+ byte[] bsBytes = bs.getBytes();
+
+ assertTrue(bsBytes.length >= arr.length);
+ arr = copyOf(arr, bsBytes.length);
+ assertTrue(Arrays.areEqual(arr, bsBytes));
+ }
+
+ public void testGetTrailing()
+ {
+ BitString bs = new BitString();
+ bs.appendBits((byte)78);
+ BitString bs2 = bs.getTrailing(3);
+ assertBitStringEquals(bs2, new byte[]{6});
+
+ bs = new BitString();
+ bs.appendBits((byte)78);
+ bs.appendBits((byte)-5);
+ bs2 = bs.getTrailing(9);
+ assertBitStringEquals(bs2, new byte[]{78, 1});
+
+ bs2.appendBits((byte)100);
+ assertBitStringEquals(bs2, new byte[]{78, -55});
+ bs = bs2.getTrailing(13);
+ assertBitStringEquals(bs, new byte[]{78, 9});
+ bs2 = bs2.getTrailing(11);
+ assertBitStringEquals(bs2, new byte[]{78, 1});
+
+ bs2.appendBits((byte)100);
+ assertBitStringEquals(bs2, new byte[]{78, 33, 3});
+ bs2 = bs2.getTrailing(16);
+ assertBitStringEquals(bs2, new byte[]{78, 33});
+ }
+
+ public void testGetLeadingAsInt()
+ {
+ BitString bs = new BitString();
+ bs.appendBits((byte)78);
+ bs.appendBits((byte)42);
+ assertEquals(1, bs.getLeadingAsInt(3));
+ assertEquals(84, bs.getLeadingAsInt(9));
+ assertEquals(338, bs.getLeadingAsInt(11));
+
+ BitString bs2 = bs.getTrailing(11);
+ assertBitStringEquals(bs2, new byte[]{78, 2});
+ assertEquals(590, bs2.getLeadingAsInt(11));
+ assertEquals(9, bs2.getLeadingAsInt(5));
+
+ bs2.appendBits((byte)115);
+ assertEquals(230, bs2.getLeadingAsInt(9));
+ assertEquals(922, bs2.getLeadingAsInt(11));
+
+ bs2.appendBits((byte)-36);
+ assertEquals(55, bs2.getLeadingAsInt(6));
+ }
+
+ private byte[] copyOf(byte[] src, int length)
+ {
+ byte[] tmp = new byte[length];
+ System.arraycopy(src, 0, tmp, 0, tmp.length > src.length ? src.length : tmp.length);
+ return tmp;
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/pqc/crypto/test/EncryptionKeyTest.java b/core/src/test/java/org/spongycastle/pqc/crypto/test/EncryptionKeyTest.java
new file mode 100644
index 00000000..1b152bff
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/crypto/test/EncryptionKeyTest.java
@@ -0,0 +1,51 @@
+package org.spongycastle.pqc.crypto.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import junit.framework.TestCase;
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.pqc.crypto.ntru.NTRUEncryptionKeyPairGenerator;
+import org.spongycastle.pqc.crypto.ntru.NTRUEncryptionKeyGenerationParameters;
+import org.spongycastle.pqc.crypto.ntru.NTRUEncryptionPrivateKeyParameters;
+import org.spongycastle.pqc.crypto.ntru.NTRUEncryptionPublicKeyParameters;
+
+public class EncryptionKeyTest
+ extends TestCase
+{
+ public void testEncode()
+ throws IOException
+ {
+ for (NTRUEncryptionKeyGenerationParameters params : new NTRUEncryptionKeyGenerationParameters[]{NTRUEncryptionKeyGenerationParameters.APR2011_743, NTRUEncryptionKeyGenerationParameters.APR2011_743_FAST, NTRUEncryptionKeyGenerationParameters.EES1499EP1})
+ {
+ testEncode(params);
+ }
+ }
+
+ private void testEncode(NTRUEncryptionKeyGenerationParameters params)
+ throws IOException
+ {
+ NTRUEncryptionKeyPairGenerator kpGen = new NTRUEncryptionKeyPairGenerator();
+
+ kpGen.init(params);
+
+ AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();
+ byte[] priv = ((NTRUEncryptionPrivateKeyParameters)kp.getPrivate()).getEncoded();
+ byte[] pub = ((NTRUEncryptionPublicKeyParameters)kp.getPublic()).getEncoded();
+
+ AsymmetricCipherKeyPair kp2 = new AsymmetricCipherKeyPair(new NTRUEncryptionPublicKeyParameters(pub, params.getEncryptionParameters()), new NTRUEncryptionPrivateKeyParameters(priv, params.getEncryptionParameters()));
+ assertEquals(kp.getPublic(), kp2.getPublic());
+ assertEquals(kp.getPrivate(), kp2.getPrivate());
+
+ ByteArrayOutputStream bos1 = new ByteArrayOutputStream();
+ ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
+ ((NTRUEncryptionPrivateKeyParameters)kp.getPrivate()).writeTo(bos1);
+ ((NTRUEncryptionPublicKeyParameters)kp.getPublic()).writeTo(bos2);
+ ByteArrayInputStream bis1 = new ByteArrayInputStream(bos1.toByteArray());
+ ByteArrayInputStream bis2 = new ByteArrayInputStream(bos2.toByteArray());
+ AsymmetricCipherKeyPair kp3 = new AsymmetricCipherKeyPair(new NTRUEncryptionPublicKeyParameters(bis2, params.getEncryptionParameters()), new NTRUEncryptionPrivateKeyParameters(bis1, params.getEncryptionParameters()));
+ assertEquals(kp.getPublic(), kp3.getPublic());
+ assertEquals(kp.getPrivate(), kp3.getPrivate());
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/pqc/crypto/test/GMSSSignerTest.java b/core/src/test/java/org/spongycastle/pqc/crypto/test/GMSSSignerTest.java
new file mode 100644
index 00000000..476322eb
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/crypto/test/GMSSSignerTest.java
@@ -0,0 +1,88 @@
+package org.spongycastle.pqc.crypto.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.Signer;
+import org.spongycastle.crypto.digests.SHA224Digest;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.pqc.crypto.DigestingMessageSigner;
+import org.spongycastle.pqc.crypto.gmss.GMSSDigestProvider;
+import org.spongycastle.pqc.crypto.gmss.GMSSKeyGenerationParameters;
+import org.spongycastle.pqc.crypto.gmss.GMSSKeyPairGenerator;
+import org.spongycastle.pqc.crypto.gmss.GMSSParameters;
+import org.spongycastle.pqc.crypto.gmss.GMSSPrivateKeyParameters;
+import org.spongycastle.pqc.crypto.gmss.GMSSSigner;
+import org.spongycastle.util.BigIntegers;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.FixedSecureRandom;
+import org.spongycastle.util.test.SimpleTest;
+
+
+public class GMSSSignerTest
+ extends SimpleTest
+{
+ byte[] keyData = Hex.decode("b5014e4b60ef2ba8b6211b4062ba3224e0427dd3");
+
+ SecureRandom keyRandom = new FixedSecureRandom(new byte[][]{keyData, keyData});
+
+ public String getName()
+ {
+ return "GMSS";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+
+ GMSSParameters params = new GMSSParameters(3,
+ new int[]{15, 15, 10}, new int[]{5, 5, 4}, new int[]{3, 3, 2});
+
+ GMSSDigestProvider digProvider = new GMSSDigestProvider()
+ {
+ public Digest get()
+ {
+ return new SHA224Digest();
+ }
+ };
+
+ GMSSKeyPairGenerator gmssKeyGen = new GMSSKeyPairGenerator(digProvider);
+
+ GMSSKeyGenerationParameters genParam = new GMSSKeyGenerationParameters(keyRandom, params);
+
+ gmssKeyGen.init(genParam);
+
+ AsymmetricCipherKeyPair pair = gmssKeyGen.generateKeyPair();
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), keyRandom);
+
+ // TODO
+ Signer gmssSigner = new DigestingMessageSigner(new GMSSSigner(digProvider), new SHA224Digest());
+ gmssSigner.init(true, param);
+
+ byte[] message = BigIntegers.asUnsignedByteArray(new BigInteger("968236873715988614170569073515315707566766479517"));
+ gmssSigner.update(message, 0, message.length);
+ byte[] sig = gmssSigner.generateSignature();
+
+
+ gmssSigner.init(false, pair.getPublic());
+ gmssSigner.update(message, 0, message.length);
+ if (!gmssSigner.verifySignature(sig))
+ {
+ fail("verification fails");
+ }
+
+ if (!((GMSSPrivateKeyParameters)pair.getPrivate()).isUsed())
+ {
+ fail("private key not marked as used");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new GMSSSignerTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/pqc/crypto/test/McElieceFujisakiCipherTest.java b/core/src/test/java/org/spongycastle/pqc/crypto/test/McElieceFujisakiCipherTest.java
new file mode 100644
index 00000000..d36107c2
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/crypto/test/McElieceFujisakiCipherTest.java
@@ -0,0 +1,102 @@
+package org.spongycastle.pqc.crypto.test;
+
+import java.security.SecureRandom;
+import java.util.Random;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2KeyGenerationParameters;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2KeyPairGenerator;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2Parameters;
+import org.spongycastle.pqc.crypto.mceliece.McElieceFujisakiCipher;
+import org.spongycastle.pqc.crypto.mceliece.McElieceFujisakiDigestCipher;
+import org.spongycastle.util.test.SimpleTest;
+
+public class McElieceFujisakiCipherTest
+ extends SimpleTest
+{
+
+ SecureRandom keyRandom = new SecureRandom();
+
+ public String getName()
+ {
+ return "McElieceFujisaki";
+
+ }
+
+
+ public void performTest()
+ {
+ int numPassesKPG = 1;
+ int numPassesEncDec = 10;
+ Random rand = new Random();
+ byte[] mBytes;
+ for (int j = 0; j < numPassesKPG; j++)
+ {
+
+ McElieceCCA2Parameters params = new McElieceCCA2Parameters();
+ McElieceCCA2KeyPairGenerator mcElieceCCA2KeyGen = new McElieceCCA2KeyPairGenerator();
+ McElieceCCA2KeyGenerationParameters genParam = new McElieceCCA2KeyGenerationParameters(keyRandom, params);
+
+ mcElieceCCA2KeyGen.init(genParam);
+ AsymmetricCipherKeyPair pair = mcElieceCCA2KeyGen.generateKeyPair();
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPublic(), keyRandom);
+ Digest msgDigest = new SHA256Digest();
+ McElieceFujisakiDigestCipher mcElieceFujisakiDigestCipher = new McElieceFujisakiDigestCipher(new McElieceFujisakiCipher(), msgDigest);
+
+
+ for (int k = 1; k <= numPassesEncDec; k++)
+ {
+ System.out.println("############### test: " + k);
+ // initialize for encryption
+ mcElieceFujisakiDigestCipher.init(true, param);
+
+ // generate random message
+ int mLength = (rand.nextInt() & 0x1f) + 1;;
+ mBytes = new byte[mLength];
+ rand.nextBytes(mBytes);
+
+ // encrypt
+ mcElieceFujisakiDigestCipher.update(mBytes, 0, mBytes.length);
+ byte[] enc = mcElieceFujisakiDigestCipher.messageEncrypt();
+
+ // initialize for decryption
+ mcElieceFujisakiDigestCipher.init(false, pair.getPrivate());
+ byte[] constructedmessage = mcElieceFujisakiDigestCipher.messageDecrypt(enc);
+
+ // XXX write in McElieceFujisakiDigestCipher?
+ msgDigest.update(mBytes, 0, mBytes.length);
+ byte[] hash = new byte[msgDigest.getDigestSize()];
+ msgDigest.doFinal(hash, 0);
+
+ boolean verified = true;
+ for (int i = 0; i < hash.length; i++)
+ {
+ verified = verified && hash[i] == constructedmessage[i];
+ }
+
+ if (!verified)
+ {
+ fail("en/decryption fails");
+ }
+ else
+ {
+ System.out.println("test okay");
+ System.out.println();
+ }
+
+ }
+ }
+
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new McElieceFujisakiCipherTest());
+ }
+
+}
diff --git a/core/src/test/java/org/spongycastle/pqc/crypto/test/McElieceKobaraImaiCipherTest.java b/core/src/test/java/org/spongycastle/pqc/crypto/test/McElieceKobaraImaiCipherTest.java
new file mode 100644
index 00000000..df8d4ed9
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/crypto/test/McElieceKobaraImaiCipherTest.java
@@ -0,0 +1,102 @@
+package org.spongycastle.pqc.crypto.test;
+
+import java.security.SecureRandom;
+import java.util.Random;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2KeyGenerationParameters;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2KeyPairGenerator;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2Parameters;
+import org.spongycastle.pqc.crypto.mceliece.McElieceKobaraImaiCipher;
+import org.spongycastle.pqc.crypto.mceliece.McElieceKobaraImaiDigestCipher;
+import org.spongycastle.util.test.SimpleTest;
+
+public class McElieceKobaraImaiCipherTest
+ extends SimpleTest
+{
+
+ SecureRandom keyRandom = new SecureRandom();
+
+ public String getName()
+ {
+ return "McElieceKobaraImai";
+
+ }
+
+
+ public void performTest()
+ {
+ int numPassesKPG = 1;
+ int numPassesEncDec = 10;
+ Random rand = new Random();
+ byte[] mBytes;
+ for (int j = 0; j < numPassesKPG; j++)
+ {
+
+ McElieceCCA2Parameters params = new McElieceCCA2Parameters();
+ McElieceCCA2KeyPairGenerator mcElieceCCA2KeyGen = new McElieceCCA2KeyPairGenerator();
+ McElieceCCA2KeyGenerationParameters genParam = new McElieceCCA2KeyGenerationParameters(keyRandom, params);
+
+ mcElieceCCA2KeyGen.init(genParam);
+ AsymmetricCipherKeyPair pair = mcElieceCCA2KeyGen.generateKeyPair();
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPublic(), keyRandom);
+ Digest msgDigest = new SHA256Digest();
+ McElieceKobaraImaiDigestCipher mcElieceKobaraImaiDigestCipher = new McElieceKobaraImaiDigestCipher(new McElieceKobaraImaiCipher(), msgDigest);
+
+
+ for (int k = 1; k <= numPassesEncDec; k++)
+ {
+ System.out.println("############### test: " + k);
+ // initialize for encryption
+ mcElieceKobaraImaiDigestCipher.init(true, param);
+
+ // generate random message
+ int mLength = (rand.nextInt() & 0x1f) + 1;
+ mBytes = new byte[mLength];
+ rand.nextBytes(mBytes);
+
+ // encrypt
+ mcElieceKobaraImaiDigestCipher.update(mBytes, 0, mBytes.length);
+ byte[] enc = mcElieceKobaraImaiDigestCipher.messageEncrypt();
+
+ // initialize for decryption
+ mcElieceKobaraImaiDigestCipher.init(false, pair.getPrivate());
+ byte[] constructedmessage = mcElieceKobaraImaiDigestCipher.messageDecrypt(enc);
+
+ // XXX write in McElieceFujisakiDigestCipher?
+ msgDigest.update(mBytes, 0, mBytes.length);
+ byte[] hash = new byte[msgDigest.getDigestSize()];
+ msgDigest.doFinal(hash, 0);
+
+ boolean verified = true;
+ for (int i = 0; i < hash.length; i++)
+ {
+ verified = verified && hash[i] == constructedmessage[i];
+ }
+
+ if (!verified)
+ {
+ fail("en/decryption fails");
+ }
+ else
+ {
+ System.out.println("test okay");
+ System.out.println();
+ }
+
+ }
+ }
+
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new McElieceKobaraImaiCipherTest());
+ }
+
+}
diff --git a/core/src/test/java/org/spongycastle/pqc/crypto/test/McEliecePKCSCipherTest.java b/core/src/test/java/org/spongycastle/pqc/crypto/test/McEliecePKCSCipherTest.java
new file mode 100644
index 00000000..8578d808
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/crypto/test/McEliecePKCSCipherTest.java
@@ -0,0 +1,102 @@
+package org.spongycastle.pqc.crypto.test;
+
+import java.security.SecureRandom;
+import java.util.Random;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.pqc.crypto.mceliece.McElieceKeyGenerationParameters;
+import org.spongycastle.pqc.crypto.mceliece.McElieceKeyPairGenerator;
+import org.spongycastle.pqc.crypto.mceliece.McEliecePKCSCipher;
+import org.spongycastle.pqc.crypto.mceliece.McEliecePKCSDigestCipher;
+import org.spongycastle.pqc.crypto.mceliece.McElieceParameters;
+import org.spongycastle.util.test.SimpleTest;
+
+public class McEliecePKCSCipherTest
+ extends SimpleTest
+{
+
+ SecureRandom keyRandom = new SecureRandom();
+
+ public String getName()
+ {
+ return "McEliecePKCS";
+
+ }
+
+
+ public void performTest()
+ {
+ int numPassesKPG = 1;
+ int numPassesEncDec = 10;
+ Random rand = new Random();
+ byte[] mBytes;
+ for (int j = 0; j < numPassesKPG; j++)
+ {
+
+ McElieceParameters params = new McElieceParameters();
+ McElieceKeyPairGenerator mcElieceKeyGen = new McElieceKeyPairGenerator();
+ McElieceKeyGenerationParameters genParam = new McElieceKeyGenerationParameters(keyRandom, params);
+
+ mcElieceKeyGen.init(genParam);
+ AsymmetricCipherKeyPair pair = mcElieceKeyGen.generateKeyPair();
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPublic(), keyRandom);
+ Digest msgDigest = new SHA256Digest();
+ McEliecePKCSDigestCipher mcEliecePKCSDigestCipher = new McEliecePKCSDigestCipher(new McEliecePKCSCipher(), msgDigest);
+
+
+ for (int k = 1; k <= numPassesEncDec; k++)
+ {
+ System.out.println("############### test: " + k);
+ // initialize for encryption
+ mcEliecePKCSDigestCipher.init(true, param);
+
+ // generate random message
+ int mLength = (rand.nextInt() & 0x1f) + 1;
+ mBytes = new byte[mLength];
+ rand.nextBytes(mBytes);
+
+ // encrypt
+ mcEliecePKCSDigestCipher.update(mBytes, 0, mBytes.length);
+ byte[] enc = mcEliecePKCSDigestCipher.messageEncrypt();
+
+ // initialize for decryption
+ mcEliecePKCSDigestCipher.init(false, pair.getPrivate());
+ byte[] constructedmessage = mcEliecePKCSDigestCipher.messageDecrypt(enc);
+
+ // XXX write in McElieceFujisakiDigestCipher?
+ msgDigest.update(mBytes, 0, mBytes.length);
+ byte[] hash = new byte[msgDigest.getDigestSize()];
+ msgDigest.doFinal(hash, 0);
+
+ boolean verified = true;
+ for (int i = 0; i < hash.length; i++)
+ {
+ verified = verified && hash[i] == constructedmessage[i];
+ }
+
+ if (!verified)
+ {
+ fail("en/decryption fails");
+ }
+ else
+ {
+ System.out.println("test okay");
+ System.out.println();
+ }
+
+ }
+ }
+
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new McEliecePKCSCipherTest());
+ }
+
+}
diff --git a/core/src/test/java/org/spongycastle/pqc/crypto/test/McEliecePointchevalCipherTest.java b/core/src/test/java/org/spongycastle/pqc/crypto/test/McEliecePointchevalCipherTest.java
new file mode 100644
index 00000000..ba41fcfd
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/crypto/test/McEliecePointchevalCipherTest.java
@@ -0,0 +1,102 @@
+package org.spongycastle.pqc.crypto.test;
+
+import java.security.SecureRandom;
+import java.util.Random;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2KeyGenerationParameters;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2KeyPairGenerator;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2Parameters;
+import org.spongycastle.pqc.crypto.mceliece.McEliecePointchevalCipher;
+import org.spongycastle.pqc.crypto.mceliece.McEliecePointchevalDigestCipher;
+import org.spongycastle.util.test.SimpleTest;
+
+public class McEliecePointchevalCipherTest
+ extends SimpleTest
+{
+
+ SecureRandom keyRandom = new SecureRandom();
+
+ public String getName()
+ {
+ return "McElieceFujisaki";
+
+ }
+
+
+ public void performTest()
+ {
+ int numPassesKPG = 1;
+ int numPassesEncDec = 10;
+ Random rand = new Random();
+ byte[] mBytes;
+ for (int j = 0; j < numPassesKPG; j++)
+ {
+
+ McElieceCCA2Parameters params = new McElieceCCA2Parameters();
+ McElieceCCA2KeyPairGenerator mcElieceCCA2KeyGen = new McElieceCCA2KeyPairGenerator();
+ McElieceCCA2KeyGenerationParameters genParam = new McElieceCCA2KeyGenerationParameters(keyRandom, params);
+
+ mcElieceCCA2KeyGen.init(genParam);
+ AsymmetricCipherKeyPair pair = mcElieceCCA2KeyGen.generateKeyPair();
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPublic(), keyRandom);
+ Digest msgDigest = new SHA256Digest();
+ McEliecePointchevalDigestCipher mcEliecePointchevalDigestCipher = new McEliecePointchevalDigestCipher(new McEliecePointchevalCipher(), msgDigest);
+
+
+ for (int k = 1; k <= numPassesEncDec; k++)
+ {
+ System.out.println("############### test: " + k);
+ // initialize for encryption
+ mcEliecePointchevalDigestCipher.init(true, param);
+
+ // generate random message
+ int mLength = (rand.nextInt() & 0x1f) + 1;
+ mBytes = new byte[mLength];
+ rand.nextBytes(mBytes);
+
+ // encrypt
+ mcEliecePointchevalDigestCipher.update(mBytes, 0, mBytes.length);
+ byte[] enc = mcEliecePointchevalDigestCipher.messageEncrypt();
+
+ // initialize for decryption
+ mcEliecePointchevalDigestCipher.init(false, pair.getPrivate());
+ byte[] constructedmessage = mcEliecePointchevalDigestCipher.messageDecrypt(enc);
+
+ // XXX write in McElieceFujisakiDigestCipher?
+ msgDigest.update(mBytes, 0, mBytes.length);
+ byte[] hash = new byte[msgDigest.getDigestSize()];
+ msgDigest.doFinal(hash, 0);
+
+ boolean verified = true;
+ for (int i = 0; i < hash.length; i++)
+ {
+ verified = verified && hash[i] == constructedmessage[i];
+ }
+
+ if (!verified)
+ {
+ fail("en/decryption fails");
+ }
+ else
+ {
+ System.out.println("test okay");
+ System.out.println();
+ }
+
+ }
+ }
+
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new McEliecePointchevalCipherTest());
+ }
+
+}
diff --git a/core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUEncryptTest.java b/core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUEncryptTest.java
new file mode 100644
index 00000000..f61cb6e8
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUEncryptTest.java
@@ -0,0 +1,298 @@
+package org.spongycastle.pqc.crypto.test;
+
+import java.io.IOException;
+import java.security.SecureRandom;
+
+import junit.framework.TestCase;
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.InvalidCipherTextException;
+import org.spongycastle.pqc.crypto.ntru.NTRUEngine;
+import org.spongycastle.pqc.crypto.ntru.NTRUEncryptionKeyPairGenerator;
+import org.spongycastle.pqc.crypto.ntru.NTRUEncryptionKeyGenerationParameters;
+import org.spongycastle.pqc.crypto.ntru.NTRUEncryptionPrivateKeyParameters;
+import org.spongycastle.pqc.crypto.ntru.NTRUEncryptionPublicKeyParameters;
+import org.spongycastle.pqc.crypto.ntru.NTRUParameters;
+import org.spongycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.Polynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.TernaryPolynomial;
+import org.spongycastle.util.Arrays;
+
+public class NTRUEncryptTest
+ extends TestCase
+{
+ public void testEncryptDecrypt()
+ throws InvalidCipherTextException
+ {
+ NTRUEncryptionKeyGenerationParameters params = NTRUEncryptionKeyGenerationParameters.APR2011_743.clone();
+ // set df1..df3 and dr1..dr3 so params can be used for SIMPLE as well as PRODUCT
+ params.df1 = NTRUEncryptionKeyGenerationParameters.APR2011_743_FAST.df1;
+ params.df2 = NTRUEncryptionKeyGenerationParameters.APR2011_743_FAST.df2;
+ params.df3 = NTRUEncryptionKeyGenerationParameters.APR2011_743_FAST.df3;
+ params.dr1 = NTRUEncryptionKeyGenerationParameters.APR2011_743_FAST.dr1;
+ params.dr2 = NTRUEncryptionKeyGenerationParameters.APR2011_743_FAST.dr2;
+ params.dr3 = NTRUEncryptionKeyGenerationParameters.APR2011_743_FAST.dr3;
+
+ int[] values = new int[] { NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE, NTRUParameters.TERNARY_POLYNOMIAL_TYPE_PRODUCT };
+
+ for (int i = 0; i != values.length; i++)
+ {
+ int polyType = values[i];
+
+ boolean[] booleans = {true, false};
+ for (int j = 0; j != booleans.length; j++)
+ {
+ params.polyType = polyType;
+ params.fastFp = booleans[j];
+
+ VisibleNTRUEngine ntru = new VisibleNTRUEngine();
+ NTRUEncryptionKeyPairGenerator ntruGen = new NTRUEncryptionKeyPairGenerator();
+
+ ntruGen.init(params);
+
+ AsymmetricCipherKeyPair kp = ntruGen.generateKeyPair();
+
+ testPolynomial(ntru, kp, params);
+
+ testText(ntru, kp, params);
+ // sparse/dense
+ params.sparse = !params.sparse;
+ testText(ntru, kp, params);
+ params.sparse = !params.sparse;
+
+ testEmpty(ntru, kp, params);
+ testMaxLength(ntru, kp, params);
+ testTooLong(ntru, kp, params);
+ testInvalidEncoding(ntru, kp, params);
+ }
+ }
+ }
+
+ // encrypts and decrypts a polynomial
+ private void testPolynomial(VisibleNTRUEngine ntru, AsymmetricCipherKeyPair kp, NTRUEncryptionKeyGenerationParameters params)
+ {
+ SecureRandom random = new SecureRandom();
+ IntegerPolynomial m = DenseTernaryPolynomial.generateRandom(params.N, random);
+ SparseTernaryPolynomial r = SparseTernaryPolynomial.generateRandom(params.N, params.dr, params.dr, random);
+
+ ntru.init(true, kp.getPublic()); // just to set params
+
+ IntegerPolynomial e = ntru.encrypt(m, r, ((NTRUEncryptionPublicKeyParameters)kp.getPublic()).h);
+ IntegerPolynomial c = ntru.decrypt(e, ((NTRUEncryptionPrivateKeyParameters)kp.getPrivate()).t, ((NTRUEncryptionPrivateKeyParameters)kp.getPrivate()).fp);
+
+ assertTrue(Arrays.areEqual(m.coeffs, c.coeffs));
+ }
+
+ // encrypts and decrypts text
+ private void testText(NTRUEngine ntru, AsymmetricCipherKeyPair kp, NTRUEncryptionKeyGenerationParameters params)
+ throws InvalidCipherTextException
+ {
+ byte[] plainText = "text to encrypt".getBytes();
+
+ ntru.init(true, kp.getPublic());
+
+ byte[] encrypted = ntru.processBlock(plainText, 0, plainText.length);
+
+ ntru.init(false, kp.getPrivate());
+
+ byte[] decrypted = ntru.processBlock(encrypted, 0, encrypted.length);
+
+ assertTrue(Arrays.areEqual(plainText, decrypted));
+ }
+
+ // tests an empty message
+ private void testEmpty(NTRUEngine ntru, AsymmetricCipherKeyPair kp, NTRUEncryptionKeyGenerationParameters params)
+ throws InvalidCipherTextException
+ {
+ byte[] plainText = "".getBytes();
+
+ ntru.init(true, kp.getPublic());
+
+ byte[] encrypted = ntru.processBlock(plainText, 0, plainText.length);
+
+ ntru.init(false, kp.getPrivate());
+
+ byte[] decrypted = ntru.processBlock(encrypted, 0, encrypted.length);
+
+ assertTrue(Arrays.areEqual(plainText, decrypted));
+ }
+
+ // tests a message of the maximum allowed length
+ private void testMaxLength(NTRUEngine ntru, AsymmetricCipherKeyPair kp, NTRUEncryptionKeyGenerationParameters params)
+ throws InvalidCipherTextException
+ {
+ byte[] plainText = new byte[params.maxMsgLenBytes];
+ System.arraycopy("secret encrypted text".getBytes(), 0, plainText, 0, 21);
+ ntru.init(true, kp.getPublic());
+
+ byte[] encrypted = ntru.processBlock(plainText, 0, plainText.length);
+
+ ntru.init(false, kp.getPrivate());
+
+ byte[] decrypted = ntru.processBlock(encrypted, 0, encrypted.length);
+
+ assertTrue(Arrays.areEqual(plainText, decrypted));
+ }
+
+ // tests a message that is too long
+ private void testTooLong(NTRUEngine ntru, AsymmetricCipherKeyPair kp, NTRUEncryptionKeyGenerationParameters params)
+ {
+ byte[] plainText = new byte[params.maxMsgLenBytes + 1];
+ try
+ {
+ System.arraycopy("secret encrypted text".getBytes(), 0, plainText, 0, 21);
+
+ ntru.init(true, kp.getPublic());
+
+ byte[] encrypted = ntru.processBlock(plainText, 0, plainText.length);
+
+ ntru.init(false, kp.getPrivate());
+
+ byte[] decrypted = ntru.processBlock(encrypted, 0, encrypted.length);
+
+ assertTrue(Arrays.areEqual(plainText, decrypted));
+ fail("An exception should have been thrown!");
+ }
+ catch (DataLengthException ex)
+ {
+ assertEquals("Message too long: " + plainText.length + ">" + params.maxMsgLenBytes, ex.getMessage());
+ }
+ catch (InvalidCipherTextException e)
+ {
+ e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+ }
+ }
+
+ // tests that altering the public key *AFTER* encryption causes the decrypted message to be rejected
+ private void testInvalidEncoding(NTRUEngine ntru, AsymmetricCipherKeyPair kp, NTRUEncryptionKeyGenerationParameters params)
+ {
+ try
+ {
+ byte[] plainText = "secret encrypted text".getBytes();
+ ntru.init(true, kp.getPublic());
+
+ byte[] encrypted = ntru.processBlock(plainText, 0, plainText.length);
+
+ NTRUEncryptionPrivateKeyParameters orig = (NTRUEncryptionPrivateKeyParameters)kp.getPrivate();
+ IntegerPolynomial h = (IntegerPolynomial)((NTRUEncryptionPublicKeyParameters)kp.getPublic()).h.clone();
+ h.coeffs[0] = (h.coeffs[0] + 111) % params.q; // alter h
+ NTRUEncryptionPrivateKeyParameters privKey = new NTRUEncryptionPrivateKeyParameters(h, orig.t, orig.fp, params.getEncryptionParameters());
+
+ ntru.init(false, privKey);
+
+ ntru.processBlock(encrypted, 0, encrypted.length);
+
+ fail("An exception should have been thrown!");
+ }
+ catch (InvalidCipherTextException ex)
+ {
+ assertEquals("Invalid message encoding", ex.getMessage());
+ }
+ }
+
+ // encrypts and decrypts text using an encoded key pair (fastFp=false, simple ternary polynomials)
+ public void testEncodedKeysSlow()
+ throws IOException, InvalidCipherTextException
+ {
+ byte[] plainText = "secret encrypted text".getBytes();
+
+ // dense polynomials
+ NTRUEncryptionKeyGenerationParameters params = NTRUEncryptionKeyGenerationParameters.APR2011_743;
+ NTRUEngine ntru = new NTRUEngine();
+
+ byte[] privBytes = {2, -94, 95, 65, -107, 27, 98, 62, -15, -62, 21, -4, 119, -117, 7, 68, 100, 113, -36, -82, 87, -87, -82, 24, -45, -75, -74, -108, 105, 24, 123, 117, 124, 74, -27, 42, -106, -78, 114, 27, 18, 77, -41, 105, -113, 39, 49, 46, 109, -69, 61, 77, 49, 117, 14, -29, 42, 3, 120, -121, -120, -37, 95, 84, 60, -9, -31, -64, 31, 72, 115, -15, 21, -6, 27, -60, -73, -29, -33, -81, -43, 106, 65, 114, 102, -14, -115, -96, 9, 54, 23, -18, -24, -76, 84, -41, -79, 35, 88, 11, 41, 67, 44, -63, -28, 76, 84, -41, -103, 106, -22, 35, -2, -40, -48, -121, -128, 76, 63, 123, -11, 103, -35, -32, 21, -51, -99, -40, -103, -12, 64, -80, 57, -56, 1, -51, 103, 83, 50, 111, -87, -98, 7, -109, 25, -51, 23, -92};
+ byte[] pubBytes = {91, -66, -25, -81, -66, -33, 25, -31, 48, 23, -38, 20, -30, -120, -17, 1, 21, 51, -11, 102, -50, 62, 71, 79, 32, -49, -57, 105, 21, -34, -45, -67, 113, -46, -103, 57, 28, -54, -21, 94, -112, -63, 105, -100, -95, 21, -52, 50, 11, -22, -63, -35, -42, 50, 93, -40, 23, 0, 121, 23, -93, 111, -98, -14, 92, -24, -117, -8, -109, -118, -4, -107, -60, 100, -128, -47, -92, -117, -108, 39, -113, 43, 48, 68, 95, 123, -112, 41, -27, -99, 59, 33, -57, -120, -44, 72, -98, -105, -91, -52, -89, 107, 119, 87, -36, -102, -83, 67, -8, 30, -54, 74, 93, 119, -3, 126, 69, -104, -44, -24, 124, 108, -125, 73, 98, 121, -49, -37, -24, 87, -71, 91, 8, -31, -50, 95, 112, 27, 97, -93, 3, -73, -54, -16, -92, -108, -74, 88, -5, 23, 70, 69, -49, -46, -50, 65, 69, -54, -41, 109, 8, -80, -23, -84, 120, -77, 26, 99, -104, -33, 82, 91, 22, -17, 113, -29, 66, -7, -114, -101, -111, -47, -1, -3, -57, 62, 79, -70, -58, 45, 76, 28, -117, 59, -117, 113, 84, -55, 48, 119, 58, -105, -20, 80, 102, 14, -69, -69, 5, 11, -87, 107, 15, 105, -69, -27, -24, 47, -18, -54, -45, -67, 27, -52, -20, -94, 64, -26, -58, 98, 33, -61, 71, -101, 120, 28, 113, 72, 127, 50, 123, 36, -97, 78, 32, -74, 105, 62, 92, 84, -17, 21, -75, 24, -90, -78, -4, -121, 47, -82, 119, 27, -61, 17, -66, 43, 96, -49, -6, 66, -13, -75, -95, 64, -12, -39, 111, 46, -3, -123, 82, 12, -26, -30, -29, 71, -108, -79, -112, 13, 16, -70, 7, 100, 84, 89, -100, 114, 47, 56, 71, 83, 63, -61, -39, -53, -100, 23, -31, -52, -46, 36, -13, 62, 107, 28, -28, 92, 116, -59, 28, -111, -23, -44, 21, -2, 127, -112, 54, -126, 13, -104, 47, -43, -109, -19, 107, -94, -126, 50, 92, -69, 1, 115, -121, -52, -100, 25, 126, -7, 86, 77, 72, -2, -104, -42, 98, -16, 54, -67, 117, 14, -73, 4, 58, 121, 35, 1, 99, -127, -9, -60, 32, -37, -106, 6, -108, -13, -62, 23, -20, -9, 21, 15, 4, 126, -112, 123, 34, -67, -51, 43, -30, -75, 119, -112, -58, -55, -90, 2, -5, -46, -12, 119, 87, 24, -52, 2, -29, 113, 61, -82, -101, 57, -11, -107, -11, 67, -42, -43, -13, 112, -49, 82, 60, 13, -50, 108, 64, -64, 53, -107, -9, 102, -33, 75, -100, -115, 102, -113, -48, 19, -119, -72, -65, 22, -65, -93, 34, -71, 75, 101, 54, 126, 75, 34, -21, -53, -36, 127, -21, 70, 24, 89, -88, 63, -43, -4, 68, 97, -45, -101, -125, -38, 98, -118, -34, -63, 23, 78, 15, 17, 101, -107, 119, -41, 107, 117, 17, 108, 43, -93, -6, -23, -30, 49, -61, 27, 61, -125, -68, 51, 40, -106, -61, 51, 127, 2, 123, 7, -50, -115, -32, -95, -96, 67, 4, 5, 59, -45, 61, 95, 14, 2, -76, -121, 8, 125, 16, -126, 58, 118, -32, 19, -113, -113, 120, -101, 86, 76, -90, 50, -92, 51, -92, 1, 121, -74, -101, -33, 53, -53, -83, 46, 20, -87, -112, -61, -87, 106, -126, 64, 99, -60, 70, 120, 47, -53, 36, 20, -90, 110, 61, -93, 55, -10, 85, 45, 52, 79, 87, 100, -81, -85, 34, 55, -91, 27, 116, -18, -71, -11, 87, -11, 76, 48, 97, -78, 64, -100, -59, -12, 19, -90, 121, 48, -19, 64, 113, -70, -14, -70, 92, 124, 42, 95, 7, -115, 36, 127, 73, 33, 30, 121, 88, 16, -90, 99, 120, -68, 64, -125, -78, 76, 112, 68, 8, 105, 10, -47, -124, 39, -107, -101, 46, -61, 118, -74, 102, -62, -6, -128, 17, -45, 61, 76, 63, -10, -41, 50, -113, 75, -83, -59, -51, -23, -61, 47, 7, -80, 126, -2, 79, -53, 110, -93, -38, -91, -22, 20, -84, -113, -124, -73, 124, 0, 33, -58, 63, -26, 52, 7, 74, 65, 38, -33, 21, -9, -1, 120, -16, 47, -96, 59, -64, 74, 6, 48, -67, -32, -26, 35, 68, 47, 82, 36, 52, 41, 112, -28, -22, -51, -6, -49, 105, 16, -34, 99, -41, 75, 7, 79, -22, -125, -30, -126, 35, 119, -43, -30, 32, 8, 44, -42, -98, 78, -92, -95, -10, -94, -1, -91, -122, 77, 0, 40, -23, 36, 85, 123, -57, -74, -69, -90, 89, 111, -120, 22, 5, -48, 114, 59, 31, 31, -25, -3, 24, 110, -110, 73, -40, 92, -26, -12, 52, 83, -98, -119, -6, -117, -89, 95, 83, -25, 122, -26, 114, 81, 25, 110, 79, -49, -39, 10, -78, -65, 57, -90, -46, -126, 15, -124, -104, -89, -66, -87, 24, -45, 39, -34, -40, -13, 106, 12, -25, -116, -47, 79, -81, 64, -17, -31, -70, 87, 36, 46, 102, 107, 48, 88, 34, 46, 24, 63, -100, 106, 27, 58, -71, 38, 60, -66, 45, -89, 39, -60, -116, -14, -119, 118, 0, -24, -9, 38, -71, -79, 124, -119, -64, -9, 71, -56, -82, -73, -69, 127, -1, -20, 123, 32, -43, 49, 5, 49, 105, -5, -2, 5, -105, -111, 89, -30, -41, -49, 61, 80, 69, 44, -33, -116, -45, -96, 63, 28, -17, -106, -94, 90, -40, -88, 122, 116, 116, 113, -65, 104, 119, -3, 96, -45, 18, -120, -111, 83, 43, -5, 101, 71, 48, 104, -112, -95, -46, 53, -96, -93, -126, 96, 56, 104, -111, 114, -1, -44, -120, -112, -19, 100, 41, -122, 23, -78, 33, -35, 11, 57, -18, 106, -40, 74, 61, 66, 54, -77, 96, 70, 108, -128, 91, -97, -36, -23, -86, -91, 44, 58, 117, 2, 26, 44, 95, 79, -101, -81, -92, 110, -81, -12, -88, -21, -83, 60, 93, -121, -114, -48, -34, -119, -1, 127, -121, 54, -128, -106, -39, -108, 81, 17, -3, -13, -57, 74, 41, -122, -65, -107, -118, -65, -61, 103, -69, 19};
+
+ byte[] fullBytes = new byte[pubBytes.length + privBytes.length];
+
+ System.arraycopy(pubBytes, 0, fullBytes, 0, pubBytes.length);
+ System.arraycopy(privBytes, 0, fullBytes, pubBytes.length, privBytes.length);
+
+ NTRUEncryptionPrivateKeyParameters priv = new NTRUEncryptionPrivateKeyParameters(fullBytes, params.getEncryptionParameters());
+ NTRUEncryptionPublicKeyParameters pub = new NTRUEncryptionPublicKeyParameters(pubBytes, params.getEncryptionParameters());
+ AsymmetricCipherKeyPair kp = new AsymmetricCipherKeyPair(pub, priv);
+
+ ntru.init(true, kp.getPublic());
+
+ byte[] encrypted = ntru.processBlock(plainText, 0, plainText.length);
+
+ ntru.init(false, kp.getPrivate());
+
+ byte[] decrypted = ntru.processBlock(encrypted, 0, encrypted.length);
+ assertTrue(Arrays.areEqual(plainText, decrypted));
+
+ // sparse polynomials
+ params = NTRUEncryptionKeyGenerationParameters.EES1499EP1;
+ ntru = new NTRUEngine();
+ privBytes = new byte[] {116, 7, 118, 121, 6, 77, -36, 60, 65, 108, 10, -106, 12, 9, -22, -113, 122, -31, -31, 18, 120, 81, -33, 5, 122, -76, 109, -30, -101, -45, 21, 13, -11, -49, -111, 46, 91, 4, -28, -109, 121, -119, -121, -58, -113, -9, -10, -25, -53, 40, -86, -22, -50, 42, 52, 107, 119, 17, 33, 125, -26, 33, 55, 25, -77, -65, -106, 116, -67, 91, 105, -7, 42, -107, -54, 101, 12, -12, 57, -116, 45, -107, -17, 110, 35, -64, 19, -38, -122, 115, -93, 53, 69, 66, -106, 17, 20, -71, 121, 23, -21, -45, 108, 97, 23, -98, -12, -41, -31, -53, 30, -42, 15, 85, -21, -89, 118, 42, -117, -39, 69, 0, -63, 83, 48, -80, -14, -123, -4, -116, -90, -107, -89, 119, 29, -30, 69, 22, -84, 47, 117, -123, 102, -116, 35, 93, -13, 84, -9, -122, 58, 101, 93, -106, -119, -35, -75, 76, 27, -125, -22, 68, 101, 49, 103, -13, -98, 93, -56, -110, -19, -12, 74, 104, 7, 6, -11, 47, 57, 90, 75, -30, 47, 66, -58, 14, 14, 70, 11, -119, -36, -118, -55, -53, 101, -73, -77, 33, -29, 96, -86, 38, 47, 103, 19, -37, -17, -50, -82, -87, -119, 37, -54, 77, -69, -16, -48, -52, 110, -26, 111, 35, 26, -53, -10, 9, -108, -34, 102, 7, -18, -72, -26, 24, -50, -43, 92, 56, -94, 23, -36, 60, 28, -121, 27, 127, -93, -79, -45, -60, 105, -6, -88, 72, -41, 47, -51, 3, 91, 116, 75, 122, -94, -113, 28, -96, -62, -29, -74, -85, -93, 51, 58, 72, 44, 9, 18, -48, -24, 73, 122, 60, -23, 83, -110, -7, -111, -69, 106, 51, 118, -83, -18, 109, -32, 40, 22};
+
+ pubBytes = new byte[] {-62, 56, 59, -46, 30, -19, 22, -115, -20, 117, -14, 3, 2, -57, 85, -24, 27, 57, 49, -93, -52, 87, 49, 96, 15, 95, -95, -86, -61, 50, -18, 3, 109, -55, -110, -57, 82, 124, -5, -57, 68, -18, 126, 114, 6, -22, 8, 121, 125, 29, -16, 112, -81, 27, -7, 109, -44, -123, -15, -14, 74, -126, 95, -94, -91, 119, 80, -48, 41, 49, 6, 104, 93, -97, -108, -82, 93, 70, -127, -113, -22, -103, 35, -115, 20, -115, 63, 57, -84, -18, -107, 81, 44, -16, 83, 71, -27, -2, -125, 87, 26, 100, -116, 110, 94, -46, -56, -82, 119, -110, -127, -99, -8, -118, 90, 64, -29, 102, 99, 92, 86, -117, 26, -89, 32, 17, 55, -65, -10, -5, -74, 19, 13, 113, -15, -103, 17, 10, -127, -95, -79, 19, 11, -24, 59, 28, -70, -55, -69, -105, -20, -117, 66, 4, 77, 116, -124, -62, 19, 109, 49, -120, 10, -15, 108, 84, 126, 122, -46, -37, 114, -78, -72, 34, -12, 25, -104, -3, 114, -94, 16, 31, 31, -124, -109, -64, 57, -47, -113, -26, 97, -58, 112, -40, 49, 80, -54, -115, -98, -60, -123, 91, 14, 75, -86, 77, -93, 68, 112, 82, 79, 28, -25, 49, -27, -112, 103, 60, -128, 95, -63, 2, -51, 2, -107, 80, 113, 18, 123, 24, 70, 77, -56, -48, 33, 89, 88, 29, 112, -102, -15, 52, -96, 17, -9, 6, -11, -119, 29, -107, -84, -19, 84, 124, 19, 90, -60, -41, 123, -81, 96, -119, 17, -61, 62, 55, 95, -73, -13, -60, 56, 77, 24, -39, -107, -78, 47, -91, 88, 90, 34, 112, -80, 83, -58, 127, 76, -97, -40, 78, -20, -1, -62, 19, 6, -43, -46, -36, -53, -22, -28, -119, 8, 19, 79, -9, -54, -126, -3, -20, -110, -82, 51, 3, 1, -123, -41, -40, -11, 91, -52, 48, 104, -11, -2, 49, 45, 52, -33, 109, -44, -30, -44, -83, -108, -10, 77, 106, 82, 3, 14, -48, -18, -79, -64, -34, -63, -18, 122, 33, 25, 44, 82, -112, 111, 68, 97, -58, -38, 25, 62, 78, 97, -36, 57, -19, 122, -18, -74, 67, -127, -24, 32, -45, 67, -106, 90, 0, 1, 91, 30, -80, 95, 9, 78, -4, -14, 16, 111, -56, -102, -90, 52, -1, 116, 19, -127, -23, -87, 103, -94, -111, 118, 53, -69, 77, 17, -3, 31, -53, -21, -78, 124, -88, 52, 117, 34, -52, -77, -107, -38, -102, 23, 73, -76, -88, 95, 64, -85, 12, 36, -86, 86, -17, 77, 121, 90, 24, -49, -107, 33, -116, 65, 13, 91, 118, -107, -21, 65, -59, 18, 125, 61, -65, -68, -19, 23, 88, 60, -6, 78, -8, 69, -62, -118, -93, 97, -64, -67, 28, 28, -87, -97, 72, -125, -119, 4, -43, 7, 22, -15, 52, 52, -82, -5, -51, 99, 20, -59, -2, -54, -67, 40, -128, -20, -37, 50, 123, 32, 8, -39, -105, 93, 73, 77, 84, 43, 89, 88, -6, 7, -108, 81, 27, 1, 50, 16, -101, 67, 95, 119, 105, 70, 99, -127, 22, 127, -33, -19, -113, -55, -100, 122, -86, 98, 53, 27, -95, 4, -121, -96, 87, 67, -98, -37, -10, 92, 29, -3, -115, -23, 37, 8, -30, 99, -117, 62, 101, 83, 49, 60, -83, -47, -33, 41, -118, 76, -7, 111, -15, 123, -59, 53, 2, -20, -57, 24, 57, 62, 84, -26, -11, 93, -118, 54, -13, 56, 77, -66, 18, -62, -76, 80, 98, 26, 120, -93, 55, 103, -1, 78, -92, 120, -23, -60, -75, 11, 53, -62, -94, -80, 120, 113, 33, -24, -64, -5, 23, 120, -14, 61, 26, -1, 56, 79, 34, 116, -16, -95, -71, 40, -89, -50, 71, -117, -109, 2, -2, -34, 94, -78, -88, -27, 70, 94, -86, 123, -49, 107, -65, -67, 84, 90, 123, -61, -2, 43, -119, -93, 75, -4, -81, 98, -36, 125, -23, -37, 81, 104, 90, -63, -52, 88, -96, -44, 25, 3, -37, -123, -48, 113, -76, -94, -109, -115, 37, -39, 104, -124, 82, -73, 100, 48, -54, -40, -65, 81, 16, -85, -41, 60, 42, 117, 65, 77, 14, -8, -56, 52, -118, -109, 125, 13, 64, -20, 125, -37, -74, -28, 118, 112, -126, 18, -101, 11, 75, 30, -4, -121, -13, -65, -13, -122, -53, -52, 20, -2, 67, 18, -106, 67, 83, -111, 15, 106, 10, 113, 53, -112, -3, 118, 8, -56, 40, 53, 23, -123, 96, 87, -118, -97, -116, -47, 85, -73, -85, -82, 124, -55, 55, 61, 46, 12, -6, 34, 22, -22, 3, 115, -49, 102, 23, 46, 39, 0, 118, 3, -45, 48, -73, -38, 29, -36, 11, -127, -86, 30, 29, -2, -108, -114, 64, 110, 86, -46, -91, -64, 95, -40, -65, 49, -79, -126, -37, -103, -71, 53, -85, 45, -51, 33, -28, -126, 36, -77, -120, 55, -54, 72, -21, 58, -87, -73, 18, -12, 20, -100, 30, 118, -83, -22, -90, 71, -64, 108, 101, -46, 36, 105, -46, -91, 60, -113, 72, 100, 82, -90, 106, -127, 65, -94, 17, 77, -10, -112, 46, 118, 72, -84, 57, -86, -114, 88, 91, 79, 30, 107, -35, 61, 81, 71, 40, -29, -6, -107, 61, -62, -6, 65, -68, 118, 61, 110, -115, -119, -73, 104, 59, -66, -89, -127, -8, -67, 122, -38, 79, -13, 93, 1, -32, -47, -3, 62, 88, -112, 105, 73, 96, 73, -104, -126, -69, 21, -22, 16, -85, 116, 9, 82, 54, -15, -55, -67, 68, -23, 16, -89, 48, -17, -107, 60, -43, -34, 66, -114, 63, -3, -26, 68, 68, -86, 120, -111, 99, 61, 101, 27, 93, 31, 90, -33, -94, 29, -89, 41, -80, 26, -23, -80, 27, 107, 69, -45, -123, 62, 63, 80, 1, -28, 52, -8, 35, -86, -127, 76, 102, 83, -104, -79, -98, 77, -28, 118, 18, -15, -98, -39, 2, -58, 95, 64, 105, -82, -7, 96, 110, 104, 127, 126, -124, 26, 36, 33, -42, 59, 82, 127, 42, -24, -61, -50, -18, -87, 22, -32, -125, -70, 103, -121, -112, -94, 58, -95, -97, 53, 95, -61, -83, 42, 37, 80, 51, -118, 125, 15, 67, 41, -97, 41, -121, 29, -88, 100, -113, 39, 101, 47, 91, -36, 48, -56, -13, 12, 37, 0, 81, 3, -40, 8, 36, -65, -11, -32, 108, 62, 79, 70, 91, -83, 2, -47, 0, 91, 10, 87, -19, -40, 96, 106, 41, 120, -53, 40, -114, 90, 64, 59, -115, 39, 2, 53, -49, -72, -114, 94, 5, 49, 74, 13, 50, -14, 76, -123, -11, -81, 100, 120, 16, -41, -72, -118, 28, 41, 98, 122, 27, 18, -108, -43, 51, -71, 93, -13, -42, -64, -118, -106, 45, 108, 72, -128, 58, -123, -29, -114, 15, 52, -72, 108, -62, 75, -15, 105, -89, 25, 37, 13, -21, -109, 68, 5, -89, 69, 10, -46, 18, -57, 77, -103, -74, 57, -43, -110, 1, -80, 82, 5, -9, -49, -53, 83, 4, 44, 64, -117, -67, -11, 1, -65, -81, 34, -23, -71, 14, 105, -93, 2, -120, 90, 92, -6, -128, -16, -51, 27, 123, 71, -117, -72, -81, 26, 28, 5, -117, -30, 22, -72, -76, -32, -14, 82, 90, 69, 74, -94, -72, -30, -17, 12, -37, -3, -80, 72, 2, -40, 41, 0, -53, 48, -37, -117, -128, -120, -80, 28, 49, -52, 114, -119, 92, -42, -105, 125, -95, 78, 76, 123, -56, 32, -66, 69, -58, 57, -77, -100, -70, 125, 53, -115, 8, 116, 88, -34, 86, -75, 55, 64, 79, -113, -124, -91, 50, -82, -119, 50, 11, 87, -14, -25, 15, -1, -49, -127, -5, -50, 72, -29, -78, 101, -119, -21, -15, 97, -63, 57, -123, -94, -24, -8, 104, 86, 79, 49, 102, -8, -76, 8, 69, 99, -64, -108, 70, 36, 71, -127, 56, 39, 78, 109, 42, -42, -2, 126, 17, -88, -65, -23, -64, 78, 87, 7, 6, -82, -98, 41, -46, -10, -25, 90, -73, 24, 127, -27, 118, -9, 81, -3, 115, -4, 47, 86, -30, -9, -50, 32, 86, 114, 58, -5, 78, 74, 36, 29, -126, 116, 117, -114, -92, -121, -36, -86, -18, 55, 49, 112, 43, 111, -99, -116, 70, 60, -63, 87, -4, -35, 15, 28, -27, -65, 66, 115, -33, 112, 94, 74, -22, 104, -56, -27, 39, -8, -53, -120, 8, -109, 73, -68, 67, 40, -59, 59, 121, -76, -41, -80, -54, -88, -120, -121, -118, -58, 74, -120, 82, -88, -113, 30, -8, 54, -126, -106, 37, -43, -74, -56, 40, -76, 93, 91, 28, -59, -30, -2, 107, 6, -89, -69, -121, -125, -109, 5, -94, -7, -2, -5, -67, 54, -90, 39, 5, -80, 93, -99, 82, -100, -128, -8, -39, -109, 66, -11, 99, -41, 18, -32, -122, 69, 6, -95, -21, 9, 19, -117, -34, -42, 11, 20, 84, 89, 91, -61, -13, -7, 55, 90, -15, 62, 59, -4, 125, -127, -24, -124, -99, -63, -23, 52, 111, -52, -60, -113, -65, -26, 127, 57, 21, 102, 101, -77, 66, -116, 117, 80, 7, 1, -96, -29, -99, 75, -73, 44, -99, 61, -73, 15, -18, 89, 95, 104, -12, 94, 33, 13, -49, 118, -84, -122, -2, -121, 62, -32, -80, 11, -10, 102, -67, 20, -3, 25, -6, 51, -17, -123, -76, 103, 3, 127, -107, -5, 122, 65, 22, 113, 120, 6, -19, -110, 86, 55, -88, -124, 0, -54, 17, 112, 15, 105, -28, 111, -93, 85, -59, -88, 28, 123, 55, 117, 10, 76, 54, -98, 116, 40, -65, -53, -80, 46, 66, -8, -114, 102, 66, 67, -117, 46, 21, -116, -38, 58, -105, 101, 37, -16, 5, 55, -33, -87, 72, 122, -114, -91, 41, -114, 77, 50, 109, 35, -61, 9, -55, -118, 126, -35, -108, 5, 62, 125, -109, -115, -55, 32, -71, 69, 110, 87, -82, 119, 26, 103, -77, -38, -13, 113, 74, 69, 116, 94, -21, 5, 35, 73, -80, -87, 80, 13, 108, 1, 82, -56, -35, -21, -78, -98, 121, 112, -117, 72, 47, 76, -97, -84, -110, -35, -19, -120, -13, 127, 5, 56, 72, -22, 110, -8, -71, 0, -57, -125, -101, 60, -64, -32, 1, 126, -109, 9, 84, 117, 62, -68, -106, 28, -118, -52, -81, 112, 11, 55, 68, -86, -65, 123, 83, 55, -72, 110, 63, -90, 31, 11, 90, -60, 20, 14, -36, 5, -92, 11, -100, 64, -57, -72, -105, 7, 103, 125, 99, -88, 32, -5, 41, -115, -11, 89, 81, 77, -33, -7, -123, -17, 109, 59, 40, -12, -61, 98, -91, 19, -36, 108, 118, -124, -82, -40, -124, -66, 19, 127, -73, -39, 99, 43, -16, -44, -83, -77, -34, 68, -118, -71, -116, 114, 120, -34, -105, -32, -46, 102, 73, -79, 7, 42, 35, -66, 125, 34, 113, 66, 78, 71, 6, 44, -17, 4, -80, 38, -59, 12, -8, -78, 103, 8, 80, 18, -74, 20, 3, 56, -20, 106, -1, -12, 83, 4, 68, -119, 84, -87, 97, -53, 102, 119, 34, -85, 22, -26, 55, -107, 96, -70, 77, -68, -96, -15, -22, -77, -55, 5, 103, -42, -87, 122, -80, -103, -37, -120, -56, -16, -51, -7, -19, -104, 120, 9, 54, -85, 48, -76, -38, 58, -68, 116, -20, -44, 22, -32, 75, -46, -41, 13, -100, 16, -59, -93, -115, 54, 22, -110, -46, -119, 44, -98, -48, 4, -58, -115, -57, 103, -56, 36, -63, 104, -114, -125, 92, 65, 117, -21, -59, -31, 56, -98, -126, 56, 47, -116, 100, 122, -98, 4, 26, -29, -127, -113, 73, 48, 106, 125, -69, -127, 62, 56, -79, 76, 84, -46, -31, -17, 94, -98, 62, 63, 118, -24, 63, 123, -93, -46, 103, 117, -120, -35, 19, 25, 15, -110, -125, 12, -75, -50, 103, 49, 47, 98, 92, 10, -88, 54, -53, 19, 25, -90, 93, -49, 64, 126, -106, -30, -52, 58, 37, 68, -18, -60, 15, -27, 93, -124, 88, 110, -80, -106, 88, 55, 108, -58, -43, -70, 76, 85, 98, 27, -66, 18, 75, 69, 114, 90, -26, -10, -12, -126, 84, -109, 108, 15, -115, 90, 11, -127, 63, -7, 47, 92, -72, 38, -58, -35, 18, 25, 12, -103, 0};
+
+ fullBytes = new byte[pubBytes.length + privBytes.length];
+
+ System.arraycopy(pubBytes, 0, fullBytes, 0, pubBytes.length);
+ System.arraycopy(privBytes, 0, fullBytes, pubBytes.length, privBytes.length);
+
+ priv = new NTRUEncryptionPrivateKeyParameters(fullBytes, params.getEncryptionParameters());
+ pub = new NTRUEncryptionPublicKeyParameters(pubBytes, params.getEncryptionParameters());
+ kp = new AsymmetricCipherKeyPair(pub, priv);
+ ntru.init(true, kp.getPublic());
+
+ encrypted = ntru.processBlock(plainText, 0, plainText.length);
+
+ ntru.init(false, kp.getPrivate());
+
+ decrypted = ntru.processBlock(encrypted, 0, encrypted.length);
+
+ assertTrue(Arrays.areEqual(plainText, decrypted));
+ }
+
+ // encrypts and decrypts text using an encoded key pair (fastFp=true)
+ public void testEncodedKeysFast()
+ throws IOException, InvalidCipherTextException
+ {
+ byte[] plainText = "secret encrypted text".getBytes();
+
+ NTRUEncryptionKeyGenerationParameters params = NTRUEncryptionKeyGenerationParameters.APR2011_743_FAST;
+ NTRUEngine ntru = new NTRUEngine();
+ byte[] privBytes = {10, 16, 2, 30, -40, -63, -109, -77, -72, -122, 66, 23, -30, -44, -82, 0, 95, 64, 68, 48, -62, -14, 26, -19, -72, -25, 72, 123, 98, 84, -83, 0, 7, 40, 65, 35, 68, 113, 12, -112, 32, -123, 58, 85, -30, -109, -74, 0, 34, -8, -126, 57, 30, 98, -107, -45, -88, 102, 68, 42, -30, -108, -89, 0, 38, -40, -61, 37, 82, 113, -115, 123, -100, 5, 46, 125, -23, 78, -111, -76, 36, -90, 67, -31, 10, 2, 96, -127, 21, 50, -79, 13, -125, -124, 38, 55, -67, -95, 81, -107, 12, 117, -86, 99, -127, 11};
+ byte[] pubBytes = {108, -76, -104, -75, -87, -65, -18, -5, 45, -57, -100, -83, 51, 99, 94, 15, -73, 89, -100, 40, -114, 91, -107, 104, 127, 22, 13, 5, -16, 69, -104, -126, -44, 119, 47, -48, 75, 66, 83, -37, -66, -84, 73, 52, 23, -27, 53, 63, 56, 14, -2, 43, -59, -85, -80, 46, 38, -126, 75, -8, -63, 88, 104, 13, 72, -25, -10, -58, -51, 117, -84, 115, -24, -53, 83, -103, -97, 46, 90, -82, -61, 113, -49, -24, -72, 24, -124, -42, -36, 7, 41, 8, 14, -71, -75, -84, -24, -39, 56, 67, 88, 67, 66, -13, 70, -119, -64, 74, -100, -58, 35, 105, -20, 93, 80, -116, -55, 37, -52, 64, 0, -36, -71, 8, 77, -10, -41, -22, -73, 4, -115, -74, -74, -73, 23, -10, -26, 48, 125, -114, -32, -116, 74, 19, -104, 59, 43, 4, 97, -84, 112, 45, 16, 3, -110, -13, 119, -6, 29, -80, 109, 82, -31, 82, 30, 76, -111, -122, -50, -69, -41, -123, 107, 78, -35, 24, -121, -87, -108, 13, 70, 32, -74, 112, 104, -40, -61, 86, -125, 60, -94, -5, -18, 55, 54, -128, 83, -88, 71, 71, -66, 29, -113, 120, 30, 16, -38, 37, 96, -90, 38, -85, 88, 59, 15, -69, 6, -8, 1, 1, 71, 12, 60, -26, -110, 97, 77, 33, 58, 63, 104, 108, 83, 72, -21, -99, 115, -125, -16, 12, 99, 68, 39, -97, -6, 17, 26, -59, 123, -110, -37, -71, 47, 50, 5, 110, -34, 89, -74, 20, 79, -108, -7, 42, 106, -112, 44, 107, 106, -50, 55, 127, -124, 53, 123, -119, -46, -114, -52, -85, 75, 34, -39, -125, 58, -5, -31, -81, -37, -94, -123, 113, 11, -104, -124, 96, -103, 9, 108, 115, 97, -6, 98, -43, 26, -89, -23, 83, 60, 34, -86, -54, 107, 78, -48, 118, -31, -19, 29, -106, 108, 117, 83, 119, 51, -45, 115, 108, -13, -89, -29, 29, -120, 108, 20, 22, -3, 22, 78, -109, 95, 3, -68, -10, -53, -117, -96, -49, 9, 7, 38, 116, 33, -65, 31, 9, -5, -73, 127, 52, 113, 87, -39, 119, -96, 74, -105, 75, -89, 63, 69, -109, -127, 92, -54, 17, -98, -23, -69, 123, -125, 23, -93, 44, -11, -25, -101, 120, -29, 113, -33, 0, -117, -100, -114, 22, 41, -46, 29, -109, 107, 37, -94, 125, 46, 17, 16, -65, -14, 105, -118, 51, -21, 121, -5, 56, 29, 30, -69, -38, -10, -77, -74, 6, -105, 83, 110, 23, 114, -11, -123, -14, 30, -11, -9, 84, -90, -20, -29, 72, -85, 97, -74, -59, -112, -15, -51, -105, 117, 123, -17, -64, -127, 127, -33, -102, 88, 77, 122, -127, -15, 121, -125, -32, 53, 113, 45, -22, 84, -87, 20, 36, 65, 83, -84, -66, -22, 4, 15, -108, -92, 109, -128, -48, 4, -27, -13, 25, 51, -10, 34, 87, 88, 38, -87, 89, -64, -62, 20, 78, 35, -26, -2, 55, 3, -72, -64, 30, 28, -105, 6, -37, -38, -8, 26, -118, 105, -37, -30, 85, -66, 105, -46, -37, -11, -72, 71, 43, -65, -44, 17, -79, 98, 79, -77, -111, 95, 74, 101, -40, -106, 14, -108, -112, 86, 108, 49, 72, -38, -103, -31, 65, -119, 8, 78, -89, 100, -28, 116, 94, 15, -18, 108, 101, 85, 8, -6, 111, -82, -49, -66, -89, 28, -84, -85, -119, 111, 45, 83, -60, -40, -45, -101, -105, -35, 123, -1, 13, -112, 79, -80, -85, -109, -71, 69, 104, 95, -93, 121, -17, 83, 117, -73, -63, -65, -107, -72, 118, -102, -56, 38, 79, 121, -25, -86, -81, -38, 8, 122, 97, 37, 82, -40, 53, 11, 124, -94, -76, -107, -125, -9, -119, 63, 52, -34, -72, -21, 59, 3, -100, -127, 47, -102, 19, -37, -45, -114, -65, 39, -106, 6, -127, -110, -38, 96, -38, -51, 110, -3, 28, 8, 102, -102, 96, -127, 109, -56, -53, -13, 59, -98, 92, 80, 1, 55, -91, -122, -105, 28, 69, -85, 109, -38, 105, 87, -5, 3, -102, 62, -92, 60, 43, -20, -7, -23, -84, 106, 121, -48, 123, -112, 56, -17, -52, 14, -123, -122, 64, 14, -23, -71, 60, 70, -121, 6, 37, -15, 77, 96, 104, -34, 58, -125, -61, 1, -26, 118, -78, -35, -1, 0, 5, 33, -98, -86, -127, 25, 56, -91, 82, -33, 60, -64, -86, 27, 31, -80, -79, 118, -12, -18, 40, -72, 32, 119, -28, -62, 100, -121, -71, -79, -9, 38, -37, 25, 65, -46, 8, -112, 37, 9, -56, 123, -40, -44, -90, -21, -54, -2, -7, 107, -93, 24, -126, 69, 42, -111, -84, 57, 69, -119, 21, 60, 57, -122, 111, -99, 49, -46, -119, 100, 98, 24, -62, 112, 122, 46, 18, -35, -67, 89, 104, 82, 12, 125, 57, -70, -112, -109, 96, 51, -68, 1, -101, -59, -92, 54, 85, -41, 17, 31, 94, 75, -128, 53, 84, 0, -83, -94, -123, 49, -30, -24, 18, 46, 48, -33, 120, 66, -69, 70, 23, -124, -117, 81, 96, 46, 47, -33, 83, -13, -14, -94, 49, 66, -46, 84, -27, -77, 6, 0, -75, -18, 86, -119, -88, 82, -50, 55, -20, 63, 55, -57, 22, -108, -103, -17, -22, 64, 65, 90, -34, -96, -117, 51, 119, -103, -35, 95, -15, -118, 2, -31, 31, -9, -58, 84, -75, 80, 39, -101, -56, 16, -75, 59, 48, -63, -24, -95, 119, 73, -110, -115, 49, -18, 54, -124, 112, -61, -40, -105, -118, -66, 15, -107, 75, 82, -70, -87, -11, -11, 48, 41, 119, -42, -34, -33, 57, 23, -14, -45, -125, -108, -75, 3, 44, 44, 58, 126, -126, -20, -123, 58, 114, 79, -102, -115, 115, 12, 66, 108, 84, 43, -46, -80, -41, -70, 111, -114, 123, 21, 1, 34, -72, 23, 105, -52, -39, -54, -119, 45, 77, -16, -66, -105, -11, 91, -46, 77, -104, -93, 52, -3, 17, 55, -10, 67, -33, 43, 75, -103, 106, 7, -35, -65, -21, 68, 118, -38, 59, -115, 31};
+
+ byte[] fullBytes = new byte[pubBytes.length + privBytes.length];
+
+ System.arraycopy(pubBytes, 0, fullBytes, 0, pubBytes.length);
+ System.arraycopy(privBytes, 0, fullBytes, pubBytes.length, privBytes.length);
+
+ NTRUEncryptionPrivateKeyParameters priv = new NTRUEncryptionPrivateKeyParameters(fullBytes, params.getEncryptionParameters());
+ NTRUEncryptionPublicKeyParameters pub = new NTRUEncryptionPublicKeyParameters(pubBytes, params.getEncryptionParameters());
+ AsymmetricCipherKeyPair kp = new AsymmetricCipherKeyPair(pub, priv);
+
+ ntru.init(true, kp.getPublic());
+
+ byte[] encrypted = ntru.processBlock(plainText, 0, plainText.length);
+
+ assertEquals(encrypted.length, ntru.getOutputBlockSize());
+
+ ntru.init(false, kp.getPrivate());
+
+ byte[] decrypted = ntru.processBlock(encrypted, 0, encrypted.length);
+
+ assertTrue(Arrays.areEqual(plainText, decrypted));
+ }
+
+ private class VisibleNTRUEngine
+ extends NTRUEngine
+ {
+ public IntegerPolynomial encrypt(IntegerPolynomial m, TernaryPolynomial r, IntegerPolynomial pubKey)
+ {
+ return super.encrypt(m, r, pubKey);
+ }
+
+ public IntegerPolynomial decrypt(IntegerPolynomial e, Polynomial priv_t, IntegerPolynomial priv_fp)
+ {
+ return super.decrypt(e, priv_t, priv_fp);
+ }
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUEncryptionParametersTest.java b/core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUEncryptionParametersTest.java
new file mode 100644
index 00000000..c05ea7d0
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUEncryptionParametersTest.java
@@ -0,0 +1,48 @@
+package org.spongycastle.pqc.crypto.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import junit.framework.TestCase;
+import org.spongycastle.pqc.crypto.ntru.NTRUEncryptionKeyGenerationParameters;
+
+public class NTRUEncryptionParametersTest
+ extends TestCase
+{
+ public void testLoadSave()
+ throws IOException
+ {
+ NTRUEncryptionKeyGenerationParameters params = NTRUEncryptionKeyGenerationParameters.EES1499EP1;
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ params.writeTo(os);
+ ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
+ assertEquals(params, new NTRUEncryptionKeyGenerationParameters(is));
+ }
+
+ public void testEqualsHashCode()
+ throws IOException
+ {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ NTRUEncryptionKeyGenerationParameters.EES1499EP1.writeTo(os);
+ ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
+ NTRUEncryptionKeyGenerationParameters params = new NTRUEncryptionKeyGenerationParameters(is);
+
+ assertEquals(params, NTRUEncryptionKeyGenerationParameters.EES1499EP1);
+ assertEquals(params.hashCode(), NTRUEncryptionKeyGenerationParameters.EES1499EP1.hashCode());
+
+ params.N += 1;
+ assertFalse(params.equals(NTRUEncryptionKeyGenerationParameters.EES1499EP1));
+ assertFalse(NTRUEncryptionKeyGenerationParameters.EES1499EP1.equals(params));
+ assertFalse(params.hashCode() == NTRUEncryptionKeyGenerationParameters.EES1499EP1.hashCode());
+ }
+
+ public void testClone()
+ {
+ NTRUEncryptionKeyGenerationParameters params = NTRUEncryptionKeyGenerationParameters.APR2011_439;
+ assertEquals(params, params.clone());
+
+ params = NTRUEncryptionKeyGenerationParameters.APR2011_439_FAST;
+ assertEquals(params, params.clone());
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUSignatureKeyTest.java b/core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUSignatureKeyTest.java
new file mode 100644
index 00000000..f741532c
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUSignatureKeyTest.java
@@ -0,0 +1,58 @@
+package org.spongycastle.pqc.crypto.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import junit.framework.TestCase;
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.pqc.crypto.ntru.NTRUSigner;
+import org.spongycastle.pqc.crypto.ntru.NTRUSigningKeyGenerationParameters;
+import org.spongycastle.pqc.crypto.ntru.NTRUSigningKeyPairGenerator;
+import org.spongycastle.pqc.crypto.ntru.NTRUSigningPrivateKeyParameters;
+import org.spongycastle.pqc.crypto.ntru.NTRUSigningPublicKeyParameters;
+
+public class NTRUSignatureKeyTest
+ extends TestCase
+{
+ public void testEncode()
+ throws IOException
+ {
+ for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157, NTRUSigningKeyGenerationParameters.TEST157_PROD})
+ {
+ testEncode(params);
+ }
+ }
+
+ private void testEncode(NTRUSigningKeyGenerationParameters params)
+ throws IOException
+ {
+ NTRUSigner ntru = new NTRUSigner(params.getSigningParameters());
+ NTRUSigningKeyPairGenerator kGen = new NTRUSigningKeyPairGenerator();
+
+ kGen.init(params);
+
+ AsymmetricCipherKeyPair kp = kGen.generateKeyPair();
+
+ NTRUSigningPrivateKeyParameters kPriv = (NTRUSigningPrivateKeyParameters)kp.getPrivate();
+ NTRUSigningPublicKeyParameters kPub = (NTRUSigningPublicKeyParameters)kp.getPublic();
+
+ // encode to byte[] and reconstruct
+ byte[] priv = kPriv.getEncoded();
+ byte[] pub = kPub.getEncoded();
+ AsymmetricCipherKeyPair kp2 = new AsymmetricCipherKeyPair(new NTRUSigningPublicKeyParameters(pub, params.getSigningParameters()), new NTRUSigningPrivateKeyParameters(priv, params));
+ assertEquals(kPub, kp2.getPublic());
+ assertEquals(kPriv, kp2.getPrivate());
+
+ // encode to OutputStream and reconstruct
+ ByteArrayOutputStream bos1 = new ByteArrayOutputStream();
+ ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
+ kPriv.writeTo(bos1);
+ kPub.writeTo(bos2);
+ ByteArrayInputStream bis1 = new ByteArrayInputStream(bos1.toByteArray());
+ ByteArrayInputStream bis2 = new ByteArrayInputStream(bos2.toByteArray());
+ AsymmetricCipherKeyPair kp3 = new AsymmetricCipherKeyPair(new NTRUSigningPublicKeyParameters(bis2, params.getSigningParameters()), new NTRUSigningPrivateKeyParameters(bis1, params));
+ assertEquals(kPub, kp3.getPublic());
+ assertEquals(kPriv, kp3.getPrivate());
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUSignatureParametersTest.java b/core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUSignatureParametersTest.java
new file mode 100644
index 00000000..96fa3d4c
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUSignatureParametersTest.java
@@ -0,0 +1,64 @@
+package org.spongycastle.pqc.crypto.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import junit.framework.TestCase;
+import org.spongycastle.pqc.crypto.ntru.NTRUSigningKeyGenerationParameters;
+
+public class NTRUSignatureParametersTest
+ extends TestCase
+{
+ public void testLoadSave()
+ throws IOException
+ {
+ for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157, NTRUSigningKeyGenerationParameters.TEST157_PROD, NTRUSigningKeyGenerationParameters.APR2011_743, NTRUSigningKeyGenerationParameters.APR2011_743_PROD})
+ {
+ testLoadSave(params);
+ }
+ }
+
+ private void testLoadSave(NTRUSigningKeyGenerationParameters params)
+ throws IOException
+ {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ params.writeTo(os);
+ ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
+ assertEquals(params, new NTRUSigningKeyGenerationParameters(is));
+ }
+
+ public void testEqualsHashCode()
+ throws IOException
+ {
+ for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157, NTRUSigningKeyGenerationParameters.TEST157_PROD, NTRUSigningKeyGenerationParameters.APR2011_743, NTRUSigningKeyGenerationParameters.APR2011_743_PROD})
+ {
+ testEqualsHashCode(params);
+ }
+ }
+
+ private void testEqualsHashCode(NTRUSigningKeyGenerationParameters params)
+ throws IOException
+ {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ params.writeTo(os);
+ ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
+ NTRUSigningKeyGenerationParameters params2 = new NTRUSigningKeyGenerationParameters(is);
+
+ assertEquals(params, params2);
+ assertEquals(params.hashCode(), params2.hashCode());
+
+ params.N += 1;
+ assertFalse(params.equals(params2));
+ assertFalse(params.equals(params2));
+ assertFalse(params.hashCode() == params2.hashCode());
+ }
+
+ public void testClone()
+ {
+ for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157, NTRUSigningKeyGenerationParameters.TEST157_PROD, NTRUSigningKeyGenerationParameters.APR2011_743, NTRUSigningKeyGenerationParameters.APR2011_743_PROD})
+ {
+ assertEquals(params, params.clone());
+ }
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUSignerTest.java b/core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUSignerTest.java
new file mode 100644
index 00000000..91451e43
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUSignerTest.java
@@ -0,0 +1,317 @@
+package org.spongycastle.pqc.crypto.test;
+
+
+import junit.framework.TestCase;
+
+/**
+ * @deprecated algorithm no longer safe.
+ */
+public class NTRUSignerTest
+ extends TestCase
+{
+ public void testStub()
+ {
+
+ }
+ /*
+ public void testCreateBasis()
+ {
+ for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157.clone(), NTRUSigningKeyGenerationParameters.TEST157_PROD.clone()})
+ {
+ testCreateBasis(params);
+ }
+ }
+
+ private void testCreateBasis(NTRUSigningKeyGenerationParameters params)
+ {
+ NTRUSigningKeyPairGenerator ntru = new NTRUSigningKeyPairGenerator();
+
+ ntru.init(params);
+
+ NTRUSigningKeyPairGenerator.FGBasis basis = (NTRUSigningKeyPairGenerator.FGBasis)ntru.generateBoundedBasis();
+ assertTrue(equalsQ(basis.f, basis.fPrime, basis.F, basis.G, params.q, params.N));
+
+ // test KeyGenAlg.FLOAT (default=RESULTANT)
+ params.keyGenAlg = NTRUSigningKeyGenerationParameters.KEY_GEN_ALG_FLOAT;
+ ntru.init(params);
+ basis = (NTRUSigningKeyPairGenerator.FGBasis)ntru.generateBoundedBasis();
+ assertTrue(equalsQ(basis.f, basis.fPrime, basis.F, basis.G, params.q, params.N));
+ }
+
+ // verifies that f*G-g*F=q
+ private boolean equalsQ(Polynomial f, Polynomial g, IntegerPolynomial F, IntegerPolynomial G, int q, int N)
+ {
+ IntegerPolynomial x = f.mult(G);
+ x.sub(g.mult(F));
+ boolean equalsQ = true;
+ for (int i = 1; i < x.coeffs.length; i++)
+ {
+ equalsQ &= x.coeffs[i] == 0;
+ }
+ equalsQ &= x.coeffs[0] == q;
+ return equalsQ;
+ }
+
+ /**
+ * a test for the one-method-call variants: sign(byte, SignatureKeyPair) and verify(byte[], byte[], SignatureKeyPair)
+ *
+ public void testSignVerify157()
+ throws IOException
+ {
+ for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157.clone(), NTRUSigningKeyGenerationParameters.TEST157_PROD.clone(), NTRUSigningKeyGenerationParameters.APR2011_439.clone(), NTRUSigningKeyGenerationParameters.APR2011_439_PROD.clone(), NTRUSigningKeyGenerationParameters.APR2011_743.clone(), NTRUSigningKeyGenerationParameters.APR2011_743_PROD.clone()})
+ {
+ testSignVerify(params);
+ }
+ }
+
+ public void testSignVerify439()
+ throws IOException
+ {
+ for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.APR2011_439.clone(), NTRUSigningKeyGenerationParameters.APR2011_439_PROD.clone()})
+ {
+ testSignVerify(params);
+ }
+ }
+//
+// public void testSignVerify743()
+// throws IOException
+// {
+// for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.APR2011_743.clone(), NTRUSigningKeyGenerationParameters.APR2011_743_PROD.clone()})
+// {
+// testSignVerify(params);
+// }
+// }
+
+ private void testSignVerify(NTRUSigningKeyGenerationParameters params)
+ throws IOException
+ {
+ NTRUSigner ntru = new NTRUSigner(params.getSigningParameters());
+ NTRUSigningKeyPairGenerator kGen = new NTRUSigningKeyPairGenerator();
+
+ kGen.init(params);
+
+ AsymmetricCipherKeyPair kp = kGen.generateKeyPair();
+
+ Random rng = new Random();
+ byte[] msg = new byte[10 + rng.nextInt(1000)];
+ rng.nextBytes(msg);
+
+ // sign and verify
+ ntru.init(true, kp.getPrivate());
+
+ ntru.update(msg, 0, msg.length);
+
+ byte[] s = ntru.generateSignature();
+
+ ntru.init(false, kp.getPublic());
+
+ ntru.update(msg, 0, msg.length);
+
+ boolean valid = ntru.verifySignature(s);
+
+ assertTrue(valid);
+
+ // altering the signature should make it invalid
+ s[rng.nextInt(params.N)] += 1;
+ ntru.init(false, kp.getPublic());
+
+ ntru.update(msg, 0, msg.length);
+
+ valid = ntru.verifySignature(s);
+ assertFalse(valid);
+
+ // test that a random signature fails
+ rng.nextBytes(s);
+
+ ntru.init(false, kp.getPublic());
+
+ ntru.update(msg, 0, msg.length);
+
+ valid = ntru.verifySignature(s);
+ assertFalse(valid);
+
+ // encode, decode keypair, test
+ NTRUSigningPrivateKeyParameters priv = new NTRUSigningPrivateKeyParameters(((NTRUSigningPrivateKeyParameters)kp.getPrivate()).getEncoded(), params);
+ NTRUSigningPublicKeyParameters pub = new NTRUSigningPublicKeyParameters(((NTRUSigningPublicKeyParameters)kp.getPublic()).getEncoded(), params.getSigningParameters());
+ kp = new AsymmetricCipherKeyPair(pub, priv);
+
+ ntru.init(true, kp.getPrivate());
+ ntru.update(msg, 0, msg.length);
+
+ s = ntru.generateSignature();
+
+ ntru.init(false, kp.getPublic());
+ ntru.update(msg, 0, msg.length);
+
+ valid = ntru.verifySignature(s);
+ assertTrue(valid);
+
+ // altering the signature should make it invalid
+ s[rng.nextInt(s.length)] += 1;
+ ntru.init(false, kp.getPublic());
+ ntru.update(msg, 0, msg.length);
+ valid = ntru.verifySignature(s);
+ assertFalse(valid);
+
+ // sparse/dense
+ params.sparse = !params.sparse;
+
+ ntru.init(true, kp.getPrivate());
+ ntru.update(msg, 0, msg.length);
+
+ s = ntru.generateSignature();
+
+ ntru.init(false, kp.getPublic());
+ ntru.update(msg, 0, msg.length);
+ valid = ntru.verifySignature(s);
+ assertTrue(valid);
+
+ s[rng.nextInt(s.length)] += 1;
+ ntru.init(false, kp.getPublic());
+ ntru.update(msg, 0, msg.length);
+ valid = ntru.verifySignature(s);
+ assertFalse(valid);
+ params.sparse = !params.sparse;
+
+ // decrease NormBound to force multiple signing attempts
+ NTRUSigningKeyGenerationParameters params2 = params.clone();
+ params2.normBoundSq *= 4.0 / 9;
+ params2.signFailTolerance = 10000;
+ ntru = new NTRUSigner(params2.getSigningParameters());
+
+ ntru.init(true, kp.getPrivate());
+ ntru.update(msg, 0, msg.length);
+
+ s = ntru.generateSignature();
+
+ ntru.init(false, kp.getPublic());
+ ntru.update(msg, 0, msg.length);
+ valid = ntru.verifySignature(s);
+
+ assertTrue(valid);
+
+ // test KeyGenAlg.FLOAT (default=RESULTANT)
+ params2 = params.clone();
+ params.keyGenAlg = NTRUSigningKeyGenerationParameters.KEY_GEN_ALG_FLOAT;
+ ntru = new NTRUSigner(params.getSigningParameters());
+
+ kGen.init(params);
+
+ kp = kGen.generateKeyPair();
+ ntru.init(true, kp.getPrivate());
+ ntru.update(msg, 0, msg.length);
+
+ s = ntru.generateSignature();
+ ntru.init(false, kp.getPublic());
+ ntru.update(msg, 0, msg.length);
+ valid = ntru.verifySignature(s);
+ assertTrue(valid);
+ s[rng.nextInt(s.length)] += 1;
+ ntru.init(false, kp.getPublic());
+ ntru.update(msg, 0, msg.length);
+ valid = ntru.verifySignature(s);
+ assertFalse(valid);
+ }
+
+ /**
+ * test for the initSign/update/sign and initVerify/update/verify variant
+ *
+ public void testInitUpdateSign()
+ {
+ for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157.clone(), NTRUSigningKeyGenerationParameters.TEST157_PROD.clone()})
+ {
+ testInitUpdateSign(params);
+ }
+ }
+
+ private void testInitUpdateSign(NTRUSigningKeyGenerationParameters params)
+ {
+ NTRUSigner ntru = new NTRUSigner(params.getSigningParameters());
+ NTRUSigningKeyPairGenerator kGen = new NTRUSigningKeyPairGenerator();
+
+ kGen.init(params);
+
+ AsymmetricCipherKeyPair kp = kGen.generateKeyPair();
+
+ Random rng = new Random();
+ byte[] msg = new byte[10 + rng.nextInt(1000)];
+ rng.nextBytes(msg);
+
+ // sign and verify a message in two pieces each
+ ntru.init(true, kp.getPrivate());
+ int splitIdx = rng.nextInt(msg.length);
+ ntru.update(msg[0]); // first byte
+ ntru.update(msg, 1, splitIdx - 1); // part 1 of msg
+ ntru.update(msg, splitIdx, msg.length - splitIdx);
+ byte[] s = ntru.generateSignature(); // part 2 of msg
+ ntru.init(false, kp.getPublic());
+ splitIdx = rng.nextInt(msg.length);
+ ntru.update(msg, 0, splitIdx); // part 1 of msg
+ ntru.update(msg, splitIdx, msg.length - splitIdx); // part 2 of msg
+ boolean valid = ntru.verifySignature(s);
+ assertTrue(valid);
+ // verify the same signature with the one-step method
+ ntru.init(false, (NTRUSigningPublicKeyParameters)kp.getPublic());
+ ntru.update(msg, 0, msg.length); // part 1 of msg
+ valid = ntru.verifySignature(s);
+ assertTrue(valid);
+
+ // sign using the one-step method and verify using the multi-step method
+ ntru.init(true, kp.getPrivate());
+ ntru.update(msg, 0, msg.length);
+ s = ntru.generateSignature();
+ ntru.init(false, (NTRUSigningPublicKeyParameters)kp.getPublic());
+ splitIdx = rng.nextInt(msg.length);
+ ntru.update(msg, 0, splitIdx); // part 1 of msg
+ ntru.update(msg, splitIdx, msg.length - splitIdx); // part 2 of msg
+ valid = ntru.verifySignature(s);
+ assertTrue(valid);
+ }
+
+ public void testCreateMsgRep()
+ {
+ for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157.clone(), NTRUSigningKeyGenerationParameters.TEST157_PROD.clone()})
+ {
+ testCreateMsgRep(params);
+ }
+ }
+
+ private void testCreateMsgRep(NTRUSigningKeyGenerationParameters params)
+ {
+ VisibleNTRUSigner ntru = new VisibleNTRUSigner(params.getSigningParameters());
+ byte[] msgHash = "adfsadfsdfs23234234".getBytes();
+
+ // verify that the message representative is reproducible
+ IntegerPolynomial i1 = ntru.createMsgRep(msgHash, 1);
+ IntegerPolynomial i2 = ntru.createMsgRep(msgHash, 1);
+ assertTrue(Arrays.areEqual(i1.coeffs, i2.coeffs));
+ i1 = ntru.createMsgRep(msgHash, 5);
+ i2 = ntru.createMsgRep(msgHash, 5);
+ assertTrue(Arrays.areEqual(i1.coeffs, i2.coeffs));
+
+ i1 = ntru.createMsgRep(msgHash, 2);
+ i2 = ntru.createMsgRep(msgHash, 3);
+ assertFalse(Arrays.areEqual(i1.coeffs, i2.coeffs));
+ }
+
+ private class VisibleNTRUSigner
+ extends NTRUSigner
+ {
+
+ /**
+ * Constructs a new instance with a set of signature parameters.
+ *
+ * @param params signature parameters
+ *
+ public VisibleNTRUSigner(NTRUSigningParameters params)
+ {
+ super(params);
+ }
+
+ public IntegerPolynomial createMsgRep(byte[] hash, int i)
+ {
+ return super.createMsgRep(hash, i);
+ }
+ }
+ */
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUSigningParametersTest.java b/core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUSigningParametersTest.java
new file mode 100644
index 00000000..b9129f00
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/crypto/test/NTRUSigningParametersTest.java
@@ -0,0 +1,65 @@
+package org.spongycastle.pqc.crypto.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import junit.framework.TestCase;
+import org.spongycastle.pqc.crypto.ntru.NTRUSigningKeyGenerationParameters;
+
+public class NTRUSigningParametersTest
+ extends TestCase
+{
+
+ public void testLoadSave()
+ throws IOException
+ {
+ for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157, NTRUSigningKeyGenerationParameters.TEST157_PROD})
+ {
+ testLoadSave(params);
+ }
+ }
+
+ private void testLoadSave(NTRUSigningKeyGenerationParameters params)
+ throws IOException
+ {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ params.writeTo(os);
+ ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
+ assertEquals(params, new NTRUSigningKeyGenerationParameters(is));
+ }
+
+ public void testEqualsHashCode()
+ throws IOException
+ {
+ for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157, NTRUSigningKeyGenerationParameters.TEST157_PROD})
+ {
+ testEqualsHashCode(params);
+ }
+ }
+
+ private void testEqualsHashCode(NTRUSigningKeyGenerationParameters params)
+ throws IOException
+ {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ params.writeTo(os);
+ ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
+ NTRUSigningKeyGenerationParameters params2 = new NTRUSigningKeyGenerationParameters(is);
+
+ assertEquals(params, params2);
+ assertEquals(params.hashCode(), params2.hashCode());
+
+ params.N += 1;
+ assertFalse(params.equals(params2));
+ assertFalse(params.equals(params2));
+ assertFalse(params.hashCode() == params2.hashCode());
+ }
+
+ public void testClone()
+ {
+ for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157, NTRUSigningKeyGenerationParameters.TEST157_PROD})
+ {
+ assertEquals(params, params.clone());
+ }
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/pqc/crypto/test/RainbowSignerTest.java b/core/src/test/java/org/spongycastle/pqc/crypto/test/RainbowSignerTest.java
new file mode 100644
index 00000000..361a80a5
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/crypto/test/RainbowSignerTest.java
@@ -0,0 +1,67 @@
+package org.spongycastle.pqc.crypto.test;
+
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.digests.SHA224Digest;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.pqc.crypto.DigestingMessageSigner;
+import org.spongycastle.pqc.crypto.rainbow.RainbowKeyGenerationParameters;
+import org.spongycastle.pqc.crypto.rainbow.RainbowKeyPairGenerator;
+import org.spongycastle.pqc.crypto.rainbow.RainbowParameters;
+import org.spongycastle.pqc.crypto.rainbow.RainbowSigner;
+import org.spongycastle.util.BigIntegers;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.FixedSecureRandom;
+import org.spongycastle.util.test.SimpleTest;
+
+
+public class RainbowSignerTest
+extends SimpleTest
+{
+ byte[] keyData = Hex.decode("b5014e4b60ef2ba8b6211b4062ba3224e0427dd3");
+
+ SecureRandom keyRandom = new FixedSecureRandom(new byte[][] { keyData, keyData });
+
+
+ public String getName()
+ {
+ return "Rainbow";
+ }
+
+ public void performTest()
+ {
+ RainbowParameters params = new RainbowParameters();
+
+ RainbowKeyPairGenerator rainbowKeyGen = new RainbowKeyPairGenerator();
+ RainbowKeyGenerationParameters genParam = new RainbowKeyGenerationParameters(keyRandom, params);
+
+ rainbowKeyGen.init(genParam);
+
+ AsymmetricCipherKeyPair pair = rainbowKeyGen.generateKeyPair();
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), keyRandom);
+
+ DigestingMessageSigner rainbowSigner = new DigestingMessageSigner(new RainbowSigner() , new SHA224Digest());
+ rainbowSigner.init(true, param);
+
+ byte[] message = BigIntegers.asUnsignedByteArray(new BigInteger("968236873715988614170569073515315707566766479517"));
+ rainbowSigner.update(message, 0, message.length);
+ byte[] sig = rainbowSigner.generateSignature();
+
+ rainbowSigner.init(false, pair.getPublic());
+ rainbowSigner.update(message, 0, message.length);
+ if (!rainbowSigner.verify(sig))
+ {
+ fail("verification fails");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new RainbowSignerTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/pqc/crypto/test/RegressionTest.java b/core/src/test/java/org/spongycastle/pqc/crypto/test/RegressionTest.java
new file mode 100644
index 00000000..a081ec89
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/crypto/test/RegressionTest.java
@@ -0,0 +1,33 @@
+package org.spongycastle.pqc.crypto.test;
+
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+public class RegressionTest
+{
+ public static Test[] tests = {
+ new GMSSSignerTest(),
+ new McElieceFujisakiCipherTest(),
+ new McElieceKobaraImaiCipherTest(),
+ new McEliecePKCSCipherTest(),
+ new McEliecePointchevalCipherTest(),
+ new RainbowSignerTest()
+ };
+
+ public static void main(
+ String[] args)
+ {
+ for (int i = 0; i != tests.length; i++)
+ {
+ TestResult result = tests[i].perform();
+
+ if (result.getException() != null)
+ {
+ result.getException().printStackTrace();
+ }
+
+ System.out.println(result);
+ }
+ }
+}
+
diff --git a/core/src/test/java/org/spongycastle/pqc/math/ntru/euclid/test/AllTests.java b/core/src/test/java/org/spongycastle/pqc/math/ntru/euclid/test/AllTests.java
new file mode 100644
index 00000000..051581f8
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/math/ntru/euclid/test/AllTests.java
@@ -0,0 +1,24 @@
+package org.spongycastle.pqc.math.ntru.euclid.test;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class AllTests
+ extends TestCase
+{
+ public static void main (String[] args)
+ {
+ junit.textui.TestRunner.run(suite());
+ }
+
+ public static Test suite()
+ {
+ TestSuite suite = new TestSuite("NTRU Euclid Tests");
+
+ suite.addTestSuite(BigIntEuclideanTest.class);
+ suite.addTestSuite(IntEuclideanTest.class);
+
+ return suite;
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/pqc/math/ntru/euclid/test/BigIntEuclideanTest.java b/core/src/test/java/org/spongycastle/pqc/math/ntru/euclid/test/BigIntEuclideanTest.java
new file mode 100644
index 00000000..5078090a
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/math/ntru/euclid/test/BigIntEuclideanTest.java
@@ -0,0 +1,23 @@
+package org.spongycastle.pqc.math.ntru.euclid.test;
+
+import java.math.BigInteger;
+
+import junit.framework.TestCase;
+import org.spongycastle.pqc.math.ntru.euclid.BigIntEuclidean;
+
+public class BigIntEuclideanTest
+ extends TestCase
+{
+ public void testCalculate()
+ {
+ BigIntEuclidean r = BigIntEuclidean.calculate(BigInteger.valueOf(120), BigInteger.valueOf(23));
+ assertEquals(BigInteger.valueOf(-9), r.x);
+ assertEquals(BigInteger.valueOf(47), r.y);
+ assertEquals(BigInteger.valueOf(1), r.gcd);
+
+ r = BigIntEuclidean.calculate(BigInteger.valueOf(126), BigInteger.valueOf(231));
+ assertEquals(BigInteger.valueOf(2), r.x);
+ assertEquals(BigInteger.valueOf(-1), r.y);
+ assertEquals(BigInteger.valueOf(21), r.gcd);
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/pqc/math/ntru/euclid/test/IntEuclideanTest.java b/core/src/test/java/org/spongycastle/pqc/math/ntru/euclid/test/IntEuclideanTest.java
new file mode 100644
index 00000000..9cfa62b0
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/math/ntru/euclid/test/IntEuclideanTest.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2011 Tim Buktu (tbuktu@hotmail.com)
+ *
+ * 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, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+package org.spongycastle.pqc.math.ntru.euclid.test;
+
+import junit.framework.TestCase;
+import org.spongycastle.pqc.math.ntru.euclid.IntEuclidean;
+
+public class IntEuclideanTest
+ extends TestCase
+{
+ public void testCalculate()
+ {
+ IntEuclidean r = IntEuclidean.calculate(120, 23);
+ assertEquals(-9, r.x);
+ assertEquals(47, r.y);
+ assertEquals(1, r.gcd);
+
+ r = IntEuclidean.calculate(126, 231);
+ assertEquals(2, r.x);
+ assertEquals(-1, r.y);
+ assertEquals(21, r.gcd);
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/AllTests.java b/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/AllTests.java
new file mode 100644
index 00000000..ce9c6d60
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/AllTests.java
@@ -0,0 +1,29 @@
+package org.spongycastle.pqc.math.ntru.polynomial.test;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class AllTests
+ extends TestCase
+{
+ public static void main (String[] args)
+ {
+ junit.textui.TestRunner.run(suite());
+ }
+
+ public static Test suite()
+ {
+ TestSuite suite = new TestSuite("NTRU Polynomial Tests");
+
+ suite.addTestSuite(BigDecimalPolynomialTest.class);
+ suite.addTestSuite(BigIntPolynomialTest.class);
+ suite.addTestSuite(IntegerPolynomialTest.class);
+ suite.addTestSuite(LongPolynomial2Test.class);
+ suite.addTestSuite(LongPolynomial5Test.class);
+ suite.addTestSuite(ProductFormPolynomialTest.class);
+ suite.addTestSuite(SparseTernaryPolynomialTest.class);
+
+ return suite;
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/BigDecimalPolynomialTest.java b/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/BigDecimalPolynomialTest.java
new file mode 100644
index 00000000..fdeb6855
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/BigDecimalPolynomialTest.java
@@ -0,0 +1,47 @@
+package org.spongycastle.pqc.math.ntru.polynomial.test;
+
+import java.math.BigDecimal;
+import java.security.SecureRandom;
+
+import junit.framework.TestCase;
+import org.spongycastle.pqc.math.ntru.polynomial.BigDecimalPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.BigIntPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
+
+public class BigDecimalPolynomialTest
+ extends TestCase
+{
+ public void testMult()
+ {
+ BigDecimalPolynomial a = new BigDecimalPolynomial(new BigIntPolynomial(new IntegerPolynomial(new int[]{4, -1, 9, 2, 1, -5, 12, -7, 0, -9, 5})));
+ BigDecimalPolynomial b = new BigDecimalPolynomial(new BigIntPolynomial(new IntegerPolynomial(new int[]{-6, 0, 0, 13, 3, -2, -4, 10, 11, 2, -1})));
+ BigDecimalPolynomial c = a.mult(b);
+ BigDecimal[] expectedCoeffs = new BigDecimalPolynomial(new BigIntPolynomial(new IntegerPolynomial(new int[]{2, -189, 77, 124, -29, 0, -75, 124, -49, 267, 34}))).getCoeffs();
+
+ BigDecimal[] cCoeffs = c.getCoeffs();
+
+ assertEquals(expectedCoeffs.length, cCoeffs.length);
+ for (int i = 0; i != cCoeffs.length; i++)
+ {
+ assertEquals(expectedCoeffs[i], cCoeffs[i]);
+ }
+
+ // multiply a polynomial by its inverse modulo 2048 and check that the result is 1
+ SecureRandom random = new SecureRandom();
+ IntegerPolynomial d, dInv;
+ do
+ {
+ d = DenseTernaryPolynomial.generateRandom(1001, 333, 334, random);
+ dInv = d.invertFq(2048);
+ }
+ while (dInv == null);
+
+ d.mod(2048);
+ BigDecimalPolynomial e = new BigDecimalPolynomial(new BigIntPolynomial(d));
+ BigIntPolynomial f = new BigIntPolynomial(dInv);
+ IntegerPolynomial g = new IntegerPolynomial(e.mult(f).round());
+ g.modPositive(2048);
+ assertTrue(g.equalsOne());
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/BigIntPolynomialTest.java b/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/BigIntPolynomialTest.java
new file mode 100644
index 00000000..334ece96
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/BigIntPolynomialTest.java
@@ -0,0 +1,26 @@
+package org.spongycastle.pqc.math.ntru.polynomial.test;
+
+import java.math.BigInteger;
+
+import junit.framework.TestCase;
+import org.spongycastle.pqc.math.ntru.polynomial.BigIntPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
+
+public class BigIntPolynomialTest
+ extends TestCase
+{
+ public void testMult()
+ {
+ BigIntPolynomial a = new BigIntPolynomial(new IntegerPolynomial(new int[]{4, -1, 9, 2, 1, -5, 12, -7, 0, -9, 5}));
+ BigIntPolynomial b = new BigIntPolynomial(new IntegerPolynomial(new int[]{-6, 0, 0, 13, 3, -2, -4, 10, 11, 2, -1}));
+ BigIntPolynomial c = a.mult(b);
+ BigInteger[] expectedCoeffs = new BigIntPolynomial(new IntegerPolynomial(new int[]{2, -189, 77, 124, -29, 0, -75, 124, -49, 267, 34})).getCoeffs();
+ BigInteger[] cCoeffs = c.getCoeffs();
+
+ assertEquals(expectedCoeffs.length, cCoeffs.length);
+ for (int i = 0; i != cCoeffs.length; i++)
+ {
+ assertEquals(expectedCoeffs[i], cCoeffs[i]);
+ }
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/IntegerPolynomialTest.java b/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/IntegerPolynomialTest.java
new file mode 100644
index 00000000..1c7fcabf
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/IntegerPolynomialTest.java
@@ -0,0 +1,230 @@
+package org.spongycastle.pqc.math.ntru.polynomial.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import junit.framework.TestCase;
+import org.spongycastle.pqc.crypto.ntru.NTRUSigningKeyGenerationParameters;
+import org.spongycastle.pqc.math.ntru.polynomial.BigIntPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.Resultant;
+import org.spongycastle.util.Arrays;
+
+
+public class IntegerPolynomialTest
+ extends TestCase
+{
+ public void testMult()
+ {
+ // multiplication modulo q
+ IntegerPolynomial a = new IntegerPolynomial(new int[]{-1, 1, 1, 0, -1, 0, 1, 0, 0, 1, -1});
+ IntegerPolynomial b = new IntegerPolynomial(new int[]{14, 11, 26, 24, 14, 16, 30, 7, 25, 6, 19});
+ IntegerPolynomial c = a.mult(b, 32);
+ assertEqualsMod(new int[]{3, -7, -10, -11, 10, 7, 6, 7, 5, -3, -7}, c.coeffs, 32);
+
+ a = new IntegerPolynomial(new int[]{15, 27, 18, 16, 12, 13, 16, 2, 28, 22, 26});
+ b = new IntegerPolynomial(new int[]{-1, 0, 1, 1, 0, 1, 0, 0, -1, 0, -1});
+ c = a.mult(b, 32);
+ assertEqualsMod(new int[]{8, 25, 22, 20, 12, 24, 15, 19, 12, 19, 16}, c.coeffs, 32);
+
+ // multiplication without a modulus
+ a = new IntegerPolynomial(new int[]{1, 1, 0, 0, -1, -1, 0, 0, -1, 0, 1});
+ b = new IntegerPolynomial(new int[]{704, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
+ c = a.mult(b);
+
+ // mult(p, modulus) should give the same result as mult(p) followed by modulus
+ a = new IntegerPolynomial(new int[]{1, 0, -1, 1, 0, 1, 1, 1, -1, 1, -1});
+ b = new IntegerPolynomial(new int[]{0, 1, 1, 0, 0, -1, -1, 1, 1, -1, 1});
+ c = a.mult(b);
+ c.modPositive(20);
+ IntegerPolynomial d = a.mult(b, 20);
+ d.modPositive(20);
+ assertTrue(Arrays.areEqual(c.coeffs, d.coeffs));
+ }
+
+ void assertEqualsMod(int[] arr1, int[] arr2, int m)
+ {
+ assertEquals(arr1.length, arr2.length);
+ for (int i = 0; i < arr1.length; i++)
+ {
+ assertEquals((arr1[i] + m) % m, (arr2[i] + m) % m);
+ }
+ }
+
+ public void testInvertFq()
+ {
+ SecureRandom random = new SecureRandom();
+ // Verify an example from the NTRU tutorial
+ IntegerPolynomial a = new IntegerPolynomial(new int[]{-1, 1, 1, 0, -1, 0, 1, 0, 0, 1, -1});
+ IntegerPolynomial b = a.invertFq(32);
+ assertEqualsMod(new int[]{5, 9, 6, 16, 4, 15, 16, 22, 20, 18, 30}, b.coeffs, 32);
+ verifyInverse(a, b, 32);
+
+ // test 3 random polynomials
+ int numInvertible = 0;
+ while (numInvertible < 3)
+ {
+ a = DenseTernaryPolynomial.generateRandom(853, random);
+ b = a.invertFq(2048);
+ if (b != null)
+ {
+ numInvertible++;
+ verifyInverse(a, b, 2048);
+ }
+ }
+
+ // test a non-invertible polynomial
+ a = new IntegerPolynomial(new int[]{-1, 0, 1, 1, 0, 0, -1, 0, -1, 0, 1});
+ b = a.invertFq(32);
+ assertNull(b);
+ }
+
+ public void testInvertF3()
+ {
+ IntegerPolynomial a = new IntegerPolynomial(new int[]{-1, 1, 1, 0, -1, 0, 1, 0, 0, 1, -1});
+ IntegerPolynomial b = a.invertF3();
+ assertEqualsMod(new int[]{1, 2, 0, 2, 2, 1, 0, 2, 1, 2, 0}, b.coeffs, 3);
+ verifyInverse(a, b, 3);
+
+ // test a non-invertible polynomial
+ a = new IntegerPolynomial(new int[]{0, 1, -1, 1, 0, 0, 0, 0, -1, 0, 0});
+ b = a.invertF3();
+ assertNull(b);
+ }
+
+ // tests if a*b=1 (mod modulus)
+ private void verifyInverse(IntegerPolynomial a, IntegerPolynomial b, int modulus)
+ {
+ IntegerPolynomial c = a.mult(b, modulus);
+ for (int i = 1; i < c.coeffs.length; i++)
+ {
+ c.coeffs[i] %= modulus;
+ }
+ c.ensurePositive(modulus);
+ assertTrue(c.equalsOne());
+ }
+
+ public void testFromToBinary()
+ {
+ byte[] a = new byte[]{-44, -33, 30, -109, 101, -28, -6, -105, -45, 113, -72, 99, 101, 15, 9, 49, -80, -76, 58, 42, -57, -113, -89, -14, -125, 24, 125, -16, 37, -58, 10, -49, -77, -31, 120, 103, -29, 105, -56, -126, -92, 36, 125, 127, -90, 38, 9, 4, 104, 10, -78, -106, -88, -1, -1, -43, -19, 90, 41, 0, -43, 102, 118, -72, -122, 19, -76, 57, -59, -2, 35, 47, 83, 114, 86, -115, -125, 58, 75, 115, -29, -6, 108, 6, -77, -51, 127, -8, -8, -58, -30, -126, 110, -5, -35, -41, -37, 69, 22, -48, 26, 4, -120, -19, -32, -81, -77, 124, -7, -2, -46, -96, 38, -35, 88, 4, -5, 16, 101, 29, 7, 2, 88, 35, -64, 31, -66, -70, 120, -97, 76, -74, -97, -61, 52, -56, 87, -35, 5, 95, -93, -30, 10, 38, 17, -102, -25, 86, 7, -43, 44, -52, -108, 33, -18, -110, -9, -115, 66, -71, 66, 1, -90, -72, 90, -88, -38, 75, 47, -124, -120, -15, -49, -8, 85, 5, 17, -88, 76, 99, -4, 83, 16, -91, 82, 116, 112, -83, 56, -45, -26, 125, 13, -75, -115, 92, -12, -59, 3, -12, 14, -6, 43, -17, 121, 122, 22, 92, -74, 99, -59, -103, 113, 8, -103, 114, 99, -48, 92, -88, 77, 81, 5, 31, -4, -69, -24, 23, 94, 126, 71, 93, 20, 77, 82, -54, -14, 86, 45, -81, 0, 52, -63, -66, 48, 104, -54, 15, -73, -2, -52, 115, 76, 28, -5, -94, -63, 117, -69, 0, 61, 22, -1, 71, -115, 9, -73, -100, -128, -31, 106, -74, -61, -37, 98, -6, 11, -5, 6, -18, -53, -6, 11, -49, 62, 23, 6, -128, 38, -91, 89, -34, 18, -38, -110, -101, 43, 36, 62, 101, 112, 59, -91, 78, -81, 61, 126, -21, -42, -110, -38, -27, 69, 57, 9, 24, -50, -118, 31, -17, 42, 87, -54, 122, -16, 42, -47, -19, -80, 16, 54, -97, -89, 81, -22, -35, 45, 54, -46, 22, -122, -95, -17, 7, -127, 105, -100, -56, -98, -105, 101, -81, 104, 121, -7, 33, 126, 110, -125, -85, 111, -52, 123, -98, 41, -42, 88, -68, -17, 39, -19, -96, -10, -117, 13, -88, -75, -101, -16, -7, 73, 23, -12, 41, -116, -105, -64, -4, 103, 49, -15, -49, 60, 88, -25, -21, 42, 26, 95, -90, -83, -69, 64, -2, 50, -116, -64, 26, -29, -93, -120, -70, 32, -38, 39, -126, -19, 103, 127, 65, 54, 110, 94, 126, -82, -80, -18, 43, 45, 56, -118, 109, 36, -8, 10, 113, 69, 53, -122, -127, 92, -127, -73, 70, -19, -105, -80, -15, -5, 99, -109, -27, 119, -76, -57, -48, 42, -35, 23, 39, -126, 44, -107, -100, -125, 117, -50, 115, -79, -16, 104, 8, -102, 83, -73, 21, -85, 113, -87, -54, 93, 63, -108, -64, 109, -74, 15, 14, -119, -6, -68, 45, 37, -15, -97, -95, -55, 89, 25, -63, -92, -80, -27, -8, 55, 50, 96, -91, 40, -74, 110, -96, 94, 6, 85, 92, 0, 34, -122, 5, -126, 123, 37, -90, -94, 60, 14, 36, 49, -98, -23, 57, 75, 63, 106, -7, -36, -89, 84, 71, 60, -21, 104, -47, 90, -52, -66, 88, -91, -81, -3, 116, 23, 62, -47, -84, -118, 65, 31, 7, -103, 37, -29, 115, -114, 73, 12, -121, 96, -91, -7, 56, 10, -72, 27, -45, 122, -27, -38, 74, 64, 30, -60, 64, -21, 48, 101, 113, 126, -60, -103, 71, 100, -117, 124, -125, 116, 78, 114, -74, 42, -81, -54, 34, 33, -10, 19, 23, 24, 40, 0, -8, 78, 100, 73, -88, -95, -62, -115, -18, 47, 10, -14, -39, 82, 27, -9, -115, -70, 92, -6, 39, 45, -71, -109, -41, 94, -88, -63, 19, -58, -37, -31, 1, 127, -42, 125, -120, -57, 120, -86, -6, 17, -27, -37, 47, 55, -22, -11, -31, 38, -1, 29, 56, -34, -104, -66, -62, 72, -11, -30, -30, 61, -31, 10, -63, 116, -84, 118, -127, 6, 17, -36, 91, 123, 77, 35, 22, 110, 114, 107, -3, 52, 11, 86, 68, -56, 0, 119, -43, -73, 112, 89, -4, -122, -71, -26, 103, -118, -61, -112, -108, -44, -25, -22, 4, 24, 53, -5, -71, 9, -41, 84, -28, 22, 99, 39, -26, -2, -51, 68, 63, -15, 99, 66, -78, 46, -89, 21, -38, -114, -51, 100, -59, 84, -76, -105, 51, 28, 19, 74, 42, 91, -73, 12, -89, -128, 34, 38, -100, 121, -78, 114, -28, 127, -29, 50, 105, -6, 36, 98, -35, 79, -58, 5, -13, -86, -101, -108, -99, -70, 25, 103, 63, 57, 79, -12, -63, 125, -54, 61, 15, 6, -79, 90, 76, 103, -45, 7, 39, 93, 107, 58, 76, 80, 56, -108, 55, -22, 36, 125, -91, -65, 11, 69, 10, -19, -14, -4, -26, -36, 114, 124, 63, -31, 88, 92, 108, 33, -52, -22, 80, -65, 57, 126, 43, -13, 122, -8, 68, 72, 92, -50, 100, -91, 1, -81, 75, 95, -11, -99, 38, 121, -20, -70, 82, -125, -94, -18, 16, 59, 89, 18, -96, 91, -97, 62, -96, 127, 45, 70, 16, 84, -43, -75, -118, 81, 58, 84, -115, -120, -3, 41, -103, -70, 123, 26, 101, 33, 58, 13, -11, -73, -84, -47, -7, 81, -63, 60, -45, 30, 100, -51, -15, 73, 58, -119, -3, 62, -63, -17, -69, -44, 60, -54, -115, -59, 23, -59, 98, -89, -72, 20, -96, 27, 53, -89, 59, -85, -29, 120, 23, 62, 8, -86, 113, 87, -15, 102, 106, -104, 57, -57, 37, 110, 118, 109, 25, 64, 26, -20, -86, -2, 60, -70, -33, 67, 13, -28, -29, -63, -37, 67, 99, 84, 121, -126, -38, 45, 24, 122, 51, 11, -19, -80, 26, -106, -95, 82, 69, -2, -75, 62, 106, -120, 87, -107, 87, 17, 102, -52, -16, 22, 12, -86, -48, -95, -61, 109, 64, -29, 111, 40, -90, -35, 49, 88, -15, 122, 127, 87, 113, 116, 93, 100, 28, -70, -87, -40, -1, -126, -114, 7, 79, 16, 2, -47, -98, -102, 49, 58, 61, -32, 44, 18, -26, 37, 27, -123, -76, 56, 91, 51, -21, -48, -122, -33, 40, -8, -62, -56, -126, 91, -51, 76, -29, 127, -22, -18, -110, 27, 13, -111, 81, 51, -104, 70, 98, 12, 120, -7, 15, 104, -43, -104, 124, 46, 116, 7, -26, 21, 33, 105, 17, -99, -42, -106, 8, -85, 39, 8, 79, -54, -81, 109, 40, 25, 29, -18, -90, 22, 85, -12, -16, 61, 49, -31, 127, 64, 5, 25, 39, -65, -42, 13, -97, -92, 36, -126, -18, -4, -22, -14, 109, -93, -76, -5, 13, 74, 44, 103, 79, 110, 85, 58, 39, -24, 119, 120, 122, 120, 43, 110, 67, 21, 47, 39, -48, 7, 91, -51, 126, 100, -38, -124, 0, -97, 99, -123, 118, -27, 8, 102, -106, -23, -53, -4, -56, -9, -126, -85, 93, -4, -5, 4, 49, 29, 2, 63, 78, -32, -106, 118, 111, 52, 54, 74, 53, 106, 39, -95, -38, -18, 118, -5, 94, -83, -97, -27, 62, -56, -90, -36, 43, 43, -113, 119, -89, 44, -108, -46, 66, 28, 66, -38, 3, -62, -83, -35, -127, -2, 51, 104, 105, 40, 76, -10, -124, -95, 52, 11, 101, -32, -122, -73, -17, 37, -126, 68, -126, 55, 112, -126, 38, 99, -63, 123, -74, -31, 58, 8, 93, -68, 111, -22, -24, -23, 9, -87, -25, -115, 81, -116, -91, 60, 96, -102, -1, -7, 73, 99, 46, -78, 62, 48, -116, -52, -44, -5, 82, -45, 5, -55, -101, 101, 65, -109, -108, 26, 98, -55, 11, -86, 57, 30, 92, -58, 20, 82, 65, 103, 27, -64, 76, 123, -56, -16, -111, -83, 125, 65, 111, 9, 123, 14, 119, 126, -80, 79, 94, -19, 66, -25, 35, 112, -64, 10, -66, -86, 51, 56, -78, 103, 92, -116, 8, 75, 41, -49, -79, -53, 125, -32, -76, -27, 59, -8, -4, -94, -104, -15, 79, -7, -124, 32, -87, -104, 85, -118, -36, 125, 65, 111, -105, 5, -105, 40, -50, 2, 118, 123, -54, 59, -22, 94, 20, 99, -87, -27, 28, -30, -109, 72, -19, 92, 60, 19, 115, 47, 96, -96, 10, -74, 60, 96, -86, 101, 101, 68, -44, -72, 9, -36, 126, 96, -45, -12, 9, 14, -15, 79, -79, -48, 8, -107, -81, 47, 35, -36, -107, -120, -36, -124, 37, 103, -60, -35, -74, 100, -38, -88, -99, -99, -94, -107, 79, 115, 108, 54, 119, 73, 84, 110, -74, 92, 57, 108, 80, 47, -36, -119, -115, 58, -62, -4, -97, 43, -98, 5, 112, 47, 59, -89, 82, -69, -103, 39, -29, 75, -9, -94, -72, 99, -64, 22, -10, 21, 89, 101, 21, 94, -30, -17, 73, -36, -68, -89, -91, -94, 99, -106, 119, -116, 123, -19, 54, -99, 64, -119, 82, 120, -106, -99, 80, 69, 29, -48, 77, 28, 13, 92, -107, -77, 94, -116, 108, 89, -115, 96, -41, 25, 99, -65, 118, -5, -16, 48, -122, 5, 50, -123, -115, 13, 24, 7, 15, -103, -62, -71, 92, -82, -5, -70, 49, -6, -51, -17, -47, 12, 46, -86, 30, 93, 84, -101, 43, -92, -87, -118, -110, -32, 52, 115, -4, 36, -2, -79, -69, -46, -110, 70, -82, 6, 21, -27, -11, 94, 42, -81, -96, 116, -102, -38, 36, 32, 91, 28, 80, -45, 116, -94, -33, -5, -102, 64, -96, 27, -2, 100, -126, 59, -71, 33, -36, -124, 123, 99, -76, 108, 127, -11, -24, -19, 84, -6, 19, 105, -19, -18, 120, -14, 23, 39, 54, 87, 105, 58, -95, -15, 127, -65, 114, 49, 4, -66, 32, -7, 84, 43, -103, 76, 11, 36, -68, -3, -98, -5, -43, 35, -48, 20, -40, -33, -123, 1, -54, -44, 99, -68, 8, -100, 97, -49, -10, 110, 49, 84, 46, -85, 98, -103, -58, -4, 104, -100, -40, -79, 67, -20, -95, 85, 51, 73, 10, -25, 102, 68, -97, -83, -39, 35, 2, -111, 71, 62, -89, 20, 25, -126, 17, -81, -29, 39, -27, -55, 55, -122, 97, 23, -99, 55, 86, 33, -9, 8, 55, -40, -84, 39, 38, 37, -29, 87, 113, -118, -26, 123, -95, 24, -126, 119, -94, 17, 83, -43, 10, 63, -98, 72, 8, 16, -95, -96, 119, -91, 6, 71, -60, 1, -77, 4, 53, -121, 55, 7, 36, -86, -49, -118, -121, 56, 84, -49, -57, -99, 3, -68, 37, -108, -72, 114, -74, 120, 3, 121, -28, -106, 54, -20, 63, -121, -85, -59, -111, 32, 13, -69, 122, 90, 5, 40, 88, 15, -90, 125, -28, 89, 95, 73, 96, 60, -60, -51, 102, 7, 57, 91, 59, 15, 92, -76, -34, -23, -77, 90, 45, 91, 77, -63, 94, -127, 74, -97, -44, 50, -87, -94, -25, -71, 112, 127, -117, 6, 32, -113, 54, 83, -31, 111, -73, 53, 34, -32, -98, 125, -39, 63, 15, 72, -69, 87, -118, 108, 17, 84, 15, 61, -47, 54, -24, -79, 91, 28, -28, 66, 53, 22, 9, -28, -12, 38, 64, 75, -122, 96, -59, -45, 4, -19, 47, -30, 75, -94, 62, -64, 76, -49, 19, -66, -34, 3, 84, -2, -54, 13, -84, 86, -117, 94, -27, 89, 16, 96, 52, -77, -36, -116, 27, -52, -33, -50, 14, -59, 77, 93, -109, 8, -89, 81, -114, -29, -94, 73, -119, -56, -19, 88, -17, -33, 125, -18, -68, 113, 40, -128, -112, -119, -106, -106, -30, 23, -77, 49, 3, 98, -101, 99, -107, -121, -12, -112, 24, -74, -74, 79, -17, 96, 65, -52, 86, -63, 45, 84, 119, -42, 61, -91, 29, -87, 65, -85, 99, -14, 71, 33, -41, -48, -2, -121, 78, -38, 41, -7, -37, 48, 122, 61, -124, 42, -22, 24, 2, -49, 74, -81, -88, -89, -107, 109, 53, -68, 90, -117, 123, -109, -28, 12, 80, 120, 26, -104, 73, 70, -36, 34, -80, -104, 23, 16, 14, -96, -5, 27, 71, 25, -8, -125, 58, 88, -52, -97, -97, -93, 11, -44, 116, 42, -102, -100, -31, -86, 71, 84, 70, 27, 117, -67, 92, -84, -13, 54, -102, 34, 5, 19, -76, 71, 89, 22, -49, -34, -29};
+ IntegerPolynomial poly = IntegerPolynomial.fromBinary(a, 1499, 2048);
+ byte[] b = poly.toBinary(2048);
+ // verify that bytes 0..2047 match, ignore non-relevant bits of byte 2048
+ assertTrue(Arrays.areEqual(copyOf(a, 2047), copyOf(b, 2047)));
+ assertEquals((a[a.length - 1] & 1) >> (7 - (1499 * 11) % 8), (b[b.length - 1] & 1) >> (7 - (1499 * 11) % 8));
+ }
+
+ public void testFromToBinary3Sves()
+ {
+ byte[] a = new byte[]{-112, -78, 19, 15, 99, -65, -56, -90, 44, -93, -109, 104, 40, 90, -84, -21, -124, 51, -33, 4, -51, -106, 33, 86, -76, 42, 41, -17, 47, 79, 81, -29, 15, 116, 101, 120, 116, 32, 116, 111, 32, 101, 110, 99, 114, 121, 112, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ IntegerPolynomial poly = IntegerPolynomial.fromBinary3Sves(a, 1499);
+ byte[] b = poly.toBinary3Sves();
+ assertTrue(Arrays.areEqual(a, b));
+ }
+
+ public void testFromToBinary3Tight()
+ {
+ int[] c = new int[]{0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 1, 0, 1, 0, -1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0};
+ IntegerPolynomial poly1 = new IntegerPolynomial(c);
+ IntegerPolynomial poly2 = IntegerPolynomial.fromBinary3Tight(poly1.toBinary3Tight(), c.length);
+ assertTrue(Arrays.areEqual(poly1.coeffs, poly2.coeffs));
+
+ IntegerPolynomial poly3 = new IntegerPolynomial(new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, -1, -1, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0});
+ byte[] arr = poly3.toBinary3Tight();
+ IntegerPolynomial poly4 = IntegerPolynomial.fromBinary3Tight(arr, 1499);
+ assertTrue(Arrays.areEqual(poly3.coeffs, poly4.coeffs));
+
+ IntegerPolynomial poly5 = new IntegerPolynomial(new int[]{0, 0, 0, 1, -1, -1, -1});
+ arr = poly5.toBinary3Tight();
+ IntegerPolynomial poly6 = IntegerPolynomial.fromBinary3Tight(arr, 7);
+ assertTrue(Arrays.areEqual(poly5.coeffs, poly6.coeffs));
+
+ SecureRandom random = new SecureRandom();
+
+ for (int i = 0; i < 100; i++)
+ {
+ IntegerPolynomial poly7 = DenseTernaryPolynomial.generateRandom(157, random);
+ arr = poly7.toBinary3Tight();
+ IntegerPolynomial poly8 = IntegerPolynomial.fromBinary3Tight(arr, 157);
+ assertTrue(Arrays.areEqual(poly7.coeffs, poly8.coeffs));
+ }
+ }
+
+ public void testResultant()
+ {
+ SecureRandom random = new SecureRandom();
+ NTRUSigningKeyGenerationParameters params = NTRUSigningKeyGenerationParameters.APR2011_439;
+ IntegerPolynomial a = DenseTernaryPolynomial.generateRandom(params.N, params.d, params.d, random);
+ verifyResultant(a, a.resultant());
+
+ a = new IntegerPolynomial(new int[]{0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 1, -1, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, -1, -1, 0, -1, 1, -1, 0, -1, 0, -1, -1, -1, 0, 0, 0, 1, 1, -1, -1, -1, 0, -1, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 1, 1, -1, 0, 1, -1, 0, 1, 0, 1, 0, -1, -1, 0, 1, 0, -1, 1, 1, 1, 1, 0, 0, -1, -1, 1, 0, 0, -1, -1, 0, -1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 1, 0, 1, -1, 0, 0, 1, 1, 1, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0, -1, -1, 0, -1, -1, -1, 0, -1, -1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, -1, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, -1, -1, 0, -1, -1, 1, 1, 0, 0, -1, 1, 0, 0, 0, -1, 1, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 1, 1, 0, 0, -1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, -1, 0, 1, 0, -1, -1, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 1, -1, 1, -1, -1, 1, -1, 0, 1, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, -1, 0, 1, -1, 0, 0, 1, 1, 0, 0, 1, 1, 0, -1, 0, -1, 1, -1, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 1, -1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, -1, -1, 0, 0, -1, 0, 1, 1, -1, 1, -1, 0, 0, 0, 1});
+ verifyResultant(a, a.resultant());
+ }
+
+ // verifies that res=rho*a mod x^n-1
+ private void verifyResultant(IntegerPolynomial a, Resultant r)
+ {
+ BigIntPolynomial b = new BigIntPolynomial(a).mult(r.rho);
+ BigInteger[] bCoeffs = b.getCoeffs();
+
+ for (int j = 1; j < bCoeffs.length - 1; j++)
+ {
+ assertEquals(BigInteger.ZERO, bCoeffs[j]);
+ }
+ if (r.res.equals(BigInteger.ZERO))
+ {
+ assertEquals(BigInteger.ZERO, bCoeffs[0].subtract(bCoeffs[bCoeffs.length - 1]));
+ }
+ else
+ {
+ assertEquals(BigInteger.ZERO, (bCoeffs[0].subtract(bCoeffs[bCoeffs.length - 1]).mod(r.res)));
+ }
+ assertEquals(bCoeffs[0].subtract(r.res), bCoeffs[bCoeffs.length - 1].negate());
+ }
+
+ public void testResultantMod()
+ {
+ int p = 46337; // prime; must be less than sqrt(2^31) or integer overflows will occur
+
+ IntegerPolynomial a = new IntegerPolynomial(new int[]{0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 1, -1, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, -1, -1, 0, -1, 1, -1, 0, -1, 0, -1, -1, -1, 0, 0, 0, 1, 1, -1, -1, -1, 0, -1, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 1, 1, -1, 0, 1, -1, 0, 1, 0, 1, 0, -1, -1, 0, 1, 0, -1, 1, 1, 1, 1, 0, 0, -1, -1, 1, 0, 0, -1, -1, 0, -1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 1, 0, 1, -1, 0, 0, 1, 1, 1, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0, -1, -1, 0, -1, -1, -1, 0, -1, -1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, -1, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, -1, -1, 0, -1, -1, 1, 1, 0, 0, -1, 1, 0, 0, 0, -1, 1, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 1, 1, 0, 0, -1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, -1, 0, 1, 0, -1, -1, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 1, -1, 1, -1, -1, 1, -1, 0, 1, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, -1, 0, 1, -1, 0, 0, 1, 1, 0, 0, 1, 1, 0, -1, 0, -1, 1, -1, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 1, -1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, -1, -1, 0, 0, -1, 0, 1, 1, -1, 1, -1, 0, 0, 0, 1});
+ verifyResultant(a, a.resultant(p), p);
+
+ SecureRandom random = new SecureRandom();
+
+ for (int i = 0; i < 10; i++)
+ {
+ a = DenseTernaryPolynomial.generateRandom(853, random);
+ verifyResultant(a, a.resultant(p), p);
+ }
+ }
+
+ // verifies that res=rho*a mod x^n-1 mod p
+ private void verifyResultant(IntegerPolynomial a, Resultant r, int p)
+ {
+ BigIntPolynomial b = new BigIntPolynomial(a).mult(r.rho);
+ b.mod(BigInteger.valueOf(p));
+ BigInteger[] bCoeffs = b.getCoeffs();
+
+ for (int j = 1; j < bCoeffs.length - 1; j++)
+ {
+ assertEquals(BigInteger.ZERO, bCoeffs[j]);
+ }
+ if (r.res.equals(BigInteger.ZERO))
+ {
+ assertEquals(BigInteger.ZERO, bCoeffs[0].subtract(bCoeffs[bCoeffs.length - 1]));
+ }
+ else
+ {
+ assertEquals(BigInteger.ZERO, (bCoeffs[0].subtract(bCoeffs[bCoeffs.length - 1]).subtract(r.res).mod(BigInteger.valueOf(p))));
+ }
+ assertEquals(BigInteger.ZERO, bCoeffs[0].subtract(r.res).subtract(bCoeffs[bCoeffs.length - 1].negate()).mod(BigInteger.valueOf(p)));
+ }
+
+ private byte[] copyOf(byte[] src, int length)
+ {
+ byte[] tmp = new byte[length];
+ System.arraycopy(src, 0, tmp, 0, tmp.length);
+ return tmp;
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/LongPolynomial2Test.java b/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/LongPolynomial2Test.java
new file mode 100644
index 00000000..cff9fa74
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/LongPolynomial2Test.java
@@ -0,0 +1,60 @@
+package org.spongycastle.pqc.math.ntru.polynomial.test;
+
+import java.util.Random;
+
+import junit.framework.TestCase;
+import org.spongycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.LongPolynomial2;
+import org.spongycastle.util.Arrays;
+
+public class LongPolynomial2Test
+ extends TestCase
+{
+ public void testMult()
+ {
+ IntegerPolynomial i1 = new IntegerPolynomial(new int[]{1368, 2047, 672, 871, 1662, 1352, 1099, 1608});
+ IntegerPolynomial i2 = new IntegerPolynomial(new int[]{1729, 1924, 806, 179, 1530, 1381, 1695, 60});
+ LongPolynomial2 a = new LongPolynomial2(i1);
+ LongPolynomial2 b = new LongPolynomial2(i2);
+ IntegerPolynomial c1 = i1.mult(i2, 2048);
+ IntegerPolynomial c2 = a.mult(b).toIntegerPolynomial();
+ assertTrue(Arrays.areEqual(c1.coeffs, c2.coeffs));
+
+ // test 10 random polynomials
+ Random rng = new Random();
+ for (int i = 0; i < 10; i++)
+ {
+ int N = 2 + rng.nextInt(2000);
+ i1 = PolynomialGenerator.generateRandom(N, 2048);
+ i2 = PolynomialGenerator.generateRandom(N, 2048);
+ a = new LongPolynomial2(i1);
+ b = new LongPolynomial2(i2);
+ c1 = i1.mult(i2);
+ c1.modPositive(2048);
+ c2 = a.mult(b).toIntegerPolynomial();
+ assertTrue(Arrays.areEqual(c1.coeffs, c2.coeffs));
+ }
+ }
+
+ public void testSubAnd()
+ {
+ IntegerPolynomial i1 = new IntegerPolynomial(new int[]{1368, 2047, 672, 871, 1662, 1352, 1099, 1608});
+ IntegerPolynomial i2 = new IntegerPolynomial(new int[]{1729, 1924, 806, 179, 1530, 1381, 1695, 60});
+ LongPolynomial2 a = new LongPolynomial2(i1);
+ LongPolynomial2 b = new LongPolynomial2(i2);
+ a.subAnd(b, 2047);
+ i1.sub(i2);
+ i1.modPositive(2048);
+ assertTrue(Arrays.areEqual(a.toIntegerPolynomial().coeffs, i1.coeffs));
+ }
+
+ public void testMult2And()
+ {
+ IntegerPolynomial i1 = new IntegerPolynomial(new int[]{1368, 2047, 672, 871, 1662, 1352, 1099, 1608});
+ LongPolynomial2 i2 = new LongPolynomial2(i1);
+ i2.mult2And(2047);
+ i1.mult(2);
+ i1.modPositive(2048);
+ assertTrue(Arrays.areEqual(i1.coeffs, i2.toIntegerPolynomial().coeffs));
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/LongPolynomial5Test.java b/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/LongPolynomial5Test.java
new file mode 100644
index 00000000..a5e65341
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/LongPolynomial5Test.java
@@ -0,0 +1,62 @@
+package org.spongycastle.pqc.math.ntru.polynomial.test;
+
+import java.security.SecureRandom;
+
+import junit.framework.TestCase;
+import org.spongycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.LongPolynomial5;
+import org.spongycastle.util.Arrays;
+
+public class LongPolynomial5Test
+ extends TestCase
+{
+ public void testMult()
+ {
+ testMult(new int[]{2}, new int[]{-1});
+ testMult(new int[]{2, 0}, new int[]{-1, 0});
+ testMult(new int[]{2, 0, 3}, new int[]{-1, 0, 1});
+ testMult(new int[]{2, 0, 3, 1}, new int[]{-1, 0, 1, 1});
+ testMult(new int[]{2, 0, 3, 1, 2}, new int[]{-1, 0, 1, 1, 0});
+ testMult(new int[]{2, 0, 3, 1, 1, 5}, new int[]{1, -1, 1, 1, 0, 1});
+ testMult(new int[]{2, 0, 3, 1, 1, 5, 1, 4}, new int[]{1, 0, 1, 1, -1, 1, 0, -1});
+ testMult(new int[]{1368, 2047, 672, 871, 1662, 1352, 1099, 1608}, new int[]{1, 0, 1, 1, -1, 1, 0, -1});
+
+ // test random polynomials
+ SecureRandom rng = new SecureRandom();
+ for (int i = 0; i < 10; i++)
+ {
+ int[] coeffs1 = new int[rng.nextInt(2000) + 1];
+ int[] coeffs2 = DenseTernaryPolynomial.generateRandom(coeffs1.length, rng).coeffs;
+ testMult(coeffs1, coeffs2);
+ }
+ }
+
+ private void testMult(int[] coeffs1, int[] coeffs2)
+ {
+ IntegerPolynomial i1 = new IntegerPolynomial(coeffs1);
+ IntegerPolynomial i2 = new IntegerPolynomial(coeffs2);
+
+ LongPolynomial5 a = new LongPolynomial5(i1);
+ DenseTernaryPolynomial b = new DenseTernaryPolynomial(i2);
+ IntegerPolynomial c1 = i1.mult(i2, 2048);
+ IntegerPolynomial c2 = a.mult(b).toIntegerPolynomial();
+ assertEqualsMod(c1.coeffs, c2.coeffs, 2048);
+ }
+
+ private void assertEqualsMod(int[] arr1, int[] arr2, int m)
+ {
+ assertEquals(arr1.length, arr2.length);
+ for (int i = 0; i < arr1.length; i++)
+ {
+ assertEquals((arr1[i] + m) % m, (arr2[i] + m) % m);
+ }
+ }
+
+ public void testToIntegerPolynomial()
+ {
+ int[] coeffs = new int[]{2, 0, 3, 1, 1, 5, 1, 4};
+ LongPolynomial5 p = new LongPolynomial5(new IntegerPolynomial(coeffs));
+ assertTrue(Arrays.areEqual(coeffs, p.toIntegerPolynomial().coeffs));
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/PolynomialGenerator.java b/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/PolynomialGenerator.java
new file mode 100644
index 00000000..a30fea4d
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/PolynomialGenerator.java
@@ -0,0 +1,27 @@
+package org.spongycastle.pqc.math.ntru.polynomial.test;
+
+import java.util.Random;
+
+import org.spongycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
+
+public class PolynomialGenerator
+{
+ /**
+ * Creates a random polynomial with <code>N</code> coefficients
+ * between <code>0</code> and <code>q-1</code>.
+ *
+ * @param N length of the polynomial
+ * @param q coefficients will all be below this number
+ * @return a random polynomial
+ */
+ public static IntegerPolynomial generateRandom(int N, int q)
+ {
+ Random rng = new Random();
+ int[] coeffs = new int[N];
+ for (int i = 0; i < N; i++)
+ {
+ coeffs[i] = rng.nextInt(q);
+ }
+ return new IntegerPolynomial(coeffs);
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/ProductFormPolynomialTest.java b/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/ProductFormPolynomialTest.java
new file mode 100644
index 00000000..96506ed4
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/ProductFormPolynomialTest.java
@@ -0,0 +1,47 @@
+package org.spongycastle.pqc.math.ntru.polynomial.test;
+
+import java.security.SecureRandom;
+
+import junit.framework.TestCase;
+import org.spongycastle.pqc.crypto.ntru.NTRUEncryptionKeyGenerationParameters;
+import org.spongycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.ProductFormPolynomial;
+
+public class ProductFormPolynomialTest
+ extends TestCase
+{
+ private NTRUEncryptionKeyGenerationParameters params;
+ private int N;
+ private int df1;
+ private int df2;
+ private int df3;
+ private int q;
+
+ public void setUp()
+ {
+ params = NTRUEncryptionKeyGenerationParameters.APR2011_439_FAST;
+ N = params.N;
+ df1 = params.df1;
+ df2 = params.df2;
+ df3 = params.df3;
+ q = params.q;
+ }
+
+ public void testFromToBinary()
+ throws Exception
+ {
+ ProductFormPolynomial p1 = ProductFormPolynomial.generateRandom(N, df1, df2, df3, df3 - 1, new SecureRandom());
+ byte[] bin1 = p1.toBinary();
+ ProductFormPolynomial p2 = ProductFormPolynomial.fromBinary(bin1, N, df1, df2, df3, df3 - 1);
+ assertEquals(p1, p2);
+ }
+
+ public void testMult()
+ {
+ ProductFormPolynomial p1 = ProductFormPolynomial.generateRandom(N, df1, df2, df3, df3 - 1, new SecureRandom());
+ IntegerPolynomial p2 = PolynomialGenerator.generateRandom(N, q);
+ IntegerPolynomial p3 = p1.mult(p2);
+ IntegerPolynomial p4 = p1.toIntegerPolynomial().mult(p2);
+ assertEquals(p3, p4);
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/SparseTernaryPolynomialTest.java b/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/SparseTernaryPolynomialTest.java
new file mode 100644
index 00000000..a4d9ce7e
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/math/ntru/polynomial/test/SparseTernaryPolynomialTest.java
@@ -0,0 +1,45 @@
+package org.spongycastle.pqc.math.ntru.polynomial.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.security.SecureRandom;
+
+import junit.framework.TestCase;
+import org.spongycastle.pqc.math.ntru.polynomial.BigIntPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial;
+
+public class SparseTernaryPolynomialTest
+ extends TestCase
+{
+
+ /**
+ * tests mult(IntegerPolynomial) and mult(BigIntPolynomial)
+ */
+ public void testMult()
+ {
+ SecureRandom random = new SecureRandom();
+ SparseTernaryPolynomial p1 = SparseTernaryPolynomial.generateRandom(1000, 500, 500, random);
+ IntegerPolynomial p2 = DenseTernaryPolynomial.generateRandom(1000, random);
+
+ IntegerPolynomial prod1 = p1.mult(p2);
+ IntegerPolynomial prod2 = p1.mult(p2);
+ assertEquals(prod1, prod2);
+
+ BigIntPolynomial p3 = new BigIntPolynomial(p2);
+ BigIntPolynomial prod3 = p1.mult(p3);
+
+ assertEquals(new BigIntPolynomial(prod1), prod3);
+ }
+
+ public void testFromToBinary()
+ throws IOException
+ {
+ SecureRandom random = new SecureRandom();
+ SparseTernaryPolynomial poly1 = SparseTernaryPolynomial.generateRandom(1000, 100, 101, random);
+ ByteArrayInputStream poly1Stream = new ByteArrayInputStream(poly1.toBinary());
+ SparseTernaryPolynomial poly2 = SparseTernaryPolynomial.fromBinary(poly1Stream, 1000, 100, 101);
+ assertEquals(poly1, poly2);
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/pqc/math/ntru/util/test/AllTests.java b/core/src/test/java/org/spongycastle/pqc/math/ntru/util/test/AllTests.java
new file mode 100644
index 00000000..ff675a73
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/math/ntru/util/test/AllTests.java
@@ -0,0 +1,23 @@
+package org.spongycastle.pqc.math.ntru.util.test;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class AllTests
+ extends TestCase
+{
+ public static void main (String[] args)
+ {
+ junit.textui.TestRunner.run(suite());
+ }
+
+ public static Test suite()
+ {
+ TestSuite suite = new TestSuite("NTRU ArrayEncoder Tests");
+
+ suite.addTestSuite(ArrayEncoderTest.class);
+
+ return suite;
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/pqc/math/ntru/util/test/ArrayEncoderTest.java b/core/src/test/java/org/spongycastle/pqc/math/ntru/util/test/ArrayEncoderTest.java
new file mode 100644
index 00000000..ebd96d1c
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/pqc/math/ntru/util/test/ArrayEncoderTest.java
@@ -0,0 +1,42 @@
+package org.spongycastle.pqc.math.ntru.util.test;
+
+import java.security.SecureRandom;
+import java.util.Random;
+
+import junit.framework.TestCase;
+import org.spongycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
+import org.spongycastle.pqc.math.ntru.polynomial.test.PolynomialGenerator;
+import org.spongycastle.pqc.math.ntru.util.ArrayEncoder;
+import org.spongycastle.util.Arrays;
+
+public class ArrayEncoderTest
+ extends TestCase
+{
+ public void testEncodeDecodeModQ()
+ {
+ int[] coeffs = PolynomialGenerator.generateRandom(1000, 2048).coeffs;
+ byte[] data = ArrayEncoder.encodeModQ(coeffs, 2048);
+ int[] coeffs2 = ArrayEncoder.decodeModQ(data, 1000, 2048);
+ assertTrue(Arrays.areEqual(coeffs, coeffs2));
+ }
+
+ public void testEncodeDecodeMod3Sves()
+ {
+ Random rng = new Random();
+ byte[] data = new byte[180];
+ rng.nextBytes(data);
+ int[] coeffs = ArrayEncoder.decodeMod3Sves(data, 960);
+ byte[] data2 = ArrayEncoder.encodeMod3Sves(coeffs);
+ assertTrue(Arrays.areEqual(data, data2));
+ }
+
+ public void testEncodeDecodeMod3Tight()
+ {
+ SecureRandom random = new SecureRandom();
+
+ int[] coeffs = DenseTernaryPolynomial.generateRandom(1000, random).coeffs;
+ byte[] data = ArrayEncoder.encodeMod3Tight(coeffs);
+ int[] coeffs2 = ArrayEncoder.decodeMod3Tight(data, 1000);
+ assertTrue(Arrays.areEqual(coeffs, coeffs2));
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/util/encoders/test/AbstractCoderTest.java b/core/src/test/java/org/spongycastle/util/encoders/test/AbstractCoderTest.java
new file mode 100644
index 00000000..03f0bf77
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/util/encoders/test/AbstractCoderTest.java
@@ -0,0 +1,211 @@
+package org.spongycastle.util.encoders.test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Random;
+
+import junit.framework.TestCase;
+
+import org.spongycastle.util.encoders.Encoder;
+
+public abstract class AbstractCoderTest extends TestCase
+{
+
+ private static final int[] SIZES_TO_CHECK = {64, 128, 1024, 1025, 1026, 2048,
+ 2049, 2050, 4096, 4097, 4098, 8192, 8193, 8194};
+
+ protected Encoder enc;
+ private Random r;
+
+ AbstractCoderTest(
+ String name)
+ {
+ super(name);
+ }
+
+ protected void setUp()
+ {
+ r = new Random();
+ }
+
+ private void checkArrayOfSize(int size)
+ throws IOException
+ {
+ byte[] original = new byte[size];
+ r.nextBytes(original);
+
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ enc.encode(original, 0, original.length, bOut);
+
+ byte[] encoded = bOut.toByteArray();
+
+ assertTrue(encoded.length > original.length);
+ assertTrue(encoded.length <= (original.length * 2));
+ checkEncoding(encoded);
+ checkSimpleDecode(original, encoded);
+ checkStringDecode(original, encoded);
+ checkOutputStreamDecode(original, encoded);
+
+ int offset = r.nextInt(20);
+ byte[] offsetEncoded = new byte[offset + encoded.length];
+ System.arraycopy(encoded, 0, offsetEncoded, offset, encoded.length);
+ checkOffsetDecode(original, offsetEncoded, offset, encoded.length);
+
+ offset = r.nextInt(20);
+ byte[] offsetOriginal = new byte[offset + original.length];
+ System.arraycopy(original, 0, offsetOriginal, offset, original.length);
+ checkOffsetEncode(original, offsetOriginal, offset, original.length);
+
+ byte[] encodedWithSpace = addWhitespace(encoded);
+ checkSimpleDecode(original, encodedWithSpace);
+ checkStringDecode(original, encodedWithSpace);
+ checkOutputStreamDecode(original, encodedWithSpace);
+ }
+
+ public void testEncode()
+ throws IOException
+ {
+ for (int i = 0; i < SIZES_TO_CHECK.length; i++)
+ {
+ checkArrayOfSize(SIZES_TO_CHECK[i]);
+ }
+ }
+
+ private void checkEncoding(byte[] encoded)
+ {
+ String encString = convertBytesToString(encoded);
+ for (int i = 0; i < encString.length(); i++)
+ {
+ char c = encString.charAt(i);
+ if (c == paddingChar())
+ {
+ // should only be padding at end of string
+ assertTrue(i > encString.length() - 3);
+ continue;
+ }
+ else if (isEncodedChar(c))
+ {
+ continue;
+ }
+ fail("Unexpected encoded character " + c);
+ }
+ }
+
+ private void checkOutputStreamDecode(byte[] original, byte[] encoded)
+ {
+ String encString = convertBytesToString(encoded);
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ try
+ {
+ assertEquals(original.length, enc.decode(encString, out));
+ assertTrue(Arrays.equals(original, out.toByteArray()));
+ }
+ catch (IOException e)
+ {
+ fail("This shouldn't happen");
+ }
+ }
+
+ private void checkSimpleDecode(byte[] original, byte[] encoded)
+ throws IOException
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ enc.decode(encoded, 0, encoded.length, bOut);
+
+ assertTrue(Arrays.equals(original, bOut.toByteArray()));
+ }
+
+ private void checkOffsetEncode(byte[] original, byte[] offsetOriginal, int off, int length)
+ throws IOException
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ enc.encode(offsetOriginal, off, length, bOut);
+
+ byte[] encoded = bOut.toByteArray();
+
+ bOut.reset();
+
+ enc.decode(encoded, 0, encoded.length, bOut);
+
+ assertTrue(Arrays.equals(original, bOut.toByteArray()));
+ }
+
+ private void checkOffsetDecode(byte[] original, byte[] encoded, int off, int length)
+ throws IOException
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ enc.decode(encoded, off, length, bOut);
+
+ assertTrue(Arrays.equals(original, bOut.toByteArray()));
+ }
+
+ private void checkStringDecode(byte[] original, byte[] encoded)
+ throws IOException
+ {
+ String encString = convertBytesToString(encoded);
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ enc.decode(encString, bOut);
+ assertTrue(Arrays.equals(original, bOut.toByteArray()));
+ }
+
+ private byte[] addWhitespace(byte[] encoded)
+ {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ addSpace(out);
+ for (int i = 0; i < encoded.length - 5; i++)
+ {
+ out.write(encoded, i, 1);
+ if (r.nextInt(100) < 5)
+ {
+ addSpace(out);
+ }
+ }
+ for (int i = encoded.length - 5; i < encoded.length; i++)
+ {
+ out.write(encoded, i, 1);
+ }
+ addSpace(out);
+ return out.toByteArray();
+ }
+
+ private void addSpace(ByteArrayOutputStream out)
+ {
+ do
+ {
+ switch (r.nextInt(3))
+ {
+ case 0 :
+ out.write((int) '\n');
+ break;
+ case 1 :
+ out.write((int) '\r');
+ break;
+ case 2 :
+ out.write((int) '\t');
+ break;
+ case 3 :
+ out.write((int) ' ');
+ break;
+ }
+ } while (r.nextBoolean());
+ }
+
+ private String convertBytesToString(byte[] encoded)
+ {
+ StringBuffer b = new StringBuffer();
+
+ for (int i = 0; i != encoded.length; i++)
+ {
+ b.append((char)(encoded[i] & 0xff));
+ }
+
+ return b.toString();
+ }
+
+ abstract protected char paddingChar();
+
+ abstract protected boolean isEncodedChar(char c);
+
+}
diff --git a/core/src/test/java/org/spongycastle/util/encoders/test/AllTests.java b/core/src/test/java/org/spongycastle/util/encoders/test/AllTests.java
new file mode 100644
index 00000000..a31c5ad2
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/util/encoders/test/AllTests.java
@@ -0,0 +1,20 @@
+package org.spongycastle.util.encoders.test;
+
+import junit.framework.*;
+
+public class AllTests
+{
+ public static void main (String[] args)
+ {
+ junit.textui.TestRunner.run (suite());
+ }
+
+ public static Test suite()
+ {
+ TestSuite suite = new TestSuite("encoder tests");
+ suite.addTestSuite(Base64Test.class);
+ suite.addTestSuite(UrlBase64Test.class);
+ suite.addTestSuite(HexTest.class);
+ return suite;
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/util/encoders/test/Base64Test.java b/core/src/test/java/org/spongycastle/util/encoders/test/Base64Test.java
new file mode 100644
index 00000000..f74f7eed
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/util/encoders/test/Base64Test.java
@@ -0,0 +1,121 @@
+package org.spongycastle.util.encoders.test;
+
+import java.io.IOException;
+
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Strings;
+import org.spongycastle.util.encoders.Base64;
+import org.spongycastle.util.encoders.Base64Encoder;
+import org.spongycastle.util.encoders.DecoderException;
+import org.spongycastle.util.encoders.Hex;
+
+public class Base64Test extends AbstractCoderTest
+{
+ private static final String sample1 = "mO4TyLWG7vjFWdKT8IJcVbZ/jwc=";
+ private static final byte[] sample1Bytes = Hex.decode("98ee13c8b586eef8c559d293f0825c55b67f8f07");
+ private static final String sample2 = "F4I4p8Vf/mS+Kxvri3FPoMcqmJ1f";
+ private static final byte[] sample2Bytes = Hex.decode("178238a7c55ffe64be2b1beb8b714fa0c72a989d5f");
+ private static final String sample3 = "UJmEdJYodqHJmd7Rtv6/OP29/jUEFw==";
+ private static final byte[] sample3Bytes = Hex.decode("50998474962876a1c999ded1b6febf38fdbdfe350417");
+
+ private static final String invalid1 = "%O4TyLWG7vjFWdKT8IJcVbZ/jwc=";
+ private static final String invalid2 = "F%I4p8Vf/mS+Kxvri3FPoMcqmJ1f";
+ private static final String invalid3 = "UJ%EdJYodqHJmd7Rtv6/OP29/jUEFw==";
+ private static final String invalid4 = "mO4%yLWG7vjFWdKT8IJcVbZ/jwc=";
+ private static final String invalid5 = "UJmEdJYodqHJmd7Rtv6/OP29/jUEF%==";
+ private static final String invalid6 = "mO4TyLWG7vjFWdKT8IJcVbZ/jw%=";
+ private static final String invalid7 = "F4I4p8Vf/mS+Kxvri3FPoMcqmJ1%";
+ private static final String invalid8 = "UJmEdJYodqHJmd7Rtv6/OP29/jUE%c==";
+ private static final String invalid9 = "mO4TyLWG7vjFWdKT8IJcVbZ/j%c=";
+ private static final String invalida = "F4I4p8Vf/mS+Kxvri3FPoMcqmJ%1";
+ private static final String invalidb = "UJmEdJYodqHJmd7Rtv6/OP29/jU%Fc==";
+ private static final String invalidc = "mO4TyLWG7vjFWdKT8IJcVbZ/%wc=";
+ private static final String invalidd = "F4I4p8Vf/mS+Kxvri3FPoMcqm%1c";
+
+
+ public Base64Test(
+ String name)
+ {
+ super(name);
+ }
+
+ protected void setUp()
+ {
+ super.setUp();
+ enc = new Base64Encoder();
+ }
+
+ public void testSamples()
+ throws IOException
+ {
+ assertTrue(Arrays.areEqual(sample1Bytes, Base64.decode(sample1)));
+ assertTrue(Arrays.areEqual(sample1Bytes, Base64.decode(Strings.toByteArray(sample1))));
+ assertTrue(Arrays.areEqual(sample2Bytes, Base64.decode(sample2)));
+ assertTrue(Arrays.areEqual(sample2Bytes, Base64.decode(Strings.toByteArray(sample2))));
+ assertTrue(Arrays.areEqual(sample3Bytes, Base64.decode(sample3)));
+ assertTrue(Arrays.areEqual(sample3Bytes, Base64.decode(Strings.toByteArray(sample3))));
+ }
+
+ public void testInvalidInput()
+ throws IOException
+ {
+ String[] invalid = new String[] { invalid1, invalid2, invalid3, invalid4, invalid5, invalid6, invalid7, invalid8, invalid9, invalida, invalidb, invalidc, invalidd };
+
+ for (int i = 0; i != invalid.length; i++)
+ {
+ invalidTest(invalid[i]);
+ invalidTest(Strings.toByteArray(invalid[i]));
+ }
+ }
+
+ private void invalidTest(String data)
+ {
+ try
+ {
+ Base64.decode(data);
+ }
+ catch (DecoderException e)
+ {
+ return;
+ }
+
+ fail("invalid String data parsed");
+ }
+
+ private void invalidTest(byte[] data)
+ {
+ try
+ {
+ Base64.decode(data);
+ }
+ catch (DecoderException e)
+ {
+ return;
+ }
+
+ fail("invalid byte data parsed");
+ }
+
+ protected char paddingChar()
+ {
+ return '=';
+ }
+
+ protected boolean isEncodedChar(char c)
+ {
+ if (Character.isLetterOrDigit(c))
+ {
+ return true;
+ }
+ else if (c == '+')
+ {
+ return true;
+ }
+ else if (c == '/')
+ {
+ return true;
+ }
+ return false;
+ }
+
+}
diff --git a/core/src/test/java/org/spongycastle/util/encoders/test/EncoderTest.java b/core/src/test/java/org/spongycastle/util/encoders/test/EncoderTest.java
new file mode 100644
index 00000000..4e0e79c2
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/util/encoders/test/EncoderTest.java
@@ -0,0 +1,250 @@
+package org.spongycastle.util.encoders.test;
+
+import java.util.Arrays;
+import java.util.Random;
+
+import org.spongycastle.util.encoders.Base64;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.SimpleTest;
+
+public class EncoderTest
+ extends SimpleTest
+{
+ public static final boolean DEBUG = true;
+
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new EncoderTest());
+ }
+
+ public String getName()
+ {
+ return "Encoder";
+ }
+
+ /*
+ *
+ * TESTS
+ *
+ */
+
+ public void performTest()
+ {
+ testHex();
+ testBase64();
+ testBase64WithNL();
+ }
+
+
+ public void testBase64()
+ {
+ try
+ {
+ Random _r = new Random();
+
+ byte[] _orig1024 = new byte[1024];
+ _r.nextBytes(_orig1024);
+
+ byte[] _orig2048 = new byte[2048];
+ _r.nextBytes(_orig2048);
+
+ byte[] _orig4096 = new byte[4096];
+ _r.nextBytes(_orig4096);
+
+ byte[] _orig8192 = new byte[8192];
+ _r.nextBytes(_orig8192);
+
+ byte[] _enc1024 = Base64.encode(_orig1024);
+ byte[] _enc2048 = Base64.encode(_orig2048);
+ byte[] _enc4096 = Base64.encode(_orig4096);
+ byte[] _enc8192 = Base64.encode(_orig8192);
+
+ byte[] _dec1024 = Base64.decode(_enc1024);
+ byte[] _dec2048 = Base64.decode(_enc2048);
+ byte[] _dec4096 = Base64.decode(_enc4096);
+ byte[] _dec8192 = Base64.decode(_enc8192);
+
+ if(!Arrays.equals(_orig1024, _dec1024))
+ {
+ fail("Failed Base64 test");
+ }
+
+ if(!Arrays.equals(_orig2048, _dec2048))
+ {
+ fail("Failed Base64 test");
+ }
+
+ if(!Arrays.equals(_orig4096, _dec4096))
+ {
+ fail("Failed Base64 test");
+ }
+
+ if(!Arrays.equals(_orig8192, _dec8192))
+ {
+ fail("Failed Base64 test");
+ }
+
+
+
+ byte[] _orig1025 = new byte[1025];
+ _r.nextBytes(_orig1025);
+
+ byte[] _orig2049 = new byte[2049];
+ _r.nextBytes(_orig2049);
+
+ byte[] _orig4097 = new byte[4097];
+ _r.nextBytes(_orig4097);
+
+ byte[] _orig8193 = new byte[8193];
+ _r.nextBytes(_orig8193);
+
+ byte[] _enc1025 = Base64.encode(_orig1025);
+ byte[] _enc2049 = Base64.encode(_orig2049);
+ byte[] _enc4097 = Base64.encode(_orig4097);
+ byte[] _enc8193 = Base64.encode(_orig8193);
+
+ byte[] _dec1025 = Base64.decode(_enc1025);
+ byte[] _dec2049 = Base64.decode(_enc2049);
+ byte[] _dec4097 = Base64.decode(_enc4097);
+ byte[] _dec8193 = Base64.decode(_enc8193);
+
+ if(!Arrays.equals(_orig1025, _dec1025))
+ {
+ fail("Failed Base64 test");
+ }
+
+ if(!Arrays.equals(_orig2049, _dec2049))
+ {
+ fail("Failed Base64 test");
+ }
+
+ if(!Arrays.equals(_orig4097, _dec4097))
+ {
+ fail("Failed Base64 test");
+ }
+
+ if(!Arrays.equals(_orig8193, _dec8193))
+ {
+ fail("Failed Base64 test");
+ }
+ }
+ catch(Exception ex)
+ {
+ fail("Failed Base64 test");
+ }
+ }
+
+ public void testBase64WithNL()
+ {
+ byte[] dec = Base64.decode("SVNC" + "\n" + "QUQ=\n");
+
+ if (dec.length != 5)
+ {
+ fail("got length " + dec.length + " when expecting 10");
+ }
+
+ if (!areEqual(dec, Base64.decode("SVNCQUQ=")))
+ {
+ fail("decodings are not equal");
+ }
+ }
+
+ public void testHex()
+ {
+ try
+ {
+ Random _r = new Random();
+
+ byte[] _orig1024 = new byte[1024];
+ _r.nextBytes(_orig1024);
+
+ byte[] _orig2048 = new byte[2048];
+ _r.nextBytes(_orig2048);
+
+ byte[] _orig4096 = new byte[4096];
+ _r.nextBytes(_orig4096);
+
+ byte[] _orig8192 = new byte[8192];
+ _r.nextBytes(_orig8192);
+
+ byte[] _enc1024 = Hex.encode(_orig1024);
+ byte[] _enc2048 = Hex.encode(_orig2048);
+ byte[] _enc4096 = Hex.encode(_orig4096);
+ byte[] _enc8192 = Hex.encode(_orig8192);
+
+ byte[] _dec1024 = Hex.decode(_enc1024);
+ byte[] _dec2048 = Hex.decode(_enc2048);
+ byte[] _dec4096 = Hex.decode(_enc4096);
+ byte[] _dec8192 = Hex.decode(_enc8192);
+
+ if(!Arrays.equals(_orig1024, _dec1024))
+ {
+ fail("Failed Hex test");
+ }
+
+ if(!Arrays.equals(_orig2048, _dec2048))
+ {
+ fail("Failed Hex test");
+ }
+
+ if(!Arrays.equals(_orig4096, _dec4096))
+ {
+ fail("Failed Hex test");
+ }
+
+ if(!Arrays.equals(_orig8192, _dec8192))
+ {
+ fail("Failed Hex test");
+ }
+
+
+ byte[] _orig1025 = new byte[1025];
+ _r.nextBytes(_orig1025);
+
+ byte[] _orig2049 = new byte[2049];
+ _r.nextBytes(_orig2049);
+
+ byte[] _orig4097 = new byte[4097];
+ _r.nextBytes(_orig4097);
+
+ byte[] _orig8193 = new byte[8193];
+ _r.nextBytes(_orig8193);
+
+ byte[] _enc1025 = Hex.encode(_orig1025);
+ byte[] _enc2049 = Hex.encode(_orig2049);
+ byte[] _enc4097 = Hex.encode(_orig4097);
+ byte[] _enc8193 = Hex.encode(_orig8193);
+
+ byte[] _dec1025 = Hex.decode(_enc1025);
+ byte[] _dec2049 = Hex.decode(_enc2049);
+ byte[] _dec4097 = Hex.decode(_enc4097);
+ byte[] _dec8193 = Hex.decode(_enc8193);
+
+ if(!Arrays.equals(_orig1025, _dec1025))
+ {
+ fail("Failed Hex test");
+ }
+
+ if(!Arrays.equals(_orig2049, _dec2049))
+ {
+ fail("Failed Hex test");
+ }
+
+ if(!Arrays.equals(_orig4097, _dec4097))
+ {
+ fail("Failed Hex test");
+ }
+
+ if(!Arrays.equals(_orig8193, _dec8193))
+ {
+ fail("Failed Hex test");
+ }
+ }
+ catch(Exception ex)
+ {
+ fail("Failed Hex test");
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/util/encoders/test/HexTest.java b/core/src/test/java/org/spongycastle/util/encoders/test/HexTest.java
new file mode 100644
index 00000000..a0c101bc
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/util/encoders/test/HexTest.java
@@ -0,0 +1,92 @@
+package org.spongycastle.util.encoders.test;
+
+import java.io.IOException;
+
+import org.spongycastle.util.Strings;
+import org.spongycastle.util.encoders.DecoderException;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.encoders.HexEncoder;
+
+public class HexTest extends AbstractCoderTest
+{
+ private static final String invalid1 = "%O4T";
+ private static final String invalid2 = "FZI4";
+ private static final String invalid3 = "ae%E";
+ private static final String invalid4 = "fO4%";
+ private static final String invalid5 = "beefe";
+ private static final String invalid6 = "beefs";
+
+ public HexTest(
+ String name)
+ {
+ super(name);
+ }
+
+ protected void setUp()
+ {
+ super.setUp();
+ enc = new HexEncoder();
+ }
+
+ protected char paddingChar()
+ {
+ return 0;
+ }
+
+ protected boolean isEncodedChar(char c)
+ {
+ if ('A' <= c && c <= 'F')
+ {
+ return true;
+ }
+ if ('a' <= c && c <= 'f')
+ {
+ return true;
+ }
+ if ('0' <= c && c <= '9')
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public void testInvalidInput()
+ throws IOException
+ {
+ String[] invalid = new String[] { invalid1, invalid2, invalid3, invalid4, invalid5, invalid6 };
+
+ for (int i = 0; i != invalid.length; i++)
+ {
+ invalidTest(invalid[i]);
+ invalidTest(Strings.toByteArray(invalid[i]));
+ }
+ }
+
+ private void invalidTest(String data)
+ {
+ try
+ {
+ Hex.decode(data);
+ }
+ catch (DecoderException e)
+ {
+ return;
+ }
+
+ fail("invalid String data parsed");
+ }
+
+ private void invalidTest(byte[] data)
+ {
+ try
+ {
+ Hex.decode(data);
+ }
+ catch (DecoderException e)
+ {
+ return;
+ }
+
+ fail("invalid byte data parsed");
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/util/encoders/test/UrlBase64Test.java b/core/src/test/java/org/spongycastle/util/encoders/test/UrlBase64Test.java
new file mode 100644
index 00000000..9822efea
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/util/encoders/test/UrlBase64Test.java
@@ -0,0 +1,119 @@
+package org.spongycastle.util.encoders.test;
+
+import java.io.IOException;
+
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Strings;
+import org.spongycastle.util.encoders.DecoderException;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.encoders.UrlBase64;
+import org.spongycastle.util.encoders.UrlBase64Encoder;
+
+public class UrlBase64Test extends AbstractCoderTest
+{
+ private static final String sample1 = "mO4TyLWG7vjFWdKT8IJcVbZ_jwc.";
+ private static final byte[] sample1Bytes = Hex.decode("98ee13c8b586eef8c559d293f0825c55b67f8f07");
+ private static final String sample2 = "F4I4p8Vf_mS-Kxvri3FPoMcqmJ1f";
+ private static final byte[] sample2Bytes = Hex.decode("178238a7c55ffe64be2b1beb8b714fa0c72a989d5f");
+ private static final String sample3 = "UJmEdJYodqHJmd7Rtv6_OP29_jUEFw..";
+ private static final byte[] sample3Bytes = Hex.decode("50998474962876a1c999ded1b6febf38fdbdfe350417");
+
+ private static final String invalid1 = "%O4TyLWG7vjFWdKT8IJcVbZ_jwc.";
+ private static final String invalid2 = "F%I4p8Vf_mS-Kxvri3FPoMcqmJ1f";
+ private static final String invalid3 = "UJ%EdJYodqHJmd7Rtv6_OP29_jUEFw..";
+ private static final String invalid4 = "mO4%yLWG7vjFWdKT8IJcVbZ_jwc.";
+ private static final String invalid5 = "UJmEdJYodqHJmd7Rtv6_OP29_jUEF%..";
+ private static final String invalid6 = "mO4TyLWG7vjFWdKT8IJcVbZ_jw%.";
+ private static final String invalid7 = "F4I4p8Vf_mS-Kxvri3FPoMcqmJ1%";
+ private static final String invalid8 = "UJmEdJYodqHJmd7Rtv6_OP29_jUE%c..";
+ private static final String invalid9 = "mO4TyLWG7vjFWdKT8IJcVbZ_j%c.";
+ private static final String invalida = "F4I4p8Vf_mS-Kxvri3FPoMcqmJ%1";
+ private static final String invalidb = "UJmEdJYodqHJmd7Rtv6_OP29_jU%Fc..";
+ private static final String invalidc = "mO4TyLWG7vjFWdKT8IJcVbZ_%wc.";
+ private static final String invalidd = "F4I4p8Vf_mS-Kxvri3FPoMcqm%1c";
+
+ public UrlBase64Test(
+ String name)
+ {
+ super(name);
+ }
+
+ protected void setUp()
+ {
+ super.setUp();
+ enc = new UrlBase64Encoder();
+ }
+
+ public void testSamples()
+ throws IOException
+ {
+ assertTrue(Arrays.areEqual(sample1Bytes, UrlBase64.decode(sample1)));
+ assertTrue(Arrays.areEqual(sample1Bytes, UrlBase64.decode(Strings.toByteArray(sample1))));
+ assertTrue(Arrays.areEqual(sample2Bytes, UrlBase64.decode(sample2)));
+ assertTrue(Arrays.areEqual(sample2Bytes, UrlBase64.decode(Strings.toByteArray(sample2))));
+ assertTrue(Arrays.areEqual(sample3Bytes, UrlBase64.decode(sample3)));
+ assertTrue(Arrays.areEqual(sample3Bytes, UrlBase64.decode(Strings.toByteArray(sample3))));
+ }
+
+ public void testInvalidInput()
+ throws IOException
+ {
+ String[] invalid = new String[] { invalid1, invalid2, invalid3, invalid4, invalid5, invalid6, invalid7, invalid8, invalid9, invalida, invalidb, invalidc, invalidd };
+
+ for (int i = 0; i != invalid.length; i++)
+ {
+ invalidTest(invalid[i]);
+ invalidTest(Strings.toByteArray(invalid[i]));
+ }
+ }
+
+ private void invalidTest(String data)
+ {
+ try
+ {
+ UrlBase64.decode(data);
+ }
+ catch (DecoderException e)
+ {
+ return;
+ }
+
+ fail("invalid String data parsed");
+ }
+
+ private void invalidTest(byte[] data)
+ {
+ try
+ {
+ UrlBase64.decode(data);
+ }
+ catch (DecoderException e)
+ {
+ return;
+ }
+
+ fail("invalid byte data parsed");
+ }
+
+ protected char paddingChar()
+ {
+ return '.';
+ }
+
+ protected boolean isEncodedChar(char c)
+ {
+ if (Character.isLetterOrDigit(c))
+ {
+ return true;
+ }
+ else if (c == '-')
+ {
+ return true;
+ }
+ else if (c == '_')
+ {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/util/io/pem/test/AllTests.java b/core/src/test/java/org/spongycastle/util/io/pem/test/AllTests.java
new file mode 100644
index 00000000..6c04ace6
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/util/io/pem/test/AllTests.java
@@ -0,0 +1,71 @@
+package org.spongycastle.util.io.pem.test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.spongycastle.util.io.pem.PemHeader;
+import org.spongycastle.util.io.pem.PemObject;
+import org.spongycastle.util.io.pem.PemWriter;
+
+public class AllTests
+ extends TestCase
+{
+ public void testPemLength()
+ throws IOException
+ {
+ for (int i = 1; i != 60; i++)
+ {
+ lengthTest("CERTIFICATE", Collections.EMPTY_LIST, new byte[i]);
+ }
+
+ lengthTest("CERTIFICATE", Collections.EMPTY_LIST, new byte[100]);
+ lengthTest("CERTIFICATE", Collections.EMPTY_LIST, new byte[101]);
+ lengthTest("CERTIFICATE", Collections.EMPTY_LIST, new byte[102]);
+ lengthTest("CERTIFICATE", Collections.EMPTY_LIST, new byte[103]);
+
+ lengthTest("CERTIFICATE", Collections.EMPTY_LIST, new byte[1000]);
+ lengthTest("CERTIFICATE", Collections.EMPTY_LIST, new byte[1001]);
+ lengthTest("CERTIFICATE", Collections.EMPTY_LIST, new byte[1002]);
+ lengthTest("CERTIFICATE", Collections.EMPTY_LIST, new byte[1003]);
+
+ List headers = new ArrayList();
+
+ headers.add(new PemHeader("Proc-Type", "4,ENCRYPTED"));
+ headers.add(new PemHeader("DEK-Info", "DES3,0001020304050607"));
+
+ lengthTest("RSA PRIVATE KEY", headers, new byte[103]);
+ }
+
+ private void lengthTest(String type, List headers, byte[] data)
+ throws IOException
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ PemWriter pWrt = new PemWriter(new OutputStreamWriter(bOut));
+
+ PemObject pemObj = new PemObject(type, headers, data);
+ pWrt.writeObject(pemObj);
+
+ pWrt.close();
+
+ assertEquals(bOut.toByteArray().length, pWrt.getOutputSize(pemObj));
+ }
+
+ public static void main (String[] args)
+ {
+ junit.textui.TestRunner.run (suite());
+ }
+
+ public static Test suite()
+ {
+ TestSuite suite = new TestSuite("util tests");
+ suite.addTestSuite(AllTests.class);
+ return suite;
+ }
+} \ No newline at end of file
diff --git a/core/src/test/java/org/spongycastle/util/io/test/BufferingOutputStreamTest.java b/core/src/test/java/org/spongycastle/util/io/test/BufferingOutputStreamTest.java
new file mode 100644
index 00000000..faaaa532
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/util/io/test/BufferingOutputStreamTest.java
@@ -0,0 +1,68 @@
+package org.spongycastle.util.io.test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.SecureRandom;
+
+import org.spongycastle.util.io.BufferingOutputStream;
+import org.spongycastle.util.test.SimpleTest;
+
+public class BufferingOutputStreamTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "BufferingStreamTest";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ SecureRandom random = new SecureRandom();
+
+ for (int i = 1; i != 256; i++)
+ {
+ byte[] data = new byte[i];
+
+ random.nextBytes(data);
+
+ checkStream(data, 16);
+ checkStream(data, 33);
+ checkStream(data, 128);
+ }
+ }
+
+ private void checkStream(byte[] data, int bufsize)
+ throws IOException
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ BufferingOutputStream bfOut = new BufferingOutputStream(bOut, bufsize);
+
+ for (int i = 0; i != 10; i++)
+ {
+ bfOut.write(data[0]);
+ bfOut.write(data, 1, data.length - 1);
+ }
+
+ bfOut.close();
+
+ byte[] output = bOut.toByteArray();
+
+ for (int i = 0; i != 10; i++)
+ {
+ for (int j = 0; j != data.length; j++)
+ {
+ if (output[i * data.length + j] != data[j])
+ {
+ fail("data mismatch!");
+ }
+ }
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new BufferingOutputStreamTest());
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/util/utiltest/AllTests.java b/core/src/test/java/org/spongycastle/util/utiltest/AllTests.java
new file mode 100644
index 00000000..37c73eb8
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/util/utiltest/AllTests.java
@@ -0,0 +1,20 @@
+package org.spongycastle.util.utiltest;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests
+{
+ public static void main (String[] args)
+ {
+ junit.textui.TestRunner.run (suite());
+ }
+
+ public static Test suite()
+ {
+ TestSuite suite = new TestSuite("util tests");
+ suite.addTestSuite(IPTest.class);
+ suite.addTestSuite(BigIntegersTest.class);
+ return suite;
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/util/utiltest/BigIntegersTest.java b/core/src/test/java/org/spongycastle/util/utiltest/BigIntegersTest.java
new file mode 100644
index 00000000..f17745ee
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/util/utiltest/BigIntegersTest.java
@@ -0,0 +1,90 @@
+package org.spongycastle.util.utiltest;
+
+import java.math.BigInteger;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.BigIntegers;
+import org.spongycastle.util.IPAddress;
+import org.spongycastle.util.encoders.Hex;
+
+public class BigIntegersTest
+ extends TestCase
+{
+ public String getName()
+ {
+ return "BigIntegers";
+ }
+
+ public void testAsUnsignedByteArray()
+ {
+ BigInteger a = new BigInteger(1, Hex.decode("ff12345678"));
+
+ byte[] a5 = BigIntegers.asUnsignedByteArray(a);
+
+ Assert.assertEquals(5, a5.length);
+ Assert.assertTrue(Arrays.areEqual(a5, Hex.decode("ff12345678")));
+
+ BigInteger b = new BigInteger(1, Hex.decode("0f12345678"));
+
+ byte[] b5 = BigIntegers.asUnsignedByteArray(b);
+
+ Assert.assertEquals(5, b5.length);
+ Assert.assertTrue(Arrays.areEqual(b5, Hex.decode("0f12345678")));
+ }
+
+ public void testFixedLengthUnsignedByteArray()
+ {
+ BigInteger a = new BigInteger(1, Hex.decode("ff12345678"));
+
+ byte[] a5 = BigIntegers.asUnsignedByteArray(5, a);
+
+ Assert.assertEquals(5, a5.length);
+ Assert.assertTrue(Arrays.areEqual(a5, Hex.decode("ff12345678")));
+
+ byte[] a6 = BigIntegers.asUnsignedByteArray(6, a);
+
+ Assert.assertEquals(6, a6.length);
+ Assert.assertEquals(0, a6[0]);
+ Assert.assertTrue(Arrays.areEqual(a6, Hex.decode("00ff12345678")));
+
+ BigInteger b = new BigInteger(1, Hex.decode("0f12345678"));
+
+ byte[] b5 = BigIntegers.asUnsignedByteArray(5, b);
+
+ Assert.assertEquals(5, b5.length);
+ Assert.assertTrue(Arrays.areEqual(b5, Hex.decode("0f12345678")));
+
+ byte[] b6 = BigIntegers.asUnsignedByteArray(6, b);
+
+ Assert.assertEquals(6, b6.length);
+ Assert.assertEquals(0, b6[0]);
+ Assert.assertTrue(Arrays.areEqual(b6, Hex.decode("000f12345678")));
+
+ BigInteger c = new BigInteger(1, Hex.decode("ff123456789a"));
+
+ try
+ {
+ byte[] c5 = BigIntegers.asUnsignedByteArray(5, c);
+
+ fail("no exception thrown");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // ignore
+ }
+
+ BigInteger d = new BigInteger(1, Hex.decode("0f123456789a"));
+ try
+ {
+ byte[] c5 = BigIntegers.asUnsignedByteArray(5, d);
+
+ fail("no exception thrown");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // ignore
+ }
+ }
+}
diff --git a/core/src/test/java/org/spongycastle/util/utiltest/IPTest.java b/core/src/test/java/org/spongycastle/util/utiltest/IPTest.java
new file mode 100644
index 00000000..93df95b9
--- /dev/null
+++ b/core/src/test/java/org/spongycastle/util/utiltest/IPTest.java
@@ -0,0 +1,55 @@
+package org.spongycastle.util.utiltest;
+
+import junit.framework.TestCase;
+import org.spongycastle.util.IPAddress;
+
+public class IPTest
+ extends TestCase
+{
+
+ private static final String validIP4v[] = new String[]
+ { "0.0.0.0", "255.255.255.255", "192.168.0.0" };
+
+ private static final String invalidIP4v[] = new String[]
+ { "0.0.0.0.1", "256.255.255.255", "1", "A.B.C", "1:.4.6.5" };
+
+ private static final String validIP6v[] = new String[]
+ { "0:0:0:0:0:0:0:0", "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF",
+ "0:1:2:3:FFFF:5:FFFF:1" };
+
+ private static final String invalidIP6v[] = new String[]
+ { "0.0.0.0:1", "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFFF" };
+
+ private void testIP(String[] valid, String[] invalid)
+ {
+ for (int i = 0; i < valid.length; i++)
+ {
+ if (!IPAddress.isValid(valid[i]))
+ {
+ fail("Valid input string not accepted: " + valid[i] + ".");
+ }
+ }
+ for (int i = 0; i < invalid.length; i++)
+ {
+ if (IPAddress.isValid(invalid[i]))
+ {
+ fail("Invalid input string accepted: " + invalid[i] + ".");
+ }
+ }
+ }
+
+ public String getName()
+ {
+ return "IPTest";
+ }
+
+ public void testIPv4()
+ {
+ testIP(validIP4v, invalidIP4v);
+ }
+
+ public void testIPv6()
+ {
+ testIP(validIP6v, invalidIP6v);
+ }
+}
diff --git a/core/src/test/javadoc/org/bouncycastle/cms/test/package.html b/core/src/test/javadoc/org/bouncycastle/cms/test/package.html
deleted file mode 100644
index 153bbd0a..00000000
--- a/core/src/test/javadoc/org/bouncycastle/cms/test/package.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Regression tests for the org.bouncycastle.cms package.
-<p>
-<b>Note</b>: The classes in this package are also a useful source of example code.
-</body>
-</html>
diff --git a/core/src/test/javadoc/org/bouncycastle/mail/smime/test/package.html b/core/src/test/javadoc/org/bouncycastle/mail/smime/test/package.html
deleted file mode 100644
index 25666a16..00000000
--- a/core/src/test/javadoc/org/bouncycastle/mail/smime/test/package.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Regression tests for the org.bouncycastle.mail.smime package.
-<p>
-<b>Note</b>: The classes in this package are also a useful source of example code.
-</body>
-</html>
diff --git a/core/src/test/javadoc/org/bouncycastle/openpgp/test/package.html b/core/src/test/javadoc/org/bouncycastle/openpgp/test/package.html
deleted file mode 100644
index b3244792..00000000
--- a/core/src/test/javadoc/org/bouncycastle/openpgp/test/package.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Regression tests and further examples of use for the org.bouncycastle.openpgp package.
-<p>
-<b>Note</b>: The classes in this package are also a useful source of example code.
-</body>
-</html>
diff --git a/core/src/test/javadoc/org/bouncycastle/asn1/test/package.html b/core/src/test/javadoc/org/spongycastle/asn1/test/package.html
index df45e190..df45e190 100644
--- a/core/src/test/javadoc/org/bouncycastle/asn1/test/package.html
+++ b/core/src/test/javadoc/org/spongycastle/asn1/test/package.html
diff --git a/core/src/test/javadoc/org/spongycastle/cms/test/package.html b/core/src/test/javadoc/org/spongycastle/cms/test/package.html
new file mode 100644
index 00000000..a2429199
--- /dev/null
+++ b/core/src/test/javadoc/org/spongycastle/cms/test/package.html
@@ -0,0 +1,7 @@
+<html>
+<body bgcolor="#ffffff">
+Regression tests for the org.spongycastle.cms package.
+<p>
+<b>Note</b>: The classes in this package are also a useful source of example code.
+</body>
+</html>
diff --git a/core/src/test/javadoc/org/bouncycastle/crypto/test/package.html b/core/src/test/javadoc/org/spongycastle/crypto/test/package.html
index 7bb5e6b1..7bb5e6b1 100644
--- a/core/src/test/javadoc/org/bouncycastle/crypto/test/package.html
+++ b/core/src/test/javadoc/org/spongycastle/crypto/test/package.html
diff --git a/core/src/test/javadoc/org/bouncycastle/crypto/tls/package.html b/core/src/test/javadoc/org/spongycastle/crypto/tls/package.html
index ee59f8af..ee59f8af 100644
--- a/core/src/test/javadoc/org/bouncycastle/crypto/tls/package.html
+++ b/core/src/test/javadoc/org/spongycastle/crypto/tls/package.html
diff --git a/core/src/test/javadoc/org/spongycastle/mail/smime/test/package.html b/core/src/test/javadoc/org/spongycastle/mail/smime/test/package.html
new file mode 100644
index 00000000..ba0911ef
--- /dev/null
+++ b/core/src/test/javadoc/org/spongycastle/mail/smime/test/package.html
@@ -0,0 +1,7 @@
+<html>
+<body bgcolor="#ffffff">
+Regression tests for the org.spongycastle.mail.smime package.
+<p>
+<b>Note</b>: The classes in this package are also a useful source of example code.
+</body>
+</html>
diff --git a/core/src/test/javadoc/org/bouncycastle/mozilla/test/package.html b/core/src/test/javadoc/org/spongycastle/mozilla/test/package.html
index 54047adc..54047adc 100644
--- a/core/src/test/javadoc/org/bouncycastle/mozilla/test/package.html
+++ b/core/src/test/javadoc/org/spongycastle/mozilla/test/package.html
diff --git a/core/src/test/javadoc/org/bouncycastle/ocsp/test/package.html b/core/src/test/javadoc/org/spongycastle/ocsp/test/package.html
index 6ce2e3a0..6ce2e3a0 100644
--- a/core/src/test/javadoc/org/bouncycastle/ocsp/test/package.html
+++ b/core/src/test/javadoc/org/spongycastle/ocsp/test/package.html
diff --git a/core/src/test/javadoc/org/spongycastle/openpgp/test/package.html b/core/src/test/javadoc/org/spongycastle/openpgp/test/package.html
new file mode 100644
index 00000000..f7da1f81
--- /dev/null
+++ b/core/src/test/javadoc/org/spongycastle/openpgp/test/package.html
@@ -0,0 +1,7 @@
+<html>
+<body bgcolor="#ffffff">
+Regression tests and further examples of use for the org.spongycastle.openpgp package.
+<p>
+<b>Note</b>: The classes in this package are also a useful source of example code.
+</body>
+</html>
diff --git a/core/src/test/javadoc/org/bouncycastle/openssl/test/package.html b/core/src/test/javadoc/org/spongycastle/openssl/test/package.html
index 368d7096..368d7096 100644
--- a/core/src/test/javadoc/org/bouncycastle/openssl/test/package.html
+++ b/core/src/test/javadoc/org/spongycastle/openssl/test/package.html
diff --git a/core/src/test/jdk1.1/org/bouncycastle/asn1/test/RegressionTest.java b/core/src/test/jdk1.1/org/bouncycastle/asn1/test/RegressionTest.java
deleted file mode 100644
index 6d827c6f..00000000
--- a/core/src/test/jdk1.1/org/bouncycastle/asn1/test/RegressionTest.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-public class RegressionTest
-{
- public static Test[] tests = {
- new InputStreamTest(),
- new EqualsAndHashCodeTest(),
- new TagTest(),
- new SetTest(),
- new DERUTF8StringTest(),
- new CertificateTest(),
- new GenerationTest(),
- new CMSTest(),
- new OCSPTest(),
- new OIDTest(),
- new PKCS10Test(),
- new PKCS12Test(),
- new X509NameTest(),
- new X500NameTest(),
- new X509ExtensionsTest(),
- new GeneralizedTimeTest(),
- new BitStringTest(),
- new MiscTest(),
- new SMIMETest(),
- new X9Test(),
- new MonetaryValueUnitTest(),
- new BiometricDataUnitTest(),
- new Iso4217CurrencyCodeUnitTest(),
- new SemanticsInformationUnitTest(),
- new QCStatementUnitTest(),
- new TypeOfBiometricDataUnitTest(),
- new SignerLocationUnitTest(),
- new CommitmentTypeQualifierUnitTest(),
- new CommitmentTypeIndicationUnitTest(),
- new EncryptedPrivateKeyInfoTest(),
- new DataGroupHashUnitTest(),
- new LDSSecurityObjectUnitTest(),
- // new CscaMasterListTest(),
- new AttributeTableUnitTest(),
- new ReasonFlagsTest(),
- new NetscapeCertTypeTest(),
- new PKIFailureInfoTest(),
- new KeyUsageTest(),
- new StringTest(),
- new UTCTimeTest(),
- new RequestedCertificateUnitTest(),
- new OtherCertIDUnitTest(),
- new OtherSigningCertificateUnitTest(),
- new ContentHintsUnitTest(),
- new CertHashUnitTest(),
- new AdditionalInformationSyntaxUnitTest(),
- new AdmissionSyntaxUnitTest(),
- new AdmissionsUnitTest(),
- new DeclarationOfMajorityUnitTest(),
- new ProcurationSyntaxUnitTest(),
- new ProfessionInfoUnitTest(),
- new RestrictionUnitTest(),
- new NamingAuthorityUnitTest(),
- new MonetaryLimitUnitTest(),
- new NameOrPseudonymUnitTest(),
- new PersonalDataUnitTest(),
- new DERApplicationSpecificTest(),
- new IssuingDistributionPointUnitTest(),
- new TargetInformationTest(),
- new SubjectKeyIdentifierTest(),
- new ESSCertIDv2UnitTest(),
- new ParsingTest(),
- new GeneralNameTest(),
- new RFC4519Test()
- };
-
- public static void main(
- String[] args)
- {
- for (int i = 0; i != tests.length; i++)
- {
- TestResult result = tests[i].perform();
-
- if (result.getException() != null)
- {
- result.getException().printStackTrace();
- }
-
- System.out.println(result);
- }
- }
-}
-
diff --git a/core/src/test/jdk1.1/org/bouncycastle/crypto/test/RegressionTest.java b/core/src/test/jdk1.1/org/bouncycastle/crypto/test/RegressionTest.java
deleted file mode 100644
index 230145df..00000000
--- a/core/src/test/jdk1.1/org/bouncycastle/crypto/test/RegressionTest.java
+++ /dev/null
@@ -1,149 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-public class RegressionTest
-{
- public static Test[] tests =
- {
- new AESTest(),
- new AESLightTest(),
- new AESFastTest(),
- new AESWrapTest(),
- new DESTest(),
- new DESedeTest(),
- new ModeTest(),
- new PaddingTest(),
- new DHTest(),
- new ElGamalTest(),
- new DSATest(),
- new ECTest(),
- new GOST3410Test(),
- new ECGOST3410Test(),
- new ECIESTest(),
- new ECNRTest(),
- new MacTest(),
- new GOST28147MacTest(),
- new RC2Test(),
- new RC2WrapTest(),
- new RC4Test(),
- new RC5Test(),
- new RC6Test(),
- new RijndaelTest(),
- new SerpentTest(),
- new CamelliaTest(),
- new CamelliaLightTest(),
- new DigestRandomNumberTest(),
- new SkipjackTest(),
- new BlowfishTest(),
- new TwofishTest(),
- new Threefish256Test(),
- new Threefish512Test(),
- new Threefish1024Test(),
- new SkeinDigestTest(),
- new SkeinMacTest(),
- new CAST5Test(),
- new CAST6Test(),
- new GOST28147Test(),
- new IDEATest(),
- new RSATest(),
- new RSABlindedTest(),
- new RSADigestSignerTest(),
- new PSSBlindTest(),
- new ISO9796Test(),
- new ISO9797Alg3MacTest(),
- new MD2DigestTest(),
- new MD4DigestTest(),
- new MD5DigestTest(),
- new SHA1DigestTest(),
- new SHA224DigestTest(),
- new SHA256DigestTest(),
- new SHA384DigestTest(),
- new SHA512DigestTest(),
- new SHA512t224DigestTest(),
- new SHA512t256DigestTest(),
- new SHA3DigestTest(),
- new RIPEMD128DigestTest(),
- new RIPEMD160DigestTest(),
- new RIPEMD256DigestTest(),
- new RIPEMD320DigestTest(),
- new TigerDigestTest(),
- new GOST3411DigestTest(),
- new WhirlpoolDigestTest(),
- new MD5HMacTest(),
- new SHA1HMacTest(),
- new SHA224HMacTest(),
- new SHA256HMacTest(),
- new SHA384HMacTest(),
- new SHA512HMacTest(),
- new RIPEMD128HMacTest(),
- new RIPEMD160HMacTest(),
- new OAEPTest(),
- new PSSTest(),
- new CTSTest(),
- new CCMTest(),
- new PKCS5Test(),
- new PKCS12Test(),
- new KDF1GeneratorTest(),
- new KDF2GeneratorTest(),
- new MGF1GeneratorTest(),
- new HKDFGeneratorTest(),
- new DHKEKGeneratorTest(),
- new ECDHKEKGeneratorTest(),
- new ShortenedDigestTest(),
- new EqualsHashCodeTest(),
- new TEATest(),
- new XTEATest(),
- new RFC3211WrapTest(),
- new SEEDTest(),
- new Salsa20Test(),
- new XSalsa20Test(),
- new ChaChaTest(),
- new CMacTest(),
- new EAXTest(),
- new GCMTest(),
- new GMacTest(),
- new HCFamilyTest(),
- new HCFamilyVecTest(),
- new ISAACTest(),
- new NoekeonTest(),
- new VMPCKSA3Test(),
- new VMPCMacTest(),
- new VMPCTest(),
- new Grainv1Test(),
- new Grain128Test(),
- //new NaccacheSternTest(),
- new SRP6Test(),
- new SCryptTest(),
- new ResetTest(),
- new NullTest(),
- new DSTU4145Test(),
- new Poly1305Test(),
- new OCBTest(),
- new NonMemoableDigestTest(),
- new RSAKeyEncapsulationTest(),
- new ECIESKeyEncapsulationTest(),
- new HashCommitmentTest(),
- new CipherStreamTest(),
- new BlockCipherResetTest(),
- new StreamCipherResetTest(),
- new SM3DigestTest()
- };
-
- public static void main(
- String[] args)
- {
- for (int i = 0; i != tests.length; i++)
- {
- TestResult result = tests[i].perform();
-
- if (result.getException() != null)
- {
- result.getException().printStackTrace();
- }
-
- System.out.println(result);
- }
- }
-}
diff --git a/core/src/test/jdk1.1/org/spongycastle/asn1/test/RegressionTest.java b/core/src/test/jdk1.1/org/spongycastle/asn1/test/RegressionTest.java
new file mode 100644
index 00000000..01633bd3
--- /dev/null
+++ b/core/src/test/jdk1.1/org/spongycastle/asn1/test/RegressionTest.java
@@ -0,0 +1,91 @@
+package org.spongycastle.asn1.test;
+
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+public class RegressionTest
+{
+ public static Test[] tests = {
+ new InputStreamTest(),
+ new EqualsAndHashCodeTest(),
+ new TagTest(),
+ new SetTest(),
+ new DERUTF8StringTest(),
+ new CertificateTest(),
+ new GenerationTest(),
+ new CMSTest(),
+ new OCSPTest(),
+ new OIDTest(),
+ new PKCS10Test(),
+ new PKCS12Test(),
+ new X509NameTest(),
+ new X500NameTest(),
+ new X509ExtensionsTest(),
+ new GeneralizedTimeTest(),
+ new BitStringTest(),
+ new MiscTest(),
+ new SMIMETest(),
+ new X9Test(),
+ new MonetaryValueUnitTest(),
+ new BiometricDataUnitTest(),
+ new Iso4217CurrencyCodeUnitTest(),
+ new SemanticsInformationUnitTest(),
+ new QCStatementUnitTest(),
+ new TypeOfBiometricDataUnitTest(),
+ new SignerLocationUnitTest(),
+ new CommitmentTypeQualifierUnitTest(),
+ new CommitmentTypeIndicationUnitTest(),
+ new EncryptedPrivateKeyInfoTest(),
+ new DataGroupHashUnitTest(),
+ new LDSSecurityObjectUnitTest(),
+ // new CscaMasterListTest(),
+ new AttributeTableUnitTest(),
+ new ReasonFlagsTest(),
+ new NetscapeCertTypeTest(),
+ new PKIFailureInfoTest(),
+ new KeyUsageTest(),
+ new StringTest(),
+ new UTCTimeTest(),
+ new RequestedCertificateUnitTest(),
+ new OtherCertIDUnitTest(),
+ new OtherSigningCertificateUnitTest(),
+ new ContentHintsUnitTest(),
+ new CertHashUnitTest(),
+ new AdditionalInformationSyntaxUnitTest(),
+ new AdmissionSyntaxUnitTest(),
+ new AdmissionsUnitTest(),
+ new DeclarationOfMajorityUnitTest(),
+ new ProcurationSyntaxUnitTest(),
+ new ProfessionInfoUnitTest(),
+ new RestrictionUnitTest(),
+ new NamingAuthorityUnitTest(),
+ new MonetaryLimitUnitTest(),
+ new NameOrPseudonymUnitTest(),
+ new PersonalDataUnitTest(),
+ new DERApplicationSpecificTest(),
+ new IssuingDistributionPointUnitTest(),
+ new TargetInformationTest(),
+ new SubjectKeyIdentifierTest(),
+ new ESSCertIDv2UnitTest(),
+ new ParsingTest(),
+ new GeneralNameTest(),
+ new RFC4519Test()
+ };
+
+ public static void main(
+ String[] args)
+ {
+ for (int i = 0; i != tests.length; i++)
+ {
+ TestResult result = tests[i].perform();
+
+ if (result.getException() != null)
+ {
+ result.getException().printStackTrace();
+ }
+
+ System.out.println(result);
+ }
+ }
+}
+
diff --git a/core/src/test/jdk1.1/org/spongycastle/crypto/test/RegressionTest.java b/core/src/test/jdk1.1/org/spongycastle/crypto/test/RegressionTest.java
new file mode 100644
index 00000000..424fe49d
--- /dev/null
+++ b/core/src/test/jdk1.1/org/spongycastle/crypto/test/RegressionTest.java
@@ -0,0 +1,149 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+public class RegressionTest
+{
+ public static Test[] tests =
+ {
+ new AESTest(),
+ new AESLightTest(),
+ new AESFastTest(),
+ new AESWrapTest(),
+ new DESTest(),
+ new DESedeTest(),
+ new ModeTest(),
+ new PaddingTest(),
+ new DHTest(),
+ new ElGamalTest(),
+ new DSATest(),
+ new ECTest(),
+ new GOST3410Test(),
+ new ECGOST3410Test(),
+ new ECIESTest(),
+ new ECNRTest(),
+ new MacTest(),
+ new GOST28147MacTest(),
+ new RC2Test(),
+ new RC2WrapTest(),
+ new RC4Test(),
+ new RC5Test(),
+ new RC6Test(),
+ new RijndaelTest(),
+ new SerpentTest(),
+ new CamelliaTest(),
+ new CamelliaLightTest(),
+ new DigestRandomNumberTest(),
+ new SkipjackTest(),
+ new BlowfishTest(),
+ new TwofishTest(),
+ new Threefish256Test(),
+ new Threefish512Test(),
+ new Threefish1024Test(),
+ new SkeinDigestTest(),
+ new SkeinMacTest(),
+ new CAST5Test(),
+ new CAST6Test(),
+ new GOST28147Test(),
+ new IDEATest(),
+ new RSATest(),
+ new RSABlindedTest(),
+ new RSADigestSignerTest(),
+ new PSSBlindTest(),
+ new ISO9796Test(),
+ new ISO9797Alg3MacTest(),
+ new MD2DigestTest(),
+ new MD4DigestTest(),
+ new MD5DigestTest(),
+ new SHA1DigestTest(),
+ new SHA224DigestTest(),
+ new SHA256DigestTest(),
+ new SHA384DigestTest(),
+ new SHA512DigestTest(),
+ new SHA512t224DigestTest(),
+ new SHA512t256DigestTest(),
+ new SHA3DigestTest(),
+ new RIPEMD128DigestTest(),
+ new RIPEMD160DigestTest(),
+ new RIPEMD256DigestTest(),
+ new RIPEMD320DigestTest(),
+ new TigerDigestTest(),
+ new GOST3411DigestTest(),
+ new WhirlpoolDigestTest(),
+ new MD5HMacTest(),
+ new SHA1HMacTest(),
+ new SHA224HMacTest(),
+ new SHA256HMacTest(),
+ new SHA384HMacTest(),
+ new SHA512HMacTest(),
+ new RIPEMD128HMacTest(),
+ new RIPEMD160HMacTest(),
+ new OAEPTest(),
+ new PSSTest(),
+ new CTSTest(),
+ new CCMTest(),
+ new PKCS5Test(),
+ new PKCS12Test(),
+ new KDF1GeneratorTest(),
+ new KDF2GeneratorTest(),
+ new MGF1GeneratorTest(),
+ new HKDFGeneratorTest(),
+ new DHKEKGeneratorTest(),
+ new ECDHKEKGeneratorTest(),
+ new ShortenedDigestTest(),
+ new EqualsHashCodeTest(),
+ new TEATest(),
+ new XTEATest(),
+ new RFC3211WrapTest(),
+ new SEEDTest(),
+ new Salsa20Test(),
+ new XSalsa20Test(),
+ new ChaChaTest(),
+ new CMacTest(),
+ new EAXTest(),
+ new GCMTest(),
+ new GMacTest(),
+ new HCFamilyTest(),
+ new HCFamilyVecTest(),
+ new ISAACTest(),
+ new NoekeonTest(),
+ new VMPCKSA3Test(),
+ new VMPCMacTest(),
+ new VMPCTest(),
+ new Grainv1Test(),
+ new Grain128Test(),
+ //new NaccacheSternTest(),
+ new SRP6Test(),
+ new SCryptTest(),
+ new ResetTest(),
+ new NullTest(),
+ new DSTU4145Test(),
+ new Poly1305Test(),
+ new OCBTest(),
+ new NonMemoableDigestTest(),
+ new RSAKeyEncapsulationTest(),
+ new ECIESKeyEncapsulationTest(),
+ new HashCommitmentTest(),
+ new CipherStreamTest(),
+ new BlockCipherResetTest(),
+ new StreamCipherResetTest(),
+ new SM3DigestTest()
+ };
+
+ public static void main(
+ String[] args)
+ {
+ for (int i = 0; i != tests.length; i++)
+ {
+ TestResult result = tests[i].perform();
+
+ if (result.getException() != null)
+ {
+ result.getException().printStackTrace();
+ }
+
+ System.out.println(result);
+ }
+ }
+}
diff --git a/core/src/test/jdk1.2/org/bouncycastle/asn1/test/RegressionTest.java b/core/src/test/jdk1.2/org/bouncycastle/asn1/test/RegressionTest.java
deleted file mode 100644
index 6d827c6f..00000000
--- a/core/src/test/jdk1.2/org/bouncycastle/asn1/test/RegressionTest.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-public class RegressionTest
-{
- public static Test[] tests = {
- new InputStreamTest(),
- new EqualsAndHashCodeTest(),
- new TagTest(),
- new SetTest(),
- new DERUTF8StringTest(),
- new CertificateTest(),
- new GenerationTest(),
- new CMSTest(),
- new OCSPTest(),
- new OIDTest(),
- new PKCS10Test(),
- new PKCS12Test(),
- new X509NameTest(),
- new X500NameTest(),
- new X509ExtensionsTest(),
- new GeneralizedTimeTest(),
- new BitStringTest(),
- new MiscTest(),
- new SMIMETest(),
- new X9Test(),
- new MonetaryValueUnitTest(),
- new BiometricDataUnitTest(),
- new Iso4217CurrencyCodeUnitTest(),
- new SemanticsInformationUnitTest(),
- new QCStatementUnitTest(),
- new TypeOfBiometricDataUnitTest(),
- new SignerLocationUnitTest(),
- new CommitmentTypeQualifierUnitTest(),
- new CommitmentTypeIndicationUnitTest(),
- new EncryptedPrivateKeyInfoTest(),
- new DataGroupHashUnitTest(),
- new LDSSecurityObjectUnitTest(),
- // new CscaMasterListTest(),
- new AttributeTableUnitTest(),
- new ReasonFlagsTest(),
- new NetscapeCertTypeTest(),
- new PKIFailureInfoTest(),
- new KeyUsageTest(),
- new StringTest(),
- new UTCTimeTest(),
- new RequestedCertificateUnitTest(),
- new OtherCertIDUnitTest(),
- new OtherSigningCertificateUnitTest(),
- new ContentHintsUnitTest(),
- new CertHashUnitTest(),
- new AdditionalInformationSyntaxUnitTest(),
- new AdmissionSyntaxUnitTest(),
- new AdmissionsUnitTest(),
- new DeclarationOfMajorityUnitTest(),
- new ProcurationSyntaxUnitTest(),
- new ProfessionInfoUnitTest(),
- new RestrictionUnitTest(),
- new NamingAuthorityUnitTest(),
- new MonetaryLimitUnitTest(),
- new NameOrPseudonymUnitTest(),
- new PersonalDataUnitTest(),
- new DERApplicationSpecificTest(),
- new IssuingDistributionPointUnitTest(),
- new TargetInformationTest(),
- new SubjectKeyIdentifierTest(),
- new ESSCertIDv2UnitTest(),
- new ParsingTest(),
- new GeneralNameTest(),
- new RFC4519Test()
- };
-
- public static void main(
- String[] args)
- {
- for (int i = 0; i != tests.length; i++)
- {
- TestResult result = tests[i].perform();
-
- if (result.getException() != null)
- {
- result.getException().printStackTrace();
- }
-
- System.out.println(result);
- }
- }
-}
-
diff --git a/core/src/test/jdk1.2/org/bouncycastle/crypto/test/RegressionTest.java b/core/src/test/jdk1.2/org/bouncycastle/crypto/test/RegressionTest.java
deleted file mode 100644
index b7b6158b..00000000
--- a/core/src/test/jdk1.2/org/bouncycastle/crypto/test/RegressionTest.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-public class RegressionTest
-{
- public static Test[] tests =
- {
- new AESTest(),
- new AESLightTest(),
- new AESFastTest(),
- new AESWrapTest(),
- new DESTest(),
- new DESedeTest(),
- new ModeTest(),
- new PaddingTest(),
- new DHTest(),
- new ElGamalTest(),
- new DSATest(),
- new ECTest(),
- new GOST3410Test(),
- new ECGOST3410Test(),
- new ECIESTest(),
- new ECNRTest(),
- new MacTest(),
- new GOST28147MacTest(),
- new RC2Test(),
- new RC2WrapTest(),
- new RC4Test(),
- new RC5Test(),
- new RC6Test(),
- new RijndaelTest(),
- new SerpentTest(),
- new CamelliaTest(),
- new CamelliaLightTest(),
- new DigestRandomNumberTest(),
- new SkipjackTest(),
- new BlowfishTest(),
- new TwofishTest(),
- new Threefish256Test(),
- new Threefish512Test(),
- new Threefish1024Test(),
- new SkeinDigestTest(),
- new SkeinMacTest(),
- new CAST5Test(),
- new CAST6Test(),
- new GOST28147Test(),
- new IDEATest(),
- new RSATest(),
- new RSABlindedTest(),
- new RSADigestSignerTest(),
- new PSSBlindTest(),
- new ISO9796Test(),
- new ISO9797Alg3MacTest(),
- new MD2DigestTest(),
- new MD4DigestTest(),
- new MD5DigestTest(),
- new SHA1DigestTest(),
- new SHA224DigestTest(),
- new SHA256DigestTest(),
- new SHA384DigestTest(),
- new SHA512DigestTest(),
- new SHA512t224DigestTest(),
- new SHA512t256DigestTest(),
- new SHA3DigestTest(),
- new RIPEMD128DigestTest(),
- new RIPEMD160DigestTest(),
- new RIPEMD256DigestTest(),
- new RIPEMD320DigestTest(),
- new TigerDigestTest(),
- new GOST3411DigestTest(),
- new WhirlpoolDigestTest(),
- new MD5HMacTest(),
- new SHA1HMacTest(),
- new SHA224HMacTest(),
- new SHA256HMacTest(),
- new SHA384HMacTest(),
- new SHA512HMacTest(),
- new RIPEMD128HMacTest(),
- new RIPEMD160HMacTest(),
- new OAEPTest(),
- new PSSTest(),
- new CTSTest(),
- new CCMTest(),
- new PKCS5Test(),
- new PKCS12Test(),
- new KDF1GeneratorTest(),
- new KDF2GeneratorTest(),
- new MGF1GeneratorTest(),
- new HKDFGeneratorTest(),
- new DHKEKGeneratorTest(),
- new ECDHKEKGeneratorTest(),
- new ShortenedDigestTest(),
- new EqualsHashCodeTest(),
- new TEATest(),
- new XTEATest(),
- new RFC3211WrapTest(),
- new SEEDTest(),
- new Salsa20Test(),
- new XSalsa20Test(),
- new ChaChaTest(),
- new CMacTest(),
- new EAXTest(),
- new GCMTest(),
- new GMacTest(),
- new HCFamilyTest(),
- new HCFamilyVecTest(),
- new ISAACTest(),
- new NoekeonTest(),
- new VMPCKSA3Test(),
- new VMPCMacTest(),
- new VMPCTest(),
- new Grainv1Test(),
- new Grain128Test(),
- //new NaccacheSternTest(),
- new SRP6Test(),
- new SCryptTest(),
- new ResetTest(),
- new NullTest(),
- new DSTU4145Test(),
- new SipHashTest(),
- new Poly1305Test(),
- new OCBTest(),
- new NonMemoableDigestTest(),
- new RSAKeyEncapsulationTest(),
- new ECIESKeyEncapsulationTest(),
- new HashCommitmentTest(),
- new CipherStreamTest(),
- new BlockCipherResetTest(),
- new StreamCipherResetTest(),
- new SM3DigestTest()
- };
-
- public static void main(
- String[] args)
- {
- for (int i = 0; i != tests.length; i++)
- {
- TestResult result = tests[i].perform();
-
- if (result.getException() != null)
- {
- result.getException().printStackTrace();
- }
-
- System.out.println(result);
- }
- }
-}
diff --git a/core/src/test/jdk1.2/org/spongycastle/asn1/test/RegressionTest.java b/core/src/test/jdk1.2/org/spongycastle/asn1/test/RegressionTest.java
new file mode 100644
index 00000000..01633bd3
--- /dev/null
+++ b/core/src/test/jdk1.2/org/spongycastle/asn1/test/RegressionTest.java
@@ -0,0 +1,91 @@
+package org.spongycastle.asn1.test;
+
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+public class RegressionTest
+{
+ public static Test[] tests = {
+ new InputStreamTest(),
+ new EqualsAndHashCodeTest(),
+ new TagTest(),
+ new SetTest(),
+ new DERUTF8StringTest(),
+ new CertificateTest(),
+ new GenerationTest(),
+ new CMSTest(),
+ new OCSPTest(),
+ new OIDTest(),
+ new PKCS10Test(),
+ new PKCS12Test(),
+ new X509NameTest(),
+ new X500NameTest(),
+ new X509ExtensionsTest(),
+ new GeneralizedTimeTest(),
+ new BitStringTest(),
+ new MiscTest(),
+ new SMIMETest(),
+ new X9Test(),
+ new MonetaryValueUnitTest(),
+ new BiometricDataUnitTest(),
+ new Iso4217CurrencyCodeUnitTest(),
+ new SemanticsInformationUnitTest(),
+ new QCStatementUnitTest(),
+ new TypeOfBiometricDataUnitTest(),
+ new SignerLocationUnitTest(),
+ new CommitmentTypeQualifierUnitTest(),
+ new CommitmentTypeIndicationUnitTest(),
+ new EncryptedPrivateKeyInfoTest(),
+ new DataGroupHashUnitTest(),
+ new LDSSecurityObjectUnitTest(),
+ // new CscaMasterListTest(),
+ new AttributeTableUnitTest(),
+ new ReasonFlagsTest(),
+ new NetscapeCertTypeTest(),
+ new PKIFailureInfoTest(),
+ new KeyUsageTest(),
+ new StringTest(),
+ new UTCTimeTest(),
+ new RequestedCertificateUnitTest(),
+ new OtherCertIDUnitTest(),
+ new OtherSigningCertificateUnitTest(),
+ new ContentHintsUnitTest(),
+ new CertHashUnitTest(),
+ new AdditionalInformationSyntaxUnitTest(),
+ new AdmissionSyntaxUnitTest(),
+ new AdmissionsUnitTest(),
+ new DeclarationOfMajorityUnitTest(),
+ new ProcurationSyntaxUnitTest(),
+ new ProfessionInfoUnitTest(),
+ new RestrictionUnitTest(),
+ new NamingAuthorityUnitTest(),
+ new MonetaryLimitUnitTest(),
+ new NameOrPseudonymUnitTest(),
+ new PersonalDataUnitTest(),
+ new DERApplicationSpecificTest(),
+ new IssuingDistributionPointUnitTest(),
+ new TargetInformationTest(),
+ new SubjectKeyIdentifierTest(),
+ new ESSCertIDv2UnitTest(),
+ new ParsingTest(),
+ new GeneralNameTest(),
+ new RFC4519Test()
+ };
+
+ public static void main(
+ String[] args)
+ {
+ for (int i = 0; i != tests.length; i++)
+ {
+ TestResult result = tests[i].perform();
+
+ if (result.getException() != null)
+ {
+ result.getException().printStackTrace();
+ }
+
+ System.out.println(result);
+ }
+ }
+}
+
diff --git a/core/src/test/jdk1.2/org/spongycastle/crypto/test/RegressionTest.java b/core/src/test/jdk1.2/org/spongycastle/crypto/test/RegressionTest.java
new file mode 100644
index 00000000..7bf7fd64
--- /dev/null
+++ b/core/src/test/jdk1.2/org/spongycastle/crypto/test/RegressionTest.java
@@ -0,0 +1,150 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+public class RegressionTest
+{
+ public static Test[] tests =
+ {
+ new AESTest(),
+ new AESLightTest(),
+ new AESFastTest(),
+ new AESWrapTest(),
+ new DESTest(),
+ new DESedeTest(),
+ new ModeTest(),
+ new PaddingTest(),
+ new DHTest(),
+ new ElGamalTest(),
+ new DSATest(),
+ new ECTest(),
+ new GOST3410Test(),
+ new ECGOST3410Test(),
+ new ECIESTest(),
+ new ECNRTest(),
+ new MacTest(),
+ new GOST28147MacTest(),
+ new RC2Test(),
+ new RC2WrapTest(),
+ new RC4Test(),
+ new RC5Test(),
+ new RC6Test(),
+ new RijndaelTest(),
+ new SerpentTest(),
+ new CamelliaTest(),
+ new CamelliaLightTest(),
+ new DigestRandomNumberTest(),
+ new SkipjackTest(),
+ new BlowfishTest(),
+ new TwofishTest(),
+ new Threefish256Test(),
+ new Threefish512Test(),
+ new Threefish1024Test(),
+ new SkeinDigestTest(),
+ new SkeinMacTest(),
+ new CAST5Test(),
+ new CAST6Test(),
+ new GOST28147Test(),
+ new IDEATest(),
+ new RSATest(),
+ new RSABlindedTest(),
+ new RSADigestSignerTest(),
+ new PSSBlindTest(),
+ new ISO9796Test(),
+ new ISO9797Alg3MacTest(),
+ new MD2DigestTest(),
+ new MD4DigestTest(),
+ new MD5DigestTest(),
+ new SHA1DigestTest(),
+ new SHA224DigestTest(),
+ new SHA256DigestTest(),
+ new SHA384DigestTest(),
+ new SHA512DigestTest(),
+ new SHA512t224DigestTest(),
+ new SHA512t256DigestTest(),
+ new SHA3DigestTest(),
+ new RIPEMD128DigestTest(),
+ new RIPEMD160DigestTest(),
+ new RIPEMD256DigestTest(),
+ new RIPEMD320DigestTest(),
+ new TigerDigestTest(),
+ new GOST3411DigestTest(),
+ new WhirlpoolDigestTest(),
+ new MD5HMacTest(),
+ new SHA1HMacTest(),
+ new SHA224HMacTest(),
+ new SHA256HMacTest(),
+ new SHA384HMacTest(),
+ new SHA512HMacTest(),
+ new RIPEMD128HMacTest(),
+ new RIPEMD160HMacTest(),
+ new OAEPTest(),
+ new PSSTest(),
+ new CTSTest(),
+ new CCMTest(),
+ new PKCS5Test(),
+ new PKCS12Test(),
+ new KDF1GeneratorTest(),
+ new KDF2GeneratorTest(),
+ new MGF1GeneratorTest(),
+ new HKDFGeneratorTest(),
+ new DHKEKGeneratorTest(),
+ new ECDHKEKGeneratorTest(),
+ new ShortenedDigestTest(),
+ new EqualsHashCodeTest(),
+ new TEATest(),
+ new XTEATest(),
+ new RFC3211WrapTest(),
+ new SEEDTest(),
+ new Salsa20Test(),
+ new XSalsa20Test(),
+ new ChaChaTest(),
+ new CMacTest(),
+ new EAXTest(),
+ new GCMTest(),
+ new GMacTest(),
+ new HCFamilyTest(),
+ new HCFamilyVecTest(),
+ new ISAACTest(),
+ new NoekeonTest(),
+ new VMPCKSA3Test(),
+ new VMPCMacTest(),
+ new VMPCTest(),
+ new Grainv1Test(),
+ new Grain128Test(),
+ //new NaccacheSternTest(),
+ new SRP6Test(),
+ new SCryptTest(),
+ new ResetTest(),
+ new NullTest(),
+ new DSTU4145Test(),
+ new SipHashTest(),
+ new Poly1305Test(),
+ new OCBTest(),
+ new NonMemoableDigestTest(),
+ new RSAKeyEncapsulationTest(),
+ new ECIESKeyEncapsulationTest(),
+ new HashCommitmentTest(),
+ new CipherStreamTest(),
+ new BlockCipherResetTest(),
+ new StreamCipherResetTest(),
+ new SM3DigestTest()
+ };
+
+ public static void main(
+ String[] args)
+ {
+ for (int i = 0; i != tests.length; i++)
+ {
+ TestResult result = tests[i].perform();
+
+ if (result.getException() != null)
+ {
+ result.getException().printStackTrace();
+ }
+
+ System.out.println(result);
+ }
+ }
+}
diff --git a/core/src/test/jdk1.3/org/bouncycastle/crypto/test/DSATest.java b/core/src/test/jdk1.3/org/bouncycastle/crypto/test/DSATest.java
deleted file mode 100644
index e0ffe858..00000000
--- a/core/src/test/jdk1.3/org/bouncycastle/crypto/test/DSATest.java
+++ /dev/null
@@ -1,602 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.digests.SHA224Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
-import org.bouncycastle.crypto.generators.DSAKeyPairGenerator;
-import org.bouncycastle.crypto.generators.DSAParametersGenerator;
-import org.bouncycastle.crypto.params.DSAKeyGenerationParameters;
-import org.bouncycastle.crypto.params.DSAParameterGenerationParameters;
-import org.bouncycastle.crypto.params.DSAParameters;
-import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
-import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
-import org.bouncycastle.crypto.params.DSAValidationParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.signers.DSASigner;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.BigIntegers;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.FixedSecureRandom;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * Test based on FIPS 186-2, Appendix 5, an example of DSA, and FIPS 168-3 test vectors.
- */
-public class DSATest
- extends SimpleTest
-{
- byte[] k1 = Hex.decode("d5014e4b60ef2ba8b6211b4062ba3224e0427dd3");
- byte[] k2 = Hex.decode("345e8d05c075c3a508df729a1685690e68fcfb8c8117847e89063bca1f85d968fd281540b6e13bd1af989a1fbf17e06462bf511f9d0b140fb48ac1b1baa5bded");
-
- SecureRandom random = new FixedSecureRandom(new byte[][] { k1, k2});
-
- byte[] keyData = Hex.decode("b5014e4b60ef2ba8b6211b4062ba3224e0427dd3");
-
- SecureRandom keyRandom = new FixedSecureRandom(new byte[][] { keyData, keyData });
-
- BigInteger pValue = new BigInteger("8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291", 16);
- BigInteger qValue = new BigInteger("c773218c737ec8ee993b4f2ded30f48edace915f", 16);
-
- public String getName()
- {
- return "DSA";
- }
-
- public void performTest()
- {
- BigInteger r = new BigInteger("68076202252361894315274692543577577550894681403");
- BigInteger s = new BigInteger("1089214853334067536215539335472893651470583479365");
- DSAParametersGenerator pGen = new DSAParametersGenerator();
-
- pGen.init(512, 20, random);
-
- DSAParameters params = pGen.generateParameters();
- DSAValidationParameters pValid = params.getValidationParameters();
-
- if (pValid.getCounter() != 105)
- {
- fail("Counter wrong");
- }
-
- if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
- {
- fail("p or q wrong");
- }
-
- DSAKeyPairGenerator dsaKeyGen = new DSAKeyPairGenerator();
- DSAKeyGenerationParameters genParam = new DSAKeyGenerationParameters(keyRandom, params);
-
- dsaKeyGen.init(genParam);
-
- AsymmetricCipherKeyPair pair = dsaKeyGen.generateKeyPair();
-
- ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), keyRandom);
-
- DSASigner dsa = new DSASigner();
-
- dsa.init(true, param);
-
- byte[] message = BigIntegers.asUnsignedByteArray(new BigInteger("968236873715988614170569073515315707566766479517"));
- BigInteger[] sig = dsa.generateSignature(message);
-
- if (!r.equals(sig[0]))
- {
- fail("r component wrong.", r, sig[0]);
- }
-
- if (!s.equals(sig[1]))
- {
- fail("s component wrong.", s, sig[1]);
- }
-
- dsa.init(false, pair.getPublic());
-
- if (!dsa.verifySignature(message, sig[0], sig[1]))
- {
- fail("verification fails");
- }
-
- //dsa2Test1();
- //dsa2Test2();
- //dsa2Test3();
- //dsa2Test4();
- }
-
- private void dsa2Test1()
- {
- byte[] seed = Hex.decode("ED8BEE8D1CB89229D2903CBF0E51EE7377F48698");
-
- DSAParametersGenerator pGen = new DSAParametersGenerator();
-
- pGen.init(new DSAParameterGenerationParameters(1024, 160, 10, new DSATestSecureRandom(seed)));
-
- DSAParameters params = pGen.generateParameters();
-
- DSAValidationParameters pv = params.getValidationParameters();
-
- if (pv.getCounter() != 5)
- {
- fail("counter incorrect");
- }
-
- if (!Arrays.areEqual(seed, pv.getSeed()))
- {
- fail("seed incorrect");
- }
-
- if (!params.getQ().equals(new BigInteger("E950511EAB424B9A19A2AEB4E159B7844C589C4F", 16)))
- {
- fail("Q incorrect");
- }
-
- if (!params.getP().equals(new BigInteger(
- "E0A67598CD1B763B" +
- "C98C8ABB333E5DDA0CD3AA0E5E1FB5BA8A7B4EABC10BA338" +
- "FAE06DD4B90FDA70D7CF0CB0C638BE3341BEC0AF8A7330A3" +
- "307DED2299A0EE606DF035177A239C34A912C202AA5F83B9" +
- "C4A7CF0235B5316BFC6EFB9A248411258B30B839AF172440" +
- "F32563056CB67A861158DDD90E6A894C72A5BBEF9E286C6B", 16)))
- {
- fail("P incorrect");
- }
-
- if (!params.getG().equals(new BigInteger(
- "D29D5121B0423C27" +
- "69AB21843E5A3240FF19CACC792264E3BB6BE4F78EDD1B15" +
- "C4DFF7F1D905431F0AB16790E1F773B5CE01C804E509066A" +
- "9919F5195F4ABC58189FD9FF987389CB5BEDF21B4DAB4F8B" +
- "76A055FFE2770988FE2EC2DE11AD92219F0B351869AC24DA" +
- "3D7BA87011A701CE8EE7BFE49486ED4527B7186CA4610A75", 16)))
- {
- fail("G incorrect");
- }
-
- DSAKeyPairGenerator kpGen = new DSAKeyPairGenerator();
-
- kpGen.init(new DSAKeyGenerationParameters(new FixedSecureRandom(Hex.decode("D0EC4E50BB290A42E9E355C73D8809345DE2E139")), params));
-
- AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();
-
- DSAPublicKeyParameters pub = (DSAPublicKeyParameters)kp.getPublic();
- DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)kp.getPrivate();
-
- if (!pub.getY().equals(new BigInteger(
- "25282217F5730501" +
- "DD8DBA3EDFCF349AAFFEC20921128D70FAC44110332201BB" +
- "A3F10986140CBB97C726938060473C8EC97B4731DB004293" +
- "B5E730363609DF9780F8D883D8C4D41DED6A2F1E1BBBDC97" +
- "9E1B9D6D3C940301F4E978D65B19041FCF1E8B518F5C0576" +
- "C770FE5A7A485D8329EE2914A2DE1B5DA4A6128CEAB70F79", 16)))
- {
- fail("Y value incorrect");
- }
-
- if (!priv.getX().equals(
- new BigInteger("D0EC4E50BB290A42E9E355C73D8809345DE2E139", 16)))
- {
- fail("X value incorrect");
- }
-
- DSASigner signer = new DSASigner();
-
- signer.init(true, new ParametersWithRandom(kp.getPrivate(), new FixedSecureRandom(Hex.decode("349C55648DCF992F3F33E8026CFAC87C1D2BA075"))));
-
- byte[] msg = Hex.decode("A9993E364706816ABA3E25717850C26C9CD0D89D");
-
- BigInteger[] sig = signer.generateSignature(msg);
-
- if (!sig[0].equals(new BigInteger("636155AC9A4633B4665D179F9E4117DF68601F34", 16)))
- {
- fail("R value incorrect");
- }
-
- if (!sig[1].equals(new BigInteger("6C540B02D9D4852F89DF8CFC99963204F4347704", 16)))
- {
- fail("S value incorrect");
- }
-
- signer.init(false, kp.getPublic());
-
- if (!signer.verifySignature(msg, sig[0], sig[1]))
- {
- fail("signature not verified");
- }
-
- }
-
- private void dsa2Test2()
- {
- byte[] seed = Hex.decode("5AFCC1EFFC079A9CCA6ECA86D6E3CC3B18642D9BE1CC6207C84002A9");
-
- DSAParametersGenerator pGen = new DSAParametersGenerator(new SHA224Digest());
-
- pGen.init(new DSAParameterGenerationParameters(2048, 224, 10, new DSATestSecureRandom(seed)));
-
- DSAParameters params = pGen.generateParameters();
-
- DSAValidationParameters pv = params.getValidationParameters();
-
- if (pv.getCounter() != 21)
- {
- fail("counter incorrect");
- }
-
- if (!Arrays.areEqual(seed, pv.getSeed()))
- {
- fail("seed incorrect");
- }
-
- if (!params.getQ().equals(new BigInteger("90EAF4D1AF0708B1B612FF35E0A2997EB9E9D263C9CE659528945C0D", 16)))
- {
- fail("Q incorrect");
- }
-
- if (!params.getP().equals(new BigInteger(
- "C196BA05AC29E1F9C3C72D56DFFC6154" +
- "A033F1477AC88EC37F09BE6C5BB95F51C296DD20D1A28A06" +
- "7CCC4D4316A4BD1DCA55ED1066D438C35AEBAABF57E7DAE4" +
- "28782A95ECA1C143DB701FD48533A3C18F0FE23557EA7AE6" +
- "19ECACC7E0B51652A8776D02A425567DED36EABD90CA33A1" +
- "E8D988F0BBB92D02D1D20290113BB562CE1FC856EEB7CDD9" +
- "2D33EEA6F410859B179E7E789A8F75F645FAE2E136D252BF" +
- "FAFF89528945C1ABE705A38DBC2D364AADE99BE0D0AAD82E" +
- "5320121496DC65B3930E38047294FF877831A16D5228418D" +
- "E8AB275D7D75651CEFED65F78AFC3EA7FE4D79B35F62A040" +
- "2A1117599ADAC7B269A59F353CF450E6982D3B1702D9CA83", 16)))
- {
- fail("P incorrect");
- }
-
- if (!params.getG().equals(new BigInteger(
- "A59A749A11242C58C894E9E5A91804E8"+
- "FA0AC64B56288F8D47D51B1EDC4D65444FECA0111D78F35F"+
- "C9FDD4CB1F1B79A3BA9CBEE83A3F811012503C8117F98E50"+
- "48B089E387AF6949BF8784EBD9EF45876F2E6A5A495BE64B"+
- "6E770409494B7FEE1DBB1E4B2BC2A53D4F893D418B715959"+
- "2E4FFFDF6969E91D770DAEBD0B5CB14C00AD68EC7DC1E574"+
- "5EA55C706C4A1C5C88964E34D09DEB753AD418C1AD0F4FDF"+
- "D049A955E5D78491C0B7A2F1575A008CCD727AB376DB6E69"+
- "5515B05BD412F5B8C2F4C77EE10DA48ABD53F5DD498927EE"+
- "7B692BBBCDA2FB23A516C5B4533D73980B2A3B60E384ED20"+
- "0AE21B40D273651AD6060C13D97FD69AA13C5611A51B9085", 16)))
- {
- fail("G incorrect");
- }
-
- DSAKeyPairGenerator kpGen = new DSAKeyPairGenerator();
-
- kpGen.init(new DSAKeyGenerationParameters(new FixedSecureRandom(Hex.decode("00D0F09ED3E2568F6CADF9224117DA2AEC5A4300E009DE1366023E17")), params));
-
- AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();
-
- DSAPublicKeyParameters pub = (DSAPublicKeyParameters)kp.getPublic();
- DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)kp.getPrivate();
-
- if (!pub.getY().equals(new BigInteger(
- "70035C9A3B225B258F16741F3941FBF0" +
- "6F3D056CD7BD864604CBB5EE9DD85304EE8E8E4ABD5E9032" +
- "11DDF25CE149075510ACE166970AFDC7DF552B7244F342FA" +
- "02F7A621405B754909D757F97290E1FE5036E904CF593446" +
- "0C046D95659821E1597ED9F2B1F0E20863A6BBD0CE74DACB" +
- "A5D8C68A90B29C2157CDEDB82EC12B81EE3068F9BF5F7F34" +
- "6ECA41ED174CCCD7D154FA4F42F80FFE1BF46AE9D8125DEB" +
- "5B4BA08A72BDD86596DBEDDC9550FDD650C58F5AE5133509" +
- "A702F79A31ECB490F7A3C5581631F7C5BE4FF7F9E9F27FA3" +
- "90E47347AD1183509FED6FCF198BA9A71AB3335B4F38BE8D" +
- "15496A00B6DC2263E20A5F6B662320A3A1EC033AA61E3B68", 16)))
- {
- fail("Y value incorrect");
- }
-
- if (!priv.getX().equals(
- new BigInteger("00D0F09ED3E2568F6CADF9224117DA2AEC5A4300E009DE1366023E17", 16)))
- {
- fail("X value incorrect");
- }
-
- DSASigner signer = new DSASigner();
-
- signer.init(true, new ParametersWithRandom(kp.getPrivate(), new FixedSecureRandom(Hex.decode("735959CC4463B8B440E407EECA8A473BF6A6D1FE657546F67D401F05"))));
-
- byte[] msg = Hex.decode("23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7");
-
- BigInteger[] sig = signer.generateSignature(msg);
-
- if (!sig[0].equals(new BigInteger("4400138D05F9639CAF54A583CAAF25D2B76D0C3EAD752CE17DBC85FE", 16)))
- {
- fail("R value incorrect");
- }
-
- if (!sig[1].equals(new BigInteger("874D4F12CB13B61732D398445698CFA9D92381D938AA57EE2C9327B3", 16)))
- {
- fail("S value incorrect");
- }
-
- signer.init(false, kp.getPublic());
-
- if (!signer.verifySignature(msg, sig[0], sig[1]))
- {
- fail("signature not verified");
- }
- }
-
- private void dsa2Test3()
- {
- byte[] seed = Hex.decode("4783081972865EA95D43318AB2EAF9C61A2FC7BBF1B772A09017BDF5A58F4FF0");
-
- DSAParametersGenerator pGen = new DSAParametersGenerator(new SHA256Digest());
-
- pGen.init(new DSAParameterGenerationParameters(2048, 256, 10, new DSATestSecureRandom(seed)));
-
- DSAParameters params = pGen.generateParameters();
-
- DSAValidationParameters pv = params.getValidationParameters();
-
- if (pv.getCounter() != 12)
- {
- fail("counter incorrect");
- }
-
- if (!Arrays.areEqual(seed, pv.getSeed()))
- {
- fail("seed incorrect");
- }
-
- if (!params.getQ().equals(new BigInteger("C24ED361870B61E0D367F008F99F8A1F75525889C89DB1B673C45AF5867CB467", 16)))
- {
- fail("Q incorrect");
- }
-
- if (!params.getP().equals(new BigInteger(
- "F56C2A7D366E3EBDEAA1891FD2A0D099" +
- "436438A673FED4D75F594959CFFEBCA7BE0FC72E4FE67D91" +
- "D801CBA0693AC4ED9E411B41D19E2FD1699C4390AD27D94C" +
- "69C0B143F1DC88932CFE2310C886412047BD9B1C7A67F8A2" +
- "5909132627F51A0C866877E672E555342BDF9355347DBD43" +
- "B47156B2C20BAD9D2B071BC2FDCF9757F75C168C5D9FC431" +
- "31BE162A0756D1BDEC2CA0EB0E3B018A8B38D3EF2487782A" +
- "EB9FBF99D8B30499C55E4F61E5C7DCEE2A2BB55BD7F75FCD" +
- "F00E48F2E8356BDB59D86114028F67B8E07B127744778AFF" +
- "1CF1399A4D679D92FDE7D941C5C85C5D7BFF91BA69F9489D" +
- "531D1EBFA727CFDA651390F8021719FA9F7216CEB177BD75", 16)))
- {
- fail("P incorrect");
- }
-
- if (!params.getG().equals(new BigInteger(
- "8DC6CC814CAE4A1C05A3E186A6FE27EA" +
- "BA8CDB133FDCE14A963A92E809790CBA096EAA26140550C1" +
- "29FA2B98C16E84236AA33BF919CD6F587E048C52666576DB" +
- "6E925C6CBE9B9EC5C16020F9A44C9F1C8F7A8E611C1F6EC2" +
- "513EA6AA0B8D0F72FED73CA37DF240DB57BBB27431D61869" +
- "7B9E771B0B301D5DF05955425061A30DC6D33BB6D2A32BD0" +
- "A75A0A71D2184F506372ABF84A56AEEEA8EB693BF29A6403" +
- "45FA1298A16E85421B2208D00068A5A42915F82CF0B858C8" +
- "FA39D43D704B6927E0B2F916304E86FB6A1B487F07D8139E" +
- "428BB096C6D67A76EC0B8D4EF274B8A2CF556D279AD267CC" +
- "EF5AF477AFED029F485B5597739F5D0240F67C2D948A6279", 16)))
- {
- fail("G incorrect");
- }
-
- DSAKeyPairGenerator kpGen = new DSAKeyPairGenerator();
-
- kpGen.init(new DSAKeyGenerationParameters(new FixedSecureRandom(Hex.decode("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C")), params));
-
- AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();
-
- DSAPublicKeyParameters pub = (DSAPublicKeyParameters)kp.getPublic();
- DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)kp.getPrivate();
-
- if (!pub.getY().equals(new BigInteger(
- "2828003D7C747199143C370FDD07A286" +
- "1524514ACC57F63F80C38C2087C6B795B62DE1C224BF8D1D" +
- "1424E60CE3F5AE3F76C754A2464AF292286D873A7A30B7EA" +
- "CBBC75AAFDE7191D9157598CDB0B60E0C5AA3F6EBE425500" +
- "C611957DBF5ED35490714A42811FDCDEB19AF2AB30BEADFF" +
- "2907931CEE7F3B55532CFFAEB371F84F01347630EB227A41" +
- "9B1F3F558BC8A509D64A765D8987D493B007C4412C297CAF" +
- "41566E26FAEE475137EC781A0DC088A26C8804A98C23140E" +
- "7C936281864B99571EE95C416AA38CEEBB41FDBFF1EB1D1D" +
- "C97B63CE1355257627C8B0FD840DDB20ED35BE92F08C49AE" +
- "A5613957D7E5C7A6D5A5834B4CB069E0831753ECF65BA02B", 16)))
- {
- fail("Y value incorrect");
- }
-
- if (!priv.getX().equals(
- new BigInteger("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C", 16)))
- {
- fail("X value incorrect");
- }
-
- DSASigner signer = new DSASigner();
-
- signer.init(true, new ParametersWithRandom(kp.getPrivate(), new FixedSecureRandom(Hex.decode("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C"))));
-
- byte[] msg = Hex.decode("BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD");
-
- BigInteger[] sig = signer.generateSignature(msg);
-
- if (!sig[0].equals(new BigInteger("315C875DCD4850E948B8AC42824E9483A32D5BA5ABE0681B9B9448D444F2BE3C", 16)))
- {
- fail("R value incorrect");
- }
-
- if (!sig[1].equals(new BigInteger("89718D12E54A8D9ED066E4A55F7ED5A2229CD23B9A3CEE78F83ED6AA61F6BCB9", 16)))
- {
- fail("S value incorrect");
- }
-
- signer.init(false, kp.getPublic());
-
- if (!signer.verifySignature(msg, sig[0], sig[1]))
- {
- fail("signature not verified");
- }
- }
-
- private void dsa2Test4()
- {
- byte[] seed = Hex.decode("193AFCA7C1E77B3C1ECC618C81322E47B8B8B997C9C83515C59CC446C2D9BD47");
-
- DSAParametersGenerator pGen = new DSAParametersGenerator(new SHA256Digest());
-
- pGen.init(new DSAParameterGenerationParameters(3072, 256, 10, new DSATestSecureRandom(seed)));
-
- DSAParameters params = pGen.generateParameters();
-
- DSAValidationParameters pv = params.getValidationParameters();
-
- if (pv.getCounter() != 20)
- {
- fail("counter incorrect");
- }
-
- if (!Arrays.areEqual(seed, pv.getSeed()))
- {
- fail("seed incorrect");
- }
-
- if (!params.getQ().equals(new BigInteger("CFA0478A54717B08CE64805B76E5B14249A77A4838469DF7F7DC987EFCCFB11D", 16)))
- {
- fail("Q incorrect");
- }
-
- if (!params.getP().equals(new BigInteger(
- "90066455B5CFC38F9CAA4A48B4281F292C260FEEF01FD610" +
- "37E56258A7795A1C7AD46076982CE6BB956936C6AB4DCFE0" +
- "5E6784586940CA544B9B2140E1EB523F009D20A7E7880E4E" +
- "5BFA690F1B9004A27811CD9904AF70420EEFD6EA11EF7DA1" +
- "29F58835FF56B89FAA637BC9AC2EFAAB903402229F491D8D" +
- "3485261CD068699B6BA58A1DDBBEF6DB51E8FE34E8A78E54" +
- "2D7BA351C21EA8D8F1D29F5D5D15939487E27F4416B0CA63" +
- "2C59EFD1B1EB66511A5A0FBF615B766C5862D0BD8A3FE7A0" +
- "E0DA0FB2FE1FCB19E8F9996A8EA0FCCDE538175238FC8B0E" +
- "E6F29AF7F642773EBE8CD5402415A01451A840476B2FCEB0" +
- "E388D30D4B376C37FE401C2A2C2F941DAD179C540C1C8CE0" +
- "30D460C4D983BE9AB0B20F69144C1AE13F9383EA1C08504F" +
- "B0BF321503EFE43488310DD8DC77EC5B8349B8BFE97C2C56" +
- "0EA878DE87C11E3D597F1FEA742D73EEC7F37BE43949EF1A" +
- "0D15C3F3E3FC0A8335617055AC91328EC22B50FC15B941D3" +
- "D1624CD88BC25F3E941FDDC6200689581BFEC416B4B2CB73", 16)))
- {
- fail("P incorrect");
- }
-
- if (!params.getG().equals(new BigInteger(
- "5E5CBA992E0A680D885EB903AEA78E4A45A469103D448EDE" +
- "3B7ACCC54D521E37F84A4BDD5B06B0970CC2D2BBB715F7B8" +
- "2846F9A0C393914C792E6A923E2117AB805276A975AADB52" +
- "61D91673EA9AAFFEECBFA6183DFCB5D3B7332AA19275AFA1" +
- "F8EC0B60FB6F66CC23AE4870791D5982AAD1AA9485FD8F4A" +
- "60126FEB2CF05DB8A7F0F09B3397F3937F2E90B9E5B9C9B6" +
- "EFEF642BC48351C46FB171B9BFA9EF17A961CE96C7E7A7CC" +
- "3D3D03DFAD1078BA21DA425198F07D2481622BCE45969D9C" +
- "4D6063D72AB7A0F08B2F49A7CC6AF335E08C4720E31476B6" +
- "7299E231F8BD90B39AC3AE3BE0C6B6CACEF8289A2E2873D5" +
- "8E51E029CAFBD55E6841489AB66B5B4B9BA6E2F784660896" +
- "AFF387D92844CCB8B69475496DE19DA2E58259B090489AC8" +
- "E62363CDF82CFD8EF2A427ABCD65750B506F56DDE3B98856" +
- "7A88126B914D7828E2B63A6D7ED0747EC59E0E0A23CE7D8A" +
- "74C1D2C2A7AFB6A29799620F00E11C33787F7DED3B30E1A2" +
- "2D09F1FBDA1ABBBFBF25CAE05A13F812E34563F99410E73B", 16)))
- {
- fail("G incorrect");
- }
-
- DSAKeyPairGenerator kpGen = new DSAKeyPairGenerator();
-
- kpGen.init(new DSAKeyGenerationParameters(new FixedSecureRandom(Hex.decode("3ABC1587297CE7B9EA1AD6651CF2BC4D7F92ED25CABC8553F567D1B40EBB8764")), params));
-
- AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();
-
- DSAPublicKeyParameters pub = (DSAPublicKeyParameters)kp.getPublic();
- DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)kp.getPrivate();
-
- if (!pub.getY().equals(new BigInteger(
- "8B891C8692D3DE875879390F2698B26FBECCA6B075535DCE" +
- "6B0C862577F9FA0DEF6074E7A7624121224A595896ABD4CD" +
- "A56B2CEFB942E025D2A4282FFAA98A48CDB47E1A6FCB5CFB" +
- "393EF35AF9DF913102BB303C2B5C36C3F8FC04ED7B8B69FE" +
- "FE0CF3E1FC05CFA713B3435B2656E913BA8874AEA9F93600" +
- "6AEB448BCD005D18EC3562A33D04CF25C8D3D69844343442" +
- "FA3DB7DE618C5E2DA064573E61E6D5581BFB694A23AC87FD" +
- "5B52D62E954E1376DB8DDB524FFC0D469DF978792EE44173" +
- "8E5DB05A7DC43E94C11A2E7A4FBE383071FA36D2A7EC8A93" +
- "88FE1C4F79888A99D3B6105697C2556B79BB4D7E781CEBB3" +
- "D4866AD825A5E830846072289FDBC941FA679CA82F5F78B7" +
- "461B2404DB883D215F4E0676CF5493950AC5591697BFEA8D" +
- "1EE6EC016B89BA51CAFB5F9C84C989FA117375E94578F28B" +
- "E0B34CE0545DA46266FD77F62D8F2CEE92AB77012AFEBC11" +
- "008985A821CD2D978C7E6FE7499D1AAF8DE632C21BB48CA5" +
- "CBF9F31098FD3FD3854C49A65D9201744AACE540354974F9", 16)))
- {
- fail("Y value incorrect");
- }
-
- if (!priv.getX().equals(
- new BigInteger("3ABC1587297CE7B9EA1AD6651CF2BC4D7F92ED25CABC8553F567D1B40EBB8764", 16)))
- {
- fail("X value incorrect");
- }
-
- DSASigner signer = new DSASigner();
-
- signer.init(true, new ParametersWithRandom(kp.getPrivate(), new FixedSecureRandom(Hex.decode("A6902C1E6E3943C5628061588A8B007BCCEA91DBF12915483F04B24AB0678BEE"))));
-
- byte[] msg = Hex.decode("BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD");
-
- BigInteger[] sig = signer.generateSignature(msg);
-
- if (!sig[0].equals(new BigInteger("5F184E645A38BE8FB4A6871B6503A9D12924C7ABE04B71410066C2ECA6E3BE3E", 16)))
- {
- fail("R value incorrect");
- }
-
- if (!sig[1].equals(new BigInteger("91EB0C7BA3D4B9B60B825C3D9F2CADA8A2C9D7723267B033CBCDCF8803DB9C18", 16)))
- {
- fail("S value incorrect");
- }
-
- signer.init(false, kp.getPublic());
-
- if (!signer.verifySignature(msg, sig[0], sig[1]))
- {
- fail("signature not verified");
- }
- }
-
- public static void main(
- String[] args)
- {
- runTest(new DSATest());
- }
-
- private class DSATestSecureRandom
- extends FixedSecureRandom
- {
- private boolean first = true;
-
- public DSATestSecureRandom(byte[] value)
- {
- super(value);
- }
-
- public void nextBytes(byte[] bytes)
- {
- if (first)
- {
- super.nextBytes(bytes);
- first = false;
- }
- else
- {
- bytes[bytes.length - 1] = 2;
- }
- }
- }
-}
diff --git a/core/src/test/jdk1.3/org/bouncycastle/i18n/test/AllTests.java b/core/src/test/jdk1.3/org/bouncycastle/i18n/test/AllTests.java
deleted file mode 100644
index 28239554..00000000
--- a/core/src/test/jdk1.3/org/bouncycastle/i18n/test/AllTests.java
+++ /dev/null
@@ -1,27 +0,0 @@
-
-package org.bouncycastle.i18n.test;
-
-import org.bouncycastle.i18n.filter.test.HTMLFilterTest;
-import org.bouncycastle.i18n.filter.test.SQLFilterTest;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-public class AllTests extends TestCase
-{
-
- public static void main (String[] args)
- {
- junit.textui.TestRunner.run (suite());
- }
-
- public static Test suite()
- {
- TestSuite suite = new TestSuite("i18n tests");
- suite.addTestSuite(HTMLFilterTest.class);
- suite.addTestSuite(SQLFilterTest.class);
- return suite;
- }
-
-}
diff --git a/core/src/test/jdk1.3/org/spongycastle/crypto/test/DSATest.java b/core/src/test/jdk1.3/org/spongycastle/crypto/test/DSATest.java
new file mode 100644
index 00000000..d1d835d8
--- /dev/null
+++ b/core/src/test/jdk1.3/org/spongycastle/crypto/test/DSATest.java
@@ -0,0 +1,602 @@
+package org.spongycastle.crypto.test;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.crypto.digests.SHA224Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.generators.DSAKeyPairGenerator;
+import org.spongycastle.crypto.generators.DSAParametersGenerator;
+import org.spongycastle.crypto.params.DSAKeyGenerationParameters;
+import org.spongycastle.crypto.params.DSAParameterGenerationParameters;
+import org.spongycastle.crypto.params.DSAParameters;
+import org.spongycastle.crypto.params.DSAPrivateKeyParameters;
+import org.spongycastle.crypto.params.DSAPublicKeyParameters;
+import org.spongycastle.crypto.params.DSAValidationParameters;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.crypto.signers.DSASigner;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.BigIntegers;
+import org.spongycastle.util.encoders.Hex;
+import org.spongycastle.util.test.FixedSecureRandom;
+import org.spongycastle.util.test.SimpleTest;
+
+/**
+ * Test based on FIPS 186-2, Appendix 5, an example of DSA, and FIPS 168-3 test vectors.
+ */
+public class DSATest
+ extends SimpleTest
+{
+ byte[] k1 = Hex.decode("d5014e4b60ef2ba8b6211b4062ba3224e0427dd3");
+ byte[] k2 = Hex.decode("345e8d05c075c3a508df729a1685690e68fcfb8c8117847e89063bca1f85d968fd281540b6e13bd1af989a1fbf17e06462bf511f9d0b140fb48ac1b1baa5bded");
+
+ SecureRandom random = new FixedSecureRandom(new byte[][] { k1, k2});
+
+ byte[] keyData = Hex.decode("b5014e4b60ef2ba8b6211b4062ba3224e0427dd3");
+
+ SecureRandom keyRandom = new FixedSecureRandom(new byte[][] { keyData, keyData });
+
+ BigInteger pValue = new BigInteger("8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291", 16);
+ BigInteger qValue = new BigInteger("c773218c737ec8ee993b4f2ded30f48edace915f", 16);
+
+ public String getName()
+ {
+ return "DSA";
+ }
+
+ public void performTest()
+ {
+ BigInteger r = new BigInteger("68076202252361894315274692543577577550894681403");
+ BigInteger s = new BigInteger("1089214853334067536215539335472893651470583479365");
+ DSAParametersGenerator pGen = new DSAParametersGenerator();
+
+ pGen.init(512, 20, random);
+
+ DSAParameters params = pGen.generateParameters();
+ DSAValidationParameters pValid = params.getValidationParameters();
+
+ if (pValid.getCounter() != 105)
+ {
+ fail("Counter wrong");
+ }
+
+ if (!pValue.equals(params.getP()) || !qValue.equals(params.getQ()))
+ {
+ fail("p or q wrong");
+ }
+
+ DSAKeyPairGenerator dsaKeyGen = new DSAKeyPairGenerator();
+ DSAKeyGenerationParameters genParam = new DSAKeyGenerationParameters(keyRandom, params);
+
+ dsaKeyGen.init(genParam);
+
+ AsymmetricCipherKeyPair pair = dsaKeyGen.generateKeyPair();
+
+ ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), keyRandom);
+
+ DSASigner dsa = new DSASigner();
+
+ dsa.init(true, param);
+
+ byte[] message = BigIntegers.asUnsignedByteArray(new BigInteger("968236873715988614170569073515315707566766479517"));
+ BigInteger[] sig = dsa.generateSignature(message);
+
+ if (!r.equals(sig[0]))
+ {
+ fail("r component wrong.", r, sig[0]);
+ }
+
+ if (!s.equals(sig[1]))
+ {
+ fail("s component wrong.", s, sig[1]);
+ }
+
+ dsa.init(false, pair.getPublic());
+
+ if (!dsa.verifySignature(message, sig[0], sig[1]))
+ {
+ fail("verification fails");
+ }
+
+ //dsa2Test1();
+ //dsa2Test2();
+ //dsa2Test3();
+ //dsa2Test4();
+ }
+
+ private void dsa2Test1()
+ {
+ byte[] seed = Hex.decode("ED8BEE8D1CB89229D2903CBF0E51EE7377F48698");
+
+ DSAParametersGenerator pGen = new DSAParametersGenerator();
+
+ pGen.init(new DSAParameterGenerationParameters(1024, 160, 10, new DSATestSecureRandom(seed)));
+
+ DSAParameters params = pGen.generateParameters();
+
+ DSAValidationParameters pv = params.getValidationParameters();
+
+ if (pv.getCounter() != 5)
+ {
+ fail("counter incorrect");
+ }
+
+ if (!Arrays.areEqual(seed, pv.getSeed()))
+ {
+ fail("seed incorrect");
+ }
+
+ if (!params.getQ().equals(new BigInteger("E950511EAB424B9A19A2AEB4E159B7844C589C4F", 16)))
+ {
+ fail("Q incorrect");
+ }
+
+ if (!params.getP().equals(new BigInteger(
+ "E0A67598CD1B763B" +
+ "C98C8ABB333E5DDA0CD3AA0E5E1FB5BA8A7B4EABC10BA338" +
+ "FAE06DD4B90FDA70D7CF0CB0C638BE3341BEC0AF8A7330A3" +
+ "307DED2299A0EE606DF035177A239C34A912C202AA5F83B9" +
+ "C4A7CF0235B5316BFC6EFB9A248411258B30B839AF172440" +
+ "F32563056CB67A861158DDD90E6A894C72A5BBEF9E286C6B", 16)))
+ {
+ fail("P incorrect");
+ }
+
+ if (!params.getG().equals(new BigInteger(
+ "D29D5121B0423C27" +
+ "69AB21843E5A3240FF19CACC792264E3BB6BE4F78EDD1B15" +
+ "C4DFF7F1D905431F0AB16790E1F773B5CE01C804E509066A" +
+ "9919F5195F4ABC58189FD9FF987389CB5BEDF21B4DAB4F8B" +
+ "76A055FFE2770988FE2EC2DE11AD92219F0B351869AC24DA" +
+ "3D7BA87011A701CE8EE7BFE49486ED4527B7186CA4610A75", 16)))
+ {
+ fail("G incorrect");
+ }
+
+ DSAKeyPairGenerator kpGen = new DSAKeyPairGenerator();
+
+ kpGen.init(new DSAKeyGenerationParameters(new FixedSecureRandom(Hex.decode("D0EC4E50BB290A42E9E355C73D8809345DE2E139")), params));
+
+ AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();
+
+ DSAPublicKeyParameters pub = (DSAPublicKeyParameters)kp.getPublic();
+ DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)kp.getPrivate();
+
+ if (!pub.getY().equals(new BigInteger(
+ "25282217F5730501" +
+ "DD8DBA3EDFCF349AAFFEC20921128D70FAC44110332201BB" +
+ "A3F10986140CBB97C726938060473C8EC97B4731DB004293" +
+ "B5E730363609DF9780F8D883D8C4D41DED6A2F1E1BBBDC97" +
+ "9E1B9D6D3C940301F4E978D65B19041FCF1E8B518F5C0576" +
+ "C770FE5A7A485D8329EE2914A2DE1B5DA4A6128CEAB70F79", 16)))
+ {
+ fail("Y value incorrect");
+ }
+
+ if (!priv.getX().equals(
+ new BigInteger("D0EC4E50BB290A42E9E355C73D8809345DE2E139", 16)))
+ {
+ fail("X value incorrect");
+ }
+
+ DSASigner signer = new DSASigner();
+
+ signer.init(true, new ParametersWithRandom(kp.getPrivate(), new FixedSecureRandom(Hex.decode("349C55648DCF992F3F33E8026CFAC87C1D2BA075"))));
+
+ byte[] msg = Hex.decode("A9993E364706816ABA3E25717850C26C9CD0D89D");
+
+ BigInteger[] sig = signer.generateSignature(msg);
+
+ if (!sig[0].equals(new BigInteger("636155AC9A4633B4665D179F9E4117DF68601F34", 16)))
+ {
+ fail("R value incorrect");
+ }
+
+ if (!sig[1].equals(new BigInteger("6C540B02D9D4852F89DF8CFC99963204F4347704", 16)))
+ {
+ fail("S value incorrect");
+ }
+
+ signer.init(false, kp.getPublic());
+
+ if (!signer.verifySignature(msg, sig[0], sig[1]))
+ {
+ fail("signature not verified");
+ }
+
+ }
+
+ private void dsa2Test2()
+ {
+ byte[] seed = Hex.decode("5AFCC1EFFC079A9CCA6ECA86D6E3CC3B18642D9BE1CC6207C84002A9");
+
+ DSAParametersGenerator pGen = new DSAParametersGenerator(new SHA224Digest());
+
+ pGen.init(new DSAParameterGenerationParameters(2048, 224, 10, new DSATestSecureRandom(seed)));
+
+ DSAParameters params = pGen.generateParameters();
+
+ DSAValidationParameters pv = params.getValidationParameters();
+
+ if (pv.getCounter() != 21)
+ {
+ fail("counter incorrect");
+ }
+
+ if (!Arrays.areEqual(seed, pv.getSeed()))
+ {
+ fail("seed incorrect");
+ }
+
+ if (!params.getQ().equals(new BigInteger("90EAF4D1AF0708B1B612FF35E0A2997EB9E9D263C9CE659528945C0D", 16)))
+ {
+ fail("Q incorrect");
+ }
+
+ if (!params.getP().equals(new BigInteger(
+ "C196BA05AC29E1F9C3C72D56DFFC6154" +
+ "A033F1477AC88EC37F09BE6C5BB95F51C296DD20D1A28A06" +
+ "7CCC4D4316A4BD1DCA55ED1066D438C35AEBAABF57E7DAE4" +
+ "28782A95ECA1C143DB701FD48533A3C18F0FE23557EA7AE6" +
+ "19ECACC7E0B51652A8776D02A425567DED36EABD90CA33A1" +
+ "E8D988F0BBB92D02D1D20290113BB562CE1FC856EEB7CDD9" +
+ "2D33EEA6F410859B179E7E789A8F75F645FAE2E136D252BF" +
+ "FAFF89528945C1ABE705A38DBC2D364AADE99BE0D0AAD82E" +
+ "5320121496DC65B3930E38047294FF877831A16D5228418D" +
+ "E8AB275D7D75651CEFED65F78AFC3EA7FE4D79B35F62A040" +
+ "2A1117599ADAC7B269A59F353CF450E6982D3B1702D9CA83", 16)))
+ {
+ fail("P incorrect");
+ }
+
+ if (!params.getG().equals(new BigInteger(
+ "A59A749A11242C58C894E9E5A91804E8"+
+ "FA0AC64B56288F8D47D51B1EDC4D65444FECA0111D78F35F"+
+ "C9FDD4CB1F1B79A3BA9CBEE83A3F811012503C8117F98E50"+
+ "48B089E387AF6949BF8784EBD9EF45876F2E6A5A495BE64B"+
+ "6E770409494B7FEE1DBB1E4B2BC2A53D4F893D418B715959"+
+ "2E4FFFDF6969E91D770DAEBD0B5CB14C00AD68EC7DC1E574"+
+ "5EA55C706C4A1C5C88964E34D09DEB753AD418C1AD0F4FDF"+
+ "D049A955E5D78491C0B7A2F1575A008CCD727AB376DB6E69"+
+ "5515B05BD412F5B8C2F4C77EE10DA48ABD53F5DD498927EE"+
+ "7B692BBBCDA2FB23A516C5B4533D73980B2A3B60E384ED20"+
+ "0AE21B40D273651AD6060C13D97FD69AA13C5611A51B9085", 16)))
+ {
+ fail("G incorrect");
+ }
+
+ DSAKeyPairGenerator kpGen = new DSAKeyPairGenerator();
+
+ kpGen.init(new DSAKeyGenerationParameters(new FixedSecureRandom(Hex.decode("00D0F09ED3E2568F6CADF9224117DA2AEC5A4300E009DE1366023E17")), params));
+
+ AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();
+
+ DSAPublicKeyParameters pub = (DSAPublicKeyParameters)kp.getPublic();
+ DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)kp.getPrivate();
+
+ if (!pub.getY().equals(new BigInteger(
+ "70035C9A3B225B258F16741F3941FBF0" +
+ "6F3D056CD7BD864604CBB5EE9DD85304EE8E8E4ABD5E9032" +
+ "11DDF25CE149075510ACE166970AFDC7DF552B7244F342FA" +
+ "02F7A621405B754909D757F97290E1FE5036E904CF593446" +
+ "0C046D95659821E1597ED9F2B1F0E20863A6BBD0CE74DACB" +
+ "A5D8C68A90B29C2157CDEDB82EC12B81EE3068F9BF5F7F34" +
+ "6ECA41ED174CCCD7D154FA4F42F80FFE1BF46AE9D8125DEB" +
+ "5B4BA08A72BDD86596DBEDDC9550FDD650C58F5AE5133509" +
+ "A702F79A31ECB490F7A3C5581631F7C5BE4FF7F9E9F27FA3" +
+ "90E47347AD1183509FED6FCF198BA9A71AB3335B4F38BE8D" +
+ "15496A00B6DC2263E20A5F6B662320A3A1EC033AA61E3B68", 16)))
+ {
+ fail("Y value incorrect");
+ }
+
+ if (!priv.getX().equals(
+ new BigInteger("00D0F09ED3E2568F6CADF9224117DA2AEC5A4300E009DE1366023E17", 16)))
+ {
+ fail("X value incorrect");
+ }
+
+ DSASigner signer = new DSASigner();
+
+ signer.init(true, new ParametersWithRandom(kp.getPrivate(), new FixedSecureRandom(Hex.decode("735959CC4463B8B440E407EECA8A473BF6A6D1FE657546F67D401F05"))));
+
+ byte[] msg = Hex.decode("23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7");
+
+ BigInteger[] sig = signer.generateSignature(msg);
+
+ if (!sig[0].equals(new BigInteger("4400138D05F9639CAF54A583CAAF25D2B76D0C3EAD752CE17DBC85FE", 16)))
+ {
+ fail("R value incorrect");
+ }
+
+ if (!sig[1].equals(new BigInteger("874D4F12CB13B61732D398445698CFA9D92381D938AA57EE2C9327B3", 16)))
+ {
+ fail("S value incorrect");
+ }
+
+ signer.init(false, kp.getPublic());
+
+ if (!signer.verifySignature(msg, sig[0], sig[1]))
+ {
+ fail("signature not verified");
+ }
+ }
+
+ private void dsa2Test3()
+ {
+ byte[] seed = Hex.decode("4783081972865EA95D43318AB2EAF9C61A2FC7BBF1B772A09017BDF5A58F4FF0");
+
+ DSAParametersGenerator pGen = new DSAParametersGenerator(new SHA256Digest());
+
+ pGen.init(new DSAParameterGenerationParameters(2048, 256, 10, new DSATestSecureRandom(seed)));
+
+ DSAParameters params = pGen.generateParameters();
+
+ DSAValidationParameters pv = params.getValidationParameters();
+
+ if (pv.getCounter() != 12)
+ {
+ fail("counter incorrect");
+ }
+
+ if (!Arrays.areEqual(seed, pv.getSeed()))
+ {
+ fail("seed incorrect");
+ }
+
+ if (!params.getQ().equals(new BigInteger("C24ED361870B61E0D367F008F99F8A1F75525889C89DB1B673C45AF5867CB467", 16)))
+ {
+ fail("Q incorrect");
+ }
+
+ if (!params.getP().equals(new BigInteger(
+ "F56C2A7D366E3EBDEAA1891FD2A0D099" +
+ "436438A673FED4D75F594959CFFEBCA7BE0FC72E4FE67D91" +
+ "D801CBA0693AC4ED9E411B41D19E2FD1699C4390AD27D94C" +
+ "69C0B143F1DC88932CFE2310C886412047BD9B1C7A67F8A2" +
+ "5909132627F51A0C866877E672E555342BDF9355347DBD43" +
+ "B47156B2C20BAD9D2B071BC2FDCF9757F75C168C5D9FC431" +
+ "31BE162A0756D1BDEC2CA0EB0E3B018A8B38D3EF2487782A" +
+ "EB9FBF99D8B30499C55E4F61E5C7DCEE2A2BB55BD7F75FCD" +
+ "F00E48F2E8356BDB59D86114028F67B8E07B127744778AFF" +
+ "1CF1399A4D679D92FDE7D941C5C85C5D7BFF91BA69F9489D" +
+ "531D1EBFA727CFDA651390F8021719FA9F7216CEB177BD75", 16)))
+ {
+ fail("P incorrect");
+ }
+
+ if (!params.getG().equals(new BigInteger(
+ "8DC6CC814CAE4A1C05A3E186A6FE27EA" +
+ "BA8CDB133FDCE14A963A92E809790CBA096EAA26140550C1" +
+ "29FA2B98C16E84236AA33BF919CD6F587E048C52666576DB" +
+ "6E925C6CBE9B9EC5C16020F9A44C9F1C8F7A8E611C1F6EC2" +
+ "513EA6AA0B8D0F72FED73CA37DF240DB57BBB27431D61869" +
+ "7B9E771B0B301D5DF05955425061A30DC6D33BB6D2A32BD0" +
+ "A75A0A71D2184F506372ABF84A56AEEEA8EB693BF29A6403" +
+ "45FA1298A16E85421B2208D00068A5A42915F82CF0B858C8" +
+ "FA39D43D704B6927E0B2F916304E86FB6A1B487F07D8139E" +
+ "428BB096C6D67A76EC0B8D4EF274B8A2CF556D279AD267CC" +
+ "EF5AF477AFED029F485B5597739F5D0240F67C2D948A6279", 16)))
+ {
+ fail("G incorrect");
+ }
+
+ DSAKeyPairGenerator kpGen = new DSAKeyPairGenerator();
+
+ kpGen.init(new DSAKeyGenerationParameters(new FixedSecureRandom(Hex.decode("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C")), params));
+
+ AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();
+
+ DSAPublicKeyParameters pub = (DSAPublicKeyParameters)kp.getPublic();
+ DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)kp.getPrivate();
+
+ if (!pub.getY().equals(new BigInteger(
+ "2828003D7C747199143C370FDD07A286" +
+ "1524514ACC57F63F80C38C2087C6B795B62DE1C224BF8D1D" +
+ "1424E60CE3F5AE3F76C754A2464AF292286D873A7A30B7EA" +
+ "CBBC75AAFDE7191D9157598CDB0B60E0C5AA3F6EBE425500" +
+ "C611957DBF5ED35490714A42811FDCDEB19AF2AB30BEADFF" +
+ "2907931CEE7F3B55532CFFAEB371F84F01347630EB227A41" +
+ "9B1F3F558BC8A509D64A765D8987D493B007C4412C297CAF" +
+ "41566E26FAEE475137EC781A0DC088A26C8804A98C23140E" +
+ "7C936281864B99571EE95C416AA38CEEBB41FDBFF1EB1D1D" +
+ "C97B63CE1355257627C8B0FD840DDB20ED35BE92F08C49AE" +
+ "A5613957D7E5C7A6D5A5834B4CB069E0831753ECF65BA02B", 16)))
+ {
+ fail("Y value incorrect");
+ }
+
+ if (!priv.getX().equals(
+ new BigInteger("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C", 16)))
+ {
+ fail("X value incorrect");
+ }
+
+ DSASigner signer = new DSASigner();
+
+ signer.init(true, new ParametersWithRandom(kp.getPrivate(), new FixedSecureRandom(Hex.decode("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C"))));
+
+ byte[] msg = Hex.decode("BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD");
+
+ BigInteger[] sig = signer.generateSignature(msg);
+
+ if (!sig[0].equals(new BigInteger("315C875DCD4850E948B8AC42824E9483A32D5BA5ABE0681B9B9448D444F2BE3C", 16)))
+ {
+ fail("R value incorrect");
+ }
+
+ if (!sig[1].equals(new BigInteger("89718D12E54A8D9ED066E4A55F7ED5A2229CD23B9A3CEE78F83ED6AA61F6BCB9", 16)))
+ {
+ fail("S value incorrect");
+ }
+
+ signer.init(false, kp.getPublic());
+
+ if (!signer.verifySignature(msg, sig[0], sig[1]))
+ {
+ fail("signature not verified");
+ }
+ }
+
+ private void dsa2Test4()
+ {
+ byte[] seed = Hex.decode("193AFCA7C1E77B3C1ECC618C81322E47B8B8B997C9C83515C59CC446C2D9BD47");
+
+ DSAParametersGenerator pGen = new DSAParametersGenerator(new SHA256Digest());
+
+ pGen.init(new DSAParameterGenerationParameters(3072, 256, 10, new DSATestSecureRandom(seed)));
+
+ DSAParameters params = pGen.generateParameters();
+
+ DSAValidationParameters pv = params.getValidationParameters();
+
+ if (pv.getCounter() != 20)
+ {
+ fail("counter incorrect");
+ }
+
+ if (!Arrays.areEqual(seed, pv.getSeed()))
+ {
+ fail("seed incorrect");
+ }
+
+ if (!params.getQ().equals(new BigInteger("CFA0478A54717B08CE64805B76E5B14249A77A4838469DF7F7DC987EFCCFB11D", 16)))
+ {
+ fail("Q incorrect");
+ }
+
+ if (!params.getP().equals(new BigInteger(
+ "90066455B5CFC38F9CAA4A48B4281F292C260FEEF01FD610" +
+ "37E56258A7795A1C7AD46076982CE6BB956936C6AB4DCFE0" +
+ "5E6784586940CA544B9B2140E1EB523F009D20A7E7880E4E" +
+ "5BFA690F1B9004A27811CD9904AF70420EEFD6EA11EF7DA1" +
+ "29F58835FF56B89FAA637BC9AC2EFAAB903402229F491D8D" +
+ "3485261CD068699B6BA58A1DDBBEF6DB51E8FE34E8A78E54" +
+ "2D7BA351C21EA8D8F1D29F5D5D15939487E27F4416B0CA63" +
+ "2C59EFD1B1EB66511A5A0FBF615B766C5862D0BD8A3FE7A0" +
+ "E0DA0FB2FE1FCB19E8F9996A8EA0FCCDE538175238FC8B0E" +
+ "E6F29AF7F642773EBE8CD5402415A01451A840476B2FCEB0" +
+ "E388D30D4B376C37FE401C2A2C2F941DAD179C540C1C8CE0" +
+ "30D460C4D983BE9AB0B20F69144C1AE13F9383EA1C08504F" +
+ "B0BF321503EFE43488310DD8DC77EC5B8349B8BFE97C2C56" +
+ "0EA878DE87C11E3D597F1FEA742D73EEC7F37BE43949EF1A" +
+ "0D15C3F3E3FC0A8335617055AC91328EC22B50FC15B941D3" +
+ "D1624CD88BC25F3E941FDDC6200689581BFEC416B4B2CB73", 16)))
+ {
+ fail("P incorrect");
+ }
+
+ if (!params.getG().equals(new BigInteger(
+ "5E5CBA992E0A680D885EB903AEA78E4A45A469103D448EDE" +
+ "3B7ACCC54D521E37F84A4BDD5B06B0970CC2D2BBB715F7B8" +
+ "2846F9A0C393914C792E6A923E2117AB805276A975AADB52" +
+ "61D91673EA9AAFFEECBFA6183DFCB5D3B7332AA19275AFA1" +
+ "F8EC0B60FB6F66CC23AE4870791D5982AAD1AA9485FD8F4A" +
+ "60126FEB2CF05DB8A7F0F09B3397F3937F2E90B9E5B9C9B6" +
+ "EFEF642BC48351C46FB171B9BFA9EF17A961CE96C7E7A7CC" +
+ "3D3D03DFAD1078BA21DA425198F07D2481622BCE45969D9C" +
+ "4D6063D72AB7A0F08B2F49A7CC6AF335E08C4720E31476B6" +
+ "7299E231F8BD90B39AC3AE3BE0C6B6CACEF8289A2E2873D5" +
+ "8E51E029CAFBD55E6841489AB66B5B4B9BA6E2F784660896" +
+ "AFF387D92844CCB8B69475496DE19DA2E58259B090489AC8" +
+ "E62363CDF82CFD8EF2A427ABCD65750B506F56DDE3B98856" +
+ "7A88126B914D7828E2B63A6D7ED0747EC59E0E0A23CE7D8A" +
+ "74C1D2C2A7AFB6A29799620F00E11C33787F7DED3B30E1A2" +
+ "2D09F1FBDA1ABBBFBF25CAE05A13F812E34563F99410E73B", 16)))
+ {
+ fail("G incorrect");
+ }
+
+ DSAKeyPairGenerator kpGen = new DSAKeyPairGenerator();
+
+ kpGen.init(new DSAKeyGenerationParameters(new FixedSecureRandom(Hex.decode("3ABC1587297CE7B9EA1AD6651CF2BC4D7F92ED25CABC8553F567D1B40EBB8764")), params));
+
+ AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();
+
+ DSAPublicKeyParameters pub = (DSAPublicKeyParameters)kp.getPublic();
+ DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)kp.getPrivate();
+
+ if (!pub.getY().equals(new BigInteger(
+ "8B891C8692D3DE875879390F2698B26FBECCA6B075535DCE" +
+ "6B0C862577F9FA0DEF6074E7A7624121224A595896ABD4CD" +
+ "A56B2CEFB942E025D2A4282FFAA98A48CDB47E1A6FCB5CFB" +
+ "393EF35AF9DF913102BB303C2B5C36C3F8FC04ED7B8B69FE" +
+ "FE0CF3E1FC05CFA713B3435B2656E913BA8874AEA9F93600" +
+ "6AEB448BCD005D18EC3562A33D04CF25C8D3D69844343442" +
+ "FA3DB7DE618C5E2DA064573E61E6D5581BFB694A23AC87FD" +
+ "5B52D62E954E1376DB8DDB524FFC0D469DF978792EE44173" +
+ "8E5DB05A7DC43E94C11A2E7A4FBE383071FA36D2A7EC8A93" +
+ "88FE1C4F79888A99D3B6105697C2556B79BB4D7E781CEBB3" +
+ "D4866AD825A5E830846072289FDBC941FA679CA82F5F78B7" +
+ "461B2404DB883D215F4E0676CF5493950AC5591697BFEA8D" +
+ "1EE6EC016B89BA51CAFB5F9C84C989FA117375E94578F28B" +
+ "E0B34CE0545DA46266FD77F62D8F2CEE92AB77012AFEBC11" +
+ "008985A821CD2D978C7E6FE7499D1AAF8DE632C21BB48CA5" +
+ "CBF9F31098FD3FD3854C49A65D9201744AACE540354974F9", 16)))
+ {
+ fail("Y value incorrect");
+ }
+
+ if (!priv.getX().equals(
+ new BigInteger("3ABC1587297CE7B9EA1AD6651CF2BC4D7F92ED25CABC8553F567D1B40EBB8764", 16)))
+ {
+ fail("X value incorrect");
+ }
+
+ DSASigner signer = new DSASigner();
+
+ signer.init(true, new ParametersWithRandom(kp.getPrivate(), new FixedSecureRandom(Hex.decode("A6902C1E6E3943C5628061588A8B007BCCEA91DBF12915483F04B24AB0678BEE"))));
+
+ byte[] msg = Hex.decode("BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD");
+
+ BigInteger[] sig = signer.generateSignature(msg);
+
+ if (!sig[0].equals(new BigInteger("5F184E645A38BE8FB4A6871B6503A9D12924C7ABE04B71410066C2ECA6E3BE3E", 16)))
+ {
+ fail("R value incorrect");
+ }
+
+ if (!sig[1].equals(new BigInteger("91EB0C7BA3D4B9B60B825C3D9F2CADA8A2C9D7723267B033CBCDCF8803DB9C18", 16)))
+ {
+ fail("S value incorrect");
+ }
+
+ signer.init(false, kp.getPublic());
+
+ if (!signer.verifySignature(msg, sig[0], sig[1]))
+ {
+ fail("signature not verified");
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new DSATest());
+ }
+
+ private class DSATestSecureRandom
+ extends FixedSecureRandom
+ {
+ private boolean first = true;
+
+ public DSATestSecureRandom(byte[] value)
+ {
+ super(value);
+ }
+
+ public void nextBytes(byte[] bytes)
+ {
+ if (first)
+ {
+ super.nextBytes(bytes);
+ first = false;
+ }
+ else
+ {
+ bytes[bytes.length - 1] = 2;
+ }
+ }
+ }
+}
diff --git a/core/src/test/jdk1.3/org/spongycastle/i18n/test/AllTests.java b/core/src/test/jdk1.3/org/spongycastle/i18n/test/AllTests.java
new file mode 100644
index 00000000..3784fd7b
--- /dev/null
+++ b/core/src/test/jdk1.3/org/spongycastle/i18n/test/AllTests.java
@@ -0,0 +1,27 @@
+
+package org.spongycastle.i18n.test;
+
+import org.spongycastle.i18n.filter.test.HTMLFilterTest;
+import org.spongycastle.i18n.filter.test.SQLFilterTest;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class AllTests extends TestCase
+{
+
+ public static void main (String[] args)
+ {
+ junit.textui.TestRunner.run (suite());
+ }
+
+ public static Test suite()
+ {
+ TestSuite suite = new TestSuite("i18n tests");
+ suite.addTestSuite(HTMLFilterTest.class);
+ suite.addTestSuite(SQLFilterTest.class);
+ return suite;
+ }
+
+}
diff --git a/core/src/test/jdk1.4/org/bouncycastle/asn1/test/AllTests.java b/core/src/test/jdk1.4/org/bouncycastle/asn1/test/AllTests.java
deleted file mode 100644
index 50817f2f..00000000
--- a/core/src/test/jdk1.4/org/bouncycastle/asn1/test/AllTests.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.bouncycastle.asn1.test;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-import org.bouncycastle.util.test.SimpleTestResult;
-
-public class AllTests
- extends TestCase
-{
- public void testASN1()
- {
- org.bouncycastle.util.test.Test[] tests = RegressionTest.tests;
-
- for (int i = 0; i != tests.length; i++)
- {
- SimpleTestResult result = (SimpleTestResult)tests[i].perform();
-
- if (!result.isSuccessful())
- {
- fail(result.toString());
- }
- }
- }
-
- public static void main (String[] args)
- {
- junit.textui.TestRunner.run(suite());
- }
-
- public static Test suite()
- {
- TestSuite suite = new TestSuite("ASN.1 Tests");
-
- suite.addTestSuite(AllTests.class);
- suite.addTestSuite(ASN1SequenceParserTest.class);
- suite.addTestSuite(OctetStringTest.class);
- suite.addTestSuite(ParseTest.class);
-
- return suite;
- }
-}
diff --git a/core/src/test/jdk1.4/org/bouncycastle/crypto/test/RegressionTest.java b/core/src/test/jdk1.4/org/bouncycastle/crypto/test/RegressionTest.java
deleted file mode 100644
index b7b6158b..00000000
--- a/core/src/test/jdk1.4/org/bouncycastle/crypto/test/RegressionTest.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package org.bouncycastle.crypto.test;
-
-import org.bouncycastle.util.test.Test;
-import org.bouncycastle.util.test.TestResult;
-
-public class RegressionTest
-{
- public static Test[] tests =
- {
- new AESTest(),
- new AESLightTest(),
- new AESFastTest(),
- new AESWrapTest(),
- new DESTest(),
- new DESedeTest(),
- new ModeTest(),
- new PaddingTest(),
- new DHTest(),
- new ElGamalTest(),
- new DSATest(),
- new ECTest(),
- new GOST3410Test(),
- new ECGOST3410Test(),
- new ECIESTest(),
- new ECNRTest(),
- new MacTest(),
- new GOST28147MacTest(),
- new RC2Test(),
- new RC2WrapTest(),
- new RC4Test(),
- new RC5Test(),
- new RC6Test(),
- new RijndaelTest(),
- new SerpentTest(),
- new CamelliaTest(),
- new CamelliaLightTest(),
- new DigestRandomNumberTest(),
- new SkipjackTest(),
- new BlowfishTest(),
- new TwofishTest(),
- new Threefish256Test(),
- new Threefish512Test(),
- new Threefish1024Test(),
- new SkeinDigestTest(),
- new SkeinMacTest(),
- new CAST5Test(),
- new CAST6Test(),
- new GOST28147Test(),
- new IDEATest(),
- new RSATest(),
- new RSABlindedTest(),
- new RSADigestSignerTest(),
- new PSSBlindTest(),
- new ISO9796Test(),
- new ISO9797Alg3MacTest(),
- new MD2DigestTest(),
- new MD4DigestTest(),
- new MD5DigestTest(),
- new SHA1DigestTest(),
- new SHA224DigestTest(),
- new SHA256DigestTest(),
- new SHA384DigestTest(),
- new SHA512DigestTest(),
- new SHA512t224DigestTest(),
- new SHA512t256DigestTest(),
- new SHA3DigestTest(),
- new RIPEMD128DigestTest(),
- new RIPEMD160DigestTest(),
- new RIPEMD256DigestTest(),
- new RIPEMD320DigestTest(),
- new TigerDigestTest(),
- new GOST3411DigestTest(),
- new WhirlpoolDigestTest(),
- new MD5HMacTest(),
- new SHA1HMacTest(),
- new SHA224HMacTest(),
- new SHA256HMacTest(),
- new SHA384HMacTest(),
- new SHA512HMacTest(),
- new RIPEMD128HMacTest(),
- new RIPEMD160HMacTest(),
- new OAEPTest(),
- new PSSTest(),
- new CTSTest(),
- new CCMTest(),
- new PKCS5Test(),
- new PKCS12Test(),
- new KDF1GeneratorTest(),
- new KDF2GeneratorTest(),
- new MGF1GeneratorTest(),
- new HKDFGeneratorTest(),
- new DHKEKGeneratorTest(),
- new ECDHKEKGeneratorTest(),
- new ShortenedDigestTest(),
- new EqualsHashCodeTest(),
- new TEATest(),
- new XTEATest(),
- new RFC3211WrapTest(),
- new SEEDTest(),
- new Salsa20Test(),
- new XSalsa20Test(),
- new ChaChaTest(),
- new CMacTest(),
- new EAXTest(),
- new GCMTest(),
- new GMacTest(),
- new HCFamilyTest(),
- new HCFamilyVecTest(),
- new ISAACTest(),
- new NoekeonTest(),
- new VMPCKSA3Test(),
- new VMPCMacTest(),
- new VMPCTest(),
- new Grainv1Test(),
- new Grain128Test(),
- //new NaccacheSternTest(),
- new SRP6Test(),
- new SCryptTest(),
- new ResetTest(),
- new NullTest(),
- new DSTU4145Test(),
- new SipHashTest(),
- new Poly1305Test(),
- new OCBTest(),
- new NonMemoableDigestTest(),
- new RSAKeyEncapsulationTest(),
- new ECIESKeyEncapsulationTest(),
- new HashCommitmentTest(),
- new CipherStreamTest(),
- new BlockCipherResetTest(),
- new StreamCipherResetTest(),
- new SM3DigestTest()
- };
-
- public static void main(
- String[] args)
- {
- for (int i = 0; i != tests.length; i++)
- {
- TestResult result = tests[i].perform();
-
- if (result.getException() != null)
- {
- result.getException().printStackTrace();
- }
-
- System.out.println(result);
- }
- }
-}
diff --git a/core/src/test/jdk1.4/org/bouncycastle/pqc/crypto/test/AllTests.java b/core/src/test/jdk1.4/org/bouncycastle/pqc/crypto/test/AllTests.java
deleted file mode 100644
index 2fd64147..00000000
--- a/core/src/test/jdk1.4/org/bouncycastle/pqc/crypto/test/AllTests.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.bouncycastle.pqc.crypto.test;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-import org.bouncycastle.util.test.SimpleTestResult;
-
-public class AllTests
- extends TestCase
-{
- public void testCrypto()
- {
- org.bouncycastle.util.test.Test[] tests = RegressionTest.tests;
-
-// for (int i = 0; i != tests.length; i++)
-// {
-// SimpleTestResult result = (SimpleTestResult)tests[i].perform();
-//
-// if (!result.isSuccessful())
-// {
-// fail(result.toString());
-// }
-// }
- }
-
- public static void main (String[] args)
- {
- junit.textui.TestRunner.run(suite());
- }
-
- public static Test suite()
- {
- TestSuite suite = new TestSuite("Lightweight PQ Crypto Tests");
-
- suite.addTestSuite(AllTests.class);
-
- return suite;
- }
-}
diff --git a/core/src/test/jdk1.4/org/spongycastle/asn1/test/AllTests.java b/core/src/test/jdk1.4/org/spongycastle/asn1/test/AllTests.java
new file mode 100644
index 00000000..ca75ad28
--- /dev/null
+++ b/core/src/test/jdk1.4/org/spongycastle/asn1/test/AllTests.java
@@ -0,0 +1,42 @@
+package org.spongycastle.asn1.test;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.spongycastle.util.test.SimpleTestResult;
+
+public class AllTests
+ extends TestCase
+{
+ public void testASN1()
+ {
+ org.spongycastle.util.test.Test[] tests = RegressionTest.tests;
+
+ for (int i = 0; i != tests.length; i++)
+ {
+ SimpleTestResult result = (SimpleTestResult)tests[i].perform();
+
+ if (!result.isSuccessful())
+ {
+ fail(result.toString());
+ }
+ }
+ }
+
+ public static void main (String[] args)
+ {
+ junit.textui.TestRunner.run(suite());
+ }
+
+ public static Test suite()
+ {
+ TestSuite suite = new TestSuite("ASN.1 Tests");
+
+ suite.addTestSuite(AllTests.class);
+ suite.addTestSuite(ASN1SequenceParserTest.class);
+ suite.addTestSuite(OctetStringTest.class);
+ suite.addTestSuite(ParseTest.class);
+
+ return suite;
+ }
+}
diff --git a/core/src/test/jdk1.4/org/spongycastle/crypto/test/RegressionTest.java b/core/src/test/jdk1.4/org/spongycastle/crypto/test/RegressionTest.java
new file mode 100644
index 00000000..7bf7fd64
--- /dev/null
+++ b/core/src/test/jdk1.4/org/spongycastle/crypto/test/RegressionTest.java
@@ -0,0 +1,150 @@
+package org.spongycastle.crypto.test;
+
+import org.spongycastle.util.test.Test;
+import org.spongycastle.util.test.TestResult;
+
+public class RegressionTest
+{
+ public static Test[] tests =
+ {
+ new AESTest(),
+ new AESLightTest(),
+ new AESFastTest(),
+ new AESWrapTest(),
+ new DESTest(),
+ new DESedeTest(),
+ new ModeTest(),
+ new PaddingTest(),
+ new DHTest(),
+ new ElGamalTest(),
+ new DSATest(),
+ new ECTest(),
+ new GOST3410Test(),
+ new ECGOST3410Test(),
+ new ECIESTest(),
+ new ECNRTest(),
+ new MacTest(),
+ new GOST28147MacTest(),
+ new RC2Test(),
+ new RC2WrapTest(),
+ new RC4Test(),
+ new RC5Test(),
+ new RC6Test(),
+ new RijndaelTest(),
+ new SerpentTest(),
+ new CamelliaTest(),
+ new CamelliaLightTest(),
+ new DigestRandomNumberTest(),
+ new SkipjackTest(),
+ new BlowfishTest(),
+ new TwofishTest(),
+ new Threefish256Test(),
+ new Threefish512Test(),
+ new Threefish1024Test(),
+ new SkeinDigestTest(),
+ new SkeinMacTest(),
+ new CAST5Test(),
+ new CAST6Test(),
+ new GOST28147Test(),
+ new IDEATest(),
+ new RSATest(),
+ new RSABlindedTest(),
+ new RSADigestSignerTest(),
+ new PSSBlindTest(),
+ new ISO9796Test(),
+ new ISO9797Alg3MacTest(),
+ new MD2DigestTest(),
+ new MD4DigestTest(),
+ new MD5DigestTest(),
+ new SHA1DigestTest(),
+ new SHA224DigestTest(),
+ new SHA256DigestTest(),
+ new SHA384DigestTest(),
+ new SHA512DigestTest(),
+ new SHA512t224DigestTest(),
+ new SHA512t256DigestTest(),
+ new SHA3DigestTest(),
+ new RIPEMD128DigestTest(),
+ new RIPEMD160DigestTest(),
+ new RIPEMD256DigestTest(),
+ new RIPEMD320DigestTest(),
+ new TigerDigestTest(),
+ new GOST3411DigestTest(),
+ new WhirlpoolDigestTest(),
+ new MD5HMacTest(),
+ new SHA1HMacTest(),
+ new SHA224HMacTest(),
+ new SHA256HMacTest(),
+ new SHA384HMacTest(),
+ new SHA512HMacTest(),
+ new RIPEMD128HMacTest(),
+ new RIPEMD160HMacTest(),
+ new OAEPTest(),
+ new PSSTest(),
+ new CTSTest(),
+ new CCMTest(),
+ new PKCS5Test(),
+ new PKCS12Test(),
+ new KDF1GeneratorTest(),
+ new KDF2GeneratorTest(),
+ new MGF1GeneratorTest(),
+ new HKDFGeneratorTest(),
+ new DHKEKGeneratorTest(),
+ new ECDHKEKGeneratorTest(),
+ new ShortenedDigestTest(),
+ new EqualsHashCodeTest(),
+ new TEATest(),
+ new XTEATest(),
+ new RFC3211WrapTest(),
+ new SEEDTest(),
+ new Salsa20Test(),
+ new XSalsa20Test(),
+ new ChaChaTest(),
+ new CMacTest(),
+ new EAXTest(),
+ new GCMTest(),
+ new GMacTest(),
+ new HCFamilyTest(),
+ new HCFamilyVecTest(),
+ new ISAACTest(),
+ new NoekeonTest(),
+ new VMPCKSA3Test(),
+ new VMPCMacTest(),
+ new VMPCTest(),
+ new Grainv1Test(),
+ new Grain128Test(),
+ //new NaccacheSternTest(),
+ new SRP6Test(),
+ new SCryptTest(),
+ new ResetTest(),
+ new NullTest(),
+ new DSTU4145Test(),
+ new SipHashTest(),
+ new Poly1305Test(),
+ new OCBTest(),
+ new NonMemoableDigestTest(),
+ new RSAKeyEncapsulationTest(),
+ new ECIESKeyEncapsulationTest(),
+ new HashCommitmentTest(),
+ new CipherStreamTest(),
+ new BlockCipherResetTest(),
+ new StreamCipherResetTest(),
+ new SM3DigestTest()
+ };
+
+ public static void main(
+ String[] args)
+ {
+ for (int i = 0; i != tests.length; i++)
+ {
+ TestResult result = tests[i].perform();
+
+ if (result.getException() != null)
+ {
+ result.getException().printStackTrace();
+ }
+
+ System.out.println(result);
+ }
+ }
+}
diff --git a/core/src/test/jdk1.4/org/spongycastle/pqc/crypto/test/AllTests.java b/core/src/test/jdk1.4/org/spongycastle/pqc/crypto/test/AllTests.java
new file mode 100644
index 00000000..2a7d87e0
--- /dev/null
+++ b/core/src/test/jdk1.4/org/spongycastle/pqc/crypto/test/AllTests.java
@@ -0,0 +1,39 @@
+package org.spongycastle.pqc.crypto.test;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.spongycastle.util.test.SimpleTestResult;
+
+public class AllTests
+ extends TestCase
+{
+ public void testCrypto()
+ {
+ org.spongycastle.util.test.Test[] tests = RegressionTest.tests;
+
+// for (int i = 0; i != tests.length; i++)
+// {
+// SimpleTestResult result = (SimpleTestResult)tests[i].perform();
+//
+// if (!result.isSuccessful())
+// {
+// fail(result.toString());
+// }
+// }
+ }
+
+ public static void main (String[] args)
+ {
+ junit.textui.TestRunner.run(suite());
+ }
+
+ public static Test suite()
+ {
+ TestSuite suite = new TestSuite("Lightweight PQ Crypto Tests");
+
+ suite.addTestSuite(AllTests.class);
+
+ return suite;
+ }
+}
diff --git a/core/src/test/resources/org/bouncycastle/asn1/test/masterlist-content.data b/core/src/test/resources/org/spongycastle/asn1/test/masterlist-content.data
index d462f0d8..d462f0d8 100644
--- a/core/src/test/resources/org/bouncycastle/asn1/test/masterlist-content.data
+++ b/core/src/test/resources/org/spongycastle/asn1/test/masterlist-content.data
Binary files differ
diff --git a/core/src/test/resources/org/bouncycastle/crypto/test/SCryptTestVectors.txt b/core/src/test/resources/org/spongycastle/crypto/test/SCryptTestVectors.txt
index b050e9f8..b050e9f8 100644
--- a/core/src/test/resources/org/bouncycastle/crypto/test/SCryptTestVectors.txt
+++ b/core/src/test/resources/org/spongycastle/crypto/test/SCryptTestVectors.txt
diff --git a/core/src/test/resources/org/bouncycastle/crypto/test/cavp/KDFCTR_gen.rsp b/core/src/test/resources/org/spongycastle/crypto/test/cavp/KDFCTR_gen.rsp
index 2edf662b..2edf662b 100644
--- a/core/src/test/resources/org/bouncycastle/crypto/test/cavp/KDFCTR_gen.rsp
+++ b/core/src/test/resources/org/spongycastle/crypto/test/cavp/KDFCTR_gen.rsp
diff --git a/core/src/test/resources/org/bouncycastle/crypto/test/cavp/KDFDblPipelineCounter_gen.rsp b/core/src/test/resources/org/spongycastle/crypto/test/cavp/KDFDblPipelineCounter_gen.rsp
index 02448610..02448610 100644
--- a/core/src/test/resources/org/bouncycastle/crypto/test/cavp/KDFDblPipelineCounter_gen.rsp
+++ b/core/src/test/resources/org/spongycastle/crypto/test/cavp/KDFDblPipelineCounter_gen.rsp
diff --git a/core/src/test/resources/org/bouncycastle/crypto/test/cavp/KDFDblPipelineNoCounter_gen.rsp b/core/src/test/resources/org/spongycastle/crypto/test/cavp/KDFDblPipelineNoCounter_gen.rsp
index 5dcbcdff..5dcbcdff 100644
--- a/core/src/test/resources/org/bouncycastle/crypto/test/cavp/KDFDblPipelineNoCounter_gen.rsp
+++ b/core/src/test/resources/org/spongycastle/crypto/test/cavp/KDFDblPipelineNoCounter_gen.rsp
diff --git a/core/src/test/resources/org/bouncycastle/crypto/test/cavp/KDFFeedbackCounter_gen.rsp b/core/src/test/resources/org/spongycastle/crypto/test/cavp/KDFFeedbackCounter_gen.rsp
index 42436725..42436725 100644
--- a/core/src/test/resources/org/bouncycastle/crypto/test/cavp/KDFFeedbackCounter_gen.rsp
+++ b/core/src/test/resources/org/spongycastle/crypto/test/cavp/KDFFeedbackCounter_gen.rsp
diff --git a/core/src/test/resources/org/bouncycastle/crypto/test/cavp/KDFFeedbackNoCounter_gen.rsp b/core/src/test/resources/org/spongycastle/crypto/test/cavp/KDFFeedbackNoCounter_gen.rsp
index 27ecb42d..27ecb42d 100644
--- a/core/src/test/resources/org/bouncycastle/crypto/test/cavp/KDFFeedbackNoCounter_gen.rsp
+++ b/core/src/test/resources/org/spongycastle/crypto/test/cavp/KDFFeedbackNoCounter_gen.rsp
diff --git a/core/src/test/resources/org/bouncycastle/crypto/test/cavp/KDFFeedbackNoIV_gen.rsp b/core/src/test/resources/org/spongycastle/crypto/test/cavp/KDFFeedbackNoIV_gen.rsp
index 85f64ae0..85f64ae0 100644
--- a/core/src/test/resources/org/bouncycastle/crypto/test/cavp/KDFFeedbackNoIV_gen.rsp
+++ b/core/src/test/resources/org/spongycastle/crypto/test/cavp/KDFFeedbackNoIV_gen.rsp
diff --git a/core/src/test/resources/org/bouncycastle/crypto/test/cavp/[original]_KDFCTR_gen.rsp b/core/src/test/resources/org/spongycastle/crypto/test/cavp/[original]_KDFCTR_gen.rsp
index 8121dc64..8121dc64 100644
--- a/core/src/test/resources/org/bouncycastle/crypto/test/cavp/[original]_KDFCTR_gen.rsp
+++ b/core/src/test/resources/org/spongycastle/crypto/test/cavp/[original]_KDFCTR_gen.rsp
diff --git a/core/src/test/resources/org/bouncycastle/crypto/test/ecrypt_HC-128.txt b/core/src/test/resources/org/spongycastle/crypto/test/ecrypt_HC-128.txt
index fbc2fbd3..fbc2fbd3 100644
--- a/core/src/test/resources/org/bouncycastle/crypto/test/ecrypt_HC-128.txt
+++ b/core/src/test/resources/org/spongycastle/crypto/test/ecrypt_HC-128.txt
diff --git a/core/src/test/resources/org/bouncycastle/crypto/test/ecrypt_HC-256_128K_128IV.txt b/core/src/test/resources/org/spongycastle/crypto/test/ecrypt_HC-256_128K_128IV.txt
index 6460df61..6460df61 100644
--- a/core/src/test/resources/org/bouncycastle/crypto/test/ecrypt_HC-256_128K_128IV.txt
+++ b/core/src/test/resources/org/spongycastle/crypto/test/ecrypt_HC-256_128K_128IV.txt
diff --git a/core/src/test/resources/org/bouncycastle/crypto/test/ecrypt_HC-256_128K_256IV.txt b/core/src/test/resources/org/spongycastle/crypto/test/ecrypt_HC-256_128K_256IV.txt
index a4784eda..a4784eda 100644
--- a/core/src/test/resources/org/bouncycastle/crypto/test/ecrypt_HC-256_128K_256IV.txt
+++ b/core/src/test/resources/org/spongycastle/crypto/test/ecrypt_HC-256_128K_256IV.txt
diff --git a/core/src/test/resources/org/bouncycastle/crypto/test/ecrypt_HC-256_256K_128IV.txt b/core/src/test/resources/org/spongycastle/crypto/test/ecrypt_HC-256_256K_128IV.txt
index 46a86d7d..46a86d7d 100644
--- a/core/src/test/resources/org/bouncycastle/crypto/test/ecrypt_HC-256_256K_128IV.txt
+++ b/core/src/test/resources/org/spongycastle/crypto/test/ecrypt_HC-256_256K_128IV.txt
diff --git a/core/src/test/resources/org/bouncycastle/crypto/test/ecrypt_HC-256_256K_256IV.txt b/core/src/test/resources/org/spongycastle/crypto/test/ecrypt_HC-256_256K_256IV.txt
index 15554076..15554076 100644
--- a/core/src/test/resources/org/bouncycastle/crypto/test/ecrypt_HC-256_256K_256IV.txt
+++ b/core/src/test/resources/org/spongycastle/crypto/test/ecrypt_HC-256_256K_256IV.txt
diff --git a/core/src/test/resources/org/bouncycastle/crypto/tls/test/README.txt b/core/src/test/resources/org/spongycastle/crypto/tls/test/README.txt
index 2f456ed6..2f456ed6 100644
--- a/core/src/test/resources/org/bouncycastle/crypto/tls/test/README.txt
+++ b/core/src/test/resources/org/spongycastle/crypto/tls/test/README.txt
diff --git a/core/src/test/resources/org/bouncycastle/crypto/tls/test/ca.tmpl b/core/src/test/resources/org/spongycastle/crypto/tls/test/ca.tmpl
index 44319d2d..44319d2d 100644
--- a/core/src/test/resources/org/bouncycastle/crypto/tls/test/ca.tmpl
+++ b/core/src/test/resources/org/spongycastle/crypto/tls/test/ca.tmpl
diff --git a/core/src/test/resources/org/bouncycastle/crypto/tls/test/client.tmpl b/core/src/test/resources/org/spongycastle/crypto/tls/test/client.tmpl
index f7f7e08a..f7f7e08a 100644
--- a/core/src/test/resources/org/bouncycastle/crypto/tls/test/client.tmpl
+++ b/core/src/test/resources/org/spongycastle/crypto/tls/test/client.tmpl
diff --git a/core/src/test/resources/org/bouncycastle/crypto/tls/test/server.tmpl b/core/src/test/resources/org/spongycastle/crypto/tls/test/server.tmpl
index e406c48b..e406c48b 100644
--- a/core/src/test/resources/org/bouncycastle/crypto/tls/test/server.tmpl
+++ b/core/src/test/resources/org/spongycastle/crypto/tls/test/server.tmpl
diff --git a/core/src/test/resources/org/bouncycastle/crypto/tls/test/x509-ca-key.pem b/core/src/test/resources/org/spongycastle/crypto/tls/test/x509-ca-key.pem
index b9144d2b..b9144d2b 100644
--- a/core/src/test/resources/org/bouncycastle/crypto/tls/test/x509-ca-key.pem
+++ b/core/src/test/resources/org/spongycastle/crypto/tls/test/x509-ca-key.pem
diff --git a/core/src/test/resources/org/bouncycastle/crypto/tls/test/x509-ca.pem b/core/src/test/resources/org/spongycastle/crypto/tls/test/x509-ca.pem
index 1639512b..1639512b 100644
--- a/core/src/test/resources/org/bouncycastle/crypto/tls/test/x509-ca.pem
+++ b/core/src/test/resources/org/spongycastle/crypto/tls/test/x509-ca.pem
diff --git a/core/src/test/resources/org/bouncycastle/crypto/tls/test/x509-client-key.pem b/core/src/test/resources/org/spongycastle/crypto/tls/test/x509-client-key.pem
index 386711f9..386711f9 100644
--- a/core/src/test/resources/org/bouncycastle/crypto/tls/test/x509-client-key.pem
+++ b/core/src/test/resources/org/spongycastle/crypto/tls/test/x509-client-key.pem
diff --git a/core/src/test/resources/org/bouncycastle/crypto/tls/test/x509-client.pem b/core/src/test/resources/org/spongycastle/crypto/tls/test/x509-client.pem
index 4f234199..4f234199 100644
--- a/core/src/test/resources/org/bouncycastle/crypto/tls/test/x509-client.pem
+++ b/core/src/test/resources/org/spongycastle/crypto/tls/test/x509-client.pem
diff --git a/core/src/test/resources/org/bouncycastle/crypto/tls/test/x509-server-key.pem b/core/src/test/resources/org/spongycastle/crypto/tls/test/x509-server-key.pem
index 894fbb99..894fbb99 100644
--- a/core/src/test/resources/org/bouncycastle/crypto/tls/test/x509-server-key.pem
+++ b/core/src/test/resources/org/spongycastle/crypto/tls/test/x509-server-key.pem
diff --git a/core/src/test/resources/org/bouncycastle/crypto/tls/test/x509-server.pem b/core/src/test/resources/org/spongycastle/crypto/tls/test/x509-server.pem
index efc80696..efc80696 100644
--- a/core/src/test/resources/org/bouncycastle/crypto/tls/test/x509-server.pem
+++ b/core/src/test/resources/org/spongycastle/crypto/tls/test/x509-server.pem
diff --git a/core/src/test/resources/org/bouncycastle/i18n/test/I18nTestMessages_de.properties b/core/src/test/resources/org/spongycastle/i18n/test/I18nTestMessages_de.properties
index 47bafc63..47bafc63 100644
--- a/core/src/test/resources/org/bouncycastle/i18n/test/I18nTestMessages_de.properties
+++ b/core/src/test/resources/org/spongycastle/i18n/test/I18nTestMessages_de.properties
diff --git a/core/src/test/resources/org/bouncycastle/i18n/test/I18nTestMessages_en.properties b/core/src/test/resources/org/spongycastle/i18n/test/I18nTestMessages_en.properties
index 5d243a0d..5d243a0d 100644
--- a/core/src/test/resources/org/bouncycastle/i18n/test/I18nTestMessages_en.properties
+++ b/core/src/test/resources/org/spongycastle/i18n/test/I18nTestMessages_en.properties
diff --git a/core/src/test/resources/org/bouncycastle/i18n/test/I18nUTF8TestMessages_de.properties b/core/src/test/resources/org/spongycastle/i18n/test/I18nUTF8TestMessages_de.properties
index 3fe32f8a..3fe32f8a 100644
--- a/core/src/test/resources/org/bouncycastle/i18n/test/I18nUTF8TestMessages_de.properties
+++ b/core/src/test/resources/org/spongycastle/i18n/test/I18nUTF8TestMessages_de.properties